summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-05 17:34:47 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-06 10:04:14 +0000
commiteaf1da4d961fbbda9455f9af3b23d1af777f43fa (patch)
tree95970599ecee31c4f7f940bc97ac98c61a3d0cad
parent38a9a29f4f9436cace7f0e7abf9c586057df8a4e (diff)
BASELINE: Update Chromium to 73.0.3683.64
Change-Id: I76517dc277ba4e16bfd7e098fda3d079656b3b9f Reviewed-by: Michael Brüning <michael.bruning@qt.io>
-rw-r--r--chromium/DEPS16
-rw-r--r--chromium/PRESUBMIT.py4
-rw-r--r--chromium/base/android/linker/BUILD.gn5
-rw-r--r--chromium/base/mac/foundation_util.h3
-rw-r--r--chromium/base/mac/foundation_util.mm6
-rw-r--r--chromium/base/mac/foundation_util_unittest.mm6
-rw-r--r--chromium/base/memory/discardable_shared_memory.cc29
-rw-r--r--chromium/base/memory/discardable_shared_memory.h6
-rw-r--r--chromium/base/memory/discardable_shared_memory_unittest.cc5
-rwxr-xr-xchromium/build/android/apk_operations.py162
-rwxr-xr-xchromium/build/android/gyp/apkbuilder.py298
-rwxr-xr-xchromium/build/android/gyp/assert_static_initializers.py117
-rw-r--r--chromium/build/android/gyp/assert_static_initializers.pydeps7
-rwxr-xr-xchromium/build/android/gyp/bundletool.py2
-rwxr-xr-xchromium/build/android/gyp/compile_resources.py2
-rwxr-xr-xchromium/build/android/gyp/create_app_bundle_minimal_apks.py46
-rw-r--r--chromium/build/android/gyp/create_app_bundle_minimal_apks.pydeps11
-rwxr-xr-xchromium/build/android/gyp/create_size_info_files.py167
-rw-r--r--chromium/build/android/gyp/create_size_info_files.pydeps8
-rwxr-xr-xchromium/build/android/gyp/javac.py24
-rwxr-xr-xchromium/build/android/gyp/merge_jar_info_files.py99
-rw-r--r--chromium/build/android/gyp/merge_jar_info_files.pydeps8
-rw-r--r--chromium/build/android/gyp/util/build_utils.py35
-rw-r--r--chromium/build/android/gyp/util/jar_info_utils.py17
-rwxr-xr-xchromium/build/android/gyp/write_build_config.py7
-rw-r--r--chromium/build/android/pylib/utils/app_bundle_utils.py103
-rwxr-xr-xchromium/build/android/resource_sizes.py296
-rw-r--r--chromium/build/config/android/internal_rules.gni82
-rw-r--r--chromium/build/config/android/rules.gni108
-rw-r--r--chromium/build/util/LASTCHANGE2
-rw-r--r--chromium/build/util/LASTCHANGE.committime2
-rw-r--r--chromium/cc/layers/scrollbar_layer_impl_base.cc6
-rw-r--r--chromium/cc/paint/paint_op_reader.cc2
-rw-r--r--chromium/cc/paint/paint_op_writer.cc2
-rw-r--r--chromium/cc/trees/layer_tree_host_impl.cc6
-rw-r--r--chromium/chrome/VERSION2
-rw-r--r--chromium/chrome/android/BUILD.gn29
-rw-r--r--chromium/chrome/android/java/strings/android_chrome_strings.grd4
-rw-r--r--chromium/chrome/app/resources/chromium_strings_am.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ar.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_bg.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_bn.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ca.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_cs.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_da.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_de.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_el.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_en-GB.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_es-419.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_es.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_et.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_fa.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_fi.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_fil.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_fr.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_gu.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_hi.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_hr.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_hu.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_id.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_it.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_iw.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ja.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_kn.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ko.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_lt.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_lv.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ml.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_mr.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ms.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_nl.xtb3
-rw-r--r--chromium/chrome/app/resources/chromium_strings_no.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_pl.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_pt-BR.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_pt-PT.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ro.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ru.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_sk.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_sl.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_sr.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_sv.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_sw.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_ta.xtb7
-rw-r--r--chromium/chrome/app/resources/chromium_strings_te.xtb135
-rw-r--r--chromium/chrome/app/resources/chromium_strings_th.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_tr.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_uk.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_vi.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_zh-CN.xtb1
-rw-r--r--chromium/chrome/app/resources/chromium_strings_zh-TW.xtb1
-rw-r--r--chromium/chrome/app/resources/generated_resources_am.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_ar.xtb43
-rw-r--r--chromium/chrome/app/resources/generated_resources_bg.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_bn.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_ca.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_cs.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_da.xtb35
-rw-r--r--chromium/chrome/app/resources/generated_resources_de.xtb35
-rw-r--r--chromium/chrome/app/resources/generated_resources_el.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_en-GB.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_es-419.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_es.xtb35
-rw-r--r--chromium/chrome/app/resources/generated_resources_et.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_fa.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_fi.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_fil.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_fr.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_gu.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_hi.xtb33
-rw-r--r--chromium/chrome/app/resources/generated_resources_hr.xtb31
-rw-r--r--chromium/chrome/app/resources/generated_resources_hu.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_id.xtb39
-rw-r--r--chromium/chrome/app/resources/generated_resources_it.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_iw.xtb31
-rw-r--r--chromium/chrome/app/resources/generated_resources_ja.xtb31
-rw-r--r--chromium/chrome/app/resources/generated_resources_kn.xtb33
-rw-r--r--chromium/chrome/app/resources/generated_resources_ko.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_lt.xtb33
-rw-r--r--chromium/chrome/app/resources/generated_resources_lv.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_ml.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_mr.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_ms.xtb35
-rw-r--r--chromium/chrome/app/resources/generated_resources_nl.xtb31
-rw-r--r--chromium/chrome/app/resources/generated_resources_no.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_pl.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_pt-BR.xtb31
-rw-r--r--chromium/chrome/app/resources/generated_resources_pt-PT.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_ro.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_ru.xtb32
-rw-r--r--chromium/chrome/app/resources/generated_resources_sk.xtb31
-rw-r--r--chromium/chrome/app/resources/generated_resources_sl.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_sr.xtb31
-rw-r--r--chromium/chrome/app/resources/generated_resources_sv.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_sw.xtb31
-rw-r--r--chromium/chrome/app/resources/generated_resources_ta.xtb181
-rw-r--r--chromium/chrome/app/resources/generated_resources_te.xtb793
-rw-r--r--chromium/chrome/app/resources/generated_resources_th.xtb29
-rw-r--r--chromium/chrome/app/resources/generated_resources_tr.xtb27
-rw-r--r--chromium/chrome/app/resources/generated_resources_uk.xtb33
-rw-r--r--chromium/chrome/app/resources/generated_resources_vi.xtb33
-rw-r--r--chromium/chrome/app/resources/generated_resources_zh-CN.xtb33
-rw-r--r--chromium/chrome/app/resources/generated_resources_zh-TW.xtb27
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_am.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ar.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_bg.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_bn.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ca.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_cs.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_da.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_de.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_el.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_en-GB.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_es-419.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_es.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_et.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_fa.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_fi.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_fil.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_fr.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_gu.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_hi.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_hr.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_hu.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_id.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_it.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_iw.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ja.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_kn.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ko.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_lt.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_lv.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ml.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_mr.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ms.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_nl.xtb3
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_no.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_pl.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_pt-BR.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_pt-PT.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ro.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ru.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_sk.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_sl.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_sr.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_sv.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_sw.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_ta.xtb7
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_te.xtb122
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_th.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_tr.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_uk.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_vi.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_zh-CN.xtb1
-rw-r--r--chromium/chrome/app/resources/google_chrome_strings_zh-TW.xtb1
-rw-r--r--chromium/chrome/browser/BUILD.gn2
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc25
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc11
-rw-r--r--chromium/chrome/browser/flag-metadata.json51
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js2
-rw-r--r--chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js9
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination_match.js13
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination_store.js195
-rw-r--r--chromium/chrome/browser/resources/print_preview/new/destination_dialog.js23
-rw-r--r--chromium/chrome/browser/resources/print_preview/new/destination_settings.html1
-rw-r--r--chromium/chrome/browser/resources/print_preview/new/destination_settings.js52
-rw-r--r--chromium/chrome/browser/resources/print_preview/new/model.js9
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.html20
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.js107
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js2
-rw-r--r--chromium/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html3
-rw-r--r--chromium/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html44
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/policy_ui_handler.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/settings/people_handler.cc29
-rw-r--r--chromium/chrome/browser/ui/webui/settings/people_handler.h6
-rw-r--r--chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc19
-rw-r--r--chromium/chrome/browser/ui/webui/welcome/nux_helper.cc6
-rw-r--r--chromium/chrome/test/BUILD.gn1
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn7
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc14
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent_unittests.mm6
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.h6
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.mm12
-rw-r--r--chromium/components/autofill_assistant/browser/service.cc1
-rw-r--r--chromium/components/autofill_assistant/browser/web_controller.cc8
-rw-r--r--chromium/components/certificate_transparency/data/log_list.json43
-rw-r--r--chromium/components/crash/android/java/src/org/chromium/components/crash/browser/PackagePaths.java11
-rw-r--r--chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc23
-rw-r--r--chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h8
-rw-r--r--chromium/components/download/public/common/auto_resumption_handler.h3
-rw-r--r--chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_it.xtb2
-rw-r--r--chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_sr.xtb2
-rw-r--r--chromium/components/feed/core/feed_scheduler_host.cc20
-rw-r--r--chromium/components/feed/core/feed_scheduler_host.h14
-rw-r--r--chromium/components/feed/core/feed_scheduler_host_unittest.cc9
-rw-r--r--chromium/components/history/ios/browser/web_state_top_sites_observer.mm5
-rw-r--r--chromium/components/language/content/browser/BUILD.gn1
-rw-r--r--chromium/components/language/content/browser/geo_language_provider.cc2
-rw-r--r--chromium/components/language/content/browser/geo_language_provider_unittest.cc3
-rw-r--r--chromium/components/language/content/browser/language_code_locator_provider.cc30
-rw-r--r--chromium/components/language/content/browser/language_code_locator_provider.h4
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn2
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.cc68
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h130
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_datatest.cc21
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_unittest.cc43
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc67
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h17
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator_unittest.cc69
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc14
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.h6
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch_unittest.cc4
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc8
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h5
-rw-r--r--chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc50
-rw-r--r--chromium/components/omnibox/browser/BUILD.gn1
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.cc112
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h70
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor_unittest.cc92
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_essentials.proto33
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc119
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h20
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.cc56
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.h23
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_fuzzer.cc43
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_fuzzer.dict9
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_generic_fuzzer.cc46
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_proto_fuzzer.cc42
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_proto_generic_fuzzer.cc45
-rw-r--r--chromium/components/password_manager/core/browser/new_password_form_manager.cc45
-rw-r--r--chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc171
-rw-r--r--chromium/components/password_manager/core/browser/vote_uploads_test_matchers.h4
-rw-r--r--chromium/components/previews/content/previews_decider_impl.cc18
-rw-r--r--chromium/components/previews/content/previews_decider_impl.h6
-rw-r--r--chromium/components/previews/content/previews_decider_impl_unittest.cc52
-rw-r--r--chromium/components/previews/core/previews_black_list.h2
-rw-r--r--chromium/components/previews/core/previews_features.cc5
-rw-r--r--chromium/components/previews/core/previews_features.h1
-rw-r--r--chromium/components/previews/core/previews_lite_page_redirect.cc5
-rw-r--r--chromium/components/previews/core/previews_lite_page_redirect_unittest.cc9
-rw-r--r--chromium/components/previews/core/previews_logger.cc4
-rw-r--r--chromium/components/printing/renderer/print_render_frame_helper.cc14
-rw-r--r--chromium/components/resources/autofill_scaled_resources.grdp2
-rw-r--r--chromium/components/resources/default_100_percent/autofill/googlepay_dark.pngbin0 -> 1195 bytes
-rw-r--r--chromium/components/resources/default_100_percent/autofill/migration_header_dark.pngbin0 -> 20145 bytes
-rw-r--r--chromium/components/resources/default_200_percent/autofill/googlepay_dark.pngbin0 -> 2630 bytes
-rw-r--r--chromium/components/resources/default_200_percent/autofill/migration_header_dark.pngbin0 -> 48059 bytes
-rw-r--r--chromium/components/resources/default_300_percent/autofill/googlepay_dark.pngbin0 -> 4000 bytes
-rw-r--r--chromium/components/resources/default_300_percent/autofill/migration_header_dark.pngbin0 -> 81401 bytes
-rw-r--r--chromium/components/safe_browsing/features.cc3
-rw-r--r--chromium/components/search_provider_logos/google_logo_api.cc21
-rw-r--r--chromium/components/search_provider_logos/google_logo_api_unittest.cc38
-rw-r--r--chromium/components/strings/components_chromium_strings_te.xtb10
-rw-r--r--chromium/components/strings/components_google_chrome_strings_te.xtb12
-rw-r--r--chromium/components/strings/components_strings_am.xtb22
-rw-r--r--chromium/components/strings/components_strings_ar.xtb20
-rw-r--r--chromium/components/strings/components_strings_bg.xtb20
-rw-r--r--chromium/components/strings/components_strings_bn.xtb20
-rw-r--r--chromium/components/strings/components_strings_ca.xtb24
-rw-r--r--chromium/components/strings/components_strings_cs.xtb20
-rw-r--r--chromium/components/strings/components_strings_da.xtb20
-rw-r--r--chromium/components/strings/components_strings_de.xtb24
-rw-r--r--chromium/components/strings/components_strings_el.xtb20
-rw-r--r--chromium/components/strings/components_strings_en-GB.xtb20
-rw-r--r--chromium/components/strings/components_strings_es-419.xtb20
-rw-r--r--chromium/components/strings/components_strings_es.xtb20
-rw-r--r--chromium/components/strings/components_strings_et.xtb20
-rw-r--r--chromium/components/strings/components_strings_fa.xtb20
-rw-r--r--chromium/components/strings/components_strings_fi.xtb20
-rw-r--r--chromium/components/strings/components_strings_fil.xtb20
-rw-r--r--chromium/components/strings/components_strings_fr.xtb20
-rw-r--r--chromium/components/strings/components_strings_gu.xtb20
-rw-r--r--chromium/components/strings/components_strings_hi.xtb20
-rw-r--r--chromium/components/strings/components_strings_hr.xtb20
-rw-r--r--chromium/components/strings/components_strings_hu.xtb20
-rw-r--r--chromium/components/strings/components_strings_id.xtb20
-rw-r--r--chromium/components/strings/components_strings_it.xtb22
-rw-r--r--chromium/components/strings/components_strings_iw.xtb22
-rw-r--r--chromium/components/strings/components_strings_ja.xtb22
-rw-r--r--chromium/components/strings/components_strings_kn.xtb26
-rw-r--r--chromium/components/strings/components_strings_ko.xtb20
-rw-r--r--chromium/components/strings/components_strings_lt.xtb20
-rw-r--r--chromium/components/strings/components_strings_lv.xtb20
-rw-r--r--chromium/components/strings/components_strings_ml.xtb20
-rw-r--r--chromium/components/strings/components_strings_mr.xtb20
-rw-r--r--chromium/components/strings/components_strings_ms.xtb20
-rw-r--r--chromium/components/strings/components_strings_nl.xtb30
-rw-r--r--chromium/components/strings/components_strings_no.xtb20
-rw-r--r--chromium/components/strings/components_strings_pl.xtb20
-rw-r--r--chromium/components/strings/components_strings_pt-BR.xtb22
-rw-r--r--chromium/components/strings/components_strings_pt-PT.xtb20
-rw-r--r--chromium/components/strings/components_strings_ro.xtb20
-rw-r--r--chromium/components/strings/components_strings_ru.xtb20
-rw-r--r--chromium/components/strings/components_strings_sk.xtb20
-rw-r--r--chromium/components/strings/components_strings_sl.xtb20
-rw-r--r--chromium/components/strings/components_strings_sr.xtb20
-rw-r--r--chromium/components/strings/components_strings_sv.xtb20
-rw-r--r--chromium/components/strings/components_strings_sw.xtb20
-rw-r--r--chromium/components/strings/components_strings_ta.xtb34
-rw-r--r--chromium/components/strings/components_strings_te.xtb189
-rw-r--r--chromium/components/strings/components_strings_th.xtb20
-rw-r--r--chromium/components/strings/components_strings_tr.xtb20
-rw-r--r--chromium/components/strings/components_strings_uk.xtb20
-rw-r--r--chromium/components/strings/components_strings_vi.xtb22
-rw-r--r--chromium/components/strings/components_strings_zh-CN.xtb20
-rw-r--r--chromium/components/strings/components_strings_zh-TW.xtb20
-rw-r--r--chromium/components/translate/content/common/BUILD.gn1
-rw-r--r--chromium/components/translate/content/common/translate.mojom12
-rw-r--r--chromium/components/translate/content/renderer/BUILD.gn8
-rw-r--r--chromium/components/ukm/ukm_recorder_impl.cc2
-rw-r--r--chromium/components/ukm/ukm_recorder_impl.h1
-rw-r--r--chromium/components/ukm/ukm_recorder_impl_unittest.cc20
-rw-r--r--chromium/components/user_manager/known_user.cc33
-rw-r--r--chromium/components/user_manager/known_user.h4
-rw-r--r--chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc168
-rw-r--r--chromium/components/viz/common/features.cc2
-rw-r--r--chromium/components/viz/common/hit_test/hit_test_data_builder.cc151
-rw-r--r--chromium/components/viz/common/hit_test/hit_test_data_builder.h8
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query.cc16
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query.h4
-rw-r--r--chromium/components/viz/host/hit_test/hit_test_query_unittest.cc11
-rw-r--r--chromium/components/viz/service/display/display.cc10
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc195
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator.cc5
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator.h6
-rw-r--r--chromium/components/viz/service/surfaces/surface.cc15
-rw-r--r--chromium/components/viz/service/surfaces/surface.h4
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_tracker.cc33
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_tracker.h4
-rw-r--r--chromium/components/viz/service/surfaces/surface_manager.cc11
-rw-r--r--chromium/content/app/strings/translations/content_strings_am.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ar.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_bg.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_bn.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ca.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_cs.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_da.xtb4
-rw-r--r--chromium/content/app/strings/translations/content_strings_de.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_el.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_en-GB.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_es-419.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_es.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_et.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_fa.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_fi.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_fil.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_fr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_gu.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_hi.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_hr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_hu.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_id.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_it.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_iw.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ja.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_kn.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ko.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_lt.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_lv.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ml.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_mr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ms.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_nl.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_no.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_pl.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-BR.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-PT.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ro.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ru.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sk.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sl.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sv.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_sw.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_ta.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_te.xtb10
-rw-r--r--chromium/content/app/strings/translations/content_strings_th.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_tr.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_uk.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_vi.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-CN.xtb2
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-TW.xtb2
-rw-r--r--chromium/content/browser/android/content_feature_list.cc1
-rw-r--r--chromium/content/browser/browser_main_loop.cc2
-rw-r--r--chromium/content/browser/child_process_launcher.cc10
-rw-r--r--chromium/content/browser/child_process_launcher.h12
-rw-r--r--chromium/content/browser/child_process_launcher_helper_android.cc6
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc11
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h4
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_helper_mac.h46
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_helper_mac.mm73
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map.h5
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map.mm25
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map_unittest.mm21
-rw-r--r--chromium/content/browser/contacts/contacts_manager_impl.cc3
-rw-r--r--chromium/content/browser/contacts/contacts_provider_android.cc12
-rw-r--r--chromium/content/browser/contacts/contacts_provider_android.h5
-rw-r--r--chromium/content/browser/devtools/devtools_session.cc12
-rw-r--r--chromium/content/browser/file_url_loader_factory.cc14
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc1
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h1
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc6
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc20
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc10
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc18
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h1
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc58
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h5
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc222
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc4
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc18
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc8
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc31
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h6
-rw-r--r--chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc4
-rw-r--r--chromium/content/browser/indexed_db/scopes/scope_lock_range.h5
-rw-r--r--chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h3
-rw-r--r--chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc36
-rw-r--r--chromium/content/browser/loader/loader_browsertest.cc6
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc2
-rw-r--r--chromium/content/browser/loader/source_stream_to_data_pipe.cc12
-rw-r--r--chromium/content/browser/media/session/media_session_impl.cc29
-rw-r--r--chromium/content/browser/media/session/media_session_impl.h5
-rw-r--r--chromium/content/browser/media/session/media_session_impl_unittest.cc55
-rw-r--r--chromium/content/browser/media/session/media_session_uma_helper.cc4
-rw-r--r--chromium/content/browser/media/session/media_session_uma_helper.h3
-rw-r--r--chromium/content/browser/network_service_browsertest.cc88
-rw-r--r--chromium/content/browser/network_service_client.cc75
-rw-r--r--chromium/content/browser/network_service_client.h23
-rw-r--r--chromium/content/browser/network_service_instance.cc38
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc22
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h8
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm6
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc67
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h14
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc12
-rw-r--r--chromium/content/browser/service_worker/service_worker_new_script_loader.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc42
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h4
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc157
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc114
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc5
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h1
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm7
-rw-r--r--chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc21
-rw-r--r--chromium/content/browser/web_package/signed_exchange_utils.cc4
-rw-r--r--chromium/content/browser/webauth/authenticator_impl.cc34
-rw-r--r--chromium/content/browser/websockets/websocket_manager.cc6
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc5
-rw-r--r--chromium/content/common/throttling_url_loader.cc36
-rw-r--r--chromium/content/common/throttling_url_loader.h3
-rw-r--r--chromium/content/public/browser/file_url_loader.h1
-rw-r--r--chromium/content/public/browser/render_process_host.h6
-rw-r--r--chromium/content/public/common/content_features.cc5
-rw-r--r--chromium/content/public/common/content_features.h1
-rw-r--r--chromium/content/public/common/url_loader_throttle.cc4
-rw-r--r--chromium/content/public/common/url_loader_throttle.h5
-rw-r--r--chromium/content/public/renderer/render_frame.h12
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc54
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h12
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc13
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc14
-rw-r--r--chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc2
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager.cc20
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager.h13
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager_unittest.cc4
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager.cc19
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager.h6
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager_unittest.cc3
-rw-r--r--chromium/content/renderer/p2p/mdns_responder_adapter.cc2
-rw-r--r--chromium/content/renderer/render_frame_impl.cc11
-rw-r--r--chromium/content/renderer/render_frame_impl.h3
-rw-r--r--chromium/content/renderer/render_thread_impl.cc5
-rw-r--r--chromium/content/renderer/render_view_impl.cc8
-rw-r--r--chromium/content/renderer/render_widget.cc8
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.cc3
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.h4
-rw-r--r--chromium/content/utility/utility_service_factory.cc2
-rw-r--r--chromium/extensions/browser/api/web_request/web_request_api.cc11
-rw-r--r--chromium/extensions/browser/api/web_request/web_request_api.h1
-rw-r--r--chromium/extensions/browser/extension_protocols.cc2
-rw-r--r--chromium/extensions/renderer/bindings/api_request_handler.cc35
-rw-r--r--chromium/extensions/renderer/bindings/api_request_handler.h4
-rw-r--r--chromium/extensions/strings/extensions_strings_id.xtb2
-rw-r--r--chromium/extensions/strings/extensions_strings_te.xtb24
-rw-r--r--chromium/google_apis/drive/base_requests_server_unittest.cc3
-rw-r--r--chromium/google_apis/drive/base_requests_unittest.cc3
-rw-r--r--chromium/google_apis/drive/drive_api_requests_unittest.cc3
-rw-r--r--chromium/google_apis/drive/files_list_request_runner_unittest.cc3
-rw-r--r--chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc10
-rw-r--r--chromium/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc28
-rw-r--r--chromium/gpu/command_buffer/client/raster_implementation.cc18
-rw-r--r--chromium/gpu/command_buffer/client/raster_implementation.h4
-rw-r--r--chromium/gpu/command_buffer/client/raster_implementation_unittest.cc7
-rw-r--r--chromium/gpu/command_buffer/service/raster_decoder.cc28
-rw-r--r--chromium/gpu/command_buffer/service/shared_context_state.cc2
-rw-r--r--chromium/gpu/command_buffer/service/shared_context_state.h2
-rw-r--r--chromium/gpu/config/gpu_driver_bug_list.json35
-rw-r--r--chromium/gpu/config/gpu_lists_version.h2
-rw-r--r--chromium/gpu/config/gpu_util.cc5
-rw-r--r--chromium/gpu/config/gpu_workaround_list.txt1
-rw-r--r--chromium/gpu/ipc/service/direct_composition_surface_win.cc6
-rw-r--r--chromium/ios/chrome/browser/ui/location_bar/BUILD.gn1
-rw-r--r--chromium/ios/chrome/browser/ui/orchestrator/BUILD.gn1
-rw-r--r--chromium/ios/chrome/browser/ui/safe_mode/BUILD.gn1
-rw-r--r--chromium/ios/chrome/browser/web/BUILD.gn3
-rw-r--r--chromium/media/base/audio_renderer_mixer_input.cc62
-rw-r--r--chromium/media/base/audio_renderer_mixer_input.h17
-rw-r--r--chromium/media/base/audio_renderer_mixer_input_unittest.cc128
-rw-r--r--chromium/media/base/media_switches.cc13
-rw-r--r--chromium/media/blink/webmediaplayer_impl.cc24
-rw-r--r--chromium/media/gpu/accelerated_video_decoder.h8
-rw-r--r--chromium/media/gpu/h264_decoder.cc12
-rw-r--r--chromium/media/gpu/h264_decoder.h12
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc136
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h23
-rw-r--r--chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc41
-rw-r--r--chromium/media/gpu/vp8_decoder.cc13
-rw-r--r--chromium/media/gpu/vp8_decoder.h1
-rw-r--r--chromium/media/gpu/vp9_decoder.cc11
-rw-r--r--chromium/media/gpu/vp9_decoder.h1
-rw-r--r--chromium/media/midi/fuzz/corpus/broken_data_11
-rw-r--r--chromium/media/midi/fuzz/corpus/broken_data_21
-rw-r--r--chromium/media/midi/fuzz/corpus/broken_data_3bin2 -> 0 bytes
-rw-r--r--chromium/media/midi/fuzz/corpus/channel_pressure1
-rw-r--r--chromium/media/midi/fuzz/corpus/channel_pressure_with_running_status1
-rw-r--r--chromium/media/midi/fuzz/corpus/data_byte_0bin1 -> 0 bytes
-rw-r--r--chromium/media/midi/fuzz/corpus/gm_on1
-rw-r--r--chromium/media/midi/fuzz/corpus/gm_on_with_real_time_clock1
-rw-r--r--chromium/media/midi/fuzz/corpus/gs_onbin11 -> 0 bytes
-rw-r--r--chromium/media/midi/fuzz/corpus/mtc_framebin2 -> 0 bytes
-rw-r--r--chromium/media/midi/fuzz/corpus/note_on1
-rw-r--r--chromium/media/midi/fuzz/corpus/note_on_with_real_time_clock1
-rw-r--r--chromium/media/midi/fuzz/corpus/note_on_with_running_status1
-rw-r--r--chromium/media/midi/fuzz/corpus/partial_gm_on_11
-rw-r--r--chromium/media/midi/fuzz/corpus/partial_gm_on_21
-rw-r--r--chromium/media/midi/fuzz/corpus/partial_gm_on_31
-rw-r--r--chromium/media/midi/fuzz/corpus/partial_note_on_11
-rw-r--r--chromium/media/midi/fuzz/corpus/partial_note_on_21
-rw-r--r--chromium/media/midi/fuzz/corpus/partial_note_on_31
-rw-r--r--chromium/media/midi/fuzz/corpus/reserved_message_11
-rw-r--r--chromium/media/midi/fuzz/corpus/reserved_message_1_with_data_bytes1
-rw-r--r--chromium/media/midi/fuzz/corpus/reserved_message_21
-rw-r--r--chromium/media/midi/fuzz/corpus/system_common_message_tune_request1
-rw-r--r--chromium/media/midi/fuzz/corpus/timing_clock1
-rw-r--r--chromium/media/midi/midi_manager_alsa.cc13
-rw-r--r--chromium/media/midi/midi_manager_android.cc13
-rw-r--r--chromium/media/midi/midi_manager_mac.cc10
-rw-r--r--chromium/media/midi/midi_manager_unittest.cc88
-rw-r--r--chromium/media/midi/midi_manager_usb.cc14
-rw-r--r--chromium/media/midi/midi_manager_win.cc32
-rw-r--r--chromium/media/midi/midi_manager_win.h5
-rw-r--r--chromium/media/midi/midi_manager_winrt.cc11
-rw-r--r--chromium/media/midi/task_service.cc38
-rw-r--r--chromium/media/midi/task_service.h47
-rw-r--r--chromium/net/BUILD.gn14
-rw-r--r--chromium/net/android/network_change_notifier_android.h4
-rw-r--r--chromium/net/base/load_timing_info.h2
-rw-r--r--chromium/net/base/net_error_list.h9
-rw-r--r--chromium/net/base/network_change_notifier.cc4
-rw-r--r--chromium/net/base/network_change_notifier_chromeos.cc144
-rw-r--r--chromium/net/base/network_change_notifier_chromeos.h94
-rw-r--r--chromium/net/base/network_change_notifier_chromeos_unittest.cc87
-rw-r--r--chromium/net/base/network_change_notifier_posix.cc158
-rw-r--r--chromium/net/base/network_change_notifier_posix.h94
-rw-r--r--chromium/net/base/network_change_notifier_posix_unittest.cc89
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.dat80
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.gperf44
-rw-r--r--chromium/net/dns/BUILD.gn2
-rw-r--r--chromium/net/http/bidirectional_stream.cc4
-rw-r--r--chromium/net/http/bidirectional_stream.h9
-rw-r--r--chromium/net/http/http_network_transaction.cc62
-rw-r--r--chromium/net/http/http_network_transaction.h23
-rw-r--r--chromium/net/http/http_network_transaction_unittest.cc118
-rw-r--r--chromium/net/http/http_proxy_client_socket.cc2
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool.cc2
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool_unittest.cc2
-rw-r--r--chromium/net/http/http_stream_factory_job.cc14
-rw-r--r--chromium/net/http/http_stream_factory_job.h11
-rw-r--r--chromium/net/http/http_stream_factory_job_controller.cc6
-rw-r--r--chromium/net/http/http_stream_factory_job_controller.h15
-rw-r--r--chromium/net/http/http_stream_factory_test_util.h10
-rw-r--r--chromium/net/http/http_stream_factory_unittest.cc10
-rw-r--r--chromium/net/http/http_stream_request.h8
-rw-r--r--chromium/net/nqe/network_quality_estimator.cc34
-rw-r--r--chromium/net/nqe/network_quality_estimator.h4
-rw-r--r--chromium/net/nqe/network_quality_estimator_params.cc5
-rw-r--r--chromium/net/nqe/network_quality_estimator_params.h10
-rw-r--r--chromium/net/nqe/network_quality_estimator_unittest.cc84
-rw-r--r--chromium/net/proxy_resolution/pac_file_decider.cc24
-rw-r--r--chromium/net/proxy_resolution/pac_file_decider.h22
-rw-r--r--chromium/net/proxy_resolution/pac_file_decider_unittest.cc37
-rw-r--r--chromium/net/proxy_resolution/proxy_info.cc7
-rw-r--r--chromium/net/proxy_resolution/proxy_info.h7
-rw-r--r--chromium/net/proxy_resolution/proxy_resolution_service.cc78
-rw-r--r--chromium/net/proxy_resolution/proxy_resolution_service.h18
-rw-r--r--chromium/net/quic/quic_proxy_client_socket.cc2
-rw-r--r--chromium/net/quic/quic_proxy_client_socket_unittest.cc2
-rw-r--r--chromium/net/socket/ssl_client_socket_pool.cc2
-rw-r--r--chromium/net/spdy/fuzzing/hpack_decoder_fuzzer.cc47
-rw-r--r--chromium/net/spdy/fuzzing/hpack_example_generator.cc78
-rw-r--r--chromium/net/spdy/fuzzing/hpack_fuzz_util.cc188
-rw-r--r--chromium/net/spdy/fuzzing/hpack_fuzz_util.h91
-rw-r--r--chromium/net/spdy/fuzzing/hpack_fuzz_util_test.cc154
-rw-r--r--chromium/net/spdy/fuzzing/http2_frame_decoder_fuzzer.cc38
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket.cc2
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket_unittest.cc2
-rw-r--r--chromium/net/url_request/http_with_dns_over_https_unittest.cc10
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc9
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc22
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h10
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc33
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h4
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc231
-rw-r--r--chromium/sandbox/win/fuzzer/fuzzer_types.h38
-rw-r--r--chromium/sandbox/win/fuzzer/sandbox_ipc_fuzzer.cc28
-rw-r--r--chromium/services/media_session/audio_focus_manager.cc48
-rw-r--r--chromium/services/media_session/audio_focus_manager.h1
-rw-r--r--chromium/services/media_session/audio_focus_manager_unittest.cc269
-rw-r--r--chromium/services/network/network_change_manager.cc8
-rw-r--r--chromium/services/network/network_change_manager.h2
-rw-r--r--chromium/services/network/network_service.cc50
-rw-r--r--chromium/services/network/network_service.h19
-rw-r--r--chromium/services/network/network_service_unittest.cc18
-rw-r--r--chromium/services/network/proxy_config_service_mojo_unittest.cc101
-rw-r--r--chromium/services/network/public/cpp/network_ipc_param_traits.h1
-rw-r--r--chromium/services/network/public/cpp/proxy_config_mojom_traits.cc4
-rw-r--r--chromium/services/network/public/cpp/proxy_config_mojom_traits.h6
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader_unittest.cc3
-rw-r--r--chromium/services/network/public/cpp/url_loader_completion_status.cc3
-rw-r--r--chromium/services/network/public/cpp/url_loader_completion_status.h3
-rw-r--r--chromium/services/network/public/mojom/BUILD.gn4
-rw-r--r--chromium/services/network/public/mojom/network_change_manager.mojom2
-rw-r--r--chromium/services/network/public/mojom/network_service.mojom8
-rw-r--r--chromium/services/network/public/mojom/proxy_config.mojom10
-rw-r--r--chromium/services/network/url_loader.cc13
-rw-r--r--chromium/services/network/url_loader_unittest.cc2
-rw-r--r--chromium/services/network/websocket.cc9
-rw-r--r--chromium/services/network/websocket_factory.cc8
-rw-r--r--chromium/services/tracing/public/cpp/traced_process_impl.cc7
-rw-r--r--chromium/skia/ext/skia_commit_hash.h2
-rw-r--r--chromium/testing/variations/fieldtrial_testing_config.json20
-rw-r--r--chromium/third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp179
-rw-r--r--chromium/third_party/blink/common/features.cc5
-rw-r--r--chromium/third_party/blink/common/frame/user_activation_state.cc2
-rw-r--r--chromium/third_party/blink/common/frame/user_activation_state_unittest.cc4
-rw-r--r--chromium/third_party/blink/public/BUILD.gn30
-rw-r--r--chromium/third_party/blink/public/common/features.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py1
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl6
-rw-r--r--chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_caret.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_test.cc83
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc69
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js14
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h14
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc146
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h2
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/View.js32
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/face_detector.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/text_detector.idl2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_compact.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/runtime_enabled_features.json51
-rw-r--r--chromium/third_party/brotli/fuzz/DEPS3
-rw-r--r--chromium/third_party/brotli/fuzz/decode_fuzzer.cc53
-rw-r--r--chromium/third_party/catapult/catapult_build/PRESUBMIT.py40
-rw-r--r--chromium/third_party/catapult/catapult_build/__init__.py33
-rw-r--r--chromium/third_party/catapult/catapult_build/appengine_deploy.py69
-rw-r--r--chromium/third_party/catapult/catapult_build/appengine_dev_server.py38
-rwxr-xr-xchromium/third_party/catapult/catapult_build/bin/run_py_tests27
-rw-r--r--chromium/third_party/catapult/catapult_build/bin_checks.py29
-rw-r--r--chromium/third_party/catapult/catapult_build/build_steps.py289
-rw-r--r--chromium/third_party/catapult/catapult_build/build_steps_unittest.py44
-rw-r--r--chromium/third_party/catapult/catapult_build/dev_server.py324
-rw-r--r--chromium/third_party/catapult/catapult_build/dev_server_unittest.py90
-rwxr-xr-xchromium/third_party/catapult/catapult_build/fetch_telemetry_deps_and_run_tests28
-rw-r--r--chromium/third_party/catapult/catapult_build/html_checks.py72
-rw-r--r--chromium/third_party/catapult/catapult_build/html_checks_unittest.py94
-rw-r--r--chromium/third_party/catapult/catapult_build/js_checks.py113
-rw-r--r--chromium/third_party/catapult/catapult_build/js_checks_unittest.py78
-rw-r--r--chromium/third_party/catapult/catapult_build/node_bootstrap.js83
-rw-r--r--chromium/third_party/catapult/catapult_build/parse_html.py18
-rw-r--r--chromium/third_party/catapult/catapult_build/perfbot_stats/__init__.py3
-rwxr-xr-xchromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_stats.py155
-rw-r--r--chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_stats_unittest.py74
-rwxr-xr-xchromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_step_timings.py166
-rwxr-xr-xchromium/third_party/catapult/catapult_build/print_project_info80
-rw-r--r--chromium/third_party/catapult/catapult_build/remove_stale_files.py48
-rw-r--r--chromium/third_party/catapult/catapult_build/repo_checks.py17
-rw-r--r--chromium/third_party/catapult/catapult_build/run_dev_server_tests.py234
-rw-r--r--chromium/third_party/catapult/catapult_build/run_wct.py31
-rw-r--r--chromium/third_party/catapult/catapult_build/run_with_typ.py37
-rw-r--r--chromium/third_party/catapult/catapult_build/temp_deployment_dir.py39
-rw-r--r--chromium/third_party/catapult/catapult_build/test_runner.py61
-rw-r--r--chromium/third_party/catapult/common/OWNERS4
-rwxr-xr-xchromium/third_party/catapult/common/bin/run_tests38
-rwxr-xr-xchromium/third_party/catapult/common/bin/update_chrome_reference_binaries189
-rw-r--r--chromium/third_party/catapult/common/eslint/LICENSE20
-rw-r--r--chromium/third_party/catapult/common/eslint/OWNERS1
-rw-r--r--chromium/third_party/catapult/common/eslint/README.md5
-rwxr-xr-xchromium/third_party/catapult/common/eslint/bin/run_eslint54
-rwxr-xr-xchromium/third_party/catapult/common/eslint/bin/run_tests35
-rw-r--r--chromium/third_party/catapult/common/eslint/eslint/__init__.py68
-rw-r--r--chromium/third_party/catapult/common/eslint/eslint/smoke_test.py36
-rw-r--r--chromium/third_party/catapult/common/eslint/rules/catapult-camelcase.js154
-rwxr-xr-xchromium/third_party/catapult/common/lab/commits.py105
-rwxr-xr-xchromium/third_party/catapult/common/lab/hardware.py93
-rwxr-xr-xchromium/third_party/catapult/common/lab/keychain_unlock.sh15
-rw-r--r--chromium/third_party/catapult/common/node_runner/node_runner/README.md11
-rw-r--r--chromium/third_party/catapult/common/node_runner/node_runner/__init__.py4
-rwxr-xr-xchromium/third_party/catapult/common/node_runner/node_runner/minify53
-rw-r--r--chromium/third_party/catapult/common/node_runner/node_runner/node_binaries.json53
-rw-r--r--chromium/third_party/catapult/common/node_runner/node_runner/node_util.py60
-rw-r--r--chromium/third_party/catapult/common/node_runner/node_runner/package-lock.json5915
-rw-r--r--chromium/third_party/catapult/common/node_runner/node_runner/package.json29
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/README.txt7
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/__init__.py9
-rwxr-xr-xchromium/third_party/catapult/common/py_trace_event/py_trace_event/run_tests163
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/setup.py12
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event.py282
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/__init__.py7
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators.py87
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators_test.py62
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log.py183
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log_io_test.py50
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/meta_class.py16
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/multiprocessing_shim.py92
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/parsed_trace_events.py98
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/trace_test.py48
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_unittest.py423
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_time.py234
-rw-r--r--chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_time_unittest.py123
-rw-r--r--chromium/third_party/catapult/common/py_utils/PRESUBMIT.py31
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/__init__.py158
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/atexit_with_log.py21
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/binary_manager.py61
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/binary_manager_unittest.py214
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/camel_case.py30
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/camel_case_unittest.py50
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/chrome_binaries.json91
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/class_util.py26
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/class_util_unittest.py138
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage.py502
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage_global_lock.py5
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage_unittest.py387
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/contextlib_ext.py33
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/contextlib_ext_unittest.py34
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/dependency_util.py49
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/discover.py191
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/discover_unittest.py146
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/expectations_parser.py124
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/expectations_parser_unittest.py165
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/file_util.py23
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/file_util_unittest.py66
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/lock.py121
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/lock_unittest.py165
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/logging_util.py35
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/logging_util_unittest.py27
-rwxr-xr-xchromium/third_party/catapult/common/py_utils/py_utils/memory_debug.py93
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/modules_util.py35
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/modules_util_unittest.py42
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/py_utils_unittest.py56
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/__init__.py28
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/__init__.py71
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/base_symbol.py36
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/class_definition.py49
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/function_definition.py49
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/import_statement.py327
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/reference.py76
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/module.py39
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/offset_token.py115
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor/snippet.py246
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/__init__.py0
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py118
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/retry_util.py57
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/retry_util_unittest.py119
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/shell_util.py42
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/slots_metaclass.py27
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/slots_metaclass_unittest.py41
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/tempfile_ext.py30
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/tempfile_ext_unittest.py39
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/__init__.py3
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/another_discover_dummyclass.py33
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/discover_dummyclass.py9
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/parameter_discover_dummyclass.py11
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/test_data/foo.txt1
-rw-r--r--chromium/third_party/catapult/common/py_utils/py_utils/xvfb.py29
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/README.chromium8
-rwxr-xr-xchromium/third_party/catapult/common/py_vulcanize/bin/run_py_tests29
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/__init__.py11
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/fake_fs.py146
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/fake_fs_unittest.py52
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/generate.py274
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/generate_unittest.py89
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_generation_controller.py28
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_module.py154
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py321
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/js_utils.py7
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/js_utils_unittest.py18
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/module.py262
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/module_unittest.py130
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/parse_html_deps.py283
-rwxr-xr-xchromium/third_party/catapult/common/py_vulcanize/py_vulcanize/parse_html_deps_unittest.py292
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/project.py235
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource.py57
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource_loader.py228
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource_unittest.py17
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/strip_js_comments.py81
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/strip_js_comments_unittest.py54
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/style_sheet.py138
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/style_sheet_unittest.py67
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/LICENSE201
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/MANIFEST354
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/PKG-INFO316
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/README.chromium16
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/README.rst153
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/__init__.py39
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/include/cext.h244
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/__init__.py27
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/commands.py267
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/data.py165
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/dist.py51
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/ext.py254
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/setup.py419
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/shell.py478
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/term/__init__.py28
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/term/_term.py115
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/util.py73
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/__init__.py27
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/commands.py266
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/data.py165
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/dist.py51
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/ext.py253
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/setup.py420
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/shell.py351
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/term/__init__.py28
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/term/_term.py116
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/util.py63
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/LICENSE.cssmin64
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/__init__.py30
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/cssmin.py246
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/main.py236
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/wikipedia.css3861
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/wikipedia.min.css1
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/write.py344
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/BENCHMARKS61
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/CHANGES42
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/CLASSIFIERS19
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/DESCRIPTION85
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/PROVIDES1
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/SUMMARY1
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/api-objects.txt6
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/crarr.pngbin0 -> 340 bytes
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/epydoc.css322
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/epydoc.js293
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/help.html261
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/identifier-index.html163
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/index.html224
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/module-tree.html94
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/rcssmin-module.html224
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/rcssmin-pysrc.html477
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/redirect.html38
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/package.cfg84
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/rcssmin.c1163
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/rcssmin.py374
-rwxr-xr-xchromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/run_tests.py166
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/setup.py42
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/LICENSE201
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/MANIFEST57
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/PKG-INFO304
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/README.chromium18
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/README.rst142
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/__init__.py39
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/include/cext.h286
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/__init__.py27
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/commands.py267
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/data.py165
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/dist.py51
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/ext.py254
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/setup.py421
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/shell.py478
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/util.py73
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/__init__.py27
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/commands.py266
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/data.py165
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/dist.py51
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/ext.py253
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/setup.py426
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/shell.py351
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/util.py63
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/DateTimeShortcuts.js388
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/__init__.py30
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/apiviewer.js178
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/bootstrap.js1829
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jquery-1.7.1.js9266
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin.c291
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin.py226
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin_2_0_9.py233
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/knockout-2.0.0.js97
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/main.py234
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/markermanager.js976
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/write.py345
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/BENCHMARKS165
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/CHANGES111
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/CLASSIFIERS19
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/DESCRIPTION73
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/PROVIDES1
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/SUMMARY1
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/api-objects.txt7
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/crarr.pngbin0 -> 340 bytes
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/epydoc.css322
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/epydoc.js293
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/help.html261
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/identifier-index.html163
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/index.html216
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/module-tree.html94
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/redirect.html38
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/rjsmin-module.html216
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/rjsmin-pysrc.html617
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/package.cfg76
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/rjsmin.c510
-rwxr-xr-xchromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/rjsmin.py515
-rw-r--r--chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/setup.py42
-rw-r--r--chromium/third_party/catapult/third_party/polymer/components/polymer/.bower.json45
-rw-r--r--chromium/third_party/catapult/third_party/polymer/components/polymer/LICENSE.txt27
-rw-r--r--chromium/third_party/catapult/third_party/polymer/components/polymer/bower.json35
-rw-r--r--chromium/third_party/catapult/third_party/polymer/components/polymer/build.log576
-rw-r--r--chromium/third_party/catapult/third_party/polymer/components/polymer/polymer-micro.html821
-rw-r--r--chromium/third_party/catapult/third_party/polymer/components/polymer/polymer-mini.html2246
-rw-r--r--chromium/third_party/catapult/third_party/polymer/components/polymer/polymer.html5555
-rw-r--r--chromium/third_party/catapult/tracing/.allow-devtools-save0
-rw-r--r--chromium/third_party/catapult/tracing/.bowerrc3
-rw-r--r--chromium/third_party/catapult/tracing/.npmignore17
-rw-r--r--chromium/third_party/catapult/tracing/LICENSE27
-rw-r--r--chromium/third_party/catapult/tracing/OWNERS21
-rw-r--r--chromium/third_party/catapult/tracing/PRESUBMIT.py81
-rw-r--r--chromium/third_party/catapult/tracing/README.md52
-rw-r--r--chromium/third_party/catapult/tracing/app.yaml58
-rw-r--r--chromium/third_party/catapult/tracing/bin/PRESUBMIT.py19
-rw-r--r--chromium/third_party/catapult/tracing/bin/README.md42
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/add_reserved_diagnostics94
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/chartjson2histograms.py38
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/compare_samples51
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/generate_about_tracing_contents14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/histograms2csv40
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/histograms2html56
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/html2trace53
-rw-r--r--chromium/third_party/catapult/tracing/bin/index.html115
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/label_histograms56
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/map_traces14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/memory_infra_remote_dump131
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/merge_histograms32
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/merge_traces14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/results2json36
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_dev_server_tests14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_metric76
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_node_tests23
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_py_tests46
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_symbolizer_tests39
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_tests25
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/run_vinn_tests14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/slim_trace16
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/strip_memory_infra_trace13
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/symbolize_trace17
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/trace2html14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/update_gni14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/validate_all_diagnostics112
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/validate_all_metrics43
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/vulcanize_trace_viewer14
-rwxr-xr-xchromium/third_party/catapult/tracing/bin/why_imported48
-rw-r--r--chromium/third_party/catapult/tracing/bower.json22
-rw-r--r--chromium/third_party/catapult/tracing/docs/coordinate-systems.md46
-rw-r--r--chromium/third_party/catapult/tracing/docs/embedding-trace-viewer.md54
-rw-r--r--chromium/third_party/catapult/tracing/docs/extending-and-customizing-trace-viewer.md26
-rw-r--r--chromium/third_party/catapult/tracing/docs/getting-started.md21
-rw-r--r--chromium/third_party/catapult/tracing/docs/trace-viewer-internals.md129
-rw-r--r--chromium/third_party/catapult/tracing/images/third-trace-viewer-circle-blue.pngbin0 -> 3111 bytes
-rw-r--r--chromium/third_party/catapult/tracing/images/trace-viewer-circle-blue.pngbin0 -> 9703 bytes
-rw-r--r--chromium/third_party/catapult/tracing/images/trace-viewer-circle-green.pngbin0 -> 9711 bytes
-rw-r--r--chromium/third_party/catapult/tracing/images/trace-viewer-circle-red.pngbin0 -> 9528 bytes
-rw-r--r--chromium/third_party/catapult/tracing/images/trace-viewer-circle-yellow.pngbin0 -> 9633 bytes
-rw-r--r--chromium/third_party/catapult/tracing/images/trace-viewer-square-blue.pngbin0 -> 3199 bytes
-rw-r--r--chromium/third_party/catapult/tracing/images/trace-viewer-square-green.pngbin0 -> 3170 bytes
-rw-r--r--chromium/third_party/catapult/tracing/images/trace-viewer-square-red.pngbin0 -> 3122 bytes
-rw-r--r--chromium/third_party/catapult/tracing/images/trace-viewer-square-yellow.pngbin0 -> 3519 bytes
-rw-r--r--chromium/third_party/catapult/tracing/package.json22
-rw-r--r--chromium/third_party/catapult/tracing/skp_data/google_homepage.skpbin0 -> 181402 bytes
-rw-r--r--chromium/third_party/catapult/tracing/skp_data/lthi_cats.skpbin0 -> 616665 bytes
-rw-r--r--chromium/third_party/catapult/tracing/third_party/chai/LICENSE7
-rw-r--r--chromium/third_party/catapult/tracing/third_party/chai/README.chromium15
-rw-r--r--chromium/third_party/catapult/tracing/third_party/chai/chai.js2
-rw-r--r--chromium/third_party/catapult/tracing/third_party/d3/LICENSE26
-rw-r--r--chromium/third_party/catapult/tracing/third_party/d3/README.chromium15
-rw-r--r--chromium/third_party/catapult/tracing/third_party/d3/d3.min.js5
-rw-r--r--chromium/third_party/catapult/tracing/third_party/devscripts/COPYING340
-rw-r--r--chromium/third_party/catapult/tracing/third_party/devscripts/README.chromium12
-rwxr-xr-xchromium/third_party/catapult/tracing/third_party/devscripts/licensecheck.pl671
-rw-r--r--chromium/third_party/catapult/tracing/third_party/devscripts/licensecheck.pl.vanilla577
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/BUILDING.md7
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/LICENSE.md19
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/README.chromium15
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/README.md22
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/TESTING.md12
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/VERSION1
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/bower.json27
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/dist/gl-matrix-min.js29
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/dist/gl-matrix.js5020
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/allclasses.tmpl14
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/allfiles.tmpl65
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/class.tmpl340
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/index.tmpl52
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/publish.js201
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/default.css428
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/header.html2
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/index.html19
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/symbol.tmpl35
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/package.json30
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/common-spec.js14
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat2-spec.js210
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat2d-spec.js194
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat3-spec.js347
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat4-spec.js637
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/quat-spec.js559
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec2-spec.js549
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec3-spec.js661
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec4-spec.js492
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/worker-spec.js44
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/helpers/spec-helper.js32
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/jasmine.yml74
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix.js37
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/common.js52
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat2.js302
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat2d.js317
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat3.js565
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat4.js1283
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/quat.js553
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec2.js523
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec3.js709
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec4.js537
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build.rake2
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build/compile.rake5
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build/minify.rake5
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/default.rake1
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/release.rake21
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix.rb84
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix/release_helper.rb104
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix/version.rb28
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/webpack.config.js47
-rw-r--r--chromium/third_party/catapult/tracing/third_party/gl-matrix/webpack.config.min.js28
-rw-r--r--chromium/third_party/catapult/tracing/third_party/jszip/LICENSE.markdown651
-rw-r--r--chromium/third_party/catapult/tracing/third_party/jszip/README.chromium16
-rw-r--r--chromium/third_party/catapult/tracing/third_party/jszip/README.markdown32
-rw-r--r--chromium/third_party/catapult/tracing/third_party/jszip/jszip.min.js14
-rw-r--r--chromium/third_party/catapult/tracing/third_party/mannwhitneyu/README.chromium15
-rw-r--r--chromium/third_party/catapult/tracing/third_party/mannwhitneyu/mannwhitneyu.js197
-rw-r--r--chromium/third_party/catapult/tracing/third_party/mocha/LICENSE22
-rw-r--r--chromium/third_party/catapult/tracing/third_party/mocha/README.chromium9
-rw-r--r--chromium/third_party/catapult/tracing/third_party/mocha/mocha.css270
-rwxr-xr-xchromium/third_party/catapult/tracing/third_party/mocha/mocha.js6557
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/.npmignore12
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/.travis.yml3
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/CONTRIBUTING.md71
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/Gruntfile.js398
-rwxr-xr-xchromium/third_party/catapult/tracing/third_party/oboe/LICENCE26
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/README.chromium19
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/README.md24
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/.gitIgnore0
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/benchmarkClient.js127
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/benchmarkServer.js94
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/build/README.md1
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/component.json18
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-browser.js2707
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-browser.min.js1
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-node.js2587
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/index.js3
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/jasmine.json8
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/logo.pngbin0 -> 14032 bytes
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/package.json86
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/LICENCE.js30
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/ascent.js15
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/ascentManager.js62
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/defaults.js41
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/detectCrossOrigin.browser.js65
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/events.js45
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/functional.js250
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/incrementalContentBuilder.js150
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/instanceApi.js254
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/jsonPath.js364
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/jsonPathSyntax.js115
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/libs/clarinet.js501
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/lists.js192
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/parseResponseHeaders.browser.js24
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/patternAdapter.js112
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/pubSub.js64
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/publicApi.js56
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/singleEventPubSub.js93
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/streamingHttp.browser.js149
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/streamingHttp.node.js135
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/util.js44
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/wire.js34
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/wrapper.browser.js24
-rw-r--r--chromium/third_party/catapult/tracing/third_party/oboe/src/wrapper.node.js9
-rw-r--r--chromium/third_party/catapult/tracing/third_party/pako/LICENSE21
-rw-r--r--chromium/third_party/catapult/tracing/third_party/pako/README.chromium15
-rw-r--r--chromium/third_party/catapult/tracing/third_party/pako/pako.min.js1
-rw-r--r--chromium/third_party/catapult/tracing/third_party/symbols/README.chromium21
-rw-r--r--chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py21
-rw-r--r--chromium/third_party/catapult/tracing/third_party/symbols/symbols/__init__.py0
-rw-r--r--chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py470
-rwxr-xr-xchromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py174
-rw-r--r--chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/__init__.py0
-rwxr-xr-xchromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line83
-rw-r--r--chromium/third_party/catapult/tracing/tracing/__init__.py6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/assert_utils.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/base.html190
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/base64.html94
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/base64_test.html63
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/category_util.html40
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/color.html260
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/color_scheme.html237
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/color_scheme_test.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/color_test.html103
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/event.html104
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/event_target.html139
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/event_target_test.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/extension_registry.html66
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/extension_registry_base.html105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/extension_registry_basic.html127
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/extension_registry_test.html132
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/extension_registry_type_based.html162
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/fixed_color_scheme.html72
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/fixed_color_scheme_test.html64
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/guid.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/headless_tests.html82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/in_memory_trace_stream.html113
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/in_memory_trace_stream_test.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/interval_tree.html350
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/interval_tree_test.html235
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/bbox2.html156
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/bbox2_test.html36
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/math.html251
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/math_test.html158
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/piecewise_linear_function.html142
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/piecewise_linear_function_test.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/quad.html233
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/quad_test.html129
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/range.html308
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/range_test.html591
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/range_utils.html135
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/range_utils_test.html133
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/rect.html163
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/rect_test.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/running_statistics.html207
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/running_statistics_test.html213
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/statistics.html857
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/math/statistics_test.html579
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/multi_dimensional_view.html1217
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/multi_dimensional_view_test.html13382
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/raf.html222
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/raf_test.html245
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/scalar.html50
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/scalar_test.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/serializable.html104
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/serializable_test.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/settings.html214
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/settings_test.html113
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/sinebow_color_generator.html93
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/sinebow_color_generator_test.html82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/task.html163
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/task_test.html79
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/time_display_modes.html52
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/timing.html129
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/timing_test.html23
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/trace_stream.html105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unit.html531
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unit_scale.html181
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unit_scale_test.html170
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unit_test.html444
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/constants.html28
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html540
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/interactive_test_runner.html735
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html253
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/test_case.html146
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/test_case_test.html18
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/test_runner.html285
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html142
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest/text_test_results.html139
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/unittest_test.html50
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/url_json.html99
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/url_json_test.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/utils.html652
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/utils_test.html433
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/view_state.html94
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/view_state_test.html100
-rw-r--r--chromium/third_party/catapult/tracing/tracing/base/xhr.html156
-rw-r--r--chromium/third_party/catapult/tracing/tracing/core/auditor.html56
-rw-r--r--chromium/third_party/catapult/tracing/tracing/core/filter.html130
-rw-r--r--chromium/third_party/catapult/tracing/tracing/core/filter_test.html107
-rw-r--r--chromium/third_party/catapult/tracing/tracing/core/scripting_controller.html66
-rw-r--r--chromium/third_party/catapult/tracing/tracing/core/scripting_controller_test.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/core/scripting_object.html26
-rw-r--r--chromium/third_party/catapult/tracing/tracing/core/test_utils.html498
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/__init__.py3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/ads/domain_category.html87
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/ads/domain_category_test.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/android/android_auditor.html767
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/android/android_auditor_test.html424
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/blame_context.html75
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/blame_context_test.html64
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/frame_blame_context_test.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/frame_tree_node.html70
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/render_frame.html82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/top_level.html59
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/blink/blink_scheduler_async_slice.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/blink/blink_scheduler_async_slice_test.html54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/cc.html12
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/constants.html27
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/debug_colors.html77
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/display_item_list.html54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/display_item_list_test.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice.html645
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice_test.html702
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_impl.html228
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl.html198
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test.html30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js345
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_impl.html178
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture.html451
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture_as_image_data.html70
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture_test.html81
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/raster_task.html66
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/region.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/render_pass.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile.html91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile_coverage_rect.html28
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile_test.html30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/util.html129
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/util_test.html114
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html84
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html129
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_processes.html69
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html161
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html261
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html84
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time.html164
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_multidimensional_view.md79
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_test.html1503
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_test_utils.html126
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency.html367
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html384
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/event_finder_utils.html234
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/event_finder_utils_test.html256
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice_test.html73
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state.html53
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state_test.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state_test_data.js22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_object.html207
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_object_test.html77
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_tree.html47
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/slice_title_fixer.html38
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/slice_title_fixer_test.html28
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/time_to_interactive.html397
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome/time_to_interactive_test.html329
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/chrome_config.html37
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/cpu/cpu_usage_auditor.html117
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/full_config.html12
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/android/atrace_process_dump_importer.html216
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/android/atrace_process_dump_importer_test.html87
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/android/event_log_importer.html324
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/android/process_data_importer.html178
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/android/process_data_importer_test.html140
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/battor_importer.html186
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/battor_importer_test.html103
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/ddms_importer.html223
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/ddms_importer_test.html188
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/etw_importer.html483
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/etw_importer_test.html293
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/eventtrace_parser.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/eventtrace_parser_test.html119
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/parser.html73
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/process_parser.html190
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/process_parser_test.html149
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/thread_parser.html256
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/etw/thread_parser_test.html176
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html234
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer_test.html183
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/gcloud_trace/gcloud_trace_importer.html99
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/gcloud_trace/gcloud_trace_importer_test.html101
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/gzip_importer.html252
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/gzip_importer_test.html108
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/heap_dump_trace_event_importer.html91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/jszip.html35
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/legacy_heap_dump_trace_event_importer.html214
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/android_parser.html239
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/android_parser_test.html233
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser.html732
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser_test.html273
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser.html97
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser_test.html68
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser.html112
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser_test.html110
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser.html114
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser_test.html173
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser.html302
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser_test.html119
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser.html69
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser_test.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser.html125
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser_test.html134
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/fence_parser.html163
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/fence_parser_test.html32
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html941
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer_test.html686
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser.html143
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser_test.html213
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i2c_parser.html177
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i2c_parser_test.html82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser.html363
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser_test.html105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ion_heap_parser.html109
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ion_heap_parser_test.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser.html271
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser_test.html67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser_test.html60
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser.html659
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser_test.html559
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser.html181
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser_test.html170
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/parser.html90
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/power_parser.html179
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/power_parser_test.html97
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser.html139
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser_test.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/rss_parser.html87
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/rss_parser_test.html35
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser.html161
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser_test.html262
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser.html121
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser_test.html55
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser.html100
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser_test.html38
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/oboe.html32
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/pako.html9
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/profiling_dictionary_reader.html315
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/profiling_dictionary_reader_test.html275
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace2html_importer.html94
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace2html_importer_test.html73
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_entry.html128
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_entry_test.html123
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_map.html124
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html3394
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_perf_test.html103
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html6593
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/v8/codemap.html383
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/v8/log_reader.html213
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/v8/splaytree.html295
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/v8/v8_log_importer.html393
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/v8/v8_log_importer_test.html290
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/importer/zip_importer.html72
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/lean_config.html14
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/measure/measure.html8
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/measure/measure_async_slice.html55
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/measure/measure_async_slice_test.html63
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/memory/lowmemory_auditor.html58
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/net/net.html8
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/net/net_async_slice.html103
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/net/net_async_slice_test.html195
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/OWNERS2
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/__init__.py3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/addr2line-pdb.exe.sha11
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/linux_trace_v2_presymbolization.json.gz.sha11
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/mac_trace_v2_presymbolization.json.gz.sha11
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/windows_trace_v1_presymbolization.json.gz.sha11
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/windows_trace_v2_presymbolization.json.gz.sha11
-rwxr-xr-xchromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py1707
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_atos_regex.py36
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_atos_regex_unittest.py49
-rwxr-xr-xchromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_end_to_end_test_slow.py195
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py26
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py26
-rwxr-xr-xchromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_unittest.py69
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/system_stats/system_stats_snapshot.html54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/systrace_config.html19
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/context.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/filter.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_all_of.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_any_of.html66
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_ancestor.html53
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_duration.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_title.html41
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_is_top_level.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_not.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/tquery.html188
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/tquery/tquery_test.html247
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8/ic_stats_entry.html209
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8/ic_stats_entry_test.html112
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8/runtime_stats_entry.html221
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8/runtime_stats_entry_test.html322
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8/v8_cpu_profile_node.html115
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8/v8_gc_stats_thread_slice.html49
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8/v8_ic_stats_thread_slice.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8/v8_thread_slice.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/v8_config.html11
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor.html143
-rw-r--r--chromium/third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor_test.html140
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/clock_sync_test.html125
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/context_processor.html206
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/context_processor_test.html297
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/empty_importer.html49
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/find_input_expectations.html1409
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html325
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/find_startup_expectations.html88
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/import.html339
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/import_test.html228
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/importer.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html202
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/simple_line_reader.html93
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/user_expectation_verifier.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/user_model_builder.html277
-rw-r--r--chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html1649
-rw-r--r--chromium/third_party/catapult/tracing/tracing/index.js24
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/__init__.py15
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/accessibility_metric.html83
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/accessibility_metric_test.html74
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/all_fixed_color_schemes.html10
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html153
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html191
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/android_systrace_metric.html224
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/android_systrace_metric_test.html146
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric.html265
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html347
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/blink/leak_detection_metric.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/blink/leak_detection_metric_test.html179
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/buildbot_output_for_compare_samples_test.txt187
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/compare_samples.py54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_cmdline.html225
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py336
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/console_error_metric.html72
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/console_error_metric_unittest.html100
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/cpu_process_metric.html92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/cpu_process_metric_test.html119
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/discover.py34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/discover_cmdline.html32
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py20
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html395
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/media_metric_test.html423
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html216
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function_test.html214
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/metric_registry.html116
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/metric_registry_test.html93
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/metric_runner.py75
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html195
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html280
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_time.html272
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_time_test.html301
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/latency.html138
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/latency_test.html119
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/pipeline.html258
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/pipeline_test.html366
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/pixels.html105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/pixels_test.html64
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html88
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration_test.html54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html52
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/sample_exception_metric.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/sample_metric.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_helper.html248
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_helper_test.html258
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_metric.html103
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_metric_test.html234
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers.html275
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html337
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/clock_sync_latency_metric.html54
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/clock_sync_latency_metric_test.html65
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html101
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric_test.html163
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_tree_data_reporter.html182
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_tree_data_reporter_test.html155
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/expected_queueing_time_metric.html462
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/expected_queueing_time_metric_test.html409
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/limited_cpu_time_metric.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html623
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html1142
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/long_tasks_metric.html137
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/long_tasks_metric_test.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html1332
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html4249
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/new_cpu_time_metric.html79
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/new_cpu_time_metric_test.html186
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/power_metric.html348
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/power_metric_test.html742
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/responsiveness_metric.html162
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/responsiveness_metric_test.html68
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/utils.html152
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/webview_startup_metric.html64
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/system_health/webview_startup_metric_test.html50
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/tabs_metric.html89
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/tabs_metric_test.html122
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/tracing_metric.html230
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/tracing_metric_test.html168
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/execution_metric.html228
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/execution_metric_test.html71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html297
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html210
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/runtime_stats_metric.html374
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/runtime_stats_metric_test.html718
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html490
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/utils_test.html189
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/vr/frame_cycle_duration_metric.html261
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/vr/frame_cycle_duration_metric_test.html333
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/vr/webvr_metric.html117
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/vr/webvr_metric_test.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/webrtc/webrtc_rendering_metric.html364
-rw-r--r--chromium/third_party/catapult/tracing/tracing/metrics/webrtc/webrtc_rendering_metric_test.html456
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/activity.html56
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/alert.html55
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/annotation.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/annotation_test.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/async_slice.html169
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/async_slice_group.html211
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/async_slice_group_test.html171
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/async_slice_test.html57
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html467
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager_test.html471
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/comment_box_annotation.html60
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/compound_event_selection_state.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/constants.html29
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/container_memory_dump.html92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/container_memory_dump_test.html181
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/counter.html190
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/counter_sample.html95
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/counter_sample_test.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/counter_series.html124
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/counter_test.html124
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/cpu.html282
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/cpu_slice.html68
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/cpu_test.html206
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/device.html124
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/device_test.html71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/event.html77
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/event_container.html167
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/event_container_test.html95
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/event_info.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/event_registry.html91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/event_set.html302
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/event_set_test.html360
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/event_test.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/flow_event.html67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/frame.html96
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/global_memory_dump.html849
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/global_memory_dump_test.html3954
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/heap_dump.html76
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/heap_dump_test.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/android_app.html344
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/android_model_helper.html105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/android_model_helper_test.html267
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/android_surface_flinger.html115
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_browser_helper.html119
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_browser_helper_test.html74
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_gpu_helper.html47
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_gpu_helper_test.html110
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_model_helper.html168
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_model_helper_test.html238
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_process_helper.html120
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_renderer_helper.html76
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_renderer_helper_test.html16
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_thread_helper.html37
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_thread_helper_test.html97
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html128
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html101
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/instant_event.html100
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/interaction_record_test.html115
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/ir_coverage.html91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/ir_coverage_test.html90
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/kernel.html137
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/kernel_test.html73
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/location.html158
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/memory_allocator_dump.html221
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/memory_allocator_dump_test.html221
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/memory_dump_test_utils.html220
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/model.html670
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/model_indices.html56
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/model_indices_test.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/model_settings.html148
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/model_settings_test.html178
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/model_stats.html97
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/model_stats_test.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/model_test.html343
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/object_collection.html229
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/object_collection_test.html230
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/object_instance.html213
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/object_instance_test.html70
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/object_snapshot.html90
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/object_snapshot_test.html40
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/power_sample.html71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/power_sample_test.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/power_series.html129
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/power_series_test.html151
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/process.html175
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/process_base.html244
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/process_memory_dump.html247
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/process_memory_dump_test.html561
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/process_test.html127
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/profile_node.html90
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/profile_tree.html88
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/proxy_selectable_item.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/proxy_selectable_item_test.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/rect_annotation.html65
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/resource_usage_sample.html74
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/resource_usage_sample_test.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/resource_usage_series.html121
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/resource_usage_series_test.html152
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/sample.html97
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/sample_test.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/scoped_id.html42
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/selectable_item.html57
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/selectable_item_test.html80
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/selection_state.html72
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/slice.html302
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/slice_group.html720
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/slice_group_test.html935
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/slice_test.html239
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/source_info/js_source_info.html57
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/source_info/source_info.html60
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/source_info/source_info_test.html27
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/stack_frame.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/stack_frame_test.html29
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/thread.html358
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/thread_slice.html71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/thread_slice_test.html41
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/thread_test.html209
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/thread_time_slice.html154
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/time_to_object_instance_map.html179
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/time_to_object_instance_map_test.html164
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/timed_event.html69
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/timed_event_test.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/animation_expectation.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/idle_expectation.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/load_expectation.html93
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/response_expectation.html35
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/segment.html49
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/startup_expectation.html33
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/stub_expectation.html76
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/user_expectation.html177
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/user_model.html95
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/user_model/user_model_test.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/vm_region.html444
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/vm_region_test.html1216
-rw-r--r--chromium/third_party/catapult/tracing/tracing/model/x_marker_annotation.html50
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/__init__.py3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/corpus_driver.py9
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/corpus_driver_cmdline.py23
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/failure.html47
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/failure.py53
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/failure_test.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py56
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/file_handle.html113
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/file_handle.py100
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/function_handle.html185
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/function_handle.py139
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/function_handle_test.html122
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/gtest_progress_reporter.py91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/job.html49
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/job.py39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/job_unittest.py15
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py20
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py69
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_runner.py105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py196
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_cmdline.html93
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py235
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_traces.py67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/map_traces_handler.py14
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/mre_result.html65
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/mre_result.py48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/mre_result_test.html30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/output_formatter.py19
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/progress_reporter.py27
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/reduce_map_results.html28
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/reduce_map_results_cmdline.html73
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/run_and_convert_errors_to_failures.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/test_trace.json6
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue.py124
-rw-r--r--chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py33
-rw-r--r--chromium/third_party/catapult/tracing/tracing/tests.html53
-rw-r--r--chromium/third_party/catapult/tracing/tracing/trace2html.html76
-rw-r--r--chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py4
-rw-r--r--chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py346
-rw-r--r--chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py98
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view.html181
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_link.html147
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_link_test.html58
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_sub_view.html266
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_sub_view_test.html35
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_view.html207
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_view_test.html141
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view.html200
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html351
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/counter_sample_sub_view.html139
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/counter_sample_sub_view_test.html177
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/flow_classifier.html92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/flow_classifier_test.html52
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart.html134
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_perf_test.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html267
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html347
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html222
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html893
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane_test.html1261
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_header_pane.html178
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_header_pane_test.html134
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html354
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_pane.html451
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_pane_test.html4045
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_path_view.html149
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_util.html101
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane.html774
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane_test.html840
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_test_utils.html593
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util.html915
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util_test.html1241
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html382
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane_test.html496
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view.html79
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view_test.html47
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view_test.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view.html211
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html94
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary.html207
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_table.html358
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_table_test.html119
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_test.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_flow_event_sub_view.html49
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_flow_event_sub_view_test.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_frame_sub_view.html58
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_instant_event_sub_view.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_instant_event_sub_view_test.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_object_sub_view.html112
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_object_sub_view_test.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_power_sample_sub_view.html77
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_power_sample_sub_view_test.html64
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view.html234
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view_test.html71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view.html104
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view_test.html87
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view.html52
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view_test.html49
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_user_expectation_sub_view.html80
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/object_instance_view.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/object_snapshot_view.html63
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/power_sample_summary_table.html135
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/power_sample_summary_table_test.html137
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/rebuildable_behavior.html57
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/rebuildable_behavior_test.html67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/related_events.html354
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/related_events_test.html221
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/selection_summary_table.html97
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/selection_summary_table_test.html75
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view.html79
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view_test.html41
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view.html149
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view_test.html80
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_event_sub_view.html356
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_event_sub_view_test.html277
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view.html82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view_test.html53
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_frame_sub_view.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_instant_event_sub_view.html63
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_instant_event_sub_view_test.html42
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_instance_sub_view.html129
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_instance_sub_view_test.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_snapshot_sub_view.html142
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_snapshot_sub_view_test.html32
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_power_sample_sub_view.html122
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_power_sample_sub_view_test.html42
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_sample_sub_view.html110
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_sample_sub_view_test.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view_test.html80
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view.html186
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view_test.html92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/single_user_expectation_sub_view.html91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/stack_frame.html81
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/stack_frame_test.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_test.html38
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_view.html195
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_view_test.html205
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/stub_analysis_table.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/user_expectation_related_samples_table.html91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/analysis/user_expectation_related_samples_table_test.html64
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/annotations/annotation_view.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/annotations/annotation_view_test.html69
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/annotations/comment_box_annotation_view.html92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/annotations/rect_annotation_view.html57
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/annotations/x_marker_annotation_view.html42
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/animation.html79
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/animation_controller.html144
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/animation_controller_test.html166
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/bar_chart.html253
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/bar_chart_test.html195
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/base.html18
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/box_chart.html135
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/box_chart_test.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/camera.html350
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html59
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/chart_base.html453
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/chart_base_2d.html571
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/chart_base_2d_brushable_x.html90
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/chart_legend_key.html124
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/checkbox.html105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_picker.html109
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_picker_test.html135
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_test.html66
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/color_legend.html82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/color_legend_test.html122
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/column_chart.html427
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/column_chart_test.html276
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/constants.html20
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children.html110
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html95
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/d3.html9
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/d3_postload.js8
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/d3_preload.js11
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/deep_utils.html91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/deep_utils_test.html70
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers.html390
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html169
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/drag_handle.html185
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/drag_handle_test.html128
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/draw_helpers.html415
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/dropdown.html103
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html81
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/elided_cache.html113
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/event_presenter.html100
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/event_presenter_test.html63
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/fast_rect_renderer.html147
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/favicons.html27
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/file.html36
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table.html229
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table_groupby_picker.html258
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table_groupby_picker_test.html55
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/heading.html139
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/hot_key.html68
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller.html310
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html139
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/info_bar.html79
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group.html68
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_test.html47
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/line_chart.html98
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/line_chart_test.html180
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/list_view.html183
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/list_view_test.html67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_icon.html115
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_icon_test.html41
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_selector.html577
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_selector_test.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/mouse_modes.html98
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/mouse_tracker.html117
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/name_bar_chart.html84
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/name_bar_chart_test.html127
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/name_column_chart.html87
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/name_column_chart_test.html119
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/name_line_chart.html63
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/name_line_chart_test.html113
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/overlay.html351
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/overlay_test.html118
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/polymer_postload.html13
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/polymer_preload.html16
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/quad_stack_view.html688
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/radio_picker.html150
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/radio_picker_test.html122
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/scatter_chart.html110
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/scatter_chart_test.html67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/tab_view.html273
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html160
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/table.html1808
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/table_header_cell.html94
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html2115
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/timing_tool.html327
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/timing_tool_test.html78
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/toolbar_button.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/toolbar_button_test.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/ui.html172
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/ui_state.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/ui_state_test.html100
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/ui_test.html246
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/utils.html83
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html77
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/brushing_state.html280
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/brushing_state_controller.html317
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/brushing_state_controller_test.html204
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/brushing_state_test.html122
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/about_tracing.html26
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/common.css25
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/devtools_stream.html99
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_connection.html115
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_tracing_controller_client.html216
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_tracing_controller_client_test.html396
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/mock_tracing_controller_client.html88
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html372
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html76
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller.html187
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html57
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog.html689
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html426
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/tracing_controller_client.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/xhr_based_tracing_controller_client.html115
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/cc.html14
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger.html451
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html134
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_list_item.html134
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_list_view.html60
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/images/input-event.pngbin0 -> 3344 bytes
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/images/input-event.svg114
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_picker.html336
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view.html142
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html37
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html1200
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html113
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view.html165
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html55
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_debugger.html455
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_debugger_test.html32
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html458
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html505
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_list_view.html261
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_list_view_test.html56
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_view.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection.html140
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection_test.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view.html222
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html70
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/selection.html304
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/tile_view.html56
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/codesearch.html49
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/gpu.html10
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/images/checkerboard.pngbin0 -> 245 bytes
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/state_view.css15
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/state_view.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/layout_tree_sub_view.html229
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/chrome_config.html33
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/html_results.html123
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/main.html65
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/scalar_value.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comment_element.html84
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comments_side_panel.html185
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comments_side_panel_test.html71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/drive/drive_comment_provider.html99
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/drive/index.html463
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/full_config.html19
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/lean_config.html21
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/alerts_side_panel.html172
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/alerts_side_panel_test.html61
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/frame_data_side_panel.html347
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/frame_data_side_panel_test.html165
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel.html334
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel_test.html148
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats.html12
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.css15
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html451
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track_test.html116
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_snapshot_view.css28
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_snapshot_view.html84
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/systrace_config.html18
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html728
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table_test.html198
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/ic_stats_table.html181
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_gc_stats_thread_slice_sub_view.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_ic_stats_thread_slice_sub_view.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view_test.html87
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/runtime_call_stats_table.html197
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/runtime_call_stats_table_test.html236
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_gc_stats_thread_slice_sub_view.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_ic_stats_thread_slice_sub_view.html42
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_thread_slice_sub_view.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_thread_slice_sub_view_test.html114
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/extras/v8_config.html17
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/find_control.html177
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/find_control_test.html66
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/find_controller.html154
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/find_controller_test.html366
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/images/chrome-left.pngbin0 -> 14088 bytes
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/images/chrome-mid.pngbin0 -> 382 bytes
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/images/chrome-right.pngbin0 -> 3264 bytes
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/images/ui-states.pngbin0 -> 4097 bytes
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/metrics_debugger_app.html132
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/null_brushing_state_controller.html196
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/scripting_control.html200
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/scripting_control_test.html22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/file_size_stats_side_panel.html221
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/file_size_stats_side_panel_test.html36
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/metrics_side_panel.html222
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/metrics_side_panel_test.html50
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel.html49
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_container.html284
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_container_test.html98
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_registry.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_registry_test.html40
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform.html117
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_animations.html175
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_animations_test.html85
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_test.html40
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_interest_range.html249
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_track_view.html1179
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_track_view_test.html200
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html641
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_view_help_overlay.html245
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_view_help_overlay_test.html17
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_view_metadata_overlay.html63
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_view_metadata_overlay_test.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_view_test.html217
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_viewport.html442
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/timeline_viewport_test.html68
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/alert_track.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/alert_track_test.html76
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html179
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track_test.html328
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_point.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_point_test.html37
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series.html566
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_test.html331
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_y_axis.html213
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_y_axis_test.html313
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_track.html281
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_track_test.html454
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_transform.html92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_transform_test.html106
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/container_to_track_map.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/container_track.html138
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track.html79
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track_perf_test.html129
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track_test.html205
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_track.html140
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_track_test.html94
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_usage_track.html91
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_usage_track_test.html215
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/device_track.html90
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/device_track_test.html145
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container.css18
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container.html236
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container_perf_test.html137
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/event_to_track_map.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/frame_track.html71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/frame_track_test.html107
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/global_memory_dump_track.html105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/global_memory_dump_track_test.html62
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/interaction_track.html67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/interaction_track_test.html51
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/kernel_track.html82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/letter_dot_track.html251
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/letter_dot_track_test.html121
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_test_utils.html155
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_util.html253
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_util_test.html270
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_track.html67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_track_test.html99
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/model_track.html534
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/model_track_test.html178
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/multi_row_track.html240
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_group_track.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track.css8
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track.html294
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track_test.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/other_threads_track.html105
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/power_series_track.html81
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/power_series_track_test.html121
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/process_memory_dump_track.html70
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/process_memory_dump_track_test.html58
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/process_summary_track.html130
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/process_summary_track_test.html110
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track.html155
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track_base.css39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track_base.html313
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track.css8
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track.html249
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track_test.html412
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/sample_track.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/sample_track_test.html34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_group_track.html167
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_group_track_test.html299
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_track.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_track_test.html29
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/spacing_track.css7
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/spacing_track.html45
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/stacked_bars_track.html131
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track.css10
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track.html185
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track_test.html141
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/track.css33
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/track.html167
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/x_axis_track.html309
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/tracks/x_axis_track_test.html133
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/view_specific_brushing_state.html92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/ui/view_specific_brushing_state_test.html67
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/__init__.py0
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/chart_json_converter.html154
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/chart_json_converter_test.html401
-rwxr-xr-xchromium/third_party/catapult/tracing/tracing/value/convert_chart_json.py24
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/convert_chart_json_cmdline.html22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/csv_builder.html111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/csv_builder_test.html75
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/__init__.py3
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/add_reserved_diagnostics.py180
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/add_reserved_diagnostics_unittest.py237
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics.html16
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics.py42
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics_unittest.py27
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.html116
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py73
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown_test.html37
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown_unittest.py31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/collected_related_event_set.html97
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.html87
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range_unittest.py31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.html133
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py95
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_map.html177
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_map_test.html130
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_ref.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_ref.py22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_test.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_unittest.py15
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/discover_cmdline.html46
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/event_ref.html43
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.html145
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py82
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set_test.html64
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set_unittest.py100
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.html129
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set_test.html92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set_unittest.py29
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.html99
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py64
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map_unittest.py50
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py92
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html89
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/scalar.html48
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.html89
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py52
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py112
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter_unittest.py114
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py201
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py58
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram.html1478
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram.py1111
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_grouping.html204
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_grouping.py161
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_grouping_test.html163
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_grouping_unittest.py127
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html131
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_parameter_collector.html141
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_parameter_collector_test.html113
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_set.html374
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_set.py155
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_set_hierarchy.html157
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_set_test.html221
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py236
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_test.html809
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py674
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histograms_to_csv.py22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/histograms_to_csv_cmdline.html23
-rwxr-xr-xchromium/third_party/catapult/tracing/tracing/value/legacy_json_converter.py68
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/legacy_json_converter_unittest.py116
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/legacy_unit_info.html271
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/merge_histograms.py34
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/merge_histograms_cmdline.html84
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/merge_histograms_unittest.py31
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span.html350
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html149
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/collected_related_event_set_span.html40
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/collected_related_event_set_span_test.html56
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/date_range_span.html35
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/date_range_span_test.html30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_map_table.html125
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_map_table_test.html27
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html73
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span_behavior.html44
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span.html97
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html112
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram-set-view.md71
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html101
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls.html557
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_export.html63
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html300
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_location.html251
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_location_test.html290
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table.html459
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_cell.html396
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_name_cell.html361
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html299
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html1679
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view.html210
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view_state.html144
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view_test.html72
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span.html599
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html300
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/metrics_visualization.html353
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/metrics_visualization_test.html86
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/preferred_display_unit.html39
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/preferred_display_unit_test.html22
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/raster_visualization.html274
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/raster_visualization_test.html57
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span.html40
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html58
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller.html204
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html312
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_diagnostic_span.html32
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_diagnostic_span_test.html23
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_map_table.html89
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_map_table_test.html30
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span.html626
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html1027
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/timings.md78
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/unmergeable_diagnostic_set_span.html41
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/unmergeable_diagnostic_set_span_test.html40
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/visualizations_data_container.html410
-rw-r--r--chromium/third_party/catapult/tracing/tracing/value/ui/visualizations_data_container_test.html124
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/__init__.py7
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/check_common.py90
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/check_common_unittest.py29
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/check_gni.py29
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents.py66
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py24
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html72
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/html2trace.py106
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/merge_traces.py687
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py48
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py81
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py95
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/run_profile.py67
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/run_vinn_tests.py47
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/slim_trace.py112
-rwxr-xr-xchromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py102
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/trace2html.py128
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py84
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/tracing_dev_server_config.py57
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/update_gni.py123
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/update_gni_unittest.py37
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/vulcanize_histograms_viewer.py27
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer.py114
-rw-r--r--chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py30
-rw-r--r--chromium/third_party/catapult/tracing/tracing_examples/chrome_inspect_test_shell.html66
-rw-r--r--chromium/third_party/catapult/tracing/tracing_examples/deep_reports.html128
-rw-r--r--chromium/third_party/catapult/tracing/tracing_examples/metrics_debugger.html31
-rw-r--r--chromium/third_party/catapult/tracing/tracing_examples/skia_debugger.html174
-rw-r--r--chromium/third_party/catapult/tracing/tracing_examples/string_convert.js171
-rw-r--r--chromium/third_party/catapult/tracing/tracing_examples/trace_viewer.html184
-rw-r--r--chromium/third_party/catapult/tracing/tracing_project.py209
-rw-r--r--chromium/third_party/chromevox/LICENSE13
-rw-r--r--chromium/third_party/chromevox/OWNERS7
-rw-r--r--chromium/third_party/chromevox/README.chromium16
-rw-r--r--chromium/third_party/chromevox/chromevox/background/chrome_shared2.css102
-rw-r--r--chromium/third_party/chromevox/chromevox/background/options.css79
-rw-r--r--chromium/third_party/chromevox/chromevox/background/options_widgets.css298
-rw-r--r--chromium/third_party/chromevox/chromevox/injected/mathjax.js188
-rw-r--r--chromium/third_party/chromevox/chromevox/injected/mathjax_external_util.js481
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/LICENSE176
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/README.chromium20
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/depstree.py189
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/source.py118
-rwxr-xr-xchromium/third_party/chromevox/third_party/closure-library/closure/bin/build/treescan.py78
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/asserts/asserts.js316
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/base.js1706
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/debug/error.js54
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/dom/nodetype.js48
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/messageformat.js764
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/ordinalrules.js733
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/pluralrules.js1100
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/object/object.js637
-rw-r--r--chromium/third_party/chromevox/third_party/closure-library/closure/goog/string/string.js47
-rw-r--r--chromium/third_party/chromevox/third_party/sre/LICENSE177
-rw-r--r--chromium/third_party/chromevox/third_party/sre/METADATA18
-rw-r--r--chromium/third_party/chromevox/third_party/sre/OWNERS2
-rw-r--r--chromium/third_party/chromevox/third_party/sre/sre_browser.js1155
-rw-r--r--chromium/third_party/cld_3/LICENSE203
-rw-r--r--chromium/third_party/cld_3/OWNERS2
-rw-r--r--chromium/third_party/cld_3/README.chromium12
-rw-r--r--chromium/third_party/cld_3/src/CONTRIBUTING.md26
-rw-r--r--chromium/third_party/cld_3/src/LICENSE203
-rw-r--r--chromium/third_party/cld_3/src/README.md73
-rw-r--r--chromium/third_party/cld_3/src/model.pngbin39276 -> 0 bytes
-rw-r--r--chromium/third_party/cld_3/src/src/DEPS4
-rw-r--r--chromium/third_party/cld_3/src/src/base.cc36
-rw-r--r--chromium/third_party/cld_3/src/src/base.h106
-rw-r--r--chromium/third_party/cld_3/src/src/casts.h98
-rw-r--r--chromium/third_party/cld_3/src/src/embedding_feature_extractor.cc51
-rw-r--r--chromium/third_party/cld_3/src/src/embedding_feature_extractor.h182
-rw-r--r--chromium/third_party/cld_3/src/src/embedding_network.cc196
-rw-r--r--chromium/third_party/cld_3/src/src/embedding_network.h186
-rw-r--r--chromium/third_party/cld_3/src/src/embedding_network_params.h285
-rw-r--r--chromium/third_party/cld_3/src/src/feature_extractor.cc137
-rw-r--r--chromium/third_party/cld_3/src/src/feature_extractor.h633
-rw-r--r--chromium/third_party/cld_3/src/src/feature_extractor.proto50
-rw-r--r--chromium/third_party/cld_3/src/src/feature_types.cc72
-rw-r--r--chromium/third_party/cld_3/src/src/feature_types.h158
-rw-r--r--chromium/third_party/cld_3/src/src/float16.h58
-rw-r--r--chromium/third_party/cld_3/src/src/fml_parser.cc308
-rw-r--r--chromium/third_party/cld_3/src/src/fml_parser.h123
-rw-r--r--chromium/third_party/cld_3/src/src/lang_id_nn_params.cc57449
-rwxr-xr-xchromium/third_party/cld_3/src/src/lang_id_nn_params.h178
-rw-r--r--chromium/third_party/cld_3/src/src/language_identifier_features.cc165
-rw-r--r--chromium/third_party/cld_3/src/src/language_identifier_features.h116
-rw-r--r--chromium/third_party/cld_3/src/src/language_identifier_features_test.cc260
-rw-r--r--chromium/third_party/cld_3/src/src/language_identifier_main.cc54
-rw-r--r--chromium/third_party/cld_3/src/src/nnet_lang_id_test.cc226
-rw-r--r--chromium/third_party/cld_3/src/src/nnet_lang_id_test_data.cc529
-rw-r--r--chromium/third_party/cld_3/src/src/nnet_lang_id_test_data.h117
-rw-r--r--chromium/third_party/cld_3/src/src/nnet_language_identifier.cc380
-rw-r--r--chromium/third_party/cld_3/src/src/nnet_language_identifier.h175
-rw-r--r--chromium/third_party/cld_3/src/src/registry.cc28
-rw-r--r--chromium/third_party/cld_3/src/src/registry.h242
-rw-r--r--chromium/third_party/cld_3/src/src/relevant_script_feature.cc89
-rw-r--r--chromium/third_party/cld_3/src/src/relevant_script_feature.h49
-rw-r--r--chromium/third_party/cld_3/src/src/relevant_script_feature_test.cc259
-rw-r--r--chromium/third_party/cld_3/src/src/script_detector.h156
-rw-r--r--chromium/third_party/cld_3/src/src/script_detector_test.cc161
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/README.md11
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/fixunicodevalue.cc55
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/fixunicodevalue.h69
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/generated_entities.cc296
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/generated_ulscript.cc678
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/generated_ulscript.h142
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/getonescriptspan.cc1109
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/getonescriptspan.h124
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/getonescriptspan_test.cc135
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/integral_types.h37
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/offsetmap.cc478
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/offsetmap.h168
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/port.h143
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/stringpiece.h81
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/text_processing.cc245
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/text_processing.h30
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/utf8acceptinterchange.h486
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/utf8prop_lettermarkscriptnum.h1631
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/utf8repl_lettermarklower.h758
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/utf8scannot_lettermarkspecial.h1455
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/utf8statetable.cc1358
-rw-r--r--chromium/third_party/cld_3/src/src/script_span/utf8statetable.h285
-rw-r--r--chromium/third_party/cld_3/src/src/sentence.proto77
-rw-r--r--chromium/third_party/cld_3/src/src/sentence_features.cc29
-rw-r--r--chromium/third_party/cld_3/src/src/sentence_features.h35
-rw-r--r--chromium/third_party/cld_3/src/src/simple_adder.h72
-rw-r--r--chromium/third_party/cld_3/src/src/task_context.cc161
-rw-r--r--chromium/third_party/cld_3/src/src/task_context.h81
-rw-r--r--chromium/third_party/cld_3/src/src/task_context_params.cc74
-rw-r--r--chromium/third_party/cld_3/src/src/task_context_params.h54
-rw-r--r--chromium/third_party/cld_3/src/src/task_spec.proto98
-rw-r--r--chromium/third_party/cld_3/src/src/unicodetext.cc96
-rw-r--r--chromium/third_party/cld_3/src/src/unicodetext.h144
-rw-r--r--chromium/third_party/cld_3/src/src/utils.cc241
-rw-r--r--chromium/third_party/cld_3/src/src/utils.h144
-rw-r--r--chromium/third_party/cld_3/src/src/workspace.cc64
-rw-r--r--chromium/third_party/cld_3/src/src/workspace.h177
-rw-r--r--chromium/third_party/expat/fuzz/OWNERS2
-rw-r--r--chromium/third_party/expat/fuzz/expat_xml_parse_fuzzer.cc30
-rw-r--r--chromium/third_party/feed/README.chromium2
-rw-r--r--chromium/third_party/ffmpeg/libavformat/isom.h1
-rw-r--r--chromium/third_party/ffmpeg/libavformat/mov.c24
-rw-r--r--chromium/third_party/google_android_play_core/LICENSE147
-rw-r--r--chromium/third_party/google_android_play_core/OWNERS2
-rw-r--r--chromium/third_party/google_android_play_core/README.chromium14
-rw-r--r--chromium/third_party/google_android_play_core/cipd.yaml10
-rw-r--r--chromium/third_party/google_android_play_core/com_google_android_play_core.info13
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/harfbuzz_fuzzer.cc46
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/0509e80afb379d16560e9e47bdd7d888bebdebc6.ttfbin61 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/051d92f8bc6ff724511b296c27623f824de256e9.ttfbin2028 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/07f054357ff8638bac3711b422a1e31180bba863.ttfbin848 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/191826b9643e3f124d865d617ae609db6a2ce203.ttfbin2140 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttfbin64 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c04a16f32a39c26c851b7fc014d2e8d298ba2b8.ttfbin820 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttfbin316 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c2fb74c1b2aa173262734c1f616148f1648cfd6.ttfbin4064 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/205edd09bd3d141cc9580f650109556cc28b22cb.ttfbin1966 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/226bc2deab3846f1a682085f70c67d0421014144.ttfbin2828 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/270b89df543a7e48e206a2d830c0e10e5265c630.ttfbin3428 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttfbin2520 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/3511ff5c1647150595846ac414c595cccac34f18.ttfbin1483 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/37033cc5cf37bb223d7355153016b6ccece93b28.ttfbin2780 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/375d6ae32a3cbe52fbf81a4e5777e3377675d5a3.ttfbin1024 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/43979b90b2dd929723cf4fe1715990bcb9c9a56b.ttfbin1804 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/43ef465752be9af900745f72fe29cb853a1401a5.ttfbin4272 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/45855bc8d46332b39c4ab9e2ee1a26b1f896da6b.ttfbin1088 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/49c9f7485c1392fa09a1b801bc2ffea79275f22e.ttfbin1496 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttfbin1320 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/5028afb650b1bb718ed2131e872fbcce57828fff.ttfbin4720 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/56cfd0e18d07f41c38e9598545a6d369127fc6f9.ttfbin1412 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/57a9d9f83020155cbb1d2be1f43d82388cbecc88.ttfbin2272 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8.ttfbin61 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/641bd9db850193064d17575053ae2bf8ec149ddc.ttfbin305 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/6466d38c62e73a39202435a4f73bf5d6acbb73c0.ttfbin824 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/6ff0fbead4462d9f229167b4e6839eceb8465058.ttfbin1148 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttfbin3868 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/757ebd573617a24aa9dfbf0b885c54875c6fe06b.ttfbin1804 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7a37dc4d5bf018456aea291cee06daf004c0221c.ttfbin1080 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7e14e7883ed152baa158b80e207b66114c823a8b.ttfbin1644 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7ef276fc886ea502a03b9b0e5c8b547d5dc2b61c.ttfbin784 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8099955657a54e9ee38a6ba1d6f950ce58e3cc25.ttfbin1024 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttfbin3428 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8240789f6d12d4cfc4b5e8e6f246c3701bcf861f.ttfbin633 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8454d22037f892e76614e1645d066689a0200e61.ttfbin6068 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttfbin3428 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a34a7b00f22ffb5fd7eef6933b81c7e71bc2cdfb.ttfbin3700 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a919b33197965846f21074b24e30250d67277bce.ttfbin12560 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a98e908e2ed21b22228ea59ebcc0f05034c86f2e.ttfbin1016 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2.ttfbin1804 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/bb0c53752e85c3d28973ebc913287b8987d3dfe8.ttfbin976 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/bb9473d2403488714043bcfb946c9f78b86ad627.ttfbin3440 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/c4e48b0886ef460f532fb49f00047ec92c432ec0.ttfbin2512 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/cc5f3d2d717fb6bd4dfae1c16d48a2cb8e12233b.ttfbin1448 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/d629e7fedc0b350222d7987345fe61613fa3929a.ttfbin1768 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/df768b9c257e0c9c35786c47cae15c46571d56be.ttfbin6332 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/e207635780b42f898d58654b65098763e340f5c7.ttfbin3000 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttfbin2748 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttfbin16736 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f499fbc23865022234775c43503bba2e63978fe1.ttfbin3564 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f518eb6f6b5eec2946c9fbbbde44e45d46f5e2ac.ttfbin1356 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fab39d60d758cb586db5a504f218442cd1395725.ttfbin1894 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fbb6c84c9e1fe0c39e152fbe845e51fd81f6748e.ttfbin2616 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fcdcffbdf1c4c97c05308d7600e4c283eb47dbca.ttfbin1344 -> 0 bytes
-rw-r--r--chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/ffa0f5d2d9025486d8469d8b1fdd983e7632499b.ttfbin1448 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/DEPS3
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/02a25363e79f11115132055fb880773b325f6aefbin2464 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/0883e336027e9e21911a277a9d8fa4c1b9490eddbin36 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/0c70b309d63d09ac033b8c80abff19457c93772abin8288 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/0d78b77395c09c9db65dc76b276944154e9cf91bbin65 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/0df4db3e331d781458ed7f5e5326812ba22a980fbin16736 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/142541422e926a0e54acfe3c00292d7ae269c9f5bin33 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/1f2216ed82922b16e3cf2194fbe320c1d0f31831bin4768 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/2051fd638bbbd568fe55066340f4827f1b60014ebin33 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/28ed3a797da3c48c309a4ef792147f3c56cfec401
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/29a708fe3eea419ee8fa22f66fa60e60ccae4398bin1010 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/2fb325875fb0367f26affb28f1b0fbf8ead43b48bin33 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/3a9cb078ca19ad92faa8695bf15bb6138386a713bin2400 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/3d922153192cbf2238450647127e88ec294576cebin60036 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/9bee55d2991f5c3b673c541152afa6b1d1c6521cbin2528 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/9deab6c08f36bbebfd65ee52fa031d8834ad886ebin33 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/b56dab34aac0c0f9863cd5e7a17bebab99389d9dbin11744 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/bbf0c58cdbc56d84118b2c6ccda1521497d07deabin33 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/bd81796eafc329a45ea7d76ab6b85a2f27334b1ebin33 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/cf670ba4a6e5d9871e334f67b137cec5efe3785bbin16544 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/e168bd974f8f0bc25219207694e3a1e9d53458c3bin7072 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/e8576db25f36cfc9c26570f098fd8c83cd92a68abin16672 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/edb7834459dd9eb4b19e48ed1c9ba73d20c4c4e8bin16856 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/en-US-7-1.bdicbin446149 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/en-US-8-0.bdicbin446642 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/f95048cdc0fc231dd712bad106578a9eeecd869bbin16608 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_corpus/fda69541054125551c41ab3e591e0482405ca2dcbin1266 -> 0 bytes
-rw-r--r--chromium/third_party/hunspell/fuzz/bdict_fuzzer.cc14
-rw-r--r--chromium/third_party/hunspell/fuzz/hunspell.dict8296
-rw-r--r--chromium/third_party/hunspell/fuzz/hunspell_fuzzer.cc35
-rw-r--r--chromium/third_party/hunspell/fuzz/hunspell_fuzzer_hunspell_dictionary.h37212
-rw-r--r--chromium/third_party/libFuzzer/LICENSE.TXT70
-rw-r--r--chromium/third_party/libFuzzer/OWNERS5
-rw-r--r--chromium/third_party/libFuzzer/README.chromium13
-rw-r--r--chromium/third_party/libFuzzer/src/CMakeLists.txt147
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerBuiltins.h36
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerBuiltinsMsvc.h59
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerCommand.h179
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerCorpus.h315
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerCrossOver.cpp52
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.cpp91
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.h56
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerDefs.h201
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerDictionary.h119
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerDriver.cpp777
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerExtFunctions.def51
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerExtFunctions.h35
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerExtFunctionsDlsym.cpp52
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWeak.cpp55
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWindows.cpp83
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerExtraCounters.cpp42
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerFlags.def164
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerIO.cpp129
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerIO.h87
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerIOPosix.cpp147
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerIOWindows.cpp343
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerInterface.h71
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerInternal.h179
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerLoop.cpp905
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerMain.cpp21
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerMerge.cpp390
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerMerge.h80
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerMutate.cpp562
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerMutate.h157
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerOptions.h77
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerRandom.h34
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerSHA1.cpp222
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerSHA1.h33
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerShmem.h69
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerShmemFuchsia.cpp38
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerShmemPosix.cpp108
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerShmemWindows.cpp64
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerTracePC.cpp719
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerTracePC.h310
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerUtil.cpp232
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerUtil.h93
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerUtilDarwin.cpp162
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerUtilFuchsia.cpp473
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerUtilLinux.cpp27
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerUtilPosix.cpp152
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerUtilWindows.cpp196
-rw-r--r--chromium/third_party/libFuzzer/src/FuzzerValueBitMap.h73
-rw-r--r--chromium/third_party/libFuzzer/src/README.txt1
-rw-r--r--chromium/third_party/libFuzzer/src/afl/afl_driver.cpp378
-rwxr-xr-xchromium/third_party/libFuzzer/src/build.sh11
-rw-r--r--chromium/third_party/libFuzzer/src/dataflow/DataFlow.cpp217
-rwxr-xr-xchromium/third_party/libFuzzer/src/scripts/collect_data_flow.py79
-rwxr-xr-xchromium/third_party/libFuzzer/src/scripts/merge_data_flow.py36
-rwxr-xr-xchromium/third_party/libFuzzer/src/scripts/unbalanced_allocs.py93
-rw-r--r--chromium/third_party/libFuzzer/src/standalone/StandaloneFuzzTargetMain.c41
-rw-r--r--chromium/third_party/libaddressinput/chromium/resources/address_input_strings_te.xtb2
-rw-r--r--chromium/third_party/libaddressinput/fuzz/data/fmt.dict76
-rw-r--r--chromium/third_party/libaddressinput/fuzz/data/require.dict8
-rw-r--r--chromium/third_party/libaddressinput/fuzz/parse_address_fields_fuzzer.cc15
-rw-r--r--chromium/third_party/libaddressinput/fuzz/parse_format_rule_fuzzer.cc16
-rw-r--r--chromium/third_party/ots/fuzz/ots_fuzzer.cc19
-rw-r--r--chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.cpp3
-rw-r--r--chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.h2
-rw-r--r--chromium/third_party/pdfium/core/fpdftext/cpdf_textpage.cpp7
-rw-r--r--chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.cpp7
-rw-r--r--chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.h6
-rw-r--r--chromium/third_party/pdfium/core/fxge/cfx_renderdevice.cpp18
-rw-r--r--chromium/third_party/re2/src/re2/fuzzing/re2_fuzzer.cc168
-rw-r--r--chromium/third_party/skia/fuzz/Fuzz.cpp50
-rw-r--r--chromium/third_party/skia/fuzz/Fuzz.h120
-rw-r--r--chromium/third_party/skia/fuzz/FuzzCanvas.cpp1731
-rw-r--r--chromium/third_party/skia/fuzz/FuzzCommon.cpp341
-rw-r--r--chromium/third_party/skia/fuzz/FuzzCommon.h29
-rw-r--r--chromium/third_party/skia/fuzz/FuzzDrawFunctions.cpp346
-rw-r--r--chromium/third_party/skia/fuzz/FuzzEncoders.cpp118
-rw-r--r--chromium/third_party/skia/fuzz/FuzzGradients.cpp274
-rw-r--r--chromium/third_party/skia/fuzz/FuzzMain.cpp725
-rw-r--r--chromium/third_party/skia/fuzz/FuzzParsePath.cpp128
-rw-r--r--chromium/third_party/skia/fuzz/FuzzPathMeasure.cpp35
-rw-r--r--chromium/third_party/skia/fuzz/FuzzPathop.cpp202
-rw-r--r--chromium/third_party/skia/fuzz/FuzzPolyUtils.cpp40
-rw-r--r--chromium/third_party/skia/fuzz/FuzzRegionOp.cpp18
-rwxr-xr-xchromium/third_party/skia/fuzz/coverage83
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzAPIImageFilter.cpp16
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzAndroidCodec.cpp63
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzAnimatedImage.cpp45
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzDrawFunctions.cpp16
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzGradients.cpp17
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzImage.cpp37
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzImageFilterDeserialize.cpp49
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzIncrementalImage.cpp54
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzJPEGEncoder.cpp16
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzJSON.cpp24
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzMockGPUCanvas.cpp28
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzNullCanvas.cpp19
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzPNGEncoder.cpp16
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathDeserialize.cpp46
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathMeasure.cpp16
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathop.cpp16
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzPolyUtils.cpp16
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzRasterN32Canvas.cpp19
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp43
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzRegionSetPath.cpp46
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzTextBlobDeserialize.cpp37
-rw-r--r--chromium/third_party/skia/fuzz/oss_fuzz/FuzzWEBPEncoder.cpp16
-rw-r--r--chromium/third_party/skia/gm/typeface.cpp31
-rw-r--r--chromium/third_party/skia/modules/skottie/fuzz/FuzzSkottieJSON.cpp30
-rw-r--r--chromium/third_party/skia/src/ports/SkFontHost_mac.cpp24
-rw-r--r--chromium/third_party/sqlite/amalgamation/rename_exports.h642
-rw-r--r--chromium/third_party/sqlite/amalgamation/shell/shell.c637
-rw-r--r--chromium/third_party/sqlite/amalgamation/sqlite3.c8014
-rw-r--r--chromium/third_party/sqlite/amalgamation/sqlite3.h73
-rw-r--r--chromium/third_party/sqlite/fuzz/DEPS1
-rw-r--r--chromium/third_party/sqlite/fuzz/disabled_queries_parser.cc30
-rw-r--r--chromium/third_party/sqlite/fuzz/disabled_queries_parser.h16
-rw-r--r--chromium/third_party/sqlite/fuzz/icu_codes.proto189
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries0bin20189 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries1bin5569 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries10bin14720 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries11bin32275 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries12bin36953 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries13bin32246 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries14bin5439 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries15bin34799 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries16bin5647 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries17bin26498 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries18bin18939 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries19bin17233 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries2bin20274 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries3bin18276 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries4bin12855 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries5bin7890 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries6bin28166 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries7bin13183 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries8bin6235 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries9bin3768 -> 0 bytes
-rw-r--r--chromium/third_party/sqlite/fuzz/sql.dict909
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_expr_fuzzer.cc31
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_fuzzer.cc58
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_generate_corpus.cc969
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_multithreaded_fuzzer.cc91
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_printf_fuzzer.cc31
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_queries.proto23
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_query_grammar.proto1663
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_query_proto_to_string.cc2757
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_query_proto_to_string.h30
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_run_queries.cc172
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_run_queries.h18
-rw-r--r--chromium/third_party/sqlite/fuzz/sql_strftime_fuzzer.cc31
-rw-r--r--chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch8
-rw-r--r--chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch13
-rw-r--r--chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch10
-rw-r--r--chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch12
-rw-r--r--chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch2
-rw-r--r--chromium/third_party/sqlite/patches/0006-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch32
-rw-r--r--chromium/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch25
-rw-r--r--chromium/third_party/sqlite/patches/0007-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch43
-rw-r--r--chromium/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch27
-rw-r--r--chromium/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch38
-rw-r--r--chromium/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch29
-rw-r--r--chromium/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch42
-rw-r--r--chromium/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch50
-rw-r--r--chromium/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch29
-rw-r--r--chromium/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch33
-rw-r--r--chromium/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch40
-rw-r--r--chromium/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch47
-rw-r--r--chromium/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch33
-rw-r--r--chromium/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch37
-rw-r--r--chromium/third_party/sqlite/patches/0018-Fix-a-segfault-in-fts3-prompted-by-a-corrupted-datab.patch29
-rw-r--r--chromium/third_party/sqlite/patches/0019-Prevent-integer-overflow-from-leading-to-buffer-over.patch31
-rw-r--r--chromium/third_party/sqlite/patches/0020-Add-extra-tests-for-database-corruption-inside-defra.patch57
-rw-r--r--chromium/third_party/sqlite/patches/0021-Fix-an-off-by-one-error-on-a-Goto-in-the-code-genera.patch29
-rw-r--r--chromium/third_party/sqlite/patches/0022-Fix-overread-on-corrupted-btree-key.patch37
-rw-r--r--chromium/third_party/sqlite/patches/0023-Avoid-buffer-overreads-on-corrupted-database-files.patch31
-rw-r--r--chromium/third_party/sqlite/patches/0024-Fix-integer-overflow-while-running-PRAGMA-integrity_.patch38
-rw-r--r--chromium/third_party/sqlite/patches/0025-Improved-corruption-handling-while-balancing-pages.patch120
-rw-r--r--chromium/third_party/sqlite/patches/0026-Avoid-reading-off-the-front-of-a-page-buffer-when-ba.patch38
-rw-r--r--chromium/third_party/sqlite/patches/0027-Fix-MSAN-error-in-sqlite3VdbeRecordUnpack-on-a-corru.patch34
-rw-r--r--chromium/third_party/sqlite/patches/0028-Fix-deleting-a-B-tree-entry-in-a-corrupt-database.patch27
-rw-r--r--chromium/third_party/sqlite/patches/0029-Fix-sorting-results-with-SRT_EphemTab-and-a-LIMIT-cl.patch42
-rw-r--r--chromium/third_party/sqlite/patches/0030-Fix-detection-of-orphaned-and-malformed-autoindexes.patch40
-rw-r--r--chromium/third_party/sqlite/patches/0031-Fix-potential-buffer-overread.patch41
-rw-r--r--chromium/third_party/sqlite/patches/0032-Fix-handling-negative-number-of-pages-database-field.patch69
-rw-r--r--chromium/third_party/sqlite/patches/0033-Fix-corner-case-in-inserting-null-into-integer-prima.patch42
-rw-r--r--chromium/third_party/sqlite/patches/0034-Fix-insert-infinite-recursion-on-some-corrupted-data.patch30
-rw-r--r--chromium/third_party/sqlite/patches/0035-Fix-null-pointer-dereference-in-sqlite3ExprCompare.patch32
-rw-r--r--chromium/third_party/sqlite/patches/0036-Fix-NEVER-that-is-sometimes-true.patch29
-rw-r--r--chromium/third_party/sqlite/patches/0037-Initialize-extra-bytes-allocated-for-saved-cursor-po.patch28
-rw-r--r--chromium/third_party/sqlite/patches/0038-Fix-leaks-caused-by-circular-references-in-vtable-sh.patch246
-rw-r--r--chromium/third_party/sqlite/patches/0039-Fix-overly-large-malloc-on-btree-corruption.patch28
-rw-r--r--chromium/third_party/sqlite/patches/0040-Fix-null-pointer-access-on-corrupted-index-key.patch44
-rw-r--r--chromium/third_party/sqlite/src/Makefile.in41
-rw-r--r--chromium/third_party/sqlite/src/Makefile.msc25
-rw-r--r--chromium/third_party/sqlite/src/VERSION2
-rw-r--r--chromium/third_party/sqlite/src/autoconf/Makefile.msc2
-rwxr-xr-xchromium/third_party/sqlite/src/configure18
-rw-r--r--chromium/third_party/sqlite/src/ext/expert/expert1.test6
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3.c126
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3Int.h14
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c10
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_expr.c15
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_hash.c4
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_icu.c4
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_snippet.c64
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_term.c6
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_test.c31
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_unicode.c17
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_unicode2.c71
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_write.c42
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl53
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/unicode/parseunicode.tcl31
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5.h20
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5Int.h28
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c20
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_buffer.c12
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_config.c8
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c55
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c22
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_index.c237
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_main.c302
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c20
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_test_mi.c4
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c6
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c37
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c82
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_varint.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c69
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/amatch.c10
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/closure.c6
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/csv.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/dbdump.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/eval.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/fileio.c45
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/fuzzer.c16
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/json1.c6
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/memstat.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/memtrace.c108
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/mmapwarm.c1
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/nextchar.c4
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/percentile.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/prefixes.c319
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/regexp.c6
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/unionvtab.c8
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/vfslog.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/zipfile.c24
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu_common.tcl13
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test27
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbuvacuum3.test63
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c13
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h4
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/test_rbu.c1
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/geopoly.c95
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtree.c128
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtree1.test14
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtree6.test13
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtreecirc.test66
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtreefuzz001.test777
-rw-r--r--chromium/third_party/sqlite/src/ext/session/changeset.c6
-rw-r--r--chromium/third_party/sqlite/src/ext/session/changesetfuzz.c15
-rw-r--r--chromium/third_party/sqlite/src/ext/session/session_speed_test.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionwor.test74
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sqlite3session.c36
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sqlite3session.h2
-rw-r--r--chromium/third_party/sqlite/src/main.mk31
-rw-r--r--chromium/third_party/sqlite/src/manifest423
-rw-r--r--chromium/third_party/sqlite/src/manifest.uuid2
-rw-r--r--chromium/third_party/sqlite/src/src/alter.c56
-rw-r--r--chromium/third_party/sqlite/src/src/analyze.c2
-rw-r--r--chromium/third_party/sqlite/src/src/attach.c15
-rw-r--r--chromium/third_party/sqlite/src/src/btree.c304
-rw-r--r--chromium/third_party/sqlite/src/src/btree.h1
-rw-r--r--chromium/third_party/sqlite/src/src/btreeInt.h13
-rw-r--r--chromium/third_party/sqlite/src/src/build.c86
-rw-r--r--chromium/third_party/sqlite/src/src/callback.c21
-rw-r--r--chromium/third_party/sqlite/src/src/dbstat.c10
-rw-r--r--chromium/third_party/sqlite/src/src/delete.c8
-rw-r--r--chromium/third_party/sqlite/src/src/expr.c648
-rw-r--r--chromium/third_party/sqlite/src/src/fkey.c9
-rw-r--r--chromium/third_party/sqlite/src/src/func.c10
-rw-r--r--chromium/third_party/sqlite/src/src/global.c12
-rw-r--r--chromium/third_party/sqlite/src/src/hash.c56
-rw-r--r--chromium/third_party/sqlite/src/src/insert.c46
-rw-r--r--chromium/third_party/sqlite/src/src/legacy.c5
-rw-r--r--chromium/third_party/sqlite/src/src/loadext.c2
-rw-r--r--chromium/third_party/sqlite/src/src/main.c68
-rw-r--r--chromium/third_party/sqlite/src/src/memdb.c46
-rw-r--r--chromium/third_party/sqlite/src/src/pager.c5
-rw-r--r--chromium/third_party/sqlite/src/src/parse.y43
-rw-r--r--chromium/third_party/sqlite/src/src/pcache1.c24
-rw-r--r--chromium/third_party/sqlite/src/src/pragma.c25
-rw-r--r--chromium/third_party/sqlite/src/src/pragma.h13
-rw-r--r--chromium/third_party/sqlite/src/src/prepare.c305
-rw-r--r--chromium/third_party/sqlite/src/src/printf.c199
-rw-r--r--chromium/third_party/sqlite/src/src/resolve.c127
-rw-r--r--chromium/third_party/sqlite/src/src/select.c88
-rw-r--r--chromium/third_party/sqlite/src/src/shell.c.in458
-rw-r--r--chromium/third_party/sqlite/src/src/sqlite.h.in45
-rw-r--r--chromium/third_party/sqlite/src/src/sqliteInt.h68
-rw-r--r--chromium/third_party/sqlite/src/src/tclsqlite.c53
-rw-r--r--chromium/third_party/sqlite/src/src/test1.c80
-rw-r--r--chromium/third_party/sqlite/src/src/test_journal.c2
-rw-r--r--chromium/third_party/sqlite/src/src/test_vfs.c125
-rw-r--r--chromium/third_party/sqlite/src/src/tokenize.c211
-rw-r--r--chromium/third_party/sqlite/src/src/treeview.c3
-rw-r--r--chromium/third_party/sqlite/src/src/trigger.c4
-rw-r--r--chromium/third_party/sqlite/src/src/update.c11
-rw-r--r--chromium/third_party/sqlite/src/src/util.c7
-rw-r--r--chromium/third_party/sqlite/src/src/vacuum.c72
-rw-r--r--chromium/third_party/sqlite/src/src/vdbe.c124
-rw-r--r--chromium/third_party/sqlite/src/src/vdbe.h21
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeInt.h30
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeapi.c38
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeaux.c188
-rw-r--r--chromium/third_party/sqlite/src/src/vdbemem.c13
-rw-r--r--chromium/third_party/sqlite/src/src/vtab.c2
-rw-r--r--chromium/third_party/sqlite/src/src/walker.c31
-rw-r--r--chromium/third_party/sqlite/src/src/where.c65
-rw-r--r--chromium/third_party/sqlite/src/src/whereInt.h3
-rw-r--r--chromium/third_party/sqlite/src/src/wherecode.c48
-rw-r--r--chromium/third_party/sqlite/src/src/whereexpr.c6
-rw-r--r--chromium/third_party/sqlite/src/src/window.c20
-rw-r--r--chromium/third_party/sqlite/src/tool/dbtotxt.c146
-rw-r--r--chromium/third_party/sqlite/src/tool/dbtotxt.md56
-rw-r--r--chromium/third_party/sqlite/src/tool/index_usage.c233
-rw-r--r--chromium/third_party/sqlite/src/tool/lemon.c12
-rw-r--r--chromium/third_party/sqlite/src/tool/lempar.c26
-rw-r--r--chromium/third_party/sqlite/src/tool/mkpragmatab.tcl5
-rw-r--r--chromium/third_party/webrtc/rtc_base/network.cc14
-rw-r--r--chromium/third_party/webrtc/rtc_base/network.h42
-rw-r--r--chromium/tools/binary_size/libsupersize/apkanalyzer.py23
-rw-r--r--chromium/tools/binary_size/libsupersize/archive.py179
-rwxr-xr-xchromium/tools/binary_size/libsupersize/integration_test.py67
-rw-r--r--chromium/tools/cfi/blacklist.txt5
-rw-r--r--chromium/tools/gn/README.chromium.md (renamed from chromium/tools/gn/README.md)0
-rwxr-xr-xchromium/tools/gn/bootstrap/bootstrap.py40
-rw-r--r--chromium/tools/gn/bootstrap/libc++.ninja71
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/DEPS2
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc1749
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/fuzzer.h91
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/fuzzer_main.cc250
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/generator.cc119
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/generator.h43
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/mutator.cc120
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/mutator.h47
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/rand_util.cc17
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/rand_util.h45
-rw-r--r--chromium/tools/metrics/actions/actions.xml25
-rw-r--r--chromium/tools/metrics/histograms/enums.xml70
-rw-r--r--chromium/tools/metrics/histograms/histograms.xml116
-rw-r--r--chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h6
-rw-r--r--chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm26
-rw-r--r--chromium/ui/accessibility/ax_tree_serializer.h18
-rw-r--r--chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_te.xtb6
-rw-r--r--chromium/ui/base/ui_base_features.cc4
-rw-r--r--chromium/ui/base/x/x11_display_util.cc78
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info.cc21
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info_unittest.cc28
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_test_util.cc60
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_test_util.h2
-rw-r--r--chromium/ui/gl/gl_context_egl.cc24
-rw-r--r--chromium/ui/gl/gl_context_egl.h9
-rw-r--r--chromium/ui/gl/init/gl_factory_mac.cc4
-rw-r--r--chromium/ui/native_theme/common_theme.cc1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc4
-rw-r--r--chromium/ui/ozone/public/ozone_switches.cc4
-rw-r--r--chromium/ui/ozone/public/ozone_switches.h2
-rw-r--r--chromium/ui/shell_dialogs/execute_select_file_win.cc8
-rw-r--r--chromium/ui/strings/translations/ui_strings_ja.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_kn.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ta.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_te.xtb14
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.mm16
-rw-r--r--chromium/ui/views/event_monitor_aura.cc45
-rw-r--r--chromium/ui/views/event_monitor_aura.h5
-rw-r--r--chromium/ui/views/event_monitor_unittest.cc12
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc3
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js1
-rw-r--r--chromium/v8/AUTHORS1
-rw-r--r--chromium/v8/DEPS2
-rw-r--r--chromium/v8/include/v8-version.h2
-rw-r--r--chromium/v8/infra/testing/builders.pyl108
-rw-r--r--chromium/v8/src/arm/macro-assembler-arm.h2
-rw-r--r--chromium/v8/src/arm64/macro-assembler-arm64.h2
-rw-r--r--chromium/v8/src/builtins/ppc/builtins-ppc.cc13
-rw-r--r--chromium/v8/src/compiler/backend/arm/instruction-selector-arm.cc3
-rw-r--r--chromium/v8/src/compiler/backend/ppc/code-generator-ppc.cc1
-rw-r--r--chromium/v8/src/ia32/macro-assembler-ia32.h2
-rw-r--r--chromium/v8/src/mips/macro-assembler-mips.h2
-rw-r--r--chromium/v8/src/mips64/macro-assembler-mips64.h2
-rw-r--r--chromium/v8/src/parsing/parser-base.h2
-rw-r--r--chromium/v8/src/parsing/parser.cc3
-rw-r--r--chromium/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc3
-rw-r--r--chromium/v8/src/simulator.h12
-rw-r--r--chromium/v8/src/x64/macro-assembler-x64.h2
-rw-r--r--chromium/v8/tools/gen-postmortem-metadata.py1
2944 files changed, 354487 insertions, 167601 deletions
diff --git a/chromium/DEPS b/chromium/DEPS
index 42b44179dd4..25336dd400d 100644
--- a/chromium/DEPS
+++ b/chromium/DEPS
@@ -122,11 +122,11 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Skia
# and whatever else without interference from each other.
- 'skia_revision': 'fda8139b467c26d85af7de898afb57dca20d80ca',
+ 'skia_revision': '84c5c846e543066678a8fd8391171fb730886852',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling V8
# and whatever else without interference from each other.
- 'v8_revision': 'ab0ebcd542ff0d6d2a947417019ab1da7da1e947',
+ 'v8_revision': 'a8a51d8837b31292af4a420039f154967f86c7eb',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling swarming_client
# and whatever else without interference from each other.
@@ -146,7 +146,7 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling PDFium
# and whatever else without interference from each other.
- 'pdfium_revision': '0389ff1a7228dc8be531a10d00ac24f118aac381',
+ 'pdfium_revision': 'b89ec0127699dab7f7ce653e3d74ee415327c8e2',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling openmax_dl
# and whatever else without interference from each other.
@@ -198,7 +198,7 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling feed
# and whatever else without interference from each other.
- 'feed_revision': 'd6031f504fcff6f34c4847f110a695fa54e90a9b',
+ 'feed_revision': '4cadd26bb73d8a74ec59fc6f8e7ed114d4c8e0ef',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling android_sdk_build-tools_version
# and whatever else without interference from each other.
@@ -680,7 +680,7 @@ deps = {
# Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
'src/third_party/chromite': {
- 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd9b3a6a40dc45c2141a78db91ec461d9bdbb0e6e',
+ 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '00f5e172c82b771bac1139cdbfa12e100834fa5b',
'condition': 'checkout_linux',
},
@@ -740,7 +740,7 @@ deps = {
},
'src/third_party/ffmpeg':
- Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '4b75b8bab99385646911c24403a016ce9c3d5740',
+ Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '41268576ad9a8b760287101f4f58d0ef468798af',
'src/third_party/flac':
Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596',
@@ -1200,7 +1200,7 @@ deps = {
Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'db52df17f0d012983dc281e4864c71485a86bd0e',
'src/third_party/webrtc':
- Var('webrtc_git') + '/src.git' + '@' + '2a1d802a35ad3d7c2a8371ce0d4263ee2476e81e',
+ Var('webrtc_git') + '/src.git' + '@' + '8bb9968c6c8643b108e1e972bf77256a97588890',
'src/third_party/xdg-utils': {
'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1241,7 +1241,7 @@ deps = {
Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'),
'src-internal': {
- 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@db84d0dfd31299df5247658112f51c2deed8f112',
+ 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@eaeb005f029e576064c33c1ff7008c2102962bb2',
'condition': 'checkout_src_internal',
},
diff --git a/chromium/PRESUBMIT.py b/chromium/PRESUBMIT.py
index 7f2ec1b2f84..1f3e63bf712 100644
--- a/chromium/PRESUBMIT.py
+++ b/chromium/PRESUBMIT.py
@@ -655,13 +655,16 @@ _ANDROID_SPECIFIC_PYDEPS_FILES = [
'build/android/gyp/aar.pydeps',
'build/android/gyp/aidl.pydeps',
'build/android/gyp/apkbuilder.pydeps',
+ 'build/android/gyp/assert_static_initializers.pydeps',
'build/android/gyp/bytecode_processor.pydeps',
'build/android/gyp/compile_resources.pydeps',
+ 'build/android/gyp/create_app_bundle_minimal_apks.pydeps',
'build/android/gyp/create_bundle_wrapper_script.pydeps',
'build/android/gyp/copy_ex.pydeps',
'build/android/gyp/create_app_bundle.pydeps',
'build/android/gyp/create_apk_operations_script.pydeps',
'build/android/gyp/create_java_binary_script.pydeps',
+ 'build/android/gyp/create_size_info_files.pydeps',
'build/android/gyp/create_stack_script.pydeps',
'build/android/gyp/create_test_runner_script.pydeps',
'build/android/gyp/create_tool_wrapper.pydeps',
@@ -679,7 +682,6 @@ _ANDROID_SPECIFIC_PYDEPS_FILES = [
'build/android/gyp/jinja_template.pydeps',
'build/android/gyp/lint.pydeps',
'build/android/gyp/main_dex_list.pydeps',
- 'build/android/gyp/merge_jar_info_files.pydeps',
'build/android/gyp/merge_manifest.pydeps',
'build/android/gyp/prepare_resources.pydeps',
'build/android/gyp/proguard.pydeps',
diff --git a/chromium/base/android/linker/BUILD.gn b/chromium/base/android/linker/BUILD.gn
index 2f40421f005..dd5a0d6f31e 100644
--- a/chromium/base/android/linker/BUILD.gn
+++ b/chromium/base/android/linker/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/android/config.gni")
+import("//build/config/sysroot.gni")
assert(is_android)
@@ -23,6 +24,10 @@ shared_library("chromium_android_linker") {
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
+ # Avoid linking libc++ and support libraries, to avoid 100 kiB of
+ # un-necessary code.
+ no_default_deps = true
+
# The linker is used on Android platforms that do not support GNU-style
# hash tables, so ensure one isn't included in it to save space (since the SysV
# format is always supported). It would be nice to also remove the GNU version
diff --git a/chromium/base/mac/foundation_util.h b/chromium/base/mac/foundation_util.h
index 433642f5384..b2d56d8301f 100644
--- a/chromium/base/mac/foundation_util.h
+++ b/chromium/base/mac/foundation_util.h
@@ -380,6 +380,9 @@ T GetValueFromDictionary(CFDictionaryRef dict, CFStringRef key) {
return value_specific;
}
+// Converts |path| to an autoreleased NSURL. Returns nil if |path| is empty.
+BASE_EXPORT NSURL* FilePathToNSURL(const FilePath& path);
+
// Converts |path| to an autoreleased NSString. Returns nil if |path| is empty.
BASE_EXPORT NSString* FilePathToNSString(const FilePath& path);
diff --git a/chromium/base/mac/foundation_util.mm b/chromium/base/mac/foundation_util.mm
index 5046eedeb43..2d619e791c0 100644
--- a/chromium/base/mac/foundation_util.mm
+++ b/chromium/base/mac/foundation_util.mm
@@ -436,6 +436,12 @@ std::string GetValueFromDictionaryErrorMessage(
" instead";
}
+NSURL* FilePathToNSURL(const FilePath& path) {
+ if (NSString* path_string = FilePathToNSString(path))
+ return [NSURL fileURLWithPath:path_string];
+ return nil;
+}
+
NSString* FilePathToNSString(const FilePath& path) {
if (path.empty())
return nil;
diff --git a/chromium/base/mac/foundation_util_unittest.mm b/chromium/base/mac/foundation_util_unittest.mm
index 5214354f695..43d55116103 100644
--- a/chromium/base/mac/foundation_util_unittest.mm
+++ b/chromium/base/mac/foundation_util_unittest.mm
@@ -305,6 +305,12 @@ TEST(FoundationUtilTest, GetValueFromDictionary) {
EXPECT_FALSE(GetValueFromDictionary<CFStringRef>(test_dict, CFSTR("one")));
}
+TEST(FoundationUtilTest, FilePathToNSURL) {
+ EXPECT_NSEQ(nil, FilePathToNSURL(FilePath()));
+ EXPECT_NSEQ([NSURL fileURLWithPath:@"/a/b"],
+ FilePathToNSURL(FilePath("/a/b")));
+}
+
TEST(FoundationUtilTest, FilePathToNSString) {
EXPECT_NSEQ(nil, FilePathToNSString(FilePath()));
EXPECT_NSEQ(@"/a/b", FilePathToNSString(FilePath("/a/b")));
diff --git a/chromium/base/memory/discardable_shared_memory.cc b/chromium/base/memory/discardable_shared_memory.cc
index 5ad48a97675..57494b592bf 100644
--- a/chromium/base/memory/discardable_shared_memory.cc
+++ b/chromium/base/memory/discardable_shared_memory.cc
@@ -487,12 +487,14 @@ DiscardableSharedMemory::LockResult DiscardableSharedMemory::LockPages(
size_t length) {
#if defined(OS_ANDROID)
if (region.IsValid()) {
- int pin_result =
- ashmem_pin_region(region.GetPlatformHandle(), offset, length);
- if (pin_result == ASHMEM_WAS_PURGED)
- return PURGED;
- if (pin_result < 0)
- return FAILED;
+ if (ashmem_device_is_supported()) {
+ int pin_result =
+ ashmem_pin_region(region.GetPlatformHandle(), offset, length);
+ if (pin_result == ASHMEM_WAS_PURGED)
+ return PURGED;
+ if (pin_result < 0)
+ return FAILED;
+ }
}
#endif
return SUCCESS;
@@ -505,9 +507,11 @@ void DiscardableSharedMemory::UnlockPages(
size_t length) {
#if defined(OS_ANDROID)
if (region.IsValid()) {
- int unpin_result =
- ashmem_unpin_region(region.GetPlatformHandle(), offset, length);
- DCHECK_EQ(0, unpin_result);
+ if (ashmem_device_is_supported()) {
+ int unpin_result =
+ ashmem_unpin_region(region.GetPlatformHandle(), offset, length);
+ DCHECK_EQ(0, unpin_result);
+ }
}
#endif
}
@@ -516,4 +520,11 @@ Time DiscardableSharedMemory::Now() const {
return Time::Now();
}
+#if defined(OS_ANDROID)
+// static
+bool DiscardableSharedMemory::IsAshmemDeviceSupportedForTesting() {
+ return ashmem_device_is_supported();
+}
+#endif
+
} // namespace base
diff --git a/chromium/base/memory/discardable_shared_memory.h b/chromium/base/memory/discardable_shared_memory.h
index 52a78b131ea..44d4cab02a5 100644
--- a/chromium/base/memory/discardable_shared_memory.h
+++ b/chromium/base/memory/discardable_shared_memory.h
@@ -150,6 +150,12 @@ class BASE_EXPORT DiscardableSharedMemory {
trace_event::ProcessMemoryDump* pmd,
bool is_owned) const;
+#if defined(OS_ANDROID)
+ // Returns true if the Ashmem device is supported on this system.
+ // Only use this for unit-testing.
+ static bool IsAshmemDeviceSupportedForTesting();
+#endif
+
private:
// LockPages/UnlockPages are platform-native discardable page management
// helper functions. Both expect |offset| to be specified relative to the
diff --git a/chromium/base/memory/discardable_shared_memory_unittest.cc b/chromium/base/memory/discardable_shared_memory_unittest.cc
index 78712d8a720..538f5c69ef0 100644
--- a/chromium/base/memory/discardable_shared_memory_unittest.cc
+++ b/chromium/base/memory/discardable_shared_memory_unittest.cc
@@ -245,6 +245,11 @@ TEST(DiscardableSharedMemoryTest, LockShouldAlwaysFailAfterSuccessfulPurge) {
TEST(DiscardableSharedMemoryTest, LockShouldFailIfPlatformLockPagesFails) {
const uint32_t kDataSize = 1024;
+ // This test cannot succeed on devices without a proper ashmem device
+ // because Lock() will always succeed.
+ if (!DiscardableSharedMemory::IsAshmemDeviceSupportedForTesting())
+ return;
+
DiscardableSharedMemory memory1;
bool rv1 = memory1.CreateAndMap(kDataSize);
ASSERT_TRUE(rv1);
diff --git a/chromium/build/android/apk_operations.py b/chromium/build/android/apk_operations.py
index 7e3aec12aca..4b594435828 100755
--- a/chromium/build/android/apk_operations.py
+++ b/chromium/build/android/apk_operations.py
@@ -61,6 +61,8 @@ _DALVIK_IGNORE_PATTERN = re.compile('|'.join([
r'^WAIT_',
]))
+BASE_MODULE = 'base'
+
def _Colorize(text, style=''):
return (style
@@ -94,43 +96,128 @@ BundleGenerationInfo = collections.namedtuple(
'keystore_alias')
-def _GenerateBundleApks(info, universal=False):
+def _GenerateBundleApks(info, output_path, minimal=False, universal=False):
"""Generate an .apks archive from a bundle on demand.
Args:
info: A BundleGenerationInfo instance.
+ output_path: Path of output .apks archive.
+ minimal: Create the minimal set of apks possible (english-only).
universal: Whether to create a single APK that contains the contents of all
- modules.
- Returns:
- Path of output .apks archive.
+ modules.
"""
app_bundle_utils.GenerateBundleApks(
info.bundle_path,
- info.bundle_apks_path,
+ output_path,
info.aapt2_path,
info.keystore_path,
info.keystore_password,
info.keystore_alias,
- universal)
- return info.bundle_apks_path
+ universal=universal,
+ minimal=minimal)
+
+
+def _InstallBundle(devices, bundle_apks, package_name, command_line_flags_file,
+ modules, fake_modules):
+ # Path to push fake modules for Chrome to pick up.
+ MODULES_SRC_DIRECTORY_PATH = '/data/local/tmp/modules'
+ # Path Chrome creates after validating fake modules. This needs to be cleared
+ # for pushed fake modules to be picked up.
+ SPLITCOMPAT_PATH = '/data/data/' + package_name + '/files/splitcompat'
+ # Chrome command line flag needed for fake modules to work.
+ FAKE_FEATURE_MODULE_INSTALL = '--fake-feature-module-install'
+
+ def ShouldWarnFakeFeatureModuleInstallFlag(device):
+ if command_line_flags_file:
+ changer = flag_changer.FlagChanger(device, command_line_flags_file)
+ return FAKE_FEATURE_MODULE_INSTALL not in changer.GetCurrentFlags()
+ return False
+
+ def ClearFakeModules(device):
+ for path in [SPLITCOMPAT_PATH, MODULES_SRC_DIRECTORY_PATH]:
+ if device.PathExists(path, as_root=True):
+ device.RemovePath(path, force=True, recursive=True, as_root=True)
+ logging.info('Removed %s', path)
+ else:
+ logging.info('Skipped removing nonexistent %s', path)
+ def InstallFakeModules(device):
+ try:
+ temp_path = tempfile.mkdtemp()
+
+ # Device-spec JSON is needed, so create that first.
+ device_spec_filename = os.path.join(temp_path, 'device_spec.json')
+ get_device_spec_cmd_args = [
+ 'get-device-spec', '--adb=' + adb_wrapper.AdbWrapper.GetAdbPath(),
+ '--device-id=' + device.serial, '--output=' + device_spec_filename
+ ]
+ bundletool.RunBundleTool(get_device_spec_cmd_args)
+
+ # Extract fake modules to temp directory. For now, installation requires
+ # running 'bundletool extract-apks'. Unfortunately, this leads to unneeded
+ # compression of module files.
+ extract_apks_cmd_args = [
+ 'extract-apks', '--apks=' + bundle_apks,
+ '--device-spec=' + device_spec_filename,
+ '--modules=' + ','.join(fake_modules), '--output-dir=' + temp_path
+ ]
+ bundletool.RunBundleTool(extract_apks_cmd_args)
+
+ # Push fake modules, with renames.
+ for fake_module in fake_modules:
+ remote = posixpath.join(MODULES_SRC_DIRECTORY_PATH,
+ '%s.apk' % fake_module)
+ # Try |local| filename alternatives, and ensure there's exactly one.
+ # TODO(huangs): Handle fake packages with different languages: See
+ # http://crbug.com/925358.
+ local_choices = []
+ for suffix in ['-master.apk', '-master_2.apk']:
+ local = os.path.join(temp_path, fake_module + suffix)
+ if os.path.isfile(local):
+ local_choices.append(local)
+ if len(local_choices) != 1:
+ raise Exception('Expect 1 matching local file for %s' % fake_module)
+ device.adb.Push(local_choices[0], remote)
+ finally:
+ shutil.rmtree(temp_path, ignore_errors=True)
+
+ def Install(device):
+ ClearFakeModules(device)
+ if fake_modules:
+ # Print warning if command line is not set up for fake modules.
+ if ShouldWarnFakeFeatureModuleInstallFlag(device):
+ msg = ('Command line has no %s: Fake modules will be ignored.' %
+ FAKE_FEATURE_MODULE_INSTALL)
+ print _Colorize(msg, colorama.Fore.YELLOW + colorama.Style.BRIGHT)
+ InstallFakeModules(device)
-def _InstallBundle(devices, bundle_apks, modules):
- def install(device):
# NOTE: For now, installation requires running 'bundletool install-apks'.
# TODO(digit): Add proper support for bundles to devil instead, then use it.
- cmd_args = [
- 'install-apks',
- '--apks=' + bundle_apks,
+ install_cmd_args = [
+ 'install-apks', '--apks=' + bundle_apks,
'--adb=' + adb_wrapper.AdbWrapper.GetAdbPath(),
'--device-id=' + device.serial
]
if modules:
- cmd_args += ['--modules=' + ','.join(modules)]
- bundletool.RunBundleTool(cmd_args)
+ install_cmd_args += ['--modules=' + ','.join(modules)]
+ bundletool.RunBundleTool(install_cmd_args)
+
+ # Basic checks for |modules| and |fake_modules|.
+ # * |fake_modules| cannot include 'base'.
+ # * If |fake_modules| is given, ensure |modules| includes 'base'.
+ # * They must be disjoint.
+ modules_set = set(modules) if modules else set()
+ fake_modules_set = set(fake_modules) if fake_modules else set()
+ if BASE_MODULE in fake_modules_set:
+ raise Exception('\'-f {}\' is disallowed.'.format(BASE_MODULE))
+ if fake_modules_set and BASE_MODULE not in modules_set:
+ raise Exception(
+ '\'-f FAKE\' must be accompanied by \'-m {}\''.format(BASE_MODULE))
+ if fake_modules_set.intersection(modules_set):
+ raise Exception('\'-m\' and \'-f\' entries must be disjoint.')
logging.info('Installing bundle.')
- device_utils.DeviceUtils.parallel(devices).pMap(install)
+ device_utils.DeviceUtils.parallel(devices).pMap(Install)
def _UninstallApk(devices, install_dict, package_name):
@@ -999,14 +1086,28 @@ class _InstallCommand(_Command):
def _RegisterExtraArgs(self, group):
if self.is_bundle:
- group.add_argument('-m', '--module', action='append',
- help='Module to install. Can be specified multiple '
- 'times. One of them has to be \'base\'')
+ group.add_argument(
+ '-m',
+ '--module',
+ action='append',
+ help='Module to install. Can be specified multiple times. ' +
+ 'One of them has to be \'{}\''.format(BASE_MODULE))
+ group.add_argument(
+ '-f',
+ '--fake',
+ action='append',
+ help='Fake bundle module install. Can be specified multiple times. '
+ 'Requires \'-m {0}\' to be given, and \'-f {0}\' is illegal.'.format(
+ BASE_MODULE))
def Run(self):
if self.is_bundle:
- bundle_apks_path = _GenerateBundleApks(self.bundle_generation_info)
- _InstallBundle(self.devices, bundle_apks_path, self.args.module)
+ # Store .apks file beside the .aab file so that it gets cached.
+ output_path = self.bundle_generation_info.bundle_apks_path
+ _GenerateBundleApks(self.bundle_generation_info, output_path)
+ _InstallBundle(self.devices, output_path, self.args.package_name,
+ self.args.command_line_flags_file, self.args.module,
+ self.args.fake)
else:
_InstallApk(self.devices, self.apk_helper, self.install_dict)
@@ -1317,21 +1418,24 @@ class _BuildBundleApks(_Command):
need_device_args = False
def _RegisterExtraArgs(self, group):
- group.add_argument('--output-apks',
- help='Destination path for .apks archive copy.')
+ group.add_argument(
+ '--output-apks', required=True, help='Destination path for .apks file.')
+ group.add_argument(
+ '--minimal',
+ action='store_true',
+ help='Build .apks archive that targets the bundle\'s minSdkVersion and '
+ 'contains only english splits. It still contains optional splits.')
group.add_argument('--universal', action='store_true',
help='Build .apks archive containing single APK with '
'contents of all splits. NOTE: Won\'t add modules '
'with <dist:fusing dist:include="false"/> flag.')
def Run(self):
- bundle_apks_path = _GenerateBundleApks(self.bundle_generation_info,
- self.args.universal)
- if self.args.output_apks:
- try:
- shutil.copyfile(bundle_apks_path, self.args.output_apks)
- except shutil.Error as e:
- logging.exception('Failed to copy .apks archive: %s', e)
+ _GenerateBundleApks(
+ self.bundle_generation_info,
+ self.args.output_apks,
+ minimal=self.args.minimal,
+ universal=self.args.universal)
# Shared commands for regular APKs and app bundles.
diff --git a/chromium/build/android/gyp/apkbuilder.py b/chromium/build/android/gyp/apkbuilder.py
index b5097aafb0c..9ffb137ec00 100755
--- a/chromium/build/android/gyp/apkbuilder.py
+++ b/chromium/build/android/gyp/apkbuilder.py
@@ -30,19 +30,18 @@ _NO_COMPRESS_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.gif', '.wav', '.mp2',
def _ParseArgs(args):
parser = argparse.ArgumentParser()
build_utils.AddDepfileOption(parser)
- parser.add_argument('--assets',
- help='GYP-list of files to add as assets in the form '
- '"srcPath:zipPath", where ":zipPath" is optional.',
- default='[]')
- parser.add_argument('--java-resources',
- help='GYP-list of java_resources JARs to include.',
- default='[]')
+ parser.add_argument(
+ '--assets',
+ help='GYP-list of files to add as assets in the form '
+ '"srcPath:zipPath", where ":zipPath" is optional.')
+ parser.add_argument(
+ '--java-resources', help='GYP-list of java_resources JARs to include.')
parser.add_argument('--write-asset-list',
action='store_true',
help='Whether to create an assets/assets_list file.')
- parser.add_argument('--uncompressed-assets',
- help='Same as --assets, except disables compression.',
- default='[]')
+ parser.add_argument(
+ '--uncompressed-assets',
+ help='Same as --assets, except disables compression.')
parser.add_argument('--resource-apk',
help='An .ap_ file built using aapt',
required=True)
@@ -51,10 +50,6 @@ def _ParseArgs(args):
required=True)
parser.add_argument('--format', choices=['apk', 'bundle-module'],
default='apk', help='Specify output format.')
- parser.add_argument('--apk-pak-info-path',
- help='Path to the *.apk.pak.info file')
- parser.add_argument('--apk-res-info-path',
- help='Path to the *.apk.res.info file')
parser.add_argument('--dex-file',
help='Path to the classes.dex to use')
parser.add_argument('--uncompress-dex', action='store_true',
@@ -74,13 +69,13 @@ def _ParseArgs(args):
parser.add_argument('--secondary-android-abi',
help='The secondary Android architecture to use for'
'secondary native libraries')
- parser.add_argument('--native-lib-placeholders',
- help='GYP-list of native library placeholders to add.',
- default='[]')
- parser.add_argument('--secondary-native-lib-placeholders',
- help='GYP-list of native library placeholders to add '
- 'for the secondary ABI',
- default='[]')
+ parser.add_argument(
+ '--native-lib-placeholders',
+ help='GYP-list of native library placeholders to add.')
+ parser.add_argument(
+ '--secondary-native-lib-placeholders',
+ help='GYP-list of native library placeholders to add '
+ 'for the secondary ABI')
parser.add_argument('--uncompress-shared-libraries', default='False',
choices=['true', 'True', 'false', 'False'],
help='Whether to uncompress native shared libraries. Argument must be '
@@ -226,31 +221,12 @@ def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress):
compress=compress)
-def _MergeResInfoFiles(res_info_path, resource_apk):
- resource_apk_info_path = resource_apk + '.info'
- shutil.copy(resource_apk_info_path, res_info_path)
-
-
-def _FilterPakInfoPaths(assets):
- return [f.split(':')[0] + '.info' for f in assets if f.endswith('.pak')]
-
-
-def _MergePakInfoFiles(merged_path, pak_infos):
- info_lines = set()
- for pak_info_path in pak_infos:
- with open(pak_info_path, 'r') as src_info_file:
- info_lines.update(src_info_file.readlines())
- with open(merged_path, 'w') as merged_info_file:
- merged_info_file.writelines(sorted(info_lines))
-
-
def main(args):
args = build_utils.ExpandFileArgs(args)
options = _ParseArgs(args)
native_libs = sorted(options.native_libs)
- input_paths = [options.resource_apk, __file__]
# Include native libs in the depfile_deps since GN doesn't know about the
# dependencies when is_component_build=true.
depfile_deps = list(native_libs)
@@ -260,17 +236,6 @@ def main(args):
secondary_native_libs = sorted(options.secondary_native_libs)
depfile_deps += secondary_native_libs
- if options.dex_file:
- input_paths.append(options.dex_file)
-
- input_strings = [options.android_abi,
- options.native_lib_placeholders,
- options.secondary_native_lib_placeholders,
- str(options.uncompress_shared_libraries)]
-
- if options.secondary_android_abi:
- input_strings.append(options.secondary_android_abi)
-
if options.java_resources:
# Included via .build_config, so need to write it to depfile.
depfile_deps.extend(options.java_resources)
@@ -278,21 +243,9 @@ def main(args):
assets = _ExpandPaths(options.assets)
uncompressed_assets = _ExpandPaths(options.uncompressed_assets)
- if options.apk_pak_info_path:
- pak_infos = _FilterPakInfoPaths(
- options.assets + options.uncompressed_assets)
- depfile_deps.extend(pak_infos)
-
- for src_path, dest_path in itertools.chain(assets, uncompressed_assets):
- # Included via .build_config, so need to write it to depfile.
- depfile_deps.append(src_path)
- input_strings.append(dest_path)
-
- output_paths = [options.output_apk]
- if options.apk_pak_info_path:
- output_paths.append(options.apk_pak_info_path)
- if options.apk_res_info_path:
- output_paths.append(options.apk_res_info_path)
+ # Included via .build_config, so need to write it to depfile.
+ depfile_deps.extend(x[0] for x in assets)
+ depfile_deps.extend(x[0] for x in uncompressed_assets)
# Bundle modules have a structure similar to APKs, except that resources
# are compiled in protobuf format (instead of binary xml), and that some
@@ -314,119 +267,110 @@ def main(args):
apk_root_dir = ''
apk_dex_dir = ''
- def on_stale_md5():
- with tempfile.NamedTemporaryFile() as tmp_apk:
- tmp_file = tmp_apk.name
- with zipfile.ZipFile(options.resource_apk) as resource_apk, \
- zipfile.ZipFile(tmp_file, 'w', zipfile.ZIP_DEFLATED) as out_apk:
- def copy_resource(zipinfo, out_dir=''):
- compress = zipinfo.compress_type != zipfile.ZIP_STORED
- build_utils.AddToZipHermetic(out_apk, out_dir + zipinfo.filename,
- data=resource_apk.read(zipinfo.filename),
- compress=compress)
-
- # Make assets come before resources in order to maintain the same file
- # ordering as GYP / aapt. http://crbug.com/561862
- resource_infos = resource_apk.infolist()
-
- # 1. AndroidManifest.xml
- copy_resource(
- resource_apk.getinfo('AndroidManifest.xml'),
- out_dir=apk_manifest_dir)
-
- # 2. Assets
- if options.write_asset_list:
- data = _CreateAssetsList(
- itertools.chain(assets, uncompressed_assets))
- build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data)
-
- _AddAssets(out_apk, assets, disable_compression=False)
- _AddAssets(out_apk, uncompressed_assets, disable_compression=True)
-
- # 3. Dex files
- if options.dex_file and options.dex_file.endswith('.zip'):
- with zipfile.ZipFile(options.dex_file, 'r') as dex_zip:
- for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')):
- build_utils.AddToZipHermetic(out_apk, apk_dex_dir + dex,
- data=dex_zip.read(dex),
- compress=not options.uncompress_dex)
- elif options.dex_file:
- build_utils.AddToZipHermetic(out_apk, apk_dex_dir + 'classes.dex',
- src_path=options.dex_file,
- compress=not options.uncompress_dex)
-
- # 4. Native libraries.
- _AddNativeLibraries(out_apk,
- native_libs,
- options.android_abi,
+ # Targets generally do not depend on apks, so no need for only_if_changed.
+ with build_utils.AtomicOutput(options.output_apk, only_if_changed=False) as f:
+ with zipfile.ZipFile(options.resource_apk) as resource_apk, \
+ zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) as out_apk:
+
+ def copy_resource(zipinfo, out_dir=''):
+ compress = zipinfo.compress_type != zipfile.ZIP_STORED
+ build_utils.AddToZipHermetic(
+ out_apk,
+ out_dir + zipinfo.filename,
+ data=resource_apk.read(zipinfo.filename),
+ compress=compress)
+
+ # Make assets come before resources in order to maintain the same file
+ # ordering as GYP / aapt. http://crbug.com/561862
+ resource_infos = resource_apk.infolist()
+
+ # 1. AndroidManifest.xml
+ copy_resource(
+ resource_apk.getinfo('AndroidManifest.xml'), out_dir=apk_manifest_dir)
+
+ # 2. Assets
+ if options.write_asset_list:
+ data = _CreateAssetsList(itertools.chain(assets, uncompressed_assets))
+ build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data)
+
+ _AddAssets(out_apk, assets, disable_compression=False)
+ _AddAssets(out_apk, uncompressed_assets, disable_compression=True)
+
+ # 3. Dex files
+ if options.dex_file and options.dex_file.endswith('.zip'):
+ with zipfile.ZipFile(options.dex_file, 'r') as dex_zip:
+ for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')):
+ build_utils.AddToZipHermetic(
+ out_apk,
+ apk_dex_dir + dex,
+ data=dex_zip.read(dex),
+ compress=not options.uncompress_dex)
+ elif options.dex_file:
+ build_utils.AddToZipHermetic(
+ out_apk,
+ apk_dex_dir + 'classes.dex',
+ src_path=options.dex_file,
+ compress=not options.uncompress_dex)
+
+ # 4. Native libraries.
+ _AddNativeLibraries(out_apk, native_libs, options.android_abi,
+ options.uncompress_shared_libraries)
+
+ if options.secondary_android_abi:
+ _AddNativeLibraries(out_apk, secondary_native_libs,
+ options.secondary_android_abi,
options.uncompress_shared_libraries)
- if options.secondary_android_abi:
- _AddNativeLibraries(out_apk,
- secondary_native_libs,
- options.secondary_android_abi,
- options.uncompress_shared_libraries)
-
- for name in sorted(options.native_lib_placeholders):
- # Note: Empty libs files are ignored by md5check (can cause issues
- # with stale builds when the only change is adding/removing
- # placeholders).
- apk_path = 'lib/%s/%s' % (options.android_abi, name)
- build_utils.AddToZipHermetic(out_apk, apk_path, data='')
-
- for name in sorted(options.secondary_native_lib_placeholders):
- # Note: Empty libs files are ignored by md5check (can cause issues
- # with stale builds when the only change is adding/removing
- # placeholders).
- apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name)
- build_utils.AddToZipHermetic(out_apk, apk_path, data='')
-
- # 5. Resources
- for info in resource_infos:
- if info.filename != 'AndroidManifest.xml':
- copy_resource(info)
-
- # 6. Java resources that should be accessible via
- # Class.getResourceAsStream(), in particular parts of Emma jar.
- # Prebuilt jars may contain class files which we shouldn't include.
- for java_resource in options.java_resources:
- with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
- for apk_path in java_resource_jar.namelist():
- apk_path_lower = apk_path.lower()
-
- if apk_path_lower.startswith('meta-inf/'):
- continue
- if apk_path_lower.endswith('/'):
- continue
- if apk_path_lower.endswith('.class'):
- continue
-
- build_utils.AddToZipHermetic(
- out_apk, apk_root_dir + apk_path,
- data=java_resource_jar.read(apk_path))
-
- if options.apk_pak_info_path:
- _MergePakInfoFiles(options.apk_pak_info_path, pak_infos)
- if options.apk_res_info_path:
- _MergeResInfoFiles(options.apk_res_info_path, options.resource_apk)
-
- if options.format == 'apk':
- finalize_apk.FinalizeApk(options.apksigner_path, options.zipalign_path,
- tmp_file, options.output_apk,
- options.key_path, options.key_passwd,
- options.key_name)
- else:
- shutil.move(tmp_file, options.output_apk)
- tmp_apk.delete = False
-
- build_utils.CallAndWriteDepfileIfStale(
- on_stale_md5,
- options,
- input_paths=input_paths + depfile_deps,
- input_strings=input_strings,
- output_paths=output_paths,
- depfile_deps=depfile_deps,
- add_pydeps=False)
+ for name in sorted(options.native_lib_placeholders):
+ # Note: Empty libs files are ignored by md5check (can cause issues
+ # with stale builds when the only change is adding/removing
+ # placeholders).
+ apk_path = 'lib/%s/%s' % (options.android_abi, name)
+ build_utils.AddToZipHermetic(out_apk, apk_path, data='')
+
+ for name in sorted(options.secondary_native_lib_placeholders):
+ # Note: Empty libs files are ignored by md5check (can cause issues
+ # with stale builds when the only change is adding/removing
+ # placeholders).
+ apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name)
+ build_utils.AddToZipHermetic(out_apk, apk_path, data='')
+
+ # 5. Resources
+ for info in resource_infos:
+ if info.filename != 'AndroidManifest.xml':
+ copy_resource(info)
+
+ # 6. Java resources that should be accessible via
+ # Class.getResourceAsStream(), in particular parts of Emma jar.
+ # Prebuilt jars may contain class files which we shouldn't include.
+ for java_resource in options.java_resources:
+ with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
+ for apk_path in java_resource_jar.namelist():
+ apk_path_lower = apk_path.lower()
+
+ if apk_path_lower.startswith('meta-inf/'):
+ continue
+ if apk_path_lower.endswith('/'):
+ continue
+ if apk_path_lower.endswith('.class'):
+ continue
+
+ build_utils.AddToZipHermetic(
+ out_apk,
+ apk_root_dir + apk_path,
+ data=java_resource_jar.read(apk_path))
+
+ if options.format == 'apk':
+ finalize_apk.FinalizeApk(options.apksigner_path, options.zipalign_path,
+ f.name, f.name, options.key_path,
+ options.key_passwd, options.key_name)
+
+ if options.depfile:
+ build_utils.WriteDepfile(
+ options.depfile,
+ options.output_apk,
+ inputs=depfile_deps,
+ add_pydeps=False)
if __name__ == '__main__':
diff --git a/chromium/build/android/gyp/assert_static_initializers.py b/chromium/build/android/gyp/assert_static_initializers.py
index 717861b77c9..019baface15 100755
--- a/chromium/build/android/gyp/assert_static_initializers.py
+++ b/chromium/build/android/gyp/assert_static_initializers.py
@@ -7,17 +7,116 @@
import argparse
import os
+import re
+import subprocess
import sys
-
-sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-import resource_sizes
+import tempfile
+import zipfile
from util import build_utils
+_DUMP_STATIC_INITIALIZERS_PATH = os.path.join(build_utils.DIR_SOURCE_ROOT,
+ 'tools', 'linux',
+ 'dump-static-initializers.py')
+
+
+def _RunReadelf(so_path, options, tool_prefix=''):
+ return subprocess.check_output([tool_prefix + 'readelf'] + options +
+ [so_path])
+
+
+def _ParseLibBuildId(so_path, tool_prefix):
+ """Returns the Build ID of the given native library."""
+ stdout = _RunReadelf(so_path, ['-n'], tool_prefix)
+ match = re.search(r'Build ID: (\w+)', stdout)
+ return match.group(1) if match else None
+
+
+def _VerifyLibBuildIdsMatch(tool_prefix, *so_files):
+ if len(set(_ParseLibBuildId(f, tool_prefix) for f in so_files)) > 1:
+ raise Exception('Found differing build ids in output directory and apk. '
+ 'Your output directory is likely stale.')
+
+
+def _GetStaticInitializers(so_path, tool_prefix):
+ output = subprocess.check_output(
+ [_DUMP_STATIC_INITIALIZERS_PATH, '-d', so_path, '-t', tool_prefix])
+ summary = re.search(r'Found \d+ static initializers in (\d+) files.', output)
+ return output.splitlines()[:-1], int(summary.group(1))
+
+
+def _PrintDumpSIsCount(apk_so_name, unzipped_so, out_dir, tool_prefix):
+ lib_name = os.path.basename(apk_so_name).replace('crazy.', '')
+ so_with_symbols_path = os.path.join(out_dir, 'lib.unstripped', lib_name)
+ if not os.path.exists(so_with_symbols_path):
+ raise Exception('Unstripped .so not found. Looked here: %s',
+ so_with_symbols_path)
+ _VerifyLibBuildIdsMatch(tool_prefix, unzipped_so, so_with_symbols_path)
+ sis, _ = _GetStaticInitializers(so_with_symbols_path, tool_prefix)
+ for si in sis:
+ print si
+
+
+# Mostly copied from //infra/scripts/legacy/scripts/slave/chromium/sizes.py.
+def _ReadInitArray(so_path, tool_prefix):
+ stdout = _RunReadelf(so_path, ['-SW'], tool_prefix)
+ # Matches: .ctors PROGBITS 000000000516add0 5169dd0 000010 00 WA 0 0 8
+ match = re.search(r'\.init_array.*$', stdout, re.MULTILINE)
+ if not match:
+ raise Exception('Did not find section: .init_array in:\n' + stdout)
+ size_str = re.split(r'\W+', match.group(0))[5]
+ return int(size_str, 16)
+
+
+def _CountStaticInitializers(so_path, tool_prefix):
+ # Find the number of files with at least one static initializer.
+ # First determine if we're 32 or 64 bit
+ stdout = _RunReadelf(so_path, ['-h'], tool_prefix)
+ elf_class_line = re.search('Class:.*$', stdout, re.MULTILINE).group(0)
+ elf_class = re.split(r'\W+', elf_class_line)[1]
+ if elf_class == 'ELF32':
+ word_size = 4
+ else:
+ word_size = 8
+
+ # Then find the number of files with global static initializers.
+ # NOTE: this is very implementation-specific and makes assumptions
+ # about how compiler and linker implement global static initializers.
+ init_array_size = _ReadInitArray(so_path, tool_prefix)
+ return init_array_size / word_size
+
+
+def _AnalyzeStaticInitializers(apk_filename, tool_prefix, dump_sis, out_dir,
+ ignored_libs):
+ # Static initializer counting mostly copies logic in
+ # infra/scripts/legacy/scripts/slave/chromium/sizes.py.
+ with zipfile.ZipFile(apk_filename) as z:
+ so_files = [
+ f for f in z.infolist() if f.filename.endswith('.so')
+ and f.file_size > 0 and os.path.basename(f.filename) not in ignored_libs
+ ]
+ # Skip checking static initializers for secondary abi libs. They will be
+ # checked by 32-bit bots. This avoids the complexity of finding 32 bit .so
+ # files in the output directory in 64 bit builds.
+ has_64 = any('64' in f.filename for f in so_files)
+ files_to_check = [f for f in so_files if not has_64 or '64' in f.filename]
+
+ si_count = 0
+ for f in files_to_check:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(z.read(f))
+ temp.flush()
+ si_count += _CountStaticInitializers(temp.name, tool_prefix)
+ if dump_sis:
+ # Print count and list of SIs reported by dump-static-initializers.py.
+ # Doesn't work well on all archs (particularly arm), which is why
+ # the readelf method is used for tracking SI counts.
+ _PrintDumpSIsCount(f.filename, temp.name, out_dir, tool_prefix)
+ return si_count
+
def main():
parser = argparse.ArgumentParser()
- build_utils.AddDepfileOption(parser)
parser.add_argument('--touch', help='File to touch upon success')
parser.add_argument('--tool-prefix', required=True,
help='Prefix for nm and friends')
@@ -30,8 +129,8 @@ def main():
#TODO(crbug.com/838414): add support for files included via loadable_modules.
ignored_libs = ['libarcore_sdk_c.so']
- si_count = resource_sizes.AnalyzeStaticInitializers(
- args.apk, args.tool_prefix, False, '.', ignored_libs)
+ si_count = _AnalyzeStaticInitializers(args.apk, args.tool_prefix, False, '.',
+ ignored_libs)
if si_count != args.expected_count:
print 'Expected {} static initializers, but found {}.'.format(
args.expected_count, si_count)
@@ -42,8 +141,8 @@ def main():
else:
print 'Dumping static initializers via dump-static-initializers.py:'
sys.stdout.flush()
- resource_sizes.AnalyzeStaticInitializers(
- args.apk, args.tool_prefix, True, '.', ignored_libs)
+ _AnalyzeStaticInitializers(args.apk, args.tool_prefix, True, '.',
+ ignored_libs)
print
print 'If the above list is not useful, consider listing them with:'
print ' //tools/binary_size/diagnose_bloat.py'
@@ -53,8 +152,6 @@ def main():
'static_initializers.md')
sys.exit(1)
- if args.depfile:
- build_utils.WriteDepfile(args.depfile, args.touch)
if args.touch:
open(args.touch, 'w')
diff --git a/chromium/build/android/gyp/assert_static_initializers.pydeps b/chromium/build/android/gyp/assert_static_initializers.pydeps
new file mode 100644
index 00000000000..e031668f467
--- /dev/null
+++ b/chromium/build/android/gyp/assert_static_initializers.pydeps
@@ -0,0 +1,7 @@
+# Generated by running:
+# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/assert_static_initializers.pydeps build/android/gyp/assert_static_initializers.py
+../../gn_helpers.py
+assert_static_initializers.py
+util/__init__.py
+util/build_utils.py
+util/md5_check.py
diff --git a/chromium/build/android/gyp/bundletool.py b/chromium/build/android/gyp/bundletool.py
index 1709b936d98..3ac9cddec35 100755
--- a/chromium/build/android/gyp/bundletool.py
+++ b/chromium/build/android/gyp/bundletool.py
@@ -8,6 +8,7 @@
Bundletool is distributed as a versioned jar file. This script abstracts the
location and version of this jar file, as well as the JVM invokation."""
+import logging
import os
import subprocess
import sys
@@ -24,6 +25,7 @@ BUNDLETOOL_JAR_PATH = os.path.join(
def RunBundleTool(args):
args = ['java', '-jar', BUNDLETOOL_JAR_PATH] + args
+ logging.debug(' '.join(args))
subprocess.check_call(args)
if __name__ == '__main__':
diff --git a/chromium/build/android/gyp/compile_resources.py b/chromium/build/android/gyp/compile_resources.py
index 72ff6fe1f4f..15381e8efca 100755
--- a/chromium/build/android/gyp/compile_resources.py
+++ b/chromium/build/android/gyp/compile_resources.py
@@ -653,7 +653,7 @@ def _CreateResourceInfoFile(
lines.update(zip_info_file.readlines())
for dest, source in renamed_paths.iteritems():
lines.add('Rename:{},{}\n'.format(dest, source))
- with open(apk_info_path, 'w') as info_file:
+ with build_utils.AtomicOutput(apk_info_path) as info_file:
info_file.writelines(sorted(lines))
diff --git a/chromium/build/android/gyp/create_app_bundle_minimal_apks.py b/chromium/build/android/gyp/create_app_bundle_minimal_apks.py
new file mode 100755
index 00000000000..f01691e418f
--- /dev/null
+++ b/chromium/build/android/gyp/create_app_bundle_minimal_apks.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Creates an .apks from an .aab with only English strings."""
+
+import argparse
+import os
+import sys
+
+sys.path.append(
+ os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)))
+from pylib.utils import app_bundle_utils
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument(
+ '--bundle', required=True, help='Path to input .aab file.')
+ parser.add_argument(
+ '--output', required=True, help='Path to output .apks file.')
+ parser.add_argument('--aapt2-path', required=True, help='Path to aapt2.')
+ parser.add_argument(
+ '--keystore-path', required=True, help='Path to keystore.')
+ parser.add_argument(
+ '--keystore-password', required=True, help='Keystore password.')
+ parser.add_argument(
+ '--keystore-name', required=True, help='Key name within keystore')
+
+ args = parser.parse_args()
+
+ app_bundle_utils.GenerateBundleApks(
+ args.bundle,
+ args.output,
+ args.aapt2_path,
+ args.keystore_path,
+ args.keystore_password,
+ args.keystore_name,
+ minimal=True,
+ check_for_noop=False)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/build/android/gyp/create_app_bundle_minimal_apks.pydeps b/chromium/build/android/gyp/create_app_bundle_minimal_apks.pydeps
new file mode 100644
index 00000000000..7cf09fdc174
--- /dev/null
+++ b/chromium/build/android/gyp/create_app_bundle_minimal_apks.pydeps
@@ -0,0 +1,11 @@
+# Generated by running:
+# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_app_bundle_minimal_apks.pydeps build/android/gyp/create_app_bundle_minimal_apks.py
+../../gn_helpers.py
+../pylib/__init__.py
+../pylib/utils/__init__.py
+../pylib/utils/app_bundle_utils.py
+bundletool.py
+create_app_bundle_minimal_apks.py
+util/__init__.py
+util/build_utils.py
+util/md5_check.py
diff --git a/chromium/build/android/gyp/create_size_info_files.py b/chromium/build/android/gyp/create_size_info_files.py
new file mode 100755
index 00000000000..5b248e41956
--- /dev/null
+++ b/chromium/build/android/gyp/create_size_info_files.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Creates size-info/*.info files used by SuperSize."""
+
+import argparse
+import os
+import sys
+import zipfile
+
+from util import build_utils
+from util import jar_info_utils
+from util import md5_check
+
+
+def _MergeResInfoFiles(res_info_path, info_paths):
+ # Concatenate them all.
+ # only_if_changed=False since no build rules depend on this as an input.
+ with build_utils.AtomicOutput(res_info_path, only_if_changed=False) as dst:
+ for p in info_paths:
+ with open(p) as src:
+ dst.write(src.read())
+
+
+def _PakInfoPathsForAssets(assets):
+ return [f.split(':')[0] + '.info' for f in assets if f.endswith('.pak')]
+
+
+def _MergePakInfoFiles(merged_path, pak_infos):
+ info_lines = set()
+ for pak_info_path in pak_infos:
+ with open(pak_info_path, 'r') as src_info_file:
+ info_lines.update(src_info_file.readlines())
+ # only_if_changed=False since no build rules depend on this as an input.
+ with build_utils.AtomicOutput(merged_path, only_if_changed=False) as f:
+ f.writelines(sorted(info_lines))
+
+
+def _FullJavaNameFromClassFilePath(path):
+ # Input: base/android/java/src/org/chromium/Foo.class
+ # Output: base.android.java.src.org.chromium.Foo
+ if not path.endswith('.class'):
+ return ''
+ path = os.path.splitext(path)[0]
+ parts = []
+ while path:
+ # Use split to be platform independent.
+ head, tail = os.path.split(path)
+ path = head
+ parts.append(tail)
+ parts.reverse() # Package comes first
+ return '.'.join(parts)
+
+
+def _MergeJarInfoFiles(output, inputs):
+ """Merge several .jar.info files to generate an .apk.jar.info.
+
+ Args:
+ output: output file path.
+ inputs: List of .info.jar or .jar files.
+ """
+ info_data = dict()
+ for path in inputs:
+ # android_java_prebuilt adds jar files in the src directory (relative to
+ # the output directory, usually ../../third_party/example.jar).
+ # android_aar_prebuilt collects jar files in the aar file and uses the
+ # java_prebuilt rule to generate gen/example/classes.jar files.
+ # We scan these prebuilt jars to parse each class path for the FQN. This
+ # allows us to later map these classes back to their respective src
+ # directories.
+ # TODO(agrieve): This should probably also check that the mtime of the .info
+ # is newer than that of the .jar, or change prebuilts to always output
+ # .info files so that they always exist (and change the depfile to
+ # depend directly on them).
+ if path.endswith('.info'):
+ info_data.update(jar_info_utils.ParseJarInfoFile(path))
+ else:
+ with zipfile.ZipFile(path) as zip_info:
+ for name in zip_info.namelist():
+ fully_qualified_name = _FullJavaNameFromClassFilePath(name)
+ if fully_qualified_name:
+ info_data[fully_qualified_name] = '{}/{}'.format(path, name)
+
+ # only_if_changed=False since no build rules depend on this as an input.
+ with build_utils.AtomicOutput(output, only_if_changed=False) as f:
+ jar_info_utils.WriteJarInfoFile(f, info_data)
+
+
+def _FindJarInputs(jar_paths):
+ ret = []
+ for jar_path in jar_paths:
+ jar_info_path = jar_path + '.info'
+ if os.path.exists(jar_info_path):
+ ret.append(jar_info_path)
+ else:
+ ret.append(jar_path)
+ return ret
+
+
+def main(args):
+ args = build_utils.ExpandFileArgs(args)
+ parser = argparse.ArgumentParser(description=__doc__)
+ build_utils.AddDepfileOption(parser)
+ parser.add_argument(
+ '--jar-info-path', required=True, help='Output .jar.info file')
+ parser.add_argument(
+ '--pak-info-path', required=True, help='Output .pak.info file')
+ parser.add_argument(
+ '--res-info-path', required=True, help='Output .res.info file')
+ parser.add_argument(
+ '--jar-files',
+ required=True,
+ action='append',
+ help='GN-list of .jar file paths')
+ parser.add_argument(
+ '--assets',
+ required=True,
+ action='append',
+ help='GN-list of files to add as assets in the form '
+ '"srcPath:zipPath", where ":zipPath" is optional.')
+ parser.add_argument(
+ '--uncompressed-assets',
+ required=True,
+ action='append',
+ help='Same as --assets, except disables compression.')
+ parser.add_argument(
+ '--resource-apk',
+ dest='resource_apks',
+ required=True,
+ action='append',
+ help='An .ap_ file built using aapt')
+
+ options = parser.parse_args(args)
+
+ options.jar_files = build_utils.ParseGnList(options.jar_files)
+ options.assets = build_utils.ParseGnList(options.assets)
+ options.uncompressed_assets = build_utils.ParseGnList(
+ options.uncompressed_assets)
+
+ jar_inputs = _FindJarInputs(set(options.jar_files))
+ pak_inputs = _PakInfoPathsForAssets(options.assets +
+ options.uncompressed_assets)
+ res_inputs = [p + '.info' for p in options.resource_apks]
+
+ # Don't bother re-running if no .info files have changed (saves ~250ms).
+ md5_check.CallAndRecordIfStale(
+ lambda: _MergeJarInfoFiles(options.jar_info_path, jar_inputs),
+ input_paths=jar_inputs,
+ output_paths=[options.jar_info_path])
+
+ # Always recreate these (just as fast as md5 checking them).
+ _MergePakInfoFiles(options.pak_info_path, pak_inputs)
+ _MergeResInfoFiles(options.res_info_path, res_inputs)
+
+ all_inputs = jar_inputs + pak_inputs + res_inputs
+ build_utils.WriteDepfile(
+ options.depfile,
+ options.jar_info_path,
+ inputs=all_inputs,
+ add_pydeps=False)
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/chromium/build/android/gyp/create_size_info_files.pydeps b/chromium/build/android/gyp/create_size_info_files.pydeps
new file mode 100644
index 00000000000..4ab7f94ea60
--- /dev/null
+++ b/chromium/build/android/gyp/create_size_info_files.pydeps
@@ -0,0 +1,8 @@
+# Generated by running:
+# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_size_info_files.pydeps build/android/gyp/create_size_info_files.py
+../../gn_helpers.py
+create_size_info_files.py
+util/__init__.py
+util/build_utils.py
+util/jar_info_utils.py
+util/md5_check.py
diff --git a/chromium/build/android/gyp/javac.py b/chromium/build/android/gyp/javac.py
index 8ad9bb7ebf0..e8ca89ab2fd 100755
--- a/chromium/build/android/gyp/javac.py
+++ b/chromium/build/android/gyp/javac.py
@@ -266,9 +266,6 @@ def _CreateInfoFile(java_files, jar_path, chromium_code, srcjar_files,
This maps fully qualified names for classes to either the java file that they
are defined in or the path of the srcjar that they came from.
-
- For apks this also produces a coalesced .apk.jar.info file combining all the
- .jar.info files of its transitive dependencies.
"""
output_path = jar_path + '.info'
logging.info('Start creating info file: %s', output_path)
@@ -290,7 +287,7 @@ def _CreateInfoFile(java_files, jar_path, chromium_code, srcjar_files,
all_info_data[fully_qualified_name] = java_file
logging.info('Writing info file: %s', output_path)
with build_utils.AtomicOutput(output_path) as f:
- jar_info_utils.WriteJarInfoFile(f.name, all_info_data, srcjar_files)
+ jar_info_utils.WriteJarInfoFile(f, all_info_data, srcjar_files)
logging.info('Completed info file: %s', output_path)
@@ -471,13 +468,6 @@ def _OnStaleMd5(changes, options, javac_cmd, java_files, classpath_inputs,
logging.info('Completed all steps in _OnStaleMd5')
-def _ParseAndFlattenGnLists(gn_lists):
- ret = []
- for arg in gn_lists:
- ret.extend(build_utils.ParseGnList(arg))
- return ret
-
-
def _ParseOptions(argv):
parser = optparse.OptionParser()
build_utils.AddDepfileOption(parser)
@@ -561,13 +551,13 @@ def _ParseOptions(argv):
options, args = parser.parse_args(argv)
build_utils.CheckOptions(options, parser, required=('jar_path',))
- options.bootclasspath = _ParseAndFlattenGnLists(options.bootclasspath)
- options.full_classpath = _ParseAndFlattenGnLists(options.full_classpath)
- options.interface_classpath = _ParseAndFlattenGnLists(
+ options.bootclasspath = build_utils.ParseGnList(options.bootclasspath)
+ options.full_classpath = build_utils.ParseGnList(options.full_classpath)
+ options.interface_classpath = build_utils.ParseGnList(
options.interface_classpath)
- options.processorpath = _ParseAndFlattenGnLists(options.processorpath)
- options.processors = _ParseAndFlattenGnLists(options.processors)
- options.java_srcjars = _ParseAndFlattenGnLists(options.java_srcjars)
+ options.processorpath = build_utils.ParseGnList(options.processorpath)
+ options.processors = build_utils.ParseGnList(options.processors)
+ options.java_srcjars = build_utils.ParseGnList(options.java_srcjars)
if options.java_version == '1.8' and options.bootclasspath:
# Android's boot jar doesn't contain all java 8 classes.
diff --git a/chromium/build/android/gyp/merge_jar_info_files.py b/chromium/build/android/gyp/merge_jar_info_files.py
deleted file mode 100755
index e6160f68469..00000000000
--- a/chromium/build/android/gyp/merge_jar_info_files.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Merges .jar.info files into one for APKs."""
-
-import argparse
-import os
-import shutil
-import sys
-import tempfile
-import zipfile
-
-from util import build_utils
-from util import jar_info_utils
-
-
-def _FullJavaNameFromClassFilePath(path):
- # Input: base/android/java/src/org/chromium/Foo.class
- # Output: base.android.java.src.org.chromium.Foo
- if not path.endswith('.class'):
- return ''
- path = os.path.splitext(path)[0]
- parts = []
- while path:
- # Use split to be platform independent.
- head, tail = os.path.split(path)
- path = head
- parts.append(tail)
- parts.reverse() # Package comes first
- return '.'.join(parts)
-
-
-def _MergeInfoFiles(output, jar_paths):
- """Merge several .jar.info files to generate an .apk.jar.info.
-
- Args:
- output: output file path.
- jar_paths: List of .jar file paths for the target apk.
- """
- info_data = dict()
- for jar_path in jar_paths:
- # android_java_prebuilt adds jar files in the src directory (relative to
- # the output directory, usually ../../third_party/example.jar).
- # android_aar_prebuilt collects jar files in the aar file and uses the
- # java_prebuilt rule to generate gen/example/classes.jar files.
- # We scan these prebuilt jars to parse each class path for the FQN. This
- # allows us to later map these classes back to their respective src
- # directories.
- jar_info_path = jar_path + '.info'
- # TODO(agrieve): This should probably also check that the mtime of the .info
- # is newer than that of the .jar, or change prebuilts to always output
- # .info files so that they always exist (and change the depfile to
- # depend directly on them).
- if os.path.exists(jar_info_path):
- info_data.update(jar_info_utils.ParseJarInfoFile(jar_path + '.info'))
- else:
- with zipfile.ZipFile(jar_path) as zip_info:
- for path in zip_info.namelist():
- fully_qualified_name = _FullJavaNameFromClassFilePath(path)
- if fully_qualified_name:
- info_data[fully_qualified_name] = '{}/{}'.format(jar_path, path)
-
- jar_info_utils.WriteJarInfoFile(output, info_data)
-
-
-def main(args):
- args = build_utils.ExpandFileArgs(args)
- parser = argparse.ArgumentParser(description=__doc__)
- build_utils.AddDepfileOption(parser)
- parser.add_argument('--output', required=True,
- help='Output .apk.jar.info file')
- parser.add_argument('--apk-jar-file', required=True,
- help='Path to main .jar file for this APK.')
- parser.add_argument('--dep-jar-files', required=True,
- help='GN-list of dependent .jar file paths')
-
- options = parser.parse_args(args)
- options.dep_jar_files = build_utils.ParseGnList(options.dep_jar_files)
- jar_files = [ options.apk_jar_file ] + options.dep_jar_files
-
- def _OnStaleMd5():
- with tempfile.NamedTemporaryFile() as tmp_file:
- _MergeInfoFiles(tmp_file.name, jar_files)
- shutil.move(tmp_file.name, options.output)
- tmp_file.delete = False
-
- build_utils.CallAndWriteDepfileIfStale(
- _OnStaleMd5, options,
- input_paths=jar_files,
- output_paths=[options.output],
- depfile_deps=jar_files,
- add_pydeps=False)
-
-
-if __name__ == '__main__':
- main(sys.argv[1:])
diff --git a/chromium/build/android/gyp/merge_jar_info_files.pydeps b/chromium/build/android/gyp/merge_jar_info_files.pydeps
deleted file mode 100644
index 710091c42fa..00000000000
--- a/chromium/build/android/gyp/merge_jar_info_files.pydeps
+++ /dev/null
@@ -1,8 +0,0 @@
-# Generated by running:
-# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/merge_jar_info_files.pydeps build/android/gyp/merge_jar_info_files.py
-../../gn_helpers.py
-merge_jar_info_files.py
-util/__init__.py
-util/build_utils.py
-util/jar_info_utils.py
-util/md5_check.py
diff --git a/chromium/build/android/gyp/util/build_utils.py b/chromium/build/android/gyp/util/build_utils.py
index b5fd17ae543..ad26224673e 100644
--- a/chromium/build/android/gyp/util/build_utils.py
+++ b/chromium/build/android/gyp/util/build_utils.py
@@ -83,24 +83,33 @@ def ReadBuildVars(path):
return dict(l.rstrip().split('=', 1) for l in f)
-def ParseGnList(gn_string):
- """Converts a command-line parameter into a list.
+def ParseGnList(value):
+ """Converts a "GN-list" command-line parameter into a list.
- If the input starts with a '[' it is assumed to be a GN-formatted list and
- it will be parsed accordingly. When empty an empty list will be returned.
- Otherwise, the parameter will be treated as a single raw string (not
- GN-formatted in that it's not assumed to have literal quotes that must be
- removed) and a list will be returned containing that string.
+ Conversions handled:
+ * None -> []
+ * '' -> []
+ * 'asdf' -> ['asdf']
+ * '["a", "b"]' -> ['a', 'b']
+ * ['["a", "b"]', 'c'] -> ['a', 'b', 'c'] (flattened list)
The common use for this behavior is in the Android build where things can
take lists of @FileArg references that are expanded via ExpandFileArgs.
"""
- if gn_string.startswith('['):
- parser = gn_helpers.GNValueParser(gn_string)
- return parser.ParseList()
- if len(gn_string):
- return [ gn_string ]
- return []
+ # Convert None to [].
+ if not value:
+ return []
+ # Convert a list of GN lists to a flattened list.
+ if isinstance(value, list):
+ ret = []
+ for arg in value:
+ ret.extend(ParseGnList(arg))
+ return ret
+ # Convert normal GN list.
+ if value.startswith('['):
+ return gn_helpers.GNValueParser(value).ParseList()
+ # Convert a single string value to a list.
+ return [value]
def CheckOptions(options, parser, required=None):
diff --git a/chromium/build/android/gyp/util/jar_info_utils.py b/chromium/build/android/gyp/util/jar_info_utils.py
index 987ee9dcf14..677e4e42616 100644
--- a/chromium/build/android/gyp/util/jar_info_utils.py
+++ b/chromium/build/android/gyp/util/jar_info_utils.py
@@ -32,21 +32,20 @@ def ParseJarInfoFile(info_path):
return info_data
-def WriteJarInfoFile(info_path, info_data, source_file_map=None):
+def WriteJarInfoFile(output_obj, info_data, source_file_map=None):
"""Generate a .jar.info file from a given dictionary.
Args:
- info_path: output file path.
+ output_obj: output file object.
info_data: a mapping of fully qualified Java class names to filepaths.
source_file_map: an optional mapping from java source file paths to the
corresponding source .srcjar. This is because info_data may contain the
path of Java source files that where extracted from an .srcjar into a
temporary location.
"""
- with open(info_path, 'w') as info_file:
- for fully_qualified_name, path in info_data.iteritems():
- if source_file_map and path in source_file_map:
- path = source_file_map[path]
- assert not path.startswith('/tmp'), (
- 'Java file path should not be in temp dir: {}'.format(path))
- info_file.write('{},{}\n'.format(fully_qualified_name, path))
+ for fully_qualified_name, path in sorted(info_data.iteritems()):
+ if source_file_map and path in source_file_map:
+ path = source_file_map[path]
+ assert not path.startswith('/tmp'), (
+ 'Java file path should not be in temp dir: {}'.format(path))
+ output_obj.write('{},{}\n'.format(fully_qualified_name, path))
diff --git a/chromium/build/android/gyp/write_build_config.py b/chromium/build/android/gyp/write_build_config.py
index 7427845ddd5..7050374f1ff 100755
--- a/chromium/build/android/gyp/write_build_config.py
+++ b/chromium/build/android/gyp/write_build_config.py
@@ -1417,6 +1417,13 @@ def main(argv):
c['main_class'] for c in processor_deps.Direct()]
deps_info['javac_full_classpath'] = javac_full_classpath
deps_info['javac_full_interface_classpath'] = javac_full_interface_classpath
+ elif options.type == 'android_app_bundle':
+ # bundles require javac_full_classpath to create .aab.jar.info.
+ javac_full_classpath = set()
+ for d in deps.Direct('android_app_bundle_module'):
+ javac_full_classpath.update(p for p in d['javac_full_classpath'])
+ javac_full_classpath.add(d['jar_path'])
+ deps_info['javac_full_classpath'] = sorted(javac_full_classpath)
if options.type in ('android_apk', 'dist_jar', 'java_binary', 'junit_binary',
'android_app_bundle_module', 'android_app_bundle'):
diff --git a/chromium/build/android/pylib/utils/app_bundle_utils.py b/chromium/build/android/pylib/utils/app_bundle_utils.py
index f4858f3c497..2a5e023367c 100644
--- a/chromium/build/android/pylib/utils/app_bundle_utils.py
+++ b/chromium/build/android/pylib/utils/app_bundle_utils.py
@@ -2,9 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import json
import logging
import os
+import re
import sys
+import tempfile
+import zipfile
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'gyp'))
@@ -12,9 +16,36 @@ from util import build_utils
from util import md5_check
import bundletool
-def GenerateBundleApks(bundle_path, bundle_apks_path, aapt2_path,
- keystore_path, keystore_password, keystore_alias,
- universal):
+
+_ALL_ABIS = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
+
+
+def _CreateMinimalDeviceSpec(bundle_path):
+ # Could also use "bundletool dump resources", but reading directly is faster.
+ with zipfile.ZipFile(bundle_path) as f:
+ manifest_data = f.read('base/manifest/AndroidManifest.xml')
+ min_sdk_version = int(
+ re.search(r'minSdkVersion.*?(\d+)', manifest_data).group(1))
+
+ # Setting sdkVersion=minSdkVersion prevents multiple per-minSdkVersion .apk
+ # files from being created within the .apks file.
+ return {
+ 'screenDensity': 1000, # Ignored since we don't split on density.
+ 'sdkVersion': min_sdk_version,
+ 'supportedAbis': _ALL_ABIS, # Our .aab files are already split on abi.
+ 'supportedLocales': ['en'],
+ }
+
+
+def GenerateBundleApks(bundle_path,
+ bundle_apks_path,
+ aapt2_path,
+ keystore_path,
+ keystore_password,
+ keystore_alias,
+ universal=False,
+ minimal=False,
+ check_for_noop=True):
"""Generate an .apks archive from a an app bundle if needed.
Args:
@@ -27,46 +58,54 @@ def GenerateBundleApks(bundle_path, bundle_apks_path, aapt2_path,
keystore_alias: Keystore signing key alias.
universal: Whether to create a single APK that contains the contents of all
modules.
+ minimal: Create the minimal set of apks possible (english-only).
+ check_for_noop: Use md5_check to short-circuit when inputs have not changed.
"""
- # NOTE: BUNDLETOOL_JAR_PATH is added to input_strings, rather than
- # input_paths, to speed up MD5 computations by about 400ms (the .jar file
- # contains thousands of class files which are checked independently,
- # resulting in an .md5.stamp of more than 60000 lines!).
- input_paths = [
- bundle_path,
- aapt2_path,
- keystore_path
- ]
- input_strings = [
- keystore_password,
- keystore_alias,
- bundletool.BUNDLETOOL_JAR_PATH,
- # NOTE: BUNDLETOOL_VERSION is already part of BUNDLETOOL_JAR_PATH, but
- # it's simpler to assume that this may not be the case in the future.
- bundletool.BUNDLETOOL_VERSION
- ]
- output_paths = [bundle_apks_path]
+ device_spec = None
+ if minimal:
+ device_spec = _CreateMinimalDeviceSpec(bundle_path)
def rebuild():
- logging.info('Building %s', os.path.basename(bundle_apks_path))
- with build_utils.AtomicOutput(bundle_apks_path) as tmp_apks:
+ logging.info('Building %s', bundle_apks_path)
+ with tempfile.NamedTemporaryFile(suffix='.json') as spec_file, \
+ build_utils.AtomicOutput(bundle_apks_path, only_if_changed=False) as f:
cmd_args = [
- 'java', '-jar', bundletool.BUNDLETOOL_JAR_PATH, 'build-apks',
+ 'build-apks',
'--aapt2=%s' % aapt2_path,
- '--output=%s' % tmp_apks.name,
+ '--output=%s' % f.name,
'--bundle=%s' % bundle_path,
'--ks=%s' % keystore_path,
'--ks-pass=pass:%s' % keystore_password,
'--ks-key-alias=%s' % keystore_alias,
'--overwrite',
]
+ if device_spec:
+ json.dump(device_spec, spec_file)
+ spec_file.flush()
+ cmd_args += ['--device-spec=' + spec_file.name]
if universal:
cmd_args += ['--mode=universal']
+ bundletool.RunBundleTool(cmd_args)
- build_utils.CheckOutput(cmd_args)
-
- md5_check.CallAndRecordIfStale(
- rebuild,
- input_paths=input_paths,
- input_strings=input_strings,
- output_paths=output_paths)
+ if check_for_noop:
+ # NOTE: BUNDLETOOL_JAR_PATH is added to input_strings, rather than
+ # input_paths, to speed up MD5 computations by about 400ms (the .jar file
+ # contains thousands of class files which are checked independently,
+ # resulting in an .md5.stamp of more than 60000 lines!).
+ input_paths = [bundle_path, aapt2_path, keystore_path]
+ input_strings = [
+ keystore_password,
+ keystore_alias,
+ bundletool.BUNDLETOOL_JAR_PATH,
+ # NOTE: BUNDLETOOL_VERSION is already part of BUNDLETOOL_JAR_PATH, but
+ # it's simpler to assume that this may not be the case in the future.
+ bundletool.BUNDLETOOL_VERSION,
+ device_spec,
+ ]
+ md5_check.CallAndRecordIfStale(
+ rebuild,
+ input_paths=input_paths,
+ input_strings=input_strings,
+ output_paths=[bundle_apks_path])
+ else:
+ rebuild()
diff --git a/chromium/build/android/resource_sizes.py b/chromium/build/android/resource_sizes.py
index 3901c716b7d..c9869623693 100755
--- a/chromium/build/android/resource_sizes.py
+++ b/chromium/build/android/resource_sizes.py
@@ -3,7 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""Reports binary size and static initializer metrics for an APK.
+"""Reports binary size metrics for an APK.
More information at //docs/speed/binary_size/metrics.md.
"""
@@ -20,6 +20,7 @@ import posixpath
import re
import struct
import sys
+import tempfile
import zipfile
import zlib
@@ -103,8 +104,6 @@ _BASE_CHART = {
'trace_rerun_options': [],
'charts': {}
}
-_DUMP_STATIC_INITIALIZERS_PATH = os.path.join(
- host_paths.DIR_SOURCE_ROOT, 'tools', 'linux', 'dump-static-initializers.py')
# Macro definitions look like (something, 123) when
# enable_resource_whitelist_generation=true.
_RC_HEADER_RE = re.compile(r'^#define (?P<name>\w+).* (?P<id>\d+)\)?$')
@@ -173,13 +172,6 @@ def _CreateSectionNameSizeMap(so_path, tool_prefix):
return section_sizes
-def _ParseLibBuildId(so_path, tool_prefix):
- """Returns the Build ID of the given native library."""
- stdout = _RunReadelf(so_path, ['-n'], tool_prefix)
- match = re.search(r'Build ID: (\w+)', stdout)
- return match.group(1) if match else None
-
-
def _ParseManifestAttributes(apk_path):
# Check if the manifest specifies whether or not to extract native libs.
skip_extract_lib = False
@@ -196,46 +188,6 @@ def _ParseManifestAttributes(apk_path):
return sdk_version, skip_extract_lib
-def CountStaticInitializers(so_path, tool_prefix):
- # Mostly copied from //infra/scripts/legacy/scripts/slave/chromium/sizes.py.
- def get_elf_section_size(readelf_stdout, section_name):
- # Matches: .ctors PROGBITS 000000000516add0 5169dd0 000010 00 WA 0 0 8
- match = re.search(r'\.%s.*$' % re.escape(section_name),
- readelf_stdout, re.MULTILINE)
- if not match:
- return (False, -1)
- size_str = re.split(r'\W+', match.group(0))[5]
- return (True, int(size_str, 16))
-
- # Find the number of files with at least one static initializer.
- # First determine if we're 32 or 64 bit
- stdout = _RunReadelf(so_path, ['-h'], tool_prefix)
- elf_class_line = re.search('Class:.*$', stdout, re.MULTILINE).group(0)
- elf_class = re.split(r'\W+', elf_class_line)[1]
- if elf_class == 'ELF32':
- word_size = 4
- else:
- word_size = 8
-
- # Then find the number of files with global static initializers.
- # NOTE: this is very implementation-specific and makes assumptions
- # about how compiler and linker implement global static initializers.
- si_count = 0
- stdout = _RunReadelf(so_path, ['-SW'], tool_prefix)
- has_init_array, init_array_size = get_elf_section_size(stdout, 'init_array')
- if has_init_array:
- si_count = init_array_size / word_size
- si_count = max(si_count, 0)
- return si_count
-
-
-def GetStaticInitializers(so_path, tool_prefix):
- output = cmd_helper.GetCmdOutput([_DUMP_STATIC_INITIALIZERS_PATH, '-d',
- so_path, '-t', tool_prefix])
- summary = re.search(r'Found \d+ static initializers in (\d+) files.', output)
- return output.splitlines()[:-1], int(summary.group(1))
-
-
def _NormalizeLanguagePaks(translations, normalized_apk_size, factor):
english_pak = translations.FindByPattern(r'.*/en[-_][Uu][Ss]\.l?pak')
num_translations = translations.GetNumEntries()
@@ -345,8 +297,7 @@ class _FileGroup(object):
return self.ComputeExtractedSize() + self.ComputeZippedSize()
-def GenerateApkAnalysis(apk_filename, tool_prefix, out_dir,
- unknown_handler=None):
+def _DoApkAnalysis(apk_filename, is_bundle, tool_prefix, out_dir, report_func):
"""Analyse APK to determine size contributions of different file classes."""
file_groups = []
@@ -449,20 +400,22 @@ def GenerateApkAnalysis(apk_filename, tool_prefix, out_dir,
total_install_size += extracted_size
zip_overhead -= actual_size
- yield ('Breakdown', group.name + ' size', actual_size, 'bytes')
- yield ('InstallBreakdown', group.name + ' size', int(install_size), 'bytes')
+ report_func('Breakdown', group.name + ' size', actual_size, 'bytes')
+ report_func('InstallBreakdown', group.name + ' size', int(install_size),
+ 'bytes')
# Only a few metrics are compressed in the first place.
# To avoid over-reporting, track uncompressed size only for compressed
# entries.
if uncompressed_size != actual_size:
- yield ('Uncompressed', group.name + ' size', uncompressed_size, 'bytes')
+ report_func('Uncompressed', group.name + ' size', uncompressed_size,
+ 'bytes')
if group is java_code and is_shared_apk:
# Updates are compiled using quicken, but system image uses speed-profile.
extracted_size = uncompressed_size * speed_profile_dex_multiplier
total_install_size_android_go += extracted_size
- yield ('InstallBreakdownGo', group.name + ' size',
- actual_size + extracted_size, 'bytes')
+ report_func('InstallBreakdownGo', group.name + ' size',
+ actual_size + extracted_size, 'bytes')
else:
total_install_size_android_go += extracted_size
@@ -470,23 +423,23 @@ def GenerateApkAnalysis(apk_filename, tool_prefix, out_dir,
# * 30 byte entry header + len(file name)
# * 46 byte central directory entry + len(file name)
# * 0-3 bytes for zipalign.
- yield ('Breakdown', 'Zip Overhead', zip_overhead, 'bytes')
- yield ('InstallSize', 'APK size', total_apk_size, 'bytes')
- yield ('InstallSize', 'Estimated installed size', int(total_install_size),
- 'bytes')
+ report_func('Breakdown', 'Zip Overhead', zip_overhead, 'bytes')
+ report_func('InstallSize', 'APK size', total_apk_size, 'bytes')
+ report_func('InstallSize', 'Estimated installed size',
+ int(total_install_size), 'bytes')
if is_shared_apk:
- yield ('InstallSize', 'Estimated installed size (Android Go)',
- int(total_install_size_android_go), 'bytes')
+ report_func('InstallSize', 'Estimated installed size (Android Go)',
+ int(total_install_size_android_go), 'bytes')
transfer_size = _CalculateCompressedSize(apk_filename)
- yield ('TransferSize', 'Transfer size (deflate)', transfer_size, 'bytes')
+ report_func('TransferSize', 'Transfer size (deflate)', transfer_size, 'bytes')
# Size of main dex vs remaining.
main_dex_info = java_code.FindByPattern('classes.dex')
if main_dex_info:
main_dex_size = main_dex_info.file_size
- yield ('Specifics', 'main dex size', main_dex_size, 'bytes')
+ report_func('Specifics', 'main dex size', main_dex_size, 'bytes')
secondary_size = java_code.ComputeUncompressedSize() - main_dex_size
- yield ('Specifics', 'secondary dex size', secondary_size, 'bytes')
+ report_func('Specifics', 'secondary dex size', secondary_size, 'bytes')
main_lib_info = native_code.FindLargest()
native_code_unaligned_size = 0
@@ -498,12 +451,12 @@ def GenerateApkAnalysis(apk_filename, tool_prefix, out_dir,
# Size of main .so vs remaining.
if lib_info == main_lib_info:
main_lib_size = lib_info.file_size
- yield ('Specifics', 'main lib size', main_lib_size, 'bytes')
+ report_func('Specifics', 'main lib size', main_lib_size, 'bytes')
secondary_size = native_code.ComputeUncompressedSize() - main_lib_size
- yield ('Specifics', 'other lib size', secondary_size, 'bytes')
+ report_func('Specifics', 'other lib size', secondary_size, 'bytes')
for metric_name, size in section_sizes.iteritems():
- yield ('MainLibInfo', metric_name, size, 'bytes')
+ report_func('MainLibInfo', metric_name, size, 'bytes')
# Main metric that we want to monitor for jumps.
normalized_apk_size = total_apk_size
@@ -521,56 +474,45 @@ def GenerateApkAnalysis(apk_filename, tool_prefix, out_dir,
# Normalized dex size: size within the zip + size on disk for Android Go
# devices (which ~= uncompressed dex size).
normalized_apk_size += java_code.ComputeUncompressedSize()
- # Avoid noise caused when strings change and translations haven't yet been
- # updated.
- num_translations = translations.GetNumEntries()
- num_stored_translations = stored_translations.GetNumEntries()
-
- if num_translations > 1:
- # Multipliers found by looking at MonochromePublic.apk and seeing how much
- # smaller en-US.pak is relative to the average locale.pak.
- normalized_apk_size = _NormalizeLanguagePaks(
- translations, normalized_apk_size, 1.17)
- if num_stored_translations > 1:
- normalized_apk_size = _NormalizeLanguagePaks(
- stored_translations, normalized_apk_size, 1.43)
- if num_translations + num_stored_translations > 1:
- if num_translations == 0:
- # WebView stores all locale paks uncompressed.
- num_arsc_translations = num_stored_translations
- else:
- # Monochrome has more configurations than Chrome since it includes
- # WebView (which supports more locales), but these should mostly be empty
- # so ignore them here.
- num_arsc_translations = num_translations
- normalized_apk_size += int(_NormalizeResourcesArsc(
- apk_filename, arsc.GetNumEntries(), num_arsc_translations, out_dir))
-
- yield ('Specifics', 'normalized apk size', normalized_apk_size, 'bytes')
+ if not is_bundle:
+ # Avoid noise caused when strings change and translations haven't yet been
+ # updated.
+ num_translations = translations.GetNumEntries()
+ num_stored_translations = stored_translations.GetNumEntries()
+
+ if num_translations > 1:
+ # Multipliers found by looking at MonochromePublic.apk and seeing how much
+ # smaller en-US.pak is relative to the average locale.pak.
+ normalized_apk_size = _NormalizeLanguagePaks(translations,
+ normalized_apk_size, 1.17)
+ if num_stored_translations > 1:
+ normalized_apk_size = _NormalizeLanguagePaks(stored_translations,
+ normalized_apk_size, 1.43)
+ if num_translations + num_stored_translations > 1:
+ if num_translations == 0:
+ # WebView stores all locale paks uncompressed.
+ num_arsc_translations = num_stored_translations
+ else:
+ # Monochrome has more configurations than Chrome since it includes
+ # WebView (which supports more locales), but these should mostly be
+ # empty so ignore them here.
+ num_arsc_translations = num_translations
+ normalized_apk_size += int(
+ _NormalizeResourcesArsc(apk_filename, arsc.GetNumEntries(),
+ num_arsc_translations, out_dir))
+
+ report_func('Specifics', 'normalized apk size', normalized_apk_size, 'bytes')
# The "file count" metric cannot be grouped with any other metrics when the
# end result is going to be uploaded to the perf dashboard in the HistogramSet
# format due to mixed units (bytes vs. zip entries) causing malformed
# summaries to be generated.
# TODO(https://crbug.com/903970): Remove this workaround if unit mixing is
# ever supported.
- yield ('FileCount', 'file count', len(apk_contents), 'zip entries')
-
- if unknown_handler is not None:
- for info in unknown.AllEntries():
- unknown_handler(info)
-
-
-def PrintApkAnalysis(apk_filename, tool_prefix, out_dir, chartjson=None):
- """Calls GenerateApkAnalysis() and report the value."""
+ report_func('FileCount', 'file count', len(apk_contents), 'zip entries')
- def PrintUnknown(info):
- print('Unknown entry: %s %d' % (info.filename, info.compress_size))
-
- title_prefix = os.path.basename(apk_filename) + '_'
- for data in GenerateApkAnalysis(apk_filename, tool_prefix, out_dir,
- PrintUnknown):
- title = title_prefix + data[0]
- perf_tests_results_helper.ReportPerfResult(chartjson, title, *data[1:])
+ for info in unknown.AllEntries():
+ sys.stderr.write(
+ 'Unknown entry: %s %d\n' % (info.filename, info.compress_size))
def _AnnotatePakResources(out_dir):
@@ -600,48 +542,6 @@ def _AnnotatePakResources(out_dir):
return id_name_map, id_header_map
-# This method also used by //build/android/gyp/assert_static_initializers.py
-def AnalyzeStaticInitializers(apk_filename, tool_prefix, dump_sis, out_dir,
- ignored_libs):
- # Static initializer counting mostly copies logic in
- # infra/scripts/legacy/scripts/slave/chromium/sizes.py.
- with zipfile.ZipFile(apk_filename) as z:
- so_files = [f for f in z.infolist()
- if f.filename.endswith('.so') and f.file_size > 0
- and os.path.basename(f.filename) not in ignored_libs]
- # Skip checking static initializers for 32 bit .so files when 64 bit .so files
- # are present since the 32 bit versions will be checked by bots that only
- # build the 32 bit version. This avoids the complexity of finding 32 bit .so
- # files in the output directory in 64 bit builds.
- has_64 = any('64' in f.filename for f in so_files)
- files_to_check = [f for f in so_files if not has_64 or '64' in f.filename]
-
- si_count = 0
- for f in files_to_check:
- with Unzip(apk_filename, filename=f.filename) as unzipped_so:
- si_count += CountStaticInitializers(unzipped_so, tool_prefix)
- if dump_sis:
- # Print count and list of SIs reported by dump-static-initializers.py.
- # Doesn't work well on all archs (particularly arm), which is why
- # the readelf method is used for tracking SI counts.
- _PrintDumpSIsCount(f.filename, unzipped_so, out_dir, tool_prefix)
- return si_count
-
-
-def _PrintDumpSIsCount(apk_so_name, unzipped_so, out_dir, tool_prefix):
- lib_name = os.path.basename(apk_so_name).replace('crazy.', '')
- so_with_symbols_path = os.path.join(out_dir, 'lib.unstripped', lib_name)
- if os.path.exists(so_with_symbols_path):
- _VerifyLibBuildIdsMatch(tool_prefix, unzipped_so, so_with_symbols_path)
- sis, _ = GetStaticInitializers(
- so_with_symbols_path, tool_prefix)
- for si in sis:
- print(si)
- else:
- raise Exception('Unstripped .so not found. Looked here: %s',
- so_with_symbols_path)
-
-
def _CalculateCompressedSize(file_path):
CHUNK_SIZE = 256 * 1024
compressor = zlib.compressobj()
@@ -653,7 +553,7 @@ def _CalculateCompressedSize(file_path):
return total_size
-def GenerateDexAnalysis(apk_filename):
+def _DoDexAnalysis(apk_filename, report_func):
sizes, total_size = method_count.ExtractSizesFromZip(apk_filename)
dex_metrics = method_count.CONTRIBUTORS_TO_DEX_CACHE
@@ -662,21 +562,13 @@ def GenerateDexAnalysis(apk_filename):
for key in dex_metrics:
cumulative_sizes[key] += classes_dex_sizes[key]
for key, label in dex_metrics.iteritems():
- yield ('Dex', label, cumulative_sizes[key], 'entries')
+ report_func('Dex', label, cumulative_sizes[key], 'entries')
- yield ('DexCache', 'DexCache', total_size, 'bytes')
+ report_func('DexCache', 'DexCache', total_size, 'bytes')
-def _PrintDexAnalysis(apk_filename, chartjson=None):
- title_prefix = os.path.basename(apk_filename) + '_'
- for data in GenerateDexAnalysis(apk_filename):
- title = title_prefix + data[0]
- perf_tests_results_helper.ReportPerfResult(chartjson, title, *data[1:])
-
-
-def _PrintPatchSizeEstimate(new_apk, builder, bucket, chartjson=None):
+def _PrintPatchSizeEstimate(new_apk, builder, bucket, report_func):
apk_name = os.path.basename(new_apk)
- title = apk_name + '_PatchSizeEstimate'
# Reference APK paths have spaces replaced by underscores.
builder = builder.replace(' ', '_')
old_apk = apk_downloader.MaybeDownloadApk(
@@ -688,12 +580,10 @@ def _PrintPatchSizeEstimate(new_apk, builder, bucket, chartjson=None):
tmp_name = os.path.join(tmp, 'patch.tmp')
bsdiff = apk_patch_size_estimator.calculate_bsdiff(
old_apk, new_apk, None, tmp_name)
- perf_tests_results_helper.ReportPerfResult(chartjson, title,
- 'BSDiff (gzipped)', bsdiff, 'bytes')
+ report_func('PatchSizeEstimate', 'BSDiff (gzipped)', bsdiff, 'bytes')
fbf = apk_patch_size_estimator.calculate_filebyfile(
old_apk, new_apk, None, tmp_name)
- perf_tests_results_helper.ReportPerfResult(chartjson, title,
- 'FileByFile (gzipped)', fbf, 'bytes')
+ report_func('PatchSizeEstimate', 'FileByFile (gzipped)', fbf, 'bytes')
@contextmanager
@@ -708,12 +598,6 @@ def Unzip(zip_file, filename=None):
yield unzipped_files[0]
-def _VerifyLibBuildIdsMatch(tool_prefix, *so_files):
- if len(set(_ParseLibBuildId(f, tool_prefix) for f in so_files)) > 1:
- raise Exception('Found differing build ids in output directory and apk. '
- 'Your output directory is likely stale.')
-
-
def _ConfigOutDirAndToolsPrefix(out_dir):
if out_dir:
constants.SetOutputDirectory(os.path.abspath(out_dir))
@@ -732,6 +616,25 @@ def _ConfigOutDirAndToolsPrefix(out_dir):
return out_dir, tool_prefix
+def _Analyze(apk_path, chartjson, args):
+ metric_prefix = os.path.basename(args.input) + '_'
+ metric_prefix = metric_prefix.replace('.minimal.apks', '.apk')
+
+ def report_func(title, *args):
+ # Do not add any new metrics without also documenting them in:
+ # //docs/speed/binary_size/metrics.md.
+ title = metric_prefix + title
+ perf_tests_results_helper.ReportPerfResult(chartjson, title, *args)
+
+ out_dir, tool_prefix = _ConfigOutDirAndToolsPrefix(args.out_dir)
+ is_bundle = args.input.endswith('.apks')
+ _DoApkAnalysis(apk_path, is_bundle, tool_prefix, out_dir, report_func)
+ _DoDexAnalysis(apk_path, report_func)
+ if args.estimate_patch_size:
+ _PrintPatchSizeEstimate(apk_path, args.reference_apk_builder,
+ args.reference_apk_bucket, report_func)
+
+
def main():
argparser = argparse.ArgumentParser(description='Print APK size metrics.')
argparser.add_argument('--min-pak-resource-size',
@@ -752,14 +655,7 @@ def main():
argparser.add_argument('--output-dir',
default='.',
help='Directory to save chartjson to.')
- argparser.add_argument('--dump-static-initializers',
- action='store_true',
- dest='dump_sis',
- help='Run dump-static-initializers.py to get the list'
- 'of static initializers (slow).')
- argparser.add_argument('--loadable_module',
- action='append',
- help='Use for libraries added via loadable_modules')
+ argparser.add_argument('--loadable_module', help='Obsolete (ignored).')
argparser.add_argument('--estimate-patch-size',
action='store_true',
help='Include patch size estimates. Useful for perf '
@@ -772,7 +668,7 @@ def main():
argparser.add_argument('--reference-apk-bucket',
default=apk_downloader.DEFAULT_BUCKET,
help='Storage bucket holding reference APKs.')
- argparser.add_argument('apk', help='APK file path.')
+ argparser.add_argument('input', help='Path to .apk or .apks file to measure.')
args = argparser.parse_args()
# TODO(bsheedy): Remove this once uses of --chartjson have been removed.
@@ -780,27 +676,17 @@ def main():
args.output_format = 'chartjson'
chartjson = _BASE_CHART.copy() if args.output_format else None
- out_dir, tool_prefix = _ConfigOutDirAndToolsPrefix(args.out_dir)
- if args.dump_sis and not out_dir:
- argparser.error(
- '--dump-static-initializers requires --chromium-output-directory')
-
- # Do not add any new metrics without also documenting them in:
- # //docs/speed/binary_size/metrics.md.
-
- PrintApkAnalysis(args.apk, tool_prefix, out_dir, chartjson=chartjson)
- _PrintDexAnalysis(args.apk, chartjson=chartjson)
- ignored_libs = args.loadable_module if args.loadable_module else []
-
- si_count = AnalyzeStaticInitializers(
- args.apk, tool_prefix, args.dump_sis, out_dir, ignored_libs)
- perf_tests_results_helper.ReportPerfResult(
- chartjson, 'StaticInitializersCount', 'count', si_count, 'count')
-
- if args.estimate_patch_size:
- _PrintPatchSizeEstimate(args.apk, args.reference_apk_builder,
- args.reference_apk_bucket, chartjson=chartjson)
+ if args.input.endswith('.apk'):
+ _Analyze(args.input, chartjson, args)
+ elif args.input.endswith('.apks'):
+ with tempfile.NamedTemporaryFile(suffix='.apk') as f:
+ with zipfile.ZipFile(args.input) as z:
+ f.write(z.read('splits/base-master.apk'))
+ f.flush()
+ _Analyze(f.name, chartjson, args)
+ else:
+ raise Exception('Unknown file type: ' + args.input)
if chartjson:
results_path = os.path.join(args.output_dir, 'results-chart.json')
diff --git a/chromium/build/config/android/internal_rules.gni b/chromium/build/config/android/internal_rules.gni
index ee4498abd03..e059dab0ac9 100644
--- a/chromium/build/config/android/internal_rules.gni
+++ b/chromium/build/config/android/internal_rules.gni
@@ -2316,40 +2316,70 @@ if (enable_java_templates) {
}
}
- # Create an apk.jar.info file by merging several .jar.info files into one.
+ # Create an .jar.info file by merging several .jar.info files into one.
#
# Variables:
- # apk_build_config: Path to APK's build config file. Used to extract the
+ # build_config: Path to APK's build config file. Used to extract the
# list of input .jar files from its dependencies.
- # output: Output file path.
+ # name: Name of the apk or app bundle (e.g. "Foo.apk").
+ # packaged_resources_path: Path to .ap_ file.
#
- template("create_apk_jar_info") {
- _output = invoker.output
- _build_config = invoker.apk_build_config
- _rebased_build_config = rebase_path(_build_config, root_build_dir)
+ template("create_size_info_files") {
action_with_pydeps(target_name) {
forward_variables_from(invoker,
[
"testonly",
"deps",
])
- script = "//build/android/gyp/merge_jar_info_files.py"
- inputs = [
- _build_config,
- ]
+ script = "//build/android/gyp/create_size_info_files.py"
+ _jar_info_path = "$root_build_dir/size-info/${invoker.name}.jar.info"
+ _pak_info_path = "$root_build_dir/size-info/${invoker.name}.pak.info"
+ _res_info_path = "$root_build_dir/size-info/${invoker.name}.res.info"
outputs = [
- _output,
+ _jar_info_path,
+ _pak_info_path,
+ _res_info_path,
]
depfile = "$target_gen_dir/$target_name.d"
args = [
"--depfile",
rebase_path(depfile, root_build_dir),
- "--output",
- rebase_path(_output, root_build_dir),
- "--apk-jar-file=@FileArg($_rebased_build_config:deps_info:jar_path)",
- "--dep-jar-files=@FileArg(" +
- "$_rebased_build_config:deps_info:javac_full_classpath)",
- ]
+ "--jar-info-path",
+ rebase_path(_jar_info_path, root_build_dir),
+ "--pak-info-path",
+ rebase_path(_pak_info_path, root_build_dir),
+ "--res-info-path",
+ rebase_path(_res_info_path, root_build_dir),
+ ]
+ _is_bundle = defined(invoker.module_build_configs)
+ if (_is_bundle) {
+ inputs = invoker.module_build_configs
+ foreach(_build_config, invoker.module_build_configs) {
+ _rebased_build_config = rebase_path(_build_config, root_build_dir)
+ args += [
+ "--jar-files=@FileArg($_rebased_build_config:deps_info:unprocessed_jar_path)",
+ "--jar-files=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)",
+ "--resource-apk=@FileArg($_rebased_build_config:deps_info:proto_resources_path)",
+ "--assets=@FileArg($_rebased_build_config:assets)",
+ "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)",
+ ]
+ }
+ } else {
+ inputs = [
+ invoker.build_config,
+ invoker.packaged_resources_path,
+ ]
+ _rebased_build_config =
+ rebase_path(invoker.build_config, root_build_dir)
+ args += [
+ "--jar-files=@FileArg($_rebased_build_config:deps_info:jar_path)",
+ "--jar-files=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)",
+ "--resource-apk",
+ rebase_path(invoker.packaged_resources_path, root_build_dir),
+ "--assets=@FileArg($_rebased_build_config:assets)",
+ "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)",
+ ]
+ }
}
}
@@ -2459,22 +2489,6 @@ if (enable_java_templates) {
# TODO(mlopatkin) We are relying on the fact that assets_build_config is
# an APK build_config.
args += [ "--java-resources=@FileArg($_rebased_build_config:java_resources_jars)" ]
-
- if (defined(invoker.apk_name)) {
- # The supersize tool will search in this directory for each apk.
- _apk_pak_info_path = "size-info/${invoker.apk_name}.apk.pak.info"
- _apk_res_info_path = "size-info/${invoker.apk_name}.apk.res.info"
- args += [
- "--apk-pak-info-path",
- _apk_pak_info_path,
- "--apk-res-info-path",
- _apk_res_info_path,
- ]
- outputs += [
- "$root_build_dir/$_apk_pak_info_path",
- "$root_build_dir/$_apk_res_info_path",
- ]
- }
}
if (defined(invoker.write_asset_list) && invoker.write_asset_list) {
args += [ "--write-asset-list" ]
diff --git a/chromium/build/config/android/rules.gni b/chromium/build/config/android/rules.gni
index aec451019b8..3c843ec157c 100644
--- a/chromium/build/config/android/rules.gni
+++ b/chromium/build/config/android/rules.gni
@@ -2643,21 +2643,29 @@ if (enable_java_templates) {
[ _native_libs_file_arg_dep ]
}
- # Generate .apk.jar.info files if needed.
- if (defined(invoker.name)) {
- _apk_jar_info_target = "${target_name}__apk_jar_info"
- create_apk_jar_info(_apk_jar_info_target) {
- output = "$root_build_dir/size-info/${invoker.name}.apk.jar.info"
- apk_build_config = _build_config
- deps = [
- ":$_build_config_target",
- ":$_java_target",
- ]
+ if (!_is_bundle_module) {
+ # Generate size-info/*.jar.info files.
+ if (defined(invoker.name)) {
+ # Create size info files for targets that care about size
+ # (have proguard enabled).
+ if (_proguard_enabled) {
+ _size_info_target = "${target_name}__size_info"
+ create_size_info_files(_size_info_target) {
+ name = "${invoker.name}.apk"
+ build_config = _build_config
+ packaged_resources_path = _packaged_resources_path
+ deps = _deps + [
+ ":$_build_config_target",
+ ":$_compile_resources_target",
+ ":$_java_target",
+ ]
+ }
+ _final_deps += [ ":$_size_info_target" ]
+ } else {
+ not_needed(invoker, [ "name" ])
+ }
}
- _deps += [ ":$_apk_jar_info_target" ]
- }
- if (!_is_bundle_module) {
_keystore_path = android_keystore_path
_keystore_name = android_keystore_name
_keystore_password = android_keystore_password
@@ -2686,9 +2694,6 @@ if (enable_java_templates) {
dex_path = _final_dex_path
load_library_from_apk = _load_library_from_apk
- # This is used to generate *.apk.pak.info files.
- apk_name = invoker.name
-
keystore_name = _keystore_name
keystore_path = _keystore_path
keystore_password = _keystore_password
@@ -3922,10 +3927,8 @@ if (enable_java_templates) {
# Make build config, which is required for synchronized proguarding.
_module_targets = []
- _module_build_config_targets = []
foreach(_module, _all_modules) {
_module_targets += [ _module.module_target ]
- _module_build_config_targets += [ _module.build_config_target ]
}
_build_config = "$target_gen_dir/${target_name}.build_config"
_rebased_build_config = rebase_path(_build_config, root_build_dir)
@@ -3939,6 +3942,7 @@ if (enable_java_templates) {
type = "android_app_bundle"
possible_config_deps = _module_targets + [ proguard_android_sdk_dep_ ]
build_config = _build_config
+ proguard_enabled = _proguard_enabled
}
if (_proguard_enabled) {
@@ -3953,8 +3957,7 @@ if (enable_java_templates) {
forward_variables_from(invoker, [ "proguard_jar_path" ])
build_config = _build_config
- deps = _module_targets + _module_build_config_targets +
- [ ":$_build_config_target" ]
+ deps = _module_targets + [ ":$_build_config_target" ]
output = _unsplit_dex_zip
}
@@ -4092,6 +4095,17 @@ if (enable_java_templates) {
}
}
+ # Create size info files for targets that care about size
+ # (have proguard enabled).
+ if (_proguard_enabled) {
+ _size_info_target = "${target_name}__size_info"
+ create_size_info_files(_size_info_target) {
+ name = "$_bundle_name.aab"
+ deps = _module_targets + [ ":$_build_config_target" ]
+ module_build_configs = _all_module_build_configs
+ }
+ }
+
# Generate a wrapper script for the bundle.
_android_aapt2_path = android_sdk_tools_bundle_aapt2
@@ -4102,7 +4116,6 @@ if (enable_java_templates) {
action_with_pydeps("${target_name}__wrapper_script") {
script = "//build/android/gyp/create_bundle_wrapper_script.py"
inputs = [
- "//build/android/gyp/bundletool.py",
_base_module_build_config,
]
outputs = [
@@ -4145,10 +4158,61 @@ if (enable_java_templates) {
}
group(target_name) {
- deps = [
+ public_deps = [
":${target_name}__bundle",
":${target_name}__wrapper_script",
]
+ if (defined(_size_info_target)) {
+ public_deps += [ ":$_size_info_target" ]
+ }
+ }
+ }
+
+ # Create an .apks file from an .aab file. The .apks file will contain the
+ # minimal set of .apk files needed for tracking binary size.
+ # The file will be created at "$bundle_path_without_extension.minimal.apks".
+ #
+ # Variables:
+ # bundle_path: Path to the input .aab file.
+ #
+ # Example:
+ # create_app_bundle_minimal_apks("minimal_apks") {
+ # deps = [
+ # ":bundle_target",
+ # ]
+ # bundle_path = "$root_build_dir/apks/Bundle.aab"
+ # }
+ template("create_app_bundle_minimal_apks") {
+ action_with_pydeps(target_name) {
+ forward_variables_from(invoker,
+ [
+ "deps",
+ "testonly",
+ ])
+ script = "//build/android/gyp/create_app_bundle_minimal_apks.py"
+ _dir = get_path_info(invoker.bundle_path, "dir")
+ _name = get_path_info(invoker.bundle_path, "name")
+ _output_path = "$_dir/$_name.minimal.apks"
+ outputs = [
+ _output_path,
+ ]
+ inputs = [
+ invoker.bundle_path,
+ ]
+ args = [
+ "--bundle",
+ rebase_path(invoker.bundle_path, root_build_dir),
+ "--output",
+ rebase_path(_output_path, root_build_dir),
+ "--aapt2-path",
+ rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir),
+ "--keystore-path",
+ rebase_path(android_keystore_path, root_build_dir),
+ "--keystore-name",
+ android_keystore_name,
+ "--keystore-password",
+ android_keystore_password,
+ ]
}
}
}
diff --git a/chromium/build/util/LASTCHANGE b/chromium/build/util/LASTCHANGE
index 6ab40dbb98f..590de91593e 100644
--- a/chromium/build/util/LASTCHANGE
+++ b/chromium/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=8cd51bd20244a019d86ed5092017a118e2ad962a-refs/branch-heads/3683@{#379}
+LASTCHANGE=4564075605dd87605df1f8c00bf7161c9c4eb41b-refs/branch-heads/3683@{#721}
diff --git a/chromium/build/util/LASTCHANGE.committime b/chromium/build/util/LASTCHANGE.committime
index 1d5565daa59..3e22592f58a 100644
--- a/chromium/build/util/LASTCHANGE.committime
+++ b/chromium/build/util/LASTCHANGE.committime
@@ -1 +1 @@
-1550022051 \ No newline at end of file
+1551663520 \ No newline at end of file
diff --git a/chromium/cc/layers/scrollbar_layer_impl_base.cc b/chromium/cc/layers/scrollbar_layer_impl_base.cc
index 24a855e2f84..768048fefa7 100644
--- a/chromium/cc/layers/scrollbar_layer_impl_base.cc
+++ b/chromium/cc/layers/scrollbar_layer_impl_base.cc
@@ -87,6 +87,12 @@ bool ScrollbarLayerImplBase::CanScrollOrientation() const {
const auto* scroll_node =
property_trees->scroll_tree.FindNodeFromElementId(scroll_element_id_);
DCHECK(scroll_node);
+ // TODO(bokan): Looks like we sometimes get here without a ScrollNode. It
+ // should be safe to just return false here (we don't use scroll_element_id_
+ // anywhere else) so we can merge the fix. Once merged, will investigate the
+ // underlying cause. https://crbug.com/924068.
+ if (!scroll_node)
+ return false;
if (orientation() == ScrollbarOrientation::HORIZONTAL) {
if (!scroll_node->user_scrollable_horizontal)
diff --git a/chromium/cc/paint/paint_op_reader.cc b/chromium/cc/paint/paint_op_reader.cc
index a8b777f7c22..1dcd199bd83 100644
--- a/chromium/cc/paint/paint_op_reader.cc
+++ b/chromium/cc/paint/paint_op_reader.cc
@@ -1002,7 +1002,7 @@ void PaintOpReader::ReadMergePaintFilter(
sk_sp<PaintFilter>* filter,
const base::Optional<PaintFilter::CropRect>& crop_rect) {
size_t input_count = 0;
- ReadSimple(&input_count);
+ ReadSize(&input_count);
// The minimum size for a serialized filter is 4 bytes (a zero uint32_t to
// indicate a null filter). Make sure the |input_count| doesn't exceed the
diff --git a/chromium/cc/paint/paint_op_writer.cc b/chromium/cc/paint/paint_op_writer.cc
index 72783966429..57884df1c0b 100644
--- a/chromium/cc/paint/paint_op_writer.cc
+++ b/chromium/cc/paint/paint_op_writer.cc
@@ -674,7 +674,7 @@ void PaintOpWriter::Write(const RecordPaintFilter& filter) {
}
void PaintOpWriter::Write(const MergePaintFilter& filter) {
- WriteSimple(filter.input_count());
+ WriteSize(filter.input_count());
for (size_t i = 0; i < filter.input_count(); ++i)
Write(filter.input_at(i));
}
diff --git a/chromium/cc/trees/layer_tree_host_impl.cc b/chromium/cc/trees/layer_tree_host_impl.cc
index 6a44080f309..2782b23d66c 100644
--- a/chromium/cc/trees/layer_tree_host_impl.cc
+++ b/chromium/cc/trees/layer_tree_host_impl.cc
@@ -5171,12 +5171,13 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
// UIResource will be copied into it.
std::unique_ptr<base::SharedMemory> shared_memory;
viz::SharedBitmapId shared_bitmap_id;
+ bool overlay_candidate = false;
if (layer_tree_frame_sink_->context_provider()) {
viz::ContextProvider* context_provider =
layer_tree_frame_sink_->context_provider();
const auto& caps = context_provider->ContextCapabilities();
- bool overlay_candidate =
+ overlay_candidate =
settings_.resource_settings.use_gpu_memory_buffer_resources &&
caps.texture_storage_image &&
viz::IsGpuMemoryBufferFormatSupported(format);
@@ -5287,7 +5288,8 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
->GenUnverifiedSyncToken();
transferable = viz::TransferableResource::MakeGLOverlay(
- mailbox, GL_LINEAR, texture_target, sync_token, upload_size, false);
+ mailbox, GL_LINEAR, texture_target, sync_token, upload_size,
+ overlay_candidate);
transferable.format = format;
} else {
mojo::ScopedSharedBufferHandle memory_handle =
diff --git a/chromium/chrome/VERSION b/chromium/chrome/VERSION
index ebfef3289f7..1c8737afe1c 100644
--- a/chromium/chrome/VERSION
+++ b/chromium/chrome/VERSION
@@ -1,4 +1,4 @@
MAJOR=73
MINOR=0
BUILD=3683
-PATCH=37
+PATCH=64
diff --git a/chromium/chrome/android/BUILD.gn b/chromium/chrome/android/BUILD.gn
index 78f1b99760d..ae0a70eda4a 100644
--- a/chromium/chrome/android/BUILD.gn
+++ b/chromium/chrome/android/BUILD.gn
@@ -5,6 +5,7 @@
import("//build/config/android/chrome_version.gni")
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
+import("//build/config/python.gni")
import("//build/util/process_version.gni")
import("//chrome/android/chrome_common_shared_library.gni")
import("//chrome/android/chrome_public_apk_tmpl.gni")
@@ -116,6 +117,9 @@ jinja_template("monochrome_public_bundle_android_manifest") {
"target_sdk_version=$android_sdk_version",
"webview_library=libmonochrome${bundle_library_suffix}.so",
]
+
+ # Override include_arcore_manifest_flag to true for bundles.
+ variables += [ "include_arcore_manifest_flag=true" ]
}
jinja_template("trichrome_library_android_manifest") {
@@ -1813,7 +1817,7 @@ if (enable_arcore && package_arcore) {
}
if (defined(expected_static_initializer_count)) {
- action("monochrome_static_initializers") {
+ action_with_pydeps("monochrome_static_initializers") {
script = "//build/android/gyp/assert_static_initializers.py"
inputs = [
"$root_build_dir/apks/MonochromePublic.apk",
@@ -1870,6 +1874,7 @@ if (modularize_vr) {
android_app_bundle("chrome_public_bundle") {
bundle_name = "ChromePublic"
base_module_target = ":chrome_public_base_bundle_module"
+ command_line_flags_file = "chrome-command-line"
if (!is_java_debug) {
proguard_enabled = true
}
@@ -1884,6 +1889,7 @@ android_app_bundle("chrome_public_bundle") {
android_app_bundle("chrome_modern_public_bundle") {
bundle_name = "ChromeModernPublic"
base_module_target = ":chrome_modern_public_base_bundle_module"
+ command_line_flags_file = "chrome-command-line"
if (!is_java_debug) {
proguard_enabled = true
}
@@ -1899,9 +1905,20 @@ android_app_bundle("chrome_modern_public_bundle") {
}
}
+if (is_official_build) {
+ # Used for binary size monitoring.
+ create_app_bundle_minimal_apks("chrome_modern_public_minimal_apks") {
+ deps = [
+ ":chrome_modern_public_bundle",
+ ]
+ bundle_path = "$root_build_dir/apks/ChromeModernPublic.aab"
+ }
+}
+
android_app_bundle("monochrome_public_bundle") {
bundle_name = "MonochromePublic"
base_module_target = ":monochrome_public_base_bundle_module"
+ command_line_flags_file = "chrome-command-line"
if (!is_java_debug) {
proguard_enabled = true
proguard_android_sdk_dep = webview_framework_dep
@@ -1925,3 +1942,13 @@ android_app_bundle("monochrome_public_bundle") {
]
}
}
+
+if (is_official_build) {
+ # Used for binary size monitoring.
+ create_app_bundle_minimal_apks("monochrome_public_minimal_apks") {
+ deps = [
+ ":monochrome_public_bundle",
+ ]
+ bundle_path = "$root_build_dir/apks/MonochromePublic.aab"
+ }
+}
diff --git a/chromium/chrome/android/java/strings/android_chrome_strings.grd b/chromium/chrome/android/java/strings/android_chrome_strings.grd
index 6f5f1587d6a..cb556e1bfc0 100644
--- a/chromium/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chromium/chrome/android/java/strings/android_chrome_strings.grd
@@ -3629,6 +3629,10 @@ However, you aren’t invisible. Going private doesn’t hide your browsing from
<message name="IDS_CONTACTS_PICKER_ALL_CONTACTS" desc="The label associated with the select all checkbox, indicating that all the contacts will be selected.">
All contacts
</message>
+ <message name="IDS_CONTACTS_PICKER_NO_CONTACTS_FOUND" desc="The label shown when no contacts are found (e.g. none exist on the device).">
+ No contacts found
+ </message>
+
<message name="IDS_CONTACTS_PICKER_MORE_DETAILS" desc="Label describing that the user has one or more telephone/emails (used for either). The leading space is a word separator, for those languages that use space as a separator.">
{DETAIL_COUNT, plural,
=1 { (+ 1 more)}
diff --git a/chromium/chrome/app/resources/chromium_strings_am.xtb b/chromium/chrome/app/resources/chromium_strings_am.xtb
index fae98a02edf..e026b82c9e4 100644
--- a/chromium/chrome/app/resources/chromium_strings_am.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_am.xtb
@@ -88,6 +88,7 @@
<translation id="378917192836375108">Chromium ድር ላይ ያለ ስልክ ቁጥር ጠቅ እንዲያደርጉትና በSkype እንዲደውሉበት ያስችልዎታል!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromiumን ወደ የእርስዎ የተግባር አሞሌ ያያይዙ</translation>
+<translation id="388648406173476553">Chromiumን ያብጁ እና ይቆጣጠሩ። የሆነ ነገር ትኩረትዎ ያስፈልገዋል - ለዝርዝሮች ጠቅ ያድርጉ።</translation>
<translation id="3889543394854987837">Chromiumን ለመክፈት እና ማሰስ ለመጀመር ስምዎን ጠቅ ያድርጉት።</translation>
<translation id="3898493977366060150">የድር አሰሳ በGoogle ዘመናዊ ይሆናል</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS በ1 ሰዓት ውስጥ ዳግም ይጀምራል}one{Chromium OS በ# ሰዓቶች ውስጥ ዳግም ይጀምራል}other{Chromium OS በ# ሰዓቶች ውስጥ ዳግም ይጀምራል}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ar.xtb b/chromium/chrome/app/resources/chromium_strings_ar.xtb
index 6d55ce6e45a..6a3a70b3a13 100644
--- a/chromium/chrome/app/resources/chromium_strings_ar.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ar.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">‏يتيح لك Chromium النقر على رقم هاتف على الويب والاتصال به باستخدام Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">‏تثبيت Chromium على شريط المهام</translation>
+<translation id="388648406173476553">‏تخصيص Chromium والتحكُّم فيه معلومات مهمة - انقر للحصول على التفاصيل.</translation>
<translation id="3889543394854987837">‏انقر على اسمك لفتح Chromium وبدء التصفح.</translation>
<translation id="3898493977366060150">‏تصفُح الويب من خلال ميزات Google الذكية</translation>
<translation id="3965668104013180445">{0,plural, =1{‏ستتم إعادة تشغيل نظام التشغيل Chromium خلال ساعة واحدة}zero{‏ستتم إعادة تشغيل نظام التشغيل Chromium خلال # ساعة}two{‏ستتم إعادة تشغيل نظام التشغيل Chromium خلال ساعتين (#)}few{‏ستتم إعادة تشغيل نظام التشغيل Chromium خلال # ساعات}many{‏ستتم إعادة تشغيل نظام التشغيل Chromium خلال # ساعةً}other{‏ستتم إعادة تشغيل نظام التشغيل Chromium خلال # ساعة}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_bg.xtb b/chromium/chrome/app/resources/chromium_strings_bg.xtb
index f64a62cdaa1..30a952a3285 100644
--- a/chromium/chrome/app/resources/chromium_strings_bg.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_bg.xtb
@@ -84,6 +84,7 @@
<translation id="378917192836375108">Chromium ви позволява да кликнете върху телефонен номер в мрежата и да се обадите до него със Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Закачване на Chromium към лентата на задачите</translation>
+<translation id="388648406173476553">Персонализиране и контролиране на Chromium. Трябва да обърнете внимание на нещо – кликнете за подробности.</translation>
<translation id="3889543394854987837">Кликнете върху името си, за да отворите Chromium и да започнете да сърфирате.</translation>
<translation id="3898493977366060150">Интелигентен начин за сърфиране в мрежата, създаден от Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS ще се рестартира след един час}other{Chromium OS ще се рестартира след # часа}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_bn.xtb b/chromium/chrome/app/resources/chromium_strings_bn.xtb
index 4e9cd408a3d..d5cf4eb76cb 100644
--- a/chromium/chrome/app/resources/chromium_strings_bn.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_bn.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium আপনাকে ওয়েবে কোনো ফোন নম্বরে ক্লিক করতে এবং Skype-এর মাধ্যমে সেটিতে কল করতে দেয়!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromium কে আপনার কার্যদণ্ডে পিন করুন</translation>
+<translation id="388648406173476553">Chromium কাস্টমাইজ ও নিয়ন্ত্রণ করুন। একটি বিষয়ে আপনার নজর দেওয়া দরকার - বিস্তারিত বিবরণের জন্য ক্লিক করুন।</translation>
<translation id="3889543394854987837">Chromium খোলার জন্য আপনার নামের উপরে ক্লিক করুন এবং ব্রাউজ করা শুরু করুন৷</translation>
<translation id="3898493977366060150">Google স্মার্ট ব্যবহার করে ওয়েব ব্রাউজিং</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS ১ ঘণ্টার মধ্যে রিস্টার্ট হবে}one{Chromium OS # ঘণ্টার মধ্যে রিস্টার্ট হবে}other{Chromium OS # ঘণ্টার মধ্যে রিস্টার্ট হবে}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ca.xtb b/chromium/chrome/app/resources/chromium_strings_ca.xtb
index ffda7ef9391..a30474d0d6c 100644
--- a/chromium/chrome/app/resources/chromium_strings_ca.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ca.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium us permet fer clic en un número de telèfon al web i trucar-hi amb Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" />: Chromium</translation>
<translation id="3852700440713538496">Ancora Chromium a la barra de tasques</translation>
+<translation id="388648406173476553">Personalitza i controla Chromium. Cal la teva intervenció. Fes clic per obtenir més informació.</translation>
<translation id="3889543394854987837">Feu clic al vostre nom per obrir Chromium i començar a navegar.</translation>
<translation id="3898493977366060150">Navegació web amb les eines intel·ligents de Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS es reiniciarà d'aquí a 1 hora}other{Chromium OS es reiniciarà d'aquí a # hores}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_cs.xtb b/chromium/chrome/app/resources/chromium_strings_cs.xtb
index 7d7407b151a..6870ca94595 100644
--- a/chromium/chrome/app/resources/chromium_strings_cs.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_cs.xtb
@@ -88,6 +88,7 @@ Některé funkce možná nebudou k dispozici a změny nastavení se neuloží.</
<translation id="378917192836375108">Chromium umožňuje kliknout na telefonní číslo na webu a volat na něj prostřednictvím aplikace Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Připněte si Chromium na hlavní panel</translation>
+<translation id="388648406173476553">Přizpůsobte si prohlížeč Chromium a ovládejte jej. Něco vyžaduje vaši pozornost – podrobnosti zobrazíte kliknutím.</translation>
<translation id="3889543394854987837">Chcete-li otevřít Chromium a začít procházet Internet, klikněte na svoje jméno.</translation>
<translation id="3898493977366060150">Procházení webu s chytrými funkcemi Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS se za hodinu restartuje}few{Chromium OS se za # hodiny restartuje}many{Chromium OS se za # hodiny restartuje}other{Chromium OS se za # hodin restartuje}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_da.xtb b/chromium/chrome/app/resources/chromium_strings_da.xtb
index fb53e7c96af..ae7bff014bf 100644
--- a/chromium/chrome/app/resources/chromium_strings_da.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_da.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Med Chromium kan du klikke på et telefonnummer på nettet og ringe op til det via Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Fastgør Chromium til proceslinjen</translation>
+<translation id="388648406173476553">Tilpas og administrer Chromium. Noget kræver din opmærksomhed – klik for at få oplysninger.</translation>
<translation id="3889543394854987837">Klik på dit navn for at åbne Chromium og gå i gang med at browse.</translation>
<translation id="3898493977366060150">Webbrowsing med Googles smarte funktioner</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS genstarter om en time}one{Chromium OS genstarter om # time}other{Chromium OS genstarter om # timer}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_de.xtb b/chromium/chrome/app/resources/chromium_strings_de.xtb
index 428652bfe5f..300ea209b84 100644
--- a/chromium/chrome/app/resources/chromium_strings_de.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_de.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">In Chromium können Sie auf eine Telefonnummer im Web klicken und diese mit Skype anrufen.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromium an Ihre Taskleiste anpinnen</translation>
+<translation id="388648406173476553">Sie können Chromium anpassen und Einstellungen festlegen. Etwas erfordert Ihre Aufmerksamkeit – klicken Sie, um mehr zu erfahren.</translation>
<translation id="3889543394854987837">Klicken Sie auf Ihren Namen, um Chromium zu öffnen und im Web zu surfen.</translation>
<translation id="3898493977366060150">Smart surfen mit Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS wird in einer Stunde neu gestartet}other{Chromium OS wird in # Stunden neu gestartet}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_el.xtb b/chromium/chrome/app/resources/chromium_strings_el.xtb
index 2c061df036d..32d58451543 100644
--- a/chromium/chrome/app/resources/chromium_strings_el.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_el.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Το Chromium σάς επιτρέπει να κάνετε κλικ σε έναν τηλεφωνικό αριθμό στον ιστό και να τον καλέσετε με το Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Καρφιτσώστε το Chromium στη γραμμή εργασιών σας</translation>
+<translation id="388648406173476553">Προσαρμογή και έλεγχος του Chromium. Θα πρέπει να ελέγξετε μια ειδοποίηση, κάντε κλικ για λεπτομέρειες.</translation>
<translation id="3889543394854987837">Κάντε κλικ στο όνομά σας, για να ανοίξετε το Chromium και να ξεκινήσετε την περιήγηση.</translation>
<translation id="3898493977366060150">Περιήγηση στον ιστό με το Google smarts</translation>
<translation id="3965668104013180445">{0,plural, =1{Η επανεκκίνηση του Chromium OS θα γίνει σε μία ώρα}other{Η επανεκκίνηση του Chromium OS θα γίνει σε # ώρες}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_en-GB.xtb b/chromium/chrome/app/resources/chromium_strings_en-GB.xtb
index 0619ed299ec..456d3f2e337 100644
--- a/chromium/chrome/app/resources/chromium_strings_en-GB.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_en-GB.xtb
@@ -88,6 +88,7 @@ Some features may be unavailable and changes to preferences won't be saved.</tra
<translation id="378917192836375108">Chromium lets you click a phone number on the web and call it with Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Pin Chromium to your taskbar</translation>
+<translation id="388648406173476553">Customise and control Chromium. Something needs your attention – click for details.</translation>
<translation id="3889543394854987837">Click your name to open Chromium and start browsing.</translation>
<translation id="3898493977366060150">Web browsing with Google smarts</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS will restart in an hour}other{Chromium OS will restart in # hours}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_es-419.xtb b/chromium/chrome/app/resources/chromium_strings_es-419.xtb
index 3cd1c112867..e99cf368018 100644
--- a/chromium/chrome/app/resources/chromium_strings_es-419.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_es-419.xtb
@@ -84,6 +84,7 @@
<translation id="378917192836375108">Chromium te permite hacer clic en un número de teléfono en la Web y comunicarte con este por Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Cómo fijar Chromium a la barra de tareas</translation>
+<translation id="388648406173476553">Personaliza y controla Chromium. Una alerta necesita tu atención. Haz clic para ver los detalles.</translation>
<translation id="3889543394854987837">Haz clic en tu nombre para abrir Chromium y empezar a navegar.</translation>
<translation id="3898493977366060150">Navegación en Internet con las funciones inteligentes de Google</translation>
<translation id="3965668104013180445">{0,plural, =1{El SO Chromium se reiniciará en una hora}other{El SO Chromium se reiniciará en # horas}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_es.xtb b/chromium/chrome/app/resources/chromium_strings_es.xtb
index 61cccdf0c37..7b3faafb6da 100644
--- a/chromium/chrome/app/resources/chromium_strings_es.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_es.xtb
@@ -88,6 +88,7 @@ Es posible que algunas funciones no estén disponibles y que no se guarden los c
<translation id="378917192836375108">Chromium te permite hacer clic en un número de teléfono en la Web y llamar mediante Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Ancla Chromium a la barra de tareas</translation>
+<translation id="388648406173476553">Personaliza y controla Chromium. Se requiere tu intervención. Haz clic aquí para obtener más información.</translation>
<translation id="3889543394854987837">Haz clic en tu nombre para abrir Chromium y empezar a navegar.</translation>
<translation id="3898493977366060150">Navegación web con soluciones inteligentes de Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS se volverá a iniciar en una hora}other{Chromium OS se volverá a iniciar en #  horas}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_et.xtb b/chromium/chrome/app/resources/chromium_strings_et.xtb
index d3ab67a6aa1..7005d234f78 100644
--- a/chromium/chrome/app/resources/chromium_strings_et.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_et.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium võimaldab teil veebis telefoninumbril klõpsata ja sellele Skype'i kaudu helistada!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Chromiumi kinnitamine tegumiribale</translation>
+<translation id="388648406173476553">Chromiumi kohandamine ja haldamine. Miski vajab teie tähelepanu – klõpsake üksikasjade nägemiseks.</translation>
<translation id="3889543394854987837">Chromiumi avamiseks ja sirvimise alustamiseks klõpsake oma nimel.</translation>
<translation id="3898493977366060150">Veebi sirvimine Google'i nutikate funktsioonidega</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS taaskäivitatakse tunni pärast}other{Chromium OS taaskäivitatakse # tunni pärast}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_fa.xtb b/chromium/chrome/app/resources/chromium_strings_fa.xtb
index c3827832008..ade0ad6edc7 100644
--- a/chromium/chrome/app/resources/chromium_strings_fa.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_fa.xtb
@@ -85,6 +85,7 @@
<translation id="378917192836375108">‏Chromium به شما اجازه می‌دهد بر روی شماره تلفن روی وب کلیک کرده و از طریق Skype تماس بگیرید!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">‏Chromium به نوار وظیفه شما پین شود</translation>
+<translation id="388648406173476553">‏Chromium را سفارشی و کنترل کنید. چیزی نیاز به رسیدگی دارد، برای اطلاعات بیشتر کلیک کنید.</translation>
<translation id="3889543394854987837">‏برای باز کردن Chromium و شروع به مرور، روی نامتان کلیک کنید.</translation>
<translation id="3898493977366060150">‏مرور وب با هوشمندی‌های Google</translation>
<translation id="3965668104013180445">{0,plural, =1{‏سیستم‌عامل Chromium یک ساعت دیگر بازراه‌اندازی می‌شود}one{‏سیستم‌عامل Chromium ‏# ساعت دیگر بازراه‌اندازی می‌شود}other{‏سیستم‌عامل Chromium ‏# ساعت دیگر بازراه‌اندازی می‌شود}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_fi.xtb b/chromium/chrome/app/resources/chromium_strings_fi.xtb
index 94a10916717..172700d136a 100644
--- a/chromium/chrome/app/resources/chromium_strings_fi.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_fi.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromiumin avulla voit soittaa Skypellä puhelinnumeroon klikkaamalla sitä verkossa!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromiumin kiinnittäminen tehtäväpalkkiin</translation>
+<translation id="388648406173476553">Yksilöi ja ylläpidä Chromiumia. Toimenpiteitä vaaditaan. Katso lisätiedot klikkaamalla.</translation>
<translation id="3889543394854987837">Avaa Chromium klikkaamalla nimeäsi ja aloita selaaminen.</translation>
<translation id="3898493977366060150">Verkkoselaaminen Googlen älykkäillä ratkaisuilla</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS käynnistetään uudelleen tunnin kuluttua}other{Chromium OS käynnistetään uudelleen # tunnin kuluttua}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_fil.xtb b/chromium/chrome/app/resources/chromium_strings_fil.xtb
index 817de8dd869..8d695d12584 100644
--- a/chromium/chrome/app/resources/chromium_strings_fil.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_fil.xtb
@@ -88,6 +88,7 @@ Maaaring hindi available ang ilang tampok at hindi mase-save ang mga pagbabago s
<translation id="378917192836375108">Pinapayagan ka ng Google Chrome na mag-click sa isang numero ng telepono sa web at tawagan ito gamit ang Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">I-pin ang Chromium sa iyong taskbar</translation>
+<translation id="388648406173476553">I-customize at kontrolin ang Chromium. May kailangan kang pagtuunan ng pansin - mag-click para sa mga detalye.</translation>
<translation id="3889543394854987837">I-click ang iyong pangalan upang buksan ang Chromium at simulan ang pagba-browse.</translation>
<translation id="3898493977366060150">Pag-browse sa web gamit ang mga smart na feature ng Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Magre-restart ang Chromium OS sa loob ng isang oras}one{Magre-restart ang Chromium OS sa loob ng # oras}other{Magre-restart ang Chromium OS sa loob ng # na oras}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_fr.xtb b/chromium/chrome/app/resources/chromium_strings_fr.xtb
index 8cca091d842..fc407f8e694 100644
--- a/chromium/chrome/app/resources/chromium_strings_fr.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_fr.xtb
@@ -87,6 +87,7 @@ Certaines fonctionnalités ne seront peut-être pas disponibles, et les modifica
<translation id="378917192836375108">Avec Chromium, cliquez sur un numéro de téléphone sur le Web et appelez-le dans Skype !</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Épingler Chromium à votre barre des tâches</translation>
+<translation id="388648406173476553">Personnalisez et contrôlez Chromium. Une action de votre part est requise. Cliquez pour en savoir plus.</translation>
<translation id="3889543394854987837">Cliquez sur votre nom pour ouvrir Chromium et commencer à naviguer.</translation>
<translation id="3898493977366060150">Navigation sur le Web avec les fonctionnalités intelligentes de Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS va redémarrer dans une heure}one{Chromium OS va redémarrer dans # heure}other{Chromium OS va redémarrer dans # heures}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_gu.xtb b/chromium/chrome/app/resources/chromium_strings_gu.xtb
index f7a432a2d35..b00d4dacf26 100644
--- a/chromium/chrome/app/resources/chromium_strings_gu.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_gu.xtb
@@ -88,6 +88,7 @@
<translation id="378917192836375108">Chromium થી તમે વેબ પર એક ફોન નંબર પર ક્લિક કરી શકો છો અને તેને Skype થી કૉલ કરી શકો છો!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">તમારા ટાસ્કબારમાં Chromium ને પિન કરો</translation>
+<translation id="388648406173476553">Chromiumને કસ્ટમાઇઝ અને તેનું નિયંત્રણ કરો. તમારે ક્યાંક ધ્યાન આપવાની જરૂર છે - વિગતો માટે ક્લિક કરો.</translation>
<translation id="3889543394854987837">Chromium ને ખોલવા માટે તમારા નામને ક્લિક કરો અને બ્રાઉઝ કરવાનું પ્રારંભ કરો.</translation>
<translation id="3898493977366060150">Google સ્માર્ટ સાથે વેબ બ્રાઉઝ કરો</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS એક કલાકમાં ફરી શરૂ થશે}one{Chromium OS # કલાકમાં ફરી શરૂ થશે}other{Chromium OS # કલાકમાં ફરી શરૂ થશે}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_hi.xtb b/chromium/chrome/app/resources/chromium_strings_hi.xtb
index b8d4df11f1e..16c07325b06 100644
--- a/chromium/chrome/app/resources/chromium_strings_hi.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_hi.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Google Chrome आपको वेब पर फ़ोन नंबर क्लिक करने और उसे Skype से कॉल करने की सुविधा देता है!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - क्रोमियम</translation>
<translation id="3852700440713538496">क्रोमियम को अपने टास्कबार में पिन करें</translation>
+<translation id="388648406173476553">क्रोमियम को पसंद के मुताबिक बनाएं और नियंत्रित करें. कुछ है जिस पर आपको ध्यान देने की ज़रूरत है - विवरण के लिए क्लिक करें.</translation>
<translation id="3889543394854987837">क्रोमियम को खोलने और ब्राउज़ करना प्रारंभ करने के लिए अपना नाम क्लिक करें.</translation>
<translation id="3898493977366060150">Google स्मार्ट के ज़रिए वेब ब्राउज़ करें</translation>
<translation id="3965668104013180445">{0,plural, =1{क्रोमियम OS एक घंटे में रीस्टार्ट होगा}one{क्रोमियम OS # घंटों में रीस्टार्ट होगा}other{क्रोमियम OS # घंटों में रीस्टार्ट होगा}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_hr.xtb b/chromium/chrome/app/resources/chromium_strings_hr.xtb
index f8642d6f8dc..57d28f03b41 100644
--- a/chromium/chrome/app/resources/chromium_strings_hr.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_hr.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium omogućuje da kliknete telefonski broj na webu i nazovete ga koristeći se Skypeom!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Prikvačite Chromium na programsku traku</translation>
+<translation id="388648406173476553">Prilagodite Chromium i upravljajte njime. Trebate obratiti pozornost na nešto – kliknite za pojedinosti.</translation>
<translation id="3889543394854987837">Kliknite svoje ime da biste otvorili Chromium i počeli s pregledavanjem.</translation>
<translation id="3898493977366060150">Pregledavanje weba uz pametne Googleove značajke</translation>
<translation id="3965668104013180445">{0,plural, =1{OS Chromium ponovo će se pokrenuti za sat vremena}one{OS Chromium ponovo će se pokrenuti za # sat}few{OS Chromium ponovo će se pokrenuti za # sata}other{OS Chromium ponovo će se pokrenuti za # sati}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_hu.xtb b/chromium/chrome/app/resources/chromium_strings_hu.xtb
index 30501706ad9..290b6eee14d 100644
--- a/chromium/chrome/app/resources/chromium_strings_hu.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_hu.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">A Chromium egyetlen kattintással lehetővé teszi a weboldalakon található telefonszámok felhívását Skype-on!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> -- Chromium</translation>
<translation id="3852700440713538496">Chromium rögzítése a tálcán</translation>
+<translation id="388648406173476553">Személyre szabhatja a Chromium működését. Figyelmet kell fordítania valamire – a részletekért kattintson.</translation>
<translation id="3889543394854987837">Kattintson a nevére a Chromium megnyitásához és a böngészés megkezdéséhez.</translation>
<translation id="3898493977366060150">Webes böngészés Google-okostelefonokkal</translation>
<translation id="3965668104013180445">{0,plural, =1{A Chromium OS 1 órán belül újraindul}other{A Chromium OS # órán belül újraindul}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_id.xtb b/chromium/chrome/app/resources/chromium_strings_id.xtb
index e8ed0d2438e..03317f5d2ab 100644
--- a/chromium/chrome/app/resources/chromium_strings_id.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_id.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium memungkinkan Anda mengeklik nomor telepon pada web dan menghubunginya melalui Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Sematkan Chromium di bilah tugas</translation>
+<translation id="388648406173476553">Sesuaikan dan kontrol Chromium. Ada sesuatu yang memerlukan perhatian Anda - klik untuk melihat detailnya.</translation>
<translation id="3889543394854987837">Klik nama Anda untuk membuka Chromium dan mulai menjelajah.</translation>
<translation id="3898493977366060150">Browsing web dengan fitur smart dari Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS akan dimulai ulang dalam 1 jam}other{Chromium OS akan dimulai ulang dalam # jam}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_it.xtb b/chromium/chrome/app/resources/chromium_strings_it.xtb
index 6fc0bfc5892..e9f1c5c2c11 100644
--- a/chromium/chrome/app/resources/chromium_strings_it.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_it.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium ti consente di fare clic su un numero di telefono sul Web e di chiamarlo con Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Aggiungi Chromium alla barra delle applicazioni</translation>
+<translation id="388648406173476553">Personalizza e controlla Chromium. C'è qualcosa che richiede la tua attenzione. Fai clic per avere informazioni dettagliate.</translation>
<translation id="3889543394854987837">Fai clic sul tuo nome per aprire Chromium e iniziare a navigare.</translation>
<translation id="3898493977366060150">Navigazione sul Web con l'esperienza di Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS verrà riavviato tra un'ora}other{Chromium OS verrà riavviato tra # ore}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_iw.xtb b/chromium/chrome/app/resources/chromium_strings_iw.xtb
index f09f39411ea..0d0ed40d124 100644
--- a/chromium/chrome/app/resources/chromium_strings_iw.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_iw.xtb
@@ -84,6 +84,7 @@
<translation id="378917192836375108">‏Chromium מאפשר לך ללחוץ על מספר טלפון באינטרנט ולהתקשר אליו באמצעות Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">‏הצמד את Chromium לשורת המשימות</translation>
+<translation id="388648406173476553">‏התאמה אישית וניהול של Chromium נחוצה פעולה שלך - יש ללחוץ לקבלת פרטים נוספים.</translation>
<translation id="3889543394854987837">‏לחץ על השם שלך כדי לפתוח את Chromium ולהתחיל לגלוש.</translation>
<translation id="3898493977366060150">‏גלישה באינטרנט עם Google Smarts</translation>
<translation id="3965668104013180445">{0,plural, =1{‏Chromium OS תופעל מחדש בעוד שעה אחת}two{‏Chromium OS תופעל מחדש בעוד שעתיים}many{‏Chromium OS תופעל מחדש בעוד # שעות}other{‏Chromium OS תופעל מחדש בעוד # שעות}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ja.xtb b/chromium/chrome/app/resources/chromium_strings_ja.xtb
index 19b68f518e8..2ff0f0e82d3 100644
--- a/chromium/chrome/app/resources/chromium_strings_ja.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ja.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium では、ウェブサイト上の電話番号をクリックするだけで Skype で通話を発信できます。</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromium をタスクバーにピン留めする</translation>
+<translation id="388648406173476553">Chromium をカスタマイズ、制御します。確認の必要な項目があります。クリックして詳細をご覧ください。</translation>
<translation id="3889543394854987837">Chromium を開いてブラウジングを始めるには、名前をクリックしてください。</translation>
<translation id="3898493977366060150">Google の最先端技術を活用したウェブ ブラウジング</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS は 1 時間後に再起動されます}other{Chromium OS は # 時間後に再起動されます}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_kn.xtb b/chromium/chrome/app/resources/chromium_strings_kn.xtb
index ecb1a8fc3e5..5fa2e7d60bc 100644
--- a/chromium/chrome/app/resources/chromium_strings_kn.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_kn.xtb
@@ -84,6 +84,7 @@
<translation id="378917192836375108">Chromium ನೀವು ವೆಬ್‌ನಲ್ಲಿ ಫೋನ್ ಸಂಖ್ಯೆಯನ್ನು ಕ್ಲಿಕ್ ಮಾಡಲು ಅವಕಾಶ ಮಾಡುತ್ತದೆ ಮತ್ತು Skype ನೊಂದಿಗೆ ಕರೆ ಮಾಡುತ್ತದೆ!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">ನಿಮ್ಮ ಕಾರ್ಯಪಟ್ಟಿಗೆ Chromium ಅನ್ನು ಪಿನ್ ಮಾಡಿ</translation>
+<translation id="388648406173476553">Chromium ಕಸ್ಟಮೈಸ್ ಮಾಡಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ. ನೀವು ಕೆಲವು ಸಂಗತಿಗಳ ಕುರಿತು ಗಮನಹರಿಸಬೇಕಿದೆ - ವಿವರಗಳಿಗಾಗಿ ಕ್ಲಿಕ್ ಮಾಡಿ.</translation>
<translation id="3889543394854987837">Chromium ತೆರೆಯಲು ಮತ್ತು ಬ್ರೌಸ್ ಮಾಡುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ನಿಮ್ಮ ಹೆಸರನ್ನು ಕ್ಲಿಕ್ ಮಾಡಿ.</translation>
<translation id="3898493977366060150">Google ಸ್ಮಾರ್ಟ್‌ಗಳ ಮೂಲಕ ವೆಬ್‌ ಬ್ರೌಸ್‌ ಮಾಡುವಿಕೆ</translation>
<translation id="3965668104013180445">{0,plural, =1{ಒಂದು ಗಂಟೆಯಲ್ಲಿ Chromium OS ಮರುಪ್ರಾರಂಭಗೊಳ್ಳುತ್ತದೆ}one{# ಗಂಟೆಗಳಲ್ಲಿ Chromium OS ಮರುಪ್ರಾರಂಭಗೊಳ್ಳುತ್ತದೆ}other{# ಗಂಟೆಗಳಲ್ಲಿ Chromium OS ಮರುಪ್ರಾರಂಭಗೊಳ್ಳುತ್ತದೆ}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ko.xtb b/chromium/chrome/app/resources/chromium_strings_ko.xtb
index 65349a659c8..10dab948d10 100644
--- a/chromium/chrome/app/resources/chromium_strings_ko.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ko.xtb
@@ -88,6 +88,7 @@
<translation id="378917192836375108">Chromium을 사용하면 웹에서 전화번호를 클릭하여 Skype로 통화할 수 있습니다.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromium을 작업 표시줄에 고정</translation>
+<translation id="388648406173476553">Chromium을 맞춤설정 및 제어합니다. 확인이 필요한 항목이 있습니다. 클릭하여 세부정보를 보세요.</translation>
<translation id="3889543394854987837">Chromium을 열고 탐색을 시작하려면 내 이름을 클릭하세요.</translation>
<translation id="3898493977366060150">Google과 스마트하게 웹을 탐색하세요</translation>
<translation id="3965668104013180445">{0,plural, =1{1시간 후에 Chromium OS 다시 시작}other{#시간 후에 Chromium OS 다시 시작}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_lt.xtb b/chromium/chrome/app/resources/chromium_strings_lt.xtb
index 404327ccadc..12b24555088 100644
--- a/chromium/chrome/app/resources/chromium_strings_lt.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_lt.xtb
@@ -88,6 +88,7 @@ Kai kurios funkcijos gali būti nepasiekiamos ir nuostatų pakeitimai nebus išs
<translation id="378917192836375108">Naudodami „Chromium“ galite spustelėti telefono numerį žiniatinklyje ir skambinti juo naudodami „Skype“!</translation>
<translation id="3848258323044014972">„<ph name="PAGE_TITLE" />“ – „Chromium“</translation>
<translation id="3852700440713538496">„Chromium“ prisegimas prie užduočių juostos</translation>
+<translation id="388648406173476553">Tinkinkite ir valdykite „Chromium“. Reikia atkreipti dėmesį – spustelėkite ir peržiūrėkite išsamią informaciją.</translation>
<translation id="3889543394854987837">Spustelėkite savo vardą, kad atidarytumėte „Chromium“ ir pradėtumėte naršyti.</translation>
<translation id="3898493977366060150">Žiniatinklio naršymas naudojant „Google“ išmaniąsias funkcijas</translation>
<translation id="3965668104013180445">{0,plural, =1{„Chromium“ OS bus paleista iš naujo po valandos}one{„Chromium“ OS bus paleista iš naujo # valandos}few{„Chromium“ OS bus paleista iš naujo # valandų}many{„Chromium“ OS bus paleista iš naujo # valandos}other{„Chromium“ OS bus paleista iš naujo # valandų}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_lv.xtb b/chromium/chrome/app/resources/chromium_strings_lv.xtb
index aba701926f7..85cc05ccb31 100644
--- a/chromium/chrome/app/resources/chromium_strings_lv.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_lv.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium ļauj jums noklikšķināt uz tālruņa numura un zvanīt uz to pakalpojumā Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> — Chromium</translation>
<translation id="3852700440713538496">Piespraudiet pārlūku Chromium uzdevumjoslai</translation>
+<translation id="388648406173476553">Pielāgojiet un kontrolējiet pārlūkprogrammu Chromium. Ir nepieciešama jūsu uzmanība. Noklikšķiniet, lai skatītu plašāku informāciju.</translation>
<translation id="3889543394854987837">Noklikšķiniet uz sava vārda, lai atvērtu Chromium un sāktu pārlūkošanu.</translation>
<translation id="3898493977366060150">Tīmekļa pārlūkošana, izmantojot Google viedās tehnoloģijas</translation>
<translation id="3965668104013180445">{0,plural, =1{Operētājsistēma Chromium OS tiks restartēta pēc vienas stundas}zero{Operētājsistēma Chromium OS tiks restartēta pēc # stundām}one{Operētājsistēma Chromium OS tiks restartēta pēc # stundas}other{Operētājsistēma Chromium OS tiks restartēta pēc # stundām}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ml.xtb b/chromium/chrome/app/resources/chromium_strings_ml.xtb
index 7eb98632821..c6d59615d14 100644
--- a/chromium/chrome/app/resources/chromium_strings_ml.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ml.xtb
@@ -88,6 +88,7 @@
<translation id="378917192836375108">വെബിലുള്ള ഒരു ഫോണ്‍ നമ്പറില്‍ ക്ലിക്കുചെയ്യുവാനും Skype ഉപയോഗിച്ച് അതിൽ വിളിക്കുവാനും Chromium നിങ്ങളെ അനുവദിക്കുന്നു!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromium-ത്തെ നിങ്ങളുടെ ടാസ്‌ക്‌ബാറിൽ പിൻ ചെയ്യുക</translation>
+<translation id="388648406173476553">Chromium ഇഷ്‌ടാനുസൃതമാക്കുക, നിയന്ത്രിക്കുക. എന്തോ ഒന്നിന് നിങ്ങളുടെ ശ്രദ്ധ വേണം -വിശദാംശങ്ങൾക്ക് ക്ലിക്ക് ചെയ്യുക.</translation>
<translation id="3889543394854987837">Chromium തുറന്ന് ബ്രൗസിംഗ് ആരംഭിക്കാൻ നിങ്ങളുടെ പേരിൽ ക്ലിക്കുചെയ്യുക.</translation>
<translation id="3898493977366060150">Google ഉപയോഗിച്ചുള്ള വെബ് ബ്രൗസിംഗ് മികവുറ്റതാണ്</translation>
<translation id="3965668104013180445">{0,plural, =1{ഒരു മണിക്കൂറിൽ Chromium OS പുനഃരാരംഭിക്കും}other{# മണിക്കൂറിൽ Chromium OS പുനഃരാരംഭിക്കും}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_mr.xtb b/chromium/chrome/app/resources/chromium_strings_mr.xtb
index ef14cfec1ad..d7bd7a8bc36 100644
--- a/chromium/chrome/app/resources/chromium_strings_mr.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_mr.xtb
@@ -87,6 +87,7 @@
<translation id="378917192836375108">Chromium तुम्हाला वेबवरील फोन नंबर क्लिक करू देते आणि Skype सह त्याला कॉल करते!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromium ला आपल्या टास्कबारवर पिन करा</translation>
+<translation id="388648406173476553">Chromium कस्टमाइझ करा आणि नियंत्रित करा. एका गोष्टीवर तुम्ही लक्ष द्यायला हवे - तपशिलांसाठी क्लिक करा.</translation>
<translation id="3889543394854987837">Chromium उघडण्यासाठी तुमचे नाव क्लिक करा आणि ब्राउझिंग प्रारंभ करा.</translation>
<translation id="3898493977366060150">Google smarts सह वेब ब्राउझिंग</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS एका तासात रीस्टार्ट करेल}one{Chromium OS # तासामध्ये रीस्टार्ट करेल}other{Chromium OS # तासांमध्ये रीस्टार्ट करेल}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ms.xtb b/chromium/chrome/app/resources/chromium_strings_ms.xtb
index f3548703499..8ee48c7d72b 100644
--- a/chromium/chrome/app/resources/chromium_strings_ms.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ms.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium membolehkan anda mengklik nombor telefon pada web dan menghubunginya dengan Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Sematkan Chromium pada bar tugas anda</translation>
+<translation id="388648406173476553">Sesuaikan dan kawal Chromium. Perhatian anda diperlukan - klik untuk mendapatkan butiran.</translation>
<translation id="3889543394854987837">Klik nama anda untuk membuka Chromium dan mula menyemak imbas.</translation>
<translation id="3898493977366060150">Penyemakan imbas web dengan Google smarts</translation>
<translation id="3965668104013180445">{0,plural, =1{OS Chromium akan dimulakan semula dalam masa sejam}other{OS Chromium akan dimulakan semula dalam masa # jam}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_nl.xtb b/chromium/chrome/app/resources/chromium_strings_nl.xtb
index e4c2997b7d1..4d86ce0bfe8 100644
--- a/chromium/chrome/app/resources/chromium_strings_nl.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_nl.xtb
@@ -88,6 +88,7 @@ Sommige functies zijn wellicht niet beschikbaar en wijzigingen in voorkeuren wor
<translation id="378917192836375108">Met Chromium kun je klikken op een telefoonnummer op internet om dit via Skype te bellen!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromium vastzetten op je taakbalk</translation>
+<translation id="388648406173476553">Pas Chromium aan en beheer de instellingen. Je aandacht is vereist. Klik voor meer informatie.</translation>
<translation id="3889543394854987837">Klik op je naam om Chromium te openen en begin met surfen.</translation>
<translation id="3898493977366060150">Browsen met innovaties van Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS wordt over een uur opnieuw opgestart}other{Chromium OS wordt over # uur opnieuw opgestart}}</translation>
@@ -119,7 +120,7 @@ Sommige functies zijn wellicht niet beschikbaar en wijzigingen in voorkeuren wor
<translation id="5021854341188256296">{0,plural, =0{Er is een Chromium OS-update beschikbaar}=1{Er is een Chromium OS-update beschikbaar}other{Er is al # dagen een Chromium OS-update beschikbaar}}</translation>
<translation id="5032989939245619637">Details opslaan in Chromium</translation>
<translation id="5045248521775609809">Neem Chromium overal mee naartoe</translation>
-<translation id="5116586539350239523">Chromium slaat je persoonlijke gegevens beveiligd op, zodat je ze niet opnieuw hoeft op te geven.</translation>
+<translation id="5116586539350239523">Chromium slaat je persoonsgegevens beveiligd op, zodat je ze niet opnieuw hoeft op te geven.</translation>
<translation id="5181952534059945058">Omdat deze pagina te veel geheugen gebruikt, heeft Chromium wat content verwijderd.</translation>
<translation id="5277894862589591112">Als je de wijzigingen wilt toepassen, start je Chromium opnieuw</translation>
<translation id="5358375970380395591">Je logt in op een beheerd account waarmee de eigenaar van dat account beheer krijgt over je Chromium-profiel. Je Chromium-gegevens zoals je apps, bladwijzers, geschiedenis, wachtwoorden en andere instellingen worden permanent gekoppeld aan <ph name="USER_NAME" />. Je kunt deze gegevens verwijderen via het Google Accounts Dashboard, maar je kunt deze gegevens niet koppelen aan een ander account.<ph name="LEARN_MORE" /></translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_no.xtb b/chromium/chrome/app/resources/chromium_strings_no.xtb
index 3bba23415dd..2ecc56ba128 100644
--- a/chromium/chrome/app/resources/chromium_strings_no.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_no.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Med Chromium kan du klikke på et telefonnummer på nettet og ringe til det med Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Fest Chromium til oppgavelinjen</translation>
+<translation id="388648406173476553">Tilpass og kontrollér Chromium. Det er noe du må se på – klikk for mer informasjon.</translation>
<translation id="3889543394854987837">Klikk på navnet ditt for å åpne Chromium og starte surfingen.</translation>
<translation id="3898493977366060150">Surfing med Googles smarte funksjoner</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS startes på nytt om én time}other{Chromium OS startes på nytt om # timer}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_pl.xtb b/chromium/chrome/app/resources/chromium_strings_pl.xtb
index b8d5667a675..e12ac4e8d9f 100644
--- a/chromium/chrome/app/resources/chromium_strings_pl.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_pl.xtb
@@ -84,6 +84,7 @@
<translation id="378917192836375108">W Chromium możesz kliknąć numer telefonu zamieszczony w sieci i zadzwonić pod niego przez Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Przypinanie Chromium na pasku zadań</translation>
+<translation id="388648406173476553">Dostosuj i kontroluj Chromium. Pewna kwestia wymaga Twojej uwagi – kliknij, by przejść do szczegółów.</translation>
<translation id="3889543394854987837">Otwórz Chromium, klikając swoją nazwę i rozpocznij przeglądanie.</translation>
<translation id="3898493977366060150">Przeglądanie stron internetowych za pomocą inteligentnych rozwiązań Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS uruchomi się ponownie za godzinę}few{Chromium OS uruchomi się ponownie za # godziny}many{Chromium OS uruchomi się ponownie za # godzin}other{Chromium OS uruchomi się ponownie za # godziny}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_pt-BR.xtb b/chromium/chrome/app/resources/chromium_strings_pt-BR.xtb
index 1fcbfe142aa..f01482e579b 100644
--- a/chromium/chrome/app/resources/chromium_strings_pt-BR.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_pt-BR.xtb
@@ -84,6 +84,7 @@
<translation id="378917192836375108">O Chromium permite que você clique em um número de telefone na web e ligue para ele com o Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Fixar o Chromium na barra de tarefas</translation>
+<translation id="388648406173476553">Personalize e controle o Chromium. Algo precisa da sua atenção. Clique para ver mais detalhes.</translation>
<translation id="3889543394854987837">Clique no seu nome para abrir o Chromium e começar a navegar.</translation>
<translation id="3898493977366060150">Navegação na Web com a tecnologia do Google</translation>
<translation id="3965668104013180445">{0,plural, =1{O Chromium OS será reiniciado em uma hora}one{O Chromium OS será reiniciado em # hora}other{O Chromium OS será reiniciado em # horas}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_pt-PT.xtb b/chromium/chrome/app/resources/chromium_strings_pt-PT.xtb
index 0d96e8400f7..26d30fd04c6 100644
--- a/chromium/chrome/app/resources/chromium_strings_pt-PT.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_pt-PT.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">O Chromium permite-lhe clicar num número de telefone na Web e fazer a chamada com o Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Afixar o Chromium na barra de tarefas</translation>
+<translation id="388648406173476553">Personalize e controle o Chromium. É necessária a sua atenção – clique para obter detalhes.</translation>
<translation id="3889543394854987837">Clique no seu nome para abrir o Chromium e começar a navegar.</translation>
<translation id="3898493977366060150">Navegação na Web com a inteligência da Google</translation>
<translation id="3965668104013180445">{0,plural, =1{O Chromium OS será reiniciado dentro de uma hora}other{O Chromium OS será reiniciado dentro de # horas}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ro.xtb b/chromium/chrome/app/resources/chromium_strings_ro.xtb
index 034bad1ba43..43c8e05b4cd 100644
--- a/chromium/chrome/app/resources/chromium_strings_ro.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ro.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium vă permite să dați clic pe un număr de telefon de pe web pentru a-l apela cu Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Fixează Chromium pe bara de activități</translation>
+<translation id="388648406173476553">Personalizează și controlează Chromium. Ceva are nevoie de atenția ta – dă clic pentru detalii.</translation>
<translation id="3889543394854987837">Dați clic pe numele dvs. pentru a deschide Chromium și a începe să navigați.</translation>
<translation id="3898493977366060150">Navigare pe web cu ingeniozitatea Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Sistemul de operare Chromium va reporni într-o oră}few{Sistemul de operare Chromium va reporni în # ore}other{Sistemul de operare Chromium va reporni în # de ore}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ru.xtb b/chromium/chrome/app/resources/chromium_strings_ru.xtb
index 690b0c9fd91..c00dca8b7c5 100644
--- a/chromium/chrome/app/resources/chromium_strings_ru.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ru.xtb
@@ -84,6 +84,7 @@
<translation id="378917192836375108">В Chromium вы можете нажать на любой номер телефона и позвонить на него через Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Как прикрепить Chromium на панель задач</translation>
+<translation id="388648406173476553">Настройка и управление Chromium Требуется ваше внимание. Нажмите, чтобы получить подробную информацию.</translation>
<translation id="3889543394854987837">Нажмите на свое имя, чтобы войти в Chromium.</translation>
<translation id="3898493977366060150">Технологии Google для простого и быстрого поиска в Интернете.</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS перезапустится через 1 час}one{Chromium OS перезапустится через # час}few{Chromium OS перезапустится через # часа}many{Chromium OS перезапустится через # часов}other{Chromium OS перезапустится через # часа}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_sk.xtb b/chromium/chrome/app/resources/chromium_strings_sk.xtb
index 795b674d2f2..8ff2dd5ebba 100644
--- a/chromium/chrome/app/resources/chromium_strings_sk.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_sk.xtb
@@ -88,6 +88,7 @@ Niektoré funkcie nemusia byť k dispozícii a zmeny vykonané v predvoľbách s
<translation id="378917192836375108">Prehliadač Chromium vám umožňuje vybrať telefónne číslo na webe a zavolať naň pomocou aplikácie Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Pripnutie prehliadača Chromium na panel úloh</translation>
+<translation id="388648406173476553">Prispôsobte a ovládajte Chromium. Vyžaduje sa vaša pozornosť. Podrobnosti získate kliknutím.</translation>
<translation id="3889543394854987837">Ak chcete otvoriť prehliadač Chromium a začať prehliadať, kliknite na svoje meno.</translation>
<translation id="3898493977366060150">Prehliadanie webu pomocou inteligentných doplnkov Googlu</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS sa reštartuje o 1 hodinu}few{Chromium OS sa reštartuje o # hodiny}many{Chromium OS sa reštartuje o # hodiny}other{Chromium OS sa reštartuje o # hodín}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_sl.xtb b/chromium/chrome/app/resources/chromium_strings_sl.xtb
index fee56d05841..33594a0c14f 100644
--- a/chromium/chrome/app/resources/chromium_strings_sl.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_sl.xtb
@@ -89,6 +89,7 @@ Te storitve lahko po želji onemogočite. <ph name="BEGIN_LINK" />Več o tem<ph
<translation id="378917192836375108">Chromium omogoča, da v spletu kliknete telefonsko številko in jo pokličete prek Skypa.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Pripenjanje Chromiuma v opravilno vrstico</translation>
+<translation id="388648406173476553">Prilagajanje in nadziranje Chromiuma. Nekaj morate preveriti – kliknite za podrobnosti.</translation>
<translation id="3889543394854987837">Kliknite ime, da odprete Chromium in začnete brskati.</translation>
<translation id="3898493977366060150">Brskanje po spletu z Googlovimi pametnimi rešitvami</translation>
<translation id="3965668104013180445">{0,plural, =1{OS Chromium se bo znova zagnal čez eno uro}one{OS Chromium se bo znova zagnal čez # uro}two{OS Chromium se bo znova zagnal čez # uri}few{OS Chromium se bo znova zagnal čez # ure}other{OS Chromium se bo znova zagnal čez # ur}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_sr.xtb b/chromium/chrome/app/resources/chromium_strings_sr.xtb
index d9ba8a990cc..e76cac4af3c 100644
--- a/chromium/chrome/app/resources/chromium_strings_sr.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_sr.xtb
@@ -88,6 +88,7 @@
<translation id="378917192836375108">Chromium вам омогућава да кликнете на број телефона на вебу и да га позовете помоћу Skype-а!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Закачите Chromium на траку задатака</translation>
+<translation id="388648406173476553">Прилагодите и контролишите Chromium. Треба да обратите пажњу на нешто – кликните за више детаља.</translation>
<translation id="3889543394854987837">Кликните на име да бисте отворили Chromium и почните да прегледате.</translation>
<translation id="3898493977366060150">Веб-прегледање помоћу паметних Google функција</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium ОС ће се рестартовати за један сат}one{Chromium ОС ће се рестартовати за # сат}few{Chromium ОС ће се рестартовати за # сата}other{Chromium ОС ће се рестартовати за # сати}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_sv.xtb b/chromium/chrome/app/resources/chromium_strings_sv.xtb
index d24b92a278b..a551932ec51 100644
--- a/chromium/chrome/app/resources/chromium_strings_sv.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_sv.xtb
@@ -88,6 +88,7 @@ Vissa funktioner kanske inte är tillgängliga och ändringar i inställningarna
<translation id="378917192836375108">I Chromium kan du klicka på ett telefonnummer på nätet och ringa det med Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Fäst Chromium i aktivitetsfältet</translation>
+<translation id="388648406173476553">Anpassa och kontrollera Chromium. Någonting behöver ses över. Klicka här för mer information.</translation>
<translation id="3889543394854987837">Öppna Chromium genom att klicka på ditt namn och börja surfa.</translation>
<translation id="3898493977366060150">Surfa smart med Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Om en timme startas Chromium OS om}other{Om # timmar startas Chromium OS om}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_sw.xtb b/chromium/chrome/app/resources/chromium_strings_sw.xtb
index 58f1356a92e..94d5c7c58cf 100644
--- a/chromium/chrome/app/resources/chromium_strings_sw.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_sw.xtb
@@ -88,6 +88,7 @@ Baadhi ya vipengele huenda visipatikane na mabadiliko katika mapendeleo hayatahi
<translation id="378917192836375108">Chromium hukuruhusu kubofya nambari ya simu kwenye wavuti na kuipiga kwa Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Tundika Chromium kwenye upau wa kazi wa kompyuta yako</translation>
+<translation id="388648406173476553">Dhibiti na uweke mapendeleo kwenye Chromium. Unahitaji kushughulikia jambo fulani. Bofya ili upate maelezo.</translation>
<translation id="3889543394854987837">Bofya jina lako ili ufungue Chromium na uanze kuvinjari.</translation>
<translation id="3898493977366060150">Kuvinjari kwenye wavuti kwa kutumia programu mahiri za Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Mfumo wa uendeshaji wa Chromium utazimwa kisha uwashwe baada ya saa moja}other{Mfumo wa uendeshaji wa Chromium utazimwa kisha uwashwe baada ya saa #}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_ta.xtb b/chromium/chrome/app/resources/chromium_strings_ta.xtb
index 0b8cd3bce9d..c1c5eda143d 100644
--- a/chromium/chrome/app/resources/chromium_strings_ta.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_ta.xtb
@@ -56,7 +56,7 @@
<translation id="2910007522516064972">&amp;Chromium அறிமுகம்</translation>
<translation id="2977470724722393594">Chromium புதுப்பித்த நிலையில் உள்ளது</translation>
<translation id="3032787606318309379">Chromium இல் சேர்க்கிறது...</translation>
-<translation id="3046695367536568084">பயன்பாடுகளைப் பயன்படுத்த Chromium இல் உள்நுழைந்திருக்க வேண்டும். எல்லா சாதனங்களிலும் உள்ள உங்கள் பயன்பாடுகள், புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளை ஒத்திசைக்க Chromium ஐ இது அனுமதிக்கிறது.</translation>
+<translation id="3046695367536568084">பயன்பாடுகளைப் பயன்படுத்த Chromium இல் உள்நுழைந்திருக்க வேண்டும். எல்லா சாதனங்களிலும் உள்ள உங்கள் பயன்பாடுகள், புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளை ஒத்திசைக்க Chromium ஐ இது அனுமதிக்கிறது.</translation>
<translation id="3052899382720782935">{0,plural, =1{1 நிமிடத்தில் Chromium மீண்டும் தொடங்கும்}other{# நிமிடங்களில் Chromium மீண்டும் தொடங்கும்}}</translation>
<translation id="3068515742935458733">சிதைவு அறிக்கைகளையும் <ph name="UMA_LINK" /> உம் Google க்கு அனுப்புவதன் மூலம் Chromium ஐ மேலும் சிறப்பானதாக்க உதவவும்</translation>
<translation id="3103660991484857065">காப்பகத்தைச் சுருக்குவதில் நிறுவி தோல்வியடைந்தது. Chromium ஐ மீண்டும் பதிவிறக்குக.</translation>
@@ -86,6 +86,7 @@
<translation id="378917192836375108">வலையில் ஒரு தொலைபேசி எண்ணைக் கிளிக் செய்து, அதனை Skype மூலமாக அழைப்பதற்கு உங்களை Chromium அனுமதிக்கிறது!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">பணிப்பட்டியில் Chromiumஐப் பொருத்தவும்</translation>
+<translation id="388648406173476553">Chromiumமைத் தேவைக்கேற்ப மாற்றி கட்டுப்படுத்தும். சிலவற்றை நீங்கள் கவனிக்க வேண்டும் - விவரங்களுக்கு, கிளிக் செய்யவும்.</translation>
<translation id="3889543394854987837">Chromium ஐத் திறந்து, உலாவலைத் தொடங்க உங்கள் பெயரைக் கிளிக் செய்யவும்.</translation>
<translation id="3898493977366060150">Google ஸ்மார்ட்ஸ் மூலம் இணையத்தில் உலாவுதல்</translation>
<translation id="3965668104013180445">{0,plural, =1{1 மணிநேரத்தில் Chromium OS மீண்டும் தொடங்கும்}other{# மணிநேரத்தில் Chromium OS மீண்டும் தொடங்கும்}}</translation>
@@ -201,7 +202,7 @@
<translation id="7331920710658926971">உங்கள் மொபைலில் Chromiumஐ நிறுவவும். மொபைல் எண்ணுக்கு SMS ஒன்றை அனுப்புவோம்.</translation>
<translation id="7337881442233988129">Chromium</translation>
<translation id="7339898014177206373">புதிய சாளரம்</translation>
-<translation id="734373864078049451">உங்களின் இணையம், புத்தகக்குறிகள் மற்றும் பிற Chromium உருப்படிகள் இங்கே உள்ளன.</translation>
+<translation id="734373864078049451">உங்களின் இணையம், புக்மார்க்குகள் மற்றும் பிற Chromium உருப்படிகள் இங்கே உள்ளன.</translation>
<translation id="7344413941077984497"><ph name="NEW_PROFILE_NAME" /> எந்த இணையதளங்களைப் பார்க்கலாம் என்பதை அமைக்க, <ph name="BEGIN_LINK_1" /><ph name="DISPLAY_LINK" /><ph name="END_LINK_1" />க்குச் சென்று கட்டுப்பாடுகளையும் அமைப்புகளையும் உள்ளமைக்கலாம். இயல்புநிலை அமைப்புகளை மாற்றவில்லை எனில், <ph name="NEW_PROFILE_NAME" /> இணையத்தில் எல்லா தளங்களிலும் உலாவ முடியும்.
உங்கள் கணக்கை அணுகாதபடி <ph name="NEW_PROFILE_NAME" />ஐத் தடுக்க, நீங்கள் Chromiumஐப் பயன்படுத்தாத போது தவறாமல் உங்கள் சுயவிவரத்தைப் பூட்டவும். இதைச் செய்ய, உலாவியின் மேல் வலது மூலையில் உள்ள சுயவிவரப் பெயரைக் கிளிக் செய்து, "வெளியேறி, குழந்தைப்பூட்டை இயக்கு" என்பதைத் தேர்ந்தெடுக்கவும்.
@@ -269,7 +270,7 @@
<translation id="9089354809943900324">Chromium காலாவதியானது</translation>
<translation id="91086099826398415">புதிய Chromium &amp;தாவலில் இணைப்பைத் திற</translation>
<translation id="911206726377975832">உங்கள் உலாவுதல் தரவையும் நீக்க வேண்டுமா?</translation>
-<translation id="918373042641772655"><ph name="USERNAME" /> ஐத் துண்டிப்பது, இந்தச் சாதனத்தில் உள்ள உங்கள் வரலாறு, புத்தகக்குறிகள், அமைப்புகள் மற்றும் பிற Chromium தரவை அழிக்கும். உங்கள் Google கணக்கில் சேமிக்கப்பட்ட தரவு அழிக்கப்படாது, மேலும் <ph name="GOOGLE_DASHBOARD_LINK" />Google டாஷ்போர்டில்<ph name="END_GOOGLE_DASHBOARD_LINK" /> நிர்வகிக்கலாம்.</translation>
+<translation id="918373042641772655"><ph name="USERNAME" /> ஐத் துண்டிப்பது, இந்தச் சாதனத்தில் உள்ள உங்கள் வரலாறு, புக்மார்க்குகள், அமைப்புகள் மற்றும் பிற Chromium தரவை அழிக்கும். உங்கள் Google கணக்கில் சேமிக்கப்பட்ட தரவு அழிக்கப்படாது, மேலும் <ph name="GOOGLE_DASHBOARD_LINK" />Google டாஷ்போர்டில்<ph name="END_GOOGLE_DASHBOARD_LINK" /> நிர்வகிக்கலாம்.</translation>
<translation id="9190841055450128916">Chromium (mDNS-In)</translation>
<translation id="9197815481970649201">இப்போது Chromium இல் உள்நுழைந்துள்ளீர்கள்</translation>
<translation id="93478295209880648">Windows XP அல்லது Windows Vista ஆகியவற்றில் Chromium இனி ஆதரிக்கப்படாது என்பதால், அது சரியாகச் செயல்படாது</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_te.xtb b/chromium/chrome/app/resources/chromium_strings_te.xtb
index b3e5e459292..6a1b0874d50 100644
--- a/chromium/chrome/app/resources/chromium_strings_te.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_te.xtb
@@ -3,74 +3,74 @@
<translationbundle lang="te">
<translation id="1065672644894730302">మీ ప్రాధాన్యతలు చదవబడలేవు. కొన్ని లక్షణాలు అందుబాటులో ఉండకపోవచ్చు మరియు ప్రాధాన్యతలకు మార్పులు సేవ్ చేయబడకపోవచ్చు.</translation>
<translation id="1104942323762546749">Chromium మీ పాస్‌వర్డ్‌లను ఎగుమతి చేయాలనుకుంటోంది. దీనిని అనుమతించడం కోసం మీ Windows పాస్‌వర్డ్‌ని టైప్ చేయండి.</translation>
-<translation id="1115445892567829615">Chromium మీ డేటాను సింక్ చేయలేకపోయింది. దయచేసి మీ సింక్ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
+<translation id="1115445892567829615">Chromium మీ డేటాను సింక్ చేయ‌లేక‌పోయింది. దయచేసి మీ సింక్‌ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
<translation id="113122355610423240">మీ డిఫాల్ట్ బ్రౌజర్ Chromium</translation>
<translation id="1170115874949214249">మీ ఫోన్‌లో Chromiumను ఇన్‌స్టాల్ చేయండి. మేము మీ ఖాతా పునరుద్ధరణ ఫోన్ నంబర్‌కు SMS పంపుతాము.</translation>
<translation id="1174473354587728743">కంప్యూటర్‌ను షేర్‌ చేయాలా? ఇప్పుడు మీరు కోరుకున్న విధంగా Chromiumను సెటప్ చేయవచ్చు.</translation>
<translation id="1185134272377778587">Chromium గురించి</translation>
<translation id="1209657686917656928">{0,plural, =0{Chromium ఇప్పుడు తిరిగి ప్రారంభించబడుతుంది}=1{1 సెకనులో Chromium తిరిగి ప్రారంభించబడుతుంది}other{# సెకన్లలో Chromium తిరిగి ప్రారంభించబడుతుంది}}</translation>
<translation id="1267419686153937460">{0,plural, =1{ఒక రోజులో Chromiumని తిరిగి ప్రారంభించండి}other{# రోజుల్లో Chromiumని తిరిగి ప్రారంభించండి}}</translation>
-<translation id="1298199220304005244">Chromium OSని ఉపయోగించి సహాయాన్ని పొందండి</translation>
+<translation id="1298199220304005244">Chromium OSను ఉపయోగించడం గురించి సహాయాన్ని పొందండి</translation>
<translation id="1396446129537741364">Chromium పాస్‌వర్డ్‌లను చూపడానికి ప్రయత్నిస్తోంది.</translation>
<translation id="1414495520565016063">మీరు Chromiumకు సైన్ ఇన్ చేసారు!</translation>
<translation id="1502360822835740515">Chromiumను మీ డిఫాల్ట్ బ్రౌజర్‌గా చేయండి</translation>
-<translation id="151962892725702025">మీ డొమైన్ కోసం సమకాలీకరణ అందుబాటులో లేనందున Chromium OS మీ డేటాను సమకాలీకరించలేకపోయింది.</translation>
+<translation id="151962892725702025">మీ డొమైన్ కోసం సింక్‌ అందుబాటులో లేనందున, Chromium OS, మీ డేటాను సింక్ చేయ‌లేక‌పోయింది.</translation>
<translation id="1585657529869845941">ఇది కనిపిస్తే, <ph name="BEGIN_BOLD" />అయిన కూడా మార్చు<ph name="END_BOLD" />ను క్లిక్ చేయండి</translation>
<translation id="1668054258064581266">Chromium నుండి మీ ఖాతాను తీసివేసిన తర్వాత, ప్రభావవంతం కావడానికి మీరు మీ తెరిచిన ట్యాబ్‌లను మళ్లీ లోడ్ చేయాల్సి రావచ్చు.</translation>
-<translation id="1688750314291223739">వెబ్‌కు మీ వ్యక్తిగతీకరించిన బ్రౌజర్ ఫీచర్‌లను సేవ్ చేయడానికి సమకాలీకణని సెటప్ చేయండి మరియు వాటిని ఏదైనా కంప్యూటర్‌లోని Chromium నుండి యాక్సెస్ చేయండి.</translation>
-<translation id="1708666629004767631">Chromium యొక్క క్రొత్త సురక్షితమైన సంస్కరణ అందుబాటులో ఉంది.</translation>
-<translation id="1766096484055239003">అప్‌డేట్‌ని వర్తింపజేయడం కోసం మీరు Chromiumని పునఃప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
+<translation id="1688750314291223739">మీ వ్యక్తిగతీకరించిన బ్రౌజర్ ఫీచ‌ర్‌ల‌ను వెబ్‌లో సేవ్ చేయడానికి సమకాలీకణను సెటప్ చేయండి. వాటిని ఏదైనా కంప్యూటర్‌లోని Chromium నుండి యాక్సెస్‌ చేయండి.</translation>
+<translation id="1708666629004767631">Chromium యొక్క కొత్త సురక్షితమైన వెర్షన్ అందుబాటులో ఉంది.</translation>
+<translation id="1766096484055239003">అప్‌డేట్‌ను వర్తింపజేయడం కోసం మీరు Chromiumను పునఃప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
<translation id="1774152462503052664">నేపథ్యంలో Chromiumని అమలు చేయడానికి అనుమతించు</translation>
<translation id="1779356040007214683">Chromiumను సురక్షితం చేయడానికి, మేము <ph name="IDS_EXTENSION_WEB_STORE_TITLE" />లో జాబితా చేయబడని మరియు మీకు తెలియకుండానే జోడించబడిన కొన్ని పొడిగింపులను నిలిపివేసాము.</translation>
<translation id="1808667845054772817">Chromiumను మళ్లీ ఇన్‌స్టాల్ చేయి</translation>
-<translation id="1869480248812203386">సంభావ్య భద్రతాపరమైన దాడులకు సంబంధించిన వివరాలను Googleకి స్వయంచాలకంగా నివేదించడం ద్వారా Chromiumని సురక్షితంగా మరియు సులభంగా ఉపయోగించదగినదిగా చేయడంలో మీ సహాయం అందించవచ్చు.</translation>
-<translation id="1881322772814446296">మీరు నిర్వహించబడే ఖాతాతో సైన్ ఇన్ చేస్తున్నారు మరియు దీని నిర్వాహకునికి మీ Chromium ప్రొఫైల్‌పై నియంత్రణను అందిస్తున్నారు. మీ యాప్‌లు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌ల వంటి మీ Chromium డేటా శాశ్వతంగా <ph name="USER_NAME" />కు అనుబంధించబడుతుంది. మీరు Google ఖాతాల డాష్‌బోర్డ్ ద్వారా ఈ డేటాను తొలగించవచ్చు, కానీ ఈ డేటాను మరో ఖాతాతో అనుబంధించలేరు. మీరు ప్రస్తుతం ఉన్న మీ Chromium డేటాను వేరుగా ఉంచడానికి ఐచ్ఛికంగా క్రొత్త ప్రొఫైల్‌ను సృష్టించవచ్చు. <ph name="LEARN_MORE" /></translation>
+<translation id="1869480248812203386">భద్రతాపరమైన దాడులయ్యే అవకాశమున్న అన్ని సంఘటనలకు సంబంధించిన వివరాలను Googleకు ఆటోమేటిక్‌గా నివేదించడం ద్వారా Chromiumను సురక్షితంగా మరియు సులభంగా ఉపయోగించదగినదిగా చేయడంలో సాయం చేయవచ్చు.</translation>
+<translation id="1881322772814446296">మీరు నిర్వహించబడే ఖాతాతో సైన్ ఇన్ చేస్తున్నారు. దీని నిర్వాహకునికి మీ Chromium ప్రొఫైల్‌పై నియంత్రణను అందిస్తున్నారు. మీ యాప్‌లు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌ల వంటి మీ Chromium డేటా, శాశ్వతంగా <ph name="USER_NAME" />కు అనుబంధించబడుతుంది. మీరు Google ఖాతాల డాష్‌బోర్డ్ ద్వారా ఈ డేటాను తొలగించవచ్చు. కానీ ఈ డేటాను మరో ఖాతాతో అనుబంధించలేరు. ప్రస్తుతం ఉన్న మీ Chromium డేటాను వేరుగా ఉంచడానికి మీరు ఐచ్ఛికంగా కొత్త‌ ప్రొఫైల్‌ను సృష్టించవచ్చు. <ph name="LEARN_MORE" /></translation>
<translation id="1895626441344023878">{0,plural, =0{Chromium అప్‌డేట్ అందుబాటులో ఉంది}=1{Chromium అప్‌డేట్ అందుబాటులో ఉంది}other{# రోజులుగా Chromium అప్‌డేట్ అందుబాటులో ఉంది}}</translation>
<translation id="1911763535808217981">దీనిని ఆఫ్ చేయడం ద్వారా, మీరు Chromiumకి సైన్ ఇన్ చేయకుండానే Gmail లాంటి Google సైట్‌లలో సైన్ ఇన్ చేయగలరు</translation>
<translation id="1929939181775079593">Chromium ప్రతిస్పందించడం లేదు. ఇప్పుడు మళ్లీ ప్రారంభించాలా?</translation>
<translation id="1966382378801805537">Chromium డిఫాల్ట్ బ్రౌజర్‌ను నిశ్చయించలేదు లేదా సెట్ చేయలేదు</translation>
-<translation id="2008474315282236005">ఇది ఈ పరికరం నుండి 1 అంశాన్ని తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromiumకి <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
-<translation id="2117378023188580026">ఈ అప్‌డేట్‌ని వర్తింపజేయడం కోసం మీరు Chromiumని పునఃప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
+<translation id="2008474315282236005">ఇది ఈ పరికరం నుండి 1 అంశాన్ని తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromiumకు <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
+<translation id="2117378023188580026">ఈ అప్‌డేట్‌ను వర్తింపజేయడం కోసం మీరు Chromiumను పునఃప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
<translation id="2119636228670142020">&amp;Chromium OS గురించి</translation>
<translation id="2178765360243863853">మీరు ఇప్పుడే Chromiumని పునఃప్రారంభించాలి</translation>
-<translation id="2241627712206172106">మీరు కంప్యూటర్‌ను షేర్ చేస్తే, స్నేహితులు మరియు కుటుంబ సభ్యులు విడివిడిగా బ్రౌజ్ చేయవచ్చు మరియు Chromiumను వారికి నచ్చిన రీతిలో సెటప్ చేసుకోవచ్చు.</translation>
+<translation id="2241627712206172106">మీరు కంప్యూటర్‌ను షేర్‌ చేస్తే, స్నేహితులు, కుటుంబ సభ్యులు విడివిడిగా బ్రౌజ్ చేయవచ్చు. Chromiumను వారికి నచ్చిన రీతిలో సెటప్ చేసుకోవచ్చు.</translation>
<translation id="2265088490657775772">మీ iPhoneలో Chromiumని పొందండి</translation>
<translation id="2347108572062610441">ఈ పొడిగింపు మీరు Chromiumని ప్రారంభించినప్పుడు చూపబడే పేజీని మార్చింది.</translation>
<translation id="2396765026452590966"><ph name="EXTENSION_NAME" /> పొడిగింపు మీరు Chromiumని ప్రారంభించినప్పుడు చూపబడే పేజీని మార్చింది.</translation>
<translation id="2483889755041906834">Chromiumలో</translation>
<translation id="2485422356828889247">అన్ఇన్‌స్టాల్ చేయి</translation>
<translation id="2527042973354814951"><ph name="PLUGIN_NAME" />ని ప్రారంభించడానికి Chromiumని పునఃప్రారంభించండి</translation>
-<translation id="2535480412977113886">మీ ఖాతా సైన్-ఇన్ వివరాల గడువు ముగిసినందున Chromium OS మీ డేటాను సమకాలీకరించలేకపోయింది.</translation>
+<translation id="2535480412977113886">మీ ఖాతా సైన్-ఇన్ వివరాల గడువు ముగిసినందున Chromium OS మీ డేటాను సింక్ చేయలేకపోయింది.</translation>
<translation id="2560420686485554789">ఫైల్‌లను డౌన్‌లోడ్ చేయడానికి Chromiumకు నిల్వ యాక్సెస్ అవసరం</translation>
<translation id="2572494885440352020">Chromium సహాయకం</translation>
-<translation id="2587578672395088481">అప్‌డేట్‌ను వర్తింపజేయడానికి Chromium OSని పునఃప్రారంభించాలి.</translation>
+<translation id="2587578672395088481">అప్‌డేట్‌ను వర్తింపజేయడానికి Chromium OSను పునఃప్రారంభించాలి.</translation>
<translation id="2647554856022461007">Chromium మీ బ్రౌజింగ్ అనుభవాన్ని మెరుగుపరచడానికి వెబ్ సేవలను ఉపయోగించవచ్చు. మీరు ఈ సేవలను ఐచ్ఛికంగా నిలిపివేయవచ్చు. <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation>
-<translation id="2648074677641340862">ఇన్‌స్టాలేషన్ సమయంలో ఆపరేటింగ్ సిస్టమ్ ఎర్రర్ ఏర్పడింది. దయచేసి Chromiumను మళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
+<translation id="2648074677641340862">ఇన‌స్ట‌లేష‌న్‌ సమయంలో ఆపరేటింగ్ సిస్టమ్ ఎర్ర‌ర్‌ సంభవించింది. దయచేసి Chromiumను మళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
<translation id="2711502716910134313">Chromium ట్యాబ్</translation>
<translation id="2718390899429598676">అదనపు భద్రత కోసం, Chromium మీ డేటాను ఎన్‌క్రిప్ట్ చేస్తుంది.</translation>
<translation id="2770231113462710648">డిఫాల్ట్ బ్రౌజర్‌ను దీనికి మార్చు:</translation>
<translation id="2799223571221894425">మళ్లీ ప్రారంభించు</translation>
<translation id="2847479871509788944">Chromium నుండి తీసివేయి...</translation>
-<translation id="2886012850691518054">ఐచ్ఛికం: Googleకు వినియోగ‌ గణాంకాలను, క్రాష్ నివేదికలను ఆటోమేటిక్‌గా పంపడం ద్వారా Chromiumను మరింత మెరుగుపరచడానికి సహాయం చేస్తుంది.</translation>
+<translation id="2886012850691518054">ఐచ్ఛికం: వినియోగ గణాంకాలు మరియు క్రాష్ నివేదికలను ఆటోమేటిక్‌గా Googleకు పంపడం ద్వారా Chromiumను మరింత మెరుగుపరచడానికి సహాయం చేయండి.</translation>
<translation id="2898082584336937987">మీ ఫోన్‌లో Chromiumను ఇన్‌స్టాల్ చేయండి. మేము మీ ఫోన్ నంబర్‌కు SMS పంపుతాము: <ph name="PHONE_NUMBER" /></translation>
<translation id="2910007522516064972">&amp;Chromium గురించి</translation>
<translation id="2977470724722393594">Chromium తాజాగా ఉంది</translation>
<translation id="3032787606318309379">Chromiumకి జోడిస్తోంది...</translation>
<translation id="3046695367536568084">మీరు అనువర్తనాలను ఉపయోగించడానికి Chromiumకు సైన్ ఇన్ చేయాలి. ఇది పరికరాల్లో మీ అనువర్తనాలు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లను సమకాలీకరించడానికి Chromiumను అనుమతిస్తుంది.</translation>
<translation id="3052899382720782935">{0,plural, =1{1 నిమిషంలో Chromium తిరిగి ప్రారంభించబడుతుంది}other{# నిమిషాల్లో Chromium తిరిగి ప్రారంభించబడుతుంది}}</translation>
-<translation id="3068515742935458733">Googleకు వినియోగ గణాంకాలు, <ph name="UMA_LINK" />ను పంపడం ద్వారా Chromiumను మెరుగుపరచడంలో సహాయపడండి</translation>
-<translation id="3103660991484857065">ఇన్‌స్టాలర్ ఆర్కైవ్‌ను వాస్తవ పరిమాణానికి తీసుకు రావడంలో విఫలమైంది. దయచేసి Chromiumను మళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
+<translation id="3068515742935458733">వినియోగ గణాంకాలు మరియు <ph name="UMA_LINK" />ను Googleకు పంపడం ద్వారా Chromiumను మెరుగుపరచడంలో సహాయపడండి</translation>
+<translation id="3103660991484857065">ఇన్‌స్టాలర్ ఆర్కైవ్‌ను వాస్తవ పరిమాణానికి తీసుకుని రావడంలో విఫలమైంది. దయచేసి Chromiumను మళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
<translation id="3130323860337406239">Chromium మీ మైక్రోఫోన్‌ని ఉపయోగిస్తోంది.</translation>
<translation id="3155163173539279776">Chromiumను పునఃప్రారంభించండి</translation>
-<translation id="3179665906251668410">Chromium అజ్ఞా&amp;త విండోలో లింక్‌ని తెరువు</translation>
+<translation id="3179665906251668410">Chromium అజ్ఞా&amp;త విండోలో లింక్‌ను తెరువు</translation>
<translation id="3190315855212034486">అయ్యో! Chromium క్రాష్ అయ్యింది. ఇప్పుడే మళ్లీ ప్రారంభించాలా?</translation>
<translation id="3229526316128325841">Chromium మీ పాస్‌వర్డ్‌లను ఎగుమతి చేయాలనుకుంటోంది.</translation>
<translation id="3256316712990552818">Chromiumకి కాపీ చేయబడింది</translation>
-<translation id="3258596308407688501">Chromium దీని డేటా డైరెక్టరీని చదవలేదు మరియు దీనిలో వ్రాయలేదు: <ph name="USER_DATA_DIRECTORY" /></translation>
+<translation id="3258596308407688501">Chromium దీని డేటా డైరెక్టరీని చదవలేదు మరియు దీనిలో రాయ‌లేదు: <ph name="USER_DATA_DIRECTORY" /></translation>
<translation id="328888136576916638">Google API కీలు లేవు. Chromium కార్యాచరణలో కొంత భాగం నిలిపివేయబడుతుంది.</translation>
<translation id="3296368748942286671">Chromium మూసివేయబడినప్పుడు నేపథ్య అనువర్తనాలను అమలు చేయడాన్ని కొనసాగించు</translation>
<translation id="331951419404882060">సైన్ ఇన్ చేయడంలో ఎర్రర్ ఏర్పడినందున Chromium OS మీ డేటాను సింక్ చేయలేకపోయింది.</translation>
-<translation id="3474745554856756813">ఇది ఈ పరికరం నుండి <ph name="ITEMS_COUNT" /> అంశాలను తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromiumకి <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
+<translation id="3474745554856756813">ఇది ఈ పరికరం నుండి <ph name="ITEMS_COUNT" /> అంశాలను తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromiumకు <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
<translation id="3479552764303398839">ఇప్పుడు కాదు</translation>
<translation id="3509308970982693815">దయచేసి అన్ని Chromium విండోలను మూసివేసి, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="352783484088404971">Chromium నుండి తీసివేయి...</translation>
@@ -84,17 +84,18 @@
<translation id="378917192836375108">వెబ్‌లో ఏదైనా ఒక ఫోన్ నంబర్‌ను క్లిక్ చేసి, దానికి Skypeతో కాల్ చేయగలిగే సదుపాయాన్ని Chromium మీకు ఇస్తుంది!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromiumని మీ విధి పట్టీకి పిన్ చేయండి</translation>
+<translation id="388648406173476553">Chromiumను అనుకూలీకరించండి మరియు నియంత్రించండి. మీరు గమనించాల్సిన విషయం ఒకటి ఉంది - వివరాల కోసం క్లిక్ చేయండి.</translation>
<translation id="3889543394854987837">Chromiumను తెరిచి, బ్రౌజింగ్‌ను ప్రారంభించడానికి మీ పేరును క్లిక్ చేయండి.</translation>
<translation id="3898493977366060150">Google స్మార్ట్‌లతో వెబ్ బ్రౌజింగ్</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS ఒక గంటలో మళ్లీ ప్రారంభించబడుతుంది}other{Chromium OS # గంటల్లో మళ్లీ ప్రారంభించబడుతుంది}}</translation>
-<translation id="4036079820698952681"><ph name="BEGIN_LINK" />ప్రస్తుత సెట్టింగ్‌లను<ph name="END_LINK" /> నివేదించడం ద్వారా Chromiumని మెరుగుపరచడంలో సహాయపడండి</translation>
-<translation id="4050175100176540509">ముఖ్యమైన భద్రతా మెరుగుదలలు మరియు కొత్త లక్షణాలు తాజా సంస్కరణలో అందుబాటులో ఉన్నాయి.</translation>
+<translation id="4036079820698952681"><ph name="BEGIN_LINK" />ప్రస్తుత సెట్టింగ్‌లను<ph name="END_LINK" /> నివేదించడం ద్వారా Chromiumను మెరుగుపరచడంలో సహాయపడండి</translation>
+<translation id="4050175100176540509">ముఖ్యమైన భద్రతా మెరుగుదలలు మరియు కొత్త ఫీచర్‌లు తాజా వెర్షన్‌లో అందుబాటులో ఉన్నాయి.</translation>
<translation id="407254336480250557"><ph name="SMALL_PRODUCT_LOGO" /> <ph name="BEGIN_BOLD" />Chromium<ph name="END_BOLD" />ని ఎంచుకోండి</translation>
<translation id="421369550622382712">Chromium కోసం గొప్ప అనువర్తనాలు, ఆటలు, పొడిగింపులు మరియు థీమ్‌లను కనుగొనండి.</translation>
-<translation id="4222580632002216401">ఇప్పుడు మీరు Chromiumకు సైన్ ఇన్ చేసారు! మీ నిర్వాహకులు సమకాలీకరణను నిలిపివేసారు.</translation>
+<translation id="4222580632002216401">ఇప్పుడు మీరు Chromiumకు సైన్ ఇన్ చేశారు! మీ నిర్వాహకులు సింక్‌ను నిలిపివేశారు.</translation>
<translation id="4224199872375172890">Chromium తాజాగా ఉంది.</translation>
<translation id="4230135487732243613">మీ Chromium డేటాను ఈ ఖాతాకు జోడించాలా?</translation>
-<translation id="4271805377592243930">Chromiumతో సహాయాన్ని పొందండి</translation>
+<translation id="4271805377592243930">Chromium గురించి సహాయాన్ని పొందండి</translation>
<translation id="4285930937574705105">పేర్కొనబడని ఎర్రర్ కారణంగా ఇన్‌స్టాలేషన్ విఫలమైంది. ప్రస్తుతం Chromium అమలు చేయబడుతుంటే, దయచేసి దీనిని మూసివేసి, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="4407044323746248786">ఏదేమైనా Chromium నుండి నిష్క్రమించాలా?</translation>
<translation id="4415566066719264597">నేపథ్యంలో అమలయ్యేందుకు Chromiumని అనుమతించండి</translation>
@@ -102,8 +103,8 @@
<translation id="4567424176335768812">మీరు <ph name="USER_EMAIL_ADDRESS" />గా సైన్ ఇన్ చేసారు. ఇప్పుడు మీరు సైన్ ఇన్ చేసిన అన్ని పరికరాల్లో మీ బుక్‌మార్క్‌లు, చరిత్ర మరియు ఇతర సెట్టింగ్‌లను యాక్సెస్ చేయవచ్చు.</translation>
<translation id="459535195905078186">Chromium అనువర్తనాలు</translation>
<translation id="4621240073146040695">దాదాపుగా నవీకృతంగా ఉంది! నవీకరణను పూర్తి చేయడానికి Chromiumని పునఃప్రారంభించండి.</translation>
-<translation id="4677944499843243528">ప్రొఫైల్‌ని మరొక కంప్యూటర్ (<ph name="HOST_NAME" />)లో మరో Chromium ప్రాసెస్ (<ph name="PROCESS_ID" />) ఉపయోగిస్తున్నట్లు కనిపిస్తోంది. Chromium ప్రొఫైల్‌ని లాక్ చేసినందున అది పాడవదు. ఈ ప్రొఫైల్‌ని వేరే ఇతర ప్రాసెస్‌లు ఏవీ ఉపయోగించడం లేదని మీకు ఖచ్చితంగా తెలిస్తే, మీరు ప్రొఫైల్‌ని అన్‌లాక్ చేసి Chromiumని మళ్లీ లాంచ్ చేయవచ్చు.</translation>
-<translation id="469338717132742108">Chromium OSతో సహాయాన్ని పొందండి</translation>
+<translation id="4677944499843243528">ఈ ప్రొఫైల్‌ను మరొక కంప్యూటర్ (<ph name="HOST_NAME" />)లో మరో Chromium ప్రాసెస్ (<ph name="PROCESS_ID" />) ఉపయోగిస్తున్నట్లు కనిపిస్తోంది. Chromium ప్రొఫైల్‌ను లాక్ చేసినందున అది పాడవదు. ఈ ప్రొఫైల్‌ను వేరే ప్రాసెస్‌లు ఏవీ ఉపయోగించడం లేదని మీకు ఖచ్చితంగా తెలిస్తే, ప్రొఫైల్‌ను అన్‌లాక్ చేసి Chromiumను మళ్లీ ప్రారంభించవచ్చు.</translation>
+<translation id="469338717132742108">Chromium OS గురించి సహాయాన్ని పొందండి</translation>
<translation id="4708774505295300557">ఒకరు ఈ కంప్యూటర్‌లో మునుపు <ph name="ACCOUNT_EMAIL_LAST" /> లాగా Chromiumకు సైన్ ఇన్ చేసారు. మీ సమాచారాన్ని విడిగా ఉంచేందుకు దయచేసి కొత్త Chromium వినియోగదారును సృష్టించండి.</translation>
<translation id="4714956846925717402">Chromiumకి వేగవంతంగా వెళ్లండి</translation>
<translation id="4746050847053251315">ఏదేమైనా Chromiumని మూసివేయాలా?</translation>
@@ -118,21 +119,21 @@
<translation id="5116586539350239523">Chromium మీ వ్యక్తిగత వివరాలను సురక్షితంగా నిల్వ చేస్తుంది కాబట్టి మీరు వాటిని మళ్లీ టైప్ చేయాల్సిన అవసరం లేదు.</translation>
<translation id="5181952534059945058">ఈ పేజీ చాలా ఎక్కువ మెమరీని ఉపయోగిస్తోంది, కాబట్టి Chromium కొంత కంటెంట్‌ను తీసివేసింది.</translation>
<translation id="5277894862589591112">మీ మార్పులను వర్తింపజేయడానికి, Chromiumని పునఃప్రారంభించండి</translation>
-<translation id="5358375970380395591">మీరు నిర్వహించబడే ఖాతాతో సైన్ ఇన్ చేస్తున్నారు మరియు దీని నిర్వాహకునికి మీ Chromium ప్రొఫైల్‌పై నియంత్రణను అందిస్తున్నారు. మీ యాప్‌లు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌ల వంటి మీ Chromium డేటా శాశ్వతంగా <ph name="USER_NAME" />కు అనుబంధించబడుతుంది. మీరు Google ఖాతాల డాష్‌బోర్డ్ ద్వారా ఈ డేటాను తొలగించవచ్చు, కానీ ఈ డేటాను మరో ఖాతాతో అనుబంధించలేరు. <ph name="LEARN_MORE" /></translation>
+<translation id="5358375970380395591">మీరు నిర్వహించబడే ఖాతాతో సైన్ ఇన్ చేస్తున్నారు. దీని నిర్వాహకునికి మీ Chromium ప్రొఫైల్‌పై నియంత్రణను అందిస్తున్నారు. మీ యాప్‌లు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌ల వంటి మీ Chromium డేటా, శాశ్వతంగా <ph name="USER_NAME" />కు అనుబంధించబడుతుంది. మీరు Google ఖాతాల డాష్‌బోర్డ్ ద్వారా ఈ డేటాను తొలగించవచ్చు. కానీ ఈ డేటాను మరో ఖాతాతో అనుబంధించలేరు. <ph name="LEARN_MORE" /></translation>
<translation id="5386450000063123300">Chromium నవీకరించబడుతోంది (<ph name="PROGRESS_PERCENT" />)</translation>
<translation id="538767207339317086">Chromium సైన్-ఇన్‌ని అనుమతించండి</translation>
-<translation id="5398878173008909840">క్రొత్త Chromium సంస్కరణ అందుబాటులో ఉంది.</translation>
+<translation id="5398878173008909840">కొత్త Chromium వెర్షన్ అందుబాటులో ఉంది.</translation>
<translation id="5416696090975899932">అంతర్నిర్మిత PDF వ్యూయర్ లేనప్పుడు Chromium ముద్రణ ప్రివ్యూని చూపించదు.</translation>
<translation id="5427571867875391349">Chromiumను మీ డిఫాల్ట్ బ్రౌజర్‌గా సెట్ చేయండి</translation>
<translation id="5438241569118040789"><ph name="PAGE_TITLE" /> - Chromium బీటా</translation>
-<translation id="5466153949126434691">Chromium స్వయంచాలకంగా నవీకరించబడుతుంది కనుక మీరు ఎల్లప్పుడూ తాజా సంస్కరణని కలిగి ఉంటారు. ఈ డౌన్‌లోడ్ పూర్తయినప్పుడు, Chromium పునఃప్రారంభించబడుతుంది మరియు మీరు మీ పనిని కొనసాగించవచ్చు.</translation>
+<translation id="5466153949126434691">Chromium ఆటోమేటిక్‌గా అప్‌డేట్ అవుతుంది కాబట్టి మీ వద్ద ఎప్పుడూ తాజా వెర్షన్ ఉంటుంది. ఈ డౌన్‌లోడ్ పూర్తయినప్పుడు, Chromium పునఃప్రారంభించబడుతుంది, మీరు మీ పనిని కొనసాగించవచ్చు.</translation>
<translation id="5479196819031988440">Chromium OS ఈ పేజీని తెరవలేదు.</translation>
<translation id="5480860683791598150">ఈ సైట్‌తో మీ స్థానాన్ని షేర్ చేయడానికి Chromiumకు మీ స్థాన యాక్సెస్ అవసరం</translation>
<translation id="549669000822060376">దయచేసి Chromium తాజా సిస్టమ్ నవీకరణలను ఇన్‌స్టాల్ చేస్తున్నప్పుడు వేచి ఉండండి.</translation>
<translation id="5529843986978123325">{0,plural, =1{Chromium OS 1 నిమిషంలో మళ్లీ ప్రారంభించబడుతుంది}other{Chromium OS # నిమిషాల్లో మళ్లీ ప్రారంభించబడుతుంది}}</translation>
<translation id="5631814766731275228">Chromium పేరు మరియు చిత్రం</translation>
<translation id="5634636535844844681">Chromiumకి Windows 7 లేదా అంతకంటే ఆధునికమైనది ఉండటం ఆవశ్యకం.</translation>
-<translation id="5680901439334282664">Chromiumకి సైన్ ఇన్ చేయండి</translation>
+<translation id="5680901439334282664">Chromiumకు సైన్ ఇన్ చేయండి</translation>
<translation id="5698481217667032250">Chromiumను ఈ భాషలో ప్రదర్శించు</translation>
<translation id="5712253116097046984">ఈ అప్‌డేట్‌ని వర్తింపజేయడం కోసం మీరు Chromium OSని మళ్లీ ప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
<translation id="5726838626470692954">మీ నిర్వాహకులు తప్పనిసరిగా మిమ్మల్ని Chromium నుండి తీసివేసి, తిరిగి జోడించాలి.</translation>
@@ -142,19 +143,19 @@
<translation id="5862307444128926510">Chromiumకు స్వాగతం</translation>
<translation id="5877064549588274448">ఛానెల్ మార్చబడింది. మార్పులను వర్తింపజేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
<translation id="5895138241574237353">మళ్ళీ ప్రారంభించు</translation>
-<translation id="5906655207909574370">దాదాపు నవీకృతంగా ఉంది! నవీకరణను పూర్తి చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
-<translation id="5987687638152509985">సింక్‌ను ప్రారంభించడానికి Chromiumని అప్‌డేట్ చేయండి</translation>
+<translation id="5906655207909574370">దాదాపు తాజాగా ఉంది! అప్‌డేట్‌ను పూర్తి చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
+<translation id="5987687638152509985">సింక్‌ను ప్రారంభించడానికి Chromiumను అప్‌డేట్ చేయండి</translation>
<translation id="6013050204643758987"><ph name="BEGIN_LINK_LINUX_OSS" />Linux (బీటా) <ph name="END_LINK_LINUX_OSS" /> లాగానే, Chromium OS కూడా అదనపు <ph name="BEGIN_LINK_CROS_OSS" /> ఓపెన్ సోర్స్ సాఫ్ట్‌వేర్‌ <ph name="END_LINK_CROS_OSS" /> మూలంగానే సాధ్యమైంది.</translation>
<translation id="6040143037577758943">మూసివేయి</translation>
-<translation id="6055895534982063517">క్రొత్త Chromium సంస్కరణ అందుబాటులో ఉంది, ఇది ఎప్పటి కంటే వేగంగా ఉంది.</translation>
+<translation id="6055895534982063517">కొత్త Chromium వెర్షన్ అందుబాటులో ఉంది, ఇది మునుపటి కంటే వేగవంతంగా ఉంటుంది.</translation>
<translation id="6063093106622310249">&amp;Chromiumలో తెరవండి</translation>
<translation id="6072279588547424923">Chromiumకు <ph name="EXTENSION_NAME" /> జోడించబడింది</translation>
<translation id="608189560609172163">సైన్ ఇన్ చేయడంలో ఎర్రర్ కారణంగా Chromium మీ డేటాను సింక్ చేయలేకపోయింది.</translation>
-<translation id="6096348254544841612">Chromiumని అనుకూలీకరించండి మరియు నియంత్రించండి. అప్‌డేట్ అందుబాటులో ఉంది.</translation>
+<translation id="6096348254544841612">Chromiumను అనుకూలీకరించండి మరియు నియంత్రించండి. అప్‌డేట్ అందుబాటులో ఉంది.</translation>
<translation id="6120345080069858279">Chromium ఈ పాస్‌వర్డ్‌ను మీ Google ఖాతాలో సేవ్ చేస్తుంది. మీరు దీనిని గుర్తుంచుకోవాల్సిన అవసరం లేదు.</translation>
<translation id="6129621093834146363"><ph name="FILE_NAME" /> హానికరం, కావున Chromium దాన్ని బ్లాక్ చేసింది.</translation>
<translation id="620022061217911843">అప్‌డేట్‌ని వర్తింపజేయడం కోసం మీరు Chromium OSని మళ్లీ ప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
-<translation id="6212496753309875659">ఈ కంప్యూటర్‌లో ఇదివరకే మరింత తాజాదైన Chromium వెర్షన్ ఉంది. సాఫ్ట్‌వేర్ పని చేయకపోతే, దయచేసి Chromiumను అన్ఇన్‌స్టాల్ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="6212496753309875659">ఈ కంప్యూటర్‌లో ఇప్పటికే మరింత తాజాదైన Chromium వెర్షన్ ఉంది. సాఫ్ట్‌వేర్ పని చేయకపోతే, దయచేసి Chromiumను అన్ఇన్‌స్టాల్ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="6248213926982192922">Chromiumను డిఫాల్ట్ బ్రౌజర్‌గా చేయి</translation>
<translation id="6268381023930128611">Chromium నుండి సైన్ అవుట్ చేయాలా?</translation>
<translation id="6295779123002464101"><ph name="FILE_NAME" /> హానికరం కావచ్చు, కావున Chromium దాన్ని బ్లాక్ చేసింది.</translation>
@@ -163,94 +164,94 @@
<translation id="6334986366598267305">ఇప్పుడు మీ Google ఖాతాతో, షేర్ చేయ‌బ‌డిన కంప్యూట‌ర్‌ల‌లో Chromiumను సులభంగా ఉపయోగించవచ్చు.</translation>
<translation id="6373523479360886564">మీరు ఖచ్చితంగా Chromiumను అన్ఇన్‌స్టాల్ చేయాలనుకుంటున్నారా?</translation>
<translation id="6400072781405947421">Chromiumకి ఇప్పుడు Mac OS X 10.9లో మద్దతు లేనందున ఇది సరిగ్గా పని చేయకపోవచ్చు.</translation>
-<translation id="6403826409255603130">Chromium అనేది మెరుపు వేగంతో వెబ్‌పేజీలను మరియు యాప్‌లను అమలు చేసే వెబ్ బ్రౌజర్. ఇది వేగవంతమైనది, స్థిరమైనది మరియు ఉపయోగించడానికి సులభమైనది. Chromiumలో అంతర్గతంగా అందజేసే 'మాల్వేర్ మరియు ఫిషింగ్ రక్షణ'తో మరింత సురక్షితంగా వెబ్‌లో బ్రౌజ్ చేయండి.</translation>
+<translation id="6403826409255603130">Chromium అనేది మెరుపు వేగంతో వెబ్‌పేజీలను, యాప్‌ల‌ను అమలు చేసే వెబ్ బ్రౌజర్. ఇది వేగవంతమైనది, స్థిరమైనది, ఉపయోగించడానికి సులభమైనది. Chromiumలో రూపొందించిన మాల్‌వేర్‌ మరియు ఫిషింగ్ రక్షణతో మరింత సురక్షితంగా వెబ్‌లో బ్రౌజ్ చేయండి.</translation>
<translation id="6434250628340475518">Chromium OS సిస్టమ్</translation>
<translation id="6457450909262716557">{SECONDS,plural, =1{Chromium 1 సెకనులో పునఃప్రారంభమవుతుంది}other{Chromium # సెకన్లలో పునఃప్రారంభమవుతుంది}}</translation>
<translation id="6475912303565314141">ఇది మీరు Chromiumని ప్రారంభించేటప్పుడు చూపబడే పేజీని కూడా నియంత్రిస్తుంది.</translation>
-<translation id="6485906693002546646">మీరు మీ Chromium అంశాలను సింక్ చేయ‌డానికి <ph name="PROFILE_EMAIL" />ను ఉపయోగిస్తున్నారు. మీ సింక్‌ ప్రాధాన్యతను అప్‌డేట్ చేయ‌డానికి లేదా Google ఖాతా లేకుండా Chromiumను ఉపయోగించడానికి, <ph name="SETTINGS_LINK" />ను సందర్శించండి.</translation>
+<translation id="6485906693002546646">మీరు, మీ Chromium అంశాలను సింక్ చేయ‌డానికి <ph name="PROFILE_EMAIL" />ను ఉపయోగిస్తున్నారు. మీ సింక్‌ ప్రాధాన్యతను అప్‌డేట్ చేయ‌డానికి లేదా Google ఖాతా లేకుండా Chromiumను ఉపయోగించడానికి, <ph name="SETTINGS_LINK" />ను సందర్శించండి.</translation>
<translation id="6510925080656968729">Chromiumను అన్ఇన్‌స్టాల్ చేయి</translation>
<translation id="6570579332384693436">అక్షరక్రమ లోపాలను పరిష్కరించడానికి, మీరు వచన ఫీల్డ్‌లలో టైప్ చేసే వచనాన్ని, Chromium Googleకి పంపుతుంది</translation>
<translation id="6598877126913850652">Chromium నోటిఫికేషన్ సెట్టింగ్‌లకు వెళ్లు</translation>
<translation id="6676384891291319759">ఇంటర్నెట్‌ను ఆక్సెస్ చెయ్యండి</translation>
-<translation id="6717134281241384636">మీ ప్రొఫైల్ క్రొత్త Chromium వెర్షన్ అయినందున ఇది ఉపయోగించబడదు.
+<translation id="6717134281241384636">మీ ప్రొఫైల్, కొత్త Chromium వెర్షన్‌కు చెందినది కాబట్టి, దీనిని ఉపయోగించడం సాధ్యపడదు.
-కొన్ని లక్షణాలు అందుబాటులో ఉండకపోవచ్చు. దయచేసి వేరొక ప్రొఫైల్ డైరెక్టరీని పేర్కొనండి లేదా Chromium యొక్క క్రొత్త వెర్షన్‌ని ఉపయోగించండి.</translation>
-<translation id="6734080038664603509">&amp;Chromiumని అప్‌డేట్ చేయండి</translation>
+కొన్ని ఫీచర్‌లు అందుబాటులో ఉండకపోవచ్చు. దయచేసి వేరొక ప్రొఫైల్ డైరెక్టరీని పేర్కొనండి లేదా Chromium యొక్క కొత్త వెర్షన్‌ను ఉపయోగించండి.</translation>
+<translation id="6734080038664603509">&amp;Chromiumను అప్‌డేట్ చేయండి</translation>
<translation id="6734291798041940871">మీ కంప్యూటర్‌లోని వినియోగదారులందరికీ Chromium ఇప్పటికే ఇన్‌స్టాల్ చేయబడింది.</translation>
-<translation id="6810143991807788455">ప్రస్తుత సెట్టింగ్‌లను నివేదించడం ద్వారా Chromiumని మెరుగుపరచడంలో సహాయపడండి</translation>
+<translation id="6810143991807788455">ప్రస్తుత సెట్టింగ్‌లను నివేదించడం ద్వారా Chromiumను మెరుగుపరచడంలో సహాయపడండి</translation>
<translation id="6857782730669500492">Chromium - <ph name="PAGE_TITLE" /></translation>
<translation id="6863361426438995919">Google Pay (Chromiumకి కాపీ చేయబడింది)</translation>
<translation id="6893813176749746474">Chromium నవీకరించబడింది, కానీ మీరు దీన్ని గత 30 రోజులుగా ఉపయోగించలేదు.</translation>
<translation id="692832138936263906">Chromium మీరు చూసే పేజీలలోని ఫోటోలను Google సర్వర్‌లకు పంపడం ద్వారా ఆయా ఫోటోలలో ఉండే ఆకారాలు మరియు అక్షరాలను గుర్తించి, ఆ పేజీలలోని కంటెంట్‌ని మీకు మరింత అర్థవంతంగా తెలియజేయడానికి కృషి చేస్తుంది.</translation>
<translation id="6964305034639999644">Chromium అజ్ఞా&amp;త విండోలో లింక్‌ని తెరువు</translation>
-<translation id="6970811910055250180">మీ పరికరాన్ని నవీకరిస్తోంది...</translation>
+<translation id="6970811910055250180">మీ పరికరాన్ని అప్‌డేట్ చేస్తోంది...</translation>
<translation id="6990124437352146030">ఈ సైట్ కోసం మీ మైక్రోఫోన్‌ను యాక్సెస్ చేయడానికి Chromiumకు అనుమతి అవసరం</translation>
-<translation id="705851970750939768">Chromiumని అప్‌డేట్ చేయి</translation>
-<translation id="7066436765290594559">Chromium OS మీ డేటాను సింక్ చేయలేకపోయింది. దయచేసి మీ సింక్ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
-<translation id="7162152143154757523">మీరు బ్రౌజర్‌లో టైప్ చేసే వాటిని Google సర్వర్‌లకు పంపడం ద్వారా, Google శోధనలో ఉపయోగించేటటువంటి స్పెల్-చెకింగ్ సాంకేతికతను ఉపయోగించడానికి మిమ్మల్ని అనుమతించడం ద్వారా Chromium మరింత మెరుగైన స్పెల్-చెకింగ్ సాంకేతికతను అందించగలదు.</translation>
+<translation id="705851970750939768">Chromiumను అప్‌డేట్ చేయి</translation>
+<translation id="7066436765290594559">Chromium OS మీ డేటాను సింక్ చేయ‌లేక‌పోయింది. దయచేసి మీ సింక్‌ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
+<translation id="7162152143154757523">మీరు బ్రౌజర్‌లో టైప్ చేసే వాటిని Google సర్వర్‌లకు పంపించడం ద్వారా స్మార్ట్ స్పెల్‌చెక్‌ను Google Chromium అందిస్తుంది. త‌ద్వారా Google శోధనలో స్మార్ట్ స్పెల్‌చెక్‌ పరిజ్ఞానాన్ని మీరు ఉపయోగించడానికి అనుమ‌తిస్తుంది</translation>
<translation id="7196312274710523067">Chromiumను ప్రారంభించడం సాధ్యపడలేదు. మళ్లీ ప్రయత్నించండి.</translation>
<translation id="7205698830395646142">Chromium మెనూలో దాచండి</translation>
<translation id="7223968959479464213">విధి నిర్వాహకుడు - Chromium</translation>
-<translation id="731644333568559921">&amp;Chromium OSని అప్‌డేట్ చేయండి</translation>
+<translation id="731644333568559921">&amp;Chromium OSను అప్‌డేట్ చేయండి</translation>
<translation id="731795002583552498">Chromiumని నవీకరిస్తోంది</translation>
<translation id="7318036098707714271">మీ ప్రాధాన్యతల ఫైల్ పాడైంది లేదా చెల్లదు. Chromium మీ సెట్టింగ్‌లను పునరుద్ధరించలేకపోయింది.</translation>
<translation id="7331920710658926971">మీ ఫోన్‌లో Chromiumని ఇన్‌స్టాల్ చేయండి. మేము మీ ఫోన్ నంబర్‌కు SMS పంపుతాము.</translation>
<translation id="7337881442233988129">Chromium</translation>
<translation id="7339898014177206373">కొత్త విండో</translation>
<translation id="734373864078049451">మీ వెబ్, బుక్‌మార్క్‌లు మరియు ఇతర Chromium అంశాలు ఇక్కడ చూపబడతాయి.</translation>
-<translation id="7344413941077984497"><ph name="NEW_PROFILE_NAME" /> వీక్షించగల వెబ్‌సైట్‌లను సెట్ చేయడానికి, మీరు <ph name="BEGIN_LINK_1" /><ph name="DISPLAY_LINK" /><ph name="END_LINK_1" />ని సందర్శించడం ద్వారా పరిమితులు మరియు సెట్టింగ్‌లను కాన్ఫిగర్ చేయవచ్చు. మీరు డిఫాల్ట్ సెట్టింగ్‌లను మార్చకపోతే, <ph name="NEW_PROFILE_NAME" /> వెబ్‌లో అన్నీ బ్రౌజ్ చేయగలరు.
+<translation id="7344413941077984497"><ph name="NEW_PROFILE_NAME" /> వీక్షించగల వెబ్‌సైట్‌లను సెట్ చేయడానికి, మీరు <ph name="BEGIN_LINK_1" /><ph name="DISPLAY_LINK" /><ph name="END_LINK_1" />ను సందర్శించడం ద్వారా పరిమితులు మరియు సెట్టింగ్‌లను కాన్ఫిగర్ చేయవచ్చు. మీరు డిఫాల్ట్ సెట్టింగ్‌లను మార్చకపోతే, <ph name="NEW_PROFILE_NAME" /> వెబ్‌లో అన్నీ బ్రౌజ్ చేయగలరు.
-<ph name="NEW_PROFILE_NAME" /> ని మీ ఖాతా యాక్సెస్‌ చేయనీయకుండా నిరోధించడానికి, మీరు Chromiumను ఉపయోగించనప్పుడు మీ ప్రొఫైల్‌ను లాక్ చేసి ఉంచేట్లు చూసుకోండి. దీన్ని చేయడానికి, బ్రౌజర్ ఎగువ కుడి మూలన ఉన్న మీ ప్రొఫైల్ పేరును క్లిక్ చేసి, ఆపై "నిష్క్రమించి, చైల్డ్ లాక్ చేయి" ఎంపికను ఎంచుకోండి.
+<ph name="NEW_PROFILE_NAME" />ను మీ ఖాతా యాక్సెస్‌ చేయనీయకుండా నిరోధించడానికి, మీరు Chromiumను ఉపయోగించనప్పుడు మీ ప్రొఫైల్‌ను లాక్ చేసి ఉంచేట్లు చూసుకోండి. ఇలా చేయ‌డానికి, బ్రౌజర్ ఎగువ కుడి మూలన ఉన్న మీ ప్రొఫైల్ పేరును క్లిక్ చేసి, ఆపై "నిష్క్రమించి, చైల్డ్ లాక్ చేయి" ఎంపికను ఎంచుకోండి.
<ph name="BEGIN_LINK_2" />మరింత తెలుసుకోండి<ph name="END_LINK_2" />
-దయచేసి తదుపరి సూచనల కోసం <ph name="ACCOUNT_EMAIL" />లో మీ ఇమెయిల్‌ను చూడండి.</translation>
+దయచేసి తదుపరి సూచనల కోసం <ph name="ACCOUNT_EMAIL" /> లో మీ ఇమెయిల్‌ను చూడండి.</translation>
<translation id="7448255348454382571">Chromium OSని మళ్లీ ప్రారంభించండి</translation>
<translation id="7449453770951226939"><ph name="PAGE_TITLE" /> - Chromium Dev</translation>
<translation id="7451052299415159299">ఈ సైట్ కోసం మీ కెమెరాని యాక్సెస్ చేయడానికి Chromiumకు అనుమతి అవసరం</translation>
<translation id="7471302858145901434">{0,plural, =1{ఒక రోజులో Chromium OSని మళ్లీ ప్రారంభించండి}other{# రోజుల్లో Chromium OSని మళ్లీ ప్రారంభించండి}}</translation>
-<translation id="7483335560992089831">ప్రస్తుతం అమలు చేయబడుతున్న అదే Chromium వెర్ష‌న్‌ను ఇన్‌స్టాల్ చేయలేరు. దయచేసి Chromiumను మూసివేసి, మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="7483335560992089831">ప్రస్తుతం అమలు అవుతోన్న అదే Chromium వెర్షన్‌ను ఇన్‌స్టాల్ చేయలేరు. దయచేసి Chromiumను మూసివేసి, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="7549178288319965365">Chromium OS గురించి</translation>
<translation id="7561906087460245826">అలాగే (<ph name="URL" />)లో ఉన్న Chromiumకి సంబంధించిన డేటాని తీసివేయి</translation>
<translation id="761356813943268536">Chromium మీ కెమెరా మరియు మైక్రోఫోన్‌ని ఉపయోగిస్తోంది.</translation>
<translation id="7617377681829253106">Chromium ఇప్పుడు మెరుగైంది</translation>
<translation id="7686590090926151193">Chromium మీ డిఫాల్ట్ బ్రౌజర్ కాదు</translation>
<translation id="7689606757190482937">మీ పరికరాల అంతటా Chromiumను సింక్ చేయండి మరియు వ్యక్తిగతీకరించండి</translation>
-<translation id="7729447699958282447">Chromium మీ డేటాను సమకాలీకరించలేకపోయింది ఎందుకంటే మీ డొమైన్‌కు సమకాలీకరణ అందుబాటులో లేదు.</translation>
-<translation id="7745317241717453663">ఇది ఈ పరికరం నుండి మీ బ్రౌజింగ్ డేటాను తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromiumకి <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
-<translation id="7747138024166251722">ఇన్‌స్టాలర్ ఒక తాత్కాలిక డైరక్టరీని సృష్టించలేకపోయింది. సాఫ్ట్‌వేర్‌ను ఇన్‌స్టాల్ చేయడానికి దయచేసి డిస్క్‌కు సంబంధించి నిల్వ, అనుమతిని తనిఖీ చేయండి.</translation>
-<translation id="7773960292263897147">హెచ్చరిక:Chromium మీ బ్రౌజింగ్ చరిత్రను రికార్డ్ చేయడం నుండి పొడిగింపును నిరోధించలేదు. ఈ పొడిగింపును అజ్ఞాత మోడ్‌లో ఆపివేయడానికి, ఈ ఎంపికను రద్దు చేయండి.</translation>
+<translation id="7729447699958282447">Chromium మీ డేటాను సింక్ చేయ‌లేక‌పోయింది. ఎందుకంటే మీ డొమైన్‌కు సింక్‌ అందుబాటులో లేదు.</translation>
+<translation id="7745317241717453663">ఇది ఈ పరికరం నుండి మీ బ్రౌజింగ్ డేటాను తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromiumకు <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
+<translation id="7747138024166251722">ఇన్‌స్టాలర్ ఒక తాత్కాలిక డైరక్టరీని సృష్టించలేకపోయింది. సాఫ్ట్‌వేర్‌ను ఇన్‌స్టాల్ చేయడానికి దయచేసి ఖాళీ డిస్క్ స్థలం, అనుమతిని తనిఖీ చేయండి.</translation>
+<translation id="7773960292263897147">హెచ్చరిక: Chromium, మీ బ్రౌజింగ్ చరిత్రను రికార్డ్ చేయడం నుండి ఎక్స్‌టెన్ష‌న్‌ను నిరోధించలేదు. ఈ ఎక్స్‌టెన్ష‌న్‌ను అజ్ఞాత మోడ్‌లో నిలిపివేయడానికి, ఈ ఎంపికను రద్దు చేయండి.</translation>
<translation id="7790626492778995050"><ph name="PAGE_TITLE" /> - Chromium Canary</translation>
-<translation id="7867198900892795913">Chromiumని తాజా వెర్షన్‌కు అప్‌డేట్ చేయడం సాధ్యం కాలేదు, కనుక మీరు కొత్త ఫీచర్‌లు మరియు భద్రతా పరిష్కారాలను పొందలేరు.</translation>
+<translation id="7867198900892795913">Chromiumను తాజా వెర్షన్‌కు అప్‌డేట్ చేయడం సాధ్యం కాలేదు, కాబట్టి మీరు కొత్త ఫీచర్‌లు మరియు భద్రతా పరిష్కారాలను పొందడం లేదు.</translation>
<translation id="7901117350626490574">Chromiumకు కొత్త అప్‌డేట్ అందుబాటులో ఉంది మరియు మీరు పునఃప్రారంభించిన వెంటనే వర్తింపజేయబడుతుంది.</translation>
-<translation id="7937630085815544518">మీరు <ph name="USER_EMAIL_ADDRESS" />గా Chromiumకు సైన్ ఇన్ చేశారు. దయచేసి మళ్లీ సైన్ ఇన్ చేయడానికి ఇదే ఖాతాను ఉపయోగించండి.</translation>
-<translation id="7962572577636132072">Chromium స్వయంచాలకంగా నవీకరించబడుతుంది కనుక మీరు ఎల్లప్పుడూ తాజా సంస్కరణను కలిగి ఉంటారు.</translation>
-<translation id="7975919845073681630">ఇది Chromium యొక్క రెండవ ఇన‌స్ట‌లేష‌న్‌. దీన్ని మీ డిఫాల్ట్ బ్రౌజర్‌గా చేయడం సాధ్యపడదు.</translation>
+<translation id="7937630085815544518">మీరు <ph name="USER_EMAIL_ADDRESS" />గా Chromiumకు సైన్ ఇన్ చేసారు. మళ్లీ సైన్ ఇన్ చేయడానికి, దయచేసి ఇదే ఖాతాను ఉపయోగించండి.</translation>
+<translation id="7962572577636132072">Chromium ఆటోమేటిక్‌గా అప్‌డేట్ అవుతుంది కాబట్టి మీ వద్ద ఎప్పుడూ తాజా వెర్షన్ ఉంటుంది.</translation>
+<translation id="7975919845073681630">ఇది Chromium రెండవ ఇన‌స్ట‌లేష‌న్. దీన్ని మీ డిఫాల్ట్ బ్రౌజర్‌గా చేయడం సాధ్యపడదు.</translation>
<translation id="7979877361127045932">Chromium మెనూలో దాచండి</translation>
<translation id="8013436988911883588">ఓసారి Chromiumకి యాక్సెస్ లభించాక, ఆపై వెబ్‌సైట్‌లకు ఏమైనా యాక్సెస్‌ కావాలంటే అవి మిమ్మల్ని అడగవచ్చు.</translation>
-<translation id="8030318113982266900">మీ పరికరాన్ని <ph name="CHANNEL_NAME" /> ఛానెల్‌కి నవీకరిస్తోంది...</translation>
+<translation id="8030318113982266900">మీ పరికరాన్ని <ph name="CHANNEL_NAME" /> ఛానెల్‌కు అప్‌డేట్ చేస్తోంది...</translation>
<translation id="8157153840442649507">Chromium ఈ భాషలో ప్రదర్శించబడుతోంది</translation>
<translation id="81770708095080097">ఈ ఫైల్ అపాయకరమైనది, కాబట్టి Chromium దీన్ని బ్లాక్ చేసింది.</translation>
<translation id="8222496066431494154">మీ ఫోన్‌లో Chromiumను ఇన్‌స్టాల్ చేయండి. మేము మీ ఖాతా పునరుద్ధరణ ఫోన్ నంబర్‌కు SMS పంపుతాము: <ph name="PHONE_NUMBER" /></translation>
-<translation id="8269379391216269538">Chromiumని మెరుగుపరచడంలో సహాయం అందించండి</translation>
+<translation id="8269379391216269538">Chromiumను మెరుగుపరచడంలో సహాయం అందించండి</translation>
<translation id="8290862415967981663">ఈ ఫైల్ అపాయకరం కావచ్చు, కాబట్టి Chromium దీన్ని బ్లాక్ చేసింది.</translation>
-<translation id="8330519371938183845">మీ పరికరాల అంతటా Chromiumను సింక్ చేయడం మరియు వ్యక్తిగతీకరించడం కోసం సైన్ ఇన్ చేయండి</translation>
+<translation id="8330519371938183845">మీ పరికరాల అంతటా Chromiumను సింక్ చేయడానికి, వ్యక్తిగతీకరించడానికి సైన్ ఇన్ చేయండి</translation>
<translation id="8340674089072921962"><ph name="USER_EMAIL_ADDRESS" /> మునుపు Chromiumని ఉపయోగించింది</translation>
<translation id="8375950122744241554">Chromium 70తో మొదలు పెట్టి, తర్వాతి వెర్షన్‌లలో పర్యవేక్షించబడే వినియోగదారు ప్రొఫైల్‌లు ఇకపై అందుబాటులో ఉండవు.</translation>
<translation id="8379713241968949941">{0,plural, =1{ఒక గంటలో Chromium తిరిగి ప్రారంభించబడుతుంది}other{# గంటల్లో Chromium తిరిగి ప్రారంభించబడుతుంది}}</translation>
<translation id="8453117565092476964">ఇన్‌స్టాలర్ ఆర్కైవ్ పాడైంది లేదా చెల్లదు. దయచేసి Chromiumను మళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
<translation id="8493179195440786826">Chromium కాలం చెల్లినది</translation>
-<translation id="85843667276690461">Chromiumని ఉపయోగించి సహాయాన్ని పొందండి</translation>
+<translation id="85843667276690461">Chromiumను ఉపయోగించడం గురించి సహాయాన్ని పొందండి</translation>
<translation id="8586442755830160949">కాపీరైట్ <ph name="YEAR" /> Chromium రచయితలు. అన్ని హ‌క్కులు రిజ‌ర్వ్ చేయ‌బ‌డ్డాయి.</translation>
<translation id="8599548569518771270">{0,plural, =0{Chromium OS ఇప్పుడు మళ్లీ ప్రారంభించబడుతుంది}=1{Chromium OS 1 సెకనులో మళ్లీ ప్రారంభమవుతుంది}other{Chromium OS # సెకన్లలో మళ్లీ ప్రారంభమవుతుంది}}</translation>
<translation id="8619360774459241877">Chromiumని ప్రారంభిస్తోంది...</translation>
-<translation id="8621669128220841554">పేర్కొనబడని ఎర్రర్ కారణంగా ఇన్‌స్టాలేషన్ విఫలమైంది. దయచేసి Chromiumను మళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
+<translation id="8621669128220841554">తెలియ‌ని ఎర్ర‌ర్‌ కారణంగా ఇన‌స్ట‌లేష‌న్‌ విఫలమైంది. దయచేసి Chromiumను మళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
<translation id="8667808506758191620">మీ <ph name="DEVICE_TYPE" /> ఆధునికంగా ఉంది.</translation>
<translation id="8697124171261953979">ఇది మీరు Chromiumను ప్రారంభించేటప్పుడు లేదా ఓమ్నిబాక్స్ నుండి వెతికేటప్పుడు చూపబడే పేజీని కూడా నియంత్రిస్తుంది.</translation>
<translation id="8704119203788522458">ఇది మీ Chromium</translation>
<translation id="8796602469536043152">ఈ సైట్ కోసం మీ కెమెరా మరియు మైక్రోఫోన్‌ను యాక్సెస్ చేయడానికి Chromiumకు అనుమతి అవసరం</translation>
<translation id="8803635938069941624">Chromium OS నిబంధనలు</translation>
-<translation id="8821041990367117597">Chromium మీ డేటాను సింక్ చేయ‌లేకపోయింది ఎందుకంటే మీ ఖాతా సైన్-ఇన్ వివరాల గడువు ముగిసింది.</translation>
-<translation id="8862326446509486874">సిస్టమ్-స్థాయిలో ఇన్‌స్టాల్‌ చెయ్యడానికి మీకు సరైన హక్కులు లేవు. నిర్వాహకుడి లాగా ఇన్‌స్టాలర్‌ను మళ్లీ రన్ చెయ్యడానికి ప్రయత్నించండి.</translation>
+<translation id="8821041990367117597">మీ ఖాతా సైన్-ఇన్ వివరాల గడువు ముగిసింది కాబట్టి Chromium మీ డేటాను సింక్ చేయలేకపోయింది.</translation>
+<translation id="8862326446509486874">సిస్టమ్-స్థాయిలో ఇన్‌స్టాల్‌ చేయ‌డానికి మీకు సరైన హక్కులు లేవు. నిర్వాహకుడి లాగా ఇన్‌స్టాలర్‌ను మ‌ళ్లీ రన్ చేయ‌డానికి ప్రయత్నించండి.</translation>
<translation id="8897323336392112261">ఇది మీరు Chromiumను ప్రారంభించేటప్పుడు లేదా హోమ్ బటన్‌ను క్లిక్ చేసేటప్పుడు చూపబడే పేజీని కూడా నియంత్రిస్తుంది.</translation>
<translation id="8907580949721785412">Chromium పాస్‌వర్డ్‌లను చూపడానికి ప్రయత్నిస్తోంది. దీన్ని అనుమతించడానికి మీ Windows పాస్‌వర్డ్‌ను టైప్ చేయండి.</translation>
<translation id="8941642502866065432">Chromiumని అప్‌డేట్ చేయడం సాధ్యం కాదు</translation>
@@ -259,12 +260,12 @@
ఏది ఏమైనా సైన్ ఇన్ చేస్తే బుక్‌మార్క్‌లు, చరిత్ర, ఇతర సెట్టింగ్‌ల వంటి Chromium సమాచారం <ph name="ACCOUNT_EMAIL_NEW" />కు విలీనం చేయబడుతుంది.</translation>
<translation id="9019929317751753759">Chromiumని సురక్షితం చేయడానికి, మేము క్రింది పొడిగింపుని నిలిపివేసాము, ఇది <ph name="IDS_EXTENSION_WEB_STORE_TITLE" />లో జాబితా చేయబడలేదు మరియు మీకు తెలియకుండా జోడించబడి ఉండవచ్చు.</translation>
-<translation id="9022552996538154597">Chromiumకి సైన్ ఇన్ చేయండి</translation>
+<translation id="9022552996538154597">Chromiumకు సైన్ ఇన్ చేయండి</translation>
<translation id="9025992965467895364">ఈ పేజీ చాలా మెమరీని ఉపయోగిస్తోంది, కాబట్టి దీన్ని Chromium పాజ్ చేయబడింది.</translation>
<translation id="9036189287518468038">Chromium యాప్ లాంఛ‌ర్</translation>
<translation id="9089354809943900324">Chromium కాలం చెల్లినది</translation>
<translation id="91086099826398415">కొత్త Chromium &amp;ట్యాబ్‌లో లింక్‌ని తెరువు</translation>
-<translation id="911206726377975832">మీ బ్రౌజింగ్ డేటాని కూడా తొలగించాలా?</translation>
+<translation id="911206726377975832">మీ బ్రౌజింగ్ డేటాను కూడా తొలగించాలా?</translation>
<translation id="918373042641772655"><ph name="USERNAME" />ని డిస్‌కనెక్ట్ చేయడం వలన ఈ పరికరంలో నిల్వ చేయబడిన మీ చరిత్ర, బుక్‌మార్క్‌లు, సెట్టింగ్‌లు, ఇతర Chromium డేటా క్లియర్ చేయబడతాయి. మీ Google ఖాతాలో నిల్వ చేయబడిన డేటా క్లియర్ చేయబడదు. దాన్ని <ph name="GOOGLE_DASHBOARD_LINK" />Google డాష్‌బోర్డ్<ph name="END_GOOGLE_DASHBOARD_LINK" />లో నిర్వహించవచ్చు.</translation>
<translation id="9190841055450128916">Chromium (mDNS-In)</translation>
<translation id="9197815481970649201">మీరు ఇప్పుడు Chromiumకు సైన్ ఇన్ చేసారు</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_th.xtb b/chromium/chrome/app/resources/chromium_strings_th.xtb
index a4c3654b473..5d6038040c9 100644
--- a/chromium/chrome/app/resources/chromium_strings_th.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_th.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium ช่วยให้คุณสามารถคลิกหมายเลขโทรศัพท์บนเว็บและโทรออกด้วย Skype ได้!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">ตรึง Chromium กับแถบงาน</translation>
+<translation id="388648406173476553">ปรับแต่งและควบคุม Chromium มีสิ่งที่คุณจำเป็นต้องทราบ โปรดคลิกเพื่อดูรายละเอียด</translation>
<translation id="3889543394854987837">คลิกชื่อของคุณเพื่อเปิด Chromium และเริ่มท่องเว็บ</translation>
<translation id="3898493977366060150">การท่องเว็บพร้อมฟีเจอร์เจ๋งๆ จาก Google</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS จะรีสตาร์ทใน 1 ชั่วโมง}other{Chromium OS จะรีสตาร์ทใน # ชั่วโมง}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_tr.xtb b/chromium/chrome/app/resources/chromium_strings_tr.xtb
index 4811b4fb11e..2a1b653e1a8 100644
--- a/chromium/chrome/app/resources/chromium_strings_tr.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_tr.xtb
@@ -84,6 +84,7 @@
<translation id="378917192836375108">Chromium Web'de bir telefon numarasını tıklayarak Skype ile aramanıza olanak sağlar!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Chromium'u görev çubuğunuza sabitleme</translation>
+<translation id="388648406173476553">Chromium'u özelleştirin ve kontrol edin. İlgilenmeniz gereken bir konu var. Ayrıntılar için tıklayın.</translation>
<translation id="3889543394854987837">Chromium'u açmak ve göz atmaya başlamak için adınızı tıklayın.</translation>
<translation id="3898493977366060150">Google Smarts ile web'e göz atma</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS bir saat içinde yeniden başlatılacak}other{Chromium OS # saat içinde yeniden başlatılacak}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_uk.xtb b/chromium/chrome/app/resources/chromium_strings_uk.xtb
index f26b5a8a0b4..bd98d5beba6 100644
--- a/chromium/chrome/app/resources/chromium_strings_uk.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_uk.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium дозволяє натиснути номер телефону в Інтернеті та зателефонувати за ним через Skype.</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> – Chromium</translation>
<translation id="3852700440713538496">Як закріпити значок Chromium на панелі завдань</translation>
+<translation id="388648406173476553">Налаштуйте й керуйте Chromium. Якщо з’явиться сповіщення, натисніть його, щоб дізнатися більше.</translation>
<translation id="3889543394854987837">Натисніть своє ім’я, щоб відкрити Chromium і розпочати перегляд сайтів.</translation>
<translation id="3898493977366060150">Перегляд веб-сторінок із розумними функціями Google</translation>
<translation id="3965668104013180445">{0,plural, =1{ОС Chromium перезапуститься через годину}one{ОС Chromium перезапуститься через # годину}few{ОС Chromium перезапуститься через # години}many{ОС Chromium перезапуститься через # годин}other{ОС Chromium перезапуститься через # години}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_vi.xtb b/chromium/chrome/app/resources/chromium_strings_vi.xtb
index bec468d43a2..a9b6bd7e31a 100644
--- a/chromium/chrome/app/resources/chromium_strings_vi.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_vi.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">Chromium cho phép bạn nhấp vào số điện thoại trên web và gọi tới số đó bằng Skype!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">Ghim Chromium vào thanh tác vụ của bạn</translation>
+<translation id="388648406173476553">Tùy chỉnh và kiểm soát Chromium. Bạn cần lưu ý - nhấp để xem thông tin chi tiết.</translation>
<translation id="3889543394854987837">Nhấp vào tên của bạn để mở Chromium và bắt đầu duyệt web.</translation>
<translation id="3898493977366060150">Duyệt web bằng Google smarts</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium OS sẽ khởi động lại sau một giờ}other{Chromium OS sẽ khởi động lại sau # giờ}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_zh-CN.xtb b/chromium/chrome/app/resources/chromium_strings_zh-CN.xtb
index a6ef79a1318..d084f06bb09 100644
--- a/chromium/chrome/app/resources/chromium_strings_zh-CN.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_zh-CN.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">您可以在 Chromium 中点击网上的电话号码,然后通过 Skype 拨打!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">将 Chromium 固定到任务栏</translation>
+<translation id="388648406173476553">自定义和控制 Chromium。出了点需要您注意的状况 - 点击即可查看详情。</translation>
<translation id="3889543394854987837">点击您的姓名即可打开Chromium并开始浏览。</translation>
<translation id="3898493977366060150">利用 Google 的智能技术浏览网页</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium 操作系统将会在 1 小时后重启}other{Chromium 操作系统将会在 # 小时后重启}}</translation>
diff --git a/chromium/chrome/app/resources/chromium_strings_zh-TW.xtb b/chromium/chrome/app/resources/chromium_strings_zh-TW.xtb
index a8fe49e96d1..14064530d79 100644
--- a/chromium/chrome/app/resources/chromium_strings_zh-TW.xtb
+++ b/chromium/chrome/app/resources/chromium_strings_zh-TW.xtb
@@ -86,6 +86,7 @@
<translation id="378917192836375108">透過 Chromium,你只要按一下網路上的電話號碼,即可用 Skype 打電話!</translation>
<translation id="3848258323044014972"><ph name="PAGE_TITLE" /> - Chromium</translation>
<translation id="3852700440713538496">將 Chromium 固定至工作列</translation>
+<translation id="388648406173476553">自訂及管理 Chromium。重要注意事項 - 按這裡瞭解詳情。</translation>
<translation id="3889543394854987837">按一下你的名稱即可開啟 Chromium 並開始瀏覽。</translation>
<translation id="3898493977366060150">採用 Google 技術的網路瀏覽體驗</translation>
<translation id="3965668104013180445">{0,plural, =1{Chromium 作業系統將於 1 小時後重新啟動}other{Chromium 作業系統將於 # 小時後重新啟動}}</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_am.xtb b/chromium/chrome/app/resources/generated_resources_am.xtb
index edff1f27ed6..f776a1e4339 100644
--- a/chromium/chrome/app/resources/generated_resources_am.xtb
+++ b/chromium/chrome/app/resources/generated_resources_am.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">ገጽታን አንቃ</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">በChrome የድር መደብር ውስጥ ይመልከቱ</translation>
-<translation id="1761588866118490543">የድምፅ ሞዴል</translation>
<translation id="176193854664720708">የጣት አሻራ ዳሳሹ በኃይል አዝራሩ ውስጥ ነው። በማንኛውም ጣት ቀስ ብለው ይንኩት።</translation>
<translation id="1763046204212875858">የመተግበሪያ አቋራጮችን ፍጠር</translation>
<translation id="1763108912552529023">ማሰሱን ቀጥል</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">የአጠቃቀም እና የምርመራ ውሂብ ይላኩ። ይህ መሣሪያ በአሁኑ ጊዜ በራስ-ሰር የምርመራ፣ የመሣሪያ እና የመተግበሪያ አጠቃቀም ውሂብ ወደ Google እየላከ ነው። ይህ የስርዓት እና የመተግበሪያ እርጋታን እና ሌሎች ማሻሻያዎችን ያግዛል። አንዳንድ ውሑድ ውሂብ እንዲሁም የGoogle መተግበሪያዎችን እና እንደ የAndroid ገንቢዎች ያሉ አጋሮችን ያግዛሉ። ይህ ቅንብር በባለቤቱ ተፈጻሚ ይደረጋል። የእርስዎ የተጨማሪ ድር እና መተግበሪያ እንቅስቃሴ ቅንብር በርቶ ከሆነ ይህ ውሂብ በGoogle መለያዎ ላይ ሊቀመጥ ይችላል። <ph name="BEGIN_LINK1" />የበለጠ ለመረዳት<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">የZip ማህደር</translation>
<translation id="220858061631308971">እባክዎ ይህን የፒን ኮድ በ«<ph name="DEVICE_NAME" />» ላይ ያስገቡት፦</translation>
+<translation id="2213140827792212876">ማጋራትን አስወግድ</translation>
+<translation id="2214018885812055163">የተጋሩ አቃፊዎች</translation>
<translation id="2214884991347062907">የተሳሳተ የይለፍ ቃል። እንደገና ይሞክሩ</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 መስመር አይታይም&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> መስመሮች አይታዩም&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> መስመሮች አይታዩም&gt;}}</translation>
<translation id="2217501013957346740">አንድ ስም ይፍጠሩ -</translation>
@@ -1014,6 +1015,7 @@
<translation id="2501173422421700905">የተያዘ ሰርቲፊኬት</translation>
<translation id="2501797496290880632">አቋራጭ ይተይቡ</translation>
<translation id="2502441965851148920">ራስ-ሰር ዝማኔዎች ነቅተዋል። ራስዎ የሚያደርጓቸው ዝማኔዎች በአስተዳዳሪዎ ተሰናክለዋል።</translation>
+<translation id="2505127913256479918">ይህ ክትትል የሚደረግበት መለያ በቅርቡ ይወገዳል</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{ማያ ገጽ #}one{ማያ ገጽ #}other{ማያ ገጽ #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> ከ <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">የGoogle Play መደብር መለያ</translation>
@@ -1374,6 +1376,7 @@
<translation id="304747341537320566">የንግግር ፕሮግራሞች</translation>
<translation id="3053013834507634016">የሰርቲፊኬት ቁልፍ ጠቀሜታ</translation>
<translation id="3057861065630527966">የእርስዎን ፎቶዎች እና ቪዲዮዎች በምትኬ ያስቀምጡ</translation>
+<translation id="3058498974290601450">ስምረትን በማንኛውም ጊዜ በቅንብሮች ውስጥ ማብራት ይችላሉ።</translation>
<translation id="3060379269883947824">ለመናገር-ይምረጡን ያንቁ</translation>
<translation id="3061707000357573562">የመጠገኛ አገልግሎት</translation>
<translation id="3065041951436100775">የትር ተገድሏል ግብረመልስ።</translation>
@@ -1565,6 +1568,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> ይጫናል።</translation>
<translation id="3380365263193509176">ያልታወቀ ስህተት</translation>
<translation id="3382073616108123819">ውይ! ስርዓቱ ለዚህ መሳሪያ የመሳሪያ መለያዎችን መወሰን አልቻለም።</translation>
+<translation id="3382086682569279540">እርስዎ የሚያስተዳድሩት መለያ በቅርቡ ይወገዳል</translation>
<translation id="3382200254148930874">ክትትልን በማቆም ላይ...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">መለያ</translation>
@@ -1745,8 +1749,8 @@
<translation id="3636096452488277381">እሺ፣ እንዴት ነው <ph name="USER_GIVEN_NAME" />?</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> ቀርቷል</translation>
<translation id="3637682276779847508">ትክክለኛውን የመክፈቻ ፒን ቁልፍ ማስገባት ካልቻሉ የእርስዎ ሲም ካርድ በቋሚነት ይሰናከላል።</translation>
-<translation id="363863692969456324">በላቀ የፊደል ማረም አማካኝነት የፊደል ግድፈቶችን ያስተካክሉ</translation>
<translation id="3640214691812501263">«<ph name="EXTENSION_NAME" />» ለ<ph name="USER_NAME" /> ይታከል?</translation>
+<translation id="3640613767643722554">የእርስዎ ረዳት ድምጽዎን ለይቶ እንዲያውቅ ያስተምሩት</translation>
<translation id="3644896802912593514">ስፋት</translation>
<translation id="3645372836428131288">የጣት አሻራውን የተለየ ክፍል ለመያዝ በቀስታ ያንቀሳቅሱት።</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> ተገኝቷል</translation>
@@ -2144,7 +2148,6 @@
<translation id="4244238649050961491">ተጨማሪ የስቲለስ መተግበሪያዎችን ያግኙ</translation>
<translation id="424546999567421758">ከፍተኛ የዲስክ መጠቀም ተገኝቷል</translation>
<translation id="424726838611654458">ሁልጊዜ በAdobe Reader ክፈት</translation>
-<translation id="4247330672018280062">በጽሑፍ መስኮቹ ላይ የሚታይቡት ጽሑፍ ወደ Google ይላካል</translation>
<translation id="4247901771970415646">ከ<ph name="USERNAME" /> ጋር ማሳመር አይቻልም</translation>
<translation id="4249248555939881673">የአውታረ መረብ ግንኙነትን በመጠበቅ ላይ...</translation>
<translation id="4249373718504745892">ይህ ገጽ ካሜራዎን እና ማይክሮፎንዎን እንዳይደርስባቸው ታግዷል።</translation>
@@ -2486,6 +2489,7 @@
<translation id="4821935166599369261">&amp;መገለጫ መስራት ነቅቷል</translation>
<translation id="4823484602432206655">የተጠቃሚ እና የመሣሪያ ቅንብሮችን ያንብቡ እና ይለውጡ</translation>
<translation id="4823651846660089135">መሣሪያው ተነባቢ-ብቻ ነው</translation>
+<translation id="4824958205181053313">ስምረት ይሰረዝ?</translation>
<translation id="4827675678516992122">መገናኘት አልተቻለም</translation>
<translation id="4828937774870308359">የአውስትራሊያ</translation>
<translation id="4829768588131278040">ፒን ያዋቅሩ</translation>
@@ -2868,6 +2872,7 @@
<translation id="5374359983950678924">ስዕል ይቀይሩ</translation>
<translation id="5376169624176189338">ወደ ኋላ ለመመለስ ጠቅ ያድርጉ፣ ታሪክ ለማየት ይያዙ</translation>
<translation id="5376931455988532197">ፋይሉ በጣም ትልቅ ነው</translation>
+<translation id="5377594097385838788">ማንነትን የማያሳውቅ</translation>
<translation id="537813040452600081">በዚህ መስኮት ላይ የሚመለከቷቸውን ገጾች በአሳሽ ታሪክ ላይ የማይታዩ ሲሆን ዘግተው ከወጡ በኋላ ገጾቹ እንደ ኩኪዎች ያሉ ሌሎች መከታተያዎችን አይተዉም። የሚያወርዷቸው ፋይሎች እና ዕልባቶች አይቀመጡም።</translation>
<translation id="5379140238605961210">የማይክሮፎን መዳረሻ ማገዱን ቀጥል</translation>
<translation id="5379268888377976432">ስረዛውን ቀልብስ</translation>
@@ -2889,6 +2894,7 @@
<translation id="5414566801737831689">የሚጎበኟቸውን የድር ጣቢያዎች አዶዎች ያነብባል</translation>
<translation id="5417312524372586921">የአሳሽ ገጽታዎች</translation>
<translation id="5419294236999569767">የስርዓት ጊዜ</translation>
+<translation id="5419405654816502573">Voice match</translation>
<translation id="5420438158931847627">የጽሑፍ እና ምስሎትች ጠርዝ ጥራትነትን ይወስናል</translation>
<translation id="5422221874247253874">የመዳረሻ ነጥብ</translation>
<translation id="5422781158178868512">ይቅርታ፣ የውጫዊ ማከማቻ መሣሪያዎ ሊታወቅ አልቻለም።</translation>
@@ -2909,6 +2915,7 @@
<translation id="5434065355175441495">PKCS #1 RSA ምስጠራ</translation>
<translation id="5436492226391861498">ተኪ መሹለኪያን በመጠበቅ ላይ...</translation>
<translation id="5436510242972373446">ፍለጋ ከ<ph name="SITE_NAME" />፦</translation>
+<translation id="543806387003274181">እባክዎ ፋይሎችዎን ያስቀምጡና አዲስ መለያ ይፍጠሩ።</translation>
<translation id="5438224778284622050">የመስመር ውጭ ፋይሎች ይሰረዙ?</translation>
<translation id="544083962418256601">አቋራጮችን ይፍጠሩ...</translation>
<translation id="5442228125690314719">የዲስክ ምስልን በመፍጠር ላይ ስህተት። እባክዎ እንደገና ይሞክሩ።</translation>
@@ -3281,6 +3288,8 @@
<translation id="5965661248935608907">እንዲሁም የመነሻ አዝራሩን ጠቅ ሲያደርጉ ወይም ከኦምኒቦክሱ ሆነው ሲፈልጉ ምን ገጽ እንደሚታይ ይቆጣጠራል።</translation>
<translation id="5971037678316050792">የብሉቱዝ አስማሚ ሁኔታ እና ማጣመርን ይቆጣጠራል</translation>
<translation id="5972017421290582825">MIDI ቅንብሮችን አስተዳድር...</translation>
+<translation id="597235323114979258">ተጨማሪ መድረሻዎችን ይመልከቱ</translation>
+<translation id="5972666587303800813">ክወና-አልባ አገልግሎት</translation>
<translation id="5972708806901999743">ወደ ላይ ሂድ</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" />ን ጀምር</translation>
<translation id="5975792506968920132">የባትሪ መሞላት መቶኛ ደረጃ</translation>
@@ -3651,6 +3660,7 @@
<translation id="6527303717912515753">አጋራ</translation>
<translation id="6528513914570774834">ሌሎች የዚህ መሣሪያ ተጠቃሚዎች ይህን አውታረ መረብ እንዲጠቀሙ ይፍቀዱላቸው</translation>
<translation id="652948702951888897">የChrome ታሪክ</translation>
+<translation id="6530186581263215931">እነዚህ ቅንብሮች በአስተዳዳሪዎ ነው የሚፈጸሙት</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" />ን በማመሳሰል ላይ...</translation>
<translation id="6531282281159901044">አደገኛ ፋይልን አስቀምጥ</translation>
<translation id="6532101170117367231">ወደ Google Drive ያስቀምጡ</translation>
@@ -3969,7 +3979,6 @@
<translation id="7018275672629230621">የአሰሳ ታሪክዎን ያነብባል እና ይቀይራል</translation>
<translation id="7019805045859631636">ፈጣን</translation>
<translation id="7022562585984256452">የእርስዎ መነሻ ገጽ ተዋቅሯል።</translation>
-<translation id="702384510542929236">አንዳንድ የስርዓት መረጃን እና የገጽ ይዘትን ስም-አልባ በሆነ መልኩ ወደ Google ይልካል</translation>
<translation id="7025190659207909717">የተንቀሳቃሽ ስልክ ውሂብ አገልግሎት ማቀናበር</translation>
<translation id="7027125358315426638">የውሂብ ጎታ ስም፦</translation>
<translation id="7029809446516969842">የይለፍ ቃላት</translation>
@@ -4149,6 +4158,7 @@
<translation id="7289225569524511578">የልጣፍ መተግበሪያውን ክፈት</translation>
<translation id="7290242001003353852">ይህ በ<ph name="SAML_DOMAIN" /> የሚስተናገድ የመለያ መግቢያ አገልግሎት የእርስዎን ካሜራ እየደረሰበት ነው።</translation>
<translation id="7290594223351252791">ምዝገባ ያረጋግጡ</translation>
+<translation id="7292696521213967957">ረዳትን ለማረም መረጃ</translation>
<translation id="7295662345261934369">ከሌሎች ጋር ተጋራ</translation>
<translation id="729583233778673644">የAES እና የRC4 ምሥጠራን ይፍቀዱ። የRC4 ምሥጠራዎች ለደህንነት አስተማማኝ ስላልሆኑ ይህን አማራጭ መጠቀም የእርስዎን አደጋ ይጨምራል።</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> ውል</translation>
@@ -4249,7 +4259,6 @@
<translation id="7456847797759667638">የተቀመጠበትን ቦታ ክፈት…</translation>
<translation id="7461924472993315131">ሰካ</translation>
<translation id="7463006580194749499">ሰው አክል</translation>
-<translation id="7464902436585505072">የ«Ok Google» ድምፅ ሞዴል</translation>
<translation id="7465778193084373987">የNetscape ሰርቲፊኬት የመሻሪያ URL</translation>
<translation id="7469894403370665791">ከዚህ አውታረ መረብ ጋር በራስ-ሰር ይገናኙ</translation>
<translation id="747114903913869239">ስህተት፦ ቅጥያዎችን ዲኮድ ማድረግ አልተቻለም</translation>
@@ -4277,6 +4286,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> እና ከእሱ ጋር የተጎዳኘው ውሂብ ከዚህ መሣሪያ ይወገዳል።</translation>
<translation id="7497215489070763236">የአገልጋይ CA እውቅና ማረጋገጫ</translation>
<translation id="7497981768003291373">ምንም በቅርብ ጊዜ የተቀረጹ WebRTC የጽሑፍ ምዝግብ ማስታወሻዎች የለዎትም።</translation>
+<translation id="7502199377020483660">እነዚህን ካርዶች በሁሉም መሣሪያዎችዎ ላይ ለመጠቀም በGoogle መለያዎ ላይ ያስቀምጧቸው</translation>
<translation id="7502658306369382406">የIPv6 አድራሻ</translation>
<translation id="7503191893372251637">የNetscape ሰርቲፊኬት አይነት</translation>
<translation id="7503821294401948377">አዶ «<ph name="ICON" />»ን ለአሳሽ እርምጃ መጫን አልተቻለም።</translation>
@@ -4374,6 +4384,7 @@
<translation id="7663719505383602579">ተቀባይ፦ <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">የማይደገፍ የብሉቱዝ መሣሪያ፦ «<ph name="DEVICE_NAME" />»።</translation>
<translation id="7665369617277396874">መለያ ያክሉ</translation>
+<translation id="7667248760110172428">ውጫዊ ማከማቻ</translation>
<translation id="7671130400130574146">የሥርዓት ርእሰ አሞሌ እና ጠርዞች</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />፣ በ<ph name="PAGE_TITLE" /> ውስጥ።</translation>
<translation id="7676867886086876795">ወደ ማናቸውም የጽሑፍ መስክ በቃል ማስጻፍን ለመፍቀድ ድምጽዎን ወደ Google ይላኩ።</translation>
@@ -4577,6 +4588,7 @@
<translation id="7930294771522048157">የተቀመጡ የመክፈያ ዘዴዎች እዚህ ላይ ብቅ ይላሉ</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> የእርስዎን ማያ ገጽ እና ኦዲዮ እያጋራ ነው።</translation>
<translation id="7931318309563332511">ያልታወቀ</translation>
+<translation id="7932969338829957666">የተጋሩ አቃፊዎች <ph name="BASE_DIR" /> ላይ በLinux ላይ ይይገኛሉ።</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{የጣቢያን ድምጸ-ከል አንሳ}one{የጣቢያዎችን ድምጸ-ከል አንሳ}other{የጣቢያዎችን ድምጸ-ከል አንሳ}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> የተጠበቀ ይዘትን ማጫወት ይፈልጋል። የመሣሪያዎ ማንነት በGoogle ይረጋገጣል።</translation>
<translation id="793531125873261495">ምናባዊ ማሽንን በማውረድ ላይ ስህተት። እባክዎ እንደገና ይሞክሩ።</translation>
@@ -4673,6 +4685,7 @@ nil</translation>
<translation id="8049705080247101012">Google «<ph name="EXTENSION_NAME" />»ን ተንኮል-አዘል ብሎ ጠቁሞታል፣ እና እንዳይጫን ተከልክሏል</translation>
<translation id="8049913480579063185">የቅጥያ ስም</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">ይህ ፍፋይል የWindows ሶፍትዌር ለሚጠቀም ፒሲ የተነደፈ ነው። ይህ Chrome OS ከሚያሄደው መሣሪያዎ ጋር ተኳኋኝ አይደለም። <ph name="BEGIN_LINK_HELP" />የበለጠ ለመረዳት<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 ፋይሎች</translation>
<translation id="8053390638574070785">ይህን ገጽ ዳግም ጫን</translation>
<translation id="8054517699425078995">የዚህ አይነት ፋይል መሣሪያዎን ሊጎዳ ይችላል። <ph name="FILE_NAME" />ን ለማንኛውም ማስቀመጥ ይፈልጋሉ?</translation>
@@ -4915,6 +4928,7 @@ nil</translation>
<translation id="8438566539970814960">ፍለጋዎችን እና አሰሳን የተሻለ አድርግ</translation>
<translation id="8439506636278576865">በዚህ ቋንቋ ውስጥ ያሉ ገጾችን ለመተርጎም ያቅርቡ</translation>
<translation id="8440630305826533614">Linux መተግበሪያዎች</translation>
+<translation id="8443338615972234259">እባክዎ ክትትል ለሚደረገው ተጤቃሚዎች አዲስ መለያ አሁን ይፍጠሩ።</translation>
<translation id="8446884382197647889">ተጨማሪ ለመረዳት</translation>
<translation id="8447409163267621480">Ctrl ወይም Alt ያካትቱ</translation>
<translation id="8448729345478502352">በማያ ገጽዎ ላይ ያሉ ንጥሎችን ያሳንሱ ወይም ያተልቁ</translation>
@@ -4939,6 +4953,7 @@ nil</translation>
<translation id="8468750959626135884">የእርስዎን <ph name="DEVICE_TYPE" /> በAndroid ስልክዎ ይክፈቱት።</translation>
<translation id="8470028084415844044">ሁሉንም የእርስዎ የይለፍ ቃላት በሁሉም መሣሪያዎችዎ ላይ ለማግኘት ስምረትን ያብሩ።</translation>
<translation id="8470513973197838199">የተቀመጡ የ<ph name="ORIGIN" /> የይለፍ ቃላት</translation>
+<translation id="8471635086304129332">ይህን ካርድ በሁሉም መሣሪያዎችዎ ላይ ለመጠቀም በGoogle መለያዎ ላይ ያስቀምጡት</translation>
<translation id="8472623782143987204">የሃርድዌር ደጀን ያለው</translation>
<translation id="8473863474539038330">አድራሻዎች እና ተጨማሪ</translation>
<translation id="8475313423285172237">በኮምፒውተርዎ ላይ ያለ ሌላ ፕሮግራም Chrome የሚሰራበት መንገድ ሊቀይር የሚችል አንድ ቅጥያ አክሏል።</translation>
@@ -5014,7 +5029,6 @@ nil</translation>
<translation id="8598453409908276158">ከማጠሪያ የወጣ ተሰኪ ታግዷል</translation>
<translation id="8601206103050338563">TLS WWW የተገልጋይ ማረጋገጫ</translation>
<translation id="8602851771975208551">በኮምፒውተርዎ ላይ ያለ ሌላ ፕሮግራም Chrome የሚሰራበት መንገድ ሊቀይር የሚችል አንድ መተግበሪያ አክሏል።</translation>
-<translation id="8604763363205185560">Chrome እና ደህንነቱ እንዲሻሻል ያግዙ</translation>
<translation id="8605428685123651449">የSQLite ማህደረ ትውስታ</translation>
<translation id="8606726445206553943">የእርስዎን የ MIDI መሣሪያዎች ይጠቀሙ</translation>
<translation id="8609465669617005112">ወደላይ አውጣ</translation>
@@ -5190,6 +5204,7 @@ nil</translation>
<translation id="8846141544112579928">የቁልፍ ሰሌዳን በመፈለግ ላይ...</translation>
<translation id="8847988622838149491">ዩ ኤስ ቢ</translation>
<translation id="8848561196844274665">መሣሪያዎችዎን ሲያገናኙ የእርስዎ Chromebook እነዚህን ማድረግ እንደሚችል ይስማማሉ፦</translation>
+<translation id="8850251000316748990">ተጨማሪ ይመልከቱ...</translation>
<translation id="8859057652521303089">ቋንቋዎትን ይምረጡ፦</translation>
<translation id="8859174528519900719">ንዑስ ክፈፍ፦ <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">የExcel ተመን ሉህ</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ar.xtb b/chromium/chrome/app/resources/generated_resources_ar.xtb
index 08125027f69..0ed1ad6821b 100644
--- a/chromium/chrome/app/resources/generated_resources_ar.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ar.xtb
@@ -367,7 +367,7 @@
<translation id="15373452373711364">مؤشر الماوس الكبير</translation>
<translation id="1538729222189715449">‏جارٍ فتح ملفات نظام التشغيل Linux...</translation>
<translation id="1540605929960647700">تفعيل الوضع التجريبي</translation>
-<translation id="1541396123399225659">إضافة إلى مجموعة جديدة</translation>
+<translation id="1541396123399225659">الإضافة إلى مجموعة جديدة</translation>
<translation id="1542514202066550870">‏تقدم علامة التبويب هذه محتوى VR إلى سماعة رأس.</translation>
<translation id="1543284117603151572">‏تم الاستيراد من شبكة Edge</translation>
<translation id="1545177026077493356">وضع الكشك التلقائي</translation>
@@ -518,7 +518,6 @@
<translation id="175772926354468439">تفعيل المظهر</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">‏العرض في سوق Chrome الإلكتروني</translation>
-<translation id="1761588866118490543">النموذج الصوتي</translation>
<translation id="176193854664720708">يتوفَّر مستشعر بصمات الإصبع في زر التشغيل. يمكنك لمسه برفقٍ بأي إصبع.</translation>
<translation id="1763046204212875858">إنشاء اختصارات للتطبيق</translation>
<translation id="1763108912552529023">متابعة الاستكشاف</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">‏يمكنك إرسال بيانات الاستخدام والتشخيص. يرسل هذا الجهاز حاليًا بيانات استخدام التطبيق والجهاز والتشخيص تلقائيًا إلى Google. سيساعد ذلك في استقرار عمل النظام والتطبيقات، بالإضافة إلى التحسينات الأخرى. كما ستساعد بعض البيانات المجمّعة تطبيقات Google وشركائها، مثل مطوّري برامج نظام التشغيل Android. ويفرض المالك هذا الإعداد. في حال تفعيل إعداد "النشاط الإضافي على الويب وفي التطبيقات"، قد يتم حفظ هذه البيانات في حسابك على Google. <ph name="BEGIN_LINK1" />مزيد من المعلومات<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">‏أرشيف Zip</translation>
<translation id="220858061631308971">يُرجى إدخال رمز رقم التعريف الشخصي هذا على "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">إزالة المشاركة</translation>
+<translation id="2214018885812055163">المجلدات التي تمت مشاركتها</translation>
<translation id="2214884991347062907">كلمة المرور غير صحيحة، يُرجى إعادة المحاولة.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;لم يتم عرض سطر واحد&gt;}zero{&lt;لم يتم عرض <ph name="NUMBER_OF_LINES" /> سطر&gt;}two{&lt;لم يتم عرض سطرين (<ph name="NUMBER_OF_LINES" />)&gt;}few{&lt;لم يتم عرض <ph name="NUMBER_OF_LINES" />) سطور&gt;}many{&lt;لم يتم عرض <ph name="NUMBER_OF_LINES" /> سطرًا&gt;}other{&lt;لم يتم عرض <ph name="NUMBER_OF_LINES" /> سطر&gt;}}</translation>
<translation id="2217501013957346740">أنشئ اسمًا -</translation>
@@ -940,7 +941,7 @@
<translation id="2379281330731083556">الطباعة باستخدام مربع حوار النظام... <ph name="SHORTCUT_KEY" /></translation>
<translation id="2381756643783702095">اسأل قبل الإرسال (موصى به)</translation>
<translation id="2384436799579181135">حدث خطأ ما. يُرجى التحقق من الطابعة وإعادة المحاولة.</translation>
-<translation id="2386926718981642523">‏يمكنك الوصول إلى "مساعد Google" في أي وقت تنطق فيه عبارة "Ok Google".</translation>
+<translation id="2386926718981642523">‏يمكنك الوصول إلى "مساعد Google" في أي وقت بمجرّد قول العبارة "Ok Google".</translation>
<translation id="2387458720915042159">نوع الاتصال بالخادم الوكيل</translation>
<translation id="2391419135980381625">الخط القياسي</translation>
<translation id="2391762656119864333">إبطال</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">شهادة معلقة</translation>
<translation id="2501797496290880632">اكتب اختصارًا</translation>
<translation id="2502441965851148920">يتم تفعيل التحديثات التلقائية. يتم إيقاف التحديثات اليدوية من قبل المشرف.</translation>
+<translation id="2505127913256479918">ستتم إزالة حسابك الخاضع للإشراف قريبًا</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{شاشة #}zero{شاشة #}two{شاشة #}few{شاشة #}many{شاشة #}other{شاشة #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> من <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">‏حساب متجر Google Play</translation>
@@ -1318,7 +1320,7 @@
<translation id="2972581237482394796">إعا&amp;دة</translation>
<translation id="2972642118232180842">تشغيل المحتوى المهم فقط (موصى به)</translation>
<translation id="2973324205039581528">تجاهل الموقع</translation>
-<translation id="2977480621796371840">إزالة من مجموعة</translation>
+<translation id="2977480621796371840">الإزالة من مجموعة</translation>
<translation id="2979639724566107830">فتح الإشارة في نافذة جديدة</translation>
<translation id="2981113813906970160">عرض مؤشر الماوس الكبير</translation>
<translation id="2982970937345031">إرسال التقرير بدون الكشف عن هويتك</translation>
@@ -1374,6 +1376,7 @@
<translation id="304747341537320566">محركات الكلام</translation>
<translation id="3053013834507634016">استخدام مفتاح الشهادة</translation>
<translation id="3057861065630527966">نسخ الصور والفيديوهات احتياطيًا</translation>
+<translation id="3058498974290601450">يمكنك تفعيل المزامنة في أي وقت في الإعدادات.</translation>
<translation id="3060379269883947824">تفعيل الاختيار والاستماع</translation>
<translation id="3061707000357573562">خدمة رمز التصحيح</translation>
<translation id="3065041951436100775">التعليقات المرتبطة بعلامة التبويب المعطلة.</translation>
@@ -1564,11 +1567,12 @@
<translation id="337920581046691015">سيتم تثبيت <ph name="PRODUCT_NAME" />.</translation>
<translation id="3380365263193509176">خطأ غير معروف</translation>
<translation id="3382073616108123819">عفوا! تعذّر النظام في تحديد معرفات هذا الجهاز.</translation>
+<translation id="3382086682569279540">ستتم إزالة الحساب الذي تديره قريبًا</translation>
<translation id="3382200254148930874">جارٍ إيقاف الإشراف...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">فاصل</translation>
<translation id="3389312115541230716">انقر بزر الماوس الأيمن على رمز <ph name="SMALL_PRODUCT_LOGO" /> في شريط المهام</translation>
-<translation id="3393352139658145068">‏يُرجى تفعيل "مساعد Google" عندما ينطق مستخدم عبارة “Ok Google”. ولتوفير شحن البطارية، يتم تفعيل “Ok Google” عند توصيل الجهاز بمصدر طاقة.</translation>
+<translation id="3393352139658145068">‏يُرجى تفعيل "مساعد Google" عند سماع العبارة "Ok Google". ولتوفير شحن البطارية، يتم تفعيل "Ok Google" فقط عند توصيل الجهاز بمصدر طاقة.</translation>
<translation id="3396800784455899911">‏بالنقر على الزر "قبول ومتابعة"، فأنت توافق على المعالجة الموضّحة أعلاه لخدمات Google هذه.</translation>
<translation id="3399432415385675819">سيتم إيقاف الإشعارات</translation>
<translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />، <ph name="TIME_LEFT" /></translation>
@@ -1744,8 +1748,8 @@
<translation id="3636096452488277381">مرحبًا، <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> وقت متبقٍ</translation>
<translation id="3637682276779847508">‏سيتم إيقاف شريحة SIM نهائيًا إذا لم تتمكن من إدخال مفتاح إلغاء القفل باستخدام رقم التعريف الشخصي الصحيح.</translation>
-<translation id="363863692969456324">إصلاح الأخطاء الإملائية من خلال التدقيق الإملائي المُحسَّن</translation>
<translation id="3640214691812501263">هل تريد إضافة "<ph name="EXTENSION_NAME" />" لـ <ph name="USER_NAME" />؟</translation>
+<translation id="3640613767643722554">‏تدريب "مساعد Google" على التعرُّف على صوتك</translation>
<translation id="3644896802912593514">العرض</translation>
<translation id="3645372836428131288">حرّك إصبعك قليلاً لالتقاط جزء مختلف من بصمة الإصبع.</translation>
<translation id="3648348069317717750">تم اكتشاف <ph name="USB_DEVICE_NAME" /></translation>
@@ -2142,7 +2146,6 @@
<translation id="4244238649050961491">العثور على المزيد من تطبيقات قلم الشاشة</translation>
<translation id="424546999567421758">تم اكتشاف استخدام مرتفع للقرص</translation>
<translation id="424726838611654458">‏الفتح دائمًا باستخدام Adobe Reader</translation>
-<translation id="4247330672018280062">‏سيتم إرسال النص الذي كتبته في حقول النص إلى Google.</translation>
<translation id="4247901771970415646">تتعذّر المزامنة مع <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">في انتظار الاتصال بالشبكة...</translation>
<translation id="4249373718504745892">تم حظر دخول هذه الصفحة إلى الكاميرا والميكروفون التابعين لك.</translation>
@@ -2484,6 +2487,7 @@
<translation id="4821935166599369261">&amp;التوصيف مفعّل</translation>
<translation id="4823484602432206655">قراءة إعدادات المستخدم والجهاز وتغييرها</translation>
<translation id="4823651846660089135">الجهاز للقراءة فقط</translation>
+<translation id="4824958205181053313">هل تريد إلغاء المزامنة؟</translation>
<translation id="4827675678516992122">تعذّر الاتصال</translation>
<translation id="4828937774870308359">أسترالي</translation>
<translation id="4829768588131278040">إعداد رقم التعريف الشخصي</translation>
@@ -2866,6 +2870,7 @@
<translation id="5374359983950678924">تغيير صورة</translation>
<translation id="5376169624176189338">انقر للرجوع إلى الوراء واضغط لمشاهدة السجل</translation>
<translation id="5376931455988532197">الملف كبير جدًا</translation>
+<translation id="5377594097385838788">التصفُّح المتخفي</translation>
<translation id="537813040452600081">لن تظهر الصفحات التي تعرضها في هذه النافذة في سجل المتصفح، ولن تترك آثارًا أخرى، كملفات تعريف الارتباط، في الكمبيوتر بعد الخروج. كما لن يتم الحفاظ على الملفات التي تنزلها والإشارات المرجعية التي تنشئها.</translation>
<translation id="5379140238605961210">متابعة حظر الدخول إلى الميكروفون</translation>
<translation id="5379268888377976432">التراجع عن الحذف</translation>
@@ -2887,6 +2892,7 @@
<translation id="5414566801737831689">قراءة رموز مواقع الويب التي تزورها</translation>
<translation id="5417312524372586921">مظاهر المتصفح</translation>
<translation id="5419294236999569767">وقت النظام</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">تحدّد درجة حدة النص والصور</translation>
<translation id="5422221874247253874">نقطة الوصول</translation>
<translation id="5422781158178868512">عذرًا، تعذر التعرف على جهاز مساحة التخزين الخارجية.</translation>
@@ -2907,6 +2913,7 @@
<translation id="5434065355175441495">‏تشفير PKCS #1 RSA</translation>
<translation id="5436492226391861498">في انتظار قناة الخادم...</translation>
<translation id="5436510242972373446">البحث في الموقع <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">يُرجى حفظ الملفات وإنشاء حساب جديد الآن.</translation>
<translation id="5438224778284622050">هل تريد حذف الملفات بلا إنترنت؟</translation>
<translation id="544083962418256601">إنشاء اختصارات...</translation>
<translation id="5442228125690314719">لقد حدث خطأ أثناء إنشاء نسخة القرص. يُرجى إعادة المحاولة.</translation>
@@ -3280,6 +3287,8 @@
<translation id="5965661248935608907">كما أنها تتحكم في الصفحة التي تظهر عند النقر على زر الصفحة الرئيسية أو إجراء بحث من المربع متعدد الاستخدامات.</translation>
<translation id="5971037678316050792">التحكم في حالة محول بلوتوث وإقرانه</translation>
<translation id="5972017421290582825">‏إدارة إعدادات MIDI...</translation>
+<translation id="597235323114979258">عرض المزيد من الوجهات</translation>
+<translation id="5972666587303800813">‏خدمة No-op</translation>
<translation id="5972708806901999743">نقل إلى الأعلى</translation>
<translation id="5972826969634861500">بدء <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">النسبة المئوية لشحن البطارية</translation>
@@ -3651,6 +3660,7 @@
<translation id="6527303717912515753">مشاركة</translation>
<translation id="6528513914570774834">السماح للمستخدمين الآخرين لهذا الجهاز باستخدام هذه الشبكة</translation>
<translation id="652948702951888897">‏سجل Chrome</translation>
+<translation id="6530186581263215931">فرض مشرفك هذه الإعدادات</translation>
<translation id="653019979737152879">جارٍ مزامنة <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">الاحتفاظ بالملف الضار</translation>
<translation id="6532101170117367231">‏حفظ في Google Drive</translation>
@@ -3714,9 +3724,9 @@
<translation id="6629841649550503054">‏تم نسخ جميع العناصر احتياطيًا في <ph name="BEGIN_LINK" />Google Drive.<ph name="END_LINK" /></translation>
<translation id="6630752851777525409"><ph name="EXTENSION_NAME" /> يريد وصولاً دائمًا إلى شهادة للمصادقة الذاتية نيابةً عنك.</translation>
<translation id="6635956300022133031">اختيار إعدادات الصوت في ميزة تحويل النص إلى كلام وتخصيصها</translation>
-<translation id="6637585982786704944">‏يمكن للتطبيقات والمواقع الإلكترونية التي تمنحها إذن الوصول إلى معلومات الحساب التي تحتاج إليها للعمل بشكلٍ صحيح.
+<translation id="6637585982786704944">‏يمكن للتطبيقات والمواقع الإلكترونية الحاصلة على إذن منك الوصول إلى معلومات الحساب التي تحتاج إليها للعمل بشكلٍ صحيح.
- في حال لم ترغب في إضافة حساب، يُرجى تسجيل الدخول كضيف أو فتح نافذة التصفُّح المتخفي لتصفًّح الويب.
+ إذا كنت لا تريد إضافة حساب، ما عليك سوى تسجيل الدخول كضيف أو فتح نافذة التصفُّح المتخفّي لتصفًّح الويب.
يمكنك الانتقال إلى "الإعدادات" -&gt; "حسابات Google" لعرض جميع الحسابات وإدارتها.</translation>
<translation id="6639554308659482635">‏ذاكرة SQLite</translation>
@@ -3920,7 +3930,7 @@
<translation id="6957231940976260713">اسم الخدمة</translation>
<translation id="696203921837389374">تفعيل المزامنة عبر بيانات الجوّال</translation>
<translation id="6964390816189577014">بطل</translation>
-<translation id="6964760285928603117">إزالة من مجموعة</translation>
+<translation id="6964760285928603117">الإزالة من مجموعة</translation>
<translation id="6965382102122355670">موافق</translation>
<translation id="6965648386495488594">المنفذ</translation>
<translation id="6965978654500191972">جهاز</translation>
@@ -3969,7 +3979,6 @@
<translation id="7018275672629230621">الاطّلاع على سجل التصفح وتغييره</translation>
<translation id="7019805045859631636">سريع</translation>
<translation id="7022562585984256452">تم تعيين صفحتك الرئيسية.</translation>
-<translation id="702384510542929236">‏يتم إرسال بعض معلومات النظام ومحتوى الصفحة إلى Google بدون الكشف عن الهوية.</translation>
<translation id="7025190659207909717">إدارة خدمة بيانات الجوال</translation>
<translation id="7027125358315426638">اسم قاعدة البيانات:</translation>
<translation id="7029809446516969842">كلمات المرور</translation>
@@ -4149,6 +4158,7 @@
<translation id="7289225569524511578">فتح تطبيق الخلفية</translation>
<translation id="7290242001003353852">تحاول خدمة تسجيل الدخول هذه، المُستضافة من قبل <ph name="SAML_DOMAIN" />، الدخول إلى الكاميرا.</translation>
<translation id="7290594223351252791">تأكيد التسجيل</translation>
+<translation id="7292696521213967957">‏معلومات لتصحيح أخطاء "مساعد Google"</translation>
<translation id="7295662345261934369">المشاركة مع الآخرين</translation>
<translation id="729583233778673644">‏السماح بتشفير AES وRC4: يؤدي استخدام هذا الخيار إلى زيادة المخاطر، لأن رموز RC4 غير آمنة.</translation>
<translation id="7296774163727375165">بنود <ph name="DOMAIN" /></translation>
@@ -4249,7 +4259,6 @@
<translation id="7456847797759667638">فتح موقع...</translation>
<translation id="7461924472993315131">تثبيت</translation>
<translation id="7463006580194749499">إضافة شخص</translation>
-<translation id="7464902436585505072">‏النموذج الصوتي لعبارة "Ok Google"</translation>
<translation id="7465778193084373987">‏عنوان URL لإبطال شهادة Netscape</translation>
<translation id="7469894403370665791">الاتصال بهذه الشبكة تلقائيًا</translation>
<translation id="747114903913869239">خطأ: تعذر فك تشفير الإضافة</translation>
@@ -4277,6 +4286,7 @@
<translation id="7496511874649569424">سيتم إزالة <ph name="LINUX_APP_NAME" /> والبيانات المرتبطة به من هذا الجهاز.</translation>
<translation id="7497215489070763236">‏شهادة CA للخادم</translation>
<translation id="7497981768003291373">‏ليست لديك أي سجلَّات نصية WebRTC تم التقاطها مؤخرًا.</translation>
+<translation id="7502199377020483660">‏لاستخدام هذه البطاقات على جميع الأجهزة، يمكنك حفظها في حسابك على Google</translation>
<translation id="7502658306369382406">‏عنوان IPv6</translation>
<translation id="7503191893372251637">‏نوع شهادات Netscape</translation>
<translation id="7503821294401948377">تعذر تحميل رمز '<ph name="ICON" />' لإجراء المتصفح.</translation>
@@ -4338,7 +4348,7 @@
<translation id="7602079150116086782">لا توجد علامات تبويب من أجهزة أخرى</translation>
<translation id="7604942372593434070">الدخول إلى نشاط التصفح</translation>
<translation id="7605594153474022051">المزامنة لا تعمل</translation>
-<translation id="7606992457248886637">الصلاحيات</translation>
+<translation id="7606992457248886637">مراجع التصديق</translation>
<translation id="7607002721634913082">تعليق التحميل</translation>
<translation id="7607274158153386860">طلب موقع الجهاز اللوحي</translation>
<translation id="7609148976235050828">يُرجى الاتصال بالإنترنت وإعادة المحاولة.</translation>
@@ -4374,6 +4384,7 @@
<translation id="7663719505383602579">المتلقي: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">جهاز بلوتوث غير متوافق: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">إضافة حساب</translation>
+<translation id="7667248760110172428">مساحة تخزين خارجية</translation>
<translation id="7671130400130574146">استخدام شريط عناوين النظام والحدود</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />، في <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">‏يمكنك إرسال صوتك إلى Google للسماح بالإملاء في أي حقل نصي.</translation>
@@ -4577,6 +4588,7 @@
<translation id="7930294771522048157">ستظهر هنا طرق الدفع المحفوظة</translation>
<translation id="79312157130859720">يشارك <ph name="APP_NAME" /> الشاشة والصوت.</translation>
<translation id="7931318309563332511">غير معروف</translation>
+<translation id="7932969338829957666">‏تتوفَّر المجلدات المشتركة في Linux على <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{إعادة صوت موقع ويب واحد}zero{إعادة صوت مواقع الويب}two{إعادة صوت موقعيِّ الويب}few{إعادة صوت مواقع الويب}many{إعادة صوت مواقع الويب}other{إعادة صوت مواقع الويب}}</translation>
<translation id="7934414805353235750">‏يريد عنوان <ph name="URL" /> تشغيل محتوى محمٍ، لذلك ستتحقَّق Google من هوية جهازك.</translation>
<translation id="793531125873261495">حدث خطأ أثناء تنزيل الآلة الافتراضية. يُرجى إعادة المحاولة.</translation>
@@ -4668,6 +4680,7 @@
<translation id="8049705080247101012">‏وضعت Google علامة على الإضافة <ph name="EXTENSION_NAME" /> باعتبارها ضارة وتم منع تثبيتها.</translation>
<translation id="8049913480579063185">اسم الإضافة</translation>
<translation id="8050038245906040378">‏التوقيع بالرمز التجاري لـ Microsoft</translation>
+<translation id="8052887694493382350">‏تم تصميم هذا الملف لجهاز الكمبيوتر باستخدام برنامج Windows. وهذا الملف غير متوافق مع جهازك الذي يعمل بنظام التشغيل Chrome. <ph name="BEGIN_LINK_HELP" />مزيد من المعلومات<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">‏ملفات PKCS #12</translation>
<translation id="8053390638574070785">إعادة تحميل هذه الصفحة</translation>
<translation id="8054517699425078995">قد يُلحق هذا النوع من الملفات الضرر بجهازك. هل تريد الاحتفاظ بـ <ph name="FILE_NAME" /> على أيّ حال؟</translation>
@@ -4911,6 +4924,7 @@
<translation id="8438566539970814960">تحسين عمليات البحث والتصفُّح</translation>
<translation id="8439506636278576865">عرض ترجمة الصفحات المكتوبة بهذه اللغة</translation>
<translation id="8440630305826533614">‏تطبيقات Linux</translation>
+<translation id="8443338615972234259">يُرجى إنشاء حساب جديد للمستخدم تحت الإشراف الآن.</translation>
<translation id="8446884382197647889">مزيد من المعلومات</translation>
<translation id="8447409163267621480">‏تضمين إما مفتاح Ctrl أو Alt</translation>
<translation id="8448729345478502352">تصغير العناصر المعروضة على شاشتك أو تكبيرها</translation>
@@ -4935,6 +4949,7 @@
<translation id="8468750959626135884">‏إلغاء قفل <ph name="DEVICE_TYPE" /> باستخدام هاتف Android.</translation>
<translation id="8470028084415844044">لإضافة كل كلمات المرور على جميع أجهزتك، يُرجى تفعيل المزامنة.</translation>
<translation id="8470513973197838199">كلمات المرور المحفوظة لـ <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">‏لاستخدام هذه البطاقة على جميع الأجهزة، يمكنك حفظها في حسابك على Google.</translation>
<translation id="8472623782143987204">يستند إلى الجهاز</translation>
<translation id="8473863474539038330">العناوين والمزيد</translation>
<translation id="8475313423285172237">‏أضاف برنامج آخر بجهاز الكمبيوتر إضافة قد تؤدي إلى تغيير طريقة عمل Chrome.</translation>
@@ -5010,7 +5025,6 @@
<translation id="8598453409908276158">تم حظر المكوّن الإضافي دون استخدام وضع الحماية</translation>
<translation id="8601206103050338563">‏مصادقة TLS (بروتوكول أمان طبقة النقل) لشبكة الإنترنت العالمية (WWW)</translation>
<translation id="8602851771975208551">‏أضاف برنامج آخر بجهاز الكمبيوتر تطبيقًا قد يؤدي إلى تغيير طريقة عمل Chrome.</translation>
-<translation id="8604763363205185560">‏المساعدة في تحسين Chrome وأمانه</translation>
<translation id="8605428685123651449">‏ذاكرة SQLite</translation>
<translation id="8606726445206553943">‏استخدام أجهزة MIDI</translation>
<translation id="8609465669617005112">التحريك إلى أعلى</translation>
@@ -5186,6 +5200,7 @@
<translation id="8846141544112579928">جارٍ البحث عن لوحة المفاتيح...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">‏عند ربط أجهزتك، أنت توافق على أن جهاز Chromebook سيتمكّن مما يلي:</translation>
+<translation id="8850251000316748990">عرض المزيد...</translation>
<translation id="8859057652521303089">حدد لغتك:</translation>
<translation id="8859174528519900719">هيكل سفلي: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">‏جدول بيانات Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_bg.xtb b/chromium/chrome/app/resources/generated_resources_bg.xtb
index 27a99367dcf..5e0d57b13a1 100644
--- a/chromium/chrome/app/resources/generated_resources_bg.xtb
+++ b/chromium/chrome/app/resources/generated_resources_bg.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">Активиране на темата</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Преглед в уеб магазина на Chrome</translation>
-<translation id="1761588866118490543">Гласов модел</translation>
<translation id="176193854664720708">Сензорът за отпечатъци е в бутона за включване/изключване. Докоснете го леко с който и да е пръст.</translation>
<translation id="1763046204212875858">Създаване на преки пътища към приложението</translation>
<translation id="1763108912552529023">Продължаване на изследването</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">Изпращане на данни за употребата и диагностиката. Понастоящем това устройство автоматично изпраща до Google диагностична информация и данни за употребата на устройството и приложенията. Това ще послужи за подобряване на стабилността на системата и приложенията и др. Някои обобщени данни също така ще подпомогнат приложенията и партньорите на Google, напр. програмистите за Android. Тази настройка е наложена от собственика. Ако настройката „Допълнителна активност в мрежата и приложенията“ е включена за вас, тези данни може да се запазват в профила ви в Google. <ph name="BEGIN_LINK1" />Научете повече<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Компресиран архивен файл</translation>
<translation id="220858061631308971">Моля, въведете този ПИН код на „<ph name="DEVICE_NAME" />“:</translation>
+<translation id="2213140827792212876">Премахване на споделянето</translation>
+<translation id="2214018885812055163">Споделени папки</translation>
<translation id="2214884991347062907">Грешна парола. Опитайте отново.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 ред не е показан&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> реда не са показани&gt;}}</translation>
<translation id="2217501013957346740">Създаване на име –</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">Сертификатът не е активен</translation>
<translation id="2501797496290880632">Въведете комбинация</translation>
<translation id="2502441965851148920">Автоматичните актуализации са активирани. Ръчните са деактивирани от администратора ви.</translation>
+<translation id="2505127913256479918">Този контролиран профил скоро ще бъде премахнат</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Екран #}other{Екран #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> от <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Профил за Google Play Магазин</translation>
@@ -1372,6 +1374,7 @@
<translation id="304747341537320566">Машини за синтезиран говор</translation>
<translation id="3053013834507634016">Използване на ключа на сертификата</translation>
<translation id="3057861065630527966">Създаване на резервни копия на снимките и видеоклиповете ви</translation>
+<translation id="3058498974290601450">Можете по всяко време да включите синхронизирането в настройките</translation>
<translation id="3060379269883947824">Активиране на функцията Прочитане на глас</translation>
<translation id="3061707000357573562">Услуга за корекции</translation>
<translation id="3065041951436100775">Отзиви за затворен раздел.</translation>
@@ -1563,11 +1566,12 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> ще се инсталира.</translation>
<translation id="3380365263193509176">Неизвестна грешка</translation>
<translation id="3382073616108123819">Ами сега! Системата не успя да определи идентификаторите за това устройство.</translation>
+<translation id="3382086682569279540">Профилът, който управлявате, скоро ще бъде премахнат</translation>
<translation id="3382200254148930874">Контролирането се прекратява...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Разделител</translation>
<translation id="3389312115541230716">Кликнете с десния бутон на мишката върху иконата <ph name="SMALL_PRODUCT_LOGO" /> в лентата на задачите</translation>
-<translation id="3393352139658145068">Активиране на Асистент, когато който и да е каже „Ok Google“. С цел икономия на батерия „Ok Google“ е активно само когато устройството е свързано със захранващ източник.</translation>
+<translation id="3393352139658145068">Активиране на Асистент, когато някой каже „Ok Google“. С цел икономия на батерия „Ok Google“ е активно само когато устройството е свързано със захранващ източник.</translation>
<translation id="3396800784455899911">С кликването си върху бутона „Приемам и продължавам“ приемате описаното по-горе обработване за тези услуги на Google.</translation>
<translation id="3399432415385675819">Известията ще бъдат деактивирани</translation>
<translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />, <ph name="TIME_LEFT" /></translation>
@@ -1744,8 +1748,8 @@
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – остава/т <ph name="TIME" /></translation>
<translation id="3637682276779847508">SIM картата ви ще бъде деактивирана за постоянно, ако не успеете да въведете
правилния PUK код</translation>
-<translation id="363863692969456324">Поправка на правописните грешки посредством подобрената функция за проверка на правописа</translation>
<translation id="3640214691812501263">Да се добави ли <ph name="EXTENSION_NAME" /> за <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Обучете Асистент да разпознава гласа ви</translation>
<translation id="3644896802912593514">Ширина</translation>
<translation id="3645372836428131288">Преместете малко пръста си, за да бъде заснета друга част от отпечатъка.</translation>
<translation id="3648348069317717750">Открито е устройство <ph name="USB_DEVICE_NAME" /></translation>
@@ -2146,7 +2150,6 @@
<translation id="4244238649050961491">Намиране на още приложения за писалка</translation>
<translation id="424546999567421758">Установено е използване на много място на диска</translation>
<translation id="424726838611654458">Отваряне винаги в Adobe Reader</translation>
-<translation id="4247330672018280062">Текстът, който въвеждате в текстовите полета, ще се изпраща до Google</translation>
<translation id="4247901771970415646">Не може да се синхронизира с/ъс <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Изчаква се връзка с мрежата...</translation>
<translation id="4249373718504745892">Достъпът на тази страница до камерата и микрофона ви е блокиран.</translation>
@@ -2488,6 +2491,7 @@
<translation id="4821935166599369261">&amp;Профилирането е активирано</translation>
<translation id="4823484602432206655">Четене и промяна на настройките на потребителите и устройството</translation>
<translation id="4823651846660089135">Устройството е само за четене</translation>
+<translation id="4824958205181053313">Да се анулира ли синхронизирането?</translation>
<translation id="4827675678516992122">Не можа да се установи връзка</translation>
<translation id="4828937774870308359">Обратно</translation>
<translation id="4829768588131278040">Настройване на ПИН</translation>
@@ -2870,6 +2874,7 @@
<translation id="5374359983950678924">Промяна на снимката</translation>
<translation id="5376169624176189338">Кликнете, за да се върнете назад. Задръжте, за да видите историята.</translation>
<translation id="5376931455988532197">Файлът е твърде голям</translation>
+<translation id="5377594097385838788">„Инкогнито“</translation>
<translation id="537813040452600081">Преглежданите от вас страници в този прозорец няма да се показват в историята на браузъра и няма да оставят на компютъра други следи, като „бисквитки“, след като излезете от профила си. Файловете, които изтеглите, и отметките, които създадете, няма да бъдат запазени.</translation>
<translation id="5379140238605961210">Достъпът до микрофона да продължи да се блокира</translation>
<translation id="5379268888377976432">Отмяна на изтриването</translation>
@@ -2891,6 +2896,7 @@
<translation id="5414566801737831689">Четене на иконите на посещаваните от вас уебсайтове</translation>
<translation id="5417312524372586921">Теми за браузъра</translation>
<translation id="5419294236999569767">Системен час</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Определя отчетливостта на текста и изображенията</translation>
<translation id="5422221874247253874">Точка за достъп</translation>
<translation id="5422781158178868512">За съжаление външното ви устройство за съхранение не можа да бъде разпознато.</translation>
@@ -2911,6 +2917,7 @@
<translation id="5434065355175441495">PKCS 1 с RSA шифроване</translation>
<translation id="5436492226391861498">Изчаква се прокси тунел...</translation>
<translation id="5436510242972373446">Търсене с <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Моля, запазете файловете си и създайте нов профил сега.</translation>
<translation id="5438224778284622050">Да се изтрият ли офлайн файловете?</translation>
<translation id="544083962418256601">Създаване на преки пътища...</translation>
<translation id="5442228125690314719">Грешка при създаването на образ на диска. Моля, опитайте отново.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">То също контролира коя страница се показва при кликване върху бутона „Начална страница“ или при търсене от полето за всичко.</translation>
<translation id="5971037678316050792">Контролиране на състоянието и сдвояването на адаптера за Bluetooth</translation>
<translation id="5972017421290582825">Управление на настройките за MIDI...</translation>
+<translation id="597235323114979258">Преглед на още дестинации</translation>
+<translation id="5972666587303800813">Услуга без функции</translation>
<translation id="5972708806901999743">Преместване най-горе</translation>
<translation id="5972826969634861500">Стартиране на <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Процент на зареждане на батерията</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">Споделяне</translation>
<translation id="6528513914570774834">Разрешаване на другите потребители на устройството да използват тази мрежа</translation>
<translation id="652948702951888897">История в Chrome</translation>
+<translation id="6530186581263215931">Тези настройки са наложени от администратора ви</translation>
<translation id="653019979737152879">„<ph name="FILE_NAME" />“ се синхронизира...</translation>
<translation id="6531282281159901044">Запазване на опасния файл</translation>
<translation id="6532101170117367231">Запазване в Google Диск</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">Четене и промяна на историята на сърфирането ви</translation>
<translation id="7019805045859631636">Бързо</translation>
<translation id="7022562585984256452">Началната ви страница е зададена.</translation>
-<translation id="702384510542929236">Изпраща анонимно до Google системна информация и част от съдържанието на страниците</translation>
<translation id="7025190659207909717">Управление на мобилната услуга за данни</translation>
<translation id="7027125358315426638">Име на базата от данни:</translation>
<translation id="7029809446516969842">Пароли</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">Отваряне на приложението за тапети</translation>
<translation id="7290242001003353852">Тази услуга за вход, хоствана от <ph name="SAML_DOMAIN" />, осъществява достъп до камерата ви.</translation>
<translation id="7290594223351252791">Потвърждаване на регистрацията</translation>
+<translation id="7292696521213967957">Информация за отстраняване на грешки в Асистент</translation>
<translation id="7295662345261934369">Споделяне с други хора</translation>
<translation id="729583233778673644">Разрешаване на AES и RC4 шифроване. Използването на тази опция увеличава риска, тъй като шифрите RC4 са несигурни.</translation>
<translation id="7296774163727375165">Условия на <ph name="DOMAIN" /></translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">Отваряне на местоположение...</translation>
<translation id="7461924472993315131">Фиксиране</translation>
<translation id="7463006580194749499">Добавяне на човек</translation>
-<translation id="7464902436585505072">Гласов модел на „Ok Google“</translation>
<translation id="7465778193084373987">URL адрес за анулиране на сертификат на Netscape</translation>
<translation id="7469894403370665791">Автоматично свързване с тази мрежа</translation>
<translation id="747114903913869239">Грешка: Разширението не може да се декодира</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424">Приложението <ph name="LINUX_APP_NAME" /> и свързаните с него данни ще бъдат премахнати от това устройство.</translation>
<translation id="7497215489070763236">Сертификат от сертифициращ орган за сървъра</translation>
<translation id="7497981768003291373">Нямате наскоро записани регистрационни файлове за предаване на текст с WebRTC.</translation>
+<translation id="7502199377020483660">За да използвате картите си на всичките си устройства, запазете ги в профила си в Google</translation>
<translation id="7502658306369382406">IPv6 адрес</translation>
<translation id="7503191893372251637">Тип на сертификата на Netscape</translation>
<translation id="7503821294401948377">Не можа да се зареди иконата „<ph name="ICON" />“ за действието на браузъра.</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">Приемник: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Неподдържано устройство с Bluetooth: <ph name="DEVICE_NAME" />.</translation>
<translation id="7665369617277396874">Добавяне на профил</translation>
+<translation id="7667248760110172428">Външно хранилище</translation>
<translation id="7671130400130574146">Използване на системната заглавна лента и контурите</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, в страницата „<ph name="PAGE_TITLE" />“.</translation>
<translation id="7676867886086876795">Изпращане на гласа ви до Google, за да можете да диктувате във всяко текстово поле.</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">Тук ще се покажат запазените начини на плащане</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> споделя екрана и звука ви.</translation>
<translation id="7931318309563332511">Неизвестно</translation>
+<translation id="7932969338829957666">Споделените папки са достъпни в директорията <ph name="BASE_DIR" /> на Linux.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Включване отново на звука на сайта}other{Включване отново на звука на сайтовете}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> иска да възпроизвежда защитено съдържание. Идентичността на устройството ви ще бъде удостоверена от Google.</translation>
<translation id="793531125873261495">Грешка при изтеглянето на виртуалната машина. Моля, опитайте отново.</translation>
@@ -4672,6 +4684,7 @@
<translation id="8049705080247101012">Google сигнализира, че разширението <ph name="EXTENSION_NAME" /> е злонамерено, и инсталирането бе предотвратено</translation>
<translation id="8049913480579063185">Име на разширението</translation>
<translation id="8050038245906040378">Подписване от Microsoft на код за търговски цели</translation>
+<translation id="8052887694493382350">Този файл е предназначен за компютри с Windows. Не е съвместим с устройството ви, което работи с Chrome OS. <ph name="BEGIN_LINK_HELP" />Научете повече<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Файлове PKCS #12</translation>
<translation id="8053390638574070785">Презареждане на тази страница</translation>
<translation id="8054517699425078995">Този тип файл може да навреди на устройството ви. Искате ли да запазите „<ph name="FILE_NAME" />“ въпреки това?</translation>
@@ -4915,6 +4928,7 @@
<translation id="8438566539970814960">Подобряване на търсенията и сърфирането</translation>
<translation id="8439506636278576865">Предлагане страниците на този език да се превеждат</translation>
<translation id="8440630305826533614">Приложения за Linux</translation>
+<translation id="8443338615972234259">Моля, създайте нов профил за контролирания потребител сега.</translation>
<translation id="8446884382197647889">Научете повече</translation>
<translation id="8447409163267621480">Използвайте или Ctrl, или Alt</translation>
<translation id="8448729345478502352">Смаляване или уголемяване на елементите на екрана</translation>
@@ -4939,6 +4953,7 @@
<translation id="8468750959626135884">Отключвайте устройството си <ph name="DEVICE_TYPE" /> с телефона си с Android.</translation>
<translation id="8470028084415844044">Включете синхронизирането, за да получите паролите си на всичките си устройства.</translation>
<translation id="8470513973197838199">Запазени пароли за <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">За да използвате тази карта на всичките си устройства, запазете я в профила си в Google</translation>
<translation id="8472623782143987204">с хардуерна поддръжка</translation>
<translation id="8473863474539038330">Адреси и др.</translation>
<translation id="8475313423285172237">Друга програма на компютъра ви добави разширение, което може да промени начина на работа на Chrome.</translation>
@@ -5014,7 +5029,6 @@
<translation id="8598453409908276158">Приставката извън тестовата среда е блокирана</translation>
<translation id="8601206103050338563">Удостоверяване на TLS WWW клиент</translation>
<translation id="8602851771975208551">Друга програма на компютъра ви добави приложение, което може да промени начина на работа на Chrome.</translation>
-<translation id="8604763363205185560">Помогнете за подобряването на Chrome и сигурността му</translation>
<translation id="8605428685123651449">Памет за SQLite</translation>
<translation id="8606726445206553943">Да използва MIDI устройствата ви.</translation>
<translation id="8609465669617005112">Придвижване нагоре</translation>
@@ -5190,6 +5204,7 @@
<translation id="8846141544112579928">Търси се клавиатура...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Когато свържете устройствата си, приемате, че вашият Chromebook може да:</translation>
+<translation id="8850251000316748990">Вижте още...</translation>
<translation id="8859057652521303089">Изберете своя език:</translation>
<translation id="8859174528519900719">Подрамка: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Електронна таблица в Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_bn.xtb b/chromium/chrome/app/resources/generated_resources_bn.xtb
index b0e5bc538e2..ebd8aca6e9d 100644
--- a/chromium/chrome/app/resources/generated_resources_bn.xtb
+++ b/chromium/chrome/app/resources/generated_resources_bn.xtb
@@ -517,7 +517,6 @@
<translation id="175772926354468439">থিম সক্ষম করুন</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome ওয়েব স্টোরে দেখুন</translation>
-<translation id="1761588866118490543">ভয়েস মডেল</translation>
<translation id="176193854664720708">পাওয়ার বোতামে আঙ্গুলের ছাপের সেন্সরটি আছে। যেকোনও আঙ্গুল দিয়ে আলতো করে এটিকে টাচ করুন।</translation>
<translation id="1763046204212875858">অ্যাপ্লিকেশন শর্টকাটগুলি তৈরি করুন</translation>
<translation id="1763108912552529023">অন্বেষণ করা চালিয়ে যান</translation>
@@ -814,6 +813,8 @@
<translation id="220792432208469595">ব্যবহার এবং ডায়াগনস্টিক ডেটা পাঠান। এখন এই ডিভাইসটি নিজে থেকেই Google-এ ডায়াগনিস্টিক, ডিভাইস এবং অ্যাপ ব্যবহারের ডেটা পাঠাচ্ছে। এটি সিস্টেম ও অ্যাপের স্থিতিশীলতা এবং অন্যান্য উন্নতিতে সাহায্য করে। ব্যবহারকারীদের কিছু সম্মিলিত ডেটা Google অ্যাপ এবং Android ডেভেলপারদের মতো পার্টনারদের কাজে লাগবে। এই সেটিং মালিকের নিয়ন্ত্রণে রয়েছে। আপনার অতিরিক্ত ওয়েব ও অ্যাপ অ্যাক্টিভিটি সেটিং চালু থাকলে, এই ডেটা আপনার Google অ্যাকাউন্টে সেভ করা হতে পারে। <ph name="BEGIN_LINK1" />আরও জানুন<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">জিপ সংগ্রহ</translation>
<translation id="220858061631308971">দয়া করে <ph name="DEVICE_NAME" /> "-এ পিন কোড লিখুন: </translation>
+<translation id="2213140827792212876">শেয়ার করা বন্ধ করুন</translation>
+<translation id="2214018885812055163">শেয়ার করা ফোল্ডার</translation>
<translation id="2214884991347062907">পাসওয়ার্ডটি ভুল হয়েছে, আবার চেষ্টা করুন</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;১টি লাইন দেখানো হয়নি&gt;}one{&lt;<ph name="NUMBER_OF_LINES" />টি লাইন দেখানো হয়নি&gt;}other{&lt;<ph name="NUMBER_OF_LINES" />টি লাইন দেখানো হয়নি&gt;}}</translation>
<translation id="2217501013957346740">একটি নাম লিখুন -</translation>
@@ -1013,6 +1014,7 @@
<translation id="2501173422421700905">সার্টিফিকেট স্থগিত অবস্থায় আছে</translation>
<translation id="2501797496290880632">একটি শর্টকাট লিখুন</translation>
<translation id="2502441965851148920">স্বয়ংক্রিয় আপডেট সক্ষম রয়েছে। আপনার প্রশাসক দ্বারা ম্যানুয়াল আপডেট অক্ষম করা হয়েছে।</translation>
+<translation id="2505127913256479918">এই তত্ত্বাবধানে থাকা অ্যাকাউন্ট শীঘ্রই সরিয়ে দেওয়া হবে</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{স্ক্রিন #}one{স্ক্রিন #}other{স্ক্রিন #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" />-এর <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play স্টোর অ্যাকাউন্ট</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">ভাষ্য ইঞ্জিন</translation>
<translation id="3053013834507634016">সার্টিফিকেট কী ব্যবহার</translation>
<translation id="3057861065630527966">আপনার ফটো ও ভিডিওগুলির ব্যাকআপ নিন</translation>
+<translation id="3058498974290601450">যেকোনও সময় সেটিংস থেকে আপনি সিঙ্ক চালু করতে পারেন</translation>
<translation id="3060379269883947824">'বাছুন ও শুনুন' চালু করুন</translation>
<translation id="3061707000357573562">প্যাচ পরিষেবা</translation>
<translation id="3065041951436100775">ট্যাব নষ্ট হওয়ার প্রতিক্রিয়া।</translation>
@@ -1563,6 +1566,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> ইনস্টল করা হবে৷</translation>
<translation id="3380365263193509176">অজানা ত্রুটি</translation>
<translation id="3382073616108123819">ওহো! সিস্টেমটি এই ডিভাইসের জন্য ডিভাইস শনাক্তকারী নির্ধারণ করতে ব্যর্থ হয়েছে৷</translation>
+<translation id="3382086682569279540">আপনার পরিচালিত অ্যাকাউন্ট শীঘ্রই সরিয়ে দেওয়া হবে</translation>
<translation id="3382200254148930874">তত্ত্বাবধান থামানো হচ্ছে...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">পৃথককারী</translation>
@@ -1699,7 +1703,7 @@
<translation id="3574917942258583917">ছদ্মবেশী মোড থেকে বেরিয়ে আসতে চান?</translation>
<translation id="3576324189521867626">সফলভাবে ইনস্টল হয়েছে</translation>
<translation id="3578594933904494462">এই ট্যাবের সামগ্রী শেয়ার করা হচ্ছে৷</translation>
-<translation id="357886715122934472">আপনার মালিকানাধীন একটি গোষ্ঠীর সাথে &lt;strong&gt;<ph name="SENDER" />&lt;/strong&gt; একটি প্রিন্টার শেয়ার করতে চান &lt;strong&gt;<ph name="PRINTER_NAME" />&lt;/strong&gt;: &lt;strong&gt;<ph name="GROUP_NAME" />&lt;/strong&gt;. যদি আপানি স্বীকার করেন তবে, গোষ্ঠীর সকল সদস্য প্রিন্টারটিকে প্রিন্ট করতে পারবেন৷</translation>
+<translation id="357886715122934472">আপনার মালিকানাধীন &lt;strong&gt;<ph name="GROUP_NAME" />&lt;/strong&gt; গ্রুপের সাথে &lt;strong&gt;<ph name="SENDER" />&lt;/strong&gt; একটি প্রিন্টার &lt;strong&gt;<ph name="PRINTER_NAME" />&lt;/strong&gt; শেয়ার করতে চান। যদি আপনি স্বীকার করেন তাহলে গ্রুপের সব সদস্য এই প্রিন্টারে প্রিন্ট করতে পারবেন।</translation>
<translation id="3580923162759633716">প্রোফাইলিং পরিষেবা</translation>
<translation id="3584169441612580296">আপনার কম্পিউটার থেকে ফটো, সঙ্গীত ও অন্য মিডিয়া পডুন এবং পরিবর্তন করুন</translation>
<translation id="3587482841069643663">সকল</translation>
@@ -1743,8 +1747,8 @@
<translation id="3636096452488277381"><ph name="USER_GIVEN_NAME" />, কেমন আছেন?</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> বাকি আছে</translation>
<translation id="3637682276779847508">আপনি পিন আনলক করার সঠিক কী না লিখলে আপনার সিম কার্ড স্থায়ীভাবে অক্ষম হয়ে যাবে।</translation>
-<translation id="363863692969456324">আরও উন্নত বানান পরীক্ষার মাধ্যমে ভুল বানানগুলি ঠিক করুন</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> এর জন্য "<ph name="EXTENSION_NAME" />" জুড়বেন?</translation>
+<translation id="3640613767643722554">অ্যাসিস্ট্যান্টকে আপনার ভয়েস চিনতে শেখান</translation>
<translation id="3644896802912593514">প্রস্থ</translation>
<translation id="3645372836428131288">আঙ্গুলের ছাপের বিভিন্ন অংশ ক্যাপচার করতে একটু এদিক-ওদিক সরান৷</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> শনাক্ত হয়েছে</translation>
@@ -2143,7 +2147,6 @@
<translation id="4244238649050961491">আরও স্টাইলাস স্টাইলাস অ্যাপ খুঁজুন</translation>
<translation id="424546999567421758">খুব বেশি পরিমান ডিস্কের ব্যবহার শনাক্ত করা হয়েছে</translation>
<translation id="424726838611654458">সর্বদা Adobe Reader এ খুলুন</translation>
-<translation id="4247330672018280062">টেক্সট ফিল্ডে আপনার লেখা টেক্সট Google-এ পাঠানো হবে</translation>
<translation id="4247901771970415646"><ph name="USERNAME" />-এর সাথে সিঙ্ক করা যাবে না</translation>
<translation id="4249248555939881673">নেটওয়ার্ক সংযোগের জন্য অপেক্ষা করা হচ্ছে...</translation>
<translation id="4249373718504745892">এই পৃষ্ঠাটিকে আপনার ক্যামেরা এবং মাইক্রোফোন অ্যাক্সেস করা থেকে অবরুদ্ধ করা হয়েছে৷</translation>
@@ -2485,6 +2488,7 @@
<translation id="4821935166599369261">&amp;প্রোফাইলিং সক্ষমিত</translation>
<translation id="4823484602432206655">ব্যবহারকারী এবং ডিভাইস সেটিংস পড়ুন ও পরিবর্তন করুন</translation>
<translation id="4823651846660089135">ডিভাইস শুধুমাত্র পঠনযোগ্য</translation>
+<translation id="4824958205181053313">সিঙ্ক বাতিল করতে চান?</translation>
<translation id="4827675678516992122">কানেক্ট করা যায়নি</translation>
<translation id="4828937774870308359">অস্ট্রেলীয়</translation>
<translation id="4829768588131278040">পিন সেট আপ করুন</translation>
@@ -2866,6 +2870,7 @@
<translation id="5374359983950678924">ছবি পরিবর্তন করুন</translation>
<translation id="5376169624176189338">পিছনে যাওয়ার জন্য ক্লিক করুন, ইতিহাস দেখার জন্য ধরে রাখুন</translation>
<translation id="5376931455988532197">ফাইল অত্যন্ত বড়</translation>
+<translation id="5377594097385838788">ছদ্মবেশী মোড</translation>
<translation id="537813040452600081">এই উইন্ডোতে আপনি যে পৃষ্ঠাগুলি দেখেন তা ব্রাউজারের ইতিহাসে দেখাবে না এবং আপনি কম্পিউটার থেকে সাইন-আউটের পরে এটি কম্পিউটারে কুকিজের মতো অন্য কোনো রকম চিহ্ন রেখে যাবে না। আপনার ডাউনলোড করা ফাইল এবং বুকমার্কগুলি সংরক্ষিত হবে না।</translation>
<translation id="5379140238605961210">মাইক্রোফোন অ্যাক্সেসের অবরোধ করা অবিরত রাখুন</translation>
<translation id="5379268888377976432">মোছা পূর্বাবস্থায় ফিরুন</translation>
@@ -2887,6 +2892,7 @@
<translation id="5414566801737831689">আপনার পরিদর্শন করা ওয়েবসাইটগুলির আইকনগুলি পড়ুন</translation>
<translation id="5417312524372586921">ব্রাউজারের থিম</translation>
<translation id="5419294236999569767">সিস্টেমের সময়</translation>
+<translation id="5419405654816502573">Voice match</translation>
<translation id="5420438158931847627">টেক্সট এবং ছবির তীক্ষ্ণতা নির্ধারণ করে</translation>
<translation id="5422221874247253874">অ্যাক্সেস পয়েন্ট</translation>
<translation id="5422781158178868512">আপনার বাহ্যিক স্টোরেজের ডিভাইসটি শনাক্ত করা যায়নি৷</translation>
@@ -2907,6 +2913,7 @@
<translation id="5434065355175441495">PKCS #1 RSA এনক্রিপশান</translation>
<translation id="5436492226391861498">প্রক্সি টানেলের জন্য প্রতীক্ষারত...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> খুঁজুন:</translation>
+<translation id="543806387003274181">আপনার ফাইল সেভ করে একটি নতুন অ্যাকাউন্ট তৈরি করুন।</translation>
<translation id="5438224778284622050">অফলাইন ফাইলগুলি মুছবেন?</translation>
<translation id="544083962418256601">শর্টকাটগুলি তৈরি করুন...</translation>
<translation id="5442228125690314719">ডিস্ক ইমেজ তৈরি করতে সমস্যা হচ্ছে। আবার চেষ্টা করুন।</translation>
@@ -3281,6 +3288,8 @@
<translation id="5965661248935608907">আপনি হোম বোতাম ক্লিক করলে বা Omnibox থেকে সার্চ করলে কোন পৃষ্ঠাটি দেখানো হবে তাও এটি নিয়ন্ত্রণ করে।</translation>
<translation id="5971037678316050792">ব্লুটুথ অ্যাডাপ্টারের স্থিতি ও যুক্ত করা নিয়ন্ত্রণ করে</translation>
<translation id="5972017421290582825">MIDI সেটিংস পরিচালনা করুন...</translation>
+<translation id="597235323114979258">প্রিন্ট করার জন্য আরও ডিভাইস দেখুন</translation>
+<translation id="5972666587303800813">নো-অপারেশন পরিষেবা</translation>
<translation id="5972708806901999743">শীর্ষে যান</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> শুরু করুন</translation>
<translation id="5975792506968920132">ব্যাটারি চার্জের শতাংশ মান</translation>
@@ -3652,6 +3661,7 @@
<translation id="6527303717912515753">শেয়ার করুন</translation>
<translation id="6528513914570774834">এই ডিভাইসের অন্যান্য ব্যবহারকারীদের এই নেটওয়ার্ক ব্যবহার করতে দিন</translation>
<translation id="652948702951888897">Chrome ইতিহাস</translation>
+<translation id="6530186581263215931">আপনার অ্যাডমিনিস্ট্রেটর এই সেটিংস প্রয়োগ করেন</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> সিঙ্ক হচ্ছে...</translation>
<translation id="6531282281159901044">বিপজ্জনক ফাইল রাখুন</translation>
<translation id="6532101170117367231">Google ড্রাইভে সেভ করুন</translation>
@@ -3970,7 +3980,6 @@
<translation id="7018275672629230621">আপনার ব্রাউজিং ইতিহাস পড়ুন এবং পরিবর্তন করুন</translation>
<translation id="7019805045859631636">দ্রুত</translation>
<translation id="7022562585984256452">আপনার হোম পৃষ্ঠা সেট করা হয়েছে৷</translation>
-<translation id="702384510542929236">সিস্টেমের কিছু তথ্য এবং পৃষ্ঠার কন্টেন্ট Google-কে পরিচয় গোপন রেখে পাঠায়</translation>
<translation id="7025190659207909717">মোবাইল ডেটা পরিষেবা পরিচালন</translation>
<translation id="7027125358315426638">ডেটাবেসের নাম:</translation>
<translation id="7029809446516969842">পাসওয়ার্ড</translation>
@@ -4150,6 +4159,7 @@
<translation id="7289225569524511578">ওয়ালপেপার অ্যাপ্লিকেশানটি খুলুন</translation>
<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> দ্বারা হোস্ট করা এই সাইন ইন পরিষেবাটি আপনার ক্যামেরা অ্যাক্সেস করছে।</translation>
<translation id="7290594223351252791">নিবন্ধিকরণ নিশ্চিত করুন</translation>
+<translation id="7292696521213967957">অ্যাসিস্ট্যান্ট ডিবাগ করা সংক্রান্ত তথ্য</translation>
<translation id="7295662345261934369">অন্যদের সাথে শেয়ার করুন</translation>
<translation id="729583233778673644">AES এবং RC4 এনক্রিপশন অনুমতি দিন। এই বিকল্পটির ব্যবহার ঝুঁকি বাড়ায় কারণ RC4 সাইফারটি নিরাপদ নয়।</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> এর শর্তাবলী</translation>
@@ -4250,7 +4260,6 @@
<translation id="7456847797759667638">লোকেশন খুলুন...</translation>
<translation id="7461924472993315131">পিন</translation>
<translation id="7463006580194749499">একজন ব্যক্তিকে যোগ করুন</translation>
-<translation id="7464902436585505072">"ওকে Google" ভয়েস মডেল</translation>
<translation id="7465778193084373987">Netscape সার্টিফিকেট রদকরণ ইউআরএল</translation>
<translation id="7469894403370665791">স্বয়ংক্রিয়ভাবে এই নেটওয়ার্কে সংযোগ করুন</translation>
<translation id="747114903913869239">সমস্যা: এক্সটেনশন ডিকোড করা যায়নি</translation>
@@ -4278,6 +4287,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> ও সেটির সাথে সংশ্লিষ্ট ডেটা এই ডিভাইস থেকে সরিয়ে দেওয়া হবে।</translation>
<translation id="7497215489070763236">সার্ভার CA সার্টিফিকেট</translation>
<translation id="7497981768003291373">আপনার সাম্প্রতিক কোনও ক্যাপচার করা WebRTC টেক্সট লগ নেই।</translation>
+<translation id="7502199377020483660">আপনার সব ডিভাইসে এই কার্ডগুলি ব্যবহার করতে আপনার Google অ্যাকাউন্টে সেগুলি সেভ করুন</translation>
<translation id="7502658306369382406">IPv6 ঠিকানা</translation>
<translation id="7503191893372251637">Netscape সার্টিফিকেটের প্রকার</translation>
<translation id="7503821294401948377">ব্রাউজার ক্রিয়ার জন্য '<ph name="ICON" />' আইকন লোড করা যায়নি৷</translation>
@@ -4375,6 +4385,7 @@
<translation id="7663719505383602579">গ্রাহক: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">অসমর্থিত ব্লুটুথ ডিভাইস: "<ph name="DEVICE_NAME" />"৷</translation>
<translation id="7665369617277396874">অ্যাকাউন্ট যোগ করুন</translation>
+<translation id="7667248760110172428">এক্সটার্নাল স্টোরেজ</translation>
<translation id="7671130400130574146">সিস্টেম শিরোনাম দণ্ড ও সীমানাগুলি ব্যবহার করুন</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> এ।</translation>
<translation id="7676867886086876795">যেকোনও টেক্সট ক্ষেত্রে ডিকটেশনের অনুমতি দেওয়ার জন্য Google-কে আপনার ভয়েস পাঠান।</translation>
@@ -4577,6 +4588,7 @@
<translation id="7930294771522048157">এখানে সেভ করা পেমেন্টের পদ্ধতিগুলি দেখা যাবে</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> আপনার স্ক্রিন এবং অডিও শেয়ার করছে।</translation>
<translation id="7931318309563332511">অজানা</translation>
+<translation id="7932969338829957666">Linux-এর <ph name="BASE_DIR" />-এ শেয়ার করা ফোল্ডার পাওয়া যাবে।</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{সাইট আনমিউট করুন}one{সাইট আনমিউট করুন}other{সাইট আনমিউট করুন}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> সুরক্ষিত কন্টেন্ট চালাতে চায়। আপনার ডিভাইসের পরিচয় Google দ্বারা যাচাই করা হবে।</translation>
<translation id="793531125873261495">ভার্চুয়াল মেশিন ডাউনলোড করার সময় সমস্যা হয়েছে। আবার চেষ্টা করুন।</translation>
@@ -4668,6 +4680,7 @@
<translation id="8049705080247101012">Google <ph name="EXTENSION_NAME" /> কে ক্ষতিকারক হিসাবে ফ্ল্যাগ করেছে এবং ইনস্টলেশন বন্ধ করা হয়েছে</translation>
<translation id="8049913480579063185">এক্সটেনশনের নাম</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">Windows সফ্টওয়্যার ব্যবহার করে এমন PC-এর জন্য ফাইলটি তৈরি করা হয়েছে। আপনার ডিভাইস Chrome OS-এ চলে বলে সেটি এর জন্য মানানসই নয়। <ph name="BEGIN_LINK_HELP" />আরও জানুন<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 টি ফাইল</translation>
<translation id="8053390638574070785">এই পৃষ্ঠাটি পুনঃ লোড করুন</translation>
<translation id="8054517699425078995">এই ধরনের ফাইলের প্রকার আপনার ডিভাইসের ক্ষতি করতে পারে৷ আপনি কী যে কোনো উপায়ে <ph name="FILE_NAME" />টিকে রাখতে চান?</translation>
@@ -4911,6 +4924,7 @@
<translation id="8438566539970814960">সার্চ এবং ব্রাউজিং অভিজ্ঞতা আরও উন্নত করুন</translation>
<translation id="8439506636278576865">এই ভাষাতে পৃষ্ঠাগুলি অনুবাদ করার প্রস্তাব করে</translation>
<translation id="8440630305826533614">Linux অ্যাপ</translation>
+<translation id="8443338615972234259">আপনার তত্ত্বাবধানে থাকা ব্যবহারকারীর জন্য একটি অ্যাকাউন্ট এখন তৈরি করুন।</translation>
<translation id="8446884382197647889">আরও জানুন</translation>
<translation id="8447409163267621480">Ctrl অথবা Alt ব্যবহার করতে হবে</translation>
<translation id="8448729345478502352">আপনার স্ক্রিনে আইটেমগুলি ছোট অথবা বড় করুন</translation>
@@ -4935,6 +4949,7 @@
<translation id="8468750959626135884">আপনার Android ফোন দিয়ে আপনার <ph name="DEVICE_TYPE" /> আনলক করুন।</translation>
<translation id="8470028084415844044">সব ডিভাইসে আপনার পাসওয়ার্ড পেতে, সিঙ্ক চালু করুন।</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" /> এর জন্য সেভ করা পাসওয়ার্ডগুলি</translation>
+<translation id="8471635086304129332">আপনার সব ডিভাইসে এই কার্ড ব্যবহার করতে আপনার Google অ্যাকাউন্টে সেটি সেভ করুন</translation>
<translation id="8472623782143987204">hardware-backed</translation>
<translation id="8473863474539038330">ঠিকানা ও আরও অনেককিছু</translation>
<translation id="8475313423285172237">আপনার কম্পিউটারের অন্য একটি প্রোগ্রাম এক্সটেনশন যোগ করেছে যা Chrome-এর কাজ করার ধরন পাল্টে দিতে পারে৷</translation>
@@ -5010,7 +5025,6 @@
<translation id="8598453409908276158">আনস্যান্ডবক্সড প্লাগ-ইন ব্লক করা হয়েছে</translation>
<translation id="8601206103050338563">TLS WWW ক্লায়েন্ট প্রমাণীকরণ</translation>
<translation id="8602851771975208551">আপনার কম্পিউটারের অন্য একটি প্রোগ্রাম একটি অ্যাপ্লিকেশন জুড়েছে যা Chrome এর কাজ করার পদ্ধতিকে পাল্টে দিতে পারে৷</translation>
-<translation id="8604763363205185560">Chrome-এর বৈশিষ্ট্য এবং নিরাপত্তা উন্নত করে তুলতে সাহায্য করুন</translation>
<translation id="8605428685123651449">SQLite মেমোরি</translation>
<translation id="8606726445206553943">আপনার MIDI ডিভাইসসমূহ ব্যবহার করুন</translation>
<translation id="8609465669617005112">উপরে যান</translation>
@@ -5186,6 +5200,7 @@
<translation id="8846141544112579928">কীবোর্ডের জন্য সার্চ করা হচ্ছে...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">আপনার ডিভাইস কানেক্ট করার মাধ্যমে আপনি সম্মত হচ্ছেন যে আপনার Chromebook এগুলি করতে পারে:</translation>
+<translation id="8850251000316748990">আরও দেখুন…</translation>
<translation id="8859057652521303089">আপনার ভাষা বেছে নিন:</translation>
<translation id="8859174528519900719">সাবফ্রেম: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel spreadsheet</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ca.xtb b/chromium/chrome/app/resources/generated_resources_ca.xtb
index a23e9b13865..f83990b3df4 100644
--- a/chromium/chrome/app/resources/generated_resources_ca.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ca.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Activa el tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Mostra a Chrome Web Store</translation>
-<translation id="1761588866118490543">Model de veu</translation>
<translation id="176193854664720708">El sensor d'empremtes digitals és al botó d'engegada. Toca'l lleugerament amb un dit.</translation>
<translation id="1763046204212875858">Creació de dreceres a aplicacions</translation>
<translation id="1763108912552529023">Continua explorant</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Envia dades d'ús i de diagnòstic. En aquests moments aquest dispositiu envia automàticament a Google dades de diagnòstic, del dispositiu i d''ús d'aplicacions. Aquestes dades ajudaran a millorar l'estabilitat del sistema i de les aplicacions, entre altres característiques. Una part de les dades agregades també serà útil per a les aplicacions i els col·laboradors de Google, com ara els desenvolupadors d'Android. El propietari ha aplicat aquesta opció de configuració. Si tens activada l'opció Activitat al web i en aplicacions addicional, és possible que aquestes dades es desin al teu Compte de Google. <ph name="BEGIN_LINK1" />Més informació<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Fitxer zip</translation>
<translation id="220858061631308971">Introduïu aquest codi PIN a "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Deixa de compartir</translation>
+<translation id="2214018885812055163">Carpetes compartides</translation>
<translation id="2214884991347062907">La contrasenya no és correcta. Torna-ho a provar.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;Hi ha 1 línia que no es mostra&gt;}other{&lt;Hi ha <ph name="NUMBER_OF_LINES" /> línies que no es mostren&gt;}}</translation>
<translation id="2217501013957346740">Creeu un nom:</translation>
@@ -1014,6 +1015,7 @@
<translation id="2501173422421700905">Certificat retingut</translation>
<translation id="2501797496290880632">Escriviu una drecera</translation>
<translation id="2502441965851148920">Les actualitzacions automàtiques estan activades. En canvi, el vostre administrador ha desactivat les manuals.</translation>
+<translation id="2505127913256479918">Aquest compte supervisat se suprimirà aviat</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Pantalla #}other{Pantalla #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> de <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Compte de Google Play Store</translation>
@@ -1373,6 +1375,7 @@
<translation id="304747341537320566">Motors de veu</translation>
<translation id="3053013834507634016">Ús de claus de certificat</translation>
<translation id="3057861065630527966">Crea una còpia de seguretat de les fotos i dels vídeos</translation>
+<translation id="3058498974290601450">Pots activar la sincronització en qualsevol moment des de la configuració</translation>
<translation id="3060379269883947824">Activa Escolta la selecció</translation>
<translation id="3061707000357573562">Servei de pedaç</translation>
<translation id="3065041951436100775">Suggeriments sobre el tancament sobtat de la pestanya</translation>
@@ -1563,6 +1566,7 @@
<translation id="337920581046691015">S'instal·larà <ph name="PRODUCT_NAME" />.</translation>
<translation id="3380365263193509176">Error desconegut</translation>
<translation id="3382073616108123819">El sistema no ha pogut determinar els identificadors d'aquest dispositiu.</translation>
+<translation id="3382086682569279540">El compte que gestiones se suprimirà aviat</translation>
<translation id="3382200254148930874">S'està aturant la supervisió...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separador</translation>
@@ -1738,13 +1742,13 @@
<translation id="3627588569887975815">Obre l'enllaç en una finestra d'incò&amp;gnit</translation>
<translation id="3627671146180677314">Data i hora de renovació de certificat de Netscape</translation>
<translation id="3627879631695760395">Instal·la <ph name="APP" />...</translation>
-<translation id="3630132874740063857">Telèfon</translation>
+<translation id="3630132874740063857">El teu telèfon</translation>
<translation id="3630995161997703415">Afegeix aquest lloc web al teu prestatge per utilitzar-lo en qualsevol moment</translation>
<translation id="3636096452488277381">Hola, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - Temps restant: <ph name="TIME" /></translation>
<translation id="3637682276779847508">Si no introdueixes el número PUK correcte, la targeta SIM es desactivarà de manera definitiva.</translation>
-<translation id="363863692969456324">Corregeix els errors d'ortografia amb el corrector ortogràfic millorat</translation>
<translation id="3640214691812501263">Voleu afegir l'extensió <ph name="EXTENSION_NAME" /> per a <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Ensenya l'Assistent a reconèixer la teva veu</translation>
<translation id="3644896802912593514">Amplada</translation>
<translation id="3645372836428131288">Mou el dit lleugerament perquè es pugui capturar una altra part de l'empremta digital.</translation>
<translation id="3648348069317717750">S'ha detectat <ph name="USB_DEVICE_NAME" /></translation>
@@ -2143,7 +2147,6 @@
<translation id="4244238649050961491">Cerca més aplicacions de llapis òptic</translation>
<translation id="424546999567421758">Ús de disc elevat detectat</translation>
<translation id="424726838611654458">Obre sempre a Adobe Reader</translation>
-<translation id="4247330672018280062">Allò que escriguis als camps de text s'enviarà a Google</translation>
<translation id="4247901771970415646">No es pot sincronitzar amb <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">S'està esperant la connexió de xarxa...</translation>
<translation id="4249373718504745892">S'ha bloquejat l'accés d'aquesta pàgina a la càmera i al micròfon</translation>
@@ -2485,6 +2488,7 @@
<translation id="4821935166599369261">Creació de &amp;perfils activada</translation>
<translation id="4823484602432206655">Llegir i canviar la configuració d'usuari i del dispositiu</translation>
<translation id="4823651846660089135">El dispositiu és només de lectura</translation>
+<translation id="4824958205181053313">Vols cancel·lar la sincronització?</translation>
<translation id="4827675678516992122">No s'ha pogut connectar</translation>
<translation id="4828937774870308359">Australià</translation>
<translation id="4829768588131278040">Configura un PIN</translation>
@@ -2868,6 +2872,7 @@
<translation id="5374359983950678924">Canvia la imatge</translation>
<translation id="5376169624176189338">Feu clic per tornar enrere o manteniu premut per veure l'historial</translation>
<translation id="5376931455988532197">El fitxer és massa gran</translation>
+<translation id="5377594097385838788">Incògnit</translation>
<translation id="537813040452600081">Les pàgines que visualitzeu en aquesta finestra no es mostraran a l'historial del navegador i no deixaran cap altre rastre a l'ordinador, com ara galetes, després de tancar la sessió. No es conservaran els fitxers que baixeu ni les adreces d'interès.</translation>
<translation id="5379140238605961210">Continua bloquejant l'accés al micròfon</translation>
<translation id="5379268888377976432">Desfés la supressió</translation>
@@ -2889,6 +2894,7 @@
<translation id="5414566801737831689">Llegeix les icones dels llocs web visitats</translation>
<translation id="5417312524372586921">Temes del navegador</translation>
<translation id="5419294236999569767">Hora del sistema</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Determina la nitidesa del text i les imatges</translation>
<translation id="5422221874247253874">Punt d'accés</translation>
<translation id="5422781158178868512">El dispositiu d'emmagatzematge extern no s'ha pogut reconèixer.</translation>
@@ -2909,6 +2915,7 @@
<translation id="5434065355175441495">PKCS #1 amb encriptació RSA</translation>
<translation id="5436492226391861498">S'està esperant un túnel de servidor intermediari...</translation>
<translation id="5436510242972373446">Cerca <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Desa els teus fitxers i crea un compte ara.</translation>
<translation id="5438224778284622050">Vols suprimir els fitxers sense connexió?</translation>
<translation id="544083962418256601">Crea dreceres...</translation>
<translation id="5442228125690314719">S'ha produït un error en crear la imatge de disc. Torna-ho a provar.</translation>
@@ -3283,6 +3290,8 @@ Assegureu-vos que no es pugui accedir a informació sensible.</translation>
<translation id="5965661248935608907">També controla la pàgina que es mostra quan feu clic al botó Pàgina d'inici o quan feu una cerca des de l'omnibox.</translation>
<translation id="5971037678316050792">Controlar l'estat i l'emparellament de l'adaptador Bluetooth</translation>
<translation id="5972017421290582825">Gestiona la configuració de MIDI...</translation>
+<translation id="597235323114979258">Mostra més destinacions</translation>
+<translation id="5972666587303800813">Servei no operatiu</translation>
<translation id="5972708806901999743">Mou a la part superior</translation>
<translation id="5972826969634861500">Inicia <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Percentatge de càrrega de la bateria</translation>
@@ -3653,6 +3662,7 @@ Assegureu-vos que no es pugui accedir a informació sensible.</translation>
<translation id="6527303717912515753">Comparteix</translation>
<translation id="6528513914570774834">Permet que els altres usuaris d'aquest dispositiu facin servir aquesta xarxa</translation>
<translation id="652948702951888897">Historial de Chrome</translation>
+<translation id="6530186581263215931">L'administrador ha aplicat aquesta configuració</translation>
<translation id="653019979737152879">S'està sincronitzant <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Desa el fitxer perillós</translation>
<translation id="6532101170117367231">Desa a Google Drive</translation>
@@ -3971,7 +3981,6 @@ Assegureu-vos que no es pugui accedir a informació sensible.</translation>
<translation id="7018275672629230621">Llegeix i modifica l'historial de navegació</translation>
<translation id="7019805045859631636">Ràpid</translation>
<translation id="7022562585984256452">S'ha definit la pàgina d'inici.</translation>
-<translation id="702384510542929236">Envia a Google algunes dades del sistema i contingut de les pàgines de manera anònima</translation>
<translation id="7025190659207909717">Gestió de serveis de dades mòbils</translation>
<translation id="7027125358315426638">Nom de la base de dades:</translation>
<translation id="7029809446516969842">Contrasenyes</translation>
@@ -4151,6 +4160,7 @@ Assegureu-vos que no es pugui accedir a informació sensible.</translation>
<translation id="7289225569524511578">Obre l'aplicació de fons de pantalla</translation>
<translation id="7290242001003353852">Aquest servei d'inici de sessió, que s'allotja a <ph name="SAML_DOMAIN" />, està accedint a la càmera.</translation>
<translation id="7290594223351252791">Confirmació del registre</translation>
+<translation id="7292696521213967957">Informació per depurar l'Assistent</translation>
<translation id="7295662345261934369">Comparteix amb altres persones</translation>
<translation id="729583233778673644">Permet l'encriptació AES i RC4. L'ús d'aquesta opció augmenta el risc, ja que els xifratges RC4 no són segurs.</translation>
<translation id="7296774163727375165">Condicions de <ph name="DOMAIN" /></translation>
@@ -4251,7 +4261,6 @@ Assegureu-vos que no es pugui accedir a informació sensible.</translation>
<translation id="7456847797759667638">Obre la ubicació...</translation>
<translation id="7461924472993315131">Fixa</translation>
<translation id="7463006580194749499">Afegeix una persona</translation>
-<translation id="7464902436585505072">Model de veu d'"Ok Google"</translation>
<translation id="7465778193084373987">URL de revocació de certificats de Netscape</translation>
<translation id="7469894403370665791">Connecta automàticament a aquesta xarxa</translation>
<translation id="747114903913869239">Error: no s'ha pogut descodificar l'extensió</translation>
@@ -4279,6 +4288,7 @@ Assegureu-vos que no es pugui accedir a informació sensible.</translation>
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> i les dades associades a l'aplicació se suprimiran del dispositiu.</translation>
<translation id="7497215489070763236">Certificat de CA del servidor</translation>
<translation id="7497981768003291373">No s'ha capturat cap registre de text de WebRTC recentment.</translation>
+<translation id="7502199377020483660">Per fer servir aquestes targetes en tots els teus dispositius, desa-les al Compte de Google</translation>
<translation id="7502658306369382406">Adreça IPv6</translation>
<translation id="7503191893372251637">Tipus de certificat de Netscape</translation>
<translation id="7503821294401948377">No s'ha pogut carregar la icona "<ph name="ICON" />" per a l'acció del navegador.</translation>
@@ -4374,6 +4384,7 @@ Assegureu-vos que no es pugui accedir a informació sensible.</translation>
<translation id="7663719505383602579">Receptor: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Dispositiu Bluetooth no compatible: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Afegeix un compte</translation>
+<translation id="7667248760110172428">Emmagatzematge extern</translation>
<translation id="7671130400130574146">Utilitza la barra del títol i els límits del sistema</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, a <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Envia la teva veu a Google per permetre els dictats en qualsevol camp de text.</translation>
@@ -4577,6 +4588,7 @@ Assegureu-vos que no es pugui accedir a informació sensible.</translation>
<translation id="7930294771522048157">Les formes de pagament desades es mostraran aquí</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> està compartint la pantalla i l'àudio.</translation>
<translation id="7931318309563332511">Desconegut</translation>
+<translation id="7932969338829957666">Les carpetes compartides estan disponibles a Linux a <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Activa el so del lloc web}other{Activa el so dels llocs web}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> vol reproduir contingut protegit. Google verificarà la identitat del teu dispositiu.</translation>
<translation id="793531125873261495">S'ha produït un error en baixar la màquina virtual. Torna-ho a provar.</translation>
@@ -4668,6 +4680,7 @@ Deseu el fitxer de clau en una ubicació segura. El necessitareu per crear versi
<translation id="8049705080247101012">Google ha marcat l'extensió <ph name="EXTENSION_NAME" /> com a maliciosa i, per tant, s'ha evitat que s'instal·lés</translation>
<translation id="8049913480579063185">Nom de l'extensió</translation>
<translation id="8050038245906040378">Signatura de codi comercial de Microsoft</translation>
+<translation id="8052887694493382350">Aquest fitxer està dissenyat per a un ordinador que faci servir programari de Windows. No és compatible amb el teu dispositiu, que funciona amb Chrome OS. <ph name="BEGIN_LINK_HELP" />Més informació<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 fitxers</translation>
<translation id="8053390638574070785">Torna a carregar aquesta pàgina</translation>
<translation id="8054517699425078995">Aquest tipus de fitxer pot malmetre el vostre dispositiu. Voleu conservar <ph name="FILE_NAME" /> de totes maneres?</translation>
@@ -4910,6 +4923,7 @@ Deseu el fitxer de clau en una ubicació segura. El necessitareu per crear versi
<translation id="8438566539970814960">Millora les cerques i la navegació</translation>
<translation id="8439506636278576865">Proposa'm traduir pàgines en aquest idioma</translation>
<translation id="8440630305826533614">Aplicacions per a Linux</translation>
+<translation id="8443338615972234259">Crea un compte per al teu usuari supervisat ara.</translation>
<translation id="8446884382197647889">Més informació</translation>
<translation id="8447409163267621480">Inclou la tecla Ctrl o Alt</translation>
<translation id="8448729345478502352">Amplia o redueix els elements de la pantalla</translation>
@@ -4934,6 +4948,7 @@ Deseu el fitxer de clau en una ubicació segura. El necessitareu per crear versi
<translation id="8468750959626135884">Desbloqueja <ph name="DEVICE_TYPE" /> amb el telèfon Android.</translation>
<translation id="8470028084415844044">Per tenir totes les teves contrasenyes en tots els dispositius, activa la sincronització.</translation>
<translation id="8470513973197838199">Contrasenyes desades per a <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Per fer servir aquesta targeta en tots els teus dispositius, desa-la al Compte de Google</translation>
<translation id="8472623782143987204">recolzat per maquinari</translation>
<translation id="8473863474539038330">Adreces i més</translation>
<translation id="8475313423285172237">Un altre programa de l'ordinador ha afegit una extensió que pot canviar el funcionament de Chrome.</translation>
@@ -5009,7 +5024,6 @@ Deseu el fitxer de clau en una ubicació segura. El necessitareu per crear versi
<translation id="8598453409908276158">S'ha bloquejat l'accés al connector de fora de la zona de proves</translation>
<translation id="8601206103050338563">Autenticació de client WWW de TLS</translation>
<translation id="8602851771975208551">Un altre programa de l'ordinador ha afegit una aplicació que pot canviar el funcionament de Chrome.</translation>
-<translation id="8604763363205185560">Ajuda a millorar Chrome i la seva seguretat</translation>
<translation id="8605428685123651449">Memòria SQLite</translation>
<translation id="8606726445206553943">Utilitzar els dispositius MIDI</translation>
<translation id="8609465669617005112">Desplaça cap amunt</translation>
@@ -5185,6 +5199,7 @@ Deseu el fitxer de clau en una ubicació segura. El necessitareu per crear versi
<translation id="8846141544112579928">S'està cercant el teclat...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">En connectar els dispositius, acceptes que Chromebook pugui fer el següent:</translation>
+<translation id="8850251000316748990">Mostra'n més...</translation>
<translation id="8859057652521303089">Seleccioneu el vostre idioma:</translation>
<translation id="8859174528519900719">Submarc: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Full de càlcul d'Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_cs.xtb b/chromium/chrome/app/resources/generated_resources_cs.xtb
index d0dd9b10d27..f5ab69b2f1f 100644
--- a/chromium/chrome/app/resources/generated_resources_cs.xtb
+++ b/chromium/chrome/app/resources/generated_resources_cs.xtb
@@ -518,7 +518,6 @@ Na následující obrazovce prosím zadejte zpětnou vazbu, která nám problém
<translation id="175772926354468439">Aktivovat motiv</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Zobrazit v Internetovém obchodu Chrome</translation>
-<translation id="1761588866118490543">Hlasový model</translation>
<translation id="176193854664720708">Snímač otisků prstů je součástí vypínače. Zlehka se ho dotkněte jakýmkoli prstem.</translation>
<translation id="1763046204212875858">Vytvořit zástupce aplikací</translation>
<translation id="1763108912552529023">Pokračovat v průzkumu</translation>
@@ -815,6 +814,8 @@ Na následující obrazovce prosím zadejte zpětnou vazbu, která nám problém
<translation id="220792432208469595">Odesílat údaje o využití a diagnostice. Toto zařízení aktuálně automaticky odesílá do Googlu diagnostické údaje a údaje o zařízení a využití. Tyto údaje nám pomohou se zvyšováním stability systému a aplikací a dalšími vylepšeními. Některá souhrnná data budou moci využít také naši partneři, např. vývojáři aplikací pro Android. Toto nastavení je vyžadováno vlastníkem. Pokud máte zapnuté dodatečné nastavení Aktivita na webu a v aplikacích, mohou se tato data ukládat do vašeho účtu Google. <ph name="BEGIN_LINK1" />Další informace<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Archiv ZIP</translation>
<translation id="220858061631308971">Zadejte prosím v zařízení <ph name="DEVICE_NAME" /> tento kód PIN:</translation>
+<translation id="2213140827792212876">Odstranit sdílení</translation>
+<translation id="2214018885812055163">Sdílené složky</translation>
<translation id="2214884991347062907">Nesprávné heslo, zkuste to znovu</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 řádek není zobrazen&gt;}few{&lt;<ph name="NUMBER_OF_LINES" /> řádky nejsou zobrazeny&gt;}many{&lt;<ph name="NUMBER_OF_LINES" /> řádku není zobrazeno&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> řádků není zobrazeno&gt;}}</translation>
<translation id="2217501013957346740">Vytvořte jméno –</translation>
@@ -1014,6 +1015,7 @@ Na následující obrazovce prosím zadejte zpětnou vazbu, která nám problém
<translation id="2501173422421700905">Přidržený certifikát</translation>
<translation id="2501797496290880632">Zadejte zkratku</translation>
<translation id="2502441965851148920">Automatické aktualizace jsou aktivní. Ruční aktualizace byly administrátorem deaktivovány.</translation>
+<translation id="2505127913256479918">Tento dozorovaný účet bude brzy odstraněn</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Obrazovka #}few{Obrazovka #}many{Obrazovka #}other{Obrazovka #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> z <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Účet Obchodu Google Play</translation>
@@ -1374,6 +1376,7 @@ Zpráva serveru: <ph name="SERVER_MSG" /></translation>
<translation id="304747341537320566">Moduly převodu textu na řeč</translation>
<translation id="3053013834507634016">Použití klíče certifikátu</translation>
<translation id="3057861065630527966">Zálohovat fotky a videa</translation>
+<translation id="3058498974290601450">Synchronizaci můžete kdykoliv zapnout v nastavení</translation>
<translation id="3060379269883947824">Zapnout poslech vybraného textu</translation>
<translation id="3061707000357573562">Služba oprav</translation>
<translation id="3065041951436100775">Zpětná vazba k ukončení procesu karty</translation>
@@ -1563,6 +1566,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="337920581046691015">Bude nainstalována aplikace <ph name="PRODUCT_NAME" /></translation>
<translation id="3380365263193509176">Neznámá chyba</translation>
<translation id="3382073616108123819">Jejda, systému se nepodařilo určit identifikátory tohoto zařízení.</translation>
+<translation id="3382086682569279540">Účet, který spravujete, bude brzy odstraněn</translation>
<translation id="3382200254148930874">Ukončování dohledu...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Oddělovač</translation>
@@ -1743,8 +1747,8 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="3636096452488277381">Ahoj uživateli <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> %, zbývá <ph name="TIME" /></translation>
<translation id="3637682276779847508">Pokud správně nezadáte klíč k odemknutí kódu PIN, bude SIM karta natrvalo deaktivována</translation>
-<translation id="363863692969456324">Odstraňte překlepy pomocí vylepšené kontroly pravopisu</translation>
<translation id="3640214691812501263">Přidat aplikaci <ph name="EXTENSION_NAME" /> pro uživatele <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Naučte Asistenta rozpoznávat váš hlas</translation>
<translation id="3644896802912593514">Šířka</translation>
<translation id="3645372836428131288">Lehce prst natočte, aby se zaznamenala jiná část otisku.</translation>
<translation id="3648348069317717750">Bylo rozpoznáno zařízení <ph name="USB_DEVICE_NAME" /></translation>
@@ -2143,7 +2147,6 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="4244238649050961491">Najít další aplikace pro dotyková pera</translation>
<translation id="424546999567421758">Bylo zjištěno vysoké využití disku</translation>
<translation id="424726838611654458">Vždy otevřít v aplikaci Adobe Reader</translation>
-<translation id="4247330672018280062">Text, který zadáte do textových polí, se odešle do Googlu</translation>
<translation id="4247901771970415646">Synchronizace na účet <ph name="USERNAME" /> se nezdařila</translation>
<translation id="4249248555939881673">Čeká se na připojení k síti...</translation>
<translation id="4249373718504745892">Přístup této stránky k vaší webové kameře a mikrofonu je zablokován.</translation>
@@ -2485,6 +2488,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="4821935166599369261">&amp;Profilování povoleno</translation>
<translation id="4823484602432206655">Čtení a změna nastavení zařízení a uživatele</translation>
<translation id="4823651846660089135">Zařízení je pouze pro čtení</translation>
+<translation id="4824958205181053313">Zrušit synchronizaci?</translation>
<translation id="4827675678516992122">Nelze se připojit</translation>
<translation id="4828937774870308359">Opačné</translation>
<translation id="4829768588131278040">Nastavit PIN</translation>
@@ -2866,6 +2870,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="5374359983950678924">Změnit obrázek</translation>
<translation id="5376169624176189338">Kliknutím se vrátíte zpět, přidržením se zobrazí historie</translation>
<translation id="5376931455988532197">Soubor je příliš velký</translation>
+<translation id="5377594097385838788">Anonymní</translation>
<translation id="537813040452600081">Stránky, které otevřete v tomto okně, nebudou uvedeny v historii prohlížeče a po odhlášení v počítači nezanechají žádné stopy, např. soubory cookie. Zachovány nezůstanou ani stažené soubory či vytvořené záložky.</translation>
<translation id="5379140238605961210">Blokovat přístup k mikrofonu i nadále</translation>
<translation id="5379268888377976432">Vrátit smazání</translation>
@@ -2887,6 +2892,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="5414566801737831689">Číst ikony navštívených webových stránek</translation>
<translation id="5417312524372586921">Motivy prohlížeče</translation>
<translation id="5419294236999569767">Systémový čas</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Určuje ostrost textu a obrázků</translation>
<translation id="5422221874247253874">Přístupový bod</translation>
<translation id="5422781158178868512">Je nám líto, externí paměťové zařízení nelze rozpoznat.</translation>
@@ -2907,6 +2913,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="5434065355175441495">Šifrování PKCS #1 RSA</translation>
<translation id="5436492226391861498">Čeká se na tunel proxy...</translation>
<translation id="5436510242972373446">Vyhledat <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Uložte teď své soubory a vytvořte nový účet.</translation>
<translation id="5438224778284622050">Smazat offline soubory?</translation>
<translation id="544083962418256601">Vytvořit zástupce…</translation>
<translation id="5442228125690314719">Při vytváření obrazu disku došlo k chybě. Zkuste to znovu.</translation>
@@ -3280,6 +3287,8 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="5965661248935608907">Také řídí, která stránka se zobrazí, když kliknete na tlačítko Domovská stránka nebo budete vyhledávat v omniboxu.</translation>
<translation id="5971037678316050792">Ovládání stavu a párování adaptéru Bluetooth</translation>
<translation id="5972017421290582825">Spravovat nastavení MIDI...</translation>
+<translation id="597235323114979258">Zobrazit další cíle</translation>
+<translation id="5972666587303800813">Prázdná služba</translation>
<translation id="5972708806901999743">Přesunout nahoru</translation>
<translation id="5972826969634861500">Spustit <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Procento nabití baterie</translation>
@@ -3650,6 +3659,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="6527303717912515753">Sdílet</translation>
<translation id="6528513914570774834">Povolit ostatním uživatelům tohoto zařízení používat tuto síť</translation>
<translation id="652948702951888897">Historie Chromu</translation>
+<translation id="6530186581263215931">Tato nastavení jsou vynucena administrátorem</translation>
<translation id="653019979737152879">Synchronizace souboru <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Ponechat nebezpečný soubor</translation>
<translation id="6532101170117367231">Uložit na Disk Google</translation>
@@ -3968,7 +3978,6 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="7018275672629230621">Číst a upravovat vaši historii procházení</translation>
<translation id="7019805045859631636">Rychle</translation>
<translation id="7022562585984256452">Domovská stránka byla nastavena.</translation>
-<translation id="702384510542929236">Anonymně odesílá část informací o systému a obsahu stránek do Googlu</translation>
<translation id="7025190659207909717">Správa mobilních datových služeb</translation>
<translation id="7027125358315426638">Název databáze:</translation>
<translation id="7029809446516969842">Hesla</translation>
@@ -4148,6 +4157,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="7289225569524511578">Spustit aplikaci tapety</translation>
<translation id="7290242001003353852">Přihlašovací služba hostovaná doménou <ph name="SAML_DOMAIN" /> požádala o přístup ke kameře.</translation>
<translation id="7290594223351252791">Potvrzení registrace</translation>
+<translation id="7292696521213967957">Informace k ladění Asistenta</translation>
<translation id="7295662345261934369">Sdílet s dalšími uživateli</translation>
<translation id="729583233778673644">Povolit šifrování AES a RC4. Použití této možnosti zvyšuje riziko, protože šifry RC4 nejsou bezpečné.</translation>
<translation id="7296774163727375165">Smluvní podmínky domény <ph name="DOMAIN" /></translation>
@@ -4248,7 +4258,6 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="7456847797759667638">Otevřít umístění...</translation>
<translation id="7461924472993315131">Připnout</translation>
<translation id="7463006580194749499">Přidat osobu</translation>
-<translation id="7464902436585505072">Hlasový model „Ok Google“</translation>
<translation id="7465778193084373987">Adresa URL pro odvolání certifikátu Netscape</translation>
<translation id="7469894403370665791">Automaticky připojit k této síti</translation>
<translation id="747114903913869239">Chyba: Nelze dekódovat rozšíření</translation>
@@ -4276,6 +4285,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="7496511874649569424">Aplikace <ph name="LINUX_APP_NAME" /> a k ní přidružená data budou z tohoto zařízení odstraněna.</translation>
<translation id="7497215489070763236">Certifikát CA serveru</translation>
<translation id="7497981768003291373">Nemáte žádné nedávno zaznamenané textové protokoly WebRTC.</translation>
+<translation id="7502199377020483660">Chcete-li tyto karty používat na všech svých zařízeních, uložte si je do účtu Google</translation>
<translation id="7502658306369382406">Adresa IPv6</translation>
<translation id="7503191893372251637">Certifikát typu Netscape</translation>
<translation id="7503821294401948377">Nelze načíst ikonu „<ph name="ICON" />“ pro akci prohlížeče.</translation>
@@ -4371,6 +4381,7 @@ Pokud nezměníte výchozí nastavení, uživatel <ph name="USER_DISPLAY_NAME" /
<translation id="7663719505383602579">Příjemce: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Nepodporované zařízení Bluetooth: <ph name="DEVICE_NAME" />.</translation>
<translation id="7665369617277396874">Přidat účet</translation>
+<translation id="7667248760110172428">Externí úložiště</translation>
<translation id="7671130400130574146">Použít systémové záhlaví a okraje okna</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> na stránce <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Odesílat hlasové údaje do Googlu, aby bylo možné diktovat do libovolného textového pole.</translation>
@@ -4574,6 +4585,7 @@ V zařízení se systémem Chrome OS můžete aktivovat funkce ladění, abyste
<translation id="7930294771522048157">Zde se budou zobrazovat uložené platební metody</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> sdílí vaši obrazovku a zvuk.</translation>
<translation id="7931318309563332511">Neznámé</translation>
+<translation id="7932969338829957666">Sdílené složky jsou v Linuxu k dispozici v adresáři <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Zapnout zvuk webu}few{Zapnout zvuk webů}many{Zapnout zvuk webů}other{Zapnout zvuk webů}}</translation>
<translation id="7934414805353235750">Web <ph name="URL" /> chce přehrát chráněný obsah. Google ověří identitu vašeho zařízení.</translation>
<translation id="793531125873261495">Při stahování virtuálního počítače došlo k chybě. Zkuste to znovu.</translation>
@@ -4665,6 +4677,7 @@ Svůj soubor klíče uchovávejte na bezpečném místě. Budete jej potřebovat
<translation id="8049705080247101012">Rozšíření <ph name="EXTENSION_NAME" /> bylo společností Google označeno jako škodlivé a jeho instalace byla zablokována</translation>
<translation id="8049913480579063185">Název rozšíření</translation>
<translation id="8050038245906040378">Komerční podepisování kódu Microsoft</translation>
+<translation id="8052887694493382350">Tento soubor je určen pro počítač se softwarem Windows. S vaším zařízením se systémem Chrome OS není kompatibilní. <ph name="BEGIN_LINK_HELP" />Další informace<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Soubory PKCS #12</translation>
<translation id="8053390638574070785">Načíst tuto stránku znovu</translation>
<translation id="8054517699425078995">Tento typ souboru může poškodit vaše zařízení. Chcete soubor <ph name="FILE_NAME" /> přesto zachovat?</translation>
@@ -4907,6 +4920,7 @@ Svůj soubor klíče uchovávejte na bezpečném místě. Budete jej potřebovat
<translation id="8438566539970814960">Vylepšit vyhledávání a procházení</translation>
<translation id="8439506636278576865">Nabízet překlad stránek v tomto jazyce</translation>
<translation id="8440630305826533614">Aplikace pro Linux</translation>
+<translation id="8443338615972234259">Vytvořte dozorovanému uživateli nový účet.</translation>
<translation id="8446884382197647889">Další informace</translation>
<translation id="8447409163267621480">Zahrňte klávesu Ctrl nebo Alt</translation>
<translation id="8448729345478502352">Umožňuje zvětšit nebo zmenšit položky na obrazovce</translation>
@@ -4931,6 +4945,7 @@ Svůj soubor klíče uchovávejte na bezpečném místě. Budete jej potřebovat
<translation id="8468750959626135884">Odemykejte <ph name="DEVICE_TYPE" /> pomocí telefonu Android.</translation>
<translation id="8470028084415844044">Chcete-li mít všechna hesla na všech svých zařízeních, zapněte synchronizaci.</translation>
<translation id="8470513973197838199">Uložená hesla z webu <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Chcete-li tuto kartu používat na všech svých zařízeních, uložte si ji do účtu Google.</translation>
<translation id="8472623782143987204">hardwarová</translation>
<translation id="8473863474539038330">Adresy a další</translation>
<translation id="8475313423285172237">Jiný program ve vašem počítači nainstaloval rozšíření, které může měnit funkce Chromu.</translation>
@@ -5006,7 +5021,6 @@ Svůj soubor klíče uchovávejte na bezpečném místě. Budete jej potřebovat
<translation id="8598453409908276158">Pluginu byl zablokován přístup mimo izolovaný prostor</translation>
<translation id="8601206103050338563">Ověření TLS webového klienta</translation>
<translation id="8602851771975208551">Jiný program ve vašem počítači nainstaloval aplikaci, která může měnit funkce Chromu.</translation>
-<translation id="8604763363205185560">Pomozte s vylepšováním Chromu a jeho zabezpečení</translation>
<translation id="8605428685123651449">Paměť SQLite</translation>
<translation id="8606726445206553943">Používat vaše zařízení MIDI</translation>
<translation id="8609465669617005112">Posunout nahoru</translation>
@@ -5182,6 +5196,7 @@ Svůj soubor klíče uchovávejte na bezpečném místě. Budete jej potřebovat
<translation id="8846141544112579928">Vyhledávání klávesnice...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Propojením zařízení souhlasíte, že Chromebook může:</translation>
+<translation id="8850251000316748990">Zobrazit další...</translation>
<translation id="8859057652521303089">Vyberte jazyk:</translation>
<translation id="8859174528519900719">Podrámec: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Tabulka aplikace Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_da.xtb b/chromium/chrome/app/resources/generated_resources_da.xtb
index 94fa93a0f02..653254084f5 100644
--- a/chromium/chrome/app/resources/generated_resources_da.xtb
+++ b/chromium/chrome/app/resources/generated_resources_da.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">Aktivér tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Se i Chrome Webshop</translation>
-<translation id="1761588866118490543">Stemmemodel</translation>
<translation id="176193854664720708">Fingeraftrykslæseren sidder i afbryderknappen. Tryk let på den med en finger.</translation>
<translation id="1763046204212875858">Opret programgenveje</translation>
<translation id="1763108912552529023">Udforsk videre</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">Send brugs- og diagnosticeringsdata. Denne enhed sender i øjeblikket automatisk diagnosticerings- og enhedsdata samt data om brug af apps til Google. Dataene bruges til forbedring af bl.a. systemets og appens stabilitet. Visse samlede data hjælper også Google-apps og -partnere, f.eks. Android-udviklere. Denne indstilling håndhæves af ejeren. Hvis indstillingen til yderligere web- og appaktivitet er aktiveret, gemmes disse data muligvis på din Google-konto. <ph name="BEGIN_LINK1" />Få flere oplysninger<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip-arkiv</translation>
<translation id="220858061631308971">Angiv denne pinkode på "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Fjern deling</translation>
+<translation id="2214018885812055163">Delte mapper</translation>
<translation id="2214884991347062907">Adgangskoden er forkert. Prøv igen.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 linje vises ikke&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> linje vise ikke&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> linjer vises ikke&gt;}}</translation>
<translation id="2217501013957346740">Opret et navn –</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">Certifikat venter</translation>
<translation id="2501797496290880632">Angiv en genvej</translation>
<translation id="2502441965851148920">Automatiske opdateringer er aktiveret. Manuelle opdateringer er deaktiveret af din administrator.</translation>
+<translation id="2505127913256479918">Denne administrerede konto fjernes snart</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Skærm #}one{Skærm #}other{Skærm #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> af <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Butik-konto</translation>
@@ -1373,6 +1375,7 @@
<translation id="304747341537320566">Oplæsningsmaskiner</translation>
<translation id="3053013834507634016">Brug af certifikatnøgle</translation>
<translation id="3057861065630527966">Sikkerhedskopiér dine billeder og videoer</translation>
+<translation id="3058498974290601450">Du kan til enhver tid aktivere synkronisering i indstillingerne</translation>
<translation id="3060379269883947824">Aktivér Tekstoplæsning</translation>
<translation id="3061707000357573562">Tjeneste til programrettelse</translation>
<translation id="3065041951436100775">Feedback i tilfælde, hvor fanen døde.</translation>
@@ -1564,6 +1567,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> bliver installeret.</translation>
<translation id="3380365263193509176">Ukendt fejl</translation>
<translation id="3382073616108123819">Ups! Systemet kunne ikke bestemme enhedsidentifikatorer til denne enhed.</translation>
+<translation id="3382086682569279540">Den konto, du administrerer, fjernes snart</translation>
<translation id="3382200254148930874">Afslutter tilsyn…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Separator</translation>
@@ -1663,7 +1667,7 @@
<translation id="3518985090088779359">Acceptér og fortsæt</translation>
<translation id="351952459507671940">Føj til ny gruppe</translation>
<translation id="3523642406908660543">Spørg om tilladelse, når et website ønsker at anvende et plugin til at få adgang til din computer (anbefales)</translation>
-<translation id="3526034519184079374">Websitets data kan hverken læses eller ændres</translation>
+<translation id="3526034519184079374">Kan hverken læse eller ændre websitedata</translation>
<translation id="3527085408025491307">Mappe</translation>
<translation id="3527276236624876118">En administreret bruger ved navn <ph name="USER_DISPLAY_NAME" /> er blevet oprettet.</translation>
<translation id="3528033729920178817">Denne side sporer din placering.</translation>
@@ -1674,7 +1678,7 @@
<translation id="3534879087479077042">Hvad er en administreret bruger?</translation>
<translation id="3538066758857505094">Der opstod en fejl under installationen af Linux. Prøv igen.</translation>
<translation id="354060433403403521">Vekselstrømsadapter</translation>
-<translation id="354068948465830244">Den kan læse og ændre websitedata</translation>
+<translation id="354068948465830244">Udvidelsen kan læse og ændre websitedata</translation>
<translation id="3543393733900874979">Opdateringen mislykkedes (fejl: <ph name="ERROR_NUMBER" />)</translation>
<translation id="3543597750097719865">X9.62 ECDSA-signatur med SHA-512</translation>
<translation id="3544879808695557954">Brugernavn (valgfrit)</translation>
@@ -1744,8 +1748,8 @@
<translation id="3636096452488277381">Goddag <ph name="USER_GIVEN_NAME" /></translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> % - <ph name="TIME" /> tilbage</translation>
<translation id="3637682276779847508">Dit SIM-kort deaktiveres permanent, hvis du ikke kan angive den korrekte nøgle til oplåsning af pinkode.</translation>
-<translation id="363863692969456324">Ret stavefejl med forbedret stavekontrol</translation>
<translation id="3640214691812501263">Vil du tilføje "<ph name="EXTENSION_NAME" />" for <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Lær din assistent at genkende din stemme</translation>
<translation id="3644896802912593514">Bredde</translation>
<translation id="3645372836428131288">Flyt fingeren en smule for at registrere en anden del af fingeraftrykket.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> blev registreret</translation>
@@ -2145,7 +2149,6 @@ Vil du starte <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="4244238649050961491">Find flere apps til styluspenne</translation>
<translation id="424546999567421758">Et højt forbrug af diskplads er blevet registreret</translation>
<translation id="424726838611654458">Altid åben i Adobe Reader</translation>
-<translation id="4247330672018280062">Den tekst, du angiver i tekstfelter, sendes til Google</translation>
<translation id="4247901771970415646">Der kan ikke synkroniseres med <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Venter på netværksforbindelse...</translation>
<translation id="4249373718504745892">Denne sides adgang til dit kamera og din mikrofon er blevet blokeret.</translation>
@@ -2487,6 +2490,7 @@ Vil du starte <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="4821935166599369261">&amp;Profilering aktiveret</translation>
<translation id="4823484602432206655">Læs og rediger bruger- og enhedsindstillinger</translation>
<translation id="4823651846660089135">Enheden er skrivebeskyttet</translation>
+<translation id="4824958205181053313">Vil du annullere synkroniseringen?</translation>
<translation id="4827675678516992122">Der kunne ikke oprettes forbindelse</translation>
<translation id="4828937774870308359">Australsk</translation>
<translation id="4829768588131278040">Konfiguration af pinkode</translation>
@@ -2869,6 +2873,7 @@ Vil du starte <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="5374359983950678924">Skift billede</translation>
<translation id="5376169624176189338">Klik for at gå tilbage. Hold knappen inde for at se historikken.</translation>
<translation id="5376931455988532197">Filen er for stor</translation>
+<translation id="5377594097385838788">Inkognito</translation>
<translation id="537813040452600081">De sider, du ser i dette vindue, vises ikke i browserhistorikken, og de efterlader ikke andre spor som f.eks. cookies på computeren, når du logger ud. De filer, du downloader, og bogmærker, du opretter, bliver ikke gemt.</translation>
<translation id="5379140238605961210">Fortsæt blokeringen af mikrofonadgang</translation>
<translation id="5379268888377976432">Fortryd sletning</translation>
@@ -2890,6 +2895,7 @@ Vil du starte <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="5414566801737831689">Læs ikonerne for de websites, du besøger</translation>
<translation id="5417312524372586921">Browsertemaer</translation>
<translation id="5419294236999569767">Systemklokkeslæt</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Bestemmer skarpheden af tekst og billeder</translation>
<translation id="5422221874247253874">Adgangspunkt</translation>
<translation id="5422781158178868512">Vi beklager, men din eksterne lagringsenhed kunne ikke genkendes.</translation>
@@ -2910,6 +2916,7 @@ Vil du starte <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="5434065355175441495">PKCS #1 RSA-kryptering</translation>
<translation id="5436492226391861498">Venter på proxytunnel...</translation>
<translation id="5436510242972373446">Søg på <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Gem dine filer, og opret en ny konto nu.</translation>
<translation id="5438224778284622050">Vil du slette offlinefiler?</translation>
<translation id="544083962418256601">Opret genveje...</translation>
<translation id="5442228125690314719">Der opstod en fejl under oprettelsen af diskbilledet. Prøv igen.</translation>
@@ -3283,6 +3290,8 @@ Vil du starte <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="5965661248935608907">Den styrer også, hvilken side der vises, når du klikker på knappen Startside eller søger via omnifeltet.</translation>
<translation id="5971037678316050792">Kontrollere tilstand og parring af Bluetooth-adaptere</translation>
<translation id="5972017421290582825">Administrer MIDI-indstillinger...</translation>
+<translation id="597235323114979258">Se flere destinationer</translation>
+<translation id="5972666587303800813">Selvkørende tjeneste</translation>
<translation id="5972708806901999743">Flyt til toppen</translation>
<translation id="5972826969634861500">Start <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Procentdel for batteriopladning</translation>
@@ -3654,6 +3663,7 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="6527303717912515753">Del</translation>
<translation id="6528513914570774834">Giv andre brugere af denne enhed tilladelse til at bruge dette netværk</translation>
<translation id="652948702951888897">Chrome-historik</translation>
+<translation id="6530186581263215931">Disse indstillinger håndhæves af din administrator</translation>
<translation id="653019979737152879">Synkroniserer <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Behold farlig fil</translation>
<translation id="6532101170117367231">Gem på Google Drev</translation>
@@ -3972,7 +3982,6 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="7018275672629230621">Læs og rediger din browserhistorik</translation>
<translation id="7019805045859631636">Hurtig</translation>
<translation id="7022562585984256452">Din startside er blevet konfigureret.</translation>
-<translation id="702384510542929236">Sender nogle systemoplysninger og noget sideindhold anonymt til Google</translation>
<translation id="7025190659207909717">Administration af mobildatatjeneste</translation>
<translation id="7027125358315426638">Databasenavn:</translation>
<translation id="7029809446516969842">Adgangskoder</translation>
@@ -4002,7 +4011,7 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="706626672220389329">Der opstod en fejl ved anvendelse af deling. Den angivne deling anvendes allerede.</translation>
<translation id="7066944511817949584">Kunne ikke oprette forbindelse til "<ph name="DEVICE_NAME" />".</translation>
<translation id="7067725467529581407">Vis aldrig dette igen.</translation>
-<translation id="7070484045139057854">Den kan læse og ændre websitedata</translation>
+<translation id="7070484045139057854">Udvidelsen kan læse og ændre websitedata</translation>
<translation id="7072010813301522126">Navn på genvejen</translation>
<translation id="707392107419594760">Vælg dit tastatur:</translation>
<translation id="7075513071073410194">PKCS #1 MD5 med RSA-kryptering</translation>
@@ -4152,6 +4161,7 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="7289225569524511578">Åbn baggrundsappen</translation>
<translation id="7290242001003353852">Denne logintjeneste, som hostes af <ph name="SAML_DOMAIN" />, har adgang til dit kamera.</translation>
<translation id="7290594223351252791">Bekræft registrering</translation>
+<translation id="7292696521213967957">Oplysninger til fejlretning i Assistent</translation>
<translation id="7295662345261934369">Del med andre</translation>
<translation id="729583233778673644">Tillad AES- og RC4-kryptering. Du løber en større risiko, hvis du vælger denne mulighed, da RC4-krypteringsalgoritmerne er usikre.</translation>
<translation id="7296774163727375165">Vilkår for <ph name="DOMAIN" /></translation>
@@ -4252,7 +4262,6 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="7456847797759667638">Åbn placering...</translation>
<translation id="7461924472993315131">Fastgør</translation>
<translation id="7463006580194749499">Tilføj person</translation>
-<translation id="7464902436585505072">Stemmemodellen "Ok Google"</translation>
<translation id="7465778193084373987">Webadresse for tilbagekaldelse af Netscape-certifikat</translation>
<translation id="7469894403370665791">Opret automatisk forbindelse til dette netværk</translation>
<translation id="747114903913869239">Fejl: Udvidelsen kunne ikke afkodes</translation>
@@ -4280,6 +4289,7 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> og de tilknyttede data fjernes fra denne enhed.</translation>
<translation id="7497215489070763236">Serverens CA-certifikat</translation>
<translation id="7497981768003291373">Du har ingen nyligt registrerede WebRTC-tekstlogfiler.</translation>
+<translation id="7502199377020483660">Hvis du vil bruge disse kort på alle dine enheder, skal du gemme dem på din Google-konto</translation>
<translation id="7502658306369382406">IPv6-adresse</translation>
<translation id="7503191893372251637">Netscape-certifikatstype</translation>
<translation id="7503821294401948377">Ikonet '<ph name="ICON" />' for browserhandling kunne ikke indlæses.</translation>
@@ -4377,6 +4387,7 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="7663719505383602579">Modtager: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Ikke-understøttet Bluetooth-enhed: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Tilføj konto</translation>
+<translation id="7667248760110172428">Ekstern lagerplads</translation>
<translation id="7671130400130574146">Brug systemets titellinje og rammer</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> på <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Send din stemme til Google, så du kan diktere i ethvert tekstfelt.</translation>
@@ -4447,7 +4458,7 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="7782102568078991263">Ikke flere forslag fra Google</translation>
<translation id="778330624322499012"><ph name="PLUGIN_NAME" /> kunne ikke indlæses</translation>
<translation id="7784067724422331729">Sikkerhedsindstillingerne på din computer blokerede denne fil.</translation>
-<translation id="7784796923038949829">Websitets data kan hverken læses eller ændres</translation>
+<translation id="7784796923038949829">Kan hverken læse eller ændre websitedata</translation>
<translation id="778480864305029524">Hvis du vil bruge Øjeblikkelig netdeling, skal du aktivere notifikationer om Google Play-tjenester.</translation>
<translation id="7786207843293321886">Afslut gæstesession</translation>
<translation id="7786889348652477777">&amp;Genindlæs app</translation>
@@ -4579,6 +4590,7 @@ slettes permanent, når den administrerede bruger fjernes. Besøgte websites og
<translation id="7930294771522048157">Her kan du se dine gemte betalingsmetoder</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> deler din skærm og lyd.</translation>
<translation id="7931318309563332511">ukendt</translation>
+<translation id="7932969338829957666">Delte mapper er tilgængelige i Linux på <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Slå lyden til på website}one{Slå lyden til på website}other{Slå lyden til på websites}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> vil afspille beskyttet indhold. Din enheds identitet bekræftes af Google.</translation>
<translation id="793531125873261495">Der opstod en fejl under forsøget på at downloade den virtuelle maskine. Prøv igen.</translation>
@@ -4670,6 +4682,7 @@ Opbevar din nøglefil på et sikkert sted. Du skal bruge den til at oprette nye
<translation id="8049705080247101012">Google har markeret "<ph name="EXTENSION_NAME" />" som skadelig, og installationen blev forhindret</translation>
<translation id="8049913480579063185">Udvidelsesnavn</translation>
<translation id="8050038245906040378">Microsoft-signering af kommerciel kode</translation>
+<translation id="8052887694493382350">Denne fil er udviklet til en pc, der kører Windows-software. Den er ikke kompatibel med din enhed, som kører Chrome OS. <ph name="BEGIN_LINK_HELP" />Få flere oplysninger<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12-filer</translation>
<translation id="8053390638574070785">Genindlæs denne side</translation>
<translation id="8054517699425078995">Denne type fil kan beskadige din enhed. Vil du beholde <ph name="FILE_NAME" /> alligevel?</translation>
@@ -4913,6 +4926,7 @@ Opbevar din nøglefil på et sikkert sted. Du skal bruge den til at oprette nye
<translation id="8438566539970814960">Gør søgninger og browsing endnu bedre</translation>
<translation id="8439506636278576865">Tilbyd at oversætte sider på dette sprog</translation>
<translation id="8440630305826533614">Linux-apps</translation>
+<translation id="8443338615972234259">Opret en ny konto for din administrerede bruger nu.</translation>
<translation id="8446884382197647889">Få flere oplysninger</translation>
<translation id="8447409163267621480">Skal indeholde enten Ctrl eller Alt</translation>
<translation id="8448729345478502352">Gør elementer på skærmen mindre eller større</translation>
@@ -4937,6 +4951,7 @@ Opbevar din nøglefil på et sikkert sted. Du skal bruge den til at oprette nye
<translation id="8468750959626135884">Lås din <ph name="DEVICE_TYPE" /> op med din Android-telefon.</translation>
<translation id="8470028084415844044">Aktivér synkronisering for at få alle dine adgangskoder på alle dine enheder.</translation>
<translation id="8470513973197838199">Gemte adgangskoder til <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Hvis du vil bruge dette kort på alle dine enheder, skal du gemme det på din Google-konto</translation>
<translation id="8472623782143987204">hardwarebaseret</translation>
<translation id="8473863474539038330">Adresser og meget mere</translation>
<translation id="8475313423285172237">Et andet program på din computer tilføjede en udvidelse, der kan ændre den måde, hvorpå Chrome fungerer.</translation>
@@ -5012,7 +5027,6 @@ Opbevar din nøglefil på et sikkert sted. Du skal bruge den til at oprette nye
<translation id="8598453409908276158">Plugin, der ikke er gemt i sandbox, blev blokeret</translation>
<translation id="8601206103050338563">TLS WWW-klientgodkendelse</translation>
<translation id="8602851771975208551">Et andet program på din computer tilføjede en app, der kan ændre den måde, hvorpå Chrome fungerer.</translation>
-<translation id="8604763363205185560">Hjælp med at forbedre Chrome og dets sikkerhed</translation>
<translation id="8605428685123651449">SQLite-hukommelse</translation>
<translation id="8606726445206553943">Brug dine MIDI-enheder</translation>
<translation id="8609465669617005112">Flyt op</translation>
@@ -5189,6 +5203,7 @@ Opbevar din nøglefil på et sikkert sted. Du skal bruge den til at oprette nye
<translation id="8846141544112579928">Søger efter tastatur...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Når du opretter forbindelse mellem dine enheder, accepterer du, at din Chromebook kan gøre følgende:</translation>
+<translation id="8850251000316748990">Se flere...</translation>
<translation id="8859057652521303089">Vælg dit sprog:</translation>
<translation id="8859174528519900719">Underramme: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel-regneark</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_de.xtb b/chromium/chrome/app/resources/generated_resources_de.xtb
index d38e1932449..122f5d3d5f7 100644
--- a/chromium/chrome/app/resources/generated_resources_de.xtb
+++ b/chromium/chrome/app/resources/generated_resources_de.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">Design aktivieren</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Im Chrome Web Store ansehen</translation>
-<translation id="1761588866118490543">Sprachmodell</translation>
<translation id="176193854664720708">Der Fingerabdrucksensor ist in die Ein-/Aus-Taste integriert. Berühren Sie diese leicht mit dem Finger.</translation>
<translation id="1763046204212875858">App-Verknüpfungen erstellen</translation>
<translation id="1763108912552529023">Weiter erkunden</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">Sie haben die Möglichkeit, Nutzungs- und Diagnosedaten zu senden. Dieses Gerät sendet momentan automatisch Diagnose- sowie Geräte- und App-Nutzungsdaten an Google. Die Daten helfen unter anderem dabei, die Stabilität des Systems und der Apps zu verbessern. Einige aggregierte Daten sind auch für Apps und Partner von Google, beispielsweise Android-Entwickler, nützlich. Diese Einstellung wird vom Inhaber erzwungen. Wenn zusätzlich die Einstellung "Web- &amp; App-Aktivitäten" aktiviert ist, werden diese Daten eventuell in Ihrem Google-Konto gespeichert. <ph name="BEGIN_LINK1" />Weitere Informationen<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">ZIP-Archiv</translation>
<translation id="220858061631308971">Geben Sie diesen PIN-Code bitte auf "<ph name="DEVICE_NAME" /> " ein:</translation>
+<translation id="2213140827792212876">Freigabe beenden</translation>
+<translation id="2214018885812055163">Freigegebene Ordner</translation>
<translation id="2214884991347062907">Falsches Passwort. Versuchen Sie es noch einmal.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 Zeile wird nicht angezeigt&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> Zeilen werden nicht angezeigt&gt;}}</translation>
<translation id="2217501013957346740">Namen erstellen –</translation>
@@ -1011,6 +1012,7 @@
<translation id="2501173422421700905">Zertifikat vorübergehend ausgesetzt</translation>
<translation id="2501797496290880632">Tastenkombination eingeben</translation>
<translation id="2502441965851148920">Automatische Updates sind aktiviert. Manuelle Updates sind durch Ihren Administrator deaktiviert.</translation>
+<translation id="2505127913256479918">Dieses gemeinsam verwaltete Konto wird bald entfernt</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Bildschirm #}other{Bildschirm #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> von <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Store-Konto</translation>
@@ -1370,6 +1372,7 @@ Servernachricht: <ph name="SERVER_MSG" /></translation>
<translation id="304747341537320566">Sprach-Engines</translation>
<translation id="3053013834507634016">Zertifikatschlüsselverwendung</translation>
<translation id="3057861065630527966">Fotos und Videos sichern</translation>
+<translation id="3058498974290601450">Sie können die Synchronisierung jederzeit in den Einstellungen aktivieren</translation>
<translation id="3060379269883947824">Vorlesen aktivieren</translation>
<translation id="3061707000357573562">Patchdienst</translation>
<translation id="3065041951436100775">Feedback zur Tab-Beendigung</translation>
@@ -1561,11 +1564,12 @@ Servernachricht: <ph name="SERVER_MSG" /></translation>
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> wird installiert.</translation>
<translation id="3380365263193509176">Unbekannter Fehler</translation>
<translation id="3382073616108123819">Hoppla! Das System konnte die Geräte-IDs für dieses Gerät nicht ermitteln.</translation>
+<translation id="3382086682569279540">Das von Ihnen verwaltete Konto wird bald entfernt</translation>
<translation id="3382200254148930874">Elternaufsicht wird beendet…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Trennzeichen</translation>
<translation id="3389312115541230716">Klicken Sie mit der rechten Maustaste auf das Symbol <ph name="SMALL_PRODUCT_LOGO" /> in der Taskleiste</translation>
-<translation id="3393352139658145068">Assistant wird aktiviert, sobald jemand "Ok Google" sagt. Damit dein Akku geschont wird, wird "Ok Google" nur aktiviert, wenn Ihr Gerät an eine Stromquelle angeschlossen ist.</translation>
+<translation id="3393352139658145068">Assistant wird aktiviert, sobald jemand "Ok Google" sagt. Damit der Akku geschont wird, wird "Ok Google" nur aktiviert, wenn Ihr Gerät an eine Stromquelle angeschlossen ist.</translation>
<translation id="3396800784455899911">Wenn Sie auf die Schaltfläche "Akzeptieren und fortfahren" klicken, willigen Sie damit in die oben für diese Google-Dienste beschriebene Verarbeitung Ihrer Daten ein.</translation>
<translation id="3399432415385675819">Benachrichtigungen werden deaktiviert</translation>
<translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />, <ph name="TIME_LEFT" /></translation>
@@ -1741,8 +1745,8 @@ Servernachricht: <ph name="SERVER_MSG" /></translation>
<translation id="3636096452488277381">Hallo <ph name="USER_GIVEN_NAME" /></translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> % – Restzeit: <ph name="TIME" /></translation>
<translation id="3637682276779847508">Ihre SIM-Karte wird dauerhaft deaktiviert, wenn Sie nicht den korrekten PUK eingeben.</translation>
-<translation id="363863692969456324">Rechtschreibfehler mit der erweiterten Rechtschreibprüfung korrigieren</translation>
<translation id="3640214691812501263">"<ph name="EXTENSION_NAME" />" für <ph name="USER_NAME" /> hinzufügen?</translation>
+<translation id="3640613767643722554">Assistant beibringen, Ihre Stimme zu erkennen</translation>
<translation id="3644896802912593514">Breite</translation>
<translation id="3645372836428131288">Bewegen Sie Ihren Finger etwas, um einen anderen Teil des Fingerabdrucks zu erfassen.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> erkannt</translation>
@@ -1760,7 +1764,7 @@ Servernachricht: <ph name="SERVER_MSG" /></translation>
<translation id="3664511988987167893">Erweiterungssymbol</translation>
<translation id="3665589677786828986">Chrome hat festgestellt, dass einige Ihrer Einstellungen von einem anderen Programm manipuliert wurden, und hat sie auf die ursprünglichen Standardwerte zurückgesetzt.</translation>
<translation id="3668570675727296296">Spracheinstellungen</translation>
-<translation id="3668801437375206837">Damit Bluetooth-Probleme besser diagnostiziert werden können, haben Google-Mitarbeiter die Möglichkeit, Feedbackberichte durch zusätzliche Bluetooth-Protokolle zu ergänzen. Wenn diese Option ausgewählt ist, enthält Ihr Bericht btsnoop- und HCI-Protokolle der aktuellen Sitzung. Personenbezogene Daten werden dabei so gut wie möglich entfernt. Nur die Administratoren der entsprechenden Chrome OS-Produktgruppe in Listnr haben Zugriff auf die Protokolle. Diese werden nach 90 Tagen dauerhaft gelöscht.</translation>
+<translation id="3668801437375206837">Damit Bluetooth-Probleme besser diagnostiziert werden können, haben Google-Mitarbeiter die Möglichkeit, Feedbackberichte durch zusätzliche Bluetooth-Protokolle zu ergänzen. Wenn diese Option ausgewählt ist, enthält Ihr Bericht btsnoop- und HCI-Protokolle der aktuellen Sitzung. Personenidentifizierbare Informationen werden dabei so gut wie möglich entfernt. Nur die Administratoren der entsprechenden Chrome OS-Produktgruppe in Listnr haben Zugriff auf die Protokolle. Diese werden nach 90 Tagen dauerhaft gelöscht.</translation>
<translation id="3668823961463113931">Handler</translation>
<translation id="3670229581627177274">Bluetooth aktivieren</translation>
<translation id="3672681487849735243">Ein werkseitiger Fehler wurde festgestellt.</translation>
@@ -2142,7 +2146,6 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="4244238649050961491">Mehr Eingabestift-Apps suchen</translation>
<translation id="424546999567421758">Hohe Festplattennutzung festgestellt</translation>
<translation id="424726838611654458">Immer mit Adobe Reader öffnen</translation>
-<translation id="4247330672018280062">Wenn Sie etwas in ein Textfeld eingeben, wird dieser Text an Google gesendet</translation>
<translation id="4247901771970415646">Synchronisierung mit <ph name="USERNAME" /> nicht möglich</translation>
<translation id="4249248555939881673">Auf Netzwerkverbindung warten...</translation>
<translation id="4249373718504745892">Diese Seite darf nicht auf die Kamera und das Mikrofon zugreifen.</translation>
@@ -2484,6 +2487,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="4821935166599369261">&amp;Profilerstellung aktiviert</translation>
<translation id="4823484602432206655">Nutzer- und Geräteeinstellungen lesen und ändern</translation>
<translation id="4823651846660089135">Gerät ist schreibgeschützt</translation>
+<translation id="4824958205181053313">Synchronisierung abbrechen?</translation>
<translation id="4827675678516992122">Verbindung nicht möglich</translation>
<translation id="4828937774870308359">Australisch</translation>
<translation id="4829768588131278040">PIN erstellen</translation>
@@ -2866,6 +2870,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="5374359983950678924">Bild ändern</translation>
<translation id="5376169624176189338">Klicken, um zurückzugehen. Gedrückt halten, um den Verlauf aufzurufen</translation>
<translation id="5376931455988532197">Datei zu groß</translation>
+<translation id="5377594097385838788">Inkognito</translation>
<translation id="537813040452600081">In diesem Fenster aufgerufene Seiten erscheinen nicht im Browserverlauf und hinterlassen auch keine anderweitigen Spuren wie Cookies auf dem Computer, nachdem Sie sich abgemeldet haben. Ihre Lesezeichen und Ihre heruntergeladenen Dateien bleiben nicht erhalten.</translation>
<translation id="5379140238605961210">Zugriff auf das Mikrofon weiter blockieren</translation>
<translation id="5379268888377976432">Löschen rückgängig machen</translation>
@@ -2887,6 +2892,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="5414566801737831689">Die Symbole der von Ihnen besuchten Websites lesen</translation>
<translation id="5417312524372586921">Browserdesigns</translation>
<translation id="5419294236999569767">Systemzeit</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Bestimmt die Schärfe von Text und Bildern</translation>
<translation id="5422221874247253874">Zugangspunkt</translation>
<translation id="5422781158178868512">Ihr externes Speichergerät wurde nicht erkannt.</translation>
@@ -2907,6 +2913,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="5434065355175441495">PKCS #1 RSA-Verschlüsselung</translation>
<translation id="5436492226391861498">Warten auf Proxy-Tunnel...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> durchsuchen:</translation>
+<translation id="543806387003274181">Bitte speichern Sie jetzt Ihre Dateien und erstellen Sie ein neues Konto.</translation>
<translation id="5438224778284622050">Offlinedateien löschen?</translation>
<translation id="544083962418256601">Verknüpfungen erstellen...</translation>
<translation id="5442228125690314719">Fehler beim Erstellen des Datenträgerabbilds. Bitte versuchen Sie es noch einmal.</translation>
@@ -3246,7 +3253,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="5916664084637901428">An</translation>
<translation id="59174027418879706">Aktiviert</translation>
<translation id="5920543303088087579">Die Möglichkeit einer Verbindung zu diesem Netzwerk wurde von Ihrem Administrator deaktiviert</translation>
-<translation id="5920835625712313205">Chrome OS-Systemabbild-Writer</translation>
+<translation id="5920835625712313205">Chrome OS-System-Image-Writer</translation>
<translation id="5924047253200400718">Hilfe aufrufen, <ph name="SCANNING_STATUS" /></translation>
<translation id="5924527146239595929">Nehmen Sie ein neues Foto auf oder wählen Sie ein vorhandenes Foto oder Symbol aus.
<ph name="LINE_BREAK" />
@@ -3280,6 +3287,8 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="5965661248935608907">Die Erweiterung legt auch fest, welche Seite bei der Suche über die Omnibox angezeigt wird oder wenn Sie auf die Schaltfläche "Startseite" klicken.</translation>
<translation id="5971037678316050792">Bluetooth-Adapterstatus und -Kopplung steuern</translation>
<translation id="5972017421290582825">MIDI-Einstellungen verwalten...</translation>
+<translation id="597235323114979258">Weitere Ziele anzeigen</translation>
+<translation id="5972666587303800813">Managementfreier Dienst</translation>
<translation id="5972708806901999743">An den Anfang verschieben</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> starten</translation>
<translation id="5975792506968920132">Akkustand in %</translation>
@@ -3650,6 +3659,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="6527303717912515753">Teilen</translation>
<translation id="6528513914570774834">Anderen Nutzern des Geräts erlauben, dieses Netzwerk zu verwenden</translation>
<translation id="652948702951888897">Chrome-Verlauf</translation>
+<translation id="6530186581263215931">Diese Einstellungen werden von Ihrem Administrator erzwungen</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> wird synchronisiert...</translation>
<translation id="6531282281159901044">Schädliche Datei beibehalten</translation>
<translation id="6532101170117367231">In Google Drive speichern</translation>
@@ -3968,7 +3978,6 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="7018275672629230621">Ihren Browserverlauf lesen und ändern</translation>
<translation id="7019805045859631636">Schnell</translation>
<translation id="7022562585984256452">Ihre Startseite wurde eingerichtet.</translation>
-<translation id="702384510542929236">Einige Systeminformationen und Seiteninhalte werden anonym an Google gesendet</translation>
<translation id="7025190659207909717">Verwaltung mobiler Datendienste</translation>
<translation id="7027125358315426638">Datenbankname:</translation>
<translation id="7029809446516969842">Passwörter</translation>
@@ -4148,6 +4157,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="7289225569524511578">Hintergrund-App öffnen</translation>
<translation id="7290242001003353852">Dieser Anmeldedienst wird von <ph name="SAML_DOMAIN" /> gehostet und greift auf Ihre Kamera zu.</translation>
<translation id="7290594223351252791">Registrierung bestätigen</translation>
+<translation id="7292696521213967957">Informationen für die Fehlerbehebung bei Assistant</translation>
<translation id="7295662345261934369">Mit anderen teilen</translation>
<translation id="729583233778673644">AES- und RC4-Verschlüsselung erlauben. Mit dieser Option ist ein höheres Risiko verbunden, da RC4-Verschlüsselungen nicht sicher sind.</translation>
<translation id="7296774163727375165">Nutzungsbedingungen für <ph name="DOMAIN" /></translation>
@@ -4248,7 +4258,6 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="7456847797759667638">Adresse öffnen...</translation>
<translation id="7461924472993315131">Anpinnen</translation>
<translation id="7463006580194749499">Person hinzufügen</translation>
-<translation id="7464902436585505072">"Ok Google"-Sprachmodell</translation>
<translation id="7465778193084373987">URL zum Zurückrufen von Netscape-Zertifikaten</translation>
<translation id="7469894403370665791">Verbindung zu diesem Netzwerk automatisch herstellen</translation>
<translation id="747114903913869239">Fehler: Erweiterung kann nicht entschlüsselt werden.</translation>
@@ -4276,6 +4285,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> und die damit verknüpften Daten werden von diesem Gerät entfernt.</translation>
<translation id="7497215489070763236">CA-Serverzertifikat</translation>
<translation id="7497981768003291373">Es sind keine kürzlich erfassten WebRTC-Textprotokolle vorhanden.</translation>
+<translation id="7502199377020483660">Wenn Sie diese Karten auf allen Ihren Geräten verwenden möchten, speichern Sie sie in Ihrem Google-Konto</translation>
<translation id="7502658306369382406">IPv6-Adresse</translation>
<translation id="7503191893372251637">Netscape-Zertifikatstyp</translation>
<translation id="7503821294401948377">Symbol "<ph name="ICON" />" konnte nicht für Browseraktion geladen werden.</translation>
@@ -4373,6 +4383,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="7663719505383602579">Empfänger: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Nicht unterstütztes Bluetooth-Gerät: "<ph name="DEVICE_NAME" />"</translation>
<translation id="7665369617277396874">Konto hinzufügen</translation>
+<translation id="7667248760110172428">Externer Speicher</translation>
<translation id="7671130400130574146">Titelleiste und Ränder des Systems verwenden</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> auf <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Ihre Spracheingaben werden an Google gesendet, damit sie in das entsprechende Textfeld eingetragen werden können.</translation>
@@ -4576,6 +4587,7 @@ Möchten Sie <ph name="CONTROL_PANEL_APPLET_NAME" /> starten?</translation>
<translation id="7930294771522048157">Gespeicherte Zahlungsmethoden werden hier angezeigt</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> teilt Bildschirm und Audio.</translation>
<translation id="7931318309563332511">Unbekannt</translation>
+<translation id="7932969338829957666">Freigegebene Ordner sind auf Linux-Geräten unter <ph name="BASE_DIR" /> verfügbar.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Stummschaltung für Website aufheben}other{Stummschaltung für Websites aufheben}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> möchte geschützte Inhalte abspielen. Die Identität Ihres Geräts wird von Google geprüft.</translation>
<translation id="793531125873261495">Fehler beim Herunterladen der virtuellen Maschine. Bitte versuchen Sie es noch einmal.</translation>
@@ -4667,6 +4679,7 @@ Speichern Sie Ihre Schlüsseldatei an einem sicheren Ort. Sie benötigen die Dat
<translation id="8049705080247101012">"<ph name="EXTENSION_NAME" />" wurde von Google als schädlich eingestuft und die Installation wurde blockiert</translation>
<translation id="8049913480579063185">Name der Erweiterung</translation>
<translation id="8050038245906040378">Kommerzielle Microsoft-Codesignatur</translation>
+<translation id="8052887694493382350">Diese Datei wurde für Computer mit Windows-Software entwickelt. Sie ist nicht mit Ihrem Chrome OS-Gerät kompatibel. <ph name="BEGIN_LINK_HELP" />Weitere Informationen<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12-Dateien</translation>
<translation id="8053390638574070785">Diese Seite neu laden</translation>
<translation id="8054517699425078995">Dateien dieses Typs können Schäden auf Ihrem Gerät verursachen. Möchten Sie <ph name="FILE_NAME" /> dennoch behalten?</translation>
@@ -4910,6 +4923,7 @@ Andere Personen mit langsamen Verbindungen sehen Ihre Inhalte möglicherweise ni
<translation id="8438566539970814960">Suchanfragen und das Surfen verbessern</translation>
<translation id="8439506636278576865">Übersetzung für Seiten in dieser Sprache anbieten</translation>
<translation id="8440630305826533614">Linux-Apps</translation>
+<translation id="8443338615972234259">Bitte erstellen Sie jetzt ein neues Konto für Ihren betreuten Nutzer.</translation>
<translation id="8446884382197647889">Weitere Informationen</translation>
<translation id="8447409163267621480">Entweder Strg oder Alt integrieren</translation>
<translation id="8448729345478502352">Die Elemente auf dem Bildschirm vergrößern oder verkleinern</translation>
@@ -4934,6 +4948,7 @@ Andere Personen mit langsamen Verbindungen sehen Ihre Inhalte möglicherweise ni
<translation id="8468750959626135884">Entsperren Sie Ihr <ph name="DEVICE_TYPE" /> mit Ihrem Android-Smartphone.</translation>
<translation id="8470028084415844044">Wenn Sie Ihre Passwörter auf allen Ihren Geräten verfügbar haben möchten, aktivieren Sie die Synchronisierung.</translation>
<translation id="8470513973197838199">Gespeicherte Passwörter für <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Wenn Sie diese Karte auf allen Ihren Geräten verwenden möchten, speichern Sie sie in Ihrem Google-Konto</translation>
<translation id="8472623782143987204">Hardwaregestützt</translation>
<translation id="8473863474539038330">AutoFill-Einstellungen</translation>
<translation id="8475313423285172237">Ein anderes Programm auf Ihrem Computer hat eine Erweiterung hinzugefügt, die sich möglicherweise auf die Funktionsweise von Chrome auswirkt.</translation>
@@ -5009,7 +5024,6 @@ Andere Personen mit langsamen Verbindungen sehen Ihre Inhalte möglicherweise ni
<translation id="8598453409908276158">Plug-in ohne Sandbox blockiert</translation>
<translation id="8601206103050338563">TLS-WWW-Client-Authentifizierung</translation>
<translation id="8602851771975208551">Ein anderes Programm auf Ihrem Computer hat eine App hinzugefügt, die sich möglicherweise auf die Funktionsweise von Chrome auswirkt.</translation>
-<translation id="8604763363205185560">Helfen Sie, die Sicherheit und Funktionen von Chrome zu verbessern</translation>
<translation id="8605428685123651449">SQLite-Speicher</translation>
<translation id="8606726445206553943">Ihre MIDI-Geräte verwenden</translation>
<translation id="8609465669617005112">Nach oben</translation>
@@ -5185,6 +5199,7 @@ Andere Personen mit langsamen Verbindungen sehen Ihre Inhalte möglicherweise ni
<translation id="8846141544112579928">Suche nach Tastatur läuft...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Durch das Verbinden Ihrer Geräte erlauben Sie Ihrem Chromebook Folgendes:</translation>
+<translation id="8850251000316748990">Mehr…</translation>
<translation id="8859057652521303089">Sprache auswählen:</translation>
<translation id="8859174528519900719">Subframe: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel-Tabelle</translation>
@@ -5194,7 +5209,7 @@ Andere Personen mit langsamen Verbindungen sehen Ihre Inhalte möglicherweise ni
<translation id="8870318296973696995">Startseite</translation>
<translation id="8870413625673593573">Kürzlich geschlossen</translation>
<translation id="8871551568777368300">Vom Administrator angeheftet</translation>
-<translation id="8871696467337989339">Sie verwenden eine nicht unterstützte Befehlszeilenmarkierung: <ph name="BAD_FLAG" />. Dadurch werden Stabilität und Sicherheit beeinträchtigt.</translation>
+<translation id="8871696467337989339">Sie verwenden ein nicht unterstütztes Befehlszeilen-Flag: <ph name="BAD_FLAG" />. Dadurch werden Stabilität und Sicherheit beeinträchtigt.</translation>
<translation id="8871974300055371298">Inhaltseinstellungen</translation>
<translation id="8872155268274985541">Ungültige Manifestdatei für externes Kiosk-Update gefunden. Die Kiosk-App konnte nicht aktualisiert werden. Bitte entfernen Sie den USB-Stick.</translation>
<translation id="8874184842967597500">Nicht verbunden</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_el.xtb b/chromium/chrome/app/resources/generated_resources_el.xtb
index 4fb4f9613e3..afe8af1fa03 100644
--- a/chromium/chrome/app/resources/generated_resources_el.xtb
+++ b/chromium/chrome/app/resources/generated_resources_el.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Ενεργοποίηση θέματος</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Προβολή στο Chrome Web Store</translation>
-<translation id="1761588866118490543">Φωνητικό μοντέλο</translation>
<translation id="176193854664720708">Ο αισθητήρας δακτυλικού αποτυπώματος βρίσκεται στο κουμπί λειτουργίας. Αγγίξτε το ελαφρώς με οποιοδήποτε δάκτυλο.</translation>
<translation id="1763046204212875858">Δημιουργία συντομεύσεων εφαρμογής</translation>
<translation id="1763108912552529023">Συνεχίστε την εξερεύνηση</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Αποστολή δεδομένων χρήσης και διαγνωστικών. Επί του παρόντος, αυτή η συσκευή στέλνει αυτόματα διαγνωστικά δεδομένα, δεδομένα συσκευής και χρήσης εφαρμογών στην Google. Με αυτόν τον τρόπο βελτιώνεται η σταθερότητα του συστήματος και των εφαρμογών και παρέχονται επιπλέον βελτιώσεις. Ορισμένα συγκεντρωτικά δεδομένα θα βοηθήσουν επίσης τις εφαρμογές και τους συνεργάτες της Google, όπως τους προγραμματιστές Android. Αυτή η ρύθμιση επιβάλλεται από τον κάτοχο. Εάν η ρύθμιση της πρόσθετης Δραστηριότητας ιστού και εφαρμογών είναι ενεργοποιημένη, αυτά τα δεδομένα μπορεί να αποθηκευτούν στον Λογαριασμό σας Google. <ph name="BEGIN_LINK1" />Μάθετε περισσότερα<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Αρχείο Zip</translation>
<translation id="220858061631308971">Εισαγάγετε αυτόν τον κωδικό PIN στη συσκευή "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Κατάργηση κοινοποίησης</translation>
+<translation id="2214018885812055163">Κοινόχρηστοι φάκελοι</translation>
<translation id="2214884991347062907">Λανθασμένος κωδικός πρόσβασης, δοκιμάστε ξανά</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 γραμμή δεν εμφανίζεται&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> γραμμές δεν εμφανίζονται&gt;}}</translation>
<translation id="2217501013957346740">Δημιουργία ονόματος -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Πιστοποιητικό σε αναμονή</translation>
<translation id="2501797496290880632">Πληκτρολογήστε μια συντόμευση</translation>
<translation id="2502441965851148920">Έχουν ενεργοποιηθεί οι αυτόματες ενημερώσεις. Οι μη αυτόματες ενημερώσεις έχουν απενεργοποιηθεί από τον διαχειριστή σας.</translation>
+<translation id="2505127913256479918">Αυτός ο εποπτευόμενος λογαριασμός θα καταργηθεί σύντομα</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Οθόνη #}other{Οθόνη #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> από <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Λογαριασμός Google Play Store</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Μηχανές ομιλίας</translation>
<translation id="3053013834507634016">Χρήση κλειδιού πιστοποιητικού</translation>
<translation id="3057861065630527966">Δημιουργία αντιγράφων ασφαλείας για τις φωτογραφίες και τα βίντεό σας</translation>
+<translation id="3058498974290601450">Μπορείτε να ενεργοποιήσετε τον συγχρονισμό ανά πάσα στιγμή στις ρυθμίσεις</translation>
<translation id="3060379269883947824">Ενεργοποίηση λειτουργίας "Επιλέξτε για εκφώνηση"</translation>
<translation id="3061707000357573562">Υπηρεσία ενημέρωσης κώδικα</translation>
<translation id="3065041951436100775">Σχόλια για απότομο κλείσιμο καρτέλας.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015">Θα γίνει εγκατάσταση του <ph name="PRODUCT_NAME" />.</translation>
<translation id="3380365263193509176">Άγνωστο σφάλμα</translation>
<translation id="3382073616108123819">Ωχ! Το σύστημα δεν κατάφερε να προσδιορίσει αναγνωριστικά συσκευής για αυτήν τη συσκευή.</translation>
+<translation id="3382086682569279540">Ο λογαριασμός που διαχειρίζεστε θα καταργηθεί σύντομα</translation>
<translation id="3382200254148930874">Διακοπή επίβλεψης…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Διαχωριστικό</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Γεια σας, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - Απομένει <ph name="TIME" /></translation>
<translation id="3637682276779847508">Η κάρτα SIM θα απενεργοποιηθεί οριστικά αν δεν καταφέρετε να πληκτρολογήσετε το σωστό κλειδί ξεκλειδώματος PIN.</translation>
-<translation id="363863692969456324">Διορθώστε τα ορθογραφικά λάθη με τον βελτιωμένο ορθογραφικό έλεγχο</translation>
<translation id="3640214691812501263">Προσθήκη "<ph name="EXTENSION_NAME" />" για <ph name="USER_NAME" />;</translation>
+<translation id="3640613767643722554">Εκπαιδεύστε τον Βοηθό ώστε να αναγνωρίζει τη φωνή σας</translation>
<translation id="3644896802912593514">Πλάτος</translation>
<translation id="3645372836428131288">Μετακινήστε ελαφρώς για να αποτυπώσετε ένα διαφορετικό τμήμα του δακτυλικού αποτυπώματος.</translation>
<translation id="3648348069317717750">Εντοπίστηκε συσκευή <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Εύρεση περισσότερων εφαρμογών γραφίδας</translation>
<translation id="424546999567421758">Εντοπίστηκε υψηλή χρήση του δίσκου</translation>
<translation id="424726838611654458">Να είναι πάντα ανοικτό στο Adobe Reader</translation>
-<translation id="4247330672018280062">Το κείμενο που πληκτρολογείτε σε πεδία κειμένου θα αποσταλεί στην Google</translation>
<translation id="4247901771970415646">Δεν είναι δυνατός ο συγχρονισμός με τον χρήστη <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Αναμονή για σύνδεση δικτύου…</translation>
<translation id="4249373718504745892">Αποκλείστηκε η πρόσβαση αυτής της σελίδας στην κάμερα και στο μικρόφωνό σας.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">Ενεργοποιημένη &amp;δυνατότητα δημιουργίας προφίλ</translation>
<translation id="4823484602432206655">Ανάγνωση και αλλαγή των ρυθμίσεων χρήστη και συσκευής</translation>
<translation id="4823651846660089135">Η συσκευή είναι μόνο για ανάγνωση</translation>
+<translation id="4824958205181053313">Ακύρωση συγχρονισμού;</translation>
<translation id="4827675678516992122">Αδυναμία σύνδεσης</translation>
<translation id="4828937774870308359">Αυστραλός</translation>
<translation id="4829768588131278040">Ρύθμιση PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Αλλαγή εικόνας</translation>
<translation id="5376169624176189338">Κάντε κλικ για για να πάτε πίσω, κρατήστε το κουμπί πατημένο για να δείτε το ιστορικό</translation>
<translation id="5376931455988532197">Το αρχείο είναι πολύ μεγάλο</translation>
+<translation id="5377594097385838788">Ανώνυμη περιήγηση</translation>
<translation id="537813040452600081">Οι σελίδες που προβάλλονται σε αυτό το παράθυρο δεν θα εμφανίζονται στο ιστορικό του προγράμματος περιήγησης και δεν θα αφήνουν άλλα ίχνη, όπως cookie, στον υπολογιστή μετά την έξοδό σας. Τα αρχεία που κατεβάζετε και οι σελιδοδείκτες που δημιουργείτε δεν θα φυλάσσονται.</translation>
<translation id="5379140238605961210">Να συνεχιστεί ο αποκλεισμός πρόσβασης στο μικρόφωνο</translation>
<translation id="5379268888377976432">Αναίρεση διαγραφής</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Ανάγνωση εικονιδίων των ιστοτόπων που επισκέπτεστε</translation>
<translation id="5417312524372586921">Θέματα προγράμματος περιήγησης</translation>
<translation id="5419294236999569767">Ώρα συστήματος</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Καθορίζει την οξύτητα του κειμένου και των εικόνων</translation>
<translation id="5422221874247253874">Σημείο πρόσβασης</translation>
<translation id="5422781158178868512">Λυπούμαστε, δεν ήταν δυνατή η αναγνώριση της εξωτερικής συσκευής αποθήκευσης.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 Κρυπτογράφηση RSA</translation>
<translation id="5436492226391861498">Αναμονή για διοχέτευση διακομιστή μεσολάβησης...</translation>
<translation id="5436510242972373446">Αναζήτηση <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Αποθηκεύστε τα αρχεία σας και δημιουργήστε έναν νέο λογαριασμό τώρα.</translation>
<translation id="5438224778284622050">Διαγραφή αρχείων εκτός σύνδεσης;</translation>
<translation id="544083962418256601">Δημιουργία συντομεύσεων…</translation>
<translation id="5442228125690314719">Σφάλμα δημιουργίας εικόνας δίσκου. Δοκιμάστε ξανά.</translation>
@@ -3286,6 +3293,8 @@
<translation id="5965661248935608907">Επίσης, ελέγχει τη σελίδα που εμφανίζεται όταν κάνετε κλικ στο κουμπί αρχικής σελίδας ή όταν κάνετε αναζήτηση από το κύριο πλαίσιο.</translation>
<translation id="5971037678316050792">Έλεγχος κατάστασης προσαρμογέα Bluetooth και σύζευξη</translation>
<translation id="5972017421290582825">Διαχείριση ρυθμίσεων MIDI…</translation>
+<translation id="597235323114979258">Δείτε περισσότερους προορισμούς</translation>
+<translation id="5972666587303800813">Υπηρεσία No-op</translation>
<translation id="5972708806901999743">Μετακίνηση στην κορυφή</translation>
<translation id="5972826969634861500">Έναρξη του <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Ποσοστό φόρτισης μπαταρίας</translation>
@@ -3656,6 +3665,7 @@
<translation id="6527303717912515753">Κοινοποίηση</translation>
<translation id="6528513914570774834">Επιτρέψτε σε άλλους χρήστες της συσκευής να χρησιμοποιούν αυτό το δίκτυο</translation>
<translation id="652948702951888897">Ιστορικό Chrome</translation>
+<translation id="6530186581263215931">Αυτές οι ρυθμίσεις εφαρμόζονται από τον διαχειριστή σας</translation>
<translation id="653019979737152879">Συγχρονισμός <ph name="FILE_NAME" />…</translation>
<translation id="6531282281159901044">Διατήρηση επικίνδυνου αρχείου</translation>
<translation id="6532101170117367231">Αποθήκευση στο Google Drive</translation>
@@ -3974,7 +3984,6 @@
<translation id="7018275672629230621">Ανάγνωση και αλλαγή του ιστορικού περιήγησης</translation>
<translation id="7019805045859631636">Γρήγορα</translation>
<translation id="7022562585984256452">Η αρχική σελίδα σας έχει οριστεί.</translation>
-<translation id="702384510542929236">Αποστέλλει ανώνυμα ορισμένες πληροφορίες συστήματος και περιεχόμενο σελίδων στην Google</translation>
<translation id="7025190659207909717">Διαχείριση υπηρεσιών δεδομένων κινητής συσκευής</translation>
<translation id="7027125358315426638">Όνομα βάσης δεδομένων:</translation>
<translation id="7029809446516969842">Κωδικοί πρόσβασης</translation>
@@ -4154,6 +4163,7 @@
<translation id="7289225569524511578">Ανοίξτε την εφαρμογή ταπετσαρίας</translation>
<translation id="7290242001003353852">Η υπηρεσία σύνδεσης που φιλοξενείται από τον τομέα <ph name="SAML_DOMAIN" />, έχει πρόσβαση στην κάμερά σας.</translation>
<translation id="7290594223351252791">Επιβεβαίωση εγγραφής</translation>
+<translation id="7292696521213967957">Πληροφορίες για τον εντοπισμό σφαλμάτων του Βοηθού</translation>
<translation id="7295662345261934369">Κοινοποίηση σε άλλα άτομα</translation>
<translation id="729583233778673644">Να επιτρέπεται η κρυπτογράφηση AES και RC4. Η χρήση αυτής της επιλογής αυξάνει τον κίνδυνο, επειδή η κρυπτογράφηση RC4 δεν είναι ασφαλής.</translation>
<translation id="7296774163727375165">Όροι <ph name="DOMAIN" /></translation>
@@ -4254,7 +4264,6 @@
<translation id="7456847797759667638">Άνοιγμα Τοποθεσίας...</translation>
<translation id="7461924472993315131">Καρφίτσωμα</translation>
<translation id="7463006580194749499">Προσθήκη χρήστη</translation>
-<translation id="7464902436585505072">Φωνητικό μοντέλο "Ok Google"</translation>
<translation id="7465778193084373987">URL ανάκλησης πιστοποιητικού Netscape</translation>
<translation id="7469894403370665791">Αυτόματη σύνδεση σε αυτό το δίκτυο</translation>
<translation id="747114903913869239">Σφάλμα: Δεν είναι δυνατή η αποκωδικοποίηση της επέκτασης</translation>
@@ -4282,6 +4291,7 @@
<translation id="7496511874649569424">Η εφαρμογή <ph name="LINUX_APP_NAME" /> και τα δεδομένα που σχετίζονται με αυτή θα καταργηθούν από αυτήν τη συσκευή.</translation>
<translation id="7497215489070763236">Πιστοποιητικό διακομιστή CA</translation>
<translation id="7497981768003291373">Δεν υπάρχουν αρχεία καταγραφής κειμένου WebRTC τα οποία λήφθηκαν πρόσφατα.</translation>
+<translation id="7502199377020483660">Για να χρησιμοποιήσετε αυτές τις κάρτες σε όλες τις συσκευές σας, αποθηκεύστε τις στον Λογαριασμό σας Google</translation>
<translation id="7502658306369382406">Διεύθυνση IPv6</translation>
<translation id="7503191893372251637">Τύπος πιστοποιητικού Netscape</translation>
<translation id="7503821294401948377">Δεν ήταν δυνατή η φόρτωση του εικονιδίου "<ph name="ICON" />" για ενέργεια προγράμματος περιήγησης.</translation>
@@ -4379,6 +4389,7 @@
<translation id="7663719505383602579">Δέκτης: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Μη υποστηριζόμενη συσκευή Bluetooth: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Προσθήκη λογαριασμού</translation>
+<translation id="7667248760110172428">Εξωτερικός αποθηκευτικός χώρος</translation>
<translation id="7671130400130574146">Χρήση της γραμμής τίτλου συστήματος και των περιγραμμάτων.</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> στη σελίδα <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Αποστολή της φωνής σας στην Google, ώστε να επιτρέπεται η υπαγόρευση σε οποιοδήποτε πεδίο κειμένου.</translation>
@@ -4582,6 +4593,7 @@
<translation id="7930294771522048157">Οι αποθηκευμένοι τρόποι πληρωμής θα εμφανίζονται εδώ</translation>
<translation id="79312157130859720">Η εφαρμογή <ph name="APP_NAME" /> μοιράζεται την οθόνη και τον ήχο σας.</translation>
<translation id="7931318309563332511">Άγνωστη</translation>
+<translation id="7932969338829957666">Οι κοινόχρηστοι φάκελοι είναι διαθέσιμοι στο Linux στη θέση <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Κατάργηση σίγασης ιστοτόπου}other{Κατάργηση σίγασης ιστοτόπων}}</translation>
<translation id="7934414805353235750">Το <ph name="URL" /> θέλει να κάνει αναπαραγωγή προστατευόμενου περιεχομένου. η ταυτότητα της συσκευής σας θα επικυρωθεί από την Google.</translation>
<translation id="793531125873261495">Σφάλμα λήψης του εικονικού μηχανήματος. Δοκιμάστε ξανά.</translation>
@@ -4673,6 +4685,7 @@
<translation id="8049705080247101012">Η Google έχει επισημάνει την επέκταση "<ph name="EXTENSION_NAME" />" ως κακόβουλη και η εγκατάσταση έχει εμποδιστεί</translation>
<translation id="8049913480579063185">Όνομα επέκτασης</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">Αυτό το αρχείο έχει σχεδιαστεί για έναν υπολογιστή ο οποίος χρησιμοποιεί λογισμικό Windows. Δεν είναι συμβατό με τη συσκευή σας η οποία χρησιμοποιεί Chrome OS. <ph name="BEGIN_LINK_HELP" />Μάθετε περισσότερα<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Αρχεία PKCS #12</translation>
<translation id="8053390638574070785">Επαναφόρτωση αυτής της σελίδας</translation>
<translation id="8054517699425078995">Αυτός ο τύπος αρχείου ενδέχεται να βλάψει τη συσκευή σας. Θέλετε να διατηρήσετε το αρχείο <ph name="FILE_NAME" /> ούτως ή άλλως;</translation>
@@ -4916,6 +4929,7 @@
<translation id="8438566539970814960">Βελτιώστε τις αναζητήσεις και την περιήγηση</translation>
<translation id="8439506636278576865">Ερώτηση για τη μετάφραση σελίδων σε αυτήν τη γλώσσα</translation>
<translation id="8440630305826533614">Εφαρμογές Linux</translation>
+<translation id="8443338615972234259">Δημιουργήστε έναν νέο λογαριασμό για τον εποπτευόμενο χρήστη τώρα.</translation>
<translation id="8446884382197647889">Μάθετε περισσότερα</translation>
<translation id="8447409163267621480">Συμπερίληψη είτε του Ctrl είτε του Alt</translation>
<translation id="8448729345478502352">Κάντε τα στοιχεία στην οθόνη μικρότερα ή μεγαλύτερα</translation>
@@ -4940,6 +4954,7 @@
<translation id="8468750959626135884">Ξεκλειδώστε τη συσκευή <ph name="DEVICE_TYPE" /> με το τηλέφωνο Android που χρησιμοποιείτε.</translation>
<translation id="8470028084415844044">Για να έχετε όλους τους κωδικούς πρόσβασης σε όλες τις συσκευές σας, ενεργοποιήστε τον συγχρονισμό.</translation>
<translation id="8470513973197838199">Αποθηκευμένοι κωδικοί πρόσβασης για το <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Για να χρησιμοποιήσετε αυτήν την κάρτα σε όλες τις συσκευές σας, αποθηκεύστε τη στον Λογαριασμό σας Google</translation>
<translation id="8472623782143987204">υποστηριζόμενο από υλικό</translation>
<translation id="8473863474539038330">Διευθύνσεις και άλλα</translation>
<translation id="8475313423285172237">Κάποιο άλλο πρόγραμμα στον υπολογιστή σας πρόσθεσε μια επέκταση, η οποία ενδέχεται να αλλάξει τον τρόπο λειτουργίας του Chrome.</translation>
@@ -5015,7 +5030,6 @@
<translation id="8598453409908276158">Η προσθήκη εκτός περιβάλλοντος δοκιμών αποκλείστηκε</translation>
<translation id="8601206103050338563">Έλεγχος ταυτότητας πελάτη TLS WWW</translation>
<translation id="8602851771975208551">Κάποιο άλλο πρόγραμμα στον υπολογιστή σας πρόσθεσε μια εφαρμογή, η οποία ενδέχεται να αλλάξει τον τρόπο λειτουργίας του Chrome.</translation>
-<translation id="8604763363205185560">Συμβάλλετε στη βελτίωση του Chrome και της ασφάλειάς του</translation>
<translation id="8605428685123651449">Μνήμη SQLite</translation>
<translation id="8606726445206553943">Χρήση των συσκευών σας MIDI</translation>
<translation id="8609465669617005112">Μετακίνηση προς τα επάνω</translation>
@@ -5189,6 +5203,7 @@
<translation id="8846141544112579928">Αναζήτηση για πληκτρολόγιο…</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Όταν συνδέετε τις συσκευές σας, συμφωνείτε ότι το Chromebook μπορεί:</translation>
+<translation id="8850251000316748990">Δείτε περισσότερα…</translation>
<translation id="8859057652521303089">Επιλέξτε τη γλώσσα σας:</translation>
<translation id="8859174528519900719">Υποπλαίσιο: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Υπολογιστικό φύλλο Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_en-GB.xtb b/chromium/chrome/app/resources/generated_resources_en-GB.xtb
index dddced0831a..168109f1580 100644
--- a/chromium/chrome/app/resources/generated_resources_en-GB.xtb
+++ b/chromium/chrome/app/resources/generated_resources_en-GB.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Enable theme</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">View in Chrome Web Store</translation>
-<translation id="1761588866118490543">Voice model</translation>
<translation id="176193854664720708">The fingerprint sensor is in the power button. Touch it lightly with any finger.</translation>
<translation id="1763046204212875858">Create application shortcuts</translation>
<translation id="1763108912552529023">Keep exploring</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Send usage and diagnostic data. This device is currently automatically sending diagnostic, device and app usage data to Google. This will help system and app stability and other improvements. Some aggregate data will also help Google apps and partners, such as Android developers. This setting is enforced by the owner. If your additional Web &amp; App Activity setting is turned on, this data may be saved to your Google account. <ph name="BEGIN_LINK1" />Find out more<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip archive</translation>
<translation id="220858061631308971">Please enter this PIN code on "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Remove sharing</translation>
+<translation id="2214018885812055163">Shared folders</translation>
<translation id="2214884991347062907">Wrong password. Try again</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 line not shown&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> lines not shown&gt;}}</translation>
<translation id="2217501013957346740">Create a name -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Certificate on Hold</translation>
<translation id="2501797496290880632">Type a shortcut</translation>
<translation id="2502441965851148920">Automatic updates are enabled. Manual updates are disabled by your administrator.</translation>
+<translation id="2505127913256479918">This supervised account will be removed soon</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Screen #}other{Screen #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> of <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Store Account</translation>
@@ -1374,6 +1376,7 @@
<translation id="304747341537320566">Speech Engines</translation>
<translation id="3053013834507634016">Certificate Key Usage</translation>
<translation id="3057861065630527966">Backup your photos and videos</translation>
+<translation id="3058498974290601450">You can turn on sync at any time in settings</translation>
<translation id="3060379269883947824">Enable Select to Speak</translation>
<translation id="3061707000357573562">Patch Service</translation>
<translation id="3065041951436100775">Tab killed feedback.</translation>
@@ -1565,6 +1568,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> will be installed.</translation>
<translation id="3380365263193509176">Unknown error</translation>
<translation id="3382073616108123819">Oops! The system failed to determine device identifiers for this device.</translation>
+<translation id="3382086682569279540">The account that you manage will be removed soon</translation>
<translation id="3382200254148930874">Stopping supervision...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separator</translation>
@@ -1745,8 +1749,8 @@
<translation id="3636096452488277381">Hi, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> left</translation>
<translation id="3637682276779847508">Your SIM card will be permanently disabled if you cannot enter the correct PIN Unlock Key.</translation>
-<translation id="363863692969456324">Fix spelling errors with enhanced spell check</translation>
<translation id="3640214691812501263">Add "<ph name="EXTENSION_NAME" />" for <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Teach your Assistant to recognise your voice</translation>
<translation id="3644896802912593514">Width</translation>
<translation id="3645372836428131288">Move slightly to capture a different part of the fingerprint.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> detected</translation>
@@ -2146,7 +2150,6 @@
<translation id="4244238649050961491">Find more stylus apps</translation>
<translation id="424546999567421758">High disk usage detected</translation>
<translation id="424726838611654458">Always open in Adobe Reader</translation>
-<translation id="4247330672018280062">The text that you type in text fields will be sent to Google</translation>
<translation id="4247901771970415646">Can't sync to <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Waiting for network connection...</translation>
<translation id="4249373718504745892">This page has been blocked from accessing your camera and microphone.</translation>
@@ -2488,6 +2491,7 @@
<translation id="4821935166599369261">&amp;Profiling Enabled</translation>
<translation id="4823484602432206655">Read and change user and device settings</translation>
<translation id="4823651846660089135">Device is read-only</translation>
+<translation id="4824958205181053313">Cancel sync?</translation>
<translation id="4827675678516992122">Couldn't connect</translation>
<translation id="4828937774870308359">Australian</translation>
<translation id="4829768588131278040">Set up PIN</translation>
@@ -2870,6 +2874,7 @@
<translation id="5374359983950678924">Change picture</translation>
<translation id="5376169624176189338">Click to go back, hold to see history</translation>
<translation id="5376931455988532197">File too large</translation>
+<translation id="5377594097385838788">Incognito</translation>
<translation id="537813040452600081">Pages that you view in this window won’t appear in the browser history and they won’t leave other traces, like cookies, on the computer after you sign out. Files that you download and bookmarks that you create won’t be preserved.</translation>
<translation id="5379140238605961210">Continue blocking microphone access</translation>
<translation id="5379268888377976432">Undo Delete</translation>
@@ -2891,6 +2896,7 @@
<translation id="5414566801737831689">Read the icons of the websites that you visit</translation>
<translation id="5417312524372586921">Browser themes</translation>
<translation id="5419294236999569767">System time</translation>
+<translation id="5419405654816502573">Voice match</translation>
<translation id="5420438158931847627">Determines sharpness of text and images</translation>
<translation id="5422221874247253874">Access Point</translation>
<translation id="5422781158178868512">Sorry, your external storage device could not be recognised.</translation>
@@ -2911,6 +2917,7 @@
<translation id="5434065355175441495">PKCS #1 RSA Encryption</translation>
<translation id="5436492226391861498">Waiting for proxy tunnel...</translation>
<translation id="5436510242972373446">Search <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Please save your files and create a new account now.</translation>
<translation id="5438224778284622050">Delete offline files?</translation>
<translation id="544083962418256601">Create shortcuts...</translation>
<translation id="5442228125690314719">Error creating disk image. Please try again.</translation>
@@ -3284,6 +3291,8 @@
<translation id="5965661248935608907">It also controls what page is shown when you click the Home button or search from the Omnibox.</translation>
<translation id="5971037678316050792">Control Bluetooth adaptor state and pairing</translation>
<translation id="5972017421290582825">Manage MIDI settings...</translation>
+<translation id="597235323114979258">See more destinations</translation>
+<translation id="5972666587303800813">No-op Service</translation>
<translation id="5972708806901999743">Move to the top</translation>
<translation id="5972826969634861500">Start <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Battery Charge Percentage</translation>
@@ -3654,6 +3663,7 @@
<translation id="6527303717912515753">Share</translation>
<translation id="6528513914570774834">Allow other users of this device to use this network</translation>
<translation id="652948702951888897">Chrome history</translation>
+<translation id="6530186581263215931">These settings are enforced by your administrator</translation>
<translation id="653019979737152879">Syncing <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Keep dangerous file</translation>
<translation id="6532101170117367231">Save to Google Drive</translation>
@@ -3972,7 +3982,6 @@
<translation id="7018275672629230621">Read and change your browsing history</translation>
<translation id="7019805045859631636">Fast</translation>
<translation id="7022562585984256452">Your home page has been set.</translation>
-<translation id="702384510542929236">Sends some system information and page content to Google anonymously</translation>
<translation id="7025190659207909717">Mobile data service management</translation>
<translation id="7027125358315426638">Database Name:</translation>
<translation id="7029809446516969842">Passwords</translation>
@@ -4152,6 +4161,7 @@
<translation id="7289225569524511578">Open the wallpaper app</translation>
<translation id="7290242001003353852">This sign-in service, hosted by <ph name="SAML_DOMAIN" />, is accessing your camera.</translation>
<translation id="7290594223351252791">Confirm registration</translation>
+<translation id="7292696521213967957">Info to debug Assistant</translation>
<translation id="7295662345261934369">Share with others</translation>
<translation id="729583233778673644">Allow AES and RC4 encryption. Using this option increases your risk, as the RC4 ciphers are insecure.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> Terms</translation>
@@ -4252,7 +4262,6 @@
<translation id="7456847797759667638">Open Location...</translation>
<translation id="7461924472993315131">Pin</translation>
<translation id="7463006580194749499">Add person</translation>
-<translation id="7464902436585505072">"Ok Google" voice model</translation>
<translation id="7465778193084373987">Netscape Certificate Revocation URL</translation>
<translation id="7469894403370665791">Automatically connect to this network</translation>
<translation id="747114903913869239">Error: Unable to decode extension</translation>
@@ -4280,6 +4289,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> and the data associated with it will be removed from this device.</translation>
<translation id="7497215489070763236">Server CA certificate</translation>
<translation id="7497981768003291373">You have no recently captured WebRTC text logs.</translation>
+<translation id="7502199377020483660">To use these cards on all your devices, save them in your Google account</translation>
<translation id="7502658306369382406">IPv6 address</translation>
<translation id="7503191893372251637">Netscape Certificate Type</translation>
<translation id="7503821294401948377">Could not load icon '<ph name="ICON" />' for browser action.</translation>
@@ -4377,6 +4387,7 @@
<translation id="7663719505383602579">Receiver: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Unsupported Bluetooth device: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Add account</translation>
+<translation id="7667248760110172428">External storage</translation>
<translation id="7671130400130574146">Use system title bar and borders</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, in <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Send your voice to Google to allow dictation into any text field.</translation>
@@ -4580,6 +4591,7 @@
<translation id="7930294771522048157">Saved payment methods will appear here</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> is sharing your screen and audio.</translation>
<translation id="7931318309563332511">Unknown</translation>
+<translation id="7932969338829957666">Shared folders are available in Linux at <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Unmute Site}other{Unmute Sites}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> wants to play protected content. Your device’s identity will be verified by Google.</translation>
<translation id="793531125873261495">Error downloading the virtual machine. Please try again.</translation>
@@ -4671,6 +4683,7 @@ Keep your key file in a safe place. You will need it to create new versions of y
<translation id="8049705080247101012">Google has flagged '<ph name="EXTENSION_NAME" />' as malicious, and installation has been prevented</translation>
<translation id="8049913480579063185">Extension Name</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">This file is designed for a PC using Windows software. This is not compatible with your device which runs Chrome OS. <ph name="BEGIN_LINK_HELP" />Find out more<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS No.12 Files</translation>
<translation id="8053390638574070785">Reload This Page</translation>
<translation id="8054517699425078995">This type of file can harm your device. Do you want to keep <ph name="FILE_NAME" /> anyway?</translation>
@@ -4914,6 +4927,7 @@ Keep your key file in a safe place. You will need it to create new versions of y
<translation id="8438566539970814960">Make searches and browsing better</translation>
<translation id="8439506636278576865">Offer to translate pages in this language</translation>
<translation id="8440630305826533614">Linux apps</translation>
+<translation id="8443338615972234259">Please create a new account for your supervised user now.</translation>
<translation id="8446884382197647889">Learn More</translation>
<translation id="8447409163267621480">Include either Ctrl or Alt</translation>
<translation id="8448729345478502352">Make items on your screen smaller or larger</translation>
@@ -4938,6 +4952,7 @@ Keep your key file in a safe place. You will need it to create new versions of y
<translation id="8468750959626135884">Unlock your <ph name="DEVICE_TYPE" /> with your Android phone.</translation>
<translation id="8470028084415844044">To get all of your passwords on all your devices, turn on sync.</translation>
<translation id="8470513973197838199">Saved passwords for <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">To use this card on all your devices, save it in your Google account</translation>
<translation id="8472623782143987204">hardware-backed</translation>
<translation id="8473863474539038330">Addresses and more</translation>
<translation id="8475313423285172237">Another programme on your computer added an extension that may change the way Chrome works.</translation>
@@ -5013,7 +5028,6 @@ Keep your key file in a safe place. You will need it to create new versions of y
<translation id="8598453409908276158">Unsandboxed plug-in blocked</translation>
<translation id="8601206103050338563">TLS WWW Client Authentication</translation>
<translation id="8602851771975208551">Another programme on your computer added an app that may change the way Chrome works.</translation>
-<translation id="8604763363205185560">Help improve Chrome and its security</translation>
<translation id="8605428685123651449">SQLite Memory</translation>
<translation id="8606726445206553943">Use your MIDI devices</translation>
<translation id="8609465669617005112">Move up</translation>
@@ -5189,6 +5203,7 @@ Keep your key file in a safe place. You will need it to create new versions of y
<translation id="8846141544112579928">Searching for keyboard...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">When you connect your devices, you agree that your Chromebook can:</translation>
+<translation id="8850251000316748990">See more...</translation>
<translation id="8859057652521303089">Select your language:</translation>
<translation id="8859174528519900719">Subframe: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel spreadsheet</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_es-419.xtb b/chromium/chrome/app/resources/generated_resources_es-419.xtb
index 92fff2772e9..edf0f02e1b6 100644
--- a/chromium/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chromium/chrome/app/resources/generated_resources_es-419.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">Habilitar tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Ver en Chrome Web Store</translation>
-<translation id="1761588866118490543">Modelo de voz</translation>
<translation id="176193854664720708">El sensor de huellas digitales es el botón de encendido. Tócalo suavemente con cualquier dedo.</translation>
<translation id="1763046204212875858">Crear accesos directos a aplicaciones</translation>
<translation id="1763108912552529023">Seguir explorando</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">Envía datos de uso y diagnóstico. De forma automática, este dispositivo está enviando a Google datos de diagnóstico y sobre el uso del dispositivo y las apps. Esta información ayudará a lograr la estabilidad de las apps y el sistema, entre otras mejoras. Algunos datos agregados también ayudarán a las apps y los socios de Google, como los desarrolladores de Android. El propietario controla esta configuración. Si habilitaste la "Actividad de web y de aplicaciones adicional", es posible que se almacenen estos datos en tu Cuenta de Google. <ph name="BEGIN_LINK1" />Más información<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Archivo Zip</translation>
<translation id="220858061631308971">Ingresa este código PIN en "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Dejar de compartir</translation>
+<translation id="2214018885812055163">Carpetas compartidas</translation>
<translation id="2214884991347062907">La contraseña es incorrecta; vuelve a intentarlo</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;No se muestra una línea&gt;}other{&lt;No se muestran <ph name="NUMBER_OF_LINES" /> líneas&gt;}}</translation>
<translation id="2217501013957346740">Crear un nombre:</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">Certificado en espera</translation>
<translation id="2501797496290880632">Escribe un acceso directo.</translation>
<translation id="2502441965851148920">Las actualizaciones automáticas están habilitadas. Tu administrador inhabilitó las actualizaciones manuales.</translation>
+<translation id="2505127913256479918">Pronto se quitará esta cuenta supervisada</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Pantalla #}other{Pantalla #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> de <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Cuenta de Google Play Store</translation>
@@ -1372,6 +1374,7 @@
<translation id="304747341537320566">Motores de comentarios de texto a voz</translation>
<translation id="3053013834507634016">Uso de la clave del certificado</translation>
<translation id="3057861065630527966">Crea una copia de seguridad de tus fotos y videos.</translation>
+<translation id="3058498974290601450">Puedes activar la sincronización en la configuración en cualquier momento</translation>
<translation id="3060379269883947824">Habilitar Seleccionar para pronunciar</translation>
<translation id="3061707000357573562">Aplicar parche al servicio</translation>
<translation id="3065041951436100775">La pestaña terminó los comentarios.</translation>
@@ -1563,6 +1566,7 @@
<translation id="337920581046691015">Se instalará <ph name="PRODUCT_NAME" />.</translation>
<translation id="3380365263193509176">Error desconocido</translation>
<translation id="3382073616108123819">El sistema no pudo determinar los identificadores de dispositivo para este dispositivo.</translation>
+<translation id="3382086682569279540">Pronto se quitará la cuenta que administras</translation>
<translation id="3382200254148930874">Deteniendo la supervisión…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separador</translation>
@@ -1743,8 +1747,8 @@
<translation id="3636096452488277381">Hola, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - Queda(n) <ph name="TIME" /></translation>
<translation id="3637682276779847508">Tu tarjeta SIM quedará inhabilitada de forma permanente si no ingresas la clave de desbloqueo de PIN correcta.</translation>
-<translation id="363863692969456324">Revisa los errores de escritura con el corrector ortográfico mejorado</translation>
<translation id="3640214691812501263">¿Quieres agregar "<ph name="EXTENSION_NAME" />" para <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Enséñale al Asistente a reconocer tu voz</translation>
<translation id="3644896802912593514">Ancho</translation>
<translation id="3645372836428131288">Mueve el dedo ligeramente para capturar otra parte de la huella digital.</translation>
<translation id="3648348069317717750">Se detectó <ph name="USB_DEVICE_NAME" /></translation>
@@ -2144,7 +2148,6 @@
<translation id="4244238649050961491">Encontrar más apps para la pluma stylus</translation>
<translation id="424546999567421758">Se detectó un uso elevado del disco</translation>
<translation id="424726838611654458">Abrir siempre en Adobe Reader</translation>
-<translation id="4247330672018280062">El texto que escribas en los campos de texto se enviará a Google</translation>
<translation id="4247901771970415646">No se puede sincronizar con <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Esperando la conexión de red...</translation>
<translation id="4249373718504745892">Se bloqueó el acceso de esta página a la cámara y el micrófono.</translation>
@@ -2486,6 +2489,7 @@
<translation id="4821935166599369261">&amp;Perfiles activados</translation>
<translation id="4823484602432206655">Leer y cambiar la configuración del dispositivo y del usuario</translation>
<translation id="4823651846660089135">El dispositivo es de solo lectura</translation>
+<translation id="4824958205181053313">¿Quieres cancelar la sincronización?</translation>
<translation id="4827675678516992122">No se pudo establecer conexión</translation>
<translation id="4828937774870308359">Australiano</translation>
<translation id="4829768588131278040">Configurar PIN</translation>
@@ -2868,6 +2872,7 @@
<translation id="5374359983950678924">Cambiar imagen</translation>
<translation id="5376169624176189338">Haz clic para volver atrás o espera para ver el historial</translation>
<translation id="5376931455988532197">Archivo demasiado grande</translation>
+<translation id="5377594097385838788">Incógnito</translation>
<translation id="537813040452600081">Las páginas a las que accedas desde esta ventana no aparecerán en el historial del navegador ni dejarán rastros (por ejemplo, cookies) en la computadora una vez que salgas del navegador. Los archivos que descargues y los favoritos que crees no se guardarán.</translation>
<translation id="5379140238605961210">Seguir bloqueando el acceso al micrófono</translation>
<translation id="5379268888377976432">Deshacer eliminación</translation>
@@ -2889,6 +2894,7 @@
<translation id="5414566801737831689">Leer los íconos de los sitios web que visites</translation>
<translation id="5417312524372586921">Temas del navegador</translation>
<translation id="5419294236999569767">Hora del sistema</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Determina la nitidez del texto y las imágenes</translation>
<translation id="5422221874247253874">Punto de acceso</translation>
<translation id="5422781158178868512">Lo sentimos, tu dispositivo de almacenamiento externo no se reconoció.</translation>
@@ -2901,7 +2907,7 @@
<translation id="5427459444770871191">Girar &amp;a la derecha</translation>
<translation id="542872847390508405">Estás navegando como invitado</translation>
<translation id="5428850089342283580"><ph name="ACCNAME_APP" /> (actualización disponible)</translation>
-<translation id="5430931332414098647">Conexión instantánea mediante dispositivo portátil</translation>
+<translation id="5430931332414098647">Conexión instantánea mediante dispositivo móvil</translation>
<translation id="5431318178759467895">Color</translation>
<translation id="5431825016875453137">OpenVPN/L2TP</translation>
<translation id="5432996274932278848">Realiza búsquedas en tu dispositivo, la Web y entre las apps. Usa las teclas de flecha para navegar por las apps.</translation>
@@ -2909,6 +2915,7 @@
<translation id="5434065355175441495">PKCS N. º 1, Encriptación RSA</translation>
<translation id="5436492226391861498">Esperando túnel proxy...</translation>
<translation id="5436510242972373446">Buscar <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Guarda tus archivos y crea una cuenta nueva ahora.</translation>
<translation id="5438224778284622050">¿Borrar los archivos sin conexión?</translation>
<translation id="544083962418256601">Crear accesos directos...</translation>
<translation id="5442228125690314719">Se produjo un error al crear la imagen de disco. Vuelve a intentarlo.</translation>
@@ -3282,6 +3289,8 @@
<translation id="5965661248935608907">También controla qué página se muestra al hacer clic en el botón de página principal o al realizar búsquedas desde el cuadro multifunción.</translation>
<translation id="5971037678316050792">Controlar el estado y la sincronización del adaptador Bluetooth</translation>
<translation id="5972017421290582825">Administrar configuración MIDI</translation>
+<translation id="597235323114979258">Ver más destinos</translation>
+<translation id="5972666587303800813">Servicio sin funcionamiento</translation>
<translation id="5972708806901999743">Mover al principio</translation>
<translation id="5972826969634861500">Comienzo <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Porcentaje de carga de batería</translation>
@@ -3652,6 +3661,7 @@
<translation id="6527303717912515753">Compartir</translation>
<translation id="6528513914570774834">Permitir que otros usuarios de este dispositivo usen esta red</translation>
<translation id="652948702951888897">Historial de Chrome</translation>
+<translation id="6530186581263215931">Tu administrador gestiona estas opciones de configuración.</translation>
<translation id="653019979737152879">Sincronizando <ph name="FILE_NAME" />…</translation>
<translation id="6531282281159901044">Conservar archivo peligroso</translation>
<translation id="6532101170117367231">Guardar en Google Drive</translation>
@@ -3970,7 +3980,6 @@
<translation id="7018275672629230621">Leer y cambiar el historial de navegación</translation>
<translation id="7019805045859631636">Rápido</translation>
<translation id="7022562585984256452">Se configuró tu página principal.</translation>
-<translation id="702384510542929236">Envía información del sistema y contenido de la página a Google de forma anónima</translation>
<translation id="7025190659207909717">Administración del servicio de datos para celulares</translation>
<translation id="7027125358315426638">Nombre de la base de datos:</translation>
<translation id="7029809446516969842">Contraseñas</translation>
@@ -4150,6 +4159,7 @@
<translation id="7289225569524511578">Abrir la app de fondos de pantalla</translation>
<translation id="7290242001003353852">Este servicio de acceso, alojado por <ph name="SAML_DOMAIN" />, está accediendo a tu cámara.</translation>
<translation id="7290594223351252791">Confirmar registro</translation>
+<translation id="7292696521213967957">Información para depurar el Asistente</translation>
<translation id="7295662345261934369">Compartir con otros</translation>
<translation id="729583233778673644">Permite la encriptación AES y RC4. Esta opción es riesgosa, ya que los cifrados RC4 son inseguros.</translation>
<translation id="7296774163727375165">Condiciones de <ph name="DOMAIN" /></translation>
@@ -4250,7 +4260,6 @@
<translation id="7456847797759667638">Abrir ubicación...</translation>
<translation id="7461924472993315131">Fijar</translation>
<translation id="7463006580194749499">Agregar a una persona</translation>
-<translation id="7464902436585505072">Modelo de voz de "Ok Google"</translation>
<translation id="7465778193084373987">URL de revocación del certificado de Netscape</translation>
<translation id="7469894403370665791">Conectarse automáticamente a esta red</translation>
<translation id="747114903913869239">Error: No se puede decodificar la extensión</translation>
@@ -4278,6 +4287,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> y los datos asociados se quitarán de este dispositivo.</translation>
<translation id="7497215489070763236">Certificado de CA del servidor</translation>
<translation id="7497981768003291373">No capturaste ningún registro de texto de WebRTC recientemente.</translation>
+<translation id="7502199377020483660">Para usar estas tarjetas en todos tus dispositivos, guárdalas en tu Cuenta de Google</translation>
<translation id="7502658306369382406">Dirección IPv6</translation>
<translation id="7503191893372251637">Tipo de certificado Netscape</translation>
<translation id="7503821294401948377">No se pudo cargar el ícono '<ph name="ICON" />' para las acciones del navegador.</translation>
@@ -4375,6 +4385,7 @@
<translation id="7663719505383602579">Receptor: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Dispositivo Bluetooth no compatible: "<ph name="DEVICE_NAME" />"</translation>
<translation id="7665369617277396874">Agregar cuenta</translation>
+<translation id="7667248760110172428">Almacenamiento externo</translation>
<translation id="7671130400130574146">Usar la barra de título y los bordes del sistema</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, en <ph name="PAGE_TITLE" /></translation>
<translation id="7676867886086876795">Envía tu voz a Google para habilitar el dictado en cualquier campo de texto.</translation>
@@ -4578,6 +4589,7 @@
<translation id="7930294771522048157">Las formas de pago guardadas se mostrarán aquí</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> comparte tu pantalla y audio.</translation>
<translation id="7931318309563332511">Desconocido</translation>
+<translation id="7932969338829957666">Las carpetas compartidas están disponibles en Linux, en <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Activar el sonido del sitio}other{Activar el sonido de los sitios}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> desea reproducir contenido protegido. Google verificará la identidad de tu dispositivo.</translation>
<translation id="793531125873261495">Se produjo un error al descargar la máquina virtual. Vuelve a intentarlo.</translation>
@@ -4669,6 +4681,7 @@ Mantén el archivo de clave en un lugar seguro. Debes crear las nuevas versiones
<translation id="8049705080247101012">Google marcó <ph name="EXTENSION_NAME" /> como extensión maliciosa y se canceló la instalación</translation>
<translation id="8049913480579063185">Nombre de la extensión</translation>
<translation id="8050038245906040378">Firma de código comercial de Microsoft</translation>
+<translation id="8052887694493382350">Este archivo se diseñó para computadoras que utilizan software de Windows, por lo que no es compatible con tu dispositivo, el cual ejecuta Sistema operativo Chrome. <ph name="BEGIN_LINK_HELP" />Más información<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Archivos PKCS #12</translation>
<translation id="8053390638574070785">Volver a cargar esta página</translation>
<translation id="8054517699425078995">Este tipo de archivo puede dañar tu dispositivo. ¿Quieres descargar <ph name="FILE_NAME" /> de todas formas?</translation>
@@ -4913,6 +4926,7 @@ Es posible que los usuarios con conexiones lentas no puedan ver tu contenido.</t
<translation id="8438566539970814960">Mejorar las búsquedas y la navegación</translation>
<translation id="8439506636278576865">Ofrecer la traducción de páginas en este idioma</translation>
<translation id="8440630305826533614">Apps de Linux</translation>
+<translation id="8443338615972234259">Crea una nueva cuenta para tu usuario supervisado ahora.</translation>
<translation id="8446884382197647889">Más información</translation>
<translation id="8447409163267621480">Incluir Ctrl o Alt</translation>
<translation id="8448729345478502352">Aumenta o reduce el tamaño de los elementos en tu pantalla</translation>
@@ -4937,6 +4951,7 @@ Es posible que los usuarios con conexiones lentas no puedan ver tu contenido.</t
<translation id="8468750959626135884">Desbloquea tu dispositivo <ph name="DEVICE_TYPE" /> con tu teléfono Android.</translation>
<translation id="8470028084415844044">Para obtener todas tus contraseñas en todos los dispositivos, activa la sincronización.</translation>
<translation id="8470513973197838199">Se guardaron contraseñas para <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Para usar esta tarjeta en todos tus dispositivos, guárdala en tu Cuenta de Google</translation>
<translation id="8472623782143987204">respaldado por hardware</translation>
<translation id="8473863474539038330">Direcciones y más</translation>
<translation id="8475313423285172237">Otro programa en tu computadora agregó una extensión que puede cambiar el funcionamiento de Chrome.</translation>
@@ -5012,7 +5027,6 @@ Es posible que los usuarios con conexiones lentas no puedan ver tu contenido.</t
<translation id="8598453409908276158">Se bloquearon complementos no incluidos en la zona de pruebas</translation>
<translation id="8601206103050338563">Autenticación de cliente TLS WWW</translation>
<translation id="8602851771975208551">Otro programa en tu computadora agregó una app que puede cambiar el funcionamiento de Chrome.</translation>
-<translation id="8604763363205185560">Ayuda a mejorar Chrome y la seguridad</translation>
<translation id="8605428685123651449">Memoria SQLite</translation>
<translation id="8606726445206553943">Usar tus dispositivos MIDI</translation>
<translation id="8609465669617005112">Subir</translation>
@@ -5188,6 +5202,7 @@ Es posible que los usuarios con conexiones lentas no puedan ver tu contenido.</t
<translation id="8846141544112579928">Buscando teclado…</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Cuando conectas tus dispositivos, aceptas que tu Chromebook puede hacer lo siguiente:</translation>
+<translation id="8850251000316748990">Ver más…</translation>
<translation id="8859057652521303089">Selecciona tu idioma:</translation>
<translation id="8859174528519900719">Submarco: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Hoja de cálculo de Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_es.xtb b/chromium/chrome/app/resources/generated_resources_es.xtb
index 30a8d5642d0..ec706c41554 100644
--- a/chromium/chrome/app/resources/generated_resources_es.xtb
+++ b/chromium/chrome/app/resources/generated_resources_es.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Habilitar tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Ver en Chrome Web Store</translation>
-<translation id="1761588866118490543">Modelo de voz</translation>
<translation id="176193854664720708">El sensor de huellas digitales está situado en el botón de encendido. Tócalo ligeramente con un dedo.</translation>
<translation id="1763046204212875858">Crear accesos directos a aplicaciones</translation>
<translation id="1763108912552529023">Seguir explorando</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Enviar datos de uso y diagnóstico. Este dispositivo envía automáticamente a Google datos de diagnóstico, del dispositivo y del uso de las aplicaciones. Los datos servirán para aumentar la estabilidad de las aplicaciones y del sistema y realizar otras mejoras. Parte de los datos recogidos también ayudarán a las aplicaciones y los colaboradores de Google, como los desarrolladores de Android. El propietario ha aplicado este ajuste. Si la opción Actividad en la Web y en Aplicaciones Adicional está activada, es posible que estos datos se guarden en tu cuenta de Google. <ph name="BEGIN_LINK1" />Más información<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Archivo zip</translation>
<translation id="220858061631308971">Introduce este código PIN en "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Dejar de compartir</translation>
+<translation id="2214018885812055163">Carpetas compartidas</translation>
<translation id="2214884991347062907">La contraseña no es correcta; vuelve a intentarlo</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;no se muestra 1 línea&gt;}other{&lt;no se muestran <ph name="NUMBER_OF_LINES" /> líneas&gt;}}</translation>
<translation id="2217501013957346740">Crea un nombre -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Certificado en espera</translation>
<translation id="2501797496290880632">Escribe una combinación.</translation>
<translation id="2502441965851148920">Se han habilitado las actualizaciones automáticas. El administrador ha inhabilitado las actualizaciones manuales.</translation>
+<translation id="2505127913256479918">Esta cuenta supervisada se eliminará pronto</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Pantalla #}other{Pantalla #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> de <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Cuenta de Google Play Store</translation>
@@ -1375,6 +1377,7 @@ y su configuración no se sincronizan en otros dispositivos con la función de s
<translation id="304747341537320566">Motores de voz</translation>
<translation id="3053013834507634016">Uso de claves de certificado</translation>
<translation id="3057861065630527966">Realiza copias de seguridad de tus fotos y vídeos</translation>
+<translation id="3058498974290601450">Puedes activar la sincronización en cualquier momento desde la configuración</translation>
<translation id="3060379269883947824">Habilitar Enunciar Selección</translation>
<translation id="3061707000357573562">Aplicar parche a servicio</translation>
<translation id="3065041951436100775">Comentarios sobre una pestaña que se ha cerrado.</translation>
@@ -1564,6 +1567,7 @@ Si no cambias la configuración predeterminada, <ph name="USER_DISPLAY_NAME" />
<translation id="337920581046691015">Se va a instalar <ph name="PRODUCT_NAME" />.</translation>
<translation id="3380365263193509176">Error desconocido</translation>
<translation id="3382073616108123819">¡Vaya! El sistema no ha podido determinar los identificadores de dispositivo de este dispositivo.</translation>
+<translation id="3382086682569279540">La cuenta que gestionas se eliminará pronto</translation>
<translation id="3382200254148930874">Deteniendo la supervisión...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Separador</translation>
@@ -1738,14 +1742,14 @@ Si no cambias la configuración predeterminada, <ph name="USER_DISPLAY_NAME" />
<translation id="3627320433825461852">Menos de 1 minuto</translation>
<translation id="3627588569887975815">Abrir el enlace en una ventana de incó&amp;gnito</translation>
<translation id="3627671146180677314">Tiempo de renovación de certificado de Netscape</translation>
-<translation id="3627879631695760395">Installar <ph name="APP" />...</translation>
+<translation id="3627879631695760395">Instalar <ph name="APP" />...</translation>
<translation id="3630132874740063857">Tu teléfono</translation>
<translation id="3630995161997703415">Añade este sitio web a tu estantería para usarlo en cualquier momento</translation>
<translation id="3636096452488277381">Hola, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> hasta agotar la batería</translation>
<translation id="3637682276779847508">La tarjeta SIM se inhabilitará de forma permanente si no introduces el código PUK correcto.</translation>
-<translation id="363863692969456324">Corrige errores ortográficos con la revisión ortográfica mejorada</translation>
<translation id="3640214691812501263">¿Añadir <ph name="EXTENSION_NAME" /> para <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Enseña al Asistente a reconocer tu voz</translation>
<translation id="3644896802912593514">Anchura</translation>
<translation id="3645372836428131288">Mueve el dedo ligeramente para capturar otra parte de la huella digital.</translation>
<translation id="3648348069317717750">Se ha detectado <ph name="USB_DEVICE_NAME" /></translation>
@@ -1754,7 +1758,7 @@ Si no cambias la configuración predeterminada, <ph name="USER_DISPLAY_NAME" />
<translation id="3650952250015018111">Permitir que "<ph name="APP_NAME" />" acceda a:</translation>
<translation id="3651488188562686558">Se desconectará de la red Wi-Fi</translation>
<translation id="3652817283076144888">Inicializando</translation>
-<translation id="3653160965917900914">Archivos compartidos de red</translation>
+<translation id="3653160965917900914">Archivos compartidos en red</translation>
<translation id="3653842108912548333">Accede al Asistente con Voice Match</translation>
<translation id="3653999333232393305">Seguir permitiendo que <ph name="HOST" /> acceda al micrófono</translation>
<translation id="3654045516529121250">Leer tu configuración de accesibilidad</translation>
@@ -2144,7 +2148,6 @@ Si no cambias la configuración predeterminada, <ph name="USER_DISPLAY_NAME" />
<translation id="4244238649050961491">Buscar más aplicaciones para el lápiz óptico</translation>
<translation id="424546999567421758">Se ha detectado un uso elevado del disco</translation>
<translation id="424726838611654458">Abrir siempre en Adobe Reader</translation>
-<translation id="4247330672018280062">El texto que escribas en los campos de texto se enviará a Google</translation>
<translation id="4247901771970415646">No se puede sincronizar con <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Esperando conexión de red...</translation>
<translation id="4249373718504745892">Esta página no tiene permiso para acceder a la cámara y al micrófono.</translation>
@@ -2486,6 +2489,7 @@ Si no cambias la configuración predeterminada, <ph name="USER_DISPLAY_NAME" />
<translation id="4821935166599369261">Perfiles &amp;habilitados</translation>
<translation id="4823484602432206655">Leer y cambiar la configuración del dispositivo y del usuario</translation>
<translation id="4823651846660089135">El dispositivo es de solo lectura</translation>
+<translation id="4824958205181053313">¿Quieres cancelar la sincronización?</translation>
<translation id="4827675678516992122">No se ha podido conectar</translation>
<translation id="4828937774870308359">Australiano</translation>
<translation id="4829768588131278040">Configurar PIN</translation>
@@ -2868,6 +2872,7 @@ Si no cambias la configuración predeterminada, <ph name="USER_DISPLAY_NAME" />
<translation id="5374359983950678924">Cambiar imagen</translation>
<translation id="5376169624176189338">Haz clic para retroceder una página o pulsa unos segundos para ver el historial</translation>
<translation id="5376931455988532197">El archivo es demasiado grande.</translation>
+<translation id="5377594097385838788">Incógnito</translation>
<translation id="537813040452600081">Las páginas que aparezcan en esta ventana no se mostrarán en el historial del navegador y no dejarán otros rastros, como cookies, en el ordenador después de cerrar sesión. No se conservarán los archivos que descargues ni los marcadores que crees.</translation>
<translation id="5379140238605961210">Seguir bloqueando el acceso al micrófono</translation>
<translation id="5379268888377976432">Deshacer eliminación</translation>
@@ -2889,6 +2894,7 @@ Si no cambias la configuración predeterminada, <ph name="USER_DISPLAY_NAME" />
<translation id="5414566801737831689">Leer los iconos de los sitios web que visites</translation>
<translation id="5417312524372586921">Temas del navegador</translation>
<translation id="5419294236999569767">Hora del sistema</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Determina la nitidez del texto y las imágenes</translation>
<translation id="5422221874247253874">Punto de acceso</translation>
<translation id="5422781158178868512">No se ha podido reconocer tu dispositivo de almacenamiento externo.</translation>
@@ -2909,6 +2915,7 @@ Si no cambias la configuración predeterminada, <ph name="USER_DISPLAY_NAME" />
<translation id="5434065355175441495">PKCS #1 con cifrado RSA</translation>
<translation id="5436492226391861498">Esperando túnel proxy...</translation>
<translation id="5436510242972373446">Buscar <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Guarda tus archivos y crea una cuenta.</translation>
<translation id="5438224778284622050">¿Eliminar archivos sin conexión?</translation>
<translation id="544083962418256601">Crear accesos directos...</translation>
<translation id="5442228125690314719">No se ha podido crear la imagen de disco. Inténtalo de nuevo.</translation>
@@ -3282,6 +3289,8 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="5965661248935608907">También controla qué página se muestra al hacer clic en el botón Página de inicio o al hacer búsquedas desde el omnibox.</translation>
<translation id="5971037678316050792">Controlar el estado y la vinculación del adaptador de Bluetooth</translation>
<translation id="5972017421290582825">Administrar configuración de MIDI...</translation>
+<translation id="597235323114979258">Ver más destinos</translation>
+<translation id="5972666587303800813">Servicio No-op</translation>
<translation id="5972708806901999743">Mover al principio</translation>
<translation id="5972826969634861500">Iniciar <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Porcentaje de carga de batería</translation>
@@ -3652,6 +3661,7 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="6527303717912515753">Compartir</translation>
<translation id="6528513914570774834">Permitir que otros usuarios de este dispositivo usen esta red</translation>
<translation id="652948702951888897">Historial de Chrome</translation>
+<translation id="6530186581263215931">El administrador aplica estas opciones</translation>
<translation id="653019979737152879">Sincronizando <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Conservar archivo peligroso</translation>
<translation id="6532101170117367231">Guardar en Google Drive</translation>
@@ -3970,7 +3980,6 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="7018275672629230621">Leer y modificar tu historial de navegación</translation>
<translation id="7019805045859631636">Rápido</translation>
<translation id="7022562585984256452">Se ha establecido tu página de inicio.</translation>
-<translation id="702384510542929236">Envía a Google información del sistema y contenido de las páginas de forma anónima</translation>
<translation id="7025190659207909717">Administración de servicio de datos para móviles</translation>
<translation id="7027125358315426638">Nombre de la base de datos:</translation>
<translation id="7029809446516969842">Contraseñas</translation>
@@ -4048,7 +4057,7 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="7133578150266914903">Tu administrador va a instalar una versión anterior en este dispositivo (<ph name="PROGRESS_PERCENT" />)</translation>
<translation id="7134098520442464001">Reducir el tamaño del texto</translation>
<translation id="7135729336746831607">¿Activar Bluetooth?</translation>
-<translation id="7136694880210472378">Establecer como predeterminado</translation>
+<translation id="7136694880210472378">Elegir como predeterminado</translation>
<translation id="7136984461011502314">Te damos la bienvenida a <ph name="PRODUCT_NAME" /></translation>
<translation id="7136993520339022828">Se ha producido un error. Selecciona otras imágenes e inténtalo de nuevo.</translation>
<translation id="7138678301420049075">Otro</translation>
@@ -4150,6 +4159,7 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="7289225569524511578">Abrir aplicación de fondos de pantalla</translation>
<translation id="7290242001003353852">Este servicio de inicio de sesión (que se aloja en <ph name="SAML_DOMAIN" />) está accediendo a la cámara.</translation>
<translation id="7290594223351252791">Confirmar registro</translation>
+<translation id="7292696521213967957">Información para la depuración del Asistente</translation>
<translation id="7295662345261934369">Compartir con otros usuarios</translation>
<translation id="729583233778673644">Permite los cifrados AES y RC4. Esta opción aumenta el riesgo, ya que los algoritmos de cifrado de RC4 no son seguros.</translation>
<translation id="7296774163727375165">Condiciones de <ph name="DOMAIN" /></translation>
@@ -4250,7 +4260,6 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="7456847797759667638">Abrir ubicación...</translation>
<translation id="7461924472993315131">Fijar</translation>
<translation id="7463006580194749499">Añadir perfil</translation>
-<translation id="7464902436585505072">Modelo de voz de "Ok Google"</translation>
<translation id="7465778193084373987">URL de revocación de certificado de Netscape</translation>
<translation id="7469894403370665791">Conectarse automáticamente a esta red</translation>
<translation id="747114903913869239">Error: no es posible decodificar la extensión.</translation>
@@ -4278,6 +4287,7 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> y los datos asociados a esta aplicación se eliminarán de este dispositivo.</translation>
<translation id="7497215489070763236">Certificado de CA del servidor</translation>
<translation id="7497981768003291373">No has capturado ningún registro de texto de WebRTC recientemente.</translation>
+<translation id="7502199377020483660">Para usar estas tarjetas en todos tus dispositivos, guárdalas en tu cuenta de Google</translation>
<translation id="7502658306369382406">Dirección IPv6</translation>
<translation id="7503191893372251637">Tipo de certificado de Netscape</translation>
<translation id="7503821294401948377">No se ha podido cargar el icono "<ph name="ICON" />" para la acción del navegador.</translation>
@@ -4375,6 +4385,7 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="7663719505383602579">Receptor: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Dispositivo Bluetooth no compatible: <ph name="DEVICE_NAME" /></translation>
<translation id="7665369617277396874">Añadir cuenta</translation>
+<translation id="7667248760110172428">Almacenamiento externo</translation>
<translation id="7671130400130574146">Utilizar bordes y barra de título</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> en <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Envía tu voz a Google para utilizar el dictado en cualquier campo de texto.</translation>
@@ -4578,6 +4589,7 @@ Exponente público (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bits):
<translation id="7930294771522048157">Los métodos de pago guardados aparecerán aquí</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> está compartiendo la pantalla y el audio.</translation>
<translation id="7931318309563332511">Desconocido</translation>
+<translation id="7932969338829957666">En Linux, las carpetas compartidas están disponibles en <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Activar sonido del sitio web}other{Activar sonido de los sitios web}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> quiere reproducir contenido protegido. Google verificará la identidad de tu dispositivo.</translation>
<translation id="793531125873261495">No se ha podido descargar la máquina virtual Inténtalo de nuevo.</translation>
@@ -4669,6 +4681,7 @@ Guarda tu archivo de clave en un lugar seguro, ya que lo necesitarás para crear
<translation id="8049705080247101012">Google ha marcado "<ph name="EXTENSION_NAME" />" como extensión maliciosa, por lo que ha evitado que se instale</translation>
<translation id="8049913480579063185">Nombre de la extensión</translation>
<translation id="8050038245906040378">Firma de código comercial de Microsoft</translation>
+<translation id="8052887694493382350">Este archivo se ha diseñado para ordenadores que utilicen Windows. No es compatible con tu dispositivo, que utiliza Chrome OS. <ph name="BEGIN_LINK_HELP" />Más información<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Archivos PKCS #12</translation>
<translation id="8053390638574070785">Cargar página de nuevo</translation>
<translation id="8054517699425078995">Este tipo de archivo puede dañar tu dispositivo. ¿Quieres descargar <ph name="FILE_NAME" /> de todas formas?</translation>
@@ -4912,6 +4925,7 @@ Guarda tu archivo de clave en un lugar seguro, ya que lo necesitarás para crear
<translation id="8438566539970814960">Mejorar las búsquedas y la navegación</translation>
<translation id="8439506636278576865">Ofrecer la traducción de páginas en este idioma</translation>
<translation id="8440630305826533614">Aplicaciones de Linux</translation>
+<translation id="8443338615972234259">Crea una cuenta para tu usuario supervisado.</translation>
<translation id="8446884382197647889">Más información</translation>
<translation id="8447409163267621480">Incluye Ctrl o Alt</translation>
<translation id="8448729345478502352">Reducir o aumentar el tamaño de los elementos de la pantalla</translation>
@@ -4936,6 +4950,7 @@ Guarda tu archivo de clave en un lugar seguro, ya que lo necesitarás para crear
<translation id="8468750959626135884">Desbloquea tu <ph name="DEVICE_TYPE" /> con tu teléfono Android.</translation>
<translation id="8470028084415844044">Activa la sincronización para tener tus contraseñas en todos tus dispositivos.</translation>
<translation id="8470513973197838199">Contraseñas guardadas de <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Para utilizar esta tarjeta en todos tus dispositivos, guárdala en tu cuenta de Google</translation>
<translation id="8472623782143987204">respaldado por hardware</translation>
<translation id="8473863474539038330">Direcciones y más</translation>
<translation id="8475313423285172237">Otro programa de tu ordenador ha añadido una extensión que puede cambiar el funcionamiento de Chrome.</translation>
@@ -5011,7 +5026,6 @@ Guarda tu archivo de clave en un lugar seguro, ya que lo necesitarás para crear
<translation id="8598453409908276158">Complemento no incluido en la zona de pruebas bloqueado</translation>
<translation id="8601206103050338563">Autenticación de cliente WWW TLS</translation>
<translation id="8602851771975208551">Otro programa de tu ordenador ha añadido una aplicación que puede cambiar el funcionamiento de Chrome.</translation>
-<translation id="8604763363205185560">Ayuda a mejorar Chrome y su seguridad</translation>
<translation id="8605428685123651449">Memoria SQLite</translation>
<translation id="8606726445206553943">Utilizar tus dispositivos MIDI</translation>
<translation id="8609465669617005112">Subir</translation>
@@ -5187,6 +5201,7 @@ Guarda tu archivo de clave en un lugar seguro, ya que lo necesitarás para crear
<translation id="8846141544112579928">Buscando teclado...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Cuando conectas tus dispositivos, aceptas que el Chromebook puede hacer lo siguiente:</translation>
+<translation id="8850251000316748990">Ver más...</translation>
<translation id="8859057652521303089">Selecciona tu idioma:</translation>
<translation id="8859174528519900719">Submarco: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Hoja de cálculo de Excel</translation>
@@ -5411,7 +5426,7 @@ Guarda tu archivo de clave en un lugar seguro, ya que lo necesitarás para crear
<translation id="9214520840402538427">¡Vaya! Se ha agotado el tiempo de la inicialización de los atributos de tiempo de instalación. Ponte en contacto con el representante del servicio de asistencia.</translation>
<translation id="9214695392875603905">Cupcake</translation>
<translation id="9215293857209265904">"<ph name="EXTENSION_NAME" />" añadida</translation>
-<translation id="9218430445555521422">Establecer como predeterminado</translation>
+<translation id="9218430445555521422">Elegir como predeterminado</translation>
<translation id="9219103736887031265">Imágenes</translation>
<translation id="9220525904950070496">Quitar cuenta</translation>
<translation id="9220820413868316583">Levanta el dedo y vuelve a intentarlo.</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_et.xtb b/chromium/chrome/app/resources/generated_resources_et.xtb
index 6e1887278af..8e3335f96a1 100644
--- a/chromium/chrome/app/resources/generated_resources_et.xtb
+++ b/chromium/chrome/app/resources/generated_resources_et.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Luba teema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Kuva Chrome'i veebipoes</translation>
-<translation id="1761588866118490543">Häälemudel</translation>
<translation id="176193854664720708">Sõrmejäljeandur on toitenupp. Puudutage seda õrnalt mis tahes sõrmega.</translation>
<translation id="1763046204212875858">Rakenduse otseteede loomine</translation>
<translation id="1763108912552529023">Jätka uurimist</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Saada kasutus- ja diagnostikaandmeid. See seade saadab Google'ile praegu automaatselt seadme teavet ning rakenduse kasutus- ja diagnostikaandmeid. See aitab parandada süsteemi ja rakenduse stabiilsust ning muud. Teatud koondandmed on abiks ka Google'i rakendustele ja partneritele, näiteks Androidi arendajatele. Selle seade on jõustanud omanik. Kui täiendavad veebi- ja rakendustegevused on sisse lülitatud, võidakse need andmed salvestada teie Google'i kontole. <ph name="BEGIN_LINK1" />Lisateave<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip-arhiiv</translation>
<translation id="220858061631308971">Sisestage seadmes „<ph name="DEVICE_NAME" />” see PIN-kood:</translation>
+<translation id="2213140827792212876">Jagamise eemaldamine</translation>
+<translation id="2214018885812055163">Jagatud kaustad</translation>
<translation id="2214884991347062907">Vale parool, proovige uuesti</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;Ei näidata 1 rida&gt;}other{&lt;Ei näidata <ph name="NUMBER_OF_LINES" /> rida&gt;}}</translation>
<translation id="2217501013957346740">Nime loomine –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Ootel sertifikaat</translation>
<translation id="2501797496290880632">Sisestage otsetee</translation>
<translation id="2502441965851148920">Automaatsed värskendused on lubatud. Administraator keelas käsitsi värskendused.</translation>
+<translation id="2505127913256479918">See järelevalvega konto eemaldatakse peagi</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{#. ekraan}other{#. ekraan}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> / <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play poe konto</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Kõnesünteesimootorid</translation>
<translation id="3053013834507634016">Sertifikaadi võtme kasutus</translation>
<translation id="3057861065630527966">Fotode ja videote varundamine</translation>
+<translation id="3058498974290601450">Saate sünkroonimise seadetes alati sisse lülitada</translation>
<translation id="3060379269883947824">Luba funktsioon Vali ja kuula</translation>
<translation id="3061707000357573562">Teenuse paikamine</translation>
<translation id="3065041951436100775">Tagasiside vahelehe sulgumise kohta.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015">Installitakse <ph name="PRODUCT_NAME" />.</translation>
<translation id="3380365263193509176">Tundmatu viga</translation>
<translation id="3382073616108123819">Vabandust! Süsteemil ei õnnestunud määrata sellele seadmele seadme tuvastajaid.</translation>
+<translation id="3382086682569279540">Teie hallatav konto eemaldatakse peagi</translation>
<translation id="3382200254148930874">Järelevalve peatamine …</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Eraldaja</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Terekest, <ph name="USER_GIVEN_NAME" />!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – <ph name="TIME" /> on jäänud</translation>
<translation id="3637682276779847508">Kui te ei sisesta õiget PUK-koodi, keelatakse teie SIM-kaart jäädavalt.</translation>
-<translation id="363863692969456324">Täiustatud õigekirjakontrolliga kirjavigade parandamine</translation>
<translation id="3640214691812501263">Kas soovite lisada kasutajale <ph name="USER_NAME" /> laiendi „<ph name="EXTENSION_NAME" />”?</translation>
+<translation id="3640613767643722554">Õpetage assistendile, kuidas teie häält ära tunda</translation>
<translation id="3644896802912593514">Laius</translation>
<translation id="3645372836428131288">Liigutage veidi sõrme, et sõrmejälje teine osa jäädvustada</translation>
<translation id="3648348069317717750">Tuvastati <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="4244238649050961491">Otsi rohkem elektronpliiatsi rakendusi</translation>
<translation id="424546999567421758">Tuvastati suur kettakasutus</translation>
<translation id="424726838611654458">Ava alati programmis Adobe Reader</translation>
-<translation id="4247330672018280062">Tekst, mille sisestate tekstiväljadele, saadetakse Google’ile</translation>
<translation id="4247901771970415646">Kasutajaga <ph name="USERNAME" /> ei saa sünkroonida</translation>
<translation id="4249248555939881673">Võrguühenduse ootamine ...</translation>
<translation id="4249373718504745892">Sellele lehele on juurdepääs teie kaamerale ja mikrofonile blokeeritud.</translation>
@@ -2489,6 +2492,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="4821935166599369261">&amp;Profileerimine lubatud</translation>
<translation id="4823484602432206655">Loe ja muuda kasutaja ja seadme seadeid</translation>
<translation id="4823651846660089135">Seade on kirjutuskaitstud</translation>
+<translation id="4824958205181053313">Kas tühistada sünkroonimine?</translation>
<translation id="4827675678516992122">Ühendamine ebaõnnestus</translation>
<translation id="4828937774870308359">Austraalia</translation>
<translation id="4829768588131278040">Seadista PIN-kood</translation>
@@ -2871,6 +2875,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="5374359983950678924">Muuda pilti</translation>
<translation id="5376169624176189338">Klõpsake tagasi minemiseks, hoidke all ajaloo kuvamiseks</translation>
<translation id="5376931455988532197">Fail on liiga suur</translation>
+<translation id="5377594097385838788">Inkognito</translation>
<translation id="537813040452600081">Lehti, mida vaatate selles aknas, ei lisata teie brauseri ajalukku ja pärast väljalogimist ei jää neist arvutisse ka muid jälgi (nt küpsiseid). Allalaaditud faile ja loodud järjehoidjaid ei säilitata.</translation>
<translation id="5379140238605961210">Blokeeri ka edaspidi juurdepääs mikrofonile</translation>
<translation id="5379268888377976432">Võta kustutamine tagasi</translation>
@@ -2892,6 +2897,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="5414566801737831689">Külastatavate veebisaitide ikoonide lugemine</translation>
<translation id="5417312524372586921">Brauseri teemad</translation>
<translation id="5419294236999569767">Süsteemiaeg</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Määrab teksti ja piltide teravuse</translation>
<translation id="5422221874247253874">Pääsupunkt</translation>
<translation id="5422781158178868512">Kahjuks ei õnnestu teie välist salvestusseadet ära tunda.</translation>
@@ -2912,6 +2918,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="5434065355175441495">PKCS 1 RSA krüpteerimine</translation>
<translation id="5436492226391861498">Puhverserveri tunneli ootamine...</translation>
<translation id="5436510242972373446">Otsi <ph name="SITE_NAME" />-st:</translation>
+<translation id="543806387003274181">Salvestage oma failid ja looge kohe uus konto.</translation>
<translation id="5438224778284622050">Kas kustutada võrguühenduseta failid?</translation>
<translation id="544083962418256601">Loo otseteid ...</translation>
<translation id="5442228125690314719">Viga kettakujutise loomisel. Proovige uuesti.</translation>
@@ -3285,6 +3292,8 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="5965661248935608907">Lisaks juhib see seda, mis leht kuvatakse avalehe nupul klõpsamisel või omnikastikeses otsingu tegemisel.</translation>
<translation id="5971037678316050792">Bluetoothi adapteri oleku ja sidumise juhtimine</translation>
<translation id="5972017421290582825">MIDI-seadete haldamine ...</translation>
+<translation id="597235323114979258">Kuva rohkem sihtkohti</translation>
+<translation id="5972666587303800813">Toiminguta teenus</translation>
<translation id="5972708806901999743">Teisalda ülaossa</translation>
<translation id="5972826969634861500">Käivita <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Aku laetuse protsent</translation>
@@ -3655,6 +3664,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="6527303717912515753">Jaga</translation>
<translation id="6528513914570774834">Luba teistel selle seadme kasutajatel seda võrku kasutada</translation>
<translation id="652948702951888897">Chrome'i ajalugu</translation>
+<translation id="6530186581263215931">Need seaded jõustas administraator</translation>
<translation id="653019979737152879">Faili <ph name="FILE_NAME" /> sünkroonimine ...</translation>
<translation id="6531282281159901044">Säilita ohtlik fail</translation>
<translation id="6532101170117367231">Salvesta rakendusse Google Drive</translation>
@@ -3973,7 +3983,6 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="7018275672629230621">Sirvimisajaloo lugemine ja muutmine</translation>
<translation id="7019805045859631636">Kiire</translation>
<translation id="7022562585984256452">Teie avaleht on määratud.</translation>
-<translation id="702384510542929236">Saadab Google'ile anonüümselt teatud süsteemiteavet ja lehe sisu</translation>
<translation id="7025190659207909717">Mobiilse andmesideteenuse haldus</translation>
<translation id="7027125358315426638">Andmebaasi nimi:</translation>
<translation id="7029809446516969842">Paroolid</translation>
@@ -4153,6 +4162,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="7289225569524511578">Ava taustapildi rakendus</translation>
<translation id="7290242001003353852">See domeeni <ph name="SAML_DOMAIN" /> hostitud sisselogimisteenus pääseb teie kaamerale juurde.</translation>
<translation id="7290594223351252791">Registreerimise kinnitamine</translation>
+<translation id="7292696521213967957">Teave assistendi silumiseks</translation>
<translation id="7295662345261934369">Jaga teistega</translation>
<translation id="729583233778673644">Lubatakse AES- ja RC4-krüpteerimine. Selle valiku kasutamine suurendab riski, kuna RC4-šifrid on ebaturvalised.</translation>
<translation id="7296774163727375165">Domeeni <ph name="DOMAIN" /> tingimused</translation>
@@ -4253,7 +4263,6 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="7456847797759667638">Ava asukoht...</translation>
<translation id="7461924472993315131">Kinnita</translation>
<translation id="7463006580194749499">Lisa inimene</translation>
-<translation id="7464902436585505072">Otsetee sõna „Ok Google" häälmudel</translation>
<translation id="7465778193084373987">Netscape'i sertifikaadi tühistus-URL</translation>
<translation id="7469894403370665791">Võta automaatselt selle võrguga ühendust</translation>
<translation id="747114903913869239">Viga: laiendust ei õnnestu dekodeerida</translation>
@@ -4281,6 +4290,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> ja sellega seotud andmed eemaldatakse seadmest.</translation>
<translation id="7497215489070763236">Serveri CA-sertifikaat</translation>
<translation id="7497981768003291373">Teil pole ühtegi hiljuti jäädvustatud WebRTC tekstilogi.</translation>
+<translation id="7502199377020483660">Kui soovite neid kaarte kasutada kõigis oma seadmetes, salvestage need oma Google'i kontole</translation>
<translation id="7502658306369382406">IPv6 aadress</translation>
<translation id="7503191893372251637">Netscape'i sertifikaadi tüüp</translation>
<translation id="7503821294401948377">Brauseri toimingu jaoks ei õnnestunud laadida ikooni <ph name="ICON" />.</translation>
@@ -4378,6 +4388,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="7663719505383602579">Saaja: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Toetamata Bluetooth-seade: „<ph name="DEVICE_NAME" />”.</translation>
<translation id="7665369617277396874">Konto lisamine</translation>
+<translation id="7667248760110172428">Väline salvestusruum</translation>
<translation id="7671130400130574146">Kasutage süsteemi pealkirjariba ja ääriseid</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> lehel <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Saatke oma hääl Google'ile, et lubada dikteerimine kõigil tekstiväljadel.</translation>
@@ -4581,6 +4592,7 @@ kasutades juhtpaneeli funktsiooni <ph name="CONTROL_PANEL_APPLET_NAME" />.
<translation id="7930294771522048157">Salvestatud makseviisid kuvatakse siin</translation>
<translation id="79312157130859720">Rakendus <ph name="APP_NAME" /> jagab teie ekraani ja heli.</translation>
<translation id="7931318309563332511">Teadmata</translation>
+<translation id="7932969338829957666">Linuxis on jagatud kaustad saadaval asukohas <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Tühista saidi vaigistus}other{Tühista saitide vaigistus}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> soovib esitada kaitstud sisu. Google kontrollib teie seadme identiteeti.</translation>
<translation id="793531125873261495">Viga virtuaalseadme allalaadimisel. Proovige uuesti.</translation>
@@ -4672,6 +4684,7 @@ Hoidke oma võtmefail kindlas kohas. Teil läheb seda oma laiendi uute versiooni
<translation id="8049705080247101012">Google märgistas laienduse „<ph name="EXTENSION_NAME" />” pahatahtlikuks ja installimine blokeeriti</translation>
<translation id="8049913480579063185">Laienduse nimi</translation>
<translation id="8050038245906040378">Microsofti äriline koodsigneerimine</translation>
+<translation id="8052887694493382350">See fail on mõeldud Windowsi tarkvara kasutavale arvutile. See ei ühildu teie seadmega, mis käitab Chrome OS-i. <ph name="BEGIN_LINK_HELP" />Lisateave<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 failid</translation>
<translation id="8053390638574070785">Laadi see leht uuesti</translation>
<translation id="8054517699425078995">Seda tüüpi fail võib teie seadet kahjustada. Kas soovite faili <ph name="FILE_NAME" /> siiski alles jätta?</translation>
@@ -4916,6 +4929,7 @@ Inimesed, kelle ühendus on aeglane, ei pruugi teie sisu näha.</translation>
<translation id="8438566539970814960">Otsingute ja sirvimise paremaks muutmine</translation>
<translation id="8439506636278576865">Paku selles keeles olevate lehtede tõlkimist</translation>
<translation id="8440630305826533614">Linuxi rakendused</translation>
+<translation id="8443338615972234259">Looge jälgitavatele kasutajatele nüüd uus konto.</translation>
<translation id="8446884382197647889">Lisateave</translation>
<translation id="8447409163267621480">Kaasake Ctrl või Alt</translation>
<translation id="8448729345478502352">Muutke ekraanil kuvatud üksused väiksemaks või suuremaks</translation>
@@ -4940,6 +4954,7 @@ Inimesed, kelle ühendus on aeglane, ei pruugi teie sisu näha.</translation>
<translation id="8468750959626135884">Seadme <ph name="DEVICE_TYPE" /> avamine Android-telefoniga.</translation>
<translation id="8470028084415844044">Selleks et hankida kõik oma paroolid kõikidesse seadmetesse, lülitage sünkroonimine sisse.</translation>
<translation id="8470513973197838199">Salvestatud paroolid – <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Kui soovite seda kaarti kasutada kõigis oma seadmetes, salvestage see oma Google'i kontole</translation>
<translation id="8472623782143987204">riistvaraga toetatud</translation>
<translation id="8473863474539038330">Aadressid ja muu</translation>
<translation id="8475313423285172237">Teine programm teie arvutis lisas laienduse, mis võib muuta Chrome'i toimimist.</translation>
@@ -5015,7 +5030,6 @@ Inimesed, kelle ühendus on aeglane, ei pruugi teie sisu näha.</translation>
<translation id="8598453409908276158">Liivakastist eemaldatud pistikprogramm on blokeeritud</translation>
<translation id="8601206103050338563">TLS WWW kliendi autentimine</translation>
<translation id="8602851771975208551">Teine programm teie arvutis lisas rakenduse, mis võib muuta Chrome'i toimimist.</translation>
-<translation id="8604763363205185560">Aidake täiustada Chrome'i ja selle turvalisust</translation>
<translation id="8605428685123651449">SQLite'i mälu</translation>
<translation id="8606726445206553943">Kasutada MIDI-seadmeid</translation>
<translation id="8609465669617005112">Liiguta üles</translation>
@@ -5191,6 +5205,7 @@ Inimesed, kelle ühendus on aeglane, ei pruugi teie sisu näha.</translation>
<translation id="8846141544112579928">Klaviatuuri otsimine ...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Kui loote seadmetega ühenduse, lubate Chromebookil teha järgmist.</translation>
+<translation id="8850251000316748990">Vaadake rohkem …</translation>
<translation id="8859057652521303089">Valige keel:</translation>
<translation id="8859174528519900719">Alamraam: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Exceli tabel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_fa.xtb b/chromium/chrome/app/resources/generated_resources_fa.xtb
index 27058304249..6760275ec9b 100644
--- a/chromium/chrome/app/resources/generated_resources_fa.xtb
+++ b/chromium/chrome/app/resources/generated_resources_fa.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">فعال کردن طرح زمینه</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">‏مشاهده در «نت‌بازار Chrome»</translation>
-<translation id="1761588866118490543">مدل صوتی</translation>
<translation id="176193854664720708">حسگر اثر انگشت روی دکمه روشن/خاموش است. با یکی از انگشت‌هایتان آن را به‌آرامی لمس کنید.</translation>
<translation id="1763046204212875858">ایجاد میان‌برهای برنامه</translation>
<translation id="1763108912552529023">به کاوش ادامه دهید</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">‏داده‌های استفاده و عیب‌یابی را ارسال کنید. این دستگاه درحال‌حاضر به‌صورت‌ خودکار داده‌های عیب‌یابی و داده‌های استفاده از دستگاه و برنامه را برای Google ارسال می‌کند. این داده‌ها به بهبود پایداری سیستم و برنامه و موارد دیگر کمک خواهد کرد. بعضی داده‌های انبوه نیز به برنامه‌ها و شرکای Google (مانند برنامه‌نویس‌های Android) کمک می‌کند. این تنظیم توسط مالک اعمال می‌شود. اگر تنظیم «فعالیت وب و برنامه» تکمیلی روشن باشد، ممکن است این داده‌ها در حساب Google شما ذخیره شود. <ph name="BEGIN_LINK1" />بیشتر بدانید<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">فایل بایگانی زیپ</translation>
<translation id="220858061631308971">لطفاً این کد پین را در "<ph name="DEVICE_NAME" />" وارد کنید:</translation>
+<translation id="2213140827792212876">برداشتن اشتراک‌گذاری</translation>
+<translation id="2214018885812055163">پوشه‌های اشتراک‌گذاری‌شده</translation>
<translation id="2214884991347062907">گذرواژه نادرست است، دوباره امتحان کنید.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;۱ خط نشان داده نمی‌شود&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> خط نشان داده نمی‌شوند&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> خط نشان داده نمی‌شوند&gt;}}</translation>
<translation id="2217501013957346740">یک نام ایجاد کنید -</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">گواهی در انتظار</translation>
<translation id="2501797496290880632">تایپ کردن میان‌بر</translation>
<translation id="2502441965851148920">به‌روزرسانی‌های خودکار فعال شده‌اند. سرپرست سیستم شما به‌روزرسانی‌های دستی را غیرفعال کرده است.</translation>
+<translation id="2505127913256479918">این حساب تحت‌نظارت به‌زودی برداشته می‌شود</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{صفحه #}one{صفحه #}other{صفحه #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> از <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">‏حساب فروشگاه Google Play</translation>
@@ -1371,6 +1373,7 @@
<translation id="304747341537320566">موتورهای گفتار</translation>
<translation id="3053013834507634016">کاربرد کلید گواهی</translation>
<translation id="3057861065630527966">از عکس‌ها و ویدئوهایتان پشتیبان بگیرید</translation>
+<translation id="3058498974290601450">هرزمان خواستید می‌توانید همگام‌سازی را در تنظیمات روشن کنید</translation>
<translation id="3060379269883947824">فعال کردن «انتخاب برای شنیدن»</translation>
<translation id="3061707000357573562">سرویس وصله</translation>
<translation id="3065041951436100775">بازخورد بسته شدن برگه.</translation>
@@ -1562,6 +1565,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> نصب خواهد شد.</translation>
<translation id="3380365263193509176">خطای ناشناس</translation>
<translation id="3382073616108123819">وای! سیستم نتوانست شناسه‌های دستگاه را برای این دستگاه تعیین کند.</translation>
+<translation id="3382086682569279540">حسابی که مدیریت می‌کنید به‌زودی برداشته می‌شود</translation>
<translation id="3382200254148930874">درحال توقف نظارت...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">جداساز</translation>
@@ -1742,8 +1746,8 @@
<translation id="3636096452488277381">سلام <ph name="USER_GIVEN_NAME" />، حالتان چطور است.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />٪ - <ph name="TIME" /> باقی مانده است</translation>
<translation id="3637682276779847508">اگر نتوانید کلید باز کردن قفل پین صحیح را وارد کنید، سیم‌کارت برای همیشه غیرفعال می‌شود.</translation>
-<translation id="363863692969456324">رفع اشتباهات املایی بااستفاده از غلط‌گیر املای بهبودیافته</translation>
<translation id="3640214691812501263">«<ph name="EXTENSION_NAME" />» برای «<ph name="USER_NAME" />» اضافه شود؟</translation>
+<translation id="3640613767643722554">به «دستیار» آموزش دهید صدایتان را تشخیص دهد</translation>
<translation id="3644896802912593514">عرض</translation>
<translation id="3645372836428131288">انگشتتان را کمی حرکت دهید تا بخش دیگری از اثرانگشت ثبت شود.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> شناسایی شد</translation>
@@ -2143,7 +2147,6 @@
<translation id="4244238649050961491">پیدا کردن برنامه‌های قلم بیشتر</translation>
<translation id="424546999567421758">مصرف بالای دیسک شناسایی شد</translation>
<translation id="424726838611654458">‏همیشه در Adobe Reader باز شود</translation>
-<translation id="4247330672018280062">‏نوشتاری که در فیلدهای نوشتار تایپ کرده‌اید به Google ارسال خواهد شد</translation>
<translation id="4247901771970415646">همگام‌سازی با <ph name="USERNAME" /> نمی‌تواند انجام شود</translation>
<translation id="4249248555939881673">در انتظار اتصال شبکه...</translation>
<translation id="4249373718504745892">این صفحه از دسترسی به دوربین و میکروفون شما بازداشته شده است.</translation>
@@ -2485,6 +2488,7 @@
<translation id="4821935166599369261">&amp;ایجاد نمایه فعال شد</translation>
<translation id="4823484602432206655">تغییر و خواندن تنظیمات کاربر و دستگاه</translation>
<translation id="4823651846660089135">دستگاه فقط خواندنی است</translation>
+<translation id="4824958205181053313">همگام‌سازی لغو شود؟</translation>
<translation id="4827675678516992122">متصل نشد</translation>
<translation id="4828937774870308359">استرالیایی</translation>
<translation id="4829768588131278040">تنظیم پین</translation>
@@ -2867,6 +2871,7 @@
<translation id="5374359983950678924">تغییر عکس</translation>
<translation id="5376169624176189338">برای برگشت به عقب کلیک کنید، برای دیدن سابقه نگه دارید</translation>
<translation id="5376931455988532197">فایل بسیار بزرگ است</translation>
+<translation id="5377594097385838788">حالت ناشناس</translation>
<translation id="537813040452600081">صفحاتی که در این پنجره مشاهده می‌کنید در سابقه مروگر نشان داده نمی‌شوند و بعد از خروج از سیستم هیچ رد دیگری در رایانه از خود به جای نمی‌گذارند (مانند کوکی‌ها). فایل‌هایی که بارگیری می‌کنید و نشانک‌هایی که ایجاد می‌کنید حفظ نمی‌شوند.</translation>
<translation id="5379140238605961210">ادامه مسدود کردن دسترسی به میکروفون</translation>
<translation id="5379268888377976432">واگرد حذف</translation>
@@ -2888,6 +2893,7 @@
<translation id="5414566801737831689">خواندن نمادهای وب‌سایت‌هایی که بازدید می‌کنید</translation>
<translation id="5417312524372586921">طرح‌های زمینه مرورگر</translation>
<translation id="5419294236999569767">زمان سیستم</translation>
+<translation id="5419405654816502573">Voice match</translation>
<translation id="5420438158931847627">وضوح نوشتار یا تصاویر را تعیین می‌کند</translation>
<translation id="5422221874247253874">نقطه دسترسی</translation>
<translation id="5422781158178868512">متأسفیم، دستگاه ذخیره‌سازی خارجی شما شناسایی نشد.</translation>
@@ -2900,7 +2906,7 @@
<translation id="5427459444770871191">چرخاندن در جهت &amp;عقربه‌های ساعت</translation>
<translation id="542872847390508405">به عنوان مهمان مرور می‌کنید</translation>
<translation id="5428850089342283580"><ph name="ACCNAME_APP" /> (به‌روزرسانی موجود است)</translation>
-<translation id="5430931332414098647">اتصال فوری به اینترنت با تلفن همراه</translation>
+<translation id="5430931332414098647">اشتراک‌گذاری اینترنت فوری</translation>
<translation id="5431318178759467895">رنگ</translation>
<translation id="5431825016875453137">OpenVPN / L2TP</translation>
<translation id="5432996274932278848">دستگاه خود، برنامه‌ها و وب را جستجو کنید. با کلیدهای پیکانی، برنامه‌هایتان را پیمایش کنید.</translation>
@@ -2908,6 +2914,7 @@
<translation id="5434065355175441495">‏PKCS #1 RSA رمزگذاری</translation>
<translation id="5436492226391861498">منتظر تونل پراکسی...</translation>
<translation id="5436510242972373446">جستجوی <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">لطفاً فایل‌هایتان را ذخیره کنید و همین حالا حساب جدیدی ایجاد کنید.</translation>
<translation id="5438224778284622050">فایل‌های آفلاین حذف شوند؟</translation>
<translation id="544083962418256601">ایجاد میان‌برها...</translation>
<translation id="5442228125690314719">هنگام ایجاد تصویر دیسک خطایی روی داد. لطفاً دوباره امتحان کنید.</translation>
@@ -3281,6 +3288,8 @@
<translation id="5965661248935608907">‏این برنامه افزودنی همچنین صفحه‌ای را که هنگام کلیک کردن روی دکمه صفحه اصلی یا جستجو از Omnibox نشان داده می‌شود، کنترل می‌کند.</translation>
<translation id="5971037678316050792">کنترل حالت آداپتور بلوتوث و مرتبط‌سازی</translation>
<translation id="5972017421290582825">‏مدیریت تنظیمات MIDI ...</translation>
+<translation id="597235323114979258">دیدن مقصدهای بیشتر</translation>
+<translation id="5972666587303800813">سرویس غیرفعال</translation>
<translation id="5972708806901999743">انتقال به بالا</translation>
<translation id="5972826969634861500">شروع <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">درصد شارژ باتری</translation>
@@ -3651,6 +3660,7 @@
<translation id="6527303717912515753">اشتراک‌گذاری</translation>
<translation id="6528513914570774834">به سایر کاربران این دستگاه اجازه داده شود از این شبکه استفاده کنند</translation>
<translation id="652948702951888897">‏سابقه Chrome</translation>
+<translation id="6530186581263215931">این تنظیمات توسط سرپرست سیستم شما اعمال شده است</translation>
<translation id="653019979737152879">در حال همگام‌سازی <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">حفظ فایل خطرناک</translation>
<translation id="6532101170117367231">‏‫ذخیره در Google Drive</translation>
@@ -3969,7 +3979,6 @@
<translation id="7018275672629230621">خواندن و تغییر سابقه مرورگرتان</translation>
<translation id="7019805045859631636">سریع</translation>
<translation id="7022562585984256452">صفحه اصلی شما تنظیم شد.</translation>
-<translation id="702384510542929236">‏برخی از اطلاعات سیستم و محتوای صفحه را به‌طور ناشناس به Google ارسال می‌کند</translation>
<translation id="7025190659207909717">مدیریت خدمات داده‌های تلفن همراه</translation>
<translation id="7027125358315426638">نام پایگاه داده:</translation>
<translation id="7029809446516969842">گذرواژه‌ها</translation>
@@ -4149,6 +4158,7 @@
<translation id="7289225569524511578">باز کردن برنامه کاغذ دیواری</translation>
<translation id="7290242001003353852">این سرویس ورود به سیستم با میزبانی <ph name="SAML_DOMAIN" /> در حال دسترسی به دوربین شما است.</translation>
<translation id="7290594223351252791">تأیید ثبت</translation>
+<translation id="7292696521213967957">اطلاعات برای اشکال‌زدایی «دستیار»</translation>
<translation id="7295662345261934369">هم‌رسانی با دیگران</translation>
<translation id="729583233778673644">‏مجاز کردن رمزگذاری AES و RC4. استفاده از این گزینه احتمال خطر را بالا می‌برد، زیرا رمزهای RC4 امن نیست.</translation>
<translation id="7296774163727375165">شرایط <ph name="DOMAIN" /></translation>
@@ -4249,7 +4259,6 @@
<translation id="7456847797759667638">باز کردن مکان...</translation>
<translation id="7461924472993315131">پین</translation>
<translation id="7463006580194749499">افزودن شخص</translation>
-<translation id="7464902436585505072">‏مدل صوتی «Ok Google»</translation>
<translation id="7465778193084373987">‏نشانی وب ابطال گواهی Netscape</translation>
<translation id="7469894403370665791">اتصال به این شبکه به صورت خودکار</translation>
<translation id="747114903913869239">خطا: رمزگشایی برنامهٔ افزودنی ممکن نیست</translation>
@@ -4277,6 +4286,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> و داده‌های مرتبط با آن از این دستگاه برداشته می‌شود.</translation>
<translation id="7497215489070763236">گواهینامه مرکز صدور گواهی سرور</translation>
<translation id="7497981768003291373">‏هیچ گزارش نوشتاری WebRTC که اخیراً ثبت شده باشد ندارید.</translation>
+<translation id="7502199377020483660">‏برای استفاده از این کارت‌ها در همه دستگاه‌هایتان، آن‌ها را در حساب Google خود ذخیره کنید</translation>
<translation id="7502658306369382406">‏نشانی IPv6</translation>
<translation id="7503191893372251637">‏نوع گواهی Netscape</translation>
<translation id="7503821294401948377">بارگیری نماد "<ph name="ICON" />" برای عملکرد مرورگر ممکن نیست.</translation>
@@ -4374,6 +4384,7 @@
<translation id="7663719505383602579">گیرنده: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">دستگاه بلوتوث پشتیبانی نشده: «<ph name="DEVICE_NAME" />».</translation>
<translation id="7665369617277396874">افزودن حساب</translation>
+<translation id="7667248760110172428">فضای ذخیره‌سازی خارجی</translation>
<translation id="7671130400130574146">استفاده از نوار عنوان سیستم و مرزها</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />، در <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">‏صدایتان را برای Google ارسال کنید تا بتوانید هر فیلد نوشتاری را با دیکته کردن پر کنید.</translation>
@@ -4577,6 +4588,7 @@
<translation id="7930294771522048157">روش‌های پرداخت ذخیره‌شده در اینجا نشان داده می‌شود</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> درحال اشتراک‌گذاری صفحه و صوت شماست.</translation>
<translation id="7931318309563332511">ناشناس</translation>
+<translation id="7932969338829957666">‏پوشه‌های اشتراک‌گذاری‌شده در Linux در <ph name="BASE_DIR" /> دردسترس است.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{باصدا کردن سایت}one{باصدا کردن سایت‌ها}other{باصدا کردن سایت‌ها}}</translation>
<translation id="7934414805353235750">‏<ph name="URL" /> می‌خواهد محتوای محافظت‌شده را پخش کند. Google هویت دستگاهتان را به تأیید می‌رساند.</translation>
<translation id="793531125873261495">هنگام بارگیری دستگاه مجازی خطایی روی داد. لطفاً دوباره امتحان کنید.</translation>
@@ -4668,6 +4680,7 @@
<translation id="8049705080247101012">‏‫Google‏ «<ph name="EXTENSION_NAME" />» را به عنوان برنامه مخرب پرچم‌‌گذاری کرده است و از نصب آن جلوگیری شده است</translation>
<translation id="8049913480579063185">نام برنامه افزودنی</translation>
<translation id="8050038245906040378">‏امضای کد تجاری Microsoft</translation>
+<translation id="8052887694493382350">‏این فایل برای رایانه‌ای که از نرم‌افزار Windows استفاده می‌کند طراحی شده است. این فایل با دستگاه شما که سیستم‌عامل Chrome را اجرا می‌کند سازگار نیست. <ph name="BEGIN_LINK_HELP" />بیشتر بدانید<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">‏فایل‌های PKCS #12</translation>
<translation id="8053390638574070785">تازه سازی این صفحه</translation>
<translation id="8054517699425078995">این نوع فایل می‌تواند به دستگاه شما آسیب برساند. با این حال می‌خواهید <ph name="FILE_NAME" /> را نگه دارید؟</translation>
@@ -4911,6 +4924,7 @@
<translation id="8438566539970814960">بهبود جستجوها و مرور</translation>
<translation id="8439506636278576865">ترجمه صفحات نوشته شده به این زبان پیشنهاد داده شود</translation>
<translation id="8440630305826533614">‏برنامه‌های Linux</translation>
+<translation id="8443338615972234259">لطفاً همین حالا حساب کاربری جدیدی برای کاربر تحت‌نظارت ایجاد کنید.</translation>
<translation id="8446884382197647889">بیشتر بیاموزید</translation>
<translation id="8447409163267621480">‏باید شامل Ctrl یا Alt باشد</translation>
<translation id="8448729345478502352">بزرگ‌تر با کوچک‌تر کردن موارد روی صفحه</translation>
@@ -4935,6 +4949,7 @@
<translation id="8468750959626135884">‏قفل <ph name="DEVICE_TYPE" /> خود را با تلفن Android خود باز کنید.</translation>
<translation id="8470028084415844044">برای اینکه همه گذرواژه‌هایتان را در همه دستگاه‌ها دریافت کنید، همگام‌سازی را روشن کنید.</translation>
<translation id="8470513973197838199">گذرواژه‌های ذخیره‌شده برای <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">‏برای استفاده از این کارت در همه دستگاه‌هایتان، آن را در حساب Google خود ذخیره کنید</translation>
<translation id="8472623782143987204">سخت‌افزار پشتیبانی</translation>
<translation id="8473863474539038330">نشانی‌ها و سایر موارد</translation>
<translation id="8475313423285172237">‏برنامه‌ای دیگر بر روی رایانه شما یک برنامه افزودنی را اضافه کرده است که ممکن است نحوه کارکرد Chrome را تغییر دهد.</translation>
@@ -5010,7 +5025,6 @@
<translation id="8598453409908276158">افزایه خارج از جعبه ایمنی مسدود شد</translation>
<translation id="8601206103050338563">‏راستی‌آزمایی سرویس گیرنده TLS WWW</translation>
<translation id="8602851771975208551">‏برنامه‌ای دیگر بر روی رایانه شما یک برنامه را اضافه کرده است که ممکن است نحوه کارکرد Chrome را تغییر دهد.</translation>
-<translation id="8604763363205185560">‏کمک به بهبود Chrome و امنیت آن</translation>
<translation id="8605428685123651449">‏حافظه SQLite</translation>
<translation id="8606726445206553943">‏استفاده از دستگاه‌های MIDI شما</translation>
<translation id="8609465669617005112">انتقال به بالا</translation>
@@ -5186,6 +5200,7 @@
<translation id="8846141544112579928">در حال جستجو برای صفحه‌کلید...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">‏وقتی دستگاه‌هایتان را متصل می‌کنید، موافقت می‌کنید Chromebook بتواند:</translation>
+<translation id="8850251000316748990">دیدن موارد بیشتر...</translation>
<translation id="8859057652521303089">انتخاب زبان:</translation>
<translation id="8859174528519900719">قاب فرعی: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">‏صفحه‌گسترده Excel </translation>
diff --git a/chromium/chrome/app/resources/generated_resources_fi.xtb b/chromium/chrome/app/resources/generated_resources_fi.xtb
index 608e432c60d..133bdf8801a 100644
--- a/chromium/chrome/app/resources/generated_resources_fi.xtb
+++ b/chromium/chrome/app/resources/generated_resources_fi.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Ota teema käyttöön</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Näytä Chrome Web Storessa</translation>
-<translation id="1761588866118490543">Äänimalli</translation>
<translation id="176193854664720708">Sormenjälkitunnistin on virtapainikkeessa. Kosketa sitä kevyesti millä tahansa sormella.</translation>
<translation id="1763046204212875858">Luo sovelluspikakuvakkeita</translation>
<translation id="1763108912552529023">Jatka tutkimista</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Lähetä käyttö- ja diagnostiikkadataa. Laite lähettää tällä hetkellä diagnostiikkadataa sekä laitteen ja sovellusten käyttödataa automaattisesti Googlelle. Datan avulla parannetaan esimerkiksi järjestelmän ja sovellusten vakautta. Kootusta datasta on hyötyä myös Googlen sovelluksille ja kumppaneille, kuten Android-kehittäjille. Omistaja on ottanut tämän asetuksen käyttöön. Jos olet ottanut käyttöön muun verkko- ja sovellustoiminnan asetuksen, tätä dataa voidaan tallentaa Google-tilillesi. <ph name="BEGIN_LINK1" />Lue lisää<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip-arkisto</translation>
<translation id="220858061631308971">Syötä tämä PIN-koodi laitteella <ph name="DEVICE_NAME" />:</translation>
+<translation id="2213140827792212876">Poista jakaminen</translation>
+<translation id="2214018885812055163">Jaetut kansiot</translation>
<translation id="2214884991347062907">Väärä salasana. Yritä uudelleen.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 riviä ei näytetä&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> riviä ei näytetä&gt;}}</translation>
<translation id="2217501013957346740">Luo nimi –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Varmenne on pidossa</translation>
<translation id="2501797496290880632">Syötä pikanäppäin</translation>
<translation id="2502441965851148920">Automaattiset päivitykset ovat käytössä, mutta järjestelmänvalvoja on estänyt manuaaliset päivitykset.</translation>
+<translation id="2505127913256479918">Tämä valvottu tili poistetaan pian</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Näyttö #}other{Näyttö #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> / <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Kauppa ‑tili</translation>
@@ -1376,6 +1378,7 @@
<translation id="304747341537320566">Puhemoottorit</translation>
<translation id="3053013834507634016">Varmenteen avaimen käyttö</translation>
<translation id="3057861065630527966">Varmuuskopioi valokuvasi ja videosi.</translation>
+<translation id="3058498974290601450">Voit ottaa synkronoinnin käyttöön milloin tahansa asetuksista.</translation>
<translation id="3060379269883947824">Ota käyttöön Teksti puhuttuna</translation>
<translation id="3061707000357573562">Virheenkorjauspalvelu</translation>
<translation id="3065041951436100775">Välilehti sulki palautesivun.</translation>
@@ -1567,6 +1570,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> asennetaan.</translation>
<translation id="3380365263193509176">Tuntematon virhe</translation>
<translation id="3382073616108123819">Hups! Järjestelmä ei onnistunut määrittämään tämän laitteen laitetunnisteita.</translation>
+<translation id="3382086682569279540">Ylläpitämäsi tili poistetaan pian</translation>
<translation id="3382200254148930874">Lopetetaan valvontaa...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Erotin</translation>
@@ -1747,8 +1751,8 @@
<translation id="3636096452488277381">Heipä hei, <ph name="USER_GIVEN_NAME" />!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> % – <ph name="TIME" /> jäljellä</translation>
<translation id="3637682276779847508">SIM-korttisi poistetaan käytöstä pysyvästi, jos et anna oikeaa PUK-koodia.</translation>
-<translation id="363863692969456324">Korjaa kirjoitusvirheet parannetulla oikeinkirjoituksen tarkistuksella</translation>
<translation id="3640214691812501263">Lisätäänkö <ph name="EXTENSION_NAME" /> käyttäjälle <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Opeta Assistant tunnistamaan äänesi</translation>
<translation id="3644896802912593514">Leveys</translation>
<translation id="3645372836428131288">Liikuta sormeasi hieman, niin sormenjäljen toinen osa tallennetaan.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> havaittiin</translation>
@@ -2145,7 +2149,6 @@
<translation id="4244238649050961491">Hae lisää näyttökynäsovelluksia</translation>
<translation id="424546999567421758">Kohde käyttää paljon levytilaa</translation>
<translation id="424726838611654458">Avaa aina Adobe Readerissa</translation>
-<translation id="4247330672018280062">Kenttiin kirjoittamasi teksti lähetetään Googlelle</translation>
<translation id="4247901771970415646">Synkronointi tilille <ph name="USERNAME" /> epäonnistui</translation>
<translation id="4249248555939881673">Odotetaan verkkoyhteyttä…</translation>
<translation id="4249373718504745892">Tältä sivulta on estetty kameran ja mikrofonin käyttö.</translation>
@@ -2487,6 +2490,7 @@
<translation id="4821935166599369261">&amp;Profilointi on käytössä</translation>
<translation id="4823484602432206655">Lukea ja muokata käyttäjän ja laitteen asetuksia.</translation>
<translation id="4823651846660089135">Laite on vain luku ‑tilassa.</translation>
+<translation id="4824958205181053313">Peruutetaanko synkronointi?</translation>
<translation id="4827675678516992122">Ei yhteyttä</translation>
<translation id="4828937774870308359">Australialainen</translation>
<translation id="4829768588131278040">Määritä PIN-koodi</translation>
@@ -2869,6 +2873,7 @@
<translation id="5374359983950678924">Vaihda kuva</translation>
<translation id="5376169624176189338">Siirry taaksepäin klikkaamalla, tarkastele historiaa pitämällä alhaalla</translation>
<translation id="5376931455988532197">Tiedosto on liian suuri</translation>
+<translation id="5377594097385838788">Incognito</translation>
<translation id="537813040452600081">Tässä ikkunassa katselemiasi sivuja ei lisätä selaushistoriaan, eikä niistä jää tietokoneelle muita jälkiä, kuten evästeitä, kirjauduttuasi ulos. Lataamiasi tiedostoja ja luomiasi kirjanmerkkejä ei tallenneta.</translation>
<translation id="5379140238605961210">Estä edelleen mikrofonin käyttö</translation>
<translation id="5379268888377976432">Kumoa poisto</translation>
@@ -2890,6 +2895,7 @@
<translation id="5414566801737831689">Käyttää selaamiesi sivustojen kuvakkeita</translation>
<translation id="5417312524372586921">Selainteemat</translation>
<translation id="5419294236999569767">Järjestelmän aika</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Määrittää tekstin ja kuvien terävyyden</translation>
<translation id="5422221874247253874">Tukiasema</translation>
<translation id="5422781158178868512">Ulkoista tallennuslaitettasi ei tunnistettu.</translation>
@@ -2910,6 +2916,7 @@
<translation id="5434065355175441495">PKCS #1 RSA-salaus</translation>
<translation id="5436492226391861498">Odotetaan välityspalvelintunnelia...</translation>
<translation id="5436510242972373446">Haku sivustosta <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Tallenna tiedostot ja luo uusi tili.</translation>
<translation id="5438224778284622050">Poistetaanko offline-tiedostot?</translation>
<translation id="544083962418256601">Luo pikakuvakkeita...</translation>
<translation id="5442228125690314719">Näköistiedoston luominen epäonnistui. Yritä uudelleen.</translation>
@@ -3283,6 +3290,8 @@ Julkinen eksponentti (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bittiä):
<translation id="5965661248935608907">Määrittää myös Etusivu-painikkeella avattavan sivun ja omnibox-hakujen aloitussivun.</translation>
<translation id="5971037678316050792">Hallinnoida Bluetooth-sovittimen tilaa ja laiteparin muodostusta.</translation>
<translation id="5972017421290582825">Hallinnoi MIDI-asetuksia…</translation>
+<translation id="597235323114979258">Katso lisää kohteita</translation>
+<translation id="5972666587303800813">Automatisoitu palvelu</translation>
<translation id="5972708806901999743">Siirrä alkuun</translation>
<translation id="5972826969634861500">Käynnistä <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Akun varaus prosentteina</translation>
@@ -3655,6 +3664,7 @@ Julkinen eksponentti (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bittiä):
<translation id="6527303717912515753">Jaa</translation>
<translation id="6528513914570774834">Anna muiden laitteen käyttäjien käyttää tätä verkkoa</translation>
<translation id="652948702951888897">Chromen historia</translation>
+<translation id="6530186581263215931">Järjestelmänvalvojasi on ottanut nämä asetukset käyttöön</translation>
<translation id="653019979737152879">Synkronoidaan kohdetta <ph name="FILE_NAME" />…</translation>
<translation id="6531282281159901044">Pidä haitallinen tiedosto</translation>
<translation id="6532101170117367231">Tallenna Google Driveen</translation>
@@ -3973,7 +3983,6 @@ Julkinen eksponentti (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bittiä):
<translation id="7018275672629230621">Lukea ja muokata selaushistoriaasi</translation>
<translation id="7019805045859631636">Nopea</translation>
<translation id="7022562585984256452">Etusivusi on asetettu.</translation>
-<translation id="702384510542929236">Lähettää joitain järjestelmän tietoja ja sivujen sisältöjä Googlelle anonyymisti</translation>
<translation id="7025190659207909717">Mobiilitiedonsiirtopalvelun hallinta</translation>
<translation id="7027125358315426638">Tietokannan nimi:</translation>
<translation id="7029809446516969842">Salasanat</translation>
@@ -4153,6 +4162,7 @@ Julkinen eksponentti (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bittiä):
<translation id="7289225569524511578">Avaa taustakuvasovellus.</translation>
<translation id="7290242001003353852">Tämä kirjautumispalvelu, jota isännöi <ph name="SAML_DOMAIN" />, käyttää kameraasi.</translation>
<translation id="7290594223351252791">Vahvista rekisteröityminen</translation>
+<translation id="7292696521213967957">Assistantin viankorjaustiedot</translation>
<translation id="7295662345261934369">Jaa muille</translation>
<translation id="729583233778673644">Salli AES- ja RC4-salaus. Tämä valinta lisää riskejä, koska RC4-salaustekniikat ovat suojaamattomia.</translation>
<translation id="7296774163727375165">Verkkotunnuksen <ph name="DOMAIN" /> käyttöehdot</translation>
@@ -4253,7 +4263,6 @@ Julkinen eksponentti (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bittiä):
<translation id="7456847797759667638">Avaa sijainti...</translation>
<translation id="7461924472993315131">Kiinnitä</translation>
<translation id="7463006580194749499">Lisää käyttäjä</translation>
-<translation id="7464902436585505072">OK Google -puhemalli</translation>
<translation id="7465778193084373987">Netscape-varmenteen kumoamis-URL</translation>
<translation id="7469894403370665791">Yhdistä automaattisesti tähän verkkoon</translation>
<translation id="747114903913869239">Virhe: laajennuksen koodauksen purkaminen ei onnistunut</translation>
@@ -4281,6 +4290,7 @@ Julkinen eksponentti (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bittiä):
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> ja siihen yhdistetyt tiedot poistetaan tältä laitteelta.</translation>
<translation id="7497215489070763236">Palvelimen CA-varmenne</translation>
<translation id="7497981768003291373">Sinulla ei ole äskettäin tallennettuja WebRTC-tekstilokeja.</translation>
+<translation id="7502199377020483660">Tallenna kortit Google-tilillesi, niin voit käyttää niitä kaikilla laitteillasi.</translation>
<translation id="7502658306369382406">IPv6-osoite</translation>
<translation id="7503191893372251637">Netscape-varmennetyyppi</translation>
<translation id="7503821294401948377">Kuvakkeen <ph name="ICON" /> lataaminen selaintoimintoa varten epäonnistui.</translation>
@@ -4378,6 +4388,7 @@ Julkinen eksponentti (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bittiä):
<translation id="7663719505383602579">Vastaanottaja: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Tukematon Bluetooth-laite: <ph name="DEVICE_NAME" />.</translation>
<translation id="7665369617277396874">Lisää tili</translation>
+<translation id="7667248760110172428">Ulkoinen tallennustila</translation>
<translation id="7671130400130574146">Käytä järjestelmän otsikkoriviä ja reunoja</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> (<ph name="PAGE_TITLE" />)</translation>
<translation id="7676867886086876795">Lähetä äänesi Googlelle, jotta sanelu on mahdollista kaikissa tekstikentissä.</translation>
@@ -4580,6 +4591,7 @@ Julkinen eksponentti (<ph name="PUBLIC_EXPONENT_NUM_BITS" /> bittiä):
<translation id="7930294771522048157">Tallennetut maksutavat näkyvät täällä</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> jakaa näyttösi ja äänesi.</translation>
<translation id="7931318309563332511">Tuntematon</translation>
+<translation id="7932969338829957666">Jaettujen kansioiden sijainti Linuxissa: <ph name="BASE_DIR" /></translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Poista sivuston mykistys}other{Poista sivustojen mykistys}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> yrittää toistaa suojattua sisältöä. Google vahvistaa laitteesi tunnistetiedot.</translation>
<translation id="793531125873261495">Virtuaalikoneen lataus epäonnistui. Yritä uudelleen.</translation>
@@ -4671,6 +4683,7 @@ Tallenna avaintiedosto suojattuun sijaintiin. Tarvitset sitä, jos haluat luoda
<translation id="8049705080247101012"><ph name="EXTENSION_NAME" /> on Googlen haitalliseksi merkitsemä, joten sen asennus on estetty.</translation>
<translation id="8049913480579063185">Laajennuksen nimi</translation>
<translation id="8050038245906040378">Microsoftin kaupallinen koodin allekirjoitus</translation>
+<translation id="8052887694493382350">Tämä tiedosto on tarkoitettu tietokoneelle, joka käyttää Windowsia. Se ei ole yhteensopiva Chrome-käyttöjärjestelmää käyttävän laitteesi kanssa. <ph name="BEGIN_LINK_HELP" />Lue lisää<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 -tiedostot</translation>
<translation id="8053390638574070785">Lataa tämä sivu uudelleen</translation>
<translation id="8054517699425078995">Tämäntyyppinen tiedosto voi vahingoittaa laitettasi. Haluatko silti säilyttää tiedoston <ph name="FILE_NAME" />?</translation>
@@ -4914,6 +4927,7 @@ Tallenna avaintiedosto suojattuun sijaintiin. Tarvitset sitä, jos haluat luoda
<translation id="8438566539970814960">Paranna hakuja ja selausta</translation>
<translation id="8439506636278576865">Tarjoudu kääntämään sivuja tälle kielelle</translation>
<translation id="8440630305826533614">Linux-sovellukset</translation>
+<translation id="8443338615972234259">Luo valvotulle käyttäjälle uusi tili.</translation>
<translation id="8446884382197647889">Lisätietoja</translation>
<translation id="8447409163267621480">Lisää alkuun joko Ctrl tai Alt</translation>
<translation id="8448729345478502352">Pienennä tai suurenna näytöllä näkyviä kohteita</translation>
@@ -4938,6 +4952,7 @@ Tallenna avaintiedosto suojattuun sijaintiin. Tarvitset sitä, jos haluat luoda
<translation id="8468750959626135884">Avaa <ph name="DEVICE_TYPE" /> Android-puhelimellasi.</translation>
<translation id="8470028084415844044">Ota synkronointi käyttöön, niin voit käyttää salasanojasi kaikilla laitteilla.</translation>
<translation id="8470513973197838199">Tallennetut salasanat: <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Tallenna kortti Google-tilillesi, niin voit käyttää sitä kaikilla laitteillasi.</translation>
<translation id="8472623782143987204">laitteiston tukema</translation>
<translation id="8473863474539038330">Osoitteet ja muita tietoja</translation>
<translation id="8475313423285172237">Toinen tietokoneellasi oleva ohjelma lisäsi laajennuksen, joka voi muuttaa Chromen toimintaa.</translation>
@@ -5013,7 +5028,6 @@ Tallenna avaintiedosto suojattuun sijaintiin. Tarvitset sitä, jos haluat luoda
<translation id="8598453409908276158">Ei hiekkalaatikossa toimiva laajennus estetty</translation>
<translation id="8601206103050338563">TLS WWW -palvelimen todennus</translation>
<translation id="8602851771975208551">Toinen tietokoneellasi oleva ohjelma lisäsi sovelluksen, joka voi muuttaa Chromen toimintaa.</translation>
-<translation id="8604763363205185560">Auta parantamaan Chromea ja sen turvallisuutta</translation>
<translation id="8605428685123651449">SQLiten käyttämä muisti</translation>
<translation id="8606726445206553943">Käyttää MIDI-laitteitasi.</translation>
<translation id="8609465669617005112">Siirrä ylös</translation>
@@ -5189,6 +5203,7 @@ Tallenna avaintiedosto suojattuun sijaintiin. Tarvitset sitä, jos haluat luoda
<translation id="8846141544112579928">Näppäimistöä etsitään…</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Yhdistämällä laitteet annat Chromebookille seuraavat oikeudet:</translation>
+<translation id="8850251000316748990">Katso lisää…</translation>
<translation id="8859057652521303089">Valitse kieli:</translation>
<translation id="8859174528519900719">Alakehys: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel-laskentataulukko</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_fil.xtb b/chromium/chrome/app/resources/generated_resources_fil.xtb
index b131bb5520f..f65d91dfa36 100644
--- a/chromium/chrome/app/resources/generated_resources_fil.xtb
+++ b/chromium/chrome/app/resources/generated_resources_fil.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Paganahin ang tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Tingnan sa Chrome Web Store</translation>
-<translation id="1761588866118490543">Voice model</translation>
<translation id="176193854664720708">Nasa power button ang sensor para sa fingerprint. Pundutin ito nang magaan gamit ang alinmang daliri.</translation>
<translation id="1763046204212875858">Gumawa ng mga shortcut ng application</translation>
<translation id="1763108912552529023">Magpatuloy sa pag-explore</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Magpadala ng data ng paggamit at diagnostic na data. Sa kasalukuyan, ang device na ito ay awtomatikong nagpapadala ng diagnostic na data, data ng device, at data ng paggamit sa app sa Google. Makakatulong ito sa stability ng system at ng app, at sa iba pang pagpapahusay. Makakatulong din ang ilang pinagsama-samang data sa mga app at partner ng Google, gaya ng mga developer ng Android. Ipinapatupad ng may-ari ang setting na ito. Kung naka-on ang iyong karagdagang setting ng Aktibidad sa Web at App, maaaring ma-save ang data na ito sa Google Account mo. <ph name="BEGIN_LINK1" />Matuto Pa<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip archive</translation>
<translation id="220858061631308971">Pakilagay ang PIN code na ito sa "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Alisin ang pagbabahagi</translation>
+<translation id="2214018885812055163">Mga nakabahaging folder</translation>
<translation id="2214884991347062907">Maling password, subukang muli</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 linya ang hindi ipinapakita&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> linya ang hindi ipinapakita&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> (na) linya ang hindi ipinapakita&gt;}}</translation>
<translation id="2217501013957346740">Gumawa ng pangalan -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Naka-hold na Certificate</translation>
<translation id="2501797496290880632">Mag-type ng shortcut</translation>
<translation id="2502441965851148920">Naka-enable ang mga awtomatikong update. Na-disable ng iyong administrator ang mga manu-manong update.</translation>
+<translation id="2505127913256479918">Malapit nang alisin ang sinusubaybayang account na ito</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Screen #}one{Screen #}other{Screen #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> ng <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Store Account</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Mga Engine sa Pagsasalita</translation>
<translation id="3053013834507634016">Paggamit ng Certificate Key </translation>
<translation id="3057861065630527966">I-back up ang iyong mga larawan at video</translation>
+<translation id="3058498974290601450">Maaari mong i-on ang pag-sync anumang oras sa mga setting.</translation>
<translation id="3060379269883947824">I-enable ang Select to Speak</translation>
<translation id="3061707000357573562">Serbisyo sa Pag-patch</translation>
<translation id="3065041951436100775">Feedback na isinara ang tab</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015">Ang <ph name="PRODUCT_NAME" /> ay maiinstall.</translation>
<translation id="3380365263193509176">Hindi kilalang error</translation>
<translation id="3382073616108123819">Oops! Hindi nakatukoy ang system ng mga identifier ng device para sa device na ito.</translation>
+<translation id="3382086682569279540">Malapit nang alisin ang pinapamahalaan mong account</translation>
<translation id="3382200254148930874">Inihihinto ang pagsubaybay...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separator</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Kamusta, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> na lang ang natitira</translation>
<translation id="3637682276779847508">Permanenteng madi-disable ang iyong SIM card kung hindi mo mailalagay ang tamang PIN Unlock Key.</translation>
-<translation id="363863692969456324">Mag-ayos ng mga error sa spelling sa pamamagitan ng pinahusay na pang-check ng spelling</translation>
<translation id="3640214691812501263">Idagdag ang "<ph name="EXTENSION_NAME" />" para sa <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Turuan ang iyong Assistant na makilala ang boses mo</translation>
<translation id="3644896802912593514">Lapad</translation>
<translation id="3645372836428131288">Gumalaw nang bahagya para mag-capture ng ibang bahagi ng fingerprint.</translation>
<translation id="3648348069317717750">Natukoy ang <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Maghanap ng higit pang app ng stylus</translation>
<translation id="424546999567421758">Natukoy ang mataas na paggamit ng disk</translation>
<translation id="424726838611654458">Palaging buksan sa Adobe Reader</translation>
-<translation id="4247330672018280062">Ipapadala sa Google ang text na ita-type mo sa mga field ng text</translation>
<translation id="4247901771970415646">Hindi ma-sync sa <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Naghihintay ng koneksyon sa network...</translation>
<translation id="4249373718504745892">Na-block ang pahinang ito sa pag-access ng iyong camera at mikropono.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Pinagana ang Pag-profile</translation>
<translation id="4823484602432206655">Basahin at baguhin ang mga setting ng user at device</translation>
<translation id="4823651846660089135">Read-only ang device</translation>
+<translation id="4824958205181053313">Kanselahin ang pag-sync?</translation>
<translation id="4827675678516992122">Hindi makakonekta</translation>
<translation id="4828937774870308359">Australian</translation>
<translation id="4829768588131278040">Mag-set up ng PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Palitan ang larawan</translation>
<translation id="5376169624176189338">I-click upang bumalik, pindutin nang matagal upang makita ang history</translation>
<translation id="5376931455988532197">Masyadong malaki ang file</translation>
+<translation id="5377594097385838788">Incognito</translation>
<translation id="537813040452600081">Hindi lalabas sa history ng browser ang mga page na tiningnan mo sa window na ito at hindi mag-iiwan ang mga ito ng iba pang mga palatandaan, tulad ng cookies, sa computer pagkatapos mong mag-sign out. Hindi papanatilihin ang iyong mga na-download na file at ginawang bookmark.</translation>
<translation id="5379140238605961210">Magpatuloy sa pag-block ng access sa mikropono</translation>
<translation id="5379268888377976432">I-undo ang pagtanggal</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Basahin ang mga icon ng mga website na iyong binibisita</translation>
<translation id="5417312524372586921">Mga tema ng browser</translation>
<translation id="5419294236999569767">Oras sa system</translation>
+<translation id="5419405654816502573">Voice match</translation>
<translation id="5420438158931847627">Tumutukoy sa sharpness ng text at mga larawan</translation>
<translation id="5422221874247253874">Access Point</translation>
<translation id="5422781158178868512">Paumanhin, hindi makilala ang iyong panlabas na device sa storage.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 RSA Encryption</translation>
<translation id="5436492226391861498">Naghihintay para sa proxy tunnel...</translation>
<translation id="5436510242972373446">Hanapan ang <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Paki-save ang iyong mga file at gumawa ng bagong account ngayon.</translation>
<translation id="5438224778284622050">Gusto mo bang i-delete ang mga offline na file?</translation>
<translation id="544083962418256601">Lumikha ng mga shortcut...</translation>
<translation id="5442228125690314719">Nagkaroon ng error sa paggawa ng larawan ng disk. Pakisubukang muli.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">Kinokontrol din nito kung anong pahina ang ipinapakita kapag na-click mo ang button ng Home o naghanap mula sa Omnibox.</translation>
<translation id="5971037678316050792">Kontrolin ang estado at pagpapares ng Bluetooth adapter</translation>
<translation id="5972017421290582825">Pamahalaan ang mga setting ng MIDI...</translation>
+<translation id="597235323114979258">Tumingin pa ng mga destinasyon</translation>
+<translation id="5972666587303800813">No-op na Serbisyo</translation>
<translation id="5972708806901999743">Ilipat sa itaas</translation>
<translation id="5972826969634861500">Simulan ang <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Porsyento ng Charge ng Baterya</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">Ibahagi</translation>
<translation id="6528513914570774834">Payagan ang iba pang user ng device na ito na gamitin ang network na ito</translation>
<translation id="652948702951888897">History sa Chrome</translation>
+<translation id="6530186581263215931">Ipinapatupad ng iyong administrator ang mga setting na ito</translation>
<translation id="653019979737152879">Sini-sync ang <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Panatilihin ang mapanganib na file</translation>
<translation id="6532101170117367231">I-save sa Google Drive</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">Basahin at baguhin ang iyong history ng pagba-browse</translation>
<translation id="7019805045859631636">Mabilis</translation>
<translation id="7022562585984256452">Naitakda na ang iyong home page.</translation>
-<translation id="702384510542929236">Anonymous na nagpapadala ng ilang impormasyon ng system at content ng page sa Google</translation>
<translation id="7025190659207909717">Pamamahala sa serbisyo ng data ng mobile</translation>
<translation id="7027125358315426638">Pangalan ng database:</translation>
<translation id="7029809446516969842">Mga Password</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">Buksan ang wallpaper app</translation>
<translation id="7290242001003353852">Ina-access ng serbisyo sa pag-sign in na ito, na hino-host ng <ph name="SAML_DOMAIN" />, ang iyong camera.</translation>
<translation id="7290594223351252791">Kumpirmahin ang pagpaparehistro</translation>
+<translation id="7292696521213967957">Impormasyon para i-debug ang Assistant</translation>
<translation id="7295662345261934369">Ibahagi sa iba</translation>
<translation id="729583233778673644">Payagan ang AES at RC4 encryption. Magiging mas mapanganib para sa iyo kapag ginamit ang opsyong ito, dahil hindi secure ang mga RC4 cipher.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> Mga Tuntunin</translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">Buksan ang Lokasyon...</translation>
<translation id="7461924472993315131">I-pin</translation>
<translation id="7463006580194749499">Magdagdag ng tao</translation>
-<translation id="7464902436585505072">Voice model na "Ok Google"</translation>
<translation id="7465778193084373987">URL ng Pagpapawalang-bisa ng Netscape Certificate</translation>
<translation id="7469894403370665791">Awtomatikong kumonekta sa network na ito</translation>
<translation id="747114903913869239">Error: Hindi magawang i-decode ang extension</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424">Aalisin sa device na ito ang <ph name="LINUX_APP_NAME" /> at ang data na nauugnay rito.</translation>
<translation id="7497215489070763236">CA certificate ng server</translation>
<translation id="7497981768003291373">Wala kang kamakailang nakuhang log ng text ng WebRTC.</translation>
+<translation id="7502199377020483660">Para magamit ang mga card na ito sa lahat ng iyong device, i-save ang mga ito sa Google Account mo</translation>
<translation id="7502658306369382406">IPv6 address</translation>
<translation id="7503191893372251637">Uri ng Netscape Certificate</translation>
<translation id="7503821294401948377">Maaaring hindi mai-load ang icon na '<ph name="ICON" />' para sa pagkilos ng browser.</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">Tatanggap: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Hindi sinusuportahang Bluetooth device: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Magdagdag ng account</translation>
+<translation id="7667248760110172428">External na storage</translation>
<translation id="7671130400130574146">Gumamit ng system title bar at mga hangganan</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, sa <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Ipinapadala ang iyong boses sa Google para mabigyang-daan ang dictation sa anumang field ng text.</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">Lalabas dito ang mga naka-save na paraan ng pagbabayad</translation>
<translation id="79312157130859720">Ibinabahagi ng <ph name="APP_NAME" /> ang iyong screen at audio.</translation>
<translation id="7931318309563332511">Hindi Alam</translation>
+<translation id="7932969338829957666">Available ang mga nakabahaging folder sa Linux sa <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{I-unmute ang Site}one{I-unmute ang Mga Site}other{I-unmute ang Mga Site}}</translation>
<translation id="7934414805353235750">Gusto ng <ph name="URL" /> na mag-play ng pinoprotektahang content. Ive-veify ng Google ang pagkakakilanlan ng iyong device.</translation>
<translation id="793531125873261495">Nagkaroon ng error sa pag-download ng virtual machine. Pakisubukang muli.</translation>
@@ -4672,6 +4684,7 @@ Ilagay ang iyong key file sa ligtas na lugar. Kailangan mo ito upang lumikha ng
<translation id="8049705080247101012">Na-flag ng Google ang "<ph name="EXTENSION_NAME" />" bilang nakakahamak at pinigilan ang pag-install</translation>
<translation id="8049913480579063185">Pangalan ng Extension</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">Idinisenyo ang file na ito para sa PC na gumagamit ng Windows software. Hindi ito compatible sa iyong device na tumatakbo sa Chrome OS. <ph name="BEGIN_LINK_HELP" />Matuto Pa<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Mga PKCS #12 File</translation>
<translation id="8053390638574070785">Reload This Page</translation>
<translation id="8054517699425078995">Maaaring mapinsala ng ganitong uri ng file ang iyong device. Gusto mo pa rin bang panatilihin ang <ph name="FILE_NAME" />?</translation>
@@ -4916,6 +4929,7 @@ Ilagay ang iyong key file sa ligtas na lugar. Kailangan mo ito upang lumikha ng
<translation id="8439506636278576865">Mag-alok na magsalin ng mga page sa wikang ito
</translation>
<translation id="8440630305826533614">Mga Linux app</translation>
+<translation id="8443338615972234259">Gumawa ng bagong account para sa iyong pinangangasiwaang user ngayon.</translation>
<translation id="8446884382197647889">Matuto nang Higit Pa</translation>
<translation id="8447409163267621480">Isama ang Ctrl o Alt</translation>
<translation id="8448729345478502352">Paliitin o palakihin ang mga item sa iyong screen</translation>
@@ -4940,6 +4954,7 @@ Ilagay ang iyong key file sa ligtas na lugar. Kailangan mo ito upang lumikha ng
<translation id="8468750959626135884">I-unlock ang iyong <ph name="DEVICE_TYPE" /> gamit ang iyong Android phone.</translation>
<translation id="8470028084415844044">Para mailagay ang lahat ng iyong password sa lahat ng device mo, i-on ang pag-sync.</translation>
<translation id="8470513973197838199">Mga naka-save na password para sa <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Para magamit ang card na ito sa lahat ng iyong device, i-save ito sa Google Account mo</translation>
<translation id="8472623782143987204">na-hardware-back</translation>
<translation id="8473863474539038330">Mga address at higit pa</translation>
<translation id="8475313423285172237">Ang isa pang program sa iyong computer ay nagdagdag ng extension na maaaring magpabago sa paraan ng paggana ng Chrome.</translation>
@@ -5015,7 +5030,6 @@ Ilagay ang iyong key file sa ligtas na lugar. Kailangan mo ito upang lumikha ng
<translation id="8598453409908276158">Na-block ang hindi naka-sandbox na plugin</translation>
<translation id="8601206103050338563">Pagpapatotoo ng Client sa TLS WWW</translation>
<translation id="8602851771975208551">Ang isa pang program sa iyong computer ay nagdagdag ng app na maaaring magpabago sa paraan ng paggana ng Chrome.</translation>
-<translation id="8604763363205185560">Tumulong na pahusayin ang Chrome at ang seguridad nito</translation>
<translation id="8605428685123651449">Memory ng SQLite</translation>
<translation id="8606726445206553943">Gamitin ang iyong mga MIDI device</translation>
<translation id="8609465669617005112">Lumipat</translation>
@@ -5191,6 +5205,7 @@ Ilagay ang iyong key file sa ligtas na lugar. Kailangan mo ito upang lumikha ng
<translation id="8846141544112579928">Naghahanap ng keyboard...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Kapag ikinonekta mo ang iyong mga device, sumasang-ayon kang magagawa ng iyong Chromebook ang sumusunod:</translation>
+<translation id="8850251000316748990">Tumingin pa...</translation>
<translation id="8859057652521303089">Piliin ang iyong wika:</translation>
<translation id="8859174528519900719">Subframe: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Spreadsheet ng Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_fr.xtb b/chromium/chrome/app/resources/generated_resources_fr.xtb
index b87e4af6609..164ad4d657c 100644
--- a/chromium/chrome/app/resources/generated_resources_fr.xtb
+++ b/chromium/chrome/app/resources/generated_resources_fr.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Activer le thème</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Afficher sur le Chrome Web Store</translation>
-<translation id="1761588866118490543">Empreinte vocale</translation>
<translation id="176193854664720708">Le lecteur d'empreinte digitale est intégré au bouton Marche/Arrêt. Effleurez-le avec n'importe quel doigt.</translation>
<translation id="1763046204212875858">Créer des raccourcis vers des applications</translation>
<translation id="1763108912552529023">Poursuivre la découverte</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Envoyer des données d'utilisation et de diagnostic. À l'heure actuelle, cet appareil envoie automatiquement à Google des données relatives aux diagnostics et à l'utilisation de l'appareil et des applications. Ce processus permettra d'améliorer, entre autres, la stabilité du système et des applications. Certaines données globales seront également utiles aux développeurs des applications Google et à nos partenaires, tels que les développeurs Android. Ce paramètre est appliqué par le propriétaire. Si vous activez le paramètre relatif à l'activité supplémentaire sur le Web et les applications, ces données peuvent être enregistrées dans votre compte Google. <ph name="BEGIN_LINK1" />En savoir plus<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Archive ZIP</translation>
<translation id="220858061631308971">Veuillez saisir le code d'accès de "<ph name="DEVICE_NAME" />" :</translation>
+<translation id="2213140827792212876">Supprimer le partage</translation>
+<translation id="2214018885812055163">Dossiers partagés</translation>
<translation id="2214884991347062907">Mot de passe incorrect, veuillez réessayer</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 ligne non affichée&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> ligne non affichée&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> lignes non affichées&gt;}}</translation>
<translation id="2217501013957346740">Créer un nom</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Certificat en attente</translation>
<translation id="2501797496290880632">Tapez un raccourci</translation>
<translation id="2502441965851148920">Les mises à jour automatiques sont activées. L'administrateur a désactivé les mises à jour manuelles.</translation>
+<translation id="2505127913256479918">Ce compte supervisé sera supprimé prochainement</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Écran #}one{Écran #}other{Écran #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> sur <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Compte Google Play Store</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Moteurs de synthèse vocale</translation>
<translation id="3053013834507634016">Utilisation de la clé du certificat</translation>
<translation id="3057861065630527966">Sauvegarder vos photos et vos vidéos</translation>
+<translation id="3058498974290601450">Vous pouvez activer la synchronisation à tout moment dans les paramètres</translation>
<translation id="3060379269883947824">Activer "Sélectionner pour prononcer"</translation>
<translation id="3061707000357573562">Service d'application de correctifs</translation>
<translation id="3065041951436100775">Commentaires relatifs à l'arrêt de l'onglet</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> va être installé.</translation>
<translation id="3380365263193509176">Erreur inconnue.</translation>
<translation id="3382073616108123819">Petit problème… Impossible de déterminer les identifiants de cet appareil.</translation>
+<translation id="3382086682569279540">Le compte que vous gérez sera bientôt supprimé</translation>
<translation id="3382200254148930874">Arrêt de la supervision...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Séparateur</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Bonjour <ph name="USER_GIVEN_NAME" /></translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> % – <ph name="TIME" /> restantes</translation>
<translation id="3637682276779847508">Votre carte SIM sera définitivement désactivée si vous ne saisissez pas la clé de déblocage du code.</translation>
-<translation id="363863692969456324">Corrigez les fautes d'orthographe avec le correcteur orthographique amélioré</translation>
<translation id="3640214691812501263">Ajouter <ph name="EXTENSION_NAME" /> pour <ph name="USER_NAME" /> ?</translation>
+<translation id="3640613767643722554">Apprendre à l'Assistant à reconnaître votre voix</translation>
<translation id="3644896802912593514">Largeur</translation>
<translation id="3645372836428131288">Déplacez légèrement votre doigt pour enregistrer une autre partie de votre empreinte digitale.</translation>
<translation id="3648348069317717750">L'appareil "<ph name="USB_DEVICE_NAME" />" a été détecté</translation>
@@ -2147,7 +2151,6 @@ Souhaitez-vous lancer <ph name="CONTROL_PANEL_APPLET_NAME" /> ?</translation>
<translation id="4244238649050961491">Trouver plus d'applications de stylet</translation>
<translation id="424546999567421758">Utilisation intensive du disque détectée</translation>
<translation id="424726838611654458">Toujours ouvrir dans Adobe Reader</translation>
-<translation id="4247330672018280062">Le texte que vous saisissez dans les champs sera envoyé à Google</translation>
<translation id="4247901771970415646">Impossible de synchroniser avec <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Connexion réseau en attente…</translation>
<translation id="4249373718504745892">L'accès à votre caméra et à votre micro est bloqué pour cette page</translation>
@@ -2489,6 +2492,7 @@ Souhaitez-vous lancer <ph name="CONTROL_PANEL_APPLET_NAME" /> ?</translation>
<translation id="4821935166599369261">&amp;Profilage activé</translation>
<translation id="4823484602432206655">Consulter et modifier les paramètres d'utilisateur et d'appareil</translation>
<translation id="4823651846660089135">Appareil en lecture seule</translation>
+<translation id="4824958205181053313">Annuler la synchronisation ?</translation>
<translation id="4827675678516992122">Impossible de se connecter</translation>
<translation id="4828937774870308359">Australien</translation>
<translation id="4829768588131278040">Configurer un code</translation>
@@ -2871,6 +2875,7 @@ Souhaitez-vous lancer <ph name="CONTROL_PANEL_APPLET_NAME" /> ?</translation>
<translation id="5374359983950678924">Modifier l'image</translation>
<translation id="5376169624176189338">Cliquer pour revenir en arrière, maintenir pour voir l'historique</translation>
<translation id="5376931455988532197">Fichier trop volumineux.</translation>
+<translation id="5377594097385838788">Navigation privée</translation>
<translation id="537813040452600081">Les pages que vous consultez dans cette fenêtre ne sont pas consignées dans l'historique du navigateur et ne laissent aucune autre trace sur votre ordinateur (des cookies, par exemple), une fois que vous vous êtes déconnecté. Les fichiers téléchargés et vos favoris ne sont pas conservés.</translation>
<translation id="5379140238605961210">Continuer à bloquer l'accès au micro</translation>
<translation id="5379268888377976432">Annuler la suppression</translation>
@@ -2892,6 +2897,7 @@ Souhaitez-vous lancer <ph name="CONTROL_PANEL_APPLET_NAME" /> ?</translation>
<translation id="5414566801737831689">Accéder aux icônes des sites Web que vous consultez</translation>
<translation id="5417312524372586921">Thèmes du navigateur</translation>
<translation id="5419294236999569767">Heure du système</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Détermine la netteté des images et du texte</translation>
<translation id="5422221874247253874">Point d'accès</translation>
<translation id="5422781158178868512">Désolé, impossible de reconnaître votre périphérique de stockage externe.</translation>
@@ -2912,6 +2918,7 @@ Souhaitez-vous lancer <ph name="CONTROL_PANEL_APPLET_NAME" /> ?</translation>
<translation id="5434065355175441495">Chiffrement RSA PKCS #1</translation>
<translation id="5436492226391861498">En attente du tunnel proxy...</translation>
<translation id="5436510242972373446">Rechercher sur <ph name="SITE_NAME" /> :</translation>
+<translation id="543806387003274181">Veuillez enregistrer vos fichiers et créer un compte.</translation>
<translation id="5438224778284622050">Supprimer les fichiers hors connexion ?</translation>
<translation id="544083962418256601">Créer des raccourcis…</translation>
<translation id="5442228125690314719">Erreur lors de la création de l'image disque. Veuillez réessayer.</translation>
@@ -3286,6 +3293,8 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
<translation id="5965661248935608907">Elle contrôle également la page qui s'affiche lorsque vous cliquez sur le bouton Accueil ou lorsque vous effectuez une recherche dans l'omnibox.</translation>
<translation id="5971037678316050792">Contrôler l'état et l'association de l'adaptateur Bluetooth</translation>
<translation id="5972017421290582825">Gérer les paramètres MIDI…</translation>
+<translation id="597235323114979258">Voir plus de destinations</translation>
+<translation id="5972666587303800813">Service expérimental</translation>
<translation id="5972708806901999743">Déplacer vers le haut</translation>
<translation id="5972826969634861500">Lancer <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Pourcentage de chargement de la batterie</translation>
@@ -3656,6 +3665,7 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
<translation id="6527303717912515753">Partager</translation>
<translation id="6528513914570774834">Autoriser les autres utilisateurs de cet appareil à employer ce réseau</translation>
<translation id="652948702951888897">Historique Chrome</translation>
+<translation id="6530186581263215931">Ces paramètres sont appliqués par votre administrateur</translation>
<translation id="653019979737152879">Synchronisation de <ph name="FILE_NAME" /> en cours…</translation>
<translation id="6531282281159901044">Conserver le fichier dangereux</translation>
<translation id="6532101170117367231">Enregistrer sur Google Drive</translation>
@@ -3974,7 +3984,6 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
<translation id="7018275672629230621">Accéder à votre historique de navigation et le modifier</translation>
<translation id="7019805045859631636">Rapide</translation>
<translation id="7022562585984256452">Votre page d'accueil a été définie.</translation>
-<translation id="702384510542929236">Envoie des informations système et du contenu de pages à Google de manière anonyme</translation>
<translation id="7025190659207909717">Gestion des services Internet mobiles</translation>
<translation id="7027125358315426638">Nom de la base de données :</translation>
<translation id="7029809446516969842">Mots de passe</translation>
@@ -4154,6 +4163,7 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
<translation id="7289225569524511578">Ouvrir l'application des fonds d'écran</translation>
<translation id="7290242001003353852">Ce service de connexion hébergé par <ph name="SAML_DOMAIN" /> accède actuellement à votre caméra.</translation>
<translation id="7290594223351252791">Confirmer l'enregistrement</translation>
+<translation id="7292696521213967957">Informations pour déboguer l'Assistant</translation>
<translation id="7295662345261934369">Partager</translation>
<translation id="729583233778673644">Autorisez le chiffrement AES et RC4. L'activation de cette option est risquée, car les algorithmes de chiffrement RC4 ne sont pas sécurisés.</translation>
<translation id="7296774163727375165">Conditions d'utilisation du domaine "<ph name="DOMAIN" />"</translation>
@@ -4254,7 +4264,6 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
<translation id="7456847797759667638">Ouvrir une adresse</translation>
<translation id="7461924472993315131">Épingler</translation>
<translation id="7463006580194749499">Ajouter une personne</translation>
-<translation id="7464902436585505072">Empreinte vocale pour "Ok Google"</translation>
<translation id="7465778193084373987">URL de révocation de certificat Netscape</translation>
<translation id="7469894403370665791">Se connecter automatiquement à ce réseau</translation>
<translation id="747114903913869239">Erreur : impossible de décoder l'extension.</translation>
@@ -4282,6 +4291,7 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
<translation id="7496511874649569424">L'application <ph name="LINUX_APP_NAME" /> et les données qui y sont associées seront supprimées de cet appareil.</translation>
<translation id="7497215489070763236">Certificat de l'autorité de certification du serveur</translation>
<translation id="7497981768003291373">Aucun journal texte WebRTC n'a été créé récemment.</translation>
+<translation id="7502199377020483660">Pour utiliser ces cartes sur tous vos appareils, enregistrez-les dans votre compte Google</translation>
<translation id="7502658306369382406">Adresse IPv6</translation>
<translation id="7503191893372251637">Type de certificat Netscape</translation>
<translation id="7503821294401948377">Impossible de charger l'icône "<ph name="ICON" />" d'action du navigateur.</translation>
@@ -4379,6 +4389,7 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
<translation id="7663719505383602579">Destinataire : <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Appareil Bluetooth non compatible : "<ph name="DEVICE_NAME" />"</translation>
<translation id="7665369617277396874">Ajouter un compte</translation>
+<translation id="7667248760110172428">Espace de stockage externe</translation>
<translation id="7671130400130574146">Utiliser la barre de titre et les bordures de fenêtre du système</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> sur <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Transmettez votre voix à Google pour pouvoir dicter ce que vous voulez dans n'importe quelle zone de texte.</translation>
@@ -4582,6 +4593,7 @@ Assurez-vous de ne pas dévoiler d'informations sensibles.</translation>
<translation id="7930294771522048157">Les modes de paiement enregistrés s'afficheront ici</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> partage votre écran et un contenu audio.</translation>
<translation id="7931318309563332511">Langue source inconnue</translation>
+<translation id="7932969338829957666">Les dossiers partagés sont disponibles dans Linux sous <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Réactiver le son du site}one{Réactiver le son du site}other{Réactiver le son des sites}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> souhaite diffuser un contenu protégé. L'identité de votre appareil sera validée par Google.</translation>
<translation id="793531125873261495">Erreur lors du téléchargement de la machine virtuelle. Veuillez réessayer.</translation>
@@ -4673,6 +4685,7 @@ Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la cr
<translation id="8049705080247101012">Google a signalé l'extension <ph name="EXTENSION_NAME" /> comme malveillante et a bloqué son installation</translation>
<translation id="8049913480579063185">Nom d'extension</translation>
<translation id="8050038245906040378">Signature du code commercial Microsoft</translation>
+<translation id="8052887694493382350">Ce fichier est destiné à un ordinateur utilisant un logiciel Windows. Il n'est pas compatible avec votre appareil qui exécute Chrome OS. <ph name="BEGIN_LINK_HELP" />En savoir plus<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Fichiers PKCS #12</translation>
<translation id="8053390638574070785">Actualiser cette page</translation>
<translation id="8054517699425078995">Ce type de fichier peut endommager votre appareil. Voulez-vous vraiment conserver le fichier <ph name="FILE_NAME" /> ?</translation>
@@ -4916,6 +4929,7 @@ Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la cr
<translation id="8438566539970814960">Améliorer les recherches et la navigation</translation>
<translation id="8439506636278576865">Proposer de traduire les pages dans cette langue</translation>
<translation id="8440630305826533614">Applications Linux</translation>
+<translation id="8443338615972234259">Veuillez créer un compte pour votre utilisateur supervisé.</translation>
<translation id="8446884382197647889">En savoir plus</translation>
<translation id="8447409163267621480">Vous devez inclure la touche Ctrl ou la touche Alt</translation>
<translation id="8448729345478502352">Agrandir ou réduire la taille des éléments à l'écran</translation>
@@ -4940,6 +4954,7 @@ Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la cr
<translation id="8468750959626135884">Déverrouillez votre <ph name="DEVICE_TYPE" /> avec votre téléphone Android.</translation>
<translation id="8470028084415844044">Pour avoir tous vos mots de passe sur tous vos appareils, activez la synchronisation.</translation>
<translation id="8470513973197838199">Mots de passe enregistrés pour <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Pour utiliser cette carte sur tous vos appareils, enregistrez-la dans votre compte Google</translation>
<translation id="8472623782143987204">matériel requis</translation>
<translation id="8473863474539038330">Adresses et autres</translation>
<translation id="8475313423285172237">Un autre programme sur votre ordinateur a ajouté une extension qui risque de modifier le fonctionnement de Google Chrome.</translation>
@@ -5015,7 +5030,6 @@ Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la cr
<translation id="8598453409908276158">Blocage de l'accès via un plug-in sans système de bac à sable</translation>
<translation id="8601206103050338563">Authentification du client WWW TLS</translation>
<translation id="8602851771975208551">Un autre programme sur votre ordinateur a ajouté une application qui risque de modifier le fonctionnement de Google Chrome.</translation>
-<translation id="8604763363205185560">Contribuez à l'amélioration de Chrome et de sa sécurité</translation>
<translation id="8605428685123651449">Mémoire SQLite</translation>
<translation id="8606726445206553943">Utiliser vos appareils MIDI</translation>
<translation id="8609465669617005112">Monter</translation>
@@ -5191,6 +5205,7 @@ Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la cr
<translation id="8846141544112579928">Recherche du clavier en cours…</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Lorsque vous connectez vos appareils, vous acceptez que votre Chromebook puisse :</translation>
+<translation id="8850251000316748990">Voir plus…</translation>
<translation id="8859057652521303089">Sélectionnez votre langue :</translation>
<translation id="8859174528519900719">Sous-cadre : <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Feuille de calcul Excel</translation>
@@ -5211,7 +5226,7 @@ Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la cr
<translation id="8883847527783433352">Synchroniser avec un autre compte</translation>
<translation id="8885197664446363138">Smart Lock indisponible</translation>
<translation id="88870264962436283">Utiliser Touch ID avec <ph name="APP_NAME" /></translation>
-<translation id="8888253246822647887">Votre application s'ouvrira lorsque la mise à jour sera terminée. Les mises à jour peuvent prendre quelques minutes.</translation>
+<translation id="8888253246822647887">Votre application s'ouvrira une fois la mise à jour terminée. Les mises à jour peuvent prendre quelques minutes.</translation>
<translation id="8888432776533519951">Couleur :</translation>
<translation id="8890516388109605451">Sources</translation>
<translation id="8892168913673237979">Vous êtes prêt</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_gu.xtb b/chromium/chrome/app/resources/generated_resources_gu.xtb
index 3306b6f3c52..7050229587d 100644
--- a/chromium/chrome/app/resources/generated_resources_gu.xtb
+++ b/chromium/chrome/app/resources/generated_resources_gu.xtb
@@ -514,7 +514,6 @@
<translation id="175772926354468439">થીમ ચાલુ કરો</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome વેબ સ્ટોરમાં જુઓ</translation>
-<translation id="1761588866118490543">વૉઇસ મૉડલ</translation>
<translation id="176193854664720708">ફિંગરપ્રિન્ટ સેન્સર એ પાવર બટનમાં ઉપલબ્ધ છે. તેને કોઈપણ આંગળીથી હળવેથી સ્પર્શ કરો.</translation>
<translation id="1763046204212875858">ઍપ્લિકેશન શૉર્ટકટ્સ બનાવો</translation>
<translation id="1763108912552529023">અન્વેષણ કરતાં રહો</translation>
@@ -811,6 +810,8 @@
<translation id="220792432208469595">વપરાશ અને નિદાનનો ડેટા મોકલો. આ ડિવાઇસ હાલમાં Googleને નિદાન, ડિવાઇસ અને ઍપ વપરાશનો ડેટા ઑટોમૅટિક રીતે મોકલી રહ્યું છે. આ સિસ્ટમ અને ઍપની સ્થિરતા અને અન્ય સુધારણાઓમાં સહાય કરશે. એકત્રીકરણ કરેલો કેટલોક ડેટા Google ઍપ અને ભાગીદારોને પણ મદદ કરશે, જેમ કે Android ડેવલપર. આ સેટિંગ માલિક દ્વારા લાગુ કરવામાં આવેલ છે. જો તમારી વધારાની વેબ અને ઍપ પ્રવૃત્તિ સેટિંગ ચાલુ હોય, તો આ ડેટા તમારા Google એકાઉન્ટમાં સાચવવામાં આવી શકે છે. <ph name="BEGIN_LINK1" />વધુ જાણો<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">ઝિપ આર્કાઈવ</translation>
<translation id="220858061631308971">કૃપા કરીને "<ph name="DEVICE_NAME" />" પર આ પિન કોડ દાખલ કરો:</translation>
+<translation id="2213140827792212876">શેરિંગ કાઢી નાખો</translation>
+<translation id="2214018885812055163">શેર કરેલા ફોલ્ડરો</translation>
<translation id="2214884991347062907">ખોટો પાસવર્ડ. ફરી પ્રયાસ કરો</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 પંક્તિ બતાવેલ નથી&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> પંક્તિ બતાવેલ નથી&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> પંક્તિ બતાવેલ નથી&gt;}}</translation>
<translation id="2217501013957346740">એક નામ બનાવો -</translation>
@@ -1011,6 +1012,7 @@
<translation id="2501173422421700905">પ્રમાણપત્ર હોલ્ડ પર છે</translation>
<translation id="2501797496290880632">એક શૉર્ટકટ લખો</translation>
<translation id="2502441965851148920">સ્વચલિત અપડેટ્સ સક્ષમ કરેલ છે. તમારા વ્યવસ્થાપક દ્વારા મેન્યુઅલ અપડેટ્સ અક્ષમ કરવામાં આવ્યાં છે.</translation>
+<translation id="2505127913256479918">આ નિરીક્ષિત એકાઉન્ટને ટૂંક સમયમાં કાઢી નાખવામાં આવશે</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{સ્ક્રીન #}one{સ્ક્રીન #}other{સ્ક્રીન #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" /> માંથી <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play સ્ટોર એકાઉન્ટ</translation>
@@ -1371,6 +1373,7 @@
<translation id="304747341537320566">વાણી એન્જિનો</translation>
<translation id="3053013834507634016">પ્રમાણપત્ર કી ઉપયોગ</translation>
<translation id="3057861065630527966">તમારા ફોટો અને વિડિઓઝનો બેકઅપ લો</translation>
+<translation id="3058498974290601450">તમે કોઈ પણ સમયે સેટિંગમાં 'સિંક કરો' ચાલુ કરી શકો છો</translation>
<translation id="3060379269883947824">સાંભળવા માટે પસંદ કરોને ચાલુ કરો</translation>
<translation id="3061707000357573562">પૅચ સેવા</translation>
<translation id="3065041951436100775">ટેબ ફરજિયાત બંધ કરવાનો પ્રતિસાદ.</translation>
@@ -1562,6 +1565,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> ઇન્સ્ટોલ કરવામાં આવશે.</translation>
<translation id="3380365263193509176">અજ્ઞાત ભૂલ</translation>
<translation id="3382073616108123819">અરેરે! આ ઉપકરણ માટે ઉપકરણ ઓળખકર્તા નક્કી કરવામાં સિસ્ટમ નિષ્ફળ થઇ.</translation>
+<translation id="3382086682569279540">તમે મેનેજ કરો છો તે એકાઉન્ટને ટૂંક સમયમાં કાઢી નાખવામાં આવશે</translation>
<translation id="3382200254148930874">નિરીક્ષણ બંધ કરી રહ્યાં છીએ...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">વિભાજક</translation>
@@ -1742,8 +1746,8 @@
<translation id="3636096452488277381">હેલો, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> બાકી</translation>
<translation id="3637682276779847508">જો તમે સાચી PIN અનલૉક કી દાખલ કરી ન શકો તો તમારું SIM કાર્ડ કાયમીરૂપે અક્ષમ કરવામાં આવશે.</translation>
-<translation id="363863692969456324">જોડણીના તપાસની બહેતર સુવિધા વડે જોડણીની ભૂલો સુધારો</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> માટે "<ph name="EXTENSION_NAME" />" ઉમેરીએ?</translation>
+<translation id="3640613767643722554">તમારા આસિસ્ટંટને તમારો અવાજ ઓળખવાનું શીખવો</translation>
<translation id="3644896802912593514">પહોળાઈ</translation>
<translation id="3645372836428131288">ફિંગરપ્રિન્ટનો કોઈ બીજો ભાગ કૅપ્ચર કરવા માટે તેને સહેજ ખસેડો.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> મળ્યું</translation>
@@ -2143,7 +2147,6 @@
<translation id="4244238649050961491">વધુ સ્ટાઇલસ ઍપ મેમરીનો શોધો</translation>
<translation id="424546999567421758">ઉચ્ચ ડિસ્ક વપરાશ મળ્યો</translation>
<translation id="424726838611654458">હંમેશાં Adobe Reader માં ખોલો</translation>
-<translation id="4247330672018280062">ટેક્સ્ટ ફીલ્ડમાં તમે જે ટાઇપ કરો છો તે ટેક્સ્ટ Googleને મોકલવામાં આવશે</translation>
<translation id="4247901771970415646"><ph name="USERNAME" /> સાથે સિંક કરી શકાતું નથી</translation>
<translation id="4249248555939881673">નેટવર્ક કનેક્શનની રાહ જોઈ રહ્યાં છે...</translation>
<translation id="4249373718504745892">આ પૃષ્ઠને તમારા કૅમેરા અને માઇક્રોફોનને ઍક્સેસ કરવાથી અવરોધિત કરવામાં આવ્યું છે.</translation>
@@ -2485,6 +2488,7 @@
<translation id="4821935166599369261">&amp;પ્રોફાઇલિંગ સક્ષમ</translation>
<translation id="4823484602432206655">વપરાશકર્તા અને ઉપકરણ સેટિંગ્સ વાંચો અને બદલો</translation>
<translation id="4823651846660089135">ઉપકરણ ફક્ત વાંચવા માટે છે</translation>
+<translation id="4824958205181053313">સિંક કરવાનું રદ કરીએ?</translation>
<translation id="4827675678516992122">કનેક્ટ કરી શકાયું નથી</translation>
<translation id="4828937774870308359">ઓસ્ટ્રેલિયન</translation>
<translation id="4829768588131278040">PIN સેટ કરો</translation>
@@ -2867,6 +2871,7 @@
<translation id="5374359983950678924">ચિત્ર બદલો</translation>
<translation id="5376169624176189338">પાછળ જવા માટે ક્લિક કરો, ઇતિહાસ જોવા માટે દબાવી રાખો</translation>
<translation id="5376931455988532197">ફાઇલ ખૂબ મોટી છે</translation>
+<translation id="5377594097385838788">છૂપો મોડ</translation>
<translation id="537813040452600081">આ વિંડોમાં તમે જે પેજ જોઈ રહ્યાં છો તે બ્રાઉઝર ઇતિહાસમાં દેખાશે નહિ અને એ તમારા સાઇન આઉટ કર્યા પછી કમ્પ્યુટર પર કૂકી જેવા કોઈ બીજા નિશાન છોડશે નહિ. તમે ડાઉનલોડ કરો છો તે ફાઇલો અને તમે બનાવો છો તે બુકમાર્ક જળવાશે નહિ.</translation>
<translation id="5379140238605961210">માઇક્રોફોનની ઍક્સેસને અવરોધિત કરવાનું ચાલુ રાખો</translation>
<translation id="5379268888377976432">ડિલીટ કરવાનો છેલ્લો ફેરફાર રદ કરો</translation>
@@ -2888,6 +2893,7 @@
<translation id="5414566801737831689">તમે મુલાકાત લો છો તે વેબસાઇટ્સના આયકન્સ વાંચો</translation>
<translation id="5417312524372586921">બ્રાઉઝરની થીમ</translation>
<translation id="5419294236999569767">સિસ્ટમ સમય</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">ટેક્સ્ટ અને છબીઓની તીવ્રતા નિર્ધારિત કરે છે</translation>
<translation id="5422221874247253874">ઍક્સેસ પૉઇન્ટ</translation>
<translation id="5422781158178868512">માફ કરશો, તમારો બાહ્ય સ્ટોરેજ ઉપકરણ ઓળખી શકાયું નથી.</translation>
@@ -2908,6 +2914,7 @@
<translation id="5434065355175441495">PKCS #1 RSA એન્ક્રિપ્શન</translation>
<translation id="5436492226391861498">પ્રૉક્સી ટનલની પ્રતીક્ષા કરી રહ્યાં છે...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> શોધો:</translation>
+<translation id="543806387003274181">કૃપા કરીને તમારી ફાઇલો સાચવો અને હમણાં જ નવું એકાઉન્ટ બનાવો.</translation>
<translation id="5438224778284622050">ઑફલાઇન ફાઇલો ડિલીટ કરી દઈએ?</translation>
<translation id="544083962418256601">શૉર્ટકટ્સ બનાવો ...</translation>
<translation id="5442228125690314719">ડિસ્ક છબી બનાવતી વખતે ભૂલ આવી, કૃપા કરીને ફરી પ્રયાસ કરો.</translation>
@@ -3282,6 +3289,8 @@
<translation id="5965661248935608907">જ્યારે તમે હોમ બટન ક્લિક કરો અથવા ઑમ્નિબૉક્સ પરથી શોધ કરો ત્યારે કયું પૃષ્ઠ બતાવવામાં આવે તે તેનું પણ નિયંત્રણ કરે છે.</translation>
<translation id="5971037678316050792">Bluetooth એડેપ્ટર સ્થિતિ અને જોડીનું નિયંત્રણ કરો</translation>
<translation id="5972017421290582825">MIDI સેટિંગ્સનું સંચાલન કરો...</translation>
+<translation id="597235323114979258">વધુ સ્થાનો જુઓ</translation>
+<translation id="5972666587303800813">નો-ઑપ સેવાઓ</translation>
<translation id="5972708806901999743">ટોચ પર જાઓ</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> શરૂ કરો</translation>
<translation id="5975792506968920132">બેટરી ચાર્જની ટકાવારી</translation>
@@ -3652,6 +3661,7 @@
<translation id="6527303717912515753">શેર કરો</translation>
<translation id="6528513914570774834">આ ઉપકરણના અન્ય વપરાશકર્તાઓને આ નેટવર્ક વાપરવાની મંજૂરી આપો</translation>
<translation id="652948702951888897">Chrome ઇતિહાસ</translation>
+<translation id="6530186581263215931">આ સેટિંગ તમારા વ્યવસ્થાપક દ્વારા લાગુ કરવામાં આવ્યા છે</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> સમન્વયિત કરી રહ્યું છે...</translation>
<translation id="6531282281159901044">જોખમી ફાઇલ રાખો</translation>
<translation id="6532101170117367231">Google ડ્રાઇવ પર સાચવો</translation>
@@ -3970,7 +3980,6 @@
<translation id="7018275672629230621">તમારો બ્રાઉઝિંગ ઇતિહાસ વાંચો અને બદલો</translation>
<translation id="7019805045859631636">ઝડપી</translation>
<translation id="7022562585984256452">તમારું હોમ પેજ સેટ કરવામાં આવ્યું છે.</translation>
-<translation id="702384510542929236">Googleને અનામી રીતે અમુક સિસ્ટમની માહિતી અને પેજ કન્ટેન્ટ મોકલે છે</translation>
<translation id="7025190659207909717">મોબાઇલ ડેટા સેવા મેનેજમેન્ટ</translation>
<translation id="7027125358315426638">ડેટાબેઝ નામ:</translation>
<translation id="7029809446516969842">પાસવર્ડ્સ</translation>
@@ -4150,6 +4159,7 @@
<translation id="7289225569524511578">વૉલપેપર ઍપ્લિકેશન ખોલો</translation>
<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> દ્વારા હોસ્ટ થયેલ સાઇન-ઇન સેવા, તમારા કૅમેરાને ઍક્સેસ કરી રહી છે.</translation>
<translation id="7290594223351252791">નોંધણીની પુષ્ટિ કરો</translation>
+<translation id="7292696521213967957">આસિસ્ટંટ ડિબગ કરવા માટેની માહિતી</translation>
<translation id="7295662345261934369">બીજા સાથે શેર કરો</translation>
<translation id="729583233778673644">AES અને RC4 એન્ક્રિપ્શનની મંજૂરી આપો. આનાથી વિકલ્પનો ઉપયોગ કરવાનું તમારું જોખમ વધે છે, કારણ કે RC4 સાઇફર અસુરક્ષિત હોય છે.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> શરતો</translation>
@@ -4250,7 +4260,6 @@
<translation id="7456847797759667638">સ્થાન ખોલો...</translation>
<translation id="7461924472993315131">પિન કરો</translation>
<translation id="7463006580194749499">વ્યક્તિ ઉમેરો</translation>
-<translation id="7464902436585505072">"ઑકે Google" વૉઇસ મોડલ</translation>
<translation id="7465778193084373987">નેટસ્કેપ પ્રમાણપત્ર રિવોકેશન URL</translation>
<translation id="7469894403370665791">આ નેટવર્કથી આપમેળે કનેક્ટ થાઓ</translation>
<translation id="747114903913869239">ભૂલ: એક્સટેન્શનને ડિકોડ કરવામાં અક્ષમ</translation>
@@ -4278,6 +4287,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> અને તેની સાથે સંકળાયેલ ડેટાને આ ડિવાઇસમાંથી કાઢી નાખવામાં આવશે.</translation>
<translation id="7497215489070763236">સર્વર CA પ્રમાણપત્ર</translation>
<translation id="7497981768003291373">તમારી પાસે તાજેતરમાં કૅપ્ચર કરેલ કોઈ WebRTC ટેક્સ્ટ લૉગ નથી.</translation>
+<translation id="7502199377020483660">તમારા બધા ડિવાઇસ પર આ કાર્ડનો ઉપયોગ કરવા માટે, તેમને તમારા Google એકાઉન્ટમાં સાચવો</translation>
<translation id="7502658306369382406">IPv6 સરનામું</translation>
<translation id="7503191893372251637">નેટસ્કેપ પ્રમાણપત્રનો પ્રકાર</translation>
<translation id="7503821294401948377">બ્રાઉઝર ક્રિયા માટે આયકન '<ph name="ICON" />' લોડ કરી શકાયું નથી.</translation>
@@ -4375,6 +4385,7 @@
<translation id="7663719505383602579">પ્રાપ્તકર્તા: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">સપોર્ટ ન કરતું Bluetooth ડિવાઇસ: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">એકાઉન્ટ ઉમેરો</translation>
+<translation id="7667248760110172428">બાહ્ય સ્ટોરેજ</translation>
<translation id="7671130400130574146">સિસ્ટમ શીર્ષક બાર અને બોર્ડર્સનો ઉપયોગ કરો</translation>
<translation id="7672520070349703697"><ph name="PAGE_TITLE" />માં <ph name="HUNG_IFRAME_URL" />.</translation>
<translation id="7676867886086876795">કોઈપણ ટેક્સ્ટ ફીલ્ડમાં શ્રુતલેખનને મંજૂરી આપવા માટે Googleને તમારો અવાજ મોકલો.</translation>
@@ -4575,6 +4586,7 @@
<translation id="7930294771522048157">સાચવેલ ચુકવણી પદ્ધતિઓ અહીં દેખાશે</translation>
<translation id="79312157130859720"><ph name="APP_NAME" />, તમારી સ્ક્રીન અને ઑડિઓને શેર કરી રહી છે.</translation>
<translation id="7931318309563332511">અજાણ</translation>
+<translation id="7932969338829957666">શેર કરેલા ફોલ્ડરો Linuxમાં <ph name="BASE_DIR" />પર ઉપલબ્ધ હોય છે.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{સાઇટને અનમ્યૂટ કરો}one{સાઇટને અનમ્યૂટ કરો}other{સાઇટને અનમ્યૂટ કરો}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> સુરક્ષિત કન્ટેન્ટ ચલાવવા માગે છે. Google દ્વારા તમારા ડિવાઇસની ઓળખ ચકાસવામાં આવશે.</translation>
<translation id="793531125873261495">વર્ચ્યુઅલ મશીન ડાઉનલોડ કરવામાં ભૂલ આવી. કૃપા કરીને ફરી પ્રયાસ કરો.</translation>
@@ -4661,6 +4673,7 @@
<translation id="8049705080247101012">Googleએ "<ph name="EXTENSION_NAME" />"ને બ્લેકલિસ્ટેડ ચિહ્નિત કર્યું છે અને ઇન્સ્ટૉલેશન અટકાવવામાં આવ્યું છે</translation>
<translation id="8049913480579063185">એક્સ્ટેન્શન નામ</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">આ ફાઇલ Windows સૉફ્ટવેરનો ઉપયોગ કરતા PC માટે ડિઝાઇન કરવામાં આવી છે. Chrome OS પર ચાલતા તમારા ડિવાઇસ સાથે આ સુસંગત નથી. <ph name="BEGIN_LINK_HELP" />વધુ જાણો<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 ફાઇલો</translation>
<translation id="8053390638574070785">આ પૃષ્ઠને રીલોડ કરો</translation>
<translation id="8054517699425078995">આ પ્રકારની ફાઇલ તમારા ઉપકરણને નુકસાન પહોંચાડી શકે છે. શું તમે તો પણ <ph name="FILE_NAME" /> ને રાખવા માંગો છો?</translation>
@@ -4904,6 +4917,7 @@
<translation id="8438566539970814960">શોધ અને બ્રાઉઝિંગ વધુ સારું બનાવો</translation>
<translation id="8439506636278576865">આ ભાષામાં પૃષ્ઠોનું અનુવાદ કરવાની ઓફર આપે છે</translation>
<translation id="8440630305826533614">Linux ઍપ</translation>
+<translation id="8443338615972234259">કૃપા કરીને તમારા નિરીક્ષિત વપરાશકર્તા માટે હમણાં જ નવું એકાઉન્ટ બનાવો.</translation>
<translation id="8446884382197647889">વધુ જાણો</translation>
<translation id="8447409163267621480">કાં તો Ctrl અથવા Alt શામેલ કરો</translation>
<translation id="8448729345478502352">તમારી સ્ક્રીન પર આઇટમો નાની અથવા મોટી કરો</translation>
@@ -4928,6 +4942,7 @@
<translation id="8468750959626135884">તમારા Android ફોન વડે તમારી <ph name="DEVICE_TYPE" /> ને અનલૉક કરો.</translation>
<translation id="8470028084415844044">તમારા બધા ઉપકરણો પર તમારા બધા પાસવર્ડ મેળવવા માટે સિંક ચાલુ કરો.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" /> માટે સાચવેલા પાસવર્ડ</translation>
+<translation id="8471635086304129332">તમારા બધા ડિવાઇસ પર આ કાર્ડનો ઉપયોગ કરવા માટે, તેને તમારા Google એકાઉન્ટમાં સાચવો</translation>
<translation id="8472623782143987204">હાર્ડવેર-બેક્ડ</translation>
<translation id="8473863474539038330">સરનામા અને વધુ</translation>
<translation id="8475313423285172237">તમારા કમ્પ્યુટર પરના બીજા પ્રોગ્રામે એક એક્સ્ટેંશન ઉમેર્યું જે Chrome કાર્ય કરે છે તે રીતને બદલી શકે છે.</translation>
@@ -5003,7 +5018,6 @@
<translation id="8598453409908276158">અનસૅન્ડબૉક્સ કરેલ પ્લગ-ઇન અવરોધિત</translation>
<translation id="8601206103050338563">TLS WWW ક્લાયંટ પ્રમાણીકરણ</translation>
<translation id="8602851771975208551">તમારા કમ્પ્યુટર પરના બીજા પ્રોગ્રામે એક ઍપ્લિકેશન ઉમેરી જે Chrome કાર્ય કરે છે તે રીતને બદલી શકે છે.</translation>
-<translation id="8604763363205185560">Chrome અને તેની સુરક્ષા બહેતર બનાવવામાં સહાય કરો</translation>
<translation id="8605428685123651449">SQLite મેમરી</translation>
<translation id="8606726445206553943">તમારા MIDI ઉપકરણોનો ઉપયોગ કરો</translation>
<translation id="8609465669617005112">ઉપર ખસેડો</translation>
@@ -5179,6 +5193,7 @@
<translation id="8846141544112579928">કીબોર્ડ માટે શોધ કરી રહ્યું છે...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">તમે જ્યારે તમારાં ડિવાઇસ કનેક્ટ કરો, ત્યારે તમારી Chromebook આ કરી શકે તે બાબતે તમે સંમત થાઓ છો:</translation>
+<translation id="8850251000316748990">વધુ જુઓ...</translation>
<translation id="8859057652521303089">તમારી ભાષા પસંદ કરો:</translation>
<translation id="8859174528519900719">સબફ્રેમ: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel સ્પ્રેડશીટ</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_hi.xtb b/chromium/chrome/app/resources/generated_resources_hi.xtb
index 11d1ede00b8..a99cf49e62b 100644
--- a/chromium/chrome/app/resources/generated_resources_hi.xtb
+++ b/chromium/chrome/app/resources/generated_resources_hi.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">थीम सक्षम करें</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome वेब स्टोर में देखें</translation>
-<translation id="1761588866118490543">आवाज़ का नमूना</translation>
<translation id="176193854664720708">पावर बटन में फ़िंगरप्रिंट सेंसर मौजूद होता है. किसी भी उंगली से इसे हल्के से छुएं.</translation>
<translation id="1763046204212875858">ऐप्स शॉर्टकट बनाएं</translation>
<translation id="1763108912552529023">एक्सप्लोर करते रहें</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">इस्तेमाल और निदान से जुड़ा डेटा भेजें. यह डिवाइस फ़िलहाल Google को निदान, डिवाइस, और ऐप्लिकेशन के इस्तेमाल से जुड़ा डेटा अपने आप भेज रहा है. यह सिस्टम और ऐप्लिकेशन की स्थिरता और दूसरे सुधारों में मदद करेगा. कुछ एग्रीगेट डेटा Google ऐप्लिकेशन और पार्टनर, जैसे कि Android डेवलपरों की भी मदद करेगा. यह सेटिंग डिवाइस के मालिक ने लागू की है. अगर आपकी दूसरी 'वेब और ऐप्लिकेशन गतिविधि' सेटिंग चालू है, तो यह डेटा आपके Google खाते में सेव किया जा सकता है. <ph name="BEGIN_LINK1" />ज़्यादा जानें<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">ज़िप संग्रह</translation>
<translation id="220858061631308971">कृपया इस पिन कोड को "<ph name="DEVICE_NAME" />" पर दर्ज करें:</translation>
+<translation id="2213140827792212876">शेयर की गई फ़ाइलें हटाएं</translation>
+<translation id="2214018885812055163">शेयर किया गया फ़ोल्डर</translation>
<translation id="2214884991347062907">पासवर्ड गलत है. फिर से कोशिश करें</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 पंक्ति नहीं दिखाई गई है&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> पंक्तियां नहीं दिखाई गई हैं&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> पंक्तियां नहीं दिखाई गई हैं&gt;}}</translation>
<translation id="2217501013957346740">कोई नाम बनाएं -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">प्रमाणपत्र लंबित है</translation>
<translation id="2501797496290880632">कोई शॉर्टकट लिखें</translation>
<translation id="2502441965851148920">स्वतः अपडेट सक्षम किए गए हैं. मैन्युअल अपडेट आपके व्यवस्थापक के द्वारा अक्षम किए गए हैं.</translation>
+<translation id="2505127913256479918">निगरानी में रखे गए इस उपयोगकर्ता खाते को जल्द ही हटा दिया जाएगा</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{स्क्रीन #}one{स्क्रीन #}other{स्क्रीन #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" /> में से <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play स्टोर खाता</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">बोली इंजन</translation>
<translation id="3053013834507634016">प्रमाणपत्र कुंजी उपयोग</translation>
<translation id="3057861065630527966">अपनी फ़ोटो और वीडियो का बैक अप लें</translation>
+<translation id="3058498974290601450">आप सेटिंग में किसी भी समय सिंक चालू कर सकते हैं</translation>
<translation id="3060379269883947824">चुनें और सुनें सुविधा चालू करें</translation>
<translation id="3061707000357573562">पैच सेवा</translation>
<translation id="3065041951436100775">टैब किल्ड फ़ीडबैक.</translation>
@@ -1566,11 +1569,12 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> स्थापित कर दिया जाएगा.</translation>
<translation id="3380365263193509176">अज्ञात गड़बड़ी</translation>
<translation id="3382073616108123819">ओह! सिस्‍टम इस डिवाइस के लिए डिवाइस पहचानकर्ताओं का निर्धारण करने में विफल रहा.</translation>
+<translation id="3382086682569279540">आप जिस खाते को प्रबंधित करते हैं उसे जल्द ही हटा दिया जाएगा</translation>
<translation id="3382200254148930874">निगरानी की सुविधा बंद की जा रही है...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">विभाजक</translation>
<translation id="3389312115541230716">टास्कबार में <ph name="SMALL_PRODUCT_LOGO" /> आइकॉन पर राइट क्लिक करें</translation>
-<translation id="3393352139658145068">जब कोई “Ok Google” कहे, तो Assistant चालू करें. बैटरी बचाने के लिए, “Ok Google” सिर्फ़ तब ही चालू होता है जब आपका डिवाइस किसी पावर स्रोत से कनेक्ट होता है.</translation>
+<translation id="3393352139658145068">जब कोई “Ok Google” कहे, तो Assistant चालू करें. बैटरी बचाने के लिए, “Ok Google” सिर्फ़ तब चालू होता है जब आपका डिवाइस चार्जिंग पर लगा होता है.</translation>
<translation id="3396800784455899911">"स्वीकार करें और जारी रखें" बटन पर क्लिक करके, आप पुष्टि करते हैं कि इन Google सेवाओं के लिए ऊपर बताई गई प्रोसेसिंग से आप सहमत हैं.</translation>
<translation id="3399432415385675819">नोटिफ़िकेशन अक्षम हो जाएंगे</translation>
<translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />, <ph name="TIME_LEFT" /></translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">कैसे हैं, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> शेष</translation>
<translation id="3637682276779847508">अगर आप सही पिन अनलॉक कुंजी नहीं डाल पाते हैं तो आपका SIM कार्ड हमेशा के लिए अक्षम कर दिया जाएगा.</translation>
-<translation id="363863692969456324">बेहतर वर्तनी जाँच के ज़रिए वर्तनी की गड़बड़ियां ठीक करना</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> के लिए "<ph name="EXTENSION_NAME" />" को जोड़ें?</translation>
+<translation id="3640613767643722554">अपनी Assistant को आपकी आवाज़ पहचानना सिखाएं</translation>
<translation id="3644896802912593514">चौड़ाई</translation>
<translation id="3645372836428131288">फ़िंगरप्रिंट के अलग हिस्से को कैप्चर करने के लिए उंगली धीरे से हिलाएं</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> का पता चला</translation>
@@ -2146,7 +2150,6 @@
<translation id="4244238649050961491">और अधिक स्टाइलस ऐप ढूंढें</translation>
<translation id="424546999567421758">अधिक डिस्क उपयोग का पता चला</translation>
<translation id="424726838611654458">हमेशा Adobe Reader में खोलें</translation>
-<translation id="4247330672018280062">आप टेक्स्ट फ़ील्ड में जो भी टेक्स्ट लिखेंगे, उसे Google को भेजा जाएगा</translation>
<translation id="4247901771970415646"><ph name="USERNAME" /> से सिंक नहीं किया जा सकता</translation>
<translation id="4249248555939881673">नेटवर्क कनेक्शन के लिए प्रतीक्षारत...</translation>
<translation id="4249373718504745892">इस पेज को आपके कैमरे और माइक्रोफ़ोन को एक्सेस करने से अवरोधित कर दिया गया है.</translation>
@@ -2488,6 +2491,7 @@
<translation id="4821935166599369261">&amp;प्रोफ़ाइलिंग सक्षम</translation>
<translation id="4823484602432206655">उपयोगकर्ता और डिवाइस सेटिंग पढ़ें और बदलें</translation>
<translation id="4823651846660089135">डिवाइस केवल-पढ़ने के लिए है</translation>
+<translation id="4824958205181053313">सिंक करना रद्द करें?</translation>
<translation id="4827675678516992122">जोड़ा नहीं जा सका</translation>
<translation id="4828937774870308359">आस्ट्रेलियाई</translation>
<translation id="4829768588131278040">पिन सेट करें</translation>
@@ -2870,6 +2874,7 @@
<translation id="5374359983950678924">चित्र बदलें</translation>
<translation id="5376169624176189338">वापस जाने के लिए क्लिक करें, इतिहास देखने के लिए दबाए रखें</translation>
<translation id="5376931455988532197">फ़ाइल बहुत बड़ी है</translation>
+<translation id="5377594097385838788">गुप्त</translation>
<translation id="537813040452600081">प्रस्थान करने के बाद, आपके द्वारा देखे गए पेज ब्राउज़र इतिहास में दिखाई नहीं देंगे और वे कंप्यूटर पर कुकी जैसे अन्य चिह्न नहीं छोड़ेंगे. आपके द्वारा डाउनलोड की जाने वाली फ़ाइलें और आपके द्वारा बनाए जाने वाले बुकमार्क संरक्षित नहीं किए जाएंगे.</translation>
<translation id="5379140238605961210">माइक्रोफ़ोन की एक्सेस अवरुद्ध करना जारी रखें</translation>
<translation id="5379268888377976432">हटाना वापस लाएं</translation>
@@ -2891,6 +2896,7 @@
<translation id="5414566801737831689">आप जिन वेबसाइट पर जाते हैं, उनके आइकॉन पढ़ें</translation>
<translation id="5417312524372586921">ब्राउज़र थीम</translation>
<translation id="5419294236999569767">सिस्टम का समय</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">लेख और इमेज का पैनापन तय करता है</translation>
<translation id="5422221874247253874">एक्सेस प्वाइंट</translation>
<translation id="5422781158178868512">क्षमा करें, आपके बाह्य मेमोरी डिवाइस की पहचान नहीं हो सकी.</translation>
@@ -2911,6 +2917,7 @@
<translation id="5434065355175441495">PKCS #1 RSA सुरक्षित तरीका</translation>
<translation id="5436492226391861498">प्रॉक्सी टनेल की प्रतीक्षा कर रहा है...</translation>
<translation id="5436510242972373446">खोज <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">कृपया अपनी फ़ाइलें सेव करें और अभी नया खाता बनाएं.</translation>
<translation id="5438224778284622050">ऑफ़लाइन फ़ाइलें हटाएं?</translation>
<translation id="544083962418256601">शॉर्टकट बनाएं...</translation>
<translation id="5442228125690314719">डिस्क इमेज बनाते समय गड़बड़ी हुई. कृपया फिर से कोशिश करें.</translation>
@@ -3284,6 +3291,8 @@
<translation id="5965661248935608907">इससे यह भी नियंत्रित होता है कि जब आप होम बटन क्लिक करते हैं या खोज वाली पट्टी से खोजते हैं तब कौन सा पृष्‍ठ दिखाया जाए.</translation>
<translation id="5971037678316050792">ब्लूटूथ एडाप्टर स्थिति और युग्मन नियंत्रित करें</translation>
<translation id="5972017421290582825">MIDI सेटिंग प्रबंधित करें...</translation>
+<translation id="597235323114979258">ज़्यादा मंज़िलें देखें</translation>
+<translation id="5972666587303800813">सेवा में नहीं है</translation>
<translation id="5972708806901999743">शीर्ष पर ले जाएं</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> प्रारंभ करें</translation>
<translation id="5975792506968920132">बैटरी चार्ज का प्रतिशत</translation>
@@ -3654,6 +3663,7 @@
<translation id="6527303717912515753">शेयर करें</translation>
<translation id="6528513914570774834">इस डिवाइस के दूसरे उपयोगकर्ताओं को इस नेटवर्क का उपयोग करने दें</translation>
<translation id="652948702951888897">Chrome इतिहास</translation>
+<translation id="6530186581263215931">ये सेटिंग आपके एडमिन ने लागू की हैं</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> समन्वयित किया जा रहा है...</translation>
<translation id="6531282281159901044">खतरनाक फ़ाइल रखें</translation>
<translation id="6532101170117367231">Google डिस्क में सहेजें</translation>
@@ -3717,9 +3727,9 @@
<translation id="6629841649550503054">सभी का <ph name="BEGIN_LINK" />Google डिस्‍क<ph name="END_LINK" /> में बैक अप लिया गया!</translation>
<translation id="6630752851777525409"><ph name="EXTENSION_NAME" /> को आपकी ओर से स्वयं को प्रमाणीकृत करने के लिए प्रमाणपत्र की स्थायी ऐक्सेस चाहिए.</translation>
<translation id="6635956300022133031">लिखाई को बोली में बदलने वाली आवाज़ें चुनें और उन्हें पसंद के मुताबिक बनाएं</translation>
-<translation id="6637585982786704944">जिन ऐप्लिकेशन और वेबसाइटों को मंज़ूरी मिली हुई है, वे उस खाता जानकारी को एक्सेस कर सकते हैं, जो काम को ठीक तरीके से करने के लिए ज़रूरी है.
+<translation id="6637585982786704944">जिन ऐप्लिकेशन और वेबसाइटों को आपने मंज़ूरी दी है, वे उस खाता जानकारी को एक्सेस कर सकते हैं, जो काम को ठीक तरीके से करने के लिए ज़रूरी है.
- अगर आप खाता नहीं जोड़ना चाहते हैं, तो वेब ब्राउज़िंग के लिए मेहमान के तौर पर साइन इन करें या कोई गुप्त विडो खोलें.
+ अगर आप खाता नहीं जोड़ना चाहते हैं, तो वेब ब्राउज़िंग के लिए मेहमान के तौर पर साइन इन करें या कोई गुप्त विंडो खोलें.
सभी खातों को देखने और प्रबंधित करने के लिए आप सेटिंग -&gt; Google खाते पर जा सकते हैं.</translation>
<translation id="6639554308659482635">SQLite मेमोरी</translation>
@@ -3972,7 +3982,6 @@
<translation id="7018275672629230621">अपना ब्राउज़र इतिहास पढ़ें और बदलें</translation>
<translation id="7019805045859631636">तेज़</translation>
<translation id="7022562585984256452">आपका मुख पेज सेट कर दिया गया है.</translation>
-<translation id="702384510542929236">सिस्टम की कुछ जानकारी और पेज की सामग्री Google को पहचान छिपाकर भेजती है</translation>
<translation id="7025190659207909717">मोबाइल डेटा सेवा प्रबंधन</translation>
<translation id="7027125358315426638">डेटाबेस नाम:</translation>
<translation id="7029809446516969842">पासवर्ड</translation>
@@ -4152,6 +4161,7 @@
<translation id="7289225569524511578">वॉलपेपर ऐप्लिकेशन खोलें</translation>
<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> द्वारा होस्ट की गई यह प्रवेश सेवा, आपका कैमरा एक्सेस कर रही है.</translation>
<translation id="7290594223351252791">पंजीकरण की दुबारा पूछें</translation>
+<translation id="7292696521213967957">Assistant को डीबग करने की जानकारी</translation>
<translation id="7295662345261934369">दूसरों से शेयर करें</translation>
<translation id="729583233778673644">AES और RC4 सुरक्षा की अनुमति दें. इस विकल्प का इस्तेमाल करने से आपका खतरा बढ़ जाता है, क्योंकि RC4 सिफ़र असुरक्षित होते हैं.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> शर्तें</translation>
@@ -4252,7 +4262,6 @@
<translation id="7456847797759667638">स्थान खोलें...</translation>
<translation id="7461924472993315131">पिन करें</translation>
<translation id="7463006580194749499">व्‍यक्ति जोड़ें</translation>
-<translation id="7464902436585505072">"Ok Google" आवाज़ का नमूना</translation>
<translation id="7465778193084373987">Netscape प्रमाणपत्र रद्द करने संबंधी URL</translation>
<translation id="7469894403370665791">इस नेटवर्क से अपने आप कनेक्ट करें</translation>
<translation id="747114903913869239">गड़बड़ी: एक्सटेंशन डिकोड करने में असमर्थ</translation>
@@ -4280,6 +4289,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> और उससे जुड़े डेटा को इस डिवाइस से हटा दिया जाएगा.</translation>
<translation id="7497215489070763236">सर्वर CA प्रमाणपत्र</translation>
<translation id="7497981768003291373">आपके पास हाल ही में कैप्चर किया गया कोई WebRTC लेख लॉग नहीं है.</translation>
+<translation id="7502199377020483660">अपने सभी डिवाइस पर इन कार्ड का इस्तेमाल करने के लिए, उन्हें अपने Google खाते में सेव करें</translation>
<translation id="7502658306369382406">IPv6 पता</translation>
<translation id="7503191893372251637">Netscape प्रमाणपत्र प्रकार</translation>
<translation id="7503821294401948377">ब्राउज़र कार्रवाई के लिए आइकॉन '<ph name="ICON" />' लोड नहीं किया जा सका.</translation>
@@ -4377,6 +4387,7 @@
<translation id="7663719505383602579">प्राप्तकर्ता: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">असमर्थित ब्लूटूथ डिवाइस: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">खाता जोड़ें</translation>
+<translation id="7667248760110172428">बाहरी मेमोरी</translation>
<translation id="7671130400130574146">सिस्टम शीर्षक बार और बॉर्डर का उपयोग करें</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> में.</translation>
<translation id="7676867886086876795">किसी भी लेख फ़ील्ड में बोलकर टाइप करने की सुविधा देने के लिए आपकी आवाज़ Google को भेजी जाती है.</translation>
@@ -4580,6 +4591,7 @@
<translation id="7930294771522048157">सेव किए गए भुगतान के तरीके यहां दिखाई देंगे</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> आपकी स्क्रीन और ऑडियो को शेयर कर रहा है.</translation>
<translation id="7931318309563332511">अज्ञात</translation>
+<translation id="7932969338829957666">शेयर किए गए फ़ोल्डर Linux में <ph name="BASE_DIR" /> पर उपलब्ध हैं.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{साइट अनम्यूट करें}one{साइटें अनम्यूट करें}other{साइटें अनम्यूट करें}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> सुरक्षित सामग्री चलाना चाहता है. Google आपके डिवाइस की पहचान की पुष्टि करेगा.</translation>
<translation id="793531125873261495">वर्चुअल मशीन डाउनलोड करने में गड़बड़ी हुई. कृपया फिर से कोशिश करें.</translation>
@@ -4671,6 +4683,7 @@
<translation id="8049705080247101012">Google ने <ph name="EXTENSION_NAME" /> को दुर्भावनापूर्ण के रूप में फ़्लैग किया है और इंस्टॉलेशन रोक दिया गया है</translation>
<translation id="8049913480579063185">एक्सटेंशन का नाम</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">यह फ़ाइल पीसी के लिए Windows सॉफ़्टवेयर का इस्तेमाल करके बनाई गई है. यह आपके Chrome OS चलाने वाले डिवाइस के साथ काम नहीं करता है. <ph name="BEGIN_LINK_HELP" />ज़्यादा जानें<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 फ़ाइलें</translation>
<translation id="8053390638574070785">यह पेज फिर से लोड करें</translation>
<translation id="8054517699425078995">इस प्रकार की फ़ाइल आपके डिवाइस को हानि पहुंचा सकती है. क्‍या आप <ph name="FILE_NAME" /> को किसी भी तरह रखना चाहते हैं?</translation>
@@ -4914,6 +4927,7 @@
<translation id="8438566539970814960">खोजों और ब्राउज़िंग को बेहतर बनाएं</translation>
<translation id="8439506636278576865">इस भाषा में पृष्ठों का अनुवाद करने का ऑफ़र दें</translation>
<translation id="8440630305826533614">Linux ऐप्लिकेशन</translation>
+<translation id="8443338615972234259">निगरानी में रखे गए अपने उपयोगकर्ता के लिए कृपया अभी एक नया खाता बनाएं.</translation>
<translation id="8446884382197647889">अधिक जानें</translation>
<translation id="8447409163267621480">Ctrl या Alt में से किसी एक को शामिल करें</translation>
<translation id="8448729345478502352">अपनी स्क्रीन पर मौजूद आइटम को छोटा या बड़ा करें</translation>
@@ -4938,6 +4952,7 @@
<translation id="8468750959626135884">अपने <ph name="DEVICE_TYPE" /> को अपने Android फ़ोन से अनलॉक करें.</translation>
<translation id="8470028084415844044">अपने सभी डिवाइस पर अपने सभी पासवर्ड पाने के लिए, सिंक चालू करें.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" /> के लिए सेव किए गए पासवर्ड</translation>
+<translation id="8471635086304129332">अपने सभी कार्ड पर इस डिवाइस का इस्तेमाल करने के लिए, इसे अपने Google खाते में सेव करें</translation>
<translation id="8472623782143987204">हार्डवेयर-समर्थित</translation>
<translation id="8473863474539038330">पते वगैरह</translation>
<translation id="8475313423285172237">आपके कंप्यूटर पर किसी अन्य प्रोग्राम ने एक्सटेंशन जोड़ा है, जो Chrome के काम करने के तरीके को बदल सकता है.</translation>
@@ -5013,7 +5028,6 @@
<translation id="8598453409908276158">सैंडबॉक्स नहीं किया गया प्लग इन ब्लॉक किया गया</translation>
<translation id="8601206103050338563">TLS WWW क्लाइंट प्रमाणीकरण</translation>
<translation id="8602851771975208551">आपके कंप्यूटर पर किसी अन्य प्रोग्राम ने ऐप्स जोड़ा है, जो Chrome के काम करने के तरीके को बदल सकता है.</translation>
-<translation id="8604763363205185560">Chrome और उसकी सुरक्षा को बेहतर बनाने में मदद करना</translation>
<translation id="8605428685123651449">SQLite मेमोरी</translation>
<translation id="8606726445206553943">अपने MIDI डिवाइस का उपयोग करें</translation>
<translation id="8609465669617005112">ऊपर जाएं</translation>
@@ -5189,6 +5203,7 @@
<translation id="8846141544112579928">कीबोर्ड खोजा जा रहा है...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">जब आप अपने डिवाइस जोड़ते हैं, तब आप सहमति देते हैं कि आपका Chromebook ये काम कर सकता है:</translation>
+<translation id="8850251000316748990">ज़्यादा देखें...</translation>
<translation id="8859057652521303089">अपनी भाषा चुनें:</translation>
<translation id="8859174528519900719">सबफ़्रेम: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel स्‍प्रैडशीट</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_hr.xtb b/chromium/chrome/app/resources/generated_resources_hr.xtb
index 19685209455..bdeae230b5d 100644
--- a/chromium/chrome/app/resources/generated_resources_hr.xtb
+++ b/chromium/chrome/app/resources/generated_resources_hr.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Omogućiti temu</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Prikaz u Chrome web-trgovini</translation>
-<translation id="1761588866118490543">Glasovni model</translation>
<translation id="176193854664720708">Senzor otiska prsta nalazi se u tipki za uključivanje/isključivanje. Dodirnite ga lagano bilo kojim prstom.</translation>
<translation id="1763046204212875858">Stvaranje prečaca aplikacije</translation>
<translation id="1763108912552529023">Nastavi istraživati</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Slanje podataka o upotrebi i dijagnostici. Ovaj uređaj trenutačno Googleu automatski šalje dijagnostičke podatke te podatke o upotrebi uređaja i aplikacija. Ti podaci pomoći će poboljšati stabilnost sustava, aplikacija i drugo. Neki skupni podaci pomoći će i Googleovim aplikacijama i partnerima, na primjer razvojnim programerima za Android. Ovu postavku zadao je vlasnik. Ako je uključena dodatna postavka Aktivnost na webu i u aplikacijama, ti se podaci mogu spremati na vaš Google račun. <ph name="BEGIN_LINK1" />Saznajte više<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip arhiva</translation>
<translation id="220858061631308971">Unesite ovaj PIN kôd na uređaj "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Ukloni dijeljenje</translation>
+<translation id="2214018885812055163">Dijeljene mape</translation>
<translation id="2214884991347062907">Pogrešna zaporka. Pokušajte ponovo.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;Ne prikazuje se jedan redak&gt;}one{&lt;Ne prikazuje se <ph name="NUMBER_OF_LINES" /> redak&gt;}few{&lt;Ne prikazuju se <ph name="NUMBER_OF_LINES" /> retka&gt;}other{&lt;Ne prikazuje se <ph name="NUMBER_OF_LINES" /> redaka&gt;}}</translation>
<translation id="2217501013957346740">Izrada naziva –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Certifikat je na čekanju</translation>
<translation id="2501797496290880632">Upišite prečac</translation>
<translation id="2502441965851148920">Automatska su ažuriranja omogućena. Ručna ažuriranja onemogućio je administrator.</translation>
+<translation id="2505127913256479918">Ovaj nadzirani račun uskoro će se ukloniti</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Zaslon #}one{Zaslon #}few{Zaslon #}other{Zaslon #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> od <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Račun Trgovine Google Play</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Alati za pretvaranje teksta u govor</translation>
<translation id="3053013834507634016">Korištenje ključa certifikata</translation>
<translation id="3057861065630527966">Izrada sigurnosnih kopija fotografija i videozapisa</translation>
+<translation id="3058498974290601450">Sinkronizaciju možete uključiti u bilo kojem trenutku u postavkama</translation>
<translation id="3060379269883947824">Omogući Odabir za govor</translation>
<translation id="3061707000357573562">Usluga zakrpe</translation>
<translation id="3065041951436100775">Povratne informacije o zatvorenoj kartici.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015">Bit će instaliran program <ph name="PRODUCT_NAME" />.</translation>
<translation id="3380365263193509176">Nepoznata pogreška</translation>
<translation id="3382073616108123819">Ups! Sustav nije uspio utvrditi identifikatore ovog uređaja.</translation>
+<translation id="3382086682569279540">Račun kojim upravljate uskoro će se ukloniti</translation>
<translation id="3382200254148930874">Zaustavljanje nadzora...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separator</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Pozdrav, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – još <ph name="TIME" /></translation>
<translation id="3637682276779847508">SIM kartica trajno će se onemogućiti ako ne unesete točan ključ za otključavanje PIN-a</translation>
-<translation id="363863692969456324">Ispravljajte pravopisne pogreške pomoću poboljšane provjere pravopisa</translation>
<translation id="3640214691812501263">Želite li dodati proširenje "<ph name="EXTENSION_NAME" />" za korisnika <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Naučite Asistent da prepoznaje vaš glas</translation>
<translation id="3644896802912593514">Širina</translation>
<translation id="3645372836428131288">Lagano pomaknite prst da biste snimili različite dijelove otiska prsta.</translation>
<translation id="3648348069317717750">Otkriven je uređaj <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Pronađite više aplikacija pisaljke</translation>
<translation id="424546999567421758">Otkrivena je intenzivna upotreba diska</translation>
<translation id="424726838611654458">Uvijek otvaraj u Adobe Readeru</translation>
-<translation id="4247330672018280062">Tekst koji unesete u tekstna polja poslat će se Googleu</translation>
<translation id="4247901771970415646">Nije moguće sinkronizirati s korisničkim imenom <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Čekanje mrežne veze...</translation>
<translation id="4249373718504745892">Stranici je blokiran pristup vašoj kameri i vašem mikrofonu.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Profiliranje omogućeno</translation>
<translation id="4823484602432206655">čitati i mijenjati korisničke postavke i postavke uređaja</translation>
<translation id="4823651846660089135">Uređaj je samo za čitanje</translation>
+<translation id="4824958205181053313">Otkazati sinkronizaciju?</translation>
<translation id="4827675678516992122">Povezivanje nije uspjelo</translation>
<translation id="4828937774870308359">Australsko (obrnuto)</translation>
<translation id="4829768588131278040">Postavi PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Promijeni sliku</translation>
<translation id="5376169624176189338">Kliknite da biste se vratili natrag, zadržite da biste vidjeli povijest</translation>
<translation id="5376931455988532197">Datoteka je prevelika</translation>
+<translation id="5377594097385838788">Anonimno</translation>
<translation id="537813040452600081">Stranice koje gledate u ovom prozoru neće se pojaviti u povijesti preglednika niti će ostaviti druge tragove, na primjer, kolačiće, na računalu nakon što se odjavite. Datoteke koje preuzmete i oznake koje stvorite neće se sačuvati.</translation>
<translation id="5379140238605961210">Nastavi blokirati pristup mikrofonu</translation>
<translation id="5379268888377976432">Poništavanje brisanja</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">čitati ikone posjećenih web-lokacija</translation>
<translation id="5417312524372586921">Teme preglednika</translation>
<translation id="5419294236999569767">Vrijeme sustava</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Određuje oštrinu teksta i slika</translation>
<translation id="5422221874247253874">Pristupna točka</translation>
<translation id="5422781158178868512">Žao nam je, nije bilo moguće prepoznati vanjski uređaj za pohranu.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS br. 1 RSA enkripcija</translation>
<translation id="5436492226391861498">Čekanje na proxy tunel...</translation>
<translation id="5436510242972373446">Pretraži <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Sada spremite svoje datoteke i izradite novi račun.</translation>
<translation id="5438224778284622050">Želite li izbrisati offline datoteke?</translation>
<translation id="544083962418256601">Stvaranje prečaca...</translation>
<translation id="5442228125690314719">Došlo je do pogreške prilikom izrade slike diska. Pokušajte ponovo.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">Upravlja i time koja se stranica prikazuje kada se klikne gumb Početna ili prilikom pretraživanja putem višenamjenskog okvira.</translation>
<translation id="5971037678316050792">upravljati stanjem i uparivanjem Bluetootha</translation>
<translation id="5972017421290582825">Upravljanje postavkama MIDI uređaja...</translation>
+<translation id="597235323114979258">Pogledajte više odredišta</translation>
+<translation id="5972666587303800813">Usluga bez funkcije</translation>
<translation id="5972708806901999743">Premjesti na vrh</translation>
<translation id="5972826969634861500">Pokreni <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Postotak napunjenosti baterije</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">Podijeli</translation>
<translation id="6528513914570774834">Dopusti drugim korisnicima ovog uređaja da upotrebljavaju ovu mrežu</translation>
<translation id="652948702951888897">Chromeova povijest</translation>
+<translation id="6530186581263215931">Te je postavke nametnuo vaš administrator</translation>
<translation id="653019979737152879">Sinkronizacija datoteke <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Zadrži opasnu datoteku</translation>
<translation id="6532101170117367231">Spremi na Google disk</translation>
@@ -3720,9 +3730,9 @@
<translation id="6635956300022133031">Odaberite i prilagodite glasove za pretvaranje teksta u govor</translation>
<translation id="6637585982786704944">Aplikacije i web-lokacije koje imaju vaše dopuštenje mogu pristupiti podacima o računu koji su im potrebni za pravilan rad.
- Ako ne želite dodati račun, prijavite se kao gost ili otvorite anoniman prozor za pregledavanje weba.
+ Ako ne želite dodati račun, prijavite se kao gost ili otvorite anonimni prozor za pregledavanje weba.
- Otvorite Postavke -&gt; Google računi da biste pregledali sve račune i upravljali njima.</translation>
+ Otvorite Postavke -&gt; Google računi da biste pregledali sve račune i njima upravljali.</translation>
<translation id="6639554308659482635">SQLite memorija</translation>
<translation id="6641138807883536517">Nasumično generirana zaporka sigurnog modula nije dostupna. To je uobičajeno nakon primjene funkcije Powerwash.</translation>
<translation id="6643016212128521049">Izbriši</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">pročitati i promijeniti povijest pregledavanja</translation>
<translation id="7019805045859631636">Brzo</translation>
<translation id="7022562585984256452">Vaša je početna stranica postavljena.</translation>
-<translation id="702384510542929236">Anonimno šalje neke informacije o sustavu i sadržaj web-stranice Googleu</translation>
<translation id="7025190659207909717">Upravljanje podatkovnom uslugom za mobilne uređaje</translation>
<translation id="7027125358315426638">Naziv baze podataka:</translation>
<translation id="7029809446516969842">Zaporke</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">Otvori aplikaciju pozadine</translation>
<translation id="7290242001003353852">Usluga prijave, koju hostira <ph name="SAML_DOMAIN" />, pristupa vašoj kameri.</translation>
<translation id="7290594223351252791">Potvrda registracije</translation>
+<translation id="7292696521213967957">Informacije za otklanjanje pogrešaka Asistenta</translation>
<translation id="7295662345261934369">Dijeli s drugima</translation>
<translation id="729583233778673644">Dopuštanje AES i RC4 šifriranja. Upotreba te opcije izlaže vas većoj opasnosti jer RC4 šifre nisu sigurne.</translation>
<translation id="7296774163727375165">Uvjeti domene <ph name="DOMAIN" /></translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">Otvori lokaciju...</translation>
<translation id="7461924472993315131">Prikvači</translation>
<translation id="7463006580194749499">Dodaj osobu</translation>
-<translation id="7464902436585505072">Glasovni model za "Ok Google"</translation>
<translation id="7465778193084373987">URL za opoziv Netscape certifikata</translation>
<translation id="7469894403370665791">Automatski se povežite s tom mrežom</translation>
<translation id="747114903913869239">Pogreška: Nije moguće dekodirati proširenje</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424">Aplikacija <ph name="LINUX_APP_NAME" /> i s njom povezani podaci uklonit će se s ovog uređaja.</translation>
<translation id="7497215489070763236">CA certifikat poslužitelja</translation>
<translation id="7497981768003291373">Nemate nedavno snimljenih WebRTC tekstnih zapisnika.</translation>
+<translation id="7502199377020483660">Da biste te kartice upotrebljavali na svim svojim uređajima, spremite ih na svoj Google račun</translation>
<translation id="7502658306369382406">IPv6 adresa</translation>
<translation id="7503191893372251637">Vrsta Netscape certifikata</translation>
<translation id="7503821294401948377">Nije uspjelo učitavanje ikone "<ph name="ICON" />" za radnju preglednika.</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">Prijemnik: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Nepodržani Bluetooth uređaj: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Dodaj račun</translation>
+<translation id="7667248760110172428">Vanjska pohrana</translation>
<translation id="7671130400130574146">Koristi naslovnu traku sustava i obrube</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, na stranici <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Pošaljite audiopodatke o svojem glasu Googleu da biste omogućili diktiranje za bilo koje tekstno polje.</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">Ovdje će se prikazivati spremljeni načini plaćanja</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> dijeli zaslon i zvuk.</translation>
<translation id="7931318309563332511">Nepoznato</translation>
+<translation id="7932969338829957666">Dijeljene mape dostupne su na Linuxu na <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Uključi zvuk na web-lokaciji}one{Uključi zvuk na web-lokacijama}few{Uključi zvuk na web-lokacijama}other{Uključi zvuk na web-lokacijama}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> želi reproducirati zaštićeni sadržaj. Identitet vašeg uređaja potvrdit će Google.</translation>
<translation id="793531125873261495">Došlo je do pogreške prilikom preuzimanja virtualnog računala. Pokušajte ponovo.</translation>
@@ -4672,6 +4684,7 @@ Ključnu datoteku čuvajte na sigurnom mjestu. Trebat će vam za stvaranje novih
<translation id="8049705080247101012">Google je označio proširenje "<ph name="EXTENSION_NAME" />" kao zlonamjerno, pa je instalacija spriječena</translation>
<translation id="8049913480579063185">Naziv proširenja</translation>
<translation id="8050038245906040378">Microsoftovo komercijalno kodno potpisivanje</translation>
+<translation id="8052887694493382350">Ova je datoteka predviđena za računalo sa softverom Windows. Nije kompatibilna s uređajem na kojem se izvodi Chrome OS. <ph name="BEGIN_LINK_HELP" />Saznajte više<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Datoteke PKCS #12</translation>
<translation id="8053390638574070785">Ponovo učitaj ovu stranicu</translation>
<translation id="8054517699425078995">Ta vrsta datoteke može nauditi vašem uređaju. Želite li svejedno zadržati datoteku <ph name="FILE_NAME" />?</translation>
@@ -4916,6 +4929,7 @@ Osobe sa sporom vezom možda neće vidjeti vaš sadržaj.</translation>
<translation id="8438566539970814960">Poboljšajte pretraživanje i pregledavanje</translation>
<translation id="8439506636278576865">Ponudi prevođenje stranica na tom jeziku</translation>
<translation id="8440630305826533614">Linux aplikacije</translation>
+<translation id="8443338615972234259">Sada izradite novi račun za svog nadziranog korisnika.</translation>
<translation id="8446884382197647889">Saznajte više</translation>
<translation id="8447409163267621480">Mora sadržavati Ctrl ili Alt</translation>
<translation id="8448729345478502352">Povećajte ili smanjite stavke na zaslonu</translation>
@@ -4940,6 +4954,7 @@ Osobe sa sporom vezom možda neće vidjeti vaš sadržaj.</translation>
<translation id="8468750959626135884">Otključavajte uređaj <ph name="DEVICE_TYPE" /> Android telefonom.</translation>
<translation id="8470028084415844044">Da biste imali sve svoje zaporke na svim svojim uređajima, uključite sinkronizaciju.</translation>
<translation id="8470513973197838199">Spremljene zaporke za <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Da biste karticu upotrebljavali na svim uređajima, spremite je na svoj Google račun</translation>
<translation id="8472623782143987204">s hardverskom podlogom</translation>
<translation id="8473863474539038330">Adrese i više</translation>
<translation id="8475313423285172237">Drugi program na vašem računalu dodao je proširenje koje može promijeniti način na koji radi Chrome.</translation>
@@ -5015,7 +5030,6 @@ Osobe sa sporom vezom možda neće vidjeti vaš sadržaj.</translation>
<translation id="8598453409908276158">Blokiran je dodatak izvan testnog okruženja</translation>
<translation id="8601206103050338563">TLS WWW klijentska provjera autentičnosti</translation>
<translation id="8602851771975208551">Drugi program na vašem računalu dodao je aplikaciju koja može promijeniti način na koji radi Chrome.</translation>
-<translation id="8604763363205185560">Pomognite poboljšati Chrome i njegovu sigurnost</translation>
<translation id="8605428685123651449">SQLite memorija</translation>
<translation id="8606726445206553943">upotrebljavati vaše MIDI uređaje</translation>
<translation id="8609465669617005112">Premjesti gore</translation>
@@ -5191,6 +5205,7 @@ Osobe sa sporom vezom možda neće vidjeti vaš sadržaj.</translation>
<translation id="8846141544112579928">Traženje tipkovnice...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Kad povežete uređaje, prihvaćate da Chromebook može:</translation>
+<translation id="8850251000316748990">Pogledajte više...</translation>
<translation id="8859057652521303089">Odaberite svoj jezik:</translation>
<translation id="8859174528519900719">Podokvir: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excelova proračunska tablica</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_hu.xtb b/chromium/chrome/app/resources/generated_resources_hu.xtb
index 2b15af92833..1eaead6740f 100644
--- a/chromium/chrome/app/resources/generated_resources_hu.xtb
+++ b/chromium/chrome/app/resources/generated_resources_hu.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Téma engedélyezése</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Megtekintés a Chrome Internetes áruházban</translation>
-<translation id="1761588866118490543">Hangminta</translation>
<translation id="176193854664720708">Az ujjlenyomat-érzékelő a bekapcsológombban található. Érintse meg finoman valamelyik ujjával.</translation>
<translation id="1763046204212875858">Parancsikon létrehozása az alkalmazáshoz</translation>
<translation id="1763108912552529023">A felfedezés folytatása</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Használati és diagnosztikai adatok küldése. Ez az eszköz jelenleg automatikusan küld diagnosztikai, eszköz- és alkalmazáshasználati adatokat a Google-nak. Az adatok a rendszer- és alkalmazásstabilitás javításában, valamint más fejlesztésekben segítenek. Bizonyos összesített adatok a Google-alkalmazásoknak és -partnereknek, például az Android-fejlesztőknek is segítenek. Ezt a beállítást kötelezővé tette az eszköz tulajdonosa. Ha az Internetes és alkalmazástevékenységek beállítás is be van kapcsolva, akkor a rendszer ezeket az adatokat az Ön Google-fiókjába is mentheti. <ph name="BEGIN_LINK1" />További információ.<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip-archívum</translation>
<translation id="220858061631308971">Kérjük, adja meg a PIN kódot a(z) "<ph name="DEVICE_NAME" />" eszközhöz:</translation>
+<translation id="2213140827792212876">Megosztás visszavonása</translation>
+<translation id="2214018885812055163">Megosztott mappák</translation>
<translation id="2214884991347062907">Téves jelszó; próbálja újra</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 sor nincs megjelenítve&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> sor nincs megjelenítve&gt;}}</translation>
<translation id="2217501013957346740">Név létrehozása –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">A tanúsítvány felfüggesztve</translation>
<translation id="2501797496290880632">Írjon be egy billentyűkódot</translation>
<translation id="2502441965851148920">Az automatikus frissítések engedélyezve vannak. A kézi frissítéseket a rendszergazda letiltotta.</translation>
+<translation id="2505127913256479918">Ez a felügyelt fiók hamarosan eltávolításra kerül</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{#. képernyő}other{#. képernyő}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" />, összesen: <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Áruház-fiók</translation>
@@ -1376,6 +1378,7 @@
<translation id="304747341537320566">Beszédmotorok</translation>
<translation id="3053013834507634016">Tanúsítványkulcs felhasználása</translation>
<translation id="3057861065630527966">Biztonsági másolat készítése a fotókról és videókról</translation>
+<translation id="3058498974290601450">A szinkronizálás bármikor bekapcsolható a beállításokban</translation>
<translation id="3060379269883947824">Felolvasás engedélyezése</translation>
<translation id="3061707000357573562">Javítókészlet szolgáltatás</translation>
<translation id="3065041951436100775">Visszajelzés megszakított lapról.</translation>
@@ -1567,6 +1570,7 @@
<translation id="337920581046691015">A <ph name="PRODUCT_NAME" /> telepítésére készül.</translation>
<translation id="3380365263193509176">Ismeretlen hiba</translation>
<translation id="3382073616108123819">Hoppá! A rendszer nem tudta megállapítani az eszközazonosítókat ehhez az eszközhöz.</translation>
+<translation id="3382086682569279540">Az Ön által kezelt fiók hamarosan eltávolításra kerül</translation>
<translation id="3382200254148930874">Felügyelet leállítása...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Elválasztó</translation>
@@ -1747,8 +1751,8 @@
<translation id="3636096452488277381">Üdvözöljük, <ph name="USER_GIVEN_NAME" />!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – <ph name="TIME" /> maradt</translation>
<translation id="3637682276779847508">Ha nem tudja megadni a helyes PUK-kódot, a SIM-kártya véglegesen le lesz tiltva.</translation>
-<translation id="363863692969456324">Gépelési hibák javítása intelligens helyesírás-ellenőrzővel</translation>
<translation id="3640214691812501263">Hozzáadja a(z) „<ph name="EXTENSION_NAME" />” bővítményt a következő felhasználónál: <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">A Segéd megtanítása az Ön hangjának felismerésére</translation>
<translation id="3644896802912593514">Szélesség</translation>
<translation id="3645372836428131288">Óvatosan mozgassa ujját az ujjlenyomat újabb részének rögzítéséhez.</translation>
<translation id="3648348069317717750">A rendszer <ph name="USB_DEVICE_NAME" /> eszközt észlelt</translation>
@@ -2147,7 +2151,6 @@ Elindítja a következőt: <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation
<translation id="4244238649050961491">További érintőceruza-alkalmazások keresése</translation>
<translation id="424546999567421758">Magas lemezfelhasználás észlelve</translation>
<translation id="424726838611654458">Megnyitás mindig az Adobe Readerben</translation>
-<translation id="4247330672018280062">A szövegmezőkbe gépelt szöveget elküldjük a Google-nak</translation>
<translation id="4247901771970415646">Nem lehet vele szinkronizálni: <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Várakozás a hálózati kapcsolatra...</translation>
<translation id="4249373718504745892">Az oldal nem férhet hozzá az Ön kamerájához és mikrofonjához.</translation>
@@ -2489,6 +2492,7 @@ Elindítja a következőt: <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation
<translation id="4821935166599369261">&amp;Profilozás bekapcsolva</translation>
<translation id="4823484602432206655">A felhasználó és az eszköz beállításainak olvasása és módosítása</translation>
<translation id="4823651846660089135">Az eszköz csak olvasható</translation>
+<translation id="4824958205181053313">Megszakítja a szinkronizálást?</translation>
<translation id="4827675678516992122">Nem sikerült csatlakozni</translation>
<translation id="4828937774870308359">Ausztrál</translation>
<translation id="4829768588131278040">PIN-kód beállítása</translation>
@@ -2872,6 +2876,7 @@ Egyes webhelyek például válaszolhatnak rá úgy, hogy olyan hirdetéseket jel
<translation id="5374359983950678924">Kép lecserélése</translation>
<translation id="5376169624176189338">Kattintson, ha az előző oldalra szeretne lépni; tartsa lenyomva, ha látni szeretné az előzményeket</translation>
<translation id="5376931455988532197">Túl nagyméretű a fájl</translation>
+<translation id="5377594097385838788">Inkognitó</translation>
<translation id="537813040452600081">Az oldalak, melyeket ebben az ablakban megtekint, a kijelentkezést követően nem fognak megjelenni a böngészési előzmények között, és nem hagynak egyéb nyomokat a számítógépen (mint pl. cookie-k). Az Ön által letöltött fájlokat és a létrehozott könyvjelzőket a rendszer nem őrzi meg.</translation>
<translation id="5379140238605961210">Mikrofon-hozzáférés tiltásának fenntartása</translation>
<translation id="5379268888377976432">Törlés visszavonása</translation>
@@ -2893,6 +2898,7 @@ Egyes webhelyek például válaszolhatnak rá úgy, hogy olyan hirdetéseket jel
<translation id="5414566801737831689">A felkeresett webhelyek ikonjainak olvasása</translation>
<translation id="5417312524372586921">Böngészőtémák</translation>
<translation id="5419294236999569767">Rendszeridő</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">A szövegek és képek élességét határozza meg</translation>
<translation id="5422221874247253874">Hozzáférési pont</translation>
<translation id="5422781158178868512">Elnézést kérünk, de a külső tárolóeszköz nem ismerhető fel.</translation>
@@ -2913,6 +2919,7 @@ Egyes webhelyek például válaszolhatnak rá úgy, hogy olyan hirdetéseket jel
<translation id="5434065355175441495">PKCS #1 RSA titkosítás</translation>
<translation id="5436492226391861498">Várakozás a proxy alagútra...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> keresés:</translation>
+<translation id="543806387003274181">Most mentse a fájlokat, és készítsen új fiókot.</translation>
<translation id="5438224778284622050">Törli az offline fájlokat?</translation>
<translation id="544083962418256601">Parancsikonok létrehozása...</translation>
<translation id="5442228125690314719">Nem sikerült létrehozni a lemezképet. Próbálja újra.</translation>
@@ -3287,6 +3294,8 @@ Győződjön meg arról, hogy nem ad ki bizalmas adatokat.</translation>
<translation id="5965661248935608907">Továbbá azt is szabályozza, hogy melyik oldal jelenik meg a Kezdőlap gombra történő kattintáskor vagy a cím- és keresősávban indított kereséskor.</translation>
<translation id="5971037678316050792">Bluetooth-adapter állapotának és párosításának vezérlése</translation>
<translation id="5972017421290582825">MIDI-beállítások kezelése...</translation>
+<translation id="597235323114979258">További célhelyek</translation>
+<translation id="5972666587303800813">Hatásmentes szolgáltatás</translation>
<translation id="5972708806901999743">Mozgatás a lista tetejére</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> indítása</translation>
<translation id="5975792506968920132">Az akkumulátor feltöltöttségének százaléka</translation>
@@ -3657,6 +3666,7 @@ Győződjön meg arról, hogy nem ad ki bizalmas adatokat.</translation>
<translation id="6527303717912515753">Megosztás</translation>
<translation id="6528513914570774834">Engedélyezi a hálózat használatát az eszköz többi felhasználója számára</translation>
<translation id="652948702951888897">Chrome-előzmények</translation>
+<translation id="6530186581263215931">Ezeket a beállításokat a rendszergazda kötelezővé tette</translation>
<translation id="653019979737152879">A(z) <ph name="FILE_NAME" /> szinkronizálása…</translation>
<translation id="6531282281159901044">Veszélyes fájl megtartása</translation>
<translation id="6532101170117367231">Mentés a Google Drive-ba</translation>
@@ -3975,7 +3985,6 @@ Győződjön meg arról, hogy nem ad ki bizalmas adatokat.</translation>
<translation id="7018275672629230621">Böngészési előzmények olvasása és módosítása</translation>
<translation id="7019805045859631636">Gyors</translation>
<translation id="7022562585984256452">Beállítottuk kezdőoldalát.</translation>
-<translation id="702384510542929236">Anonim módon elküld bizonyos rendszer-információkat és oldaltartalmakat a Google-nak</translation>
<translation id="7025190659207909717">Mobil adatátviteli szolgáltatás kezelése</translation>
<translation id="7027125358315426638">Adatbázis neve:</translation>
<translation id="7029809446516969842">Jelszavak</translation>
@@ -4155,6 +4164,7 @@ Győződjön meg arról, hogy nem ad ki bizalmas adatokat.</translation>
<translation id="7289225569524511578">Nyissa meg a háttérkép alkalmazást</translation>
<translation id="7290242001003353852">Ez a bejelentkezési szolgáltatás, amelyet a(z) <ph name="SAML_DOMAIN" /> üzemeltet, hozzáfér a kamerához.</translation>
<translation id="7290594223351252791">Regisztráció megerősítése</translation>
+<translation id="7292696521213967957">Hibakeresését szolgáló adatok a Segédhez</translation>
<translation id="7295662345261934369">Megosztás másokkal</translation>
<translation id="729583233778673644">Az AES és RC4 titkosítás engedélyezése. A beállítás használata növeli a kockázatot, mivel az RC4-kódok nem biztonságosak.</translation>
<translation id="7296774163727375165">A(z) <ph name="DOMAIN" /> feltételei</translation>
@@ -4255,7 +4265,6 @@ Győződjön meg arról, hogy nem ad ki bizalmas adatokat.</translation>
<translation id="7456847797759667638">Hely megnyitása...</translation>
<translation id="7461924472993315131">Rögzítés</translation>
<translation id="7463006580194749499">Személy hozzáadása</translation>
-<translation id="7464902436585505072">„Ok Google” hangminta</translation>
<translation id="7465778193084373987">Netscape tanúsítvány - visszavonási URL</translation>
<translation id="7469894403370665791">Automatikus kapcsolódás ehhez a hálózathoz</translation>
<translation id="747114903913869239">Hiba: nem lehet dekódolni a bővítményt</translation>
@@ -4283,6 +4292,7 @@ Győződjön meg arról, hogy nem ad ki bizalmas adatokat.</translation>
<translation id="7496511874649569424">A(z) <ph name="LINUX_APP_NAME" /> és a hozzá tartozó adatok törlődnek erről az eszközről.</translation>
<translation id="7497215489070763236">Szerver CA tanúsítványa</translation>
<translation id="7497981768003291373">Nincsenek mostanában rögzített szöveges WebRTC-naplói.</translation>
+<translation id="7502199377020483660">Ha minden eszközén használni szeretné ezeket a kártyákat, mentse őket Google-fiókjába.</translation>
<translation id="7502658306369382406">IPv6-cím</translation>
<translation id="7503191893372251637">Netscape-tanúsítvány típusa</translation>
<translation id="7503821294401948377">Nem sikerült a(z) '<ph name="ICON" />' ikon betöltése a böngészőművelethez.</translation>
@@ -4380,6 +4390,7 @@ Győződjön meg arról, hogy nem ad ki bizalmas adatokat.</translation>
<translation id="7663719505383602579">Fogadó fél: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Nem támogatott Bluetooth-eszköz: „<ph name="DEVICE_NAME" />”.</translation>
<translation id="7665369617277396874">Fiók hozzáadása</translation>
+<translation id="7667248760110172428">Külső tárhely</translation>
<translation id="7671130400130574146">Az ablak fejlécének és keretének megjelenítése</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, itt: <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">A hangjának elküldése a Google számára, hogy bármely szövegmezőbe diktálhasson.</translation>
@@ -4583,6 +4594,7 @@ Győződjön meg arról, hogy nem ad ki bizalmas adatokat.</translation>
<translation id="7930294771522048157">Az elmentett fizetési módok itt jelennek meg</translation>
<translation id="79312157130859720">A(z) <ph name="APP_NAME" /> megosztja a képernyőt és a hangot.</translation>
<translation id="7931318309563332511">Ismeretlen</translation>
+<translation id="7932969338829957666">A megosztott mappák a következő helyen találhatók a Linux rendszerben: <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Webhely némításának feloldása}other{Webhelyek némításának feloldása}}</translation>
<translation id="7934414805353235750">A(z) <ph name="URL" /> védett tartalmat szeretne lejátszani. A Google ellenőrzi az eszköz azonosító adatait.</translation>
<translation id="793531125873261495">Nem sikerült letölteni a virtuális gépet. Próbálja újra.</translation>
@@ -4674,6 +4686,7 @@ A kulcsfájlt tartsa biztonságos helyen. Szüksége lesz rá ahhoz, hogy új ve
<translation id="8049705080247101012">A Google rosszindulatúként jelölte meg a(z) „<ph name="EXTENSION_NAME" />” bővítményt, és megakadályozta a telepítést</translation>
<translation id="8049913480579063185">Bővítmény neve</translation>
<translation id="8050038245906040378">Microsoft kereskedelmi kódaláírás</translation>
+<translation id="8052887694493382350">Ez a fájl Windows rendszert futtató számítógéphez készült. Az Ön Chrome OS rendszert futtató eszközével nem kompatibilis. <ph name="BEGIN_LINK_HELP" />További információ.<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 fájlok</translation>
<translation id="8053390638574070785">Az oldal újratöltése</translation>
<translation id="8054517699425078995">Az ilyen típusú fájlok kárt okozhatnak eszközében. Mindenképp szeretné megtartani a(z) <ph name="FILE_NAME" /> fájlt?</translation>
@@ -4917,6 +4930,7 @@ A kulcsfájlt tartsa biztonságos helyen. Szüksége lesz rá ahhoz, hogy új ve
<translation id="8438566539970814960">Keresések és böngészés javítása</translation>
<translation id="8439506636278576865">Kínálja fel az ezen a nyelven írt oldalak fordítását</translation>
<translation id="8440630305826533614">Linux-alkalmazások</translation>
+<translation id="8443338615972234259">Most készítsen új fiókot a felügyelt felhasználó számára.</translation>
<translation id="8446884382197647889">További információ</translation>
<translation id="8447409163267621480">Használja a Ctrl vagy az Alt gombot</translation>
<translation id="8448729345478502352">Nagyíthatja és kicsinyítheti a képernyőn megjelenő elemeket</translation>
@@ -4941,6 +4955,7 @@ A kulcsfájlt tartsa biztonságos helyen. Szüksége lesz rá ahhoz, hogy új ve
<translation id="8468750959626135884">Oldja fel <ph name="DEVICE_TYPE" /> eszközét androidos telefonjával.</translation>
<translation id="8470028084415844044">Ha az összes eszközén szeretné elérni jelszavait, kapcsolja be a szinkronizálást.</translation>
<translation id="8470513973197838199">A(z) <ph name="ORIGIN" /> mentett jelszavai</translation>
+<translation id="8471635086304129332">Ha minden eszközén használni szeretné ezt a kártyát, mentse el Google-fiókjába.</translation>
<translation id="8472623782143987204">hardvertámogatott</translation>
<translation id="8473863474539038330">Címek és egyebek</translation>
<translation id="8475313423285172237">A számítógépen lévő egyik program olyan bővítményt adott hozzá, amely módosíthatja a Chrome működését.</translation>
@@ -5016,7 +5031,6 @@ A kulcsfájlt tartsa biztonságos helyen. Szüksége lesz rá ahhoz, hogy új ve
<translation id="8598453409908276158">Sandbox-technológiát nem alkalmazó beépülő modul letiltva</translation>
<translation id="8601206103050338563">TLS WWW ügyfél hitelesítése</translation>
<translation id="8602851771975208551">A számítógépen lévő egyik program olyan alkalmazást adott hozzá, amely módosíthatja a Chrome működését.</translation>
-<translation id="8604763363205185560">Segítség a Chrome és biztonsági funkciói fejlesztésében</translation>
<translation id="8605428685123651449">SQLite-memória</translation>
<translation id="8606726445206553943">MIDI-eszközök használata</translation>
<translation id="8609465669617005112">Mozgatás felfelé</translation>
@@ -5192,6 +5206,7 @@ A kulcsfájlt tartsa biztonságos helyen. Szüksége lesz rá ahhoz, hogy új ve
<translation id="8846141544112579928">Billentyűzet keresése…</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Ha egymáshoz csatlakoztatja az eszközöket, engedélyezi a Chromebooknak a következőket:</translation>
+<translation id="8850251000316748990">Továbbiak...</translation>
<translation id="8859057652521303089">Nyelv kiválasztása:</translation>
<translation id="8859174528519900719">Subframe: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel-táblázat</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_id.xtb b/chromium/chrome/app/resources/generated_resources_id.xtb
index 8b4c33509f5..b0e5f52cb74 100644
--- a/chromium/chrome/app/resources/generated_resources_id.xtb
+++ b/chromium/chrome/app/resources/generated_resources_id.xtb
@@ -508,7 +508,7 @@
<translation id="1743570585616704562">Tidak dikenali</translation>
<translation id="1743970419083351269">Tutup Kotak Download</translation>
<translation id="1744060673522309905">Tidak dapat menggabungkan perangkat ke domain. Pastikan Anda tidak melampaui jumlah perangkat yang dapat ditambahkan.</translation>
-<translation id="1744108098763830590">halaman latar belakang</translation>
+<translation id="1744108098763830590">halaman background</translation>
<translation id="1745520510852184940">Selalu Lakukan Tindakan Ini</translation>
<translation id="174937106936716857">Jumlah file total</translation>
<translation id="175196451752279553">Buka k&amp;embali tab yang tertutup</translation>
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Aktifkan tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Lihat di Chrome Web Store</translation>
-<translation id="1761588866118490543">Model suara</translation>
<translation id="176193854664720708">Sensor sidik jari ada di tombol power. Sentuh sensor menggunakan jari mana pun.</translation>
<translation id="1763046204212875858">Buat pintasan aplikasi</translation>
<translation id="1763108912552529023">Terus menjelajah</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Kirim data penggunaan dan diagnostik. Perangkat ini saat ini otomatis mengirim data diagnostik, perangkat, dan penggunaan aplikasi ke Google. Data ini akan membantu sistem dan stabilitas aplikasi serta peningkatan lainnya. Beberapa data gabungan juga akan membantu aplikasi dan partner Google, seperti developer Android. Setelan ini diterapkan oleh pemilik. Jika setelan Aktivitas Web &amp; Aplikasi tambahan diaktifkan, data ini mungkin akan disimpan ke Akun Google Anda. <ph name="BEGIN_LINK1" />Pelajari Lebih Lanjut<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Arsip Zip</translation>
<translation id="220858061631308971">Masukkan kode PIN ini ke "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Hapus folder bersama</translation>
+<translation id="2214018885812055163">Folder bersama</translation>
<translation id="2214884991347062907">Sandi salah, coba lagi</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 baris tidak ditampilkan&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> baris tidak ditampilkan&gt;}}</translation>
<translation id="2217501013957346740">Buat nama -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Sertifikat Ditahan</translation>
<translation id="2501797496290880632">Ketik pintasan</translation>
<translation id="2502441965851148920">Pembaruan otomatis diaktifkan. Pembaruan manual dinonaktifkan oleh administrator.</translation>
+<translation id="2505127913256479918">Akun yang diawasi ini akan segera dihapus</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Layar #}other{Layar #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> dari <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Akun Google Play Store</translation>
@@ -1115,7 +1117,7 @@
<translation id="266079277508604648">Tidak dapat terhubung ke printer. Harap periksa apakah printer sudah diaktifkan dan terhubung ke Chromebook dengan Wi-Fi atau USB.</translation>
<translation id="2661146741306740526">16x9</translation>
<translation id="2661714428027871023">Browsing lebih cepat dan gunakan lebih sedikit data dengan Mode Ringan. Klik untuk mempelajari lebih lanjut.</translation>
-<translation id="2662876636500006917">Chrome Webstore</translation>
+<translation id="2662876636500006917">Chrome Web Store</translation>
<translation id="2663302507110284145">Bahasa</translation>
<translation id="2665394472441560184">Tambahkan kata baru</translation>
<translation id="2665717534925640469">Halaman ini sekarang menjadi layar penuh dan telah menonaktifkan kursor mouse Anda.</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Mesin Ucapan</translation>
<translation id="3053013834507634016">Penggunaan Kunci Sertifikat</translation>
<translation id="3057861065630527966">Cadangkan foto dan video</translation>
+<translation id="3058498974290601450">Anda dapat mengaktifkan sinkronisasi kapan saja di setelan</translation>
<translation id="3060379269883947824">Aktifkan fitur klik untuk diucapkan</translation>
<translation id="3061707000357573562">Layanan Patch</translation>
<translation id="3065041951436100775">Masukan tab yang ditutup.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> akan dipasang.</translation>
<translation id="3380365263193509176">Kesalahan tidak dikenal</translation>
<translation id="3382073616108123819">Ups! Sistem gagal menentukan pengenal perangkat untuk perangkat ini.</translation>
+<translation id="3382086682569279540">Akun yang Anda kelola akan segera dihapus</translation>
<translation id="3382200254148930874">Menghentikan pengawasan...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Pemisah</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Hai, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - Sisa <ph name="TIME" /></translation>
<translation id="3637682276779847508">Kartu SIM Anda akan dinonaktifkan secara permanen jika Anda tidak dapat memasukkan PIN Pembuka Kunci yang benar.</translation>
-<translation id="363863692969456324">Perbaiki kesalahan ejaan dengan fitur periksa ejaan yang disempurnakan</translation>
<translation id="3640214691812501263">Tambahkan "<ph name="EXTENSION_NAME" />" untuk <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Ajari Asisten untuk mengenali suara Anda</translation>
<translation id="3644896802912593514">Lebar</translation>
<translation id="3645372836428131288">Gerakkan jari sedikit untuk merekam bagian sidik jari yang lain.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> terdeteksi</translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Temukan aplikasi stilus lainnya</translation>
<translation id="424546999567421758">Penggunaan disk tinggi terdeteksi</translation>
<translation id="424726838611654458">Selalu buka di Adobe Reader</translation>
-<translation id="4247330672018280062">Teks yang Anda ketik di kolom teks akan dikirim ke Google</translation>
<translation id="4247901771970415646">Tidak dapat disinkronkan ke <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Menunggu sambungan jaringan...</translation>
<translation id="4249373718504745892">Halaman ini telah diblokir agar tidak dapat mengakses kamera dan mikrofon Anda.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Penyidikan Diaktifkan</translation>
<translation id="4823484602432206655">Membaca dan mengubah setelan perangkat dan pengguna</translation>
<translation id="4823651846660089135">Perangkat berstatus hanya-baca</translation>
+<translation id="4824958205181053313">Batalkan sinkronisasi?</translation>
<translation id="4827675678516992122">Tidak dapat tersambung</translation>
<translation id="4828937774870308359">Australia</translation>
<translation id="4829768588131278040">Siapkan PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Ubah gambar</translation>
<translation id="5376169624176189338">Klik untuk mundur, tahan untuk melihat histori</translation>
<translation id="5376931455988532197">File terlalu besar</translation>
+<translation id="5377594097385838788">Penyamaran</translation>
<translation id="537813040452600081">Halaman yang Anda lihat di jendela ini tidak akan muncul di histori browser dan tidak akan meninggalkan jejak lain, seperti cookie, di komputer setelah Anda keluar. File yang didownload dan bookmark yang dibuat tidak akan disimpan.</translation>
<translation id="5379140238605961210">Terus blokir akses mikrofon</translation>
<translation id="5379268888377976432">Urungkan Menghapus</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Membaca ikon situs web yang Anda kunjungi</translation>
<translation id="5417312524372586921">Tema browser</translation>
<translation id="5419294236999569767">Waktu sistem</translation>
+<translation id="5419405654816502573">Voice match</translation>
<translation id="5420438158931847627">Menentukan ketajaman teks dan gambar</translation>
<translation id="5422221874247253874">Titik Akses</translation>
<translation id="5422781158178868512">Maaf, perangkat penyimpanan eksternal Anda tidak dapat dikenali.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 MD Dengan Enkripsi RSA</translation>
<translation id="5436492226391861498">Menunggu terowongan proxy...</translation>
<translation id="5436510242972373446">Telusuri <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Simpan file dan buat akun baru sekarang.</translation>
<translation id="5438224778284622050">Hapus file offline?</translation>
<translation id="544083962418256601">Buat pintasan...</translation>
<translation id="5442228125690314719">Error saat membuat disk image. Harap coba lagi.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">Juga mengontrol apa yang ditampilkan halaman saat Anda mengeklik tombol Beranda atau menelusuri dari Omnibox.</translation>
<translation id="5971037678316050792">Mengontrol penyandingan dan keadaan adaptor Bluetooth</translation>
<translation id="5972017421290582825">Kelola setelan MIDI...</translation>
+<translation id="597235323114979258">Lihat tujuan lainnya</translation>
+<translation id="5972666587303800813">Layanan Tanpa Operasi</translation>
<translation id="5972708806901999743">Pindahkan ke atas</translation>
<translation id="5972826969634861500">Mulai <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Persentase Pengisian Daya Baterai</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">Bagikan</translation>
<translation id="6528513914570774834">Izinkan pengguna lain di perangkat ini untuk menggunakan jaringan ini</translation>
<translation id="652948702951888897">Histori Chrome</translation>
+<translation id="6530186581263215931">Setelan ini diberlakukan oleh administrator</translation>
<translation id="653019979737152879">Menyinkronkan <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Simpan file berbahaya</translation>
<translation id="6532101170117367231">Simpan ke Google Drive</translation>
@@ -3738,7 +3748,7 @@
<translation id="665061930738760572">Buka di &amp;Jendela Baru</translation>
<translation id="6651237644330755633">Percayai sertifikat ini untuk mengidentifikasi situs web</translation>
<translation id="665355505818177700">Integrasi <ph name="MS_AD_NAME" /> Chrome hanya didukung di platform x86_64. Chromebook yang dibuat di platform ARM atau x86 tidak mendukung fungsi ini.</translation>
-<translation id="6655190889273724601">Mode pengembang</translation>
+<translation id="6655190889273724601">Mode developer</translation>
<translation id="6655458902729017087">Sembunyikan Akun</translation>
<translation id="6657585470893396449">Sandi</translation>
<translation id="6659213950629089752">Halaman ini diperbesar/diperkecil oleh ekstensi "<ph name="NAME" />"</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">Membaca dan mengubah histori penjelajahan Anda</translation>
<translation id="7019805045859631636">Cepat</translation>
<translation id="7022562585984256452">Beranda Anda telah disetel.</translation>
-<translation id="702384510542929236">Mengirim beberapa informasi sistem dan konten halaman ke Google secara anonim</translation>
<translation id="7025190659207909717">Pengelolaan layanan data seluler</translation>
<translation id="7027125358315426638">Nama basis data:</translation>
<translation id="7029809446516969842">Sandi</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">Buka aplikasi wallpaper</translation>
<translation id="7290242001003353852">Layanan masuk ini, dihosting oleh <ph name="SAML_DOMAIN" /> dan sedang mengakses kamera Anda.</translation>
<translation id="7290594223351252791">Konfirmasi pendaftaran</translation>
+<translation id="7292696521213967957">Info untuk melakukan debug Asisten</translation>
<translation id="7295662345261934369">Bagikan dengan yang lain</translation>
<translation id="729583233778673644">Izinkan enkripsi AES dan RC4. Penggunaan opsi ini akan meningkatkan risiko, karena cipher RC4 tidak aman.</translation>
<translation id="7296774163727375165">Persyaratan <ph name="DOMAIN" /></translation>
@@ -4239,7 +4249,7 @@
<translation id="7422192691352527311">Preferensi...</translation>
<translation id="7423098979219808738">Tanyakan terlebih dahulu</translation>
<translation id="7427315641433634153">MSCHAP</translation>
-<translation id="7427348830195639090">Halaman Latar Belakang: <ph name="BACKGROUND_PAGE_URL" /></translation>
+<translation id="7427348830195639090">Halaman Background: <ph name="BACKGROUND_PAGE_URL" /></translation>
<translation id="7433692219247014412">{COUNT,plural, =0{Buka Semua di &amp;Jendela Baru}=1{Buka di &amp;Jendela Baru}other{Buka Semua (#) di &amp;Jendela Baru}}</translation>
<translation id="7434509671034404296">Pengembang</translation>
<translation id="7436921188514130341">Maaf. Terjadi error saat mengganti nama.</translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">Buka Lokasi...</translation>
<translation id="7461924472993315131">Pasang Pin</translation>
<translation id="7463006580194749499">Tambahkan pengguna</translation>
-<translation id="7464902436585505072">Model suara "Ok Google"</translation>
<translation id="7465778193084373987">Netscape Certificate Revocation URL</translation>
<translation id="7469894403370665791">Sambungkan ke jaringan ini secara otomatis</translation>
<translation id="747114903913869239">Kesalahan: Tidak dapat mendekodekan ekstensi</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> dan data yang terkait dengannya akan dihapus dari perangkat.</translation>
<translation id="7497215489070763236">Sertifikat CA server</translation>
<translation id="7497981768003291373">Anda tidak memiliki log teks WebRTC yang direkam baru-baru ini.</translation>
+<translation id="7502199377020483660">Untuk menggunakannya di semua perangkat Anda, simpan kartu ini di Akun Google Anda</translation>
<translation id="7502658306369382406">Alamat IPv6</translation>
<translation id="7503191893372251637">Netscape Certificate Type</translation>
<translation id="7503821294401948377">Tidak dapat memuat ikon '<ph name="ICON" />' untuk tindakan browser.</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">Penerima: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Perangkat Bluetooth tidak didukung: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Tambahkan akun</translation>
+<translation id="7667248760110172428">Penyimpanan eksternal</translation>
<translation id="7671130400130574146">Gunakan bilah judul dan batas sistem</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, di <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Kirimkan suara Anda ke Google untuk memungkinkan pengetikan dengan suara ke kolom teks.</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">Metode pembayaran yang tersimpan akan muncul di sini</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> membagikan layar dan audio Anda.</translation>
<translation id="7931318309563332511">Tidak dikenal</translation>
+<translation id="7932969338829957666">Folder bersama tersedia pada Linux di <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Aktifkan Notifikasi Situs}other{Aktifkan Notifikasi Beberapa Situs}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> ingin memutar konten yang dilindungi. Identitas perangkat Anda akan diverifikasi oleh Google.</translation>
<translation id="793531125873261495">Error saat mendownload mesin virtual. Coba lagi.</translation>
@@ -4672,6 +4684,7 @@ Simpan file kunci Anda di tempat yang aman. Anda akan membutuhkannya untuk membu
<translation id="8049705080247101012">Google telah menandai "<ph name="EXTENSION_NAME" />" sebagai berbahaya dan penginstalannya telah dicegah</translation>
<translation id="8049913480579063185">Nama Ekstensi</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">File ini didesain untuk PC yang menggunakan software Windows. Ini tidak kompatibel dengan perangkat Anda yang menjalankan Chrome OS. <ph name="BEGIN_LINK_HELP" />Pelajari Lebih Lanjut<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 File</translation>
<translation id="8053390638574070785">Muat Ulang Halaman Ini</translation>
<translation id="8054517699425078995">Jenis file ini dapat membahayakan perangkat Anda. Tetap ingin menyimpan <ph name="FILE_NAME" />?</translation>
@@ -4912,9 +4925,10 @@ Simpan file kunci Anda di tempat yang aman. Anda akan membutuhkannya untuk membu
<translation id="8435395510592618362">Verifikasi identitas Anda dengan <ph name="APP_NAME" /></translation>
<translation id="843760761634048214">Simpan kartu kredit</translation>
<translation id="8438328416656800239">Beralih ke browser cerdas</translation>
-<translation id="8438566539970814960">Jadikan penelusuran dan penjelajahan lebih baik</translation>
+<translation id="8438566539970814960">Jadikan penelusuran dan browsing lebih baik</translation>
<translation id="8439506636278576865">Tawarkan penerjemahan halaman ke dalam bahasa ini</translation>
<translation id="8440630305826533614">Aplikasi Linux</translation>
+<translation id="8443338615972234259">Buat akun baru untuk pengguna yang dilindungi sekarang.</translation>
<translation id="8446884382197647889">Pelajari Lebih Lanjut</translation>
<translation id="8447409163267621480">Sertakan Ctrl atau Alt</translation>
<translation id="8448729345478502352">Membuat item di layar menjadi lebih kecil atau lebih besar</translation>
@@ -4939,6 +4953,7 @@ Simpan file kunci Anda di tempat yang aman. Anda akan membutuhkannya untuk membu
<translation id="8468750959626135884">Buka <ph name="DEVICE_TYPE" /> menggunakan ponsel Android.</translation>
<translation id="8470028084415844044">Untuk mendapatkan semua sandi di semua perangkat Anda, aktifkan sinkronisasi.</translation>
<translation id="8470513973197838199">Sandi yang tersimpan untuk <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Untuk menggunakannya di semua perangkat Anda, simpan kartu ini di Akun Google Anda</translation>
<translation id="8472623782143987204">cadangan hardware</translation>
<translation id="8473863474539038330">Alamat dan informasi lainnya</translation>
<translation id="8475313423285172237">Program lain di komputer Anda menambahkan ekstensi yang dapat mengubah cara kerja Chrome.</translation>
@@ -5014,7 +5029,6 @@ Simpan file kunci Anda di tempat yang aman. Anda akan membutuhkannya untuk membu
<translation id="8598453409908276158">Plugin yang tidak dimasukkan sandbox diblokir</translation>
<translation id="8601206103050338563">Autentikasi klien TLS WWW</translation>
<translation id="8602851771975208551">Program lain di komputer Anda menambahkan aplikasi yang dapat mengubah cara kerja Chrome.</translation>
-<translation id="8604763363205185560">Bantu sempurnakan Chrome dan keamanannya</translation>
<translation id="8605428685123651449">Memori SQLite</translation>
<translation id="8606726445206553943">Menggunakan perangkat MIDI Anda</translation>
<translation id="8609465669617005112">Berpindah ke atas</translation>
@@ -5190,6 +5204,7 @@ Simpan file kunci Anda di tempat yang aman. Anda akan membutuhkannya untuk membu
<translation id="8846141544112579928">Mencari keyboard...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Dengan menghubungkan perangkat, Anda setuju bahwa Chromebook Anda dapat:</translation>
+<translation id="8850251000316748990">Lihat selengkapnya...</translation>
<translation id="8859057652521303089">Pilih bahasa Anda:</translation>
<translation id="8859174528519900719">Subframe: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Spreadsheet Excel</translation>
@@ -5210,7 +5225,7 @@ Simpan file kunci Anda di tempat yang aman. Anda akan membutuhkannya untuk membu
<translation id="8883847527783433352">Sinkronkan ke Akun Lain</translation>
<translation id="8885197664446363138">Smart Lock tidak tersedia</translation>
<translation id="88870264962436283">Gunakan Touch ID dengan <ph name="APP_NAME" /></translation>
-<translation id="8888253246822647887">Aplikasi Anda akan terbuka setelah proses upgrade selesai. Proses upgrade dapat memakan waktu beberapa menit.</translation>
+<translation id="8888253246822647887">Aplikasi Anda akan terbuka setelah proses upgrade selesai. Proses upgrade dapat memerlukan waktu beberapa menit.</translation>
<translation id="8888432776533519951">Warna:</translation>
<translation id="8890516388109605451">Sumber</translation>
<translation id="8892168913673237979">Semua sudah siap!</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_it.xtb b/chromium/chrome/app/resources/generated_resources_it.xtb
index 50dbaac6c7d..9bd0a32b537 100644
--- a/chromium/chrome/app/resources/generated_resources_it.xtb
+++ b/chromium/chrome/app/resources/generated_resources_it.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Attiva tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Visualizza nel Chrome Web Store</translation>
-<translation id="1761588866118490543">Modello vocale</translation>
<translation id="176193854664720708">Il sensore di impronte digitali si trova nel tasto di accensione. Toccalo leggermente con un dito.</translation>
<translation id="1763046204212875858">Creazione di scorciatoie applicazione</translation>
<translation id="1763108912552529023">Continua a esplorare</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Invia dati diagnostici e sull'utilizzo. Questo dispositivo attualmente invia a Google dati diagnostici e sull'utilizzo delle app e del dispositivo. Tali dati contribuiranno alla stabilità di app e sistema, nonché ad altri miglioramenti. Alcuni dati aggregati saranno utili anche alle app e ai partner di Google, ad esempio agli sviluppatori Android. Questa impostazione è applicata dal proprietario. Se hai attivato l'impostazione Attività web e app aggiuntiva, queste informazioni potrebbero essere salvate nel tuo Account Google. <ph name="BEGIN_LINK1" />Ulteriori informazioni<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Archivio Zip</translation>
<translation id="220858061631308971">Inserisci questo codice PIN su "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Rimuovi condivisione</translation>
+<translation id="2214018885812055163">Cartelle condivise</translation>
<translation id="2214884991347062907">Password errata, riprova</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 riga non mostrata&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> righe non mostrate&gt;}}</translation>
<translation id="2217501013957346740">Crea un nome -</translation>
@@ -1014,6 +1015,7 @@
<translation id="2501173422421700905">Certificato in attesa</translation>
<translation id="2501797496290880632">Digita una scorciatoia</translation>
<translation id="2502441965851148920">Gli aggiornamenti automatici sono attivi. Gli aggiornamenti manuali sono stati disattivati dall'amministratore.</translation>
+<translation id="2505127913256479918">Questo account supervisionato verrà rimosso a breve</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Schermo #}other{Schermo #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> di <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Account Google Play Store</translation>
@@ -1373,6 +1375,7 @@
<translation id="304747341537320566">Motori di riconoscimento vocale</translation>
<translation id="3053013834507634016">Uso della chiave del certificato</translation>
<translation id="3057861065630527966">Effettua il backup di foto e video</translation>
+<translation id="3058498974290601450">Puoi attivare la sincronizzazione in qualsiasi momento nelle impostazioni</translation>
<translation id="3060379269883947824">Attiva Seleziona per ascoltare</translation>
<translation id="3061707000357573562">Servizio di applicazione patch</translation>
<translation id="3065041951436100775">Feedback relativo alle schede ignorate</translation>
@@ -1562,6 +1565,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> verrà installato.</translation>
<translation id="3380365263193509176">Errore sconosciuto</translation>
<translation id="3382073616108123819">Spiacenti, il sistema non è riuscito a determinare gli identificatori di questo dispositivo.</translation>
+<translation id="3382086682569279540">L'account che gestisci verrà rimosso a breve</translation>
<translation id="3382200254148930874">Interruzione della supervisione…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separatore</translation>
@@ -1742,8 +1746,8 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="3636096452488277381">Salve <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> rimanenti</translation>
<translation id="3637682276779847508">La scheda SIM verrà definitivamente disabilitata se non sei in grado di inserire il codice di sblocco PIN corretto.</translation>
-<translation id="363863692969456324">Correggi gli errori ortografici con il controllo ortografico avanzato</translation>
<translation id="3640214691812501263">Aggiungere "<ph name="EXTENSION_NAME" />" per <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Insegna all'assistente a riconoscere la tua voce</translation>
<translation id="3644896802912593514">Larghezza</translation>
<translation id="3645372836428131288">Muovi leggermente il dito per acquisire una parte diversa dell'impronta digitale.</translation>
<translation id="3648348069317717750">Rilevato dispositivo <ph name="USB_DEVICE_NAME" /></translation>
@@ -2143,7 +2147,6 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="4244238649050961491">Trova altre app per stilo</translation>
<translation id="424546999567421758">È stato rilevato un elevato utilizzo del disco</translation>
<translation id="424726838611654458">Apri sempre in Adobe Reader</translation>
-<translation id="4247330672018280062">Quanto digitato nei campi di testo verrà inviato a Google</translation>
<translation id="4247901771970415646">Impossibile sincronizzare con <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">In attesa della connessione di rete...</translation>
<translation id="4249373718504745892">A questa pagina è stato impedito l'accesso alla webcam e al microfono.</translation>
@@ -2485,6 +2488,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="4821935166599369261">&amp;Profiling attivato</translation>
<translation id="4823484602432206655">Lettura e modifica delle impostazioni utente e dispositivo</translation>
<translation id="4823651846660089135">Il dispositivo è in sola lettura</translation>
+<translation id="4824958205181053313">Vuoi annullare la sincronizzazione?</translation>
<translation id="4827675678516992122">Impossibile collegarsi</translation>
<translation id="4828937774870308359">Australiano</translation>
<translation id="4829768588131278040">Imposta il codice PIN</translation>
@@ -2866,6 +2870,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="5374359983950678924">Cambia immagine</translation>
<translation id="5376169624176189338">Fai clic per tornare indietro, tieni premuto per vedere la cronologia</translation>
<translation id="5376931455988532197">File troppo grande</translation>
+<translation id="5377594097385838788">In incognito</translation>
<translation id="537813040452600081">Le pagine visualizzate in questa finestra non verranno memorizzate nella cronologia del browser e non lasceranno altre tracce, ad esempio cookie, sul computer dopo l'uscita dall'account. I file scaricati e i Preferiti creati non verranno conservati.</translation>
<translation id="5379140238605961210">Continua a impedire l'accesso al microfono</translation>
<translation id="5379268888377976432">Annulla eliminazione</translation>
@@ -2887,6 +2892,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="5414566801737831689">Lettura delle icone dei siti web visitati</translation>
<translation id="5417312524372586921">Temi del browser</translation>
<translation id="5419294236999569767">Ora di sistema</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Determina la nitidezza del testo e delle immagini</translation>
<translation id="5422221874247253874">Punto di accesso</translation>
<translation id="5422781158178868512">Spiacenti, impossibile riconoscere il dispositivo di archiviazione esterno.</translation>
@@ -2907,6 +2913,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="5434065355175441495">PKCS #1 con crittografia RSA</translation>
<translation id="5436492226391861498">In attesa del tunnel proxy...</translation>
<translation id="5436510242972373446">Cerca su <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Salva subito i tuoi file e crea un nuovo account.</translation>
<translation id="5438224778284622050">Eliminare i file offline?</translation>
<translation id="544083962418256601">Crea scorciatoie...</translation>
<translation id="5442228125690314719">Errore durante la creazione dell'immagine disco. Riprova.</translation>
@@ -3280,6 +3287,8 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="5965661248935608907">Controlla anche la pagina visualizzata quando fai clic sul pulsante Pagina iniziale o quando esegui ricerche dalla Omnibox.</translation>
<translation id="5971037678316050792">Controllo dello stato e dell'accoppiamento dell'adattatore Bluetooth</translation>
<translation id="5972017421290582825">Gestisci impostazioni MIDI...</translation>
+<translation id="597235323114979258">Mostra altre destinazioni</translation>
+<translation id="5972666587303800813">Servizio autonomo</translation>
<translation id="5972708806901999743">Sposta in alto</translation>
<translation id="5972826969634861500">Avvia <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Percentuale di carica della batteria</translation>
@@ -3328,7 +3337,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="6041155700700864984">Chiudi schermo intero</translation>
<translation id="604124094241169006">Automatica</translation>
<translation id="6042169520002885235">Seleziona un produttore e un modello di stampante</translation>
-<translation id="6042308850641462728">Più</translation>
+<translation id="6042308850641462728">Altro</translation>
<translation id="6043317578411397101"><ph name="APP_NAME" /> condivide una scheda Chrome con <ph name="TAB_NAME" />.</translation>
<translation id="6044805581023976844"><ph name="APP_NAME" /> condivide l'audio e una scheda Chrome con <ph name="TAB_NAME" />.</translation>
<translation id="6045021379489914695">Connetti il telefono Android e il Chromebook per un funzionamento migliore, ad esempio per poter mandare SMS dal computer, condividere la connessione a Internet e sbloccare il Chromebook con il telefono.<ph name="FOOTNOTE_POINTER" /> <ph name="LINK_BEGIN" />Ulteriori informazioni<ph name="LINK_END" /></translation>
@@ -3650,6 +3659,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="6527303717912515753">Condividi</translation>
<translation id="6528513914570774834">Consenti ad altri utenti del dispositivo di usare questa rete</translation>
<translation id="652948702951888897">Cronologia di Chrome</translation>
+<translation id="6530186581263215931">Queste impostazioni sono applicate dall'amministratore</translation>
<translation id="653019979737152879">Sincronizzazione del file <ph name="FILE_NAME" /> in corso...</translation>
<translation id="6531282281159901044">Conserva il file pericoloso</translation>
<translation id="6532101170117367231">Salva in Google Drive</translation>
@@ -3968,7 +3978,6 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="7018275672629230621">Lettura e modifica della cronologia di navigazione</translation>
<translation id="7019805045859631636">Veloce</translation>
<translation id="7022562585984256452">La tua pagina iniziale è stata impostata.</translation>
-<translation id="702384510542929236">Invia in forma anonima a Google parte delle informazioni sul sistema e dei contenuti della pagina</translation>
<translation id="7025190659207909717">Gestione del servizio dati mobile</translation>
<translation id="7027125358315426638">Nome database:</translation>
<translation id="7029809446516969842">Password</translation>
@@ -4148,6 +4157,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="7289225569524511578">Apri l'app wallpaper</translation>
<translation id="7290242001003353852">Questo servizio di accesso, ospitato da <ph name="SAML_DOMAIN" />, sta accedendo alla videocamera.</translation>
<translation id="7290594223351252791">Conferma registrazione</translation>
+<translation id="7292696521213967957">Informazioni per il debug dell'assistente</translation>
<translation id="7295662345261934369">Condividi con altri</translation>
<translation id="729583233778673644">Consenti la crittografia AES e RC4. Se scegli di utilizzare quest'opzione vai incontro a un rischio maggiore, in quanto le crittografie RC4 non sono sicure.</translation>
<translation id="7296774163727375165">Termini di <ph name="DOMAIN" /></translation>
@@ -4248,7 +4258,6 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="7456847797759667638">Apri percorso...</translation>
<translation id="7461924472993315131">Blocca</translation>
<translation id="7463006580194749499">Aggiungi persona</translation>
-<translation id="7464902436585505072">Modello vocale "Ok Google"</translation>
<translation id="7465778193084373987">URL di revoca certificato Netscape</translation>
<translation id="7469894403370665791">Collegati automaticamente a questa rete</translation>
<translation id="747114903913869239">Errore: impossibile decodificare l'estensione</translation>
@@ -4276,6 +4285,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> e i dati associati saranno rimossi da questo dispositivo.</translation>
<translation id="7497215489070763236">Certificato CA del server</translation>
<translation id="7497981768003291373">Nessun log di testo WebRTC acquisito di recente.</translation>
+<translation id="7502199377020483660">Per usare queste carte su tutti i tuoi dispositivi, salvale nel tuo Account Google</translation>
<translation id="7502658306369382406">Indirizzo IPv6</translation>
<translation id="7503191893372251637">Tipo di certificato Netscape</translation>
<translation id="7503821294401948377">Impossibile caricare l'icona "<ph name="ICON" />" per l'azione del browser.</translation>
@@ -4371,6 +4381,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="7663719505383602579">Ricevitore: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Dispositivo Bluetooth non supportato: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Aggiungi account</translation>
+<translation id="7667248760110172428">Spazio di archiviazione esterno</translation>
<translation id="7671130400130574146">Usa barra del titolo di sistema e bordi</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, in <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Invia i tuoi dati audio a Google per consentire la dettatura in tutti i campi di testo.</translation>
@@ -4574,6 +4585,7 @@ Se non modifichi le impostazioni predefinite, <ph name="USER_DISPLAY_NAME" /> pu
<translation id="7930294771522048157">I metodi di pagamento salvati verranno visualizzati qui</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> condivide l'audio e il tuo schermo.</translation>
<translation id="7931318309563332511">Sconosciuta</translation>
+<translation id="7932969338829957666">Le cartelle condivise sono disponibili su Linux al percorso <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Riattiva l'audio del sito}other{Riattiva l'audio dei siti}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> vuole riprodurre contenuti protetti. Google verificherà l'identità del tuo dispositivo.</translation>
<translation id="793531125873261495">Errore durante il download della macchina virtuale. Riprova.</translation>
@@ -4665,6 +4677,7 @@ Conserva il file di chiave in un luogo sicuro. Ti servirà per creare nuove vers
<translation id="8049705080247101012">Google ha contrassegnato l'estensione "<ph name="EXTENSION_NAME" />" come dannosa ed è stata impedita l'installazione</translation>
<translation id="8049913480579063185">Nome estensione</translation>
<translation id="8050038245906040378">Firma codice commerciale Microsoft</translation>
+<translation id="8052887694493382350">Questo file è supportato su PC con software Windows. Non è compatibile con il tuo dispositivo Chrome OS. <ph name="BEGIN_LINK_HELP" />Ulteriori informazioni<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">File PKCS #12</translation>
<translation id="8053390638574070785">Ricarica questa pagina</translation>
<translation id="8054517699425078995">Questo tipo di file può danneggiare il tuo dispositivo. Vuoi conservare comunque <ph name="FILE_NAME" />?</translation>
@@ -4907,6 +4920,7 @@ Conserva il file di chiave in un luogo sicuro. Ti servirà per creare nuove vers
<translation id="8438566539970814960">Migliora le ricerche e le attività di navigazione</translation>
<translation id="8439506636278576865">Proponi di tradurre pagine in questa lingua</translation>
<translation id="8440630305826533614">App Linux</translation>
+<translation id="8443338615972234259">Crea subito un nuovo account per l'utente supervisionato.</translation>
<translation id="8446884382197647889">Ulteriori informazioni</translation>
<translation id="8447409163267621480">Includi CTRL o ALT</translation>
<translation id="8448729345478502352">Ingrandisci o rimpicciolisci gli elementi sullo schermo</translation>
@@ -4931,6 +4945,7 @@ Conserva il file di chiave in un luogo sicuro. Ti servirà per creare nuove vers
<translation id="8468750959626135884">Sblocca il tuo <ph name="DEVICE_TYPE" /> con il tuo telefono Android.</translation>
<translation id="8470028084415844044">Attiva la sincronizzazione per trovare tutte le tue password su tutti i dispositivi.</translation>
<translation id="8470513973197838199">Password salvate per il sito <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Per usare questa carta su tutti i tuoi dispositivi, salvala nel tuo Account Google</translation>
<translation id="8472623782143987204">basato sull'hardware</translation>
<translation id="8473863474539038330">Indirizzi e altro</translation>
<translation id="8475313423285172237">Un altro programma sul computer ha aggiunto un'estensione che potrebbe modificare il funzionamento di Chrome.</translation>
@@ -5006,7 +5021,6 @@ Conserva il file di chiave in un luogo sicuro. Ti servirà per creare nuove vers
<translation id="8598453409908276158">Plug-in senza sandbox bloccato</translation>
<translation id="8601206103050338563">Autenticazione TLS client WWW</translation>
<translation id="8602851771975208551">Un altro programma sul computer ha aggiunto un'applicazione che potrebbe modificare il funzionamento di Chrome.</translation>
-<translation id="8604763363205185560">Contribuisci a migliorare Chrome e la sua sicurezza</translation>
<translation id="8605428685123651449">Memoria SQLite</translation>
<translation id="8606726445206553943">Utilizzare i tuoi dispositivi MIDI</translation>
<translation id="8609465669617005112">Sposta su</translation>
@@ -5182,6 +5196,7 @@ Conserva il file di chiave in un luogo sicuro. Ti servirà per creare nuove vers
<translation id="8846141544112579928">Ricerca tastiera in corso...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Quando colleghi i tuoi dispositivi, accetti che il Chromebook possa:</translation>
+<translation id="8850251000316748990">Visualizza altre...</translation>
<translation id="8859057652521303089">Seleziona la tua lingua:</translation>
<translation id="8859174528519900719">Frame secondario: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Foglio di calcolo Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_iw.xtb b/chromium/chrome/app/resources/generated_resources_iw.xtb
index ad4a93a333e..201e9e30334 100644
--- a/chromium/chrome/app/resources/generated_resources_iw.xtb
+++ b/chromium/chrome/app/resources/generated_resources_iw.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">הפעל עיצוב</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">‏הצגה בחנות האינטרנט של Chrome</translation>
-<translation id="1761588866118490543">תבנית קול</translation>
<translation id="176193854664720708">חיישן טביעות האצבע נמצא בלחצן ההפעלה. יש לגעת בו בעדינות באחת האצבעות.</translation>
<translation id="1763046204212875858">צור קיצורי דרך ליישום</translation>
<translation id="1763108912552529023">המשך לחקור</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">‏שליחה של נתוני אבחון ונתונים על השימוש. המכשיר הזה שולח עכשיו אל Google באופן אוטומטי נתוני אבחון ונתונים לגבי השימוש במכשיר ובאפליקציות. נתונים אלה יעזרו לשמור על יציבות המערכת והאפליקציות, כמו גם לביצוע שיפורים אחרים. חלק מהנתונים הנצברים יעזרו גם לאפליקציות ולשותפים של Google, כמו מפתחי Android. ההגדרה הזו נאכפת על-ידי הבעלים. אם הופעלה האפשרות 'פעילות באתרי אינטרנט ובאפליקציות נוספים', ייתכן שהנתונים יישמרו בחשבון Google שלך. <ph name="BEGIN_LINK1" />מידע נוסף<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">‏ארכיון Zip</translation>
<translation id="220858061631308971">‏הזן את קוד PIN זה ב-"<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">הסרת השיתוף</translation>
+<translation id="2214018885812055163">תיקיות משותפות</translation>
<translation id="2214884991347062907">סיסמה לא נכונה, צריך לנסות שוב</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;שורה אחת לא מוצגת&gt;}two{&lt;<ph name="NUMBER_OF_LINES" /> שורות לא מוצגות&gt;}many{&lt;<ph name="NUMBER_OF_LINES" /> שורות לא מוצגות&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> שורות לא מוצגות&gt;}}</translation>
<translation id="2217501013957346740">צור שם -</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">אישור בהמתנה</translation>
<translation id="2501797496290880632">הקלד קיצור</translation>
<translation id="2502441965851148920">הופעלו עדכונים אוטומטיים. מנהל המערכת השבית את העדכונים הידניים.</translation>
+<translation id="2505127913256479918">החשבון הזה בפיקוח יוסר בקרוב</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{מסך #}two{מסך #}many{מסך #}other{מסך #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> מתוך <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">‏חשבון בחנות Google Play</translation>
@@ -1372,6 +1374,7 @@
<translation id="304747341537320566">מנועי דיבור</translation>
<translation id="3053013834507634016">שימוש במפתח אישור </translation>
<translation id="3057861065630527966">גבה את התמונות והסרטונים</translation>
+<translation id="3058498974290601450">אפשר להפעיל את הסנכרון בכל זמן דרך ההגדרות</translation>
<translation id="3060379269883947824">הפעלת הקראה</translation>
<translation id="3061707000357573562">שירות תיקון</translation>
<translation id="3065041951436100775">משוב על כרטיסייה שנסגרה.</translation>
@@ -1563,6 +1566,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> יותקן.</translation>
<translation id="3380365263193509176">שגיאה לא ידועה</translation>
<translation id="3382073616108123819">אופס! המערכת לא הצליחה לקבוע את המזהים של מכשיר זה.</translation>
+<translation id="3382086682569279540">החשבון בניהולך יוסר בקרוב</translation>
<translation id="3382200254148930874">הפיקוח מופסק...</translation>
<translation id="3385092118218578224">%<ph name="DISPLAY_ZOOM" /></translation>
<translation id="338583716107319301">מפריד</translation>
@@ -1743,8 +1747,8 @@
<translation id="3636096452488277381">אהלן, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684">‏‎‎‎%‎‏‎‎‏‎‏‎<ph name="PERCENTAGE" />‌ - נותרו <ph name="TIME" /></translation>
<translation id="3637682276779847508">‏כרטיס ה-SIM שלך יושבת לצמיתות אם לא תזין את המפתח הנכון לביטול נעילת ה-PIN.</translation>
-<translation id="363863692969456324">תיקון שגיאות איות בעזרת בדיקת האיות המשופרת</translation>
<translation id="3640214691812501263">האם להוסיף את "<ph name="EXTENSION_NAME" />" בשביל <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">‏ה-Assistant יכול ללמוד לזהות את הקול שלך</translation>
<translation id="3644896802912593514">רוחב</translation>
<translation id="3645372836428131288">יש להזיז קצת את האצבע כדי לסרוק חלק אחר של טביעת האצבע.</translation>
<translation id="3648348069317717750">המערכת זיהתה את <ph name="USB_DEVICE_NAME" /></translation>
@@ -2144,7 +2148,6 @@
<translation id="4244238649050961491">חפש עוד אפליקציות לשימוש בסטיילוס</translation>
<translation id="424546999567421758">אותר שימוש בכמות גדולה מנפח הדיסק</translation>
<translation id="424726838611654458">‏פתח תמיד ב-Adobe Reader</translation>
-<translation id="4247330672018280062">‏הטקסט שיוקלד בשדות טקסט יישלח אל Google</translation>
<translation id="4247901771970415646">לא ניתן לסנכרן עם <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">ממתין לחיבור רשת...</translation>
<translation id="4249373718504745892">הגישה של הדף הזה למצלמה ולמיקרופון נחסמה.</translation>
@@ -2486,6 +2489,7 @@
<translation id="4821935166599369261">&amp;יצירת פרופילים מופעלת</translation>
<translation id="4823484602432206655">קריאה ושינוי של הגדרות המשתמש והמכשיר</translation>
<translation id="4823651846660089135">המכשיר מוגדר לקריאה בלבד</translation>
+<translation id="4824958205181053313">לבטל את הסנכרון?</translation>
<translation id="4827675678516992122">לא ניתן להתחבר</translation>
<translation id="4828937774870308359">אוסטרלית</translation>
<translation id="4829768588131278040">‏הגדר PIN</translation>
@@ -2869,6 +2873,7 @@
<translation id="5374359983950678924">שנה תמונה</translation>
<translation id="5376169624176189338">לחץ כדי לחזור, לחץ והחזק כדי לראות את ההיסטוריה</translation>
<translation id="5376931455988532197">הקובץ גדול מדי</translation>
+<translation id="5377594097385838788">גלישה בסתר</translation>
<translation id="537813040452600081">‏דפים שתעיין בהם בחלון זה לא יופיעו בהיסטוריה של הדפדפן, והם לא ישאירו במחשב עקבות אחרים, כגון קובצי Cookie, לאחר שתצא. קבצים שתוריד וסימניות שתיצור לא יישמרו.</translation>
<translation id="5379140238605961210">המשך לחסום גישה למיקרופון</translation>
<translation id="5379268888377976432">בטל מחיקה</translation>
@@ -2890,6 +2895,7 @@
<translation id="5414566801737831689">קריאה של סמלי האתרים שבהם אתה מבקר</translation>
<translation id="5417312524372586921">עיצובי דפדפן</translation>
<translation id="5419294236999569767">שעת מערכת</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">קביעת החדות של הטקסט והתמונות</translation>
<translation id="5422221874247253874">נקודת גישה</translation>
<translation id="5422781158178868512">מצטערים, לא ניתן לזהות את מכשיר האחסון החיצוני שלך.</translation>
@@ -2910,6 +2916,7 @@
<translation id="5434065355175441495">‏הצפנת RSA של PKCS #1</translation>
<translation id="5436492226391861498">‏ממתין ל-Proxy Tunnel...</translation>
<translation id="5436510242972373446">חפש ב-<ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">יש לשמור את הקבצים וליצור עכשיו חשבון חדש.</translation>
<translation id="5438224778284622050">האם למחוק קבצים לא מקוונים?</translation>
<translation id="544083962418256601">יצירת קיצורי דרך...</translation>
<translation id="5442228125690314719">קרתה שגיאה ביצירת תמונת הדיסק. צריך לנסות שוב.</translation>
@@ -3283,6 +3290,8 @@
<translation id="5965661248935608907">הגדרה זו גם קובעת איזה דף מוצג כשאתה לוחץ על הלחצן 'דף הבית' או מבצע חיפוש מסרגל הכתובות.</translation>
<translation id="5971037678316050792">‏הגדרת מצב ושליטה בהתאמה עבור מתאם Bluetooth</translation>
<translation id="5972017421290582825">‏נהל הגדרות MIDI...</translation>
+<translation id="597235323114979258">הצגת יעדים נוספים</translation>
+<translation id="5972666587303800813">‏שירות ללא תפעול (no-ops)</translation>
<translation id="5972708806901999743">העבר למעלה</translation>
<translation id="5972826969634861500">הפעל את <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">אחוז טעינת הסוללה</translation>
@@ -3653,6 +3662,7 @@
<translation id="6527303717912515753">שתף</translation>
<translation id="6528513914570774834">אפשר למשתמשים האחרים במכשיר הזה להשתמש ברשת הזו</translation>
<translation id="652948702951888897">‏היסטוריה של Chrome</translation>
+<translation id="6530186581263215931">את ההגדרות האלה אוכף מנהל המערכת</translation>
<translation id="653019979737152879">מסנכרן את <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">השאר את הקובץ המסוכן</translation>
<translation id="6532101170117367231">‏שמור ב-Google Drive</translation>
@@ -3971,7 +3981,6 @@
<translation id="7018275672629230621">לקרוא ולשנות את היסטוריית הגלישה שלך</translation>
<translation id="7019805045859631636">מהיר</translation>
<translation id="7022562585984256452">דף הבית שלך הוגדר.</translation>
-<translation id="702384510542929236">‏חלק מפרטי המערכת ותוכן הדף יישלחו אל Google באופן אנונימי</translation>
<translation id="7025190659207909717">ניהול שירות של נתונים סלולריים</translation>
<translation id="7027125358315426638">שם מסד נתונים:</translation>
<translation id="7029809446516969842">סיסמאות</translation>
@@ -4032,7 +4041,7 @@
<translation id="7109543803214225826">קיצור הדרך הוסר</translation>
<translation id="7113502843173351041">לדעת את כתובת האימייל שלך</translation>
<translation id="7114054701490058191">הסיסמאות לא תואמות</translation>
-<translation id="7114648273807173152">‏כדי להשתמש ב-Smart Lock על מנת להיכנס אל חשבון Google צריך לעבור אל 'הגדרות' &gt; 'מכשירים מחוברים' &gt; 'הטלפון שלך &gt; Smart Lock.</translation>
+<translation id="7114648273807173152">‏כדי להשתמש ב-Smart Lock על מנת להיכנס אל חשבון Google צריך לעבור אל 'הגדרות' &gt; 'מכשירים מחוברים' &gt; 'הטלפון שלך' &gt; Smart Lock.</translation>
<translation id="7117228822971127758">אפשר לנסות שוב מאוחר יותר</translation>
<translation id="7117247127439884114">היכנס שוב...</translation>
<translation id="711840821796638741">הצג סימניות מנוהלות</translation>
@@ -4151,6 +4160,7 @@
<translation id="7289225569524511578">פתח את אפליקציית הטפט</translation>
<translation id="7290242001003353852">שירות הכניסה הזה, המתארח ב-<ph name="SAML_DOMAIN" />, ניגש אל המצלמה שלך.</translation>
<translation id="7290594223351252791">אישור רישום</translation>
+<translation id="7292696521213967957">‏מידע לניפוי באגים ב-Assistant</translation>
<translation id="7295662345261934369">שתף עם אחרים</translation>
<translation id="729583233778673644">‏התרה של הצפנת AES ו-RC4. שימוש באפשרות הזו מגדיל את הסיכון, כי הצפנות RC4 אינן מאובטחות.</translation>
<translation id="7296774163727375165">תנאים של <ph name="DOMAIN" /></translation>
@@ -4251,7 +4261,6 @@
<translation id="7456847797759667638">פתח מיקום...</translation>
<translation id="7461924472993315131">הצמד</translation>
<translation id="7463006580194749499">הוספת משתמש</translation>
-<translation id="7464902436585505072">‏תבנית קול בשביל "Ok Google"</translation>
<translation id="7465778193084373987">‏כתובת אתר לביטול אישור של Netscape</translation>
<translation id="7469894403370665791">התחבר אוטומטית לרשת זו.</translation>
<translation id="747114903913869239">שגיאה: לא ניתן לפענח תוסף</translation>
@@ -4279,6 +4288,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> והנתונים שמשויכים לאפליקציה יוסרו מהמכשיר הזה.</translation>
<translation id="7497215489070763236">‏אישור CA של שרת</translation>
<translation id="7497981768003291373">‏אין לך יומני טקסט של WebRTC שתועדו לאחרונה.</translation>
+<translation id="7502199377020483660">‏כדי להשתמש בכרטיסים האלה בכל המכשירים שברשותך, צריך לשמור אותם בחשבון Google</translation>
<translation id="7502658306369382406">‏כתובת IPv6</translation>
<translation id="7503191893372251637">‏סוג אישור Netscape</translation>
<translation id="7503821294401948377">לא היתה אפשרות לטעון את האייקון '<ph name="ICON" />' עבור פעולת דפדפן.</translation>
@@ -4374,6 +4384,7 @@
<translation id="7663719505383602579">מקבל: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">‏מכשיר Bluetooth שאינו נתמך: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">הוסף חשבון</translation>
+<translation id="7667248760110172428">אחסון חיצוני</translation>
<translation id="7671130400130574146">השתמש בגבולות ובשורת הכותרת של המערכת</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, ב-<ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">‏שליחת הקלטה של הקול שלך אל Google מאפשרת הכתבה בכל תיבת טקסט.</translation>
@@ -4576,6 +4587,7 @@
<translation id="7930294771522048157">אמצעי תשלום שנשמרו יופיעו כאן</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> משתף את המסך והאודיו שלך.</translation>
<translation id="7931318309563332511">לא ידוע</translation>
+<translation id="7932969338829957666">‏תיקיות משותפות זמינות ב-Linux בספרייה <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{ביטול השתקת האתר}two{ביטול השתקת האתרים}many{ביטול השתקת האתרים}other{ביטול השתקת האתרים}}</translation>
<translation id="7934414805353235750">‏<ph name="URL" /> רוצה להפעיל תוכן מוגן. זהות המכשיר שלך תאומת על-ידי Google.</translation>
<translation id="793531125873261495">קרתה שגיאה בהורדת המכונה הווירטואלית. צריך לנסות שוב.</translation>
@@ -4667,6 +4679,7 @@
<translation id="8049705080247101012">‏Google סימנה את "<ph name="EXTENSION_NAME" />" כזדוני, וההתקנה נמנעה</translation>
<translation id="8049913480579063185">שם תוסף</translation>
<translation id="8050038245906040378">‏חתימת קוד מסחרי של Microsoft</translation>
+<translation id="8052887694493382350">‏הקובץ הזה מיועד למחשב PC עם מערכת ההפעלה Windows. הוא לא מתאים למכשיר שלך, שבו פועלת מערכת ההפעלה Chrome OS. <ph name="BEGIN_LINK_HELP" />מידע נוסף<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">‏קבצים של PKCS #12</translation>
<translation id="8053390638574070785">טען דף זה מחדש</translation>
<translation id="8054517699425078995">קובץ מסוג זה יכול לפגוע במכשיר שלך. האם אתה רוצה לשמור את <ph name="FILE_NAME" /> בכל זאת?</translation>
@@ -4820,7 +4833,7 @@
<translation id="827097179112817503">הצג את לחצן 'דף הבית'</translation>
<translation id="8271246892936492311">{COUNT,plural, =1{סימניה אחת נמחקה}two{# סימניות נמחקו}many{# סימניות נמחקו}other{# סימניות נמחקו}}</translation>
<translation id="8272443605911821513">נהל את התוספים שלך על ידי לחיצה על 'תוספים' בתפריט 'כלים נוספים'.</translation>
-<translation id="8272966760965438857">‏יש לך אפשרות לנהל את כל חשבונות Google שלך במקום אחד</translation>
+<translation id="8272966760965438857">‏יש לך אפשרות לנהל את כל חשבונות Google במקום אחד</translation>
<translation id="8274332263553132018">העברת קובץ</translation>
<translation id="8274924778568117936">אל תכבה או תסגור את ה-<ph name="DEVICE_TYPE" /> לפני סיום העדכון. ה-<ph name="DEVICE_TYPE" /> יופעל מחדש באופן אוטומטי בסיום ההתקנה.</translation>
<translation id="8275038454117074363">ייבוא</translation>
@@ -4912,6 +4925,7 @@
<translation id="8438566539970814960">שיפור החיפושים והגלישה</translation>
<translation id="8439506636278576865">הצעות לתרגום דפים שנכתבו בשפה זו</translation>
<translation id="8440630305826533614">‏אפליקציות Linux</translation>
+<translation id="8443338615972234259">יש ליצור עכשיו חשבון חדש בשביל המשתמש בפיקוח.</translation>
<translation id="8446884382197647889">למידע נוסף</translation>
<translation id="8447409163267621480">‏יש לכלול את Ctrl או Alt</translation>
<translation id="8448729345478502352">הגדלה או הקטנה של פריטים במסך</translation>
@@ -4936,6 +4950,7 @@
<translation id="8468750959626135884">‏בטל את הנעילה של <ph name="DEVICE_TYPE" /> באמצעות טלפון ה-Android שלך.</translation>
<translation id="8470028084415844044">כדי שכל הסיסמאות יהיו זמינות בכל המכשירים שברשותך, צריך להפעיל את הסינכרון.</translation>
<translation id="8470513973197838199">סיסמאות שנשמרו בשביל <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">‏כדי להשתמש בכרטיס הזה בכל המכשירים שברשותך, צריך לשמור אותו בחשבון Google</translation>
<translation id="8472623782143987204">גיבוי חומרה</translation>
<translation id="8473863474539038330">כתובות ועוד</translation>
<translation id="8475313423285172237">‏תוכנה אחרת במחשב שלך הוסיפה תוסף שעשוי לשנות את אופן הפעולה של Chrome.</translation>
@@ -5011,7 +5026,6 @@
<translation id="8598453409908276158">פלאגין ללא ארגז חול נחסם</translation>
<translation id="8601206103050338563">‏אימות לקוח TLS WWW</translation>
<translation id="8602851771975208551">‏תכנית אחרת במחשב שלך הוסיפה יישום שעשוי לשנות את אופן הפעולה של Chrome.</translation>
-<translation id="8604763363205185560">‏עזרה בשיפור Chrome והאבטחה שלו</translation>
<translation id="8605428685123651449">‏זיכרון SQLite</translation>
<translation id="8606726445206553943">‏להשתמש במכשירי ה-MIDI שלך</translation>
<translation id="8609465669617005112">הזז למעלה</translation>
@@ -5187,6 +5201,7 @@
<translation id="8846141544112579928">מחפש מקלדת...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">‏חיבור המכשירים מבטא את הסכמתך ש-Chromebook יבצע את הפעולות הבאות:</translation>
+<translation id="8850251000316748990">עוד אפשרויות...</translation>
<translation id="8859057652521303089">בחר שפה:</translation>
<translation id="8859174528519900719">תת-מסגרת: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">‏גיליון אלקטרוני של Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ja.xtb b/chromium/chrome/app/resources/generated_resources_ja.xtb
index a151c3c200c..161c80c8c32 100644
--- a/chromium/chrome/app/resources/generated_resources_ja.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ja.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">テーマを有効にする</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome ウェブストアのページに移動</translation>
-<translation id="1761588866118490543">音声モデル</translation>
<translation id="176193854664720708">指紋認証センサーは電源ボタンに搭載されています。いずれかの指で軽く触れてください。</translation>
<translation id="1763046204212875858">アプリケーションのショートカットを作成</translation>
<translation id="1763108912552529023">さらに確認</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">使用状況データや診断データを送信します。このデバイスは現在、診断データやデバイスとアプリの使用状況データを Google に自動送信するように設定されています。この情報は、システムとアプリの安定性の向上やその他の機能の改善に役立てられます。また、Google のアプリやパートナー(Android デベロッパーなど)も、集計データとしてこの情報を活用します。この設定は所有者によって管理されています。[その他のウェブとアプリのアクティビティ] の設定がオンになっている場合、このデータは Google アカウントに保存されます。<ph name="BEGIN_LINK1" />詳細<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip アーカイブ</translation>
<translation id="220858061631308971">「<ph name="DEVICE_NAME" />」の PIN コードを入力してください:</translation>
+<translation id="2213140827792212876">共有を解除します</translation>
+<translation id="2214018885812055163">共有フォルダ</translation>
<translation id="2214884991347062907">パスワードが正しくありません。もう一度お試しください</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 行が非表示です&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> 行が非表示です&gt;}}</translation>
<translation id="2217501013957346740">名前を作成 -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">証明書が保留になった</translation>
<translation id="2501797496290880632">ショートカットを入力する</translation>
<translation id="2502441965851148920">自動更新が有効になっています。手動更新は管理者によって無効になっています。</translation>
+<translation id="2505127913256479918">この管理対象アカウントはまもなく削除されます</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{画面 #}other{画面 #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" /> 中 <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play ストア アカウント</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">読み上げエンジン</translation>
<translation id="3053013834507634016">証明書キーの用途</translation>
<translation id="3057861065630527966">写真や動画をバックアップします</translation>
+<translation id="3058498974290601450">同期は設定でいつでもオンにできます。</translation>
<translation id="3060379269883947824">「選択して読み上げ」を有効にする</translation>
<translation id="3061707000357573562">サービスへのパッチの適用</translation>
<translation id="3065041951436100775">タブの強制終了に関するフィードバック。</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> がインストールされます。</translation>
<translation id="3380365263193509176">不明なエラー</translation>
<translation id="3382073616108123819">このデバイスの端末識別子を特定できませんでした。</translation>
+<translation id="3382086682569279540">管理対象のアカウントはまもなく削除されます</translation>
<translation id="3382200254148930874">管理機能を停止しています...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">セパレータ</translation>
@@ -1740,14 +1744,14 @@
<translation id="3627320433825461852">あと 1 分未満</translation>
<translation id="3627588569887975815">シークレット ウィンドウで開く(&amp;G)</translation>
<translation id="3627671146180677314">Netscape 証明書更新時間</translation>
-<translation id="3627879631695760395">「<ph name="APP" />」をインストールしています...</translation>
+<translation id="3627879631695760395">「<ph name="APP" />」をインストール...</translation>
<translation id="3630132874740063857">スマートフォン</translation>
<translation id="3630995161997703415">このサイトをシェルフに追加するといつでも使えるようになります</translation>
<translation id="3636096452488277381">こんにちは、<ph name="USER_GIVEN_NAME" /> さん。</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - 残り <ph name="TIME" /></translation>
<translation id="3637682276779847508">正しい PIN ロック解除キーを入力できない場合、SIM カードは永久的に無効になります。</translation>
-<translation id="363863692969456324">改善されたスペルチェック機能でスペルミスを修正する</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> さんのアイテムとして「<ph name="EXTENSION_NAME" />」を追加しますか?</translation>
+<translation id="3640613767643722554">アシスタントに声を認識させましょう</translation>
<translation id="3644896802912593514">幅</translation>
<translation id="3645372836428131288">指紋の別の部分を登録するため、指を少し移動してください。</translation>
<translation id="3648348069317717750">「<ph name="USB_DEVICE_NAME" />」を検出しました</translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">他のタッチペン アプリを探す</translation>
<translation id="424546999567421758">ディスクの使用率が高くなっています</translation>
<translation id="424726838611654458">常に Adobe Reader で開く</translation>
-<translation id="4247330672018280062">テキスト欄に入力したテキストが Google に送信されます</translation>
<translation id="4247901771970415646"><ph name="USERNAME" /> に同期できません</translation>
<translation id="4249248555939881673">ネットワークに接続しています...</translation>
<translation id="4249373718504745892">このページではカメラとマイクへのアクセスがブロックされています。</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">プロファイル記録の開始(&amp;P)</translation>
<translation id="4823484602432206655">ユーザー設定とデバイス設定の読み取りと変更</translation>
<translation id="4823651846660089135">デバイスは読み取り専用です</translation>
+<translation id="4824958205181053313">同期をキャンセルしますか?</translation>
<translation id="4827675678516992122">接続エラー</translation>
<translation id="4828937774870308359">逆方向</translation>
<translation id="4829768588131278040">PIN を設定</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">画像を変更</translation>
<translation id="5376169624176189338">クリックすると前に戻ります。押したまま待つと履歴が表示されます。</translation>
<translation id="5376931455988532197">ファイル サイズが大きすぎます</translation>
+<translation id="5377594097385838788">シークレット</translation>
<translation id="537813040452600081">このウィンドウで開いたページはブラウザ履歴には記録されません。Cookie などの記録も、ログアウトするとパソコンから消去されます。ダウンロードしたファイルや追加したブックマークは保持されません。</translation>
<translation id="5379140238605961210">マイクへのアクセスを引き続きブロックする</translation>
<translation id="5379268888377976432">削除を取り消す</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">アクセスしたウェブサイトのアイコンの読み取り</translation>
<translation id="5417312524372586921">ブラウザのテーマ</translation>
<translation id="5419294236999569767">システムの時刻</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">テキストと画像をどの程度鮮明に表示するかを指定します</translation>
<translation id="5422221874247253874">アクセス ポイント</translation>
<translation id="5422781158178868512">外部ストレージ デバイスを認識できませんでした。</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 RSA 暗号化</translation>
<translation id="5436492226391861498">プロキシ トンネルの待機中...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> を検索:</translation>
+<translation id="543806387003274181">ファイルを保存して新しいアカウントを今すぐ作成してください。</translation>
<translation id="5438224778284622050">オフライン ファイルを削除しますか?</translation>
<translation id="544083962418256601">ショートカットを作成...</translation>
<translation id="5442228125690314719">ディスク イメージの作成中にエラーが発生しました。もう一度お試しください。</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">この拡張機能では、ホーム ボタンのクリック時、またはアドレスバーからの検索時に表示されるページも制御されます。</translation>
<translation id="5971037678316050792">Bluetooth アダプタの状態とペア設定の制御</translation>
<translation id="5972017421290582825">MIDI の設定を管理...</translation>
+<translation id="597235323114979258">その他の印刷先</translation>
+<translation id="5972666587303800813">機能なしのサービス</translation>
<translation id="5972708806901999743">トップに移動</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> を起動</translation>
<translation id="5975792506968920132">バッテリー残量(%)</translation>
@@ -3421,7 +3430,7 @@
<translation id="6163363155248589649">標準(&amp;N)</translation>
<translation id="6163522313638838258">すべてを展開...</translation>
<translation id="6164005077879661055">この監視対象ユーザーを削除すると、このユーザーに関連付けられたすべてのファイルとローカル データも完全に削除されます。この監視対象ユーザーがアクセスしたウェブサイトやこのユーザーの設定は引き続き、管理者が <ph name="MANAGEMENT_URL" /> で見ることができます。</translation>
-<translation id="6165508094623778733">詳細</translation>
+<translation id="6165508094623778733">詳しく見る</translation>
<translation id="6166185671393271715">Chrome にパスワードをインポート</translation>
<translation id="6169040057125497443">マイクを確認してください。</translation>
<translation id="6169666352732958425">デスクトップをキャストできません。</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">共有</translation>
<translation id="6528513914570774834">この端末の他のユーザーにこのネットワークの使用を許可する</translation>
<translation id="652948702951888897">Chrome 履歴</translation>
+<translation id="6530186581263215931">管理者が行った設定です</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> を同期しています...</translation>
<translation id="6531282281159901044">危険なファイルを保存</translation>
<translation id="6532101170117367231">Google ドライブに保存</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">閲覧履歴の読み取りと変更</translation>
<translation id="7019805045859631636">速い</translation>
<translation id="7022562585984256452">ホームページが設定されました。</translation>
-<translation id="702384510542929236">一部のシステム情報とページのコンテンツを匿名化して Google に送信します</translation>
<translation id="7025190659207909717">モバイル データ サービスの管理</translation>
<translation id="7027125358315426638">データベース名:</translation>
<translation id="7029809446516969842">パスワード</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">壁紙アプリを開きます</translation>
<translation id="7290242001003353852">このログイン サービスは <ph name="SAML_DOMAIN" /> でホストされており、カメラにアクセスしています。</translation>
<translation id="7290594223351252791">登録の確認</translation>
+<translation id="7292696521213967957">アシスタントをデバッグするための情報</translation>
<translation id="7295662345261934369">他のユーザーと共有</translation>
<translation id="729583233778673644">AES 暗号化と RC4 暗号化を許可します。なお RC4 暗号は安全でないため、このオプションを使用するとリスクが高まります。</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> 利用規約</translation>
@@ -4254,7 +4264,6 @@
<translation id="7456847797759667638">場所を開く...</translation>
<translation id="7461924472993315131">固定</translation>
<translation id="7463006580194749499">ユーザーを追加</translation>
-<translation id="7464902436585505072">「OK Google」音声モデル</translation>
<translation id="7465778193084373987">Netscape 証明書取り消し URL</translation>
<translation id="7469894403370665791">このネットワークに自動接続する</translation>
<translation id="747114903913869239">エラー: 拡張機能をデコードできません</translation>
@@ -4282,6 +4291,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> および関連付けられているデータはこのデバイスから削除されます。</translation>
<translation id="7497215489070763236">サーバーの CA 証明書</translation>
<translation id="7497981768003291373">最近記録された WebRTC テキストログはありません。</translation>
+<translation id="7502199377020483660">お使いのすべてのデバイスでこれらのカードを使用できるようにするには、Google アカウントにカードを保存します</translation>
<translation id="7502658306369382406">IPv6 アドレス</translation>
<translation id="7503191893372251637">Netscape 証明書タイプ</translation>
<translation id="7503821294401948377">ブラウザ操作のアイコン「<ph name="ICON" />」を読み込むことができませんでした。</translation>
@@ -4379,6 +4389,7 @@
<translation id="7663719505383602579">レシーバー: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">サポートされていない Bluetooth デバイス: 「<ph name="DEVICE_NAME" />」</translation>
<translation id="7665369617277396874">アカウントを追加</translation>
+<translation id="7667248760110172428">外部ストレージ</translation>
<translation id="7671130400130574146">システム タイトル バーと枠線の使用</translation>
<translation id="7672520070349703697"><ph name="PAGE_TITLE" /> 内の <ph name="HUNG_IFRAME_URL" /> が停止しています。</translation>
<translation id="7676867886086876795">テキスト欄で音声入力できるように Google に音声を送信します。</translation>
@@ -4582,6 +4593,7 @@
<translation id="7930294771522048157">保存したお支払い方法がここに表示されます</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> が画面と音声を共有しています。</translation>
<translation id="7931318309563332511">不明</translation>
+<translation id="7932969338829957666">共有フォルダは Linux では <ph name="BASE_DIR" /> にあります。</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{サイトのミュートを解除}other{サイトのミュートを解除}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> から、保護されたコンテンツの再生許可を求められています。デバイスの識別情報が Google により確認されます。</translation>
<translation id="793531125873261495">仮想マシンのダウンロード中にエラーが発生しました。もう一度お試しください。</translation>
@@ -4673,6 +4685,7 @@
<translation id="8049705080247101012">「<ph name="EXTENSION_NAME" />」は、不正な拡張機能として認識されているためインストールされませんでした</translation>
<translation id="8049913480579063185">拡張機能名</translation>
<translation id="8050038245906040378">Microsoft 商用コード署名</translation>
+<translation id="8052887694493382350">このファイルは Windows ソフトウェアを使用する PC 向けのもので、Chrome OS を実行するデバイスとは互換性がありません。<ph name="BEGIN_LINK_HELP" />詳細<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 ファイル</translation>
<translation id="8053390638574070785">ページを再読み込み</translation>
<translation id="8054517699425078995">この種類のファイルはお使いの端末に悪影響を与える可能性があります。<ph name="FILE_NAME" />を保存しますか?</translation>
@@ -4916,6 +4929,7 @@
<translation id="8438566539970814960">検索とブラウジングを改善する</translation>
<translation id="8439506636278576865">この言語のページで翻訳ツールを表示する</translation>
<translation id="8440630305826533614">Linux アプリ</translation>
+<translation id="8443338615972234259">監視対象ユーザー用の新しいアカウントを今すぐ作成してください。</translation>
<translation id="8446884382197647889">詳細</translation>
<translation id="8447409163267621480">Ctrl キーまたは Alt キーが必要です</translation>
<translation id="8448729345478502352">画面上のアイテムのサイズを変更します</translation>
@@ -4940,6 +4954,7 @@
<translation id="8468750959626135884">Android スマートフォンで <ph name="DEVICE_TYPE" /> のロックを解除します。</translation>
<translation id="8470028084415844044">お使いのどの端末でも同じパスワードを使用するには、同期を有効にします。</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" /> 用に保存されているパスワード</translation>
+<translation id="8471635086304129332">お使いのすべてのデバイスでこのカードを使用できるようにするには、Google アカウントにカードを保存します</translation>
<translation id="8472623782143987204">ハードウェア式</translation>
<translation id="8473863474539038330">住所やその他の情報</translation>
<translation id="8475313423285172237">パソコン上の別のプログラムにより、Chrome の動作方法を変更する可能性のある拡張機能が追加されました。</translation>
@@ -5015,7 +5030,6 @@
<translation id="8598453409908276158">サンドボックスの無効化プラグインがブロックされました</translation>
<translation id="8601206103050338563">TLS WWW クライアント認証</translation>
<translation id="8602851771975208551">パソコン上の別のプログラムにより、Chrome の動作方法を変更する可能性のあるアプリが追加されました。</translation>
-<translation id="8604763363205185560">Chrome とそのセキュリティの向上に協力する</translation>
<translation id="8605428685123651449">SQLite メモリ</translation>
<translation id="8606726445206553943">MIDI デバイスの使用</translation>
<translation id="8609465669617005112">上に移動</translation>
@@ -5191,6 +5205,7 @@
<translation id="8846141544112579928">キーボードを探しています...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">デバイスを接続する場合、Chromebook による次の操作を許可することになります。</translation>
+<translation id="8850251000316748990">もっと見る...</translation>
<translation id="8859057652521303089">言語の選択:</translation>
<translation id="8859174528519900719">サブフレーム: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel スプレッドシート</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_kn.xtb b/chromium/chrome/app/resources/generated_resources_kn.xtb
index c6c35706e67..f7863fd8fc9 100644
--- a/chromium/chrome/app/resources/generated_resources_kn.xtb
+++ b/chromium/chrome/app/resources/generated_resources_kn.xtb
@@ -127,7 +127,7 @@
<translation id="1177138678118607465">ಹುಡುಕಾಟ, ಜಾಹೀರಾತುಗಳು ಮತ್ತು ಇತರ Google ಸೇವೆಗಳನ್ನು ವೈಯಕ್ತೀಕರಿಸಲು ನಿಮ್ಮ ಬ್ರೌಸಿಂಗ್ ಇತಿಹಾಸವನ್ನು Google ಬಳಸಬಹುದು. ನೀವು ಇದನ್ನು myaccount.google.com/activitycontrols/search ನಲ್ಲಿ ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು</translation>
<translation id="1177863135347784049">ಕಸ್ಟಮ್</translation>
<translation id="1178581264944972037">ವಿರಾಮ</translation>
-<translation id="1181037720776840403">ತೆಗೆದುಹಾಕಿ</translation>
+<translation id="1181037720776840403">ತೆಗೆದುಹಾಕು</translation>
<translation id="1183237619868651138"><ph name="EXTERNAL_CRX_FILE" /> ಅನ್ನು ಸ್ಥಳೀಯ ಸಂಗ್ರಹದಲ್ಲಿ ಸ್ಥಾಪಿಸಲಾಗುವುದಿಲ್ಲ.</translation>
<translation id="1185924365081634987">ಈ ನೆಟ್‌ವರ್ಕ್‌ ದೋಷವನ್ನು ಬಗೆಹರಿಸಲು <ph name="GUEST_SIGNIN_LINK_START" />ಅತಿಥಿಯಾಗಿ ಬ್ರೌಸ್ ಮಾಡುವುದನ್ನು<ph name="GUEST_SIGNIN_LINK_END" /> ಕೂಡಾ ನೀವು ಪ್ರಯತ್ನಿಸಬಹುದು.</translation>
<translation id="1186771945450942097">ಹಾನಿಕಾರಕ ಸಾಫ್ಟ್‌ವೇರ್ ತೆಗೆದುಹಾಕಿ</translation>
@@ -515,7 +515,6 @@
<translation id="175772926354468439">ಥೀಮ್ ಸಕ್ರಿಯಗೊಳಿಸು</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome ವೆಬ್‌ ಸ್ಟೋರ್‌ನಲ್ಲಿ ವೀಕ್ಷಿಸಿ</translation>
-<translation id="1761588866118490543">ಧ್ವನಿ ಮಾದರಿ</translation>
<translation id="176193854664720708">ಪವರ್ ಬಟನ್‌ನಲ್ಲಿ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಇದೆ. ಯಾವುದೇ ಬೆರಳಿನಿಂದ ಅದನ್ನು ಲಘುವಾಗಿ ಸ್ಪರ್ಶಿಸಿ.</translation>
<translation id="1763046204212875858">ಅಪ್ಲಿಕೇಶನ್ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ರಚಿಸಿ</translation>
<translation id="1763108912552529023">ಅನ್ವೇಷಣೆ ಮುಂದುವರಿಸು</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">ಬಳಕೆ ಮತ್ತು ಡಯಾಗ್ನಾಸ್ಟಿಕ್ ಡೇಟಾವನ್ನು ಕಳುಹಿಸಿ. ಪ್ರಸ್ತುತ ಈ ಸಾಧನವು ಡಯಾಗ್ನಾಸ್ಟಿಕ್, ಸಾಧನ, ಮತ್ತು ಆ್ಯಪ್ ಬಳಕೆಯ ಡೇಟಾವನ್ನು Google ಗೆ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕಳುಹಿಸುತ್ತಿದೆ. ಇದು ಸಿಸ್ಟಮ್ ಮತ್ತು ಆ್ಯಪ್ ಸ್ಥಿರತೆಗೆ, ಹಾಗೂ ಇತರ ಸುಧಾರಣೆಗಳಿಗೆ ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಕೆಲವು ಒಟ್ಟುಗೂಡಿಸಿದ ಡೇಟಾವು, Google ಆ್ಯಪ್‌ಗಳಿಗೆ ಮತ್ತು ಪಾಲುದಾರರಿಗೂ ಸಹ ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, Android ಡೆವಲಪರ್‌ಗಳು. ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಮಾಲೀಕರೇ ಜಾರಿಗೊಳಿಸುತ್ತಾರೆ. ನಿಮ್ಮ ಹೆಚ್ಚುವರಿ ವೆಬ್‌ ಮತ್ತು ಆ್ಯಪ್ ಚಟುವಟಿಕೆ ಸೆಟ್ಟಿಂಗ್ ಆನ್‌ ಆಗಿದ್ದಲ್ಲಿ, ಈ ಡೇಟಾವು ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಉಳಿಸಲ್ಪಡಬಹುದು. <ph name="BEGIN_LINK1" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">ಜಿಪ್ ಆರ್ಕೈವ್</translation>
<translation id="220858061631308971">ದಯವಿಟ್ಟು "<ph name="DEVICE_NAME" />" ಇದರಲ್ಲಿ ಈ ಪಿನ್ ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ :</translation>
+<translation id="2213140827792212876">ಹಂಚಿಕೆಯನ್ನು ತೆಗೆದುಹಾಕಿ</translation>
+<translation id="2214018885812055163">ಹಂಚಿದ ಫೋಲ್ಡರ್‌ಗಳು</translation>
<translation id="2214884991347062907">ಪಾಸ್‌ವರ್ಡ್‌ ತಪ್ಪಾಗಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 ಸಾಲನ್ನು ತೋರಿಸಿಲ್ಲ&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> ಸಾಲುಗಳನ್ನು ತೋರಿಸಿಲ್ಲ&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> ಸಾಲುಗಳನ್ನು ತೋರಿಸಿಲ್ಲ&gt;}}</translation>
<translation id="2217501013957346740">ಹೆಸರು ರಚಿಸಿ -</translation>
@@ -1011,6 +1012,7 @@
<translation id="2501173422421700905">ತಡೆಹಿಡಿಯಲಾದ ಪ್ರಮಾಣಪತ್ರ</translation>
<translation id="2501797496290880632">ಶಾರ್ಟ್‌‌ಕಟ್‌ ಅನ್ನು ಟೈಪ್ ಮಾಡಿ</translation>
<translation id="2502441965851148920">ಸ್ವಯಂಚಾಲಿತ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ. ಹಸ್ತಚಾಲಿತ ಅಪ್‌ಡೇಟ್‌ಗಳನ್ನು ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ.</translation>
+<translation id="2505127913256479918">ಈ ಮೇಲ್ವಿಚಾರಣೆಯ ಖಾತೆಯನ್ನು ಶೀಘ್ರವೇ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{ಸ್ಕ್ರೀನ್ #}one{ಸ್ಕ್ರೀನ್ #}other{ಸ್ಕ್ರೀನ್ #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" /> ರಲ್ಲಿ <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play ಸ್ಟೋರ್ ಖಾತೆ</translation>
@@ -1371,6 +1373,7 @@
<translation id="304747341537320566">ಧ್ವನಿ ಎಂಜಿನ್‌ಗಳು</translation>
<translation id="3053013834507634016">ಪ್ರಮಾಣಪತ್ರ ಕೀಲಿ ಬಳಕೆ</translation>
<translation id="3057861065630527966">ನಿಮ್ಮ ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಬ್ಯಾಕಪ್ ಮಾಡಿ</translation>
+<translation id="3058498974290601450">ನೀವು ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಯಾವಾಗ ಬೇಕಾದರೂ ಸಿಂಕ್ ಆನ್ ಮಾಡಬಹುದು</translation>
<translation id="3060379269883947824">ಆಯ್ಕೆಮಾಡಿ ಮತ್ತು ಆಲಿಸಿಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ</translation>
<translation id="3061707000357573562">ಪ್ಯಾಚ್ ಸೇವೆ</translation>
<translation id="3065041951436100775">ಟ್ಯಾಬ್ ನಾಶಪಡಿಸಿದ ಪ್ರತಿಕ್ರಿಯೆ.</translation>
@@ -1562,6 +1565,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> ಸ್ಥಾಪನೆಮಾಡಲಾಗುತ್ತದೆ</translation>
<translation id="3380365263193509176">ಅಪರಿಚಿತ ದೋಷ</translation>
<translation id="3382073616108123819">ಓಹ್‌‌! ಈ ಸಾಧನಕ್ಕಾಗಿ ಸಾಧನ ಗುರುತಿಸುವಿಕೆಗಳನ್ನು ನಿರ್ಧರಿಸುವಲ್ಲಿ ಸಿಸ್ಟಂ ವಿಫಲಗೊಂಡಿದೆ.</translation>
+<translation id="3382086682569279540">ನೀವು ನಿರ್ವಹಿಸುತ್ತಿರುವ ಖಾತೆಯನ್ನು ಶೀಘ್ರವೇ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ</translation>
<translation id="3382200254148930874">ಮೇಲ್ವಿಚಾರಣೆಯನ್ನು ನಿಲ್ಲಿಸಲಾಗುತ್ತಿದೆ...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">ವಿಭಾಜಕ</translation>
@@ -1742,8 +1746,8 @@
<translation id="3636096452488277381">ಹೇಗಿರುವಿರಿ, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> ಉಳಿದಿದೆ</translation>
<translation id="3637682276779847508">ನೀವು ಸರಿಯಾದ ಪಿನ್ ಅನ್‌ಲಾಕ್ ಕೀಯನ್ನು ನಮೂದಿಸದಿದ್ದಲ್ಲಿ ನಿಮ್ಮ ಸಿಮ್ ಕಾರ್ಡ್ ಅನ್ನು ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗುತ್ತದೆ.</translation>
-<translation id="363863692969456324">ವರ್ಧಿತ ಕಾಗುಣಿತ ಪರೀಕ್ಷೆಯನ್ನು ಬಳಸಿಕೊಂಡು ಕಾಗುಣಿತ ದೋಷಗಳನ್ನು ಸರಿಪಡಿಸಿ</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> ಬಳಕೆದಾರರಿಗೆ "<ph name="EXTENSION_NAME" />" ವಿಸ್ತರಣೆಯನ್ನು ಸೇರಿಸುವುದೇ?</translation>
+<translation id="3640613767643722554">ನಿಮ್ಮ ಅಸಿಸ್ಟೆಂಟ್‌ಗೆ ನಿಮ್ಮ ಧ್ವನಿಯನ್ನು ಗುರುತಿಸಲು ಕಲಿಸಿ</translation>
<translation id="3644896802912593514">ಅಗಲ</translation>
<translation id="3645372836428131288">ಫಿಂಗರ್‌‌ಪ್ರಿಂಟ್‌‌ನ ಬೇರೊಂದು ಭಾಗವನ್ನು ಸೆರೆಹಿಡಿಯಲು ಬೆರಳನ್ನು ನಿಧಾನವಾಗಿ ಸರಿಸಿ.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> ಪತ್ತೆ ಮಾಡಲಾಗಿದೆ</translation>
@@ -2143,7 +2147,6 @@
<translation id="4244238649050961491">ಇನ್ನಷ್ಟು ಸ್ಟೈಲಸ್ ಅಪ್ಲಿಕೇಶನ್‌‌ಗಳನ್ನು ಹುಡುಕಿ</translation>
<translation id="424546999567421758">ಅಧಿಕ ಡಿಸ್ಕ್ ಬಳಕೆಯನ್ನು ಪತ್ತೆ ಹಚ್ಚಲಾಗಿದೆ</translation>
<translation id="424726838611654458">ಯಾವಾಗಲೂ Adobe Reader ನಲ್ಲಿ ತೆರೆಯಿರಿ</translation>
-<translation id="4247330672018280062">ನೀವು ಪಠ್ಯ ಕ್ಷೇತ್ರಗಳಲ್ಲಿ ಟೈಪ್ ಮಾಡುವ ಪಠ್ಯವನ್ನು Google ಗೆ ಕಳುಹಿಸಲಾಗುತ್ತದೆ.</translation>
<translation id="4247901771970415646"><ph name="USERNAME" /> ಗೆ ಸಿಂಕ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ</translation>
<translation id="4249248555939881673">ನೆಟ್‌ವರ್ಕ್ ಸಂಪರ್ಕಕ್ಕಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ...</translation>
<translation id="4249373718504745892">ನಿಮ್ಮ ಕ್ಯಾಮರಾ ಹಾಗೂ ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಪ್ರವೇಶಿಸುವುದರಿಂದ ಈ ಪುಟವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ.</translation>
@@ -2486,6 +2489,7 @@
</translation>
<translation id="4823484602432206655">ಬಳಕೆದಾರ ಮತ್ತು ಸಾಧನ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಓದಿ ಹಾಗೂ ಬದಲಾಯಿಸಿ</translation>
<translation id="4823651846660089135">ಸಾಧನ ಓದಲು ಮಾತ್ರ ಆಗಿದೆ</translation>
+<translation id="4824958205181053313">ಸಿಂಕ್ ರದ್ದುಗೊಳಿಸುವುದೇ?</translation>
<translation id="4827675678516992122">ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ</translation>
<translation id="4828937774870308359">ಆಸ್ಟ್ರೇಲಿಯನ್</translation>
<translation id="4829768588131278040">ಪಿನ್ ಹೊಂದಿಸು</translation>
@@ -2870,6 +2874,7 @@
<translation id="5374359983950678924">ಚಿತ್ರವನ್ನು ಬದಲಿಸಿ</translation>
<translation id="5376169624176189338">ಹಿಂದಕ್ಕೆ ಹೋಗಲು ಕ್ಲಿಕ್ ಮಾಡಿ, ಇತಿಹಾಸ ವೀಕ್ಷಿಸಲು ಒತ್ತಿಹಿಡಿಯಿರಿ</translation>
<translation id="5376931455988532197">ಫೈಲ್ ತುಂಬಾ ದೊಡ್ಡದಾಗಿದೆ</translation>
+<translation id="5377594097385838788">ಅದೃಶ್ಯ</translation>
<translation id="537813040452600081">ನೀವು ಈ ವಿಂಡೋದಲ್ಲಿ ವೀಕ್ಷಿಸುವ ಪುಟಗಳು ಬ್ರೌಸರ್ ಇತಿಹಾಸದಲ್ಲಿ ಗೋಚರಿಸುವುದಿಲ್ಲ ಮತ್ತು ನೀವು ಸೈನ್ ಔಟ್ ಮಾಡಿದ ನಂತರ, ಅವುಗಳು ಕುಕೀಗಳಂತಹ ಇತರ ಗುರುತುಗಳನ್ನು ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿ ಬಿಡುವುದಿಲ್ಲ. ನೀವು ಡೌನ್‌ಲೋಡ್ ಮಾಡಿದ ಫೈಲ್‌ಗಳು ಮತ್ತು ನೀವು ರಚಿಸಿದ ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳನ್ನು ರಕ್ಷಿಸಲಾಗುವುದಿಲ್ಲ.</translation>
<translation id="5379140238605961210">ಮೈಕ್ರೋಫೋನ್ ಪ್ರವೇಶ ನಿರ್ಬಂಧವನ್ನು ಮುಂದುವರಿಸಿ</translation>
<translation id="5379268888377976432">ಅಳಿಸುವುದನ್ನು ರದ್ದುಗೊಳಿಸಿ</translation>
@@ -2891,6 +2896,7 @@
<translation id="5414566801737831689">ನೀವು ಭೇಟಿ ನೀಡುವ ವೆಬ್‌ಸೈಟ್‌ಗಳ ಐಕಾನ್‌ಗಳನ್ನು ಓದಿರಿ</translation>
<translation id="5417312524372586921">ಬ್ರೌಸರ್ ಥೀಮ್‌ಗಳು</translation>
<translation id="5419294236999569767">ಸಿಸ್ಟಂ ಸಮಯ</translation>
+<translation id="5419405654816502573">ಧ್ವನಿ ಹೊಂದಾಣಿಕೆ</translation>
<translation id="5420438158931847627">ಪಠ್ಯ ಮತ್ತು ಚಿತ್ರಗಳ ತೀಕ್ಷ್ಣತೆಯನ್ನು ನಿರ್ಧರಿಸುತ್ತದೆ</translation>
<translation id="5422221874247253874">ಪ್ರವೇಶ ಬಿಂದು</translation>
<translation id="5422781158178868512">ಕ್ಷಮಸಿ, ನಿಮ್ಮ ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಯ ಸಾಧನವನ್ನು ಗುರುತಿಸಲಾಗಲಿಲ್ಲ.</translation>
@@ -2911,6 +2917,7 @@
<translation id="5434065355175441495">PKCS #1 RSA ಎನ್‌ಕ್ರಿಪ್ಶನ್</translation>
<translation id="5436492226391861498">ಪ್ರಾಕ್ಸಿ ಟನಲ್‌‌ಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> ಹುಡುಕಿ:</translation>
+<translation id="543806387003274181">ದಯವಿಟ್ಟು ನಿಮ್ಮ ಫೈಲ್‌ಗಳನ್ನು ಉಳಿಸಿಕೊಳ್ಳಿ ಮತ್ತು ಈಗಲೇ ಹೊಸದೊಂದು ಖಾತೆಯನ್ನು ರಚಿಸಿ.</translation>
<translation id="5438224778284622050">ಆಫ್‌ಲೈನ್ ಫೈಲ್‌ಗಳನ್ನು ಅಳಿಸುವುದೇ?</translation>
<translation id="544083962418256601">ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ರಚಿಸಿ...</translation>
<translation id="5442228125690314719">ಡಿಸ್ಕ್ ಚಿತ್ರವನ್ನು ರಚಿಸುವಲ್ಲಿ ದೋಷ ಕಂಡುಬಂದಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
@@ -3283,6 +3290,8 @@
<translation id="5965661248935608907">ನೀವು ಮುಖಪುಟ ಬಟನ್ ಕ್ಲಿಕ್ ಮಾಡಿದಾಗ ಅಥವಾ ಓಮ್ನಿಬಾಕ್ಸ್‌ನಿಂದ ಹುಡುಕಿದಾಗ ತೋರಿಸಬೇಕಾದ ಪುಟವನ್ನು ಕೂಡಾ ಇದು ನಿಯಂತ್ರಿಸುತ್ತದೆ.</translation>
<translation id="5971037678316050792">ಬ್ಲೂಟೂತ್‌ ಅಡಾಪ್ಟರ್ ಸ್ಥಿತಿ ಮತ್ತು ಜೋಡಿಸುವಿಕೆಯನ್ನು ನಿಯಂತ್ರಿಸಿ</translation>
<translation id="5972017421290582825">MIDI ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ...</translation>
+<translation id="597235323114979258">ಇನ್ನಷ್ಟು ಗಮ್ಯಸ್ಥಾನಗಳನ್ನು ನೋಡಿ</translation>
+<translation id="5972666587303800813">ಯಾವುದೇ ಕಾರ್ಯಾಚರಣೆ ಸೇವೆಯಿಲ್ಲ</translation>
<translation id="5972708806901999743">ಮೇಲಕ್ಕೆ ಸರಿಸಿ</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> ಪ್ರಾರಂಭಿಸು</translation>
<translation id="5975792506968920132">ಬ್ಯಾಟರಿ ಚಾರ್ಜ್‌ನ ಶೇಕಡಾವಾರು</translation>
@@ -3653,6 +3662,7 @@
<translation id="6527303717912515753">ಹಂಚಿಕೊಳ್ಳು</translation>
<translation id="6528513914570774834">ಈ ನೆಟ್‌ವರ್ಕ್ ಬಳಸಲು, ಈ ಸಾಧನದ ಇತರ ಬಳಕೆದಾರರಿಗೆ ಅವಕಾಶ ನೀಡಿ</translation>
<translation id="652948702951888897">Chrome ಇತಿಹಾಸ</translation>
+<translation id="6530186581263215931">ಈ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಜಾರಿಗೊಳಿಸಿದ್ದಾರೆ</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> ಸಿಂಕ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ...</translation>
<translation id="6531282281159901044">ಅಪಾಯಕಾರಿ ಫೈಲ್ ಇರಿಸು</translation>
<translation id="6532101170117367231">Google ಡ್ರೈವ್‌ನಲ್ಲಿ ಉಳಿಸಿ</translation>
@@ -3970,7 +3980,6 @@
<translation id="7018275672629230621">ನಿಮ್ಮ ಬ್ರೌಸಿಂಗ್‌ ಇತಿಹಾಸವನ್ನು ಓದಿ ಮತ್ತು ಬದಲಾಯಿಸಿ</translation>
<translation id="7019805045859631636">ವೇಗ</translation>
<translation id="7022562585984256452">ನಿಮ್ಮ ಮುಖಪಟವನ್ನು ಹೊಂದಿಸಲಾಗಿದೆ.</translation>
-<translation id="702384510542929236">ಸಿಸ್ಟಂ ಕುರಿತಾದ ಕೆಲವು ಮಾಹಿತಿ ಮತ್ತು ಪುಟದ ವಿಷಯವನ್ನು ಅನಾಮಧೇಯವಾಗಿ Google ಗೆ ಕಳುಹಿಸುತ್ತದೆ</translation>
<translation id="7025190659207909717">ಮೊಬೈಲ್ ಡೇಟಾ ಸೇವೆಯ ನಿರ್ವಹಣೆ
</translation>
<translation id="7027125358315426638">ಡೇಟಾಬೇಸ್ ಹೆಸರು:</translation>
@@ -4032,7 +4041,7 @@
<translation id="7109543803214225826">ಶಾರ್ಟ್‌ಕಟ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ</translation>
<translation id="7113502843173351041">ನಿಮ್ಮ ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ತಿಳಿದುಕೊಳ್ಳಿ</translation>
<translation id="7114054701490058191">ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ</translation>
-<translation id="7114648273807173152">ನಿಮ್ಮ Google ಖಾತೆಗೆ ಸೈನ್ ಇನ್ ಮಾಡಲು Smart Lock ಬಳಸುವುದಕ್ಕೆ, ಸೆಟ್ಟಿಂಗ್‌ಗಳು&gt; ಸಂಪರ್ಕಗೊಂಡಿರುವ ಸಾಧನಗಳು &gt; ನಿಮ್ಮ ಫೋನ್ &gt; Smart Lock ಎಂಬಲ್ಲಿ ಹೋಗಿ.</translation>
+<translation id="7114648273807173152">ನಿಮ್ಮ Google ಖಾತೆಗೆ ಸೈನ್ ಇನ್ ಮಾಡಲು Smart Lock ಬಳಸುವುದಕ್ಕೆ, ಸೆಟ್ಟಿಂಗ್‌ಗಳು &gt; ಸಂಪರ್ಕಗೊಂಡಿರುವ ಸಾಧನಗಳು &gt; ನಿಮ್ಮ ಫೋನ್ &gt; Smart Lock ಎಂಬಲ್ಲಿ ಹೋಗಿ.</translation>
<translation id="7117228822971127758">ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ</translation>
<translation id="7117247127439884114">ಪುನಃ ಸೈನ್ ಇನ್ ಮಾಡಿ...</translation>
<translation id="711840821796638741">ನಿರ್ವಹಿಸಲಾದ ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳನ್ನು ತೋರಿಸು</translation>
@@ -4073,7 +4082,7 @@
<translation id="7171559745792467651">ನಿಮ್ಮ ಇತರ ಸಾಧನಗಳಿಂದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ</translation>
<translation id="7175037578838465313"><ph name="NAME" /> ಅನ್ನು ಕಾನ್ಫಿಗರ್‌ ಮಾಡಿ</translation>
<translation id="7175353351958621980">ಇದರಿಂದ ಲೋಡ್ ಮಾಡಲಾಗಿದೆ:</translation>
-<translation id="7180611975245234373">ರಿಫ್ರೆಶ್</translation>
+<translation id="7180611975245234373">ರಿಫ್ರೆಶ್ ಮಾಡಿ</translation>
<translation id="7180865173735832675">ಕಸ್ಟಮೈಸ್</translation>
<translation id="7182359331070524176">Google ಫೋಟೋಗಳ ಆಲ್ಬಮ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ</translation>
<translation id="7186088072322679094">ಪರಿಕರಪಟ್ಟಿಯಲ್ಲಿ ಇರಿಸು</translation>
@@ -4151,6 +4160,7 @@
<translation id="7289225569524511578">ವಾಲ್‌ಪೇಪರ್ ಅಪ್ಲಿಕೇಶನ್ ತೆರೆಯಿರಿ</translation>
<translation id="7290242001003353852">ಈ ಸೈನ್ ಇನ್ ಸೇವೆಯನ್ನು <ph name="SAML_DOMAIN" /> ಮೂಲಕ ಹೋಸ್ಟ್ ಮಾಡಲಾಗಿದೆ, ಇದು ನಿಮ್ಮ ಕ್ಯಾಮರಾವನ್ನು ಪ್ರವೇಶಿಸುತ್ತದೆ.</translation>
<translation id="7290594223351252791">ನೋಂದಣಿಯನ್ನು ದೃಢೀಕರಿಸಿ</translation>
+<translation id="7292696521213967957">ಅಸಿಸ್ಟೆಂಟ್ ಡೀಬಗ್‌ಗೆ ಮಾಹಿತಿ</translation>
<translation id="7295662345261934369">ಇತರರೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಿ</translation>
<translation id="729583233778673644">AES ಮತ್ತು RC4 ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಅನ್ನು ಅನುಮತಿಸಿ . RC4 ಸೈಫರ್‌ಗಳು ಅಸುರಕ್ಷಿತವಾಗಿರುವುದರಿಂದ ಈ ಆಯ್ಕೆಯನ್ನು ಬಳಸುವುದು ನಿಮ್ಮ ಅಪಾಯವನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> ನಿಯಮಗಳು</translation>
@@ -4251,7 +4261,6 @@
<translation id="7456847797759667638">ಸ್ಥಳವನ್ನು ತೆರೆ...</translation>
<translation id="7461924472993315131">ಪಿನ್</translation>
<translation id="7463006580194749499">ವ್ಯಕ್ತಿಯನ್ನು ಸೇರಿಸು</translation>
-<translation id="7464902436585505072">"ಓಕೆ Google" ಧ್ವನಿ ಮಾದರಿ</translation>
<translation id="7465778193084373987">Netscape ಪ್ರಮಾಣಪತ್ರ ಹಿಂತೆಗೆದುಕೊಳ್ಳುವಿಕೆ URL</translation>
<translation id="7469894403370665791">ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಿ</translation>
<translation id="747114903913869239">ದೋಷ: ವಿಸ್ತರಣೆಯನ್ನು ಡಿಕೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ</translation>
@@ -4277,6 +4286,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> ಮತ್ತು ಅದಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾವನ್ನು ಈ ಸಾಧನದಿಂದ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ.</translation>
<translation id="7497215489070763236">ಸರ್ವರ್ CA ಪ್ರಮಾಣಪತ್ರ</translation>
<translation id="7497981768003291373">ನಿಮ್ಮಲ್ಲಿ ಇತ್ತೀಚೆಗೆ ಕ್ಯಾಪ್ಚರ್‌ ಆಗಿರುವ WebRTC ಪಠ್ಯ ಲಾಗ್‌ಗಳು ಇಲ್ಲ.</translation>
+<translation id="7502199377020483660">ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಲ್ಲಿ ಈ ಕಾರ್ಡ್‌ಗಳನ್ನು ಬಳಸಲು, ಅವುಗಳನ್ನು ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಉಳಿಸಿ</translation>
<translation id="7502658306369382406">IPv6 ವಿಳಾಸ</translation>
<translation id="7503191893372251637">Netscape ಪ್ರಮಾಣಪತ್ರ ಪ್ರಕಾರ</translation>
<translation id="7503821294401948377">ಬ್ರೌಸರ್ ಕ್ರಿಯೆಗಾಗಿ '<ph name="ICON" />' ಐಕಾನ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ.</translation>
@@ -4374,6 +4384,7 @@
<translation id="7663719505383602579">ರಿಸೀವರ್: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">ಬೆಂಬಲಿಸದಿರುವ ಬ್ಲೂಟೂತ್ ಸಾಧನ: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">ಖಾತೆಯನ್ನು ಸೇರಿಸು</translation>
+<translation id="7667248760110172428">ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆ</translation>
<translation id="7671130400130574146">ಸಿಸ್ಟಂ ಶೀರ್ಷಿಕೆ ಪಟ್ಟಿ ಮತ್ತು ಅಂಚುಗಳನ್ನು ಬಳಸಿ</translation>
<translation id="7672520070349703697"><ph name="PAGE_TITLE" /> ನಲ್ಲಿ <ph name="HUNG_IFRAME_URL" /></translation>
<translation id="7676867886086876795">ಯಾವುದೇ ಪಠ್ಯ ಫೀಲ್ಡ್‌ನಲ್ಲಿ ಡಿಕ್ಟೇಷನ್ ಅನ್ನು ಅನುಮತಿಸಲು ನಿಮ್ಮ ಧ್ವನಿಯನ್ನು Google ಗೆ ಕಳುಹಿಸಿ.</translation>
@@ -4572,6 +4583,7 @@
<translation id="7930294771522048157">ಉಳಿಸಲಾದ ಪಾವತಿ ವಿಧಾನಗಳು ಇಲ್ಲಿ ಗೋಚರಿಸುತ್ತವೆ</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> ನಿಮ್ಮ ಪರದೆ ಮತ್ತು ಆಡಿಯೋವನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿದೆ.</translation>
<translation id="7931318309563332511">ಅಪರಿಚಿತ</translation>
+<translation id="7932969338829957666">ಹಂಚಿದ ಫೋಲ್ಡರ್‌ಗಳು Linux ನಲ್ಲಿ <ph name="BASE_DIR" /> ಎಂಬಲ್ಲಿ ಲಭ್ಯವಿರುತ್ತವೆ.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{ಸೈಟ್‌ ಅನ್ನು ಅನ್‌ಮ್ಯೂಟ್‌ ಮಾಡಿ}one{ಸೈಟ್‌ಗಳನ್ನು ಅನ್‌ಮ್ಯೂಟ್‌ ಮಾಡಿ}other{ಸೈಟ್‌ಗಳನ್ನು ಅನ್‌ಮ್ಯೂಟ್‌ ಮಾಡಿ}}</translation>
<translation id="7934414805353235750">ಸಂರಕ್ಷಿಸಲಾದ ವಿಷಯವನ್ನು ಪ್ಲೇ ಮಾಡಲು <ph name="URL" /> ಬಯಸುತ್ತದೆ. ನಿಮ್ಮ ಸಾಧನದ ಗುರುತನ್ನು Google ಪರಿಶೀಲಿಸುವುದು.</translation>
<translation id="793531125873261495">ವರ್ಚುವಲ್ ಯಂತ್ರವನ್ನು ಡೌನ್‌ಲೋಡ್‌ ಮಾಡುವಲ್ಲಿ ದೋಷ ಕಂಡುಬಂದಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
@@ -4661,6 +4673,7 @@
<translation id="8049705080247101012"><ph name="EXTENSION_NAME" /> ದೋಷಪೂರಿತವೆಂದು Google ಫ್ಲ್ಯಾಗ್ ಮಾಡಿದೆ ಹಾಗೂ ಅದರ ಇನ್‌ಸ್ಟಾಲೇಶನ್ ಅನ್ನು ತಡೆಗಟ್ಟಲಾಗಿದೆ</translation>
<translation id="8049913480579063185">ವಿಸ್ತರಣೆಯ ಹೆಸರು</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">ಈ ಫೈಲ್ ಅನ್ನು Windows ಸಾಫ್ಟ್‌ವೇರ್ ಬಳಸುವ PC ಗಾಗಿ ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ. Chrome OS ನಲ್ಲಿ ರನ್ ಆಗುವ ನಿಮ್ಮ ಸಾಧನದ ಜೊತೆಗೆ ಇದು ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ. <ph name="BEGIN_LINK_HELP" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 ಫೈಲ್‌ಗಳು</translation>
<translation id="8053390638574070785">ಈ ಪುಟವನ್ನು ರೀಲೋಡ್ ಮಾಡಿ</translation>
<translation id="8054517699425078995">ಈ ಫೈಲ್ ಪ್ರಕಾರವು ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಹಾನಿಮಾಡಬಹುದು. ಆದರೂ ನೀವು <ph name="FILE_NAME" /> ಅನ್ನು ಇರಿಸಿಕೊಳ್ಳಲು ಬಯಸುವಿರಾ?</translation>
@@ -4905,6 +4918,7 @@
<translation id="8438566539970814960">ಹುಡುಕಾಟಗಳನ್ನು ಮತ್ತು ಬ್ರೌಸಿಂಗ್ ಅನ್ನು ಉತ್ತಮಗೊಳಿಸುವಂತೆ ಮಾಡಿ</translation>
<translation id="8439506636278576865">ಪುಟಗಳನ್ನು ಈ ಭಾಷೆಯಲ್ಲಿ ಅನುವಾದ ಮಾಡಲು ಅವಕಾಶ</translation>
<translation id="8440630305826533614">Linux ಆ್ಯಪ್‌ಗಳು</translation>
+<translation id="8443338615972234259">ನಿಮ್ಮ ಮೇಲ್ವಿಚಾರಣೆಯ ಬಳಕೆದಾರರಿಗಾಗಿ ಈಗಲೇ ಒಂದು ಹೊಸ ಖಾತೆಯನ್ನು ರಚಿಸಿ.</translation>
<translation id="8446884382197647889">ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ</translation>
<translation id="8447409163267621480">Ctrl ಅಥವಾ Alt ಅನ್ನು ಒಳಗೊಂಡಿದೆ</translation>
<translation id="8448729345478502352">ನಿಮ್ಮ ಪರದೆಯ ಮೇಲೆ ಐಟಂಗಳನ್ನು ಸಣ್ಣದು ಅಥವಾ ದೊಡ್ಡದು ಮಾಡಿ</translation>
@@ -4931,6 +4945,7 @@
<translation id="8468750959626135884">ನಿಮ್ಮ Android ಫೋನ್ ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ <ph name="DEVICE_TYPE" /> ಅನ್‌ಲಾಕ್ ಮಾಡಿ.</translation>
<translation id="8470028084415844044">ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಲ್ಲಿ ನಿಮ್ಮ ಎಲ್ಲಾ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಪಡೆದುಕೊಳ್ಳಲು, ಸಿಂಕ್ ಆನ್ ಮಾಡಿ.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" /> ಗಾಗಿ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</translation>
+<translation id="8471635086304129332">ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಲ್ಲಿ ಈ ಕಾರ್ಡ್ ಬಳಸಲು, ಅದನ್ನು ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಉಳಿಸಿ</translation>
<translation id="8472623782143987204">ಹಾರ್ಡ್‌ವೇರ್-ಹಿಂತಿರುಗಿಸಿದೆ</translation>
<translation id="8473863474539038330">ವಿಳಾಸಗಳು ಮತ್ತು ಇನ್ನಷ್ಟು</translation>
<translation id="8475313423285172237">ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿನ ಮತ್ತೊಂದು ಪ್ರೋಗ್ರಾಂ Chrome ಕಾರ್ಯನಿರ್ವಹಿಸುವ ವಿಧಾನವನ್ನು ಬದಲಿಸಬಹುದಾದಂತಹ ವಿಸ್ತರಣೆಯನ್ನು ಸೇರಿಸಿದೆ.</translation>
@@ -5006,7 +5021,6 @@
<translation id="8598453409908276158">ಸ್ಯಾಂಡ್‌ಬಾಕ್ಸ್ ರದ್ದುಗೊಳಿಸಿರುವ ಪ್ಲಗ್ ಇನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
<translation id="8601206103050338563">TLS WWW ಗ್ರಾಹಕ ಅಪ್ಲಿಕೇಶನ್</translation>
<translation id="8602851771975208551">ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿನ ಮತ್ತೊಂದು ಪ್ರೋಗ್ರಾಂ Chrome ಕಾರ್ಯನಿರ್ವಹಿಸುವ ವಿಧಾನವನ್ನು ಬದಲಿಸಬಹುದಾದಂತಹ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸೇರಿಸಿದೆ.</translation>
-<translation id="8604763363205185560">Chrome ಮತ್ತು ಅದರ ಭದ್ರತೆಯನ್ನು ಸುಧಾರಿಸಲು ಸಹಾಯ ಮಾಡಿ</translation>
<translation id="8605428685123651449">SQLite ಸ್ಮರಣೆ</translation>
<translation id="8606726445206553943">ನಿಮ್ಮ MIDI ಸಾಧನಗಳನ್ನು ಬಳಸಿ</translation>
<translation id="8609465669617005112">ಮೇಲೆ ಸರಿಸು</translation>
@@ -5182,6 +5196,7 @@
<translation id="8846141544112579928">ಕೀಬೋರ್ಡ್‍ಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">ನಿಮ್ಮ ಸಾಧನಗಳನ್ನು ನೀವು ಸಂಪರ್ಕಪಡಿಸಿದಾಗ, ನಿಮ್ಮ Chromebook ಇವುಗಳನ್ನು ಮಾಡಬಹುದು ಎಂಬುದನ್ನು ನೀವು ಒಪ್ಪುತ್ತೀರಿ:</translation>
+<translation id="8850251000316748990">ಇನ್ನಷ್ಟು ನೋಡಿ...</translation>
<translation id="8859057652521303089">ನಿಮ್ಮ ಭಾಷೆ ಆಯ್ಕೆ ಮಾಡಿ:</translation>
<translation id="8859174528519900719">ಉಪಫ್ರೇಮ್‌: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel ಸ್ಪ್ರೆಡ್‌ಶೀಟ್</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ko.xtb b/chromium/chrome/app/resources/generated_resources_ko.xtb
index 677164918c7..ba547f94b69 100644
--- a/chromium/chrome/app/resources/generated_resources_ko.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ko.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">테마 사용</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome 웹 스토어에서 보기</translation>
-<translation id="1761588866118490543">음성 모델</translation>
<translation id="176193854664720708">지문 센서는 전원 버튼에 있습니다. 손가락으로 가볍게 터치하세요.</translation>
<translation id="1763046204212875858">애플리케이션 바로가기 만들기</translation>
<translation id="1763108912552529023">계속 살펴보기</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">사용 및 진단 데이터를 보냅니다. 이 기기는 현재 진단, 기기 및 앱 사용 데이터를 Google에 자동으로 보내고 있습니다. 이 데이터는 시스템 및 앱 안정성 등을 개선하는 데 활용됩니다. 일부 수집 데이터는 Google 앱과 파트너(Android 개발자 등)에게도 도움을 줍니다. 이 설정은 소유자가 지정합니다. 추가 웹 및 앱 활동이 사용 설정되어 있다면 이 데이터가 Google 계정에 저장될 수 있습니다. <ph name="BEGIN_LINK1" />자세히 알아보기<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip 아카이브</translation>
<translation id="220858061631308971">'<ph name="DEVICE_NAME" />'의 PIN 코드를 입력하세요:</translation>
+<translation id="2213140827792212876">공유 폴더 삭제</translation>
+<translation id="2214018885812055163">공유 폴더</translation>
<translation id="2214884991347062907">잘못된 비밀번호입니다. 다시 시도하세요.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1줄이 표시되지 않음&gt;}other{&lt;<ph name="NUMBER_OF_LINES" />줄이 표시되지 않음&gt;}}</translation>
<translation id="2217501013957346740">이름 만들기 -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">인증서 보류</translation>
<translation id="2501797496290880632">단축키 입력</translation>
<translation id="2502441965851148920">자동 업데이트가 사용 설정되었습니다. 관리자가 수동 업데이트를 사용 중지했습니다.</translation>
+<translation id="2505127913256479918">이 감독 대상 계정이 곧 삭제됩니다</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{화면 #}other{화면 #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" />중 <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play 스토어 계정</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">음성 엔진</translation>
<translation id="3053013834507634016">인증서 키 사용</translation>
<translation id="3057861065630527966">사진 및 동영상을 백업합니다.</translation>
+<translation id="3058498974290601450">언제든지 설정에서 동기화를 사용 설정할 수 있습니다.</translation>
<translation id="3060379269883947824">텍스트 읽어주기 사용</translation>
<translation id="3061707000357573562">서비스 패치</translation>
<translation id="3065041951436100775">탭 사용 중지 관련 피드백</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" />이(가) 설치됩니다.</translation>
<translation id="3380365263193509176">알 수 없는 오류가 발생했습니다.</translation>
<translation id="3382073616108123819">시스템에서 이 기기의 기기 식별자를 확인하지 못했습니다.</translation>
+<translation id="3382086682569279540">관리 중인 계정이 곧 삭제됩니다</translation>
<translation id="3382200254148930874">감독 기능 중지...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">구분자</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381"><ph name="USER_GIVEN_NAME" />님, 반갑습니다.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> 남음</translation>
<translation id="3637682276779847508">정확한 PIN 잠금 해제 키를 입력하지 않으면 SIM 카드가 영구적으로 사용 중지됩니다.</translation>
-<translation id="363863692969456324">향상된 맞춤법 검사 기술로 맞춤법 오류 수정</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" />님에 대하여 '<ph name="EXTENSION_NAME" />'을(를) 추가할까요?</translation>
+<translation id="3640613767643722554">어시스턴트가 내 음성을 인식하도록 학습시키기</translation>
<translation id="3644896802912593514">너비</translation>
<translation id="3645372836428131288">지문의 다른 부분이 인식되도록 손가락을 살짝 움직이세요.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> 발견됨</translation>
@@ -2145,7 +2149,6 @@
<translation id="4244238649050961491">스타일러스 앱 더보기</translation>
<translation id="424546999567421758">디스크 사용률이 높음</translation>
<translation id="424726838611654458">항상 Adobe Reader에서 열기</translation>
-<translation id="4247330672018280062">입력란에 텍스트를 입력하면 Google로 전송됩니다.</translation>
<translation id="4247901771970415646"><ph name="USERNAME" />과(와) 동기화할 수 없음</translation>
<translation id="4249248555939881673">네트워크 연결 대기 중...</translation>
<translation id="4249373718504745892">카메라와 마이크 액세스가 차단된 페이지입니다.</translation>
@@ -2487,6 +2490,7 @@
<translation id="4821935166599369261">프로파일링 사용(&amp;P)</translation>
<translation id="4823484602432206655">사용자와 기기 설정 확인 및 변경</translation>
<translation id="4823651846660089135">읽기 전용 기기</translation>
+<translation id="4824958205181053313">동기화를 취소하시겠습니까?</translation>
<translation id="4827675678516992122">연결할 수 없음</translation>
<translation id="4828937774870308359">오스트레일리아</translation>
<translation id="4829768588131278040">PIN 설정</translation>
@@ -2869,6 +2873,7 @@
<translation id="5374359983950678924">사진 변경</translation>
<translation id="5376169624176189338">클릭하면 이전 페이지로 가고 누르고 있으면 방문 기록이 나타납니다.</translation>
<translation id="5376931455988532197">파일이 너무 큼</translation>
+<translation id="5377594097385838788">시크릿 모드</translation>
<translation id="537813040452600081">이 창에서 보는 페이지는 브라우저 기록에 나타나지 않으며 로그아웃한 후에도 컴퓨터에 쿠키와 같은 다른 흔적을 남기지 않습니다. 다운로드한 파일과 생성한 북마크는 보관되지 않습니다.</translation>
<translation id="5379140238605961210">마이크 액세스 계속 차단</translation>
<translation id="5379268888377976432">삭제 실행취소</translation>
@@ -2890,6 +2895,7 @@
<translation id="5414566801737831689">방문하는 웹사이트의 아이콘 조회</translation>
<translation id="5417312524372586921">브라우저 테마</translation>
<translation id="5419294236999569767">시스템 시간</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">텍스트와 이미지의 선명도를 결정합니다.</translation>
<translation id="5422221874247253874">액세스포인트</translation>
<translation id="5422781158178868512">죄송합니다. 외부 저장장치를 인식하지 못했습니다.</translation>
@@ -2910,6 +2916,7 @@
<translation id="5434065355175441495">PKCS #1 RSA 암호화</translation>
<translation id="5436492226391861498">프록시 터널을 기다리는 중...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> 검색:</translation>
+<translation id="543806387003274181">지금 파일을 저장하고 새 계정을 만드세요.</translation>
<translation id="5438224778284622050">오프라인 파일을 삭제하시겠습니까?</translation>
<translation id="544083962418256601">바로가기 만들기...</translation>
<translation id="5442228125690314719">디스크 이미지를 생성하는 중 오류가 발생했습니다. 다시 시도해 주세요.</translation>
@@ -3283,6 +3290,8 @@
<translation id="5965661248935608907">또한 홈 버튼을 클릭하거나 검색주소창에서 검색할 때 표시되는 페이지를 설정합니다.</translation>
<translation id="5971037678316050792">블루투스 어댑터 상태 및 페어링을 제어합니다.</translation>
<translation id="5972017421290582825">MIDI 설정 관리...</translation>
+<translation id="597235323114979258">대상 더보기</translation>
+<translation id="5972666587303800813">작동하지 않는 서비스</translation>
<translation id="5972708806901999743">위로 이동</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> 시작</translation>
<translation id="5975792506968920132">배터리 충전율</translation>
@@ -3653,6 +3662,7 @@
<translation id="6527303717912515753">공유</translation>
<translation id="6528513914570774834">이 기기의 다른 사용자가 이 네트워크를 사용하도록 허용</translation>
<translation id="652948702951888897">Chrome 방문 기록</translation>
+<translation id="6530186581263215931">이 설정은 관리자가 시행합니다.</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" />을(를) 동기화하는 중...</translation>
<translation id="6531282281159901044">위험한 파일 보관</translation>
<translation id="6532101170117367231">Google 드라이브에 저장</translation>
@@ -3971,7 +3981,6 @@
<translation id="7018275672629230621">인터넷 사용기록 조회 및 변경</translation>
<translation id="7019805045859631636">빠르게</translation>
<translation id="7022562585984256452">홈페이지가 설정되었습니다.</translation>
-<translation id="702384510542929236">일부 시스템 정보와 페이지 콘텐츠를 익명으로 Google에 전송합니다.</translation>
<translation id="7025190659207909717">모바일 데이터 서비스 관리</translation>
<translation id="7027125358315426638">데이터베이스 이름:</translation>
<translation id="7029809446516969842">비밀번호</translation>
@@ -4151,6 +4160,7 @@
<translation id="7289225569524511578">배경화면 앱 열기</translation>
<translation id="7290242001003353852"><ph name="SAML_DOMAIN" />에서 호스팅하는 이 로그인 서비스는 카메라에 액세스합니다.</translation>
<translation id="7290594223351252791">등록 확인</translation>
+<translation id="7292696521213967957">어시스턴트를 디버그하기 위한 정보</translation>
<translation id="7295662345261934369">다른 사용자와 공유</translation>
<translation id="729583233778673644">AES 및 RC4 암호화를 허용합니다. RC4 암호화는 안전하지 않으므로 이 옵션을 사용하면 보안 위험도가 높아집니다.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> 약관</translation>
@@ -4251,7 +4261,6 @@
<translation id="7456847797759667638">위치 열기...</translation>
<translation id="7461924472993315131">고정</translation>
<translation id="7463006580194749499">사용자 추가</translation>
-<translation id="7464902436585505072">'Ok Google' 음성 모델</translation>
<translation id="7465778193084373987">Netscape Certificate Revocation URL</translation>
<translation id="7469894403370665791">네트워크에 자동 연결</translation>
<translation id="747114903913869239">오류: 확장 프로그램을 디코딩할 수 없음</translation>
@@ -4279,6 +4288,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> 및 관련 데이터가 이 기기에서 삭제됩니다.</translation>
<translation id="7497215489070763236">서버 CA 인증서</translation>
<translation id="7497981768003291373">최근 캡처한 WebRTC 텍스트 로그가 없습니다.</translation>
+<translation id="7502199377020483660">모든 기기에서 이 카드를 사용하려면 Google 계정에 카드를 저장하세요.</translation>
<translation id="7502658306369382406">IPv6 주소</translation>
<translation id="7503191893372251637">Netscape Certificate Type</translation>
<translation id="7503821294401948377">브라우저 작업의 아이콘('<ph name="ICON" />')을 로드하지 못했습니다.</translation>
@@ -4376,6 +4386,7 @@
<translation id="7663719505383602579">수신기: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">지원되지 않는 블루투스 기기(<ph name="DEVICE_NAME" />)입니다.</translation>
<translation id="7665369617277396874">계정 추가</translation>
+<translation id="7667248760110172428">외부 저장소</translation>
<translation id="7671130400130574146">시스템 제목 표시줄 및 테두리 사용</translation>
<translation id="7672520070349703697"><ph name="PAGE_TITLE" />에 포함된 <ph name="HUNG_IFRAME_URL" /></translation>
<translation id="7676867886086876795">모든 텍스트 입력란에서 음성기록 기능을 지원하기 위해 Google에 음성이 전송됩니다.</translation>
@@ -4579,6 +4590,7 @@
<translation id="7930294771522048157">저장한 결제 수단이 여기에 표시됩니다.</translation>
<translation id="79312157130859720"><ph name="APP_NAME" />에서 내 화면과 오디오를 공유하는 중입니다.</translation>
<translation id="7931318309563332511">알 수 없음</translation>
+<translation id="7932969338829957666"><ph name="BASE_DIR" />에서 Linux의 공유 폴더를 사용할 수 있습니다.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{사이트 숨기기 취소}other{사이트 숨기기 취소}}</translation>
<translation id="7934414805353235750"><ph name="URL" />에서 보호된 콘텐츠를 재생하려고 합니다. Google에서 기기의 ID를 인증해야 합니다.</translation>
<translation id="793531125873261495">가상 머신을 다운로드하는 중 문제가 발생했습니다. 다시 시도해 주세요.</translation>
@@ -4670,6 +4682,7 @@
<translation id="8049705080247101012">Google에서 '<ph name="EXTENSION_NAME" />'을(를) 악성 프로그램으로 분류했으며 설치가 금지되었습니다</translation>
<translation id="8049913480579063185">확장 프로그램 이름</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">이 파일은 Windows 소프트웨어를 사용하는 PC용으로 설계되었으며 Chrome OS를 실행하는 기기와 호환되지 않습니다. <ph name="BEGIN_LINK_HELP" />자세히 알아보기<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 파일</translation>
<translation id="8053390638574070785">페이지 새로고침</translation>
<translation id="8054517699425078995">이러한 형식의 파일은 기기를 손상시킬 수 있습니다. <ph name="FILE_NAME" />을(를) 다운로드하시겠습니까?</translation>
@@ -4913,6 +4926,7 @@
<translation id="8438566539970814960">검색 및 탐색 기능 개선</translation>
<translation id="8439506636278576865">이 언어로 된 페이지에 대한 번역 옵션 제공</translation>
<translation id="8440630305826533614">Linux 앱</translation>
+<translation id="8443338615972234259">지금 관리 대상 사용자용 계정을 새로 만드세요.</translation>
<translation id="8446884382197647889">자세히 알아보기</translation>
<translation id="8447409163267621480">Ctrl 또는 Alt 중 하나를 포함해야 합니다</translation>
<translation id="8448729345478502352">화면에 표시되는 항목을 축소 또는 확대합니다.</translation>
@@ -4937,6 +4951,7 @@
<translation id="8468750959626135884">Android 휴대전화로 <ph name="DEVICE_TYPE" />을(를) 잠금 해제하세요.</translation>
<translation id="8470028084415844044">저장된 비밀번호를 어느 기기에서나 사용하려면 동기화를 사용 설정하세요.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" />의 저장된 비밀번호</translation>
+<translation id="8471635086304129332">모든 기기에서 이 카드를 사용하려면 Google 계정에 카드를 저장하세요.</translation>
<translation id="8472623782143987204">하드웨어 지원</translation>
<translation id="8473863474539038330">주소 및 기타</translation>
<translation id="8475313423285172237">컴퓨터의 다른 프로그램에서 Chrome 작동에 영향을 줄 수 있는 확장 프로그램을 추가했습니다.</translation>
@@ -5012,7 +5027,6 @@
<translation id="8598453409908276158">샌드박스 처리되지 않은 플러그인이 차단됨</translation>
<translation id="8601206103050338563">TLS WWW 클라이언트 인증</translation>
<translation id="8602851771975208551">컴퓨터의 다른 프로그램에서 Chrome 작동에 영향을 줄 수 있는 앱을 추가했습니다.</translation>
-<translation id="8604763363205185560">Chrome 및 보안 개선에 참여</translation>
<translation id="8605428685123651449">SQLite 메모리</translation>
<translation id="8606726445206553943">MIDI 기기를 사용합니다.</translation>
<translation id="8609465669617005112">위로 이동</translation>
@@ -5188,6 +5202,7 @@
<translation id="8846141544112579928">키보드 검색 중...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">기기를 연결하면 Chromebook에서 다음 작업을 처리하는 것에 동의하게 됩니다.</translation>
+<translation id="8850251000316748990">더보기...</translation>
<translation id="8859057652521303089">언어 선택:</translation>
<translation id="8859174528519900719">서브프레임: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel 스프레드시트</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_lt.xtb b/chromium/chrome/app/resources/generated_resources_lt.xtb
index 748f4ad3896..f3d7b610c28 100644
--- a/chromium/chrome/app/resources/generated_resources_lt.xtb
+++ b/chromium/chrome/app/resources/generated_resources_lt.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Įgalinti temą</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Žr. „Chrome“ internetinėje parduotuvėje</translation>
-<translation id="1761588866118490543">Balso modelis</translation>
<translation id="176193854664720708">Piršto antspaudo jutiklis yra maitinimo mygtuko viduje. Lengvai jį palieskite bet kuriuo pirštu.</translation>
<translation id="1763046204212875858">Kurti programos sparčiuosius mygtukus</translation>
<translation id="1763108912552529023">Toliau tyrinėti</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Siųskite naudojimo ir diagnostikos duomenis. Šiuo metu šis įrenginys automatiškai siunčia „Google“ diagnostikos, įrenginio ir programų naudojimo duomenis. Tai padės pagerinti sistemos bei programos stabilumą ir teikti kitus patobulinimus. Kai kurie sukaupti duomenys taip pat bus naudingi „Google“ programoms ir partneriams, pvz., „Android“ kūrėjams. Šį nustatymą taiko savininkas. Jei papildomas „Žiniatinklio ir programų veiklos“ nustatymas įjungtas, šie duomenys gali būti išsaugoti „Google“ paskyroje. <ph name="BEGIN_LINK1" />Sužinokite daugiau<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Talpusis archyvas</translation>
<translation id="220858061631308971">Įveskite šį PIN kodą „<ph name="DEVICE_NAME" />“:</translation>
+<translation id="2213140827792212876">Pašalinti bendrinimą</translation>
+<translation id="2214018885812055163">Bendrinami aplankai</translation>
<translation id="2214884991347062907">Netinkamas slaptažodis, bandykite dar kartą.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 nerodoma eilutė&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> nerodoma eilutė&gt;}few{&lt;<ph name="NUMBER_OF_LINES" /> nerodomos eilutės&gt;}many{&lt;<ph name="NUMBER_OF_LINES" /> nerodomos eilutės&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> nerodomų eilučių&gt;}}</translation>
<translation id="2217501013957346740">Sukurti pavadinimą –</translation>
@@ -940,7 +941,7 @@
<translation id="2379281330731083556">Spausdinti naudojant sistemos dialogo langą... <ph name="SHORTCUT_KEY" /></translation>
<translation id="2381756643783702095">Klausti prieš siunčiant (rekomenduojama)</translation>
<translation id="2384436799579181135">Įvyko klaida. Patikrinkite spausdintuvą ir bandykite dar kartą.</translation>
-<translation id="2386926718981642523">Pasiekite Padėjėją bet kuriuo metu pasakę „Ok Google“</translation>
+<translation id="2386926718981642523">Pasiekite „Google Assistant“ bet kuriuo metu pasakę „Ok Google“</translation>
<translation id="2387458720915042159">Tarpinio serverio ryšio tipas</translation>
<translation id="2391419135980381625">Standartinis šriftas</translation>
<translation id="2391762656119864333">Anuliuoti</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Sertifikatas sulaikytas</translation>
<translation id="2501797496290880632">Paspauskite sparčiuosius klavišus</translation>
<translation id="2502441965851148920">Įgalinti automatiniai naujiniai. Neautomatinius naujinius išjungė administratorius.</translation>
+<translation id="2505127913256479918">Ši prižiūrima paskyra netrukus bus pašalinta</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{# ekranas}one{# ekranas}few{# ekranai}many{# ekrano}other{# ekranų}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> iš <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">„Google Play“ parduotuvės paskyra</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Kalbų varikliai</translation>
<translation id="3053013834507634016">Sertifikato rakto naudojimas</translation>
<translation id="3057861065630527966">Kurkite atsargines nuotraukų ir vaizdo įrašų kopijas</translation>
+<translation id="3058498974290601450">Galite bet kada įjungti sinchronizavimą „Nustatymų“ skiltyje</translation>
<translation id="3060379269883947824">Įgalinti funkciją „Teksto ištarimas“</translation>
<translation id="3061707000357573562">Pataisos paslauga</translation>
<translation id="3065041951436100775">Atsiliepimai dėl uždaryto skirtuko.</translation>
@@ -1566,11 +1569,12 @@
<translation id="337920581046691015">„<ph name="PRODUCT_NAME" />“ bus įdiegta.</translation>
<translation id="3380365263193509176">Nežinoma klaida</translation>
<translation id="3382073616108123819">Oi! Sistemai nepavyko nustatyti šio įrenginio identifikatorių.</translation>
+<translation id="3382086682569279540">Jūsų valdoma paskyra netrukus bus pašalinta</translation>
<translation id="3382200254148930874">Stabdoma priežiūra...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Skyriklis</translation>
<translation id="3389312115541230716">Dešiniuoju pelės klavišu spustelėkite piktogramą <ph name="SMALL_PRODUCT_LOGO" /> užduočių juostoje</translation>
-<translation id="3393352139658145068">Suaktyvinti Padėjėją, kai tik pasakoma „Ok Google“. Siekiant tausoti akumuliatoriaus energiją, funkcija „Ok Google“ įjungiama, tik kai įrenginys prijungtas prie maitinimo šaltinio.</translation>
+<translation id="3393352139658145068">Suaktyvinti „Google Assistant“, kai tik pasakoma „Ok Google“. Siekiant tausoti akumuliatoriaus energiją, funkcija „Ok Google“ įjungiama, tik kai įrenginys prijungtas prie maitinimo šaltinio.</translation>
<translation id="3396800784455899911">Spustelėdami mygtuką „Sutikti ir tęsti“ sutinkate, kad šios „Google“ paslaugos būtų apdorojamos, kaip aprašyta anksčiau.</translation>
<translation id="3399432415385675819">Pranešimai bus išjungti</translation>
<translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />, <ph name="TIME_LEFT" /></translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Sveiki, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> % – liko <ph name="TIME" /></translation>
<translation id="3637682276779847508">SIM kortelė bus visam laikui išjungta, jei negalėsite įvesti tinkamo PIN kodo atrakinimo rakto.</translation>
-<translation id="363863692969456324">Pataisykite rašybos klaidas naudodami patobulintą rašybos tikrinimo funkciją</translation>
<translation id="3640214691812501263">Pridėti „<ph name="EXTENSION_NAME" />“ naudotojui <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Išmokykite Padėjėją atpažinti jūsų balsą</translation>
<translation id="3644896802912593514">Plotis</translation>
<translation id="3645372836428131288">Truputį pajudinkite pirštą, kad būtų užfiksuota kita piršto antspaudo dalis.</translation>
<translation id="3648348069317717750">Aptiktas „<ph name="USB_DEVICE_NAME" />“</translation>
@@ -2147,7 +2151,6 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="4244238649050961491">Rasti daugiau rašiklio programų</translation>
<translation id="424546999567421758">Aptiktas intensyvus disko naudojimas</translation>
<translation id="424726838611654458">Visada atidaryti naudojant „Adobe Reader“</translation>
-<translation id="4247330672018280062">Teksto laukuose įvestas tekstas bus siunčiamas į sistemą „Google“</translation>
<translation id="4247901771970415646">Negalima sinchronizuoti su <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Laukiama tinklo ryšio...</translation>
<translation id="4249373718504745892">Šis puslapis užblokuotas, kad nepasiektų fotoaparato ir mikrofono.</translation>
@@ -2489,6 +2492,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="4821935166599369261">&amp;Profiliavimas įgalintas</translation>
<translation id="4823484602432206655">Skaityti ir keisti naudotojo bei įrenginio nustatymus</translation>
<translation id="4823651846660089135">Įrenginys yra tik skaitomas</translation>
+<translation id="4824958205181053313">Atšaukti sinchronizavimą?</translation>
<translation id="4827675678516992122">Nepavyko prisijungti</translation>
<translation id="4828937774870308359">Australiškas</translation>
<translation id="4829768588131278040">Nustatyti PIN kodą</translation>
@@ -2871,6 +2875,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="5374359983950678924">Keisti paveikslėlį</translation>
<translation id="5376169624176189338">Spustelėkite, kad grįžtumėte, palaukite, kad pamatytumėte istoriją</translation>
<translation id="5376931455988532197">Failas per didelis</translation>
+<translation id="5377594097385838788">Inkognito</translation>
<translation id="537813040452600081">Puslapiai, kuriuos peržiūrite šiame lange, nerodomi naršyklės istorijoje. Kai atsijungsite, kompiuteryje neliks ir kitų jų pėdsakų, pvz., slapukų. Atsisiųsti failai ir sukurtos žymės nebus išsaugoti.</translation>
<translation id="5379140238605961210">Toliau blokuoti prieigą prie mikrofono</translation>
<translation id="5379268888377976432">Anuliuoti ištrynimą</translation>
@@ -2892,6 +2897,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="5414566801737831689">Skaityti lankomų svetainių piktogramas</translation>
<translation id="5417312524372586921">Naršyklės temos</translation>
<translation id="5419294236999569767">Sistemos laikas</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Nustatomas teksto ir vaizdų ryškumas</translation>
<translation id="5422221874247253874">Prieigos taškas</translation>
<translation id="5422781158178868512">Apgailestaujame, tačiau jūsų išorinis atmintinės įrenginys yra neatpažįstamas.</translation>
@@ -2912,6 +2918,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="5434065355175441495">PKCS Nr. 1 RSA šifruotė</translation>
<translation id="5436492226391861498">Laukiama, kol bus nustatytas tarpinio serverio tunelis...</translation>
<translation id="5436510242972373446">Ieškoti <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Dabar išsaugokite failus ir sukurkite naują paskyrą.</translation>
<translation id="5438224778284622050">Ištrinti neprisijungus pasiekiamus failus?</translation>
<translation id="544083962418256601">Kurti sparčiuosius klavišus...</translation>
<translation id="5442228125690314719">Kuriant disko vaizdą įvyko klaida. Bandykite dar kartą.</translation>
@@ -3286,6 +3293,8 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="5965661248935608907">Ji taip pat kontroliuoja, koks puslapis rodomas, kai spustelėjate pagrindinio puslapio mygtuką ar ieškote „Omnibox“.</translation>
<translation id="5971037678316050792">Valdyti „Bluetooth“ adapterio būseną ir susiejimą</translation>
<translation id="5972017421290582825">Valdyti MIDI nustatymus...</translation>
+<translation id="597235323114979258">Žr. daugiau paskirties vietų</translation>
+<translation id="5972666587303800813">Neveikianti paslauga</translation>
<translation id="5972708806901999743">Perkelti į viršų</translation>
<translation id="5972826969634861500">Paleisti „<ph name="PRODUCT_NAME" />“</translation>
<translation id="5975792506968920132">Akumuliatoriaus įkrovimo procentas</translation>
@@ -3656,6 +3665,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="6527303717912515753">Bendrinti</translation>
<translation id="6528513914570774834">Leisti kitiems šio įrenginio naudotojams naudoti šį tinklą</translation>
<translation id="652948702951888897">„Chrome“ istorija</translation>
+<translation id="6530186581263215931">Šiuos nustatymus įgalina jūsų administratorius</translation>
<translation id="653019979737152879">Sinchronizuojamas failas „<ph name="FILE_NAME" />“...</translation>
<translation id="6531282281159901044">Palikti pavojingą failą</translation>
<translation id="6532101170117367231">Išsaugoti „Google“ diske</translation>
@@ -3974,7 +3984,6 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="7018275672629230621">Skaityti ir keisti naršymo istoriją</translation>
<translation id="7019805045859631636">Greitas</translation>
<translation id="7022562585984256452">Pagrindinis puslapis nustatytas.</translation>
-<translation id="702384510542929236">Anonimiškai siunčia tam tikrą sistemos informaciją ir puslapio turinį į sistemą „Google“</translation>
<translation id="7025190659207909717">Duomenų mobiliesiems paslaugos valdymas</translation>
<translation id="7027125358315426638">Duomenų pavadinimas:</translation>
<translation id="7029809446516969842">Slaptažodžiai</translation>
@@ -4154,6 +4163,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="7289225569524511578">Atidaryti ekrano fonų programą</translation>
<translation id="7290242001003353852">Ši prisijungimo paslauga, priglobiama <ph name="SAML_DOMAIN" />, pasiekia jūsų fotoaparatą.</translation>
<translation id="7290594223351252791">Patvirtinti registraciją</translation>
+<translation id="7292696521213967957">Padėjėjo derinimo informacija</translation>
<translation id="7295662345261934369">Bendrinti su kitais žmonėmis</translation>
<translation id="729583233778673644">Leisti AES ir RC4 šifruotes. Naudojant šią parinktį padidėja rizika, nes RC4 šifrai nesaugūs.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> sąlygos</translation>
@@ -4254,7 +4264,6 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="7456847797759667638">Atidaryti vietą...</translation>
<translation id="7461924472993315131">Prisegti</translation>
<translation id="7463006580194749499">Pridėti asmenį</translation>
-<translation id="7464902436585505072">„Ok Google“ balso modelis</translation>
<translation id="7465778193084373987">„Netscape“ sertifikato panaikinimo URL</translation>
<translation id="7469894403370665791">Automatiškai prisijungti prie šio tinklo</translation>
<translation id="747114903913869239">Klaida: neįmanoma iššifruoti plėtinio</translation>
@@ -4282,6 +4291,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="7496511874649569424">„<ph name="LINUX_APP_NAME" />“ ir su ja susieti duomenys bus pašalinti iš šio įrenginio.</translation>
<translation id="7497215489070763236">Serverio CA sertifikatas</translation>
<translation id="7497981768003291373">Neturite neseniai užfiksuotų „WebRTC“ teksto žurnalų.</translation>
+<translation id="7502199377020483660">Jei norite naudoti šias korteles visuose įrenginiuose, išsaugokite jas „Google“ paskyroje</translation>
<translation id="7502658306369382406">„IPv6“ adresas</translation>
<translation id="7503191893372251637">„Netscape“ sertifikato tipas</translation>
<translation id="7503821294401948377">Naršyklės veiksmui įkelti „<ph name="ICON" />“ piktogramos nepavyko.</translation>
@@ -4379,6 +4389,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="7663719505383602579">Gavėjas: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Nepalaikomas „Bluetooth“ įrenginys: „<ph name="DEVICE_NAME" />“.</translation>
<translation id="7665369617277396874">Pridėti paskyrą</translation>
+<translation id="7667248760110172428">Išorinė saugykla</translation>
<translation id="7671130400130574146">Naudoti sistemos pavadinimo juostą ir rėmelius</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, puslapyje „<ph name="PAGE_TITLE" />“.</translation>
<translation id="7676867886086876795">Balsas siunčiamas į sistemą „Google“, kad bet kuriame teksto lauke būtų galima diktuoti tekstą.</translation>
@@ -4582,6 +4593,7 @@ Ar norite paleisti „<ph name="CONTROL_PANEL_APPLET_NAME" />“?</translation>
<translation id="7930294771522048157">Čia bus rodomi išsaugoti mokėjimo metodai</translation>
<translation id="79312157130859720">„<ph name="APP_NAME" />“ bendrina jūsų ekraną ir garsą.</translation>
<translation id="7931318309563332511">Nežinoma</translation>
+<translation id="7932969338829957666">Bendrinami aplankai pasiekiami sistemoje „Linux“ adresu <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Įjungti svetainės garsą}one{Įjungti svetainių garsą}few{Įjungti svetainių garsą}many{Įjungti svetainių garsą}other{Įjungti svetainių garsą}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> nori leisti apsaugotą turinį. Įrenginio tapatybę patvirtins „Google“</translation>
<translation id="793531125873261495">Atsisiunčiant virtualų įrenginį įvyko klaida. Bandykite dar kartą.</translation>
@@ -4673,6 +4685,7 @@ Rakto failą laikykite saugioje vietoje. Jo reikės, kai norėsite sukurti nauja
<translation id="8049705080247101012">„Google“ pažymėjo plėtinį „<ph name="EXTENSION_NAME" />“ kaip kenkėjišką ir neleido jo įdiegti</translation>
<translation id="8049913480579063185">Plėtinio pavadinimas</translation>
<translation id="8050038245906040378">„Microsoft“ komercinio kodo pasirašymas</translation>
+<translation id="8052887694493382350">Šis failas skirtas kompiuteriui, kuriame naudojama „Windows“ programinė įranga. Jis nesuderinamas su jūsų įrenginiu, kuriame veikia „Chrome“ OS. <ph name="BEGIN_LINK_HELP" />Sužinokite daugiau<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS Nr. 12 failai</translation>
<translation id="8053390638574070785">Iš naujo įkelti šį puslapį</translation>
<translation id="8054517699425078995">Šio tipo failas gali pakenkti įrenginiui. Ar vis tiek norite pasilikti „<ph name="FILE_NAME" />“?</translation>
@@ -4916,6 +4929,7 @@ Rakto failą laikykite saugioje vietoje. Jo reikės, kai norėsite sukurti nauja
<translation id="8438566539970814960">Tobulinti paieškas ir naršymą</translation>
<translation id="8439506636278576865">Siūlyti versti puslapius šia kalba</translation>
<translation id="8440630305826533614">„Linux“ programos</translation>
+<translation id="8443338615972234259">Dabar sukurkite naują prižiūrimo naudotojo paskyrą.</translation>
<translation id="8446884382197647889">Sužinokite daugiau</translation>
<translation id="8447409163267621480">Naudokite „Ctrl“ arba „Alt“</translation>
<translation id="8448729345478502352">Padidinkite arba sumažinkite elementus ekrane</translation>
@@ -4940,6 +4954,7 @@ Rakto failą laikykite saugioje vietoje. Jo reikės, kai norėsite sukurti nauja
<translation id="8468750959626135884">Atrakinkite „<ph name="DEVICE_TYPE" />“ naudodami „Android“ telefoną.</translation>
<translation id="8470028084415844044">Jei norite pasiekti visus slaptažodžius visuose įrenginiuose, įjunkite sinchronizavimą.</translation>
<translation id="8470513973197838199">Išsaugoti <ph name="ORIGIN" /> slaptažodžiai</translation>
+<translation id="8471635086304129332">Jei norite naudoti šią kortelę visuose įrenginiuose, išsaugokite ją „Google“ paskyroje</translation>
<translation id="8472623782143987204">palaikoma aparatinės įrangos</translation>
<translation id="8473863474539038330">Adresai ir dar daugiau</translation>
<translation id="8475313423285172237">Kita jūsų kompiuteryje esanti programa pridėjo plėtinį, kuris gali pakeisti „Chrome“ veikimo būdą.</translation>
@@ -5015,7 +5030,6 @@ Rakto failą laikykite saugioje vietoje. Jo reikės, kai norėsite sukurti nauja
<translation id="8598453409908276158">Ne „smėlio dėžės“ papildinys užblokuotas</translation>
<translation id="8601206103050338563">TLS WWW kliento tapatybės nustatymas</translation>
<translation id="8602851771975208551">Kita jūsų kompiuteryje esanti programa pridėjo programą, kuri gali pakeisti „Chrome“ veikimo būdą.</translation>
-<translation id="8604763363205185560">Padėkite tobulinti naršyklę „Chrome“ ir jos našumą</translation>
<translation id="8605428685123651449">„SQLite“ atmintis</translation>
<translation id="8606726445206553943">Naudoti MIDI įrenginius</translation>
<translation id="8609465669617005112">Perkelti į viršų</translation>
@@ -5191,6 +5205,7 @@ Rakto failą laikykite saugioje vietoje. Jo reikės, kai norėsite sukurti nauja
<translation id="8846141544112579928">Ieškoma klaviatūros...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Susiedami įrenginius sutinkate, kad „Chromebook“ gali:</translation>
+<translation id="8850251000316748990">Žr. daugiau...</translation>
<translation id="8859057652521303089">Pasirinkite kalbą:</translation>
<translation id="8859174528519900719">Antrinis kadras: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">„Excel“ skaičiuoklė</translation>
@@ -5211,7 +5226,7 @@ Rakto failą laikykite saugioje vietoje. Jo reikės, kai norėsite sukurti nauja
<translation id="8883847527783433352">Sinchronizuoti su kita paskyra</translation>
<translation id="8885197664446363138">„Smart Lock“ nepasiekiama</translation>
<translation id="88870264962436283">Naudokite „Touch ID“ su programa „<ph name="APP_NAME" />“</translation>
-<translation id="8888253246822647887">Programa bus atidaryta baigus naujovinti. Naujovinimo procesas gali užtrukti keletą minučių.</translation>
+<translation id="8888253246822647887">Programa bus atidaryta baigus naujovinti. Naujovinimas gali užtrukti keletą minučių.</translation>
<translation id="8888432776533519951">Spalva:</translation>
<translation id="8890516388109605451">Šaltiniai</translation>
<translation id="8892168913673237979">Viskas nustatyta!</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_lv.xtb b/chromium/chrome/app/resources/generated_resources_lv.xtb
index 641b9838a22..a89af2785bc 100644
--- a/chromium/chrome/app/resources/generated_resources_lv.xtb
+++ b/chromium/chrome/app/resources/generated_resources_lv.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Iespējot motīvu</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Skatīt Chrome interneta veikalā</translation>
-<translation id="1761588866118490543">Balss modelis</translation>
<translation id="176193854664720708">Pirksta nospieduma sensors atrodas barošanas pogā. Viegli pieskarieties tai ar jebkuru pirkstu.</translation>
<translation id="1763046204212875858">Izveidot lietojumprogrammu saīsnes</translation>
<translation id="1763108912552529023">Turpināt izpēti</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Lietojuma un diagnostikas datu sūtīšana. Pašlaik dati par šo ierīci un ierīces diagnostikas un lietotņu lietojuma dati tiek automātiski sūtīti uzņēmumam Google. Šī informācija palīdzēs uzlabot sistēmas un lietotņu stabilitāti un daudz ko citu. Noteiktus apkopotus datus izmantos arī Google lietotņu izstrādātāji un partneri, piemēram, Android izstrādātāji. Šo iestatījumu ir noteicis īpašnieks. Ja ir ieslēgts papildu iestatījums “Darbības tīmeklī un lietotnēs”, šie dati var tikt saglabāti jūsu Google kontā. <ph name="BEGIN_LINK1" />Uzzināt vairāk<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip arhīvs</translation>
<translation id="220858061631308971">Ievadiet šo PIN kodu ierīcē <ph name="DEVICE_NAME" />:</translation>
+<translation id="2213140827792212876">Noņemt kopīgošanu</translation>
+<translation id="2214018885812055163">Kopīgotās mapes</translation>
<translation id="2214884991347062907">Parole nav pareiza. Mēģiniet vēlreiz.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 rinda netiek rādīta&gt;}zero{&lt;<ph name="NUMBER_OF_LINES" /> rindas netiek rādītas&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> rinda netiek rādīta&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> rindas netiek rādītas&gt;}}</translation>
<translation id="2217501013957346740">Vārda izveide —</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Sertifikāts ir aizturēts</translation>
<translation id="2501797496290880632">Ierakstiet saīsnes</translation>
<translation id="2502441965851148920">Automātiski atjauninājumi ir iespējoti. Administrators ir atspējojis manuālus atjauninājumus.</translation>
+<translation id="2505127913256479918">Drīzumā tiks noņemts šis uzraudzītais konts</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{#. ekrāns}zero{#. ekrāns}one{#. ekrāns}other{#. ekrāns}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> no <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play veikala konts</translation>
@@ -1375,6 +1377,7 @@ Servera ziņojums: <ph name="SERVER_MSG" /></translation>
<translation id="304747341537320566">Runas programmas</translation>
<translation id="3053013834507634016">Sertifikāta atslēgas lietošana</translation>
<translation id="3057861065630527966">Dublēt fotoattēlus un videoklipus</translation>
+<translation id="3058498974290601450">Jebkurā brīdī varat ieslēgt sinhronizāciju iestatījumos.</translation>
<translation id="3060379269883947824">Iespējot funkciju “Atlasīt, lai izrunātu”</translation>
<translation id="3061707000357573562">Ielāpu pakalpojums</translation>
<translation id="3065041951436100775">Atsauksme par cilnes darbības pārtraukšanu.</translation>
@@ -1566,6 +1569,7 @@ Servera ziņojums: <ph name="SERVER_MSG" /></translation>
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> tiks instalēts.</translation>
<translation id="3380365263193509176">Nezināma kļūda</translation>
<translation id="3382073616108123819">Diemžēl sistēmai neizdevās noteikt šīs ierīces identifikatorus.</translation>
+<translation id="3382086682569279540">Drīzumā tiks noņemts jūsu pārvaldītais konts</translation>
<translation id="3382200254148930874">Notiek uzraudzības pārtraukšana...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Atdalītājs</translation>
@@ -1746,8 +1750,8 @@ Servera ziņojums: <ph name="SERVER_MSG" /></translation>
<translation id="3636096452488277381">Sveicināti, <ph name="USER_GIVEN_NAME" />!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% — atlicis: <ph name="TIME" /></translation>
<translation id="3637682276779847508">SIM karte tiks neatgriezeniski atspējota, ja nevarēsiet ievadīt pareizo PIN atbloķēšanas atslēgu.</translation>
-<translation id="363863692969456324">Labojiet pareizrakstības kļūdas, izmantojot uzlaboto pareizrakstības pārbaudi</translation>
<translation id="3640214691812501263">Vai vēlaties pievienot lietotni “<ph name="EXTENSION_NAME" />” lietotājam <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Asistenta apmācība atpazīt balsi</translation>
<translation id="3644896802912593514">Platums</translation>
<translation id="3645372836428131288">Mazliet pakustiniet, lai uzņemtu citu pirksta nospieduma daļu</translation>
<translation id="3648348069317717750">Konstatēta ierīce <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="4244238649050961491">Atrast citas skārienekrāna pildspalvas lietotnes</translation>
<translation id="424546999567421758">Konstatēts apjomīgs diska lietojums</translation>
<translation id="424726838611654458">Vienmēr atvērt programmā Adobe Reader</translation>
-<translation id="4247330672018280062">Teksts, ko rakstāt teksta lauciņos, tiks nosūtīts Google serveriem.</translation>
<translation id="4247901771970415646">Nevar sinhronizēt ar lietotāju <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Tiek gaidīta savienojuma izveide ar tīklu...</translation>
<translation id="4249373718504745892">Šīs lapas piekļuve jūsu kamerai un mikrofonam ir bloķēta.</translation>
@@ -2489,6 +2492,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="4821935166599369261">%Profilēšana iespējota</translation>
<translation id="4823484602432206655">Lasīt un mainīt lietotāja un ierīces iestatījumus</translation>
<translation id="4823651846660089135">Ierīce ir tikai lasāma.</translation>
+<translation id="4824958205181053313">Vai atcelt sinhronizāciju?</translation>
<translation id="4827675678516992122">Nevarēja izveidot savienojumu</translation>
<translation id="4828937774870308359">Austrāliešu</translation>
<translation id="4829768588131278040">Iestatīt PIN</translation>
@@ -2871,6 +2875,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="5374359983950678924">Mainīt attēlu</translation>
<translation id="5376169624176189338">Nospiediet, lai dotos atpakaļ, paturiet, lai redzētu vēsturi</translation>
<translation id="5376931455988532197">Fails ir pārāk liels.</translation>
+<translation id="5377594097385838788">Inkognito režīms</translation>
<translation id="537813040452600081">Lapas, ko skatāt šajā logā, nebūs redzamas pārlūka vēsturē, un, kad izrakstīsieties, datorā nepaliks nekādi vienumi, piemēram, sīkfaili. Tomēr visi lejupielādētie faili un izveidotās grāmatzīmes tiks saglabātas.</translation>
<translation id="5379140238605961210">Turpināt piekļuves bloķēšanu mikrofonam</translation>
<translation id="5379268888377976432">Atsaukt dzēšanu</translation>
@@ -2892,6 +2897,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="5414566801737831689">Lasīt jūsu apmeklēto vietņu ikonas</translation>
<translation id="5417312524372586921">Pārlūka motīvi</translation>
<translation id="5419294236999569767">Sistēmas laiks</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Regulē teksta un attēlu asumu</translation>
<translation id="5422221874247253874">Piekļuves punkts</translation>
<translation id="5422781158178868512">Diemžēl jūsu ārējo atmiņas ierīci nevarēja atpazīt.</translation>
@@ -2912,6 +2918,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="5434065355175441495">PKCS #1 RSA šifrējums</translation>
<translation id="5436492226391861498">Gaida starpniekservera tuneli...</translation>
<translation id="5436510242972373446">Meklēt <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Lūdzu, saglabājiet savus failus un izveidojiet jaunu kontu tūlīt.</translation>
<translation id="5438224778284622050">Vai dzēst bezsaistes failus?</translation>
<translation id="544083962418256601">Izveidot saīsnes...</translation>
<translation id="5442228125690314719">Izveidojot diska attēlu, radās kļūda. Lūdzu, mēģiniet vēlreiz.</translation>
@@ -3285,6 +3292,8 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="5965661248935608907">Tas nosaka arī to, kāda lapa tiks rādīta, kad noklikšķināsiet uz pogas “Sākums” vai meklēsiet, izmantojot universālo lodziņu.</translation>
<translation id="5971037678316050792">Kontrolēt Bluetooth adaptera statusu un savienošanu pārī</translation>
<translation id="5972017421290582825">Pārvaldīt MIDI iestatījumus...</translation>
+<translation id="597235323114979258">Skatīt citus galamērķus</translation>
+<translation id="5972666587303800813">Pakalpojums, kas nedarbojas</translation>
<translation id="5972708806901999743">Pārvietot uz augšu</translation>
<translation id="5972826969634861500">Sākt <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Akumulatora uzlādes līmenis (procentos)</translation>
@@ -3655,6 +3664,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="6527303717912515753">Kopīgot</translation>
<translation id="6528513914570774834">Atļaut citiem lietotājiem šajā ierīcē izmantot šo tīklu</translation>
<translation id="652948702951888897">Chrome vēsture</translation>
+<translation id="6530186581263215931">Šos iestatījumus ir noteicis administrators</translation>
<translation id="653019979737152879">Notiek faila <ph name="FILE_NAME" /> sinhronizēšana...</translation>
<translation id="6531282281159901044">Paturēt bīstamo failu</translation>
<translation id="6532101170117367231">Saglabāt Google diskā</translation>
@@ -3973,7 +3983,6 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="7018275672629230621">Lasīt un mainīt jūsu pārlūkošanas vēsturi</translation>
<translation id="7019805045859631636">Ātrs</translation>
<translation id="7022562585984256452">Jūsu sākumlapa ir iestatīta.</translation>
-<translation id="702384510542929236">Anonīmi nosūta noteiktu sistēmas informāciju un lapas saturu Google serveriem.</translation>
<translation id="7025190659207909717">Mobilo datu pakalpojumu pārvaldība</translation>
<translation id="7027125358315426638">Datu bāzes nosaukums:</translation>
<translation id="7029809446516969842">Paroles</translation>
@@ -4153,6 +4162,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="7289225569524511578">Atvērt fona tapešu lietotni</translation>
<translation id="7290242001003353852">Šis domēnā <ph name="SAML_DOMAIN" /> mitinātais pierakstīšanās pakalpojums piekļūst jūsu kamerai.</translation>
<translation id="7290594223351252791">Reģistrācijas apstiprināšana</translation>
+<translation id="7292696521213967957">Informācija Asistenta atkļūdošanai</translation>
<translation id="7295662345261934369">Kopīgot ar citiem</translation>
<translation id="729583233778673644">Atļaut AES un RC4 šifrēšanu. Ja izmantosiet šo opciju, palielināsies risks, jo RC4 šifri nav droši.</translation>
<translation id="7296774163727375165">Vietnes <ph name="DOMAIN" /> noteikumi</translation>
@@ -4253,7 +4263,6 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="7456847797759667638">Atvērt atrašanās vietu...</translation>
<translation id="7461924472993315131">Piespraust</translation>
<translation id="7463006580194749499">Pievienot personu</translation>
-<translation id="7464902436585505072">“Ok Google” balss modelis</translation>
<translation id="7465778193084373987">Netscape sertifikāta atsaukšanas URL</translation>
<translation id="7469894403370665791">Automātiski pievienoties šim tīklam</translation>
<translation id="747114903913869239">Kļūda: nespēj dekodēt paplašinājumu</translation>
@@ -4281,6 +4290,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="7496511874649569424">Lietotne <ph name="LINUX_APP_NAME" /> un ar to saistītie dati tiks noņemti no šīs ierīces.</translation>
<translation id="7497215489070763236">Servera CA sertifikāts</translation>
<translation id="7497981768003291373">Jums nav nesen ierakstītu WebRTC tekstu žurnālu.</translation>
+<translation id="7502199377020483660">Lai izmantotu šīs kartes visās savās ierīcēs, saglabājiet tās savā Google kontā</translation>
<translation id="7502658306369382406">IPv6 adrese</translation>
<translation id="7503191893372251637">Netscape sertifikāta veids</translation>
<translation id="7503821294401948377">Nevarēja ielādēt pārlūka darbības ikonu “<ph name="ICON" />”.</translation>
@@ -4378,6 +4388,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="7663719505383602579">Uztvērējs: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Neatbalstīta Bluetooth ierīce: <ph name="DEVICE_NAME" />.</translation>
<translation id="7665369617277396874">Pievienot kontu</translation>
+<translation id="7667248760110172428">Ārējā krātuve</translation>
<translation id="7671130400130574146">Izmantot sistēmas virsrakstjoslu un apmales</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, lapā <ph name="PAGE_TITLE" /></translation>
<translation id="7676867886086876795">Nosūtiet savus balss datus Google serveriem, lai atļautu diktēšanu jebkurā teksta laukā.</translation>
@@ -4580,6 +4591,7 @@ Vai vēlaties palaist rīku <ph name="CONTROL_PANEL_APPLET_NAME" />?</translatio
<translation id="7930294771522048157">Šeit tiks parādīti saglabātie maksājumu veidi.</translation>
<translation id="79312157130859720">Lietotne <ph name="APP_NAME" /> koplieto jūsu ekrānu un audio.</translation>
<translation id="7931318309563332511">Nezināma</translation>
+<translation id="7932969338829957666">Kopīgotās mapes operētājsistēmā Linux ir pieejamas sadaļā <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Rādīt vietni}zero{Rādīt vietnes}one{Rādīt vietnes}other{Rādīt vietnes}}</translation>
<translation id="7934414805353235750">Vietne <ph name="URL" /> vēlas atskaņot aizsargātu saturu. Google verificēs jūsu ierīces identitāti.</translation>
<translation id="793531125873261495">Lejupielādējot virtuālo mašīnu, radās kļūda. Lūdzu, mēģiniet vēlreiz.</translation>
@@ -4671,6 +4683,7 @@ Glabājiet atslēgas failu drošā vietā. Tas būs vajadzīgs, lai izveidotu ja
<translation id="8049705080247101012">Google atzīmēja paplašinājumu <ph name="EXTENSION_NAME" /> kā ļaunprātīgu un nepieļāva instalēšanu.</translation>
<translation id="8049913480579063185">Paplašinājuma nosaukums</translation>
<translation id="8050038245906040378">Microsoft tirdzniecības koda parakstīšana</translation>
+<translation id="8052887694493382350">Šis fails ir paredzēts datoram ar Windows programmatūru. Tas nav saderīgs ar jūsu ierīci, kurā darbojas operētājsistēma Chrome OS. <ph name="BEGIN_LINK_HELP" />Uzziniet vairāk<ph name="END_LINK_HELP" />.</translation>
<translation id="8053278772142718589">PKCS #12 faili</translation>
<translation id="8053390638574070785">Atkārtoti ielādēt šo lapu</translation>
<translation id="8054517699425078995">Šāda veida fails var kaitēt jūsu ierīcei. Vai tomēr vēlaties saglabāt failu <ph name="FILE_NAME" />?</translation>
@@ -4915,6 +4928,7 @@ Citas personas ar lēnu savienojumu, iespējams, neredzēs jūsu saturu.</transl
<translation id="8438566539970814960">Uzlabot meklēšanu un pārlūkošanu</translation>
<translation id="8439506636278576865">Piedāvāt tulkot lapas šajā valodā</translation>
<translation id="8440630305826533614">Linux lietotnes</translation>
+<translation id="8443338615972234259">Lūdzu, izveidojiet jaunu kontu uzraudzītajam lietotājam tūlīt.</translation>
<translation id="8446884382197647889">Uzziniet vairāk</translation>
<translation id="8447409163267621480">Jāiekļauj “Ctrl” vai “Alt”</translation>
<translation id="8448729345478502352">Palieliniet vai samaziniet ekrānā redzamos vienumus.</translation>
@@ -4939,6 +4953,7 @@ Citas personas ar lēnu savienojumu, iespējams, neredzēs jūsu saturu.</transl
<translation id="8468750959626135884">Atbloķējiet ierīci <ph name="DEVICE_TYPE" />, izmantojot savu Android tālruni.</translation>
<translation id="8470028084415844044">Lai visas paroles būtu pieejamas visās jūsu ierīcēs, ieslēdziet sinhronizēšanu.</translation>
<translation id="8470513973197838199">Saglabātās paroles vietnei <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Lai izmantotu šo karti visās savās ierīcēs, saglabājiet to savā Google kontā</translation>
<translation id="8472623782143987204">hardware-backed</translation>
<translation id="8473863474539038330">Adreses un citus datus</translation>
<translation id="8475313423285172237">Cita datorā instalēta programma ir izraisījusi tāda paplašinājuma pievienošanu, kas var ietekmēt pārlūkprogrammas Chrome darbību.</translation>
@@ -5014,7 +5029,6 @@ Citas personas ar lēnu savienojumu, iespējams, neredzēs jūsu saturu.</transl
<translation id="8598453409908276158">Ir bloķēts spraudnis, kas nav ievietots smilškastē</translation>
<translation id="8601206103050338563">TLS WWW klienta autentifikācija</translation>
<translation id="8602851771975208551">Cita datorā instalēta programma ir izraisījusi tādas lietotnes pievienošanu, kas var ietekmēt pārlūkprogrammas Chrome darbību.</translation>
-<translation id="8604763363205185560">Palīdziet uzlabot pārlūkprogrammu Chrome un tās drošību</translation>
<translation id="8605428685123651449">SQLite atmiņa</translation>
<translation id="8606726445206553943">izmantot jūsu MIDI ierīces</translation>
<translation id="8609465669617005112">Virziet uz augšu</translation>
@@ -5190,6 +5204,7 @@ Citas personas ar lēnu savienojumu, iespējams, neredzēs jūsu saturu.</transl
<translation id="8846141544112579928">Notiek tastatūras meklēšana...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Savienojot ierīces, jūs piekrītat, ka Chromebook var:</translation>
+<translation id="8850251000316748990">Skatīt vairāk...</translation>
<translation id="8859057652521303089">Atlasiet savu valodu:</translation>
<translation id="8859174528519900719">Apakšrāmis: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel izklājlapa</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ml.xtb b/chromium/chrome/app/resources/generated_resources_ml.xtb
index b68a2bc44f1..7c518963026 100644
--- a/chromium/chrome/app/resources/generated_resources_ml.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ml.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">തീം പ്രവർത്തനക്ഷമമാക്കുക</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome വെബ് സ്‌റ്റോറിൽ കാണുക</translation>
-<translation id="1761588866118490543">വോയ്‌സ് മോഡൽ</translation>
<translation id="176193854664720708">വിരലടയാള സെന്‍സര്‍, പവര്‍ ബട്ടണിലാണ്‌ ഉള്ളത്. ഏതെങ്കിലും വിരലുകൊണ്ട് അത് മൃദുവായി സ്‌പര്‍ശിക്കുക.</translation>
<translation id="1763046204212875858">അപ്ലിക്കേഷന്‍‌ കുറുക്കുവഴികള്‍‌ സൃഷ്‌ടിക്കുക</translation>
<translation id="1763108912552529023">പര്യവേക്ഷണം ചെയ്യുന്നത് തുടരുക</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">ഉപയോഗവും പ്രശ്‌നനിർണ്ണയവുമായി ബന്ധപ്പെട്ട ഡാറ്റ അയയ്ക്കുക. പ്രശ്‌നനിർണ്ണയം, ഉപകരണം, ആപ്പ് ഉപയോഗം എന്നിവയുമായി ബന്ധപ്പെട്ട ഡാറ്റ, ഈ ഉപകരണം നിലവിൽ സ്വയമേവ Google-ന് അയയ്ക്കുന്നുണ്ട്. സിസ്‌റ്റം, ആപ്പ് സ്ഥിരത, മറ്റ് മെച്ചപ്പെടുത്തൽ എന്നിവയ്ക്ക് ഇത് സഹായിക്കും. ചില സംഗ്രഹ ഡാറ്റ, Google ആപ്പുകളെയും Android ഡെവലപ്പർമാരെപ്പോലുള്ള പങ്കാളികളെയും സഹായിക്കുകയും ചെയ്യും. ഈ ക്രമീകരണം നടപ്പിലാക്കുന്നത് ഉടമയാണ്. നിങ്ങളുടെ അധിക വെബ്, ആപ്പ് ആക്റ്റിവിറ്റി ക്രമീകരണം ഓണാക്കിയിട്ടുണ്ടെങ്കിൽ, ഈ ഡാറ്റ നിങ്ങളുടെ Google അക്കൗണ്ടിൽ സംരക്ഷിക്കപ്പെട്ടേക്കാം. <ph name="BEGIN_LINK1" />കൂടുതലറിയുക<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip ശേഖരം</translation>
<translation id="220858061631308971">"<ph name="DEVICE_NAME" />" എന്നതിൽ PIN കോഡ് നൽകുക:</translation>
+<translation id="2213140827792212876">പങ്കിടൽ നീക്കം ചെയ്യുന്നു</translation>
+<translation id="2214018885812055163">പങ്കിട്ട ഫോൾഡറുകൾ</translation>
<translation id="2214884991347062907">പാസ്‌വേഡ് തെറ്റാണ്, വീണ്ടും ശ്രമിക്കുക</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;ഒരു വരി കാണിച്ചിട്ടില്ല&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> വരികൾ കാണിച്ചിട്ടില്ല&gt;}}</translation>
<translation id="2217501013957346740">ഒരു പേര് സൃഷ്‌ടിക്കുക -</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">സര്‍‌ട്ടിഫിക്കറ്റ് തടഞ്ഞിരിക്കുന്നു</translation>
<translation id="2501797496290880632">ഒരു കുറുക്കുവഴി ടൈപ്പുചെയ്യുക</translation>
<translation id="2502441965851148920">സ്വയമേവയുള്ള അപ്‌ഡേറ്റുകൾ പ്രവർത്തനക്ഷമമാക്കി. സ്വമേധയാ ഉള്ള അപ്‌ഡേറ്റുകൾ നിങ്ങളുടെ അഡ്‌മിനി‌സ്‌ട്രേറ്റർ പ്രവർത്തനരഹിതമാക്കി.</translation>
+<translation id="2505127913256479918">മേൽനോട്ടം വഹിക്കപ്പെടുന്ന ഈ അക്കൗണ്ട് വൈകാതെ നീക്കം ചെയ്യപ്പെടും</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{സ്‌ക്രീൻ #}other{സ്‌ക്രീൻ #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" /> ന്റെ <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play സ്‌റ്റോർ അക്കൗണ്ട്</translation>
@@ -1372,6 +1374,7 @@
<translation id="304747341537320566">സ്പീച്ച് എഞ്ചിനുകൾ</translation>
<translation id="3053013834507634016">സര്‍‌ട്ടിഫിക്കറ്റ് കീ ഉപയോഗം</translation>
<translation id="3057861065630527966">നിങ്ങളുടെ ഫോട്ടോകളും വീഡിയോകളും ബാക്കപ്പുചെയ്യുക</translation>
+<translation id="3058498974290601450">നിങ്ങൾക്ക് ഏത് സമയത്തും ക്രമീകരണത്തിൽ സമന്വയം ഓണാക്കാവുന്നതാണ്</translation>
<translation id="3060379269883947824">'വായിച്ചുകേൾക്കാൻ തിരഞ്ഞെടുക്കുക' പ്രവർത്തനക്ഷമമാക്കുക</translation>
<translation id="3061707000357573562">പാച്ച് സേവനം</translation>
<translation id="3065041951436100775">ടാബ് പ്രവർത്തനരഹിതമായതിനെക്കുറിച്ചുള്ള ഫീഡ്‌ബാക്ക്.</translation>
@@ -1563,6 +1566,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> ഇന്‍സ്റ്റാള്‍ ചെയ്യും.</translation>
<translation id="3380365263193509176">അജ്ഞാതമായ പിശക്</translation>
<translation id="3382073616108123819">ക്ഷമിക്കണം! ഈ ഉപകരണത്തിന് ഉപകരണ ഐഡന്റിഫയറുകൾ കണ്ടെത്തുന്നതിൽ ഈ സി‌സ്‌റ്റം പരാജയപ്പെട്ടു.</translation>
+<translation id="3382086682569279540">നിങ്ങൾ മാനേജ് ചെയ്യുന്ന അക്കൗണ്ട് വൈകാതെ നീക്കം ചെയ്യപ്പെടും</translation>
<translation id="3382200254148930874">മേൽനോട്ടം നിർത്തുന്നു...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">സെപ്പറേറ്റര്‍</translation>
@@ -1743,8 +1747,8 @@
<translation id="3636096452488277381">ഹലോ, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> ശേഷിക്കുന്നു</translation>
<translation id="3637682276779847508">ശരിയായ പിൻ അണ്‍ലോക്ക് കീ നല്‍കാന്‍ നിങ്ങള്‍ക്ക് കഴിഞ്ഞില്ലെങ്കിൽ സിം കാര്‍ഡ് ശാശ്വതമായി പ്രവർത്തനരഹിതമാക്കും.</translation>
-<translation id="363863692969456324">മെച്ചപ്പെടുത്തിയ അക്ഷരത്തെറ്റ് പരിശോധന ഉപയോഗിച്ച്, അക്ഷരപ്പിശകുകൾ പരിഹരിക്കുക</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> എന്നയാൾക്കായി "<ph name="EXTENSION_NAME" />" ചേർക്കണോ?</translation>
+<translation id="3640613767643722554">നിങ്ങളുടെ ശബ്‌ദം തിരിച്ചറിയാൻ അസിസ്‌റ്റൻ്റിനെ പഠിപ്പിക്കുക</translation>
<translation id="3644896802912593514">വീതി</translation>
<translation id="3645372836428131288">ഫിംഗർപ്രിന്റിന്റെ മറ്റൊരു ഭാഗം പകർത്താൻ ചെറുതായി നീക്കുക.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> കണ്ടെത്തി</translation>
@@ -2143,7 +2147,6 @@
<translation id="4244238649050961491">കൂടുതൽ സ്‌റ്റൈലസ് ആപ്പുകൾ കാണുക</translation>
<translation id="424546999567421758">ഉയർന്ന ഡിസ്‌ക് ഉപയോഗം കണ്ടെത്തി</translation>
<translation id="424726838611654458">എപ്പോഴും Adobe Reader-ൽ തുറക്കുക</translation>
-<translation id="4247330672018280062">ടെക്‌സ്‌റ്റ് ഫീൽഡുകളിൽ നിങ്ങൾ ടൈപ്പ് ചെയ്യുന്ന ടെക്‌സ്‌റ്റ് Google-ലേക്ക് അയയ്ക്കും</translation>
<translation id="4247901771970415646"><ph name="USERNAME" /> എന്ന ഉപയോക്താവിലേക്ക് സമന്വയിപ്പിക്കാനാവില്ല</translation>
<translation id="4249248555939881673">നെറ്റ്‌വർക്ക് കണക്ഷനുവേണ്ടി കാത്തിരിക്കുന്നു...</translation>
<translation id="4249373718504745892">നിങ്ങളുടെ ക്യാമറയും മൈക്രോഫോണും ആക്‌സസ്സുചെയ്യുന്നതിൽ നിന്ന് ഈ പേജിനെ തടഞ്ഞിരിക്കുന്നു.</translation>
@@ -2485,6 +2488,7 @@
<translation id="4821935166599369261">&amp;പ്രൊഫൈലിംഗ് പ്രാപ്തമാക്കി</translation>
<translation id="4823484602432206655">ഉപയോക്തൃ, ഉപകരണ ക്രമീകരണങ്ങൾ റീഡുചെയ്‌ത് മാറ്റുക</translation>
<translation id="4823651846660089135">ഉപകരണം വായിക്കാൻ മാത്രമുള്ള മോഡിലാണ്</translation>
+<translation id="4824958205181053313">സമന്വയം റദ്ദാക്കണോ?</translation>
<translation id="4827675678516992122">കണക്റ്റ് ചെയ്യാനായില്ല</translation>
<translation id="4828937774870308359">ഓസ്‌ട്രേലിയൻ</translation>
<translation id="4829768588131278040">പിൻ നമ്പർ സജ്ജമാക്കുക</translation>
@@ -2867,6 +2871,7 @@
<translation id="5374359983950678924">ചിത്രം മാറ്റുക</translation>
<translation id="5376169624176189338">തിരികെ പോകാൻ ക്ലിക്ക് ചെയ്യുക, ചരിത്രം കാണാൻ ഹോൾഡ് ചെയ്യുക</translation>
<translation id="5376931455988532197">ഫയല്‍ വളരെ വലുതാണ്</translation>
+<translation id="5377594097385838788">അദൃശ്യ മോഡ്</translation>
<translation id="537813040452600081">ഈ വിൻഡോയിൽ നിങ്ങൾ കാണുന്ന പേജുകൾ സൈൻ ഔട്ട് ചെയ്‌ത ശേഷം ബ്രൗസർ ചരിത്രത്തിൽ ദൃശ്യമാകില്ല, ഒപ്പം കുക്കികൾ പോലുള്ള മറ്റ് തെളിവുകൾ കമ്പ്യൂട്ടറിൽ അവശേഷിപ്പിക്കുകയുമില്ല. നിങ്ങൾ ഡൗൺലോഡ് ചെയ്യുന്ന ഫയലുകളും സൃഷ്‌ടിക്കുന്ന ബുക്ക്‌മാർക്കുകളും സംരക്ഷിക്കപ്പെടില്ല.</translation>
<translation id="5379140238605961210">മൈക്രോഫോൺ ആക്‌സസ്സ് തടയുന്നത് തുടരുക</translation>
<translation id="5379268888377976432">ഇല്ലാതാക്കിയത് പഴയപടിയാക്കുക</translation>
@@ -2888,6 +2893,7 @@
<translation id="5414566801737831689">നിങ്ങൾ സന്ദർശിക്കുന്ന വെബ്‌സൈറ്റുകളുടെ ഐക്കൺ റീഡുചെയ്യുക</translation>
<translation id="5417312524372586921">ബ്രൗസർ തീമുകൾ</translation>
<translation id="5419294236999569767">സിസ്‌റ്റം സമയം</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">ടെക്‌സ്‌റ്റിന്റെയും ചിത്രങ്ങളുടെയും ഷാർപ്പ്‌നെസ്സ് നിർണ്ണയിക്കുന്നു</translation>
<translation id="5422221874247253874">ആക്‌സസ് പോയിന്റ്</translation>
<translation id="5422781158178868512">ക്ഷമിക്കണം, നിങ്ങളുടെ ബാഹ്യ സംഭരണി ഉപകരണം അംഗീകരിക്കാൻ കഴിഞ്ഞില്ല.</translation>
@@ -2908,6 +2914,7 @@
<translation id="5434065355175441495">PKCS #1 RSA എന്‍‌ക്രിപ്‌ഷന്‍‌</translation>
<translation id="5436492226391861498">പ്രോക്സി ടണലിനായി കാത്തിരിക്കുന്നു...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> തിരയുക:</translation>
+<translation id="543806387003274181">നിങ്ങളുടെ ഫയലുകൾ സംരക്ഷിച്ച് ഇപ്പോൾ പുതിയൊരു അക്കൗണ്ട് സൃഷ്‌ടിക്കുക.</translation>
<translation id="5438224778284622050">ഓഫ്‌ലൈൻ ഫയലുകൾ ഇല്ലാതാക്കണോ?</translation>
<translation id="544083962418256601">കുറുക്കുവഴികൾ സൃഷ്‌ടിക്കുക...</translation>
<translation id="5442228125690314719">ഡിസ്‌ക് ഇമേജ് സൃഷ്‌ടിക്കുന്നതിൽ പിശക്. വീണ്ടും ശ്രമിക്കുക.</translation>
@@ -3282,6 +3289,8 @@
<translation id="5965661248935608907">നിങ്ങൾ ഹോം ബട്ടൺ ക്ലിക്കുചെയ്യുമ്പോഴോ ഓമ്‌നിബോക്‌സിൽ നിന്ന് തിരയുമ്പോഴോ ദൃശ്യമാകുന്ന പേജും അത് നിയന്ത്രിയ്ക്കും.</translation>
<translation id="5971037678316050792">Bluetooth അഡാപ്‌റ്റർ നിലയും ജോടിയാക്കലും നിയന്ത്രിക്കുക</translation>
<translation id="5972017421290582825">MIDI ക്രമീകരണങ്ങൾ നിയന്ത്രിക്കുക...</translation>
+<translation id="597235323114979258">കൂടുതൽ ലക്ഷ്യസ്ഥാനങ്ങൾ കാണുക</translation>
+<translation id="5972666587303800813">No-op സേവനം</translation>
<translation id="5972708806901999743">മുകളിലേക്ക് നീക്കുക</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> ആരംഭിക്കുക</translation>
<translation id="5975792506968920132">ബാറ്ററി ചാർജ്ജ് ശതമാനം</translation>
@@ -3654,6 +3663,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="6527303717912515753">പങ്കിടുക</translation>
<translation id="6528513914570774834">ഈ നെറ്റ്‌വർക്ക് ഉപയോഗിക്കാൻ ഉപകരണത്തിലെ മറ്റ് ഉപയോക്താക്കളെ അനുവദിക്കുക</translation>
<translation id="652948702951888897">Chrome ചരിത്രം</translation>
+<translation id="6530186581263215931">ഈ ക്രമീകരണം നടപ്പിലാക്കുന്നത് നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്ററാണ്</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> എന്നത് സമന്വയിപ്പിക്കുന്നു...</translation>
<translation id="6531282281159901044">അപകടകരമായ ഫയൽ സൂക്ഷിക്കുക</translation>
<translation id="6532101170117367231">Google ഡ്രൈവിൽ സംരക്ഷിക്കുക</translation>
@@ -3972,7 +3982,6 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="7018275672629230621">നിങ്ങളുടെ ബ്രൗസിംഗ് ചരിത്രം റീഡുചെയ്യുക, മാറ്റുക</translation>
<translation id="7019805045859631636">വേഗത</translation>
<translation id="7022562585984256452">നിങ്ങളുടെ ഹോം പേജ് സജ്ജമാക്കി.</translation>
-<translation id="702384510542929236">വ്യക്തിപര വിവരങ്ങൾ ഒഴികെയുള്ള ചില സിസ്‌റ്റം വിവരങ്ങളും പേജ് ഉള്ളടക്കവും Google-ലേക്ക് അയയ്ക്കുന്നു</translation>
<translation id="7025190659207909717">മൊബൈല്‍ ഡാറ്റ സേവന മാനേജുമെന്‍റ്</translation>
<translation id="7027125358315426638">ഡാറ്റാബേസിന്റെ പേര്:</translation>
<translation id="7029809446516969842">പാസ്‌വേഡുകള്‍</translation>
@@ -4152,6 +4161,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="7289225569524511578">വാൾപേപ്പർ ആപ്പ് തുറക്കുക</translation>
<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> ഹോസ്‌റ്റുചെയ്യുന്ന ഈ സൈൻ ഇൻ സേവനം നിങ്ങളുടെ ക്യാമറ ആക്‌സസ്സ് ചെയ്യുന്നുണ്ട്.</translation>
<translation id="7290594223351252791">രജിസ്ട്രേഷൻ സ്ഥിരീകരിക്കുക</translation>
+<translation id="7292696521213967957">അസിസ്‌റ്റന്‍റ് ഡീബഗ് ചെയ്യാനുള്ള വിവരം</translation>
<translation id="7295662345261934369">മറ്റുള്ളവരുമായി പങ്കിടുക</translation>
<translation id="729583233778673644">AES,RC4 എൻക്രിപ്ഷനുകൾ അനുവദിക്കുക. RC4 രഹസ്യലിപി സുരക്ഷിതമല്ലാത്തതിനാൽ ഈ ഓപ്ഷൻ അനുവദിക്കുന്നത് അപകടസാധ്യത വർദ്ധിപ്പിക്കുന്നു.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> നിബന്ധനകൾ</translation>
@@ -4252,7 +4262,6 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="7456847797759667638">സ്ഥാനം തുറക്കുക...</translation>
<translation id="7461924472993315131">പിൻ ചെയ്യുക</translation>
<translation id="7463006580194749499">വ്യക്തിയെ ചേർക്കുക</translation>
-<translation id="7464902436585505072">"Ok Google" വോയ്‌സ് മോഡൽ</translation>
<translation id="7465778193084373987">നെറ്റ്‌സ്‌കേപ്പ് സര്‍‌ട്ടിഫിക്കറ്റ് അസാധുവാക്കല്‍‌ URL</translation>
<translation id="7469894403370665791">ഈ നെറ്റ്‍വര്‍ക്കിലേക്ക് സ്വപ്രേരിതമായി ബന്ധിപ്പിക്കുന്നു</translation>
<translation id="747114903913869239">പിശക്: വിപുലീകരണം ഡീകോഡ് ചെയ്യാനാവില്ല</translation>
@@ -4280,6 +4289,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> എന്നതും അതുമായി ബന്ധപ്പെട്ട ഡാറ്റയും ഈ ഉപകരണത്തിൽ നിന്ന് ഇല്ലാതാക്കും.</translation>
<translation id="7497215489070763236">സെർവർ CA സർട്ടിഫിക്കറ്റ്</translation>
<translation id="7497981768003291373">നിങ്ങൾക്ക് അടുത്തിടെ രേഖപ്പെടുത്തിയ WebRTC ടെക്‌സ്‌റ്റ് ലോഗുകളൊന്നുമില്ല.</translation>
+<translation id="7502199377020483660">നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങളിലും ഈ കാർഡുകൾ ഉപയോഗിക്കാൻ, അവ നിങ്ങളുടെ Google അക്കൗണ്ടിൽ സംരക്ഷിക്കുക</translation>
<translation id="7502658306369382406">IPv6 വിലാസം</translation>
<translation id="7503191893372251637">നെറ്റ്‌സ്‌കേപ്പ് സര്‍‌ട്ടിഫിക്കറ്റ് തരം</translation>
<translation id="7503821294401948377">ബ്രൗസർ പ്രവർത്തനത്തിനായി '<ph name="ICON" />' ഐക്കൺ ലോഡ് ചെയ്യാനായില്ല.</translation>
@@ -4377,6 +4387,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="7663719505383602579">റിസീവർ: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">പിന്തുണയ്‌ക്കാത്ത Bluetooth ഉപകരണം: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">അക്കൗണ്ട് ചേർക്കുക</translation>
+<translation id="7667248760110172428">ബാഹ്യ സ്‌റ്റോറേജ്</translation>
<translation id="7671130400130574146">സിസ്റ്റം ശീര്‍ഷക ബാറും ബോര്‍ഡറുകളും ഉപയോഗിക്കുക</translation>
<translation id="7672520070349703697"><ph name="PAGE_TITLE" />-ൽ <ph name="HUNG_IFRAME_URL" />.</translation>
<translation id="7676867886086876795">ഏതെങ്കിലും ടെക്‌സ്‌റ്റ് ഫീൽഡിലേക്ക് കേട്ടെഴുതുന്നത് അനുവദിക്കാൻ നിങ്ങളുടെ വോയ്‌സ് Google-ലേക്ക് അയയ്‌ക്കുക.</translation>
@@ -4580,6 +4591,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="7930294771522048157">സംരക്ഷിച്ച പേയ്മെന്റ് രീതികൾ ഇവിടെ ദൃശ്യമാകും</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> നിങ്ങളുടെ സ്‌ക്രീനും ഓഡിയോയും പങ്കിടുന്നു.</translation>
<translation id="7931318309563332511">അറിഞ്ഞുകൂടാത്തത്</translation>
+<translation id="7932969338829957666">പങ്കിട്ട ഫോൾഡറുകൾ <ph name="BASE_DIR" /> എന്ന ലൊക്കേഷനിലെ Linux-ൽ ലഭ്യമാണ്.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{സൈറ്റ് അൺമ്യൂട്ട് ചെയ്യുക}other{സൈറ്റുകൾ അൺമ്യൂട്ട് ചെയ്യുക}}</translation>
<translation id="7934414805353235750">പരിരക്ഷിത ഉള്ളടക്കം പ്ലേ ചെയ്യാൻ <ph name="URL" /> ആഗ്രഹിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിന്റെ ഐഡന്റിറ്റി, Google പരിശോധിച്ചുറപ്പിക്കും</translation>
<translation id="793531125873261495">വെർച്വൽ മെഷീൻ ഡൗൺലോഡ് ചെയ്യുന്നതിൽ പിശക്. വീണ്ടും ശ്രമിക്കുക.</translation>
@@ -4671,6 +4683,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="8049705080247101012">"<ph name="EXTENSION_NAME" />" എന്നതിനെ Google ക്ഷുദ്രകരമെന്ന് ഫ്ലാഗ് ചെയ്‌തതിനാൽ ഇൻസ്റ്റലേഷൻ തടയപ്പെട്ടു</translation>
<translation id="8049913480579063185">വിപുലീകരണത്തിന്റെ പേര്</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">ഈ ഫയൽ, Windows സോഫ്‌റ്റ്‌വെയർ ഉപയോഗിക്കുന്ന PC-‌യ്ക്കായി രൂപകൽപ്പന ചെയ്‌തതാണ്. ഇത് Chrome OS റൺ ചെയ്യുന്ന നിങ്ങളുടെ ഉപകരണത്തിന് അനുയോജ്യമല്ല. <ph name="BEGIN_LINK_HELP" />കൂടുതലറിയുക<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 ഫയലുകള്‍</translation>
<translation id="8053390638574070785">ഈ പേജ് വീണ്ടും ലോഡ് ചെയ്യുക</translation>
<translation id="8054517699425078995">ഈ തരത്തിലുള്ള ഫയൽ നിങ്ങളുടെ ഉപകരണത്തിന് ദോഷകരമാണ്. ഏതുവിധേനയും <ph name="FILE_NAME" /> നിലനിർത്താൻ നിങ്ങൾക്ക് താൽപ്പര്യമുണ്ടോ?</translation>
@@ -4914,6 +4927,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="8438566539970814960">തിരയലുകളും ബ്രൗസിംഗും മികച്ചതാക്കുക</translation>
<translation id="8439506636278576865">പേജുകൾ ഈ ഭാഷയിലേക്ക് വിവർത്തനം ചെയ്യാനുള്ള ഓഫർ</translation>
<translation id="8440630305826533614">Linux ആപ്പുകൾ</translation>
+<translation id="8443338615972234259">ഇപ്പോൾ നിങ്ങളുടെ മേൽനോട്ടത്തിലുള്ള ഉപയോക്താവിനായി പുതിയൊരു അക്കൗണ്ട് സൃഷ്ടിക്കുക.</translation>
<translation id="8446884382197647889">കൂടുതലറിയുക</translation>
<translation id="8447409163267621480">ഒന്നുകിൽ Ctrl അല്ലെങ്കിൽ, Alt ഉൾപ്പെടുത്തുക</translation>
<translation id="8448729345478502352">സ്ക്രീനിലെ ഇനങ്ങൾ കൂടുതൽ ചെറുതോ വലുതോ ആക്കുക</translation>
@@ -4938,6 +4952,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="8468750959626135884">Android ഫോൺ ഉപയോഗിച്ച് നിങ്ങളുടെ <ph name="DEVICE_TYPE" /> അൺലോക്കുചെയ്യുക.</translation>
<translation id="8470028084415844044">നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങളിലും മുഴുവൻ പാസ്‌വേഡുകളും ലഭിക്കാൻ സമന്വയിപ്പിക്കൽ ഓണാക്കുക.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" />-നായി സംരക്ഷിച്ച പാസ്‌വേഡുകൾ</translation>
+<translation id="8471635086304129332">നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങളിലും ഈ കാർഡ് ഉപയോഗിക്കാൻ അത് നിങ്ങളുടെ Google അക്കൗണ്ടിൽ സംരക്ഷിക്കുക</translation>
<translation id="8472623782143987204">ഹാര്‍ഡ്‌വെയര്‍-ബാക്കുചെയ്തു</translation>
<translation id="8473863474539038330">വിലാസങ്ങളും മറ്റും</translation>
<translation id="8475313423285172237">നിങ്ങളുടെ കമ്പ്യൂട്ടറിലെ മറ്റൊരു പ്രോഗ്രാം Chrome പ്രവർത്തിക്കുന്ന രീതി മാറ്റിയേക്കാവുന്ന ഒരു വിപുലീകരണം ചേർത്തു.</translation>
@@ -5013,7 +5028,6 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="8598453409908276158">അൺസാൻഡ്‌ബോക്‌സ് ചെയ്‌ത പ്ലഗിൻ ബ്ലോക്ക് ചെയ്‌തു</translation>
<translation id="8601206103050338563">TLS WWW ക്ലയന്‍റ് പ്രാമാണീകരണം</translation>
<translation id="8602851771975208551">നിങ്ങളുടെ കമ്പ്യൂട്ടറിലെ മറ്റൊരു പ്രോഗ്രാം Chrome പ്രവർത്തിക്കുന്ന രീതി മാറ്റിയേക്കാവുന്ന ഒരു അപ്ലിക്കേഷൻ ചേർത്തു.</translation>
-<translation id="8604763363205185560">Chrome, അതിന്റെ സുരക്ഷ എന്നിവ മെച്ചപ്പെടുത്താൻ സഹായിക്കുക</translation>
<translation id="8605428685123651449">SQLite മെമ്മറി</translation>
<translation id="8606726445206553943">നിങ്ങളുടെ MIDI ഉപകരണങ്ങൾ ഉപയോഗിക്കുക</translation>
<translation id="8609465669617005112">മുകളിലേക്ക് നീക്കുക</translation>
@@ -5188,6 +5202,7 @@ Google Chrome മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കും.
<translation id="8846141544112579928">കീബോർഡിനായി തിരയുന്നു...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">ഉപകരണങ്ങൾ കണക്‌റ്റ് ചെയ്യുമ്പോൾ, Chromebook-ന് ഇനിപ്പറയുന്ന കാര്യങ്ങൾ ചെയ്യാനാകുമെന്ന് നിങ്ങൾ അംഗീകരിക്കുന്നു:</translation>
+<translation id="8850251000316748990">കൂടുതൽ കാണുക...</translation>
<translation id="8859057652521303089">നിങ്ങളുടെ ഭാഷ തിരഞ്ഞെടുക്കുക :</translation>
<translation id="8859174528519900719">സബ്ഫ്രെയിം: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel സ്‌പ്രെഡ്‌ഷീറ്റ്</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_mr.xtb b/chromium/chrome/app/resources/generated_resources_mr.xtb
index 09b91319d3e..956806877e3 100644
--- a/chromium/chrome/app/resources/generated_resources_mr.xtb
+++ b/chromium/chrome/app/resources/generated_resources_mr.xtb
@@ -517,7 +517,6 @@
<translation id="175772926354468439">थीम सक्षम करा</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome वेब स्टोअरमध्ये पहा</translation>
-<translation id="1761588866118490543">व्हॉइस मॉडेल</translation>
<translation id="176193854664720708">फिंगरप्रिंट सेन्सर पॉवर बटणात आहे. कोणत्याही बोटाने हळूवारपणे स्पर्श करा.</translation>
<translation id="1763046204212875858">अॅप्लिकेशन शॉर्टकट तयार करा</translation>
<translation id="1763108912552529023">एक्सप्लोर करत रहा</translation>
@@ -814,6 +813,8 @@
<translation id="220792432208469595">वापर आणि निदान डेटा पाठवा. हे डिव्हाइस सध्या Google ला आपोआप निदान, डिव्हाइस आणि अ‍ॅप वापर डेटा पाठवत आहे. हे सिस्ट्म आणि अ‍ॅप स्थिरता आणि इतर सुधारणा करण्यात मदत करेल. काही एकत्रित केलेला डेटा Google अ‍ॅप्स आणि Android डेव्हलपर सारख्या भागीदारांना देखील मदत करेल. या सेटिंगची मालकाद्वारे अंमलबजावणी केली जाते. जर तुमची अतिरिक्त वेब आणि अ‍ॅप अ‍ॅक्टिव्हिटी सेटिंग सुरू केलेली असल्यास, हा डेटा तुमच्या Google खाते वर सेव्ह केला जाऊ शकतो. <ph name="BEGIN_LINK1" />अधिक जाणून घ्या<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">झीप संग्रहण करा</translation>
<translation id="220858061631308971">कृपया यावर हा पिन कोड प्रविष्‍ट करा "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">शेअरिंग काढा</translation>
+<translation id="2214018885812055163">शेअर केलेली फोल्डर</translation>
<translation id="2214884991347062907">चुकीचा पासवर्ड, पुन्हा प्रयत्न करा</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;एक ओळ दाखवलेली नाही&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> ओळ दाखवलेली नाही&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> ओळी दाखवलेल्या नाहीत&gt;}}</translation>
<translation id="2217501013957346740">एक नाव तयार करा -</translation>
@@ -1014,6 +1015,7 @@
<translation id="2501173422421700905">राखून ठेवलेले सर्टिफिकेट</translation>
<translation id="2501797496290880632">शॉर्टकट टाइप करा</translation>
<translation id="2502441965851148920">स्वयंचलित अपडेट सक्षम केली आहेत. आपल्‍या प्रशासकाने व्यक्तिचलित अपडेट अक्षम केली आहेत.</translation>
+<translation id="2505127913256479918">हे पर्यवेक्षित खाते लवकरच काढले जाईल</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{स्क्रीन #}one{स्क्रीन #}other{स्क्रीन #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" /> पैकी <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play स्टोअर खाते</translation>
@@ -1374,6 +1376,7 @@
<translation id="304747341537320566">स्पीच इंजिन</translation>
<translation id="3053013834507634016">सर्टिफिकेट की वापर</translation>
<translation id="3057861065630527966">तुमचे फोटो आणि व्हिडिओंचा बॅकअप घ्या</translation>
+<translation id="3058498974290601450">तुम्ही सेटिंग्जमध्ये कधीही सिंक सुरू करू शकता</translation>
<translation id="3060379269883947824">बोलण्यासाठी निवडा सुरू करा</translation>
<translation id="3061707000357573562">पॅच सेवा</translation>
<translation id="3065041951436100775">टॅबने नष्ट केलेला अभिप्राय</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> इंस्टॉल केले जाईल.</translation>
<translation id="3380365263193509176">अज्ञात एरर</translation>
<translation id="3382073616108123819">अरेरे! या डिव्हाइससाठी डिव्हाइस अभिज्ञापक निर्धारित करण्यात सिस्टम अयशस्वी.</translation>
+<translation id="3382086682569279540">तुम्ही व्यवस्थापित करत असलेले खाते लवकरच काढले जाईल</translation>
<translation id="3382200254148930874">पर्यवेक्षण थांबवत आहे...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">विभाजक</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">कसे आहात, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> शिल्लक</translation>
<translation id="3637682276779847508">तुम्ही योग्य पिन अनलॉक की एंटर न केल्यास तुमचे सिम कार्ड कायमचे अक्षम केले जाईल.</translation>
-<translation id="363863692969456324">सुधारित स्पेल चेकसह शब्दलेखनातील एररमध्ये सुधारणा करा</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> साठी "<ph name="EXTENSION_NAME" />" जोडायचे?</translation>
+<translation id="3640613767643722554">तुमच्या असिस्टंटला तुमचा आवाज ओळखण्यास शिकवा</translation>
<translation id="3644896802912593514">रूंदी</translation>
<translation id="3645372836428131288">फिंगरप्रिंटचा वेगळा भाग कॅप्चर करण्यासाठी बोट किंचित हलवा.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> आढळले</translation>
@@ -2146,7 +2150,6 @@
<translation id="4244238649050961491">अधिक लेखणी अॅप्स शोधा</translation>
<translation id="424546999567421758">अतिशय जास्त डिस्क वापर आढळला</translation>
<translation id="424726838611654458">Adobe Reader मध्ये नेहमी उघडा</translation>
-<translation id="4247330672018280062">मजकुराच्या भागात टाइप केलेला मजकूर Google कडे पाठवला जाईल</translation>
<translation id="4247901771970415646"><ph name="USERNAME" /> शी सिंक करू शकत नाही</translation>
<translation id="4249248555939881673">नेटवर्क कनेक्शनची प्रतीक्षा करत आहे...</translation>
<translation id="4249373718504745892">हे पृष्‍ठ तुमचा कॅमेरा आणि मायक्रोफोनवर प्रवेश करण्यापासून अवरोधित केले गेले आहे.</translation>
@@ -2488,6 +2491,7 @@
<translation id="4821935166599369261">&amp;प्रोफाइलिंग सक्षम</translation>
<translation id="4823484602432206655">वापरकर्ता आणि डिव्हाइस सेटिंग्ज वाचा आणि बदला</translation>
<translation id="4823651846660089135">डिव्हाइस केवळ वाचनीय आहे</translation>
+<translation id="4824958205181053313">सिंक रद्द करायचे?</translation>
<translation id="4827675678516992122">कनेक्ट करता आले नाही</translation>
<translation id="4828937774870308359">ऑस्ट्रेलियन</translation>
<translation id="4829768588131278040">पिन सेट करा</translation>
@@ -2870,6 +2874,7 @@
<translation id="5374359983950678924">चित्र बदला</translation>
<translation id="5376169624176189338">परत जाण्यासाठी क्लिक करा, इतिहास पहाण्यासाठी होल्ड करा</translation>
<translation id="5376931455988532197">फाईल खूप मोठी आहे</translation>
+<translation id="5377594097385838788">गुप्त</translation>
<translation id="537813040452600081">या विंडोमध्ये तुम्ही पाहत असलेली पेज ब्राउझर इतिहासात दिसणार नाहीत आणि तुम्ही साइन आउट केल्यानंतर, संगणकावर कुकीज सारखे, अन्य ट्रेस ते सोडणार नाहीत. तुम्ही डाउनलोड करता त्या फायली आणि तुम्ही तयार करता ते बुकमार्क संरक्षित केले जाणार नाहीत.</translation>
<translation id="5379140238605961210">मायक्रोफोन प्रवेश अवरोधित करणे सुरू ठेवा</translation>
<translation id="5379268888377976432">हटवणे पहिल्यासारखी करा</translation>
@@ -2891,6 +2896,7 @@
<translation id="5414566801737831689">तुम्ही भेट देता त्या वेबसाइटची चिन्हे वाचा</translation>
<translation id="5417312524372586921">ब्राउझर थीम</translation>
<translation id="5419294236999569767">प्रणाली वेळ</translation>
+<translation id="5419405654816502573">Voice match</translation>
<translation id="5420438158931847627">मजकूर आणि इमेजचे शार्पनेस निर्धारित करते</translation>
<translation id="5422221874247253874">प्रवेश स्‍थान</translation>
<translation id="5422781158178868512">क्षमस्व, तुमचे बाह्य स्टोरेज डिव्हाइस ओळखले जाऊ शकले नाही.</translation>
@@ -2911,6 +2917,7 @@
<translation id="5434065355175441495">PKCS #1 RSA एंक्रिप्शन</translation>
<translation id="5436492226391861498">प्रॉक्झी टनलसाठी प्रतीक्षा करत आहे...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> शोधा:</translation>
+<translation id="543806387003274181">कृपया आता तुमच्या फायली सेव्ह करा आणि नवीन खाते तयार करा.</translation>
<translation id="5438224778284622050">ऑफलाइन फायली हटवायच्या?</translation>
<translation id="544083962418256601">शॉर्टकट तयार करा...</translation>
<translation id="5442228125690314719">डिस्क इमेज तयार करताना एरर आली. कृपया पुन्हा प्रयत्न करा.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">तुम्ही होम बटण क्लिक करता किंवा ओम्निबॉक्समधून शोध घेता तेव्हा कोणते पृष्ठ दर्शविले जाते हे देखील हे नियंत्रित करते.</translation>
<translation id="5971037678316050792">ब्लूटूथ अडाप्टर स्थिती आणि पेअरिंग नियंत्रित करा</translation>
<translation id="5972017421290582825">MIDI सेटिंग्ज व्यवस्थापित करा...</translation>
+<translation id="597235323114979258">आणखी गंतव्यस्थाने पहा</translation>
+<translation id="5972666587303800813">नो-ऑप सेवा</translation>
<translation id="5972708806901999743">शीर्षस्थानी हलवा</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> प्रारंभ करा</translation>
<translation id="5975792506968920132">बॅटरी चार्ज टक्केवारी</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">शेअर करा</translation>
<translation id="6528513914570774834">या डिव्हाइसच्या इतर वापरकर्त्यांना हे नेटवर्क वापरण्याची परवानगी द्या</translation>
<translation id="652948702951888897">Chrome इतिहास</translation>
+<translation id="6530186581263215931">या सेटिंग्जची अंमलबजावणी तुमच्या अॅडमिनिस्ट्रेटरकडून होते</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> संकालित करत आहे...</translation>
<translation id="6531282281159901044">धोकादायक फाईल ठेवा</translation>
<translation id="6532101170117367231">Google ड्राइव्ह मध्ये सेव्ह करा</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">तुमचा ब्राउझिंग इतिहास वाचा आणि बदला</translation>
<translation id="7019805045859631636">जलद</translation>
<translation id="7022562585984256452">तुमचे मुख्यपृष्‍ठ सेट केले गेले आहे.</translation>
-<translation id="702384510542929236">Google ला काही सिस्टम माहिती आणि पेज आशय अनामिकपणे पाठवते</translation>
<translation id="7025190659207909717">मोबाइल डेटा सेवा व्यवस्थापन</translation>
<translation id="7027125358315426638">डेटाबेस नाव:</translation>
<translation id="7029809446516969842">पासवर्ड</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">वॉलपेपर ॲप उघडा</translation>
<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> नी होस्ट केलेली, ही साइन-इन सेवा, आपल्या कॅमेर्‍यामध्ये प्रवेश करीत आहे.</translation>
<translation id="7290594223351252791">नोंदणीची पुष्टी करा</translation>
+<translation id="7292696521213967957">असिस्टंट डीबग करण्याबाबत माहिती</translation>
<translation id="7295662345261934369">इतरांशी शेअर करा</translation>
<translation id="729583233778673644">AES आणि RC4 एंक्रिप्‍शनला अनुमती द्या. हा पर्याय वापरल्याने तुमचा धोका वाढतो, कारण RC4 सायफर असुरक्षित आहेत.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> अटी</translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">स्थान उघडा...</translation>
<translation id="7461924472993315131">पिन</translation>
<translation id="7463006580194749499">व्यक्ती जोडा</translation>
-<translation id="7464902436585505072">"Ok Google" व्हॉइस मॉडेल</translation>
<translation id="7465778193084373987">Netscape सर्टिफिकेट रिव्होकीकरण URL</translation>
<translation id="7469894403370665791">या नेटवर्कशी स्वयंचलितपणे कनेक्ट व्हा</translation>
<translation id="747114903913869239">एरर: विस्तार डीकोड करण्यात अक्षम</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> आणि त्याच्याशी संबंधित डेटा या डिव्हाइसवरून काढला जाईल.</translation>
<translation id="7497215489070763236">सर्व्हर CA सर्टिफिकेट</translation>
<translation id="7497981768003291373">तुमच्याकडे नुकतेच कॅप्चर केलेले कोणतेही WebRTC मजकूर लॉग नाहीत.</translation>
+<translation id="7502199377020483660">ही कार्डे तुमच्या सर्व डिव्हाइसवर वापरण्यासाठी, ती तुमच्या Google खात्यामध्ये सेव्ह करा</translation>
<translation id="7502658306369382406">IPv6 पत्ता</translation>
<translation id="7503191893372251637">Netscape सर्टिफिकेट प्रकार</translation>
<translation id="7503821294401948377">ब्राउझर क्रियेसाठी '<ph name="ICON" />' आयकन लोड करू शकलो नाही.</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">प्राप्तकर्ता: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">असमर्थित ब्लूटूथ डिव्हाइस: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">खाते जोडा</translation>
+<translation id="7667248760110172428">बाह्य स्टोरेज</translation>
<translation id="7671130400130574146">सिस्टम शीर्षक बार आणि किनारी वापरा</translation>
<translation id="7672520070349703697"><ph name="PAGE_TITLE" /> मध्ये <ph name="HUNG_IFRAME_URL" />.</translation>
<translation id="7676867886086876795">कोणत्याही मजकूर फील्डमध्ये डिक्टेशनला अनुमती देण्यासाठी Google ला तुमचा व्हॉइस पाठवा.</translation>
@@ -4579,6 +4590,7 @@
<translation id="7930294771522048157">सेव्ह केलेल्या पेमेंट पद्धती येथे दिसतील</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> तुमची स्क्रीन आणि ऑडिओ शेअर करीत आहे</translation>
<translation id="7931318309563332511">अनोळखी</translation>
+<translation id="7932969338829957666">शेअर केलेली फोल्डर Linux मध्ये <ph name="BASE_DIR" /> येथे उपलब्ध आहेत.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{साइट अनम्यूट करा}one{साइट अनम्यूट करा}other{साइट अनम्यूट करा}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> ला संरक्षित आशय चालू करायचा आहे. तुमच्या डिव्हाइसची ओळख Google द्वारे पडताळली जाईल</translation>
<translation id="793531125873261495">व्हर्च्युअल मशीन डाउनलोड करताना एरर आली. कृपया पुन्हा प्रयत्न करा.</translation>
@@ -4670,6 +4682,7 @@
<translation id="8049705080247101012">Google ने "<ph name="EXTENSION_NAME" />" ला दुर्भावनापूर्ण म्हणून फ्लॅग केले आहे आणि इंस्टॉल करणे रोखले गेले आहे</translation>
<translation id="8049913480579063185">विस्तार नाव</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">ही फाइल Windows सॉफ्टवेअर वापरणार्‍या PC साठी डिझाइन केली आहे. ही तुमच्या Chrome OS रन करणार्‍या डिव्हाइससोबत कंपॅटिबल नाही. <ph name="BEGIN_LINK_HELP" />अधिक जाणून घ्या<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 फायली</translation>
<translation id="8053390638574070785">हे पृष्ठ रीलोड करा</translation>
<translation id="8054517699425078995">या प्रकारची फाईल आपल्‍या डिव्‍हाइसला हानी पोहचवू शकते. तुम्ही <ph name="FILE_NAME" /> तरीही ठेवू इच्‍छिता?</translation>
@@ -4913,6 +4926,7 @@
<translation id="8438566539970814960">शोध आणि ब्राउझ करणे चांगले करा</translation>
<translation id="8439506636278576865">या भाषेमध्ये पेज भाषांतरीत करण्यासाठी ऑफर</translation>
<translation id="8440630305826533614">Linux अॅप्स</translation>
+<translation id="8443338615972234259">आता तुमच्या व्यवस्थापित वापरकर्त्यासाठी नवीन खाते तयार करा.</translation>
<translation id="8446884382197647889">अधिक जाणून घ्या</translation>
<translation id="8447409163267621480">एकतर Ctrl किंवा Alt समाविष्‍ट करा</translation>
<translation id="8448729345478502352">तुमच्या स्क्रीनवर आयटम लहान किंवा मोठे करा</translation>
@@ -4937,6 +4951,7 @@
<translation id="8468750959626135884">Android फोनसह तुमचे <ph name="DEVICE_TYPE" /> अनलॉक करा.</translation>
<translation id="8470028084415844044">तुमच्या सर्व डिव्हाइसवर सर्व पासवर्ड मिळवण्यासाठी, सिंक सुरू करा.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" /> साठी सेव्ह केलेले पासवर्ड</translation>
+<translation id="8471635086304129332">हे कार्ड तुमच्या सर्व डिव्हाइसवर वापरण्यासाठी, ते तुमच्या Google खात्यामध्ये सेव्ह करा</translation>
<translation id="8472623782143987204">हार्डवेअर-बॅक्ड</translation>
<translation id="8473863474539038330">पत्ते आणि बरेच काही</translation>
<translation id="8475313423285172237">आपल्या संगणकावरील दुसऱ्या प्रोग्रामने Chrome च्या कार्य करण्याचा मार्ग बदलू शकणारा विस्तार जोडला.</translation>
@@ -5012,7 +5027,6 @@
<translation id="8598453409908276158">सँडबॉक्स न केलेले प्लग-इन ब्लॉक केले</translation>
<translation id="8601206103050338563">TLS WWW क्लायंट अॉथेंटिकेशन</translation>
<translation id="8602851771975208551">आपल्या संगणकावरील दुसऱ्या प्रोग्रामने Chrome च्या कार्य करण्याचा मार्ग बदलू शकणारा अ‍ॅप जोडला.</translation>
-<translation id="8604763363205185560">Chrome आणि त्याची सुरक्षितता सुधारण्यास मदत करा</translation>
<translation id="8605428685123651449">SQLite मेमरी</translation>
<translation id="8606726445206553943">तुमचे MIDI डिव्हाइसेस वापरा</translation>
<translation id="8609465669617005112">वर हलवा</translation>
@@ -5189,6 +5203,7 @@
<translation id="8846141544112579928">कीबोर्डचा शोध घेत आहे...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">तुम्ही तुमची डिव्हाइस कनेक्ट करता तेव्हा, तुम्ही सहमती दर्शवता की तुमचे Chromebook हे करू शकेल:</translation>
+<translation id="8850251000316748990">आणखी पहा...</translation>
<translation id="8859057652521303089">तुमची भाषा निवडा:</translation>
<translation id="8859174528519900719">सबफ्रेम: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel स्प्रेडशीट</translation>
@@ -5209,7 +5224,7 @@
<translation id="8883847527783433352">दुसऱ्या खात्याशी सिंक करा</translation>
<translation id="8885197664446363138">Smart Lock अनुपलब्ध आहे</translation>
<translation id="88870264962436283"><ph name="APP_NAME" /> सह टच आयडी वापरा</translation>
-<translation id="8888253246822647887">अपग्रेड करणे पूर्ण झाल्यावर तुमचे अ‍ॅप उघडेल. अपग्रेड करण्यास काही मिनिटे लागू शकतात.</translation>
+<translation id="8888253246822647887">अपग्रेड पूर्ण झाल्यावर तुमचे अ‍ॅप उघडेल. अपग्रेड करण्यास काही मिनिटे लागू शकतात.</translation>
<translation id="8888432776533519951">रंग:</translation>
<translation id="8890516388109605451">स्रोत</translation>
<translation id="8892168913673237979">सर्व सेट झाले!</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ms.xtb b/chromium/chrome/app/resources/generated_resources_ms.xtb
index 07ce8ba1124..05b793fd855 100644
--- a/chromium/chrome/app/resources/generated_resources_ms.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ms.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Dayakan tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Lihat di Gedung Web Chrome</translation>
-<translation id="1761588866118490543">Model suara</translation>
<translation id="176193854664720708">Penderia cap jari terletak di dalam butang kuasa. Sentuh dengan lembut menggunakan mana-mana jari.</translation>
<translation id="1763046204212875858">Cipta pintasan aplikasi</translation>
<translation id="1763108912552529023">Teruskan meneroka</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Hantar data penggunaan dan diagnostik. Pada masa ini, peranti ini menghantar data diagnostik dan penggunaan peranti serta apl kepada Google secara automatik. Data ini akan membantu peningkatan kestabilan sistem dan apl serta pelbagai lagi. Sesetengah data agregat juga akan membantu apl dan rakan kongsi Google, seperti pembangun Android. Tetapan ini dikuatkuasakan oleh pemilik. Jika tetapan Aktiviti Web &amp; Apl tambahan anda dihidupkan, data ini mungkin disimpan ke Akaun Google anda. <ph name="BEGIN_LINK1" />Ketahui Lebih Lanjut<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Arkib zip</translation>
<translation id="220858061631308971">Sila masukkan kod PIN ini pada "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Alih keluar perkongsian</translation>
+<translation id="2214018885812055163">Folder kongsi</translation>
<translation id="2214884991347062907">Kata laluan salah, cuba lagi</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 garisan tidak ditunjukkan&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> garisan tidak ditunjukkan&gt;}}</translation>
<translation id="2217501013957346740">Cipta nama -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Sijil Ditahan</translation>
<translation id="2501797496290880632">Taipkan pintasan</translation>
<translation id="2502441965851148920">Kemas kini automatik didayakan. Kemas kini manual dilumpuhkan oleh pentadbir anda.</translation>
+<translation id="2505127913256479918">Akaun di bawah seliaan ini akan dialih keluar tidak lama lagi</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Skrin #}other{Skrin #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> daripada <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Akaun Gedung Google Play</translation>
@@ -1046,7 +1048,7 @@
<translation id="2553340429761841190"><ph name="PRODUCT_NAME" /> tidak dapat menyambung ke <ph name="NETWORK_ID" />. Sila pilih rangkaian lain atau cuba semula.</translation>
<translation id="2553440850688409052">Sembunyikan Pemalam Ini</translation>
<translation id="2554553592469060349">Fail yang dipilih terlalu besar (saiz maks: 3mb).</translation>
-<translation id="255747371423522804">Tambahkan pada kumpulan yang sedia ada</translation>
+<translation id="255747371423522804">Tambahkan tab pada kumpulan yang sedia ada</translation>
<translation id="2558896001721082624">Sentiasa paparkan pilihan kebolehcapaian dalam menu sistem</translation>
<translation id="2562685439590298522">Dokumen</translation>
<translation id="2562743677925229011">Tidak log masuk ke <ph name="SHORT_PRODUCT_NAME" /></translation>
@@ -1376,6 +1378,7 @@
<translation id="304747341537320566">Enjin Pertuturan</translation>
<translation id="3053013834507634016">Penggunaan Penting Sijil</translation>
<translation id="3057861065630527966">Sandarkan foto dan video anda</translation>
+<translation id="3058498974290601450">Anda boleh mematikan penyegerakan pada bila-bila masa dalam tetapan</translation>
<translation id="3060379269883947824">Dayakan pilih untuk bercakap</translation>
<translation id="3061707000357573562">Perkhidmatan Tampung</translation>
<translation id="3065041951436100775">Maklum balas tab dibunuh.</translation>
@@ -1567,6 +1570,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> akan dipasang.</translation>
<translation id="3380365263193509176">Ralat tidak diketahui</translation>
<translation id="3382073616108123819">Op! Sistem gagal menentukan pengecam peranti untuk peranti ini.</translation>
+<translation id="3382086682569279540">Akaun yang anda urus akan dialih keluar tidak lama lagi</translation>
<translation id="3382200254148930874">Menghentikan pengawasan...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Pemisah</translation>
@@ -1747,8 +1751,8 @@
<translation id="3636096452488277381">Helo, <ph name="USER_GIVEN_NAME" /> .</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - berbaki <ph name="TIME" /></translation>
<translation id="3637682276779847508">Kad SIM anda akan dilumpuhkan secara kekal jika anda tidak dapat memasukkan Kunci Buka Kunci PIN yang betul.</translation>
-<translation id="363863692969456324">Betulkan ralat ejaan dengan semakan ejaan dipertingkat</translation>
<translation id="3640214691812501263">Tambahkan "<ph name="EXTENSION_NAME" />" untuk <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Ajar Assistant supaya mengecam suara anda</translation>
<translation id="3644896802912593514">Lebar</translation>
<translation id="3645372836428131288">Bergerak sedikit untuk menangkap bahagian lain cap jari.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> dikesan</translation>
@@ -2148,7 +2152,6 @@
<translation id="4244238649050961491">Dapatkan lagi apl stilus</translation>
<translation id="424546999567421758">Penggunaan tinggi cakera dikesan</translation>
<translation id="424726838611654458">Sentiasa buka dalam Adobe Reader</translation>
-<translation id="4247330672018280062">Teks yang anda taip dalam medan teks akan dihantar kepada Google</translation>
<translation id="4247901771970415646">Tidak dapat disegerakkan ke <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Menunggu sambungan rangkaian...</translation>
<translation id="4249373718504745892">Halaman ini telah disekat daripada mengakses kamera dan mikrofon anda.</translation>
@@ -2490,6 +2493,7 @@
<translation id="4821935166599369261">&amp;Pemprofilan Didayakan</translation>
<translation id="4823484602432206655">Baca dan tukar pengguna dan tetapan peranti</translation>
<translation id="4823651846660089135">Peranti dalam mod baca sahaja</translation>
+<translation id="4824958205181053313">Batalkan penyegerakan?</translation>
<translation id="4827675678516992122">Tidak dapat menyambung</translation>
<translation id="4828937774870308359">Australia</translation>
<translation id="4829768588131278040">Sediakan PIN</translation>
@@ -2872,6 +2876,7 @@
<translation id="5374359983950678924">Tukar gambar</translation>
<translation id="5376169624176189338">Klik untuk kembali, tahan untuk lihat sejarah</translation>
<translation id="5376931455988532197">Fail terlalu besar</translation>
+<translation id="5377594097385838788">Inkognito</translation>
<translation id="537813040452600081">Halaman yang anda lihat dalam tetingkap ini tidak akan dipaparkan dalam sejarah penyemak imbas dan halaman ini tidak akan meninggalkan kesan lain, seperti kuki, pada komputer selepas anda log keluar. Fail yang anda muat turun dan penanda halaman yang anda buat tidak akan disimpan.</translation>
<translation id="5379140238605961210">Teruskan menyekat akses mikrofon</translation>
<translation id="5379268888377976432">Buat Asal Pemadaman</translation>
@@ -2893,6 +2898,7 @@
<translation id="5414566801737831689">Baca ikon tapak web yang anda lawati</translation>
<translation id="5417312524372586921">Tema penyemak imbas</translation>
<translation id="5419294236999569767">Masa sistem</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Menentukan kejelasan teks dan imej</translation>
<translation id="5422221874247253874">Titik Akses</translation>
<translation id="5422781158178868512">Maaf, peranti storan luaran anda tidak dapat dikenali.</translation>
@@ -2913,6 +2919,7 @@
<translation id="5434065355175441495">PKCS #1 Penyulitan RSA</translation>
<translation id="5436492226391861498">Menunggu terowong proksi...</translation>
<translation id="5436510242972373446">Cari <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Sila simpan fail anda dan buat akaun baharu sekarang.</translation>
<translation id="5438224778284622050">Padam fail luar talian?</translation>
<translation id="544083962418256601">Buat pintasan...</translation>
<translation id="5442228125690314719">Ralat semasa membuat imej cakera. Sila cuba lagi.</translation>
@@ -3174,7 +3181,7 @@
<translation id="5816434091619127343">Perubahan pencetak yang diminta akan menjadikan pencetak tidak boleh digunakan.</translation>
<translation id="5817918615728894473">Gandingkan</translation>
<translation id="5821565227679781414">Cipta Pintasan</translation>
-<translation id="5825412242012995131">Hidupkan (Disyorkan)</translation>
+<translation id="5825412242012995131">Hidup (Disyorkan)</translation>
<translation id="5826507051599432481">Nama Biasa (CN)</translation>
<translation id="5827266244928330802">Safari</translation>
<translation id="5828633471261496623">Mencetak...</translation>
@@ -3286,6 +3293,8 @@
<translation id="5965661248935608907">Sambungan turut mengawal halaman yang ditunjukkan apabila anda mengklik butang Laman Utama atau membuat carian dari Kotak Omni.</translation>
<translation id="5971037678316050792">Kawal keadaan dan gandingan penyesuai Bluetooth</translation>
<translation id="5972017421290582825">Urus tetapan MIDI...</translation>
+<translation id="597235323114979258">Lihat lagi destinasi</translation>
+<translation id="5972666587303800813">Perkhidmatan Tanpa Pengendalian</translation>
<translation id="5972708806901999743">Alihkan ke bahagian atas</translation>
<translation id="5972826969634861500">Mula <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Peratusan Cas Bateri</translation>
@@ -3656,6 +3665,7 @@
<translation id="6527303717912515753">Kongsi</translation>
<translation id="6528513914570774834">Benarkan pengguna lain peranti ini untuk menggunakan rangkaian ini</translation>
<translation id="652948702951888897">Sejarah Chrome</translation>
+<translation id="6530186581263215931">Tetapan ini dikuatkuasakan oleh pentadbir anda</translation>
<translation id="653019979737152879">Menyegerakkan <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Simpan fail berbahaya</translation>
<translation id="6532101170117367231">Simpan ke Google Drive</translation>
@@ -3925,7 +3935,7 @@
<translation id="6957231940976260713">Nama perkhidmatan</translation>
<translation id="696203921837389374">Dayakan penyegerakan melalui data mudah alih</translation>
<translation id="6964390816189577014">Wira</translation>
-<translation id="6964760285928603117">Alih Keluar daripada Kumpulan</translation>
+<translation id="6964760285928603117">Alih Keluar Daripada Kumpulan</translation>
<translation id="6965382102122355670">OK</translation>
<translation id="6965648386495488594">Port</translation>
<translation id="6965978654500191972">Peranti</translation>
@@ -3974,7 +3984,6 @@
<translation id="7018275672629230621">Baca dan ubah sejarah penyemakan imbas anda</translation>
<translation id="7019805045859631636">Cepat</translation>
<translation id="7022562585984256452">Halaman utama anda telah ditetapkan.</translation>
-<translation id="702384510542929236">Menghantar beberapa maklumat sistem dan kandungan halaman kepada Google secara awanama</translation>
<translation id="7025190659207909717">Pengurusan perkhidmatan data mudah alih</translation>
<translation id="7027125358315426638">Nama pangkalan data:</translation>
<translation id="7029809446516969842">Kata laluan</translation>
@@ -4154,6 +4163,7 @@
<translation id="7289225569524511578">Buka apl kertas dinding</translation>
<translation id="7290242001003353852">Perkhidmatan log masuk yang dihoskan oleh <ph name="SAML_DOMAIN" /> ini sedang mengakses kamera anda.</translation>
<translation id="7290594223351252791">Sahkan pendaftaran</translation>
+<translation id="7292696521213967957">Maklumat untuk menyahpepijat Assistant</translation>
<translation id="7295662345261934369">Kongsi dengan orang lain</translation>
<translation id="729583233778673644">Benarkan penyulitan AES dan RC4. Penggunaan pilihan ini akan meningkatkan risiko anda, kerana sifer RC4 tidak selamat.</translation>
<translation id="7296774163727375165">Syarat <ph name="DOMAIN" /></translation>
@@ -4191,7 +4201,7 @@
<translation id="7348093485538360975">Papan kekunci pada skrin</translation>
<translation id="7352651011704765696">Kesilapan telah berlaku</translation>
<translation id="735361434055555355">Memasang Linux...</translation>
-<translation id="7353887511974462734">Tambahkan pada Kumpulan yang Sedia Ada</translation>
+<translation id="7353887511974462734">Tambahkan tab pada Kumpulan yang Sedia Ada</translation>
<translation id="735745346212279324">VPN diputuskan sambungan</translation>
<translation id="7359359531237882347">Menyalin <ph name="NUMBER_OF_ITEMS" /> item...</translation>
<translation id="7359588939039777303">Iklan disekat.</translation>
@@ -4254,7 +4264,6 @@
<translation id="7456847797759667638">Buka Lokasi...</translation>
<translation id="7461924472993315131">Pin</translation>
<translation id="7463006580194749499">Tambah orang</translation>
-<translation id="7464902436585505072">Model suara "Ok Google"</translation>
<translation id="7465778193084373987">URL Pembatalan Sijil Netscape</translation>
<translation id="7469894403370665791">Menyambung ke rangkaian ini secara automatik</translation>
<translation id="747114903913869239">Ralat: Tidak dapat menyahkod sambungan</translation>
@@ -4282,6 +4291,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> dan data yang berkaitan akan dialih keluar daripada peranti ini.</translation>
<translation id="7497215489070763236">Sijil CA pelayan</translation>
<translation id="7497981768003291373">Anda tiada log teks WebRTC yang dirakam baru-baru ini.</translation>
+<translation id="7502199377020483660">Untuk menggunakan kad ini pada semua peranti anda, simpan kad tersebut dalam akaun Google anda</translation>
<translation id="7502658306369382406">Alamat IPv6</translation>
<translation id="7503191893372251637">Jenis Sijil Netscape</translation>
<translation id="7503821294401948377">Tidak dapat memuatkan ikon '<ph name="ICON" />' untuk tindakan penyemak imbas.</translation>
@@ -4379,6 +4389,7 @@
<translation id="7663719505383602579">Penerima: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Peranti Bluetooth tidak disokong: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Tambah akaun</translation>
+<translation id="7667248760110172428">Storan luaran</translation>
<translation id="7671130400130574146">Gunakan bar dan sempadan tajuk sistem</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, dalam <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Hantar suara anda kepada Google untuk membolehkan pengimlakan dalam mana-mana medan teks.</translation>
@@ -4582,6 +4593,7 @@
<translation id="7930294771522048157">Kaedah pembayaran yang disimpan akan dipaparkan di sini</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> berkongsi skrin dan audio anda.</translation>
<translation id="7931318309563332511">Tidak diketahui</translation>
+<translation id="7932969338829957666">Folder kongsi tersedia dalam Linux di <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Nyahredam Tapak}other{Nyahredam Tapak}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> mahu memainkan kandungan yang dilindungi. Identiti peranti anda akan disahkan oleh Google.</translation>
<translation id="793531125873261495">Ralat memuat turun mesin maya. Sila cuba lagi.</translation>
@@ -4673,6 +4685,7 @@ Simpan fail kunci anda di tempat selamat. Anda akan memerlukannya untuk mencipta
<translation id="8049705080247101012">Google telah menandai <ph name="EXTENSION_NAME" /> sebagai berhasad dan pemasangan telah dihalang</translation>
<translation id="8049913480579063185">Nama Sambungan</translation>
<translation id="8050038245906040378">Menandatangani Kod Komersial Microsoft</translation>
+<translation id="8052887694493382350">Fail ini direka bentuk untuk PC yang menggunakan perisian Windows. Fail ini tidak serasi dengan peranti anda yang menjalankan OS Chrome. <ph name="BEGIN_LINK_HELP" />Ketahui Lebih Lanjut<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Fail PKCS #12</translation>
<translation id="8053390638574070785">Muatkan Semula Halaman Ini</translation>
<translation id="8054517699425078995">Jenis fail ini boleh menjejaskan peranti anda. Adakah anda hendak juga menyimpan <ph name="FILE_NAME" />?</translation>
@@ -4917,6 +4930,7 @@ perubahan ini berlaku, anda mungkin tidak mahukannya.</translation>
<translation id="8438566539970814960">Mempertingkatkan carian dan penyemakan imbas</translation>
<translation id="8439506636278576865">Tawaran untuk menterjemahkan halaman dalam bahasa ini</translation>
<translation id="8440630305826533614">Apl Linux</translation>
+<translation id="8443338615972234259">Sila buat akaun baharu untuk pengguna di bawah seliaan anda sekarang.</translation>
<translation id="8446884382197647889">Ketahui Lebih Lanjut</translation>
<translation id="8447409163267621480">Termasuk sama ada Ctrl atau Alt</translation>
<translation id="8448729345478502352">Kecilkan atau besarkan item pada skrin anda</translation>
@@ -4941,6 +4955,7 @@ perubahan ini berlaku, anda mungkin tidak mahukannya.</translation>
<translation id="8468750959626135884">Buka kunci <ph name="DEVICE_TYPE" /> anda dengan telefon Android anda.</translation>
<translation id="8470028084415844044">Hidupkan penyegerakan untuk mendapatkan semua kata laluan anda pada semua peranti anda.</translation>
<translation id="8470513973197838199">Kata laluan disimpan untuk <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Untuk menggunakan kad ini pada semua peranti anda, simpan kad ini dalam Akaun Google anda</translation>
<translation id="8472623782143987204">disokong perkakasan</translation>
<translation id="8473863474539038330">Alamat dan pelbagai lagi</translation>
<translation id="8475313423285172237">Program lain pada komputer anda menambah sambungan yang boleh mengubah cara Chrome berfungsi.</translation>
@@ -5016,7 +5031,6 @@ perubahan ini berlaku, anda mungkin tidak mahukannya.</translation>
<translation id="8598453409908276158">Pemalam tanpa kotak pasir disekat</translation>
<translation id="8601206103050338563">Pengesahan Klien TLS WWW</translation>
<translation id="8602851771975208551">Program lain pada komputer anda menambah apl yang boleh mengubah cara Chrome berfungsi.</translation>
-<translation id="8604763363205185560">Bantu memperbaik Chrome dan keselamatannya</translation>
<translation id="8605428685123651449">Memori SQLite</translation>
<translation id="8606726445206553943">Gunakan peranti MIDI anda</translation>
<translation id="8609465669617005112">Alihkan ke atas</translation>
@@ -5192,6 +5206,7 @@ perubahan ini berlaku, anda mungkin tidak mahukannya.</translation>
<translation id="8846141544112579928">Mencari papan kekunci...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Apabila anda menyambungkan peranti anda, anda bersetuju bahawa Chromebook anda boleh:</translation>
+<translation id="8850251000316748990">Lihat lagi...</translation>
<translation id="8859057652521303089">Pilih bahasa anda:</translation>
<translation id="8859174528519900719">Subbingkai: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Hamparan Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_nl.xtb b/chromium/chrome/app/resources/generated_resources_nl.xtb
index 4d9a3ddb5e3..d445cd343e6 100644
--- a/chromium/chrome/app/resources/generated_resources_nl.xtb
+++ b/chromium/chrome/app/resources/generated_resources_nl.xtb
@@ -382,7 +382,7 @@
<translation id="1564414980088536597">Deze afbeelding kan niet worden gebruikt. Kies een andere afbeelding.</translation>
<translation id="1566049601598938765">Website</translation>
<translation id="1567387640189251553">Er is een ander toetsenbord aangesloten sinds de laatste keer dat je je wachtwoord hebt ingevoerd. Mogelijk wordt geprobeerd om je toetsaanslagen te stelen.</translation>
-<translation id="1567750922576943685">Wanneer je je identiteit verifieert, blijven je persoonlijke gegevens beter beschermd</translation>
+<translation id="1567750922576943685">Wanneer je je identiteit verifieert, blijven je persoonsgegevens beter beschermd</translation>
<translation id="1567993339577891801">JavaScript-console</translation>
<translation id="1568323446248056064">Weergave-instellingen van apparaat openen</translation>
<translation id="1572266655485775982">Wifi inschakelen</translation>
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Thema inschakelen</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Bekijken in de Chrome Web Store</translation>
-<translation id="1761588866118490543">Spraakmodel</translation>
<translation id="176193854664720708">De vingerafdruksensor bevindt zich in de aan/uit-knop. Raak deze kort aan met een vinger.</translation>
<translation id="1763046204212875858">Applicatiesnelkoppelingen maken</translation>
<translation id="1763108912552529023">Blijf ontdekken</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Verzend gebruiks- en diagnostische gegevens. Dit apparaat verzendt momenteel automatisch diagnostische, apparaat- en app-gebruiksgegevens naar Google. Deze gegevens kunnen worden gebruikt om de systeem- en app-stabiliteit te verbeteren en andere optimalisaties mogelijk te maken. Daarnaast zijn bepaalde verzamelde gegevens nuttig voor Google-apps en -partners, zoals Android-ontwikkelaars. Deze instelling wordt afgedwongen door de eigenaar. Als je de instelling voor aanvullende Web- en app-activiteit hebt ingeschakeld, kunnen deze gegevens worden opgeslagen in je Google-account. <ph name="BEGIN_LINK1" />Meer informatie<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip-archiefbestand</translation>
<translation id="220858061631308971">Voer deze pincode in op '<ph name="DEVICE_NAME" />':</translation>
+<translation id="2213140827792212876">Delen verwijderen</translation>
+<translation id="2214018885812055163">Gedeelde mappen</translation>
<translation id="2214884991347062907">Wachtwoord onjuist. Probeer het opnieuw.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 regel niet weergegeven&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> regels niet weergegeven&gt;}}</translation>
<translation id="2217501013957346740">Maak een naam -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Certificaat gepauzeerd</translation>
<translation id="2501797496290880632">Typ een sneltoets</translation>
<translation id="2502441965851148920">Automatische updates zijn ingeschakeld. Handmatige updates zijn uitgeschakeld door je beheerder.</translation>
+<translation id="2505127913256479918">Dit account dat onder toezicht staat, wordt binnenkort verwijderd</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Scherm #}other{Scherm #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> van <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Store-account</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Spraakengines</translation>
<translation id="3053013834507634016">Sleutelgebruik voor certificaat</translation>
<translation id="3057861065630527966">Een back-up van je foto's en video's maken</translation>
+<translation id="3058498974290601450">Je kunt synchronisatie op elk gewenst moment inschakelen via de instellingen</translation>
<translation id="3060379269883947824">'Selecteer om uitgesproken te worden' inschakelen</translation>
<translation id="3061707000357573562">Patchservice</translation>
<translation id="3065041951436100775">Feedback over gesloten tabblad.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> wordt geïnstalleerd.</translation>
<translation id="3380365263193509176">Onbekende fout</translation>
<translation id="3382073616108123819">Het systeem kan de apparaat-ID's voor dit apparaat niet bepalen.</translation>
+<translation id="3382086682569279540">Het account dat je beheert, wordt binnenkort verwijderd</translation>
<translation id="3382200254148930874">Toezicht stoppen...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separator</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Hallo, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> resterend</translation>
<translation id="3637682276779847508">Je simkaart wordt permanent uitgeschakeld als je geen correcte pukcode kunt opgeven.</translation>
-<translation id="363863692969456324">Spelfouten corrigeren met een uitgebreide spellingcontrole</translation>
<translation id="3640214691812501263">'<ph name="EXTENSION_NAME" />' toevoegen voor <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Train de Assistent om je stem te herkennen</translation>
<translation id="3644896802912593514">Breedte</translation>
<translation id="3645372836428131288">Beweeg je vinger enigszins om een ander deel van de vingerafdruk vast te leggen.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> gedetecteerd</translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Meer stylus-apps zoeken</translation>
<translation id="424546999567421758">Intensief schijfgebruik gedetecteerd</translation>
<translation id="424726838611654458">Altijd in Adobe Reader openen</translation>
-<translation id="4247330672018280062">De tekst die je in tekstvelden typt, wordt verzonden naar Google</translation>
<translation id="4247901771970415646">Kan niet synchroniseren met <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Wachten op netwerkverbinding...</translation>
<translation id="4249373718504745892">Deze pagina heeft geen toegang tot je camera en microfoon.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Profiling ingeschakeld</translation>
<translation id="4823484602432206655">Gebruikers- en apparaatinstellingen lezen en wijzigen</translation>
<translation id="4823651846660089135">Apparaat is alleen-lezen</translation>
+<translation id="4824958205181053313">Synchronisatie annuleren?</translation>
<translation id="4827675678516992122">Kan geen verbinding maken</translation>
<translation id="4828937774870308359">Australisch</translation>
<translation id="4829768588131278040">Pincode instellen</translation>
@@ -2872,6 +2876,7 @@
<translation id="5374359983950678924">Afbeelding wijzigen</translation>
<translation id="5376169624176189338">Klik om terug te gaan, houd ingedrukt om de geschiedenis weer te geven</translation>
<translation id="5376931455988532197">Bestand is te groot</translation>
+<translation id="5377594097385838788">Incognito</translation>
<translation id="537813040452600081">Pagina's die je in dit venster bekijkt, worden niet in de browser- of zoekgeschiedenis vermeld en laten geen sporen (zoals cookies) achter op de computer nadat je bent uitgelogd. Bestanden die je downloadt en bladwijzers die je instelt, worden niet bewaard. Meer informatie over de gastmodus.</translation>
<translation id="5379140238605961210">Microfoontoegang blijven blokkeren</translation>
<translation id="5379268888377976432">Verwijderen ongedaan maken</translation>
@@ -2893,6 +2898,7 @@
<translation id="5414566801737831689">De pictogrammen lezen van websites die je bezoekt</translation>
<translation id="5417312524372586921">Browserthema's</translation>
<translation id="5419294236999569767">Systeemtijd</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Hiermee wordt de scherpte van tekst en afbeeldingen bepaald</translation>
<translation id="5422221874247253874">Toegangspunt</translation>
<translation id="5422781158178868512">Je externe opslagapparaat kan niet worden herkend.</translation>
@@ -2913,6 +2919,7 @@
<translation id="5434065355175441495">PKCS nr. 1 met RSA-encryptie</translation>
<translation id="5436492226391861498">Wachten op proxytunnel...</translation>
<translation id="5436510242972373446">Zoeken op <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Sla je nu bestanden op en maak een nieuw account.</translation>
<translation id="5438224778284622050">Offline bestanden verwijderen?</translation>
<translation id="544083962418256601">Snelle links maken...</translation>
<translation id="5442228125690314719">Fout bij maken van schijfimage. Probeer het opnieuw.</translation>
@@ -3286,6 +3293,8 @@
<translation id="5965661248935608907">Hiermee wordt ook gecontroleerd welke pagina wordt weergegeven wanneer je op de knop 'Homepage' klikt of vanuit de omnibox zoekt.</translation>
<translation id="5971037678316050792">Status van Bluetooth-adapter en Bluetooth-koppeling beheren</translation>
<translation id="5972017421290582825">MIDI-instellingen beheren...</translation>
+<translation id="597235323114979258">Meer bestemmingen weergeven</translation>
+<translation id="5972666587303800813">No-op Service</translation>
<translation id="5972708806901999743">Verplaatsen naar boven</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> starten</translation>
<translation id="5975792506968920132">Percentage acculading</translation>
@@ -3656,6 +3665,7 @@
<translation id="6527303717912515753">Delen</translation>
<translation id="6528513914570774834">Andere gebruikers van dit apparaat toestaan om dit netwerk te gebruiken</translation>
<translation id="652948702951888897">Chrome-geschiedenis</translation>
+<translation id="6530186581263215931">Deze instellingen worden door je beheerder afgedwongen</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> synchroniseren...</translation>
<translation id="6531282281159901044">Gevaarlijk bestand behouden</translation>
<translation id="6532101170117367231">Opslaan in Google Drive</translation>
@@ -3974,7 +3984,6 @@
<translation id="7018275672629230621">Je browsegeschiedenis lezen en wijzigen</translation>
<translation id="7019805045859631636">Snel</translation>
<translation id="7022562585984256452">Je homepage is ingesteld.</translation>
-<translation id="702384510542929236">Hiermee worden bepaalde systeemgegevens en paginacontent anoniem naar Google verzonden</translation>
<translation id="7025190659207909717">Beheer van mobiele netwerken</translation>
<translation id="7027125358315426638">Naam database:</translation>
<translation id="7029809446516969842">Wachtwoorden</translation>
@@ -4154,6 +4163,7 @@
<translation id="7289225569524511578">De achtergrond-app openen</translation>
<translation id="7290242001003353852">Deze inlogservice wordt gehost door <ph name="SAML_DOMAIN" /> en heeft toegang tot je camera.</translation>
<translation id="7290594223351252791">Registratie bevestigen</translation>
+<translation id="7292696521213967957">Foutopsporingsgegevens voor de Assistent</translation>
<translation id="7295662345261934369">Delen met anderen</translation>
<translation id="729583233778673644">AES- en RC4-versleuteling toestaan. Als je deze optie gebruikt, loop je meer risico, aangezien RC4-codering onbeveiligd is.</translation>
<translation id="7296774163727375165">Voorwaarden voor <ph name="DOMAIN" /></translation>
@@ -4254,7 +4264,6 @@
<translation id="7456847797759667638">Open locatie...</translation>
<translation id="7461924472993315131">Vastzetten</translation>
<translation id="7463006580194749499">Persoon toevoegen</translation>
-<translation id="7464902436585505072">'Oké Google'-spraakmodel</translation>
<translation id="7465778193084373987">URL voor intrekken van Netscape-certificaat</translation>
<translation id="7469894403370665791">Automatisch verbinding maken met dit netwerk</translation>
<translation id="747114903913869239">Fout: kan extensie niet decoderen</translation>
@@ -4275,13 +4284,14 @@
<translation id="7489355918927585587">{COUNT,plural, =0{Alles &amp;openen}=1{Bladwijzer &amp;openen}other{Alles (#) &amp;openen}}</translation>
<translation id="749028671485790643">Persoon <ph name="VALUE" /></translation>
<translation id="7490813197707563893">MAC-adres</translation>
-<translation id="7493386493263658176">De extensie <ph name="EXTENSION_NAME" /> kan alle tekst verzamelen die je typt, waaronder persoonlijke gegevens zoals wachtwoorden en creditcardnummers. Wil je deze extensie gebruiken?</translation>
+<translation id="7493386493263658176">De extensie <ph name="EXTENSION_NAME" /> kan alle tekst verzamelen die je typt, waaronder persoonsgegevens zoals wachtwoorden en creditcardnummers. Wil je deze extensie gebruiken?</translation>
<translation id="7494065396242762445">Windows-instellingen openen</translation>
<translation id="7494694779888133066"><ph name="WIDTH" /> x <ph name="HEIGHT" /></translation>
<translation id="7495778526395737099">Je oude wachtwoord vergeten?</translation>
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> en de gegevens die aan deze app gekoppeld zijn, worden verwijderd van dit apparaat.</translation>
<translation id="7497215489070763236">CA-certificaat van server</translation>
<translation id="7497981768003291373">Je hebt geen onlangs vastgelegde WebRTC-tekstlogboeken.</translation>
+<translation id="7502199377020483660">Als je deze kaarten op al je apparaten wilt gebruiken, sla je ze op in je Google-account</translation>
<translation id="7502658306369382406">IPv6-adres</translation>
<translation id="7503191893372251637">Type Netscape-certificaat</translation>
<translation id="7503821294401948377">Kan pictogram '<ph name="ICON" />' voor browseractie niet laden.</translation>
@@ -4379,6 +4389,7 @@
<translation id="7663719505383602579">Ontvanger: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Niet-ondersteund Bluetooth-apparaat: '<ph name="DEVICE_NAME" />'.</translation>
<translation id="7665369617277396874">Account toevoegen</translation>
+<translation id="7667248760110172428">Externe opslag</translation>
<translation id="7671130400130574146">Titelbalk en kaders van systeem gebruiken</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, in <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Verzend je stem naar Google zodat je kunt dicteren in tekstvelden.</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">Opgeslagen betaalmethoden worden hier weergegeven</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> deelt je scherm en audio.</translation>
<translation id="7931318309563332511">Onbekend</translation>
+<translation id="7932969338829957666">Gedeelde mappen zijn beschikbaar in Linux in <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Dempen site opheffen}other{Dempen sites opheffen}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> wil beveiligde content afspelen. De identiteit van je apparaat wordt geverifieerd door Google.</translation>
<translation id="793531125873261495">Fout bij downloaden van virtuele machine. Probeer het opnieuw.</translation>
@@ -4672,6 +4684,7 @@ Bewaar je sleutelbestand op een veilige plaats. Je hebt het bestand nodig om nie
<translation id="8049705080247101012">Google heeft <ph name="EXTENSION_NAME" /> als schadelijk gemarkeerd en de installatie is geblokkeerd</translation>
<translation id="8049913480579063185">Extensienaam</translation>
<translation id="8050038245906040378">Commerciële handtekening bij programmacode van Microsoft</translation>
+<translation id="8052887694493382350">Dit bestand is bedoeld voor een pc met Windows-software. Het is niet geschikt voor jouw apparaat, waarop Chrome OS wordt uitgevoerd. <ph name="BEGIN_LINK_HELP" />Meer informatie<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Bestanden van het type PKCS #12</translation>
<translation id="8053390638574070785">Laad pagina opnieuw</translation>
<translation id="8054517699425078995">Dit type bestand kan schade toebrengen aan je apparaat. Wil je <ph name="FILE_NAME" /> toch blijven gebruiken?</translation>
@@ -4915,6 +4928,7 @@ Bewaar je sleutelbestand op een veilige plaats. Je hebt het bestand nodig om nie
<translation id="8438566539970814960">Zoekopdrachten en browsefunctionaliteit verbeteren</translation>
<translation id="8439506636278576865">Aanbieden pagina's te vertalen in deze taal</translation>
<translation id="8440630305826533614">Linux-apps</translation>
+<translation id="8443338615972234259">Maak nu een nieuw account voor je gebruiker met beperkte rechten.</translation>
<translation id="8446884382197647889">Meer informatie</translation>
<translation id="8447409163267621480">Neem Ctrl of Alt op</translation>
<translation id="8448729345478502352">Items op het scherm kleiner of groter maken</translation>
@@ -4939,6 +4953,7 @@ Bewaar je sleutelbestand op een veilige plaats. Je hebt het bestand nodig om nie
<translation id="8468750959626135884">Ontgrendel je <ph name="DEVICE_TYPE" /> met je Android-telefoon.</translation>
<translation id="8470028084415844044">Schakel synchronisatie in om al je wachtwoorden op al je apparaten beschikbaar te maken.</translation>
<translation id="8470513973197838199">Opgeslagen wachtwoorden voor <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Als je deze kaart op al je apparaten wilt gebruiken, sla je deze op in je Google-account</translation>
<translation id="8472623782143987204">hardware-ondersteund</translation>
<translation id="8473863474539038330">Adressen en meer</translation>
<translation id="8475313423285172237">Een ander programma op je computer heeft een extensie toegevoegd die de manier waarop Chrome werkt kan wijzigen.</translation>
@@ -5014,7 +5029,6 @@ Bewaar je sleutelbestand op een veilige plaats. Je hebt het bestand nodig om nie
<translation id="8598453409908276158">Plug-in zonder sandbox geblokkeerd</translation>
<translation id="8601206103050338563">TLS WWW-clientverificatie</translation>
<translation id="8602851771975208551">Een ander programma op je computer heeft een app toegevoegd die de manier waarop Chrome werkt kan wijzigen.</translation>
-<translation id="8604763363205185560">Help Chrome en de beveiliging daarvan te verbeteren</translation>
<translation id="8605428685123651449">SQLite-geheugen</translation>
<translation id="8606726445206553943">Je MIDI-apparaten gebruiken</translation>
<translation id="8609465669617005112">Omhoog</translation>
@@ -5191,6 +5205,7 @@ Bewaar je sleutelbestand op een veilige plaats. Je hebt het bestand nodig om nie
<translation id="8846141544112579928">Toetsenbord zoeken...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Als je je apparaten koppelt, stem je ermee in dat je Chromebook het volgende kan doen:</translation>
+<translation id="8850251000316748990">Meer weergeven…</translation>
<translation id="8859057652521303089">Selecteer je taal:</translation>
<translation id="8859174528519900719">Subframe: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel-spreadsheet</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_no.xtb b/chromium/chrome/app/resources/generated_resources_no.xtb
index b8710db9641..923322bb12c 100644
--- a/chromium/chrome/app/resources/generated_resources_no.xtb
+++ b/chromium/chrome/app/resources/generated_resources_no.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">Aktiver temaet</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Se i Chrome Nettmarked</translation>
-<translation id="1761588866118490543">Stemmemodell</translation>
<translation id="176193854664720708">Fingeravtrykkssensoren er i av/på-knappen. Trykk på den forsiktig.</translation>
<translation id="1763046204212875858">Opprett snarveier</translation>
<translation id="1763108912552529023">Fortsett å utforske</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">Send bruks- og diagnostikkdata. Denne enheten sender for øyeblikket diagnostikk-, enhets- og appbruksdata til Google automatisk. Dette bidrar til å gjøre systemet og appene bedre og mer stabile. Noen aggregerte data hjelper også Google-apper og -partnere, for eksempel Android-utviklere. Denne innstillingen håndheves av eieren. Hvis du har slått på innstillingen for annen nett- og appaktivitet, kan disse dataene bli lagret i Google-kontoen din. <ph name="BEGIN_LINK1" />Finn ut mer<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">.zip-arkiv</translation>
<translation id="220858061631308971">Skriv inn denne PIN-koden på «<ph name="DEVICE_NAME" />»:</translation>
+<translation id="2213140827792212876">Slutt å dele</translation>
+<translation id="2214018885812055163">Delte mapper</translation>
<translation id="2214884991347062907">Feil passord. Prøv på nytt</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 linje vises ikke&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> linjer vises ikke&gt;}}</translation>
<translation id="2217501013957346740">Lag et navn –</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">Sertifikat på vent</translation>
<translation id="2501797496290880632">Skriv inn en snarvei</translation>
<translation id="2502441965851148920">Automatiske oppdateringer er slått på. Administratoren din har slått av manuelle oppdateringer.</translation>
+<translation id="2505127913256479918">Denne administrerte kontoen fjernes snart</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Skjerm #}other{Skjerm #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> av <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Butikk-konto</translation>
@@ -1371,6 +1373,7 @@
<translation id="304747341537320566">Talemotorer</translation>
<translation id="3053013834507634016">Bruk av sertifikatnøkkel</translation>
<translation id="3057861065630527966">Sikkerhetskopiér bildene og videoene dine</translation>
+<translation id="3058498974290601450">Du kan når som helst slå på synkronisering i innstillingene</translation>
<translation id="3060379269883947824">Slå på Tekstopplesing</translation>
<translation id="3061707000357573562">Feilrettingstjeneste</translation>
<translation id="3065041951436100775">Tilbakemelding for lukket fane.</translation>
@@ -1561,6 +1564,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> vil bli installert.</translation>
<translation id="3380365263193509176">Ukjent feil</translation>
<translation id="3382073616108123819">Beklager. Systemet kunne ikke fastslå enhetsidentifikatorer for denne enheten.</translation>
+<translation id="3382086682569279540">Kontoen du administrerer, fjernes snart</translation>
<translation id="3382200254148930874">Avslutter tilsynet …</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Skillelinje</translation>
@@ -1741,8 +1745,8 @@
<translation id="3636096452488277381">Heisann, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> % – <ph name="TIME" /> til batteriet er tomt</translation>
<translation id="3637682276779847508">SIM-kortet ditt blir deaktivert permanent hvis du ikke angir riktig PUK-kode.</translation>
-<translation id="363863692969456324">Fiks stavefeil med forbedret stavekontroll</translation>
<translation id="3640214691812501263">Vil du legge til «<ph name="EXTENSION_NAME" />» for <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Lær assistenten å gjenkjenne stemmen din</translation>
<translation id="3644896802912593514">Bredde</translation>
<translation id="3645372836428131288">Flytt litt på fingeren for å registrere en annen del av fingeravtrykket.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> oppdaget</translation>
@@ -2140,7 +2144,6 @@
<translation id="4244238649050961491">Finn flere pekepennapper</translation>
<translation id="424546999567421758">Høyt forbruk av lagringsplass oppdaget</translation>
<translation id="424726838611654458">Åpne alltid i Adobe Reader</translation>
-<translation id="4247330672018280062">Teksten du skriver inn i tekstfelt, sendes til Google</translation>
<translation id="4247901771970415646">Kan ikke synkronisere med <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Venter på nettverkstilkobling …</translation>
<translation id="4249373718504745892">Kameraet og mikrofonen er blokkert for denne siden.</translation>
@@ -2482,6 +2485,7 @@
<translation id="4821935166599369261">&amp;Profilering aktivert</translation>
<translation id="4823484602432206655">lese og endre bruker- og enhetsinnstillinger</translation>
<translation id="4823651846660089135">Enheten er skrivebeskyttet</translation>
+<translation id="4824958205181053313">Vil du avbryte synkroniseringen?</translation>
<translation id="4827675678516992122">Kan ikke koble til</translation>
<translation id="4828937774870308359">Australsk</translation>
<translation id="4829768588131278040">Konfigurer en PIN-kode</translation>
@@ -2864,6 +2868,7 @@
<translation id="5374359983950678924">Endre bilde</translation>
<translation id="5376169624176189338">Klikk for å gå tilbake – hold for å se logg</translation>
<translation id="5376931455988532197">Filen er for stor</translation>
+<translation id="5377594097385838788">Inkognito</translation>
<translation id="537813040452600081">Sider i dette vinduet vises ikke i nettleserloggen, og de legger ikke igjen andre spor (f.eks. informasjonskapsler) på datamaskinen etter at du har logget av. Filer du laster ned og bokmerker du oppretter, lagres ikke.</translation>
<translation id="5379140238605961210">Fortsett blokkering av mikrofontilgang</translation>
<translation id="5379268888377976432">Angre sletting</translation>
@@ -2885,6 +2890,7 @@
<translation id="5414566801737831689">lese ikonene på nettstedene du besøker</translation>
<translation id="5417312524372586921">Nettlesertemaer</translation>
<translation id="5419294236999569767">Systemtid</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Bestemmer skarpheten på tekst og bilder</translation>
<translation id="5422221874247253874">Tilgangspunkt</translation>
<translation id="5422781158178868512">Beklager, men den eksterne lagringsenheten din ble ikke gjenkjent.</translation>
@@ -2905,6 +2911,7 @@
<translation id="5434065355175441495">PKCS #1 RSA-kryptering</translation>
<translation id="5436492226391861498">Venter på mellomtjenertunnel</translation>
<translation id="5436510242972373446">Søk på <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Lagre filene dine, og opprett en ny konto nå.</translation>
<translation id="5438224778284622050">Vil du slette filer som er lagret lokalt?</translation>
<translation id="544083962418256601">Opprett snarveier</translation>
<translation id="5442228125690314719">Feil ved oppretting av diskavbildning. Prøv på nytt.</translation>
@@ -3278,6 +3285,8 @@
<translation id="5965661248935608907">Den styrer også hvilken side som vises når du klikker på Startside-knappen eller søker fra multifunksjonsfeltet.</translation>
<translation id="5971037678316050792">kontrollere statusen og tilkoblingen for Bluetooth-adapteren</translation>
<translation id="5972017421290582825">Administrer MIDI-innstillinger</translation>
+<translation id="597235323114979258">Se flere destinasjoner</translation>
+<translation id="5972666587303800813">Eksperimenttjeneste</translation>
<translation id="5972708806901999743">Flytt øverst</translation>
<translation id="5972826969634861500">Start <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Ladingsprosent for batteri</translation>
@@ -3648,6 +3657,7 @@
<translation id="6527303717912515753">Del</translation>
<translation id="6528513914570774834">La andre brukere av denne enheten bruke dette nettverket</translation>
<translation id="652948702951888897">Chrome-logg</translation>
+<translation id="6530186581263215931">Disse innstillingene håndheves av administratoren din</translation>
<translation id="653019979737152879">Synkroniserer <ph name="FILE_NAME" /> …</translation>
<translation id="6531282281159901044">Behold den farlige filen</translation>
<translation id="6532101170117367231">Lagre i Google Disk</translation>
@@ -3966,7 +3976,6 @@
<translation id="7018275672629230621">lese og endre leserloggen din</translation>
<translation id="7019805045859631636">Høy</translation>
<translation id="7022562585984256452">Startsiden din er angitt.</translation>
-<translation id="702384510542929236">Sender noe systeminformasjon og sideinnhold til Google anonymt</translation>
<translation id="7025190659207909717">Administrering av tjenester for mobildata</translation>
<translation id="7027125358315426638">Databasenavn:</translation>
<translation id="7029809446516969842">Passord</translation>
@@ -4146,6 +4155,7 @@
<translation id="7289225569524511578">Åpne bakgrunnsappen</translation>
<translation id="7290242001003353852">Denne påloggingstjenesten, som driftes av <ph name="SAML_DOMAIN" />, har tilgang til kameraet ditt</translation>
<translation id="7290594223351252791">Bekreft registrering</translation>
+<translation id="7292696521213967957">Feilsøkingsinfo for assistenten</translation>
<translation id="7295662345261934369">Del med andre</translation>
<translation id="729583233778673644">Tillat AES- og RC4-kryptering. Hvis du bruker dette alternativet, øker risikoen, ettersom RC4-chiffere ikke er sikre.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" />-vilkår</translation>
@@ -4246,7 +4256,6 @@
<translation id="7456847797759667638">Åpne sted</translation>
<translation id="7461924472993315131">Fest</translation>
<translation id="7463006580194749499">Legg til person</translation>
-<translation id="7464902436585505072">Stemmemodell for «Ok Google»</translation>
<translation id="7465778193084373987">Nettadresse for tilbakekalling av Netscape-sertifikat</translation>
<translation id="7469894403370665791">Koble til dette nettverket automatisk</translation>
<translation id="747114903913869239">Feil: Kan ikke avkode etternavnet</translation>
@@ -4274,6 +4283,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> og alle tilknyttede data blir fjernet fra denne enheten.</translation>
<translation id="7497215489070763236">Tjenerens CA-sertifikat</translation>
<translation id="7497981768003291373">Du har ingen nylig lagrede WebRTC-tekstlogger.</translation>
+<translation id="7502199377020483660">For å bruke disse kortene på alle enhetene dine, lagre dem i Google-kontoen din</translation>
<translation id="7502658306369382406">IPv6-adresse</translation>
<translation id="7503191893372251637">Netscape sertifikattype</translation>
<translation id="7503821294401948377">Kan ikke laste inn ikonet «<ph name="ICON" />» for nettleserhandling.</translation>
@@ -4369,6 +4379,7 @@
<translation id="7663719505383602579">Mottaker: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Ustøttet Bluetooth-enhet: <ph name="DEVICE_NAME" />.</translation>
<translation id="7665369617277396874">Legg til konto</translation>
+<translation id="7667248760110172428">Ekstern lagring</translation>
<translation id="7671130400130574146">Bruk systemets tittellinje og kantlinjer</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> på <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Send stemmen din til Google for å tillate diktat til hvilket som helst tekstfelt.</translation>
@@ -4572,6 +4583,7 @@
<translation id="7930294771522048157">Lagrede betalingsmåter vises her</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> deler lyden og skjermen din.</translation>
<translation id="7931318309563332511">Ukjent</translation>
+<translation id="7932969338829957666">Delte mapper er tilgjengelige i Linux i <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Slå på lyden for nettstedet}other{Slå på lyden for nettstedene}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> vil spille av beskyttet innhold. Identiteten til enheten din blir bekreftet av Google.</translation>
<translation id="793531125873261495">Feil ved nedlasting av den virtuelle maskinen. Prøv på nytt.</translation>
@@ -4663,6 +4675,7 @@ Oppbevar nøkkelfilen på et trygt sted. Du får bruk for den når du skal oppre
<translation id="8049705080247101012">Google har merket <ph name="EXTENSION_NAME" /> som skadelig, og installasjonen har blitt avbrutt</translation>
<translation id="8049913480579063185">Navn på utvidelse</translation>
<translation id="8050038245906040378">Microsoft-signering med kommersiell kode</translation>
+<translation id="8052887694493382350">Denne filen er laget for datamaskiner som kjører Windows. Den er ikke kompatibel med enheten din, som kjører Chrome OS. <ph name="BEGIN_LINK_HELP" />Finn ut mer<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Filer for PKCS #12</translation>
<translation id="8053390638574070785">Last inn denne siden på nytt</translation>
<translation id="8054517699425078995">Denne filtypen kan skade enheten din. Vil du beholde <ph name="FILE_NAME" /> likevel?</translation>
@@ -4906,6 +4919,7 @@ Jeg tror ikke det er nødvendig å blokkere dette nettstedet.</translation>
<translation id="8438566539970814960">Gjør søking og surfing bedre</translation>
<translation id="8439506636278576865">Tilby å oversette nettsider på dette språket</translation>
<translation id="8440630305826533614">Linux-apper</translation>
+<translation id="8443338615972234259">Opprett en ny konto for den administrerte brukeren din nå.</translation>
<translation id="8446884382197647889">Les mer</translation>
<translation id="8447409163267621480">Inkluder enten Ctrl eller Alt</translation>
<translation id="8448729345478502352">Gjør elementer på skjermen mindre eller større.</translation>
@@ -4930,6 +4944,7 @@ Jeg tror ikke det er nødvendig å blokkere dette nettstedet.</translation>
<translation id="8468750959626135884">Lås opp <ph name="DEVICE_TYPE" /> med Android-telefonen din.</translation>
<translation id="8470028084415844044">For å få alle passordene dine på alle enhetene du bruker, slå på synkronisering.</translation>
<translation id="8470513973197838199">Lagrede passord for <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">For å bruke dette kortet på alle enhetene dine, lagre det i Google-kontoen din</translation>
<translation id="8472623782143987204">maskinvarestøttet</translation>
<translation id="8473863474539038330">Adresser med mer</translation>
<translation id="8475313423285172237">Et annet program på datamaskinen la til en utvidelse som kan endre måten Chrome fungerer på.</translation>
@@ -5005,7 +5020,6 @@ Jeg tror ikke det er nødvendig å blokkere dette nettstedet.</translation>
<translation id="8598453409908276158">Programtillegg uten prosessisolering er blokkert</translation>
<translation id="8601206103050338563">Autentisering av klienten TLS WWW</translation>
<translation id="8602851771975208551">Et annet program på datamaskinen la til en app som kan endre måten Chrome fungerer på.</translation>
-<translation id="8604763363205185560">Hjelp til med å gjøre Chrome bedre og sikrere</translation>
<translation id="8605428685123651449">SQLite-minne</translation>
<translation id="8606726445206553943">bruke MIDI-enhetene dine</translation>
<translation id="8609465669617005112">Flytt opp</translation>
@@ -5181,6 +5195,7 @@ Jeg tror ikke det er nødvendig å blokkere dette nettstedet.</translation>
<translation id="8846141544112579928">Søker etter tastatur …</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Når du kobler sammen enhetene, samtykker du til at Chromebook kan:</translation>
+<translation id="8850251000316748990">Se flere …</translation>
<translation id="8859057652521303089">Velg språk:</translation>
<translation id="8859174528519900719">Underramme: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel-regneark</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_pl.xtb b/chromium/chrome/app/resources/generated_resources_pl.xtb
index 533b96650b5..e475b25d10d 100644
--- a/chromium/chrome/app/resources/generated_resources_pl.xtb
+++ b/chromium/chrome/app/resources/generated_resources_pl.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Włącz motyw</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Wyświetl w Chrome Web Store</translation>
-<translation id="1761588866118490543">Model głosu</translation>
<translation id="176193854664720708">Czytnik linii papilarnych znajduje się na przycisku zasilania. Przyłóż do niego dowolny palec.</translation>
<translation id="1763046204212875858">Utwórz skróty do aplikacji</translation>
<translation id="1763108912552529023">Odkrywaj dalej</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Wysyłaj dane diagnostyczne oraz informacje o użyciu. To urządzenie automatycznie wysyła do Google dane diagnostyczne oraz informacje o używaniu urządzenia i aplikacji. Dzięki temu będziemy mogli poprawić stabilność systemu i aplikacji oraz wprowadzić inne ulepszenia. Niektóre dane zbiorcze pomogą nam też udoskonalić aplikacje Google lub zostaną wykorzystane przez naszych partnerów, na przykład deweloperów aplikacji na Androida. To ustawienie jest wymuszone przez właściciela. Jeśli włączysz ustawienie Dodatkowa aktywność w internecie i aplikacjach, te dane mogą być zapisywane na Twoim koncie Google. <ph name="BEGIN_LINK1" />Więcej informacji<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Archiwum ZIP</translation>
<translation id="220858061631308971">Wpisz ten kod PIN na urządzeniu „<ph name="DEVICE_NAME" />”:</translation>
+<translation id="2213140827792212876">Usuń udostępnianie</translation>
+<translation id="2214018885812055163">Foldery udostępnione</translation>
<translation id="2214884991347062907">Nieprawidłowe hasło – spróbuj ponownie</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 wiersz jest niewidoczny&gt;}few{&lt;<ph name="NUMBER_OF_LINES" /> wiersze są niewidoczne&gt;}many{&lt;<ph name="NUMBER_OF_LINES" /> wierszy jest niewidocznych&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> wiersza jest niewidoczne&gt;}}</translation>
<translation id="2217501013957346740">Utwórz nazwę –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Certyfikat wstrzymany</translation>
<translation id="2501797496290880632">Wpisz skrót</translation>
<translation id="2502441965851148920">Automatyczne aktualizacje są włączone. Ręczne aktualizacje zostały wyłączone przez administratora.</translation>
+<translation id="2505127913256479918">To konto nadzorowane zostanie wkrótce usunięte</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Ekran #}few{Ekran #}many{Ekran #}other{Ekran #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> z <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Konto w Sklepie Google Play</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Mechanizmy syntezy mowy</translation>
<translation id="3053013834507634016">Użycie klucza certyfikatu</translation>
<translation id="3057861065630527966">Utwórz kopię zapasową zdjęć i filmów</translation>
+<translation id="3058498974290601450">W każdej chwili możesz włączyć synchronizację w ustawieniach</translation>
<translation id="3060379269883947824">Włącz funkcję Przeczytaj na głos</translation>
<translation id="3061707000357573562">Zastosowanie poprawki do usługi</translation>
<translation id="3065041951436100775">Informacje o zakończeniu działania karty.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015">Aplikacja <ph name="PRODUCT_NAME" /> zostanie zainstalowana.</translation>
<translation id="3380365263193509176">Nieznany błąd</translation>
<translation id="3382073616108123819">Ups. System nie może określić identyfikatorów tego urządzenia.</translation>
+<translation id="3382086682569279540">Konto, którym zarządzasz, zostanie wkrótce usunięte</translation>
<translation id="3382200254148930874">Zatrzymuję nadzorowanie…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separator</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Cześć <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – pozostało <ph name="TIME" /></translation>
<translation id="3637682276779847508">Jeśli nie wpiszesz prawidłowego klucza odblokowującego kod PIN, karta SIM zostanie trwale wyłączona.</translation>
-<translation id="363863692969456324">Poprawiaj błędy w tekście przy użyciu zaawansowanego sprawdzania pisowni</translation>
<translation id="3640214691812501263">Dodać „<ph name="EXTENSION_NAME" />” dla: <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Naucz Asystenta rozpoznawać Twój głos</translation>
<translation id="3644896802912593514">Szerokość</translation>
<translation id="3645372836428131288">Przesuń odrobinę, by zeskanować inną część odcisku palca.</translation>
<translation id="3648348069317717750">Wykryto <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Znajdź więcej aplikacji dla rysika</translation>
<translation id="424546999567421758">Wykryto wysokie użycie dysku</translation>
<translation id="424726838611654458">Zawsze otwieraj w Adobe Reader</translation>
-<translation id="4247330672018280062">Tekst wpisywany w polach tekstowych będzie wysyłany do Google</translation>
<translation id="4247901771970415646">Nie można zsynchronizować z <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Czekam na połączenie z siecią...</translation>
<translation id="4249373718504745892">Ta strona ma zablokowany dostęp do kamery i mikrofonu.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Profilowanie włączone</translation>
<translation id="4823484602432206655">Odczyt i zmiana ustawień użytkownika oraz urządzenia</translation>
<translation id="4823651846660089135">Urządzenie tylko do odczytu</translation>
+<translation id="4824958205181053313">Anulować synchronizację?</translation>
<translation id="4827675678516992122">Nie udało się połączyć</translation>
<translation id="4828937774870308359">Australijskie</translation>
<translation id="4829768588131278040">Ustaw kod PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Zmień zdjęcie</translation>
<translation id="5376169624176189338">Kliknij, aby przejść wstecz. Przytrzymaj, aby wyświetlić historię</translation>
<translation id="5376931455988532197">Plik jest za duży</translation>
+<translation id="5377594097385838788">Incognito</translation>
<translation id="537813040452600081">Strony wyświetlane w tym oknie nie pojawią się w historii przeglądarki. Po wylogowaniu się nie zostanie po nich na komputerze żaden ślad (np. w postaci plików cookie). Nie zostaną też zachowane pobrane pliki ani utworzone zakładki.</translation>
<translation id="5379140238605961210">Nadal blokuj dostęp do mikrofonu</translation>
<translation id="5379268888377976432">Cofnij usunięcie</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Odczyt ikon otwieranych stron</translation>
<translation id="5417312524372586921">Motywy przeglądarki</translation>
<translation id="5419294236999569767">Czas systemowy</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Wpływa na ostrość tekstu i grafiki</translation>
<translation id="5422221874247253874">Punkt dostępu</translation>
<translation id="5422781158178868512">Nie można rozpoznać urządzenia zewnętrznej pamięci masowej.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1, szyfrowanie RSA</translation>
<translation id="5436492226391861498">Czekam na tunel serwera proxy...</translation>
<translation id="5436510242972373446">Wyszukiwanie w <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Zapisz teraz pliki i załóż nowe konto.</translation>
<translation id="5438224778284622050">Usunąć pliki offline?</translation>
<translation id="544083962418256601">Utwórz skróty...</translation>
<translation id="5442228125690314719">Błąd podczas tworzenia obrazu dysku. Spróbuj ponownie.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">Kontroluje także to, jaka strona wyświetla się po kliknięciu przycisku strony głównej lub wyszukiwaniu w omniboksie.</translation>
<translation id="5971037678316050792">Kontrolowanie stanu adaptera Bluetooth i parowania</translation>
<translation id="5972017421290582825">Zarządzaj ustawieniami MIDI...</translation>
+<translation id="597235323114979258">Zobacz więcej lokalizacji docelowych</translation>
+<translation id="5972666587303800813">Usługa w środowisku bezobsługowym</translation>
<translation id="5972708806901999743">Przenieś na początek</translation>
<translation id="5972826969634861500">Uruchom przeglądarkę <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Procent naładowania akumulatora</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">Udostępnij</translation>
<translation id="6528513914570774834">Zezwól innym użytkownikom tego urządzenia na używanie tej sieci</translation>
<translation id="652948702951888897">Historia Chrome</translation>
+<translation id="6530186581263215931">Te ustawienia są wymuszone przez administratora</translation>
<translation id="653019979737152879">Synchronizuję <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Zachowaj niebezpieczny plik</translation>
<translation id="6532101170117367231">Zapisz na Dysku Google</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">Odczyt i zmiana historii przeglądania</translation>
<translation id="7019805045859631636">Szybko</translation>
<translation id="7022562585984256452">Strona główna została ustawiona.</translation>
-<translation id="702384510542929236">Wysyła do Google niektóre anonimowe informacje o systemie i zawartości stron</translation>
<translation id="7025190659207909717">Zarządzanie komórkową usługą transmisji danych</translation>
<translation id="7027125358315426638">Nazwa bazy danych:</translation>
<translation id="7029809446516969842">Hasła</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">Otwórz aplikację tapety</translation>
<translation id="7290242001003353852">Ta usługa logowania, pochodząca z domeny <ph name="SAML_DOMAIN" />, ma dostęp do kamery.</translation>
<translation id="7290594223351252791">Potwierdź rejestrację</translation>
+<translation id="7292696521213967957">Informacje służące do debugowania Asystenta</translation>
<translation id="7295662345261934369">Udostępnij innym</translation>
<translation id="729583233778673644">Zezwala na szyfrowanie AES i RC4. Używanie tej opcji jest ryzykowne, ponieważ szyfrowanie RC4 nie zapewnia bezpieczeństwa.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> – warunki</translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">Otwórz lokalizację...</translation>
<translation id="7461924472993315131">Przypnij</translation>
<translation id="7463006580194749499">Dodaj osobę</translation>
-<translation id="7464902436585505072">Model głosu „OK Google”</translation>
<translation id="7465778193084373987">Adres URL odwołania certyfikatu firmy Netscape</translation>
<translation id="7469894403370665791">Automatycznie łącz się z tą siecią</translation>
<translation id="747114903913869239">Błąd: nie można zdekodować rozszerzenia</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424">Aplikacja <ph name="LINUX_APP_NAME" /> zostanie usunięta z tego urządzenia wraz z powiązanymi z nią danymi.</translation>
<translation id="7497215489070763236">Certyfikat CA serwera</translation>
<translation id="7497981768003291373">Nie ma zapisanych ostatnio logów tekstowych WebRTC.</translation>
+<translation id="7502199377020483660">Aby używać tych kart na wszystkich swoich urządzeniach, zapisz je na swoim koncie Google</translation>
<translation id="7502658306369382406">Adres IPv6</translation>
<translation id="7503191893372251637">Typ certyfikatu firmy Netscape</translation>
<translation id="7503821294401948377">Nie można wczytać ikony „<ph name="ICON" />” dla czynności wykonywanej w przeglądarce.</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">Odbiorca: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Nieobsługiwane urządzenie Bluetooth: „<ph name="DEVICE_NAME" />”.</translation>
<translation id="7665369617277396874">Dodaj konto</translation>
+<translation id="7667248760110172428">Pamięć zewnętrzna</translation>
<translation id="7671130400130574146">Użyj systemowego paska tytułu i ramek</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> na stronie <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Wysyła Twój głos do Google, by umożliwić dyktowanie w dowolnym polu tekstowym.</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">Tutaj pojawią się zapisane formy płatności</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> udostępnia ekran i dźwięk.</translation>
<translation id="7931318309563332511">Nieznany</translation>
+<translation id="7932969338829957666">Foldery udostępnione są dostępne w Linuxie w folderze <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Wyłącz wyciszenie strony}few{Wyłącz wyciszenie stron}many{Wyłącz wyciszenie stron}other{Wyłącz wyciszenie stron}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> chce odtworzyć treści chronione. Tożsamość Twojego urządzenia zostanie zweryfikowana przez Google.</translation>
<translation id="793531125873261495">Błąd podczas pobierania maszyny wirtualnej. Spróbuj ponownie.</translation>
@@ -4672,6 +4684,7 @@ Przechowuj plik klucza w bezpiecznym miejscu. Będzie on potrzebny do utworzenia
<translation id="8049705080247101012">Google uznaje rozszerzenie „<ph name="EXTENSION_NAME" />” za złośliwe, dlatego nie dopuściliśmy do jego zainstalowania</translation>
<translation id="8049913480579063185">Nazwa rozszerzenia</translation>
<translation id="8050038245906040378">Podpisywanie kodu handlowego firmy Microsoft</translation>
+<translation id="8052887694493382350">To jest plik na komputery z oprogramowaniem Windows. Twoje urządzenie z Chrome OS go nie obsługuje. <ph name="BEGIN_LINK_HELP" />Więcej informacji<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Pliki PKCS #12</translation>
<translation id="8053390638574070785">Załaduj ponownie tę stronę</translation>
<translation id="8054517699425078995">Pliki tego typu mogą wyrządzić szkody na urządzeniu. Czy mimo to chcesz zachować plik <ph name="FILE_NAME" />?</translation>
@@ -4916,6 +4929,7 @@ Osoby z wolnym połączeniem mogą nie zobaczyć treści, które przesyłasz.</
<translation id="8438566539970814960">Ulepsz wyszukiwanie i przeglądanie</translation>
<translation id="8439506636278576865">Proponuj tłumaczenie stron w tym języku</translation>
<translation id="8440630305826533614">Aplikacje na Linuksa</translation>
+<translation id="8443338615972234259">Utwórz teraz nowe konto dla nadzorowanego użytkownika.</translation>
<translation id="8446884382197647889">Więcej informacji</translation>
<translation id="8447409163267621480">Uwzględnij Ctrl lub Alt</translation>
<translation id="8448729345478502352">Powiększ lub pomniejsz elementy na ekranie</translation>
@@ -4940,6 +4954,7 @@ Osoby z wolnym połączeniem mogą nie zobaczyć treści, które przesyłasz.</
<translation id="8468750959626135884">Urządzenie <ph name="DEVICE_TYPE" /> możesz odblokowywać przy użyciu swojego telefonu z Androidem.</translation>
<translation id="8470028084415844044">Aby korzystać ze wszystkich swoich haseł na innych urządzeniach, włącz synchronizację.</translation>
<translation id="8470513973197838199">Zapisane hasła do <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Aby używać tej karty na wszystkich swoich urządzeniach, zapisz ją na swoim koncie Google</translation>
<translation id="8472623782143987204">sprzętowe</translation>
<translation id="8473863474539038330">Adresy i ustawienia</translation>
<translation id="8475313423285172237">Inny program na Twoim komputerze dodał rozszerzenie, które może zmienić działanie Chrome.</translation>
@@ -5015,7 +5030,6 @@ Osoby z wolnym połączeniem mogą nie zobaczyć treści, które przesyłasz.</
<translation id="8598453409908276158">Wtyczka spoza piaskownicy zablokowana</translation>
<translation id="8601206103050338563">Uwierzytelnianie klienta WWW TLS</translation>
<translation id="8602851771975208551">Inny program na Twoim komputerze dodał aplikację, która może zmienić działanie Chrome.</translation>
-<translation id="8604763363205185560">Pomóż w ulepszaniu funkcji i zabezpieczeń Chrome</translation>
<translation id="8605428685123651449">Pamięć SQLite</translation>
<translation id="8606726445206553943">Korzystać z urządzeń MIDI</translation>
<translation id="8609465669617005112">W górę</translation>
@@ -5191,6 +5205,7 @@ Osoby z wolnym połączeniem mogą nie zobaczyć treści, które przesyłasz.</
<translation id="8846141544112579928">Szukam klawiatury...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Łącząc swoje urządzenia, zgadzasz się na to, by Twój Chromebook mógł:</translation>
+<translation id="8850251000316748990">Zobacz więcej…</translation>
<translation id="8859057652521303089">Wybierz język:</translation>
<translation id="8859174528519900719">Ramka podrzędna: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Arkusz kalkulacyjny Excela</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_pt-BR.xtb b/chromium/chrome/app/resources/generated_resources_pt-BR.xtb
index 195ff22b577..a37e8f300f5 100644
--- a/chromium/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chromium/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Ativar tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Ver na Chrome Web Store</translation>
-<translation id="1761588866118490543">Modelo de voz</translation>
<translation id="176193854664720708">O sensor de impressão digital fica no botão liga/desliga. Toque levemente com qualquer dedo.</translation>
<translation id="1763046204212875858">Criar atalhos para aplicativos</translation>
<translation id="1763108912552529023">Continuar explorando</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Envie dados de uso e diagnóstico. No momento, este dispositivo está enviando automaticamente ao Google dados de diagnóstico, de uso de apps e do dispositivo. Eles ajudarão a melhorar o sistema, a estabilidade de apps e muito mais. Alguns dados agregados também ajudarão os apps do Google e os nossos parceiros, como os desenvolvedores Android. Essa configuração é aplicada pelo proprietário. Se a configuração "Atividade na Web e de apps adicional" estiver ativada, esses dados poderão ser salvos na sua Conta do Google. <ph name="BEGIN_LINK1" />Saiba mais<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Arquivo Zip</translation>
<translation id="220858061631308971">Digite este código PIN em "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Remover compartilhamento</translation>
+<translation id="2214018885812055163">Pastas compartilhadas</translation>
<translation id="2214884991347062907">Senha incorreta. Tente novamente</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 linha não mostrada&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> linha não mostrada&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> linhas não mostradas&gt;}}</translation>
<translation id="2217501013957346740">Criar um nome –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Certificado em espera</translation>
<translation id="2501797496290880632">Digite um atalho</translation>
<translation id="2502441965851148920">As atualizações automáticas estão ativadas. As atualizações manuais foram desativadas pelo seu administrador.</translation>
+<translation id="2505127913256479918">Esta conta supervisionada será removida em breve</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Tela #}one{Tela #}other{Tela #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> de <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Conta da Google Play Store</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Mecanismos de fala</translation>
<translation id="3053013834507634016">Uso da chave de certificado</translation>
<translation id="3057861065630527966">Fazer backup de suas fotos e seus vídeos</translation>
+<translation id="3058498974290601450">Ative a sincronização quando quiser nas configurações</translation>
<translation id="3060379269883947824">Ativar Selecionar para ouvir</translation>
<translation id="3061707000357573562">Aplicar patch ao serviço</translation>
<translation id="3065041951436100775">Feedback para guia desativada.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015">O <ph name="PRODUCT_NAME" /> será instalado</translation>
<translation id="3380365263193509176">Erro desconhecido</translation>
<translation id="3382073616108123819">O sistema falhou ao determinar os identificadores deste dispositivo.</translation>
+<translation id="3382086682569279540">A conta que você gerencia será removida em breve</translation>
<translation id="3382200254148930874">Parando a supervisão…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separador</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Olá, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> restantes</translation>
<translation id="3637682276779847508">Seu chip será permanentemente desativado se você não informar a chave correta de desbloqueio por PIN.</translation>
-<translation id="363863692969456324">Corrija os erros de ortografia com a verificação ortográfica aprimorada</translation>
<translation id="3640214691812501263">Adicionar "<ph name="EXTENSION_NAME" />" para <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Ensine o Assistente a reconhecer sua voz</translation>
<translation id="3644896802912593514">Largura</translation>
<translation id="3645372836428131288">Mova o dedo levemente para capturar outra parte da impressão digital.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> detectado</translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Encontrar mais apps para usar com a stylus</translation>
<translation id="424546999567421758">Detectado alto uso de disco</translation>
<translation id="424726838611654458">Sempre abrir com o Adobe Reader</translation>
-<translation id="4247330672018280062">O texto inserido nos campos editáveis será enviado para o Google</translation>
<translation id="4247901771970415646">Não é possível sincronizar com <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Aguardando conexão da rede...</translation>
<translation id="4249373718504745892">Esta página foi impedida de acessar sua câmera e seu microfone.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Criação de perfil ativada</translation>
<translation id="4823484602432206655">Ler e alterar as configurações do dispositivo e usuário</translation>
<translation id="4823651846660089135">O dispositivo é somente leitura</translation>
+<translation id="4824958205181053313">Cancelar sincronização?</translation>
<translation id="4827675678516992122">Não foi possível conectar</translation>
<translation id="4828937774870308359">Australiano</translation>
<translation id="4829768588131278040">Configurar PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Alterar imagem</translation>
<translation id="5376169624176189338">Clique para voltar, mantenha pressionado para ver o histórico</translation>
<translation id="5376931455988532197">Arquivo muito grande</translation>
+<translation id="5377594097385838788">Anônimo</translation>
<translation id="537813040452600081">As páginas que você visualiza nesta janela não aparecerão no histórico do navegador nem deixarão outros rastros, como cookies, no computador depois que você sair. Os downloads que você fizer e os favoritos que criar não serão preservados.</translation>
<translation id="5379140238605961210">Continuar bloqueando o acesso ao microfone</translation>
<translation id="5379268888377976432">Desfazer exclusão</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Ler os ícones dos websites que você visitar</translation>
<translation id="5417312524372586921">Temas do navegador</translation>
<translation id="5419294236999569767">Hora do sistema</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Determina a nitidez de textos e imagens</translation>
<translation id="5422221874247253874">Ponto de acesso</translation>
<translation id="5422781158178868512">Seu dispositivo de armazenamento externo não foi reconhecido.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 Criptografia RSA</translation>
<translation id="5436492226391861498">Esperando pelo túnel de proxy...</translation>
<translation id="5436510242972373446">Pesquisar em <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Salve seus arquivos e crie uma nova conta agora mesmo.</translation>
<translation id="5438224778284622050">Excluir arquivos off-line?</translation>
<translation id="544083962418256601">Criar atalhos...</translation>
<translation id="5442228125690314719">Erro ao criar imagem de disco. Tente novamente.</translation>
@@ -3286,6 +3293,8 @@ Não exponha nenhuma informação confidencial.</translation>
<translation id="5965661248935608907">Controla também qual página deve ser exibida quando você clica no botão "Página inicial" ou quando faz uma pesquisa na Omnibox.</translation>
<translation id="5971037678316050792">Controlar estado e pareamento do adaptador Bluetooth</translation>
<translation id="5972017421290582825">Gerenciar configurações MIDI...</translation>
+<translation id="597235323114979258">Ver mais destinos</translation>
+<translation id="5972666587303800813">Serviço sem operação</translation>
<translation id="5972708806901999743">Mover para a parte superior</translation>
<translation id="5972826969634861500">Iniciar o <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Percentual de carga da bateria</translation>
@@ -3657,6 +3666,7 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
<translation id="6527303717912515753">Compartilhar</translation>
<translation id="6528513914570774834">Permitir que outros usuários deste dispositivo usem esta rede</translation>
<translation id="652948702951888897">Histórico do Chrome</translation>
+<translation id="6530186581263215931">Estas configurações são aplicadas pelo administrador</translation>
<translation id="653019979737152879">Sincronizando <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Manter arquivo perigoso</translation>
<translation id="6532101170117367231">Salvar no Google Drive</translation>
@@ -3724,7 +3734,7 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
Se você não quiser adicionar uma conta, faça login como convidado ou abra uma janela anônima para navegar na Web.
- Acesse Configurações -&gt; Contas do Google para ver e gerenciar todas as contas.</translation>
+ Acesse "Configurações" -&gt; "Contas do Google" para ver e gerenciar todas as contas.</translation>
<translation id="6639554308659482635">Memória SQLite</translation>
<translation id="6641138807883536517">A senha do módulo de segurança gerada aleatoriamente não está disponível. Isso é normal após um Powerwash.</translation>
<translation id="6643016212128521049">Limpar</translation>
@@ -3975,7 +3985,6 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
<translation id="7018275672629230621">Ler e alterar seu histórico de navegação</translation>
<translation id="7019805045859631636">Rápido</translation>
<translation id="7022562585984256452">Sua página inicial foi definida.</translation>
-<translation id="702384510542929236">Envia algumas informações do sistema e conteúdo da página para o Google anonimamente</translation>
<translation id="7025190659207909717">Gerenciamento dos serviços de dados móveis</translation>
<translation id="7027125358315426638">Nome do banco de dados:</translation>
<translation id="7029809446516969842">Senhas</translation>
@@ -4036,7 +4045,7 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
<translation id="7109543803214225826">Atalho removido</translation>
<translation id="7113502843173351041">Saiba seu endereço de e-mail</translation>
<translation id="7114054701490058191">As senhas não correspondem</translation>
-<translation id="7114648273807173152">Para usar o Smart Lock para fazer login na sua Conta do Google, acesse Config. &gt; Dispositivos conectados &gt; Seu smartphone &gt; Smart Lock.</translation>
+<translation id="7114648273807173152">Para usar o Smart Lock para fazer login na sua Conta do Google, acesse "Config." &gt; "Dispositivos conectados" &gt; "Seu smartphone" &gt; "Smart Lock".</translation>
<translation id="7117228822971127758">Tente novamente mais tarde</translation>
<translation id="7117247127439884114">Fazer login novamente...</translation>
<translation id="711840821796638741">Mostrar favoritos gerenciados</translation>
@@ -4155,6 +4164,7 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
<translation id="7289225569524511578">Abra o app de papel de parede</translation>
<translation id="7290242001003353852">Este serviço de login, hospedado por <ph name="SAML_DOMAIN" />, está acessando sua câmara.</translation>
<translation id="7290594223351252791">Confirmar registro</translation>
+<translation id="7292696521213967957">Informações para depurar o Assistente</translation>
<translation id="7295662345261934369">Compartilhar com outras pessoas</translation>
<translation id="729583233778673644">Permitir a codificação AES e RC4. O uso dessa opção é mais arriscado, porque as criptografias RC4 não são seguras.</translation>
<translation id="7296774163727375165">Termos de <ph name="DOMAIN" /></translation>
@@ -4255,7 +4265,6 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
<translation id="7456847797759667638">Abrir local...</translation>
<translation id="7461924472993315131">Fixar</translation>
<translation id="7463006580194749499">Adicionar pessoa</translation>
-<translation id="7464902436585505072">Modelo de voz "Ok Google"</translation>
<translation id="7465778193084373987">URL da revogação do certificado do Netscape</translation>
<translation id="7469894403370665791">Conectar-se automaticamente a esta rede</translation>
<translation id="747114903913869239">Erro: Não foi possível decodificar a extensão</translation>
@@ -4283,6 +4292,7 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
<translation id="7496511874649569424">O app <ph name="LINUX_APP_NAME" /> e os dados associados serão removidos deste dispositivo.</translation>
<translation id="7497215489070763236">Certificado de CA do servidor</translation>
<translation id="7497981768003291373">Você não tem nenhum registro de texto WebRTC capturado recentemente.</translation>
+<translation id="7502199377020483660">Para usar estes cartões em todos os seus dispositivos, salve-os na sua Conta do Google</translation>
<translation id="7502658306369382406">Endereço IPv6</translation>
<translation id="7503191893372251637">Tipo de certificado do Netscape</translation>
<translation id="7503821294401948377">Não foi possível carregar o ícone "<ph name="ICON" />" para a ação do navegador.</translation>
@@ -4380,6 +4390,7 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
<translation id="7663719505383602579">Destinatário: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Dispositivo Bluetooth não suportado: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Adicionar conta</translation>
+<translation id="7667248760110172428">Armazenamento externo</translation>
<translation id="7671130400130574146">Usar barra de título e bordas do sistema</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, neste site: <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Envie sua voz para que o Google permita que o ditado seja usado em qualquer campo de texto.</translation>
@@ -4583,6 +4594,7 @@ permanentemente excluídos assim que esse usuário for removido. Os websites vis
<translation id="7930294771522048157">As formas de pagamento salvas serão exibidas aqui</translation>
<translation id="79312157130859720">O app <ph name="APP_NAME" /> está compartilhando sua tela e áudio.</translation>
<translation id="7931318309563332511">Desconhecido</translation>
+<translation id="7932969338829957666">As pastas compartilhadas estão disponíveis no Linux em <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Ativar som do site}one{Ativar som do site}other{Ativar som dos sites}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> quer reproduzir conteúdo protegido. A identidade do seu dispositivo será verificada pelo Google.</translation>
<translation id="793531125873261495">Erro ao fazer o download da máquina virtual. Tente novamente.</translation>
@@ -4674,6 +4686,7 @@ Mantenha a sua chave de arquivo em um local seguro. Você precisará dela para c
<translation id="8049705080247101012">O Google sinalizou a extensão "<ph name="EXTENSION_NAME" />" como maliciosa e impediu a instalação</translation>
<translation id="8049913480579063185">Nome da extensão</translation>
<translation id="8050038245906040378">Assinatura do código comercial da Microsoft</translation>
+<translation id="8052887694493382350">Esse arquivo foi criado para computadores que utilizam o software do Windows. Ele não é compatível com seu dispositivo, que executa o Chrome OS. <ph name="BEGIN_LINK_HELP" />Saiba mais<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Arquivos PKCS #12</translation>
<translation id="8053390638574070785">Recarregar esta página</translation>
<translation id="8054517699425078995">Este tipo de arquivo pode danificar seu dispositivo. Quer manter <ph name="FILE_NAME" /> mesmo assim?</translation>
@@ -4918,6 +4931,7 @@ Pessoas com conexões mais lentas talvez não vejam seu conteúdo.</translation>
<translation id="8438566539970814960">Melhorar pesquisas e navegação</translation>
<translation id="8439506636278576865">Oferecer para traduzir páginas neste idioma</translation>
<translation id="8440630305826533614">Aplicativos Linux</translation>
+<translation id="8443338615972234259">Crie uma nova conta para seu usuário supervisionado agora mesmo.</translation>
<translation id="8446884382197647889">Saiba mais</translation>
<translation id="8447409163267621480">Incluir a tecla Ctrl ou Alt</translation>
<translation id="8448729345478502352">Torne os itens na tela menores ou maiores</translation>
@@ -4942,6 +4956,7 @@ Pessoas com conexões mais lentas talvez não vejam seu conteúdo.</translation>
<translation id="8468750959626135884">Desbloquear o <ph name="DEVICE_TYPE" /> com seu smartphone Android.</translation>
<translation id="8470028084415844044">Para ter todas as suas senhas em todos os seus dispositivos, ative a sincronização.</translation>
<translation id="8470513973197838199">Senhas salvas para <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Para usar este cartão em todos os seus dispositivos, salve-o na sua Conta do Google</translation>
<translation id="8472623782143987204">suportado por hardware</translation>
<translation id="8473863474539038330">Endereços e mais</translation>
<translation id="8475313423285172237">Outro programa em seu computador adicionou uma extensão que pode mudar a forma como o Google Chrome funciona.</translation>
@@ -5017,7 +5032,6 @@ Pessoas com conexões mais lentas talvez não vejam seu conteúdo.</translation>
<translation id="8598453409908276158">Plug-in sem sandbox bloqueado</translation>
<translation id="8601206103050338563">Autenticação do cliente TLS WWW</translation>
<translation id="8602851771975208551">Outro programa em seu computador adicionou um aplicativo que pode mudar a forma como o Google Chrome funciona.</translation>
-<translation id="8604763363205185560">Ajude a melhorar o Chrome e a segurança do navegador</translation>
<translation id="8605428685123651449">Memória SQLite</translation>
<translation id="8606726445206553943">Usar seus dispositivos MIDI</translation>
<translation id="8609465669617005112">Mover para cima</translation>
@@ -5193,6 +5207,7 @@ Pessoas com conexões mais lentas talvez não vejam seu conteúdo.</translation>
<translation id="8846141544112579928">Procurando teclado...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Ao conectar os dispositivos, você concorda que o Chromebook pode:</translation>
+<translation id="8850251000316748990">Ver mais…</translation>
<translation id="8859057652521303089">Selecione o seu idioma:</translation>
<translation id="8859174528519900719">Subquadro: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Planilha do Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_pt-PT.xtb b/chromium/chrome/app/resources/generated_resources_pt-PT.xtb
index 929236c6da2..69852bb4b1c 100644
--- a/chromium/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chromium/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Ativar tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Ver na Web Store do Chrome</translation>
-<translation id="1761588866118490543">Modelo de voz</translation>
<translation id="176193854664720708">O sensor de impressões digitais está no botão ligar/desligar. Toque levemente no mesmo com qualquer dedo.</translation>
<translation id="1763046204212875858">Criar atalhos da aplicação</translation>
<translation id="1763108912552529023">Continuar a explorar</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Envie dados de utilização e diagnóstico. Agora, este dispositivo está a enviar automaticamente dados de diagnóstico, de utilização de aplicações e do dispositivo para a Google. Deste modo, ajudará a melhorar a estabilidade das aplicações e do sistema, entre outras melhorias. Alguns dados agregados também ajudarão as aplicações e os parceiros Google, como os programadores Android. Esta definição é aplicada pelo proprietário. Se a definição Atividade da Web e de aplicações adicional estiver ativada, estes dados podem ser guardados na sua Conta Google. <ph name="BEGIN_LINK1" />Saiba mais<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Ficheiro zip</translation>
<translation id="220858061631308971">Introduza este código PIN no "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Remover a partilha</translation>
+<translation id="2214018885812055163">Pastas partilhadas</translation>
<translation id="2214884991347062907">Palavra-passe incorreta. Tente novamente.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 linha não apresentada&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> linhas não apresentadas&gt;}}</translation>
<translation id="2217501013957346740">Criar um nome –</translation>
@@ -1014,6 +1015,7 @@
<translation id="2501173422421700905">Certificado em espera</translation>
<translation id="2501797496290880632">Introduza um atalho</translation>
<translation id="2502441965851148920">As atualizações automáticas estão ativadas. As atualizações manuais estão desativadas pelo seu gestor.</translation>
+<translation id="2505127913256479918">Esta conta supervisionada será removida brevemente</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Ecrã #}other{Ecrãs #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> de <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Conta da Google Play Store</translation>
@@ -1375,6 +1377,7 @@ Pretende pará-lo?</translation>
<translation id="304747341537320566">Motores de voz</translation>
<translation id="3053013834507634016">Utilização de chave de certificado</translation>
<translation id="3057861065630527966">Fazer uma cópia de segurança de fotos e vídeos</translation>
+<translation id="3058498974290601450">Pode ativar a sincronização em qualquer altura nas definições.</translation>
<translation id="3060379269883947824">Ativar Selecionar para ativar voz</translation>
<translation id="3061707000357573562">Serviço de patch</translation>
<translation id="3065041951436100775">Comentários acerca de separador desativado.</translation>
@@ -1566,6 +1569,7 @@ Pretende pará-lo?</translation>
<translation id="337920581046691015">O <ph name="PRODUCT_NAME" /> será instalado.</translation>
<translation id="3380365263193509176">Erro desconhecido</translation>
<translation id="3382073616108123819">Ups! O sistema não conseguiu determinar identificadores de dispositivos para este dispositivo.</translation>
+<translation id="3382086682569279540">A conta que gere será removida brevemente</translation>
<translation id="3382200254148930874">A parar a supervisão…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separador</translation>
@@ -1746,8 +1750,8 @@ Pretende pará-lo?</translation>
<translation id="3636096452488277381">Olá <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – <ph name="TIME" /> restantes</translation>
<translation id="3637682276779847508">O seu cartão SIM é desativado definitivamente se não conseguir introduzir a chave de desbloqueio do PIN correta</translation>
-<translation id="363863692969456324">Corrigir erros ortográficos com a verificação ortográfica melhorada</translation>
<translation id="3640214691812501263">Adicionar "<ph name="EXTENSION_NAME" />" para <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Ensine o Assistente a reconhecer a sua voz</translation>
<translation id="3644896802912593514">Largura</translation>
<translation id="3645372836428131288">Mova ligeiramente para capturar uma parte diferente da impressão digital.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> detetado</translation>
@@ -2147,7 +2151,6 @@ Pretende pará-lo?</translation>
<translation id="4244238649050961491">Encontrar mais aplicações para a caneta stylus</translation>
<translation id="424546999567421758">Detetada elevada utilização do disco</translation>
<translation id="424726838611654458">Sempre aberto no Adobe Reader</translation>
-<translation id="4247330672018280062">O texto que introduzir nos campos de texto será enviado para a Google.</translation>
<translation id="4247901771970415646">Não é possível sincronizar com <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">A aguardar ligação à rede...</translation>
<translation id="4249373718504745892">Esta página foi impedida de aceder à sua câmara e microfone.</translation>
@@ -2489,6 +2492,7 @@ Pretende pará-lo?</translation>
<translation id="4821935166599369261">Criação de &amp;perfis ativada</translation>
<translation id="4823484602432206655">Ler e alterar definições do utilizador e do dispositivo</translation>
<translation id="4823651846660089135">O dispositivo é apenas de leitura</translation>
+<translation id="4824958205181053313">Pretende cancelar a sincronização?</translation>
<translation id="4827675678516992122">Não foi possível ligar</translation>
<translation id="4828937774870308359">Australiano</translation>
<translation id="4829768588131278040">Configurar PIN</translation>
@@ -2871,6 +2875,7 @@ Pretende pará-lo?</translation>
<translation id="5374359983950678924">Alterar imagem</translation>
<translation id="5376169624176189338">Clique para retroceder, mantenha premido para ver o histórico</translation>
<translation id="5376931455988532197">Ficheiro demasiado grande</translation>
+<translation id="5377594097385838788">Navegação anónima</translation>
<translation id="537813040452600081">As páginas visualizadas nesta janela não serão apresentadas no histórico do navegador nem no histórico de pesquisas e não deixarão outros vestígios, como cookies, no computador depois de terminar sessão. Os ficheiros transferidos e os marcadores criados não serão preservados.</translation>
<translation id="5379140238605961210">Continuar a bloquear o acesso ao microfone</translation>
<translation id="5379268888377976432">Anular Eliminação</translation>
@@ -2892,6 +2897,7 @@ Pretende pará-lo?</translation>
<translation id="5414566801737831689">Ler os ícones dos Sites que visita</translation>
<translation id="5417312524372586921">Temas do navegador</translation>
<translation id="5419294236999569767">Hora do sistema</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Determina a nitidez do texto e das imagens.</translation>
<translation id="5422221874247253874">Ponto de acesso</translation>
<translation id="5422781158178868512">Lamentamos, não foi possível reconhecer o aparelho de armazenamento externo.</translation>
@@ -2912,6 +2918,7 @@ Pretende pará-lo?</translation>
<translation id="5434065355175441495">PKCS #1 Encriptação RSA</translation>
<translation id="5436492226391861498">A aguardar pelo túnel do proxy...</translation>
<translation id="5436510242972373446">Pesquisar <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Guarde os ficheiros e crie uma nova conta agora.</translation>
<translation id="5438224778284622050">Pretende eliminar os ficheiros offline?</translation>
<translation id="544083962418256601">Criar atalhos...</translation>
<translation id="5442228125690314719">Ocorreu um erro ao criar a imagem do disco. Tente novamente.</translation>
@@ -3286,6 +3293,8 @@ Certifique-se de que não revela informações confidenciais.</translation>
<translation id="5965661248935608907">Também controla a página apresentada quando clica no botão Página Inicial ou pesquisa a partir da Caixa geral.</translation>
<translation id="5971037678316050792">Controlar estado e sincronização do adaptador Bluetooth</translation>
<translation id="5972017421290582825">Gerir as definições de MIDI...</translation>
+<translation id="597235323114979258">Ver mais destinos</translation>
+<translation id="5972666587303800813">Serviço autónomo</translation>
<translation id="5972708806901999743">Mover para o início</translation>
<translation id="5972826969634861500">Iniciar o <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Percentagem de carga da bateria</translation>
@@ -3656,6 +3665,7 @@ Certifique-se de que não revela informações confidenciais.</translation>
<translation id="6527303717912515753">Partilhar</translation>
<translation id="6528513914570774834">Permitir que outros utilizadores deste dispositivo utilizem esta rede</translation>
<translation id="652948702951888897">Histórico do Chrome</translation>
+<translation id="6530186581263215931">Estas definições são aplicadas pelo seu administrador</translation>
<translation id="653019979737152879">A sincronizar <ph name="FILE_NAME" />…</translation>
<translation id="6531282281159901044">Manter ficheiro perigoso</translation>
<translation id="6532101170117367231">Guardar no Google Drive</translation>
@@ -3974,7 +3984,6 @@ Certifique-se de que não revela informações confidenciais.</translation>
<translation id="7018275672629230621">Ler e alterar o histórico de navegação</translation>
<translation id="7019805045859631636">Rápido</translation>
<translation id="7022562585984256452">A sua página inicial foi definida.</translation>
-<translation id="702384510542929236">Envia algumas informações do sistema e conteúdo da página para a Google anonimamente.</translation>
<translation id="7025190659207909717">Gestão de serviços de dados móveis</translation>
<translation id="7027125358315426638">Nome da base de dados:</translation>
<translation id="7029809446516969842">Palavras-passe</translation>
@@ -4154,6 +4163,7 @@ Certifique-se de que não revela informações confidenciais.</translation>
<translation id="7289225569524511578">Abrir a aplicação da imagem de fundo</translation>
<translation id="7290242001003353852">Este serviço de início de sessão, alojado por <ph name="SAML_DOMAIN" />, está a aceder à sua câmara.</translation>
<translation id="7290594223351252791">Confirmar registo</translation>
+<translation id="7292696521213967957">Informações para depurar o Assistente</translation>
<translation id="7295662345261934369">Partilhar com outros</translation>
<translation id="729583233778673644">Permitir a encriptação AES e RC4. A utilização desta opção aumenta o seu risco, uma vez que as cifras RC4 são inseguras.</translation>
<translation id="7296774163727375165">Termos de <ph name="DOMAIN" /></translation>
@@ -4254,7 +4264,6 @@ Certifique-se de que não revela informações confidenciais.</translation>
<translation id="7456847797759667638">Abrir localização...</translation>
<translation id="7461924472993315131">Fixar</translation>
<translation id="7463006580194749499">Adicionar pessoa</translation>
-<translation id="7464902436585505072">Modelo de voz "Ok Google"</translation>
<translation id="7465778193084373987">URL de revogação do certificado Netscape</translation>
<translation id="7469894403370665791">Ligar automaticamente a esta rede</translation>
<translation id="747114903913869239">Erro: não foi possível descodificar a extensão</translation>
@@ -4282,6 +4291,7 @@ Certifique-se de que não revela informações confidenciais.</translation>
<translation id="7496511874649569424">A aplicação <ph name="LINUX_APP_NAME" /> e os dados associados à mesma serão removidos deste dispositivo.</translation>
<translation id="7497215489070763236">Certificado da AC do servidor</translation>
<translation id="7497981768003291373">Não existem registos de textos WebRTC capturados recentemente.</translation>
+<translation id="7502199377020483660">Para utilizar estes cartões em todos os seus dispositivos, guarde-os na sua Conta Google.</translation>
<translation id="7502658306369382406">Endereço IPv6</translation>
<translation id="7503191893372251637">Tipo de certificado Netscape</translation>
<translation id="7503821294401948377">Não foi possível carregar o ícone "<ph name="ICON" />" para a ação do navegador.</translation>
@@ -4379,6 +4389,7 @@ Certifique-se de que não revela informações confidenciais.</translation>
<translation id="7663719505383602579">Recetor: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Dispositivo Bluetooth não suportado: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Adicionar conta</translation>
+<translation id="7667248760110172428">Armazenamento externo</translation>
<translation id="7671130400130574146">Utilizar os limites e a barra de título do sistema</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, em <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Envie a sua voz para o Google para permitir a introdução por voz em qualquer campo de texto.</translation>
@@ -4582,6 +4593,7 @@ Certifique-se de que não revela informações confidenciais.</translation>
<translation id="7930294771522048157">Os métodos de pagamento guardados são apresentados aqui.</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> está a partilhar o ecrã e o áudio.</translation>
<translation id="7931318309563332511">Desconhecido</translation>
+<translation id="7932969338829957666">As pastas partilhadas estão disponíveis no Linux em <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Reativar o som do site}other{Reativar o som dos sites}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> pretende reproduzir conteúdo protegido. A Google irá validar a identidade do seu dispositivo.</translation>
<translation id="793531125873261495">Ocorreu um erro ao transferir a máquina virtual. Tente novamente.</translation>
@@ -4673,6 +4685,7 @@ Mantenha o seu ficheiro de chave num local seguro, pois irá precisar dele para
<translation id="8049705080247101012">A Google sinalizou a extensão "<ph name="EXTENSION_NAME" />" como sendo maliciosa e a instalação foi impedida.</translation>
<translation id="8049913480579063185">Nome da Extensão</translation>
<translation id="8050038245906040378">Assinatura de código comercial Microsoft</translation>
+<translation id="8052887694493382350">Este ficheiro foi concebido para computadores com software Windows. Não é compatível com o seu dispositivo, pois este tem o Chrome OS instalado. <ph name="BEGIN_LINK_HELP" />Saiba mais<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Ficheiros PKCS #12</translation>
<translation id="8053390638574070785">Recarregar esta página</translation>
<translation id="8054517699425078995">Este tipo de ficheiro pode danificar o seu dispositivo. Ainda assim, pretende manter o ficheiro <ph name="FILE_NAME" />?</translation>
@@ -4915,6 +4928,7 @@ Mantenha o seu ficheiro de chave num local seguro, pois irá precisar dele para
<translation id="8438566539970814960">Melhorar as pesquisas e a navegação</translation>
<translation id="8439506636278576865">Oferecer para traduzir páginas neste idioma</translation>
<translation id="8440630305826533614">Aplicações para Linux</translation>
+<translation id="8443338615972234259">Crie uma nova conta para o seu utilizador supervisionado agora.</translation>
<translation id="8446884382197647889">Saiba Mais</translation>
<translation id="8447409163267621480">Inclua Ctrl ou Alt.</translation>
<translation id="8448729345478502352">Diminuir ou aumentar os elementos no ecrã</translation>
@@ -4939,6 +4953,7 @@ Mantenha o seu ficheiro de chave num local seguro, pois irá precisar dele para
<translation id="8468750959626135884">Desbloqueie o <ph name="DEVICE_TYPE" /> com o telemóvel Android.</translation>
<translation id="8470028084415844044">Para obter todas as suas palavras-passe em todos os dispositivos, ative a sincronização.</translation>
<translation id="8470513973197838199">Palavras-passe guardadas para <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Para utilizar este cartão em todos os seus dispositivos, guarde-o na sua Conta Google.</translation>
<translation id="8472623782143987204">suporte de hardware</translation>
<translation id="8473863474539038330">Endereços e mais</translation>
<translation id="8475313423285172237">Outro programa do computador adicionou uma extensão que pode alterar o funcionamento do Chrome.</translation>
@@ -5014,7 +5029,6 @@ Mantenha o seu ficheiro de chave num local seguro, pois irá precisar dele para
<translation id="8598453409908276158">Plug-in sem isolamento de processos bloqueado</translation>
<translation id="8601206103050338563">Autenticação de cliente TLS WWW</translation>
<translation id="8602851771975208551">Outro programa do computador adicionou uma aplicação que pode alterar o funcionamento do Chrome</translation>
-<translation id="8604763363205185560">Ajudar a melhorar o Chrome e a respetiva segurança</translation>
<translation id="8605428685123651449">Memória SQLite</translation>
<translation id="8606726445206553943">Utilizar os seus dispositivos MIDI</translation>
<translation id="8609465669617005112">Mover para cima</translation>
@@ -5190,6 +5204,7 @@ Mantenha o seu ficheiro de chave num local seguro, pois irá precisar dele para
<translation id="8846141544112579928">A pesquisar teclado...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Ao associar os seus dispositivos, concorda que o Chromebook pode:</translation>
+<translation id="8850251000316748990">Veja mais…</translation>
<translation id="8859057652521303089">Selecionar idioma:</translation>
<translation id="8859174528519900719">Subestrutura: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Folha de cálculo do Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ro.xtb b/chromium/chrome/app/resources/generated_resources_ro.xtb
index d7c55648e93..4d6094263d8 100644
--- a/chromium/chrome/app/resources/generated_resources_ro.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ro.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Activați tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Vezi în Magazinul web Chrome</translation>
-<translation id="1761588866118490543">Model vocal</translation>
<translation id="176193854664720708">Senzorul de amprentă digitală se află în butonul de pornire. Atinge-l ușor cu oricare deget.</translation>
<translation id="1763046204212875858">Creează comenzi rapide pentru aplicație</translation>
<translation id="1763108912552529023">Explorați în continuare</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Trimite date de utilizare și diagnosticare. Momentan, dispozitivul trimite automat date de diagnosticare și de utilizare a dispozitivului și aplicațiilor la Google. Aceasta va ajuta la stabilitatea sistemului, a aplicației și altele. Unele date cumulate vor ajuta aplicațiile și partenerii Google, cum ar fi dezvoltatorii Android. Această setare este impusă de proprietar. Dacă setarea Activitatea suplimentară de pe web și din aplicații este activată, aceste date pot fi salvate în Contul tău Google. <ph name="BEGIN_LINK1" />Află mai multe<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Arhivă zip</translation>
<translation id="220858061631308971">Introduceți acest cod PIN pe „<ph name="DEVICE_NAME" />”:</translation>
+<translation id="2213140827792212876">Elimină utilizarea comună</translation>
+<translation id="2214018885812055163">Dosare comune</translation>
<translation id="2214884991347062907">Parolă greșită, încearcă din nou</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;O linie nu este afișată&gt;}few{&lt;<ph name="NUMBER_OF_LINES" /> linii nu sunt afișate&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> de linii nu sunt afișate&gt;}}</translation>
<translation id="2217501013957346740">Creați un nume –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Certificat reținut</translation>
<translation id="2501797496290880632">Tastați o comandă rapidă</translation>
<translation id="2502441965851148920">Actualizările automate sunt activate. Actualizările manuale sunt dezactivate de administrator.</translation>
+<translation id="2505127913256479918">Acest cont supravegheat va fi eliminat în curând</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Ecranul #}few{Ecranul #}other{Ecranul #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> din <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Contul Magazin Google Play</translation>
@@ -1375,6 +1377,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="304747341537320566">Motoare de vorbire</translation>
<translation id="3053013834507634016">Folosirea cheii de certificat</translation>
<translation id="3057861065630527966">Fă backup pentru fotografii și videoclipuri</translation>
+<translation id="3058498974290601450">Poți să activezi sincronizarea oricând în setări</translation>
<translation id="3060379269883947824">Activează „Selectează și ascultă”</translation>
<translation id="3061707000357573562">Serviciu de corecție</translation>
<translation id="3065041951436100775">Feedback despre fila eliminată.</translation>
@@ -1566,6 +1569,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> va fi instalat.</translation>
<translation id="3380365263193509176">Eroare necunoscută</translation>
<translation id="3382073616108123819">Hopa! Sistemul nu a stabilit identificatorii de dispozitiv pentru acest dispozitiv.</translation>
+<translation id="3382086682569279540">Contul pe care îl gestionezi va fi eliminat în curând</translation>
<translation id="3382200254148930874">Se oprește supravegherea…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Separator</translation>
@@ -1746,8 +1750,8 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="3636096452488277381">Bună ziua, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – Timp rămas: <ph name="TIME" /></translation>
<translation id="3637682276779847508">Cardul SIM va fi dezactivat definitiv dacă nu vei introduce cheia corectă de deblocare a codului PIN.</translation>
-<translation id="363863692969456324">Corectează erorile de ortografie cu verificarea ortografiei îmbunătățită</translation>
<translation id="3640214691812501263">Adaugi „<ph name="EXTENSION_NAME" />” pentru <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Învață Asistentul să îți recunoască vocea</translation>
<translation id="3644896802912593514">Lățime</translation>
<translation id="3645372836428131288">Mută ușor pentru a înregistra o altă parte a amprentei</translation>
<translation id="3648348069317717750">S-a detectat <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="4244238649050961491">Găsește mai multe aplicații pentru creion</translation>
<translation id="424546999567421758">S-a detectat o utilizare ridicată a spațiului de pe disc</translation>
<translation id="424726838611654458">Deschide întotdeauna în Adobe Reader</translation>
-<translation id="4247330672018280062">Textul pe care îl introduci în câmpurile de text va fi trimis la Google.</translation>
<translation id="4247901771970415646">Nu se poate sincroniza cu <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Se așteaptă realizarea conexiunii la rețea...</translation>
<translation id="4249373718504745892">Accesul acestei pagini la camera și microfonul dvs. a fost blocat.</translation>
@@ -2489,6 +2492,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="4821935166599369261">&amp;Analizare activată</translation>
<translation id="4823484602432206655">Citește și modifică setările pentru dispozitiv și pentru utilizator</translation>
<translation id="4823651846660089135">Dispozitivul este numai în citire</translation>
+<translation id="4824958205181053313">Anulezi sincronizarea?</translation>
<translation id="4827675678516992122">Nu s-a putut conecta</translation>
<translation id="4828937774870308359">Inversă</translation>
<translation id="4829768588131278040">Configurează codul PIN</translation>
@@ -2871,6 +2875,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="5374359983950678924">Schimbă imaginea</translation>
<translation id="5376169624176189338">Dă clic pentru a naviga înapoi, ține apăsat pentru a vedea istoricul</translation>
<translation id="5376931455988532197">Fișierul este prea mare</translation>
+<translation id="5377594097385838788">Incognito</translation>
<translation id="537813040452600081">Paginile pe care le accesați în această fereastră nu vor apărea în istoricul browserului și nu vor lăsa alte urme pe computer (de ex., cookie-uri) după ce vă deconectați. Fișierele pe care le descărcați și marcajele pe care le creați nu se vor păstra.</translation>
<translation id="5379140238605961210">Blocați în continuare accesul la microfon</translation>
<translation id="5379268888377976432">Anulați ștergerea</translation>
@@ -2892,6 +2897,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="5414566801737831689">Citește pictogramele site-urilor pe care le accesezi</translation>
<translation id="5417312524372586921">Teme pentru browser</translation>
<translation id="5419294236999569767">Ora sistemului</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Stabilește claritatea textului și imaginilor</translation>
<translation id="5422221874247253874">Punct de acces</translation>
<translation id="5422781158178868512">Ne pare rău, dispozitivul dvs. de stocare externă nu a putut fi recunoscut.</translation>
@@ -2912,6 +2918,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="5434065355175441495">Criptare RSA PKCS #1</translation>
<translation id="5436492226391861498">Se așteaptă tunelul proxy...</translation>
<translation id="5436510242972373446">Caută <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Salvează fișierele și configurează un cont nou.</translation>
<translation id="5438224778284622050">Ștergi fișierele offline?</translation>
<translation id="544083962418256601">Creați comenzi rapide...</translation>
<translation id="5442228125690314719">A apărut o eroare la crearea imaginii discului. Încearcă din nou.</translation>
@@ -3285,6 +3292,8 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="5965661248935608907">Stabilește și ce pagină se afișează când dai clic pe butonul Pagina principală sau când cauți din caseta polivalentă.</translation>
<translation id="5971037678316050792">Controlează starea și conectarea adaptorului Bluetooth</translation>
<translation id="5972017421290582825">Gestionați setările MIDI...</translation>
+<translation id="597235323114979258">Vezi mai multe destinații</translation>
+<translation id="5972666587303800813">Serviciu no-op</translation>
<translation id="5972708806901999743">Mută în partea de sus</translation>
<translation id="5972826969634861500">Pornește <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Procent de încărcare a bateriei</translation>
@@ -3655,6 +3664,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="6527303717912515753">Trimite</translation>
<translation id="6528513914570774834">Permite altor utilizatori ai dispozitivului să folosească această rețea</translation>
<translation id="652948702951888897">Istoricul Chrome</translation>
+<translation id="6530186581263215931">Aceste setări sunt impuse de administrator</translation>
<translation id="653019979737152879">Se sincronizează <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Păstrează fișierul periculos</translation>
<translation id="6532101170117367231">Salvați în Google Drive</translation>
@@ -3973,7 +3983,6 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="7018275672629230621">Citește și modifică istoricul de navigare</translation>
<translation id="7019805045859631636">Rapid</translation>
<translation id="7022562585984256452">Pagina de pornire a fost setată.</translation>
-<translation id="702384510542929236">Trimite anonim la Google anumite informații despre sistem și conținutul paginii,</translation>
<translation id="7025190659207909717">Gestionarea serviciului de date mobile</translation>
<translation id="7027125358315426638">Nume bază de date:</translation>
<translation id="7029809446516969842">Parole</translation>
@@ -4153,6 +4162,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="7289225569524511578">Deschide aplicația pentru imaginea de fundal</translation>
<translation id="7290242001003353852">Acest serviciu de conectare, găzduit de <ph name="SAML_DOMAIN" />, îți accesează camera foto.</translation>
<translation id="7290594223351252791">Confirmarea înregistrării</translation>
+<translation id="7292696521213967957">Informații pentru a remedia erorile Asistentului</translation>
<translation id="7295662345261934369">Permite accesul altor utilizatori</translation>
<translation id="729583233778673644">Permite criptarea AES și RC4. Folosirea acestei opțiuni îți mărește riscul, deoarece suitele de codificare RC4 sunt nesecurizate.</translation>
<translation id="7296774163727375165">Termenii și condițiile <ph name="DOMAIN" /></translation>
@@ -4253,7 +4263,6 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="7456847797759667638">Deschide o locație...</translation>
<translation id="7461924472993315131">PIN</translation>
<translation id="7463006580194749499">Adăugați o persoană</translation>
-<translation id="7464902436585505072">Model vocal „OK Google”</translation>
<translation id="7465778193084373987">Adresă URL de revocare a certificatului Netscape</translation>
<translation id="7469894403370665791">Conectează-te automat la această rețea</translation>
<translation id="747114903913869239">Eroare: extensia nu poate fi decodificată</translation>
@@ -4281,6 +4290,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> și datele asociate acestei aplicații vor fi eliminate de pe dispozitiv.</translation>
<translation id="7497215489070763236">Certificat CA de server</translation>
<translation id="7497981768003291373">Nu ai jurnale text WebRTC înregistrate recent.</translation>
+<translation id="7502199377020483660">Pentru a folosi cardurile pe toate dispozitivele, salvează-le în Contul tău Google</translation>
<translation id="7502658306369382406">Adresă IPv6</translation>
<translation id="7503191893372251637">Tip de certificat Netscape</translation>
<translation id="7503821294401948377">Nu se poate încărca pictograma „<ph name="ICON" />” pentru acțiunea browserului.</translation>
@@ -4378,6 +4388,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="7663719505383602579">Receptor: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Dispozitiv Bluetooth neacceptat: „<ph name="DEVICE_NAME" />”.</translation>
<translation id="7665369617277396874">Adăugați un cont</translation>
+<translation id="7667248760110172428">Stocare externă</translation>
<translation id="7671130400130574146">Folosește bara de titlu și chenarele definite în sistem</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, în <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Trimite-ți vocea la Google pentru a permite dictarea în orice câmp de text.</translation>
@@ -4581,6 +4592,7 @@ Mesaj de la server: <ph name="SERVER_MSG" /></translation>
<translation id="7930294771522048157">Metodele de plată salvate vor fi afișate aici</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> trimite conținutul de pe ecran și conținutul audio.</translation>
<translation id="7931318309563332511">Necunoscută</translation>
+<translation id="7932969338829957666">Dosarele comune sunt disponibile în Linux la <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Activează sunetul pentru site}few{Activează sunetul pentru site-uri}other{Activează sunetul pentru site-uri}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> vrea să redea conținut protejat. Google va verifica identitatea dispozitivului tău.</translation>
<translation id="793531125873261495">A apărut o eroare la descărcarea mașinii virtuale. Încearcă din nou.</translation>
@@ -4672,6 +4684,7 @@ Păstrează fișierul cu cheia într-un loc sigur. Acesta va fi necesar la crear
<translation id="8049705080247101012">Google a semnalat „<ph name="EXTENSION_NAME" />” ca extensie rău intenționată și instalarea nu a fost permisă</translation>
<translation id="8049913480579063185">Numele extensiei</translation>
<translation id="8050038245906040378">Semnare comercială a codului Microsoft</translation>
+<translation id="8052887694493382350">Acest fișier este conceput pentru un PC care folosește software-ul Windows. Acesta nu este compatibil cu dispozitivul tău care rulează sistemul de operare Chrome. <ph name="BEGIN_LINK_HELP" />Află mai multe<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Fișiere PKCS #12</translation>
<translation id="8053390638574070785">Reîncarcă această pagină</translation>
<translation id="8054517699425078995">Acest tip de fișier poate dăuna dispozitivului. Doriți totuși să păstrați fișierul <ph name="FILE_NAME" />?</translation>
@@ -4915,6 +4928,7 @@ Păstrează fișierul cu cheia într-un loc sigur. Acesta va fi necesar la crear
<translation id="8438566539970814960">Îmbunătățește căutările și navigarea</translation>
<translation id="8439506636278576865">Oferă-te să traduci paginile în această limbă</translation>
<translation id="8440630305826533614">Aplicații Linux</translation>
+<translation id="8443338615972234259">Creează acum un cont nou pentru utilizatorul monitorizat.</translation>
<translation id="8446884382197647889">Află mai multe</translation>
<translation id="8447409163267621480">Include Ctrl sau Alt</translation>
<translation id="8448729345478502352">Micșorează sau mărește elementele de pe ecran</translation>
@@ -4939,6 +4953,7 @@ Păstrează fișierul cu cheia într-un loc sigur. Acesta va fi necesar la crear
<translation id="8468750959626135884">Deblochează dispozitivul <ph name="DEVICE_TYPE" /> folosind telefonul Android.</translation>
<translation id="8470028084415844044">Pentru a accesa toate parolele pe toate dispozitivele, activează sincronizarea.</translation>
<translation id="8470513973197838199">Parole salvate pentru <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Pentru a folosi acest card pe toate dispozitivele, salvează-l în Contul tău Google</translation>
<translation id="8472623782143987204">susținut de hardware</translation>
<translation id="8473863474539038330">Adrese și altele</translation>
<translation id="8475313423285172237">Un alt program de pe computerul dvs. a adăugat o extensie care poate schimba modul în care funcționează Chrome.</translation>
@@ -5014,7 +5029,6 @@ Păstrează fișierul cu cheia într-un loc sigur. Acesta va fi necesar la crear
<translation id="8598453409908276158">Pluginul în afara mediului de testare este blocat</translation>
<translation id="8601206103050338563">Autentificare client TLS WWW</translation>
<translation id="8602851771975208551">Un alt program de pe computerul dvs. a adăugat o aplicație care poate schimba modul în care funcționează Chrome.</translation>
-<translation id="8604763363205185560">Ajută la îmbunătățirea Chrome și a securității acestuia</translation>
<translation id="8605428685123651449">Memorie SQLite</translation>
<translation id="8606726445206553943">Folosească dispozitive MIDI</translation>
<translation id="8609465669617005112">Mutați mai sus</translation>
@@ -5190,6 +5204,7 @@ Păstrează fișierul cu cheia într-un loc sigur. Acesta va fi necesar la crear
<translation id="8846141544112579928">Se caută tastatura...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Când îți conectezi dispozitivele, ești de acord că Chromebookul poate:</translation>
+<translation id="8850251000316748990">Mai multe detalii...</translation>
<translation id="8859057652521303089">Selectează limba:</translation>
<translation id="8859174528519900719">Subcadru: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Foaie de calcul Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ru.xtb b/chromium/chrome/app/resources/generated_resources_ru.xtb
index 987f4e6e1c7..55ba2d80737 100644
--- a/chromium/chrome/app/resources/generated_resources_ru.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ru.xtb
@@ -517,7 +517,6 @@
<translation id="175772926354468439">Включить тему</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Перейти в Интернет-магазин Chrome</translation>
-<translation id="1761588866118490543">Образец голоса</translation>
<translation id="176193854664720708">Сканер отпечатков пальцев встроен в кнопку питания. Несильно нажмите на нее любым пальцем.</translation>
<translation id="1763046204212875858">Создание ярлыков приложений</translation>
<translation id="1763108912552529023">Дополнительные сведения</translation>
@@ -814,6 +813,8 @@
<translation id="220792432208469595">Отправка данных о работе устройства. Сейчас это устройство автоматически отправляет в Google диагностическую информацию, сведения об использовании приложений и самого устройства. Эти данные нужны нам, чтобы в будущем повысить стабильность приложений и внести другие улучшения. Некоторые данные в обобщенном виде пригодятся партнерам Google, например разработчикам Android. Эта настройка принудительно применяется владельцем. Если запись дополнительной истории приложений и веб-поиска включена, эта информация может сохраняться в вашем аккаунте. <ph name="BEGIN_LINK1" />Подробнее…<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">ZIP-архив</translation>
<translation id="220858061631308971">Введите PIN-код для устройства "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Закрыть доступ</translation>
+<translation id="2214018885812055163">Общие папки</translation>
<translation id="2214884991347062907">Неверный пароль. Повторите попытку.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 строка скрыта&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> строка скрыта&gt;}few{&lt;<ph name="NUMBER_OF_LINES" /> строки скрыто&gt;}many{&lt;<ph name="NUMBER_OF_LINES" /> строк скрыто&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> строки скрыто&gt;}}</translation>
<translation id="2217501013957346740">Придумайте имя –</translation>
@@ -1013,6 +1014,7 @@
<translation id="2501173422421700905">Cертификат приостановлен</translation>
<translation id="2501797496290880632">Укажите быстрые клавиши</translation>
<translation id="2502441965851148920">Включен режим автоматического обновления. Функция обновления вручную отключена администратором.</translation>
+<translation id="2505127913256479918">Скоро этот контролируемый аккаунт будет удален</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Экран #}one{Экран #}few{Экран #}many{Экран #}other{Экран #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> из <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Аккаунт Google Play</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Синтезаторы речи</translation>
<translation id="3053013834507634016">Использование ключа сертификата</translation>
<translation id="3057861065630527966">Создать резервные копии фото и видео</translation>
+<translation id="3058498974290601450">Ее можно включить в настройках в любой момент.</translation>
<translation id="3060379269883947824">Включить озвучивание при нажатии</translation>
<translation id="3061707000357573562">Исправление сервиса</translation>
<translation id="3065041951436100775">Сообщение о вкладке, закрытой из-за отсутствия ответа.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015">Будет установлен <ph name="PRODUCT_NAME" /></translation>
<translation id="3380365263193509176">Неизвестная ошибка</translation>
<translation id="3382073616108123819">Не удалось определить идентификаторы устройства.</translation>
+<translation id="3382086682569279540">Скоро будет удален управляемый вами аккаунт.</translation>
<translation id="3382200254148930874">Отключение родительского контроля…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Разделитель</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Привет, <ph name="USER_GIVEN_NAME" />!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% (ещё <ph name="TIME" />)</translation>
<translation id="3637682276779847508">Если вы введете неправильный PUK-код, SIM-карта будет окончательно заблокирована.</translation>
-<translation id="363863692969456324">Исправляйте опечатки с помощью улучшенного инструмента проверки правописания</translation>
<translation id="3640214691812501263">Добавить расширение "<ph name="EXTENSION_NAME" />" для пользователя <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Научите Ассистента узнавать ваш голос</translation>
<translation id="3644896802912593514">Ширина</translation>
<translation id="3645372836428131288">Немного перемещайте палец, чтобы отсканировать его полностью.</translation>
<translation id="3648348069317717750">Обнаружено устройство "<ph name="USB_DEVICE_NAME" />"</translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Другие приложения для стилуса</translation>
<translation id="424546999567421758">Большая нагрузка на диск</translation>
<translation id="424726838611654458">Всегда открывать в Adobe Reader</translation>
-<translation id="4247330672018280062">Текст, который вы указываете в полях ввода, будет отправляться в Google.</translation>
<translation id="4247901771970415646">Не удалось синхронизироваться с аккаунтом <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Ожидается подключение к сети...</translation>
<translation id="4249373718504745892">Этот сайт не имеет доступа к вашим камере и микрофону</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Сбор данных включен</translation>
<translation id="4823484602432206655">Просмотр и изменение настроек для пользователей и устройств</translation>
<translation id="4823651846660089135">Устройство доступно только для чтения</translation>
+<translation id="4824958205181053313">Отключить синхронизацию?</translation>
<translation id="4827675678516992122">Ошибка подключения</translation>
<translation id="4828937774870308359">Обратная</translation>
<translation id="4829768588131278040">Установить PIN-код</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Изменить картинку</translation>
<translation id="5376169624176189338">Нажмите, чтобы вернуться. Удерживайте, чтобы просмотреть историю.</translation>
<translation id="5376931455988532197">Слишком большой файл</translation>
+<translation id="5377594097385838788">Инкогнито</translation>
<translation id="537813040452600081">Страницы, открытые в этом окне, не сохранятся в истории браузера. Они не оставят на компьютере следов, таких как файлы cookie, после того как вы выйдете из аккаунта. Скачанные вами файлы и добавленные закладки будут удалены.</translation>
<translation id="5379140238605961210">Всегда блокировать доступ к микрофону</translation>
<translation id="5379268888377976432">Отменить удаление</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Доступ к значкам посещаемых сайтов</translation>
<translation id="5417312524372586921">Темы браузера</translation>
<translation id="5419294236999569767">Системное время</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Определяет резкость текста и изображений.</translation>
<translation id="5422221874247253874">Точка доступа</translation>
<translation id="5422781158178868512">Не удалось распознать внешнее запоминающее устройство.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 шифрование RSA</translation>
<translation id="5436492226391861498">Ожидание создания туннеля прокси...</translation>
<translation id="5436510242972373446">Искать на <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Сохраните свои файлы и создайте новый аккаунт.</translation>
<translation id="5438224778284622050">Удалить скачанные файлы?</translation>
<translation id="544083962418256601">Создать ярлык…</translation>
<translation id="5442228125690314719">Не удалось создать образ диска. Повторите попытку.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">Кроме того, расширение изменило страницу, которая отображается при нажатии кнопки "Главная страница", и поисковую систему, используемую по умолчанию при вводе запроса в омнибокс.</translation>
<translation id="5971037678316050792">Управление состоянием адаптера Bluetooth и подключением</translation>
<translation id="5972017421290582825">Настройки MIDI…</translation>
+<translation id="597235323114979258">Другие места назначения печати</translation>
+<translation id="5972666587303800813">No-op</translation>
<translation id="5972708806901999743">К началу</translation>
<translation id="5972826969634861500">Запустить <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Процент зарядки батареи</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">Поделиться</translation>
<translation id="6528513914570774834">Предоставить другим пользователям устройства доступ к этой сети</translation>
<translation id="652948702951888897">История Chrome</translation>
+<translation id="6530186581263215931">Эти настройки определяются администратором</translation>
<translation id="653019979737152879">Синхронизация файла "<ph name="FILE_NAME" />"…</translation>
<translation id="6531282281159901044">Сохранить</translation>
<translation id="6532101170117367231">Сохранить в Google Диске</translation>
@@ -3718,11 +3728,12 @@
<translation id="6629841649550503054">Данные сохранены на <ph name="BEGIN_LINK" />Google Диске<ph name="END_LINK" /></translation>
<translation id="6630752851777525409">Расширение "<ph name="EXTENSION_NAME" />" запрашивает постоянный доступ к сертификату для прохождения аутентификации от вашего имени.</translation>
<translation id="6635956300022133031">Выбор и настройка голоса</translation>
-<translation id="6637585982786704944">Приложения и сайты, которым вы предоставили соответствующие разрешения, могут получать доступ к данным аккаунта, необходимым для корректной работы.
+<translation id="6637585982786704944">У приложений и сайтов, которым вы предоставили соответствующие разрешения, есть доступ к данным аккаунта, необходимым для корректной работы.
Если вы не хотите добавлять аккаунт, используйте для просмотра веб-страниц гостевой режим или окно в режиме инкогнито.
- Чтобы посмотреть список аккаунтов и управлять ими, нажмите "Настройки &gt; Аккаунты Google".</translation>
+
+Чтобы посмотреть список аккаунтов и управлять ими, нажмите "Настройки &gt; Аккаунты Google".</translation>
<translation id="6639554308659482635">Память SQLite</translation>
<translation id="6641138807883536517">Случайно сгенерированный пароль безопасного модуля недоступен после выполнения функции Powerwash.</translation>
<translation id="6643016212128521049">Очистить</translation>
@@ -3973,7 +3984,6 @@
<translation id="7018275672629230621">Чтение и изменение истории просмотров</translation>
<translation id="7019805045859631636">Быстро</translation>
<translation id="7022562585984256452">Главная страница настроена.</translation>
-<translation id="702384510542929236">В Google время от времени будет анонимно отправляться системная информация и контент страниц.</translation>
<translation id="7025190659207909717">Управление передачей данных в мобильных сетях</translation>
<translation id="7027125358315426638">Название базы данных:</translation>
<translation id="7029809446516969842">Пароли</translation>
@@ -4153,6 +4163,7 @@
<translation id="7289225569524511578">Откройте приложение "Обои"</translation>
<translation id="7290242001003353852">Сервису входа, размещенному в домене <ph name="SAML_DOMAIN" />, разрешен доступ к вашей камере.</translation>
<translation id="7290594223351252791">Подтверждение регистрации</translation>
+<translation id="7292696521213967957">Данные для отладки Ассистента</translation>
<translation id="7295662345261934369">Предоставить доступ</translation>
<translation id="729583233778673644">Разрешить шифрование по алгоритмам AES и RC4. Использовать этот параметр небезопасно, так как потоковый шифр RC4 ненадежен.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> – Условия использования</translation>
@@ -4253,7 +4264,6 @@
<translation id="7456847797759667638">Открыть адрес...</translation>
<translation id="7461924472993315131">Закрепить</translation>
<translation id="7463006580194749499">Добавить пользователя</translation>
-<translation id="7464902436585505072">Образец голоса с командой "Окей, Google"</translation>
<translation id="7465778193084373987">URL отзыва сертификатов Netscape</translation>
<translation id="7469894403370665791">Автоматически подключаться к этой сети</translation>
<translation id="747114903913869239">Ошибка: не удается расшифровать расширение</translation>
@@ -4281,6 +4291,7 @@
<translation id="7496511874649569424">Приложение "<ph name="LINUX_APP_NAME" />" и связанные данные будут удалены с устройства.</translation>
<translation id="7497215489070763236">Серверный сертификат ЦС</translation>
<translation id="7497981768003291373">Не обнаружено недавно сохраненных текстовых журналов WebRTC.</translation>
+<translation id="7502199377020483660">Сохраните карты в аккаунте Google, чтобы пользоваться ими на всех своих устройствах.</translation>
<translation id="7502658306369382406">Адрес IPv6</translation>
<translation id="7503191893372251637">Тип сертификата Netscape</translation>
<translation id="7503821294401948377">Не удалось загрузить значок "<ph name="ICON" />" для действия браузера.</translation>
@@ -4378,6 +4389,7 @@
<translation id="7663719505383602579">Получатель: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Устройство Bluetooth "<ph name="DEVICE_NAME" />" не поддерживается.</translation>
<translation id="7665369617277396874">Добавить аккаунт</translation>
+<translation id="7667248760110172428">Внешний накопитель</translation>
<translation id="7671130400130574146">Использовать системные рамки и строку заголовка</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> на странице <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Запись вашего голоса отправляется в Google. Это позволяет использовать голосовой набор для любого текстового поля.</translation>
@@ -4581,6 +4593,7 @@
<translation id="7930294771522048157">Здесь появятся сохраненные способы оплаты.</translation>
<translation id="79312157130859720">Приложение "<ph name="APP_NAME" />" предоставило доступ к экрану и аудио.</translation>
<translation id="7931318309563332511">Неизвестно</translation>
+<translation id="7932969338829957666">В Linux общие папки находятся здесь: <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Включить звук на сайте}one{Включить звук на сайтах}few{Включить звук на сайтах}many{Включить звук на сайтах}other{Включить звук на сайтах}}</translation>
<translation id="7934414805353235750">С сайта <ph name="URL" /> поступил запрос на воспроизведение защищенного контента. Для вашего устройства будет проведена проверка Google.</translation>
<translation id="793531125873261495">Не удалось скачать виртуальную машину. Повторите попытку.</translation>
@@ -4672,6 +4685,7 @@
<translation id="8049705080247101012">Google заблокировал установку потенциально опасной программы (<ph name="EXTENSION_NAME" />).</translation>
<translation id="8049913480579063185">Название расширения</translation>
<translation id="8050038245906040378">Подписывание коммерческого кода Microsoft</translation>
+<translation id="8052887694493382350">Этот файл разработан для ПК под управлением Windows. Его нельзя открыть в системе Chrome OS, установленной на вашем устройстве. <ph name="BEGIN_LINK_HELP" />Подробнее…<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Файлы PKCS #12</translation>
<translation id="8053390638574070785">Обновить страницу</translation>
<translation id="8054517699425078995">Файл этого типа может причинить вред вашему мобильному устройству. Сохранить файл <ph name="FILE_NAME" />?</translation>
@@ -4914,6 +4928,7 @@
<translation id="8438566539970814960">Помогать улучшить просмотр страниц и поиск</translation>
<translation id="8439506636278576865">Предлагать перевести страницы на этом языке</translation>
<translation id="8440630305826533614">Приложения для Linux</translation>
+<translation id="8443338615972234259">Создайте новый аккаунт для контролируемого профиля.</translation>
<translation id="8446884382197647889">Подробнее...</translation>
<translation id="8447409163267621480">Сочетание должно начинаться с клавиши Ctrl или Alt</translation>
<translation id="8448729345478502352">Уменьшить или увеличить объекты на экране</translation>
@@ -4938,6 +4953,7 @@
<translation id="8468750959626135884">Снимайте блокировку устройства <ph name="DEVICE_TYPE" /> с помощью телефона Android.</translation>
<translation id="8470028084415844044">Чтобы получить доступ к паролям на всех своих устройствах, включите синхронизацию.</translation>
<translation id="8470513973197838199">Сохраненные пароли для <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Сохраните карту в аккаунте Google, чтобы пользоваться ею на всех своих устройствах.</translation>
<translation id="8472623782143987204">требуется оборудование</translation>
<translation id="8473863474539038330">Адреса и другая информация</translation>
<translation id="8475313423285172237">Одна из программ на вашем компьютере установила расширение, которое может влиять на работу Chrome.</translation>
@@ -5013,7 +5029,6 @@
<translation id="8598453409908276158">Доступ к плагинам вне тестовой среды запрещен</translation>
<translation id="8601206103050338563">Клиентская аутентификация TLS WWW</translation>
<translation id="8602851771975208551">Одна из программ на вашем компьютере установила приложение, которое может влиять на работу Chrome.</translation>
-<translation id="8604763363205185560">Помогайте Google улучшать Chrome и его функции безопасности</translation>
<translation id="8605428685123651449">Память SQLite</translation>
<translation id="8606726445206553943">использование MIDI-устройств</translation>
<translation id="8609465669617005112">Переместить вверх</translation>
@@ -5189,6 +5204,7 @@
<translation id="8846141544112579928">Поиск клавиатуры…</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">После подключения устройство Chromebook сможет:</translation>
+<translation id="8850251000316748990">Ещё...</translation>
<translation id="8859057652521303089">Выберите язык:</translation>
<translation id="8859174528519900719">Субфрейм: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Электронные таблицы Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_sk.xtb b/chromium/chrome/app/resources/generated_resources_sk.xtb
index aed7bfa29c8..a45bffc0d04 100644
--- a/chromium/chrome/app/resources/generated_resources_sk.xtb
+++ b/chromium/chrome/app/resources/generated_resources_sk.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Povoliť motív</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Zobraziť v Internetovom obchode Chrome</translation>
-<translation id="1761588866118490543">Hlasový model</translation>
<translation id="176193854664720708">Senzor odtlačkov prstov je vo vypínači. Dotknite sa ho ľubovoľným prstom.</translation>
<translation id="1763046204212875858">Vytvoriť odkazy na aplikáciu</translation>
<translation id="1763108912552529023">Skúmať</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Odosielať údaje o využití a diagnostiky. Toto zariadenie momentálne automaticky odosiela Googlu diagnostiky a údaje o používaní zariadenia a aplikácií. Pomôžu zvýšiť stabilitu systému a aplikácií a poskytovať ďalšie vylepšenia. Niektoré súhrnné údaje tiež pomôžu aplikáciám Google a partnerom, ako napríklad vývojárom Androidu. Používanie tohto nastavenia je presadzované vlastníkom. Ak aktivujete dodatočnú aktivitu na internete a v aplikáciách, tieto údaje sa môžu uložiť vo vašom účte Google. <ph name="BEGIN_LINK1" />Ďalšie informácie<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Archív ZIP</translation>
<translation id="220858061631308971">Zadajte tento kód PIN v zariadení „<ph name="DEVICE_NAME" />“:</translation>
+<translation id="2213140827792212876">Odstrániť zdieľanie</translation>
+<translation id="2214018885812055163">Zdieľané priečinky</translation>
<translation id="2214884991347062907">Nesprávne heslo. Skúste to znova.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;nie je zobrazený 1 riadok&gt;}few{&lt;nie sú zobrazené <ph name="NUMBER_OF_LINES" /> riadky&gt;}many{&lt;<ph name="NUMBER_OF_LINES" /> lines not shown&gt;}other{&lt;nie je zobrazených <ph name="NUMBER_OF_LINES" /> riadkov&gt;}}</translation>
<translation id="2217501013957346740">Vytvoriť meno –</translation>
@@ -1014,6 +1015,7 @@
<translation id="2501173422421700905">Pozastavený certifikát</translation>
<translation id="2501797496290880632">Zadajte skratku</translation>
<translation id="2502441965851148920">Automatické aktualizácie sú povolené. Ručné aktualizácie zakázal váš správca.</translation>
+<translation id="2505127913256479918">Tento kontrolovaný účet bude čoskoro odstránený</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Obrazovka #}few{Obrazovka #}many{Obrazovka #}other{Obrazovka #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> z <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Účet Obchodu Google Play</translation>
@@ -1373,6 +1375,7 @@
<translation id="304747341537320566">Nástroje hlasovej odozvy</translation>
<translation id="3053013834507634016">Použitie kľúča certifikátu</translation>
<translation id="3057861065630527966">Zálohovať fotky a videá</translation>
+<translation id="3058498974290601450">Synchronizáciu môžete kedykoľvek zapnúť v nastaveniach</translation>
<translation id="3060379269883947824">Povoliť počúvanie vybraného textu</translation>
<translation id="3061707000357573562">Služba opráv</translation>
<translation id="3065041951436100775">Spätná väzba týkajúca sa vynútene ukončenej karty</translation>
@@ -1564,6 +1567,7 @@
<translation id="337920581046691015">Nainštaluje sa <ph name="PRODUCT_NAME" />.</translation>
<translation id="3380365263193509176">Neznáma chyba</translation>
<translation id="3382073616108123819">Ojoj! Systém nedokázal rozpoznať identifikátory tohto zariadenia</translation>
+<translation id="3382086682569279540">Účet, ktorý spravujete, bude čoskoro odstránený</translation>
<translation id="3382200254148930874">Zastavuje sa dohľad…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Oddeľovač</translation>
@@ -1744,8 +1748,8 @@
<translation id="3636096452488277381">Dobrý deň, <ph name="USER_GIVEN_NAME" />!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> % – <ph name="TIME" /> do vybitia</translation>
<translation id="3637682276779847508">Ak nezadáte správny kód PIN na odomknutie, vaša SIM karta bude natrvalo deaktivovaná.</translation>
-<translation id="363863692969456324">Opravujte pravopisné chyby vylepšenou kontrolou pravopisu.</translation>
<translation id="3640214691812501263">Pridať rozšírenie <ph name="EXTENSION_NAME" /> pre používateľa <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Naučte Asistenta rozpoznať váš hlas</translation>
<translation id="3644896802912593514">Šírka</translation>
<translation id="3645372836428131288">Zľahka pohýbte, aby sa nasnímala ďalšia časť odtlačku.</translation>
<translation id="3648348069317717750">Rozpoznané zariadenie: <ph name="USB_DEVICE_NAME" /></translation>
@@ -2145,7 +2149,6 @@
<translation id="4244238649050961491">Nájsť ďalšie aplikácie pre dotykové pero</translation>
<translation id="424546999567421758">Zistilo sa vysoké využitie disku</translation>
<translation id="424726838611654458">Vždy otvoriť v programe Adobe Reader</translation>
-<translation id="4247330672018280062">Text zadaný v textových poliach sa odošle Googlu</translation>
<translation id="4247901771970415646">Nedá sa synchronizovať do účtu <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Čaká sa na sieťové pripojenie...</translation>
<translation id="4249373718504745892">Táto stránka má zablokovaný prístup ku kamere a mikrofónu.</translation>
@@ -2487,6 +2490,7 @@
<translation id="4821935166599369261">&amp;Profilovanie povolené</translation>
<translation id="4823484602432206655">Čítať a meniť nastavenia používateľa a zariadenia</translation>
<translation id="4823651846660089135">Zariadenie je len na čítanie</translation>
+<translation id="4824958205181053313">Chcete zrušiť synchronizáciu?</translation>
<translation id="4827675678516992122">Nepodarilo sa pripojiť</translation>
<translation id="4828937774870308359">Opačné</translation>
<translation id="4829768588131278040">Nastaviť kód PIN</translation>
@@ -2869,6 +2873,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="5374359983950678924">Zmeniť obrázok</translation>
<translation id="5376169624176189338">Kliknutím prejdete naspäť. Pri dlhšom stlačení sa zobrazí história.</translation>
<translation id="5376931455988532197">Súbor je príliš veľký</translation>
+<translation id="5377594097385838788">Inkognito</translation>
<translation id="537813040452600081">Stránky otvorené v tomto okne sa nezobrazia v histórii prehliadača a po odhlásení nezanechajú na počítači žiadne stopy, ako napríklad súbory cookie. Nezachovajú sa ani stiahnuté súbory a záložky.</translation>
<translation id="5379140238605961210">Aj naďalej blokovať prístup k mikrofónu</translation>
<translation id="5379268888377976432">Vrátiť späť odstránenie</translation>
@@ -2890,6 +2895,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="5414566801737831689">Čítať ikony webov, ktoré navštevujete</translation>
<translation id="5417312524372586921">Motívy prehliadača</translation>
<translation id="5419294236999569767">Čas systému</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Určuje ostrosť textu a snímok</translation>
<translation id="5422221874247253874">Prístupový bod</translation>
<translation id="5422781158178868512">Je nám ľúto, ale externé pamäťové zariadenie sa nepodarilo rozpoznať.</translation>
@@ -2910,6 +2916,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="5434065355175441495">Štandard PKCS #1 so šifrovaním RSA</translation>
<translation id="5436492226391861498">Čaká sa na tunelové prepojenie servera proxy...</translation>
<translation id="5436510242972373446">Prehľadať webovú stránku <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Uložte svoje súbory a zriaďte ihneď nový účet.</translation>
<translation id="5438224778284622050">Odstrániť súbory offline?</translation>
<translation id="544083962418256601">Vytvoriť odkazy na pracovnej ploche...</translation>
<translation id="5442228125690314719">Pri vytváraní obrazu disku sa vyskytla chyba. Skúste to znova.</translation>
@@ -3283,6 +3290,8 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="5965661248935608907">Tiež určuje, ktorá stránka sa zobrazí po kliknutí na tlačidlo Domovská stránka alebo pri vyhľadávaní pomocou všeobecného poľa.</translation>
<translation id="5971037678316050792">Ovládanie stavu a párovania adaptéra Bluetooth</translation>
<translation id="5972017421290582825">Spravovať nastavenia rozhrania MIDI...</translation>
+<translation id="597235323114979258">Zobraziť ďalšie cieľové tlačiarne</translation>
+<translation id="5972666587303800813">Neprevádzkovaná služba</translation>
<translation id="5972708806901999743">Presunúť na začiatok</translation>
<translation id="5972826969634861500">Spustiť <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Percento nabitia batérie</translation>
@@ -3653,6 +3662,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="6527303717912515753">Zdieľať</translation>
<translation id="6528513914570774834">Povoliť ostatným používateľom zariadenia pripojiť sa k tejto sieti</translation>
<translation id="652948702951888897">História Chromu</translation>
+<translation id="6530186581263215931">Tieto nastavenia sú vynútené správcom</translation>
<translation id="653019979737152879">Prebieha synchronizácia súboru <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Ponechať nebezpečný súbor</translation>
<translation id="6532101170117367231">Uložiť do služby Disk Google</translation>
@@ -3971,7 +3981,6 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="7018275672629230621">Čítať a upravovať históriu prehliadania</translation>
<translation id="7019805045859631636">Rýchle</translation>
<translation id="7022562585984256452">Vaša domovská stránka bola nastavená.</translation>
-<translation id="702384510542929236">Googlu sa budú anonymne odosielať niektoré informácie o systéme a obsah stránok</translation>
<translation id="7025190659207909717">Správa mobilnej dátovej služby</translation>
<translation id="7027125358315426638">Názov databázy:</translation>
<translation id="7029809446516969842">Heslá</translation>
@@ -4151,6 +4160,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="7289225569524511578">Otvoriť aplikáciu tapety</translation>
<translation id="7290242001003353852">Prihlasovacia služba hostená doménou <ph name="SAML_DOMAIN" /> pristupuje k vášmu fotoaparátu.</translation>
<translation id="7290594223351252791">Potvrdenie registrácie</translation>
+<translation id="7292696521213967957">Informácie na ladenie Asistenta</translation>
<translation id="7295662345261934369">Zdieľať s ostatnými</translation>
<translation id="729583233778673644">Povoľte šifrovania AES a RC4. Šifry RC4 sú nezabezpečené, takže použitím tejto možnosti zvýšite riziko.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> – Zmluvné podmienky</translation>
@@ -4251,7 +4261,6 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="7456847797759667638">Otvoriť umiestnenie...</translation>
<translation id="7461924472993315131">Pripnúť</translation>
<translation id="7463006580194749499">Pridať osobu</translation>
-<translation id="7464902436585505072">Hlasový model „Ok Google“</translation>
<translation id="7465778193084373987">Netscape – webová adresa pre zrušenie certifikátu</translation>
<translation id="7469894403370665791">Automaticky sa pripojiť k tejto sieti</translation>
<translation id="747114903913869239">Chyba: Nepodarilo sa dekódovať rozšírenie</translation>
@@ -4279,6 +4288,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="7496511874649569424">Aplikácia <ph name="LINUX_APP_NAME" /> a s ňou združené údaje sa odstránia z tohto zariadenia.</translation>
<translation id="7497215489070763236">Certifikát CA servera</translation>
<translation id="7497981768003291373">Nemáte žiadne nedávno zaznamenané textové denníky WebRTC.</translation>
+<translation id="7502199377020483660">Ak chcete používať tieto karty vo všetkých zariadeniach, uložte si ich v účte Google</translation>
<translation id="7502658306369382406">Adresa IPv6</translation>
<translation id="7503191893372251637">Netscape – typ certifikátu </translation>
<translation id="7503821294401948377">Nepodarilo sa načítať ikonu „<ph name="ICON" />“ akcie prehliadača.</translation>
@@ -4376,6 +4386,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="7663719505383602579">Prijímač: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Nepodporované zariadenie Bluetooth: <ph name="DEVICE_NAME" />.</translation>
<translation id="7665369617277396874">Pridať účet</translation>
+<translation id="7667248760110172428">Externé úložisko</translation>
<translation id="7671130400130574146">Použiť záhlavie a orámovanie okna systému</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> na stránke <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Odošlite svoj hlas do Googlu a umožnite tak diktovanie do všetkých textových polí.</translation>
@@ -4556,7 +4567,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="7893393459573308604"><ph name="ENGINE_NAME" /> (predvolené nastavenie)</translation>
<translation id="7897900149154324287">V budúcnosti nezabudnite v aplikácii Súbory vysunúť odnímateľné zariadenie skôr, ako ho odpojíte. Inak by ste mohli prísť o údaje.</translation>
<translation id="7898627924844766532">Ponechať na paneli s nástrojmi</translation>
-<translation id="7898725031477653577">Vždy preložiť</translation>
+<translation id="7898725031477653577">Vždy prekladať</translation>
<translation id="790040513076446191">Manipulovať s nastaveniami týkajúcimi sa ochrany osobných údajov</translation>
<translation id="7902874111237641165">Plynulý pohyb [beta]</translation>
<translation id="7903345046358933331">Stránka prestala reagovať. Môžete počkať, kým začne reagovať, alebo ju ukončite.</translation>
@@ -4579,6 +4590,7 @@ s ostatnými, a to všetko na jednom mieste.<ph name="MARKUP_9" /></translatio
<translation id="7930294771522048157">Tu sa zobrazia uložené spôsoby platby</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> zdieľa vašu obrazovku a zvuk.</translation>
<translation id="7931318309563332511">Neznámy</translation>
+<translation id="7932969338829957666">Zdieľané priečinky sú k dispozícii v systéme Linux v adresári <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Zapnúť zvuk webu}few{Zapnúť zvuk webov}many{Zapnúť zvuk webov}other{Zapnúť zvuk webov}}</translation>
<translation id="7934414805353235750">Web <ph name="URL" /> chce prehrať chránený obsah. Google overí totožnosť zariadenia.</translation>
<translation id="793531125873261495">Pri sťahovaní virtuálneho počítača sa vyskytla chyba. Skúste to znova.</translation>
@@ -4670,6 +4682,7 @@ Súbor kľúča uložte na bezpečné miesto. Budete ho potrebovať na vytvoreni
<translation id="8049705080247101012">Google označil rozšírenie <ph name="EXTENSION_NAME" /> ako škodlivé a jeho inštalácia bola zakázaná</translation>
<translation id="8049913480579063185">Názov rozšírenia</translation>
<translation id="8050038245906040378">Komerčné podpisovanie kódu Microsoft</translation>
+<translation id="8052887694493382350">Tento súbor je určený pre počítač so softvérom Windows. Nie je kompatibilný so zariadením so systémom Chrome OS. <ph name="BEGIN_LINK_HELP" />Ďalšie informácie<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Súbory PKCS #12</translation>
<translation id="8053390638574070785">Obnoviť túto stránku</translation>
<translation id="8054517699425078995">Tento typ súboru môže poškodiť vaše zariadenie. Chcete súbor <ph name="FILE_NAME" /> aj napriek tomu zachovať?</translation>
@@ -4912,6 +4925,7 @@ Súbor kľúča uložte na bezpečné miesto. Budete ho potrebovať na vytvoreni
<translation id="8438566539970814960">Zlepšovať vyhľadávania a prehliadanie</translation>
<translation id="8439506636278576865">Ponúkať preklady stránok v tomto jazyku</translation>
<translation id="8440630305826533614">Aplikácie pre Linux</translation>
+<translation id="8443338615972234259">Zriaďte ihneď nový účet pre kontrolovaného používateľa.</translation>
<translation id="8446884382197647889">Ďalšie informácie</translation>
<translation id="8447409163267621480">Použite buď Ctrl, alebo Alt</translation>
<translation id="8448729345478502352">Zväčšte alebo zmenšite položky na obrazovke</translation>
@@ -4936,6 +4950,7 @@ Súbor kľúča uložte na bezpečné miesto. Budete ho potrebovať na vytvoreni
<translation id="8468750959626135884">Odomknite zariadenie <ph name="DEVICE_TYPE" /> pomocou telefónu s Androidom.</translation>
<translation id="8470028084415844044">Ak chcete získať svoje heslá vo všetkých zariadeniach, zapnite synchronizáciu.</translation>
<translation id="8470513973197838199">Uložené heslá pre <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Ak chcete túto kartu používať vo všetkých svojich zariadeniach, uložte si ju v účte Google</translation>
<translation id="8472623782143987204">hardvérová záloha</translation>
<translation id="8473863474539038330">Adresy a ďalšie údaje</translation>
<translation id="8475313423285172237">Iný program v počítači pridal rozšírenie, ktoré môže zmeniť spôsob fungovania prehliadača Chrome.</translation>
@@ -5011,7 +5026,6 @@ Súbor kľúča uložte na bezpečné miesto. Budete ho potrebovať na vytvoreni
<translation id="8598453409908276158">Bol zablokovaný doplnok mimo karantény</translation>
<translation id="8601206103050338563">Overenie WWW klienta protokolom TLS</translation>
<translation id="8602851771975208551">Iný program v počítači pridal aplikáciu, ktorá môže zmeniť spôsob fungovania prehliadača Chrome.</translation>
-<translation id="8604763363205185560">Pomôžte zlepšiť Chrome a jeho zabezpečenie</translation>
<translation id="8605428685123651449">Pamäť nástroja SQLite</translation>
<translation id="8606726445206553943">Používať zariadenia MIDI</translation>
<translation id="8609465669617005112">Presunúť nahor</translation>
@@ -5187,6 +5201,7 @@ Súbor kľúča uložte na bezpečné miesto. Budete ho potrebovať na vytvoreni
<translation id="8846141544112579928">Hľadá sa klávesnica...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Keď prepojíte svoje zariadenia, súhlasíte s tým, že Chromebook bude môcť:</translation>
+<translation id="8850251000316748990">Zobraziť ďalšie…</translation>
<translation id="8859057652521303089">Vyberte svoj jazyk:</translation>
<translation id="8859174528519900719">Podrámec: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Tabuľka aplikácie Excel</translation>
@@ -5207,7 +5222,7 @@ Súbor kľúča uložte na bezpečné miesto. Budete ho potrebovať na vytvoreni
<translation id="8883847527783433352">Synchronizovať do iného účtu</translation>
<translation id="8885197664446363138">Funkcia Smart Lock nie je k dispozícii</translation>
<translation id="88870264962436283">Použitie funkcie Touch ID s aplikáciou <ph name="APP_NAME" /></translation>
-<translation id="8888253246822647887">Vaša aplikácia sa spustí po dokončení inovácie. Inovácie môžu trvať niekoľko minút.</translation>
+<translation id="8888253246822647887">Aplikácia sa spustí po dokončení inovácie. Inovácia môže trvať niekoľko minút.</translation>
<translation id="8888432776533519951">Farba:</translation>
<translation id="8890516388109605451">Zdroje</translation>
<translation id="8892168913673237979">Všetko je nastavené!</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_sl.xtb b/chromium/chrome/app/resources/generated_resources_sl.xtb
index d1b90c829e7..013f0a19243 100644
--- a/chromium/chrome/app/resources/generated_resources_sl.xtb
+++ b/chromium/chrome/app/resources/generated_resources_sl.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Omogoči temo</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Prikaži v Spletni trgovini Chrome</translation>
-<translation id="1761588866118490543">Glasovni model</translation>
<translation id="176193854664720708">Tipalo prstnih odtisov je v gumbu za vklop. Rahlo se ga dotaknite s poljubnim prstom.</translation>
<translation id="1763046204212875858">Ustvari bližnjice do &amp;programov ...</translation>
<translation id="1763108912552529023">Nadaljujte raziskovanje</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Pošiljanje podatkov o uporabi in diagnostičnih podatkov. Ta naprava trenutno Googlu samodejno pošilja diagnostične podatke ter podatke o uporabi naprave in aplikacij. Te podatke uporabljamo za izboljšanje stabilnosti sistema in izvajanja aplikacij ter drugega. Nekateri združeni podatki bodo pomagali tudi Googlovim aplikacijam in partnerjem, na primer razvijalcem za Android. To nastavitev je uveljavil lastnik naprave. Če ste vklopili dodatno beleženje dejavnosti v spletu in aplikacijah, bodo ti podatki morda shranjeni v vašem računu za Google. <ph name="BEGIN_LINK1" />Več o tem<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Arhiv zip</translation>
<translation id="220858061631308971">Vnesite PIN za napravo »<ph name="DEVICE_NAME" />«:</translation>
+<translation id="2213140827792212876">Odstrani skupno rabo</translation>
+<translation id="2214018885812055163">Mape v skupni rabi</translation>
<translation id="2214884991347062907">Napačno geslo. Poskusite znova.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 vrstica ni prikazana&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> vrstica ni prikazana&gt;}two{&lt;<ph name="NUMBER_OF_LINES" /> vrstici nista prikazani&gt;}few{&lt;<ph name="NUMBER_OF_LINES" /> vrstice niso prikazane&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> vrstic ni prikazanih&gt;}}</translation>
<translation id="2217501013957346740">Ustvarite ime –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Potrdilo zadržano</translation>
<translation id="2501797496290880632">Vnesite bližnjico</translation>
<translation id="2502441965851148920">Samodejne posodobitve so omogočene. Skrbnik je onemogočil ročne posodobitve.</translation>
+<translation id="2505127913256479918">Ta nadzorovani račun bo kmalu odstranjen</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Zaslon #}one{Zaslon #}two{Zaslon #}few{Zaslon #}other{Zaslon #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> od <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Račun za Trgovino Google Play</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Mehanizmi za govor</translation>
<translation id="3053013834507634016">Raba ključa potrdila</translation>
<translation id="3057861065630527966">Varnostno kopiranje fotografij videoposnetkov</translation>
+<translation id="3058498974290601450">Sinhronizacijo lahko kadarkoli vklopite v nastavitvah.</translation>
<translation id="3060379269883947824">Omogoči storitev Izberite in poslušajte</translation>
<translation id="3061707000357573562">Storitev za popravke</translation>
<translation id="3065041951436100775">Povratne informacije o zaustavitvi zavihka.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> bo nameščen.</translation>
<translation id="3380365263193509176">Neznana napaka</translation>
<translation id="3382073616108123819">Ups. Sistemu ni uspelo določiti identifikatorjev naprave za to napravo.</translation>
+<translation id="3382086682569279540">Račun, ki ga upravljate, bo kmalu odstranjen</translation>
<translation id="3382200254148930874">Ustavitev nadzora ...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Ločilo</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Zdravo, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684">Še <ph name="PERCENTAGE" /> % – <ph name="TIME" /></translation>
<translation id="3637682276779847508">Kartica SIM bo trajno onemogočena, če ne boste vnesli pravilne kode za odklepanje kode PIN.</translation>
-<translation id="363863692969456324">Odpravljanje napak pri črkovanju z izboljšanim preverjanjem črkovanja</translation>
<translation id="3640214691812501263">Želite dodati »<ph name="EXTENSION_NAME" />« za uporabnika <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Naučite Pomočnika prepoznati vaš glas</translation>
<translation id="3644896802912593514">Širina</translation>
<translation id="3645372836428131288">Rahlo premaknite prst, da bo zajet drug del prstnega odtisa.</translation>
<translation id="3648348069317717750">Zaznana naprava USB: <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Iskanje več aplikacij za pisalo</translation>
<translation id="424546999567421758">Zaznana je bila visoka uporaba diska</translation>
<translation id="424726838611654458">Vedno odpri v Adobe Readerju</translation>
-<translation id="4247330672018280062">Besedilo, ki ga vnesete v besedilnih poljih, bo poslano Googlu</translation>
<translation id="4247901771970415646">Ni mogoče sinhronizirati z uporabnikom <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Čakanje na povezavo z omrežjem ...</translation>
<translation id="4249373718504745892">Tej strani je onemogočen dostop do kamere in mikrofona.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Profiliranje je omogočeno</translation>
<translation id="4823484602432206655">Branje in spreminjanje nastavitev funkcij za ljudi s posebnimi potrebami</translation>
<translation id="4823651846660089135">Naprava je samo za branje</translation>
+<translation id="4824958205181053313">Želite preklicati sinhronizacijo?</translation>
<translation id="4827675678516992122">Povezava ni mogoča</translation>
<translation id="4828937774870308359">Avstralsko</translation>
<translation id="4829768588131278040">Nastavi kodo PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Spremeni sliko</translation>
<translation id="5376169624176189338">Kliknite, če se želite vrniti nazaj, za ogled zgodovine pa zadržite</translation>
<translation id="5376931455988532197">Datoteka je prevelika</translation>
+<translation id="5377594097385838788">Brez beleženja zgodovine</translation>
<translation id="537813040452600081">Strani, ki si jih ogledujete v tem oknu, ne bodo prikazane v zgodovini brskalnika in po odjavi v računalniku ne bodo pustile drugih sledi, na primer piškotkov. Datoteke, ki jih prenesete, in zaznamki, ki jih ustvarite, se ne bodo ohranili.</translation>
<translation id="5379140238605961210">Še naprej preprečuj dostop do mikrofona</translation>
<translation id="5379268888377976432">Razveljavi brisanje</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Branje ikon spletnih mest, ki jih obiščete</translation>
<translation id="5417312524372586921">Teme brskalnika</translation>
<translation id="5419294236999569767">Sistemski čas</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Določa ostrino besedila in slik</translation>
<translation id="5422221874247253874">Dostopna točka</translation>
<translation id="5422781158178868512">Zunanje naprave za shranjevanje ni bilo mogoče prepoznati.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 s šifriranjem RSA</translation>
<translation id="5436492226391861498">Čakanje na tunel namestniškega strežnika ...</translation>
<translation id="5436510242972373446">Iskanje po <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Shranite datoteke in ustvarite nov račun.</translation>
<translation id="5438224778284622050">Želite izbrisati datoteke brez povezave?</translation>
<translation id="544083962418256601">Ustvarjanje bližnjic ...</translation>
<translation id="5442228125690314719">Napaka pri izdelavi slike diska. Poskusite znova.</translation>
@@ -3287,6 +3294,8 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
<translation id="5965661248935608907">Določa tudi, katera stran je prikazana, ko kliknete gumb za domačo stran ali iščete v naslovni vrstici.</translation>
<translation id="5971037678316050792">Nadzor nad stanjem vmesnika Bluetooth in seznanjanjem</translation>
<translation id="5972017421290582825">Upravljanje nastavitev za MIDI ...</translation>
+<translation id="597235323114979258">Več ciljev</translation>
+<translation id="5972666587303800813">Nedelujoča storitev</translation>
<translation id="5972708806901999743">Premakni na vrh</translation>
<translation id="5972826969634861500">Zaženi <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Napolnjenost akumulatorja</translation>
@@ -3657,6 +3666,7 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
<translation id="6527303717912515753">Skupna raba</translation>
<translation id="6528513914570774834">Omogoči drugim uporabnikom te naprave uporabo tega omrežja</translation>
<translation id="652948702951888897">Zgodovina v Chromu</translation>
+<translation id="6530186581263215931">Te nastavitve je uveljavil skrbnik</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> – sinhroniziranje ...</translation>
<translation id="6531282281159901044">Obdrži nevarno datoteko</translation>
<translation id="6532101170117367231">Shrani v Google Drive</translation>
@@ -3724,7 +3734,7 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
Če ne želite dodati računa, se prijavite kot gost ali odprite okno za brskanje po spletu brez beleženja zgodovine.
- Vse računa si lahko ogledate in jih upravljate v »Nastavitve -&gt; Računi za Google«.</translation>
+ Vse račune si lahko ogledate in jih upravljate v »Nastavitve -&gt; Računi za Google«.</translation>
<translation id="6639554308659482635">Pomnilnik SQLite</translation>
<translation id="6641138807883536517">Naključno ustvarjeno geslo za varni modul ni na voljo. To je običajno po izvedbi funkcije Powerwash.</translation>
<translation id="6643016212128521049">Počisti</translation>
@@ -3975,7 +3985,6 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
<translation id="7018275672629230621">Branje in spreminjanje zgodovine brskanja</translation>
<translation id="7019805045859631636">Hitro</translation>
<translation id="7022562585984256452">Domača stran je nastavljena.</translation>
-<translation id="702384510542929236">Anonimno pošilja nekatere informacije o sistemu in vsebino strani Googlu</translation>
<translation id="7025190659207909717">Upravljanje mobilne podatkovne storitve</translation>
<translation id="7027125358315426638">Ime zbirke podatkov:</translation>
<translation id="7029809446516969842">Gesla</translation>
@@ -4155,6 +4164,7 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
<translation id="7289225569524511578">Odprite aplikacijo za ozadje</translation>
<translation id="7290242001003353852">Prijavna storitev, ki jo gosti <ph name="SAML_DOMAIN" />, dostopa do vaše kamere.</translation>
<translation id="7290594223351252791">Potrditev registracije</translation>
+<translation id="7292696521213967957">Podatki za odpravljanje napak v Pomočniku</translation>
<translation id="7295662345261934369">Deljenje z drugimi</translation>
<translation id="729583233778673644">Dovoli šifriranje AES in RC4. Če uporabite to možnosti, je tveganje večje, saj šifriranje RC4 ni varno.</translation>
<translation id="7296774163727375165">Pogoji za <ph name="DOMAIN" /></translation>
@@ -4255,7 +4265,6 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
<translation id="7456847797759667638">Odpri mesto ...</translation>
<translation id="7461924472993315131">Pripni</translation>
<translation id="7463006580194749499">Dodaj osebo</translation>
-<translation id="7464902436585505072">Glasovni model »OK Google«</translation>
<translation id="7465778193084373987">Spletni naslov ukinjenega Netscapeovega potrdila</translation>
<translation id="7469894403370665791">Samodejno vzpostavi povezavo s tem omrežjem</translation>
<translation id="747114903913869239">Napaka: Razširitve ni bilo mogoče dekodirati</translation>
@@ -4283,6 +4292,7 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> in podatki, povezani s to aplikacijo, bodo odstranjeni iz te naprave.</translation>
<translation id="7497215489070763236">Strežniško overjeno potrdilo</translation>
<translation id="7497981768003291373">Nimate nedavno zajetih besedilnih dnevnikov za WebRTC.</translation>
+<translation id="7502199377020483660">Če želite te kartice uporabljati v vseh svojih napravah, jih shranite v računu za Google</translation>
<translation id="7502658306369382406">Naslov IPv6</translation>
<translation id="7503191893372251637">Vrsta Netscapeovega potrdila</translation>
<translation id="7503821294401948377">Ikone »<ph name="ICON" />« za dejanje brskalnika ni bilo mogoče naložiti.</translation>
@@ -4380,6 +4390,7 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
<translation id="7663719505383602579">Sprejemnik: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Nepodprta naprava Bluetooth: »<ph name="DEVICE_NAME" />«.</translation>
<translation id="7665369617277396874">Dodaj račun</translation>
+<translation id="7667248760110172428">Zunanja shramba</translation>
<translation id="7671130400130574146">Uporabi sistemsko naslovno vrstico in obrobe</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, na strani storitve <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Pošljite glas Googlu, če želite omogočiti narekovanje v poljubno besedilno polje.</translation>
@@ -4583,6 +4594,7 @@ Poskrbite, da ne boste razkrili morebitnih občutljivih podatkov.</translation>
<translation id="7930294771522048157">Shranjena plačilna sredstva bodo prikazana tu</translation>
<translation id="79312157130859720">Aplikacija <ph name="APP_NAME" /> je v skupno rabo dala vaš zaslon in zvok.</translation>
<translation id="7931318309563332511">Neznano</translation>
+<translation id="7932969338829957666">Mape v skupni rabi so v Linuxu na voljo v <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Vklop zvoka spletnega mesta}one{Vklop zvoka spletnih mest}two{Vklop zvoka spletnih mest}few{Vklop zvoka spletnih mest}other{Vklop zvoka spletnih mest}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> želi predvajati zaščiteno vsebino. Google bo preveril identiteto vaše naprave.</translation>
<translation id="793531125873261495">Napaka pri prenosu navideznega računalnika. Poskusite znova.</translation>
@@ -4674,6 +4686,7 @@ Datoteko s ključem shranite na varnem. Potrebovali jo boste za izdelavo novih r
<translation id="8049705080247101012">Google je z zastavico označil razširitev »<ph name="EXTENSION_NAME" />« kot zlonamerno in preprečil namestitev</translation>
<translation id="8049913480579063185">Ime razširitve</translation>
<translation id="8050038245906040378">Microsoftovo komercialno podpisovanje kode</translation>
+<translation id="8052887694493382350">Ta datoteka je namenjena za računalnike s programsko opremo Windows in ni združljiva z vašo napravo, ki uporablja OS Chrome. <ph name="BEGIN_LINK_HELP" />Več o tem<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Datoteke PKCS #12</translation>
<translation id="8053390638574070785">Znova naloži to stran</translation>
<translation id="8054517699425078995">Ta vrsta datoteke lahko škoduje vaši napravi. Želite vseeno obdržati datoteko <ph name="FILE_NAME" />?</translation>
@@ -4917,6 +4930,7 @@ Datoteko s ključem shranite na varnem. Potrebovali jo boste za izdelavo novih r
<translation id="8438566539970814960">Izboljšanje iskanja in brskanja</translation>
<translation id="8439506636278576865">Ponudi prevajanje strani v tem jeziku</translation>
<translation id="8440630305826533614">Aplikacije za Linux</translation>
+<translation id="8443338615972234259">Ustvarite nov račun za nadzorovanega uporabnika.</translation>
<translation id="8446884382197647889">Več o tem</translation>
<translation id="8447409163267621480">Vključevati morajo ali Ctrl ali Alt</translation>
<translation id="8448729345478502352">Pomanjšajte ali povečajte elemente na zaslonu.</translation>
@@ -4941,6 +4955,7 @@ Datoteko s ključem shranite na varnem. Potrebovali jo boste za izdelavo novih r
<translation id="8468750959626135884">Odklenite napravo <ph name="DEVICE_TYPE" /> s telefonom Android.</translation>
<translation id="8470028084415844044">Če želite dostopati do vseh gesel v vseh napravah, vklopite sinhronizacijo.</translation>
<translation id="8470513973197838199">Shranjena gesla za <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Če želite to kartico uporabljati v vseh svojih napravah, jo shranite v računu za Google</translation>
<translation id="8472623782143987204">podprto s strojno opremo</translation>
<translation id="8473863474539038330">Naslovi in drugo</translation>
<translation id="8475313423285172237">Drug program v računalniku je dodal razširitev, ki lahko spremeni način delovanja Chroma.</translation>
@@ -5016,7 +5031,6 @@ Datoteko s ključem shranite na varnem. Potrebovali jo boste za izdelavo novih r
<translation id="8598453409908276158">Vtičnik, ki ni v peskovniku, je blokiran</translation>
<translation id="8601206103050338563">Preverjanje pristnosti odjemalca TLS WWW</translation>
<translation id="8602851771975208551">Drug program v računalniku je dodal aplikacijo, ki lahko spremeni način delovanja Chroma.</translation>
-<translation id="8604763363205185560">Pomagajte izboljšati Chrome in njegovo varnost</translation>
<translation id="8605428685123651449">Pomnilnik za SQLite</translation>
<translation id="8606726445206553943">Uporaba naprav MIDI</translation>
<translation id="8609465669617005112">Premakni navzgor</translation>
@@ -5192,6 +5206,7 @@ Datoteko s ključem shranite na varnem. Potrebovali jo boste za izdelavo novih r
<translation id="8846141544112579928">Iskanje tipkovnice ...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Ko povežete napravi, se strinjate, da lahko Chromebook:</translation>
+<translation id="8850251000316748990">Več ...</translation>
<translation id="8859057652521303089">Izberite jezik:</translation>
<translation id="8859174528519900719">Podokvir: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excelova preglednica</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_sr.xtb b/chromium/chrome/app/resources/generated_resources_sr.xtb
index b38bd69882c..ac6343b7799 100644
--- a/chromium/chrome/app/resources/generated_resources_sr.xtb
+++ b/chromium/chrome/app/resources/generated_resources_sr.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">Омогући тему</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Прикажи у Chrome веб-продавници</translation>
-<translation id="1761588866118490543">Гласовни модел</translation>
<translation id="176193854664720708">Сензор за отисак прста је у дугмету за напајање. Лагано га додирните било којим прстом.</translation>
<translation id="1763046204212875858">Направите пречице за апликације</translation>
<translation id="1763108912552529023">Настави са истраживањем</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">Шаљите податке о коришћењу и дијагностичке податке. Овај уређај тренутно аутоматски шаље податке о дијагностици, уређају и коришћењу апликација Google-у. То ће помоћи у одржавању стабилности система и апликације и другим подешавањима. Неки обједињени подаци ће такође помоћи Google апликацијама и партнерима, попут Android програмера. То подешавање примењује власник. Ако укључите подешавање додатне активности на вебу и у апликацијама, ти подаци ће се можда чувати на Google налогу. <ph name="BEGIN_LINK1" />Сазнајте више<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip архива</translation>
<translation id="220858061631308971">Унесите овај PIN кôд на уређају „<ph name="DEVICE_NAME" />“:</translation>
+<translation id="2213140827792212876">Уклоните дељење</translation>
+<translation id="2214018885812055163">Дељени директоријуми</translation>
<translation id="2214884991347062907">Нетачна лозинка. Пробајте поново</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 ред није приказан&gt;}one{&lt;<ph name="NUMBER_OF_LINES" /> ред није приказан&gt;}few{&lt;<ph name="NUMBER_OF_LINES" /> реда нису приказана&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> редова није приказано&gt;}}</translation>
<translation id="2217501013957346740">Направите име –</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">Сертификат на чекању</translation>
<translation id="2501797496290880632">Унесите пречицу</translation>
<translation id="2502441965851148920">Аутоматска ажурирања су омогућена. Администратор је онемогућио ручна ажурирања.</translation>
+<translation id="2505127913256479918">Овај налог под надзором ће ускоро бити уклоњен</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Екран #}one{Екран #}few{Екран #}other{Екран #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> од <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Налог Google Play продавнице</translation>
@@ -1371,6 +1373,7 @@
<translation id="304747341537320566">Механизми говора</translation>
<translation id="3053013834507634016">Употреба кључа сертификата</translation>
<translation id="3057861065630527966">Направите резервне копије слика и видео снимака</translation>
+<translation id="3058498974290601450">Можете да укључите синхронизацију у подешавањима у било ком тренутку</translation>
<translation id="3060379269883947824">Омогући услугу Изаберите за говор</translation>
<translation id="3061707000357573562">Услуга крпљења</translation>
<translation id="3065041951436100775">Повратне информације о затварању картице.</translation>
@@ -1562,6 +1565,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> ће бити инсталиран.</translation>
<translation id="3380365263193509176">Непозната грешка</translation>
<translation id="3382073616108123819">Упс! Систем није успео да одреди идентификаторе за овај уређај.</translation>
+<translation id="3382086682569279540">Налог којим управљате ће ускоро бити уклоњен</translation>
<translation id="3382200254148930874">Надзор се зауставља...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Разделник</translation>
@@ -1742,8 +1746,8 @@
<translation id="3636096452488277381">Здраво <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – преостало је <ph name="TIME" /></translation>
<translation id="3637682276779847508">SIM картица ће бити трајно онемогућена ако не унесете исправну шифру за откључавање PIN-а.</translation>
-<translation id="363863692969456324">Исправите правописне грешке помоћу побољшане провере правописа</translation>
<translation id="3640214691812501263">Додај „<ph name="EXTENSION_NAME" />“ за корисника <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Научите Помоћник да вам препозна глас</translation>
<translation id="3644896802912593514">Ширина</translation>
<translation id="3645372836428131288">Мало померите да бисте снимили други део отиска прста.</translation>
<translation id="3648348069317717750">Уређај <ph name="USB_DEVICE_NAME" /> је откривен</translation>
@@ -2060,7 +2064,7 @@
<translation id="4089235344645910861">Подешавања су сачувана. Синхронизација је почела.</translation>
<translation id="4090103403438682346">Омогућите верификовани приступ</translation>
<translation id="4090947011087001172">Желите ли да ресетујете дозволе за сајт <ph name="SITE" />?</translation>
-<translation id="4091434297613116013">листови папира</translation>
+<translation id="4091434297613116013"> лист(ов)а папира</translation>
<translation id="4093955363990068916">Локална датотека:</translation>
<translation id="4095507791297118304">Главни приказ</translation>
<translation id="409579654357498729">Додај у Cloud штампање</translation>
@@ -2143,7 +2147,6 @@
<translation id="4244238649050961491">Пронађи још апликација за писаљку</translation>
<translation id="424546999567421758">Откривена је велика искоришћеност диска</translation>
<translation id="424726838611654458">Увек отвори у Adobe Reader-у</translation>
-<translation id="4247330672018280062">Текст који уносите у поља за текст се шаље Google-у</translation>
<translation id="4247901771970415646">Није успела синхронизација за <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Чека се мрежна веза...</translation>
<translation id="4249373718504745892">Овој страници је забрањен приступ камери и микрофону.</translation>
@@ -2485,6 +2488,7 @@
<translation id="4821935166599369261">&amp;Профилисање је омогућено</translation>
<translation id="4823484602432206655">Читање и мењање подешавања корисника и уређаја</translation>
<translation id="4823651846660089135">Уређај је само за читање</translation>
+<translation id="4824958205181053313">Желите ли да откажете синхронизацију?</translation>
<translation id="4827675678516992122">Повезивање није успело</translation>
<translation id="4828937774870308359">Аустралијски</translation>
<translation id="4829768588131278040">Подеси PIN</translation>
@@ -2867,6 +2871,7 @@
<translation id="5374359983950678924">Промените слику</translation>
<translation id="5376169624176189338">Кликните да бисте отишли назад, кликните задржите се да бисте видели историју</translation>
<translation id="5376931455988532197">Датотека је превелика</translation>
+<translation id="5377594097385838788">Без архивирања</translation>
<translation id="537813040452600081">Странице које видите у овом прозору се неће појављивати у историји прегледача и неће остављати друге трагове, попут колачића, на рачунару после одјављивања. Датотеке које преузмете и обележивачи које направите неће бити сачувани.</translation>
<translation id="5379140238605961210">Настави да блокираш приступ микрофону</translation>
<translation id="5379268888377976432">Опозови брисање</translation>
@@ -2888,6 +2893,7 @@
<translation id="5414566801737831689">Читање икона веб-сајтова које посећујете</translation>
<translation id="5417312524372586921">Теме за прегледач</translation>
<translation id="5419294236999569767">Системско време</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Одређује оштрину текста и слика</translation>
<translation id="5422221874247253874">Приступна тачка</translation>
<translation id="5422781158178868512">Жао нам је, није било могуће препознати спољни меморијски уређај.</translation>
@@ -2908,6 +2914,7 @@
<translation id="5434065355175441495">PKCS #1 RSA шифровање</translation>
<translation id="5436492226391861498">Чекање на прокси тунел...</translation>
<translation id="5436510242972373446">Претражи сајт <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Сачувајте датотеке и отворите нови налог одмах.</translation>
<translation id="5438224778284622050">Желите ли да избришите офлајн датотеке?</translation>
<translation id="544083962418256601">Направи пречице...</translation>
<translation id="5442228125690314719">Грешка при прављењу слике диска. Пробајте поново.</translation>
@@ -3283,6 +3290,8 @@
<translation id="5965661248935608907">Контролише и страницу која се приказује када кликнете на дугме Почетна или претражујете из омнибокса.</translation>
<translation id="5971037678316050792">Контрола стања и упаривања Bluetooth адаптера</translation>
<translation id="5972017421290582825">Управљај MIDI подешавањима...</translation>
+<translation id="597235323114979258">Погледајте још дестинација</translation>
+<translation id="5972666587303800813">Услуга без операције</translation>
<translation id="5972708806901999743">Премести на врх</translation>
<translation id="5972826969634861500">Покрени <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Проценат напуњености батерије</translation>
@@ -3331,7 +3340,7 @@
<translation id="6041155700700864984">Изађи из целог екрана</translation>
<translation id="604124094241169006">Аутоматски</translation>
<translation id="6042169520002885235">Изаберите произвођача и модел штампача</translation>
-<translation id="6042308850641462728">Више</translation>
+<translation id="6042308850641462728">Још</translation>
<translation id="6043317578411397101"><ph name="APP_NAME" /> дели Chrome картицу са <ph name="TAB_NAME" />.</translation>
<translation id="6044805581023976844"><ph name="APP_NAME" /> дели Chrome картицу и звук са <ph name="TAB_NAME" />.</translation>
<translation id="6045021379489914695">Chromebook и Android телефон боље раде заједно. Повежите их да бисте могли да шаљете SMS-ове помоћу рачунара, делите интернет везу и откључавате Chromebook помоћу телефона.<ph name="FOOTNOTE_POINTER" /> <ph name="LINK_BEGIN" />Сазнајте више<ph name="LINK_END" /></translation>
@@ -3653,6 +3662,7 @@
<translation id="6527303717912515753">Дели</translation>
<translation id="6528513914570774834">Дозволите другим корисницима овог уређаја да користе ову мрежу</translation>
<translation id="652948702951888897">Историја Chrome-а</translation>
+<translation id="6530186581263215931">Администратор примењује ова подешавања</translation>
<translation id="653019979737152879">Синхронизује се <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Задржи опасну датотеку</translation>
<translation id="6532101170117367231">Чување на Google диску</translation>
@@ -3971,7 +3981,6 @@
<translation id="7018275672629230621">Читање историје прегледања и мењање те историје</translation>
<translation id="7019805045859631636">Брзо</translation>
<translation id="7022562585984256452">Почетна страница је подешена.</translation>
-<translation id="702384510542929236">Неке системске информације и садржај страница се шаљу анонимно Google-у</translation>
<translation id="7025190659207909717">Управљање услугом мобилног преноса података</translation>
<translation id="7027125358315426638">Назив базе података:</translation>
<translation id="7029809446516969842">Лозинке</translation>
@@ -4151,6 +4160,7 @@
<translation id="7289225569524511578">Отварање апликације за позадине</translation>
<translation id="7290242001003353852">Ова услуга пријављивања, коју хостује <ph name="SAML_DOMAIN" />, приступа вашој камери.</translation>
<translation id="7290594223351252791">Потврђивање регистрације</translation>
+<translation id="7292696521213967957">Информације за отклањање грешака у Асистенту</translation>
<translation id="7295662345261934369">Делите са другима</translation>
<translation id="729583233778673644">Дозвољава AES и RC4 шифровање. Коришћење ове опције вас излаже већем ризику јер су RC4 шифре небезбедне.</translation>
<translation id="7296774163727375165">Услови за <ph name="DOMAIN" /></translation>
@@ -4251,7 +4261,6 @@
<translation id="7456847797759667638">Отвори локацију...</translation>
<translation id="7461924472993315131">Закачи</translation>
<translation id="7463006580194749499">Додај особу</translation>
-<translation id="7464902436585505072">Гласовни модел „Ок Google“</translation>
<translation id="7465778193084373987">URL за опозив Netscape сертификата</translation>
<translation id="7469894403370665791">Аутоматски се повезуј са овом мрежом</translation>
<translation id="747114903913869239">Грешка: Није могуће дешифровати додатак</translation>
@@ -4279,6 +4288,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> и подаци повезани са овом апликацијом биће уклоњени са овог уређаја.</translation>
<translation id="7497215489070763236">CA сертификат сервера</translation>
<translation id="7497981768003291373">Нисте недавно снимили ниједну WebRTC евиденцију текста.</translation>
+<translation id="7502199377020483660">Да бисте користили ове картице на свим уређајима, сачувајте их на Google налогу.</translation>
<translation id="7502658306369382406">IPv6 адреса</translation>
<translation id="7503191893372251637">Тип Netscape сертификата</translation>
<translation id="7503821294401948377">Није могуће учитати икону „<ph name="ICON" />“ за радњу прегледача.</translation>
@@ -4376,6 +4386,7 @@
<translation id="7663719505383602579">Пријемник: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Неподржани Bluetooth уређај: „<ph name="DEVICE_NAME" />“.</translation>
<translation id="7665369617277396874">Додајте налог</translation>
+<translation id="7667248760110172428">Екстерни меморијски простор</translation>
<translation id="7671130400130574146">Користи системску траку наслова и ивице</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, на страници <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Шаљите податке о гласу Google-у да би се омогућило диктирање у свим пољима за текст.</translation>
@@ -4579,6 +4590,7 @@
<translation id="7930294771522048157">Сачувани начини плаћања ће се приказивати овде</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> дели екран и звук.</translation>
<translation id="7931318309563332511">Непознато</translation>
+<translation id="7932969338829957666">Дељени директоријуми су доступни у Linux-у на <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Укључи звук сајта}one{Укључи звук сајтова}few{Укључи звук сајтова}other{Укључи звук сајтова}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> жели да пусти заштићени садржај. Google ће потврдити идентитет уређаја.</translation>
<translation id="793531125873261495">Грешка при преузимању виртуелне машине. Пробајте поново.</translation>
@@ -4670,6 +4682,7 @@
<translation id="8049705080247101012">Google је означио додатак „<ph name="EXTENSION_NAME" />“ као злонамеран и инсталација је спречена</translation>
<translation id="8049913480579063185">Назив додатка</translation>
<translation id="8050038245906040378">Microsoft потписивање комерцијалних кодова</translation>
+<translation id="8052887694493382350">Датотека је осмишљена за рачунар који користи Windows софтвер. Није компатибилна са уређајем, који користи Chrome ОС. <ph name="BEGIN_LINK_HELP" />Сазнајте више<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 датотеке</translation>
<translation id="8053390638574070785">Поново учитај ову страницу</translation>
<translation id="8054517699425078995">Овај тип датотеке може да нашкоди уређају. Желите ли да ипак задржите датотеку <ph name="FILE_NAME" />?</translation>
@@ -4913,6 +4926,7 @@
<translation id="8438566539970814960">Побољшај претраге и прегледање</translation>
<translation id="8439506636278576865">Понуди превод страница на овом језику</translation>
<translation id="8440630305826533614">Linux апликације</translation>
+<translation id="8443338615972234259">Отворите нов налог за корисника под надзором одмах.</translation>
<translation id="8446884382197647889">Сазнајте више</translation>
<translation id="8447409163267621480">Користите или Ctrl или Alt</translation>
<translation id="8448729345478502352">Увећајте или умањите ставке на екрану</translation>
@@ -4937,6 +4951,7 @@
<translation id="8468750959626135884">Откључајте <ph name="DEVICE_TYPE" /> помоћу Android телефона.</translation>
<translation id="8470028084415844044">Да би вам све лозинке били доступне на свим уређајима, укључите синхронизацију.</translation>
<translation id="8470513973197838199">Сачуване лозинке за <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Да бисте користили ову картицу на свим уређајима, сашувајте је на Google налогу</translation>
<translation id="8472623782143987204">хардверски подржан</translation>
<translation id="8473863474539038330">Адресе и друго</translation>
<translation id="8475313423285172237">Други програм на рачунару је додао додатак који може да промени начин на који Chrome функционише.</translation>
@@ -5012,7 +5027,6 @@
<translation id="8598453409908276158">Додатна компонента ван заштићеног окружења је блокирана</translation>
<translation id="8601206103050338563">TLS WWW потврда идентитета клијента</translation>
<translation id="8602851771975208551">Други програм на рачунару је додао апликацију која може да промени начин на који Chrome функционише.</translation>
-<translation id="8604763363205185560">Помозите нам да побољшамо Chrome и његову безбедност</translation>
<translation id="8605428685123651449">SQLite меморија</translation>
<translation id="8606726445206553943">користи MIDI уређаје</translation>
<translation id="8609465669617005112">Премести нагоре</translation>
@@ -5188,6 +5202,7 @@
<translation id="8846141544112579928">Тражимо тастатуру...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Када повежете уређаје, прихватате да Chromebook може:</translation>
+<translation id="8850251000316748990">Прикажи више...</translation>
<translation id="8859057652521303089">Изаберите језик:</translation>
<translation id="8859174528519900719">Подоквир: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel табела</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_sv.xtb b/chromium/chrome/app/resources/generated_resources_sv.xtb
index a4eb482ce97..27c017f79e1 100644
--- a/chromium/chrome/app/resources/generated_resources_sv.xtb
+++ b/chromium/chrome/app/resources/generated_resources_sv.xtb
@@ -517,7 +517,6 @@
<translation id="175772926354468439">Aktivera tema</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Visa i Chrome Web Store</translation>
-<translation id="1761588866118490543">Röstmodell</translation>
<translation id="176193854664720708">Fingeravtryckssensorn sitter på strömbrytaren. Tryck lätt på den med ett finger.</translation>
<translation id="1763046204212875858">Skapa programgenvägar</translation>
<translation id="1763108912552529023">Fortsätt att utforska</translation>
@@ -814,6 +813,8 @@
<translation id="220792432208469595">Skicka diagnostik- och användningsdata. Den här enheten skickar för närvarande diagnostikdata, enhetsdata och data om appanvändning till Google automatiskt. Denna data används till att förbättra systemets och apparnas stabilitet med mera. Viss samlad data används även till att förbättra appar från Google och partner, till exempel Android-utvecklare. Ägaren har gjort denna inställning obligatorisk. Om ytterligare webb- och appaktivitet har aktiverats kan denna data sparas i Google-kontot. <ph name="BEGIN_LINK1" />Läs mer<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip-arkiv</translation>
<translation id="220858061631308971">Ange den här PIN-koden på <ph name="DEVICE_NAME" />:</translation>
+<translation id="2213140827792212876">Ta bort delning</translation>
+<translation id="2214018885812055163">Delade mappar</translation>
<translation id="2214884991347062907">Fel lösenord. Försök igen.</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 rad visas inte&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> rader visas inte&gt;}}</translation>
<translation id="2217501013957346740">Skapa ett namn –</translation>
@@ -1014,6 +1015,7 @@
<translation id="2501173422421700905">Certifikatet är avstängt</translation>
<translation id="2501797496290880632">Ange en genväg</translation>
<translation id="2502441965851148920">Automatiska uppdateringar har aktiverats. Manuella uppdateringar har inaktiverats av administratören.</translation>
+<translation id="2505127913256479918">Det här kontrollerade kontot tas snart bort</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Skärm #}other{Skärm #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> av <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Konto i Google Play Butik</translation>
@@ -1374,6 +1376,7 @@
<translation id="304747341537320566">Talmotorer</translation>
<translation id="3053013834507634016">Certifikatnyckelanvändning</translation>
<translation id="3057861065630527966">Säkerhetskopiera foton och videor</translation>
+<translation id="3058498974290601450">Du kan när som helst inaktivera synkroniseringen i inställningarna</translation>
<translation id="3060379269883947824">Aktivera Textuppläsning</translation>
<translation id="3061707000357573562">Tjänst för programkorrigering</translation>
<translation id="3065041951436100775">Feedback vid stängd flik.</translation>
@@ -1565,6 +1568,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> installeras.</translation>
<translation id="3380365263193509176">Okänt fel</translation>
<translation id="3382073616108123819">Hoppsan! Det gick inte att fastställa enhets-id för den här enheten.</translation>
+<translation id="3382086682569279540">Kontot du hanterar tas snart bort</translation>
<translation id="3382200254148930874">Föräldrakontroll avslutas …</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" /> %</translation>
<translation id="338583716107319301">Avgränsare</translation>
@@ -1745,8 +1749,8 @@
<translation id="3636096452488277381">Hejsan <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" /> % – <ph name="TIME" /> kvar</translation>
<translation id="3637682276779847508">SIM-kortet inaktiveras permanent om du inte anger korrekt upplåsningskod för pinkoden.</translation>
-<translation id="363863692969456324">Åtgärda stavfel med den förbättrade stavningskontrollen</translation>
<translation id="3640214691812501263">Vill du lägga till <ph name="EXTENSION_NAME" /> för <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Lär assistenten att känna igen din röst</translation>
<translation id="3644896802912593514">Bredd</translation>
<translation id="3645372836428131288">Flytta fingret något så att en annan del av fingeravtrycket registreras.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> hittades</translation>
@@ -2146,7 +2150,6 @@
<translation id="4244238649050961491">Hitta fler appar för e-penna</translation>
<translation id="424546999567421758">Intensiv användning av disken har upptäckts</translation>
<translation id="424726838611654458">Öppna alltid i Adobe Reader</translation>
-<translation id="4247330672018280062">Det du skriver i textfält skickas till Google</translation>
<translation id="4247901771970415646">Det gick inte att synkronisera med <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Väntar på nätverksanslutning ...</translation>
<translation id="4249373718504745892">Den här sidan har blockerats och kan inte komma åt kameran och mikrofonen.</translation>
@@ -2488,6 +2491,7 @@
<translation id="4821935166599369261">&amp;Profilering aktiverad</translation>
<translation id="4823484602432206655">Läsa och ändra användarinställningar och enhetsinställningar</translation>
<translation id="4823651846660089135">Enheten är skrivskyddad</translation>
+<translation id="4824958205181053313">Vill du avbryta synkroniseringen?</translation>
<translation id="4827675678516992122">Det gick inte att ansluta</translation>
<translation id="4828937774870308359">Australiensisk</translation>
<translation id="4829768588131278040">Konfigurera pinkod</translation>
@@ -2698,7 +2702,7 @@
<translation id="5127805178023152808">Synkronisering är av</translation>
<translation id="5127881134400491887">Hantera nätverksanslutningar</translation>
<translation id="512903556749061217">ansluten</translation>
-<translation id="5133483819862530305">Soluppgång till solnedgång</translation>
+<translation id="5133483819862530305">Solnedgång till soluppgång</translation>
<translation id="5135533361271311778">Det gick inte att skapa bokmärkesobjektet.</translation>
<translation id="5137501176474113045">Ta bort det här objektet</translation>
<translation id="5138227688689900538">Visa färre</translation>
@@ -2870,6 +2874,7 @@
<translation id="5374359983950678924">Byt bild</translation>
<translation id="5376169624176189338">Klicka för att återvända, håll ned för att se historik</translation>
<translation id="5376931455988532197">Filen är för stor</translation>
+<translation id="5377594097385838788">Inkognito</translation>
<translation id="537813040452600081">Sidor du visar i det här fönstret syns inte i webbläsarhistoriken och de lämnar inga andra spår efter sig (till exempel cookies) på datorn när du har loggat ut till. Filer som du laddar ned och bokmärken du skapar sparas inte.</translation>
<translation id="5379140238605961210">Fortsätt att blockera mikrofonåtkomsten</translation>
<translation id="5379268888377976432">Ångra borttagning</translation>
@@ -2891,6 +2896,7 @@
<translation id="5414566801737831689">Läsa in ikonerna för de webbplatser du besöker</translation>
<translation id="5417312524372586921">Webbläsarteman</translation>
<translation id="5419294236999569767">Systemtid</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Ställer in hur skarp bilden och texten ska vara</translation>
<translation id="5422221874247253874">Åtkomstpunkt</translation>
<translation id="5422781158178868512">Den externa lagringsenheten kunde tyvärr inte identifieras.</translation>
@@ -2911,6 +2917,7 @@
<translation id="5434065355175441495">PKCS #1 RSA-kryptering</translation>
<translation id="5436492226391861498">Väntar på proxytunnel...</translation>
<translation id="5436510242972373446">Sök <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Spara dina filer och skapa ett nytt konto nu.</translation>
<translation id="5438224778284622050">Vill du radera offlinefiler?</translation>
<translation id="544083962418256601">Skapa genvägar ...</translation>
<translation id="5442228125690314719">Det gick inte att skapa skivavbildningen. Försök igen.</translation>
@@ -3284,6 +3291,8 @@
<translation id="5965661248935608907">Det styr också vilken sida som visas när du klickar på hemknappen eller söker i adressfältet.</translation>
<translation id="5971037678316050792">Styr status och koppling för Bluetooth-adaptern</translation>
<translation id="5972017421290582825">Hantera MIDI-inställningar ...</translation>
+<translation id="597235323114979258">Se fler utskriftsmål</translation>
+<translation id="5972666587303800813">Testtjänst utan funktion</translation>
<translation id="5972708806901999743">Flytta högst upp</translation>
<translation id="5972826969634861500">Starta <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Batteriets laddning i procent</translation>
@@ -3654,6 +3663,7 @@
<translation id="6527303717912515753">Dela</translation>
<translation id="6528513914570774834">Tillåt att andra användare på den här enheten kan använda det här nätverket</translation>
<translation id="652948702951888897">Chrome-historik</translation>
+<translation id="6530186581263215931">Administratören har låst inställningarna</translation>
<translation id="653019979737152879">Synkroniserar <ph name="FILE_NAME" /> ...</translation>
<translation id="6531282281159901044">Behåll den farliga filen</translation>
<translation id="6532101170117367231">Spara på Google Drive</translation>
@@ -3972,7 +3982,6 @@
<translation id="7018275672629230621">Läsa och ändra din webbhistorik</translation>
<translation id="7019805045859631636">Snabb</translation>
<translation id="7022562585984256452">Startsidan har ställts in.</translation>
-<translation id="702384510542929236">Viss systeminformation och visst sidinnehåll skickas anonymt till Google</translation>
<translation id="7025190659207909717">Hantering av mobil datatjänst</translation>
<translation id="7027125358315426638">Databasnamn:</translation>
<translation id="7029809446516969842">Lösenord</translation>
@@ -4152,6 +4161,7 @@
<translation id="7289225569524511578">Öppna bakgrundsappen</translation>
<translation id="7290242001003353852">Inloggningstjänsten som tillhandahålls av <ph name="SAML_DOMAIN" /> använder din kamera.</translation>
<translation id="7290594223351252791">Bekräfta registrering</translation>
+<translation id="7292696521213967957">Felsökningsinformation för assistenten</translation>
<translation id="7295662345261934369">Dela med andra</translation>
<translation id="729583233778673644">Tillåt AES- och RC4-kryptering. Det här alternativet är mer riskabelt eftersom RC4-chiffer är osäkra.</translation>
<translation id="7296774163727375165">Villkor för <ph name="DOMAIN" /></translation>
@@ -4252,7 +4262,6 @@
<translation id="7456847797759667638">Öppna plats...</translation>
<translation id="7461924472993315131">Fäst</translation>
<translation id="7463006580194749499">Lägg till person</translation>
-<translation id="7464902436585505072">Röstmodell för Ok Google</translation>
<translation id="7465778193084373987">Återkallandeadress för Netscape-certifikat</translation>
<translation id="7469894403370665791">Anslut automatiskt till det här nätverket.</translation>
<translation id="747114903913869239">Fel: det går inte att avkoda tillägget</translation>
@@ -4280,6 +4289,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> och tillhörande data tas bort från den här enheten.</translation>
<translation id="7497215489070763236">Serverns CA-certifikat</translation>
<translation id="7497981768003291373">Du har inga nyligen registrerade WebRTC-textloggar.</translation>
+<translation id="7502199377020483660">Spara de här korten i Google-kontot om du vill kunna använda dem på alla enheter</translation>
<translation id="7502658306369382406">IPv6-adress</translation>
<translation id="7503191893372251637">Certifieringstyp för Netscape</translation>
<translation id="7503821294401948377">Det gick inte att läsa in ikonen <ph name="ICON" /> för webbläsaråtgärden.</translation>
@@ -4377,6 +4387,7 @@
<translation id="7663719505383602579">Mottagare: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Bluetooth-enhet som inte stöds: <ph name="DEVICE_NAME" />.</translation>
<translation id="7665369617277396874">Lägg till konto</translation>
+<translation id="7667248760110172428">Extern lagring</translation>
<translation id="7671130400130574146">Använd systemets inställningar för namnlist och ramar</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> på <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Skicka det du säger till Google så att du kan tala in text i vilket textfält som helst.</translation>
@@ -4580,6 +4591,7 @@
<translation id="7930294771522048157">Sparade betalningsmetoder visas här</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> delar skärmen och ljudet.</translation>
<translation id="7931318309563332511">okänt</translation>
+<translation id="7932969338829957666">Delade mappar finns i <ph name="BASE_DIR" /> i Linux.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Sätt på webbplatsens ljud}other{Sätt på webbplatsernas ljud}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> vill spela upp skyddat innehåll. Enhetens identitet verifieras av Google.</translation>
<translation id="793531125873261495">Det gick inte att ladda ned den virtuella maskinen. Försök igen.</translation>
@@ -4671,6 +4683,7 @@ Spara nyckelfilen på ett säkert ställe. Den behövs om du ska skapa nya versi
<translation id="8049705080247101012">Google har flaggat <ph name="EXTENSION_NAME" /> som skadligt och installationen har förhindrats</translation>
<translation id="8049913480579063185">Tilläggets namn</translation>
<translation id="8050038245906040378">Microsofts kommersiella kodsignering</translation>
+<translation id="8052887694493382350">Den här filen är avsedd för en dator med Windows-programvara. Den är inte kompatibel med din enhet, som har Chrome OS. <ph name="BEGIN_LINK_HELP" />Läs mer<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12-filer</translation>
<translation id="8053390638574070785">Hämta sidan igen</translation>
<translation id="8054517699425078995">Den här typen av fil kan skada enheten. Vill du behålla <ph name="FILE_NAME" /> ändå?</translation>
@@ -4914,6 +4927,7 @@ Spara nyckelfilen på ett säkert ställe. Den behövs om du ska skapa nya versi
<translation id="8438566539970814960">Förbättra sökningar och surfandet</translation>
<translation id="8439506636278576865">Erbjud att översätta sidor på detta språk</translation>
<translation id="8440630305826533614">Linux-appar</translation>
+<translation id="8443338615972234259">Skapa ett nytt konto åt den kontrollerade användaren nu.</translation>
<translation id="8446884382197647889">Läs mer</translation>
<translation id="8447409163267621480">Ctrl- eller alt-tangenten måste finnas med</translation>
<translation id="8448729345478502352">Gör objekt på skärmen mindre eller större</translation>
@@ -4938,6 +4952,7 @@ Spara nyckelfilen på ett säkert ställe. Den behövs om du ska skapa nya versi
<translation id="8468750959626135884">Lås upp <ph name="DEVICE_TYPE" /> med Android-mobilen.</translation>
<translation id="8470028084415844044">Aktivera synkronisering om du vill ha tillgång till alla lösenord oavsett vilken enhet du använder.</translation>
<translation id="8470513973197838199">Sparade lösenord för <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Spara det här kortet i Google-kontot om du vill kunna använda det på alla enheter</translation>
<translation id="8472623782143987204">maskinvarustödd</translation>
<translation id="8473863474539038330">Adresser och annat</translation>
<translation id="8475313423285172237">Ett annat program i datorn har lagt till ett tillägg som kan ändra hur Chrome fungerar.</translation>
@@ -5013,7 +5028,6 @@ Spara nyckelfilen på ett säkert ställe. Den behövs om du ska skapa nya versi
<translation id="8598453409908276158">Plugin utanför sandlåda har blockerats</translation>
<translation id="8601206103050338563">TLS WWW-klientautentisering</translation>
<translation id="8602851771975208551">Ett annat program i datorn har lagt till en app som kan ändra hur Chrome fungerar.</translation>
-<translation id="8604763363205185560">Hjälp till att göra Chrome bättre och säkrare</translation>
<translation id="8605428685123651449">SQLite-minne</translation>
<translation id="8606726445206553943">Använda MIDI-enheter</translation>
<translation id="8609465669617005112">Flytta upp</translation>
@@ -5189,6 +5203,7 @@ Spara nyckelfilen på ett säkert ställe. Den behövs om du ska skapa nya versi
<translation id="8846141544112579928">Söker efter tangentbord …</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">När du ansluter enheter godkänner du att Chromebook</translation>
+<translation id="8850251000316748990">Visa fler …</translation>
<translation id="8859057652521303089">Välj språk:</translation>
<translation id="8859174528519900719">Underram: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel-kalkylark</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_sw.xtb b/chromium/chrome/app/resources/generated_resources_sw.xtb
index 9477d64ad17..3616bc3a80a 100644
--- a/chromium/chrome/app/resources/generated_resources_sw.xtb
+++ b/chromium/chrome/app/resources/generated_resources_sw.xtb
@@ -403,7 +403,7 @@
<translation id="1593594475886691512">Inaumbiza...</translation>
<translation id="159359590073980872">Akiba ya Picha</translation>
<translation id="1593926297800505364">Hifadhi njia ya kulipa</translation>
-<translation id="1595492813686795610">Inaweka toleo jipya la Linux.</translation>
+<translation id="1595492813686795610">Inaweka toleo jipya la Linux</translation>
<translation id="1598233202702788831">Sasisho zimezimwa na msimamizi wako.</translation>
<translation id="1600857548979126453">Fikia sehemu ya nyuma ya kitatuzi ukurasa</translation>
<translation id="1601560923496285236">Tekeleza</translation>
@@ -515,7 +515,6 @@
<translation id="175772926354468439">Washa mandhari</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Angalia katika Duka la Chrome kwenye Wavuti</translation>
-<translation id="1761588866118490543">Muundo wa sauti</translation>
<translation id="176193854664720708">Kitambua alama ya kidole kiko kwenye kitufe cha kuwasha/kuzima. Kiguse taratibu ukitumia kidole chako.</translation>
<translation id="1763046204212875858">Unda mikato ya programu</translation>
<translation id="1763108912552529023">Endelea kugundua</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">Tuma data ya matumizi na uchunguzi. Kwa sasa, kifaa hiki kinatuma kiotomatiki data ya uchunguzi na matumizi ya programu na kifaa kwa Google. Maelezo haya yatatusaidia kuboresha uthabiti wa programu na mfumo na maboresho mengine. Baadhi ya maelezo yaliyojumlishwa pia yatasaidia programu za Google na washirika kama vile wasanidi programu za Android. Mipangilio hii inatekelezwa na mmiliki. Ikiwa umewasha mipangilio ya historia ya Shughuli za ziada kwenye Wavuti na Programu, huenda data hii itahifadhiwa kwenye Akaunti yako ya Google. <ph name="BEGIN_LINK1" />Pata maelezo zaidi<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Kumbukumbu ya Zip</translation>
<translation id="220858061631308971">Tafadhali weka nambari hii ya PIN kwenye "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Ondoa faili ya kushiriki</translation>
+<translation id="2214018885812055163">Folda zinazoshirikiwa</translation>
<translation id="2214884991347062907">Nenosiri si sahihi, jaribu tena</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;Haijaonyesha mstari wa 1&gt;}other{&lt;Haijaonyesha mistari <ph name="NUMBER_OF_LINES" />&gt;}}</translation>
<translation id="2217501013957346740">Unda jina -</translation>
@@ -1012,6 +1013,7 @@
<translation id="2501173422421700905">Cheti Kimesimamishwa</translation>
<translation id="2501797496290880632">Charaza mkato</translation>
<translation id="2502441965851148920">Sasisho za kiotomatiki zimewashwa. Sasisho za kujiwekea zimezimwa na msimamizi wako.</translation>
+<translation id="2505127913256479918">Akaunti hii inayodhibitiwa itaondolewa hivi karibuni</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Skrini ya #}other{Skrini ya #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> ya <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Akaunti ya Duka la Google Play</translation>
@@ -1371,6 +1373,7 @@
<translation id="304747341537320566">Mitambo ya Sauti</translation>
<translation id="3053013834507634016">Matumizi ya Ufunguo wa Cheti</translation>
<translation id="3057861065630527966">Weka hifadhi rudufu ya picha na video zako</translation>
+<translation id="3058498974290601450">Unaweza kuwasha kipengele cha kusawazisha wakati wowote katika mipangilio</translation>
<translation id="3060379269883947824">Washa kipengele cha chagua ili izungumze</translation>
<translation id="3061707000357573562">Huduma ya Kurekebisha</translation>
<translation id="3065041951436100775">Majibu ya kichupo kilichoangamizwa.</translation>
@@ -1559,6 +1562,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> itasakinishwa.</translation>
<translation id="3380365263193509176">Hitilafu isiyojulikana</translation>
<translation id="3382073616108123819">Lo! Mfumo haukuweza kutambua vitambuaji vya kifaa kwa kifaa hiki.</translation>
+<translation id="3382086682569279540">Tutaondoa akaunti unayodhibiti hivi karibuni</translation>
<translation id="3382200254148930874">Inakomesha usimamizi...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Kitenganishi</translation>
@@ -1739,8 +1743,8 @@
<translation id="3636096452488277381">Hujambo, <ph name="USER_GIVEN_NAME" /> .</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - Zimesalia <ph name="TIME" /></translation>
<translation id="3637682276779847508">SIM kadi yako itafungwa kabisa ikiwa hutaweka Ufunguo sahihi wa Kufungua PIN.</translation>
-<translation id="363863692969456324">Rekebisha makosa ya tahajia ukitumia kikagua maendelezo kilichoboreshwa</translation>
<translation id="3640214691812501263">Ungependa kuongeza "<ph name="EXTENSION_NAME" />" kwa <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Ifunze programu ya Mratibu kutambua sauti yako</translation>
<translation id="3644896802912593514">Upana</translation>
<translation id="3645372836428131288">Sogeza kidogo ili unase sehemu tofauti ya alama ya kidole.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> kimegunduliwa</translation>
@@ -2138,7 +2142,6 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="4244238649050961491">Pata programu zaidi za stylus</translation>
<translation id="424546999567421758">Utumiaji mkubwa wa diski umegunduliwa</translation>
<translation id="424726838611654458">Fungua katika Adobe Reader wakati wowote</translation>
-<translation id="4247330672018280062">Tutatuma kwa Google maelezo unayoandika katika sehemu za maandishi</translation>
<translation id="4247901771970415646">Imeshindwa kusawazisha kwenye <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Inasubiri muunganisho kwa mtandao...</translation>
<translation id="4249373718504745892">Ukurasa huu umezuiwa kufikia kamera na maikrofoni yako.</translation>
@@ -2480,6 +2483,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="4821935166599369261">&amp;Uwekaji Wasifu Umewezeshwa</translation>
<translation id="4823484602432206655">Soma na ubadilishe mipangilio ya mtumiaji na kifaa</translation>
<translation id="4823651846660089135">Kifaa ni cha kusoma tu</translation>
+<translation id="4824958205181053313">Ungependa kughairi usawazishaji?</translation>
<translation id="4827675678516992122">Imeshindwa kuunganisha</translation>
<translation id="4828937774870308359">Kiaustralia</translation>
<translation id="4829768588131278040">Unda PIN</translation>
@@ -2862,6 +2866,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="5374359983950678924">Badilisha picha</translation>
<translation id="5376169624176189338">Bofya ili urudi nyuma, shikilia ili uone historia</translation>
<translation id="5376931455988532197">Faili ni kubwa mno</translation>
+<translation id="5377594097385838788">Hali fiche</translation>
<translation id="537813040452600081">Kurasa unazoangalia katika dirisha hili hazitaonekana katika historia ya kivinjari na hazitaacha alama nyingine, kama vile vidakuzi, kwenye kompyuta baada ya wewe kuondoka katika akaunti. Faili unazopakua na alamisho unazounda hazitahifadhiwa.</translation>
<translation id="5379140238605961210">Endelea kuzuia ufikiaji wa maikrofoni</translation>
<translation id="5379268888377976432">Tendua Kufuta</translation>
@@ -2883,6 +2888,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="5414566801737831689">Soma aikoni za tovuti unazozitembelea</translation>
<translation id="5417312524372586921">Vinjari mandhari</translation>
<translation id="5419294236999569767">Saa ya mfumo</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Hubainisha ung'aavu wa maandishi na picha</translation>
<translation id="5422221874247253874">Lango la Mtandao</translation>
<translation id="5422781158178868512">Samahani, kifaa chako cha hifadhi ya nje hakingeweza kutambuliwa.</translation>
@@ -2903,6 +2909,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="5434065355175441495">PKCS #1 Usimbaji wa RSA</translation>
<translation id="5436492226391861498">Inasubiri handaki la proksi...</translation>
<translation id="5436510242972373446">Tafuta <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Tafadhali hifadhi faili zako halafu ufungue akaunti mpya.</translation>
<translation id="5438224778284622050">Ungependa kufuta faili za nje ya mtandao?</translation>
<translation id="544083962418256601">Unda njia mikato...</translation>
<translation id="5442228125690314719">Hitilafu imetokea wakati wa kuunda picha ya diski. Tafadhali jaribu tena.</translation>
@@ -3276,6 +3283,8 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="5965661248935608907">Pia inadhibiti ukurasa unaoonyeshwa unapobofya kitufe cha Mwanzo au unapotafuta kutoka Sanduku Kuu.</translation>
<translation id="5971037678316050792">Dhibiti hali na uoanishaji wa adapta ya Bluetooth</translation>
<translation id="5972017421290582825">Dhibiti mipangilio ya MIDI...</translation>
+<translation id="597235323114979258">Ona maeneo zaidi</translation>
+<translation id="5972666587303800813">Huduma ya No-op</translation>
<translation id="5972708806901999743">Sogeza juu</translation>
<translation id="5972826969634861500">Anzisha <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Asilimia ya Kuchaji Betri</translation>
@@ -3646,6 +3655,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="6527303717912515753">Shiriki</translation>
<translation id="6528513914570774834">Waruhusu watumiaji wengine wa kifaa hiki kutumia mtandao huu</translation>
<translation id="652948702951888897">Historia ya Chrome</translation>
+<translation id="6530186581263215931">Mipangilio hii inatekelezwa na msimamizi wako</translation>
<translation id="653019979737152879">Inasawazisha <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Hifadhi faili hatari</translation>
<translation id="6532101170117367231">Hifadhi katika Hifadhi ya Google</translation>
@@ -3964,7 +3974,6 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="7018275672629230621">Kusoma na kubadilisha historia yako ya kuvinjari</translation>
<translation id="7019805045859631636">Haraka</translation>
<translation id="7022562585984256452">Ukurasa wako wa mwanzo umewekwa.</translation>
-<translation id="702384510542929236">Hutuma kwa Google baadhi ya maelezo na maudhui ya ukurasa bila kutambulisha mhusika.</translation>
<translation id="7025190659207909717">Udhibiti wa huduma ya data ya simu ya mkononi</translation>
<translation id="7027125358315426638">Jina la hifadhidata:</translation>
<translation id="7029809446516969842">Manenosiri</translation>
@@ -4144,6 +4153,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="7289225569524511578">Fungua programu ya mandhari</translation>
<translation id="7290242001003353852">Huduma hii ya kuingia katika akaunti, inayopangishwa na <ph name="SAML_DOMAIN" />, ina idhini ya kufikia kamera yako.</translation>
<translation id="7290594223351252791">Thibitisha usajili</translation>
+<translation id="7292696521213967957">Maelezo ya kusaidia kutatua programu ya Mratibu</translation>
<translation id="7295662345261934369">Shiriki na wengine</translation>
<translation id="729583233778673644">Ruhusu usimbaji wa AES na RC4. Kutumia chaguo hili huongeza uwezekano wa hatari, kwa kuwa misimbo ya RC45 si salama.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> Masharti</translation>
@@ -4244,7 +4254,6 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="7456847797759667638">Fungua Mahali...</translation>
<translation id="7461924472993315131">Bana</translation>
<translation id="7463006580194749499">Ongeza mtumiaji mwingine</translation>
-<translation id="7464902436585505072">Muundo wa sauti ya "Ok Google"</translation>
<translation id="7465778193084373987">URL ya Kughairi Cheti cha Netscape</translation>
<translation id="7469894403370665791">Unganisha otomatiki kwenye mtandao huu</translation>
<translation id="747114903913869239">Hitilafu: Haikuweza kufumbua kiendelezi</translation>
@@ -4272,6 +4281,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> na data inayohusishwa nayo itaondolewa kwenye kifaa hiki.</translation>
<translation id="7497215489070763236">Cheti cha CA cha Seva</translation>
<translation id="7497981768003291373">Huna kumbukumbu za maandishi ya WebRTC uliyorekodi hivi majuzi.</translation>
+<translation id="7502199377020483660">Ili utumie kadi hizi kwenye vifaa vyako vyote, zihifadhi kwenye Akaunti yako ya Google</translation>
<translation id="7502658306369382406">Anwani ya IPv6</translation>
<translation id="7503191893372251637">Aina ya Cheti cha Netscape</translation>
<translation id="7503821294401948377">Aikoni '<ph name="ICON" />' haikuweza kupakiwa kwa kitendo cha kivinjari.</translation>
@@ -4369,6 +4379,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="7663719505383602579">Kipokezi: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Kifaa cha Bluetooth kisichoweza kutumiwa: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Ongeza akaunti</translation>
+<translation id="7667248760110172428">Hifadhi ya nje</translation>
<translation id="7671130400130574146">Tumia upau jina na mipaka ya mfumo</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, katika <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Tuma sauti yako kwa Google ili uruhusu kuandika kwa kutamka katika sehemu ya maandishi.</translation>
@@ -4574,6 +4585,7 @@ Ungependa kuanza <ph name="CONTROL_PANEL_APPLET_NAME" />?</translation>
<translation id="7930294771522048157">Njia za kulipa ulizohifadhi zitaonekana hapa</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> inashiriki skrini na sauti yako.</translation>
<translation id="7931318309563332511">Haijulikani</translation>
+<translation id="7932969338829957666">Folda zinazoshirikiwa zinapatikana kwenye Linux katika <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Washa Sauti ya Tovuti}other{Washa Sauti za Tovuti}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> inataka kucheza maudhui yanayolindwa. Kitambulisho cha kifaa chako kitathibitishwa na Google.</translation>
<translation id="793531125873261495">Hitilafu imetokea wakati wa kupakua mashine dhahania. Tafadhali jaribu tena.</translation>
@@ -4665,6 +4677,7 @@ Weka faili yako ya funguo mahali salama. Utaihitaji kuunda matoleo mapya ya kien
<translation id="8049705080247101012">Google imeripoti kuwa "<ph name="EXTENSION_NAME" />" ni programu hasidi na imezuia kuisakinisha</translation>
<translation id="8049913480579063185">Jina la Kiendelezi</translation>
<translation id="8050038245906040378">Uwekaji Sahihi kwa Misimbo kwa Biashara kutoka Microsoft</translation>
+<translation id="8052887694493382350">Faili hii imeundwa kwa ajili ya kompyuta inayotumia programu ya Windows. Kwa hivyo haioani na kifaa chako kinachotumia Mfumo wa Uendeshaji wa Chrome. <ph name="BEGIN_LINK_HELP" />Pata maelezo zaidi<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Faili PKCS #12</translation>
<translation id="8053390638574070785">Pakia Ukurasa Huu Upya</translation>
<translation id="8054517699425078995">Aina hii ya faili inaweza kudhuru kifaa chako. Je, ungetaka kupakua <ph name="FILE_NAME" /> licha ya hayo?</translation>
@@ -4909,6 +4922,7 @@ Huenda watu wengine wenye miunganisho ya polepole hawataona maudhui yako.</trans
<translation id="8438566539970814960">Boresha utafutaji na kuvinjari</translation>
<translation id="8439506636278576865">Jitolee kutafsiri kurasa katika lugha hii</translation>
<translation id="8440630305826533614">Programu za Linux</translation>
+<translation id="8443338615972234259">Tafadhali fungua akaunti ya mtumiaji unayemsimamia sasa.</translation>
<translation id="8446884382197647889">Pata Maelezo Zaidi</translation>
<translation id="8447409163267621480">Jumuisha kitufe cha Ctrl au Alt</translation>
<translation id="8448729345478502352">Ongeza au upunguze ukubwa wa vipengee vilivyo kwenye skrini yako</translation>
@@ -4933,6 +4947,7 @@ Huenda watu wengine wenye miunganisho ya polepole hawataona maudhui yako.</trans
<translation id="8468750959626135884">Fungua kifaa chako cha <ph name="DEVICE_TYPE" /> kwa kutumia simu yako ya Android.</translation>
<translation id="8470028084415844044">Ili upate manenosiri yako yote kwenye vifaa vyako vyote, washa usawazishaji.</translation>
<translation id="8470513973197838199">Manenosiri yaliyohifadhiwa ya <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Ili utumie kadi hii kwenye vifaa vyako vyote, ihifadhi kwenye Akaunti yako ya Google.</translation>
<translation id="8472623782143987204">maunzi-imechelezwa</translation>
<translation id="8473863474539038330">Anwani na zaidi</translation>
<translation id="8475313423285172237">Programu nyingine kwenye kompyuta yako iliongeza kiendelezi ambacho kinaweza kubadilisha jinsi Chrome inavyofanya kazi.</translation>
@@ -5008,7 +5023,6 @@ Huenda watu wengine wenye miunganisho ya polepole hawataona maudhui yako.</trans
<translation id="8598453409908276158">Ufikiaji wa programu jalizi isiyo na utaratibu wa kuwekea vikwazo umezuiwa</translation>
<translation id="8601206103050338563">Uthibitishaji wa Teja wa TLS WWW</translation>
<translation id="8602851771975208551">Programu nyingine kwenye kompyuta yako iliongeza programu ambayo inaweza kubadilisha jinsi Chrome inavyofanya kazi.</translation>
-<translation id="8604763363205185560">Tusaidie tuboreshe Chrome na usalama wake</translation>
<translation id="8605428685123651449">Kumbukumbu ya SQLite</translation>
<translation id="8606726445206553943">Tumia vifaa vyako vya MIDI</translation>
<translation id="8609465669617005112">Songa juu</translation>
@@ -5184,6 +5198,7 @@ Huenda watu wengine wenye miunganisho ya polepole hawataona maudhui yako.</trans
<translation id="8846141544112579928">Inatafuta kibodi...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Unapounganisha vifaa vyako, unakubali kwamba Chromebook yako inaweza:</translation>
+<translation id="8850251000316748990">Ona mengine...</translation>
<translation id="8859057652521303089">Chagua lugha yako:</translation>
<translation id="8859174528519900719">Fremu ndogo: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Lahajedwali la Excel</translation>
@@ -5204,7 +5219,7 @@ Huenda watu wengine wenye miunganisho ya polepole hawataona maudhui yako.</trans
<translation id="8883847527783433352">Sawazisha katika Akaunti Nyingine</translation>
<translation id="8885197664446363138">Smart Lock haipatikani</translation>
<translation id="88870264962436283">Tumia Touch ID kwenye <ph name="APP_NAME" /></translation>
-<translation id="8888253246822647887">Programu yako itafunguka baada ya kukamilisha kuweka toleo jipya. Matoleo mapya yanaweza kuchukua dakika kadhaa.</translation>
+<translation id="8888253246822647887">Programu yako itafunguka baada ya kukamilisha kuweka toleo jipya. Matoleo mapya yanaweza kuchukua dakika kadhaa kuwekwa.</translation>
<translation id="8888432776533519951">Rangi:</translation>
<translation id="8890516388109605451">Vyanzo</translation>
<translation id="8892168913673237979">Zote zimesanidiwa!</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_ta.xtb b/chromium/chrome/app/resources/generated_resources_ta.xtb
index 80afdc2c3a1..5dbe23d65f1 100644
--- a/chromium/chrome/app/resources/generated_resources_ta.xtb
+++ b/chromium/chrome/app/resources/generated_resources_ta.xtb
@@ -113,7 +113,7 @@
<translation id="1151917987301063366">சென்சார்களை அணுக, <ph name="HOST" />ஐ எப்போதும் அனுமதி</translation>
<translation id="1153356358378277386">இணைத்த சாதனங்கள்</translation>
<translation id="1156488781945104845">தற்போதைய நேரம்</translation>
-<translation id="1161575384898972166">கிளையன்ட் சான்றிதழை ஏற்றுமதி செய்ய, தயவுசெய்து <ph name="TOKEN_NAME" /> இல் உள்நுழைக.</translation>
+<translation id="1161575384898972166">கிளையண்ட் சான்றிதழை ஏற்றுமதி செய்ய, தயவுசெய்து <ph name="TOKEN_NAME" /> இல் உள்நுழைக.</translation>
<translation id="1161699061380012396">Chrome OS உள்ளீட்டு முறை</translation>
<translation id="1163931534039071049">சட்டக ஆதாரங்களைக் &amp;காண்க</translation>
<translation id="1164674268730883318"><ph name="DEVICE_TYPE" />க்கான Smart Lockஐ முடக்கவா?</translation>
@@ -219,7 +219,7 @@
<translation id="1307931752636661898">Linux கோப்புகளைப் பார்க்க முடியவில்லை</translation>
<translation id="1313405956111467313">தானியங்கு ப்ராக்ஸி உள்ளமைவு</translation>
<translation id="131364520783682672">Caps Lock</translation>
-<translation id="1313705515580255288">உங்கள் புத்தகக்குறிகள், வரலாறு மற்றும் பிற அமைப்புகள் ஆகியவை உங்கள் Google கணக்கில் ஒத்திசைக்கப்படும்.</translation>
+<translation id="1313705515580255288">உங்கள் புக்மார்க்குகள், வரலாறு மற்றும் பிற அமைப்புகள் ஆகியவை உங்கள் Google கணக்கில் ஒத்திசைக்கப்படும்.</translation>
<translation id="1314565355471455267">Android VPN</translation>
<translation id="131461803491198646">உள்ளூர் நெட்வொர்க், ரோமிங் இல்லை</translation>
<translation id="1316136264406804862">தேடுகிறது...</translation>
@@ -229,7 +229,7 @@
<translation id="1327074568633507428">Google கிளவுடு அச்சில் உள்ள பிரிண்டர்</translation>
<translation id="1327977588028644528">கேட்வே</translation>
<translation id="1329584516321524826">சற்றுமுன் புதுப்பிக்கப்பட்டது</translation>
-<translation id="1330145147221172764">திரை விசைப்பலகை இயக்கு</translation>
+<translation id="1330145147221172764">ஸ்கிரீன் கீபோர்ட் இயக்கு</translation>
<translation id="1331977651797684645">அது நான் தான்.</translation>
<translation id="133535873114485416">விருப்பமான உள்ளீட்டு முறை</translation>
<translation id="1338776410427958681"><ph name="FOLDER_NAME" />ஐச் சுருக்கும் பொத்தான்</translation>
@@ -252,7 +252,7 @@
<translation id="1363028406613469049">ட்ராக் எண்</translation>
<translation id="1364702626840264065">{NUM_TABS,plural, =1{தாவலை மூடுக}other{தாவல்களை மூடுக}}</translation>
<translation id="1367951781824006909">கோப்பைத் தேர்வுசெய்க</translation>
-<translation id="1371301976177520732">உங்கள் எல்லாச் சாதனங்களிலும் உங்கள் புத்தகக்குறிகள், கடவுச்சொற்கள், வரலாறு, மேலும் பலவற்றைப் பெறலாம்</translation>
+<translation id="1371301976177520732">உங்கள் எல்லாச் சாதனங்களிலும் உங்கள் புக்மார்க்குகள், கடவுச்சொற்கள், வரலாறு, மேலும் பலவற்றைப் பெறலாம்</translation>
<translation id="1372841398847029212">எனது கணக்குடன் ஒத்திசை</translation>
<translation id="1374844444528092021">"<ph name="NETWORK_NAME" />" நெட்வொர்க்குக்குத் தேவைப்படும் சான்றிதழானது நிறுவப்படாமலோ இனி செல்லுபடியாகாத நிலையிலோ உள்ளது. புதிய சான்றிதழைப் பெற்று, மீண்டும் இணைக்க முயலவும்.</translation>
<translation id="1375321115329958930">சேமிக்கப்பட்ட கடவுச்சொற்கள்</translation>
@@ -274,12 +274,12 @@
<translation id="1397500194120344683">தகுதியான சாதனங்கள் இல்லை. <ph name="LINK_BEGIN" />மேலும் அறிக<ph name="LINK_END" /></translation>
<translation id="1398853756734560583">பெரிதாக்கு</translation>
<translation id="1399511500114202393">பயனர் சான்றிதழ் இல்லை</translation>
-<translation id="140520891692800925"><ph name="PROFILE_DISPLAY_NAME" /> (கண்காணிக்கப்படும் பயனர்)</translation>
+<translation id="140520891692800925"><ph name="PROFILE_DISPLAY_NAME" /> (மேற்பார்வையிடப்படும் பயனர்)</translation>
<translation id="1406500794671479665">சரிபார்க்கிறது...</translation>
<translation id="1407489512183974736">மையமாக வெட்டப்பட்டது</translation>
<translation id="1408504635543854729">கோப்புகள் பயன்பாட்டில் சாதனத்தின் உள்ளடக்கத்தைத் தேடவும். உள்ளடக்கத்தை நிர்வாகி கட்டுப்படுத்துவதால் அதைத் திருத்த முடியாது.</translation>
<translation id="1408789165795197664">மேம்பட்டவை...</translation>
-<translation id="1409390508152595145">கண்காணிக்கப்படும் பயனரை உருவாக்கு</translation>
+<translation id="1409390508152595145">மேற்பார்வையிடப்படும் பயனரை உருவாக்கு</translation>
<translation id="1410197035576869800">பயன்பாட்டின் ஐகான்</translation>
<translation id="1410616244180625362">உங்கள் கேமராவை அணுக <ph name="HOST" /> ஐத் தொடர்ந்து அனுமதிக்கவும்</translation>
<translation id="1411668397053040814">VR இல் Chromeஐப் பயன்படுத்த, Daydream விசைப்பலகையை நிறுவவும் அல்லது புதுப்பிக்கவும்</translation>
@@ -306,7 +306,7 @@
<translation id="1444628761356461360">இந்த அமைப்பானது சாதனத்தின் உரிமையாளரால் <ph name="OWNER_EMAIL" /> நிர்வகிக்கப்படுகிறது.</translation>
<translation id="144518587530125858">தீமிற்காக '<ph name="IMAGE_PATH" />' ஐ ஏற்ற முடியவில்லை.</translation>
<translation id="1451375123200651445">இணையப்பக்கம், ஒற்றைக் கோப்பு</translation>
-<translation id="1451917004835509682">கண்காணிக்கப்படும் பயனரைச் சேர்</translation>
+<translation id="1451917004835509682">மேற்பார்வையிடப்படும் பயனரைச் சேர்</translation>
<translation id="1454223536435069390">ஸ்கிரீன் ஷாட்டை எடு</translation>
<translation id="1459967076783105826">நீட்டிப்புகளால் சேர்க்கப்பட்ட தேடல் இன்ஜின்கள்</translation>
<translation id="146000042969587795">இந்த சட்டகம் சில பாதுகாப்பாற்ற உள்ளடக்கத்தைக் கொண்டுள்ளதால் தடுக்கப்பட்டது.</translation>
@@ -439,7 +439,7 @@
<translation id="1644574205037202324">வரலாறு</translation>
<translation id="1645516838734033527"><ph name="DEVICE_TYPE" />ஐப் பாதுகாப்பாக வைக்க, Smart Lockக்கு உங்கள் மொபைலில் திரைப் பூட்டை இயக்க வேண்டும்.</translation>
<translation id="1646982517418478057">இந்தச் சான்றிதழை என்க்ரிப்ட் செய்ய கடவுச்சொல்லை உள்ளிடவும்</translation>
-<translation id="164814987133974965">கண்காணிக்கப்படும் பயனர் உங்கள் வழிகாட்டுதலினால் இணையத்தைக் உலாவலாம். கண்காணிப்பு பயனரின் நிர்வாகியாக, நீங்கள்
+<translation id="164814987133974965">மேற்பார்வையிடப்படும் பயனர் உங்கள் வழிகாட்டுதலினால் இணையத்தைக் உலாவலாம். கண்காணிப்பு பயனரின் நிர்வாகியாக, நீங்கள்
குறிப்பிட்ட இணையத்தளங்களை <ph name="BEGIN_BOLD" />அனுமதிக்கலாம் அல்லது தடுக்கலாம்<ph name="END_BOLD" />,
கண்காணிப்பு பயனர் பார்வையிட்ட இணையதளங்களை <ph name="BEGIN_BOLD" />மதிப்பாய்வு செய்யலாம்<ph name="END_BOLD" /> மற்றும்
மற்ற அமைப்புகளை <ph name="BEGIN_BOLD" />நிர்வகிக்கலாம்<ph name="END_BOLD" />.</translation>
@@ -518,7 +518,6 @@
<translation id="175772926354468439">தீம் ஐ இயக்கு</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome இணைய அங்காடியில் காட்டு</translation>
-<translation id="1761588866118490543">குரல் மாதிரி</translation>
<translation id="176193854664720708">கைரேகை சென்சார் பவர் பட்டனில் உள்ளது. அதை ஏதேனும் ஒரு விரலால் மெதுவாகத் தொடவும்.</translation>
<translation id="1763046204212875858">பயன்பாட்டு குறுக்குவழிகளை உருவாக்குக</translation>
<translation id="1763108912552529023">தொடர்ந்து அறிக</translation>
@@ -550,7 +549,7 @@
<translation id="1805738995123446102">பின்னணித் தாவல் மைக்ரோஃபோனைப் பயன்படுத்துகிறது</translation>
<translation id="1805822111539868586">பார்வைகளை ஆய்வு செய்</translation>
<translation id="1807938677607439181">எல்லா கோப்புகளும்</translation>
-<translation id="1809734401532861917"><ph name="USER_EMAIL_ADDRESS" /> இல் எனது புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைச் சேர்</translation>
+<translation id="1809734401532861917"><ph name="USER_EMAIL_ADDRESS" /> இல் எனது புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைச் சேர்</translation>
<translation id="1810764548349082891">மாதிரிக்காட்சி இல்லை</translation>
<translation id="1813278315230285598">சேவைகள்</translation>
<translation id="18139523105317219">EDI பார்ட்டி பெயர்</translation>
@@ -671,7 +670,7 @@
<translation id="1976323404609382849">பல தளங்களிலிருந்து வரும் குக்கீகள் தடுக்கப்பட்டுள்ளன.</translation>
<translation id="1977965994116744507"><ph name="DEVICE_TYPE" /> சாதனத்தைத் திறக்க, அதற்கு அருகில் உங்கள் மொபைலை எடுத்து வரவும்.</translation>
<translation id="1979280758666859181"><ph name="PRODUCT_NAME" /> இன் பழைய பதிப்பிற்கு சேனலை மாற்றுகிறீர்கள். உங்கள் சாதனத்தில் நிறுவப்பட்ட பதிப்புடன் சேனல் பதிப்பு பொருந்தும்போது சேனலின் மாற்றமும் பயன்படுத்தப்படும்.</translation>
-<translation id="1983959805486816857">புதிய கண்காணிக்கப்படும் பயனரை உருவாக்கிய பிறகு, நீங்கள் எந்தச் சாதனத்திலிருந்தும் எப்போது வேண்டுமானாலும் <ph name="MANAGEMENT_URL" /> இல் அமைப்புகளை நிர்வகிக்கலாம்.</translation>
+<translation id="1983959805486816857">புதிய மேற்பார்வையிடப்படும் பயனரை உருவாக்கிய பிறகு, நீங்கள் எந்தச் சாதனத்திலிருந்தும் எப்போது வேண்டுமானாலும் <ph name="MANAGEMENT_URL" /> இல் அமைப்புகளை நிர்வகிக்கலாம்.</translation>
<translation id="1987317783729300807">கணக்குகள்</translation>
<translation id="1989112275319619282">உலாவு</translation>
<translation id="1992397118740194946">அமைக்கப்படவில்லை</translation>
@@ -706,7 +705,7 @@
<translation id="204622017488417136">ஏற்கனவே நிறுவப்பட்ட Chrome இன் பதிப்பிற்கு உங்கள் சாதனம் மாற்றியமைக்கப்படும். எல்லா பயனர் கணக்குகளும் அகத் தரவும் அகற்றப்படும். இதைச் செயல்தவிர்க்க முடியாது.</translation>
<translation id="2048182445208425546">உங்கள் நெட்வொர்க் ட்ராஃபிக்கை அணுகலாம்</translation>
<translation id="2048653237708779538">இச்செயலைச் செய்ய இயலாது</translation>
-<translation id="204914487372604757">குறுக்குவழியை உருவாக்குக</translation>
+<translation id="204914487372604757">ஷார்ட்கட்டை உருவாக்குக</translation>
<translation id="2050339315714019657">செங்குத்து நிலை</translation>
<translation id="2053312383184521053">செயல்படா நிலையில் இருக்கும் தரவு</translation>
<translation id="205560151218727633">Google அசிஸ்டண்ட் லோகோ</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">உபயோகம் &amp; கண்டறிதல் தரவை அனுப்புக. கண்டறிதல் தரவு, சாதனம் மற்றும் ஆப்ஸ் உபயோகத் தரவு போன்றவற்றை இந்தச் சாதனம் தற்போது Googleளுக்குத் தானாக அனுப்புகிறது. இது சிஸ்டம் மற்றும் ஆப்ஸின் நிலைத்தன்மையை மேம்படுத்தவும் பிற மேம்பாடுகளைச் செய்யவும் உதவும். ஒருங்கிணைக்கப்பட்ட சில தரவுகள், Google ஆப்ஸ் மற்றும் Android டெவெலப்பர்கள் போன்ற கூட்டாளர்களுக்கும் உதவும். உரிமையாளர் இந்த அமைப்பைச் செயல்படுத்தியுள்ளார். கூடுதல் ’இணையம் &amp; ஆப்ஸ் செயல்பாடு’ அமைப்பு இயக்கப்பட்டிருந்தால், இந்தத் தரவு உங்கள் Google கணக்கில் சேமிக்கப்படலாம். <ph name="BEGIN_LINK1" />மேலும் அறிக<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">ஜிப் காப்பகம்</translation>
<translation id="220858061631308971">"<ph name="DEVICE_NAME" />" இல் இந்த PIN குறியீட்டை உள்ளிடுக:</translation>
+<translation id="2213140827792212876">பகிர்வை அகற்றும்</translation>
+<translation id="2214018885812055163">பகிர்ந்த கோப்புறைகள்</translation>
<translation id="2214884991347062907">தவறான கடவுச்சொல், மீண்டும் முயலவும்</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 வரி காட்டப்படவில்லை&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> வரிகள் காட்டப்படவில்லை&gt;}}</translation>
<translation id="2217501013957346740">பெயரை உருவாக்கவும் -</translation>
@@ -866,7 +867,7 @@
<translation id="2272570998639520080">மார்டினி கிளாஸ்</translation>
<translation id="2276503375879033601">மேலும் பயன்பாடுகளைச் சேர்க்கவும்</translation>
<translation id="2277255602909579701">எல்லா குக்கீகளும் தளத்தின் தரவும்</translation>
-<translation id="2277769717710009150">{COUNT,plural, =1{ஒரு புத்தகக்குறி நகலெடுக்கப்பட்டது}other{# புத்தகக்குறிகள் நகலெடுக்கப்பட்டன}}</translation>
+<translation id="2277769717710009150">{COUNT,plural, =1{ஒரு புத்தகக்குறி நகலெடுக்கப்பட்டது}other{# புக்மார்க்குகள் நகலெடுக்கப்பட்டன}}</translation>
<translation id="2278562042389100163">உலாவி சாளரத்தைத் திற</translation>
<translation id="2279874276457403668">ஒரு நேரத்தில் ஒரே ஒரு அமர்வை மட்டும் உருவாக்க முடியும்.</translation>
<translation id="2280486287150724112">வலது ஓரஇடம்</translation>
@@ -897,7 +898,7 @@
<translation id="2325650632570794183">இந்தக் கோப்பு வகை ஆதரிக்கப்படவில்லை. இந்த வகையானக் கோப்பைத் திறக்கும் பயன்பாட்டைக் கண்டறிய Chrome இணைய அங்காடியைப் பார்வையிடவும்.</translation>
<translation id="2326931316514688470">&amp;பயன்பாட்டை மீண்டும் ஏற்று</translation>
<translation id="2327492829706409234">பயன்பாட்டை இயக்கு</translation>
-<translation id="2329597144923131178">உங்கள் எல்லா சாதனங்களிலும் புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெற உள்நுழையவும்.</translation>
+<translation id="2329597144923131178">உங்கள் எல்லா சாதனங்களிலும் புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெற உள்நுழையவும்.</translation>
<translation id="2332131598580221120">அங்காடியில் காட்டு</translation>
<translation id="2332742915001411729">இயல்புநிலைக்கு மீட்டமை</translation>
<translation id="2335122562899522968">இந்தப் பக்கம் குக்கீகளை அமைக்கும்.</translation>
@@ -1013,8 +1014,9 @@
<translation id="2499747912851752301">கடவுச்சொற்களை ஏற்றுகிறது...</translation>
<translation id="2500471369733289700">உங்கள் தனியுரிமையைப் பாதுகாக்க, தடுக்கப்பட்டது</translation>
<translation id="2501173422421700905">சான்றிதழ் நிலுவையிலுள்ளது</translation>
-<translation id="2501797496290880632">குறுக்குவழியைத் தட்டச்சு செய்க</translation>
+<translation id="2501797496290880632">ஷார்ட்கட்டைத் தட்டச்சு செய்க</translation>
<translation id="2502441965851148920">தானியங்கு புதுப்பிப்புகள் இயக்கப்பட்டன. பயனரால் செய்யப்பட்ட புதுப்பிப்புகள் உங்கள் நிர்வாகியால் முடக்கப்பட்டன.</translation>
+<translation id="2505127913256479918">இந்த மேற்பார்வையிடப்படும் கணக்கு விரைவில் அகற்றப்படும்</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{திரை #}other{திரை #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" /> இல் <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play ஸ்டோர் கணக்கு</translation>
@@ -1066,9 +1068,9 @@
<translation id="2585724835339714757">இந்தத் தாவல் உங்கள் திரையைப் பகிர்கிறது.</translation>
<translation id="2586657967955657006">கிளிப்போர்டு</translation>
<translation id="2586672484245266891">சிறிய URLஐ உள்ளிடவும்</translation>
-<translation id="2587922270115112871">கண்காணிக்கப்படும் பயனரை உருவாக்குவது Google கணக்கை உருவாக்காது, மேலும் அதன் அமைப்புகளும் தரவும்
+<translation id="2587922270115112871">மேற்பார்வையிடப்படும் பயனரை உருவாக்குவது Google கணக்கை உருவாக்காது, மேலும் அதன் அமைப்புகளும் தரவும்
Chrome ஒத்திசைவு மூலம் பிற சாதனங்களில் அவர்களைப் பின்தொடராது.
- இந்தச் சாதனத்தில் மட்டுமே கண்காணிக்கப்படும் பயனர் பயன்படுத்தப்படுவார்.</translation>
+ இந்தச் சாதனத்தில் மட்டுமே மேற்பார்வையிடப்படும் பயனர் பயன்படுத்தப்படுவார்.</translation>
<translation id="258932246702879617"><ph name="BEGIN_BOLD" />பணிப்பட்டியில் பொருத்து<ph name="END_BOLD" /> என்பதைத் தேர்ந்தெடுக்கவும்</translation>
<translation id="2594999711683503743">Googleளில் தேடவும் அல்லது URLலை உள்ளிடவும்</translation>
<translation id="2603115962224169880">கணினியைச் சுத்தமாக்கு</translation>
@@ -1129,7 +1131,7 @@
<translation id="2672142220933875349">தவறான crx கோப்பு, அசல் நிலைக்கு மாற்றுவது தோல்வி.</translation>
<translation id="2672394958563893062">பிழை ஏற்பட்டது. ஆரம்பத்திலிருந்து மீண்டும் தொடங்க கிளிக் செய்க.</translation>
<translation id="2673135533890720193">உங்கள் உலாவல் வரலாற்றைப் படித்தல்</translation>
-<translation id="2673589024369449924">இந்தப் பயனருக்கு ஒரு டெஸ்க்டாப் குறுக்குவழியை உருவாக்கு</translation>
+<translation id="2673589024369449924">இந்தப் பயனருக்கு ஒரு டெஸ்க்டாப் ஷார்ட்கட்டை உருவாக்கு</translation>
<translation id="2676946222714718093">இதில் இயங்குகிறது</translation>
<translation id="2677748264148917807">வெளியேறு</translation>
<translation id="2678063897982469759">மீண்டும் இயக்கு</translation>
@@ -1157,7 +1159,7 @@
<translation id="2719936478972253983">பின்வரும் குக்கீகள் தடுக்கப்பட்டன:</translation>
<translation id="2721037002783622288"><ph name="SEARCH_ENGINE" /> இல் படத்தைத் &amp;தேடு</translation>
<translation id="2721334646575696520">Microsoft Edge</translation>
-<translation id="2721695630904737430">கண்காணிக்கப்படும் பயனர்களை உங்கள் நிர்வாகி முடக்கியுள்ளார்.</translation>
+<translation id="2721695630904737430">மேற்பார்வையிடப்படும் பயனர்களை உங்கள் நிர்வாகி முடக்கியுள்ளார்.</translation>
<translation id="2724841811573117416">WebRTC பதிவுகள்</translation>
<translation id="2725200716980197196">நெட்வொர்க் இணைப்பு மீட்டெடுக்கப்பட்டது</translation>
<translation id="2727633948226935816">மீண்டும் நினைவுபடுத்தாதே</translation>
@@ -1165,7 +1167,7 @@
<translation id="273093730430620027">இந்தப் பக்கம் உங்கள் கேமராவை அணுகுகிறது.</translation>
<translation id="2731392572903530958">மூடப்பட்ட சாளரத்தை மீ&amp;ண்டும் திற</translation>
<translation id="2731700343119398978">காத்திருக்கவும்...</translation>
-<translation id="2731710757838467317">உங்கள் கண்காணிக்கப்படும் பயனரை உருவாக்குகிறது. இதற்கு ஒரு சில நிமிடங்கள் ஆகலாம்.</translation>
+<translation id="2731710757838467317">உங்கள் மேற்பார்வையிடப்படும் பயனரை உருவாக்குகிறது. இதற்கு ஒரு சில நிமிடங்கள் ஆகலாம்.</translation>
<translation id="2734760316755174687"><ph name="SITE_GROUP_NAME" /> குழுவில் உள்ள எல்லா தளங்களும் மீட்டமைக்கப்படும்.</translation>
<translation id="2735438478659026460">மவுஸ் கர்சர் நிற்கும் போது, தானாகக் கிளிக் செய்</translation>
<translation id="2735712963799620190">திட்ட அட்டவணை</translation>
@@ -1173,7 +1175,7 @@
<translation id="2738771556149464852">இதன்பிறகு அல்ல</translation>
<translation id="2739191690716947896">பிழைத்திருத்து</translation>
<translation id="2739240477418971307">உங்கள் அணுகல்தன்மை அமைப்புகளை மாற்றலாம்</translation>
-<translation id="2740393541869613458">கண்காணிக்கப்படும் பயனர் பார்வையிட்ட இணையதளங்களைச் சரிபார்க்கலாம், மேலும்</translation>
+<translation id="2740393541869613458">மேற்பார்வையிடப்படும் பயனர் பார்வையிட்ட இணையதளங்களைச் சரிபார்க்கலாம், மேலும்</translation>
<translation id="2743387203779672305">கிளிப்போர்டுக்கு நகலெடு</translation>
<translation id="2745080116229976798">Microsoft Qualified Subordination</translation>
<translation id="2749756011735116528"><ph name="PRODUCT_NAME" /> இல் உள்நுழையவும்</translation>
@@ -1197,7 +1199,7 @@
<translation id="2781692009645368755">Google Pay</translation>
<translation id="2782104745158847185">ஒரு Linux ஆப்ஸை நிறுவும்போது பிழை நேர்ந்தது</translation>
<translation id="2783298271312924866">பதிவிறக்கப்பட்டது</translation>
-<translation id="2783321960289401138">குறுக்கு வழியை உருவாக்கு...</translation>
+<translation id="2783321960289401138">ஷார்ட்கட்டை உருவாக்கு...</translation>
<translation id="2783829359200813069">என்க்ரிப்ஷன் வகைகளைத் தேர்வுசெய்யவும்</translation>
<translation id="2783952358106015700"><ph name="APP_NAME" /> உடன் உங்கள் பாதுகாப்பு விசையைப் பயன்படுத்துதல்</translation>
<translation id="2784407158394623927">மொபைல் டேட்டா சேவை இயக்கப்படுகிறது</translation>
@@ -1355,13 +1357,13 @@
<translation id="3015639418649705390">இப்போதே மீண்டும் தொடங்கு</translation>
<translation id="3016641847947582299">உறுப்பு மேம்படுத்தப்பட்டது</translation>
<translation id="3016780570757425217">உங்கள் இருப்பிடத்தை அறியும்</translation>
-<translation id="3020183492814296499">குறுக்குவழிகள்</translation>
+<translation id="3020183492814296499">ஷார்ட்கட்கள்</translation>
<translation id="3020990233660977256">வரிசை எண்: <ph name="SERIAL_NUMBER" /></translation>
<translation id="3021678814754966447">சட்டக ஆதாரங்களைக் &amp;காண்க</translation>
<translation id="3022978424994383087">மொழிபெயர்க்க முடியவில்லை.</translation>
<translation id="3023464535986383522">பேசும் திரை</translation>
<translation id="3024374909719388945">24-மணிநேர கடிகாரத்தைப் பயன்படுத்து</translation>
-<translation id="3031417829280473749">ஏஜென்ட் X</translation>
+<translation id="3031417829280473749">ஏஜெண்ட் X</translation>
<translation id="3031557471081358569">இறக்குமதிக்கு உருப்படிகளைத் தேர்ந்தெடு</translation>
<translation id="3031601332414921114">அச்சிடுவதை மீண்டும் தொடங்கு</translation>
<translation id="303198083543495566">புவியியல்</translation>
@@ -1376,6 +1378,7 @@
<translation id="304747341537320566">பேச்சு என்ஜின்கள்</translation>
<translation id="3053013834507634016">சான்றிதழ் விசைப் பயன்பாடு</translation>
<translation id="3057861065630527966">உங்கள் படங்கள் மற்றும் வீடியோக்களைக் காப்புப் பிரதியெடுக்கவும்</translation>
+<translation id="3058498974290601450">அமைப்புகளில் ஒத்திசைவை எந்த நேரத்திலும் இயக்கலாம்</translation>
<translation id="3060379269883947824">பேசும் திரையை இயக்கு</translation>
<translation id="3061707000357573562">பேட்ச் சேவை</translation>
<translation id="3065041951436100775">தாவல் நிறுத்தப்பட்டது பற்றிய கருத்து.</translation>
@@ -1526,7 +1529,7 @@
<translation id="3308134619352333507">பொத்தானை மறை</translation>
<translation id="3308852433423051161">Google அசிஸ்டண்ட்டை ஏற்றுகிறது...</translation>
<translation id="3312424061798279731">இயக்கத்திலுள்ள மொழிகள்</translation>
-<translation id="3313590242757056087">எந்த இணையதளங்களைக் கண்காணிக்கப்படும் பயனர் பார்க்கலாம் என்பதை அமைக்க, <ph name="MANAGEMENT_URL" /> ஐப் பார்வையிடுவதன் மூலம் நீங்கள் கட்டுப்பாடுகள் மற்றும் அமைப்புகளை உள்ளமைக்கலாம்.
+<translation id="3313590242757056087">எந்த இணையதளங்களைக் மேற்பார்வையிடப்படும் பயனர் பார்க்கலாம் என்பதை அமைக்க, <ph name="MANAGEMENT_URL" /> ஐப் பார்வையிடுவதன் மூலம் நீங்கள் கட்டுப்பாடுகள் மற்றும் அமைப்புகளை உள்ளமைக்கலாம்.
நீங்கள் இயல்பு அமைப்புகளை மாற்றவில்லை எனில்,
இணையத்தில் எல்லா தளங்களையும் <ph name="USER_DISPLAY_NAME" /> உலாவ முடியும்.</translation>
<translation id="3313622045786997898">சான்றிதழ் கையொப்ப மதிப்பு</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> நிறுவப்படும்.</translation>
<translation id="3380365263193509176">அறியப்படாத பிழை</translation>
<translation id="3382073616108123819">அச்சச்சோ! இந்தச் சாதனத்திற்கான சாதன அணுகலைத் தீர்மானிப்பதில் அமைப்பு தோல்வி.</translation>
+<translation id="3382086682569279540">நீங்கள் நிர்வகிக்கும் கணக்கு விரைவில் அகற்றப்படும்</translation>
<translation id="3382200254148930874">கண்காணிப்பை நிறுத்துகிறது...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">பிரிப்பான்</translation>
@@ -1667,13 +1671,13 @@
<translation id="3523642406908660543">எனது கணினியை அணுகுவதற்கான செருநிரலை தளம் பயன்படுத்த விரும்பும்போது கேள் (பரிந்துரைக்கப்படுவது)</translation>
<translation id="3526034519184079374">தளத்தின் தரவைப் படிக்கவோ மாற்றவோ முடியாது</translation>
<translation id="3527085408025491307">கோப்புறை</translation>
-<translation id="3527276236624876118"><ph name="USER_DISPLAY_NAME" /> என்ற பெயரில் கண்காணிக்கப்படும் பயனர் உருவாக்கப்பட்டுள்ளார்.</translation>
+<translation id="3527276236624876118"><ph name="USER_DISPLAY_NAME" /> என்ற பெயரில் மேற்பார்வையிடப்படும் பயனர் உருவாக்கப்பட்டுள்ளார்.</translation>
<translation id="3528033729920178817">இந்தப் பக்கம் உங்கள் இருப்பிடத்தை தடமறிகிறது.</translation>
-<translation id="3528498924003805721">குறுக்குவழி இலக்குகள்</translation>
+<translation id="3528498924003805721">ஷார்ட்கட் இலக்குகள்</translation>
<translation id="3530305684079447434">உங்கள் எல்லா சாதனங்களிலும் புத்தகக்குறிகளைப் பெற, <ph name="SIGN_IN_LINK" />.</translation>
<translation id="3532844647053365774"><ph name="HOST" /> உங்கள் மைக்ரோஃபோனைப் பயன்படுத்த விரும்புகிறது</translation>
<translation id="353316712352074340"><ph name="WINDOW_TITLE" /> - ஆடியோ முடக்கப்பட்டது</translation>
-<translation id="3534879087479077042">கண்காணிக்கப்படும் பயனர் என்றால் என்ன?</translation>
+<translation id="3534879087479077042">மேற்பார்வையிடப்படும் பயனர் என்றால் என்ன?</translation>
<translation id="3538066758857505094">Linuxஸை நிறுவல் நீக்கும்போது பிழை ஏற்பட்டது. மீண்டும் முயலவும்.</translation>
<translation id="354060433403403521">AC அடாப்டர்</translation>
<translation id="354068948465830244">இந்த நீட்டிப்பால் தளத் தரவைப் படிக்கவும் மாற்றவும் முடியும்</translation>
@@ -1732,7 +1736,7 @@
<translation id="3616741288025931835">உலாவல் தரவை &amp;சுத்தமாக்கு...</translation>
<translation id="3617891479562106823">பின்னணிகள் கிடைக்கவில்லை. பின்னர் மீண்டும் முயலவும்.</translation>
<translation id="3620292326130836921">எல்லாம் காப்புப் பிரதி எடுக்கப்பட்டன!</translation>
-<translation id="3623574769078102674">இந்தக் கண்காணிக்கப்படும் பயனர் <ph name="MANAGER_EMAIL" /> ஆல் நிர்வகிக்கப்படுவார்.</translation>
+<translation id="3623574769078102674">இந்தக் மேற்பார்வையிடப்படும் பயனர் <ph name="MANAGER_EMAIL" /> ஆல் நிர்வகிக்கப்படுவார்.</translation>
<translation id="3624567683873126087">ஃபோனைத் திறந்து, Google கணக்கில் உள்நுழை</translation>
<translation id="3625258641415618104">ஸ்கிரீன்ஷாட்கள் முடக்கப்பட்டன</translation>
<translation id="3625481642044239431">தவறான கோப்பைத் தேர்ந்தெடுத்துள்ளீர்கள். மீண்டும் முயலவும்.</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">நலமா <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> மீதமுள்ளது</translation>
<translation id="3637682276779847508">பின்னின் தடையை நீக்குவதற்கான சரியான குறியீட்டை உள்ளிடவில்லை எனில், சிம் கார்டு நிரந்தரமாக முடக்கப்படும்.</translation>
-<translation id="363863692969456324">மேம்படுத்தப்பட்ட எழுத்துப் பிழை சரிபார்ப்பான் அம்சம் மூலம் எழுத்துப் பிழைகளைச் சரிசெய்யலாம்</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" />க்கு "<ph name="EXTENSION_NAME" />"ஐச் சேர்க்கவா?</translation>
+<translation id="3640613767643722554">உங்கள் குரலை அடையாளம் காண அசிஸ்டண்ட்டுக்குக் கற்றுத்தரவும்</translation>
<translation id="3644896802912593514">அகலம்</translation>
<translation id="3645372836428131288">கைரேகையின் வேறொரு பகுதியைப் பதிவுசெய்ய, விரலைக் கொஞ்சம் நகர்த்தவும்.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> கண்டறியப்பட்டது</translation>
@@ -1820,7 +1824,7 @@
<translation id="3738924763801731196"><ph name="OID" />:</translation>
<translation id="3739254215541673094"><ph name="APPLICATION" />ஐத் திறக்கவா?</translation>
<translation id="3741243925913727067">மீடியா சாதனத்தின் படங்களையும் வீடியோக்களையும் Google இயக்ககத்தில் காப்புப் பிரதி எடுக்கும்.</translation>
-<translation id="3742055079367172538">ஸ்கிரீன் ஷாட் எடுக்கப்பட்டது</translation>
+<translation id="3742055079367172538">ஸ்கிரீன்ஷாட் எடுக்கப்பட்டது</translation>
<translation id="3742666961763734085">அந்தப் பெயரில் நிறுவன யூனிட் எதையும் கண்டறிய முடியவில்லை. மீண்டும் முயலவும்.</translation>
<translation id="3744111561329211289">பின்புல ஒத்திசைவு</translation>
<translation id="3748026146096797577">இணைக்கப்படவில்லை</translation>
@@ -1851,7 +1855,7 @@
<translation id="3780536599611287598">'<ph name="FOLDER_NAME" />' என்ற கோப்புறைக்குக் கோப்புகளை நகர்த்த உங்களுக்கு அனுமதி இல்லை.</translation>
<translation id="378312418865624974">இந்தக் கணினிக்கான தனிப்பட்ட அடையாளங்காட்டியைப் படிக்கலாம்</translation>
<translation id="3785071023202624850">{NUM_TABS,plural, =1{தாவலின் ஒலியை முடக்கு}other{தாவல்களின் ஒலியை முடக்கு}}</translation>
-<translation id="3785308913036335955">பயன்பாடுகளின் குறுக்குவழியைக் காட்டு</translation>
+<translation id="3785308913036335955">ஆப்ஸின் ஷார்ட்கட்டைக் காட்டு</translation>
<translation id="3785727820640310185">இந்தத் தளத்திற்குச் சேமிக்கப்பட்ட கடவுச்சொற்கள்</translation>
<translation id="3786301125658655746">ஆஃப்லைனில் உள்ளீர்கள்</translation>
<translation id="3788401245189148511">இது அணுக விரும்புபவை:</translation>
@@ -1923,7 +1927,7 @@
<translation id="3872991219937722530">சாதனத்தில் காலி இடத்தை உருவாக்கவும் அல்லது உங்கள் சாதனம் இயங்காது.</translation>
<translation id="3873315167136380065">இதை இயக்குவதற்கு, <ph name="BEGIN_LINK" />ஒத்திசைவை மீட்டமைத்து<ph name="END_LINK" /> உங்கள் ஒத்திசைவுக் கடவுச்சொற்றொடரை அகற்றவும்.</translation>
<translation id="3873915545594852654">ARC++ல் ஒரு சிக்கல் ஏற்பட்டது.</translation>
-<translation id="3878840326289104869">கண்காணிக்கப்படும் பயனரை உருவாக்குகிறது</translation>
+<translation id="3878840326289104869">மேற்பார்வையிடப்படும் பயனரை உருவாக்குகிறது</translation>
<translation id="3879748587602334249">பதிவிறக்க நிர்வாகி</translation>
<translation id="3888550877729210209"><ph name="LOCK_SCREEN_APP_NAME" /> மூலம் குறிப்புகளை எடுத்தல்</translation>
<translation id="3892414795099177503">OpenVPN / L2TPஐச் சேர்...</translation>
@@ -2012,7 +2016,7 @@
<translation id="4005817994523282006">நேர மண்டலம் கண்டறிதல் முறை</translation>
<translation id="4008291085758151621">VR இல் தளத் தகவல் இல்லை</translation>
<translation id="4010917659463429001">மொபைல் சாதனத்தில் உங்கள் புத்தகக்குறிகளைப் பெற, <ph name="GET_IOS_APP_LINK" />.</translation>
-<translation id="4013132157686828973">"<ph name="CLIENT_NAME" />" இந்த உலாவியில் பிழைத் திருத்தம் செய்கிறது</translation>
+<translation id="4013132157686828973">"<ph name="CLIENT_NAME" />" இந்த உலாவியில் பிழைதிருத்தம் செய்கிறது</translation>
<translation id="4014432863917027322">"<ph name="EXTENSION_NAME" />"ஐப் புதுப்பிக்கவா?</translation>
<translation id="4020106588733303597">அச்சச்சோ! கிடைக்கும் உரிமங்களை ஏற்ற முடியவில்லை.</translation>
<translation id="4020327272915390518">விருப்பங்கள் மெனு</translation>
@@ -2147,12 +2151,11 @@
<translation id="4244238649050961491">மேலும் ஸ்டைலஸ் பயன்பாடுகளைக் கண்டறிக</translation>
<translation id="424546999567421758">அதிக வட்டுப் பயன்பாடு கண்டுபிடிக்கப்பட்டது</translation>
<translation id="424726838611654458">எப்போதும் Adobe Reader இல் திற</translation>
-<translation id="4247330672018280062">உரைப் புலங்களில் நீங்கள் உள்ளிடும் உரைகள் Googleளுக்கு அனுப்பப்படும்</translation>
<translation id="4247901771970415646"><ph name="USERNAME" />க்கு ஒத்திசைக்க முடியவில்லை</translation>
<translation id="4249248555939881673">நெட்வொர்க் இணைப்பிற்காகக் காத்திருக்கிறது...</translation>
<translation id="4249373718504745892">உங்கள் கேமராவையும், மைக்ரோஃபோனையும் அணுகுவதிலிருந்து இந்தப் பக்கம் தடுக்கப்பட்டுள்ளது.</translation>
<translation id="424963718355121712">ஆப்ஸ் எந்த ஹோஸ்ட்டை பாதிக்கின்றனவோ, அதிலிருந்தே வழங்கப்பட வேண்டும்</translation>
-<translation id="4250229828105606438">ஸ்கிரீன் ஷாட்</translation>
+<translation id="4250229828105606438">ஸ்கிரீன்ஷாட்</translation>
<translation id="4250680216510889253">இல்லை</translation>
<translation id="4252852543720145436">பாதுகாக்கப்படும் உள்ளடக்க அடையாளங்காட்டிகள்</translation>
<translation id="4252899949534773101">புளூடூத் முடக்கப்பட்டுள்ளது</translation>
@@ -2180,7 +2183,7 @@
<translation id="4290535918735525311">Linuxஸுடன் 1 கோப்புறை பகிரப்பட்டது</translation>
<translation id="4291934469232591280">பதிப்பு: <ph name="VERSION" /></translation>
<translation id="4295072614469448764">ஆப்ஸ் உங்கள் முனையத்தில் உள்ளது. உங்கள் தொடக்கியிலும் ஒரு ஐகான் இருக்கக்கூடும்.</translation>
-<translation id="4296575653627536209">கண்காணிக்கப்படும் பயனரைச் சேர்</translation>
+<translation id="4296575653627536209">மேற்பார்வையிடப்படும் பயனரைச் சேர்</translation>
<translation id="4297219207642690536">மீண்டும் தொடங்கி, மீட்டமை</translation>
<translation id="4297322094678649474">மொழிகளை மாற்று</translation>
<translation id="4305227814872083840">நீண்டது (2வி)</translation>
@@ -2213,7 +2216,7 @@
<translation id="4356334633973342967">அல்லது உங்கள் சொந்த இயக்கியைக் குறிப்பிடவும்:</translation>
<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
<translation id="4359408040881008151">நீட்டிப்பு(கள்) சார்ந்திருப்பதன் காரணமாக நிறுவப்பட்டது.</translation>
-<translation id="4361142739114356624">இந்தக் கிளையன்ட் சான்றிதழுக்கான தனிப்பட்ட குறியீடு இல்லை அல்லது தவறானது</translation>
+<translation id="4361142739114356624">இந்தக் கிளையண்ட் சான்றிதழுக்கான தனிப்பட்ட குறியீடு இல்லை அல்லது தவறானது</translation>
<translation id="4363771538994847871">எங்கே அலைபரப்புவது என்று கண்டறிய முடியவில்லை. உதவி வேண்டுமா?</translation>
<translation id="4364567974334641491"><ph name="APP_NAME" /> சாளரத்தைப் பகிர்கிறது.</translation>
<translation id="4364830672918311045">அறிவிப்புகளைக் காட்டலாம்</translation>
@@ -2299,7 +2302,7 @@
<translation id="4508265954913339219">செயலாக்கம் தோல்வியுற்றது</translation>
<translation id="4508765956121923607">ஆ&amp;தாரத்தைக் காண்பி</translation>
<translation id="451407183922382411"><ph name="COMPANY_NAME" /> வழங்குவது</translation>
-<translation id="4514542542275172126">புதிய கண்காணிக்கப்படும் பயனரை அமை</translation>
+<translation id="4514542542275172126">புதிய மேற்பார்வையிடப்படும் பயனரை அமை</translation>
<translation id="4514610446763173167">இயக்க அல்லது இடைநிறுத்த, வீடியோவை நிலைமாற்றவும்</translation>
<translation id="451515744433878153">அகற்று</translation>
<translation id="4518677423782794009">Chrome செயலிழக்கிறதா, வழக்கத்திற்கு மாறான துவக்கப் பக்கங்கள், கருவிப்பட்டிகள் தோன்றுகின்றனவா, தவிர்க்கமுடியாத திடீர் விளம்பரங்களால் தொல்லையா, உங்கள் உவாவல் அனுபவத்தில் மாற்றங்கள் உள்ளதா? Chrome சுத்திகரிப்புக் கருவியை இயக்கி இச்சிக்கல்களைத் தீர்க்கலாம்.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;சுயவிவரமாக்கம் இயக்கப்பட்டது</translation>
<translation id="4823484602432206655">பயணர் மற்றும் சாதன அமைப்புகளைப் படிக்கும் மற்றும் மாற்றும்</translation>
<translation id="4823651846660089135">படிப்பதற்கு மட்டுமேயான சாதனம்</translation>
+<translation id="4824958205181053313">ஒத்திசைவை ரத்துசெய்யவா?</translation>
<translation id="4827675678516992122">இணைக்க முடியவில்லை</translation>
<translation id="4828937774870308359">ஆஸ்திரேலியன்</translation>
<translation id="4829768588131278040">பின்னை அமை</translation>
@@ -2562,7 +2566,7 @@
<translation id="4907161631261076876">பொதுவாக இந்தக் கோப்புப் பதிவிறக்கப்படுவதில்லை, மேலும் ஆபத்தானதாக இருக்கக்கூடும்.</translation>
<translation id="4907306957610201395">அனுமதி வகை</translation>
<translation id="4908811072292128752">ஒரே நேரத்தில் இரண்டு தளங்களைப் பார்வையிட, புதிய தாவலைத் திறக்கவும்</translation>
-<translation id="4909038193460299775">இந்தக் கணக்கை <ph name="DOMAIN" /> நிர்வகிப்பதால், இந்தச் சாதனத்திலிருந்து உங்கள் புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் அழிக்கப்படும். இருப்பினும், உங்கள் தரவு தொடர்ந்து Google கணக்கில் சேமிக்கப்படும். அவற்றை <ph name="BEGIN_LINK" />Google டாஷ்போர்டில்<ph name="END_LINK" /> நிர்வகிக்கலாம்.</translation>
+<translation id="4909038193460299775">இந்தக் கணக்கை <ph name="DOMAIN" /> நிர்வகிப்பதால், இந்தச் சாதனத்திலிருந்து உங்கள் புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் அழிக்கப்படும். இருப்பினும், உங்கள் தரவு தொடர்ந்து Google கணக்கில் சேமிக்கப்படும். அவற்றை <ph name="BEGIN_LINK" />Google டாஷ்போர்டில்<ph name="END_LINK" /> நிர்வகிக்கலாம்.</translation>
<translation id="4909359680501173791">பதிவுசெய்துவிட்டீர்கள்</translation>
<translation id="4912643508233590958">செயல்படாமல் இருக்கும் நினைவூட்டல்கள்</translation>
<translation id="491691592645955587">பாதுகாப்பான உலாவிக்கு மாறவும்</translation>
@@ -2577,11 +2581,11 @@
<translation id="4924638091161556692">நிலையான</translation>
<translation id="4925542575807923399">பல உள்நுழைவு அமர்வில் இந்தக் கணக்கு முதலில் உள்நுழைந்த கணக்காக இருக்க வேண்டிய தேவை இந்தக் கணக்கின் நிர்வாகிக்கு உள்ளது.</translation>
<translation id="4927753642311223124">பார்க்க இங்கு எதுவுமில்லை, தொடரவும்.</translation>
-<translation id="4927846293686536410">உங்கள் எல்லாச் சாதனங்களிலும் உள்ள புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெற, உள்நுழையவும். மேலும், உங்கள் Google சேவைகளிலும் தானாகவே உள்நுழைவீர்கள்.</translation>
+<translation id="4927846293686536410">உங்கள் எல்லாச் சாதனங்களிலும் உள்ள புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெற, உள்நுழையவும். மேலும், உங்கள் Google சேவைகளிலும் தானாகவே உள்நுழைவீர்கள்.</translation>
<translation id="4929386379796360314">அச்சிடுவதற்கான இலக்குகள்</translation>
<translation id="4931132176527519925">எப்போதும் பிரதிபலித்தலைப் பயன்படுத்து</translation>
<translation id="4933484234309072027"><ph name="URL" /> இல் உட்பொதியப்பட்டது</translation>
-<translation id="493571969993549666">கண்காணிக்கப்படும் பயனரைச் சேர்</translation>
+<translation id="493571969993549666">மேற்பார்வையிடப்படும் பயனரைச் சேர்</translation>
<translation id="4941246025622441835">நிறுவன மேலாண்மைக்காக சாதனத்தைச் சேர்க்கும்போது இந்தச் சாதனக் கோரிக்கையைப் பயன்படுத்தவும்:</translation>
<translation id="4941627891654116707">எழுத்துரு அளவு</translation>
<translation id="494286511941020793">பதிலி உள்ளமைவு உதவி</translation>
@@ -2654,7 +2658,7 @@
<translation id="5052499409147950210">தளத்தைத் திருத்து</translation>
<translation id="5053604404986157245">தோராயமாக உருவாக்கப்பட்ட TPM கடவுச்சொல் கிடைக்கவில்லை. இது பவர்வாஷுக்குப் பிறகு இயல்பாக ஏற்படக்கூடியது.</translation>
<translation id="5057110919553308744">நீங்கள் நீட்டிப்பைக் கிளிக் செய்யும்போது</translation>
-<translation id="5061347216700970798">{NUM_BOOKMARKS,plural, =1{இந்தக் கோப்புறையில் ஒரு புத்தகக்குறி உள்ளது. அதை நிச்சயமாக நீக்க விரும்புகிறீர்களா?}other{இந்தக் கோப்புறையில் # புத்தகக்குறிகள் உள்ளன. அவற்றை நிச்சயமாக நீக்க விரும்புகிறீர்களா?}}</translation>
+<translation id="5061347216700970798">{NUM_BOOKMARKS,plural, =1{இந்தக் கோப்புறையில் ஒரு புத்தகக்குறி உள்ளது. அதை நிச்சயமாக நீக்க விரும்புகிறீர்களா?}other{இந்தக் கோப்புறையில் # புக்மார்க்குகள் உள்ளன. அவற்றை நிச்சயமாக நீக்க விரும்புகிறீர்களா?}}</translation>
<translation id="5061708541166515394">ஒளி மாறுபாடு</translation>
<translation id="5062930723426326933">உள்நுழைவில் தோல்வி, இணையத்துடன் இணைத்து மீண்டும் முயற்சிக்கவும்.</translation>
<translation id="5063480226653192405">பயன்பாடு</translation>
@@ -2680,7 +2684,7 @@
<translation id="509429900233858213">பிழை ஏற்பட்டது.</translation>
<translation id="5094721898978802975">ஒண்றிணைந்த குறிப்பிட்ட சாதனத்திற்கான பயன்பாடுகளுடன் தொடர்புகொள்ளவும்</translation>
<translation id="5097002363526479830">'<ph name="NAME" />' நெட்வொர்க்குடன் இணைய முடியவில்லை: <ph name="DETAILS" /></translation>
-<translation id="5101042277149003567">புத்தகக்குறிகள் அனைத்தையும் திற</translation>
+<translation id="5101042277149003567">புக்மார்க்குகள் அனைத்தையும் திற</translation>
<translation id="5108967062857032718">அமைப்புகள் - Android பயன்பாடுகளை அகற்றவும்</translation>
<translation id="5109044022078737958">மியா</translation>
<translation id="5111646998522066203">மறைநிலையிலிருந்து வெளியேறு</translation>
@@ -2752,7 +2756,7 @@
<translation id="521582610500777512">படம் விலக்கப்பட்டது</translation>
<translation id="5222676887888702881">வெளியேறு</translation>
<translation id="52232769093306234">தொகுக்க முடியவில்லை.</translation>
-<translation id="5225324770654022472">பயன்பாடுகளின் குறுக்குவழியைக் காட்டு</translation>
+<translation id="5225324770654022472">ஆப்ஸின் ஷார்ட்கட்டைக் காட்டு</translation>
<translation id="5227679487546032910">இயல்பு பசும்நீலநிற அவதார்</translation>
<translation id="5228076606934445476">சாதனத்தில் ஏதோ தவறு உள்ளது. இந்தப் பிழையிலிருந்து மீட்டமைக்க நீங்கள் சாதனத்தை மறுதொடக்கம் செய்து மீண்டும் முயற்சிக்கவும்.</translation>
<translation id="5229189185761556138">உள்ளீட்டு முறைகளை நிர்வகி</translation>
@@ -2871,7 +2875,8 @@
<translation id="5374359983950678924">படத்தை மாற்றுக</translation>
<translation id="5376169624176189338">முந்தைய பக்கத்திற்கு செல்ல கிளிக் செய்க, வரலாற்றைக் காண அழுத்திக்கொண்டே இருங்கள்</translation>
<translation id="5376931455988532197">மிகப் பெரிய கோப்பு</translation>
-<translation id="537813040452600081">இந்தச் சாளரத்தில் நீங்கள் பார்க்கும் பக்கங்கள், உலாவி வரலாற்றில் தோன்றாது, மேலும் நீங்கள் வெளியேறிய பிறகு, பிற தடங்களான குக்கீகள் போன்றவற்றை கணினியில் விட்டுச் செல்லாது. நீங்கள் பதிவிறக்கிய கோப்புகள் மற்றும் உருவாக்கிய புத்தகக்குறிகள் பாதுகாக்கப்படாது.</translation>
+<translation id="5377594097385838788">மறைநிலை</translation>
+<translation id="537813040452600081">இந்தச் சாளரத்தில் நீங்கள் பார்க்கும் பக்கங்கள், உலாவி வரலாற்றில் தோன்றாது, மேலும் நீங்கள் வெளியேறிய பிறகு, பிற தடங்களான குக்கீகள் போன்றவற்றை கணினியில் விட்டுச் செல்லாது. நீங்கள் பதிவிறக்கிய கோப்புகள் மற்றும் உருவாக்கிய புக்மார்க்குகள் பாதுகாக்கப்படாது.</translation>
<translation id="5379140238605961210">மைக்ரோஃபோன் அணுகலை தொடர்ந்து தடு</translation>
<translation id="5379268888377976432">நீக்கியதை செயல்தவிர்</translation>
<translation id="5382591305415226340">ஆதரிக்கப்படும் இணைப்புகளை நிர்வகி</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">பார்வையிடும் இணையதளங்களின் ஐகான்களைப் படிக்கலாம்</translation>
<translation id="5417312524372586921">உலாவித் தீம்கள்</translation>
<translation id="5419294236999569767">கணினி நேரம்</translation>
+<translation id="5419405654816502573">Voice match</translation>
<translation id="5420438158931847627">உரை மற்றும் படங்களின் கூர்மையைத் தீர்மானிக்கிறது</translation>
<translation id="5422221874247253874">ஆக்சஸ் பாயிண்ட்</translation>
<translation id="5422781158178868512">வெளிப்புற சேகரிப்பு சாதனத்தை அறிய முடியவில்லை. மன்னிக்கவும்.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 RSA குறியாக்கம்</translation>
<translation id="5436492226391861498">ப்ராக்ஸி டனலுக்காக காத்திருக்கிறது...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> தளத்தைத் தேடுக:</translation>
+<translation id="543806387003274181">இப்போது உங்கள் கோப்புகளைச் சேமித்து, புதிய கணக்கை அமைக்கவும்.</translation>
<translation id="5438224778284622050">ஆஃப்லைன் கோப்புகளை நீக்கவா?</translation>
<translation id="544083962418256601">குறுக்குவழிகளை உருவாக்கு...</translation>
<translation id="5442228125690314719">டிஸ்க் இமேஜை உருவாக்கும்போது பிழை ஏற்பட்டது. மீண்டும் முயலவும்.</translation>
@@ -2959,14 +2966,14 @@
<translation id="5511379779384092781">மிகச்சிறியது</translation>
<translation id="5511823366942919280">"Shark" சாதனமாக, இதை அமைக்க விரும்புகிறீர்களா?</translation>
<translation id="5512653252560939721">பயனர் சான்றிதழானது வன்பொருளால் பாதுகாக்கப்பட்டதாக இருப்பது அவசியம்.</translation>
-<translation id="5516183516694518900">உங்கள் எல்லாச் சாதனங்களிலும் புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெற, Google கணக்கைப் பயன்படுத்தி Chrome இல் உள்நுழையவும்.</translation>
+<translation id="5516183516694518900">உங்கள் எல்லாச் சாதனங்களிலும் புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெற, Google கணக்கைப் பயன்படுத்தி Chrome இல் உள்நுழையவும்.</translation>
<translation id="551752069230578406">உங்கள் கணக்குடன் பிரிண்டரைச் சேர்க்கிறது - இதற்குச் சில நிமிடங்கள் எடுக்கலாம்...</translation>
<translation id="5518219166343146486">கிளிப்போர்டுக்கு நகலெடுத்த உரையையும் படங்களையும் பார்ப்பதற்குத் தளம் விரும்பும் போது, கேள்</translation>
<translation id="5518584115117143805">மின்னஞ்சல் குறியாக்கச் சான்றிதழ்</translation>
<translation id="5521078259930077036">இந்த முகப்புப் பக்கம் நீங்கள் எதிர்பார்த்தது போன்று உள்ளதா?</translation>
<translation id="5522156646677899028">இந்த நீட்டிப்பு தீவிர பாதுகாப்புப் பாதிப்பைக் கொண்டுள்ளது.</translation>
<translation id="5524517123096967210">கோப்பை படிக்க முடியவில்லை.</translation>
-<translation id="5525677322972469346">புதிய கண்காணிக்கப்படும் பயனரை உருவாக்கு</translation>
+<translation id="5525677322972469346">புதிய மேற்பார்வையிடப்படும் பயனரை உருவாக்கு</translation>
<translation id="5526701598901867718">எல்லாம் (பாதுகாப்பற்றது)</translation>
<translation id="5526745900034778153">ஒத்திசைவைத் தொடர, மீண்டும் உள்நுழையவும்</translation>
<translation id="5527463195266282916">நீட்டிப்பின் தரத்தைக் குறைக்க முயற்சித்தது.</translation>
@@ -3051,7 +3058,7 @@
<translation id="5626134646977739690">பெயர்:</translation>
<translation id="5627086634964711283">முகப்புப் பொத்தானைக் கிளிக் செய்யும்போது காண்பிக்கப்படும் பக்கத்தையும் இது கட்டுப்படுத்துகிறது.</translation>
<translation id="5627676517703583263">Chromeஐப் பயன்படுத்தி, ஸ்மார்ட்டாக உலாவவும்</translation>
-<translation id="562935524653278697">புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளை ஒத்திசைப்பதை உங்கள் நிர்வாகி முடக்கியுள்ளார்.</translation>
+<translation id="562935524653278697">புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளை ஒத்திசைப்பதை உங்கள் நிர்வாகி முடக்கியுள்ளார்.</translation>
<translation id="5632566673632479864">உங்கள் <ph name="EMAIL" /> கணக்கு இனி முதன்மைக் கணக்காகச் செயல்பட அனுமதிக்கப்படாது. இந்தக் கணக்கை <ph name="DOMAIN" /> நிர்வகிப்பதால், உங்கள் புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் இந்தச் சாதனத்திலிருந்து அழிக்கப்படும்.</translation>
<translation id="5632592977009207922">பதிவிறக்குகிறது, <ph name="PERCENT_REMAINING" />% மீதமுள்ளது</translation>
<translation id="563535393368633106">அணுகும் முன் கேள் (பரிந்துரைக்கப்படுகிறது)</translation>
@@ -3150,7 +3157,7 @@
<translation id="5781092003150880845"><ph name="ACCOUNT_FULL_NAME" /> ஆக ஒத்திசை</translation>
<translation id="5781865261247219930"><ph name="EXTENSION_NAME" />க்குக் கட்டளைகளை அனுப்பவும்</translation>
<translation id="5782227691023083829">மொழிபெயர்க்கிறது...</translation>
-<translation id="5783221160790377646">பிழை காரணமாக கண்காணிக்கப்படும் பயனர் உருவாக்கப்படவில்லை. பிறகு முயற்சிக்கவும்.</translation>
+<translation id="5783221160790377646">பிழை காரணமாக மேற்பார்வையிடப்படும் பயனர் உருவாக்கப்படவில்லை. பிறகு முயற்சிக்கவும்.</translation>
<translation id="5783602409389152506">சாதனங்களைத் தேடும் வரை காத்திருக்கவும்...</translation>
<translation id="57838592816432529">ஒலியடக்கு</translation>
<translation id="5785221443435874078">இந்தப் பரிந்துரையை அகற்றும்</translation>
@@ -3173,7 +3180,7 @@
<translation id="5815645614496570556">X.400 முகவரி</translation>
<translation id="5816434091619127343">கோரிய பிரிண்டர் மாற்றங்கள், அதைப் பயன்படுத்த முடியாததாக மாற்றும்.</translation>
<translation id="5817918615728894473">இணை</translation>
-<translation id="5821565227679781414">குறுக்குவழி உருவாக்கு</translation>
+<translation id="5821565227679781414">ஷார்ட்கட் உருவாக்கு</translation>
<translation id="5825412242012995131">ஆன் (பரிந்துரைக்கப்படுவது)</translation>
<translation id="5826507051599432481">பொதுவான பெயர் (CN)</translation>
<translation id="5827266244928330802">Safari</translation>
@@ -3191,7 +3198,7 @@
<translation id="5835754902560991078">மிகமிகக் குறுகியது (0.6வி)</translation>
<translation id="5838456317242088717">நடப்பு மறைநிலை அமர்வு</translation>
<translation id="5842497610951477805">புளூடூத்தை இயக்கு</translation>
-<translation id="5843250171025351504">உங்கள் நிர்வாகியால் குறிப்பிடப்படும் குறைந்தபட்சக் கிளையன்ட் பதிப்புடன் உங்கள் சாதனம் இனி இணங்காது. உள்நுழைய, புதுப்பிக்கவும்.</translation>
+<translation id="5843250171025351504">உங்கள் நிர்வாகியால் குறிப்பிடப்படும் குறைந்தபட்சக் கிளையண்ட் பதிப்புடன் உங்கள் சாதனம் இனி இணங்காது. உள்நுழைய, புதுப்பிக்கவும்.</translation>
<translation id="5849212445710944278">ஏற்கனவே சேர்க்கப்பட்டுள்ளது</translation>
<translation id="5849570051105887917">உள்நாட்டு மொபைல் சேவை வழங்குநர் குறியீடு</translation>
<translation id="5850516540536751549">இந்தக் கோப்பு வகை ஆதரிக்கப்படவில்லை. இந்த வகையான கோப்பைத் திறக்கக்கூடிய பயன்பாட்டைக் கண்டறிய <ph name="BEGIN_LINK" />Chrome இணைய அங்காடியைப்<ph name="END_LINK" /> பார்வையிடவும்.
@@ -3278,7 +3285,7 @@
<translation id="5956585768868398362">இந்தத் தேடல் பக்கம் நீங்கள் எதிர்பார்த்தது போன்று உள்ளதா?</translation>
<translation id="5957613098218939406">கூடுதல் விருப்பங்கள்</translation>
<translation id="5957987129450536192">உங்கள் சுயவிவரப் படத்தின் அருகில் உள்ள பேசும் திரை ஐகானைத் தட்டி, படிக்க வேண்டியதைத் தேர்ந்தெடுக்கவும்.</translation>
-<translation id="5958529069007801266">கண்காணிக்கப்படும் பயனர்</translation>
+<translation id="5958529069007801266">மேற்பார்வையிடப்படும் பயனர்</translation>
<translation id="5959471481388474538">நெட்வொர்க் கிடைக்கவில்லை</translation>
<translation id="595959584676692139">இந்த நீட்டிப்பைப் பயன்படுத்த, பக்கத்தை ரெஃப்ரெஷ் செய்யவும்</translation>
<translation id="5962207703002684882">உங்கள் குரல் மாதிரியை உருவாக்குவதற்கு இந்தப் பதிவுகளை 'அசிஸ்டண்ட்’ பயன்படுத்தும், அது உங்கள் சாதனத்தில் சேமிக்கப்படும். அசிஸ்டண்ட் அமைப்புகளில் மாதிரியை நீக்கலாம் அல்லது மேம்படுத்தலாம். உங்கள் Google செயல்பாட்டுக் கட்டுப்பாடுகளில் குரல் கட்டளைகளைப் பார்க்கலாம் அல்லது நீக்கலாம்.</translation>
@@ -3286,6 +3293,8 @@
<translation id="5965661248935608907">முகப்பு பட்டனைக் கிளிக் செய்யும்போது அல்லது சர்வபுலத்திலிருந்து தேடலை மேற்கொள்ளும்போது காண்பிக்கப்படும் பக்கத்தையும் இது கட்டுப்படுத்துகிறது.</translation>
<translation id="5971037678316050792">புளூடூத் அடாப்டரின் நிலையையும், இணைத்தலையும் கட்டுப்படுத்துதல்</translation>
<translation id="5972017421290582825">MIDI அமைப்புகளை நிர்வகி...</translation>
+<translation id="597235323114979258">மேலும் பிரிண்டர்களைக் காட்டு</translation>
+<translation id="5972666587303800813">No-op Service</translation>
<translation id="5972708806901999743">மேலே நகர்த்து</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> ஐத் தொடங்கு</translation>
<translation id="5975792506968920132">பேட்டரி சார்ஜ் சதவீதம்</translation>
@@ -3362,7 +3371,7 @@
<translation id="6076448957780543068">இந்த ஸ்கிரீன் ஷாட்டைச் சேர்</translation>
<translation id="6077131872140550515">விருப்பப்பட்டியலிலிருந்து அகற்று</translation>
<translation id="6077189836672154517"><ph name="DEVICE_TYPE" /> பற்றிய உதவிக்குறிப்புகளும் அறிவிப்புகளும்</translation>
-<translation id="6078323886959318429">குறுக்குவழியைச் சேர்</translation>
+<translation id="6078323886959318429">ஷார்ட்கட்டைச் சேர்</translation>
<translation id="6078752646384677957">உங்கள் மைக்ரோஃபோனையும் ஆடியோ நிலைகளையும் சரிபார்க்கவும்.</translation>
<translation id="6080515710685820702">பலரும் பயன்படுத்தும் கணினியைப் பயன்படுத்துகிறீர்களா? மறைநிலைச் சாளரத்தைப் பயன்படுத்திப் பார்க்கவும்.</translation>
<translation id="6080689532560039067">கணினி நேரத்தைச் சரிபார்க்கவும்</translation>
@@ -3421,7 +3430,7 @@
<translation id="6160625263637492097">அங்கீகரிப்பிற்குச் சான்றிதழ்களை வழங்கு</translation>
<translation id="6163363155248589649">&amp;இயல்பு</translation>
<translation id="6163522313638838258">அனைத்தையும் விரி...</translation>
-<translation id="6164005077879661055">இந்தக் கண்காணிக்கப்படும் பயனர் அகற்றப்பட்டவுடன் கண்காணிக்கப்படும் பயனருடன் தொடர்புடைய எல்லா கோப்புகளும், அகத் தரவும் நிரந்தரமாக நீக்கப்படும். இந்தக் கண்காணிக்கப்படும் பயனர் பார்வையிட்ட இணையதளங்களையும் அமைப்புகளையும் <ph name="MANAGEMENT_URL" /> இல் இன்னும் நிர்வாகியால் பார்க்க முடியும்.</translation>
+<translation id="6164005077879661055">இந்தக் மேற்பார்வையிடப்படும் பயனர் அகற்றப்பட்டவுடன் மேற்பார்வையிடப்படும் பயனருடன் தொடர்புடைய எல்லா கோப்புகளும், அகத் தரவும் நிரந்தரமாக நீக்கப்படும். இந்தக் மேற்பார்வையிடப்படும் பயனர் பார்வையிட்ட இணையதளங்களையும் அமைப்புகளையும் <ph name="MANAGEMENT_URL" /> இல் இன்னும் நிர்வாகியால் பார்க்க முடியும்.</translation>
<translation id="6165508094623778733">மேலும் அறிக</translation>
<translation id="6166185671393271715">Chromeக்குக் கடவுச்சொற்களை இறக்குதல்</translation>
<translation id="6169040057125497443">உங்கள் மைக்ரோஃபோனைச் சரிபார்க்கவும்.</translation>
@@ -3656,6 +3665,7 @@
<translation id="6527303717912515753">பகிர்</translation>
<translation id="6528513914570774834">இந்தச் சாதனத்தின் பிற பயனர்களையும் இந்த நெட்வொர்க்கைப் பயன்படுத்த அனுமதி</translation>
<translation id="652948702951888897">Chrome வரலாறு</translation>
+<translation id="6530186581263215931">இந்த அமைப்புகள் உங்கள் நிர்வாகியால் அமலாக்கப்படுகின்றன</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> ஐ ஒத்திசைக்கிறது...</translation>
<translation id="6531282281159901044">ஆபத்தான கோப்பை வைத்திரு</translation>
<translation id="6532101170117367231">Google இயக்ககத்தில் சேமி</translation>
@@ -3694,7 +3704,7 @@
<translation id="6590458744723262880">கோப்புறையின் பெயரை மாற்றவும்</translation>
<translation id="6592267180249644460">WebRTC பதிவு எடுக்கப்பட்ட நேரம் <ph name="WEBRTC_LOG_CAPTURE_TIME" /></translation>
<translation id="6594883168703494535">உங்கள் Google கணக்கில் உள்நுழைய, Smart Lockகைப் பயன்படுத்தவும்</translation>
-<translation id="6596325263575161958">குறியாக்க விருப்பங்கள்</translation>
+<translation id="6596325263575161958">என்கோடர் விருப்பங்கள்</translation>
<translation id="6596816719288285829">IP முகவரி</translation>
<translation id="6597017209724497268">மாதிரிகள்</translation>
<translation id="659934686219830168">இந்தப் பக்கத்திலிருந்து நீங்கள் வெளியேறியதும், ஒத்திசைவு தொடங்கும்</translation>
@@ -3790,7 +3800,7 @@
<translation id="6736045498964449756">அச்சச்சோ, கடவுச்சொற்கள் பொருந்தவில்லை!</translation>
<translation id="6736243959894955139">முகவரி</translation>
<translation id="6736329909263487977"><ph name="ISSUED_BY" /> [<ph name="ISSUED_TO" />]</translation>
-<translation id="6739923123728562974">டெஸ்க்டாப் குறுக்குவழியைக் காட்டு</translation>
+<translation id="6739923123728562974">டெஸ்க்டாப் ஷார்ட்கட்டைக் காட்டு</translation>
<translation id="6740234557573873150"><ph name="FILE_NAME" /> பதிவிறக்கம் இடைநிறுத்தப்பட்டது</translation>
<translation id="6742339027238151589">ஸ்கிரிப்ட் அணுகலாம்</translation>
<translation id="6745592621698551453">இப்போது புதுப்பி</translation>
@@ -3814,7 +3824,7 @@
<translation id="6781284683813954823">Doodle இணைப்பு</translation>
<translation id="6782111308708962316">குக்கீத் தரவைச் சேமிப்பதிலிருந்தும் படிப்பதிலிருந்தும் மூன்றாம் தரப்பு இணையதளங்களைத் தடு</translation>
<translation id="6786747875388722282">நீட்டிப்புகள்</translation>
-<translation id="6787839852456839824">விசைப்பலகைக் குறுக்குவழிகள்</translation>
+<translation id="6787839852456839824">கீபோர்டு ஷார்ட்கட்கள்</translation>
<translation id="6788210894632713004">தொகுக்கப்படாத நீட்டிப்பு</translation>
<translation id="6790428901817661496">இயக்கு</translation>
<translation id="6790497603648687708">தொலைநிலையில் <ph name="EXTENSION_NAME" /> சேர்க்கப்பட்டது</translation>
@@ -3829,7 +3839,7 @@
<translation id="6802031077390104172"><ph name="USAGE" /> (<ph name="OID" />)</translation>
<translation id="6804671422566312077">&amp;புதிய சாளரத்தில் எல்லா புக்மார்க்ஸையும் திற</translation>
<translation id="6805038906417219576">சரி</translation>
-<translation id="6805647936811177813"><ph name="HOST_NAME" /> இல் இருந்து கிளையன்ட் சான்றிதழை இறக்குமதி செய்ய <ph name="TOKEN_NAME" /> இல் தயவுசெய்து உள்நுழைக.</translation>
+<translation id="6805647936811177813"><ph name="HOST_NAME" /> இல் இருந்து கிளையண்ட் சான்றிதழை இறக்குமதி செய்ய <ph name="TOKEN_NAME" /> இல் தயவுசெய்து உள்நுழைக.</translation>
<translation id="680572642341004180"><ph name="SHORT_PRODUCT_OS_NAME" /> இல் RLZ கண்காணிப்பை இயக்கு.</translation>
<translation id="6806699711453372963">Linux பகிர்வை நிர்வகி</translation>
<translation id="6810613314571580006">சேமித்த நற்சான்றிதழ்களைப் பயன்படுத்தி இணையதளங்களில் தானாகவே உள்நுழையும். இந்த அம்சம் முடக்கப்பட்டிருக்கும் போது, ஒவ்வொரு முறை இணையதளத்தில் உள்நுழைவதற்கு முன் உறுதிப்படுத்தும்படி கேட்கும்.</translation>
@@ -3957,7 +3967,7 @@
<translation id="6998793565256476099">வீடியோ கலந்துரையாடலுக்கு, சாதனத்தைப் பதிவுசெய்</translation>
<translation id="7000347579424117903">Ctrl, Alt அல்லது தேடல் விசையைப் பயன்படுத்தித் தொடங்கவும்</translation>
<translation id="7002055706763150362">Chromebookக்கான Smart Lockஐ அமைக்க, இது நீங்கள் தான் என்பதை Google உறுதிப்படுத்த வேண்டும்—தொடங்க, கடவுச்சொல்லை உள்ளிடவும்.</translation>
-<translation id="7002454948392136538">இந்தக் கண்காணிக்கப்படும் பயனருக்கான நிர்வாகியைத் தேர்வுசெய்க</translation>
+<translation id="7002454948392136538">இந்தக் மேற்பார்வையிடப்படும் பயனருக்கான நிர்வாகியைத் தேர்வுசெய்க</translation>
<translation id="7003339318920871147">வலை தரவுத்தளங்கள்</translation>
<translation id="7003723821785740825">சாதனத்தை விரைவாகத் திறப்பதற்கான வழியை அமைக்கவும்</translation>
<translation id="7004499039102548441">சமீபத்திய தாவல்கள்</translation>
@@ -3974,7 +3984,6 @@
<translation id="7018275672629230621">உங்கள் உலாவல் வரலாற்றை படிக்கலாம் மற்றும் மாற்றலாம்</translation>
<translation id="7019805045859631636">வேகமான</translation>
<translation id="7022562585984256452">உங்களின் முகப்பு பக்கம் அமைக்கப்பட்டது.</translation>
-<translation id="702384510542929236">சில சாதனத் தகவலையும் பக்க உள்ளடக்கத்தையும் அடையாளம் நீக்கி Googleளுக்கு அனுப்பும்</translation>
<translation id="7025190659207909717">மொபைல் டேட்டா சேவை மேலாண்மை</translation>
<translation id="7027125358315426638">தரவுத்தளப் பெயர்:</translation>
<translation id="7029809446516969842">கடவுச்சொற்கள்</translation>
@@ -4005,7 +4014,7 @@
<translation id="7066944511817949584">"<ph name="DEVICE_NAME" />" க்கு இணைப்பதில் தோல்வி.</translation>
<translation id="7067725467529581407">இதை ஒருபோதும் காட்டாதே.</translation>
<translation id="7070484045139057854">இந்த நீட்டிப்பால் தளத் தரவைப் படிக்கவும் மாற்றவும் முடியும்</translation>
-<translation id="7072010813301522126">குறுக்குவழி பெயர்</translation>
+<translation id="7072010813301522126">ஷார்ட்கட் பெயர்</translation>
<translation id="707392107419594760">உங்கள் விசைப்பலகையைத் தேர்ந்தெடு:</translation>
<translation id="7075513071073410194">RSA குறியாக்கத்துடன் PKCS #1 MD5</translation>
<translation id="7075625805486468288">HTTPS/SSL சான்றிதழ்களையும் அமைப்புகளையும் நிர்வகிக்கவும்</translation>
@@ -4116,7 +4125,7 @@
<translation id="7238585580608191973">SHA-256 விரல்அச்சு</translation>
<translation id="7240120331469437312">சான்றிதழ் பொருள் மாற்றுப் பெயர்</translation>
<translation id="7240339475467890413">புதிய ஹாட்ஸ்பாட்டுடன் இணைக்கவா?</translation>
-<translation id="7241389281993241388">கிளையன்ட் சான்றிதழை இறக்குமதி செய்ய தயவுசெய்து <ph name="TOKEN_NAME" /> இல் உள்நுழைக.</translation>
+<translation id="7241389281993241388">கிளையண்ட் சான்றிதழை இறக்குமதி செய்ய தயவுசெய்து <ph name="TOKEN_NAME" /> இல் உள்நுழைக.</translation>
<translation id="7243632151880336635">அழித்து, வெளியேறு</translation>
<translation id="7245628041916450754"><ph name="WIDTH" /> x <ph name="HEIGHT" /> (சிறந்தது)</translation>
<translation id="7246947237293279874">FTP ப்ராக்ஸி</translation>
@@ -4154,6 +4163,7 @@
<translation id="7289225569524511578">வால்பேப்பர் பயன்பாட்டைத் திற</translation>
<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> ஹோஸ்ட் செய்யும் இந்த உள்நுழைவுச் சேவை உங்கள் கேமராவிற்கான அணுகலைக் கோரியுள்ளது.</translation>
<translation id="7290594223351252791">பதிவை உறுதிசெய்க</translation>
+<translation id="7292696521213967957">அசிஸ்டண்ட்டைப் பிழைதிருத்துவதற்கான தகவல்</translation>
<translation id="7295662345261934369">பிறருடன் பகிர்</translation>
<translation id="729583233778673644">AES மற்றும் RC4 என்க்ரிப்ஷனை அனுமதிக்கும். RC4 சைஃபர்கள் பாதுகாப்பற்றது என்பதால், இந்த விருப்பத்தைப் பயன்படுத்துவது, உங்கள் அபாயத்தை அதிகரிக்கும்.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> விதிமுறைகள்</translation>
@@ -4188,14 +4198,14 @@
<translation id="7345706641791090287">கடவுச்சொல்லை உறுதிப்படுத்தவும்</translation>
<translation id="7346909386216857016">சரி, புரிந்தது</translation>
<translation id="7347751611463936647">இந்த நீட்டிப்பைப் பயன்படுத்துவதற்கு, "<ph name="EXTENSION_KEYWORD" />" என தட்டச்சு செய்து, TABஐ அழுத்தி, பின்னர் உங்கள் கட்டளை அல்லது தேடலைத் தட்டச்சு செய்யவும்.</translation>
-<translation id="7348093485538360975">ஆன்-ஸ்கிரீன் விசைப்பலகை</translation>
+<translation id="7348093485538360975">ஸ்கிரீன் கீபோர்ட்</translation>
<translation id="7352651011704765696">ஏதோ தவறு ஏற்பட்டது</translation>
<translation id="735361434055555355">Linuxஸை நிறுவுகிறது...</translation>
<translation id="7353887511974462734">ஏற்கனவே உள்ள குழுவில் சேர்</translation>
<translation id="735745346212279324">VPN துண்டிக்கப்பட்டது</translation>
<translation id="7359359531237882347"><ph name="NUMBER_OF_ITEMS" /> உள்ளடக்கங்களை நகலெடுக்கிறது...</translation>
<translation id="7359588939039777303">விளம்பரங்கள் தடுக்கப்பட்டன.</translation>
-<translation id="7360183604634508679">புத்தகக்குறிகள் மெனு</translation>
+<translation id="7360183604634508679">புக்மார்க்குகள் மெனு</translation>
<translation id="7360233684753165754"><ph name="PAGE_NUMBER" /> பக்கங்கள் - <ph name="PRINTER_NAME" /></translation>
<translation id="7361297102842600584"><ph name="PLUGIN_NAME" />ஐ இயக்க, வலது கிளிக் செய்யவும்</translation>
<translation id="7361537270840348817">Chromebookகிலிருந்து உங்கள் ஃபோனின் இணைப்பைத் துண்டிக்கும்</translation>
@@ -4254,7 +4264,6 @@
<translation id="7456847797759667638">இருப்பிடத்தைத் திற...</translation>
<translation id="7461924472993315131">நிலையாக வை</translation>
<translation id="7463006580194749499">நபரைச் சேர்</translation>
-<translation id="7464902436585505072">"Ok Google" குரல் மாதிரி</translation>
<translation id="7465778193084373987">Netscape சான்றிதழ் தளர்த்தல் URL</translation>
<translation id="7469894403370665791">இந்த நெட்வொர்க்குடன் தானாகவே இணைக்கவும்</translation>
<translation id="747114903913869239">பிழை: நீட்டிப்பை குறி இறக்கம் செய்ய முடியவில்லை</translation>
@@ -4282,6 +4291,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> மற்றும் அதனுடன் தொடர்புடைய தரவு இந்தச் சாதனத்திலிருந்து அகற்றப்படும்.</translation>
<translation id="7497215489070763236">சேவையக CA சான்றிதழ்</translation>
<translation id="7497981768003291373">சமீபத்தில் எடுக்கப்பட்ட WebRTC உரைப் பதிவுகள் எதுவும் இல்லை.</translation>
+<translation id="7502199377020483660">இந்தக் கார்டுகளை உங்கள் எல்லாச் சாதனங்களிலும் பயன்படுத்த, அவற்றை உங்கள் ‘Google கணக்கில்’ சேமிக்கவும்</translation>
<translation id="7502658306369382406">IPv6 முகவரி</translation>
<translation id="7503191893372251637">Netscape சான்றிதழ் வகை</translation>
<translation id="7503821294401948377">உலாவிச் செயல்பாட்டிற்காக படவுரு '<ph name="ICON" />' ஐ ஏற்ற முடியவில்லை.</translation>
@@ -4314,7 +4324,7 @@
<translation id="7556033326131260574">Smart Lock ஆல் உங்கள் கணக்கைச் சரிபார்க்க முடியவில்லை. நுழைவதற்கு உங்கள் கடவுச்சொல்லை உள்ளிடவும்.</translation>
<translation id="7556242789364317684">துரதிருஷ்டவசமாக, <ph name="SHORT_PRODUCT_NAME" /> ஆல் உங்கள் அமைப்புகளை மீட்க முடியவில்லை. பிழையைச் சரிசெய்வதற்கு, உங்கள் சாதனத்தை <ph name="SHORT_PRODUCT_NAME" /> பவர்வாஷ் மூலம் மீட்டமைக்க வேண்டும்.</translation>
<translation id="7559719679815339381">காத்திருக்கவும்....கியாஸ்க் பயன்பாடு புதுப்பிக்கப்படுகிறது. USB சாதனத்தை அகற்றாதீர்கள்.</translation>
-<translation id="7563991800558061108">இந்தப் பிழையிலிருந்து மீட்டமைக்க, உள்நுழைவுத் திரையிலிருந்து உங்கள் Google கணக்கில் உள்நுழைய வேண்டும். பின்னர் உங்கள் Google கணக்கிலிருந்து வெளியேறி, கண்காணிக்கப்படும் பயனரை மீண்டும் உருவாக்க முயற்சிக்கலாம்.</translation>
+<translation id="7563991800558061108">இந்தப் பிழையிலிருந்து மீட்டமைக்க, உள்நுழைவுத் திரையிலிருந்து உங்கள் Google கணக்கில் உள்நுழைய வேண்டும். பின்னர் உங்கள் Google கணக்கிலிருந்து வெளியேறி, மேற்பார்வையிடப்படும் பயனரை மீண்டும் உருவாக்க முயற்சிக்கலாம்.</translation>
<translation id="756445078718366910">உலாவி சாளரத்தைத் திற</translation>
<translation id="7564847347806291057">செயலாக்கத்தை முடி</translation>
<translation id="7566118625369982896">Play பயன்பாடு இணைப்புகளை நிர்வகி</translation>
@@ -4377,6 +4387,7 @@
<translation id="7663719505383602579">ரிசீவர்: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">ஆதரிக்கப்படாத புளூடூத் சாதனம்: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">கணக்கைச் சேர்</translation>
+<translation id="7667248760110172428">வெளிப்புறச் சேமிப்பகம்</translation>
<translation id="7671130400130574146">முறைமை தலைப்புப் பட்டியையும் கரைகளையும் பயன்படுத்து</translation>
<translation id="7672520070349703697"><ph name="PAGE_TITLE" /> இல் <ph name="HUNG_IFRAME_URL" />.</translation>
<translation id="7676867886086876795">உரை புலங்களில் நீங்கள் சொல்வதை எழுதும் வசதியை அனுமதிக்க, Googleளுக்கு உங்கள் குரலை அனுப்பும்.</translation>
@@ -4391,7 +4402,7 @@
<translation id="7690853182226561458">&amp;கோப்புறையைச் சேர்...</translation>
<translation id="769569204874261517"><ph name="USER_DISPLAY_NAME" /> (ஏற்கனவே இந்தச் சாதனத்தில் உள்ளார்)</translation>
<translation id="7696063401938172191">உங்கள் '<ph name="PHONE_NAME" />' இல்:</translation>
-<translation id="7698408911093959127">{COUNT,plural, =1{புத்தகக்குறிப் பட்டியலில் 1 புத்தகக்குறி உள்ளது}other{புத்தகக்குறிப் பட்டியலில் # புத்தகக்குறிகள் உள்ளன}}</translation>
+<translation id="7698408911093959127">{COUNT,plural, =1{புத்தகக்குறிப் பட்டியலில் 1 புத்தகக்குறி உள்ளது}other{புத்தகக்குறிப் பட்டியலில் # புக்மார்க்குகள் உள்ளன}}</translation>
<translation id="7701040980221191251">எதுவுமில்லை</translation>
<translation id="7701869757853594372">USER ஹேண்டில்ஸ்</translation>
<translation id="7702574632857388784">பட்டியலிலிருந்து <ph name="FILE_NAME" />ஐ அகற்று</translation>
@@ -4584,13 +4595,14 @@
<translation id="7930294771522048157">சேமிக்கப்பட்ட பேமெண்ட் முறைகள் இங்கு காண்பிக்கப்படும்</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> உங்கள் திரையையும் ஆடியோவையும் பகிர்கிறது.</translation>
<translation id="7931318309563332511">தெரியவில்லை</translation>
+<translation id="7932969338829957666">Linuxஸில் <ph name="BASE_DIR" /> என்பதில் பகிர்ந்த கோப்புறைகள் கிடைக்கின்றன.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{தளத்தின் ஒலியை இயக்கு}other{தளங்களின் ஒலியை இயக்கு}}</translation>
<translation id="7934414805353235750">பாதுகாக்கப்பட்ட உள்ளடக்கத்தை இயக்க <ph name="URL" /> விரும்புகிறது. உங்கள் சாதனத்தின் அடையாளத்தை Google சரிபார்க்கும்.</translation>
<translation id="793531125873261495">விர்ச்சுவல் மெஷினைப் பதிவிறக்கும்போது பிழை ஏற்பட்டது. மீண்டும் முயலவும்.</translation>
<translation id="7938594894617528435">தற்போது ஆஃப்லைனில் உள்ளது</translation>
<translation id="7939062555109487992">மேம்பட்ட விருப்பங்கள்</translation>
<translation id="7939412583708276221">எப்படியும் வைத்திரு</translation>
-<translation id="7939997691108949385">இந்தக் கண்காணிக்கப்படும் பயனருக்கான கட்டுப்பாடுகள் மற்றும் அமைப்புகளை நிர்வாகியால் <ph name="MANAGEMENT_URL" /> இல் உள்ளமைக்க முடியும்.</translation>
+<translation id="7939997691108949385">இந்தக் மேற்பார்வையிடப்படும் பயனருக்கான கட்டுப்பாடுகள் மற்றும் அமைப்புகளை நிர்வாகியால் <ph name="MANAGEMENT_URL" /> இல் உள்ளமைக்க முடியும்.</translation>
<translation id="7943837619101191061">இடத்தைச் சேர்...</translation>
<translation id="7945031593909029181">"<ph name="CHROME_EXTENSION_NAME" />" இணைய விரும்புகிறது</translation>
<translation id="7946586320617670168">மூலம் பாதுகாப்பானதாக இருக்க வேண்டும்</translation>
@@ -4627,7 +4639,7 @@
<translation id="798835209536175951">உங்கள் Chromebookகில் இருந்து மெசேஜ்களை அனுப்பலாம், பெறலாம். <ph name="LINK_BEGIN" />மேலும் அறிக<ph name="LINK_END" /></translation>
<translation id="7988355189918024273">அணுகல்தன்மை அம்சங்களை இயக்கு</translation>
<translation id="7994702968232966508">EAP முறை</translation>
-<translation id="799547531016638432">குறுக்குவழியை அகற்று</translation>
+<translation id="799547531016638432">ஷார்ட்கட்டை அகற்று</translation>
<translation id="7997826902155442747">செயல்படுத்தல் முன்னுரிமை</translation>
<translation id="7999229196265990314">பின்வரும் கோப்புகள் உருவாக்கப்பட்டன:
@@ -4675,6 +4687,7 @@
<translation id="8049705080247101012">"<ph name="EXTENSION_NAME" />"ஐத் தீங்கானது என Google கொடியிட்டுள்ளது, மேலும் நிறுவல் தடுக்கப்பட்டுள்ளது</translation>
<translation id="8049913480579063185">நீட்டிப்பின் பெயர்</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">Windows மென்பொருளைப் பயன்படுத்தும் PCக்காக இந்தக் கோப்பு வடிவமைக்கப்பட்டுள்ளது. Chrome OSஸில் இயங்கும் உங்கள் சாதனத்திற்கு இது இணக்கமானதல்ல. <ph name="BEGIN_LINK_HELP" />மேலும் அறிக<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 கோப்புகள்</translation>
<translation id="8053390638574070785">இந்த பக்கத்தை மீண்டும் ஏற்றுக</translation>
<translation id="8054517699425078995">இந்த வகையான கோப்பு , உங்கள் சாதனத்திற்கு தீங்கு விளைவிக்கலாம். எப்படியேனும் <ph name="FILE_NAME" /> ஐ வைத்திருக்க விரும்புகிறீர்களா?</translation>
@@ -4732,7 +4745,7 @@
<translation id="8137559199583651773">நீட்டிப்புகளை நிர்வகிக்கவும்</translation>
<translation id="8138082791834443598">விருப்பத்தேர்வுக்குரியது — புதிய தகவலை உள்ளிடவும் அல்லது இந்தச் சாதனத்துடன் தொடர்புடைய ஏற்கனவேயுள்ள தகவலைப் புதுப்பிக்கவும்.</translation>
<translation id="813913629614996137">துவக்குகிறது...</translation>
-<translation id="8140778357236808512">ஏற்கனவே உள்ள கண்காணிக்கப்படும் பயனரை இறக்குமதிசெய்யவும்</translation>
+<translation id="8140778357236808512">ஏற்கனவே உள்ள மேற்பார்வையிடப்படும் பயனரை இறக்குமதிசெய்யவும்</translation>
<translation id="8141725884565838206">உங்கள் கடவுச்சொற்களை நிர்வகிக்கவும்</translation>
<translation id="8142441511840089262">இரு கிளிக்</translation>
<translation id="8143442547342702591">தவறான பயன்பாடு</translation>
@@ -4779,7 +4792,7 @@
<translation id="8206354486702514201">இந்த அமைப்பு உங்கள் நிர்வாகியால் செயலாக்கப்பட்டுள்ளது.</translation>
<translation id="8206581664590136590">உபயோகம் &amp; கண்டறிதல் தரவை அனுப்புக. கண்டறிதல் தரவு, சாதனம் மற்றும் ஆப்ஸ் உபயோகத் தரவு போன்றவற்றை Googleளுக்குத் தானாக அனுப்புவதன் மூலம் உங்கள் பிள்ளையின் Android அனுபவத்தை மேம்படுத்த உதவுக. இது உங்கள் பிள்ளையை அடையாளம் கண்டறியப் பயன்படுத்தப்படாது, இது சிஸ்டம் மற்றும் ஆப்ஸின் நிலைத்தன்மையை மேம்படுத்தவும் பிற மேம்பாடுகளைச் செய்யவும் உதவும். ஒருங்கிணைக்கப்பட்ட சில தரவுகள், Google ஆப்ஸ் மற்றும் Android டெவெலப்பர்கள் போன்ற கூட்டாளர்களுக்கும் உதவும். உங்கள் பிள்ளையின் கணக்கில் கூடுதல் ’இணையம் &amp; ஆப்ஸ் செயல்பாடு’ அமைப்பு இயக்கப்பட்டிருந்தால், இந்தத் தரவு அவரது Google கணக்கில் சேமிக்கப்படலாம். <ph name="BEGIN_LINK1" />மேலும் அறிக<ph name="END_LINK1" /></translation>
<translation id="8206745257863499010">ப்ளூஸி</translation>
-<translation id="8209677645716428427">உங்கள் வழிகாட்டுதல் மூலம் கண்காணிக்கப்படும் பயனர் இணையத்தை உலாவலாம். Chrome இல் கண்காணிக்கப்படும் பயனரின் நிர்வாகியாக நீங்கள் இதைச் செய்யலாம்:</translation>
+<translation id="8209677645716428427">உங்கள் வழிகாட்டுதல் மூலம் மேற்பார்வையிடப்படும் பயனர் இணையத்தை உலாவலாம். Chrome இல் மேற்பார்வையிடப்படும் பயனரின் நிர்வாகியாக நீங்கள் இதைச் செய்யலாம்:</translation>
<translation id="8212008074015601248">{NUM_DOWNLOAD,plural, =1{பதிவிறக்கம் செயலில் உள்ளது}other{பதிவிறக்கங்கள் செயலில் உள்ளன}}</translation>
<translation id="8213449224684199188">படப் பயன்முறைக்குச் சென்றது</translation>
<translation id="8213577208796878755">கிடைக்கும் இன்னொரு சாதனம்.</translation>
@@ -4824,7 +4837,7 @@
<ph name="BEGIN_PARAGRAPH4" />உங்கள் பிள்ளைக்கான அமைப்பில் கூடுதல் ’இணையம் மற்றும் ஆப்ஸ் செயல்பாட்டு அமைப்பு’ இயக்கப்பட்டிருந்தால், இந்தத் தரவு அவரது Google கணக்கில் சேமிக்கப்படலாம். இந்த அமைப்புகளைப் பற்றி மேலும் அறியவும் அவற்றை எவ்வாறு திருத்தி அமைக்கலாம் என்பதைத் தெரிந்துகொள்ளவும் families.google.com என்பதற்குச் செல்லவும்.<ph name="END_PARAGRAPH4" /></translation>
<translation id="8270242299912238708">PDF ஆவணங்கள்</translation>
<translation id="827097179112817503">முகப்பு பொத்தானைக் காட்டு</translation>
-<translation id="8271246892936492311">{COUNT,plural, =1{ஒரு புத்தகக்குறி நீக்கப்பட்டது}other{# புத்தகக்குறிகள் நீக்கப்பட்டன}}</translation>
+<translation id="8271246892936492311">{COUNT,plural, =1{ஒரு புத்தகக்குறி நீக்கப்பட்டது}other{# புக்மார்க்குகள் நீக்கப்பட்டன}}</translation>
<translation id="8272443605911821513">"கூடுதல் கருவிகள்" மெனுவில் நீட்டிப்புகள் என்பதைக் கிளிக் செய்து நீட்டிப்புகளை நிர்வகிக்கவும்.</translation>
<translation id="8272966760965438857">உங்கள் Google கணக்குகளை ஒரே இடத்திலிருந்து நிர்வகிக்கலாம்</translation>
<translation id="8274332263553132018">கோப்பை அலைபரப்பு</translation>
@@ -4918,6 +4931,7 @@
<translation id="8438566539970814960">தேடல்களையும் உலாவலையும் மேலும் சிறப்பாக்குக</translation>
<translation id="8439506636278576865">பக்கங்களை இந்த மொழியில் மொழிபெயர்ப்பதற்கான அனுமதி</translation>
<translation id="8440630305826533614">Linux ஆப்ஸ்</translation>
+<translation id="8443338615972234259">உங்கள் மேற்பார்வையிடப்படும் பயனருக்கு இப்போது ஒரு புதிய கணக்கை உருவாக்கவும்.</translation>
<translation id="8446884382197647889">மேலும் அறிக</translation>
<translation id="8447409163267621480">கன்ட்ரோல் அல்லது ஆல்ட் விசையைப் பயன்படுத்தித் தொடங்கவும்</translation>
<translation id="8448729345478502352">திரையில் உள்ளவற்றைச் சிறிதாக்கும் அல்லது பெரிதாக்கும்</translation>
@@ -4942,6 +4956,7 @@
<translation id="8468750959626135884"><ph name="DEVICE_TYPE" /> சாதனத்தை உங்கள் Android மொபைலைப் பயன்படுத்தித் திறக்கலாம்.</translation>
<translation id="8470028084415844044">உங்கள் எல்லாச் சாதனங்களிலும் எல்லாக் கடவுச்சொற்களையும் பெற, ஒத்திசைவை இயக்கவும்.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" />க்கான சேமித்த கடவுச்சொற்கள்</translation>
+<translation id="8471635086304129332">இந்தக் கார்டை உங்கள் எல்லாச் சாதனங்களிலும் பயன்படுத்த, அதை உங்கள் ‘Google கணக்கில்’ சேமிக்கவும்</translation>
<translation id="8472623782143987204">வன்பொருளைச் சார்ந்தது</translation>
<translation id="8473863474539038330">முகவரிகள் மற்றும் பல</translation>
<translation id="8475313423285172237">உங்கள் கணினியில் உள்ள மற்றொரு நிரலானது, Chrome வேலைசெய்யும் வழியை மாற்றும் நீட்டிப்பைச் சேர்த்துள்ளது.</translation>
@@ -4978,7 +4993,7 @@
<translation id="8535005006684281994">Netscape சான்றிதழ் புதுப்பிப்பு URL</translation>
<translation id="8538358978858059843">அலைபரப்பலுக்கான கிளவுட் சேவைகளை இயக்கவா?</translation>
<translation id="8539727552378197395">இல்லை (Httpமட்டும்)</translation>
-<translation id="8545575359873600875">மன்னிக்கவும், உங்கள் கடவுச்சொல் சரிபார்க்கப்படவில்லை. இந்தக் கண்காணிக்கப்படும் பயனரின் நிர்வாகி சமீபத்தில் கடவுச்சொல்லை மாற்றியிருக்கலாம். அவ்வாறு இருந்தால், நீங்கள் அடுத்த முறை உள்நுழையும்போது புதிய கடவுச்சொல் செயலாக்கப்படும். உங்கள் பழைய கடவுச்சொல்லைப் பயன்படுத்தி முயற்சிக்கவும்.</translation>
+<translation id="8545575359873600875">மன்னிக்கவும், உங்கள் கடவுச்சொல் சரிபார்க்கப்படவில்லை. இந்தக் மேற்பார்வையிடப்படும் பயனரின் நிர்வாகி சமீபத்தில் கடவுச்சொல்லை மாற்றியிருக்கலாம். அவ்வாறு இருந்தால், நீங்கள் அடுத்த முறை உள்நுழையும்போது புதிய கடவுச்சொல் செயலாக்கப்படும். உங்கள் பழைய கடவுச்சொல்லைப் பயன்படுத்தி முயற்சிக்கவும்.</translation>
<translation id="8546186510985480118">சாதனத்தில் காலியிடம் குறைவாக உள்ளது</translation>
<translation id="8546306075665861288">பட தற்காலிக சேமிப்பு</translation>
<translation id="8546541260734613940">[*.]example.com</translation>
@@ -5017,7 +5032,6 @@
<translation id="8598453409908276158">சாண்ட்பாக்ஸ் செய்யப்படாத செருகுநிரல் தடுக்கப்பட்டது</translation>
<translation id="8601206103050338563">TLS WWW கிளையன்ட அங்கீகரிப்பு</translation>
<translation id="8602851771975208551">உங்கள் கணினியில் உள்ள மற்றொரு நிரலானது, Chrome வேலைசெய்யும் வழியை மாற்றும் பயன்பாட்டைச் சேர்த்துள்ளது.</translation>
-<translation id="8604763363205185560">Chromeமின் அம்சங்களையும் பாதுகாப்பையும் மேம்படுத்த உதவுக</translation>
<translation id="8605428685123651449">SQLite நினைவகம்</translation>
<translation id="8606726445206553943">MIDI சாதனங்களைப் பயன்படுத்தவும்</translation>
<translation id="8609465669617005112">மேலே நகர்த்து</translation>
@@ -5032,7 +5046,7 @@
<translation id="862727964348362408">இடைநீக்கப்பட்டது</translation>
<translation id="862750493060684461">CSS தற்காலிக சேமிப்பு</translation>
<translation id="8627795981664801467">பாதுகாப்பான இணைப்புகள் மட்டும்</translation>
-<translation id="8630903300770275248">கண்காணிக்கப்படும் பயனரை இறக்குமதிசெய்</translation>
+<translation id="8630903300770275248">மேற்பார்வையிடப்படும் பயனரை இறக்குமதிசெய்</translation>
<translation id="8631032106121706562">பெட்டல்ஸ்</translation>
<translation id="8637542770513281060">உங்கள் கணினியில் பாதுகாப்பு மாட்யூல் உள்ளது. இது Chrome OS இல் உள்ள பல முக்கியமான பாதுகாப்பு அம்சங்களைச் செயல்படுத்தப் பயன்படுத்தப்படுகிறது. மேலும் அறிய, Chromebook உதவி மையத்திற்குச் செல்லவும்: https://support.google.com/chromebook/?p=sm</translation>
<translation id="8637688295594795546">கணினிப் புதுப்பிப்பு உள்ளது. பதிவிறக்கத் தயாராகிறது...</translation>
@@ -5077,7 +5091,7 @@
<translation id="8677212948402625567">அனைத்தையும் சுருக்கு...</translation>
<translation id="8678648549315280022">பதிவிறக்க அமைப்புகளை நிர்வகிக்கவும்...</translation>
<translation id="8678933587484842200">இந்தப் பயன்பாட்டை எப்படித் துவக்க விரும்புகிறீர்கள்?</translation>
-<translation id="8680251145628383637">உள்நுழைந்து, உங்கள் சாதனங்கள் எல்லாவற்றிலும் உள்ள புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெறவும். உங்கள் Google சேவைகளிலும் தானாகவே உள்நுழைவீர்கள்.</translation>
+<translation id="8680251145628383637">உள்நுழைந்து, உங்கள் சாதனங்கள் எல்லாவற்றிலும் உள்ள புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகளைப் பெறவும். உங்கள் Google சேவைகளிலும் தானாகவே உள்நுழைவீர்கள்.</translation>
<translation id="8686213429977032554">இந்த இயக்ககக் கோப்பு இன்னும் பகிரப்படவில்லை</translation>
<translation id="8688579245973331962">உங்கள் பெயரைப் பார்க்கவில்லையா?</translation>
<translation id="8688591111840995413">எளிதான கடவுச்சொல்</translation>
@@ -5175,7 +5189,7 @@
<translation id="881799181680267069">மற்றதை மறை</translation>
<translation id="8818152010000655963">வால்பேப்பர்</translation>
<translation id="8818958672113348984">எனது மொபைல் வழியாகச் சரிபார்</translation>
-<translation id="8820817407110198400">புத்தகக்குறிகள்</translation>
+<translation id="8820817407110198400">புக்மார்க்குகள்</translation>
<translation id="8821045908425223359">IP முகவரியைத் தானாகவே உள்ளமை</translation>
<translation id="882204272221080310">கூடுதல் பாதுகாப்பிற்கு, நிலைபொருளைப் புதுப்பி.</translation>
<translation id="8823514049557262177">இணைப்பு &amp;உரையை நகலெடு</translation>
@@ -5193,6 +5207,7 @@
<translation id="8846141544112579928">விசைப்பலகையைத் தேடுகிறது...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">உங்கள் சாதனங்களை இணைக்கும்போது, ​​உங்கள் Chromebook இவற்றைச் செய்யலாம் என்பதை ஏற்கிறீர்கள்:</translation>
+<translation id="8850251000316748990">மேலும் காட்டு...</translation>
<translation id="8859057652521303089">உங்கள் மொழியைத் தேர்ந்தெடுங்கள்:</translation>
<translation id="8859174528519900719">துணைச்சட்டகம்: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel விரிதாள்</translation>
@@ -5228,7 +5243,7 @@
<translation id="890616557918890486">மூலத்தை மாற்று</translation>
<translation id="8909833622202089127">தளமானது உங்கள் இருப்பிடத்தைக் கண்காணிக்கிறது</translation>
<translation id="8910146161325739742">உங்கள் திரையைப் பகிரலாம்</translation>
-<translation id="8910222113987937043">புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் உங்கள் Google கணக்கிற்கு இனி ஒத்திசைக்கப்படாது. இருப்பினும், ஏற்கனவே உங்களிடம் உள்ள தரவு தொடர்ந்து Google கணக்கில் சேமிக்கப்படும். அவற்றை <ph name="BEGIN_LINK" />Google டாஷ்போர்டில்<ph name="END_LINK" /> நிர்வகிக்கலாம்.</translation>
+<translation id="8910222113987937043">புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் உங்கள் Google கணக்கிற்கு இனி ஒத்திசைக்கப்படாது. இருப்பினும், ஏற்கனவே உங்களிடம் உள்ள தரவு தொடர்ந்து Google கணக்கில் சேமிக்கப்படும். அவற்றை <ph name="BEGIN_LINK" />Google டாஷ்போர்டில்<ph name="END_LINK" /> நிர்வகிக்கலாம்.</translation>
<translation id="8912362522468806198">Google கணக்கு</translation>
<translation id="8912793549644936705">விரிவாக்கு</translation>
<translation id="891365694296252935">உபயோகம் &amp; கண்டறிதல் தரவை அனுப்புக. கண்டறிதல் தரவு, சாதனம் மற்றும் ஆப்ஸ் உபயோகத் தரவு போன்றவற்றை இந்தச் சாதனம் தற்போது Googleளுக்குத் தானாக அனுப்புகிறது. இது உங்கள் பிள்ளையை அடையாளம் கண்டறியப் பயன்படுத்தப்படாது, இது சிஸ்டம் மற்றும் ஆப்ஸின் நிலைத்தன்மையை மேம்படுத்தவும் பிற மேம்பாடுகளைச் செய்யவும் உதவும். ஒருங்கிணைக்கப்பட்ட சில தரவுகள், Google ஆப்ஸ் மற்றும் Android டெவெலப்பர்கள் போன்ற கூட்டாளர்களுக்கும் உதவும். உரிமையாளர் இந்த அமைப்பைச் செயல்படுத்தியுள்ளார். உங்கள் பிள்ளையின் கணக்கில் கூடுதல் ’இணையம் &amp; ஆப்ஸ் செயல்பாடு’ அமைப்பு இயக்கப்பட்டிருந்தால், இந்தத் தரவு அவருடைய Google கணக்கில் சேமிக்கப்படலாம். <ph name="BEGIN_LINK1" />மேலும் அறிக<ph name="END_LINK1" /></translation>
@@ -5254,7 +5269,7 @@
<translation id="894871326938397531">மறைநிலையிலிருந்து வெளியேறவா?</translation>
<translation id="895347679606913382">தொடங்குகிறது...</translation>
<translation id="895944840846194039">JavaScript நினைவகம்</translation>
-<translation id="8959810181433034287">கண்காணிக்கப்படும் பயனர் உள்நுழைவதற்கு இந்தக் கடவுச்சொல்லைப் பயன்படுத்த வேண்டியிருக்கும், அதனால் பாதுகாப்பான கடவுச்சொல்லைத் தேர்வுசெய்யவும், மேலும் கண்காணிக்கப்படும் பயனருடன் இதைப் பற்றி கலந்துரையாட மறக்க வேண்டாம்</translation>
+<translation id="8959810181433034287">மேற்பார்வையிடப்படும் பயனர் உள்நுழைவதற்கு இந்தக் கடவுச்சொல்லைப் பயன்படுத்த வேண்டியிருக்கும், அதனால் பாதுகாப்பான கடவுச்சொல்லைத் தேர்வுசெய்யவும், மேலும் மேற்பார்வையிடப்படும் பயனருடன் இதைப் பற்றி கலந்துரையாட மறக்க வேண்டாம்</translation>
<translation id="8962083179518285172">விவரங்களை மறை</translation>
<translation id="8962918469425892674">நகர்வு அல்லது ஒளி சென்சார்களை இந்தத் தளம் பயன்படுத்துகிறது.</translation>
<translation id="8965037249707889821">பழைய கடவுச்சொல்லை உள்ளிடு</translation>
@@ -5388,7 +5403,7 @@
<translation id="9153934054460603056">அடையாளம் மற்றும் கடவுச்சொல்லைச் சேமி</translation>
<translation id="9154194610265714752">புதுப்பிக்கப்பட்டது</translation>
<translation id="9154418932169119429">இந்தப் படம் ஆஃப்லைனில் கிடைக்காது.</translation>
-<translation id="91568222606626347">குறுக்கு வழியை உருவாக்கு...</translation>
+<translation id="91568222606626347">ஷார்ட்கட்டை உருவாக்கு...</translation>
<translation id="9157697743260533322">அனைத்து பயனர்களுக்கும் தானியங்கு புதுப்பிப்புகளை அமைக்க முடியவில்லை (ப்ரீஃபிளைட் செயலாக்கப் பிழை: <ph name="ERROR_NUMBER" />)</translation>
<translation id="9158715103698450907">அச்சச்சோ! அங்கீகரிப்பின்போது நெட்வொர்க் தகவல்தொடர்பு சிக்கல் ஏற்பட்டது. உங்கள் நெட்வொர்க் இணைப்பைச் சோதித்து மீண்டும் முயலவும்.</translation>
<translation id="916607977885256133">பிக்ச்சர்-இன்-பிக்ச்சர்</translation>
@@ -5428,7 +5443,7 @@
<translation id="93343527085570547">சட்டரீதியான காரணங்களுக்காக உள்ளடக்கத்தை மாற்றக் கோருவதற்கு, <ph name="BEGIN_LINK1" />சட்ட உதவிப் பக்கத்திற்குச்<ph name="END_LINK1" /> செல்லவும். சில கணக்கு மற்றும் சாதனத் தகவல்கள் Googleளுக்கு அனுப்பப்படலாம். நீங்கள் எங்களுக்கு அளிக்கும் தகவல்களை, எங்கள் <ph name="BEGIN_LINK2" />தனியுரிமைக் கொள்கை<ph name="END_LINK2" /> மற்றும் <ph name="BEGIN_LINK3" />சேவை விதிமுறைகள்<ph name="END_LINK3" /> ஆகியவற்றுக்கு உட்பட்டு, தொழில்நுட்பச் சிக்கல்களைத் தீர்க்கவும் எங்கள் சேவைகளை மேம்படுத்தவும் பயன்படுத்துவோம்.</translation>
<translation id="93393615658292258">கடவுச்சொல் மட்டும்</translation>
<translation id="934503638756687833">தேவைப்பட்டால், இங்கே பட்டியலிடப்படாத உருப்படிகளும் அகற்றப்படும். Chrome தனியுரிமைத் தகவல் கையேட்டில் &lt;a href="<ph name="URL" />"&gt;தேவையற்ற மென்பொருளிலிருந்து பாதுகாப்பு&lt;/a&gt; பற்றி மேலும் அறிக.</translation>
-<translation id="935490618240037774">புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் உங்கள் Google கணக்குடன் ஒத்திசைக்கப்படும் என்பதால் அவற்றை எல்லா சாதனங்களிலும் பயன்படுத்தலாம்.</translation>
+<translation id="935490618240037774">புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் உங்கள் Google கணக்குடன் ஒத்திசைக்கப்படும் என்பதால் அவற்றை எல்லா சாதனங்களிலும் பயன்படுத்தலாம்.</translation>
<translation id="936801553271523408">முறைமை பகுப்பாய்வு தரவு</translation>
<translation id="93766956588638423">நீட்டிப்பைப் பழுதுநீக்கு</translation>
<translation id="938339467127511841">Linux (பீட்டா) சேமிப்பகம்</translation>
@@ -5450,7 +5465,7 @@
<translation id="962802172452141067">புத்தகக்குறி கோப்புறை ட்ரீ</translation>
<translation id="964286338916298286">உங்கள் சாதனத்திற்கான Chrome சலுகைகளை உங்கள் IT நிர்வாகி முடக்கியுள்ளார்.</translation>
<translation id="964439421054175458">{NUM_APLLICATIONS,plural, =1{இணங்காத பயன்பாடு}other{இணங்காத பயன்பாடுகள்}}</translation>
-<translation id="967007123645306417">உங்கள் Google கணக்குகளிலிருந்து வெளியேற்றப்படுவீர்கள். இனி உங்கள் Google கணக்குடன் புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் ஒத்திசைக்கப்படாது. இருப்பினும், ஏற்கனவே சேமிக்கப்பட்ட உங்கள் தரவு Google கணக்கில் அப்படியே இருக்கும், அவற்றை <ph name="BEGIN_LINK" />Google டாஷ்போர்டில்<ph name="END_LINK" /> நிர்வகிக்கலாம்.</translation>
+<translation id="967007123645306417">உங்கள் Google கணக்குகளிலிருந்து வெளியேற்றப்படுவீர்கள். இனி உங்கள் Google கணக்குடன் புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் ஒத்திசைக்கப்படாது. இருப்பினும், ஏற்கனவே சேமிக்கப்பட்ட உங்கள் தரவு Google கணக்கில் அப்படியே இருக்கும், அவற்றை <ph name="BEGIN_LINK" />Google டாஷ்போர்டில்<ph name="END_LINK" /> நிர்வகிக்கலாம்.</translation>
<translation id="967624055006145463">சேமிக்கப்பட்ட தரவின்படி</translation>
<translation id="968000525894980488">Google Play சேவைகளை இயக்கவும்.</translation>
<translation id="968174221497644223">பயன்பாட்டு தற்காலிக சேமிப்பு</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_te.xtb b/chromium/chrome/app/resources/generated_resources_te.xtb
index 2e10bd55539..55e9a9f511d 100644
--- a/chromium/chrome/app/resources/generated_resources_te.xtb
+++ b/chromium/chrome/app/resources/generated_resources_te.xtb
@@ -11,7 +11,7 @@
<translation id="1010833424573920260">{NUM_PAGES,plural, =1{పేజీ ప్రతిస్పందించడం లేదు}other{పేజీలు ప్రతిస్పందించడం లేదు}}</translation>
<translation id="1012794136286421601">మీ డాక్స్, షీట్‌లు, స్లయిడ్‌లు మరియు డ్రాయింగ్‌ల ఫైల్‌లు సమకాలీకరించబడుతున్నాయి. వీటిని ఆన్‌లైన్ లేదా ఆఫ్‌లైన్‌లో యాక్సెస్ చేయడానికి Google డిస్క్ యాప్‌ని తెరవండి.</translation>
<translation id="1012876632442809908">USB-C పరికరం (ముందువైపు పోర్ట్)</translation>
-<translation id="1013707859758800957">ఈ పేజీలో అమలు కావడానికి శాండ్‌బాక్స్ చేయని ప్లగిన్ అనుమతించబడింది.</translation>
+<translation id="1013707859758800957">ఈ పేజీలో అమలు కావడానికి శాండ్‌బాక్స్ చేయని ప్లగ్ఇన్‌ అనుమతించబడింది.</translation>
<translation id="1015318665228971643">ఫోల్డర్ పేరును సవరించండి</translation>
<translation id="1016437870506746108">{COUNT,plural, =0{అన్నింటినీ &amp;కొత్త విండోలో తెరవండి}=1{&amp;కొత్త విండోలో తెరవండి}other{అన్నింటినీ (#) &amp;కొత్త విండోలో తెరవండి}}</translation>
<translation id="1016566241875885511">అదనపు సమాచారం (ఐచ్ఛికం)</translation>
@@ -20,7 +20,7 @@
<translation id="1023873740278604399">మీ వేలిముద్ర యొక్క వేర్వేరు భాగాలను జోడించడానికి మీ వేలిని కొద్దిగా జరపండి.</translation>
<translation id="1026822031284433028">చిత్రాన్ని లోడ్ చేయండి</translation>
<translation id="1029317248976101138">జూమ్ చేయి:</translation>
-<translation id="1030706264415084469"><ph name="URL" /> శాశ్వతంగా అధిక డేటాను మీ పరికరంలో నిల్వ చేయాలనుకుంటోంది</translation>
+<translation id="1030706264415084469">డేటాను మీ పరికరంలో అధిక మొత్తంలో, శాశ్వతంగా నిల్వ చేయాలని <ph name="URL" /> అనుకుంటోంది</translation>
<translation id="1031362278801463162">ప్రివ్యూ లోడ్ అవుతోంది</translation>
<translation id="103279545524624934">Android యాప్‌లను ప్రారంభించడానికి డిస్క్ స్థలాన్ని ఖాళీ చేయండి.</translation>
<translation id="1033780634303702874">మీ క్రమానుసార పరికరాలను యాక్సెస్ చేయడం</translation>
@@ -42,7 +42,7 @@
<translation id="1049795001945932310">&amp;భాష సెట్టింగ్‌లు</translation>
<translation id="1049926623896334335">Word పత్రం</translation>
<translation id="1054153489933238809">అసలు &amp;చిత్రాన్ని కొత్త ట్యాబ్‌లో తెరువు</translation>
-<translation id="1055806300943943258">బ్లూటూత్ మరియు USB పరికరాల కోసం శోధిస్తోంది...</translation>
+<translation id="1055806300943943258">బ్లూటూత్, USB పరికరాల కోసం శోధిస్తోంది...</translation>
<translation id="1056466516655540509"><ph name="MINUTES" /> నిమిషాల క్రితం అప్‌డేట్ చేయబడింది</translation>
<translation id="1056775291175587022">నెట్‌వర్క్‌లు లేవు</translation>
<translation id="1056898198331236512">హెచ్చరిక</translation>
@@ -60,7 +60,7 @@
<translation id="1076698951459398590">థీమ్‌ను ప్రారంభించు</translation>
<translation id="1076818208934827215">Microsoft Internet Explorer</translation>
<translation id="1079766198702302550">ఎల్లప్పుడూ కెమెరా యాక్సెస్‌ను బ్లాక్ చేయి</translation>
-<translation id="1082398631555931481"><ph name="THIRD_PARTY_TOOL_NAME" /> మీ Chrome సెట్టింగ్‌లను వాటి అసలు డిఫాల్ట్‌లకు పునరుద్ధరించాలనుకుంటోంది. ఇది మీ హోమ్ పేజీని, కొత్త ట్యాబ్ పేజీని మరియు శోధన ఇంజిన్‌ను రీసెట్ చేస్తుంది, మీ ఎక్స్‌టెన్షన్‌లను నిలిపివేస్తుంది మరియు ట్యాబ్‌లు అన్నింటినీ అన్‌పిన్ చేస్తుంది. ఇది కుక్కీలు, కంటెంట్ మరియు సైట్ డేటా వంటి ఇతర తాత్కాలిక మరియు కాష్ చేసిన డేటాను కూడా తీసివేస్తుంది.</translation>
+<translation id="1082398631555931481"><ph name="THIRD_PARTY_TOOL_NAME" /> మీ Chrome సెట్టింగ్‌లను వాటి అసలు డిఫాల్ట్‌లకు పునరుద్ధరించాలనుకుంటోంది. ఇది మీ హోమ్ పేజీని, కొత్త ట్యాబ్ పేజీని, శోధన ఇంజిన్‌ను రీసెట్ చేస్తుంది. మీ ఎక్స్‌టెన్ష‌న్‌లను నిలిపివేస్తుంది. ట్యాబ్‌లన్నింటినీ అన్‌పిన్ చేస్తుంది. ఇది కుక్కీలు, కంటెంట్, సైట్ డేటా వంటి ఇతర తాత్కాలిక మరియు కాష్ చేసిన డేటాను కూడా తీసివేస్తుంది.</translation>
<translation id="1082725763867769612">ఆఫ్‌లైన్ ఫైల్‌లు</translation>
<translation id="1084824384139382525">లింక్ చిరు&amp;నామాను కాపీ చెయ్యి</translation>
<translation id="1085697365578766383">వర్చువల్ మెషిన్‌ను ప్రారంభించడంలో ఎర్రర్ ఏర్పడింది. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
@@ -77,7 +77,7 @@
<translation id="1112420131909513020">బ్యాక్‌గ్రౌండ్‌ ట్యాబ్ బ్లూటూత్‌ను ఉపయోగిస్తోంది</translation>
<translation id="1114102982691049955"><ph name="PRINTER_MANUFACTURER" /> <ph name="PRINTER_MODEL" /> (USB)</translation>
<translation id="1114202307280046356">చతుర్భుజం</translation>
-<translation id="1114335938027186412">మీ కంప్యూటర్‌లో ట్రస్టెడ్ ప్లాట్‌ఫామ్ మాడ్యూల్ (TPM) భద్రతా పరికరం ఉంది, ఇది Chrome OSలో అనేక కీలకమైన భద్రతా ఫీచర్‌లను అమలు చేయడానికి ఉపయోగించబడుతుంది. మరింత తెలుసుకోవడానికి Chromebook సహాయ కేంద్రాన్ని సందర్శించండి: https://support.google.com/chromebook/?p=tpm</translation>
+<translation id="1114335938027186412">మీ కంప్యూటర్ ట్రస్టెడ్ ప్లాట్‌ఫారమ్ మాడ్యూల్ (TPM) భద్రతా పరికరాన్ని కలిగి ఉంది. ఇది Chrome OSలో అనేక కీలకమైన భద్రతా ఫీచ‌ర్‌ల‌ను అమలు చేయడానికి ఉపయోగించబడుతుంది. మరింత తెలుసుకోవడానికి Chromebook సహాయ కేంద్రాన్ని సందర్శించండి: https://support.google.com/chromebook/?p=tpm</translation>
<translation id="1114525161406758033">మూత మూసి ఉన్నప్పుడు స్లీప్ స్థితికి వెళ్లు</translation>
<translation id="1116639326869298217">మీ గుర్తింపును ధృవీకరించడం సాధ్యపడలేదు</translation>
<translation id="1116694919640316211">గురించి</translation>
@@ -96,11 +96,11 @@
<translation id="1128591060186966949">శోధన ఇంజిన్‌ను సవరించండి</translation>
<translation id="1134009406053225289">అజ్ఞాత విండోలో తెరువు</translation>
<translation id="1137673463384776352">లింక్‌ను <ph name="APP" />లో తెరువు</translation>
-<translation id="1140351953533677694">మీ బ్లూటూత్ మరియు క్రమానుసార పరికరాలను యాక్సెస్ చేయడం</translation>
-<translation id="1140610710803014750">మీ బుక్‌మార్క్‌లను మీ అన్ని పరికరాలలోనూ పొందాలంటే, సైన్ ఇన్ చేసి, సమకాలీకరణను ఆన్ చేయండి.</translation>
+<translation id="1140351953533677694">మీ బ్లూటూత్‌ను, క్రమానుసార పరికరాలను యాక్సెస్‌ చేయడం</translation>
+<translation id="1140610710803014750">మీ బుక్‌మార్క్‌లను మీ అన్ని పరికరాలలోనూ పొందడానికి, సైన్ ఇన్ చేసి, సింక్‌ను ఆన్ చేయండి.</translation>
<translation id="1140746652461896221">మీరు సందర్శించే ఏ పేజీలో అయినా కంటెంట్‌ని బ్లాక్ చేయండి</translation>
<translation id="1143142264369994168">సర్టిఫికెట్ సంతకందారు</translation>
-<translation id="1145292499998999162">ప్లగిన్ బ్లాక్ చేయబడింది</translation>
+<translation id="1145292499998999162">ప్లగ్ఇన్‌ బ్లాక్ చేయబడింది</translation>
<translation id="1145532888383813076">మీ పరికరం, యాప్‌లు మరియు వెబ్‌ను వెతకండి.</translation>
<translation id="1146204723345436916">HTML ఫైల్ నుండి బుక్‌మార్క్‌లను దిగుమతి చేయి...</translation>
<translation id="114721135501989771">Chromeలో Google స్మార్ట్‌లను పొందండి</translation>
@@ -113,7 +113,7 @@
<translation id="1151917987301063366">సెన్సార్‌లను యాక్సెస్ చేయడానికి ఎల్లవేళలా <ph name="HOST" />ని అనుమతించు</translation>
<translation id="1153356358378277386">జత చేసిన పరికరాలు</translation>
<translation id="1156488781945104845">ప్రస్తుత సమయం</translation>
-<translation id="1161575384898972166">దయచేసి క్లయింట్ స‌ర్టిఫికెట్‌ను ఎగుమతి చేయ‌డానికి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చేయండి.</translation>
+<translation id="1161575384898972166">క్లయింట్ సర్టిఫికెట్‌ను ఎగుమతి చేయడానికి, దయచేసి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చేయండి.</translation>
<translation id="1161699061380012396">Chrome OS ఇన్‌పుట్ విధానం</translation>
<translation id="1163931534039071049">ఫ్రేమ్ మూలాన్ని &amp;వీక్షించండి</translation>
<translation id="1164674268730883318"><ph name="DEVICE_TYPE" />కు Smart Lockని ఆఫ్ చేయాలా?</translation>
@@ -122,7 +122,7 @@
<translation id="1166212789817575481">కుడివైపు టాబ్‌లను మూసివెయ్యి</translation>
<translation id="1168020859489941584"><ph name="TIME_REMAINING" />లో తెరవబడుతోంది...</translation>
<translation id="1168100932582989117">Google పేరు సర్వర్‌లు</translation>
-<translation id="1171135284592304528">కీబోర్డ్ దృష్టి కేంద్రీకరణ గల ఆబ్జెక్ట్ మారినప్పుడు దాన్ని హైలైట్ చేస్తుంది</translation>
+<translation id="1171135284592304528">కీబోర్డ్ దృష్టి కేంద్రీకరణ గల ఆబ్జెక్ట్ మారినప్పుడు దానిని హైలైట్ చేస్తుంది</translation>
<translation id="1173894706177603556">పేరుమార్చు</translation>
<translation id="1174073918202301297">షార్ట్‌కట్ జోడించబడింది</translation>
<translation id="117445914942805388">మీ అన్ని సమకాలీకరించబడుతున్న పరికరాలతో సహా, మీ Google ఖాతా నుండి బ్రౌజింగ్ డేటాను తీసివేయడానికి, <ph name="BEGIN_LINK" />సమకాలీకరణ సెట్టింగ్‌లను సందర్శించండి<ph name="END_LINK" />.</translation>
@@ -133,13 +133,13 @@
<translation id="1178581264944972037">పాజ్ చేయి</translation>
<translation id="1181037720776840403">తీసివేయి</translation>
<translation id="1183237619868651138">స్థానిక కాష్‌లో <ph name="EXTERNAL_CRX_FILE" />ను ఇన్‌స్టాల్ చేయడం సాధ్యపడదు.</translation>
-<translation id="1185924365081634987">మీరు ఈ నెట్‌వర్క్ ఎర్రర్‌ను పరిష్కరించడానికి <ph name="GUEST_SIGNIN_LINK_START" />అతిథిగా బ్రౌజ్ చేయడం<ph name="GUEST_SIGNIN_LINK_END" /> కూడా ప్రయత్నించవచ్చు.</translation>
+<translation id="1185924365081634987">మీరు ఈ నెట్‌వర్క్ ఎర్ర‌ర్‌ను పరిష్కరించడానికి <ph name="GUEST_SIGNIN_LINK_START" />అతిథిగా బ్రౌజ్ చేయడాన్ని<ph name="GUEST_SIGNIN_LINK_END" /> కూడా ప్రయత్నించవచ్చు.</translation>
<translation id="1186771945450942097">హానికరమైన సాఫ్ట్‌వేర్‌ని తీసివేయండి</translation>
<translation id="1187722533808055681">ఇన్‌యాక్టివ్‌ మేల్కొలుపులు</translation>
-<translation id="1188807932851744811">లాగ్ అప్‌లోడ్ చేయబడలేదు.</translation>
+<translation id="1188807932851744811">లాగ్ అప్‌లోడ్ కాలేదు.</translation>
<translation id="1189418886587279221">మీ పరికరాన్ని సులభంగా ఉపయోగించడానికి యాక్సెస్‌ సౌల‌భ్య‌ ఫీచ‌ర్‌ల‌ను ప్రారంభించండి.</translation>
<translation id="1190144681599273207">ఈ ఫైల్‌ను పొందడానికి మొబైల్ డేటాలో సుమారుగా <ph name="FILE_SIZE" /> ఉపయోగించబడుతుంది.</translation>
-<translation id="11901918071949011">{NUM_FILES,plural, =1{మీ కంప్యూటర్‌లో నిల్వ చేసిన ఫైల్‌ను యాక్సెస్ చేయండి}other{మీ కంప్యూటర్‌లో నిల్వ చేసిన # ఫైల్‌లను యాక్సెస్ చేయండి}}</translation>
+<translation id="11901918071949011">{NUM_FILES,plural, =1{మీ కంప్యూటర్‌లో నిల్వ చేసిన ఫైల్‌ను యాక్సెస్ చేయండి}other{ మీ కంప్యూటర్‌లో నిల్వ చేసిన # ఫైల్‌లను యాక్సెస్ చేయండి}}</translation>
<translation id="1190660338026981543"><ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> ద్వారా సంస్థ నిర్వహణకు మీ <ph name="DEVICE_TYPE" /> విజయవంతంగా నమోదు చేయబడింది.</translation>
<translation id="119092896208640858">బ్రౌజింగ్ డేటాను మీ Google ఖాతాలో అలాగే ఉంచి, కేవలం ఈ పరికరం నుండి మాత్రమే తీసివేయడానికి <ph name="BEGIN_LINK" />సైన్ అవుట్ చేయండి<ph name="END_LINK" />.</translation>
<translation id="1193273168751563528">నిర్వహిత సెషన్‌లోకి వెళ్లండి</translation>
@@ -155,11 +155,11 @@
<translation id="1211364473545090084">అజ్ఞాత విండోలో మీ బ్రౌజింగ్ చరిత్రను సేవ్ చేయకుండానే వెబ్‌ని ఉపయోగించండి</translation>
<translation id="1213037489357051291"><ph name="NUM_FINGERPRINTS" /> వేలిముద్రలు సెటప్ చేయబడ్డాయి</translation>
<translation id="1215411991991485844">కొత్త బ్యాక్‌గ్రౌండ్‌ యాప్ జోడించబడింది</translation>
-<translation id="1216659994753476700">మమ్మల్ని క్షమించండి. మేము మీ ప్రొఫైల్‌ను యాక్సెస్ చేయలేకపోయాము. ఈ పరికరంలో నిల్వ చేయబడిన ఫైల్‌లు మరియు డేటా కోల్పోయి ఉండవచ్చు.<ph name="BR" />
+<translation id="1216659994753476700">మమ్మల్ని క్షమించండి. మేము మీ ప్రొఫైల్‌ను యాక్సెస్ చేయలేకపోయాము. ఈ పరికరంలో అయిన ఫైల్‌లు మరియు డేటా కోల్పోయి ఉండవచ్చు.<ph name="BR" />
<ph name="BR" />
మీరు మీ ప్రొఫైల్‌ను మళ్లీ సెటప్ చేయాల్సి ఉంటుంది.<ph name="BR" />
<ph name="BR" />
- తదుపరి స్క్రీన్‌లో, దయచేసి ఈ సమస్యను పరిష్కరించడంలో మాకు సహాయపడటానికి అభిప్రాయాన్ని పంపండి.</translation>
+ ఈ సమస్యను పరిష్కరించడంలో మాకు సహాయపడటానికి, దయచేసి మీ అభిప్రాయాన్ని తర్వాతి స్క్రీన్‌లో పంపండి.</translation>
<translation id="1217668622537098248">చర్య తర్వాత తిరిగి ఎడమ క్లిక్ వద్దకు మారు</translation>
<translation id="121783623783282548">పాస్‌‌వర్డ్‌లు సరిపోలలేదు.</translation>
<translation id="1218839827383191197"><ph name="BEGIN_PARAGRAPH1" />ఈ పరికర స్థానాన్ని అంచనా వేయడంలో సహాయపడటానికి Wi‑Fi, మొబైల్ నెట్‌వర్క్‌లు మరియు సెన్సార్‌ల వంటి మూలాధారాలను Google స్థాన సేవ ఉపయోగిస్తుంది.<ph name="END_PARAGRAPH1" />
@@ -194,11 +194,11 @@
<translation id="126710816202626562">అనువాద భాష:</translation>
<translation id="126768002343224824">16x</translation>
<translation id="1272079795634619415">ఆపు</translation>
-<translation id="1272978324304772054">ఈ వినియోగదారు ఖాతా, పరికరం నమోదు చేయబడిన డొమైన్‌కు చెందినది కాదు. మీరు వేరొక డొమైన్‌కు నమోదు చేయాలనుకుంటే మీరు ముందుగా పరికరాన్ని పునరుద్ధరించాలి.</translation>
+<translation id="1272978324304772054">ఈ వినియోగదారు ఖాతా పరికరం నమోదు చేయబడిన డొమైన్‌కు చెందినది కాదు. మీరు వేరొక డొమైన్‌కు నమోదు చేయాలనుకుంటే మీరు ముందుగా పరికరాన్ని పునరుద్ధరించాలి.</translation>
<translation id="1274977772557788323">Adobe Flash Player నిల్వ సెట్టింగ్‌లు</translation>
<translation id="1274997165432133392">కుక్కీలు మరియు ఇతర సైట్ డేటా</translation>
<translation id="127668050356036882">మీ అన్ని విండోలను మూసివేయండి</translation>
-<translation id="1277908057200820621">పరికర జాబితాను వీక్షించండి</translation>
+<translation id="1277908057200820621">పరికర జాబితాను చూడండి</translation>
<translation id="1280820357415527819">మొబైల్ నెట్‌వర్క్‌ల కోసం వెతుకుతోంది</translation>
<translation id="1285320974508926690">ఈ సైట్‌ను అనువదించవద్దు</translation>
<translation id="1285484354230578868">మీ Google డిస్క్ ఖాతాలో డేటాను నిల్వ చేయండి</translation>
@@ -208,7 +208,7 @@
<translation id="1293556467332435079">ఫైళ్ళు</translation>
<translation id="1296497012903089238">ప్రమాణపత్రం రకం</translation>
<translation id="1297175357211070620">గమ్యం</translation>
-<translation id="1297922636971898492">Google డిస్క్ ప్రస్తుతం అందుబాటులో లేదు. Google డిస్క్ అందుబాటులోకి వచ్చిన తర్వాత అప్‌లోడ్ స్వయంచాలకంగా మళ్లీ ప్రారంభమవుతుంది.</translation>
+<translation id="1297922636971898492">Google డిస్క్ ప్రస్తుతం అందుబాటులో లేదు. Google డిస్క్ అందుబాటులోకి వచ్చిన తర్వాత అప్‌లోడ్ ఆటోమేటిక్‌గా మళ్లీ ప్రారంభమవుతుంది.</translation>
<translation id="1300415640239881824">ఈ పరికరంలో రక్షిత కంటెంట్‌కు మెరుగుపరిచిన ప్లేబ్యాక్ అర్హత ఉందో లేదో నిర్ధారించడానికి, <ph name="DOMAIN" /> మీ పరికర గుర్తింపును Google ద్వారా ధృవీకరించాలనుకుంటోంది.</translation>
<translation id="1300806585489372370">ఈ సెట్టింగ్‌ని మార్చాలంటే, ముందుగా <ph name="BEGIN_LINK" />ఐడెంటిఫైయర్‌లను ఆన్ చేయండి<ph name="END_LINK" /></translation>
<translation id="1302227299132585524">Apple ఈవెంట్‌ల నుండి JavaScriptని అనుమతించు</translation>
@@ -217,7 +217,7 @@
<translation id="1306606229401759371">సెట్టింగ్‌లను మార్చు</translation>
<translation id="1307559529304613120">అయ్యో! సిస్టమ్ ఈ పరికరం కోసం దీర్ఘకాల API యాక్సెస్ టోకెన్‌ను నిల్వ చేయడంలో విఫలమైంది.</translation>
<translation id="1307931752636661898">Linux ఫైల్‌లను చూడటం సాధ్యపడలేదు</translation>
-<translation id="1313405956111467313">స్వయంచాలక ప్రాక్సీ కాన్ఫిగరేషన్</translation>
+<translation id="1313405956111467313">ఆటోమేటిక్‌ ప్రాక్సీ కాన్ఫిగరేషన్</translation>
<translation id="131364520783682672">Caps Lock</translation>
<translation id="1313705515580255288">మీ బుక్‌మార్క్‌లు, చరిత్ర, ఇతర సెట్టింగ్‌లు మీ Google ఖాతాకు సింక్ చేయ‌బ‌డ‌తాయి.</translation>
<translation id="1314565355471455267">Android VPN</translation>
@@ -225,7 +225,7 @@
<translation id="1316136264406804862">శోధిస్తోంది...</translation>
<translation id="1316495628809031177">సమకాలీకరణ పాజ్ చేయబడింది</translation>
<translation id="1322046419516468189">మీ <ph name="SAVED_PASSWORDS_STORE" />లో సేవ్ చేసిన పాస్‌వర్డ్‌లను చూడండి మరియు నిర్వహించండి</translation>
-<translation id="1326317727527857210">మీ ఇతర పరికరాల నుండి మీ ట్యాబ్‌లను పొందడానికి, Chromeకి సైన్ ఇన్ చేయండి.</translation>
+<translation id="1326317727527857210">మీ ఇతర పరికరాల నుండి మీ ట్యాబ్‌లను పొందడానికి, Chromeకు సైన్ ఇన్ చేయండి.</translation>
<translation id="1327074568633507428">Google క్లౌడ్ ప్రింట్‌లోని ప్రింటర్</translation>
<translation id="1327977588028644528">గేట్‌వే</translation>
<translation id="1329584516321524826">ఇప్పుడే నవీకరించబడింది</translation>
@@ -234,11 +234,11 @@
<translation id="133535873114485416">ప్రాధాన్య ఇన్‌పుట్</translation>
<translation id="1338776410427958681"><ph name="FOLDER_NAME" />ని కుదించండి</translation>
<translation id="1338950911836659113">తొలగిస్తోంది...</translation>
-<translation id="1340527397989195812">ఫైల్‌ల‌ యాప్‌‌ను ఉపయోగించి పరికరం నుండి మీడియాను బ్యాకప్ చేయండి.</translation>
+<translation id="1340527397989195812">'ఫైల్‌లు' యాప్‌ను ఉపయోగించి పరికరం నుండి మీడియాను బ్యాకప్ చేయండి.</translation>
<translation id="1341988552785875222">ప్రస్తుత వాల్‌పేపర్‌ను '<ph name="APP_NAME" />' సెట్ చేసింది. మీరు వేరొక వాల్‌పేపర్‌ను ఎంచుకోవడానికి ముందు '<ph name="APP_NAME" />'ను అన్ఇన్‌స్టాల్ చేయాల్సి రావచ్చు.</translation>
<translation id="1346748346194534595">కుడి</translation>
<translation id="1347256498747320987">అప్‌డేట్‌లు &amp; యాప్‌లను ఇన్‌స్టాల్ చేయండి. కొనసాగించడం ద్వారా, ఈ పరికరం Google, మీ క్యారియర్ మరియు మీ పరికర తయారీదారు నుండి అప్‌డేట్‌లు మరియు యాప్‌లను ఆటోమేటిక్‌గా కూడా డౌన్‌లోడ్ మరియు ఇన్‌స్టాల్ చేయవచ్చని మీరు అంగీకరిస్తున్నారు, బహుశా సెల్యులార్ డేటా ఉపయోగించబడవచ్చు. ఈ యాప్‌లలో కొన్ని యాప్‌లో కొనుగోళ్లను అందించవచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
-<translation id="1347975661240122359">బ్యాటరీ స్థాయి <ph name="BATTERY_LEVEL" />% చేరుకున్నప్పుడు అప్‌డేట్ ప్రారంభమవుతుంది.</translation>
+<translation id="1347975661240122359">బ్యాటరీ <ph name="BATTERY_LEVEL" />% ఉన్నప్పుడు అప్‌డేట్ ప్రారంభమవుతుంది.</translation>
<translation id="1351692861129622852"><ph name="FILE_COUNT" /> ఫైల్‌లను దిగుమతి చేస్తోంది...</translation>
<translation id="1353686479385938207"><ph name="PROVIDER_NAME" />: <ph name="NETWORK_NAME" /></translation>
<translation id="1353980523955420967">PPDని కనుగొనడం సాధ్యం కాదు. మీ Chromebook ఇంటర్నెట్‌కు కనెక్ట్ అయ్యి ఉందని నిర్ధారించుకుని, ఆపై మళ్లీ ప్రయత్నించండి.</translation>
@@ -254,7 +254,7 @@
<translation id="1367951781824006909">ఒక ఫైల్‌ని ఎంచుకోండి</translation>
<translation id="1371301976177520732">మీ బుక్‌మార్క్‌లు, పాస్‌వర్డ్‌‌లు, చరిత్ర మరియు మరిన్నింటిని మీ అన్ని పరికరాల్లోనూ పొందగలరు</translation>
<translation id="1372841398847029212">మీ ఖాతాకు సింక్ చేయండి</translation>
-<translation id="1374844444528092021">"<ph name="NETWORK_NAME" />" నెట్‌వర్క్‌కు అవసరమైన సర్టిఫికెట్ ఇన్‌స్టాల్ చేయబడలేదు లేదా చెల్లదు. దయచేసి కొత్త సర్టిఫికెట్‌ను పొందండి, ఆపై కనెక్ట్ చేయడం మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="1374844444528092021">"<ph name="NETWORK_NAME" />" నెట్‌వర్క్‌కు అవసరమైన ప్రమాణపత్రం ఇన్‌స్టాల్ చేయబడలేదు లేదా చెల్లదు. దయచేసి క్రొత్త ప్రమాణపత్రాన్ని పొందండి మరియు మళ్లీ కనెక్ట్ చేయడాన్ని ప్రయత్నించండి.</translation>
<translation id="1375321115329958930">సేవ్ చెయ్యబడిన పాస్‌వర్డ్‌లు</translation>
<translation id="137651782282853227">సేవ్ చేసిన చిరునామాలు ఇక్కడ కనిపిస్తాయి</translation>
<translation id="1377600615067678409">ప్రస్తుతానికి దాటవేయి</translation>
@@ -282,8 +282,8 @@
<translation id="1409390508152595145">పర్యవేక్షించబడే వినియోగదారుని సృష్టించు</translation>
<translation id="1410197035576869800">యాప్ చిహ్నం</translation>
<translation id="1410616244180625362">మీ కెమెరాను యాక్సెస్ చేయడానికి <ph name="HOST" />కు అనుమతిని కొనసాగించండి</translation>
-<translation id="1411668397053040814">VRలో Chromeని ఉపయోగించడానికి Daydream కీబోర్డ్‌ని ఇన్‌స్టాల్ చేయండి లేదా అప్‌డేట్ చేయండి</translation>
-<translation id="1414648216875402825">మీరు <ph name="PRODUCT_NAME" /> యొక్క అస్థిర సంస్కరణకు నవీకరిస్తున్నారు, ఇది పురోగతిలో ఉన్న లక్షణాలను కలిగి ఉంటుంది. క్రాష్‌లు మరియు ఊహించని బగ్‌లు సంభవించవచ్చు. దయచేసి జాగ్రత్తగా కొనసాగండి.</translation>
+<translation id="1411668397053040814">VRలో Chromeను ఉపయోగించడానికి Daydream కీబోర్డ్‌ను ఇన్‌స్టాల్ చేయండి లేదా అప్‌డేట్ చేయండి</translation>
+<translation id="1414648216875402825">మీరు <ph name="PRODUCT_NAME" /> యొక్క అస్థిర వెర్షన్‌కు అప్‌డేట్ చేస్తున్నారు, ఇందులో పురోగతిలో ఉన్న ఫీచర్‌లు ఉంటాయి. క్రాష్‌లు మరియు ఊహించని బగ్‌లు ఏర్పడవచ్చు. దయచేసి జాగ్రత్తగా కొనసాగండి.</translation>
<translation id="1415708812149920388">క్లిప్‌బోర్డ్‌ను చదివే యాక్సెస్ నిరాకరించబడింది</translation>
<translation id="1415990189994829608"><ph name="EXTENSION_NAME" /> (ఎక్స్‌టెన్షన్‌ ID "<ph name="EXTENSION_ID" />") ఈ రకమైన సెషన్‌లో అనుమతించబడదు.</translation>
<translation id="1416836038590872660">EAP-MD5</translation>
@@ -297,13 +297,13 @@
<translation id="1430915738399379752">ముద్రించు</translation>
<translation id="1432581352905426595">శోధన ఇంజిన్‌లను నిర్వహించండి</translation>
<translation id="1433811987160647649">ప్రాప్యత చేసే ముందు అడగాలి</translation>
-<translation id="1434696352799406980">దీని వలన మీ ప్రారంభ పేజీ, కొత్త ట్యాబ్ పేజీ, శోధన ఇంజిన్ మరియు పిన్ చేసిన ట్యాబ్‌లు రీసెట్ చేయబడతాయి. ఇది ఎక్స్‌టెన్షన్‌లన్నింటినీ నిలిపివేసి, కుక్కీల వంటి తాత్కాలిక డేటాను తీసివేస్తుంది. మీ బుక్‌మార్క్‌లు, చరిత్ర మరియు సేవ్ చేసిన పాస్‌వర్డ్‌లు తీసివేయబడవు.</translation>
+<translation id="1434696352799406980">దీని వలన మీ ప్రారంభ పేజీ, కొత్త ట్యాబ్ పేజీ, శోధన ఇంజిన్, పిన్ చేసిన ట్యాబ్‌లు రీసెట్ చేయబడతాయి. ఇది అన్ని ఎక్స్‌టెన్ష‌న్‌లను కూడా నిలిపివేస్తుంది. కుక్కీల వంటి తాత్కాలిక డేటాను తీసివేస్తుంది. మీ బుక్‌మార్క్‌లు, చరిత్ర, సేవ్ చేసిన పాస్‌వర్డ్‌లు తీసివేయబడవు.</translation>
<translation id="1434886155212424586">హోమ్‌పేజీ అనేది కొత్త ట్యాబ్ పేజీ</translation>
<translation id="1436671784520050284">సెటప్‌ని కొనసాగించు</translation>
<translation id="1436784010935106834">తీసివేయబడింది</translation>
<translation id="1442392616396121389">రూటింగ్ ఆదిప్రత్యయం</translation>
<translation id="144283815522798837"><ph name="NUMBER_OF_ITEMS_SELECTED" /> ఎంచుకోబడింది/ఎంచుకోబడ్డాయి</translation>
-<translation id="1444628761356461360">ఈ సెట్టింగ్‌ను పరికరం యజమాని అయిన <ph name="OWNER_EMAIL" /> నిర్వహించారు.</translation>
+<translation id="1444628761356461360">ఈ సెట్టింగ్‌ను పరికరం యజమాని అయిన <ph name="OWNER_EMAIL" /> నిర్వహిస్తున్నారు.</translation>
<translation id="144518587530125858">థీమ్ కోసం '<ph name="IMAGE_PATH" />'ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
<translation id="1451375123200651445">వెబ్ పేజీ, ఒకే ఫైల్</translation>
<translation id="1451917004835509682">పర్యవేక్షించబడే వ్యక్తిని జోడించు</translation>
@@ -328,7 +328,7 @@
<translation id="1478607704480248626">ఇన్‌స్టాలేషన్ ప్రారంభించబడలేదు</translation>
<translation id="1483493594462132177">పంపు</translation>
<translation id="1485015260175968628">ఇప్పుడు ఇది వీటిని చేయగలదు:</translation>
-<translation id="1485141095922496924">సంస్కరణ <ph name="PRODUCT_VERSION" /> (<ph name="PRODUCT_CHANNEL" />) <ph name="PRODUCT_MODIFIER" /> <ph name="PRODUCT_VERSION_BITS" /></translation>
+<translation id="1485141095922496924">వెర్షన్ <ph name="PRODUCT_VERSION" /> (<ph name="PRODUCT_CHANNEL" />) <ph name="PRODUCT_MODIFIER" /> <ph name="PRODUCT_VERSION_BITS" /></translation>
<translation id="1486096554574027028">పాస్‌వర్డ్‌లను వెతుకు</translation>
<translation id="1487335504823219454">ఆన్ - అనుకూల సెట్టింగ్‌లు</translation>
<translation id="1489664337021920575">మరొక ఎంపికను ఎంచుకోండి</translation>
@@ -377,7 +377,7 @@
<translation id="1553538517812678578">అపరిమిత</translation>
<translation id="1554390798506296774"><ph name="HOST" />లో ఎల్లప్పుడూ శాండ్‌బాక్స్ చేయని ప్లగిన్‌లను అనుమతించు</translation>
<translation id="1556189134700913550">అన్నింటికీ వర్తింపజేయి</translation>
-<translation id="1556537182262721003">ప్రొఫైల్‌లోకి ఎక్సటెన్షన్ డైరెక్టరీని తరలించలేకపోయింది.</translation>
+<translation id="1556537182262721003">ఎక్స్‌టెన్షన్ డైరెక్టరీని ప్రొఫైల్ లోపలికి తరలించలేకపోయింది.</translation>
<translation id="155865706765934889">టచ్‌ప్యాడ్</translation>
<translation id="1564414980088536597">ఈ చిత్రాన్ని ఉపయోగించడం సాధ్యం కాదు. వేరొక చిత్రాన్ని ఎంచుకోండి.</translation>
<translation id="1566049601598938765">వెబ్‌సైట్</translation>
@@ -407,7 +407,7 @@
<translation id="159359590073980872">చిత్రం కాష్</translation>
<translation id="1593926297800505364">చెల్లింపు పద్దతిని సేవ్ చేయండి</translation>
<translation id="1595492813686795610">Linux అప్‌గ్రేడ్ అవుతోంది</translation>
-<translation id="1598233202702788831">నవీకరణలను మీ నిర్వాహకులు నిలిపివేసారు.</translation>
+<translation id="1598233202702788831">అప్‌డేట్‌లను మీ నిర్వాహకులు నిలిపివేశారు.</translation>
<translation id="1600857548979126453">పేజీ డీబగ్గర్ బ్యాకెండ్‌ను యాక్సెస్ చేయండి</translation>
<translation id="1601560923496285236">వర్తించు</translation>
<translation id="1603914832182249871">(అజ్ఞాతంగా)</translation>
@@ -428,27 +428,27 @@
<translation id="1632803087685957583">మీ కీబోర్డ్ పునరావృత రేటు, పద సూచన మొదలైనవి సర్దుబాటు చేయడానికి మిమ్మల్ని అనుమతిస్తుంది</translation>
<translation id="1635033183663317347">మీ పర్యవేక్షకుడు ఇన్‌స్టాల్ చేసారు.</translation>
<translation id="1637224376458524414">ఈ బుక్‌మార్క్‌ను మీ iPhoneలో పొందండి</translation>
-<translation id="1637765355341780467">మీ ప్రొఫైల్‌ను తెరుస్తున్నప్పుడు ఏదో తప్పు జరిగింది. కొన్ని లక్షణాలు అందుబాటులో ఉండకపోవచ్చు.</translation>
+<translation id="1637765355341780467">మీ ప్రొఫైల్‌ను తెరుస్తున్నప్పుడు ఏదో తప్పు జరిగింది. కొన్ని ఫీచర్‌లు అందుబాటులో ఉండకపోవచ్చు.</translation>
<translation id="1639239467298939599">లోడ్ అవుతోంది</translation>
<translation id="163993578339087550">మీరు అర్హత ఉన్న Chrome OS పరికరాన్ని ఉపయోగిస్తున్నారని <ph name="SERVICE_NAME" /> తనిఖీ చేయాలనుకుంటోంది.</translation>
<translation id="1640283014264083726">RSA ఎన్‌క్రిప్షన్‌తో PKCS #1 MD4</translation>
<translation id="1641113438599504367">సురక్షిత బ్రౌజింగ్</translation>
-<translation id="1642494467033190216">ఇతర డీబగ్గింగ్ లక్షణాలను ప్రారంభించడానికి ముందు rootfs రక్షణను తీసివేసి, పునఃప్రారంభించాలి.</translation>
+<translation id="1642494467033190216">ఇతర డీబగ్గింగ్ ఫీచ‌ర్‌లను ప్రారంభించడానికి ముందు rootfs రక్షణను తీసివేసి, పునఃప్రారంభించాలి.</translation>
<translation id="1643050526526937107">కేవలం సమకాలీకరించు</translation>
<translation id="1643072738649235303">SHA-1తో X9.62 ECDSA సంతకం</translation>
<translation id="1644574205037202324">చరిత్ర</translation>
<translation id="1645516838734033527">మీ <ph name="DEVICE_TYPE" />ను సురక్షితంగా ఉంచడానికి, Smart Lockకు మీ ఫోన్‌లో ఒక స్క్రీన్ లాక్ అవసరం.</translation>
-<translation id="1646982517418478057">దయచేసి ఈ స‌ర్టిఫికెట్‌ను ఎన్‌క్రిప్ట్ చేయ‌డానికి పాస్‌వర్డ్‌ను నమోదు చేయండి</translation>
+<translation id="1646982517418478057">దయచేసి ఈ ప్రమాణపత్రాన్ని గుప్తీకరించడానికి పాస్‌వర్డ్‌ను నమోదు చేయండి</translation>
<translation id="164814987133974965">పర్యవేక్షించబడే వినియోగదారు మీ మార్గదర్శకత్వంలో వెబ్‌ను విశ్లేషించగలరు. పర్యవేక్షించబడే వినియోగదారు యొక్క నిర్వాహకునిగా, మీరు వీటిని చేయగలరు
నిర్దిష్ట వెబ్‌సైట్‌లను <ph name="BEGIN_BOLD" />అనుమతించడం లేదా నిషేధించడం<ph name="END_BOLD" />,
పర్యవేక్షించబడే వినియోగదారు సందర్శించిన వెబ్‌సైట్‌లను <ph name="BEGIN_BOLD" />సమీక్షించడం<ph name="END_BOLD" /> మరియు
ఇతర సెట్టింగ్‌లను <ph name="BEGIN_BOLD" />నిర్వహించడం<ph name="END_BOLD" />.</translation>
<translation id="1648528859488547844">స్థానాన్ని గుర్తించడానికి Wi‑Fi లేదా మొబైల్ నెట్‌వర్క్‌లను ఉపయోగించండి</translation>
-<translation id="1648943974594387137">సైన్-ఇన్ వివరాలు పాతవి</translation>
+<translation id="1648943974594387137">సైన్-ఇన్ వివరాల గడువు ముగిసింది</translation>
<translation id="1650371550981945235">ఇన్‌పుట్ ఎంపికలను చూపు</translation>
<translation id="1651008383952180276">మీరు తప్పనిసరిగా ఒకే రహస్య పదబంధాన్ని రెండుసార్లు నమోదు చేయాలి</translation>
<translation id="1653526288038954982">{NUM_PRINTER,plural, =1{Google క్లౌడ్ ప్రింట్‌కు ఆ ప్రింటర్‌ను జోడించండి, అప్పుడు మీరు ఎక్కడి నుండైనా ముద్రించవచ్చు.}other{Google క్లౌడ్ ప్రింట్‌కు # ప్రింటర్‌లను జోడించండి, అప్పుడు మీరు ఎక్కడి నుండైనా ముద్రించవచ్చు.}}</translation>
-<translation id="1657406563541664238">Googleకు వినియోగ గ‌ణాంకాలు, క్రాష్ నివేదికలను ఆటోమేటిక్‌గా పంపడం ద్వారా <ph name="PRODUCT_NAME" />ను మరింత మెరుగుపరచడంలో సహాయపడండి</translation>
+<translation id="1657406563541664238">వినియోగ గణాంకాలు మరియు క్రాష్ నివేదికలను Googleకు ఆటోమేటిక్‌గా పంపడం ద్వారా <ph name="PRODUCT_NAME" />ను మరింత మెరుగుపరచడంలో సహాయపడండి</translation>
<translation id="1658424621194652532">ఈ పేజీ మీ మైక్రోఫోన్‌ను ప్రాప్యత చేస్తోంది.</translation>
<translation id="1660204651932907780">ధ్వనిని ప్లే చేయడానికి సైట్‌లను అనుమతించండి (సిఫార్సు చేయబడింది)</translation>
<translation id="1661156625580498328">AES ఎన్‌క్రిప్షన్‌ను అమలు చేయి (సిఫార్సు చేయబడినది).</translation>
@@ -518,15 +518,14 @@
<translation id="175772926354468439">థీమ్‌ను ప్రారంభించు</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome వెబ్ స్టోర్‌లో చూడండి</translation>
-<translation id="1761588866118490543">వాయిస్ నమూనా (మోడల్)</translation>
<translation id="176193854664720708">వేలిముద్ర సెన్సార్ పవర్ బటన్‌లో ఉంది. ఏదైనా వేలితో మెల్లిగా దానిని తాకండి.</translation>
<translation id="1763046204212875858">అప్లికేషన్ షార్ట్‌కట్‌లను సృష్టించు</translation>
<translation id="1763108912552529023">విశ్లేషణ కొనసాగించండి</translation>
<translation id="1763808908432309942">కొత్త ట్యాబ్‌లో తెరవబడుతుంది</translation>
<translation id="1764226536771329714">బీటా</translation>
<translation id="176587472219019965">&amp;క్రొత్త విండో</translation>
-<translation id="1768278914020124551">అయ్యో! లాగాన్ సర్వర్‌ను సంప్రదించడంలో సమస్య ఉంది. దయచేసి మీ నెట్‌వర్క్ కనెక్షన్‌ను మరియు డొమైన్ పేరును తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
-<translation id="1769104665586091481">లింక్‌ను క్రొత్త &amp;విండోలో తెరువు</translation>
+<translation id="1768278914020124551">అయ్యో! లాగ్ఆన్ సర్వర్‌ను సంప్రదించడంలో సమస్య ఉంది. దయచేసి మీ నెట్‌వర్క్ కనెక్షన్‌ను మరియు డొమైన్ పేరును తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="1769104665586091481">లింక్‌ను కొత్త &amp;విండోలో తెరువు</translation>
<translation id="1773212559869067373">ప్రామాణీకరణ ప్రమాణపత్రం స్థానికంగా తిరస్కరించబడింది</translation>
<translation id="177336675152937177">హోస్ట్ చేసిన యాప్‌ డేటా</translation>
<translation id="1774833706453699074">తెరిచి ఉన్న పేజీలను బుక్‌మార్క్ చేయి...</translation>
@@ -537,7 +536,7 @@
<translation id="1781502536226964113">కొత్త‌ ట్యాబ్ పేజీని తెరువు</translation>
<translation id="1781771911845953849">ఖాతాలు మరియు సమకాలీకరణ</translation>
<translation id="1782196717298160133">మీ ఫోన్‌ను కనుగొంటోంది</translation>
-<translation id="1784849162047402014">పరికరంలో ఖాళీ డిస్క్ స్థలం తక్కువగా ఉంది</translation>
+<translation id="1784849162047402014">పరికరంలో ఖాళీ నిల్వ స్థలం తక్కువగా ఉంది</translation>
<translation id="1786636458339910689">బృంద డిస్క్‌లు</translation>
<translation id="1792619191750875668">విస్తారిత డిస్‌ప్లే</translation>
<translation id="1794791083288629568">ఈ సమస్యను పరిష్కరించడంలో మాకు సహాయం చేయడానికి అభిప్రాయాన్ని పంపుతుంది.</translation>
@@ -600,20 +599,20 @@
<translation id="1864756863218646478">ఫైల్‌ను కనుగొనబడలేదు.</translation>
<translation id="1865678028973512614">ఫైల్‌లను తొలగించు</translation>
<translation id="1865769994591826607">ఒకే సైట్ కనెక్షన్‌లు మాత్రమే</translation>
-<translation id="186612162884103683">తనిఖీ చేయబడిన స్థానాల్లో "<ph name="EXTENSION" />" చిత్రాలను, వీడియోను మరియు సౌండ్ ఫైల్‌లను చదవగలదు మరియు వ్రాయగలదు.</translation>
+<translation id="186612162884103683">తనిఖీ చేయబడిన స్థానాల్లో "<ph name="EXTENSION" />" చిత్రాలను, వీడియోను మరియు సౌండ్ ఫైల్స్‌ను చదవగలదు మరియు రాయ‌గ‌ల‌దు.</translation>
<translation id="1867780286110144690">మీ వ్యవస్థాపనను పూర్తి చెయ్యడానికి <ph name="PRODUCT_NAME" /> సిద్ధంగా ఉంది</translation>
<translation id="1868193363684582383">"Ok Google"</translation>
<translation id="1871615898038944731">మీ <ph name="DEVICE_TYPE" /> తాజాగా ఉంది</translation>
<translation id="1875312262568496299">ప్రారంభించు</translation>
<translation id="1875387611427697908">దీనిని <ph name="CHROME_WEB_STORE" /> నుండి మాత్రమే జోడించవచ్చు</translation>
-<translation id="1877520246462554164">ప్రామాణీకరణ టోకెన్‌ను పొందడం విఫలమైంది. దయచేసి సైన్ అవుట్ చేసి, సైన్ ఇన్ చేసిన తర్వాత మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="1877520246462554164">ప్రమాణీకరణ టోకెన్‌ను పొందడం విఫలమైంది. దయచేసి సైన్ అవుట్ చేసి, సైన్ ఇన్ చేసిన తర్వాత మళ్లీ ప్రయత్నించండి.</translation>
<translation id="1879000426787380528">ఇలా సైన్ ఇన్ చేయండి</translation>
-<translation id="1880905663253319515">ప్రమాణపత్రం "<ph name="CERTIFICATE_NAME" />"ని తొలగించాలా?</translation>
+<translation id="1880905663253319515">ప్రమాణపత్రం "<ph name="CERTIFICATE_NAME" />"ను తొలగించాలా?</translation>
<translation id="1886996562706621347">ప్రోటోకాల్స్‌కు డిఫాల్ట్ హ్యాండ్లర్‌లుగా కావడం కోసం అడగటానికి సైట్‌లను అనుమతించండి (సిఫార్సు చేయబడింది)</translation>
<translation id="1887442540531652736">సైన్ ఇన్ ఎర్రర్</translation>
<translation id="1887597546629269384">మళ్లీ ఒక్కసారి "Hey Google" అని చెప్పండి</translation>
<translation id="1887850431809612466">హార్డ్‌వేర్ పునర్విమర్శ</translation>
-<translation id="1889984860246851556">ప్రాక్సీ సెట్టింగ్‌లని తెరవండి</translation>
+<translation id="1889984860246851556">ప్రాక్సీ సెట్టింగ్‌లను తెరవండి</translation>
<translation id="1890674179660343635">&lt;span&gt;ID: &lt;/span&gt;<ph name="EXTENSION_ID" /></translation>
<translation id="189210018541388520">పూర్తి స్క్రీన్‌ని తెరువు</translation>
<translation id="189358972401248634">ఇతర భాషలు</translation>
@@ -631,7 +630,7 @@
<translation id="1916502483199172559">డిఫాల్ట్ ఎరుపు రంగు అవతార్</translation>
<translation id="1918141783557917887">&amp;చిన్నగా</translation>
<translation id="1919345977826869612">ప్రకటనలు</translation>
-<translation id="1919814239594435008">శాండ్‌బాక్స్ చేయని ప్లగిన్ అనుమతించబడింది</translation>
+<translation id="1919814239594435008">శాండ్‌బాక్స్ చేయని ప్లగ్ఇన్‌ అనుమతించబడింది</translation>
<translation id="1921050530041573580">మీ ఫోన్‌ని సందేశాలతో జత చేయండి</translation>
<translation id="1921584744613111023"><ph name="DPI" /> dpi</translation>
<translation id="1924559387127953748"><ph name="IDS_SHORT_PRODUCT_NAME" />లో Google సామర్థ్యాలను పొందండి</translation>
@@ -667,10 +666,10 @@
<translation id="1974821797477522211">నెట్‌వర్క్‌కి కనెక్ట్ చేయండి</translation>
<translation id="197560921582345123">సవరించగలరు</translation>
<translation id="1975841812214822307">తీసివేయి...</translation>
-<translation id="1976150099241323601">భద్రతా పరికరానికి సైన్ ఇన్ చెయ్యండి</translation>
+<translation id="1976150099241323601">భద్రతా పరికరానికి సైన్ ఇన్ చేయండి</translation>
<translation id="1976323404609382849">బహుళ సైట్‌ల నుండి కుకీలు బ్లాక్ చేయబడ్డాయి.</translation>
<translation id="1977965994116744507">మీ <ph name="DEVICE_TYPE" />ను అన్‌లాక్ చేయడానికి మీ ఫోన్‌ను సమీపంలోకి తీసుకురండి.</translation>
-<translation id="1979280758666859181">మీరు <ph name="PRODUCT_NAME" /> యొక్క పాత సంస్కరణను కలిగి ఉన్న ఛానెల్‌కు మారుతున్నారు. ఛానెల్ సంస్కరణ మీ పరికరంలో ప్రస్తుతం ఇన్‌స్టాల్ చేయబడిన సంస్కరణకు సరిపోలినప్పుడు ఛానెల్ మార్పు వర్తిస్తుంది.</translation>
+<translation id="1979280758666859181">మీరు <ph name="PRODUCT_NAME" /> పాత వెర్షన్ ఉన్న ఛానెల్‌కు మారుతున్నారు. ఈ ఛానెల్ వెర్షన్, మీ పరికరంలో ప్రస్తుతం ఇన్‌స్టాల్ అయిన వెర్షన్‌కు సరిపోలినప్పుడు ఛానెల్ మార్పు వర్తిస్తుంది.</translation>
<translation id="1983959805486816857">మీరు క్రొత్త పర్యవేక్షించబడే వినియోగదారును సృష్టించిన తర్వాత, ఏ సమయంలో అయినా ఏ పరికరం నుండి అయినా <ph name="MANAGEMENT_URL" />లో సెట్టింగ్‌లను నిర్వహించవచ్చు.</translation>
<translation id="1987317783729300807">ఖాతాలు</translation>
<translation id="1989112275319619282">బ్రౌజ్ చేయి</translation>
@@ -693,17 +692,17 @@
<translation id="2019718679933488176">కొత్త ట్యాబ్‌లో ఆడియోను &amp;తెరవండి</translation>
<translation id="2020183425253392403">నెట్‌వర్క్ చిరునామా సెట్టింగ్‌లను చూపు</translation>
<translation id="2023167225947895179">PIN సులభంగా ఊహించగలిగేలా ఉండవచ్చు</translation>
-<translation id="202352106777823113">డౌన్‌లోడ్ పూర్తి కావడానికి చాలా సమయం పట్టింది, అందువల్ల దానిని నెట్‌వర్క్ నిలిపివేసింది.</translation>
+<translation id="202352106777823113">డౌన్‌లోడ్‌కు చాలా సమయం పడుతుంది మరియు నెట్‌వర్క్ ద్వారా నిలిపివేయబడింది.</translation>
<translation id="2025632980034333559"><ph name="APP_NAME" /> క్రాష్ అయ్యింది. ఎక్స్‌టెన్షన్‌ను మళ్లీ లోడ్ చేయడానికి ఈ బెలూన్‌ను క్లిక్ చేయండి.</translation>
<translation id="2028997212275086731">RAR ఆర్కైవ్</translation>
<translation id="2034346955588403444">మరో WiFi నెట్‌వర్క్‌ని జోడించండి</translation>
<translation id="203574396658008164">లాక్ స్క్రీన్ నుండి గ‌మ‌నిక‌ సేకరణను ప్రారంభించండి</translation>
-<translation id="2040460856718599782">అయ్యో! మిమ్మల్ని ప్రామాణీకరించడానికి ప్రయత్నిస్తున్నప్పుడు ఏదో తప్పు జరిగింది. దయచేసి మీ సైన్-ఇన్ ప్రమాణాలను ఒకటికి రెండుసార్లు తనిఖీ చేసుకుని మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="2040460856718599782">అయ్యో! మిమ్మల్ని ప్రామాణీకరించడానికి ప్రయత్నిస్తున్నప్పుడు ఏదో తప్పు జరిగింది. దయచేసి మీ సైన్-ఇన్ ప్రమాణాలను ఒకటికి రెండుసార్లు తనిఖీ చేసుకుని మళ్లీ ప్రయత్నించండి.</translation>
<translation id="2043818754674261542">ఈ <ph name="DEVICE_TYPE" />ని అన్‌లాక్ చేయడానికి ఫోన్‌ను ఉంచాల్సిన దూరం</translation>
<translation id="204497730941176055">Microsoft సర్టిఫికెట్ టెంప్లేట్ పేరు</translation>
<translation id="2045117674524495717">కీబోర్డ్ షార్ట్‌కట్ సహాయం</translation>
<translation id="2045969484888636535">కుకీలను నిరోధించడాన్ని కొనసాగించండి</translation>
-<translation id="204622017488417136">మీ పరికరం మునుపు ఇన్‌స్టాల్ చేసిన Chrome సంస్కరణకు తిరిగి మార్చబడింది. అన్ని వినియోగదారు ఖాతాలు మరియు స్థానిక డేటా తీసివేయబడుతుంది. దీన్ని రద్దు చేయడం సాధ్యపడదు.</translation>
+<translation id="204622017488417136">మీ పరికరం మునుపు ఇన్‌స్టాల్ చేసిన Chrome వెర్షన్‌కు తిరిగి మార్చబడింది. అన్ని వినియోగదారు ఖాతాలు మరియు స్థానిక డేటా తీసివేయబడతాయి. దీనిని రద్దు చేయడం సాధ్యపడదు.</translation>
<translation id="2048182445208425546">మీ నెట్‌వర్క్ ట్రాఫిక్‌ను యాక్సెస్ చేయండి</translation>
<translation id="2048653237708779538">చర్య అందుబాటులో లేదు</translation>
<translation id="204914487372604757">షార్ట్‌కట్‌ను సృష్టించు</translation>
@@ -717,9 +716,9 @@
<translation id="2071393345806050157">స్థానిక లాగ్ ఫైల్ లేదు.</translation>
<translation id="2075474481720804517">బ్యాటరీ <ph name="BATTERY_PERCENTAGE" />% ఉంది</translation>
<translation id="2075959085554270910">క్లిక్ చేయ‌డానికి నొక్కండి. నొక్కి పట్టుకుని, లాగండిని ప్రారంభించడానికి/నిలిపివేయడానికి మిమ్మల్ని అనుమతిస్తుంది</translation>
-<translation id="2076269580855484719">ఈ ప్లగ్ఇన్‌ని దాచిపెట్టు</translation>
+<translation id="2076269580855484719">ఈ ప్లగ్ఇన్‌ను దాచు</translation>
<translation id="2076672359661571384">మధ్యస్థం (సిఫార్సు చేయబడింది)</translation>
-<translation id="2077129598763517140">అందుబాటులో ఉన్నప్పుడు హార్డ్‌వేర్ వేగవృద్ధిని ఉపయోగించు</translation>
+<translation id="2077129598763517140">హార్డ్‌వేర్ వేగవృద్ధి అందుబాటులో ఉన్నప్పుడు ఉపయోగించు</translation>
<translation id="2078019350989722914">నిష్క్రమించే ముందు హెచ్చరించు (<ph name="KEY_EQUIVALENT" />)</translation>
<translation id="2079053412993822885">మీరు మీ స్వంత ప్రమాణపత్రాలలోని ఒకదాన్ని తొలగించినట్లయితే, మీరు దీన్ని గుర్తించడానికి మీరే ఇకపై ఉపయోగించలేరు.</translation>
<translation id="2079545284768500474">చర్య రద్దు</translation>
@@ -732,12 +731,12 @@
<translation id="2090165459409185032">మీ ఖాతా సమాచారాన్ని పునరుద్ధరించడానికి, దీనికి వెళ్లండి: google.com/accounts/recovery</translation>
<translation id="2090876986345970080">సిస్టమ్ భద్రతా సెట్టింగ్</translation>
<translation id="2091887806945687916">ధ్వని</translation>
-<translation id="2097372108957554726">మీరు కొత్త పరికరాలను నమోదు చేయడానికి Chromeకి సైన్ ఇన్ చేయాలి</translation>
+<translation id="2097372108957554726">మీరు కొత్త పరికరాలను నమోదు చేయడానికి Chromeకు సైన్ ఇన్ చేయాలి</translation>
<translation id="2098305189700762159">దొరకలేదు</translation>
-<translation id="2099172618127234427">మీరు sshd daemonను సెటప్ చేసే, USB డ్రైవ్‌ల నుండి బూటింగ్‌ను ప్రారంభించే Chrome OS డీబగ్గింగ్ ఫీచ‌ర్‌ల‌ను ప్రారంభిస్తున్నారు.</translation>
-<translation id="2099686503067610784">సర్వర్ సర్టిఫికెట్ "<ph name="CERTIFICATE_NAME" />"ను తొలగించాలా?</translation>
+<translation id="2099172618127234427">మీరు sshd daemonను సెటప్ చేసే మరియు USB డ్రైవ్‌ల నుండి బూటింగ్‌ను ప్రారంభించే Chrome OS డీబగ్గింగ్ ఫీచ‌ర్‌లను ప్రారంభిస్తున్నారు.</translation>
+<translation id="2099686503067610784">సర్వర్ ప్రమాణపత్రం "<ph name="CERTIFICATE_NAME" />"ను తొలగించాలా?</translation>
<translation id="2100273922101894616">స్వీయ సైన్-ఇన్</translation>
-<translation id="2101225219012730419">సంస్కరణ:</translation>
+<translation id="2101225219012730419">వెర్షన్:</translation>
<translation id="21133533946938348">టాబ్‌ను పిన్ చెయ్యి</translation>
<translation id="2113479184312716848">ఫైల్‌ను &amp;తెరువు...</translation>
<translation id="2113921862428609753">అధికార సమాచార ప్రాప్తి</translation>
@@ -749,10 +748,10 @@
<translation id="2120478168904746065">{NUM_TABS,plural, =1{ట్యాబ్‌ని అన్‌మ్యూట్ చేయి}other{ట్యాబ్‌లను అన్‌మ్యూట్ చేయి}}</translation>
<translation id="2121825465123208577">పరిమాణం మార్చు</translation>
<translation id="2124930039827422115">{1,plural, =1{ఒక వినియోగదారుచే <ph name="AVERAGE_RATING" /> రేట్ చేయబడింది.}other{# వినియోగదారులచే <ph name="AVERAGE_RATING" /> రేట్ చేయబడింది.}}</translation>
-<translation id="2126167708562367080">సమకాలీకరణను మీ నిర్వాహకులు నిలిపివేసారు.</translation>
+<translation id="2126167708562367080">సింక్‌ను మీ నిర్వాహకులు నిలిపివేశారు.</translation>
<translation id="2127372758936585790">తక్కువ-పవర్ గల ఛార్జర్</translation>
<translation id="212862741129535676">తరచుదనం స్థితి అధీన శాతం</translation>
-<translation id="2129825002735785149">ప్లగిన్‌ను నవీకరించండి</translation>
+<translation id="2129825002735785149">ప్లగిన్‌ను అప్‌డేట్ చేయండి</translation>
<translation id="2131077480075264">"<ph name="APP_NAME" />"ను అనుమతించనందున దీన్ని ఇన్‌స్టాల్ చేయడం సాధ్యపడలేదు "<ph name="IMPORT_NAME" />"</translation>
<translation id="2135456203358955318">డాక్ చేయబడిన మాగ్నిఫైయర్</translation>
<translation id="2135787500304447609">&amp;మళ్ళీ ప్రారంభించు</translation>
@@ -781,18 +780,18 @@
<translation id="216169395504480358">Wi-Fiని జోడించండి...</translation>
<translation id="2162155940152307086">మీరు ఒకసారి సింక్ సెట్టింగ్‌ల పేజీని వదిలివెళ్లినప్పటి నుండి సింక్ ప్రారంభమవుతుంది</translation>
<translation id="2163152940313951844">చెల్లని అక్షరం: <ph name="CHARACTER_NAME" /></translation>
-<translation id="2163470535490402084">దయచేసి మీ <ph name="DEVICE_TYPE" />కు సైన్ ఇన్ చేయడానికి ఇంటర్నెట్‌కు కనెక్ట్ అవ్వండి.</translation>
+<translation id="2163470535490402084">మీ <ph name="DEVICE_TYPE" />కు సైన్ ఇన్ చేయడానికి దయచేసి ఇంటర్నెట్‌కు కనెక్ట్ చేయండి.</translation>
<translation id="2166369534954157698">దేశ భాషలందు తెలుగు లెస్స</translation>
<translation id="2169062631698640254">ఏదేమైనా సైన్ ఇన్ చేయి</translation>
<translation id="2173801458090845390">ఈ పరికరానికి అభ్యర్థన IDని జోడించండి</translation>
<translation id="2175042898143291048">ఎల్లప్పుడూ దీన్ని చేయి</translation>
-<translation id="2175607476662778685">శీఘ్ర ప్రాయోగిక పట్టీ</translation>
+<translation id="2175607476662778685">త్వరిత ప్రారంభ బార్</translation>
<translation id="2177950615300672361">అజ్ఞాత ట్యాబ్: <ph name="TAB_NAME" /></translation>
<translation id="2178098616815594724"><ph name="PEPPER_PLUGIN_DOMAIN" />లోని <ph name="PEPPER_PLUGIN_NAME" /> మీ కంప్యూటర్‌ని యాక్సెస్ చేయాలనుకుంటోంది</translation>
<translation id="2178614541317717477">CA రాజీ</translation>
<translation id="218070003709087997">ఎన్ని కాపీలను ముద్రించాలో (1 నుండి 999) సంఖ్యతో సూచించండి.</translation>
<translation id="2184515124301515068">సైట్‌లు ధ్వనిని ఎప్పుడు ప్లే చేయాలనేది Chrome ఎంచుకునేలా సెట్ చేయండి (సిఫార్సు చేయబడింది)</translation>
-<translation id="2187895286714876935">సర్వర్ సర్టిఫికెట్ దిగుమతి ఎర్రర్</translation>
+<translation id="2187895286714876935">సర్వర్ ప్రమాణపత్రం దిగుమతి లోపం</translation>
<translation id="2187906491731510095">పొడిగింపులు నవీకరించబడ్డాయి</translation>
<translation id="2188881192257509750"><ph name="APPLICATION" />ని తెరువు</translation>
<translation id="2190069059097339078">WiFi క్రెడెన్షియల్స్ గెట్టర్</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. ఈ పరికరం ప్రస్తుతం సమస్య విశ్లేషణ, అలాగే పరికర, యాప్ వినియోగ డేటాను ఆటోమేటిక్‌గా Googleకి పంపుతుంది. ఇది సిస్టమ్, యాప్ స్థిరత్వానికి, అలాగే ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. ఈ సెట్టింగ్‌ని యజమాని అమలు చేసారు. మీ అదనపు వెబ్ &amp; యాప్ కార్యకలాపం సెట్టింగ్‌ను ఆన్ చేసినట్లయితే, ఈ డేటా మీ Google ఖాతాలో సేవ్ చేయబడవచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">జిప్ ఆర్కైవ్</translation>
<translation id="220858061631308971">దయచేసి ఈ PIN కోడ్‌ను "<ph name="DEVICE_NAME" />"లో నమోదు చేయండి:</translation>
+<translation id="2213140827792212876">షేర్ చేయడాన్ని తీసివేయండి</translation>
+<translation id="2214018885812055163">షేర్ చేసిన ఫోల్డర్‌లు</translation>
<translation id="2214884991347062907">పాస్‌వర్డ్ తప్పు, మళ్లీ ప్రయత్నించండి</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 పంక్తి చూపబడలేదు&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> పంక్తులు చూపబడలేదు&gt;}}</translation>
<translation id="2217501013957346740">పేరును సృష్టించండి -</translation>
@@ -835,7 +836,7 @@
<translation id="2230051135190148440">CHAP</translation>
<translation id="2230062665678605299">"<ph name="FOLDER_NAME" />" ఫోల్డర్‌ను సృష్టించడం సాధ్యపడలేదు. <ph name="ERROR_MESSAGE" /></translation>
<translation id="223106756035922488">నేటి డూడుల్‌ను వీక్షించడం కోసం క్లిక్ చేయండి</translation>
-<translation id="2231238007119540260">మీరు సర్వర్ సర్టిఫికెట్‌ని తొలగిస్తే, సర్వర్ కోసం మీరు సాధారణ భద్రతా తనిఖీలను పునరుద్ధరించండి మరియు చెల్లుబాటు అయ్యే ప్రమాణపత్రాన్ని ఉపయోగించడానికి ఇది అవసరం.</translation>
+<translation id="2231238007119540260">మీరు సర్వర్ ప్రమాణపత్రాన్ని తొలగిస్తే, సర్వర్ కోసం మీరు సాధారణ భద్రతా తనిఖీలను పునరుద్ధరించండి మరియు చెల్లుబాటు అయ్యే ప్రమాణపత్రాన్ని ఉపయోగించడానికి ఇది అవసరం.</translation>
<translation id="2232379019872353004">కొంత సిస్టమ్ సమాచారం మరియు పేజీ కంటెంట్‌ను Googleకి పంపుతుంది</translation>
<translation id="2232876851878324699">ఫైల్ దిగుమతి చెయ్యని ఒక ప్రమాణపత్రాన్ని కలిగి ఉంది:</translation>
<translation id="2233502537820838181">&amp;మరింత సమాచారం</translation>
@@ -854,7 +855,7 @@
<translation id="2256115617011615191">ఇప్పుడే పునఃప్రారంభించు</translation>
<translation id="225614027745146050">స్వాగతం</translation>
<translation id="225692081236532131">క్రియాశీలత స్థితి</translation>
-<translation id="2261323523305321874">మీ నిర్వాహకులు కొన్ని పాత ప్రొఫైల్‌లను నిలిపివేసేలా వ్యవస్థాగత మార్పు చేసారు.</translation>
+<translation id="2261323523305321874">మీ నిర్వాహకులు కొన్ని పాత ప్రొఫైల్‌లను నిలిపివేసేలా వ్యవస్థాగత మార్పు చేశారు.</translation>
<translation id="2262332168014443534">ఇప్పుడు లైట్ మోడ్‌లో HTTPSతో పాటు అన్ని పేజీలలో మరింత వేగంగా బ్రౌజ్ చేయవచ్చు.</translation>
<translation id="2262477216570151239">పునరావృతానికి ముందు జాప్యం</translation>
<translation id="2263189956353037928">సైన్ అవుట్ చేసి, తిరిగి సైన్ ఇన్ చేయి</translation>
@@ -873,7 +874,7 @@
<translation id="2282146716419988068">GPU ప్రాసెస్</translation>
<translation id="2282155092769082568">ఆటోకాన్ఫిగరేషన్ URL:</translation>
<translation id="228758327756499171"><ph name="NUMBER_OF_MORE_APPS" /> యాప్‌లు</translation>
-<translation id="2288181517385084064">వీడియో రికార్డర్‌కి మార్చు</translation>
+<translation id="2288181517385084064">వీడియో రికార్డర్‌కు మార్చు</translation>
<translation id="2288735659267887385">ప్రాప్యత సెట్టింగ్‌లు</translation>
<translation id="2291538123825441971"><ph name="NUMBER_OF_FILES" /> ఫైల్‌లను తెరుస్తోంది.</translation>
<translation id="2292848386125228270"><ph name="PRODUCT_NAME" />ని ఒక సాధారణ వినియోగదారుగా దయచేసి ప్రారంభించండి. డెవలపర్‌గా వాడటానికి మీరు రూట్ లాగా అమలు చేయాలనుకుంటే, --no-sandbox ఫ్లాగ్‌తో మళ్లీ అమలు చేయండి.</translation>
@@ -891,13 +892,13 @@
<translation id="2316129865977710310">వద్దు, ధన్యవాదాలు</translation>
<translation id="2317842250900878657"><ph name="PROGRESS_PERCENT" />% పూర్తయింది</translation>
<translation id="2318143611928805047">కాగితపు పరిమాణం</translation>
-<translation id="2318817390901984578">Android యాప్‌లను ఉపయోగించడానికి, మీ <ph name="DEVICE_TYPE" />ని ఛార్జ్ చేసి, అప్‌డేట్ చేయండి.</translation>
+<translation id="2318817390901984578">Android యాప్‌ల‌ను ఉపయోగించాలంటే, మీ <ph name="DEVICE_TYPE" />ని ఛార్జ్ చేసి, అప్‌డేట్ చేయండి.</translation>
<translation id="2318923050469484167">ప్రస్తుత అజ్ఞాత సెషన్ (<ph name="EMBEDDING" />)</translation>
<translation id="2322193970951063277">హెడర్‌లు మరియు ఫుటర్‌లు</translation>
<translation id="2325650632570794183">ఈ ఫైల్ రకానికి మద్దతు లేదు. ఈ రకమైన ఫైల్‌ను తెరవగల యాప్‌ను కనుగొనడానికి దయచేసి Chrome వెబ్ స్టోర్‌ను సందర్శించండి.</translation>
<translation id="2326931316514688470">యాప్‌ను &amp;మళ్లీ లోడ్ చేయి</translation>
<translation id="2327492829706409234">యాప్‌ను ప్రారంభించు</translation>
-<translation id="2329597144923131178">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌లను మీ అన్ని పరికరాల్లో పొందడానికి సైన్ ఇన్ చేయండి.</translation>
+<translation id="2329597144923131178">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌లను మీ అన్ని పరికరాలలో పొందడానికి సైన్ ఇన్ చేయండి.</translation>
<translation id="2332131598580221120">స్టోర్‌లో వీక్షించండి</translation>
<translation id="2332742915001411729">డిఫాల్ట్‌కు రీసెట్ చేయి</translation>
<translation id="2335122562899522968">ఈ పేజీ కుక్కీలను సెట్ చేస్తుంది.</translation>
@@ -918,7 +919,7 @@
<translation id="2352947182261340447">స్థానిక నిల్వలో తగినంత స్థలం అందుబాటులో లేదు.</translation>
<translation id="2353297238722298836">కెమెరా మరియు మైక్రోఫోన్ అనుమతించబడ్డాయి</translation>
<translation id="2356070529366658676">అడుగు</translation>
-<translation id="2357949918965361754">మీరు మీ టీవీ లేదా ఇతర పరికరాల్లో Chrome నుండి కంటెంట్‌ను ప్రదర్శించడానికి ఈ ఫీచర్‌ని ఉపయోగించవచ్చు.</translation>
+<translation id="2357949918965361754">మీరు మీ టీవీ లేదా ఇతర పరికరాల్లో Chrome నుండి కంటెంట్‌ను ప్రదర్శించడానికి ఈ ఫీచర్‌ను ఉపయోగించవచ్చు.</translation>
<translation id="2359345697448000899">'సాధనాలు' మెనూలోని ఎక్స్‌టెన్షన్‌లను క్లిక్ చేయడం ద్వారా మీ ఎక్స్‌టెన్షన్‌లను నిర్వహించండి.</translation>
<translation id="2359808026110333948">కొనసాగించు</translation>
<translation id="236117173274098341">ఆప్టిమైజ్ చేయండి</translation>
@@ -935,7 +936,7 @@
<translation id="2378075407703503998"><ph name="SELCTED_FILE_COUNT" /> ఫైల్‌లు ఎంచుకోబడ్డాయి</translation>
<translation id="237828693408258535">ఈ పేజీని అనువదించాలా?</translation>
<translation id="2378346380592252785"><ph name="SHARE_PATH" /> కోసం యూజర్ పేరు, పాస్‌‌వర్డ్ అప్‌డేట్ చేయండి.</translation>
-<translation id="2378982052244864789">పొడిగింపు డైరెక్టరీని ఎంచుకోండి.</translation>
+<translation id="2378982052244864789">ఎక్స్‌టెన్ష‌న్‌ డైరెక్టరీని ఎంచుకోండి.</translation>
<translation id="2379232090534544565">ఆడియో మరియు వీడియో ఇన్‌పుట్‌ని ఒక సైట్ యాక్సెస్ చేస్తోంది</translation>
<translation id="2379281330731083556">సిస్టమ్ డైలాగ్‌ ఉపయోగించి ముద్రించు ...<ph name="SHORTCUT_KEY" /></translation>
<translation id="2381756643783702095">పంపడానికి ముందు అడుగుతుంది (సిఫార్సు చేయబడింది)</translation>
@@ -949,7 +950,7 @@
<translation id="2395616325548404795">మీ <ph name="DEVICE_TYPE" /> ఎంటర్‌ప్రైజ్ నిర్వహణ కోసం విజయవంతంగా నమోదు చేయబడింది, కానీ దాని లక్షణ మరియు స్థాన సమాచారాన్ని పంపడంలో విఫలమైంది. దయచేసి ఈ పరికరం కోసం ఈ సమాచారాన్ని మీ నిర్వాహక కన్సోల్ నుండి మాన్యువల్‌గా నమోదు చేయండి.</translation>
<translation id="240770291734945588"><ph name="SPACE_AVAILABLE" /> అందుబాటులో ఉంది</translation>
<translation id="2408955596600435184">మీ PINని నమోదు చేయండి</translation>
-<translation id="241082044617551207">తెలియని ప్లగిన్</translation>
+<translation id="241082044617551207">తెలియని ప్లగ్ఇన్‌</translation>
<translation id="2413749388954403953">బుక్‌మార్క్‌ల వినియోగదారు ఇంటర్‌ఫేస్‌ను మార్చడం</translation>
<translation id="241727068219398187"><ph name="TIME" /> నాటికి మీ Google పాస్‌వర్డ్‌తో డేటా ఎన్‌క్రిప్ట్ చేయబడింది.
Google Payకి చెందిన చెల్లింపు పద్ధతులు మరియు చిరునామాలు ఇందులో ఉండవు.</translation>
@@ -961,7 +962,7 @@
<translation id="2428510569851653187">ట్యాబ్ క్రాష్ అయిన సమయంలో మీరు ఏం చేస్తున్నారో వివరించండి</translation>
<translation id="2431027948063157455">Google అసిస్టెంట్‌ను లోడ్ చేయడం సాధ్యపడలేదు, దయచేసి మీ నెట్‌వర్క్ కనెక్షన్‌ను తనిఖీ చేసుకుని మళ్లీ ప్రయత్నించండి.</translation>
<translation id="2432753757290432042">Linux (బీటా) అప్‌డేట్ అవసరం</translation>
-<translation id="2433452467737464329">పేజీని ఆటోమేటిక్ రిఫ్రెష్ చేయడానికి URLలో ప్రశ్న పారామీటర్‌ను జోడించండి: chrome://network/?refresh=&lt;sec&gt;</translation>
+<translation id="2433452467737464329">పేజీని స్వీయ రీఫ్రెష్ చేయడానికి URLలో ప్రశ్న పరామితిని జోడించండి: chrome://network/?refresh=&lt;sec&gt;</translation>
<translation id="2433507940547922241">కనిపించే తీరు</translation>
<translation id="2433836460518180625">పరికరాన్ని మాత్రం అన్‌లాక్ చేయండి</translation>
<translation id="2435248616906486374">నెట్‌వర్క్ డిస్‌కనెక్ట్ అయింది</translation>
@@ -969,8 +970,8 @@
<translation id="2436186046335138073">అన్ని <ph name="PROTOCOL" /> లింక్‌లను తెరవడానికి <ph name="HANDLER_HOSTNAME" />ను అనుమతించాలా?</translation>
<translation id="2436707352762155834">కనిష్టం</translation>
<translation id="2440604414813129000">&amp;సోర్స్‌ను చూడండి</translation>
-<translation id="2445081178310039857">పొడిగింపు మూలం డైరెక్టరీ అవసరం.</translation>
-<translation id="2445484935443597917">కొత్త ప్రొఫైల్‌ని సృష్టించు</translation>
+<translation id="2445081178310039857">ఎక్స్‌టెన్ష‌న్‌ మూలం డైరెక్టరీ అవసరం.</translation>
+<translation id="2445484935443597917">కొత్త ప్రొఫైల్‌ను సృష్టించు</translation>
<translation id="2446585455334014596">మీ గుర్తింపుని ధృవీకరించాలని <ph name="APP_NAME" /> కోరుతోంది</translation>
<translation id="2448312741937722512">రకం</translation>
<translation id="2450223707519584812">Google API కీలు లేనందున మీరు వినియోగదారులను జోడించలేరు. వివరాల కోసం <ph name="DETAILS_URL" /> చూడండి.</translation>
@@ -1006,7 +1007,7 @@
<translation id="2495777824269688114">మరిన్ని ఫీచర్‌లను కనుగొనండి లేదా సమాధానాలను పొందండి. సహాయం కోసం "?" ఎంచుకోండి.</translation>
<translation id="2496180316473517155">బ్రౌజింగ్ చరిత్ర</translation>
<translation id="2497229222757901769">మౌస్ వేగం</translation>
-<translation id="2497852260688568942">సమకాలీకరణను మీ నిర్వాహకులు నిలిపివేసారు</translation>
+<translation id="2497852260688568942">సింక్‌ను మీ నిర్వాహకులు నిలిపివేశారు</translation>
<translation id="249819058197909513">ఈ యాప్ కోసం మళ్లీ హెచ్చరించవద్దు</translation>
<translation id="2498539833203011245">కనిష్ఠీకరించు</translation>
<translation id="2498765460639677199">ఎక్కువ</translation>
@@ -1014,7 +1015,8 @@
<translation id="2500471369733289700">మీ గోప్యతను రక్షించడానికి బ్లాక్ చేయబడింది</translation>
<translation id="2501173422421700905">సర్టిఫికెట్ హోల్డ్‌లో ఉంది</translation>
<translation id="2501797496290880632">షార్ట్‌కట్‌ను టైప్ చేయండి</translation>
-<translation id="2502441965851148920">స్వయంచాలక నవీకరణలు ప్రారంభించబడ్డాయి. స్వయంగా చేసే నవీకరణలను మాత్రం మీ నిర్వాహకులు నిలిపివేసారు.</translation>
+<translation id="2502441965851148920">ఆటోమేటిక్‌ అప్‌డేట్‌లు ప్రారంభించబడ్డాయి. స్వయంగా చేసే అప్‌డేట్‌లను మాత్రం మీ నిర్వాహకులు నిలిపివేశారు.</translation>
+<translation id="2505127913256479918">ఈ పర్యవేక్షిత వినియోగదారు ప్రొఫైల్‌ త్వరలో తీసివేయబడుతుంది</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{స్క్రీన్ #}other{స్క్రీన్ #}}</translation>
<translation id="2505402373176859469"><ph name="TOTAL_SIZE" />లో <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="2508428939232952663">Google Play స్టోర్ ఖాతా</translation>
@@ -1030,7 +1032,7 @@
<translation id="2525250408503682495">క్రిప్టోనైట్! కియోస్క్ అప్లికేషన్ కోసం క్రిప్టోహోమ్ మౌంట్ చేయబడలేదు.</translation>
<translation id="2526277209479171883">ఇన్‌స్టాల్ చేసి, కొనసాగించండి</translation>
<translation id="2526590354069164005">డెస్క్‌టాప్</translation>
-<translation id="2526619973349913024">అప్‌డేట్ కోసం తనిఖీ చేయి</translation>
+<translation id="2526619973349913024">అప్‌డేట్‌ కోసం తనిఖీ చెయ్యి</translation>
<translation id="2527167509808613699">ఎలాంటి కనెక్షన్ అయినా</translation>
<translation id="2532589005999780174">అధిక కాంట్రాస్ట్ మోడ్</translation>
<translation id="253434972992662860">&amp;పాజ్ చెయ్యి</translation>
@@ -1039,18 +1041,18 @@
<translation id="2538361623464451692">సింక్ నిలిపివేయబడింది</translation>
<translation id="2541002089857695151">పూర్తిస్క్రీన్ ప్రసారాన్ని ఆప్టిమైజ్ చేయాలా?</translation>
<translation id="2542049655219295786">Google పట్టిక</translation>
-<translation id="2544853746127077729">ప్రామాణీకరణ సర్టిఫికెట్‌ను నెట్‌వర్క్ తిరస్కరించింది</translation>
+<translation id="2544853746127077729">ప్రామాణీకరణ ప్రమాణపత్రం నెట్‌వర్క్ ద్వారా తిరస్కరించబడింది</translation>
<translation id="2547921442987553570"><ph name="EXTENSION_NAME" />కి జోడించండి</translation>
<translation id="2550212893339833758">వినిమయం చేసిన మెమరీ</translation>
<translation id="2550596535588364872"><ph name="EXTENSION_NAME" />ని <ph name="FILE_NAME" /> తెరవడానికి అనుమతించాలా?</translation>
<translation id="2553340429761841190"><ph name="NETWORK_ID" />కు కనెక్ట్ చెయ్యడానికి <ph name="PRODUCT_NAME" />కి సాధ్యం కాలేదు. దయచేసి మరొక నెట్‌వర్క్‌ని ఎంచుకోండి లేదా మళ్ళీ ప్రయత్నిచండి.</translation>
-<translation id="2553440850688409052">ఈ ప్లగ్ఇన్‌ని దాచిపెట్టు</translation>
+<translation id="2553440850688409052">ఈ ప్లగ్ఇన్‌ను దాచిపెట్టు</translation>
<translation id="2554553592469060349">ఎంచుకోబడిన ఫైల్ చాలా పెద్దదిగా ఉంది (గరిష్ట పరిమాణం: 3mb).</translation>
<translation id="255747371423522804">ఇప్పటికే ఉన్న గుంపునకు జోడించు</translation>
<translation id="2558896001721082624">సిస్టమ్ మెనూలో ఎల్లప్పుడూ యాక్సెస్ సామర్థ్య ఎంపికలను చూపు</translation>
<translation id="2562685439590298522">డాక్స్</translation>
<translation id="2562743677925229011"><ph name="SHORT_PRODUCT_NAME" />కు సైన్ ఇన్ చేయలేదు</translation>
-<translation id="2564520396658920462">AppleScript ద్వారా JavaScriptని అమలు చేయడం ఆఫ్ చేయబడింది. దీనిని ఆన్ చేయడం కోసం, మెనూ బార్ నుండి, వీక్షణ &gt; డెవలపర్ &gt; Apple ఈవెంట్‌ల నుండి 'JavaScriptని అనుమతించండి' ఎంపికను ఎంచుకోండి. మరింత సమాచారం కోసం ఇక్కడ చూడండి: https://support.google.com/chrome/?p=applescript</translation>
+<translation id="2564520396658920462">AppleScript ద్వారా JavaScriptను అమలు చేయడం ఆఫ్ చేయబడింది. దీనిని ఆన్ చేయడం కోసం, మెనూ బార్‌లో, వీక్షించండి &gt; డెవలపర్ &gt; Apple ఈవెంట్‌ల నుండి JavaScriptను అనుమతించండి ఎంపికను ఎంచుకోండి. మరింత సమాచారం కోసం ఇక్కడ చూడండి: https://support.google.com/chrome/?p=applescript</translation>
<translation id="2564653188463346023">మెరుగుపరిచిన స్పెల్ చెక్</translation>
<translation id="2566124945717127842">మీ <ph name="IDS_SHORT_PRODUCT_NAME" /> పరికరాన్ని కొత్త దాని లాగా రీసెట్ చేయడానికి పవర్‌వాష్ చేయండి.</translation>
<translation id="2568774940984945469">సమాచారబార్ కంటైనర్</translation>
@@ -1059,14 +1061,14 @@
<translation id="2575247648642144396">ప్రస్తుత పేజీలో ఎక్స్‌టెన్ష‌న్‌ను అమలు చేయగలిగినప్పుడు ఈ చిహ్నం కనిపిస్తుంది. చిహ్నంపై క్లిక్ చేయడం ద్వారా లేదా <ph name="EXTENSION_SHORTCUT" />ను నొక్కడం ద్వారా ఈ ఎక్స్‌టెన్ష‌న్‌ను ఉపయోగించండి.</translation>
<translation id="257779572837908839">సమావేశాల కోసం Chromebox వలె సెటప్ చేయండి</translation>
<translation id="2579575372772932244">ప్రొఫైల్‌ను పునఃసృష్టిస్తోంది, దయచేసి వేచి ఉండండి...</translation>
-<translation id="2580889980133367162">బహుళ ఫైల్‌లను డౌన్‌లోడ్ చేయడానికి <ph name="HOST" />ని ఎల్లప్పుడూ అనుమతించు</translation>
+<translation id="2580889980133367162">బహుళ ఫైల్‌లను డౌన్‌లోడ్ చేయడానికి <ph name="HOST" />ను ఎల్లప్పుడూ అనుమతించు</translation>
<translation id="2580924999637585241">మొత్తం: <ph name="NUMBER_OF_SHEETS" /> <ph name="SHEETS_LABEL" /></translation>
<translation id="258095186877893873">ఎక్కువ</translation>
<translation id="2582253231918033891"><ph name="PRODUCT_NAME" /> <ph name="PRODUCT_VERSION" /> (ప్లాట్‌ఫారమ్ <ph name="PLATFORM_VERSION" />) <ph name="DEVICE_SERIAL_NUMBER" /></translation>
<translation id="2585724835339714757">ఈ ట్యాబ్‌ మీ స్క్రీన్‌ను షేర్ చేస్తోంది.</translation>
<translation id="2586657967955657006">క్లిప్‌బోర్డ్</translation>
<translation id="2586672484245266891">దయచేసి చిన్న URLని నమోదు చేయండి</translation>
-<translation id="2587922270115112871">పర్యవేక్షించబడే వినియోగదారుని సృష్టించడం వ‌ల్ల Google ఖాతా సృష్టించబడదు. వారి సెట్టింగ్‌లు, డేటా- Chrome సింక్‌తో ఇతర పరికరాలకు అనుసరించబడదు. పర్యవేక్షించబడే వినియోగదారు ఈ పరికరానికి మాత్రమే వర్తింపజేయబడతారు.</translation>
+<translation id="2587922270115112871">పర్యవేక్షించబడే వినియోగదారును సృష్టించడం వలన Google ఖాతా సృష్టించబడదు, వారి సెట్టింగ్‌లు మరియు డేటా Chrome సింక్‌తో ఇతర పరికరాలకు పంపబడవు. పర్యవేక్షించబడే వినియోగదారు ఈ పరికరానికి మాత్రమే వర్తింపజేయబడతారు.</translation>
<translation id="258932246702879617"><ph name="BEGIN_BOLD" />విధి పట్టీకి పిన్ చేయి<ph name="END_BOLD" /> ఎంపికను ఎంచుకోండి</translation>
<translation id="2594999711683503743">Googleలో వెతకండి లేదా URLను టైప్ చేయండి</translation>
<translation id="2603115962224169880">కంప్యూటర్‌ నుండి హానికరమైనవి తీసివేయండి</translation>
@@ -1105,7 +1107,7 @@
<translation id="264810637653812429">అనుకూల పరికరాలు ఏవీ కనుగొనబడలేదు.</translation>
<translation id="2649045351178520408">Base64-ఎన్‌కోడ్ చేసిన ASCII, సర్టిఫికెట్ చైన్</translation>
<translation id="2653033005692233957">శోధన విఫలమైంది</translation>
-<translation id="2653266418988778031">మీరు ప్రమాణపత్ర అధికారి (CA) ప్రమాణపత్రాన్ని తొలగిస్తే, మీ బ్రౌజర్ CA ద్వారా జారీ చెయ్యబడిన ఏ ప్రమాణపత్రాలను ఇకపై నమ్మదు.</translation>
+<translation id="2653266418988778031">మీరు స‌ర్టిఫికెట్‌ అధికారి (CA) స‌ర్టిఫికెట్‌ను తొలగిస్తే, మీ బ్రౌజర్ CA ద్వారా జారీ చేయబడిన ఏ స‌ర్టిఫికెట్‌లను ఇకపై నమ్మదు.</translation>
<translation id="2653659639078652383">సమర్పించు</translation>
<translation id="265390580714150011">ఫీల్డ్ విలువ</translation>
<translation id="2654166010170466751">చెల్లింపు హ్యాండ్లర్‌లను ఇన్‌స్టాల్ చేయడానికి సైట్‌లను అనుమతించండి</translation>
@@ -1127,14 +1129,14 @@
<translation id="2672142220933875349">చెల్లని crx ఫైల్, అన్‌ప్యాక్ చేయడం విఫలమైంది.</translation>
<translation id="2672394958563893062">ఎర్రర్ ఏర్పడింది. మొదటి నుండి పునఃప్రారంభించడానికి క్లిక్ చేయండి.</translation>
<translation id="2673135533890720193">మీ బ్రౌజింగ్ చరిత్రను చదవడానికి అనుమతి</translation>
-<translation id="2673589024369449924">ఈ వినియోగదారు కోసం డెస్క్‌టాప్ షార్ట్‌కట్‌ను సృష్టించు</translation>
+<translation id="2673589024369449924">ఈ వినియోగదారు కోసం డెస్క్‌టాప్ షార్ట్‌క‌ట్‌ను సృష్టించు</translation>
<translation id="2676946222714718093">ఇందులో ప్లే అవుతోంది</translation>
<translation id="2677748264148917807">నిష్క్రమించు</translation>
<translation id="2678063897982469759">మ‌ళ్లీ-ప్రారంభించు</translation>
<translation id="268053382412112343">&amp;చరిత్ర</translation>
<translation id="2683638487103917598">ఫోల్డర్ క్రమబద్ధీకరించబడింది</translation>
-<translation id="2684004000387153598">కొనసాగించడానికి, సరే క్లిక్ చేసి, ఆపై మీ ఇమెయిల్ చిరునామా కోసం కొత్త ప్రొఫైల్‌ని రూపొందించడానికి వ్యక్తిని జోడించు క్లిక్ చేయండి.</translation>
-<translation id="2688196195245426394">పరికరం సర్వర్‌తో నమోదు అవుతున్నప్పుడు ఎర్రర్: <ph name="CLIENT_ERROR" />.</translation>
+<translation id="2684004000387153598">కొనసాగించాలంటే, 'సరే' క్లిక్ చేసి, ఆపై మీ ఇమెయిల్ చిరునామాకు కొత్త ప్రొఫైల్‌ను సృష్టించడానికి 'వ్యక్తిని జోడించు' క్లిక్ చేయండి.</translation>
+<translation id="2688196195245426394">పరికరాన్ని సర్వర్‌తో నమోదు చేస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది: <ph name="CLIENT_ERROR" />.</translation>
<translation id="2690024944919328218">భాష ఎంపికలను చూపు</translation>
<translation id="2691385045260836588">మోడల్</translation>
<translation id="2693176596243495071">అయ్యో! తెలియని ఎర్రర్ ఏర్పడింది. దయచేసి తర్వాత మళ్లీ ప్రయత్నించండి లేదా సమస్య కొనసాగినట్లయితే మీ నిర్వాహకులను సంప్రదించండి.</translation>
@@ -1142,7 +1144,7 @@
<translation id="270358213449696159">Google Chrome OS నిబంధనల కంటెంట్‌లు</translation>
<translation id="2704184184447774363">Microsoft Document Signing</translation>
<translation id="270516211545221798">టచ్‌ప్యాడ్ వేగం</translation>
-<translation id="2705736684557713153">ఇది కనిపించినట్లయితే, స్క్రీన్ దిగువకు స్క్రోల్ చేసి, తక్షణ టెథెరింగ్‌ని ఆన్ చేయండి. ఇది కనిపించకుంటే, మీరు మొత్తం సెట్ చేసినట్లే.</translation>
+<translation id="2705736684557713153">ఇది కనిపించినట్లయితే, స్క్రీన్ దిగువకు స్క్రోల్ చేసి, తక్షణ టెథెరింగ్‌ను ఆన్ చేయండి. ఇది కనిపించకుంటే, మీరు మొత్తం సెట్ చేసినట్లే.</translation>
<translation id="2707024448553392710">అంశాన్ని డౌన్‌లోడ్ చేస్తోంది</translation>
<translation id="270921614578699633">మొత్తం సగటు</translation>
<translation id="2709453993673701466">అవి ఆన్ చేసే ముందు సింక్ మరియు వ్యక్తిగతీకరణను నిర్వహించాలనుకుంటున్నారా? <ph name="BEGIN_LINK" />సెట్టింగ్<ph name="END_LINK" />లను సందర్శించండి.</translation>
@@ -1155,7 +1157,7 @@
<translation id="2719936478972253983">కింది కుక్కీలు బ్లాక్ చేయబడ్డాయి</translation>
<translation id="2721037002783622288">చిత్రం కోసం <ph name="SEARCH_ENGINE" />లో &amp;శోధించండి</translation>
<translation id="2721334646575696520">Microsoft Edge</translation>
-<translation id="2721695630904737430">పర్యవేక్షిత వినియోగదారులను మీ నిర్వాహకులు నిలిపివేసారు.</translation>
+<translation id="2721695630904737430">పర్యవేక్షిత వినియోగదారులను మీ నిర్వాహకులు నిలిపివేశారు.</translation>
<translation id="2724841811573117416">WebRTC లాగ్‌లు</translation>
<translation id="2725200716980197196">నెట్‌వర్క్ కనెక్టివిటీ పునరుద్ధరించబడింది</translation>
<translation id="2727633948226935816">నాకు మళ్లీ గుర్తు చేయవద్దు</translation>
@@ -1174,7 +1176,7 @@
<translation id="2740393541869613458">పర్యవేక్షించబడే వినియోగదారు సందర్శించిన వెబ్‌సైట్‌లను సమీక్షించండి మరియు</translation>
<translation id="2743387203779672305">క్లిప్‌బోర్డ్‌కు కాపీ చేయి</translation>
<translation id="2745080116229976798">Microsoft Qualified Subordination</translation>
-<translation id="2749756011735116528"><ph name="PRODUCT_NAME" />కి సైన్ ఇన్ చేయండి</translation>
+<translation id="2749756011735116528"><ph name="PRODUCT_NAME" />కు సైన్ ఇన్ చేయండి</translation>
<translation id="2749881179542288782">స్పెల్ చెక్‌తో పాటు వ్యాకరణాన్ని కూడా తనిఖీ చేయి</translation>
<translation id="2751739896257479635">EAP 2వ దశ ప్రమాణీకరణ</translation>
<translation id="2755367719610958252">ప్రాప్యత లక్షణాలను నిర్వహించండి</translation>
@@ -1191,7 +1193,7 @@
<translation id="2772936498786524345">స్నీకీ</translation>
<translation id="2773802008104670137">ఈ రకమైన ఫైల్ మీ కంప్యూటర్‌కు హాని కలిగించవచ్చు.</translation>
<translation id="2775104091073479743">వేలిముద్రలను సవరించండి</translation>
-<translation id="2776441542064982094">నెట్‌వర్క్‌లో నమోదు చేయడానికి పరికరాలు అందుబాటులో లేనట్లుగా కనిపిస్తోంది. మీ పరికరం ఆన్‌లో ఉండి, ఇంటర్నెట్‌కు కనెక్ట్ చేయబడి ఉంటే, దాని యొక్క సూచన మాన్యువల్‌లోని సూచనలని పాటించి దాన్ని నమోదు చేయడానికి ప్రయత్నించండి.</translation>
+<translation id="2776441542064982094">నెట్‌వర్క్‌లో నమోదు చేయడానికి పరికరాలు అందుబాటులో లేనట్లుగా కనిపిస్తోంది. మీ పరికరం ఆన్‌లో ఉండి, ఇంటర్నెట్‌కు కనెక్ట్ అయ్యి ఉంటే, దాని సూచన మాన్యువల్‌లోని సూచనలను పాటించి, దానిని నమోదు చేయడానికి ప్రయత్నించండి.</translation>
<translation id="2781692009645368755">Google Pay</translation>
<translation id="2782104745158847185">Linux అప్లికేషన్‌ను ఇన్‌స్టాల్ చేయడంలో ఎర్రర్</translation>
<translation id="2783298271312924866">డౌన్‌లోడ్ చేయబడింది</translation>
@@ -1205,9 +1207,9 @@
<translation id="2787354132612937472">—</translation>
<translation id="2788135150614412178">+</translation>
<translation id="2789486458103222910">సరే</translation>
-<translation id="2791952154587244007">ఎర్రర్ ఏర్పడింది. ఈ పరికరంలో కియోస్క్ యాప్ స్వీయ-ప్రారంభం సాధ్యపడదు.</translation>
+<translation id="2791952154587244007">ఎర్రర్ ఏర్పడింది. కియోస్క్ యాప్‌నకు ఈ పరికరంలో స్వీయ-ప్రారంభం సాధ్యపడదు.</translation>
<translation id="2792290659606763004">Android యాప్‌లను తీసివేయాలా?</translation>
-<translation id="2796424461616874739">"<ph name="DEVICE_NAME" />"కి కనెక్ట్ చేస్తున్నప్పుడు ప్రామాణీకరణ సమయం ముగిసింది.</translation>
+<translation id="2796424461616874739">"<ph name="DEVICE_NAME" />"కు కనెక్ట్ చేస్తున్నప్పుడు ప్రామాణీకరణ సమయం ముగిసింది.</translation>
<translation id="2796740370559399562">కుక్కీల అనుమతి కొనసాగించు</translation>
<translation id="2799223571221894425">మళ్లీ ప్రారంభించు</translation>
<translation id="2800760947029405028">చిత్రాన్ని అప్‌లోడ్ చేయండి</translation>
@@ -1225,11 +1227,11 @@
<translation id="2815693974042551705">బుక్‌మార్క్ ఫోల్డర్</translation>
<translation id="2818476747334107629">ప్రింటర్ వివరాలు</translation>
<translation id="2820957248982571256">స్కాన్ చేస్తోంది...</translation>
-<translation id="2822634587701817431">కుదించు / విస్తరింపజేయి</translation>
+<translation id="2822634587701817431">కుదించు / విస్త‌రించు</translation>
<translation id="2825758591930162672">విషయం యొక్క పబ్లిక్ కీ</translation>
<translation id="2828650939514476812">Wi-Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయండి</translation>
<translation id="2836269494620652131">క్రాష్</translation>
-<translation id="2836635946302913370">ఈ వినియోగదారు పేరుతో సైన్ ఇన్ చేయడం మీ నిర్వాహకుడి ద్వారా నిలిపివేయబడింది.</translation>
+<translation id="2836635946302913370">ఈ వినియోగదారు పేరుతో సైన్ ఇన్ చేయడం, మీ నిర్వాహకుడి ద్వారా నిలిపివేయబడింది.</translation>
<translation id="283669119850230892"><ph name="NETWORK_ID" /> నెట్‌వర్క్‌ను ఉపయోగించడానికి, మొదట దిగువ ఇంటర్నెట్‌కు మీ కనెక్షన్‌ను పూర్తి చేయండి.</translation>
<translation id="2838379631617906747">ఇన్‌స్టాల్ చేస్తోంది</translation>
<translation id="2841837950101800123">ప్రదాత</translation>
@@ -1249,12 +1251,12 @@
<translation id="2861941300086904918">స్థానిక‌ క్లయింట్ భద్రతా మేనేజ‌ర్‌</translation>
<translation id="2864601841139725659">మీ ప్రొఫైల్ చిత్రాన్ని సెట్ చేయండి</translation>
<translation id="2867768963760577682">పిన్ చేసిన ట్యాబ్ లాగా తెరువు</translation>
-<translation id="2868746137289129307">ఈ పొడిగింపు చాలా పాతది మరియు వ్యాపార విధానం కారణంగా నిలిపివేయబడింది. కొత్త సంస్కరణ అందుబాటులో ఉన్నప్పుడు ఇది స్వయంచాలకంగా ప్రారంభించబడవచ్చు.</translation>
+<translation id="2868746137289129307">ఈ ఎక్స్‌టెన్షన్ చాలా పాతది, వ్యాపార విధానం ప్రకారం నిలిపివేయబడింది. కొత్త వెర్షన్ అందుబాటులోకి వచ్చినప్పుడు ఇది ఆటోమేటిక్‌గా ప్రారంభించబడవచ్చు.</translation>
<translation id="2870560284913253234">సైట్</translation>
<translation id="2870909136778269686">అప్‌డేట్ చేస్తోంది...</translation>
<translation id="2871813825302180988">ఈ ఖాతా ఈ పరికరంలో ఇప్పటికే ఉపయోగించబడుతోంది.</translation>
<translation id="287286579981869940"><ph name="PROVIDER_NAME" />ని జోడించు...</translation>
-<translation id="2874343608108773609">మీ అన్ని పరికరాలలో మీ పాస్‌వర్డ్‌లను పొందడానికి, Chromeకి సైన్ ఇన్ చేయండి.</translation>
+<translation id="2874343608108773609">మీ అన్ని పరికరాలలో మీ పాస్‌వర్డ్‌లను పొందడానికి, Chromeకు సైన్ ఇన్ చేయండి.</translation>
<translation id="2875698561019555027">(Chrome ఎర్రర్ పేజీలు)</translation>
<translation id="2876336351874743617">రెండో వేలు</translation>
<translation id="288042212351694283">మీ సార్వత్రిక 2వ కారకం పరికరాలను యాక్సెస్ చేయండి</translation>
@@ -1277,7 +1279,7 @@
<translation id="2902312830803030883">మరిన్ని చర్యలు</translation>
<translation id="2903457445916429186">ఎంచుకున్న అంశాలను తెరవండి</translation>
<translation id="2903882649406874750">సెన్సార్‌లను యాక్సెస్ చేయనీయకుండా ఎల్లప్పుడూ <ph name="HOST" />ని బ్లాక్ చేయి</translation>
-<translation id="2904456025988372123">సైట్ మొదటి ఫైల్ తర్వాత స్వయంచాలకంగా ఫైల్‌లను డౌన్‌లోడ్ చేయడానికి ప్రయత్నించేటప్పుడు అడగాలి</translation>
+<translation id="2904456025988372123">సైట్ మొదటి ఫైల్ తర్వాత ఆటోమేటిక్‌గా ఫైల్‌లను డౌన్‌లోడ్ చేయడానికి ప్రయత్నించేటప్పుడు అడగాలి</translation>
<translation id="2907619724991574506">ప్రారంభ URLలు</translation>
<translation id="2907798539022650680">'<ph name="NAME" />'కి కనెక్ట్ చేయడంలో విఫలమైంది: <ph name="DETAILS" />
సర్వర్ సందేశం: <ph name="SERVER_MSG" /></translation>
@@ -1285,7 +1287,7 @@
<translation id="2910318910161511225">నెట్‌వర్క్‌కి కనెక్ట్ చేసి మళ్లీ ప్రయత్నించండి</translation>
<translation id="2913331724188855103">కుక్కీ డేటాను సేవ్ చేయడానికి, చదవడానికి సైట్‌లను అనుమతిస్తుంది (సిఫార్సు చేయబడింది)</translation>
<translation id="2915102088417824677">కార్యకలాపం లాగ్‌ని చూడండి</translation>
-<translation id="2916073183900451334">ఫారమ్ ఫీల్డ్‌ల లాగా వెబ్‌పేజీ హైలైట్‌ల లింక్‌లపై ట్యాబ్‌ను నొక్కడం</translation>
+<translation id="2916073183900451334">వెబ్‌పేజీలో Tab కీని నొక్కితే లింక్‌లు, ఫారమ్ ఫీల్డ్‌లను హైలైట్ చేస్తుంది</translation>
<translation id="2916745397441987255">ఎక్స్‌టెన్షన్‌లను వెతకండి</translation>
<translation id="2921081876747860777">దయచేసి మీ స్థానిక డేటాను రక్షించడానికి పాస్‌వర్డ్‌ను సృష్టించండి.</translation>
<translation id="2925966894897775835">షీట్‌లు</translation>
@@ -1293,7 +1295,7 @@
<translation id="2927017729816812676">కాష్ నిల్వ</translation>
<translation id="2932085390869194046">పాస్‌వర్డ్‌‌ను సూచించు...</translation>
<translation id="2932330436172705843"><ph name="PROFILE_DISPLAY_NAME" /> (పిల్లల ఖాతా)</translation>
-<translation id="2932483646085333864">సమకాలీకరణను ప్రారంభించడానికి సైన్ అవుట్ చేసి, ఆపై సైన్ ఇన్ చేయండి</translation>
+<translation id="2932483646085333864">సింక్‌ను ప్రారంభించడానికి సైన్ అవుట్ చేసి, సైన్ ఇన్ చేయండి</translation>
<translation id="2932883381142163287">దుర్వినియోగాన్ని నివేదించు</translation>
<translation id="2938225289965773019"><ph name="PROTOCOL" /> లింక్‌లను తెరవండి</translation>
<translation id="2939938020978911855">అందుబాటులో ఉన్న బ్లూటూత్ పరికరాలను చూపు</translation>
@@ -1306,15 +1308,15 @@
<translation id="2944060181911631861">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. సమస్య విశ్లేషణ, పరికరం, యాప్ వినియోగ డేటాను Googleకి ఆటోమేటిక్‌గా పంపడం ద్వారా మీ Android అనుభవాన్ని మెరుగుపరచడంలో సహాయపడండి. ఇది సిస్టమ్, యాప్ స్థిరత్వానికి, అలాగే ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. మీ అదనపు వెబ్ &amp; యాప్ కార్యకలాపం సెట్టింగ్‌ను ఆన్ చేసినట్లయితే, ఈ డేటా మీ Google ఖాతాలో సేవ్ చేయబడవచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
<translation id="2946119680249604491">కనెక్షన్‌ని జోడించండి</translation>
<translation id="2948300991547862301"><ph name="PAGE_TITLE" />కు వెళ్లండి</translation>
-<translation id="29488703364906173">ఆధునిక వెబ్ కోసం రూపొందించబడిన వేగవంతమైన, సరళమైన మరియు సురక్షితమైన వెబ్ బ్రౌజర్.</translation>
+<translation id="29488703364906173">ఆధునిక వెబ్ కోసం రూపొందించబడిన వేగవంతమైన, సరళమైన, సురక్షితమైన వెబ్ బ్రౌజర్.</translation>
<translation id="2949289451367477459">స్థానాన్ని ఉపయోగించండి. స్థాన అనుమతిని కలిగిన యాప్‌లు మరియు సేవలు ఈ పరికర స్థానాన్ని ఉపయోగించడానికి అనుమతించండి. Google కాలానుగుణంగా స్థాన డేటాని సేకరించవచ్చు మరియు స్థాన ఖచ్చితత్వం మరియు స్థానం-ఆధారిత సేవలను మెరుగుపరచడం కోసం ఈ డేటాని అనామకంగా ఉపయోగించవచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
<translation id="2958721676848865875">ప్యాక్ పొడిగింపు హెచ్చరిక</translation>
<translation id="296026337010986570">పూర్తయింది! హానికరమైన సాఫ్ట్‌వేర్ తీసివేయబడింది. ఎక్స్‌టెన్షన్‌లను తిరిగి ఆన్ చేయడానికి, &lt;a href="chrome://extensions"&gt;ఎక్స్‌టెన్షన్‌లు&lt;/a&gt; సందర్శించండి.</translation>
<translation id="2961090598421146107"><ph name="CERTIFICATE_NAME" /> (పొడిగింపు అందించినది)</translation>
-<translation id="2961695502793809356">ముందుకు వెళ్ళడానికి క్లిక్ చెయ్యండి, చరిత్రను చూడటానికి నొక్కి ఉంచండి</translation>
-<translation id="2963151496262057773">క్రింది ప్లగిన్ ప్రతిస్పందించడం లేదు: <ph name="PLUGIN_NAME" />మీరు దీన్ని ఆపివేయాలనుకుంటున్నారా?</translation>
+<translation id="2961695502793809356">ముందుకు వెళ్ళడానికి క్లిక్ చేయండి, చరిత్రను చూడటానికి నొక్కి ఉంచండి</translation>
+<translation id="2963151496262057773">కింది ప్లగ్ఇన్‌ ప్రతిస్పందించడం లేదు: <ph name="PLUGIN_NAME" />మీరు దీనిని ఆపివేయాలనుకుంటున్నారా?</translation>
<translation id="2966937470348689686">Android ప్రాధాన్యతలను నిర్వహించండి</translation>
-<translation id="2972557485845626008">ఫిర్మ్‌వేర్</translation>
+<translation id="2972557485845626008">ఫర్మ్‌వేర్</translation>
<translation id="2972581237482394796">&amp;పునరావృతం</translation>
<translation id="2972642118232180842">ముఖ్యమైన కంటెంట్‌ను మాత్రమే అమలు చేయి (సిఫార్సు చేస్తున్నాము)</translation>
<translation id="2973324205039581528">సైట్‌ని మ్యూట్ చేయండి</translation>
@@ -1348,7 +1350,7 @@
<translation id="3011488081941333749">నిష్క్రమించేటప్పుడు <ph name="DOMAIN" /> నుండి కుక్కీలు తీసివేయబడతాయి</translation>
<translation id="3012631534724231212">(iframe)</translation>
<translation id="3012804260437125868">సురక్షితమైన ఒకే సైట్ కనెక్షన్‌లు మాత్రమే</translation>
-<translation id="3012917896646559015">మీ కంప్యూటర్‌ను మరమ్మత్తు కోసం పంపడానికి దయచేసి వెంటనే మీ హార్డ్‌వేర్ తయారీదారుని సంప్రదించండి.</translation>
+<translation id="3012917896646559015">మీ కంప్యూటర్‌ను మరమ్మత్తు చేయడానికి పంపడానికి, దయచేసి వెంటనే మీ హార్డ్‌వేర్ తయారీదారుని సంప్రదించండి.</translation>
<translation id="3013291976881901233">MIDI పరికరాలు</translation>
<translation id="3015639418649705390">ఇప్పుడే పునఃప్రారంభించు</translation>
<translation id="3016641847947582299">అంశం నవీకరించబడింది</translation>
@@ -1361,7 +1363,7 @@
<translation id="3024374909719388945">24-గంటల గడియారాన్ని ఉపయోగించండి</translation>
<translation id="3031417829280473749">ఏజెంట్ X</translation>
<translation id="3031557471081358569">దిగుమతి చెయ్యడానికి ఐటమ్‌లను ఎంచుకోండి:</translation>
-<translation id="3031601332414921114">ముద్రణను పునఃప్రారంభించు</translation>
+<translation id="3031601332414921114">ప్రింటింగ్‌ను పునఃప్రారంభించు</translation>
<translation id="303198083543495566">భూగోళ శాస్త్రం</translation>
<translation id="3033999583152214331">మీ Chromebookలో Linux సాధనాలు, ఎడిటర్‌లు మరియు IDEలను అమలు చేయండి. &lt;a target = "_ blank" href = " <ph name="URL" /> "&gt;మరింత తెలుసుకోండి&lt;/a&gt;</translation>
<translation id="3036546437875325427">ఫ్లాష్‌ను ప్రారంభించు</translation>
@@ -1373,12 +1375,13 @@
<translation id="3046910703532196514">వెబ్‌పేజీ, సంపూర్ణం</translation>
<translation id="304747341537320566">ప్రసంగ ఇంజిన్‌లు</translation>
<translation id="3053013834507634016">సర్టిఫికెట్ కీ ఉపయోగం</translation>
-<translation id="3057861065630527966">మీ ఫోటోలను మరియు వీడియోలను బ్యాకప్ చేయండి</translation>
+<translation id="3057861065630527966">మీ ఫోటోలను, వీడియోలను బ్యాకప్ చేయండి</translation>
+<translation id="3058498974290601450">సెట్టింగ్‌లలో ఎప్పుడైనా మీరు సింక్‌ను ఆన్ చేయవచ్చు</translation>
<translation id="3060379269883947824">వినడానికి-ఎంచుకోండిని ప్రారంభించు</translation>
<translation id="3061707000357573562">ప్యాచ్ సేవ</translation>
<translation id="3065041951436100775">ట్యాబ్ మూసివేత ప్ర‌తిస్పంద‌న‌.</translation>
<translation id="3067198179881736288">యాప్‌ను ఇన్‌స్టాల్ చేయాలా?</translation>
-<translation id="3067198360141518313">ఈ ప్లగ్ఇన్‌ని అమలు చెయ్యి</translation>
+<translation id="3067198360141518313">ఈ ప్లగ్ఇన్‌ను అమలు చేయి</translation>
<translation id="3071624960923923138">మీరు కొత్త ట్యాబ్‌ను తెరవడానికి ఇక్కడ క్లిక్ చేయవచ్చు</translation>
<translation id="3074037959626057712">మీరు సైన్ ఇన్ చేసి, సింక్‌ను ఆన్ చేసారు</translation>
<translation id="3075874217500066906">పవర్‌వాష్ ప్రక్రియను మొదలుపెట్టడానికి పునఃప్రారంభించడం అవసరం. పునఃప్రారంభించిన తర్వాత మీరు కొనసాగించాలనుకుంటున్నారో లేదో నిర్ధారించమని మిమ్మల్ని అడగడం జరుగుతుంది.</translation>
@@ -1395,13 +1398,13 @@
<translation id="3085752524577180175">SOCKS హోస్ట్</translation>
<translation id="3088325635286126843">&amp;పేరుమార్చు...</translation>
<translation id="3089137131053189723">శోధన తీసివేయబడింది</translation>
-<translation id="3090193911106258841">ఆడియో మరియు వీడియో ఇన్‌పుట్ ప్రాప్యత చేయబడుతోంది</translation>
+<translation id="3090193911106258841">ఆడియో, వీడియో ఇన్‌పుట్ యాక్సెస్‌ చేయబడుతోంది</translation>
<translation id="3090819949319990166">బాహ్య crx ఫైల్‌ను <ph name="TEMP_CRX_FILE" />కి కాపీ చేయడం సాధ్యపడదు.</translation>
<translation id="3090871774332213558">"<ph name="DEVICE_NAME" />" జత చేయబడింది</translation>
<translation id="3101709781009526431">తేదీ మరియు సమయం</translation>
<translation id="3104763887980088552">కార్యకలాప లాగ్</translation>
-<translation id="310671807099593501">సైట్ బ్లూటూత్‌ని ఉపయోగిస్తోంది</translation>
-<translation id="3115128645424181617">మీ ఫోన్‌ను కనుగొనలేము. అది చేతికి అందేంత దగ్గర్లో ఉందనీ, బ్లూటూత్ ఆన్ చేసి ఉన్నట్లు నిర్ధారించుకోండి.</translation>
+<translation id="310671807099593501">సైట్, బ్లూటూత్‌ను ఉపయోగిస్తోంది</translation>
+<translation id="3115128645424181617">మీ ఫోన్‌ను కనుగొనలేము. అది చేతికి అందేంత దగ్గర్లో ఉందని, బ్లూటూత్ ఆన్ చేసి ఉన్నట్లు నిర్ధారించుకోండి.</translation>
<translation id="3115147772012638511">కాష్ కోసం వేచి ఉంది...</translation>
<translation id="3118319026408854581"><ph name="PRODUCT_NAME" /> సహాయం</translation>
<translation id="3120430004221004537">దీనిలో నిర్దిష్ట చర్య కోసం తగిన ఎన్‌క్రిప్షన్ లేదు: "<ph name="DEVICE_NAME" />".</translation>
@@ -1431,18 +1434,18 @@
<translation id="3151562827395986343">చరిత్ర, కుక్కీలు, కాష్ మొదలైన వాటిని తీసివేస్తుంది</translation>
<translation id="3151786313568798007">దృగ్విన్యాసం</translation>
<translation id="3153862085237805241">కార్డ్‌ని సేవ్ చేయండి</translation>
-<translation id="3154351730702813399">పరికర నిర్వాహకుడు మీ బ్రౌజింగ్ కార్యాచరణను పర్యవేక్షించవచ్చు.</translation>
+<translation id="3154351730702813399">పరికర నిర్వాహకుడు మీ బ్రౌజింగ్ కార్యకలాపాన్ని పర్యవేక్షించవచ్చు.</translation>
<translation id="3154429428035006212">నెలకు పైగా ఆఫ్‌లైన్‌లో ఉంది</translation>
-<translation id="3156531245809797194">Chromeని ఉపయోగించాలంటే, దయచేసి సైన్ ఇన్ చేయండి</translation>
+<translation id="3156531245809797194">Chromeను ఉపయోగించడానికి, దయచేసి సైన్ ఇన్ చేయండి</translation>
<translation id="3157931365184549694">పునరుద్ధరించు</translation>
<translation id="3158033540161634471">మీ వేలిముద్రను సెటప్ చేయండి</translation>
-<translation id="3160842278951476457"><ph name="ISSUED_BY" /> [<ph name="ISSUED_TO" />] (హార్డ్‌వేర్ భద్రత కలిగినది)</translation>
+<translation id="3160842278951476457"><ph name="ISSUED_BY" /> [<ph name="ISSUED_TO" />] (హార్డ్‌వేర్ మద్దతు కలిగినది)</translation>
<translation id="316125635462764134">యాప్‌ను తీసివేయి</translation>
<translation id="3161522574479303604">అన్ని భాషలు</translation>
<translation id="3165390001037658081">కొన్ని క్యారియర్‌లు ఈ లక్షణాన్ని బ్లాక్ చేయవచ్చు.</translation>
-<translation id="316854673539778496">మీ అన్ని పరికరాలలో మీ అన్ని ఎక్స్‌టెన్షన్‌లను పొందాలంటే, సైన్ ఇన్ చేసి, సమకాలీకరణను ఆన్ చేయండి.</translation>
+<translation id="316854673539778496">మీ అన్ని పరికరాలలో మీ అన్ని ఎక్స్‌టెన్షన్‌లను పొందడానికి, సైన్ ఇన్ చేసి, సింక్‌ను ఆన్ చేయండి.</translation>
<translation id="3169472444629675720">కనుగొను</translation>
-<translation id="3170072451822350649">మీరు సైన్ ఇన్ చేయడాన్ని కూడా దాటవేయవచ్చు మరియు <ph name="LINK_START" />అతిథిగా బ్రౌజ్ చేయవచ్చు<ph name="LINK_END" />.</translation>
+<translation id="3170072451822350649">మీరు సైన్ ఇన్ చేయడాన్ని కూడా దాట వేయవచ్చు. <ph name="LINK_START" />అతిథిగా బ్రౌజ్ చేయవచ్చు<ph name="LINK_END" />.</translation>
<translation id="3172045848207518317">వీడియో ఇన్‌పుట్‌ని ఒక సైట్ యాక్సెస్ చేస్తోంది</translation>
<translation id="3177909033752230686">పేజీ భాష:</translation>
<translation id="3182749001423093222">స్పెల్ చెక్</translation>
@@ -1471,7 +1474,7 @@
<translation id="3232318083971127729">విలువ:</translation>
<translation id="3236289833370040187">యాజమాన్యం <ph name="DESTINATION_DOMAIN" />కి బదిలీ చేయబడుతుంది.</translation>
<translation id="323803881985677942">ఎక్సటెన్షన్ ఎంపికలను తెరువు</translation>
-<translation id="3241680850019875542">ప్యాక్ చేయడానికి ఎక్స్‌టెన్షన్ యొక్క మూల డైరెక్టరీని ఎంచుకోండి. ఒక ఎక్స్‌టెన్షన్‌ను అప్‌డేట్ చేయడానికి, మళ్ళీ ఉపయోగించడానికి వ్యక్తిగత కీ ఫైల్‌ను కూడా ఎంచుకోండి.</translation>
+<translation id="3241680850019875542">ప్యాక్ చేయ‌డానికి ఎక్స్‌టెన్ష‌న్‌ యొక్క రూట్ డైరెక్టరీని ఎంచుకోండి. ఒక ఎక్స్‌టెన్ష‌న్‌ను అప్‌డేట్ చేయ‌డానికి, మ‌ళ్లీ ఉపయోగించడానికి వ్యక్తిగత కీ ఫైల్‌ను కూడా ఎంచుకోండి.</translation>
<translation id="3244294424315804309">సౌండ్‌ని మ్యూట్ చేయడాన్ని కొనసాగించు</translation>
<translation id="3245321423178950146">తెలియని కళాకారుడు</translation>
<translation id="324849028894344899"><ph name="WINDOW_TITLE" /> - నెట్‌వర్క్ ఎర్రర్</translation>
@@ -1503,7 +1506,7 @@
<translation id="3281892622610078515">నిరోధించాల్సిన ఫైల్‌లు, ప్రోగ్రామ్‌లు:</translation>
<translation id="3282568296779691940">Chromeకు సైన్ ఇన్ చేయండి</translation>
<translation id="3285322247471302225">క్రొత్త &amp;టాబ్</translation>
-<translation id="3288047731229977326">డెవలపర్ మోడ్‌లో అమలవుతున్న ఎక్స్‌టెన్షన్‌లు మీ కంప్యూటర్‌కు హాని కలిగించవచ్చు. మీరు డెవలపర్ కాకపోతే, సురక్షితంగా ఉంచడానికి డెవలపర్ మోడ్‌లో అమలవుతున్న ఈ ఎక్స్‌టెన్షన్‌లను నిలిపివేయాలి.</translation>
+<translation id="3288047731229977326">డెవలపర్ మోడ్‌లో అమలవుతున్న ఎక్స్‌టెన్ష‌న్‌లు మీ కంప్యూటర్‌కు హాని కలిగించవచ్చు. మీరు డెవలపర్ కాకపోతే, సురక్షితంగా ఉంచడానికి డెవలపర్ మోడ్‌లో అమలవుతున్న ఈ ఎక్స్‌టెన్ష‌న్‌లను నిలిపివేయాలి.</translation>
<translation id="3289856944988573801">అప్‌డేట్‌ల కోసం తనిఖీ చేయడానికి, దయచేసి ఈథర్‌నెట్ లేదా Wi-Fiని ఉపయోగించండి.</translation>
<translation id="32939749466444286">Linux కంటైనర్ ప్రారంభించబడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="3294437725009624529">అతిథి</translation>
@@ -1561,10 +1564,11 @@
<translation id="337286756654493126">మీరు అప్లికేషన్‌లో తెరిచే ఫోల్డర్‌లను చదవండి</translation>
<translation id="3378503599595235699">మీరు మీ బ్రౌజర్ నుండి నిష్క్రమించే వరకు మాత్రమే స్థానిక డేటాను భద్రపరచాలి</translation>
<translation id="3378572629723696641">ఈ పొడిగింపు పాడై ఉండవచ్చు.</translation>
-<translation id="3378630551672149129">సైన్ ఇన్ చేయండి. ఇన్‌పుట్ అంశాలతో పరస్పర చర్య చేయడానికి ట్యాబ్ కీని నొక్కండి</translation>
+<translation id="3378630551672149129">సైన్ ఇన్ చేయండి, ఇన్‌పుట్ అంశాలతో పరస్పర చర్య చేయడానికి ట్యాబ్ కీని నొక్కండి</translation>
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> వ్యవస్థాపించబడుతుంది.</translation>
<translation id="3380365263193509176">తెలియని ఎర్రర్</translation>
<translation id="3382073616108123819">అయ్యో! ఈ పరికరం కోసం పరికర ఐడెంటిఫైయర్‌లను నిర్ణయించడంలో సిస్టమ్ విఫలమైంది.</translation>
+<translation id="3382086682569279540">మీరు నిర్వహించే ఖాతా త్వరలో తీసివేయబడుతుంది</translation>
<translation id="3382200254148930874">పర్యవేక్షణను ఆపివేస్తోంది...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">విభాగిని</translation>
@@ -1574,7 +1578,7 @@
<translation id="3399432415385675819">నోటిఫికేషన్‌లు నిలిపివేయబడతాయి</translation>
<translation id="340282674066624"><ph name="DOWNLOAD_RECEIVED" />, <ph name="TIME_LEFT" /></translation>
<translation id="3404065873681873169">ఈ సైట్ కోసం పాస్‌వర్డ్‌లు సేవ్ చేయబడలేదు</translation>
-<translation id="340485819826776184">చిరునామా పట్టీలో టైప్ చేసిన URLలు మరియు శోధనలను పూర్తి చేసేందుకు సహాయం చెయ్యడానికి సూచన సేవను ఉపయోగించండి</translation>
+<translation id="340485819826776184">చిరునామా బార్‌లో టైప్ చేసిన URLలు మరియు శోధనలను పూర్తి చేసేందుకు సహాయం చేయడానికి సూచన సేవను ఉపయోగించండి</translation>
<translation id="3405664148539009465">ఫాంట్‌లను అనుకూలీకరించు</translation>
<translation id="3405763860805964263">...</translation>
<translation id="3406605057700382950"> &amp;బుక్‌మార్క్‌ల బార్‌ను చూపు</translation>
@@ -1592,7 +1596,7 @@
<translation id="3428419049384081277">మీరు సైన్ ఇన్ చేసారు!</translation>
<translation id="3429275422858276529">ఈ పేజీని తర్వాత సులభంగా కనుగొనడానికి దీనిని బుక్‌మార్క్ చేయండి</translation>
<translation id="3432227430032737297">చూపుతున్నవన్నీ తీసివేయి</translation>
-<translation id="3432757130254800023">స్థానిక నెట్‌వర్క్‌లో డిస్‌ప్లేలకు ఆడియో మరియు వీడియోను పంపడం</translation>
+<translation id="3432757130254800023">స్థానిక నెట్‌వర్క్‌లో డిస్‌ప్లేలకు ఆడియోను, వీడియోను పంపడం</translation>
<translation id="3432762828853624962">షేర్డ్ వర్కర్స్</translation>
<translation id="3433621910545056227">అయ్యో! పరికరం ఇన్‌స్టాలేషన్-సమయ లక్షణాల లాక్‌ను ఏర్పాటు చేయడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="3434107140712555581"><ph name="BATTERY_PERCENTAGE" />%</translation>
@@ -1624,7 +1628,7 @@
<translation id="346431825526753">ఇది <ph name="CUSTODIAN_EMAIL" /> నిర్వహించే చిన్నపిల్లల ఖాతా.</translation>
<translation id="3466147780910026086">మీ మీడియా పరికరాన్ని స్కాన్ చేస్తోంది...</translation>
<translation id="3467267818798281173">సూచనల కోసం Googleను అడగండి</translation>
-<translation id="3468275649641751422">వీడియో లేదా ఆడియో ఫైల్‌ని ప్రసారం చేయండి</translation>
+<translation id="3468275649641751422">వీడియో లేదా ఆడియో ఫైల్‌ను ప్రసారం చేయండి</translation>
<translation id="3468522857997926824"><ph name="FILE_COUNT" /> ఫోటోలు <ph name="BEGIN_LINK" />Google డిస్క్<ph name="END_LINK" />కి బ్యాకప్ చేయబడ్డాయి</translation>
<translation id="3468999815377931311">Android ఫోన్</translation>
<translation id="3470442499439619530">ఈ వినియోగదారుని తీసివేయి</translation>
@@ -1635,7 +1639,7 @@
<translation id="3476303763173086583">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. సమస్య విశ్లేషణ, పరికరం, యాప్ వినియోగ డేటాను ఆటోమేటిక్‌గా Googleకి పంపడం ద్వారా మీ చిన్నారి Android అనుభవాన్ని మెరుగుపరచడంలో సహాయపడండి. ఇది మీ చిన్నారి గురించి గుర్తించడానికి ఉపయోగించబడదు, ఇది కేవలం సిస్టమ్, యాప్ స్థిరత్వానికి, ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. ఈ <ph name="BEGIN_LINK1" />సెట్టింగ్‌<ph name="END_LINK1" />ని యజమాని అమలు చేసారు. ఈ పరికరానికి సంబంధించిన విశ్లేషణ, వినియోగ డేటాను Googleకి పంపేలా యజమాని ఎంచుకోవచ్చు. మీ చిన్నారి కోసం అదనపు వెబ్ &amp; యాప్ కార్యకలాపం సెట్టింగ్‌ను ఆన్ చేసినట్లయితే, ఈ డేటా వారి Google ఖాతాలో సేవ్ చేయబడవచ్చు. <ph name="BEGIN_LINK2" />మరింత తెలుసుకోండి<ph name="END_LINK2" /></translation>
<translation id="347670947055184738">అయ్యో! మీ పరికరం కోసం విధానాన్ని పొందడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="347785443197175480">మీ కెమెరా మరియు మైక్రోఫోన్‌ను యాక్సెస్ చేయడానికి <ph name="HOST" />ను అనుమతించడాన్ని కొనసాగించండి</translation>
-<translation id="3478685642445675458">దయచేసి వ్యక్తిని తీసివేయబోయే ముందు మీ ప్రొఫైల్‌ను అన్‌లాక్ చేయండి.</translation>
+<translation id="3478685642445675458">వ్యక్తిని తీసివేయబోయే ముందు దయచేసి మీ ప్రొఫైల్‌ను అన్‌లాక్ చేయండి.</translation>
<translation id="3479552764303398839">ఇప్పుడు కాదు</translation>
<translation id="3480119035619598820">నా పరికరాలకు పంపు</translation>
<translation id="3484273680291419129">హానికరమైన సాఫ్ట్‌వేర్‌ని తీసివేస్తోంది...</translation>
@@ -1645,7 +1649,7 @@
<translation id="3488065109653206955">పాక్షికంగా సక్రియం చెయ్యబడింది</translation>
<translation id="3492788708641132712">సమకాలీకరణ పని చేయడం లేదు. మళ్లీ సైన్ ఇన్ చేేయడానికి ప్రయత్నించండి.</translation>
<translation id="3493881266323043047">చెల్లుబాటు</translation>
-<translation id="3494769164076977169">సైట్ మొదటి ఫైల్ తర్వాత స్వయంచాలకంగా ఫైల్‌లను డౌన్‌లోడ్ చేయడానికి ప్రయత్నించేటప్పుడు అడగాలి (సిఫార్సు చేయబడింది)</translation>
+<translation id="3494769164076977169">సైట్ మొదటి ఫైల్ తర్వాత ఆటోమేటిక్‌గా ఫైల్‌లను డౌన్‌లోడ్ చేయడానికి ప్రయత్నించేటప్పుడు అడగాలి (సిఫార్సు చేయబడింది)</translation>
<translation id="3495304270784461826"><ph name="COUNT" /> లోపాలు.</translation>
<translation id="3495660573538963482">Google సహాయకం సెట్టింగ్‌లు</translation>
<translation id="3496213124478423963">దూరంగా జూమ్ చెయ్యి</translation>
@@ -1657,7 +1661,7 @@
<translation id="3508920295779105875">మరొక ఫోల్డర్‌ను ఎంచుకోండి...</translation>
<translation id="3510797500218907545">WiMAX</translation>
<translation id="3511200754045804813">మళ్లీ స్కాన్ చేయండి</translation>
-<translation id="3511307672085573050">లింక్ చిరు&amp;నామాను కాపీ చెయ్యి</translation>
+<translation id="3511307672085573050">లింక్ చిరు&amp;నామాను కాపీ చేయి</translation>
<translation id="351152300840026870">స్థిర-వెడల్పు ఫాంట్</translation>
<translation id="3511528412952710609">స్వల్పం</translation>
<translation id="3514373592552233661">ఒకటి కంటే ఎక్కువ నెట్‌వర్క్‌లు అందుబాటులో ఉంటే, తెలిసిన ఇతర నెట్‌వర్క్‌ల కంటే ప్రాధాన్య నెట్‌వర్క్‌లకు ప్రాధాన్యత ఇవ్వబడుతుంది</translation>
@@ -1676,14 +1680,14 @@
<translation id="3538066758857505094">Linuxని అన్‌ఇన్‌స్టాల్ చేయడంలో ఎర్రర్ ఏర్పడింది. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="354060433403403521">AC అడాప్టర్</translation>
<translation id="354068948465830244">ఇది సైట్ డేటాను చదవగలదు మరియు మార్చగలదు</translation>
-<translation id="3543393733900874979">అప్‌డేట్ చేయడం విఫలమైంది (ఎర్రర్: <ph name="ERROR_NUMBER" />)</translation>
+<translation id="3543393733900874979">అప్‌డేట్ చేయ‌డం విఫలమైంది (ఎర్ర‌ర్‌: <ph name="ERROR_NUMBER" />)</translation>
<translation id="3543597750097719865">SHA-512తో X9.62 ECDSA సంతకం</translation>
<translation id="3544879808695557954">వినియోగదారు పేరు (ఐచ్ఛికం)</translation>
<translation id="354602065659584722">హానికరమైన సాఫ్ట్‌వేర్ తీసివేయబడింది</translation>
-<translation id="3547495624659668105">PRL సంస్కరణ</translation>
+<translation id="3547495624659668105">PRL వెర్షన్</translation>
<translation id="3547954654003013442">ప్రాక్సీ సెట్టింగ్‌లు</translation>
<translation id="3549797760399244642">drive.google.comకు వెళ్లండి...</translation>
-<translation id="3550915441744863158">Chrome స్వయంచాలకంగా నవీకరించబడుతుంది కాబట్టి మీరు ఎల్లప్పుడూ సరికొత్త సంస్కరణను కలిగి ఉంటారు</translation>
+<translation id="3550915441744863158">Chrome ఆటోమేటిక్‌గా అప్‌డేట్ అవుతుంది కాబట్టి మీ వద్ద ఎప్పుడూ సరికొత్త వెర్షన్ ఉంటుంది</translation>
<translation id="3551320343578183772">ట్యాబ్‌ను మూసివేయి</translation>
<translation id="3552780134252864554">నిష్క్రమణలో క్లియర్ చేయబడింది</translation>
<translation id="3555812735919707620">ఎక్సటెన్షన్‌ని తీసివేయి</translation>
@@ -1697,7 +1701,7 @@
<translation id="3569382839528428029">మీరు మీ స్క్రీన్‌ను <ph name="APP_NAME" /> భాగస్వామ్యం చేయాలనుకుంటున్నారా?</translation>
<translation id="3570985609317741174">వెబ్ కంటెంట్</translation>
<translation id="3571734092741541777">సెటప్ చేయి</translation>
-<translation id="3574210789297084292">సైన్ ఇన్ అవ్వండి</translation>
+<translation id="3574210789297084292">సైన్ ఇన్</translation>
<translation id="3574917942258583917">ఏదేమైనా అజ్ఞాత మోడ్ నుండి నిష్క్రమించాలా?</translation>
<translation id="3576324189521867626">విజయవంతంగా ఇన్‌స్టాల్ చేయబడింది</translation>
<translation id="3578594933904494462">ఈ ట్యాబ్ యొక్క కంటెంట్ భాగస్వామ్యం చేయబడుతోంది.</translation>
@@ -1707,7 +1711,7 @@
<translation id="3587482841069643663">మొత్తం</translation>
<translation id="358796204584394954">జత చేయడానికి "<ph name="DEVICE_NAME" />"లో ఈ కోడ్‌ను టైప్ చేయండి:</translation>
<translation id="3589766037099229847">అసురక్షిత కంటెంట్ బ్లాక్ చేయబడింది</translation>
-<translation id="3590194807845837023">ప్రొఫైల్‌ని అన్‌లాక్ చేసి, మళ్లీ లాంచ్ చేయి</translation>
+<translation id="3590194807845837023">ప్రొఫైల్‌ను అన్‌లాక్ చేసి, మళ్లీ ప్రారంభించు</translation>
<translation id="3590295622232282437">నిర్వహిత సెషన్‌లోకి ప్రవేశిస్తోంది.</translation>
<translation id="3592260987370335752">&amp;మరింత తెలుసుకోండి</translation>
<translation id="359283478042092570">నమోదు చేయి</translation>
@@ -1718,7 +1722,7 @@
<translation id="360180734785106144">కొత్త ఫీచర్‌లు అందుబాటులోకి వస్తే వాటిని అందించడం</translation>
<translation id="3602290021589620013">ప్రివ్యూ</translation>
<translation id="3603533104205588786">మీరు పేజీని బుక్‌మార్క్ చేసేందుకు నక్షత్రం గుర్తును క్లిక్ చేయవచ్చు</translation>
-<translation id="3603622770190368340">నెట్‌వర్క్ స‌ర్టిఫికెట్‌ను పొందండి</translation>
+<translation id="3603622770190368340">నెట్‌వర్క్ ప్రమాణపత్రాన్ని పొందండి</translation>
<translation id="3605780360466892872">బటన్‌డౌన్</translation>
<translation id="3608576286259426129">వినియోగదారు చిత్ర ప్రివ్యూ</translation>
<translation id="3609785682760573515">సమకాలీకరిస్తోంది...</translation>
@@ -1728,7 +1732,7 @@
<translation id="3613134908380545408"><ph name="FOLDER_NAME" />ని చూపు</translation>
<translation id="3613422051106148727">&amp;కొత్త‌ ట్యాబ్‌లో తెరువు</translation>
<translation id="3616113530831147358">ఆడియో</translation>
-<translation id="3616741288025931835">బ్రౌజింగ్ డేటాను &amp;క్లియర్ చెయ్యి...</translation>
+<translation id="3616741288025931835">బ్రౌజింగ్ డేటాను &amp;క్లియర్ చేయి...</translation>
<translation id="3617891479562106823">నేపథ్యాలు అందుబాటులో లేవు. తర్వాత మళ్లీ ప్రయత్నించండి.</translation>
<translation id="3620292326130836921">అన్నీ బ్యాకప్ చేయబడ్డాయి!</translation>
<translation id="3623574769078102674">ఈ పర్యవేక్షించబడే వినియోగదారు <ph name="MANAGER_EMAIL" /> ద్వారా నిర్వహించబడతారు.</translation>
@@ -1737,7 +1741,7 @@
<translation id="3625481642044239431">చెల్లని ఫైల్ ఎంచుకోబడింది. మళ్లీ ప్రయత్నించండి.</translation>
<translation id="3626281679859535460">ప్రకాశం</translation>
<translation id="3627320433825461852">1 నిమిషం కంటే తక్కువ సమయం మిగిలి ఉంది</translation>
-<translation id="3627588569887975815">లింక్‌ను అజ్ఞా&amp;త విండోలో తెరువు</translation>
+<translation id="3627588569887975815">అ&amp;జ్ఞాత విండోలో లింక్‌ను తెరువు</translation>
<translation id="3627671146180677314">Netscape సర్టిఫికెట్ పునరుద్ధరణ సమయం</translation>
<translation id="3627879631695760395"><ph name="APP" />ను ఇన్‌స్టాల్ చేయి...</translation>
<translation id="3630132874740063857">మీ ఫోన్</translation>
@@ -1745,8 +1749,8 @@
<translation id="3636096452488277381">హాయ్, <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - <ph name="TIME" /> మిగిలి ఉంది</translation>
<translation id="3637682276779847508">మీరు సరైన PIN అన్‌లాక్ కీని నమోదు చేయకపోతే, మీ SIM కార్డ్ శాశ్వతంగా నిలిపివేయబడుతుంది.</translation>
-<translation id="363863692969456324">మెరుగుపరచబడిన స్పెల్‌చెక్‌తో స్పెల్లింగ్ ఎర్రర్‌లను సరిదిద్దిండి</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> కోసం "<ph name="EXTENSION_NAME" />"ని జోడించాలా?</translation>
+<translation id="3640613767643722554">మీ వాయిస్‌ను గుర్తించేలా అసిస్టెంట్‌కు తగిన శిక్షణ ఇవ్వండి</translation>
<translation id="3644896802912593514">వెడల్పు</translation>
<translation id="3645372836428131288">వేలిముద్రలోని వేరే భాగాన్ని క్యాప్చర్ చేయడం కోసం కొద్దిగా కదిలించండి.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> గుర్తించబడింది</translation>
@@ -1759,7 +1763,7 @@
<translation id="3653842108912548333">మీ అసిస్టెంట్‌ని Voice Match సాయంతో యాక్సెస్ చేసుకోండి</translation>
<translation id="3653999333232393305">మీ మైక్రోఫోన్‌ను యాక్సెస్ చేయడానికి <ph name="HOST" />కి అనుమతిని కొనసాగించండి</translation>
<translation id="3654045516529121250">మీ ప్రాప్యత సెట్టింగ్‌లను చదవండి</translation>
-<translation id="3655712721956801464">{NUM_FILES,plural, =1{ఇది ఒక ఫైల్‌కు శాశ్వత ప్రాప్యతను కలిగి ఉంది.}other{ఇది # ఫైల్‌లకు శాశ్వత ప్రాప్యతను కలిగి ఉంది.}}</translation>
+<translation id="3655712721956801464">{NUM_FILES,plural, =1{ఇది ఒక ఫైల్‌కు శాశ్వత యాక్సెస్‌ను కలిగి ఉంది.}other{ఇది # ఫైల్‌లకు శాశ్వత యాక్సెస్‌ను కలిగి ఉంది.}}</translation>
<translation id="3660234220361471169">అవిశ్వసనీయ</translation>
<translation id="3664511988987167893">ఎక్స్‌టెన్షన్ చిహ్నం</translation>
<translation id="3665589677786828986">మీ సెట్టింగ్‌లలో కొన్నింటిని మరో ప్రోగ్రామ్ మార్చినట్లుగా Chrome గుర్తించింది, తర్వాత వాటిని వాటి అసలు డిఫాల్ట్‌లకు రీసెట్ చేసింది.</translation>
@@ -1818,7 +1822,7 @@
<translation id="3737536731758327622">మీ డౌన్‌లోడ్‌లు ఇక్కడ కనిపిస్తాయి</translation>
<translation id="3738924763801731196"><ph name="OID" />:</translation>
<translation id="3739254215541673094"><ph name="APPLICATION" />ని తెరవాలా?</translation>
-<translation id="3741243925913727067">మీ మీడియా పరికర ఫోటోలు మరియు వీడియోలను Google డిస్క్‌కి బ్యాకప్ చేయండి.</translation>
+<translation id="3741243925913727067">మీ మీడియా పరికర ఫోటోలు మరియు వీడియోలను Google డిస్క్‌కు బ్యాకప్ చేయండి.</translation>
<translation id="3742055079367172538">స్క్రీన్‌షాట్ తీసినప్పుడు</translation>
<translation id="3742666961763734085">ఈ పేరుతో సంస్థాగత యూనిట్ కనుగొనబడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="3744111561329211289">నేపథ్య సమకాలీకరణ</translation>
@@ -1840,13 +1844,13 @@
<translation id="3765246971671567135">ఆఫ్‌లైన్ డెమో మోడ్ విధానాన్ని చదవడం సాధ్యపడలేదు.</translation>
<translation id="3766223500670287046">రిమోట్ స్క్రీన్</translation>
<translation id="3768037234834996183">మీ ప్రాధాన్యతలను సమకాలీకరిస్తోంది...</translation>
-<translation id="3771294271822695279">వీడియో ఫైళ్ళు</translation>
+<translation id="3771294271822695279">వీడియో ఫైళ్లు</translation>
<translation id="3775432569830822555">SSL సర్వర్ సర్టిఫికెట్</translation>
<translation id="3776796446459804932">ఈ పొడిగింపు Chrome వెబ్ స్టోర్ విధానాన్ని ఉల్లంఘిస్తోంది.</translation>
<translation id="3777806571986431400">పొడిగింపు ప్రారంభించబడింది</translation>
<translation id="3778152852029592020">డౌన్‌లోడ్ చేయడం రద్దు చేయబడింది.</translation>
<translation id="3778740492972734840">డెవలపర్ ఉపకరణాలు</translation>
-<translation id="3778868487658107119">దీన్ని ప్రశ్నలు అడగండి. కార్యాచరణలు చేయమని ఆదేశించండి. ఇది మీ వ్యక్తిగతమైన Google, ఎల్లవేళలా సహాయం చేయడానికి సిద్ధంగా ఉంటుంది.</translation>
+<translation id="3778868487658107119">దీనిని ప్రశ్నలు అడగండి. పనులు చేయమని చెప్పండి. ఇది మీ వ్యక్తిగతమైన Google, ఎల్లవేళలా సహాయం చేయడానికి సిద్ధంగా ఉంటుంది.</translation>
<translation id="3780536599611287598">'<ph name="FOLDER_NAME" />'లోకి ఫైల్‌లను తరలించడానికి మీకు అనుమతి లేదు.</translation>
<translation id="378312418865624974">ఈ కంప్యూటర్ యొక్క ప్రత్యేక ఐడెంటిఫైయర్‌ని చదవడం</translation>
<translation id="3785071023202624850">{NUM_TABS,plural, =1{ట్యాబ్‌ను మ్యూట్ చేయి}other{ట్యాబ్‌లను మ్యూట్ చేయి}}</translation>
@@ -1859,10 +1863,10 @@
<translation id="3792890930871100565">ముద్రకాలను డిస్‌కనెక్ట్ చేయి</translation>
<translation id="3796648294839530037">ఇష్టమైన నెట్‌వర్క్‌లు:</translation>
<translation id="3797900183766075808">“<ph name="SEARCH_TERMS" />” కోసం <ph name="SEARCH_ENGINE" />లో &amp;శోధించండి</translation>
-<translation id="3798449238516105146">సంస్కరణ</translation>
+<translation id="3798449238516105146">వెర్షన్</translation>
<translation id="3799201711591988491">{COUNT,plural, =0{అన్నింటినీ &amp;తెరవండి}=1{బుక్‌మార్క్‌ని &amp;తెరవండి}other{అన్నింటినీ (#) &amp;తెరవండి}}</translation>
<translation id="3800806661949714323">అన్నీ చూపు (సిఫార్సు చేయబడింది)</translation>
-<translation id="380408572480438692">పనితీరు డేటా సేకరణను ప్రారంభించడం అనేది సమయానుగుణంగా సిస్టమ్‌ను మెరుగుపరచడానికి Googleకు సహాయపడుతుంది. మీరు అభిప్రాయ నివేదిక (Alt-Shift-I)ను ఫైల్ చేసి, పనితీరు డేటాను చేర్చే వరకు డేటా పంపబడదు. మీరు ఎప్పుడైనా సేకరణను నిలిపివేయడానికి ఈ స్క్రీన్‌కి తిరిగి రావచ్చు.</translation>
+<translation id="380408572480438692">పనితీరు డేటా సేకరణను ప్రారంభించడం అనేది, సమయానుగుణంగా సిస్టమ్‌ను మెరుగుపరచడంలో Googleకు సహాయపడుతుంది. మీరు అభిప్రాయ నివేదిక (Alt-Shift-I)ను ఫైల్ చేసి, పనితీరు డేటాను చేర్చే వరకు డేటా పంపబడదు. మీరు ఎప్పుడైనా సేకరణను నిలిపివేయడానికి ఈ స్క్రీన్‌కు తిరిగి రావచ్చు.</translation>
<translation id="3807249107536149332"><ph name="EXTENSION_NAME" /> (ఎక్స్‌టెన్షన్‌ ID "<ph name="EXTENSION_ID" />") లాగిన్ స్క్రీన్‌లో అనుమతించబడదు.</translation>
<translation id="3807747707162121253">&amp;రద్దు</translation>
<translation id="38089336910894858">⌘Qతో నిష్క్రమించడానికి ముందు హెచ్చరికను చూపు</translation>
@@ -1871,7 +1875,7 @@
<translation id="3811494700605067549">1 ఫైల్ ఎంచుకోబడింది</translation>
<translation id="381202950560906753">మరొక దానిని జోడించు</translation>
<translation id="3812525830114410218">ప్రమాణపత్రం చెల్లదు</translation>
-<translation id="3813296892522778813">మీరు వెతుకుతున్నది మీకు కనిపించకపోతే <ph name="BEGIN_LINK_CHROMIUM" />Google Chrome సహాయం<ph name="END_LINK_CHROMIUM" />కి వెళ్లండి</translation>
+<translation id="3813296892522778813">మీరు వెతుకుతున్నది మీకు కనిపించకపోతే <ph name="BEGIN_LINK_CHROMIUM" />Google Chrome సహాయం<ph name="END_LINK_CHROMIUM" />కు వెళ్లండి</translation>
<translation id="3817579325494460411">అందించబడలేదు</translation>
<translation id="3819261658055281761">ఈ పరికరానికి దీర్ఘకాల API యాక్సెస్ టోకెన్‌ను నిల్వ చేయడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="3819752733757735746">స్విచ్ యాక్సెస్ (కేవలం ఒకటి లేదా రెండు స్విచ్‌లతో కంప్యూటర్‌ను నియంత్రించండి)</translation>
@@ -1892,7 +1896,7 @@
<translation id="3835522725882634757">అయ్యో! ఈ సర్వర్ పంపిస్తున్న డేటా <ph name="PRODUCT_NAME" />కు అర్థం కాలేదు. దయచేసి <ph name="BEGIN_LINK" />బగ్‌ను నివేదించి<ph name="END_LINK" />, అందులో <ph name="BEGIN2_LINK" />అసలు జాబితా<ph name="END2_LINK" />ను చేర్చండి.</translation>
<translation id="3838085852053358637">ఎక్స్‌టెన్షన్‌ను లోడ్ చేయడం విఫలమైంది</translation>
<translation id="3838486795898716504">మరిన్ని <ph name="PAGE_TITLE" /></translation>
-<translation id="3838543471119263078">కుక్కీలు మరియు ఇతర సైట్ మరియు ప్లగిన్ డేటా</translation>
+<translation id="3838543471119263078">కుక్కీలు మరియు ఇతర సైట్ మరియు ప్లగ్ఇన్‌ డేటా</translation>
<translation id="383891835335927981">సైట్‌లు ఏవీ దగ్గరకు లేదా దూరానికి జూమ్ చేయబడలేదు</translation>
<translation id="3839516600093027468">క్లిప్‌బోర్డ్‌ను చూడనీయకుండా ఎల్లప్పుడూ <ph name="HOST" />ని బ్లాక్ చేయి</translation>
<translation id="3842552989725514455">Serif ఫాంట్</translation>
@@ -1919,11 +1923,11 @@
<translation id="3870931306085184145"><ph name="DOMAIN" /> కోసం సేవ్ చేసిన పాస్‌వర్డ్‌లు లేవు</translation>
<translation id="3871092408932389764">అతి తక్కువ</translation>
<translation id="3872220884670338524">మరిన్ని చర్యలు, <ph name="DOMAIN" />లో <ph name="USERNAME" /> కోసం సేవ్ చేయబడిన ఖాతా</translation>
-<translation id="3872991219937722530">డిస్క్ స్థలాన్ని ఖాళీ చేయండి, లేదంటే పరికరం ప్రతిస్పందనరహితం అవుతుంది.</translation>
+<translation id="3872991219937722530">డిస్క్ స్థలాన్ని ఖాళీ చేయండి, లేదంటే పరికరం ఇక స్పందించదు.</translation>
<translation id="3873315167136380065">దీన్ని ఆన్ చేయడానికి, మీ సమకాలీకరణ రహస్య పదబంధాన్ని తీసివేయడానికి <ph name="BEGIN_LINK" />సమకాలీకరణను రీసెట్ చేయండి<ph name="END_LINK" /></translation>
<translation id="3873915545594852654">ARC++కి సంబంధించి ఒక సమస్య సంభవించింది.</translation>
<translation id="3878840326289104869">పర్యవేక్షించబడే వినియోగదారుని సృష్టిస్తోంది</translation>
-<translation id="3879748587602334249">డౌన్‌లోడ్ నిర్వాహికి</translation>
+<translation id="3879748587602334249">డౌన్‌లోడ్ మేనేజ‌ర్‌</translation>
<translation id="3888550877729210209"><ph name="LOCK_SCREEN_APP_NAME" />తో గమనికలు రూపొందిస్తున్నారు</translation>
<translation id="3892414795099177503">OpenVPN / L2TPని జోడించు...</translation>
<translation id="3893536212201235195">మీ ప్రాప్యత సౌలభ్య సెట్టింగ్‌లను చదవడానికి మరియు మార్చడానికి అనుమతి</translation>
@@ -1941,7 +1945,7 @@
<translation id="3909477809443608991">రక్షిత కంటెంట్‌ను ప్లే చేయడానికి <ph name="URL" /> అనుమతి కోరుతుంది. మీ పరికరం గుర్తింపు Google ద్వారా ధృవీకరించబడుతుంది, దీనిని ఈ సైట్ ద్వారా యాక్సెస్ చేయవచ్చు</translation>
<translation id="3909690856344416952"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /> మరియు మరొకటి</translation>
<translation id="3909791450649380159">క&amp;త్తిరించు</translation>
-<translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ఈ పరికరంలో పేరు ఉపయోగించబడింది)</translation>
+<translation id="3911073280391218446"><ph name="USER_DISPLAY_NAME" /> (ఈ పరికరంలో ఉపయోగించబడిన పేరు)</translation>
<translation id="3911824782900911339">కొత్త‌ ట్యాబ్ పేజీ</translation>
<translation id="3915280005470252504">వాయిస్ ద్వారా వెతుకు</translation>
<translation id="3916445069167113093">ఈ రకం ఫైల్‌ మీ కంప్యూటర్‌కు హాని చేయవచ్చు. అయినా సరే <ph name="FILE_NAME" />ని ఉంచాలని అనుకుంటున్నారా?</translation>
@@ -1986,7 +1990,7 @@
<translation id="3966072572894326936">మరొక ఫోల్డర్‌ను ఎంచుకోండి...</translation>
<translation id="3966388904776714213">ఆడియో ప్లేయర్</translation>
<translation id="3967822245660637423">డౌన్‌లోడ్ పూర్తయింది</translation>
-<translation id="3967919079500697218">మీ నిర్వాహకులు స్క్రీన్‌షాట్‌లను తీయగల సామర్థ్యాన్ని నిలిపివేసారు.</translation>
+<translation id="3967919079500697218">మీ నిర్వాహకులు స్క్రీన్‌షాట్‌లను తీయగల సామర్ధ్యాన్ని నిలిపివేశారు.</translation>
<translation id="3970114302595058915">ID</translation>
<translation id="397105322502079400">గణిస్తోంది...</translation>
<translation id="397703832102027365">పూర్తి చేస్తోంది...</translation>
@@ -2034,7 +2038,7 @@
<translation id="4044612648082411741">మీ ప్రమాణపత్రం పాస్‌వర్డ్‌ను నమోదు చేయండి</translation>
<translation id="404493185430269859">డిఫాల్ట్ శోధన ఇంజిన్</translation>
<translation id="4052120076834320548">చిన్న</translation>
-<translation id="4055023634561256217">మీ పరికరాన్ని పవర్‌వాష్‌తో రీసెట్ చేసే ముందు పునఃప్రారంభించడం అవసరం.</translation>
+<translation id="4055023634561256217">మీ పరికరాన్ని పవర్‌వాష్‌తో రీసెట్ చేయడానికి ముందు పునఃప్రారంభించడం అవసరం.</translation>
<translation id="4057041477816018958"><ph name="SPEED" /> - <ph name="RECEIVED_AMOUNT" /></translation>
<translation id="4057896668975954729">స్టోర్‌లో వీక్షించండి</translation>
<translation id="4058647953897694817">బ్లూటూత్ ద్వారా ధృవీకరించు</translation>
@@ -2046,7 +2050,7 @@
<translation id="4068776064906523561">సేవ్ చేయబడిన వేలిముద్రలు</translation>
<translation id="407173827865827707">క్లిక్ చేసినప్పుడు</translation>
<translation id="4072793381000095">{NUM_TABS,plural, =1{ట్యాబ్‌ను అన్‌పిన్ చేయి}other{ట్యాబ్‌లను అన్‌పిన్ చేయి}}</translation>
-<translation id="4074900173531346617">ఇమెయిల్ సైన్ చేసిన వారి సర్టిఫికెట్</translation>
+<translation id="4074900173531346617">ఇమెయిల్ సైన్ చేసినవారి సర్టిఫికెట్</translation>
<translation id="407520071244661467">ప్రమాణం</translation>
<translation id="4075639477629295004"><ph name="FILE_NAME" />ని ప్రసారం చేయడం సాధ్యపడలేదు.</translation>
<translation id="4077917118009885966">ఈ సైట్‌లో ప్రకటనలు బ్లాక్ చేయబడ్డాయి</translation>
@@ -2067,17 +2071,17 @@
<translation id="4093955363990068916">స్థానిక ఫైల్:</translation>
<translation id="4095507791297118304">ప్రాథమిక డిస్‌ప్లే</translation>
<translation id="409579654357498729">క్లౌడ్ ప్రింట్‌కు జోడించు</translation>
-<translation id="4096508467498758490">డెవలపర్ మోడ్ పొడిగింపులను నిలిపివేయండి</translation>
+<translation id="4096508467498758490">డెవలపర్ మోడ్ ఎక్స్‌టెన్ష‌న్‌లను నిలిపివేయండి</translation>
<translation id="4096824249111507322">సురక్షిత మాడ్యూల్ సిద్ధం చేయబడుతోంది, దయచేసి వేచి ఉండండి (ఇందుకు కొన్ని నిమిషాలు పట్టవచ్చు)...</translation>
<translation id="4099060993766194518">డిఫాల్ట్ శోధన ఇంజిన్‌ను పునరుద్ధరించాలా?</translation>
<translation id="4099874310852108874">నెట్‌వర్క్ ఎర్రర్ సంభవించింది.</translation>
<translation id="4100733287846229632">పరికరంలో ఖాళీ స్థలం చాలా తక్కువగా ఉంది</translation>
-<translation id="4103091233824664032">స్క్రీన్ లాక్‌ను, సైన్ ఇన్‌ను కాన్ఫిగర్ చేయడం కోసం మీ పాస్‌వర్డ్‌ను నమోదు చేయండి</translation>
+<translation id="4103091233824664032">స్క్రీన్ లాక్ మరియు సైన్ ఇన్‌ను కాన్ఫిగర్ చేయడానికి మీ పాస్‌వర్డ్‌ను నమోదు చేయండి</translation>
<translation id="4104163789986725820">ఎ&amp;గుమతి...</translation>
<translation id="4107048419833779140">నిల్వ డివైజ్‌లను గుర్తించి, తొలగించండి</translation>
<translation id="4109135793348361820">విండోను <ph name="USER_NAME" /> (<ph name="USER_EMAIL" />)కి తరలించండి</translation>
<translation id="4110490973560452005">డౌన్‌లోడ్ పూర్తయింది: <ph name="FILE_NAME" />. డౌన్‌లోడ్‌ల బార్ ప్రాంతంలోకి వెళ్లడం కోసం Shift+F6 నొక్కండి.</translation>
-<translation id="4110895898888439383">అధిక కాంట్రాస్ట్ మోడ్‌లో వెబ్‌ని బ్రౌజ్ చేయండి</translation>
+<translation id="4110895898888439383">అధిక కాంట్రాస్ట్ మోడ్‌లో వెబ్‌ను బ్రౌజ్ చేయండి</translation>
<translation id="4115002065223188701">నెట్‌వర్క్ అందుబాటులో లేదు</translation>
<translation id="4115080753528843955">రక్షిత కంటెంట్‌కు యాక్సెస్‌ను ప్రామాణీకరించే ప్రయోజనాల కోసం కొన్ని కంటెంట్ సేవలు ప్రత్యేక ఐడెంటిఫైయర్‌లను ఉపయోగిస్తాయి</translation>
<translation id="4118579674665737931">దయచేసి పరికరాన్ని రీబూట్ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
@@ -2110,7 +2114,7 @@
<translation id="4172051516777682613">ఎల్లప్పుడూ చూపు</translation>
<translation id="4175737294868205930">నిరంతర నిల్వ</translation>
<translation id="4176463684765177261">ఆపివేయబడింది</translation>
-<translation id="4180788401304023883">ప్రమాణపత్రం "<ph name="CERTIFICATE_NAME" />"ని తొలగించాలా?</translation>
+<translation id="4180788401304023883">CA ప్రమాణపత్రం "<ph name="CERTIFICATE_NAME" />"ను తొలగించాలా?</translation>
<translation id="4181602000363099176">20x</translation>
<translation id="4181841719683918333">భాషలు</translation>
<translation id="4184885522552335684">డిస్‌ప్లేను తరలించడానికి లాగండి</translation>
@@ -2128,7 +2132,7 @@
<translation id="4206944295053515692">సూచనల కోసం Googleను అడగండి</translation>
<translation id="4208390505124702064"><ph name="SITE_NAME" />లో వెతకండి</translation>
<translation id="4209092469652827314">పెద్దది</translation>
-<translation id="4209464433672152343">ముద్రించడం కోసం పత్రాలను సిద్ధం చేయడానికి అవి <ph name="BEGIN_LINK_HELP" />Googleకు పంపబడతాయి<ph name="END_LINK_HELP" />. <ph name="BEGIN_LINK_DASHBOARD" />Google క్లౌడ్ ప్రింట్ డాష్‌బోర్డ్<ph name="END_LINK_DASHBOARD" />లో మీ ప్రింటర్‌లు మరియు ప్రింటర్ చరిత్రను చూడండి, సవరించండి మరియు నిర్వహించండి.</translation>
+<translation id="4209464433672152343">ప్రింటింగ్‌ కోసం పత్రాలను సిద్ధం చేయడానికి అవి <ph name="BEGIN_LINK_HELP" />Googleకు పంపబడతాయి<ph name="END_LINK_HELP" />. <ph name="BEGIN_LINK_DASHBOARD" />Google క్లౌడ్ ప్రింట్ డాష్‌బోర్డ్<ph name="END_LINK_DASHBOARD" />లో మీ ప్రింటర్‌లు, ప్రింటర్ చరిత్రను చూడండి. సవరించండి. నిర్వహించండి.</translation>
<translation id="421017592316736757">ఈ ఫైల్‌ను యాక్సెస్ చేయడానికి మీరు తప్పనిసరిగా ఆన్‌లైన్‌లో ఉండాలి.</translation>
<translation id="421182450098841253"> &amp;బుక్‌మార్క్‌ల బార్‌ను చూపు</translation>
<translation id="4211851069413100178">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. సమస్య విశ్లేషణ, పరికరం, యాప్ వినియోగ డేటాను Googleకి ఆటోమేటిక్‌గా పంపడం ద్వారా మీ Android అనుభవాన్ని మెరుగుపరచడంలో సహాయపడండి. ఇది సిస్టమ్, యాప్ స్థిరత్వానికి, అలాగే ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. ఈ <ph name="BEGIN_LINK1" />సెట్టింగ్‌<ph name="END_LINK1" />ని యజమాని అమలు చేసారు. ఈ పరికరానికి సంబంధించిన విశ్లేషణ, వినియోగ డేటాను Googleకి పంపేలా యజమాని ఎంచుకోవచ్చు. మీ అదనపు వెబ్ &amp; యాప్ కార్యకలాపం సెట్టింగ్‌ను ఆన్ చేసినట్లయితే, ఈ డేటా మీ Google ఖాతాలో సేవ్ చేయబడవచ్చు. <ph name="BEGIN_LINK2" />మరింత తెలుసుకోండి<ph name="END_LINK2" /></translation>
@@ -2140,13 +2144,12 @@
<translation id="4225397296022057997">అన్ని సైట్‌లలో</translation>
<translation id="4235200303672858594">పూర్తి స్క్రీన్</translation>
<translation id="4235813040357936597"><ph name="PROFILE_NAME" /> కోసం ఖాతాను జోడించు</translation>
-<translation id="4235965441080806197">సైన్ ఇన్‌ని రద్దు చేయి</translation>
+<translation id="4235965441080806197">సైన్ ఇన్‌ను రద్దు చేయి</translation>
<translation id="4242533952199664413">సెట్టింగ్‌లను తెరువు</translation>
<translation id="4242577469625748426">పరికరంలో విధాన సెట్టింగ్‌లను ఇన్‌స్టాల్ చేయడంలో విఫలమైంది: <ph name="VALIDATION_ERROR" />.</translation>
-<translation id="4244238649050961491">మరిన్ని స్టైలస్ అనువర్తనాలను కనుగొనండి</translation>
+<translation id="4244238649050961491">మరిన్ని స్టైలస్ యాప్‌లను కనుగొనండి</translation>
<translation id="424546999567421758">అధిక డిస్క్ వినియోగం గుర్తించబడింది</translation>
<translation id="424726838611654458">ఎల్లప్పుడూ Adobe Readerలో తెరువు</translation>
-<translation id="4247330672018280062">మీరు వచన ఫీల్డ్‌లలో టైప్ చేసే వచనం Googleకు పంపబడుతుంది</translation>
<translation id="4247901771970415646"><ph name="USERNAME" />కి సమకాలీకరించడం సాధ్యం కాదు</translation>
<translation id="4249248555939881673">నెట్‌వర్క్ కనెక్షన్ కోసం వేచి ఉంది...</translation>
<translation id="4249373718504745892">మీ కెమెరా మరియు మైక్రోఫోన్‌ను ప్రాప్యత చేయకుండా ఈ పేజీ బ్లాక్ చేయబడింది.</translation>
@@ -2157,14 +2160,14 @@
<translation id="4252899949534773101">బ్లూటూత్ నిలిపివేయబడింది</translation>
<translation id="4252996741873942488"><ph name="WINDOW_TITLE" /> - ట్యాబ్ కంటెంట్ భాగస్వామ్యం చేయబడింది</translation>
<translation id="4254813446494774748">అనువాద భాష:</translation>
-<translation id="425573743389990240">వాట్‌లలో బ్యాటరీ తరుగుదల రేట్ (రుణాత్మక విలువ ఉందంటే బ్యాటరీ ఛార్జ్ అవుతోందని అర్థం)</translation>
-<translation id="4256316378292851214">వీడియోను ఇలా సే&amp;వ్ చెయ్యి...</translation>
+<translation id="425573743389990240">వాట్‌లలో బ్యాటరీ తరుగుదల రేట్ (నెగెటివ్‌ విలువ ఉందంటే బ్యాటరీ ఛార్జ్ అవుతోందని అర్థం)</translation>
+<translation id="4256316378292851214">వీడియోను ఇలా సే&amp;వ్ చేయి...</translation>
<translation id="4258348331913189841">ఫైల్ సిస్టమ్‌లు</translation>
<translation id="4261901459838235729">Google ప్రెజెంటేషన్</translation>
<translation id="4263757076580287579">ప్రింటర్ నమోదు రద్దు చేయబడింది.</translation>
<translation id="426564820080660648">అప్‌డేట్‌ల కోసం తనిఖీ చేయడానికి, దయచేసి ఈథర్‌నెట్, Wi-Fi లేదా మొబైల్ డేటాను ఉపయోగించండి.</translation>
<translation id="4268025649754414643">కీ గుప్తీకరణ</translation>
-<translation id="4270393598798225102">సంస్కరణ <ph name="NUMBER" /></translation>
+<translation id="4270393598798225102">వెర్షన్ <ph name="NUMBER" /></translation>
<translation id="4271396100647220620">సరిపోలికలు లేవు</translation>
<translation id="4275830172053184480">మీ పరికరాన్ని పునఃప్రారంభించండి</translation>
<translation id="4278101229438943600">మీ అసిస్టెంట్ సిద్ధంగా ఉంది</translation>
@@ -2174,7 +2177,7 @@
<translation id="4285418559658561636">పాస్‌వర్డ్‌ను అప్‌డేట్ చేయి</translation>
<translation id="4285498937028063278">అన్‌పిన్ చేయి</translation>
<translation id="428565720843367874">ఈ ఫైల్‌ను స్కాన్ చేస్తున్నప్పుడు ఊహించని విధంగా యాంటీ-వైరస్ సాఫ్ట్‌వేర్ విఫలమైంది.</translation>
-<translation id="4287502004382794929">ఈ పరికరాన్ని నమోదు చేయడానికి కావలసిన సాఫ్ట్‌వేర్ లైసెన్స్‌లు మీ వద్ద లేవు. దయచేసి మరిన్నింటిని కొనుగోలు చేయడానికి విక్రయ కేంద్రాన్ని సంప్రదించండి. మీరు ఈ సందేశాన్ని పొరపాటున చూస్తున్నారని విశ్వసిస్తే, దయచేసి మద్దతు కేంద్రాన్ని సంప్రదించండి.</translation>
+<translation id="4287502004382794929">ఈ పరికరాన్ని నమోదు చేయడానికి మీకు తగిన సాఫ్ట్‌వేర్ లైసెన్స్‌లు లేవు. దయచేసి మరిన్నింటిని కొనుగోలు చేయడానికి విక్రయ కేంద్రాన్ని సంప్రదించండి. మీరు ఈ సందేశాన్ని పొరపాటున చూస్తున్నారని విశ్వసిస్తే, దయచేసి మద్దతు కేంద్రాన్ని సంప్రదించండి.</translation>
<translation id="4289540628985791613">స్థూలదృష్టి</translation>
<translation id="4290535918735525311">Linuxతో 1 ఫోల్డర్ షేర్ చేయబడింది</translation>
<translation id="4291934469232591280">వెర్షన్: <ph name="VERSION" /></translation>
@@ -2206,13 +2209,13 @@
<translation id="4342311272543222243">అయ్యో, TPM ఎర్రర్.</translation>
<translation id="4345587454538109430">కాన్ఫిగర్ చేయి...</translation>
<translation id="4348766275249686434">లోపాలను సేకరించు</translation>
-<translation id="4350019051035968019">ఈ పరికరాన్ని మీ ఖాతా చెందిన డొమైన్‌కు నమోదు చేయడం సాధ్యపడదు. ఎందుకంటే పరికరం వేరే డొమైన్ ద్వారా నిర్వహించబడేలా గుర్తించబడింది.</translation>
+<translation id="4350019051035968019">ఈ పరికరాన్ని మీ ఖాతా చెందిన డొమైన్‌కు నమోదు చేయడం సాధ్యపడదు ఎందుకంటే పరికరం వేరే డొమైన్ ద్వారా నిర్వహించబడేలా గుర్తించబడింది.</translation>
<translation id="4354344420232759511">మీరు సందర్శించే సైట్‌లు ఇక్కడ చూపబడతాయి</translation>
<translation id="435527878592612277">మీ ఫోటోని ఎంచుకోండి</translation>
<translation id="4356334633973342967">లేదంటే, మీ స్వంత డ్రైవర్‌ను పేర్కొనండి:</translation>
<translation id="4358353773267946514"><ph name="LANGUAGE_1" />, <ph name="LANGUAGE_2" /></translation>
<translation id="4359408040881008151">ఆధారిత పొడిగింపు(లు) కారణంగా ఇన్‌స్టాల్ చేయబడింది.</translation>
-<translation id="4361142739114356624">ఈ క్లయింట్ సర్టిఫికెట్ యొక్క ప్రైవేట్ కీ లేదు లేదా చెల్లదు</translation>
+<translation id="4361142739114356624">ఈ క్లయింట్ ప్రమాణపత్రం యొక్క ప్రైవేట్ కీ లేదు లేదా చెల్లదు</translation>
<translation id="4363771538994847871">Cast గమ్యస్థానాలు ఏవీ కనుగొనబడలేదు. సహాయం కావాలా?</translation>
<translation id="4364567974334641491"><ph name="APP_NAME" /> ఒక విండోను భాగస్వామ్యం చేస్తోంది.</translation>
<translation id="4364830672918311045">నోటిఫికేషన్‌లను ప్రదర్శించడం</translation>
@@ -2233,7 +2236,7 @@
<translation id="4387004326333427325">ప్రామాణీకరణ ప్రమాణపత్రం రిమోట్‌లో తిరస్కరించబడింది</translation>
<translation id="4389091756366370506">వినియోగదారు <ph name="VALUE" /></translation>
<translation id="439266289085815679">బ్లూటూత్ కాన్ఫిగరేషన్ <ph name="USER_EMAIL" /> ద్వారా నియంత్రించబడుతుంది.</translation>
-<translation id="4394049700291259645">ఆపివెయ్యి</translation>
+<translation id="4394049700291259645">నిలిపివేయి</translation>
<translation id="4400367121200150367">పాస్‌వర్డ్‌లను ఎప్పుడూ సేవ్ చేయని సైట్‌లు ఇక్కడ కనిపిస్తాయి</translation>
<translation id="4400632832271803360">ఎగువ-అడ్డు వరుసలోని కీల ప్రవర్తనను మార్చడానికి లాంచర్ కీని నొక్కి ఉంచండి</translation>
<translation id="4405117686468554883">*.jpeg, *.jpg, *.png</translation>
@@ -2274,7 +2277,7 @@
<translation id="4451757071857432900">అనుచితమైన లేదా తప్పుదారి పట్టించే ప్రకటనలను చూపించే సైట్‌లలో బ్లాక్ చేయబడింది (సిఫార్సు చేయబడింది)</translation>
<translation id="4453946976636652378"><ph name="SEARCH_ENGINE_NAME" />లో వెతకండి లేదా URLని టైప్ చేయండి</translation>
<translation id="4462159676511157176">అనుకూల పేరు సర్వర్‌లు</translation>
-<translation id="4467101674048705704"><ph name="FOLDER_NAME" />ని విస్తరింపజేయండి</translation>
+<translation id="4467101674048705704"><ph name="FOLDER_NAME" />ను విస్తరింపజేయండి</translation>
<translation id="4469477701382819144">అనుచితమైన లేదా తప్పుదారి పట్టించే ప్రకటనలను చూపించే సైట్‌లలో బ్లాక్ చేయబడింది</translation>
<translation id="447252321002412580">Chrome ఫీచర్‌లు మరియు పనితీరును మెరుగుపరచడంలో సహాయపడండి</translation>
<translation id="4472575034687746823">ప్రారంభించండి</translation>
@@ -2327,7 +2330,7 @@
<translation id="4547672827276975204">స్వయంచాలకంగా సెట్ చేయి</translation>
<translation id="4552089082226364758">ఫ్లాష్</translation>
<translation id="4552678318981539154">మరింత నిల్వను కొనుగోలు చేయండి</translation>
-<translation id="4554591392113183336">బాహ్య పొడిగింపు ప్రస్తుతం ఉన్న సంస్కరణతో పోలిస్తే అదేలాంటి సంస్కరణ లేదా తక్కువ సంస్కరణ.</translation>
+<translation id="4554591392113183336">ప్రస్తుతం ఉన్న వెర్షన్‌తో పోలిస్తే, బాహ్య ఎక్స్‌టెన్షన్ అదే వెర్షన్‌కు చెందినది లేదా తక్కువ వెర్షన్‌కు చెందినది.</translation>
<translation id="4555769855065597957">నీడ</translation>
<translation id="4556110439722119938">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌లు మీ Google ఖాతాకు సింక్ చేయ‌బ‌డ‌తాయి. కాబట్టి మీరు వీటిని మీ అన్ని పరికరాల్లో ఉపయోగించవచ్చు</translation>
<translation id="4558426062282641716">స్వీయ-ప్రారంభ అనుమతి అభ్యర్థించబడింది</translation>
@@ -2341,7 +2344,7 @@
<translation id="4568854179928172494">సవరించిన సమయం</translation>
<translation id="4569747168316751899">నిష్క్రియంగా ఉన్నప్పుడు</translation>
<translation id="4570387585180509432">చిరునామాలు, ఫోన్ నంబర్‌లు మరియు మరిన్ని</translation>
-<translation id="4572659312570518089">"<ph name="DEVICE_NAME" />"కి కనెక్ట్ చేస్తున్నప్పుడు ప్రామాణీకరణ రద్దు చేయబడింది.</translation>
+<translation id="4572659312570518089">"<ph name="DEVICE_NAME" />"కు కనెక్ట్ చేస్తున్నప్పుడు ప్రామాణీకరణ రద్దు చేయబడింది.</translation>
<translation id="4572815280350369984"><ph name="FILE_TYPE" /> ఫైల్</translation>
<translation id="457386861538956877">మరిన్ని...</translation>
<translation id="4574741712540401491">• <ph name="LIST_ITEM_TEXT" /></translation>
@@ -2376,8 +2379,8 @@
<translation id="4628762811416793313">Linux కంటెయినర్ సెటప్ పూర్తి కాలేదు. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="4628948037717959914">ఫోటో</translation>
<translation id="4631887759990505102">చిత్రకారుడు</translation>
-<translation id="4633003931260532286">పొడిగింపు కోసం కనీసం "<ph name="IMPORT_NAME" />" యొక్క "<ph name="IMPORT_VERSION" />" వెర్షన్ ఉండాలి, కానీ "<ph name="INSTALLED_VERSION" />" వెర్షన్ మాత్రమే ఇన్‌స్టాల్ చేయబడింది</translation>
-<translation id="4634771451598206121">మళ్ళీ సైన్ ఇన్ చెయ్యండి...</translation>
+<translation id="4633003931260532286">"<ph name="IMPORT_NAME" />" యొక్క వెర్షన్ కనీసం "<ph name="IMPORT_VERSION" />" ఉండాలని ఎక్స్‌టెన్షన్ కోరుతోంది, కానీ "<ph name="INSTALLED_VERSION" />" వెర్షన్ మాత్రమే ఇన్‌స్టాల్ చేయబడి ఉంది</translation>
+<translation id="4634771451598206121">మళ్ళీ సైన్ ఇన్ చేయండి...</translation>
<translation id="4635398712689569051">అతిథి వినియోగదారులకు <ph name="PAGE_NAME" /> అందుబాటులో లేదు.</translation>
<translation id="4641539339823703554">Chrome సిస్టమ్ సమయాన్ని సెట్ చేయలేకపోయింది. దయచేసి దిగువ సమయాన్ని తనిఖీ చేసి, అవసరమైతే సరిదిద్దండి.</translation>
<translation id="4643612240819915418">కొత్త ట్యాబ్‌లో వీడియోను &amp;తెరవండి</translation>
@@ -2385,7 +2388,7 @@
<translation id="4647090755847581616">ట్యాబ్‌ను &amp;మూసివేయి</translation>
<translation id="4647697156028544508">దయచేసి "<ph name="DEVICE_NAME" />" కోసం PINను నమోదు చేయండి:</translation>
<translation id="4648491805942548247">చాలని అనుమతులు</translation>
-<translation id="4648499713050786492">దయచేసి వ్యక్తిని జోడించే ముందు మీ ప్రొఫైల్‌ను అన్‌లాక్ చేయండి.</translation>
+<translation id="4648499713050786492">వ్యక్తిని జోడించే ముందు దయచేసి మీ ప్రొఫైల్‌ను అన్‌లాక్ చేయండి.</translation>
<translation id="4651484272688821107">డెమో మోడ్ వనరులతో ఆన్‌లైన్ అంతర్భాగాన్ని లోడ్ చేయడం సాధ్యపడలేదు.</translation>
<translation id="4656293982926141856">ఈ కంప్యూటర్</translation>
<translation id="4660476621274971848">ఆశించిన వెర్షన్ "<ph name="EXPECTED_VERSION" />", కానీ ఉన్న వెర్షన్ "<ph name="NEW_ID" />"</translation>
@@ -2410,7 +2413,7 @@
<translation id="4690091457710545971">&lt;Intel Wi-Fi ఫర్మ్‌వేర్ రూపొందించిన నాలుగు ఫైల్‌లు: csr.lst, fh_regs.lst, radio_reg.lst, monitor.lst.sysmon. మొదటి మూడు బైనరీ ఫైల్‌లు, వీటిలో రిజిస్టర్ డంప్‌లు ఉంటాయి మరియు వ్యక్తిగత లేదా పరికర సమాచారం కలిగి ఉండకుండా వీటిని Intel అందిస్తోంది. చివరిది Intel ఫర్మ్‌వేర్ అందించే, అమలు స్థితిగతిని కనుగొనే ఫైల్; ఇందులో వ్యక్తిగత లేదా పరికర గుర్తింపు సమాచారం తీసివేయబడింది, కానీ ఇది చాలా పెద్దదిగా ఉన్న కారణంగా ఇక్కడ ప్రదర్శించడం సాధ్యం కాదు. మీ పరికరంలో ఉన్న ఇటీవల Wi-Fi సమస్యలకు ప్రతిస్పందనగా ఈ ఫైల్‌లు రూపొందించబడ్డాయి మరియు ఈ సమస్యలను పరిష్కరించడంలో సహాయపడటం కోసం ఇవి Intelతో షేర్ చేయబడతాయి.&gt;</translation>
<translation id="469230890969474295">OEM ఫోల్డర్</translation>
<translation id="4692623383562244444">శోధన ఇంజిన్‌లు</translation>
-<translation id="4694024090038830733">ప్రింటర్ కాన్ఫిగరేషన్‌ని నిర్వాహకుడు నిర్వహిస్తారు.</translation>
+<translation id="4694024090038830733">ప్రింటర్ కాన్ఫిగరేషన్‌ను నిర్వాహకుడు నిర్వహిస్తారు.</translation>
<translation id="4697551882387947560">బ్రౌజింగ్ సెషన్ ముగిసినప్పుడు</translation>
<translation id="4699172675775169585">కాష్ చేసిన చిత్రాలు మరియు ఫైల్‌లు</translation>
<translation id="4699357559218762027">(స్వయంచాలకంగా ప్రారంభించబడింది)</translation>
@@ -2440,13 +2443,13 @@
<translation id="4735803855089279419">ఈ పరికర ఐడెంటిఫైయర్‌లను గుర్తించడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="4736292055110123391">మీ బుక్‌మార్క్‌లు, పాస్‌వర్డ్‌‌లు, చరిత్ర మరియు మరిన్నింటిని మీ అన్ని పరికరాల్లోనూ సింక్ చేయండి</translation>
<translation id="4737715515457435632">దయచేసి నెట్‌వర్క్‌కు కనెక్ట్ చేయండి</translation>
-<translation id="473775607612524610">అప్‌డేట్</translation>
+<translation id="473775607612524610">అప్‌డేట్‌</translation>
<translation id="4739098340603978916">పరిమాణం: <ph name="APP_SIZE" /></translation>
<translation id="4742746985488890273">అరకు పిన్ చేయండి</translation>
<translation id="4743260470722568160"><ph name="BEGIN_LINK" />అప్లికేషన్‌లను ఎలా అప్‌డేట్ చేయాలో తెలుసుకోండి<ph name="END_LINK" /></translation>
<translation id="4744981231093950366">{NUM_TABS,plural, =1{సైట్‌ను అన్‌మ్యూట్ చేయి}other{సైట్‌లను అన్‌మ్యూట్ చేయి}}</translation>
<translation id="4746351372139058112">సందేశాలు</translation>
-<translation id="4746971725921104503">మీరు ఇప్పటికే ఆ పేరు ద్వారా వినియోగదారుని నిర్వహిస్తున్నట్లు కనిపిస్తోంది. మీరు <ph name="LINK_START" />ఈ ప‌రిక‌రంలోకి <ph name="USER_DISPLAY_NAME" />ను దిగుమతి చేయాలనుకుంటున్నారా<ph name="LINK_END" />?</translation>
+<translation id="4746971725921104503">మీరు ఇప్పటికే ఆ పేరు ద్వారా వినియోగదారును నిర్వహిస్తున్నట్లు కనిపిస్తోంది. మీరు <ph name="LINK_START" />ఈ పరికరానికి <ph name="USER_DISPLAY_NAME" />ని దిగుమతి చేయాలనుకుంటున్నారా<ph name="LINK_END" />?</translation>
<translation id="4748762018725435655">Chrome వెబ్ స్టోర్‌ నుండి ఎక్సటెన్షన్ అవసరం</translation>
<translation id="4750394297954878236">సూచనలు</translation>
<translation id="475088594373173692">మొదటి వినియోగదారు</translation>
@@ -2488,17 +2491,18 @@
<translation id="4821935166599369261">&amp;ప్రొఫైలింగ్ అనుమతించబడింది</translation>
<translation id="4823484602432206655">వినియోగదారు మరియు పరికర సెట్టింగ్‌లను చదవడానికి మరియు మార్చడానికి అనుమతి</translation>
<translation id="4823651846660089135">పరికరం చదవడానికి మాత్రమే</translation>
+<translation id="4824958205181053313">సింక్‌ను రద్దు చేయాలా?</translation>
<translation id="4827675678516992122">కనెక్ట్ చేయడం సాధ్యపడలేదు</translation>
<translation id="4828937774870308359">ఆస్ట్రేలియన్</translation>
<translation id="4829768588131278040">PINని సెటప్ చేయి</translation>
-<translation id="4830502475412647084">OS అప్‌డేట్‌ ఇన్‌స్టాల్ చేయబడుతోంది</translation>
+<translation id="4830502475412647084">OS అప్‌డేట్‌ ఇన్‌స్టాల్ చేయబడుతుంది</translation>
<translation id="4830573902900904548"><ph name="NETWORK_NAME" />ను ఉపయోగించి మీ <ph name="DEVICE_TYPE" /> ఇంటర్నెట్‌కి కనెక్ట్ చేయలేకపోయింది. దయచేసి మరో నెట్‌వర్క్‌ను ఎంచుకోండి. <ph name="LEARN_MORE_LINK_START" />మరింత తెలుసుకోండి<ph name="LEARN_MORE_LINK_END" /></translation>
<translation id="4835385943915508971">Chrome అభ్యర్థించిన వనరుకు యాక్సెస్ కలిగి లేదు.</translation>
<translation id="4835836146030131423">సైన్ ఇన్ చేయడంలో ఎర్రర్.</translation>
<translation id="4837926214103741331">ఈ పరికరాన్ని ఉపయోగించడానికి మీకు అధికారం లేదు. దయచేసి సైన్-ఇన్ అనుమతి కోసం పరికర యజమానిని సంప్రదించండి.</translation>
<translation id="4837952862063191349">మీ స్థానిక డేటాను అన్‌లాక్ చేసి పునరుద్ధరించడానికి, దయచేసి మీ పాత <ph name="DEVICE_TYPE" /> పాస్‌వర్డ్‌ను నమోదు చేయండి.</translation>
<translation id="4838836835474292213">క్లిప్‌బోర్డ్‌ను చదివే యాక్సెస్ అనుమతించబడింది</translation>
-<translation id="4839303808932127586">వీడియోను ఇలా సే&amp;వ్ చెయ్యి...</translation>
+<translation id="4839303808932127586">వీడియోను ఇలా సే&amp;వ్ చేయి...</translation>
<translation id="4839847978919684242"><ph name="SELCTED_FILES_COUNT" /> అంశాలు ఎంచుకోబడ్డాయి</translation>
<translation id="4840150926623932060">{NUM_DOWNLOAD,plural, =1{మరో 1}other{మరో #}}</translation>
<translation id="4842976633412754305">ప్రామాణీకరించని మూలాల నుండి స్క్రిప్ట్‌లను లోడ్ చేయడానికి, ఈ పేజీ ప్రయత్నిస్తోంది.</translation>
@@ -2526,7 +2530,7 @@
<translation id="4871370605780490696">బుక్‌మార్క్‌ను జోడించండి</translation>
<translation id="4873265419374180291"><ph name="NUMBER_OF_BYTES" /> బైట్‌లు</translation>
<translation id="4873312501243535625">మీడియా ఫైల్ చెక్కర్</translation>
-<translation id="4876273079589074638">క్రాష్ ఎందుకు జరిగిందన్నది తెలుసుకోవడానికి, పరిష్కరించడానికి మా ఇంజినీర్‌లకు సహాయం చేయండి. మీకు సాధ్యమైతే విషయాన్ని క్రమ పద్ధతిలో దశల వారీగా పేర్కొనండి. వివరణ ఏదీ మరీ చిన్నగా ఉండకూడదు!</translation>
+<translation id="4876273079589074638">క్రాష్ ఎందుకు జరిగిందన్నది తెలుసుకోవడానికి మరియు పరిష్కరించడానికి మా ఇంజినీర్‌లకు సహాయం చేయండి. మీకు సాధ్యమైతే విషయాన్ని క్రమ పద్ధతిలో దశల వారీగా పేర్కొనండి. వివరణ ఏదీ మరీ చిన్నగా ఉండకూడదు!</translation>
<translation id="4876895919560854374">స్క్రీన్‌ను లాక్ చేయండి మరియు అన్‌లాక్ చేయండి</translation>
<translation id="4877276003880815204">మూలకాలను పర్యవేక్షించు</translation>
<translation id="4879491255372875719">ఆటోమేటిక్ (డిఫాల్ట్)</translation>
@@ -2550,18 +2554,18 @@
<translation id="4891089016822695758">బీటా ఫోరమ్</translation>
<translation id="4892823793812813456">లేబుల్‌లు ఇవ్వు</translation>
<translation id="4892969127351273348"><ph name="APP_NAME" />తో తెరవడం సాధ్యపడలేదు</translation>
-<translation id="4893336867552636863">దీని వలన మీ బ్రౌజింగ్ డేటా ఈ పరికరం నుండి శాశ్వతంగా తొలగించబడుతుంది.</translation>
+<translation id="4893336867552636863">దీని వ‌ల్ల‌ మీ బ్రౌజింగ్ డేటా ఈ పరికరం నుండి శాశ్వతంగా తొలగించబడుతుంది.</translation>
<translation id="4893522937062257019">లాక్ స్క్రీన్‌పై</translation>
<translation id="4898011734382862273">ప్రమాణపత్రం "<ph name="CERTIFICATE_NAME" />" ప్రమాణపత్రాలను మంజూరు చేసే సంస్థను సూచిస్తోంది</translation>
<translation id="489985760463306091">హానికరమైన సాఫ్ట్‌వేర్ తొలగింపును పూర్తి చేసేందుకు, మీ కంప్యూటర్‌ను పునఃప్రారంభించాలి</translation>
<translation id="4900392736118574277">మా ప్రారంభ పేజీ <ph name="URL" />కి మార్చబడింది.</translation>
-<translation id="490074449735753175">అక్షరక్రమ లోపాలను పరిష్కరించడానికి సహాయం కోసం వెబ్ సేవను ఉపయోగించండి</translation>
+<translation id="490074449735753175">అక్షరక్రమ ఎర్రర్‌లను పరిష్కరించడంలో సహాయం కోసం వెబ్ సేవను ఉపయోగించండి</translation>
<translation id="49027928311173603">సర్వర్ నుండి డౌన్‌లోడ్ చేయబడిన విధానం చెల్లదు: <ph name="VALIDATION_ERROR" />.</translation>
<translation id="4905417359854579806"><ph name="FILE_COUNT" /> వాటిని బ్యాకప్ చేయడానికి సిద్ధంగా ఉంది</translation>
<translation id="4907161631261076876">ఈ ఫైల్ సాధారణ పద్ధతిలో డౌన్‌లోడ్ కాలేదు, ఇది అపాయకరమైనది కావచ్చు.</translation>
<translation id="4907306957610201395">అనుమతి వర్గం</translation>
<translation id="4908811072292128752">ఒకేసారి రెండు సైట్‌లను బ్రౌజ్ చేయడానికి కొత్త ట్యాబ్‌ను తెరవండి</translation>
-<translation id="4909038193460299775">ఈ ఖాతా <ph name="DOMAIN" /> నిర్వహణలో ఉన్నందున, మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లు ఈ పరికరం నుండి తీసివేయబడతాయి. అయితే, మీ డేటా మీ Google ఖాతాలో అలాగే నిల్వ చేయబడి ఉంటుంది. <ph name="BEGIN_LINK" />Google డాష్‌బోర్డ్<ph name="END_LINK" />లో నిర్వహించవచ్చు.</translation>
+<translation id="4909038193460299775">ఈ ఖాతా <ph name="DOMAIN" /> నిర్వహణలో ఉన్నందున, మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లు ఈ పరికరం నుండి తీసివేయబడతాయి. అయితే, మీ డేటా మీ Google ఖాతాలో అలాగే నిల్వ చేయబడి ఉంటుంది, దానిని <ph name="BEGIN_LINK" />Google డాష్‌బోర్డ్<ph name="END_LINK" />లో నిర్వహించవచ్చు.</translation>
<translation id="4909359680501173791">మీరు విజయవంతంగా నమోదు చేసుకున్నారు</translation>
<translation id="4912643508233590958">ఇన్‌యాక్టివ్‌ మేల్కొలుపులు</translation>
<translation id="491691592645955587">సురక్షితమైన బ్రౌజర్‌కు మారండి</translation>
@@ -2574,9 +2578,9 @@
<translation id="4923279099980110923">అవును, నేను సహాయం అందించాలనుకుంటున్నాను</translation>
<translation id="4924352752174756392">12x</translation>
<translation id="4924638091161556692">స్థిరపరచబడింది</translation>
-<translation id="4925542575807923399">బహుళ సైన్-ఇన్ సెషన్‌లో ఈ ఖాతాను మొదట సైన్-ఇన్ చేయాల్సిందిగా నిర్వాహకులు నిర్దేశించారు.</translation>
+<translation id="4925542575807923399">బహుళ సైన్-ఇన్ సెషన్‌లో ఈ ఖాతా మొదటిగా సైన్-ఇన్ చేసిన ఖాతాగా ఉండటం ఈ ఖాతా నిర్వాహకులకు అవసరం.</translation>
<translation id="4927753642311223124">ఇక్కడ చూడటానికి ఏమీ లేదు, కొనసాగండి.</translation>
-<translation id="4927846293686536410">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లను మీ అన్ని పరికరాల్లో పొందడానికి సైన్ ఇన్ చేయండి. మీరు మీ Google సేవలకు కూడా స్వయంచాలకంగా సైన్ ఇన్ చేయబడతారు.</translation>
+<translation id="4927846293686536410">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లను మీ అన్ని పరికరాలలో పొందడానికి సైన్ ఇన్ చేయండి. మీరు మీ Google సేవలకు కూడా ఆటోమేటిక్‌గా సైన్ ఇన్ చేయబడతారు.</translation>
<translation id="4929386379796360314">ముద్రణ గమ్యస్థానాలు</translation>
<translation id="4931132176527519925">ఎల్లప్పుడూ మిర్రరింగ్‌ను ఉపయోగించు</translation>
<translation id="4933484234309072027"><ph name="URL" />లో పొందుపరచబడింది</translation>
@@ -2595,7 +2599,7 @@
<translation id="4960294539892203357"><ph name="WINDOW_TITLE" /> - <ph name="PROFILE_NAME" /></translation>
<translation id="4964455510556214366">అమరిక</translation>
<translation id="4964673849688379040">తనిఖీ చేస్తోంది...</translation>
-<translation id="4965808351167763748">మీరు Hangouts సమావేశాన్ని అమలు చేయడానికి ఈ పరికరాన్ని ఖచ్చితంగా సెటప్ చేయాలనుకుంటున్నారా?</translation>
+<translation id="4965808351167763748">Hangouts Meetను అమలు చేసేలా ఈ పరికరాన్ని ఖచ్చితంగా సెటప్ చేయాలని అనుకుంటున్నారా?</translation>
<translation id="496888482094675990">ఫైల్‌ల యాప్ మీరు Google డిస్క్, బాహ్య నిల్వ లేదా మీ Chrome OS పరికరంలో సేవ్ చేసిన ఫైల్‌లకు శీఘ్ర యాక్సెస్‌ను అందిస్తుంది.</translation>
<translation id="4969785127455456148">ఆల్బమ్</translation>
<translation id="4971412780836297815">పూర్తవగానే తెరువు</translation>
@@ -2609,12 +2613,12 @@
<translation id="4977942889532008999">యాక్సెస్‌ను నిర్ధారించండి</translation>
<translation id="4980805016576257426">ఈ ఎక్స్‌టెన్షన్‌లో మాల్వేర్ ఉంది.</translation>
<translation id="4981449534399733132">మీ అన్ని సమకాలీకరించబడుతున్న పరికరాలతో సహా, మీ Google ఖాతా నుండి బ్రౌజింగ్ డేటాను తీసివేయడానికి, <ph name="BEGIN_LINK" />సైన్ ఇన్ చేయండి<ph name="END_LINK" />.</translation>
-<translation id="498294082491145744">కుక్కీలు, జావాస్క్రిప్ట్, ప్లగిన్‌లు, భౌగోళిక స్థానం, మైక్రోఫోన్, కెమెరా మొదలైన ఫీచర్‌లకు వెబ్‌సైట్‌ల యాక్సెస్‌ను నియంత్రించే మీ సెట్టింగ్‌లను మార్చండి.</translation>
+<translation id="498294082491145744">కుక్కీలు, జావాస్క్రిప్ట్, ప్లగిన్‌లు, భౌగోళిక స్థానం, మైక్రోఫోన్, కెమెరా మొదలైన ఫీచ‌ర్‌లకు వెబ్‌సైట్‌ల యాక్సెస్‌ను నియంత్రించే మీ సెట్టింగ్‌లను మార్చండి.</translation>
<translation id="4988205478593450158">మీరు ఖచ్చితంగా "<ph name="FILE_NAME" />"ని తొలగించాలనుకుంటున్నారా?</translation>
<translation id="4988526792673242964">పేజీలు</translation>
<translation id="49896407730300355">అ&amp;పసవ్యదిశలో తిప్పు</translation>
<translation id="4989966318180235467">&amp;నేపథ్య పేజీని పర్యవేక్షించు</translation>
-<translation id="4990343175649730969">Chrome క్లీన్‌అప్ సాధనాన్ని డౌన్‌లోడ్ చేయి</translation>
+<translation id="4990343175649730969">Chrome క్లీన‌ప్‌ సాధనాన్ని డౌన్‌లోడ్ చేయి</translation>
<translation id="4991420928586866460">ఎగువ-అడ్డు వరుస కీలను ఫంక్షన్ కీల వలె పరిగణించు</translation>
<translation id="499165176004408815">అధిక కాంట్రాస్ట్ మోడ్‌ను ఉపయోగించు</translation>
<translation id="4992066212339426712">అన్‌మ్యూట్ చేయి</translation>
@@ -2641,7 +2645,7 @@
<translation id="5029568752722684782">కాపీని తీసివేయి</translation>
<translation id="5030338702439866405">వీరిచే జారీచేయబడింది</translation>
<translation id="503498442187459473"><ph name="HOST" /> మీ కెమెరాను మరియు మైక్రోఫోన్‌ను ఉపయోగించాలనుకుంటోంది</translation>
-<translation id="5036662165765606524">బహుళ ఫైల్‌లను స్వయంచాలకంగా డౌన్‌లోడ్ చేయడానికి ఏ సైట్‌ను అనుమతించవద్దు</translation>
+<translation id="5036662165765606524">బహుళ ఫైల్‌లను ఆటోమేటిక్‌గా డౌన్‌లోడ్ చేయడానికి ఏ సైట్‌ను అనుమతించవద్దు</translation>
<translation id="5037676449506322593">అన్నీ ఎంచుకోండి</translation>
<translation id="5038625366300922036">మరింత చూడండి...</translation>
<translation id="5038863510258510803">ప్రారంభిస్తోంది...</translation>
@@ -2718,8 +2722,8 @@
<translation id="5158983316805876233">అన్ని ప్రోటోకాల్‌ల కోసం అదే ప్రాక్సీని ఉపయోగించండి</translation>
<translation id="5159383109919732130"><ph name="BEGIN_BOLD" />మీ పరికరాన్ని వెంటనే తీసివేయవద్దు!<ph name="END_BOLD" />
<ph name="LINE_BREAKS" />
- మీ పరికరం ఉపయోగంలో ఉన్నప్పుడు తీసివేస్తే డేటా నష్టం కలగవచ్చు. దయచేసి చర్య పూర్తయ్యే వరకు వేచి ఉండి ఆపై ఫైల్స్ యాప్‌ను ఉపయోగించి పరికరాన్ని తీసివేయండి.</translation>
-<translation id="5160857336552977725">మీ <ph name="DEVICE_TYPE" />కి సైన్ ఇన్ చేయండి</translation>
+ మీ పరికరం వినియోగంలో ఉన్నప్పుడు తీసివేస్తే డేటా నష్టం కలగవచ్చు. దయచేసి చర్య పూర్తయ్యే వరకు వేచి ఉండి ఆపై 'ఫైల్‌లు' యాప్‌ను ఉపయోగించి పరికరాన్ని తీసివేయండి.</translation>
+<translation id="5160857336552977725">మీ <ph name="DEVICE_TYPE" />కు సైన్ ఇన్ చేయండి</translation>
<translation id="5163869187418756376">షేర్ చేయడం విఫలమైంది. మీ కనెక్షన్‌ను తనిఖీ చేసి, తర్వాత మళ్లీ ప్రయత్నించండి.</translation>
<translation id="5166596762332123936">గడువు తేదీ ముగిసినందున <ph name="PLUGIN_NAME" /> బ్లాక్ చేయబడింది</translation>
<translation id="5170477580121653719">Google డిస్క్‌లో మిగిలి ఉన్న ఖాళీ: <ph name="SPACE_AVAILABLE" />.</translation>
@@ -2734,8 +2738,8 @@
<translation id="5179127818058486126">{NUM_TABS,plural, =1{ట్యాబ్‌ని అన్‌మ్యూట్ చేయి}other{ట్యాబ్‌లను అన్‌మ్యూట్ చేయి}}</translation>
<translation id="5181140330217080051">డౌన్‌లోడ్ చేస్తోంది</translation>
<translation id="5184063094292164363">&amp;JavaScript కన్సోల్</translation>
-<translation id="5184662919967270437">మీ పరికరాన్ని నవీకరిస్తోంది</translation>
-<translation id="5185386675596372454">"<ph name="EXTENSION_NAME" />"యొక్క క్రొత్త సంస్కరణ ఆపివెయ్యబడింది ఎందుకంటే దానికి మరిన్ని అనుమతులు అవసరం.</translation>
+<translation id="5184662919967270437">మీ పరికరాన్ని అప్‌డేట్ చేస్తోంది</translation>
+<translation id="5185386675596372454">"<ph name="EXTENSION_NAME" />" కొత్త వెర్షన్ నిలిపివేయబడింది ఎందుకంటే దానికి మరిన్ని అనుమతులు అవసరం.</translation>
<translation id="5187295959347858724"><ph name="SHORT_PRODUCT_NAME" />కు మీరు ఇప్పుడు సైన్‌ఇన్ చేశారు. మీ బుక్‌మార్క్‌లు, చరిత్ర, మరియు ఇతర సెట్టింగ్‌లు మీ Google ఖాతాకు సమకాలీకరించబడుతున్నాయి.</translation>
<translation id="5187826826541650604"><ph name="KEY_NAME" /> (<ph name="DEVICE" />)</translation>
<translation id="5187892128515678283">టోగుల్ ఆన్ చేయడం ద్వారా USB పరికరాన్ని Linuxతో షేర్ చేయండి. పరికరాన్ని డిటాచ్ చేసే వరకు మాత్రమే షేరింగ్ కొనసాగుతుంది.</translation>
@@ -2743,7 +2747,7 @@
<translation id="5204673965307125349">దయచేసి పరికరాన్ని పవర్‌వాష్ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="5204967432542742771">పాస్‌వర్డ్‌ని నమోదు చేయండి</translation>
<translation id="5206215183583316675">"<ph name="CERTIFICATE_NAME" />"ని తొలగించాలా?</translation>
-<translation id="520621735928254154">సర్టిఫికెట్ దిగుమతి ఎర్రర్</translation>
+<translation id="520621735928254154">ప్రమాణపత్ర దిగుమతి లోపం</translation>
<translation id="5209320130288484488">పరికరాలు కనుగొనబడలేదు</translation>
<translation id="5209518306177824490">SHA-1 వేలిముద్ర</translation>
<translation id="5213481667492808996">మీ '<ph name="NAME" />' డేటా సేవ ఉపయోగించడానికి సిద్ధంగా ఉంది</translation>
@@ -2783,14 +2787,14 @@
<translation id="5256861893479663409">అన్ని సైట్‌లలో</translation>
<translation id="5260508466980570042">క్షమించండి, మీ ఇమెయిల్ లేదా పాస్‌వర్డ్ ధృవీకరించబడలేదు. దయచేసి మళ్ళీ ప్రయత్నించండి.</translation>
<translation id="5261683757250193089">వెబ్ స్టోర్‌లో తెరవండి</translation>
-<translation id="5262311848634918433"><ph name="MARKUP_1" />ఫైల్‌లను ఎక్కడి నుండైనా యాక్సెస్ చేయండి, ఆఫ్‌లైన్‌లో ఉన్నప్పటికీ యాక్సెస్ చేయగలరు.<ph name="MARKUP_2" />
- Google డిస్క్‌లోని ఫైల్‌లు నవీకృతంగా ఉంటాయి మరియు ఏ పరికరం నుండి అయినా అందుబాటులో ఉంటాయి.<ph name="MARKUP_3" />
+<translation id="5262311848634918433"><ph name="MARKUP_1" />ఫైల్‌లను ఎక్కడి నుండైనా యాక్సెస్ చేయండి, ఆఫ్‌లైన్‌లో ఉన్నా కూడా.<ph name="MARKUP_2" />
+ Google డిస్క్‌లోని ఫైల్‌లు అప్‌డేట్ చేయబడి ఉంటాయి, ఇవి ఏ పరికరం నుండైనా అందుబాటులో ఉంటాయి.<ph name="MARKUP_3" />
<ph name="MARKUP_4" />మీ ఫైల్‌లను సురక్షితంగా ఉంచుకోండి.<ph name="MARKUP_5" />
మీ పరికరానికి ఏ విధమైన ఆపద సంభవించినా ఫర్వాలేదు, మీ ఫైల్‌లు Google డిస్క్‌లో సురక్షితంగా నిల్వ చేయబడి ఉంటాయి.<ph name="MARKUP_6" />
- అన్ని ఫైల్‌లు ఒకే చోట ఉంటాయి, కనుక <ph name="MARKUP_7" />షేర్ చేయండి, సృష్టించండి
- మరియు వాటిపై ఇతరులతో కలిసి పని చేయండి<ph name="MARKUP_8" />.<ph name="MARKUP_9" /></translation>
+ అన్ని ఫైల్‌లు ఒకే చోట ఉంటాయి, కాబట్టి <ph name="MARKUP_7" />షేర్ చేయండి, సృష్టించండి,
+ వాటిపై ఇతరులతో కలిసి పని చేయండి<ph name="MARKUP_8" />.<ph name="MARKUP_9" /></translation>
<translation id="5264148714798105376">ఇది ఇంచుమించు ఒక నిమిషంలో పూర్తి కావచ్చు.</translation>
-<translation id="5264252276333215551">దయచేసి మీ యాప్‌ను కియోస్క్ మోడ్‌లో లాంఛ్‌ చేయడానికి ఇంటర్నెట్‌కు కనెక్ట్ చేయండి.</translation>
+<translation id="5264252276333215551">మీ యాప్‌ను కియోస్క్ మోడ్‌లో ప్రారంభించడానికి దయచేసి ఇంటర్నెట్‌కు కనెక్ట్ చేయండి.</translation>
<translation id="5265562206369321422">వారానికి పైగా ఆఫ్‌లైన్‌లో ఉంది</translation>
<translation id="5265797726250773323">ఇన్‌స్టాల్ చేయడంలో ఎర్రర్</translation>
<translation id="5266113311903163739">సర్టిఫికెట్ అధికారి దిగుమతి ఎర్రర్</translation>
@@ -2802,8 +2806,8 @@
<translation id="527605982717517565"><ph name="HOST" />పై ఎల్లప్పుడూ JavaScriptను అనుమతించు</translation>
<translation id="5280174558369304332">తీసివేయాల్సిన ఎక్స్‌టెన్షన్‌లు:</translation>
<translation id="5280426389926346830">షార్ట్‌కట్‌ను సృష్టించాలా?</translation>
-<translation id="528208740344463258">Android యాప్‌లను డౌన్‌లోడ్ చేసి, ఉపయోగించడం కోసం, ముందుగా మీరు ఈ అవసరమైన అప్‌డేట్‌ని ఇన్‌స్టాల్ చేయాలి. మీ <ph name="DEVICE_TYPE" /> అప్‌డేట్ అవుతున్న సమయంలో, మీరు దీనిని ఉపయోగించలేరు. ఇన్‌స్టాల్ చేయడం పూర్తయిన తర్వాత, మీ <ph name="DEVICE_TYPE" /> పునఃప్రారంభించబడుతుంది.</translation>
-<translation id="5282733140964383898">"ట్రాక్ చేయవద్దు"ను ప్రారంభించడం వలన మీ బ్రౌజింగ్ ట్రాఫిక్‌తో ఒక అభ్యర్థన చేర్చబడుతుంది. ఈ అభ్యర్థనకు వెబ్‌సైట్ ప్రతిస్పందించిందా లేదా మరియు అభ్యర్థన ఎలా పరిగణించబడింది అనే వాటిపై ఈ ఫీచర్ ప్రభావం ఆధారపడి ఉంటుంది. ఉదాహరణకు, కొన్ని వెబ్‌సైట్‌లు ఈ అభ్యర్థనకు ప్రతిస్పందనగా మీరు సందర్శించిన ఇతర వెబ్‌సైట్‌ల ఆధారంగా కాకుండా ఇతర ప్రకటనలను మీకు చూపుతాయి. అనేక వెబ్‌సైట్‌లు ఇప్పటికీ మీ బ్రౌజింగ్ డేటాను సేకరించి ఉపయోగిస్తాయి - ఉదాహరణకు భద్రతను మెరుగుపరిచేందుకు, వారి వెబ్‌సైట్‌లలో కంటెంట్, సేవలు, ప్రకటనలు మరియు సిఫార్సులను అందించేందుకు మరియు నివేదన గణాంకాలను రూపొందించేందుకు ఆ డేటాను ఉపయోగిస్తాయి. <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation>
+<translation id="528208740344463258">Android యాప్‌లను డౌన్‌లోడ్ చేసి, ఉపయోగించడం కోసం, ముందుగా మీరు ఈ అవసరమైన అప్‌డేట్‌ను ఇన్‌స్టాల్ చేయాలి. మీ <ph name="DEVICE_TYPE" /> అప్‌డేట్ అవుతున్న సమయంలో, మీరు దీనిని ఉపయోగించలేరు. ఇన్‌స్టాల్ చేయడం పూర్తయిన తర్వాత, మీ <ph name="DEVICE_TYPE" /> పునఃప్రారంభించబడుతుంది.</translation>
+<translation id="5282733140964383898">"ట్రాక్ చేయవద్దు" ప్రారంభించడం వ‌ల్ల‌ మీ బ్రౌజింగ్ ట్రాఫిక్‌తో ఒక అభ్యర్థన చేర్చబడుతుంది. ఏదైనా అభ్యర్థనకు వెబ్‌సైట్ ప్రతిస్పందించిందా? లేదా? మరియు అభ్యర్థన ఎలా ప‌రిగ‌ణించ‌బ‌డింది? అనే వాటిపై ప్రభావం ఆధారపడి ఉంటుంది. ఉదాహరణకు, కొన్ని వెబ్‌సైట్‌లు ఈ అభ్యర్థనకు ప్రతిస్పందనగా మీరు సందర్శించిన ఇతర వెబ్‌సైట్‌ల ఆధారంగా కాకుండా ఇతర ప్రకటనలను మీకు చూపుతాయి. అనేక వెబ్‌సైట్‌లు అప్పటికీ మీ బ్రౌజింగ్ డేటాను సేకరించి ఉపయోగిస్తాయి - ఉదాహరణకు భద్రతను మెరుగుపరిచే, వారి వెబ్‌సైట్‌ల్లో కంటెంట్, సేవలు, ప్రకటనలు మరియు సిఫార్సులను అందించే మరియు నివేదన గణాంకాలను రూపొందించే ఉద్దేశాలతో ఆ డేటాను ఉపయోగిస్తాయి. <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation>
<translation id="5283677936944177147">అయ్యో! పరికర మోడల్ లేదా క్రమ సంఖ్యను గుర్తించడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="5284445933715251131">డౌన్‌లోడ్‌ చేయడాన్ని కొనసాగించు</translation>
<translation id="5285635972691565180">ప్రదర్శన <ph name="DISPLAY_ID" /></translation>
@@ -2835,15 +2839,15 @@
<translation id="5324780743567488672">మీ స్థానాన్ని ఉపయోగించి సమయ మండలిని స్వయంచాలకంగా సెట్ చేయండి</translation>
<translation id="5327248766486351172">పేరు</translation>
<translation id="5327570636534774768">ఈ పరికరం వేరొక డొమైన్ ద్వారా నిర్వహణ కోసం గుర్తించబడింది. డెమో మోడ్‌ని సెటప్ చేయడం కంటే ముందు ఆ డొమైన్ నుండి దీని కేటాయింపు తీసివేయండి.</translation>
-<translation id="532943162177641444">ఈ పరికరం ఉపయోగించగల విధంగా మొబైల్ హాట్‌స్పాట్‌ను సెటప్ చేయడం కోసం మీ <ph name="PHONE_NAME" />లో నోటిఫికేషన్‌ని నొక్కండి.</translation>
+<translation id="532943162177641444">ఈ పరికరం ఉపయోగించగల విధంగా మొబైల్ హాట్‌స్పాట్‌ను సెటప్ చేయడానికి, మీ <ph name="PHONE_NAME" />లోని నోటిఫికేషన్‌ను నొక్కండి.</translation>
<translation id="5329858601952122676">&amp;తొలగించు</translation>
-<translation id="5330145655348521461">ఈ ఫైల్‌లు వేరే డెస్క్‌టాప్‌లో తెరవబడ్డాయి. దీన్ని వీక్షించడానికి <ph name="USER_NAME" /> (<ph name="MAIL_ADDRESS" />)కి తరలించండి.</translation>
+<translation id="5330145655348521461">ఈ ఫైల్స్ వేరే డెస్క్‌టాప్‌లో తెరవబడ్డాయి. దీన్ని వీక్షించడానికి <ph name="USER_NAME" /> (<ph name="MAIL_ADDRESS" />)కు తరలించండి.</translation>
<translation id="5330512191124428349">సమాచారం పొందండి</translation>
<translation id="5331069282670671859">ఈ వర్గంలో మీకు ప్రమాణపత్రాలు ఏవీ లేవు</translation>
<translation id="5331425616433531170">"<ph name="CHROME_EXTENSION_NAME" />" దీనితో జత చేయాలనుకుంటోంది</translation>
<translation id="5331975486040154427">USB-C పరికరం (ఎడమవైపు వెనుక పోర్ట్)</translation>
<translation id="5332624210073556029">టైమ్ జోన్:</translation>
-<translation id="5334142896108694079">స్క్రిప్ట్ కాష్</translation>
+<translation id="5334142896108694079">స్క్రిప్ట్ క్యాష్</translation>
<translation id="5335458522276292100"><ph name="FILE_COUNT" /> వాటిని <ph name="BEGIN_LINK" />Google డిస్క్<ph name="END_LINK" />కు బ్యాకప్ చేస్తోంది</translation>
<translation id="5336126339807372270">USB పరికరాలను యాక్సెస్ చేయడానికి ఏ సైట్‌లను అనుమతించవద్దు</translation>
<translation id="5337771866151525739">మూడవ పక్షం ద్వారా ఇన్‌స్టాల్ చేయబడింది.</translation>
@@ -2864,19 +2868,20 @@
<translation id="5367091008316207019">ఫైల్‌ను చదువుతోంది..</translation>
<translation id="5368191757080475556">Linuxతో ఫోల్డర్‌ను షేర్ చేయండి</translation>
<translation id="5368720394188453070">మీ ఫోన్ లాక్ చేయబడింది. దానిని తెరవడానికి, అన్‌లాక్ చేయండి.</translation>
-<translation id="5368779022775404937"><ph name="REALM" />కి సైన్ ఇన్ చేయండి</translation>
+<translation id="5368779022775404937"><ph name="REALM" />కు సైన్ ఇన్ చేయండి</translation>
<translation id="5370819323174483825">&amp;మళ్లీ లోడ్ చేయి</translation>
-<translation id="5372529912055771682">సరఫరా చేయబడిన నమోదు మోడ్‌కు ఆపరేటింగ్ సిస్టమ్ యొక్క ఈ వెర్ష‌న్‌ ద్వారా మద్దతు లేదు. దయచేసి మీరు తాజా వెర్ష‌న్‌ను అమలు చేస్తున్నారని నిర్ధారించుకోండి. మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="5372529912055771682">సరఫరా చేయబడిన నమోదు మోడ్‌ను, ఆపరేటింగ్ సిస్టమ్ యొక్క ఈ వెర్షన్ మద్దతివ్వదు. మీరు తాజా వెర్షన్‌ను అమలు చేస్తున్నారని దయచేసి నిర్ధారించుకుని, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="5374359983950678924">చిత్రాన్ని మార్చు</translation>
<translation id="5376169624176189338">వెనుకకు వెళ్ల‌డానికి క్లిక్ చేయండి. చరిత్రను చూడటానికి నొక్కి ఉంచండి</translation>
<translation id="5376931455988532197">ఫైల్ చాలా పెద్దదిగా ఉంది</translation>
-<translation id="537813040452600081">మీరు ఈ విండోలో వీక్షించే పేజీలు బ్రౌజర్ చరిత్రలో కనిపించవు. మీరు సైన్ అవుట్ చేసిన తర్వాత కంప్యూటర్‌లో అవి కుక్కీల వంటి ఇతర జాడలను వదిలిపెట్టవు. మీరు డౌన్‌లోడ్ చేసే ఫైల్‌లు, సృష్టించే బుక్‌మార్క్‌లు భద్రపరచబడవు.</translation>
+<translation id="5377594097385838788">అజ్ఞాతం</translation>
+<translation id="537813040452600081">మీరు ఈ విండోలో వీక్షించే పేజీలు బ్రౌజర్ చరిత్రలో కనిపించవు. మీరు సైన్ అవుట్ చేసిన తర్వాత కంప్యూటర్‌లో అవి కుక్కీల వంటి ఇతర జాడలను వదిలిపెట్టవు. మీరు డౌన్‌లోడ్ చేసే ఫైల్స్, సృష్టించే బుక్‌మార్క్‌లు భద్రపరచబడవు.</translation>
<translation id="5379140238605961210">మైక్రోఫోన్ యాక్సెస్‌ను బ్లాక్ చేయడాన్ని కొనసాగించు</translation>
<translation id="5379268888377976432">తొలగింపు చర్య రద్దు చేయండి</translation>
<translation id="5382591305415226340">మద్దతు గల లింక్‌లను నిర్వహించండి</translation>
<translation id="5384883051496921101">ఈ సైట్, అజ్ఞాత మోడ్ వెలుపల యాప్‌‌తో సమాచారాన్ని షేర్ చేయబోతోంది.</translation>
<translation id="5388885445722491159">జత చేయబడింది</translation>
-<translation id="5389237414310520250">కొత్త వినియోగదారుని సృష్టించడం సాధ్యపడలేదు. దయచేసి మీ హార్డ్ డ్రైవ్‌కు సంబంధించి నిల్వ మరియు అనుమతులను తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="5389237414310520250">కొత్త వినియోగదారుని సృష్టించడం సాధ్యపడలేదు. దయచేసి మీ హార్డ్ డ్రైవ్ నిల్వ స్థలాన్ని, అనుమతులను తనిఖీ చేసి, ఆపై మళ్లీ ప్రయత్నించండి.</translation>
<translation id="5390100381392048184">ధ్వనిని ప్లే చేయడానికి సైట్‌లను అనుమతించండి</translation>
<translation id="5390284375844109566">సూచికలోని డేటాబేస్</translation>
<translation id="5390743329570580756">దీని కోసం పంపు</translation>
@@ -2891,26 +2896,28 @@
<translation id="5414566801737831689">మీరు సందర్శించే వెబ్‌సైట్‌ల చిహ్నాలను చదవడం</translation>
<translation id="5417312524372586921">బ్రౌజర్ థీమ్‌లు</translation>
<translation id="5419294236999569767">సిస్టమ్ సమయం</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">వచన సందేశం మరియు చిత్రాల స్పష్టతను నిర్ణయిస్తుంది</translation>
<translation id="5422221874247253874">యాక్సెస్ స్థానం</translation>
<translation id="5422781158178868512">క్షమించండి, మీ బాహ్య నిల్వ పరికరం గుర్తించబడలేదు.</translation>
<translation id="5423849171846380976">సక్రియం చెయ్యబడింది</translation>
<translation id="5425042808445046667">డౌన్‌లోడ్‌ చేయడాన్ని కొనసాగించు</translation>
<translation id="5425722269016440406">ఈ సెట్టింగ్ మీ ఫోన్ మరియు ఇతర పరికరాలకు సింక్ చేయబడినందున Smart Lockను ఆఫ్ చేయడానికి మీరు తప్పనిసరిగా ఆన్‌లైన్‌లో ఉండాలి. దయచేసి ముందుగా నెట్‌వర్క్‌కు కనెక్ట్ చేయండి.</translation>
-<translation id="5425863515030416387">పరికరాల్లో సులభంగా సైన్ ఇన్ చేయండి</translation>
+<translation id="5425863515030416387">పరికరాలలో సులభంగా సైన్ ఇన్ చేయండి</translation>
<translation id="5426179911063097041"><ph name="SITE" /> మీకు నోటిఫికేషన్‌లను పంపాలనుకుంటోంది</translation>
<translation id="5427278936122846523">ఎల్లప్పుడూ అనువదించు</translation>
<translation id="5427459444770871191">&amp;సవ్యదిశలో తిప్పు</translation>
<translation id="542872847390508405">మీరు అతిథిగా బ్రౌజ్ చేస్తున్నారు</translation>
-<translation id="5428850089342283580"><ph name="ACCNAME_APP" /> (అప్‌డేట్ అందుబాటులో ఉంది)</translation>
+<translation id="5428850089342283580"><ph name="ACCNAME_APP" /> (అప్‌డేట్‌ అందుబాటులో ఉంది)</translation>
<translation id="5430931332414098647">తక్షణ టెథెరింగ్</translation>
<translation id="5431318178759467895">రంగు</translation>
<translation id="5431825016875453137">OpenVPN / L2TP</translation>
-<translation id="5432996274932278848">మీ పరికరం, యాప్‌లు మరియు వెబ్‌ను వెతకండి. మీ యాప్‌లను నావిగేట్ చేయడానికి బాణం కీలను ఉపయోగించండి.</translation>
+<translation id="5432996274932278848">మీ పరికరాన్ని, యాప్‌ల‌ను, వెబ్‌ను శోధించండి. మీ యాప్‌లను నావిగేట్ చేయడానికి బాణం కీలను ఉపయోగించండి.</translation>
<translation id="543381445212956829">WiMAXని ప్రారంభించు</translation>
<translation id="5434065355175441495">PKCS #1 RSA ఎన్‌క్రిప్షన్</translation>
<translation id="5436492226391861498">ప్రాక్సీ టనెల్ కోసం వేచి ఉంది...</translation>
<translation id="5436510242972373446"><ph name="SITE_NAME" /> వెతుకు:</translation>
+<translation id="543806387003274181">దయచేసి మీ స్థానిక ఫైల్‌లను సేవ్ చేసుకుని, ఇప్పుడే కొత్త ఖాతాని సృష్టించండి.</translation>
<translation id="5438224778284622050">ఆఫ్‌లైన్ ఫైల్‌లను తొలగించాలా?</translation>
<translation id="544083962418256601">సత్వరమార్గాలను సృష్టించు...</translation>
<translation id="5442228125690314719">డిస్క్ ఇమేజ్‌ను సృష్టించడంలో ఎర్రర్ ఏర్పడింది. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
@@ -2924,7 +2931,7 @@
<translation id="5454166040603940656"><ph name="PROVIDER" />తో</translation>
<translation id="5457113250005438886">చెల్లదు</translation>
<translation id="5457459357461771897">మీ కంప్యూటర్‌లోని ఫోటోలు, సంగీతం మరియు ఇతర మీడియాను చదవడం మరియు తొలగించడం</translation>
-<translation id="5457599981699367932">అతిథి వలె బ్రౌజ్ చెయ్యండి</translation>
+<translation id="5457599981699367932">అతిథి లాగా బ్రౌజ్ చేయండి</translation>
<translation id="5458998536542739734">లాక్ స్క్రీన్ గమనికలు</translation>
<translation id="5463275305984126951"><ph name="LOCATION" /> యొక్క సూచిక</translation>
<translation id="5463856536939868464">దాచిపెట్టిన బుక్‌మార్క్‌లు ఉన్న మెను</translation>
@@ -2946,7 +2953,7 @@
<translation id="5493792505296048976">స్క్రీన్ ఆన్‌లో ఉంది</translation>
<translation id="5494362494988149300">&amp;పూర్తవగానే తెరువు</translation>
<translation id="5494920125229734069">అన్నీ ఎంచుకోండి</translation>
-<translation id="5495466433285976480">మీరు తదుపరిసారి పునఃప్రారంభించినప్పుడు ఇది స్థానిక వినియోగదారులు, ఫైల్‌లు, డేటా మరియు ఇతర సెట్టింగ్‌లు మొత్తాన్ని తీసివేస్తుంది. వినియోగదారులందరూ మళ్లీ సైన్ ఇన్ చేయాల్సి ఉంటుంది.</translation>
+<translation id="5495466433285976480">మీరు తర్వాతిసారి పునఃప్రారంభించినప్పుడు ఇది స్థానిక వినియోగదారులు, ఫైల్‌లు, డేటా మరియు ఇతర సెట్టింగ్‌లు మొత్తాన్ని తీసివేస్తుంది. వినియోగదారులందరూ మళ్లీ సైన్ ఇన్ చేయాల్సి ఉంటుంది.</translation>
<translation id="5495597166260341369">ప్రదర్శనను ఆన్‌లో ఉంచండి</translation>
<translation id="5496587651328244253">క్రమంగా పేర్చు</translation>
<translation id="549673810209994709">ఈ పేజీని అనువదించడం సాధ్యపడలేదు.</translation>
@@ -2958,17 +2965,17 @@
<translation id="5511379779384092781">అతి చిన్నది</translation>
<translation id="5511823366942919280">మీరు ఖచ్చితంగా ఈ పరికరాన్ని "షార్క్"గా సెటప్ చేయాలనుకుంటున్నారా?</translation>
<translation id="5512653252560939721">వినియోగదారు సర్టిఫికెట్ ఖచ్చితంగా హార్డ్‌వేర్-బ్యాకెడ్ అయ్యుండాలి.</translation>
-<translation id="5516183516694518900">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌లను మీ అన్ని పరికరాల్లో పొందడానికి మీ Google ఖాతాతో Chromeకు సైన్ ఇన్ చేయండి.</translation>
+<translation id="5516183516694518900">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లను మీ అన్ని పరికరాలలో పొందడానికి మీ Google ఖాతాతో Chromeకు సైన్ ఇన్ చేయండి.</translation>
<translation id="551752069230578406">మీ ఖాతాకు ప్రింటర్‌ను జోడిస్తోంది - దీనికి కొంత సమయం పట్టవచ్చు...</translation>
<translation id="5518219166343146486">క్లిప్‌బోర్డ్‌కు కాపీ చేసిన వచనం మరియు చిత్రాలను సైట్ చూడాలన్నప్పుడు అనుమతి అడగాలి</translation>
-<translation id="5518584115117143805">ఇమెయిల్ ఎన్‌క్రిప్షన్ సర్టిఫికెట్</translation>
+<translation id="5518584115117143805">ఇమెయిల్ గుప్తీకరణ సర్టిఫికెట్</translation>
<translation id="5521078259930077036">మీరు ఆశిస్తున్న హోమ్ పేజీ ఇదేనా?</translation>
<translation id="5522156646677899028">ఈ పొడిగింపు తీవ్రమైన భద్రతా భేద్యతలను కలిగి ఉంది.</translation>
<translation id="5524517123096967210">ఫైల్‌ను చదవడం సాధ్యపడదు.</translation>
<translation id="5525677322972469346">కొత్త పర్యవేక్షించబడే వినియోగదారును సృష్టించండి</translation>
<translation id="5526701598901867718">అన్ని (అసురక్షితం)</translation>
-<translation id="5526745900034778153">సమకాలీకరణను మళ్లీ ప్రారంభించడానికి మళ్లీ సైన్ ఇన్ చేయండి</translation>
-<translation id="5527463195266282916">ఎక్సటెన్షన్‌ను డౌన్‌గ్రేడ్ చేయడానికి ప్రయత్నించబడింది.</translation>
+<translation id="5526745900034778153">సింక్‌ను కొనసాగించడానికి మళ్లీ సైన్ ఇన్ చేయండి</translation>
+<translation id="5527463195266282916">ఎక్స్‌టెన్ష‌న్‌ను డౌన్‌గ్రేడ్ చేయడానికి ప్ర‌య‌త్నం జ‌రిగింది.</translation>
<translation id="5527474464531963247">మీరు మరొక నెట్‌వర్క్‌ను కూడా ఎంచుకోవచ్చు.</translation>
<translation id="5530160549030561969">ప్రతి ఫీచర్ యొక్క సెట్టింగ్‌లను సమీక్షించి, మీకు నచ్చనివి మార్చండి</translation>
<translation id="5530766185686772672">అజ్ఞాత ట్యాబ్‌లను మూసివేయి</translation>
@@ -3000,14 +3007,14 @@
<translation id="5563234215388768762">Googleలో వెతకండి లేదా URLను టైప్ చేయండి</translation>
<translation id="5567950944308676169">మీ భద్రతా కీని ప్లగ్ చేసి, దాన్ని యాక్టివేట్ చేయండి</translation>
<translation id="5567989639534621706">అప్లికేషన్ కాష్‌లు</translation>
-<translation id="5568069709869097550">సైన్ ఇన్ చెయ్యలేరు</translation>
+<translation id="5568069709869097550">సైన్ ఇన్ చేయడం సాధ్యపడలేదు</translation>
<translation id="5568144734023334204">Android నిల్వ</translation>
<translation id="5573248369095789351">కొనసాగింపు చర్య</translation>
<translation id="5575473780076478375">అజ్ఞాత ఎక్స్‌టెన్‌షన్: <ph name="EXTENSION_NAME" /></translation>
<translation id="5575528586625653441">డెమో నమోదు అభ్యర్థనకు సంబంధించి ఒక సమస్య ఏర్పడింది.</translation>
<translation id="557722062034137776">మీ పరికరాన్ని రీసెట్ చేయడం వలన మీ Google ఖాతాలపై లేదా ఈ ఖాతాలకు సమకాలీకరించబడిన ఏదైనా డేటాపై ఎటువంటి ప్రభావం ఉండదు. అయితే, మీ పరికరంలో స్థానికంగా సేవ్ చేయబడిన అన్ని ఫైల్‌లు తొలగించబడతాయి.</translation>
-<translation id="5578059481725149024">స్వీయ సైన్-ఇన్</translation>
-<translation id="558170650521898289">Microsoft Windows Hardware Driver Verification</translation>
+<translation id="5578059481725149024">ఆటోమేటిక్ సైన్-ఇన్</translation>
+<translation id="558170650521898289">Microsoft Windows హార్డ్‌వేర్ డ్రైవర్ ధృవీకరణ</translation>
<translation id="5582839680698949063">ప్రధాన మెను</translation>
<translation id="5583640892426849032">Backspace</translation>
<translation id="5584088138253955452">వినియోగదారు పేరుని సేవ్ చేయాలా?</translation>
@@ -3025,22 +3032,22 @@
<translation id="5595152862129936745">చాలా దూరంగా ఉండాలి</translation>
<translation id="5595485650161345191">చిరునామాను సవరించు</translation>
<translation id="5596627076506792578">మరిన్ని ఎంపికలు</translation>
-<translation id="5600706100022181951"><ph name="UPDATE_SIZE_MB" /> MB మొబైల్ డేటాను ఉపయోగించి అప్‌డేట్ డౌన్‌లోడ్ అవుతుంది. మీరు కొనసాగాలనుకుంటున్నారా?</translation>
+<translation id="5600706100022181951"><ph name="UPDATE_SIZE_MB" /> MB మొబైల్ డేటాను ఉపయోగించి అప్‌డేట్‌ డౌన్‌లోడ్ చేయబడుతుంది. మీరు కొనసాగాలని అనుకుంటున్నారా?</translation>
<translation id="5601503069213153581">PIN</translation>
-<translation id="5602765853043467355">ఈ పరికరం నుండి బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు తదితరమైనవి తీసివేయి</translation>
+<translation id="5602765853043467355">ఈ పరికరం నుండి బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు వంటివాటిని తీసివేయి</translation>
<translation id="5605623530403479164">ఇతర శోధన ఇంజిన్‌లు</translation>
<translation id="5608580678041221894">కత్తిరింపు ప్రాంతాన్ని సర్దుబాటు చేయడానికి లేదా తరలించడానికి క్రింది కీలను నొక్కండి</translation>
<translation id="5609231933459083978">అప్లికేష‌న్‌ చెల్లనిదిగా కనిపిస్తోంది.</translation>
<translation id="5610038042047936818">కెమెరా మోడ్‌కు మార్చు</translation>
<translation id="5612720917913232150"><ph name="URL" /> మీ కంప్యూటర్ స్థానాన్ని ఉపయోగించాలనుకుంటోంది</translation>
-<translation id="5612734644261457353">క్షమించండి, మీ పాస్‌వర్డ్ ఇప్పటికీ ధృవీకరించబడలేదు. గమనిక: మీరు మీ పాస్‌వర్డ్‌ను ఇటీవల మార్చి ఉంటే, మీరు సైన్ అవుట్ చేసిన తర్వాత మీ క్రొత్త పాస్‌వర్డ్ వర్తించబడుతుంది, దయచేసి ఇక్కడ పాత పాస్‌వర్డ్‌ను ఉపయోగించండి.</translation>
+<translation id="5612734644261457353">క్షమించండి, మీ పాస్‌వర్డ్ ఇప్పటికీ ధృవీకరించబడలేదు. గమనిక: మీరు మీ పాస్‌వర్డ్‌ను ఇటీవల మార్చి ఉంటే, మీరు సైన్ అవుట్ చేసిన తర్వాత మీ కొత్త పాస్‌వర్డ్ వర్తించబడుతుంది, దయచేసి ఇక్కడ పాత పాస్‌వర్డ్‌ను ఉపయోగించండి.</translation>
<translation id="5614190747811328134">వినియోగదారు నోటీస్</translation>
<translation id="5614553682702429503">పాస్‌వర్డ్‌ను సేవ్ చేయాలా?</translation>
<translation id="561698261642843490">Firefoxని మూసివేయండి</translation>
<translation id="5618075537869101857">అయ్యో, కియోస్క్ అప్లికేషన్‌ను ప్రారంభించడం సాధ్యపడలేదు.</translation>
<translation id="5618333180342767515">(దీనికి కొన్ని నిమిషాల సమయం పట్టవచ్చు)</translation>
<translation id="5618972959246891967">సిస్టమ్ తేదీ</translation>
-<translation id="56197088284879152">కనెక్షన్ ఈ రిమోట్ పరికరానికి తక్కువ నాణ్యతతో అధిక డేటాను నిర్వహిస్తోంది: "<ph name="DEVICE_NAME" />".</translation>
+<translation id="56197088284879152">ఈ రిమోట్ పరికరానికి ఉన్న కనెక్షన్ రద్దీగా ఉంది: "<ph name="DEVICE_NAME" />".</translation>
<translation id="5620568081365989559">DevTools <ph name="FOLDER_PATH" />కు పూర్తి యాక్సెస్‌ను అభ్యర్థిస్తున్నాయి. మీరు ఎటువంటి ముఖ్యమైన సమాచారాన్ని బహిర్గతం చేయలేదని నిర్ధారించుకోండి.</translation>
<translation id="5620612546311710611">వినియోగ గణాంకాలు</translation>
<translation id="5620655347161642930">పాస్‌వర్డ్‌లను ఎగుమతి చేయండి...</translation>
@@ -3049,11 +3056,11 @@
<translation id="5626134646977739690">పేరు:</translation>
<translation id="5627086634964711283">ఇది హోమ్ బటన్‌ను క్లిక్ చేసేటప్పుడు చూపబడే పేజీని కూడా నియంత్రిస్తుంది.</translation>
<translation id="5627676517703583263">Chromeతో స్మార్ట్‌గా బ్రౌజ్ చేయండి</translation>
-<translation id="562935524653278697">మీ నిర్వాహకుడు మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌ల సమకాలీకరణను నిలిపివేసారు.</translation>
+<translation id="562935524653278697">మీ నిర్వాహకుడు మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌ల సింక్‌ను నిలిపివేశారు.</translation>
<translation id="5632566673632479864">మీ ఖాతా <ph name="EMAIL" /> ఇకపై ప్రాథమిక ఖాతాగా అనుమతించబడదు. ఈ ఖాతా <ph name="DOMAIN" /> ద్వారా నిర్వహించబడుతోంది కాబట్టి, మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లు ఈ పరికరం నుండి తొలగించబడతాయి.</translation>
<translation id="5632592977009207922">డౌన్‌లోడ్ చేస్తోంది, <ph name="PERCENT_REMAINING" />% మిగిలి ఉంది</translation>
<translation id="563535393368633106">ప్రాప్యత చేయడానికి ముందు అడుగుతుంది (సిఫార్సు చేయబడింది)</translation>
-<translation id="5636996382092289526">మీరు <ph name="NETWORK_ID" />ని ఉపయోగించడానికి మొదట కొన్ని సెకన్లలో ఆటోమేటిక్‌గా తెరుచుకునే <ph name="LINK_START" />నెట్‌వర్క్ సైన్ ఇన్ పేజీని సందర్శించాలి<ph name="LINK_END" />. ఇది జరగకపోతే, నెట్‌వర్క్‌ను ఉపయోగించలేరు.</translation>
+<translation id="5636996382092289526">మీరు <ph name="NETWORK_ID" />ను ఉపయోగించే ముందు, కొన్ని సెకన్లలో ఆటోమేటిక్‌గా తెరవబడే <ph name="LINK_START" />నెట్‌వర్క్ సైన్ ఇన్ పేజీని సందర్శించాలి<ph name="LINK_END" />. ఆ పేజీ తెరుచుకోకపోతే, నెట్‌వర్క్‌ను ఉపయోగించలేరు.</translation>
<translation id="5637476008227280525">మొబైల్ డేటాను ప్రారంభించు</translation>
<translation id="5638309510554459422"><ph name="BEGIN_LINK" />Chrome వెబ్ స్టోర్‌లో<ph name="END_LINK" /> పొడిగింపులు మరియు థీమ్‌లను కనుగొనండి</translation>
<translation id="5639549361331209298">ఈ పేజీని మళ్లీ లోడ్ చేయండి, మరిన్ని ఎంపికలను చూడటానికి దీనిపై కర్సర్ ఉంచండి</translation>
@@ -3064,7 +3071,7 @@
<translation id="5648166631817621825">గత 7 రోజులు</translation>
<translation id="5649053991847567735">స్వయంచాలక డౌన్‌లోడ్‌లు</translation>
<translation id="5649768706273821470">వినండి</translation>
-<translation id="5657667036353380798">బాహ్య పొడిగింపుకి chrome సంస్కరణ <ph name="MINIMUM_CHROME_VERSION" /> లేదా అంతకంటే అధిక సంస్కరణను ఇన్‌స్టాల్ చేయడం అవసరం.</translation>
+<translation id="5657667036353380798">బాహ్య ఎక్స్‌టెన్షన్‌కు chrome వెర్షన్ <ph name="MINIMUM_CHROME_VERSION" /> లేదా అంతకంటే అధిక వెర్షన్‌ను ఇన్‌స్టాల్ చేయడం అవసరం.</translation>
<translation id="5658415415603568799">అదనపు భద్రత కోసం, 20 గంటల తర్వాత మీ పాస్‌వర్డ్‌‌ను నమోదు చేయమని మీ Smart Lock అడుగుతుంది.</translation>
<translation id="5659593005791499971">ఇమెయిల్</translation>
<translation id="5659833766619490117">ఈ పేజీని అనువదించడం సాధ్యపడలేదు</translation>
@@ -3094,7 +3101,7 @@
<translation id="5699533844376998780">పొడిగింపు "<ph name="EXTENSION_NAME" />" జోడించబడింది.</translation>
<translation id="5700087501958648444">ఆడియో సమాచారం</translation>
<translation id="570043786759263127">Google Play యాప్‌లు మరియు సేవలు</translation>
-<translation id="5700836101007545240">కనెక్షన్‌ను జోడించడాన్ని మీ నిర్వాహకులు నిలిపివేసారు</translation>
+<translation id="5700836101007545240">కనెక్షన్‌ను జోడించడాన్ని మీ నిర్వాహకులు నిలిపివేశారు</translation>
<translation id="5701080607174488915">సర్వర్ నుండి విధానాన్ని పొందుతున్నప్పుడు ఎర్రర్ ఏర్పడింది.</translation>
<translation id="5701381305118179107">మధ్యకు</translation>
<translation id="5702898740348134351">&amp;శోధన ఇంజిన్‌లను సవరించండి...</translation>
@@ -3103,7 +3110,7 @@
<translation id="5708171344853220004">Microsoft ప్రధాన పేరు</translation>
<translation id="5709557627224531708">Chromeని మీ డిఫాల్ట్ బ్రౌజర్‌గా సెట్ చేయండి</translation>
<translation id="5711983031544731014">అన్‌లాక్ చేయడం సాధ్యపడలేదు. మీ పాస్‌వర్డ్‌ను నమోదు చేయండి.</translation>
-<translation id="5715711091495208045">ప్లగిన్ బ్రోకర్: <ph name="PLUGIN_NAME" /></translation>
+<translation id="5715711091495208045">ప్లగ్ఇన్‌ బ్రోకర్: <ph name="PLUGIN_NAME" /></translation>
<translation id="5719603411793408026">డిఫాల్ట్ శోధన ఇంజిన్‌లు</translation>
<translation id="5720705177508910913">ప్రస్తుత వినియోగదారు</translation>
<translation id="572155275267014074">Android సెట్టింగ్‌లు</translation>
@@ -3124,7 +3131,7 @@
<translation id="5747552184818312860">గడువు ముగింపు</translation>
<translation id="5747785204778348146">డెవలపర్ - అస్థిరం</translation>
<translation id="5750324801516359607">దూరంగా ఉండాలి</translation>
-<translation id="5752453871435543420">Chrome OS Cloud బ్యాకప్</translation>
+<translation id="5752453871435543420">Chrome OS క్లౌడ్ బ్యాకప్</translation>
<translation id="5756163054456765343">స&amp;హాయ కేంద్రం</translation>
<translation id="5759728514498647443">మీరు <ph name="APP_NAME" /> ద్వారా ముద్రించడానికి పంపే పత్రాలు <ph name="APP_NAME" /> ద్వారా చదవబడతాయి.</translation>
<translation id="5763315388120433852">నెట్‌వర్క్ ఫైల్ షేర్‌లను సెటప్ చేయండి లేదా నిర్వహించండి.</translation>
@@ -3132,7 +3139,7 @@
<translation id="5764483294734785780">ఆడియోని ఇలా సే&amp;వ్ చెయ్యి...</translation>
<translation id="57646104491463491">తేదీ సవరించబడింది</translation>
<translation id="5764797882307050727">దయచేసి మీ పరికరంలో కొంత స్థలాన్ని ఖాళీ చేయండి.</translation>
-<translation id="5765425701854290211">క్షమించండి, కొన్ని ఫైల్‌లు పాడయ్యాయి మరియు అప్‌డేట్ విజయవంతం కాలేదు. మీ సింక్ చేసిన ఫైల్‌లు సురక్షితంగా ఉన్నాయి.</translation>
+<translation id="5765425701854290211">క్షమించండి, కొన్ని ఫైల్‌లు పాడయ్యాయి. అప్‌డేట్ విజయవంతం కాలేదు. మీ సింక్ చేసిన‌ ఫైల్‌లు సురక్షితంగా ఉన్నాయి.</translation>
<translation id="5765491088802881382">నెట్‌వర్క్‌లు ఏవీ అందుబాటులో లేవు</translation>
<translation id="5765780083710877561">వివరణ:</translation>
<translation id="5771816112378578655">సెటప్ పురోగమనంలో ఉంది...</translation>
@@ -3161,7 +3168,7 @@
<translation id="5794786537412027208">అన్ని Chrome యాప్‌ల నుండి నిష్క్రమించు</translation>
<translation id="5797070761912323120">శోధన, ప్రకటనలు, ఇతర Google సేవలను వ్యక్తిగతీకరించడానికి Google మీ చరిత్రను ఉపయోగించే అవకాశం ఉంటుంది</translation>
<translation id="5799508265798272974">Linux వర్చువల్ మెషీన్: <ph name="LINUX_VM_NAME" /></translation>
-<translation id="5800020978570554460">లక్ష్య ఫైల్ చివరి డౌన్‌లోడ్ తర్వాత కుదించబడింది లేదా తీసివేయబడింది.</translation>
+<translation id="5800020978570554460">గమ్యస్థానం ఫైల్ చివరి డౌన్‌లోడ్ తర్వాత కుదించబడింది లేదా తీసివేయబడింది.</translation>
<translation id="5801568494490449797">ప్రాధాన్యతలు</translation>
<translation id="5804241973901381774">అనుమతులు</translation>
<translation id="5805697420284793859">విండో మేనేజర్</translation>
@@ -3189,27 +3196,27 @@
<translation id="5835754902560991078">అత్యంత సంక్షిప్తం (0.6s)</translation>
<translation id="5838456317242088717">ప్రస్తుత అజ్ఞాత సెషన్‌కు</translation>
<translation id="5842497610951477805">బ్లూటూత్‌ను ప్రారంభించు</translation>
-<translation id="5843250171025351504">మీ నిర్వాహకుడు పేర్కొన్న కనీస క్లయింట్ వెర్షన్‌తో మీ పరికరం ఇకపై అనుకూలించదు. దయచేసి లాగిన్ చేయడానికి అప్‌డేట్ చేయండి.</translation>
+<translation id="5843250171025351504">మీ నిర్వాహకుడు పేర్కొన్న కనీస క్లయింట్ వెర్షన్‌తో మీ పరికరం ఇకపై అనుకూలించదు. లాగిన్ చేయడానికి, దయచేసి అప్‌డేట్ చేయండి.</translation>
<translation id="5849212445710944278">ఇప్పటికే జోడించబడింది</translation>
<translation id="5849570051105887917">స్వస్థల నెట్‌వర్క్ ప్రదాత కోడ్</translation>
<translation id="5850516540536751549">ఈ ఫైల్ రకానికి మద్దతు లేదు. దయచేసి ఈ రకమైన ఫైల్‌ను తెరవగల యాప్‌ను కనుగొనడానికి <ph name="BEGIN_LINK" />Chrome వెబ్ స్టోర్<ph name="END_LINK" />ను సందర్శించండి.
<ph name="BEGIN_LINK_HELP" />మరింత తెలుసుకోండి<ph name="END_LINK_HELP" /></translation>
<translation id="5851063901794976166">ఇక్కడ చూడటానికి ఏమీ లేదు...</translation>
<translation id="5851868085455377790">జారీ చేసినవారు</translation>
-<translation id="5852112051279473187">అయ్యో! ఈ పరికరాన్ని నమోదు చేస్తున్నపుడు ఏదో తప్పు జరిగింది. దయచేసి మళ్లీ ప్రయత్నించండి లేదా మీ మద్దతు ప్రతినిధిని సంప్రదించండి.</translation>
+<translation id="5852112051279473187">అయ్యో! ఈ పరికరాన్ని నమోదు చేస్తున్నపుడు ఏదో తప్పిదం జరిగింది. దయచేసి మరల ప్రయత్నించండి లేదా మీ మద్దతు ప్రతినిధిని సంప్రదించండి.</translation>
<translation id="5852137567692933493">పునఃప్రారంభించి, పవర్‌వాష్ చేయి</translation>
<translation id="5854912040170951372">స్లైస్</translation>
<translation id="5855773610748894548">అయ్యో, సురక్షిత మాడ్యూల్ ఎర్రర్ ఏర్పడింది.</translation>
-<translation id="5856721540245522153">డీబగ్గింగ్ ఫీచ‌ర్‌ల‌ను ప్రారంభించండి</translation>
+<translation id="5856721540245522153">డీబగ్గింగ్ ఫీచ‌ర్‌లను ప్రారంభించండి</translation>
<translation id="5857090052475505287">క్రొత్త ఫోల్డర్</translation>
<translation id="5857774240076772505"><ph name="FOLDER_NAME" />ఫోల్డర్‌లోని ఫైల్‌లను సవరించడానికి Linux యాప్‌లకు అనుమతి ఇవ్వండి</translation>
<translation id="5858490737742085133">టెర్మినల్</translation>
<translation id="585979798156957858">బాహ్య మెటా</translation>
<translation id="5860033963881614850">ఆఫ్ అయ్యింది</translation>
<translation id="5860491529813859533">ఆన్ చేయండి</translation>
-<translation id="5860494867054883682">మీ పరికరం <ph name="CHANNEL_NAME" /> ఛానెల్‌కు నవీకరించబడుతోంది (<ph name="PROGRESS_PERCENT" />)</translation>
+<translation id="5860494867054883682">మీ పరికరం <ph name="CHANNEL_NAME" /> ఛానెల్‌కు అప్‌డేట్ చేయబడుతోంది (<ph name="PROGRESS_PERCENT" />)</translation>
<translation id="5862109781435984885">అరలో స్టైలస్ సాధనాలను చూపుతుంది</translation>
-<translation id="5863445608433396414">డీబగ్గింగ్ ఫీచ‌ర్‌ల‌ను ప్రారంభించు</translation>
+<translation id="5863445608433396414">డీబగ్గింగ్ ఫీచ‌ర్‌లను ప్రారంభించు</translation>
<translation id="5864471791310927901">DHCP లుక్‌అప్ విఫలమైంది</translation>
<translation id="586567932979200359">మీరు <ph name="PRODUCT_NAME" /> డిస్క్ ఇమేజ్ నుండి దాన్ని అమలు చేస్తున్నారు. మీ కంప్యూటర్‌లో దీన్ని ఇన్‌స్టాల్ చేయడం వలన డిస్క్ ఇమేజ్ లేకుండా దాన్ని అమలు చేయడానికి మీరు అనుమతించబడతారు. ఇది తాజాగా ఉంటుందని హామీ పొందుతారు.</translation>
<translation id="5865733239029070421">Googleకు ఆటోమేటిక్‌గా వినియోగ గణాంకాలను, క్రాష్ నివేదికలను పంపుతుంది</translation>
@@ -3233,7 +3240,7 @@
<translation id="5895138241574237353">మళ్ళీ ప్రారంభించు</translation>
<translation id="5895187275912066135">జారీ చేయబడినది</translation>
<translation id="5900302528761731119">Google ప్రొఫైల్ ఫోటో</translation>
-<translation id="5906655207909574370">దాదాపు నవీకృతంగా ఉంది! నవీకరణను పూర్తి చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
+<translation id="5906655207909574370">దాదాపు తాజాగా ఉంది! అప్‌డేట్‌ను పూర్తి చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
<translation id="5906732635754427568">ఈ యాప్‌తో అనుబంధించబడిన డేటా ఈ పరికరం నుండి తీసివేయబడుతుంది.</translation>
<translation id="5908769186679515905">Flashని అమలు చేయనీయకుండా సైట్‌లను బ్లాక్ చేయి</translation>
<translation id="5910363049092958439">చిత్రాన్ని ఇలా సే&amp;వ్ చేయి...</translation>
@@ -3249,7 +3256,7 @@
<ph name="EXPONENT_HEX_DUMP" /></translation>
<translation id="5916664084637901428">ఆన్ చేయి</translation>
<translation id="59174027418879706">ప్రారంభించబడింది</translation>
-<translation id="5920543303088087579">ఈ నెట్‌వర్క్‌కు కనెక్ట్ చేయడాన్ని మీ నిర్వాహకులు నిలిపివేసారు</translation>
+<translation id="5920543303088087579">ఈ నెట్‌వర్క్‌కు కనెక్ట్ చేయడాన్ని మీ నిర్వాహకులు నిలిపివేశారు</translation>
<translation id="5920835625712313205">Chrome OS సిస్టమ్ ఇమేజ్ రైటర్</translation>
<translation id="5924047253200400718">సహాయం పొందండి<ph name="SCANNING_STATUS" /></translation>
<translation id="5924527146239595929">కొత్త ఫోటోను తీసుకోండి లేదా ఇప్పటికే ఉన్న ఫోటో లేదా చిహ్నాన్ని ఎంచుకోండి.
@@ -3265,13 +3272,13 @@
<translation id="5939518447894949180">రీసెట్ చేయి</translation>
<translation id="5939847200023027600">PDF కంపోజిటర్ సేవ</translation>
<translation id="5941153596444580863">వ్యక్తిని జోడించు...</translation>
-<translation id="5941343993301164315">దయచేసి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చెయ్యండి.</translation>
+<translation id="5941343993301164315">దయచేసి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చేయండి.</translation>
<translation id="5941711191222866238">కనిష్టీకరించు</translation>
<translation id="5945188205370098537">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. సమస్య విశ్లేషణ, పరికరం, యాప్ వినియోగ డేటాను Googleకి ఆటోమేటిక్‌గా పంపడం ద్వారా మీ Android అనుభవాన్ని మెరుగుపరచడంలో సహాయపడండి. ఇది సిస్టమ్, యాప్ స్థిరత్వానికి, అలాగే ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. మీ అదనపు వెబ్ &amp; యాప్ కార్యకలాపం సెట్టింగ్‌ను ఆన్ చేసినట్లయితే, ఈ డేటా మీ Google ఖాతాలో సేవ్ చేయబడవచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
<translation id="5946591249682680882">నివేదిక ID <ph name="WEBRTC_LOG_REPORT_ID" /></translation>
<translation id="5949281959820712067">మీ Google డిస్క్‌లోని ఫైల్‌లను సవరించడానికి Linux యాప్‌లకు అనుమతి ఇవ్వండి. మార్పులు మీ ఇతర పరికరాలలో సమకాలీకరించబడతాయి.</translation>
<translation id="5949544233750246342">ఫైల్‌ని అన్వయించడం సాధ్యపడలేదు</translation>
-<translation id="5955282598396714173">మీ పాస్‌వర్డ్ గడువు ముగిసింది. దచయేసి దీనిని మార్చడం కోసం సైన్ అవుట్ చేసి, సైన్ ఇన్ చేయండి.</translation>
+<translation id="5955282598396714173">మీ పాస్‌వర్డ్ గడువు ముగిసింది. దయచేసి దీనిని మార్చడానికి సైన్ అవుట్ చేసి, సైన్ ఇన్ చేయండి.</translation>
<translation id="5955809630138889698">ఈ పరికరం కేవలం ఆన్‌లైన్ డెమో మోడ్ కోసం మాత్రమే అందుబాటులో ఉండవచ్చు. దయచేసి మరిన్ని వివరాల కోసం మీ మద్దతు ప్రతినిధిని సంప్రదించండి.</translation>
<translation id="5956585768868398362">మీరు ఆశిస్తున్న శోధన పేజీ ఇదేనా?</translation>
<translation id="5957613098218939406">మరిన్ని ఎంపికలు</translation>
@@ -3282,8 +3289,10 @@
<translation id="5962207703002684882">మీ అసిస్టెంట్ మీ వాయిస్ మోడల్‌ని సృష్టించడానికి ఈ రికార్డింగ్‌లను ఉపయోగిస్తుంది, ఇది మీ పరికరంలో నిల్వ చేయబడుతుంది. అసిస్టెంట్ సెట్టింగ్‌లలో ఆ మోడల్‌ను తొలగించండి లేదా మళ్లీ శిక్షణనివ్వండి. మీ Google కార్యకలాప నియంత్రణలలో వాయిస్ ఆదేశాలను చూడండి లేదా తొలగించండి.</translation>
<translation id="5963453369025043595"><ph name="NUM_HANDLES" /> (<ph name="NUM_KILOBYTES_LIVE" /> మిగిలి ఉన్నాయి)</translation>
<translation id="5965661248935608907">మీరు హోమ్ బటన్‌ను క్లిక్ చేసేటప్పుడు లేదా ఓమ్నిబాక్స్ నుండి వెతికేటప్పుడు చూపబడే పేజీని కూడా ఇది నియంత్రిస్తుంది.</translation>
-<translation id="5971037678316050792">బ్లూటూత్ అడాప్టర్ స్థితిని మరియు జత చేసే విధానాన్ని నియంత్రించడానికి అనుమతి</translation>
+<translation id="5971037678316050792">బ్లూటూత్ అడాప్టర్ స్థితిని, జత చేసే విధానాన్ని నియంత్రించడానికి అనుమతి</translation>
<translation id="5972017421290582825">MIDI సెట్టింగ్‌లను నిర్వహించండి...</translation>
+<translation id="597235323114979258">మరిన్ని గమ్యస్థానాలను చూడండి</translation>
+<translation id="5972666587303800813">నిర్వహణ సేవ లేదు</translation>
<translation id="5972708806901999743">పైకి తరలించు</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> ప్రారంభించు</translation>
<translation id="5975792506968920132">బ్యాటరీ ఛార్జ్ శాతం</translation>
@@ -3294,7 +3303,7 @@
<translation id="5984222099446776634">ఇటీవల సందర్శించినవి</translation>
<translation id="5985458664595100876">URL ఫార్మాట్ చెల్లదు. మద్దతు ఉన్న ఫార్మాట్‌లు \\server\share మరియు smb://server/share.</translation>
<translation id="5990386583461751448">అనువదించబడింది</translation>
-<translation id="599131315899248751">{NUM_APPLICATIONS,plural, =1{వెబ్‌ను బ్రౌజ్ చేస్తూనే ఉండడాన్ని నిర్ధారించడానికి, మీ నిర్వాహకుడిని ఈ అప్లికేషన్‌న్ని తీసివేయమని కోరండి.}other{వెబ్‌ను బ్రౌజ్ చేస్తూనే ఉండడాన్ని నిర్ధారించడానికి, మీ నిర్వాహకుడిని ఈ అప్లికేషన్‌లను తీసివేయమని కోరండి.}}</translation>
+<translation id="599131315899248751">{NUM_APPLICATIONS,plural, =1{వెబ్‌ను బ్రౌజ్ చేస్తూనే ఉండడాన్ని నిర్ధారించడానికి, మీ నిర్వాహకుడిని ఈ అప్లికేషన్‌ను తీసివేయమని కోరండి.}other{వెబ్‌ను బ్రౌజ్ చేస్తూనే ఉండడాన్ని నిర్ధారించడానికి, మీ నిర్వాహకుడిని ఈ అప్లికేషన్‌లను తీసివేయమని కోరండి.}}</translation>
<translation id="5997337190805127100">సైట్ యాక్సెస్ గురించి మరింత తెలుసుకోండి</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' అనే దానికి <ph name="RESULT_COUNT" /> ఫలితాలు లభించాయి</translation>
<translation id="6002458620803359783">ప్రాధాన్య వాయిస్‌లు</translation>
@@ -3303,11 +3312,11 @@
<translation id="6007237601604674381">తరలింపు విఫలమైంది. <ph name="ERROR_MESSAGE" /></translation>
<translation id="6007240208646052708">మీ భాషలో వాయిస్ శోధన అందుబాటులో లేదు.</translation>
<translation id="6009781704028455063">అంతర్నిర్మిత సెన్సార్</translation>
-<translation id="6010869025736512584">వీడియో ఇన్‌పుట్ ప్రాప్యత చేయబడుతోంది</translation>
+<translation id="6010869025736512584">వీడియో ఇన్‌పుట్ యాక్సెస్‌ చేయబడుతోంది</translation>
<translation id="6011193465932186973">వేలిముద్ర</translation>
<translation id="6011449291337289699">సైట్ డేటాను తీసివేయండి</translation>
<translation id="6015796118275082299">సంవత్సరం</translation>
-<translation id="6016551720757758985">మునుపటి వెర్షన్‌కు తిరిగి మార్చేలా పవర్‌వాష్‌ను నిర్ధారించండి</translation>
+<translation id="6016551720757758985">మునుపటి వెర్షన్‌కు తిరిగి మార్చేలా చేసే పవర్‌వాష్‌ను నిర్ధారించండి</translation>
<translation id="6016972670657536680">'భాష మరియు కీబోర్డ్‌ను ఎంచుకోండి' బటన్‌. ప్రస్తుతం ఎంచుకున్న భాష <ph name="LANGUAGE" />.</translation>
<translation id="6019169947004469866">కత్తిరించు</translation>
<translation id="6020431688553761150">మీకు ఈ వనరుని యాక్సెస్ చేయడానికి సర్వర్ అధికారం ఇవ్వలేదు.</translation>
@@ -3315,7 +3324,7 @@
<translation id="6022659036123304283">Chromeని మీకు నచ్చినట్లు తయారు చేసుకోండి</translation>
<translation id="6022705094403139349">మీ భద్రతా కీని జత చేయడానికి సిద్ధంగా ఉన్నారా?</translation>
<translation id="6023643151125006053">ఈ (SN: <ph name="SERIAL_NUMBER" />) పరికరం <ph name="SAML_DOMAIN" /> నిర్వాహకుడిచే లాక్ చేయబడింది.</translation>
-<translation id="6025215716629925253">స్టాక్ ఆచూకీ</translation>
+<translation id="6025215716629925253">స్టాక్ ట్రేస్</translation>
<translation id="6026047032548434446">యాప్‌ను ఇన్‌స్టాల్ చేయాలా?</translation>
<translation id="6026819612896463875"><ph name="WINDOW_TITLE" /> - USB పరికరం కనెక్ట్ చేయబడింది</translation>
<translation id="6029027682598229313">Linuxను ఇన్‌స్టాల్ చేయడం పూర్తయింది.</translation>
@@ -3324,7 +3333,7 @@
<translation id="6032912588568283682">ఫైల్ సిస్టమ్</translation>
<translation id="6038929619733116134">సైట్ అనుచితమైన లేదా తప్పుదారి పట్టించే ప్రకటనలను చూపినట్లయితే బ్లాక్ చేయండి</translation>
<translation id="6039651071822577588">నెట్‌వర్క్ ఫీచర్ నిఘంటువు తప్పు ఫార్మాట్‌లో ఉంది</translation>
-<translation id="604001903249547235">Cloud బ్యాకప్</translation>
+<translation id="604001903249547235">క్లౌడ్ బ్యాకప్</translation>
<translation id="6040143037577758943">మూసివేయి</translation>
<translation id="6040852767465482106">అనామక గుర్తింపు</translation>
<translation id="6041046205544295907"><ph name="BEGIN_PARAGRAPH1" />మీ పరికర స్థానాన్ని అంచనా వేయడంలో సహాయపడటానికి Wi‑Fi, మొబైల్ నెట్‌వర్క్‌లు మరియు సెన్సార్‌ల వంటి మూలాధారాలను Google స్థాన సేవ ఉపయోగిస్తుంది.<ph name="END_PARAGRAPH1" />
@@ -3340,7 +3349,7 @@
<translation id="6049065490165456785">అంతర్గత కెమెరా నుండి ఫోటో</translation>
<translation id="6051354611314852653">అయ్యో! ఈ పరికరం కోసం API యాక్సెస్‌ను ప్రామాణీకరించడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="6052976518993719690">SSL ధృవీకరణ అధికారం</translation>
-<translation id="6053401458108962351">&amp;బ్రౌజింగ్‌ డేటాను క్లియర్ చెయ్యి...</translation>
+<translation id="6053401458108962351">&amp;బ్రౌజింగ్‌ డేటాను క్లియర్ చేయి...</translation>
<translation id="6055171183283175969">మీరు నమోదు చేసిన పాస్‌వర్డ్ తప్పు.</translation>
<translation id="6055392876709372977">RSA ఎన్‌క్రిప్షన్‌తో PKCS #1 SHA-256</translation>
<translation id="6056710589053485679">సాధారణంగా మళ్లీ లోడ్ చేయి</translation>
@@ -3348,7 +3357,7 @@
<translation id="6059652578941944813">సర్టిఫికెట్ అధికార క్రమం</translation>
<translation id="6059925163896151826">USB పరికరాలు</translation>
<translation id="6064217302520318294">స్క్రీన్ లాక్</translation>
-<translation id="6065289257230303064">సర్టిఫికెట్ విషయ డైరెక్టరీ లక్షణాలు</translation>
+<translation id="6065289257230303064">సర్టిఫికెట్ విషయ డైరెక్టరీ ఫీచర్‌లు</translation>
<translation id="6069671174561668781">వాల్‌పేపర్‌ని సెట్ చేయండి</translation>
<translation id="6071181508177083058">పాస్‌వర్డ్‌ను నిర్ధారించండి</translation>
<translation id="6071576563962215370">పరికరం ఇన్‌స్టాలేషన్-సమయ లక్షణాల లాక్‌ను ఏర్పాటు చేయడంలో సిస్టమ్ విఫలమైంది.</translation>
@@ -3357,7 +3366,7 @@
<translation id="6075731018162044558">అయ్యో! ఈ పరికరం కోసం దీర్ఘకాల API యాక్సెస్ టోకెన్‌ను పొందడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="6075907793831890935"><ph name="HOSTNAME" /> పేరు గల పరికరంతో డేటాను ఇచ్చిపుచ్చుకోవడానికి అనుమతి</translation>
<translation id="6076175485108489240">స్థానాన్ని ఉపయోగించండి. స్థాన అనుమతిని కలిగిన యాప్‌లు మరియు సేవలు మీ పరికర స్థానాన్ని ఉపయోగించడానికి అనుమతించండి. Google కాలానుగుణంగా స్థాన డేటాని సేకరించవచ్చు మరియు స్థాన ఖచ్చితత్వం మరియు స్థానం-ఆధారిత సేవలను మెరుగుపరచడం కోసం ఈ డేటాని అనామకంగా ఉపయోగించవచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
-<translation id="6076448957780543068">ఈ స్క్రీన్‌షాట్‌ని చేర్చు</translation>
+<translation id="6076448957780543068">ఈ స్క్రీన్‌షాట్‌ను చేర్చు</translation>
<translation id="6077131872140550515">ప్రాధాన్య నెట్‌వర్క్‌ల నుండి తీసివేయి</translation>
<translation id="6077189836672154517"><ph name="DEVICE_TYPE" />కు సంబంధించిన చిట్కాలు మరియు అప్‌డేట్‌లు</translation>
<translation id="6078323886959318429">షార్ట్‌కట్‌ను జోడించు</translation>
@@ -3365,11 +3374,11 @@
<translation id="6080515710685820702">షేర్ చేయబడిన కంప్యూటర్‌ని ఉపయోగిస్తున్నారా? అజ్ఞాత విండోను తెరిచి ప్రయత్నించండి.</translation>
<translation id="6080689532560039067">మీ సిస్టమ్ సమయాన్ని తనిఖీ చేయండి</translation>
<translation id="6082651258230788217">సాధనపట్టీలో చూపండి</translation>
-<translation id="6086846494333236931">మీ నిర్వాహకుడు ఇన్‌స్టాల్ చేసారు</translation>
+<translation id="6086846494333236931">మీ నిర్వాహకుడు ఇన్‌స్టాల్ చేశారు</translation>
<translation id="6087960857463881712">అద్భుతమైన ముఖం</translation>
<translation id="6089481419520884864">పేజీ డిస్టిల్ చేయి</translation>
<translation id="6091761513005122595">షేర్ విజయవంతంగా మౌంట్ చేయబడింది.</translation>
-<translation id="6093888419484831006">అప్‌డేట్ రద్దు అవుతోంది...</translation>
+<translation id="6093888419484831006">అప్‌డేట్‌ రద్దు చేయడం...</translation>
<translation id="6095984072944024315">−</translation>
<translation id="6096047740730590436">గరిష్టీకరించిన దాన్ని తెరువు</translation>
<translation id="6096326118418049043">X.500 పేరు</translation>
@@ -3414,7 +3423,7 @@
<translation id="6154697846084421647">ప్రస్తుతం సైన్ ఇన్ చేసారు</translation>
<translation id="6155141482566063812">బ్యాక్‌గ్రౌండ్ ట్యాబ్ మీ స్క్రీన్‌ను షేర్ చేస్తోంది</translation>
<translation id="6156323911414505561">బుక్‌మార్క్‌ల పట్టీని చూపు</translation>
-<translation id="6156863943908443225">లిపి కాష్</translation>
+<translation id="6156863943908443225">స్క్రిప్ట్ కాష్</translation>
<translation id="6156960295318603523">భాష సెట్టింగ్‌లు</translation>
<translation id="6160625263637492097">ప్రామాణీకరణ కోసం ప్రమాణపత్రాలను అందించడానికి అనుమతి</translation>
<translation id="6163363155248589649">&amp;సాధారణంగా</translation>
@@ -3428,14 +3437,14 @@
<translation id="6173623053897475761">మీ పిన్‌ని మళ్లీ టైప్ చేయండి</translation>
<translation id="6175314957787328458">Microsoft డొమైన్ GUID</translation>
<translation id="6176043333338857209">మీ భద్రతా కీతో కమ్యూనికేట్ చేయడానికి బ్లూటూత్‌ తాత్కాలికంగా ఆన్ చేయబడుతుంది</translation>
-<translation id="6178664161104547336">ఒక సర్టిఫికెట్ని ఎంచుకోండి</translation>
+<translation id="6178664161104547336">ఒక సర్టిఫికెట్‌ను ఎంచుకోండి</translation>
<translation id="6181431612547969857">డౌన్‌లోడ్ బ్లాక్ చేయబడింది</translation>
<translation id="6184660361319693890">లేబుల్‌లు ఇవ్వు</translation>
<translation id="6185132558746749656">పరికర స్థానం</translation>
<translation id="6189412234224385711"><ph name="EXTENSION_NAME" />తో తెరవండి</translation>
<translation id="6195693561221576702">ఈ పరికరాన్ని ఆఫ్‌లైన్ డెమో మోడ్‌లో సెటప్ చేయలేరు.</translation>
<translation id="6196640612572343990">మూడవ పక్షం కుక్కీలను బ్లాక్ చేయి</translation>
-<translation id="6196854373336333322">"<ph name="EXTENSION_NAME" />" పొడిగింపు మీ ప్రాక్సీ సెట్టింగ్‌లపై నియంత్రణను కలిగి ఉంది, అంటే ఇది మీరు ఆన్‌లైన్‌‍లో చేసే ప్రతిదీ మార్చగలదు, విచ్ఛిన్నం చేయగలదు లేదా మీకు తెలియకుండా గమనించగలదు. ఈ మార్పు ఎందుకు జరిగిందో మీకు సరిగ్గా తెలియదంటే, బహుశా మీరు ఇది కోరుకొని ఉండకపోవచ్చు.</translation>
+<translation id="6196854373336333322">"<ph name="EXTENSION_NAME" />" ఎక్సటెన్షన్ మీ ప్రాక్సీ సెట్టింగ్‌లపై నియంత్రణను కలిగి ఉంది, అంటే ఇది మీరు ఆన్‌లైన్‌‍లో చేసే ప్రతిదీ మార్చగలదు, విచ్ఛిన్నం చేయగలదు లేదా మీకు తెలియకుండా గమనించగలదు. ఈ మార్పు ఎందుకు జరిగిందో మీకు సరిగ్గా తెలియదంటే, బహుశా మీరు ఇది కోరుకొని ఉండకపోవచ్చు.</translation>
<translation id="6198102561359457428">సైన్ అవుట్ చేసి, మళ్లీ సైన్ ఇన్ చేయండి...</translation>
<translation id="6198252989419008588">పిన్ మార్పు</translation>
<translation id="6199801702437275229">ఖాళీ సమాచారం కోసం వేచి ఉంది...</translation>
@@ -3449,7 +3458,7 @@
<translation id="6211495400987308581"><ph name="PROFILE_NAME" />: సమకాలీకరణ పని చేయడం లేదు</translation>
<translation id="6212039847102026977">అధునాతన నెట్‌వర్క్ లక్షణాలను చూపు</translation>
<translation id="6212168817037875041">ప్రదర్శనను ఆఫ్ చేయండి</translation>
-<translation id="6212752530110374741">ఇమెయిల్ లింక్</translation>
+<translation id="6212752530110374741">లింక్‌ను ఇమెయిల్ చేయి</translation>
<translation id="6218058416316985984"><ph name="DEVICE_TYPE" /> ఆఫ్‌లైన్‌లో ఉంది. ఇంటర్నెట్‌కు కనెక్ట్ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="6220413761270491930">ఎక్స్‌టెన్షన్‌ను లోడ్ చేయడంలో ఎర్రర్</translation>
<translation id="6223447490656896591">అనుకూల చిత్రం:</translation>
@@ -3461,19 +3470,19 @@
<translation id="6228516488918914827">వేగవంతమైన పేజీ లోడ్ అయింది</translation>
<translation id="6228691855869374890">ఈ సైట్ MIDI పరికరాలకు పూర్తి నియంత్రణను కలిగి ఉంది.</translation>
<translation id="6229890768313448549">Google Play సేవా నిబంధనలను లోడ్ చేయడం సాధ్యపడదు. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
-<translation id="6231881193380278751">పేజీని ఆటోమేటిక్‌గా రిఫ్రెష్ చేయడానికి URLలో ప్రశ్న పారామీటర్‌ను జోడించండి: chrome://device-log/?refresh=&lt;sec&gt;</translation>
+<translation id="6231881193380278751">పేజీని ఆటోమేటిక్‌గా రిఫ్రెష్ చేయడానికి URLలో ప్రశ్న పరామితిని జోడించండి: chrome://device-log/?refresh=&lt;sec&gt;</translation>
<translation id="6232017090690406397">బ్యాటరీ</translation>
<translation id="6232116551750539448"><ph name="NAME" />కి కనెక్షన్ కోల్పోయింది</translation>
<translation id="6233154960150021497">కీబోర్డ్ బదులుగా వాయిస్‌ను డిఫాల్ట్‌గా ఉపయోగించండి</translation>
<translation id="6237816943013845465">మీ స్క్రీన్ రిజల్యూషన్‌ను సర్దుబాటు చేయడానికి మిమ్మల్ని అనుమతిస్తుంది</translation>
<translation id="6238923052227198598">లాక్ స్క్రీన్‌పై తాజా గమనికను ఉంచండి</translation>
<translation id="6239558157302047471">&amp;ఫ్రేమ్‌ను మళ్లీ లోడ్ చేయి</translation>
-<translation id="6241530762627360640">మీ సిస్టమ్‌తో జత చేయబడిన బ్లూటూత్ పరికరాలకు సంబంధించిన సమాచారాన్ని యాక్సెస్ చేయడానికి మరియు సమీపంలోని బ్లూటూత్ పరికరాలను కనుగొనడానికి అనుమతి.</translation>
+<translation id="6241530762627360640">మీ సిస్టమ్‌తో జత చేయబడిన బ్లూటూత్ పరికరాలకు సంబంధించిన సమాచారాన్ని యాక్సెస్‌ చేయడానికి, సమీపంలోని బ్లూటూత్ పరికరాలను కనుగొనడానికి అనుమతి.</translation>
<translation id="6243280677745499710">ప్రస్తుతం సెట్ చేసినది</translation>
<translation id="6243774244933267674">సర్వర్ అందుబాటులో లేదు</translation>
<translation id="6247708409970142803"><ph name="PERCENTAGE" />%</translation>
<translation id="6247802389331535091">సిస్టమ్: <ph name="ARC_PROCESS_NAME" /></translation>
-<translation id="624789221780392884">అప్‌డేట్ సిద్ధంగా ఉంది</translation>
+<translation id="624789221780392884">అప్‌డేట్‌ సిద్ధంగా ఉంది</translation>
<translation id="6248400709929739064">ఉపశీర్షికలను ప్రారంభించు</translation>
<translation id="6248988683584659830">శోధన సెట్టింగ్‌లు</translation>
<translation id="6251870443722440887">GDI నిర్వహించేవి</translation>
@@ -3481,13 +3490,13 @@
<translation id="6254503684448816922">కీ రాజీ</translation>
<translation id="6257602895346497974">సమకాలీకరణను ఆన్ చేయి...</translation>
<translation id="6259104249628300056">మీ స్థానిక నెట్‌వర్క్‌లో పరికరాలను కనుగొనండి</translation>
-<translation id="6263082573641595914">Microsoft CA సంస్కరణ</translation>
+<translation id="6263082573641595914">Microsoft CA వెర్షన్</translation>
<translation id="6263284346895336537">క్లిష్టమైనది కాదు</translation>
<translation id="6264365405983206840">&amp;అన్నీ ఎంచుకోండి</translation>
-<translation id="6267166720438879315"><ph name="HOST_NAME" />కు మిమ్మల్ని మీరు ప్రమాణీకరించడానికి ఒక సర్టిఫికెట్ను ఎంచుకోండి</translation>
+<translation id="6267166720438879315"><ph name="HOST_NAME" />కు మిమ్మల్ని మీరు ప్రమాణీకరించడానికి ఒక సర్టిఫికెట్‌ను ఎంచుకోండి</translation>
<translation id="6268252012308737255"><ph name="APP" />తో తెరువు</translation>
<translation id="6268747994388690914">HTML ఫైల్ నుండి బుక్‌మార్క్‌లను దిగుమతి చేయి...</translation>
-<translation id="6272643420381259437">ప్లగిన్‌ను డౌన్‌లోడ్ చేస్తున్నప్పుడు ఎర్రర్ (<ph name="ERROR" />) ఏర్పడింది</translation>
+<translation id="6272643420381259437">ప్లగ్ఇన్‌‌ను డౌన్‌లోడ్ చేస్తున్నప్పుడు ఎర్రర్ (<ph name="ERROR" />) ఏర్పడింది</translation>
<translation id="6273677812470008672">నాణ్యత</translation>
<translation id="6277105963844135994">నెట్‌వర్క్ సమయం ముగిసింది</translation>
<translation id="6277518330158259200">స్క్రీన్‌షాట్‌ను తీ&amp;యి</translation>
@@ -3500,7 +3509,7 @@
<translation id="6286708577777130801">సేవ్ చేసిన పాస్‌వర్డ్ వివరాలు</translation>
<translation id="6287852322318138013">ఈ ఫైల్‌ను తెరవడానికి యాప్‌ను ఎంచుకోండి</translation>
<translation id="6289452883081499048">వ్యక్తిగతీకరించిన Google సేవలు, ఉదా., Play వంటివి</translation>
-<translation id="6290556621549272952">మీరు మీ టీవీ లేదా ఇతర పరికరాల్లో Chromium నుండి కంటెంట్‌ను ప్రదర్శించడానికి ఈ ఫీచర్‌ని ఉపయోగించవచ్చు.</translation>
+<translation id="6290556621549272952">మీరు మీ టీవీ లేదా ఇతర పరికరాల్లో Chromium నుండి కంటెంట్‌ను ప్రదర్శించడానికి ఈ ఫీచర్‌ను ఉపయోగించవచ్చు.</translation>
<translation id="6291949900244949761">సైట్ USB పరికరాలను యాక్సెస్ చేయాలనుకున్నప్పుడు అడుగు (సిఫార్సు చేయబడింది)</translation>
<translation id="6291953229176937411">శోధినిలో &amp;చూపించు</translation>
<translation id="6295158916970320988">అన్ని సైట్‌లు</translation>
@@ -3510,23 +3519,23 @@
<translation id="6305607932814307878">సార్వజనీన విధానం:</translation>
<translation id="6307990684951724544">సిస్టమ్ బిజీగా ఉంది</translation>
<translation id="6308937455967653460">లిం&amp;క్‌ను ఇలా సేవ్ చెయ్యి...</translation>
-<translation id="6311220991371174222">మీ ప్రొఫైల్‌ను తెరుస్తున్నప్పుడు ఏదో తప్పు జరిగినందున Chromeని తెరవడం సాధ్యపడదు. Chromeని పునఃప్రారంభించడానికి ప్రయత్నించండి.</translation>
+<translation id="6311220991371174222">మీ ప్రొఫైల్‌ను తెరుస్తున్నప్పుడు ఏదో తప్పు జరిగినందున Chromeను తెరవడం సాధ్యపడలేదు. Chromeను పునఃప్రారంభించడానికి ప్రయత్నించండి.</translation>
<translation id="6312403991423642364">తెలియని నెట్‌వర్క్ ఎర్రర్</translation>
<translation id="6313320178014547270">మీరు ఈ వెబ్‌సైట్‌తో నమోదు కాని కీని ఉపయోగిస్తున్నారు</translation>
<translation id="6313641880021325787">VRని నిష్క్రమించు</translation>
-<translation id="6314819609899340042">మీరు ఈ <ph name="IDS_SHORT_PRODUCT_NAME" /> పరికరంలో డీబగ్గింగ్ లక్షణాలను విజయవంతంగా ప్రారంభించారు.</translation>
+<translation id="6314819609899340042">మీరు ఈ <ph name="IDS_SHORT_PRODUCT_NAME" /> పరికరంలో డీబగ్గింగ్ ఫీచ‌ర్‌లను విజయవంతంగా ప్రారంభించారు.</translation>
<translation id="6315493146179903667">అన్నీ ముందుకు తీసుకెళ్లు</translation>
-<translation id="6316806695097060329">ఈ <ph name="SHORT_PRODUCT_NAME" /> పరికరం మీకు వెబ్‌లోని ఉత్తమ అనుభవాన్ని అందించేందుకు రూపొందించబడింది.</translation>
+<translation id="6316806695097060329">మీకు వెబ్‌లో అత్యుత్తమ అనుభవాన్ని అందించేందుకు ఈ <ph name="SHORT_PRODUCT_NAME" /> పరికరం రూపొందించబడింది.</translation>
<translation id="6317318380444133405">ఇప్పుడు మద్దతు లేదు.</translation>
<translation id="6317369057005134371">అప్లికేషన్‌ విండో కోసం వేచి ఉంది...</translation>
<translation id="6318407754858604988">డౌన్‌లోడ్ ప్రారంభించబడింది</translation>
<translation id="6322653941595359182">మీ Chromebook నుండి వచన సందేశాలను పంపండి మరియు స్వీకరించండి</translation>
<translation id="6324916366299863871">షార్ట్‌కట్‌ను సవరించండి</translation>
-<translation id="6325191661371220117">స్వీయ-ప్రారంభాన్ని నిలిపివేయి</translation>
+<translation id="6325191661371220117">ఆటో-లాంఛ్‌ను నిలిపివేయి</translation>
<translation id="6326175484149238433">Chrome నుండి తీసివేయండి</translation>
<translation id="6326855256003666642">సక్రియ కార్యాచరణల గణన</translation>
<translation id="6327785803543103246">వెబ్ ప్రాక్సీ స్వీయశోధన</translation>
-<translation id="6333064448949140209">పైల్ డీబగ్గింగ్ కోసం Googleకి పంపబడుతుంది</translation>
+<translation id="6333064448949140209">ఫైల్ డీబగ్గింగ్ కోసం Googleకు పంపబడుతుంది</translation>
<translation id="6336451774241870485">కొత్త ప్రైవేట్ ట్యాబ్</translation>
<translation id="6339668969738228384"><ph name="USER_EMAIL_ADDRESS" /> కోసం కొత్త ప్రొఫైల్‌ను సృష్టించు</translation>
<translation id="6340017061976355871">సర్వర్‌కి కనెక్ట్ చేయడం సాధ్యం కాలేదు. దయచేసి మీ నెట్‌వర్క్ కనెక్షన్‌ని తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి. సమస్య కొనసాగినట్లయితే, మీ Chromebookని పునఃప్రారంభించండి.</translation>
@@ -3534,12 +3543,12 @@
<translation id="6341850831632289108">మీ భౌతిక స్థానాన్ని గుర్తించండి</translation>
<translation id="6344170822609224263">నెట్‌వర్క్ కనెక్షన్‌ల జాబితాను యాక్సెస్ చేయండి</translation>
<translation id="6346310558342052870">యాక్సెస్ నియంత్రించబడింది</translation>
-<translation id="6349170655202535379">సమకాలీకరణ పని చేయడం లేదు. సైన్ అవుట్ చేసి, తిరిగి మళ్లీ సైన్ ఇన్ చేయండి.</translation>
+<translation id="6349170655202535379">సింక్‌ పని చేయడం లేదు. సైన్ అవుట్ చేసి, తిరిగి మళ్లీ సైన్ ఇన్ చేయండి.</translation>
<translation id="6351063337294363751">మీరు ఈ మెనూ నుండి మీ బ్రౌజింగ్ డేటాను తీసివేయవచ్చు</translation>
<translation id="6352773953037195952">అత్యధికం</translation>
<translation id="6354918092619878358">SECG దీర్ఘవృత్తాకార వక్రం secp256r1 (ANSI X9.62 prime256v1, NIST P-256గా కూడా పిలువబడతాయి)</translation>
<translation id="635609604405270300">పరికరాన్ని ఆన్ చేసి ఉంచండి</translation>
-<translation id="6356138805250111037">బ్రౌజర్‌లో మీరు టైప్ చేసేది Googleకు పంపడం ద్వారా సాంకేతికంగా అక్షరక్రమాన్ని తనిఖీ చేస్తుంది</translation>
+<translation id="6356138805250111037">బ్రౌజర్‌లో మీరు టైప్ చేసేది Googleకు పంపడం ద్వారా స్మార్ట్ స్పెల్‌చెక్‌ చేస్తుంది</translation>
<translation id="63566973648609420">మీ రహస్య పదబంధాన్ని కలిగి ఉన్న వారు మాత్రమే మీ ఎన్‌క్రిప్ట్ చేసిన‌ డేటాను చదవగలరు. రహస్య పదబంధం ఎవరికీ పంపబడదు లేదా Googleలో నిల్వ చేయబడదు. మీరు మీ రహస్య పదబంధాన్ని మర్చిపోతే లేదా ఈ సెట్టింగ్‌ను మార్చాలనుకుంటే, సింక్‌ను రీసెట్ చేయాల్సి ఉంటుంది. <ph name="BEGIN_LINK" />సింక్‌ను రీసెట్ చేయండి<ph name="END_LINK" />.</translation>
<translation id="6357619544108132570"><ph name="SHORT_PRODUCT_NAME" /> కుటుంబానికి స్వాగతం. ఇది సాధారణ కంప్యూటర్ కాదు.</translation>
<translation id="6361850914223837199">ఎర్రర్ వివరాలు:</translation>
@@ -3548,7 +3557,7 @@
<translation id="6365411474437319296">కుటుంబ సభ్యులు మరియు స్నేహితులను జోడించండి</translation>
<translation id="636850387210749493">ఎంటర్‌ప్రైజ్ నమోదు</translation>
<translation id="6370021412472292592">మానిఫెస్ట్‌ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
-<translation id="637062427944097960">ఈ పైల్ వేరే డెస్క్‌టాప్‌లో తెరవబడింది. దీన్ని వీక్షించడానికి <ph name="USER_NAME" /> (<ph name="MAIL_ADDRESS" />)కి తరలించండి.</translation>
+<translation id="637062427944097960">ఈ పైల్ వేరే డెస్క్‌టాప్‌లో తెరవబడింది. దీన్ని వీక్షించడానికి <ph name="USER_NAME" /> (<ph name="MAIL_ADDRESS" />)కు తరలించండి.</translation>
<translation id="6374077068638737855">Iceweasel</translation>
<translation id="6374469231428023295">మళ్లీ ప్రయత్నించు</translation>
<translation id="6377268785556383139">'<ph name="SEARCH_TEXT" />' అనే దానికి 1 ఫలితం మాత్రమే లభించింది</translation>
@@ -3557,7 +3566,7 @@
<translation id="6385543213911723544">సైట్‌లు కుక్కీ డేటాను సేవ్ చేయగలవు. చదవగలవు</translation>
<translation id="6386099547750337629">ఇది అనూహ్యమైనదైతే, దయచేసి మద్దతును సంప్రదించండి.</translation>
<translation id="6388429472088318283">భాషలను వెతకండి</translation>
-<translation id="6390799748543157332">మీరు ఈ విండో‌లో వీక్షించే పేజీలు బ్రౌజర్ చరిత్రలో కనిపించవు. తెరవబడిన అన్ని అతిథి విండోలను మీరు మూసివేసిన తర్వాత అవి కంప్యూటర్‌లో కుక్కీల వంటి ఇతర జాడలను వదిలిపెట్టవు. అయితే, మీరు డౌన్‌లోడ్ చేసే ఫైల్‌లు భద్రపరచబడతాయి.</translation>
+<translation id="6390799748543157332">మీరు ఈ విండో‌లో వీక్షించే పేజీలు బ్రౌజర్ చరిత్రలో కనిపించవు. తెరవబడిన అన్ని అతిథి విండోలను మీరు మూసివేసిన తర్వాత అవి కంప్యూటర్‌లో కుక్కీల వంటి ఇతర జాడలను వదిలిపెట్టవు. అయితే, మీరు డౌన్‌లోడ్ చేసే ఫైల్స్ భద్రపరచబడతాయి.</translation>
<translation id="6390994422085833176">సెటప్ పూర్తయిన తర్వాత సమకాలీకరణ మరియు వ్యక్తిగతీకరణ ఫీచర్‌లను సమీక్షించండి</translation>
<translation id="6395575651121294044"><ph name="NUMBER_OF_FILES" /> అంశాలు</translation>
<translation id="6397094776139756010">సమకాలీకరణ మరియు వ్యక్తిగతీకరణ ఎంపికలు</translation>
@@ -3579,9 +3588,9 @@
<translation id="6412931879992742813">కొత్త అజ్ఞాత విండో</translation>
<translation id="6415900369006735853">మీ ఫోన్ ద్వారా ఇంటర్నెట్‌కు కనెక్ట్ అవ్వండి</translation>
<translation id="6417265370957905582">Google సహాయకం</translation>
-<translation id="6418160186546245112">మునుపు ఇన్‌స్టాల్ చేసిన <ph name="IDS_SHORT_PRODUCT_NAME" /> సంస్కరణకు తిరిగి మారుస్తోంది</translation>
+<translation id="6418160186546245112">మునుపు ఇన్‌స్టాల్ చేసిన <ph name="IDS_SHORT_PRODUCT_NAME" /> వెర్షన్‌కు తిరిగి మారుస్తోంది</translation>
<translation id="6418481728190846787">అన్ని యాప్‌ల కోసం యాక్సెస్‌ను శాశ్వతంగా తీసివేయి</translation>
-<translation id="6418511932144861495">కీలకమైన అప్‌డేట్‌ని ఇన్‌స్టాల్ చేయండి</translation>
+<translation id="6418511932144861495">కీలకమైన అప్‌డేట్‌ను ఇన్‌స్టాల్ చేయండి</translation>
<translation id="6419288379019356534">ఈ పరికరం <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />.ద్వారా నిర్వహించబడుతోంది.
<ph name="LINE_BREAK" />
@@ -3591,7 +3600,7 @@
<translation id="642469772702851743">ఈ (SN: <ph name="SERIAL_NUMBER" />) పరికరం యజమానిచే లాక్ చేయబడింది.</translation>
<translation id="6426200009596957090">ChromeVox సెట్టింగ్‌లను తెరువు</translation>
<translation id="6429384232893414837">అప్‌డేట్‌లో ఎర్రర్</translation>
-<translation id="6430814529589430811">Base64-ఎన్‌కోడ్ చేసిన ASCII, సింగిల్ సర్టిఫికెట్</translation>
+<translation id="6430814529589430811">Base64-ఎన్‌కోడ్ చేసిన ASCII, ఒక్క సర్టిఫికెట్</translation>
<translation id="6431347207794742960"><ph name="PRODUCT_NAME" />ఈ కంప్యూటర్ వినియోగదారులందరికీ ఆటోమేటిక్ అప్‌డేట్‌లను సెట్ చేస్తుంది.</translation>
<translation id="6434309073475700221">తొలగించు</translation>
<translation id="6436164536244065364">వెబ్ స్టోర్‌లో వీక్షించండి</translation>
@@ -3608,7 +3617,7 @@
<translation id="6455264371803474013">కొన్ని నిర్దిష్ట సైట్‌లలో మాత్రమే</translation>
<translation id="6455894534188563617">&amp;కొత్త ఫోల్డర్</translation>
<translation id="6456394469623773452">శ్రేష్టమైనది</translation>
-<translation id="6456631036739229488">Smart Lock ఫోన్ మారింది. Smart Lockను అప్‌డేట్ చేయడానికి మీ పాస్‌వర్డ్‌ను నమోదు చేయండి. తర్వాతిసారి, మీ ఫోన్ మీ <ph name="DEVICE_TYPE" />ను అన్‌లాక్ చేస్తుంది. సెట్టింగ్‌లలో Smart Lockను ఆఫ్ చేయండి.</translation>
+<translation id="6456631036739229488">Smart Lock ఫోన్ మారింది. Smart Lockను అప్‌డేట్ చేయడానికి మీ పాస్‌వర్డ్‌ను నమోదు చేయండి. తదుపరిసారి, మీ ఫోన్ మీ <ph name="DEVICE_TYPE" />ను అన్‌లాక్ చేస్తుంది. సెట్టింగ్‌లలో Smart Lockను ఆఫ్ చేయండి.</translation>
<translation id="645705751491738698">JavaScriptను నిరోధించడాన్ని కొనసాగించు</translation>
<translation id="6458701200018867744">అప్‌లోడ్ విఫలమైంది (<ph name="WEBRTC_LOG_UPLOAD_TIME" />).</translation>
<translation id="6459488832681039634">కనుగొనడానికి ఎంపికను ఉపయోగించండి</translation>
@@ -3655,16 +3664,17 @@
<translation id="6527303717912515753">భాగస్వామ్యం చేయి</translation>
<translation id="6528513914570774834">ఈ నెట్‌వర్క్‌ని ఉపయోగించడానికి ఈ పరికరం యొక్క ఇతర వినియోగదారులను అనుమతించండి</translation>
<translation id="652948702951888897">Chrome చరిత్ర</translation>
+<translation id="6530186581263215931">ఈ సెట్టింగ్‌లు మీ నిర్వాహకుడి ద్వారా అమలు చేయబడ్డాయి</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" />ని సమకాలీకరిస్తోంది...</translation>
<translation id="6531282281159901044">అపాయకరమైన ఫైల్‌ను అలాగే ఉంచు</translation>
<translation id="6532101170117367231">Google డిస్క్‌‌కు సేవ్ చేయండి</translation>
<translation id="654039047105555694"><ph name="BEGIN_BOLD" />గమనిక:<ph name="END_BOLD" /> డేటా సేకరణ వలన పనితీరు తగ్గవచ్చు, అందువల్ల‌ మీరు చేస్తున్నది మీకు తెలిసినప్పుడు లేదా ఇలా చేయాలని మీకు చెప్పినప్పుడు మాత్రమే ప్రారంభించండి.</translation>
-<translation id="654233263479157500">నావిగేషన్ ఎర్రర్‌లను పరిష్కరించడానికి సహాయం కోసం వెబ్ సేవను ఉపయోగించు</translation>
+<translation id="654233263479157500">నావిగేషన్ ఎర్రర్‌లను పరిష్కరించడానికి సహాయం కోసం వెబ్ సేవను ఉపయోగించండి</translation>
<translation id="6544215763872433504">మీ కోసం Google సమర్పిత వెబ్ బ్రౌజర్</translation>
<translation id="6545665334409411530">పునరావృత రేటు</translation>
<translation id="6545834809683560467">చిరునామా బార్‌లో లేదా యాప్ లాంచర్ శోధన పెట్టెలో టైప్ చేసే శోధనలను మరియు URLలను పూర్తి చేయడంలో సహాయకరంగా ఉండటానికి సూచన సేవను ఉపయోగించండి</translation>
<translation id="6547316139431024316">ఈ పొడిగింపు కోసం మళ్లీ హెచ్చరించవద్దు</translation>
-<translation id="6547354035488017500">కనీసం 512 MB స్థలాన్ని ఖాళీగా ఉంచండి, లేదంటే మీ పరికరం ప్రతిస్పందనరహితం అవుతుంది. స్థలాన్ని ఖాళీ చేయడానికి, పరికర నిల్వ నుండి ఫైల్‌లను తొలగించండి.</translation>
+<translation id="6547354035488017500">కనీసం 512 MB స్థలాన్ని ఖాళీగా ఉంచండి, లేదంటే పరికరం ఇక స్పందించదు. స్థలాన్ని ఖాళీ చేయడానికి, పరికర నిల్వ నుండి ఫైల్‌లను తొలగించండి.</translation>
<translation id="6549689063733911810">ఇటీవల</translation>
<translation id="6550675742724504774">ఎంపికలు</translation>
<translation id="6551508934388063976">ఆదేశం అందుబాటులో లేదు. కొత్త విండోను తెరవడానికి control-N నొక్కండి.</translation>
@@ -3684,7 +3694,7 @@
<translation id="6577284282025554716">డౌన్‌లోడ్ రద్దు చేయబడింది: <ph name="FILE_NAME" /></translation>
<translation id="6578664922716508575">మీ Google వినియోగదారు పేరు మరియు పాస్‌వర్డ్‌తో సింక్ చేసిన‌ పాస్‌వర్డ్‌లను ఎన్‌క్రిప్ట్ చేయండి</translation>
<translation id="6579705087617859690"><ph name="WINDOW_TITLE" /> - డెస్క్‌టాప్‌ కంటెంట్‌ షేర్ చేయబడింది</translation>
-<translation id="6580151766480067746">ARC సంస్కరణ</translation>
+<translation id="6580151766480067746">ARC వెర్షన్</translation>
<translation id="6581162200855843583">Google డిస్క్ లింక్</translation>
<translation id="6582080224869403177">మీ భద్రతను అప్‌గ్రేడ్ చేయడానికి మీ <ph name="DEVICE_TYPE" />ని రీసెట్ చేయండి</translation>
<translation id="6584878029876017575">Microsoft Lifetime Signing</translation>
@@ -3732,18 +3742,18 @@
<translation id="6647228709620733774">Netscape సర్టిఫికెట్ అధికార రద్దు URL</translation>
<translation id="6647838571840953560">ప్రస్తుతం <ph name="CHANNEL_NAME" />లో ఉన్నారు</translation>
<translation id="6648051959475508072">భద్రతా కీ యాక్టివేట్ చేయబడింది...</translation>
-<translation id="6648911618876616409">ఒక ముఖ్యమైన అప్‌డేట్ ఇన్‌స్టాల్ కావడానికి సిద్ధంగా ఉంది. ప్రారంభించడం కోసం సైన్ ఇన్ చేయండి.</translation>
+<translation id="6648911618876616409">ఒక ముఖ్యమైన అప్‌డేట్ ఇన్‌స్టాల్ కావడానికి సిద్ధంగా ఉంది. ప్రారంభించడానికి సైన్ ఇన్ చేయండి.</translation>
<translation id="6649018507441623493">ఒక సెకను వేచి ఉండండి…</translation>
<translation id="6649563841575838401">ఆర్కైవ్ ఫార్మాట్‌కు మద్దతు లేదు, లేదా ఫైల్ పాడైంది.</translation>
<translation id="665061930738760572">&amp;క్రొత్త విండోలో తెరువు</translation>
<translation id="6651237644330755633">వెబ్‌సైట్‌లను గుర్తించడానికి ఈ ప్రమాణపత్రాన్ని విశ్వసిస్తుంది</translation>
-<translation id="665355505818177700">Chrome <ph name="MS_AD_NAME" /> ఏకీకరణకు కేవలం x86_64 ప్లాట్‌ఫారమ్‌లలో మాత్రమే మద్దతు ఉంది. ఈ పనితనం ARM లేదా x86 ప్లాట్‌ఫారమ్ కంటే ఉన్నత స్థాయిలో రూపొందించబడిన Chromebookలకు పని చేయదు.</translation>
+<translation id="665355505818177700">Chrome <ph name="MS_AD_NAME" /> ఏకీకరణకు కేవలం x86_64 ప్లాట్‌ఫారమ్‌లలో మాత్రమే మద్దతు ఉంది. ఈ కార్య‌శీల‌త‌ ARM లేదా x86 ప్లాట్‌ఫారమ్ కంటే ఉన్నత స్థాయిలో రూపొందించబడిన Chromebookలకు పని చేయదు.</translation>
<translation id="6655190889273724601">డెవలపర్ మోడ్</translation>
<translation id="6655458902729017087">ఖాతాలను దాచు</translation>
<translation id="6657585470893396449">పాస్‌వర్డ్</translation>
<translation id="6659213950629089752">ఈ పేజీ "<ph name="NAME" />" పొడిగింపు ద్వారా జూమ్ చేయబడింది</translation>
<translation id="6659594942844771486">ట్యాబ్</translation>
-<translation id="6664237456442406323">దురదృష్టవశాత్తూ, మీ కంప్యూటర్ తప్పుగా ఆకృతి చేయబడిన హార్డ్‌వేర్ IDతో కాన్ఫిగర్ చేయబడింది. ఇది తాజా భద్రతా పరిష్కారాలతో అప్‌డేట్ కానివ్వకుండా Chrome OSని నిరోధిస్తుంది, తద్వారా మీ కంప్యూటర్ <ph name="BEGIN_BOLD" />హానికరమైన దాడులకు గురి కావచ్చు<ph name="END_BOLD" />.</translation>
+<translation id="6664237456442406323">దురదృష్టవశాత్తూ, తప్పుగా ఫార్మాట్ చేయబడిన హార్డ్‌వేర్ IDతో మీ కంప్యూటర్ కాన్ఫిగర్ చేయబడింది. Chrome OSను తాజా భద్రతా పరిష్కారాలతో అప్‌డేట్ అవ్వకుండా ఇది నిరోధిస్తుంది, తద్వారా మీ కంప్యూటర్ <ph name="BEGIN_BOLD" />హానికరమైన దాడులకు గురి కావచ్చు<ph name="END_BOLD" />.</translation>
<translation id="6664774537677393800">మీ ప్రొఫైల్‌ను తెరుస్తున్నప్పుడు ఏదో తప్పు జరిగింది. దయచేసి సైన్ అవుట్ చేసి, మళ్లీ సైన్ ఇన్ చేయండి.</translation>
<translation id="6673391612973410118"><ph name="PRINTER_MAKE_OR_MODEL" /> (USB)</translation>
<translation id="667517062706956822">ఈ పేజీని Google <ph name="SOURCE_LANGUAGE" /> నుండి <ph name="TARGET_LANGUAGE" />కి అనువదించాలని మీరు కోరుకుంటున్నారా?</translation>
@@ -3758,14 +3768,14 @@
<translation id="6686490380836145850">కుడివైపు ట్యాబ్‌లను మూసివేయి</translation>
<translation id="6686817083349815241">మీ పాస్‌వర్డ్‌ను సేవ్ చేయండి</translation>
<translation id="6690659332373509948">ఈ ఫైల్‌ను అన్వయించడం సాధ్యపడలేదు: <ph name="FILE_NAME" /></translation>
-<translation id="6690751852586194791">ఈ పరికరానికి జోడించడానికి పర్యవేక్షించబడే వినియోగదారుని ఎంచుకోండి.</translation>
+<translation id="6690751852586194791">ఈ పరికరానికి జోడించడానికి పర్యవేక్షించబడే వినియోగదారును ఎంచుకోండి.</translation>
<translation id="6691331417640343772">Google డాష్‌బోర్డ్‌లో సింక్ చేయ‌బ‌డిన‌ డేటాను నిర్వహించండి</translation>
<translation id="6691936601825168937">&amp;ఫార్వార్డ్ చెయ్యి</translation>
<translation id="6697492270171225480">పేజీ కనుగొనబడనప్పుడు అటువంటి పేజీల కోసం సూచనలను చూపుతుంది</translation>
<translation id="6697690052557311665">షేర్ చేయడానికి, ఫైల్‌లు యాప్‌లో ఫోల్డర్‌పై కుడి క్లిక్ చేసి, ఆపై "Linuxతో షేర్ చేయి" ఎంచుకోండి.</translation>
<translation id="6698810901424468597"><ph name="WEBSITE_1" /> మరియు <ph name="WEBSITE_2" />లో ఉన్న మీ డేటాను చదవడం మరియు మార్చడం</translation>
<translation id="6700480081846086223"><ph name="HOST_NAME" />ని ప్రసారం చేయండి</translation>
-<translation id="6701535245008341853">ప్రొఫైల్‌ని పొందడం సాధ్యం కాలేదు.</translation>
+<translation id="6701535245008341853">ప్రొఫైల్‌ను పొందడం సాధ్యం కాలేదు.</translation>
<translation id="6702639462873609204">&amp;సవరించు...</translation>
<translation id="6706210727756204531">పరిధి</translation>
<translation id="6707389671160270963">SSL క్లయింట్ సర్టిఫికెట్</translation>
@@ -3776,8 +3786,8 @@
<translation id="6718273304615422081">జిప్ చేస్తోంది...</translation>
<translation id="6721678857435001674">మీ భద్రతా కీ యొక్క తయారీదారు బ్రాండ్ పేరు మరియు మోడల్‌ని చూడండి</translation>
<translation id="6721972322305477112">&amp;ఫైల్</translation>
-<translation id="672213144943476270">దయచేసి అతిథి లాగా బ్రౌజ్ చేయబోయే ముందు మీ ప్రొఫైల్‌ను అన్‌లాక్ చేయండి.</translation>
-<translation id="6723354935081862304">Google డాక్స్ మరియు ఇతర క్లౌడ్ గమ్యస్థానాలకు ముద్రించండి. Google క్లౌడ్ ప్రింట్‌కు ముద్రించడానికి <ph name="BEGIN_LINK" />సైన్ ఇన్ చేయండి<ph name="END_LINK" />.</translation>
+<translation id="672213144943476270">అతిథి లాగా బ్రౌజ్ చేయబోయే ముందు దయచేసి మీ ప్రొఫైల్‌ను అన్‌లాక్ చేయండి.</translation>
+<translation id="6723354935081862304">Google డాక్స్ మరియు ఇతర క్లౌడ్ గమ్యస్థానాలలో ముద్రించండి. Google క్లౌడ్ ప్రింట్‌కు ముద్రించడానికి <ph name="BEGIN_LINK" />సైన్ ఇన్ చేయండి<ph name="END_LINK" />.</translation>
<translation id="6723661294526996303">బుక్‌మార్క్‌లను మరియు సెట్టింగులను దిగుమతి చెయ్యి...</translation>
<translation id="6723839937902243910">పవర్</translation>
<translation id="6725073593266469338">UI సేవ</translation>
@@ -3789,9 +3799,9 @@
<translation id="6736045498964449756">అయ్యో, పాస్‌వర్డ్‌లు సరిపోలలేదు!</translation>
<translation id="6736243959894955139">చిరునామా</translation>
<translation id="6736329909263487977"><ph name="ISSUED_BY" /> [<ph name="ISSUED_TO" />]</translation>
-<translation id="6739923123728562974">డెస్క్‌టాప్ షార్ట్‌కట్‌ను చూపు</translation>
+<translation id="6739923123728562974">డెస్క్‌టాప్ షార్ట్‌క‌ట్‌ను చూపు</translation>
<translation id="6740234557573873150"><ph name="FILE_NAME" /> పాజ్ చేయబడింది</translation>
-<translation id="6742339027238151589">స్క్రిప్ట్‌కి ప్రాప్యత చేయదగినది</translation>
+<translation id="6742339027238151589">స్క్రిప్ట్‌కు యాక్సెస్ చేయదగినది</translation>
<translation id="6745592621698551453">ఇప్పుడే అప్‌డేట్ చేయి</translation>
<translation id="6746124502594467657">క్రిందికి తరలించు</translation>
<translation id="674632704103926902">నొక్కి లాగడాన్ని ప్రారంభించు</translation>
@@ -3819,19 +3829,19 @@
<translation id="6790497603648687708"><ph name="EXTENSION_NAME" /> రిమోట్ విధానంలో జోడించబడింది</translation>
<translation id="6790820461102226165">వ్యక్తిని జోడించు...</translation>
<translation id="6792072150955115067"><ph name="APP_NAME" /> మీ స్క్రీన్‌పై ఉన్న కంటెంట్‌లను <ph name="TARGET_NAME" />తో షేర్ చేయాలనుకుంటోంది. మీరు షేర్ చేయాలనుకుంటున్న వాటిని ఎంచుకోండి.</translation>
-<translation id="6793604637258913070">వచన కేరెట్‌ కనిపించినప్పుడు లేదా అది కదలికలో ఉన్నప్పుడు, దాన్ని హైలైట్ చేస్తుంది</translation>
+<translation id="6793604637258913070">వచన కేరెట్‌ కనిపించినప్పుడు లేదా అది కదలికలో ఉన్నప్పుడు, దానిని హైలైట్ చేస్తుంది</translation>
<translation id="6797493596609571643">అయ్యో, ఏదో తప్పు జరిగింది.</translation>
<translation id="6798578729981748444">దిగుమతిని పూర్తి చేయాలంటే, అన్ని Firefox విండోలను మూసివేయండి.</translation>
<translation id="6798780071646309401">caps lock ఆన్‌లో ఉంది</translation>
-<translation id="6798954102094737107">ప్లగిన్: <ph name="PLUGIN_NAME" /></translation>
+<translation id="6798954102094737107">ప్లగ్ఇన్‌: <ph name="PLUGIN_NAME" /></translation>
<translation id="6801435275744557998">టచ్‌స్క్రీన్‌ను క్రమాంకనం చేయి</translation>
<translation id="6802031077390104172"><ph name="USAGE" /> (<ph name="OID" />)</translation>
<translation id="6804671422566312077">అన్ని బుక్‌మార్క్‌లను &amp;క్రొత్త విండోలో తెరువు</translation>
<translation id="6805038906417219576">సరే</translation>
-<translation id="6805647936811177813">దయచేసి <ph name="HOST_NAME" /> నుండి క్లయింట్ స‌ర్టిఫికెట్‌ను దిగుమతి చేయ‌డానికి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చేయండి.</translation>
+<translation id="6805647936811177813"><ph name="HOST_NAME" /> నుండి క్లయింట్ సర్టిఫికెట్‌ను దిగుమతి చేయడానికి, దయచేసి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చేయండి.</translation>
<translation id="680572642341004180"><ph name="SHORT_PRODUCT_OS_NAME" />లో RLZ ట్రాకింగ్‌ను ప్రారంభించు.</translation>
<translation id="6806699711453372963">Linux షేరింగ్‌ని నిర్వహించండి</translation>
-<translation id="6810613314571580006">నిల్వ చేసిన ఆధారాలను ఉపయోగించి ఆటోమేటిక్‌గా వెబ్‌సైట్‌లకు సైన్ ఇన్ చేస్తుంది. లక్షణాన్ని నిలిపివేసినప్పుడు, మీరు వెబ్‌సైట్‌కు సైన్ ఇన్ చేసే ప్రతిసారి నిర్ధారణ కోసం మిమ్మల్ని అడుగుతుంది.</translation>
+<translation id="6810613314571580006">నిల్వ చేసిన ఆధారాలను ఉపయోగించి ఆటోమేటిక్‌గా వెబ్‌సైట్‌లకు సైన్ ఇన్ చేస్తుంది. ఫీచర్‌ను నిలిపివేసినప్పుడు, మీరు వెబ్‌సైట్‌కు సైన్ ఇన్ చేసే ప్రతిసారి నిర్ధారణ కోసం మిమ్మల్ని అడుగుతుంది.</translation>
<translation id="6810768462515084623">అయ్యో! మీ పాస్‌వర్డ్ గడువు ముగిసింది. దయచేసి మరో పరికరంలో దానిని పునరుద్ధరించి, ఆపై మళ్లీ ప్రయత్నించండి.</translation>
<translation id="6811034713472274749">పేజీ వీక్షించడానికి సిద్ధంగా ఉంది</translation>
<translation id="6812349420832218321"><ph name="PRODUCT_NAME" /> రూట్‌గా రన్ చేయలేదు.</translation>
@@ -3839,20 +3849,20 @@
<translation id="6817174620439930047">MIDI పరికరాలను యాక్సెస్ చేయడానికి సిస్టమ్ విశిష్ట సందేశాలను సైట్ ఉపయోగించాలనుకున్నప్పుడు అడుగు (సిఫార్సు చేయబడింది)</translation>
<translation id="6820687829547641339">Gzip కుదించిన tar ఆర్కైవ్</translation>
<translation id="682123305478866682">డెస్క్‌టాప్‌ను ప్రసారం చేయండి</translation>
-<translation id="6823506025919456619">మీరు మీ పరికరాలను చూడటానికి Chromeకి సైన్ ఇన్ చేయాలి</translation>
+<translation id="6823506025919456619">మీరు మీ పరికరాలను చూడటానికి Chromeకు సైన్ ఇన్ చేయాలి</translation>
<translation id="6824564591481349393">&amp;ఇమెయిల్ చిరునామాను కాపీ చెయ్యి</translation>
<translation id="6824584962142919697">&amp;మూలకాలను పర్యవేక్షించు</translation>
<translation id="6825184156888454064">పేరు ద్వారా క్రమబద్ధీకరించు</translation>
<translation id="6826872289184051766">USB ద్వారా ధృవీకరించు</translation>
<translation id="6827236167376090743">ఈ వీడియో నిరంతరంగా ప్లే అవుతూనే ఉంటుంది.</translation>
-<translation id="6828153365543658583">క్రింది వినియోగదారులకు సైన్-ఇన్‌ని నిరోధించు:</translation>
+<translation id="6828153365543658583">కింది వినియోగదారులకు మాత్రమే సైన్-ఇన్‌ను అనుమతించు:</translation>
<translation id="6828860976882136098">వినియోగదారులందరి కోసం ఆటోమేటిక్ అప్‌డేట్‌లను సెటప్ చేయడం విఫలమైంది (ప్రీఫ్లయిట్ అమలు ఎర్రర్: <ph name="ERROR_NUMBER" />)</translation>
-<translation id="6829250331733125857">మీ <ph name="DEVICE_TYPE" />తో సహాయం పొందండి.</translation>
+<translation id="6829250331733125857">మీ <ph name="DEVICE_TYPE" /> గురించి సహాయం పొందండి.</translation>
<translation id="682971198310367122">Google గోప్యతా విధానం</translation>
<translation id="6831043979455480757">అనువదించు</translation>
<translation id="683373380308365518">స్మార్ట్ మరియు సురక్షిత బ్రౌజర్‌కు మారండి</translation>
<translation id="6835762382653651563">దయచేసి మీ <ph name="DEVICE_TYPE" />ని అప్‌డేట్ చేయడానికి ఇంటర్నెట్‌కి కనెక్ట్ చేయండి.</translation>
-<translation id="6839225236531462745">సర్టిఫికెట్ తొలగింపు ఎర్రర్</translation>
+<translation id="6839225236531462745">ప్రమాణపత్రం తొలగింపు లోపం</translation>
<translation id="6840155290835956714">పంపే ముందు అడగాలి</translation>
<translation id="6840184929775541289">ప్రమాణపత్రం అధికారం కాదు</translation>
<translation id="6841186874966388268">లోపాలు</translation>
@@ -3878,11 +3888,11 @@
<translation id="6883319974225028188">అయ్యో! పరికర కాన్ఫిగరేషన్‌ను సేవ్ చేయడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="6885771755599377173">సిస్టమ్ సమాచార ప్రివ్యూ</translation>
<translation id="6886476658664859389">NFC భద్రతా కీ</translation>
-<translation id="6886871292305414135">లింక్‌ను క్రొత్త &amp;ట్యాబ్‌లో తెరువు</translation>
+<translation id="6886871292305414135">కొత్త &amp;ట్యాబ్‌లో లింక్‌ను తెరువు</translation>
<translation id="6892812721183419409">లింక్‌ను <ph name="USER" /> తరపున తెరువు</translation>
<translation id="6895032998810961280">ఈ క్లీన్అప్ సమయంలో మీ కంప్యూటర్‌లో గుర్తించిన హానికరమైన సాఫ్ట్‌వేర్, సిస్టమ్ సెట్టింగ్‌లు మరియు ప్రాసెస్‌ల గురించి Googleకు వివరాలను నివేదించండి</translation>
<translation id="6896758677409633944">కాపీ చెయ్యి</translation>
-<translation id="6898440773573063262">కియోస్క్ యాప్‌లను ఇప్పుడు ఈ పరికరంలో ఆటోమేటిక్‌గా ప్రారంభించడానికి కాన్ఫిగర్ చేయవచ్చు.</translation>
+<translation id="6898440773573063262">కియోస్క్ యాప్‌లను ఇప్పుడు ఈ పరికరంలో ఆటోమేటిక్‌గా ప్రారంభించగలిగేలా కాన్ఫిగర్ చేయవచ్చు.</translation>
<translation id="6898699227549475383">సంస్థ (O)</translation>
<translation id="6900284862687837908">బ్యాక్‌గ్రౌండ్ యాప్: <ph name="BACKGROUND_APP_URL" /></translation>
<translation id="6902066522699286937">వాయిస్ యొక్క ప్రివ్యూ</translation>
@@ -3910,7 +3920,7 @@
<ph name="LINE_BREAK1" />
<ph name="FILE_COUNT" /> కనుగొనబడ్డాయి</translation>
<translation id="693807610556624488">వ్రాసే చర్య దీనికి సంబంధించిన లక్షణం గరిష్ట పొడవును మించిపోయింది: "<ph name="DEVICE_NAME" />".</translation>
-<translation id="6941937518557314510">దయచేసి మీ ప్రమాణపత్రంతో <ph name="HOST_NAME" />ని ప్రమాణీకరించడానికి <ph name="TOKEN_NAME" />కి సైన్ ఇన్ చెయ్యండి.</translation>
+<translation id="6941937518557314510">మీ సర్టిఫికెట్‌తో <ph name="HOST_NAME" />ను ప్రమాణీకరించడానికి దయచేసి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చేయండి.</translation>
<translation id="6943176775188458830">ముద్రణను రద్దు చేయి</translation>
<translation id="6943836128787782965">HTTP పొందడంలో విఫలమైంది</translation>
<translation id="6945221475159498467">ఎంచుకోండి</translation>
@@ -3945,7 +3955,7 @@
<translation id="6980462514016882061">శోధన, ప్రకటనలు మరియు ఇతర Google సేవలను వ్యక్తిగతీకరించడం కోసం Google మీ బ్రౌజింగ్ చరిత్రను ఉపయోగించవచ్చు</translation>
<translation id="6981982820502123353">యాక్సెస్ సామర్థ్యం</translation>
<translation id="6983783921975806247">రిజిస్టర్ చేసిన OID</translation>
-<translation id="6984299437918708277">సైన్-ఇన్ స్క్రీన్‌లో మీ ఖాతా కోసం ప్రదర్శించడానికి చిత్రాన్ని ఎంచుకోండి</translation>
+<translation id="6984299437918708277">సైన్-ఇన్ స్క్రీన్‌లో మీ ఖాతాకు ప్రదర్శించడానికి చిత్రాన్ని ఎంచుకోండి</translation>
<translation id="6985235333261347343">Microsoft Key Recovery Agent</translation>
<translation id="698524779381350301">కింది సైట్‌లలో యాక్సెస్‌ను ఆటోమేటిక్‌గా అనుమతించు</translation>
<translation id="6985607387932385770">ప్రింటర్‌లు</translation>
@@ -3956,7 +3966,7 @@
<translation id="6998711733709403587"><ph name="SELCTED_FOLDERS_COUNT" /> ఫోల్డర్‌లు ఎంచుకోబడ్డాయి</translation>
<translation id="6998793565256476099">వీడియో సమావేశం కోసం పరికరాన్ని నమోదు చేయండి</translation>
<translation id="7000347579424117903">Ctrl, Alt, లేదా Search చేర్చండి</translation>
-<translation id="7002055706763150362">Chromebook కోసం Smart Lockని సెటప్ చేయడానికి, Google ఇది మీరే అని నిర్ధారించుకోవాలి—కనుక ప్రారంభించడానికి మీ పాస్‌వర్డ్‌ను టైప్ చేయండి.</translation>
+<translation id="7002055706763150362">Chromebook కోసం Smart Lockను సెటప్ చేయడానికి, ఇది మీరేనని Google నిర్ధారించుకోవాలి—ప్రారంభించడానికి మీ పాస్‌వర్డ్‌ను టైప్ చేయండి.</translation>
<translation id="7002454948392136538">ఈ పర్యవేక్షించబడే వినియోగదారు కోసం నిర్వాహకుని ఎంచుకోండి</translation>
<translation id="7003339318920871147">వెబ్ డేటాబేస్‌లు</translation>
<translation id="7003723821785740825">మీ పరికరాన్ని అన్‌లాక్ చేయడానికి వేగవంతమైన మార్గాన్ని సెటప్ చేయండి</translation>
@@ -3974,12 +3984,11 @@
<translation id="7018275672629230621">మీ బ్రౌజింగ్ చరిత్రని చదవడం మరియు మార్చడం</translation>
<translation id="7019805045859631636">వేగంగా</translation>
<translation id="7022562585984256452">మీ హోమ్ పేజీ సెట్ చేయబడింది.</translation>
-<translation id="702384510542929236">కొంత సిస్టమ్ సమాచారం, పేజీ కంటెంట్‌ను Googleకి వివరాలను అజ్ఞాతంగా పంపుతుంది</translation>
<translation id="7025190659207909717">మొబైల్ డేటా సేవ నిర్వహణ</translation>
<translation id="7027125358315426638">డేటాబేస్ పేరు:</translation>
<translation id="7029809446516969842">పాస్‌వర్డ్‌లు</translation>
<translation id="7031962166228839643">TPM అనేది సిద్ధం అవుతోంది, దయచేసి వేచి ఉంచండి (దీనికి కొన్ని నిమిషాల సమయం పట్టవచ్చు)...</translation>
-<translation id="7037509989619051237">వచనం యొక్క ప్రివ్యూ</translation>
+<translation id="7037509989619051237">ప్రివ్యూ చేయవలసిన వచనం</translation>
<translation id="7039326228527141150"><ph name="VENDOR_NAME" /> అందించిన USB పరికరాలకు యాక్సెస్</translation>
<translation id="7039912931802252762">Microsoft Smart Card Logon</translation>
<translation id="7040138676081995583">దీనితో తెరువు...</translation>
@@ -3994,12 +4003,12 @@
<translation id="7055152154916055070">మళ్లింపు బ్లాక్ చేయబడింది:</translation>
<translation id="7056526158851679338">&amp;పరికరాలను పర్యవేక్షించు</translation>
<translation id="7059858479264779982">స్వీయ-ప్రారంభానికి సెట్ చేయి</translation>
-<translation id="7059893117020417984">ప్రైవేట్‌గా బ్రౌజ్ చేయాలంటే, అజ్ఞాత విండోను తెరవడం కోసం చుక్కల చిహ్నం మెనూను క్లిక్ చేయండి.</translation>
+<translation id="7059893117020417984">ప్రైవేట్‌గా బ్రౌజ్ చేయాలంటే, అజ్ఞాత విండోని తెరవడం కోసం చుక్కల చిహ్నం మెనూని క్లిక్ చేయండి.</translation>
<translation id="7062222374113411376">డేటాను పంపడం మరియు స్వీకరించడం పూర్తి చేయడానికి ఇటీవల మూసివేసిన సైట్‌లను అనుమతించు (సిఫార్సు చేయబడింది)</translation>
<translation id="7063129466199351735">సత్వరమార్గాలను ప్రాసెస్ చేస్తోంది...</translation>
<translation id="7063311912041006059">ప్రశ్న యొక్క ప్రదేశంలో <ph name="SPECIAL_SYMBOL" />తో URL</translation>
<translation id="7063957500469387217">Google క్లౌడ్ ప్రింట్‌లో ప్రింటర్‌లను సెటప్ చేయండి లేదా నిర్వహించండి.</translation>
-<translation id="7065223852455347715">ఈ పరికరం వ్యాపార నమోదుని నిరోధించే మోడ్‌లో లాక్ చేయబడింది. మీరు పరికరాన్ని నమోదు చేయాలనుకుంటే ముందుగా పరికర పునరుద్ధరణను పరిశీలించాలి.</translation>
+<translation id="7065223852455347715">వ్యాపార నమోదును నిరోధించే మోడ్‌లో ఈ పరికరం లాక్ చేయబడింది. మీరు పరికరాన్ని నమోదు చేయాలనుకుంటే ముందుగా పరికరాన్ని పునరుద్ధరించాలి.</translation>
<translation id="7065534935986314333">సిస్టమ్ గురించి</translation>
<translation id="706626672220389329">షేర్‌ను మౌంట్ చేయడంలో ఎర్రర్ ఏర్పడింది. పేర్కొన్న షేర్ ఇప్పటికే మౌంట్ చేయబడింది.</translation>
<translation id="7066944511817949584">"<ph name="DEVICE_NAME" />"కి కనెక్ట్ చేయడం విఫలమైంది.</translation>
@@ -4017,9 +4026,9 @@
<translation id="708278670402572152">స్కానింగ్‌ను ప్రారంభించడం కోసం డిస్‌కనెక్ట్ చేయండి</translation>
<translation id="7084192839369222683">కేవలం ముఖ్యమైన కంటెంట్‌ను అమలు చేయి</translation>
<translation id="7085389578340536476">ఆడియోను రికార్డ్ చేయడానికి Chromeను అనుమతించాలా?</translation>
-<translation id="7088434364990739311">అప్‌డేట్ తనిఖీ ప్రారంభం విఫలమైంది (ఎర్రర్ కోడ్ <ph name="ERROR" />).</translation>
+<translation id="7088434364990739311">అప్‌డేట్‌ తనిఖీ ప్రారంభం విఫలమైంది (ఎర్ర‌ర్‌ కోడ్ <ph name="ERROR" />).</translation>
<translation id="7088561041432335295">జిప్ ఆర్కైవర్ - ఫైల్‌ల‌ యాప్‌‌లో జిప్ ఫైల్‌లను తెరవండి మరియు ప్యాక్ చేయండి.</translation>
-<translation id="7088674813905715446">ఈ పరికరాన్ని నిర్వాహకులు కేటాయించబడని స్థితిలో ఉంచారు. దీన్ని నమోదు కోసం ప్రారంభించడానికి, దయచేసి మీ నిర్వాహకులు పరికరాన్ని పెండింగ్ స్థితిలో ఉంచేలా చేయండి.</translation>
+<translation id="7088674813905715446">నిర్వాహకులు, ఈ పరికరాన్ని కేటాయించబడని స్థితిలో ఉంచారు. దీనిని నమోదు కోసం ప్రారంభించడానికి, ఈ పరికరాన్ని పెండింగ్ స్థితిలో ఉంచమని దయచేసి మీ నిర్వాహకులను కోరండి.</translation>
<translation id="7093434536568905704">GTK+</translation>
<translation id="7093866338626856921">ఈ పేర్లు గల పరికరాలతో డేటాను ఇచ్చిపుచ్చుకోవడానికి అనుమతి: <ph name="HOSTNAMES" /></translation>
<translation id="7098389117866926363">USB-C పరికరం (వెనుక భాగంలో ఎడమ పోర్ట్)</translation>
@@ -4037,7 +4046,7 @@
<translation id="7114054701490058191">పాస్‌‌వర్డ్‌లు సరిపోలలేదు</translation>
<translation id="7114648273807173152">మీ Google ఖాతాకు సైన్ ఇన్ చేయడం కోసం Smart Lockని ఉపయోగించడానికి, సెట్టింగ్‌లు &gt; కనెక్ట్ చేసిన పరికరాలు &gt; మీ ఫోన్ &gt; Smart Lockకు వెళ్లండి.</translation>
<translation id="7117228822971127758">దయచేసి తర్వాత మళ్లీ ప్రయత్నించండి</translation>
-<translation id="7117247127439884114">మళ్ళీ సైన్ ఇన్ చెయ్యండి...</translation>
+<translation id="7117247127439884114">మళ్ళీ సైన్ ఇన్ చేయండి...</translation>
<translation id="711840821796638741">నిర్వహించబడే బుక్‌మార్క్‌లను చూపు</translation>
<translation id="711902386174337313">మీ సైన్-ఇన్ చేసిన పరికరాల యొక్క జాబితాను చదవడం</translation>
<translation id="7120865473764644444">సమకాలీకరణ సర్వర్‌కి కనెక్ట్ చేయడం సాధ్యపడలేదు. మళ్లీ ప్రయత్నిస్తోంది...</translation>
@@ -4058,7 +4067,7 @@
<translation id="7138678301420049075">ఇతర</translation>
<translation id="713888829801648570">క్షమించండి, మీరు ఆఫ్‌లైన్‌లో ఉన్నందున మీ పాస్‌వర్డ్‌ను ధ్రువీక‌రించ‌డం సాధ్య‌ప‌డ‌దు.</translation>
<translation id="7140928199327930795">అందుబాటులో ఉన్న ఇతర పరికరాలు ఏవీ లేవు.</translation>
-<translation id="7141105143012495934">మీ ఖాతా వివరాలను తిరిగి పొందలేనందున సైన్-ఇన్ విఫలమైంది. దయచేసి మీ నిర్వాహకుడిని సంప్రదించండి లేదా మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="7141105143012495934">మీ ఖాతా వివరాలను పొందలేనందున సైన్-ఇన్ విఫలమైంది. దయచేసి మీ నిర్వాహకుడిని సంప్రదించండి లేదా మళ్లీ ప్రయత్నించండి.</translation>
<translation id="7143092389027215216">డెమో మోడ్‌ను ప్రారంభిస్తోంది</translation>
<translation id="7143207342074048698">కనెక్ట్ అవుతోంది</translation>
<translation id="7144878232160441200">మళ్లీ ప్రయత్నించండి</translation>
@@ -4068,7 +4077,7 @@
<translation id="7154130902455071009">మీ ప్రారంభ పేజీని దీనికి మార్చండి: <ph name="START_PAGE" /></translation>
<translation id="7155171745945906037">కెమెరా లేదా ఫైల్‌లో ఉన్న ఫోటో</translation>
<translation id="7165320105431587207">నెట్‌వర్క్‌ను కాన్ఫిగర్ చేయడంలో విఫలమైంది</translation>
-<translation id="716640248772308851">తనిఖీ చేయబడిన స్థానాల్లో "<ph name="EXTENSION" />" చిత్రాలను, వీడియోను మరియు సౌండ్ ఫైల్‌లను చదవగలదు.</translation>
+<translation id="716640248772308851">తనిఖీ చేయబడిన స్థానాల్లో "<ph name="EXTENSION" />" చిత్రాలను, వీడియోను, సౌండ్ ఫైల్స్‌ను చదవగలదు.</translation>
<translation id="7167486101654761064">&amp;ఎల్లప్పుడూ ఈ రకం ఫైళ్ళను తెరువు</translation>
<translation id="716810439572026343"><ph name="FILE_NAME" />ని డౌన్‌లోడ్ చేస్తోంది</translation>
<translation id="7168109975831002660">కనిష్ఠ ఫాంట్ పరిమాణం</translation>
@@ -4116,16 +4125,16 @@
<translation id="7238585580608191973">SHA-256 వేలిముద్ర</translation>
<translation id="7240120331469437312">సర్టిఫికెట్ విషయ ప్రత్యామ్నాయ పేరు</translation>
<translation id="7240339475467890413">కొత్త హాట్‌స్పాట్‌కి కనెక్ట్ చేయాలా?</translation>
-<translation id="7241389281993241388">దయచేసి క్లయింట్ స‌ర్టిఫికెట్‌ను దిగుమతి చేయ‌డానికి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చేయండి.</translation>
+<translation id="7241389281993241388">క్లయింట్ సర్టిఫికెట్‌ను దిగుమతి చేయడానికి, దయచేసి <ph name="TOKEN_NAME" />కు సైన్ ఇన్ చేయండి.</translation>
<translation id="7243632151880336635">తీసివేసి, సైన్ అవుట్ చేయి</translation>
<translation id="7245628041916450754"><ph name="WIDTH" /> x <ph name="HEIGHT" /> (ఉత్తమం)</translation>
<translation id="7246947237293279874">FTP ప్రాక్సీ</translation>
<translation id="7248671827512403053">అప్లికేషన్‌</translation>
-<translation id="725109152065019550">క్షమించండి, మీ నిర్వాహకుడు మీ ఖాతాలో బాహ్య నిల్వను నిలిపివేసారు.</translation>
+<translation id="725109152065019550">క్షమించండి, మీ నిర్వాహకుడు మీ ఖాతాలో బాహ్య నిల్వను నిలిపివేశారు.</translation>
<translation id="7251346854160851420">డిఫాల్ట్ వాల్‌పేపర్</translation>
<translation id="7253521419891527137">&amp;మరింత తెలుసుకోండి</translation>
<translation id="7254554697254365959">ఈ పేజీని అనువదించడం సాధ్యపడలేదు.</translation>
-<translation id="7254951428499890870">మీరు ఖచ్చితంగా విశ్లేషణ మోడ్‌లో "<ph name="APP_NAME" />"ని లాంచ్ చేయాలనుకుంటున్నారా?</translation>
+<translation id="7254951428499890870">మీరు ఖచ్చితంగా సమస్య విశ్లేషణ మోడ్‌లో "<ph name="APP_NAME" />"ను ప్రారంభించాలనుకుంటున్నారా?</translation>
<translation id="7255002516883565667">ప్రస్తుతం, కేవలం ఈ పరికరంలో మాత్రమే ఉపయోగించగల ఒక కార్డ్ మీ వద్ద ఉంది</translation>
<translation id="7255220508626648026">ప్రసారం చేస్తోంది: <ph name="ROUTETITLE" /></translation>
<translation id="7255935316994522020">వర్తింపజేయి</translation>
@@ -4135,13 +4144,13 @@
<translation id="725758059478686223">ముద్రణ సేవ</translation>
<translation id="7257666756905341374">మీరు కాపీ చేసి అతికించే డేటాను చదవడం</translation>
<translation id="7258697411818564379">మీ పిన్ జోడించబడింది</translation>
-<translation id="7262004276116528033">ఈ సైన్-ఇన్ సేవ <ph name="SAML_DOMAIN" /> ద్వారా హోస్ట్ చేయబడుతోంది</translation>
+<translation id="7262004276116528033">ఈ సైన్-ఇన్ సేవను <ph name="SAML_DOMAIN" /> హోస్ట్ చేస్తోంది</translation>
<translation id="7268659760406822741">అందుబాటులో ఉన్న సేవలు</translation>
<translation id="7270858098575133036">MIDI పరికరాలను యాక్సెస్ చేయడానికి సిస్టమ్ విశిష్ట సందేశాలను సైట్ ఉపయోగించాలనుకున్నప్పుడు అడుగు</translation>
<translation id="7272674038937250585">వివరణ ఏదీ అందించబడలేదు</translation>
<translation id="7273110280511444812"><ph name="DATE" />న చివరిగా జోడించబడింది</translation>
<translation id="727441411541283857"><ph name="PERCENTAGE" />% - <ph name="TIME" />లో పూర్తి ఛార్జ్ అవుతుంది</translation>
-<translation id="727952162645687754">డౌన్‌లోడ్ చేయడంలో ఎర్రర్</translation>
+<translation id="727952162645687754">డౌన్‌లోడ్ చేయడంలో ఎర్ర‌ర్‌</translation>
<translation id="7279701417129455881">కుక్కీ నిరోధించడాన్ని నిర్వహించు...</translation>
<translation id="7280041992884344566">Chrome హానికరమైన సాఫ్ట్‌వేర్ కోసం వెతుకుతున్నప్పుడు ఎర్రర్ ఏర్పడింది</translation>
<translation id="7280649757394340890">వచనం-నుండి-ప్రసంగం వాయిస్ సెట్టింగ్‌లు</translation>
@@ -4152,8 +4161,9 @@
<translation id="7287411021188441799">డిఫాల్ట్ నేపథ్యాన్ని పునరుద్ధరించండి</translation>
<translation id="7288676996127329262"><ph name="HORIZONTAL_DPI" />x<ph name="VERTICAL_DPI" /> dpi</translation>
<translation id="7289225569524511578">వాల్‌పేపర్ యాప్‌ను తెరువు</translation>
-<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> ద్వారా హోస్ట్ చేయబడిన ఈ సైన్-ఇన్ సేవ మీ కెమెరాను ప్రాప్యత చేస్తోంది.</translation>
+<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> హోస్ట్ చేసిన ఈ సైన్-ఇన్ సేవ, మీ కెమెరాను యాక్సెస్ చేస్తోంది.</translation>
<translation id="7290594223351252791">నమోదుని నిర్ధారించండి</translation>
+<translation id="7292696521213967957">అసిస్టెంట్‌ని డీబగ్ చేయడానికి సమాచారం</translation>
<translation id="7295662345261934369">ఇతరులతో భాగస్వామ్యం చేయి</translation>
<translation id="729583233778673644">AES మరియు RC4 ఎన్‌క్రిప్షన్‌ను అనుమతించండి. ఈ ఎంపికను ఉపయోగించడం వలన RC4 సైఫర్‌లు అసురక్షితమైనవి కాబట్టి మీకు హాని పెరుగుతుంది.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> నిబంధనలు</translation>
@@ -4175,7 +4185,7 @@
<translation id="7325437708553334317">అధిక కాంట్రాస్ట్ పొడిగింపు</translation>
<translation id="7328699668338161242">ఇప్పటికే మీ వాయిస్‌ని మీ అసిస్టెంట్ గుర్తించగలదు</translation>
<translation id="7328867076235380839">చెల్లని కాంబినేషన్</translation>
-<translation id="7329154610228416156">అసురక్షిత URL (<ph name="BLOCKED_URL" />)ని ఉపయోగించేలా కాన్ఫిగర్ చేయబడినందున సైన్-ఇన్ విఫలమైంది. దయచేసి మీ నిర్వాహకుడిని సంప్రదించండి.</translation>
+<translation id="7329154610228416156">అసురక్షిత URL (<ph name="BLOCKED_URL" />)ను ఉపయోగించేలా కాన్ఫిగర్ చేయబడినందున సైన్-ఇన్ విఫలమైంది. దయచేసి మీ నిర్వాహకుడిని సంప్రదించండి.</translation>
<translation id="7334190995941642545">Smart Lock ప్రస్తుతం అందుబాటులో లేదు. దయచేసి తర్వాత మళ్లీ ప్రయత్నించండి.</translation>
<translation id="7334274148831027933">డాక్ చేయబడిన మాగ్నిఫైయర్‌ను ప్రారంభించండి</translation>
<translation id="7338630283264858612">పరికరం క్రమ సంఖ్య చెల్లదు.</translation>
@@ -4219,7 +4229,7 @@
<translation id="7388222713940428051">అతిథి విండోని తెరువు</translation>
<translation id="7392118418926456391">వైరస్‌ను స్కాన్ చేయడంలో విఫలమైంది</translation>
<translation id="7392915005464253525">మూ&amp;సిన విండోని మళ్ళీ తెరువు</translation>
-<translation id="7396845648024431313"><ph name="APP_NAME" /> సిస్టమ్ ప్రారంభంలో ప్రారంభమవుతుంది మరియు మీరు అన్ని ఇతర <ph name="PRODUCT_NAME" /> విండోలను మూసివేసిన తర్వాత కూడా నేపథ్యంలో అమలవడం కొనసాగుతుంది.</translation>
+<translation id="7396845648024431313"><ph name="APP_NAME" /> సిస్టమ్ ప్రారంభంలో ప్రారంభమవ్వడమే కాక, అన్ని ఇతర <ph name="PRODUCT_NAME" /> విండోలను మీరు మూసివేసిన తర్వాత కూడా నేపథ్యంలో అమలవడం కొనసాగుతుంది.</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7400839060291901923">మీ <ph name="PHONE_NAME" />లో కనెక్షన్‌ని సెటప్ చేయండి</translation>
<translation id="740624631517654988">పాప్-అప్ నిరోధించబడింది</translation>
@@ -4247,14 +4257,13 @@
<translation id="7441736921018636843">ఈ సెట్టింగ్‌ని మార్చడానికి, మీ సమకాలీకరణ రహస్య పదబంధాన్ని తీసివేయడానికి <ph name="BEGIN_LINK" />సమకాలీకరణను రీసెట్ చేయండి<ph name="END_LINK" /></translation>
<translation id="7441830548568730290">ఇతర వినియోగదారులు</translation>
<translation id="7442465037756169001">మీ Hangouts Meet hardware సెటప్ చేయడానికి సిద్ధంగా ఉంది.</translation>
-<translation id="744341768939279100">కొత్త ప్రొఫైల్‌ని సృష్టించు</translation>
-<translation id="7444983668544353857"><ph name="NETWORKDEVICE" />ను ఆపివెయ్యి</translation>
+<translation id="744341768939279100">కొత్త ప్రొఫైల్‌ను సృష్టించు</translation>
+<translation id="7444983668544353857"><ph name="NETWORKDEVICE" />ను నిలిపివేయి</translation>
<translation id="7453008956351770337">ఈ ప్రింటర్‌ను ఎంచుకోవడం ద్వారా, మీరు మీ ప్రింటర్‌ని యాక్సెస్ చేయడానికి క్రింది ఎక్సటెన్షన్‌కు అనుమతి ఇస్తున్నారు:</translation>
<translation id="7456142309650173560">డెవలపర్</translation>
<translation id="7456847797759667638">స్థానాన్ని తెరువు...</translation>
<translation id="7461924472993315131">పిన్ చేయి</translation>
<translation id="7463006580194749499">వ్యక్తిని జోడించు</translation>
-<translation id="7464902436585505072">"Ok Google" వాయిస్ నమూనా (మోడల్)</translation>
<translation id="7465778193084373987">Netscape సర్టిఫికెట్ రద్దు URL</translation>
<translation id="7469894403370665791">ఆటోమేటిక్‌గా ఈ నెట్‌వర్క్‌కు కనెక్ట్ చేయి</translation>
<translation id="747114903913869239">ఎర్రర్: ఎక్స్‌టెన్షన్‌లను డీకోడ్ చేయడం సాధ్యం కాలేదు</translation>
@@ -4282,6 +4291,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" />, అలాగే దానితో అనుబంధితమైన డేటా ఈ పరికరం నుండి తీసివేయబడుతుంది.</translation>
<translation id="7497215489070763236">సర్వర్ CA సర్టిఫికేట్</translation>
<translation id="7497981768003291373">మీ వద్ద ఇటీవల క్యాప్చర్ చేయబడిన WebRTC వచన లాగ్‌లు ఏవీ లేవు.</translation>
+<translation id="7502199377020483660">మీ అన్ని పరికరాలలో ఈ కార్డ్‌లను ఉపయోగించేందుకు, వీటిని మీ Google ఖాతాలో సేవ్ చేయండి</translation>
<translation id="7502658306369382406">IPv6 చిరునామా</translation>
<translation id="7503191893372251637">Netscape సర్టిఫికెట్ రకం</translation>
<translation id="7503821294401948377">బ్రౌజర్ చర్య కోసం '<ph name="ICON" />' చిహ్నాన్ని లోడ్ చేయడం సాధ్యపడలేదు.</translation>
@@ -4289,8 +4299,8 @@
<translation id="7505167922889582512">దాచిన ఫైల్‌లను చూపు</translation>
<translation id="7506541170099744506">మీ <ph name="DEVICE_TYPE" /> ఎంటర్‌ప్రైజ్ నిర్వహణ కోసం విజయవంతంగా నమోదు చేయబడింది.</translation>
<translation id="7507930499305566459">స్థితి ప్రతిస్పందన సర్టిఫికెట్</translation>
-<translation id="7508545000531937079">స్లయిడ్ ప్రదర్శన</translation>
-<translation id="7513029293694390567">నిల్వ చేసిన ఆధారాలను ఉపయోగించి ఆటోమేటిక్‌గా వెబ్‌సైట్‌లకు సైన్ ఇన్ చేస్తుంది. దీన్ని నిలిపివేస్తే, మీరు వెబ్‌సైట్‌కు సైన్ ఇన్ చేసే ప్రతిసారి నిర్ధారణ కోసం మిమ్మల్ని అడుగుతుంది.</translation>
+<translation id="7508545000531937079">స్లయిడ్ షో</translation>
+<translation id="7513029293694390567">నిల్వ చేసిన ఆధారాలను ఉపయోగించి ఆటోమేటిక్‌గా వెబ్‌సైట్‌లకు సైన్ ఇన్ చేస్తుంది. దీనిని నిలిపివేస్తే, మీరు వెబ్‌సైట్‌కు సైన్ ఇన్ చేసే ప్రతిసారి నిర్ధారణ కోసం మిమ్మల్ని అడుగుతుంది.</translation>
<translation id="7517786267097410259">పాస్‌వర్డ్‌ను సృష్టించండి -</translation>
<translation id="7521387064766892559">JavaScript</translation>
<translation id="7522255036471229694">"Ok Google" చెప్పండి</translation>
@@ -4301,7 +4311,7 @@
<translation id="7537601449003285327">విధి పట్టీకి పిన్ చేయి</translation>
<translation id="7539856059004947393">బ్లూటూత్ భద్రతా కీ</translation>
<translation id="7540972813190816353">అప్‌డేట్‌ల కోసం తనిఖీ చేస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది: <ph name="ERROR" /></translation>
-<translation id="7543104066686362383">ఈ <ph name="IDS_SHORT_PRODUCT_NAME" /> పరికరంలో డీబగ్గింగ్ ఫీచ‌ర్‌ల‌ను ప్రారంభించండి</translation>
+<translation id="7543104066686362383">ఈ <ph name="IDS_SHORT_PRODUCT_NAME" /> పరికరంలో డీబగ్గింగ్ ఫీచ‌ర్‌లను ప్రారంభించండి</translation>
<translation id="7544853251252956727">షఫుల్ చేయి</translation>
<translation id="7547317915858803630">హెచ్చరిక: మీ <ph name="PRODUCT_NAME" /> సెట్టింగ్‌లు నెట్‌వర్క్ డిస్క్‌లో నిల్వ చేయబడ్డాయి. దీని ఫలితంగా స్లోడౌన్‌లు, క్రాష్‌లు జరగవచ్చు లేదా డేటాను కూడా నష్టపోవచ్చు.</translation>
<translation id="7548856833046333824">నిమ్మరసం</translation>
@@ -4314,8 +4324,8 @@
<translation id="7556033326131260574">Smart Lock మీ ఖాతాను ధృవీకరించలేకపోయింది. ప్రవేశించడానికి మీ పాస్‌వర్డ్‌ను టైప్ చేయండి.</translation>
<translation id="7556242789364317684">దురదృష్టవశాత్తూ, <ph name="SHORT_PRODUCT_NAME" /> మీ సెట్టింగ్‌లను పునరుద్ధరించలేకపోయింది. ఎర్రర్‌ను పరిష్కరించడానికి, <ph name="SHORT_PRODUCT_NAME" /> మీ పరికరాన్ని తప్పనిసరిగా పవర్‌వాష్‌తో రీసెట్ చేయాలి.</translation>
<translation id="7559719679815339381">దయచేసి వేచి ఉండండి....కియోస్క్ యాప్ అప్‌డేట్ అయ్యే ప్రాసెస్‌లో ఉంది. USB స్టిక్‌ను తీసివేయకండి.</translation>
-<translation id="7563991800558061108">ఈ ఎర్రర్ నుండి పునరుద్ధరించడానికి, మీరు సైన్-ఇన్ స్క్రీన్ నుండి మీ Google ఖాతాకు
- సైన్ ఇన్ చేయాలి. మీరు ఆపై మీ Google ఖాతా నుండి సైన్ అవుట్ చేసి మళ్లీ
+<translation id="7563991800558061108">ఈ ఎర్రర్ నుండి పునరుద్ధరించడానికి, సైన్-ఇన్ స్క్రీన్ నుండి మీ Google ఖాతాకు
+ సైన్ ఇన్ చేయాలి. ఆపై మీ Google ఖాతా నుండి సైన్ అవుట్ చేసి మళ్లీ
పర్యవేక్షించబడే వినియోగదారుని సృష్టించడాన్ని ప్రయత్నించవచ్చు.</translation>
<translation id="756445078718366910">బ్రౌజర్ విండోను తెరువు</translation>
<translation id="7564847347806291057">ప్రాసెస్‌ని ముగించు</translation>
@@ -4353,7 +4363,7 @@
<translation id="7621382409404463535">పరికర కాన్ఫిగరేషన్‌ను సేవ్ చేయడంలో సిస్టమ్ విఫలమైంది.</translation>
<translation id="7622114377921274169">ఛార్జింగ్.</translation>
<translation id="7624337243375417909">caps lock ఆఫ్‌లో ఉంది</translation>
-<translation id="7625568159987162309">సైట్‌లలోని అనుమతులు మరియు నిల్వ చేయబడిన డేటాని చూడండి</translation>
+<translation id="7625568159987162309">సైట్‌లలోని అనుమతులను, నిల్వ చేయబడిన డేటాను చూడండి</translation>
<translation id="7627790789328695202">అయ్యో, <ph name="FILE_NAME" /> ఇప్పటికే ఉంది. దీని పేరు మార్చి, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="7629827748548208700">టాబ్: <ph name="TAB_NAME" /></translation>
<translation id="7631887513477658702">&amp;ఎల్లప్పుడూ ఈ రకం ఫైళ్ళను తెరువు</translation>
@@ -4379,12 +4389,13 @@
<translation id="7663719505383602579">స్వీకర్త: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">మద్దతు లేని బ్లూటూత్ పరికరం: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">ఖాతాను జోడించండి</translation>
+<translation id="7667248760110172428">బాహ్య నిల్వ</translation>
<translation id="7671130400130574146">సిస్టమ్ శీర్షిక బార్ మరియు హద్దులను ఉపయోగించు</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" />లో.</translation>
<translation id="7676867886086876795">మీరు రాయాలనుకునేది Googleకి చెబితే చాలు వెంటనే వచన రూపంలోకి మారుస్తుంది.</translation>
-<translation id="7681095912841365527">సైట్ బ్లూటూత్‌ని ఉపయోగించవచ్చు</translation>
-<translation id="7683373461016844951">కొనసాగించాలంటే, సరే క్లిక్ చేసి, ఆపై మీ <ph name="DOMAIN" /> ఇమెయిల్ చిరునామా కోసం కొత్త ప్రొఫైల్‌ను సృష్టించడానికి వ్యక్తిని జోడించు క్లిక్ చేయండి.</translation>
-<translation id="7684212569183643648">మీ నిర్వాహకుడు ఇన్‌స్టాల్ చేసారు</translation>
+<translation id="7681095912841365527">సైట్ బ్లూటూత్‌ను ఉపయోగించవచ్చు</translation>
+<translation id="7683373461016844951">కొనసాగించాలంటే, 'సరే' క్లిక్ చేసి, ఆపై మీ <ph name="DOMAIN" /> ఇమెయిల్ చిరునామాకు కొత్త ప్రొఫైల్‌ను సృష్టించడానికి 'వ్యక్తిని జోడించు' క్లిక్ చేయండి.</translation>
+<translation id="7684212569183643648">మీ నిర్వాహకుడు ఇన్‌స్టాల్ చేశారు</translation>
<translation id="7684559058815332124">క్యాప్టివ్ పోర్టల్ లాగిన్ పేజీని సందర్శించండి</translation>
<translation id="7685049629764448582">JavaScript మెమరీ</translation>
<translation id="7686938547853266130"><ph name="FRIENDLY_NAME" /> (<ph name="DEVICE_PATH" />)</translation>
@@ -4494,16 +4505,16 @@
<ph name="BR" />
మీరు మీ పరికరంలో అనుకూల కోడ్‌ను ఇన్‌స్టాల్ చేయడానికి మరియు పరీక్షించడానికి మీ Chrome OS పరికరంలో డీబగ్గింగ్ ఫీచర్‌లను ఆరంభించవచ్చు. వీటిని చేయడానికి ఇది మిమ్మల్ని అనుమతిస్తుంది:<ph name="BR" />
<ph name="BEGIN_LIST" />
- <ph name="LIST_ITEM" />ధృవీకరణను తీసివేయడం, తద్వారా మీరు OS ఫైల్‌లను సవరించవచ్చు
+ <ph name="LIST_ITEM" />rootfs ధృవీకరణను తీసివేయడం, తద్వారా మీరు OS ఫైల్‌లను సవరించవచ్చు
<ph name="LIST_ITEM" />ప్రామాణిక పరీక్ష కీలను ఉపయోగించి పరికరానికి SSH యాక్సెస్‌ను ఆరంభించడం, తద్వారా మీరు పరికరాన్ని యాక్సెస్ చేయడానికి <ph name="BEGIN_CODE" />'cros flash'<ph name="END_CODE" /> వంటి సాధానాలను ఉపయోగించవచ్చు
- <ph name="LIST_ITEM" />USB నుండి బూటింగ్‌ని ఆరంభించడం, తద్వారా మీరు USB డ్రైవ్ నుండి OS ఇమేజ్‌ని ఇన్‌స్టాల్ చేయవచ్చు
+ <ph name="LIST_ITEM" />USB నుండి బూటింగ్‌ను ఆరంభించడం, తద్వారా మీరు USB డ్రైవ్ నుండి OS ఇమేజ్‌ను ఇన్‌స్టాల్ చేయవచ్చు
<ph name="LIST_ITEM" />డెవలపర్ మరియు సిస్టమ్ రూట్ లాగిన్ పాస్‌వర్డ్ రెండింటినీ అనుకూల విలువకు సెట్ చేయడం, తద్వారా మీరు పరికరంలోకి మ్యానువల్‌గా SSH చేయవచ్చు
<ph name="END_LIST" />
<ph name="BR" />
- ఒకసారి ఆరంభించబడితే, ఎంటర్‌ప్రైజ్ నిర్వహిత పరికరంలో పవర్‌వాష్ అమలు చేసిన తర్వాత లేదా డేటాను తుడిచివేసిన తర్వాత కూడా చాలా వరకు డీబగ్గింగ్ ఫీచర్‌లు అలాగే ఆరంభించబడి ఉంటాయి. అన్ని డీబగ్గింగ్ ఫీచర్‌లను పూర్తిగా నిలిపివేయడానికి, Chrome OS పునరుద్ధరణ ప్రక్రియ (https://support.google.com/chromebook/answer/1080595).
+ ఒకసారి ఆరంభించబడితే, ఎంటర్‌ప్రైజ్ నిర్వాహిత‌ పరికరంలో పవర్‌వాష్ అమలు చేసిన తర్వాత లేదా డేటాను తుడిచివేసిన తర్వాత కూడా చాలా వరకు డీబగ్గింగ్ ఫీచర్‌లు అలాగే ఆరంభించబడి ఉంటాయి. అన్ని డీబగ్గింగ్ ఫీచర్‌లను పూర్తిగా నిలిపివేయడానికి, Chrome OS పునరుద్ధరణ ప్రక్రియ (https://support.google.com/chromebook/answer/1080595) పూర్తి చేయండి.
<ph name="BR" />
<ph name="BR" />
- డీబగ్గింగ్ ఫీచర్‌ల గురించి మరింత సమాచారం కోసం, ఈ లింక్‌ని చూడండి:<ph name="BR" />
+ డీబగ్గింగ్ ఫీచర్‌ల గురించి మరింత సమాచారం కోసం, ఈ లింక్‌ను చూడండి:<ph name="BR" />
https://www.chromium.org/chromium-os/how-tos-and-troubleshooting/debugging-features
<ph name="BR" />
<ph name="BR" />
@@ -4527,7 +4538,7 @@
<translation id="7849264908733290972">&amp;చిత్రాన్ని కొత్త‌ టాబ్‌లో తెరువు</translation>
<translation id="784934925303690534">సమయ పరిధి</translation>
<translation id="7850851215703745691">ఈ డిస్క్ ఫైల్‌లు ఇంకా భాగస్వామ్యం చేయబడలేదు</translation>
-<translation id="7851457902707056880">సైన్-ఇన్ కేవలం యజమాని ఖాతాకు పరిమితం చేయబడింది. దయచేసి రీబూట్ చేసి యజమాని ఖాతాతో సైన్ ఇన్ చేయండి. మెషీన్ 30 సెకన్లలో ఆటోమేటిక్‌గా రీబూట్ అవుతుంది.</translation>
+<translation id="7851457902707056880">సైన్-ఇన్ అనేది, యజమాని ఖాతాకు మాత్రమే పరిమితం చేయబడింది. దయచేసి రీబూట్ చేసి యజమాని ఖాతాతో సైన్ ఇన్ చేయండి. మెషీన్ 30 సెకన్లలో ఆటోమేటిక్‌గా రీబూట్ అవుతుంది.</translation>
<translation id="7851716364080026749">ఎల్లప్పుడూ కెమెరా మరియు మైక్రోఫోన్ యాక్సెస్‌ను బ్లాక్ చేయి</translation>
<translation id="7853747251428735">మరిన్ని సాధనా&amp;లు</translation>
<translation id="7857117644404132472">మినహాయింపును జోడించు</translation>
@@ -4539,10 +4550,10 @@
<translation id="7868378670806575181">{NUM_COOKIES,plural, =1{1 కుక్కీ}other{# కుక్కీలు}}</translation>
<translation id="786957569166715433"><ph name="DEVICE_NAME" /> - జత చేయబడింది</translation>
<translation id="7870730066603611552">సెటప్ చేసిన తర్వాత సమకాలీకరణ ఎంపికలను సమీక్షించండి</translation>
-<translation id="7870790288828963061">సరికొత్త వెర్షన్‌ అందుబాటులో ఉన్న కియోస్క్ అనువర్తనాలేవీ కనుగొనబడలేదు. నవీకరించడానికి ఏదీ లేదు. దయచేసి USB స్టిక్‌ను తీసివేయండి.</translation>
+<translation id="7870790288828963061">సరికొత్త వెర్షన్ అందుబాటులో ఉన్న కియోస్క్ యాప్‌లేవీ కనుగొనబడలేదు. అప్‌డేట్ చేయడానికి ఏదీ లేదు. దయచేసి USB స్టిక్‌ను తీసివేయండి.</translation>
<translation id="7873831373602885875"><ph name="FOLDER_NAME" />లో సేవ్ చేయడం సాధ్యపడలేదు. అన్ని సవరణలు డౌన్‌లోడ్‌లు ఫోల్డర్‌లోని<ph name="DOWNLOADS_FOLDER" />లో సేవ్ చేయబడతాయి.</translation>
<translation id="7874257161694977650">Chrome నేపథ్యాలు</translation>
-<translation id="7877451762676714207">తెలియని సర్వర్ ఎర్రర్. దయచేసి మళ్లీ ప్రయత్నించండి లేదా సర్వర్ నిర్వాహకుడిని సంప్రదించండి.</translation>
+<translation id="7877451762676714207">తెలియని సర్వర్ ఎర్ర‌ర్‌. దయచేసి మళ్లీ ప్రయత్నించండి లేదా సర్వర్ నిర్వాహకుడిని సంప్రదించండి.</translation>
<translation id="7877680364634660272">పర్యటన</translation>
<translation id="7878562273885520351">మీ పాస్‌వర్డ్ ఎవరికైనా తెలిసిపోయి ఉండవచ్చు</translation>
<translation id="7881483672146086348">ఖాతాను వీక్షించండి</translation>
@@ -4564,7 +4575,7 @@
<translation id="7903345046358933331">పేజీ ప్రతిస్పందించడం లేదు. మీరు అది ప్రతిస్పందించే వరకు వేచి ఉండవచ్చు లేదా దాన్ని మూసివేయవచ్చు.</translation>
<translation id="7903742244674067440">మీకు ఫైల్‌లో ఈ ప్రమాణపత్రం అధికారాలను గుర్తించే ప్రమాణపత్రాలు ఉన్నాయి</translation>
<translation id="7903925330883316394">యుటిలిటీ: <ph name="UTILITY_TYPE" /></translation>
-<translation id="7904094684485781019">ఈ ఖాతా నిర్వాహకులు బహుళ సైన్-ఇన్‌కు అనుమతించలేదు.</translation>
+<translation id="7904094684485781019">ఈ ఖాతా నిర్వాహకులు బహుళ సైన్-ఇన్‌ను అనుమతించలేదు.</translation>
<translation id="7904402721046740204">ప్రామాణీకరిస్తోంది</translation>
<translation id="7908378463497120834">క్షమించండి, మీ బాహ్య నిల్వ పరికరంలో కనీసం ఒక విభజనను మౌంట్ చేయడం వీలుకాలేదు.</translation>
<translation id="7909969815743704077">అజ్ఞాతంలో డౌన్‌లోడ్ చేయబడింది</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">సేవ్ చేయబడిన చెల్లింపు పద్ధతులు ఇక్కడ కనిపిస్తాయి</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> మీ స్క్రీన్ మరియు ఆడియోను భాగస్వామ్యం చేస్తోంది.</translation>
<translation id="7931318309563332511">తెలియదు</translation>
+<translation id="7932969338829957666">Linuxలో <ph name="BASE_DIR" />లో షేర్ చేసిన ఫోల్డర్‌లు అందుబాటులో ఉన్నాయి.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{సైట్‌ను అన్‌మ్యూట్ చేయి}other{సైట్‌లను అన్‌మ్యూట్ చేయి}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> రక్షిత కంటెంట్‌ని ప్లే చేయాలనుకుంటోంది. మీ పరికర గుర్తింపును Google ధృవీకరిస్తుంది.</translation>
<translation id="793531125873261495">వర్చువల్ మెషిన్‌ను డౌన్‌లోడ్ చేయడంలో ఎర్రర్ ఏర్పడింది. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
@@ -4615,7 +4627,7 @@
<translation id="7979036127916589816">సింక్ ఎర్రర్</translation>
<translation id="7980084013673500153">అసెట్ ID: <ph name="ASSET_ID" /></translation>
<translation id="7981313251711023384">వేగవంతమైన బ్రౌజింగ్ మరియు శోధన కోసం పేజీలను ముందస్తుగా లోడ్ చేస్తుంది</translation>
-<translation id="7982083145464587921">ఈ ఎర్రర్‌ను పరిష్కరించడానికి, దయచేసి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
+<translation id="7982083145464587921">ఈ ఎర్రర్‌ను పరిష్కరించడానికి దయచేసి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
<translation id="7982283708762922719">ఎత్తు</translation>
<translation id="7982789257301363584">నెట్‌వర్క్</translation>
<translation id="7984068253310542383">మిర్రర్ <ph name="DISPLAY_NAME" /></translation>
@@ -4638,19 +4650,19 @@
<translation id="8009225694047762179">పాస్‌వర్డ్‌లను నిర్వహించండి</translation>
<translation id="8012382203418782830">ఈ పేజీ అనువదించబడింది.</translation>
<translation id="8014154204619229810">అప్‌డేటర్ ప్రస్తుతం అమలులో ఉంది. మళ్లీ తనిఖీ చేయడానికి ఒక నిమిషం తర్వాత రిఫ్రెష్ చేయండి.</translation>
-<translation id="8014206674403687691"><ph name="IDS_SHORT_PRODUCT_NAME" /> మునుపు ఇన్‌స్టాల్ చేసిన సంస్కరణకు తిరిగి మారలేకపోయింది. దయచేసి మీ పరికరాన్ని పవర్‌వాష్ చేయడానికి మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="8014206674403687691"><ph name="IDS_SHORT_PRODUCT_NAME" /> మునుపు ఇన్‌స్టాల్ చేసిన వెర్షన్‌కు తిరిగి మారలేకపోయింది. దయచేసి మీ పరికరాన్ని పవర్‌వాష్ చేయడానికి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="8014210335923519270">సిస్టమ్ సమాచారం మరియు వినియోగ వివరాలను Googleకి పంపడం ద్వారా <ph name="IDS_SHORT_PRODUCT_NAME" />ని మరియు దాని భద్రతను మరింత మెరుగుపరచండి</translation>
<translation id="8016266267177410919">తాత్కాలిక నిల్వ</translation>
<translation id="8017335670460187064"><ph name="LABEL" /></translation>
<translation id="8017679124341497925">షార్ట్‌కట్ సవరించబడింది</translation>
<translation id="8018313076035239964">వెబ్‌‍సైట్‌లు ఉపయోగించగల సమాచారాన్ని మరియు అవి మీకు చూపగల కంటెంట్‌ను నియంత్రించండి</translation>
-<translation id="8023801379949507775">ఎక్స్‌టెన్షన్‌లను ఇప్పుడు అప్‌డేట్ చేయి</translation>
+<translation id="8023801379949507775">ఎక్స్‌టెన్ష‌న్‌లను ఇప్పుడు అప్‌డేట్ చేయి</translation>
<translation id="8024483450737722621">మీరు Google Play నుండి డౌన్‌లోడ్ చేసిన యాప్‌లు ఈ Chromebook నుండి తొలగించబడతాయి.
<ph name="LINE_BREAKS1" />
మీరు కొనుగోలు చేసిన చలన చిత్రాలు, టీవీ కార్యక్రమాలు, సంగీతం, పుస్తకాలు లేదా ఇతర యాప్‌లో కొనుగోళ్లు కూడా తొలగించబడవచ్చు.
<ph name="LINE_BREAKS2" />
ఇది ఇతర పరికరాల్లో యాప్‌లు లేదా కంటెంట్‌ను ప్రభావితం చేయదు.</translation>
-<translation id="8026334261755873520">బ్రౌజింగ్ డేటాను క్లియర్ చెయ్యి</translation>
+<translation id="8026334261755873520">బ్రౌజింగ్ డేటాను క్లియర్ చేయి</translation>
<translation id="8028060951694135607">Microsoft Key Recovery</translation>
<translation id="8028803902702117856"><ph name="SIZE" />, <ph name="FILE_NAME" /> డౌన్‌లోడ్ చేస్తోంది</translation>
<translation id="8028993641010258682">పరిమాణం</translation>
@@ -4669,6 +4681,7 @@
<translation id="8049705080247101012">Google "<ph name="EXTENSION_NAME" />"ను హానికరమైనదిగా ఫ్లాగ్ చేసినందున ఇన్‌స్టాలేషన్ నిరోధించబడింది</translation>
<translation id="8049913480579063185">పొడిగింపు పేరు</translation>
<translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
+<translation id="8052887694493382350">ఈ ఫైల్ Windows సాఫ్ట్‌వేర్‌ను ఉపయోగించే PC కోసం రూపొందించినది. ఇది Chrome OSను అమలు చేసే మీ పరికరానికి అనుకూలంగా లేదు. <ph name="BEGIN_LINK_HELP" />మరింత తెలుసుకోండి<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 ఫైళ్ళు</translation>
<translation id="8053390638574070785">ఈ పేజీని మళ్లీ లోడ్ చేయి</translation>
<translation id="8054517699425078995">ఈ రకమైన ఫైల్ మీ పరికరానికి హాని కలిగించవచ్చు. ఏదేమైనా <ph name="FILE_NAME" />ని ఉంచాలనుకుంటున్నారా?</translation>
@@ -4688,7 +4701,7 @@
<ph name="BEGIN_PARAGRAPH3" />మీరు సెట్టింగ్‌లలో ఈ సేవని ఆఫ్ చేయవచ్చు.<ph name="END_PARAGRAPH3" /></translation>
<translation id="8074127646604999664">డేటాను పంపడం మరియు స్వీకరించడం పూర్తి చేయడానికి ఇటీవల మూసివేసిన సైట్‌లను అనుమతించు</translation>
<translation id="8076492880354921740">ట్యాబ్‌లు</translation>
-<translation id="8076835018653442223">మీ నిర్వాహకులు మీ పరికరంలోని స్థానిక ఫైల్‌లకు యాక్సెస్‌ని నిలిపివేసారు</translation>
+<translation id="8076835018653442223">మీ నిర్వాహకులు మీ పరికరంలోని స్థానిక ఫైల్‌లకు యాక్సెస్‌ను నిలిపివేసారు</translation>
<translation id="8079530767338315840">పునరావృతం చేయి</translation>
<translation id="8079938625609335826">మీ పరికరాలన్నింటిలో మీ అన్ని ఎక్స్‌టెన్షన్‌లను పొందడానికి, సమకాలీకరణను ఆన్ చేయండి.</translation>
<translation id="8084114998886531721">సేవ్ చేసిన పాస్‌వర్డ్</translation>
@@ -4730,16 +4743,16 @@
<translation id="8141725884565838206">మీ పాస్‌వర్డ్‌లను నిర్వహించండి</translation>
<translation id="8142441511840089262">రెండు సార్లు క్లిక్ చేయండి</translation>
<translation id="8143442547342702591">చెల్లని అప్లికేషన్</translation>
-<translation id="8146177459103116374">మీరు ఇప్పటికే ఈ పరికరంలో నమోదు చేసి ఉంటే, మీరు <ph name="LINK2_START" />ఇప్పటికే ఉన్న వినియోగదారు వలే సైన్ ఇన్ చేయవచ్చు<ph name="LINK2_END" />.</translation>
+<translation id="8146177459103116374">మీరు ఇప్పటికే ఈ పరికరంలో నమోదు చేసి ఉంటే, మీరు <ph name="LINK2_START" />ఇప్పటికే ఉన్న వినియోగదారు లాగా సైన్ ఇన్ చేయవచ్చు<ph name="LINK2_END" />.</translation>
<translation id="8146793085009540321">సైన్-ఇన్ విఫలమైంది. దయచేసి మీ నిర్వాహకులను సంప్రదించండి లేదా మళ్లీ ప్రయత్నించండి.</translation>
<translation id="8151638057146502721">కాన్ఫిగర్ చేయి</translation>
<translation id="8152091997436726702">ప్రింటర్ నమోదు‌కు గడువు ముగిసింది. ప్రింటర్‌ను నమోదు చేయడానికి, మీరు తప్పనిసరిగా ప్రింటర్‌లో నమోదును నిర్ధారించాలి.</translation>
<translation id="8153607920959057464">ఈ ఫైల్‌ని ప్రదర్శించడం సాధ్యం కాలేదు.</translation>
<translation id="8154790740888707867">ఫైల్ లేదు</translation>
-<translation id="815491593104042026">అయ్యో! ఇది సురక్షితం కాని URL (<ph name="BLOCKED_URL" />)ని ఉపయోగించే విధంగా కాన్ఫిగర్ చేయబడినందున ప్రామాణీకరణ విఫలమైంది. దయచేసి మీ నిర్వాహకుడిని సంప్రదించండి.</translation>
+<translation id="815491593104042026">అయ్యో! ఇది సురక్షితం కాని URL (<ph name="BLOCKED_URL" />)ను ఉపయోగించే విధంగా కాన్ఫిగర్ చేయబడినందున ప్రామాణీకరణ విఫలమైంది. దయచేసి మీ నిర్వాహకుడిని సంప్రదించండి.</translation>
<translation id="8157684860301034423">యాప్ సమాచారాన్ని తిరిగి పొందడంలో విఫలమైంది.</translation>
<translation id="8157939133946352716">7x5</translation>
-<translation id="816055135686411707">సర్టిఫికెట్ నమ్మకాన్ని సెట్ చేయడంలో ఎర్రర్</translation>
+<translation id="816055135686411707">లోపం సెట్టింగ్ ప్రమాణపత్ర నమ్మకం</translation>
<translation id="816095449251911490"><ph name="SPEED" /> - <ph name="RECEIVED_AMOUNT" />, <ph name="TIME_REMAINING" /></translation>
<translation id="8162857629993139764">కొత్త గమనికను సృష్టించండి</translation>
<translation id="8168435359814927499">కంటెంట్</translation>
@@ -4749,7 +4762,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8180239481735238521"> పేజీ</translation>
<translation id="8180294223783876911">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. ఈ పరికరం ప్రస్తుతం సమస్య విశ్లేషణ, అలాగే పరికర, యాప్ వినియోగ డేటాను ఆటోమేటిక్‌గా Googleకి పంపుతుంది. ఇది సిస్టమ్, యాప్ స్థిరత్వానికి, అలాగే ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. మీ అదనపు వెబ్ &amp; యాప్ కార్యకలాపం సెట్టింగ్‌ను ఆన్ చేసినట్లయితే, ఈ డేటా మీ Google ఖాతాలో సేవ్ చేయబడవచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
-<translation id="8180786512391440389">"<ph name="EXTENSION" />" ఎంచుకున్న స్థానాల్లోని చిత్రాలను, వీడియోను మరియు సౌండ్ ఫైల్‌లను చదవగలదు మరియు తొలగించగలదు.</translation>
+<translation id="8180786512391440389">"<ph name="EXTENSION" />" ఎంచుకున్న స్థానాల్లోని చిత్రాలను, వీడియోను, సౌండ్ ఫైల్స్‌ను చదవగలదు. తొలగించగలదు.</translation>
<translation id="8181215761849004992">డొమైన్‌కు చేర్చడం సాధ్యపడలేదు. పరికరాలను జోడించడానికి తగిన అధికారాలు మీకు ఉన్నాయో లేదో మీ ఖాతాలో తనిఖీ చేయండి.</translation>
<translation id="8182664696082410784"><ph name="REASON" />
ఈ సైట్‌ను బ్లాక్ చేసి ఉండకూడదు!</translation>
@@ -4766,8 +4779,8 @@
<translation id="8195027750202970175">డిస్క్‌లో పరిమాణం</translation>
<translation id="8198323535106903877">మేము మీ కోసం ఈ <ph name="NUMBER_OF_APPS" /> యాప్‌లు ఇన్‌స్టాల్ చేస్తాము</translation>
<translation id="8199300056570174101">నెట్‌వర్క్ (సేవ) మరియు పరికర లక్షణాలు</translation>
-<translation id="8200772114523450471">మళ్ళీ ప్రారంభించు</translation>
-<translation id="8202160505685531999">దయచేసి మీ <ph name="DEVICE_TYPE" /> ప్రొఫైల్‌ను నవీకరించడానికి మీ పాస్‌వర్డ్‌ను మళ్లీ నమోదు చేయండి.</translation>
+<translation id="8200772114523450471">మ‌ళ్లీ ప్రారంభించు</translation>
+<translation id="8202160505685531999">దయచేసి మీ <ph name="DEVICE_TYPE" /> ప్రొఫైల్‌ను అప్‌డేట్ చేయ‌డానికి మీ పాస్‌వర్డ్‌ను మళ్లీ నమోదు చేయండి.</translation>
<translation id="8203732864715032075">మీకు నోటిఫికేషన్‌లను పంపుతుంది, అలాగే సందేశాల కోసం ఈ కంప్యూటర్‌ను డిఫాల్ట్‌గా గుర్తుపెట్టుకుంటుంది. <ph name="LINK_BEGIN" />మరింత తెలుసుకోండి<ph name="LINK_END" /></translation>
<translation id="8203795194971602413">కుడి క్లిక్</translation>
<translation id="8206354486702514201">ఈ సెట్టింగ్ మీ నిర్వాహకుడి ద్వారా అమలు చేయబడింది.</translation>
@@ -4780,14 +4793,14 @@
<translation id="8214489666383623925">ఫైల్‌ను తెరువు...</translation>
<translation id="8214962590150211830">ఈ వ్యక్తిని తీసివేయి</translation>
<translation id="8217399928341212914">బహుళ ఫైల్‌ల యొక్క స్వయంచాలక డౌన్‌లోడ్‌లను బ్లాక్ చేయడాన్ని కొనసాగించు</translation>
-<translation id="8223479393428528563">ఈ ఫైల్‌లను ఆఫ్‌లైన్‌లో ఉపయోగించేందుకు వాటిని సేవ్ చేయడానికి, తిరిగి ఆన్‌లైన్‌లోకి వచ్చి, ఫైల్‌లపై కుడి-క్లిక్ చేసి, ఆపై <ph name="OFFLINE_CHECKBOX_NAME" /> ఎంపికను ఎంచుకోండి.</translation>
+<translation id="8223479393428528563">ఈ ఫైల్స్‌ను ఆఫ్‌లైన్‌లో ఉపయోగించేందుకు వాటిని సేవ్ చేయడానికి, తిరిగి ఆన్‌లైన్‌లోకి వచ్చి, ఫైల్స్‌పై కుడి-క్లిక్ చేసి, ఆపై <ph name="OFFLINE_CHECKBOX_NAME" /> ఎంపికను ఎంచుకోండి.</translation>
<translation id="8225753906568652947">మీ ఆఫర్‌లను రీడీమ్ చేయండి</translation>
<translation id="8226222018808695353">నిషేధించబడింది</translation>
<translation id="8226619461731305576">క్రమ వరుస</translation>
<translation id="8226742006292257240">మీ కంప్యూటర్‌కు కేటాయించబడిన యాదృచ్ఛికంగా రూపొందించబడిన TPM పాస్‌వర్డ్ దిగువన అందించబడింది:</translation>
<translation id="8227119283605456246">ఫైల్‌ను జోడించు</translation>
<translation id="8230134520748321204"><ph name="ORIGIN" /> కోసం పాస్‌వర్డ్‌ని సేవ్ చేయాలా?</translation>
-<translation id="8234795456569844941">దయచేసి ఈ సమస్యను పరిష్కరించడంలో మా ఇంజినీర్‌లకు సహాయపడండి. మీకు ప్రొఫైల్ ఎర్రర్ సందేశం ఎదురుకావడం కంటే ముందు ఏమి జరిగిందో మాకు తెలియజేయండి:</translation>
+<translation id="8234795456569844941">దయచేసి ఈ సమస్యను పరిష్కరించడంలో మా ఇంజినీర్‌లకు సహాయపడండి. ప్రొఫైల్ ఎర్రర్ సందేశం ఎదురయ్యే ముందు ఏమి జరిగిందో మాకు తెలియజేయండి:</translation>
<translation id="8241040075392580210">షేడీ</translation>
<translation id="8241806945692107836">పరికర కాన్ఫిగరేషన్‌ను గుర్తిస్తోంది...</translation>
<translation id="8241868517363889229">మీ బుక్‌మార్క్‌లను చదవడం మరియు మార్చడం</translation>
@@ -4822,7 +4835,7 @@
<translation id="8272443605911821513">"మరిన్ని సాధనాలు" మెనూలోని ఎక్స్‌టెన్షన్‌లను క్లిక్ చేయడం ద్వారా మీ ఎక్స్‌టెన్షన్‌లను నిర్వహించండి.</translation>
<translation id="8272966760965438857">మీ Google ఖాతాలను ఒకే స్థలంలో నిర్వహించండి</translation>
<translation id="8274332263553132018">ఫైల్‌ను ప్రసారం చేయండి</translation>
-<translation id="8274924778568117936">అప్‌డేట్ పూర్తయ్యే వరకు మీ <ph name="DEVICE_TYPE" />ని ఆఫ్ చేయవద్దు లేదా మూసివేయవద్దు. ఇన్‌స్టాలేషన్ పూర్తయిన తర్వాత మీ <ph name="DEVICE_TYPE" /> పునఃప్రారంభమవుతుంది.</translation>
+<translation id="8274924778568117936">అప్‌డేట్ పూర్తయ్యే వరకు మీ <ph name="DEVICE_TYPE" />ని ఆఫ్ చేయవద్దు లేదా మూసివేయవద్దు. ఇన‌స్ట‌లేష‌న్‌ పూర్తయిన తర్వాత మీ <ph name="DEVICE_TYPE" /> పునఃప్రారంభమవుతుంది.</translation>
<translation id="8275038454117074363">దిగుమతి చెయ్యి</translation>
<translation id="8276560076771292512">కాష్‌ను ఖాళీ చేసి, నిర్బంధంగా మళ్లీ లోడ్ చేయి</translation>
<translation id="8281886186245836920">దాటవేయి</translation>
@@ -4831,7 +4844,7 @@
<translation id="8283475148136688298">"<ph name="DEVICE_NAME" />"కు కనెక్ట్ చేస్తున్నప్పుడు ప్రామాణీకరణ కోడ్ తిరస్కరించబడింది.</translation>
<translation id="8284279544186306258">అన్ని <ph name="WEBSITE_1" /> వెబ్‌సైట్‌లు</translation>
<translation id="8286036467436129157">సైన్ ఇన్ చేయండి</translation>
-<translation id="8286963743045814739">అజ్ఞాత విండోని ఉపయోగించి మీరు ప్రైవేట్‌గా బ్రౌజ్ చేయవచ్చు</translation>
+<translation id="8286963743045814739">అజ్ఞాత విండోను ఉపయోగించి మీరు ప్రైవేట్‌గా బ్రౌజ్ చేయవచ్చు</translation>
<translation id="82871696630048499">వెబ్ పేజీ మెమరీ నిండినందున అది మళ్లీ లోడ్ చేయబడింది.</translation>
<translation id="8287902281644548111">API కాల్/URL ద్వారా శోధించండి</translation>
<translation id="8288032458496410887"><ph name="APP" />ని అన్‌ఇన్‌స్టాల్ చేయి...</translation>
@@ -4860,16 +4873,16 @@
<translation id="8342861492835240085">సేకరణను ఎంచుకోండి</translation>
<translation id="8343956361364550006">ఉత్తమ శ్రేణి వీడియో లేదా యానిమేషన్ కోసం అధిక బ్యాండ్‌విడ్త్‌ను ఉపయోగించండి.
నెమ్మది కనెక్షన్‌లు గల ఇతర వ్యక్తులు మీ కంటెంట్‌ను చూడలేకపోవచ్చు.</translation>
-<translation id="8351419472474436977">ఈ ఎక్స్‌టెన్షన్‌ మీ ప్రాక్సీ సెట్టింగ్‌లను దాని నియంత్రణలోకి తీసుకుంది, అది మీరు ఆన్‌లైన్‌లో ఏదైనా చేస్తుంటే దాన్ని మార్చడం, అంతరాయం కలిగించడం లేదా రహస్యంగా గమనించడం వంటివి చేయగలదని దీనర్థం. ఈ మార్పు ఎందుకు సంభవించిందో మీకు ఖచ్చితంగా తెలియలేదంటే బహుశా మీరు దాన్ని కోరుకొని ఉండకపోవచ్చు.</translation>
+<translation id="8351419472474436977">ఈ ఎక్సటెన్షన్ మీ ప్రాక్సీ సెట్టింగ్‌లను దాని నియంత్రణలోకి తీసుకుంది, అది మీరు ఆన్‌లైన్‌లో ఏదైనా చేస్తుంటే దాన్ని మార్చడం, అంతరాయం కలిగించడం లేదా రహస్యంగా గమనించడం వంటివి చేయగలదని దీనర్థం. ఈ మార్పు ఎందుకు సంభవించిందో మీకు ఖచ్చితంగా తెలియలేదంటే బహుశా మీరు దాన్ని కోరుకొని ఉండకపోవచ్చు.</translation>
<translation id="835238322900896202">అన్ఇన్‌స్టాల్ సమయంలో ఎర్రర్ ఏర్పడింది. దయచేసి టెర్మినల్ ద్వారా అన్ఇన్‌స్టాల్ చేయండి.</translation>
-<translation id="8352772353338965963">బహుళ సైన్ ఇన్ కోసం ఖాతాను జోడించండి. సైన్ ఇన్ చేసిన అన్ని ఖాతాలను పాస్‌వర్డ్ లేకుండానే యాక్సెస్ చేయవచ్చు, కనుక ఈ ఫీచర్‌ను విశ్వసనీయ ఖాతాలతో మాత్రమే ఉపయోగించాలి.</translation>
+<translation id="8352772353338965963">బహుళ సైన్ ఇన్ కోసం ఖాతాను జోడించండి. అన్ని సైన్ ఇన్ చేసిన ఖాతాలను పాస్‌వర్డ్ లేకుండానే యాక్సెస్ చేయవచ్చు, కనుక ఈ ఫీచర్‌ను విశ్వసనీయ ఖాతాలతో మాత్రమే ఉపయోగించాలి.</translation>
<translation id="8353683614194668312">ఇది వీటిని చేయగలదు:</translation>
<translation id="8356197132883132838"><ph name="TITLE" /> - <ph name="COUNT" /></translation>
<translation id="8358685469073206162">పేజీలను పునరుద్ధరించాలా?</translation>
<translation id="8362993567435070757">మీ కీ వెనుకవైపు ఉన్న 6-అంకెల పిన్‌ని చూడండి</translation>
<translation id="8363095875018065315">స్థిరం</translation>
<translation id="8363142353806532503">మైక్రోఫోన్ బ్లాక్ చేయబడింది</translation>
-<translation id="8366396658833131068">మీ నెట్‌వర్క్ కనెక్టివిటీ పునరుద్ధరించబడింది. దయచేసి వేరే నెట్‌వర్క్‌ను ఎంచుకోండి లేదా మీ కియోస్క్ యాప్‌ను ప్రారంభించడానికి కింద ఉన్న 'కొనసాగించు' బటన్ నొక్కండి.</translation>
+<translation id="8366396658833131068">మీ నెట్‌వర్క్ కనెక్టివిటీ పునరుద్ధరించబడింది. దయచేసి వేరే నెట్‌వర్క్‌ను ఎంచుకోండి లేదా మీ కియోస్క్ యాప్‌ను ప్రారంభించడానికి కింది 'కొనసాగించు' బటన్ నొక్కండి.</translation>
<translation id="8368859634510605990">&amp;అన్ని బుక్‌మార్క్‌లను తెరువు</translation>
<translation id="8371695176452482769">ఇప్పుడు మాట్లాడండి</translation>
<translation id="8371925839118813971">{NUM_TABS,plural, =1{సైట్‌ను మ్యూట్ చేయి}other{సైట్‌లను మ్యూట్ చేయి}}</translation>
@@ -4884,7 +4897,7 @@
<translation id="8391712576156218334">చిత్రం అందుబాటులో లేదు. తర్వాత మళ్లీ ప్రయత్నించండి.</translation>
<translation id="8392234662362215700">కీబోర్డ్ లేఅవుట్‌ను మార్చడానికి Control-Shift-Space నొక్కండి.</translation>
<translation id="8392451568018454956"><ph name="USER_EMAIL_ADDRESS" /> కోసం ఎంపికల మెను</translation>
-<translation id="8393511274964623038">ప్లగిన్‌ను ఆపివేయి</translation>
+<translation id="8393511274964623038">ప్లగ్ఇన్‌‌ను ఆపివేయి</translation>
<translation id="8393700583063109961">సందేశాన్ని పంపండి</translation>
<translation id="8395901698320285466">కొలతలు</translation>
<translation id="8396532978067103567">సరికాని పాస్‌వర్డ్</translation>
@@ -4913,6 +4926,7 @@
<translation id="8438566539970814960">శోధనలు మరియు బ్రౌజింగ్‌ను మెరుగుపరచండి</translation>
<translation id="8439506636278576865">ఈ భాషలో పేజీలకు అనువాదం అందించు</translation>
<translation id="8440630305826533614">Linux యాప్‌లు</translation>
+<translation id="8443338615972234259">పర్యవేక్షించబడే మీ వినియోగదారు కోసం దయచేసి కొత్త ఖాతాను సృష్టించండి.</translation>
<translation id="8446884382197647889">మరింత తెలుసుకోండి</translation>
<translation id="8447409163267621480">Ctrl లేదా Altను చేర్చండి</translation>
<translation id="8448729345478502352">మీ స్క్రీన్‌లోని అంశాలను చిన్నవిగా లేదా పెద్దవిగా చేయండి</translation>
@@ -4937,7 +4951,8 @@
<translation id="8468750959626135884">మీ Android ఫోన్‌తో మీ <ph name="DEVICE_TYPE" />ను అన్‌లాక్ చేయండి.</translation>
<translation id="8470028084415844044">మీ పరికరాలన్నింటిలో మీ అన్ని పాస్‌వర్డ్‌‌లను పొందడానికి, సింక్‌ను ఆన్ చేయండి.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" /> కోసం సేవ్ చేసిన పాస్‌వర్డ్‌లు</translation>
-<translation id="8472623782143987204">హార్డ్‌వేర్-వెనుకకు చెయ్యి</translation>
+<translation id="8471635086304129332">మీ అన్ని పరికరాలలో ఈ కార్డ్‌ను ఉపయోగించేందుకు, దీనిని మీ Google ఖాతాలో సేవ్ చేయండి</translation>
+<translation id="8472623782143987204">హార్డ్‌వేర్ మద్దతు గలది</translation>
<translation id="8473863474539038330">చిరునామాలు మరియు మరిన్ని</translation>
<translation id="8475313423285172237">మీ కంప్యూటర్‌లోని మరో ప్రోగ్రామ్ జోడించిన ఎక్స్‌టెన్షన్ కారణంగా Chrome పని చేసే విధానం మారవచ్చు.</translation>
<translation id="8475647382427415476">Google డిస్క్ ప్రస్తుతం "<ph name="FILENAME" />"ని సమకాలీకరించలేకపోయింది. Google డిస్క్ తర్వాత మళ్లీ ప్రయత్నిస్తుంది.</translation>
@@ -4949,16 +4964,16 @@
<translation id="8483248364096924578">IP చిరునామా</translation>
<translation id="8487678622945914333">దగ్గరికి జూమ్ చెయ్యి</translation>
<translation id="8487700953926739672">ఆఫ్‌లైన్‌లో అందుబాటు</translation>
-<translation id="8490896350101740396">కింది కియోస్క్ యాప్‌లు "<ph name="UPDATED_APPS" />" అప్‌డేట్ చేయబడ్డాయి. అప్‌డేట్ ప్రాసెస్‌ను పూర్తి చేయడానికి దయచేసి పరికరాన్ని రీబూట్ చేయండి.</translation>
+<translation id="8490896350101740396">కింది కియోస్క్ యాప్‌లు "<ph name="UPDATED_APPS" />" అప్‌డేట్ అయ్యాయి. దయచేసి అప్‌డేట్‌ ప్రాసెస్‌ను పూర్తి చేయడానికి పరికరాన్ని రీబూట్ చేయండి.</translation>
<translation id="8493236660459102203">మైక్రోఫోన్:</translation>
-<translation id="8496717697661868878">ఈ ప్లగ్ఇన్‌ని అమలు చెయ్యి</translation>
+<translation id="8496717697661868878">ఈ ప్లగ్ఇన్‌ను అమలు చేయి</translation>
<translation id="8497219075884839166">Windows వినియోగాలు</translation>
<translation id="8498214519255567734">కాంతి తక్కువగా ఉన్నప్పుడు మీ స్క్రీన్‌ని చూడటం లేదా చదవడాన్ని సులభతరం చేస్తుంది</translation>
<translation id="8498395510292172881">Chromeలో చదవడం కొనసాగించండి</translation>
<translation id="8502536196501630039">Google Play నుండి యాప్‌లను ఉపయోగించడానికి, మీరు మొదట మీ యాప్‌లను పునరుద్ధరించాలి. ఆ యాప్‌లు కొంత డేటాను కోల్పోయి ఉండవచ్చు.</translation>
<translation id="8503813439785031346">యూజర్‌పేరు</translation>
<translation id="850875081535031620">హానికరమైన సాఫ్ట్‌వేర్ కనుగొనబడలేదు</translation>
-<translation id="8509646642152301857">స్పెల్ చెక్ నిఘంటువును డౌన్‌లోడ్ చేయడం విఫలమైంది.</translation>
+<translation id="8509646642152301857">స్పెల్ చెక్ తనిఖీ నిఘంటువును డౌన్‌లోడ్ చేయడం విఫలమైంది.</translation>
<translation id="8512476990829870887">ప్రాసెస్‌ని ముగించు</translation>
<translation id="851263357009351303">చిత్రాలను చూపించడానికి ఎల్లప్పుడూ <ph name="HOST" />ను అనుమతించు</translation>
<translation id="8521475323816527629">మీ యాప్‌లను వేగంగా పొందండి</translation>
@@ -4973,7 +4988,7 @@
<translation id="8535005006684281994">Netscape సర్టిఫికెట్ పునరుద్ధరణ URL</translation>
<translation id="8538358978858059843">ప్రసారానికి క్లౌడ్ సేవలను ప్రారంభించమంటారా?</translation>
<translation id="8539727552378197395">లేదు (Httpమాత్రమే)</translation>
-<translation id="8545575359873600875">క్షమించండి, మీ పాస్‌వర్డ్‌ను ధృవీకరించడం సాధ్యపడలేదు. ఈ పర్యవేక్షించబడే వినియోగదారు యొక్క నిర్వాహకులు పాస్‌వర్డ్‌ను ఇటీవల మార్చి ఉండవచ్చు. అలా అయితే, మీరు సైన్ ఇన్ చేసే తరువాత సారి కొత్త పాస్‌వర్డ్ వర్తింపజేయబడుతుంది. మీ పాత పాస్‌వర్డ్‌ను ఉపయోగించడాన్ని ప్రయత్నించండి.</translation>
+<translation id="8545575359873600875">క్షమించండి, మీ పాస్‌వర్డ్‌ను ధృవీకరించడం సాధ్యపడలేదు. ఈ పర్యవేక్షించబడే వినియోగదారు యొక్క నిర్వాహకులు పాస్‌వర్డ్‌ను ఇటీవల మార్చి ఉండవచ్చు. అలా అయితే, మీరు సైన్ ఇన్ చేసే తర్వాతిసారి కొత్త పాస్‌వర్డ్ వర్తింపజేయబడుతుంది. మీ పాత పాస్‌వర్డ్‌ను ఉపయోగించడాన్ని ప్రయత్నించండి.</translation>
<translation id="8546186510985480118">పరికరంలో తక్కువ స్థలం ఉంది</translation>
<translation id="8546306075665861288">చిత్రం కాష్</translation>
<translation id="8546541260734613940">[*.]example.com</translation>
@@ -4985,7 +5000,7 @@
<translation id="8551388862522347954">లైసెన్స్‌లు</translation>
<translation id="8553342806078037065">ఇతర వ్యక్తులను నిర్వహించు</translation>
<translation id="8554899698005018844">భాష లేదు</translation>
-<translation id="855773602626431402">శాండ్‌బాక్స్ చేయని ప్లగిన్ ఈ పేజీలో అమలు కానీయకుండా నిరోధించబడింది.</translation>
+<translation id="855773602626431402">శాండ్‌బాక్స్ చేయని ప్లగ్ఇన్‌ ఈ పేజీలో అమలు కానీయకుండా నిరోధించబడింది.</translation>
<translation id="8557930019681227453">మానిఫెస్ట్</translation>
<translation id="8559694214572302298">ఇమేజ్ డీకోడర్</translation>
<translation id="8561853412914299728"><ph name="TAB_TITLE" /> <ph name="EMOJI_PLAYING" /></translation>
@@ -5000,7 +5015,7 @@
<translation id="8579285237314169903"><ph name="NUMBER_OF_FILES" /> అంశాలను సమకాలీకరిస్తోంది...</translation>
<translation id="857943718398505171">అనుమతించబడింది (సిఫార్సు చేయబడింది)</translation>
<translation id="8581809080475256101">ముందుకు వెళ్లడానికి నొక్కండి, చరిత్రను చూసేందుకు సందర్భ మెనూను నొక్కండి</translation>
-<translation id="8584280235376696778">&amp;వీడియోను కొత్త‌ టాబ్‌లో తెరువు</translation>
+<translation id="8584280235376696778">&amp;వీడియోను కొత్త‌ ట్యాబ్‌లో తెరువు</translation>
<translation id="8588866096426746242">ప్రొఫైల్ గణాంకాలను చూపు</translation>
<translation id="8588868914509452556"><ph name="WINDOW_TITLE" /> - హెడ్‌సెట్ ద్వారా VR కంటెంట్‌ని ప్రదర్శిస్తోంది.</translation>
<translation id="8590375307970699841">ఆటోమేటిక్ అప్డేట్లను సెట్ అప్ చేయండి</translation>
@@ -5009,10 +5024,9 @@
<translation id="8594908476761052472">వీడియోను క్యాప్చర్ చేయి</translation>
<translation id="8596540852772265699">అనుకూల ఫైళ్ళు</translation>
<translation id="8597845839771543242">లక్షణ ఆకృతి:</translation>
-<translation id="8598453409908276158">శాండ్‌బాక్స్ చేయని ప్లగిన్ బ్లాక్ చేయబడింది</translation>
+<translation id="8598453409908276158">శాండ్‌బాక్స్ చేయని ప్లగ్ఇన్‌ బ్లాక్ చేయబడింది</translation>
<translation id="8601206103050338563">TLS WWW క్లయింట్ ప్రామాణీకరణ</translation>
<translation id="8602851771975208551">మీ కంప్యూటర్‌లోని మరో ప్రోగ్రామ్ జోడించిన యాప్ కారణంగా Chrome పని చేసే విధానం మారవచ్చు.</translation>
-<translation id="8604763363205185560">Chrome మరియు దాని భద్రతను మెరుగుపరచడంలో సహాయపడండి</translation>
<translation id="8605428685123651449">SQLite మెమరీ</translation>
<translation id="8606726445206553943">మీ MIDI పరికరాలను ఉపయోగించాలనుకుంటోంది</translation>
<translation id="8609465669617005112">పైకి తరలించు</translation>
@@ -5029,8 +5043,8 @@
<translation id="8627795981664801467">సురక్షిత కనెక్షన్‌ల మాత్రమే</translation>
<translation id="8630903300770275248">పర్యవేక్షించబడే వినియోగదారుని దిగుమతి చేయి</translation>
<translation id="8631032106121706562">పూరేకులు</translation>
-<translation id="8637542770513281060">మీ కంప్యూటర్‌లో ఒక సురక్షిత మాడ్యూల్ ఉంది, Chrome OSలో అనేక కీలకమైన భద్రతా ఫీచర్‌లను అమలు చేయడానికి ఇది ఉపయోగించబడుతుంది. Chromebook సహాయ కేంద్రంలో దీని గురించి మరింత తెలుసుకోవడానికి, ఇక్కడికి వెళ్లండి: https://support.google.com/chromebook/?p=sm</translation>
-<translation id="8637688295594795546">సిస్టమ్ అప్‌డేట్ అందుబాటులో ఉంది. డౌన్‌లోడ్ చెయ్యడానికి సిద్ధం చేస్తోంది...</translation>
+<translation id="8637542770513281060">మీ కంప్యూటర్‌లో ఒక సురక్షిత మాడ్యూల్ ఉంది. Chrome OSలో అనేక కీలకమైన భద్రతా ఫీచర్‌లను అమలు చేయడానికి ఇది ఉపయోగించబడుతుంది. Chromebook సహాయ కేంద్రంలో దీని గురించి మరింత తెలుసుకోండి. ఇక్కడికి వెళ్లండి: https://support.google.com/chromebook/?p=sm</translation>
+<translation id="8637688295594795546">సిస్టమ్ అప్‌డేట్‌ అందుబాటులో ఉంది. డౌన్‌లోడ్ చేయ‌డానికి సిద్ధం చేస్తోంది...</translation>
<translation id="8639047128869322042">హానికరమైన సాఫ్ట్‌వేర్‌ కోసం తనిఖీ చేస్తోంది...</translation>
<translation id="8642171459927087831">యాక్సెస్ టోకెన్</translation>
<translation id="8642895855701880552"><ph name="BEGIN_LINK1" />సిస్టమ్, యాప్ సమాచారం<ph name="END_LINK1" /> పంపు</translation>
@@ -5045,7 +5059,7 @@
<translation id="8654151524613148204">మీ కంప్యూటర్ నిర్వహించడానికి ఫైల్ చాలా పెద్దదిగా ఉంది. క్షమించండి.</translation>
<translation id="8655295600908251630">ఛానల్</translation>
<translation id="8655319619291175901">అయ్యో, ఏదో తప్పు జరిగింది.</translation>
-<translation id="8655972064210167941">మీ పాస్‌వర్డ్‌ను ధృవీకరించనందున సైన్-ఇన్ విఫలమైంది. దయచేసి మీ నిర్వాహకుడిని సంప్రదించండి లేదా మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="8655972064210167941">మీ పాస్‌వర్డ్‌ను ధృవీకరించలేకపోయినందున సైన్-ఇన్ విఫలమైంది. దయచేసి మీ నిర్వాహకుడిని సంప్రదించండి లేదా మళ్లీ ప్రయత్నించండి.</translation>
<translation id="8656619792520327915">మరొక బ్లూటూత్ భద్రతా కీని జోడించు</translation>
<translation id="8656768832129462377">తనిఖీ చేయవద్దు</translation>
<translation id="8658645149275195032"><ph name="APP_NAME" /> మీ స్క్రీన్ మరియు ఆడియోను <ph name="TAB_NAME" />తో భాగస్వామ్యం చేస్తోంది.</translation>
@@ -5058,7 +5072,7 @@
<translation id="8662978096466608964">వాల్‌పేపర్‌ను Chrome సెట్ చేయలేదు.</translation>
<translation id="8663099077749055505"><ph name="HOST" />లో ఎల్లప్పుడూ బహుళ స్వయంచాలక డౌన్‌లోడ్‌లను బ్లాక్ చేయి</translation>
<translation id="8664389313780386848">పేజీ మూలాన్ని &amp;వీక్షించండి</translation>
-<translation id="866611985033792019">ఇమెయిల్ వినియోగదారులను గుర్తించడానికి ఈ స‌ర్టిఫికెట్‌ను విశ్వసిస్తుంది</translation>
+<translation id="866611985033792019">ఇమెయిల్ వినియోగదారులను గుర్తించడానికి ఈ ప్రమాణపత్రాన్ని విశ్వసిస్తుంది</translation>
<translation id="8666584013686199826">సైట్ USB పరికరాలను యాక్సెస్ చేయాలనుకున్నప్పుడు అడుగు</translation>
<translation id="8667328578593601900">ఇప్పుడు <ph name="FULLSCREEN_ORIGIN" /> పూర్తి స్క్రీన్‌లో ఉంది, అది మీ మౌస్ కర్సర్‌ను నిలిపివేసింది.</translation>
<translation id="8669284339312441707">తీక్షణమైనది</translation>
@@ -5071,8 +5085,8 @@
<translation id="8676374126336081632">ఇన్‌పుట్‌ను తీసివేయండి</translation>
<translation id="8677212948402625567">అన్నీ కుదించు...</translation>
<translation id="8678648549315280022">డౌన్‌లోడ్ సెట్టింగ్‌లను నిర్వహించండి...</translation>
-<translation id="8678933587484842200">మీరు ఈ అప్లికేషన్‌ని ఎలా ప్రారంభించాలనుకుంటున్నారు?</translation>
-<translation id="8680251145628383637">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లను మీ అన్ని పరికరాల్లో పొందడానికి సైన్ ఇన్ చేయండి. మీరు మీ Google సేవలకు కూడా స్వయంచాలకంగా సైన్ ఇన్ చేయబడతారు.</translation>
+<translation id="8678933587484842200">మీరు ఈ అప్లికేషన్‌ను ఎలా ప్రారంభించాలనుకుంటున్నారు?</translation>
+<translation id="8680251145628383637">మీ బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లను మీ అన్ని పరికరాలలో పొందడానికి సైన్ ఇన్ చేయండి. మీరు మీ Google సేవలకు కూడా ఆటోమేటిక్‌గా సైన్ ఇన్ చేయబడతారు.</translation>
<translation id="8686213429977032554">ఈ డిస్క్ ఫైల్ ఇంకా భాగస్వామ్యం చేయబడలేదు</translation>
<translation id="8688579245973331962">మీ పేరు కనిపించలేదా?</translation>
<translation id="8688591111840995413">పాస్‌వర్డ్ చెల్లదు</translation>
@@ -5111,7 +5125,7 @@
<translation id="8732030010853991079">ఈ చిహ్నంపై క్లిక్ చేయడం ద్వారా ఈ ఎక్సటెన్షన్‌ను ఉపయోగించండి.</translation>
<translation id="8732212173949624846">మీ సైన్-ఇన్ చేసిన అన్ని పరికరాల్లో మీ బ్రౌజింగ్ చరిత్రను చదవడం మరియు మార్చడం</translation>
<translation id="8732844209475700754">గోప్యత, భద్రత మరియు డేటా సేకరణకు సంబంధించిన మరిన్ని సెట్టింగ్‌లు</translation>
-<translation id="8734073480934656039">ఈ సెట్టింగ్‌ను ప్రారంభించడం వలన కియోస్క్ యాప్‌లు ప్రారంభంలో ఆటోమేటిక్‌గా లాంచ్ కావడానికి అనుమతించబడతాయి.</translation>
+<translation id="8734073480934656039">ఈ సెట్టింగ్‌ను ప్రారంభించడం వలన కియోస్క్ యాప్‌లు ప్రారంభంలో ఆటోమేటిక్‌గా ప్రారంభించడానికి అనుమతించబడతాయి.</translation>
<translation id="873545264931343897"><ph name="PLUGIN_NAME" />ను అప్‌డేట్ చేయడం పూర్తయినప్పుడు, దానిని యాక్టివేట్ చేయడానికి పేజీని మళ్లీ లోడ్ చేయండి</translation>
<translation id="8736288397686080465">ఈ సైట్ నేపథ్యంలో నవీకరించబడింది.</translation>
<translation id="8737685506611670901"><ph name="REPLACED_HANDLER_TITLE" />కి బదులుగా <ph name="PROTOCOL" /> లింక్‌లను తెరవాలనుకుంటోంది</translation>
@@ -5122,19 +5136,19 @@
<translation id="8748384418490037181">Smart Lock ఎంపికలు</translation>
<translation id="8749863574775030885">తెలియని విక్రేత అందించిన USB పరికరాలకు యాక్సెస్</translation>
<translation id="8750155211039279868"><ph name="ORIGIN" /> ఈ సీరియల్ పోర్ట్‌లలో ఒకదానితో కనెక్ట్ (అనుసంధానం) కావాలని కోరుకుంటుంది</translation>
-<translation id="8754200782896249056">&lt;p&gt;<ph name="PRODUCT_NAME" />ని మద్దతు ఉన్న డెస్క్‌టాప్ పరిసరంలో అమలు చేస్తున్నప్పుడు, సిస్టమ్ ప్రాక్సీ సెట్టింగ్‌లు ఉపయోగించబడతాయి. అయితే, మీ సిస్టమ్ మద్దతు ఇవ్వడం లేదు లేదా మీ సిస్టమ్ కాన్ఫిగరేషన్‌ను ప్రారంభించడంలో సమస్య ఉంది.&lt;/p&gt;
+<translation id="8754200782896249056">&lt;p&gt;When running <ph name="PRODUCT_NAME" />ను మద్దతు ఉన్న డెస్క్‌టాప్ పరిసరంలో అమలు చేస్తున్నప్పుడు, సిస్టమ్ ప్రాక్సీ సెట్టింగ్‌లు ఉపయోగించబడతాయి. అయితే, మీ సిస్టమ్ మద్దతు ఇవ్వడం లేదు లేదా మీ సిస్టమ్ కాన్ఫిగరేషన్‌ను ప్రారంభించడంలో సమస్య ఉంది.&lt;/p&gt;
- &lt;p&gt;కానీ మీరు ఇప్పటికీ ఆదేశ లైన్‌ ద్వారా కాన్ఫిగర్ చేయవచ్చు. దయచేసి ఫ్లాగ్‌లు, పరిసర చరరాశులకు సంబంధించిన మరింత సమాచారం కోసం &lt;code&gt;man <ph name="PRODUCT_BINARY_NAME" />&lt;/code&gt;ని సందర్శించండి.&lt;/p&gt;</translation>
+ &lt;p&gt;కానీ మీరు ఇప్పటికీ ఆదేశ పంక్తి ద్వారా కాన్ఫిగర్ చేయవచ్చు. దయచేసి ఫ్లాగ్‌లు మరియు పరిసర చరరాశులకు సంబంధించిన మరింత సమాచారం కోసం &lt;code&gt;man <ph name="PRODUCT_BINARY_NAME" />&lt;/code&gt; ని సందర్శించండి.&lt;/p&gt;</translation>
<translation id="8755376271068075440">&amp;పెద్దగా</translation>
<translation id="8756969031206844760">పాస్‌వర్డ్‌ను అప్‌డేట్ చేయాలా?</translation>
-<translation id="8757090071857742562">డెస్క్‌టాప్‌ను ప్రసారం చేయడం సాధ్యపడలేదు. మీ స్క్రీన్‌ను షేర్ చేయడం ప్రారంభించడానికి మీరు ప్రాంప్ట్‌ని నిర్ధారించారో లేదో సరిచూసుకోవడానికి తనిఖీ చేయండి.</translation>
+<translation id="8757090071857742562">డెస్క్‌టాప్‌ను ప్రసారం చేయడం సాధ్యపడలేదు. మీ స్క్రీన్‌ను షేర్‌ చేయడం ప్రారంభించడానికి మీరు ప్రాంప్ట్‌ను నిర్ధారించారో లేదో సరిచూసుకోవడానికి తనిఖీ చేయండి.</translation>
<translation id="8757803915342932642">Google క్లౌడ్‌ పరికరాల్లోని పరికరం</translation>
<translation id="8758418656925882523">డిక్టేషన్‌ను ప్రారంభించండి (టైప్ చేయడానికి మాట్లాడండి)</translation>
<translation id="8759408218731716181">బహుళ సైన్-ఇన్‌ను సెటప్ చేయలేరు</translation>
<translation id="8759753423332885148">మరింత తెలుసుకోండి.</translation>
<translation id="8762886931014513155">మీ <ph name="DEVICE_TYPE" />ని అప్‌డేట్ చేయాలి</translation>
<translation id="8767621466733104912">అందరు వినియోగదారుల కోసం Chromeను ఆటోమేటిక్‌గా అప్‌డేట్ చేయి</translation>
-<translation id="8770406935328356739">పొడిగింపు మూలం డైరెక్టరీ</translation>
+<translation id="8770406935328356739">ఎక్స్‌టెన్ష‌న్‌ మూలం డైరెక్టరీ</translation>
<translation id="8770507190024617908">వ్యక్తులను నిర్వహించు</translation>
<translation id="8774934320277480003">ఎగువ అంచు</translation>
<translation id="8775144690796719618">URL చెల్లదు</translation>
@@ -5163,7 +5177,7 @@
<translation id="8808478386290700967">వెబ్ స్టోర్</translation>
<translation id="8808686172382650546">పిల్లి</translation>
<translation id="8810671769985673465">జిప్ చేయడంలో విఫలమైంది, ఈ అంశం ఉనికిలో ఉంది: "<ph name="FILE_NAME" />"</translation>
-<translation id="8813698869395535039"><ph name="USERNAME" />కి సైన్ ఇన్ చేయడం సాధ్యపడదు</translation>
+<translation id="8813698869395535039"><ph name="USERNAME" />కు సైన్ ఇన్ చేయడం సాధ్యపడదు</translation>
<translation id="8813811964357448561">పేపర్ షీట్</translation>
<translation id="8814190375133053267">Wi-Fi</translation>
<translation id="8814687660896548945">దయచేసి వేచి ఉండండి. ఆర్కైవ్ స్కాన్ అవుతోంది...</translation>
@@ -5178,7 +5192,7 @@
<translation id="8824701697284169214">పే&amp;జీని జోడించండి...</translation>
<translation id="8827752199525959199">మరిన్ని చర్యలు, <ph name="DOMAIN" />లో <ph name="USERNAME" /> కోసం పాస్‌వర్డ్</translation>
<translation id="8828933418460119530">DNS పేరు</translation>
-<translation id="8830796635868321089">ప్రస్తుత ప్రాక్సీ సెట్టింగ్‌లను ఉపయోగించి అప్‌డేట్‌ను తనిఖీ చేయడం విఫలమైంది. దయచేసి మీ <ph name="PROXY_SETTINGS_LINK_START" />ప్రాక్సీ సెట్టింగ్‌ల<ph name="PROXY_SETTINGS_LINK_END" />ను సర్దుబాటు చేయండి.</translation>
+<translation id="8830796635868321089">ప్రస్తుత ప్రాక్సీ సెట్టింగ్‌లను ఉపయోగించి అప్‌‌డేట్‌ను తనిఖీ చేయడం విఫలమైంది. దయచేసి మీ <ph name="PROXY_SETTINGS_LINK_START" />ప్రాక్సీ సెట్టింగ్‌ల<ph name="PROXY_SETTINGS_LINK_END" />ను సర్దుబాటు చేయండి.</translation>
<translation id="8834039744648160717">నెట్‌వర్క్ కాన్ఫిగరేషన్‌ను <ph name="USER_EMAIL" /> నియంత్రిస్తున్నారు.</translation>
<translation id="8834164572807951958">'<ph name="DESTINATION_NAME" />' యొక్క సభ్యులు ఈ అంశాల కాపీకి యాక్సెస్‌ను పొందుతారు.</translation>
<translation id="8838770651474809439">హాంబర్గర్</translation>
@@ -5188,6 +5202,7 @@
<translation id="8846141544112579928">కీబోర్డ్ కోసం శోధిస్తోంది...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">మీరు మీ పరికరాలను కనెక్ట్ చేసినప్పుడు, మీ Chromebook ఈ కింది వాటిని చేయవచ్చని మీరు అంగీకరిస్తున్నారు:</translation>
+<translation id="8850251000316748990">మరిన్ని చూడండి...</translation>
<translation id="8859057652521303089">మీ భాషను ఎంచుకోండి:</translation>
<translation id="8859174528519900719">సబ్‌ఫ్రేమ్: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel స్ప్రెడ్‌షీట్</translation>
@@ -5196,7 +5211,7 @@
<translation id="8868626022555786497">ఉపయోగంలో ఉంది</translation>
<translation id="8870318296973696995">హోమ్ పేజీ</translation>
<translation id="8870413625673593573">ఇటీవల మూసివేసినవి</translation>
-<translation id="8871551568777368300">నిర్వాహకులు పిన్ చేసారు</translation>
+<translation id="8871551568777368300">నిర్వాహకులు పిన్ చేశారు</translation>
<translation id="8871696467337989339">మీరు మద్దతులేని ఆదేశ పంక్తి ఫ్లాగ్‌ను ఉపయోగిస్తున్నారు: <ph name="BAD_FLAG" />. స్థిరత్వం మరియు భద్రతలను మీరు నష్టపోవచ్చు.</translation>
<translation id="8871974300055371298">కంటెంట్ సెట్టింగ్‌లు</translation>
<translation id="8872155268274985541">చెల్లని కియోస్క్ బాహ్య అప్‌డేట్‌ మానిఫెస్ట్ ఫైల్ కనుగొనబడింది. కియోస్క్ యాప్‌ను అప్‌డేట్ చేయ‌డంలో విఫలమైంది. దయచేసి USB స్టిక్‌ను తీసివేయండి.</translation>
@@ -5217,7 +5232,7 @@
<translation id="8895454554629927345">బుక్‌మార్క్‌ జాబితా</translation>
<translation id="8898786835233784856">తదుపరి టాబ్‌ను ఎంచుకో</translation>
<translation id="8898840733695078011">సిగ్నల్ సామర్థ్యం</translation>
-<translation id="8899851313684471736">లింక్‌ను క్రొత్త &amp;విండోలో తెరువు</translation>
+<translation id="8899851313684471736">కొత్త &amp;విండోలో లింక్‌ను తెరువు</translation>
<translation id="8902667442496790482">వినడానికి-ఎంచుకోండి ఎంపికలను తెరువు</translation>
<translation id="8904976895050290827">Chrome Sync</translation>
<translation id="890616557918890486">మూలాధారాన్ని మార్చు</translation>
@@ -5229,7 +5244,7 @@
<translation id="891365694296252935">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. ఈ పరికరం ప్రస్తుతం సమస్య విశ్లేషణ, అలాగే పరికర, యాప్ వినియోగ డేటాను ఆటోమేటిక్‌గా Googleకి పంపుతుంది. ఇది మీ చిన్నారి గురించి గుర్తించడానికి ఉపయోగించబడదు, ఇది కేవలం సిస్టమ్, యాప్ స్థిరత్వానికి, అలాగే ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. ఈ సెట్టింగ్‌ని యజమాని అమలు చేసారు. మీ చిన్నారి కోసం అదనపు వెబ్ &amp; యాప్ కార్యకలాపాన్ని ఆన్ చేసినట్లయితే, ఈ డేటా వారి Google ఖాతాలో సేవ్ కావచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
<translation id="8915370057835397490">సూచన లోడ్ అవుతోంది</translation>
<translation id="8916476537757519021">అజ్ఞాత సబ్‌ఫ్రేమ్: <ph name="SUBFRAME_SITE" /></translation>
-<translation id="8919275547519617350">మీ అన్ని పరికరాలలో మీ అన్ని పాస్‌వర్డ్‌‌లను పొందాలంటే, సైన్ ఇన్ చేసి, సింక్‌ని ఆన్ చేయండి.</translation>
+<translation id="8919275547519617350">మీ అన్ని పరికరాలలో మీ అన్ని పాస్‌వర్డ్‌‌లను పొందడానికి, సైన్ ఇన్ చేసి, సింక్‌ను ఆన్ చేయండి.</translation>
<translation id="8921366488406707015">మీ భద్రతా కీని ధృవీకరిస్తోంది...</translation>
<translation id="8922013791253848639">ఎల్లప్పుడూ ఈ సైట్‌లోని ప్రకటనలను అనుమతించు</translation>
<translation id="8925458182817574960">&amp;సెట్టింగ్‌లు</translation>
@@ -5243,13 +5258,13 @@
<translation id="8940081510938872932">ప్రస్తుతం మీ కంప్యూటర్ అనేక చర్యలను అమలు చేస్తోంది. తర్వాత మళ్లీ ప్రయత్నించండి.</translation>
<translation id="8941173171815156065">'<ph name="PERMISSION" />' అనుమతిని ఉపసంహరించు</translation>
<translation id="894360074127026135">Netscape అంతర్జాతీయ స్టెప్‌-అప్</translation>
-<translation id="8944099748578356325">బ్యాటరీని మరింత శీఘ్రంగా ఉపయోగిస్తుంది (ప్రస్తుతం <ph name="BATTERY_PERCENTAGE" />% ఉంది)</translation>
+<translation id="8944099748578356325">బ్యాటరీని మరింత వేగంగా ఉపయోగిస్తుంది (ప్రస్తుతం <ph name="BATTERY_PERCENTAGE" />% ఉంది)</translation>
<translation id="8944964446326379280"><ph name="APP_NAME" /> ఒక విండోను <ph name="TAB_NAME" />తో భాగస్వామ్యం చేస్తోంది.</translation>
-<translation id="8946359700442089734">డీబగ్గింగ్ లక్షణాలు ఈ <ph name="IDS_SHORT_PRODUCT_NAME" /> పరికరంలో పూర్తిగా ప్రారంభించబడలేదు.</translation>
+<translation id="8946359700442089734">డీబగ్గింగ్ ఫీచ‌ర్‌లు ఈ <ph name="IDS_SHORT_PRODUCT_NAME" /> పరికరంలో పూర్తిగా ప్రారంభించబడలేదు.</translation>
<translation id="894871326938397531">అజ్ఞాత మోడ్ నుండి నిష్క్రమించాలా?</translation>
<translation id="895347679606913382">ప్రారంభిస్తోంది...</translation>
<translation id="895944840846194039">JavaScript మెమరీ</translation>
-<translation id="8959810181433034287">పర్యవేక్షించబడే వినియోగదారు సైన్ ఇన్ చేయడానికి ఈ పాస్‌వర్డ్‌ను ఉపయోగించాల్సి ఉంటుంది, అందువల్ల సురక్షితమైన పాస్‌వర్డ్‌ను ఎంచుకుని, దాన్ని పర్యవేక్షించబడే వినియోగదారుతో చర్చించాలని గుర్తుంచుకోండి.</translation>
+<translation id="8959810181433034287">పర్యవేక్షించబడే వినియోగదారు సైన్ ఇన్ చేయడానికి ఈ పాస్‌వర్డ్‌ను ఉపయోగించాల్సి ఉంటుంది, అందువల్ల సురక్షితమైన పాస్‌వర్డ్‌ను ఎంచుకుని, దానిని పర్యవేక్షించబడే వినియోగదారుతో చర్చించాలని గుర్తుంచుకోండి.</translation>
<translation id="8962083179518285172">వివరాలను దాచిపెట్టు</translation>
<translation id="8962918469425892674">ఈ సైట్ మోషన్ లేదా లైట్ సెన్సార్‌లను ఉపయోగిస్తోంది.</translation>
<translation id="8965037249707889821">పాత పాస్‌వర్డ్‌ను నమోదు చేయండి</translation>
@@ -5258,7 +5273,7 @@
<translation id="8967866634928501045">చూపడం కోసం Alt Shift A నొక్కండి</translation>
<translation id="8970203673128054105">ప్రసార మోడ్ జాబితాను వీక్షించండి</translation>
<translation id="89720367119469899">ఎస్కేప్</translation>
-<translation id="8972513834460200407">Google సర్వర్‌ల నుండి డౌన్‌లోడ్‌లను ఫైర్‌వాల్ బ్లాక్ చేయడం లేదని నిర్ధారించుకోవడానికి దయచేసి మీ నెట్‌వర్క్ నిర్వాహకుడిని సంప్రదించండి.</translation>
+<translation id="8972513834460200407">దయచేసి Google సర్వర్‌ల నుండి డౌన్‌లోడ్‌లను ఫైర్‌వాల్ బ్లాక్ చేయడం లేదని నిర్ధారించుకోవడానికి మీ నెట్‌వర్క్ నిర్వాహకుడిని సంప్రదించండి.</translation>
<translation id="8973557916016709913">జూమ్ స్థాయిని తీసివేయి</translation>
<translation id="8973596347849323817">మీరు మీ అవసరాలకు అనుగుణంగా ఈ పరికరాన్ని అనుకూలీకరించవచ్చు. ఈ యాక్సెస్ ఫీచర్‌లను సెట్టింగ్‌లలో తర్వాత మార్చవచ్చు.</translation>
<translation id="897414447285476047">కనెక్షన్ సమస్య కారణంగా గమ్యస్థాన ఫైల్ సంపూర్ణంగా లేదు.</translation>
@@ -5300,7 +5315,7 @@
<translation id="9030515284705930323">మీ సంస్థ మీ ఖాతా కోసం Google Play స్టోర్‌ను ప్రారంభించలేదు. మరింత సమాచారం కోసం మీ నిర్వాహకులను సంప్రదించండి.</translation>
<translation id="9033857511263905942">&amp;అతికించు</translation>
<translation id="9034924485347205037">Linux ఫైల్‌లు</translation>
-<translation id="9035012421917565900">ఈ అంశాలను '<ph name="DESTINATION_NAME" />'లోకి తిరిగి తరలించడం సాధ్యపడదు. కాబ‌ట్టి మీరు ఈ చర్యను రద్దు చేయలేరు.</translation>
+<translation id="9035012421917565900">ఈ అంశాలను '<ph name="DESTINATION_NAME" />'లోకి తిరిగి తరలించడం సాధ్యపడదు. కాబట్టి మీరు ఈ చర్యను రద్దు చేయలేరు.</translation>
<translation id="9037965129289936994">అసలైనది చూపు</translation>
<translation id="9038430547971207796">తర్వాతిసారి, మీ ఫోన్ మీ <ph name="DEVICE_TYPE" />ను అన్‌లాక్ చేస్తుంది. సెట్టింగ్‌లలో Smart Lockను ఆఫ్ చేయండి.</translation>
<translation id="9038620279323455325">"<ph name="FILE_NAME" />" పేరు గల ఫైల్ ఇప్పటికే ఉంది. దయచేసి వేరొక పేరును ఎంచుకోండి.</translation>
@@ -5332,7 +5347,7 @@
<translation id="9066782832737749352">వచనం నుండి ప్రసంగం</translation>
<translation id="9073281213608662541">PAP</translation>
<translation id="90737709606140813">మీ కీని ఈ పరికరానికి జత చేయండి, తద్వారా మీరు మీ ఖాతాకు సైన్ ఇన్ చేయడానికి దాన్ని ఉపయోగించవచ్చు</translation>
-<translation id="9074739597929991885">Bluetooth</translation>
+<translation id="9074739597929991885">బ్లూటూత్</translation>
<translation id="9074836595010225693">USB మౌస్ కనెక్ట్ చేయబడింది</translation>
<translation id="9076523132036239772">క్షమించండి, మీ ఇమెయిల్ లేదా పాస్‌వర్డ్ ధృవీకరించబడలేదు. మొదట నెట్‌వర్క్‌కి కనెక్ట్ చేయడానికి ప్రయత్నించండి.</translation>
<translation id="9084064520949870008">విండో వలె తెరువు</translation>
@@ -5346,10 +5361,10 @@
<translation id="9100765901046053179">అధునాతన సెట్టింగ్‌లు</translation>
<translation id="9101691533782776290">యాప్‌ను ప్రారంభించు</translation>
<translation id="9102610709270966160">ఎక్స్‌టెన్ష‌న్‌ను ప్రారంభించు</translation>
-<translation id="9103868373786083162">వెనుకకు వెళ్లడానికి నొక్కండి, చరిత్రను చూసేందుకు సందర్భ మెనూను నొక్కండి</translation>
+<translation id="9103868373786083162">చరిత్రను చూసేందుకు వెనుకకు వెళ్లు, సందర్భ మెనూ నొక్కండి</translation>
<translation id="9104396740804929809">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. సమస్య విశ్లేషణ, పరికరం, యాప్ వినియోగ డేటాను Googleకి ఆటోమేటిక్‌గా పంపడం ద్వారా మీ Android అనుభవాన్ని మెరుగుపరచడంలో సహాయపడండి. ఇది సిస్టమ్, యాప్ స్థిరత్వానికి, అలాగే ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. ఈ సెట్టింగ్‌ని యజమాని అమలు చేసారు. ఈ పరికరానికి సంబంధించిన విశ్లేషణ, వినియోగ డేటాను Googleకి పంపేలా యజమాని ఎంచుకోవచ్చు. మీ అదనపు వెబ్ &amp; యాప్ కార్యకలాపం సెట్టింగ్‌ను ఆన్ చేసినట్లయితే, ఈ డేటా మీ Google ఖాతాలో సేవ్ చేయబడవచ్చు. <ph name="BEGIN_LINK1" />మరింత తెలుసుకోండి<ph name="END_LINK1" /></translation>
<translation id="9109122242323516435">స్థలాన్ని ఖాళీ చేయడానికి, పరికర నిల్వ నుండి ఫైల్‌లను తొలగించండి.</translation>
-<translation id="9110990317705400362">మేము మీ బ్రౌజింగ్‌ను సురక్షితం చేసే మార్గాల కోసం నిరంతరం శోధిస్తున్నాము. గతంలో, ఏ వెబ్‌సైట్ అయినా మీ బ్రౌజర్‌కు ఎక్సటెన్షన్‌ని జోడించడానికి మిమ్మల్ని ప్రాంప్ట్ చేయవచ్చు. Google Chrome తాజా వెర్షన్‌లలో, మీరు తప్పనిసరిగా ఎక్సటెన్షన్‌ల పేజీలో వాటిని జోడించడం ద్వారా ఈ ఎక్సటెన్షన్‌లను ఇన్‌స్టాల్ చేయాలనుకుంటున్నట్లు Chromeకి ప్రత్యేకించి తెలియజేయాలి. <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation>
+<translation id="9110990317705400362">మేము మీ బ్రౌజింగ్‌ను సురక్షితం చేసే మార్గాల కోసం నిరంతరం శోధిస్తున్నాము. గతంలో, ఏ వెబ్‌సైట్ అయినా మీ బ్రౌజర్‌కు ఎక్స్‌టెన్ష‌న్‌ను జోడించడానికి మిమ్మల్ని ప్రాంప్ట్ చేయవచ్చు. Google Chrome తాజా వెర్ష‌న్‌ల్లో, మీరు తప్పనిసరిగా ఎక్స్‌టెన్ష‌న్‌ల పేజీలో వాటిని జోడించడం ద్వారా ఈ ఎక్స్‌టెన్ష‌న్‌లను ఇన్‌స్టాల్ చేయాలనుకుంటున్నట్లు Chromeకు ప్రత్యేకించి తెలియజేయాలి. <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation>
<translation id="9111102763498581341">అన్‌లాక్ చేయి</translation>
<translation id="9111395131601239814"><ph name="NETWORKDEVICE" />: <ph name="STATUS" /></translation>
<translation id="9112748030372401671">మీ వాల్‌పేపర్‌ను మార్చండి</translation>
@@ -5377,7 +5392,7 @@
<translation id="9147304170847707004">ప్రమాణీకరణ పద్ధతి</translation>
<translation id="9147392381910171771">&amp;ఐచ్ఛికాలు</translation>
<translation id="9148058034647219655">నిష్క్రమించు</translation>
-<translation id="9148126808321036104">మళ్ళీ సైన్ ఇన్ చెయ్యండి</translation>
+<translation id="9148126808321036104">మళ్ళీ సైన్ ఇన్ చేయండి</translation>
<translation id="9149866541089851383">సవరించు...</translation>
<translation id="9150045010208374699">మీ కెమెరాను ఉపయోగించండి</translation>
<translation id="9153934054460603056">గుర్తింపు మరియు పాస్‌వర్డ్‌ సేవ్ చెయ్యి</translation>
@@ -5385,10 +5400,10 @@
<translation id="9154418932169119429">ఈ చిత్రం ఆఫ్‌లైన్‌లో అందుబాటులో లేదు.</translation>
<translation id="91568222606626347">షార్ట్‌కట్‌ను సృష్టించు...</translation>
<translation id="9157697743260533322">వినియోగదారులందరి కోసం ఆటోమేటిక్ అప్‌డేట్‌లను సెటప్ చేయడం విఫలమైంది (ప్రీఫ్లయిట్ ప్రారంభ ఎర్రర్: <ph name="ERROR_NUMBER" />)</translation>
-<translation id="9158715103698450907">అయ్యో! ప్రామాణీకరణ సమయంలో నెట్‌వర్క్ కమ్యూనికేషన్ సమస్య ఏర్పడింది. దయచేసి మీ నెట్‌వర్క్ కనెక్షన్‌ను తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
+<translation id="9158715103698450907">అయ్యో! ప్రామాణీకరణ సమయంలో నెట్‌వర్క్ కమ్యూనికేషన్ సమస్య సంభవించింది. దయచేసి మీ నెట్‌వర్క్ కనెక్షన్‌ను తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి.</translation>
<translation id="916607977885256133">చిత్రంలో చిత్రం</translation>
<translation id="9168436347345867845">దీనిని తర్వాత చేయి</translation>
-<translation id="9169496697824289689">కీబోర్డ్ సత్వరమార్గాలను వీక్షించండి</translation>
+<translation id="9169496697824289689">కీబోర్డ్ షార్ట్‌క‌ట్‌లను వీక్షించండి</translation>
<translation id="9169931577761441333"><ph name="APP_NAME" />ను హోమ్ స్క్రీన్‌కు జోడించండి</translation>
<translation id="9170848237812810038">&amp;అన్డు</translation>
<translation id="9170884462774788842">మీ కంప్యూటర్‌లోని మరో ప్రోగ్రామ్ జోడించిన థీమ్ కారణంగా Chrome పని చేసే విధానం మారవచ్చు.</translation>
@@ -5399,7 +5414,7 @@
<translation id="9179734824669616955">మీ <ph name="DEVICE_TYPE" />లో Linux (బీటా)ను సెటప్ చేయండి</translation>
<translation id="9180281769944411366">ఈ ప్రాసెస్‌కు కొన్ని నిమిషాలు పట్టవచ్చు. Linux కంటైనర్ ప్రారంభం అవుతోంది.</translation>
<translation id="9180380851667544951">సైట్ మీ స్క్రీన్‌ని షేర్ చేయవచ్చు</translation>
-<translation id="9188441292293901223">ఈ <ph name="DEVICE_TYPE" />ను అన్‌లాక్ చేయడానికి దయచేసి మీ ఫోన్‌ను Android తాజా వెర్షన్‌కు అప్‌డేట్ చేయండి.</translation>
+<translation id="9188441292293901223">దయచేసి ఈ <ph name="DEVICE_TYPE" />ను అన్‌లాక్ చేయడానికి మీ ఫోన్‌ను Android తాజా వెర్షన్‌కు అప్‌డేట్ చేయండి.</translation>
<translation id="9188732951356337132">వినియోగం &amp; విశ్లేషణల డేటాను పంపండి. ఈ పరికరం ప్రస్తుతం సమస్య విశ్లేషణ, అలాగే పరికర, యాప్ వినియోగ డేటాను ఆటోమేటిక్‌గా Googleకి పంపుతుంది. ఇది మీ చిన్నారి గురించి గుర్తించడానికి ఉపయోగించబడదు, ఇది కేవలం సిస్టమ్, యాప్ స్థిరత్వానికి, అలాగే ఇతర మెరుగుదలలకు సహాయపడుతుంది. కొంత సముదాయ డేటా కూడా Google యాప్‌లకు, అలాగే Android డెవలపర్‌ల లాంటి భాగస్వాములకు సహాయపడుతుంది. మీ చిన్నారి కోసం అదనపు వెబ్ &amp; యాప్ కార్యకలాపం సెట్టింగ్‌ను ఆన్ చేసినట్లయితే, ఈ డేటా వారి Google ఖాతాలో సేవ్ చేయబడవచ్చు. <ph name="BEGIN_LINK2" />మరింత తెలుసుకోండి<ph name="END_LINK2" /></translation>
<translation id="9190063653747922532">L2TP/IPsec + ముందుగా భాగస్వామ్యం చేసిన కీ</translation>
<translation id="919031884024748298">ఫోటోలలో కనిపించే వివిధ అంశాలను లేబుల్‌ చేయడానికి ఫోటోలను Google సర్వర్‌లకు పంపుతుంది</translation>
@@ -5407,9 +5422,9 @@
<translation id="9201220332032049474">స్క్రీన్ లాక్ ఎంపికలు</translation>
<translation id="9203398526606335860">&amp;ప్రొఫైలింగ్ అనుమతించబడింది</translation>
<translation id="9203904171912129171">ఒక పరికరాన్ని ఎంచుకోండి</translation>
-<translation id="9203962528777363226">ఈ పరికరం యొక్క నిర్వాహకుడు క్రొత్త వినియోగదారులను జోడించడం నిలిపివేసారు</translation>
+<translation id="9203962528777363226">ఈ పరికరం యొక్క నిర్వాహకుడు కొత్త‌ వినియోగదారులను జోడించడం నిలిపివేశారు</translation>
<translation id="9213073329713032541">ఇన్‌స్టాలేషన్ విజయవంతంగా ప్రారంభించబడింది.</translation>
-<translation id="9214520840402538427">అయ్యో! ఇన్‌స్టాలేషన్-సమయ లక్షణాల ప్రారంభ సమయం ముగిసింది. దయచేసి మీ మద్దతు ప్రతినిధిని సంప్రదించండి.</translation>
+<translation id="9214520840402538427">అయ్యో! ఇన‌స్ట‌లేష‌న్-సమయ లక్షణాల ప్రారంభ సమయం ముగిసింది. దయచేసి మీ మద్దతు ప్రతినిధిని సంప్రదించండి.</translation>
<translation id="9214695392875603905">కప్ కేక్</translation>
<translation id="9215293857209265904">"<ph name="EXTENSION_NAME" />" జోడించబడింది</translation>
<translation id="9218430445555521422">డిఫాల్ట్‌లా సెట్ చేయండి</translation>
@@ -5427,7 +5442,7 @@
<translation id="936801553271523408">సిస్టమ్ విశ్లేషణ డేటా</translation>
<translation id="93766956588638423">పొడిగింపును సరి చేయి</translation>
<translation id="938339467127511841">Linux (బీటా) నిల్వ</translation>
-<translation id="938470336146445890">దయచేసి వినియోగదారు సర్టిఫికెట్‌ను ఇన్‌స్టాల్ చేయండి.</translation>
+<translation id="938470336146445890">దయచేసి వినియోగదారు సర్టిఫికెట్‌ను వ్యవస్థాపించండి.</translation>
<translation id="939252827960237676">స్క్రీన్‌షాట్‌ను సేవ్ చేయడంలో విఫలమైంది</translation>
<translation id="939519157834106403">SSID</translation>
<translation id="939598580284253335">రహస్య పదబంధాన్ని నమోదు చేయండి</translation>
@@ -5463,7 +5478,7 @@
<translation id="988685240266037636">"<ph name="FILE_NAME" />" పేరు గల ఫైల్ ఇప్పటికే వినియోగంలో ఉంది. మీరు దీనిని భర్తీ చేయాలనుకుంటున్నారా?</translation>
<translation id="988978206646512040">రహస్య పదబంధం ఖాళీగా ఉంటే అనుమతించబడదు</translation>
<translation id="992032470292211616">పొడిగింపులు, అనువర్తనాలు మరియు థీమ్‌లు మీ పరికరానికి హాని కలిగించవచ్చు. మీరు ఖచ్చితంగా కొనసాగాలనుకుంటున్నారా?</translation>
-<translation id="992592832486024913">ChromeVox (చదవబడే అభిప్రాయం)ని నిలిపివేయి</translation>
+<translation id="992592832486024913">ChromeVox (చదవబడే అభిప్రాయం)ను నిలిపివేయి</translation>
<translation id="993540765962421562">ఇన్‌స్టాలేషన్ జరుగుతోంది</translation>
<translation id="994289308992179865">&amp;లూప్</translation>
<translation id="995782501881226248">YouTube</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_th.xtb b/chromium/chrome/app/resources/generated_resources_th.xtb
index 435055ae234..8a9a90b0ada 100644
--- a/chromium/chrome/app/resources/generated_resources_th.xtb
+++ b/chromium/chrome/app/resources/generated_resources_th.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">เปิดใช้งานธีม</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">ดูใน Chrome เว็บสโตร์</translation>
-<translation id="1761588866118490543">รูปแบบเสียง</translation>
<translation id="176193854664720708">เซ็นเซอร์ลายนิ้วมืออยู่ในปุ่มเปิด/ปิด โปรดแตะเบาๆ ด้วยนิ้วใดก็ได้</translation>
<translation id="1763046204212875858">สร้างทางลัดไปยังแอปพลิเคชัน</translation>
<translation id="1763108912552529023">สำรวจต่อไป</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">ส่งข้อมูลการใช้งานและการวินิจฉัย ปัจจุบันอุปกรณ์นี้ส่งข้อมูลการวินิจฉัย อุปกรณ์ และการใช้งานแอปไปยัง Google โดยอัตโนมัติ ซึ่งจะช่วยปรับปรุงความเสถียรของแอปและระบบ และอื่นๆ ข้อมูลที่รวบรวมมาบางส่วนจะมีประโยชน์ต่อแอปและพาร์ทเนอร์ของ Google ด้วย เช่น นักพัฒนาซอฟต์แวร์ Android เจ้าของเป็นผู้บังคับใช้การตั้งค่านี้ หากเปิดการตั้งค่ากิจกรรมเพิ่มเติมบนเว็บและแอปไว้ ระบบอาจบันทึกข้อมูลนี้ไว้ในบัญชี Google ของคุณ <ph name="BEGIN_LINK1" />ดูข้อมูลเพิ่มเติม<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">การเก็บถาวรแบบ Zip</translation>
<translation id="220858061631308971">โปรดป้อนรหัส PIN นี้บน "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">นำการแชร์ออก</translation>
+<translation id="2214018885812055163">โฟลเดอร์ที่แชร์</translation>
<translation id="2214884991347062907">รหัสผ่านไม่ถูกต้อง โปรดลองอีกครั้ง</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;ไม่ได้แสดง 1 บรรทัด&gt;}other{&lt;ไม่ได้แสดง <ph name="NUMBER_OF_LINES" /> บรรทัด&gt;}}</translation>
<translation id="2217501013957346740">สร้างชื่อ -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">ใบรับรองถูกระงับไว้</translation>
<translation id="2501797496290880632">พิมพ์แป้นพิมพ์ลัด</translation>
<translation id="2502441965851148920">เปิดใช้การอัปเดตอัตโนมัติอยู่ ผู้ดูแลระบบได้ปิดใช้การอัปเดตด้วยตนเอง</translation>
+<translation id="2505127913256479918">ระบบจะนำบัญชีที่มีการควบคุมดูแลนี้ออกในเร็วๆ นี้</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{หน้าจอ #}other{หน้าจอ #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> จาก <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">บัญชี Google Play Store</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">เครื่องมืออ่านออกเสียง</translation>
<translation id="3053013834507634016">การใช้คีย์ใบรับรอง </translation>
<translation id="3057861065630527966">สำรองรูปภาพและวิดีโอ</translation>
+<translation id="3058498974290601450">คุณเปิดการซิงค์ได้ทุกเมื่อในการตั้งค่า</translation>
<translation id="3060379269883947824">เปิดใช้การเลือกเพื่อให้อ่าน</translation>
<translation id="3061707000357573562">แพตช์บริการ</translation>
<translation id="3065041951436100775">แตะความคิดเห็นที่ปิดไป</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> จะถูกติดตั้ง</translation>
<translation id="3380365263193509176">ข้อผิดพลาดที่ไม่รู้จัก</translation>
<translation id="3382073616108123819">อ๊ะ! ระบบไม่สามารถระบุตัวบ่งชี้อุปกรณ์สำหรับอุปกรณ์นี้</translation>
+<translation id="3382086682569279540">ระบบจะนำบัญชีที่คุณจัดการออกในเร็วๆ นี้</translation>
<translation id="3382200254148930874">กำลังหยุดการควบคุมดูแล...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">ตัวแยก</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">สวัสดี <ph name="USER_GIVEN_NAME" /></translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - ใช้ได้อีก <ph name="TIME" /></translation>
<translation id="3637682276779847508">ระบบจะปิดใช้ซิมการ์ดของคุณโดยถาวรหากคุณไม่สามารถป้อนคีย์ปลดล็อก PIN ที่ถูกต้อง</translation>
-<translation id="363863692969456324">แก้ไขข้อผิดพลาดในการสะกดคำด้วยฟีเจอร์ตรวจตัวสะกดที่ปรับปรุงแล้ว</translation>
<translation id="3640214691812501263">เพิ่ม "<ph name="EXTENSION_NAME" />" สำหรับ <ph name="USER_NAME" /> ไหม</translation>
+<translation id="3640613767643722554">สอนให้ Assistant รู้จักเสียงของคุณ</translation>
<translation id="3644896802912593514">ความกว้าง</translation>
<translation id="3645372836428131288">เลื่อนนิ้วเล็กน้อยเพื่อจับภาพส่วนต่างๆ ของลายนิ้วมือ</translation>
<translation id="3648348069317717750">ตรวจพบ <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">ค้นหาแอปสไตลัสเพิ่มเติม</translation>
<translation id="424546999567421758">พบการใช้ดิสก์สูง</translation>
<translation id="424726838611654458">เปิดใน Adobe Reader ทุกครั้ง</translation>
-<translation id="4247330672018280062">ข้อความที่คุณพิมพ์ในช่องข้อความจะส่งไปยัง Google</translation>
<translation id="4247901771970415646">ซิงค์กับ <ph name="USERNAME" /> ไม่ได้</translation>
<translation id="4249248555939881673">กำลังรอการเชื่อมต่อเครือข่าย...</translation>
<translation id="4249373718504745892">หน้าเว็บนี้ถูกบล็อกไม่ให้เข้าถึงกล้องถ่ายรูปและไมโครโฟนของคุณ</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;เปิดใช้งานการทำแฟ้มประวัติ</translation>
<translation id="4823484602432206655">อ่านและเปลี่ยนการตั้งค่าผู้ใช้และอุปกรณ์</translation>
<translation id="4823651846660089135">อุปกรณ์เป็นแบบอ่านอย่างเดียว</translation>
+<translation id="4824958205181053313">ยกเลิกการซิงค์ใช่ไหม</translation>
<translation id="4827675678516992122">เชื่อมต่อไม่ได้</translation>
<translation id="4828937774870308359">ออสเตรเลีย</translation>
<translation id="4829768588131278040">ตั้งค่า PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">เปลี่ยนรูปภาพ</translation>
<translation id="5376169624176189338">คลิกเพื่อย้อนกลับ กดค้างเพื่อดูประวัติการเข้าชม</translation>
<translation id="5376931455988532197">ไฟล์ใหญ่เกินไป</translation>
+<translation id="5377594097385838788">ไม่ระบุตัวตน</translation>
<translation id="537813040452600081">หน้าที่คุณดูในหน้าต่างนี้จะไม่ปรากฏในประวัติเบราว์เซอร์และจะไม่ทิ้งร่องรอยอื่นๆ เช่น คุกกี้ ไว้ในคอมพิวเตอร์หลังจากที่คุณออกจากระบบ ไฟล์ที่คุณดาวน์โหลดและบุ๊กมาร์กที่คุณสร้างจะหายไป</translation>
<translation id="5379140238605961210">บล็อกการเข้าถึงไมโครโฟนต่อไป</translation>
<translation id="5379268888377976432">เลิกทำการนำออก</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">อ่านไอคอนของเว็บไซต์ที่คุณเข้าชม</translation>
<translation id="5417312524372586921">ธีมของเบราว์เซอร์</translation>
<translation id="5419294236999569767">เวลาระบบ</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">กำหนดความคมชัดของข้อความและรูปภาพ</translation>
<translation id="5422221874247253874">จุดเข้าใช้งาน</translation>
<translation id="5422781158178868512">ขออภัย ระบบไม่รู้จักอุปกรณ์จัดเก็บข้อมูลภายนอกของคุณ</translation>
@@ -2904,7 +2910,7 @@
<translation id="5427459444770871191">หมุน&amp;ตามเข็มนาฬิกา</translation>
<translation id="542872847390508405">คุณกำลังเรียกดูในฐานะผู้เยี่ยมชม</translation>
<translation id="5428850089342283580"><ph name="ACCNAME_APP" /> (มีการอัปเดต)</translation>
-<translation id="5430931332414098647">การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือแบบด่วน</translation>
+<translation id="5430931332414098647">การเชื่อมต่อ Wi-Fi ฮอตสปอตจากมือถือโดยอัตโนมัติ</translation>
<translation id="5431318178759467895">สี</translation>
<translation id="5431825016875453137">OpenVPN/L2TP</translation>
<translation id="5432996274932278848">ค้นอุปกรณ์ แอป และเว็บ ใช้แป้นลูกศรเพื่อเลื่อนดูแอป</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 การเข้ารหัส RSA</translation>
<translation id="5436492226391861498">กำลังรอช่องทางการเชื่อมต่อพร็อกซี...</translation>
<translation id="5436510242972373446">ค้นหา <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">โปรดบันทึกไฟล์และสร้างบัญชีใหม่ตอนนี้เลย</translation>
<translation id="5438224778284622050">คุณต้องการลบไฟล์ออฟไลน์ใช่ไหม</translation>
<translation id="544083962418256601">สร้างทางลัด...</translation>
<translation id="5442228125690314719">เกิดข้อผิดพลาดขณะสร้างดิสก์อิมเมจ โปรดลองอีกครั้ง</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">อีกทั้งยังควบคุมหน้าที่จะแสดงเมื่อคุณคลิกปุ่ม "หน้าแรก" หรือทำการค้นหาจากแถบอเนกประสงค์</translation>
<translation id="5971037678316050792">ควบคุมสถานะและการจับคู่อะแดปเตอร์บลูทูธ</translation>
<translation id="5972017421290582825">จัดการการตั้งค่า MIDI...</translation>
+<translation id="597235323114979258">ดูปลายทางเพิ่มเติม</translation>
+<translation id="5972666587303800813">บริการที่ไม่มีการดำเนินการ</translation>
<translation id="5972708806901999743">ย้ายไปด้านบน</translation>
<translation id="5972826969634861500">เริ่มต้นใช้งาน <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">เปอร์เซ็นต์การชาร์จแบตเตอรี่</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">แชร์</translation>
<translation id="6528513914570774834">อนุญาตให้ผู้ใช้อุปกรณ์นี้คนอื่นๆ ใช้เครือข่ายนี้ได้</translation>
<translation id="652948702951888897">ประวัติการเข้าชมใน Chrome</translation>
+<translation id="6530186581263215931">ผู้ดูแลระบบกำหนดให้ใช้การตั้งค่าเหล่านี้</translation>
<translation id="653019979737152879">กำลังซิงค์ <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">เก็บไฟล์อันตรายไว้</translation>
<translation id="6532101170117367231">บันทึกไปยัง Google ไดรฟ์</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">อ่านและเปลี่ยนแปลงประวัติการเข้าชม</translation>
<translation id="7019805045859631636">เร็ว</translation>
<translation id="7022562585984256452">ตั้งค่าหน้าแรกของคุณแล้ว</translation>
-<translation id="702384510542929236">ส่งข้อมูลบางอย่างของระบบและเนื้อหาของหน้าเว็บให้กับ Google โดยไม่ระบุตัวตนของคุณ</translation>
<translation id="7025190659207909717">การจัดการบริการดาต้าบนมือถือ</translation>
<translation id="7027125358315426638">ชื่อฐานข้อมูล:</translation>
<translation id="7029809446516969842">รหัสผ่าน</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">เปิดแอปวอลล์เปเปอร์</translation>
<translation id="7290242001003353852">บริการลงชื่อเข้าใช้ที่โฮสต์โดย <ph name="SAML_DOMAIN" /> กำลังเข้าถึงกล้องถ่ายรูปของคุณ</translation>
<translation id="7290594223351252791">ยืนยันการลงทะเบียน</translation>
+<translation id="7292696521213967957">ข้อมูลสำหรับการแก้ไขข้อบกพร่องของ Assistant</translation>
<translation id="7295662345261934369">แชร์กับคนอื่นๆ</translation>
<translation id="729583233778673644">อนุญาตการเข้ารหัส AES และ RC4 การใช้ตัวเลือกนี้เป็นการเพิ่มความเสี่ยงเนื่องจากการเข้ารหัส RC4 นั้นไม่ปลอดภัย</translation>
<translation id="7296774163727375165">ข้อกำหนดของ <ph name="DOMAIN" /></translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">เปิดตำแหน่ง...</translation>
<translation id="7461924472993315131">ตรึง</translation>
<translation id="7463006580194749499">เพิ่มบุคคล</translation>
-<translation id="7464902436585505072">รูปแบบเสียง "Ok Google"</translation>
<translation id="7465778193084373987">URL การเพิกถอนใบรับรองของ Netscape</translation>
<translation id="7469894403370665791">เชื่อมต่อกับเครือข่ายนี้อัตโนมัติ</translation>
<translation id="747114903913869239">ข้อผิดพลาด: ไม่สามารถถอดรหัสส่วนขยาย</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424">ระบบจะนำ <ph name="LINUX_APP_NAME" /> และข้อมูลที่เชื่อมโยงกับแอปนี้ออกจากอุปกรณ์เครื่องนี้</translation>
<translation id="7497215489070763236">ใบรับรอง CA ของเซิร์ฟเวอร์</translation>
<translation id="7497981768003291373">คุณไม่มีบันทึกข้อความ WebRTC ที่จับภาพเมื่อเร็วๆ นี้</translation>
+<translation id="7502199377020483660">หากต้องการใช้บัตรเหล่านี้ในอุปกรณ์ทุกเครื่อง ให้บันทึกบัตรไว้ในบัญชี Google</translation>
<translation id="7502658306369382406">ที่อยู่ IPv6</translation>
<translation id="7503191893372251637">ประเภทใบรับรองของ Netscape </translation>
<translation id="7503821294401948377">ไม่สามารถโหลดไอคอน "<ph name="ICON" />" เพื่อให้เกิดการทำงานของเบราว์เซอร์</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">เครื่องรับ: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">อุปกรณ์บลูทูธที่ไม่สนับสนุน: "<ph name="DEVICE_NAME" />"</translation>
<translation id="7665369617277396874">เพิ่มบัญชี</translation>
+<translation id="7667248760110172428">พื้นที่เก็บข้อมูลภายนอก</translation>
<translation id="7671130400130574146">ใช้แถบชื่อและเส้นขอบของระบบ</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> ใน <ph name="PAGE_TITLE" /></translation>
<translation id="7676867886086876795">ส่งเสียงของคุณไปยัง Google เพื่อให้พิมพ์ตามคำบอกในช่องข้อความต่างๆ</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">วิธีการชำระเงินที่บันทึกไว้จะปรากฏที่นี่</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> กำลังแชร์หน้าจอและเสียงของคุณ</translation>
<translation id="7931318309563332511">ไม่รู้จัก</translation>
+<translation id="7932969338829957666">โฟลเดอร์ที่แชร์ใน Linux จะอยู่ที่ <ph name="BASE_DIR" /></translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{เลิกซ่อนเว็บไซต์}other{เลิกซ่อนเว็บไซต์}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> ต้องการเปิดเนื้อหาที่มีการคุ้มครอง Google จะตรวจสอบข้อมูลประจำตัวของอุปกรณ์</translation>
<translation id="793531125873261495">เกิดข้อผิดพลาดขณะดาวน์โหลดเครื่องเสมือน โปรดลองอีกครั้ง</translation>
@@ -4672,6 +4684,7 @@
<translation id="8049705080247101012">Google ได้ตั้งค่าสถานะ "<ph name="EXTENSION_NAME" />" ว่าเป็นอันตราย และป้องกันไม่ให้มีการติดตั้งแล้ว</translation>
<translation id="8049913480579063185">ชื่อส่วนขยาย</translation>
<translation id="8050038245906040378">การรับรองรหัสเชิงพาณิชย์ของ Microsoft</translation>
+<translation id="8052887694493382350">ไฟล์นี้ออกแบบมาสำหรับพีซีที่ใช้ซอฟต์แวร์ Windows จึงเข้ากันไม่ได้กับอุปกรณ์ของคุณซึ่งใช้ Chrome OS <ph name="BEGIN_LINK_HELP" />ดูข้อมูลเพิ่มเติม<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">ไฟล์ PKCS #12</translation>
<translation id="8053390638574070785">โหลดหน้านี้ใหม่</translation>
<translation id="8054517699425078995">ไฟล์ประเภทนี้อาจเป็นอันตรายต่ออุปกรณ์ของคุณ คุณยังต้องการเก็บไฟล์ <ph name="FILE_NAME" /> ไว้ไหม</translation>
@@ -4915,6 +4928,7 @@
<translation id="8438566539970814960">ปรับปรุงการค้นหาและการท่องเว็บให้ดียิ่งขึ้น</translation>
<translation id="8439506636278576865">เสนอที่จะแปลหน้าต่างๆ ที่เป็นภาษานี้</translation>
<translation id="8440630305826533614">แอป Linux</translation>
+<translation id="8443338615972234259">โปรดสร้างบัญชีใหม่ให้ผู้ใช้ภายใต้การควบคุมดูแลตอนนี้เลย</translation>
<translation id="8446884382197647889">ดูข้อมูลเพิ่มเติม</translation>
<translation id="8447409163267621480">รวมปุ่ม Ctrl หรือ Alt</translation>
<translation id="8448729345478502352">ทำให้รายการในหน้าจอมีขนาดเล็กลงหรือใหญ่ขึ้น</translation>
@@ -4939,6 +4953,7 @@
<translation id="8468750959626135884">ปลดล็อก <ph name="DEVICE_TYPE" /> ด้วยโทรศัพท์ Android ของคุณ</translation>
<translation id="8470028084415844044">เปิดการซิงค์เพื่อรับรหัสผ่านทั้งหมดในอุปกรณ์ทุกเครื่องของคุณ</translation>
<translation id="8470513973197838199">รหัสผ่านที่บันทึกไว้สำหรับ <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">หากต้องการใช้บัตรนี้ในอุปกรณ์ทุกเครื่อง ให้บันทึกบัตรไว้ในบัญชี Google</translation>
<translation id="8472623782143987204">การสนับสนุนฮาร์ดแวร์</translation>
<translation id="8473863474539038330">ที่อยู่และอื่นๆ</translation>
<translation id="8475313423285172237">โปรแกรมอื่นในคอมพิวเตอร์ของคุณเพิ่มส่วนขยายที่อาจเปลี่ยนวิธีการทำงานของ Chrome</translation>
@@ -5014,7 +5029,6 @@
<translation id="8598453409908276158">บล็อกปลั๊กอินที่ไม่ได้อยู่ในแซนด์บ็อกซ์</translation>
<translation id="8601206103050338563">การตรวจสอบสิทธิ์ไคลเอ็นต์ TLS WWW </translation>
<translation id="8602851771975208551">โปรแกรมอื่นในคอมพิวเตอร์ของคุณเพิ่มแอปพลิเคชันที่อาจเปลี่ยนวิธีการทำงานของ Chrome</translation>
-<translation id="8604763363205185560">ช่วยปรับปรุง Chrome และความปลอดภัยของ Chrome</translation>
<translation id="8605428685123651449">หน่วยความจำ SQLite</translation>
<translation id="8606726445206553943">ใช้อุปกรณ์ MIDI ของคุณ</translation>
<translation id="8609465669617005112">เลื่อนขึ้น</translation>
@@ -5190,6 +5204,7 @@
<translation id="8846141544112579928">กำลังค้นหาแป้นพิมพ์...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">เมื่อเชื่อมต่ออุปกรณ์ คุณยอมรับว่า Chromebook ทำสิ่งต่อไปนี้ได้</translation>
+<translation id="8850251000316748990">ดูเพิ่มเติม...</translation>
<translation id="8859057652521303089">เลือกภาษาที่ต้องการ:</translation>
<translation id="8859174528519900719">เฟรมย่อย: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">สเปรดชีต Excel</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_tr.xtb b/chromium/chrome/app/resources/generated_resources_tr.xtb
index 9a9af64cc48..8a2682f3e1f 100644
--- a/chromium/chrome/app/resources/generated_resources_tr.xtb
+++ b/chromium/chrome/app/resources/generated_resources_tr.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Temayı etkinleştir</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Chrome Web Mağazası'nda göster</translation>
-<translation id="1761588866118490543">Ses modeli</translation>
<translation id="176193854664720708">Parmak izi sensörü güç düğmesidir. Tek parmağınızla bu düğmeye hafifçe dokunun.</translation>
<translation id="1763046204212875858">Uygulama kısayolları oluşturun</translation>
<translation id="1763108912552529023">Keşfetmeye devam et</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Kullanım ve teşhis verilerini gönder. Bu cihaz şu anda teşhis, cihaz ve uygulama kullanımı verilerini otomatik olarak Google'a gönderiyor. Bu veriler, sistem ve uygulama kararlılığı ile diğer özellikleri iyileştirmeye yardımcı olur. Bazı birleştirilmiş veriler, Google uygulamalarına ve iş ortaklarına da (ör. Android geliştiricileri) yardımcı olur. Bu ayar, cihazın sahibi tarafından zorunlu kılınmıştır. Ek Web ve Uygulama Etkinliği açıksa bu veriler Google Hesabınıza kaydedilebilir. <ph name="BEGIN_LINK1" />Daha Fazla Bilgi<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip arşivi</translation>
<translation id="220858061631308971">Lütfen "<ph name="DEVICE_NAME" />" cihazında bu PIN kodunu girin:</translation>
+<translation id="2213140827792212876">Paylaşımı kaldır</translation>
+<translation id="2214018885812055163">Paylaşılan klasörler</translation>
<translation id="2214884991347062907">Yanlış şifre, tekrar deneyin</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 satır gösterilmiyor&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> satır gösterilmiyor&gt;}}</translation>
<translation id="2217501013957346740">Bir ad oluşturun -</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Sertifika Beklemede</translation>
<translation id="2501797496290880632">Bir kısayol yazın</translation>
<translation id="2502441965851148920">Otomatik güncellemeler etkin. Manuel güncellemeler yöneticiniz tarafından devre dışı bırakıldı.</translation>
+<translation id="2505127913256479918">Gözetim altındaki bu hesap yakında kaldırılacak</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{#. Ekran}other{#. Ekran}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> / <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play Store Hesabı</translation>
@@ -1375,6 +1377,7 @@ Sunucunun mesajı: <ph name="SERVER_MSG" /></translation>
<translation id="304747341537320566">Konuşma Motorları</translation>
<translation id="3053013834507634016">Sertifika Anahtarı Kullanımı</translation>
<translation id="3057861065630527966">Fotoğraflarınızı ve videolarınızı yedekleyin</translation>
+<translation id="3058498974290601450">Senkronizasyonu istediğiniz zaman ayarlardan açabilirsiniz</translation>
<translation id="3060379269883947824">Seç ve Dinle'yi etkinleştir</translation>
<translation id="3061707000357573562">Yama Hizmeti</translation>
<translation id="3065041951436100775">Sekme sonlandırıldı geri bildirimi.</translation>
@@ -1566,6 +1569,7 @@ Sunucunun mesajı: <ph name="SERVER_MSG" /></translation>
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> yüklenecek.</translation>
<translation id="3380365263193509176">Bilinmeyen hata</translation>
<translation id="3382073616108123819">Hata! Sistem, bu cihaz için cihaz tanıtıcılarını belirleyemedi.</translation>
+<translation id="3382086682569279540">Yönettiğiniz hesap yakında kaldırılacak</translation>
<translation id="3382200254148930874">Gözetim durduruluyor...</translation>
<translation id="3385092118218578224">%<ph name="DISPLAY_ZOOM" /></translation>
<translation id="338583716107319301">Ayırıcı</translation>
@@ -1746,8 +1750,8 @@ Sunucunun mesajı: <ph name="SERVER_MSG" /></translation>
<translation id="3636096452488277381">Merhaba <ph name="USER_GIVEN_NAME" />.</translation>
<translation id="3636766455281737684">%<ph name="PERCENTAGE" /> - <ph name="TIME" /> kaldı</translation>
<translation id="3637682276779847508">Doğru PIN Kilit Açma Anahtarını giremezseniz SIM kartınız kalıcı olarak devre dışı bırakılacaktır.</translation>
-<translation id="363863692969456324">Yazım hatalarını geliştirilmiş yazım denetimiyle düzeltin</translation>
<translation id="3640214691812501263"><ph name="USER_NAME" /> için "<ph name="EXTENSION_NAME" />" uzantısı eklensin mi?</translation>
+<translation id="3640613767643722554">Asistanınıza sesinizi tanımayı öğretin</translation>
<translation id="3644896802912593514">Genişlik</translation>
<translation id="3645372836428131288">Parmak izinizin farklı bir kısmının yakalanması için parmağınızı çok az hareket ettirin.</translation>
<translation id="3648348069317717750"><ph name="USB_DEVICE_NAME" /> algılandı</translation>
@@ -2147,7 +2151,6 @@ Sunucunun mesajı: <ph name="SERVER_MSG" /></translation>
<translation id="4244238649050961491">Daha fazla ekran kalemi uygulaması bul</translation>
<translation id="424546999567421758">Fazla disk kullanımı tespit edildi</translation>
<translation id="424726838611654458">Her zaman Adobe Reader programında aç</translation>
-<translation id="4247330672018280062">Metin alanlarına yazdığınız metinler Google'a gönderilir</translation>
<translation id="4247901771970415646"><ph name="USERNAME" /> ile senkronize edilemiyor</translation>
<translation id="4249248555939881673">Ağ bağlantısı bekleniyor...</translation>
<translation id="4249373718504745892">Bu sayfanın kamera ve mikrofonunuza erişimi engellenmiştir.</translation>
@@ -2489,6 +2492,7 @@ Sunucunun mesajı: <ph name="SERVER_MSG" /></translation>
<translation id="4821935166599369261">&amp;Profil Oluşturma Etkin</translation>
<translation id="4823484602432206655">Kullanıcı ve cihaz ayarlarını okuma ve değiştirme</translation>
<translation id="4823651846660089135">Cihaz salt okunur</translation>
+<translation id="4824958205181053313">Senkronizasyon iptal edilsin mi?</translation>
<translation id="4827675678516992122">Bağlanılamadı</translation>
<translation id="4828937774870308359">Avustralya</translation>
<translation id="4829768588131278040">PIN ayarla</translation>
@@ -2871,6 +2875,7 @@ Sunucunun mesajı: <ph name="SERVER_MSG" /></translation>
<translation id="5374359983950678924">Resmi değiştir</translation>
<translation id="5376169624176189338">Geri dönmek için tıkla, geçmişi görmek için tıklayıp tut</translation>
<translation id="5376931455988532197">Dosya çok büyük</translation>
+<translation id="5377594097385838788">Gizli</translation>
<translation id="537813040452600081">Bu pencerede görüntülediğiniz sayfalar tarayıcı geçmişinde görünmez ve oturumu kapatmanızdan sonra bilgisayarda çerezler gibi başka izler bırakmaz. İndirdiğiniz dosyalar ve oluşturduğunuz yer işaretleri saklanmaz.</translation>
<translation id="5379140238605961210">Mikrofon erişimini engellemeye devam et</translation>
<translation id="5379268888377976432">Silme işlemini geri al</translation>
@@ -2892,6 +2897,7 @@ Sunucunun mesajı: <ph name="SERVER_MSG" /></translation>
<translation id="5414566801737831689">Ziyaret ettiğiniz web sitelerinin simgelerini okuma</translation>
<translation id="5417312524372586921">Tarayıcı temaları</translation>
<translation id="5419294236999569767">Sistem saati</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Metin ve resimlerin keskinliğini belirler</translation>
<translation id="5422221874247253874">Erişim Noktası</translation>
<translation id="5422781158178868512">Maalesef, harici depolama cihazınız tanınamadı.</translation>
@@ -2912,6 +2918,7 @@ Sunucunun mesajı: <ph name="SERVER_MSG" /></translation>
<translation id="5434065355175441495">PKCS #1 RSA Şifrelemesi</translation>
<translation id="5436492226391861498">Proxy tüneli bekleniyor...</translation>
<translation id="5436510242972373446">Ara <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Lütfen şimdi dosyalarınızı kaydedin ve yeni bir hesap oluşturun.</translation>
<translation id="5438224778284622050">Çevrimdışı dosyalar silinsin mi?</translation>
<translation id="544083962418256601">Kısayol oluştur...</translation>
<translation id="5442228125690314719">Disk görüntüsü oluşturulurken hata oluştu. Lütfen tekrar deneyin.</translation>
@@ -3286,6 +3293,8 @@ Hassas bilgileri vermediğinizden emin olun.</translation>
<translation id="5965661248935608907">Ayrıca Ana Sayfa düğmesini tıkladığınızda veya Çok Amaçlı Adres Çubuğu'ndan arama yaptığınızda gösterilecek sayfayı da denetler.</translation>
<translation id="5971037678316050792">Bluetooth adaptörü durumunu ve eşlemeyi kontrol etme</translation>
<translation id="5972017421290582825">MIDI ayarlarını yönet...</translation>
+<translation id="597235323114979258">Diğer hedefleri göster</translation>
+<translation id="5972666587303800813">İşlemsiz Hizmet</translation>
<translation id="5972708806901999743">Yukarı taşı</translation>
<translation id="5972826969634861500"><ph name="PRODUCT_NAME" /> uygulamasını başlat</translation>
<translation id="5975792506968920132">Pil Şarjı Yüzdesi</translation>
@@ -3656,6 +3665,7 @@ Hassas bilgileri vermediğinizden emin olun.</translation>
<translation id="6527303717912515753">Paylaş</translation>
<translation id="6528513914570774834">Bu cihazın diğer kullanıcılarının bu ağı kullanmalarına izin verin</translation>
<translation id="652948702951888897">Chrome geçmişi</translation>
+<translation id="6530186581263215931">Bu ayarlar yöneticiniz tarafınızdan uygulanıyor</translation>
<translation id="653019979737152879"><ph name="FILE_NAME" /> senkronize ediliyor...</translation>
<translation id="6531282281159901044">Tehlikeli dosyayı tut</translation>
<translation id="6532101170117367231">Google Drive'a Kaydet</translation>
@@ -3974,7 +3984,6 @@ Hassas bilgileri vermediğinizden emin olun.</translation>
<translation id="7018275672629230621">Göz atma geçmişinizi okuma ve değiştirme</translation>
<translation id="7019805045859631636">Hızlı</translation>
<translation id="7022562585984256452">Ana sayfanız ayarlandı.</translation>
-<translation id="702384510542929236">Bazı sistem bilgilerini ve sayfa içeriğini Google'a anonim olarak gönderir</translation>
<translation id="7025190659207909717">Mobil veri hizmeti yönetimi</translation>
<translation id="7027125358315426638">Veritabanı adı:</translation>
<translation id="7029809446516969842">Şifreler</translation>
@@ -4154,6 +4163,7 @@ Hassas bilgileri vermediğinizden emin olun.</translation>
<translation id="7289225569524511578">Duvar kağıdı uygulamasını aç</translation>
<translation id="7290242001003353852"><ph name="SAML_DOMAIN" /> tarafından barındırılan bu oturum açma hizmeti kameranıza erişiyor.</translation>
<translation id="7290594223351252791">Kaydı onaylayın</translation>
+<translation id="7292696521213967957">Asistan hatalarını ayıklama bilgileri</translation>
<translation id="7295662345261934369">Başkalarıyla paylaş</translation>
<translation id="729583233778673644">AES ve RC4 şifrelemesine izin ver. RC4 şifreleri güvenli olmadığından bu seçeneğin kullanılması, riskinizi artırır.</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> Şartları</translation>
@@ -4254,7 +4264,6 @@ Hassas bilgileri vermediğinizden emin olun.</translation>
<translation id="7456847797759667638">Konumu Aç...</translation>
<translation id="7461924472993315131">Sabitle</translation>
<translation id="7463006580194749499">Kişi ekle</translation>
-<translation id="7464902436585505072">"OK Google" ses modeli</translation>
<translation id="7465778193084373987">Netscape Sertifika İptali URL'si</translation>
<translation id="7469894403370665791">Bu ağa otomatik olarak bağlan</translation>
<translation id="747114903913869239">Hata: Uzantının kodu çözülemiyor</translation>
@@ -4282,6 +4291,7 @@ Hassas bilgileri vermediğinizden emin olun.</translation>
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> ve onunla ilişkili veriler bu cihazdan kaldırılacak.</translation>
<translation id="7497215489070763236">Sunucu CA sertifikası</translation>
<translation id="7497981768003291373">Yakın zamanda yakalanmış herhangi bir WebRTC metin günlüğünüz yok.</translation>
+<translation id="7502199377020483660">Bu kartları tüm cihazlarınızda kullanabilmek için Google Hesabınıza kaydedin</translation>
<translation id="7502658306369382406">IPv6 adresi</translation>
<translation id="7503191893372251637">Netscape Sertifika Türü</translation>
<translation id="7503821294401948377">Tarayıcı işlemine ilişkin '<ph name="ICON" />' simgesi yüklenemedi.</translation>
@@ -4379,6 +4389,7 @@ Hassas bilgileri vermediğinizden emin olun.</translation>
<translation id="7663719505383602579">Alıcı: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Desteklenmeyen Bluetooth cihazı: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Hesap ekle</translation>
+<translation id="7667248760110172428">Harici depolama</translation>
<translation id="7671130400130574146">Sistemin başlık çubuğunu ve kenarlıklarını kullan</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, <ph name="PAGE_TITLE" /> sayfasında.</translation>
<translation id="7676867886086876795">Dikte özelliğiyle metin alanına herhangi bir şey yazabilmek için sesinizi Google'a gönderin.</translation>
@@ -4581,6 +4592,7 @@ Hassas bilgileri vermediğinizden emin olun.</translation>
<translation id="7930294771522048157">Kaydedilen ödeme yöntemleri burada görünecek</translation>
<translation id="79312157130859720"><ph name="APP_NAME" />, ekranınızı ve sesinizi paylaşıyor.</translation>
<translation id="7931318309563332511">Bilinmiyor</translation>
+<translation id="7932969338829957666">Paylaşılan klasörleri Linux'ta <ph name="BASE_DIR" /> adresinde bulabilirsiniz.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Sitenin Sesini Aç}other{Sitelerin Sesini Aç}}</translation>
<translation id="7934414805353235750"><ph name="URL" />, korumalı içeriği oynatmak istiyor. Cihazınızın kimliği Google tarafından doğrulanacak.</translation>
<translation id="793531125873261495">Sanal makine indirilirken hata oluştu. Lütfen tekrar deneyin.</translation>
@@ -4672,6 +4684,7 @@ Anahtar dosyanızı güvenli bir yerde saklayın. Uzantınızın yeni sürümler
<translation id="8049705080247101012">Google <ph name="EXTENSION_NAME" /> uzantısını kötü amaçlı olarak işaretledi ve yükleme işlemi engellendi</translation>
<translation id="8049913480579063185">Uzantı Adı</translation>
<translation id="8050038245906040378">Microsoft Ticari Kod İmzalama</translation>
+<translation id="8052887694493382350">Bu dosya Windows yazılımı kullanan PC'ler için tasarlanmıştır. Chrome OS çalıştıran cihazınızla uyumlu değildir. <ph name="BEGIN_LINK_HELP" />Daha Fazla Bilgi<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 Dosyaları</translation>
<translation id="8053390638574070785">Bu Sayfayı Tekrar Yükle</translation>
<translation id="8054517699425078995">Bu türden dosyalar cihazınıza zarar verebilir. Yine de <ph name="FILE_NAME" /> adlı dosyayı saklamak istiyor musunuz?</translation>
@@ -4915,6 +4928,7 @@ Anahtar dosyanızı güvenli bir yerde saklayın. Uzantınızın yeni sürümler
<translation id="8438566539970814960">Aramaları ve göz atmayı daha iyi yap</translation>
<translation id="8439506636278576865">Bu dildeki sayfaları çevirmeyi öner</translation>
<translation id="8440630305826533614">Linux uygulamaları</translation>
+<translation id="8443338615972234259">Lütfen denetlenen kullanıcınız için şimdi yeni bir hesap oluşturun.</translation>
<translation id="8446884382197647889">Daha Fazla Bilgi Edinin</translation>
<translation id="8447409163267621480">Ctrl veya Alt tuşunu ekleyin</translation>
<translation id="8448729345478502352">Ekranınızdaki öğeleri küçültün veya büyütün</translation>
@@ -4939,6 +4953,7 @@ Anahtar dosyanızı güvenli bir yerde saklayın. Uzantınızın yeni sürümler
<translation id="8468750959626135884"><ph name="DEVICE_TYPE" /> cihazınızın kilidini Android telefonunuzla açın.</translation>
<translation id="8470028084415844044">Tüm şifrelerinize tüm cihazlarınızda ulaşmak için senkronizasyonu açın.</translation>
<translation id="8470513973197838199"><ph name="ORIGIN" /> için kaydedilmiş şifreler</translation>
+<translation id="8471635086304129332">Bu kartı tüm cihazlarınızda kullanabilmek için Google Hesabınıza kaydedin</translation>
<translation id="8472623782143987204">donanım esaslı</translation>
<translation id="8473863474539038330">Adresler ve daha fazlası</translation>
<translation id="8475313423285172237">Bilgisayarınızdaki başka bir program, Chrome'un çalışma şeklini değiştirebilecek bir uzantı ekledi.</translation>
@@ -5014,7 +5029,6 @@ Anahtar dosyanızı güvenli bir yerde saklayın. Uzantınızın yeni sürümler
<translation id="8598453409908276158">Korumalı alan içinde olmayan eklenti engellendi</translation>
<translation id="8601206103050338563">TLS WWW İstemci Kimlik Doğrulaması</translation>
<translation id="8602851771975208551">Bilgisayarınızdaki başka bir program, Chrome'un çalışma şeklini değiştirebilecek bir uygulama ekledi.</translation>
-<translation id="8604763363205185560">Chrome'u ve güvenlik özelliklerini iyileştirmeye yardımcı olun</translation>
<translation id="8605428685123651449">SQLite Belleği</translation>
<translation id="8606726445206553943">MIDI cihazlarınızı kullanma</translation>
<translation id="8609465669617005112">Yukarı taşı</translation>
@@ -5190,6 +5204,7 @@ Anahtar dosyanızı güvenli bir yerde saklayın. Uzantınızın yeni sürümler
<translation id="8846141544112579928">Klavye aranıyor...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Cihazlarınızı bağladığınızda, Chromebook'unuzun şu işlemleri yapabileceğini kabul etmiş olursunuz:</translation>
+<translation id="8850251000316748990">Daha fazla göster...</translation>
<translation id="8859057652521303089">Dilinizi seçin:</translation>
<translation id="8859174528519900719">Alt çerçeve: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel e-tablosu</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_uk.xtb b/chromium/chrome/app/resources/generated_resources_uk.xtb
index d9f57fc52ed..f90acc59ad8 100644
--- a/chromium/chrome/app/resources/generated_resources_uk.xtb
+++ b/chromium/chrome/app/resources/generated_resources_uk.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Увімкнути тему</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Переглянути у Веб-магазині Chrome</translation>
-<translation id="1761588866118490543">Зразок голосу</translation>
<translation id="176193854664720708">Сканер відбитків пальців знаходиться на кнопці живлення. Легко торкніться його будь-яким пальцем.</translation>
<translation id="1763046204212875858">Створити ярлики програми</translation>
<translation id="1763108912552529023">Продовжити</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Надсилати дані про використання й діагностику. Цей пристрій наразі автоматично надсилає в Google дані про діагностику та використання пристрою і додатків. Ця інформація допоможе покращити стабільність системи, додатків тощо. Деякі зведені дані також корисні для додатків і партнерів Google, як-от розробників Android. Це налаштування застосовує власник. Якщо ввімкнено додаткову Історію додатків і веб-пошуку, ці дані зберігаються в обліковому записі Google. <ph name="BEGIN_LINK1" />Докладніше<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Архів Zip</translation>
<translation id="220858061631308971">Введіть цей PIN-код на пристрої "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Скасувати доступ</translation>
+<translation id="2214018885812055163">Спільні папки</translation>
<translation id="2214884991347062907">Неправильний пароль, повторіть спробу</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;Не показано 1 рядок&gt;}one{&lt;Не показано <ph name="NUMBER_OF_LINES" /> рядок&gt;}few{&lt;Не показано <ph name="NUMBER_OF_LINES" /> рядки&gt;}many{&lt;Не показано <ph name="NUMBER_OF_LINES" /> рядків&gt;}other{&lt;Не показано <ph name="NUMBER_OF_LINES" /> рядка&gt;}}</translation>
<translation id="2217501013957346740">Створіть ім’я –</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Сертифікат відтерміновано</translation>
<translation id="2501797496290880632">Введіть комбінацію</translation>
<translation id="2502441965851148920">Автоматичні оновлення ввімкнено. Адміністратор заборонив оновлювати вручну.</translation>
+<translation id="2505127913256479918">Цей контрольований обліковий запис незабаром буде видалено</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Екран #}one{Екран #}few{Екран #}many{Екран #}other{Екран #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> із <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Обліковий запис Google Play</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Системи синтезу мовлення</translation>
<translation id="3053013834507634016">Використання ключа сертифіката</translation>
<translation id="3057861065630527966">Створити резервні копії фотографій і відео</translation>
+<translation id="3058498974290601450">Ви можете будь-коли ввімкнути синхронізацію в налаштуваннях</translation>
<translation id="3060379269883947824">Увімкнути службу Читання з екрана</translation>
<translation id="3061707000357573562">Служба виправлень</translation>
<translation id="3065041951436100775">Відповідь "Вкладка закрилась".</translation>
@@ -1510,7 +1513,7 @@
<translation id="3294437725009624529">Гість</translation>
<translation id="329703603001918157">Неможливо змінити ярлик</translation>
<translation id="3297951628821704004">Видалити обліковий запис із цього пристрою</translation>
-<translation id="329838636886466101">Відновити</translation>
+<translation id="329838636886466101">Полагодити</translation>
<translation id="3298789223962368867">Введено недійсну URL-адресу.</translation>
<translation id="32991397311664836">Пристрої:</translation>
<translation id="33022249435934718">Обробка GDI</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> буде встановлено.</translation>
<translation id="3380365263193509176">Невідома помилка</translation>
<translation id="3382073616108123819">На жаль, системі не вдалося визначити ідентифікатори цього пристрою.</translation>
+<translation id="3382086682569279540">Обліковий запис, яким ви керуєте, незабаром буде видалено</translation>
<translation id="3382200254148930874">Вимкнення батьківського контролю…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Розділювач</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Вітаємо, <ph name="USER_GIVEN_NAME" />!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% – залишилося <ph name="TIME" /></translation>
<translation id="3637682276779847508">Вашу SIM-карту буде назавжди заблоковано, якщо ви не введете правильний ключ для розблокування PIN-коду.</translation>
-<translation id="363863692969456324">Виправляйте помилки правопису за допомогою покращеної функції перевірки орфографії</translation>
<translation id="3640214691812501263">Додати розширення <ph name="EXTENSION_NAME" /> для користувача <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Навчіть Асистент розпізнавати ваш голос</translation>
<translation id="3644896802912593514">Ширина</translation>
<translation id="3645372836428131288">Трохи перемістіть палець, щоб зісканувати іншу частину відбитка.</translation>
<translation id="3648348069317717750">Виявлено пристрій <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Більше додатків із використанням стилуса</translation>
<translation id="424546999567421758">Виявлено надмірне використання місця на диску</translation>
<translation id="424726838611654458">Завжди відкривати в Adobe Reader</translation>
-<translation id="4247330672018280062">Введений текст буде надіслано в Google</translation>
<translation id="4247901771970415646">Не вдалося синхронізуватися з користувачем <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Очікування на з’єднання з мережею…</translation>
<translation id="4249373718504745892">Доступ цієї сторінки до ваших камери та мікрофона заблоковано.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Профілювання ввімкнено</translation>
<translation id="4823484602432206655">Переглядати та змінювати налаштування користувача й пристрою</translation>
<translation id="4823651846660089135">Пристрій лише для перегляду</translation>
+<translation id="4824958205181053313">Скасувати синхронізацію?</translation>
<translation id="4827675678516992122">Не вдалося під’єднатись</translation>
<translation id="4828937774870308359">Австралійське</translation>
<translation id="4829768588131278040">Налаштувати PIN-код</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Змінити зображення</translation>
<translation id="5376169624176189338">Натисніть, щоб повернутися назад; утримуйте, щоб переглянути історію</translation>
<translation id="5376931455988532197">Файл завеликий</translation>
+<translation id="5377594097385838788">Режим анонімного перегляду</translation>
<translation id="537813040452600081">Сторінки, які ви переглядаєте в цьому вікні, не відображатимуться в історії веб-переглядача, а після вашого виходу не залишать у комп'ютері інших слідів, наприклад, файлів cookie. Завантажені вами файли та створені закладки не зберігаються.</translation>
<translation id="5379140238605961210">Продовжити блокувати доступ до мікрофона</translation>
<translation id="5379268888377976432">Відмінити видалення</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Читати значки веб-сайтів, які ви відвідуєте</translation>
<translation id="5417312524372586921">Теми веб-переглядача</translation>
<translation id="5419294236999569767">Час системи</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Визначає різкість тексту та зображень</translation>
<translation id="5422221874247253874">Точка доступу</translation>
<translation id="5422781158178868512">На жаль, пристрій зовнішньої пам’яті неможливо розпізнати.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 шифрування RSA</translation>
<translation id="5436492226391861498">Очікування тунелю проксі-сервера...</translation>
<translation id="5436510242972373446">Пошук <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Збережіть свої файли та створіть новий обліковий запис.</translation>
<translation id="5438224778284622050">Видалити офлайн-файли?</translation>
<translation id="544083962418256601">Створення ярликів...</translation>
<translation id="5442228125690314719">Не вдалося створити образ диска. Повторіть спробу.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">Також указує сторінку, яка відкривається під час натискання кнопки "Домашня сторінка" чи пошуку в універсальному вікні пошуку.</translation>
<translation id="5971037678316050792">Керувати станом і під’єднанням адаптера Bluetooth</translation>
<translation id="5972017421290582825">Керувати налаштуваннями MIDI…</translation>
+<translation id="597235323114979258">Переглянути більше пунктів призначення</translation>
+<translation id="5972666587303800813">Сервіс, що не потребує керування</translation>
<translation id="5972708806901999743">На початок</translation>
<translation id="5972826969634861500">Запустити <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Відсоток заряду акумулятора</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">Надіслати</translation>
<translation id="6528513914570774834">Надіти іншим користувачам цього пристрою доступ до цієї мережі</translation>
<translation id="652948702951888897">Історія Chrome</translation>
+<translation id="6530186581263215931">Ці налаштування застосовує адміністратор</translation>
<translation id="653019979737152879">Синхронізація файлу <ph name="FILE_NAME" />…</translation>
<translation id="6531282281159901044">Завантажити небезпечний файл</translation>
<translation id="6532101170117367231">Зберегти на Диску Google</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">Читати й змінювати історію веб-перегляду</translation>
<translation id="7019805045859631636">Швидка</translation>
<translation id="7022562585984256452">Вашу домашню сторінку налаштовано.</translation>
-<translation id="702384510542929236">Деякі системні дані та вміст сторінок анонімно надсилаються в Google</translation>
<translation id="7025190659207909717">Керування службою пересилання мобільних даних</translation>
<translation id="7027125358315426638">Назва бази даних:</translation>
<translation id="7029809446516969842">Паролі</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">Відкрити додаток Фоновий малюнок</translation>
<translation id="7290242001003353852">Ця служба входу в обліковий запис, зареєстрована в домені <ph name="SAML_DOMAIN" />, намагається отримати доступ до вашої камери.</translation>
<translation id="7290594223351252791">Підтвердження реєстрації</translation>
+<translation id="7292696521213967957">Інформація про налагодження роботи Асистента</translation>
<translation id="7295662345261934369">Надати доступ іншим користувачам</translation>
<translation id="729583233778673644">Дозволяє шифрування AES і RC4. Використання цієї опції підвищує ризик, оскільки шифри RC4 ненадійні.</translation>
<translation id="7296774163727375165">Умови <ph name="DOMAIN" /></translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">Відкрити розташування...</translation>
<translation id="7461924472993315131">Закріпити</translation>
<translation id="7463006580194749499">Додати користувача</translation>
-<translation id="7464902436585505072">Зразок голосу для команди "Ok Google"</translation>
<translation id="7465778193084373987">URL-адреса відкликання сертифіката Netscape</translation>
<translation id="7469894403370665791">Автоматично з'єднувати з цією мережею</translation>
<translation id="747114903913869239">Помилка: не вдається розшифрувати розширення</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424">Додаток <ph name="LINUX_APP_NAME" /> і пов’язані з ним дані буде видалено з цього пристрою.</translation>
<translation id="7497215489070763236">Сертифікат ЦС для сервера</translation>
<translation id="7497981768003291373">Немає нещодавно створених текстових журналів WebRTC.</translation>
+<translation id="7502199377020483660">Щоб користуватися цими картками на всіх пристроях, збережіть їх в обліковому записі Google</translation>
<translation id="7502658306369382406">Адреса IPv6</translation>
<translation id="7503191893372251637">Тип сертифіката Netscape</translation>
<translation id="7503821294401948377">Не вдалося завантажити піктограму "<ph name="ICON" />" для роботи веб-переглядача.</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">Одержувач: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Непідтримуваний пристрій Bluetooth: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Додати обліковий запис</translation>
+<translation id="7667248760110172428">Зовнішня пам’ять</translation>
<translation id="7671130400130574146">Використовувати системні границі та рядок заголовка</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, на сторінці <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Надішліть зразок свого голосу в Google, щоб дозволити диктування в будь-якому текстовому полі.</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">Тут відображатимуться збережені способи оплати</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> транслює ваш екран і аудіо.</translation>
<translation id="7931318309563332511">невідомо</translation>
+<translation id="7932969338829957666">Спільні папки в Linux доступні за шляхом <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Увімкнути звук на сайті}one{Увімкнути звук на сайтах}few{Увімкнути звук на сайтах}many{Увімкнути звук на сайтах}other{Увімкнути звук на сайтах}}</translation>
<translation id="7934414805353235750">Сайт <ph name="URL" /> хоче відтворювати захищений вміст. Google перевірить ідентифікатор вашого пристрою.</translation>
<translation id="793531125873261495">Не вдалося завантажити віртуальну машину. Повторіть спробу.</translation>
@@ -4672,6 +4684,7 @@
<translation id="8049705080247101012">Система Google позначила розширення <ph name="EXTENSION_NAME" /> як шкідливе та заборонила встановлення</translation>
<translation id="8049913480579063185">Назва розширення</translation>
<translation id="8050038245906040378">Підписування комерційного коду Microsoft</translation>
+<translation id="8052887694493382350">Цей файл створено для ПК з програмним забезпеченням Windows. Він несумісний із вашим пристроєм, оскільки на ньому встановлено ОС Chrome. <ph name="BEGIN_LINK_HELP" />Докладніше<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Файли PKCS #12</translation>
<translation id="8053390638574070785">Перезавантажити цю сторінку</translation>
<translation id="8054517699425078995">Цей тип файлу може зашкодити вашому пристрою. Усе одно зберегти <ph name="FILE_NAME" />?</translation>
@@ -4881,7 +4894,7 @@
<translation id="8382913212082956454">Копіювати &amp;адресу електронної пошти</translation>
<translation id="8386091599636877289">Правило не знайдено.</translation>
<translation id="8386903983509584791">Сканування завершено</translation>
-<translation id="8389492867173948260">Дозвольте цьому розширенню переглядати й змінювати всі ваші дані на веб-сайтах, які ви відвідуєте.</translation>
+<translation id="8389492867173948260">Дозволити розширенню переглядати й змінювати ваші дані на веб-сайтах, які ви відвідуєте:</translation>
<translation id="8390449457866780408">Сервер не доступний.</translation>
<translation id="8391712576156218334">Зображення недоступне. Повторіть спробу пізніше.</translation>
<translation id="8392234662362215700">Натисніть комбінацію клавіш Control-Shift-Space, щоб змінити розкладку клавіатури.</translation>
@@ -4915,6 +4928,7 @@
<translation id="8438566539970814960">Покращувати пошук і веб-перегляд</translation>
<translation id="8439506636278576865">Пропонувати переклад сторінок цією мовою</translation>
<translation id="8440630305826533614">Додатки Linux</translation>
+<translation id="8443338615972234259">Створіть новий обліковий запис для контрольованого користувача.</translation>
<translation id="8446884382197647889">Докладніше</translation>
<translation id="8447409163267621480">Натискайте Ctrl або Alt</translation>
<translation id="8448729345478502352">Зменшуйте або збільшуйте елементи на екрані</translation>
@@ -4939,6 +4953,7 @@
<translation id="8468750959626135884">Розблоковуйте пристрій <ph name="DEVICE_TYPE" /> за допомогою телефона Android.</translation>
<translation id="8470028084415844044">Щоб мати доступ до паролів на всіх своїх пристроях, увімкніть синхронізацію.</translation>
<translation id="8470513973197838199">Збережені паролі для <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Щоб користуватися цією карткою на всіх пристроях, збережіть її в обліковому записі Google</translation>
<translation id="8472623782143987204">з апаратною підтримкою</translation>
<translation id="8473863474539038330">Адреси й інше</translation>
<translation id="8475313423285172237">Інша програма на вашому комп’ютері додала розширення, яке може змінити роботу Chrome.</translation>
@@ -5014,7 +5029,6 @@
<translation id="8598453409908276158">Плагін із неізольованим програмним середовищем заблоковано</translation>
<translation id="8601206103050338563">Автентифікація клієнта TLS WWW</translation>
<translation id="8602851771975208551">Інша програма на вашому комп’ютері додала програму, яка може змінити роботу Chrome.</translation>
-<translation id="8604763363205185560">Допоможіть покращити веб-переглядач Chrome і його функції безпеки</translation>
<translation id="8605428685123651449">Пам’ять SQLite</translation>
<translation id="8606726445206553943">Використовувати ваші пристрої MIDI</translation>
<translation id="8609465669617005112">Угору</translation>
@@ -5190,6 +5204,7 @@
<translation id="8846141544112579928">Пошук клавіатури…</translation>
<translation id="8847988622838149491">Сповіщення щодо USB</translation>
<translation id="8848561196844274665">Підключаючи пристрої, ви дозволяєте Chromebook:</translation>
+<translation id="8850251000316748990">Показати більше…</translation>
<translation id="8859057652521303089">Виберіть мову:</translation>
<translation id="8859174528519900719">Додатковий фрейм: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Таблиця Excel</translation>
@@ -5427,7 +5442,7 @@
<translation id="934503638756687833">Якщо потрібно, можна також видалити елементи, не перелічені тут. Докладніше про &lt;a href="<ph name="URL" />"&gt;захист від небажаних програм&lt;/a&gt; читайте в інформаційному документі про конфіденційність Chrome.</translation>
<translation id="935490618240037774">Ваші закладки, історія, паролі й інші налаштування синхронізуватимуться з обліковим записом Google, щоб ви могли користуватися ними на всіх своїх пристроях.</translation>
<translation id="936801553271523408">Дані діагностики системи</translation>
-<translation id="93766956588638423">Відновити розширення</translation>
+<translation id="93766956588638423">Полагодити розширення</translation>
<translation id="938339467127511841">Обсяг пам’яті Linux (бета-версія)</translation>
<translation id="938470336146445890">Установіть сертифікат користувача.</translation>
<translation id="939252827960237676">Не вдалося зберегти знімок екрана</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_vi.xtb b/chromium/chrome/app/resources/generated_resources_vi.xtb
index e366e953460..3cc4f95c360 100644
--- a/chromium/chrome/app/resources/generated_resources_vi.xtb
+++ b/chromium/chrome/app/resources/generated_resources_vi.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">Bật chủ đề</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">Xem trong Cửa hàng Chrome trực tuyến</translation>
-<translation id="1761588866118490543">Mẫu giọng nói</translation>
<translation id="176193854664720708">Cảm biến vân tay nằm trong nút nguồn. Hãy chạm nhẹ vào nút này bằng ngón tay bất kỳ.</translation>
<translation id="1763046204212875858">Tạo các lối tắt cho ứng dụng</translation>
<translation id="1763108912552529023">Tiếp tục khám phá</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">Gửi dữ liệu chẩn đoán và dữ liệu về mức sử dụng. Thiết bị này hiện tự động gửi dữ liệu chẩn đoán, dữ liệu về mức sử dụng ứng dụng và thiết bị cho Google. Những thông tin này sẽ giúp tăng độ ổn định của hệ thống và ứng dụng cũng như cải thiện các mặt khác. Một số dữ liệu tổng hợp cũng sẽ hữu ích cho các ứng dụng và đối tác của Google, chẳng hạn như những nhà phát triển Android. Mục cài đặt này do chủ sở hữu thực thi. Nếu bạn bật mục cài đặt bổ sung Hoạt động web và ứng dụng thì dữ liệu này có thể được lưu vào Tài khoản Google của bạn. <ph name="BEGIN_LINK1" />Tìm hiểu thêm<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Nén zip</translation>
<translation id="220858061631308971">Vui lòng nhập mã PIN này trên "<ph name="DEVICE_NAME" />":</translation>
+<translation id="2213140827792212876">Xóa thư mục dùng chung</translation>
+<translation id="2214018885812055163">Thư mục dùng chung</translation>
<translation id="2214884991347062907">Mật khẩu không chính xác. Hãy thử lại</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;1 dòng không hiển thị&gt;}other{&lt;<ph name="NUMBER_OF_LINES" /> dòng không hiển thị&gt;}}</translation>
<translation id="2217501013957346740">Tạo một tên -</translation>
@@ -940,7 +941,7 @@
<translation id="2379281330731083556">In bằng hộp thoại hệ thống... <ph name="SHORTCUT_KEY" /></translation>
<translation id="2381756643783702095">Hỏi trước khi gửi (được đề xuất)</translation>
<translation id="2384436799579181135">Đã xảy ra lỗi. Vui lòng kiểm tra máy in của bạn và thử lại.</translation>
-<translation id="2386926718981642523">Nói "Ok Google" bất cứ lúc nào để sử dụng Trợ lý</translation>
+<translation id="2386926718981642523">Nói "Ok Google" bất cứ lúc nào bạn muốn sử dụng Trợ lý</translation>
<translation id="2387458720915042159">Loại kết nối proxy</translation>
<translation id="2391419135980381625">Phông chữ tiêu chuẩn</translation>
<translation id="2391762656119864333">Thu hồi</translation>
@@ -1015,6 +1016,7 @@
<translation id="2501173422421700905">Chứng chỉ bị Thu hồi</translation>
<translation id="2501797496290880632">Nhập phím tắt</translation>
<translation id="2502441965851148920">Đã bật cập nhật tự động. Quản trị viên của bạn đã tắt cập nhật thủ công.</translation>
+<translation id="2505127913256479918">Tài khoản được giám sát này sẽ sớm bị xóa</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{Màn hình #}other{Màn hình #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" /> của <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Tài khoản Cửa hàng Google Play</translation>
@@ -1375,6 +1377,7 @@
<translation id="304747341537320566">Công cụ chuyển văn bản sang lời nói</translation>
<translation id="3053013834507634016">Sử dụng Khoá Chứng chỉ</translation>
<translation id="3057861065630527966">Sao lưu ảnh và video của bạn</translation>
+<translation id="3058498974290601450">Bạn có thể bật tính năng đồng bộ hóa bất cứ lúc nào trong phần cài đặt</translation>
<translation id="3060379269883947824">Bật chọn để nói</translation>
<translation id="3061707000357573562">Dịch vụ vá lỗi</translation>
<translation id="3065041951436100775">Phản hồi tab bị lỗi.</translation>
@@ -1566,6 +1569,7 @@
<translation id="337920581046691015"><ph name="PRODUCT_NAME" /> sẽ được cài đặt.</translation>
<translation id="3380365263193509176">Lỗi không xác định</translation>
<translation id="3382073616108123819">Rất tiếc! Hệ thống không thể xác định số nhận dạng thiết bị cho thiết bị này.</translation>
+<translation id="3382086682569279540">Tài khoản bạn quản lý sẽ sớm bị xóa</translation>
<translation id="3382200254148930874">Ngừng tính năng giám sát...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">Dấu phân tách</translation>
@@ -1746,8 +1750,8 @@
<translation id="3636096452488277381">Xin chào <ph name="USER_GIVEN_NAME" />!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - còn lại <ph name="TIME" /></translation>
<translation id="3637682276779847508">Thẻ SIM của bạn sẽ bị vô hiệu hóa vĩnh viễn nếu bạn không thể nhập Khóa mở khóa mã PIN chính xác.</translation>
-<translation id="363863692969456324">Sửa lỗi chính tả bằng tính năng kiểm tra chính tả nâng cao</translation>
<translation id="3640214691812501263">Thêm "<ph name="EXTENSION_NAME" />" cho <ph name="USER_NAME" />?</translation>
+<translation id="3640613767643722554">Hướng dẫn Trợ lý nhận dạng giọng nói của bạn</translation>
<translation id="3644896802912593514">Chiều rộng</translation>
<translation id="3645372836428131288">Nhẹ nhàng di chuyển ngón tay để hệ thống quét các phần của vân tay.</translation>
<translation id="3648348069317717750">Đã phát hiện thấy <ph name="USB_DEVICE_NAME" /></translation>
@@ -2147,7 +2151,6 @@
<translation id="4244238649050961491">Tìm thêm ứng dụng bút cảm ứng</translation>
<translation id="424546999567421758">Đã phát hiện mức sử dụng ổ đĩa cao</translation>
<translation id="424726838611654458">Luôn mở trong Adobe Reader</translation>
-<translation id="4247330672018280062">Nội dung bạn nhập vào các trường văn bản sẽ được gửi đến Google</translation>
<translation id="4247901771970415646">Không thể đồng bộ hóa với <ph name="USERNAME" /></translation>
<translation id="4249248555939881673">Đang chờ kết nối mạng...</translation>
<translation id="4249373718504745892">Trang này đã bị chặn truy cập vào máy ảnh và micrô của bạn.</translation>
@@ -2489,6 +2492,7 @@
<translation id="4821935166599369261">&amp;Bật cấu hình</translation>
<translation id="4823484602432206655">Đọc và thay đổi cài đặt người dùng và thiết bị</translation>
<translation id="4823651846660089135">Thiết bị chỉ đọc</translation>
+<translation id="4824958205181053313">Bạn muốn hủy đồng bộ hóa?</translation>
<translation id="4827675678516992122">Không thể kết nối</translation>
<translation id="4828937774870308359">Tiếng Úc</translation>
<translation id="4829768588131278040">Thiết lập mã PIN</translation>
@@ -2871,6 +2875,7 @@
<translation id="5374359983950678924">Thay đổi hình ảnh</translation>
<translation id="5376169624176189338">Nhấp vào để quay lại, giữ để xem lịch sử</translation>
<translation id="5376931455988532197">Tệp quá lớn</translation>
+<translation id="5377594097385838788">Ẩn danh</translation>
<translation id="537813040452600081">Các trang bạn xem trong cửa sổ này sẽ không xuất hiện trong lịch sử trình duyệt đồng thời sẽ không để lại dấu vết khác, như cookie, trên máy tính sau khi bạn đăng xuất. Các tệp bạn tải xuống và các dấu trang bạn tạo sẽ không được lưu giữ.</translation>
<translation id="5379140238605961210">Tiếp tục chặn quyền truy cập micrô</translation>
<translation id="5379268888377976432">Khôi phục xóa</translation>
@@ -2892,6 +2897,7 @@
<translation id="5414566801737831689">Đọc biểu tượng của các trang web bạn truy cập</translation>
<translation id="5417312524372586921">Chủ đề của trình duyệt</translation>
<translation id="5419294236999569767">Giờ hệ thống</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">Xác định độ sắc nét của văn bản và hình ảnh</translation>
<translation id="5422221874247253874">Điểm truy cập</translation>
<translation id="5422781158178868512">Rất tiếc, thiết bị lưu trữ bên ngoài của bạn không thể nhận dạng được.</translation>
@@ -2912,6 +2918,7 @@
<translation id="5434065355175441495">PKCS #1 Mã hóa RSA</translation>
<translation id="5436492226391861498">Chờ đường hầm proxy...</translation>
<translation id="5436510242972373446">Tìm kiếm <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">Vui lòng lưu tệp của bạn và tạo tài khoản mới ngay bây giờ.</translation>
<translation id="5438224778284622050">Xóa tệp ngoại tuyến?</translation>
<translation id="544083962418256601">Tạo phím tắt...</translation>
<translation id="5442228125690314719">Lỗi khi tạo hình ảnh đĩa. Vui lòng thử lại.</translation>
@@ -3285,6 +3292,8 @@
<translation id="5965661248935608907">Tiện ích này cũng điều khiển trang nào được hiển thị khi bạn nhấp vào nút Trang chủ hoặc tìm kiếm từ Thanh địa chỉ.</translation>
<translation id="5971037678316050792">Kiểm soát ghép nối và trạng thái bộ đổi nguồn Bluetooth</translation>
<translation id="5972017421290582825">Quản lý cài đặt MIDI...</translation>
+<translation id="597235323114979258">Xem điểm đích khác</translation>
+<translation id="5972666587303800813">Dịch vụ không hoạt động</translation>
<translation id="5972708806901999743">Chuyển lên trên cùng</translation>
<translation id="5972826969634861500">Khởi động <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">Phần trăm sạc pin</translation>
@@ -3655,6 +3664,7 @@
<translation id="6527303717912515753">Chia sẻ</translation>
<translation id="6528513914570774834">Cho phép người dùng khác của thiết bị sử dụng mạng này</translation>
<translation id="652948702951888897">Lịch sử Chrome</translation>
+<translation id="6530186581263215931">Các tùy chọn cài đặt này được quản trị viên của bạn yêu cầu buộc phải tuân theo</translation>
<translation id="653019979737152879">Đang đồng bộ hóa <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">Giữ tệp nguy hiểm</translation>
<translation id="6532101170117367231">Lưu vào Google Drive</translation>
@@ -3848,7 +3858,7 @@
<translation id="6828153365543658583">Giới hạn đăng nhập cho những người dùng sau:</translation>
<translation id="6828860976882136098">Không thiết lập được cập nhật tự động cho tất cả người dùng (lỗi thực thi kiểm tra <ph name="ERROR_NUMBER" />)</translation>
<translation id="6829250331733125857">Nhận trợ giúp với <ph name="DEVICE_TYPE" /> của bạn.</translation>
-<translation id="682971198310367122">Chính sách bảo mật của Google</translation>
+<translation id="682971198310367122">Chính sách quyền riêng tư của Google</translation>
<translation id="6831043979455480757">Dịch</translation>
<translation id="683373380308365518">Chuyển sang trình duyệt an toàn và thông minh</translation>
<translation id="6835762382653651563">Vui lòng kết nối Internet để cập nhật <ph name="DEVICE_TYPE" /> của bạn.</translation>
@@ -3973,7 +3983,6 @@
<translation id="7018275672629230621">Đọc và thay đổi lịch sử duyệt web của bạn</translation>
<translation id="7019805045859631636">Nhanh</translation>
<translation id="7022562585984256452">Trang chủ của bạn đã được đặt.</translation>
-<translation id="702384510542929236">Gửi ẩn danh một số thông tin hệ thống và nội dung trang cho Google</translation>
<translation id="7025190659207909717">Quản lý dịch vụ dữ liệu di động</translation>
<translation id="7027125358315426638">Tên cơ sở dữ liệu:</translation>
<translation id="7029809446516969842">Mật khẩu</translation>
@@ -4153,6 +4162,7 @@
<translation id="7289225569524511578">Mở ứng dụng hình nền</translation>
<translation id="7290242001003353852">Dịch vụ đăng nhập này, do <ph name="SAML_DOMAIN" /> lưu trữ, đang truy cập vào máy ảnh của bạn.</translation>
<translation id="7290594223351252791">Xác nhận đăng ký</translation>
+<translation id="7292696521213967957">Thông tin để gỡ lỗi Trợ lý</translation>
<translation id="7295662345261934369">Chia sẻ với những người khác</translation>
<translation id="729583233778673644">Cho phép mã hóa AES và RC4. Việc sử dụng tùy chọn này sẽ làm gia tăng rủi ro vì các thuật toán mã hóa RC4 là không an toàn.</translation>
<translation id="7296774163727375165">Điều khoản dành cho <ph name="DOMAIN" /></translation>
@@ -4253,7 +4263,6 @@
<translation id="7456847797759667638">Mở Vị trí...</translation>
<translation id="7461924472993315131">Ghim</translation>
<translation id="7463006580194749499">Thêm người</translation>
-<translation id="7464902436585505072">Mẫu giọng nói "Ok Google"</translation>
<translation id="7465778193084373987">ULR Thu hồi của Tổ chức Cấp Chứng chỉ Netscape</translation>
<translation id="7469894403370665791">Tự động kết nối vào mạng này</translation>
<translation id="747114903913869239">Lỗi: Không thể giải mã tiện ích</translation>
@@ -4281,6 +4290,7 @@
<translation id="7496511874649569424"><ph name="LINUX_APP_NAME" /> và dữ liệu liên kết với ứng dụng sẽ bị xóa khỏi thiết bị này.</translation>
<translation id="7497215489070763236">Chứng chỉ CA máy chủ</translation>
<translation id="7497981768003291373">Bạn không ghi nhật ký văn bản WebRTC nào gần đây.</translation>
+<translation id="7502199377020483660">Hãy lưu các thẻ này vào Tài khoản Google của bạn để sử dụng trên tất cả các thiết bị</translation>
<translation id="7502658306369382406">Địa chỉ IPv6</translation>
<translation id="7503191893372251637">Loại Chứng chỉ Netscape</translation>
<translation id="7503821294401948377">Không thể tải biểu tượng '<ph name="ICON" />' cho tác vụ của trình duyệt.</translation>
@@ -4378,6 +4388,7 @@
<translation id="7663719505383602579">Bộ thu: <ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">Thiết bị Bluetooth không được hỗ trợ: "<ph name="DEVICE_NAME" />".</translation>
<translation id="7665369617277396874">Thêm tài khoản</translation>
+<translation id="7667248760110172428">Bộ nhớ bên ngoài</translation>
<translation id="7671130400130574146">Sử dụng thanh tiêu đề và đường viền của hệ thống</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />, trong <ph name="PAGE_TITLE" />.</translation>
<translation id="7676867886086876795">Gửi giọng nói của bạn tới Google để cho phép nhập bằng giọng nói vào bất kỳ trường văn bản nào.</translation>
@@ -4581,6 +4592,7 @@
<translation id="7930294771522048157">Các phương thức thanh toán đã lưu sẽ xuất hiện ở đây</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> đang chia sẻ màn hình và âm thanh của bạn.</translation>
<translation id="7931318309563332511">Không xác định</translation>
+<translation id="7932969338829957666">Thư mục dùng chung có sẵn trong Linux tại <ph name="BASE_DIR" />.</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{Bật âm thanh trang web}other{Bật âm thanh các trang web}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> muốn phát nội dung được bảo vệ. Thông tin định danh thiết bị của bạn sẽ được Google xác minh.</translation>
<translation id="793531125873261495">Lỗi khi tải máy ảo xuống. Vui lòng thử lại.</translation>
@@ -4672,6 +4684,7 @@ Giữ tệp khóa của bạn ở nơi an toàn. Bạn sẽ cần tệp khóa đ
<translation id="8049705080247101012">Google đã gắn cờ "<ph name="EXTENSION_NAME" />" là độc hại và cài đặt đã bị chặn</translation>
<translation id="8049913480579063185">Tên tiện ích</translation>
<translation id="8050038245906040378">Ký Mã Thương mại của Microsoft</translation>
+<translation id="8052887694493382350">Tệp này dành cho máy tính để bàn chạy hệ điều hành Windows. Tệp này không tương thích với thiết bị chạy Chrome OS của bạn. <ph name="BEGIN_LINK_HELP" />Tìm hiểu thêm<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">Tệp PKCS #12</translation>
<translation id="8053390638574070785">Tải lại Trang Này</translation>
<translation id="8054517699425078995">Loại tệp này có thể gây hại cho thiết bị của bạn. Bạn vẫn muốn giữ lại <ph name="FILE_NAME" />?</translation>
@@ -4915,6 +4928,7 @@ Giữ tệp khóa của bạn ở nơi an toàn. Bạn sẽ cần tệp khóa đ
<translation id="8438566539970814960">Cải thiện tính năng tìm kiếm và duyệt web</translation>
<translation id="8439506636278576865">Đề xuất dịch trang bằng ngôn ngữ này</translation>
<translation id="8440630305826533614">Ứng dụng Linux</translation>
+<translation id="8443338615972234259">Vui lòng tạo tài khoản mới cho người dùng được giám sát của bạn ngay bây giờ.</translation>
<translation id="8446884382197647889">Tìm hiểu thêm</translation>
<translation id="8447409163267621480">Bao gồm phím Ctrl hoặc phím Alt</translation>
<translation id="8448729345478502352">Thu nhỏ hoặc phóng to các mục trên màn hình</translation>
@@ -4939,6 +4953,7 @@ Giữ tệp khóa của bạn ở nơi an toàn. Bạn sẽ cần tệp khóa đ
<translation id="8468750959626135884">Mở khóa <ph name="DEVICE_TYPE" /> của bạn bằng điện thoại Android.</translation>
<translation id="8470028084415844044">Để lấy tất cả mật khẩu của bạn trên mọi thiết bị, hãy bật tính năng đồng bộ hóa.</translation>
<translation id="8470513973197838199">Đã lưu mật khẩu cho <ph name="ORIGIN" /></translation>
+<translation id="8471635086304129332">Hãy lưu thẻ này vào Tài khoản Google của bạn để sử dụng trên tất cả các thiết bị</translation>
<translation id="8472623782143987204">được hỗ trợ bằng phần cứng</translation>
<translation id="8473863474539038330">Địa chỉ và các tùy chọn khác</translation>
<translation id="8475313423285172237">Một chương trình khác trên máy tính của bạn đã thêm một tiện ích có thể thay đổi cách Chrome hoạt động.</translation>
@@ -5014,7 +5029,6 @@ Giữ tệp khóa của bạn ở nơi an toàn. Bạn sẽ cần tệp khóa đ
<translation id="8598453409908276158">Đã chặn truy cập vào plugin không có hộp cát</translation>
<translation id="8601206103050338563">Xác thực Ứng dụng khách TLS WWW</translation>
<translation id="8602851771975208551">Một chương trình khác trên máy tính của bạn đã thêm một ứng dụng có thể thay đổi cách Chrome hoạt động.</translation>
-<translation id="8604763363205185560">Giúp cải thiện Chrome và tăng cường khả năng bảo mật</translation>
<translation id="8605428685123651449">Bộ nhớ SQLite</translation>
<translation id="8606726445206553943">Sử dụng các thiết bị MIDI của bạn</translation>
<translation id="8609465669617005112">Di chuyển lên</translation>
@@ -5190,6 +5204,7 @@ Giữ tệp khóa của bạn ở nơi an toàn. Bạn sẽ cần tệp khóa đ
<translation id="8846141544112579928">Đang tìm kiếm bàn phím...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">Khi kết nối các thiết bị, bạn đồng ý rằng Chromebook có thể:</translation>
+<translation id="8850251000316748990">Xem thêm...</translation>
<translation id="8859057652521303089">Chọn ngôn ngữ:</translation>
<translation id="8859174528519900719">Khung phụ: <ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Bảng tính Excel</translation>
@@ -5210,7 +5225,7 @@ Giữ tệp khóa của bạn ở nơi an toàn. Bạn sẽ cần tệp khóa đ
<translation id="8883847527783433352">Đồng bộ hóa với một tài khoản khác</translation>
<translation id="8885197664446363138">Smart Lock không khả dụng</translation>
<translation id="88870264962436283">Sử dụng Touch ID cho <ph name="APP_NAME" /></translation>
-<translation id="8888253246822647887">Ứng dụng của bạn sẽ mở khi nâng cấp xong. Quá trình nâng cấp có thể mất vài phút.</translation>
+<translation id="8888253246822647887">Ứng dụng sẽ mở khi nâng cấp xong. Quá trình nâng cấp có thể mất vài phút.</translation>
<translation id="8888432776533519951">Màu:</translation>
<translation id="8890516388109605451">Nguồn</translation>
<translation id="8892168913673237979">Đã hoàn tất!</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_zh-CN.xtb b/chromium/chrome/app/resources/generated_resources_zh-CN.xtb
index 29cdab72983..2f450b5bf35 100644
--- a/chromium/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chromium/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -515,7 +515,6 @@
<translation id="175772926354468439">启用主题背景</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">在 Chrome 网上应用店中查看详情</translation>
-<translation id="1761588866118490543">语音模型</translation>
<translation id="176193854664720708">指纹传感器位于电源按钮中。请用任一根手指轻轻触摸它。</translation>
<translation id="1763046204212875858">创建应用快捷方式</translation>
<translation id="1763108912552529023">继续了解</translation>
@@ -812,6 +811,8 @@
<translation id="220792432208469595">发送使用情况数据和诊断数据。目前,此设备会自动向 Google 发送诊断数据、设备数据和应用使用情况数据。这些数据会被用来帮助提高系统和应用的稳定性以及实现其他方面的改进。部分汇总数据也会对 Google 应用和合作伙伴(例如 Android 开发者)有所帮助。这项设置是由此设备的所有者强制指定的。如果您已开启“其他网络与应用活动记录”设置,这些数据可能会被保存到您的 Google 帐号中。<ph name="BEGIN_LINK1" />了解详情<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip 归档</translation>
<translation id="220858061631308971">请在“<ph name="DEVICE_NAME" />”上输入此 PIN 码:</translation>
+<translation id="2213140827792212876">停止共享</translation>
+<translation id="2214018885812055163">共享的文件夹</translation>
<translation id="2214884991347062907">密码不正确,请重试</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;有 1 行代码未显示出来&gt;}other{&lt;有 <ph name="NUMBER_OF_LINES" /> 行代码未显示出来&gt;}}</translation>
<translation id="2217501013957346740">新建用户名 -</translation>
@@ -1011,6 +1012,7 @@
<translation id="2501173422421700905">待批证书</translation>
<translation id="2501797496290880632">输入快捷键</translation>
<translation id="2502441965851148920">已启用自动更新。您的管理员已停用手动更新。</translation>
+<translation id="2505127913256479918">这个受监管帐号很快就会被移除</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{屏幕 #}other{屏幕 #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" />,共 <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play 商店帐号</translation>
@@ -1370,6 +1372,7 @@
<translation id="304747341537320566">语音引擎</translation>
<translation id="3053013834507634016">证书密钥用法</translation>
<translation id="3057861065630527966">备份您的照片和视频</translation>
+<translation id="3058498974290601450">您随时可在“设置”中开启同步功能</translation>
<translation id="3060379269883947824">启用“随选朗读”</translation>
<translation id="3061707000357573562">修补服务</translation>
<translation id="3065041951436100775">标签页意外关闭反馈。</translation>
@@ -1559,11 +1562,12 @@
<translation id="337920581046691015">系统将要安装<ph name="PRODUCT_NAME" />。</translation>
<translation id="3380365263193509176">未知错误</translation>
<translation id="3382073616108123819">糟糕!系统无法识别此设备的标识符。</translation>
+<translation id="3382086682569279540">您所管理的帐号很快就会被移除</translation>
<translation id="3382200254148930874">正在停用监管功能…</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">分隔符</translation>
<translation id="3389312115541230716">右键点击任务栏中的 <ph name="SMALL_PRODUCT_LOGO" /> 图标</translation>
-<translation id="3393352139658145068">只要有人说“Ok Google”,就能启动 Google 助理。为了省电,仅当您的设备连接至电源时,“Ok Google”才可用。</translation>
+<translation id="3393352139658145068">只要有人说“Ok Google”,就能启动 Google 助理。为了省电,“Ok Google”仅在您的设备连接至电源时可用。</translation>
<translation id="3396800784455899911">点击“接受并继续”按钮,即表示您同意上述针对这些 Google 服务的处理方式。</translation>
<translation id="3399432415385675819">通知将被停用</translation>
<translation id="340282674066624">已下载 <ph name="DOWNLOAD_RECEIVED" />,还需 <ph name="TIME_LEFT" /></translation>
@@ -1739,8 +1743,8 @@
<translation id="3636096452488277381"><ph name="USER_GIVEN_NAME" />,您好!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - 还可使用 <ph name="TIME" /></translation>
<translation id="3637682276779847508">如果您无法输入正确的 PIN 码解锁密钥,您的 SIM 卡将被永久停用。</translation>
-<translation id="363863692969456324">通过增强的“拼写检查”功能修正拼写错误</translation>
<translation id="3640214691812501263">要为<ph name="USER_NAME" />添加“<ph name="EXTENSION_NAME" />”吗?</translation>
+<translation id="3640613767643722554">训练 Google 助理识别您的声音</translation>
<translation id="3644896802912593514">宽度</translation>
<translation id="3645372836428131288">请稍微移动一下手指,以便系统记录您指纹的不同部分。</translation>
<translation id="3648348069317717750">检测到<ph name="USB_DEVICE_NAME" /></translation>
@@ -2139,7 +2143,6 @@
<translation id="4244238649050961491">查找更多触控笔应用</translation>
<translation id="424546999567421758">检测到磁盘占用量非常高</translation>
<translation id="424726838611654458">始终用Adobe Reader打开</translation>
-<translation id="4247330672018280062">您在文本字段中输入的文字将会被发送给 Google</translation>
<translation id="4247901771970415646">无法同步到“<ph name="USERNAME" />”</translation>
<translation id="4249248555939881673">正在等待建立网络连接…</translation>
<translation id="4249373718504745892">已禁止此网页使用您的摄像头和麦克风。</translation>
@@ -2481,6 +2484,7 @@
<translation id="4821935166599369261">分析已启用(&amp;P)</translation>
<translation id="4823484602432206655">读取和更改用户设置与设备设置</translation>
<translation id="4823651846660089135">设备目前处于只读模式</translation>
+<translation id="4824958205181053313">取消同步?</translation>
<translation id="4827675678516992122">无法连接</translation>
<translation id="4828937774870308359">澳大利亚</translation>
<translation id="4829768588131278040">设置 PIN 码</translation>
@@ -2858,6 +2862,7 @@
<translation id="5374359983950678924">更改照片</translation>
<translation id="5376169624176189338">点击可后退,按住可查看历史记录</translation>
<translation id="5376931455988532197">文件过大</translation>
+<translation id="5377594097385838788">无痕模式</translation>
<translation id="537813040452600081">当您退出后,您在此窗口中浏览的网页将不会显示在浏览器历史记录中,也不会在计算机上留下其他痕迹(例如Cookie)。您下载的文件和创建的书签将不会保留。</translation>
<translation id="5379140238605961210">继续禁止使用麦克风</translation>
<translation id="5379268888377976432">撤消删除操作</translation>
@@ -2879,6 +2884,7 @@
<translation id="5414566801737831689">读取您访问过的网站对应的图标</translation>
<translation id="5417312524372586921">浏览器主题背景</translation>
<translation id="5419294236999569767">系统时间</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">确定文字和图片的清晰度</translation>
<translation id="5422221874247253874">接入点</translation>
<translation id="5422781158178868512">抱歉,系统无法识别您的外部存储设备。</translation>
@@ -2899,6 +2905,7 @@
<translation id="5434065355175441495">PKCS #1 RSA 加密</translation>
<translation id="5436492226391861498">正在等待代理隧道的响应...</translation>
<translation id="5436510242972373446">用 <ph name="SITE_NAME" /> 搜索:</translation>
+<translation id="543806387003274181">请立即保存您的文件并创建一个新帐号。</translation>
<translation id="5438224778284622050">要删除离线文件吗?</translation>
<translation id="544083962418256601">创建快捷方式...</translation>
<translation id="5442228125690314719">创建磁盘映像时出错。请重试。</translation>
@@ -3272,6 +3279,8 @@
<translation id="5965661248935608907">它还能够控制您点击“主页”按钮后或通过多功能框进行搜索时系统显示的页面。</translation>
<translation id="5971037678316050792">控制蓝牙适配器状态和配对</translation>
<translation id="5972017421290582825">管理 MIDI 设置…</translation>
+<translation id="597235323114979258">查看更多目的地</translation>
+<translation id="5972666587303800813">无运维服务</translation>
<translation id="5972708806901999743">移到顶部</translation>
<translation id="5972826969634861500">启动<ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">电池充电百分比</translation>
@@ -3642,6 +3651,7 @@
<translation id="6527303717912515753">分享</translation>
<translation id="6528513914570774834">允许此设备的其他用户使用此网络</translation>
<translation id="652948702951888897">Chrome 历史记录</translation>
+<translation id="6530186581263215931">这些设置是由您的管理员强制指定的</translation>
<translation id="653019979737152879">正在同步<ph name="FILE_NAME" />…</translation>
<translation id="6531282281159901044">保留危险文件</translation>
<translation id="6532101170117367231">保存到 Google 云端硬盘</translation>
@@ -3705,7 +3715,7 @@
<translation id="6629841649550503054">所有文件都已备份到 <ph name="BEGIN_LINK" />Google 云端硬盘<ph name="END_LINK" />!</translation>
<translation id="6630752851777525409"><ph name="EXTENSION_NAME" />希望获得某个证书的永久访问权限,以便代表您进行自我身份验证。</translation>
<translation id="6635956300022133031">选择和自定义文字转语音的语音</translation>
-<translation id="6637585982786704944">已获得您的授权的应用和网站可访问其所需的帐号信息以正常运行。
+<translation id="6637585982786704944">已获得您授权的应用和网站可访问其正常运行所需的帐号信息。
如果您不想添加帐号,请以访客身份登录,或打开一个无痕式窗口来浏览网页。
@@ -3960,7 +3970,6 @@
<translation id="7018275672629230621">读取和更改您的浏览记录</translation>
<translation id="7019805045859631636">快</translation>
<translation id="7022562585984256452">您的主页已设置。</translation>
-<translation id="702384510542929236">将一些系统信息和网页内容匿名发送给 Google</translation>
<translation id="7025190659207909717">移动数据服务管理</translation>
<translation id="7027125358315426638">数据库名称:</translation>
<translation id="7029809446516969842">密码</translation>
@@ -4140,6 +4149,7 @@
<translation id="7289225569524511578">打开壁纸应用</translation>
<translation id="7290242001003353852">这项由 <ph name="SAML_DOMAIN" /> 托管的登录服务正在使用您的摄像头。</translation>
<translation id="7290594223351252791">确认注册</translation>
+<translation id="7292696521213967957">附上用于调试 Google 助理的信息</translation>
<translation id="7295662345261934369">与他人共享</translation>
<translation id="729583233778673644">允许使用 AES 和 RC4 加密。选中此选项会令您面临更大的风险,因为 RC4 加密不安全。</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> 条款</translation>
@@ -4240,7 +4250,6 @@
<translation id="7456847797759667638">打开位置...</translation>
<translation id="7461924472993315131">固定</translation>
<translation id="7463006580194749499">添加用户</translation>
-<translation id="7464902436585505072">“Ok Google”语音模型</translation>
<translation id="7465778193084373987">Netscape 证书吊销网址</translation>
<translation id="7469894403370665791">自动连接到该网络</translation>
<translation id="747114903913869239">错误:无法对扩展程序进行解码</translation>
@@ -4268,6 +4277,7 @@
<translation id="7496511874649569424">系统将会从此设备上移除“<ph name="LINUX_APP_NAME" />”以及与其相关的数据。</translation>
<translation id="7497215489070763236">服务器 CA 证书</translation>
<translation id="7497981768003291373">您最近未记录 WebRTC 文本日志。</translation>
+<translation id="7502199377020483660">若想在您的所有设备上使用这些卡,请将它们保存到您的 Google 帐号中</translation>
<translation id="7502658306369382406">IPv6 地址</translation>
<translation id="7503191893372251637">Netscape 证书类型</translation>
<translation id="7503821294401948377">无法加载浏览器操作的“<ph name="ICON" />”图标。</translation>
@@ -4363,6 +4373,7 @@
<translation id="7663719505383602579">接收器:<ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">不支持的蓝牙设备:“<ph name="DEVICE_NAME" />”。</translation>
<translation id="7665369617277396874">添加帐号</translation>
+<translation id="7667248760110172428">外部存储空间</translation>
<translation id="7671130400130574146">使用系统标题栏和边框</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" />(在 <ph name="PAGE_TITLE" /> 中)。</translation>
<translation id="7676867886086876795">将您的语音内容发送给 Google,以便能向任何文本字段输入语音内容。</translation>
@@ -4566,6 +4577,7 @@
<translation id="7930294771522048157">已保存的付款方式会显示在这里</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> 正在共享您的屏幕和音频。</translation>
<translation id="7931318309563332511">未知</translation>
+<translation id="7932969338829957666">共享的文件夹位于 Linux 中的 <ph name="BASE_DIR" /> 下。</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{将这个网站取消静音}other{将这些网站取消静音}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> 想播放受保护的内容。Google 将对您的设备进行身份验证。</translation>
<translation id="793531125873261495">下载虚拟机时出错。请重试。</translation>
@@ -4657,6 +4669,7 @@
<translation id="8049705080247101012">Google 已将“<ph name="EXTENSION_NAME" />”标记为恶意扩展程序并已阻止系统安装它</translation>
<translation id="8049913480579063185">扩展程序名称</translation>
<translation id="8050038245906040378">Microsoft 商业代码签名</translation>
+<translation id="8052887694493382350">此文件适用于运行 Windows 软件的 PC,不适用于运行 Chrome 操作系统的设备。<ph name="BEGIN_LINK_HELP" />了解详情<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 文件</translation>
<translation id="8053390638574070785">重新加载此页</translation>
<translation id="8054517699425078995">此类型的文件可能会危害您的设备。仍要保留 <ph name="FILE_NAME" /> 吗?</translation>
@@ -4899,6 +4912,7 @@
<translation id="8438566539970814960">改善搜索和浏览体验</translation>
<translation id="8439506636278576865">询问是否翻译此语言的网页</translation>
<translation id="8440630305826533614">Linux 应用</translation>
+<translation id="8443338615972234259">请立即为您的受监管用户创建一个新帐号。</translation>
<translation id="8446884382197647889">了解详情</translation>
<translation id="8447409163267621480">必须以 Ctrl 键或 Alt 键开头</translation>
<translation id="8448729345478502352">缩小或放大屏幕上的内容</translation>
@@ -4923,6 +4937,7 @@
<translation id="8468750959626135884">利用 Android 手机解锁您的 <ph name="DEVICE_TYPE" />。</translation>
<translation id="8470028084415844044">要想将您的所有密码同步到您的所有设备上,请开启同步功能。</translation>
<translation id="8470513973197838199">已保存用于登录 <ph name="ORIGIN" /> 的密码</translation>
+<translation id="8471635086304129332">若想在您的所有设备上使用这张卡,请将它保存到您的 Google 帐号中</translation>
<translation id="8472623782143987204">硬件支持</translation>
<translation id="8473863474539038330">地址和其他信息</translation>
<translation id="8475313423285172237">您计算机上的其他程序添加了一个扩展程序,该扩展程序可能会改变 Chrome 的工作方式。</translation>
@@ -4998,7 +5013,6 @@
<translation id="8598453409908276158">已拦截未经过沙盒屏蔽的插件</translation>
<translation id="8601206103050338563">TLS WWW 客户端身份验证</translation>
<translation id="8602851771975208551">您计算机上的其他程序添加了一个应用,该应用可能会改变 Chrome 的工作方式。</translation>
-<translation id="8604763363205185560">帮助改进 Chrome 并提高其安全性</translation>
<translation id="8605428685123651449">SQLite 使用的内存</translation>
<translation id="8606726445206553943">使用您的 MIDI 设备</translation>
<translation id="8609465669617005112">上移</translation>
@@ -5174,6 +5188,7 @@
<translation id="8846141544112579928">正在搜索键盘…</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">连接您的设备即表示您同意 Chromebook 执行以下操作:</translation>
+<translation id="8850251000316748990">查看更多…</translation>
<translation id="8859057652521303089">选择语言:</translation>
<translation id="8859174528519900719">辅助框架:<ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel 电子表格</translation>
@@ -5194,7 +5209,7 @@
<translation id="8883847527783433352">同步到另一帐号中</translation>
<translation id="8885197664446363138">无法开启 Smart Lock</translation>
<translation id="88870264962436283">使用 Touch ID 登录 <ph name="APP_NAME" /></translation>
-<translation id="8888253246822647887">待完成升级后,您的应用即会打开。整个升级过程可能需要几分钟的时间。</translation>
+<translation id="8888253246822647887">待完成升级后,您的应用即会打开。升级过程可能会持续几分钟。</translation>
<translation id="8888432776533519951">颜色:</translation>
<translation id="8890516388109605451">来源</translation>
<translation id="8892168913673237979">搞定了!</translation>
diff --git a/chromium/chrome/app/resources/generated_resources_zh-TW.xtb b/chromium/chrome/app/resources/generated_resources_zh-TW.xtb
index 7920adeff0c..f024a408020 100644
--- a/chromium/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chromium/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -518,7 +518,6 @@
<translation id="175772926354468439">啟用主題</translation>
<translation id="1758018619400202187">EAP-TLS</translation>
<translation id="17584710573359123">前往 Chrome 線上應用程式商店查看</translation>
-<translation id="1761588866118490543">語音模型</translation>
<translation id="176193854664720708">指紋感應器位於電源按鈕上,請以任何一隻手指輕觸指紋感應器。</translation>
<translation id="1763046204212875858">建立應用程式捷徑</translation>
<translation id="1763108912552529023">繼續探索</translation>
@@ -815,6 +814,8 @@
<translation id="220792432208469595">傳送使用狀況與診斷資料。這個裝置目前會自動將診斷資料以及裝置和應用程式的使用狀況資料傳送給 Google。這些資料將有助於系統和應用程式提高穩定性及做出其他改善。部分匯總資料還能夠為 Google 應用程式和合作夥伴 (例如 Android 開發人員) 提供幫助。這項設定是由裝置擁有者執行。如果你的「其他網路和應用程式活動」設定為開啟,系統可能會將這些資料儲存到你的 Google 帳戶。<ph name="BEGIN_LINK1" />瞭解詳情<ph name="END_LINK1" /></translation>
<translation id="2208158072373999562">Zip 封存</translation>
<translation id="220858061631308971">請在「<ph name="DEVICE_NAME" />」上輸入以下 PIN 碼:</translation>
+<translation id="2213140827792212876">移除共用設定</translation>
+<translation id="2214018885812055163">共用資料夾</translation>
<translation id="2214884991347062907">密碼錯誤,請再試一次</translation>
<translation id="2214893006758804920">{LINE_COUNT,plural, =1{&lt;還有 1 行未顯示&gt;}other{&lt;還有 <ph name="NUMBER_OF_LINES" /> 行未顯示&gt;}}</translation>
<translation id="2217501013957346740">建立名稱 -</translation>
@@ -1014,6 +1015,7 @@
<translation id="2501173422421700905">憑證保留中</translation>
<translation id="2501797496290880632">按下快速鍵</translation>
<translation id="2502441965851148920">自動更新功能已啟用。您的管理員停用了手動更新功能。</translation>
+<translation id="2505127913256479918">系統即將移除這個受監管的帳戶</translation>
<translation id="2505324914378689427">{SCREEN_INDEX,plural, =1{螢幕 #}other{螢幕 #}}</translation>
<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT" />,總共 <ph name="TOTAL_SIZE" /></translation>
<translation id="2508428939232952663">Google Play 商店帳戶</translation>
@@ -1374,6 +1376,7 @@
<translation id="304747341537320566">語音引擎</translation>
<translation id="3053013834507634016">憑證金鑰用途</translation>
<translation id="3057861065630527966">備份您的相片和影片</translation>
+<translation id="3058498974290601450">你隨時可以在設定中開啟同步功能</translation>
<translation id="3060379269883947824">啟用隨選朗讀功能</translation>
<translation id="3061707000357573562">修補服務</translation>
<translation id="3065041951436100775">分頁毀損意見回饋。</translation>
@@ -1565,6 +1568,7 @@
<translation id="337920581046691015">系統將會安裝「<ph name="PRODUCT_NAME" />」。</translation>
<translation id="3380365263193509176">未知的錯誤</translation>
<translation id="3382073616108123819">糟糕!系統無法判別這個裝置的裝置識別碼。</translation>
+<translation id="3382086682569279540">系統即將移除你管理的帳戶</translation>
<translation id="3382200254148930874">正在停用監督功能...</translation>
<translation id="3385092118218578224"><ph name="DISPLAY_ZOOM" />%</translation>
<translation id="338583716107319301">分隔線</translation>
@@ -1745,8 +1749,8 @@
<translation id="3636096452488277381"><ph name="USER_GIVEN_NAME" />,你好!</translation>
<translation id="3636766455281737684"><ph name="PERCENTAGE" />% - 還可以使用 <ph name="TIME" /></translation>
<translation id="3637682276779847508">如果無法輸入正確的 PIN 解鎖金鑰,SIM 卡會遭到永久停用。</translation>
-<translation id="363863692969456324">使用進階拼字檢查功能修正拼字錯誤</translation>
<translation id="3640214691812501263">為<ph name="USER_NAME" />新增「<ph name="EXTENSION_NAME" />」?</translation>
+<translation id="3640613767643722554">訓練 Google 助理辨識你的聲音</translation>
<translation id="3644896802912593514">寬度</translation>
<translation id="3645372836428131288">請稍微移動手指,讓系統擷取完整指紋</translation>
<translation id="3648348069317717750">偵測到 <ph name="USB_DEVICE_NAME" /></translation>
@@ -2145,7 +2149,6 @@
<translation id="4244238649050961491">尋找其他觸控筆應用程式</translation>
<translation id="424546999567421758">偵測到磁碟使用量偏高情形</translation>
<translation id="424726838611654458">一律在 Adobe Reader 中開啟</translation>
-<translation id="4247330672018280062">系統會將你在文字欄位中輸入的文字傳送給 Google</translation>
<translation id="4247901771970415646">無法與 <ph name="USERNAME" /> 同步</translation>
<translation id="4249248555939881673">正在等待網路連線...</translation>
<translation id="4249373718504745892">系統已封鎖這個網頁存取你的攝影機和麥克風。</translation>
@@ -2487,6 +2490,7 @@
<translation id="4821935166599369261">分析已啟用(&amp;P)</translation>
<translation id="4823484602432206655">讀取及變更使用者和裝置設定</translation>
<translation id="4823651846660089135">裝置目前是唯讀模式</translation>
+<translation id="4824958205181053313">取消同步處理?</translation>
<translation id="4827675678516992122">無法連線</translation>
<translation id="4828937774870308359">澳洲式</translation>
<translation id="4829768588131278040">設定 PIN 碼</translation>
@@ -2869,6 +2873,7 @@
<translation id="5374359983950678924">變更圖片</translation>
<translation id="5376169624176189338">按一下回上一頁,按住可查看記錄</translation>
<translation id="5376931455988532197">檔案過大</translation>
+<translation id="5377594097385838788">無痕模式</translation>
<translation id="537813040452600081">你在這個視窗瀏覽的網頁不會顯示在瀏覽器記錄中,而且在你登出之後,電腦也不會留下 Cookie 等其他記錄。此外,系統不會保留你下載的檔案和建立的書籤。</translation>
<translation id="5379140238605961210">繼續封鎖存取麥克風</translation>
<translation id="5379268888377976432">復原刪除</translation>
@@ -2890,6 +2895,7 @@
<translation id="5414566801737831689">讀取你所瀏覽網站的圖示</translation>
<translation id="5417312524372586921">瀏覽器主題</translation>
<translation id="5419294236999569767">系統時間</translation>
+<translation id="5419405654816502573">Voice Match</translation>
<translation id="5420438158931847627">決定文字和圖片的銳利度</translation>
<translation id="5422221874247253874">存取點</translation>
<translation id="5422781158178868512">很抱歉,系統無法識別你的外部儲存裝置。</translation>
@@ -2910,6 +2916,7 @@
<translation id="5434065355175441495">PKCS #1 RSA 加密</translation>
<translation id="5436492226391861498">正在等待 Proxy 通道...</translation>
<translation id="5436510242972373446">搜尋 <ph name="SITE_NAME" />:</translation>
+<translation id="543806387003274181">請立即儲存你的檔案並建立新帳戶。</translation>
<translation id="5438224778284622050">要刪除離線檔案嗎?</translation>
<translation id="544083962418256601">建立捷徑...</translation>
<translation id="5442228125690314719">建立磁碟映像檔時發生錯誤,請再試一次。</translation>
@@ -3283,6 +3290,8 @@
<translation id="5965661248935608907">這個擴充功能也會控管你點選 [首頁] 按鈕或使用網址列搜尋時所顯示的網頁。</translation>
<translation id="5971037678316050792">控制藍牙介面卡狀態與連線配對功能</translation>
<translation id="5972017421290582825">管理 MIDI 設定...</translation>
+<translation id="597235323114979258">顯示更多列印端點</translation>
+<translation id="5972666587303800813">無作業服務</translation>
<translation id="5972708806901999743">移至頂端</translation>
<translation id="5972826969634861500">啟動 <ph name="PRODUCT_NAME" /></translation>
<translation id="5975792506968920132">電池充電百分比</translation>
@@ -3653,6 +3662,7 @@
<translation id="6527303717912515753">分享</translation>
<translation id="6528513914570774834">允許這個裝置的其他使用者使用這個網路</translation>
<translation id="652948702951888897">Chrome 歷史記錄</translation>
+<translation id="6530186581263215931">這些是系統管理員強制套用的設定</translation>
<translation id="653019979737152879">正在同步處理 <ph name="FILE_NAME" />...</translation>
<translation id="6531282281159901044">保留不安全的檔案</translation>
<translation id="6532101170117367231">儲存至 Google 雲端硬碟</translation>
@@ -3967,7 +3977,6 @@
<translation id="7018275672629230621">讀取及變更你的瀏覽記錄</translation>
<translation id="7019805045859631636">快</translation>
<translation id="7022562585984256452">首頁已設定完成。</translation>
-<translation id="702384510542929236">將部分系統資訊和網頁內容以匿名方式傳送給 Google。</translation>
<translation id="7025190659207909717">行動數據服務管理</translation>
<translation id="7027125358315426638">資料庫名稱:</translation>
<translation id="7029809446516969842">密碼</translation>
@@ -4147,6 +4156,7 @@
<translation id="7289225569524511578">開啟桌布應用程式</translation>
<translation id="7290242001003353852">這項登入服務 (由 <ph name="SAML_DOMAIN" /> 代管) 正在存取您的攝影機。</translation>
<translation id="7290594223351252791">確認註冊</translation>
+<translation id="7292696521213967957">Google 助理偵錯資訊</translation>
<translation id="7295662345261934369">與他人共用</translation>
<translation id="729583233778673644">允許執行 AES 和 RC4 加密。由於 RC4 加密不安全,使用這個加密選項會提高風險。</translation>
<translation id="7296774163727375165"><ph name="DOMAIN" /> 條款</translation>
@@ -4247,7 +4257,6 @@
<translation id="7456847797759667638">開啟位置...</translation>
<translation id="7461924472993315131">固定</translation>
<translation id="7463006580194749499">新增使用者</translation>
-<translation id="7464902436585505072">「Ok Google」語音模型</translation>
<translation id="7465778193084373987">Netscape 憑證撤銷網址</translation>
<translation id="7469894403370665791">自動連線至這個網路</translation>
<translation id="747114903913869239">錯誤:無法為擴充功能解碼</translation>
@@ -4275,6 +4284,7 @@
<translation id="7496511874649569424">「<ph name="LINUX_APP_NAME" />」和與這個應用程式相關聯的資料會從這個裝置上移除。</translation>
<translation id="7497215489070763236">伺服器 CA 憑證</translation>
<translation id="7497981768003291373">你最近並未擷取 WebRTC 文字記錄。</translation>
+<translation id="7502199377020483660">如要在所有裝置上使用這些卡片,請將卡片儲存在你的 Google 帳戶中</translation>
<translation id="7502658306369382406">IPv6 位址</translation>
<translation id="7503191893372251637">Netscape 憑證類型</translation>
<translation id="7503821294401948377">無法載入瀏覽器動作的圖示「<ph name="ICON" />」。</translation>
@@ -4371,6 +4381,7 @@
<translation id="7663719505383602579">接收端:<ph name="ARC_PROCESS_NAME" /></translation>
<translation id="7664620655576155379">不支援的藍牙裝置:「<ph name="DEVICE_NAME" />」。</translation>
<translation id="7665369617277396874">新增帳戶</translation>
+<translation id="7667248760110172428">外部儲存空間</translation>
<translation id="7671130400130574146">使用系統標題列及邊界</translation>
<translation id="7672520070349703697"><ph name="HUNG_IFRAME_URL" /> (在「<ph name="PAGE_TITLE" />」中)。</translation>
<translation id="7676867886086876795">將你的語音資料傳送給 Google,讓你在任何文字欄位中使用語音輸入功能。</translation>
@@ -4574,6 +4585,7 @@
<translation id="7930294771522048157">已儲存的付款方式會顯示在這裡</translation>
<translation id="79312157130859720"><ph name="APP_NAME" /> 正在共用您的畫面和音訊。</translation>
<translation id="7931318309563332511">不明</translation>
+<translation id="7932969338829957666">在 Linux 中,你可以前往 <ph name="BASE_DIR" /> 存取共用資料夾。</translation>
<translation id="7933314993013528982">{NUM_TABS,plural, =1{開啟網站音訊}other{開啟多個網站的音訊}}</translation>
<translation id="7934414805353235750"><ph name="URL" /> 要求播放受保護的內容。Google 會驗證你裝置的識別資訊。</translation>
<translation id="793531125873261495">下載虛擬機器時發生錯誤,請再試一次。</translation>
@@ -4665,6 +4677,7 @@
<translation id="8049705080247101012">Google 已將「<ph name="EXTENSION_NAME" />」標示為惡意擴充功能並禁止安裝</translation>
<translation id="8049913480579063185">擴充功能名稱</translation>
<translation id="8050038245906040378">Microsoft 商用程式碼簽署</translation>
+<translation id="8052887694493382350">這個檔案是專為使用 Windows 軟體的個人電腦所設計。你的裝置搭載的是 Chrome 作業系統,因此與這個檔案不相容。<ph name="BEGIN_LINK_HELP" />瞭解詳情<ph name="END_LINK_HELP" /></translation>
<translation id="8053278772142718589">PKCS #12 檔案</translation>
<translation id="8053390638574070785">重新載入此網頁</translation>
<translation id="8054517699425078995">這種類型的檔案可能會損害你的裝置,你要保留 <ph name="FILE_NAME" /> 嗎?</translation>
@@ -4907,6 +4920,7 @@
<translation id="8438566539970814960">改善搜尋和瀏覽體驗</translation>
<translation id="8439506636278576865">翻譯這個語言的網頁</translation>
<translation id="8440630305826533614">Linux 應用程式</translation>
+<translation id="8443338615972234259">請立即為你的受監管使用者建立新帳戶。</translation>
<translation id="8446884382197647889">瞭解詳情</translation>
<translation id="8447409163267621480">必須包含 Ctrl 或 Alt 鍵</translation>
<translation id="8448729345478502352">縮小或放大畫面上的項目</translation>
@@ -4931,6 +4945,7 @@
<translation id="8468750959626135884">使用 Android 手機解鎖您的 <ph name="DEVICE_TYPE" />。</translation>
<translation id="8470028084415844044">如要將密碼同步到所有裝置,請開啟同步處理功能。</translation>
<translation id="8470513973197838199">已儲存 <ph name="ORIGIN" /> 的密碼</translation>
+<translation id="8471635086304129332">如要在所有裝置上使用這張卡片,請將卡片儲存在你的 Google 帳戶中</translation>
<translation id="8472623782143987204">硬體支援</translation>
<translation id="8473863474539038330">地址和其他資訊</translation>
<translation id="8475313423285172237">電腦中其他程式所新增的擴充功能可能會變更 Chrome 的運作方式。</translation>
@@ -5006,7 +5021,6 @@
<translation id="8598453409908276158">已封鎖無沙箱防護的外掛程式</translation>
<translation id="8601206103050338563">TLS WWW 用戶端驗證</translation>
<translation id="8602851771975208551">電腦中其他程式所新增的應用程式可能會變更 Chrome 的運作方式。</translation>
-<translation id="8604763363205185560">協助改善 Chrome 及其安全性</translation>
<translation id="8605428685123651449">SQLite 記憶體使用量</translation>
<translation id="8606726445206553943">使用您的 MIDI 裝置</translation>
<translation id="8609465669617005112">上移</translation>
@@ -5182,6 +5196,7 @@
<translation id="8846141544112579928">正在搜尋鍵盤...</translation>
<translation id="8847988622838149491">USB</translation>
<translation id="8848561196844274665">當裝置連結時,即表示你同意讓 Chromebook 執行以下事項:</translation>
+<translation id="8850251000316748990">顯示更多...</translation>
<translation id="8859057652521303089">選擇語言:</translation>
<translation id="8859174528519900719">子頁框:<ph name="SUBFRAME_SITE" /></translation>
<translation id="8860454412039442620">Excel 試算表</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_am.xtb b/chromium/chrome/app/resources/google_chrome_strings_am.xtb
index 48832f5500f..4b7998bb13c 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_am.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_am.xtb
@@ -177,6 +177,7 @@ Google Chrome ቅንጅቶችዎን ማስመለስ አልቻለም።</translat
<translation id="556024056938947818">Google Chrome የይለፍ ቃላትን ለማሳየት እየሞከረ ነው።</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> አደገኛ ሊሆን ስለሚችል Chrome አግዶታል።</translation>
+<translation id="5686916850681061684">Google Chromeን ያብጁ እና ይቆጣጠሩ። የሆነ ነገር ትኩረትዎ ያስፈልገዋል - ለዝርዝሮች ጠቅ ያድርጉ።</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome በ1 ሰከንድ ውስጥ ዳግም ይጀምራል}one{Google Chrome በ​​# ሰከንዶች ውስጥ ዳግም ይጀምራል}other{Google Chrome በ​​# ሰከንዶች ውስጥ ዳግም ይጀምራል}}</translation>
<translation id="573759479754913123">ስለ Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS በዚህ ቋንቋ እየታየ ነው</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ar.xtb b/chromium/chrome/app/resources/google_chrome_strings_ar.xtb
index c8f2bafbb11..321d119d2f1 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ar.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ar.xtb
@@ -173,6 +173,7 @@
<translation id="556024056938947818">‏يحاول Google Chrome إظهار كلمات المرور.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">‏قد يكون ملف <ph name="FILE_NAME" /> ضارًا، لذلك فقد حظره Chrome.</translation>
+<translation id="5686916850681061684">‏تخصيص Google Chrome والتحكم فيه معلومات مهمة - انقر للحصول على التفاصيل.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{‏ستتم إعادة تشغيل Google Chrome خلال ثانية واحدة}zero{‏ستتم إعادة تشغيل Google Chrome خلال # ثانية}two{‏ستتم إعادة تشغيل Google Chrome خلال ثانيتين (#)}few{‏ستتم إعادة تشغيل Google Chrome خلال # ثوانٍ}many{‏ستتم إعادة تشغيل Google Chrome خلال # ثانيةً}other{‏ستتم إعادة تشغيل Google Chrome خلال # ثانية}}</translation>
<translation id="573759479754913123">‏حول نظام التشغيل Chrome</translation>
<translation id="5774845247549698882">‏يتم عرض نظام التشغيل Chrome بهذه اللغة</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_bg.xtb b/chromium/chrome/app/resources/google_chrome_strings_bg.xtb
index a4e0fc48be2..91b08a02f7f 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_bg.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_bg.xtb
@@ -171,6 +171,7 @@
<translation id="556024056938947818">Google Chrome опитва да покаже паролите.</translation>
<translation id="5566025111015594046">Google Chrome (входящ трафик за mDNS)</translation>
<translation id="565744775970812598">Chrome блокира „<ph name="FILE_NAME" />“, тъй като файлът може да е опасен.</translation>
+<translation id="5686916850681061684">Персонализиране и контролиране на Google Chrome. Трябва да обърнете внимание на нещо – кликнете за подробности.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome ще се рестартира след 1 секунда}other{Google Chrome ще се рестартира след # секунди}}</translation>
<translation id="573759479754913123">Всичко за Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS се показва на този език</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_bn.xtb b/chromium/chrome/app/resources/google_chrome_strings_bn.xtb
index 2b4ded5d7c5..d03d1da2530 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_bn.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_bn.xtb
@@ -173,6 +173,7 @@
<translation id="556024056938947818">Google Chrome পাসওয়ার্ডগুলি দেখানোর চেষ্টা করছে৷</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> বিপজ্জনক হতে পারে, তাই Chrome এটিকে অবরুদ্ধ করেছে।</translation>
+<translation id="5686916850681061684">Google Chrome কাস্টমাইজ ও নিয়ন্ত্রণ করুন। একটি বিষয়ে আপনার নজর দেওয়া দরকার - বিস্তারিত বিবরণের জন্য ক্লিক করুন।</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome ১ সেকেন্ডের মধ্যে রিস্টার্ট হবে}one{Google Chrome # সেকেন্ডের মধ্যে রিস্টার্ট হবে}other{Google Chrome # সেকেন্ডের মধ্যে রিস্টার্ট হবে}}</translation>
<translation id="573759479754913123">Chrome OS সম্পর্কে </translation>
<translation id="5774845247549698882">Chrome OS এই ভাষায় প্রদর্শিত হচ্ছে</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ca.xtb b/chromium/chrome/app/resources/google_chrome_strings_ca.xtb
index e79e1280c9a..bcae4be6f07 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ca.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ca.xtb
@@ -169,6 +169,7 @@ Per obtenir més instruccions, consulteu el correu electrònic a <ph name="ACCOU
<translation id="556024056938947818">Google Chrome està provant de mostrar les contrasenyes.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Chrome ha bloquejat <ph name="FILE_NAME" /> perquè pot ser perillós.</translation>
+<translation id="5686916850681061684">Personalitza i controla Google Chrome. Cal la teva intervenció. Fes clic per obtenir més informació.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome es reiniciarà d'aquí a 1 segon}other{Google Chrome es reiniciarà d'aquí a # segons}}</translation>
<translation id="573759479754913123">Sobre Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS es mostra en aquest idioma</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_cs.xtb b/chromium/chrome/app/resources/google_chrome_strings_cs.xtb
index 2c0830082b2..255abb5132f 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_cs.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_cs.xtb
@@ -177,6 +177,7 @@ Aplikace Google Chrome nemůže vaše nastavení obnovit.</translation>
<translation id="556024056938947818">Google Chrome se pokouší zobrazit hesla.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Soubor <ph name="FILE_NAME" /> může být nebezpečný, proto jej Chrome zablokoval.</translation>
+<translation id="5686916850681061684">Přizpůsobte si Google Chrome a ovládejte jej. Něco vyžaduje vaši pozornost – podrobnosti zobrazíte kliknutím.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome se za 1 sekundu restartuje}few{Google Chrome se za # sekundy restartuje}many{Google Chrome se za # sekundy restartuje}other{Google Chrome se za # sekund restartuje}}</translation>
<translation id="573759479754913123">O operačním systému Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS se zobrazuje v tomto jazyce</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_da.xtb b/chromium/chrome/app/resources/google_chrome_strings_da.xtb
index 929dec22976..274e13fb8ca 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_da.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_da.xtb
@@ -169,6 +169,7 @@ Gå til din mail på <ph name="ACCOUNT_EMAIL" /> for at få yderligere vejlednin
<translation id="556024056938947818">Google Chrome forsøger at vise adgangskoder.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> kan være skadelig, så Chrome har blokeret den.</translation>
+<translation id="5686916850681061684">Tilpas og administrer Google Chrome. Noget kræver din opmærksomhed – klik for at få oplysninger.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome genstarter om 1 sekund}one{Google Chrome genstarter om # sekund}other{Google Chrome genstarter om # sekunder}}</translation>
<translation id="573759479754913123">Om Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS vises på dette sprog</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_de.xtb b/chromium/chrome/app/resources/google_chrome_strings_de.xtb
index 26eeaef670f..4470677bd67 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_de.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_de.xtb
@@ -169,6 +169,7 @@ Weitere Informationen wurden per E-Mail an <ph name="ACCOUNT_EMAIL" /> gesendet.
<translation id="556024056938947818">Google Chrome versucht, Passwörter anzuzeigen.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> ist möglicherweise schädlich und wurde daher von Chrome blockiert.</translation>
+<translation id="5686916850681061684">Sie können Google Chrome anpassen und Einstellungen festlegen. Etwas erfordert Ihre Aufmerksamkeit – klicken Sie, um mehr zu erfahren.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome wird in 1 Sekunde neu gestartet}other{Google Chrome wird in # Sekunden neu gestartet}}</translation>
<translation id="573759479754913123">Über Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS wird in dieser Sprache angezeigt</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_el.xtb b/chromium/chrome/app/resources/google_chrome_strings_el.xtb
index 999573642a2..30e0ded9ff8 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_el.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_el.xtb
@@ -173,6 +173,7 @@
<translation id="556024056938947818">Το Google Chrome επιχειρεί να εμφανίσει κωδικούς πρόσβασης.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Το αρχείο <ph name="FILE_NAME" /> μπορεί να είναι επικίνδυνο, επομένως έχει αποκλειστεί από το Chrome.</translation>
+<translation id="5686916850681061684">Προσαρμογή και έλεγχος του Google Chrome. Θα πρέπει να ελέγξετε μια ειδοποίηση, κάντε κλικ για λεπτομέρειες.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Θα γίνει επανεκκίνηση του Google Chrome σε 1 δευτερόλεπτο}other{Θα γίνει επανεκκίνηση του Google Chrome σε # δευτερόλεπτα}}</translation>
<translation id="573759479754913123">Σχετικά με το Chrome OS</translation>
<translation id="5774845247549698882">Το Chrome OS εμφανίζεται σε αυτήν τη γλώσσα</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_en-GB.xtb b/chromium/chrome/app/resources/google_chrome_strings_en-GB.xtb
index 4789996fd35..e375cd96f2e 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_en-GB.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_en-GB.xtb
@@ -177,6 +177,7 @@ Google Chrome is unable to recover your settings.</translation>
<translation id="556024056938947818">Google Chrome is trying to show passwords.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> may be dangerous, so Chrome has blocked it.</translation>
+<translation id="5686916850681061684">Customise and control Google Chrome. Something needs your attention – click for details.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome will restart in 1 second}other{Google Chrome will restart in # seconds}}</translation>
<translation id="573759479754913123">About Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS is displayed in this language</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_es-419.xtb b/chromium/chrome/app/resources/google_chrome_strings_es-419.xtb
index c082c686383..803a963a670 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_es-419.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_es-419.xtb
@@ -169,6 +169,7 @@ Para obtener más instrucciones, revisa tu correo electrónico en <ph name="ACCO
<translation id="556024056938947818">Google Chrome está intentando mostrar contraseñas.</translation>
<translation id="5566025111015594046">Google Chrome (tráfico mDNS entrante)</translation>
<translation id="565744775970812598">Chrome bloqueó <ph name="FILE_NAME" /> porque es posible que sea un archivo peligroso.</translation>
+<translation id="5686916850681061684">Personaliza y controla Google Chrome. Una alerta necesita tu atención. Haz clic para ver los detalles.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome se reiniciará en 1 segundo}other{Google Chrome se reiniciará en # segundos}}</translation>
<translation id="573759479754913123">Acerca de Chrome OS</translation>
<translation id="5774845247549698882">El Sistema operativo Chrome se muestra en este idioma</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_es.xtb b/chromium/chrome/app/resources/google_chrome_strings_es.xtb
index 2a359305c5c..e46b8a8885c 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_es.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_es.xtb
@@ -177,6 +177,7 @@ Google Chrome no puede recuperar tu configuración.</translation>
<translation id="556024056938947818">Google Chrome está intentando mostrar contraseñas.</translation>
<translation id="5566025111015594046">Google Chrome (tráfico mDNS entrante)</translation>
<translation id="565744775970812598">Es posible que <ph name="FILE_NAME" /> sea peligroso, por lo que Chrome lo ha bloqueado.</translation>
+<translation id="5686916850681061684">Personaliza y controla Google Chrome. Se requiere tu intervención. Haz clic aquí para obtener más información.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome se reiniciará en 1 segundo}other{Google Chrome se reiniciará en # segundos}}</translation>
<translation id="573759479754913123">Información de Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS se muestra en este idioma</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_et.xtb b/chromium/chrome/app/resources/google_chrome_strings_et.xtb
index 45b64b69a10..d42e74cf906 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_et.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_et.xtb
@@ -173,6 +173,7 @@ Mõned funktsioonid ei pruugi saadaval olla. Määrake muu profiilikataloog või
<translation id="556024056938947818">Google Chrome püüab näidata paroole.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> võib olla ohtlik, mistõttu Chrome blokeeris selle.</translation>
+<translation id="5686916850681061684">Kohandage ja hallake Google Chrome'i. Miski vajab teie tähelepanu – klõpsake üksikasjade nägemiseks.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome taaskäivitub 1 sekundi pärast}other{Google Chrome taaskäivitub # sekundi pärast}}</translation>
<translation id="573759479754913123">Teave Chrome OS-i kohta</translation>
<translation id="5774845247549698882">Chrome OS kuvatakse selles keeles</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_fa.xtb b/chromium/chrome/app/resources/google_chrome_strings_fa.xtb
index 77f8eb7df6c..c22d6c7f092 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_fa.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_fa.xtb
@@ -170,6 +170,7 @@
<translation id="556024056938947818">‏Google Chrome می‌خواهد گذرواژه‌ها را نمایش دهد.</translation>
<translation id="5566025111015594046">‏Google Chrome (ورودی mDNS)</translation>
<translation id="565744775970812598">‏<ph name="FILE_NAME" /> ممکن است خطرناک باشد، بنابراین Chrome آن را مسدود کرده است.</translation>
+<translation id="5686916850681061684">‏Google Chrome ‫را سفارشی و کنترل کنید. چیزی نیاز به رسیدگی دارد، برای اطلاعات بیشتر کلیک کنید.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{‏Google Chrome بعد از ۱ ثانیه بازراه‌اندازی می‌شود}one{‏Google Chrome بعد از # ثانیه بازراه‌اندازی می‌شود}other{‏Google Chrome بعد از # ثانیه بازراه‌اندازی می‌شود}}</translation>
<translation id="573759479754913123">‏درباره سیستم عامل Chrome</translation>
<translation id="5774845247549698882">‏سیستم عامل Chrome به این زبان نشان داده می‌شود</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_fi.xtb b/chromium/chrome/app/resources/google_chrome_strings_fi.xtb
index 1f088ec64d9..67904d33941 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_fi.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_fi.xtb
@@ -170,6 +170,7 @@ Lähetimme lisäohjeita sähköpostiisi osoitteeseen <ph name="ACCOUNT_EMAIL" />
<translation id="556024056938947818">Google Chrome yrittää näyttää salasanoja.</translation>
<translation id="5566025111015594046">Google Chrome (saapuva mDNS)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> voi olla vaarallinen, joten Chrome on estänyt sen.</translation>
+<translation id="5686916850681061684">Yksilöi ja ylläpidä Google Chromea. Toimenpiteitä vaaditaan. Katso lisätiedot klikkaamalla.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome käynnistyy uudelleen 1 sekunnin kuluttua}other{Google Chrome käynnistyy uudelleen # sekunnin kuluttua}}</translation>
<translation id="573759479754913123">Tietoja Chrome-käyttöjärjestelmästä</translation>
<translation id="5774845247549698882">Chrome-käyttöjärjestelmä näytetään tällä kielellä.</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_fil.xtb b/chromium/chrome/app/resources/google_chrome_strings_fil.xtb
index 02032413412..4b3d1ed34a2 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_fil.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_fil.xtb
@@ -177,6 +177,7 @@ Hindi magawang bawiin ng Google Chrome ang iyong mga setting.</translation>
<translation id="556024056938947818">Sinusubukan ng Google Chrome na magpakita ng mga password.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Maaaring mapanganib ang <ph name="FILE_NAME" />, kaya na-block ito ng Chrome.</translation>
+<translation id="5686916850681061684">I-customize at kontrolin ang Google Chrome. May kailangan kang pagtuunan ng pansin - mag-click para sa mga detalye.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Magre-restart ang Google Chrome pagkalipas ng 1 segundo}one{Magre-restart ang Google Chrome pagkalipas ng # segundo}other{Magre-restart ang Google Chrome pagkalipas ng # na segundo}}</translation>
<translation id="573759479754913123">Tungkol sa Chrome OS</translation>
<translation id="5774845247549698882">Ipinapakita ang Chrome OS sa wikang ito</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_fr.xtb b/chromium/chrome/app/resources/google_chrome_strings_fr.xtb
index 67737226ca3..186be2803c4 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_fr.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_fr.xtb
@@ -177,6 +177,7 @@ Google Chrome ne peut pas récupérer vos paramètres.</translation>
<translation id="556024056938947818">Tentative d'affichage des mots de passe dans Google Chrome</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Chrome a bloqué <ph name="FILE_NAME" />, car ce fichier peut être dangereux.</translation>
+<translation id="5686916850681061684">Personnalisez et contrôlez Google Chrome. Une action de votre part est requise. Cliquez pour en savoir plus.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome va redémarrer dans 1 seconde}one{Google Chrome va redémarrer dans # seconde}other{Google Chrome va redémarrer dans # secondes}}</translation>
<translation id="573759479754913123">À propos de Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS est affiché dans cette langue</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_gu.xtb b/chromium/chrome/app/resources/google_chrome_strings_gu.xtb
index 7455e39a91a..2cc0a1139ab 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_gu.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_gu.xtb
@@ -177,6 +177,7 @@ Google Chrome તમારી સેટિંગ્સને પુનઃપ્
<translation id="556024056938947818">Google Chrome પાસવર્ડ્સ બતાવવાનો પ્રયાસ કરી રહ્યું છે.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> જોખમી હોઈ શકે છે, તેથી Chrome એ તેને અવરોધિત કરેલ છે.</translation>
+<translation id="5686916850681061684">Google Chromeને કસ્ટમાઇઝ કરો અને તેનું નિયંત્રણ કરો. તમારે ક્યાંક ધ્યાન આપવાની જરૂર છે - વિગતો માટે ક્લિક કરો.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome 1 સેકન્ડમાં ફરી શરૂ થશે}one{Google Chrome # સેકન્ડમાં ફરી શરૂ થશે}other{Google Chrome # સેકન્ડમાં ફરી શરૂ થશે}}</translation>
<translation id="573759479754913123">Chrome OS વિશે</translation>
<translation id="5774845247549698882">આ ભાષામાં Chrome OS પ્રદર્શિત થાય છે</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_hi.xtb b/chromium/chrome/app/resources/google_chrome_strings_hi.xtb
index be237162c63..e9e2772096e 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_hi.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_hi.xtb
@@ -173,6 +173,7 @@ Google Chrome आपकी सेटिंग बहाल नहीं कर
<translation id="556024056938947818">Google Chrome पासवर्ड दिखाने का प्रयास कर रहा है.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> खरतरनाक हो सकता है, इसलिए Chrome ने उसे अवरोधित कर दिया है.</translation>
+<translation id="5686916850681061684">Google Chrome को पसंद के मुताबिक बनाएं और नियंत्रित करें. कुछ है जिस पर आपको ध्यान देने की ज़रूरत है - विवरण के लिए क्लिक करें.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome 1 सेकंड में रीस्टार्ट होगा}one{Google Chrome # सेकंड में रीस्टार्ट होगा}other{Google Chrome # सेकंड में रीस्टार्ट होगा}}</translation>
<translation id="573759479754913123">Chrome OS के बारे में</translation>
<translation id="5774845247549698882">Chrome OS इस भाषा में प्रदर्शित किया जा रहा है</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_hr.xtb b/chromium/chrome/app/resources/google_chrome_strings_hr.xtb
index ed8e2ba4a08..a77d63031b6 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_hr.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_hr.xtb
@@ -169,6 +169,7 @@ Daljnje upute poslali smo vam na e-adresu <ph name="ACCOUNT_EMAIL" />.</translat
<translation id="556024056938947818">Google Chrome pokušava prikazati zaporke.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Datoteka <ph name="FILE_NAME" /> mogla bi biti opasna, pa ju je Chrome blokirao.</translation>
+<translation id="5686916850681061684">Prilagodite Google Chrome i upravljajte njime. Trebate obratiti pozornost na nešto – kliknite za pojedinosti.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome ponovo će se pokrenuti za 1 sekundu}one{Google Chrome ponovo će se pokrenuti za # sekundu}few{Google Chrome ponovo će se pokrenuti za # sekunde}other{Google Chrome ponovo će se pokrenuti za # sekundi}}</translation>
<translation id="573759479754913123">O OS-u Chrome</translation>
<translation id="5774845247549698882">OS Chrome prikazuje se na tom jeziku</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_hu.xtb b/chromium/chrome/app/resources/google_chrome_strings_hu.xtb
index 172f8264d4c..5f52a24151d 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_hu.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_hu.xtb
@@ -169,6 +169,7 @@ További utasításokat a(z) <ph name="ACCOUNT_EMAIL" /> címére küldött e-ma
<translation id="556024056938947818">A Google Chrome megpróbálja megjeleníteni a jelszavakat.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">A(z) <ph name="FILE_NAME" /> veszélyes lehet, ezért a Chrome letiltotta.</translation>
+<translation id="5686916850681061684">A Google Chrome személyre szabása és beállításai Figyelmet kell fordítania valamire – a részletekért kattintson.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{A Google Chrome 1 másodpercen belül újraindul}other{A Google Chrome # másodpercen belül újraindul}}</translation>
<translation id="573759479754913123">A Chrome OS névjegye</translation>
<translation id="5774845247549698882">A Chrome OS ezen a nyelven jelenik meg</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_id.xtb b/chromium/chrome/app/resources/google_chrome_strings_id.xtb
index c02958860b4..0651af68ba3 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_id.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_id.xtb
@@ -169,6 +169,7 @@ Periksa email Anda di <ph name="ACCOUNT_EMAIL" /> untuk petunjuk lebih lanjut.</
<translation id="556024056938947818">Google Chrome mencoba menampilkan sandi.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> mungkin berbahaya, sehingga Chrome memblokirnya.</translation>
+<translation id="5686916850681061684">Sesuaikan dan kontrol Google Chrome. Ada sesuatu yang memerlukan perhatian Anda - klik untuk melihat detailnya.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome akan dimulai ulang dalam 1 detik}other{Google Chrome akan dimulai ulang dalam # detik}}</translation>
<translation id="573759479754913123">Tentang Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS ditampilkan dalam bahasa ini</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_it.xtb b/chromium/chrome/app/resources/google_chrome_strings_it.xtb
index d22bad65e4e..5dc2678be66 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_it.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_it.xtb
@@ -170,6 +170,7 @@ Per ulteriori informazioni, controlla l'email all'indirizzo <ph name="ACCOUNT_EM
<translation id="556024056938947818">Google Chrome sta cercando di visualizzare le password.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> potrebbe essere pericoloso, pertanto è stato bloccato da Chrome.</translation>
+<translation id="5686916850681061684">Personalizza e controlla Google Chrome. C'è qualcosa che richiede la tua attenzione. Fai clic per avere informazioni dettagliate.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome si riavvierà tra 1 secondo}other{Google Chrome si riavvierà tra # secondi}}</translation>
<translation id="573759479754913123">Informazioni su Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS è visualizzato in questa lingua</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_iw.xtb b/chromium/chrome/app/resources/google_chrome_strings_iw.xtb
index 8959bdeca35..a9b53e966e1 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_iw.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_iw.xtb
@@ -169,6 +169,7 @@
<translation id="556024056938947818">‏Google Chrome מנסה להציג סיסמאות.</translation>
<translation id="5566025111015594046">‏Google Chrome‏ (mDNS-In)</translation>
<translation id="565744775970812598">‏<ph name="FILE_NAME" /> עלול להיות מסוכן, ולכן Chrome חסם אותו.</translation>
+<translation id="5686916850681061684">‏התאמה אישית וניהול של Google Chrome. נחוצה פעולה שלך - יש ללחוץ לקבלת פרטים נוספים.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{‏Google Chrome יבצע אתחול בעוד שנייה אחת}two{‏Google Chrome יבצע אתחול בעוד # שניות}many{‏Google Chrome יבצע אתחול בעוד # שניות}other{‏Google Chrome יבצע אתחול בעוד # שניות}}</translation>
<translation id="573759479754913123">‏מידע על מערכת ההפעלה של Chrome</translation>
<translation id="5774845247549698882">‏Chrome OS מוצג בשפה זו</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ja.xtb b/chromium/chrome/app/resources/google_chrome_strings_ja.xtb
index 3aaed985844..348c6613b93 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ja.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ja.xtb
@@ -169,6 +169,7 @@
<translation id="556024056938947818">Google Chrome はパスワードを表示しようとしています。</translation>
<translation id="5566025111015594046">Google Chrome(mDNS インバウンド)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> は危険なファイルの可能性があるため、Chrome でブロックしました。</translation>
+<translation id="5686916850681061684">Google Chrome をカスタマイズ、制御します。確認の必要な項目があります。クリックして詳細をご覧ください。</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome は 1 秒後に再起動します}other{Google Chrome は # 秒後に再起動します}}</translation>
<translation id="573759479754913123">Chrome OS について</translation>
<translation id="5774845247549698882">Chrome OS はこの言語で表示されています</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_kn.xtb b/chromium/chrome/app/resources/google_chrome_strings_kn.xtb
index 66ef450f5c3..f07f0d6b62a 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_kn.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_kn.xtb
@@ -171,6 +171,7 @@
<translation id="556024056938947818">Google Chrome ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ತೋರಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದೆ.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> ಅಪಾಯಕಾರಿಯಾಗಿರಬಹುದು, ಹಾಗಾಗಿ Chrome ಅದನ್ನು ನಿರ್ಬಂಧಿಸಿದೆ.</translation>
+<translation id="5686916850681061684">Google Chrome ಕಸ್ಟಮೈಸ್ ಮಾಡಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ. ನೀವು ಕೆಲವು ಸಂಗತಿಗಳ ಕುರಿತು ಗಮನಹರಿಸಬೇಕಿದೆ - ವಿವರಗಳಿಗಾಗಿ ಕ್ಲಿಕ್ ಮಾಡಿ.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome 1 ಸೆಕೆಂಡ್‌ನಲ್ಲಿ ಮರುಪ್ರಾರಂಭವಾಗುತ್ತದೆ}one{Google Chrome # ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮರುಪ್ರಾರಂಭವಾಗುತ್ತದೆ}other{Google Chrome # ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮರುಪ್ರಾರಂಭವಾಗುತ್ತದೆ}}</translation>
<translation id="573759479754913123">Chrome OS ಕುರಿತು</translation>
<translation id="5774845247549698882">ಈ ಭಾಷೆಯಲ್ಲಿ Chrome OS ಪ್ರದರ್ಶನಗೊಂಡಿದೆ</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ko.xtb b/chromium/chrome/app/resources/google_chrome_strings_ko.xtb
index 0664b85b933..65e528ee995 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ko.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ko.xtb
@@ -177,6 +177,7 @@ Chrome에서 설정을 복구할 수 없습니다.</translation>
<translation id="556024056938947818">Chrome에서 비밀번호를 표시하려고 합니다.</translation>
<translation id="5566025111015594046">Chrome(mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" />은(는) 위험할 수 있으므로 Chrome에서 차단했습니다.</translation>
+<translation id="5686916850681061684">Chrome을 맞춤설정 및 제어합니다. 확인이 필요한 항목이 있습니다. 클릭하여 세부정보를 보세요.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{1초 후에 Chrome이 다시 시작됩니다}other{#초 후에 Chrome이 다시 시작됩니다}}</translation>
<translation id="573759479754913123">Chrome OS 정보</translation>
<translation id="5774845247549698882">현재 Chrome OS에서 사용 중인 언어</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_lt.xtb b/chromium/chrome/app/resources/google_chrome_strings_lt.xtb
index 59d0e7ddfd0..dc48914d98f 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_lt.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_lt.xtb
@@ -178,6 +178,7 @@ Kai kurios funkcijos gali būti nepasiekiamos. Nurodykite kitą profilio katalog
<translation id="556024056938947818">„Google Chrome“ bando rodyti slaptažodžius.</translation>
<translation id="5566025111015594046">„Google Chrome“ (mDNS-In)</translation>
<translation id="565744775970812598">Failas „<ph name="FILE_NAME" />“ gali būti pavojingas, todėl „Chrome“ jį užblokavo.</translation>
+<translation id="5686916850681061684">Tinkinkite ir valdykite „Google Chrome“. Reikia atkreipti dėmesį – spustelėkite ir peržiūrėkite išsamią informaciją.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{„Google Chrome“ bus paleista iš naujo po 1 sekundės}one{„Google Chrome“ bus paleista iš naujo po # sekundės}few{„Google Chrome“ bus paleista iš naujo po # sekundžių}many{„Google Chrome“ bus paleista iš naujo po # sekundės}other{„Google Chrome“ bus paleista iš naujo po # sekundžių}}</translation>
<translation id="573759479754913123">Apie „Chrome“ OS</translation>
<translation id="5774845247549698882">„Chrome“ OS pateikiama šia kalba</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_lv.xtb b/chromium/chrome/app/resources/google_chrome_strings_lv.xtb
index 67514409357..ac6fa0599fb 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_lv.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_lv.xtb
@@ -173,6 +173,7 @@ Dažas funkcijas var nebūt pieejamas. Norādiet citu profila direktoriju vai li
<translation id="556024056938947818">Google Chrome mēģina rādīt paroles.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS ienākošā datplūsma)</translation>
<translation id="565744775970812598">Fails <ph name="FILE_NAME" /> var būt bīstams, tādēļ Chrome to bloķēja.</translation>
+<translation id="5686916850681061684">Pielāgojiet un kontrolējiet pārlūkprogrammu Google Chrome. Ir nepieciešama jūsu uzmanība. Noklikšķiniet, lai skatītu plašāku informāciju.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Pārlūks Google Chrome tiks restartēts pēc 1 sekundes.}zero{Pārlūks Google Chrome tiks restartēts pēc # sekundēm.}one{Pārlūks Google Chrome tiks restartēts pēc # sekundes.}other{Pārlūks Google Chrome tiks restartēts pēc # sekundēm.}}</translation>
<translation id="573759479754913123">Par &amp;Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS tiek rādīta šajā valodā.</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ml.xtb b/chromium/chrome/app/resources/google_chrome_strings_ml.xtb
index 3747aff9c8b..d82ce28af91 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ml.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ml.xtb
@@ -177,6 +177,7 @@
<translation id="556024056938947818">Google Chrome പാസ്‌വേഡുകൾ ദൃശ്യമാക്കാൻ ശ്രമിക്കുന്നു.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> അപകടകരമാകാൻ ഇടയുള്ളതിനാൽ, Chrome ഇതിനെ ബ്ലോക്കുചെയ്‌തു.</translation>
+<translation id="5686916850681061684">Google Chrome ഇഷ്‌ടാനുസൃതമാക്കുക, നിയന്ത്രിക്കുക. എന്തോ ഒന്നിന് നിങ്ങളുടെ ശ്രദ്ധ വേണം -വിശദാംശങ്ങൾക്ക് ക്ലിക്ക് ചെയ്യുക.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome ഒരു സെക്കൻഡിൽ പുനഃരാരംഭിക്കും}other{Google Chrome # സെക്കൻഡിൽ പുനഃരാരംഭിക്കും}}</translation>
<translation id="573759479754913123">Chrome OS-നെക്കുറിച്ച്</translation>
<translation id="5774845247549698882">Chrome OS ഈ ഭാഷയിൽ പ്രദർശിപ്പിച്ചിരിക്കുന്നു</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_mr.xtb b/chromium/chrome/app/resources/google_chrome_strings_mr.xtb
index 330e93af008..65693b5b596 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_mr.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_mr.xtb
@@ -174,6 +174,7 @@ Google Chrome तुमची सेटिंग्ज पुन्हा मि
<translation id="556024056938947818">Google Chrome पासवर्ड दर्शवण्याचा प्रयत्न करत आहे.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-मध्ये)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> धोकादायक असू शकते, त्यामुळे Chrom ने ते अवरोधित केले आहे.</translation>
+<translation id="5686916850681061684">Google Chrome कस्टमाइझ करा आणि नियंत्रित करा. एका गोष्टीवर तुम्ही लक्ष द्यायला हवे - तपशिलांसाठी क्लिक करा.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome १ सेकंदात रीस्टार्ट होईल}one{Google Chrome # सेकंदात रीस्टार्ट होईल}other{Google Chrome # सेकंदांत रीस्टार्ट होईल}}</translation>
<translation id="573759479754913123">Chrome OS बद्दल</translation>
<translation id="5774845247549698882">Chrome OS या भाषेत प्रदर्शित केली आहे</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ms.xtb b/chromium/chrome/app/resources/google_chrome_strings_ms.xtb
index 55d6308fd58..0edbf9a9c7c 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ms.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ms.xtb
@@ -169,6 +169,7 @@ Sila semak e-mel anda di <ph name="ACCOUNT_EMAIL" /> untuk arahan lanjut.</trans
<translation id="556024056938947818">Google Chrome sedang cuba memaparkan kata laluan.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> mungkin berbahaya, jadi Chrome telah menyekat fail itu.</translation>
+<translation id="5686916850681061684">Sesuaikan dan kawal Google Chrome. Perhatian anda diperlukan - klik untuk mendapatkan butiran.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome akan dimulakan semula dalam 1 saat}other{Google Chrome akan dimulakan semula dalam # saat}}</translation>
<translation id="573759479754913123">Mengenai Chrome OS</translation>
<translation id="5774845247549698882">OS Chrome dipaparkan dalam bahasa ini</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_nl.xtb b/chromium/chrome/app/resources/google_chrome_strings_nl.xtb
index 2cc7e8e3eaf..d72f301db23 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_nl.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_nl.xtb
@@ -175,6 +175,7 @@ Sommige functies zijn wellicht niet beschikbaar. Geef een andere profieldirector
<translation id="556024056938947818">Google Chrome probeert wachtwoorden weer te geven.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> kan gevaarlijk zijn en is daarom door Chrome geblokkeerd.</translation>
+<translation id="5686916850681061684">Pas Google Chrome aan en beheer de instellingen. Je aandacht is vereist. Klik voor meer informatie.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome wordt over één seconde opnieuw gestart}other{Google Chrome wordt over # seconden opnieuw gestart}}</translation>
<translation id="573759479754913123">Over Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS wordt weergegeven in deze taal</translation>
@@ -255,7 +256,7 @@ Sommige functies zijn wellicht niet beschikbaar. Geef een andere profieldirector
<translation id="8077352834923175128">Je beheerder vraagt je Chrome OS opnieuw op te starten om deze update toe te passen</translation>
<translation id="8129812357326543296">Over &amp;Google Chrome</translation>
<translation id="8179874765710681175">Installeer Chrome op je telefoon. We sturen een sms naar je telefoon.</translation>
-<translation id="8183957050892517584">Chrome slaat je persoonlijke gegevens beveiligd op, zodat je ze niet opnieuw hoeft op te geven.</translation>
+<translation id="8183957050892517584">Chrome slaat je persoonsgegevens beveiligd op, zodat je ze niet opnieuw hoeft op te geven.</translation>
<translation id="8226081633851087288">{0,plural, =0{Chrome OS wordt nu opnieuw opgestart}=1{Chrome OS wordt over één seconde opnieuw opgestart}other{Chrome OS wordt over # seconden opnieuw opgestart}}</translation>
<translation id="825412236959742607">Omdat deze pagina te veel geheugen gebruikt, heeft Chrome wat content verwijderd.</translation>
<translation id="8255190535488645436">Google Chrome gebruikt je camera en microfoon.</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_no.xtb b/chromium/chrome/app/resources/google_chrome_strings_no.xtb
index 32c9ae2b516..f74b1a2c52f 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_no.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_no.xtb
@@ -169,6 +169,7 @@ Vi har sendt deg (<ph name="ACCOUNT_EMAIL" />) en e-post med nærmere instruksjo
<translation id="556024056938947818">Google Chrome prøver å vise passord.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-Inn)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> kan være farlig, så Chrome har blokkert den.</translation>
+<translation id="5686916850681061684">Tilpass og kontrollér Google Chrome. Det er noe du må se på – klikk for mer informasjon.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome startes på nytt om 1 sekund}other{Google Chrome startes på nytt om # sekunder}}</translation>
<translation id="573759479754913123">Om Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS vises på dette språket</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_pl.xtb b/chromium/chrome/app/resources/google_chrome_strings_pl.xtb
index ef2ad7730e0..ff9a6f0c36f 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_pl.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_pl.xtb
@@ -170,6 +170,7 @@ Więcej instrukcji znajdziesz w e-mailu wysłanym na adres <ph name="ACCOUNT_EM
<translation id="556024056938947818">Google Chrome próbuje pokazać hasła.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Plik <ph name="FILE_NAME" /> może być niebezpieczny, dlatego został zablokowany przez Chrome.</translation>
+<translation id="5686916850681061684">Dostosuj i kontroluj Google Chrome. Pewna kwestia wymaga Twojej uwagi – kliknij, by przejść do szczegółów.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome uruchomi się ponownie za sekundę}few{Google Chrome uruchomi się ponownie za # sekundy}many{Google Chrome uruchomi się ponownie za # sekund}other{Google Chrome uruchomi się ponownie za # sekundy}}</translation>
<translation id="573759479754913123">System operacyjny Chrome – informacje</translation>
<translation id="5774845247549698882">System operacyjny Chrome działa obecnie w tym języku</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_pt-BR.xtb b/chromium/chrome/app/resources/google_chrome_strings_pt-BR.xtb
index 38ffd4d6929..e9c054c6788 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_pt-BR.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_pt-BR.xtb
@@ -170,6 +170,7 @@ Verifique seu e-mail em <ph name="ACCOUNT_EMAIL" /> para ver mais instruções.<
<translation id="556024056938947818">O Google Chrome está tentando mostrar senhas.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">O arquivo <ph name="FILE_NAME" /> pode ser perigoso. Por isso, ele foi bloqueado pelo Chrome.</translation>
+<translation id="5686916850681061684">Personalize e controle o Google Chrome. Algo precisa da sua atenção. Clique para ver mais detalhes.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{O Google Chrome será reiniciado em 1 segundo}one{O Google Chrome será reiniciado em # segundo}other{O Google Chrome será reiniciado em # segundos}}</translation>
<translation id="573759479754913123">Sobre o Chrome OS</translation>
<translation id="5774845247549698882">O Chrome OS é exibido neste idioma</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_pt-PT.xtb b/chromium/chrome/app/resources/google_chrome_strings_pt-PT.xtb
index 97ec1f4b31c..9dff1c0750b 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_pt-PT.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_pt-PT.xtb
@@ -169,6 +169,7 @@ Para obter mais instruções, verifique o seu email em <ph name="ACCOUNT_EMAIL"
<translation id="556024056938947818">O Google Chrome está a tentar mostrar palavras-passe.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> pode ser perigoso, por isso o Chrome bloqueou-o.</translation>
+<translation id="5686916850681061684">Personalize e controle o Google Chrome. É necessária a sua atenção – clique para obter detalhes.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{O Google Chrome será reiniciado dentro de 1 segundo}other{O Google Chrome será reiniciado dentro de # segundos}}</translation>
<translation id="573759479754913123">Acerca do Chrome OS</translation>
<translation id="5774845247549698882">O Chrome OS é apresentado neste idioma</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ro.xtb b/chromium/chrome/app/resources/google_chrome_strings_ro.xtb
index d1112e87abc..bf205d49ab8 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ro.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ro.xtb
@@ -169,6 +169,7 @@ Verifică e-mailul la <ph name="ACCOUNT_EMAIL" /> pentru instrucțiuni supliment
<translation id="556024056938947818">Google Chrome încearcă să afișeze parolele.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Este posibil ca <ph name="FILE_NAME" /> să fie periculos, așadar Chrome l-a blocat.</translation>
+<translation id="5686916850681061684">Personalizează și controlează Google Chrome. Ceva are nevoie de atenția ta – dă clic pentru detalii.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome va reporni într-o secundă}few{Google Chrome va reporni în # secunde}other{Google Chrome va reporni în # de secunde}}</translation>
<translation id="573759479754913123">Despre sistemul de operare Chrome</translation>
<translation id="5774845247549698882">Sistemul de operare Chrome este afișat în această limbă</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ru.xtb b/chromium/chrome/app/resources/google_chrome_strings_ru.xtb
index ce8916fb49f..fb76f10865c 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ru.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ru.xtb
@@ -169,6 +169,7 @@
<translation id="556024056938947818">Вводимые пароли будут отображаться в Google Chrome.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Chrome заблокировал файл <ph name="FILE_NAME" /> как потенциально опасный.</translation>
+<translation id="5686916850681061684">Настройка и управление Google Chrome Требуется ваше внимание. Нажмите, чтобы получить подробную информацию.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome перезапустится через 1 секунду}one{Google Chrome перезапустится через # секунду}few{Google Chrome перезапустится через # секунды}many{Google Chrome перезапустится через # секунд}other{Google Chrome перезапустится через # секунды}}</translation>
<translation id="573759479754913123">О Chrome OS</translation>
<translation id="5774845247549698882">Этот язык сейчас используется в Chrome OS</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_sk.xtb b/chromium/chrome/app/resources/google_chrome_strings_sk.xtb
index 7a5cd86a065..d2559ba94ed 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_sk.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_sk.xtb
@@ -175,6 +175,7 @@ Prehliadač Google Chrome nedokáže obnoviť vaše nastavenia.</translation>
<translation id="556024056938947818">Prehliadač Google Chrome sa snaží zobraziť heslá.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Súbor <ph name="FILE_NAME" /> môže byť nebezpečný, a preto ho Chrome zablokoval.</translation>
+<translation id="5686916850681061684">Prispôsobte a ovládajte Google Chrome. Vyžaduje sa vaša pozornosť. Podrobnosti získate kliknutím.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome sa reštartuje o 1 sekundu}few{Google Chrome sa reštartuje o # sekundy}many{Google Chrome sa reštartuje o # sekundy}other{Google Chrome sa reštartuje o # sekúnd}}</translation>
<translation id="573759479754913123">Informácie o systéme Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS sa zobrazuje v tomto jazyku</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_sl.xtb b/chromium/chrome/app/resources/google_chrome_strings_sl.xtb
index a78e39807ba..6b62231ef50 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_sl.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_sl.xtb
@@ -177,6 +177,7 @@ Google Chrome ne more obnoviti vaših nastavitev.</translation>
<translation id="556024056938947818">Google Chrome poskuša prikazati gesla.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Datoteka <ph name="FILE_NAME" /> je morda nevarna, zato jo je Chrome blokiral.</translation>
+<translation id="5686916850681061684">Prilagajanje in nadziranje Google Chroma. Nekaj morate preveriti – kliknite za podrobnosti.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome se bo znova zagnal čez 1 sekundo}one{Google Chrome se bo znova zagnal čez # sekundo}two{Google Chrome se bo znova zagnal čez # sekundi}few{Google Chrome se bo znova zagnal čez # sekunde}other{Google Chrome se bo znova zagnal čez # sekund}}</translation>
<translation id="573759479754913123">O sistemu Chrome OS</translation>
<translation id="5774845247549698882">OS Chrome je v tem jeziku</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_sr.xtb b/chromium/chrome/app/resources/google_chrome_strings_sr.xtb
index dc54260a6fd..89f1c05b1f1 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_sr.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_sr.xtb
@@ -177,6 +177,7 @@ Google Chrome не може да врати подешавања.</translation>
<translation id="556024056938947818">Google Chrome покушава да прикаже лозинке.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Датотека <ph name="FILE_NAME" /> је можда опасна, па ју је Chrome блокирао.</translation>
+<translation id="5686916850681061684">Прилагодите и контролишите Google Chrome. Треба да обратите пажњу на нешто – кликните за више детаља.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome ће се рестартовати за 1 секунду}one{Google Chrome ће се рестартовати за # секунду}few{Google Chrome ће се рестартовати за # секунде}other{Google Chrome ће се рестартовати за # секунди}}</translation>
<translation id="573759479754913123">О Chrome ОС-у</translation>
<translation id="5774845247549698882">Chrome ОС се приказује на овом језику</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_sv.xtb b/chromium/chrome/app/resources/google_chrome_strings_sv.xtb
index 52222798e45..a6213ca7371 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_sv.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_sv.xtb
@@ -177,6 +177,7 @@ Google Chrome kan inte återställa dina inställningar.</translation>
<translation id="556024056938947818">Google Chrome försöker visa lösenord.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> kan vara skadlig och har blockerats av Chrome.</translation>
+<translation id="5686916850681061684">Anpassa och styr Google Chrome. Någonting behöver ses över. Klicka här för mer information.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome startas om om en sekund}other{Google Chrome startas om om # sekunder}}</translation>
<translation id="573759479754913123">Om Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS visas på det här språket</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_sw.xtb b/chromium/chrome/app/resources/google_chrome_strings_sw.xtb
index 7a3cfbf45fc..bcdc593ec40 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_sw.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_sw.xtb
@@ -177,6 +177,7 @@ Google Chrome haiwezi kufufua mipangilio yako.</translation>
<translation id="556024056938947818">Google Chrome inajaribu kuonyesha manenosiri.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Huenda <ph name="FILE_NAME" /> ni hatari, kwa hivyo Chromium imeizuia.</translation>
+<translation id="5686916850681061684">Dhibiti na uweke mapendeleo kwenye Google Chrome. Unahitaji kushughulikia jambo fulani. Bofya ili upate maelezo.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome itazimika na kuwaka tena baada ya sekunde 1}other{Google Chrome itazimika na kuwaka tena baada ya sekunde #}}</translation>
<translation id="573759479754913123">Kuhusu Chrome OS</translation>
<translation id="5774845247549698882">Mfumo wa Uendeshaji wa Chrome unaonyeshwa katika lugha hii</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_ta.xtb b/chromium/chrome/app/resources/google_chrome_strings_ta.xtb
index d27fbdd7b0a..bb8ba50f960 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_ta.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_ta.xtb
@@ -81,7 +81,7 @@
<translation id="2871893339301912279">Chrome இல் உள்நுழைந்துள்ளீர்கள்!</translation>
<translation id="2888126860611144412">Chrome அறிமுகம்</translation>
<translation id="3037838751736561277">Google Chrome பின்புலப் பயன்முறையில் இயங்குகிறது.</translation>
-<translation id="3047079729301751317"><ph name="USERNAME" /> ஐத் துண்டிப்பது, இந்தச் சாதனத்தில் உள்ள உங்கள் வரலாறு, புத்தகக்குறிகள், அமைப்புகள் மற்றும் பிற Chrome தரவை அழிக்கும். உங்கள் Google கணக்கில் சேமிக்கப்பட்ட தரவு அழிக்கப்படாது, மேலும் <ph name="GOOGLE_DASHBOARD_LINK" />Google டாஷ்போர்டில்<ph name="END_GOOGLE_DASHBOARD_LINK" /> நிர்வகிக்கலாம்.</translation>
+<translation id="3047079729301751317"><ph name="USERNAME" /> ஐத் துண்டிப்பது, இந்தச் சாதனத்தில் உள்ள உங்கள் வரலாறு, புக்மார்க்குகள், அமைப்புகள் மற்றும் பிற Chrome தரவை அழிக்கும். உங்கள் Google கணக்கில் சேமிக்கப்பட்ட தரவு அழிக்கப்படாது, மேலும் <ph name="GOOGLE_DASHBOARD_LINK" />Google டாஷ்போர்டில்<ph name="END_GOOGLE_DASHBOARD_LINK" /> நிர்வகிக்கலாம்.</translation>
<translation id="3065168410429928842">Chrome தாவல்</translation>
<translation id="3080151273017101988">Google Chrome மூடப்பட்டிருக்கும்போது பின்புல பயன்பாடுகளை இயக்க அனுமதி</translation>
<translation id="3089968997497233615">புதிய, இன்னும் பாதுகாப்பான Google Chrome பதிப்பு தற்போது கிடைக்கிறது.</translation>
@@ -169,6 +169,7 @@
<translation id="556024056938947818">Google Chrome ஆனது கடவுச்சொற்களைக் காட்ட முயற்சிக்கிறது.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> ஆபத்தானதாக இருக்கலாம் என்பதால் Chrome அதைத் தடுத்துள்ளது.</translation>
+<translation id="5686916850681061684">Google Chromeமைத் தேவைக்கேற்ப மாற்றி கட்டுப்படுத்தும். சிலவற்றை நீங்கள் கவனிக்க வேண்டும் - விவரங்களுக்கு, கிளிக் செய்யவும்.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome 1 வினாடியில் மீண்டும் தொடங்கும்}other{Google Chrome # வினாடிகளில் மீண்டும் தொடங்கும்}}</translation>
<translation id="573759479754913123">Chrome OS அறிமுகம்</translation>
<translation id="5774845247549698882">Chrome OS இந்த மொழியில் காட்டப்படுகிறது</translation>
@@ -177,7 +178,7 @@
<translation id="5877064549588274448">சேனல் மாற்றப்பட்டது. மாற்றங்களைச் செயல்படுத்த உங்கள் சாதனத்தை மீண்டும் தொடங்கவும்.</translation>
<translation id="5895138241574237353">மறுதொடக்கம்</translation>
<translation id="5906655207909574370">கிட்டத்தட்ட புதுப்பிக்கப்பட்டது! புதுப்பிப்பதை முடிக்க, சாதனத்தை மறுதொடக்கம் செய்யவும்.</translation>
-<translation id="5940385492829620908">உங்களின் இணையம், புத்தகக்குறிகள் மற்றும் பிற Chrome உருப்படிகள் இங்கே உள்ளன.</translation>
+<translation id="5940385492829620908">உங்களின் இணையம், புக்மார்க்குகள் மற்றும் பிற Chrome உருப்படிகள் இங்கே உள்ளன.</translation>
<translation id="5941830788786076944">Google Chrome ஐ இயல்புநிலை உலாவியாக அமை</translation>
<translation id="6014844626092547096">தற்போது Chrome இல் உள்நுழைந்துள்ளீர்கள்! உங்கள் நிர்வாகியால் ஒத்திசைவு முடக்கப்பட்டுள்ளது.</translation>
<translation id="6040143037577758943">மூடு</translation>
@@ -267,7 +268,7 @@
<translation id="8540666473246803645">Google Chrome</translation>
<translation id="8547799825197623713">Chrome பயன்பாட்டுத் துவக்கி Canary</translation>
<translation id="8556340503434111824">Google Chrome இன் புதிய பதிப்பு கிடைக்கிறது, அது முன்னெப்போதையும் விட விரைவானது.</translation>
-<translation id="8568392309447938879">பயன்பாடுகளைப் பயன்படுத்துவதற்கு நீங்கள் Chrome இல் உள்நுழைந்திருக்க வேண்டும். இது எல்லா சாதனங்களிலும் உங்கள் பயன்பாடுகள், புத்தகக்குறிகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் ஆகியவற்றை ஒத்திசைக்க Chrome ஐ அனுமதிக்கிறது.</translation>
+<translation id="8568392309447938879">பயன்பாடுகளைப் பயன்படுத்துவதற்கு நீங்கள் Chrome இல் உள்நுழைந்திருக்க வேண்டும். இது எல்லா சாதனங்களிலும் உங்கள் பயன்பாடுகள், புக்மார்க்குகள், வரலாறு, கடவுச்சொற்கள் மற்றும் பிற அமைப்புகள் ஆகியவற்றை ஒத்திசைக்க Chrome ஐ அனுமதிக்கிறது.</translation>
<translation id="8606668294522778825">உங்கள் உலாவல் அனுபவத்தை மேம்படுத்த இணைய சேவைகளை Google Chrome பயன்படுத்தலாம். விருப்பத்திற்கேற்ப இந்தச் சேவைகளை நீங்கள் முடக்கலாம். <ph name="BEGIN_LINK" />மேலும் அறிக<ph name="END_LINK" /></translation>
<translation id="8614913330719544658">Google Chrome பதிலளிக்கவில்லை. இப்போது மீண்டும் தொடங்கவா?</translation>
<translation id="8667808506758191620">உங்கள் <ph name="DEVICE_TYPE" /> புதுப்பித்த நிலையில் உள்ளது.</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_te.xtb b/chromium/chrome/app/resources/google_chrome_strings_te.xtb
index 97a4c6c47c2..477d43ac482 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_te.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_te.xtb
@@ -1,22 +1,22 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="te">
-<translation id="1001534784610492198">ఇన్‌స్టాలర్ ఆర్కైవ్ పాడైంది లేదా చెల్లదు. దయచేసి Google Chromeను మళ్లీ డౌన్‌లోడ్ చేయ‌ండి.</translation>
-<translation id="102763973188675173">Google Chromeని అనుకూలీకరించండి మరియు నియంత్రించండి. అప్‌డేట్ అందుబాటులో ఉంది.</translation>
+<translation id="1001534784610492198">ఇన్‌స్టాలర్ ఆర్కైవ్ పాడైంది లేదా చెల్లదు. దయచేసి Google Chromeను మ‌ళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
+<translation id="102763973188675173">Google Chromeను అనుకూలీకరించండి మరియు నియంత్రించండి. అప్‌డేట్ అందుబాటులో ఉంది.</translation>
<translation id="1035334672863811645">Chromeకు సైన్ ఇన్ చేయండి</translation>
<translation id="1051826050538111504">మీ కంప్యూటర్‌లో మీ భద్రతకు హాని కలిగించే సాఫ్ట్‌వేర్‌ ఉంది. మీ బ్రౌజర్‌ని మళ్లీ సాధారణంగా పని చేసేలా చేయడానికి Chrome దానిని తీసివేసి, మీ సెట్టింగ్‌లను పునరుద్ధరించి, ఎక్స్‌టెన్షన్‌లను నిలిపివేయగలదు.</translation>
<translation id="1065672644894730302">మీ ప్రాధాన్యతలు చదవబడలేవు. కొన్ని లక్షణాలు అందుబాటులో ఉండకపోవచ్చు మరియు ప్రాధాన్యతలకు మార్పులు సేవ్ చేయబడకపోవచ్చు.</translation>
<translation id="1088300314857992706"><ph name="USER_EMAIL_ADDRESS" /> మునుపు Chromeని ఉపయోగించింది</translation>
<translation id="1104959162601287462">&amp;Chrome OS గురించి</translation>
<translation id="110877069173485804">ఇది మీ Chrome</translation>
-<translation id="1142745911746664600">Chromeని అప్‌డేట్ చేయడం సాధ్యం కాదు</translation>
+<translation id="1142745911746664600">Chromeను అప్‌డేట్ చేయడం సాధ్యం కాదు</translation>
<translation id="1154147086299354128">&amp;Chromeలో తెరువు</translation>
-<translation id="123620459398936149">Chrome OS మీ డేటాను సింక్ చేయలేకపోయింది. దయచేసి మీ సింక్ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
-<translation id="127345590676626841">Chrome స్వయంచాలకంగా నవీకరించబడుతుంది కనుక మీరు ఎల్లప్పుడూ తాజా సంస్కరణని కలిగి ఉంటారు. ఈ డౌన్‌లోడ్ పూర్తయినప్పుడు, Chrome పునఃప్రారంభించబడుతుంది మరియు మీరు మీ పనిని కొనసాగించవచ్చు.</translation>
+<translation id="123620459398936149">Chrome OS మీ డేటాను సింక్ చేయ‌లేక‌పోయింది. దయచేసి మీ సింక్‌ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
+<translation id="127345590676626841">Chrome ఆటోమేటిక్‌గా అప్‌డేట్ చేయబడుతుంది కాబట్టి మీరు ఎప్పుడూ తాజా వెర్షన్‌ను కలిగి ఉంటారు. ఈ డౌన్‌లోడ్ పూర్తయినప్పుడు, Chrome పునఃప్రారంభించబడుతుంది, మీరు మీ పనిని కొనసాగించవచ్చు.</translation>
<translation id="1302523850133262269">దయచేసి Chrome తాజా సిస్టమ్ నవీకరణలను ఇన్‌స్టాల్ చేస్తున్నప్పుడు వేచి ఉండండి.</translation>
<translation id="1312676208694947750">{0,plural, =0{Chrome OS అప్‌డేట్ అందుబాటులో ఉంది}=1{Chrome OS అప్‌డేట్ అందుబాటులో ఉంది}other{# రోజులుగా Chrome OS అప్‌డేట్ అందుబాటులో ఉంది}}</translation>
<translation id="137466361146087520">Google Chrome బీటా</translation>
-<translation id="1393853151966637042">Chromeని ఉపయోగించి సహాయాన్ని పొందండి</translation>
+<translation id="1393853151966637042">Chromeను ఉపయోగించడం గురించి సహాయాన్ని పొందండి</translation>
<translation id="1399397803214730675">ఈ కంప్యూటర్‌లో ఇప్పటికే Google Chrome యొక్క తాజా వెర్షన్ ఉంది. సాఫ్ట్‌వేర్ పని చేయకపోతే, దయచేసి Google Chromeను అన్‌ఇన్‌స్టాల్ చేసి, మళ్ళీ ప్రయత్నించండి.</translation>
<translation id="1434626383986940139">Chrome కెనరీ అనువర్తనాలు</translation>
<translation id="1457721931618994305">Google Chromeని నవీకరిస్తోంది...</translation>
@@ -26,16 +26,16 @@
<translation id="1587223624401073077">Google Chrome మీ కెమెరాను ఉపయోగిస్తోంది.</translation>
<translation id="1587325591171447154"><ph name="FILE_NAME" /> హానికరం, కావున Chrome దాన్ని బ్లాక్ చేసింది.</translation>
<translation id="1619887657840448962">Chromeని సురక్షితం చేయడానికి, మేము క్రింది పొడిగింపుని నిలిపివేసాము, ఇది <ph name="IDS_EXTENSION_WEB_STORE_TITLE" />లో జాబితా చేయబడలేదు మరియు మీకు తెలియకుండా జోడించబడి ఉండవచ్చు.</translation>
-<translation id="1628000112320670027">Chromeతో సహాయం పొందండి</translation>
+<translation id="1628000112320670027">Chrome గురించి సహాయం పొందండి</translation>
<translation id="1662639173275167396"><ph name="BEGIN_LINK_LINUX_OSS" /> Linux (బీటా) <ph name="END_LINK_LINUX_OSS" /> లాగానే, Chrome OS కూడా అదనపు <ph name="BEGIN_LINK_CROS_OSS" /> ఓపెన్ సోర్స్ సాఫ్ట్‌వేర్‌ <ph name="END_LINK_CROS_OSS" />పై ఎంతగానో ఆధారపడుతుంది.</translation>
-<translation id="1674870198290878346">Chrome అజ్ఞా&amp;త విండోలో లింక్‌ని తెరువు</translation>
-<translation id="1682634494516646069">Google Chrome దీని డేటా డైరెక్టరీని చదవలేదు మరియు దీనిలో వ్రాయలేదు: <ph name="USER_DATA_DIRECTORY" /></translation>
-<translation id="1698376642261615901">Google Chrome అనేది మెరుపు వేగంతో వెబ్‌పేజీలను మరియు యాప్‌లను అమలు చేసే వెబ్ బ్రౌజర్. ఇది వేగమైనది, స్థిరమైనది మరియు ఉపయోగించడానికి సులభమైంది. Google Chromeలో నిర్మితమైన మాల్వేర్ మరియు ఫిషింగ్ భద్రతతో మరింత సురక్షితంగా వెబ్‌ను బ్రౌజ్ చేయండి.</translation>
+<translation id="1674870198290878346">Chrome అజ్ఞా&amp;త విండోలో లింక్‌ను తెరువు</translation>
+<translation id="1682634494516646069">Google Chrome దీని డేటా డైరెక్టరీని చదవలేదు మరియు దీనిలో రాయ‌లేదు: <ph name="USER_DATA_DIRECTORY" /></translation>
+<translation id="1698376642261615901">Google Chrome అనేది మెరుపు వేగంతో వెబ్‌పేజీలను, యాప్‌ల‌ను అమలు చేసే వెబ్ బ్రౌజర్. ఇది వేగమైనది, సామర్థ్యం కలది మరియు ఉపయోగించడానికి సులభమైంది. Google Chromeలో నిర్మితమైన మాల్‌వేర్‌ మరియు ఫిషింగ్ భద్రతతో మరింత సురక్షితంగా వెబ్‌ను బ్రౌజ్ చేయండి.</translation>
<translation id="1718131156967340976"><ph name="SMALL_PRODUCT_LOGO" /> <ph name="BEGIN_BOLD" />Google Chrome<ph name="END_BOLD" />ని ఎంచుకోండి</translation>
<translation id="1734234790201236882">Chrome ఈ పాస్‌వర్డ్‌ను మీ Google ఖాతాలో సేవ్ చేస్తుంది. మీరు దీనిని గుర్తుంచుకోవాల్సిన అవసరం లేదు.</translation>
<translation id="174539241580958092">సైన్ ఇన్ చేయడంలో ఎర్రర్ ఏర్పడినందున Google Chrome మీ డేటాను సింక్ చేయలేకపోయింది.</translation>
<translation id="1759842336958782510">Chrome</translation>
-<translation id="1773601347087397504">Chrome OSని ఉపయోగించి సహాయాన్ని పొందండి</translation>
+<translation id="1773601347087397504">Chrome OSను ఉపయోగించడం గురించి సహాయాన్ని పొందండి</translation>
<translation id="1795405610103747296">మీ ఫోన్‌లో Chromeను ఇన్‌స్టాల్ చేయండి. మేము మీ ఫోన్ నంబర్‌కు SMS పంపుతాము: <ph name="PHONE_NUMBER" /></translation>
<translation id="1812689907177901597">దీనిని ఆఫ్ చేయడం ద్వారా, మీరు Chromeకి సైన్ ఇన్ చేయకుండానే Gmail లాంటి Google సైట్‌లలో సైన్ ఇన్ చేయగలరు</translation>
<translation id="1860536484129686729">ఈ సైట్ కోసం మీ కెమెరాని ఉపయోగించడానికి Chromeకి అనుమతి అవసరం</translation>
@@ -44,34 +44,34 @@
<translation id="1877026089748256423">Chrome కాలం చెల్లినది</translation>
<translation id="1915828456209461693">Chrome కోసం కొత్త అప్‌డేట్ అందుబాటులో ఉంది మరియు మీరు పునఃప్రారంభించిన వెంటనే వర్తించబడుతుంది.</translation>
<translation id="1919130412786645364">Chrome సైన్-ఇన్‌ని అనుమతించండి</translation>
-<translation id="2063848847527508675">అప్‌డేట్‌ను వర్తింపజేయడానికి Chrome OSని పునఃప్రారంభించాలి.</translation>
+<translation id="2063848847527508675">అప్‌డేట్‌ను వర్తింపజేయడానికి Chrome OSను పునఃప్రారంభించాలి.</translation>
<translation id="2094919256425865063">ఏదేమైనా Chromeని మూసివేయాలా?</translation>
-<translation id="2120620239521071941">ఇది ఈ పరికరం నుండి <ph name="ITEMS_COUNT" /> అంశాలను తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromeకి <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
+<translation id="2120620239521071941">ఇది ఈ పరికరం నుండి <ph name="ITEMS_COUNT" /> అంశాలను తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromeకు <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
<translation id="2123055963409958220"><ph name="BEGIN_LINK" />ప్రస్తుత సెట్టింగ్‌లను<ph name="END_LINK" /> నివేదించడం ద్వారా Chromeను మెరుగుపరచడంలో సహాయపడండి</translation>
<translation id="216054706567564023">మీ ఫోన్‌లో Chromeను ఇన్‌స్టాల్ చేయండి. మేము మీ ఖాతా పునరుద్ధరణ ఫోన్ నంబర్‌కు SMS పంపుతాము.</translation>
-<translation id="2246246234298806438">అంతర్గత PDF వ్యూయర్ లేనప్పుడు Google Chrome ముద్రణ ప్రివ్యూను చూపించడం వీలుకాదు.</translation>
+<translation id="2246246234298806438">అంతర్గత PDF వ్యూవర్ లేనప్పుడు Google Chrome ముద్రణ ప్రివ్యూను చూపించదు.</translation>
<translation id="2252923619938421629">ప్రస్తుత సెట్టింగ్‌లను నివేదించడం ద్వారా Google Chromeను మెరుగుపరచడంలో సహాయపడండి</translation>
<translation id="225363235161345695">{0,plural, =1{ఒక గంటలో Chrome తిరిగి ప్రారంభించబడుతుంది}other{# గంటల్లో Chrome తిరిగి ప్రారంభించబడుతుంది}}</translation>
<translation id="2286950485307333924">మీరు ఇప్పుడు Chromeకి సైన్ ఇన్ చేసారు</translation>
<translation id="2290014774651636340">Google API కీలు లేవు. Google Chrome కార్యాచరణలో కొంత భాగం నిలిపివేయబడుతుంది.</translation>
<translation id="2290095356545025170">మీరు Google Chromeను ఖచ్చితంగా అన్‌ఇన్‌స్టాల్ చేయాలని అనుకుంటున్నారా?</translation>
-<translation id="2309047409763057870">ఇది Google Chrome యొక్క రెండవ ఇన‌స్ట‌లేష‌న్‌. దీన్ని మీ డిఫాల్ట్ బ్రౌజర్‌గా చేయడం సాధ్యపడదు.</translation>
+<translation id="2309047409763057870">ఇది Google Chrome యొక్క రెండవ ఇన‌స్ట‌లేష‌న్. దీన్ని మీ డిఫాల్ట్ బ్రౌజర్‌గా చేయడం సాధ్యపడదు.</translation>
<translation id="2334084861041072223">కాపీరైట్ <ph name="YEAR" /> Google Inc. అన్ని హ‌క్కులు రిజ‌ర్వ్ చేయ‌బ‌డ్డాయి.</translation>
<translation id="2346876346033403680">ఒకరు ఈ కంప్యూటర్‌లో మునుపు <ph name="ACCOUNT_EMAIL_LAST" />గా Chromeకు సైన్ ఇన్ చేశారు. అది మీ ఖాతా కాకుంటే, మీ సమాచారాన్ని వేరుగా ఉంచడానికి కొత్త Chrome వినియోగదారును సృష్టించండి.
ఏది ఏమైనా సైన్ ఇన్ చేస్తే బుక్‌మార్క్‌లు, చరిత్ర, ఇతర సెట్టింగ్‌ల వంటి Chrome సమాచారం <ph name="ACCOUNT_EMAIL_NEW" />కు విలీనం చేయబడుతుంది.</translation>
<translation id="2348335408836342058">ఈ సైట్ కోసం మీ కెమెరా మరియు మైక్రోఫోన్‌ను యాక్సెస్ చేయడానికి Chromeకు అనుమతి అవసరం</translation>
-<translation id="2429317896000329049">మీ డొమైన్ కోసం సమకాలీకరణ అందుబాటులో లేనందున Google Chrome మీ డేటాను సమకాలీకరించలేకపోయింది.</translation>
+<translation id="2429317896000329049">మీ డొమైన్ కోసం సింక్‌ అందుబాటులో లేనందున Google Chrome మీ డేటాను సింక్ చేయ‌లేక‌పోయింది.</translation>
<translation id="2467438592969358367">Google Chrome మీ పాస్‌వర్డ్‌లను ఎగుమతి చేయాలనుకుంటోంది. దీనిని అనుమతించడం కోసం మీ Windows పాస్‌వర్డ్‌ని టైప్ చేయండి.</translation>
<translation id="2485422356828889247">అన్ఇన్‌స్టాల్ చేయి</translation>
<translation id="2534507159460261402">Google Pay (Chromeకి కాపీ చేయబడింది)</translation>
-<translation id="2535429035253759792">ఈ అప్‌డేట్‌ని వర్తింపజేయడం కోసం మీరు Chromeని పునఃప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
-<translation id="2580411288591421699">ప్రస్తుతం అమలవుతున్న Google Chrome వెర్ష‌న్‌ను ఇన్‌స్టాల్ చేయ‌లేదు. దయచేసి Google Chromeను మూసివేసి, మళ్లీ ప్రయత్నించండి.</translation>
-<translation id="2586406160782125153">ఇది ఈ పరికరం నుండి మీ బ్రౌజింగ్ డేటాను తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromeకి <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
+<translation id="2535429035253759792">ఈ అప్‌డేట్‌ను వర్తింపజేయడం కోసం మీరు Chromeను పునఃప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
+<translation id="2580411288591421699">ప్రస్తుతం అమలవుతున్న Google Chrome వెర్షన్‌నే ఇన్‌స్టాల్ చేయడం సాధ్యపడదు. దయచేసి Google Chromeను మూసివేసి, మళ్ళీ ప్రయత్నించండి.</translation>
+<translation id="2586406160782125153">ఇది ఈ పరికరం నుండి మీ బ్రౌజింగ్ డేటాను తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromeకు <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
<translation id="2588322182880276190">Chrome లోగో</translation>
<translation id="2644798301485385923">Chrome OS సిస్టమ్</translation>
<translation id="2652691236519827073">కొత్త Chrome &amp;ట్యాబ్‌లో లింక్‌ను తెరువు</translation>
-<translation id="2665296953892887393">Googleకు క్రాష్ నివేదికలను, <ph name="UMA_LINK" />ను పంపడం ద్వారా Google Chromeను మెరుగుపరచడంలో సహాయపడండి</translation>
+<translation id="2665296953892887393">వినియోగ గణాంకాలు మరియు <ph name="UMA_LINK" />ను Googleకు పంపడం ద్వారా Google Chromeను మెరుగుపరచడంలో సహాయపడండి</translation>
<translation id="2689103672227170538">ఈ పొడిగింపు మీరు Chromeని ప్రారంభించినప్పుడు చూపబడే పేజీని మార్చింది.</translation>
<translation id="2765403129283291972">ఈ సైట్ కోసం మీ మైక్రోఫోన్‌ను యాక్సెస్ చేయడానికి Chromeకు అనుమతి అవసరం</translation>
<translation id="2770231113462710648">డిఫాల్ట్ బ్రౌజర్‌ను దీనికి మార్చు:</translation>
@@ -81,21 +81,22 @@
<translation id="2871893339301912279">మీరు Chromeకు సైన్ ఇన్ చేసారు!</translation>
<translation id="2888126860611144412">Chrome పరిచయం</translation>
<translation id="3037838751736561277">Google Chrome నేపథ్య మోడ్‌లో ఉంది.</translation>
-<translation id="3047079729301751317"><ph name="USERNAME" />ని డిస్‌కనెక్ట్ చేయడం వలన ఈ పరికరంలో నిల్వ చేయబడిన మీ చరిత్ర, బుక్‌మార్క్‌లు, సెట్టింగ్‌లు మరియు ఇతర Chrome డేటా క్లియర్ చేయబడతాయి. మీ Google ఖాతాలో నిల్వ చేయబడిన డేటా క్లియర్ చేయబడదు. దాన్ని <ph name="GOOGLE_DASHBOARD_LINK" />Google డాష్‌బోర్డ్<ph name="END_GOOGLE_DASHBOARD_LINK" />లో నిర్వహించవచ్చు.</translation>
+<translation id="3047079729301751317"><ph name="USERNAME" />ను డిస్‌కనెక్ట్ చేయడం వలన ఈ పరికరంలో నిల్వ చేయబడిన మీ చరిత్ర, బుక్‌మార్క్‌లు, సెట్టింగ్‌లు మరియు ఇతర Chrome డేటా క్లియర్ చేయబడతాయి. మీ Google ఖాతాలో నిల్వ చేయబడిన డేటా క్లియర్ చేయబడదు, దానిని <ph name="GOOGLE_DASHBOARD_LINK" />Google డాష్‌బోర్డ్<ph name="END_GOOGLE_DASHBOARD_LINK" />లో నిర్వహించవచ్చు.</translation>
<translation id="3065168410429928842">Chrome ట్యాబ్</translation>
<translation id="3080151273017101988">Google Chromeను మూసివేసినపుడు, యాప్‌లను నేపథ్యంలో అమలు చేయడాన్ని కొనసాగించు</translation>
-<translation id="3089968997497233615">Google Chrome యొక్క క్రొత్త సురక్షితమైన సంస్కరణ అందుబాటులో ఉంది.</translation>
+<translation id="3089968997497233615">Google Chrome యొక్క కొత్తదైన, మరింత సురక్షిత వెర్షన్ అందుబాటులో ఉంది.</translation>
<translation id="3149510190863420837">Chrome యాప్‌లు</translation>
<translation id="3180085900771989961">మీ నిర్వాహకులు తప్పనిసరిగా మిమ్మల్ని Chrome నుండి తీసివేసి, తిరిగి జోడించాలి.</translation>
-<translation id="3251381707915721925"><ph name="NEW_PROFILE_NAME" /> వీక్షించగల వెబ్‌సైట్‌లను సెట్ చేయడానికి, మీరు <ph name="BEGIN_LINK_1" /><ph name="DISPLAY_LINK" /><ph name="END_LINK_1" />ని సందర్శించడం ద్వారా పరిమితులు మరియు సెట్టింగ్‌లను కాన్ఫిగర్ చేయవచ్చు. మీరు డిఫాల్ట్ సెట్టింగ్‌లను మార్చకపోతే, <ph name="NEW_PROFILE_NAME" /> వెబ్‌లో అన్నీ బ్రౌజ్ చేయగలరు.
-<ph name="NEW_PROFILE_NAME" />ని మీ ఖాతా యాక్సెస్‌ చేయనీయకుండా నిరోధించడానికి, మీరు Chromeను ఉపయోగించనప్పుడు మీ ప్రొపైల్‌ను లాక్ చేసి ఉంచేట్లు చూసుకోండి. దీన్ని చేయడానికి, బ్రౌజర్ ఎగువ కుడి మూలన ఉన్న మీ ప్రొఫైల్ పేరును క్లిక్ చేసి, ఆపై "నిష్క్రమించి, చైల్డ్ లాక్ చేయి" ఎంపికను ఎంచుకోండి.
+<translation id="3251381707915721925"><ph name="NEW_PROFILE_NAME" /> వీక్షించగల వెబ్‌సైట్‌లను సెట్ చేయడానికి, మీరు <ph name="BEGIN_LINK_1" /><ph name="DISPLAY_LINK" /><ph name="END_LINK_1" />ని సందర్శించడం ద్వారా పరిమితులు మరియు సెట్టింగ్‌లను కాన్ఫిగర్ చేయవచ్చు. మీరు డిఫాల్ట్ సెట్టింగ్‌లను మార్చకపోతే, <ph name="NEW_PROFILE_NAME" /> వెబ్‌లో అన్నీ బ్రౌజ్ చేయగలరు.
+
+<ph name="NEW_PROFILE_NAME" /> ను మీ ఖాతా యాక్సెస్‌ చేయనీయకుండా నిరోధించడానికి, మీరు Chromeను ఉపయోగించనప్పుడు మీ ప్రొఫైల్‌ను లాక్ చేసి ఉంచేట్లు చూసుకోండి. ఇలా చేయడానికి, బ్రౌజర్ ఎగువ కుడి మూలన ఉన్న మీ ప్రొఫైల్ పేరును క్లిక్ చేసి, ఆపై "నిష్క్రమించి, చైల్డ్ లాక్ చేయి" ఎంపికను ఎంచుకోండి.
<ph name="BEGIN_LINK_2" />మరింత తెలుసుకోండి<ph name="END_LINK_2" />
దయచేసి తదుపరి సూచనల కోసం <ph name="ACCOUNT_EMAIL" />లో మీ ఇమెయిల్‌ను చూడండి.</translation>
<translation id="3282568296779691940">Chromeకు సైన్ ఇన్ చేయండి</translation>
<translation id="3360895254066713204">Chrome సహాయకారుడు</translation>
-<translation id="3395323229510056640">Chrome OSతో సహాయాన్ని పొందండి</translation>
-<translation id="3396977131400919238">ఇన్‌స్టాలేషన్ సమయంలో ఒక ఆపరేటింగ్ సిస్టమ్ ఎర్రర్ ఏర్పడింది. దయచేసి Google Chromeను మళ్ళీ డౌన్‌లోడ్ చేయండి.</translation>
+<translation id="3395323229510056640">Chrome OS గురించి సహాయాన్ని పొందండి</translation>
+<translation id="3396977131400919238">ఇన‌స్ట‌లేష‌న్‌ సమయంలో ఒక ఆపరేటింగ్ సిస్టమ్ ఎర్ర‌ర్‌ ఏర్పడింది. దయచేసి Google Chromeను మ‌ళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
<translation id="3398288718845740432">Chrome మెనూలో దాచండి</translation>
<translation id="3451115285585441894">Chromeకు జోడిస్తోంది...</translation>
<translation id="345171907106878721">Chromeకు మిమ్మల్ని జోడించుకోండి</translation>
@@ -106,7 +107,7 @@
<translation id="3622797965165704966">ఇప్పుడు మీ Google ఖాతాతో, షేర్ చేయ‌బ‌డిన కంప్యూటర్‌ల‌లో Chromeను సులభంగా ఉపయోగించవచ్చు.</translation>
<translation id="3637702109597584617">Google Chrome OS <ph name="TERMS_OF_SERVICE_LINK" />సేవా నిబంధనలు<ph name="END_TERMS_OF_SERVICE_LINK" /></translation>
<translation id="3716182511346448902">ఈ పేజీ చాలా మెమరీని ఉపయోగిస్తోంది, కాబట్టి దీన్ని Chrome పాజ్ చేయబడింది.</translation>
-<translation id="3718181793972440140">ఇది ఈ పరికరం నుండి 1 అంశాన్ని తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromeకి <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
+<translation id="3718181793972440140">ఇది ఈ పరికరం నుండి 1 అంశాన్ని తొలగిస్తుంది. మీ డేటాను తర్వాత తిరిగి పొందడానికి, Chromeకు <ph name="USER_EMAIL" /> లాగా సైన్ ఇన్ చేయండి.</translation>
<translation id="3735758079232443276"><ph name="EXTENSION_NAME" /> పొడిగింపు మీరు Chromeని ప్రారంభించినప్పుడు చూపబడే పేజీని మార్చింది.</translation>
<translation id="3780814664026482060">Chrome - <ph name="PAGE_TITLE" /></translation>
<translation id="3784527566857328444">Chrome నుండి తీసివేయి...</translation>
@@ -116,15 +117,15 @@
<translation id="3889417619312448367">Google Chromeను అన్‌ఇన్‌స్టాల్ చేయండి</translation>
<translation id="3898493977366060150">Google స్మార్ట్‌లతో వెబ్ బ్రౌజింగ్</translation>
<translation id="4028693306634653894">Chromeకి వేగవంతంగా వెళ్లండి</translation>
-<translation id="4050175100176540509">ముఖ్యమైన భద్రతా మెరుగుదలలు మరియు కొత్త లక్షణాలు తాజా సంస్కరణలో అందుబాటులో ఉన్నాయి.</translation>
+<translation id="4050175100176540509">ముఖ్యమైన భద్రతా మెరుగుదలలు మరియు కొత్త ఫీచర్‌లు తాజా వెర్షన్‌లో అందుబాటులో ఉన్నాయి.</translation>
<translation id="4053720452172726777">Google Chromeను అనుకూలీకరించండి మరియు నియంత్రించండి</translation>
<translation id="4143243756087420366">Chrome పేరు మరియు చిత్రం</translation>
-<translation id="4147555960264124640">మీరు నిర్వహించబడే ఖాతాతో సైన్ ఇన్ చేస్తున్నారు మరియు దీని నిర్వాహకునికి మీ Google Chrome ప్రొఫైల్‌పై నియంత్రణను అందిస్తున్నారు. మీ యాప్‌లను, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌ల వంటి మీ Chrome డేటా శాశ్వతంగా <ph name="USER_NAME" />కు అనుబంధించబడుతుంది. మీరు Google ఖాతాల డాష్‌బోర్డ్ ద్వారా ఈ డేటాను తొలగించవచ్చు, కానీ ఈ డేటాను మరో ఖాతాతో అనుబంధించలేరు. <ph name="LEARN_MORE" /></translation>
-<translation id="4149882025268051530">ఆర్కైవ్‌ను విస్తరించడంలో ఇన్‌స్టాలర్ విఫలమైంది. దయచేసి Google Chromeను మళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
+<translation id="4147555960264124640">మీరు నిర్వహించబడే ఖాతాతో సైన్ ఇన్ చేస్తున్నారు. దీని నిర్వాహకునికి మీ Google Chrome ప్రొఫైల్‌పై నియంత్రణను అందిస్తున్నారు. మీ యాప్‌లు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌ల వంటి మీ Chrome డేటా శాశ్వతంగా <ph name="USER_NAME" />కు అనుబంధించబడుతుంది. మీరు Google ఖాతాల డాష్‌బోర్డ్ ద్వారా ఈ డేటాను తొలగించవచ్చు. కానీ ఈ డేటాను మరో ఖాతాతో అనుబంధించలేరు. <ph name="LEARN_MORE" /></translation>
+<translation id="4149882025268051530">ఆర్కైవ్‌ను విస్తరించడంలో ఇన్‌స్టాలర్ విఫలమైంది. దయచేసి Google Chromeను మ‌ళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
<translation id="424864128008805179">Chrome నుండి సైన్ అవుట్ చేయాలా?</translation>
<translation id="4251615635259297716">మీ Chrome డేటాను ఈ ఖాతాకు జోడించాలా?</translation>
<translation id="4251625577313994583">మీ iPhoneలో Chromeని పొందండి</translation>
-<translation id="4293420128516039005">మీ పరికరాల అంతటా Chromeను సింక్ చేయడం మరియు వ్యక్తిగతీకరించడం కోసం సైన్ ఇన్ చేయండి</translation>
+<translation id="4293420128516039005">మీ పరికరాల అంతటా Chromeను సింక్ చేయడానికి, వ్యక్తిగతీకరించడానికి సైన్ ఇన్ చేయండి</translation>
<translation id="4328355335528187361">Google Chrome డెవలపర్ (mDNS-In)</translation>
<translation id="4331809312908958774">Chrome OS</translation>
<translation id="4343195214584226067">Chromeకు <ph name="EXTENSION_NAME" /> జోడించబడింది</translation>
@@ -135,10 +136,10 @@
<translation id="4567424176335768812">మీరు <ph name="USER_EMAIL_ADDRESS" />గా సైన్ ఇన్ చేసారు. ఇప్పుడు మీరు సైన్ ఇన్ చేసిన అన్ని పరికరాల్లో మీ బుక్‌మార్క్‌లు, చరిత్ర మరియు ఇతర సెట్టింగ్‌లను యాక్సెస్ చేయవచ్చు.</translation>
<translation id="4571503333518166079">Chrome నోటిఫికేషన్ సెట్టింగ్‌లలోకి వెళ్లు</translation>
<translation id="459622048091363950">ఓసారి Chromeకి యాక్సెస్ లభించాక, ఆపై వెబ్‌సైట్‌లకు ఏమైనా యాక్సెస్‌ కావాలంటే అవి మిమ్మల్ని అడగవచ్చు.</translation>
-<translation id="4600710005438004015">Chromeని తాజా వెర్షన్‌కు అప్‌డేట్ చేయడం సాధ్యం కాలేదు, కనుక మీరు కొత్త ఫీచర్‌లు మరియు భద్రతా పరిష్కారాలను పొందలేరు.</translation>
+<translation id="4600710005438004015">Chromeను తాజా వెర్షన్‌కు అప్‌డేట్ చేయడం సాధ్యం కాలేదు, కాబట్టి మీరు కొత్త ఫీచర్‌లు మరియు భద్రతా పరిష్కారాలను పొందలేరు.</translation>
<translation id="4631713731678262610">Chrome మెనూలో దాచండి</translation>
<translation id="4633000520311261472">Chromeను సురక్షితం చేయడానికి, మేము <ph name="IDS_EXTENSION_WEB_STORE_TITLE" />లో జాబితా చేయబడని మరియు మీకు తెలియకుండానే జోడించబడిన కొన్ని పొడిగింపులను నిలిపివేసాము.</translation>
-<translation id="4700157086864140907">మీరు బ్రౌజర్‌లో టైప్ చేసే వాటిని Google సర్వర్‌లకు పంపించడం ద్వారా, Google శోధనలో ఉపయోగించే స్పెల్ చెక్ - సాంకేతిక పరిజ్ఞానాన్ని మీరు ఉపయోగించగలిగేలా అనుమతించి, మరింత మెరుగైన స్పెల్ చెక్‌ను Google Chrome అందించగలదు.</translation>
+<translation id="4700157086864140907">మీరు బ్రౌజర్‌లో టైప్ చేసే వాటిని Google సర్వర్‌లకు పంపించడం ద్వారా స్మార్ట్ స్పెల్‌చెక్‌ను Google Chrome అందిస్తుంది. త‌ద్వారా Google శోధనలో స్మార్ట్ స్పెల్‌చెక్‌ పరిజ్ఞానాన్ని మీరు ఉపయోగించడానికి అనుమ‌తిస్తుంది.</translation>
<translation id="4728575227883772061">పేర్కొనబడని ఎర్రర్ కారణంగా ఇన్‌స్టాలేషన్ విఫలమైంది. ప్రస్తుతం Google Chrome అమలు అవుతున్నట్లయితే, దయచేసి దానిని మూసివేసి, మళ్ళీ ప్రయత్నించండి.</translation>
<translation id="4750550185319565338"><ph name="PLUGIN_NAME" />ని ప్రారంభించడానికి Chromeను పునఃప్రారంభించండి</translation>
<translation id="4754614261631455953">Google Chrome కెనరీ (mDNS-In)</translation>
@@ -151,16 +152,16 @@
<translation id="4953650215774548573">Google Chromeను మీ డిఫాల్ట్ బ్రౌజర్‌గా సెట్ చేయండి</translation>
<translation id="495931528404527476">Chromeలో</translation>
<translation id="4990567037958725628">Google Chrome కేనరీ</translation>
-<translation id="5028489144783860647">Google Chrome మీ డేటాను సింక్ చేయలేకపోయింది. దయచేసి మీ సింక్ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
+<translation id="5028489144783860647">Google Chrome మీ డేటాను సింక్ చేయ‌లేక‌పోయింది. దయచేసి మీ సింక్‌ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
<translation id="5062123544085870375">Chrome OSను మళ్లీ ప్రారంభించండి</translation>
<translation id="5090044601776247154">Google Chrome 70తో మొదలు పెట్టి, తర్వాతి వెర్షన్‌లలో పర్యవేక్షించబడే వినియోగదారు ప్రొఫైల్‌లు ఇకపై అందుబాటులో ఉండవు.</translation>
<translation id="5132929315877954718">Google Chrome కోసం గొప్ప అనువర్తనాలు, ఆటలు, పొడిగింపులు మరియు థీమ్‌లను కనుగొనండి.</translation>
<translation id="5166975452760862670">Google Chrome ఈ భాషలో ప్రదర్శించబడుతోంది</translation>
-<translation id="5170938038195470297">మీ ప్రొఫైల్ ఉపయోగించబడదు ఎందుకంటే ఇది ఒక క్రొత్త Google Chrome వెర్షన్ నుండి తీసుకోబడింది. కొన్ని లక్షణాలు అందుబాటులో ఉండకపోవచ్చు. దయచేసి వేరొక ప్రొఫైల్ డైరెక్టరీని పేర్కొనండి లేదా Chrome యొక్క క్రొత్త వెర్షన్ను ఉపయోగించండి.</translation>
+<translation id="5170938038195470297">మీ ప్రొఫైల్‌ను ఉపయోగించడం సాధ్యపడదు, ఎందుకంటే ఇది ఒక కొత్త Google Chrome వెర్షన్ నుండి తీసుకోబడింది. కొన్ని ఫీచర్‌లు అందుబాటులో ఉండకపోవచ్చు. దయచేసి వేరొక ప్రొఫైల్ డైరెక్టరీని పేర్కొనండి లేదా Chrome కొత్త వెర్షన్‌ను ఉపయోగించండి.</translation>
<translation id="5193136243808726294">Google Chrome OS ఈ పేజీని తెరవలేదు.</translation>
<translation id="5204098752394657250">Google Chrome <ph name="TERMS_OF_SERVICE_LINK" />సేవా నిబంధనలు<ph name="END_TERMS_OF_SERVICE_LINK" /></translation>
<translation id="5251420635869119124">అతిథులు ఎటువంటి చరిత్రను వదలకుండానే Chromeను ఉపయోగించవచ్చు.</translation>
-<translation id="532046782124376502">హెచ్చరిక: Google Chrome మీ బ్రౌజింగ్ చరిత్రను రికార్డ్ చేయకుండా ఎక్సటెన్షన్‌లను నివారించలేదు. ఈ ఎక్సటెన్షన్‌ను అజ్ఞాత మోడ్‌లో ఆపివేయడానికి, ఈ ఎంపికను రద్దు చేయండి.</translation>
+<translation id="532046782124376502">హెచ్చరిక: Google Chrome మీ బ్రౌజింగ్ చరిత్రను రికార్డ్ చేయకుండా ఎక్స్‌టెన్ష‌న్‌లను నివారించలేదు. ఈ ఎక్స్‌టెన్ష‌న్‌ను అజ్ఞాత మోడ్‌లో నిలిపివేయడానికి, ఈ ఎంపికను రద్దు చేయండి.</translation>
<translation id="5386244825306882791">ఇది మీరు Chromeను ప్రారంభించేటప్పుడు లేదా ఓమ్నిబాక్స్ నుండి వెతికేటప్పుడు చూపబడే పేజీని కూడా నియంత్రిస్తుంది.</translation>
<translation id="5430073640787465221">మీ ప్రాధాన్యతల ఫైల్ పాడైంది లేదా చెల్లదు. Google Chrome మీ సెట్టింగ్‌లను తిరిగి పొందలేకపోయింది.</translation>
<translation id="5483595757826856374">{0,plural, =0{ఇప్పుడు Chrome తిరిగి ప్రారంభించబడుతుంది}=1{1 సెకనులో Chrome తిరిగి ప్రారంభించబడుతుంది}other{# సెకన్లలో Chrome తిరిగి ప్రారంభించబడుతుంది}}</translation>
@@ -168,6 +169,7 @@
<translation id="556024056938947818">Google Chrome పాస్‌వర్డ్‌లను చూపడానికి ప్రయత్నిస్తోంది.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> హానికరం కావచ్చు, కావున Chrome దాన్ని బ్లాక్ చేసింది.</translation>
+<translation id="5686916850681061684">Google Chromeను అనుకూలీకరించండి, నియంత్రించండి. మీరు గమనించాల్సిన విషయం ఒకటి ఉంది - వివరాల కోసం క్లిక్ చేయండి.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome 1 సెకనులో పునఃప్రారంభమవుతుంది}other{Google Chrome # సెకన్లలో పునఃప్రారంభమవుతుంది}}</translation>
<translation id="573759479754913123">Chrome OS గురించి</translation>
<translation id="5774845247549698882">Chrome OS ఈ భాషలో ప్రదర్శించబడుతోంది</translation>
@@ -175,10 +177,10 @@
<translation id="5804318322022881572">Chromeను ప్రారంభించడం సాధ్యపడలేదు. మళ్లీ ప్రయత్నించండి.</translation>
<translation id="5877064549588274448">ఛానెల్ మార్చబడింది. మార్పులను వర్తింపజేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
<translation id="5895138241574237353">మళ్ళీ ప్రారంభించు</translation>
-<translation id="5906655207909574370">దాదాపు నవీకృతంగా ఉంది! నవీకరణను పూర్తి చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
+<translation id="5906655207909574370">దాదాపు తాజాగా ఉంది! అప్‌డేట్‌ను పూర్తి చేయడానికి మీ పరికరాన్ని పునఃప్రారంభించండి.</translation>
<translation id="5940385492829620908">మీ వెబ్, బుక్‌మార్క్‌లు మరియు ఇతర Chrome అంశాలు ఇక్కడ చూపబడతాయి.</translation>
<translation id="5941830788786076944">Google Chromeను డిఫాల్ట్ బ్రౌజర్‌గా చేసుకోండి</translation>
-<translation id="6014844626092547096">ఇప్పుడు మీరు Chromeకు సైన్ ఇన్ చేసారు! మీ నిర్వాహకులు సమకాలీకరణని నిలిపివేసారు.</translation>
+<translation id="6014844626092547096">ఇప్పుడు మీరు Chromeకు సైన్ ఇన్ చేశారు! మీ నిర్వాహకులు సింక్‌ను నిలిపివేశారు.</translation>
<translation id="6040143037577758943">మూసివేయి</translation>
<translation id="6070348360322141662">అదనపు భద్రత దృష్ట్యా, Google Chrome మీ డేటాను ఎన్‌క్రిప్ట్ చేస్తుంది</translation>
<translation id="6113794647360055231">Chrome ఇప్పుడు మెరుగైంది</translation>
@@ -205,45 +207,45 @@
<translation id="6943584222992551122">ఈ వ్యక్తి బ్రౌజింగ్ డేటా ఈ పరికరం నుండి తొలగించబడుతుంది. డేటాను పునరుద్ధరించడానికి, <ph name="USER_EMAIL" />గా Chromeకి సైన్ ఇన్ చేయండి.</translation>
<translation id="6964107240822114422">{0,plural, =0{Chrome అప్‌డేట్ అందుబాటులో ఉంది}=1{Chrome అప్‌డేట్ అందుబాటులో ఉంది}other{# రోజులుగా Chrome అప్‌డేట్ అందుబాటులో ఉంది}}</translation>
<translation id="6967962315388095737">mDNS ట్రాఫిక్‌ను అనుమతించడానికి Google Chrome బీటా కోసం ఇన్‌బౌండ్ నియమం.</translation>
-<translation id="6970811910055250180">మీ పరికరాన్ని నవీకరిస్తోంది...</translation>
+<translation id="6970811910055250180">మీ పరికరాన్ని అప్‌డేట్ చేస్తోంది...</translation>
<translation id="6982337800632491844">మీరు ఈ పరికరాన్ని ఉపయోగించడానికి ముందు సేవా నిబంధనలను చదివి, అంగీకరించాలని <ph name="DOMAIN" /> కోరుతోంది. ఈ నిబంధనలు Google Chrome OS నిబంధనలను విస్తరింపజేయవు, సవరించవు లేదా పరిమితం చేయవు.</translation>
<translation id="6989339256997917931">Google Chrome నవీకరింబడింది, కానీ మీరు దీన్ని కనీసం 30 రోజులు ఉయోగించలేరు.</translation>
<translation id="7023651421574588884">అప్‌డేట్‌ని వర్తింపజేయడం కోసం మీరు Chrome OSని మళ్లీ ప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
<translation id="7098166902387133879">Google Chrome మీ మైక్రోఫోన్‌ని ఉపయోగిస్తోంది.</translation>
<translation id="7106741999175697885">విధి నిర్వాహకుడు - Google Chrome</translation>
-<translation id="7164397146364144019">సంభావ్య భద్రతాపరమైన దాడులకు సంబంధించిన వివరాలను Googleకి స్వయంచాలకంగా నివేదించడం ద్వారా Chrome‌ని సురక్షితంగా మరియు సులభంగా ఉపయోగించదగినదిగా చేయడంలో మీ సహాయం అందించవచ్చు.</translation>
-<translation id="7242029209006116544">మీరు నిర్వహించబడే ఖాతాతో సైన్ ఇన్ చేస్తున్నారు మరియు దీని నిర్వాహకునికి మీ Google Chrome ప్రొఫైల్‌పై నియంత్రణను అందిస్తున్నారు. మీ యాప్‌లు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌ల వంటి మీ Chrome డేటా శాశ్వతంగా <ph name="USER_NAME" />కు అనుబంధించబడుతుంది. మీరు Google ఖాతాల డాష్‌బోర్డ్ ద్వారా ఈ డేటాను తొలగించవచ్చు, కానీ ఈ డేటాను మరో ఖాతాతో అనుబంధించలేరు. మీరు ప్రస్తుతం ఉన్న మీ Chrome డేటాను వేరుగా ఉంచడానికి ఐచ్ఛికంగా క్రొత్త ప్రొఫైల్‌ను సృష్టించవచ్చు. <ph name="LEARN_MORE" /></translation>
+<translation id="7164397146364144019">భద్రతాపరమైన దాడులయ్యే అవకాశమున్న అన్ని సంఘటనలకు సంబంధించిన వివరాలను Googleకు ఆటోమేటిక్‌గా నివేదించడం ద్వారా Chrome‌ను సురక్షితంగా మరియు సులభంగా ఉపయోగించదగినదిగా చేయడంలో సాయం చేయవచ్చు.</translation>
+<translation id="7242029209006116544">మీరు నిర్వహించబడే ఖాతాతో సైన్ ఇన్ చేస్తున్నారు. దీని నిర్వాహకునికి మీ Google Chrome ప్రొఫైల్‌పై నియంత్రణను అందిస్తున్నారు. మీ యాప్‌లు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు, ఇతర సెట్టింగ్‌ల వంటి మీ Chrome డేటా, శాశ్వతంగా <ph name="USER_NAME" />కు అనుబంధించబడుతుంది. మీరు Google ఖాతాల డాష్‌బోర్డ్ ద్వారా ఈ డేటాను తొలగించవచ్చు, కానీ ఈ డేటాను మరో ఖాతాతో అనుబంధించలేరు. మీరు ప్రస్తుతం ఉన్న మీ Chrome డేటాను వేరుగా ఉంచడానికి ఐచ్ఛికంగా కొత్త‌ ప్రొఫైల్‌ను సృష్టించవచ్చు. <ph name="LEARN_MORE" /></translation>
<translation id="7296210096911315575">ముఖ్యమైన వినియోగ, భద్రతా సమాచారం</translation>
<translation id="7308322188646931570">ఫైల్‌లను డౌన్‌లోడ్ చేయడానికి Chromeకు నిల్వ యాక్సెస్ అవసరం</translation>
<translation id="7339898014177206373">కొత్త విండో</translation>
-<translation id="7398801000654795464">మీరు <ph name="USER_EMAIL_ADDRESS" />గా Chromeకు సైన్ ఇన్ చేసారు. మళ్లీ సైన్ ఇన్ చేయడానికి దయచేసి ఇదే ఖాతాను ఉపయోగించండి.</translation>
+<translation id="7398801000654795464">మీరు <ph name="USER_EMAIL_ADDRESS" />గా Chromeకు సైన్ ఇన్ చేసారు. మళ్లీ సైన్ ఇన్ చేయడానికి, దయచేసి ఇదే ఖాతాను ఉపయోగించండి.</translation>
<translation id="7408085963519505752">Chrome OS నిబంధనలు</translation>
-<translation id="7419046106786626209">మీ డొమైన్ కోసం సమకాలీకరణ అందుబాటులో లేనందున Chrome OS మీ డేటాను సమకాలీకరించలేకపోయింది.</translation>
-<translation id="7459554271817304652">వెబ్‌కు మీ వ్యక్తిగతీకరించి బ్రౌజర్ ఫీచర్‌లను సేవ్ చేయడానికి మరియు ఏదైనా కంప్యూటర్‌లోని Google Chrome నుండి అయినా వాటిని యాక్సెస్ చేయడానికి సమకాలీకరణని సెటప్ చేయండి.</translation>
-<translation id="7473136999113284234">Chrome స్వయంచాలకంగా నవీకరించబడుతుంది కనుక మీరు ఎల్లప్పుడూ తాజా సంస్కరణను కలిగి ఉంటారు.</translation>
+<translation id="7419046106786626209">మీ డొమైన్ కోసం సింక్‌ అందుబాటులో లేనందున Chrome OS మీ డేటాను సింక్ చేయ‌లేక‌పోయింది.</translation>
+<translation id="7459554271817304652">వెబ్‌కు మీ వ్యక్తిగతీకరించిన‌ బ్రౌజర్ ఫీచ‌ర్‌ల‌ను సేవ్ చేయడానికి, ఏదైనా కంప్యూటర్‌లోని Google Chrome నుండి అయినా వాటిని యాక్సెస్‌ చేయడానికి సింక్‌ను సెటప్ చేయండి.</translation>
+<translation id="7473136999113284234">Chrome ఆటోమేటిక్‌గా అప్‌డేట్ అవుతుంది కాబట్టి మీ వద్ద ఎప్పుడూ తాజా వెర్షన్ ఉంటుంది.</translation>
<translation id="7486227612705979895">చిరునామా బార్‌లో సూచనలను చేయడానికి Chrome మీ డిస్క్‌ను యాక్సెస్ చేస్తుంది</translation>
<translation id="7535429826459677826">Google Chrome డెవలపర్</translation>
<translation id="7552219221109926349">Chrome OSను ఈ భాషలో ప్రదర్శించు</translation>
<translation id="7561940363513215021">{0,plural, =1{1 నిమిషంలో Chrome తిరిగి ప్రారంభించబడుతుంది}other{# నిమిషాల్లో Chrome తిరిగి ప్రారంభించబడుతుంది}}</translation>
<translation id="7589360514048265910">Mac OS X 10.9కు మద్దతు లేనందున ఈ కంప్యూటర్ ఇకపై Google Chrome అప్‌డేట్‌లను స్వీకరించదు.</translation>
-<translation id="7592736734348559088">మీ ఖాతా సైన్-ఇన్ వివరాల గడువు ముగిసినందున Google Chrome మీ డేటాను సమకాలీకరించలేకపోయింది.</translation>
+<translation id="7592736734348559088">మీ ఖాతా సైన్-ఇన్ వివరాల గడువు ముగిసినందున Google Chrome మీ డేటాను సింక్ చేయలేకపోయింది.</translation>
<translation id="7626032353295482388">Chromeకు స్వాగతం</translation>
<translation id="7651907282515937834">Chrome ఎంటర్‌ప్రైజ్ లోగో</translation>
-<translation id="7747138024166251722">ఇన్‌స్టాలర్ ఒక తాత్కాలిక డైరక్టరీని సృష్టించలేకపోయింది. సాఫ్ట్‌వేర్‌ను ఇన్‌స్టాల్ చేయడానికి దయచేసి డిస్క్‌కు సంబంధించి నిల్వ, అనుమతిని తనిఖీ చేయండి.</translation>
+<translation id="7747138024166251722">ఇన్‌స్టాలర్ ఒక తాత్కాలిక డైరక్టరీని సృష్టించలేకపోయింది. సాఫ్ట్‌వేర్‌ను ఇన్‌స్టాల్ చేయడానికి దయచేసి ఖాళీ డిస్క్ స్థలం, అనుమతిని తనిఖీ చేయండి.</translation>
<translation id="7761834446675418963">Chromeను తెరిచి, బ్రౌజింగ్‌ను ప్రారంభించడానికి మీ పేరును క్లిక్ చేయండి.</translation>
-<translation id="7781002470561365167">Google Chrome యొక్క క్రొత్త సంస్కరణ ఇప్పుడు అందుబాటులో ఉంది.</translation>
-<translation id="7787950393032327779">ప్రొఫైల్‌ని మరొక కంప్యూటర్ (<ph name="HOST_NAME" />)లో మరో Google Chrome ప్రాసెస్ (<ph name="PROCESS_ID" />) ఉపయోగిస్తున్నట్లు కనిపిస్తోంది. Chrome ప్రొఫైల్‌ని లాక్ చేసినందున అది పాడవదు. ఈ ప్రొఫైల్‌ని వేరే ఇతర ప్రాసెస్‌లు ఏవీ ఉపయోగించడం లేదని మీకు ఖచ్చితంగా తెలిస్తే, మీరు ప్రొఫైల్‌ని అన్‌లాక్ చేసి Chromeని మళ్లీ లాంచ్ చేయవచ్చు.</translation>
+<translation id="7781002470561365167">Google Chrome యొక్క కొత్త వెర్షన్ ఇప్పుడు అందుబాటులో ఉంది.</translation>
+<translation id="7787950393032327779">ఈ ప్రొఫైల్‌ను మరొక కంప్యూటర్ (<ph name="HOST_NAME" />)లో మరో Google Chrome ప్రాసెస్ (<ph name="PROCESS_ID" />) ఉపయోగిస్తున్నట్లు కనిపిస్తోంది. ఆ ప్రొఫైల్ పాడవకూడదనే ఉద్దేశ్యంతో Chrome దానిని లాక్ చేసింది. ఈ ప్రొఫైల్‌ను వేరే ఇతర ప్రాసెస్‌లు ఏవీ ఉపయోగించడం లేదని మీకు ఖచ్చితంగా తెలిస్తే, మీరు ప్రొఫైల్‌ను అన్‌లాక్ చేసి Chromeను మళ్లీ లాంచ్ చేయవచ్చు.</translation>
<translation id="7808348361785373670">Chrome నుండి తీసివేయి...</translation>
-<translation id="7825851276765848807">పేర్కొనబడని ఎర్రర్ కారణంగా ఇన్‌స్టాలేషన్ విఫలమైంది. దయచేసి Google Chromeను మళ్ళీ డౌన్‌లోడ్ చేయండి.</translation>
+<translation id="7825851276765848807">నిర్దిష్టంగా తెలియ‌ని ఎర్ర‌ర్‌ కారణంగా ఇన్‌స్ట‌లేష‌న్‌ విఫలమైంది. దయచేసి Google Chromeను మ‌ళ్లీ డౌన్‌లోడ్ చేయండి.</translation>
<translation id="7855730255114109580">Google Chrome తాజాగా ఉంది</translation>
<translation id="7888186132678118370">Chromeని మీ విధి పట్టీకి పిన్ చేయండి</translation>
-<translation id="7890208801193284374">మీరు కంప్యూటర్‌ను షేర్ చేస్తే, స్నేహితులు మరియు కుటుంబ సభ్యులు విడివిడిగా బ్రౌజ్ చేయవచ్చు మరియు Chromeను వారికి నచ్చిన రీతిలో సెటప్ చేసుకోవచ్చు.</translation>
+<translation id="7890208801193284374">మీరు కంప్యూటర్‌ను షేర్‌ చేస్తే, స్నేహితులు, కుటుంబ సభ్యులు విడివిడిగా బ్రౌజ్ చేయవచ్చు. Chromeను వారికి నచ్చిన రీతిలో సెటప్ చేసుకోవచ్చు.</translation>
<translation id="7896673875602241923">మునుపు ఒకరు ఈ కంప్యూటర్‌లో Chromeకు <ph name="ACCOUNT_EMAIL_LAST" /> లాగా సైన్ ఇన్ చేశారు. మీ సమాచారాన్ని విడిగా ఉంచడానికి దయచేసి కొత్త Chrome వినియోగదారును సృష్టించండి.</translation>
<translation id="7908168227788431038">దాదాపుగా నవీకృతంగా ఉంది! నవీకరణను పూర్తి చేయడానికి Google Chromeని పునఃప్రారంభించండి.</translation>
<translation id="7962410387636238736">Windows XP మరియు Windows Vistaలకు ఇప్పుడు మద్దతు లేనందున ఈ కంప్యూటర్ ఇకపై Google Chrome అప్‌డేట్‌లను స్వీకరించదు</translation>
<translation id="8005540215158006229">Chrome దాదాపు సిద్ధంగా ఉంది.</translation>
<translation id="8008534537613507642">Chromeను మళ్లీ ఇన్‌స్టాల్ చేయి</translation>
-<translation id="8030318113982266900">మీ పరికరాన్ని <ph name="CHANNEL_NAME" /> ఛానెల్‌కి నవీకరిస్తోంది...</translation>
+<translation id="8030318113982266900">మీ పరికరాన్ని <ph name="CHANNEL_NAME" /> ఛానెల్‌కు అప్‌డేట్ చేస్తోంది...</translation>
<translation id="8032142183999901390">Chrome నుండి మీ ఖాతాను తీసివేసిన తర్వాత, ప్రభావవంతం కావడానికి మీరు మీ తెరిచిన ట్యాబ్‌లను మళ్లీ లోడ్ చేయాల్సి రావచ్చు.</translation>
<translation id="8077352834923175128">ఈ అప్‌డేట్‌ని వర్తింపజేయడం కోసం మీరు Chrome OSని మళ్లీ ప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
<translation id="8129812357326543296">&amp;Google Chrome గురించి</translation>
@@ -257,15 +259,15 @@
<translation id="8342675569599923794">ఈ ఫైల్ అపాయకరమైనది, కాబట్టి Chrome దీన్ని బ్లాక్ చేసింది.</translation>
<translation id="8380166467911888159">అక్షరక్రమ లోపాలను పరిష్కరించడానికి, Chrome మీరు వచన ఫీల్డ్‌లలో టైప్ చేసే వచనాన్ని Googleకి పంపుతుంది</translation>
<translation id="840084489713044809">Google Chrome మీ పాస్‌వర్డ్‌లను ఎగుమతి చేయాలనుకుంటోంది.</translation>
-<translation id="8406086379114794905">Chromeని మెరుగుపరచడంలో సహాయపడండి</translation>
+<translation id="8406086379114794905">Chromeను మెరుగుపరచడంలో సహాయపడండి</translation>
<translation id="8432724323949790809">మీరు ఇప్పుడు Google Chromeని పునఃప్రారంభించాలి</translation>
-<translation id="8455999171311319804">ఐచ్ఛికం: విశ్లేషణ మరియు వినియోగ డేటాను ఆటోమేటిక్‌గా Googleకి పంపడం ద్వారా Chrome OSని మెరుగుపరచడంలో సహాయం అందించండి.</translation>
+<translation id="8455999171311319804">ఐచ్ఛికం: విశ్లేషణ మరియు వినియోగ డేటాను ఆటోమేటిక్‌గా Googleకు పంపడం ద్వారా Chrome OSను మెరుగుపరచడంలో సహాయం అందించండి.</translation>
<translation id="8478823064122749032">మీ ఫోన్‌లో Chromeను ఇన్‌స్టాల్ చేయండి. మేము మీ ఖాతా పునరుద్ధరణ ఫోన్ నంబర్‌కు SMS పంపుతాము: <ph name="PHONE_NUMBER" /></translation>
<translation id="8498858610309223613">Google Chromeకి సంబంధించిన ప్రత్యేక భద్రతా అప్‌డేట్ వర్తింపజేయబడింది. ఇప్పుడే పునఃప్రారంభించండి, మేము మీ ట్యాబ్‌లను పునరుద్ధరిస్తాము.</translation>
<translation id="8521348052903287641">mDNS ట్రాఫిక్‌ను అనుమతించడానికి Google Chrome డెవలపర్ కోసం ఇన్‌బౌండ్ నియమం.</translation>
<translation id="8540666473246803645">Google Chrome</translation>
<translation id="8547799825197623713">Chrome యాప్‌ లాంఛ‌ర్‌ కెనరీ</translation>
-<translation id="8556340503434111824">Google Chrome యొక్క క్రొత్త సంస్కరణ అందుబాటులో ఉంది, ఇది ఎప్పటి కంటే వేగంగా ఉంది.</translation>
+<translation id="8556340503434111824">Google Chrome యొక్క కొత్త వెర్షన్ అందుబాటులో ఉంది, ఇది మునుపటి కంటే వేగవంతంగా ఉంటుంది.</translation>
<translation id="8568392309447938879">మీరు అనువర్తనాలను ఉపయోగించడానికి Chromeకు సైన్ ఇన్ చేయాలి. ఇది పరికరాల్లో మీ అనువర్తనాలు, బుక్‌మార్క్‌లు, చరిత్ర, పాస్‌వర్డ్‌లు మరియు ఇతర సెట్టింగ్‌లను సమకాలీకరించడానికి Chromeను అనుమతిస్తుంది.</translation>
<translation id="8606668294522778825">Google Chrome మీ బ్రౌజింగ్ అనుభవాన్ని మెరుగుపరచడానికి వెబ్ సేవలను ఉపయోగించవచ్చు. మీరు ఈ సేవలను ఐచ్ఛికంగా నిలిపివేయవచ్చు. <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" /></translation>
<translation id="8614913330719544658">Google Chrome స్పందించడం లేదు. ఇప్పుడే పునఃప్రారంభించాలా?</translation>
@@ -274,18 +276,18 @@
<translation id="8679801911857917785">ఇది మీరు Chromeని ప్రారంభించేటప్పుడు చూపబడే పేజీని కూడా నియంత్రిస్తుంది.</translation>
<translation id="870251953148363156">&amp;Google Chromeను అప్‌డేట్ చేయి</translation>
<translation id="873133009373065397">Google Chrome డిఫాల్ట్ బ్రౌజర్‌ను నిశ్చయించలేదు లేదా సెట్ చేయలేదు</translation>
-<translation id="8736674169840206667">అప్‌డేట్‌ని వర్తింపజేయడం కోసం మీరు Chromeని పునఃప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
+<translation id="8736674169840206667">అప్‌డేట్‌ను వర్తింపజేయడం కోసం మీరు Chromeను పునఃప్రారంభించాలని మీ నిర్వాహకుడు కోరుతున్నారు</translation>
<translation id="8791470158600044404">{0,plural, =1{Chrome OS 1 నిమిషంలో మళ్లీ ప్రారంభించబడుతుంది}other{Chrome OS # నిమిషాల్లో మళ్లీ ప్రారంభించబడుతుంది}}</translation>
<translation id="8823341990149967727">Chrome కాలం చెల్లినది</translation>
<translation id="884296878221830158">ఇది మీరు Chromeను ప్రారంభించేటప్పుడు లేదా హోమ్ బటన్‌ను క్లిక్ చేసేటప్పుడు చూపబడే పేజీని కూడా నియంత్రిస్తుంది.</translation>
-<translation id="8862326446509486874">సిస్టమ్-స్థాయిలో ఇన్‌స్టాల్‌ చెయ్యడానికి మీకు సరైన హక్కులు లేవు. నిర్వాహకుడి లాగా ఇన్‌స్టాలర్‌ను మళ్లీ రన్ చెయ్యడానికి ప్రయత్నించండి.</translation>
+<translation id="8862326446509486874">సిస్టమ్-స్థాయిలో ఇన్‌స్టాల్‌ చేయ‌డానికి మీకు సరైన హక్కులు లేవు. నిర్వాహకుడి లాగా ఇన్‌స్టాలర్‌ను మ‌ళ్లీ రన్ చేయ‌డానికి ప్రయత్నించండి.</translation>
<translation id="8914504000324227558">Chromeను పునఃప్రారంభించు</translation>
-<translation id="9026991721384951619">మీ ఖాతా సైన్-ఇన్ వివరాల గడువు ముగిసినందున Chrome OS మీ డేటాను సింక్ చేయ‌లేకపోయింది.</translation>
+<translation id="9026991721384951619">మీ ఖాతా సైన్-ఇన్ వివరాల గడువు ముగిసినందున Chrome OS మీ డేటాను సింక్ చేయలేకపోయింది.</translation>
<translation id="9067395829937117663">Google Chromeకి Windows 7 లేదా అంతకంటే ఆధునికమైనది ఉండటం ఆవశ్యకం.</translation>
<translation id="909149346112452267">{0,plural, =1{Chrome OS గంటలో మళ్లీ ప్రారంభించబడుతుంది}other{Chrome OS # గంటల్లో మళ్లీ ప్రారంభించబడుతుంది}}</translation>
-<translation id="911206726377975832">మీ బ్రౌజింగ్ డేటాని కూడా తొలగించాలా?</translation>
+<translation id="911206726377975832">మీ బ్రౌజింగ్ డేటాను కూడా తొలగించాలా?</translation>
<translation id="9138603949443464873">మీ మార్పులను వర్తింపజేయడానికి, Chromeని పునఃప్రారంభించండి</translation>
-<translation id="919706545465235479">సింక్‌ను ప్రారంభించడానికి Chromeని అప్‌డేట్ చేయండి</translation>
+<translation id="919706545465235479">సింక్‌ను ప్రారంభించడానికి Chromeను అప్‌డేట్ చేయాలి</translation>
<translation id="924447568950697217">Chromeను మీ డిఫాల్ట్ బ్రౌజర్‌గా చేయండి</translation>
<translation id="989369509083708165">మీ డిఫాల్ట్ బ్రౌజర్ Google Chrome</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/chrome/app/resources/google_chrome_strings_th.xtb b/chromium/chrome/app/resources/google_chrome_strings_th.xtb
index 0405761e8c7..a6de901a21a 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_th.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_th.xtb
@@ -170,6 +170,7 @@
<translation id="556024056938947818">Google Chrome กำลังพยายามแสดงรหัสผ่าน</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> อาจเป็นอันตราย Chrome จึงบล็อกไว้</translation>
+<translation id="5686916850681061684">ปรับแต่งและควบคุม Google Chrome มีสิ่งที่คุณจำเป็นต้องทราบ โปรดคลิกเพื่อดูรายละเอียด</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome จะรีสตาร์ทใน 1 วินาที}other{Google Chrome จะรีสตาร์ทใน # วินาที}}</translation>
<translation id="573759479754913123">เกี่ยวกับ Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS แสดงในภาษานี้</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_tr.xtb b/chromium/chrome/app/resources/google_chrome_strings_tr.xtb
index 338641ef210..5e281c1ce3e 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_tr.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_tr.xtb
@@ -172,6 +172,7 @@ Bazı özellikler kullanılamayabilir. Lütfen farklı bir profil dizini belirti
<translation id="556024056938947818">Google Chrome şifreleri göstermeyi deniyor.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> tehlikeli olabileceği için Chrome tarafından engellendi.</translation>
+<translation id="5686916850681061684">Google Chrome'u özelleştirin ve kontrol edin. İlgilenmeniz gereken bir konu var. Ayrıntılar için tıklayın.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome 1 saniye içinde yeniden başlatılacak}other{Google Chrome # saniye içinde yeniden başlatılacak}}</translation>
<translation id="573759479754913123">Chrome OS hakkında</translation>
<translation id="5774845247549698882">Chrome OS bu dilde görüntüleniyor</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_uk.xtb b/chromium/chrome/app/resources/google_chrome_strings_uk.xtb
index 0dc671774b1..914c7b9d107 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_uk.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_uk.xtb
@@ -169,6 +169,7 @@
<translation id="556024056938947818">Google Chrome намагається показати паролі.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598">Файл <ph name="FILE_NAME" /> може бути небезпечним, тому Chrome заблокував його.</translation>
+<translation id="5686916850681061684">Налаштовуйте й керуйте Google Chrome. Якщо з’явиться сповіщення, натисніть його, щоб дізнатися більше.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome перезапуститься через 1 секунду}one{Google Chrome перезапуститься через # секунду}few{Google Chrome перезапуститься через # секунди}many{Google Chrome перезапуститься через # секунд}other{Google Chrome перезапуститься через # секунди}}</translation>
<translation id="573759479754913123">Про ОС Chrome</translation>
<translation id="5774845247549698882">Для ОС Chrome вибрано цю мову</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_vi.xtb b/chromium/chrome/app/resources/google_chrome_strings_vi.xtb
index 06732bb5474..086ea74e7cc 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_vi.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_vi.xtb
@@ -174,6 +174,7 @@ Một số tính năng có thể không khả dụng. Vui lòng chỉ định th
<translation id="556024056938947818">Google Chrome đang cố gắng hiển thị mật khẩu.</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> có thể nguy hiểm, do đó Chrome đã chặn tệp.</translation>
+<translation id="5686916850681061684">Tùy chỉnh và kiểm soát Google Chrome. Bạn cần lưu ý - nhấp để xem thông tin chi tiết.</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome sẽ khởi động lại sau 1 giây}other{Google Chrome sẽ khởi động lại sau # giây}}</translation>
<translation id="573759479754913123">Giới thiệu về Chrome OS</translation>
<translation id="5774845247549698882">Chrome OS được hiển thị bằng ngôn ngữ này</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_zh-CN.xtb b/chromium/chrome/app/resources/google_chrome_strings_zh-CN.xtb
index af919252dd9..9875357337b 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_zh-CN.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_zh-CN.xtb
@@ -170,6 +170,7 @@
<translation id="556024056938947818">Google Chrome 正尝试显示密码。</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> 可能存在危险,因此 Chrome 已将其拦截。</translation>
+<translation id="5686916850681061684">自定义和控制 Google Chrome。出了点需要您注意的状况 - 点击即可查看详情。</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome 将在 1 秒后重新启动}other{Google Chrome 将在 # 秒后重新启动}}</translation>
<translation id="573759479754913123">关于 Chrome 操作系统</translation>
<translation id="5774845247549698882">Chrome 操作系统界面目前使用的是这种语言</translation>
diff --git a/chromium/chrome/app/resources/google_chrome_strings_zh-TW.xtb b/chromium/chrome/app/resources/google_chrome_strings_zh-TW.xtb
index 695d74a4c99..94b54b803cf 100644
--- a/chromium/chrome/app/resources/google_chrome_strings_zh-TW.xtb
+++ b/chromium/chrome/app/resources/google_chrome_strings_zh-TW.xtb
@@ -171,6 +171,7 @@ Google Chrome 無法復原你的設定。</translation>
<translation id="556024056938947818">Google Chrome 即將顯示密碼。</translation>
<translation id="5566025111015594046">Google Chrome (mDNS-In)</translation>
<translation id="565744775970812598"><ph name="FILE_NAME" /> 可能不安全,因此遭到 Chrome 封鎖。</translation>
+<translation id="5686916850681061684">自訂及管理 Google Chrome。重要注意事項 - 按這裡瞭解詳情。</translation>
<translation id="5715063361988620182">{SECONDS,plural, =1{Google Chrome 將於 1 秒後重新啟動}other{Google Chrome 將於 # 秒後重新啟動}}</translation>
<translation id="573759479754913123">關於 Chrome 作業系統</translation>
<translation id="5774845247549698882">Chrome 作業系統的介面文字已設為這種語言</translation>
diff --git a/chromium/chrome/browser/BUILD.gn b/chromium/chrome/browser/BUILD.gn
index 6748ad379db..5f188cf2d30 100644
--- a/chromium/chrome/browser/BUILD.gn
+++ b/chromium/chrome/browser/BUILD.gn
@@ -761,6 +761,8 @@ jumbo_split_static_library("browser") {
"memory_details_win.cc",
"metrics/antivirus_metrics_provider_win.cc",
"metrics/antivirus_metrics_provider_win.h",
+ "metrics/bluetooth_available_utility.cc",
+ "metrics/bluetooth_available_utility.h",
"metrics/browser_window_histogram_helper.cc",
"metrics/browser_window_histogram_helper.h",
"metrics/chrome_browser_main_extra_parts_metrics.cc",
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
index 1fc47dd8660..c754c5b085c 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
@@ -114,7 +114,7 @@ void AppendAdditionalBrowserInformation(em::ChromeDesktopReportRequest* request,
request->mutable_browser_report()
->mutable_chrome_user_profile_reports(0)
->set_policy_data(
- policy::GetAllPolicyValuesAsJSON(profile, true, false));
+ policy::GetAllPolicyValuesAsJSON(profile, true, false, false));
int64_t timestamp = GetMachineLevelUserCloudPolicyFetchTimestamp();
if (timestamp > 0) {
diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc
index c8f67cb0264..fd210d82a00 100644
--- a/chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/extensions/extension_with_management_policy_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/ui_test_utils.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "extensions/browser/extension_prefs.h"
@@ -184,6 +185,30 @@ IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsFileAccess) {
// EXPECT_TRUE(prefs->AllowFileAccess("hlonmbgfjccgolnaboonlakjckinmhmd"));
}
+// Tests loading of files or directory listings when an extension has file
+// access.
+IN_PROC_BROWSER_TEST_F(PermissionsApiTest, FileLoad) {
+ base::ScopedTempDir temp_dir;
+ {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath empty_file = temp_dir.GetPath().AppendASCII("empty.html");
+ base::FilePath original_empty_file = ui_test_utils::GetTestFilePath(
+ base::FilePath(), base::FilePath().AppendASCII("empty.html"));
+
+ EXPECT_TRUE(base::PathExists(original_empty_file));
+ EXPECT_TRUE(base::CopyFile(original_empty_file, empty_file));
+ }
+ EXPECT_TRUE(RunExtensionTestWithFlagsAndArg(
+ "permissions/file_load", temp_dir.GetPath().MaybeAsASCII().c_str(),
+ kFlagEnableFileAccess))
+ << message_;
+ {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ ASSERT_TRUE(temp_dir.Delete());
+ }
+}
+
// Test requesting, querying, and removing host permissions for host
// permissions that are a subset of the optional permissions.
IN_PROC_BROWSER_TEST_F(PermissionsApiTest, HostSubsets) {
diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 088ae5e7c94..a565a712966 100644
--- a/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -522,6 +522,17 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
message_;
}
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestAuthRequiredIncognito) {
+ CancelLoginDialog login_dialog_helper;
+
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ ASSERT_TRUE(RunExtensionSubtestWithArgAndFlags(
+ "webrequest", "test_auth_required.html", nullptr,
+ kFlagEnableIncognito | kFlagUseIncognito | kFlagEnableFileAccess))
+ << message_;
+}
+
// This test times out regularly on win_rel trybots. See http://crbug.com/122178
// Also on Linux/ChromiumOS debug, ASAN and MSAN builds.
// https://crbug.com/670415
diff --git a/chromium/chrome/browser/flag-metadata.json b/chromium/chrome/browser/flag-metadata.json
index d780627b298..f325b413c90 100644
--- a/chromium/chrome/browser/flag-metadata.json
+++ b/chromium/chrome/browser/flag-metadata.json
@@ -553,8 +553,8 @@
"expiry_milestone": 76
},
{
- "name": "disable-explicit-dma-fences",
- // "owners": [ "your-team" ],
+ "name": "enable-explicit-dma-fences",
+ "owners": [ "chromeos-gfx" ],
"expiry_milestone": 76
},
{
@@ -2774,9 +2774,54 @@
"expiry_milestone": 76
},
{
+ "name": "omnibox-ui-show-suggestion-favicons",
+ "owners": [ "chrome-omnibox-team" ],
+ "expiry_milestone": 80
+ },
+ {
"name": "omnibox-ui-swap-title-and-url",
// "owners": [ "your-team" ],
- "expiry_milestone": 76
+ "expiry_milestone": 80
+ },
+ {
+ "name": "omnibox-ui-blue-search-loop-and-search-query",
+ "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
+ "expiry_milestone": 80
+ },
+ {
+ "name": "omnibox-ui-blue-titles-and-gray-urls-on-page-suggestions",
+ "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
+ "expiry_milestone": 80
+ },
+ {
+ "name": "omnibox-ui-blue-titles-on-page-suggestions",
+ "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
+ "expiry_milestone": 80
+ },
+ {
+ "name": "omnibox-ui-show-suffix-on-all-search-suggestions",
+ "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
+ "expiry_milestone": 80
+ },
+ {
+ "name": "omnibox-ui-white-background-on-blur",
+ "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
+ "expiry_milestone": 80
+ },
+ {
+ "name": "omnibox-ui-use-generic-search-engine-icon",
+ "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
+ "expiry_milestone": 80
+ },
+ {
+ "name": "omnibox-ui-bold-user-text-on-search-suggestions",
+ "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
+ "expiry_milestone": 80
+ },
+ {
+ "name": "omnibox-ui-unbold-suggestion-text",
+ "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
+ "expiry_milestone": 80
},
{
"name": "only-new-password-form-parsing",
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js
index 3d6890f4d37..0ce8ebd6667 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js
@@ -25,7 +25,7 @@ Polymer({
header: String,
/** Whether to hide the header at the top of the dropdown. */
- hideHeader: Boolean,
+ hideHeader: {type: Boolean, value: false},
/** Icon to display when the dropdown is closed. */
closedIcon: String,
diff --git a/chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js b/chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js
index 713309bf8dd..4bed3cf6e7e 100644
--- a/chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js
+++ b/chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js
@@ -332,7 +332,6 @@ cr.define('cloudprint', function() {
for (let i = 0; i < users.length; i++) {
this.userSessionIndex_[users[i]] = i;
}
- this.dispatchUserUpdateEvent_(request.result['request']['user'], users);
}
}
@@ -433,6 +432,8 @@ cr.define('cloudprint', function() {
});
// Extract and store users.
this.setUsers_(request);
+ this.dispatchUserUpdateEvent_(
+ activeUser, request.result['request']['users']);
// Dispatch SEARCH_DONE event.
this.eventTarget_.dispatchEvent(
new CustomEvent(CloudPrintInterfaceEventType.SEARCH_DONE, {
@@ -555,11 +556,12 @@ cr.define('cloudprint', function() {
request.result && request.result['request']['user'] &&
request.result['request']['users'] &&
request.account != request.result['request']['user']) {
+ const users = request.result['request']['users'];
this.setUsers_(request);
// In case the user account is known, but not the primary one,
// activate it.
- if (request.account && this.userSessionIndex_[request.account] > 0) {
- this.dispatchUserUpdateEvent_(request.result['request']['user']);
+ if (this.userSessionIndex_[request.account] > 0 && request.account) {
+ this.dispatchUserUpdateEvent_(request.account, users);
// Repeat the request for the newly activated account.
this.printer(
request.result['request']['params']['printerid'], request.origin,
@@ -567,6 +569,7 @@ cr.define('cloudprint', function() {
// Stop processing this request, wait for the new response.
return;
}
+ this.dispatchUserUpdateEvent_(request.result['request']['user'], users);
}
// Process response.
if (request.xhr.status == 200 && request.result['success']) {
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination_match.js b/chromium/chrome/browser/resources/print_preview/data/destination_match.js
index e30339c7345..9e3e9307f93 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination_match.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination_match.js
@@ -8,8 +8,7 @@ cr.define('print_preview', function() {
* Converts DestinationOrigin to PrinterType.
* @param {!print_preview.DestinationOrigin} origin The printer's
* destination origin.
- * return {?print_preview.PrinterType} The corresponding PrinterType.
- * Returns null if no match is found.
+ * return {!print_preview.PrinterType} The corresponding PrinterType.
*/
const originToType = function(origin) {
if (origin === print_preview.DestinationOrigin.LOCAL ||
@@ -22,7 +21,8 @@ cr.define('print_preview', function() {
if (origin === print_preview.DestinationOrigin.EXTENSION) {
return print_preview.PrinterType.EXTENSION_PRINTER;
}
- return null;
+ assert(print_preview.CloudOrigins.includes(origin));
+ return print_preview.PrinterType.CLOUD_PRINTER;
};
class DestinationMatch {
@@ -107,12 +107,11 @@ cr.define('print_preview', function() {
}
/**
- * @return {!Set<?print_preview.PrinterType>} The printer types that
- * correspond to this destination match. A null element in the set
- * indicates the match may represent a Cloud destination.
+ * @return {!Set<!print_preview.PrinterType>} The printer types that
+ * correspond to this destination match.
*/
getTypes() {
- return new Set(this.origins_.map(origin => originToType(origin)));
+ return new Set(this.origins_.map(originToType));
}
}
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination_store.js b/chromium/chrome/browser/resources/print_preview/data/destination_store.js
index 5db4db9460b..b6e38eb8a36 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination_store.js
@@ -376,65 +376,71 @@ cr.define('print_preview', function() {
}
this.recentDestinations_ = recentDestinations;
- const serializedDestination = {
- id: '',
- origin: this.platformOrigin_,
- account: '',
- capabilities: null,
- displayName: '',
- extensionId: '',
- extensionName: '',
- };
- let foundDestination = false;
+ let startedAutoSelect = false;
+ let selected = false;
+ let account = '';
// Run through the destinations forward. As soon as we find a
- // destination, don't select any future destinations, just mark
- // them recent. Otherwise, there is a race condition between selecting
- // destinations/updating the print ticket and this selecting a new
- // destination that causes random print preview errors.
+ // destination, don't select any future destinations, just fetch their
+ // capabilities in case the user switches to them later.
for (const destination of recentDestinations) {
const candidate = this.destinationMap_.get(
print_preview.createRecentDestinationKey(destination));
+ const shouldSelectDestination =
+ !this.useSystemDefaultAsDefault_ && !selected && !startedAutoSelect;
+ if (destination.account && account && destination.account !== account) {
+ // If we have already selected a destination with a specific account,
+ // don't request destinations from a different account, as doing so
+ // will cause the cloud print interface to reset the UI to have a
+ // different active user from the user that owns the selected printer.
+ continue;
+ }
if (candidate != undefined) {
candidate.isRecent = true;
- if (!foundDestination && !this.useSystemDefaultAsDefault_) {
+ // Destination is already in the store. Select it, if we haven't
+ // started selecting a destination already.
+ if (shouldSelectDestination) {
this.selectDestination(candidate);
+ selected = true;
+ account = destination.account;
}
- foundDestination = true;
} else {
- // Only automatically select the destination if we are not using the
- // system default and we have not already found a destination to
- // select.
- const autoSelect =
- !foundDestination && !this.useSystemDefaultAsDefault_;
- const foundNewDestination =
- this.fetchPreselectedDestination_(destination, autoSelect);
- foundDestination = foundDestination || foundNewDestination;
+ // Pre-fetch the destination and start auto select if needed.
+ const startedFetch = this.fetchPreselectedDestination_(
+ destination, shouldSelectDestination);
+ if (startedFetch && shouldSelectDestination) {
+ startedAutoSelect = true;
+ account = destination.account;
+ }
}
}
- if (foundDestination && !this.useSystemDefaultAsDefault_) {
- this.startAutoSelectTimeout_();
+ if ((selected || startedAutoSelect) && !this.useSystemDefaultAsDefault_) {
+ // Return early since we already selected a destination.
return;
}
// Try the system default
- serializedDestination.id = this.systemDefaultDestinationId_;
- serializedDestination.origin = serializedDestination.id ==
- print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ?
- print_preview.DestinationOrigin.LOCAL :
- this.platformOrigin_;
- serializedDestination.account = '';
+ const serializedSystemDefault = {
+ id: this.systemDefaultDestinationId_,
+ origin: this.systemDefaultDestinationId_ ==
+ print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ?
+ print_preview.DestinationOrigin.LOCAL :
+ this.platformOrigin_,
+ account: '',
+ capabilities: null,
+ displayName: '',
+ extensionId: '',
+ extensionName: '',
+ };
const systemDefaultCandidate = this.destinationMap_.get(
- print_preview.createRecentDestinationKey(serializedDestination));
+ print_preview.createRecentDestinationKey(serializedSystemDefault));
if (systemDefaultCandidate != undefined) {
this.selectDestination(systemDefaultCandidate);
- this.startAutoSelectTimeout_();
return;
}
if (this.fetchPreselectedDestination_(
- serializedDestination, true /* autoSelect */)) {
- this.startAutoSelectTimeout_();
+ serializedSystemDefault, true /* autoSelect */)) {
return;
}
@@ -458,56 +464,63 @@ cr.define('print_preview', function() {
this.createExactDestinationMatch_(origin, id);
}
+ let error = false;
const type = print_preview.originToType(origin);
- if (type == print_preview.PrinterType.LOCAL_PRINTER) {
- this.nativeLayer_.getPrinterCapabilities(id, type).then(
- this.onCapabilitiesSet_.bind(this, origin, id),
- this.onGetCapabilitiesFail_.bind(this, origin, id));
- return true;
- }
+ switch (type) {
+ case print_preview.PrinterType.LOCAL_PRINTER:
+ this.nativeLayer_.getPrinterCapabilities(id, type).then(
+ this.onCapabilitiesSet_.bind(this, origin, id),
+ this.onGetCapabilitiesFail_.bind(this, origin, id));
+ break;
+ case print_preview.PrinterType.PRIVET_PRINTER:
+ case print_preview.PrinterType.EXTENSION_PRINTER:
+ // TODO(noamsml): Resolve a specific printer instead of listing all
+ // privet or extension printers in this case.
+ this.startLoadDestinations_(type);
- if (this.cloudPrintInterface_ &&
- print_preview.CloudOrigins.includes(origin)) {
- this.cloudPrintInterface_.printer(
- id, origin, serializedDestination.account);
- return true;
+ if (autoSelect) {
+ // Create a fake selectedDestination_ that is not actually in the
+ // destination store. When the real destination is created, this
+ // destination will be overwritten.
+ const params =
+ (origin === print_preview.DestinationOrigin.PRIVET) ? {} : {
+ description: '',
+ extensionId: serializedDestination.extensionId,
+ extensionName: serializedDestination.extensionName,
+ provisionalType: print_preview.DestinationProvisionalType.NONE
+ };
+ this.selectedDestination_ = new print_preview.Destination(
+ id, print_preview.DestinationType.LOCAL, origin,
+ serializedDestination.displayName, false /* isRecent */,
+ print_preview.DestinationConnectionStatus.ONLINE, params);
+
+ if (serializedDestination.capabilities) {
+ this.selectedDestination_.capabilities =
+ serializedDestination.capabilities;
+ this.dispatchEvent(new CustomEvent(
+ DestinationStore.EventType
+ .SELECTED_DESTINATION_CAPABILITIES_READY));
+ }
+ }
+ break;
+ case print_preview.PrinterType.CLOUD_PRINTER:
+ if (this.cloudPrintInterface_) {
+ this.cloudPrintInterface_.printer(
+ id, origin, serializedDestination.account);
+ } else {
+ // No cloud print interface.
+ error = true;
+ }
+ break;
+ default:
+ // Unknown type.
+ error = true;
}
- if (origin == print_preview.DestinationOrigin.PRIVET ||
- origin == print_preview.DestinationOrigin.EXTENSION) {
- // TODO(noamsml): Resolve a specific printer instead of listing all
- // privet or extension printers in this case.
- this.startLoadDestinations_(type);
-
- if (!autoSelect) {
- return true;
- }
-
- // Create a fake selectedDestination_ that is not actually in the
- // destination store. When the real destination is created, this
- // destination will be overwritten.
- const params =
- (origin === print_preview.DestinationOrigin.PRIVET) ? {} : {
- description: '',
- extensionId: serializedDestination.extensionId,
- extensionName: serializedDestination.extensionName,
- provisionalType: print_preview.DestinationProvisionalType.NONE
- };
- this.selectedDestination_ = new print_preview.Destination(
- id, print_preview.DestinationType.LOCAL, origin,
- serializedDestination.displayName, false /*isRecent*/,
- print_preview.DestinationConnectionStatus.ONLINE, params);
-
- if (serializedDestination.capabilities) {
- this.selectedDestination_.capabilities =
- serializedDestination.capabilities;
- this.dispatchEvent(
- new CustomEvent(DestinationStore.EventType
- .SELECTED_DESTINATION_CAPABILITIES_READY));
- }
- return true;
+ if (!error && autoSelect) {
+ this.startAutoSelectTimeout_();
}
- return false;
+ return !error;
}
/**
@@ -519,7 +532,8 @@ cr.define('print_preview', function() {
this.autoSelectMatchingDestination_ = destinationMatch;
const types = destinationMatch.getTypes();
types.forEach(type => {
- if (type != null) { // Local, extension, or privet printer
+ if (type != print_preview.PrinterType.CLOUD_PRINTER) {
+ // Local, extension, or privet printer
this.startLoadDestinations_(type);
} else if (print_preview.CloudOrigins.some(origin => {
return destinationMatch.matchOrigin(origin);
@@ -665,8 +679,8 @@ cr.define('print_preview', function() {
*/
selectDestination(destination) {
this.autoSelectMatchingDestination_ = null;
- // When auto select expires, DESTINATION_SELECT event has to be dispatched
- // anyway (see isAutoSelectDestinationInProgress() logic).
+ // Clear the timeout. Otherwise, when it expires, we will fall back to the
+ // default destination.
if (this.autoSelectTimeout_) {
clearTimeout(this.autoSelectTimeout_);
this.autoSelectTimeout_ = null;
@@ -706,7 +720,7 @@ cr.define('print_preview', function() {
// known yet.
if (destination.capabilities == null) {
const type = print_preview.originToType(destination.origin);
- if (type !== null) {
+ if (type !== print_preview.PrinterType.CLOUD_PRINTER) {
this.nativeLayer_.getPrinterCapabilities(destination.id, type)
.then(
(caps) => this.onCapabilitiesSet_(
@@ -1143,13 +1157,10 @@ cr.define('print_preview', function() {
this.destinationMap_.clear();
this.selectDestination(null);
this.loadedCloudOrigins_.clear();
- for (const printerType of Object.values(print_preview.PrinterType)) {
- if (printerType !== print_preview.PrinterType.PDF_PRINTER) {
- this.destinationSearchStatus_.set(
- printerType,
- print_preview.DestinationStorePrinterSearchStatus.START);
- }
- }
+ this.destinationSearchStatus_.forEach((status, type) => {
+ this.destinationSearchStatus_.set(
+ type, print_preview.DestinationStorePrinterSearchStatus.START);
+ });
this.startAutoSelectTimeout_();
this.dispatchEvent(
new CustomEvent(DestinationStore.EventType.DESTINATIONS_RESET));
diff --git a/chromium/chrome/browser/resources/print_preview/new/destination_dialog.js b/chromium/chrome/browser/resources/print_preview/new/destination_dialog.js
index b5d32995189..8a1cf893d15 100644
--- a/chromium/chrome/browser/resources/print_preview/new/destination_dialog.js
+++ b/chromium/chrome/browser/resources/print_preview/new/destination_dialog.js
@@ -22,6 +22,8 @@ Polymer({
activeUser: String,
+ currentDestinationAccount: String,
+
/** @type {!Array<string>} */
users: Array,
@@ -46,7 +48,6 @@ Polymer({
/** @private {!Array<!print_preview.Destination>} */
destinations_: {
type: Array,
- notify: true,
value: [],
},
@@ -158,8 +159,7 @@ Polymer({
}
this.updateList(
- 'destinations_',
- destination => destination.origin + '/' + destination.id,
+ 'destinations_', destination => destination.key,
this.destinationStore.destinations(this.activeUser));
this.loadingDestinations_ =
@@ -171,12 +171,15 @@ Polymer({
if (this.searchQuery_) {
this.$.searchBox.setValue('');
}
- if (this.$.dialog.getNative().returnValue == 'success') {
- this.metrics_.record(print_preview.Metrics.DestinationSearchBucket
- .DESTINATION_CLOSED_CHANGED);
- } else {
- this.metrics_.record(print_preview.Metrics.DestinationSearchBucket
- .DESTINATION_CLOSED_UNCHANGED);
+ const cancelled = this.$.dialog.getNative().returnValue !== 'success';
+ this.metrics_.record(
+ cancelled ? print_preview.Metrics.DestinationSearchBucket
+ .DESTINATION_CLOSED_UNCHANGED :
+ print_preview.Metrics.DestinationSearchBucket
+ .DESTINATION_CLOSED_CHANGED);
+ if (cancelled && this.currentDestinationAccount &&
+ this.currentDestinationAccount !== this.activeUser) {
+ this.fire('account-change', this.currentDestinationAccount);
}
},
@@ -366,6 +369,8 @@ Polymer({
const account = select.value;
if (account) {
this.showCloudPrintPromo = false;
+ this.loadingDestinations_ = true;
+ this.destinations_ = [];
this.fire('account-change', account);
this.metrics_.record(
print_preview.Metrics.DestinationSearchBucket.ACCOUNT_CHANGED);
diff --git a/chromium/chrome/browser/resources/print_preview/new/destination_settings.html b/chromium/chrome/browser/resources/print_preview/new/destination_settings.html
index 4bdf89f3828..6d5427d1283 100644
--- a/chromium/chrome/browser/resources/print_preview/new/destination_settings.html
+++ b/chromium/chrome/browser/resources/print_preview/new/destination_settings.html
@@ -85,6 +85,7 @@
invitation-store="[[invitationStore]]"
recent-destination-list="[[recentDestinationList_]]"
active-user="[[activeUser]]" users="[[users]]"
+ current-destination-account="[[destination.account]]"
on-close="onDialogClose_">
</print-preview-destination-dialog>
</template>
diff --git a/chromium/chrome/browser/resources/print_preview/new/destination_settings.js b/chromium/chrome/browser/resources/print_preview/new/destination_settings.js
index 9f7b60c8640..395a2dfa777 100644
--- a/chromium/chrome/browser/resources/print_preview/new/destination_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/new/destination_settings.js
@@ -19,7 +19,10 @@ Polymer({
},
/** @type {!print_preview.Destination} */
- destination: Object,
+ destination: {
+ type: Object,
+ observer: 'onDestinationSet_',
+ },
/** @type {?print_preview.DestinationStore} */
destinationStore: {
@@ -149,22 +152,26 @@ Polymer({
/** @private */
onCloudPrintStateChanged_: function() {
- if (this.cloudPrintState !== print_preview.CloudPrintState.ENABLED &&
- this.cloudPrintState !== print_preview.CloudPrintState.SIGNED_IN) {
+ if (this.cloudPrintState !== print_preview.CloudPrintState.SIGNED_IN) {
return;
}
- this.loadDropdownCloudDestinations_();
- if (this.cloudPrintState === print_preview.CloudPrintState.SIGNED_IN) {
- return;
+ if (this.destination && this.destination.account !== '') {
+ this.updateDestination_();
}
- const destinationDialog = this.$$('print-preview-destination-dialog');
- if (destinationDialog && destinationDialog.isOpen()) {
- this.destinationStore.startLoadCloudDestinations();
- if (this.activeUser) {
- this.invitationStore.startLoadingInvitations(this.activeUser);
- }
+ this.loadDropdownCloudDestinations_();
+ },
+
+ /** @private */
+ onDestinationSet_: function() {
+ if (this.cloudPrintState === print_preview.CloudPrintState.ENABLED) {
+ // Only try to load the docs destination for now. If this request
+ // succeeds, it will trigger a transition to SIGNED_IN, and we can
+ // load the remaining destinations. Otherwise, it will transition to
+ // NOT_SIGNED_IN, so we will not do this more than once.
+ this.destinationStore.startLoadCookieDestination(
+ print_preview.Destination.GooglePromotedId.DOCS);
}
},
@@ -204,6 +211,16 @@ Polymer({
});
},
+ /** @private */
+ onLoadingDestinationChange_: function() {
+ if (this.loadingDestination_ || this.noDestinationsFound ||
+ (this.cloudPrintState !== print_preview.CloudPrintState.SIGNED_IN &&
+ this.destination.account !== '')) {
+ return;
+ }
+ this.updateDestination_();
+ },
+
/**
* @param {!CustomEvent<string>} e Event containing the new selected value.
* @private
@@ -223,20 +240,15 @@ Polymer({
/** @private */
onDialogClose_: function() {
- // Reset the select value in case the user dismissed the dialog without
+ // Reset the select value if the user dismissed the dialog without
// selecting a new destination.
if (this.destination) {
- this.$.destinationSelect.updateDestination();
+ this.updateDestination_();
}
this.$.destinationSelect.focus();
},
- /** @private */
- onLoadingDestinationChange_: function() {
- if (this.loadingDestination_) {
- return;
- }
-
+ updateDestination_: function() {
// TODO (rbpotter): Remove this conditional when the Polymer 2 migration
// is completed.
if (Polymer.DomIf) {
diff --git a/chromium/chrome/browser/resources/print_preview/new/model.js b/chromium/chrome/browser/resources/print_preview/new/model.js
index 6635130f817..74972831a02 100644
--- a/chromium/chrome/browser/resources/print_preview/new/model.js
+++ b/chromium/chrome/browser/resources/print_preview/new/model.js
@@ -317,7 +317,7 @@ Polymer({
'updateSettingsFromDestination_(destination.capabilities)',
'updateSettingsAvailabilityFromDocumentSettings_(' +
'documentSettings.isModifiable, documentSettings.hasCssMediaStyles,' +
- 'documentSettings.hasSelection, documentSettings.isScalingDisabled)',
+ 'documentSettings.hasSelection)',
'updateHeaderFooterAvailable_(' +
'margins, settings.margins.value, ' +
'settings.customMargins.value, settings.mediaSize.value)',
@@ -412,11 +412,8 @@ Polymer({
this.set('settings.fitToPage.unavailableValue', !isSaveAsPDF);
this.set(
'settings.fitToPage.available',
- !knownSizeToSaveAsPdf && !this.documentSettings.isModifiable &&
- !this.documentSettings.isScalingDisabled);
- this.set(
- 'settings.scaling.available',
- !knownSizeToSaveAsPdf && !this.documentSettings.isScalingDisabled);
+ !knownSizeToSaveAsPdf && !this.documentSettings.isModifiable);
+ this.set('settings.scaling.available', !knownSizeToSaveAsPdf);
const caps = (!!this.destination && !!this.destination.capabilities) ?
this.destination.capabilities.printer :
null;
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_page.html b/chromium/chrome/browser/resources/settings/people_page/sync_page.html
index d4cd3360215..96403b98cce 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_page.html
@@ -243,9 +243,11 @@
</paper-icon-button-light>
</a>
- <a class$="inherit-color no-outline
- [[getListItemClass_(unifiedConsentEnabled)]]" tabindex="-1"
- target="_blank" href="$i18n{syncDashboardUrl}">
+ <a id="syncDashboardLink"
+ class$="inherit-color no-outline
+ [[getListItemClass_(unifiedConsentEnabled)]]"
+ tabindex="-1" target="_blank" href="$i18n{syncDashboardUrl}"
+ hidden="[[syncStatus.supervisedUser]]">
<div class="start settings-box-text">
$i18n{manageSyncedDataTitle}
</div>
@@ -273,15 +275,19 @@
<div id="encryptionRadioGroupContainer" class="list-frame"
hidden="[[syncPrefs.passphraseRequired]]">
- <cr-radio-group disabled$="[[syncPrefs.encryptAllData]]"
+ <cr-radio-group
+ id="encryptionRadioGroup"
selected="[[selectedEncryptionRadio_(
syncPrefs.passphraseTypeIsCustom)]]"
- on-selected-changed="onEncryptionRadioSelectionChanged_">
+ on-selected-changed="onEncryptionRadioSelectionChanged_"
+ disabled$="[[disableEncryptionOptions_]]">
<cr-radio-button name="encrypt-with-google" class="list-item"
- aria-label="$i18n{encryptWithGoogleCredentialsLabel}">
+ aria-label="$i18n{encryptWithGoogleCredentialsLabel}"
+ disabled$="[[disableEncryptionOptions_]]">
$i18n{encryptWithGoogleCredentialsLabel}
</cr-radio-button>
- <cr-radio-button name="encrypt-with-passphrase" class="list-item">
+ <cr-radio-button name="encrypt-with-passphrase" class="list-item"
+ disabled$="[[disableEncryptionOptions_]]">
<span hidden="[[!syncPrefs.fullEncryptionBody]]">
[[syncPrefs.fullEncryptionBody]]
</span>
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_page.js b/chromium/chrome/browser/resources/settings/people_page/sync_page.js
index e57935a7535..ae8ffa13afe 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_page.js
@@ -147,24 +147,45 @@ Polymer({
type: Boolean,
value: false,
},
+
+ disableEncryptionOptions_: {
+ type: Boolean,
+ computed: 'computeDisableEncryptionOptions_(' +
+ 'syncPrefs, syncStatus)',
+ },
},
/** @private {?settings.SyncBrowserProxy} */
browserProxy_: null,
/**
- * The unload callback is needed because the sign-in flow needs to know
- * if the user has closed the tab with the sync settings. This property is
- * non-null if the user is currently navigated on the sync settings route.
+ * If unified consent is enabled, the beforeunload callback is used to
+ * show the 'Leave site' dialog. This makes sure that the user has the chance
+ * to go back and confirm the sync opt-in before leaving.
*
- * TODO(crbug.com/862983): When unified consent is rolled out to 100% this
- * should be removed.
+ * If unified consent is disabled, the beforeunload callback is used
+ * to confirm the sync setup before leaving the opt-in flow.
+ *
+ * This property is non-null if the user is currently navigated on the sync
+ * settings route.
*
* @private {?Function}
*/
beforeunloadCallback_: null,
/**
+ * If unified consent is enabled, the unload callback is used to cancel the
+ * sync setup when the user hits the browser back button after arriving on the
+ * page.
+ * Note: Cases like closing the tab or reloading don't need to be handled,
+ * because they are already caught in |PeopleHandler::~PeopleHandler|
+ * from the C++ code.
+ *
+ * @private {?Function}
+ */
+ unloadCallback_: null,
+
+ /**
* Whether the initial layout for collapsible sections has been computed. It
* is computed only once, the first time the sync status is updated.
* @private {boolean}
@@ -179,10 +200,10 @@ Polymer({
didAbort_: false,
/**
- * Whether the user clicked the confirm button on the "Cancel sync?" dialog.
+ * Whether the user confirmed the cancellation of sync.
* @private {boolean}
*/
- setupCancelDialogConfirmed_: false,
+ setupCancelConfirmed_: false,
/** @override */
created: function() {
@@ -211,6 +232,10 @@ Polymer({
window.removeEventListener('beforeunload', this.beforeunloadCallback_);
this.beforeunloadCallback_ = null;
}
+ if (this.unloadCallback_) {
+ window.removeEventListener('unload', this.unloadCallback_);
+ this.unloadCallback_ = null;
+ }
},
/**
@@ -250,7 +275,7 @@ Polymer({
/** @private */
onSetupCancelDialogConfirm_: function() {
- this.setupCancelDialogConfirmed_ = true;
+ this.setupCancelConfirmed_ = true;
this.$$('#setupCancelDialog').close();
settings.navigateTo(settings.routes.BASIC);
chrome.metricsPrivate.recordUserAction(
@@ -267,11 +292,13 @@ Polymer({
if (settings.getCurrentRoute() == settings.routes.SYNC) {
this.onNavigateToPage_();
} else if (!settings.routes.SYNC.contains(settings.getCurrentRoute())) {
- // When the user wants to cancel the sync setup, but hasn't confirmed
- // the cancel dialog, navigate back and show the dialog.
+ // When the user is about to cancel the sync setup, but hasn't confirmed
+ // the cancellation, navigate back and show the 'Cancel sync?' dialog.
if (this.unifiedConsentEnabled && this.syncStatus &&
!!this.syncStatus.setupInProgress && this.didAbort_ &&
- !this.setupCancelDialogConfirmed_) {
+ !this.setupCancelConfirmed_) {
+ chrome.metricsPrivate.recordUserAction(
+ 'Signin_Signin_BackOnAdvancedSyncSettings');
// Yield so that other |currentRouteChanged| observers are called,
// before triggering another navigation (and another round of observers
// firing). Triggering navigation from within an observer leads to some
@@ -284,7 +311,7 @@ Polymer({
this.$$('#setupCancelDialog').showModal();
});
} else {
- this.setupCancelDialogConfirmed_ = false;
+ this.setupCancelConfirmed_ = false;
this.onNavigateAwayFromPage_();
}
}
@@ -314,8 +341,27 @@ Polymer({
this.browserProxy_.didNavigateToSyncPage();
- this.beforeunloadCallback_ = this.onNavigateAwayFromPage_.bind(this);
- window.addEventListener('beforeunload', this.beforeunloadCallback_);
+ if (this.unifiedConsentEnabled) {
+ this.beforeunloadCallback_ = event => {
+ // When the user tries to leave the sync setup, show the 'Leave site'
+ // dialog.
+ if (this.unifiedConsentEnabled && this.syncStatus &&
+ !!this.syncStatus.setupInProgress) {
+ event.preventDefault();
+ event.returnValue = '';
+
+ chrome.metricsPrivate.recordUserAction(
+ 'Signin_Signin_AbortAdvancedSyncSettings');
+ }
+ };
+ window.addEventListener('beforeunload', this.beforeunloadCallback_);
+
+ this.unloadCallback_ = this.onNavigateAwayFromPage_.bind(this);
+ window.addEventListener('unload', this.unloadCallback_);
+ } else {
+ this.beforeunloadCallback_ = this.onNavigateAwayFromPage_.bind(this);
+ window.addEventListener('beforeunload', this.beforeunloadCallback_);
+ }
},
/** @private */
@@ -333,6 +379,11 @@ Polymer({
window.removeEventListener('beforeunload', this.beforeunloadCallback_);
this.beforeunloadCallback_ = null;
+
+ if (this.unloadCallback_) {
+ window.removeEventListener('unload', this.unloadCallback_);
+ this.unloadCallback_ = null;
+ }
},
/**
@@ -343,8 +394,12 @@ Polymer({
this.syncPrefs = syncPrefs;
this.pageStatus_ = settings.PageStatus.CONFIGURE;
- // Hide the new passphrase box if the sync data has been encrypted.
- if (this.syncPrefs.encryptAllData) {
+ // Hide the new passphrase box if (a) full data encryption is enabled,
+ // (b) encrypting all data is not allowed (so far, only applies to
+ // supervised accounts), or (c) the user is a supervised account.
+ if (this.syncPrefs.encryptAllData ||
+ !this.syncPrefs.encryptAllDataAllowed ||
+ (this.syncStatus && this.syncStatus.supervisedUser)) {
this.creatingNewPassphrase_ = false;
}
@@ -578,6 +633,25 @@ Polymer({
!!this.syncPrefs.passphraseRequired;
},
+ /**
+ * Whether we should disable the radio buttons that allow choosing the
+ * encryption options for Sync.
+ * We disable the buttons if:
+ * (a) full data encryption is enabled, or,
+ * (b) full data encryption is not allowed (so far, only applies to
+ * supervised accounts), or,
+ * (c) the user is a supervised account.
+ * @return {boolean}
+ * @private
+ */
+ computeDisableEncryptionOptions_: function() {
+ return !!(
+ (this.syncPrefs &&
+ (this.syncPrefs.encryptAllData ||
+ !this.syncPrefs.encryptAllDataAllowed)) ||
+ (this.syncStatus && this.syncStatus.supervisedUser));
+ },
+
/** @private */
onSyncAdvancedTap_: function() {
settings.navigateTo(settings.routes.SYNC_ADVANCED);
@@ -617,6 +691,7 @@ Polymer({
chrome.metricsPrivate.recordUserAction(
'Signin_Signin_ConfirmAdvancedSyncSettings');
} else {
+ this.setupCancelConfirmed_ = true;
chrome.metricsPrivate.recordUserAction(
'Signin_Signin_CancelAdvancedSyncSettings');
}
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js b/chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
index 8bd134c5788..5963d59e048 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
@@ -96,6 +96,8 @@ const PrinterSetupResult = {
INVALID_PPD: 11,
PPD_NOT_FOUND: 12,
PPD_UNRETRIEVABLE: 13,
+ DBUS_NO_REPLY: 64,
+ DBUS_TIMEOUT: 65,
};
/**
diff --git a/chromium/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html b/chromium/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
index 0f97022e56c..c88537c4643 100644
--- a/chromium/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
+++ b/chromium/chrome/browser/resources/welcome/onboarding_welcome/set_as_default/nux_set_as_default.html
@@ -34,6 +34,7 @@
content: -webkit-image-set(
url(../images/set_as_default_illustration_1x.png) 1x,
url(../images/set_as_default_illustration_2x.png) 2x);
+ margin: auto;
width: 454px;
}
@@ -76,7 +77,7 @@
<div class="logo"></div>
<h1 tabindex="-1">$i18n{setDefaultHeader}</h1>
<h2>$i18n{setDefaultSubHeader}</h2>
- <div class="illustration"></div>
+ <div class="illustration" aria-hidden="true"></div>
<div class="button-bar">
<paper-button id="decline-button" on-click="onDeclineClick_">
$i18n{setDefaultSkip}
diff --git a/chromium/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html b/chromium/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html
index 07e92723a92..f9e2430efc8 100644
--- a/chromium/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html
+++ b/chromium/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html
@@ -20,19 +20,20 @@
box-shadow: 0 1px 2px 0 rgba(0, 36, 100, .3),
0 3px 6px 2px rgba(0, 36, 100, .15);
box-sizing: border-box;
+ cursor: pointer;
display: inline-flex;
flex-direction: column;
font-family: inherit;
- height: 84px;
+ height: 5.25rem;
justify-content: center;
outline: 0;
position: relative;
vertical-align: bottom;
- width: 104px;
+ width: 6.5rem;
}
.option:not(:first-of-type) {
- margin-inline-start: 24px;
+ margin-inline-start: 1.5rem;
}
.option.keyboard-focused:focus {
@@ -51,18 +52,23 @@
background-position: center;
background-repeat: no-repeat;
background-size: contain;
- height: 32px;
+ height: 2rem;
margin: auto;
- width: 32px;
+ width: 2rem;
}
.option .option-icon-shadow {
background-color: var(--google-grey-refresh-100);
border-radius: 50%;
display: flex;
- height: 48px;
- margin-bottom: 4px;
- width: 48px;
+ height: 3rem;
+ margin-bottom: 0.25rem;
+ width: 3rem;
+ }
+
+ :host-context([dir=rtl]) .option iron-icon {
+ left: 0.375rem;
+ right: unset;
}
.option iron-icon {
@@ -70,12 +76,12 @@
background: lightgrey;
border-radius: 50%;
display: none;
- height: 12px;
+ height: 0.75rem;
margin: 0;
position: absolute;
- right: 6px;
- top: 6px;
- width: 12px;
+ right: 0.375rem;
+ top: 0.375rem;
+ width: 0.75rem;
}
.option.keyboard-focused:focus iron-icon[icon='cr:check'],
@@ -97,14 +103,18 @@
.button-bar {
display: flex;
justify-content: space-between;
- margin-top: 64px;
+ margin-top: 4rem;
+ }
+
+ :host-context([dir=rtl]) iron-icon[icon='cr:chevron-right'] {
+ transform: scaleX(-1);
}
iron-icon[icon='cr:chevron-right'] {
- height: 20px;
- margin-left: 6px;
- margin-right: -10px;
- width: 20px;
+ height: 1.25rem;
+ margin-inline-end: -0.625rem;
+ margin-inline-start: 0.375rem;
+ width: 1.25rem;
}
</style>
</template>
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
index 6d88ecc4029..6f4a3e8186a 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
@@ -30,7 +30,7 @@ bool TouchSupportAvailable(const display::Display& display) {
}
// TODO(felixe): More context at crbug.com/738885
-const uint16_t kDeviceIds[] = {0x0457, 0x266e};
+const uint16_t kDeviceIds[] = {0x0457, 0x266e, 0x222a};
// Returns true if |vendor_id| is a valid vendor id that may be made the primary
// display.
diff --git a/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index ff1c8c4bc25..e658f7fc05f 100644
--- a/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -433,7 +433,8 @@ void NetInternalsMessageHandler::OnStoreDebugLogs(const base::ListValue* list) {
base::FilePath policies_path = path.Append("policies.json");
std::string json_policies = policy::GetAllPolicyValuesAsJSON(
web_ui()->GetWebContents()->GetBrowserContext(),
- true /* with_user_policies */, false /* with device identity */);
+ true /* with_user_policies */, false /* with device identity */,
+ true /* is_pretty_print */);
base::PostTaskWithTraitsAndReply(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
diff --git a/chromium/chrome/browser/ui/webui/policy_ui_handler.cc b/chromium/chrome/browser/ui/webui/policy_ui_handler.cc
index 030562d894c..4b9774e0025 100644
--- a/chromium/chrome/browser/ui/webui/policy_ui_handler.cc
+++ b/chromium/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -844,7 +844,8 @@ void PolicyUIHandler::SendPolicyNames() const {
void PolicyUIHandler::SendPolicyValues() const {
base::Value all_policies = policy::GetAllPolicyValuesAsDictionary(
web_ui()->GetWebContents()->GetBrowserContext(),
- true /* with_user_policies */, true /* convert_values */);
+ true /* with_user_policies */, true /* convert_values */,
+ true /* is_pretty_print */);
web_ui()->CallJavascriptFunctionUnsafe("policy.Page.setPolicyValues",
all_policies);
}
@@ -921,7 +922,8 @@ void PolicyUIHandler::WritePoliciesToJSONFile(
const base::FilePath& path) const {
std::string json_policies = policy::GetAllPolicyValuesAsJSON(
web_ui()->GetWebContents()->GetBrowserContext(),
- true /* with_user_policies */, false /* with device identity */);
+ true /* with_user_policies */, false /* with device identity */,
+ true /* is_pretty_print */);
base::PostTaskWithTraits(
FROM_HERE,
diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
index 81bd450d999..17cac053ea8 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -219,7 +219,9 @@ void LocalPrinterHandlerChromeos::HandlePrinterSetup(
case chromeos::PrinterSetupResult::kFatalError:
case chromeos::PrinterSetupResult::kNativePrintersNotAllowed:
case chromeos::PrinterSetupResult::kInvalidPrinterUpdate:
- LOG(ERROR) << "Unexpected error in printer setup." << result;
+ case chromeos::PrinterSetupResult::kDbusNoReply:
+ case chromeos::PrinterSetupResult::kDbusTimeout:
+ LOG(ERROR) << "Unexpected error in printer setup. " << result;
break;
case chromeos::PrinterSetupResult::kMaxValue:
NOTREACHED() << "This value is not expected";
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index 7932d706c9e..440b61401c3 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -700,6 +700,12 @@ void CupsPrintersHandler::OnAddedPrinterCommon(const Printer& printer,
PRINTER_LOG(ERROR)
<< "Requested printer changes would make printer unusable";
break;
+ case PrinterSetupResult::kDbusNoReply:
+ PRINTER_LOG(ERROR) << "Couldn't talk to debugd over D-Bus.";
+ break;
+ case PrinterSetupResult::kDbusTimeout:
+ PRINTER_LOG(ERROR) << "Timed out trying to reach debugd over D-Bus.";
+ break;
case PrinterSetupResult::kMaxValue:
NOTREACHED() << "This is not an expected value";
break;
diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler.cc b/chromium/chrome/browser/ui/webui/settings/people_handler.cc
index e92cea80ce7..7c368a6df80 100644
--- a/chromium/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/people_handler.cc
@@ -12,6 +12,8 @@
#include "base/i18n/time_formatting.h"
#include "base/json/json_reader.h"
#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/lifetime/application_lifetime.h"
@@ -215,8 +217,11 @@ PeopleHandler::~PeopleHandler() {
if (!web_ui())
return;
- // Note that if the user left the sync page by closing the tab, refresh,
- // or via the back navigation, it would first go through OnDidClosePage().
+ // If unified consent is enabled and the user left the sync page by closing
+ // the tab, refresh, or via the back navigation, the sync setup needs to be
+ // closed. If this was the first time setup, sync will be cancelled.
+ // Note, if unified consent is disabled, it will first go through
+ // |OnDidClosePage()|.
CloseSyncSetup();
}
@@ -546,8 +551,10 @@ void PeopleHandler::HandleSetEncryption(const base::ListValue* args) {
// Don't allow "encrypt all" if the SyncService doesn't allow it.
// The UI is hidden, but the user may have enabled it e.g. by fiddling with
// the web inspector.
- if (!service->GetUserSettings()->IsEncryptEverythingAllowed())
+ if (!service->GetUserSettings()->IsEncryptEverythingAllowed()) {
configuration.encrypt_all = false;
+ configuration.set_new_passphrase = false;
+ }
// Note: Data encryption will not occur until configuration is complete
// (when the PSS receives its CONFIGURE_DONE notification from the sync
@@ -616,6 +623,9 @@ void PeopleHandler::HandleShowSetupUI(const base::ListValue* args) {
GetLoginUIService()->SetLoginUI(this);
+ // Observe the web contents for a before unload event.
+ Observe(web_ui()->GetWebContents());
+
PushSyncPrefs();
// Always let the page open when unified consent is enabled.
return;
@@ -832,6 +842,9 @@ void PeopleHandler::CloseSyncSetup() {
sync_blocker_.reset();
configuring_sync_ = false;
+
+ // Stop observing the web contents.
+ Observe(nullptr);
}
void PeopleHandler::InitializeSyncBlocker() {
@@ -876,6 +889,16 @@ void PeopleHandler::OnStateChanged(syncer::SyncService* sync) {
PushSyncPrefs();
}
+void PeopleHandler::BeforeUnloadDialogCancelled() {
+ // The before unload dialog is only shown during the first sync setup.
+ DCHECK(IdentityManagerFactory::GetForProfile(profile_)->HasPrimaryAccount());
+ syncer::SyncService* service = GetSyncService();
+ DCHECK(service && service->IsFirstSetupInProgress());
+
+ base::RecordAction(
+ base::UserMetricsAction("Signin_Signin_CancelAbortAdvancedSyncSettings"));
+}
+
std::unique_ptr<base::DictionaryValue>
PeopleHandler::GetSyncStatusDictionary() {
std::unique_ptr<base::DictionaryValue> sync_status(new base::DictionaryValue);
diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler.h b/chromium/chrome/browser/ui/webui/settings/people_handler.h
index 37e540233c2..e4748f7864f 100644
--- a/chromium/chrome/browser/ui/webui/settings/people_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/people_handler.h
@@ -22,6 +22,7 @@
#include "components/prefs/pref_change_registrar.h"
#include "components/signin/core/browser/signin_buildflags.h"
#include "components/sync/driver/sync_service_observer.h"
+#include "content/public/browser/web_contents_observer.h"
#include "services/identity/public/cpp/identity_manager.h"
class LoginUIService;
@@ -45,7 +46,8 @@ class PeopleHandler : public SettingsPageUIHandler,
public identity::IdentityManager::Observer,
public SyncStartupTracker::Observer,
public LoginUIService::LoginUI,
- public syncer::SyncServiceObserver {
+ public syncer::SyncServiceObserver,
+ public content::WebContentsObserver {
public:
// TODO(tommycli): Remove these strings and instead use WebUIListener events.
// These string constants are used from JavaScript (sync_browser_proxy.js).
@@ -137,6 +139,8 @@ class PeopleHandler : public SettingsPageUIHandler,
// syncer::SyncServiceObserver implementation.
void OnStateChanged(syncer::SyncService* sync) override;
+ // content::WebContentsObserver implementation
+ void BeforeUnloadDialogCancelled() override;
// Returns a newly created dictionary with a number of properties that
// correspond to the status of sync.
diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 7ef14432f17..a4fe434142c 100644
--- a/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -731,6 +731,8 @@ TEST_F(PeopleHandlerTest, SetNewCustomPassphrase) {
base::ListValue list_args;
list_args.AppendString(kTestCallbackId);
list_args.AppendString(args);
+ ON_CALL(*mock_pss_->GetUserSettingsMock(), IsEncryptEverythingAllowed())
+ .WillByDefault(Return(true));
ON_CALL(*mock_pss_->GetUserSettingsMock(),
IsPassphraseRequiredForDecryption())
.WillByDefault(Return(false));
@@ -1067,11 +1069,6 @@ TEST_F(PeopleHandlerTest, ShowSetupEncryptAllDisallowed) {
}
TEST_F(PeopleHandlerTest, TurnOnEncryptAllDisallowed) {
- std::string args = GetConfiguration(
- NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_ALL_DATA);
- base::ListValue list_args;
- list_args.AppendString(kTestCallbackId);
- list_args.AppendString(args);
ON_CALL(*mock_pss_->GetUserSettingsMock(),
IsPassphraseRequiredForDecryption())
.WillByDefault(Return(false));
@@ -1080,8 +1077,20 @@ TEST_F(PeopleHandlerTest, TurnOnEncryptAllDisallowed) {
SetupInitializedProfileSyncService();
ON_CALL(*mock_pss_->GetUserSettingsMock(), IsEncryptEverythingAllowed())
.WillByDefault(Return(false));
+
+ base::DictionaryValue dict;
+ dict.SetBoolean("setNewPassphrase", true);
+ std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(),
+ "password", ENCRYPT_ALL_DATA);
+ base::ListValue list_args;
+ list_args.AppendString(kTestCallbackId);
+ list_args.AppendString(args);
+
EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), EnableEncryptEverything())
.Times(0);
+ EXPECT_CALL(*mock_pss_->GetUserSettingsMock(), SetEncryptionPassphrase(_))
+ .Times(0);
+
handler_->HandleSetEncryption(&list_args);
ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
diff --git a/chromium/chrome/browser/ui/webui/welcome/nux_helper.cc b/chromium/chrome/browser/ui/webui/welcome/nux_helper.cc
index e1cb081e069..05132e5ae81 100644
--- a/chromium/chrome/browser/ui/webui/welcome/nux_helper.cc
+++ b/chromium/chrome/browser/ui/webui/welcome/nux_helper.cc
@@ -77,8 +77,10 @@ bool IsNuxOnboardingEnabled(Profile* profile) {
return false;
}
- // TODO(hcarmona): Re-enable synthetic trial reporting when we know more
- // about https://crbug.com/919705
+ // User will be tied to their original onboarding group, even after
+ // experiment ends.
+ ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
+ "NaviOnboardingSynthetic", onboard_group);
if (base::FeatureList::IsEnabled(nux::kNuxOnboardingFeature)) {
return true;
diff --git a/chromium/chrome/test/BUILD.gn b/chromium/chrome/test/BUILD.gn
index 101b6f34dce..7644572ee8f 100644
--- a/chromium/chrome/test/BUILD.gn
+++ b/chromium/chrome/test/BUILD.gn
@@ -929,6 +929,7 @@ test("browser_tests") {
"../browser/ui/search/local_ntp_js_browsertest.cc",
"../browser/ui/search/local_ntp_one_google_bar_browsertest.cc",
"../browser/ui/search/local_ntp_promos_browsertest.cc",
+ "../browser/ui/search/local_ntp_suggestions_browsertest.cc",
"../browser/ui/search/local_ntp_voice_search_browsertest.cc",
"../browser/ui/search/new_tab_page_navigation_throttle_browsertest.cc",
"../browser/ui/search_engines/search_engine_tab_helper_browsertest.cc",
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index 46afe629e70..9cf6e445d70 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -335,6 +335,13 @@ jumbo_static_library("browser") {
]
}
+ if (!is_android && !is_ios) {
+ deps += [
+ "//ui/native_theme",
+ "//ui/native_theme:native_theme_browser",
+ ]
+ }
+
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
}
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index f1f617296f1..2f40e6d1911 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -29,6 +29,10 @@
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/base/l10n/l10n_util.h"
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "ui/native_theme/native_theme.h" // nogncheck
+#endif
+
namespace autofill {
namespace {
@@ -352,8 +356,16 @@ void AutofillExternalDelegate::ApplyAutofillOptions(
suggestions->back().frontend_id = POPUP_ITEM_ID_AUTOFILL_OPTIONS;
// On Android and Desktop, Google Pay branding is shown along with Settings.
// So Google Pay Icon is just attached to an existing menu item.
- if (is_all_server_suggestions)
+ if (is_all_server_suggestions) {
+#if defined(OS_ANDROID) || defined(OS_IOS)
suggestions->back().icon = base::ASCIIToUTF16("googlePay");
+#else
+ suggestions->back().icon = base::ASCIIToUTF16(
+ ui::NativeTheme::GetInstanceForNativeUi()->SystemDarkModeEnabled()
+ ? "googlePayDark"
+ : "googlePay");
+#endif
+ }
// On iOS, GooglePayIcon comes at the begining and hence prepended to the list.
#if defined(OS_IOS)
diff --git a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
index e323c47c3e9..72283a3d514 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
@@ -713,9 +713,11 @@ TEST_F(AutofillAgentTests, FrameInitializationOrderFrames) {
test_web_state_.RemoveWebFrame(fake_main_frame_->GetFrameId());
// Both frames available, then page loaded.
+ test_web_state_.SetLoading(true);
auto main_frame_unique =
std::make_unique<web::FakeWebFrame>("main", true, GURL());
web::FakeWebFrame* main_frame = main_frame_unique.get();
+ test_web_state_.AddWebFrame(std::move(main_frame_unique));
autofill::AutofillDriverIOS* main_frame_driver =
autofill::AutofillDriverIOS::FromWebStateAndWebFrame(&test_web_state_,
main_frame);
@@ -725,13 +727,11 @@ TEST_F(AutofillAgentTests, FrameInitializationOrderFrames) {
EXPECT_TRUE(main_frame_driver->is_processed());
});
FakeWebFrameCallback* iframe = iframe_unique.get();
+ test_web_state_.AddWebFrame(std::move(iframe_unique));
autofill::AutofillDriverIOS* iframe_driver =
autofill::AutofillDriverIOS::FromWebStateAndWebFrame(&test_web_state_,
iframe);
EXPECT_FALSE(iframe_driver->IsInMainFrame());
- test_web_state_.SetLoading(true);
- test_web_state_.AddWebFrame(std::move(main_frame_unique));
- test_web_state_.AddWebFrame(std::move(iframe_unique));
EXPECT_FALSE(main_frame_driver->is_processed());
EXPECT_FALSE(iframe_driver->is_processed());
test_web_state_.SetLoading(false);
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.h b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
index 2624127f010..f460f3f12c7 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
@@ -80,9 +80,9 @@ class AutofillDriverIOS : public AutofillDriver {
// The WebState with which this object is associated.
web::WebState* web_state_ = nullptr;
- // The WebState with which this object is associated.
- // nullptr if frame messaging is disabled.
- web::WebFrame* web_frame_ = nullptr;
+ // The id of the WebFrame with which this object is associated.
+ // "" if frame messaging is disabled.
+ std::string web_frame_id_;
// AutofillDriverIOSBridge instance that is passed in.
__unsafe_unretained id<AutofillDriverIOSBridge> bridge_;
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
index bba0e29ee9a..ce08c746ecd 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -12,6 +12,7 @@
#include "components/autofill/ios/browser/autofill_switches.h"
#include "ios/web/public/browser_state.h"
#import "ios/web/public/origin_util.h"
+#import "ios/web/public/web_state/web_frame_util.h"
#import "ios/web/public/web_state/web_state.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -63,10 +64,10 @@ AutofillDriverIOS::AutofillDriverIOS(
const std::string& app_locale,
AutofillManager::AutofillDownloadManagerState enable_download_manager)
: web_state_(web_state),
- web_frame_(web_frame),
bridge_(bridge),
autofill_manager_(this, client, app_locale, enable_download_manager),
autofill_external_delegate_(&autofill_manager_, this) {
+ web_frame_id_ = web::GetWebFrameId(web_frame);
autofill_manager_.SetExternalDelegate(&autofill_external_delegate_);
}
@@ -77,7 +78,8 @@ bool AutofillDriverIOS::IsIncognito() const {
}
bool AutofillDriverIOS::IsInMainFrame() const {
- return web_frame_ ? web_frame_->IsMainFrame() : true;
+ web::WebFrame* web_frame = web::GetWebFrameWithId(web_state_, web_frame_id_);
+ return web_frame ? web_frame->IsMainFrame() : true;
}
net::URLRequestContextGetter* AutofillDriverIOS::GetURLRequestContext() {
@@ -98,7 +100,8 @@ void AutofillDriverIOS::SendFormDataToRenderer(
int query_id,
RendererFormDataAction action,
const FormData& data) {
- [bridge_ fillFormData:data inFrame:web_frame_];
+ web::WebFrame* web_frame = web::GetWebFrameWithId(web_state_, web_frame_id_);
+ [bridge_ fillFormData:data inFrame:web_frame];
}
void AutofillDriverIOS::PropagateAutofillPredictions(
@@ -108,8 +111,9 @@ void AutofillDriverIOS::PropagateAutofillPredictions(
void AutofillDriverIOS::SendAutofillTypePredictionsToRenderer(
const std::vector<FormStructure*>& forms) {
+ web::WebFrame* web_frame = web::GetWebFrameWithId(web_state_, web_frame_id_);
[bridge_ fillFormDataPredictions:FormStructure::GetFieldTypePredictions(forms)
- inFrame:web_frame_];
+ inFrame:web_frame];
}
void AutofillDriverIOS::RendererShouldAcceptDataListSuggestion(
diff --git a/chromium/components/autofill_assistant/browser/service.cc b/chromium/components/autofill_assistant/browser/service.cc
index b9cfb7ebfdb..f07ca76dee6 100644
--- a/chromium/components/autofill_assistant/browser/service.cc
+++ b/chromium/components/autofill_assistant/browser/service.cc
@@ -90,6 +90,7 @@ Service::Service(const std::string& api_key,
url::StringPieceReplacements<std::string> action_replacements;
action_replacements.SetPathStr(kActionEndpoint);
script_action_server_url_ = server_url.ReplaceComponents(action_replacements);
+ VLOG(1) << "Using script domain " << script_action_server_url_.host();
}
Service::~Service() {}
diff --git a/chromium/components/autofill_assistant/browser/web_controller.cc b/chromium/components/autofill_assistant/browser/web_controller.cc
index b3135e7d40c..4880a18589f 100644
--- a/chromium/components/autofill_assistant/browser/web_controller.cc
+++ b/chromium/components/autofill_assistant/browser/web_controller.cc
@@ -1436,10 +1436,10 @@ void WebController::OnGetElementPositionResult(
float visual_h = static_cast<float>(list[7].GetDouble());
RectF rect;
- rect.left = std::max(0.0f, left_layout - visual_left_offset) / visual_w;
- rect.top = std::max(0.0f, top_layout - visual_top_offset) / visual_h;
- rect.right = std::max(0.0f, right_layout - visual_left_offset) / visual_w;
- rect.bottom = std::max(0.0f, bottom_layout - visual_top_offset) / visual_h;
+ rect.left = (left_layout - visual_left_offset) / visual_w;
+ rect.top = (top_layout - visual_top_offset) / visual_h;
+ rect.right = (right_layout - visual_left_offset) / visual_w;
+ rect.bottom = (bottom_layout - visual_top_offset) / visual_h;
std::move(callback).Run(true, rect);
}
diff --git a/chromium/components/certificate_transparency/data/log_list.json b/chromium/components/certificate_transparency/data/log_list.json
index 17e4b37f8ae..802887002f6 100644
--- a/chromium/components/certificate_transparency/data/log_list.json
+++ b/chromium/components/certificate_transparency/data/log_list.json
@@ -41,6 +41,46 @@
"dns_api_endpoint": "argon2021.ct.googleapis.com"
},
{
+ "description": "Google 'Xenon2019' log",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/XyDwqzXL9i2GTjMYkqaEyiRL0Dy9sHq/BTebFdshbvCaXXEh6mjUK0Yy+AsDcI4MpzF1l7Kded2MD5zi420gA==",
+ "url": "ct.googleapis.com/logs/xenon2019/",
+ "maximum_merge_delay": 86400,
+ "operated_by": [
+ 0
+ ],
+ "dns_api_endpoint": "xenon2019.ct.googleapis.com"
+ },
+ {
+ "description": "Google 'Xenon2020' log",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZU75VqjyzSTgFZKAnWg1QeYfFFIRZTMK7q3kWWZsmHhQdrBYnHRZ3OA4kUeUx0JN+xX+dSgt1ruqUhhl7jOvmw==",
+ "url": "ct.googleapis.com/logs/xenon2020/",
+ "maximum_merge_delay": 86400,
+ "operated_by": [
+ 0
+ ],
+ "dns_api_endpoint": "xenon2020.ct.googleapis.com"
+ },
+ {
+ "description": "Google 'Xenon2021' log",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAER+1MInu8Q39BwDZ5Rp9TwXhwm3ktvgJzpk/r7dDgGk7ZacMm3ljfcoIvP1E72T8jvyLT1bvdapylajZcTH6W5g==",
+ "url": "ct.googleapis.com/logs/xenon2021/",
+ "maximum_merge_delay": 86400,
+ "operated_by": [
+ 0
+ ],
+ "dns_api_endpoint": "xenon2021.ct.googleapis.com"
+ },
+ {
+ "description": "Google 'Xenon2022' log",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+WS9FSxAYlCVEzg8xyGwOrmPonoV14nWjjETAIdZvLvukPzIWBMKv6tDNlQjpIHNrUcUt1igRPpqoKDXw2MeKw==",
+ "url": "ct.googleapis.com/logs/xenon2022/",
+ "maximum_merge_delay": 86400,
+ "operated_by": [
+ 0
+ ],
+ "dns_api_endpoint": "xenon2022.ct.googleapis.com"
+ },
+ {
"description": "Google 'Aviator' log",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1/TMabLkDpCjiupacAlP7xNi0I1JYP8bQFAHDG1xhtolSY1l4QgNRzRrvSe8liE+NPWHdjGxfx3JhTsN9x8/6Q==",
"url": "ct.googleapis.com/aviator/",
@@ -264,6 +304,7 @@
"operated_by": [
2
],
+ "disqualified_at": 1550275200,
"dns_api_endpoint": "symantec.ct.googleapis.com"
},
{
@@ -274,6 +315,7 @@
"operated_by": [
2
],
+ "disqualified_at": 1550275200,
"dns_api_endpoint": "symantec-vega.ct.googleapis.com"
},
{
@@ -284,6 +326,7 @@
"operated_by": [
2
],
+ "disqualified_at": 1550275200,
"dns_api_endpoint": "symantec-sirius.ct.googleapis.com"
},
{
diff --git a/chromium/components/crash/android/java/src/org/chromium/components/crash/browser/PackagePaths.java b/chromium/components/crash/android/java/src/org/chromium/components/crash/browser/PackagePaths.java
index 9b621c4801b..115f082669b 100644
--- a/chromium/components/crash/android/java/src/org/chromium/components/crash/browser/PackagePaths.java
+++ b/chromium/components/crash/android/java/src/org/chromium/components/crash/browser/PackagePaths.java
@@ -56,6 +56,17 @@ public abstract class PackagePaths {
File parent = new File(pi.applicationInfo.nativeLibraryDir).getParentFile();
if (parent != null) {
libPaths.add(new File(parent, arch).getPath());
+
+ // arch is the currently loaded library's ABI name. This is the name of the library
+ // directory in an APK, but may differ from the library directory extracted to the
+ // filesystem. ARM family abi names have a suffix specifying the architecture
+ // version, but may be extracted to directories named "arm64" or "arm".
+ // crbug.com/930342
+ if (arch.startsWith("arm64")) {
+ libPaths.add(new File(parent, "arm64").getPath());
+ } else if (arch.startsWith("arm")) {
+ libPaths.add(new File(parent, "arm").getPath());
+ }
}
for (String zip : zipPaths) {
if (zip.endsWith(".apk")) {
diff --git a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
index 8be2989609a..793067d82a7 100644
--- a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
+++ b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
@@ -75,6 +75,14 @@ void DataReductionProxyURLLoaderThrottle::BeforeWillProcessResponse(
if (params::IsWarmupURL(response_url))
return;
+ MaybeRetry(proxy_server, response_head.headers.get(), net::OK, defer);
+}
+
+void DataReductionProxyURLLoaderThrottle::MaybeRetry(
+ const net::ProxyServer& proxy_server,
+ const net::HttpResponseHeaders* headers,
+ net::Error net_error,
+ bool* defer) {
// The set of data reduction proxy servers to mark as bad prior to
// restarting the request.
std::vector<net::ProxyServer> bad_proxies;
@@ -82,10 +90,6 @@ void DataReductionProxyURLLoaderThrottle::BeforeWillProcessResponse(
// TODO(https://crbug.com/721403): Implement retry due to authentication
// failure.
- // TODO(https://crbug.com/721403): Should be calling this for cases where the
- // request failed with an error too.
- net::Error net_error = net::OK;
-
// TODO(https://crbug.com/721403): Need the actual bad proxies map. Since
// this is only being used for some metrics logging not a big deal.
net::ProxyRetryInfoMap proxy_retry_info;
@@ -96,8 +100,8 @@ void DataReductionProxyURLLoaderThrottle::BeforeWillProcessResponse(
DataReductionProxyBypassProtocol protocol;
pending_restart_ = protocol.MaybeBypassProxyAndPrepareToRetry(
- request_method_, url_chain_, response_head.headers.get(),
- response_head.proxy_server, net_error, proxy_retry_info,
+ request_method_, url_chain_, headers, proxy_server, net_error,
+ proxy_retry_info,
manager_->FindConfiguredDataReductionProxy(proxy_server), &bypass_type,
&data_reduction_proxy_info, &bad_proxies, &pending_restart_load_flags_);
@@ -129,6 +133,13 @@ void DataReductionProxyURLLoaderThrottle::WillProcessResponse(
is_main_frame_);
}
+void DataReductionProxyURLLoaderThrottle::WillOnCompleteWithError(
+ const network::URLLoaderCompletionStatus& status,
+ bool* defer) {
+ MaybeRetry(status.proxy_server, nullptr,
+ static_cast<net::Error>(status.error_code), defer);
+}
+
void DataReductionProxyURLLoaderThrottle::MarkProxiesAsBad(
const std::vector<net::ProxyServer>& bad_proxies,
base::TimeDelta bypass_duration) {
diff --git a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
index fc461452e78..d8d7edaf02b 100644
--- a/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
+++ b/chromium/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
@@ -45,8 +45,16 @@ class DataReductionProxyURLLoaderThrottle : public content::URLLoaderThrottle {
void WillProcessResponse(const GURL& response_url,
network::ResourceResponseHead* response_head,
bool* defer) override;
+ void WillOnCompleteWithError(const network::URLLoaderCompletionStatus& status,
+ bool* defer) override;
private:
+ // Retry the request bypassing proxies or falling back to next proxy based on
+ // |net_error| and the response headers.
+ void MaybeRetry(const net::ProxyServer& proxy_server,
+ const net::HttpResponseHeaders* headers,
+ net::Error net_error,
+ bool* defer);
// Marks |bad_proxies| to be bypassed for |bypass_duration|. Once that action
// has completed will call OnMarkProxiesAsBadComplete().
void MarkProxiesAsBad(const std::vector<net::ProxyServer>& bad_proxies,
diff --git a/chromium/components/download/public/common/auto_resumption_handler.h b/chromium/components/download/public/common/auto_resumption_handler.h
index a66c8c6a941..14982236837 100644
--- a/chromium/components/download/public/common/auto_resumption_handler.h
+++ b/chromium/components/download/public/common/auto_resumption_handler.h
@@ -40,7 +40,8 @@ class COMPONENTS_DOWNLOAD_EXPORT AutoResumptionHandler
std::unique_ptr<download::TaskManager> task_manager,
std::unique_ptr<Config> config);
- // Returns the singleton instance of the AutoResumptionHandler.
+ // Returns the singleton instance of the AutoResumptionHandler, or nullptr if
+ // initialization is not yet complete.
static AutoResumptionHandler* Get();
AutoResumptionHandler(
diff --git a/chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_it.xtb b/chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_it.xtb
index 26d68d11395..613c86a291e 100644
--- a/chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_it.xtb
+++ b/chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_it.xtb
@@ -8,7 +8,7 @@
<translation id="4115378294792113321">Magenta</translation>
<translation id="5901630391730855834">Giallo</translation>
<translation id="6017514345406065928">Verde</translation>
-<translation id="6042308850641462728">Più</translation>
+<translation id="6042308850641462728">Altro</translation>
<translation id="6727102863431372879">Imposta</translation>
<translation id="7535087603100972091">Valore</translation>
<translation id="7569983096843329377">Nero</translation>
diff --git a/chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_sr.xtb b/chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_sr.xtb
index b1b1b6e814a..3f6e57524e3 100644
--- a/chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_sr.xtb
+++ b/chromium/components/embedder_support/android/java/strings/translations/web_contents_delegate_android_strings_sr.xtb
@@ -8,7 +8,7 @@
<translation id="4115378294792113321">Циклама</translation>
<translation id="5901630391730855834">Жута</translation>
<translation id="6017514345406065928">Зелена</translation>
-<translation id="6042308850641462728">Више</translation>
+<translation id="6042308850641462728">Још</translation>
<translation id="6727102863431372879">Постави</translation>
<translation id="7535087603100972091">Вредност</translation>
<translation id="7569983096843329377">Црна</translation>
diff --git a/chromium/components/feed/core/feed_scheduler_host.cc b/chromium/components/feed/core/feed_scheduler_host.cc
index 4fd86dce3d4..f7a488efa63 100644
--- a/chromium/components/feed/core/feed_scheduler_host.cc
+++ b/chromium/components/feed/core/feed_scheduler_host.cc
@@ -215,10 +215,14 @@ NativeRequestBehavior FeedSchedulerHost::ShouldSessionRequestData(
// completion of all requests. We should never encounter a scenario where only
// the scheduler thinks there is an outstanding request.
- // TODO(skym): Resolve ambiguity around this expectation.
+ // TODO(skym): Update this to use kTimeoutDurationSeconds.
// DCHECK(has_outstanding_request || !tracking_oustanding_request_);
- tracking_oustanding_request_ |= has_outstanding_request;
+ if (outstanding_request_until_.is_null() && has_outstanding_request) {
+ outstanding_request_until_ =
+ clock_->Now() +
+ base::TimeDelta::FromSeconds(kTimeoutDurationSeconds.Get());
+ }
NativeRequestBehavior behavior;
if (ShouldRefresh(TriggerType::kNtpShown)) {
@@ -260,7 +264,7 @@ void FeedSchedulerHost::OnReceiveNewContent(
content_creation_date_time);
TryRun(std::move(fixed_timer_completion_));
ScheduleFixedTimerWakeUp(GetTriggerThreshold(TriggerType::kFixedTimer));
- tracking_oustanding_request_ = false;
+ outstanding_request_until_ = base::Time();
time_until_first_shown_trigger_reported_ = false;
time_until_first_foregrounded_trigger_reported_ = false;
DVLOG(2) << "Received OnReceiveNewContent with time "
@@ -270,7 +274,7 @@ void FeedSchedulerHost::OnReceiveNewContent(
void FeedSchedulerHost::OnRequestError(int network_response_code) {
profile_prefs_->SetTime(prefs::kLastFetchAttemptTime, clock_->Now());
TryRun(std::move(fixed_timer_completion_));
- tracking_oustanding_request_ = false;
+ outstanding_request_until_ = base::Time();
time_until_first_shown_trigger_reported_ = false;
time_until_first_foregrounded_trigger_reported_ = false;
DVLOG(2) << "Received OnRequestError with code " << network_response_code;
@@ -330,7 +334,7 @@ bool FeedSchedulerHost::OnArticlesCleared(bool suppress_refreshes) {
// The Feed will try to drop any outstanding refresh request, so we should
// stop tracking one as well.
- tracking_oustanding_request_ = false;
+ outstanding_request_until_ = base::Time();
if (suppress_refreshes) {
// Due to privacy, we should not fetch for a while (unless the user
@@ -354,7 +358,7 @@ void FeedSchedulerHost::OnEulaAccepted() {
}
bool FeedSchedulerHost::ShouldRefresh(TriggerType trigger) {
- if (tracking_oustanding_request_) {
+ if (clock_->Now() < outstanding_request_until_) {
DVLOG(2) << "Outstanding request stopped refresh from trigger "
<< static_cast<int>(trigger);
return false;
@@ -435,7 +439,9 @@ bool FeedSchedulerHost::ShouldRefresh(TriggerType trigger) {
DVLOG(2) << "Requesting refresh from trigger " << static_cast<int>(trigger);
UMA_HISTOGRAM_ENUMERATION("ContentSuggestions.Feed.Scheduler.RefreshTrigger",
trigger);
- tracking_oustanding_request_ = true;
+ outstanding_request_until_ =
+ clock_->Now() +
+ base::TimeDelta::FromSeconds(kTimeoutDurationSeconds.Get());
return true;
}
diff --git a/chromium/components/feed/core/feed_scheduler_host.h b/chromium/components/feed/core/feed_scheduler_host.h
index ca3991b3c05..31469361e43 100644
--- a/chromium/components/feed/core/feed_scheduler_host.h
+++ b/chromium/components/feed/core/feed_scheduler_host.h
@@ -176,13 +176,13 @@ class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer {
// should cause a refresh to occur.
base::Time suppress_refreshes_until_;
- // Whether the scheduler is aware of an outstanding refresh or not. There are
- // cases where a refresh may be occurring without the scheduler knowing about
- // it, such as user interaction with UI on the NTP. If this field holds a
- // value of true, it is expected that either OnReceiveNewContent or
- // OnRequestError will be called eventually, somewhere on the order of seconds
- // from now, assuming the browser does not shut down.
- bool tracking_oustanding_request_ = false;
+ // The goal of this field is to not make multiple refresh request at the same
+ // time. When the scheduler starts or indicates the caller should start a
+ // request, this field is set. When that request finishes, this field is
+ // cleared. It is unclear if this field is always and correctly cleared out,
+ // so after the point in time held by this field, the scheduler is allowed to
+ // trigger another request.
+ base::Time outstanding_request_until_;
// May hold a nullptr if the platform does not show the user a EULA. Will only
// notify if IsEulaAccepted() is called and it returns false.
diff --git a/chromium/components/feed/core/feed_scheduler_host_unittest.cc b/chromium/components/feed/core/feed_scheduler_host_unittest.cc
index f236a914b98..d7ba47085c6 100644
--- a/chromium/components/feed/core/feed_scheduler_host_unittest.cc
+++ b/chromium/components/feed/core/feed_scheduler_host_unittest.cc
@@ -875,17 +875,16 @@ TEST_F(FeedSchedulerHostTest, OustandingRequest) {
/*has_content*/ false, /*content_creation_date_time*/ Time(),
/*has_outstanding_request*/ true));
- test_clock()->Advance(TimeDelta::FromDays(7));
+ profile_prefs()->SetTime(prefs::kLastFetchAttemptTime, base::Time());
scheduler()->OnForegrounded();
EXPECT_EQ(1, refresh_call_count());
- // Although this clears outstanding, it also updates last attempted time, so
- // still expect no refresh.
- scheduler()->OnRequestError(0);
+ test_clock()->Advance(
+ TimeDelta::FromSeconds(kTimeoutDurationSeconds.Get() - 1));
scheduler()->OnForegrounded();
EXPECT_EQ(1, refresh_call_count());
- test_clock()->Advance(TimeDelta::FromDays(7));
+ test_clock()->Advance(TimeDelta::FromSeconds(2));
scheduler()->OnForegrounded();
EXPECT_EQ(2, refresh_call_count());
diff --git a/chromium/components/history/ios/browser/web_state_top_sites_observer.mm b/chromium/components/history/ios/browser/web_state_top_sites_observer.mm
index 966857fc5d9..9883b3eac08 100644
--- a/chromium/components/history/ios/browser/web_state_top_sites_observer.mm
+++ b/chromium/components/history/ios/browser/web_state_top_sites_observer.mm
@@ -40,7 +40,10 @@ WebStateTopSitesObserver::~WebStateTopSitesObserver() {
void WebStateTopSitesObserver::DidFinishNavigation(
web::WebState* web_state,
web::NavigationContext* navigation_context) {
- if (top_sites_ && navigation_context->HasCommitted()) {
+ // TODO(crbug.com/931841): Remove GetLastCommittedItem nil check once
+ // HasComitted has been fixed.
+ if (top_sites_ && navigation_context->HasCommitted() &&
+ web_state->GetNavigationManager()->GetLastCommittedItem()) {
top_sites_->OnNavigationCommitted(
web_state->GetNavigationManager()->GetLastCommittedItem()->GetURL());
}
diff --git a/chromium/components/language/content/browser/BUILD.gn b/chromium/components/language/content/browser/BUILD.gn
index d903df3a729..5332abe0ee2 100644
--- a/chromium/components/language/content/browser/BUILD.gn
+++ b/chromium/components/language/content/browser/BUILD.gn
@@ -51,6 +51,7 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//components/language/content/browser/regional_language_code_locator:unit_tests",
+ "//components/language/content/browser/ulp_language_code_locator:ulp_language_code_locator",
"//components/language/content/browser/ulp_language_code_locator:unit_tests",
"//components/language/core/common",
"//components/prefs:test_support",
diff --git a/chromium/components/language/content/browser/geo_language_provider.cc b/chromium/components/language/content/browser/geo_language_provider.cc
index 14abf6b739e..1dbf51e9e0a 100644
--- a/chromium/components/language/content/browser/geo_language_provider.cc
+++ b/chromium/components/language/content/browser/geo_language_provider.cc
@@ -91,7 +91,7 @@ void GeoLanguageProvider::BackgroundStartUp() {
DCHECK_CALLED_ON_VALID_SEQUENCE(background_sequence_checker_);
// Initialize location->language lookup library.
- language_code_locator_ = GetLanguageCodeLocator();
+ language_code_locator_ = GetLanguageCodeLocator(prefs_);
// Make initial query.
QueryNextPosition();
diff --git a/chromium/components/language/content/browser/geo_language_provider_unittest.cc b/chromium/components/language/content/browser/geo_language_provider_unittest.cc
index 9dd6832175a..8693e600bb0 100644
--- a/chromium/components/language/content/browser/geo_language_provider_unittest.cc
+++ b/chromium/components/language/content/browser/geo_language_provider_unittest.cc
@@ -14,6 +14,7 @@
#include "base/test/test_mock_time_task_runner.h"
#include "base/timer/timer.h"
#include "components/language/content/browser/test_utils.h"
+#include "components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h"
#include "components/language/core/common/language_experiments.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -35,6 +36,8 @@ class GeoLanguageProviderTest : public testing::Test {
base::Unretained(&mock_ip_geo_location_provider_)));
language::GeoLanguageProvider::RegisterLocalStatePrefs(
local_state_.registry());
+ language::UlpLanguageCodeLocator::RegisterLocalStatePrefs(
+ local_state_.registry());
}
protected:
diff --git a/chromium/components/language/content/browser/language_code_locator_provider.cc b/chromium/components/language/content/browser/language_code_locator_provider.cc
index 1bd1e178ec5..d7f5bdd6c5b 100644
--- a/chromium/components/language/content/browser/language_code_locator_provider.cc
+++ b/chromium/components/language/content/browser/language_code_locator_provider.cc
@@ -5,6 +5,7 @@
#include "components/language/content/browser/language_code_locator_provider.h"
#include <memory>
+#include <utility>
#include "base/feature_list.h"
#include "components/language/content/browser/language_code_locator.h"
@@ -12,26 +13,29 @@
#include "components/language/content/browser/ulp_language_code_locator/s2langquadtree.h"
#include "components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h"
#include "components/language/core/common/language_experiments.h"
+#include "components/prefs/pref_service.h"
namespace language {
namespace {
#include "components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator_helper.h"
} // namespace
-std::unique_ptr<LanguageCodeLocator> GetLanguageCodeLocator() {
+std::unique_ptr<LanguageCodeLocator> GetLanguageCodeLocator(
+ PrefService* prefs) {
if (base::FeatureList::IsEnabled(kImprovedGeoLanguageData)) {
- std::vector<std::unique_ptr<S2LangQuadTreeNode>> roots;
- roots.reserve(3);
- roots.push_back(
- std::make_unique<S2LangQuadTreeNode>(S2LangQuadTreeNode::Deserialize(
- GetLanguagesRank0(), GetTreeSerializedRank0())));
- roots.push_back(
- std::make_unique<S2LangQuadTreeNode>(S2LangQuadTreeNode::Deserialize(
- GetLanguagesRank1(), GetTreeSerializedRank1())));
- roots.push_back(
- std::make_unique<S2LangQuadTreeNode>(S2LangQuadTreeNode::Deserialize(
- GetLanguagesRank2(), GetTreeSerializedRank2())));
- return std::make_unique<UlpLanguageCodeLocator>(std::move(roots));
+ std::vector<std::unique_ptr<SerializedLanguageTree>> serialized_langtrees;
+ serialized_langtrees.reserve(3);
+ serialized_langtrees.push_back(
+ std::make_unique<BitsetSerializedLanguageTree<kNumBits0>>(
+ GetLanguagesRank0(), GetTreeSerializedRank0()));
+ serialized_langtrees.push_back(
+ std::make_unique<BitsetSerializedLanguageTree<kNumBits1>>(
+ GetLanguagesRank1(), GetTreeSerializedRank1()));
+ serialized_langtrees.push_back(
+ std::make_unique<BitsetSerializedLanguageTree<kNumBits2>>(
+ GetLanguagesRank2(), GetTreeSerializedRank2()));
+ return std::make_unique<UlpLanguageCodeLocator>(
+ std::move(serialized_langtrees), prefs);
} else {
return std::make_unique<RegionalLanguageCodeLocator>();
}
diff --git a/chromium/components/language/content/browser/language_code_locator_provider.h b/chromium/components/language/content/browser/language_code_locator_provider.h
index fc7ccce725c..9c5eceb5ddd 100644
--- a/chromium/components/language/content/browser/language_code_locator_provider.h
+++ b/chromium/components/language/content/browser/language_code_locator_provider.h
@@ -7,11 +7,13 @@
#include <memory>
+class PrefService;
+
namespace language {
class LanguageCodeLocator;
-std::unique_ptr<LanguageCodeLocator> GetLanguageCodeLocator();
+std::unique_ptr<LanguageCodeLocator> GetLanguageCodeLocator(PrefService* prefs);
} // namespace language
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn b/chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn
index eeb576396e2..117cefe4165 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn
@@ -52,6 +52,7 @@ source_set("ulp_language_code_locator") {
":ulp_serialized_to_static_c",
"//base",
"//components/language/content/browser:language_code_locator",
+ "//components/prefs:prefs",
"//third_party/s2cellid",
]
}
@@ -67,6 +68,7 @@ source_set("unit_tests") {
":ulp_language_code_locator",
"//base",
"//base/test:test_support",
+ "//components/prefs:test_support",
"//testing/gmock",
"//testing/gtest",
"//third_party/s2cellid",
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.cc b/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.cc
index d621d6d3c06..94e12708620 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.cc
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.cc
@@ -12,31 +12,63 @@ S2LangQuadTreeNode::S2LangQuadTreeNode(const S2LangQuadTreeNode& other) =
default;
S2LangQuadTreeNode::~S2LangQuadTreeNode() = default;
-std::string S2LangQuadTreeNode::Get(const S2CellId& cell) const {
+std::string S2LangQuadTreeNode::Get(const S2CellId& cell,
+ int* level_ptr) const {
const S2LangQuadTreeNode* node = this;
- const std::string* language = &(node->language_);
- for (int current_level = 1; current_level <= cell.level(); ++current_level) {
- const S2LangQuadTreeNode* const child =
- node->GetChild(cell.child_position(current_level));
- if (child == nullptr)
- break;
- node = child;
- if (!node->language_.empty())
- language = &(node->language_);
+ for (int current_level = 0; current_level <= cell.level(); current_level++) {
+ if (node->IsLeaf()) {
+ *level_ptr = current_level;
+ return node->language_;
+ }
+ if (current_level < cell.level())
+ node = &(node->GetChild(cell.child_position(current_level + 1)));
}
- return *language;
+ *level_ptr = -1;
+ return "";
}
-const S2LangQuadTreeNode* S2LangQuadTreeNode::GetChild(
+S2LangQuadTreeNode S2LangQuadTreeNode::Deserialize(
+ const SerializedLanguageTree* serialized_langtree) {
+ S2LangQuadTreeNode root;
+ int bits_per_lang_index = serialized_langtree->GetBitsPerLanguageIndex();
+ DeserializeSubtree(serialized_langtree, bits_per_lang_index, 0, &root);
+ return root;
+}
+
+size_t S2LangQuadTreeNode::DeserializeSubtree(
+ const SerializedLanguageTree* serialized_langtree,
+ int bits_per_lang_index,
+ size_t bit_offset,
+ S2LangQuadTreeNode* root) {
+ if (serialized_langtree->GetBitAt(bit_offset)) {
+ int index = 0;
+ for (int bit_index = 1; bit_index <= bits_per_lang_index; bit_index++) {
+ index <<= 1;
+ index += serialized_langtree->GetBitAt(bit_offset + bit_index);
+ }
+ if (index != 0)
+ root->language_ = serialized_langtree->GetLanguageAt(index - 1);
+ return bits_per_lang_index + 1;
+ } else {
+ size_t subtree_size = 1;
+ root->children_.reserve(4);
+ for (int child_index = 0; child_index < 4; child_index++) {
+ S2LangQuadTreeNode child;
+ subtree_size +=
+ DeserializeSubtree(serialized_langtree, bits_per_lang_index,
+ bit_offset + subtree_size, &child);
+ root->children_.push_back(child);
+ }
+ return subtree_size;
+ }
+}
+
+const S2LangQuadTreeNode& S2LangQuadTreeNode::GetChild(
const int child_index) const {
- auto it = children_.find(child_index);
- return it == children_.end() ? nullptr : &it->second;
+ DCHECK(!children_.empty());
+ return children_[child_index];
}
bool S2LangQuadTreeNode::IsLeaf() const {
return children_.empty();
-}
-
-bool S2LangQuadTreeNode::IsNullLeaf() const {
- return IsLeaf() && language_.empty();
} \ No newline at end of file
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h b/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h
index 1b39848bdd7..efee31ec319 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree.h
@@ -14,6 +14,50 @@
class S2CellId;
+// A serialized language tree. The bits given by GetBitAt represent a
+// depth-first traversal of the tree with (1) internal nodes represented by a
+// single bit 0, and (2) leaf nodes represented by a bit 1 followed by the
+// binary form of the index of the language at that leaf into the tree's
+// languages, accessible through GetLanguageAt. We assume those indexes have the
+// smallest number of bits necessary. Indices are 1-based; index 0 represents
+// absent language.
+class SerializedLanguageTree {
+ public:
+ virtual ~SerializedLanguageTree(){};
+
+ virtual std::string GetLanguageAt(const size_t pos) const = 0;
+ virtual size_t GetNumLanguages() const = 0;
+ virtual bool GetBitAt(const size_t pos) const = 0;
+
+ int GetBitsPerLanguageIndex() const {
+ return base::bits::Log2Ceiling(GetNumLanguages() + 1);
+ }
+};
+
+// An implementation of SerializedLanguageTree that backs the tree's structure
+// by a bitset.
+template <size_t numbits>
+class BitsetSerializedLanguageTree : public SerializedLanguageTree {
+ public:
+ BitsetSerializedLanguageTree(std::vector<std::string> languages,
+ std::bitset<numbits> bits)
+ : languages_(languages), bits_(bits) {}
+ ~BitsetSerializedLanguageTree() override{};
+
+ // SerializedTree implementation
+ std::string GetLanguageAt(const size_t pos) const override {
+ return languages_[pos];
+ }
+
+ size_t GetNumLanguages() const override { return languages_.size(); }
+
+ bool GetBitAt(const size_t pos) const override { return bits_[pos]; }
+
+ private:
+ std::vector<std::string> languages_;
+ std::bitset<numbits> bits_;
+};
+
// The node of a S2Cell-based quadtree holding string languages in its leaves.
class S2LangQuadTreeNode {
public:
@@ -21,77 +65,37 @@ class S2LangQuadTreeNode {
S2LangQuadTreeNode(const S2LangQuadTreeNode& other);
~S2LangQuadTreeNode();
- // Return the language in the deepest/lowest/smallest node containing the
- // given cell.
- std::string Get(const S2CellId& cell) const;
-
- // Reconstruct a S2LangQuadTree with structure given by |tree| and with
- // languages given by |languages|. |tree| represents a depth-first traversal
- // of the tree with (1) internal nodes represented by a single bit 0, and (2)
- // leaf nodes represented by a bit 1 followed by the binary form of the index
- // of the language at that leaf into |languages|. We assume those indexes have
- // the smallest number of bits necessary. Indices are 1-based; index 0
- // represents absent language.
- // The bitset size is templated to allow this method to be re-used for the
- // small number of different-sized serialized trees we have.
- template <size_t numbits>
- static S2LangQuadTreeNode Deserialize(
- const std::vector<std::string>& languages,
- const std::bitset<numbits>& tree) {
- S2LangQuadTreeNode root;
- DeserializeSubtree(tree, 0, languages,
- GetBitsPerLanguageIndex(languages.size()), &root);
- return root;
+ // Return language of the leaf containing the given |cell|.
+ // Empty string if a null-leaf contains given |cell|.
+ // |level_ptr| is set to the level (see S2CellId::level) of the leaf. (-1 if
+ // |cell| matches an internal node).
+ std::string Get(const S2CellId& cell, int* level_ptr) const;
+ std::string Get(const S2CellId& cell) const {
+ int level;
+ return Get(cell, &level);
}
+ // Reconstruct a S2LangQuadTree with structure and languages given by
+ // |serialized_langtree|. The bitset size is templated to allow this method to
+ // be re-used for the small number of different-sized serialized trees we
+ // have.
+ static S2LangQuadTreeNode Deserialize(
+ const SerializedLanguageTree* serialized_langtree);
+
private:
- // Recursively deserialize the subtree at |bit_offset| in |serialized| into
- // the node |root|. |languages| and |bits_per_lang_index| dictacte
- // how languages in leaves are serialized.
- template <size_t numbits>
- static size_t DeserializeSubtree(const std::bitset<numbits>& serialized,
- size_t bit_offset,
- const std::vector<std::string>& languages,
- const int bits_per_lang_index,
- S2LangQuadTreeNode* root) {
- if (serialized[bit_offset]) {
- int index = 0;
- for (int bit = 1; bit <= bits_per_lang_index; bit++) {
- index <<= 1;
- index += serialized[bit_offset + bit];
- }
- if (index != 0)
- root->language_ = languages[index - 1];
- return bits_per_lang_index + 1;
- } else {
- size_t subtree_size = 1;
- for (int child_index = 0; child_index < 4; child_index++) {
- S2LangQuadTreeNode child;
- subtree_size +=
- DeserializeSubtree(serialized, bit_offset + subtree_size, languages,
- bits_per_lang_index, &child);
- if (!child.IsNullLeaf())
- root->children_[child_index] = child;
- }
- return subtree_size;
- }
- }
+ static size_t DeserializeSubtree(
+ const SerializedLanguageTree* serialized_langtree,
+ int bits_per_lang_index,
+ size_t bit_offset,
+ S2LangQuadTreeNode* root);
- const S2LangQuadTreeNode* GetChild(const int child_index) const;
+ const S2LangQuadTreeNode& GetChild(const int child_index) const;
// Return true iff the node is a leaf.
bool IsLeaf() const;
- // Return true iff the node is a leaf with no language.
- bool IsNullLeaf() const;
-
- static int GetBitsPerLanguageIndex(const size_t num_languages) {
- DCHECK(num_languages > 0);
- return base::bits::Log2Ceiling(num_languages + 1);
- }
-
- std::map<int, S2LangQuadTreeNode> children_;
+ std::vector<S2LangQuadTreeNode> children_;
std::string language_;
};
-#endif // COMPONENTS_LANGUAGE_CONTENT_BROWSER_ULP_LANGUAGE_CODE_LOCATOR_S2LANGQUADTREE_H_ \ No newline at end of file
+#endif // COMPONENTS_LANGUAGE_CONTENT_BROWSER_ULP_LANGUAGE_CODE_LOCATOR_S2LANGQUADTREE_H_
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_datatest.cc b/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_datatest.cc
index 8e985ef6907..8e0f876ef6c 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_datatest.cc
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_datatest.cc
@@ -60,21 +60,24 @@ void ExpectTreeContainsData(const S2LangQuadTreeNode& root,
}
}
-TEST(UlpLanguageCodeLocatorDataTest, TreeContainsDataRank0) {
- ExpectTreeContainsData(S2LangQuadTreeNode::Deserialize(
- GetLanguagesRank0(), GetTreeSerializedRank0()),
+TEST(S2LangQuadTreeDataTest, TreeContainsDataRank0) {
+ const BitsetSerializedLanguageTree<kNumBits0> serialized_langtree(
+ GetLanguagesRank0(), GetTreeSerializedRank0());
+ ExpectTreeContainsData(S2LangQuadTreeNode::Deserialize(&serialized_langtree),
GetData(0));
}
-TEST(UlpLanguageCodeLocatorDataTest, TreeContainsDataRank1) {
- ExpectTreeContainsData(S2LangQuadTreeNode::Deserialize(
- GetLanguagesRank1(), GetTreeSerializedRank1()),
+TEST(S2LangQuadTreeDataTest, TreeContainsDataRank1) {
+ const BitsetSerializedLanguageTree<kNumBits1> serialized_langtree(
+ GetLanguagesRank1(), GetTreeSerializedRank1());
+ ExpectTreeContainsData(S2LangQuadTreeNode::Deserialize(&serialized_langtree),
GetData(1));
}
-TEST(UlpLanguageCodeLocatorDataTest, TreeContainsDataRank2) {
- ExpectTreeContainsData(S2LangQuadTreeNode::Deserialize(
- GetLanguagesRank2(), GetTreeSerializedRank2()),
+TEST(S2LangQuadTreeDataTest, TreeContainsDataRank2) {
+ const BitsetSerializedLanguageTree<kNumBits2> serialized_langtree(
+ GetLanguagesRank2(), GetTreeSerializedRank2());
+ ExpectTreeContainsData(S2LangQuadTreeNode::Deserialize(&serialized_langtree),
GetData(2));
}
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_unittest.cc b/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_unittest.cc
index 81493936ab7..d37126f0d52 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_unittest.cc
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/s2langquadtree_unittest.cc
@@ -16,18 +16,22 @@ namespace {
template <size_t numbits>
S2LangQuadTreeNode GetTree(const std::vector<std::string>& languages,
std::bitset<numbits> tree) {
- return S2LangQuadTreeNode::Deserialize(languages, tree);
+ const BitsetSerializedLanguageTree<numbits> serialized_langtree(languages,
+ tree);
+ return S2LangQuadTreeNode::Deserialize(&serialized_langtree);
}
} // namespace
namespace language {
-TEST(S2LangQuadTreeTest, Empty) {
+TEST(S2LangQuadTreeTest, RootIsEmptyLeaf) {
S2LangQuadTreeNode root;
const S2CellId cell = S2CellId::FromFace(0);
- const std::string language = root.Get(cell);
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_TRUE(language.empty());
+ EXPECT_EQ(level, 0);
}
TEST(S2LangQuadTreeTest, RootIsLeaf_FaceIsPresent) {
@@ -35,8 +39,10 @@ TEST(S2LangQuadTreeTest, RootIsLeaf_FaceIsPresent) {
const std::bitset<2> tree("11"); // String is in reverse order.
const S2LangQuadTreeNode root = GetTree(languages, tree);
const S2CellId cell = S2CellId::FromFace(0);
- const std::string language = root.Get(cell);
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_EQ(language, "fr");
+ EXPECT_EQ(level, 0);
}
TEST(S2LangQuadTreeTest, RootIsLeaf_FaceChildGetsFaceLanguage) {
@@ -44,8 +50,10 @@ TEST(S2LangQuadTreeTest, RootIsLeaf_FaceChildGetsFaceLanguage) {
const std::bitset<2> tree("11"); // String is in reverse order.
const S2LangQuadTreeNode root = GetTree(languages, tree);
const S2CellId cell = S2CellId::FromFace(0).child(0);
- const std::string language = root.Get(cell);
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_EQ(language, "fr");
+ EXPECT_EQ(level, 0);
}
TEST(S2LangQuadTreeTest, RootThenSingleLeaf_LeafIsPresent) {
@@ -53,8 +61,10 @@ TEST(S2LangQuadTreeTest, RootThenSingleLeaf_LeafIsPresent) {
const std::bitset<9> tree("110101010"); // String is in reverse order.
const S2LangQuadTreeNode root = GetTree(languages, tree);
const S2CellId cell = S2CellId::FromFace(0).child(3);
- const std::string language = root.Get(cell);
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_EQ(language, "fr");
+ EXPECT_EQ(level, 1);
}
TEST(S2LangQuadTreeTest, RootThenSingleLeaf_ParentIsAbsent) {
@@ -62,9 +72,10 @@ TEST(S2LangQuadTreeTest, RootThenSingleLeaf_ParentIsAbsent) {
const std::bitset<9> tree("110101010"); // String is in reverse order.
const S2LangQuadTreeNode root = GetTree(languages, tree);
const S2CellId cell = S2CellId::FromFace(0);
- const std::string language = root.Get(cell);
- LOG(INFO) << language;
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_TRUE(language.empty());
+ EXPECT_EQ(level, -1);
}
TEST(S2LangQuadTreeTest, RootThenSingleLeaf_SiblingIsAbsent) {
@@ -72,8 +83,10 @@ TEST(S2LangQuadTreeTest, RootThenSingleLeaf_SiblingIsAbsent) {
const std::bitset<9> tree("110101010"); // String is in reverse order.
const S2LangQuadTreeNode root = GetTree(languages, tree);
const S2CellId cell = S2CellId::FromFace(0).child(0);
- const std::string language = root.Get(cell);
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_TRUE(language.empty());
+ EXPECT_EQ(level, 1);
}
TEST(S2LangQuadTreeTest, RootThenAllLeaves_LeavesArePresent) {
@@ -82,12 +95,16 @@ TEST(S2LangQuadTreeTest, RootThenAllLeaves_LeavesArePresent) {
const S2LangQuadTreeNode root = GetTree(languages, tree);
for (int leaf_index = 0; leaf_index < 3; leaf_index++) {
const S2CellId cell = S2CellId::FromFace(0).child(leaf_index);
- const std::string language = root.Get(cell);
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_EQ(language, "fr");
+ EXPECT_EQ(level, 1);
}
const S2CellId cell = S2CellId::FromFace(0).child(3);
- const std::string language = root.Get(cell);
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_EQ(language, "en");
+ EXPECT_EQ(level, 1);
}
TEST(S2LangQuadTreeTest, RootThenAllLeaves_ParentIsAbsent) {
@@ -95,8 +112,10 @@ TEST(S2LangQuadTreeTest, RootThenAllLeaves_ParentIsAbsent) {
const std::bitset<13> tree("0111011011010"); // String is in reverse order.
const S2LangQuadTreeNode root = GetTree(languages, tree);
const S2CellId cell = S2CellId::FromFace(0);
- const std::string language = root.Get(cell);
+ int level;
+ const std::string language = root.Get(cell, &level);
EXPECT_TRUE(language.empty());
+ EXPECT_EQ(level, -1);
}
} // namespace language
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc b/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc
index 79c36ae7260..a08f3077ce9 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.cc
@@ -6,26 +6,85 @@
#include <memory>
+#include "base/values.h"
#include "components/language/content/browser/ulp_language_code_locator/s2langquadtree.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
#include "third_party/s2cellid/src/s2/s2cellid.h"
#include "third_party/s2cellid/src/s2/s2latlng.h"
+namespace {
+
+const char kCellTokenKey[] = "celltoken";
+const char kLanguageKey[] = "language";
+
+base::Value GetCellLanguagePairValue(S2CellId cell, std::string language) {
+ base::Value value(base::Value::Type::DICTIONARY);
+ value.SetKey(kCellTokenKey, base::Value(cell.ToToken()));
+ value.SetKey(kLanguageKey, base::Value(language));
+ return value;
+}
+
+} // namespace
+
namespace language {
+const char UlpLanguageCodeLocator::kCachedGeoLanguagesPref[] =
+ "language.ulp_language_code_locator.cached_geo_languages";
+
UlpLanguageCodeLocator::UlpLanguageCodeLocator(
- std::vector<std::unique_ptr<S2LangQuadTreeNode>>&& roots) {
- roots_ = std::move(roots);
+ std::vector<std::unique_ptr<SerializedLanguageTree>>&& serialized_langtrees,
+ PrefService* prefs) {
+ serialized_langtrees_ = std::move(serialized_langtrees);
+ prefs_ = prefs;
}
UlpLanguageCodeLocator::~UlpLanguageCodeLocator() {}
+// static
+void UlpLanguageCodeLocator::RegisterLocalStatePrefs(
+ PrefRegistrySimple* const registry) {
+ registry->RegisterListPref(kCachedGeoLanguagesPref, PrefRegistry::LOSSY_PREF);
+}
+
std::vector<std::string> UlpLanguageCodeLocator::GetLanguageCodes(
double latitude,
double longitude) const {
S2CellId cell(S2LatLng::FromDegrees(latitude, longitude));
std::vector<std::string> languages;
- for (const auto& root : roots_) {
- const std::string language = root.get()->Get(cell);
+
+ ListPrefUpdate update(prefs_, kCachedGeoLanguagesPref);
+ base::ListValue* celllangs_cached = update.Get();
+ for (size_t index = 0; index < serialized_langtrees_.size(); index++) {
+ std::string language;
+
+ const base::DictionaryValue* celllang_cached;
+ const bool is_cached =
+ celllangs_cached->GetDictionary(index, &celllang_cached);
+
+ const S2CellId cell_cached =
+ is_cached ? S2CellId::FromToken(
+ *celllang_cached->FindStringKey(kCellTokenKey))
+ : S2CellId::None();
+
+ if (cell_cached.is_valid() && cell_cached.contains(cell)) {
+ language = *celllang_cached->FindStringKey(kLanguageKey);
+ } else {
+ const S2LangQuadTreeNode& root =
+ S2LangQuadTreeNode::Deserialize(serialized_langtrees_[index].get());
+ int level;
+ language = root.Get(cell, &level);
+ if (level != -1) {
+ if (is_cached) {
+ celllangs_cached->GetList()[index] =
+ GetCellLanguagePairValue(cell.parent(level), language);
+ } else {
+ celllangs_cached->GetList().push_back(
+ GetCellLanguagePairValue(cell.parent(level), language));
+ }
+ }
+ }
if (!language.empty())
languages.push_back(language);
}
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h b/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h
index 61b0f8e621c..f28a68d0340 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h
@@ -12,7 +12,9 @@
#include "base/macros.h"
#include "components/language/content/browser/language_code_locator.h"
-class S2LangQuadTreeNode;
+class PrefRegistrySimple;
+class PrefService;
+class SerializedLanguageTree;
namespace language {
@@ -21,16 +23,23 @@ namespace language {
// constructor.
class UlpLanguageCodeLocator : public LanguageCodeLocator {
public:
- UlpLanguageCodeLocator(
- std::vector<std::unique_ptr<S2LangQuadTreeNode>>&& roots);
+ static const char kCachedGeoLanguagesPref[];
+
+ UlpLanguageCodeLocator(std::vector<std::unique_ptr<SerializedLanguageTree>>&&
+ serialized_langtrees,
+ PrefService* prefs);
~UlpLanguageCodeLocator() override;
+ static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+
// LanguageCodeLocator implementation.
std::vector<std::string> GetLanguageCodes(double latitude,
double longitude) const override;
private:
- std::vector<std::unique_ptr<S2LangQuadTreeNode>> roots_;
+ std::vector<std::unique_ptr<SerializedLanguageTree>> serialized_langtrees_;
+ PrefService* prefs_;
+
DISALLOW_COPY_AND_ASSIGN(UlpLanguageCodeLocator);
};
} // namespace language
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator_unittest.cc b/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator_unittest.cc
index 3bdc553b010..9b0bf6ad181 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator_unittest.cc
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator_unittest.cc
@@ -7,10 +7,12 @@
#include <bitset>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/logging.h"
#include "components/language/content/browser/ulp_language_code_locator/s2langquadtree.h"
+#include "components/prefs/testing_pref_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/s2cellid/src/s2/s2cellid.h"
@@ -18,7 +20,16 @@
namespace language {
-std::vector<std::unique_ptr<S2LangQuadTreeNode>> GetTestTrees() {
+class UlpLanguageCodeLocatorTest : public testing::Test {
+ public:
+ UlpLanguageCodeLocatorTest() {
+ UlpLanguageCodeLocator::RegisterLocalStatePrefs(local_state_.registry());
+ }
+
+ TestingPrefServiceSimple local_state_;
+};
+
+std::vector<std::unique_ptr<SerializedLanguageTree>> GetSerializedTrees() {
const std::vector<std::string> languages_rank0{"fr", "en"};
// |tree_rank0| is a two level quadtree with the second level being all leaves
// with language indices 0, 0, 0, 1.
@@ -31,13 +42,15 @@ std::vector<std::unique_ptr<S2LangQuadTreeNode>> GetTestTrees() {
const std::bitset<13> tree_rank1(
"1011011010110"); // String is in reverse order.
- std::vector<std::unique_ptr<S2LangQuadTreeNode>> roots;
- roots.reserve(2);
- roots.push_back(std::make_unique<S2LangQuadTreeNode>(
- S2LangQuadTreeNode::Deserialize(languages_rank0, tree_rank0)));
- roots.push_back(std::make_unique<S2LangQuadTreeNode>(
- S2LangQuadTreeNode::Deserialize(languages_rank1, tree_rank1)));
- return roots;
+ std::vector<std::unique_ptr<SerializedLanguageTree>> serialized_langtrees;
+ serialized_langtrees.reserve(2);
+ serialized_langtrees.push_back(
+ std::make_unique<BitsetSerializedLanguageTree<13>>(languages_rank0,
+ tree_rank0));
+ serialized_langtrees.push_back(
+ std::make_unique<BitsetSerializedLanguageTree<13>>(languages_rank1,
+ tree_rank1));
+ return serialized_langtrees;
}
void ExpectLatLngHasLanguages(const UlpLanguageCodeLocator& locator,
@@ -49,9 +62,11 @@ void ExpectLatLngHasLanguages(const UlpLanguageCodeLocator& locator,
EXPECT_THAT(languages, ::testing::ElementsAreArray(languages_expected));
}
-TEST(UlpLanguageCodeLocatorTest, QuadrantMatchLanguages) {
- std::vector<std::unique_ptr<S2LangQuadTreeNode>> roots = GetTestTrees();
- const UlpLanguageCodeLocator locator(std::move(roots));
+TEST_F(UlpLanguageCodeLocatorTest, TreeLeaves) {
+ std::vector<std::unique_ptr<SerializedLanguageTree>> serialized_langtrees =
+ GetSerializedTrees();
+ const UlpLanguageCodeLocator locator(std::move(serialized_langtrees),
+ &local_state_);
const S2CellId face = S2CellId::FromFace(0);
ExpectLatLngHasLanguages(locator, face.child(0), {"fr", "de"});
@@ -59,4 +74,36 @@ TEST(UlpLanguageCodeLocatorTest, QuadrantMatchLanguages) {
ExpectLatLngHasLanguages(locator, face.child(2), {"fr", "en"});
ExpectLatLngHasLanguages(locator, face.child(3), {"en", "en"});
}
+
+TEST_F(UlpLanguageCodeLocatorTest, Idempotence) {
+ std::vector<std::unique_ptr<SerializedLanguageTree>> serialized_langtrees =
+ GetSerializedTrees();
+ const UlpLanguageCodeLocator locator(std::move(serialized_langtrees),
+ &local_state_);
+ const S2CellId face = S2CellId::FromFace(0);
+
+ ExpectLatLngHasLanguages(locator, face.child(0), {"fr", "de"});
+ ExpectLatLngHasLanguages(locator, face.child(0), {"fr", "de"});
+
+ ExpectLatLngHasLanguages(locator, face.child(3), {"en", "en"});
+ ExpectLatLngHasLanguages(locator, face.child(3), {"en", "en"});
+}
+
+TEST_F(UlpLanguageCodeLocatorTest, TreeLeafDescendants) {
+ std::vector<std::unique_ptr<SerializedLanguageTree>> serialized_langtrees =
+ GetSerializedTrees();
+ const UlpLanguageCodeLocator locator(std::move(serialized_langtrees),
+ &local_state_);
+ const S2CellId cell = S2CellId::FromFace(0).child(0);
+
+ ExpectLatLngHasLanguages(locator, cell, {"fr", "de"});
+
+ const int depth = 2;
+ // Check that the 4**|depth| descendants of |child| map to the same language.
+ const int level = cell.level() + depth;
+ for (S2CellId descendant = cell.child_begin(level);
+ descendant != cell.child_end(level); descendant = descendant.next())
+ ExpectLatLngHasLanguages(locator, descendant, {"fr", "de"});
+}
+
} // namespace language
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc
index 59ac52b7e4f..97c4aa26677 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.cc
@@ -183,11 +183,8 @@ ContextualSuggestionsResult ResultFromResponse(
ContextualSuggestionsFetch::ContextualSuggestionsFetch(
const GURL& url,
- const std::string& bcp_language_code,
- bool include_cookies)
- : url_(url),
- bcp_language_code_(bcp_language_code),
- include_cookies_(include_cookies) {}
+ const std::string& bcp_language_code)
+ : url_(url), bcp_language_code_(bcp_language_code) {}
ContextualSuggestionsFetch::~ContextualSuggestionsFetch() = default;
@@ -272,11 +269,8 @@ ContextualSuggestionsFetch::MakeResourceRequest() const {
resource_request->url = GURL(GetFetchEndpoint());
resource_request->method = "GET";
AppendHeaders(resource_request.get());
-
- int cookie_flag = include_cookies_ ? 0 : net::LOAD_DO_NOT_SEND_COOKIES;
- resource_request->load_flags = net::LOAD_BYPASS_CACHE |
- net::LOAD_DO_NOT_SAVE_COOKIES | cookie_flag |
- net::LOAD_DO_NOT_SEND_AUTH_DATA;
+ resource_request->load_flags = net::LOAD_BYPASS_CACHE;
+ resource_request->allow_credentials = false;
return resource_request;
}
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.h b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.h
index dd8845f5526..15f371a4e0d 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.h
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch.h
@@ -28,9 +28,7 @@ namespace contextual_suggestions {
// body protos and parsing the response body protos.
class ContextualSuggestionsFetch {
public:
- ContextualSuggestionsFetch(const GURL& url,
- const std::string& bcp_language,
- bool include_cookies);
+ ContextualSuggestionsFetch(const GURL& url, const std::string& bcp_language);
~ContextualSuggestionsFetch();
// Get the url used to fetch suggestions.
@@ -62,8 +60,6 @@ class ContextualSuggestionsFetch {
// Identifier for the spoken language in BCP47 format.
const std::string bcp_language_code_;
- bool include_cookies_ = false;
-
// The loader for downloading the suggestions. Only non-null if a fetch is
// currently ongoing.
std::unique_ptr<network::SimpleURLLoader> url_loader_;
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch_unittest.cc b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch_unittest.cc
index 1a29fc78843..c02ed601b12 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch_unittest.cc
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetch_unittest.cc
@@ -94,7 +94,7 @@ TEST(ContextualSuggestionsFetch, MakeResourceRequest_VariationsHeader) {
variations::VariationsHttpHeaderProvider::GetInstance()
->ForceVariationIds({"12345"}, ""));
- ContextualSuggestionsFetch fetch(GURL("http://test.com"), "en-US", false);
+ ContextualSuggestionsFetch fetch(GURL("http://test.com"), "en-US");
std::unique_ptr<network::ResourceRequest> resource_request =
fetch.MakeResourceRequestForTesting();
@@ -114,7 +114,7 @@ TEST(ContextualSuggestionsFetch,
variations::VariationsHttpHeaderProvider::GetInstance()
->ForceVariationIds({"12345"}, ""));
- ContextualSuggestionsFetch fetch(GURL("http://test.com"), "en-US", false);
+ ContextualSuggestionsFetch fetch(GURL("http://test.com"), "en-US");
std::unique_ptr<network::ResourceRequest> resource_request =
fetch.MakeResourceRequestForTesting();
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
index ef050f796a9..9130ab485ab 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.cc
@@ -12,11 +12,8 @@ namespace contextual_suggestions {
ContextualSuggestionsFetcherImpl::ContextualSuggestionsFetcherImpl(
const scoped_refptr<network::SharedURLLoaderFactory>& loader_factory,
- std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>
- consent_helper,
const std::string& application_language_code)
: loader_factory_(loader_factory),
- consent_helper_(std::move(consent_helper)),
bcp_language_code_(application_language_code) {}
ContextualSuggestionsFetcherImpl::~ContextualSuggestionsFetcherImpl() = default;
@@ -25,9 +22,8 @@ void ContextualSuggestionsFetcherImpl::FetchContextualSuggestionsClusters(
const GURL& url,
FetchClustersCallback callback,
ReportFetchMetricsCallback metrics_callback) {
- bool include_cookies = consent_helper_ && consent_helper_->IsEnabled();
- auto fetch = std::make_unique<ContextualSuggestionsFetch>(
- url, bcp_language_code_, include_cookies);
+ auto fetch =
+ std::make_unique<ContextualSuggestionsFetch>(url, bcp_language_code_);
ContextualSuggestionsFetch* fetch_unowned = fetch.get();
pending_requests_.emplace(std::move(fetch));
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
index 65410f84273..3eccc9da95b 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl.h
@@ -15,7 +15,6 @@
#include "components/ntp_snippets/contextual/contextual_suggestion.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_fetch.h"
#include "components/ntp_snippets/contextual/contextual_suggestions_fetcher.h"
-#include "components/unified_consent/url_keyed_data_collection_consent_helper.h"
namespace network {
class SharedURLLoaderFactory;
@@ -31,8 +30,6 @@ class ContextualSuggestionsFetcherImpl : public ContextualSuggestionsFetcher {
public:
ContextualSuggestionsFetcherImpl(
const scoped_refptr<network::SharedURLLoaderFactory>& loader_factory,
- std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>
- consent_helper,
const std::string& application_language_code);
~ContextualSuggestionsFetcherImpl() override;
@@ -48,8 +45,6 @@ class ContextualSuggestionsFetcherImpl : public ContextualSuggestionsFetcher {
ContextualSuggestionsResult result);
const scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
- std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>
- consent_helper_;
/// BCP47 formatted language code to use.
const std::string bcp_language_code_;
diff --git a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
index 1f27157fc28..1b8a993618b 100644
--- a/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
+++ b/chromium/components/ntp_snippets/contextual/contextual_suggestions_fetcher_impl_unittest.cc
@@ -147,36 +147,18 @@ std::string SerializedResponseProto(const std::string& peek_text,
} // namespace
-class TestUrlKeyedDataCollectionConsentHelper
- : public unified_consent::UrlKeyedDataCollectionConsentHelper {
- public:
- TestUrlKeyedDataCollectionConsentHelper() = default;
- ~TestUrlKeyedDataCollectionConsentHelper() override = default;
-
- bool IsEnabled() override { return is_enabled_; }
- void SetIsEnabled(bool enabled) { is_enabled_ = enabled; }
-
- private:
- bool is_enabled_ = false;
-};
-
class ContextualSuggestionsFetcherTest : public testing::Test {
public:
ContextualSuggestionsFetcherTest() {
shared_url_loader_factory_ =
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_factory_);
- auto consent_helper =
- std::make_unique<TestUrlKeyedDataCollectionConsentHelper>();
- consent_helper_ = consent_helper.get();
fetcher_ = std::make_unique<ContextualSuggestionsFetcherImpl>(
- shared_url_loader_factory_, std::move(consent_helper), "en");
+ shared_url_loader_factory_, "en");
}
~ContextualSuggestionsFetcherTest() override {}
- void SetUp() override { consent_helper()->SetIsEnabled(true); }
-
void SetFakeResponse(const std::string& response_data,
net::HttpStatusCode response_code = net::HTTP_OK,
network::URLLoaderCompletionStatus status =
@@ -210,15 +192,10 @@ class ContextualSuggestionsFetcherTest : public testing::Test {
TestURLLoaderFactory* test_factory() { return &test_factory_; }
- TestUrlKeyedDataCollectionConsentHelper* consent_helper() {
- return consent_helper_;
- }
-
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
network::TestURLLoaderFactory test_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
- TestUrlKeyedDataCollectionConsentHelper* consent_helper_;
std::unique_ptr<ContextualSuggestionsFetcherImpl> fetcher_;
DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsFetcherTest);
@@ -435,25 +412,7 @@ TEST_F(ContextualSuggestionsFetcherTest, RequestHeaderSetCorrectly) {
"ContextualSuggestions.FetchRequestProtoSizeKB", 1);
}
-TEST_F(ContextualSuggestionsFetcherTest, CookiesIncludedWhenConsentIsEnabled) {
- network::ResourceRequest last_resource_request;
-
- test_factory()->SetInterceptor(
- base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
- last_resource_request = request;
- }));
-
- SetFakeResponse(SerializedResponseProto("Peek Text", DefaultClusters()));
-
- MockClustersCallback callback;
- SendAndAwaitResponse(GURL("http://www.article.com/"), &callback);
-
- int load_flags = last_resource_request.load_flags;
- EXPECT_EQ(0, load_flags & net::LOAD_DO_NOT_SEND_COOKIES);
-}
-
-TEST_F(ContextualSuggestionsFetcherTest, CookiesExcludedWhenConsentIsDisabled) {
- consent_helper()->SetIsEnabled(false);
+TEST_F(ContextualSuggestionsFetcherTest, CredentialsExcluded) {
network::ResourceRequest last_resource_request;
test_factory()->SetInterceptor(
@@ -465,10 +424,7 @@ TEST_F(ContextualSuggestionsFetcherTest, CookiesExcludedWhenConsentIsDisabled) {
MockClustersCallback callback;
SendAndAwaitResponse(GURL("http://www.article.com/"), &callback);
-
- int load_flags = last_resource_request.load_flags;
- EXPECT_EQ(net::LOAD_DO_NOT_SEND_COOKIES,
- load_flags & net::LOAD_DO_NOT_SEND_COOKIES);
+ EXPECT_FALSE(last_resource_request.allow_credentials);
}
TEST_F(ContextualSuggestionsFetcherTest, ProtocolError) {
diff --git a/chromium/components/omnibox/browser/BUILD.gn b/chromium/components/omnibox/browser/BUILD.gn
index 7d18e55580b..a60bf739348 100644
--- a/chromium/components/omnibox/browser/BUILD.gn
+++ b/chromium/components/omnibox/browser/BUILD.gn
@@ -228,6 +228,7 @@ jumbo_static_library("browser") {
"//skia",
"//sql",
"//third_party/protobuf:protobuf_lite",
+ "//third_party/re2",
"//ui/base",
"//ui/gfx",
]
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.cc b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.cc
deleted file mode 100644
index 2d1df7700d5..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
-
-#include <string.h>
-
-#include <algorithm>
-#include <bitset>
-
-#include "base/logging.h"
-
-namespace password_manager {
-
-namespace {
-
-// The maximum byte length of a string to be returned by |ConsumeString*|.
-constexpr size_t kMaxStringBytes = 256;
-
-} // namespace
-
-DataAccessor::DataAccessor(const uint8_t* data, size_t size)
- : data_(data), bits_consumed_(0), size_(size) {
- DCHECK(data_ || size_ == 0); // Enforce the first invariant for data members.
-}
-
-DataAccessor::~DataAccessor() = default;
-
-bool DataAccessor::ConsumeBit() {
- return ConsumeNumber(1) != 0;
-}
-
-size_t DataAccessor::ConsumeNumber(size_t bit_length) {
- CHECK_LE(bit_length, sizeof(size_t) * 8);
-
- // Fast track.
- if (bit_length == 0)
- return 0;
-
- // No genuine input bits left, return padding.
- if (size_ == 0)
- return 0;
-
- // Compute the number recursively, processing one byte from |data_| at a time.
- std::bitset<8> b(*data_);
- if (bits_consumed_ + bit_length < 8) { // Base case: all within |*data_|.
- // Shift the |bit_length|-sized interesting window up and down to discard
- // uninteresting bits. An alternative approach would be:
- // b << bit_length; // Discard consumed bits.
- // b &= std::bitset<8>((1 << bit_length) - 1); // Discard the tail.
- // But the shifting below avoids the construction of the temproary bitset.
- b <<= (8 - bits_consumed_ - bit_length);
- b >>= (8 - bit_length);
- bits_consumed_ += bit_length;
- return b.to_ulong();
- }
- // Recursive case: crossing the byte boundary in |data_|.
- const size_t original_bits_consumed = bits_consumed_;
- bit_length -= (8 - bits_consumed_);
- bits_consumed_ = 0;
- ++data_;
- --size_;
- return (b.to_ulong() | (ConsumeNumber(bit_length) << 8)) >>
- original_bits_consumed;
-}
-
-void DataAccessor::ConsumeBytesToBuffer(size_t length, uint8_t* string_buffer) {
- // First of all, align to a whole byte for efficiency.
- if (size_ > 0 && bits_consumed_ != 0) {
- bits_consumed_ = 0;
- ++data_;
- --size_;
- }
-
- size_t non_padded_length = std::min(length, size_);
- std::memcpy(string_buffer, data_, non_padded_length);
-
- if (non_padded_length != length) {
- // Pad with zeroes as needed.
- std::memset(string_buffer + non_padded_length, 0,
- length - non_padded_length);
- // The rest of the input string was not enough, so now it's certainly
- // depleted.
- size_ = 0;
- } else {
- // There was either more of the input string than needed, or just exactly
- // enough bytes of it. Either way, the update below reflects the new
- // situation.
- size_ -= length;
- data_ += length;
- }
-}
-
-std::string DataAccessor::ConsumeString(size_t length) {
- CHECK_LE(length, kMaxStringBytes);
-
- uint8_t string_buffer[kMaxStringBytes];
- ConsumeBytesToBuffer(length, string_buffer);
- return std::string(reinterpret_cast<const char*>(string_buffer), length);
-}
-
-base::string16 DataAccessor::ConsumeString16(size_t length) {
- CHECK_LE(2 * length, kMaxStringBytes);
-
- uint8_t string_buffer[kMaxStringBytes];
- ConsumeBytesToBuffer(2 * length, string_buffer);
- return base::string16(
- reinterpret_cast<base::string16::value_type*>(string_buffer), length);
-}
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h
deleted file mode 100644
index 1130440edee..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_DATA_ACCESSOR_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_DATA_ACCESSOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-
-namespace password_manager {
-
-// DataAccessor is an encapsulation over the input string delivered by the
-// fuzzer framework. It pads the input string with zeroes after its end and
-// deliveres data based on the consumed string. More details in the design doc
-// linked from https://crbug.com/827945#c2.
-class DataAccessor {
- public:
- // Wraps the input string of length |size| at address |data|. Does not own the
- // input string. It sets the "reading head" to the start of the string and
- // advances it with each Consume* operation to avoid generating data from the
- // same part of input twice.
- DataAccessor(const uint8_t* data, size_t size);
-
- ~DataAccessor();
-
- // Return the next bit and advance the "reading head" by one bit.
- bool ConsumeBit();
-
- // Return the number stored on the next |bit_length| bits and advance the
- // "reading head" by |bit_length| bits.
- size_t ConsumeNumber(size_t bit_length);
-
- // Advance the "reading head" to the next whole-byte boundary, if needed, then
- // return the string stored in the next |length| characters, advancing the
- // "reading head" to point past the read data. A "character" means byte for
- // std::string and two bytes for base::string16. At most 256 bytes can be
- // consumed at once, hence |length| is restricted as noted below.
- std::string ConsumeString(size_t length); // |length| <= 256
- base::string16 ConsumeString16(size_t length); // |length| <= 128
-
- private:
- // Helper for |ConsumeString*|. It combines the |data_| and padding, if
- // needed, into |string_buffer|, to provide |length| bytes for creating a new
- // string. It also updates |data_|, |bits_consumed_| and |size_| accordingly.
- void ConsumeBytesToBuffer(size_t length, uint8_t* string_buffer);
-
- // The remaining portion of the input string (without padding) starts at
- // |data_| without the least significant |bits_consumed_| bits, and lasts
- // until |data_ + size_|, exclusively. If |size_| is 0, then there is not a
- // single bit left and all available is just the 0-padding.
- // Invariants:
- // * |data_| is not null as long as |size_| > 0
- // * |bits_consumed_| < 8
- // * if |size_| == 0 then |bits_consumed_| == 0
- const uint8_t* data_;
- size_t bits_consumed_;
- size_t size_;
-
- DISALLOW_COPY_AND_ASSIGN(DataAccessor);
-};
-
-} // namespace password_manager
-
-#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_DATA_ACCESSOR_H_
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor_unittest.cc b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor_unittest.cc
deleted file mode 100644
index ffbf4304aee..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/data_accessor_unittest.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
-
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::UTF8ToUTF16;
-
-namespace password_manager {
-
-namespace {
-
-TEST(DataAccessorTest, NullInput) {
- DataAccessor accessor(nullptr, 0);
- EXPECT_EQ(0u, accessor.ConsumeNumber(13));
- EXPECT_EQ(false, accessor.ConsumeBit());
- EXPECT_EQ(std::string("\0\0\0", 3), accessor.ConsumeString(3));
- EXPECT_EQ(base::string16(), accessor.ConsumeString16(0));
-}
-
-TEST(DataAccessorTest, Bit) {
- const uint8_t x = 0b10110001;
- DataAccessor accessor(&x, 1);
- EXPECT_EQ(true, accessor.ConsumeBit());
- EXPECT_EQ(false, accessor.ConsumeBit());
- EXPECT_EQ(false, accessor.ConsumeBit());
- EXPECT_EQ(false, accessor.ConsumeBit());
- EXPECT_EQ(true, accessor.ConsumeBit());
- EXPECT_EQ(true, accessor.ConsumeBit());
- EXPECT_EQ(false, accessor.ConsumeBit());
- EXPECT_EQ(true, accessor.ConsumeBit());
-}
-
-TEST(DataAccessorTest, Number) {
- const uint8_t xs[] = {0b01100110, 0b11100110};
- DataAccessor accessor(xs, sizeof(xs));
- accessor.ConsumeBit(); // Just skip the first bit for fun.
- EXPECT_EQ(0b011u, accessor.ConsumeNumber(3));
- EXPECT_EQ(0b0u, accessor.ConsumeNumber(1));
- EXPECT_EQ(0b11u, accessor.ConsumeNumber(2));
- // 10 (2nd byte) ++ 0 (1st byte):
- EXPECT_EQ(0b100u, accessor.ConsumeNumber(3));
- EXPECT_EQ(0u, accessor.ConsumeNumber(0)); // An empty string represents 0.
- EXPECT_EQ(0b11001u, accessor.ConsumeNumber(5));
- EXPECT_EQ(0b01u, accessor.ConsumeNumber(2)); // 1, also reaching padding
- EXPECT_EQ(0b0000000u, accessor.ConsumeNumber(7)); // padding
-}
-
-TEST(DataAccessorTest, String) {
- const std::string str = "Test string 123.";
- DataAccessor accessor(reinterpret_cast<const uint8_t*>(str.c_str()),
- str.size());
- EXPECT_EQ("Test", accessor.ConsumeString(4));
- accessor.ConsumeNumber(3); // Skip 3 bits to test re-alignment.
- EXPECT_EQ("string 123", accessor.ConsumeString(10));
- EXPECT_EQ(std::string(), accessor.ConsumeString(0));
- // Test also that padding is included.
- EXPECT_EQ(std::string(".\0\0", 3), accessor.ConsumeString(3));
-}
-
-TEST(DataAccessorTest, String16) {
- const base::string16 str = UTF8ToUTF16("Test string 123.");
- DataAccessor accessor(reinterpret_cast<const uint8_t*>(str.c_str()),
- str.size() * 2);
- EXPECT_EQ(UTF8ToUTF16("Test"), accessor.ConsumeString16(4));
- accessor.ConsumeNumber(13); // Skip 13 bits to test re-alignment.
- EXPECT_EQ(UTF8ToUTF16("string 123"), accessor.ConsumeString16(10));
- EXPECT_EQ(base::string16(), accessor.ConsumeString16(0));
- // Test also that padding is included.
- EXPECT_EQ(UTF8ToUTF16(std::string(".\0\0", 3)), accessor.ConsumeString16(3));
-}
-
-TEST(DataAccessorTest, Mix) {
- const uint8_t xs[] = {'a', 'b', 0b11100101, 5, 9,
- 0b10000001, 'c', 'd', 'e', 0};
- DataAccessor accessor(xs, sizeof(xs));
- EXPECT_EQ("ab", accessor.ConsumeString(2));
- EXPECT_EQ(true, accessor.ConsumeBit());
- EXPECT_EQ(0b1110010u, accessor.ConsumeNumber(7));
- EXPECT_EQ(5u, accessor.ConsumeNumber(8));
- EXPECT_EQ(9u + (1u << 8), accessor.ConsumeNumber(9));
- EXPECT_EQ(false, accessor.ConsumeBit());
- EXPECT_EQ("cd", accessor.ConsumeString(2));
- EXPECT_EQ(UTF8ToUTF16("e"), accessor.ConsumeString16(1));
-}
-} // namespace
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_essentials.proto b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_essentials.proto
deleted file mode 100644
index fde6d4bdadc..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_essentials.proto
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto3";
-package form_data_fuzzer;
-
-// The FormField message describes those data members of
-// autofill::FormFieldData, which are interesting for the FormData parsing code
-// being fuzzed.
-message FormField {
- bool is_focusable = 1;
- string form_control_type = 2;
- string autocomplete_attribute = 3;
- string label = 4;
- string name = 5;
- string id = 6;
- string value = 7;
-}
-
-// The Form message describes those data members of autofill::FormData, which
-// are interesting for the FormData parsing code being fuzzed.
-message Form {
- bool is_mode_filling = 1;
- bool is_form_tag = 2;
- bool is_formless_checkout = 3;
- string name = 4;
- string action = 5;
- string origin = 6;
- string main_frame_origin = 7;
- string id = 9;
- repeated FormField fields = 8;
-}
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc
deleted file mode 100644
index e00006c72d4..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "components/autofill/core/common/form_field_data.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-using autofill::FormData;
-using autofill::FormFieldData;
-
-namespace password_manager {
-
-namespace {
-
-struct FormFieldDataParams {
- size_t form_control_type_length;
- size_t autocomplete_attribute_length;
- size_t label_length;
- size_t name_length;
- size_t id_length;
- size_t value_length;
- // In an array of FormFieldData, all instances with |same_value_field| true
- // get the same value as the first such instance.
- bool same_value_field;
-};
-
-} // namespace
-
-FormData GenerateWithDataAccessor(DataAccessor* accessor) {
- FormData result;
-
- // First determine the main non-string attributes not specific to particular
- // fields.
- result.is_form_tag = accessor->ConsumeBit();
- result.is_formless_checkout = accessor->ConsumeBit();
-
- // To minimize wasting bits, string-based data itself gets extracted after all
- // numbers and flags are. Their length can be determined now, however. A
- // reasonable range is 0-127 characters, i.e., 7 bits.
- const size_t name_length = accessor->ConsumeNumber(7);
- const size_t action_length = accessor->ConsumeNumber(7);
- const size_t origin_length = accessor->ConsumeNumber(7);
- const size_t main_frame_origin_length = accessor->ConsumeNumber(7);
-
- // Determine how many fields this form will have. 0-15, i.e., 4 bits.
- const size_t number_of_fields = accessor->ConsumeNumber(4);
- result.fields.resize(number_of_fields);
- FormFieldDataParams field_params[15];
-
- int first_field_with_same_value = -1;
- for (size_t i = 0; i < number_of_fields; ++i) {
- // Determine the non-string value for each field.
- result.fields[i].is_focusable = accessor->ConsumeBit();
- // And the lengths of the string values.
- field_params[i].form_control_type_length = accessor->ConsumeNumber(7);
- field_params[i].autocomplete_attribute_length = accessor->ConsumeNumber(7);
- field_params[i].label_length = accessor->ConsumeNumber(7);
- field_params[i].name_length = accessor->ConsumeNumber(7);
- field_params[i].id_length = accessor->ConsumeNumber(7);
- field_params[i].same_value_field = accessor->ConsumeBit();
- bool has_value_copy_from_earlier = field_params[i].same_value_field;
- if (field_params[i].same_value_field && first_field_with_same_value == -1) {
- first_field_with_same_value = static_cast<int>(i);
- has_value_copy_from_earlier = false;
- }
- // Emtpy values are interesting from the parsing perspective. Ensure that a
- // big chunk of the cases ends up with an empty value by letting an input
- // bit decide.
- field_params[i].value_length = 0;
- if (!has_value_copy_from_earlier && accessor->ConsumeBit()) {
- field_params[i].value_length = accessor->ConsumeNumber(7) + 1;
- }
- }
-
- // Now go back and determine the string-based values of the form itself.
- result.name = accessor->ConsumeString16(name_length);
- result.action = GURL(accessor->ConsumeString(action_length));
- result.origin = GURL(accessor->ConsumeString(origin_length));
- result.main_frame_origin = url::Origin::Create(
- GURL(accessor->ConsumeString(main_frame_origin_length)));
-
- // And finally do the same for all the fields.
- for (size_t i = 0; i < number_of_fields; ++i) {
- result.fields[i].form_control_type =
- accessor->ConsumeString(field_params[i].form_control_type_length);
- result.fields[i].autocomplete_attribute =
- accessor->ConsumeString(field_params[i].autocomplete_attribute_length);
- result.fields[i].label =
- accessor->ConsumeString16(field_params[i].label_length);
- result.fields[i].name =
- accessor->ConsumeString16(field_params[i].name_length);
- result.fields[i].name_attribute = result.fields[i].name;
- result.fields[i].id_attribute =
- accessor->ConsumeString16(field_params[i].id_length);
-#if defined(OS_IOS)
- result.fields[i].unique_id = result.fields[i].id_attribute +
- base::UTF8ToUTF16("-") +
- base::NumberToString16(i);
-#endif
- if (field_params[i].same_value_field &&
- first_field_with_same_value != static_cast<int>(i)) {
- result.fields[i].value = result.fields[first_field_with_same_value].value;
- } else {
- result.fields[i].value =
- accessor->ConsumeString16(field_params[i].value_length);
- }
- }
-
- return result;
-}
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h
deleted file mode 100644
index 3ea1b798c0f..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_FORM_DATA_PRODUCER_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_FORM_DATA_PRODUCER_H_
-
-#include "components/autofill/core/common/form_data.h"
-
-namespace password_manager {
-
-class DataAccessor;
-
-// Generates a |FormData| object based on values obtained via |accessor|. See
-// https://goo.gl/29t6VH for a detailed design.
-autofill::FormData GenerateWithDataAccessor(DataAccessor* accessor);
-
-} // namespace password_manager
-
-#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_FORM_DATA_PRODUCER_H_
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.cc b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.cc
deleted file mode 100644
index 356c7b6abd7..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "components/autofill/core/common/form_field_data.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_essentials.pb.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-using autofill::FormData;
-using autofill::FormFieldData;
-using base::UTF8ToUTF16;
-
-namespace password_manager {
-
-FormData GenerateWithProto(const ::form_data_fuzzer::Form& form_proto) {
- FormData result;
-
- result.id_attribute = UTF8ToUTF16(form_proto.id());
- result.name_attribute = UTF8ToUTF16(form_proto.name());
- result.is_form_tag = form_proto.is_form_tag();
- result.is_formless_checkout = form_proto.is_formless_checkout();
- result.name = UTF8ToUTF16(form_proto.name());
- result.action = GURL(form_proto.action());
- result.origin = GURL(form_proto.origin());
- result.main_frame_origin =
- url::Origin::Create(GURL(form_proto.main_frame_origin()));
-
- result.fields.resize(form_proto.fields_size());
- for (int i = 0; i < form_proto.fields_size(); ++i) {
- const ::form_data_fuzzer::FormField& form_data_proto = form_proto.fields(i);
- result.fields[i].id_attribute = UTF8ToUTF16(form_data_proto.id());
-#if defined(OS_IOS)
- result.fields[i].unique_id = result.fields[i].id_attribute +
- base::UTF8ToUTF16("-") +
- base::NumberToString16(i);
-#endif
- result.fields[i].name_attribute = UTF8ToUTF16(form_data_proto.name());
- result.fields[i].is_focusable = form_data_proto.is_focusable();
- result.fields[i].form_control_type = form_data_proto.form_control_type();
- result.fields[i].autocomplete_attribute =
- form_data_proto.autocomplete_attribute();
- result.fields[i].label = UTF8ToUTF16(form_data_proto.label());
- result.fields[i].name = UTF8ToUTF16(form_data_proto.name());
- result.fields[i].value = UTF8ToUTF16(form_data_proto.value());
- }
-
- return result;
-}
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.h b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.h
deleted file mode 100644
index 2542323f889..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_FORM_DATA_PROTO_PRODUCER_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_FORM_DATA_PROTO_PRODUCER_H_
-
-#include "components/autofill/core/common/form_data.h"
-
-namespace form_data_fuzzer {
-class Form;
-}
-
-namespace password_manager {
-
-// Generates a |FormData| object based on values represented by a parsed
-// protobuf |form_proto|.
-autofill::FormData GenerateWithProto(
- const ::form_data_fuzzer::Form& form_proto);
-
-} // namespace password_manager
-
-#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FUZZER_FORM_DATA_PROTO_PRODUCER_H_
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_fuzzer.cc b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_fuzzer.cc
deleted file mode 100644
index 2f581e32e10..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_fuzzer.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/at_exit.h"
-#include "base/i18n/icu_util.h"
-#include "components/autofill/core/common/password_form.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h"
-#include "components/password_manager/core/browser/form_parsing/ios_form_parser.h"
-
-namespace password_manager {
-
-// ICU is used inside GURL parser, which is used by GenerateWithDataAccessor.
-struct IcuEnvironment {
- IcuEnvironment() { CHECK(base::i18n::InitializeICU()); }
- // used by ICU integration.
- base::AtExitManager at_exit_manager;
-};
-
-IcuEnvironment* env = new IcuEnvironment();
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- DataAccessor accessor(data, size);
- FormParsingMode mode = accessor.ConsumeBit() ? FormParsingMode::FILLING
- : FormParsingMode::SAVING;
- autofill::FormData form_data = GenerateWithDataAccessor(&accessor);
- std::unique_ptr<autofill::PasswordForm> result =
- ParseFormData(form_data, mode);
- if (result) {
- // Create a copy of the result -- running the copy-constructor might
- // discover some invalid data in |result|.
- autofill::PasswordForm copy(*result);
- }
- return 0;
-}
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_fuzzer.dict b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_fuzzer.dict
deleted file mode 100644
index 16e42119107..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_fuzzer.dict
+++ /dev/null
@@ -1,9 +0,0 @@
-"http://"
-"password"
-"username"
-"current-password"
-"new-password"
-"cc-name"
-"cc-number"
-"cc-csc"
-"cc-exp"
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_generic_fuzzer.cc b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_generic_fuzzer.cc
deleted file mode 100644
index 81dc4fb5262..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_generic_fuzzer.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/at_exit.h"
-#include "base/i18n/icu_util.h"
-#include "components/autofill/core/common/password_form.h"
-#include "components/password_manager/core/browser/form_parsing/form_parser.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.h"
-
-namespace password_manager {
-
-// ICU is used inside GURL parser, which is used by GenerateWithDataAccessor.
-struct IcuEnvironment {
- IcuEnvironment() { CHECK(base::i18n::InitializeICU()); }
- // used by ICU integration.
- base::AtExitManager at_exit_manager;
-};
-
-IcuEnvironment* env = new IcuEnvironment();
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- DataAccessor accessor(data, size);
- FormDataParser::Mode mode = accessor.ConsumeBit()
- ? FormDataParser::Mode::kFilling
- : FormDataParser::Mode::kSaving;
- autofill::FormData form_data = GenerateWithDataAccessor(&accessor);
-
- FormDataParser parser;
- std::unique_ptr<autofill::PasswordForm> result =
- parser.Parse(form_data, mode);
- if (result) {
- // Create a copy of the result -- running the copy-constructor might
- // discover some invalid data in |result|.
- autofill::PasswordForm copy(*result);
- }
- return 0;
-}
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_proto_fuzzer.cc b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_proto_fuzzer.cc
deleted file mode 100644
index d4728e3e8e4..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_proto_fuzzer.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/at_exit.h"
-#include "base/i18n/icu_util.h"
-#include "components/autofill/core/common/password_form.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_essentials.pb.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.h"
-#include "components/password_manager/core/browser/form_parsing/ios_form_parser.h"
-#include "testing/libfuzzer/proto/lpm_interface.h"
-
-namespace password_manager {
-
-// ICU is used inside GURL parser, which is used by GenerateWithDataAccessor.
-struct IcuEnvironment {
- IcuEnvironment() { CHECK(base::i18n::InitializeICU()); }
- // used by ICU integration.
- base::AtExitManager at_exit_manager;
-};
-
-IcuEnvironment* env = new IcuEnvironment();
-
-DEFINE_BINARY_PROTO_FUZZER(const ::form_data_fuzzer::Form& form_proto) {
- FormParsingMode mode = form_proto.is_mode_filling() ? FormParsingMode::FILLING
- : FormParsingMode::SAVING;
- autofill::FormData form_data = GenerateWithProto(form_proto);
- std::unique_ptr<autofill::PasswordForm> result =
- ParseFormData(form_data, mode);
- if (result) {
- // Create a copy of the result -- running the copy-constructor might
- // discover some invalid data in |result|.
- autofill::PasswordForm copy(*result);
- }
-}
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_proto_generic_fuzzer.cc b/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_proto_generic_fuzzer.cc
deleted file mode 100644
index 7d2508a6f41..00000000000
--- a/chromium/components/password_manager/core/browser/form_parsing/fuzzer/form_parser_proto_generic_fuzzer.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/at_exit.h"
-#include "base/i18n/icu_util.h"
-#include "components/autofill/core/common/password_form.h"
-#include "components/password_manager/core/browser/form_parsing/form_parser.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_essentials.pb.h"
-#include "components/password_manager/core/browser/form_parsing/fuzzer/form_data_proto_producer.h"
-#include "testing/libfuzzer/proto/lpm_interface.h"
-
-namespace password_manager {
-
-// ICU is used inside GURL parser, which is used by GenerateWithDataAccessor.
-struct IcuEnvironment {
- IcuEnvironment() { CHECK(base::i18n::InitializeICU()); }
- // used by ICU integration.
- base::AtExitManager at_exit_manager;
-};
-
-IcuEnvironment* env = new IcuEnvironment();
-
-DEFINE_BINARY_PROTO_FUZZER(const ::form_data_fuzzer::Form& form_proto) {
- FormDataParser::Mode mode = form_proto.is_mode_filling()
- ? FormDataParser::Mode::kFilling
- : FormDataParser::Mode::kSaving;
- autofill::FormData form_data = GenerateWithProto(form_proto);
-
- FormDataParser parser;
- std::unique_ptr<autofill::PasswordForm> result =
- parser.Parse(form_data, mode);
- if (result) {
- // Create a copy of the result -- running the copy-constructor might
- // discover some invalid data in |result|.
- autofill::PasswordForm copy(*result);
- }
-}
-
-} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/new_password_form_manager.cc b/chromium/components/password_manager/core/browser/new_password_form_manager.cc
index e2de6dd1d74..8d4fb9e2ee9 100644
--- a/chromium/components/password_manager/core/browser/new_password_form_manager.cc
+++ b/chromium/components/password_manager/core/browser/new_password_form_manager.cc
@@ -315,8 +315,23 @@ void NewPasswordFormManager::UpdateUsername(
parsed_submitted_form_->username_value = new_username;
parsed_submitted_form_->username_element.clear();
- // TODO(https://crbug.com/831123): Implement processing username editing votes
- // after implementation of |other_possible_usernames|.
+ // |has_username_edited_vote_| is true iff |new_username| was typed in another
+ // field. Otherwise, |has_username_edited_vote_| is false and no vote will be
+ // uploaded.
+ votes_uploader_.set_has_username_edited_vote(false);
+ if (!new_username.empty()) {
+ // |other_possible_usernames| has all possible usernames.
+ // TODO(crbug.com/831123): rename to |all_possible_usernames| when the old
+ // parser is gone.
+ for (const auto& possible_username :
+ parsed_submitted_form_->other_possible_usernames) {
+ if (possible_username.first == new_username) {
+ parsed_submitted_form_->username_element = possible_username.second;
+ votes_uploader_.set_has_username_edited_vote(true);
+ break;
+ }
+ }
+ }
CreatePendingCredentials();
}
@@ -343,15 +358,29 @@ void NewPasswordFormManager::UpdatePasswordValue(
CreatePendingCredentials();
}
-// TODO(https://crbug.com/831123): Implement all methods from
-// PasswordFormManagerForUI.
-void NewPasswordFormManager::OnNopeUpdateClicked() {}
+void NewPasswordFormManager::OnNopeUpdateClicked() {
+ votes_uploader_.UploadPasswordVote(*parsed_submitted_form_,
+ *parsed_submitted_form_,
+ autofill::NOT_NEW_PASSWORD, std::string());
+}
void NewPasswordFormManager::OnNeverClicked() {
+ // |UNKNOWN_TYPE| is sent in order to record that a generation popup was
+ // shown and ignored.
+ votes_uploader_.UploadPasswordVote(*parsed_submitted_form_,
+ *parsed_submitted_form_,
+ autofill::UNKNOWN_TYPE, std::string());
PermanentlyBlacklist();
}
-void NewPasswordFormManager::OnNoInteraction(bool is_update) {}
+void NewPasswordFormManager::OnNoInteraction(bool is_update) {
+ // |UNKNOWN_TYPE| is sent in order to record that a generation popup was
+ // shown and ignored.
+ votes_uploader_.UploadPasswordVote(
+ *parsed_submitted_form_, *parsed_submitted_form_,
+ is_update ? autofill::PROBABLY_NEW_PASSWORD : autofill::UNKNOWN_TYPE,
+ std::string());
+}
void NewPasswordFormManager::PermanentlyBlacklist() {
DCHECK(!client_->IsIncognito());
@@ -365,7 +394,9 @@ void NewPasswordFormManager::PermanentlyBlacklist() {
form_saver_->PermanentlyBlacklist(new_blacklisted_.get());
}
-void NewPasswordFormManager::OnPasswordsRevealed() {}
+void NewPasswordFormManager::OnPasswordsRevealed() {
+ votes_uploader_.set_has_passwords_revealed_vote(true);
+}
bool NewPasswordFormManager::IsNewLogin() const {
return is_new_login_;
diff --git a/chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc b/chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc
index 1b65f68d918..f12d540d1cb 100644
--- a/chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/new_password_form_manager_unittest.cc
@@ -26,6 +26,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using autofill::AutofillUploadContents;
using autofill::FieldPropertiesFlags;
using autofill::FormData;
using autofill::FormFieldData;
@@ -39,6 +40,7 @@ using base::ASCIIToUTF16;
using base::TestMockTimeTaskRunner;
using testing::_;
using testing::AllOf;
+using testing::Contains;
using testing::Mock;
using testing::NiceMock;
using testing::Return;
@@ -947,6 +949,7 @@ TEST_F(NewPasswordFormManagerTest, UpdatePasswordOnChangePasswordForm) {
EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
EXPECT_FALSE(form_manager_->IsNewLogin());
EXPECT_FALSE(form_manager_->IsPasswordOverridden());
+ EXPECT_TRUE(form_manager_->IsPasswordUpdate());
MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
PasswordForm updated_form;
@@ -977,38 +980,43 @@ TEST_F(NewPasswordFormManagerTest, UpdatePasswordOnChangePasswordForm) {
TEST_F(NewPasswordFormManagerTest, VotesUploadingOnPasswordUpdate) {
TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
- CreateFormManager(observed_form_only_password_fields_);
- fetcher_->SetNonFederated({&saved_match_}, 0u);
- FormData submitted_form = observed_form_only_password_fields_;
- submitted_form.fields[0].value = saved_match_.password_value;
- base::string16 new_password = saved_match_.password_value + ASCIIToUTF16("1");
- submitted_form.fields[1].value = new_password;
-
- EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
- EXPECT_TRUE(form_manager_->IsPasswordUpdate());
-
- MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
- PasswordForm updated_form;
- std::map<base::string16, const PasswordForm*> best_matches;
- std::vector<PasswordForm> credentials_to_update;
- EXPECT_CALL(form_saver, Update(_, _, _, nullptr))
- .WillOnce(DoAll(SaveArg<0>(&updated_form), SaveArg<1>(&best_matches),
- SaveArgPointee<2>(&credentials_to_update)));
-
- std::map<base::string16, autofill::ServerFieldType> expected_types;
- expected_types[ASCIIToUTF16("password")] = autofill::PASSWORD;
- expected_types[ASCIIToUTF16("password2")] = autofill::NEW_PASSWORD;
+ for (auto expected_vote :
+ {autofill::NEW_PASSWORD, autofill::PROBABLY_NEW_PASSWORD,
+ autofill::NOT_NEW_PASSWORD}) {
+ SCOPED_TRACE(testing::Message("expected_vote=") << expected_vote);
+ CreateFormManager(observed_form_only_password_fields_);
+ fetcher_->SetNonFederated({&saved_match_}, 0u);
- testing::InSequence in_sequence;
- EXPECT_CALL(mock_autofill_download_manager_,
- StartUploadRequest(UploadedAutofillTypesAre(expected_types),
- false, _, _, true, nullptr));
- // An unrelated |FIRST_USE| vote.
- EXPECT_CALL(mock_autofill_download_manager_,
- StartUploadRequest(_, _, _, _, _, _));
+ FormData submitted_form = observed_form_only_password_fields_;
+ submitted_form.fields[0].value = saved_match_.password_value;
+ auto new_password = saved_match_.password_value + ASCIIToUTF16("1");
+ submitted_form.fields[1].value = new_password;
+
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form, &driver_));
+
+ std::map<base::string16, autofill::ServerFieldType> expected_types;
+ expected_types[ASCIIToUTF16("password")] = autofill::PASSWORD;
+ expected_types[ASCIIToUTF16("password2")] = expected_vote;
+
+ testing::InSequence in_sequence;
+ EXPECT_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(UploadedAutofillTypesAre(expected_types),
+ false, _, _, true, nullptr));
+ if (expected_vote == autofill::NEW_PASSWORD) {
+ // An unrelated |FIRST_USE| vote.
+ EXPECT_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(_, _, _, _, _, _));
+ }
- form_manager_->Save();
+ if (expected_vote == autofill::NEW_PASSWORD)
+ form_manager_->Save();
+ else if (expected_vote == autofill::PROBABLY_NEW_PASSWORD)
+ form_manager_->OnNoInteraction(true /* is_update */);
+ else
+ form_manager_->OnNopeUpdateClicked();
+ Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
+ }
}
TEST_F(NewPasswordFormManagerTest, UpdateUsernameEmptyStore) {
@@ -1029,6 +1037,40 @@ TEST_F(NewPasswordFormManagerTest, UpdateUsernameEmptyStore) {
EXPECT_TRUE(form_manager_->IsNewLogin());
}
+TEST_F(NewPasswordFormManagerTest, UpdateUsernameToAnotherFieldValue) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+ fetcher_->SetNonFederated({}, 0u);
+
+ base::string16 user_chosen_username = ASCIIToUTF16("user_chosen_username");
+ base::string16 automatically_chosen_username =
+ ASCIIToUTF16("automatically_chosen_username");
+ submitted_form_.fields[0].value = user_chosen_username;
+ submitted_form_.fields[1].value = automatically_chosen_username;
+ form_manager_->ProvisionallySave(submitted_form_, &driver_);
+
+ EXPECT_EQ(automatically_chosen_username,
+ form_manager_->GetPendingCredentials().username_value);
+
+ form_manager_->UpdateUsername(user_chosen_username);
+
+ EXPECT_EQ(user_chosen_username,
+ form_manager_->GetPendingCredentials().username_value);
+
+ FieldTypeMap expected_types = {
+ {ASCIIToUTF16("firstname"), autofill::USERNAME},
+ {ASCIIToUTF16("password"), autofill::PASSWORD}};
+ VoteTypeMap expected_vote_types = {
+ {ASCIIToUTF16("firstname"),
+ AutofillUploadContents::Field::USERNAME_EDITED}};
+ EXPECT_CALL(
+ mock_autofill_download_manager_,
+ StartUploadRequest(
+ AllOf(UploadedAutofillTypesAre(expected_types),
+ HasGenerationVote(false), VoteTypesAre(expected_vote_types)),
+ _, Contains(autofill::USERNAME), _, _, nullptr));
+ form_manager_->Save();
+}
+
TEST_F(NewPasswordFormManagerTest, UpdateUsernameToAlreadyExisting) {
TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
fetcher_->SetNonFederated({&saved_match_}, 0u);
@@ -1703,6 +1745,77 @@ TEST_F(NewPasswordFormManagerTest, MAYBE_FillingAssistanceMetric) {
PasswordFormMetricsRecorder::FillingAssistance::kManual, 1);
}
+TEST_F(NewPasswordFormManagerTest, PasswordRevealedVote) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+
+ for (bool password_revealed : {false, true}) {
+ SCOPED_TRACE(testing::Message("password_revealed=") << password_revealed);
+ CreateFormManager(observed_form_);
+ fetcher_->SetNonFederated({}, 0u);
+
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+
+ if (password_revealed)
+ form_manager_->OnPasswordsRevealed();
+
+ EXPECT_CALL(mock_autofill_download_manager_,
+ StartUploadRequest(PasswordsWereRevealed(password_revealed),
+ false, _, _, true, nullptr));
+ form_manager_->Save();
+ Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
+ }
+}
+
+TEST_F(NewPasswordFormManagerTest, GenerationUploadOnNoInteraction) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+
+ for (bool generation_popup_shown : {false, true}) {
+ SCOPED_TRACE(testing::Message("generation_popup_shown=")
+ << generation_popup_shown);
+ CreateFormManager(observed_form_);
+ fetcher_->SetNonFederated({}, 0u);
+
+ if (generation_popup_shown) {
+ form_manager_->SetGenerationElement(ASCIIToUTF16("password"));
+ form_manager_->SetGenerationPopupWasShown(
+ true /*generation_popup_was_shown*/, false /*is_manual_generation*/);
+ }
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+
+ EXPECT_CALL(
+ mock_autofill_download_manager_,
+ StartUploadRequest(HasGenerationVote(true), false, _, _, true, nullptr))
+ .Times(generation_popup_shown ? 1 : 0);
+ form_manager_->OnNoInteraction(false /*is_update */);
+ Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
+ }
+}
+
+TEST_F(NewPasswordFormManagerTest, GenerationUploadOnNeverClicked) {
+ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get());
+
+ for (bool generation_popup_shown : {false, true}) {
+ SCOPED_TRACE(testing::Message("generation_popup_shown=")
+ << generation_popup_shown);
+ CreateFormManager(observed_form_);
+ fetcher_->SetNonFederated({}, 0u);
+
+ if (generation_popup_shown) {
+ form_manager_->SetGenerationElement(ASCIIToUTF16("password"));
+ form_manager_->SetGenerationPopupWasShown(
+ true /*generation_popup_was_shown*/, false /*is_manual_generation*/);
+ }
+ EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_));
+
+ EXPECT_CALL(
+ mock_autofill_download_manager_,
+ StartUploadRequest(HasGenerationVote(true), false, _, _, true, nullptr))
+ .Times(generation_popup_shown ? 1 : 0);
+ form_manager_->OnNeverClicked();
+ Mock::VerifyAndClearExpectations(&mock_autofill_download_manager_);
+ }
+}
+
} // namespace
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/vote_uploads_test_matchers.h b/chromium/components/password_manager/core/browser/vote_uploads_test_matchers.h
index 40726423521..7ee81d76622 100644
--- a/chromium/components/password_manager/core/browser/vote_uploads_test_matchers.h
+++ b/chromium/components/password_manager/core/browser/vote_uploads_test_matchers.h
@@ -158,4 +158,8 @@ MATCHER_P2(UploadedGenerationTypesAre,
return true;
}
+MATCHER_P(PasswordsWereRevealed, passwords_were_revealed, "") {
+ return passwords_were_revealed == arg.passwords_were_revealed();
+}
+
#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_VOTE_UPLOADS_TEST_MATCHERS_H_
diff --git a/chromium/components/previews/content/previews_decider_impl.cc b/chromium/components/previews/content/previews_decider_impl.cc
index ce9b27d96e6..47034fa9941 100644
--- a/chromium/components/previews/content/previews_decider_impl.cc
+++ b/chromium/components/previews/content/previews_decider_impl.cc
@@ -274,6 +274,18 @@ PreviewsEligibilityReason PreviewsDeciderImpl::DeterminePreviewEligibility(
// eligibility so that it will be available at commit time.
previews_data->set_navigation_ect(effective_connection_type_);
+ // Do not allow previews on any authenticated pages.
+ if (url.has_username() || url.has_password())
+ return PreviewsEligibilityReason::URL_HAS_BASIC_AUTH;
+
+ // Trigger the USER_RECENTLY_OPTED_OUT rule when a reload on a preview has
+ // occurred recently.
+ if (recent_preview_reload_time_ &&
+ recent_preview_reload_time_.value() + params::SingleOptOutDuration() >
+ clock_->Now()) {
+ return PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT;
+ }
+
// In the case that the user has chosen to ignore the normal blacklist rules
// (flags or interventions-internals), a preview should still not be served
// for 5 seconds after the last opt out. This allows "show original" to
@@ -536,4 +548,10 @@ void PreviewsDeciderImpl::SetEffectiveConnectionType(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
effective_connection_type_ = effective_connection_type;
}
+
+void PreviewsDeciderImpl::AddPreviewReload() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ recent_preview_reload_time_ = clock_->Now();
+}
+
} // namespace previews
diff --git a/chromium/components/previews/content/previews_decider_impl.h b/chromium/components/previews/content/previews_decider_impl.h
index aab49ccab4c..37788904bfd 100644
--- a/chromium/components/previews/content/previews_decider_impl.h
+++ b/chromium/components/previews/content/previews_decider_impl.h
@@ -131,6 +131,10 @@ class PreviewsDeciderImpl : public PreviewsDecider,
void SetEffectiveConnectionType(
net::EffectiveConnectionType effective_connection_type);
+ // When a preview is reloaded, this is called. No Previews are allowed for
+ // params::SingleOptOutDuration after that reload is reported.
+ void AddPreviewReload();
+
protected:
// Sets a blacklist for testing.
void SetPreviewsBlacklistForTesting(
@@ -201,6 +205,8 @@ class PreviewsDeciderImpl : public PreviewsDecider,
base::Clock* clock_;
+ base::Optional<base::Time> recent_preview_reload_time_;
+
// Whether the preview is enabled. Valid after Initialize() is called.
PreviewsIsEnabledCallback is_enabled_callback_;
diff --git a/chromium/components/previews/content/previews_decider_impl_unittest.cc b/chromium/components/previews/content/previews_decider_impl_unittest.cc
index d87fbd0f689..78f2b17804a 100644
--- a/chromium/components/previews/content/previews_decider_impl_unittest.cc
+++ b/chromium/components/previews/content/previews_decider_impl_unittest.cc
@@ -437,6 +437,26 @@ TEST_F(PreviewsDeciderImplTest, AllPreviewsDisabledByFeature) {
PreviewsType::NOSCRIPT));
}
+TEST_F(PreviewsDeciderImplTest, TestDisallowBasicAuthentication) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi}, {});
+ InitializeUIService();
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
+
+ base::HistogramTester histogram_tester;
+ PreviewsUserData user_data(kDefaultPageId);
+ EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
+ &user_data, GURL("https://user:pass@www.google.com"), false,
+ PreviewsType::LOFI));
+ histogram_tester.ExpectBucketCount(
+ "Previews.EligibilityReason",
+ static_cast<int>(PreviewsEligibilityReason::URL_HAS_BASIC_AUTH), 1);
+ histogram_tester.ExpectBucketCount(
+ "Previews.EligibilityReason.LoFi",
+ static_cast<int>(PreviewsEligibilityReason::URL_HAS_BASIC_AUTH), 1);
+}
+
// Tests most of the reasons that a preview could be disallowed because of the
// state of the blacklist. Excluded values are USER_RECENTLY_OPTED_OUT,
// USER_BLACKLISTED, HOST_BLACKLISTED. These are internal to the blacklist.
@@ -1528,6 +1548,38 @@ TEST_F(PreviewsDeciderImplTest, IgnoreFlagStillHasFiveSecondRule) {
::testing::Contains(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT));
}
+TEST_F(PreviewsDeciderImplTest, ReloadsTriggerFiveMinuteRule) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitWithFeatures(
+ {features::kPreviews, features::kClientLoFi,
+ features::kPreviewsReloadsAreSoftOptOuts},
+ {});
+ InitializeUIService();
+ ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
+
+ PreviewsUserData user_data(kDefaultPageId);
+ EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
+ &user_data, GURL("https://www.google.com"), false, PreviewsType::LOFI));
+
+ previews_decider_impl()->AddPreviewNavigation(
+ GURL("http://wwww.somedomain.com"), false, PreviewsType::LOFI, 1);
+
+ previews_decider_impl()->AddPreviewReload();
+
+ EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
+ &user_data, GURL("https://www.google.com"), false, PreviewsType::LOFI));
+ EXPECT_EQ(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
+ ui_service()->decision_reasons().back());
+
+ clock_.Advance(base::TimeDelta::FromMinutes(6));
+
+ EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
+ &user_data, GURL("https://www.google.com"), false, PreviewsType::LOFI));
+ EXPECT_THAT(
+ ui_service()->decision_passed_reasons().back(),
+ ::testing::Contains(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT));
+}
+
TEST_F(PreviewsDeciderImplTest,
LoFi_LogDecisionMadeNetworkQualityNotAvailable) {
base::test::ScopedFeatureList scoped_feature_list;
diff --git a/chromium/components/previews/core/previews_black_list.h b/chromium/components/previews/core/previews_black_list.h
index 3f705be5a06..0b35fffcb40 100644
--- a/chromium/components/previews/core/previews_black_list.h
+++ b/chromium/components/previews/core/previews_black_list.h
@@ -69,6 +69,8 @@ enum class PreviewsEligibilityReason {
NETWORK_NOT_SLOW_FOR_SESSION = 14,
// Device is offline.
DEVICE_OFFLINE = 15,
+ // URL contained Basic Authentication, i.e.: a username or password.
+ URL_HAS_BASIC_AUTH = 16,
LAST,
};
diff --git a/chromium/components/previews/core/previews_features.cc b/chromium/components/previews/core/previews_features.cc
index 6c87ad138d7..f440cb1cbeb 100644
--- a/chromium/components/previews/core/previews_features.cc
+++ b/chromium/components/previews/core/previews_features.cc
@@ -103,5 +103,10 @@ const base::Feature kHTTPSServerPreviewsUsingURLLoader{
const base::Feature kDataSaverLiteModeRebranding{
"DataSaverLiteModeRebranding", base::FEATURE_DISABLED_BY_DEFAULT};
+// When enabled, reloading on a preview will cause the session (5 minute) rule
+// to trigger.
+const base::Feature kPreviewsReloadsAreSoftOptOuts{
+ "PreviewsReloadsAreSoftOptOuts", base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
} // namespace previews
diff --git a/chromium/components/previews/core/previews_features.h b/chromium/components/previews/core/previews_features.h
index 9266ddeab07..99a43ac5095 100644
--- a/chromium/components/previews/core/previews_features.h
+++ b/chromium/components/previews/core/previews_features.h
@@ -25,6 +25,7 @@ extern const base::Feature kSlowPageTriggering;
extern const base::Feature kPreviewsDisallowedOnReloads;
extern const base::Feature kHTTPSServerPreviewsUsingURLLoader;
extern const base::Feature kDataSaverLiteModeRebranding;
+extern const base::Feature kPreviewsReloadsAreSoftOptOuts;
} // namespace features
} // namespace previews
diff --git a/chromium/components/previews/core/previews_lite_page_redirect.cc b/chromium/components/previews/core/previews_lite_page_redirect.cc
index 86fe7b97b54..6e50124352f 100644
--- a/chromium/components/previews/core/previews_lite_page_redirect.cc
+++ b/chromium/components/previews/core/previews_lite_page_redirect.cc
@@ -54,8 +54,11 @@ bool ExtractOriginalURLFromLitePageRedirectURL(const GURL& url,
if (!net::GetValueForKeyInQuery(url, "u", &original_url_query_param))
return false;
- if (original_url)
+ if (original_url) {
+ if (url.has_ref())
+ original_url_query_param += "#" + url.ref();
*original_url = original_url_query_param;
+ }
return true;
}
diff --git a/chromium/components/previews/core/previews_lite_page_redirect_unittest.cc b/chromium/components/previews/core/previews_lite_page_redirect_unittest.cc
index 957e283c676..13a8f145ead 100644
--- a/chromium/components/previews/core/previews_lite_page_redirect_unittest.cc
+++ b/chromium/components/previews/core/previews_lite_page_redirect_unittest.cc
@@ -38,6 +38,15 @@ TEST(PreviewsLitePageURLHandlerTest,
"http%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes",
true,
},
+ {
+ "https://previews.host.com",
+ "http://original.host.com/path/path/path?query=yes#fragment",
+ "https://6p7dar4ju6r4ynz7x3pucmlcltuqsf7z5auhvckzln7voglkt56q."
+ "previews.host.com/p?u="
+ "http%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes"
+ "#fragment",
+ true,
+ },
};
for (const TestCase& test_case : kTestCases) {
diff --git a/chromium/components/previews/core/previews_logger.cc b/chromium/components/previews/core/previews_logger.cc
index 332cce4d9a3..5799207fdb5 100644
--- a/chromium/components/previews/core/previews_logger.cc
+++ b/chromium/components/previews/core/previews_logger.cc
@@ -86,6 +86,10 @@ std::string GetReasonDescription(PreviewsEligibilityReason reason,
case PreviewsEligibilityReason::DEVICE_OFFLINE:
return want_inverse_description ? "Device is online"
: "Device is offline";
+ case PreviewsEligibilityReason::URL_HAS_BASIC_AUTH:
+ return want_inverse_description
+ ? "URL did not contain basic authentication"
+ : "URL contained basic authentication";
}
NOTREACHED();
return "";
diff --git a/chromium/components/printing/renderer/print_render_frame_helper.cc b/chromium/components/printing/renderer/print_render_frame_helper.cc
index cd9306860bb..d51abda693d 100644
--- a/chromium/components/printing/renderer/print_render_frame_helper.cc
+++ b/chromium/components/printing/renderer/print_render_frame_helper.cc
@@ -345,12 +345,6 @@ bool IsPrintingNodeOrPdfFrame(const blink::WebLocalFrame* frame,
return plugin && plugin->SupportsPaginatedPrint();
}
-bool IsPrintingFrameset(const blink::WebLocalFrame* frame) {
- return frame->GetDocument().IsHTMLDocument() &&
- !frame->GetDocument().Body().IsNull() &&
- frame->GetDocument().Body().TagName().Equals("FRAMESET");
-}
-
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
// Returns true if the current destination printer is PRINT_TO_PDF.
bool IsPrintToPdfRequested(const base::DictionaryValue& job_settings) {
@@ -1273,8 +1267,7 @@ void PrintRenderFrameHelper::OnPrintPreview(
void PrintRenderFrameHelper::PrepareFrameForPreviewDocument() {
reset_prep_frame_view_ = false;
- if (!print_pages_params_ ||
- IsPrintingFrameset(print_preview_context_.source_frame())) {
+ if (!print_pages_params_) {
print_preview_context_.set_error(PREVIEW_ERROR_ZERO_PAGES);
DidFinishPrinting(FAIL_PREVIEW);
return;
@@ -1641,11 +1634,6 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
FrameReference frame_ref(frame);
- if (IsPrintingFrameset(frame)) {
- DidFinishPrinting(FAIL_PRINT);
- return;
- }
-
int expected_page_count = 0;
if (!CalculateNumberOfPages(frame, node, &expected_page_count)) {
DidFinishPrinting(FAIL_PRINT_INIT);
diff --git a/chromium/components/resources/autofill_scaled_resources.grdp b/chromium/components/resources/autofill_scaled_resources.grdp
index 40cb93f008b..85ee0d7ef7a 100644
--- a/chromium/components/resources/autofill_scaled_resources.grdp
+++ b/chromium/components/resources/autofill_scaled_resources.grdp
@@ -11,6 +11,7 @@
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_UNIONPAY" file="autofill/unionpay.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_CC_VISA" file="autofill/visa.png" />
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_GOOGLE_PAY" file="autofill/googlepay.png" />
+ <structure type="chrome_scaled_image" name="IDR_AUTOFILL_GOOGLE_PAY_DARK" file="autofill/googlepay_dark.png" />
<!-- These are not used on desktop, only Android, so use a placeholder file.
TODO(rouslan): Remove non-keyboard-accessory icon when keyboard
@@ -27,6 +28,7 @@
<if expr="not is_android and not is_ios">
<structure type="chrome_scaled_image" name="IDR_AUTOFILL_MIGRATION_DIALOG_HEADER" file="autofill/migration_header.png" />
+ <structure type="chrome_scaled_image" name="IDR_AUTOFILL_MIGRATION_DIALOG_HEADER_DARK" file="autofill/migration_header_dark.png" />
</if>
<structure type="chrome_scaled_image" name="IDR_CREDIT_CARD_CVC_HINT" file="autofill/credit_card_cvc_hint.png" />
diff --git a/chromium/components/resources/default_100_percent/autofill/googlepay_dark.png b/chromium/components/resources/default_100_percent/autofill/googlepay_dark.png
new file mode 100644
index 00000000000..0299246196d
--- /dev/null
+++ b/chromium/components/resources/default_100_percent/autofill/googlepay_dark.png
Binary files differ
diff --git a/chromium/components/resources/default_100_percent/autofill/migration_header_dark.png b/chromium/components/resources/default_100_percent/autofill/migration_header_dark.png
new file mode 100644
index 00000000000..5893ea3d855
--- /dev/null
+++ b/chromium/components/resources/default_100_percent/autofill/migration_header_dark.png
Binary files differ
diff --git a/chromium/components/resources/default_200_percent/autofill/googlepay_dark.png b/chromium/components/resources/default_200_percent/autofill/googlepay_dark.png
new file mode 100644
index 00000000000..45b0e251dfe
--- /dev/null
+++ b/chromium/components/resources/default_200_percent/autofill/googlepay_dark.png
Binary files differ
diff --git a/chromium/components/resources/default_200_percent/autofill/migration_header_dark.png b/chromium/components/resources/default_200_percent/autofill/migration_header_dark.png
new file mode 100644
index 00000000000..b39066c7a2f
--- /dev/null
+++ b/chromium/components/resources/default_200_percent/autofill/migration_header_dark.png
Binary files differ
diff --git a/chromium/components/resources/default_300_percent/autofill/googlepay_dark.png b/chromium/components/resources/default_300_percent/autofill/googlepay_dark.png
new file mode 100644
index 00000000000..18bbe69af7a
--- /dev/null
+++ b/chromium/components/resources/default_300_percent/autofill/googlepay_dark.png
Binary files differ
diff --git a/chromium/components/resources/default_300_percent/autofill/migration_header_dark.png b/chromium/components/resources/default_300_percent/autofill/migration_header_dark.png
new file mode 100644
index 00000000000..37992e47ba0
--- /dev/null
+++ b/chromium/components/resources/default_300_percent/autofill/migration_header_dark.png
Binary files differ
diff --git a/chromium/components/safe_browsing/features.cc b/chromium/components/safe_browsing/features.cc
index 41a24b1c779..f00d697bedd 100644
--- a/chromium/components/safe_browsing/features.cc
+++ b/chromium/components/safe_browsing/features.cc
@@ -23,8 +23,9 @@ const base::Feature kAdSamplerTriggerFeature{"SafeBrowsingAdSamplerTrigger",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls the billing interstitial UI.
+// TODO(http://crbug.com/933807): remove this base::Feature after a full launch.
const base::Feature kBillingInterstitial{"BillingInterstitial",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// If enabled in pre-network-service world, SafeBrowsing URL checks are done by
// applying SafeBrowsing's URLLoaderThrottle subclasses to ThrottlingURLLoader.
diff --git a/chromium/components/search_provider_logos/google_logo_api.cc b/chromium/components/search_provider_logos/google_logo_api.cc
index bc180064969..2ef1c087c36 100644
--- a/chromium/components/search_provider_logos/google_logo_api.cc
+++ b/chromium/components/search_provider_logos/google_logo_api.cc
@@ -208,18 +208,23 @@ std::unique_ptr<EncodedLogo> ParseDoodleLogoResponse(
const base::DictionaryValue* share_button = nullptr;
std::string short_link_str;
// The short link in the doodle proto is an incomplete URL with the format
- // //g.co/*. Complete the URL if possible.
+ // //g.co/*, //doodle.gle/* or //google.com?doodle=*.
+ // Complete the URL if possible.
if (ddljson->GetDictionary("share_button", &share_button) &&
ddljson->GetString("short_link", &short_link_str) &&
- short_link_str.find("//g.co") == 0) {
- share_button->GetInteger("offset_x", &logo->metadata.share_button_x);
- share_button->GetInteger("offset_y", &logo->metadata.share_button_y);
- share_button->GetDouble("opacity", &logo->metadata.share_button_opacity);
- share_button->GetString("icon_image", &logo->metadata.share_button_icon);
- share_button->GetString("background_color",
- &logo->metadata.share_button_bg);
+ short_link_str.find("//") == 0) {
short_link_str.insert(0, "https:");
logo->metadata.short_link = GURL(short_link_str);
+ if (logo->metadata.short_link.is_valid()) {
+ share_button->GetInteger("offset_x", &logo->metadata.share_button_x);
+ share_button->GetInteger("offset_y", &logo->metadata.share_button_y);
+ share_button->GetDouble("opacity",
+ &logo->metadata.share_button_opacity);
+ share_button->GetString("icon_image",
+ &logo->metadata.share_button_icon);
+ share_button->GetString("background_color",
+ &logo->metadata.share_button_bg);
+ }
}
}
diff --git a/chromium/components/search_provider_logos/google_logo_api_unittest.cc b/chromium/components/search_provider_logos/google_logo_api_unittest.cc
index 1e63d72a4c3..fa56f9ae58b 100644
--- a/chromium/components/search_provider_logos/google_logo_api_unittest.cc
+++ b/chromium/components/search_provider_logos/google_logo_api_unittest.cc
@@ -217,7 +217,7 @@ TEST(GoogleNewLogoApiTest, ParsesShareButtonForSimpleDoodle) {
EXPECT_EQ(0.5, logo->metadata.share_button_opacity);
}
-TEST(GoogleNewLogoApiTest, ParsesNoShareButtonIfShortLinkInvalid) {
+TEST(GoogleNewLogoApiTest, ParsesNoShareButtonIfWrongShortLinkFormat) {
const GURL base_url("https://base.doo/");
// Note: The base64 encoding of "abc" is "YWJj".
const std::string json = R"json()]}'
@@ -225,7 +225,7 @@ TEST(GoogleNewLogoApiTest, ParsesNoShareButtonIfShortLinkInvalid) {
"ddljson": {
"doodle_type": "SIMPLE",
"data_uri": "data:image/png;base64,YWJj",
- "short_link": "invalid.club",
+ "short_link": "www.//g.co",
"share_button": {
"background_color": "#fe8080",
"icon_image": "test_img",
@@ -251,6 +251,40 @@ TEST(GoogleNewLogoApiTest, ParsesNoShareButtonIfShortLinkInvalid) {
EXPECT_EQ(0, logo->metadata.share_button_opacity);
}
+TEST(GoogleNewLogoApiTest, ParsesNoShareButtonIfShortLinkInvalid) {
+ const GURL base_url("https://base.doo/");
+ // Note: The base64 encoding of "abc" is "YWJj".
+ const std::string json = R"json()]}'
+{
+ "ddljson": {
+ "doodle_type": "SIMPLE",
+ "data_uri": "data:image/png;base64,YWJj",
+ "short_link": "//dsdjf2(*&^%&",
+ "share_button": {
+ "background_color": "#fe8080",
+ "icon_image": "test_img",
+ "offset_x": 111,
+ "offset_y": 222,
+ "opacity": 0.5
+ }
+ }
+})json";
+
+ bool failed = false;
+ std::unique_ptr<EncodedLogo> logo = ParseDoodleLogoResponse(
+ base_url, std::make_unique<std::string>(json), base::Time(), &failed);
+
+ ASSERT_FALSE(failed);
+ ASSERT_TRUE(logo);
+ EXPECT_EQ("abc", logo->encoded_image->data());
+ EXPECT_EQ(LogoType::SIMPLE, logo->metadata.type);
+ ASSERT_FALSE(logo->metadata.short_link.is_valid());
+ ASSERT_TRUE(logo->metadata.share_button_icon.empty());
+ EXPECT_EQ(-1, logo->metadata.share_button_x);
+ EXPECT_EQ(-1, logo->metadata.share_button_y);
+ EXPECT_EQ(0, logo->metadata.share_button_opacity);
+}
+
TEST(GoogleNewLogoApiTest, ParsesShareButtonForAnimatedDoodle) {
const GURL base_url("https://base.doo/");
// Note: The base64 encoding of "abc" is "YWJj".
diff --git a/chromium/components/strings/components_chromium_strings_te.xtb b/chromium/components/strings/components_chromium_strings_te.xtb
index c31a056369a..9c38776049b 100644
--- a/chromium/components/strings/components_chromium_strings_te.xtb
+++ b/chromium/components/strings/components_chromium_strings_te.xtb
@@ -1,13 +1,13 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="te">
-<translation id="130631256467250065">మీ మార్పులు మీరు మీ పరికరాన్ని పునఃప్రారంభించే తరువాతసారి ప్రభావవంతం అవుతాయి.</translation>
+<translation id="130631256467250065">మీ మార్పులు మీరు మీ పరికరాన్ని పునఃప్రారంభించే తర్వాతిసారి అమలులోకి వస్తాయి.</translation>
<translation id="1838412507805038478">Chromium ఈ వెబ్‌సైట్ ప్రమాణపత్రాన్ని <ph name="ISSUER" /> జారీ చేసినట్లు ధృవీకరించింది.</translation>
<translation id="275588974610408078">Chromiumలో క్రాష్ నివేదిక అందుబాటులో లేదు.</translation>
<translation id="3064346599913645280">మీరు సురక్షితమైన Chromium పేజీని వీక్షిస్తున్నారు</translation>
<translation id="3550966579244642892">Chromium OS దాని ప్రాథమిక సెటప్‌ను పూర్తి చేయలేదు.</translation>
<translation id="4365115785552740256">Chromium అనేది <ph name="BEGIN_LINK_CHROMIUM" />Chromium<ph name="END_LINK_CHROMIUM" /> ఓపెన్ సోర్స్ ప్రాజెక్ట్ మరియు ఇతర <ph name="BEGIN_LINK_OSS" />ఓపెన్ సోర్స్ సాఫ్ట్‌వేర్<ph name="END_LINK_OSS" />లపై ఎంతగానో ఆధారపడుతుంది.</translation>
-<translation id="4559775032954821361">Chromium మెనూ &gt;
+<translation id="4559775032954821361">Chromium మెను &gt;
<ph name="SETTINGS_TITLE" />
&gt;
<ph name="ADVANCED_TITLE" />
@@ -15,7 +15,7 @@
<ph name="PROXIES_TITLE" />
&gt;
LAN సెట్టింగ్‌లకు వెళ్లండి
- మరియు "మీ LAN కోసం ప్రాక్సీ సర్వర్‌ను ఉపయోగించండి" చెక్‌బాక్స్‌ ఎంపికను తీసివేయండి.</translation>
+ మరియు "మీ LAN కోసం ప్రాక్సీ సర్వర్‌ను ఉపయోగించండి" తనిఖీ పెట్టె ఎంపికను తీసివేయండి.</translation>
<translation id="48558539577516920">మీ ఫైర్‌వాల్ లేదా యాంటీవైరస్ సెట్టింగ్‌ల్లో నెట్‌వర్క్‌ను యాక్సెస్ చేయడానికి
Chromiumను అనుమతించండి.</translation>
<translation id="580822234363523061">Chromium మెను &gt;
@@ -23,8 +23,8 @@
&gt;
<ph name="ADVANCED_TITLE" />
&gt;
- <ph name="PROXIES_TITLE" />కు వెళ్లి
- మీ కాన్ఫిగరేషన్ "ప్రాక్సీ వద్దు" లేదా "నేరుగా" లాగా సెట్ చేసి ఉందని నిర్ధారించుకోండి.</translation>
+ <ph name="PROXIES_TITLE" />కు వెళ్లండి
+ మరియు మీ కాన్ఫిగరేషన్ "ప్రాక్సీ వద్దు" లేదా "నేరుగా" లాగా సెట్ చేయబడిందని నిర్ధారించుకోండి.</translation>
<translation id="6613594504749178791">మీ మార్పులు మీరు Chromiumని మరుసటిసారి ప్రారంభించినప్పుడు ప్రభావాన్ని చూపుతాయి.</translation>
<translation id="7861509383340276692">Chromium మెను &gt;
<ph name="SETTINGS_TITLE" />
diff --git a/chromium/components/strings/components_google_chrome_strings_te.xtb b/chromium/components/strings/components_google_chrome_strings_te.xtb
index 20215edac59..afb751e5d8e 100644
--- a/chromium/components/strings/components_google_chrome_strings_te.xtb
+++ b/chromium/components/strings/components_google_chrome_strings_te.xtb
@@ -2,7 +2,7 @@
<!DOCTYPE translationbundle>
<translationbundle lang="te">
<translation id="1016765312371154165">Chrome సరిగ్గా షట్ డౌన్ కాలేదు.</translation>
-<translation id="130631256467250065">మీ మార్పులు మీరు మీ పరికరాన్ని పునఃప్రారంభించే తరువాతసారి ప్రభావవంతం అవుతాయి.</translation>
+<translation id="130631256467250065">మీ మార్పులు మీరు మీ పరికరాన్ని పునఃప్రారంభించే తర్వాతిసారి అమలులోకి వస్తాయి.</translation>
<translation id="2147651015520127414">Chrome ఈ వెబ్‌సైట్ ప్రమాణపత్రాన్ని <ph name="ISSUER" /> జారీ చేసినట్లు ధృవీకరించింది.</translation>
<translation id="2874156562296220396"><ph name="BEGIN_LINK_CHROMIUM" />Chromium<ph name="END_LINK_CHROMIUM" /> ఓపెన్ సోర్స్ ప్రాజెక్ట్‌ మరియు ఇతర <ph name="BEGIN_LINK_OSS" />ఓపెన్ సోర్స్ సాఫ్ట్‌వేర్<ph name="END_LINK_OSS" />లపై Google Chrome ఎంతగానో ఆధారపడుతుంది.</translation>
<translation id="3140883423282498090">మీ మార్పులు మీరు Google Chromeను మళ్లీ ప్రారంభించినప్పుడు ప్రభావాన్ని చూపుతాయి.</translation>
@@ -11,13 +11,13 @@
Chromeను అనుమతించండి.</translation>
<translation id="4010643444566880169">Chrome OS దాని ప్రాథమిక సెటప్‌ను పూర్తి చేయలేదు.</translation>
<translation id="4853578032408195113">మీరు సురక్షితమైన Google Chrome పేజీని వీక్షిస్తున్నారు</translation>
-<translation id="6011049234605203654">          Chrome మెను &gt;
+<translation id="6011049234605203654">Chrome మెను &gt;
<ph name="SETTINGS_TITLE" />
&gt;
<ph name="ADVANCED_TITLE" />
&gt;
- <ph name="PROXIES_TITLE" />కు వెళ్లి
- మీ కాన్ఫిగరేషన్ "ప్రాక్సీ వద్దు" లేదా "నేరుగా" లాగా సెట్ చేయబడిందని నిర్ధారించుకోండి.</translation>
+ <ph name="PROXIES_TITLE" />కు వెళ్లండి
+ మరియు మీ కాన్ఫిగరేషన్ "ప్రాక్సీ వద్దు" లేదా "నేరుగా" లాగా సెట్ చేయబడిందని నిర్ధారించుకోండి.</translation>
<translation id="6341737370356890233">Chrome మెను &gt;
<ph name="SETTINGS_TITLE" />
&gt;
@@ -32,8 +32,8 @@
&gt;
<ph name="PROXIES_TITLE" />
&gt;
- LAN సెట్టింగ్‌లకు వెళ్లి
- "మీ LAN కోసం ప్రాక్సీ సర్వర్‌ను ఉపయోగించండి" ఎంపికను తీసివేయండి.</translation>
+ LAN సెట్టింగ్‌లకు వెళ్లండి
+ మరియు "మీ LAN కోసం ప్రాక్సీ సర్వర్‌ను ఉపయోగించండి" ఎంపికను తీసివేయండి.</translation>
<translation id="8187289872471304532">ఇలా వెళ్లండి
అప్లికేష‌న్‌లు &gt; సిస్టమ్ ప్రాధాన్యతలు &gt; నెట్‌వర్క్ &gt; అధునాతనం &gt; ప్రాక్సీలు
ఏవైనా ప్రాక్సీలను ఎంపిక చేసుకుని ఉంటే వాటిని తొల‌గించండి.</translation>
diff --git a/chromium/components/strings/components_strings_am.xtb b/chromium/components/strings/components_strings_am.xtb
index cbf653153c9..dbb20e50647 100644
--- a/chromium/components/strings/components_strings_am.xtb
+++ b/chromium/components/strings/components_strings_am.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">በ<ph name="LANGUAGE" /> ያሉ ገጾች አይተረጎሙም።</translation>
<translation id="2053553514270667976">ዚፕ ኮድ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 የአስተያየት ጥቆማ}one{# የአስተያየት ጥቆማዎች}other{# የአስተያየት ጥቆማዎች}}</translation>
+<translation id="2068124040035837596">የእርስዎ መለያ በ<ph name="ENROLLMENT_DOMAIN" /> ነው የሚተዳደረው። ይህ ማለት የእርስዎ አስተዳዳሪ መለያዎን በርቀት ሊያዋቅሩት ይችላሉ ማለት ነው።</translation>
<translation id="2068663545051464999">የስንክል ሪፖርት መታወቂያ ተሰቅሏል <ph name="CRASH_ID" /> (ከባቢያዊ ዓውድ፦ <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">ቀልብስ</translation>
<translation id="20817612488360358">የስርዓት ተኪ ቅንብሮች ስራ ላይ እንዲውሉ ተቀናብረዋል ግን ግልጽ የሆነ የተኪ ውቅርም ተገልጿል።</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">ይህ የመላኪያ ዘዴ አይገኝም። የተለየ ዘዴ ይሞክሩ።</translation>
<translation id="2396249848217231973">&amp;ስረዛን ቀልብስ</translation>
<translation id="2413528052993050574">ይህ አገልጋይ <ph name="DOMAIN" /> መሆኑን ሊያረጋግጥ አልቻለም፤ የደህንነት እውቅና ማረጋገጫው ተሽሮ ሊሆን ይችላል። ይሄ በተሳሳተ አወቃቀር ወይም አንድ አጥቂ ግንኙነትዎን በመጥለፉ የተከሰተ ሊሆን ይችላል።</translation>
+<translation id="244665789865330679">የእርስዎ መሣሪያ እና መለያ በ<ph name="ENROLLMENT_DOMAIN" /> ነው የሚተዳደረው። ይህ ማለት የእርስዎ አስተዳዳሪ የእርስዎን መሣሪያ እና መለያ በርቀት ሊያዋቅር ይችላል ማለት ነው።</translation>
<translation id="2463193859425327265">መነሻ ገጹን ቀይር</translation>
<translation id="2463739503403862330">ሙላ</translation>
<translation id="2465655957518002998">የማድረሻ ዘዴ ይምረጡ</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" />ን ለመድረስ ሞክረዋል፣ ነገር ግን አገልጋዩ ያቀረበው የእውቅና ማረጋገጫ በሰጪው ተሽሯል። ይህ ማለት አገልጋዩ ያቀረበው የደህንነት ምስክርነቶች ፈጽሞ ሊታመኑ አይገባም። ከአጥቂ ጋር እየተገናኙ ሊሆን ይችላል።</translation>
<translation id="4378154925671717803">ስልክ</translation>
<translation id="4406896451731180161">የፍለጋ ውጤቶች</translation>
+<translation id="4406972042435603828">የእርስዎ አስተዳዳሪዎች ኃይለኛ ችሎታዎች ያላቸው ቅጥያዎችን ጭነዋል።</translation>
<translation id="4408413947728134509">ኩኪዎች <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">የመውሰጃ አድራሻ</translation>
<translation id="4424024547088906515">ይህ አገልጋይ <ph name="DOMAIN" /> መሆኑን ሊያረጋግጥ አልቻለም፤ የደህንነት እውቅና ማረጋገጫው በChrome የሚታመን አይደለም። ይሄ በተሳሳተ አወቃቀር ወይም አንድ አጥቂ ግንኙነትዎን በመጥለፉ የተከሰተ ሊሆን ይችላል።</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">ውጤቶች የሉም</translation>
<translation id="4950898438188848926">የትር መቀየሪያ አዝራር፣ ወደ ክፍቱ ትር <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /> ለመቀየር Enterን ይጫኑ</translation>
<translation id="495170559598752135">እርምጃዎች</translation>
+<translation id="495832697253704892">ቅጥያን ሪፖርት ማድረግ</translation>
<translation id="4958444002117714549">ዝርዝሩን ዘርጋ</translation>
<translation id="4974590756084640048">ማስጠንቀቂያዎችን ዳግም አንቃ</translation>
<translation id="4989163558385430922">ሁሉንም ይመልከቱ</translation>
<translation id="4989809363548539747">ይህ ተሰኪ አይደገፍም</translation>
+<translation id="4996230189582812866">ሪፖርት ማድረግ</translation>
<translation id="5002932099480077015">የነቃ እንደሆነ Chrome ለበለጠ ፈጣን ቅጽ አሞላል ሲባል በዚህ መሳሪያ ላይ ያለው የካርድዎን ቅጂ ያከማቻል።</translation>
<translation id="5014174725590676422">በChrome ውስጥ Google ረዳት የመጀመሪያ ማሄድ ማያ ገጽ ይታያል</translation>
<translation id="5015510746216210676">የማሽን ስም፦</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">ግዛት</translation>
<translation id="5094747076828555589">ይህ አገልጋይ <ph name="DOMAIN" /> መሆኑን ሊያረጋግጥ አልቻለም፤ የደህንነት እውቅና ማረጋገጫው በChromium የሚታመን አይደለም። ይሄ በተሳሳተ አወቃቀር ወይም አንድ አጥቂ ግንኙነትዎን በመጥለፉ የተከሰተ ሊሆን ይችላል።</translation>
<translation id="5095208057601539847">ጠቅላይ ግዛት</translation>
+<translation id="5098222253617183465">የእርስዎ መሣሪያ በ<ph name="ENROLLMENT_DOMAIN" /> የሚተዳደር ስሲሆን የእርስዎ መለያ በ<ph name="ACCOUNT_DOMAIN" /> ይተዳደራል። ይህ ማለት የእርስዎ አስተዳዳሪዎች በርቀት የእርስዎን መሣሪያና መለያ ሊያዋቅሩት ይችላሉ ማለት ነው።</translation>
<translation id="5115563688576182185">(64-ቢት)</translation>
<translation id="5128122789703661928">ይህ ስም ያለው ክፍለ-ጊዜ ለስረዛ ልክ ያልሆነ ነው።</translation>
<translation id="5135404736266831032">አድራሻዎችን ያቀናብሩ...</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">ማሽን</translation>
<translation id="5179510805599951267">በ<ph name="ORIGINAL_LANGUAGE" /> አይደለም? ይህን ስህተት ሪፖርት ያድርጉ</translation>
<translation id="5190835502935405962">የዕልባቶች አሞሌ</translation>
+<translation id="5200263511887412697">በቅርቡ በመለያ የገቡ የመሣሪያ ተጠቃሚዎች ዝርዝርን ሪፖርት አድርግ</translation>
<translation id="5201306358585911203">በዚህ ድረ-ገጽ ላይ ያለ የተካተተ ገጽ እንዲህ ይላል፦</translation>
<translation id="5205222826937269299">ስም ያስፈልጋል</translation>
<translation id="5215116848420601511">Google Payን የሚጠቀሙ የመክፈያ ዘዴዎች እና አድራሻዎች</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">ይህ ጣቢያ ሊደረስበት አይችልም</translation>
<translation id="5869522115854928033">የተቀመጡ የይለፍ ቃሎች</translation>
<translation id="5887400589839399685">ካርድ ተቀምጧል</translation>
+<translation id="5893718151540690985">የአውታረ መረብ በይነገጾች ዝርዝርን ከአይነቶቻቸው እና የሃርድዌር አድራሻዎቻቸው ጋር ሪፖርት አድርግ</translation>
<translation id="5893752035575986141">ክሬዲት ካርዶች ተቀባይነት አላቸው።</translation>
<translation id="5901630391730855834">ቢጫ</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (ሰምሯል)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">የዕውቂያ መረጃን ያርትዑ</translation>
<translation id="5967867314010545767">ከታሪክ አስወግድ</translation>
<translation id="5975083100439434680">አሳንስ</translation>
+<translation id="5977489021191000276">የእርስዎ መሣሪያ በአስተዳዳሪ አይተዳደርም።</translation>
<translation id="5977976211062815271">በዚህ መሣሪያ ላይ</translation>
<translation id="598637245381783098">የክፍያ መተግበሪያን መክፈት አይቻልም</translation>
<translation id="5989320800837274978">ቋሚ ተኪ አገልጋዮችም ሆኑ የ.pac ስክሪፕት ዩአርኤል አልተገለጹም።</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347">በ<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ላይ ያሉ አጥቂዎች የሆነ ሌላ ነገር እንደሆነ መስለው የሚቀርቡ አታላይ መተግበሪያዎችን ሊጭኑ ወይም የእርስዎን ዱካ ለመከታተል የሚያስችል ውሂብን ሊሰበስቡ ይችላሉ። <ph name="BEGIN_LEARN_MORE_LINK" />የበለጠ ለመረዳት<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />፣ <ph name="TYPE_2" />፣ <ph name="TYPE_3" /> (ሰምሯል)</translation>
<translation id="6027201098523975773">ስም ያስገቡ</translation>
+<translation id="6033927989869462158">እንደ የሲፒዩ/ራም አጠቃቀም ያሉ የሃርድዌር ስታቲስቲክስን ሪፖርት አድርግ</translation>
<translation id="6034000775414344507">ፈካ ያለ ግራጫ</translation>
<translation id="6039846035001940113">ችግሩ ከቀጠለ የጣቢያ ባለቤቱን ያነጋግሩ።</translation>
<translation id="6040143037577758943">ዝጋ</translation>
@@ -829,7 +839,7 @@
<translation id="627746635834430766">በሚቀጥለው ጊዜ በበለጠ ፍጥነት ለመክፈል ካርድዎን እና የማስከፈያ አድራሻዎን በGoogle መለያዎ ላይ ያስቀምጡ።</translation>
<translation id="6280223929691119688">ወደዚህ አድራሻ ማድረስ አይቻልም። የተለየ አድራሻ ይምረጡ።</translation>
<translation id="6282194474023008486">የፖስታ ኮድ</translation>
-<translation id="6290238015253830360">በእርስዎ የተጠቆሙ ዘገባዎች እዚህ ይመጣሉ</translation>
+<translation id="6290238015253830360">የእርስዎ የተጠቆሙ ዘገባዎች እዚህ ይመጣሉ</translation>
<translation id="6302269476990306341">በChrome ውስጥ Google ረዳት እያቆመ ነው</translation>
<translation id="6305205051461490394"><ph name="URL" /> ሊደረስበት አይችልም።</translation>
<translation id="6321917430147971392">የዲኤንኤስ ቅንብሮችዎን ይፈትሹ</translation>
@@ -904,6 +914,8 @@
<translation id="6897140037006041989">የተጠቀሚ ተወካይ</translation>
<translation id="6903319715792422884">አንዳንድ <ph name="BEGIN_WHITEPAPER_LINK" />የሥርዓት መረጃ እና የገጽ ይዘት<ph name="END_WHITEPAPER_LINK" />ን ወደ Google በመላክ የጥንቃቄ አሰሳን ለማሻሻል እንዲቻል ያግዙ።<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ተጠቃሚ፦</translation>
+<translation id="6934672428414710184">ይህ ስም ከእርስዎ Google መለያ የተገኘ ነው</translation>
+<translation id="6939583532829045966">የእርስዎ መሣሪያ በ<ph name="ENROLLMENT_DOMAIN" /> ነው የሚተዳደረው። ይህ ማለት የእርስዎ አስተዳዳሪ መሣሪያዎን በርቀት ሊያዋቅሩት ይችላሉ ማለት ነው።</translation>
<translation id="6944692733090228304">በ<ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ወደ የማይተዳደር ጣቢያ ላይ የእርስዎን የይለፍ ቃል አስገብተዋል። ለእርስዎ መለያ ጥበቃ ለማድረግ፣ በሌሎች መተግበሪያዎች እና ጣቢያዎች ላይ የእርስዎን የይለፍ ቃል ዳግም አይጠቀሙ።</translation>
<translation id="6945221475159498467">ይምረጡ</translation>
<translation id="6948701128805548767">የመውሰጃ ዘዴዎችን እና መስፈርቶችን ለመመልከት አድራሻ ይምረጡ</translation>
@@ -991,6 +1003,7 @@
&lt;li&gt;&lt;strong&gt;ተግብር&lt;/strong&gt;ን ጠቅ ያድርጉ፣ ከዚያ &lt;strong&gt;እሺ&lt;/strong&gt;ን ጠቅ ያድርጉ
&lt;li&gt;እንዴት ሶፍትዌሩን ከኮምፒውተርዎ እስከመጨረሻው ማስወገድ እንደሚችሉ ለማወቅ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;የChrome እገዛ ማዕከል&lt;/a&gt;ን ይጎብኙ
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">የ<ph name="PRODUCT_NAME" /> አስተዳደር</translation>
<translation id="7416351320495623771">የይለፍ ቃላትን ያስተዳድሩ...</translation>
<translation id="7419106976560586862">የመገለጫ ዱካ</translation>
<translation id="7437289804838430631">የእውቂያ መረጃ አክል</translation>
@@ -999,10 +1012,12 @@
<translation id="7442725080345379071">ፈዘዝ ያለ ብርትኳናማ</translation>
<translation id="7444046173054089907">ይህ ጣቢያ ታግዷል</translation>
<translation id="7445762425076701745">የተገናኙት የአገልጋይ ማንነት ሙሉ ለሙሉ ሊረጋገጥ አልቻለም። ስሙ በአውታረ መረብዎ ውስጥ ብቻ ልክ ከሆነ አገልጋይ ጋር ነው የተገናኙት፣ እና ባለቤትነቱ በውጫዊ የእውቅና ማረጋገጫ ሊረጋገጥ አይችልም። አንዳንድ የእውቅና ማረጋገጫ ባለስልጣናት ይሁን ብለው ለእነዚህ ስሞች የእውቅና ማረጋገጫዎች መስጠታቸው የማይቀር እንደመሆኑ መጠን፣ ከአጥቂ ሳይሆን ከታሰበው ድር ጣቢያ ጋር መገናኘትዎን የሚረጋገጥበት ምንም መንገድ የለም።</translation>
+<translation id="7449109375006139765">የስርዓት ምዝግብ ማስታወሻዎችን ወደ የአስተዳደር አገልጋዩ ይላኩ</translation>
<translation id="7451311239929941790">ስለዚህ ችግር <ph name="BEGIN_LINK" />ይበልጥ በመረዳት ላይ<ph name="END_LINK" />።</translation>
<translation id="7455133967321480974">ሁለንተናዊ ነባሪውን ተጠቀም (አግድ)</translation>
<translation id="7460618730930299168">ማያ ገጹ አቀራረብ እርስዎ ከመረጡት የተለየ ነው። ይቀጥል?</translation>
<translation id="7473891865547856676">አይ፣ አመሰግናለሁ</translation>
+<translation id="7475525192983021547">አንድ ተጠቃሚ በመሣሪያው ላይ ገቢር ሲሆን ክፍለ-ጊዜዎችን ሪፖርት አድርግ</translation>
<translation id="7481312909269577407">ወደ ፊት</translation>
<translation id="7485870689360869515">ምንም ውሂብ አልተገኘም።</translation>
<translation id="7508255263130623398">የተመላሽ መመሪያ መሣሪያ መታወቂያ ባዶ ነው ወይም ከአሁኑ የመሣሪያ መታወቂያ ጋር አይዛመድም</translation>
@@ -1095,6 +1110,7 @@
<translation id="7995512525968007366">አልተጠቀሰም</translation>
<translation id="800218591365569300">የማህደረ ትውስታ ቦታን ለማስለቀቅ ሌሎች ትሮችን ወይም ፕሮግራሞችን ዘግተው ይሞክሩ።</translation>
<translation id="8009225694047762179">የይለፍ ቃላትን ያቀናብሩ</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ይህ ካርድ እና የክፍያ መጠየቂያ አድራሻው ይቀመጣሉ። በመለያ ወደ <ph name="USER_EMAIL" /> ሲገቡ ሊጠቀሙበት ይችላሉ።}one{እነዚህ ካርዶች እና የክፍያ መጠየቂያ አድራሻዎቻቸው ይቀመጣሉ። በመለያ ወደ <ph name="USER_EMAIL" /> ሲገቡ ሊጠቀሙባቸው ይችላሉ።}other{እነዚህ ካርዶች እና የክፍያ መጠየቂያ አድራሻዎቻቸው ይቀመጣሉ። በመለያ ወደ <ph name="USER_EMAIL" /> ሲገቡ ሊጠቀሙባቸው ይችላሉ።}}</translation>
<translation id="8012647001091218357">በዚህ ጊዜ ላይ ወላጆችህን መድረስ አልቻልንም። እባክህ እንደገና ሞክር።</translation>
<translation id="8025119109950072390">በዚህ ጣቢያ ላይ ያሉ አጥቂዎች እርስዎ እንደ ሶፍትዌር መጫን ወይም የግል መረጃዎን (ለምሳሌ፦ የይለፍ ቃላት፣ ስልክ ቁጥሮች ወይም ክሬዲት ካርዶች) አሳልፈው እንዲሰጡ ያሉ አደገኛ ነገር እንዲያደርጉ ሊያታልሉዎት ይችላሉ።</translation>
<translation id="8034522405403831421">ይህ ገጽ በ<ph name="SOURCE_LANGUAGE" /> ነው። ወደ <ph name="TARGET_LANGUAGE" /> ይተርጎም?</translation>
@@ -1105,6 +1121,7 @@
<translation id="8041940743680923270">ሁለንተናዊ ነባሪውን ተጠቀሙ (ጠይቅ)</translation>
<translation id="8042918947222776840">የመውሰጃ ዘዴ ይምረጡ</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» በአግባቡ አልተዋቀረም። «<ph name="SOFTWARE_NAME" />»ን ማራገፍ አብዛኛው ጊዜ ችግሩን ይፈታዋል። <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">የእርስዎ መሣሪያ ለሚከተሉት ተዋቅሯል፦</translation>
<translation id="8078141288243656252">በሚሸከርከርበት ጊዜ ማብራራት አይችልም</translation>
<translation id="8079031581361219619">ጣቢያ ዳግም ይጫን?</translation>
<translation id="8088680233425245692">ጽሑፉን ማየት አልተቻለም።</translation>
@@ -1155,6 +1172,7 @@
<translation id="8363502534493474904">የአውሮፕላን ሁነታን ማጥፋት</translation>
<translation id="8364627913115013041">አልተዋቀረም።</translation>
<translation id="8368476060205742148">Google Play አገልግሎቶች</translation>
+<translation id="8371889962595521444">ብጁ የስር ቅንብሮች</translation>
<translation id="8380941800586852976">አደገኛ</translation>
<translation id="8381674639488873545">እነዚህ ክፍያዎች የአንድ ጊዜ ወይም ተደጋጋሚ፣ እና የማያስታውቁ ሊሆኑ ይችላሉ። <ph name="BEGIN_LINK" />የሆነው ሆኖ አሳይ<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">በቅርቡ የጎበኟቸው ዕልባቶች እዚህ ይመጣሉ</translation>
@@ -1164,6 +1182,7 @@
<translation id="8416694386774425977">የአውታረ መረቡ ውቅረት ልክ ያልሆነ እና ሊመጣ የማይችል ነው።
ተጨማሪ ዝርዝሮች፦
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">መሣሪያ የሚተዳደረው በ<ph name="ENROLLMENT_DOMAIN" /> ነው</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">ለውጥ</translation>
<translation id="8428213095426709021">ቅንብሮች</translation>
@@ -1225,6 +1244,7 @@
<translation id="8932102934695377596">የእርስዎ ሰዓት ወደ ኋላ ቀርቷል</translation>
<translation id="893332455753468063">ስም ያክሉ</translation>
<translation id="8938939909778640821">ተቀባይነት ያላቸው የክሬዲት እና የቅድመ-ክፍያ ካርዶች</translation>
+<translation id="894185898663964645">የእርስዎ አስተዳዳሪ ብጁ የስር እውቅና ማረጋገጫዎችን አዋቅረዋል፣ እነዚህም አስተዳዳሪው እርስዎ የሚጎበኟቸው የድር ጣቢያዎች ይዘትን እንዲመለከቱ ያስችላቸዋል።</translation>
<translation id="8943282376843390568">ሎሚ ቀለም</translation>
<translation id="8957210676456822347">የተያዥ መግቢያ ፈቀዳ</translation>
<translation id="8968766641738584599">ካርድ አስቀምጥ</translation>
diff --git a/chromium/components/strings/components_strings_ar.xtb b/chromium/components/strings/components_strings_ar.xtb
index 4e096b2f81b..3768c33680b 100644
--- a/chromium/components/strings/components_strings_ar.xtb
+++ b/chromium/components/strings/components_strings_ar.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">لن تتم ترجمة الصفحات باللغة <ph name="LANGUAGE" />.</translation>
<translation id="2053553514270667976">الرمز البريدي</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{اقتراح واحد}zero{# اقتراح}two{اقتراحان (#)}few{# اقتراحات}many{# اقتراحًا}other{# اقتراح}}</translation>
+<translation id="2068124040035837596">يدير <ph name="ENROLLMENT_DOMAIN" /> حسابك. وهذا يعني أنه قد يضبط مشرفك حسابك عن بُعد.</translation>
<translation id="2068663545051464999">مُعرّف تقارير الأعطال الذي تم تحميله <ph name="CRASH_ID" /> (السياق المحلي: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">تراجع</translation>
<translation id="20817612488360358">تم تعيين إعدادات الخادم الوكيل ليتم استخدامها وتم أيضًا تحديد تهيئة صريحة للخادم الوكيل.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">طريقة الشحن هذه غير متاحة، جرِّب طريقة أخرى.</translation>
<translation id="2396249848217231973">تراجع عن الحذ&amp;ف</translation>
<translation id="2413528052993050574">هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان ربما تم إلغاء صلاحيتها. وربما يكون السبب في ذلك خطأ في التكوين أو مهاجمًا يعترض اتصالك.</translation>
+<translation id="244665789865330679">يدير <ph name="ENROLLMENT_DOMAIN" /> جهازك وحسابك. وهذا يعني أنه قد يضبط مشرفك جهازك وحسابك عن بُعد.</translation>
<translation id="2463193859425327265">تغيير الصفحة الرئيسية</translation>
<translation id="2463739503403862330">ملء</translation>
<translation id="2465655957518002998">اختيار طريقة التسليم للمستخدم</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">لقد حاولت الوصول إلى <ph name="DOMAIN" />، ولكن جهة إصدار الشهادة التي قدمها الخادم قد أبطلت الشهادة. وهذا يعني أن بيانات اعتماد الأمان التي قدمها الخادم يجب عدم الوثوق بها مطلقًا. فقد تكون على اتصال بأحد المهاجمين.</translation>
<translation id="4378154925671717803">هاتف</translation>
<translation id="4406896451731180161">نتائج البحث</translation>
+<translation id="4406972042435603828">ثبّت المشرفون الإضافات التي تتضمّن إمكانات فعَّالة.</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> من ملفات تعريف الارتباط</translation>
<translation id="4415426530740016218">عنوان الاستلام</translation>
<translation id="4424024547088906515">‏هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان غير موثوقة من قبل Chrome. وربما يكون السبب في ذلك خطأ في التكوين أو مهاجمًا يعترض الاتصال.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">لا نتائج</translation>
<translation id="4950898438188848926">‏زر التبديل بين علامات التبويب، اضغط على Enter للتبديل إلى علامة التبويب المفتوحة هذه <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">إجراءات</translation>
+<translation id="495832697253704892">إعداد التقارير الخاصة بالإضافات</translation>
<translation id="4958444002117714549">توسيع القائمة</translation>
<translation id="4974590756084640048">إعادة تفعيل التحذيرات</translation>
<translation id="4989163558385430922">عرض الكل</translation>
<translation id="4989809363548539747">هذا المكوِّن الإضافي غير مدعوم</translation>
+<translation id="4996230189582812866">إعداد التقارير</translation>
<translation id="5002932099480077015">‏إذا تم التمكين، سيخزن Chrome نسخة من بطاقتك على هذا الجهاز لملء النموذج بشكل أسرع.</translation>
<translation id="5014174725590676422">‏يتم عرض شاشة التشغيل الأولى "لمساعد Google" على Chrome</translation>
<translation id="5015510746216210676">اسم الجهاز:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">الولاية</translation>
<translation id="5094747076828555589">‏هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />؛ بل إنه شهادة أمان غير موثوقة من قبل Chromium. وربما يكون السبب في ذلك خطأ في التكوين أو مهاجمًا يعترض الاتصال.</translation>
<translation id="5095208057601539847">المقاطعة</translation>
+<translation id="5098222253617183465">يدير <ph name="ENROLLMENT_DOMAIN" /> جهازك ويدير<ph name="ACCOUNT_DOMAIN" /> حسابك. وهذا يعني أنه قد يضبط المشرفون جهازك وحسابك عن بُعد.</translation>
<translation id="5115563688576182185">(64 بت)</translation>
<translation id="5128122789703661928">الجلسة التي تحمل هذا الاسم غير صالحة للحذف.</translation>
<translation id="5135404736266831032">إدارة العناوين...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">الجهاز</translation>
<translation id="5179510805599951267">هل الصفحة ليست باللغة <ph name="ORIGINAL_LANGUAGE" />؟ الإبلاغ عن هذا الخطأ</translation>
<translation id="5190835502935405962">شريط الإشارات</translation>
+<translation id="5200263511887412697">الإبلاغ عن قائمة مستخدمي الأجهزة الذين سجّلوا الدخول مؤخرًا</translation>
<translation id="5201306358585911203">تعرض صفحة مضمّنة في هذه الصفحة</translation>
<translation id="5205222826937269299">الاسم مطلوب</translation>
<translation id="5215116848420601511">‏طرق الدفع والعناوين باستخدام Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">لا يمكن الوصول إلى موقع الويب هذا</translation>
<translation id="5869522115854928033">كلمات المرور المحفوظة</translation>
<translation id="5887400589839399685">تم حفظ البطاقة</translation>
+<translation id="5893718151540690985">الإبلاغ عن قائمة بواجهات الشبكات مع تحديد أنواعها وعناوين الأجهزة</translation>
<translation id="5893752035575986141">يتم قبول بطاقات الائتمان.</translation>
<translation id="5901630391730855834">أصفر</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (تمت المزامنة)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">تعديل معلومات الاتصال</translation>
<translation id="5967867314010545767">إزالة من السجل</translation>
<translation id="5975083100439434680">تصغير</translation>
+<translation id="5977489021191000276">لا يدير جهازك أيّ مشرف.</translation>
<translation id="5977976211062815271">على هذا الجهاز</translation>
<translation id="598637245381783098">لا يمكن فتح تطبيق الدفع</translation>
<translation id="5989320800837274978">‏لم يتم تحديد أي من الخوادم الوكيلة الثابتة ولا عنوان URL للنص البرمجي pac.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">يمكن للمهاجمين على <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> تثبيت تطبيقات مضللة تدعي أنها شيء آخر أو تجمع بيانات قد يتم استخدامها لتتبعك. <ph name="BEGIN_LEARN_MORE_LINK" />مزيد من المعلومات<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />، <ph name="TYPE_2" />، <ph name="TYPE_3" /> (تمت المزامنة)</translation>
<translation id="6027201098523975773">أدخِل اسمًا</translation>
+<translation id="6033927989869462158">‏الإبلاغ عن إحصاءات الأجهزة مثل استخدام وحدة المعالجة المركزية (CPU)/ ذاكرة الوصول العشوائي (RAM)</translation>
<translation id="6034000775414344507">رمادي فاتح</translation>
<translation id="6039846035001940113">في حال استمرت المشكلة، اتصل بمالك الموقع.</translation>
<translation id="6040143037577758943">إغلاق</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">وكيل المستخدم</translation>
<translation id="6903319715792422884">‏يمكنك المساعدة في تحسين التصفُّح الآمن عن طريق إرسال بعض <ph name="BEGIN_WHITEPAPER_LINK" />معلومات النظام ومحتوى الصفحة<ph name="END_WHITEPAPER_LINK" /> إلى Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">المستخدم:</translation>
+<translation id="6934672428414710184">‏هذا الاسم من حسابك على Google</translation>
+<translation id="6939583532829045966">يدير <ph name="ENROLLMENT_DOMAIN" /> جهازك. وهذا يعني أنه قد يضبط مشرفك جهازك عن بُعد.</translation>
<translation id="6944692733090228304">لقد أدخلتَ كلمة المرور في موقع ويب لا تديره <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. ويُرجى عدم إعادة استخدام كلمة المرور في التطبيقات ومواقع الويب الأخرى لحماية حسابك.</translation>
<translation id="6945221475159498467">تحديد</translation>
<translation id="6948701128805548767">لعرض طرق الاستلام ومتطلباته، حدِّد عنوانًا</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;انقر على &lt;strong&gt;"تطبيق"&lt;/strong&gt;، ثم على &lt;strong&gt;"موافق"&lt;/strong&gt;
&lt;li&gt;انتقِل إلى &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;مركز مساعدة Chrome&lt;/a&gt; لمعرفة كيفية إزالة البرنامج من جهاز الكمبيوتر نهائيًا
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">إدارة <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">إدارة كلمات المرور…</translation>
<translation id="7419106976560586862">مسار الملف الشخصي</translation>
<translation id="7437289804838430631">إضافة معلومات الاتصال</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">برتقالي فاتح</translation>
<translation id="7444046173054089907">تم حظر هذا الموقع</translation>
<translation id="7445762425076701745">لا يمكن التحقق بصورة كاملة من صحة هوية الخادم الذي تتصل به. فأنت متصل بخادم باستخدام اسم صالح فقط ضمن شبكتك، والذي لن يتمكن المرجع المصدق الخارجي من التحقق من ملكيته. وحيث إن بعض المراجع المصدقة تُصدر الشهادات لهذه الأسماء على أي حال، فليست هناك طريقة للتأكد من أنك متصل بموقع الويب المقصود وليس بأحد المهاجمين.</translation>
+<translation id="7449109375006139765">إرسال سجلَّات النظام إلى خادم الإدارة</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /> حول هذه المشكلة.</translation>
<translation id="7455133967321480974">استخدام الإعداد التلقائي العمومي (حظر)</translation>
<translation id="7460618730930299168">يختلف هذا الفحص عن اختيارك. هل تريد المتابعة؟</translation>
<translation id="7473891865547856676">لا، شكرًا</translation>
+<translation id="7475525192983021547">الإبلاغ عن الفترات الزمنية التي يكون المستخدم فيها نشطًا على الجهاز</translation>
<translation id="7481312909269577407">إلى الأمام</translation>
<translation id="7485870689360869515">لم يتم العثور على بيانات.</translation>
<translation id="7508255263130623398">رقم تعريف الجهاز المعروض للسياسة فارغ أو لا يتطابق مع رقم تعريف الجهاز الحالي</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">غير محدد</translation>
<translation id="800218591365569300">جرّب إغلاق علامات التبويب أو البرامج الأخرى لتفريغ مساحة من الذاكرة.</translation>
<translation id="8009225694047762179">إدارة كلمات المرور</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{سيتم حفظ هذه البطاقة وعنوان إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}zero{سيتم حفظ هذه البطاقات وعناوين إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}two{سيتم حفظ هاتين البطاقتين وعنواني إرسال الفواتير. ستتمكَّن من استخدامهما عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}few{سيتم حفظ هذه البطاقات وعناوين إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}many{سيتم حفظ هذه البطاقات وعناوين إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}other{سيتم حفظ هذه البطاقات وعناوين إرسال الفواتير. ستتمكَّن من استخدامها عند تسجيل الدخول إلى <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">لم نتمكن من الوصول إلى والديك في الوقت الحالي. يُرجى إعادة المحاولة مرة أخرى.</translation>
<translation id="8025119109950072390">قد يحاول المهاجمون الموجودون على هذا الموقع فعل شيء خطير كتثبيت البرامج أو الكشف عن معلوماتك الشخصية (على سبيل المثال، كلمات المرور أو أرقام الهواتف أو بطاقات الائتمان).</translation>
<translation id="8034522405403831421">هذه الصفحة باللغة <ph name="SOURCE_LANGUAGE" />. هل تريد ترجمتها إلى اللغة <ph name="TARGET_LANGUAGE" />؟</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">استخدام الإعداد التلقائي العمومي (طلب)</translation>
<translation id="8042918947222776840">اختيار طريقة الاستلام من المستخدم</translation>
<translation id="8057711352706143257">لم تتم تهيئة "<ph name="SOFTWARE_NAME" />" بشكل صحيح. يؤدي عادةً إلغاء تثبيت "<ph name="SOFTWARE_NAME" />" إلى إصلاح المشكلة. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">تم ضبط جهازك لإجراء ما يلي:</translation>
<translation id="8078141288243656252">لا يمكن إضافة تعليق توضيحي عند تدوير المستند</translation>
<translation id="8079031581361219619">هل تريد إعادة تحميل الموقع؟</translation>
<translation id="8088680233425245692">تعذّر عرض المقالة.</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">إيقاف تشغيل وضع الطائرة</translation>
<translation id="8364627913115013041">لم يتم تعيينها.</translation>
<translation id="8368476060205742148">‏خدمات Google Play</translation>
+<translation id="8371889962595521444">شهادات الجذر المُخصَّصة</translation>
<translation id="8380941800586852976">ضارة</translation>
<translation id="8381674639488873545">قد يتم تحصيل هذه الرسوم لمرة واحدة أو بشكل متكرِّر، وقد تكون غير واضحة. <ph name="BEGIN_LINK" />عرض على أي حال<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">تظهر الإشارات المرجعية التي زرتها مؤخرًا هنا</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">تهيئة الشبكة غير صالحة ويتعذّر استيرادها.
التفاصيل الإضافية:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">جهاز مُدار من خلال <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">تغيير</translation>
<translation id="8428213095426709021">الإعدادات</translation>
@@ -1226,6 +1245,7 @@
<translation id="8932102934695377596">توقيت ساعتك متأخر عن الوقت الحالي</translation>
<translation id="893332455753468063">إضافة اسم</translation>
<translation id="8938939909778640821">بطاقات الائتمان وبطاقات الدفع المسبق المقبولة</translation>
+<translation id="894185898663964645">ضبط مشرفك شهادات الجذر المُخصّصة والتي قد تسمح للمشرف بالتعرُّف على محتوى مواقع الويب التي تزورها.</translation>
<translation id="8943282376843390568">ليموني</translation>
<translation id="8957210676456822347">تفويض المدخل المقيد</translation>
<translation id="8968766641738584599">حفظ البطاقة</translation>
diff --git a/chromium/components/strings/components_strings_bg.xtb b/chromium/components/strings/components_strings_bg.xtb
index e4182085cca..c4f16b2c40f 100644
--- a/chromium/components/strings/components_strings_bg.xtb
+++ b/chromium/components/strings/components_strings_bg.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Страниците на <ph name="LANGUAGE" /> няма да се превеждат.</translation>
<translation id="2053553514270667976">Пощенски код</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 предложение}other{# предложения}}</translation>
+<translation id="2068124040035837596">Профилът ви се управлява от <ph name="ENROLLMENT_DOMAIN" />. Това значи, че администраторът ви може да го конфигурира отдалечено.</translation>
<translation id="2068663545051464999">Идентификатор на качения сигнал за срив <ph name="CRASH_ID" /> (Локално контекстно меню: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Отмяна</translation>
<translation id="20817612488360358">За използване са зададени системни настройки за прокси сървъра, но е посочена и изрична конфигурация.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Този начин на доставка не се поддържа. Опитайте с друг.</translation>
<translation id="2396249848217231973">&amp;Отмяна на изтриването</translation>
<translation id="2413528052993050574">Сървърът не можа да докаже, че е <ph name="DOMAIN" />; възможно е сертификатът му за сигурност да е оттеглен. Това може да се дължи на неправилно конфигуриране или на прихващане на връзката ви от атакуващ.</translation>
+<translation id="244665789865330679">Устройството и профилът ви се управляват от <ph name="ENROLLMENT_DOMAIN" />. Това значи, че администраторът ви може да ги конфигурира отдалечено.</translation>
<translation id="2463193859425327265">Промяна на началната страница</translation>
<translation id="2463739503403862330">Попълване</translation>
<translation id="2465655957518002998">Избиране на начин на бърза доставка</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Направихте опит да се свържете с/ъс <ph name="DOMAIN" />, но сървърът предoстави сертификат, анулиран от издателя си. Това означава, че в никакъв случай не трябва да се доверявате на представените от сървъра идентификационни данни за сигурност. Възможно е да сте се свързали с извършител на атака.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4406896451731180161">резултата от търсенето</translation>
+<translation id="4406972042435603828">Администраторите ви са инсталирали разширения с големи възможности.</translation>
<translation id="4408413947728134509">„Бисквитки“ <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Адрес за вземане</translation>
<translation id="4424024547088906515">Сървърът не можа да докаже, че е <ph name="DOMAIN" />; Chrome няма доверие на сертификата му за сигурност. Това може да се дължи на неправилно конфигуриране или на прихващане на връзката ви от атакуващ.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Няма резултати</translation>
<translation id="4950898438188848926">Бутон за превключване между раздели. Натиснете Enter, за да преминете към отворения раздел – <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Действия</translation>
+<translation id="495832697253704892">Отчитане на разширенията</translation>
<translation id="4958444002117714549">Разгъване на списъка</translation>
<translation id="4974590756084640048">Повторно активиране на предупрежденията</translation>
<translation id="4989163558385430922">Преглед на всички</translation>
<translation id="4989809363548539747">Тази приставка не се поддържа</translation>
+<translation id="4996230189582812866">Отчитане</translation>
<translation id="5002932099480077015">Ако настройката е активирана, копие на картата ви ще се съхранява в Chrome на това устройство с цел по-бързо попълване на формуляри.</translation>
<translation id="5014174725590676422">Показан е екранът при първо стартиране на Google Асистент в Chrome</translation>
<translation id="5015510746216210676">Име на компютъра:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Щат</translation>
<translation id="5094747076828555589">Сървърът не можа да докаже, че е <ph name="DOMAIN" />; Chromium няма доверие на сертификата му за сигурност. Това може да се дължи на неправилно конфигуриране или на прихващане на връзката ви от атакуващ.</translation>
<translation id="5095208057601539847">Провинция</translation>
+<translation id="5098222253617183465">Устройството ви се управлява от <ph name="ENROLLMENT_DOMAIN" />, а профилът ви се управлява от <ph name="ACCOUNT_DOMAIN" />. Това означава, че администраторите може отдалечено да конфигурират устройството и профила ви.</translation>
<translation id="5115563688576182185">(64 бита)</translation>
<translation id="5128122789703661928">Сесията с това име не е валидна за изтриване.</translation>
<translation id="5135404736266831032">Управление на адресите...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Машината</translation>
<translation id="5179510805599951267">Не е на <ph name="ORIGINAL_LANGUAGE" />? Подайте сигнал за тази грешка</translation>
<translation id="5190835502935405962">Лента на отметките</translation>
+<translation id="5200263511887412697">съставя списък с потребителите на устройството, които наскоро са влизали в профилите си</translation>
<translation id="5201306358585911203">Страница, вградена в тази страница, изпраща съобщение</translation>
<translation id="5205222826937269299">Името е задължително</translation>
<translation id="5215116848420601511">Начини на плащане и адреси посредством Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Няма достъп до този сайт</translation>
<translation id="5869522115854928033">Запазени пароли</translation>
<translation id="5887400589839399685">Картата бе запазена</translation>
+<translation id="5893718151540690985">съставя списък с мрежовите интерфейси, включващ типовете и хардуерните им адреси</translation>
<translation id="5893752035575986141">Приемат се кредитни карти.</translation>
<translation id="5901630391730855834">жълто</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (синхронизирано)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Редактиране на информацията за връзка</translation>
<translation id="5967867314010545767">Премахване от историята</translation>
<translation id="5975083100439434680">Намаляване на мащаба</translation>
+<translation id="5977489021191000276">Устройството ви не се управлява от администратор.</translation>
<translation id="5977976211062815271">На това устройство</translation>
<translation id="598637245381783098">Приложението за плащане не може да се отвори</translation>
<translation id="5989320800837274978">Не са посочени нито фиксирани прокси сървъри, нито URL адрес на скрипт във формат .pac.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Извършители на атака срещу <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> могат да инсталират измамни приложения, които се представят за нещо друго или събират данни, които може да се използват за проследяването ви. <ph name="BEGIN_LEARN_MORE_LINK" />Научете повече<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (синхронизирани)</translation>
<translation id="6027201098523975773">Въведете име</translation>
+<translation id="6033927989869462158">отчита статистически данни за хардуера, като използване на централния процесор и RAM паметта</translation>
<translation id="6034000775414344507">светлосиво</translation>
<translation id="6039846035001940113">Ако проблемът не бъде отстранен, свържете се със собственика на сайта.</translation>
<translation id="6040143037577758943">Затваряне</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Потребителски агент</translation>
<translation id="6903319715792422884">Помогнете за подобряването на Безопасно сърфиране, като ни изпращате <ph name="BEGIN_WHITEPAPER_LINK" />системна информация и част от съдържанието на страниците<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Потребител:</translation>
+<translation id="6934672428414710184">Това име е от профила ви в Google</translation>
+<translation id="6939583532829045966">Устройството ви се управлява от <ph name="ENROLLMENT_DOMAIN" />. Това значи, че администраторът ви може да го конфигурира отдалечено.</translation>
<translation id="6944692733090228304">Въведохте паролата си на сайт, който не се управлява от <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. За да защитите профила си, не използвайте паролата си повторно в други приложения и сайтове.</translation>
<translation id="6945221475159498467">Изберете</translation>
<translation id="6948701128805548767">За да видите начините на вземане и изискванията, изберете адрес</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;Кликнете върху &lt;strong&gt;Приложи&lt;/strong&gt; и след това – върху &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;Посетете &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Помощния център на Chrome&lt;/a&gt;, за да научите как да премахнете за постоянно софтуера от компютъра си.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Управление на <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Управление на паролите…</translation>
<translation id="7419106976560586862">Път на потребителския профил</translation>
<translation id="7437289804838430631">Добавяне на информация за връзка</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">светлооранжево</translation>
<translation id="7444046173054089907">Този сайт е блокиран</translation>
<translation id="7445762425076701745">Идентичността на сървъра, към който сте свързани, не може да бъде потвърдена изцяло. Свързани сте към сървър чрез име, което е валидно само във вашата мрежа и чиято собственост няма начин да се потвърди от външен сертифициращ орган. Тъй като някои сертифициращи органи въпреки това издават сертификати за такива имена, не е възможно да се гарантира, че сте свързани към желания сайт, а не към атакуващ.</translation>
+<translation id="7449109375006139765">изпраща системните регистрационни файлове до сървъра за управление</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Научете повече<ph name="END_LINK" /> за този проблем.</translation>
<translation id="7455133967321480974">Използване на глобалната стандартна стойност (блокиране)</translation>
<translation id="7460618730930299168">Прожекцията е различна от избраната от вас. Искате ли да продължите?</translation>
<translation id="7473891865547856676">Не, благодаря</translation>
+<translation id="7475525192983021547">отчита периодите от време, когато потребителят е активен на устройството</translation>
<translation id="7481312909269577407">Препращане</translation>
<translation id="7485870689360869515">Няма намерени данни.</translation>
<translation id="7508255263130623398">Върнатият от правилата идентификационен номер на устройството е празен или не съответства на текущия</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">Не е посочено</translation>
<translation id="800218591365569300">Затворете другите раздели или програми, за да освободите памет.</translation>
<translation id="8009225694047762179">Управление на паролите</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Тази карта и адресът й за фактуриране ще бъдат запазени. Ще можете да я използвате, когато сте влезли в профила <ph name="USER_EMAIL" />.}other{Тези карти и адресите им за фактуриране ще бъдат запазени. Ще можете да ги използвате, когато сте влезли в профила <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Не можахме да се свържем с родителите ви. Моля, опитайте отново.</translation>
<translation id="8025119109950072390">Извършителите на атаки, използващи този сайт, може да ви подведат да направите нещо опасно, като например да инсталирате софтуер или да разкриете лична информация (например пароли, телефонни номера или номера на кредитни карти).</translation>
<translation id="8034522405403831421">Тази страница е на <ph name="SOURCE_LANGUAGE" />. Да се преведе ли на <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">Използване на глобалната стандартна стойност (запитване)</translation>
<translation id="8042918947222776840">Избиране на начин на вземане</translation>
<translation id="8057711352706143257">Софтуерът <ph name="SOFTWARE_NAME" /> не е конфигуриран правилно. Обикновено проблемът се отстранява с деинсталиране на <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Устройството ви е конфигурирано да:</translation>
<translation id="8078141288243656252">Добавянето на пояснения не е възможно, когато документът е завъртян</translation>
<translation id="8079031581361219619">Искате ли да презаредите сайта?</translation>
<translation id="8088680233425245692">Преглеждането на статията не бе успешно.</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">Изключете самолетния режим.</translation>
<translation id="8364627913115013041">Не е зададено.</translation>
<translation id="8368476060205742148">Услуги за Google Play</translation>
+<translation id="8371889962595521444">Персонализирани основни сертификати</translation>
<translation id="8380941800586852976">Опасно</translation>
<translation id="8381674639488873545">Тези таксувания може да са еднократни или периодични и е възможно да не са явни. <ph name="BEGIN_LINK" />Показване въпреки това<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Наскоро посетените от вас отметки ще се показват тук</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">Конфигурацията на мрежата е невалидна и не можа да се импортира.
Допълнителни подробности:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Устройството се управлява от <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" />, <ph name="SECOND_LABEL" />, <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Промяна</translation>
<translation id="8428213095426709021">Настройки</translation>
@@ -1225,6 +1244,7 @@
<translation id="8932102934695377596">Часовникът ви е назад</translation>
<translation id="893332455753468063">Добавяне на име</translation>
<translation id="8938939909778640821">Приемани кредитни и предплатени карти</translation>
+<translation id="894185898663964645">Администраторът ви е конфигурирал персонализирани основни сертификати, което може да му позволи да вижда съдържанието на посещаваните от вас уебсайтове.</translation>
<translation id="8943282376843390568">лимоненозелено</translation>
<translation id="8957210676456822347">Упълномощаване в портал за удостоверяване</translation>
<translation id="8968766641738584599">Запазване на картата</translation>
diff --git a/chromium/components/strings/components_strings_bn.xtb b/chromium/components/strings/components_strings_bn.xtb
index 0dcb4c8999a..12165f1ffff 100644
--- a/chromium/components/strings/components_strings_bn.xtb
+++ b/chromium/components/strings/components_strings_bn.xtb
@@ -187,6 +187,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" /> ভাষার পৃষ্ঠা অনুবাদ করা হবে না।</translation>
<translation id="2053553514270667976">পিন কোড</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{১টি প্রস্তাব}one{#টি প্রস্তাব}other{#টি প্রস্তাব}}</translation>
+<translation id="2068124040035837596">আপনার অ্যাকাউন্ট <ph name="ENROLLMENT_DOMAIN" />-এর দ্বারা পরিচালিত হয়। অর্থাৎ, অ্যাডমিনিস্ট্রেটর দূর থেকে আপনার ডিভাইস ও অ্যাকাউন্ট কনফিগার করতে পারেন।</translation>
<translation id="2068663545051464999">ক্র্যাশ রিপোর্ট আইডি <ph name="CRASH_ID" /> আপলোড করা হয়েছে (স্থানীয় প্রসঙ্গ: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">পূর্বাবস্থায় ফিরুন</translation>
<translation id="20817612488360358">সিস্টেম প্রক্সি সেটিংস ব্যবহার করার জন্য সেট আছে কিন্তু একটি সুনির্দিষ্ট প্রক্সি কনফিগারেশনও নির্দিষ্ট করা আছে৷</translation>
@@ -245,6 +246,7 @@
<translation id="239429038616798445">এই পদ্ধতিতে শিপিং করা যাবে না। অন্য পদ্ধতি ব্যবহার করুন।</translation>
<translation id="2396249848217231973">&amp;মুছে ফেলাকে পূর্বাবস্থায় ফেরান</translation>
<translation id="2413528052993050574">এই সার্ভার প্রমাণ করতে পারেনি যে এটি <ph name="DOMAIN" />; এর নিরাপত্তা সার্টিফিকেট প্রত্যাহার করা হতে পারে। কোনো ভুল কনফিগারেশনের কারণে অথবা কোনো আক্রমণকারী আপনার সংযোগ মাঝপথে আটকে দিচ্ছে বলে এমনটা হতে পারে।</translation>
+<translation id="244665789865330679">আপনার ডিভাইস ও আপনার অ্যাকাউন্ট <ph name="ENROLLMENT_DOMAIN" />-এর দ্বারা পরিচালিত হয়। অর্থাৎ, অ্যাডমিনিস্ট্রেটর দূর থেকে আপনার ডিভাইস ও অ্যাকাউন্ট কনফিগার করতে পারেন।</translation>
<translation id="2463193859425327265">হোম পৃষ্ঠা পরিবর্তন করুন</translation>
<translation id="2463739503403862330">পূরণ করুন</translation>
<translation id="2465655957518002998">ডেলিভারি পদ্ধতি বেছে নিন</translation>
@@ -562,6 +564,7 @@
<translation id="4377125064752653719">আপনি <ph name="DOMAIN" />-এ পৌঁছানোর প্রচেষ্টা করেছেন, তবে সার্ভারটি যে সার্টিফিকেটটি উপস্থাপন করেছে সেটির জারিকর্তা সেটিকে প্রত্যাহার করেছে৷ এর অর্থ হ'ল সার্ভারটি যে সুরক্ষা প্রমানপত্র উপস্থাপন করেছে তা কোনওমতেই বিশ্বাসযোগ্য নয়৷ হতে পারে আপনি একজন আক্রমণকারীর সাথে যোগাযোগ করছেন৷</translation>
<translation id="4378154925671717803">ফোন</translation>
<translation id="4406896451731180161">সার্চের ফলাফলগুলি</translation>
+<translation id="4406972042435603828">আপনার অ্যাডমিনিস্ট্রেটর শক্তিশালী ক্ষমতা আছে এমন এক্সটেনশন ইনস্টল করেছেন।</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" />টি কুকিজ</translation>
<translation id="4415426530740016218">পিক-আপের ঠিকানা</translation>
<translation id="4424024547088906515">এই সার্ভার প্রমাণ করতে পারেনি যে এটি <ph name="DOMAIN" />; এর নিরাপত্তা সার্টিফিকেট Chrome এর নিকট বিশ্বাসযোগ্য নয়। কোনো ভুল কনফিগারেশনের কারণে অথবা কোনো আক্রমণকারী আপনার সংযোগ মাঝপথে আটকে দিচ্ছে বলে এমনটা হতে পারে।</translation>
@@ -633,10 +636,12 @@
<translation id="4943872375798546930">কোন ফলাফল নেই</translation>
<translation id="4950898438188848926">একটি ট্যাব থেকে অন্য ট্যাবে যাওয়ার বোতাম, খোলা ট্যাবে যেতে এন্টার টিপুন, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">ক্রিয়াসমূহ</translation>
+<translation id="495832697253704892">এক্সটেনশন রিপোর্ট করা</translation>
<translation id="4958444002117714549">তালিকা প্রসারিত করুন</translation>
<translation id="4974590756084640048">সতর্কবার্তাগুলি পুনঃসক্ষম করুন</translation>
<translation id="4989163558385430922">সবগুলি দেখুন</translation>
<translation id="4989809363548539747">এই প্লাগ ইন সমর্থিত নয়</translation>
+<translation id="4996230189582812866">জানানো</translation>
<translation id="5002932099480077015">সক্রিয় করা হলে, ফর্ম পূরনের কাজ দ্রুত করতে Chrome এই ডিভাইসে আপনার কার্ডের একটি প্রতিলিপি সংরক্ষণ করবে।</translation>
<translation id="5014174725590676422">Chrome প্রথমবার চালানোর সময়ে Google অ্যাসিস্ট্যান্ট কীভাবে কাজ করবে তা দেখানো হয়েছে</translation>
<translation id="5015510746216210676">মেশিনের নাম:</translation>
@@ -657,6 +662,7 @@
<translation id="5089810972385038852">রাজ্য</translation>
<translation id="5094747076828555589">এই সার্ভার প্রমাণ করতে পারেনি যে এটি <ph name="DOMAIN" />; এর নিরাপত্তা সার্টিফিকেটটি Chromium এর নিকট বিশ্বাসযোগ্য নয়। কোনো ভুল কনফিগারেশনের কারণে অথবা কোনো আক্রমণকারী আপনার সংযোগ মাঝপথে আটকে দিচ্ছে বলে এমনটা হতে পারে।</translation>
<translation id="5095208057601539847">প্রদেশ</translation>
+<translation id="5098222253617183465">আপনার ডিভাইস <ph name="ENROLLMENT_DOMAIN" /> ও আপনার অ্যাকাউন্ট <ph name="ACCOUNT_DOMAIN" />-এর দ্বারা পরিচালিত হয়। অর্থাৎ, অ্যাডমিনিস্ট্রেটর দূর থেকে আপনার ডিভাইস ও অ্যাকাউন্ট কনফিগার করতে পারেন।</translation>
<translation id="5115563688576182185">(৬৪-বিট)</translation>
<translation id="5128122789703661928">এই নামের সেশনটি মুছে ফেলার জন্য সঠিক নয়।</translation>
<translation id="5135404736266831032">ঠিকানাগুলি পরিচালনা করুন...</translation>
@@ -669,6 +675,7 @@
<translation id="5172758083709347301">যন্ত্র</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" />-এ নেই? এই ত্রুটি রিপোর্ট করুন</translation>
<translation id="5190835502935405962">বুকমার্ক দণ্ড</translation>
+<translation id="5200263511887412697">ডিভাইসে সম্প্রতি লগ-ইন করেছেন এমন ব্যবহারকারীর একটি সূচি প্রদান করে</translation>
<translation id="5201306358585911203">এই পৃষ্ঠার এম্বেডেড করা একটি পৃষ্ঠায় এটি দেখানো হচ্ছে</translation>
<translation id="5205222826937269299">নাম প্রয়োজন</translation>
<translation id="5215116848420601511">Google Pay ব্যবহার করে এমন পেমেন্টের পদ্ধতি এবং ঠিকানা</translation>
@@ -770,6 +777,7 @@
<translation id="5869405914158311789">এই সাইটটিতে পৌছানো যাচ্ছে না</translation>
<translation id="5869522115854928033">সংরক্ষিত পাসওয়ার্ড</translation>
<translation id="5887400589839399685">কার্ড সেভ করা হয়েছে</translation>
+<translation id="5893718151540690985">ধরন ও হার্ডওয়্যার ঠিকানা সহ নেটওয়ার্ক ইন্টারফেসের একটি সূচি দেখায়</translation>
<translation id="5893752035575986141">ক্রেডিট কার্ড গ্রহণ করা হয়।</translation>
<translation id="5901630391730855834">হলুদ</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (সিঙ্ক হয়েছে)</translation>
@@ -783,6 +791,7 @@
<translation id="5967592137238574583">পরিচিতির তথ্য সম্পাদনা করুন</translation>
<translation id="5967867314010545767">ইতিহাস থেকে সরান</translation>
<translation id="5975083100439434680">জুম কমান</translation>
+<translation id="5977489021191000276">কোনও অ্যাডমিনিস্ট্রেটর আপনার ডিভাইস পরিচালনা করেন না।</translation>
<translation id="5977976211062815271">এই ডিভাইসে</translation>
<translation id="598637245381783098">পেমেন্ট অ্যাপ খোলা যাচ্ছে না</translation>
<translation id="5989320800837274978">কোনো নির্ধারিত প্রক্সি সার্ভার অথবা একটি.pac স্ক্রিপ্ট UR সুর্নিদিষ্টভাবে উল্লেখ করা হয়নি৷</translation>
@@ -794,6 +803,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />-এ সক্রিয় থাকা আক্রমণকারীরা এমন প্রতারণামূলক অ্যাপ ইনস্টল করে দিতে পারে যেগুলি অন্যান্য আপের থেকে আলাদা করা যায় না অথবা যেগুলি এমন ডেটা সংগ্রহ করে যা দিয়ে আপনার উপরে নজর রাখা যাবে। <ph name="BEGIN_LEARN_MORE_LINK" />আরও জানুন<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (সিঙ্ক হয়েছে)</translation>
<translation id="6027201098523975773">একটি নাম লিখুন</translation>
+<translation id="6033927989869462158">CPU/RAM ব্যবহারের মতো হার্ডওয়্যার পরিসংখ্যান অ্যাডমিনিস্ট্রেটরকে দেখায়</translation>
<translation id="6034000775414344507">হালকা ধূসর</translation>
<translation id="6039846035001940113">যদি সমস্যাটি চলতে থাকে তবে সাইট মালিকের সাথে যোগাযোগ করুন।</translation>
<translation id="6040143037577758943">বন্ধ</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">ব্যবহারকারী এজেন্ট</translation>
<translation id="6903319715792422884">সিস্টেমের কিছু <ph name="BEGIN_WHITEPAPER_LINK" />তথ্য এবং পৃষ্ঠার কন্টেন্ট<ph name="END_WHITEPAPER_LINK" /> Google-কে পাঠানোর মাধ্যমে আপনি নিরাপদ ব্রাউজিং আরও ভাল করে তুলতে সহায়তা করতে পারেন। <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ব্যবহারকারী:</translation>
+<translation id="6934672428414710184">এই নাম আপনার Google অ্যাকাউন্ট থেকে নেওয়া</translation>
+<translation id="6939583532829045966">আপনার ডিভাইস <ph name="ENROLLMENT_DOMAIN" />-এর দ্বারা পরিচালিত হয়। অর্থাৎ, অ্যাডমিনিস্ট্রেটর দূর থেকে আপনার ডিভাইস ও অ্যাকাউন্ট কনফিগার করতে পারেন।</translation>
<translation id="6944692733090228304">আপনার <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />-এর নয় এমন একটি সাইটে আপনার পাসওয়ার্ড লিখেছেন। আপনার অ্যাকাউন্টের সুরক্ষার জন্য অন্যান্য অ্যাপ এবং সাইটে আপনার এই পাসওয়ার্ডটি ব্যবহার করবেন না।</translation>
<translation id="6945221475159498467">নির্বাচন</translation>
<translation id="6948701128805548767">পিকআপ এর পদ্ধতি এবং প্রয়োজনীয়তা দেখতে একটি ঠিকানা বেছে নিন</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;&lt;strong&gt;প্রয়োগ করুন&lt;/strong&gt;-এ ক্লিক করে, &lt;strong&gt;ঠিক আছে&lt;/strong&gt;বোতামে ক্লিক করুন
&lt;li&gt;কম্পিউটার থেকে সফ্টওয়্যারটি স্থায়ীভাবে সরিয়ে দেওয়ার পদ্ধতি জানতে &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome সহায়তা কেন্দ্রে&lt;/a&gt; যান
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> ম্যানেজমেন্ট</translation>
<translation id="7416351320495623771">পাসওয়ার্ডগুলি পরিচালনা করুন…</translation>
<translation id="7419106976560586862">প্রোফাইল পথ</translation>
<translation id="7437289804838430631">পরিচিতির তথ্য যোগ করুন</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">হালকা কমলা</translation>
<translation id="7444046173054089907">সাইটটি অবরুদ্ধ</translation>
<translation id="7445762425076701745">আপনি যে সার্ভারে সংযুক্ত রয়েছে সেটিকে সম্পূর্ণ যাচাই করতে পারা যায় না৷ আপনি নামগুলি দিয়ে এমন একটি সার্ভারে সংযুক্ত রয়েছেন যা আপনার নেটওয়ার্কে বৈধ, যেটি একটি বাহ্যিক শংসাকরণ কর্তৃপক্ষ যার এটির মালিকানা যাচাই করার কোনও উপায় নেই৷ কিছু সার্টিফিকেট কর্তৃপক্ষ এই নামগুলি নির্বিচারে সার্টিফিকেটগুলি ইস্যু করবে, আপনি উদ্দিষ্ট ওয়েবসাইটে সংযুক্ত রয়েছেন কোনও আক্রমণকারীতে নয় তা নিশ্চিত করার কোনও উপায় নেই৷</translation>
+<translation id="7449109375006139765">ম্যানেজমেন্ট সার্ভারে সিস্টেম লগ পাঠান</translation>
<translation id="7451311239929941790">এই সমস্যা সম্পর্কে <ph name="BEGIN_LINK" />আরও জানুন<ph name="END_LINK" />।</translation>
<translation id="7455133967321480974">বিশ্বব্যাপী ডিফল্ট ব্যবহার করুন (অবরোধ করুন)</translation>
<translation id="7460618730930299168">আপনি যা বেছে নিয়েছেন তার থেকে স্ক্রিনিংটি আলাদা। এগিয়ে যাবেন?</translation>
<translation id="7473891865547856676">না থাক</translation>
+<translation id="7475525192983021547">কোনও ব্যবহারকারীর ডিভাইস ব্যবহার করার সময়কাল দেখায়</translation>
<translation id="7481312909269577407">ফরওয়ার্ড</translation>
<translation id="7485870689360869515">কোনো ডেটা পাওয়া যায়নি৷</translation>
<translation id="7508255263130623398">ফিরে পাওয়া নীতির ডিভাইস আইডি খালি অথবা বর্তমান ডিভাইস আইডির সাথে মিলছে না</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">নির্দিষ্ট করে উল্লেখ করা নেই</translation>
<translation id="800218591365569300">মেমরি ফাঁকা করতে অন্যান্য ট্যাব বা প্রোগ্রাম বন্ধ করার চেষ্টা করুন।</translation>
<translation id="8009225694047762179">পাসওয়ার্ড পরিচালনা করুন</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{এই কার্ড ও সেটির বিলিং ঠিকানা সেভ করা হবে। <ph name="USER_EMAIL" />-এ সাইন-ইন করে থাকা অবস্থায় আপনি সেটি ব্যবহার করতে পারবেন।}one{এই কার্ডগুলি ও সেগুলির বিলিং ঠিকানা সেভ করা হবে। <ph name="USER_EMAIL" />-এ সাইন-ইন করে থাকা অবস্থায় আপনি সেগুলি ব্যবহার করতে পারবেন।}other{এই কার্ডগুলি ও সেগুলির বিলিং ঠিকানা সেভ করা হবে। <ph name="USER_EMAIL" />-এ সাইন-ইন করে থাকা অবস্থায় আপনি সেগুলি ব্যবহার করতে পারবেন।}}</translation>
<translation id="8012647001091218357">এই মুহূর্তে আমরা আপনার পিতামাতার কাছে পৌঁছাতে পারিনি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷</translation>
<translation id="8025119109950072390">Attackers on this site may trick you into doing something dangerous like installing software or revealing your personal information (for example, passwords, phone numbers, or credit cards).</translation>
<translation id="8034522405403831421">এই পৃষ্ঠাটি <ph name="SOURCE_LANGUAGE" /> ভাষায় রয়েছে৷ এটিকে <ph name="TARGET_LANGUAGE" /> ভাষায় অনুবাদ করবেন?</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">বিশ্বব্যাপী ডিফল্ট ব্যবহার করুন (জানতে চান)</translation>
<translation id="8042918947222776840">পিক-আপের পদ্ধতি বেছে নিন</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" সঠিকভাবে কনফিগার হয়নি। সাধারণত "<ph name="SOFTWARE_NAME" />" আন-ইনস্টল করা হলে সমস্যার সমাধান হয়ে যায়। <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">আপনার ডিভাইসে এই নীতিগুলি সেট করা হয়েছে:</translation>
<translation id="8078141288243656252">ঘূর্ণনের সময় ব্যাখ্যা করা যাবে না</translation>
<translation id="8079031581361219619">সাইটটি আবার লোড করবেন?</translation>
<translation id="8088680233425245692">নিবন্ধ দেখতে ব্যর্থ হয়েছে৷</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">বিমান মোড বন্ধ করে দেখুন</translation>
<translation id="8364627913115013041">সেট করা নেই৷</translation>
<translation id="8368476060205742148">Google Play পরিষেবাদি</translation>
+<translation id="8371889962595521444">কাস্টম রুট সার্টিফিকেট</translation>
<translation id="8380941800586852976">বিপজ্জনক</translation>
<translation id="8381674639488873545">এই চার্জ এককালীন হতে পারে বা তার পুনরাবৃত্তি হতে পারে এবং তা স্পষ্ট করে বোঝা নাও যেতে পারে। <ph name="BEGIN_LINK" />তবুও দেখান<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">আপনার সম্প্রতি ঘুরে দেখা বুকমার্কগুলি এখানে দেখা যাবে</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">নেটওয়ার্ক কনফিগারেশনটি সঠিক নয় এবং ইমপোর্ট করা যায়নি৷
অতিরিক্ত বিবরণ:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533"><ph name="ENROLLMENT_DOMAIN" />-এর দ্বারা পরিচালিত ডিভাইস</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">পরিবর্তন</translation>
<translation id="8428213095426709021">সেটিংস</translation>
@@ -1225,6 +1244,7 @@
<translation id="8932102934695377596">আপনার ঘড়ির সময় পিছিয়ে রয়েছে</translation>
<translation id="893332455753468063">নাম যোগ করুন</translation>
<translation id="8938939909778640821">ক্রেডিট ও প্রিপেড কার্ড গ্রহণ করা হয়</translation>
+<translation id="894185898663964645">আপনার অ্যাডমিনিস্ট্রেটর কাস্টম রুট সার্টিফিকেট কনফিগার করেছেন, যার ফলে আপনি যে ওয়েবসাইটে যাচ্ছেন সেটির কন্টেন্ট তিনি দেখতে পেতে পারেন।</translation>
<translation id="8943282376843390568">লাইম</translation>
<translation id="8957210676456822347">ক্যাপটিভ পোর্টাল অনুমোদন</translation>
<translation id="8968766641738584599">কার্ড সেভ করুন</translation>
diff --git a/chromium/components/strings/components_strings_ca.xtb b/chromium/components/strings/components_strings_ca.xtb
index 63f6ab4c3c1..15d733328a1 100644
--- a/chromium/components/strings/components_strings_ca.xtb
+++ b/chromium/components/strings/components_strings_ca.xtb
@@ -6,7 +6,7 @@
<translation id="1010200102790553230">Carrega la pàgina més tard</translation>
<translation id="1015730422737071372">Proporcioneu més informació</translation>
<translation id="1021110881106174305">Targetes acceptades</translation>
-<translation id="1032854598605920125">Gira en el sentit de les agulles del rellotge</translation>
+<translation id="1032854598605920125">Gira en sentit horari</translation>
<translation id="1035334672863811645">Inicia la sessió a Chrome</translation>
<translation id="1038842779957582377">nom desconegut</translation>
<translation id="1050038467049342496">Tanca altres aplicacions</translation>
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Les pàgines en <ph name="LANGUAGE" /> no es traduiran.</translation>
<translation id="2053553514270667976">Codi postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggeriment}other{# suggeriments}}</translation>
+<translation id="2068124040035837596">El compte està gestionat per <ph name="ENROLLMENT_DOMAIN" />. Això vol dir que l'administrador pot configurar el compte de manera remota.</translation>
<translation id="2068663545051464999">S'ha penjat l'identificador <ph name="CRASH_ID" /> de l'informe d'error (context local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Desfés</translation>
<translation id="20817612488360358">S'ha definit la configuració del servidor intermediari del sistema perquè es pugui utilitzar, però també s'ha especificat una configuració del servidor intermediari explícita.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Aquest mètode d'enviament no està disponible. Prova'n un altre.</translation>
<translation id="2396249848217231973">&amp;Desfés la supressió</translation>
<translation id="2413528052993050574">El servidor no ha pogut comprovar que sigui <ph name="DOMAIN" /> perquè és possible que el seu certificat de seguretat s'hagi revocat. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la vostra connexió.</translation>
+<translation id="244665789865330679">El dispositiu i el compte estan gestionats per <ph name="ENROLLMENT_DOMAIN" />. Això vol dir que l'administrador pot configurar el dispositiu i el compte de manera remota.</translation>
<translation id="2463193859425327265">Canvia la pàgina d'inici</translation>
<translation id="2463739503403862330">Emplena</translation>
<translation id="2465655957518002998">Tria el mètode d'entrega</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Heu provat d'accedir a <ph name="DOMAIN" />, però l'emissor ha revocat el certificat que ha presentat el servidor. Això vol dir que no heu de confiar gens en les credencials de seguretat que ha presentat el servidor. És possible que us estigueu comunicant amb un atacant.</translation>
<translation id="4378154925671717803">Telèfon</translation>
<translation id="4406896451731180161">resultats de la cerca</translation>
+<translation id="4406972042435603828">Els administradors han instal·lat extensions amb funcions molt potents.</translation>
<translation id="4408413947728134509">Galetes <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Adreça de recollida</translation>
<translation id="4424024547088906515">Aquest servidor no ha pogut comprovar que sigui <ph name="DOMAIN" /> perquè Chrome considera que el seu certificat de seguretat no és de confiança. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la vostra connexió.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">No hi ha resultats</translation>
<translation id="4950898438188848926">Botó per canviar de pestanya; prem Retorn per canviar a la pestanya oberta, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Accions</translation>
+<translation id="495832697253704892">Informes d'extensions</translation>
<translation id="4958444002117714549">Desplega la llista</translation>
<translation id="4974590756084640048">Torna a activar els advertiments</translation>
<translation id="4989163558385430922">Mostra-ho tot</translation>
<translation id="4989809363548539747">Aquest connector no és compatible</translation>
+<translation id="4996230189582812866">Informes</translation>
<translation id="5002932099480077015">Si s'activa, Chrome emmagatzemarà una còpia de la targeta en aquest dispositiu per agilitzar l'emplenament de formularis.</translation>
<translation id="5014174725590676422">Es mostra la pantalla de la primera execució de l'Assistent de Google a Chrome</translation>
<translation id="5015510746216210676">Nom de l'ordinador:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Estat</translation>
<translation id="5094747076828555589">Aquest servidor no ha pogut comprovar que sigui <ph name="DOMAIN" /> perquè Chromium considera que el seu certificat de seguretat no és de confiança. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la vostra connexió.</translation>
<translation id="5095208057601539847">Província</translation>
+<translation id="5098222253617183465">El dispositiu està gestionat per <ph name="ENROLLMENT_DOMAIN" /> i el compte, per <ph name="ACCOUNT_DOMAIN" />. Això vol dir que els administradors poden configurar tant el dispositiu com el compte de manera remota.</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5128122789703661928">La sessió amb aquest nom no es pot suprimir.</translation>
<translation id="5135404736266831032">Gestiona les adreces...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Automàtica</translation>
<translation id="5179510805599951267">No està escrita en <ph name="ORIGINAL_LANGUAGE" />? Informa d'aquest error</translation>
<translation id="5190835502935405962">Barra d'adreces d'interès</translation>
+<translation id="5200263511887412697">informa de la llista d'usuaris del dispositiu que han iniciat la sessió recentment</translation>
<translation id="5201306358585911203">Una pàgina inserida en aquesta pàgina diu</translation>
<translation id="5205222826937269299">El nom és obligatori</translation>
<translation id="5215116848420601511">Formes de pagament i adreces que fan servir Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">No es pot accedir a aquest lloc</translation>
<translation id="5869522115854928033">Contrasenyes desades</translation>
<translation id="5887400589839399685">S'ha desat la targeta</translation>
+<translation id="5893718151540690985">informa de la llista d'interfícies de xarxa amb els seus tipus i adreces de maquinari</translation>
<translation id="5893752035575986141">S'accepten targetes de crèdit.</translation>
<translation id="5901630391730855834">Groc</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (informació sincronitzada)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Edita la informació de contacte</translation>
<translation id="5967867314010545767">Elimina de l'historial</translation>
<translation id="5975083100439434680">Redueix</translation>
+<translation id="5977489021191000276">El dispositiu no està gestionat per cap administrador.</translation>
<translation id="5977976211062815271">En aquest dispositiu</translation>
<translation id="598637245381783098">No es pot obrir l'aplicació de pagament</translation>
<translation id="5989320800837274978">No s'especifiquen servidors intermediaris ni URL d'script .pac.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Pot ser que els atacants que es troben a <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> instal·lin aplicacions enganyoses que es facin passar per d'altres o que recullin dades que podrien utilitzar-se per fer un seguiment de la teva activitat. <ph name="BEGIN_LEARN_MORE_LINK" />Més informació<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (informació sincronitzada)</translation>
<translation id="6027201098523975773">Escriu un nom</translation>
+<translation id="6033927989869462158">informa d'estadístiques del maquinari com ara l'ús de CPU o de RAM.</translation>
<translation id="6034000775414344507">Gris clar</translation>
<translation id="6039846035001940113">Si el problema continua, contacta amb el propietari del lloc web.</translation>
<translation id="6040143037577758943">Tanca</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Agent d'usuari</translation>
<translation id="6903319715792422884">Per ajudar a millorar Navegació segura, envia a Google <ph name="BEGIN_WHITEPAPER_LINK" />algunes dades del sistema i contingut de les pàgines<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Usuari:</translation>
+<translation id="6934672428414710184">Aquest nom prové del teu Compte de Google</translation>
+<translation id="6939583532829045966">El dispositiu està gestionat per <ph name="ENROLLMENT_DOMAIN" />. Això vol dir que l'administrador pot configurar el dispositiu de manera remota.</translation>
<translation id="6944692733090228304">Has introduït la contrasenya en un lloc web que no està gestionat per <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Per protegir el teu compte, no facis servir la mateixa contrasenya en altres aplicacions ni llocs web.</translation>
<translation id="6945221475159498467">Selecciona</translation>
<translation id="6948701128805548767">Per veure els mètodes i els requisits de recollida, selecciona una adreça</translation>
@@ -992,6 +1004,7 @@ Detalls addicionals:
&lt;li&gt;Feu clic a &lt;strong&gt;Aplica&lt;/strong&gt; i, a continuació, a &lt;strong&gt;D'acord&lt;/strong&gt;.
&lt;li&gt;Visiteu el &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centre d'ajuda de Chrome&lt;/a&gt; per obtenir informació sobre com podeu suprimir permanentment el programari de l'ordinador.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Gestió de: <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Gestiona les contrasenyes…</translation>
<translation id="7419106976560586862">Camí del perfil</translation>
<translation id="7437289804838430631">Afegeix informació de contacte</translation>
@@ -1000,10 +1013,12 @@ Detalls addicionals:
<translation id="7442725080345379071">Taronja clar</translation>
<translation id="7444046173054089907">Aquest lloc està bloquejat</translation>
<translation id="7445762425076701745">La identitat del servidor al qual esteu connectat no es pot acabar de validar. Esteu connectat a un servidor que utilitza un nom que només és vàlid dins la vostra xarxa, de manera que una autoritat de certificació externa no en pot validar la propietat. Com que de tota manera algunes autoritats de certificació emetran certificats per a aquests noms, no es pot assegurar que estigueu connectat al lloc web previst i no a un atacant.</translation>
+<translation id="7449109375006139765">envia registres del sistema al servidor de gestió</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Obtenir més informació<ph name="END_LINK" /> sobre aquest problema</translation>
<translation id="7455133967321480974">Utilitza l'opció predeterminada global (Bloqueja)</translation>
<translation id="7460618730930299168">La projecció no és com havies seleccionat. Vols continuar?</translation>
<translation id="7473891865547856676">No, gràcies</translation>
+<translation id="7475525192983021547">informa dels períodes de temps en què un usuari està actiu al dispositiu</translation>
<translation id="7481312909269577407">Endavant</translation>
<translation id="7485870689360869515">No s'han trobat dades.</translation>
<translation id="7508255263130623398">L'identificador de dispositiu de la política que s'ha tornat és buit o no coincideix amb l'actual</translation>
@@ -1096,6 +1111,7 @@ Detalls addicionals:
<translation id="7995512525968007366">No especificat</translation>
<translation id="800218591365569300">Prova de tancar altres pestanyes o programes per alliberar memòria.</translation>
<translation id="8009225694047762179">Gestiona les contrasenyes</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Aquesta targeta i l'adreça de facturació associada es desaran. La podràs utilitzar quan tinguis la sessió iniciada a <ph name="USER_EMAIL" />.}other{Aquestes targetes i les adreces de facturació associades es desaran. Les podràs utilitzar quan tinguis la sessió iniciada a <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">En aquests moments no ens hem pogut posar en contacte amb els pares. Torneu-ho a provar.</translation>
<translation id="8025119109950072390">Els atacants d'aquest lloc et poden enganyar perquè facis alguna acció perillosa, com ara instal·lar programari o revelar informació personal (per exemple, contrasenyes, números de telèfon o targetes de crèdit).</translation>
<translation id="8034522405403831421">Aquesta pàgina està escrita en <ph name="SOURCE_LANGUAGE" />. Vols traduir-la a <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Detalls addicionals:
<translation id="8041940743680923270">Utilitza l'opció predeterminada global (Pregunta)</translation>
<translation id="8042918947222776840">Tria un mètode de recollida</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> no s'ha configurat correctament. Normalment el problema se soluciona desinstal·lant <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">El dispositiu s'ha configurat de la manera següent:</translation>
<translation id="8078141288243656252">No es poden fer anotacions en un document girat</translation>
<translation id="8079031581361219619">Vols tornar a carregar el lloc web?</translation>
<translation id="8088680233425245692">No s'ha pogut consultar l'article.</translation>
@@ -1156,6 +1173,7 @@ Detalls addicionals:
<translation id="8363502534493474904">Desactiva el mode d'avió.</translation>
<translation id="8364627913115013041">No s'ha definit.</translation>
<translation id="8368476060205742148">Serveis de Google Play</translation>
+<translation id="8371889962595521444">Certificats arrel personalitzats</translation>
<translation id="8380941800586852976">Perillós</translation>
<translation id="8381674639488873545">Aquests càrrecs poden ser únics o recurrents i és possible que no s'indiquin d'una manera evident. <ph name="BEGIN_LINK" />Mostra igualment<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Les adreces d'interès que has visitat fa poc es mostren aquí</translation>
@@ -1165,6 +1183,7 @@ Detalls addicionals:
<translation id="8416694386774425977">La configuració de la xarxa no és vàlida i no s'ha pogut importar.
Detalls addicionals:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Dispositiu gestionat per <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Canvia</translation>
<translation id="8428213095426709021">Configuració</translation>
@@ -1225,6 +1244,7 @@ Detalls addicionals:
<translation id="8932102934695377596">El rellotge està endarrerit</translation>
<translation id="893332455753468063">Afegeix un nom</translation>
<translation id="8938939909778640821">Targetes de crèdit i de prepagament acceptades</translation>
+<translation id="894185898663964645">L'administrador ha configurat certificats arrel personalitzats, que li poden permetre veure el contingut dels llocs web que visites.</translation>
<translation id="8943282376843390568">Verd llima</translation>
<translation id="8957210676456822347">Autorització de portals captius</translation>
<translation id="8968766641738584599">Desa la targeta</translation>
@@ -1253,7 +1273,7 @@ Detalls addicionals:
<translation id="9065203028668620118">Edita</translation>
<translation id="9065745800631924235">Cerca de <ph name="TEXT" /> des de l'historial</translation>
<translation id="9069693763241529744">Bloquejat per una extensió</translation>
-<translation id="9076283476770535406">Pot incloure contingut per a adults</translation>
+<translation id="9076283476770535406">Pot incloure contingut no apte per a menors</translation>
<translation id="9078964945751709336">Necessitem més informació</translation>
<translation id="9080712759204168376">Resum de la comanda</translation>
<translation id="9103872766612412690"><ph name="SITE" /> utilitza normalment l'encriptació per protegir la vostra informació. En aquesta ocasió, quan Chromium ha provat de connectar-se a <ph name="SITE" />, el lloc web ha enviat credencials poc comunes i incorrectes. Pot ser que un atacant estigui provant de fer-se passar per <ph name="SITE" /> o que una pantalla d'inici de sessió a la xarxa Wi-Fi hagi interromput la connexió. En qualsevol cas, la vostra informació continua estant segura, perquè Chromium ha aturat la connexió abans no s'intercanviés cap dada.</translation>
diff --git a/chromium/components/strings/components_strings_cs.xtb b/chromium/components/strings/components_strings_cs.xtb
index b22c1ae9d8e..69253c29018 100644
--- a/chromium/components/strings/components_strings_cs.xtb
+++ b/chromium/components/strings/components_strings_cs.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Stránky v jazyce <ph name="LANGUAGE" /> se nebudou překládat.</translation>
<translation id="2053553514270667976">PSČ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 návrh}few{# návrhy}many{# návrhu}other{# návrhů}}</translation>
+<translation id="2068124040035837596">Váš účet je spravován doménou <ph name="ENROLLMENT_DOMAIN" />. To znamená, že jej váš administrátor může vzdáleně konfigurovat.</translation>
<translation id="2068663545051464999">ID nahrané zprávy o selhání <ph name="CRASH_ID" /> (místní kontext: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Vrátit zpět</translation>
<translation id="20817612488360358">Jako aktivní jsou nakonfigurována systémová nastavení proxy serveru, je však určena i explicitní konfigurace proxy serveru.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Tento způsob dopravy není k dispozici. Zkuste použít jiný způsob.</translation>
<translation id="2396249848217231973">&amp;Vrátit smazání zpět</translation>
<translation id="2413528052993050574">Server nedokázal prokázat, že patří doméně <ph name="DOMAIN" />. Jeho bezpečnostní certifikát byl zřejmě zrušen. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaše připojení zachytává útočník.</translation>
+<translation id="244665789865330679">Vaše zařízení a účet jsou spravovány doménou <ph name="ENROLLMENT_DOMAIN" />. To znamená, že je může vzdáleně konfigurovat váš administrátor.</translation>
<translation id="2463193859425327265">Změnit domovskou stránku</translation>
<translation id="2463739503403862330">Vyplnit</translation>
<translation id="2465655957518002998">Vybrat způsob doručení</translation>
@@ -557,6 +559,7 @@
<translation id="4377125064752653719">Pokusili jste se přejít na web <ph name="DOMAIN" />, ale certifikát prezentovaný tímto webem byl vydavatelem certifikátu zrušen. To znamená, že bezpečnostním pověřením, která web prezentoval, nelze zcela důvěřovat. Je možné, že komunikujete s útočníkem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">výsledky vyhledávání</translation>
+<translation id="4406972042435603828">Vaši administrátoři nainstalovali rozšíření s rozsáhlými funkcemi.</translation>
<translation id="4408413947728134509">Soubory cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Adresa vyzvednutí</translation>
<translation id="4424024547088906515">Server nedokázal prokázat, že patří doméně <ph name="DOMAIN" />. Chrome jeho bezpečnostnímu certifikátu nedůvěřuje. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaše připojení zachytává útočník.</translation>
@@ -628,10 +631,12 @@
<translation id="4943872375798546930">Žádné výsledky</translation>
<translation id="4950898438188848926">Tlačítko přepínání karet. Stisknutím klávesy Enter přejdete na otevřenou kartu (<ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />)</translation>
<translation id="495170559598752135">Akce</translation>
+<translation id="495832697253704892">Hlášení rozšíření</translation>
<translation id="4958444002117714549">Rozbalit seznam</translation>
<translation id="4974590756084640048">Znovu zapnout upozornění</translation>
<translation id="4989163558385430922">Zobrazit vše</translation>
<translation id="4989809363548539747">Tento plugin není podporován</translation>
+<translation id="4996230189582812866">Hlášení</translation>
<translation id="5002932099480077015">Pokud je tato možnost aktivována, Chrome do zařízení uloží kopii karty za účelem rychlejšího vyplňování formulářů.</translation>
<translation id="5014174725590676422">Je zobrazena obrazovka prvního spuštění Asistenta Google v Chromu</translation>
<translation id="5015510746216210676">Název počítače:</translation>
@@ -652,6 +657,7 @@
<translation id="5089810972385038852">Stát/kraj</translation>
<translation id="5094747076828555589">Server nedokázal prokázat, že patří doméně <ph name="DOMAIN" />. Chromium jeho bezpečnostnímu certifikátu nedůvěřuje. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaše připojení zachytává útočník.</translation>
<translation id="5095208057601539847">Provincie</translation>
+<translation id="5098222253617183465">Vaše zařízení spravuje doména <ph name="ENROLLMENT_DOMAIN" /> a váš účet doména <ph name="ACCOUNT_DOMAIN" />. To znamená, že administrátoři vaše zařízení a účet mohou vzdáleně nakonfigurovat.</translation>
<translation id="5115563688576182185">(64bitový)</translation>
<translation id="5128122789703661928">Relace s tímto názvem není pro smazání platná.</translation>
<translation id="5135404736266831032">Spravovat adresy...</translation>
@@ -664,6 +670,7 @@
<translation id="5172758083709347301">Počítač</translation>
<translation id="5179510805599951267">Nejedná se o jazyk <ph name="ORIGINAL_LANGUAGE" />? Nahlaste tuto chybu.</translation>
<translation id="5190835502935405962">Lišta záložek</translation>
+<translation id="5200263511887412697">hlásit seznam uživatelů zařízení, kteří se nedávno přihlásili.</translation>
<translation id="5201306358585911203">Stránka vložená na této stránce říká</translation>
<translation id="5205222826937269299">Je nutné zadat jméno</translation>
<translation id="5215116848420601511">Platební metody a adresy pomocí služby Google Pay</translation>
@@ -765,6 +772,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="5869405914158311789">Tento web není dostupný</translation>
<translation id="5869522115854928033">Uložená hesla</translation>
<translation id="5887400589839399685">Karta byla uložena</translation>
+<translation id="5893718151540690985">hlásit seznam síťových rozhraní s informacemi o typu a hardwarových adresách</translation>
<translation id="5893752035575986141">Obchodník přijímá kreditní karty.</translation>
<translation id="5901630391730855834">Žlutá</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synchronizováno)</translation>
@@ -778,6 +786,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="5967592137238574583">Úprava kontaktních údajů</translation>
<translation id="5967867314010545767">Odstranit z historie</translation>
<translation id="5975083100439434680">Oddálit</translation>
+<translation id="5977489021191000276">Vaše zařízení není spravováno administrátorem.</translation>
<translation id="5977976211062815271">V tomto zařízení</translation>
<translation id="598637245381783098">Platební aplikaci nelze otevřít</translation>
<translation id="5989320800837274978">Nejsou určeny pevně dané servery proxy ani adresa URL skriptu PAC.</translation>
@@ -789,6 +798,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="6017850046339264347">Útočníci na webu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> by vám do zařízení mohli nainstalovat klamavé aplikace, které se vydávají za něco jiného nebo shromažďují data ke sledování vaší aktivity. <ph name="BEGIN_LEARN_MORE_LINK" />Další informace<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synchronizováno)</translation>
<translation id="6027201098523975773">Zadejte jméno</translation>
+<translation id="6033927989869462158">hlásit statistiky hardwaru, například využití CPU/RAM</translation>
<translation id="6034000775414344507">Světle šedá</translation>
<translation id="6039846035001940113">Pokud problém přetrvává, kontaktujte vlastníka webu.</translation>
<translation id="6040143037577758943">Zavřít</translation>
@@ -900,6 +910,8 @@ Kontaktujte administrátora systému.</translation>
<translation id="6897140037006041989">User agent</translation>
<translation id="6903319715792422884">Pomozte zlepšit Bezpečné vyhledávání tím, že budete část <ph name="BEGIN_WHITEPAPER_LINK" />informací o systému a obsahu stránek<ph name="END_WHITEPAPER_LINK" /> odesílat do Googlu. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Uživatel:</translation>
+<translation id="6934672428414710184">Toto jméno pochází z vašeho účtu Google</translation>
+<translation id="6939583532829045966">Vaše zařízení je spravováno doménou <ph name="ENROLLMENT_DOMAIN" />. To znamená, že jej může vzdáleně konfigurovat váš administrátor.</translation>
<translation id="6944692733090228304">Zadali jste heslo na webu, který není spravován organizací <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Aby byl váš účet chráněn, nepoužívejte jeho heslo v jiných aplikacích a na jiných webech.</translation>
<translation id="6945221475159498467">Vybrat</translation>
<translation id="6948701128805548767">Chcete-li zobrazit způsoby vyzvednutí a požadavky, vyberte adresu</translation>
@@ -986,6 +998,7 @@ Kontaktujte administrátora systému.</translation>
&lt;li&gt;Klikněte na &lt;strong&gt;Použít&lt;/strong&gt; a poté na &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;Informace o tom, jak tento software trvale odstranit z počítače, naleznete v &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;centru nápovědy prohlížeče Chrome&lt;/a&gt;.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Správa prohlížeče <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Spravovat hesla…</translation>
<translation id="7419106976560586862">Cesta k profilu</translation>
<translation id="7437289804838430631">Přidat kontaktní údaje</translation>
@@ -994,10 +1007,12 @@ Kontaktujte administrátora systému.</translation>
<translation id="7442725080345379071">Světle oranžová</translation>
<translation id="7444046173054089907">Tento web je blokován</translation>
<translation id="7445762425076701745">Totožnost serveru, k němuž jste připojeni, nelze plně ověřit. Jste připojeni k serveru, který používá název platný pouze v rámci vaší sítě. Externí certifikační autorita nemůže vlastnictví názvu nijak ověřit. Některé certifikační autority však vydají certifikát i pro takové názvy, a nelze tedy zaručit, že jste připojeni k požadovanému webu a nikoli k webu útočníka.</translation>
+<translation id="7449109375006139765">odesílat systémové protokoly na server správy</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Další informace<ph name="END_LINK" /> o tomto problému.</translation>
<translation id="7455133967321480974">Použít výchozí globální hodnotu (Blokovat)</translation>
<translation id="7460618730930299168">Přehrává se jiný obsah, než jste vybrali. Pokračovat?</translation>
<translation id="7473891865547856676">Ne, děkuji</translation>
+<translation id="7475525192983021547">hlásit časová období, kdy uživatel zařízení aktivně používá</translation>
<translation id="7481312909269577407">Vpřed</translation>
<translation id="7485870689360869515">Nebyla nalezena žádná data.</translation>
<translation id="7508255263130623398">Vrácené ID zařízení pro zásady je prázdné nebo neodpovídá aktuálnímu ID zařízení</translation>
@@ -1090,6 +1105,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="7995512525968007366">Není zadáno</translation>
<translation id="800218591365569300">Zkuste uvolnit paměť tím, že zavřete ostatní karty nebo programy.</translation>
<translation id="8009225694047762179">Spravovat hesla</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Tato karta a její fakturační adresa se uloží. Budete ji moci používat, když budete přihlášeni k účtu <ph name="USER_EMAIL" />.}few{Tyto karty a jejich fakturační adresy se uloží. Budete je moci používat, když budete přihlášeni k účtu <ph name="USER_EMAIL" />.}many{Tyto karty a jejich fakturační adresy se uloží. Budete je moci používat, když budete přihlášeni k účtu <ph name="USER_EMAIL" />.}other{Tyto karty a jejich fakturační adresy se uloží. Budete je moci používat, když budete přihlášeni k účtu <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">V tuto chvíli se nám s vašimi rodiči nepodařilo spojit. Zkuste to prosím znovu.</translation>
<translation id="8025119109950072390">Útočníci na tomto webu vás mohou podvodem přimět k nebezpečnému chování, jako je instalace softwaru nebo vyzrazení osobních údajů (například hesel, telefonních čísel nebo platebních karet).</translation>
<translation id="8034522405403831421">Stránka je v jazyce <ph name="SOURCE_LANGUAGE" />. Chcete ji přeložit do jazyka <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1100,6 +1116,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8041940743680923270">Použít výchozí globální hodnotu (Dotázat se)</translation>
<translation id="8042918947222776840">Vybrat způsob vyzvednutí</translation>
<translation id="8057711352706143257">Software <ph name="SOFTWARE_NAME" /> není nakonfigurován správně. Tento problém lze obvykle vyřešit odinstalováním softwaru <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Ve vašem zařízení byly nastaveny tyto zásady:</translation>
<translation id="8078141288243656252">Když je dokument otočený, nelze do něj přidávat značky a poznámky</translation>
<translation id="8079031581361219619">Načíst web znovu?</translation>
<translation id="8088680233425245692">Zobrazení článku se nezdařilo.</translation>
@@ -1150,6 +1167,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8363502534493474904">Vypnout režim Letadlo</translation>
<translation id="8364627913115013041">Nenastaveno.</translation>
<translation id="8368476060205742148">Služby Google Play</translation>
+<translation id="8371889962595521444">Vlastní kořenové certifikáty</translation>
<translation id="8380941800586852976">Nebezpečné</translation>
<translation id="8381674639488873545">Může se jednat o jednorázové nebo opakované poplatky, které nemusejí být jasně patrné. <ph name="BEGIN_LINK" />Přesto zobrazit<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Zde se zobrazí nedávno navštívené záložky</translation>
@@ -1159,6 +1177,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8416694386774425977">Konfigurace sítě je neplatná a nelze ji importovat.
Další podrobnosti:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Zařízení spravuje organizace <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Změnit</translation>
<translation id="8428213095426709021">Nastavení</translation>
@@ -1220,6 +1239,7 @@ Další podrobnosti:
<translation id="8932102934695377596">Vaše hodiny se zpožďují</translation>
<translation id="893332455753468063">Přidání jména</translation>
<translation id="8938939909778640821">Přijímané kreditní a předplacené karty</translation>
+<translation id="894185898663964645">Váš administrátor nakonfiguroval vlastní kořenové certifikáty, které mu mohou umožnit zobrazit obsah webů, jež navštěvujete.</translation>
<translation id="8943282376843390568">Limetková</translation>
<translation id="8957210676456822347">Autorizace captive portálu</translation>
<translation id="8968766641738584599">Uložit kartu</translation>
diff --git a/chromium/components/strings/components_strings_da.xtb b/chromium/components/strings/components_strings_da.xtb
index 074fa44adb9..fd422d7aa51 100644
--- a/chromium/components/strings/components_strings_da.xtb
+++ b/chromium/components/strings/components_strings_da.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Sider på <ph name="LANGUAGE" /> oversættes ikke.</translation>
<translation id="2053553514270667976">Postnummer</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 forslag}one{# forslag}other{# forslag}}</translation>
+<translation id="2068124040035837596">Din konto administreres af <ph name="ENROLLMENT_DOMAIN" />. Dette betyder, at din administrator kan konfigurere din konto via fjernadgang.</translation>
<translation id="2068663545051464999">Uploadet nedbrudsrapport-id <ph name="CRASH_ID" /> (lokal kontekst: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Fortryd</translation>
<translation id="20817612488360358">Indstillingerne for systemproxy er angivet at blive brugt, men en eksplicit proxykonfiguration er også angivet.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Denne forsendelsesmetode er ikke tilgængelig. Prøv en anden metode.</translation>
<translation id="2396249848217231973">&amp;Fortryd sletning</translation>
<translation id="2413528052993050574">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da sikkerhedscertifikatet muligvis er blevet tilbagekaldt. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
+<translation id="244665789865330679">Din enhed og konto administreres af <ph name="ENROLLMENT_DOMAIN" />. Dette betyder, at din administrator kan konfigurere din enhed og konto via fjernadgang.</translation>
<translation id="2463193859425327265">Skift startside</translation>
<translation id="2463739503403862330">Udfyld</translation>
<translation id="2465655957518002998">Vælg leveringsmetode</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Du har forsøgt at få fat på <ph name="DOMAIN" />, men serverens certifikat er blevet tilbagekaldt af udgiveren. Det betyder, at du bestemt ikke bør have tillid til serverens sikkerhedsoplysninger. Du kommunikerer muligvis med en hacker.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">søgeresultater</translation>
+<translation id="4406972042435603828">Dine administratorer har installeret udvidelser med effektive funktioner.</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Afhentningsadresse</translation>
<translation id="4424024547088906515">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da Chrome ikke har tillid til sikkerhedscertifikatet. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Ingen resultater</translation>
<translation id="4950898438188848926">Knap til faneskift. Tryk på Enter for at skifte til den åbne fane, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Handlinger</translation>
+<translation id="495832697253704892">Udvidelsers rapportering</translation>
<translation id="4958444002117714549">Udvid liste</translation>
<translation id="4974590756084640048">Genaktiver advarsler</translation>
<translation id="4989163558385430922">Se alle</translation>
<translation id="4989809363548539747">Dette plugin understøttes ikke</translation>
+<translation id="4996230189582812866">Rapportering</translation>
<translation id="5002932099480077015">Hvis denne indstilling er slået til, gemmer Chrome en kopi af dit kort på denne enhed for at gøre det hurtigere at udfylde formularer.</translation>
<translation id="5014174725590676422">Skærmen for førstegangsbrug af Google Assistent i Chrome vises</translation>
<translation id="5015510746216210676">Maskinnavn:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Stat</translation>
<translation id="5094747076828555589">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da Chromium ikke har tillid til sikkerhedscertifikatet. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
<translation id="5095208057601539847">Provins</translation>
+<translation id="5098222253617183465">Din enhed administreres af <ph name="ENROLLMENT_DOMAIN" />, og din konto administreres af <ph name="ACCOUNT_DOMAIN" />. Dette betyder, at dine administratorer kan konfigurere din enhed og konto via fjernadgang.</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5128122789703661928">Sessionen med dette navn kan ikke slettes.</translation>
<translation id="5135404736266831032">Administrer adresser...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Maskine</translation>
<translation id="5179510805599951267">Ikke på <ph name="ORIGINAL_LANGUAGE" />? Rapporter denne fejl</translation>
<translation id="5190835502935405962">Bogmærkelinje</translation>
+<translation id="5200263511887412697">rapportér en liste over enhedsbrugere, der har logget ind for nylig</translation>
<translation id="5201306358585911203">En integreret side på denne side siger</translation>
<translation id="5205222826937269299">Navn påkrævet</translation>
<translation id="5215116848420601511">Betalingsmetoder og adresser, der bruger Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Der kan ikke oprettes forbindelse til dette website</translation>
<translation id="5869522115854928033">Gemte adgangskoder</translation>
<translation id="5887400589839399685">Kortet er gemt</translation>
+<translation id="5893718151540690985">rapportér en liste over netværksgrænseflader med deres typer og hardwareadresser</translation>
<translation id="5893752035575986141">Kreditkort accepteres.</translation>
<translation id="5901630391730855834">Gul</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synkroniseret)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Rediger kontaktoplysninger</translation>
<translation id="5967867314010545767">Fjern fra historik</translation>
<translation id="5975083100439434680">Zoom ud</translation>
+<translation id="5977489021191000276">Din enhed administreres ikke af en administrator.</translation>
<translation id="5977976211062815271">På denne enhed</translation>
<translation id="598637245381783098">Betalingsappen kan ikke åbnes</translation>
<translation id="5989320800837274978">Der er hverken angivet faste proxyservere eller en .pac-scriptwebadresse.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Hackere på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kan installere vildledende apps, der foregiver at være noget andet, eller som indsamler data, der kan anvendes til at overvåge dig. <ph name="BEGIN_LEARN_MORE_LINK" />Få flere oplysninger<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synkroniseret)</translation>
<translation id="6027201098523975773">Angiv et navn</translation>
+<translation id="6033927989869462158">rapportér hardwarestatistik såsom CPU-/RAM-forbrug</translation>
<translation id="6034000775414344507">Lysegrå</translation>
<translation id="6039846035001940113">Kontakt ejeren af websitet, hvis problemet fortsætter.</translation>
<translation id="6040143037577758943">Luk</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Brugeragent</translation>
<translation id="6903319715792422884">Hjælp med at forbedre Beskyttet browsing ved at sende nogle <ph name="BEGIN_WHITEPAPER_LINK" />systemoplysninger og noget sideindhold<ph name="END_WHITEPAPER_LINK" /> til Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Bruger:</translation>
+<translation id="6934672428414710184">Dette navn er fra din Google-konto</translation>
+<translation id="6939583532829045966">Din enhed administreres af <ph name="ENROLLMENT_DOMAIN" />. Dette betyder, at din administrator kan konfigurere din enhed via fjernadgang.</translation>
<translation id="6944692733090228304">Du indtastede din adgangskode på et website, der ikke administreres af <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Du kan beskytte din konto ved at undgå at bruge din adgangskode i andre apps og på andre websites.</translation>
<translation id="6945221475159498467">Vælg</translation>
<translation id="6948701128805548767">Vælg en adresse for at se afhentningsmetoder og -krav</translation>
@@ -992,6 +1004,7 @@ Yderligere oplysninger:
&lt;li&gt;Klik på &lt;strong&gt;Anvend&lt;/strong&gt;, og klik derefter på &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Gå til &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Hjælp til Chrome&lt;/a&gt; for at se, hvordan du permanent fjerner softwaren fra din computer
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Administration af <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Administrer adgangskoder…</translation>
<translation id="7419106976560586862">Profilsti</translation>
<translation id="7437289804838430631">Tilføj kontaktoplysninger</translation>
@@ -1000,10 +1013,12 @@ Yderligere oplysninger:
<translation id="7442725080345379071">Lys orange</translation>
<translation id="7444046173054089907">Dette website er blokeret</translation>
<translation id="7445762425076701745">Identiteten på den server, som du er tilknyttet, kan ikke bekræftes. Du er tilknyttet en server via et navn, der kun er gyldigt i dit netværk, og som en ekstern certifikatautoritet derfor ikke har mulighed for at bekræfte ejerskabet på. Da enkelte certifikatautoriteter alligevel udsteder certifikater for disse navne, kan vi på ingen måde sikre, at du er tilknyttet det tilsigtede website og ikke til en forbryder.</translation>
+<translation id="7449109375006139765">send systemlogfiler til administrationsserveren</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Få flere oplysninger<ph name="END_LINK" /> om dette problem.</translation>
<translation id="7455133967321480974">Brug global standard (bloker)</translation>
<translation id="7460618730930299168">Screeningen stemmer ikke overens med det, du har valgt. Vil du fortsætte?</translation>
<translation id="7473891865547856676">Nej tak</translation>
+<translation id="7475525192983021547">rapportér tidsperioder, hvor en bruger er aktiv på enheden</translation>
<translation id="7481312909269577407">Frem</translation>
<translation id="7485870689360869515">Der blev ikke fundet nogen data.</translation>
<translation id="7508255263130623398">Det returnerede enheds-id for politikken er tomt eller stemmer ikke overens med det nuværende enheds-id</translation>
@@ -1096,6 +1111,7 @@ Yderligere oplysninger:
<translation id="7995512525968007366">Ikke angivet</translation>
<translation id="800218591365569300">Prøv at lukke andre faner eller programmer for at frigøre hukommelse.</translation>
<translation id="8009225694047762179">Administrer adgangskoder</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Kortet og faktureringsadressen gemmes. Du kan bruge dem, når du er logget ind på <ph name="USER_EMAIL" />.}one{Kortet og faktureringsadressen gemmes. Du kan bruge dem, når du er logget ind på <ph name="USER_EMAIL" />.}other{Kortene og faktureringsadresserne gemmes. Du kan bruge dem, når du er logget ind på <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Vi kan ikke få kontakt til dine forældre på nuværende tidspunkt. Prøv igen.</translation>
<translation id="8025119109950072390">Hackere på dette website kan narre dig til at gøre noget farligt, såsom at installere software eller afsløre dine personlige oplysninger (f.eks. adgangskoder, telefonnumre eller kreditkort).</translation>
<translation id="8034522405403831421">Denne side er på <ph name="SOURCE_LANGUAGE" />. Vil du oversætte den til <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Yderligere oplysninger:
<translation id="8041940743680923270">Brug global standard (spørg)</translation>
<translation id="8042918947222776840">Vælg afhentningsmetode</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" er ikke konfigureret korrekt. Problemet kan normalt løses ved at afinstallere "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Din enhed er konfigureret til:</translation>
<translation id="8078141288243656252">Der kan ikke annoteres ved rotering</translation>
<translation id="8079031581361219619">Vil du genindlæse websitet?</translation>
<translation id="8088680233425245692">Artiklen kunne ikke vises.</translation>
@@ -1156,6 +1173,7 @@ Yderligere oplysninger:
<translation id="8363502534493474904">Deaktivere flytilstand</translation>
<translation id="8364627913115013041">Ikke angivet.</translation>
<translation id="8368476060205742148">Google Play-tjenester</translation>
+<translation id="8371889962595521444">Tilpassede rodcertifikater</translation>
<translation id="8380941800586852976">Farlig</translation>
<translation id="8381674639488873545">Disse debiteringer kan være enkeltstående eller gentagne og fremgår muligvis ikke tydeligt. <ph name="BEGIN_LINK" />Vis alligevel<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">De bogmærker, du har besøgt for nylig, vises her</translation>
@@ -1165,6 +1183,7 @@ Yderligere oplysninger:
<translation id="8416694386774425977">Netværkskonfigurationen er ugyldig og kunne ikke importeres.
Yderligere oplysninger:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Enheden administreres af <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Skift</translation>
<translation id="8428213095426709021">Indstillinger</translation>
@@ -1226,6 +1245,7 @@ Yderligere oplysninger:
<translation id="8932102934695377596">Dit ur er bagud</translation>
<translation id="893332455753468063">Tilføj navn</translation>
<translation id="8938939909778640821">Accepterede betalingskort</translation>
+<translation id="894185898663964645">Din administrator har konfigureret tilpassede rodcertifikater, hvilket kan give administratoren mulighed for at se indholdet på de websites, du besøger.</translation>
<translation id="8943282376843390568">Limegrøn</translation>
<translation id="8957210676456822347">Godkendelse af captive portal</translation>
<translation id="8968766641738584599">Gem kort</translation>
diff --git a/chromium/components/strings/components_strings_de.xtb b/chromium/components/strings/components_strings_de.xtb
index e8f7e1b9faa..064a0a3f7d2 100644
--- a/chromium/components/strings/components_strings_de.xtb
+++ b/chromium/components/strings/components_strings_de.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Seiten auf <ph name="LANGUAGE" /> werden nicht übersetzt.</translation>
<translation id="2053553514270667976">Postleitzahl</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 Vorschlag}other{# Vorschläge}}</translation>
+<translation id="2068124040035837596">Ihr Konto wird durch <ph name="ENROLLMENT_DOMAIN" /> verwaltet. Das bedeutet, dass der Administrator Ihr Konto per Remotezugriff konfigurieren kann.</translation>
<translation id="2068663545051464999">ID des hochgeladenen Absturzberichts: <ph name="CRASH_ID" /> (lokaler Kontext: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Rückgängig machen</translation>
<translation id="20817612488360358">Die System-Proxy-Einstellungen sind zur Verwendung angegeben, gleichzeitig wurde aber auch eine explizite Proxy-Konfiguration festgelegt.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Diese Versandart ist nicht verfügbar. Bitte wählen Sie eine andere aus.</translation>
<translation id="2396249848217231973">&amp;Löschen rückgängig machen</translation>
<translation id="2413528052993050574">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat wurde möglicherweise widerrufen. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
+<translation id="244665789865330679">Ihr Gerät und Ihr Konto werden durch <ph name="ENROLLMENT_DOMAIN" /> verwaltet. Dies bedeutet, dass der Administrator Ihr Gerät und Ihr Konto per Remotezugriff konfigurieren kann.</translation>
<translation id="2463193859425327265">Startseite ändern</translation>
<translation id="2463739503403862330">Ausfüllen</translation>
<translation id="2465655957518002998">Lieferoption auswählen</translation>
@@ -381,11 +383,11 @@
<translation id="3338095232262050444">Sicher</translation>
<translation id="3345135638360864351">Ihre Zugriffsanfrage für diese Website konnte nicht an <ph name="NAME" /> gesendet werden. Bitte versuchen Sie es erneut.</translation>
<translation id="3355823806454867987">Proxy-Einstellungen ändern...</translation>
-<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />speichert die folgenden Informationen nicht<ph name="END_EMPHASIS" />:
+<translation id="3361596688432910856">Chrome <ph name="BEGIN_EMPHASIS" />speichert die folgenden Daten nicht<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
<ph name="LIST_ITEM" />Ihren Browserverlauf
<ph name="LIST_ITEM" />Cookies und Websitedaten
- <ph name="LIST_ITEM" />In Formulare eingegebene Informationen
+ <ph name="LIST_ITEM" />In Formulare eingegebene Daten
<ph name="END_LIST" /></translation>
<translation id="3366477098757335611">Karten ansehen</translation>
<translation id="3369192424181595722">Fehler bei der Uhrzeit</translation>
@@ -559,6 +561,7 @@
<translation id="4377125064752653719">Sie haben versucht, auf <ph name="DOMAIN" /> zuzugreifen, das vom Server übermittelte Zertifikat wurde jedoch vom entsprechenden Aussteller widerrufen. Das bedeutet, dass die vom Server übermittelten Sicherheitsinformationen nicht vertrauenswürdig sind. Möglicherweise kommunizieren Sie mit einem Hacker.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">Suchergebnisse</translation>
+<translation id="4406972042435603828">Ihre Administratoren haben Erweiterungen mit leistungsstarken Funktionen installiert.</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Abholadresse</translation>
<translation id="4424024547088906515">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat wird von Chrome als nicht vertrauenswürdig eingestuft. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
@@ -630,10 +633,12 @@
<translation id="4943872375798546930">Keine Ergebnisse</translation>
<translation id="4950898438188848926">Schaltfläche zum Wechseln von Tabs, Eingabetaste drücken, um zum offenen Tab "<ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />" zu wechseln</translation>
<translation id="495170559598752135">Aktionen</translation>
+<translation id="495832697253704892">Berichte zu Erweiterungen</translation>
<translation id="4958444002117714549">Liste einblenden</translation>
<translation id="4974590756084640048">Warnmeldungen wieder aktivieren</translation>
<translation id="4989163558385430922">Alle ansehen</translation>
<translation id="4989809363548539747">Dieses Plug-in wird nicht unterstützt</translation>
+<translation id="4996230189582812866">Berichte</translation>
<translation id="5002932099480077015">Wenn diese Funktion aktiviert ist, speichert Chrome eine Kopie Ihrer Karte auf diesem Gerät, um ein Ausfüllen von Formularen zu beschleunigen.</translation>
<translation id="5014174725590676422">Bildschirm für die erste Ausführung von Google Assistant für Chrome wird angezeigt</translation>
<translation id="5015510746216210676">Computername:</translation>
@@ -654,6 +659,7 @@
<translation id="5089810972385038852">Bundesstaat</translation>
<translation id="5094747076828555589">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat wird von Chromium als nicht vertrauenswürdig eingestuft. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
<translation id="5095208057601539847">Provinz</translation>
+<translation id="5098222253617183465">Ihr Gerät wird durch <ph name="ENROLLMENT_DOMAIN" /> und Ihr Konto durch <ph name="ACCOUNT_DOMAIN" /> verwaltet. Das bedeutet, dass die Administratoren Ihr Gerät und Ihr Konto per Remotezugriff konfigurieren können.</translation>
<translation id="5115563688576182185">(64-Bit)</translation>
<translation id="5128122789703661928">Die Sitzung mit diesem Namen kann nicht gelöscht werden.</translation>
<translation id="5135404736266831032">Adressen verwalten…</translation>
@@ -666,6 +672,7 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Nicht auf <ph name="ORIGINAL_LANGUAGE" />? Diesen Fehler melden</translation>
<translation id="5190835502935405962">Lesezeichenleiste</translation>
+<translation id="5200263511887412697">erstellt eine Liste der Gerätenutzer, die sich kürzlich angemeldet haben</translation>
<translation id="5201306358585911203">Auf einer in dieser Seite eingebetteten Seite wird Folgendes angezeigt</translation>
<translation id="5205222826937269299">Name erforderlich</translation>
<translation id="5215116848420601511">Bei Google Pay gespeicherte Zahlungsmethoden und Adressen</translation>
@@ -767,6 +774,7 @@
<translation id="5869405914158311789">Die Website ist nicht erreichbar</translation>
<translation id="5869522115854928033">Gespeicherte Passwörter</translation>
<translation id="5887400589839399685">Karte gespeichert</translation>
+<translation id="5893718151540690985">meldet eine Liste der Netzwerkschnittstellen mit deren Typen und Hardwareadressen</translation>
<translation id="5893752035575986141">Kreditkarten werden akzeptiert.</translation>
<translation id="5901630391730855834">Gelb</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synchronisiert)</translation>
@@ -780,6 +788,7 @@
<translation id="5967592137238574583">Kontaktdaten bearbeiten</translation>
<translation id="5967867314010545767">Aus Verlauf entfernen</translation>
<translation id="5975083100439434680">Verkleinern</translation>
+<translation id="5977489021191000276">Ihr Gerät wird nicht von einem Administrator verwaltet.</translation>
<translation id="5977976211062815271">Auf diesem Gerät</translation>
<translation id="598637245381783098">Fehler beim Öffnen der Zahlungs-App</translation>
<translation id="5989320800837274978">Weder feste Proxyserver noch eine PAC-Skript-URL sind festgelegt.</translation>
@@ -791,6 +800,7 @@
<translation id="6017850046339264347">Angreifer auf der Website <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> könnten betrügerische Apps installieren, die scheinbar einem anderen Zweck dienen oder Daten erfassen, um Sie auszuspionieren. <ph name="BEGIN_LEARN_MORE_LINK" />Weitere Informationen<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synchronisiert)</translation>
<translation id="6027201098523975773">Geben Sie einen Namen ein</translation>
+<translation id="6033927989869462158">meldet Hardwarestatistiken wie die CPU/RAM-Nutzung</translation>
<translation id="6034000775414344507">Hellgrau</translation>
<translation id="6039846035001940113">Falls das Problem weiterhin besteht, wenden Sie sich an den Inhaber der Website.</translation>
<translation id="6040143037577758943">Schließen</translation>
@@ -903,6 +913,8 @@
<translation id="6897140037006041989">User-Agent</translation>
<translation id="6903319715792422884">Sie können uns dabei helfen, Safe Browsing weiter zu verbessern, <ph name="BEGIN_WHITEPAPER_LINK" />indem Sie einige Systeminformationen und Seiteninhalte an Google senden<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Nutzer:</translation>
+<translation id="6934672428414710184">Dieser Name stammt aus Ihrem Google-Konto</translation>
+<translation id="6939583532829045966">Ihr Gerät wird durch <ph name="ENROLLMENT_DOMAIN" /> verwaltet. Dies bedeutet, dass der Administrator Ihr Gerät per Remotezugriff konfigurieren kann.</translation>
<translation id="6944692733090228304">Sie haben Ihr Passwort auf einer Website eingegeben, die nicht von <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> verwaltet wird. Zum Schutz Ihres Kontos sollten Sie das Passwort nicht für andere Apps und Websites verwenden.</translation>
<translation id="6945221475159498467">Auswählen</translation>
<translation id="6948701128805548767">Wählen Sie eine Adresse aus, um Abholoptionen und -anforderungen zu sehen</translation>
@@ -990,6 +1002,7 @@ Weitere Details:
&lt;li&gt;Klicken Sie auf &lt;strong&gt;Übernehmen&lt;/strong&gt; und dann auf &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;In der &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome-Hilfe&lt;/a&gt; finden Sie eine Anleitung dazu, wie Sie die Software von Ihrem Computer entfernen.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" />-Verwaltung</translation>
<translation id="7416351320495623771">Passwörter verwalten…</translation>
<translation id="7419106976560586862">Profilpfad</translation>
<translation id="7437289804838430631">Kontaktdaten hinzufügen</translation>
@@ -998,10 +1011,12 @@ Weitere Details:
<translation id="7442725080345379071">Helles Orange</translation>
<translation id="7444046173054089907">Diese Website ist blockiert</translation>
<translation id="7445762425076701745">Die Identität des Servers, mit dem Sie verbunden sind, kann nicht vollständig überprüft werden. Sie sind mit einem Server verbunden, dessen Name nur innerhalb Ihres Netzwerks gültig ist und dessen Eigentümerschaft von einer externen Zertifizierungsstelle nicht überprüft werden kann. Da einige Zertifizierungsstellen ungeachtet dessen dennoch Zertifikate für diese Namen ausstellen, gibt es keine Möglichkeit, sicherzustellen, dass Sie mit der gewünschten Website und nicht mit einem Angreifer verbunden sind.</translation>
+<translation id="7449109375006139765">Systemprotokolle an den Verwaltungsserver senden</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Weitere Informationen<ph name="END_LINK" /> zu diesem Problem.</translation>
<translation id="7455133967321480974">Globalen Standard verwenden (Blockieren)</translation>
<translation id="7460618730930299168">Die Filmvorführung entspricht nicht Ihrer Auswahl. Möchten Sie fortfahren?</translation>
<translation id="7473891865547856676">Nein danke</translation>
+<translation id="7475525192983021547">meldet die Zeiträume, in denen ein Nutzer auf dem Gerät aktiv ist</translation>
<translation id="7481312909269577407">Vorwärts</translation>
<translation id="7485870689360869515">Keine Daten gefunden</translation>
<translation id="7508255263130623398">Zurückgegebene Geräte-ID der Richtlinie ist leer oder entspricht nicht der aktuellen Geräte-ID</translation>
@@ -1094,6 +1109,7 @@ Weitere Details:
<translation id="7995512525968007366">Nicht angegeben</translation>
<translation id="800218591365569300">Versuchen Sie, andere Tabs oder Programme zu schließen, um Speicher freizugeben.</translation>
<translation id="8009225694047762179">Passwort verwalten</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Diese Karte und die entsprechende Rechnungsadresse werden gespeichert. Sie können sie nutzen, wenn Sie in <ph name="USER_EMAIL" /> angemeldet sind.}other{Diese Karten und die entsprechenden Rechnungsadressen werden gespeichert. Sie können sie nutzen, wenn Sie in <ph name="USER_EMAIL" /> angemeldet sind.}}</translation>
<translation id="8012647001091218357">Wir können deine Eltern momentan nicht erreichen. Bitte versuche es später noch einmal.</translation>
<translation id="8025119109950072390">Unbefugte Dritte auf dieser Website versuchen unter Umständen auf betrügerische Weise, Sie zur Installation von Software zu bewegen oder Ihnen personenbezogene Daten zu entlocken, zum Beispiel Passwörter, Telefonnummern oder Kreditkartendaten.</translation>
<translation id="8034522405403831421">Diese Seite ist auf <ph name="SOURCE_LANGUAGE" />. In folgende Sprache übersetzen: <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1104,6 +1120,7 @@ Weitere Details:
<translation id="8041940743680923270">Globalen Standard verwenden (Fragen)</translation>
<translation id="8042918947222776840">Abholoption auswählen</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ist nicht ordnungsgemäß konfiguriert. Durch die Deinstallation von "<ph name="SOFTWARE_NAME" />" sollte das Problem behoben werden. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Ihr Gerät wurde so konfiguriert:</translation>
<translation id="8078141288243656252">Anmerkungen bei gedrehtem Dokument nicht möglich</translation>
<translation id="8079031581361219619">Website neu laden?</translation>
<translation id="8088680233425245692">Der Artikel kann nicht angezeigt werden.</translation>
@@ -1154,6 +1171,7 @@ Weitere Details:
<translation id="8363502534493474904">Flugmodus ausschalten</translation>
<translation id="8364627913115013041">Nicht eingerichtet</translation>
<translation id="8368476060205742148">Google Play-Dienste</translation>
+<translation id="8371889962595521444">Benutzerdefinierte Root-Zertifikate</translation>
<translation id="8380941800586852976">Schädlich</translation>
<translation id="8381674639488873545">Diese Kosten können einmalig oder wiederkehrend sein und sind vielleicht nicht klar zu erkennen. <ph name="BEGIN_LINK" />Trotzdem anzeigen<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Hier werden Ihre kürzlich aufgerufenen Lesezeichen angezeigt</translation>
@@ -1163,6 +1181,7 @@ Weitere Details:
<translation id="8416694386774425977">Die Netzwerkkonfiguration ist ungültig und konnte nicht importiert werden.
Weitere Details:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Gerät verwaltet durch <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" />, <ph name="SECOND_LABEL" />, <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Ändern</translation>
<translation id="8428213095426709021">Einstellungen</translation>
@@ -1224,6 +1243,7 @@ Weitere Details:
<translation id="8932102934695377596">Ihre Uhr geht nach</translation>
<translation id="893332455753468063">Namen hinzufügen</translation>
<translation id="8938939909778640821">Akzeptierte Kredit- und Prepaidkarten</translation>
+<translation id="894185898663964645">Ihr Administrator hat benutzerdefinierte Root-Zertifikate konfiguriert, mit denen er unter Umständen die Inhalte der von Ihnen besuchten Websites sehen kann.</translation>
<translation id="8943282376843390568">Limone</translation>
<translation id="8957210676456822347">Erfassungsportal-Autorisierung</translation>
<translation id="8968766641738584599">Karte speichern</translation>
diff --git a/chromium/components/strings/components_strings_el.xtb b/chromium/components/strings/components_strings_el.xtb
index 4d894f7d45b..1c9ecd7487c 100644
--- a/chromium/components/strings/components_strings_el.xtb
+++ b/chromium/components/strings/components_strings_el.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Οι σελίδες στα <ph name="LANGUAGE" /> δεν θα μεταφράζονται.</translation>
<translation id="2053553514270667976">Ταχυδρομικός κώδικας</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 πρόταση}other{# προτάσεις}}</translation>
+<translation id="2068124040035837596">Η διαχείριση του λογαριασμού σας γίνεται από τον τομέα <ph name="ENROLLMENT_DOMAIN" />. Αυτό σημαίνει ότι ο διαχειριστής σας μπορεί να διαμορφώνει απομακρυσμένα τον λογαριασμό σας.</translation>
<translation id="2068663545051464999">Αναγνωριστικό αναφοράς σφάλματος που ανέβηκε <ph name="CRASH_ID" /> (Τοπικό περιβάλλον: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Αναίρεση</translation>
<translation id="20817612488360358">Οι ρυθμίσεις διακομιστή μεσολάβησης του συστήματος έχουν οριστεί για να χρησιμοποιηθούν, αλλά καθορίζεται επίσης μια ρητή διαμόρφωση του διακομιστή μεσολάβησης.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Αυτός ο τρόπος αποστολής δεν είναι διαθέσιμος. Δοκιμάστε έναν άλλο τρόπο.</translation>
<translation id="2396249848217231973">&amp;Αναίρεση διαγραφής</translation>
<translation id="2413528052993050574">Ο διακομιστής δεν κατάφερε να αποδείξει ότι είναι <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας του μπορεί να έχει ανακληθεί. Αυτό μπορεί να οφείλεται σε λανθασμένη ρύθμιση ή σε κάποιον τρίτο που επιτίθεται στη σύνδεσή σας.</translation>
+<translation id="244665789865330679">Η διαχείριση της συσκευής και του λογαριασμού γίνεται από τον τομέα <ph name="ENROLLMENT_DOMAIN" />. Αυτό σημαίνει ότι ο διαχειριστής σας μπορεί να διαμορφώσει απομακρυσμένα τη συσκευή και τον λογαριασμό σας.</translation>
<translation id="2463193859425327265">Αλλαγή αρχικής σελίδας</translation>
<translation id="2463739503403862330">Συμπλήρωση</translation>
<translation id="2465655957518002998">Επιλογή τρόπου παράδοσης</translation>
@@ -562,6 +564,7 @@
<translation id="4377125064752653719">Προσπαθήσατε να μεταβείτε στον τομέα <ph name="DOMAIN" />, όμως το πιστοποιητικό που παρουσιάστηκε από το διακομιστή ανακλήθηκε από τον εκδότη του. Αυτό σημαίνει ότι τα διαπιστευτήρια ασφαλείας που παρουσιάστηκαν από το διακομιστή δεν πρέπει σε καμία περίπτωση να θεωρηθούν αξιόπιστα. Ενδέχεται να επικοινωνείτε με κάποιον εισβολέα.</translation>
<translation id="4378154925671717803">Τηλέφωνο</translation>
<translation id="4406896451731180161">αποτελέσματα αναζήτησης</translation>
+<translation id="4406972042435603828">Οι διαχειριστές σας έχουν εγκαταστήσει επεκτάσεις με ισχυρές δυνατότητες.</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Διεύθυνση παραλαβής</translation>
<translation id="4424024547088906515">Ο διακομιστής δεν μπόρεσε να αποδείξει ότι είναι <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας του δεν θεωρείται έμπιστο από τον Chrome. Αυτό μπορεί να οφείλεται σε λανθασμένη ρύθμιση ή σε κάποιον τρίτο που επιτίθεται στη σύνδεσή σας.</translation>
@@ -633,10 +636,12 @@
<translation id="4943872375798546930">Δεν υπάρχουν αποτελέσματα</translation>
<translation id="4950898438188848926">Κουμπί εναλλαγής καρτέλας, πατήστε Enter για μετάβαση στην ανοιχτή καρτέλα, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Ενέργειες</translation>
+<translation id="495832697253704892">Επέκταση αναφοράς</translation>
<translation id="4958444002117714549">Ανάπτυξη λίστας</translation>
<translation id="4974590756084640048">Επανενεργοποίηση προειδοποιήσεων</translation>
<translation id="4989163558385430922">Εμφάνιση όλων</translation>
<translation id="4989809363548539747">Αυτή η προσθήκη δεν υποστηρίζεται</translation>
+<translation id="4996230189582812866">Αναφορές</translation>
<translation id="5002932099480077015">Εάν ενεργοποιηθεί, το Chrome θα αποθηκεύσει ένα αντίγραφο της κάρτας σας σε αυτήν τη συσκευή για ταχύτερη συμπλήρωση φορμών.</translation>
<translation id="5014174725590676422">Εμφανίζεται ο Βοηθός Google στην η οθόνη πρώτης εκτέλεσης του Chrome</translation>
<translation id="5015510746216210676">Όνομα συσκευής:</translation>
@@ -657,6 +662,7 @@
<translation id="5089810972385038852">Πολιτεία</translation>
<translation id="5094747076828555589">Ο διακομιστής δεν μπορεί να αποδείξει ότι είναι το <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας του δεν θεωρείται έμπιστο από το Chromium. Αυτό μπορεί να οφείλεται σε λανθασμένη ρύθμιση ή σε κάποιον τρίτο που επιτίθεται στη σύνδεσή σας.</translation>
<translation id="5095208057601539847">Επαρχία</translation>
+<translation id="5098222253617183465">Η διαχείριση της συσκευής γίνεται από <ph name="ENROLLMENT_DOMAIN" /> και η διαχείριση του λογαριασμού σας γίνεται από <ph name="ACCOUNT_DOMAIN" />. Αυτό σημαίνει ότι οι διαχειριστές σας μπορούν να διαμορφώσουν απομακρυσμένα τη συσκευή και τον λογαριασμό σας.</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5128122789703661928">Η περίοδος σύνδεσης με αυτό το όνομα δεν είναι έγκυρη για διαγραφή.</translation>
<translation id="5135404736266831032">Διαχείριση διευθύνσεων…</translation>
@@ -669,6 +675,7 @@
<translation id="5172758083709347301">Υπολογιστής</translation>
<translation id="5179510805599951267">Δεν είναι στα <ph name="ORIGINAL_LANGUAGE" />; Αναφέρετε αυτό το σφάλμα</translation>
<translation id="5190835502935405962">Γραμμή σελιδοδεικτών</translation>
+<translation id="5200263511887412697">αναφορά λίστας συσκευών που χρησιμοποίησαν πρόσφατα οι χρήστες για να συνδεθούν</translation>
<translation id="5201306358585911203">Μια ενσωματωμένη σελίδα σε αυτήν τη σελίδα λέει</translation>
<translation id="5205222826937269299">Απαιτείται όνομα</translation>
<translation id="5215116848420601511">Τρόποι πληρωμής και διευθύνσεις που χρησιμοποιούν το Google Pay</translation>
@@ -770,6 +777,7 @@
<translation id="5869405914158311789">Δεν είναι δυνατή η πρόσβαση σε αυτόν τον ιστότοπο</translation>
<translation id="5869522115854928033">Αποθηκευμένοι κωδικοί πρόσβασης</translation>
<translation id="5887400589839399685">Η κάρτα αποθηκεύτηκε</translation>
+<translation id="5893718151540690985">αναφορά λίστας των διεπαφών δικτύου με τον τύπο τους και τις διευθύνσεις υλικού</translation>
<translation id="5893752035575986141">Οι πιστωτικές κάρτες γίνονται δεκτές.</translation>
<translation id="5901630391730855834">Κίτρινο</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (συγχρονισμένο)</translation>
@@ -783,6 +791,7 @@
<translation id="5967592137238574583">Επεξεργασία στοιχείων επικοινωνίας</translation>
<translation id="5967867314010545767">Κατάργηση από το ιστορικό</translation>
<translation id="5975083100439434680">Σμίκρυνση</translation>
+<translation id="5977489021191000276">Η διαχείριση της συσκευής σας δεν γίνεται από έναν διαχειριστή.</translation>
<translation id="5977976211062815271">Σε αυτήν τη συσκευή</translation>
<translation id="598637245381783098">Δεν είναι δυνατό το άνοιγμα της εφαρμογής πληρωμής</translation>
<translation id="5989320800837274978">Δεν προσδιορίζονται ούτε οι σταθεροί διακομιστές μεσολάβησης ούτε μια διεύθυνση URL σεναρίου .pac.</translation>
@@ -794,6 +803,7 @@
<translation id="6017850046339264347">Οι εισβολείς στον ιστότοπο <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> θα μπορούσαν να εγκαταστήσουν παραπλανητικές εφαρμογές που προσποιούνται ότι είναι κάτι άλλο ή συλλέγουν δεδομένα τα οποία μπορεί να χρησιμοποιηθούν για την παρακολούθησή σας. <ph name="BEGIN_LEARN_MORE_LINK" />Μάθετε περισσότερα<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (συγχρονισμένο)</translation>
<translation id="6027201098523975773">Εισαγωγή ονόματος</translation>
+<translation id="6033927989869462158">αναφορά στατιστικών στοιχείων εξοπλισμού όπως της χρήσης CPU/RAM</translation>
<translation id="6034000775414344507">Ανοιχτό γκρι</translation>
<translation id="6039846035001940113">Εάν το πρόβλημα παραμείνει, επικοινωνήστε με τον κάτοχο του ιστοτόπου.</translation>
<translation id="6040143037577758943">Κλείσιμο</translation>
@@ -906,6 +916,8 @@
<translation id="6897140037006041989">Παράγοντας χρήστη</translation>
<translation id="6903319715792422884">Συμβάλετε στη βελτίωση της Ασφαλούς περιήγησης στέλνοντας ορισμένες <ph name="BEGIN_WHITEPAPER_LINK" />πληροφορίες συστήματος και περιεχόμενο σελίδων<ph name="END_WHITEPAPER_LINK" /> στην Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Χρήστης</translation>
+<translation id="6934672428414710184">Αυτό το όνομα προέρχεται από τον Λογαριασμό σας Google</translation>
+<translation id="6939583532829045966">Η διαχείριση της συσκευής γίνεται από τον τομέα <ph name="ENROLLMENT_DOMAIN" />. Αυτό σημαίνει ότι ο διαχειριστής σας μπορεί να διαμορφώσει απομακρυσμένα τη συσκευή σας.</translation>
<translation id="6944692733090228304">Καταχωρίσατε τον κωδικό πρόσβασής σας σε έναν ιστότοπο τον οποίο δεν διαχειρίζεται ο οργανισμός <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Για να προστατεύσετε τον λογαριασμό σας, μην χρησιμοποιήσετε ξανά αυτόν τον κωδικό πρόσβασης σε άλλες εφαρμογές και ιστότοπους.</translation>
<translation id="6945221475159498467">Επιλογή</translation>
<translation id="6948701128805548767">Για να δείτε τρόπους και απαιτήσεις παραλαβής, επιλέξτε μια διεύθυνση</translation>
@@ -993,6 +1005,7 @@
&lt;li&gt;Κάντε κλικ στο κουμπί &lt;strong&gt;Εφαρμογή&lt;/strong&gt; και, έπειτα, στο κουμπί &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Επισκεφτείτε το &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Κέντρο βοήθειας του Chrome&lt;/a&gt;, για να μάθετε πώς μπορείτε να καταργήσετε οριστικά το λογισμικό από τον υπολογιστή σας
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Διαχείριση <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Διαχείριση κωδικών πρόσβασης…</translation>
<translation id="7419106976560586862">Διαδρομή προφίλ</translation>
<translation id="7437289804838430631">Προσθήκη στοιχείων επικοινωνίας</translation>
@@ -1001,10 +1014,12 @@
<translation id="7442725080345379071">Ανοιχτό πορτοκαλί</translation>
<translation id="7444046173054089907">Αυτός ο ιστότοπος είναι αποκλεισμένος</translation>
<translation id="7445762425076701745">Η ταυτότητα του διακομιστή στον οποίο έχετε συνδεθεί δεν μπορεί να επικυρωθεί πλήρως. Είστε συδεδεμένοι σε ένα διακομιστή χρησιμοποιώντας ένα όνομα που είναι έγκυρο μόνο εντός του δικτύου σας, την κατοχή του οποίου δεν έχει τρόπο να επικυρώσει μια εξωτερική αρχή πιστοποίησης. Καθώς ορισμένες αρχές πιστοποιητικών εκδίδουν πιστοποιητικά για αυτά τα ονόματα ούτως ή άλλως, δεν υπάρχει τρόπος να βεβαιωθείτε ότι είστε συνδεδεμένοι στον ιστότοπο που επιθυμείτε και όχι σε έναν εισβολέα.</translation>
+<translation id="7449109375006139765">αποστολή αρχείων καταγραφής συστήματος στον διακομιστή διαχείρισης</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Να μάθετε περισσότερα<ph name="END_LINK" /> σχετικά με αυτό το πρόβλημα.</translation>
<translation id="7455133967321480974">Χρήση καθολικής προεπιλεγμένης ρύθμισης (Αποκλεισμός)</translation>
<translation id="7460618730930299168">Η προβολή είναι διαφορετική από αυτήν που έχετε επιλέξει. Θέλετε να συνεχίσετε;</translation>
<translation id="7473891865547856676">Όχι, ευχαριστώ</translation>
+<translation id="7475525192983021547">αναφορά χρονικών περιόδων στις οποίες ένας χρήστης είναι ενεργός στη συσκευή</translation>
<translation id="7481312909269577407">Προώθηση</translation>
<translation id="7485870689360869515">Δεν βρέθηκαν δεδομένα</translation>
<translation id="7508255263130623398">Η εμφανιζόμενη συσκευή πολιτικής είναι κενή ή δεν αντιστοιχεί στο τρέχον αναγνωριστικό συσκευής</translation>
@@ -1097,6 +1112,7 @@
<translation id="7995512525968007366">Δεν καθορίστηκε</translation>
<translation id="800218591365569300">Δοκιμάστε να κλείσετε τις άλλες καρτέλες ή τα άλλα προγράμματα για να απελευθερώσετε μνήμη.</translation>
<translation id="8009225694047762179">Διαχείριση Κωδικός πρόσβασης</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Αυτή η κάρτα και η διεύθυνση χρέωσής της θα αποθηκευτούν. Θα μπορείτε να τη χρησιμοποιείτε όταν συνδέεστε στον λογαριασμό <ph name="USER_EMAIL" />.}other{Αυτές οι κάρτες και οι διευθύνσεις χρέωσής τους θα αποθηκευτούν. Θα μπορείτε να τις χρησιμοποιείτε όταν συνδέεστε στον λογαριασμό <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Δεν ήταν δυνατή η επικοινωνία με τους γονείς σας αυτήν τη στιγμή. Δοκιμάστε ξανά.</translation>
<translation id="8025119109950072390">Οι εισβολείς σε αυτόν τον ιστότοπο μπορεί να σας ξεγελάσουν και να κάνετε κάτι επικίνδυνο, όπως να εγκαταστήσετε κάποιο λογισμικό ή να αποκαλύψετε προσωπικά σας στοιχεία (για παράδειγμα, κωδικούς πρόσβασης, αριθμούς τηλεφώνου ή πιστωτικές κάρτες).</translation>
<translation id="8034522405403831421">Αυτή η σελίδα είναι στα <ph name="SOURCE_LANGUAGE" />. Μετάφρασή της στα <ph name="TARGET_LANGUAGE" />;</translation>
@@ -1107,6 +1123,7 @@
<translation id="8041940743680923270">Χρήση καθολικής προεπιλεγμένης ρύθμισης (Ερώτηση)</translation>
<translation id="8042918947222776840">Επιλογή τρόπου παραλαβής</translation>
<translation id="8057711352706143257">Το λογισμικό "<ph name="SOFTWARE_NAME" />" δεν έχει διαμορφωθεί σωστά. Το πρόβλημα διορθώνεται συνήθως με την απεγκατάσταση του λογισμικού "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Η συσκευή σας έχει διαμορφωθεί ως εξής:</translation>
<translation id="8078141288243656252">Δεν είναι δυνατός ο σχολιασμός μετά από περιστροφή</translation>
<translation id="8079031581361219619">Να επαναληφθεί η φόρτωση του ιστοτόπου;</translation>
<translation id="8088680233425245692">Αποτυχία προβολής άρθρου.</translation>
@@ -1157,6 +1174,7 @@
<translation id="8363502534493474904">Απενεργοποιήστε τη λειτουργία πτήσης</translation>
<translation id="8364627913115013041">Δεν έχει οριστεί.</translation>
<translation id="8368476060205742148">Υπηρεσίες Google Play</translation>
+<translation id="8371889962595521444">Προσαρμοσμένα πιστοποιητικά ρίζας</translation>
<translation id="8380941800586852976">Επικίνδυνο</translation>
<translation id="8381674639488873545">Αυτές οι χρεώσεις μπορεί να είναι εφάπαξ ή επαναλαμβανόμενες και ίσως να μην είναι εμφανείς.<ph name="BEGIN_LINK" />Εμφάνιση ούτως ή άλλως<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Οι σελιδοδείκτες που επισκεφτήκατε πρόσφατα εμφανίζονται εδώ.</translation>
@@ -1166,6 +1184,7 @@
<translation id="8416694386774425977">Η διαμόρφωση δικτύου είναι μη έγκυρη και δεν ήταν δυνατή η εισαγωγή της.
Πρόσθετες λεπτομέρειες:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Η διαχείριση της συσκευής γίνεται από <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Αλλαγή</translation>
<translation id="8428213095426709021">Ρυθμίσεις</translation>
@@ -1227,6 +1246,7 @@
<translation id="8932102934695377596">Το ρολόι σας πάει πίσω</translation>
<translation id="893332455753468063">Προσθήκη ονόματος</translation>
<translation id="8938939909778640821">Αποδεκτές πιστωτικές και προπληρωμένες κάρτες</translation>
+<translation id="894185898663964645">Ο διαχειριστής σας έχει διαμορφώσει προσαρμοσμένα πιστοποιητικά ρίζας, τα οποία ενδέχεται να επιτρέπουν στον διαχειριστή να βλέπει το περιεχόμενο των ιστοτόπων που επισκέπτεστε.</translation>
<translation id="8943282376843390568">Λάιμ</translation>
<translation id="8957210676456822347">Εξουσιοδότηση πύλης υποδοχής</translation>
<translation id="8968766641738584599">Αποθήκευση κάρτας</translation>
diff --git a/chromium/components/strings/components_strings_en-GB.xtb b/chromium/components/strings/components_strings_en-GB.xtb
index 94fc535f486..05340154b02 100644
--- a/chromium/components/strings/components_strings_en-GB.xtb
+++ b/chromium/components/strings/components_strings_en-GB.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Pages in <ph name="LANGUAGE" /> will not be translated.</translation>
<translation id="2053553514270667976">ZIP code</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestion}other{# suggestions}}</translation>
+<translation id="2068124040035837596">Your account is managed by <ph name="ENROLLMENT_DOMAIN" />. This means that your administrator may remotely configure your account.</translation>
<translation id="2068663545051464999">Uploaded Crash Report ID <ph name="CRASH_ID" /> (Local Context: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Undo</translation>
<translation id="20817612488360358">System proxy settings are set to be used but an explicit proxy configuration is also specified.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">This delivery method isn’t available. Try a different method.</translation>
<translation id="2396249848217231973">&amp;Undo delete</translation>
<translation id="2413528052993050574">This server could not prove that it is <ph name="DOMAIN" />; its security certificate might be revoked. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
+<translation id="244665789865330679">Your device and account is managed by <ph name="ENROLLMENT_DOMAIN" />. This means that your administrator may remotely configure your device and account.</translation>
<translation id="2463193859425327265">Change home page</translation>
<translation id="2463739503403862330">Fill in</translation>
<translation id="2465655957518002998">Choose delivery method</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">You attempted to reach <ph name="DOMAIN" />, but the certificate that the server presented has been revoked by its issuer. This means that the security credentials the server presented absolutely should not be trusted. You may be communicating with an attacker.</translation>
<translation id="4378154925671717803">Phone</translation>
<translation id="4406896451731180161">search results</translation>
+<translation id="4406972042435603828">Your administrators have installed extensions with powerful capabilities.</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Pickup Address</translation>
<translation id="4424024547088906515">This server could not prove that it is <ph name="DOMAIN" />; its security certificate is not trusted by Chrome. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">No results</translation>
<translation id="4950898438188848926">Tab switch button, press Enter to switch to the open tab, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Actions</translation>
+<translation id="495832697253704892">Extension reporting</translation>
<translation id="4958444002117714549">Expand list</translation>
<translation id="4974590756084640048">Re-enable warnings</translation>
<translation id="4989163558385430922">See all</translation>
<translation id="4989809363548539747">This plug-in is not supported</translation>
+<translation id="4996230189582812866">Reporting</translation>
<translation id="5002932099480077015">If enabled, Chrome will store a copy of your card on this device for faster form filling.</translation>
<translation id="5014174725590676422">Google Assistant in Chrome first run screen is shown</translation>
<translation id="5015510746216210676">Machine Name:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">State</translation>
<translation id="5094747076828555589">This server could not prove that it is <ph name="DOMAIN" />; its security certificate is not trusted by Chromium. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
<translation id="5095208057601539847">Province</translation>
+<translation id="5098222253617183465">Your device is managed by <ph name="ENROLLMENT_DOMAIN" /> and your account is managed by <ph name="ACCOUNT_DOMAIN" />. This means that your administrators may remotely configure your device and account.</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5128122789703661928">The session with this name is not valid for deletion.</translation>
<translation id="5135404736266831032">Manage addresses...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Machine</translation>
<translation id="5179510805599951267">Not in <ph name="ORIGINAL_LANGUAGE" />? Report this error</translation>
<translation id="5190835502935405962">Bookmarks Bar</translation>
+<translation id="5200263511887412697">report list of device users that have recently logged in</translation>
<translation id="5201306358585911203">An embedded page on this page says</translation>
<translation id="5205222826937269299">Name required</translation>
<translation id="5215116848420601511">Payment methods and addresses using Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">This site can’t be reached</translation>
<translation id="5869522115854928033">Saved passwords</translation>
<translation id="5887400589839399685">Card saved</translation>
+<translation id="5893718151540690985">report list of network interfaces with their types and hardware addresses</translation>
<translation id="5893752035575986141">Credit cards are accepted.</translation>
<translation id="5901630391730855834">Yellow</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synced)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Edit Contact Info</translation>
<translation id="5967867314010545767">Remove from history</translation>
<translation id="5975083100439434680">Zoom out</translation>
+<translation id="5977489021191000276">Your device is not managed by an administrator.</translation>
<translation id="5977976211062815271">On this device</translation>
<translation id="598637245381783098">Can’t open payment app</translation>
<translation id="5989320800837274978">Neither fixed proxy servers nor a .pac script URL are specified.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Attackers on <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> could install deceptive apps that pretend to be something else or collect data that may be used to track you. <ph name="BEGIN_LEARN_MORE_LINK" />Learn more<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synced)</translation>
<translation id="6027201098523975773">Enter a name</translation>
+<translation id="6033927989869462158">report hardware statistics such as CPU/RAM usage</translation>
<translation id="6034000775414344507">Light grey</translation>
<translation id="6039846035001940113">If the problem continues, contact the site owner.</translation>
<translation id="6040143037577758943">Close</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">User Agent</translation>
<translation id="6903319715792422884">Help improve Safe Browsing by sending some <ph name="BEGIN_WHITEPAPER_LINK" />system information and page content<ph name="END_WHITEPAPER_LINK" /> to Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">User:</translation>
+<translation id="6934672428414710184">This name is from your Google account</translation>
+<translation id="6939583532829045966">Your device is managed by <ph name="ENROLLMENT_DOMAIN" />. This means that your administrator may remotely configure your device.</translation>
<translation id="6944692733090228304">You entered your password on a site that’s not managed by <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. To protect your account, don’t reuse your password on other apps and sites.</translation>
<translation id="6945221475159498467">Select</translation>
<translation id="6948701128805548767">To see pickup methods and requirements, select an address</translation>
@@ -992,6 +1004,7 @@ Additional details:
&lt;li&gt;Click &lt;strong&gt;Apply&lt;/strong&gt;, then click &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Visit the &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome help centre&lt;/a&gt; to find out how to permanently remove the software from your computer
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> management</translation>
<translation id="7416351320495623771">Manage passwords...</translation>
<translation id="7419106976560586862">Profile Path</translation>
<translation id="7437289804838430631">Add contact info</translation>
@@ -1000,10 +1013,12 @@ Additional details:
<translation id="7442725080345379071">Light orange</translation>
<translation id="7444046173054089907">This site is blocked</translation>
<translation id="7445762425076701745">The identity of the server to which you are connected cannot be fully validated. You are connected to a server using a name valid only within your network, and an external certificate authority has no way to validate ownership. As some certificate authorities will issue certificates for these names regardless, there is no way to ensure that you are connected to the intended website and not to an attacker.</translation>
+<translation id="7449109375006139765">send system logs to the management server</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Find out more<ph name="END_LINK" /> about this problem.</translation>
<translation id="7455133967321480974">Use global default (Block)</translation>
<translation id="7460618730930299168">The screening is different from what you selected. Continue?</translation>
<translation id="7473891865547856676">No Thanks</translation>
+<translation id="7475525192983021547">report time periods when a user is active on the device</translation>
<translation id="7481312909269577407">Forward</translation>
<translation id="7485870689360869515">No data found.</translation>
<translation id="7508255263130623398">Returned policy device ID is empty or doesn't match current device ID</translation>
@@ -1096,6 +1111,7 @@ Additional details:
<translation id="7995512525968007366">Not Specified</translation>
<translation id="800218591365569300">Try closing other tabs or programmes to free up memory.</translation>
<translation id="8009225694047762179">Manage Passwords</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{This card and its billing address will be saved. You'll be able to use it when signed in to <ph name="USER_EMAIL" />.}other{These cards and their billing addresses will be saved. You'll be able to use them when signed in to <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">We could not reach your parents at the moment. Please try again.</translation>
<translation id="8025119109950072390">Attackers on this site may trick you into doing something dangerous like installing software or revealing your personal information (for example passwords, phone numbers or credit cards).</translation>
<translation id="8034522405403831421">This page is in <ph name="SOURCE_LANGUAGE" />. Translate it to <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Additional details:
<translation id="8041940743680923270">Use global default (Ask)</translation>
<translation id="8042918947222776840">Choose pickup method</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />' isn’t configured correctly. Uninstalling '<ph name="SOFTWARE_NAME" />' usually fixes the problem. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Your device has been configured to:</translation>
<translation id="8078141288243656252">Cannot annotate when rotated</translation>
<translation id="8079031581361219619">Reload site?</translation>
<translation id="8088680233425245692">Failed to view article.</translation>
@@ -1156,6 +1173,7 @@ Additional details:
<translation id="8363502534493474904">Turning off aeroplane mode</translation>
<translation id="8364627913115013041">Not set.</translation>
<translation id="8368476060205742148">Google Play services</translation>
+<translation id="8371889962595521444">Custom root certificates</translation>
<translation id="8380941800586852976">Dangerous</translation>
<translation id="8381674639488873545">These charges could be one-time or recurring and may not be obvious. <ph name="BEGIN_LINK" />Show anyway<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Your recently visited bookmarks appear here</translation>
@@ -1165,6 +1183,7 @@ Additional details:
<translation id="8416694386774425977">The network configuration is invalid and couldn't be imported.
Additional details:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Device managed by <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Change</translation>
<translation id="8428213095426709021">Settings</translation>
@@ -1225,6 +1244,7 @@ Additional details:
<translation id="8932102934695377596">Your clock is behind</translation>
<translation id="893332455753468063">Add Name</translation>
<translation id="8938939909778640821">Accepted credit and prepaid cards</translation>
+<translation id="894185898663964645">Your administrator has configured custom root certificates, which may allow the administrator to see the contents of websites that you visit.</translation>
<translation id="8943282376843390568">Lime</translation>
<translation id="8957210676456822347">Captive Portal Authorisation</translation>
<translation id="8968766641738584599">Save card</translation>
diff --git a/chromium/components/strings/components_strings_es-419.xtb b/chromium/components/strings/components_strings_es-419.xtb
index e1768fdc385..9be328f398c 100644
--- a/chromium/components/strings/components_strings_es-419.xtb
+++ b/chromium/components/strings/components_strings_es-419.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">No se traducirán las páginas en <ph name="LANGUAGE" />.</translation>
<translation id="2053553514270667976">Código Postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugerencia}other{# sugerencias}}</translation>
+<translation id="2068124040035837596">Tu cuenta se administra mediante el dominio <ph name="ENROLLMENT_DOMAIN" />. Esto significa que tu administrador puede configurarla de forma remota.</translation>
<translation id="2068663545051464999">ID del informe de fallos subido <ph name="CRASH_ID" /> (Contexto local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Deshacer</translation>
<translation id="20817612488360358">Se ha establecido la configuración de proxy del sistema, pero también se ha especificado una configuración explícita de proxy.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">El método de envío no está disponible. Prueba otro método.</translation>
<translation id="2396249848217231973">&amp;Deshacer Eliminar</translation>
<translation id="2413528052993050574">Este servidor no pudo probar que su dominio es <ph name="DOMAIN" /> y se podría revocar el certificado de seguridad. Es posible que esto se deba a una configuración incorrecta o a que un atacante interceptó la conexión.</translation>
+<translation id="244665789865330679">Tu dispositivo y cuenta se administran mediante el dominio <ph name="ENROLLMENT_DOMAIN" />. Esto significa que tu administrador puede configurarlos de forma remota.</translation>
<translation id="2463193859425327265">Cambiar página principal</translation>
<translation id="2463739503403862330">Llenar</translation>
<translation id="2465655957518002998">Elegir método de entrega</translation>
@@ -562,6 +564,7 @@
<translation id="4377125064752653719">Intentaste acceder a <ph name="DOMAIN" />, pero el emisor anuló el certificado que presentó el servidor. Esto significa que no se debe confiar en absoluto en las credenciales de seguridad que presentó el servidor. Te puedes estar comunicando con un atacante.</translation>
<translation id="4378154925671717803">Teléfono</translation>
<translation id="4406896451731180161">resultados de búsqueda</translation>
+<translation id="4406972042435603828">Tus administradores instalaron extensiones con potentes capacidades.</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Dirección de retiro</translation>
<translation id="4424024547088906515">Este servidor no pudo probar que su dominio es <ph name="DOMAIN" />; Chrome no confía en el certificado de seguridad. Es posible que esto se deba a una configuración incorrecta o a que un atacante interceptó la conexión.</translation>
@@ -633,10 +636,12 @@
<translation id="4943872375798546930">Sin resultados</translation>
<translation id="4950898438188848926">Botón para cambiar de pestaña; presiona Intro para cambiar a la pestaña abierta <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Acciones</translation>
+<translation id="495832697253704892">Informe de las extensiones</translation>
<translation id="4958444002117714549">Mostrar lista</translation>
<translation id="4974590756084640048">Volver a habilitar las advertencias</translation>
<translation id="4989163558385430922">Ver todo</translation>
<translation id="4989809363548539747">Este complemento no es compatible</translation>
+<translation id="4996230189582812866">Informes</translation>
<translation id="5002932099480077015">Si se habilita esta opción, Chrome almacenará una copia de la tarjeta en el dispositivo para llenar más rápidamente los formularios.</translation>
<translation id="5014174725590676422">Se muestra la pantalla de primera ejecución del Asistente de Google en Chrome</translation>
<translation id="5015510746216210676">Nombre de la máquina:</translation>
@@ -657,6 +662,7 @@
<translation id="5089810972385038852">Estado</translation>
<translation id="5094747076828555589">Este servidor no pudo probar que su dominio es <ph name="DOMAIN" />; Chromium no confía en el certificado de seguridad. Es posible que esto se deba a una configuración incorrecta o a que un atacante interceptó la conexión.</translation>
<translation id="5095208057601539847">Provincia</translation>
+<translation id="5098222253617183465">Tu dispositivo y tu cuenta se administran mediante el dominio <ph name="ENROLLMENT_DOMAIN" /> y el <ph name="ACCOUNT_DOMAIN" /> respectivamente. Esto significa que tus administradores pueden configurarlos de forma remota.</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5128122789703661928">La sesión con este nombre no se puede borrar.</translation>
<translation id="5135404736266831032">Administrar direcciones…</translation>
@@ -669,6 +675,7 @@
<translation id="5172758083709347301">Equipo</translation>
<translation id="5179510805599951267">¿No está en <ph name="ORIGINAL_LANGUAGE" />? Informa este error</translation>
<translation id="5190835502935405962">Barra de favoritos</translation>
+<translation id="5200263511887412697">enviar una lista con los usuarios de dispositivos que accedieron recientemente</translation>
<translation id="5201306358585911203">Una página incorporada en esta página dice</translation>
<translation id="5205222826937269299">Nombre (obligatorio)</translation>
<translation id="5215116848420601511">Formas de pago y direcciones con Google Pay</translation>
@@ -770,6 +777,7 @@
<translation id="5869405914158311789">No se puede acceder a este sitio</translation>
<translation id="5869522115854928033">Contraseñas almacenadas</translation>
<translation id="5887400589839399685">Tarjeta guardada</translation>
+<translation id="5893718151540690985">informar una lista de las interfaces de red con sus tipos y direcciones de hardware</translation>
<translation id="5893752035575986141">Se aceptan tarjetas de crédito.</translation>
<translation id="5901630391730855834">Amarillo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizado)</translation>
@@ -783,6 +791,7 @@
<translation id="5967592137238574583">Editar la información de contacto</translation>
<translation id="5967867314010545767">Eliminar del historial</translation>
<translation id="5975083100439434680">Alejar</translation>
+<translation id="5977489021191000276">Tu dispositivo no está administrado.</translation>
<translation id="5977976211062815271">En este dispositivo</translation>
<translation id="598637245381783098">No se puede abrir la app de pago</translation>
<translation id="5989320800837274978">No se especifican servidores proxy fijos ni URL de secuencias de comandos .pac.</translation>
@@ -794,6 +803,7 @@
<translation id="6017850046339264347">Es posible que los atacantes que se encuentran en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> instalen apps engañosas que se hagan pasar por otro tipo de contenido o que recopilen datos que se usen para rastrearte. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sincronizados)</translation>
<translation id="6027201098523975773">Ingresa un nombre</translation>
+<translation id="6033927989869462158">informar las estadísticas sobre hardware, como el uso de CPU y RAM</translation>
<translation id="6034000775414344507">Gris claro</translation>
<translation id="6039846035001940113">Si el problema persiste, comunícate con el propietario del sitio.</translation>
<translation id="6040143037577758943">Cerrar</translation>
@@ -906,6 +916,8 @@
<translation id="6897140037006041989">User agent</translation>
<translation id="6903319715792422884">Para mejorar la Navegación segura, envía <ph name="BEGIN_WHITEPAPER_LINK" />información del sistema y contenido de la página<ph name="END_WHITEPAPER_LINK" /> a Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Usuario:</translation>
+<translation id="6934672428414710184">Este nombre es de tu Cuenta de Google</translation>
+<translation id="6939583532829045966">Tu dispositivo se administra mediante el dominio <ph name="ENROLLMENT_DOMAIN" />. Esto significa que tu administrador puede configurarlo de forma remota.</translation>
<translation id="6944692733090228304">Ingresaste tu contraseña en un sitio que no está administrado por <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Para proteger tu cuenta, no vuelvas a usar la contraseña en otras apps y sitios.</translation>
<translation id="6945221475159498467">Seleccionar</translation>
<translation id="6948701128805548767">Para ver los requisitos y métodos de retiro, selecciona una dirección</translation>
@@ -993,6 +1005,7 @@ Detalles adicionales:
&lt;li&gt;Haz clic en &lt;strong&gt;Aplicar&lt;/strong&gt; y, luego, en &lt;strong&gt;Aceptar&lt;/strong&gt;.
&lt;li&gt;Visita el &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centro de ayuda de Chrome&lt;/a&gt; para obtener información sobre cómo quitar el software de forma permanente de tu computadora.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Administración de <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Administrar contraseñas…</translation>
<translation id="7419106976560586862">Ruta del perfil</translation>
<translation id="7437289804838430631">Agregar información de contacto</translation>
@@ -1001,10 +1014,12 @@ Detalles adicionales:
<translation id="7442725080345379071">Naranja claro</translation>
<translation id="7444046173054089907">Este sitio está bloqueado</translation>
<translation id="7445762425076701745">La identidad del servidor al que estás conectado no se puede validar en su totalidad. Estás conectado a un servidor utilizando un nombre que sólo es válido dentro de tu red y cuya propiedad no puede validar una entidad externa de certificación. Debido a que algunas entidades emiten certificados aún para estos nombres, no hay manera de asegurar que estás conectado al sitio web que pretendías o a un atacante.</translation>
+<translation id="7449109375006139765">enviar registros del sistema al servidor de administración</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Más información<ph name="END_LINK" /> acerca de este problema</translation>
<translation id="7455133967321480974">Usar configuración global predeterminada (Bloquear)</translation>
<translation id="7460618730930299168">La proyección es diferente a tu selección. ¿Quieres continuar?</translation>
<translation id="7473891865547856676">No, gracias</translation>
+<translation id="7475525192983021547">informar los períodos en el que un usuario utiliza el dispositivo</translation>
<translation id="7481312909269577407">Reenviar</translation>
<translation id="7485870689360869515">No se encontró ningún dato.</translation>
<translation id="7508255263130623398">El ID de dispositivo de la política que se muestra está vacío o no coincide con el ID de dispositivo actual</translation>
@@ -1097,6 +1112,7 @@ Detalles adicionales:
<translation id="7995512525968007366">Sin especificar</translation>
<translation id="800218591365569300">Prueba cerrar las demás pestañas o programas para liberar memoria.</translation>
<translation id="8009225694047762179">Administrar contraseñas</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Se guardará esta tarjeta y su dirección de facturación. Podrás usarla cuando accedas a <ph name="USER_EMAIL" />.}other{Se guardarán estas tarjetas y sus direcciones de facturación. Podrás usarlas cuando accedas a <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">No pudimos comunicarnos con tus padres. Vuelve a intentarlo.</translation>
<translation id="8025119109950072390">Es posible que los atacantes de este sitio te engañen para que hagas algo peligroso, como instalar software o divulgar información personal (p. ej., contraseñas, números de teléfono o tarjetas de crédito).</translation>
<translation id="8034522405403831421">Esta página está en <ph name="SOURCE_LANGUAGE" />. ¿Quieres traducirla al <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1107,6 +1123,7 @@ Detalles adicionales:
<translation id="8041940743680923270">Usar configuración global predeterminada (Preguntar)</translation>
<translation id="8042918947222776840">Elegir método de retiro</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" no se configuró correctamente. Prueba desinstalar "<ph name="SOFTWARE_NAME" />" para corregir el problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Tu dispositivo se configuró para:</translation>
<translation id="8078141288243656252">No se pueden realizar anotaciones cuando el documento está rotado</translation>
<translation id="8079031581361219619">¿Deseas volver a cargar el sitio?</translation>
<translation id="8088680233425245692">Error al visualizar artículo</translation>
@@ -1157,6 +1174,7 @@ Detalles adicionales:
<translation id="8363502534493474904">Desactivar el modo de avión.</translation>
<translation id="8364627913115013041">Sin establecer</translation>
<translation id="8368476060205742148">Servicios de Google Play</translation>
+<translation id="8371889962595521444">Certificados raíz personalizados</translation>
<translation id="8380941800586852976">Peligrosa</translation>
<translation id="8381674639488873545">Estos cargos pueden ser únicos o recurrentes, y es posible que no sean evidentes. <ph name="BEGIN_LINK" />Mostrar de todos modos<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Los favoritos que visitaste recientemente aparecen aquí</translation>
@@ -1166,6 +1184,7 @@ Detalles adicionales:
<translation id="8416694386774425977">La configuración de red no es válida y no se pudo importar.
Detalles adicionales:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Dispositivo administrado por <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Cambiar</translation>
<translation id="8428213095426709021">Configuración</translation>
@@ -1227,6 +1246,7 @@ Detalles adicionales:
<translation id="8932102934695377596">El reloj está atrasado</translation>
<translation id="893332455753468063">Agregar nombre</translation>
<translation id="8938939909778640821">Tarjetas de crédito y prepago aceptadas</translation>
+<translation id="894185898663964645">Tu administrador configuró certificados raíz personalizados, lo que le permite ver el contenido de los sitios web que visites.</translation>
<translation id="8943282376843390568">Verde lima</translation>
<translation id="8957210676456822347">Autorización de portal cautivo</translation>
<translation id="8968766641738584599">Guardar la tarjeta</translation>
diff --git a/chromium/components/strings/components_strings_es.xtb b/chromium/components/strings/components_strings_es.xtb
index b480c14cff0..fc6ce007982 100644
--- a/chromium/components/strings/components_strings_es.xtb
+++ b/chromium/components/strings/components_strings_es.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">No se traducirán las páginas en <ph name="LANGUAGE" />.</translation>
<translation id="2053553514270667976">Código postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{Una sugerencia}other{# sugerencias}}</translation>
+<translation id="2068124040035837596"><ph name="ENROLLMENT_DOMAIN" /> gestiona tu cuenta. Esto significa que el administrador puede configurar tu cuenta de manera remota.</translation>
<translation id="2068663545051464999">ID del informe sobre fallos subido: <ph name="CRASH_ID" /> (contexto local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Deshacer</translation>
<translation id="20817612488360358">Se ha establecido la configuración del proxy del sistema, pero también se han especificado ajustes de proxy explícitos.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Este método de envío no está disponible. Selecciona otro.</translation>
<translation id="2396249848217231973">&amp;Deshacer eliminación</translation>
<translation id="2413528052993050574">Este servidor no ha podido probar que su dominio es <ph name="DOMAIN" /> y se podría rechazar su certificado de seguridad. Este problema puede deberse a una configuración incorrecta o a que un atacante haya interceptado la conexión.</translation>
+<translation id="244665789865330679"><ph name="ENROLLMENT_DOMAIN" /> gestiona tu dispositivo y tu cuenta. Esto significa que el administrador puede configurar tu dispositivo y tu cuenta de manera remota.</translation>
<translation id="2463193859425327265">Cambiar página de inicio</translation>
<translation id="2463739503403862330">Rellenar</translation>
<translation id="2465655957518002998">Seleccionar método de entrega</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Has intentado acceder a <ph name="DOMAIN" />, pero el emisor ha revocado el certificado mostrado por el servidor, lo que significa que las credenciales de seguridad presentadas por el servidor no son de confianza. Es posible que hayas accedido a la página de un atacante.</translation>
<translation id="4378154925671717803">Teléfono</translation>
<translation id="4406896451731180161">resultados de la búsqueda</translation>
+<translation id="4406972042435603828">Tus administradores han instalado extensiones que incluyen funciones muy potentes.</translation>
<translation id="4408413947728134509">Cookies: <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Dirección de recogida</translation>
<translation id="4424024547088906515">Este servidor no ha podido probar que su dominio es <ph name="DOMAIN" />, Chrome no confía en su certificado de seguridad. Este problema puede deberse a una configuración incorrecta o a que un atacante haya interceptado la conexión.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Sin resultados</translation>
<translation id="4950898438188848926">Botón de cambio de pestaña; pulsa Intro para cambiar a la pestaña abierta, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Acciones</translation>
+<translation id="495832697253704892">Informes de extensiones</translation>
<translation id="4958444002117714549">Expandir lista</translation>
<translation id="4974590756084640048">Volver a habilitar advertencias</translation>
<translation id="4989163558385430922">Ver todo</translation>
<translation id="4989809363548539747">Este complemento no es compatible</translation>
+<translation id="4996230189582812866">Informes</translation>
<translation id="5002932099480077015">Si se habilita esta opción, Chrome guardará una copia de tu tarjeta en este dispositivo para rellenar la información más rápido.</translation>
<translation id="5014174725590676422">Se muestra la primera pantalla de ejecución del Asistente de Google en Chrome</translation>
<translation id="5015510746216210676">Nombre del equipo:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Estado/provincia</translation>
<translation id="5094747076828555589">Este servidor no ha podido probar que su dominio es <ph name="DOMAIN" />, Chromium no confía en su certificado de seguridad. Este problema puede deberse a una configuración incorrecta o a que un atacante haya interceptado la conexión.</translation>
<translation id="5095208057601539847">Provincia</translation>
+<translation id="5098222253617183465"><ph name="ENROLLMENT_DOMAIN" /> gestiona tu dispositivo y <ph name="ACCOUNT_DOMAIN" />, tu cuenta. Esto significa que los administradores pueden configurar de manera remota tu dispositivo y tu cuenta.</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5128122789703661928">No se puede eliminar la sesión con este nombre.</translation>
<translation id="5135404736266831032">Gestiona tus direcciones...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Equipo</translation>
<translation id="5179510805599951267">¿Esta página no está escrita en <ph name="ORIGINAL_LANGUAGE" />? Informa de este error.</translation>
<translation id="5190835502935405962">Barra de marcadores</translation>
+<translation id="5200263511887412697">permite informar de la lista de usuarios del dispositivo que han iniciado sesión recientemente</translation>
<translation id="5201306358585911203">Una página insertada en esta dice</translation>
<translation id="5205222826937269299">Nombre obligatorio</translation>
<translation id="5215116848420601511">Métodos de pago y direcciones con Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">No se puede acceder a este sitio web</translation>
<translation id="5869522115854928033">Contraseñas guardadas</translation>
<translation id="5887400589839399685">Tarjeta guardada</translation>
+<translation id="5893718151540690985">permite informar de la lista de interfaces de red con sus tipos y sus direcciones de hardware</translation>
<translation id="5893752035575986141">Se aceptan tarjetas de crédito.</translation>
<translation id="5901630391730855834">Amarillo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizado)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Edita la información de contacto</translation>
<translation id="5967867314010545767">Eliminar del historial</translation>
<translation id="5975083100439434680">Reducir</translation>
+<translation id="5977489021191000276">Tu dispositivo no está gestionado por un administrador.</translation>
<translation id="5977976211062815271">En este dispositivo</translation>
<translation id="598637245381783098">No se ha podido abrir la aplicación de pago</translation>
<translation id="5989320800837274978">No se han especificado servidores proxy fijos ni una URL de secuencia de comandos .pac.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Se ha detectado la presencia de atacantes en el sitio web <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />. Estos podrían instalar aplicaciones engañosas que se hagan pasar por otra persona o recojan datos que podrían usarse para realizar un seguimiento de tu actividad. <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sincronizados)</translation>
<translation id="6027201098523975773">Introduce un nombre</translation>
+<translation id="6033927989869462158">permite informar de estadísticas de hardware, como el uso de CPU y memoria RAM</translation>
<translation id="6034000775414344507">Gris claro</translation>
<translation id="6039846035001940113">Si el problema persiste, ponte en contacto con el propietario del sitio web.</translation>
<translation id="6040143037577758943">Cerrar</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Agente de usuario</translation>
<translation id="6903319715792422884">Ayuda a mejorar la Navegación Segura enviando <ph name="BEGIN_WHITEPAPER_LINK" />datos del sistema y contenido de las páginas<ph name="END_WHITEPAPER_LINK" /> a Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Usuario:</translation>
+<translation id="6934672428414710184">Este nombre proviene de tu cuenta de Google</translation>
+<translation id="6939583532829045966"><ph name="ENROLLMENT_DOMAIN" /> gestiona tu cuenta. Esto significa que el administrador puede configurar tu cuenta de manera remota.</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> no gestiona el sitio web en el que has introducido tu contraseña. Para proteger tu cuenta, no utilices la misma contraseña en otras aplicaciones o sitios web.</translation>
<translation id="6945221475159498467">Seleccionar</translation>
<translation id="6948701128805548767">Selecciona una dirección para ver los métodos de recogida y los requisitos</translation>
@@ -992,6 +1004,7 @@ Más información:
&lt;li&gt;Haz clic en &lt;strong&gt;Aplicar&lt;/strong&gt; y, a continuación, en &lt;strong&gt;Aceptar&lt;/strong&gt;
&lt;li&gt;Visita el &lt;a href="https://support.google.com/chrome/answer/6098869?hl=es"&gt;Centro de Ayuda de Chrome&lt;/a&gt; para consultar cómo eliminar el software de forma permanente de tu ordenador
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Gestión de <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Gestionar contraseñas…</translation>
<translation id="7419106976560586862">Ruta del perfil</translation>
<translation id="7437289804838430631">Añade la información de contacto</translation>
@@ -1000,10 +1013,12 @@ Más información:
<translation id="7442725080345379071">Naranja claro</translation>
<translation id="7444046173054089907">Este sitio web se ha bloqueado</translation>
<translation id="7445762425076701745">La identidad del servidor al que estás conectado no se puede validar por completo. Estás conectado a un servidor con un nombre que solo es válido en tu red y cuya propiedad no puede validar en modo alguno una entidad emisora de certificados externa. A pesar de ello, algunas entidades emisoras emiten certificados para esos nombres, por lo que no es posible garantizar que estés conectado al sitio web deseado, en lugar de a un atacante.</translation>
+<translation id="7449109375006139765">permite enviar los registros del sistema al servidor de administración</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Consultar más información<ph name="END_LINK" /> sobre este problema</translation>
<translation id="7455133967321480974">Utilizar valor predeterminado global (Bloquear)</translation>
<translation id="7460618730930299168">El filtro es distinto al que has seleccionado. ¿Quieres continuar?</translation>
<translation id="7473891865547856676">No, gracias</translation>
+<translation id="7475525192983021547">permite informar de los periodos durante los que un usuario está activo en el dispositivo</translation>
<translation id="7481312909269577407">Adelante</translation>
<translation id="7485870689360869515">No se han encontrado datos.</translation>
<translation id="7508255263130623398">El ID de dispositivo de política devuelto está vacío o no coincide con el ID de dispositivo actual</translation>
@@ -1096,6 +1111,7 @@ Más información:
<translation id="7995512525968007366">Sin especificar</translation>
<translation id="800218591365569300">Prueba a cerrar otros programas o pestañas para liberar memoria.</translation>
<translation id="8009225694047762179">Administrar contraseñas</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Se guardará la tarjeta y su dirección de facturación. Podrás utilizarla cuando inicies sesión como <ph name="USER_EMAIL" />.}other{Se guardarán las tarjetas y sus direcciones de facturación. Podrás utilizarlas cuando inicies sesión como <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">No hemos podido contactar con tus padres. Vuelve a intentarlo.</translation>
<translation id="8025119109950072390">Es posible que los atacantes que se encuentren en este sitio web intenten engañarte para que realices una acción peligrosa, como instalar software o revelar tu información personal (por ejemplo, contraseñas, números de teléfono o tarjetas de crédito).</translation>
<translation id="8034522405403831421">Esta página está escrita en <ph name="SOURCE_LANGUAGE" />. ¿Quieres traducirla al <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Más información:
<translation id="8041940743680923270">Utilizar valor predeterminado global (Preguntar)</translation>
<translation id="8042918947222776840">Seleccionar método de recogida</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" no se ha configurado correctamente. Normalmente, el problema se soluciona al desinstalar "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Tu dispositivo se ha configurado de la siguiente manera:</translation>
<translation id="8078141288243656252">No se pueden añadir anotaciones a los documentos girados</translation>
<translation id="8079031581361219619">¿Quieres volver a cargar el sitio web?</translation>
<translation id="8088680233425245692">Se ha producido un error al ver el artículo.</translation>
@@ -1156,6 +1173,7 @@ Más información:
<translation id="8363502534493474904">Desactivar el modo avión</translation>
<translation id="8364627913115013041">No establecida</translation>
<translation id="8368476060205742148">Servicios de Google Play</translation>
+<translation id="8371889962595521444">Certificados raíz personalizados</translation>
<translation id="8380941800586852976">Peligroso</translation>
<translation id="8381674639488873545">Estos cargos pueden ser únicos o periódicos, y es posible que no se indiquen de una forma evidente. <ph name="BEGIN_LINK" />Mostrar de todos modos<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Los marcadores a los que hayas accedido recientemente aparecen aquí</translation>
@@ -1165,6 +1183,7 @@ Más información:
<translation id="8416694386774425977">La configuración de red no es válida y no se ha podido importar.
Más información:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Dispositivo gestionado por <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Cambiar</translation>
<translation id="8428213095426709021">Configuración</translation>
@@ -1225,6 +1244,7 @@ Más información:
<translation id="8932102934695377596">Tu reloj está atrasado</translation>
<translation id="893332455753468063">Añade un nombre</translation>
<translation id="8938939909778640821">Tarjetas prepago y de crédito aceptadas</translation>
+<translation id="894185898663964645">Tu administrador ha configurado certificados raíz personalizados que permiten al administrador ver el contenido de los sitios web que visites.</translation>
<translation id="8943282376843390568">Lima</translation>
<translation id="8957210676456822347">Autorización de portal cautivo</translation>
<translation id="8968766641738584599">Guardar tarjeta</translation>
diff --git a/chromium/components/strings/components_strings_et.xtb b/chromium/components/strings/components_strings_et.xtb
index 4b6b0dab0f4..e2bdcc4b774 100644
--- a/chromium/components/strings/components_strings_et.xtb
+++ b/chromium/components/strings/components_strings_et.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Selles keeles lehti ei tõlgita: <ph name="LANGUAGE" />.</translation>
<translation id="2053553514270667976">Postiindeks</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 soovitus}other{# soovitust}}</translation>
+<translation id="2068124040035837596">Teie kontot hallatakse domeenilt <ph name="ENROLLMENT_DOMAIN" />. See tähendab, et administraator saab teie kontot kaugühenduse teel seadistada.</translation>
<translation id="2068663545051464999">Üleslaaditud krahhiaruande ID <ph name="CRASH_ID" /> (kohalik kontekst: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Võta tagasi</translation>
<translation id="20817612488360358">Kasutamiseks on määratud süsteemi puhverserveri seaded, kuid määratud on ka konkreetne puhverserveri konfigureerimine.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">See tarneviis pole saadaval. Proovige mõnda teist tarneviisi.</translation>
<translation id="2396249848217231973">&amp;Võta kustutamine tagasi</translation>
<translation id="2413528052993050574">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />, selle turvasertifikaat võib olla tühistatud. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
+<translation id="244665789865330679">Teie seadet ja kontot hallatakse domeenilt <ph name="ENROLLMENT_DOMAIN" />. See tähendab, et administraator saab teie seadet ja kontot kaugühenduse teel seadistada.</translation>
<translation id="2463193859425327265">Muuda avalehte</translation>
<translation id="2463739503403862330">Täida</translation>
<translation id="2465655957518002998">Valige kohaletoimetamisviis</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Püüdsite jõuda saidile <ph name="DOMAIN" />, kuid sertifikaadi väljaandja on serveri esitatud sertifikaadi tagasi võtnud. See tähendab, et serveri esitatud turvamandaate ei tohiks mingil juhul usaldada. Võimalik, et suhtlete ründajaga.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">otsingutulemused</translation>
+<translation id="4406972042435603828">Teie administraatorid on installinud võimekad laiendused.</translation>
<translation id="4408413947728134509">Küpsisefailid: <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Kättesaamisaadress</translation>
<translation id="4424024547088906515">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />, Chrome ei usalda selle turvasertifikaati. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Tulemusi pole</translation>
<translation id="4950898438188848926">Vahelehe vahetamise nupp, vajutage sisestusklahvi avatud vahelehe aktiveerimiseks, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Toimingud</translation>
+<translation id="495832697253704892">Laienduste aruandlus</translation>
<translation id="4958444002117714549">Laienda loendit</translation>
<translation id="4974590756084640048">Luba hoiatused uuesti</translation>
<translation id="4989163558385430922">Kuva kõik</translation>
<translation id="4989809363548539747">Seda pistikprogrammi ei toetata</translation>
+<translation id="4996230189582812866">Aruandlus</translation>
<translation id="5002932099480077015">Kui see on lubatud, salvestab Chrome teie kaardi koopia vormide kiiremini täitmiseks sellesse seadmesse.</translation>
<translation id="5014174725590676422">Näidatud on Google'i assistendi esmakordse käivitamise kuva Chrome'is</translation>
<translation id="5015510746216210676">Seadme nimi:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Osariik/Maakond</translation>
<translation id="5094747076828555589">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />, Chromium ei usalda selle turvasertifikaati. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
<translation id="5095208057601539847">Provints</translation>
+<translation id="5098222253617183465">Teie seadet hallatakse domeenilt <ph name="ENROLLMENT_DOMAIN" /> ja kontot domeenilt <ph name="ACCOUNT_DOMAIN" />. See tähendab, et administraatorid saavad teie seadet ja kontot kaugühenduse teel seadistada.</translation>
<translation id="5115563688576182185">(64-bitine)</translation>
<translation id="5128122789703661928">Selle nimega seanssi ei saa kustutada.</translation>
<translation id="5135404736266831032">Halda aadresse …</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Masin</translation>
<translation id="5179510805599951267">Tegu ei ole <ph name="ORIGINAL_LANGUAGE" /> keelega? Andke veast teada</translation>
<translation id="5190835502935405962">Järjehoidjariba</translation>
+<translation id="5200263511887412697">Edastab loendi seadme kasutajatest, kes on hiljuti sisse loginud.</translation>
<translation id="5201306358585911203">Selle lehe manustatud leht ütleb</translation>
<translation id="5205222826937269299">Nimi on nõutav</translation>
<translation id="5215116848420601511">Makseviisid ja aadressid, mis kasutavad teenust Google Pay.</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Selle saidiga ei saa ühendust</translation>
<translation id="5869522115854928033">Salvestatud paroolid</translation>
<translation id="5887400589839399685">Kaart on salvestatud</translation>
+<translation id="5893718151540690985">Edastab loendi võrguliidestest koos nende tüüpide ja riistvara aadressidega</translation>
<translation id="5893752035575986141">Kaupmees aktsepteerib krediitkaarte.</translation>
<translation id="5901630391730855834">Kollane</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sünkroonitud)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Kontaktteabe muutmine</translation>
<translation id="5967867314010545767">Eemalda ajaloost</translation>
<translation id="5975083100439434680">Suumib välja</translation>
+<translation id="5977489021191000276">Teie seadet ei halda administraator.</translation>
<translation id="5977976211062815271">Selles seadmes</translation>
<translation id="598637245381783098">Makserakendust ei saa avada</translation>
<translation id="5989320800837274978">Määratud ei ole fikseeritud puhverservereid ega pac-skriptiga URL-i.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Ründajad saidil <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> võivad installida petlikke rakendusi, mis esinevad millegi muuna või koguvad andmeid, mida võidakse kasutada teie jälgimiseks. <ph name="BEGIN_LEARN_MORE_LINK" />Lisateave<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sünkroonitud)</translation>
<translation id="6027201098523975773">Sisestage nimi</translation>
+<translation id="6033927989869462158">Edastab riistvara statistikat (nt protsessori/RAM-i kasutus)</translation>
<translation id="6034000775414344507">Helehall</translation>
<translation id="6039846035001940113">Kui probleem jätkub, võtke ühendust saidi omanikuga.</translation>
<translation id="6040143037577758943">Sulge</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Kasutajaagent</translation>
<translation id="6903319715792422884">Aidake ohutu sirvimise funktsiooni täiustada, saates Google'ile <ph name="BEGIN_WHITEPAPER_LINK" />süsteemiteavet ja lehesisu<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Kasutaja:</translation>
+<translation id="6934672428414710184">Nimi pärineb teie Google'i kontolt</translation>
+<translation id="6939583532829045966">Teie seadet hallatakse domeenilt <ph name="ENROLLMENT_DOMAIN" />. See tähendab, et administraator saab teie seadet kaugühenduse teel seadistada.</translation>
<translation id="6944692733090228304">Sisestasite oma parooli saidile, mida ei halda <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Oma konto kaitsmiseks ärge kasutage oma parooli muudes rakendustes ega saitidel.</translation>
<translation id="6945221475159498467">Vali</translation>
<translation id="6948701128805548767">Kättesaamisviiside ja nõuete nägemiseks valige aadress</translation>
@@ -992,6 +1004,7 @@ Lisateave:
&lt;li&gt;Klõpsake käsul &lt;strong&gt;Apply&lt;/strong&gt; ja seejärel valikul &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Vaadake &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome'i abikeskusest&lt;/a&gt; teavet selle kohta, kuidas tarkvara arvutist jäädavalt eemaldada
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Teenuse <ph name="PRODUCT_NAME" /> haldus</translation>
<translation id="7416351320495623771">Halda paroole …</translation>
<translation id="7419106976560586862">Profiili tee</translation>
<translation id="7437289804838430631">Lisa kontaktteave</translation>
@@ -1000,10 +1013,12 @@ Lisateave:
<translation id="7442725080345379071">Heleoranž</translation>
<translation id="7444046173054089907">See sait on blokeeritud</translation>
<translation id="7445762425076701745">Serveri identiteeti, millega olete ühenduses, ei saa täielikult valideerida. Olete ühenduses serveriga nime abil, mis kehtib ainult teie võrgus, mistõttu ei saa väline sertifitseerimisorgan selle omandiõigust valideerida. Kuna mõni sertifitseerimisorgan väljastab sertifikaate hoolimata nende nimedest, puudub igasugune võimalus tagada, et olete ühenduses soovitud veebisaidi, mitte ründajaga.</translation>
+<translation id="7449109375006139765">Saadab süsteemilogid haldusserverisse</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Vaadake lisateavet<ph name="END_LINK" /> probleemi kohta.</translation>
<translation id="7455133967321480974">Kasuta globaalset vaikeseadet (blokeeri)</translation>
<translation id="7460618730930299168">Filtreerimine erineb valitust. Kas jätkata?</translation>
<translation id="7473891865547856676">Tänan, ei</translation>
+<translation id="7475525192983021547">Edastab perioodid, millal kasutaja on seadmes aktiivne</translation>
<translation id="7481312909269577407">Edasta</translation>
<translation id="7485870689360869515">Andmeid ei leitud.</translation>
<translation id="7508255263130623398">Tagastatud reegli seadme-ID on tühi või ei kattu praeguse seadme-ID-ga</translation>
@@ -1096,6 +1111,7 @@ Lisateave:
<translation id="7995512525968007366">Ei ole määratud</translation>
<translation id="800218591365569300">Sulgege muud vahelehed või programmid, et mälu vabastada.</translation>
<translation id="8009225694047762179">Halda paroole</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{See kaart ja selle arveldusaadress salvestatakse. Saate seda kasutada, kui olete kontole <ph name="USER_EMAIL" /> sisse logitud.}other{Need kaardid ja nende arveldusaadressid salvestatakse. Saate neid kasutada, kui olete kontole <ph name="USER_EMAIL" /> sisse logitud.}}</translation>
<translation id="8012647001091218357">Teie vanematega ei õnnestunud praegu ühendust võtta. Proovige hiljem uuesti.</translation>
<translation id="8025119109950072390">Sellel saidil asuvad ründajad võivad teid meelitada ohtlikele tegevustele, nagu tarkvara installimine või isiklike andmete (nt paroolid, telefoninumbrid või krediitkaardid) avaldamine.</translation>
<translation id="8034522405403831421">Leht on <ph name="SOURCE_LANGUAGE" /> keeles. Kas tõlkida <ph name="TARGET_LANGUAGE" /> keelde?</translation>
@@ -1106,6 +1122,7 @@ Lisateave:
<translation id="8041940743680923270">Kasuta globaalset vaikeseadet (küsi)</translation>
<translation id="8042918947222776840">Valige kättesaamisviis</translation>
<translation id="8057711352706143257">Tarkvara „<ph name="SOFTWARE_NAME" />” ei ole õigesti seadistatud. Tarkvara „<ph name="SOFTWARE_NAME" />” desinstallimine lahendab tavaliselt probleemi. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Teie seade on seadistatud järgmiseks.</translation>
<translation id="8078141288243656252">Pööramisel ei saa märkusi lisada</translation>
<translation id="8079031581361219619">Kas laadida sait uuesti?</translation>
<translation id="8088680233425245692">Artikli kuvamine ebaõnnestus.</translation>
@@ -1156,6 +1173,7 @@ Lisateave:
<translation id="8363502534493474904">Lülitage lennurežiim välja</translation>
<translation id="8364627913115013041">Määramata.</translation>
<translation id="8368476060205742148">Google Play teenused</translation>
+<translation id="8371889962595521444">Kohandatud juursertifikaadid</translation>
<translation id="8380941800586852976">Ohtlik</translation>
<translation id="8381674639488873545">Tasud võivad olla ühekordsed või korduvad ja need ei pruugi olla ilmselged. <ph name="BEGIN_LINK" />Kuva siiski<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Teie hiljuti külastatud järjehoidjad kuvatakse siin</translation>
@@ -1165,6 +1183,7 @@ Lisateave:
<translation id="8416694386774425977">Võrgu seadistus on sobimatu ja seda ei saa importida.
Lisateave:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Seadet haldab <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Muuda</translation>
<translation id="8428213095426709021">Seaded</translation>
@@ -1225,6 +1244,7 @@ Lisateave:
<translation id="8932102934695377596">Teie kell on taga</translation>
<translation id="893332455753468063">Nime lisamine</translation>
<translation id="8938939909778640821">Aktsepteeritavad ettemakstud ja krediitkaardid</translation>
+<translation id="894185898663964645">Teie administraator on seadistanud kohandatud juursertifikaadid, mille loal võib administraator teie külastatud veebisaitide sisu näha.</translation>
<translation id="8943282376843390568">Laimiroheline</translation>
<translation id="8957210676456822347">Kontrollportaali volitamine</translation>
<translation id="8968766641738584599">Salvesta kaart</translation>
diff --git a/chromium/components/strings/components_strings_fa.xtb b/chromium/components/strings/components_strings_fa.xtb
index 7400493645c..f1d4c2eb083 100644
--- a/chromium/components/strings/components_strings_fa.xtb
+++ b/chromium/components/strings/components_strings_fa.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">صفحه‌های <ph name="LANGUAGE" /> ترجمه نخواهند شد.</translation>
<translation id="2053553514270667976">کد پستی</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{۱ پیشنهاد}one{# پیشنهاد}other{# پیشنهاد}}</translation>
+<translation id="2068124040035837596">حسابتان توسط <ph name="ENROLLMENT_DOMAIN" /> مدیریت می‌شود. این یعنی سرپرستتان می‌تواند حسابتان را ازراه‌دور پیکربندی کند.</translation>
<translation id="2068663545051464999">شناسه گزارش خرابی بارگذاری‌شده <ph name="CRASH_ID" /> (زمینه محلی: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">لغو</translation>
<translation id="20817612488360358">تنظیمات پروکسی سیستم تنظیم شده تا مورد استفاده قرار گیرد، اما یک پیکربندی مشخص برای پروکسی نیز تعیین شده است.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">این روش ارسال در دسترس نیست. روش دیگری را امتحان کنید.</translation>
<translation id="2396249848217231973">&amp;واگرد حذف</translation>
<translation id="2413528052993050574">این سرور نتوانست اثبات کند که این <ph name="DOMAIN" /> است؛ ممکن است گواهی امنیتی آن باطل شده باشد. ممکن است علت این موضوع پیکربندی اشتباه باشد یا مهاجمی اتصال شما را قطع کرده است.</translation>
+<translation id="244665789865330679">دستگاه و حسابتان توسط <ph name="ENROLLMENT_DOMAIN" /> مدیریت می‌شود. این یعنی سرپرستتان می‌تواند دستگاه و حسابتان را ازراه‌دور پیکربندی کند.</translation>
<translation id="2463193859425327265">صفحه اصلی را تغییر دهید</translation>
<translation id="2463739503403862330">تکمیل</translation>
<translation id="2465655957518002998">انتخاب روش ارسال</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">شما سعی در دسترسی به <ph name="DOMAIN" /> را داشتید، اما صادر کننده، گواهی ارائه شده از سوی سرور را باطل کرده است. یعنی اصلاً نباید به اطلاعات کاربری که این سرور ارائه می‌کند اطمینان کرد. ممکن است شما با مهاجمی در ارتباط باشید.</translation>
<translation id="4378154925671717803">تلفن</translation>
<translation id="4406896451731180161">نتایج جستجو</translation>
+<translation id="4406972042435603828">سرپرستتان افزونه‌هایی با قابلیت‌های قدرتمندی نصب کرده است.</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> کوکی</translation>
<translation id="4415426530740016218">نشانی تحویل گرفتن</translation>
<translation id="4424024547088906515">‏این سرور نتوانست اثبات کند که این <ph name="DOMAIN" /> است؛ گواهی امنیتی آن مورداعتماد Chrome نیست. ممکن است علت این موضوع پیکربندی اشتباه باشد یا مهاجی اتصال شما را قطع کرده است.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">نتیجه‌ای پیدا نشد</translation>
<translation id="4950898438188848926">‏دکمه جابه‌جایی برگه، برای جابه‌جایی به برگه باز، کلید Enter را فشار دهید، <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">کنش‌ها</translation>
+<translation id="495832697253704892">گزارش افزونه</translation>
<translation id="4958444002117714549">بزرگ کردن فهرست</translation>
<translation id="4974590756084640048">فعال کردن مجدد اخطارها</translation>
<translation id="4989163558385430922">دیدن همه</translation>
<translation id="4989809363548539747">این افزایه پشتیبانی نمی‌شود</translation>
+<translation id="4996230189582812866">گزارش‌دهی</translation>
<translation id="5002932099480077015">‏اگر فعال شود، Chrome یک کپی از کارت شما را برای پرکردن سریع‌تر فرم در این دستگاه ذخیره می‌کند.</translation>
<translation id="5014174725590676422">‏صفحه اولین اجرای «دستیار Google» در Chrome نشان داده می‌شود</translation>
<translation id="5015510746216210676">نام ماشین:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">ایالت</translation>
<translation id="5094747076828555589">‏این سرور نتوانست اثبات کند که این <ph name="DOMAIN" /> است؛ گواهی امنیت آن مورداعتماد Chromium نیست. علت این موضوع می‌توان پیکربندی اشتباه باشد یا مهاجمی اتصال شما را قطع کرده است.</translation>
<translation id="5095208057601539847">استان</translation>
+<translation id="5098222253617183465">دستگاهتان توسط <ph name="ENROLLMENT_DOMAIN" /> مدیریت می‌شود و حسابتان توسط <ph name="ACCOUNT_DOMAIN" /> مدیریت می‌شود. این یعنی سرپرستتان می‌تواند دستگاه و حسابتان را ازراه‌دور پیکربندی کند.</translation>
<translation id="5115563688576182185">(۶۴ بیت)</translation>
<translation id="5128122789703661928">جلسه‌ای با این نام، برای حذف معتبر نیست.</translation>
<translation id="5135404736266831032">مدیریت نشانی‌ها…</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">دستگاه</translation>
<translation id="5179510805599951267">به زبان <ph name="ORIGINAL_LANGUAGE" /> نیست؟ گزارش این خطا</translation>
<translation id="5190835502935405962">نوار نشانک‌ها</translation>
+<translation id="5200263511887412697">فهرست کاربران دستگاه را که اخیراً وارد سیستم شده‌اند گزارش می‌دهد</translation>
<translation id="5201306358585911203">صفحه جاسازی‌شده‌ای در این صفحه می‌گوید</translation>
<translation id="5205222826937269299">نام ضروری است</translation>
<translation id="5215116848420601511">‏روش‌های پرداخت و نشانی‌های مورداستفاده در Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">دسترسی به این سایت امکان‌پذیر نیست</translation>
<translation id="5869522115854928033">گذرواژه‌های ذخیره‌شده</translation>
<translation id="5887400589839399685">کارت ذخیره‌ شد</translation>
+<translation id="5893718151540690985">فهرستی از واسط‌های شبکه را همراه با نوع و نشانی سخت‌افزاری آن‌ها گزارش می‌کند</translation>
<translation id="5893752035575986141">کارت‌های اعتباری پذیرفته می‌شوند.</translation>
<translation id="5901630391730855834">زرد</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (همگام‌سازی‌شده)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">ویرایش اطلاعات تماس</translation>
<translation id="5967867314010545767">حذف از سابقه</translation>
<translation id="5975083100439434680">دورنمایی کردن</translation>
+<translation id="5977489021191000276">دستگاهتان توسط سرپرست مدیریت نمی‌شود.</translation>
<translation id="5977976211062815271">در این دستگاه</translation>
<translation id="598637245381783098">برنامه پرداخت باز نشد</translation>
<translation id="5989320800837274978">‏سرور پروکسی ثابت و URL اسکریپت pac. تعیین نشده‌اند.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">مهاجم‌ها در <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> می‌توانند برنامه‌های فریب‌دهنده‌ای نصب کنند که وانمود می‌کنند چیز دیگری هستند یا داده‌هایی جمع‌آوری کنند که ممکن است برای ردیابی شما استفاده شوند. <ph name="BEGIN_LEARN_MORE_LINK" />بیشتر بدانید<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />، <ph name="TYPE_2" />، <ph name="TYPE_3" /> (همگام‌سازی‌شده)</translation>
<translation id="6027201098523975773">نامی وارد کنید</translation>
+<translation id="6033927989869462158">‏آمار سخت‌افزاری مانند استفاده از CPU یا RAM را گزارش می‌کند</translation>
<translation id="6034000775414344507">خاکستری کم‌رنگ</translation>
<translation id="6039846035001940113">اگر مشکل ادامه دارد، با مالک سایت تماس بگیرید.</translation>
<translation id="6040143037577758943">بستن</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">نماینده کاربر</translation>
<translation id="6903319715792422884">‏با ارسال برخی <ph name="BEGIN_WHITEPAPER_LINK" />اطلاعات سیستم و محتوای صفحه<ph name="END_WHITEPAPER_LINK" /> به Google، به بهبود «مرور ایمن» کمک کنید. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">کاربر:</translation>
+<translation id="6934672428414710184">‏این نام از حساب Google شما گرفته شده است</translation>
+<translation id="6939583532829045966">دستگاهتان توسط <ph name="ENROLLMENT_DOMAIN" /> مدیریت می‌شود. این یعنی سرپرستتان می‌تواند دستگاهتان را ازراه‌دور پیکربندی کند.</translation>
<translation id="6944692733090228304">گذرواژه‌تان را در سایتی وارد کردید که توسط <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> مدیریت نمی‌شود. برای محافظت از حسابتان، از گذرواژه‌تان در برنامه‌ها و سایت‌های دیگر استفاده نکنید.</translation>
<translation id="6945221475159498467">انتخاب</translation>
<translation id="6948701128805548767">برای دیدن روش‌های تحویل گرفتن و شرایط موردنیاز، یک نشانی انتخاب کنید</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;روی &lt;strong&gt;اعمال&lt;/strong&gt; و سپس &lt;strong&gt;تأیید&lt;/strong&gt; کلیک کنید
&lt;li&gt;برای آشنایی با نحوه برداشتن دائم نرم‌افزار از رایانه، از &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;مرکز راهنمای ‏Chrome‏&lt;/a&gt; بازدید کنید
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">مدیریت <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">مدیریت گذرواژه‌ها…</translation>
<translation id="7419106976560586862">مسیر نمایه</translation>
<translation id="7437289804838430631">افرودن اطلاعات تماس</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">نارنجی روشن</translation>
<translation id="7444046173054089907">این سایت مسدود شده است</translation>
<translation id="7445762425076701745">هویت سروری که به آن متصل شده‌اید به‌طور کامل راستی‌آزمایی نمی‌شود. با استفاده از نامی به سرور متصل شده‌اید که فقط در شبکه شما معتبر است و ارائه دهنده مجوز خارجی قادر به راستی‌آزمایی مالکیت آن نیست. به دلیل آنکه برخی از ارائه دهندگان مجوز بدون توجه به هر موردی، مجوزهایی را برای این نام‌ها ارائه می‌کنند، روشی برای اطمینان از این امر وجود ندارد که آیا شما به سایت موردنظر خود متصل شده‌اید یا یک سایت مضر.</translation>
+<translation id="7449109375006139765">گزارش‌های سیستم را به سرور مدیریت ارسال کند</translation>
<translation id="7451311239929941790">درباره این مشکل <ph name="BEGIN_LINK" />بیشتر بدانید<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">استفاده از پیش‌فرض جهانی (مسدود)</translation>
<translation id="7460618730930299168">فیلم در حال نمایش با آنچه انتخاب کرده‌اید متفاوت است. ادامه می‌دهید؟</translation>
<translation id="7473891865547856676">نه متشکرم</translation>
+<translation id="7475525192983021547">دوره‌های زمانی را که کاربر در دستگاه فعال بوده است گزارش می‌کند</translation>
<translation id="7481312909269577407">ارسال کردن</translation>
<translation id="7485870689360869515">هیچ داده‌ای یافت نشد.</translation>
<translation id="7508255263130623398">شناسه دستگاه خط‌مشی برگردانده‌شده خالی است یا با شناسه کنونی دستگاه مطابقت ندارد</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">تعیین نشده</translation>
<translation id="800218591365569300">سعی کنید برگه‌ها یا برنامه‌های دیگر را ببندید تا حافظه آزاد شود.</translation>
<translation id="8009225694047762179">مدیریت گذرواژه</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{این کارت و نشانی صورت‌حساب آن ذخیره می‌شود. وقتی به سیستم <ph name="USER_EMAIL" /> وارد شوید می‌توانید از آن استفاده کنید.}one{این کارت‌ها و نشانی صورت‌حساب آن‌ها ذخیره می‌شود. وقتی به سیستم <ph name="USER_EMAIL" /> وارد شوید می‌توانید از آن‌ها استفاده کنید.}other{این کارت‌ها و نشانی صورت‌حساب آن‌ها ذخیره می‌شود. وقتی به سیستم <ph name="USER_EMAIL" /> وارد شوید می‌توانید از آن‌ها استفاده کنید.}}</translation>
<translation id="8012647001091218357">در حال حاضر نمی‌توانیم با والدینتان ارتباط برقرار کنیم. لطفاً دوباره امتحان کنید.</translation>
<translation id="8025119109950072390">مهاجمان در این سایت ممکن است شما را فریب دهند که کارهای خطرناکی مثل نصب نرم‌افزار یا ارائه اطلاعات شخصی‌تان (مثلاً گذرواژه‌ها، شماره تلفن‌ها یا کارت‌های اعتباری) انجام دهید.</translation>
<translation id="8034522405403831421">این صفحه به زبان <ph name="SOURCE_LANGUAGE" /> است. مایلید آن را به <ph name="TARGET_LANGUAGE" /> ترجمه کنید؟</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">استفاده از پیش‌فرض جهانی (سؤال شود)</translation>
<translation id="8042918947222776840">انتخاب روش تحویل گرفتن</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» درست پیکربندی نمی‌شود. معمولاً حذف‌ نصب «<ph name="SOFTWARE_NAME" />» مشکل را برطرف می‌کند. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">دستگاهتان برای این موارد پیکربندی شده است:</translation>
<translation id="8078141288243656252">در حالت چرخش نمی‌توان حاشیه‌نویسی کرد</translation>
<translation id="8079031581361219619">سایت تازه‌سازی شود؟</translation>
<translation id="8088680233425245692">مشاهده مقاله ناموفق بود.</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">خاموش کردن حالت هواپیما</translation>
<translation id="8364627913115013041">تنظیم نشده است.</translation>
<translation id="8368476060205742148">‏خدمات Google Play</translation>
+<translation id="8371889962595521444">گواهی‌نامه ریشه سفارشی</translation>
<translation id="8380941800586852976">خطرناک</translation>
<translation id="8381674639488873545">ممکن است این هزینه‌ها یک‌باره یا تکرارشونده باشند و شاید شفاف نباشند. <ph name="BEGIN_LINK" />درهرصورت نمایش داده شود<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">نشانک‌هایی که به‌تازگی از آن‌ها دیدن کرده‌اید، در اینجا نشان داده می‌شوند</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">پیکربندی شبکه نامعتبر است و نمی‌توان آن را وارد کرد.
توضیحات بیشتر:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">دستگاه تحت‌مدیریت <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">تغییر</translation>
<translation id="8428213095426709021">تنظیمات</translation>
@@ -1225,6 +1244,7 @@
<translation id="8932102934695377596">ساعت شما عقب است</translation>
<translation id="893332455753468063">افزودن نام</translation>
<translation id="8938939909778640821">کارت‌های اعتباری و پیش‌پرداخت قابل‌قبول</translation>
+<translation id="894185898663964645">سرپرستتان گواهینامه‌های ریشه سفارشی پیکربندی کرده است، که ممکن است به او اجازه دهد محتوای وب‌سایت‌هایی که بازدید می‌کنید را ببیند.</translation>
<translation id="8943282376843390568">لیمویی</translation>
<translation id="8957210676456822347">مجوز پورتال محدود</translation>
<translation id="8968766641738584599">ذخیره کارت</translation>
diff --git a/chromium/components/strings/components_strings_fi.xtb b/chromium/components/strings/components_strings_fi.xtb
index 5527c6a83ec..c4252c6fd74 100644
--- a/chromium/components/strings/components_strings_fi.xtb
+++ b/chromium/components/strings/components_strings_fi.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Kielellä <ph name="LANGUAGE" /> kirjoitettuja sivuja ei käännetä.</translation>
<translation id="2053553514270667976">Postinumero</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ehdotus}other{# ehdotusta}}</translation>
+<translation id="2068124040035837596"><ph name="ENROLLMENT_DOMAIN" /> ylläpitää tiliäsi. Järjestelmänvalvoja voi siis määrittää tilin etäyhteydellä.</translation>
<translation id="2068663545051464999">Kaatumisraportti lähetetty, raporttitunnus: <ph name="CRASH_ID" /> (paikallinen konteksti: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Kumoa</translation>
<translation id="20817612488360358">Järjestelmän välityspalvelinasetukset on määritetty käytettäviksi, mutta erilliset välityspalvelimen asetukset on myös määritetty.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Lähetystapa ei ole käytettävissä. Kokeile toista tapaa.</translation>
<translation id="2396249848217231973">K&amp;umoa poisto</translation>
<translation id="2413528052993050574">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; sen suojausvarmenne ei välttämättä ole voimassa. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
+<translation id="244665789865330679"><ph name="ENROLLMENT_DOMAIN" /> ylläpitää laitettasi ja tiliäsi. Järjestelmänvalvoja voi siis määrittää laitteen ja tilin etäyhteydellä.</translation>
<translation id="2463193859425327265">Vaihda etusivua</translation>
<translation id="2463739503403862330">Täytä</translation>
<translation id="2465655957518002998">Valitse jakelutapa</translation>
@@ -562,6 +564,7 @@
<translation id="4377125064752653719">Yritit yhdistää sivustoon <ph name="DOMAIN" />, mutta varmenteen myöntäjä on kumonnut palvelimen esittämän varmenteen. Palvelimen esittämiin suojaustietoihin ei siis tule luottaa. Saatat olla tekemisissä hakkerin kanssa.</translation>
<translation id="4378154925671717803">Puhelin</translation>
<translation id="4406896451731180161">hakutulokset</translation>
+<translation id="4406972042435603828">Järjestelmänvalvojat ovat asentaneet tehokkaita laajennuksia.</translation>
<translation id="4408413947728134509">Evästeet <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Nouto-osoite</translation>
<translation id="4424024547088906515">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; Chrome ei luota sen suojausvarmenteeseen. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
@@ -633,10 +636,12 @@
<translation id="4943872375798546930">Ei tuloksia</translation>
<translation id="4950898438188848926">Välilehden vaihtopainike, siirry avoimelle välilehdelle painamalla Enter, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Toiminnot</translation>
+<translation id="495832697253704892">Laajennusraportointi</translation>
<translation id="4958444002117714549">Laajenna luettelo</translation>
<translation id="4974590756084640048">Ota varoitukset uudelleen käyttöön</translation>
<translation id="4989163558385430922">Näytä kaikki</translation>
<translation id="4989809363548539747">Tätä laajennusta ei tueta.</translation>
+<translation id="4996230189582812866">Raportointi</translation>
<translation id="5002932099480077015">Kun tämä vaihtoehto on käytössä, Chrome nopeuttaa lomakkeiden täyttämistä tallentamalla kortin tiedot tälle laittelle.</translation>
<translation id="5014174725590676422">Chromen Google Assistantin ensimmäisen käyttökerran näyttö näkyy</translation>
<translation id="5015510746216210676">Laitteen nimi:</translation>
@@ -657,6 +662,7 @@
<translation id="5089810972385038852">Osavaltio/alue</translation>
<translation id="5094747076828555589">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; Chromium ei luota sen suojausvarmenteeseen. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
<translation id="5095208057601539847">Provinssi</translation>
+<translation id="5098222253617183465"><ph name="ENROLLMENT_DOMAIN" /> ylläpitää laitettasi ja <ph name="ACCOUNT_DOMAIN" /> tiliäsi. Järjestelmänvalvojat voivat siis määrittää laitteen ja tilin etäyhteydellä.</translation>
<translation id="5115563688576182185">(64-bittinen)</translation>
<translation id="5128122789703661928">Tämännimistä käyttökertaa ei voi poistaa.</translation>
<translation id="5135404736266831032">Hallinnoi osoitteita…</translation>
@@ -669,6 +675,7 @@
<translation id="5172758083709347301">Kaikki tietokoneen käyttäjät</translation>
<translation id="5179510805599951267">Eikö kieli ole <ph name="ORIGINAL_LANGUAGE" />? Ilmoita virheestä</translation>
<translation id="5190835502935405962">Kirjanmerkkipalkki</translation>
+<translation id="5200263511887412697">Ilmoittaa luettelon viime aikoina sisäänkirjautuneista laitteen käyttäjistä</translation>
<translation id="5201306358585911203">Viesti tälle sivulle upotetulta sivulta</translation>
<translation id="5205222826937269299">Nimi vaaditaan</translation>
<translation id="5215116848420601511">Maksutavat ja osoitteet Google Paysta</translation>
@@ -770,6 +777,7 @@
<translation id="5869405914158311789">Sivustoon ei saada yhteyttä</translation>
<translation id="5869522115854928033">Tallennetut salasanat</translation>
<translation id="5887400589839399685">Kortti tallennettu</translation>
+<translation id="5893718151540690985">Ilmoittaa luettelon verkon käyttöliittymistä, niiden tyypeistä ja laitteisto-osoitteista</translation>
<translation id="5893752035575986141">Luottokortit hyväksytään.</translation>
<translation id="5901630391730855834">Keltainen</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synkronoitu)</translation>
@@ -783,6 +791,7 @@
<translation id="5967592137238574583">Muokkaa yhteystietoja</translation>
<translation id="5967867314010545767">Poista historiasta</translation>
<translation id="5975083100439434680">Loitonna</translation>
+<translation id="5977489021191000276">Järjestelmänvalvoja ei ylläpidä laitettasi.</translation>
<translation id="5977976211062815271">Tällä laitteella</translation>
<translation id="598637245381783098">Maksusovelluksen avaaminen ei onnistu.</translation>
<translation id="5989320800837274978">Kiinteitä välityspalvelimia tai .pac-URL-osoitetta ei ole määritetty.</translation>
@@ -794,6 +803,7 @@
<translation id="6017850046339264347">Sivuston <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> hyökkääjät voivat asentaa harhaanjohtavia sovelluksia, jotka teeskentelevät olevansa jotain muuta tai keräävät tietoja, joiden avulla ne voivat seurata sinua. <ph name="BEGIN_LEARN_MORE_LINK" />Lisätietoja<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synkronoitu)</translation>
<translation id="6027201098523975773">Kirjoita nimi</translation>
+<translation id="6033927989869462158">Ilmoittaa laitetilastoja esimerkiksi CPU:n/RAM-muistin käytöstä</translation>
<translation id="6034000775414344507">Vaaleanharmaa</translation>
<translation id="6039846035001940113">Jos ongelma jatkuu, ota yhteyttä sivuston omistajaan.</translation>
<translation id="6040143037577758943">Sulje</translation>
@@ -906,6 +916,8 @@
<translation id="6897140037006041989">User agent</translation>
<translation id="6903319715792422884">Auta kehittämään selaussuojaa lähettämällä tiettyjä <ph name="BEGIN_WHITEPAPER_LINK" />järjestelmätietoa ja sivujen sisältöä<ph name="END_WHITEPAPER_LINK" /> Googlelle. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Käyttäjä:</translation>
+<translation id="6934672428414710184">Tämä nimi on peräisin Google-tililtäsi</translation>
+<translation id="6939583532829045966"><ph name="ENROLLMENT_DOMAIN" /> ylläpitää laitettasi. Järjestelmänvalvoja voi siis määrittää laitteen etäyhteydellä.</translation>
<translation id="6944692733090228304">Kirjoitit salasanan sivustolle, jota <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ei ylläpidä. Älä käytä samaa salasanaa muissa sovelluksissa tai muilla sivustoilla tilisi turvallisuuden vuoksi.</translation>
<translation id="6945221475159498467">Valitse</translation>
<translation id="6948701128805548767">Valitse osoite, niin näet noutotavat ja vaatimukset.</translation>
@@ -993,6 +1005,7 @@ Lisätietoja:
&lt;li&gt;Valitse &lt;strong&gt;Käytä&lt;/strong&gt; ja sen jälkeen &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;Saat ohjeita ohjelmiston pysyvään poistamiseen tietokoneelta &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome-ohjekeskuksesta&lt;/a&gt;.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" />: ylläpito</translation>
<translation id="7416351320495623771">Ylläpidä salasanoja…</translation>
<translation id="7419106976560586862">Profiilin polku</translation>
<translation id="7437289804838430631">Lisää yhteystieto</translation>
@@ -1001,10 +1014,12 @@ Lisätietoja:
<translation id="7442725080345379071">Vaaleanoranssi</translation>
<translation id="7444046173054089907">Tämä sivusto on estetty</translation>
<translation id="7445762425076701745">Palvelimen, johon olet muodostanut yhteyden, identiteettiä ei voi täysin todentaa. Tietokoneesi on yhdistetty palvelimeen sellaisen nimen avulla, joka on kelvollinen vain verkkosi sisällä ja jonka omistajaa ulkopuolinen varmenteen myöntäjä ei pysty todentamaan. Koska jotkin varmenteen myöntäjät kuitenkin myöntävät varmenteita tällaisille nimille, et voi varmistaa, että olet muodostanut yhteyden haluamaasi verkkosivustoon etkä hakkeriin.</translation>
+<translation id="7449109375006139765">Lähettää järjestelmälokeja hallintapalvelimelle</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />tiedonhakua<ph name="END_LINK" /> ongelmaan liittyen</translation>
<translation id="7455133967321480974">Käytä yleistä oletusasetusta (estä)</translation>
<translation id="7460618730930299168">Näkymä eroaa valinnoistasi. Haluatko jatkaa?</translation>
<translation id="7473891865547856676">Ei kiitos</translation>
+<translation id="7475525192983021547">Ilmoittaa ajanjaksoista, jolloin käyttäjä on käyttänyt laitetta</translation>
<translation id="7481312909269577407">Seuraava</translation>
<translation id="7485870689360869515">Tietoja ei löydy.</translation>
<translation id="7508255263130623398">Palautettu käytännön laitetunnus on tyhjä tai ei vastaa nykyistä laitetunnusta.</translation>
@@ -1097,6 +1112,7 @@ Lisätietoja:
<translation id="7995512525968007366">Ei määritetty</translation>
<translation id="800218591365569300">Yritä vapauttaa muistia sulkemalla muita välilehtiä tai ohjelmia.</translation>
<translation id="8009225694047762179">Salasanojen hallinta</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Tämä kortti ja sen laskutusosoite tallennetaan. Voit käyttää sitä sisäänkirjautuneena (<ph name="USER_EMAIL" />).}other{Nämä kortit ja niiden laskutusosoitteet tallennetaan. Voit käyttää niitä sisäänkirjautuneena (<ph name="USER_EMAIL" />).}}</translation>
<translation id="8012647001091218357">Emme tavoittaneet vanhempiasi. Yritä uudelleen.</translation>
<translation id="8025119109950072390">Tälle sivustolle hyökännyt taho voi yrittää huijata sinua tekemään jotain vaarallista, kuten asentamaan ohjelmistoja tai paljastamaan henkilötietojasi (esimerkiksi salasanoja, puhelinnumeroita tai luottokorttitietoja).</translation>
<translation id="8034522405403831421">Sivu on kirjoitettu kielellä <ph name="SOURCE_LANGUAGE" />. Haluatko kääntää sen kielelle <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1107,6 +1123,7 @@ Lisätietoja:
<translation id="8041940743680923270">Käytä yleistä oletusasetusta (kysy)</translation>
<translation id="8042918947222776840">Valitse noutotapa</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> on määritetty virheellisesti. Ongelma korjaantuu yleensä, jos <ph name="SOFTWARE_NAME" /> poistetaan. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Laitteen määritykset:</translation>
<translation id="8078141288243656252">Kierrettyyn asiakirjaan ei voi tehdä merkintöjä</translation>
<translation id="8079031581361219619">Ladataanko sivusto uudelleen?</translation>
<translation id="8088680233425245692">Artikkelin näyttäminen epäonnistui.</translation>
@@ -1157,6 +1174,7 @@ Lisätietoja:
<translation id="8363502534493474904">Poista lentokonetila käytöstä.</translation>
<translation id="8364627913115013041">Ei määritetty.</translation>
<translation id="8368476060205742148">Google Play Palvelut</translation>
+<translation id="8371889962595521444">Yksilöidyt juurivarmenteet</translation>
<translation id="8380941800586852976">Vaarallinen</translation>
<translation id="8381674639488873545">Veloitukset voivat olla kertaluontoisia tai toistuvia, eikä niitä välttämättä esitetä selkeästi. <ph name="BEGIN_LINK" />Näytä silti<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Viimeksi käyttämäsi kirjanmerkit näkyvät tässä.</translation>
@@ -1166,6 +1184,7 @@ Lisätietoja:
<translation id="8416694386774425977">Verkkoasetukset ovat virheelliset eikä niitä voi tuoda.
Lisätietoja:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Laitteen ylläpitäjä: <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Vaihda</translation>
<translation id="8428213095426709021">Asetukset</translation>
@@ -1227,6 +1246,7 @@ Lisätietoja:
<translation id="8932102934695377596">Kellosi jätättää</translation>
<translation id="893332455753468063">Lisää nimi</translation>
<translation id="8938939909778640821">Hyväksytyt luotto- ja prepaid-kortit</translation>
+<translation id="894185898663964645">Järjestelmänvalvoja on määrittänyt yksilöidyt juurivarmenteet, joiden avulla hän voi mahdollisesti nähdä avaamiesi verkkosivustojen sisällön.</translation>
<translation id="8943282376843390568">Lime</translation>
<translation id="8957210676456822347">Captive portal -valtuutus</translation>
<translation id="8968766641738584599">Tallenna kortti</translation>
diff --git a/chromium/components/strings/components_strings_fil.xtb b/chromium/components/strings/components_strings_fil.xtb
index 7903ccfb867..ccfe5680a84 100644
--- a/chromium/components/strings/components_strings_fil.xtb
+++ b/chromium/components/strings/components_strings_fil.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Hindi ita-translate ang mga page na nasa <ph name="LANGUAGE" />.</translation>
<translation id="2053553514270667976">ZIP code</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suhestyon}one{# suhestyon}other{# na suhestyon}}</translation>
+<translation id="2068124040035837596">Pinapamahalaan ng <ph name="ENROLLMENT_DOMAIN" /> ang iyong account. Nangangahulugan itong maaaring malayuang i-configure ng iyong administrator ang account mo.</translation>
<translation id="2068663545051464999">ID ng Na-upload na Ulat ng Pag-crash <ph name="CRASH_ID" /> (Lokal na Konteksto: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">I-undo</translation>
<translation id="20817612488360358">Itinatakda ang mga setting ng proxy ng system upang magamit ngunit tinutukoy rin ang isang tahasang configuration ng proxy.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Hindi available ang pamamaraan ng pagpapadala na ito. Sumubok ng ibang pamamaraan.</translation>
<translation id="2396249848217231973">&amp;I-undo ang pagtanggal</translation>
<translation id="2413528052993050574">Hindi mapatunayan ng server na ito na ito ay <ph name="DOMAIN" />; maaaring binawi ang certificate ng seguridad nito. Maaaring dulot ito ng maling configuration o isang umaatake na hinahadlangan ang iyong koneksyon.</translation>
+<translation id="244665789865330679">Pinapamahalaan ng <ph name="ENROLLMENT_DOMAIN" /> ang iyong device at account. Nangangahulugan itong maaaring malayuang i-configure ng iyong administrator ang device at account mo.</translation>
<translation id="2463193859425327265">Baguhin ang Home Page</translation>
<translation id="2463739503403862330">Punan</translation>
<translation id="2465655957518002998">Pumili ng Paraan ng Paghahatid</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Tinangka mong maabot ang <ph name="DOMAIN" />, subalit ang certificate na ipinakita ng server ay binawi ng nagbigay nito. Nangangahulugan ito na ang mga kredensyal sa seguridad na ipinakita ng server ay talagang hindi dapat pagkatiwalaan. Maaaring nakikipag-ugnay ka sa isang nang-aatake.</translation>
<translation id="4378154925671717803">Telepono</translation>
<translation id="4406896451731180161">mga resulta ng paghahanap</translation>
+<translation id="4406972042435603828">Ang iyong mga administrator ay may mga naka-install na extension na may mahuhusay na kakayahan.</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Address sa Pag-pick up</translation>
<translation id="4424024547088906515">Hindi mapatunayan ng server na ito na ito ay <ph name="DOMAIN" />; hindi pinagkakatiwalaan ng Chrome ang certificate ng seguridad nito. Maaaring dulot ito ng maling configuration o isang umaatake na hinahadlangan ang iyong koneksyon.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Walang mga resulta</translation>
<translation id="4950898438188848926">Button sa paglipat ng tab, pindutin ang Enter para lumipat sa nakabukas na tab, na <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Mga Pagkilos</translation>
+<translation id="495832697253704892">Pag-uulat ng extension</translation>
<translation id="4958444002117714549">Palawakin ang listahan</translation>
<translation id="4974590756084640048">Muling i-enable ang mga babala</translation>
<translation id="4989163558385430922">Tingnan lahat</translation>
<translation id="4989809363548539747">Hindi sinusuportahan ang plugin na ito</translation>
+<translation id="4996230189582812866">Pag-uulat</translation>
<translation id="5002932099480077015">Kung naka-enable, mag-iimbak ang Chrome ng kopya ng iyong card sa device na ito para sa mas mabilis na pagsagot sa form.</translation>
<translation id="5014174725590676422">Ipinapakita ang screen ng unang pagtakbo ng Google Assistant sa Chrome</translation>
<translation id="5015510746216210676">Pangalan ng Machine:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Estado</translation>
<translation id="5094747076828555589">Hindi mapatunayan ng server na ito na ito ay <ph name="DOMAIN" />; hindi pinagkakatiwalaan ng Chromium ang certificate ng seguridad nito. Maaaring dulot ito ng maling configuration o isang umaatake na hinahadlangan ang iyong koneksyon.</translation>
<translation id="5095208057601539847">Lalawigan</translation>
+<translation id="5098222253617183465">Pinapamahalaan ng <ph name="ENROLLMENT_DOMAIN" /> ang iyong device at pinapamahalaan ng <ph name="ACCOUNT_DOMAIN" /> ang account mo. Nangangahulugan itong maaaring malayuang i-configure ng iyong mga administrator ang device at account mo.</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5128122789703661928">Hindi valid ang session na may ganitong pangalan upang ma-delete.</translation>
<translation id="5135404736266831032">Pamahalaan ang mga address...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Wala sa <ph name="ORIGINAL_LANGUAGE" />? Iulat ang error na ito</translation>
<translation id="5190835502935405962">Bar ng Mga Bookmark</translation>
+<translation id="5200263511887412697">nag-uulat ng listahan ng mga user ng device na kamakailang nag-log in</translation>
<translation id="5201306358585911203">Isinasaad ng naka-embed na page sa page na ito na</translation>
<translation id="5205222826937269299">Kailangan ng pangalan</translation>
<translation id="5215116848420601511">Mga paraan ng pagbabayad at address gamit ang Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Hindi makakonekta sa site na ito</translation>
<translation id="5869522115854928033">Mga naka-save na password</translation>
<translation id="5887400589839399685">Na-save ang card</translation>
+<translation id="5893718151540690985">nag-uulat ng listahan ng mga interface ng network kasama ang mga uri at mga address ng hardware ng mga ito</translation>
<translation id="5893752035575986141">Tinatanggap ang mga credit card.</translation>
<translation id="5901630391730855834">Dilaw</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (naka-sync)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">I-edit ang Impormasyon ng Contact</translation>
<translation id="5967867314010545767">Alisin sa history</translation>
<translation id="5975083100439434680">Mag-zoom out</translation>
+<translation id="5977489021191000276">Hindi pinapamahalaan ng administrator ang iyong device.</translation>
<translation id="5977976211062815271">Sa device na ito</translation>
<translation id="598637245381783098">Hindi mabuksan ang app sa pagbabayad</translation>
<translation id="5989320800837274978">Hindi tunukoy ang alinman sa mga hindi nababagong proxy server o isang .pac script URL.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Ang mga umaatake sa <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ay maaaring mag-install ng mga mapanlinlang na app na nagpapanggap na ibang bagay o nangongolekta ng data na maaaring gamitin upang subaybayan ka. <ph name="BEGIN_LEARN_MORE_LINK" />Matuto pa<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (naka-sync)</translation>
<translation id="6027201098523975773">Maglagay ng pangalan</translation>
+<translation id="6033927989869462158">nag-uulat ng mga istatistika ng hardware tulad ng paggamit sa CPU/RAM</translation>
<translation id="6034000775414344507">Light Grey</translation>
<translation id="6039846035001940113">Kung magpapatuloy ang problema, makipag-ugnayan sa may-ari ng site.</translation>
<translation id="6040143037577758943">Isara</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">User Agent</translation>
<translation id="6903319715792422884">Tumulong sa pagpapahusay ng Ligtas na Pag-browse sa pamamagitan ng pagpapadala sa Google ng ilang <ph name="BEGIN_WHITEPAPER_LINK" />impormasyon ng system at content ng page<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">User:</translation>
+<translation id="6934672428414710184">Nagmula ang pangalang ito sa iyong Google Account</translation>
+<translation id="6939583532829045966">Pinapamahalaan ng <ph name="ENROLLMENT_DOMAIN" /> ang iyong device. Nangangahulugan itong maaaring malayuang i-configure ng iyong administrator ang device mo.</translation>
<translation id="6944692733090228304">Inilagay mo ang iyong password sa site na hindi pinapamahalaan ng <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Para protektahan ang iyong account, huwag gamiting muli ang password mo sa iba pang app at site.</translation>
<translation id="6945221475159498467">Pumili</translation>
<translation id="6948701128805548767">Upang makita ang mga pamamaraan at kinakailangan sa pag-pick up, pumili ng address</translation>
@@ -992,6 +1004,7 @@ Mga karagdagang detalye:
&lt;li&gt;I-click ang &lt;strong&gt;Apply&lt;/strong&gt;, pagkatapos ay i-click ang &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Bisitahin ang &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;help center ng Chrome&lt;/a&gt; para matutunan kung paano permanenteng alisin ang software sa iyong computer
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Pamamahala ng <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Pamahalaan ang Mga Password...</translation>
<translation id="7419106976560586862">Path ng Profile</translation>
<translation id="7437289804838430631">Magdagdag ng Impormasyon ng Contact</translation>
@@ -1000,10 +1013,12 @@ Mga karagdagang detalye:
<translation id="7442725080345379071">Light Orange</translation>
<translation id="7444046173054089907">Naka-block ang site na ito</translation>
<translation id="7445762425076701745">Hindi ganap na mapatunayan ang pagkakakilanlan ng server na konektado ka. Konektado ka sa server gamit ang pangalan na angkop lamang sa loob ng iyong network, na walang paraan ang panglabas na certificate authority na patunayan ang pagmamay-ari. Dahil magbibigay ang ilang kinauukulan sa certificate para sa mga pangalang ito, walang paraan upang matiyak na konektado ka sa nilayong website at hindi isang umaatake.</translation>
+<translation id="7449109375006139765">magpadala sa server ng pamamahala ng mga log ng system</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Matuto nang higit pa<ph name="END_LINK" /> tungkol sa problemang ito.</translation>
<translation id="7455133967321480974">Gamitin ang pangkalahatang default (I-block)</translation>
<translation id="7460618730930299168">Iba ang screening sa napili mo. Magpatuloy?</translation>
<translation id="7473891865547856676">Hindi, Salamat</translation>
+<translation id="7475525192983021547">nag-uulat ng mga yugto ng panahon kapag aktibo sa device ang isang user</translation>
<translation id="7481312909269577407">Sumulong</translation>
<translation id="7485870689360869515">Walang nahanap na data.</translation>
<translation id="7508255263130623398">Walang laman ang ibinalik na device id ng patakaran o hindi ito tumutugma sa kasalukuyang device id</translation>
@@ -1096,6 +1111,7 @@ Mga karagdagang detalye:
<translation id="7995512525968007366">Hindi Tinukoy</translation>
<translation id="800218591365569300">Subukang isara ang iba pang tab o program upang magbakante ng memory.</translation>
<translation id="8009225694047762179">Pamahalaan ang Mga Password</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Ise-save ang card na ito at ang billing address nito. Magagamit mo ito kapag nag-sign in ka sa <ph name="USER_EMAIL" />.}one{Ise-save ang mga card na ito at ang mga billing address ng mga ito. Magagamit mo ang mga ito kapag nag-sign in ka sa <ph name="USER_EMAIL" />.}other{Ise-save ang mga card na ito at ang mga billing address ng mga ito. Magagamit mo ang mga ito kapag nag-sign in ka sa <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Hindi namin makaugnayan ang iyong mga magulang sa sandaling ito. Pakisubukang muli.</translation>
<translation id="8025119109950072390">Maaari kang linlangin ng mga attacker sa site na ito na gumawa ng mga bagay na mapanganib tulad ng pag-i-install ng software o pagbubunyag ng iyong personal na impormasyon (halimbawa, mga password, numero ng telepono o credit card).</translation>
<translation id="8034522405403831421">Nasa <ph name="SOURCE_LANGUAGE" /> ang pahinang ito. Isalin ito sa <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Mga karagdagang detalye:
<translation id="8041940743680923270">Gamitin ang pangkalahatang default (Tanungin)</translation>
<translation id="8042918947222776840">Pumili ng Paraan ng Pag-pick up</translation>
<translation id="8057711352706143257">Hindi maayos na naka-configure ang "<ph name="SOFTWARE_NAME" />." Kadalasang naaayos ang problema kapag in-uninstall ang "<ph name="SOFTWARE_NAME" />." <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Na-configure ang iyong device na:</translation>
<translation id="8078141288243656252">Hindi maaaring i-annotate kapag naka-rotate</translation>
<translation id="8079031581361219619">I-reload ang site?</translation>
<translation id="8088680233425245692">Hindi natingnan ang artikulo.</translation>
@@ -1156,6 +1173,7 @@ Mga karagdagang detalye:
<translation id="8363502534493474904">I-off ang airplane mode</translation>
<translation id="8364627913115013041">Hindi nakatakda.</translation>
<translation id="8368476060205742148">Mga serbisyo ng Google Play</translation>
+<translation id="8371889962595521444">Mga custom na root certificate</translation>
<translation id="8380941800586852976">Mapanganib</translation>
<translation id="8381674639488873545">Ang mga singil na ito ay maaaring isang beses o umuulit, at maaaring hindi mapansin. <ph name="BEGIN_LINK" />Ipakita pa rin<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Lalabas dito ang iyong mga kamakailang binisitang bookmark</translation>
@@ -1165,6 +1183,7 @@ Mga karagdagang detalye:
<translation id="8416694386774425977">Invalid ang configuration ng network at hindi ito ma-import.
Mga karagdagang detalye:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Pinapamahalaan ng <ph name="ENROLLMENT_DOMAIN" /> ang device</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Baguhin</translation>
<translation id="8428213095426709021">Mga Setting</translation>
@@ -1225,6 +1244,7 @@ Mga karagdagang detalye:
<translation id="8932102934695377596">Nahuhuli ang iyong orasan</translation>
<translation id="893332455753468063">Magdagdag ng Pangalan</translation>
<translation id="8938939909778640821">Mga tinatanggap na credit at prepaid card</translation>
+<translation id="894185898663964645">Ang iyong administrator ay may mga naka-configure na custom na root certificate na maaaring payagan ang administrator na makita ang mga content ng mga website na binibisita mo.</translation>
<translation id="8943282376843390568">Lime</translation>
<translation id="8957210676456822347">Pagpapahintulot sa Captive Portal</translation>
<translation id="8968766641738584599">I-save ang card</translation>
diff --git a/chromium/components/strings/components_strings_fr.xtb b/chromium/components/strings/components_strings_fr.xtb
index a33f1b85a75..fbd1b68a04e 100644
--- a/chromium/components/strings/components_strings_fr.xtb
+++ b/chromium/components/strings/components_strings_fr.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Les pages en <ph name="LANGUAGE" /> ne seront pas traduites.</translation>
<translation id="2053553514270667976">Code postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestion}one{# suggestion}other{# suggestions}}</translation>
+<translation id="2068124040035837596">Votre compte est géré par <ph name="ENROLLMENT_DOMAIN" />. Cela signifie que votre administrateur peut configurer votre compte à distance.</translation>
<translation id="2068663545051464999">ID du rapport d'erreur importé : <ph name="CRASH_ID" /> (Contexte local : <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Annuler</translation>
<translation id="20817612488360358">Les paramètres de proxy du système sont configurés pour être utilisés, mais une configuration de proxy explicite est également spécifiée.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Mode d'expédition non disponible. Choisissez-en un autre.</translation>
<translation id="2396249848217231973">&amp;Annuler la suppression</translation>
<translation id="2413528052993050574">Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />. Il se peut que son certificat de sécurité ait été révoqué. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.</translation>
+<translation id="244665789865330679">Votre appareil et votre compte sont gérés par <ph name="ENROLLMENT_DOMAIN" />. Cela signifie que votre administrateur peut configurer votre appareil et votre compte à distance.</translation>
<translation id="2463193859425327265">Changer de page d'accueil</translation>
<translation id="2463739503403862330">Remplir</translation>
<translation id="2465655957518002998">Sélectionner un mode d'expédition</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Vous avez tenté d'accéder à <ph name="DOMAIN" />, mais le certificat présenté par le serveur a été révoqué par son émetteur. Cela signifie que le certificat présenté par le serveur ne doit pas être approuvé. Il est donc possible que vous communiquiez avec un pirate informatique.</translation>
<translation id="4378154925671717803">Téléphone</translation>
<translation id="4406896451731180161">résultats de recherche</translation>
+<translation id="4406972042435603828">Vos administrateurs ont installé des extensions aux capacités puissantes.</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Adresse d'enlèvement</translation>
<translation id="4424024547088906515">Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />, car son certificat de sécurité n'est pas considéré comme fiable par Chrome. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Aucun résultat</translation>
<translation id="4950898438188848926">Bouton pour changer d'onglet (appuyez sur Entrée pour passer à l'onglet ouvert, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />)</translation>
<translation id="495170559598752135">Actions</translation>
+<translation id="495832697253704892">Création de rapports sur les extensions installées d'office</translation>
<translation id="4958444002117714549">Développer la liste</translation>
<translation id="4974590756084640048">Réactiver les avertissements</translation>
<translation id="4989163558385430922">Tout afficher</translation>
<translation id="4989809363548539747">Ce plug-in n'est pas compatible.</translation>
+<translation id="4996230189582812866">Création de rapports</translation>
<translation id="5002932099480077015">Si cette option est activée, Chrome enregistre une copie de votre carte sur cet appareil pour vous permettre de remplir plus rapidement les formulaires.</translation>
<translation id="5014174725590676422">L'écran de première utilisation de l'Assistant Google dans Chrome est affiché</translation>
<translation id="5015510746216210676">Nom de la machine :</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">État</translation>
<translation id="5094747076828555589">Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />, car son certificat de sécurité n'est pas considéré comme fiable par Chromium. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.</translation>
<translation id="5095208057601539847">Province</translation>
+<translation id="5098222253617183465">Votre appareil est géré par <ph name="ENROLLMENT_DOMAIN" /> et votre compte est géré par <ph name="ACCOUNT_DOMAIN" />. Cela signifie que vos administrateurs peuvent configurer votre appareil et votre compte à distance.</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5128122789703661928">Impossible de supprimer la session qui porte ce nom.</translation>
<translation id="5135404736266831032">Gérer les adresses…</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Ordinateur</translation>
<translation id="5179510805599951267">Cette page n'est pas rédigée en <ph name="ORIGINAL_LANGUAGE" /> ? Signaler l'erreur</translation>
<translation id="5190835502935405962">Barre de favoris</translation>
+<translation id="5200263511887412697">générer une liste des utilisateurs qui se sont récemment connectés à l'appareil</translation>
<translation id="5201306358585911203">Une page intégrée à cette page Web indique</translation>
<translation id="5205222826937269299">Veuillez saisir un nom</translation>
<translation id="5215116848420601511">Modes de paiement et adresses utilisés dans Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Ce site est inaccessible</translation>
<translation id="5869522115854928033">Mots de passe enregistrés</translation>
<translation id="5887400589839399685">Carte enregistrée</translation>
+<translation id="5893718151540690985">générer une liste d'interfaces réseau, avec leur type et leur adresse matérielle sur le serveur</translation>
<translation id="5893752035575986141">Les cartes de crédit sont acceptées.</translation>
<translation id="5901630391730855834">Jaune</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synchronisés)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Modifier les coordonnées</translation>
<translation id="5967867314010545767">Supprimer de l'historique</translation>
<translation id="5975083100439434680">Zoom arrière</translation>
+<translation id="5977489021191000276">Votre appareil n'est pas géré par un administrateur.</translation>
<translation id="5977976211062815271">Sur cet appareil</translation>
<translation id="598637245381783098">Impossible d'ouvrir l'application de paiement</translation>
<translation id="5989320800837274978">Aucun serveur proxy déterminé ou URL de script .pac n'a été indiqué.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Les pirates informatiques qui contrôlent le site <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> peuvent installer des applications trompeuses se faisant passer pour d'autres, ou collecter des données afin de vous surveiller. <ph name="BEGIN_LEARN_MORE_LINK" />En savoir plus<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synchronisés)</translation>
<translation id="6027201098523975773">Saisissez un nom</translation>
+<translation id="6033927989869462158">envoyer des rapports sur les statistiques matérielles tels que l'utilisation du processeur et de la RAM</translation>
<translation id="6034000775414344507">Gris clair</translation>
<translation id="6039846035001940113">Si le problème persiste, contactez le propriétaire du site.</translation>
<translation id="6040143037577758943">Fermer</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Agent utilisateur</translation>
<translation id="6903319715792422884">Aidez-nous à améliorer la navigation sécurisée en nous envoyant <ph name="BEGIN_WHITEPAPER_LINK" />des informations système et du contenu de pages<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Utilisateur :</translation>
+<translation id="6934672428414710184">Ce nom provient de votre compte Google</translation>
+<translation id="6939583532829045966">Votre appareil est géré par <ph name="ENROLLMENT_DOMAIN" />. Cela signifie que votre administrateur peut configurer votre appareil à distance.</translation>
<translation id="6944692733090228304">Vous avez saisi votre mot de passe sur un site qui n'est pas géré par <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Pour protéger votre compte, ne réutilisez pas ce mot de passe dans d'autres applications ni sur d'autres sites.</translation>
<translation id="6945221475159498467">Sélectionner</translation>
<translation id="6948701128805548767">Sélectionnez une adresse pour consulter les modes et conditions d'enlèvement disponibles</translation>
@@ -992,6 +1004,7 @@ Informations supplémentaires :
&lt;li&gt;Cliquez sur &lt;strong&gt;Appliquer&lt;/strong&gt;, puis sur &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Pour savoir comment supprimer définitivement le logiciel de votre ordinateur, consultez le &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centre d'aide Chrome&lt;/a&gt;
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Gestion de <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Gérer les mots de passe…</translation>
<translation id="7419106976560586862">Chemin d'accès au profil</translation>
<translation id="7437289804838430631">Ajouter des coordonnées</translation>
@@ -1000,10 +1013,12 @@ Informations supplémentaires :
<translation id="7442725080345379071">Orange clair</translation>
<translation id="7444046173054089907">Ce site est bloqué</translation>
<translation id="7445762425076701745">Impossible de valider entièrement l'identité du serveur auquel vous êtes connecté. Le nom utilisé pour cette connexion n'est valide que sur votre réseau et aucune autorité de certification externe ne peut en vérifier la propriété. Certaines autorités de certification délivrent tout de même des certificats pour ces types de nom, par conséquent nous ne sommes pas en mesure de vérifier que vous êtes connecté au site voulu et non à un site malveillant.</translation>
+<translation id="7449109375006139765">envoyer des journaux système au serveur de gestion</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />En savoir plus<ph name="END_LINK" /> sur ce problème.</translation>
<translation id="7455133967321480974">Utiliser le paramètre global par défaut ("Bloquer")</translation>
<translation id="7460618730930299168">Le filtrage est différent de ce que vous avez sélectionné. Continuer ?</translation>
<translation id="7473891865547856676">Non, merci</translation>
+<translation id="7475525192983021547">envoyer des rapports sur les périodes d'activité d'un utilisateur sur un appareil</translation>
<translation id="7481312909269577407">Avancer</translation>
<translation id="7485870689360869515">Aucune donnée n'a été trouvée.</translation>
<translation id="7508255263130623398">L'ID d'appareil de la règle renvoyé est vide ou ne correspond pas à l'ID d'appareil actuel.</translation>
@@ -1096,6 +1111,7 @@ Informations supplémentaires :
<translation id="7995512525968007366">Non spécifié</translation>
<translation id="800218591365569300">Essayez de fermer les autres onglets ou programmes pour libérer de la mémoire.</translation>
<translation id="8009225694047762179">Gérer les mots de passe</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Cette carte et l'adresse de facturation associée seront enregistrées. Vous pourrez vous en servir lorsque vous serez connecté à <ph name="USER_EMAIL" />.}one{Cette carte et l'adresse de facturation associée seront enregistrées. Vous pourrez vous en servir lorsque vous serez connecté à <ph name="USER_EMAIL" />.}other{Ces cartes et les adresses de facturation associées seront enregistrées. Vous pourrez vous en servir lorsque vous serez connecté à <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Impossible de joindre vos parents pour le moment. Veuillez réessayer.</translation>
<translation id="8025119109950072390">Des individus malveillants à l'œuvre sur ce site pourraient vous inciter à effectuer des opérations dangereuses, telles que l'installation d'un logiciel ou la révélation d'informations personnelles (par exemple des mots de passe, des numéros de téléphone ou des numéros de carte de paiement).</translation>
<translation id="8034522405403831421">Cette page est rédigée en <ph name="SOURCE_LANGUAGE" />. Voulez-vous la traduire en <ph name="TARGET_LANGUAGE" /> ?</translation>
@@ -1106,6 +1122,7 @@ Informations supplémentaires :
<translation id="8041940743680923270">Utiliser le paramètre global par défaut ("Demander")</translation>
<translation id="8042918947222776840">Sélectionner un mode d'enlèvement</translation>
<translation id="8057711352706143257">Le logiciel "<ph name="SOFTWARE_NAME" />" n'est pas configuré correctement. En général, la désinstallation de "<ph name="SOFTWARE_NAME" />" permet de remédier à la situation. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Votre appareil a été configuré comme suit :</translation>
<translation id="8078141288243656252">Impossible d'ajouter des annotations si le document a pivoté</translation>
<translation id="8079031581361219619">Actualiser le site Web ?</translation>
<translation id="8088680233425245692">Échec de l'affichage de l'article.</translation>
@@ -1156,6 +1173,7 @@ Informations supplémentaires :
<translation id="8363502534493474904">Désactiver le mode Avion</translation>
<translation id="8364627913115013041">Non définie</translation>
<translation id="8368476060205742148">Services Google Play</translation>
+<translation id="8371889962595521444">Certificats racines personnalisés</translation>
<translation id="8380941800586852976">Dangereux</translation>
<translation id="8381674639488873545">Il peut s'agir de frais uniques ou récurrents qui ne sont pas toujours clairement signalés. <ph name="BEGIN_LINK" />Je souhaite accéder malgré tout à ce site<ph name="END_LINK" />.</translation>
<translation id="8382348898565613901">Vos favoris récemment consultés s'affichent ici</translation>
@@ -1165,6 +1183,7 @@ Informations supplémentaires :
<translation id="8416694386774425977">Impossible d'importer la configuration du réseau : elle n'est pas valide.
Informations supplémentaires :
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Appareil géré par <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Modifier</translation>
<translation id="8428213095426709021">Paramètres</translation>
@@ -1225,6 +1244,7 @@ Informations supplémentaires :
<translation id="8932102934695377596">Votre horloge est en retard</translation>
<translation id="893332455753468063">Ajouter un nom</translation>
<translation id="8938939909778640821">Cartes de crédit et cartes prépayées acceptées</translation>
+<translation id="894185898663964645">Votre administrateur a configuré des certificats racines personnalisés, qui peuvent permettre à l'administrateur de voir le contenu des sites Web que vous consultez.</translation>
<translation id="8943282376843390568">Citron vert</translation>
<translation id="8957210676456822347">Autorisation du portail captif</translation>
<translation id="8968766641738584599">Enregistrer la carte</translation>
diff --git a/chromium/components/strings/components_strings_gu.xtb b/chromium/components/strings/components_strings_gu.xtb
index b8a1488fe5a..fd2300cbba1 100644
--- a/chromium/components/strings/components_strings_gu.xtb
+++ b/chromium/components/strings/components_strings_gu.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" />માં લખાયેલાં પેજનો અનુવાદ થશે નહીં.</translation>
<translation id="2053553514270667976">પિન કોડ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 સૂચન}one{# સૂચન}other{# સૂચન}}</translation>
+<translation id="2068124040035837596">તમારું એકાઉન્ટ <ph name="ENROLLMENT_DOMAIN" /> દ્વારા મેનેજ કરવામાં આવે છે. આનો અર્થ છે કે તમારા વ્યવસ્થાપક રિમોટલી તમારું એકાઉન્ટ ગોઠવી શકે છે.</translation>
<translation id="2068663545051464999">ક્રૅશ રિપોર્ટ ID <ph name="CRASH_ID" /> અપલોડ કર્યું (સ્થાનિક સંદર્ભ: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">છેલ્લો ફેરફાર રદ કરો</translation>
<translation id="20817612488360358">સિસ્ટમ પ્રૉક્સી સેટિંગ ઉપયોગમાં લેવા માટે સેટ છે પણ એક સ્પષ્ટ પ્રૉક્સી ગોઠવણીનો પણ ઉલ્લેખ કરાયેલો છે.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">આ વિતરણ પદ્ધતિ ઉપલબ્ધ નથી. કોઈ ભિન્ન પદ્ધતિ અજમાવો.</translation>
<translation id="2396249848217231973">&amp;ડિલીટ રદ કરો</translation>
<translation id="2413528052993050574">આ સર્વર સાબિત કરી શક્યું નથી કે તે <ph name="DOMAIN" /> છે; તેનું સુરક્ષા પ્રમાણપત્ર રદબાતલ થયું હશે. આ કોઈ ખોટી ગોઠવણીને કારણે થયું હશે અથવા કોઈ હુમલાખોર તમારા કનેક્શનને અટકાવી રહ્યો છે.</translation>
+<translation id="244665789865330679">તમારું ડિવાઇસ અને એકાઉન્ટ <ph name="ENROLLMENT_DOMAIN" /> દ્વારા મેનેજ કરવામાં આવે છે. આનો અર્થ છે કે તમારા વ્યવસ્થાપક તમારા ડિવાઇસ અને એકાઉન્ટને રિમોટલી ગોઠવી શકે છે.</translation>
<translation id="2463193859425327265">હોમ પેજ બદલો</translation>
<translation id="2463739503403862330">ભરો</translation>
<translation id="2465655957518002998">વિતરણ પદ્ધતિ પસંદ કરો</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719">તમે <ph name="DOMAIN" /> પર પહોંચવાનો પ્રયાસ કર્યો, પણ સર્વર દ્વારા પ્રસ્તુત કરવામાં આવેલું પ્રમાણપત્ર તેના રજૂકર્તા દ્વારા જ રદ કરવામાં આવ્યું છે. આનો અર્થ છે કે સર્વરે પ્રસ્તુત કરેલા સુરક્ષા પ્રમાણપત્રો પૂર્ણપણે વિશ્વસનીય નથી. તમે કોઈ હુમલાખોર જોડે વાત કરતા હોઈ શકો છો.</translation>
<translation id="4378154925671717803">ફોન</translation>
<translation id="4406896451731180161">શોધ પરિણામો</translation>
+<translation id="4406972042435603828">તમારા વ્યવસ્થાપકોએ શક્તિશાળી ક્ષમતાઓવાળા એક્સ્ટેન્શન ઇન્સ્ટૉલ કર્યા છે.</translation>
<translation id="4408413947728134509">કુકી <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">પિકઅપ માટેનું સરનામું</translation>
<translation id="4424024547088906515">આ સર્વર સાબિત કરી શક્યું નથી કે તે <ph name="DOMAIN" /> છે; તેનું સુરક્ષા પ્રમાણપત્ર Chrome દ્વારા વિશ્વસનીય નથી. આ કોઈ ખોટી ગોઠવણીને કારણે થયું હશે અથવા કોઈ હુમલાખોર તમારા કનેક્શનને અટકાવી રહ્યો છે.</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">પરિણામો નથી</translation>
<translation id="4950898438188848926">ટૅબ, સ્વિચ બટન, ખુલ્લા ટૅબ, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /> પર સ્વિચ કરવા માટે Enter દબાવો</translation>
<translation id="495170559598752135">ક્રિયાઓ</translation>
+<translation id="495832697253704892">એક્સ્ટેન્શનની જાણ કરવી</translation>
<translation id="4958444002117714549">સૂચિ વિસ્તૃત કરો</translation>
<translation id="4974590756084640048">ચેતવણીઓ ફરીથી ચાલુ કરો</translation>
<translation id="4989163558385430922">બધા જુઓ</translation>
<translation id="4989809363548539747">આ પ્લગ-ઇન સમર્થિત નથી</translation>
+<translation id="4996230189582812866">જાણ કરવી</translation>
<translation id="5002932099480077015">જો સક્ષમ કરેલું હોય, તો ઝડપથી ફોર્મ ભરવા માટે Chrome આ ઉપકરણ પર તમારા કાર્ડની એક કૉપિ સંગ્રહશે.</translation>
<translation id="5014174725590676422">Chromeમાં Google આસિસ્ટંટની પહેલી સ્ક્રીન બતાવવામાં આવી છે</translation>
<translation id="5015510746216210676">મશીનનું નામ:</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">રાજ્ય</translation>
<translation id="5094747076828555589">આ સર્વર સાબિત કરી શક્યું નથી કે તે <ph name="DOMAIN" /> છે; તેનું સુરક્ષા પ્રમાણપત્ર Chromium દ્વારા વિશ્વસનીય નથી. આ કોઈ ખોટી ગોઠવણીને કારણે થયું હશે અથવા કોઈ હુમલાખોર તમારા કનેક્શનને અટકાવી રહ્યો છે.</translation>
<translation id="5095208057601539847">પ્રાંત</translation>
+<translation id="5098222253617183465">તમારું ડિવાઇસ <ph name="ENROLLMENT_DOMAIN" /> દ્વારા મેનેજ કરવામાં આવે છે અને તમારું એકાઉન્ટ <ph name="ACCOUNT_DOMAIN" /> દ્વારા મેનેજ કરવામાં આવે છે. આનો અર્થ છે કે તમારા વ્યવસ્થાપકો રિમોટલી તમારા ડિવાઇસને અને એકાઉન્ટને ગોઠવી શકે છે.</translation>
<translation id="5115563688576182185">(64-બિટ)</translation>
<translation id="5128122789703661928">આ નામવાળું સત્ર ડિલીટ કરવા માટે માન્ય નથી.</translation>
<translation id="5135404736266831032">સરનામા મેનેજ કરો…</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">મશીન</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> માં નથી? આ ભૂલની જાણ કરો </translation>
<translation id="5190835502935405962">બુકમાર્ક્સ બાર</translation>
+<translation id="5200263511887412697">તાજેતરમાં લૉગ ઇન કરેલા ડિવાઇસ વપરાશકર્તાઓની રિપોર્ટ સૂચિ</translation>
<translation id="5201306358585911203">આ પેજ પરનું શામેલ કરેલ પેજ કહે છે કે</translation>
<translation id="5205222826937269299">નામ આવશ્યક છે</translation>
<translation id="5215116848420601511">Google Payનો ઉપયોગ કરતી ચુકવણી પદ્ધતિઓ અને ઍડ્રેસ</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">આ સાઇટ પર પહોંચી શકાતું નથી</translation>
<translation id="5869522115854928033">સાચવેલા પાસવર્ડ્સ</translation>
<translation id="5887400589839399685">કાર્ડ સાચવ્યું</translation>
+<translation id="5893718151540690985">નેટવર્ક ઇન્ટરફેસની સૂચિની તેમના પ્રકાર અને હાર્ડવેર સરનામાં સાથે જાણ કરો</translation>
<translation id="5893752035575986141">ક્રેડિટ કાર્ડ સ્વીકારવામાં આવે છે.</translation>
<translation id="5901630391730855834">પીળો</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (સમન્વયિત)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">સંપર્ક માહિતીમાં ફેરફાર કરો</translation>
<translation id="5967867314010545767">ઇતિહાસમાંથી દૂર કરો</translation>
<translation id="5975083100439434680">ઝૂમ ઘટાડો</translation>
+<translation id="5977489021191000276">તમારું ડિવાઇસ વ્યવસ્થાપક દ્વારા મેનેજ કરવામાં આવતું નથી.</translation>
<translation id="5977976211062815271">આ ડિવાઇસ પર</translation>
<translation id="598637245381783098">ચુકવણી ઍપ્લિકેશન ખોલી શકાતી નથી</translation>
<translation id="5989320800837274978">ફિક્સ્ડ પ્રૉક્સી સર્વર કે .pac સ્ક્રિપ્ટ URL, બેમાંથી કોઈનો પણ ઉલ્લેખ કરેલો નથી.</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347">હુમલાખોરો <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> પર ભ્રામક ઍપ્લિકેશન ઇન્સ્ટૉલ કરી શકે છે જે કંઈક બીજું હોવાનો ડોળ કરે છે અથવા તમને ટ્રૅક કરવા માટે ઉપયોગમાં લઈ શકાય તેવો ડેટા એકત્રિત કરી શકે છે. <ph name="BEGIN_LEARN_MORE_LINK" />વધુ જાણો<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (સમન્વયિત)</translation>
<translation id="6027201098523975773">એક નામ દાખલ કરો</translation>
+<translation id="6033927989869462158">CPU/RAM વપરાશ જેવા હાર્ડવેર આંકડાની જાણ કરો</translation>
<translation id="6034000775414344507">આછો ગ્રે</translation>
<translation id="6039846035001940113">જો સમસ્યા ચાલુ રહે, તો સાઇટના માલિકનો સંપર્ક કરો.</translation>
<translation id="6040143037577758943">બંધ કરો</translation>
@@ -904,6 +914,8 @@
<translation id="6897140037006041989">વપરાશકર્તા એજન્ટ</translation>
<translation id="6903319715792422884">Googleને અમુક <ph name="BEGIN_WHITEPAPER_LINK" />સિસ્ટમ માહિતી અને પેજ કન્ટેન્ટ<ph name="END_WHITEPAPER_LINK" />મોકલીને સલામત બ્રાઉઝિંગ બહેતર બનાવવામાં સહાય કરો. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">વપરાશકર્તા: </translation>
+<translation id="6934672428414710184">આ નામ તમારા Google એકાઉન્ટમાંથી લીધું છે</translation>
+<translation id="6939583532829045966">તમારું ડિવાઇસ <ph name="ENROLLMENT_DOMAIN" /> દ્વારા મેનેજ કરવામાં આવે છે. આનો અર્થ છે કે તમારા વ્યવસ્થાપક તમારા ડિવાઇસને રિમોટલી ગોઠવી શકે છે.</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> દ્વારા સંચાલિત ન થતી હોય, તેવી સાઇટ પર તમે તમારો પાસવર્ડ દાખલ કર્યો છે. તમારા એકાઉન્ટની સુરક્ષા માટે, અન્ય ઍપ અને સાઇટ પર તમારા પાસવર્ડનો ફરી ઉપયોગ ન કરો.</translation>
<translation id="6945221475159498467">પસંદ કરો</translation>
<translation id="6948701128805548767">પિકઅપ પદ્ધતિ અને આવશ્યકતાઓ જોવા માટે, એક સરનામું પસંદ કરો</translation>
@@ -991,6 +1003,7 @@
&lt;li&gt;&lt;strong&gt;લાગુ કરો&lt;/strong&gt; પર ક્લિક કરો, પછી &lt;strong&gt;ઓકે&lt;/strong&gt; પર ક્લિક કરો
&lt;li&gt;તમારા કમ્પ્યુટર પરથી સૉફ્ટવેરને કાયમી ધોરણે કાઢી નાંખવાની રીત જાણવા માટે, &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome સહાયતા કેન્દ્ર&lt;/a&gt; પર જાઓ
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" />મેનેજમેન્ટ</translation>
<translation id="7416351320495623771">પાસવર્ડ મેનેજ કરો…</translation>
<translation id="7419106976560586862">પ્રોફાઇલ પાથ</translation>
<translation id="7437289804838430631">સંપર્ક માહિતી ઉમેરો</translation>
@@ -999,10 +1012,12 @@
<translation id="7442725080345379071">આછો નારંગી</translation>
<translation id="7444046173054089907">આ સાઇટ અવરોધિત છે</translation>
<translation id="7445762425076701745">તમે જે સર્વરથી કનેક્ટ છો તેની ઓળખ સંપૂર્ણ રૂપે માન્ય કરી શકાતી નથી. તમે જે નામનો ઉપયોગ કરીને સર્વરથી કનેક્ટ છો, તે ફક્ત તમારા નેટવર્કની અંતર્ગત જ માન્ય છે, જેના બાહ્ય પ્રમાણપત્ર અધિકારીને માલિકીને માન્ય કરવાની કોઈ રીત નથી. આના પર ધ્યાન આપ્યાં વગર કેટલાક પ્રમાણપત્ર અધિકારીઓ આ નામો માટે પ્રમાણપત્ર બહાર પાડશે, તેથી તમે ઇચ્છિત વેબસાઇટથી કનેક્ટ છો કોઈ હુમલાખોરથી નહીં, તેની ખાતરી કરવાની કોઈ રીત નથી.</translation>
+<translation id="7449109375006139765">મેનેજમેન્ટ સર્વર પર સિસ્ટમ લૉગ મોકલવા</translation>
<translation id="7451311239929941790">આ સમસ્યા વિશે <ph name="BEGIN_LINK" />વધુ જાણો<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">વૈશ્વિક ડિફોલ્ટનો ઉપયોગ કરો (અવરોધિત કરો)</translation>
<translation id="7460618730930299168">તમે પસંદ કર્યું તેનાથી સ્ક્રીનિંગ અલગ છે. ચાલુ રાખીએ?</translation>
<translation id="7473891865547856676">નહીં આભાર</translation>
+<translation id="7475525192983021547">જ્યારે વપરાશકર્તા ડિવાઇસ પર સક્રિય હોય તે સમયગાળાઓની જાણ કરો</translation>
<translation id="7481312909269577407">ફોર્વર્ડ કરો</translation>
<translation id="7485870689360869515">કોઈ ડેટા મળ્યો નથી.</translation>
<translation id="7508255263130623398">પરત થયેલ નીતિ ઉપકરણ id ખાલી છે અથવા વર્તમાન ટોકન સાથે મેળ ખાતું નથી</translation>
@@ -1095,6 +1110,7 @@
<translation id="7995512525968007366">નિર્દિષ્ટ કરાયેલ નથી</translation>
<translation id="800218591365569300">મેમરી ખાલી કરવા માટે અન્ય ટૅબ અથવા પ્રોગ્રામને બંધ કરવાનો પ્રયાસ કરો.</translation>
<translation id="8009225694047762179">બધા પાસવર્ડ મેનેજ કરો</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{આ કાર્ડ અને તેનું બિલિંગ સરનામું સાચવવામાં આવશે. જ્યારે <ph name="USER_EMAIL" />માં સાઇન ઇન કર્યું હશે ત્યારે તમે તેનો ઉપયોગ કરી શકશો.}one{આ કાર્ડ અને તેના બિલિંગ સરનામાં સાચવવામાં આવશે. જ્યારે <ph name="USER_EMAIL" />માં સાઇન ઇન કર્યું હશે ત્યારે તમે તેમનો ઉપયોગ કરી શકશો.}other{આ કાર્ડ અને તેના બિલિંગ સરનામાં સાચવવામાં આવશે. જ્યારે <ph name="USER_EMAIL" />માં સાઇન ઇન કર્યું હશે ત્યારે તમે તેમનો ઉપયોગ કરી શકશો.}}</translation>
<translation id="8012647001091218357">અમે આ પળે તમારા વાલીઓ સુધી પહોંચી શક્યાં નથી. કૃપા કરીને ફરી પ્રયાસ કરો.</translation>
<translation id="8025119109950072390">આ સાઇટ પરના હુમલાખોરો તમારી વ્યક્તિગત માહિતી (ઉદાહરણ તરીકે, પાસવર્ડ, ફોન નંબર અથવા ક્રેડિટ કાર્ડ)ને દર્શાવવા અથવા સોફ્ટવેર ઇન્સ્ટૉલ કરવા જેવી જોખમી વસ્તુઓને કરવા માટે તમને છેતરવાનો પ્રયાસ કરી શકે છે.</translation>
<translation id="8034522405403831421">આ પૃષ્ઠ <ph name="SOURCE_LANGUAGE" /> માં છે. શું તેનો અનુવાદ <ph name="TARGET_LANGUAGE" /> માં કરીએ?</translation>
@@ -1105,6 +1121,7 @@
<translation id="8041940743680923270">વૈશ્વિક ડિફોલ્ટનો ઉપયોગ કરો (કહો)</translation>
<translation id="8042918947222776840">પિકઅપ પદ્ધતિ પસંદ કરો</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />"ની ગોઠવણી યોગ્ય રીતે કરવામાં આવી નથી. સામાન્ય રીતે "<ph name="SOFTWARE_NAME" />"ને અનઇન્સ્ટૉલ કરવાથી સમસ્યા હલ થઈ જાય છે. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">તમારું ડિવાઇસ આવું ગોઠવ્યું છે:</translation>
<translation id="8078141288243656252">ફેરવેલ હોય ત્યારે એનોટેટ કરી શકતા નથી</translation>
<translation id="8079031581361219619">સાઇટ ફરીથી લોડ કરીએ?</translation>
<translation id="8088680233425245692">લેખ જોવામાં નિષ્ફળ.</translation>
@@ -1155,6 +1172,7 @@
<translation id="8363502534493474904">એરપ્લેન મોડ બંધ કરીને</translation>
<translation id="8364627913115013041">સેટ નથી.</translation>
<translation id="8368476060205742148">Google Play સેવાઓ</translation>
+<translation id="8371889962595521444">કસ્ટમ રૂટ પ્રમાણપત્રો</translation>
<translation id="8380941800586852976">જોખમી</translation>
<translation id="8381674639488873545">આ શુલ્ક એક વખત લાગે અથવા પુનરાવર્તિત હોઈ શકે અને તેનો સ્પષ્ટ ખ્યાલ ન આવે તેમ પણ બને. <ph name="BEGIN_LINK" />તો પણ બતાવો<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">તમારા તાજેતરમાં મુલાકાત લીધેલ બુકમાર્ક્સ અહીં દેખાય છે</translation>
@@ -1164,6 +1182,7 @@
<translation id="8416694386774425977">નેટવર્કની ગોઠવણી અમાન્ય છે અને તેને આયાત કરી શકાઈ નથી.
વધારાની વિગતો:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533"><ph name="ENROLLMENT_DOMAIN" /> દ્વારા મેનેજ કરાતું ડિવાઇસ</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">બદલો</translation>
<translation id="8428213095426709021">સેટિંગ્સ</translation>
@@ -1224,6 +1243,7 @@
<translation id="8932102934695377596">તમારી ઘડિયાળ પાછળ છે</translation>
<translation id="893332455753468063">નામ ઉમેરો</translation>
<translation id="8938939909778640821">સ્વીકૃત ક્રેડિટ અને પ્રીપેઇડ કાર્ડ</translation>
+<translation id="894185898663964645">તમારા વ્યવસ્થાપકે કસ્ટમ રૂટ પ્રમાણપત્રો ગોઠવ્યા છે, જે વ્યવસ્થાપકને તમે મુલાકાત લો તે વેબસાઇટના કન્ટેન્ટને જોવાની મંજૂરી આપી શકે છે.</translation>
<translation id="8943282376843390568">લાઇમ</translation>
<translation id="8957210676456822347">કૅપ્ટિવ પોર્ટલ પ્રમાણિત</translation>
<translation id="8968766641738584599">કાર્ડ સાચવો</translation>
diff --git a/chromium/components/strings/components_strings_hi.xtb b/chromium/components/strings/components_strings_hi.xtb
index 0b00c0de1a8..f47c4231d0a 100644
--- a/chromium/components/strings/components_strings_hi.xtb
+++ b/chromium/components/strings/components_strings_hi.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" /> भाषा के पेजों का अनुवाद नहीं किया जाएगा.</translation>
<translation id="2053553514270667976">ज़िप कोड</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 सुझाव}one{# सुझाव}other{# सुझाव}}</translation>
+<translation id="2068124040035837596">आपके खाते को <ph name="ENROLLMENT_DOMAIN" /> की ओर से प्रबंधित किया जाता है. इसका मतलब है कि आपका एडमिन दूर रहकर आपके खाते को कॉन्फ़िगर कर सकता है.</translation>
<translation id="2068663545051464999">अपलोड की गई खराबी रिपोर्ट आईडी <ph name="CRASH_ID" /> (स्थानीय संदर्भ : <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">वापस लाएं</translation>
<translation id="20817612488360358">सिस्‍टम प्रॉक्‍सी सेटिंग उपयोग किए जाने के लिए सेट हैं लेकिन कोई स्पष्‍ट प्रॉक्‍सी कॉन्फ़िगरेशन भी निर्दिष्ट है.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">शिपिंग का यह तरीका उपलब्ध नहीं है. कोई दूसरा तरीका आज़माएं.</translation>
<translation id="2396249848217231973">&amp;हटाना वापस लाएं</translation>
<translation id="2413528052993050574">यह सर्वर यह प्रमाणित नहीं कर सका कि यह <ph name="DOMAIN" />; इसका सुरक्षा प्रमाणपत्र निरस्त कर दिया गया है. ऐसा गलत कॉन्फ़िगरेशन के कारण या किसी आक्रमणकर्ता द्वारा आपके कनेक्शन में अवरोध डालने के कारण हो सकता है.</translation>
+<translation id="244665789865330679">आपके डिवाइस और खाते को <ph name="ENROLLMENT_DOMAIN" /> की ओर से प्रबंधित किया जाता है. इसका मतलब है कि आपका एडमिन दूर रहकर आपके डिवाइस और खाते को कॉन्फ़िगर कर सकता है.</translation>
<translation id="2463193859425327265">होम पेज बदलें</translation>
<translation id="2463739503403862330">भरें</translation>
<translation id="2465655957518002998">डिलीवरी का तरीका चुनें</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">आपने <ph name="DOMAIN" /> तक पहुंचने का प्रयास किया, लेकिन सर्वर द्वारा प्रस्तुत प्रमाणपत्र को उसके जारीकर्ता द्वारा रद्द कर दिया गया है. इसका अर्थ है कि सर्वर द्वारा प्रस्तुत सुरक्षा प्रमाणिकता पर पूर्णतया विश्वास नहीं करना चाहिए. हो सकता है कि आप किसी हमलावर से बातचीत कर रहे हों.</translation>
<translation id="4378154925671717803">फ़ोन</translation>
<translation id="4406896451731180161">खोज परिणाम</translation>
+<translation id="4406972042435603828">आपके एडमिन ने ज़्याद क्षमताओं वाले एक्सटेंशन इंस्टॉल किए हैं.</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> कुकी</translation>
<translation id="4415426530740016218">पिकअप का पता</translation>
<translation id="4424024547088906515">यह सर्वर यह नहीं प्रमाणित कर सका कि यह <ph name="DOMAIN" /> है; इसका सुरक्षा प्रमाणपत्र Chrome द्वारा विश्वसनीय नहीं है. ऐसा गलत कॉन्फ़िगरेशन या किसी आक्रमणकर्ता द्वारा आपके कनेक्शन में अवरोध डालने के कारण हो सकता है.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">कोई परिणाम नहीं</translation>
<translation id="4950898438188848926">'टैब' बदलने का बटन, नए टैब पर जाने के लिए Enter दबाएं, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">क्रियाएं</translation>
+<translation id="495832697253704892">एक्सटेंशन रिपोर्टिंग</translation>
<translation id="4958444002117714549">सूची विस्तृत करें</translation>
<translation id="4974590756084640048">चेतावनियां फिर से सक्षम करें</translation>
<translation id="4989163558385430922">सभी देखें</translation>
<translation id="4989809363548539747">यह प्लग इन समर्थित नहीं है</translation>
+<translation id="4996230189582812866">रिपोर्ट करना</translation>
<translation id="5002932099480077015">यदि सक्षम किया हुआ हो, तो Chrome फ़ॉर्म को तेज़ी से भरने के लिए इस डिवाइस पर आपके कार्ड की एक प्रति संग्रहित करेगा.</translation>
<translation id="5014174725590676422">'Chrome में Google Assistant' की सबसे पहली स्क्रीन दिखाई गई है</translation>
<translation id="5015510746216210676">मशीन का नाम:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">राज्य</translation>
<translation id="5094747076828555589">यह सर्वर यह नहीं प्रमाणित कर सका कि यह <ph name="DOMAIN" /> है; इसका सुरक्षा प्रमाणपत्र Chromium द्वारा विश्वसनीय नहीं है. ऐसा गलत कॉन्फ़िगरेशन या किसी आक्रमणकर्ता द्वारा आपके कनेक्शन में अवरोध डालने के कारण हो सकता है.</translation>
<translation id="5095208057601539847">प्रांत</translation>
+<translation id="5098222253617183465">आपके डिवाइस को <ph name="ENROLLMENT_DOMAIN" /> की ओर से प्रबंधित किया जाता है और आपके खाते को <ph name="ACCOUNT_DOMAIN" /> की ओर से प्रबंधित किया जाता है. इसका मतलब है कि आपके एडमिन दूर रहकर आपके डिवाइस और खाते को कॉन्फ़िगर कर सकते हैं.</translation>
<translation id="5115563688576182185">(64-बिट)</translation>
<translation id="5128122789703661928">इस नाम वाला सीज़न मिटाने के लिए मान्य नहीं है.</translation>
<translation id="5135404736266831032">पते प्रबंधित करें...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">मशीन</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> में नहीं है? इस गड़बड़ी की रिपोर्ट करें</translation>
<translation id="5190835502935405962">बुकमार्क बार</translation>
+<translation id="5200263511887412697">हाल ही में लॉग इन करने वाले डिवाइस उपयोगकर्ताओं की रिपोर्ट सूची</translation>
<translation id="5201306358585911203">इस पेज पर एम्बेड किए गए पेज का कहना है कि</translation>
<translation id="5205222826937269299">नाम ज़रूरी है</translation>
<translation id="5215116848420601511">Google Pay का इस्तेमाल करने वाले भुगतान के तरीके और पते</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">इस साइट तक नहीं पहुंचा जा सकता</translation>
<translation id="5869522115854928033">सहेजे गए पासवर्ड</translation>
<translation id="5887400589839399685">कार्ड सेव किया गया</translation>
+<translation id="5893718151540690985">नेटवर्क इंटरफ़ेस के प्रकारों और हार्डवेयर पतों सहित उसकी रिपोर्ट सूची</translation>
<translation id="5893752035575986141">क्रेडिट कार्ड स्वीकार किए जाते हैं.</translation>
<translation id="5901630391730855834">पीला</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (सिंक किया गया)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">संपर्क जानकारी में बदलाव करें</translation>
<translation id="5967867314010545767">इतिहास से निकालें</translation>
<translation id="5975083100439434680">ज़ूम आउट</translation>
+<translation id="5977489021191000276">आपके डिवाइस को किसी एडमिन की ओर से प्रबंधित नहीं किया जाता.</translation>
<translation id="5977976211062815271">इस डिवाइस पर</translation>
<translation id="598637245381783098">भुगतान ऐप्लिकेशन नहीं खोला जा सकता</translation>
<translation id="5989320800837274978">न तो कोई फ़िक्‍स्‍ड प्रॉक्‍सी सर्वर और न ही कोई .pac स्क्रिप्ट URL साफ़ तौर पर बताया गया है.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> पर मौजूद हमलावर ऐसे भ्रामक ऐप्लिकेशन इंस्टॉल कर सकते हैं जो कुछ और होने का दावा करते हैं या ऐसा डेटा एकत्रित करते हैं जिसका उपयोग आप पर नज़र रखने के लिए किया जा सके. <ph name="BEGIN_LEARN_MORE_LINK" />अधिक जानें<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (सिंक किए गए)</translation>
<translation id="6027201098523975773">नाम डालें</translation>
+<translation id="6033927989869462158">हार्डवेयर आंकड़ों जैसे कि सीपीयू (CPU)/RAM इस्तेमाल की रिपोर्ट करें</translation>
<translation id="6034000775414344507">हल्का भूरा</translation>
<translation id="6039846035001940113">अगर समस्या बनी रहती है, तो साइट के मालिक से संपर्क करें.</translation>
<translation id="6040143037577758943">बंद करें</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">उपयोगकर्ता एजेंट</translation>
<translation id="6903319715792422884">'सुरक्षित ब्राउज़िंग' को बेहतर बनाने में मदद करने के लिए Google को कुछ <ph name="BEGIN_WHITEPAPER_LINK" />'सिस्टम जानकारी' और 'पेज सामग्री'<ph name="END_WHITEPAPER_LINK" /> भेजें. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">उपयोगकर्ता:</translation>
+<translation id="6934672428414710184">यह नाम आपके Google खाते से है</translation>
+<translation id="6939583532829045966">आपके डिवाइस को <ph name="ENROLLMENT_DOMAIN" /> की ओर से प्रबंधित किया जाता है. इसका मतलब है कि आपका एडमिन दूर रहकर आपके डिवाइस को कॉन्फ़िगर कर सकता है.</translation>
<translation id="6944692733090228304">आपने एक ऐसी साइट पर अपना पासवर्ड डाला है जिसे <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> प्रबंधित नहीं करता है. अपने खाते को सुरक्षित रखने के लिए, दूसरे ऐप्लिकेशन और साइटों पर अपने पासवर्ड का दोबारा इस्तेमाल न करें.</translation>
<translation id="6945221475159498467">चुनें</translation>
<translation id="6948701128805548767">पिकअप के तरीके और ज़रूरतें देखने के लिए, कोई पता चुनें</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;&lt;strong&gt;लागू करें&lt;/strong&gt; पर क्लिक करें, फिर &lt;strong&gt;ठीक है&lt;/strong&gt; पर क्लिक करें
&lt;li&gt;&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome सहायता केंद्र&lt;/a&gt; पर जाकर अपने कंप्यूटर से सॉफ़्टवेयर को हमेशा के लिए हटाने का तरीका जानें
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> प्रबंधन</translation>
<translation id="7416351320495623771">पासवर्ड प्रबंधित करें…</translation>
<translation id="7419106976560586862">प्रोफ़ाइल पथ</translation>
<translation id="7437289804838430631">संपर्क जानकारी जोड़ें</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">हल्का नारंगी</translation>
<translation id="7444046173054089907">यह साइट अवरोधित है</translation>
<translation id="7445762425076701745">जिस सर्वर से आप कनेक्‍ट हैं उसकी पहचान पूर्णत: सत्‍यापित नहीं की जा सकती. आपने केवल आपके नेटवर्क में ही मान्‍य नाम का उपयोग कर किसी सर्वर से कनेक्‍ट किया है, जिसकी मान्‍यता का सत्‍यापन कोई बाह्य प्रमाणपत्र प्राधिकरण नहीं करता है. जैसा कि कुछ प्रमाणपत्र प्राधिकरण इन नामों के लिए प्रमाणपत्र जारी कर देंगे, और इस पर ध्यान नहीं दिया जाएगा कि यह सुनिश्‍चित करने का कोई तरीका नहीं है कि आप नियत वेबसाइट से कनेक्‍ट हैं, न कि किसी आक्रमणकर्ता से.</translation>
+<translation id="7449109375006139765">प्रबंधन सर्वर को सिस्टम लॉग भेजें</translation>
<translation id="7451311239929941790">इस समस्या के बारे में <ph name="BEGIN_LINK" />अधिक जानें<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">वैश्विक डिफ़ॉल्ट का उपयोग करें (अवरोधित करें)</translation>
<translation id="7460618730930299168">यह स्क्रीनिंग आपकी चुनी गई स्क्रीनिंग से अलग है. क्या आप जारी रखना चाहते हैं?</translation>
<translation id="7473891865547856676">जी रहने दें</translation>
+<translation id="7475525192983021547">किसी उपयोगकर्ता के डिवाइस पर काम करते रहने पर समय अवधि को रिपोर्ट करें</translation>
<translation id="7481312909269577407">आगे जाएं</translation>
<translation id="7485870689360869515">कोई डेटा नहीं मिला</translation>
<translation id="7508255263130623398">वापस लौटाया हुआ नीति डिवाइस आईडी खाली है या उसका मिलान वर्तमान डिवाइस आईडी से नहीं होता है</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">निर्दिष्‍ट नहीं किया गया</translation>
<translation id="800218591365569300">जगह खाली करने के लिए दूसरे टैब या प्रोग्राम बंद करके देखें.</translation>
<translation id="8009225694047762179">पासवर्ड संभालें</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{इस कार्ड और इसके बिलिंग पते को सेव किया जाएगा. <ph name="USER_EMAIL" /> में साइन इन रहने पर आप इसका इस्तेमाल कर पाएंगे.}one{ये कार्ड और इनके बिलिंग पते सेव किए जाएंगे. <ph name="USER_EMAIL" /> में साइन इन रहने पर आप उनका इस्तेमाल कर पाएंगे.}other{ये कार्ड और इनके बिलिंग पते सेव किए जाएंगे. <ph name="USER_EMAIL" /> में साइन इन रहने पर आप उनका इस्तेमाल कर पाएंगे.}}</translation>
<translation id="8012647001091218357">हम इस समय आपके अभिभावकों तक नहीं पहुंच पा रहे हैं. कृपया पुन: प्रयास करें.</translation>
<translation id="8025119109950072390">इस साइट पर मौजूद हमलावर आपको धोखा देकर आपसे कुछ जोखिम वाला काम करा सकते हैं, जैसे सॉफ़्टवेयर इंस्टॉल करना या आपकी व्यक्तिगत जानकारी (उदाहरण के लिए, पासवर्ड, फ़ोन नंबर या क्रेडिट कार्ड) प्रकट करना.</translation>
<translation id="8034522405403831421">यह पेज <ph name="SOURCE_LANGUAGE" /> में है. इसका <ph name="TARGET_LANGUAGE" /> में अनुवाद करें?</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">वैश्विक डिफ़ॉल्ट का उपयोग करें (पूछें)</translation>
<translation id="8042918947222776840">पिकअप का तरीका चुनें</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" सही तरीके से कॉन्फ़िगर नहीं किया गया है. आमतौर पर "<ph name="SOFTWARE_NAME" />" को अनइंस्टॉल करने से समस्या ठीक हो जाती है. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">आपका डिवाइस इसके लिए कॉन्फ़िगर किया गया है:</translation>
<translation id="8078141288243656252">घुमाने पर एनोटेट नहीं कर सकते</translation>
<translation id="8079031581361219619">साइट को फिर लोड करें?</translation>
<translation id="8088680233425245692">लेख देखने में विफल रहा.</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">हवाई जहाज़ मोड बंद करें</translation>
<translation id="8364627913115013041">सेट नहीं है.</translation>
<translation id="8368476060205742148">Google Play सेवाएं</translation>
+<translation id="8371889962595521444">कस्टम रूट सर्टिफ़िकेट</translation>
<translation id="8380941800586852976">खतरनाक</translation>
<translation id="8381674639488873545">ये शुल्क एक बार लगने वाले या बार-बार लगने वाले हो सकते हैं और हो सकता है कि इनके बारे में साफ़ तौर पर न बताया जाए. <ph name="BEGIN_LINK" />फिर भी दिखाएं<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">हाल ही में विज़िट किए गए आपके बुकमार्क यहां दिखाई देते हैं</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">नेटवर्क कॉन्फ़िगरेशन गलत है और उसे लाया नहीं जा सका.
ज़्यादा जानकारी:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533"><ph name="ENROLLMENT_DOMAIN" /> की ओर से प्रबंधित डिवाइस</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">बदलें</translation>
<translation id="8428213095426709021">सेटिंग</translation>
@@ -1226,6 +1245,7 @@
<translation id="8932102934695377596">आपकी घड़ी पीछे है</translation>
<translation id="893332455753468063">नाम जोड़ें</translation>
<translation id="8938939909778640821">स्वीकृत क्रेडिट और प्रीपेड कार्ड</translation>
+<translation id="894185898663964645">आपके एडमिन ने कस्टम रूट सर्टिफ़िकेट कॉन्फ़िगर किए हैं, जो एडमिन को उन वेबसाइट की सामग्री देखने दे सकते हैं जिन पर आप जाते हैं.</translation>
<translation id="8943282376843390568">नींबू पीला</translation>
<translation id="8957210676456822347">कैप्‍टिव पोर्टल प्राधिकरण</translation>
<translation id="8968766641738584599">कार्ड सेव करें</translation>
diff --git a/chromium/components/strings/components_strings_hr.xtb b/chromium/components/strings/components_strings_hr.xtb
index a255fad966f..f9a204bcf8a 100644
--- a/chromium/components/strings/components_strings_hr.xtb
+++ b/chromium/components/strings/components_strings_hr.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Neće se prevoditi <ph name="LANGUAGE" />.</translation>
<translation id="2053553514270667976">ZIP kôd</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 prijedlog}one{# prijedlog}few{# prijedloga}other{# prijedloga}}</translation>
+<translation id="2068124040035837596">Vašim računom upravlja <ph name="ENROLLMENT_DOMAIN" />. To znači da administrator može konfigurirati vaš račun na daljinu.</translation>
<translation id="2068663545051464999">Preneseno je izvješće o padu programa s ID-jem <ph name="CRASH_ID" /> (lokalni kontekst: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Poništi</translation>
<translation id="20817612488360358">Postavljena je upotreba sistemskih postavki proxy poslužitelja, ali također je određena izričita konfiguracija proxy poslužitelja.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Taj način dostave nije dostupan. Pokušajte s drugim načinom.</translation>
<translation id="2396249848217231973">&amp;Poništi brisanje</translation>
<translation id="2413528052993050574">Poslužitelj nije mogao dokazati da je <ph name="DOMAIN" />; njegov sigurnosni certifikat možda je opozvan. To može biti uzrokovano pogrešnom konfiguracijom ili napadom na vašu vezu.</translation>
+<translation id="244665789865330679">Vašim uređajem i računom upravlja <ph name="ENROLLMENT_DOMAIN" />. To znači da administrator može konfigurirati vaš uređaj i račun na daljinu.</translation>
<translation id="2463193859425327265">Promijeni početnu stranicu</translation>
<translation id="2463739503403862330">Ispuni</translation>
<translation id="2465655957518002998">Odaberite način isporuke</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719">Pokušali ste doseći domenu <ph name="DOMAIN" />, ali certifikat koji je poslužitelj predstavio povučen je od strane izdavača. Prema tome nikako ne biste trebali vjerovati sigurnosnim certifikatima koje predstavlja poslužitelj. Možda komunicirate s napadačem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">rezultati pretraživanja</translation>
+<translation id="4406972042435603828">Administratori su instalirali proširenja velikih mogućnosti.</translation>
<translation id="4408413947728134509">Kolačića: <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Adresa preuzimanja</translation>
<translation id="4424024547088906515">Poslužitelj nije mogao dokazati da je <ph name="DOMAIN" />; Chrome smatra da njegov sigurnosni certifikat nije pouzdan. To može biti uzrokovano pogrešnom konfiguracijom ili napadom na vašu vezu.</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">Nema rezultata</translation>
<translation id="4950898438188848926">Gumb za promjenu kartice, pritisnite Enter za prebacivanje na otvorenu karticu, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Radnje</translation>
+<translation id="495832697253704892">Izvješćivanje o proširenjima</translation>
<translation id="4958444002117714549">Proširi popis</translation>
<translation id="4974590756084640048">Ponovo omogući upozorenja</translation>
<translation id="4989163558385430922">Prikaži sve</translation>
<translation id="4989809363548539747">Taj dodatak nije podržan</translation>
+<translation id="4996230189582812866">Izvješćivanje</translation>
<translation id="5002932099480077015">Ako je to omogućeno, Chrome će pohraniti kopiju vaše kartice na ovom uređaju radi bržeg ispunjavanja obrazaca.</translation>
<translation id="5014174725590676422">Prikazuje se zaslon prvog pokretanja Google asistenta u Chromeu</translation>
<translation id="5015510746216210676">Naziv uređaja:</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">Savezna država</translation>
<translation id="5094747076828555589">Poslužitelj nije mogao dokazati da je <ph name="DOMAIN" />; Chromium smatra da njegov sigurnosni certifikat nije pouzdan. To može biti uzrokovano pogrešnom konfiguracijom ili napadom na vašu vezu.</translation>
<translation id="5095208057601539847">Pokrajina</translation>
+<translation id="5098222253617183465">Vašim uređajem upravlja <ph name="ENROLLMENT_DOMAIN" />, a vašim računom upravlja <ph name="ACCOUNT_DOMAIN" />. To znači da administratori mogu konfigurirati vaš uređaj i račun na daljinu.</translation>
<translation id="5115563688576182185">(64-bitni)</translation>
<translation id="5128122789703661928">Brisanje sesije nije uspjelo jer naziv sesije nije važeći.</translation>
<translation id="5135404736266831032">Upravljajte adresama...</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">Strojno</translation>
<translation id="5179510805599951267">Nije <ph name="ORIGINAL_LANGUAGE" /> jezik? Prijavite tu pogrešku</translation>
<translation id="5190835502935405962">Traka oznaka</translation>
+<translation id="5200263511887412697">generiranje popisa korisnika uređaja koji su se nedavno prijavili</translation>
<translation id="5201306358585911203">Na ugrađenoj stranici na ovoj stranici navodi se sljedeće</translation>
<translation id="5205222826937269299">Ime je obavezno</translation>
<translation id="5215116848420601511">Načini plaćanja i adrese s Google Paya</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">Web-lokacija ne može se dohvatiti</translation>
<translation id="5869522115854928033">Spremljene zaporke</translation>
<translation id="5887400589839399685">Kartica je spremljena</translation>
+<translation id="5893718151540690985">generiranje popisa mrežnih sučelja s njihovim vrstama i adresama hardvera</translation>
<translation id="5893752035575986141">Prihvaćaju se kreditne kartice.</translation>
<translation id="5901630391730855834">Žuta</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sinkronizirano)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">Uredite podatke za kontakt</translation>
<translation id="5967867314010545767">Ukloni iz povijesti</translation>
<translation id="5975083100439434680">Smanji</translation>
+<translation id="5977489021191000276">Vašim uređajem ne upravlja administrator.</translation>
<translation id="5977976211062815271">Na ovom uređaju</translation>
<translation id="598637245381783098">Aplikacija za plaćanje ne može se otvoriti</translation>
<translation id="5989320800837274978">Nisu određeni fiksni proxy poslužitelji ni URL .pac skripte.</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347">Napadači na web-lokaciji <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogli bi instalirati obmanjujuće aplikacije koje se pretvaraju da su nešto drugo ili prikupljaju podatke na temelju kojih vas je moguće pratiti. <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte više<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sinkronizirano)</translation>
<translation id="6027201098523975773">Unesite ime</translation>
+<translation id="6033927989869462158">izvješćivanje o statistici hardvera kao što je upotreba procesora/RAM-a</translation>
<translation id="6034000775414344507">Svijetlosiva</translation>
<translation id="6039846035001940113">Ako se problem nastavi, obratite se vlasniku web-lokacije.</translation>
<translation id="6040143037577758943">Zatvori</translation>
@@ -904,6 +914,8 @@
<translation id="6897140037006041989">Korisnički agent</translation>
<translation id="6903319715792422884">Pomognite poboljšati Sigurno pregledavanje tako što ćete Googleu slati neke <ph name="BEGIN_WHITEPAPER_LINK" />podatke o sustavu i sadržaj web-stranice<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Korisnik:</translation>
+<translation id="6934672428414710184">To je ime s vašeg Google računa</translation>
+<translation id="6939583532829045966">Vašim uređajem upravlja <ph name="ENROLLMENT_DOMAIN" />. To znači da administrator može konfigurirati vaš uređaj na daljinu.</translation>
<translation id="6944692733090228304">Unijeli ste zaporku na web-lokaciju kojom ne upravlja <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Da biste zaštitili račun, nemojte upotrebljavati tu zaporku za druge aplikacije i web-lokacije.</translation>
<translation id="6945221475159498467">Odaberi</translation>
<translation id="6948701128805548767">Odaberite adresu za prikaz načina preuzimanja i zahtjeva za preuzimanje</translation>
@@ -991,6 +1003,7 @@ Dodatne pojedinosti:
&lt;li&gt;Kliknite &lt;strong&gt;Primijeni&lt;/strong&gt;, a zatim kliknite &lt;strong&gt;U redu&lt;/strong&gt;
&lt;li&gt;U &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;centru za pomoć za Chrome&lt;/a&gt; možete saznati kako trajno ukloniti softver s računala
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Upravljanje <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Upravljaj zaporkama…</translation>
<translation id="7419106976560586862">Putanja profila</translation>
<translation id="7437289804838430631">Dodajte podatke za kontakt</translation>
@@ -999,10 +1012,12 @@ Dodatne pojedinosti:
<translation id="7442725080345379071">Svijetlonarančasta</translation>
<translation id="7444046173054089907">Ova je web-lokacija blokirana</translation>
<translation id="7445762425076701745">Identitet poslužitelja s kojim ste se povezali ne može se u potpunosti potvrditi. Povezali ste se s poslužiteljem upotrebom imena koje je valjano samo unutar vaše mreže, a za koje vanjsko tijelo za izdavanje certifikata nikako ne može potvrditi vlasništvo. Budući da postoje tijela za izdavanje certifikata koja će izdati certifikat za ta imena bez obzira na sve, nema načina da budete sigurni da ste povezani sa željenom web-lokacijom, a ne s napadačem.</translation>
+<translation id="7449109375006139765">slanje zapisnika sustava poslužitelju za upravljanje</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Saznajte više<ph name="END_LINK" /> o tom problemu.</translation>
<translation id="7455133967321480974">Upotrijebi globalnu zadanu vrijednost (blokiraj)</translation>
<translation id="7460618730930299168">Projekcija se razlikuje od onog što ste odabrali. Želite li nastaviti?</translation>
<translation id="7473891865547856676">Ne, hvala</translation>
+<translation id="7475525192983021547">izvješćivanje o razdobljima aktivnosti korisnika na uređaju</translation>
<translation id="7481312909269577407">Naprijed</translation>
<translation id="7485870689360869515">Nema pronađenih podataka.</translation>
<translation id="7508255263130623398">Vraćeni ID uređaja pravila prazan je ili ne odgovara trenutačnom ID-u uređaja</translation>
@@ -1095,6 +1110,7 @@ Dodatne pojedinosti:
<translation id="7995512525968007366">Nije navedeno</translation>
<translation id="800218591365569300">Pokušajte zatvoriti ostale kartice ili programe da biste oslobodili memoriju.</translation>
<translation id="8009225694047762179">Upravljanje zaporkama</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Ova kartica i njezina adresa za naplatu spremit će se. Moći ćete plaćati njome kada ste prijavljeni na račun <ph name="USER_EMAIL" />.}one{Ove kartice i njihove adrese za naplatu spremit će se. Moći ćete plaćati njima kada ste prijavljeni na račun <ph name="USER_EMAIL" />.}few{Ove kartice i njihove adrese za naplatu spremit će se. Moći ćete plaćati njima kada ste prijavljeni na račun <ph name="USER_EMAIL" />.}other{Ove kartice i njihove adrese za naplatu spremit će se. Moći ćete plaćati njima kada ste prijavljeni na račun <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Nismo uspjeli stupiti u kontakt s tvojim roditeljima. Pokušaj ponovo.</translation>
<translation id="8025119109950072390">Napadači na ovoj web-lokaciji mogu vas na prijevaru pokušati navesti da napravite nešto opasno kao što je instaliranje softvera ili otkrivanje osobnih podataka (npr. zaporki, telefonskih brojeva ili kreditnih kartica).</translation>
<translation id="8034522405403831421">Jezik ove stranice jest <ph name="SOURCE_LANGUAGE" />. Želite li je prevesti na <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1105,6 +1121,7 @@ Dodatne pojedinosti:
<translation id="8041940743680923270">Upotrijebi globalnu zadanu vrijednost (pitaj)</translation>
<translation id="8042918947222776840">Odaberite način preuzimanja</translation>
<translation id="8057711352706143257">Softver "<ph name="SOFTWARE_NAME" />" nije ispravno konfiguriran. Taj se problem obično rješava deinstaliranjem softvera "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Vaš je uređaj konfiguriran za:</translation>
<translation id="8078141288243656252">Ne može dodati bilješku kada je dokument zakrenut</translation>
<translation id="8079031581361219619">Želite li ponovo učitati web-lokaciju?</translation>
<translation id="8088680233425245692">Prikaz članka nije uspio.</translation>
@@ -1155,6 +1172,7 @@ Dodatne pojedinosti:
<translation id="8363502534493474904">isključite način rada u zrakoplovu</translation>
<translation id="8364627913115013041">Nije postavljeno.</translation>
<translation id="8368476060205742148">Google Play usluge</translation>
+<translation id="8371889962595521444">Prilagođeni korijenski certifikati</translation>
<translation id="8380941800586852976">Opasno</translation>
<translation id="8381674639488873545">Ta terećenja mogu biti jednokratna ili ponavljajuća i možda nisu vidljiva odmah. <ph name="BEGIN_LINK" />Ipak prikaži<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Ovdje će se prikazivati oznake koje ste nedavno posjetili</translation>
@@ -1164,6 +1182,7 @@ Dodatne pojedinosti:
<translation id="8416694386774425977">Konfiguracija mreže nije važeća i nije se mogla uvesti.
Dodatne pojedinosti:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Uređajem upravlja <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Promijeni</translation>
<translation id="8428213095426709021">Postavke</translation>
@@ -1225,6 +1244,7 @@ Dodatne pojedinosti:
<translation id="8932102934695377596">Sat kasni</translation>
<translation id="893332455753468063">Dodajte ime</translation>
<translation id="8938939909778640821">Prihvaćene kreditne i pretplatne kartice</translation>
+<translation id="894185898663964645">Administrator je konfigurirao prilagođene korijenske certifikate, što mu može omogućiti da vidi sadržaj web-lokacija koje posjećujete.</translation>
<translation id="8943282376843390568">Limeta</translation>
<translation id="8957210676456822347">Autorizacija obaveznog portala za autentifikaciju</translation>
<translation id="8968766641738584599">Spremanje kartice</translation>
diff --git a/chromium/components/strings/components_strings_hu.xtb b/chromium/components/strings/components_strings_hu.xtb
index 19c43ba2fa3..2aa548802a1 100644
--- a/chromium/components/strings/components_strings_hu.xtb
+++ b/chromium/components/strings/components_strings_hu.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">A(z) <ph name="LANGUAGE" /> nyelvű oldalak nem lesznek lefordítva.</translation>
<translation id="2053553514270667976">Irányítószám</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 javaslat}other{# javaslat}}</translation>
+<translation id="2068124040035837596">Fiókját a(z) <ph name="ENROLLMENT_DOMAIN" /> kezeli. A rendszergazda távolról módosíthatja a fiók beállításait.</translation>
<translation id="2068663545051464999">Feltöltött hibajelentés azonosítója: <ph name="CRASH_ID" /> (helyi kontextus: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Visszavonás</translation>
<translation id="20817612488360358">A rendszer proxybeállításai konfigurálva vannak a használathoz, de kifejezett proxykonfiguráció is meg van adva.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Ez a szállítási mód nem áll rendelkezésre. Próbálkozzon másik móddal.</translation>
<translation id="2396249848217231973">&amp;Törlés visszavonása</translation>
<translation id="2413528052993050574">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványát visszavonhatták. Ennek oka lehet konfigurációs hiba, vagy hogy egy támadó eltérítette az Ön kapcsolódását.</translation>
+<translation id="244665789865330679">Eszközét és fiókját a(z) <ph name="ENROLLMENT_DOMAIN" /> kezeli. A rendszergazda távolról módosíthatja az eszköz és a fiók beállításait.</translation>
<translation id="2463193859425327265">Kezdőlap módosítása</translation>
<translation id="2463739503403862330">Kitöltés</translation>
<translation id="2465655957518002998">Kézbesítési mód kiválasztása</translation>
@@ -559,6 +561,7 @@
<translation id="4377125064752653719">A(z) <ph name="DOMAIN" /> webhelyet próbálta megnyitni, de a kiállító visszavonta a szerver által bemutatott tanúsítványt. Ez azt jelenti, hogy a szerver biztonsági igazolásaiban egyáltalán nem lehet megbízni. Lehet, hogy egy támadóval áll kapcsolatban.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">keresési találat</translation>
+<translation id="4406972042435603828">A rendszergazdák nagy befolyást biztosító bővítményeket telepítettek.</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> cookie</translation>
<translation id="4415426530740016218">Átvételi cím</translation>
<translation id="4424024547088906515">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványa a Chrome szerint nem megbízható. Ennek oka lehet konfigurációs hiba, vagy hogy egy támadó eltérítette az Ön kapcsolódását.</translation>
@@ -630,10 +633,12 @@
<translation id="4943872375798546930">Nincs találat</translation>
<translation id="4950898438188848926">Lapváltó gomb. Nyomja meg az Entert a következő megnyitott lapra való váltáshoz: <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Műveletek</translation>
+<translation id="495832697253704892">Jelentés a bővítményekről</translation>
<translation id="4958444002117714549">Lista részletes nézete</translation>
<translation id="4974590756084640048">Figyelmeztetések újbóli engedélyezése</translation>
<translation id="4989163558385430922">Összes megtekintése</translation>
<translation id="4989809363548539747">Ez a beépülő modul nem támogatott</translation>
+<translation id="4996230189582812866">Jelentés</translation>
<translation id="5002932099480077015">Ha engedélyezi, a Chrome megőrzi a kártya másolatát ezen az eszközön a gyorsabb űrlapkitöltés érdekében.</translation>
<translation id="5014174725590676422">A képernyőn a Google Segéd a Chrome-ban szolgáltatás első futtatáskor megjelenő képernyője látható</translation>
<translation id="5015510746216210676">Számítógépnév:</translation>
@@ -654,6 +659,7 @@
<translation id="5089810972385038852">Állam</translation>
<translation id="5094747076828555589">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványa a Chromium szerint nem megbízható. Ennek oka lehet konfigurációs hiba, vagy hogy egy támadó eltérítette az Ön kapcsolódását.</translation>
<translation id="5095208057601539847">Tartomány</translation>
+<translation id="5098222253617183465">Eszközét a(z) <ph name="ENROLLMENT_DOMAIN" />, fiókját pedig a(z) <ph name="ACCOUNT_DOMAIN" /> kezeli. A rendszergazdák távolról módosíthatják eszköze és fiókja beállításait.</translation>
<translation id="5115563688576182185">(64 bites)</translation>
<translation id="5128122789703661928">Ez a munkamenetnév nem érvényes, ezért nem törölhető.</translation>
<translation id="5135404736266831032">Címek kezelése…</translation>
@@ -666,6 +672,7 @@
<translation id="5172758083709347301">Számítógép</translation>
<translation id="5179510805599951267">Nem <ph name="ORIGINAL_LANGUAGE" /> nyelven van? Hiba bejelentése</translation>
<translation id="5190835502935405962">Könyvjelzősáv</translation>
+<translation id="5200263511887412697">jelentés a közelmúltban bejelentkezett felhasználók listájáról</translation>
<translation id="5201306358585911203">Az oldal egyik beágyazott oldalának közlendője</translation>
<translation id="5205222826937269299">A név megadása kötelező</translation>
<translation id="5215116848420601511">A Google Pay szolgáltatásban használt fizetési módok és címek</translation>
@@ -767,6 +774,7 @@
<translation id="5869405914158311789">A webhely nem érhető el</translation>
<translation id="5869522115854928033">Mentett jelszavak</translation>
<translation id="5887400589839399685">Kártya elmentve</translation>
+<translation id="5893718151540690985">jelentés a hálózati interfészekről, típusukról és hardvercímeikről</translation>
<translation id="5893752035575986141">Elfogadott hitelkártyák.</translation>
<translation id="5901630391730855834">Sárga</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (szinkronizálva)</translation>
@@ -780,6 +788,7 @@
<translation id="5967592137238574583">Kapcsolattartási adatok szerkesztése</translation>
<translation id="5967867314010545767">Eltávolítás az előzmények közül</translation>
<translation id="5975083100439434680">Kicsinyítés</translation>
+<translation id="5977489021191000276">Eszközét nem kezeli rendszergazda.</translation>
<translation id="5977976211062815271">Ezen az eszközön</translation>
<translation id="598637245381783098">Nem sikerült megnyitni a fizetőalkalmazást</translation>
<translation id="5989320800837274978">Sem fix proxyszerver, sem pedig .pac típusú szkript URL-címe nincs megadva.</translation>
@@ -791,6 +800,7 @@
<translation id="6017850046339264347">A(z) <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webhelyen lévő támadók megtévesztő alkalmazásokat telepíthetnek, amelyek más alkalmazásnak tettethetik magukat, illetve az Ön nyomon követésére alkalmas adatokat gyűjthetnek. <ph name="BEGIN_LEARN_MORE_LINK" />További információ<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (szinkronizálva)</translation>
<translation id="6027201098523975773">Adjon meg nevet</translation>
+<translation id="6033927989869462158">jelentés a hardverstatisztikákról, például a CPU és a RAM kihasználtságáról</translation>
<translation id="6034000775414344507">Világosszürke</translation>
<translation id="6039846035001940113">Ha a probléma továbbra is fennáll, lépjen kapcsolatba a webhely tulajdonosával.</translation>
<translation id="6040143037577758943">Bezárás</translation>
@@ -903,6 +913,8 @@
<translation id="6897140037006041989">User agent</translation>
<translation id="6903319715792422884">A Biztonságos Böngészés fejlesztésének segítése bizonyos <ph name="BEGIN_WHITEPAPER_LINK" />rendszer-információknak és oldaltartalmaknak<ph name="END_WHITEPAPER_LINK" /> a Google-nak való elküldésével. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Felhasználó:</translation>
+<translation id="6934672428414710184">Ez a név a Google-fiókjából származik</translation>
+<translation id="6939583532829045966">Eszközét a(z) <ph name="ENROLLMENT_DOMAIN" /> kezeli. A rendszergazda távolról módosíthatja az eszköz beállításait.</translation>
<translation id="6944692733090228304">Olyan webhelyen adta meg a jelszavát, amelyet nem a(z) <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> kezel. Fiókja védelme érdekében ne használja fel újra a jelszót más alkalmazásokban és webhelyeken.</translation>
<translation id="6945221475159498467">Kiválasztás</translation>
<translation id="6948701128805548767">Az átvételi módok és követelmények megtekintéséhez válassza ki a címet</translation>
@@ -990,6 +1002,7 @@ További részletek:
&lt;li&gt;Kattintson az &lt;strong&gt;Alkalmaz&lt;/strong&gt;, majd az &lt;strong&gt;OK&lt;/strong&gt; gombra.
&lt;li&gt;Keresse fel a &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome súgóját&lt;/a&gt;, ahol további információt talál a szoftver számítógépről történő végleges eltávolításáról.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> kezelése</translation>
<translation id="7416351320495623771">Jelszavak kezelése…</translation>
<translation id="7419106976560586862">Profil elérési útja</translation>
<translation id="7437289804838430631">Kapcsolatfelvételi adatok hozzáadása</translation>
@@ -998,10 +1011,12 @@ További részletek:
<translation id="7442725080345379071">Világos narancssárga</translation>
<translation id="7444046173054089907">Ez a webhely le van tiltva</translation>
<translation id="7445762425076701745">Nem sikerült teljesen ellenőrizni a szerver azonosságát, amelyhez kapcsolódik. Egy olyan névvel kapcsolódik a szerverhez, amelynek tulajdonjogát egy külső tanúsítványkibocsátó nem ellenőrizheti. Mivel egyes tanúsítványkibocsátók figyelmen kívül hagyják ezeket a neveket, így semmi nem biztosítja, hogy a kívánt webhelyhez kapcsolódik, és nem egy támadó webhelyhez.</translation>
+<translation id="7449109375006139765">rendszernaplók küldése a kezelőszervernek</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />További információk megtekintése<ph name="END_LINK" /> a problémával kapcsolatban.</translation>
<translation id="7455133967321480974">Globális alapértelmezés használata (Tiltás)</translation>
<translation id="7460618730930299168">Az előzetes vetítés eltér az Ön által kijelölttől. Folytatja?</translation>
<translation id="7473891865547856676">Nem, köszönöm</translation>
+<translation id="7475525192983021547">jelentés az eszköz aktív használatának időszakairól</translation>
<translation id="7481312909269577407">Előre</translation>
<translation id="7485870689360869515">Nem található adat.</translation>
<translation id="7508255263130623398">A visszakapott házirend eszközazonosítója üres, vagy nem felel meg a jelenlegi eszközazonosítónak</translation>
@@ -1094,6 +1109,7 @@ További részletek:
<translation id="7995512525968007366">Nincs megadva</translation>
<translation id="800218591365569300">Próbáljon meg bezárni más lapokat vagy programokat memória felszabadítása céljából.</translation>
<translation id="8009225694047762179">Jelszó kezelése</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{A kártyát és a számlázási címet elmentjük. Az adatok kéznél lesznek, amíg <ph name="USER_EMAIL" /> e-mail-című fiókját használja.}other{A kártyákat és a számlázási címeket elmentjük. Az adatok kéznél lesznek, amíg <ph name="USER_EMAIL" /> e-mail-című fiókját használja.}}</translation>
<translation id="8012647001091218357">Jelenleg nem tudjuk elérni szüleidet. Próbálkozz újra.</translation>
<translation id="8025119109950072390">A webhely támadói megpróbálhatják csellel rávenni Önt, hogy például telepítsen egy veszélyes szoftvert, vagy felfedje személyes adatait (jelszavát, telefonszámát, hitelkártyaszámát stb.).</translation>
<translation id="8034522405403831421">Ez az oldal <ph name="SOURCE_LANGUAGE" /> nyelven van. Lefordítja <ph name="TARGET_LANGUAGE" /> nyelvre?</translation>
@@ -1104,6 +1120,7 @@ További részletek:
<translation id="8041940743680923270">Globális alapértelmezés használata (Megkérdezés)</translation>
<translation id="8042918947222776840">Átvételi mód kiválasztása</translation>
<translation id="8057711352706143257">A(z) „<ph name="SOFTWARE_NAME" />” nincs megfelelően beállítva. A(z) „<ph name="SOFTWARE_NAME" />” eltávolítása általában megoldja a problémát. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Eszközét a következőkre konfigurálták:</translation>
<translation id="8078141288243656252">Elforgatott állapotban nem lehetséges a jegyzetelés</translation>
<translation id="8079031581361219619">Újratölti a webhelyet?</translation>
<translation id="8088680233425245692">Nem sikerült megtekinteni a cikket.</translation>
@@ -1154,6 +1171,7 @@ További részletek:
<translation id="8363502534493474904">Repülős üzemmód kikapcsolása</translation>
<translation id="8364627913115013041">Nincs beállítva.</translation>
<translation id="8368476060205742148">Google Play-szolgáltatások</translation>
+<translation id="8371889962595521444">Egyéni gyökérszintű tanúsítványok</translation>
<translation id="8380941800586852976">Veszélyes</translation>
<translation id="8381674639488873545">Egyszeri és ismétlődő díjakról is szó lehet, amelyek nem feltétlenül nyilvánvalóak. <ph name="BEGIN_LINK" />Megjelenítés mégis<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">A közelmúltban megnyitott könyvjelzők helye</translation>
@@ -1163,6 +1181,7 @@ További részletek:
<translation id="8416694386774425977">A hálózati konfiguráció érvénytelen és nem importálható.
További részletek:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">A(z) <ph name="ENROLLMENT_DOMAIN" /> által kezelt eszköz</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Módosítás</translation>
<translation id="8428213095426709021">Beállítások</translation>
@@ -1224,6 +1243,7 @@ További részletek:
<translation id="8932102934695377596">Késik az órája</translation>
<translation id="893332455753468063">Név hozzáadása</translation>
<translation id="8938939909778640821">Elfogadott hitel- és feltöltőkártyák</translation>
+<translation id="894185898663964645">A rendszergazda egyéni gyökérszintű tanúsítványokat állított be, amelyekkel láthatja az Ön által meglátogatott webhelyek tartalmát.</translation>
<translation id="8943282376843390568">Limezöld</translation>
<translation id="8957210676456822347">Hitelesítés hitelesítési portállal</translation>
<translation id="8968766641738584599">Kártya mentése</translation>
diff --git a/chromium/components/strings/components_strings_id.xtb b/chromium/components/strings/components_strings_id.xtb
index b533ce86719..7199fc9a91e 100644
--- a/chromium/components/strings/components_strings_id.xtb
+++ b/chromium/components/strings/components_strings_id.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Halaman dalam bahasa <ph name="LANGUAGE" /> tidak akan diterjemahkan.</translation>
<translation id="2053553514270667976">Kode pos</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 saran}other{# saran}}</translation>
+<translation id="2068124040035837596">Akun Anda dikelola oleh <ph name="ENROLLMENT_DOMAIN" />. Ini berarti bahwa administrator dapat mengonfigurasi akun Anda dari jarak jauh.</translation>
<translation id="2068663545051464999">ID Laporan Kerusakan yang Diupload <ph name="CRASH_ID" /> (Konteks Lokal: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Urungkan</translation>
<translation id="20817612488360358">Setelan proxy sistem disetel untuk digunakan namun konfigurasi proxy eksplisit juga ditentukan.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Metode pengiriman tidak tersedia. Coba metode lain.</translation>
<translation id="2396249848217231973">&amp;Urungkan penghapusan</translation>
<translation id="2413528052993050574">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya mungkin dicabut. Hal ini dapat disebabkan oleh kesalahan konfigurasi atau penyerang memotong sambungan Anda.</translation>
+<translation id="244665789865330679">Perangkat dan akun Anda dikelola oleh <ph name="ENROLLMENT_DOMAIN" />. Ini berarti bahwa administrator dapat mengonfigurasi perangkat dan akun Anda dari jarak jauh.</translation>
<translation id="2463193859425327265">Ubah Halaman Beranda</translation>
<translation id="2463739503403862330">Isi</translation>
<translation id="2465655957518002998">Pilih Metode Pengiriman</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719">Anda berusaha menjangkau <ph name="DOMAIN" />, tetapi sertifikat yang disajikan oleh server telah dibatalkan oleh penerbitnya. Artinya informasi rahasia keamanan yang disajikan tidak dapat dipercaya. Anda mungkin sedang berkomunikasi dengan penyerang.</translation>
<translation id="4378154925671717803">Ponsel</translation>
<translation id="4406896451731180161">hasil penelusuran</translation>
+<translation id="4406972042435603828">Administrator telah menginstal ekstensi dengan kemampuan canggih.</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Alamat Pengambilan</translation>
<translation id="4424024547088906515">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya tidak dipercaya oleh Chrome. Hal ini dapat disebabkan oleh kesalahan konfigurasi atau penyerang memotong sambungan Anda.</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">Tidak ada hasil</translation>
<translation id="4950898438188848926">Tombol beralih tab, tekan Enter untuk beralih ke tab yang terbuka, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Tindakan</translation>
+<translation id="495832697253704892">Pelaporan ekstensi</translation>
<translation id="4958444002117714549">Luaskan daftar</translation>
<translation id="4974590756084640048">Aktifkan kembali peringatan</translation>
<translation id="4989163558385430922">Lihat semua</translation>
<translation id="4989809363548539747">Plugin ini tidak didukung</translation>
+<translation id="4996230189582812866">Pelaporan</translation>
<translation id="5002932099480077015">Jika diaktifkan, Chrome akan menyimpan salinan kartu Anda di perangkat ini untuk pengisian formulir yang lebih cepat.</translation>
<translation id="5014174725590676422">Layar penggunaan pertama Asisten Google di Chrome ditampilkan</translation>
<translation id="5015510746216210676">Nama Mesin:</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">Negara Bagian</translation>
<translation id="5094747076828555589">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya tidak dipercaya oleh Chromium. Hal ini dapat disebabkan oleh kesalahan konfigurasi atau penyerang memotong sambungan Anda.</translation>
<translation id="5095208057601539847">Provinsi</translation>
+<translation id="5098222253617183465">Perangkat dikelola oleh <ph name="ENROLLMENT_DOMAIN" /> dan akun dikelola oleh <ph name="ACCOUNT_DOMAIN" />. Ini berarti bahwa administrator dapat mengonfigurasi perangkat dan akun Anda dari jarak jauh.</translation>
<translation id="5115563688576182185">(64 bit)</translation>
<translation id="5128122789703661928">Sesi dengan nama ini tidak valid untuk dihapus.</translation>
<translation id="5135404736266831032">Kelola alamat...</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">Mesin</translation>
<translation id="5179510805599951267">Bukan <ph name="ORIGINAL_LANGUAGE" />? Laporkan kesalahan deteksi ini</translation>
<translation id="5190835502935405962">Bilah Bookmark</translation>
+<translation id="5200263511887412697">melaporkan daftar perangkat yang baru-baru ini digunakan oleh pengguna untuk login</translation>
<translation id="5201306358585911203">Halaman tersemat di halaman ini menyatakan</translation>
<translation id="5205222826937269299">Nama wajib diisi</translation>
<translation id="5215116848420601511">Metode pembayaran dan alamat yang menggunakan Google Pay</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">Situs ini tidak dapat dijangkau</translation>
<translation id="5869522115854928033">Sandi tersimpan</translation>
<translation id="5887400589839399685">Kartu disimpan</translation>
+<translation id="5893718151540690985">melaporkan daftar antarmuka jaringan dengan jenis dan alamat hardware</translation>
<translation id="5893752035575986141">Kartu kredit diterima.</translation>
<translation id="5901630391730855834">Kuning</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (disinkronkan)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">Edit Info Kontak</translation>
<translation id="5967867314010545767">Hapus dari histori</translation>
<translation id="5975083100439434680">Perkecil</translation>
+<translation id="5977489021191000276">Perangkat Anda tidak dikelola oleh administrator.</translation>
<translation id="5977976211062815271">Di perangkat ini</translation>
<translation id="598637245381783098">Tidak dapat membuka aplikasi pembayaran</translation>
<translation id="5989320800837274978">Baik proxy server tetap ataupun URL skrip .pac tidak ditentukan.</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347">Penyerang di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> dapat menginstal aplikasi penipuan dengan berpura-pura menjadi sesuatu yang lain atau mengumpulkan data yang dapat digunakan untuk melacak Anda. <ph name="BEGIN_LEARN_MORE_LINK" />Pelajari lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (disinkronkan)</translation>
<translation id="6027201098523975773">Masukkan nama</translation>
+<translation id="6033927989869462158">melaporkan statistik hardware seperti penggunaan CPU/RAM</translation>
<translation id="6034000775414344507">Abu-abu Muda</translation>
<translation id="6039846035001940113">Jika masalah berlanjut, hubungi pemilik situs.</translation>
<translation id="6040143037577758943">Tutup</translation>
@@ -904,6 +914,8 @@
<translation id="6897140037006041989">Agen Pengguna</translation>
<translation id="6903319715792422884">Bantu sempurnakan Safe Browsing dengan mengirimkan sebagian <ph name="BEGIN_WHITEPAPER_LINK" />informasi sistem dan konten halaman<ph name="END_WHITEPAPER_LINK" /> ke Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Pengguna:</translation>
+<translation id="6934672428414710184">Nama ini dari Akun Google Anda</translation>
+<translation id="6939583532829045966">Perangkat Anda dikelola oleh <ph name="ENROLLMENT_DOMAIN" />. Ini berarti bahwa administrator dapat mengonfigurasi perangkat Anda dari jarak jauh.</translation>
<translation id="6944692733090228304">Anda memasukkan sandi di situs yang tidak dikelola oleh <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Untuk melindungi akun, jangan gunakan sandi yang sama di aplikasi dan situs lain.</translation>
<translation id="6945221475159498467">Pilih</translation>
<translation id="6948701128805548767">Untuk melihat persyaratan dan metode pengambilan, pilih alamat</translation>
@@ -989,6 +1001,7 @@
&lt;li&gt;Klik &lt;strong&gt;Apply&lt;/strong&gt;, lalu klik &lt;strong&gt;Ok&lt;/strong&gt;
&lt;li&gt;Buka &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Pusat bantuan Chrome&lt;/a&gt; untuk mempelajari cara menghapus software tersebut secara permanen dari komputer
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Pengelolaan <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Kelola Sandi...</translation>
<translation id="7419106976560586862">Jalur Profil</translation>
<translation id="7437289804838430631">Tambahkan Info Kontak</translation>
@@ -997,10 +1010,12 @@
<translation id="7442725080345379071">Oranye Muda</translation>
<translation id="7444046173054089907">Situs ini diblokir</translation>
<translation id="7445762425076701745">Identitas server yang Anda sambungkan tidak dapat divalidasi sepenuhnya. Anda terhubung ke server menggunakan nama yang hanya valid dalam jaringan Anda, yang mana otoritas sertifikat eksternal sama sekali tidak dapat memvalidasi kepemilikannya. Karena sejumlah otoritas sertifikat akan tetap menerbitkan sertifikat untuk nama tersebut, tidak dapat dipastikan apakah Anda akan tersambung ke situs web yang dimaksudkan dan bahwa tidak akan ada penyerang.</translation>
+<translation id="7449109375006139765">mengirimkan log sistem ke server pengelolaan</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Pelajari lebih lanjut<ph name="END_LINK" /> tentang masalah ini.</translation>
<translation id="7455133967321480974">Gunakan default global (Cekal)</translation>
<translation id="7460618730930299168">Penyaringan ini berbeda dengan yang telah Anda pilih. Lanjutkan?</translation>
<translation id="7473891865547856676">Lain Kali</translation>
+<translation id="7475525192983021547">melaporkan periode waktu saat pengguna aktif menggunakan perangkat</translation>
<translation id="7481312909269577407">Maju</translation>
<translation id="7485870689360869515">Tidak ada data yang ditemukan.</translation>
<translation id="7508255263130623398">ID perangkat kebijakan yang dikembalikan kosong atau tidak cocok dengan ID perangkat saat ini</translation>
@@ -1093,6 +1108,7 @@
<translation id="7995512525968007366">Tidak Ditentukan</translation>
<translation id="800218591365569300">Coba tutup tab atau program lain untuk mengosongkan memori.</translation>
<translation id="8009225694047762179">Kelola Kata sandi</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Kartu ini dan alamat penagihannya akan disimpan. Anda dapat menggunakannya saat login ke <ph name="USER_EMAIL" />.}other{Semua kartu ini dan alamat penagihannya akan disimpan. Anda dapat menggunakannya saat login ke <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Orang tua Anda saat ini tidak dapat dihubungi. Coba lagi.</translation>
<translation id="8025119109950072390">Penyerang di situs ini dapat mengelabui Anda agar melakukan hal yang berbahaya seperti memasang software atau mengungkap informasi pribadi Anda (misalnya sandi, nomor telepon, atau kartu kredit).</translation>
<translation id="8034522405403831421">Halaman ini berbahasa <ph name="SOURCE_LANGUAGE" />. Terjemahkan ke <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1103,6 +1119,7 @@
<translation id="8041940743680923270">Gunakan default global (Tanyakan)</translation>
<translation id="8042918947222776840">Pilih Metode Pengambilan</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" tidak dikonfigurasi dengan benar. Biasanya masalah akan terselesaikan dengan meng-uninstal "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Perangkat telah dikonfigurasi untuk:</translation>
<translation id="8078141288243656252">Tidak dapat menambahkan anotasi saat diputar</translation>
<translation id="8079031581361219619">Muat ulang situs?</translation>
<translation id="8088680233425245692">Gagal melihat artikel.</translation>
@@ -1153,6 +1170,7 @@
<translation id="8363502534493474904">Nonaktifkan mode pesawat</translation>
<translation id="8364627913115013041">Tidak disetel.</translation>
<translation id="8368476060205742148">Layanan Google Play</translation>
+<translation id="8371889962595521444">Root certificate kustom</translation>
<translation id="8380941800586852976">Berbahaya</translation>
<translation id="8381674639488873545">Tagihan ini dapat hanya satu kali atau berulang, dan mungkin tidak ditampilkan dengan jelas. <ph name="BEGIN_LINK" />Tetap tampilkan<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Bookmark yang baru-baru ini dikunjungi ditampilkan di sini</translation>
@@ -1160,6 +1178,7 @@
<translation id="8412145213513410671">Ngadat (<ph name="CRASH_COUNT" />)</translation>
<translation id="8412392972487953978">Anda harus memasukkan frasa sandi yang sama dua kali.</translation>
<translation id="8416694386774425977">Konfigurasi jaringan tidak valid dan tidak dapat diimpor. Detail tambahan: <ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Perangkat dikelola oleh <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Ubah</translation>
<translation id="8428213095426709021">Setelan</translation>
@@ -1220,6 +1239,7 @@
<translation id="8932102934695377596">Setelan waktu Anda terlalu lambat</translation>
<translation id="893332455753468063">Tambahkan Nama</translation>
<translation id="8938939909778640821">Kartu kredit dan prabayar yang diterima</translation>
+<translation id="894185898663964645">Administrator telah mengonfigurasi root certificate kustom, yang dapat mengizinkan administrator melihat konten situs yang Anda buka.</translation>
<translation id="8943282376843390568">Hijau limau</translation>
<translation id="8957210676456822347">Otorisasi Portal Tawanan</translation>
<translation id="8968766641738584599">Simpan kartu</translation>
diff --git a/chromium/components/strings/components_strings_it.xtb b/chromium/components/strings/components_strings_it.xtb
index ee18eb12679..181b8b70b89 100644
--- a/chromium/components/strings/components_strings_it.xtb
+++ b/chromium/components/strings/components_strings_it.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Le pagine in <ph name="LANGUAGE" /> non verranno tradotte.</translation>
<translation id="2053553514270667976">ZIP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggerimento}other{# suggerimenti}}</translation>
+<translation id="2068124040035837596">Il tuo account è gestito da <ph name="ENROLLMENT_DOMAIN" />. L'amministratore può configurare da remoto l'account.</translation>
<translation id="2068663545051464999">ID rapporto sugli arresti anomali caricato <ph name="CRASH_ID" /> (Contesto locale: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Annulla</translation>
<translation id="20817612488360358">Devono essere utilizzate le impostazioni del proxy di sistema ma è stata specificata anche una configurazione proxy esplicita.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Questo metodo di spedizione non è disponibile. Prova un metodo diverso.</translation>
<translation id="2396249848217231973">&amp;Annulla eliminazione</translation>
<translation id="2413528052993050574">Questo server non è riuscito a dimostrare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza potrebbe essere revocato. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.</translation>
+<translation id="244665789865330679">Il tuo dispositivo e il tuo account sono gestiti da <ph name="ENROLLMENT_DOMAIN" />. L'amministratore può configurare da remoto il dispositivo e l'account.</translation>
<translation id="2463193859425327265">Cambia la pagina iniziale</translation>
<translation id="2463739503403862330">Compila</translation>
<translation id="2465655957518002998">Scegli il metodo di consegna</translation>
@@ -558,6 +560,7 @@
<translation id="4377125064752653719">Hai tentato di accedere a <ph name="DOMAIN" /> ma il server ha presentato un certificato revocato dall'autorità di certificazione. Ciò significa che le credenziali di sicurezza presentate dal server non sono assolutamente attendibili. Potresti avere stabilito una comunicazione con un utente malintenzionato.</translation>
<translation id="4378154925671717803">Telefono</translation>
<translation id="4406896451731180161">risultati di ricerca</translation>
+<translation id="4406972042435603828">Gli amministratori hanno installato estensioni con funzionalità efficaci.</translation>
<translation id="4408413947728134509">Cookie: <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Indirizzo di ritiro</translation>
<translation id="4424024547088906515">Questo server non è riuscito a dimostrare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza non è considerato attendibile da Chrome. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.</translation>
@@ -629,10 +632,12 @@
<translation id="4943872375798546930">Nessun risultato</translation>
<translation id="4950898438188848926">Pulsante per cambiare scheda, premi INVIO per passare alla scheda aperta, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Azioni</translation>
+<translation id="495832697253704892">Rapporto sulle estensioni</translation>
<translation id="4958444002117714549">Espandi elenco</translation>
<translation id="4974590756084640048">Riattiva avvisi</translation>
<translation id="4989163558385430922">Mostra tutto</translation>
<translation id="4989809363548539747">Questo plug-in non è supportato</translation>
+<translation id="4996230189582812866">Rapporti</translation>
<translation id="5002932099480077015">Se questa opzione viene attivata, Chrome memorizza una copia della carta sul dispositivo per velocizzare la compilazione dei moduli.</translation>
<translation id="5014174725590676422">È mostrata la schermata della prima esecuzione dell'Assistente Google in Chrome</translation>
<translation id="5015510746216210676">Nome macchina:</translation>
@@ -653,6 +658,7 @@
<translation id="5089810972385038852">Stato</translation>
<translation id="5094747076828555589">Questo server non è riuscito a dimostrare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza non è considerato attendibile da Chromium. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.</translation>
<translation id="5095208057601539847">Provincia</translation>
+<translation id="5098222253617183465">Il tuo dispositivo è gestito da <ph name="ENROLLMENT_DOMAIN" />, il tuo account da <ph name="ACCOUNT_DOMAIN" />. Gli amministratori possono configurare da remoto il dispositivo e l'account.</translation>
<translation id="5115563688576182185">(a 64 bit)</translation>
<translation id="5128122789703661928">Impossibile eliminare la sessione perché il nome specificato non è valido.</translation>
<translation id="5135404736266831032">Gestisci indirizzi…</translation>
@@ -665,6 +671,7 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Non in <ph name="ORIGINAL_LANGUAGE" />? Segnala questo errore</translation>
<translation id="5190835502935405962">Barra dei Preferiti</translation>
+<translation id="5200263511887412697">Segnala l'elenco di utenti del dispositivo che hanno eseguito l'accesso di recente</translation>
<translation id="5201306358585911203">Una pagina incorporata in questa pagina dice</translation>
<translation id="5205222826937269299">Nome obbligatorio</translation>
<translation id="5215116848420601511">Metodi di pagamento e indirizzi che utilizzano Google Pay</translation>
@@ -766,6 +773,7 @@
<translation id="5869405914158311789">Impossibile raggiungere il sito</translation>
<translation id="5869522115854928033">Password salvate</translation>
<translation id="5887400589839399685">Carta salvata</translation>
+<translation id="5893718151540690985">Comunica l'elenco di interfacce di rete con i relativi tipi e indirizzi hardware</translation>
<translation id="5893752035575986141">Le carte di credito sono accettate.</translation>
<translation id="5901630391730855834">Giallo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizzati)</translation>
@@ -779,6 +787,7 @@
<translation id="5967592137238574583">Modifica informazioni di contatto</translation>
<translation id="5967867314010545767">Rimuovi da cronologia</translation>
<translation id="5975083100439434680">Diminuisci lo zoom</translation>
+<translation id="5977489021191000276">Il tuo dispositivo non è gestito da un amministratore.</translation>
<translation id="5977976211062815271">Su questo dispositivo</translation>
<translation id="598637245381783098">Impossibile aprire l'app per i pagamenti</translation>
<translation id="5989320800837274978">Non sono stati specificati né server proxy fissi né un URL script .pac.</translation>
@@ -790,6 +799,7 @@
<translation id="6017850046339264347">Gli utenti malintenzionati presenti sul sito <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> potrebbero installare app ingannevoli che si spacciano per qualcos'altro o raccolgono dati che potrebbero essere usati per monitorare la tua attività. <ph name="BEGIN_LEARN_MORE_LINK" />Ulteriori informazioni<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sincronizzati)</translation>
<translation id="6027201098523975773">Inserisci un nome</translation>
+<translation id="6033927989869462158">Segnala statistiche hardware quali l'utilizzo di CPU/RAM</translation>
<translation id="6034000775414344507">Grigio chiaro</translation>
<translation id="6039846035001940113">Se il problema persiste, contatta il proprietario del sito.</translation>
<translation id="6040143037577758943">Chiudi</translation>
@@ -876,7 +886,7 @@
<translation id="6710594484020273272">&lt;Digita un termine di ricerca&gt;</translation>
<translation id="671076103358959139">Token di registrazione:</translation>
<translation id="6711464428925977395">Si è verificato un problema con il server proxy oppure l'indirizzo non è corretto.</translation>
-<translation id="6723740634201835758">Nell'account Google</translation>
+<translation id="6723740634201835758">Nell'Account Google</translation>
<translation id="674375294223700098">Errore sconosciuto del certificato del server.</translation>
<translation id="6744009308914054259">In attesa di una connessione, puoi visitare la pagina Download per leggere gli articoli offline.</translation>
<translation id="6753269504797312559">Valore norma</translation>
@@ -901,6 +911,8 @@
<translation id="6897140037006041989">User-agent</translation>
<translation id="6903319715792422884">Contribuisci a migliorare la Navigazione sicura inviando a Google <ph name="BEGIN_WHITEPAPER_LINK" />informazioni di sistema e contenuti delle pagine<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Utente:</translation>
+<translation id="6934672428414710184">Questo nome proviene dal tuo Account Google</translation>
+<translation id="6939583532829045966">Il tuo dispositivo è gestito da <ph name="ENROLLMENT_DOMAIN" />. L'amministratore può configurare da remoto il dispositivo.</translation>
<translation id="6944692733090228304">Hai inserito la password in un sito non gestito da <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Per proteggere il tuo account, non riutilizzare la password con altri siti e app.</translation>
<translation id="6945221475159498467">Seleziona</translation>
<translation id="6948701128805548767">Seleziona un indirizzo per conoscere i requisiti e i metodi di ritiro</translation>
@@ -988,6 +1000,7 @@ Ulteriori dettagli:
&lt;li&gt;Fai clic su &lt;strong&gt;Applica&lt;/strong&gt;, quindi su &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;Visita il &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centro assistenza Chrome&lt;/a&gt; per avere informazioni su come rimuovere definitivamente il software dal computer.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Gestione di <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Gestisci password…</translation>
<translation id="7419106976560586862">Percorso profilo</translation>
<translation id="7437289804838430631">Aggiungi informazioni di contatto</translation>
@@ -996,10 +1009,12 @@ Ulteriori dettagli:
<translation id="7442725080345379071">Arancione chiaro</translation>
<translation id="7444046173054089907">Questo sito è bloccato</translation>
<translation id="7445762425076701745">Impossibile convalidare completamente l'identità del server a cui sei collegato. Sei collegato a un server con un nome valido soltanto nella tua rete, di cui un'autorità di certificazione esterna non può convalidare in alcun modo la proprietà. Poiché alcune autorità di certificazione emettono comunque certificati per questi nomi, non è in alcun modo possibile garantire che tu sia collegato al sito web desiderato anziché a un sito dannoso.</translation>
+<translation id="7449109375006139765">Invia log di sistema al server di gestione</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Leggere ulteriori informazioni<ph name="END_LINK" /> sul problema.</translation>
<translation id="7455133967321480974">Usa predefinita globale (Blocca)</translation>
<translation id="7460618730930299168">I contenuti mostrati sono diversi da quelli che hai selezionato. Continuare?</translation>
<translation id="7473891865547856676">No grazie</translation>
+<translation id="7475525192983021547">Segnala i periodi di attività di un utente sul dispositivo</translation>
<translation id="7481312909269577407">Avanti</translation>
<translation id="7485870689360869515">Nessun dato trovato.</translation>
<translation id="7508255263130623398">L'ID dispositivo della norma restituito è vuoto o non corrisponde all'ID dispositivo corrente</translation>
@@ -1092,6 +1107,7 @@ Ulteriori dettagli:
<translation id="7995512525968007366">Non specificato</translation>
<translation id="800218591365569300">Prova a chiudere altri programmi o schede per liberare spazio in memoria.</translation>
<translation id="8009225694047762179">Gestisci password</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Questa carta e il relativo indirizzo di fatturazione verranno salvati. Potrai usarla dopo aver eseguito l'accesso all'account <ph name="USER_EMAIL" />.}other{Queste carte e i relativi indirizzi di fatturazione verranno salvati. Potrai usarle dopo aver eseguito l'accesso all'account <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">In questo momento, non è possibile raggiungere i tuoi genitori. Riprova.</translation>
<translation id="8025119109950072390">I malintenzionati su questo sito potrebbero indurti con l'inganno a effettuare operazioni pericolose, come installare software o fornire i tuoi dati personali (ad esempio password, numeri di telefono o carte di credito).</translation>
<translation id="8034522405403831421">Questa pagina è in <ph name="SOURCE_LANGUAGE" />. Tradurla in <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1102,6 +1118,7 @@ Ulteriori dettagli:
<translation id="8041940743680923270">Usa predefinita globale (Chiedi)</translation>
<translation id="8042918947222776840">Scegli il metodo di ritiro</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" non è configurato correttamente. La disinstallazione di "<ph name="SOFTWARE_NAME" />" solitamente risolve il problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Sul tuo dispositivo sono state configurate le seguenti norme:</translation>
<translation id="8078141288243656252">Non è possibile inserire annotazioni se il documento è ruotato</translation>
<translation id="8079031581361219619">Vuoi ricaricare il sito?</translation>
<translation id="8088680233425245692">Impossibile visualizzare l'articolo.</translation>
@@ -1152,6 +1169,7 @@ Ulteriori dettagli:
<translation id="8363502534493474904">Disattivare la modalità aereo</translation>
<translation id="8364627913115013041">Non impostato.</translation>
<translation id="8368476060205742148">Google Play Services</translation>
+<translation id="8371889962595521444">Certificati radice personalizzati</translation>
<translation id="8380941800586852976">Pericolosa</translation>
<translation id="8381674639488873545">L'addebito potrebbe essere singolo oppure ricorrente e potrebbe non essere evidente. <ph name="BEGIN_LINK" />Mostra comunque<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">I preferiti visitati di recente vengono visualizzati qui</translation>
@@ -1161,6 +1179,7 @@ Ulteriori dettagli:
<translation id="8416694386774425977">La configurazione di rete non è valida e non può essere importata.
Ulteriori dettagli:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Dispositivo gestito da <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Cambia</translation>
<translation id="8428213095426709021">Impostazioni</translation>
@@ -1221,6 +1240,7 @@ Ulteriori dettagli:
<translation id="8932102934695377596">L'orologio è indietro</translation>
<translation id="893332455753468063">Aggiungi nome</translation>
<translation id="8938939909778640821">Carte di credito e prepagate accettate</translation>
+<translation id="894185898663964645">L'amministratore ha configurato certificati radice personalizzati, che potrebbero consentirgli di vedere i contenuti dei siti web che visiti.</translation>
<translation id="8943282376843390568">Giallo-verde</translation>
<translation id="8957210676456822347">Autorizzazione Captive Portal</translation>
<translation id="8968766641738584599">Salva carta</translation>
diff --git a/chromium/components/strings/components_strings_iw.xtb b/chromium/components/strings/components_strings_iw.xtb
index 67fb3d38bad..309d3de4e66 100644
--- a/chromium/components/strings/components_strings_iw.xtb
+++ b/chromium/components/strings/components_strings_iw.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">דפים ב<ph name="LANGUAGE" /> לא יתורגמו.</translation>
<translation id="2053553514270667976">מספר / מיקוד</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{הצעה אחת}two{שתי הצעות}many{# הצעות}other{# הצעות}}</translation>
+<translation id="2068124040035837596">החשבון שלך מנוהל על-ידי <ph name="ENROLLMENT_DOMAIN" />. המשמעות היא שמנהל המערכת יכול להגדיר מרחוק את תצורת החשבון.</translation>
<translation id="2068663545051464999">הועלה דוח קריסה עם המזהה <ph name="CRASH_ID" /> (הקשר מקומי: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">בטל פעולה</translation>
<translation id="20817612488360358">‏נקבע שימוש בהגדרות שרת Proxy של מערכת אך בנוסף מצוינת גם תצורה מפורשת של שרת Proxy.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">שיטת המשלוח הזו לא זמינה. עליך לבחור שיטה אחרת.</translation>
<translation id="2396249848217231973">&amp;ביטול מחיקה</translation>
<translation id="2413528052993050574">השרת הזה לא הצליח להוכיח שהוא <ph name="DOMAIN" />. ייתכן שאישור האבטחה שלו בוטל. הסיבה לכך עשויה להיות הגדרה שגויה או תוקף המיירט את החיבור שלך.</translation>
+<translation id="244665789865330679">המכשיר והחשבון מנוהלים על-ידי <ph name="ENROLLMENT_DOMAIN" />. המשמעות היא שמנהל המערכת יכול להגדיר מרחוק את תצורת המכשיר והחשבון.</translation>
<translation id="2463193859425327265">שינוי דף הבית</translation>
<translation id="2463739503403862330">מלא</translation>
<translation id="2465655957518002998">בחירת שיטת מסירה</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">ניסית להשיג את <ph name="DOMAIN" />, אך האישור שהשרת הציג בוטל על ידי המנפיק שלו. פירוש הדבר שאין כל אפשרות לתת אמון באישורי האבטחה שהשרת הציג. ייתכן שאתה מתקשר עם תוקף.</translation>
<translation id="4378154925671717803">טלפון</translation>
<translation id="4406896451731180161">תוצאות חיפוש</translation>
+<translation id="4406972042435603828">מנהלי המערכת התקינו אפליקציות עם יכולות נרחבות.</translation>
<translation id="4408413947728134509">‏קובצי Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">כתובת איסוף</translation>
<translation id="4424024547088906515">‏השרת הזה לא הצליח להוכיח שהוא <ph name="DOMAIN" />. אישור האבטחה שלו לא נחשב כמהימן על ידי Chrome. ייתכן שהסיבה לכך היא תצורה שגויה או תוקף המיירט את החיבור שלך.</translation>
@@ -636,10 +639,12 @@ Del</translation>
<translation id="4943872375798546930">אין תוצאות</translation>
<translation id="4950898438188848926">‏לחצן החלפת כרטיסיות, יש להקיש על Enter כדי לעבור לכרטיסייה הפתוחה, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">פעולות</translation>
+<translation id="495832697253704892">דיווח תוספים</translation>
<translation id="4958444002117714549">הרחב רשימה</translation>
<translation id="4974590756084640048">הפעל מחדש אזהרות</translation>
<translation id="4989163558385430922">אני רוצה לראות הכול</translation>
<translation id="4989809363548539747">הפלאגין הזה אינו נתמך</translation>
+<translation id="4996230189582812866">דיווח</translation>
<translation id="5002932099480077015">‏אם האפשרות הזו תופעל, Chrome יאחסן עותק של הכרטיס שלך במכשיר הזה למילוי מהיר יותר של טפסים.</translation>
<translation id="5014174725590676422">‏מוצג מסך ההפעלה הראשונה של Google Assistant ב-Chrome</translation>
<translation id="5015510746216210676">שם המחשב:</translation>
@@ -660,6 +665,7 @@ Del</translation>
<translation id="5089810972385038852">מדינה</translation>
<translation id="5094747076828555589">‏השרת הזה לא הצליח להוכיח שהוא <ph name="DOMAIN" />. אישור האבטחה שלו לא נחשב כמהימן על ידי Chromium. ייתכן שהסיבה לכך היא תצורה שגויה או תוקף המיירט את החיבור שלך.</translation>
<translation id="5095208057601539847">פרובינציה</translation>
+<translation id="5098222253617183465">המכשיר מנוהל על-ידי <ph name="ENROLLMENT_DOMAIN" /> והחשבון מנוהל על-ידי <ph name="ACCOUNT_DOMAIN" />. המשמעות היא שמנהלי המערכות יכולים להגדיר מרחוק את תצורת המכשיר והחשבון.</translation>
<translation id="5115563688576182185">(64 סיביות)</translation>
<translation id="5128122789703661928">שם ההפעלה למחיקה אינו חוקי.</translation>
<translation id="5135404736266831032">ניהול כתובות...</translation>
@@ -672,6 +678,7 @@ Del</translation>
<translation id="5172758083709347301">מכונה</translation>
<translation id="5179510805599951267">לא ב<ph name="ORIGINAL_LANGUAGE" />? דיווח על שגיאה זו</translation>
<translation id="5190835502935405962">סרגל הסימניות</translation>
+<translation id="5200263511887412697">הצגת רשימה של משתמשי המכשיר שהתחברו לאחרונה</translation>
<translation id="5201306358585911203">דף מוטמע בדף הזה אומר</translation>
<translation id="5205222826937269299">שם (חובה)</translation>
<translation id="5215116848420601511">‏אמצעי תשלום וכתובות שנשמרו ב-Google Pay</translation>
@@ -774,6 +781,7 @@ Del</translation>
<translation id="5869405914158311789">לא ניתן לגשת לאתר הזה</translation>
<translation id="5869522115854928033">סיסמאות שמורות</translation>
<translation id="5887400589839399685">הכרטיס נשמר</translation>
+<translation id="5893718151540690985">דיווח רשימה של ממשקי רשתות יחד עם הסוגים וכתובות החומרה שלהם</translation>
<translation id="5893752035575986141">אפשר לשלם באמצעות כרטיסי אשראי.</translation>
<translation id="5901630391730855834">צהוב</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (מסונכרנים)</translation>
@@ -787,6 +795,7 @@ Del</translation>
<translation id="5967592137238574583">עריכת הפרטים ליצירת קשר</translation>
<translation id="5967867314010545767">הסר מההיסטוריה</translation>
<translation id="5975083100439434680">התרחק</translation>
+<translation id="5977489021191000276">המכשיר לא מנוהל על-ידי מנהל מערכת.</translation>
<translation id="5977976211062815271">במכשיר הזה</translation>
<translation id="598637245381783098">לא ניתן לפתוח את אפליקציית התשלומים</translation>
<translation id="5989320800837274978">‏לא צוינו שרתי Proxy קבועים ולא כתובת אתר של סקריפט ‎.pac</translation>
@@ -798,6 +807,7 @@ Del</translation>
<translation id="6017850046339264347">תוקפים שמשתמשים ב-<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> עלולים להתקין יישומים מטעים שמתחזים לאחרים או לאסוף נתונים שאפשר להשתמש בהם כדי לעקוב אחריך. <ph name="BEGIN_LEARN_MORE_LINK" />מידע נוסף<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (מסונכרנים)</translation>
<translation id="6027201098523975773">עליך להזין שם</translation>
+<translation id="6033927989869462158">‏דיווח נתונים סטטיסטיים לגבי חומרה, כמו שימוש ביחידת עיבוד מרכזית (CPU) או בזיכרון RAM</translation>
<translation id="6034000775414344507">אפור בהיר</translation>
<translation id="6039846035001940113">אם הבעיה ממשיכה, יש לפנות אל בעל האתר.</translation>
<translation id="6040143037577758943">סגור</translation>
@@ -910,6 +920,8 @@ Del</translation>
<translation id="6897140037006041989">User agent</translation>
<translation id="6903319715792422884">‏על-ידי שליחה של חלק מ<ph name="BEGIN_WHITEPAPER_LINK" />פרטי המערכת ותוכן הדפים<ph name="END_WHITEPAPER_LINK" /> אל Google, אפשר לעזור בשיפור של 'גלישה בטוחה'. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">משתמש:</translation>
+<translation id="6934672428414710184">‏השם הזה הוא מחשבון Google שלך</translation>
+<translation id="6939583532829045966">המכשיר מנוהל על-ידי <ph name="ENROLLMENT_DOMAIN" />. המשמעות היא שמנהל המערכת יכול להגדיר מרחוק את תצורת המכשיר.</translation>
<translation id="6944692733090228304">הזנת את הסיסמה שלך באתר שלא מנוהל על ידי <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. כדי להגן על החשבון, מומלץ לא להשתמש בסיסמה שלך באפליקציות ובאתרים אחרים.</translation>
<translation id="6945221475159498467">בחר</translation>
<translation id="6948701128805548767">עליך לבחור כתובת כדי לראות שיטות איסוף ודרישות</translation>
@@ -926,7 +938,7 @@ Del</translation>
<translation id="6979440798594660689">השתקה (ברירת מחדל)</translation>
<translation id="6984479912851154518">בחרת לצאת ממצב פרטי כדי לשלם באמצעות אפליקציה חיצונית. להמשיך?</translation>
<translation id="6989763994942163495">הצג הגדרות מתקדמות...</translation>
-<translation id="6996312675313362352">יש תמיד לתרגם <ph name="ORIGINAL_LANGUAGE" /></translation>
+<translation id="6996312675313362352">תמיד לתרגם מ<ph name="ORIGINAL_LANGUAGE" /></translation>
<translation id="7012363358306927923">China UnionPay</translation>
<translation id="7016992613359344582">התשלום עשוי להיות חד-פעמי או לכלול חיובים חוזרים וייתכן שהדרישה לתשלום לא תוצג בצורה ברורה וחד-משמעית.</translation>
<translation id="7029809446516969842">סיסמאות</translation>
@@ -997,6 +1009,7 @@ Del</translation>
&lt;li&gt;לוחצים על &lt;strong&gt;הפעלה&lt;/strong&gt; ולאחר מכן לוחצים על &lt;strong&gt;אישור&lt;/strong&gt;
&lt;li&gt;עוברים אל &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;מרכז העזרה של Chrome&lt;/a&gt; כדי ללמוד כיצד להסיר את התוכנה מהמחשב
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">ניהול <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">ניהול סיסמאות…</translation>
<translation id="7419106976560586862">נתיב פרופיל</translation>
<translation id="7437289804838430631">הוספת פרטים ליצירת קשר</translation>
@@ -1005,10 +1018,12 @@ Del</translation>
<translation id="7442725080345379071">כתום בהיר</translation>
<translation id="7444046173054089907">האתר הזה חסום</translation>
<translation id="7445762425076701745">לא ניתן לאמת לגמרי את הזהות של השרת שאליו אתה מחובר. אתה מחובר לשרת באמצעות שם שקיים רק ברשת שלך, ושלרשות אישורים חיצונית אין דרך לאמת את בעלותך עליו. מכיוון שחלק מרשויות האישורים ינפיקו אישורים לשמות אלה ללא קשר, אין דרך להבטיח שאתה מחובר לאתר המיועד ואינך גורם תוקף.</translation>
+<translation id="7449109375006139765">שליחה של יומני מערכת לשרת הניהול</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />למידע נוסף<ph name="END_LINK" /> על בעיה זו.</translation>
<translation id="7455133967321480974">השתמש בברירת המחדל הכללית (חסום)</translation>
<translation id="7460618730930299168">הסינון שונה ממה שבחרת. להמשיך?</translation>
<translation id="7473891865547856676">לא, תודה</translation>
+<translation id="7475525192983021547">דיווח תקופות זמן שבהן המשתמש פעיל במכשיר</translation>
<translation id="7481312909269577407">קדימה</translation>
<translation id="7485870689360869515">לא נמצאו נתונים.</translation>
<translation id="7508255263130623398">מזהה המכשיר במדיניות שהוחזר ריק או שאינו תואם את מזהה המכשיר הנוכחי</translation>
@@ -1101,6 +1116,7 @@ Del</translation>
<translation id="7995512525968007366">לא צוין</translation>
<translation id="800218591365569300">מומלץ לסגור כרטיסיות או תוכניות אחרות וכך לפנות מקום בזיכרון.</translation>
<translation id="8009225694047762179">ניהול סיסמאות</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{הכרטיס הזה יישמר יחד עם הכתובת שלו לחיוב. יתאפשר לך להשתמש בו לאחר התחברות אל <ph name="USER_EMAIL" />.}two{הכרטיסים האלה יישמרו יחד עם הכתובות שלהם לחיוב. יתאפשר לך להשתמש בהם לאחר התחברות אל <ph name="USER_EMAIL" />.}many{הכרטיסים האלה יישמרו יחד עם הכתובות שלהם לחיוב. יתאפשר לך להשתמש בהם לאחר התחברות אל <ph name="USER_EMAIL" />.}other{הכרטיסים האלה יישמרו יחד עם הכתובות שלהם לחיוב. יתאפשר לך להשתמש בהם לאחר התחברות אל <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">לא הצלחנו ליצור קשר עם ההורים שלך. נסה שוב מאוחר יותר.</translation>
<translation id="8025119109950072390">תוקפים באתר הזה עשויים לגרום לך, בדרכי מרמה, לבצע פעולות מסוכנות כמו התקנת תוכנה או חשיפה של מידע אישי (לדוגמה: סיסמאות, מספרי טלפון או פרטי כרטיסי אשראי).</translation>
<translation id="8034522405403831421">דף זה מוצג ב<ph name="SOURCE_LANGUAGE" />. האם לתרגם אותו ל<ph name="TARGET_LANGUAGE" />?</translation>
@@ -1111,6 +1127,7 @@ Del</translation>
<translation id="8041940743680923270">השתמש בברירת המחדל הכללית (שאל)</translation>
<translation id="8042918947222776840">בחירת שיטת איסוף</translation>
<translation id="8057711352706143257">יש בעיה בהגדרה של "<ph name="SOFTWARE_NAME" />". בדרך כלל, הסרת ההתקנה של "<ph name="SOFTWARE_NAME" />" פותרת את הבעיה. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">במכשיר הוגדרו קביעות המדיניות הבאות:</translation>
<translation id="8078141288243656252">לא ניתן להוסיף הערה במצב מסובב</translation>
<translation id="8079031581361219619">לטעון את האתר מחדש?</translation>
<translation id="8088680233425245692">הצגת הפריט נכשלה.</translation>
@@ -1161,6 +1178,7 @@ Del</translation>
<translation id="8363502534493474904">לכבות את מצב הטיסה</translation>
<translation id="8364627913115013041">לא מוגדר.</translation>
<translation id="8368476060205742148">‏שירותי Google Play</translation>
+<translation id="8371889962595521444">אישורי בסיס בהתאמה אישית</translation>
<translation id="8380941800586852976">מסוכן</translation>
<translation id="8381674639488873545">החיובים האלה יכולים להיות חד פעמיים או חוזרים, והם לא תמיד מוצגים בצורה בולטת. <ph name="BEGIN_LINK" />אני רוצה להמשיך בכל זאת<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">הסימניות שאליהן נכנסת לאחרונה מופיעות כאן</translation>
@@ -1170,6 +1188,7 @@ Del</translation>
<translation id="8416694386774425977">תצורת הרשת אינה חוקית ולא ניתן לייבא אותה.
פרטים נוספים:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">המכשיר מנוהל על-ידי <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">שנה</translation>
<translation id="8428213095426709021">הגדרות</translation>
@@ -1231,6 +1250,7 @@ Del</translation>
<translation id="8932102934695377596">השעון שלך מאחר</translation>
<translation id="893332455753468063">הוספת שם</translation>
<translation id="8938939909778640821">כרטיסי אשראי וכרטיסים משולמים מראש שהסוחר מקבל</translation>
+<translation id="894185898663964645">מנהל המערכת הגדיר אישורי בסיס מותאמים אישית, וייתכן שיש לו אפשרות לראות את תוכן האתרים שנכנסת אליהם.</translation>
<translation id="8943282376843390568">ליים</translation>
<translation id="8957210676456822347">הרשאת פורטל חובה</translation>
<translation id="8968766641738584599">שמירת הכרטיס</translation>
diff --git a/chromium/components/strings/components_strings_ja.xtb b/chromium/components/strings/components_strings_ja.xtb
index 5e65392e738..e9f13372fef 100644
--- a/chromium/components/strings/components_strings_ja.xtb
+++ b/chromium/components/strings/components_strings_ja.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" />のページは翻訳されません。</translation>
<translation id="2053553514270667976">郵便番号</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 件の候補}other{# 件の候補}}</translation>
+<translation id="2068124040035837596">ご使用のアカウントは <ph name="ENROLLMENT_DOMAIN" /> で管理されています。管理者はアカウントをリモートで設定できます。</translation>
<translation id="2068663545051464999">クラッシュ レポート ID <ph name="CRASH_ID" /> がアップロードされました(ローカル コンテキスト: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">元に戻す</translation>
<translation id="20817612488360358">システム プロキシ設定を使用するように設定されていますが、明示的なプロキシの設定も指定されています。</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">この配送方法はご利用いただけません。別の方法を選択してください。</translation>
<translation id="2396249848217231973">削除の取り消し(&amp;U)</translation>
<translation id="2413528052993050574">このサーバーが <ph name="DOMAIN" /> であることを確認できませんでした。このサーバーのセキュリティ証明書は取り消されている可能性があります。原因としては、不適切な設定や、悪意のあるユーザーによる接続妨害が考えられます。</translation>
+<translation id="244665789865330679">ご使用のデバイスとアカウントは <ph name="ENROLLMENT_DOMAIN" /> で管理されています。管理者はデバイスとアカウントをリモートで設定できます。</translation>
<translation id="2463193859425327265">ホームページを変更する</translation>
<translation id="2463739503403862330">入力する</translation>
<translation id="2465655957518002998">配達方法を選択</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> にアクセスしようとしましたが、サーバーから提示された証明書は発行元により取り消されています。これは、サーバーから提示されたセキュリティ認証情報が信頼できないことを示しており、悪意のあるユーザーと通信しようとしている可能性があります。</translation>
<translation id="4378154925671717803">電話</translation>
<translation id="4406896451731180161">検索結果</translation>
+<translation id="4406972042435603828">管理者が強力な機能を持つ拡張機能をインストールしました。</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">集荷先住所</translation>
<translation id="4424024547088906515">このサーバーが <ph name="DOMAIN" /> であることを確認できませんでした。このサーバーのセキュリティ証明書は Chrome によって信頼されているものではありません。原因としては、不適切な設定や、悪意のあるユーザーによる接続妨害が考えられます。</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">結果はありません</translation>
<translation id="4950898438188848926">タブの切り替えボタンです。Enter キーを押すと開いているタブ「<ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />」に切り替わります</translation>
<translation id="495170559598752135">操作</translation>
+<translation id="495832697253704892">拡張機能に関するレポート</translation>
<translation id="4958444002117714549">リストを展開する</translation>
<translation id="4974590756084640048">警告を再度有効にする</translation>
<translation id="4989163558385430922">すべて表示</translation>
<translation id="4989809363548539747">このプラグインはサポートされていません</translation>
+<translation id="4996230189582812866">レポート</translation>
<translation id="5002932099480077015">有効にすると、Chrome ではこの端末にカードのコピーが保存されます。これにより、フォームにすばやく入力できるようになります。</translation>
<translation id="5014174725590676422">Chrome の Google アシスタントの初回実行画面が表示されました</translation>
<translation id="5015510746216210676">マシン名:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">都道府県 / 州</translation>
<translation id="5094747076828555589">このサーバーが <ph name="DOMAIN" /> であることを確認できませんでした。このサーバーのセキュリティ証明書は Chromium によって信頼されているものではありません。原因としては、不適切な設定や、悪意のあるユーザーによる接続妨害が考えられます。</translation>
<translation id="5095208057601539847">地方</translation>
+<translation id="5098222253617183465">ご使用のデバイスは <ph name="ENROLLMENT_DOMAIN" /> で管理され、アカウントは <ph name="ACCOUNT_DOMAIN" /> で管理されています。それぞれの管理者はデバイスやアカウントをリモートで設定できます。</translation>
<translation id="5115563688576182185">(64 ビット)</translation>
<translation id="5128122789703661928">セッションの名前が有効でないため、削除できません。</translation>
<translation id="5135404736266831032">住所を管理...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">マシン</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" />でない場合はこのエラーを報告する</translation>
<translation id="5190835502935405962">ブックマーク バー</translation>
+<translation id="5200263511887412697">最近ログインしたデバイス ユーザーのリストを報告します</translation>
<translation id="5201306358585911203">このページに埋め込まれているページの内容</translation>
<translation id="5205222826937269299">名前は必須です</translation>
<translation id="5215116848420601511">Google Pay のお支払い方法と住所</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">このサイトにアクセスできません</translation>
<translation id="5869522115854928033">保存したパスワード</translation>
<translation id="5887400589839399685">カードが保存されました</translation>
+<translation id="5893718151540690985">ネットワーク インターフェースの種類とハードウェア アドレスのリストを報告します</translation>
<translation id="5893752035575986141">クレジット カードをご利用いただけます。</translation>
<translation id="5901630391730855834">黄</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" />(同期済み)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">連絡先情報の編集</translation>
<translation id="5967867314010545767">履歴から削除</translation>
<translation id="5975083100439434680">縮小する</translation>
+<translation id="5977489021191000276">お使いのデバイスは管理者によって管理されていません。</translation>
<translation id="5977976211062815271">このデバイス</translation>
<translation id="598637245381783098">お支払いアプリを開けません</translation>
<translation id="5989320800837274978">固定プロキシ サーバーと .pac スクリプト URL のどちらも指定されていません。</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> では、悪意のあるユーザーによって詐欺的なアプリ(他のものに成りすましたり、ユーザーの追跡などに使用可能なデータを収集したりするアプリ)がインストールされる可能性があります。<ph name="BEGIN_LEARN_MORE_LINK" />詳細<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />、<ph name="TYPE_2" />、<ph name="TYPE_3" />(同期済み)</translation>
<translation id="6027201098523975773">名前を入力してください</translation>
+<translation id="6033927989869462158">CPU や RAM の使用率などのハードウェア統計情報を報告します</translation>
<translation id="6034000775414344507">ライトグレー</translation>
<translation id="6039846035001940113">この問題が何度も発生する場合は、サイト所有者にお問い合わせください。</translation>
<translation id="6040143037577758943">閉じる</translation>
@@ -812,7 +822,7 @@
<translation id="614940544461990577">次をお試しください:</translation>
<translation id="6151417162996330722">サーバー証明書の有効期限が長すぎます。</translation>
<translation id="6157877588268064908">配送方法と要件を確認するには、住所を選択してください</translation>
-<translation id="6165508094623778733">詳細</translation>
+<translation id="6165508094623778733">詳しく見る</translation>
<translation id="6169916984152623906">現在、シークレット モードで閲覧しています。あなたのアクティビティは、この端末を利用する他のユーザーには表示されません。ただし、ダウンロードしたファイルとブックマークは通常どおり保存されます。</translation>
<translation id="6177128806592000436">このサイトへの接続は保護されていません</translation>
<translation id="6203231073485539293">インターネット接続を確認してください</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">ユーザー エージェント</translation>
<translation id="6903319715792422884"><ph name="BEGIN_WHITEPAPER_LINK" />一部のシステム情報とページのコンテンツ<ph name="END_WHITEPAPER_LINK" />を Google に送信して、セーフ ブラウジングの改善にご協力ください。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ユーザー:</translation>
+<translation id="6934672428414710184">Google アカウントで設定されている名前です</translation>
+<translation id="6939583532829045966">ご使用のデバイスは <ph name="ENROLLMENT_DOMAIN" /> で管理されています。管理者はデバイスをリモートで設定できます。</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> が管理していないサイトでパスワードを入力しました。アカウントを保護するには、他のアプリやサイトでパスワードを再使用しないでください。</translation>
<translation id="6945221475159498467">選択</translation>
<translation id="6948701128805548767">受け取り方法と要件を確認するには、住所を選択してください</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;[&lt;strong&gt;適用&lt;/strong&gt;] をクリックし、[&lt;strong&gt;OK&lt;/strong&gt;] をクリックします。
&lt;li&gt;このソフトウェアをパソコンから完全に削除する方法については、&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome ヘルプセンター&lt;/a&gt;をご覧ください。
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> の管理</translation>
<translation id="7416351320495623771">パスワードを管理…</translation>
<translation id="7419106976560586862">プロフィール パス</translation>
<translation id="7437289804838430631">連絡先情報を追加</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">ライトオレンジ</translation>
<translation id="7444046173054089907">このサイトはブロックされています</translation>
<translation id="7445762425076701745">接続してるサーバーの身元について、十分な検証ができません。接続しているサーバーは、そのネットワーク内でのみ有効な名前を使用しており、外部認証局がその所有権を検証する方法はありません。こうした名前で証明書を発行する認証局もあるので、接続先が意図したウェブサイトか、悪意のあるユーザーのサイトかは確認できません。</translation>
+<translation id="7449109375006139765">システムログを管理サーバーに送信します</translation>
<translation id="7451311239929941790">この問題について<ph name="BEGIN_LINK" />詳細を確認<ph name="END_LINK" />する</translation>
<translation id="7455133967321480974">グローバルのデフォルト値([ブロック])を使用</translation>
<translation id="7460618730930299168">スクリーニングが選択内容と異なっています。続行しますか?</translation>
<translation id="7473891865547856676">スキップ</translation>
+<translation id="7475525192983021547">ユーザーがデバイスを操作した時間を報告します</translation>
<translation id="7481312909269577407">進む</translation>
<translation id="7485870689360869515">データが見つかりません。</translation>
<translation id="7508255263130623398">返されたポリシーの端末 ID が空であるか、現在の端末 ID と一致しません</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">指定なし</translation>
<translation id="800218591365569300">メモリを解放するために、他のタブやプログラムを閉じてみてください。</translation>
<translation id="8009225694047762179">パスワードを管理</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{このカードと請求先住所は保存され、<ph name="USER_EMAIL" /> にログインすると使用できます。}other{これらのカードと請求先住所は保存され、<ph name="USER_EMAIL" /> にログインすると使用できます。}}</translation>
<translation id="8012647001091218357">現在、保護者にたずねることができません。もう一度お試しください。</translation>
<translation id="8025119109950072390">このサイトを利用すると、悪意のあるユーザーによって、ソフトウェアのインストールや個人情報(例: パスワード、電話番号、クレジット カード番号)の入力などの危険な操作を行うよう誘導される可能性があります。</translation>
<translation id="8034522405403831421">このページの言語は<ph name="SOURCE_LANGUAGE" />です。<ph name="TARGET_LANGUAGE" />に翻訳しますか?</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">グローバルのデフォルト値([確認])を使用</translation>
<translation id="8042918947222776840">集荷方法を選択</translation>
<translation id="8057711352706143257">「<ph name="SOFTWARE_NAME" />」が正しく設定されていません。通常、この問題は「<ph name="SOFTWARE_NAME" />」をアンインストールすることで解決します。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">お使いのデバイスは次のように設定されています:</translation>
<translation id="8078141288243656252">回転時に注釈を追加することはできません</translation>
<translation id="8079031581361219619">このサイトを再読み込みしますか?</translation>
<translation id="8088680233425245692">記事を表示できませんでした。</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">機内モードをオフにする</translation>
<translation id="8364627913115013041">未設定</translation>
<translation id="8368476060205742148">Google Play 開発者サービス</translation>
+<translation id="8371889962595521444">カスタムルート証明書</translation>
<translation id="8380941800586852976">危険</translation>
<translation id="8381674639488873545">料金の請求は 1 回限りの場合も毎月行われる場合もあり、課金されたかどうかわからないこともあります。<ph name="BEGIN_LINK" />理解したうえで表示する<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">最近アクセスしたブックマークがここに表示されます</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">ネットワーク設定が無効なためインポートできませんでした。
詳細:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533"><ph name="ENROLLMENT_DOMAIN" /> で管理されているデバイス</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">変更</translation>
<translation id="8428213095426709021">設定</translation>
@@ -1226,6 +1245,7 @@
<translation id="8932102934695377596">時計が遅れています</translation>
<translation id="893332455753468063">名前の追加</translation>
<translation id="8938939909778640821">利用可能なクレジット カードとプリペイド カード</translation>
+<translation id="894185898663964645">管理者がカスタムルート証明書を設定しています。管理者は、ユーザーがアクセスしたウェブサイトのコンテンツを表示できます。</translation>
<translation id="8943282376843390568">ライム</translation>
<translation id="8957210676456822347">キャプティブ ポータル認証</translation>
<translation id="8968766641738584599">カードを保存</translation>
diff --git a/chromium/components/strings/components_strings_kn.xtb b/chromium/components/strings/components_strings_kn.xtb
index b6547aaccb0..358b11de992 100644
--- a/chromium/components/strings/components_strings_kn.xtb
+++ b/chromium/components/strings/components_strings_kn.xtb
@@ -36,7 +36,7 @@
<translation id="1165039591588034296">ದೋಷ</translation>
<translation id="1173894706177603556">ಮರುಹೆಸರಿಸು</translation>
<translation id="1175364870820465910">&amp;ಮುದ್ರಿಸಿ...</translation>
-<translation id="1181037720776840403">ತೆಗೆದುಹಾಕಿ</translation>
+<translation id="1181037720776840403">ತೆಗೆದುಹಾಕು</translation>
<translation id="1197088940767939838">ಕಿತ್ತಳೆ</translation>
<translation id="1201402288615127009">ಮುಂದೆ</translation>
<translation id="1201895884277373915">ಈ ಸೈಟ್‌ನಿಂದ ಇನ್ನಷ್ಟು</translation>
@@ -185,6 +185,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" />ಭಾಷೆಯಲ್ಲಿರುವ ಪುಟಗಳು ಅನುವಾದಕ್ಕೊಳಪಡುವುದಿಲ್ಲ.</translation>
<translation id="2053553514270667976">ಪಿನ್ ಕೋಡ್</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ಸಲಹೆ}one{# ಸಲಹೆಗಳು}other{# ಸಲಹೆಗಳು}}</translation>
+<translation id="2068124040035837596">ನಿಮ್ಮ ಖಾತೆಯನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ. ಅಂದರೆ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಖಾತೆಯನ್ನು ದೂರದಿಂದಲೇ ಕಾನ್ಫಿಗರ್ ಮಾಡಬಹುದು ಎಂದರ್ಥ.</translation>
<translation id="2068663545051464999">ಅಪ್‌ಲೋಡ್ ಮಾಡಿದ ಕ್ರ್ಯಾಶ್ ವರದಿ ಐಡಿ <ph name="CRASH_ID" /> (ಸ್ಥಳೀಯ ಸಂದರ್ಭ: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">ರದ್ದುಮಾಡಿ</translation>
<translation id="20817612488360358">ಸಿಸ್ಟಂ ಪ್ರಾಕ್ಸಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬಳಸಲು ಹೊಂದಿಸಲಾಗಿದೆ ಆದರೆ ಬಹಿರಂಗವಾದ ಪ್ರಾಕ್ಸಿ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಸಹ ನಿರ್ದಿಷ್ಟಪಡಿಸಲಾಗಿದೆ.</translation>
@@ -243,6 +244,7 @@
<translation id="239429038616798445">ಈ ಶಿಪ್ಪಿಂಗ್ ವಿಧಾನ ಲಭ್ಯವಿಲ್ಲ. ಬೇರೊಂದು ವಿಧಾನವನ್ನು ಪ್ರಯತ್ನಿಸಿ.</translation>
<translation id="2396249848217231973">&amp;ಅಳಿಸುವುದನ್ನು ರದ್ದುಗೊಳಿಸು</translation>
<translation id="2413528052993050574">ಈ ಸರ್ವರ್ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬುದನ್ನು ಸಾಬೀತುಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ; ಅದರ ಸುರಕ್ಷತಾ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಹಿಂತೆಗೆದುಕೊಳ್ಳಲಾಗಿರಬಹುದು. ಇದು ತಪ್ಪು ಕಾನ್ಫಿಗರೇಶನ್‌ನಿಂದ ಅಥವಾ ಆಕ್ರಮಣಕಾರರು ನಿಮ್ಮ ಸಂಪರ್ಕದಲ್ಲಿ ಒಳನುಸುಳಿರುವುದರಿಂದ ಆಗಿರಬಹುದು.</translation>
+<translation id="244665789865330679">ನಿಮ್ಮ ಸಾಧನ ಮತ್ತು ಖಾತೆಯನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ. ಅಂದರೆ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಸಾಧನ ಮತ್ತು ಖಾತೆಯನ್ನು ದೂರದಿಂದಲೇ ಕಾನ್ಫಿಗರ್ ಮಾಡಬಹುದು ಎಂದರ್ಥ.</translation>
<translation id="2463193859425327265">ಮುಖಪುಟವನ್ನು ಬದಲಾಯಿಸಿ</translation>
<translation id="2463739503403862330">ಭರ್ತಿ ಮಾಡು</translation>
<translation id="2465655957518002998">ವಿತರಣೆ ವಿಧಾನವನ್ನು ಆರಿಸಿ</translation>
@@ -557,6 +559,7 @@
<translation id="4377125064752653719">ನೀವು <ph name="DOMAIN" /> ಅನ್ನು ತಲುಪಲು ಪ್ರಯತ್ನಿಸಿದಿರಿ, ಆದರೆ ಸರ್ವರ್ ನೀಡಿದ ಪ್ರಮಾಣಪತ್ರವನ್ನು ಅದರ ನೀಡುವವರು ಹಿಂತೆಗೆದುಕೊಂಡಿದ್ದಾರೆ. ಇದರರ್ಥ ಸರ್ವರ್ ನೀಡಿದ ಸುರಕ್ಷತೆ ರುಜುವಾತುಗಳನ್ನು ಖಂಡಿತವಾಗಿ ನಂಬಲಾಗುವುದಿಲ್ಲ. ನೀವು ಆಕ್ರಮಣಕಾರರೊಂದಿಗೆ ಸಂವಹಿಸುತ್ತಿರಬಹುದು.</translation>
<translation id="4378154925671717803">ಫೋನ್</translation>
<translation id="4406896451731180161">ಹುಡುಕಾಟದ ಫಲಿತಾಂಶಗಳು</translation>
+<translation id="4406972042435603828">ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಪ್ರಬಲ ಸಾಮರ್ಥ್ಯಗಳನ್ನು ಹೊಂದಿರುವ ವಿಸ್ತರಣೆಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿದ್ದಾರೆ.</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> ಕುಕೀಗಳು</translation>
<translation id="4415426530740016218">ಪಿಕಪ್ ವಿಳಾಸ</translation>
<translation id="4424024547088906515">ಈ ಸರ್ವರ್ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬುದನ್ನು ಸಾಬೀತುಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ; ಅದರ ಸುರಕ್ಷತಾ ಪ್ರಮಾಣಪತ್ರವು Chrome ಪಾಲಿಗೆ ವಿಶ್ವಾಸಾರ್ಹವಾಗಿಲ್ಲ. ಇದು ತಪ್ಪು ಕಾನ್ಫಿಗರೇಶನ್‌ನಿಂದ ಅಥವಾ ಆಕ್ರಮಣಕಾರರು ನಿಮ್ಮ ಸಂಪರ್ಕದಲ್ಲಿ ಒಳನುಸುಳಿರುವುದರಿಂದ ಆಗಿರಬಹುದು.</translation>
@@ -628,10 +631,12 @@
<translation id="4943872375798546930">ಯಾವುದೇ ಫಲಿತಾಂಶಗಳಿಲ್ಲ</translation>
<translation id="4950898438188848926">ಟ್ಯಾಬ್ ಬದಲಿಸುವ ಬಟನ್, ತೆರೆದಿರುವ ಟ್ಯಾಬ್, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /> ಗೆ ಬದಲಾಯಿಸಲು Enter ಒತ್ತಿರಿ</translation>
<translation id="495170559598752135">ಕ್ರಿಯೆಗಳು</translation>
+<translation id="495832697253704892">ವಿಸ್ತರಣೆ ವರದಿ ಮಾಡುವಿಕೆ</translation>
<translation id="4958444002117714549">ಪಟ್ಟಿಯನ್ನು ವಿಸ್ತರಿಸಿ</translation>
<translation id="4974590756084640048">ಎಚ್ಚರಿಕೆಗಳನ್ನು ಮರುಸಕ್ರಿಯಗೊಳಿಸಿ</translation>
<translation id="4989163558385430922">ಎಲ್ಲವನ್ನೂ ನೋಡಿ</translation>
<translation id="4989809363548539747">ಈ ಪ್ಲಗಿನ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ</translation>
+<translation id="4996230189582812866">ವರದಿ ಮಾಡುವಿಕೆ</translation>
<translation id="5002932099480077015">ಸಕ್ರಿಯವಾಗಿದ್ದರೆ, ವೇಗವಾಗಿ ಫಾರ್ಮ್ ಭರ್ತಿ ಮಾಡಲು Chrome ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಕಾರ್ಡ್‌ನ ಪ್ರತಿಯನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ.</translation>
<translation id="5014174725590676422">Chrome ನಲ್ಲಿನ Google ಅಸಿಸ್ಟೆಂಟ್‌ನ ಮೊದಲ ಬಾರಿ ರನ್ ಮಾಡಿದ ಸ್ಕ್ರೀನ್ ಅನ್ನು ತೋರಿಸಲಾಗಿದೆ</translation>
<translation id="5015510746216210676">ಯಂತ್ರದ ಹೆಸರು:</translation>
@@ -652,6 +657,7 @@
<translation id="5089810972385038852">ರಾಜ್ಯ</translation>
<translation id="5094747076828555589">ಈ ಸರ್ವರ್ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬುದನ್ನು ಸಾಬೀತುಪಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ; ಅದರ ಸುರಕ್ಷತಾ ಪ್ರಮಾಣಪತ್ರವು Chromium ಮೂಲಕ ವಿಶ್ವಾಸಾರ್ಹವಾಗಿಲ್ಲ. ಇದು ತಪ್ಪು ಕಾನ್ಫಿಗರೇಶನ್‌ನಿಂದ ಅಥವಾ ಆಕ್ರಮಣಕಾರರು ನಿಮ್ಮ ಸಂಪರ್ಕದಲ್ಲಿ ಒಳನುಸುಳಿರುವುದರಿಂದ ಆಗಿರಬಹುದು.</translation>
<translation id="5095208057601539847">ಪ್ರಾಂತ್ಯ</translation>
+<translation id="5098222253617183465">ನಿಮ್ಮ ಸಾಧನವನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ ಮತ್ತು ನಿಮ್ಮ ಖಾತೆಯನ್ನು <ph name="ACCOUNT_DOMAIN" /> ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ. ಅಂದರೆ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಸಾಧನ ಮತ್ತು ಖಾತೆಯನ್ನು ದೂರದಿಂದಲೇ ಕಾನ್ಫಿಗರ್ ಮಾಡಬಹುದು ಎಂದರ್ಥ.</translation>
<translation id="5115563688576182185">(64-ಬಿಟ್)</translation>
<translation id="5128122789703661928">ಈ ಹೆಸರಿನ ಸೆಶನ್ ಅಳಿಸಲು ಮಾನ್ಯವಾಗಿಲ್ಲ.</translation>
<translation id="5135404736266831032">ವಿಳಾಸಗಳನ್ನು ನಿರ್ವಹಿಸಿ...</translation>
@@ -664,6 +670,7 @@
<translation id="5172758083709347301">ಯಂತ್ರ</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> ರಲ್ಲಿ ಇಲ್ಲವೆ? ಈ ದೋಷವನ್ನು ವರದಿ ಮಾಡಿ</translation>
<translation id="5190835502935405962">ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳ ಬಾರ್</translation>
+<translation id="5200263511887412697">ಸಾಧನವನ್ನು ಇತ್ತೀಚೆಗೆ ಬಳಸಿರುವ ಬಳಕೆದಾರರ ಪಟ್ಟಿಯನ್ನು ವರದಿ ಮಾಡಿ</translation>
<translation id="5201306358585911203">ಈ ಪುಟದಲ್ಲಿ ಎಂಬೆಡ್ ಮಾಡಲಾದ ಪುಟವು ಹೀಗೆ ಹೇಳುತ್ತದೆ</translation>
<translation id="5205222826937269299">ಹೆಸರು ಅವಶ್ಯವಾಗಿದೆ</translation>
<translation id="5215116848420601511">Google Pay ಅನ್ನು ಬಳಸುವ ಪಾವತಿ ವಿಧಾನಗಳು ಮತ್ತು ವಿಳಾಸಗಳು</translation>
@@ -765,6 +772,7 @@
<translation id="5869405914158311789">ಈ ಸೈಟ್ ತಲುಪಲಾಗುವುದಿಲ್ಲ</translation>
<translation id="5869522115854928033">ಉಳಿಸಲಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು</translation>
<translation id="5887400589839399685">ಕಾರ್ಡ್ ಉಳಿಸಲಾಗಿದೆ</translation>
+<translation id="5893718151540690985">ನೆಟ್‌ವರ್ಕ್ ಇಂಟರ್ಫೇಸ್‌ಗಳ ಪಟ್ಟಿಯನ್ನು ಅದರ ಪ್ರಕಾರಗಳು ಮತ್ತು ಹಾರ್ಡ್‌ವೇರ್ ವಿಳಾಸಗಳ ಸಮೇತವಾಗಿ ವರದಿ ಮಾಡಿ</translation>
<translation id="5893752035575986141">ಕ್ರೆಡಿಟ್‌ ಕಾರ್ಡ್‌ಗಳನ್ನು ಸಮ್ಮತಿಸಲಾಗಿದೆ.</translation>
<translation id="5901630391730855834">ಹಳದಿ</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (ಸಿಂಕ್‌ ಮಾಡಲಾಗಿದೆ)</translation>
@@ -778,6 +786,7 @@
<translation id="5967592137238574583">ಸಂಪರ್ಕ ಮಾಹಿತಿಯನ್ನು ಎಡಿಟ್ ಮಾಡಿ</translation>
<translation id="5967867314010545767">ಇತಿಹಾಸದಿಂದ ತೆಗೆದುಹಾಕಿ</translation>
<translation id="5975083100439434680">ಝೂಮ್ ಔಟ್</translation>
+<translation id="5977489021191000276">ನಿಮ್ಮ ಸಾಧನವನ್ನು ಓರ್ವ ನಿರ್ವಾಹಕರು ನಿರ್ವಹಿಸುತ್ತಿಲ್ಲ.</translation>
<translation id="5977976211062815271">ಈ ಸಾಧನದಲ್ಲಿರುವವು</translation>
<translation id="598637245381783098">ಪಾವತಿ ಅಪ್ಲಿಕೇಶನ್ ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ</translation>
<translation id="5989320800837274978">ಹೊಂದಿಸಿದ ಪ್ರಾಕ್ಸಿ ಸರ್ವರ್‌ಗಳು ಆಗಲಿ ಅಥವಾ .pac ಸ್ಕ್ರಿಪ್ಟ್ URL ಅನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿಲ್ಲ.</translation>
@@ -789,6 +798,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ನಲ್ಲಿನ ದಾಳಿಕೋರರು ವಂಚನೆಯ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ, ನಿಮ್ಮನ್ನು ಟ್ರ್ಯಾಕ್ ಮಾಡಲು ಬಳಸಬಹುದಾದ ಬೇರೆ ಯಾವುದಾದರೂ ಮಾಹಿತಿ ಅಥವಾ ಡೇಟಾ ಸಂಗ್ರಹಿಸುವ ಸಾಧ್ಯವಿದೆ. <ph name="BEGIN_LEARN_MORE_LINK" />ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (ಸಿಂಕ್‌ ಮಾಡಲಾಗಿದೆ)</translation>
<translation id="6027201098523975773">ಹೆಸರು ನಮೂದಿಸಿ</translation>
+<translation id="6033927989869462158">CPU/RAM ಬಳಕೆ ರೀತಿಯ ಹಾರ್ಡ್‌ವೇರ್ ಅಂಕಿಅಂಶಗಳನ್ನು ವರದಿ ಮಾಡಿ</translation>
<translation id="6034000775414344507">ತಿಳಿ ಬೂದು</translation>
<translation id="6039846035001940113">ಸಮಸ್ಯೆ ಮುಂದುವರಿದರೆ, ಸೈಟ್ ಮಾಲೀಕರನ್ನು ಸಂಪರ್ಕಿಸಿ.</translation>
<translation id="6040143037577758943">ಮುಚ್ಚಿರಿ</translation>
@@ -825,7 +835,7 @@
<translation id="627746635834430766">ಮುಂದಿನ ಬಾರಿ ವೇಗವಾಗಿ ಪಾವತಿಸಲು, ನಿಮ್ಮ ಕಾರ್ಡ್‌ ಮತ್ತು ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸವನ್ನು ನಿಮ್ಮ Google ಖಾತೆಯಲ್ಲಿ ಉಳಿಸಿ.</translation>
<translation id="6280223929691119688">ಈ ವಿಳಾಸಕ್ಕೆ ತಲುಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಬೇರೊಂದು ವಿಳಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ.</translation>
<translation id="6282194474023008486">ಪೋಸ್ಟಲ್ ಕೋಡ್</translation>
-<translation id="6290238015253830360">ನಿಮ್ಮ ಸೂಚಿತ ಲೇಖನಗಳು ಇಲ್ಲಿ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತವೆ</translation>
+<translation id="6290238015253830360">ನೀವು ಸಲಹೆ ನೀಡಿರುವ ಲೇಖನಗಳು ಇಲ್ಲಿ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತವೆ</translation>
<translation id="6302269476990306341">Chrome ನಲ್ಲಿನ Google ಅಸಿಸ್ಟೆಂಟ್ ನಿಲ್ಲುತ್ತಿದೆ</translation>
<translation id="6305205051461490394"><ph name="URL" /> ತಲುಪಲಾಗುವುದಿಲ್ಲ.</translation>
<translation id="6321917430147971392">ನಿಮ್ಮ DNS ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ</translation>
@@ -900,6 +910,8 @@
<translation id="6897140037006041989">ಬಳಕೆದಾರ ಏಜೆಂಟ್</translation>
<translation id="6903319715792422884"><ph name="BEGIN_WHITEPAPER_LINK" />ಸಿಸ್ಟಂ ಕುರಿತು ಕೆಲವೊಂದು ಮಾಹಿತಿಯನ್ನು ಮತ್ತು ಪುಟದ ವಿಷಯವನ್ನು<ph name="END_WHITEPAPER_LINK" /> Google ಗೆ ಕಳುಹಿಸುವ ಮೂಲಕ, ಸುರಕ್ಷಿತ ಬ್ರೌಸಿಂಗ್ ಅನ್ನು ಸುಧಾರಿಸಲು ಸಹಾಯ ಮಾಡಿ. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ಬಳಕೆದಾರ:</translation>
+<translation id="6934672428414710184">ಈ ಹೆಸರು ನಿಮ್ಮ Google ಖಾತೆಯಿಂದ ಬಂದಿದೆ</translation>
+<translation id="6939583532829045966">ನಿಮ್ಮ ಸಾಧನವನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ. ಅಂದರೆ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಸಾಧನವನ್ನು ದೂರದಿಂದಲೇ ಕಾನ್ಫಿಗರ್ ಮಾಡಬಹುದು ಎಂದರ್ಥ.</translation>
<translation id="6944692733090228304">ನೀವು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ನಿರ್ವಹಣೆ ಮಾಡದ ಸೈಟ್‌ನಲ್ಲಿ ನಮೂದಿಸಿದ್ದೀರಿ. ನಿಮ್ಮ ಖಾತೆಯನ್ನು ರಕ್ಷಿಸಲು, ಇತರ ಆ್ಯಪ್‌ಗಳಲ್ಲಿ ಮತ್ತು ಸೈಟ್‌ಗಳಲ್ಲಿ ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ ಅನ್ನು ಮರುಬಳಕೆ ಮಾಡಬೇಡಿ.</translation>
<translation id="6945221475159498467">ಆಯ್ಕೆಮಾಡಿ</translation>
<translation id="6948701128805548767">ಪಿಕಪ್ ವಿಧಾನಗಳು ಹಾಗೂ ಆವಶ್ಯಕತೆಗಳನ್ನು ನೋಡಲು, ಒಂದು ವಿಳಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ</translation>
@@ -942,7 +954,7 @@
<translation id="717330890047184534">Gaia ಐಡಿ:</translation>
<translation id="7175401108899573750">{SHIPPING_OPTIONS,plural, =0{<ph name="SHIPPING_OPTION_PREVIEW" />}=1{<ph name="SHIPPING_OPTION_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ಇನ್ನಷ್ಟು}one{<ph name="SHIPPING_OPTION_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ಇನ್ನಷ್ಟು}other{<ph name="SHIPPING_OPTION_PREVIEW" /> ಮತ್ತು <ph name="NUMBER_OF_ADDITIONAL_SHIPPING_OPTIONS" /> ಇನ್ನಷ್ಟು}}</translation>
<translation id="7179323680825933600">ಪಾವತಿ ವಿಧಾನಗಳನ್ನು ಉಳಿಸಿ ಮತ್ತು ಭರ್ತಿ ಮಾಡಿ</translation>
-<translation id="7180611975245234373">ರಿಫ್ರೆಶ್</translation>
+<translation id="7180611975245234373">ರಿಫ್ರೆಶ್ ಮಾಡಿ</translation>
<translation id="7182878459783632708">ಯಾವುದೇ ನೀತಿಗಳನ್ನು ಹೊಂದಿಸಿಲ್ಲ</translation>
<translation id="7186367841673660872">ಈ ಪುಟವನ್ನು<ph name="ORIGINAL_LANGUAGE" />ನಿಂದ<ph name="LANGUAGE_LANGUAGE" />ಗೆ ಭಾಷಾಂತರಿಸಲಾಗಿದೆ</translation>
<translation id="7192203810768312527"><ph name="SIZE" /> ತೆಗೆದುಹಾಕಿ. ನಿಮ್ಮ ನಂತರದ ಭೇಟಿಯ ಸಮಯದಲ್ಲಿ ಕೆಲವು ಸೈಟ್‌ಗಳು ನಿಧಾನವಾಗಿ ಲೋಡ್ ಆಗಬಹುದು.</translation>
@@ -986,6 +998,7 @@
&lt;li&gt;&lt;strong&gt;ಸೇವೆಯ ಸ್ಥಿತಿಯ&lt;/strong&gt; ಅಡಿಯಲ್ಲಿ, &lt;strong&gt;ನಿಲ್ಲಿಸಿ&lt;/strong&gt; ಕ್ಲಿಕ್ ಮಾಡಿ
&lt;li&gt; &lt;strong&gt;ಅನ್ವಯಿಸಿ&lt;/strong&gt; ಕ್ಲಿಕ್ ಮಾಡಿ, ನಂತರ &lt;strong&gt;ಸರಿ&lt;/strong&gt; ಕ್ಲಿಕ್ ಮಾಡಿ
&lt;li&gt;ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನಿಂದ ಸಾಫ್ಟ್‌ವೇರ್ ಅನ್ನು ಶಾಶ್ವತವಾಗಿ ತೆಗೆದುಹಾಕುವುದು ಹೇಗೆ ಎಂದು ತಿಳಿದುಕೊಳ್ಳಲು &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome ಸಹಾಯ ಕೇಂದ್ರಕ್ಕೆ&lt;/a&gt; ಭೇಟಿ ನೀಡಿ &lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> ನಿರ್ವಹಣೆ</translation>
<translation id="7416351320495623771">ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ…</translation>
<translation id="7419106976560586862">ಪ್ರೊಫೈಲ್ ಹಾದಿ</translation>
<translation id="7437289804838430631">ಸಂಪರ್ಕ ಮಾಹಿತಿಯನ್ನು ಸೇರಿಸು</translation>
@@ -994,10 +1007,12 @@
<translation id="7442725080345379071">ತಿಳಿ ಕಿತ್ತಳೆ</translation>
<translation id="7444046173054089907">ಈ ಸೈಟ್ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ</translation>
<translation id="7445762425076701745">ನೀವು ಸಂಪರ್ಕ ಮಾಡಿರುವ ಸರ್ವರ್‌ನ ಗುರುತನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಮೌಲ್ಯೀಕರಿಸಲಾಗುವುದಿಲ್ಲ. ನೀವು ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿಯೇ ಮಾನ್ಯವಿರುವ ಹೆಸರನ್ನು ಮಾತ್ರ ಬಳಸಿಕೊಂಡು ಸಂಪರ್ಕ ಹೊಂದಿರುವಿರಿ, ಇದರ ಮಾಲಿಕತ್ವವನ್ನು ಮೌಲ್ಯೀಕರಿಸುವ ಯಾವ ಅವಕಾಶವನ್ನೂ ಬಾಹ್ಯ ಪ್ರಮಾಣಪತ್ರ ಪ್ರಾಧಿಕಾರವು ಹೊಂದಿಲ್ಲ. ಕೆಲವು ಪ್ರಮಾಣಪತ್ರ ಪ್ರಾಧಿಕಾರಗಳು, ಯಾವುದೇ ಹೆಸರನ್ನು ಪರಿಗಣಿಸದೇ, ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ಬಿಡುಗಡೆ ಮಾಡುವ ಕಾರಣದಿಂದಾಗಿ, ನೀವು ಉದ್ದೇಶಿತ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಸಂಪರ್ಕಿಸಿರುವಿರೇ ಹೊರತು ದಾಳಿ ಮಾಡಲು ಅಲ್ಲ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳುವ ಯಾವ ಅವಕಾಶವೂ ಇಲ್ಲ.</translation>
+<translation id="7449109375006139765">ನಿರ್ವಹಣೆ ಸರ್ವರ್‌ಗೆ ಸಿಸ್ಟಂ ಲಾಗ್‌ಗಳನ್ನು ಕಳುಹಿಸಿ</translation>
<translation id="7451311239929941790">ಈ ಸಮಸ್ಯೆಯ ಕುರಿತು <ph name="BEGIN_LINK" />ಇನ್ನಷ್ಟು ತಿಳಿಯುವಿಕೆ<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">ಜಾಗತಿಕ ಡಿಫಾಲ್ಟ್ ಬಳಸಿ (ನಿರ್ಬಂಧಿಸಿ)</translation>
<translation id="7460618730930299168">ವೀಕ್ಷಣೆ ಅವಧಿಯು ನೀವು ಆಯ್ಕೆ ಮಾಡಿರುವುದಕ್ಕಿಂತಲೂ ಭಿನ್ನವಾಗಿದೆ. ಮುಂದುವರಿಯುವುದೇ?</translation>
<translation id="7473891865547856676">ಇಲ್ಲ, ಧನ್ಯವಾದಗಳು</translation>
+<translation id="7475525192983021547">ಓರ್ವ ಬಳಕೆದಾರರು ಸಾಧನದಲ್ಲಿ ಸಕ್ರಿಯವಾಗಿರುವಾಗ ಅವರ ಚಟುವಟಿಕೆ ಕಾಲಾವಧಿಗಳನ್ನು ವರದಿ ಮಾಡಿ</translation>
<translation id="7481312909269577407">ಫಾರ್ವರ್ಡ್</translation>
<translation id="7485870689360869515">ಯಾವುದೇ ಡೇಟಾ ಕಂಡುಬಂದಿಲ್ಲ.</translation>
<translation id="7508255263130623398">ಹಿಂತಿರುಗಿಸಲಾದ ನೀತಿಯ ಸಾಧನ ಐಡಿ ಖಾಲಿ ಇದೆ ಅಥವಾ ಪ್ರಸ್ತುತ ಸಾಧನ ಐಡಿಗೆ ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ</translation>
@@ -1090,6 +1105,7 @@
<translation id="7995512525968007366">ನಿರ್ದಿಷ್ಟಪಡಿಸಲಾಗಿಲ್ಲ</translation>
<translation id="800218591365569300">ಮೆಮೊರಿ ಮುಕ್ತಗೊಳಿಸಲು ಇತರ ಟ್ಯಾಬ್‌ಗಳನ್ನು ಅಥವಾ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ಮುಚ್ಚಲು ಪ್ರಯತ್ನಿಸಿ.</translation>
<translation id="8009225694047762179">ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ಈ ಕಾರ್ಡ್ ಮತ್ತು ಅದರ ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸವನ್ನು ಉಳಿಸಲಾಗುತ್ತದೆ. ನೀವು <ph name="USER_EMAIL" /> ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅದನ್ನು ಬಳಸಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ.}one{ಈ ಕಾರ್ಡ್‌ಗಳು ಮತ್ತು ಅವುಗಳ ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸಗಳನ್ನು ಉಳಿಸಲಾಗುತ್ತದೆ. ನೀವು <ph name="USER_EMAIL" /> ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅವುಗಳನ್ನು ಬಳಸಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ.}other{ಈ ಕಾರ್ಡ್‌ಗಳು ಮತ್ತು ಅವುಗಳ ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸಗಳನ್ನು ಉಳಿಸಲಾಗುತ್ತದೆ. ನೀವು <ph name="USER_EMAIL" /> ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅವುಗಳನ್ನು ಬಳಸಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ.}}</translation>
<translation id="8012647001091218357">ಈ ಕ್ಷಣದಲ್ಲಿ ನಿಮ್ಮ ಪೋಷಕರನ್ನು ತಲುಪಲು ನಮಗೆ ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</translation>
<translation id="8025119109950072390">ಈ ಸೈಟ್‌ನಲ್ಲಿನ ಆಕ್ರಮಣಕಾರರು ಸಾಫ್ಟ್‌ವೇರ್ ಸ್ಥಾಪಿಸುವಿಕೆ ಅಥವಾ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಬಹಿರಂಗ ಪಡಿಸುವಂತಹ ಅಪಾಯಕಾರಿಯಾಗಿ ಏನಾದರೂ ಮಾಡುವಂತಹ ಮೋಸವನ್ನು ಮಾಡಬಹುದು (ಉದಾಹರಣೆಗೆ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು, ಫೋನ್‌ ಸಂಖ್ಯೆಗಳು ಅಥವಾ ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್‌ಗಳು).</translation>
<translation id="8034522405403831421">ಈ ಪುಟವು <ph name="SOURCE_LANGUAGE" /> ನಲ್ಲಿ ಇದೆ. ಇದನ್ನು <ph name="TARGET_LANGUAGE" /> ಗೆ ಅನುವಾದಿಸುವುದೇ?</translation>
@@ -1100,6 +1116,7 @@
<translation id="8041940743680923270">ಜಾಗತಿಕ ಡಿಫಾಲ್ಟ್ ಬಳಸಿ (ಕೇಳಿ)</translation>
<translation id="8042918947222776840">ಪಿಕಪ್ ವಿಧಾನವನ್ನು ಆರಿಸಿ</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ಅನ್ನು ಸರಿಯಾಗಿ ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾಗಿಲ್ಲ. ಸಾಮಾನ್ಯವಾಗಿ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು "<ph name="SOFTWARE_NAME" />" ಅನ್ನು ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲಾಗುತ್ತಿದೆ. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">ನಿಮ್ಮ ಸಾಧನವನ್ನು ಇದಕ್ಕೆ ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾಗಿದೆ:</translation>
<translation id="8078141288243656252">ಡಾಕ್ಯುಮೆಂಟ್‌ ಅನ್ನು ತಿರುಗಿಸಿದಾಗ ಟಿಪ್ಪಣಿ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ</translation>
<translation id="8079031581361219619">ಸೈಟ್ ಅನ್ನು ಪುನಃ ಲೋಡ್ ಮಾಡಬೇಕೇ?</translation>
<translation id="8088680233425245692">ಲೇಖನವನ್ನು ವೀಕ್ಷಿಸಲು ವಿಫಲವಾಗಿದೆ.</translation>
@@ -1150,6 +1167,7 @@
<translation id="8363502534493474904">ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್ ಆಫ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ</translation>
<translation id="8364627913115013041">ಹೊಂದಿಸಿಲ್ಲ.</translation>
<translation id="8368476060205742148">Google Play ಸೇವೆಗಳು</translation>
+<translation id="8371889962595521444">ಕಸ್ಟಮ್ ರೂಟ್ ಪ್ರಮಾಣಪತ್ರಗಳು</translation>
<translation id="8380941800586852976">ಅಪಾಯಕಾರಿ</translation>
<translation id="8381674639488873545">ಈ ಶುಲ್ಕವು ಒಂದು ಬಾರಿ ಪಾವತಿಯದಾಗಿರಬಹುದು ಅಥವಾ ಮರುಕಳಿಸುವುದಾಗಿರಬಹುದು, ಮತ್ತು ಸ್ಪಷ್ಟವಾಗಿಲ್ಲದೇ ಇರಬಹುದು. <ph name="BEGIN_LINK" />ಹೇಗಿದ್ದರೂ ತೋರಿಸಿ<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">ನೀವು ಇತ್ತೀಚಿಗೆ ಭೇಟಿ ನೀಡಿದ ಬುಕ್‌ಮಾರ್ಕ್‌ಗಳು ಇಲ್ಲಿ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತವೆ</translation>
@@ -1159,6 +1177,7 @@
<translation id="8416694386774425977">ನೆಟ್‌ವರ್ಕ್ ಕಾನ್ಫಿಗರೇಶನ್ ಅಮಾನ್ಯವಾಗಿದೆ ಮತ್ತು ಅದನ್ನು ಆಮದು ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.
ಹೆಚ್ಚುವರಿ ವಿವರಗಳು:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">ಸಾಧನವನ್ನು <ph name="ENROLLMENT_DOMAIN" /> ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗುತ್ತಿದೆ</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">ಬದಲಿಸಿ</translation>
<translation id="8428213095426709021">ಸೆಟ್ಟಿಂಗ್‌ಗಳು</translation>
@@ -1220,6 +1239,7 @@
<translation id="8932102934695377596">ನಿಮ್ಮ ಗಡಿಯಾರ ಹಿಂದೆ ಇದೆ</translation>
<translation id="893332455753468063">ಹೆಸರು ಸೇರಿಸಿ</translation>
<translation id="8938939909778640821">ಸಮ್ಮತಿಸಲಾದ ಕ್ರೆಡಿಟ್ ಮತ್ತು ಪ್ರೀಪೇಯ್ಡ್ ಕಾರ್ಡ್‌ಗಳು</translation>
+<translation id="894185898663964645">ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಕಸ್ಟಮ್ ರೂಟ್ ಪ್ರಮಾಣಪತ್ರಗಳನ್ನು ಕಾನ್ಫಿಗರ್ ಮಾಡಿದ್ದಾರೆ, ಇದರಿಂದಾಗಿ ನೀವು ಭೇಟಿ ನೀಡುವ ವೆಬ್‌ಸೈಟ್‌ಗಳಲ್ಲಿನ ವಿಷಯಗಳನ್ನು ನಿರ್ವಾಹಕರು ನೋಡಬಹುದು.</translation>
<translation id="8943282376843390568">ನಿಂಬೆ ಹಳದಿ</translation>
<translation id="8957210676456822347">ಕ್ಯಾಪ್ಟಿವ್ ಪೋರ್ಟಲ್ ದೃಢೀಕರಣ</translation>
<translation id="8968766641738584599">ಕಾರ್ಡ್‌ ಉಳಿಸಿ</translation>
diff --git a/chromium/components/strings/components_strings_ko.xtb b/chromium/components/strings/components_strings_ko.xtb
index 54f0d59ad3a..6391fa810be 100644
--- a/chromium/components/strings/components_strings_ko.xtb
+++ b/chromium/components/strings/components_strings_ko.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" />로 된 페이지를 번역하지 않습니다.</translation>
<translation id="2053553514270667976">우편번호</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{제안 1개}other{제안 #개}}</translation>
+<translation id="2068124040035837596"><ph name="ENROLLMENT_DOMAIN" />에서 내 계정을 관리합니다. 이는 관리자가 내 계정을 원격으로 구성할 수 있음을 의미합니다.</translation>
<translation id="2068663545051464999">비정상 종료 보고서 ID <ph name="CRASH_ID" />업로드됨(로컬 컨텍스트: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">실행취소</translation>
<translation id="20817612488360358">시스템 프록시 설정이 사용하도록 설정되었지만 명시적 프록시 설정도 지정되어 있습니다.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">사용할 수 없는 배송 방법입니다. 다른 방법을 선택하세요.</translation>
<translation id="2396249848217231973">삭제 실행 취소(&amp;U)</translation>
<translation id="2413528052993050574">이 서버가 <ph name="DOMAIN" />임을 입증할 수 없으며 서버의 보안 인증서가 취소될 수 있습니다. 서버를 잘못 설정했거나 불법 사용자가 연결을 가로채고 있기 때문일 수 있습니다.</translation>
+<translation id="244665789865330679"><ph name="ENROLLMENT_DOMAIN" />에서 내 기기 및 계정을 관리합니다. 이는 관리자가 내 기기와 계정을 원격으로 구성할 수 있음을 의미합니다.</translation>
<translation id="2463193859425327265">홈페이지 변경</translation>
<translation id="2463739503403862330">입력</translation>
<translation id="2465655957518002998">배달 방법 선택</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" />에 접속하려 했으나 발행기관에서 서버가 전달한 인증서를 폐기했습니다. 이는 서버가 제시한 보안 자격증명 정보를 신뢰할 수 없음을 의미합니다. 사용자는 현재 공격자와 통신 중일 수도 있습니다.</translation>
<translation id="4378154925671717803">전화기</translation>
<translation id="4406896451731180161">검색결과</translation>
+<translation id="4406972042435603828">관리자가 강력한 기능이 포함된 확장 프로그램을 설치했습니다.</translation>
<translation id="4408413947728134509">쿠키 <ph name="NUM_COOKIES" />개</translation>
<translation id="4415426530740016218">픽업 주소</translation>
<translation id="4424024547088906515">이 서버가 <ph name="DOMAIN" />임을 입증할 수 없으며 Chrome에서 신뢰하는 보안 인증서가 아닙니다. 서버를 잘못 설정했거나 불법 사용자가 연결을 가로채고 있기 때문일 수 있습니다.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">검색결과가 없습니다.</translation>
<translation id="4950898438188848926">탭 전환 버튼, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /> 열린 탭으로 전환하려면 Enter를 누르세요</translation>
<translation id="495170559598752135">작업</translation>
+<translation id="495832697253704892">확장 프로그램 보고</translation>
<translation id="4958444002117714549">펼치기 목록</translation>
<translation id="4974590756084640048">경고 다시 사용</translation>
<translation id="4989163558385430922">모두 보기</translation>
<translation id="4989809363548539747">이 플러그인은 지원되지 않습니다.</translation>
+<translation id="4996230189582812866">보고</translation>
<translation id="5002932099480077015">선택하면 Chrome에서 양식을 더 빠르게 작성할 수 있도록 이 기기에 카드 사본을 저장합니다.</translation>
<translation id="5014174725590676422">Chrome의 Google 어시스턴트 첫 실행 화면이 표시됩니다.</translation>
<translation id="5015510746216210676">컴퓨터 이름:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">시/도</translation>
<translation id="5094747076828555589">이 서버가 <ph name="DOMAIN" />임을 입증할 수 없으며 Chromium에서 신뢰하는 보안 인증서가 아닙니다. 서버를 잘못 설정했거나 불법 사용자가 연결을 가로채고 있기 때문일 수 있습니다.</translation>
<translation id="5095208057601539847">주/도</translation>
+<translation id="5098222253617183465"><ph name="ENROLLMENT_DOMAIN" />에서 내 기기를 관리하고 <ph name="ACCOUNT_DOMAIN" />에서 내 계정을 관리합니다. 이는 관리자가 내 기기와 계정을 원격으로 구성할 수 있음을 의미합니다.</translation>
<translation id="5115563688576182185">(64비트)</translation>
<translation id="5128122789703661928">세션 이름이 잘못되어 삭제할 수 없습니다.</translation>
<translation id="5135404736266831032">주소 관리...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">컴퓨터</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" />가 아닙니까? 오류 신고</translation>
<translation id="5190835502935405962">북마크바</translation>
+<translation id="5200263511887412697">최근 로그인한 기기 사용자 목록을 보고합니다.</translation>
<translation id="5201306358585911203">이 페이지에 삽입된 페이지 내용:</translation>
<translation id="5205222826937269299">이름은 필수입니다.</translation>
<translation id="5215116848420601511">Google Pay에 사용되는 결제 수단 및 주소</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">사이트에 연결할 수 없음</translation>
<translation id="5869522115854928033">저장된 비밀번호</translation>
<translation id="5887400589839399685">저장된 카드</translation>
+<translation id="5893718151540690985">네트워크 유형과 하드웨어 주소를 포함한 네트워크 인터페이스 목록을 보고합니다.</translation>
<translation id="5893752035575986141">신용카드를 사용할 수 있습니다.</translation>
<translation id="5901630391730855834">노란색</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" />(동기화됨)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">연락처 정보 수정</translation>
<translation id="5967867314010545767">기록에서 삭제</translation>
<translation id="5975083100439434680">축소</translation>
+<translation id="5977489021191000276">내 기기는 관리자에 의해 관리되지 않습니다.</translation>
<translation id="5977976211062815271">이 기기에서</translation>
<translation id="598637245381783098">결제 앱을 열 수 없습니다.</translation>
<translation id="5989320800837274978">고정 프록시 서버와 .pac 스크립트 URL이 모두 지정되지 않았습니다.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />에 있는 공격자는 다른 앱인 것처럼 가장하거나 사용자를 추적하는 데 사용될 수 있는 데이터를 수집하는 사기성 앱을 설치할 수도 있습니다. <ph name="BEGIN_LEARN_MORE_LINK" />자세히 알아보기<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" />(동기화됨)</translation>
<translation id="6027201098523975773">이름을 입력하세요.</translation>
+<translation id="6033927989869462158">CPU/RAM 사용 등의 하드웨어 통계를 보고합니다.</translation>
<translation id="6034000775414344507">연한 회색</translation>
<translation id="6039846035001940113">문제가 계속되면 사이트 소유자에게 문의하세요.</translation>
<translation id="6040143037577758943">닫기</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">사용자 에이전트</translation>
<translation id="6903319715792422884">일부 <ph name="BEGIN_WHITEPAPER_LINK" />시스템 정보와 페이지 콘텐츠를<ph name="END_WHITEPAPER_LINK" /> Google로 전송하여 세이프 브라우징을 개선하도록 도와주세요. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">사용자:</translation>
+<translation id="6934672428414710184">Google 계정에 등록된 이름입니다.</translation>
+<translation id="6939583532829045966"><ph name="ENROLLMENT_DOMAIN" />에서 내 기기를 관리합니다. 이는 관리자가 내 기기를 원격으로 구성할 수 있음을 의미합니다.</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />에서 관리하지 않는 사이트에 비밀번호를 입력했습니다. 계정을 안전하게 보호하려면 다른 앱과 사이트에서 동일한 비밀번호를 재사용하지 마세요.</translation>
<translation id="6945221475159498467">선택</translation>
<translation id="6948701128805548767">수령 방법과 요구사항을 확인하려면 주소를 선택하세요.</translation>
@@ -991,6 +1003,7 @@
&lt;li&gt;&lt;strong&gt;서비스 상태&lt;/strong&gt;에서 &lt;strong&gt;중지&lt;/strong&gt;를 클릭합니다.
&lt;li&gt;&lt;strong&gt;적용&lt;/strong&gt;을 클릭한 다음 &lt;strong&gt;확인&lt;/strong&gt;을 클릭합니다.
&lt;li&gt;&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome 고객센터&lt;/a&gt;를 방문하여 컴퓨터에서 소프트웨어를 영구적으로 삭제하는 방법을 알아보세요. &lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> 관리</translation>
<translation id="7416351320495623771">비밀번호 관리...</translation>
<translation id="7419106976560586862">프로필 경로</translation>
<translation id="7437289804838430631">연락처 정보 추가</translation>
@@ -999,10 +1012,12 @@
<translation id="7442725080345379071">연한 주황색</translation>
<translation id="7444046173054089907">차단된 사이트</translation>
<translation id="7445762425076701745">연결하려는 서버 ID를 확인할 수 없습니다. 외부 인증 기관에서 소유권을 확인할 수 없으므로 네트워크에서 유효한 이름을 사용하여 서버에 연결됩니다. 일부 인증 기관에서는 이러한 이름에 대해 관계없이 인증서를 발급하기 때문에 공격자가 아니라 의도한 웹사이트에 연결되어 있는지 확인할 수 없습니다.</translation>
+<translation id="7449109375006139765">시스템 로그를 관리 서버로 전송합니다.</translation>
<translation id="7451311239929941790">이 문제를 <ph name="BEGIN_LINK" />자세히 알아보기<ph name="END_LINK" /></translation>
<translation id="7455133967321480974">전체 기본값 사용(차단)</translation>
<translation id="7460618730930299168">선택한 영화와 상영 영화가 다릅니다. 계속하시겠습니까?</translation>
<translation id="7473891865547856676">건너뛰기</translation>
+<translation id="7475525192983021547">사용자가 기기를 사용한 시간을 보고합니다.</translation>
<translation id="7481312909269577407">앞으로</translation>
<translation id="7485870689360869515">데이터 없음</translation>
<translation id="7508255263130623398">반환된 정책 기기 ID가 비었거나 현재 기기 ID와 일치하지 않음</translation>
@@ -1095,6 +1110,7 @@
<translation id="7995512525968007366">지정되지 않음</translation>
<translation id="800218591365569300">다른 탭이나 프로그램을 종료하여 메모리를 확보하세요.</translation>
<translation id="8009225694047762179">비밀번호 관리</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{이 카드와 청구서 수신 주소가 저장됩니다. <ph name="USER_EMAIL" /> 계정으로 로그인하면 카드를 사용할 수 있습니다.}other{이 카드와 청구서 수신 주소가 저장됩니다. <ph name="USER_EMAIL" /> 계정으로 로그인하면 카드를 사용할 수 있습니다.}}</translation>
<translation id="8012647001091218357">현재 부모님께 연락할 수 없습니다. 나중에 다시 시도해 주세요.</translation>
<translation id="8025119109950072390">이 사이트의 공격자가 소프트웨어를 설치하거나 개인정보(예: 비밀번호, 전화번호, 신용카드)를 공개하는 등의 위험한 행동을 하도록 사용자를 속일 수 있습니다.</translation>
<translation id="8034522405403831421">이 페이지는 <ph name="SOURCE_LANGUAGE" />로 되어 있습니다. <ph name="TARGET_LANGUAGE" />로 번역하시겠습니까?</translation>
@@ -1105,6 +1121,7 @@
<translation id="8041940743680923270">전체 기본값 사용(요청)</translation>
<translation id="8042918947222776840">수령 방법 선택</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />이(가) 올바르게 설정되지 않았습니다. 일반적으로 '<ph name="SOFTWARE_NAME" />'을(를) 제거하면 문제가 해결됩니다. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">기기가 다음과 같이 구성되었습니다.</translation>
<translation id="8078141288243656252">회전 시 주석을 달 수 없습니다.</translation>
<translation id="8079031581361219619">사이트를 새로고침하시겠습니까?</translation>
<translation id="8088680233425245692">글을 조회하지 못했습니다.</translation>
@@ -1155,6 +1172,7 @@
<translation id="8363502534493474904">비행기 모드 사용 중지</translation>
<translation id="8364627913115013041">설정 안됨</translation>
<translation id="8368476060205742148">Google Play 서비스</translation>
+<translation id="8371889962595521444">맞춤 루트 인증서</translation>
<translation id="8380941800586852976">위험</translation>
<translation id="8381674639488873545">이러한 청구는 일회성이거나 반복적일 수 있으며 명확하지 않을 수도 있습니다. <ph name="BEGIN_LINK" />사이트 표시하기<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">최근에 방문한 북마크가 여기에 표시됩니다.</translation>
@@ -1164,6 +1182,7 @@
<translation id="8416694386774425977">네트워크 설정이 잘못되어 가져올 수 없습니다.
추가 세부정보:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533"><ph name="ENROLLMENT_DOMAIN" />에서 관리하는 기기</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">변경</translation>
<translation id="8428213095426709021">설정</translation>
@@ -1224,6 +1243,7 @@
<translation id="8932102934695377596">시간이 너무 먼 과거로 설정되어 있습니다.</translation>
<translation id="893332455753468063">이름 추가</translation>
<translation id="8938939909778640821">사용 가능한 신용카드 및 선불카드</translation>
+<translation id="894185898663964645">관리자가 맞춤 루트 인증서를 구성했으며, 이로 인해 관리자가 내가 방문하는 웹사이트의 콘텐츠를 볼 수 있습니다.</translation>
<translation id="8943282376843390568">라임색</translation>
<translation id="8957210676456822347">캡티브 포털 승인</translation>
<translation id="8968766641738584599">카드 저장</translation>
diff --git a/chromium/components/strings/components_strings_lt.xtb b/chromium/components/strings/components_strings_lt.xtb
index e045e9e33bb..061fe7b86b6 100644
--- a/chromium/components/strings/components_strings_lt.xtb
+++ b/chromium/components/strings/components_strings_lt.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Puslapiai, parašyti <ph name="LANGUAGE" />, verčiami nebus.</translation>
<translation id="2053553514270667976">Pašto kodas</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 pasiūlymas}one{# pasiūlymas}few{# pasiūlymai}many{# pasiūlymo}other{# pasiūlymų}}</translation>
+<translation id="2068124040035837596">Jūsų paskyrą tvarko <ph name="ENROLLMENT_DOMAIN" />. Tai reiškia, kad administratorius gali nuotoliniu būdu ją konfigūruoti.</translation>
<translation id="2068663545051464999">Įkeltos strigčių ataskaitos ID <ph name="CRASH_ID" /> (vietinis kontekstas: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Anuliuoti</translation>
<translation id="20817612488360358">Sistemos įgaliotojo serverio nustatymai nustatyti kaip naudotini, bet taip pat nurodyta tiksli įgaliotojo serverio konfigūracija.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Šis pristatymo metodas nepasiekiamas. Išbandykite kitą metodą.</translation>
<translation id="2396249848217231973">&amp;Anuliuoti ištrynimą</translation>
<translation id="2413528052993050574">Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas gali būti atšauktas. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užgrobėjo.</translation>
+<translation id="244665789865330679">Jūsų įrenginį ir paskyrą tvarko <ph name="ENROLLMENT_DOMAIN" />. Tai reiškia, kad administratorius gali nuotoliniu būdu juos konfigūruoti.</translation>
<translation id="2463193859425327265">Keisti pagrindinį puslapį</translation>
<translation id="2463739503403862330">Užpildyti</translation>
<translation id="2465655957518002998">Pasirinkti pristatymo metodą</translation>
@@ -562,6 +564,7 @@
<translation id="4377125064752653719">Bandėte pasiekti svetainę „<ph name="DOMAIN" />“, bet sertifikatą, kurį pateikė serveris, anuliavo jo išdavėjas. Tai reiškia, kad saugos kredencialais, kuriuos pateikė serveris, visiškai negalima pasitikėti. Galbūt bendraujate su užpuoliku.</translation>
<translation id="4378154925671717803">Telefonas</translation>
<translation id="4406896451731180161">paieškos rezultatai</translation>
+<translation id="4406972042435603828">Administratorius įdiegė veiksmingų funkcijų plėtinių.</translation>
<translation id="4408413947728134509">Slapukai <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Paėmimo adresas</translation>
<translation id="4424024547088906515">Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas nėra patikimas „Chrome“. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užgrobėjo.</translation>
@@ -633,10 +636,12 @@
<translation id="4943872375798546930">Rezultatų nėra</translation>
<translation id="4950898438188848926">Skirtuko perjungimo mygtukas. Paspauskite „Enter“, kad perjungtumėte į atidarytą skirtuką „<ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />“</translation>
<translation id="495170559598752135">Veiksmai</translation>
+<translation id="495832697253704892">Plėtinių ataskaitų teikimas</translation>
<translation id="4958444002117714549">Išskleisti sąrašą</translation>
<translation id="4974590756084640048">Iš naujo įgalinti įspėjimus</translation>
<translation id="4989163558385430922">Žr. viską</translation>
<translation id="4989809363548539747">Šis papildinys nepalaikomas</translation>
+<translation id="4996230189582812866">Ataskaitų teikimas</translation>
<translation id="5002932099480077015">Jei šis nustatymas įgalintas, „Chrome“ saugos kortelės kopiją šiame įrenginyje, kad būtų galima greičiau užpildyti formas.</translation>
<translation id="5014174725590676422">Rodomas „Google“ padėjėjo sistemoje „Chrome“ pirmosios paleisties ekranas</translation>
<translation id="5015510746216210676">Įrenginio pavadinimas:</translation>
@@ -657,6 +662,7 @@
<translation id="5089810972385038852">Valstija</translation>
<translation id="5094747076828555589">Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas nėra patikimas „Chromium“. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užgrobėjo.</translation>
<translation id="5095208057601539847">Provincija</translation>
+<translation id="5098222253617183465">Jūsų įrenginį tvarko <ph name="ENROLLMENT_DOMAIN" />, o jūsų paskyrą tvarko <ph name="ACCOUNT_DOMAIN" />. Tai reiškia, kad administratoriai gali nuotoliniu būdu sukonfigūruoti įrenginį ir paskyrą.</translation>
<translation id="5115563688576182185">(64 bitų)</translation>
<translation id="5128122789703661928">Sesijos šiuo pavadinimu negalima ištrinti.</translation>
<translation id="5135404736266831032">Tvarkyti adresus...</translation>
@@ -669,6 +675,7 @@
<translation id="5172758083709347301">Įrenginys</translation>
<translation id="5179510805599951267">Ne <ph name="ORIGINAL_LANGUAGE" /> k.? Pranešti apie šią klaidą</translation>
<translation id="5190835502935405962">Žymių juosta</translation>
+<translation id="5200263511887412697">pateikti neseniai prisijungusių įrenginio naudotojų sąrašą</translation>
<translation id="5201306358585911203">Šiame puslapyje įterptame puslapyje nurodyta:</translation>
<translation id="5205222826937269299">Būtina nurodyti pavadinimą</translation>
<translation id="5215116848420601511">„Google Pay“ naudojami mokėjimo metodai ir adresai</translation>
@@ -770,6 +777,7 @@
<translation id="5869405914158311789">Nepavyksta pasiekti šios svetainės</translation>
<translation id="5869522115854928033">Išsaugoti slaptažodžiai</translation>
<translation id="5887400589839399685">Kortelė išsaugota</translation>
+<translation id="5893718151540690985">pateikti tinklo sąsajų su jų tipais ir aparatinės įrangos adresais, sąrašą</translation>
<translation id="5893752035575986141">Kredito kortelės tinkamos.</translation>
<translation id="5901630391730855834">Geltona</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sinchronizuota)</translation>
@@ -783,6 +791,7 @@
<translation id="5967592137238574583">Kontaktinės informacijos redagavimas</translation>
<translation id="5967867314010545767">Pašalinti iš istorijos</translation>
<translation id="5975083100439434680">Tolinti</translation>
+<translation id="5977489021191000276">Jūsų įrenginio netvarko administratorius.</translation>
<translation id="5977976211062815271">Šiame įrenginyje</translation>
<translation id="598637245381783098">Nepavyksta atidaryti mokėjimo programos</translation>
<translation id="5989320800837274978">Nenurodyti nei fiksuoti įgaliotieji serveriai, nei .pac scenarijaus URL.</translation>
@@ -794,6 +803,7 @@
<translation id="6017850046339264347">Užgrobėjai svetainėje <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> gali įdiegti klaidinančių programų, kurios apsimeta kitomis programomis, arba rinkti duomenis, naudojamus jums stebėti. <ph name="BEGIN_LEARN_MORE_LINK" />Sužinokite daugiau<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sinchronizuota)</translation>
<translation id="6027201098523975773">Įveskite pavadinimą</translation>
+<translation id="6033927989869462158">pranešti aparatinės įrangos statistikos duomenis, pvz., centrinio procesoriaus / laisvosios prieigos atminties naudojimo duomenis</translation>
<translation id="6034000775414344507">Šviesiai pilka</translation>
<translation id="6039846035001940113">Jei problema išlieka, susisiekite su svetainės savininku.</translation>
<translation id="6040143037577758943">Uždaryti</translation>
@@ -906,6 +916,8 @@
<translation id="6897140037006041989">Naudotojo atstovas</translation>
<translation id="6903319715792422884">Padėkite tobulinti Saugų naršymą siųsdami tam tikrą <ph name="BEGIN_WHITEPAPER_LINK" />sistemos informaciją ir puslapių turinį<ph name="END_WHITEPAPER_LINK" /> „Google“. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Naudotojas:</translation>
+<translation id="6934672428414710184">Šis vardas yra iš jūsų „Google“ paskyros</translation>
+<translation id="6939583532829045966">Jūsų įrenginį tvarko <ph name="ENROLLMENT_DOMAIN" />. Tai reiškia, kad administratorius gali nuotoliniu būdu jį konfigūruoti.</translation>
<translation id="6944692733090228304">Įvedėte slaptažodį svetainėje, kurios netvarko organizacija <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Kad apsaugotumėte paskyrą, nenaudokite to paties slaptažodžio kitose programose ir svetainėse.</translation>
<translation id="6945221475159498467">Pasirinkti</translation>
<translation id="6948701128805548767">Jei norite peržiūrėti paėmimo metodus ir reikalavimus, pasirinkite adresą</translation>
@@ -993,6 +1005,7 @@ Papildoma išsami informacija:
&lt;li&gt;Spustelėkite &lt;strong&gt;Taikyti&lt;/strong&gt;, tada – &lt;strong&gt;Gerai&lt;/strong&gt;.
&lt;li&gt;Apsilankykite &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;„Chrome“ pagalbos centre&lt;/a&gt;, kad sužinotumėte, kaip visam laikui pašalinti programinę įrangą iš kompiuterio.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">„<ph name="PRODUCT_NAME" />“ tvarkymas</translation>
<translation id="7416351320495623771">Tvarkyti slaptažodžius…</translation>
<translation id="7419106976560586862">Profilio kelias</translation>
<translation id="7437289804838430631">Pridėti kontaktinę informaciją</translation>
@@ -1001,10 +1014,12 @@ Papildoma išsami informacija:
<translation id="7442725080345379071">Šviesiai oranžinė</translation>
<translation id="7444046173054089907">Ši svetainė užblokuota</translation>
<translation id="7445762425076701745">Nepavyksta visiškai patvirtinti serverio, prie kurio esate prisijungę, tapatybės. Prie serverio esate prisijungę naudodami tik tinklui galiojantį vardą, kurio nuosavybės teisių išorinė sertifikatą išduodanti institucija negali patvirtinti. Nors kai kurios sertifikatus išduodančios institucijos vis tiek išduos sertifikatus pagal šiuos vardus, niekaip nebus galima užtikrinti, kad būsite prisijungę prie numatytos svetainės, o ne prie užpuolėjo.</translation>
+<translation id="7449109375006139765">sistemos žurnalų siuntimas valdymo serveriui</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Sužinokite daugiau<ph name="END_LINK" /> apie šią problemą.</translation>
<translation id="7455133967321480974">Naudoti visuotinį numatytąjį nustatymą (blokuoti)</translation>
<translation id="7460618730930299168">Vaizdas ekrane skiriasi nuo to, ką pasirinkote. Tęsti?</translation>
<translation id="7473891865547856676">Ne, ačiū</translation>
+<translation id="7475525192983021547">pranešti apie laikotarpius, kai naudotojas naudoja įrenginį</translation>
<translation id="7481312909269577407">Persiųsti</translation>
<translation id="7485870689360869515">Nerasta jokių duomenų.</translation>
<translation id="7508255263130623398">Sugrąžinto politikos įrenginio ID nenurodytas arba neatitinka dabartinio įrenginio ID</translation>
@@ -1097,6 +1112,7 @@ Papildoma išsami informacija:
<translation id="7995512525968007366">Nenurodytas</translation>
<translation id="800218591365569300">Pabandykite uždaryti skirtukus arba kitas programas, kad atlaisvintumėte atminties.</translation>
<translation id="8009225694047762179">Tvarkyti slaptažodžius</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Ši kortelė ir jos atsiskaitymo adresas bus išsaugoti. Ją galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}one{Šios kortelės ir jų atsiskaitymo adresai bus išsaugoti. Jas galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}few{Šios kortelės ir jų atsiskaitymo adresai bus išsaugoti. Jas galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}many{Šios kortelės ir jų atsiskaitymo adresai bus išsaugoti. Jas galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}other{Šios kortelės ir jų atsiskaitymo adresai bus išsaugoti. Jas galėsite naudoti prisijungę prie <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Šiuo metu nepavyko susisiekti su jūsų tėvais. Bandykite dar kartą.</translation>
<translation id="8025119109950072390">Šios svetainės užpuolėjai gali bandyti apgaulingai priversti atlikti pavojingus veiksmus, pvz., įdiegti programinę įrangą ar atskleisti asmens informaciją (pvz., slaptažodžius, telefonų numerius ar kredito kortelių informaciją).</translation>
<translation id="8034522405403831421">Šis puslapis yra <ph name="SOURCE_LANGUAGE" /> k. Išversti į <ph name="TARGET_LANGUAGE" /> k.?</translation>
@@ -1107,6 +1123,7 @@ Papildoma išsami informacija:
<translation id="8041940743680923270">Naudoti visuotinį numatytąjį nustatymą (klausti)</translation>
<translation id="8042918947222776840">Pasirinkti paėmimo metodą</translation>
<translation id="8057711352706143257">„<ph name="SOFTWARE_NAME" />“ netinkamai sukonfigūruota. Pašalinus „<ph name="SOFTWARE_NAME" />“ paprastai pavyksta išspręsti šią problemą. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Įrenginys sukonfigūruotas:</translation>
<translation id="8078141288243656252">Negalima rašyti komentarų, kai pasukta</translation>
<translation id="8079031581361219619">Iš naujo įkelti svetainę?</translation>
<translation id="8088680233425245692">Nepavyko peržiūrėti straipsnio.</translation>
@@ -1157,6 +1174,7 @@ Papildoma išsami informacija:
<translation id="8363502534493474904">Išjungti lėktuvo režimą</translation>
<translation id="8364627913115013041">Nenustatyta.</translation>
<translation id="8368476060205742148">„Google Play“ paslaugos</translation>
+<translation id="8371889962595521444">Tinkinti šakniniai sertifikatai</translation>
<translation id="8380941800586852976">Pavojingas</translation>
<translation id="8381674639488873545">Šie mokesčiai gali būti vienkartiniai arba pasikartojantys ir gali būti neaiškūs. <ph name="BEGIN_LINK" />Vis tiek rodyti<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Čia rodomos žymės, kurias naudojote pastaruoju metu</translation>
@@ -1166,6 +1184,7 @@ Papildoma išsami informacija:
<translation id="8416694386774425977">Tinklo konfigūracija netinkama ir jos nepavyko importuoti.
Papildoma išsami informacija:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Įrenginį tvarko <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Keisti</translation>
<translation id="8428213095426709021">Nustatymai</translation>
@@ -1227,6 +1246,7 @@ Papildoma išsami informacija:
<translation id="8932102934695377596">Jūsų laikrodis atsilieka</translation>
<translation id="893332455753468063">Vardo ir pavardės pridėjimas</translation>
<translation id="8938939909778640821">Tinkamos kredito ir išankstinio mokėjimo kortelės</translation>
+<translation id="894185898663964645">Administratorius sukonfigūravo tinkintus šakninius sertifikatus, kurie gali leisti jam peržiūrėti svetainių, kuriose lankotės, turinį.</translation>
<translation id="8943282376843390568">Žaliųjų citrinų spalva</translation>
<translation id="8957210676456822347">Fiksuotojo portalo autorizavimas</translation>
<translation id="8968766641738584599">Išsaugoti kortelę</translation>
diff --git a/chromium/components/strings/components_strings_lv.xtb b/chromium/components/strings/components_strings_lv.xtb
index 9f6b95b47fa..34c93919f50 100644
--- a/chromium/components/strings/components_strings_lv.xtb
+++ b/chromium/components/strings/components_strings_lv.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Lapas netiks tulkotas no šīs valodas: <ph name="LANGUAGE" /></translation>
<translation id="2053553514270667976">Pasta indekss</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ieteikums}zero{# ieteikumi}one{# ieteikums}other{# ieteikumi}}</translation>
+<translation id="2068124040035837596">Jūsu kontu pārvalda <ph name="ENROLLMENT_DOMAIN" />. Tas nozīmē, ka administrators var attāli konfigurēt jūsu kontu.</translation>
<translation id="2068663545051464999">Augšupielādētā avārijas pārskata ID: <ph name="CRASH_ID" /> (lokālais konteksts: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Atsaukt</translation>
<translation id="20817612488360358">Ir iestatīta datora starpniekserveru iestatījumu lietošana, bet ir norādīta arī atklāta starpniekservera konfigurācija.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Šis nosūtīšanas veids nav pieejams. Izmēģiniet citu veidu.</translation>
<translation id="2396249848217231973">&amp;Atsaukt dzēšanu</translation>
<translation id="2413528052993050574">Šis serveris nevarēja pierādīt, ka šī ir vietne <ph name="DOMAIN" />; tās drošības sertifikāts, iespējams, ir atsaukts. Iespējams, tas ir nepareizas konfigurācijas dēļ vai arī kāds ir ļaunprātīgi izmantojis jūsu savienojumu.</translation>
+<translation id="244665789865330679">Jūsu ierīci un kontu pārvalda <ph name="ENROLLMENT_DOMAIN" />. Tas nozīmē, ka administrators var attāli konfigurēt jūsu ierīci un kontu.</translation>
<translation id="2463193859425327265">Mainīt sākumlapu</translation>
<translation id="2463739503403862330">Aizpildīt</translation>
<translation id="2465655957518002998">Izvēlēties piegādes veidu</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719">Jūs mēģinājāt sasniegt <ph name="DOMAIN" />, bet izdevējs atsauca servera uzrādīto sertifikātu. Tas nozīmē, ka servera uzrādītie drošības akreditācijas dati itin nemaz nav uzticami. Iespējams, jūs sazināties ar uzbrucēju.</translation>
<translation id="4378154925671717803">Tālrunis</translation>
<translation id="4406896451731180161">meklēšanas rezultāti</translation>
+<translation id="4406972042435603828">Administratori ir instalējuši paplašinājumus ar jaudīgām iespējām.</translation>
<translation id="4408413947728134509">Sīkfaili <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Saņemšanas adrese</translation>
<translation id="4424024547088906515">Šis serveris nevarēja pierādīt, ka šī ir vietne <ph name="DOMAIN" />; tās drošības sertifikāts netiek uzskatīts par uzticamu pārlūkā Chrome. Iespējams, tas ir nepareizas konfigurācijas dēļ vai arī kāds ir ļaunprātīgi izmantojis jūsu savienojumu.</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">Nav rezultātu</translation>
<translation id="4950898438188848926">Ciļņu pārslēgšanas poga. Nospiediet ievadīšanas taustiņu, lai pārslēgtos uz atvērto cilni, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />.</translation>
<translation id="495170559598752135">Darbības</translation>
+<translation id="495832697253704892">Ziņošana par paplašinājumiem</translation>
<translation id="4958444002117714549">Izvērst sarakstu</translation>
<translation id="4974590756084640048">Atkārtoti iespējot brīdinājumus</translation>
<translation id="4989163558385430922">Skatīt visu</translation>
<translation id="4989809363548539747">Šis spraudnis netiek atbalstīts</translation>
+<translation id="4996230189582812866">Ziņošana</translation>
<translation id="5002932099480077015">Iespējojot šo opciju, Chrome saglabās jūsu kartes informāciju šajā ierīcē, lai jūs varētu ātrāk aizpildīt veidlapas.</translation>
<translation id="5014174725590676422">Tiek rādīts Google asistenta pirmās palaišanas ekrāns pārlūkprogrammā Chrome.</translation>
<translation id="5015510746216210676">Ierīces nosaukums:</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">Štats</translation>
<translation id="5094747076828555589">Šis serveris nevarēja pierādīt, ka šī ir vietne <ph name="DOMAIN" />; tās drošības sertifikāts netiek uzskatīts par uzticamu Chromium sistēmā. Iespējams, tas ir nepareizas konfigurācijas dēļ vai arī kāds ir ļaunprātīgi izmantojis jūsu savienojumu.</translation>
<translation id="5095208057601539847">Province</translation>
+<translation id="5098222253617183465">Jūsu ierīci pārvalda <ph name="ENROLLMENT_DOMAIN" />, un jūsu kontu pārvalda <ph name="ACCOUNT_DOMAIN" />. Tas nozīmē, ka administratori var attāli konfigurēt jūsu ierīci un kontu.</translation>
<translation id="5115563688576182185">(64 bitu)</translation>
<translation id="5128122789703661928">Sesija ar šādu nosaukumu nav dzēšama.</translation>
<translation id="5135404736266831032">Pārvaldīt adreses...</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">Ierīce</translation>
<translation id="5179510805599951267">Vai nav valodā: <ph name="ORIGINAL_LANGUAGE" />? Ziņot par šo kļūdu</translation>
<translation id="5190835502935405962">Grāmatzīmju josla</translation>
+<translation id="5200263511887412697">parāda sarakstu ar ierīces lietotājiem, kuri nesen ir pieteikušies</translation>
<translation id="5201306358585911203">Šajā lapā iegultā lapā ir rakstīts</translation>
<translation id="5205222826937269299">Jānorāda vārds vai nosaukums.</translation>
<translation id="5215116848420601511">Adreses un maksājumu veidi, kuros tiek izmantots pakalpojums Google Pay</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">Šī vietne nav sasniedzama</translation>
<translation id="5869522115854928033">Saglabātās paroles</translation>
<translation id="5887400589839399685">Kartīte ir saglabāta</translation>
+<translation id="5893718151540690985">nosūtīt tīmekļa saskarņu sarakstu ar to veidiem un aparatūras adresēm</translation>
<translation id="5893752035575986141">Tiek pieņemtas kredītkartes.</translation>
<translation id="5901630391730855834">Dzeltena</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (veikta sinhronizācija)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">Kontaktinformācijas rediģēšana</translation>
<translation id="5967867314010545767">Noņemt no vēstures</translation>
<translation id="5975083100439434680">Tālināt</translation>
+<translation id="5977489021191000276">Jūsu ierīci nepārvalda administrators.</translation>
<translation id="5977976211062815271">Šajā ierīcē</translation>
<translation id="598637245381783098">Nevar atvērt maksājumu lietotni</translation>
<translation id="5989320800837274978">Nav norādīti nedz fiksēti starpniekserveri, nedz .pac skripta URL.</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347">Uzbrucēji vietnē <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> varētu instalēt maldinošas lietotnes, kas uzdodas par citu saturu, vai ievākt datus, ko izmantot jūsu izsekošanai. <ph name="BEGIN_LEARN_MORE_LINK" />Uzziniet vairāk<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (veikta sinhronizācija)</translation>
<translation id="6027201098523975773">Ievadiet vārdu</translation>
+<translation id="6033927989869462158">nosūtīt aparatūras statistiku, piemēram, par centrālā procesora/RAM lietojumu</translation>
<translation id="6034000775414344507">Gaiši pelēka</translation>
<translation id="6039846035001940113">Ja problēma joprojām pastāv, sazinieties ar vietnes īpašnieku.</translation>
<translation id="6040143037577758943">Aizvērt</translation>
@@ -904,6 +914,8 @@
<translation id="6897140037006041989">Lietotāja aģents</translation>
<translation id="6903319715792422884">Palīdziet uzlabot Drošo pārlūkošanu, nosūtot noteiktu <ph name="BEGIN_WHITEPAPER_LINK" />sistēmas informāciju un lapas saturu<ph name="END_WHITEPAPER_LINK" /> Google serveriem. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Lietotājs:</translation>
+<translation id="6934672428414710184">Šis vārds ir no jūsu Google konta</translation>
+<translation id="6939583532829045966">Jūsu ierīci pārvalda <ph name="ENROLLMENT_DOMAIN" />. Tas nozīmē, ka administrators var attāli konfigurēt jūsu ierīci.</translation>
<translation id="6944692733090228304">Jūs ievadījāt paroli vietnē, kuru nepārvalda <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Lai aizsargātu savu kontu, neizmantojiet šo paroli citās lietotnēs un vietnēs.</translation>
<translation id="6945221475159498467">Atlasīt</translation>
<translation id="6948701128805548767">Lai skatītu saņemšanas veidus un prasības, atlasiet adresi.</translation>
@@ -991,6 +1003,7 @@ Papildu informācija:
&lt;li&gt;Noklikšķiniet uz &lt;strong&gt;Lietot&lt;/strong&gt;, pēc tam noklikšķiniet uz &lt;strong&gt;Labi&lt;/strong&gt;.
&lt;li&gt;Apmeklējiet &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome palīdzības centru&lt;/a&gt;, lai uzzinātu, kā neatgriezeniski noņemt programmatūru no datora.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> pārvaldība</translation>
<translation id="7416351320495623771">Pārvaldīt paroles…</translation>
<translation id="7419106976560586862">Profila ceļš</translation>
<translation id="7437289804838430631">Pievienot kontaktinformāciju</translation>
@@ -999,10 +1012,12 @@ Papildu informācija:
<translation id="7442725080345379071">Gaiši oranža</translation>
<translation id="7444046173054089907">Šī vietne ir bloķēta</translation>
<translation id="7445762425076701745">Nevar pilnībā apstiprināt servera identifikācijas datus, ar kuru esat savienots. Jums ir izveidots savienojums ar serveri, izmantojot nosaukumu, kas ir derīgs tikai jūsu tīklā, kam ārējā sertifikāta izdevējiestāde nekādā veidā nevar apstiprināt īpašumtiesības. Tā kā dažas sertifikāta izdevējiestādes tāpat izsniegs sertifikātus šādiem nosaukumiem, nav iespējams garantēt, ka jūs esat savienots ar vajadzīgo vietni, nevis uzbrucēju.</translation>
+<translation id="7449109375006139765">sūtīt sistēmas žurnālus pārvaldības serverim</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Uzzināt vairāk<ph name="END_LINK" /> par šo problēmu.</translation>
<translation id="7455133967321480974">Izmantot globālo noklusējumu (Bloķēt)</translation>
<translation id="7460618730930299168">Pārmeklēšana atšķiras no jūsu atlasītās. Vai vēlaties turpināt?</translation>
<translation id="7473891865547856676">Nē, paldies!</translation>
+<translation id="7475525192983021547">nosūtīt laika periodus, kuros lietotājs aktīvi izmanto ierīci</translation>
<translation id="7481312909269577407">Pārsūtīt</translation>
<translation id="7485870689360869515">Dati netika atrasti.</translation>
<translation id="7508255263130623398">Atgrieztais politikas ierīces ID ir tukšs vai neatbilst pašreizējam ierīces ID.</translation>
@@ -1095,6 +1110,7 @@ Papildu informācija:
<translation id="7995512525968007366">Nav norādīts</translation>
<translation id="800218591365569300">Aizveriet citas cilnes vai programmas, lai atbrīvotu vietu atmiņā.</translation>
<translation id="8009225694047762179">Pārvaldīt paroles</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Šī karte un tās norēķinu adrese tiks saglabāta. Jūs varēsiet to izmantot, kad būsiet pierakstījies kontā <ph name="USER_EMAIL" />.}zero{Šīs kartes un to norēķinu adreses tiks saglabātas. Jūs varēsiet tās izmantot, kad būsiet pierakstījies kontā <ph name="USER_EMAIL" />.}one{Šīs kartes un to norēķinu adreses tiks saglabātas. Jūs varēsiet tās izmantot, kad būsiet pierakstījies kontā <ph name="USER_EMAIL" />.}other{Šīs kartes un to norēķinu adreses tiks saglabātas. Jūs varēsiet tās izmantot, kad būsiet pierakstījies kontā <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Mēs nevarējām sasniegt jūsu vecākus. Lūdzu, mēģiniet vēlreiz.</translation>
<translation id="8025119109950072390">Uzbrucēji šajā vietnē var mudināt jūs veikt bīstamas darbības, piemēram, instalēt programmatūru vai atklāt savu personas informāciju (piemēram, paroles, tālruņa numurus vai informāciju par kredītkartēm).</translation>
<translation id="8034522405403831421">Šī lapas saturs ir šādā valodā: <ph name="SOURCE_LANGUAGE" />. Vai tulkot šādā valodā: <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1105,6 +1121,7 @@ Papildu informācija:
<translation id="8041940743680923270">Izmantot globālo noklusējumu (Vaicāt)</translation>
<translation id="8042918947222776840">Izvēlēties saņemšanas veidu</translation>
<translation id="8057711352706143257">Programmatūra <ph name="SOFTWARE_NAME" /> nav pareizi konfigurēta. Atinstalējot programmatūru <ph name="SOFTWARE_NAME" />, parasti problēma tiek novērsta. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Jūsu ierīcē ir veikta šāda konfigurācija:</translation>
<translation id="8078141288243656252">Pagrieztiem dokumentiem nevar pievienot piezīmes</translation>
<translation id="8079031581361219619">Vai atkārtoti ielādēt vietni?</translation>
<translation id="8088680233425245692">Rakstu neizdevās skatīt.</translation>
@@ -1155,6 +1172,7 @@ Papildu informācija:
<translation id="8363502534493474904">Izslēdziet lidojuma režīmu.</translation>
<translation id="8364627913115013041">Nav iestatīta.</translation>
<translation id="8368476060205742148">Google Play pakalpojumi</translation>
+<translation id="8371889962595521444">Pielāgoti saknes sertifikāti</translation>
<translation id="8380941800586852976">Bīstama</translation>
<translation id="8381674639488873545">Maksa var tikt pieprasīta vienreiz vai atkārtoti; iespējams, pieprasījums nebūs skaidri pamanāms. <ph name="BEGIN_LINK" />Tik un tā rādīt<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Nesen izmantotās grāmatzīmes tiek parādītas šeit</translation>
@@ -1164,6 +1182,7 @@ Papildu informācija:
<translation id="8416694386774425977">Tīkla konfigurācija nav derīga, un to nevarēja importēt.
Papildu informācija:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Ierīci pārvalda <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" />, <ph name="SECOND_LABEL" />, <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Mainīt</translation>
<translation id="8428213095426709021">Iestatījumi</translation>
@@ -1225,6 +1244,7 @@ Papildu informācija:
<translation id="8932102934695377596">Norādītais laiks ir pārāk tālu pagātnē</translation>
<translation id="893332455753468063">Vārda pievienošana</translation>
<translation id="8938939909778640821">Atbalstītās kredītkartes un priekšapmaksas kartes</translation>
+<translation id="894185898663964645">Administrators ir konfigurējis pielāgotus saknes sertifikātus, kas, iespējams, ļauj administratoram skatīt apmeklēto vietņu saturu.</translation>
<translation id="8943282376843390568">Laima zaļa</translation>
<translation id="8957210676456822347">Caurlaides lapas autorizācija</translation>
<translation id="8968766641738584599">Saglabāt karti</translation>
diff --git a/chromium/components/strings/components_strings_ml.xtb b/chromium/components/strings/components_strings_ml.xtb
index 51fe66cb9c7..6f5d7a05d2e 100644
--- a/chromium/components/strings/components_strings_ml.xtb
+++ b/chromium/components/strings/components_strings_ml.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" /> ഭാഷയിലുള്ള പേജുകൾ വിവർത്തനം ചെയ്യില്ല.</translation>
<translation id="2053553514270667976">തപാൽ കോഡ്</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{ഒരു നിർദ്ദേശം}other{# നിർദ്ദേശങ്ങൾ}}</translation>
+<translation id="2068124040035837596">നിങ്ങളുടെ അക്കൗണ്ട് മാനേജ് ചെയ്യുന്നത് <ph name="ENROLLMENT_DOMAIN" /> ആണ്. നിങ്ങളുടെ അക്കൗണ്ട് വിദൂരമായി അഡ്‌മിനിസ്‌ട്രേറ്റർ കോൺഫിഗർ ചെയ്യാമെന്നാണ് ഇതിനർത്ഥം.</translation>
<translation id="2068663545051464999">ക്രാഷ് റിപ്പോർട്ട് ഐഡി <ph name="CRASH_ID" /> അപ്‌ലോഡ് ചെയ്‌തു (പ്രാദേശിക സന്ദർഭം: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">പഴയപടിയാക്കുക</translation>
<translation id="20817612488360358">സിസ്റ്റം പ്രോക്‌സി ക്രമീകരണം ഉപയോഗിക്കുന്നതിനായി സജ്ജമാക്കി, പക്ഷെ ഒരു സ്‌പഷ്‌ടമായ പ്രോക്‌സി കോൺഫിഗറേഷനും അതോടൊപ്പം നിർദ്ദേശിച്ചിരിക്കുന്നു.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">ഈ ഷിപ്പിംഗ് രീതി ലഭ്യമല്ല. മറ്റൊരു രീതി പരീക്ഷിക്കുക.</translation>
<translation id="2396249848217231973">&amp;ഇല്ലാതാക്കൽ പഴയപടിയാക്കുക</translation>
<translation id="2413528052993050574">ഈ സെർവറിന് അത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; സെർവറിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റ് റദ്ദാക്കിയിരിക്കാം. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
+<translation id="244665789865330679">നിങ്ങളുടെ ഉപകരണവും അക്കൗണ്ടും മാനേജ് ചെയ്യുന്നത് <ph name="ENROLLMENT_DOMAIN" /> ആണ്. നിങ്ങളുടെ അക്കൗണ്ടും ഉപകരണവും വിദൂരമായി അഡ്‌മിനിസ്‌ട്രേറ്റർ കോൺഫിഗർ ചെയ്യാമെന്നാണ് ഇതിനർത്ഥം.</translation>
<translation id="2463193859425327265">ഹോം പേജ് മാറ്റുക</translation>
<translation id="2463739503403862330">പൂരിപ്പിക്കുക</translation>
<translation id="2465655957518002998">ഡെലിവറി രീതി തിരഞ്ഞെടുക്കുക</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719">നിങ്ങള്‍‌ <ph name="DOMAIN" /> എന്നതില്‍‌ എത്താന്‍‌ ശ്രമിച്ചു, പക്ഷേ സെര്‍‌വര്‍‌ നൽകിയ സര്‍‌ട്ടിഫിക്കറ്റ് അത് നല്‍‌കിയ ആള്‍‌ അസാധുവാക്കി. സെര്‍‌വര്‍‌ നല്‍‌കിയ സുരക്ഷാ ക്രെഡന്‍‌ഷ്യലുകള്‍‌ തികച്ചും വിശ്വാ‍സയോഗ്യമല്ല എന്നാണ് ഇതിനര്‍‌ത്ഥം. നിങ്ങള്‍‌ ഒരു ആക്രമണകാരിയുമായിട്ടാകാം ആശയവിനിമയം നടത്തുന്നത്.</translation>
<translation id="4378154925671717803">ഫോൺ</translation>
<translation id="4406896451731180161">തിരയൽ ഫലങ്ങൾ</translation>
+<translation id="4406972042435603828">നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്റർമാർ ശക്തമായ ശേഷികളുള്ള വിപുലീകരണങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്‌തിട്ടുണ്ട്.</translation>
<translation id="4408413947728134509">കുക്കികൾ <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">പിക്കപ്പ് വിലാസം</translation>
<translation id="4424024547088906515">ഈ സെർവറിന് അത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷാ സർട്ടിഫിക്കറ്റ് Chrome-ന് പരിചയമില്ലാത്തതാണ്. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">ഫലങ്ങളൊന്നുമില്ല</translation>
<translation id="4950898438188848926">ടാബ് മാറാനുള്ള ബട്ടൺ, തുറന്നിരിക്കുന്ന ടാബായ <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /> എന്നതിലേക്ക് മാറാൻ എൻ്റർ അമർത്തുക</translation>
<translation id="495170559598752135">പ്രവര്‍ത്തനങ്ങള്‍</translation>
+<translation id="495832697253704892">വിപുലീകരണം റിപ്പോർട്ട് ചെയ്യൽ</translation>
<translation id="4958444002117714549">ലിസ്റ്റ് വിപുലീകരിക്കുക</translation>
<translation id="4974590756084640048">മുന്നറിയിപ്പുകൾ വീണ്ടും പ്രവർത്തനക്ഷമമാക്കുക</translation>
<translation id="4989163558385430922">എല്ലാം കാണുക</translation>
<translation id="4989809363548539747">ഈ പ്ലഗിൻ പിന്തുണയ്‌ക്കുന്നില്ല</translation>
+<translation id="4996230189582812866">റിപ്പോർട്ട് ചെയ്യൽ</translation>
<translation id="5002932099480077015">പ്രവർത്തനക്ഷമമാക്കിയെങ്കിൽ, വേഗത്തിൽ ഫോം പൂരിപ്പിക്കാൻ Chrome ഈ ഉപകരണത്തിൽ നിങ്ങളുടെ കാർഡിന്റെ ഒരു പകർപ്പ് സൂക്ഷിക്കും.</translation>
<translation id="5014174725590676422">Chrome-ലെ Google അസിസ്‌റ്റന്‍റ്, ആദ്യ റൺ സ്‌ക്രീൻ കാണിക്കുന്നു</translation>
<translation id="5015510746216210676">മെഷീനിന്‍റെ പേര്‌:</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">സ്റ്റേറ്റ്</translation>
<translation id="5094747076828555589">ഈ സെർവറിന് അത് <ph name="DOMAIN" /> ആണെന്ന് തെളിയിക്കാനായില്ല; അതിന്റെ സുരക്ഷ സർട്ടിഫിക്കറ്റിനെ Chromium-ത്തിന്ന് പരിചയമില്ല. തെറ്റായ കോൺഫിഗറേഷൻ കാരണമോ ഒരു അക്രമണകാരി നിങ്ങളുടെ കണക്ഷനെ തടസ്സപ്പെടുത്തുന്നത് കൊണ്ടോ ആയിരിക്കാം ഇത് സംഭവിച്ചത്.</translation>
<translation id="5095208057601539847">പ്രവിശ്യ</translation>
+<translation id="5098222253617183465">നിങ്ങളുടെ ഉപകരണം മാനേജ് ചെയ്യുന്നത് <ph name="ENROLLMENT_DOMAIN" />-ഉം അക്കൗണ്ട് മാനേജ് ചെയ്യുന്നത് <ph name="ACCOUNT_DOMAIN" />-ഉം ആണ്. നിങ്ങളുടെ ഉപകരണവും അക്കൗണ്ടും അഡ്‌മിനിസ്‌ട്രേറ്റർമാർ വിദൂരമായി കോൺഫിഗർ ചെയ്യാമെന്നാണ് ഇതിനർത്ഥം.</translation>
<translation id="5115563688576182185">(64-ബിറ്റ്)</translation>
<translation id="5128122789703661928">സെഷന്‍റെ പേര് തെറ്റായതിനാൽ ഇല്ലാതാക്കാനായില്ല.</translation>
<translation id="5135404736266831032">വിലാസങ്ങൾ മാനേജ് ചെയ്യുക...</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">മെഷീൻ</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> എന്നതില്‍‌ ഇല്ലേ? ഈ പിശക് റിപ്പോര്‍‌ട്ടുചെയ്യുക</translation>
<translation id="5190835502935405962">ബുക്ക്‌മാര്‍‌ക്കുകള്‍‌ ബാര്‍‌</translation>
+<translation id="5200263511887412697">അടുത്തിടെ ലോഗിൻ ചെയ്‌ത ഉപകരണ ഉപയോക്താക്കളുടെ ലിസ്‌റ്റ് റിപ്പോർട്ട് ചെയ്യുക</translation>
<translation id="5201306358585911203">ഈ പേജിലെ ഉൾച്ചേർത്ത പേജ് പറയുന്നത്:</translation>
<translation id="5205222826937269299">പേര് ആവശ്യമാണ്</translation>
<translation id="5215116848420601511">Google Pay ഉപയോഗിക്കുന്ന വിലാസങ്ങളും പേയ്മെന്റ് രീതികളും</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">ഈ സൈറ്റ് ലഭ്യമാക്കാനാകുന്നില്ല</translation>
<translation id="5869522115854928033">സംരക്ഷിച്ച പാസ്‌വേഡുകള്‍</translation>
<translation id="5887400589839399685">കാർഡ് സംരക്ഷിച്ചു</translation>
+<translation id="5893718151540690985">നെറ്റ്‌വർക്ക് ഇന്റർഫേസുകളുടെ ലിസ്റ്റും അതിൻ്റെ തരങ്ങളും ഹാർഡ്‌വെയർ വിലാസങ്ങളും റിപ്പോർട്ട് ചെയ്യുക</translation>
<translation id="5893752035575986141">ക്രെഡിറ്റ് കാർഡുകൾ സ്വീകരിക്കുന്നു.</translation>
<translation id="5901630391730855834">മഞ്ഞ</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (സമന്വയിപ്പിച്ചത്)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">കോൺടാക്‌റ്റ് വിവരം എഡിറ്റുചെയ്യുക</translation>
<translation id="5967867314010545767">ചരിത്രത്തിൽ നിന്നും നീക്കംചെയ്യുക</translation>
<translation id="5975083100439434680">സൂം ഔട്ട്</translation>
+<translation id="5977489021191000276">നിങ്ങളുടെ ഉപകരണം അഡ്‌മിനിസ്ട്രേറ്റർ മാനേജ് ചെയ്യുന്നില്ല.</translation>
<translation id="5977976211062815271">ഈ ഉപകരണത്തിലേത്</translation>
<translation id="598637245381783098">പേയ്‌മെന്റ് ആപ്പ് തുറക്കാനായില്ല</translation>
<translation id="5989320800837274978">ഒരു സ്ഥിരമായ പ്രോക്സി സെർവർ അല്ലെങ്കിൽ ഒരു .pac സ്‌ക്രിപ്റ്റ് URL വ്യക്തമാക്കിയിട്ടില്ല.</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> എന്നതിലുള്ള അക്രമികൾ, മറ്റെന്തെങ്കിലുമാണെന്ന വ്യാജേന തെറ്റിദ്ധരിപ്പിക്കുന്ന ആപ്പുകൾ ഇൻസ്‌റ്റാൾ ചെയ്യാം അല്ലെങ്കിൽ ഡാറ്റ ശേഖരിച്ച് നിങ്ങളെ ട്രാക്കുചെയ്യാൻ ഉപയോഗിക്കാം. <ph name="BEGIN_LEARN_MORE_LINK" />കൂടുതലറിയുക<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (സമന്വയിപ്പിച്ചത്)</translation>
<translation id="6027201098523975773">ഒരു പേര് നൽകുക</translation>
+<translation id="6033927989869462158">CPU/RAM ഉപയോഗം പോലുള്ള ഹാർഡ്‌വെയർ സ്ഥിതിവിവരക്കണക്കുകൾ റിപ്പോർട്ട് ചെയ്യുക</translation>
<translation id="6034000775414344507">ഇളം ചാരനിറം</translation>
<translation id="6039846035001940113">പ്രശ്‌നം പരിഹരിക്കപ്പെടുന്നില്ലെങ്കിൽ, സൈറ്റ് ഉടമയെ ബന്ധപ്പെടുക.</translation>
<translation id="6040143037577758943">അടയ്ക്കുക</translation>
@@ -903,6 +913,8 @@
<translation id="6897140037006041989">ഉപയോക്തൃ ഏജന്‍റ്</translation>
<translation id="6903319715792422884">ചില <ph name="BEGIN_WHITEPAPER_LINK" />സിസ്‌റ്റം വിവരങ്ങളും പേജ് ഉള്ളടക്കവും<ph name="END_WHITEPAPER_LINK" /> Google-ലേക്ക് അയച്ച്, സുരക്ഷിത ബ്രൗസിംഗ് മെച്ചപ്പെടുത്താൻ സഹായിക്കുക. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ഉപയോക്താവ്:</translation>
+<translation id="6934672428414710184">ഈ പേര് നിങ്ങളുടെ Google അക്കൗണ്ടിൽ നിന്നുള്ളതാണ്</translation>
+<translation id="6939583532829045966">നിങ്ങളുടെ ഉപകരണം മാനേജ് ചെയ്യുന്നത് <ph name="ENROLLMENT_DOMAIN" /> ആണ്. നിങ്ങളുടെ അക്കൗണ്ട് വിദൂരമായി അഡ്‌മിനിസ്‌ട്രേറ്റർ കോൺഫിഗർ ചെയ്യാമെന്നാണ് ഇതിനർത്ഥം.</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> മാനേജ് ചെയ്യാത്ത ഒരു സൈറ്റിൽ നിങ്ങൾ പാസ്‌വേഡ് നൽകി. നിങ്ങളുടെ അക്കൗണ്ട് പരിരക്ഷിക്കുന്നതിന്, മറ്റ് ആപ്പുകളിലും സൈറ്റുകളിലും നിങ്ങളുടെ പാസ്‌വേഡ് വീണ്ടും ഉപയോഗിക്കരുത്.</translation>
<translation id="6945221475159498467">തിരഞ്ഞെടുക്കുക</translation>
<translation id="6948701128805548767">പിക്ക്അപ്പ് രീതികളും ആവശ്യകതകളും കാണാൻ ഒരു വിലാസം തിരഞ്ഞെടുക്കുക</translation>
@@ -988,6 +1000,7 @@
&lt;strong&gt;സ്റ്റാർട്ടപ്പ് തരം/strong&gt; എന്നതിന് താഴെ, &lt;strong&gt;പ്രവർത്തനരഹിതമാക്കി&lt;/strong&gt; തിരഞ്ഞെടുക്കുക &lt;li&gt;&lt;strong&gt;സേവന നില&lt;/strong&gt; എന്നതിന് താഴെ, &lt;strong&gt;നിർത്തുക&lt;/strong&gt; ക്ലിക്ക് ചെയ്യുക &lt;li&gt;&lt;strong&gt;പ്രയോഗിക്കുക&lt;/strong&gt; ക്ലിക്ക് ചെയ്യുക, തുടർന്ന് &lt;strong&gt;ശരി&lt;/strong&gt; ക്ലിക്ക് ചെയ്യുക &lt;li&gt;
നിങ്ങളുടെ കമ്പ്യൂട്ടറിൽ നിന്ന് എങ്ങനെയാണ് സോഫ്റ്റ്‌വെയർ ശാശ്വതമായി നീക്കംചെയ്യുന്നത് എന്നറിയാൻ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome സഹായ കേന്ദ്രം&lt;/a&gt; സന്ദർശിക്കുക &lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> മാനേജ്‌മെൻ്റ്</translation>
<translation id="7416351320495623771">പാസ്‌വേഡുകൾ മാനേജ് ചെയ്യുക…</translation>
<translation id="7419106976560586862">പ്രൊഫൈൽ പാത</translation>
<translation id="7437289804838430631">ബന്ധപ്പെടാനുള്ള വിവരങ്ങൾ ചേർക്കുക</translation>
@@ -996,10 +1009,12 @@
<translation id="7442725080345379071">ഇളം ഓറഞ്ച് നിറം</translation>
<translation id="7444046173054089907">ഈ സൈറ്റ് ബ്ലോക്കുചെയ്‌തു</translation>
<translation id="7445762425076701745">നിങ്ങള്‍ ബന്ധിപ്പിച്ച സെര്‍വറിന്‍റെ ഐഡന്‍റിറ്റി പൂര്‍ണ്ണമായി സാധൂകരിക്കാന്‍ കഴിയില്ല. നിങ്ങളുടെ നെറ്റ്‍വര്‍ക്കില്‍ മാത്രം സാധുവായ ഒരു നാമം ഉപയോഗിക്കുന്ന സെര്‍വറിലേക്ക് നിങ്ങള്‍ ബന്ധിപ്പിച്ചിരിക്കുന്നു, അതിന്‍റെ ഉടമസ്ഥാവകാശം ഒരു ബാഹ്യ അതോറിറ്റിയ്ക്ക് ഒരിക്കലും സാധൂകരിക്കാന്‍ കഴിയില്ല. ചില സാക്‍ഷ്യപത്ര അതോറിറ്റികള്‍ ഈ നാമങ്ങളെ കണക്കാക്കാതെ സാക്‍ഷ്യപത്രങ്ങള്‍ നല്‍കുന്നതിനാല്‍, ഉദ്ദേശിച്ച വെബ്സൈറ്റിലേക്കാണ് നിങ്ങള്‍ ബന്ധിപ്പിച്ചിരിക്കുന്നതെന്നും ഒരു ആക്രമണകാരിയല്ലെന്നും ഉറപ്പാക്കാന്‍ ഒരു മാര്‍ഗ്ഗവുമില്ല.</translation>
+<translation id="7449109375006139765">മാനേജ്‌മെൻ്റ് സെർവറിലേക്ക് സിസ്‌റ്റം ലോഗുകൾ അയയ്‌ക്കുക</translation>
<translation id="7451311239929941790">ഈ പ്രശ്‌നത്തെക്കുറിച്ച് <ph name="BEGIN_LINK" />കൂടുതലറിയുന്നു<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">ഗ്ലോബൽ ഡിഫോൾട്ട് ഉപയോഗിക്കുക (തടയുക)</translation>
<translation id="7460618730930299168">നിങ്ങൾ തിരഞ്ഞെടുത്തതിൽ നിന്ന് വ്യത്യസ്‌തമാണ് ഈ സ്ക്രീനിംഗ്. തുടരണോ?</translation>
<translation id="7473891865547856676">വേണ്ട, നന്ദി</translation>
+<translation id="7475525192983021547">ഉപയോക്താവ് ഉപകരണത്തിൽ സജീവമായിരിക്കുമ്പോൾ സമയ കാലയളവ് റിപ്പോർട്ട് ചെയ്യുക</translation>
<translation id="7481312909269577407">മുന്നോട്ട്</translation>
<translation id="7485870689360869515">ഡാറ്റകളൊന്നും കണ്ടെത്തിയില്ല.</translation>
<translation id="7508255263130623398">നൽകിയ നയ ഉപകരണ ഐഡി ശൂന്യമാണ് അല്ലെങ്കിൽ നിലവിലെ ഉപകരണ ഐഡിയുമായി യോജിക്കുന്നില്ല</translation>
@@ -1092,6 +1107,7 @@
<translation id="7995512525968007366">വ്യക്തമാക്കിയിട്ടില്ല</translation>
<translation id="800218591365569300">ഇടം സൃഷ്‌ടിക്കാൻ മറ്റ് ടാബുകളോ പ്രോഗ്രാമുകളോ അടയ്‌ക്കുന്നത് പരീക്ഷിക്കൂ.</translation>
<translation id="8009225694047762179">പാസ്‌വേഡുകൾ മാനേജ് ചെയ്യുക</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ഈ കാർഡും അവയുടെ ബില്ലിംഗ് വിലാസവും സംരക്ഷിക്കപ്പെടും. നിങ്ങൾ <ph name="USER_EMAIL" /> എന്നതിലേക്ക് സൈൻ ഇൻ ചെയ്‌തിരിക്കുമ്പോൾ അത് ഉപയോഗിക്കാനാകും.}other{ഈ കാർഡുകളും അവയുടെ ബില്ലിംഗ് വിലാസങ്ങളും സംരക്ഷിക്കപ്പെടും. നിങ്ങൾ <ph name="USER_EMAIL" /> എന്നതിലേക്ക് സൈൻ ഇൻ ചെയ്‌തിരിക്കുമ്പോൾ അവ ഉപയോഗിക്കാനാകും.}}</translation>
<translation id="8012647001091218357">ഇപ്പോൾ ഞങ്ങൾക്ക് നിങ്ങളുടെ രക്ഷകർത്താക്കളെ ബന്ധപ്പെടാനായില്ല. വീണ്ടും ശ്രമിക്കുക.</translation>
<translation id="8025119109950072390">ഈ സൈറ്റിലെ ആക്രമണകാരികൾ സോഫ്‌റ്റ്‌വെയർ ഇൻസ്റ്റാൾ ചെയ്യുന്നതോ വ്യക്തിപരമായ വിവരങ്ങൾ വെളിപ്പെടുത്തുന്നതോ (ഉദാഹരണത്തിന്, പാസ്‌വേഡുകൾ, ഫോൺ നമ്പറുകൾ, ക്രെഡിറ്റ് കാർഡുകൾ എന്നീ വിവരങ്ങൾ) പോലുള്ള അപകടകരമായ കാര്യങ്ങൾ ചെയ്യിപ്പിക്കുന്ന തരത്തിൽ നിങ്ങളെ കബളിപ്പിച്ചേക്കാം.</translation>
<translation id="8034522405403831421">ഈ പേജ് <ph name="SOURCE_LANGUAGE" />-ലാണ്. <ph name="TARGET_LANGUAGE" />-ലേക്ക് വിവർത്തനം ചെയ്യണോ?</translation>
@@ -1102,6 +1118,7 @@
<translation id="8041940743680923270">ഗ്ലോബൽ ഡിഫോൾട്ട് ഉപയോഗിക്കുക (ചോദിക്കുക)</translation>
<translation id="8042918947222776840">പിക്കപ്പ് രീതി തിരഞ്ഞെടുക്കുക</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" ശരിയായി കോൺഫിഗർ ചെയ്‌‌തിട്ടില്ല. സാധാരണഗതിയിൽ "<ph name="SOFTWARE_NAME" />" അൺഇൻസ്‌റ്റാൾ ചെയ്യുന്നതിലൂടെ ഈ പ്രശ്‌നം പരിഹരിക്കാം. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">നിങ്ങളുടെ ഉപകരണം ഇതിലേക്ക് കോൺഫിഗർ ചെയ്‌തു:</translation>
<translation id="8078141288243656252">തിരിക്കുമ്പോൾ അനോട്ടേറ്റ് ചെയ്യാനാവില്ല</translation>
<translation id="8079031581361219619">സൈറ്റ് റീലോഡ് ചെയ്യണോ?</translation>
<translation id="8088680233425245692">ലേഖനം കാണുന്നത് പരാജയപ്പെട്ടു.</translation>
@@ -1152,6 +1169,7 @@
<translation id="8363502534493474904">ഫ്ലൈറ്റ് മോഡ് ഓഫാക്കുന്നു</translation>
<translation id="8364627913115013041">സജ്ജമാക്കിയിട്ടില്ല.</translation>
<translation id="8368476060205742148">Google Play സേവനങ്ങൾ</translation>
+<translation id="8371889962595521444">ഇഷ്‌ടാനുസൃത റൂട്ട് സർട്ടിഫിക്കറ്റുകൾ</translation>
<translation id="8380941800586852976">അപകടകരമായത്</translation>
<translation id="8381674639488873545">ഈ നിരക്കുകൾ ഒറ്റത്തവണ അടയ്ക്കുന്നതോ ആവർത്തിക്കുന്നതോ ആവാം, ഒപ്പം വ്യക്തമല്ലായിരിക്കാം. <ph name="BEGIN_LINK" />എന്തായാലും കാണിക്കുക<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">നിങ്ങൾ അടുത്തിടെ സന്ദർശിച്ച ബുക്ക്‌മാർക്കുകൾ ഇവിടെ ദൃശ്യമാകും</translation>
@@ -1161,6 +1179,7 @@
<translation id="8416694386774425977">നെറ്റ്‌വർക്ക് കോൺഫിഗറേഷൻ അസാധുവായതിനാൽ ഇമ്പോർട്ട് ചെയ്യാൻ കഴിഞ്ഞില്ല.
കൂടുതൽ വിശദാംശങ്ങൾ:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">ഉപകരണം മാനേജ് ചെയ്യുന്നത്<ph name="ENROLLMENT_DOMAIN" /> ആണ്</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">മാറ്റുക</translation>
<translation id="8428213095426709021">ക്രമീകരണങ്ങള്‍</translation>
@@ -1221,6 +1240,7 @@
<translation id="8932102934695377596">നിങ്ങളുടെ ക്ലോക്ക് വളരെ പിന്നിലാണ്</translation>
<translation id="893332455753468063">പേര് ചേർക്കുക</translation>
<translation id="8938939909778640821">ക്രെഡിറ്റ് കാർഡുകളും പ്രീപെയ്ഡ് കാർഡുകളും സ്വീകരിക്കുന്നു</translation>
+<translation id="894185898663964645">നിങ്ങളുടെ അഡ്‌മിനിസ്ട്രേറ്റർ ഇഷ്‌ടാനുസൃത റൂട്ട് സർട്ടിഫിക്കറ്റുകൾ കോൺഫിഗർ ചെയ്‌തിട്ടുണ്ട്, അത് വെബ്‌സൈറ്റുകളുടെ ഉള്ളടക്കം കാണാൻ അഡ്‌മിനിസ്ട്രേറ്ററെ അനുവദിച്ചേക്കാം.</translation>
<translation id="8943282376843390568">ചെറുനാരങ്ങയുടെ നിറം</translation>
<translation id="8957210676456822347">ക്യാപ്‌റ്റീവ് പോർട്ടൽ അംഗീകരിക്കൽ</translation>
<translation id="8968766641738584599">കാർഡ് സംരക്ഷിക്കുക</translation>
diff --git a/chromium/components/strings/components_strings_mr.xtb b/chromium/components/strings/components_strings_mr.xtb
index 2ce5f585f98..93e99f54e68 100644
--- a/chromium/components/strings/components_strings_mr.xtb
+++ b/chromium/components/strings/components_strings_mr.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" />मधील पेज भाषांतरीत केले जाणार नाहीत.</translation>
<translation id="2053553514270667976">पिनकोड</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 सूचना}one{# सूचना}other{# सूचना}}</translation>
+<translation id="2068124040035837596">तुमचे खाते <ph name="ENROLLMENT_DOMAIN" /> कडून व्यवस्थापित केले जाते. याचा अर्थ तुमचा अ‍ॅडमिनिस्ट्रेटर तुमचे खाते रिमोट पद्धतीने कॉन्फिगर करू शकतो.</translation>
<translation id="2068663545051464999">क्रॅश अहवाल <ph name="CRASH_ID" /> आयडी अपलोड केला (स्थानिक संदर्भ: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">पहिल्यासारखे करा</translation>
<translation id="20817612488360358">सिस्टम प्रॉक्सी सेटिंग्ज वापरण्‍यास सेट करण्‍यात आल्या परंतु एक सुस्पष्‍ट प्रॉक्सी कॉन्फिगरेशन देखील निर्दिष्‍ट करण्‍यात आले.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">ही शिपिंग पद्धत उपलब्ध नाही. वेगळी पद्धत वापरून पहा.</translation>
<translation id="2396249848217231973">&amp;हटवा पूर्ववत करा</translation>
<translation id="2413528052993050574">हा सर्व्हर हे <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याचे सुरक्षितता सर्टिफिकेट कदाचित रद्द केले असू शकते. हे कदाचित एका चुकीच्या कॉंफिगरेशनमुळे किंवा हल्लेखोराने तुमचे कनेक्शन इंटरसेप्ट केल्यामुळे झाले असू शकते.</translation>
+<translation id="244665789865330679">तुमचे डिव्हाइस आणि खाते <ph name="ENROLLMENT_DOMAIN" /> कडून व्यवस्थापित केले जाते. याचा अर्थ तुमचा अ‍ॅडमिनिस्ट्रेटर तुमचे डिव्हाइस आणि खाते रिमोट पद्धतीने कॉन्फिगर करू शकतो.</translation>
<translation id="2463193859425327265">होम पेज बदला</translation>
<translation id="2463739503403862330">भरून टाका</translation>
<translation id="2465655957518002998">वितरणाची पद्धत निवडा</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719">तुम्ही <ph name="DOMAIN" /> वर पोहोचण्याचा प्रयत्न केला, परंतु सर्व्हरने सादर केलेले प्रमाणपत्र त्याच्या जारीकर्त्याद्वारे मागे घेतले गेले आहे. याचा अर्थ सर्व्हरने सादर केलेल्या सुरक्षा क्रेडेंशियलवर अजिबात विश्वास ठेवला जाऊ नये. तुम्ही कदाचित आक्रमणकर्त्याशी संवाद प्रइंस्टॉल करत आहात.</translation>
<translation id="4378154925671717803">फोन</translation>
<translation id="4406896451731180161">शोध परिणाम</translation>
+<translation id="4406972042435603828">तुमच्या अ‍ॅडमिनिस्ट्रेटरनी शक्तिशाली क्षमता असलेली एक्स्टेंशन इंस्टॉल केली आहेत.</translation>
<translation id="4408413947728134509">कुकीज <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">घेण्याचा पत्ता</translation>
<translation id="4424024547088906515">हा सर्व्हर हे <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याचे सुरक्षितता सर्टिफिकेट Chrome द्वारे विश्वसनीय नाही. हे कदाचित एका चुकीच्या कॉंफिगरेशनमुळे किंवा हल्लेखोराने तुमचे कनेक्शन इंटरसेप्ट केल्यामुळे झाले असू शकते.</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">परिणाम नाहीत</translation>
<translation id="4950898438188848926">टॅब स्विच बटण, उघड्या टॅबवर स्विच करण्यासाठी एंटर दाबा, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">क्रिया</translation>
+<translation id="495832697253704892">एक्स्टेंशनचा अहवाल देणे</translation>
<translation id="4958444002117714549">सूची विस्तृत करा</translation>
<translation id="4974590756084640048">चेतावण्या पुन्हा सक्षम करा</translation>
<translation id="4989163558385430922">सर्व पाहा</translation>
<translation id="4989809363548539747">हे प्लगिन समर्थित नाही</translation>
+<translation id="4996230189582812866">अहवाल देणे</translation>
<translation id="5002932099480077015">सक्षम केल्‍यास, Chrome जलदपणे फॉर्म भरण्‍यासाठी आपल्‍या कार्डची एक प्रत या डिव्‍हाइसवर संग्रहित करेल.</translation>
<translation id="5014174725590676422">Chrome मध्ये Google असिस्टंट पहिल्यांदा रन केलेली स्क्रीन दाखवली आहे</translation>
<translation id="5015510746216210676">मशीन नाव:</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">राज्य</translation>
<translation id="5094747076828555589">हा सर्व्हर हे <ph name="DOMAIN" /> असल्याचे सिद्ध करू शकला नाही; त्याचे सुरक्षितता सर्टिफिकेट Chromium द्वारे विश्वसनीय नाही. हे कदाचित एका चुकीच्या कॉंफिगरेशनमुळे किंवा हल्लेखोराने तुमचे कनेक्शन इंटरसेप्ट केल्यामुळे झाले असू शकते.</translation>
<translation id="5095208057601539847">प्रांत</translation>
+<translation id="5098222253617183465">तुमचे डिव्हाइस <ph name="ENROLLMENT_DOMAIN" /> कडून व्यवस्थापित केले जाते आणि तुमचे खाते <ph name="ACCOUNT_DOMAIN" /> कडून व्यवस्थापित केले जाते. याचा अर्थ तुमचे अ‍ॅडमिनिस्ट्रेटर तुमचे डिव्हाइस आणि खाते रिमोट पद्धतीने कॉन्फिगर करू शकतात.</translation>
<translation id="5115563688576182185">(64-बिट)</translation>
<translation id="5128122789703661928">हे नाव असलेले सेशन हटवण्यासाठी वैध नाही.</translation>
<translation id="5135404736266831032">पत्ते व्यवस्थापित करा...</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">मशीन</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> मध्ये नाही? या एररचा अहवाल नोंदवा</translation>
<translation id="5190835502935405962">बुकमार्क बार</translation>
+<translation id="5200263511887412697">नुकतेच लॉग इन केलेल्या डिव्हाइस वापरकर्त्यांची अहवाल सूची</translation>
<translation id="5201306358585911203">या पेजवरील एंबेड केलेल्‍या पेजचे म्हणणे हे आहे की</translation>
<translation id="5205222826937269299">नाव आवश्यक आहे</translation>
<translation id="5215116848420601511">Google Pay वापरून पेमेंट पद्धती आणि पत्ते</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">या साइटवर पोहचणे शक्य नाही</translation>
<translation id="5869522115854928033">सेव्ह केलेले पासवर्ड</translation>
<translation id="5887400589839399685">कार्ड सेव्ह केले</translation>
+<translation id="5893718151540690985">नेटवर्क इंटरफेसच्या सूचीचा त्यांचे प्रकार आणि हार्डवेअर अ‍ॅड्रेससह अहवाल द्या</translation>
<translation id="5893752035575986141">क्रेडिट कार्डे स्वीकारली जातात.</translation>
<translation id="5901630391730855834">पिवळा</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (सिंक केलेले)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">संपर्क माहिती संपादित करा</translation>
<translation id="5967867314010545767">इतिहासातून काढून टाका</translation>
<translation id="5975083100439434680">झूम कमी करा</translation>
+<translation id="5977489021191000276">तुमचे डिव्हाइस अ‍ॅडमिनिस्ट्रेटरकडून व्यवस्थापित केले जात नाही.</translation>
<translation id="5977976211062815271">या डिव्हाइसवरील</translation>
<translation id="598637245381783098">पेमेंट ॲप उघडू शकत नाही</translation>
<translation id="5989320800837274978">निश्चित प्रॉक्‍सी सर्व्हर किंवा .pac स्क्रिप्ट URL देखील निर्दिष्‍ट केलेली नाही.</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />वर असलेले आक्रमणकर्ता फसवणारे अॅप्स इंस्टॉल करू शकतात जे दुसरे काहीतरी असल्याचे भासवू शकतात किंवा तुम्हाला शोधण्यासाठी डेटा वापरू शकतात. <ph name="BEGIN_LEARN_MORE_LINK" />अधिक जाणून घ्या<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (सिंक केलेले)</translation>
<translation id="6027201098523975773">नाव एंटर करा</translation>
+<translation id="6033927989869462158">CPU/RAM वापरासारख्या हार्डवेअर आकडेवारीचा अहवाल द्या</translation>
<translation id="6034000775414344507">फिकट राखाडी</translation>
<translation id="6039846035001940113">समस्या कायम राहिल्यास साइटच्या मालकाशी संपर्क साधा.</translation>
<translation id="6040143037577758943">बंद करा</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">वापरकर्ता एजंट</translation>
<translation id="6903319715792422884">सुरक्षित ब्राउझिंगमध्ये सुधारणा करण्यासाठी Google ला काही <ph name="BEGIN_WHITEPAPER_LINK" />सिस्टम माहिती आणि पेज आशय<ph name="END_WHITEPAPER_LINK" /> पाठवून मदत करा. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">वापरकर्ता:</translation>
+<translation id="6934672428414710184">हे नाव तुमच्या Google खात्यावरून आहे</translation>
+<translation id="6939583532829045966">तुमचे डिव्हाइस <ph name="ENROLLMENT_DOMAIN" /> कडून व्यवस्थापित केले जाते. याचा अर्थ तुमचा अ‍ॅडमिनिस्ट्रेटर तुमचे डिव्हाइस रिमोट पद्धतीने कॉन्फिगर करू शकतो.</translation>
<translation id="6944692733090228304">तुम्ही पासवर्ड एंटर केलेली साइट <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> द्वारे व्यवस्थापित केलेली नाही. तुमच्या खात्याच्या संरक्षणासाठी, तुमचा पासवर्ड इतर अॅप्स किंवा साइटवर पुन्हा वापरू नका.</translation>
<translation id="6945221475159498467">निवडा</translation>
<translation id="6948701128805548767">पिकअप पद्धती आणि आवश्यकता पाहण्यासाठी, एक पत्ता निवडा</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;&lt;strong&gt;लागू करा&lt;/strong&gt; वर क्लिक करा, मग &lt;strong&gt;ओके&lt;/strong&gt; वर क्लिक करा
&lt;li&gt;तुमच्या कॉंप्युटरवरून सॉफ्टवेअर कायमस्वरूपी कसे काढून टाकावे याबाबत शिकण्यासाठी&lt;a href="https://support.google.com/chrome/answer/6०९886९"&gt;Chrome मदत केंद्र&lt;/a&gt; ला भेट द्या.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> व्यवस्थापन</translation>
<translation id="7416351320495623771">पासवर्ड व्यवस्थापित करा…</translation>
<translation id="7419106976560586862">प्रोफाइल पथ</translation>
<translation id="7437289804838430631">संपर्क माहिती जोडा</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">फिकट नारिंगी</translation>
<translation id="7444046173054089907">ही साइट अवरोधित केली आहे</translation>
<translation id="7445762425076701745">तुम्ही कनेक्ट केलेल्या सर्व्हरची ओळख पूर्णपणे पडताळणे शक्य नाही. तुम्ही सर्व्हरशी फक्त आपल्‍या डोमेनमध्ये वैध असलेले नाव वापरून कनेक्ट केलेले आहे, ज्याची मालकी सत्यापित करण्यासाठी बाह्य सर्टिफिकेट अधिकृततेला परवानगी नाही. काही सर्टिफिकेट अधिकारी तरीही या नावांसाठी सर्टिफिकेट जारी करतील, याची खात्री करण्याचा काहीही मार्ग नाही की तुम्ही इच्छित वेबसाइटशी कनेक्ट केले आहे आणि हल्लेखोराशी नाही.</translation>
+<translation id="7449109375006139765">सिस्टम लॉग व्यवस्थापन सर्व्हरला पाठवा</translation>
<translation id="7451311239929941790">या समस्येविषयी <ph name="BEGIN_LINK" />अधिक जाणून घेणे<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">सार्वत्रिक डीफॉल्‍ट वापरा (अवरोधित करा)</translation>
<translation id="7460618730930299168">तुम्ही जे निवडले, त्यापेक्षा स्क्रीनिंग वेगळे आहे. सुरू ठेवायचे का?</translation>
<translation id="7473891865547856676">नाही, नको</translation>
+<translation id="7475525192983021547">वापरकर्ता डिव्हाइसवर अ‍ॅक्टिव्ह असतानाच्या कालावधींचा अहवाल द्या</translation>
<translation id="7481312909269577407">पुढील</translation>
<translation id="7485870689360869515">डेटा आढळला नाही.</translation>
<translation id="7508255263130623398">परत केलेला धोरण डिव्हाइस आयडी रिक्त आहे किंवा वर्तमान डिव्हाइस आयडी शी जुळत नाही</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">नमूद केलेले नाही</translation>
<translation id="800218591365569300">मेमरी मोकळी करण्‍यासाठी अन्य टॅब किंवा प्रोग्राम बंद करून पहा.</translation>
<translation id="8009225694047762179">पासवर्ड व्यवस्थापित करा</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{हे कार्ड आणि त्याचा बिलिंग पत्ता सेव्ह केला जाईल. <ph name="USER_EMAIL" /> मध्ये साइन इन केलेले असताना तुम्ही ते वापरू शकाल.}one{हे कार्ड आणि त्याचा बिलिंग पत्ता सेव्ह केला जाईल. <ph name="USER_EMAIL" /> मध्ये साइन इन केलेले असताना तुम्ही ते वापरू शकाल.}other{ही कार्डे आणि त्यांचे बिलिंग पत्ते सेव्ह केले जातील. <ph name="USER_EMAIL" /> मध्ये साइन इन केलेले असताना तुम्ही ती वापरू शकाल.}}</translation>
<translation id="8012647001091218357">आम्ही याक्षणी आपल्या पालकांपर्यंत पोहोचू शकलो नाही. कृपया पुन्हा प्रयत्न करा.</translation>
<translation id="8025119109950072390">या साइट वरील आक्रमणकर्ते सॉफ्‍टवेअर इंस्टॉल करणे किंवा तुमची वैयक्तिक माहिती (उदाहरणार्थ, पासवर्ड, फोन नंबर किंवा क्रेडिट कार्ड) उघड करणे यासारखे काहीतरी धोकादायक करण्‍यामध्‍ये आपल्‍याला युक्तीने गुंतवू शकतात.</translation>
<translation id="8034522405403831421">हे पृष्‍ठ <ph name="SOURCE_LANGUAGE" /> मध्ये आहे. त्यास <ph name="TARGET_LANGUAGE" /> मध्ये भाषांतरीत करायचे?</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">सार्वत्रिक डीफॉल्‍ट वापरा (विचारा)</translation>
<translation id="8042918947222776840">पिकअप पद्धत निवडा</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" योग्य रीतीने कॉन्फिगर केलेले नाही. "<ph name="SOFTWARE_NAME" />" अनइंस्टॉल केल्याने सहसा समस्या सुटते. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">तुमचे डिव्हाइस यावर कॉन्फिगर केले गेले आहे:</translation>
<translation id="8078141288243656252">फिरवल्यावर भाष्य करू शकत नाही</translation>
<translation id="8079031581361219619">साइट रीलोड करायची?</translation>
<translation id="8088680233425245692">लेख पाहण्यात अयशस्वी.</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">विमान मोड बंद करा</translation>
<translation id="8364627913115013041">सेट केलेले नाही.</translation>
<translation id="8368476060205742148">Google Play सेवा</translation>
+<translation id="8371889962595521444">कस्टम रूट सर्टिफिकेट</translation>
<translation id="8380941800586852976">धोकादायक</translation>
<translation id="8381674639488873545">हे शुल्क एका वेळचे किंवा आवर्ती असू शकते आणि ते उघड नसणे शक्य आहे. <ph name="BEGIN_LINK" />तरीही दाखवा<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">तुम्ही अलिकडेच भेट दिलेले बुकमार्क येथे दिसतील</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">नेटवर्क कॉन्फिगरेशन चुकीचे आहे आणि इंपोर्ट केले जाऊ शकत नाही.
अतिरिक्त तपशील:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">डिव्हाइस <ph name="ENROLLMENT_DOMAIN" /> ने व्‍यवस्‍थापित केले आहे</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">बदल करा</translation>
<translation id="8428213095426709021">सेटिंग्ज</translation>
@@ -1225,6 +1244,7 @@
<translation id="8932102934695377596">तुमचे घड्याळ मागे आहे</translation>
<translation id="893332455753468063">नाव जोडा</translation>
<translation id="8938939909778640821">स्वीकारलेली क्रेडिट आणि प्रीपेड कार्डे</translation>
+<translation id="894185898663964645">तुमच्या अ‍ॅडमिनिस्ट्रेटरने कस्टम रूट सर्टिफिकेट कॉन्फिगर केली आहेत, ज्यामुळे अ‍ॅडमिनिस्ट्रेटरला तुम्ही भेट देत असलेल्या वेबसाइटचे आशय पाहण्यास अनुमती मिळू शकते.</translation>
<translation id="8943282376843390568">लिंबू</translation>
<translation id="8957210676456822347">बंद पोर्टल प्राधिकृतता</translation>
<translation id="8968766641738584599">कार्ड सेव्ह करा</translation>
diff --git a/chromium/components/strings/components_strings_ms.xtb b/chromium/components/strings/components_strings_ms.xtb
index 29f59cc4258..ada6cc9015f 100644
--- a/chromium/components/strings/components_strings_ms.xtb
+++ b/chromium/components/strings/components_strings_ms.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Halaman dalam <ph name="LANGUAGE" /> tidak akan diterjemah.</translation>
<translation id="2053553514270667976">Poskod</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 cadangan}other{# cadangan}}</translation>
+<translation id="2068124040035837596">Akaun anda diurus oleh <ph name="ENROLLMENT_DOMAIN" />. Ini bermakna pentadbir anda boleh mengkonfigurasikan akaun anda dari jauh.</translation>
<translation id="2068663545051464999">Memuat Naik ID Laporan Ranap <ph name="CRASH_ID" /> (Kandungan Setempat: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Buat asal</translation>
<translation id="20817612488360358">Tetapan proksi sistem telah sedia untuk digunakan tetapi konfigurasi proksi jelas juga telah ditentukan.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Kaedah penghantaran ini tidak tersedia. Cuba kaedah lain.</translation>
<translation id="2396249848217231973">&amp;Buat asal pemadaman</translation>
<translation id="2413528052993050574">Pelayan ini tidak dapat membuktikan bahawa domainnya ialah <ph name="DOMAIN" />; sijil keselamatannya mungkin dibatalkan. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang yang memintasi sambungan anda.</translation>
+<translation id="244665789865330679">Peranti dan akaun anda diurus oleh <ph name="ENROLLMENT_DOMAIN" />. Ini bermakna pentadbir anda boleh mengkonfigurasikan peranti dan akaun anda dari jauh.</translation>
<translation id="2463193859425327265">Tukar Halaman Utama</translation>
<translation id="2463739503403862330">Isi</translation>
<translation id="2465655957518002998">Pilih Kaedah Penghantaran</translation>
@@ -562,6 +564,7 @@
<translation id="4377125064752653719">Anda cuba untuk mencapai <ph name="DOMAIN" />, tetapi sijil yang diberi pelayan telah dibatalkan oleh pengeluarnya. Ini bermakna bahawa bukti kelayakan keselamatan yang diberi pelayan sememangnya tidak harus dipercayai. Anda mungkin berkomunikasi dengan penyerang.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">hasil carian</translation>
+<translation id="4406972042435603828">Pentadbir anda telah memasang sambungan yang mempunyai keupayaan yang kuat.</translation>
<translation id="4408413947728134509">Kuki <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Alamat Pengambilan</translation>
<translation id="4424024547088906515">Pelayan ini tidak dapat membuktikan bahawa domainnya ialah <ph name="DOMAIN" />; sijil keselamatannya tidak dipercayai oleh Chrome. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang memintasi sambungan anda.</translation>
@@ -633,10 +636,12 @@
<translation id="4943872375798546930">Tiada hasil carian</translation>
<translation id="4950898438188848926">Butang peralihan tab, tekan Enter untuk beralih ke tab yang terbuka, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Tindakan</translation>
+<translation id="495832697253704892">Pelaporan sambungan</translation>
<translation id="4958444002117714549">Kembangkan senarai</translation>
<translation id="4974590756084640048">Dayakan semula amaran</translation>
<translation id="4989163558385430922">Lihat semua</translation>
<translation id="4989809363548539747">Pemalam ini tidak disokong</translation>
+<translation id="4996230189582812866">Pelaporan</translation>
<translation id="5002932099480077015">Jika didayakan, Chrome akan menyimpan salinan kad anda pada peranti ini untuk pengisian borang yang lebih cepat.</translation>
<translation id="5014174725590676422">Google Assistant dalam skrin pelaksanaan pertama Chrome dipaparkan</translation>
<translation id="5015510746216210676">Nama Mesin:</translation>
@@ -657,6 +662,7 @@
<translation id="5089810972385038852">Negeri</translation>
<translation id="5094747076828555589">Pelayan ini tidak dapat membuktikan bahawa domainnya ialah <ph name="DOMAIN" />; sijil keselamatannya tidak dipercayai oleh Chromium. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang yang memintasi sambungan anda.</translation>
<translation id="5095208057601539847">Wilayah</translation>
+<translation id="5098222253617183465">Peranti anda diurus oleh <ph name="ENROLLMENT_DOMAIN" /> dan akaun anda diurus oleh <ph name="ACCOUNT_DOMAIN" />. Ini bermakna pentadbir anda boleh mengkonfigurasikan peranti dan akaun anda dari jauh.</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5128122789703661928">Sesi dengan nama ini tidak sah untuk pemadaman.</translation>
<translation id="5135404736266831032">Urus alamat...</translation>
@@ -669,6 +675,7 @@
<translation id="5172758083709347301">Mesin</translation>
<translation id="5179510805599951267">Bukan dalam <ph name="ORIGINAL_LANGUAGE" />? Laporkan ralat ini</translation>
<translation id="5190835502935405962">Bar Penanda Halaman</translation>
+<translation id="5200263511887412697">laporkan senarai pengguna peranti yang telah log masuk baru-baru ini</translation>
<translation id="5201306358585911203">Halaman terbenam pada halaman ini menyatakan</translation>
<translation id="5205222826937269299">Nama diperlukan</translation>
<translation id="5215116848420601511">Kaedah pembayaran dan alamat yang menggunakan Google Pay</translation>
@@ -770,6 +777,7 @@
<translation id="5869405914158311789">Tapak ini tidak dapat dicapai</translation>
<translation id="5869522115854928033">Kata laluan disimpan</translation>
<translation id="5887400589839399685">Kad disimpan</translation>
+<translation id="5893718151540690985">laporkan senarai antara muka rangkaian bersama jenis dan alamat perkakasannya</translation>
<translation id="5893752035575986141">Kad kredit diterima.</translation>
<translation id="5901630391730855834">Kuning</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (disegerakkan)</translation>
@@ -783,6 +791,7 @@
<translation id="5967592137238574583">Edit Maklumat Hubungan</translation>
<translation id="5967867314010545767">Buang daripada sejarah</translation>
<translation id="5975083100439434680">Zum keluar</translation>
+<translation id="5977489021191000276">Peranti anda tidak diurus oleh pentadbir.</translation>
<translation id="5977976211062815271">Pada peranti ini</translation>
<translation id="598637245381783098">Tidak dapat membuka apl pembayaran</translation>
<translation id="5989320800837274978">Pelayan proksi tetap begitu juga URL skrip .pac, kedua-duanya tidak ditetapkan.</translation>
@@ -794,6 +803,7 @@
<translation id="6017850046339264347">Penyerang di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> boleh memasang apl yang mengelirukan yang menyamar menjadi sesuatu yang lain atau mengumpul data yang boleh digunakan untuk menjejak anda. <ph name="BEGIN_LEARN_MORE_LINK" />Ketahui lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (disegerakkan)</translation>
<translation id="6027201098523975773">Masukkan nama</translation>
+<translation id="6033927989869462158">laporkan statistik perkakasan seperti penggunaan CPU/RAM</translation>
<translation id="6034000775414344507">Kelabu Cerah</translation>
<translation id="6039846035001940113">Jika masalah berterusan, hubungi pemilik tapak.</translation>
<translation id="6040143037577758943">Tutup</translation>
@@ -906,6 +916,8 @@
<translation id="6897140037006041989">Ejen Pengguna</translation>
<translation id="6903319715792422884">Bantu dalam meningkatkan Penyemakan Imbas Selamat dengan menghantar beberapa <ph name="BEGIN_WHITEPAPER_LINK" />maklumat sistem dan kandungan halaman<ph name="END_WHITEPAPER_LINK" /> kepada Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Pengguna:</translation>
+<translation id="6934672428414710184">Nama ini daripada Akaun Google anda</translation>
+<translation id="6939583532829045966">Peranti anda diurus oleh <ph name="ENROLLMENT_DOMAIN" />. Ini bermakna pentadbir anda boleh mengkonfigurasikan peranti anda dari jauh.</translation>
<translation id="6944692733090228304">Anda memasukkan kata laluan di tapak yang tidak diurus oleh <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Untuk melindungi akaun anda, jangan gunakan semula kata laluan anda pada apl dan tapak lain.</translation>
<translation id="6945221475159498467">Pilih</translation>
<translation id="6948701128805548767">Pilih alamat untuk melihat kaedah dan syarat pengambilan</translation>
@@ -993,6 +1005,7 @@ Butiran tambahan:
&lt;li&gt;Klik &lt;strong&gt;Apply&lt;/strong&gt;, kemudian klik &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Lawati &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Pusat bantuan Chrome&lt;/a&gt; untuk mengetahui cara mengalih keluar perisian itu daripada komputer anda secara kekal
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Pengurusan <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Urus Kata Laluan…</translation>
<translation id="7419106976560586862">Laluan Profil</translation>
<translation id="7437289804838430631">Tambahkan Maklumat Hubungan</translation>
@@ -1001,10 +1014,12 @@ Butiran tambahan:
<translation id="7442725080345379071">Jingga Cerah</translation>
<translation id="7444046173054089907">Tapak ini disekat</translation>
<translation id="7445762425076701745">Identiti pelayan yang disambungkan kepada anda tidak dapat disahkan sepenuhnya. Anda disambungkan ke pelayan menggunakan nama yang sah dalam rangkaian anda sahaja, apabila pihak berkuasa sijil luaran tiada cara untuk mengesahkan pemilikan. Oleh kerana beberapa pihak berkuasa sijil juga akan terus mengeluarkan sijil untuk nama ini, tiada cara untuk memastikan anda disambungkan ke tapak web yang diingini dan bukannya penyerang.</translation>
+<translation id="7449109375006139765">hantar log sistem ke pelayan pengurusan</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Ketahui lebih lanjut<ph name="END_LINK" /> tentang masalah ini.</translation>
<translation id="7455133967321480974">Gunakan lalai global (Sekat)</translation>
<translation id="7460618730930299168">Tayangan ini berbeza daripada pilihan anda. Teruskan?</translation>
<translation id="7473891865547856676">Tidak, Terima Kasih</translation>
+<translation id="7475525192983021547">laporkan tempoh masa apabila pengguna aktif pada peranti</translation>
<translation id="7481312909269577407">Majukan</translation>
<translation id="7485870689360869515">Tiada data dijumpai.</translation>
<translation id="7508255263130623398">Id peranti yang dikembalikan kosong atau tidak sepadan dengan id peranti semasa</translation>
@@ -1097,6 +1112,7 @@ Butiran tambahan:
<translation id="7995512525968007366">Tidak Ditentukan</translation>
<translation id="800218591365569300">Cuba tutup tab atau atur cara lain untuk mengosongkan memori.</translation>
<translation id="8009225694047762179">Urus Kata Laluan</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Kad ini dan alamat pengebilannya akan disimpan. Anda akan dapat menggunakan kad ini apabila anda log masuk ke <ph name="USER_EMAIL" />.}other{Kad ini dan alamat pengebilannya akan disimpan. Anda akan dapat menggunakan kad ini apabila anda log masuk ke <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Kami tidak dapat menghubungi ibu bapa anda pada masa ini. Sila cuba lagi.</translation>
<translation id="8025119109950072390">Penyerang pada tapak ini mungkin menipu anda supaya melakukan sesuatu yang berbahaya seperti memasang perisian atau mendedahkan maklumat peribadi anda (contohnya, kata laluan, nombor telefon atau maklumat kad kredit).</translation>
<translation id="8034522405403831421">Halaman ini dalam <ph name="SOURCE_LANGUAGE" />. Terjemahkannya kepada <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1107,6 +1123,7 @@ Butiran tambahan:
<translation id="8041940743680923270">Gunakan lalai global (Tanya)</translation>
<translation id="8042918947222776840">Pilih Kaedah Pengambilan</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" tidak dikonfigurasi dengan betul. Tindakan menyahpasang "<ph name="SOFTWARE_NAME" />" biasanya dapat menyelesaikan masalah ini. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Peranti anda telah dikonfigurasikan kepada:</translation>
<translation id="8078141288243656252">Tidak boleh melakukan anotasi apabila diputarkan</translation>
<translation id="8079031581361219619">Muatkan semula tapak?</translation>
<translation id="8088680233425245692">Gagal melihat artikel.</translation>
@@ -1157,6 +1174,7 @@ Butiran tambahan:
<translation id="8363502534493474904">Matikan mod pesawat</translation>
<translation id="8364627913115013041">Tidak ditetapkan.</translation>
<translation id="8368476060205742148">Perkhidmatan Google Play</translation>
+<translation id="8371889962595521444">Sijil akar tersuai</translation>
<translation id="8380941800586852976">Berbahaya</translation>
<translation id="8381674639488873545">Caj ini mungkin caj sekali atau caj berulang dan mungkin tidak ketara. <ph name="BEGIN_LINK" />Tunjukkan juga<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Penanda halaman anda yang terbaharu dilawati dipaparkan di sini</translation>
@@ -1166,6 +1184,7 @@ Butiran tambahan:
<translation id="8416694386774425977">Konfigurasi rangkaian tidak sah dan tidak boleh diimport.
Butiran tambahan:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Peranti diurus oleh <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Tukar</translation>
<translation id="8428213095426709021">Tetapan</translation>
@@ -1227,6 +1246,7 @@ Butiran tambahan:
<translation id="8932102934695377596">Jam anda di belakang</translation>
<translation id="893332455753468063">Tambahkan Nama</translation>
<translation id="8938939909778640821">Kad kredit dan prabayar yang diterima</translation>
+<translation id="894185898663964645">Pentadbir anda telah mengkonfigurasikan sijil akar tersuai, yang mungkin membolehkan pentadbir anda melihat kandungan tapak web yang anda lawati.</translation>
<translation id="8943282376843390568">Hijau pucuk pisang</translation>
<translation id="8957210676456822347">Keizinan Portal Tawanan</translation>
<translation id="8968766641738584599">Simpan kad</translation>
diff --git a/chromium/components/strings/components_strings_nl.xtb b/chromium/components/strings/components_strings_nl.xtb
index f3d99a0e8fb..24d5d138494 100644
--- a/chromium/components/strings/components_strings_nl.xtb
+++ b/chromium/components/strings/components_strings_nl.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Pagina's in het <ph name="LANGUAGE" /> worden niet vertaald.</translation>
<translation id="2053553514270667976">Postcode</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestie}other{# suggesties}}</translation>
+<translation id="2068124040035837596">Je account wordt beheerd door <ph name="ENROLLMENT_DOMAIN" />. Dat betekent dat je beheerder je account op afstand kan configureren.</translation>
<translation id="2068663545051464999">Crashrapport-ID <ph name="CRASH_ID" /> geüpload (lokale context: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Ongedaan maken</translation>
<translation id="20817612488360358">De proxyinstellingen van het systeem moeten worden gebruikt, maar er is ook een expliciete proxyconfiguratie opgegeven.</translation>
@@ -212,7 +213,7 @@
<translation id="2202020181578195191">Geef een geldig vervaljaar op</translation>
<translation id="2212735316055980242">Beleid niet gevonden</translation>
<translation id="2213606439339815911">Items ophalen…</translation>
-<translation id="2218879909401188352">Aanvallers die zich momenteel op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> bevinden, kunnen gevaarlijke apps installeren die je apparaat beschadigen, verborgen kosten toevoegen aan je mobiele telefoonrekening of je persoonlijke gegevens stelen. <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="2218879909401188352">Aanvallers die zich momenteel op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> bevinden, kunnen gevaarlijke apps installeren die je apparaat beschadigen, verborgen kosten toevoegen aan je mobiele telefoonrekening of je persoonsgegevens stelen. <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2224337661447660594">Geen internet</translation>
<translation id="2230458221926704099">Los problemen met je verbinding op met de <ph name="BEGIN_LINK" />diagnose-app<ph name="END_LINK" /></translation>
<translation id="2239100178324503013">Nu verzenden</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Deze verzendmethode is niet beschikbaar. Kies een andere methode.</translation>
<translation id="2396249848217231973">&amp;Verwijderen ongedaan maken</translation>
<translation id="2413528052993050574">De server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het beveiligingscertificaat van de server is mogelijk ingetrokken. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.</translation>
+<translation id="244665789865330679">Je apparaat en account worden beheerd door <ph name="ENROLLMENT_DOMAIN" />. Dat betekent dat je beheerder je apparaat en account op afstand kan configureren.</translation>
<translation id="2463193859425327265">Homepage wijzigen</translation>
<translation id="2463739503403862330">Invullen</translation>
<translation id="2465655957518002998">Bezorgingsmethode kiezen</translation>
@@ -453,7 +455,7 @@
<translation id="3739623965217189342">Link die je hebt gekopieerd</translation>
<translation id="3744899669254331632">Je kunt <ph name="SITE" /> op dit moment niet bezoeken, omdat de website gecodeerde inloggegevens heeft verstuurd die niet door Chromium kunnen worden verwerkt. Aangezien netwerkfouten en aanvallen doorgaans van tijdelijke aard zijn, zal deze pagina later waarschijnlijk wel werken.</translation>
<translation id="3745099705178523657">Nadat je hebt bevestigd, worden de kaartgegevens uit je Google-account gedeeld met deze site.</translation>
-<translation id="3748148204939282805">Cybercriminelen op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> proberen je mogelijk te misleiden om iets gevaarlijks te doen, zoals software installeren of je persoonlijke gegevens bekendmaken (bijvoorbeeld wachtwoorden, telefoonnummers of creditcardgegevens). <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
+<translation id="3748148204939282805">Cybercriminelen op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> proberen je mogelijk te misleiden om iets gevaarlijks te doen, zoals software installeren of je persoonsgegevens bekendmaken (bijvoorbeeld wachtwoorden, telefoonnummers of creditcardgegevens). <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="375403751935624634">Het vertalen is mislukt wegens een serverfout.</translation>
<translation id="3759461132968374835">Je hebt geen onlangs gemelde crashes. Crashes die zich voordeden toen de crashrapportage was uitgeschakeld, worden hier niet weergegeven.</translation>
<translation id="3761718714832595332">Status verbergen</translation>
@@ -556,6 +558,7 @@
<translation id="4377125064752653719">Je probeert <ph name="DOMAIN" /> te bereiken, maar het certificaat dat de server heeft geretourneerd, is ingetrokken door de uitgever. Dat betekent dat de veiligheidsgaranties die de server heeft geretourneerd, absoluut niet kunnen worden vertrouwd. Het kan zijn dat je met een hacker aan het communiceren bent.</translation>
<translation id="4378154925671717803">Telefoon</translation>
<translation id="4406896451731180161">zoekresultaten</translation>
+<translation id="4406972042435603828">Je beheerders hebben extensies met krachtige functionaliteit geïnstalleerd.</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> cookies</translation>
<translation id="4415426530740016218">Ophaaladres</translation>
<translation id="4424024547088906515">De server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het beveiligingscertificaat van de server wordt niet vertrouwd door Chrome. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.</translation>
@@ -627,10 +630,12 @@
<translation id="4943872375798546930">Geen resultaten</translation>
<translation id="4950898438188848926">Schakelknop voor tabbladen, druk op Enter om naar het geopende tabblad, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />, te schakelen</translation>
<translation id="495170559598752135">Acties</translation>
+<translation id="495832697253704892">Extensierapportage</translation>
<translation id="4958444002117714549">Lijst uitvouwen</translation>
<translation id="4974590756084640048">Waarschuwingen opnieuw inschakelen</translation>
<translation id="4989163558385430922">Alles weergeven</translation>
<translation id="4989809363548539747">Deze plug-in wordt niet ondersteund</translation>
+<translation id="4996230189582812866">Rapportage</translation>
<translation id="5002932099480077015">Indien ingeschakeld, slaat Chrome een kopie van je kaart op dit apparaat op zodat formulieren sneller kunnen worden ingevuld.</translation>
<translation id="5014174725590676422">Het eerste uitvoeringsscherm van de Google Assistent in Chrome wordt weergegeven</translation>
<translation id="5015510746216210676">Naam apparaat:</translation>
@@ -651,6 +656,7 @@
<translation id="5089810972385038852">Staat</translation>
<translation id="5094747076828555589">De server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het beveiligingscertificaat van de server wordt niet vertrouwd door Chromium. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.</translation>
<translation id="5095208057601539847">Provincie</translation>
+<translation id="5098222253617183465">Je apparaat wordt beheerd door <ph name="ENROLLMENT_DOMAIN" /> en je account wordt beheerd door <ph name="ACCOUNT_DOMAIN" />. Dit betekent dat je beheerders je apparaat en account op afstand kunnen configureren.</translation>
<translation id="5115563688576182185">(64-bits)</translation>
<translation id="5128122789703661928">De naam van deze sessie die je wilt verwijderen, is ongeldig.</translation>
<translation id="5135404736266831032">Adressen beheren...</translation>
@@ -663,6 +669,7 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Niet in het <ph name="ORIGINAL_LANGUAGE" />? Deze fout melden</translation>
<translation id="5190835502935405962">Bladwijzerbalk</translation>
+<translation id="5200263511887412697">lijst melden met apparaatgebruikers die onlangs zijn ingelogd</translation>
<translation id="5201306358585911203">Een ingesloten pagina op deze pagina meldt het volgende</translation>
<translation id="5205222826937269299">Naam vereist</translation>
<translation id="5215116848420601511">Betaalmethoden en adressen die Google Pay gebruiken</translation>
@@ -764,6 +771,7 @@
<translation id="5869405914158311789">Deze site is niet bereikbaar</translation>
<translation id="5869522115854928033">Opgeslagen wachtwoorden</translation>
<translation id="5887400589839399685">Kaart opgeslagen</translation>
+<translation id="5893718151540690985">lijst van netwerkinterfaces rapporteren met de bijbehorende typen en hardware-adressen</translation>
<translation id="5893752035575986141">Creditcards worden geaccepteerd.</translation>
<translation id="5901630391730855834">Geel</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (gesynchroniseerd)</translation>
@@ -777,6 +785,7 @@
<translation id="5967592137238574583">Contactgegevens bewerken</translation>
<translation id="5967867314010545767">Verwijderen uit geschiedenis</translation>
<translation id="5975083100439434680">Uitzoomen</translation>
+<translation id="5977489021191000276">Je apparaat wordt niet beheerd door een beheerder.</translation>
<translation id="5977976211062815271">Op dit apparaat</translation>
<translation id="598637245381783098">Kan betaal-app niet openen</translation>
<translation id="5989320800837274978">Er worden geen vaste proxyservers en geen pac-script-URL gespecificeerd.</translation>
@@ -788,12 +797,13 @@
<translation id="6017850046339264347">Aanvallers op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kunnen misleidende apps installeren die zich voordoen als iets anders of gegevens verzamelen die kunnen worden gebruikt om je te volgen. <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (gesynchroniseerd)</translation>
<translation id="6027201098523975773">Geef een naam op</translation>
+<translation id="6033927989869462158">hardwarestatistieken rapporteren zoals CPU-/RAM-gebruik</translation>
<translation id="6034000775414344507">Lichtgrijs</translation>
<translation id="6039846035001940113">Als het probleem blijft optreden, neem je contact op met de site-eigenaar.</translation>
<translation id="6040143037577758943">Sluiten</translation>
<translation id="6044573915096792553">Grootte 12</translation>
<translation id="6047233362582046994">Als je de beveiligingsrisico's begrijpt, kun je <ph name="BEGIN_LINK" />deze site bezoeken<ph name="END_LINK" /> voordat de schadelijke apps zijn verwijderd.</translation>
-<translation id="6047927260846328439">Deze content probeert je mogelijk te misleiden om software te installeren of persoonlijke gegevens openbaar te maken. <ph name="BEGIN_LINK" />Toch weergeven<ph name="END_LINK" /></translation>
+<translation id="6047927260846328439">Deze content probeert je mogelijk te misleiden om software te installeren of persoonsgegevens openbaar te maken. <ph name="BEGIN_LINK" />Toch weergeven<ph name="END_LINK" /></translation>
<translation id="6051221802930200923">Je kunt <ph name="SITE" /> momenteel niet bezoeken, omdat de website gebruikmaakt van certificaatpinning. Netwerkfouten en aanvallen zijn doorgaans tijdelijk, dus deze pagina werkt later waarschijnlijk correct.</translation>
<translation id="6058977677006700226">Je kaarten gebruiken op al je apparaten?</translation>
<translation id="6059925163896151826">USB-apparaten</translation>
@@ -848,7 +858,7 @@
<translation id="6451458296329894277">Opnieuw indienen bevestigen</translation>
<translation id="6465306955648956876">Wachtwoorden beheren...</translation>
<translation id="647261751007945333">Apparaatbeleid</translation>
-<translation id="6477321094435799029">Chrome heeft ongebruikelijke code op deze pagina gedetecteerd en heeft de code geblokkeerd om je persoonlijke gegevens (zoals wachtwoorden, telefoonnummers en creditcards) te beschermen.</translation>
+<translation id="6477321094435799029">Chrome heeft ongebruikelijke code op deze pagina gedetecteerd en heeft de code geblokkeerd om je persoonsgegevens (zoals wachtwoorden, telefoonnummers en creditcards) te beschermen.</translation>
<translation id="6489534406876378309">Uploaden van crashes starten</translation>
<translation id="6499038740797743453">Wachtwoord opnieuw instellen?</translation>
<translation id="6507833130742554667">Creditcards en betaalpassen worden geaccepteerd.</translation>
@@ -899,6 +909,8 @@
<translation id="6897140037006041989">User-agent</translation>
<translation id="6903319715792422884">Help Safe Browsing te verbeteren door bepaalde <ph name="BEGIN_WHITEPAPER_LINK" />systeeminformatie en paginacontent<ph name="END_WHITEPAPER_LINK" /> naar Google te verzenden. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Gebruiker:</translation>
+<translation id="6934672428414710184">Dit is de naam die in je Google-account staat</translation>
+<translation id="6939583532829045966">Je apparaat wordt beheerd door <ph name="ENROLLMENT_DOMAIN" />. Dat betekent dat je beheerder je apparaat op afstand kan configureren.</translation>
<translation id="6944692733090228304">Je hebt je wachtwoord ingevoerd op een site die niet door <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> wordt beheerd. Ter bescherming van je account kun je je wachtwoord beter niet hergebruiken voor andere apps en sites.</translation>
<translation id="6945221475159498467">Selecteren</translation>
<translation id="6948701128805548767">Selecteer een adres om ophaalmethoden en vereisten te bekijken</translation>
@@ -986,6 +998,7 @@ Aanvullende informatie:
&lt;li&gt;Klik op &lt;strong&gt;Toepassen&lt;/strong&gt; en vervolgens op &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Ga naar het &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Helpcentrum van Chrome&lt;/a&gt; voor meer informatie over hoe je de software definitief van je computer kunt verwijderen
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Beheer van <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Wachtwoorden beheren…</translation>
<translation id="7419106976560586862">Profielpad</translation>
<translation id="7437289804838430631">Contactgegevens toevoegen</translation>
@@ -994,10 +1007,12 @@ Aanvullende informatie:
<translation id="7442725080345379071">Lichtoranje</translation>
<translation id="7444046173054089907">Deze site is geblokkeerd</translation>
<translation id="7445762425076701745">De identiteit van de server waarmee je verbinding maakt, kan niet volledig worden geverifieerd. Je hebt verbinding gemaakt met een server die een naam gebruikt die alleen binnen je netwerk geldig is. Een externe certificeringsinstantie kan hiervoor nooit het eigendom verifiëren. Aangezien sommige certificeringsinstanties toch certificaten voor deze namen verlenen, kun je nooit zeker weten of je verbinding hebt met de bedoelde website en niet met een aanvaller.</translation>
+<translation id="7449109375006139765">systeemlogboeken naar de beheerserver verzenden</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Meer informatie<ph name="END_LINK" /> over dit probleem.</translation>
<translation id="7455133967321480974">Algemene standaardinstelling gebruiken (Blokkeren)</translation>
<translation id="7460618730930299168">De screening verschilt van wat je hebt geselecteerd. Doorgaan?</translation>
<translation id="7473891865547856676">Nee, bedankt</translation>
+<translation id="7475525192983021547">perioden rapporteren waarin een gebruiker actief is op het apparaat</translation>
<translation id="7481312909269577407">Vooruit</translation>
<translation id="7485870689360869515">Geen gegevens gevonden.</translation>
<translation id="7508255263130623398">Geretourneerde apparaat-ID voor beleid is leeg of komt niet overeen met de huidige apparaat-ID</translation>
@@ -1090,8 +1105,9 @@ Aanvullende informatie:
<translation id="7995512525968007366">Niet opgegeven</translation>
<translation id="800218591365569300">Probeer andere tabbladen en programma's te sluiten om geheugen vrij te maken.</translation>
<translation id="8009225694047762179">Wachtwoorden beheren</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Deze kaart en het bijbehorende factuuradres worden opgeslagen. Je kunt deze gegevens gebruiken wanneer je bent ingelogd op <ph name="USER_EMAIL" />.}other{Deze kaarten en de bijbehorende factuuradressen worden opgeslagen. Je kunt deze gegevens gebruiken wanneer je bent ingelogd op <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">We kunnen je ouders momenteel niet bereiken. Probeer het opnieuw.</translation>
-<translation id="8025119109950072390">Cybercriminelen op deze site proberen je mogelijk te misleiden om iets gevaarlijks te doen, zoals software installeren of je persoonlijke gegevens bekendmaken (bijvoorbeeld wachtwoorden, telefoonnummers of creditcards).</translation>
+<translation id="8025119109950072390">Cybercriminelen op deze site proberen je mogelijk te misleiden om iets gevaarlijks te doen, zoals software installeren of je persoonsgegevens bekendmaken (bijvoorbeeld wachtwoorden, telefoonnummers of creditcards).</translation>
<translation id="8034522405403831421">Deze pagina is in het <ph name="SOURCE_LANGUAGE" />. Vertalen naar het <ph name="TARGET_LANGUAGE" />?</translation>
<translation id="8035152190676905274">Pen</translation>
<translation id="8037357227543935929">Vragen (standaard)</translation>
@@ -1100,6 +1116,7 @@ Aanvullende informatie:
<translation id="8041940743680923270">Algemene standaardinstelling gebruiken (Vragen)</translation>
<translation id="8042918947222776840">Ophaalmethode kiezen</translation>
<translation id="8057711352706143257">'<ph name="SOFTWARE_NAME" />' is niet correct geconfigureerd. Als je '<ph name="SOFTWARE_NAME" />' verwijdert, wordt het probleem meestal opgelost. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Je apparaat is geconfigureerd naar:</translation>
<translation id="8078141288243656252">Kan geen aantekeningen maken als het document is gedraaid</translation>
<translation id="8079031581361219619">Site opnieuw laden?</translation>
<translation id="8088680233425245692">Kan artikel niet bekijken.</translation>
@@ -1150,6 +1167,7 @@ Aanvullende informatie:
<translation id="8363502534493474904">Schakel de vliegtuigmodus uit</translation>
<translation id="8364627913115013041">Niet ingesteld.</translation>
<translation id="8368476060205742148">Google Play-services</translation>
+<translation id="8371889962595521444">Custom rootcertificaten</translation>
<translation id="8380941800586852976">Gevaarlijk</translation>
<translation id="8381674639488873545">Deze kosten kunnen eenmalig of terugkerend zijn en zijn mogelijk niet duidelijk aangegeven. <ph name="BEGIN_LINK" />Toch weergeven<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Je onlangs bezochte bladwijzers worden hier weergegeven</translation>
@@ -1159,6 +1177,7 @@ Aanvullende informatie:
<translation id="8416694386774425977">De netwerkconfiguratie is ongeldig en kan niet worden geïmporteerd.
Aanvullende informatie:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Apparaat beheerd door <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Wijzigen</translation>
<translation id="8428213095426709021">Instellingen</translation>
@@ -1219,6 +1238,7 @@ Aanvullende informatie:
<translation id="8932102934695377596">Je klok loopt achter</translation>
<translation id="893332455753468063">Naam toevoegen</translation>
<translation id="8938939909778640821">Geaccepteerde creditcards en prepaidkaarten</translation>
+<translation id="894185898663964645">Je beheerder heeft custom rootcertificaten geconfigureerd, waardoor de beheerder mogelijk de content kan bekijken van websites die je bezoekt.</translation>
<translation id="8943282376843390568">Limoengroen</translation>
<translation id="8957210676456822347">Autorisatie van captive portal</translation>
<translation id="8968766641738584599">Kaart opslaan</translation>
diff --git a/chromium/components/strings/components_strings_no.xtb b/chromium/components/strings/components_strings_no.xtb
index bae2010e29f..31762b8bc53 100644
--- a/chromium/components/strings/components_strings_no.xtb
+++ b/chromium/components/strings/components_strings_no.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Sider på <ph name="LANGUAGE" /> oversettes ikke.</translation>
<translation id="2053553514270667976">Postnummer</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 forslag}other{# forslag}}</translation>
+<translation id="2068124040035837596">Kontoen din administreres av <ph name="ENROLLMENT_DOMAIN" />. Det betyr at administratoren kan konfigurere kontoen din eksternt.</translation>
<translation id="2068663545051464999">ID-en for den opplastede programstopprapporten <ph name="CRASH_ID" /> (lokal kontekst: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Angre</translation>
<translation id="20817612488360358">Innstillinger for systemmellomtjener er stilt inn på å brukes, men en uttrykkelig mellomtjenerkonfigurasjon er også angitt.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Denne leveringsmetoden er ikke tilgjengelig. Prøv en annen metode.</translation>
<translation id="2396249848217231973">&amp;Angre slettingen</translation>
<translation id="2413528052993050574">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Tjenerens sikkerhetssertifikat kan være trukket tilbake. Dette kan være forårsaket av en feilkonfigurering eller en angriper som avskjærer tilkoblingen din.</translation>
+<translation id="244665789865330679">Enheten og kontoen din administreres av <ph name="ENROLLMENT_DOMAIN" />. Det betyr at administratoren kan konfigurere enheten og kontoen din eksternt.</translation>
<translation id="2463193859425327265">Endre startsiden</translation>
<translation id="2463739503403862330">Fyll ut</translation>
<translation id="2465655957518002998">Velg leveringsmåte</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Du forsøkte å gå til <ph name="DOMAIN" />, men sertifikatet tjeneren presenterte har blitt trukket tilbake av utstederen. Dette innebærer at sikkerhetsinformasjonen tjeneren presenterte ikke er klarert. Det kan hende at du kommuniserer med en angriper.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">søkeresultater</translation>
+<translation id="4406972042435603828">Administratorene dine har installert utvidelser med kraftig funksjonalitet.</translation>
<translation id="4408413947728134509">Informasjonskapsler <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Henteadresse</translation>
<translation id="4424024547088906515">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Sikkerhetssertifikatet til tjeneren er ikke klarert av Chrome. Dette kan være forårsaket av en feilkonfigurering eller en angriper som avskjærer tilkoblingen din.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Ingen resultater</translation>
<translation id="4950898438188848926">Knappen for å bytte fane – trykk på Enter for å bytte til den åpne fanen, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Handlinger</translation>
+<translation id="495832697253704892">Rapportering for utvidelser</translation>
<translation id="4958444002117714549">Utvid liste</translation>
<translation id="4974590756084640048">Slå på advarsler på nytt</translation>
<translation id="4989163558385430922">Se alle</translation>
<translation id="4989809363548539747">Dette programtillegget støttes ikke</translation>
+<translation id="4996230189582812866">Rapportering</translation>
<translation id="5002932099480077015">Hvis du slår på dette alternativet, lagrer Chrome en kopi av kortet ditt på denne enheten, slik at det blir raskere å fylle ut skjemaer i fremtiden.</translation>
<translation id="5014174725590676422">Skjermen for første kjøring av Google-assistenten i Chrome vises</translation>
<translation id="5015510746216210676">Maskinnavn:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Fylke/delstat</translation>
<translation id="5094747076828555589">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Sikkerhetssertifikatet til tjeneren er ikke klarert av Chromium. Dette kan være forårsaket av en feilkonfigurering eller en angriper som avskjærer tilkoblingen din.</translation>
<translation id="5095208057601539847">Provins</translation>
+<translation id="5098222253617183465">Enheten administreres av <ph name="ENROLLMENT_DOMAIN" />, og kontoen din administreres av <ph name="ACCOUNT_DOMAIN" />. Det betyr at administratorene kan konfigurere enheten og kontoen din eksternt.</translation>
<translation id="5115563688576182185">(64-bit)</translation>
<translation id="5128122789703661928">Økten med dette navnet er ikke gyldig for sletting.</translation>
<translation id="5135404736266831032">Adminstrer adresser…</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Datamaskin</translation>
<translation id="5179510805599951267">Er ikke dette <ph name="ORIGINAL_LANGUAGE" />? Rapportér denne feilen</translation>
<translation id="5190835502935405962">Bokmerkerad</translation>
+<translation id="5200263511887412697">rapportere en liste over enhetsbrukere som har logget på i det siste</translation>
<translation id="5201306358585911203">På en innebygd side på denne siden står det</translation>
<translation id="5205222826937269299">Navn er obligatorisk</translation>
<translation id="5215116848420601511">Betalingsmåter og adresser som bruker Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Dette nettstedet er ikke tilgjengelig</translation>
<translation id="5869522115854928033">Lagrede passord</translation>
<translation id="5887400589839399685">Kortet er lagret</translation>
+<translation id="5893718151540690985">rapportere en liste over nettverksgrensesnitt (inkludert typer og maskinvareadresser)</translation>
<translation id="5893752035575986141">Kredittkort godtas.</translation>
<translation id="5901630391730855834">Gul</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synkronisert)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Endre kontaktinformasjonen</translation>
<translation id="5967867314010545767">Fjern fra loggen</translation>
<translation id="5975083100439434680">Zoom ut</translation>
+<translation id="5977489021191000276">Enheten administreres ikke av en administrator.</translation>
<translation id="5977976211062815271">På denne enheten</translation>
<translation id="598637245381783098">Kan ikke åpne betalingsappen</translation>
<translation id="5989320800837274978">Verken statiske proxytjenere eller en nettadresse med .pac-skript er angitt.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Angripere på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kan installere villedende apper som ser ut til å være noe annet, eller samle inn data som kan brukes til å spore deg. <ph name="BEGIN_LEARN_MORE_LINK" />Finn ut mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" /> og <ph name="TYPE_3" /> (synkronisert)</translation>
<translation id="6027201098523975773">Skriv inn et navn</translation>
+<translation id="6033927989869462158">rapportere maskinvarestatistikk, som prosessor- og minnebruk</translation>
<translation id="6034000775414344507">Lysegrå</translation>
<translation id="6039846035001940113">Hvis problemet fortsetter, kan du kontakte nettstedseieren.</translation>
<translation id="6040143037577758943">Lukk</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Brukeragent</translation>
<translation id="6903319715792422884">Bidra til å gjøre Safe Browsing bedre ved å sende noe <ph name="BEGIN_WHITEPAPER_LINK" />systeminformasjon og sideinnhold<ph name="END_WHITEPAPER_LINK" /> til Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Bruker:</translation>
+<translation id="6934672428414710184">Dette navnet er fra Google-kontoen din</translation>
+<translation id="6939583532829045966">Enheten administreres av <ph name="ENROLLMENT_DOMAIN" />. Det betyr at administratoren kan konfigurere enheten eksternt.</translation>
<translation id="6944692733090228304">Du har skrevet inn passordet ditt på et nettsted som ikke administreres av <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. For å beskytte kontoen din må du ikke bruke det samme passordet i andre apper eller på andre nettsteder.</translation>
<translation id="6945221475159498467">Velg</translation>
<translation id="6948701128805548767">For å se hentemetoder og -krav, velg en adresse</translation>
@@ -991,6 +1003,7 @@
&lt;li&gt;Klikk på &lt;strong&gt;Bruk&lt;/strong&gt; og deretter på &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;Gå til &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;brukerstøtten for Chrome&lt;/a&gt; for å finne ut hvordan du fjerner programvaren fra datamaskinen permanent.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" />-administrering</translation>
<translation id="7416351320495623771">Administrer passord…</translation>
<translation id="7419106976560586862">Profilbane</translation>
<translation id="7437289804838430631">Legg til kontaktinformasjon</translation>
@@ -999,10 +1012,12 @@
<translation id="7442725080345379071">Lys oransje</translation>
<translation id="7444046173054089907">Dette nettstedet er blokkert</translation>
<translation id="7445762425076701745">Identiteten til tjernen du er tilkoblet kan ikke valideres. Du er tilkoblet en tjener som bruker et navn som kun er gyldig i ditt nettverk, som en ekstern sertifiseringsinstans ikke har noen mulighet til å validere eierskap for. Siden enkelte sertifiseringsinstanser likevel utsteder sertifikater for disse navnene, er det umulig å sikre at du er tilkoblet ønsket nettsted og ikke en angriper.</translation>
+<translation id="7449109375006139765">sende systemlogger til administrasjonstjeneren</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Finn ut mer<ph name="END_LINK" /> om dette problemet.</translation>
<translation id="7455133967321480974">Bruk global standardinnstilling (Blokkér)</translation>
<translation id="7460618730930299168">Fremvisningen er forskjellig fra den du har valgt. Vil du fortsette?</translation>
<translation id="7473891865547856676">Nei takk</translation>
+<translation id="7475525192983021547">rapportere tidsperioder med brukeraktivitet på enheten</translation>
<translation id="7481312909269577407">Frem</translation>
<translation id="7485870689360869515">Ingen data ble funnet.</translation>
<translation id="7508255263130623398">Den returnerte enhets-ID-en for regelen er tom eller samsvarer ikke med den faktiske enhets-ID-en</translation>
@@ -1095,6 +1110,7 @@
<translation id="7995512525968007366">Ikke spesifisert</translation>
<translation id="800218591365569300">Prøv å lukke andre faner eller programmer for å frigjøre minne.</translation>
<translation id="8009225694047762179">Administrer passord</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Dette kortet og den tilknyttede faktureringsadressen lagres. Du kan bruke det når du er logget på <ph name="USER_EMAIL" />.}other{Disse kortene og de tilknyttede faktureringsadressene lagres. Du kan bruke dem når du er logget på <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Vi kunne ikke nå foreldrene dine akkurat nå. Prøv igjen.</translation>
<translation id="8025119109950072390">Angripere på dette nettstedet prøver kanskje å lure deg til å gjøre farlige ting som å installere programvare eller avsløre personopplysningene dine (for eksempel passord, telefonnumre eller kredittkortinformasjon).</translation>
<translation id="8034522405403831421">Denne siden er på <ph name="SOURCE_LANGUAGE" />. Vil du oversette den til <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1105,6 +1121,7 @@
<translation id="8041940743680923270">Bruk global standardinnstilling (Spør)</translation>
<translation id="8042918947222776840">Velg hentemåte</translation>
<translation id="8057711352706143257">«<ph name="SOFTWARE_NAME" />» er ikke riktig konfigurert. Avinstallering av «<ph name="SOFTWARE_NAME" />» løser vanligvis problemet. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Enheten din er konfigurert til å</translation>
<translation id="8078141288243656252">Kan ikke legge til annoteringer når dokumentet er rotert</translation>
<translation id="8079031581361219619">Vil du laste inn nettstedet på nytt?</translation>
<translation id="8088680233425245692">Kunne ikke åpne artikkelen.</translation>
@@ -1155,6 +1172,7 @@
<translation id="8363502534493474904">Slå av flymodus</translation>
<translation id="8364627913115013041">Ikke angitt.</translation>
<translation id="8368476060205742148">Google Play Tjenester</translation>
+<translation id="8371889962595521444">Tilpassede rotsertifikater</translation>
<translation id="8380941800586852976">Farlig</translation>
<translation id="8381674639488873545">Disse belastningene kan skje én gang eller være gjentakende, og det er ikke sikkert de er åpenbare. <ph name="BEGIN_LINK" />Vis likevel<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Bokmerkene du nylig har besøkt, vises her</translation>
@@ -1164,6 +1182,7 @@
<translation id="8416694386774425977">Nettverkskonfigurasjonen er ugyldig og kan ikke importeres.
Mer informasjon:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Enheten administreres av <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Endre</translation>
<translation id="8428213095426709021">Innstillinger</translation>
@@ -1224,6 +1243,7 @@ Mer informasjon:
<translation id="8932102934695377596">Klokken går for sent</translation>
<translation id="893332455753468063">Legg til navn</translation>
<translation id="8938939909778640821">Godkjente kredittkort og forhåndsbetalte kort</translation>
+<translation id="894185898663964645">Administratoren din har konfigurert tilpassede rotsertifikater, noe som betyr at vedkommende kanskje kan se innholdet på nettsteder du besøker.</translation>
<translation id="8943282376843390568">Limegrønn</translation>
<translation id="8957210676456822347">Captive Portal-autorisasjon</translation>
<translation id="8968766641738584599">Lagre kortet</translation>
diff --git a/chromium/components/strings/components_strings_pl.xtb b/chromium/components/strings/components_strings_pl.xtb
index 52fbde1c833..86ca4a382e5 100644
--- a/chromium/components/strings/components_strings_pl.xtb
+++ b/chromium/components/strings/components_strings_pl.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Strony w tym języku (<ph name="LANGUAGE" />) nie będą tłumaczone.</translation>
<translation id="2053553514270667976">Kod pocztowy</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 podpowiedź}few{# podpowiedzi}many{# podpowiedzi}other{# podpowiedzi}}</translation>
+<translation id="2068124040035837596">Twoim kontem zarządza <ph name="ENROLLMENT_DOMAIN" />. Oznacza to, że administrator może zdalnie konfigurować Twoje konto.</translation>
<translation id="2068663545051464999">Przesłano raport o awarii – identyfikator: <ph name="CRASH_ID" /> (kontekst lokalny: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Cofnij</translation>
<translation id="20817612488360358">Skonfigurowano używanie systemowych ustawień proxy, ale podano też jawną konfigurację proxy.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Ta metoda wysyłki jest niedostępna. Wybierz inną.</translation>
<translation id="2396249848217231973">&amp;Cofnij usunięcie</translation>
<translation id="2413528052993050574">Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa mógł zostać odwołany. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
+<translation id="244665789865330679">Twoim urządzeniem i kontem zarządza <ph name="ENROLLMENT_DOMAIN" />. Oznacza to, że administrator może zdalnie konfigurować Twoje urządzenie i konto.</translation>
<translation id="2463193859425327265">Zmień stronę główną</translation>
<translation id="2463739503403862330">Wpisz</translation>
<translation id="2465655957518002998">Wybierz metodę dostawy</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Próbujesz wejść na <ph name="DOMAIN" />, ale serwer przedstawił certyfikat unieważniony przez wystawcę. Oznacza to, że dane uwierzytelniające podane przez serwer są zupełnie niewiarygodne. Możliwe, że komunikujesz się z intruzem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">wyniki wyszukiwania</translation>
+<translation id="4406972042435603828">Administratorzy zainstalowali rozszerzenia o dużych możliwościach.</translation>
<translation id="4408413947728134509">Pliki cookie (<ph name="NUM_COOKIES" />)</translation>
<translation id="4415426530740016218">Adres odbioru</translation>
<translation id="4424024547088906515">Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa nie jest zaufany w Chrome. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Brak wyników</translation>
<translation id="4950898438188848926">Przycisk przełączania kart. Naciśnij Enter, by przełączyć się na otwartą kartę, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Czynności</translation>
+<translation id="495832697253704892">Zgłaszanie rozszerzenia</translation>
<translation id="4958444002117714549">Rozwiń listę</translation>
<translation id="4974590756084640048">Ponownie włącz ostrzeżenia</translation>
<translation id="4989163558385430922">Pokaż wszystko</translation>
<translation id="4989809363548539747">Ta wtyczka nie jest obsługiwana</translation>
+<translation id="4996230189582812866">Raportowanie</translation>
<translation id="5002932099480077015">Jeśli włączysz tę opcję, Chrome zapisze kopię Twojej karty na tym urządzeniu, by umożliwić Ci szybsze wypełnianie formularzy.</translation>
<translation id="5014174725590676422">Wyświetlany jest ekran pierwszego uruchomienia Asystenta Google w Chrome</translation>
<translation id="5015510746216210676">Nazwa komputera:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Stan</translation>
<translation id="5094747076828555589">Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa nie jest zaufany w Chromium. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
<translation id="5095208057601539847">Prowincja</translation>
+<translation id="5098222253617183465">Twoim urządzeniem zarządza <ph name="ENROLLMENT_DOMAIN" />, a Twoim kontem – <ph name="ACCOUNT_DOMAIN" />. Oznacza to, że administrator może zdalnie konfigurować Twoje urządzenie i konto.</translation>
<translation id="5115563688576182185">(64-bitowa)</translation>
<translation id="5128122789703661928">Nie możesz usunąć tej sesji, bo jej nazwa jest nieprawidłowa.</translation>
<translation id="5135404736266831032">Zarządzaj adresami…</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Komputer</translation>
<translation id="5179510805599951267">Jeśli to nie jest język <ph name="ORIGINAL_LANGUAGE" />, zgłoś błąd</translation>
<translation id="5190835502935405962">Pasek zakładek</translation>
+<translation id="5200263511887412697">generować raporty z listą użytkowników urządzenia, którzy niedawno się zalogowali.</translation>
<translation id="5201306358585911203">Komunikat z elementu umieszczonego na bieżącej stronie</translation>
<translation id="5205222826937269299">Nazwa jest wymagana</translation>
<translation id="5215116848420601511">Formy płatności i adresy z Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Ta witryna jest nieosiągalna</translation>
<translation id="5869522115854928033">Zapisane hasła</translation>
<translation id="5887400589839399685">Zapisano kartę</translation>
+<translation id="5893718151540690985">generować raporty z listą interfejsów sieciowych wraz z ich typami i adresami sprzętowymi</translation>
<translation id="5893752035575986141">Karty kredytowe są akceptowane.</translation>
<translation id="5901630391730855834">Żółty</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (zsynchronizowane)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Edytuj dane kontaktowe</translation>
<translation id="5967867314010545767">Usuń z historii</translation>
<translation id="5975083100439434680">Pomniejsz</translation>
+<translation id="5977489021191000276">Twoim urządzeniem nie zarządza administrator.</translation>
<translation id="5977976211062815271">Na tym urządzeniu</translation>
<translation id="598637245381783098">Nie można otworzyć aplikacji do płatności</translation>
<translation id="5989320800837274978">Nie określono ani stałych serwerów proxy, ani adresu URL skryptu PAC.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Osoby atakujące stronę <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogą instalować wprowadzające w błąd aplikacje, które udają, że są przeznaczone do czegoś innego niż w rzeczywistości, lub zbierają dane, na podstawie których można Cię śledzić. <ph name="BEGIN_LEARN_MORE_LINK" />Więcej informacji<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (zsynchronizowane)</translation>
<translation id="6027201098523975773">Wpisz imię i nazwisko</translation>
+<translation id="6033927989869462158">generować raporty ze statystykami na temat sprzętu, np. użyciem procesora czy pamięci RAM.</translation>
<translation id="6034000775414344507">Jasnoszary</translation>
<translation id="6039846035001940113">Jeśli problem nie ustąpi, skontaktuj się z właścicielem strony.</translation>
<translation id="6040143037577758943">Zamknij</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Klient</translation>
<translation id="6903319715792422884">Pomóż w ulepszaniu Bezpiecznego przeglądania, wysyłając do Google pewne <ph name="BEGIN_WHITEPAPER_LINK" />informacje o systemie i część zawartości stron<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Użytkownik:</translation>
+<translation id="6934672428414710184">To imię i nazwisko pochodzi z Twojego konta Google</translation>
+<translation id="6939583532829045966">Twoim urządzeniem zarządza <ph name="ENROLLMENT_DOMAIN" />. Oznacza to, że administrator może zdalnie konfigurować Twoje urządzenie.</translation>
<translation id="6944692733090228304">Wpisałeś swoje hasło na stronie, którą nie zarządza <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Aby chronić konto, nie używaj swojego hasła w innych aplikacjach ani witrynach.</translation>
<translation id="6945221475159498467">Wybierz</translation>
<translation id="6948701128805548767">Aby zobaczyć metody odbioru oraz wymagania, wybierz adres</translation>
@@ -992,6 +1004,7 @@ Dodatkowe informacje:
&lt;li&gt;Kliknij &lt;strong&gt;Zastosuj&lt;/strong&gt;, a potem kliknij &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;W &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centrum pomocy Chrome&lt;/a&gt; dowiesz się, jak trwale usunąć to oprogramowanie z komputera.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> – zarządzanie</translation>
<translation id="7416351320495623771">Zarządzaj hasłami…</translation>
<translation id="7419106976560586862">Ścieżka profilu</translation>
<translation id="7437289804838430631">Dodaj dane kontaktowe</translation>
@@ -1000,10 +1013,12 @@ Dodatkowe informacje:
<translation id="7442725080345379071">Jasnopomarańczowy</translation>
<translation id="7444046173054089907">Ta strona jest zablokowana</translation>
<translation id="7445762425076701745">Nie można w pełni zweryfikować tożsamości serwera, z którym nawiązano połączenie. Nawiązano połączenie z serwerem przy użyciu nazwy obowiązującej jedynie w Twojej sieci i której własności zewnętrzny urząd certyfikacji nie jest w stanie zweryfikować. Niektóre urzędy certyfikacji wydają certyfikaty dla takich nazw bez względu na to, że nie można upewnić się, iż nawiązano połączenie z witryną, z którą zamierzano, a nie z intruzem.</translation>
+<translation id="7449109375006139765">wysyłać dzienniki systemowe na serwer zarządzania</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Dowiedz się więcej<ph name="END_LINK" /> o tym problemie.</translation>
<translation id="7455133967321480974">Użyj globalnej wartości domyślnej (Blokuj)</translation>
<translation id="7460618730930299168">Godziny seansów są inne niż wybrane przez Ciebie. Czy chcesz kontynuować?</translation>
<translation id="7473891865547856676">Nie, dziękuję</translation>
+<translation id="7475525192983021547">generować raporty z okresami aktywności użytkownika na urządzeniu</translation>
<translation id="7481312909269577407">Dalej</translation>
<translation id="7485870689360869515">Nie znaleziono danych.</translation>
<translation id="7508255263130623398">Zwrócony identyfikator urządzenia dla zasad jest pusty lub nie pasuje do bieżącego identyfikatora urządzenia</translation>
@@ -1096,6 +1111,7 @@ Dodatkowe informacje:
<translation id="7995512525968007366">Nie określono</translation>
<translation id="800218591365569300">Zamknij inne karty lub programy, by zwolnić pamięć.</translation>
<translation id="8009225694047762179">Zarządzaj hasłami</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Ta karta i jej adres rozliczeniowy zostaną zapisane. Możesz ich używać po zalogowaniu się na konto <ph name="USER_EMAIL" />.}few{Te karty i ich adresy rozliczeniowe zostaną zapisane. Możesz ich używać po zalogowaniu się na konto <ph name="USER_EMAIL" />.}many{Te karty i ich adresy rozliczeniowe zostaną zapisane. Możesz ich używać po zalogowaniu się na konto <ph name="USER_EMAIL" />.}other{Te karty i ich adresy rozliczeniowe zostaną zapisane. Możesz ich używać po zalogowaniu się na konto <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Obecnie nie możemy się skontaktować z Twoimi rodzicami. Spróbuj ponownie.</translation>
<translation id="8025119109950072390">Osoby atakujące tę stronę mogą podstępem nakłonić Cię do zrobienia czegoś niebezpiecznego, np. zainstalowania oprogramowania lub ujawnienia danych osobowych (takich jak hasła, numery telefonów czy dane kart kredytowych).</translation>
<translation id="8034522405403831421">Język tej strony to <ph name="SOURCE_LANGUAGE" />. Przetłumaczyć ją na <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Dodatkowe informacje:
<translation id="8041940743680923270">Użyj globalnej wartości domyślnej (Pytaj)</translation>
<translation id="8042918947222776840">Wybierz metodę odbioru</translation>
<translation id="8057711352706143257">Oprogramowanie „<ph name="SOFTWARE_NAME" />” nie jest prawidłowo skonfigurowane. Odinstalowanie oprogramowania „<ph name="SOFTWARE_NAME" />” zwykle rozwiązuje problem. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Twoje urządzenie zostało skonfigurowane tak, by:</translation>
<translation id="8078141288243656252">Nie można dodawać adnotacji, gdy dokument jest obrócony</translation>
<translation id="8079031581361219619">Załadować ponownie stronę?</translation>
<translation id="8088680233425245692">Nie udało się wyświetlić artykułu.</translation>
@@ -1156,6 +1173,7 @@ Dodatkowe informacje:
<translation id="8363502534493474904">Wyłącz tryb samolotowy</translation>
<translation id="8364627913115013041">Nie ustawiono.</translation>
<translation id="8368476060205742148">Usługi Google Play</translation>
+<translation id="8371889962595521444">Niestandardowy certyfikat główny</translation>
<translation id="8380941800586852976">Niebezpieczna</translation>
<translation id="8381674639488873545">Może to być opłata jednorazowa lub cykliczna, a informacje o niej mogą nie być wyraźnie podane. <ph name="BEGIN_LINK" />Pokaż mimo to<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Tutaj wyświetlają się ostatnio otwierane zakładki</translation>
@@ -1165,6 +1183,7 @@ Dodatkowe informacje:
<translation id="8416694386774425977">Konfiguracja sieci jest nieprawidłowa i nie można jej zaimportować.
Dodatkowe informacje:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Urządzeniem zarządza <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Zmień</translation>
<translation id="8428213095426709021">Ustawienia</translation>
@@ -1225,6 +1244,7 @@ Dodatkowe informacje:
<translation id="8932102934695377596">Twój zegar się spóźnia</translation>
<translation id="893332455753468063">Dodaj imię i nazwisko lub nazwę firmy</translation>
<translation id="8938939909778640821">Akceptowane karty kredytowe i przedpłacone</translation>
+<translation id="894185898663964645">Administrator skonfigurował niestandardowe certyfikaty główne, które mogą umożliwiać mu wgląd w treści stron, które otwierasz.</translation>
<translation id="8943282376843390568">Limonkowy</translation>
<translation id="8957210676456822347">Autoryzacja portalu przechwytującego</translation>
<translation id="8968766641738584599">Zapisz kartę</translation>
diff --git a/chromium/components/strings/components_strings_pt-BR.xtb b/chromium/components/strings/components_strings_pt-BR.xtb
index 4bd2dce2556..f3d847ecf30 100644
--- a/chromium/components/strings/components_strings_pt-BR.xtb
+++ b/chromium/components/strings/components_strings_pt-BR.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Páginas em <ph name="LANGUAGE" /> não serão traduzidas.</translation>
<translation id="2053553514270667976">CEP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestão}one{# sugestão}other{# sugestões}}</translation>
+<translation id="2068124040035837596">Sua conta é gerenciada por <ph name="ENROLLMENT_DOMAIN" />. Isso significa que seu administrador pode configurá-la remotamente.</translation>
<translation id="2068663545051464999">Upload do relatório de erros <ph name="CRASH_ID" /> concluído (Contexto local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Desfazer</translation>
<translation id="20817612488360358">As configurações de proxy do sistema são definidas para serem utilizadas, mas uma configuração explícita de proxy também foi especificada.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Esse método de envio não está disponível. Tente um método diferente.</translation>
<translation id="2396249848217231973">&amp;Desfazer exclusão</translation>
<translation id="2413528052993050574">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança pode ter sido revogado. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
+<translation id="244665789865330679">Seu dispositivo e sua conta são gerenciados por <ph name="ENROLLMENT_DOMAIN" />. Isso significa que seu administrador pode configurá-los remotamente.</translation>
<translation id="2463193859425327265">Alterar a página inicial</translation>
<translation id="2463739503403862330">Preencher</translation>
<translation id="2465655957518002998">Escolher método de entrega</translation>
@@ -501,7 +503,7 @@
<translation id="4098354747657067197">Site enganoso à frente</translation>
<translation id="4103249731201008433">O número de série do dispositivo é inválido</translation>
<translation id="410351446219883937">Reprodução automática</translation>
-<translation id="4103763322291513355">Visite &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver a lista de URLs adicionados à lista negra e outras políticas aplicadas pelo administrador do seu sistema.</translation>
+<translation id="4103763322291513355">Visite &lt;strong&gt;chrome://policy&lt;/strong&gt; para ver a lista de URLs adicionados à lista de proibições e outras políticas aplicadas pelo administrador do seu sistema.</translation>
<translation id="4110652170750985508">Analisar seu pagamento</translation>
<translation id="4116663294526079822">Sempre permitir neste site</translation>
<translation id="4117700440116928470">O escopo da política não é suportado.</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Você tentou acessar <ph name="DOMAIN" />, mas o certificado que o servidor apresentou foi revogado pelo seu emissor. Isso significa que as credenciais de segurança que o servidor apresentou não são nem um pouco seguras. Talvez você esteja se comunicando com um invasor.</translation>
<translation id="4378154925671717803">Telefone</translation>
<translation id="4406896451731180161">resultados da pesquisa</translation>
+<translation id="4406972042435603828">Seus administradores instalaram extensões com recursos avançados.</translation>
<translation id="4408413947728134509">Cookies: <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Endereço de Retirada</translation>
<translation id="4424024547088906515">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança não é confiável para o Chrome. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Nenhum resultado</translation>
<translation id="4950898438188848926">Botão de alternância de guia. Pressione Enter para alternar para a guia aberta, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Ações</translation>
+<translation id="495832697253704892">Relatório de extensões</translation>
<translation id="4958444002117714549">Expandir lista</translation>
<translation id="4974590756084640048">Reativar avisos</translation>
<translation id="4989163558385430922">Ver tudo</translation>
<translation id="4989809363548539747">Este plug-in não é compatível</translation>
+<translation id="4996230189582812866">Relatórios</translation>
<translation id="5002932099480077015">Se ativado, o Chrome armazenará uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="5014174725590676422">Exibição da tela de primeiro acesso do Google Assistente no Chrome</translation>
<translation id="5015510746216210676">Nome do computador:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Estado</translation>
<translation id="5094747076828555589">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança não é confiável para o Chromium. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
<translation id="5095208057601539847">Província</translation>
+<translation id="5098222253617183465">Seu dispositivo é gerenciado por <ph name="ENROLLMENT_DOMAIN" />, e sua conta é gerenciada por <ph name="ACCOUNT_DOMAIN" />. Isso significa que seus administradores podem configurá-los remotamente.</translation>
<translation id="5115563688576182185">64 bits</translation>
<translation id="5128122789703661928">A sessão com este nome não é válida para exclusão.</translation>
<translation id="5135404736266831032">Gerenciar endereços…</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Máquina</translation>
<translation id="5179510805599951267">Não está em <ph name="ORIGINAL_LANGUAGE" />? Informe este erro</translation>
<translation id="5190835502935405962">Barra de favoritos</translation>
+<translation id="5200263511887412697">informar a lista de usuários do dispositivo que fizeram login recentemente</translation>
<translation id="5201306358585911203">Uma página incorporada nesta página diz</translation>
<translation id="5205222826937269299">Nome obrigatório</translation>
<translation id="5215116848420601511">Formas de pagamento e endereços que usam o Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Não é possível acessar esse site</translation>
<translation id="5869522115854928033">Senhas salvas</translation>
<translation id="5887400589839399685">Cartão salvo</translation>
+<translation id="5893718151540690985">informar uma lista de interfaces de rede com os tipos e endereços de hardware delas</translation>
<translation id="5893752035575986141">Cartões de crédito são aceitos.</translation>
<translation id="5901630391730855834">Amarelo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizado)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Edite as Informações de Contato</translation>
<translation id="5967867314010545767">Remover do histórico</translation>
<translation id="5975083100439434680">Diminuir zoom</translation>
+<translation id="5977489021191000276">Seu dispositivo não é gerenciado por um administrador.</translation>
<translation id="5977976211062815271">Neste dispositivo</translation>
<translation id="598637245381783098">Não foi possível abrir app de pagamento</translation>
<translation id="5989320800837274978">Nem os servidores proxy fixos nem o URL de script .pac foram especificados.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Invasores em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem instalar apps enganosos que fingem ser outra pessoa ou coletam dados que podem ser usados para rastrear você. <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sincronizados)</translation>
<translation id="6027201098523975773">Insira um nome</translation>
+<translation id="6033927989869462158">informar estatísticas de hardware, como uso de CPU/RAM</translation>
<translation id="6034000775414344507">Cinza-claro</translation>
<translation id="6039846035001940113">Se o problema continuar, entre em contato com o proprietário do site.</translation>
<translation id="6040143037577758943">Fechar</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Agente do usuário</translation>
<translation id="6903319715792422884">Ajudar a melhorar o recurso "Navegação segura" enviando algumas <ph name="BEGIN_WHITEPAPER_LINK" />informações do sistema e conteúdo da página<ph name="END_WHITEPAPER_LINK" /> para o Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Usuário:</translation>
+<translation id="6934672428414710184">Este nome é da sua Conta do Google</translation>
+<translation id="6939583532829045966">Seu dispositivo é gerenciado por <ph name="ENROLLMENT_DOMAIN" />. Isso significa que seu administrador pode configurá-lo remotamente.</translation>
<translation id="6944692733090228304">Você inseriu sua senha em um site que não é gerenciado por <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Para proteger sua conta, não reutilize sua senha em outros apps e sites.</translation>
<translation id="6945221475159498467">Selecionar</translation>
<translation id="6948701128805548767">Para ver métodos e requisitos de retirada, selecione um endereço</translation>
@@ -992,6 +1004,7 @@ Mais detalhes:
&lt;li&gt;Clique em &lt;strong&gt;Aplicar&lt;/strong&gt; e depois em &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Visite a &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Central de Ajuda do Chrome&lt;/a&gt; para saber como remover permanentemente o software do seu computador
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Gerenciamento do <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Gerenciar senhas…</translation>
<translation id="7419106976560586862">Caminho de perfil</translation>
<translation id="7437289804838430631">Adicionar Informações de Contato</translation>
@@ -1000,10 +1013,12 @@ Mais detalhes:
<translation id="7442725080345379071">Laranja-claro</translation>
<translation id="7444046173054089907">Este site está bloqueado</translation>
<translation id="7445762425076701745">A identidade do servidor ao qual você está conectado não pode ser validada completamente. Você está conectado ao servidor com um nome válido somente na sua rede e que, portanto, uma autoridade de certificação externa não consegue validar a propriedade. Como algumas autoridades de certificação emitem certificados para esses nomes mesmo assim, não é possível garantir que você esteja conectado ao site que gostaria e não a um invasor.</translation>
+<translation id="7449109375006139765">enviar registros do sistema para o servidor de gerenciamento</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Saber mais<ph name="END_LINK" /> sobre esse problema.</translation>
<translation id="7455133967321480974">Usar padrão global (Bloquear)</translation>
<translation id="7460618730930299168">A exibição na tela está diferente da que você selecionou. Continuar?</translation>
<translation id="7473891865547856676">Não, obrigado</translation>
+<translation id="7475525192983021547">informar os períodos de atividade do usuário no dispositivo</translation>
<translation id="7481312909269577407">Avançar</translation>
<translation id="7485870689360869515">Nenhum dado encontrado</translation>
<translation id="7508255263130623398">O código do dispositivo da política retornado está em branco ou não corresponde ao código do dispositivo atual</translation>
@@ -1096,6 +1111,7 @@ Mais detalhes:
<translation id="7995512525968007366">Não especificado</translation>
<translation id="800218591365569300">Tente fechar outras guias ou programas para liberar memória.</translation>
<translation id="8009225694047762179">Gerenciar senha</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Este cartão e o endereço de faturamento dele serão salvos. Você poderá usá-lo quando a conta <ph name="USER_EMAIL" /> estiver conectada.}one{Este cartão e o endereço de faturamento dele serão salvos. Você poderá usá-lo quando a conta <ph name="USER_EMAIL" /> estiver conectada.}other{Estes cartões e os endereços de faturamento deles serão salvos. Você poderá usá-los quando a conta <ph name="USER_EMAIL" /> estiver conectada.}}</translation>
<translation id="8012647001091218357">Não foi possível contatar seus pais. Tente novamente.</translation>
<translation id="8025119109950072390">Invasores nesse site podem induzir você a fazer algo perigoso, como instalar um software ou revelar suas informações pessoais (por exemplo, senhas, números de telefone ou cartões de crédito).</translation>
<translation id="8034522405403831421">Esta página está escrita em <ph name="SOURCE_LANGUAGE" />. Traduzi-la para <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Mais detalhes:
<translation id="8041940743680923270">Usar padrão global (Perguntar)</translation>
<translation id="8042918947222776840">Escolher método de retirada</translation>
<translation id="8057711352706143257">O software "<ph name="SOFTWARE_NAME" />" não foi configurado corretamente. A desinstalação do "<ph name="SOFTWARE_NAME" />" costuma resolver o problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Seu dispositivo foi configurado para:</translation>
<translation id="8078141288243656252">Não é possível fazer anotações em documentos girados</translation>
<translation id="8079031581361219619">Atualizar o site?</translation>
<translation id="8088680233425245692">Falha ao exibir artigo.</translation>
@@ -1156,6 +1173,7 @@ Mais detalhes:
<translation id="8363502534493474904">Desativar modo avião</translation>
<translation id="8364627913115013041">Não definida.</translation>
<translation id="8368476060205742148">Serviços do Google Play</translation>
+<translation id="8371889962595521444">Personalizar certificados raiz</translation>
<translation id="8380941800586852976">Perigoso</translation>
<translation id="8381674639488873545">Essas cobranças podem ser únicas ou recorrentes e talvez não sejam óbvias. <ph name="BEGIN_LINK" />Mostrar mesmo assim<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Os favoritos visitados recentemente aparecerão aqui</translation>
@@ -1165,6 +1183,7 @@ Mais detalhes:
<translation id="8416694386774425977">A configuração de rede é inválida e não pôde ser importada.
Mais detalhes:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Dispositivo gerenciado por <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Alterar</translation>
<translation id="8428213095426709021">Configurações</translation>
@@ -1226,6 +1245,7 @@ Mais detalhes:
<translation id="8932102934695377596">Seu relógio está atrasado</translation>
<translation id="893332455753468063">Adicione um Nome</translation>
<translation id="8938939909778640821">Cartões de crédito e pré-pagos aceitos</translation>
+<translation id="894185898663964645">Seu administrador configurou certificados raiz personalizados, o que pode permitir que ele veja o conteúdo dos sites que você visita.</translation>
<translation id="8943282376843390568">Verde-limão</translation>
<translation id="8957210676456822347">Autorização de portal cativo</translation>
<translation id="8968766641738584599">Salvar cartão</translation>
diff --git a/chromium/components/strings/components_strings_pt-PT.xtb b/chromium/components/strings/components_strings_pt-PT.xtb
index 70b20112e72..98c58d64566 100644
--- a/chromium/components/strings/components_strings_pt-PT.xtb
+++ b/chromium/components/strings/components_strings_pt-PT.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">As páginas em <ph name="LANGUAGE" /> não serão traduzidas.</translation>
<translation id="2053553514270667976">Código postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestão}other{# sugestões}}</translation>
+<translation id="2068124040035837596">A sua conta é gerida por <ph name="ENROLLMENT_DOMAIN" />. Isto significa que o seu administrador pode configurar remotamente a sua conta.</translation>
<translation id="2068663545051464999">ID do relatório de falhas carregado <ph name="CRASH_ID" /> (contexto local: <ph name="CRASH_LOCAL_ID" />).</translation>
<translation id="2079545284768500474">Anular</translation>
<translation id="20817612488360358">As definições de proxy do sistema estão definidas para serem utilizadas, mas também está especificada uma configuração de proxy explícita.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Este método de envio não está disponível. Experimente um método diferente.</translation>
<translation id="2396249848217231973">&amp;Anular eliminação</translation>
<translation id="2413528052993050574">Este servidor não conseguiu provar que é o domínio <ph name="DOMAIN" />; o respetivo certificado de segurança poderá ser revogado. Isto pode ser o resultado de uma configuração incorreta ou de um invasor a intercetar a sua ligação.</translation>
+<translation id="244665789865330679">O seu dispositivo e a sua conta são geridos por <ph name="ENROLLMENT_DOMAIN" />. Isto significa que o seu administrador pode configurar remotamente o seu dispositivo e a sua conta.</translation>
<translation id="2463193859425327265">Alterar página inicial</translation>
<translation id="2463739503403862330">Preencher</translation>
<translation id="2465655957518002998">Escolher método de fornecimento</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Tentou aceder a <ph name="DOMAIN" />, mas o certificado que o servidor apresentou foi revogado pelo emissor. Isto significa que as credenciais de segurança apresentadas pelo servidor não deverão, em circunstância alguma, ser consideradas fidedignas. Pode estar a comunicar com um utilizador mal intencionado.</translation>
<translation id="4378154925671717803">Telemóvel</translation>
<translation id="4406896451731180161">resultados da pesquisa</translation>
+<translation id="4406972042435603828">Os seus administradores instalaram extensões com capacidades poderosas.</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Endereço de recolha</translation>
<translation id="4424024547088906515">Este servidor não conseguiu provar que é o domínio <ph name="DOMAIN" />; o Chrome não confia no respetivo certificado de segurança. Isto pode ser o resultado de uma configuração incorreta ou de um invasor a intercetar a sua ligação.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Nenhum resultado</translation>
<translation id="4950898438188848926">Botão de mudança de separador: prima Enter para mudar para o separador aberto, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Ações</translation>
+<translation id="495832697253704892">Comunicação de extensões</translation>
<translation id="4958444002117714549">Expandir lista</translation>
<translation id="4974590756084640048">Reativar avisos</translation>
<translation id="4989163558385430922">Ver tudo</translation>
<translation id="4989809363548539747">Este plug-in não é compatível</translation>
+<translation id="4996230189582812866">Relatórios</translation>
<translation id="5002932099480077015">Quando esta opção está ativada, o Chrome armazena uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="5014174725590676422">É apresentado o primeiro ecrã de execução do Assistente Google no Chrome.</translation>
<translation id="5015510746216210676">Nome do computador:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Estado</translation>
<translation id="5094747076828555589">Este servidor não conseguiu provar que é o domínio <ph name="DOMAIN" />; o Chromium não confia no respetivo certificado de segurança. Isto pode ser o resultado de uma configuração incorreta ou de um invasor a intercetar a sua ligação.</translation>
<translation id="5095208057601539847">Província</translation>
+<translation id="5098222253617183465">O seu dispositivo é gerido por <ph name="ENROLLMENT_DOMAIN" /> e a sua conta é gerida por <ph name="ACCOUNT_DOMAIN" />. Isto significa que os seus administradores podem configurar remotamente o seu dispositivo e a sua conta.</translation>
<translation id="5115563688576182185">(64 bits)</translation>
<translation id="5128122789703661928">A sessão com este nome não é válida para eliminação.</translation>
<translation id="5135404736266831032">Gerir endereços…</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Equipamento</translation>
<translation id="5179510805599951267">Não está em <ph name="ORIGINAL_LANGUAGE" />? Comunicar este erro</translation>
<translation id="5190835502935405962">Barra de marcadores</translation>
+<translation id="5200263511887412697">comunicar lista de utilizadores do dispositivo que iniciaram sessão recentemente</translation>
<translation id="5201306358585911203">Uma página incorporada nesta página diz</translation>
<translation id="5205222826937269299">Nome obrigatório</translation>
<translation id="5215116848420601511">Métodos de pagamento e endereços com o Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Não é possível aceder a este site</translation>
<translation id="5869522115854928033">Palavras-passe guardadas</translation>
<translation id="5887400589839399685">Cartão guardado</translation>
+<translation id="5893718151540690985">comunicar a lista de interfaces de rede com os respetivos tipos e endereços de hardware</translation>
<translation id="5893752035575986141">Os cartões de crédito são admitidos.</translation>
<translation id="5901630391730855834">Amarelo</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizados)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Editar informações de contacto</translation>
<translation id="5967867314010545767">Remover do histórico</translation>
<translation id="5975083100439434680">Reduzir</translation>
+<translation id="5977489021191000276">O seu dispositivo não é gerido por um administrador.</translation>
<translation id="5977976211062815271">Neste dispositivo</translation>
<translation id="598637245381783098">Não é possível abrir a aplicação de pagamento</translation>
<translation id="5989320800837274978">Não foram especificados servidores proxy fixos nem um URL de script .pac.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Os utilizadores mal-intencionados em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem instalar aplicações fraudulentas que se fazem passar por algo diferente ou recolhem dados que podem ser utilizados para o monitorizar. <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sincronizados)</translation>
<translation id="6027201098523975773">Introduza um nome</translation>
+<translation id="6033927989869462158">comunicar estatísticas de hardware, como a utilização da CPU/RAM</translation>
<translation id="6034000775414344507">Cinzento-claro</translation>
<translation id="6039846035001940113">Se o problema persistir, contacte o proprietário do site.</translation>
<translation id="6040143037577758943">Fechar</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Agente do utilizador</translation>
<translation id="6903319715792422884">Ajude a melhorar a Navegação segura ao enviar algumas <ph name="BEGIN_WHITEPAPER_LINK" />informações do sistema e conteúdo de páginas<ph name="END_WHITEPAPER_LINK" /> para a Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Utilizador:</translation>
+<translation id="6934672428414710184">Este nome é proveniente da sua Conta Google.</translation>
+<translation id="6939583532829045966">A sua conta é gerida por <ph name="ENROLLMENT_DOMAIN" />. Isto significa que o seu administrador pode configurar remotamente o seu dispositivo.</translation>
<translation id="6944692733090228304">Introduziu a palavra-passe num site que não é gerido pela <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Para proteger a conta, não reutilize a sua palavra-passe noutras aplicações e sites.</translation>
<translation id="6945221475159498467">Selecionar</translation>
<translation id="6948701128805548767">Para ver os métodos de recolha e os requisitos, selecione um endereço</translation>
@@ -991,6 +1003,7 @@ Detalhes adicionais:
&lt;li&gt;Em &lt;strong&gt;Estado do serviço&lt;/strong&gt;, clique em &lt;strong&gt;Parar&lt;/strong&gt;.
&lt;li&gt;Clique em &lt;strong&gt;Aplicar&lt;/strong&gt; e, de seguida, em &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;Visite o &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centro de Ajuda do Chrome&lt;/a&gt; para saber como remover permanentemente o software do computador. &lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Gestão do <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Gerir palavras-passe…</translation>
<translation id="7419106976560586862">Caminho do Perfil</translation>
<translation id="7437289804838430631">Adicionar informações de contacto</translation>
@@ -999,10 +1012,12 @@ Detalhes adicionais:
<translation id="7442725080345379071">Laranja-claro</translation>
<translation id="7444046173054089907">Este site está bloqueado</translation>
<translation id="7445762425076701745">Não é possível validar totalmente a identidade do servidor ao qual está ligado. Está ligado a um servidor com um nome que apenas é válido na sua rede, que não permite que uma autoridade de certificação externa valide a respectiva propriedade. Ainda assim, algumas autoridades emitem certificados para esses nomes, pelo que não há forma de garantir que está ligado ao Website que pretende e não a um site pirata.</translation>
+<translation id="7449109375006139765">enviar registos do sistema para o servidor de gestão</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Saber mais<ph name="END_LINK" /> sobre este problema.</translation>
<translation id="7455133967321480974">Utilizar predefinição global (Bloquear)</translation>
<translation id="7460618730930299168">A apresentação é diferente daquilo que selecionou. Pretende continuar?</translation>
<translation id="7473891865547856676">Não, obrigado</translation>
+<translation id="7475525192983021547">comunicar períodos de tempo quando um utilizador está ativo no dispositivo</translation>
<translation id="7481312909269577407">Avançar</translation>
<translation id="7485870689360869515">Não foram encontrados dados.</translation>
<translation id="7508255263130623398">O ID do dispositivo da política devolvido está vazio ou não corresponde ao ID do dispositivo atual</translation>
@@ -1095,6 +1110,7 @@ Detalhes adicionais:
<translation id="7995512525968007366">Não especificado</translation>
<translation id="800218591365569300">Experimente fechar outros separadores ou programas para libertar memória.</translation>
<translation id="8009225694047762179">Gerir palavras-passe</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Este cartão e o respetivo endereço de faturação serão guardados. Pode utilizá-lo quando tiver sessão iniciada em <ph name="USER_EMAIL" />.}other{Estes cartões e os respetivos endereços de faturação serão guardados. Pode utilizá-los quando tiver sessão iniciada em <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Não conseguimos falar com os seus pais de momento. Tente novamente.</translation>
<translation id="8025119109950072390">Os utilizadores mal intencionados neste site podem enganá-lo no sentido de fazer algo perigoso como instalar software ou revelar as suas informações pessoais (por exemplo, palavras-passe, números de telefone ou cartões de crédito).</translation>
<translation id="8034522405403831421">Esta página está em <ph name="SOURCE_LANGUAGE" />. Pretende traduzi-la para <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1105,6 +1121,7 @@ Detalhes adicionais:
<translation id="8041940743680923270">Utilizar predefinição global (Perguntar)</translation>
<translation id="8042918947222776840">Escolher método de levantamento</translation>
<translation id="8057711352706143257">O "<ph name="SOFTWARE_NAME" />" não está configurado corretamente. Normalmente, a desinstalação do "<ph name="SOFTWARE_NAME" />" resolve o problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">O seu dispositivo foi configurado para:</translation>
<translation id="8078141288243656252">Não é possível criar anotação se tiver sido aplicada uma rotação ao documento</translation>
<translation id="8079031581361219619">Pretende atualizar o site?</translation>
<translation id="8088680233425245692">Falha ao ver o artigo.</translation>
@@ -1155,6 +1172,7 @@ Detalhes adicionais:
<translation id="8363502534493474904">Desativar o modo de avião</translation>
<translation id="8364627913115013041">Não definida.</translation>
<translation id="8368476060205742148">Serviços do Google Play</translation>
+<translation id="8371889962595521444">Certificados de raiz personalizados</translation>
<translation id="8380941800586852976">Perigosa</translation>
<translation id="8381674639488873545">Estas cobranças podem ser únicas ou recorrentes e podem não ser óbvias. <ph name="BEGIN_LINK" />Mostrar mesmo assim<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Os seus marcadores visitados recentemente são apresentados aqui.</translation>
@@ -1164,6 +1182,7 @@ Detalhes adicionais:
<translation id="8416694386774425977">A configuração de rede é inválida e não foi possível importá-la.
Detalhes adicionais:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Dispositivo gerido por <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Alterar</translation>
<translation id="8428213095426709021">Definições</translation>
@@ -1225,6 +1244,7 @@ Detalhes adicionais:
<translation id="8932102934695377596">O seu relógio está atrasado</translation>
<translation id="893332455753468063">Adicionar nome</translation>
<translation id="8938939909778640821">Cartões de crédito e pré-pagos admitidos</translation>
+<translation id="894185898663964645">O seu administrador configurou certificados de raiz personalizados, os quais podem permitir ao administrador ver os conteúdos dos Websites que visita.</translation>
<translation id="8943282376843390568">Lima</translation>
<translation id="8957210676456822347">Autorização de portal cativo</translation>
<translation id="8968766641738584599">Guardar cartão</translation>
diff --git a/chromium/components/strings/components_strings_ro.xtb b/chromium/components/strings/components_strings_ro.xtb
index 0cf53aee9b1..261c22de977 100644
--- a/chromium/components/strings/components_strings_ro.xtb
+++ b/chromium/components/strings/components_strings_ro.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Paginile în <ph name="LANGUAGE" /> nu vor fi traduse.</translation>
<translation id="2053553514270667976">Cod zip</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestie}few{# sugestii}other{# de sugestii}}</translation>
+<translation id="2068124040035837596">Contul tău este administrat de <ph name="ENROLLMENT_DOMAIN" />. Administratorul poate să-ți configureze contul de la distanță.</translation>
<translation id="2068663545051464999">S-a încărcat Raportul de blocare cu ID-ul <ph name="CRASH_ID" /> (Context local: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Anulează</translation>
<translation id="20817612488360358">Setările proxy de sistem sunt setate pentru a fi utilizate, dar o configurație explicită pentru proxy este, de asemenea, specificată.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Această metodă de expediere nu este disponibilă. Încearcă altă metodă.</translation>
<translation id="2396249848217231973">&amp;Anulați ștergerea</translation>
<translation id="2413528052993050574">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; este posibil ca certificatul său de securitate să fie revocat. Cauza poate fi o configurare greșită sau interceptarea conexiunii de către un atacator.</translation>
+<translation id="244665789865330679">Dispozitivul și contul tău sunt administrate de <ph name="ENROLLMENT_DOMAIN" />. Administratorul poate să-ți configureze dispozitivul și contul de la distanță.</translation>
<translation id="2463193859425327265">Schimbă Pagina principală</translation>
<translation id="2463739503403862330">Completează</translation>
<translation id="2465655957518002998">Alege metoda de livrare</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Ați încercat să accesați <ph name="DOMAIN" />, dar certificatul furnizat de server a fost revocat de emitentul său. Aceasta înseamnă că acreditările de securitate furnizate de server nu sunt deloc de încredere. Este posibil să comunicați cu un atacator.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">rezultate ale căutării</translation>
+<translation id="4406972042435603828">Administratorii au instalat extensii care au capacități puternice.</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> cookie-uri</translation>
<translation id="4415426530740016218">Adresă de preluare</translation>
<translation id="4424024547088906515">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; Chrome nu consideră că certificatul său de securitate este de încredere. Cauza poate fi o configurare greșită sau interceptarea conexiunii de către un atacator.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Nu există rezultate</translation>
<translation id="4950898438188848926">Butonul Comută între file, apasă pe Enter pentru a comuta la fila deschisă, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Acțiuni</translation>
+<translation id="495832697253704892">Raportarea extensiilor</translation>
<translation id="4958444002117714549">Extindeți lista</translation>
<translation id="4974590756084640048">Reactivează avertismentele</translation>
<translation id="4989163558385430922">Afișează-le pe toate</translation>
<translation id="4989809363548539747">Acest plugin nu este acceptat</translation>
+<translation id="4996230189582812866">Raportare</translation>
<translation id="5002932099480077015">Dacă este activată, Chrome va stoca o copie a cardului pe acest dispozitiv, pentru completarea mai rapidă a formularelor.</translation>
<translation id="5014174725590676422">Se afișează ecranul pentru prima rulare a Asistentului Google în Chrome</translation>
<translation id="5015510746216210676">Numele dispozitivului:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Stat</translation>
<translation id="5094747076828555589">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; Chromium nu consideră că certificatul său de securitate este de încredere. Cauza poate fi o configurare greșită sau interceptarea conexiunii de către un atacator.</translation>
<translation id="5095208057601539847">Provincie</translation>
+<translation id="5098222253617183465">Dispozitivul tău este gestionat de <ph name="ENROLLMENT_DOMAIN" /> și contul tău este gestionat de <ph name="ACCOUNT_DOMAIN" />. Administratorii pot configura de la distanță dispozitivul și contul tău.</translation>
<translation id="5115563688576182185">(64 de biți)</translation>
<translation id="5128122789703661928">Sesiunea cu acest nume nu este validă pentru ștergere.</translation>
<translation id="5135404736266831032">Gestionează adresele...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Computer</translation>
<translation id="5179510805599951267">Nu este în <ph name="ORIGINAL_LANGUAGE" />? Semnalează această eroare.</translation>
<translation id="5190835502935405962">Bară de marcaje</translation>
+<translation id="5200263511887412697">raportează lista cu utilizatorii dispozitivului care s-au conectat recent</translation>
<translation id="5201306358585911203">O pagină încorporată de pe această pagină afișează mesajul</translation>
<translation id="5205222826937269299">Numele este obligatoriu</translation>
<translation id="5215116848420601511">Metodele de plată și adresele care folosesc Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Acest site nu poate fi accesat</translation>
<translation id="5869522115854928033">Parole salvate</translation>
<translation id="5887400589839399685">Cardul a fost salvat</translation>
+<translation id="5893718151540690985">raportează lista cu interfețele de rețea, care cuprinde tipurile acestora și adresele hardware</translation>
<translation id="5893752035575986141">Se acceptă carduri de credit.</translation>
<translation id="5901630391730855834">Galben</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sincronizat)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Editează informațiile de contact</translation>
<translation id="5967867314010545767">Eliminați din istoric</translation>
<translation id="5975083100439434680">Micșorează</translation>
+<translation id="5977489021191000276">Dispozitivul tău nu este gestionat de un administrator.</translation>
<translation id="5977976211062815271">Pe acest dispozitiv</translation>
<translation id="598637245381783098">Nu se poate deschide aplicația de plată</translation>
<translation id="5989320800837274978">Nu sunt specificate nici servere proxy fixe și nici o adresă URL pentru scripturi .pac.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Atacatorii de pe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> ar putea instala aplicații înșelătoare care pretind a fi altceva sau culeg date care pot fi folosite pentru a te urmări. <ph name="BEGIN_LEARN_MORE_LINK" />Află mai multe<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sincronizate)</translation>
<translation id="6027201098523975773">Introdu un nume</translation>
+<translation id="6033927989869462158">raportează statisticile privind hardware-ul cum ar fi utilizarea CPU/RAM</translation>
<translation id="6034000775414344507">Gri deschis</translation>
<translation id="6039846035001940113">Dacă problema persistă, contactează proprietarul site-ului.</translation>
<translation id="6040143037577758943">Închide</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">User Agent</translation>
<translation id="6903319715792422884">Ne poți ajuta să îmbunătățim Navigarea sigură dacă trimiți la Google anumite <ph name="BEGIN_WHITEPAPER_LINK" />informații despre sistem și conținutul paginii<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Utilizator:</translation>
+<translation id="6934672428414710184">Acest nume provine din Contul tău Google</translation>
+<translation id="6939583532829045966">Dispozitivul tău este administrat de <ph name="ENROLLMENT_DOMAIN" />. Administratorul poate să-ți configureze de la distanță dispozitivul.</translation>
<translation id="6944692733090228304">Ai introdus parola pe un site care nu este gestionat de <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Pentru a proteja contul, nu folosi aceeași parolă pentru alte aplicații și site-uri.</translation>
<translation id="6945221475159498467">Selectează</translation>
<translation id="6948701128805548767">Pentru a vedea metodele de preluare și cerințele, selectează o adresă</translation>
@@ -992,6 +1004,7 @@ Detalii suplimentare:
&lt;&lt;li&gt;Dă clic pe &lt;strong&gt;Apply&lt;/strong&gt; (Aplică), apoi dă clic pe &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Accesează &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centrul de ajutor Chrome&lt;/a&gt; pentru a afla cum poți să elimini definitiv software-ul de pe computer
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Gestionare <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Gestionează parolele…</translation>
<translation id="7419106976560586862">Calea profilului</translation>
<translation id="7437289804838430631">Adaugă informații de contact</translation>
@@ -1000,10 +1013,12 @@ Detalii suplimentare:
<translation id="7442725080345379071">Portocaliu deschis</translation>
<translation id="7444046173054089907">Acest site este blocat</translation>
<translation id="7445762425076701745">Identitatea serverului la care te-ai conectat nu poate fi validată complet. Ești conectat(ă) la un server folosind un nume valid numai în rețeaua ta, pentru care o autoritate de certificare externă nu are nici o modalitate de a-l valida. Deoarece unele autorități de certificare vor emite certificate pentru aceste nume oricum, nu există nicio modalitate de a te asigura că ești conectat(ă) la site-ul corect și nu la un atacator.</translation>
+<translation id="7449109375006139765">trimite jurnalele de sistem la serverul de gestionare</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />să afli mai multe<ph name="END_LINK" /> despre această problemă.</translation>
<translation id="7455133967321480974">Utilizați setarea prestabilită la nivel global (Blocați)</translation>
<translation id="7460618730930299168">Proiecția este diferită de ce ai selectat. Continui?</translation>
<translation id="7473891865547856676">Nu, mulțumesc</translation>
+<translation id="7475525192983021547">raportează intervalele de timp în care utilizatorul este activ pe dispozitiv</translation>
<translation id="7481312909269577407">Înainte</translation>
<translation id="7485870689360869515">Nu s-au găsit date.</translation>
<translation id="7508255263130623398">ID-ul de dispozitiv returnat pentru politică este gol sau nu corespunde cu ID-ul de dispozitiv actual</translation>
@@ -1096,6 +1111,7 @@ Detalii suplimentare:
<translation id="7995512525968007366">Nespecificată</translation>
<translation id="800218591365569300">Încearcă să închizi celelalte file sau programe pentru a elibera memoria.</translation>
<translation id="8009225694047762179">Gestionează parolele</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Acest card și adresa de facturare vor fi salvate. Le vei putea folosi după ce te-ai conectat la <ph name="USER_EMAIL" />.}few{Aceste carduri și adresele de facturare vor fi salvate. Le vei putea folosi după ce te-ai conectat la <ph name="USER_EMAIL" />.}other{Aceste carduri și adresele de facturare vor fi salvate. Le vei putea folosi după ce te-ai conectat la <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Momentan, nu ți-am putut contacta părinții. Încearcă din nou.</translation>
<translation id="8025119109950072390">Atacatorii de pe acest site te pot înșela, determinându-te să faci ceva periculos, cum ar fi să instalezi software sau să îți dezvălui informațiile cu caracter personal (de exemplu, parole, numere de telefon sau carduri de credit).</translation>
<translation id="8034522405403831421">Această pagină este în <ph name="SOURCE_LANGUAGE" />. Doriți traducere în <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Detalii suplimentare:
<translation id="8041940743680923270">Utilizați setarea prestabilită la nivel global (Întrebați)</translation>
<translation id="8042918947222776840">Alege metoda de preluare</translation>
<translation id="8057711352706143257">„<ph name="SOFTWARE_NAME" />” nu este configurat corect. De obicei, problema se remediază dezinstalând „<ph name="SOFTWARE_NAME" />” <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Dispozitivul a fost configurat pentru:</translation>
<translation id="8078141288243656252">Nu se poate adnota când este rotit</translation>
<translation id="8079031581361219619">Reîncarci site-ul?</translation>
<translation id="8088680233425245692">Articolul nu a fost vizualizat.</translation>
@@ -1156,6 +1173,7 @@ Detalii suplimentare:
<translation id="8363502534493474904">să dezactivezi modul Avion.</translation>
<translation id="8364627913115013041">Nesetată.</translation>
<translation id="8368476060205742148">Servicii Google Play</translation>
+<translation id="8371889962595521444">Certificate rădăcină personalizate</translation>
<translation id="8380941800586852976">Periculos</translation>
<translation id="8381674639488873545">Aceste costuri pot fi unice sau recurente și ascunse. <ph name="BEGIN_LINK" />Afișează oricum<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Marcajele accesate recent apar aici</translation>
@@ -1165,6 +1183,7 @@ Detalii suplimentare:
<translation id="8416694386774425977">Configurația rețelei este nevalidă și nu a putut fi importată.
Detalii suplimentare:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Dispozitiv gestionat de <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Modificați</translation>
<translation id="8428213095426709021">Setări</translation>
@@ -1226,6 +1245,7 @@ Detalii suplimentare:
<translation id="8932102934695377596">Ora este setată în trecut</translation>
<translation id="893332455753468063">Adaugă un nume</translation>
<translation id="8938939909778640821">Carduri de credit și preplătite acceptate</translation>
+<translation id="894185898663964645">Administratorul a configurat certificate rădăcină personalizate, care îi pot permite să vadă conținutul site-urilor pe care le accesezi.</translation>
<translation id="8943282376843390568">Verde-gălbui</translation>
<translation id="8957210676456822347">Autorizarea prin portalul captiv</translation>
<translation id="8968766641738584599">Salvează cardul</translation>
diff --git a/chromium/components/strings/components_strings_ru.xtb b/chromium/components/strings/components_strings_ru.xtb
index 2e5cf82bbd0..0056816d8fa 100644
--- a/chromium/components/strings/components_strings_ru.xtb
+++ b/chromium/components/strings/components_strings_ru.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Страницы на этом языке (<ph name="LANGUAGE" />) не будут переводиться автоматически.</translation>
<translation id="2053553514270667976">Почтовый индекс</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 вариант}one{# вариант}few{# варианта}many{# вариантов}other{# варианта}}</translation>
+<translation id="2068124040035837596">Ваш аккаунт находится под управлением домена <ph name="ENROLLMENT_DOMAIN" />. Администратор этого домена может удаленно изменять настройки вашего аккаунта.</translation>
<translation id="2068663545051464999">Идентификатор загруженного отчета о сбоях: <ph name="CRASH_ID" />. Локальный идентификатор сбоя: <ph name="CRASH_LOCAL_ID" />.</translation>
<translation id="2079545284768500474">Отмена</translation>
<translation id="20817612488360358">Включены системные настройки прокси-сервера, но при этом его конфигурация задана явным образом.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Этот способ доставки недоступен. Выберите другой.</translation>
<translation id="2396249848217231973">&amp;Отменить удаление</translation>
<translation id="2413528052993050574">Не удалось подтвердить, что это сервер <ph name="DOMAIN" />. Его сертификат безопасности может быть отозван. Возможно, сервер настроен неправильно или кто-то пытается перехватить ваши данные.</translation>
+<translation id="244665789865330679">Ваше устройство и аккаунт находятся под управлением домена <ph name="ENROLLMENT_DOMAIN" />. Администратор этого домена может удаленно изменять настройки вашего устройства и аккаунта.</translation>
<translation id="2463193859425327265">Изменить главную страницу</translation>
<translation id="2463739503403862330">Заполнить</translation>
<translation id="2465655957518002998">Выбрать способ доставки</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719">Вы попытались перейти на сайт <ph name="DOMAIN" />, однако сертификат, предоставленный сервером, был отозван издателем. Это означает, что учетные данные безопасности, предоставленные сервером, не заслуживают доверия. Возможно, вы имеете дело со злоумышленниками.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4406896451731180161">Результаты поиска</translation>
+<translation id="4406972042435603828">Администратор установил полезные расширения для вашего браузера.</translation>
<translation id="4408413947728134509">Настройки файлов cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Адрес получения</translation>
<translation id="4424024547088906515">Не удалось подтвердить, что это сервер <ph name="DOMAIN" />. Chrome не доверяет его сертификату безопасности. Возможно, сервер настроен неправильно или кто-то пытается перехватить ваши данные.</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">Нет результатов</translation>
<translation id="4950898438188848926">Кнопка переключения между вкладками. Чтобы переключиться на открытую вкладку (<ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />), нажмите клавишу "Ввод".</translation>
<translation id="495170559598752135">Действия</translation>
+<translation id="495832697253704892">Отчеты о расширениях</translation>
<translation id="4958444002117714549">Развернуть список</translation>
<translation id="4974590756084640048">Снова включить предупреждения</translation>
<translation id="4989163558385430922">Показать все</translation>
<translation id="4989809363548539747">Плагин не поддерживается</translation>
+<translation id="4996230189582812866">Отчеты</translation>
<translation id="5002932099480077015">Chrome будет хранить на этом устройстве данные карты для быстрого заполнения форм.</translation>
<translation id="5014174725590676422">Показан экран первого запуска Google Ассистента в Chrome</translation>
<translation id="5015510746216210676">Имя компьютера:</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">Штат</translation>
<translation id="5094747076828555589">Не удалось подтвердить, что это сервер <ph name="DOMAIN" />. Chromium не доверяет его сертификату безопасности. Возможно, сервер настроен неправильно или кто-то пытается перехватить ваши данные.</translation>
<translation id="5095208057601539847">Провинция</translation>
+<translation id="5098222253617183465">Ваше устройство находится под управлением домена <ph name="ENROLLMENT_DOMAIN" />, а аккаунт – <ph name="ACCOUNT_DOMAIN" />. Администраторы этих доменов могут удаленно изменять настройки вашего устройства и аккаунта.</translation>
<translation id="5115563688576182185">(64 бит)</translation>
<translation id="5128122789703661928">Невозможно удалить сеанс с таким названием.</translation>
<translation id="5135404736266831032">Управление адресами…</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">Локальный компьютер</translation>
<translation id="5179510805599951267">Это не <ph name="ORIGINAL_LANGUAGE" />? Сообщите об ошибке</translation>
<translation id="5190835502935405962">Панель закладок</translation>
+<translation id="5200263511887412697">Отправлять данные о пользователях, недавно выполнявших вход на устройстве.</translation>
<translation id="5201306358585911203">Подтвердите действие</translation>
<translation id="5205222826937269299">Введите имя или название</translation>
<translation id="5215116848420601511">Способы оплаты и адреса из Google Pay</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">Не удается получить доступ к сайту</translation>
<translation id="5869522115854928033">Сайты с сохраненными паролями</translation>
<translation id="5887400589839399685">Карта сохранена</translation>
+<translation id="5893718151540690985">Отправлять список сетевых интерфейсов с указанием их типов и адресов оборудования.</translation>
<translation id="5893752035575986141">Принимаются кредитные карты.</translation>
<translation id="5901630391730855834">Желтый</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (данные синхронизируются)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">Измените контактную информацию</translation>
<translation id="5967867314010545767">Удалить из истории</translation>
<translation id="5975083100439434680">Уменьшить</translation>
+<translation id="5977489021191000276">Ваше устройство не управляется администратором.</translation>
<translation id="5977976211062815271">На этом устройстве</translation>
<translation id="598637245381783098">Не удалось открыть Payments</translation>
<translation id="5989320800837274978">Ни фиксированные прокси-серверы, ни URL PAC-скриптов не указаны.</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347">Злоумышленники могут использовать сайт <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, чтобы установить вредоносные приложения, маскирующиеся под безопасные программы или собирающие данные, по которым вас можно отследить. <ph name="BEGIN_LEARN_MORE_LINK" />Подробнее…<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (данные синхронизируются)</translation>
<translation id="6027201098523975773">Введите имя.</translation>
+<translation id="6033927989869462158">Отправлять статистические данные о работе аппаратного оборудования, например об использовании процессора или оперативной памяти.</translation>
<translation id="6034000775414344507">Светло-серый</translation>
<translation id="6039846035001940113">Если проблема не исчезнет, свяжитесь с владельцем сайта.</translation>
<translation id="6040143037577758943">Закрыть</translation>
@@ -904,6 +914,8 @@
<translation id="6897140037006041989">User Agent</translation>
<translation id="6903319715792422884">Чтобы улучшить режим Безопасного просмотра, вы можете <ph name="BEGIN_WHITEPAPER_LINK" />отправлять системную информацию и контент страниц<ph name="END_WHITEPAPER_LINK" /> в Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Пользователь:</translation>
+<translation id="6934672428414710184">Это имя из вашего аккаунта Google</translation>
+<translation id="6939583532829045966">Ваше устройство находится под управлением домена <ph name="ENROLLMENT_DOMAIN" />. Администратор этого домена может удаленно изменять настройки вашего устройства.</translation>
<translation id="6944692733090228304">Вы ввели пароль на сайте, который не находится под управлением организации <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Чтобы защитить свой аккаунт, не используйте этот пароль для других приложений и сайтов.</translation>
<translation id="6945221475159498467">Выбрать</translation>
<translation id="6948701128805548767">Выберите адрес, чтобы посмотреть способы и условия получения.</translation>
@@ -991,6 +1003,7 @@
&lt;li&gt;Нажмите &lt;strong&gt;Применить&lt;/strong&gt;, а затем – &lt;strong&gt;ОК&lt;/strong&gt;.
&lt;li&gt;О том, как удалить ПО с компьютера, читайте в &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Справочном центре Chrome&lt;/a&gt;.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Управление <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Управление паролями</translation>
<translation id="7419106976560586862">Путь к профилю</translation>
<translation id="7437289804838430631">Добавить контактные данные</translation>
@@ -999,10 +1012,12 @@
<translation id="7442725080345379071">Светло-оранжевый</translation>
<translation id="7444046173054089907">Сайт заблокирован</translation>
<translation id="7445762425076701745">Идентификация сервера, к которому вы подключились, не может быть полностью подтверждена. Вы подключились к серверу, используя название, которое действительно только в вашей сети; владелец этого сервера не может быть проверен или подтвержден внешним центром сертификации. Так как некоторые центры сертификации могут выдавать сертификаты для подобных названий, отсутствуют гарантии в том, что это действительно нужный вам сайт, а не сайт злоумышленника.</translation>
+<translation id="7449109375006139765">Отправлять системные журналы на сервер для проверки.</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Узнайте больше<ph name="END_LINK" /> об этой проблеме.</translation>
<translation id="7455133967321480974">Использовать глобальный параметр по умолчанию (блокировать)</translation>
<translation id="7460618730930299168">Настройки этого сеанса отличаются от тех, которые выбрали вы. Продолжить?</translation>
<translation id="7473891865547856676">Пропустить</translation>
+<translation id="7475525192983021547">Отправлять данные о длительности работы пользователей с устройством.</translation>
<translation id="7481312909269577407">Вперед</translation>
<translation id="7485870689360869515">Данные не найдены.</translation>
<translation id="7508255263130623398">Возвращенный идентификатор устройства пуст или не соответствует имеющемуся</translation>
@@ -1095,6 +1110,7 @@
<translation id="7995512525968007366">Не указано</translation>
<translation id="800218591365569300">Закройте другие вкладки и программы, чтобы освободить память.</translation>
<translation id="8009225694047762179">Управление паролями</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Данные этой карты и ее платежный адрес будут сохранены. Вы сможете пользоваться ею после входа в аккаунт <ph name="USER_EMAIL" />.}one{Данные этих карт и их платежные адреса будут сохранены. Вы сможете пользоваться ими после входа в аккаунт <ph name="USER_EMAIL" />.}few{Данные этих карт и их платежные адреса будут сохранены. Вы сможете пользоваться ими после входа в аккаунт <ph name="USER_EMAIL" />.}many{Данные этих карт и их платежные адреса будут сохранены. Вы сможете пользоваться ими после входа в аккаунт <ph name="USER_EMAIL" />.}other{Данные этих карт и их платежные адреса будут сохранены. Вы сможете пользоваться ими после входа в аккаунт <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Не удалось связаться с вашими родителями. Повторите попытку.</translation>
<translation id="8025119109950072390">Посещение этого сайта может привести к установке вредоносного ПО или хищению личной информации (например, паролей, телефонных номеров и данных банковских карт).</translation>
<translation id="8034522405403831421">Язык этой страницы: <ph name="SOURCE_LANGUAGE" />. Перевести ее на <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1105,6 +1121,7 @@
<translation id="8041940743680923270">Использовать глобальный параметр по умолчанию (спрашивать)</translation>
<translation id="8042918947222776840">Выбрать способ получения</translation>
<translation id="8057711352706143257">Программа "<ph name="SOFTWARE_NAME" />" настроена неправильно. Чтобы устранить проблему, удалите программу "<ph name="SOFTWARE_NAME" />". <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Для вашего устройства установлены следующие настройки:</translation>
<translation id="8078141288243656252">Недоступно, когда документ повернут</translation>
<translation id="8079031581361219619">Перезагрузить сайт?</translation>
<translation id="8088680233425245692">Не удалось показать статью</translation>
@@ -1155,6 +1172,7 @@
<translation id="8363502534493474904">Отключите режим полета.</translation>
<translation id="8364627913115013041">Не задано</translation>
<translation id="8368476060205742148">Сервисы Google Play</translation>
+<translation id="8371889962595521444">Пользовательские корневые сертификаты</translation>
<translation id="8380941800586852976">Опасно</translation>
<translation id="8381674639488873545">Списание может быть разовым или повторяющимся без каких-либо уведомлений. <ph name="BEGIN_LINK" />Все равно продолжить<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Здесь появятся закладки, которые вы недавно открывали.</translation>
@@ -1164,6 +1182,7 @@
<translation id="8416694386774425977">Импорт невозможен: недопустимая конфигурация сети.
Подробнее:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Устройство под управлением домена <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Изменить</translation>
<translation id="8428213095426709021">Настройки</translation>
@@ -1224,6 +1243,7 @@
<translation id="8932102934695377596">Часы отстают</translation>
<translation id="893332455753468063">Добавьте имя</translation>
<translation id="8938939909778640821">Кредитные карты и карты предоплаты, которые принимаются к оплате</translation>
+<translation id="894185898663964645">Ваш администратор настроил корневые сертификаты, позволяющие ему просматривать контент посещенных вами сайтов.</translation>
<translation id="8943282376843390568">Лаймовый</translation>
<translation id="8957210676456822347">Авторизация через адаптивный портал</translation>
<translation id="8968766641738584599">Сохранить карту</translation>
diff --git a/chromium/components/strings/components_strings_sk.xtb b/chromium/components/strings/components_strings_sk.xtb
index 67f5da26817..cb47a2b105b 100644
--- a/chromium/components/strings/components_strings_sk.xtb
+++ b/chromium/components/strings/components_strings_sk.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Stránky v jazyku <ph name="LANGUAGE" /> nebudú prekladané.</translation>
<translation id="2053553514270667976">PSČ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 návrh}few{# návrhy}many{# návrhu}other{# návrhov}}</translation>
+<translation id="2068124040035837596">Váš účet spravuje doména <ph name="ENROLLMENT_DOMAIN" />. Znamená to, že správca môže vzdialene nakonfigurovať váš účet.</translation>
<translation id="2068663545051464999">Identifikátor nahranej správy o zlyhaní <ph name="CRASH_ID" /> (Miestny kontext: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Späť</translation>
<translation id="20817612488360358">Používanie systémových nastavení servera proxy je nastavené, avšak je určená aj explicitná konfigurácia servera proxy.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Tento spôsob dodania nie je k dispozícii. Skúste inú možnosť.</translation>
<translation id="2396249848217231973">&amp;Vrátiť späť odstránenie</translation>
<translation id="2413528052993050574">Server nedokáže overiť, či ide o doménu <ph name="DOMAIN" />, jej bezpečnostný certifikát bol zrejme zrušený. Môže to byť spôsobené nesprávnou konfiguráciou alebo tým, že vaše pripojenie zachytil útočník.</translation>
+<translation id="244665789865330679">Zariadenie spravuje doména <ph name="ENROLLMENT_DOMAIN" />. Znamená to, že správca môže vzdialene nakonfigurovať vaše zariadenie aj účet.</translation>
<translation id="2463193859425327265">Zmeniť domovskú stránku</translation>
<translation id="2463739503403862330">Vyplniť</translation>
<translation id="2465655957518002998">Zvoliť spôsob doručenia</translation>
@@ -557,6 +559,7 @@
<translation id="4377125064752653719">Pokúsili ste sa o prístup na stránky <ph name="DOMAIN" />, avšak certifikát poskytnutý serverom bol vydavateľom zrušený. Znamená to, že povereniam zabezpečenia, ktoré predložil server, sa celkom nedá dôverovať. Je možné, že komunikujete s útočníkom.</translation>
<translation id="4378154925671717803">Telefón</translation>
<translation id="4406896451731180161">výsledky vyhľadávania</translation>
+<translation id="4406972042435603828">Vaši správcovia nainštalovali rozšírenia s rozsiahlymi funkciami.</translation>
<translation id="4408413947728134509">Súbory cookie: <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Adresa vyzdvihnutia</translation>
<translation id="4424024547088906515">Server nedokáže overiť, či ide o doménu <ph name="DOMAIN" />, Chrome nedôveruje jej bezpečnostnému certifikátu. Môže to byť spôsobené nesprávnou konfiguráciou alebo tým, že vaše pripojenie zachytil útočník.</translation>
@@ -628,10 +631,12 @@
<translation id="4943872375798546930">Žiadne výsledky</translation>
<translation id="4950898438188848926">Tlačidlo na prepnutie karty, stlačením klávesa Enter prepnete na otvorenú kartu, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Akcie</translation>
+<translation id="495832697253704892">Prehľady rozšírenia</translation>
<translation id="4958444002117714549">Rozbaliť zoznam</translation>
<translation id="4974590756084640048">Opätovne aktivovať upozornenia</translation>
<translation id="4989163558385430922">Zobraziť všetko</translation>
<translation id="4989809363548539747">Tento doplnok nie je podporovaný</translation>
+<translation id="4996230189582812866">Prehľady</translation>
<translation id="5002932099480077015">Ak túto možnosť povolíte, Chrome bude uchovávať kópiu vašej karty na tomto zariadení na účely rýchlejšieho dopĺňania formulárov.</translation>
<translation id="5014174725590676422">Zobrazuje sa obrazovka pri prvom spustení Asistenta Google v Chrome</translation>
<translation id="5015510746216210676">Názov počítača:</translation>
@@ -652,6 +657,7 @@
<translation id="5089810972385038852">Štát</translation>
<translation id="5094747076828555589">Server nedokáže overiť, či ide o doménu <ph name="DOMAIN" />, Chromium nedôveruje jej bezpečnostnému certifikátu. Môže to byť spôsobené nesprávnou konfiguráciou alebo tým, že vaše pripojenie zachytil útočník.</translation>
<translation id="5095208057601539847">Provincia</translation>
+<translation id="5098222253617183465">Zariadenie spravuje doména <ph name="ENROLLMENT_DOMAIN" /> a váš účet spravuje <ph name="ACCOUNT_DOMAIN" />. Znamená to, že správcovia môžu vzdialene nakonfigurovať vaše zariadenie aj účet.</translation>
<translation id="5115563688576182185">(64-bitová verzia)</translation>
<translation id="5128122789703661928">Relácia s týmto názvom je neplatná a nedá sa odstrániť.</translation>
<translation id="5135404736266831032">Spravovať adresy…</translation>
@@ -664,6 +670,7 @@
<translation id="5172758083709347301">Počítač</translation>
<translation id="5179510805599951267">Text sa nezobrazil v jazyku <ph name="ORIGINAL_LANGUAGE" />? Nahláste túto chybu</translation>
<translation id="5190835502935405962">Panel so záložkami</translation>
+<translation id="5200263511887412697">nahlasovanie zoznamu používateľov zariadenia, ktorí sa nedávno prihlásili</translation>
<translation id="5201306358585911203">Vložená stránka na tejto stránke hovorí</translation>
<translation id="5205222826937269299">Meno je povinný údaj</translation>
<translation id="5215116848420601511">Spôsoby platby a adresy pomocou Google Pay</translation>
@@ -765,6 +772,7 @@
<translation id="5869405914158311789">K tomuto webu sa nedá pripojiť</translation>
<translation id="5869522115854928033">Uložené heslá</translation>
<translation id="5887400589839399685">Karta bola uložená</translation>
+<translation id="5893718151540690985">nahlasovanie zoznamu sieťových rozhraní s typmi a adresami hardvéru</translation>
<translation id="5893752035575986141">Kreditné karty sú akceptované.</translation>
<translation id="5901630391730855834">Žltá</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synchronizované)</translation>
@@ -778,6 +786,7 @@
<translation id="5967592137238574583">Úprava kontaktných informácií</translation>
<translation id="5967867314010545767">Odstrániť z histórie</translation>
<translation id="5975083100439434680">Oddialiť</translation>
+<translation id="5977489021191000276">Vaše zariadenie neovláda žiadny správca.</translation>
<translation id="5977976211062815271">V tomto zariadení</translation>
<translation id="598637245381783098">Nie je možné otvoriť platobnú aplikáciu</translation>
<translation id="5989320800837274978">Nie sú určené pevne dané servery proxy ani skript PAC webovej adresy.</translation>
@@ -789,6 +798,7 @@
<translation id="6017850046339264347">Útočníci na webe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> by mohli nainštalovať klamlivé aplikácie vydávajúce sa za iné aplikácie alebo zhromažďujúce údaje, ktoré sa dajú použiť na sledovanie vašej osoby. <ph name="BEGIN_LEARN_MORE_LINK" />Ďalšie informácie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synchronizované)</translation>
<translation id="6027201098523975773">Zadajte meno</translation>
+<translation id="6033927989869462158">nahlasovanie štatistík hardvéru, napríklad využitie procesora alebo pamäte RAM</translation>
<translation id="6034000775414344507">Svetlosivá</translation>
<translation id="6039846035001940113">Ak problém naďalej pretrváva, kontaktujte vlastníka webu.</translation>
<translation id="6040143037577758943">Zavrieť</translation>
@@ -900,6 +910,8 @@
<translation id="6897140037006041989">Používateľský agent</translation>
<translation id="6903319715792422884">Pomôžte zlepšovať Bezpečné prehliadanie tak, že budete Googlu odosielať niektoré <ph name="BEGIN_WHITEPAPER_LINK" />informácie o systéme a obsah stránok<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Používateľ:</translation>
+<translation id="6934672428414710184">Meno pochádza z vášho účtu Google</translation>
+<translation id="6939583532829045966">Zariadenie spravuje doména <ph name="ENROLLMENT_DOMAIN" />. Znamená to, že správca môže vzdialene nakonfigurovať vaše zariadenie.</translation>
<translation id="6944692733090228304">Zadali ste heslo na webe, ktorý nie je spravovaný organizáciou <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Ak chcete, aby bol váš účet chránený, nepoužívajte jeho heslo pre iné aplikácie a weby.</translation>
<translation id="6945221475159498467">Vybrať</translation>
<translation id="6948701128805548767">Ak chcete zobraziť spôsoby a požiadavky vyzdvihnutia, vyberte adresu</translation>
@@ -987,6 +999,7 @@
&lt;li&gt;Kliknite na možnosť &lt;strong&gt;Použiť&lt;/strong&gt;, potom na &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;Ďalšie informácie o tom, ako natrvalo odstrániť softvér z počítača, nájdete v &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;centre pomoci Chromu&lt;/a&gt;.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Správa prehliadača <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Spravovať heslá…</translation>
<translation id="7419106976560586862">Cesta profilu</translation>
<translation id="7437289804838430631">Pridať kontaktné informácie</translation>
@@ -995,10 +1008,12 @@
<translation id="7442725080345379071">Svetlooranžová</translation>
<translation id="7444046173054089907">Tento web je blokovaný</translation>
<translation id="7445762425076701745">Identita servera, ku ktorému ste pripojení, sa nedá úplne overiť. Ste pripojení k serveru, ktorý používa názov platný iba v rámci vašej siete. Externá certifikačná autorita nemôže vlastníctvo názvu nijakým spôsobom overiť. Niektoré certifikačné autority však vydajú certifikát aj pre takéto názvy, a preto sa nedá zaručiť, že ste pripojení k požadovaným webovým stránkam a nie k stránkam útočníka.</translation>
+<translation id="7449109375006139765">odosielanie denníkov systému na správcovský server</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Ďalšie informácie o tomto probléme<ph name="END_LINK" /></translation>
<translation id="7455133967321480974">Použiť predvolené všeobecné nastavenie (Blokovať)</translation>
<translation id="7460618730930299168">Zobrazené informácie sa líšia od vášho výberu. Pokračovať?</translation>
<translation id="7473891865547856676">Nie, ďakujem</translation>
+<translation id="7475525192983021547">nahlasovanie časových období, kedy používateľ aktívne využíval zariadenie</translation>
<translation id="7481312909269577407">Dopredu</translation>
<translation id="7485870689360869515">Nenašli sa žiadne údaje.</translation>
<translation id="7508255263130623398">Identifikátor zariadenia vráteného v rámci záruky je prázdny alebo sa nezhoduje s identifikátorom aktuálneho zariadenia</translation>
@@ -1091,6 +1106,7 @@
<translation id="7995512525968007366">Nie je upresnené</translation>
<translation id="800218591365569300">Skúste zavrieť ostatné karty alebo programy a uvoľniť tak miesto v pamäti.</translation>
<translation id="8009225694047762179">Spravovať heslá</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Táto karta a jej fakturačná adresa budú uložené. Budete ju môcť použiť po prihlásení do účtu <ph name="USER_EMAIL" />.}few{Tieto karty a ich fakturačné adresy budú uložené. Budete ich môcť použiť po prihlásení do účtu <ph name="USER_EMAIL" />.}many{Tieto karty a ich fakturačné adresy budú uložené. Budete ich môcť použiť po prihlásení do účtu <ph name="USER_EMAIL" />.}other{Tieto karty a ich fakturačné adresy budú uložené. Budete ich môcť použiť po prihlásení do účtu <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">V tejto chvíli sa nám nepodarilo spojiť s vašimi rodičmi. Skúste to znova neskôr.</translation>
<translation id="8025119109950072390">Útočníci na tomto webe sa vás môžu pokúsiť naviesť vykonať niečo nebezpečné, ako je inštalovanie softvéru alebo odhalenie osobných informácií (napr. hesiel, telefónnych čísel alebo kreditných kariet).</translation>
<translation id="8034522405403831421">Táto stránka je v jazyku <ph name="SOURCE_LANGUAGE" />. Chcete ju preložiť do jazyka <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1101,6 +1117,7 @@
<translation id="8041940743680923270">Použiť predvolené všeobecné nastavenie (Opýtať sa)</translation>
<translation id="8042918947222776840">Zvoliť spôsob vyzdvihnutia</translation>
<translation id="8057711352706143257">Softvér <ph name="SOFTWARE_NAME" /> nie je správne nakonfigurovaný. Tento problém sa zvyčajne odstráni odinštalovaním softvéru <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">V zariadení boli nakonfigurované nasledujúce pravidlá:</translation>
<translation id="8078141288243656252">Po otočení dokumentu nie je anotácia možná</translation>
<translation id="8079031581361219619">Znova načítať web?</translation>
<translation id="8088680233425245692">Článok sa nepodarilo zobraziť.</translation>
@@ -1151,6 +1168,7 @@
<translation id="8363502534493474904">Vypnúť režim v lietadle</translation>
<translation id="8364627913115013041">Nenastavené.</translation>
<translation id="8368476060205742148">Služby Google Play</translation>
+<translation id="8371889962595521444">Vlastné koreňové certifikáty</translation>
<translation id="8380941800586852976">Nebezpečná</translation>
<translation id="8381674639488873545">Tieto poplatky môžu byť jednorazové alebo opakované a nemusia byť predvídateľné. <ph name="BEGIN_LINK" />Napriek tomu zobraziť<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Tu sa zobrazia vaše nedávno navštívené záložky</translation>
@@ -1160,6 +1178,7 @@
<translation id="8416694386774425977">Konfigurácia siete je neplatná a nepodarilo sa ju importovať.
Ďalšie podrobnosti:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Zariadenie spravuje doména <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Zmeniť</translation>
<translation id="8428213095426709021">Nastavenia</translation>
@@ -1221,6 +1240,7 @@
<translation id="8932102934695377596">Vaše hodiny idú pozadu</translation>
<translation id="893332455753468063">Pridanie mena</translation>
<translation id="8938939909778640821">Akceptované kreditné a predplatené karty</translation>
+<translation id="894185898663964645">Váš správca nakonfiguroval vlastné koreňové certifikáty, ktoré mu môžu umožniť zobrazovať obsah vami navštevovaných webov.</translation>
<translation id="8943282376843390568">Limetková</translation>
<translation id="8957210676456822347">Autorizácia portálu na prihlásenie do siete</translation>
<translation id="8968766641738584599">Uložiť kartu</translation>
diff --git a/chromium/components/strings/components_strings_sl.xtb b/chromium/components/strings/components_strings_sl.xtb
index 1b856afb4c7..7731a85d81e 100644
--- a/chromium/components/strings/components_strings_sl.xtb
+++ b/chromium/components/strings/components_strings_sl.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Strani v jeziku <ph name="LANGUAGE" /> ne bodo prevedene.</translation>
<translation id="2053553514270667976">Poštna številka</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 predlog}one{# predlog}two{# predloga}few{# predlogi}other{# predlogov}}</translation>
+<translation id="2068124040035837596">Vaš račun upravlja domena <ph name="ENROLLMENT_DOMAIN" />. To pomeni, da lahko skrbnik na daljavo konfigurira vaš račun.</translation>
<translation id="2068663545051464999">ID naloženega poročila o zrušitvah <ph name="CRASH_ID" /> (lokalni kontekst: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Razveljavi</translation>
<translation id="20817612488360358">Za uporabo so nastavljene sistemske nastavitve strežnika proxy, vendar je navedena tudi izrecna konfiguracija proxyja.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Ta način pošiljanja ni na voljo. Poskusite uporabiti drugega.</translation>
<translation id="2396249848217231973">&amp;Razveljavi izbris</translation>
<translation id="2413528052993050574">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; njegovo varnostno potrdilo je bilo morda preklicano. Razlog za to je lahko napačna konfiguracija ali napadalčevo prestrezanje povezave.</translation>
+<translation id="244665789865330679">Vašo napravo in račun upravlja domena <ph name="ENROLLMENT_DOMAIN" />. To pomeni, da lahko skrbnik na daljavo konfigurira vašo napravo in račun.</translation>
<translation id="2463193859425327265">Spremeni domačo stran</translation>
<translation id="2463739503403862330">Izpolni</translation>
<translation id="2465655957518002998">Izbira načina dostave</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Poskusili ste dostopati do domene <ph name="DOMAIN" />, vendar je izdajatelj preklical potrdilo, ki ga je poslal strežnik. To pomeni, da varnostnim poverilnicam, ki jih je poslal strežnik, nikakor ne smete zaupati. Morda komunicirate z napadalcem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">rezultati iskanja</translation>
+<translation id="4406972042435603828">Skrbniki so namestili zmogljive razširitve.</translation>
<translation id="4408413947728134509">Piškotki <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Naslov za prevzem</translation>
<translation id="4424024547088906515">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; Chrome ne zaupa njegovemu varnostnemu potrdilu. Razlog za to je lahko napačna konfiguracija ali napadalčevo prestrezanje povezave.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Ni rezultatov</translation>
<translation id="4950898438188848926">Gumb za preklop zavihkov, pritisnite Enter, če želite preklopiti na odprti zavihek, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Dejanja</translation>
+<translation id="495832697253704892">Poročanje o razširitvah</translation>
<translation id="4958444002117714549">Razširi seznam</translation>
<translation id="4974590756084640048">Vnovično omogočanje opozoril</translation>
<translation id="4989163558385430922">Pokaži vse</translation>
<translation id="4989809363548539747">Ta vtičnik ni podprt</translation>
+<translation id="4996230189582812866">Poročanje</translation>
<translation id="5002932099480077015">Če je to omogočeno, Chrome shrani kopijo kartice v tej napravi zaradi hitrejšega izpolnjevanja obrazcev.</translation>
<translation id="5014174725590676422">Prikazan je zaslon za prvi zagon Pomočnika Google v Chromu</translation>
<translation id="5015510746216210676">Ime naprave:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Država:</translation>
<translation id="5094747076828555589">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; Chromium ne zaupa njegovemu varnostnemu potrdilu. Razlog za to je lahko napačna konfiguracija ali napadalčevo prestrezanje povezave.</translation>
<translation id="5095208057601539847">Provinca</translation>
+<translation id="5098222253617183465">Vašo napravo upravlja <ph name="ENROLLMENT_DOMAIN" /> in vaš račun upravlja <ph name="ACCOUNT_DOMAIN" />. To pomeni, da lahko skrbnika na daljavo konfigurirata napravo in račun.</translation>
<translation id="5115563688576182185">(64-bitno)</translation>
<translation id="5128122789703661928">Seja s tem imenom ni veljavna za izbris.</translation>
<translation id="5135404736266831032">Upravljanje naslovov ...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Računalnik</translation>
<translation id="5179510805599951267">Ni v <ph name="ORIGINAL_LANGUAGE" />? Obvestite nas o tej napaki</translation>
<translation id="5190835502935405962">Vrstica z zaznamki</translation>
+<translation id="5200263511887412697">poročanje o seznamu nedavno prijavljenih uporabnikov naprave</translation>
<translation id="5201306358585911203">Vdelana stran na tej spletni strani sporoča:</translation>
<translation id="5205222826937269299">Ime je obvezno</translation>
<translation id="5215116848420601511">Plačilna sredstva in naslovi z Googlom Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Tega spletnega mesta ni mogoče doseči</translation>
<translation id="5869522115854928033">Shranjena gesla</translation>
<translation id="5887400589839399685">Kartica je shranjena</translation>
+<translation id="5893718151540690985">poročanje seznama omrežnih vmesnikov z vrstami in naslovi strojne opreme.</translation>
<translation id="5893752035575986141">Sprejema kreditne kartice.</translation>
<translation id="5901630391730855834">Rumena</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (sinhronizirano)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Urejanje podatkov o stiku</translation>
<translation id="5967867314010545767">Odstrani iz zgodovine</translation>
<translation id="5975083100439434680">Pomanjšaj</translation>
+<translation id="5977489021191000276">Vaše naprave ne upravlja skrbnik.</translation>
<translation id="5977976211062815271">V tej napravi</translation>
<translation id="598637245381783098">Plačilne aplikacije ni mogoče odpreti</translation>
<translation id="5989320800837274978">Določeni niso ne stalni strežniki proxy ne URL skripta .pac.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Napadalci na spletnem mestu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> bi lahko namestili zavajajoče aplikacije, ki se pretvarjajo, da so nekaj drugega, ali zbirajo podatke, s katerimi vas lahko spremljajo. <ph name="BEGIN_LEARN_MORE_LINK" />Več o tem<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (sinhronizirano)</translation>
<translation id="6027201098523975773">Vnesite ime</translation>
+<translation id="6033927989869462158">poročanje statističnih podatkov o strojni opremi, kot je uporaba CPE-ja/RAM-a</translation>
<translation id="6034000775414344507">Svetlo siva</translation>
<translation id="6039846035001940113">Če težave ne odpravite, se obrnite na lastnika spletnega mesta.</translation>
<translation id="6040143037577758943">Zapri</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Uporabnikov posrednik</translation>
<translation id="6903319715792422884">S pošiljanjem nekaterih <ph name="BEGIN_WHITEPAPER_LINK" />informacij o sistemu in vsebine strani<ph name="END_WHITEPAPER_LINK" /> Googlu lahko pomagate izboljšati Varno brskanje. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Uporabnik:</translation>
+<translation id="6934672428414710184">To ime je iz vašega računa za Google</translation>
+<translation id="6939583532829045966">Vašo napravo upravlja domena <ph name="ENROLLMENT_DOMAIN" />. To pomeni, da lahko skrbnik na daljavo konfigurira vašo napravo.</translation>
<translation id="6944692733090228304">Vnesli ste geslo na spletnem mestu, ki ga ne upravlja: <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Zaradi zaščite računa gesla ne uporabljajte za druge aplikacije in spletna mesta.</translation>
<translation id="6945221475159498467">Izberi</translation>
<translation id="6948701128805548767">Če si želite ogledati načine prevzema in zahteve, izberite naslov</translation>
@@ -992,6 +1004,7 @@ Dodatne podrobnosti:
&lt;li&gt;Kliknite &lt;strong&gt;Uporabi&lt;/strong&gt; in nato &lt;strong&gt;V redu&lt;/strong&gt;.
&lt;li&gt;Obiščite &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;center za pomoč za Chrome&lt;/a&gt; če želite izvedeti, kako programsko opremo trajno odstranite iz računalnika.
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Upravljanje storitve <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Upravljaj gesla …</translation>
<translation id="7419106976560586862">Pot profila</translation>
<translation id="7437289804838430631">Dodaj podatke o stiku</translation>
@@ -1000,10 +1013,12 @@ Dodatne podrobnosti:
<translation id="7442725080345379071">Svetlo oranžna</translation>
<translation id="7444046173054089907">To spletno mesto je blokirano</translation>
<translation id="7445762425076701745">Identitete strežnika, s katerim ste povezani, ni mogoče v celoti preveriti. S strežnikom ste povezani z uporabo imena, ki je veljavno samo v vašem omrežju, zato zunanji overitelj potrdil ne more preveriti njegovega lastništva. Ker nekateri overitelji potrdil kljub temu izdajajo potrdila za takšna imena, ni mogoče zagotoviti, da ste povezani z želenim spletnim mestom in ne z napadalcem.</translation>
+<translation id="7449109375006139765">pošiljanje sistemskih dnevnikov v strežnik za upravljanje</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Preberite več<ph name="END_LINK" /> o tej težavi.</translation>
<translation id="7455133967321480974">Uporabi globalno privzeto (Blokiraj)</translation>
<translation id="7460618730930299168">Predvajanje se razlikuje od tega, kar ste izbrali. Želite nadaljevati?</translation>
<translation id="7473891865547856676">Ne, hvala</translation>
+<translation id="7475525192983021547">poročanje časovnih obdobij, ko je uporabnik aktiven v napravi</translation>
<translation id="7481312909269577407">Naprej</translation>
<translation id="7485870689360869515">Ni podatkov.</translation>
<translation id="7508255263130623398">Vrnjen ID naprave pravilnika je prazen ali se ne ujema s trenutnim ID-jem naprave</translation>
@@ -1096,6 +1111,7 @@ Dodatne podrobnosti:
<translation id="7995512525968007366">Ni navedeno</translation>
<translation id="800218591365569300">Poskusite zapreti druge zavihke ali programe, da boste tako sprostili pomnilnik.</translation>
<translation id="8009225694047762179">Upravljanje gesel</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Shranjena bosta ta kartica in njen naslov za izstavitev računa. Uporabljali jo boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}one{Shranjene bodo te kartice in njihovi naslovi za izstavitev računa. Uporabljali jih boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}two{Shranjene bodo te kartice in njihovi naslovi za izstavitev računa. Uporabljali jih boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}few{Shranjene bodo te kartice in njihovi naslovi za izstavitev računa. Uporabljali jih boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}other{Shranjene bodo te kartice in njihovi naslovi za izstavitev računa. Uporabljali jih boste lahko, ko boste prijavljeni v račun <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Trenutno ni mogoče vzpostaviti stika s starši. Poskusi znova pozneje.</translation>
<translation id="8025119109950072390">Napadalci na tem spletnem mestu vas lahko z zavajanjem morda pripravijo do tega, da storite kaj nevarnega – denimo, da namestite programsko opremo ali razkrijete osebne podatke (na primer gesla, telefonske številke ali podatke kreditnih kartic).</translation>
<translation id="8034522405403831421">Ta stran je v jeziku <ph name="SOURCE_LANGUAGE" />. Jo želite prevesti v jezik <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Dodatne podrobnosti:
<translation id="8041940743680923270">Uporabi globalno privzeto (Vprašaj)</translation>
<translation id="8042918947222776840">Izbira načina prevzema</translation>
<translation id="8057711352706143257">Programska oprema »<ph name="SOFTWARE_NAME" />« ni pravilno konfigurirana. Običajno težavo odpravite tako, da odstranite programsko opremo »<ph name="SOFTWARE_NAME" />«. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Vaša naprava je konfigurirana za to:</translation>
<translation id="8078141288243656252">Ko je dokument zasukan, pripisovanje ni mogoče</translation>
<translation id="8079031581361219619">Želite znova naložiti spletno mesto?</translation>
<translation id="8088680233425245692">Članka si ni bilo mogoče ogledati.</translation>
@@ -1156,6 +1173,7 @@ Dodatne podrobnosti:
<translation id="8363502534493474904">izklopiti način za letalo</translation>
<translation id="8364627913115013041">Ni nastavljen.</translation>
<translation id="8368476060205742148">Storitve Google Play</translation>
+<translation id="8371889962595521444">Korenska potrdila po meri</translation>
<translation id="8380941800586852976">Nevarno</translation>
<translation id="8381674639488873545">Te bremenitve so lahko enkratne ali ponavljajoče se in morda niso očitne. <ph name="BEGIN_LINK" />Vseeno pokaži<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Tu so prikazani nedavno obiskani zaznamki</translation>
@@ -1165,6 +1183,7 @@ Dodatne podrobnosti:
<translation id="8416694386774425977">Omrežna konfiguracija je neveljavna in je ni mogoče uvoziti.
Dodatne podrobnosti:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Napravo upravlja <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" />, <ph name="SECOND_LABEL" />, <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Spremeni</translation>
<translation id="8428213095426709021">Nastavitve</translation>
@@ -1225,6 +1244,7 @@ Dodatne podrobnosti:
<translation id="8932102934695377596">Ura zaostaja</translation>
<translation id="893332455753468063">Dodajanje imena</translation>
<translation id="8938939909778640821">Sprejete kreditne in predplačniške kartice</translation>
+<translation id="894185898663964645">Skrbnik je konfiguriral korenska potrdila po meri, ki skrbniku morda omogočajo ogled vsebine spletnih mest, ki jih obiščete.</translation>
<translation id="8943282376843390568">Rumenozelena</translation>
<translation id="8957210676456822347">Odobritev prestreznega portala</translation>
<translation id="8968766641738584599">Shrani kartico</translation>
diff --git a/chromium/components/strings/components_strings_sr.xtb b/chromium/components/strings/components_strings_sr.xtb
index 8f98b5f918a..cab0a7ea7ba 100644
--- a/chromium/components/strings/components_strings_sr.xtb
+++ b/chromium/components/strings/components_strings_sr.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Странице на језику <ph name="LANGUAGE" /> неће бити преведене.</translation>
<translation id="2053553514270667976">Поштански број</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 предлог}one{# предлог}few{# предлога}other{# предлога}}</translation>
+<translation id="2068124040035837596">Налогом управља <ph name="ENROLLMENT_DOMAIN" />. То значи да администратор може даљински да конфигурише налог.</translation>
<translation id="2068663545051464999">Отпремљен је ИД извештаја о отказивању <ph name="CRASH_ID" /> (локални контекст: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Опозови</translation>
<translation id="20817612488360358">Подешено је да се користе системска подешавања проксија, али је наведена експлицитна конфигурација проксија.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Овај начин слања није доступан. Испробајте неки други начин.</translation>
<translation id="2396249848217231973">&amp;Опозови брисање</translation>
<translation id="2413528052993050574">Овај сервер не може да докаже да је <ph name="DOMAIN" />; његов безбедносни сертификат ће можда бити опозван. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
+<translation id="244665789865330679">Уређајем и налогом управља <ph name="ENROLLMENT_DOMAIN" />. То значи да администратор може даљински да конфигурише уређај и налог.</translation>
<translation id="2463193859425327265">Промените почетну страницу</translation>
<translation id="2463739503403862330">Попуни</translation>
<translation id="2465655957518002998">Одаберите начин доставе</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Покушали сте да контактирате <ph name="DOMAIN" />, али је издавач опозвао сертификат који је сервер навео. То значи да никако не треба имати поверења у безбедносне акредитиве које је сервер навео. Могуће је да комуницирате са нападачем.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4406896451731180161">резултати претраге</translation>
+<translation id="4406972042435603828">Администратори су инсталирали додатке са великим могућностима.</translation>
<translation id="4408413947728134509">Колачићи (<ph name="NUM_COOKIES" />)</translation>
<translation id="4415426530740016218">Адреса преузимања</translation>
<translation id="4424024547088906515">Овај сервер не може да докаже да је <ph name="DOMAIN" />; Chrome нема поверења у његов безбедносни сертификат. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Нема резултата</translation>
<translation id="4950898438188848926">Дугме за промену картице, притисните Enter да бисте прешли на отворену картицу, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Радње</translation>
+<translation id="495832697253704892">Пријављивање додатка</translation>
<translation id="4958444002117714549">Прошири листу</translation>
<translation id="4974590756084640048">Поново омогући упозорења</translation>
<translation id="4989163558385430922">Прикажи све</translation>
<translation id="4989809363548539747">Ова додатна компонента није подржана</translation>
+<translation id="4996230189582812866">Пријављивање</translation>
<translation id="5002932099480077015">Ако је ова опција омогућена, Chrome ће складиштити копију картице на овом уређају ради бржег попуњавања образаца.</translation>
<translation id="5014174725590676422">Приказује се екран за прво покретање Google помоћника у Chrome-у</translation>
<translation id="5015510746216210676">Назив уређаја:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Држава</translation>
<translation id="5094747076828555589">Овај сервер не може да докаже да је <ph name="DOMAIN" />; Chromium нема поверења у његов безбедносни сертификат. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
<translation id="5095208057601539847">Покрајина</translation>
+<translation id="5098222253617183465">Уређајем управља <ph name="ENROLLMENT_DOMAIN" />, а налогом <ph name="ACCOUNT_DOMAIN" />. То значи да администратори могу да даљински конфигуришу уређај и налог.</translation>
<translation id="5115563688576182185">(64-битни)</translation>
<translation id="5128122789703661928">Сесија са овим називом није доступна за брисање.</translation>
<translation id="5135404736266831032">Управљајте адресама...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Рачунар</translation>
<translation id="5179510805599951267">Није <ph name="ORIGINAL_LANGUAGE" />? Пријавите ову грешку</translation>
<translation id="5190835502935405962">Трака са обележивачима</translation>
+<translation id="5200263511887412697">извештај листе корисника уређаја који су се недавно пријавили</translation>
<translation id="5201306358585911203">Уграђена страница на овој веб-страници наводи:</translation>
<translation id="5205222826937269299">Име је обавезно</translation>
<translation id="5215116848420601511">Начини плаћања и адресе из Google Pay-а</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Овај сајт није доступан</translation>
<translation id="5869522115854928033">Сачуване лозинке</translation>
<translation id="5887400589839399685">Картица је сачувана</translation>
+<translation id="5893718151540690985">да пријављује листу мрежних интерфејса са њиховим типовима и адресе хардвера</translation>
<translation id="5893752035575986141">Прихватају се кредитне картице.</translation>
<translation id="5901630391730855834">Жута</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (синхронизовано)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Измените контакт информације</translation>
<translation id="5967867314010545767">Уклони из историје</translation>
<translation id="5975083100439434680">Умањивање</translation>
+<translation id="5977489021191000276">Уређајем не управља администратор.</translation>
<translation id="5977976211062815271">На овом уређају</translation>
<translation id="598637245381783098">Отварање апликације за плаћање није успело</translation>
<translation id="5989320800837274978">Нису наведени ни фиксни прокси сервери нити URL адреса .pac скрипте.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Нападачи који су на <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> могу да инсталирају обмањујуће апликације које се претварају да су нешто друго или да прикупљају податке који могу да се користе за праћење. <ph name="BEGIN_LEARN_MORE_LINK" />Сазнајте више<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (синхронизовано)</translation>
<translation id="6027201098523975773">Унесите назив</translation>
+<translation id="6033927989869462158">да пријављује статистику о хардверу, на пример, искоришћеност процесора/RAM меморије.</translation>
<translation id="6034000775414344507">Светлосива</translation>
<translation id="6039846035001940113">Ако се проблем и даље јавља, контактирајте власника сајта.</translation>
<translation id="6040143037577758943">Затвори</translation>
@@ -904,6 +914,8 @@
<translation id="6897140037006041989">Кориснички агент</translation>
<translation id="6903319715792422884">Побољшајте Безбедно прегледање слањем <ph name="BEGIN_WHITEPAPER_LINK" />системских информација и садржаја страница<ph name="END_WHITEPAPER_LINK" /> Google-у. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Корисник:</translation>
+<translation id="6934672428414710184">То је име са вашег Google налога</translation>
+<translation id="6939583532829045966">Уређајем управља <ph name="ENROLLMENT_DOMAIN" />. То значи да администратор може даљински да конфигурише уређај.</translation>
<translation id="6944692733090228304">Унели сте лозинку на сајту којим не управља <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Да бисте заштитили налог, не користите лозинку поново у другим апликацијама ни на другим сајтовима.</translation>
<translation id="6945221475159498467">Изабери</translation>
<translation id="6948701128805548767">Да бисте видели начине и захтеве за преузимање, изаберите адресу</translation>
@@ -991,6 +1003,7 @@
&lt;li&gt;Прво кликните на &lt;strong&gt;Apply&lt;/strong&gt; (Примени), па на &lt;strong&gt;OK&lt;/strong&gt; (У реду)
&lt;li&gt;Посетите &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome центар за помоћ&lt;/a&gt; да бисте сазнали како да трајно уклоните софтвер са рачунара
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Управљајте производом <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Управљај лозинкама...</translation>
<translation id="7419106976560586862">Путања профила</translation>
<translation id="7437289804838430631">Додај контакт информације</translation>
@@ -999,10 +1012,12 @@
<translation id="7442725080345379071">Светлонаранџаста</translation>
<translation id="7444046173054089907">Овај сајт је блокиран</translation>
<translation id="7445762425076701745">Није могуће у потпуности потврдити идентитет сервера са којим сте повезани. Повезани сте са сервером који користи назив који је важећи само у вашој мрежи, а којем спољни ауторитет за издавање сертификата не може да провери власништво. Будући да неки ауторитети за издавање сертификата упркос томе издају сертификате за ове називе, ни на који начин не можете да будете сигурни да сте повезани са жељеним веб-сајтом, а не са нападачем.</translation>
+<translation id="7449109375006139765">да шаље системске евиденције на сервер за управљање</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />да сазнате више<ph name="END_LINK" /> о овом проблему.</translation>
<translation id="7455133967321480974">Користи глобалну подразумевану вредност (Блокирај)</translation>
<translation id="7460618730930299168">Приказ се разликује од онога што сте изабрали. Желите ли да наставите?</translation>
<translation id="7473891865547856676">Не, хвала</translation>
+<translation id="7475525192983021547">да пријављује временске периоде када је корисник активан на уређају</translation>
<translation id="7481312909269577407">Проследи</translation>
<translation id="7485870689360869515">Нису пронађени подаци.</translation>
<translation id="7508255263130623398">Враћени ИД уређаја за смернице је празан или се не подудара са актуелним ИД-ом уређаја</translation>
@@ -1095,6 +1110,7 @@
<translation id="7995512525968007366">Није наведено</translation>
<translation id="800218591365569300">Пробајте да затворите друге картице или програме да бисте ослободили меморију.</translation>
<translation id="8009225694047762179">Управљај лозинкама</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Та картица и њена адреса за обрачун ће бити сачуване. Моћи ћете да је користите када сте пријављени на <ph name="USER_EMAIL" />.}one{Те картице и њихове адресе за обрачун ће бити сачуване. Моћи ћете да их користите када сте пријављени на <ph name="USER_EMAIL" />.}few{Те картице и њихове адресе за обрачун ће бити сачуване. Моћи ћете да их користите када сте пријављени на <ph name="USER_EMAIL" />.}other{Те картице и њихове адресе за обрачун ће бити сачуване. Моћи ћете да их користите када сте пријављени на <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Тренутно не можемо да контактирамо родитеље. Пробај поново.</translation>
<translation id="8025119109950072390">Нападачи на овом сајту могу да вас преваре да бисте урадили нешто опасно, на пример, да инсталирате софтвер или откријете личне податке (попут лозинки, бројева телефона или бројева кредитних картица).</translation>
<translation id="8034522405403831421">Језик ове странице је <ph name="SOURCE_LANGUAGE" />. Желите ли да је преведете на <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1105,6 +1121,7 @@
<translation id="8041940743680923270">Користи глобалну подразумевану вредност (Питај)</translation>
<translation id="8042918947222776840">Одаберите начин преузимања</translation>
<translation id="8057711352706143257">Софтвер „<ph name="SOFTWARE_NAME" />“ није правилно конфигурисан. Деинсталирање софтвера „<ph name="SOFTWARE_NAME" />“ обично решава проблем. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Уређај је конфигурисан:</translation>
<translation id="8078141288243656252">Додавање напомене није могуће када је ротиран</translation>
<translation id="8079031581361219619">Желите ли поново да учитате сајт?</translation>
<translation id="8088680233425245692">Прегледање чланка није успело.</translation>
@@ -1155,6 +1172,7 @@
<translation id="8363502534493474904">да искључите режим рада у авиону</translation>
<translation id="8364627913115013041">Није подешено.</translation>
<translation id="8368476060205742148">Google Play услуге</translation>
+<translation id="8371889962595521444">Прилагођени сертификати основног нивоа</translation>
<translation id="8380941800586852976">Опасно</translation>
<translation id="8381674639488873545">Ти трошкови могу да буду једнократни или периодични и можда нису одмах видљиви. <ph name="BEGIN_LINK" />Ипак прикажи<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Недавно посећени обележивачи се приказују овде</translation>
@@ -1164,6 +1182,7 @@
<translation id="8416694386774425977">Конфигурација мреже је неважећа и не може да се увезе.
Додатни детаљи:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Уређајем управља <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Промени</translation>
<translation id="8428213095426709021">Подешавања</translation>
@@ -1225,6 +1244,7 @@
<translation id="8932102934695377596">Сат вам касни</translation>
<translation id="893332455753468063">Додајте име</translation>
<translation id="8938939909778640821">Прихватају се кредитне и припејд картице</translation>
+<translation id="894185898663964645">Администратор је конфигурисао прилагођене сертификате основног нивоа што може да омогући администратору да види садржај веб-сајтова које посећујете.</translation>
<translation id="8943282376843390568">Јаркозелена</translation>
<translation id="8957210676456822347">Овлашћење на улазном порталу</translation>
<translation id="8968766641738584599">Сачувај картицу</translation>
diff --git a/chromium/components/strings/components_strings_sv.xtb b/chromium/components/strings/components_strings_sv.xtb
index adfac1c01db..26011b8dd32 100644
--- a/chromium/components/strings/components_strings_sv.xtb
+++ b/chromium/components/strings/components_strings_sv.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Sidor på <ph name="LANGUAGE" /> översätts inte.</translation>
<translation id="2053553514270667976">ZIP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 förslag}other{# förslag}}</translation>
+<translation id="2068124040035837596">Ditt konto hanteras av <ph name="ENROLLMENT_DOMAIN" />. Det innebär att administratören kan fjärrkonfigurera kontot.</translation>
<translation id="2068663545051464999">Id för den uppladdade felrapporten <ph name="CRASH_ID" /> (Lokala: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Ångra</translation>
<translation id="20817612488360358">Datorns proxyinställningar är inställda på att användas, men det finns också en explicit proxykonfiguration.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Det här fraktalternativet är inte tillgängligt. Testa ett annat alternativ.</translation>
<translation id="2396249848217231973">&amp;Ångra Ta bort</translation>
<translation id="2413528052993050574">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom dess säkerhetscertifikat kan ha återkallats. Detta kan orsakas av en felaktig konfigurering eller att någon spärrar anslutningen.</translation>
+<translation id="244665789865330679">Enheten och kontot hanteras av <ph name="ENROLLMENT_DOMAIN" />. Detta innebär att administratören kan fjärrkonfigurera enheten och kontot.</translation>
<translation id="2463193859425327265">Ändra startsida</translation>
<translation id="2463739503403862330">Fyll i</translation>
<translation id="2465655957518002998">Välj leveranssätt</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Du försökte öppna <ph name="DOMAIN" />, men servern visade ett certifikat som har återkallats av utfärdaren. Det innebär att säkerhetsuppgifterna som servern visar inte är absolut tillförlitliga. Du kanske kommunicerar med en skadlig server.</translation>
<translation id="4378154925671717803">Mobil</translation>
<translation id="4406896451731180161">sökresultat</translation>
+<translation id="4406972042435603828">Administratören har installerat tillägg med funktioner som har vidsträckt påverkan.</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Hämtningsadress</translation>
<translation id="4424024547088906515">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom Chrome inte litar på dess säkerhetscertifikat. Detta kan orsakas av en felaktig konfigurering eller att någon spärrar anslutningen.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Inga resultat</translation>
<translation id="4950898438188848926">Knapp för flikbyte. Tryck på retur för att byta till den öppna fliken <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Åtgärder</translation>
+<translation id="495832697253704892">Tilläggsrapportering</translation>
<translation id="4958444002117714549">Expandera lista</translation>
<translation id="4974590756084640048">Aktivera varningar igen</translation>
<translation id="4989163558385430922">Visa alla</translation>
<translation id="4989809363548539747">Det här pluginprogrammet stöds inte</translation>
+<translation id="4996230189582812866">Rapportering</translation>
<translation id="5002932099480077015">Om alternativet är aktiverat sparar Chrome en kopia av kortet på enheten så att det går snabbare att fylla i formulär.</translation>
<translation id="5014174725590676422">Skärmen vid första användningen av Googe-assistenten i Chrome visas</translation>
<translation id="5015510746216210676">Datornamn:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Stat</translation>
<translation id="5094747076828555589">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom Chromium inte litar på dess säkerhetscertifikat. Detta kan orsakas av en felaktig konfigurering eller att någon spärrar anslutningen.</translation>
<translation id="5095208057601539847">Provins</translation>
+<translation id="5098222253617183465">Enheten hanteras av <ph name="ENROLLMENT_DOMAIN" /> och kontot hanteras av <ph name="ACCOUNT_DOMAIN" />. Detta innebär att administratörerna kan fjärrkonfigurera enheten och kontot.</translation>
<translation id="5115563688576182185">(64 bitar)</translation>
<translation id="5128122789703661928">Sessionen med det här namnet går inte att radera.</translation>
<translation id="5135404736266831032">Hantera adresser …</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Dator</translation>
<translation id="5179510805599951267">Inte på <ph name="ORIGINAL_LANGUAGE" />? Rapportera felet</translation>
<translation id="5190835502935405962">Bokmärkesfältet</translation>
+<translation id="5200263511887412697">rapportera en lista över enhetsanvändare som har loggat in nyligen</translation>
<translation id="5201306358585911203">På en inbäddad sida på den här sidan står det</translation>
<translation id="5205222826937269299">Namn måste anges</translation>
<translation id="5215116848420601511">Betalningsmetoder och adresser som används med Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Webbplatsen kan inte nås</translation>
<translation id="5869522115854928033">Sparade lösenord</translation>
<translation id="5887400589839399685">Kortet har sparats</translation>
+<translation id="5893718151540690985">rapportera en lista över nätverksgränssnitt med typ och maskinvaruadress</translation>
<translation id="5893752035575986141">Kreditkort får användas.</translation>
<translation id="5901630391730855834">Gul</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (synkroniserade)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Redigera kontaktuppgifter</translation>
<translation id="5967867314010545767">Ta bort från historiken</translation>
<translation id="5975083100439434680">Zooma ut</translation>
+<translation id="5977489021191000276">Din enhet hanteras inte av någon administratör.</translation>
<translation id="5977976211062815271">På den här enheten</translation>
<translation id="598637245381783098">Det gick inte att öppna betalningsappen</translation>
<translation id="5989320800837274978">Varken fasta proxyservrar eller en webbadress med PAC-skript har angetts.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Angripare på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> skulle kunna installera bedrägliga appar som inte gör vad de påstås göra eller samla in data som används för att spåra dig. <ph name="BEGIN_LEARN_MORE_LINK" />Läs mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (synkroniserade)</translation>
<translation id="6027201098523975773">Ange ett namn</translation>
+<translation id="6033927989869462158">rapportera maskinvarustatistik, till exempel CPU- och RAM-användning</translation>
<translation id="6034000775414344507">Ljusgrå</translation>
<translation id="6039846035001940113">Kontakta webbplatsens ägare om problemet kvarstår.</translation>
<translation id="6040143037577758943">Stäng</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Användaragent</translation>
<translation id="6903319715792422884">Hjälp oss att förbättra Säker webbsökning genom att låta <ph name="BEGIN_WHITEPAPER_LINK" />viss systeminformation och visst sidinnehåll<ph name="END_WHITEPAPER_LINK" /> skickas automatiskt till Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Användare:</translation>
+<translation id="6934672428414710184">Det här namnet har hämtats från Google-kontot</translation>
+<translation id="6939583532829045966">Enheten hanteras av <ph name="ENROLLMENT_DOMAIN" />. Detta innebär att administratören kan fjärrkonfigurera enheten.</translation>
<translation id="6944692733090228304">Du har angett ditt lösenord på en webbplats som inte hanteras av <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Skydda kontot genom att inte återanvända lösenordet i andra appar och webbplatser.</translation>
<translation id="6945221475159498467">Välj</translation>
<translation id="6948701128805548767">Välj en adress för att visa alternativ för utlämning och krav</translation>
@@ -992,6 +1004,7 @@ Mer information.
&lt;li&gt;Klicka på &lt;strong&gt;Verkställ&lt;/strong&gt; och sedan på &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Besök &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;hjälpcentret för Chrome&lt;/a&gt; om du vill veta mer om hur du tar bort programvaran från datorn permanent
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Hantering av <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Hantera lösenord …</translation>
<translation id="7419106976560586862">Profilsökväg</translation>
<translation id="7437289804838430631">Lägg till kontaktuppgifter</translation>
@@ -1000,10 +1013,12 @@ Mer information.
<translation id="7442725080345379071">Ljusorange</translation>
<translation id="7444046173054089907">Webbplatsen är blockerad</translation>
<translation id="7445762425076701745">Det går inte att fastställa identiteten hos servern som du är ansluten till. Servernamnet som du angav vid anslutningen är bara giltigt inom ditt nätverk och externa certifikatutfärdare kan inte fastställa dess ägarskap. Vissa certifikatutfärdare utfärdar certifikat oavsett namn och därför går det inte att säkerställa att du är ansluten till den avsedda webbplatsen och inte till en skadlig server.</translation>
+<translation id="7449109375006139765">skicka systemloggar till hanteringsservern</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />att läsa mer<ph name="END_LINK" /> om det här problemet.</translation>
<translation id="7455133967321480974">Använd global standardinställning (Blockera)</translation>
<translation id="7460618730930299168">Visningen skiljer sig från den du valde. Vill du fortsätta?</translation>
<translation id="7473891865547856676">Nej tack</translation>
+<translation id="7475525192983021547">rapportera tidsperioder när en användare är aktiv på enheten</translation>
<translation id="7481312909269577407">Framåt</translation>
<translation id="7485870689360869515">Ingen data hittades.</translation>
<translation id="7508255263130623398">Enhets-id för returnerad princip är tomt eller matchar inte nuvarande enhets-id</translation>
@@ -1096,6 +1111,7 @@ Mer information.
<translation id="7995512525968007366">Inte specificerad</translation>
<translation id="800218591365569300">Testa att stänga andra flikar eller program för att frigöra minne.</translation>
<translation id="8009225694047762179">Hantera Lösenord</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Det här kortet och dess faktureringsadress sparas. Du kan använda det när du är inloggad som <ph name="USER_EMAIL" />.}other{De här korten och deras faktureringsadresser sparas. Du kan använda dem när du är inloggad som <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Vi kunde inte nå dina föräldrar just nu. Försök igen.</translation>
<translation id="8025119109950072390">Angripare på den här webbplatsen kan lura dig att göra något farligt, till exempel installera programvara eller lämna ut personliga uppgifter (som lösenord, telefonnummer eller kreditkortsuppgifter).</translation>
<translation id="8034522405403831421">Den här sidan är skriven på <ph name="SOURCE_LANGUAGE" />. Vill du översätta den till <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Mer information.
<translation id="8041940743680923270">Använd global standardinställning (Fråga)</translation>
<translation id="8042918947222776840">Välj hämtningsalternativ</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> har inte konfigurerats korrekt. Ofta hjälper det att avinstallera <ph name="SOFTWARE_NAME" />. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Enheten har konfigurerats att</translation>
<translation id="8078141288243656252">Det går inte att annotera när dokumentet har roterats</translation>
<translation id="8079031581361219619">Vill du läsa in webbplatsen igen?</translation>
<translation id="8088680233425245692">Det gick inte att visa artikeln.</translation>
@@ -1156,6 +1173,7 @@ Mer information.
<translation id="8363502534493474904">inaktivera flygplansläget</translation>
<translation id="8364627913115013041">Inte angiven.</translation>
<translation id="8368476060205742148">Google Play-tjänster</translation>
+<translation id="8371889962595521444">Anpassade rotcertifikat</translation>
<translation id="8380941800586852976">Farlig</translation>
<translation id="8381674639488873545">Debiteringen kan göras en gång eller återkommande och det behöver inte framgå tydligt att detta händer. <ph name="BEGIN_LINK" />Visa ändå<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Dina senast besökta bokmärken visas här</translation>
@@ -1165,6 +1183,7 @@ Mer information.
<translation id="8416694386774425977">Nätverkskonfigurationen är ogiltig och kunde inte importeras.
Mer information:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Enheten hanteras av <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Ändra</translation>
<translation id="8428213095426709021">Inställningar</translation>
@@ -1226,6 +1245,7 @@ Mer information:
<translation id="8932102934695377596">Klockan går efter</translation>
<translation id="893332455753468063">Lägg till namn</translation>
<translation id="8938939909778640821">Godkända kreditkort och förbetalda kort</translation>
+<translation id="894185898663964645">Administratören har konfigurerat anpassade rotcertifikat. Det kan innebära att administratören ser innehållet på de webbplatser du besöker.</translation>
<translation id="8943282376843390568">Limegrön</translation>
<translation id="8957210676456822347">Auktorisering av infångstportal</translation>
<translation id="8968766641738584599">Spara kortet</translation>
diff --git a/chromium/components/strings/components_strings_sw.xtb b/chromium/components/strings/components_strings_sw.xtb
index d4049212bf0..8054d11c065 100644
--- a/chromium/components/strings/components_strings_sw.xtb
+++ b/chromium/components/strings/components_strings_sw.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Haitatafsiri kurasa za <ph name="LANGUAGE" />.</translation>
<translation id="2053553514270667976">Msimbo wa eneo</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{Pendekezo 1}other{Mapendekezo #}}</translation>
+<translation id="2068124040035837596">Akaunti yako inadhibitiwa na <ph name="ENROLLMENT_DOMAIN" />. Hii inamaanisha kwamba msimamizi wako anaweza kuweka mipangilio kwenye akaunti yako kwa mbali.</translation>
<translation id="2068663545051464999">Kitambulisho cha Ripoti Iliyopakiwa ya Kuacha Kufanya Kazi <ph name="CRASH_ID" /> (Maudhui ya Ndani: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Tendua</translation>
<translation id="20817612488360358">Mipangilio ya mfumo ya proksi imewekwa ili kutumiwa lakini usanidi dhahiri wa proksi pia umebainishwa.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Mbinu hii ya usafirishaji haipatikani. Jaribu mbinu tofauti.</translation>
<translation id="2396249848217231973">Tendua kufuta</translation>
<translation id="2413528052993050574">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; huenda cheti chake cha usalama kimebatilishwa. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.</translation>
+<translation id="244665789865330679">Akaunti na kifaa chako kinadhibitiwa na<ph name="ENROLLMENT_DOMAIN" />. Hii inamaanisha kwamba msimamizi wako anaweza kuweka mipangilio ya akaunti na kifaa chako kwa mbali.</translation>
<translation id="2463193859425327265">Badilisha Ukurasa wa Kwanza</translation>
<translation id="2463739503403862330">Jaza</translation>
<translation id="2465655957518002998">Chagua Njia ya Kusafirisha</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Ulijaribu kufikia <ph name="DOMAIN" />, lakini cheti kilichowasilishwa na seva kimebatilishwa na mtoaji wacho. Huku ni kumaanisha kuwa stakabadhi za usalama zilizowasilishwa na seva hii hazifai kuaminiwa kabisa. Huenda ukawa unawasiliana na mshabulizi.</translation>
<translation id="4378154925671717803">Simu</translation>
<translation id="4406896451731180161">matokeo ya utafutaji</translation>
+<translation id="4406972042435603828">Wasimamizi wako wamesakinisha viendelezi thabiti.</translation>
<translation id="4408413947728134509">Vidakuzi <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Anwani ya Mahali pa Kuchukulia Bidhaa</translation>
<translation id="4424024547088906515">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama hakiaminiwi na Chrome. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Hakuna matokeo yoyote yaliyopatikana</translation>
<translation id="4950898438188848926">Kitufe cha kubadilisha kichupo, bonyeza Enter ili uende kwenye kichupo cha kufungua, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Vitendo</translation>
+<translation id="495832697253704892">Kuripoti viendelezi</translation>
<translation id="4958444002117714549">Panua orodha</translation>
<translation id="4974590756084640048">Onyesha maonyo tena</translation>
<translation id="4989163558385430922">Angalia vyote</translation>
<translation id="4989809363548539747">Programu jalizi hii haitumiki</translation>
+<translation id="4996230189582812866">Kuripoti</translation>
<translation id="5002932099480077015">Ikiwashwa, Chrome itahifadhi nakala ya kadi yako kwenye kifaa hiki kwa ajili ya kujaza fomu haraka zaidi.</translation>
<translation id="5014174725590676422">Inaonyesha skrini ya haraka ya programu ya Mratibu wa Google katika Chrome</translation>
<translation id="5015510746216210676">Jina la Mashine:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Jimbo</translation>
<translation id="5094747076828555589">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama hakiaminiwi na Chromium. Hii inaweza kusababishwa na kusanidi kusikofaa au mvamizi kuingilia muunganisho wako.</translation>
<translation id="5095208057601539847">Mkoa</translation>
+<translation id="5098222253617183465">Kifaa chako kinadhibitiwa na <ph name="ENROLLMENT_DOMAIN" /> na akaunti yako inadhibitiwa na <ph name="ACCOUNT_DOMAIN" />. Hii inamaanisha kwamba wasimamizi wako wanaweza kuweka mipangilio kwenye kifaa na akaunti yako kwa mbali.</translation>
<translation id="5115563688576182185">(biti 64)</translation>
<translation id="5128122789703661928">Huruhusiwi kufuta kipindi kilicho na jina hili.</translation>
<translation id="5135404736266831032">Dhibiti anwani...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Mashine</translation>
<translation id="5179510805599951267">Haiko katika <ph name="ORIGINAL_LANGUAGE" />? Ripoti hitilafu hii</translation>
<translation id="5190835502935405962">Sehemu ya Alamisho</translation>
+<translation id="5200263511887412697">ripoti orodha ya watumiaji wa kifaa walioingia katika akaunti hivi majuzi</translation>
<translation id="5201306358585911203">Ukurasa uliopachikwa kwenye ukurasa huu unasema</translation>
<translation id="5205222826937269299">Jina linahitajika</translation>
<translation id="5215116848420601511">Njia za kulipa na anwani zinazotumia Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Imeshindwa kufungua tovuti hii</translation>
<translation id="5869522115854928033">Manenosiri yaliyohifadhiwa</translation>
<translation id="5887400589839399685">Kadi imehifadhiwa</translation>
+<translation id="5893718151540690985">ripoti orodha ya violesura vya mitandao pamoja na aina na anwani za maunzi husika.</translation>
<translation id="5893752035575986141">Kadi za mikopo zinakubaliwa.</translation>
<translation id="5901630391730855834">Manjano</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (imesawazishwa)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Badilisha Maelezo ya Mawasiliano</translation>
<translation id="5967867314010545767">Ondoa kwenye historia</translation>
<translation id="5975083100439434680">Fifiza</translation>
+<translation id="5977489021191000276">Kifaa chako hakidhibiwi na msimamizi.</translation>
<translation id="5977976211062815271">Kwenye kifaa hiki</translation>
<translation id="598637245381783098">Imeshindwa kufungua programu ya kulipa</translation>
<translation id="5989320800837274978">Siyo seva proksi za kudumu wala URL ya hati ya .pac zimebainishwa.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Wavamizi walio kwenye <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> wanaweza kusakinisha programu za udanganyifu zinazojifanya kuwa kitu kingine au kukusanya data inayoweza kutumika kukufuatilia. <ph name="BEGIN_LEARN_MORE_LINK" />Pata maelezo zaidi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (imesawazishwa)</translation>
<translation id="6027201098523975773">Andika jina</translation>
+<translation id="6033927989869462158">ripoti takwimu za maunzi kama vile matumizi ya CPU au RAM</translation>
<translation id="6034000775414344507">Kijivu Isiyokolea</translation>
<translation id="6039846035001940113">Ikiwa tatizo litaendelea, wasiliana na mmiliki wa tovuti.</translation>
<translation id="6040143037577758943">Funga</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Programu ya Mtumiaji</translation>
<translation id="6903319715792422884">Tusaidie tuboreshe huduma ya Kuvinjari Salama kwa kutuma baadhi ya <ph name="BEGIN_WHITEPAPER_LINK" />maudhui ya ukurasa na maelezo ya mfumo<ph name="END_WHITEPAPER_LINK" /> kwa Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Mtumiaji:</translation>
+<translation id="6934672428414710184">Jina hili linatoka kwenye Akaunti yako ya Google</translation>
+<translation id="6939583532829045966">Kifaa chako kinadhibitiwa na <ph name="ENROLLMENT_DOMAIN" />. Hii inamaanisha kwamba msimamizi wako anaweza kuweka mipangilio ya kifaa chako kwa mbali.</translation>
<translation id="6944692733090228304">Uliweka nenosiri lako kwenye tovuti ambayo haisimamiwi na <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Ili kulinda akaunti yako, usitumie tena nenosiri lako kwenye programu na tovuti zingine.</translation>
<translation id="6945221475159498467">Chagua</translation>
<translation id="6948701128805548767">Chagua anwani ili uone mbinu za kuchukua na mahitaji</translation>
@@ -990,6 +1002,7 @@
&lt;li&gt;Bofya &lt;strong&gt;Tumia&lt;/strong&gt;, kisha ubofye &lt;strong&gt;SAWA&lt;/strong&gt;
&lt;li&gt;Tembelea &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Kituo cha usaidizi wa Chrome&lt;/a&gt; ili upate maelezo zaidi kuhusu jinsi ya kuondoa kabisa programu kwenye kompyuta yako
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Usimamizi wa <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Dhibiti Manenosiri…</translation>
<translation id="7419106976560586862">Kijia cha Maelezo mafupi</translation>
<translation id="7437289804838430631">Ongeza Maelezo ya Mawasiliano</translation>
@@ -998,10 +1011,12 @@
<translation id="7442725080345379071">Chungwa Isiyokolea</translation>
<translation id="7444046173054089907">Tovuti hii imezuiwa</translation>
<translation id="7445762425076701745">Utambulisho wa seva ambayo umejiunga kwayo hauwezi kuhalalishwa kikamilifu. Umeunganishwa kwenye seva kwa kutumia jina ambalo ni halali tu katika mtandao wako, ambalo mamlaka ya cheti cha nje hayana njia ya kuhalalisha umiliki wake. Kama baadhi ya mamlaka ya cheti yatatoa vyeti vya majina haya bila kujali, hakuna njia ya kuhakikisha umeunganishwa kwenye tovuti inayohitajika na sio mshambulizi.</translation>
+<translation id="7449109375006139765">tuma kumbukumbu za mfumo kwenye seva ya kudhibiti</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Pata maelezo zaidi<ph name="END_LINK" /> kuhusu hitilafu hii.</translation>
<translation id="7455133967321480974">Tumia chaguomsingi la duniani (Zuia)</translation>
<translation id="7460618730930299168">Onyesho kwenye skrini ni tofauti na ile uliyochagua. Ungependa kuendelea?</translation>
<translation id="7473891865547856676">La Asante</translation>
+<translation id="7475525192983021547">ripoti vipindi ambavyo mtumiaji anatumia kifaa</translation>
<translation id="7481312909269577407">Mbele</translation>
<translation id="7485870689360869515">Hakuna data iliyopatikana.</translation>
<translation id="7508255263130623398">Kitambulisho cha sera ya kifaa kilichorejeshwa hakina kitu au hakilingani na kitambulisho cha kifaa kilichopo</translation>
@@ -1094,6 +1109,7 @@
<translation id="7995512525968007366">Hakijabainishwa</translation>
<translation id="800218591365569300">Jaribu kufunga vichupo au programu nyingine upate nafasi zaidi.</translation>
<translation id="8009225694047762179">Dhibiti Manenosiri</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Tutahifadhi maelezo ya kadi hii pamoja na anwani yake ya kutuma bili. Utaweza kuitumia utakapoingia katika akaunti ya <ph name="USER_EMAIL" />.}other{Tutahifadhi maelezo ya kadi hizi pamoja na anwani za kutuma bili. Utaweza kuzitumia utakapoingia katika akaunti ya <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Hatukuweza kuwafikia wazazi wako wakati huu. Tafadhali jaribu tena.</translation>
<translation id="8025119109950072390">Wavamizi kwenye tovuti hii wanaweza kukulaghai ili ufanye kitu hatari kama vile kusakinisha programu au kuonyesha maelezo yako binafsi (kwa mfano, manenosiri, nambari za simu au kadi za mikopo).</translation>
<translation id="8034522405403831421">Ukurasa huu ni wa lugha ya <ph name="SOURCE_LANGUAGE" />. Je, ungependa kuutasfiri kuwa <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1104,6 +1120,7 @@
<translation id="8041940743680923270">Tumia chaguomsingi la duniani (Uliza)</translation>
<translation id="8042918947222776840">Chagua Mbinu ya Kuchukua Bidhaa</translation>
<translation id="8057711352706143257">Haikuweka mipangilio ya "<ph name="SOFTWARE_NAME" />" kwa njia sahihi. Kwa kawaida, kuondoa "<ph name="SOFTWARE_NAME" />" hurekebisha tatizo hili. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Kifaa chako kimewekewa mipangilio ya:</translation>
<translation id="8078141288243656252">Huwezi kuweka vidokezo ikiwa imezungushwa</translation>
<translation id="8079031581361219619">Ungependa kupakia upya tovuti?</translation>
<translation id="8088680233425245692">Haikufaulu kuangalia makala.</translation>
@@ -1154,6 +1171,7 @@
<translation id="8363502534493474904">Kuzima hali ya ndegeni</translation>
<translation id="8364627913115013041">Haijawekwa.</translation>
<translation id="8368476060205742148">Huduma za Google Play</translation>
+<translation id="8371889962595521444">Vyeti maalum vya msingi</translation>
<translation id="8380941800586852976">Hatari</translation>
<translation id="8381674639488873545">Gharama hizi zinaweza kuwa za mara moja au za kujirudia na huenda zisiwe za moja kwa moja. <ph name="BEGIN_LINK" />Onyesha tu<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Alamisho ulizotembelea hivi majuzi zitaonekana hapa</translation>
@@ -1161,6 +1179,7 @@
<translation id="8412145213513410671">Mivurugo ( <ph name="CRASH_COUNT" /> )</translation>
<translation id="8412392972487953978">Lazima uingize kaulisiri ile ile mara mbili.</translation>
<translation id="8416694386774425977">Mipangilio ya mtandao si sahihi na haikuweza kupakiwa. Maelezo ya ziada: <ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Kifaa kinadhibitiwa na <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Badilisha</translation>
<translation id="8428213095426709021">Mipangilio</translation>
@@ -1222,6 +1241,7 @@
<translation id="8932102934695377596">Saa yako iko nyuma</translation>
<translation id="893332455753468063">Ongeza Jina</translation>
<translation id="8938939909778640821">Kadi za mikopo na za kulipia awali zinazokubaliwa</translation>
+<translation id="894185898663964645">Msimamizi wako ameweka mipangilio ya vyeti maalum vya msingi, hatua ambayo inaweza kumruhusu msimamizi aone maudhui ya tovuti unazotembelea.</translation>
<translation id="8943282376843390568">Chokaa</translation>
<translation id="8957210676456822347">Uidhinishaji wa Ukurasa wa Wavuti</translation>
<translation id="8968766641738584599">Hifadhi kadi</translation>
diff --git a/chromium/components/strings/components_strings_ta.xtb b/chromium/components/strings/components_strings_ta.xtb
index 847a593fbd9..cc850441ab4 100644
--- a/chromium/components/strings/components_strings_ta.xtb
+++ b/chromium/components/strings/components_strings_ta.xtb
@@ -22,7 +22,7 @@
<translation id="1103523840287552314">எப்போதும் இந்த மொழியை மொழிபெயர் <ph name="LANGUAGE" /></translation>
<translation id="1107591249535594099">இது தேர்ந்தெடுக்கப்பட்டால், விரைவாக படிவங்களை நிரப்புவதற்காக, Chrome இந்த கார்டின் பிரதியை சாதனத்தில் சேமிக்கும்.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" />க்கான அனுமதியைத் தேர்ந்தெடுக்கவும்</translation>
-<translation id="1111153019813902504">சமீபத்திய புத்தகக்குறிகள்</translation>
+<translation id="1111153019813902504">சமீபத்திய புக்மார்க்குகள்</translation>
<translation id="1113869188872983271">&amp;மறுவரிசைப்படுத்தலைச் செயல்தவிர்</translation>
<translation id="1125573121925420732">இணையதளங்கள் தங்கள் பாதுகாப்பைப் புதுப்பிக்கும் போது, எச்சரிக்கைகளைக் காண்பிப்பது வழக்கம் தான். இந்த நிலை விரைவில் மேம்படும்.</translation>
<translation id="1126551341858583091">அகச் சேமிப்பகத்தில் <ph name="CRASH_SIZE" /> அளவு உள்ளது.</translation>
@@ -173,7 +173,7 @@
<translation id="194030505837763158"><ph name="LINK" /> க்குச் செல்க</translation>
<translation id="1945968466830820669">உங்கள் நிறுவனத்தின் கணக்கிற்கான அணுகலை நீங்கள் இழக்கக்கூடும் அல்லது அடையாளத் திருட்டை எதிர்கொள்ளக்கூடும். இப்போதே உங்கள் கடவுச்சொல்லை மாற்றும்படி Chromium பரிந்துரைக்கிறது.</translation>
<translation id="1948773908305951926">ஏற்கப்படும் ப்ரீபெய்டு கார்டுகள்</translation>
-<translation id="1962204205936693436"><ph name="DOMAIN" /> புத்தகக்குறிகள்</translation>
+<translation id="1962204205936693436"><ph name="DOMAIN" /> புக்மார்க்குகள்</translation>
<translation id="1973335181906896915">தொடராக்க பிழை</translation>
<translation id="1974060860693918893">மேம்பட்டவை</translation>
<translation id="1978555033938440688">நிலைப்பொருளின் பதிப்பு</translation>
@@ -186,6 +186,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" /> மொழியில் உள்ள பக்கங்கள் மொழிபெயர்க்கப்படாது.</translation>
<translation id="2053553514270667976">ஜிப் குறியீடு</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 பரிந்துரை}other{# பரிந்துரைகள்}}</translation>
+<translation id="2068124040035837596">உங்கள் கணக்கை <ph name="ENROLLMENT_DOMAIN" /> நிர்வகிக்கிறது. அதாவது உங்கள் நிர்வாகி உங்கள் கணக்கைத் தொலைநிலையிலிருந்து உள்ளமைக்க முடியும்.</translation>
<translation id="2068663545051464999">பதிவேற்றப்பட்ட சிதைவு அறிக்கை ஐடி <ph name="CRASH_ID" /> (அகச் சூழல்: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">செயல்தவிர்</translation>
<translation id="20817612488360358">கணினி ப்ராக்ஸி அமைப்புகள் பயன்படுத்த அமைக்கப்பட்டுள்ளது. வெளிப்படையான ப்ராக்ஸி உள்ளமைவும் குறிப்பிடப்பட்டுள்ளது.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">இந்த ஷிப்பிங் முறை இல்லை. வேறு முறையைப் பயன்படுத்திப் பார்க்கவும்.</translation>
<translation id="2396249848217231973">&amp;நீக்குதலைச் செயல்தவிர்</translation>
<translation id="2413528052993050574">இது <ph name="DOMAIN" /> தான் என்பதை இந்தச் சேவையகம் உறுதிப்படுத்தவில்லை; இதன் பாதுகாப்புச் சான்றிதழ் திரும்பப்பெறப்பட்டிருக்கலாம். இது தவறான உள்ளமைவால் ஏற்பட்டிருக்கலாம் அல்லது தீங்கிழைப்பவர் உங்கள் இணைப்பில் குறுக்கிட்டிருக்கலாம்.</translation>
+<translation id="244665789865330679">உங்கள் சாதனத்தையும் கணக்கையும் <ph name="ENROLLMENT_DOMAIN" /> நிர்வகிக்கிறது. அதாவது உங்கள் நிர்வாகி இவற்றைத் தொலைநிலையிலிருந்து உள்ளமைக்க முடியும்.</translation>
<translation id="2463193859425327265">முகப்புப் பக்கத்தை மாற்று</translation>
<translation id="2463739503403862330">நிரப்பு</translation>
<translation id="2465655957518002998">டெலிவரி முறையைத் தேர்வு செய்</translation>
@@ -389,7 +391,7 @@
<translation id="337363190475750230">விடுவித்தது</translation>
<translation id="3377188786107721145">கொள்கையை அலசுவதில் பிழை</translation>
<translation id="3380365263193509176">அறியப்படாத பிழை</translation>
-<translation id="3380864720620200369">கிளையன்ட் ஐடி:</translation>
+<translation id="3380864720620200369">கிளையண்ட் ஐடி:</translation>
<translation id="3387261909427947069">கட்டண முறைகள்</translation>
<translation id="3391030046425686457">டெலிவரி முகவரி</translation>
<translation id="3395827396354264108">பிக்அப் முறை</translation>
@@ -557,6 +559,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> ஐ அடைய முயற்சி செய்தீர்கள். ஆனால் சேவையகம் வழங்கிய சான்றிதழானது அதன் வழங்குநரால் நிராகரிக்கப்பட்டது. அதாவது, சேவையகம் வழங்கிய பாதுகாப்பு நம்பிக்கைச்சான்றுகளை நிச்சயமாக எக்காரணத்தைக்கொண்டும் நம்பக்கூடாது. போலியான ஒன்றுடன் நீங்கள் தகவல் பரிமாற்றம் செய்துகொண்டிருக்கக்கூடும்.</translation>
<translation id="4378154925671717803">மொபைல்</translation>
<translation id="4406896451731180161">தேடல் முடிவுகள்</translation>
+<translation id="4406972042435603828">சக்திவாய்ந்த திறன்களுள்ள நீட்டிப்புகளை உங்கள் நிர்வாகிகள் நிறுவியுள்ளனர்.</translation>
<translation id="4408413947728134509">குக்கீகள் (<ph name="NUM_COOKIES" />)</translation>
<translation id="4415426530740016218">பிக்அப் முகவரி</translation>
<translation id="4424024547088906515">இது <ph name="DOMAIN" /> தான் என்பதை இந்தச் சேவையகம் உறுதிப்படுத்தவில்லை; இதன் பாதுகாப்புச் சான்றிதழை Chrome நம்பவில்லை. இது தவறான உள்ளமைவால் ஏற்பட்டிருக்கலாம் அல்லது தீங்கிழைப்பவர் உங்கள் இணைப்பில் குறுக்கிட்டிருக்கலாம்.</translation>
@@ -628,10 +631,12 @@
<translation id="4943872375798546930">முடிவுகள் இல்லை</translation>
<translation id="4950898438188848926"><ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /> தாவலைத் திறக்க, ‘தாவல்’ மாற்ற பட்டனைத் தட்டி, ‘எண்டர்’ பட்டனை அழுத்தவும்</translation>
<translation id="495170559598752135">செயல்கள்</translation>
+<translation id="495832697253704892">நீட்டிப்பு குறித்து அறிக்கையளித்தல்</translation>
<translation id="4958444002117714549">பட்டியலை விரி</translation>
<translation id="4974590756084640048">எச்சரிக்கைகளை மீண்டும் இயக்கு</translation>
<translation id="4989163558385430922">எல்லாம் காட்டு</translation>
<translation id="4989809363548539747">இந்தச் செருகுநிரல் ஆதரிக்கப்படவில்லை</translation>
+<translation id="4996230189582812866">அறிக்கையளித்தல்</translation>
<translation id="5002932099480077015">இயக்கப்பட்டால், விரைவாகப் படிவத்தை நிரப்ப உங்கள் கார்டின் நகலை இச்சாதனத்தில் Chrome சேமித்து வைக்கும்.</translation>
<translation id="5014174725590676422">’Chromeமில் Google அசிஸ்டண்ட்’ முதன்மைத் திரை காண்பிக்கப்படுகிறது</translation>
<translation id="5015510746216210676">சாதனப் பெயர்:</translation>
@@ -652,6 +657,7 @@
<translation id="5089810972385038852">மாநிலம்</translation>
<translation id="5094747076828555589">இது <ph name="DOMAIN" /> தான் என்பதை இந்தச் சேவையகம் உறுதிப்படுத்தவில்லை; இதன் பாதுகாப்புச் சான்றிதழை Chromium நம்பவில்லை. இது தவறான உள்ளமைவால் ஏற்பட்டிருக்கலாம் அல்லது தீங்கிழைப்பவர் உங்கள் இணைப்பில் குறுக்கிட்டிருக்கலாம்.</translation>
<translation id="5095208057601539847">பிராந்தியம்</translation>
+<translation id="5098222253617183465">உங்கள் சாதனத்தை <ph name="ENROLLMENT_DOMAIN" /> நிர்வகிக்கிறது, உங்கள் கணக்கை <ph name="ACCOUNT_DOMAIN" /> நிர்வகிக்கிறது. உங்கள் சாதனத்தையும் கணக்கையும் உங்கள் நிர்வாகிகள் தொலைநிலையிலிருந்து உள்ளமைக்க முடியும்.</translation>
<translation id="5115563688576182185">(64-பிட்)</translation>
<translation id="5128122789703661928">இந்தப் பெயரைக் கொண்ட அமர்வானது நீக்குவதற்குத் தகுதியானதல்ல.</translation>
<translation id="5135404736266831032">முகவரிகளை நிர்வகி...</translation>
@@ -664,6 +670,7 @@
<translation id="5172758083709347301">இயந்திரம்</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> இல் இல்லையா? இந்தப் பிழையை தெரிவிக்கவும்</translation>
<translation id="5190835502935405962">புக்மார்க் பட்டி</translation>
+<translation id="5200263511887412697">பயனர்கள் சமீபத்தில் உள்நுழைந்த சாதனங்களின் அறிக்கைப் பட்டியல்</translation>
<translation id="5201306358585911203">இந்தப் பக்கத்திலுள்ள உட்பொதிக்கப்பட்ட பக்கம் தெரிவிப்பது:</translation>
<translation id="5205222826937269299">பெயர் தேவை</translation>
<translation id="5215116848420601511">Google Payவைப் பயன்படுத்தும் கட்டண முறைகளும் முகவரிகளும்</translation>
@@ -765,6 +772,7 @@
<translation id="5869405914158311789">இந்தத் தளத்தை அணுக முடியவில்லை</translation>
<translation id="5869522115854928033">சேமிக்கப்பட்ட கடவுச்சொற்கள்</translation>
<translation id="5887400589839399685">கார்டு சேமிக்கப்பட்டது</translation>
+<translation id="5893718151540690985">வகைகள் மற்றும் வன்பொருள் முகவரிகளுடன் கூடிய நெட்வொர்க் இடைமுகங்களின் பட்டியலை அறிக்கையளிக்கும்</translation>
<translation id="5893752035575986141">கிரெடிட் கார்டுகள் ஏற்கப்படுகின்றன.</translation>
<translation id="5901630391730855834">மஞ்சள்</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (ஒத்திசைக்கப்பட்டது)</translation>
@@ -778,6 +786,7 @@
<translation id="5967592137238574583">தொடர்புத் தகவலைத் திருத்தவும்</translation>
<translation id="5967867314010545767">வரலாற்றிலிருந்து அகற்று</translation>
<translation id="5975083100439434680">சிறிதாக்கு</translation>
+<translation id="5977489021191000276">உங்கள் சாதனம் நிர்வாகியால் நிர்வகிக்கப்படவில்லை.</translation>
<translation id="5977976211062815271">இந்தச் சாதனத்தில்</translation>
<translation id="598637245381783098">பேமெண்ட் பயன்பாட்டைத் திறக்க முடியவில்லை</translation>
<translation id="5989320800837274978">ப்ராக்ஸி சேவையகம் சரிசெய்யப்படவும் இல்லை .pac ஸ்கிரிப்ட் URL குறிப்பிடப்படவுமில்லை.</translation>
@@ -789,6 +798,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> எனும் தளத்தில் உள்ள தீங்கிழைப்பவர்கள், ஏமாற்றக்கூடிய பயன்பாடுகளை (இவை வேறு ஏதோவொன்றைப் போல போலியாகத் தோற்றமளிக்கும் அல்லது உங்களை டிராக் செய்வதற்குப் பயன்படுத்தக்கூடிய தரவைச் சேகரிக்கும்) நிறுவலாம். <ph name="BEGIN_LEARN_MORE_LINK" />மேலும் அறிக<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (ஒத்திசைக்கப்பட்டன)</translation>
<translation id="6027201098523975773">பெயரை உள்ளிடவும்</translation>
+<translation id="6033927989869462158">CPU/RAM உபயோகம் போன்ற வன்பொருள் புள்ளிவிவரங்களை அறிக்கையளிக்கும்</translation>
<translation id="6034000775414344507">வெளிர் சாம்பல்</translation>
<translation id="6039846035001940113">சிக்கல் தொடர்ந்தால், தள உரிமையாளரைத் தொடர்புகொள்ளவும்.</translation>
<translation id="6040143037577758943">மூடு</translation>
@@ -859,7 +869,7 @@
<translation id="6563469144985748109">இன்னும் உங்கள் நிர்வாகி அனுமதிக்கவில்லை</translation>
<translation id="6569060085658103619">நீட்டிப்புப் பக்கத்தைப் பார்க்கிறீர்கள்</translation>
<translation id="6579990219486187401">வெளிர் பிங்க் நிறம்</translation>
-<translation id="6596325263575161958">குறியாக்க விருப்பங்கள்</translation>
+<translation id="6596325263575161958">என்கோடர் விருப்பங்கள்</translation>
<translation id="6604181099783169992">நகர்வு அல்லது ஒளி உணர்விகள்</translation>
<translation id="6624427990725312378">தொடர்புத் தகவல்</translation>
<translation id="6626291197371920147">சரியான கார்டு எண்ணைச் சேர்க்கவும்</translation>
@@ -897,9 +907,11 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6891596781022320156">கொள்கையின் நிலை ஆதரிக்கப்படவில்லை.</translation>
<translation id="6895330447102777224">கார்டு உறுதிசெய்யப்பட்டது</translation>
-<translation id="6897140037006041989">பயனர் முகவர்</translation>
+<translation id="6897140037006041989">பயனர் ஏஜெண்ட்</translation>
<translation id="6903319715792422884">Googleளுக்குச் சில <ph name="BEGIN_WHITEPAPER_LINK" />சாதனத் தகவல்களையும் பக்க உள்ளடக்கத்தையும்<ph name="END_WHITEPAPER_LINK" /> அனுப்புவதன் மூலம் பாதுகாப்பான உலாவலை மேம்படுத்த உதவுங்கள். <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">பயனர்:</translation>
+<translation id="6934672428414710184">இந்தப் பெயர் உங்கள் ‘Google கணக்கிலிருந்து’ பெறப்பட்டது</translation>
+<translation id="6939583532829045966">உங்கள் சாதனத்தை <ph name="ENROLLMENT_DOMAIN" /> நிர்வகிக்கிறது. அதாவது உங்கள் நிர்வாகி உங்கள் சாதனத்தைத் தொலைநிலையிலிருந்து உள்ளமைக்க முடியும்.</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> நிர்வகிக்காத ஒரு தளத்தில் உங்கள் கடவுச்சொல்லை உள்ளிட்டுள்ளீர்கள். உங்கள் கணக்கைப் பாதுகாக்க, பிற ஆப்ஸிலும் தளங்களிலும் உங்கள் கடவுச்சொல்லை மீண்டும் பயன்படுத்த வேண்டாம்.</translation>
<translation id="6945221475159498467">தேர்ந்தெடு</translation>
<translation id="6948701128805548767">பிக்அப் முறைகளையும் தேவைகளையும் பார்க்க, முகவரியைத் தேர்ந்தெடுக்கவும்</translation>
@@ -987,6 +999,7 @@
&lt;li&gt;&lt;strong&gt;பயன்படுத்து&lt;/strong&gt; என்பதைக் கிளிக் செய்து, &lt;strong&gt;சரி&lt;/strong&gt; என்பதைக் கிளிக் செய்யவும்
&lt;li&gt;உங்கள் கம்ப்யூட்டரிலிருந்து மென்பொருளை நிரந்தரமாக அகற்றுவது எப்படி என்பதை அறிய, &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome உதவி மையம்&lt;/a&gt; என்பதற்குச் செல்லவும்
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> நிர்வாகம்</translation>
<translation id="7416351320495623771">கடவுச்சொற்களை நிர்வகி…</translation>
<translation id="7419106976560586862">சுயவிவரப் பாதை</translation>
<translation id="7437289804838430631">தொடர்புத் தகவலைச் சேர்</translation>
@@ -995,10 +1008,12 @@
<translation id="7442725080345379071">வெளிர் ஆரஞ்சு</translation>
<translation id="7444046173054089907">இந்தத் தளம் தடுக்கப்பட்டது</translation>
<translation id="7445762425076701745">நீங்கள் இணைந்துள்ள சேவையகத்தின் அடையாளத்தை முழுமையாகச் சரிபார்க்க முடியவில்லை. உங்கள் நெட்வொர்க்கில் மட்டுமே செல்லுபடியாகும் பெயரைப் பயன்படுத்தி சேவையகத்துடன் இணைந்துள்ளீர்கள். இதன் உரிமையை ஒரு வெளிப்புற சான்றிதழ் மையம் உறுதிப்படுத்த முடியாது. சில சான்றிதழ் மையங்கள், இந்தப் பெயர்களுக்கும் சான்றிதழ்களை வழங்கும் என்பதால், நீங்கள் நினைத்த வலைப்பக்கத்துடனே இணைந்துள்ளீர்கள் என்பதையும் ஏதேனும் மோசடி தளத்துடன் இணையவில்லை என்பதையும் உறுதிப்படுத்த எந்த வழியும் இல்லை.</translation>
+<translation id="7449109375006139765">நிர்வகிப்புச் சேவையகத்திற்கு சிஸ்டம் பதிவுகளை அனுப்பும்</translation>
<translation id="7451311239929941790">இந்தச் சிக்கல் குறித்து <ph name="BEGIN_LINK" />மேலும் அறிக<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">முழுமையான இயல்புநிலையைப் பயன்படுத்து (தடு)</translation>
<translation id="7460618730930299168">திரையிலுள்ள உள்ளடக்கமும் நீங்கள் தேர்ந்தெடுத்த உள்ளடக்கமும் மாறுபடுகின்றன. தொடரவா?</translation>
<translation id="7473891865547856676">வேண்டாம் நன்றி</translation>
+<translation id="7475525192983021547">சாதனத்தை ஒரு பயனர் பயன்படுத்தும் காலஅளவுகளைப் பற்றி அறிக்கையளிக்கும்</translation>
<translation id="7481312909269577407">அடுத்த பக்கம்</translation>
<translation id="7485870689360869515">தரவு எதுவும் இல்லை.</translation>
<translation id="7508255263130623398">கிடைத்த பாலிசி சாதன ஐடி காலியாக உள்ளது அல்லது தற்போதைய சாதன ஐடியுடன் பொருந்தவில்லை</translation>
@@ -1091,6 +1106,7 @@
<translation id="7995512525968007366">குறிப்பிடப்படவில்லை</translation>
<translation id="800218591365569300">பிற தாவல்கள் அல்லது நிரல்களை மூடி, நினைவகத்தைக் காலியாக்கவும்.</translation>
<translation id="8009225694047762179">கடவுச்சொற்களை நிர்வகி</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{இந்தக் கார்டும் அதன் பில்லிங் முகவரியும் சேமிக்கப்படும். <ph name="USER_EMAIL" /> இல் உள்நுழைந்திருக்கும்போது இதைப் பயன்படுத்தலாம்.}other{இந்தக் கார்டுகளும் அவற்றின் பில்லிங் முகவரிகளும் சேமிக்கப்படும். <ph name="USER_EMAIL" /> இல் உள்நுழைந்திருக்கும்போது இவற்றைப் பயன்படுத்தலாம்.}}</translation>
<translation id="8012647001091218357">தற்போது எங்களால் உங்கள் பெற்றோர்களைத் தொடர்புகொள்ள முடியவில்லை. மீண்டும் முயற்சிக்கவும்.</translation>
<translation id="8025119109950072390">இந்தத் தளத்தில் உள்ள ஹேக்கர்கள், உங்களை ஏமாற்றி, மென்பொருளை நிறுவுவது அல்லது தனிப்பட்ட தகவலை (எடுத்துக்காட்டாக, கடவுச்சொற்கள், ஃபோன் எண்கள் அல்லது கிரெடிட் கார்டுகள்) வெளிப்படுத்துவது போன்ற உங்களுக்கு ஆபத்தை விளைவிக்கும் செயல்களைச் செய்ய வைக்கலாம்.</translation>
<translation id="8034522405403831421">இந்தப் பக்கம் <ph name="SOURCE_LANGUAGE" /> மொழியில் உள்ளது. இதை <ph name="TARGET_LANGUAGE" /> க்கு மொழிபெயர்க்கவா?</translation>
@@ -1101,6 +1117,7 @@
<translation id="8041940743680923270">முழுமையான இயல்புநிலையைப் பயன்படுத்து (கேள்)</translation>
<translation id="8042918947222776840">பிக்அப் முறையைத் தேர்வு செய்</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" மென்பொருள் சரியாக உள்ளமைக்கப்படவில்லை. வழக்கமாக, "<ph name="SOFTWARE_NAME" />"ஐ நிறுவல் நீக்கினால் சிக்கல் சரியாகிவிடும். <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">உங்கள் சாதனம் இவற்றுக்கு உள்ளமைக்கப்பட்டுள்ளது:</translation>
<translation id="8078141288243656252">சுழற்றப்பட்டுள்ளபோது ஆவணத்தில் விரிவுரையைச் சேர்க்க முடியாது</translation>
<translation id="8079031581361219619">தளத்தை மீண்டும் ஏற்றவா?</translation>
<translation id="8088680233425245692">கட்டுரையைக் காட்டுவதில் தோல்வி.</translation>
@@ -1151,15 +1168,17 @@
<translation id="8363502534493474904">விமானப் பயன்முறையை முடக்குதல்</translation>
<translation id="8364627913115013041">அமைக்கப்படவில்லை.</translation>
<translation id="8368476060205742148">Google Play சேவைகள்</translation>
+<translation id="8371889962595521444">பிரத்தியேகமான முதன்மை சான்றிதழ்கள்</translation>
<translation id="8380941800586852976">ஆபத்தானது</translation>
<translation id="8381674639488873545">இந்தக் கட்டணங்கள் ஒருமுறை அல்லது தொடர்ந்து வசூலிக்கப்படலாம், அவை வெளிப்படையாகத் தெரிவிக்கப்படாமல் இருக்கலாம். <ph name="BEGIN_LINK" />எனினும் காண்பி<ph name="END_LINK" /></translation>
-<translation id="8382348898565613901">நீங்கள் சமீபத்தில் பார்வையிட்ட புத்தகக்குறிகள் இங்கே தோன்றும்</translation>
+<translation id="8382348898565613901">நீங்கள் சமீபத்தில் பார்வையிட்ட புக்மார்க்குகள் இங்கே தோன்றும்</translation>
<translation id="8398259832188219207">சிதைவு அறிக்கை பதிவேற்றப்பட்ட தேதி: <ph name="UPLOAD_TIME" /></translation>
<translation id="8412145213513410671">செயலிழப்புகள் (<ph name="CRASH_COUNT" />)</translation>
<translation id="8412392972487953978">நீங்கள் கண்டிப்பாக ஒரே கடவுச்சொற்றொடரை இரு முறை உள்ளிட வேண்டும்.</translation>
<translation id="8416694386774425977">நெட்வொர்க் உள்ளமைவு தவறானது மேலும் அதை இறக்குமதி செய்ய முடியவில்லை.
கூடுதல் விவரங்கள்:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">சாதன நிர்வாகி: <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">மாற்று</translation>
<translation id="8428213095426709021">அமைப்புகள்</translation>
@@ -1205,7 +1224,7 @@
<translation id="8790007591277257123">&amp;நீக்குதலை மீண்டும் செய்</translation>
<translation id="8792621596287649091"><ph name="ORG_NAME" /> கணக்கிற்கான அணுகலை நீங்கள் இழக்கக்கூடும் அல்லது அடையாளத் திருட்டை எதிர்கொள்ளக்கூடும். இப்போதே உங்கள் கடவுச்சொல்லை மாற்றும்படி Chromium பரிந்துரைக்கிறது.</translation>
<translation id="8800988563907321413">உங்கள் அருகிலுள்ளவற்றுக்கான பரிந்துரைகள் இங்கே தோன்றும்</translation>
-<translation id="8820817407110198400">புத்தகக்குறிகள்</translation>
+<translation id="8820817407110198400">புக்மார்க்குகள்</translation>
<translation id="883848425547221593">மற்ற புக்மார்க்குகள்</translation>
<translation id="884264119367021077">ஷிப்பிங் முகவரி</translation>
<translation id="884923133447025588">திரும்பப்பெறுதல் செயல்முறை காணப்படவில்லை.</translation>
@@ -1220,6 +1239,7 @@
<translation id="8932102934695377596">உங்கள் கடிகாரம் மிகவும் பின்தங்கி இருக்கிறது</translation>
<translation id="893332455753468063">பெயரைச் சேர்க்கவும்</translation>
<translation id="8938939909778640821">ஏற்கப்படும் கிரெடிட் மற்றும் ப்ரீபெய்டு கார்டுகள்</translation>
+<translation id="894185898663964645">பிரத்தியேகமான முதன்மை சான்றிதழ்களை உங்கள் நிர்வாகி உள்ளமைத்துள்ளார், இதன் மூலம் நீங்கள் பார்வையிடும் இணையதளங்களின் உள்ளடக்கங்களை நிர்வாகியால் பார்க்க முடியும்.</translation>
<translation id="8943282376843390568">சுண்ணாம்பு நிறம்</translation>
<translation id="8957210676456822347">கேப்டிவ் போர்டல் அங்கீகாரம்</translation>
<translation id="8968766641738584599">கார்டைச் சேமி</translation>
diff --git a/chromium/components/strings/components_strings_te.xtb b/chromium/components/strings/components_strings_te.xtb
index 9455ff30805..f365f78af72 100644
--- a/chromium/components/strings/components_strings_te.xtb
+++ b/chromium/components/strings/components_strings_te.xtb
@@ -20,14 +20,14 @@
<translation id="1089439967362294234">పాస్‌వర్డ్‌ని మార్చు</translation>
<translation id="109743633954054152">Chrome సెట్టింగ్‌లలో పాస్‌వర్డ్‌లను నిర్వహించండి</translation>
<translation id="1103523840287552314">ఎల్లప్పుడూ <ph name="LANGUAGE" />ను అనువదించు</translation>
-<translation id="1107591249535594099">ఎంచుకున్నట్లయితే, Chrome వేగవంతమైన ఫారమ్ పూరింపు కోసం ఈ పరికరంలో మీ కార్డ్ కాపీని నిల్వ చేస్తుంది.</translation>
+<translation id="1107591249535594099">ఎంచుకున్నట్లయితే, మరింత వేగవంతమైన ఫారమ్ పూరింపు కోసం Chrome మీ కార్డ్ కాపీని ఈ పరికరంలో నిల్వ చేస్తుంది.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> కోసం అనుమతిని ఎంచుకోండి</translation>
<translation id="1111153019813902504">ఇటీవలి బుక్‌మార్క్‌లు</translation>
<translation id="1113869188872983271">&amp;మళ్లీ క్రమం చేయడాన్ని రద్దు చేయి</translation>
-<translation id="1125573121925420732">వెబ్‌సైట్‌ల భద్రతను అప్‌డేట్ చేస్తున్నప్పుడు హెచ్చరికలు కనిపించడం సాధారణమే. ఇది త్వరలోనే మెరుగుపరచబడుతుంది.</translation>
+<translation id="1125573121925420732">వెబ్‌సైట్‌ల యొక్క భద్రతను అప్‌డేట్ చేస్తున్నప్పుడు హెచ్చరికలు కనిపించడం సాధారణమే. ఇది త్వరలోనే మెరుగుపరచబడుతుంది.</translation>
<translation id="1126551341858583091">స్థానిక నిల్వలో పరిమాణం <ph name="CRASH_SIZE" />.</translation>
<translation id="112840717907525620">విధాన కాష్ సరిపోయింది</translation>
-<translation id="1150979032973867961">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా స‌ర్టిఫికెట్‌ను మీ కంప్యూటర్ ఆపరేటింగ్ సిస్టమ్ విశ్వసించలేదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడి చేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="1150979032973867961">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రాన్ని మీ కంప్యూటర్ ఆపరేటింగ్ సిస్టమ్ విశ్వసించలేదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
<translation id="1151972924205500581">పాస్‌వర్డ్ అవసరం</translation>
<translation id="1152921474424827756"><ph name="URL" /> యొక్క <ph name="BEGIN_LINK" />కాష్ చేయబడిన కాపీ<ph name="END_LINK" />ని యాక్సెస్ చేయండి</translation>
<translation id="1156303062776767266">మీరు స్థానిక లేదా షేర్ చేసిన ఫైల్‌ను చూస్తున్నారు</translation>
@@ -95,7 +95,7 @@
<translation id="1484290072879560759">షిప్పింగ్ చిరునామాను ఎంచుకోండి</translation>
<translation id="1501859676467574491">మీ Google ఖాతా నుండి కార్డ్‌లను చూపండి</translation>
<translation id="1506687042165942984">ఈ పేజీ యొక్క సేవ్ చేసిన (అంటే పాతది) కాపీని చూపుతుంది.</translation>
-<translation id="1507202001669085618">&lt;p&gt;ఆన్‌లైన్‌కు వెళ్లడం కంటే ముందు సైన్ ఇన్ చేయాల్సిన అవసరం ఉన్న Wi-Fi పోర్టల్‌ను మీరు ఉపయోగిస్తున్నట్లయితే మీకు ఈ ఎర్రర్ కనిపిస్తుంది.&lt;/p&gt;
+<translation id="1507202001669085618">&lt;p&gt;ఆన్‌లైన్‌కు వెళ్లగలిగే ముందు సైన్ ఇన్ చేయాల్సిన అవసరం ఉన్న Wi-Fi పోర్టల్‌ను మీరు ఉపయోగిస్తున్నట్లయితే మీకు ఈ ఎర్రర్ కనిపిస్తుంది.&lt;/p&gt;
&lt;p&gt;ఎర్రర్‌ను పరిష్కరించడానికి, మీరు తెరవాలనుకుంటున్న పేజీలో &lt;strong&gt;కనెక్ట్ చేయి&lt;/strong&gt;ని నొక్కండి.&lt;/p&gt;</translation>
<translation id="1517433312004943670">ఫోన్ నంబర్ అవసరం</translation>
<translation id="1517500485252541695">ఆమోదించబడిన క్రెడిట్ మరియు డెబిట్ కార్డ్‌లు</translation>
@@ -108,8 +108,9 @@
<translation id="1549470594296187301">ఈ ఫీచర్‌ను ఉపయోగించడానికి జావాస్క్రిప్ట్ తప్పనిసరిగా ప్రారంభించాలి.</translation>
<translation id="1555130319947370107">నీలం</translation>
<translation id="1559528461873125649">అటువంటి ఫైల్ లేదా డైరెక్టరీ లేదు</translation>
-<translation id="1559572115229829303">&lt;p&gt;మీ పరికరం తేదీ మరియు సమయం (<ph name="DATE_AND_TIME" />) తప్పుగా ఉన్నందున <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />కి ప్రైవేట్ కనెక్షన్ ఏర్పాటు చేయడం సాధ్యపడదు.&lt;/p&gt;
- &lt;p&gt;దయచేసి &lt;strong&gt;సెట్టింగ్‌లు&lt;/strong&gt; యాప్ యొక్క &lt;strong&gt;సాధారణం&lt;/strong&gt; విభాగంలో తేదీ మరియు సమయాన్ని సర్దుబాటు చేయండి.&lt;/p&gt;</translation>
+<translation id="1559572115229829303">&lt;p&gt;మీ పరికరం తేదీ మరియు సమయం తప్పుగా (<ph name="DATE_AND_TIME" />) ఉన్నందున, <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" />కు ప్రైవేట్ కనెక్షన్ ఏర్పాటు చేయడం సాధ్యపడలేదు.&lt;/p&gt;
+
+ &lt;p&gt;&lt;strong&gt;సెట్టింగ్‌లు&lt;/strong&gt; యాప్ యొక్క &lt;strong&gt;సాధారణం&lt;/strong&gt; విభాగంలో తేదీ మరియు సమయాన్ని దయచేసి సర్దుబాటు చేయండి.&lt;/p&gt;</translation>
<translation id="1581080074034554886">CVC</translation>
<translation id="1583429793053364125">ఈ వెబ్ పేజీని ప్రదర్శిస్తున్నప్పుడు ఏదో తప్పు జరిగింది.</translation>
<translation id="1592005682883173041">స్థానిక డేటా యాక్సెస్</translation>
@@ -124,12 +125,12 @@
<translation id="1640244768702815859"><ph name="BEGIN_LINK" />సైట్ యొక్క హోమ్‌పేజీని సందర్శించడం<ph name="END_LINK" /> ప్రయత్నించండి.</translation>
<translation id="1644574205037202324">చరిత్ర</translation>
<translation id="1645368109819982629">ప్రోటోకాల్‌కు మద్దతు లేదు</translation>
-<translation id="1655462015569774233">{1,plural, =1{ఇది <ph name="DOMAIN" /> అని ఈ సర్వర్ నిరూపించలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం గడువు నిన్న ముగిసింది. తప్పుగా కాన్ఫిగర్ చేసినందున లేదా దాడిచేసేవారు మీ కనెక్షన్‌కు అంతరాయం కలిగించినందున ఇలా జరిగి ఉండవచ్చు. మీ కంప్యూటర్ గడియారం ప్రస్తుతం <ph name="CURRENT_DATE" />కి సెట్ చేయబడింది. అది సరిగ్గా ఉందా? సరిగ్గా లేకుంటే, మీరు సిస్టమ్ గడియారాన్ని సరిచేసి, ఆపై ఈ పేజీని రిఫ్రెష్ చేయాలి.}other{ఇది <ph name="DOMAIN" /> అని ఈ సర్వర్ నిరూపించలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం గడువు # రోజుల క్రితం ముగిసింది. తప్పుగా కాన్ఫిగర్ చేసినందున లేదా దాడిచేసేవారు మీ కనెక్షన్‌కు అంతరాయం కలిగించినందున ఇలా జరిగి ఉండవచ్చు. మీ కంప్యూటర్ గడియారం ప్రస్తుతం <ph name="CURRENT_DATE" />కి సెట్ చేయబడింది. అది సరిగ్గా ఉందా? సరిగ్గా లేకుంటే, మీరు సిస్టమ్ గడియారాన్ని సరిచేసి, ఆపై ఈ పేజీని రిఫ్రెష్ చేయాలి.}}</translation>
+<translation id="1655462015569774233">{1,plural, =1{ఈ సర్వర్ ఇది <ph name="DOMAIN" /> అని నిరూపించలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం గడువు నిన్న ముగిసింది. తప్పుగా కాన్ఫిగర్ చేసినందున లేదా దాడిచేసేవారు మీ కనెక్షన్‌కు అంతరాయం కలిగించినందున ఇలా జరిగి ఉండవచ్చు. మీ కంప్యూటర్ గడియారం ప్రస్తుతం <ph name="CURRENT_DATE" />కు సెట్ చేయబడింది. అది సరిగ్గా ఉందా? సరిగ్గా లేకుంటే, మీరు సిస్టమ్ గడియారాన్ని సరిచేసి, ఆపై ఈ పేజీని రీఫ్రెష్ చేయాలి.}other{ఈ సర్వర్ ఇది <ph name="DOMAIN" /> అని నిరూపించలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం గడువు # రోజుల క్రితం ముగిసింది. తప్పుగా కాన్ఫిగర్ చేసినందున లేదా దాడిచేసేవారు మీ కనెక్షన్‌కు అంతరాయం కలిగించినందున ఇలా జరిగి ఉండవచ్చు. మీ కంప్యూటర్ గడియారం ప్రస్తుతం <ph name="CURRENT_DATE" />కు సెట్ చేయబడింది. అది సరిగ్గా ఉందా? సరిగ్గా లేకుంటే, మీరు సిస్టమ్ గడియారాన్ని సరిచేసి, ఆపై ఈ పేజీని రీఫ్రెష్ చేయాలి.}}</translation>
<translation id="1656489000284462475">పికప్</translation>
<translation id="1662550410081243962">చెల్లింపు పద్ధతులను సేవ్ చేసి, పూరించండి</translation>
<translation id="1663943134801823270">కార్డ్‌లు మరియు చిరునామాలు Chrome నుండి పొందినవి. మీరు <ph name="BEGIN_LINK" />సెట్టింగ్‌లు<ph name="END_LINK" />లో వాటిని నిర్వహించవచ్చు.</translation>
<translation id="1671391448414634642">ఇప్పటి నుండి <ph name="SOURCE_LANGUAGE" /> భాషలో ఉన్న పేజీలు <ph name="TARGET_LANGUAGE" /> భాషలోకి అనువదించబడతాయి.</translation>
-<translation id="1676269943528358898"><ph name="SITE" /> సాధారణంగా మీ సమాచారాన్ని రక్షించడానికి ఎన్‌క్రిప్షన్‌ను ఉపయోగిస్తుంది. Google Chrome ఈసారి <ph name="SITE" />కు కనెక్ట్ చేయడానికి ప్రయత్నించినప్పుడు, వెబ్‌సైట్ అసాధారణ మరియు తప్పు ఆధారాలు అని ప్రతిస్పందించింది. దాడి చేసే వ్యక్తి <ph name="SITE" />గా వ్యవహరించి మోసగించడానికి ప్రయత్నిస్తున్నప్పుడు లేదా Wi-Fi సైన్-ఇన్ స్క్రీన్ కనెక్షన్‌కు అంతరాయం కలిగించినప్పుడు ఇలా జరగవచ్చు. Google Chrome, డేటా వినిమయం జ‌ర‌గ‌క‌ ముందే కనెక్షన్‌ను ఆపివేసినందున మీ సమాచారం ఇప్పటికీ సురక్షితంగానే ఉంది.</translation>
+<translation id="1676269943528358898"><ph name="SITE" /> సాధారణంగా మీ సమాచారాన్ని రక్షించడానికి ఎన్‌క్రిప్ష‌న్‌ను ఉపయోగిస్తుంది. Google Chrome ఈసారి <ph name="SITE" />కు కనెక్ట్ చేయడానికి ప్రయత్నించినప్పుడు, వెబ్‌సైట్ అసాధారణ మరియు తప్పు ఆధారాలు అని ప్రతిస్పందించింది. దాడి చేసే వ్యక్తి <ph name="SITE" />గా వ్యవహరించి మోసగించడానికి ప్రయత్నిస్తున్నప్పుడు లేదా Wi-Fi సైన్-ఇన్ స్క్రీన్ కనెక్షన్‌కు అంతరాయం కలిగించినప్పుడు ఇలా జరగవచ్చు. Google Chrome డేటా వినిమయం జ‌ర‌గ‌క ముందే కనెక్షన్‌ను ఆపివేసినందున మీ సమాచారం ఇప్పటికీ సురక్షితంగానే ఉంది.</translation>
<translation id="168841957122794586">సర్వర్ ప్రమాణపత్రం బలహీన క్రిప్టోగ్రాఫిక్ కీని కలిగి ఉంది.</translation>
<translation id="1697532407822776718">మీరు సిద్ధంగా ఉన్నారు!</translation>
<translation id="1706954506755087368">{1,plural, =1{ఈ సర్వర్ ఇది <ph name="DOMAIN" /> అని నిరూపించలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం రేపటిది కావచ్చు. తప్పుగా కాన్ఫిగర్ చేసినందున లేదా దాడిచేసేవారు మీ కనెక్షన్‌కు అంతరాయం కలిగించినందున ఇలా జరిగి ఉండవచ్చు.}other{ఈ సర్వర్ ఇది <ph name="DOMAIN" /> అని నిరూపించలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం భవిష్యత్తులో # రోజుల తదుపరిది కావచ్చు. తప్పుగా కాన్ఫిగర్ చేసినందున లేదా దాడిచేసేవారు మీ కనెక్షన్‌కు అంతరాయం కలిగించినందున ఇలా జరిగి ఉండవచ్చు.}}</translation>
@@ -146,9 +147,9 @@
<translation id="1743520634839655729">తర్వాతిసారి మరింత వేగంగా చెల్లించడానికి, మీ కార్డ్, పేరు మరియు బిల్లింగ్ చిరునామాను మీ Google ఖాతాకు మరియు ఈ పరికరానికి సేవ్ చేయండి.</translation>
<translation id="17513872634828108">తెరిచిన ట్యాబ్‍లు</translation>
<translation id="1753706481035618306">పేజీ సంఖ్య</translation>
-<translation id="1763864636252898013">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా స‌ర్టిఫికెట్‌ను మీ పరికర ఆపరేటింగ్ సిస్టమ్ విశ్వసించలేదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడి చేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="1763864636252898013">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రాన్ని మీ పరికర ఆపరేటింగ్ సిస్టమ్ విశ్వసించలేదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Windows నెట్‌వర్క్ సమస్య విశ్లేషణలను అమలు చేయడం ప్రయత్నించండి<ph name="END_LINK" />.</translation>
-<translation id="1783075131180517613">దయచేసి మీ సింక్ రహస్య పదబంధాన్ని అప్‌డేట్ చేయండి.</translation>
+<translation id="1783075131180517613">దయచేసి మీ సింక్‌ ర‌హ‌స్య ప‌ద‌బంధాన్ని అప్‌డేట్ చేయండి.</translation>
<translation id="1787142507584202372">మీ తెరవబడిన ట్యాబ్‌లు ఇక్కడ కనిపిస్తాయి</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1803264062614276815">కార్డుదారుని పేరు</translation>
@@ -157,7 +158,7 @@
<translation id="1834321415901700177">ఈ సైట్ హానికరమైన ప్రోగ్రామ్‌లను కలిగి ఉంది</translation>
<translation id="1839551713262164453">విధాన విలువల క్రమబద్ధీకరణ ఎర్రర్‌లతో విఫలమైంది</translation>
<translation id="1842969606798536927">చెల్లింపు</translation>
-<translation id="1871208020102129563">ప్రాక్సీ స్థిరమైన ప్రాక్సీ సర్వర్‌లను ఉపయోగించడానికి సెట్ చేయబడింది, .pac స్క్రిప్ట్ URLను కాదు.</translation>
+<translation id="1871208020102129563">.pac స్క్రిప్ట్ URLను కాకుండా, స్థిరమైన ప్రాక్సీ సర్వర్‌లను ఉపయోగించేలా ప్రాక్సీ సెట్ చేయబడింది.</translation>
<translation id="1871284979644508959">అవసరమైన ఫీల్డ్</translation>
<translation id="1874765382782611674">ఆమోదించే డెబిట్ కార్డ్‌లు</translation>
<translation id="1875512691959384712">Google ఫారమ్‌లు</translation>
@@ -175,16 +176,17 @@
<translation id="1962204205936693436"><ph name="DOMAIN" /> బుక్‌మార్క్‌లు</translation>
<translation id="1973335181906896915">శ్రేణిగా రూపొందించడంలో ఎర్రర్</translation>
<translation id="1974060860693918893">ఆధునిక</translation>
-<translation id="1978555033938440688">ఫర్మ్‌వేర్ వెర్షన్‌</translation>
+<translation id="1978555033938440688">ఫర్మ్‌వేర్ వెర్షన్</translation>
<translation id="1981206234434200693">Chrome బ్రౌజింగ్ చరిత్ర డేటాని తీసివేయి</translation>
<translation id="2001146170449793414">{COUNT,plural, =1{మరియు మరొకటి}other{మరియు మరో #}}</translation>
<translation id="2003709556000175978">ఇప్పుడే మీ పాస్‌వర్డ్‌ని రీసెట్ చేయండి</translation>
-<translation id="2025186561304664664">ప్రాక్సీ స్వయంచాలకంగా కాన్ఫిగర్ చేయబడేలా సెట్ చేయబడింది.</translation>
+<translation id="2025186561304664664">ప్రాక్సీ ఆటోమేటిక్‌గా కాన్ఫిగర్ చేయబడేలా సెట్ చేయబడింది.</translation>
<translation id="2030481566774242610">మీ ఉద్దేశ్యం <ph name="LINK" />?</translation>
<translation id="2032962459168915086"><ph name="BEGIN_LINK" />ప్రాక్సీ మరియు ఫైర్‌వాల్‌ను తనిఖీ చేయడం<ph name="END_LINK" /></translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> భాషలో ఉన్న పేజీలు అనువదించబడవు.</translation>
<translation id="2053553514270667976">జిప్ కోడ్</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 సూచన}other{# సూచనలు}}</translation>
+<translation id="2068124040035837596">మీ ఖాతా <ph name="ENROLLMENT_DOMAIN" /> ద్వారా నిర్వహించబడుతుంది. దీని ప్రకారం, మీ నిర్వాహకుడు రిమోట్ పద్ధతిలో మీ ఖాతాను కాన్ఫిగర్ చేయవచ్చు.</translation>
<translation id="2068663545051464999">అప్‌లోడ్ చేసిన క్రాష్ నివేదిక ID <ph name="CRASH_ID" /> (స్థానిక సందర్భం: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">చర్య రద్దు</translation>
<translation id="20817612488360358">సిస్టమ్ ప్రాక్సీ సెట్టింగ్‌లు ఉపయోగించడానికి సెట్ చేయబడ్డాయి కానీ స్పష్టమైన ప్రాక్సీ కాన్ఫిగరేషన్ కూడా పేర్కొనబడింది.</translation>
@@ -200,7 +202,7 @@
<translation id="214556005048008348">చెల్లింపును రద్దు చేయి</translation>
<translation id="2147827593068025794">నేపథ్య సమకాలీకరణ</translation>
<translation id="2148613324460538318">కార్డ్‌ని జోడించు</translation>
-<translation id="2154054054215849342">సమకాలీకరణ మీ డొమైన్‌కు అందుబాటులో లేదు</translation>
+<translation id="2154054054215849342">సింక్‌ మీ డొమైన్‌కు అందుబాటులో లేదు</translation>
<translation id="2154484045852737596">కార్డ్‌ను సవరించండి</translation>
<translation id="2166049586286450108">పూర్తి నిర్వాహక యాక్సెస్</translation>
<translation id="2166378884831602661">ఈ సైట్ సురక్షితమైన కనెక్షన్‌ను అందించలేదు</translation>
@@ -222,10 +224,10 @@
<translation id="2283340219607151381">చిరునామాలను సేవ్ చేసి, పూరించండి</translation>
<translation id="2292556288342944218">మీ ఇంటర్నెట్ యాక్సెస్ బ్లాక్ చేయబడింది</translation>
<translation id="2316887270356262533">1 MB కంటే తక్కువ స్థలాన్ని ఖాళీ చేస్తుంది. కొన్ని సైట్‌లను మీరు తర్వాతిసారి సందర్శించేటప్పుడు, అవి మరింత నెమ్మదిగా లోడ్ కావచ్చు.</translation>
-<translation id="2317259163369394535"><ph name="DOMAIN" />కి వినియోగదారు పేరు మరియు పాస్‌వర్డ్ అవసరం.</translation>
+<translation id="2317259163369394535"><ph name="DOMAIN" />కు వినియోగదారు పేరు మరియు పాస్‌వర్డ్ అవసరం.</translation>
<translation id="2317583587496011522">డెబిట్ కార్డ్‌లు ఆమోదించబడతాయి.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, గడువు <ph name="EXPIRATION_DATE_ABBR" />న ముగుస్తుంది</translation>
-<translation id="2337852623177822836">సెట్టింగ్‌ని మీ నిర్వాహకులు నియంత్రిస్తున్నారు</translation>
+<translation id="2337852623177822836">సెట్టింగ్‌ను మీ నిర్వాహకులు నియంత్రిస్తున్నారు</translation>
<translation id="2349790679044093737">VR సెషన్ యాక్టివ్‌లో ఉంది</translation>
<translation id="2354001756790975382">ఇతర బుక్‌మార్క్‌లు</translation>
<translation id="2354430244986887761">Google సురక్షిత బ్రౌజింగ్ ఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />హానికర యాప్‌లను కనుగొంది<ph name="END_LINK" />.</translation>
@@ -242,7 +244,8 @@
<translation id="2392959068659972793">విలువ సెట్ చేయని విధానాలను చూపు</translation>
<translation id="239429038616798445">ఈ రవాణా పద్ధతి అందుబాటులో లేదు. వేరే పద్ధతిని ప్రయత్నించండి.</translation>
<translation id="2396249848217231973">&amp;తొలగించడాన్ని రద్దు చేయి</translation>
-<translation id="2413528052993050574">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం ఉపసంహరించబడి ఉండవచ్చు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="2413528052993050574">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం ఉపసంహరించబడి ఉండవచ్చు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="244665789865330679">మీ పరికరం, ఖాతా <ph name="ENROLLMENT_DOMAIN" /> ద్వారా నిర్వహించబడతాయి. దీని ప్రకారం, మీ నిర్వాహకుడు రిమోట్ పద్ధతిలో మీ పరికరాన్ని, ఖాతాను కాన్ఫిగర్ చేయవచ్చు.</translation>
<translation id="2463193859425327265">హోమ్ పేజీని మార్చు</translation>
<translation id="2463739503403862330">పూరించు</translation>
<translation id="2465655957518002998">బట్వాడా పద్ధతిని ఎంచుకోండి</translation>
@@ -253,7 +256,7 @@
<translation id="248348093745724435">మెషీన్ విధానాలు</translation>
<translation id="2491120439723279231">సర్వర్ యొక్క ప్రమాణపత్రంలో లోపాలు ఉన్నాయి.</translation>
<translation id="2495083838625180221">JSON పార్సర్</translation>
-<translation id="2495093607237746763">ఎంచుకుంటే, Chromium వేగవంతమైన ఫారమ్ పూరింపు కోసం ఈ పరికరంలో మీ కార్డ్ కాపీని నిల్వ చేస్తుంది.</translation>
+<translation id="2495093607237746763">ఎంచుకుంటే, మరింత వేగవంతమైన ఫారమ్ పూరింపు కోసం ఈ పరికరంలో మీ కార్డ్ కాపీని Chromium నిల్వ చేస్తుంది.</translation>
<translation id="2498091847651709837">కొత్త కార్డ్‌ను స్కాన్ చేయండి</translation>
<translation id="2501278716633472235">వెనుకకు వెళ్ళు</translation>
<translation id="2503184589641749290">ఆమోదించబడిన డెబిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు</translation>
@@ -289,7 +292,7 @@
<translation id="2713444072780614174">తెలుపు</translation>
<translation id="2720342946869265578">సమీపం</translation>
<translation id="2721148159707890343">అభ్యర్థన విజయవంతం అయింది</translation>
-<translation id="2728127805433021124">సర్వర్ సర్టిఫికెట్ బలహీన సంతకం అల్గారిథమ్‌ను ఉపయోగించి సంతకం చేయబడింది.</translation>
+<translation id="2728127805433021124">సర్వర్ ప్రమాణపత్రం బలహీన సంతకం అల్గారిథమ్‌ను ఉపయోగించి సంతకం చేయబడింది.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />కనెక్టివిటీ సమస్య విశ్లేషణలను అమలు చేయడం<ph name="END_LINK" /></translation>
<translation id="2738330467931008676">పికప్ చిరునామాను ఎంచుకోండి</translation>
<translation id="2740531572673183784">సరే</translation>
@@ -306,7 +309,7 @@
<translation id="2803306138276472711">Google సురక్షిత బ్రౌజింగ్ ఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />మాల్వేర్‌ను గుర్తించింది<ph name="END_LINK" />. సాధారణంగా సురక్షితమైన వెబ్‌సైట్‌‌లకు కూడా కొన్నిసార్లు మాల్వేర్ సోకుతుంది.</translation>
<translation id="2824775600643448204">చిరునామా మరియు శోధన బార్</translation>
<translation id="2826760142808435982"><ph name="CIPHER" />ను ఉపయోగించి కనెక్షన్ ఎన్‌క్రిప్ట్ చేయ‌బ‌డింది, ప్రామాణీకరించబడింది మరియు <ph name="KX" />ను కీలకమైన పరివర్తన విధానంగా ఉపయోగిస్తుంది.</translation>
-<translation id="2835170189407361413">ఫారమ్‌ను తుడిచివేయి</translation>
+<translation id="2835170189407361413">ఫారమ్‌ను క్లియర్ చేయి</translation>
<translation id="2847118875340931228">అజ్ఞాత విండోని తెరువు</translation>
<translation id="2851634818064021665">ఈ సైట్‌ను సందర్శించడానికి మీకు అనుమతి అవసరం</translation>
<translation id="2856444702002559011">హ్యాకర్‌లు <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> నుండి మీ సమాచారాన్ని దొంగిలించడానికి ప్రయత్నిస్తూ ఉండవచ్చు (ఉదాహరణకు, పాస్‌వర్డ్‌లు, సందేశాలు లేదా క్రెడిట్ కార్డ్‌లు). <ph name="BEGIN_LEARN_MORE_LINK" />మరింత తెలుసుకోండి<ph name="END_LEARN_MORE_LINK" /></translation>
@@ -319,14 +322,14 @@
<translation id="2925673989565098301">బట్వాడా పద్ధతి</translation>
<translation id="2928905813689894207">బిల్లింగ్ చిరునామా</translation>
<translation id="2929525460561903222">{SHIPPING_ADDRESS,plural, =0{<ph name="SHIPPING_ADDRESS_PREVIEW" />}=1{<ph name="SHIPPING_ADDRESS_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_ADDRESSES" />}other{<ph name="SHIPPING_ADDRESS_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_ADDRESSES" />}}</translation>
-<translation id="2941952326391522266">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం <ph name="DOMAIN2" /> నుండి జారీ చేయబడింది. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="2941952326391522266">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం <ph name="DOMAIN2" /> నుండి జారీ చేయబడింది. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
<translation id="2948083400971632585">మీరు సెట్టింగ్‌ల పేజీ నుండి కనెక్షన్ కోసం కాన్ఫిగర్ చేయబడిన ఏ ప్రాక్సీలను అయినా నిలిపివేయవచ్చు.</translation>
<translation id="2955913368246107853">కనుగొను పట్టీని మూసివేయి</translation>
<translation id="2969319727213777354">సురక్షిత కనెక్షన్‌ను ఏర్పాటు చేయడానికి, మీ గడియారాన్ని సరైన సమయానికి సెట్ చేయాలి. ఎందుకంటే వెబ్‌సైట్‌లు వాటిని గుర్తించడానికి ఉపయోగించే ప్రమాణపత్రాలు నిర్దిష్ట కాలవ్యవధుల్లో మాత్రమే చెల్లుబాటు అవుతాయి. మీ పరికరం గడియారం సమయం తప్పుగా ఉన్నందున, Google Chrome ఈ ప్రమాణపత్రాలను ధృవీకరించలేదు.</translation>
<translation id="2972581237482394796">&amp;పునరావృతం</translation>
<translation id="2977665033722899841"><ph name="ROW_NAME" />, ప్రస్తుతం ఎంచుకోబడింది. <ph name="ROW_CONTENT" /></translation>
<translation id="2982481275546140226">డేటాను తీసివేయి</translation>
-<translation id="2985306909656435243">ప్రారంభిస్తే, Chromium వేగవంతమైన ఫారమ్ పూరింపు కోసం ఈ పరికరంలో మీ కార్డ్ కాపీని నిల్వ చేస్తుంది.</translation>
+<translation id="2985306909656435243">ప్రారంభిస్తే, మరింత వేగవంతమైన ఫారమ్ పూరింపు కోసం Chromium మీ కార్డ్ కాపీని ఈ పరికరంలో నిల్వ చేస్తుంది.</translation>
<translation id="2985398929374701810">చెల్లుబాటు అయ్యే చిరునామాని నమోదు చేయండి</translation>
<translation id="2986368408720340940">ఈ పికప్ పద్ధతి అందుబాటులో లేదు. వేరే పద్ధతిని ప్రయత్నించండి.</translation>
<translation id="2991174974383378012">వెబ్‌సైట్‌లతో భాగస్వామ్యం</translation>
@@ -348,10 +351,10 @@
<translation id="3137507986424712703">{COUNT,plural, =0{ఏమీ లేవు}=1{1 ఖాతా సైన్ ఇన్ డేటా}other{# ఖాతాల సైన్ ఇన్ డేటా}}</translation>
<translation id="3145945101586104090">ప్రతిస్పందనను డీకోడ్ చేయడంలో విఫలమైంది</translation>
<translation id="3150653042067488994">తాత్కాలిక సర్వర్ ఎర్రర్</translation>
-<translation id="3154506275960390542">ఈ పేజీలో ఉన్న ఫారమ్‌ని సురక్షితంగా సమర్పించలేకపోవచ్చు. బదిలీ చేయబడే సమయంలో మీరు పంపే డేటాని ఇతరులు వీక్షించవచ్చు లేదా సర్వర్ స్వీకరించే డేటాని మార్చడం కోసం హ్యాకర్‌లు దీనిని సవరించవచ్చు.</translation>
+<translation id="3154506275960390542">ఈ పేజీలో ఉన్న ఫారమ్‌ను సురక్షితంగా సమర్పించలేకపోవచ్చు. బదిలీ చేయబడే సమయంలో మీరు పంపే డేటాను ఇతరులు వీక్షించవచ్చు లేదా సర్వర్ స్వీకరించే డేటాను మార్చడం కోసం హ్యాకర్‌లు దీనిని సవరించవచ్చు.</translation>
<translation id="3157931365184549694">పునరుద్ధరించు</translation>
-<translation id="3162559335345991374">మీరు ఉపయోగిస్తున్న Wi-Fiకి మీరు దాని లాగిన్ పేజీని సందర్శించడం అవసరం.</translation>
-<translation id="3167968892399408617">మీరు అజ్ఞాత ట్యాబ్‌లలో వీక్షించిన పేజీలు మీ అన్ని అజ్ఞాత ట్యాబ్‌లను మూసివేసిన తర్వాత, మీ బ్రౌజర్ చరిత్ర, కుక్కీ స్టోర్ లేదా శోధన చరిత్రలో ఉంచబడవు. మీరు డౌన్‌లోడ్ చేసే ఏవైనా ఫైల్‌లు లేదా మీరు సృష్టించే ఏవైనా బుక్‌మార్క్‌లు అలాగే ఉంచబడతాయి.</translation>
+<translation id="3162559335345991374">మీరు ఉపయోగిస్తున్న Wi-Fi, దాని లాగిన్ పేజీని మీరు సందర్శించాల్సిందిగా కోరవచ్చు.</translation>
+<translation id="3167968892399408617">మీరు అజ్ఞాత ట్యాబ్‌ల్లో వీక్షించిన పేజీలు- మీ అన్ని అజ్ఞాత ట్యాబ్‌లను మూసివేసిన అనంతరం- మీ బ్రౌజర్ చరిత్ర, కుక్కీ స్టోర్ లేదా శోధన చరిత్రలో ఉంచబడవు. మీరు డౌన్‌లోడ్ చేసే ఏవైనా ఫైల్స్ లేదా మీరు సృష్టించే ఏవైనా బుక్‌మార్క్‌లు అలాగే ఉంచబడతాయి.</translation>
<translation id="3169472444629675720">కనుగొను</translation>
<translation id="3174168572213147020">దీవి</translation>
<translation id="3176929007561373547">ప్రాక్సీ సర్వర్ పని చేస్తున్నట్లు నిర్ధారించుకోవడానికి మీ ప్రాక్సీ సెట్టింగ్‌లను తనిఖీ చేయండి లేదా
@@ -362,7 +365,7 @@
<translation id="320323717674993345">చెల్లింపును రద్దు చేయండి</translation>
<translation id="3207960819495026254">బుక్‌మార్క్ చేయబడింది</translation>
<translation id="3209375525920864198">దయచేసి చెల్లుబాటు అయ్యే సెషన్ పేరుని నమోదు చేయండి.</translation>
-<translation id="3225919329040284222">అంతర్నిర్మిత అంచనాలకు సరిపోలని ఒక ధృవీకరణ పత్రాన్ని సర్వర్ సమర్పించింది. మిమ్మల్ని సంరక్షించే దిశగా నిర్దిష్ట, ఉన్నత స్ధాయి భద్రతా వెబ్‌సైట్‌ల కోసం ఈ అంచనాలు చేర్చబడ్డాయి.</translation>
+<translation id="3225919329040284222">అంతర్గత అంచనాలకు సరిపోలని ఒక ధృవీకరణ పత్రాన్ని సర్వర్ సమర్పించింది. మిమ్మల్ని సంరక్షించే దిశగా నిర్దిష్ట, ఉన్నత స్ధాయి భద్రతా వెబ్‌సైట్‌ల కోసం ఈ అంచనాలు చేర్చబడ్డాయి.</translation>
<translation id="3226128629678568754">పేజీని లోడ్ చేయడానికి అవసరమైన డేటాను మళ్లీ సమర్పించడం కోసం 'మళ్లీ లోడ్ చేయి' బటన్ క్లిక్ చేయండి.</translation>
<translation id="3227137524299004712">మైక్రోఫోన్</translation>
<translation id="3228969707346345236">పేజీ ఇప్పటికే <ph name="LANGUAGE" />లో ఉన్నందున అనువాదం విఫలమైంది.</translation>
@@ -402,8 +405,8 @@
<translation id="3427342743765426898">&amp;సవరించడాన్ని పునరావృతం చేయి</translation>
<translation id="342781501876943858">మీరు మీ పాస్‌వర్డ్‌ని ఇతర సైట్‌లలో తిరిగి ఉపయోగించినట్లయితే దీనిని రీసెట్ చేయాల్సిందిగా Chromium సిఫార్సు చేస్తోంది.</translation>
<translation id="3431636764301398940">ఈ కార్డ్‌ను ఈ పరికరానికి సేవ్ చేయి</translation>
-<translation id="3447661539832366887">ఈ పరికర యజమాని డైనోసార్ ఆటను ఆఫ్ చేసారు.</translation>
-<translation id="3447884698081792621">సర్టిఫికేట్‌ని చూపు (<ph name="ISSUER" /> ద్వారా జారీ చేయబడింది)</translation>
+<translation id="3447661539832366887">ఈ పరికర యజమాని డైనోసార్ గేమ్‌ను ఆఫ్ చేసారు.</translation>
+<translation id="3447884698081792621">సర్టిఫికేట్‌ను చూపు (<ph name="ISSUER" /> ద్వారా జారీ చేయబడింది)</translation>
<translation id="3452404311384756672">విరామాన్ని పొందండి:</translation>
<translation id="3461824795358126837">హైలైటర్</translation>
<translation id="3462200631372590220">అధునాతనం దాచు</translation>
@@ -415,7 +418,7 @@
<translation id="3495081129428749620">పేజీలో కనుగొను
<ph name="PAGE_TITLE" /></translation>
<translation id="3498215018399854026">మేము ప్రస్తుతం మీ తల్లి/తండ్రిని సంప్రదించలేకపోయాము. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
-<translation id="3528171143076753409">సర్వర్ యొక్క ప్రమాణ పత్రం నమ్మదగినది కాదు.</translation>
+<translation id="3528171143076753409">సర్వర్ ప్రమాణపత్రం విశ్వసనీయమైనది కాదు.</translation>
<translation id="3528485271872257980">ముదురు గోధుమ రంగు</translation>
<translation id="3530944546672790857">{COUNT,plural, =0{సమకాలీకరించిన పరికరాల్లో కనీసం 1 అంశం}=1{1 అంశం (మరియు సమకాలీకరించిన పరికరాల్లో మరిన్ని)}other{# అంశాలు (మరియు సమకాలీకరించిన పరికరాల్లో మరిన్ని)}}</translation>
<translation id="3539171420378717834">ఈ పరికరంలో ఈ కార్డ్ కాపీని ఉంచు</translation>
@@ -431,7 +434,7 @@
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3614103345592970299">పరిమాణం 2</translation>
<translation id="3615877443314183785">చెల్లుబాటు అయ్యే గడువు ముగింపు తేదీని నమోదు చేయండి</translation>
-<translation id="36224234498066874">బ్రౌజింగ్ డేటాను తొలగించు...</translation>
+<translation id="36224234498066874">బ్రౌజింగ్ డేటాను క్లియర్ చేయి...</translation>
<translation id="362276910939193118">పూర్తి చరిత్రను చూపించు</translation>
<translation id="3623476034248543066">విలువను చూపండి</translation>
<translation id="3630155396527302611">ఇప్పటికే ఇది నెట్‌వర్క్‌ను యాక్సెస్ చేయడానికి అనుమతించబడిన ప్రోగ్రామ్ లాగా జాబితా చేయబడి ఉంటే,
@@ -452,7 +455,7 @@
<translation id="3714780639079136834">మొబైల్ డేటా లేదా Wi-Fiని ఆన్ చేయడం</translation>
<translation id="3715597595485130451">Wi-Fiకి కనెక్ట్ చేయండి</translation>
<translation id="3717027428350673159"><ph name="BEGIN_LINK" />ప్రాక్సీ, ఫైర్‌వాల్ మరియు DNS కాన్ఫిగరేషన్‌ను తనిఖీ చేయడం<ph name="END_LINK" /></translation>
-<translation id="372429172604983730">యాంటీవైరస్, ఫైర్‌వాల్ మరియు వెబ్ ఫిల్టరింగ్ లేదా ప్రాక్సీ సాఫ్ట్‌వేర్ వంటి అప్లికేషన్‌లు ఈ ఎర్రర్‌కు దారితీయవచ్చు.</translation>
+<translation id="372429172604983730">ఈ ఎర్రర్‌కు దారితీసే అప్లికేషన్‌లలో యాంటీవైరస్, ఫైర్‌వాల్ మరియు వెబ్ ఫిల్టరింగ్ లేదా ప్రాక్సీ సాఫ్ట్‌వేర్ ఉండవచ్చు.</translation>
<translation id="3736520371357197498">మీ భద్రతకు వాటిల్లే ఆపదల గురించి మీకు అర్థం అయ్యి ఉంటే, ప్రమాదకరమైన ప్రోగ్రామ్‌లు తీసివేయబడటానికి ముందే <ph name="BEGIN_LINK" />ఈ అసురక్షితమైన సైట్‌ను సందర్శించవచ్చు<ph name="END_LINK" />.</translation>
<translation id="3739623965217189342">మీరు కాపీ చేసిన లింక్</translation>
<translation id="3744899669254331632">మీరు సందర్శించాలనుకుంటున్న <ph name="SITE" /> వెబ్‌సైట్, Chromium ప్రాసెస్ చేయలేని చిందరవందరైన ఆధారాలను పంపినందున ప్రస్తుతం దానిని సందర్శించలేరు. నెట్‌వర్క్ ఎర్రర్‌లు మరియు దాడులు సాధారణంగా తాత్కాలికంగా మాత్రమే ఉంటాయి, కాబట్టి ఈ పేజీ బహుశా తర్వాత పని చేయవచ్చు.</translation>
@@ -472,7 +475,7 @@
<translation id="382518646247711829">మీరు ప్రాక్సీ సర్వర్‌ను ఉపయోగిస్తే...</translation>
<translation id="3828924085048779000">ఖాళీ రహస్య పదబంధం అనుమతించబడదు.</translation>
<translation id="385051799172605136">వెనుకకు</translation>
-<translation id="3858027520442213535">తేదీ మరియు సమయాన్ని అప్‌డేట్ చేయి</translation>
+<translation id="3858027520442213535">తేదీని, సమయాన్ని అప్‌డేట్ చేయి</translation>
<translation id="3884278016824448484">వైరుధ్యమైన పరికరం ఐడెంటిఫైయర్</translation>
<translation id="3885155851504623709">పారిష్</translation>
<translation id="3886446263141354045">మీరు ఈ సైట్‌ను యాక్సెస్ చేయడానికి చేసిన అభ్యర్థన <ph name="NAME" />కి పంపబడింది</translation>
@@ -480,7 +483,7 @@
<translation id="3901925938762663762">కార్డ్ గడువు సమయం ముగిసింది</translation>
<translation id="3909695131102177774"><ph name="LABEL" /> <ph name="ERROR" /></translation>
<translation id="3946209740501886391">ఈ సైట్‌లో ఎల్లప్పుడూ అడగాలి</translation>
-<translation id="3949571496842715403">ఈ సర్వర్ తను <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రంలో విషయ ప్రత్యామ్నాయ పేర్లు పేర్కొనబడలేదు. తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా హ్యాకర్ మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన ఇలా జరిగి ఉండవచ్చు.</translation>
+<translation id="3949571496842715403">ఈ సర్వర్ తను <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రంలో విషయ ప్రత్యామ్నాయ పేర్లు పేర్కొనబడలేదు. తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా హ్యాకర్ మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన ఇలా జరిగి ఉండవచ్చు.</translation>
<translation id="3949601375789751990">మీ బ్రౌజింగ్ చరిత్ర ఇక్కడ కనిపిస్తుంది</translation>
<translation id="3950820424414687140">సైన్ ఇన్</translation>
<translation id="3963721102035795474">పాఠకుని మోడ్</translation>
@@ -495,12 +498,12 @@
<translation id="4058922952496707368">కీ "<ph name="SUBKEY" />": <ph name="ERROR" /></translation>
<translation id="4067947977115446013">చెల్లుబాటు అయ్యే చిరునామాను జోడించండి</translation>
<translation id="4072486802667267160">మీ ఆర్డర్‌ను ప్రాసెస్ చేస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
-<translation id="4075732493274867456">క్లయింట్ మరియు సర్వర్ ఒకే SSL ప్రోటోకాల్ వెర్షన్ లేదా సైఫర్ సూట్‌కు మద్దతివ్వవు.</translation>
-<translation id="4079302484614802869">ప్రాక్సీ కాన్ఫిగరేషన్ స్థిరమైన ప్రాక్సీ సర్వర్‌లను కాకుండా, ఒక .pac స్క్రిప్ట్ URLను ఉపయోగించడానికి సెట్ చేయబడింది.</translation>
+<translation id="4075732493274867456">క్లయింట్ మరియు సర్వర్ ఒకే SSL ప్రోటోకాల్ వెర్ష‌న్‌ లేదా సైఫర్ సూట్‌కు మద్దతివ్వవు.</translation>
+<translation id="4079302484614802869">స్థిరమైన ప్రాక్సీ సర్వర్‌లను కాకుండా, ఒక .pac స్క్రిప్ట్ URLను ఉపయోగించేలా ప్రాక్సీ కాన్ఫిగరేషన్ సెట్ చేయబడింది.</translation>
<translation id="4098354747657067197">ముందు వంచనాత్మక సైట్ ఉంది</translation>
-<translation id="4103249731201008433">పరికరం క్రమ సంఖ్య చెల్లదు</translation>
+<translation id="4103249731201008433">పరికర క్రమ సంఖ్య చెల్లదు</translation>
<translation id="410351446219883937">స్వీయ ప్లే</translation>
-<translation id="4103763322291513355">నిరోధిత జాబితాలో ఉన్న URLల జాబితాను మరియు మీ సిస్టమ్ నిర్వాహకుని ద్వారా అమలు చేయబడిన ఇతర విధానాలను చూడటానికి &lt;strong&gt;chrome://policy&lt;/strong&gt;ని సందర్శించండి.</translation>
+<translation id="4103763322291513355">బ్లాక్‌లిస్ట్‌లో ఉన్న URLల జాబితాను మరియు మీ సిస్టమ్ నిర్వాహకుని ద్వారా అమలు చేయబడిన ఇతర విధానాలను చూడటానికి &lt;strong&gt;chrome://policy&lt;/strong&gt;ని సందర్శించండి.</translation>
<translation id="4110652170750985508">మీ చెల్లింపును సమీక్షించండి</translation>
<translation id="4116663294526079822">ఈ సైట్‌లో ఎల్లప్పుడూ అనుమతించు</translation>
<translation id="4117700440116928470">విధానం పరిధికి మద్దతు లేదు.</translation>
@@ -526,9 +529,9 @@
&lt;/ol&gt;
&lt;h4&gt;2వ దశ: అజ్ఞాత మోడ్‌లో పేజీని తెరవండి (కంప్యూటర్ మాత్రమే)&lt;/h4&gt;
&lt;p&gt;మీరు సందర్శిస్తున్న పేజీని అజ్ఞాత విండోలో తెరవండి.&lt;/p&gt;
- &lt;p&gt;పేజీ తెరుచుకుందంటే, Chrome ఎక్స్‌టెన్షన్ సరిగ్గా పని చేయడం లేదని అర్థం. ఎర్రర్‌ను పరిష్కరించడానికి, ఎక్స్‌టెన్షన్‌ను ఆఫ్ చేయండి.&lt;/p&gt;
+ &lt;p&gt;పేజీ తెరుచుకుంటే, Chrome ఎక్స్‌టెన్షన్ సరిగ్గా పని చేయడం లేదని అర్థం. ఎర్రర్‌ను పరిష్కరించడానికి, ఎక్స్‌టెన్షన్‌ను ఆఫ్ చేయండి.&lt;/p&gt;
&lt;h4&gt;3వ దశ: మీ ఆపరేటింగ్ సిస్టమ్‌ను అప్‌డేట్ చేయండి&lt;/h4&gt;
- &lt;p&gt;మీ పరికరం తాజాగా ఉన్నట్లు నిర్ధారించుకోండి.&lt;/p&gt;
+ &lt;p&gt;మీ పరికరం అప్‌డేట్ అయినట్టు నిర్ధారించుకోండి.&lt;/p&gt;
&lt;h4&gt;4వ దశ: మీ యాంటీవైరస్‌ను తాత్కాలికంగా ఆఫ్ చేయండి&lt;/h4&gt;
&lt;p&gt;"HTTPS రక్షణ" లేదా "HTTPS స్కానింగ్" వంటివి అందించే యాంటీవైరస్‌ సాఫ్ట్‌వేర్‌ను మీరు ఉపయోగిస్తున్నట్లయితే మీకు ఈ ఎర్రర్ కనిపిస్తుంది. Chrome మీకు భద్రతను అందించకుండా యాంటీవైరస్ నివారిస్తోంది.&lt;/p&gt;
&lt;p&gt;సమస్యను పరిష్కరించడానికి, మీ యాంటీవైరస్ సాఫ్ట్‌వేర్‌ను ఆఫ్ చేయండి. సాఫ్ట్‌వేర్‌ను ఆఫ్ చేసిన తర్వాత పేజీ పని చేసినట్లయితే, మీరు సురక్షిత సైట్‌లను ఉపయోగించేటప్పుడు ఈ సాఫ్ట్‌వేర్‌ను ఆఫ్ చేయండి.&lt;/p&gt;
@@ -552,17 +555,18 @@
<translation id="4325863107915753736">కథనాన్ని కనుగొనడం విఫలమైంది</translation>
<translation id="4326324639298822553">మీ గడువు ముగింపు తేదీని తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి</translation>
<translation id="4331708818696583467">సురక్షితం కాదు</translation>
-<translation id="4340982228985273705">ఈ కంప్యూటర్‌ని ఎంటర్‌ప్రైజ్ నిర్వహిస్తున్నట్లు గుర్తించబడలేదు, కనుక Chrome వెబ్‌స్టోర్‌లో హోస్ట్ చేయబడిన ఎక్స్‌టెన్షన్‌లను మాత్రమే విధానం ఆటోమేటిక్‌గా ఇన్‌స్టాల్ చేస్తుంది. Chrome వెబ్‌స్టోర్ అప్‌డేట్ URL ఇది: "<ph name="CWS_UPDATE_URL" />".</translation>
+<translation id="4340982228985273705">ఈ కంప్యూటర్‌ను ఎంటర్‌ప్రైజ్ నిర్వహిస్తున్నట్లు గుర్తించబడలేదు, కాబ‌ట్టి Chrome వెబ్‌స్టోర్‌లో హోస్ట్ చేయబడిన ఎక్స్‌టెన్షన్‌లను మాత్రమే విధానం ఆటోమేటిక్‌గా ఇన్‌స్టాల్ చేస్తుంది. Chrome వెబ్‌స్టోర్ అప్‌డేట్ URL "<ph name="CWS_UPDATE_URL" />".</translation>
<translation id="4346197816712207223">ఆమోదించే క్రెడిట్ కార్డ్‌లు</translation>
<translation id="4356973930735388585">ఈ సైట్‌లోని దాడి చేసేవారు మీ సమాచారాన్ని (ఉదాహరణకు, ఫోటోలు, పాస్‌వర్డ్‌లు, సందేశాలు మరియు క్రెడిట్ కార్డ్‌లు) దొంగిలించడం కోసం లేదా తొలగించడం కోసం మీ కంప్యూటర్‌లో ప్రమాదకరమైన ప్రోగ్రామ్‌లను ఇన్‌స్టాల్ చేయడానికి ప్రయత్నించవచ్చు.</translation>
<translation id="4358461427845829800">చెల్లింపు పద్ధతులను నిర్వహించండి...</translation>
<translation id="4372948949327679948">ఆశిస్తున్న <ph name="VALUE_TYPE" /> విలువ.</translation>
-<translation id="4377125064752653719"><ph name="DOMAIN" />ను చేరుకోవడానికి మీరు ప్రయత్నించారు, కానీ సర్వర్ అందించిన సర్టిఫికెట్ దాన్ని జారీ చేసినవారు రద్దు చేసారు. సర్వర్ అందించిన భద్రత ఆధారాలు ఖచ్చితంగా విశ్వసించబడలేదని దీని అర్థం. మీరు దాడి చేసే వారితో కమ్యూనికేట్ చేస్తూ ఉండవచ్చు.</translation>
+<translation id="4377125064752653719"><ph name="DOMAIN" />ను చేరుకోవడానికి మీరు ప్రయత్నించారు, కానీ సర్వర్ అందించిన ప్రమాణపత్రాన్ని జారీ చేసినవారు రద్దు చేసారు. సర్వర్ అందించిన భద్రత ఆధారాలు ఖచ్చితంగా విశ్వసించబడలేదని దీని అర్థం. మీరు దాడి చేసే వారితో కమ్యూనికేట్ చేస్తూ ఉండవచ్చు.</translation>
<translation id="4378154925671717803">ఫోన్</translation>
<translation id="4406896451731180161">శోధన ఫలితాలు</translation>
+<translation id="4406972042435603828">మీ నిర్వాహకులు శక్తివంతమైన సామర్థ్యాలతో ఎక్స్‌టెన్షన్‌లను ఇన్‌స్టాల్ చేశారు.</translation>
<translation id="4408413947728134509">కుక్కీలు <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">పికప్ చిరునామా</translation>
-<translation id="4424024547088906515">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రాన్ని Chrome విశ్వసించలేదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="4424024547088906515">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రాన్ని Chrome విశ్వసించలేదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
<translation id="4432688616882109544"><ph name="HOST_NAME" /> మీ లాగిన్ ప్రమాణపత్రాన్ని ఆమోదించలేదు లేదా ఏదీ అందించి ఉండకపోవచ్చు.</translation>
<translation id="4434045419905280838">పాప్-అప్‌లు మరియు మళ్లింపులు</translation>
<translation id="443673843213245140">ప్రాక్సీని ఉపయోగించడం ఆపివేయబడింది కానీ స్పష్టమైన ప్రాక్సీ కాన్ఫిగరేషన్ పేర్కొనబడింది.</translation>
@@ -570,7 +574,7 @@
<translation id="4482953324121162758">ఈ సైట్ అనువదించబడదు.</translation>
<translation id="4506176782989081258">ధృవీకరణ ఎర్రర్: <ph name="VALIDATION_ERROR" /></translation>
<translation id="4506599922270137252">సిస్టమ్ నిర్వాహకుడిని సంప్రదించడం</translation>
-<translation id="450710068430902550">నిర్వాహకుడితో భాగస్వామ్యం</translation>
+<translation id="450710068430902550">నిర్వాహకుడితో షేర్‌</translation>
<translation id="4515275063822566619">కార్డ్‌లు, చిరునామాలు- Chrome నుండి, మీ Google ఖాతా (<ph name="ACCOUNT_EMAIL" />) నుండి పొందినవి. మీరు <ph name="BEGIN_LINK" />సెట్టింగ్‌లు<ph name="END_LINK" />లో వాటిని నిర్వహించవచ్చు.</translation>
<translation id="4522570452068850558">వివరాలు</translation>
<translation id="4524805452350978254">కార్డ్‌లను నిర్వహించండి</translation>
@@ -584,9 +588,9 @@
<translation id="4597348597567598915">పరిమాణం 8</translation>
<translation id="4646534391647090355">ఇప్పుడు నన్ను అక్కడకు తీసుకు వెళ్లు</translation>
<translation id="4668929960204016307">,</translation>
-<translation id="467662567472608290">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రంలో లోపాలు ఉన్నాయి. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="467662567472608290">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రంలో లోపాలు ఉన్నాయి. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
<translation id="467809019005607715">Google స్లయిడ్‌లు</translation>
-<translation id="4690462567478992370">చెల్లని స‌ర్టిఫికెట్‌ను ఉపయోగించడాన్ని ఆపివేయి</translation>
+<translation id="4690462567478992370">చెల్లని ప్రమాణపత్రాన్ని ఉపయోగించడాన్ని ఆపివేయి</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4708268264240856090">మీ కనెక్షన్‌కు అంతరాయం ఏర్పడింది</translation>
<translation id="471880041731876836">ఈ సైట్‌ను సందర్శించడానికి మీకు అనుమతి లేదు</translation>
@@ -594,7 +598,7 @@
<translation id="4726672564094551039">విధానాలను మళ్లీ లోడ్ చేయి</translation>
<translation id="4728558894243024398">ప్లాట్‌ఫారమ్</translation>
<translation id="4736825316280949806">Chromiumని పునఃప్రారంభించండి</translation>
-<translation id="473775607612524610">అప్‌డేట్</translation>
+<translation id="473775607612524610">అప్‌డేట్‌</translation>
<translation id="4738601419177586157"><ph name="TEXT" /> శోధన సూచన</translation>
<translation id="4742407542027196863">పాస్‌వర్డ్‌లను నిర్వహించు…</translation>
<translation id="4744603770635761495">అమలు చేయగల పాథ్‌</translation>
@@ -631,11 +635,13 @@
<translation id="4943872375798546930">ఫలితాలు ఏవీ లేవు</translation>
<translation id="4950898438188848926">ట్యాబ్ మార్పు బటన్, తెరిచియున్న ట్యాబ్ <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" />కు మారడానికి ఎంటర్ నొక్కండి</translation>
<translation id="495170559598752135">చర్యలు</translation>
+<translation id="495832697253704892">ఎక్స్‌టెన్ష‌న్‌ నివేదన</translation>
<translation id="4958444002117714549">జాబితాను విస్తరించు</translation>
<translation id="4974590756084640048">హెచ్చరికలను మళ్లీ ప్రారంభించు</translation>
<translation id="4989163558385430922">అన్నీ చూడండి</translation>
-<translation id="4989809363548539747">ఈ ప్లగిన్‌కు మద్దతు లేదు</translation>
-<translation id="5002932099480077015">ప్రారంభిస్తే, వేగవంతమైన ఫారమ్ పూరింపు కోసం ఈ పరికరంలో మీ కార్డ్ కాపీని నిల్వ చేస్తుంది.</translation>
+<translation id="4989809363548539747">ఈ ప్లగ్ఇన్‌‌కు మద్దతు లేదు</translation>
+<translation id="4996230189582812866">నివేదన</translation>
+<translation id="5002932099480077015">ప్రారంభిస్తే, మరింత వేగవంతమైన ఫారమ్ పూరింపు కోసం Chrome మీ కార్డ్ కాపీని ఈ పరికరంలో నిల్వ చేస్తుంది.</translation>
<translation id="5014174725590676422">Chromeలో Google అసిస్టెంట్ మొదటి అమలు స్క్రీన్ చూపబడింది</translation>
<translation id="5015510746216210676">మెషీన్ పేరు:</translation>
<translation id="5018422839182700155">ఈ పేజీని తెరవడం సాధ్యపడదు</translation>
@@ -653,8 +659,9 @@
<translation id="5087286274860437796">ప్రస్తుతం సర్వర్ ప్రమాణపత్రం చెల్లదు.</translation>
<translation id="5087580092889165836">కార్డ్‌ను జోడించు</translation>
<translation id="5089810972385038852">రాష్ట్రం</translation>
-<translation id="5094747076828555589">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రాన్ని Chromium విశ్వసించలేదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="5094747076828555589">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రాన్ని Chromium విశ్వసించలేదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
<translation id="5095208057601539847">ప్రావిన్స్</translation>
+<translation id="5098222253617183465">మీ పరికరం <ph name="ENROLLMENT_DOMAIN" /> ద్వారా నిర్వహించబడుతుంది, అలాగే <ph name="ACCOUNT_DOMAIN" /> ద్వారా మీ ఖాతా నిర్వహించబడుతుంది. దీని ప్రకారం, మీ నిర్వాహకులు రిమోట్ విధానం ద్వారా మీ పరికరం, ఖాతాను కాన్ఫిగర్ చేయవచ్చు .</translation>
<translation id="5115563688576182185">(64-బిట్)</translation>
<translation id="5128122789703661928">ఈ పేరు కలిగిన సెషన్‌ని తొలగించలేరు.</translation>
<translation id="5135404736266831032">చిరునామాలను నిర్వహించండి...</translation>
@@ -667,6 +674,7 @@
<translation id="5172758083709347301">మెషీన్</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" />లో లేదా? ఈ ఎర్రర్‌ను నివేదించండి</translation>
<translation id="5190835502935405962">బుక్‌మార్క్‌ల బార్</translation>
+<translation id="5200263511887412697">ఇటీవల లాగిన్ చేసిన పరికర వినియోగదారుల జాబితాను నివేదించండి</translation>
<translation id="5201306358585911203">ఈ పేజీలోని పొందుపరిచిన పేజీ ఇలా చెబుతోంది</translation>
<translation id="5205222826937269299">పేరు ఆవశ్యకం</translation>
<translation id="5215116848420601511">Google Payని ఉపయోగిస్తున్న చెల్లింపు పద్ధతులు మరియు చిరునామాలు</translation>
@@ -687,13 +695,13 @@
<translation id="5327248766486351172">పేరు</translation>
<translation id="5332219387342487447">షిప్పింగ్ పద్ధతి</translation>
<translation id="5344579389779391559">ఈ పేజీ మీకు డబ్బు ఛార్జీ చేయడానికి ప్రయత్నించవచ్చు</translation>
-<translation id="5355557959165512791"><ph name="SITE" /> యొక్క సర్టిఫికెట్ రద్దు చేయబడినందున మీరు ప్రస్తుతం దీనిని సందర్శించలేరు. నెట్‌వర్క్ ఎర్రర్‌లు మరియు దాడులు సాధారణంగా తాత్కాలికమే, కనుక ఈ పేజీ తర్వాత పని చేయవచ్చు.</translation>
+<translation id="5355557959165512791"><ph name="SITE" /> యొక్క ప్రమాణపత్రం రద్దు చేయబడినందున మీరు ప్రస్తుతం దీన్ని సందర్శించలేరు. నెట్‌వర్క్ లోపాలు మరియు దాడులు సాధారణంగా తాత్కాలికమే, కనుక ఈ పేజీ తర్వాత పని చేయవచ్చు.</translation>
<translation id="536296301121032821">విధాన సెట్టింగ్‌లను నిల్వ చేయడంలో విఫలమైంది</translation>
<translation id="5371425731340848620">కార్డ్‌ని అప్‌డేట్ చేయండి</translation>
<translation id="5377026284221673050">"మీ గడియారం ఆలస్యంగా నడుస్తోంది" లేదా "మీ గడియారం ముందుగా ఉంది" లేదా "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
<translation id="5384855140246857529">మీ కార్డ్‌ల‌ను అన్ని పరికరాలలో ఉపయోగించాలంటే, సైన్ ఇన్ చేసి, సమకాలీకరణను ఆన్ చేయండి.</translation>
<translation id="5386426401304769735">ఈ సైట్ ప్రమాణపత్రం గొలుసులో SHA-1 ఉపయోగించి సంతకం చేసిన ప్రమాణపత్రం ఉంది.</translation>
-<translation id="540969355065856584">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం ప్రస్తుతం చెల్లదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడి చేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="540969355065856584">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం ప్రస్తుతం చెల్లదు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడి చేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
<translation id="5421136146218899937">బ్రౌజింగ్ డేటాను క్లియర్ చేయి...</translation>
<translation id="5430298929874300616">బుక్‌మార్క్‌ను తీసివేయండి</translation>
<translation id="5431657950005405462">మీ ఫైల్ కనుగొనబడలేదు</translation>
@@ -703,10 +711,10 @@
<translation id="5457113250005438886">చెల్లదు</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> మరియు మరో <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
<translation id="5470861586879999274">&amp;సవరించడాన్ని పునరావృతం చేయి</translation>
-<translation id="5481076368049295676">ఈ కంటెంట్ మీ సమాచారాన్ని దొంగిలించగల లేదా తొలగించగల హానికరమైన సాఫ్ట్‌వేర్‌ను మీ పరికరంలో ఇన్‌స్టాల్ చేయడానికి ప్రయత్నించవచ్చు. <ph name="BEGIN_LINK" />ఏదేమైనా స‌రే చూపు<ph name="END_LINK" /></translation>
+<translation id="5481076368049295676">ఈ కంటెంట్ మీ సమాచారాన్ని దొంగిలించగల లేదా తొలగించగల హానికరమైన సాఫ్ట్‌వేర్‌ను మీ పరికరంలో ఇన్‌స్టాల్ చేయడానికి ప్రయత్నించవచ్చు. <ph name="BEGIN_LINK" />ఏదేమైనా చూపు<ph name="END_LINK" /></translation>
<translation id="54817484435770891">చెల్లుబాటు అయ్యే చిరునామాను జోడించండి</translation>
<translation id="5490432419156082418">చిరునామాలు మరియు మరిన్ని</translation>
-<translation id="5492298309214877701">కంపెనీ, సంస్థ లేదా పాఠశాల ఇంట్రానెట్‌లోని ఈ సైట్, బ‌య‌టి వెబ్‌సైట్ కలిగి ఉన్న అదే URLను కలిగి ఉంది.
+<translation id="5492298309214877701">కంపెనీ, సంస్థ లేదా పాఠశాల ఇంట్రానెట్‌లోని ఈ సైట్- బాహ్య వెబ్‌సైట్ కలిగి ఉన్న అదే URLను కలిగి ఉంది.
<ph name="LINE_BREAK" />
మీ సిస్టమ్ నిర్వాహకుడిని సంప్రదించడానికి ప్రయత్నించండి.</translation>
<translation id="549333378215107354">పరిమాణం 3</translation>
@@ -722,7 +730,7 @@
<translation id="5565735124758917034">సక్రియం</translation>
<translation id="5571083550517324815">ఈ చిరునామా నుండి పికప్ చేసుకోవడం సాధ్యం కాదు. వేరే చిరునామాని ఎంచుకోండి.</translation>
<translation id="5571347317547569613">({NUM_COOKIES,plural, =1{1 వినియోగంలో ఉంది}other{# వినియోగంలో ఉన్నాయి}})</translation>
-<translation id="5572851009514199876">దయచేసి Chromeని ప్రారంభించి, దానికి సైన్ ఇన్ చేయండి, అప్పుడు మీకు ఈ సైట్‌ను యాక్సెస్ చేయడానికి అనుమతి ఉందో లేదో Chrome తనిఖీ చేయగలదు.</translation>
+<translation id="5572851009514199876">దయచేసి Chromeను ప్రారంభించి, దానికి సైన్ ఇన్ చేయండి, అప్పుడు ఈ సైట్‌ను యాక్సెస్ చేయడానికి మీకు అనుమతి ఉందో లేదో Chrome తనిఖీ చేయగలదు.</translation>
<translation id="5580958916614886209">మీ గడువు ముగింపు నెలను తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి</translation>
<translation id="5586446728396275693">సేవ్ చేయబడిన చిరునామాలు లేవు</translation>
<translation id="5595485650161345191">చిరునామాను సవరించు</translation>
@@ -768,6 +776,7 @@
<translation id="5869405914158311789">ఈ సైట్‌ను చేరుకోలేకపోయాము</translation>
<translation id="5869522115854928033">సేవ్ చేసిన పాస్‌వర్డ్‌లు</translation>
<translation id="5887400589839399685">కార్డ్ సేవ్ చేయబడింది</translation>
+<translation id="5893718151540690985">నెట్‌వర్క్ ఇంటర్‌ఫేస్‌ల జాబితాను వాటి రకాలు, హార్డ్‌వేర్ చిరునామాలతో నివేదిస్తుంది</translation>
<translation id="5893752035575986141">క్రెడిట్ కార్డ్‌లు ఆమోదించబడతాయి.</translation>
<translation id="5901630391730855834">పసుపు</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (సమకాలీకరించబడింది)</translation>
@@ -781,6 +790,7 @@
<translation id="5967592137238574583">సంప్రదింపు సమాచారాన్ని సవరించండి</translation>
<translation id="5967867314010545767">చరిత్ర నుండి తీసివేయి</translation>
<translation id="5975083100439434680">దూరంగా జూమ్ చెయ్యి</translation>
+<translation id="5977489021191000276">మీ పరికరం నిర్వాహకుడితో నిర్వహించబడదు.</translation>
<translation id="5977976211062815271">ఈ పరికరంలో</translation>
<translation id="598637245381783098">చెల్లింపు యాప్‌ను తెరవడం సాధ్యం కాదు</translation>
<translation id="5989320800837274978">స్థిర ప్రాక్సీ సర్వర్‌లు లేదా ఒక .pac స్క్రిప్ట్ URL పేర్కొనబడలేదు.</translation>
@@ -792,17 +802,18 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />లోని హ్యాకర్‌లు మోసపూరిత యాప్‌లను ఇన్‌స్టాల్ చేయవచ్చు. ఇవి వేరే వాటిలా కనిపించవచ్చు లేదా మిమ్మల్ని ట్రాక్ చేయడానికి ఉపయోగించబడే డేటాను సేకరించవచ్చు. <ph name="BEGIN_LEARN_MORE_LINK" />మరింత తెలుసుకోండి<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (సమకాలీకరించబడ్డాయి)</translation>
<translation id="6027201098523975773">పేరుని నమోదు చేయండి</translation>
+<translation id="6033927989869462158">CPU/RAM వినియోగం లాంటి హార్డ్‌వేర్ గణాంకాలను నివేదిస్తుంది</translation>
<translation id="6034000775414344507">లేత బూడిద రంగు</translation>
<translation id="6039846035001940113">సమస్య కొనసాగుతుంటే, సైట్ యజమానిని సంప్రదించండి.</translation>
<translation id="6040143037577758943">మూసివేయి</translation>
<translation id="6044573915096792553">పరిమాణం 12</translation>
<translation id="6047233362582046994">మీ భద్రతకు వాటిల్లే ఆపదల గురించి మీకు అర్థం అయ్యి ఉంటే, హానికర యాప్‌లు తీసివేయబడటానికి ముందే మీరు <ph name="BEGIN_LINK" />ఈ సైట్‌ను సందర్శించవచ్చు<ph name="END_LINK" />.</translation>
<translation id="6047927260846328439">ఈ కంటెంట్, సాఫ్ట్‌వేర్‌ని ఇన్‌స్టాల్ చేసేలా లేదా వ్యక్తిగత సమాచారాన్ని బహిర్గతం చేసేలా మిమ్మల్ని మోసం చేయడానికి ప్రయత్నించవచ్చు. <ph name="BEGIN_LINK" />ఏదేమైనా చూపు<ph name="END_LINK" /></translation>
-<translation id="6051221802930200923">సర్టిఫికెట్‌ను పిన్ చేసే పద్ధతిని వెబ్‌సైట్ ఉపయోగిస్తుంది కనుక మీరు ప్రస్తుతానికి <ph name="SITE" />ని సందర్శించలేరు. నెట్‌వర్క్ ఎర్రర్‌లు మరియు దాడులు సాధారణంగా తాత్కాలికమే, కనుక ఈ పేజీ తర్వాత పని చేయవచ్చు.</translation>
+<translation id="6051221802930200923">ప్రమాణపత్రాన్ని పిన్ చేసే పద్ధతిని వెబ్‌సైట్ ఉపయోగిస్తుంది కనుక మీరు ప్రస్తుతానికి <ph name="SITE" />‌ను సందర్శించలేరు. నెట్‌వర్క్ లోపాలు మరియు దాడులు సాధారణంగా తాత్కాలికమే, కనుక ఈ పేజీ తర్వాత పని చేయవచ్చు.</translation>
<translation id="6058977677006700226">మీ కార్డ్‌లను మీ అన్ని పరికరాలలో ఉపయోగించాలా?</translation>
<translation id="6059925163896151826">USB పరికరాలు</translation>
<translation id="6071091556643036997">ఈ విధాన రకం చెల్లదు.</translation>
-<translation id="6080696365213338172">మీరు నిర్వాహకుని ద్వారా అందించబడిన సర్టిఫికెట్‌ను ఉపయోగించి కంటెంట్‌ను యాక్సెస్ చేసారు. మీరు <ph name="DOMAIN" />కు అందించే డేటాను మీ నిర్వాహకుడు చూడవచ్చు.</translation>
+<translation id="6080696365213338172">మీరు నిర్వాహకుని ద్వారా అందించబడిన ప్రమాణపత్రాన్ని ఉపయోగించి కంటెంట్‌ను యాక్సెస్ చేసారు. మీరు <ph name="DOMAIN" />కు అందించే డేటాకు మీ నిర్వాహకుని ద్వారా అంతరాయం ఏర్పడవచ్చు.</translation>
<translation id="6094273045989040137">అదనపు గమనికను జోడించండి</translation>
<translation id="610911394827799129">మీ Google ఖాతా <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />లో ఇతర రూపాల్లో ఉన్న బ్రౌజింగ్ చరిత్రను కలిగి ఉండవచ్చు</translation>
<translation id="6144381551823904650">{COUNT,plural, =0{ఏమీ లేవు}=1{1 పాస్‌వర్డ్ (సమకాలీకరించబడింది)}other{# పాస్‌వర్డ్‌లు (సమకాలీకరించబడ్డాయి)}}</translation>
@@ -812,7 +823,7 @@
<translation id="6151417162996330722">సర్వర్ ప్రమాణపత్రం చెల్లుబాటు వ్యవధి చాలా ఎక్కువ కాలం ఉంది.</translation>
<translation id="6157877588268064908">రవాణా పద్ధతులు మరియు అవసరాలను చూడాలంటే, చిరునామాని ఎంచుకోండి</translation>
<translation id="6165508094623778733">మరింత తెలుసుకోండి</translation>
-<translation id="6169916984152623906">‌ఇప్పుడు మీరు వ్యక్తిగతంగా బ్రౌజ్ చేయవచ్చు మరియు ఈ పరికరాన్ని ఉపయోగించే ఇతర వ్యక్తులకు మీ కార్యాచరణ కనిపించదు. అయినప్పటికీ, డౌన్‌లోడ్‌లు మరియు బుక్‌మార్క్‌లు సేవ్ చేయబడతాయి.</translation>
+<translation id="6169916984152623906">‌ఇప్పుడు మీరు వ్యక్తిగతంగా బ్రౌజ్ చేయవచ్చు. ఈ పరికరాన్ని ఉపయోగించే ఇతర వ్యక్తులకు మీ కార్య‌క‌లాపం కనిపించదు. అయినప్పటికీ, డౌన్‌లోడ్‌లు, బుక్‌మార్క్‌లు సేవ్ చేయబడతాయి.</translation>
<translation id="6177128806592000436">ఈ సైట్‌కి మీ కనెక్షన్ సురక్షితంగా లేదు</translation>
<translation id="6203231073485539293">మీ ఇంటర్నెట్ కనెక్షన్‌ను తనిఖీ చేయండి</translation>
<translation id="6218753634732582820">Chromium నుండి చిరునామాను తీసివేయాలా?</translation>
@@ -845,7 +856,7 @@
<translation id="6404511346730675251">బుక్‌మార్క్‌ను సవరించండి</translation>
<translation id="6410264514553301377"><ph name="CREDIT_CARD" /> గడువు ముగింపు తేదీ మరియు CVCని నమోదు చేయండి</translation>
<translation id="6414888972213066896">మీరు ఈ సైట్‌ని సందర్శించడానికి అనుమతించమని కోరుతూ మీ తల్లి/తండ్రికి అభ్యర్థన పంపారు</translation>
-<translation id="6417515091412812850">సర్టిఫికెట్ రద్దు చేయబడిందా అని తనిఖీ చేయడం సాధ్యం కాలేదు.</translation>
+<translation id="6417515091412812850">ప్రమాణపత్రం రద్దు చెయ్యబడిందా అని తనిఖీ చెయ్యడం సాధ్యం కాలేదు.</translation>
<translation id="6433490469411711332">సంప్రదింపు సమాచారాన్ని సవరించండి</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> కనెక్ట్ కావడానికి నిరాకరించింది.</translation>
<translation id="6446608382365791566">మరింత సమాచారాన్ని జోడించండి</translation>
@@ -880,7 +891,7 @@
<translation id="671076103358959139">నమోదు టోకెన్:</translation>
<translation id="6711464428925977395">ప్రాక్సీ సర్వర్‌లో ఏదో తప్పు ఉంది లేదా చిరునామా సరైనది కాదు.</translation>
<translation id="6723740634201835758">మీ Google ఖాతాలో</translation>
-<translation id="674375294223700098">తెలియని సర్వర్ సర్టిఫికెట్ ఎర్రర్.</translation>
+<translation id="674375294223700098">తెలియని సర్వర్ ప్రమాణపత్రం లోపం.</translation>
<translation id="6744009308914054259">కనెక్షన్ కోసం వేచి ఉన్నప్పుడు, మీరు ఆఫ్‌లైన్ కథనాలను చదవడానికి డౌన్‌లోడ్‌లను సందర్శించవచ్చు.</translation>
<translation id="6753269504797312559">విధానం విలువ</translation>
<translation id="6757797048963528358">మీ పరికరం నిద్రావస్థకి వెళ్లింది.</translation>
@@ -890,7 +901,7 @@
<translation id="681021252041861472">అవసరమైన ఫీల్డ్</translation>
<translation id="6810899417690483278">అనుకూలీకరణ ID</translation>
<translation id="6824266427216888781">ప్రాంతాల డేటాను లోడ్ చేయడం విఫలమైంది</translation>
-<translation id="6825578344716086703"><ph name="DOMAIN" />ను చేరుకోవడానికి మీరు ప్రయత్నించారు, కానీ సర్వర్ (SHA-1 వంటి) బలహీనమైన సంతకం అల్గారిథమ్‌ను ఉపయోగించి సంతకం చేసిన సర్టిఫికెట్‌ను అందించింది. అంటే సర్వర్ అందించిన భద్రత ఆధారాలు నకిలీ కావచ్చు మరియు సర్వర్ మీరు ఊహించిన సర్వర్ కాకపోవచ్చు (మీరు హ్యాకర్‌తో పరస్పర చర్య చేస్తుండవచ్చు).</translation>
+<translation id="6825578344716086703"><ph name="DOMAIN" />ను చేరుకోవడానికి మీరు ప్రయత్నించారు, కానీ సర్వర్ (SHA-1 వంటి) బలహీనమైన సంతకం అల్గారిథమ్‌ను ఉపయోగించి సంతకం చేసిన ప్రమాణపత్రాన్ని అందించింది. అంటే సర్వర్ అందించిన భద్రత ఆధారాలు నకిలీ కావచ్చు మరియు సర్వర్ మీరు ఊహించిన సర్వర్ కాకపోవచ్చు (మీరు హ్యాకర్‌తో పరస్పర చర్య చేస్తుండవచ్చు).</translation>
<translation id="6831043979455480757">అనువదించు</translation>
<translation id="6839929833149231406">ప్రాంతం</translation>
<translation id="6852204201400771460">యాప్‌ను మళ్లీ లోడ్ చేయాలా?</translation>
@@ -904,6 +915,8 @@
<translation id="6897140037006041989">వినియోగదారు ప్రతినిధి</translation>
<translation id="6903319715792422884"><ph name="BEGIN_WHITEPAPER_LINK" />కొంత సిస్టమ్ సమాచారం మరియు పేజీ కంటెంట్‌<ph name="END_WHITEPAPER_LINK" />ను Googleకి పంపడం ద్వారా సురక్షిత బ్రౌజింగ్‌ని మెరుగుపరచడంలో సహాయపడండి. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">వినియోగదారు:</translation>
+<translation id="6934672428414710184">ఇది మీ Google ఖాతాలో ఉన్న పేరు</translation>
+<translation id="6939583532829045966">మీ పరికరం <ph name="ENROLLMENT_DOMAIN" /> ద్వారా నిర్వహించబడుతుంది. దీని ప్రకారం, మీ నిర్వాహకుడు రిమోట్ పద్ధతిలో మీ పరికరాన్ని కాన్ఫిగర్ చేయగలరు.</translation>
<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> నిర్వహించని ఒక సైట్‌లో మీరు మీ పాస్‌వర్డ్‌ని నమోదు చేసారు. మీ ఖాతాని రక్షించడం కోసం, మీ పాస్‌వర్డ్‌ని ఇతర యాప్‌లు మరియు సైట్‌లలో తిరిగి ఉపయోగించవద్దు.</translation>
<translation id="6945221475159498467">ఎంచుకోండి</translation>
<translation id="6948701128805548767">పికప్ పద్ధతులు మరియు అవసరాలను చూడాలంటే, చిరునామాని ఎంచుకోండి</translation>
@@ -924,7 +937,7 @@
<translation id="7012363358306927923">చైనా యూనియన్ పే</translation>
<translation id="7016992613359344582">ఈ ఛార్జ్‌లు ఒకే సారి చెల్లించేవి లేదా పునరావృతంగా చెల్లించాల్సినవి కావచ్చు మరియు స్పష్టంగా పేర్కొనబడకపోవచ్చు.</translation>
<translation id="7029809446516969842">పాస్‌వర్డ్‌లు</translation>
-<translation id="7050187094878475250">మీరు <ph name="DOMAIN" />ని చేరుకోవడానికి ప్రయత్నించారు, కానీ సర్వర్ అందించిన ప్రమాణపత్రం విశ్వసించలేనంత ఎక్కువ చెల్లుబాటు వ్యవధిని కలిగి ఉంది.</translation>
+<translation id="7050187094878475250">మీరు <ph name="DOMAIN" />‌ను చేరుకోవడానికి ప్రయత్నించారు, కానీ సర్వర్ అందించిన ప్రమాణపత్రం విశ్వసించలేనంత ఎక్కువ చెల్లుబాటు వ్యవధిని కలిగి ఉంది.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ప్రస్తుతం ఈ కార్డ్‌ని సేవ్ చేయలేరు}other{ప్రస్తుతం ఈ కార్డ్‌లని సేవ్ చేయలేరు}}</translation>
<translation id="7053983685419859001">నిరోధించు</translation>
<translation id="7062635574500127092">నీలి పచ్చ రంగు</translation>
@@ -957,7 +970,7 @@
<translation id="7220786058474068424">ప్రాసెస్ చేస్తోంది</translation>
<translation id="7243010569062352439"><ph name="PASSWORDS" />; <ph name="SIGNIN_DATA" /></translation>
<translation id="724691107663265825">మీరు చేరుకోబోయే సైట్‌లో మాల్వేర్ ఉంది</translation>
-<translation id="724975217298816891">మీ కార్డ్ వివరాలను అప్‌డేట్ చేయడానికి <ph name="CREDIT_CARD" /> కార్డ్ గడువు ముగింపు తేదీ మరియు CVCని నమోదు చేయండి. మీరు నిర్ధారించిన తర్వాత, మీ కార్డ్ వివరాలు ఈ సైట్‌తో షేర్ చేయబడతాయి.</translation>
+<translation id="724975217298816891">మీ కార్డ్ వివరాలను అప్‌డేట్ చేయ‌డానికి <ph name="CREDIT_CARD" /> కార్డ్ గడువు ముగింపు తేదీ మరియు CVCని నమోదు చేయండి. మీరు నిర్ధారించిన తర్వాత, మీ కార్డ్ వివరాలు ఈ సైట్‌తో షేర్‌ చేయబడతాయి.</translation>
<translation id="7251437084390964440">నెట్‌వర్క్ కాన్ఫిగరేషన్ ONC ప్రమాణానికి అనుకూలంగా లేదు. కాన్ఫిగరేషన్‌లోని భాగాలు దిగుమతి కాకపోయి ఉండకపోవచ్చు.
అదనపు వివరాలు:
<ph name="DEBUG_INFO" /></translation>
@@ -984,25 +997,28 @@
<translation id="7407424307057130981">&lt;p&gt;మీ Windows కంప్యూటర్‌లో Superfish సాఫ్ట్‌వేర్ ఉన్నట్లయితే మీకు ఈ ఎర్రర్ కనిపిస్తుంది.&lt;/p&gt;
&lt;p&gt;మీరు వెబ్‌లోకి వెళ్లడం కోసం, సాఫ్ట్‌వేర్‌ను తాత్కాలికంగా నిలిపివేయడానికి ఈ దశలను అనుసరించండి. మీ వద్ద నిర్వాహకుడి స్థాయి అధికారాలు ఉండాలి.&lt;/p&gt;
&lt;ol&gt;
- &lt;li&gt;&lt;strong&gt;ప్రారంభించు&lt;/strong&gt;ని క్లిక్ చేసి, ఆపై &lt;strong&gt;"స్థానిక సేవలను వీక్షించండి"&lt;/strong&gt; కోసం వెతికి, దానిని ఎంచుకోండి
+ &lt;li&gt;&lt;strong&gt;ప్రారంభించు&lt;/strong&gt;ను క్లిక్ చేసి, ఆపై &lt;strong&gt;"స్థానిక సేవలను వీక్షించండి"&lt;/strong&gt; కోసం వెతికి, దానిని ఎంచుకోండి
&lt;li&gt;&lt;strong&gt;VisualDiscovery&lt;/strong&gt;ని ఎంచుకోండి
&lt;li&gt;&lt;strong&gt;ప్రారంభ రకం&lt;/strong&gt;లో, &lt;strong&gt;నిలిపివేయబడింది&lt;/strong&gt; ఎంచుకోండి
&lt;li&gt;&lt;strong&gt;సేవా స్థితి&lt;/strong&gt;లో, &lt;strong&gt;ఆపివేయి&lt;/strong&gt;ని క్లిక్ చేయండి
&lt;li&gt;&lt;strong&gt;వర్తింపజేయి&lt;/strong&gt;ని క్లిక్ చేసి, ఆపై &lt;strong&gt;సరే&lt;/strong&gt; క్లిక్ చేయండి
- &lt;li&gt;సాఫ్ట్‌వేర్‌ను మీ కంప్యూటర్ నుండి శాశ్వతంగా ఎలా తొలగించాలో తెలుసుకోవడానికి &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome సహాయ కేంద్రం&lt;/a&gt;ను సందర్శించండి
+ &lt;li&gt;మీ కంప్యూటర్ నుండి శాశ్వతంగా సాఫ్ట్‌వేర్‌ను ఎలా తొలగించాలో తెలుసుకోవడానికి &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome సహాయ కేంద్రం&lt;/a&gt;ను సందర్శించండి
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> నిర్వహణ</translation>
<translation id="7416351320495623771">పాస్‌వర్డ్‌లను నిర్వహించండి…</translation>
-<translation id="7419106976560586862">ప్రొఫైల్ పాథ్‌</translation>
+<translation id="7419106976560586862">ప్రొఫైల్ మార్గం</translation>
<translation id="7437289804838430631">సంప్రదింపు సమాచారాన్ని జోడించు</translation>
<translation id="7440140511386898319">ఆఫ్‌లైన్‌లో ఉన్నప్పుడు అన్వేషించండి</translation>
<translation id="7441627299479586546">చెల్లని విధాన విషయం</translation>
<translation id="7442725080345379071">లేత నారింజ రంగు</translation>
<translation id="7444046173054089907">ఈ సైట్ బ్లాక్ చేయబడింది</translation>
-<translation id="7445762425076701745">మీరు కనెక్ట్ చేసిన సర్వర్ యొక్క గుర్తింపు పూర్తిగా ధృవీకరించబడలేదు. మీ నెట్‌వర్క్‌లో మాత్రమే చెల్లుబాటు అయ్యే పేరును ఉపయోగించి ఈ సర్వర్‌కి కనెక్ట్ చేసారు, కాబట్టి దీని యాజమాన్యాన్ని బాహ్య సర్టిఫికెట్ అధికారిక సంస్థ ధృవీకరించలేదు. అయినా కూడా, కొన్ని సర్టిఫికెట్ అధికారిక సంస్థలు ఈ పేర్లకు సర్టిఫికెట్‌ను జారీ చేస్తాయి కాబట్టి, మీరు సరైన వెబ్‌సైట్‌కి కనెక్ట్ అయ్యారా లేదా ఒక అటాకర్‌కి కనెక్ట్ అయ్యారా అని నిర్ధారించడానికి ఏ మార్గమూ లేదు.</translation>
+<translation id="7445762425076701745">మీరు కనెక్ట్ చేసిన సర్వర్ యొక్క గుర్తింపు పూర్తిగా ధృవీకరించబడలేదు. మీరు దీని యొక్క యాజమాన్యాన్ని ధృవీకరించడానికి అంతర్గత ప్రమాణపత్రం అధికారికి మరొక దాని లేని మీ నెట్‌వర్క్‌లో మాత్రమే చెల్లుబాటు అయ్యే పేరును ఉపయోగించి సర్వర్‌కు కనెక్ట్ చేసారు. కొన్ని ప్రమాణపత్రం అధికారులు సంబంధంలేని ఈ పేర్లకు ప్రమాణపత్రాన్ని జారీ చేస్తారు, మీరు సరైన వెబ్‌సైట్‌కు మరియు అటాకర్‌కు కనెక్ట్ చేసారా అని నిర్ధారించడానికి వేరే మార్గం లేదు.</translation>
+<translation id="7449109375006139765">సిస్టమ్ లాగ్‌లను నిర్వహణ సర్వర్‌కు పంపుతుంది</translation>
<translation id="7451311239929941790">ఈ సమస్య గురించి <ph name="BEGIN_LINK" />మరింత తెలుసుకోండి<ph name="END_LINK" />.</translation>
<translation id="7455133967321480974">సార్వజనీన డిఫాల్ట్‌ను ఉపయోగించు (బ్లాక్ చేయి)</translation>
<translation id="7460618730930299168">మీరు ఎంచుకున్నది మరియు స్క్రీనింగ్ చేస్తున్నది వేరుగా ఉన్నాయి. కొనసాగించాలా?</translation>
<translation id="7473891865547856676">వద్దు, ధన్యవాదాలు</translation>
+<translation id="7475525192983021547">పరికరంలో వినియోగదారు యాక్టివ్‌గా ఉన్నప్పుడు కాల వ్యవధులను నివేదిస్తుంది</translation>
<translation id="7481312909269577407">ఫార్వర్డ్</translation>
<translation id="7485870689360869515">డేటా కనుగొనబడలేదు.</translation>
<translation id="7508255263130623398">అందించబడిన విధాన పరికర id ఖాళీగా ఉంది లేదా ప్రస్తుత పరికర idకి సరిపోలలేదు</translation>
@@ -1014,7 +1030,7 @@
<translation id="7526934274050461096">ఈ సైట్‌కి మీ కనెక్షన్ ప్రైవేట్ కాదు</translation>
<translation id="7537536606612762813">తప్పనిసరి</translation>
<translation id="7542403920425041731">మీరు నిర్ధారించిన తర్వాత, మీ కార్డ్ వివరాలు ఈ సైట్‌తో షేర్ చేయబడతాయి.</translation>
-<translation id="7542995811387359312">ఈ ఫారమ్ సురక్షిత కనెక్షన్‌ని ఉపయోగించనందున ఆటోమేటిక్‌గా క్రెడిట్ కార్డ్ పూర్తి చెయ్యడం ఆపివేయబడింది.</translation>
+<translation id="7542995811387359312">ఈ ఫారమ్ సురక్షిత కనెక్షన్‌ను ఉపయోగించనందున క్రెడిట్ కార్డ్ వివరాలను ఆటోమేటిక్‌గా పూర్తి చేయడం ఆపివేయబడింది.</translation>
<translation id="7543525346216957623">మీ తల్లి/తండ్రిని అడగండి</translation>
<translation id="7548892272833184391">కనెక్షన్ ఎర్రర్‌లను పరిష్కరించండి</translation>
<translation id="7549584377607005141">ఈ వెబ్‌పేజీ సరిగ్గా ప్రదర్శించబడటానికి మీరు మునుపు నమోదు చేసిన డేటా అవసరం. మీరు ఈ డేటాను మళ్లీ పంపవచ్చు. కానీ అలా చేయడం వలన ఈ పేజీ మునుపు ప్రదర్శించిన ఏదైనా చర్య పునరావృతం కావచ్చు.</translation>
@@ -1022,7 +1038,7 @@
<translation id="7554791636758816595">కొత్త ట్యాబ్</translation>
<translation id="7564049878696755256">మీరు మీ <ph name="ORG_NAME" /> ఖాతాకు యాక్సెస్‌ని కోల్పోవచ్చు లేదా గుర్తింపు చోరీకి గురి కావచ్చు. మీ పాస్‌వర్డ్‌ని ఇప్పుడే రీసెట్ చేయాల్సిందిగా Chrome సిఫార్సు చేస్తోంది.</translation>
<translation id="7566125604157659769">మీరు కాపీ చేసిన వచనం</translation>
-<translation id="7567204685887185387">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం మోసపూరితంగా జారీ అయ్యి ఉండవచ్చు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కి అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
+<translation id="7567204685887185387">ఈ సర్వర్ <ph name="DOMAIN" /> అని నిరూపించుకోలేకపోయింది; దీని భద్రతా ప్రమాణపత్రం మోసపూరితంగా జారీ అయ్యి ఉండవచ్చు. ఇది తప్పుగా కాన్ఫిగర్ చేయడం వలన లేదా దాడిచేసే వ్యక్తి మీ కనెక్షన్‌కు అంతరాయం కలిగించడం వలన జరిగి ఉండవచ్చు.</translation>
<translation id="7569952961197462199">Chrome నుండి క్రెడిట్ కార్డ్‌ను తీసివేయాలా?</translation>
<translation id="7569983096843329377">నలుపు</translation>
<translation id="7578104083680115302">మీరు Googleతో సేవ్ చేసిన కార్డ్‌లను ఉపయోగించి పరికరాల్లోని సైట్‌లు మరియు అనువర్తనాల్లో శీఘ్రంగా చెల్లించండి.</translation>
@@ -1032,7 +1048,7 @@
<translation id="7600965453749440009"><ph name="LANGUAGE" />ను ఎప్పటికీ అనువదించవద్దు</translation>
<translation id="7610193165460212391">విలువ <ph name="VALUE" /> పరిధి వెలుపల ఉంది.</translation>
<translation id="7613889955535752492">గడువు ముగింపు: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
-<translation id="7615602087246926389">మీ ద‌గ్గ‌ర‌ ఇప్పటికే మీ Google ఖాతా పాస్‌వర్డ్ యొక్క మరొక వెర్ష‌న్‌ను ఉపయోగించి ఎన్‌క్రిప్ట్ చేసిన డేటా ఉంది. దయచేసి దాన్ని దిగువున‌ నమోదు చేయండి.</translation>
+<translation id="7615602087246926389">మీ Google ఖాతా పాస్‌వర్డ్ యొక్క మరొక వెర్షన్‌ను ఉపయోగించి ఎన్‌క్రిప్ట్ చేసిన డేటా మీ వద్ద ఇప్పటికే ఉంది. దయచేసి దానిని దిగువ నమోదు చేయండి.</translation>
<translation id="7637571805876720304">Chromium నుండి క్రెడిట్ కార్డ్‌ను తీసివేయాలా?</translation>
<translation id="7639968568612851608">ముదురు బూడిద రంగు</translation>
<translation id="765676359832457558">అధునాతన సెట్టింగ్‌లను దాచు...</translation>
@@ -1058,13 +1074,13 @@
<translation id="7755287808199759310">మీ తల్లి/తండ్రి దీన్ని మీ కోసం అన్‌బ్లాక్ చేయగలరు</translation>
<translation id="7758069387465995638">ఫైర్‌వాల్ లేదా యాంటీవైరస్ సాఫ్ట్‌వేర్ కనెక్షన్‌ను బ్లాక్ చేసి ఉండవచ్చు.</translation>
<translation id="7759163816903619567">ప్రదర్శన డొమైన్:</translation>
-<translation id="7761701407923456692">సర్వర్ సర్టిఫికెట్ URLతో సరిపోలలేదు.</translation>
+<translation id="7761701407923456692">సర్వర్ ప్రమాణపత్రం URLతో సరిపోలలేదు.</translation>
<translation id="7763386264682878361">చెల్లింపు మానిఫెస్ట్ అన్వయ ప్రక్రియ</translation>
<translation id="7764225426217299476">చిరునామాను జోడించు</translation>
<translation id="777702478322588152">అధికారిక నివాసం</translation>
<translation id="7791543448312431591">జోడించు</translation>
<translation id="7793809570500803535"><ph name="SITE" />లోని వెబ్‌పేజీ తాత్కాలికంగా పని చేయకపోవచ్చు లేదా ఇది క్రొత్త వెబ్ చిరునామాకు శాశ్వతంగా తరలించబడి ఉండవచ్చు.</translation>
-<translation id="7800304661137206267"><ph name="KX" />ను కీ మార్పిడి విధానం లాగా మరియు సందేశ ప్రామాణీకరణ కోసం <ph name="CIPHER" />ను <ph name="MAC" />తో ఉపయోగించడం ద్వారా కనెక్షన్ ఎన్‌క్రిప్ట్ చేయ‌బ‌డింది.</translation>
+<translation id="7800304661137206267"><ph name="KX" />‌ను కీ మార్పిడి విధానం లాగా మరియు సందేశ ప్రామాణీకరణ కోసం <ph name="CIPHER" />‌ను <ph name="MAC" />తో ఉపయోగించడం ద్వారా కనెక్షన్ గుప్తీకరించబడింది.</translation>
<translation id="7802523362929240268">సైట్ చట్టబద్ధమైనది</translation>
<translation id="780301667611848630">వద్దు , ధన్యవాదాలు</translation>
<translation id="7805768142964895445">స్థితి</translation>
@@ -1073,7 +1089,7 @@
<translation id="7813600968533626083">Chrome నుండి ఫారమ్ సూచనను తీసివేయాలా?</translation>
<translation id="7815407501681723534">'<ph name="SEARCH_STRING" />' కోసం <ph name="NUMBER_OF_RESULTS" /> <ph name="SEARCH_RESULTS" /> కనుగొనబడ్డాయి</translation>
<translation id="7818867226424560206">విధాన నిర్వహణ</translation>
-<translation id="782886543891417279">మీరు ఉపయోగిస్తున్న Wi-Fi (<ph name="WIFI_NAME" />)కి మీరు దాని లాగిన్ పేజీని సందర్శించడం అవసరం.</translation>
+<translation id="782886543891417279">మీరు ఉపయోగిస్తున్న Wi-Fi అయిన (<ph name="WIFI_NAME" />), దాని లాగిన్ పేజీని మీరు సందర్శించాల్సిందిగా కోరవచ్చు.</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ఏదీ వద్దు}=1{1 యాప్ (<ph name="EXAMPLE_APP_1" />)}=2{2 యాప్‌లు (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# యాప్‌లు (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
<translation id="785549533363645510">అయినప్పటికీ, మీరు అదృశ్యంగా ఉండరు. అజ్ఞాతంలోకి వెళ్లడం వ‌ల్ల‌ మీ బ్రౌజింగ్- మీ యజమానికి, మీ ఇంటర్నెట్ సేవా ప్రదాతకు లేదా మీరు సందర్శించే వెబ్‌సైట్‌లకు కనిపించకుండా దాచబడదు.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
@@ -1086,7 +1102,7 @@
<translation id="79338296614623784">చెల్లుబాటు అయ్యే ఫోన్ నంబర్‌ను నమోదు చేయండి</translation>
<translation id="7935318582918952113">DOM డిస్టిల్లర్</translation>
<translation id="7937554595067888181"><ph name="EXPIRATION_DATE_ABBR" />న గడువు ముగుస్తుంది</translation>
-<translation id="7938958445268990899">సర్వర్ ప్రమాణపత్రం ఇంకా చెల్లుబాటు కాదు.</translation>
+<translation id="7938958445268990899">సర్వర్ ప్రమాణపత్రం ఇంకా చెల్లుబాటులో లేదు.</translation>
<translation id="7942349550061667556">ఎరుపు</translation>
<translation id="7947285636476623132">మీ గడువు ముగింపు సంవత్సరాన్ని తనిఖీ చేసి, మళ్లీ ప్రయత్నించండి</translation>
<translation id="7951415247503192394">(32-బిట్)</translation>
@@ -1095,6 +1111,7 @@
<translation id="7995512525968007366">పేర్కొనబడలేదు</translation>
<translation id="800218591365569300">మెమరీని ఖాళీ చేయడానికి ఇతర ట్యాబ్‌లు లేదా ప్రోగ్రామ్‌లను మూసివేయడాన్ని ప్రయత్నించండి.</translation>
<translation id="8009225694047762179">పాస్‌వర్డ్‌లను నిర్వహించండి</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ఈ కార్డ్, దీని బిల్లింగ్ చిరునామా సేవ్ చేయబడతాయి. <ph name="USER_EMAIL" />కు సైన్ ఇన్ చేసినప్పుడు మీరు దీనిని ఉపయోగించగలరు.}other{ఈ కార్డ్‌లు, వీటి బిల్లింగ్ చిరునామాలు సేవ్ చేయబడతాయి. <ph name="USER_EMAIL" />కు సైన్ ఇన్ చేసినప్పడు, మీరు వీటిని ఉపయోగించగలరు.}}</translation>
<translation id="8012647001091218357">మేము ప్రస్తుతం మీ తల్లిదండ్రులను సంప్రదించలేకపోయాము. దయచేసి మళ్లీ ప్రయత్నించండి.</translation>
<translation id="8025119109950072390">ఈ సైట్‌లోని దాడి చేసేవారు సాఫ్ట్‌వేర్‌ను ఇన్‌స్టాల్ చేయడం లేదా మీ వ్యక్తిగత సమాచారాన్ని (ఉదాహరణకు, పాస్‌వర్డ్‌లు, ఫోన్ నంబర్‌లు లేదా క్రెడిట్ కార్డ్‌లు) వెల్లడించడం వంటి ప్రమాదకరమైన పనులు చేసేలా మిమ్మల్ని మాయ చేయవచ్చు.</translation>
<translation id="8034522405403831421">ఈ పేజీ <ph name="SOURCE_LANGUAGE" />లో ఉంది. దీన్ని <ph name="TARGET_LANGUAGE" />లోకి అనువదించాలా?</translation>
@@ -1105,6 +1122,7 @@
<translation id="8041940743680923270">సార్వజనీన డిఫాల్ట్‌ను ఉపయోగించు (అడుగు)</translation>
<translation id="8042918947222776840">పికప్ పద్ధతిని ఎంచుకోండి</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />"ని సరిగ్గా కాన్ఫిగర్ చేయలేదు. సాధారణంగా "<ph name="SOFTWARE_NAME" />"ని అన్ఇన్‌స్టాల్ చేయడం ద్వారా సమస్య పరిష్కారం కావచ్చు. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">మీ పరికరం దీనికి కాన్ఫిగర్ చేయబడింది:</translation>
<translation id="8078141288243656252">తిప్పినప్పుడు అదనపు గమనికలను అందించడం సాధ్యపడదు</translation>
<translation id="8079031581361219619">సైట్‌ను తిరిగి లోడ్ చేయాలా?</translation>
<translation id="8088680233425245692">కథనాన్ని వీక్షించడంలో విఫలమైంది.</translation>
@@ -1125,7 +1143,7 @@
<translation id="8184538546369750125">సార్వజనీన డిఫాల్ట్‌ను ఉపయోగించు (అనుమతించు)</translation>
<translation id="8194797478851900357">&amp;తరలించడాన్ని రద్దు చేయి</translation>
<translation id="8197543752516192074">పేజీని అనువదించు</translation>
-<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ఉన్న ఎక్స్‌టెన్ష‌న్‌ కోసం అప్‌డేట్ URL చెల్లదు..</translation>
+<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" ఉన్న ఎక్స్‌టెన్ష‌న్‌ కోసం అప్‌డేట్‌ URL చెల్లదు.</translation>
<translation id="8202097416529803614">ఆర్డర్ సారాంశం</translation>
<translation id="8211406090763984747">కనెక్షన్ సురక్షితంగా ఉంది</translation>
<translation id="8218327578424803826">కేటాయించిన స్థానం:</translation>
@@ -1141,8 +1159,8 @@
<translation id="8261506727792406068">తొలగించు</translation>
<translation id="8267698848189296333"><ph name="USERNAME" />గా సైన్ ఇన్ చేస్తోంది</translation>
<translation id="8286036467436129157">సైన్ ఇన్ చేయండి</translation>
-<translation id="8288807391153049143">సర్టిఫికేట్‌ని చూపు</translation>
-<translation id="8289355894181816810">మీకు దీని గురించి ఖచ్చితంగా తెలియకుంటే మీ నెట్‌వర్క్ నిర్వాహకుడిని సంప్రదించండి.</translation>
+<translation id="8288807391153049143">సర్టిఫికేట్‌ను చూపు</translation>
+<translation id="8289355894181816810">మీకు దీని గురించి ఖచ్చితంగా తెలియకుంటే మీ నెట్‌వర్క్ నిర్వాహకుని సంప్రదించండి.</translation>
<translation id="8293206222192510085">బుక్‌మార్క్‌లను జోడించు</translation>
<translation id="8294431847097064396">మూలం</translation>
<translation id="8298115750975731693">మీరు ఉపయోగిస్తున్న Wi-Fi (<ph name="WIFI_NAME" />)కి మీరు <ph name="BEGIN_BOLD" /><ph name="LOGIN_URL" /><ph name="END_BOLD" />ను సందర్శించడం అవసరం.</translation>
@@ -1155,6 +1173,7 @@
<translation id="8363502534493474904">ఎయిర్‌ప్లైన్ మోడ్‌ను ఆఫ్ చేయడం</translation>
<translation id="8364627913115013041">సెట్ చేయలేదు.</translation>
<translation id="8368476060205742148">Google Play సేవలు</translation>
+<translation id="8371889962595521444">అనుకూల రూట్ సెట్టింగ్‌లు</translation>
<translation id="8380941800586852976">అపాయకరమైనది</translation>
<translation id="8381674639488873545">ఈ ఛార్జ్‌లు ఒకసారి చెల్లించేవి లేదా పునరావృతంగా చెల్లించాల్సినవి కావచ్చు, అది స్పష్టంగా పేర్కొనబడకపోవచ్చు. <ph name="BEGIN_LINK" />ఏదేమైనా చూపు<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">మీరు ఇటీవల సందర్శించిన బుక్‌మార్క్‌లు ఇక్కడ కనిపిస్తాయి</translation>
@@ -1164,6 +1183,7 @@
<translation id="8416694386774425977">నెట్‌వర్క్ కాన్ఫిగరేషన్ చెల్లదు, కాబట్టి దిగుమతి చేయడం సాధ్యం కాదు.
అదనపు వివరాలు:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">పరికరం <ph name="ENROLLMENT_DOMAIN" /> ద్వారా నిర్వహించబడుతుంది</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">మార్చు</translation>
<translation id="8428213095426709021">సెట్టింగ్‌లు</translation>
@@ -1172,7 +1192,7 @@
<translation id="8461694314515752532">మీ స్వంత సమకాలీకరణ రహస్య పదబంధంతో సమకాలీకరించబడిన డేటాని ఎన్‌క్రిప్ట్ చేయండి</translation>
<translation id="8466379296835108687">{COUNT,plural, =1{1 క్రెడిట్ కార్డ్}other{# క్రెడిట్ కార్డ్‌లు}}</translation>
<translation id="8473863474539038330">చిరునామాలు మరియు మరిన్ని</translation>
-<translation id="8483780878231876732">మీ Google ఖాతా నుండి కార్డ్‌లను ఉపయోగించేందుకు, Chromeకి సైన్ ఇన్ చేయండి</translation>
+<translation id="8483780878231876732">మీ Google ఖాతా నుండి కార్డ్‌లను ఉపయోగించేందుకు, Chromeకు సైన్ ఇన్ చేయండి</translation>
<translation id="8488350697529856933">వీటికి వర్తిస్తుంది</translation>
<translation id="8498891568109133222"><ph name="HOST_NAME" /> ప్రతిస్పందించడానికి చాలా ఎక్కువ సమయం పట్టింది.</translation>
<translation id="8503559462189395349">Chrome పాస్‌వర్డ్‌లు</translation>
@@ -1186,7 +1206,7 @@
<translation id="8564985650692024650">మీరు మీ <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> పాస్‌వర్డ్‌ని ఇతర సైట్‌లలో తిరిగి ఉపయోగించినట్లయితే దీనిని రీసెట్ చేయాల్సిందిగా Chromium సిఫార్సు చేస్తోంది.</translation>
<translation id="8571890674111243710">పేజీని <ph name="LANGUAGE" />కు అనువదిస్తోంది...</translation>
<translation id="858637041960032120">ఫోన్ నం. జోడిం.</translation>
-<translation id="859285277496340001">ఇది రద్దు చేయబడిందా అని తనిఖీ చేయడానికి సర్టిఫికెట్ విధానాన్ని పేర్కొనలేదు.</translation>
+<translation id="859285277496340001">ఇది రద్దు చెయ్యబడిందా అని తనిఖీ చెయ్యడానికి ప్రమాణపత్రం విధానాన్ని పేర్కొనలేదు.</translation>
<translation id="860043288473659153">కార్డుదారుని పేరు</translation>
<translation id="861775596732816396">పరిమాణం 4</translation>
<translation id="8620436878122366504">మీ తల్లిదండ్రులు దీన్ని ఇంకా ఆమోదించలేదు</translation>
@@ -1199,7 +1219,7 @@
<translation id="8725066075913043281">మళ్ళీ ప్రయత్నించండి</translation>
<translation id="8728672262656704056">మీరు ఇప్పుడు అజ్ఞాత మోడ్‌లో ఉన్నారు</translation>
<translation id="8730621377337864115">పూర్తయింది</translation>
-<translation id="8738058698779197622">సురక్షిత కనెక్షన్‌ను ఏర్పాటు చేయడానికి, మీ గడియారాన్ని సరైన సమయానికి సెట్ చేయాలి. ఎందుకంటే వెబ్‌సైట్‌లు వాటిని గుర్తించడానికి ఉపయోగించే ప్రమాణపత్రాలు నిర్దిష్ట కాలవ్యవధుల్లో మాత్రమే చెల్లుబాటు అవుతాయి. మీ పరికరం యొక్క గడియారం సమయం తప్పుగా ఉన్నందున, Chromium ఈ ప్రమాణపత్రాలను ధృవీకరించడానికి వీలుపడలేదు.</translation>
+<translation id="8738058698779197622">సురక్షిత కనెక్షన్‌ను ఏర్పాటు చేయడానికి, మీ గడియారాన్ని సరైన సమయానికి సెట్ చేయాలి. ఎందుకంటే వెబ్‌సైట్‌లు వాటిని గుర్తించడానికి ఉపయోగించే సర్టిఫికెట్‌లు నిర్దిష్ట కాలవ్యవధులలో మాత్రమే చెల్లుబాటు అవుతాయి. మీ పరికరం యొక్క గడియారం సమయం తప్పుగా ఉన్నందున, Chromium ఈ సర్టిఫికెట్‌లను ధృవీకరించలేకపోయింది.</translation>
<translation id="8740359287975076522"><ph name="HOST_NAME" /> &lt;abbr id="dnsDefinition"&gt;DNS చిరునామా&lt;/abbr&gt; కనుగొనబడలేదు. సమస్యను నిర్ధారిస్తోంది.</translation>
<translation id="874846938927089722">ఆమోదించే క్రెడిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు</translation>
<translation id="8759274551635299824">ఈ కార్డ్ గడువు ముగిసింది</translation>
@@ -1224,10 +1244,11 @@
<translation id="8932102934695377596">మీ గడియారం సమయం గతంలో ఉంది</translation>
<translation id="893332455753468063">పేరుని జోడించండి</translation>
<translation id="8938939909778640821">ఆమోదించబడిన క్రెడిట్ మరియు ప్రీపెయిడ్ కార్డ్‌లు</translation>
+<translation id="894185898663964645">మీ నిర్వాహకుడు అనుకూల రూట్ సర్టిఫికెట్‌లను కాన్ఫిగర్ చేసారు, ఇవి మీరు సందర్శించే వెబ్‌సైట్‌ల కంటెంట్‌ను చూసేందుకు నిర్వాహకుడిని అనుమతించవచ్చు.</translation>
<translation id="8943282376843390568">నిమ్మపండు రంగు</translation>
<translation id="8957210676456822347">క్యాప్టివ్ పోర్టల్ ప్రామాణీకరణ</translation>
<translation id="8968766641738584599">కార్డ్‌ని సేవ్ చేయండి</translation>
-<translation id="8971063699422889582">సర్వర్ యొక్క ప్రమాణపత్రం గడువు ముగిసింది.</translation>
+<translation id="8971063699422889582">సర్వర్ ప్రమాణపత్రం గడువు ముగిసింది.</translation>
<translation id="8975012916872825179">ఫోన్ నంబర్‌లు, ఇమెయిల్ చిరునామాలు మరియు బట్వాడా చిరునామాలు లాంటి సమాచారం ఉంటుంది</translation>
<translation id="8978053250194585037">Google సురక్షిత బ్రౌజింగ్ ఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />ఫిషింగ్‌ని గుర్తించింది<ph name="END_LINK" />. ఫిషింగ్ సైట్‌లు వేరే వెబ్‌సైట్‌ల వలె ప్రవర్తించడం ద్వారా మిమ్మల్ని మాయ చేయవచ్చు.</translation>
<translation id="8983003182662520383">Google Payని ఉపయోగిస్తున్న చెల్లింపు పద్ధతులు మరియు చిరునామాలు</translation>
@@ -1247,7 +1268,7 @@
<translation id="9038649477754266430">పేజీలను మరింత త్వరగా లోడ్ చేయడానికి సూచన సేవను ఉపయోగించండి</translation>
<translation id="9039213469156557790">అలాగే, ఈ పేజీలో సురక్షితం కాని ఇతర వనరులు ఉన్నాయి. ఈ వనరులను బదిలీ చేస్తున్నప్పుడు ఇతరులు చూడగలరు మరియు దాడికి పాల్పడేవారు పేజీ ప్రవర్తనను మార్చేలా వీటిని సవరించగలరు.</translation>
<translation id="9045525010788763347"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
-<translation id="9049981332609050619">మీరు <ph name="DOMAIN" />ను చేరుకోవడానికి ప్రయత్నించారు. కానీ సర్వర్ ఒక చెల్లుబాటులో లేని సర్టిఫికెట్‌ను అందించింది.</translation>
+<translation id="9049981332609050619">మీరు <ph name="DOMAIN" />ని చేరుకోవడానికి ప్రయత్నించారు, కానీ సర్వర్ ఒక చెల్లుబాటులో లేని ప్రమాణపత్రంని అందించింది.</translation>
<translation id="9050666287014529139">రహస్య పదబంధం</translation>
<translation id="9065203028668620118">సవరించు</translation>
<translation id="9065745800631924235">చరిత్ర నుండి <ph name="TEXT" /> శోధన</translation>
@@ -1255,13 +1276,13 @@
<translation id="9076283476770535406">ఇందులో పెద్దలకు మాత్రమే తగిన కంటెంట్ ఉండవచ్చు</translation>
<translation id="9078964945751709336">మరింత సమాచారం ఆవశ్యకం</translation>
<translation id="9080712759204168376">ఆర్డర్ సారాంశం</translation>
-<translation id="9103872766612412690"><ph name="SITE" /> సాధారణంగా మీ సమాచారాన్ని రక్షించడానికి ఎన్‌క్రిప్షన్‌ను ఉపయోగిస్తుంది. Chromium ఈసారి <ph name="SITE" />కు కనెక్ట్ చేయడానికి ప్రయత్నించినప్పుడు, వెబ్‌సైట్ అసాధారణ మరియు తప్పు ఆధారాలు అని ప్రతిస్పందించింది. దాడి చేసే వ్యక్తి <ph name="SITE" />గా వ్యవహరించి మోసగించడానికి ప్రయత్నిస్తున్నప్పుడు లేదా Wi-Fi సైన్-ఇన్ స్క్రీన్ కనెక్షన్‌కు అంతరాయం కలిగించినప్పుడు ఇలా జరగవచ్చు. ఎలాంటి డేటా వినిమయం జ‌ర‌గ‌క ముందే Chromium, కనెక్షన్‌ను ఆపివేసినందున మీ సమాచారం ఇప్పటికీ సురక్షితంగానే ఉంది.</translation>
+<translation id="9103872766612412690"><ph name="SITE" /> సాధారణంగా మీ సమాచారాన్ని రక్షించడానికి ఎన్‌క్రిప్ష‌న్‌ను ఉపయోగిస్తుంది. Chromium ఈసారి <ph name="SITE" />కు కనెక్ట్ చేయడానికి ప్రయత్నించినప్పుడు, వెబ్‌సైట్ అసాధారణ మరియు తప్పు ఆధారాలు అని ప్రతిస్పందించింది. దాడి చేసే వ్యక్తి <ph name="SITE" />గా వ్యవహరించి మోసగించడానికి ప్రయత్నిస్తున్నప్పుడు లేదా Wi-Fi సైన్-ఇన్ స్క్రీన్ కనెక్షన్‌కు అంతరాయం కలిగించినప్పుడు ఇలా జరగవచ్చు. Chromium ఎలాంటి డేటా వినిమయం జ‌ర‌గ‌క ముందే కనెక్షన్‌ను ఆపివేసినందున మీ సమాచారం ఇప్పటికీ సురక్షితంగానే ఉంది.</translation>
<translation id="9106062320799175032">బిల్లింగ్ చిరునామాను జోడించండి</translation>
<translation id="9110718169272311511">Chromeలో Google అసిస్టెంట్ స్క్రీన్ దిగువ భాగానికి దగ్గరలో అందుబాటులో ఉంది</translation>
<translation id="9114524666733003316">కార్డ్‌ నిర్ధారించబడుతోంది...</translation>
<translation id="9128870381267983090">నెట్‌వర్క్‌కి కనెక్ట్ చేయి</translation>
<translation id="9137013805542155359">అసలును చూపించు</translation>
-<translation id="9137248913990643158">దయచేసి ఈ యాప్‌ను ఉపయోగించే ముందు Chromeను ప్రారంభించి, దానికి సైన్ ఇన్ చేయండి.</translation>
+<translation id="9137248913990643158">ఈ యాప్‌ను ఉపయోగించే ముందు, దయచేసి Chromeను ప్రారంభించి, దానికి సైన్ ఇన్ చేయండి.</translation>
<translation id="9148088599418889305">షిప్పింగ్ పద్ధతిని ఎంచుకోండి</translation>
<translation id="9148507642005240123">&amp;సవరించడాన్ని రద్దు చేయి</translation>
<translation id="9154194610265714752">నవీకరించబడింది</translation>
@@ -1270,7 +1291,7 @@
<translation id="9169664750068251925">ఈ సైట్‌లో ఎల్లప్పుడూ బ్లాక్ చేయి</translation>
<translation id="9170848237812810038">&amp;అన్డు</translation>
<translation id="9171296965991013597">యాప్ నుండి నిష్క్రమించాలా?</translation>
-<translation id="917450738466192189">సర్వర్ యొక్క సర్టిఫికెట్ చెల్లుబాటు కాదు.</translation>
+<translation id="917450738466192189">సర్వర్ యొక్క ప్రమాణపత్రం చెల్లుబాటు కాదు.</translation>
<translation id="9174917557437862841">ట్యాబ్ స్విచ్ బటన్, ఈ ట్యాబ్‌కి మారడానికి ఎంటర్‌ని నొక్కండి</translation>
<translation id="9183302530794969518">Google డాక్స్</translation>
<translation id="9183425211371246419"><ph name="HOST_NAME" /> మద్దతు లేని ప్రోటోకాల్‌ను ఉపయోగిస్తోంది.</translation>
diff --git a/chromium/components/strings/components_strings_th.xtb b/chromium/components/strings/components_strings_th.xtb
index 76965334793..2f4561e533a 100644
--- a/chromium/components/strings/components_strings_th.xtb
+++ b/chromium/components/strings/components_strings_th.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">ระบบจะไม่แปลหน้าเว็บภาษา<ph name="LANGUAGE" /></translation>
<translation id="2053553514270667976">รหัสไปรษณีย์</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 คำแนะนำ}other{# คำแนะนำ}}</translation>
+<translation id="2068124040035837596">บัญชีของคุณจัดการโดย <ph name="ENROLLMENT_DOMAIN" /> ซึ่งหมายความว่าผู้ดูแลระบบอาจกำหนดค่าบัญชีดังกล่าวจากระยะไกล</translation>
<translation id="2068663545051464999">อัปโหลดรหัสรายงานข้อขัดข้อง <ph name="CRASH_ID" /> แล้ว (บริบทเฉพาะรายการ: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">เลิกทำ</translation>
<translation id="20817612488360358">มีการกำหนดให้ใช้การตั้งค่าพร็อกซีระบบ แต่ก็มีการระบุการกำหนดค่าพร็อกซีอย่างชัดเจนไว้ด้วยเช่นกัน</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">วิธีการจัดส่งสินค้านี้ไม่พร้อมให้บริการ โปรดลองใช้วิธีการอื่น</translation>
<translation id="2396249848217231973">&amp;เลิกทำการนำออก</translation>
<translation id="2413528052993050574">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เพราะอาจมีการเพิกถอนใบรับรองความปลอดภัย โดยอาจเกิดจากการกำหนดค่าผิดหรือผู้บุกรุกที่ขัดขวางการเชื่อมต่อของคุณ</translation>
+<translation id="244665789865330679">อุปกรณ์และบัญชีของคุณจัดการโดย <ph name="ENROLLMENT_DOMAIN" /> ซึ่งหมายความว่าผู้ดูแลระบบอาจกำหนดค่าอุปกรณ์และบัญชีดังกล่าวจากระยะไกล</translation>
<translation id="2463193859425327265">เปลี่ยนหน้าแรก</translation>
<translation id="2463739503403862330">กรอกข้อมูล</translation>
<translation id="2465655957518002998">เลือกวิธีนำส่งสินค้า</translation>
@@ -560,6 +562,7 @@
<translation id="4377125064752653719">คุณพยายามเข้าถึง <ph name="DOMAIN" /> แต่ใบรับรองที่เซิร์ฟเวอร์แจ้งมาถูกเพิกถอนโดยผู้ออกใบรับรอง ซึ่งหมายความว่าข้อมูลรับรองด้านความปลอดภัยที่เซิร์ฟเวอร์แจ้งมานั้นไม่สามารถเชื่อถือได้ คุณอาจกำลังติดต่อกับคนที่คิดจะโจมตีคุณ</translation>
<translation id="4378154925671717803">โทรศัพท์</translation>
<translation id="4406896451731180161">ผลการค้นหา</translation>
+<translation id="4406972042435603828">ผู้ดูแลระบบได้ติดตั้งส่วนขยายซึ่งมาพร้อมกับความสามารถที่มีประสิทธิภาพ</translation>
<translation id="4408413947728134509">คุกกี้ <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">ที่อยู่ในการรับ</translation>
<translation id="4424024547088906515">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เพราะ Chrome ไม่เชื่อถือใบรับรองความปลอดภัย โดยอาจเกิดจากการกำหนดค่าผิดหรือผู้บุกรุกที่ขัดขวางการเชื่อมต่อของคุณ</translation>
@@ -631,10 +634,12 @@
<translation id="4943872375798546930">ไม่มีผลการค้นหา</translation>
<translation id="4950898438188848926">ปุ่มเปลี่ยนแท็บ โปรดกด Enter เพื่อเปลี่ยนไปยังแท็บที่เปิดอยู่ <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">การทำงาน</translation>
+<translation id="495832697253704892">การรายงานส่วนขยาย</translation>
<translation id="4958444002117714549">ขยายรายการ</translation>
<translation id="4974590756084640048">เปิดใช้คำเตือนอีกครั้ง</translation>
<translation id="4989163558385430922">ดูทั้งหมด</translation>
<translation id="4989809363548539747">ไม่รองรับปลั๊กอินนี้</translation>
+<translation id="4996230189582812866">การรายงาน</translation>
<translation id="5002932099480077015">หากเปิดใช้ Chrome จะเก็บสำเนาการ์ดของคุณในอุปกรณ์นี้เพื่อให้การกรอกฟอร์มทำได้เร็วขึ้น</translation>
<translation id="5014174725590676422">กำลังแสดงหน้าจอเรียกใช้ Google Assistant ครั้งแรกใน Chrome</translation>
<translation id="5015510746216210676">ชื่อเครื่อง:</translation>
@@ -655,6 +660,7 @@
<translation id="5089810972385038852">รัฐ</translation>
<translation id="5094747076828555589">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เพราะ Chromium ไม่เชื่อถือใบรับรองความปลอดภัย โดยอาจเกิดจากการกำหนดค่าผิดหรือผู้บุกรุกที่ขัดขวางการเชื่อมต่อของคุณ</translation>
<translation id="5095208057601539847">จังหวัด</translation>
+<translation id="5098222253617183465">อุปกรณ์ของคุณจัดการโดย <ph name="ENROLLMENT_DOMAIN" /> และบัญชีของคุณจัดการโดย <ph name="ACCOUNT_DOMAIN" /> ซึ่งหมายความว่าผู้ดูแลระบบอาจกำหนดค่าอุปกรณ์และบัญชีดังกล่าวจากระยะไกล</translation>
<translation id="5115563688576182185">(64 บิต)</translation>
<translation id="5128122789703661928">ลบเซสชันที่ใช้ชื่อนี้ไม่ได้</translation>
<translation id="5135404736266831032">จัดการที่อยู่...</translation>
@@ -667,6 +673,7 @@
<translation id="5172758083709347301">ผู้ใช้คอมพิวเตอร์นี้</translation>
<translation id="5179510805599951267">หากไม่มีในภาษา <ph name="ORIGINAL_LANGUAGE" /> ให้รายงานข้อผิดพลาดนี้</translation>
<translation id="5190835502935405962">แถบบุ๊กมาร์ก</translation>
+<translation id="5200263511887412697">รายงานรายชื่อผู้ใช้อุปกรณ์ที่ลงชื่อเข้าสู่ระบบเมื่อเร็วๆ นี้</translation>
<translation id="5201306358585911203">หน้าที่ฝังไว้ในหน้าเว็บนี้บอกว่า</translation>
<translation id="5205222826937269299">ต้องระบุชื่อ</translation>
<translation id="5215116848420601511">วิธีการชำระเงินและที่อยู่จาก Google Pay</translation>
@@ -768,6 +775,7 @@
<translation id="5869405914158311789">ไม่สามารถเข้าถึงเว็บไซต์นี้</translation>
<translation id="5869522115854928033">รหัสผ่านที่บันทึกไว้</translation>
<translation id="5887400589839399685">บันทึกการ์ดแล้ว</translation>
+<translation id="5893718151540690985">รายงานรายการอินเทอร์เฟซเครือข่ายพร้อมด้วยประเภทและที่อยู่ฮาร์ดแวร์</translation>
<translation id="5893752035575986141">รับบัตรเครดิต</translation>
<translation id="5901630391730855834">สีเหลือง</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (ซิงค์แล้ว)</translation>
@@ -781,6 +789,7 @@
<translation id="5967592137238574583">แก้ไขข้อมูลติดต่อ</translation>
<translation id="5967867314010545767">ลบจากประวัติการเข้าชม</translation>
<translation id="5975083100439434680">ย่อ</translation>
+<translation id="5977489021191000276">อุปกรณ์ไม่ได้จัดการโดยผู้ดูแลระบบ</translation>
<translation id="5977976211062815271">ในอุปกรณ์นี้</translation>
<translation id="598637245381783098">ไม่สามารถเปิดแอปการชำระเงิน</translation>
<translation id="5989320800837274978">ไม่มีการระบุทั้งพร็อกซีเซิร์ฟเวอร์แบบคงที่หรือ URL สคริปต์ .pac</translation>
@@ -792,6 +801,7 @@
<translation id="6017850046339264347">ผู้โจมตี <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> สามารถติดตั้งแอปที่หลอกลวงซึ่งปลอมเป็นเนื้อหาอย่างอื่นหรือรวบรวมข้อมูลที่อาจนำไปใช้ติดตามคุณ <ph name="BEGIN_LEARN_MORE_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" /> <ph name="TYPE_2" /> <ph name="TYPE_3" /> (ซิงค์แล้ว)</translation>
<translation id="6027201098523975773">ป้อนชื่อ</translation>
+<translation id="6033927989869462158">รายงานสถิติฮาร์ดแวร์ เช่น การใช้งาน CPU/RAM</translation>
<translation id="6034000775414344507">เทาอ่อน</translation>
<translation id="6039846035001940113">หากยังคงพบปัญหา ให้ติดต่อเจ้าของเว็บไซต์</translation>
<translation id="6040143037577758943">ปิด</translation>
@@ -904,6 +914,8 @@
<translation id="6897140037006041989">User agent</translation>
<translation id="6903319715792422884">ช่วยปรับปรุง Safe Browsing โดยส่ง<ph name="BEGIN_WHITEPAPER_LINK" />ข้อมูลบางอย่างของระบบและเนื้อหาของหน้า<ph name="END_WHITEPAPER_LINK" />ให้ Google <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">ผู้ใช้:</translation>
+<translation id="6934672428414710184">ชื่อนี้มาจากบัญชี Google ของคุณ</translation>
+<translation id="6939583532829045966">อุปกรณ์ของคุณจัดการโดย <ph name="ENROLLMENT_DOMAIN" /> ซึ่งหมายความว่าผู้ดูแลระบบอาจกำหนดค่าอุปกรณ์ดังกล่าวจากระยะไกล</translation>
<translation id="6944692733090228304">คุณป้อนรหัสผ่านในเว็บไซต์ที่ <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> ไม่ได้จัดการ เพื่อปกป้องบัญชี โปรดอย่าใช้รหัสผ่านซ้ำในแอปและเว็บไซต์อื่นๆ</translation>
<translation id="6945221475159498467">เลือก</translation>
<translation id="6948701128805548767">หากต้องการดูวิธีการรับสินค้าและข้อกำหนด โปรดเลือกที่อยู่</translation>
@@ -991,6 +1003,7 @@
&lt;li&gt;คลิก&lt;strong&gt;ใช้&lt;/strong&gt; แล้วคลิก&lt;strong&gt;ตกลง&lt;/strong&gt;
&lt;li&gt;ไปที่&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;ศูนย์ช่วยเหลือของ Chrome&lt;/a&gt; เพื่อดูวิธีนำซอฟต์แวร์ดังกล่าวออกจากคอมพิวเตอร์อย่างถาวร
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">การจัดการ <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">จัดการรหัสผ่าน…</translation>
<translation id="7419106976560586862">เส้นทางโปรไฟล์</translation>
<translation id="7437289804838430631">เพิ่มข้อมูลติดต่อ</translation>
@@ -999,10 +1012,12 @@
<translation id="7442725080345379071">ส้มอ่อน</translation>
<translation id="7444046173054089907">เว็บไซต์นี้ถูกบล็อก</translation>
<translation id="7445762425076701745">ไม่สามารถตรวจสอบความถูกต้องของข้อมูลประจำตัวของเซิร์ฟเวอร์ที่คุณเชื่อมต่ออยู่ได้ทั้งหมด คุณกำลังเชื่อมต่อกับเซิร์ฟเวอร์ที่ใช้ชื่อที่ใช้ได้เฉพาะในเครือข่ายของคุณ ซึ่งผู้ออกใบรับรองภายนอกไม่สามารถตรวจสอบการเป็นเจ้าของได้ เนื่องจากผู้ออกใบรับรองบางรายจะยังคงออกใบรับรองให้กับชื่อเหล่านี้อยู่ คุณจึงไม่มีทางมั่นใจได้ว่ากำลังเชื่อมต่อกับเว็บไซต์ที่คุณต้องการดูโดยไม่ใช่ผู้โจมตี</translation>
+<translation id="7449109375006139765">ส่งบันทึกของระบบไปยังเซิร์ฟเวอร์การจัดการ</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LINK" />เกี่ยวกับปัญหานี้</translation>
<translation id="7455133967321480974">ใช้ค่าเริ่มต้นสากล (บล็อก)</translation>
<translation id="7460618730930299168">การแสดงบนหน้าจอแตกต่างจากที่คุณเลือก ต้องการดำเนินการต่อไหม</translation>
<translation id="7473891865547856676">ไม่ ขอบคุณ</translation>
+<translation id="7475525192983021547">รายงานระยะเวลาที่ผู้ใช้ดำเนินการในอุปกรณ์</translation>
<translation id="7481312909269577407">ส่งต่อ</translation>
<translation id="7485870689360869515">ไม่พบข้อมูล</translation>
<translation id="7508255263130623398">รหัสอุปกรณ์นโยบายที่ส่งกลับว่างเปล่าหรือไม่ตรงกับรหัสอุปกรณ์ปัจจุบัน</translation>
@@ -1095,6 +1110,7 @@
<translation id="7995512525968007366">ไม่ได้ระบุ</translation>
<translation id="800218591365569300">ลองปิดแท็บหรือโปรแกรมอื่นๆ เพื่อเพิ่มหน่วยความจำ</translation>
<translation id="8009225694047762179">จัดการรหัสผ่าน</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{ระบบจะบันทึกบัตรนี้และที่อยู่สำหรับการเรียกเก็บเงินของบัตร คุณจะใช้บัตรนี้ได้เมื่อลงชื่อเข้าใช้ <ph name="USER_EMAIL" />}other{ระบบจะบันทึกบัตรเหล่านี้และที่อยู่สำหรับการเรียกเก็บเงินของบัตร คุณจะใช้บัตรเหล่านี้ได้เมื่อลงชื่อเข้าใช้ <ph name="USER_EMAIL" />}}</translation>
<translation id="8012647001091218357">เราไม่สามารถติดต่อผู้ปกครองของคุณได้ในขณะนี้ โปรดลองอีกครั้ง</translation>
<translation id="8025119109950072390">ผู้โจมตีในเว็บไซต์นี้อาจหลอกล่อให้คุณทำบางสิ่งที่อันตราย เช่น การติดตั้งซอฟต์แวร์หรือเปิดเผยข้อมูลส่วนบุคคล (ตัวอย่างเช่น รหัสผ่าน หมายเลขโทรศัพท์ หรือบัตรเครดิต)</translation>
<translation id="8034522405403831421">หน้าเว็บนี้อยู่ในภาษา<ph name="SOURCE_LANGUAGE" /> ต้องการแปลเป็นภาษา<ph name="TARGET_LANGUAGE" />ไหม</translation>
@@ -1105,6 +1121,7 @@
<translation id="8041940743680923270">ใช้ค่าเริ่มต้นสากล (ถาม)</translation>
<translation id="8042918947222776840">เลือกวิธีรับสินค้า</translation>
<translation id="8057711352706143257">กำหนดค่า "<ph name="SOFTWARE_NAME" />" ไม่ถูกต้อง การถอนการติดตั้ง "<ph name="SOFTWARE_NAME" />" มักแก้ไขปัญหานี้ได้ <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">อุปกรณ์ได้รับการกำหนดค่าเป็น</translation>
<translation id="8078141288243656252">เมื่อหมุนแล้วจะใส่หมายเหตุไม่ได้</translation>
<translation id="8079031581361219619">โหลดเว็บไซต์ซ้ำไหม</translation>
<translation id="8088680233425245692">การดูบทความล้มเหลว</translation>
@@ -1155,6 +1172,7 @@
<translation id="8363502534493474904">ปิดโหมดบนเครื่องบิน</translation>
<translation id="8364627913115013041">ไม่ได้ตั้งค่า</translation>
<translation id="8368476060205742148">บริการ Google Play</translation>
+<translation id="8371889962595521444">ใบรับรองรูทที่กำหนดเอง</translation>
<translation id="8380941800586852976">อันตราย</translation>
<translation id="8381674639488873545">การเรียกเก็บเงินเหล่านี้อาจเกิดขึ้นครั้งเดียวหรือเกิดขึ้นซ้ำๆ และอาจไม่แสดงอย่างชัดแจ้ง <ph name="BEGIN_LINK" />เปิดเว็บไซต์<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">บุ๊กมาร์กที่คุณเข้าชมล่าสุดจะปรากฏที่นี่</translation>
@@ -1164,6 +1182,7 @@
<translation id="8416694386774425977">การกำหนดค่าเครือข่ายไม่ถูกต้องและนำเข้าไม่ได้
รายละเอียดเพิ่มเติม:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">อุปกรณ์จัดการโดย <ph name="ENROLLMENT_DOMAIN" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">เปลี่ยน</translation>
<translation id="8428213095426709021">การตั้งค่า</translation>
@@ -1225,6 +1244,7 @@
<translation id="8932102934695377596">นาฬิกาช้าเกินไป</translation>
<translation id="893332455753468063">เพิ่มชื่อ</translation>
<translation id="8938939909778640821">บัตรเครดิตและบัตรเติมเงินที่ยอมรับ</translation>
+<translation id="894185898663964645">ผู้ดูแลระบบได้กำหนดค่าใบรับรองรูทที่กำหนดเอง ซึ่งอาจทำให้ผู้ดูแลระบบดูเนื้อหาของเว็บไซต์ที่คุณเข้าชมได้</translation>
<translation id="8943282376843390568">เหลืองมะนาว</translation>
<translation id="8957210676456822347">การให้สิทธิ์แคปทีฟพอร์ทัล</translation>
<translation id="8968766641738584599">บันทึกบัตร</translation>
diff --git a/chromium/components/strings/components_strings_tr.xtb b/chromium/components/strings/components_strings_tr.xtb
index 88274351afb..b46f3ba873a 100644
--- a/chromium/components/strings/components_strings_tr.xtb
+++ b/chromium/components/strings/components_strings_tr.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936"><ph name="LANGUAGE" /> dilindeki sayfalar çevrilmeyecek.</translation>
<translation id="2053553514270667976">Posta kodu</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 öneri}other{# öneri}}</translation>
+<translation id="2068124040035837596">Hesabınız <ph name="ENROLLMENT_DOMAIN" /> tarafından yönetiliyor. Bu durumda yöneticiniz hesabınızı uzaktan yapılandırabilir.</translation>
<translation id="2068663545051464999">Yüklenen Kilitlenme Raporu Kimliği <ph name="CRASH_ID" /> (Yerel Bağlam: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Geri al</translation>
<translation id="20817612488360358">Sistem proxy ayarları kullanılmak üzere ayarlandı, ancak açık bir proxy yapılandırması da belirtildi.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Bu gönderim yöntemi kullanılamıyor. Farklı bir yöntem deneyin.</translation>
<translation id="2396249848217231973">Silmeyi &amp;geri al</translation>
<translation id="2413528052993050574">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikası iptal edilmiş olabilir. Bu durum, bir yanlış yapılandırmadan veya bağlantıya müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
+<translation id="244665789865330679">Cihazınız ve hesabınız <ph name="ENROLLMENT_DOMAIN" /> tarafından yönetiliyor. Bu durumda yöneticiniz cihazınızı ve hesabınızı uzaktan yapılandırabilir.</translation>
<translation id="2463193859425327265">Ana Sayfayı değiştir</translation>
<translation id="2463739503403862330">Doldur</translation>
<translation id="2465655957518002998">Teslimat Yöntemi Seç</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> adresine ulaşmayı denediniz, ancak sunucunun sağladığı sertifika, sertifikayı veren tarafından iptal edildi. Bu, sunucunun sağladığı güvenlik kimlik bilgilerine kesinlikle güvenilmemesi gerektiği anlamına gelir. Bir saldırganla irtibat kuruyor olabilirsiniz.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4406896451731180161">arama sonuçları</translation>
+<translation id="4406972042435603828">Yöneticileriniz etkili özelliklere sahip uzantılar yüklemiş.</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> çerez</translation>
<translation id="4415426530740016218">Alınacağı Adres</translation>
<translation id="4424024547088906515">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Chrome, sunucunun güvenlik sertifikasına güvenmiyor. Bu durum, bir yanlış yapılandırmadan veya bağlantıya müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Sonuç yok</translation>
<translation id="4950898438188848926">Sekme değiştirme düğmesi, açık sekmeye geçmek için enter tuşuna basın, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">İşlemler</translation>
+<translation id="495832697253704892">Uzantı raporlama</translation>
<translation id="4958444002117714549">Listeyi genişlet</translation>
<translation id="4974590756084640048">Uyarıları yeniden etkinleştir</translation>
<translation id="4989163558385430922">Tümünü göster</translation>
<translation id="4989809363548539747">Bu eklenti desteklenmiyor</translation>
+<translation id="4996230189582812866">Raporlama</translation>
<translation id="5002932099480077015">Bu seçenek etkinleştirildiğinde Chrome, formları daha hızlı doldurmak için kartınızın bir kopyasını bu cihazda saklar.</translation>
<translation id="5014174725590676422">Chrome'da Google Asistan'ın ilk kez çalışma ekranı aşağıda gösterilmiştir</translation>
<translation id="5015510746216210676">Makine Adı:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Eyalet</translation>
<translation id="5094747076828555589">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı; Chromium, sunucunun güvenlik sertifikasına güvenmiyor. Bu durum, bir yanlış yapılandırmadan veya bağlantıya müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
<translation id="5095208057601539847">Eyalet</translation>
+<translation id="5098222253617183465">Cihazınız <ph name="ENROLLMENT_DOMAIN" /> tarafından, hesabınız ise <ph name="ACCOUNT_DOMAIN" /> tarafından yönetiliyor. Bu durumda yöneticileriniz cihazınızı ve hesabınızı uzaktan yapılandırabilir.</translation>
<translation id="5115563688576182185">(64 bit)</translation>
<translation id="5128122789703661928">Silmek üzere gönderilen bu oturum adı geçerli değil.</translation>
<translation id="5135404736266831032">Adresleri yönet...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Makine</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> dilinde değil mi? Bu hatayı bildirin</translation>
<translation id="5190835502935405962">Yer İşareti Çubuğu</translation>
+<translation id="5200263511887412697">son zamanlarda giriş yapmış cihaz kullanıcılarının listesini rapor et</translation>
<translation id="5201306358585911203">Bu sayfadaki yerleşik bir sayfanın mesajı</translation>
<translation id="5205222826937269299">Ad gerekli</translation>
<translation id="5215116848420601511">Google Pay'i kullanan ödeme yöntemleri ve adresler</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Bu siteye ulaşılamıyor</translation>
<translation id="5869522115854928033">Kayıtlı şifreler</translation>
<translation id="5887400589839399685">Kart kaydedildi</translation>
+<translation id="5893718151540690985">türleri ve donanım adresleriyle birlikte ağ arayüzleri listesini rapor et</translation>
<translation id="5893752035575986141">Kredi kartları kabul edilir.</translation>
<translation id="5901630391730855834">Sarı</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (senkronize edildi)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">İletişim Bilgilerini Düzenleyin</translation>
<translation id="5967867314010545767">Geçmişten kaldır.</translation>
<translation id="5975083100439434680">Uzaklaştır</translation>
+<translation id="5977489021191000276">Cihazınız bir yönetici tarafından yönetilmiyor.</translation>
<translation id="5977976211062815271">Bu cihazda</translation>
<translation id="598637245381783098">Ödeme uygulaması açılamıyor</translation>
<translation id="5989320800837274978">Sabit proxy sunucular veya bir .pac komut dosyası URL'si belirtilmedi.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> öğesini kullanan saldırganlar başka bir şeyi taklit eden aldatıcı uygulamalar yükleyebilir veya sizi izlemek için kullanılabilecek veriler toplayabilirler. <ph name="BEGIN_LEARN_MORE_LINK" />Daha fazla bilgi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (senkronize edildi)</translation>
<translation id="6027201098523975773">Bir ad girin</translation>
+<translation id="6033927989869462158">CPU/RAM kullanımı gibi donanım istatistiklerini rapor et</translation>
<translation id="6034000775414344507">Açık Gri</translation>
<translation id="6039846035001940113">Sorun devam ederse site sahibiyle iletişime geçin.</translation>
<translation id="6040143037577758943">Kapat</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Kullanıcı Aracısı</translation>
<translation id="6903319715792422884">Google'a bazı <ph name="BEGIN_WHITEPAPER_LINK" />sistem bilgilerini ve sayfa içeriklerini<ph name="END_WHITEPAPER_LINK" /> göndererek Güvenli Tarama'nın iyileştirilmesine yardımcı olabilirsiniz. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Kullanıcı:</translation>
+<translation id="6934672428414710184">Bu ad Google Hesabınızdan gelmektedir</translation>
+<translation id="6939583532829045966">Cihazınız <ph name="ENROLLMENT_DOMAIN" /> tarafından yönetiliyor. Bu durumda yöneticiniz cihazınızı uzaktan yapılandırabilir.</translation>
<translation id="6944692733090228304">Şifrenizi <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> tarafından yönetilmeyen bir sitede girdiniz. Hesabınızı korumak için şifrenizi başka uygulama ve sitelerde tekrar kullanmayın.</translation>
<translation id="6945221475159498467">Seç</translation>
<translation id="6948701128805548767">Alım yöntemlerini ve gereksinimlerini görmek için bir adres seçin</translation>
@@ -992,6 +1004,7 @@ Ek ayrıntılar:
&lt;li&gt;&lt;strong&gt;Uygula&lt;/strong&gt;'yı, ardından &lt;strong&gt;Tamam&lt;/strong&gt;'ı tıklayın
&lt;li&gt;Yazılımı bilgisayarınızdan kalıcı olarak nasıl kaldıracağınızı öğrenmek için &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome yardım merkezini&lt;/a&gt; ziyaret edin
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" /> yönetimi</translation>
<translation id="7416351320495623771">Şifreleri Yönet…</translation>
<translation id="7419106976560586862">Profil Yolu</translation>
<translation id="7437289804838430631">İletişim Bilgisi Ekle</translation>
@@ -1000,10 +1013,12 @@ Ek ayrıntılar:
<translation id="7442725080345379071">Açık Turuncu</translation>
<translation id="7444046173054089907">Bu site engellenmiş</translation>
<translation id="7445762425076701745">Bağlı olduğunuz sunucunun kimliği tam olarak doğrulanamıyor. Sunucuya yalnızca ağınızın içinde geçerli olan ve dış sertifika yetkilisi tarafından hiçbir şekilde sahipliği doğrulanamayacak bir ad kullanarak bağlandınız. Bazı sertifika yetkilileri bu adlar için sertifikalar yayınlasa da, bir saldırgana değil, hedeflenen web sitesine bağlandığınızdan emin olmanın herhangi bir yolu yoktur.</translation>
+<translation id="7449109375006139765">yönetim sunucusuna sistem günlükleri gönder</translation>
<translation id="7451311239929941790">Bu sorun hakkında <ph name="BEGIN_LINK" />daha fazla<ph name="END_LINK" /> bilgi edinme.</translation>
<translation id="7455133967321480974">Genel varsayılanı kullan (Engelle)</translation>
<translation id="7460618730930299168">Filtreleme sizin seçiminizden farklı. Devam etmek istiyor musunuz?</translation>
<translation id="7473891865547856676">Hayır, Teşekkürler</translation>
+<translation id="7475525192983021547">bir kullanıcının cihazı aktif olarak kullandığı dönemleri rapor et</translation>
<translation id="7481312909269577407">İleri</translation>
<translation id="7485870689360869515">Hiçbir veri bulunamadı.</translation>
<translation id="7508255263130623398">Döndürülen politika cihaz kimliği boş veya mevcut cihaz kimliğiyle eşleşmiyor</translation>
@@ -1096,6 +1111,7 @@ Ek ayrıntılar:
<translation id="7995512525968007366">Belirtilmedi</translation>
<translation id="800218591365569300">Bellekte yer açmak için diğer sekmeleri veya programları kapatmayı deneyin.</translation>
<translation id="8009225694047762179">Şifreleri Yönet</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Aşağıdaki kart ve ona ait fatura adresi kaydedilecektir. Kaydettiğiniz kartı <ph name="USER_EMAIL" /> hesabında oturumunuz açıkken kullanabilirsiniz.}other{Aşağıdaki kartlar ve onlara ait fatura adresleri kaydedilecektir. Kaydettiğiniz kartları <ph name="USER_EMAIL" /> hesabında oturumunuz açıkken kullanabilirsiniz.}}</translation>
<translation id="8012647001091218357">Şu anda ebeveynlerinize erişemedik. Lütfen tekrar deneyin.</translation>
<translation id="8025119109950072390">Bu sitedeki saldırganlar sizi kandırarak yazılım yükleme veya kişisel bilgilerinizi (örneğin şifreler, telefon numaraları veya kredi kartları) ifşa etme gibi tehlikeli şeyler yaptırabilir.</translation>
<translation id="8034522405403831421">Bu sayfa <ph name="SOURCE_LANGUAGE" /> dilinde. <ph name="TARGET_LANGUAGE" /> diline çevrilsin mi?</translation>
@@ -1106,6 +1122,7 @@ Ek ayrıntılar:
<translation id="8041940743680923270">Genel varsayılanı kullan (Sor)</translation>
<translation id="8042918947222776840">Alma Yöntemi Seç</translation>
<translation id="8057711352706143257">"<ph name="SOFTWARE_NAME" />" doğru şekilde yapılandırılmamış. Genellikle "<ph name="SOFTWARE_NAME" />" kaldırıldığında sorun çözülür. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Cihazınız şu şekilde yapılandırıldı:</translation>
<translation id="8078141288243656252">Doküman döndürüldüğünde ek açıklama özelliği kullanılamaz</translation>
<translation id="8079031581361219619">Site yeniden yüklensin mi?</translation>
<translation id="8088680233425245692">Makale görüntülenemedi.</translation>
@@ -1156,6 +1173,7 @@ Ek ayrıntılar:
<translation id="8363502534493474904">Uçak modunu kapatma</translation>
<translation id="8364627913115013041">Henüz ayarlanmadı.</translation>
<translation id="8368476060205742148">Google Play hizmetleri</translation>
+<translation id="8371889962595521444">Özel kök sertifikalar</translation>
<translation id="8380941800586852976">Tehlikeli</translation>
<translation id="8381674639488873545">Bu ödemeler bir defalık alınabileceği gibi yinelenen ödemeler de olabilir ve bu durum açıkça belli olmayabilir. <ph name="BEGIN_LINK" />Yine de göster<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Son ziyaret ettiğiniz yer işaretleri burada görünür</translation>
@@ -1165,6 +1183,7 @@ Ek ayrıntılar:
<translation id="8416694386774425977">Ağ yapılandırması geçersiz ve içe aktarılamadı.
Ek ayrıntılar:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Cihaz <ph name="ENROLLMENT_DOMAIN" /> tarafından yönetiliyor</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Değiştir</translation>
<translation id="8428213095426709021">Ayarlar</translation>
@@ -1226,6 +1245,7 @@ Ek ayrıntılar:
<translation id="8932102934695377596">Saatiniz geri</translation>
<translation id="893332455753468063">Ad Ekleyin</translation>
<translation id="8938939909778640821">Kabul edilen kredi kartları ve ön ödemeli kartlar</translation>
+<translation id="894185898663964645">Yöneticiniz, ziyaret ettiğiniz web sitelerinin içeriğinin yönetici tarafından görülmesini sağlayabilen özel kök sertifikalar yapılandırmış.</translation>
<translation id="8943282376843390568">Küf yeşili</translation>
<translation id="8957210676456822347">Giriş Portalı Yetkilendirmesi</translation>
<translation id="8968766641738584599">Kartı kaydet</translation>
diff --git a/chromium/components/strings/components_strings_uk.xtb b/chromium/components/strings/components_strings_uk.xtb
index 556398b0f4b..658dfb0734b 100644
--- a/chromium/components/strings/components_strings_uk.xtb
+++ b/chromium/components/strings/components_strings_uk.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Сторінки цією мовою (<ph name="LANGUAGE" />) не перекладатимуться.</translation>
<translation id="2053553514270667976">Поштовий індекс</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 пропозиція}one{# пропозиція}few{# пропозиції}many{# пропозицій}other{# пропозиції}}</translation>
+<translation id="2068124040035837596"><ph name="ENROLLMENT_DOMAIN" /> керує вашим обліковим записом. Це означає, що адміністратор може віддалено налаштовувати його.</translation>
<translation id="2068663545051464999">Ідентифікатор завантаженого звіту про аварійне завершення роботи – <ph name="CRASH_ID" /> (Локальний контекст: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Відмінити</translation>
<translation id="20817612488360358">Системні параметри проксі-сервера налаштовано для використання, але чітко вказано налаштування проксі-сервера.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Цей спосіб відправлення недоступний. Виберіть інший спосіб.</translation>
<translation id="2396249848217231973">&amp;Відмінити видалення</translation>
<translation id="2413528052993050574">Цей сервер не зміг довести, що він – домен <ph name="DOMAIN" />. Можливо, його сертифікат безпеки відкликано. Імовірні причини: неправильна конфігурація або хтось намагається перехопити ваше з’єднання.</translation>
+<translation id="244665789865330679"><ph name="ENROLLMENT_DOMAIN" /> керує вашим пристроєм і обліковим записом. Це означає, що адміністратор може віддалено налаштовувати їх.</translation>
<translation id="2463193859425327265">Змінити домашню сторінку</translation>
<translation id="2463739503403862330">Заповнити</translation>
<translation id="2465655957518002998">Вибрати спосіб доставки</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Ви пробували зв’язатися з доменом <ph name="DOMAIN" />, проте сервер надав сертифікат, відкликаний його видавцем. Це означає, що не варто довіряти обліковим даним системи захисту, наданим сервером. Можливо, ви обмінюєтеся даними зі зловмисником.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4406896451731180161">результати пошуку</translation>
+<translation id="4406972042435603828">Ваші адміністратори встановили потужні розширення.</translation>
<translation id="4408413947728134509">Файли cookie: <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Адреса отримання</translation>
<translation id="4424024547088906515">Цей сервер не зміг довести, що він – домен <ph name="DOMAIN" />. Chrome не вважає його сертифікат безпеки надійним. Імовірні причини: неправильна конфігурація або хтось намагається перехопити ваше з’єднання.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Не знайдено жодного результату</translation>
<translation id="4950898438188848926">Кнопка перемикання вкладки: натисніть Enter, щоб перейти на відкриту вкладку, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Дії</translation>
+<translation id="495832697253704892">Звіти про розширення</translation>
<translation id="4958444002117714549">Розгорнути список</translation>
<translation id="4974590756084640048">Показувати застереження</translation>
<translation id="4989163558385430922">Показати все</translation>
<translation id="4989809363548539747">Цей плагін не підтримується</translation>
+<translation id="4996230189582812866">Звітування</translation>
<translation id="5002932099480077015">Коли цю функцію ввімкнено, Chrome зберігає копію даних вашої картки на пристрої, щоб ви могли швидше заповнювати форми.</translation>
<translation id="5014174725590676422">Показано екран першого запуску Google Асистента в Chrome</translation>
<translation id="5015510746216210676">Назва пристрою:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Штат/провінція</translation>
<translation id="5094747076828555589">Цей сервер не зміг довести, що він – домен <ph name="DOMAIN" />. Chromium не вважає його сертифікат безпеки надійним. Імовірні причини: неправильна конфігурація або хтось намагається перехопити ваше з’єднання.</translation>
<translation id="5095208057601539847">Провінція</translation>
+<translation id="5098222253617183465"><ph name="ENROLLMENT_DOMAIN" /> керує вашим пристроєм, а <ph name="ACCOUNT_DOMAIN" /> – обліковим записом. Це означає, що адміністратори можуть віддалено налаштовувати їх.</translation>
<translation id="5115563688576182185">(64-розрядна версія)</translation>
<translation id="5128122789703661928">Сеанс із цією назвою не можна видалити.</translation>
<translation id="5135404736266831032">Керувати адресами…</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Комп’ютер</translation>
<translation id="5179510805599951267">Це не <ph name="ORIGINAL_LANGUAGE" />? Повідомте про помилку</translation>
<translation id="5190835502935405962">Панель закладок</translation>
+<translation id="5200263511887412697">надавати список користувачів, які нещодавно входили на пристрій</translation>
<translation id="5201306358585911203">Повідомлення з вбудованої сторінки на цій сторінці</translation>
<translation id="5205222826937269299">Укажіть ім’я</translation>
<translation id="5215116848420601511">Способи оплати й адреси, пов’язані з Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Немає зв’язку із сайтом</translation>
<translation id="5869522115854928033">Збережені паролі</translation>
<translation id="5887400589839399685">Картку збережено</translation>
+<translation id="5893718151540690985">повідомляти список мережевих інтерфейсів, указуючи їх типи й адреси апаратного забезпечення</translation>
<translation id="5893752035575986141">Кредитні картки, які приймаються.</translation>
<translation id="5901630391730855834">Жовтий</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (синхронізовано)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Змініть контактну інформацію</translation>
<translation id="5967867314010545767">Видалити з історії</translation>
<translation id="5975083100439434680">Зменшити масштаб</translation>
+<translation id="5977489021191000276">Адміністратор не керує вашим пристроєм.</translation>
<translation id="5977976211062815271">На цьому пристрої</translation>
<translation id="598637245381783098">Неможливо відкрити додаток для платежів</translation>
<translation id="5989320800837274978">Не вказано ні фіксованих проксі-серверів, ні URL-адрес сценарію .pac.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Зловмисники на сайті <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> можуть установити на ваш пристрій оманливі додатки, які видають себе за інший вміст або збирають дані для відстеження вашої активності. <ph name="BEGIN_LEARN_MORE_LINK" />Докладніше<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (синхронізовано)</translation>
<translation id="6027201098523975773">Введіть ім’я</translation>
+<translation id="6033927989869462158">повідомляти статистику апаратного забезпечення, як-от використання ЦП або оперативної пам’яті</translation>
<translation id="6034000775414344507">Світло-сірий</translation>
<translation id="6039846035001940113">Якщо проблема не зникла, зв’яжіться з власником сайту.</translation>
<translation id="6040143037577758943">Закрити</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Агент користувача</translation>
<translation id="6903319715792422884">Допоможіть покращити Безпечний перегляд, надсилаючи в Google деяку <ph name="BEGIN_WHITEPAPER_LINK" />інформацію про систему та вміст сторінок<ph name="END_WHITEPAPER_LINK" />. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Користувач:</translation>
+<translation id="6934672428414710184">Це ім’я з вашого облікового запису Google</translation>
+<translation id="6939583532829045966"><ph name="ENROLLMENT_DOMAIN" /> керує вашим пристроєм. Це означає, що адміністратор може віддалено налаштовувати його.</translation>
<translation id="6944692733090228304">Ви ввели пароль на сайті, яким не керує <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" />. Щоб захистити свій обліковий запис, не використовуйте цей пароль для інших додатків і сайтів.</translation>
<translation id="6945221475159498467">Вибрати</translation>
<translation id="6948701128805548767">Укажіть адресу, щоб переглянути способи отримання та вимоги.</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;Натисніть &lt;strong&gt;Застосувати&lt;/strong&gt;, а потім – кнопку &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Відвідайте &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Довідковий центр Chrome&lt;/a&gt;, щоб дізнатися, як повністю видалити програмне забезпечення з комп’ютера
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Керування <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Керувати паролями…</translation>
<translation id="7419106976560586862">Шлях до профілю</translation>
<translation id="7437289804838430631">Додати контактну інформацію</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">Світло-оранжевий</translation>
<translation id="7444046173054089907">Цей сайт заблоковано</translation>
<translation id="7445762425076701745">Ідентифікацію сервера, з яким ви з'єднані, не можна повністю підтвердити. Ви з'єднані із сервером за допомогою імені, дійсного лише у вашій мережі, і зовнішній центр сертифікації не має способів підтвердити право власності на це ім'я. Хоча деякі центри сертифікації, попри все, видають сертифікати на такі імена, неможливо цілком упевнитися, що ви з'єднані з безпечним сайтом, а не зі зловмисником.</translation>
+<translation id="7449109375006139765">надсилати системні журнали на сервер керування</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />дізнатися більше<ph name="END_LINK" /> про цю проблему.</translation>
<translation id="7455133967321480974">Використовувати глобальне налаштування за умовчанням (Блокувати)</translation>
<translation id="7460618730930299168">Дані відрізняються від вибраних. Продовжити?</translation>
<translation id="7473891865547856676">Ні, дякую</translation>
+<translation id="7475525192983021547">повідомляти періоди активності пристрою</translation>
<translation id="7481312909269577407">Переслати</translation>
<translation id="7485870689360869515">Даних не знайдено.</translation>
<translation id="7508255263130623398">Отриманий ідентифікатор правил пристрою порожній або не збігається з поточним ідентифікатором пристрою</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">Не вказано</translation>
<translation id="800218591365569300">Щоб звільнити пам’ять, закрийте інші вкладки та програми.</translation>
<translation id="8009225694047762179">Керувати паролями</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Цю картку та її платіжну адресу буде збережено. Ви зможете скористатися нею, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}one{Ці картки та їх платіжні адреси буде збережено. Ви зможете скористатися ними, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}few{Ці картки та їх платіжні адреси буде збережено. Ви зможете скористатися ними, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}many{Ці картки та їх платіжні адреси буде збережено. Ви зможете скористатися ними, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}other{Ці картки та їх платіжні адреси буде збережено. Ви зможете скористатися ними, коли ввійдете в обліковий запис <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Не вдалося зв’язатися з вашими батьками. Повторіть спробу.</translation>
<translation id="8025119109950072390">Зловмисники на цьому сайті можуть обманом змусити вас виконати небезпечну дію, як-от установити програмне забезпечення або повідомити особисту інформацію (наприклад, паролі, номери телефонів або кредитних карток).</translation>
<translation id="8034522405403831421">Мова цієї сторінки: <ph name="SOURCE_LANGUAGE" />. Перекласти її такою мовою: <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">Використовувати глобальне налаштування за умовчанням (Запитувати)</translation>
<translation id="8042918947222776840">Вибрати спосіб отримання</translation>
<translation id="8057711352706143257"><ph name="SOFTWARE_NAME" /> налаштовано неправильно. Якщо видалити програмне забезпечення <ph name="SOFTWARE_NAME" />, проблема зазвичай зникає. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Ваш пристрій налаштовано, щоб:</translation>
<translation id="8078141288243656252">Коли документ обернено, створення приміток недоступне</translation>
<translation id="8079031581361219619">Оновити сайт?</translation>
<translation id="8088680233425245692">Не вдалося переглянути статтю.</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">вимкнути режим польоту</translation>
<translation id="8364627913115013041">Не встановлено.</translation>
<translation id="8368476060205742148">Сервіси Google Play</translation>
+<translation id="8371889962595521444">Власні кореневі сертифікати</translation>
<translation id="8380941800586852976">Небезпечна</translation>
<translation id="8381674639488873545">Такі стягнення можуть бути одноразовими чи регулярними й неочевидними. <ph name="BEGIN_LINK" />Усе одно показати<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Тут відображатимуться нещодавно відкриті закладки</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">Конфігурація мережі недійсна та не може імпортуватися.
Додаткові відомості:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533"><ph name="ENROLLMENT_DOMAIN" /> керує пристроєм</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Змінити</translation>
<translation id="8428213095426709021">Налаштування</translation>
@@ -1226,6 +1245,7 @@
<translation id="8932102934695377596">Ваш годинник запізнюється</translation>
<translation id="893332455753468063">Додайте ім’я</translation>
<translation id="8938939909778640821">Прийнятні кредитні та передплачені картки</translation>
+<translation id="894185898663964645">Адміністратор налаштував власні кореневі сертифікати, які дозволяють йому переглядати вміст відвіданих вами веб-сайтів.</translation>
<translation id="8943282376843390568">Лаймовий</translation>
<translation id="8957210676456822347">Авторизація приєднаного порталу</translation>
<translation id="8968766641738584599">Зберегти картку</translation>
diff --git a/chromium/components/strings/components_strings_vi.xtb b/chromium/components/strings/components_strings_vi.xtb
index f0ccb7f74a5..2cce1a9b612 100644
--- a/chromium/components/strings/components_strings_vi.xtb
+++ b/chromium/components/strings/components_strings_vi.xtb
@@ -129,7 +129,7 @@
<translation id="1656489000284462475">Nhận hàng</translation>
<translation id="1662550410081243962">Lưu và điền phương thức thanh toán</translation>
<translation id="1663943134801823270">Thẻ và địa chỉ từ Chrome. Bạn có thể quản lý thẻ và địa chỉ trong <ph name="BEGIN_LINK" />Cài đặt<ph name="END_LINK" />.</translation>
-<translation id="1671391448414634642">Kể từ bây giờ trở đi, Trang viết bằng <ph name="SOURCE_LANGUAGE" /> sẽ được dịch sang <ph name="TARGET_LANGUAGE" />.</translation>
+<translation id="1671391448414634642">Kể từ bây giờ trở đi, các trang viết bằng <ph name="SOURCE_LANGUAGE" /> sẽ được dịch sang <ph name="TARGET_LANGUAGE" />.</translation>
<translation id="1676269943528358898"><ph name="SITE" /> thường sử dụng mã hóa để bảo vệ thông tin của bạn. Khi Google Chrome tìm cách kết nối với <ph name="SITE" /> tại thời điểm này, trang web đã gửi lại thông tin đăng nhập không chính xác và bất thường. Điều này có thể xảy ra khi kẻ tấn công đang cố gắng giả mạo là <ph name="SITE" /> hoặc màn hình đăng nhập Wi-Fi đã làm gián đoạn kết nối. Thông tin của bạn vẫn an toàn do Google Chrome đã ngừng kết nối trước khi bất kỳ dữ liệu nào được trao đổi.</translation>
<translation id="168841957122794586">Chứng chỉ máy chủ chứa khóa mật mã yếu.</translation>
<translation id="1697532407822776718">Bạn đã hoàn tất!</translation>
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">Các trang viết bằng <ph name="LANGUAGE" /> sẽ không được dịch.</translation>
<translation id="2053553514270667976">Mã zip</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 đề xuất}other{# đề xuất}}</translation>
+<translation id="2068124040035837596"><ph name="ENROLLMENT_DOMAIN" /> quản lý tài khoản của bạn. Điều này có nghĩa là quản trị viên có thể định cấu hình tài khoản của bạn từ xa.</translation>
<translation id="2068663545051464999">ID báo cáo sự cố đã tải lên <ph name="CRASH_ID" /> (Ngữ cảnh cục bộ: <ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">Hoàn tác</translation>
<translation id="20817612488360358">Cài đặt proxy hệ thống được đặt để sử dụng nhưng cấu hình proxy rõ ràng cũng được chỉ định.</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">Phương thức giao hàng này không có sẵn. Hãy thử một phương thức khác.</translation>
<translation id="2396249848217231973">&amp;Hoàn tác xóa</translation>
<translation id="2413528052993050574">Máy chủ này không chứng minh được rằng đó là <ph name="DOMAIN" />; chứng chỉ bảo mật của máy chủ này có thể đã bị thu hồi. Điều này có thể do định cấu hình sai hoặc có kẻ tấn công chặn kết nối của bạn.</translation>
+<translation id="244665789865330679"><ph name="ENROLLMENT_DOMAIN" /> quản lý thiết bị và tài khoản của bạn. Điều này có nghĩa là quản trị viên có thể định cấu hình thiết bị và tài khoản của bạn từ xa.</translation>
<translation id="2463193859425327265">Thay đổi trang chủ</translation>
<translation id="2463739503403862330">Điền</translation>
<translation id="2465655957518002998">Chọn cách giao hàng</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">Bạn đã cố truy cập vào <ph name="DOMAIN" /> nhưng chứng chỉ mà máy chủ xuất trình đã bị nhà phát hành thu hồi. Điều này có nghĩa là giấy ủy nhiệm bảo mật mà máy chủ xuất trình hoàn toàn không đáng tin cậy. Bạn có thể đang giao tiếp với kẻ tấn công.</translation>
<translation id="4378154925671717803">Điện thoại</translation>
<translation id="4406896451731180161">kết quả tìm kiếm</translation>
+<translation id="4406972042435603828">Quản trị viên của bạn đã cài đặt các tiện ích có nhiều tính năng nâng cao.</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4415426530740016218">Địa chỉ nhận hàng</translation>
<translation id="4424024547088906515">Máy chủ này không chứng minh được rằng đó là <ph name="DOMAIN" />; chứng chỉ bảo mật của máy chủ này không được Chrome tin cậy. Điều này có thể do định cấu hình sai hoặc có kẻ tấn công chặn kết nối của bạn.</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">Không tìm thấy kết quả nào</translation>
<translation id="4950898438188848926">Nút chuyển đổi tab, nhấn phím Enter để chuyển sang tab đang mở, <ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">Tác vụ</translation>
+<translation id="495832697253704892">Báo cáo tiện ích</translation>
<translation id="4958444002117714549">Mở rộng danh sách</translation>
<translation id="4974590756084640048">Bật lại cảnh báo</translation>
<translation id="4989163558385430922">Xem tất cả</translation>
<translation id="4989809363548539747">Plugin này không được hỗ trợ</translation>
+<translation id="4996230189582812866">Báo cáo</translation>
<translation id="5002932099480077015">Nếu được bật, Chrome sẽ lưu trữ bản sao thẻ của bạn trên thiết bị này để điền vào biểu mẫu nhanh hơn.</translation>
<translation id="5014174725590676422">Màn hình chạy đầu tiên của Trợ lý Google trong Chrome đã được hiển thị</translation>
<translation id="5015510746216210676">Tên máy:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">Tỉnh</translation>
<translation id="5094747076828555589">Máy chủ này không chứng minh được rằng đó là <ph name="DOMAIN" />; chứng chỉ bảo mật của máy chủ này không được Chromium tin cậy. Điều này có thể do định cấu hình sai hoặc có kẻ tấn công chặn kết nối của bạn.</translation>
<translation id="5095208057601539847">Tỉnh</translation>
+<translation id="5098222253617183465"><ph name="ENROLLMENT_DOMAIN" /> quản lý thiết bị của bạn và <ph name="ACCOUNT_DOMAIN" /> quản lý tài khoản của bạn. Điều này có nghĩa là quản trị viên có thể định cấu hình thiết bị và tài khoản của bạn từ xa.</translation>
<translation id="5115563688576182185">(64 bit)</translation>
<translation id="5128122789703661928">Không thể xóa phiên do tên phiên không hợp lệ.</translation>
<translation id="5135404736266831032">Quản lý địa chỉ...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">Máy</translation>
<translation id="5179510805599951267">Không ở <ph name="ORIGINAL_LANGUAGE" />? Báo cáo lỗi này</translation>
<translation id="5190835502935405962">Thanh Dấu trang</translation>
+<translation id="5200263511887412697">báo cáo danh sách những người dùng thiết bị đã đăng nhập gần đây</translation>
<translation id="5201306358585911203">Một trang được nhúng trên trang này cho biết</translation>
<translation id="5205222826937269299">Cần có tên</translation>
<translation id="5215116848420601511">Địa chỉ và phương thức thanh toán lưu trong Google Pay</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">Không thể truy cập trang web này</translation>
<translation id="5869522115854928033">Mật khẩu đã lưu</translation>
<translation id="5887400589839399685">Đã lưu thẻ</translation>
+<translation id="5893718151540690985">báo cáo danh sách các giao diện mạng kèm thông tin về loại giao diện và địa chỉ phần cứng</translation>
<translation id="5893752035575986141">Thẻ tín dụng được chấp nhận.</translation>
<translation id="5901630391730855834">Vàng</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (được đồng bộ hóa)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">Chỉnh sửa thông tin liên hệ</translation>
<translation id="5967867314010545767">Xóa khỏi lịch sử</translation>
<translation id="5975083100439434680">Thu nhỏ</translation>
+<translation id="5977489021191000276">Thiết bị của bạn không do quản trị viên quản lý.</translation>
<translation id="5977976211062815271">Trên thiết bị này</translation>
<translation id="598637245381783098">Không thể mở ứng dụng thanh toán</translation>
<translation id="5989320800837274978">Cả máy chủ proxy cố định và URL tập lệnh .pac đều chưa được chỉ định.</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">Những kẻ tấn công trên <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> có thể cài đặt ứng dụng lừa đảo giả vờ là nội dung khác hoặc thu thập dữ liệu có thể dùng để theo dõi bạn. <ph name="BEGIN_LEARN_MORE_LINK" />Tìm hiểu thêm<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />, <ph name="TYPE_2" />, <ph name="TYPE_3" /> (được đồng bộ hóa)</translation>
<translation id="6027201098523975773">Nhập tên</translation>
+<translation id="6033927989869462158">báo cáo thống kê phần cứng chẳng hạn như mức sử dụng CPU/RAM</translation>
<translation id="6034000775414344507">Xám nhạt</translation>
<translation id="6039846035001940113">Nếu sự cố vẫn tiếp diễn, hãy liên hệ với chủ sở hữu trang web.</translation>
<translation id="6040143037577758943">Đóng</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">Tác nhân Người dùng</translation>
<translation id="6903319715792422884">Giúp cải thiện tính năng Duyệt web an toàn bằng cách gửi một số <ph name="BEGIN_WHITEPAPER_LINK" />thông tin hệ thống và nội dung trang<ph name="END_WHITEPAPER_LINK" /> tới Google. <ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">Người dùng:</translation>
+<translation id="6934672428414710184">Tên này lấy từ Tài khoản Google của bạn</translation>
+<translation id="6939583532829045966"><ph name="ENROLLMENT_DOMAIN" /> quản lý thiết bị của bạn. Điều này có nghĩa là quản trị viên có thể định cấu hình thiết bị của bạn từ xa.</translation>
<translation id="6944692733090228304">Bạn đã nhập mật khẩu trên trang web không do <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> quản lý. Để bảo vệ tài khoản, không sử dụng lại mật khẩu của bạn trên các ứng dụng và trang web khác.</translation>
<translation id="6945221475159498467">Chọn</translation>
<translation id="6948701128805548767">Để xem các yêu cầu và phương thức nhận hàng, hãy chọn một địa chỉ</translation>
@@ -992,6 +1004,7 @@ Thông tin chi tiết bổ sung:
&lt;li&gt;Nhấp vào &lt;strong&gt;Apply&lt;/strong&gt; (Áp dụng), sau đó nhấp vào &lt;strong&gt;OK&lt;/strong&gt;
&lt;li&gt;Truy cập vào &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Trung tâm trợ giúp Chrome&lt;/a&gt; để tìm hiểu cách xóa vĩnh viễn phần mềm này khỏi máy tính của bạn
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">Quản lý <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">Quản lý mật khẩu…</translation>
<translation id="7419106976560586862">Đường dẫn cấu hình</translation>
<translation id="7437289804838430631">Thêm thông tin liên hệ</translation>
@@ -1000,10 +1013,12 @@ Thông tin chi tiết bổ sung:
<translation id="7442725080345379071">Cam nhạt</translation>
<translation id="7444046173054089907">Trang web này bị chặn</translation>
<translation id="7445762425076701745">Không thể xác thực đầy đủ nhận dạng của máy chủ bạn đã kết nối. Bạn đã kết nối vào máy chủ bằng một tên chỉ hợp lệ trong mạng của bạn và đó là tên mà các tổ chức phát hành chứng chỉ bên ngoài không thể xác thực được. Vì một số tổ chức phát hành chứng chỉ sẽ cấp chứng chỉ cho các tên này thay thế, nên không có cách nào đảm bảo bạn được kết nối tới trang web đã chỉ định và không phải là kẻ tấn công.</translation>
+<translation id="7449109375006139765">gửi nhật ký hệ thống đến máy chủ quản lý</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />Tìm hiểu thêm<ph name="END_LINK" /> về sự cố này.</translation>
<translation id="7455133967321480974">Sử dụng cài đặt mặc định chung (Chặn)</translation>
<translation id="7460618730930299168">Màn hình khác với nội dung bạn đã chọn. Bạn có muốn tiếp tục không?</translation>
<translation id="7473891865547856676">Không, cảm ơn</translation>
+<translation id="7475525192983021547">báo cáo khoảng thời gian khi người dùng sử dụng thiết bị</translation>
<translation id="7481312909269577407">Chuyển tiếp</translation>
<translation id="7485870689360869515">Không tìm thấy dữ liệu.</translation>
<translation id="7508255263130623398">ID thiết bị thuộc chính sách trả lại trống hoặc không khớp với ID của thiết bị hiện tại</translation>
@@ -1096,6 +1111,7 @@ Thông tin chi tiết bổ sung:
<translation id="7995512525968007366">Không chỉ định</translation>
<translation id="800218591365569300">Thử đóng các tab hoặc chương trình khác để giải phóng bộ nhớ.</translation>
<translation id="8009225694047762179">Quản lý mật khẩu</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{Thẻ này và địa chỉ thanh toán của thẻ sẽ được lưu. Bạn có thể sử dụng thẻ khi đăng nhập vào <ph name="USER_EMAIL" />.}other{Các thẻ này và địa chỉ thanh toán của thẻ sẽ được lưu. Bạn có thể sử dụng các thẻ này khi đăng nhập vào <ph name="USER_EMAIL" />.}}</translation>
<translation id="8012647001091218357">Chúng tôi không thể liên lạc với cha mẹ của bạn vào thời điểm này. Vui lòng thử lại.</translation>
<translation id="8025119109950072390">Những kẻ tấn công trên trang web này có thể đánh lừa bạn làm một việc gì đó nguy hiểm như cài đặt phần mềm hoặc tiết lộ thông tin cá nhân của bạn (ví dụ: mật khẩu, số điện thoại hoặc thẻ tín dụng).</translation>
<translation id="8034522405403831421">Trang này có ngôn ngữ là <ph name="SOURCE_LANGUAGE" />. Dịch trang này sang <ph name="TARGET_LANGUAGE" />?</translation>
@@ -1106,6 +1122,7 @@ Thông tin chi tiết bổ sung:
<translation id="8041940743680923270">Sử dụng cài đặt mặc định chung (Hỏi)</translation>
<translation id="8042918947222776840">Chọn phương thức nhận hàng</translation>
<translation id="8057711352706143257">Cấu hình của "<ph name="SOFTWARE_NAME" />" không chính xác. Việc gỡ cài đặt "<ph name="SOFTWARE_NAME" />" thường sẽ khắc phục được sự cố này. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">Thiết bị của bạn đã được định cấu hình thành:</translation>
<translation id="8078141288243656252">Không thể chú thích khi xoay</translation>
<translation id="8079031581361219619">Tải lại trang web?</translation>
<translation id="8088680233425245692">Không xem được bài viết.</translation>
@@ -1156,6 +1173,7 @@ Thông tin chi tiết bổ sung:
<translation id="8363502534493474904">Tắt chế độ trên máy bay</translation>
<translation id="8364627913115013041">Chưa được đặt.</translation>
<translation id="8368476060205742148">Dịch vụ của Google Play</translation>
+<translation id="8371889962595521444">Chứng chỉ gốc tùy chỉnh</translation>
<translation id="8380941800586852976">Nguy hiểm</translation>
<translation id="8381674639488873545">Những khoản phí này có thể là khoản thu một lần hoặc định kỳ và có thể không rõ ràng. <ph name="BEGIN_LINK" />Vẫn hiển thị<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">Dấu trang bạn truy cập gần đây sẽ xuất hiện ở đây</translation>
@@ -1165,6 +1183,7 @@ Thông tin chi tiết bổ sung:
<translation id="8416694386774425977">Cấu hình mạng này là không hợp lệ và không thể nhập được.
Thông tin chi tiết bổ sung:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">Thiết bị do <ph name="ENROLLMENT_DOMAIN" /> quản lý</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">Thay đổi</translation>
<translation id="8428213095426709021">Cài đặt</translation>
@@ -1226,6 +1245,7 @@ Thông tin chi tiết bổ sung:
<translation id="8932102934695377596">Đồng hồ của bạn chạy chậm</translation>
<translation id="893332455753468063">Thêm tên</translation>
<translation id="8938939909778640821">Thẻ tín dụng và thẻ trả trước được chấp nhận</translation>
+<translation id="894185898663964645">Quản trị viên của bạn đã định cấu hình chứng chỉ gốc tùy chỉnh. Điều này có thể cho phép quản trị viên xem nội dung của các trang web mà bạn truy cập.</translation>
<translation id="8943282376843390568">Vàng chanh</translation>
<translation id="8957210676456822347">Ủy quyền cổng bị khóa</translation>
<translation id="8968766641738584599">Lưu thẻ</translation>
diff --git a/chromium/components/strings/components_strings_zh-CN.xtb b/chromium/components/strings/components_strings_zh-CN.xtb
index 80fc500a628..012d1730f70 100644
--- a/chromium/components/strings/components_strings_zh-CN.xtb
+++ b/chromium/components/strings/components_strings_zh-CN.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">系统不会翻译<ph name="LANGUAGE" />网页。</translation>
<translation id="2053553514270667976">邮编</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 条建议}other{# 条建议}}</translation>
+<translation id="2068124040035837596">您的帐号由 <ph name="ENROLLMENT_DOMAIN" /> 管理。这意味着,您的管理员可能会远程配置您的帐号。</translation>
<translation id="2068663545051464999">已上传的崩溃报告的 ID:<ph name="CRASH_ID" />(本地上下文:<ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">撤消</translation>
<translation id="20817612488360358">已设置为使用系统代理设置,但同时指定了一个明确的代理配置。</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">该送货方式不可用。请另选一种方式。</translation>
<translation id="2396249848217231973">撤消删除(&amp;U)</translation>
<translation id="2413528052993050574">此服务器无法证明它是<ph name="DOMAIN" />;其安全证书可能已被撤消。出现此问题的原因可能是配置有误或您的连接被拦截了。</translation>
+<translation id="244665789865330679">您的设备和帐号由 <ph name="ENROLLMENT_DOMAIN" /> 管理。这意味着,您的管理员可能会远程配置您的设备和帐号。</translation>
<translation id="2463193859425327265">更改主页</translation>
<translation id="2463739503403862330">填充</translation>
<translation id="2465655957518002998">选择速递方式</translation>
@@ -557,6 +559,7 @@
<translation id="4377125064752653719">您尝试访问的是 <ph name="DOMAIN" />,但服务器出示的证书已被其颁发者吊销。这表明绝对不应该信任此服务器出示的安全凭据。您可能正在与攻击者进行通信。</translation>
<translation id="4378154925671717803">电话机</translation>
<translation id="4406896451731180161">搜索结果</translation>
+<translation id="4406972042435603828">您的管理员安装了一些具有强大功能的扩展程序。</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" />Cookie</translation>
<translation id="4415426530740016218">取货地址</translation>
<translation id="4424024547088906515">此服务器无法证明它是<ph name="DOMAIN" />;Chrome不信任其安全证书。出现此问题的原因可能是配置有误或您的连接被拦截了。</translation>
@@ -628,10 +631,12 @@
<translation id="4943872375798546930">找不到结果</translation>
<translation id="4950898438188848926">标签页切换按钮,按 Enter 键可切换到打开的标签页,<ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">操作</translation>
+<translation id="495832697253704892">扩展程序报告</translation>
<translation id="4958444002117714549">展开列表</translation>
<translation id="4974590756084640048">重新启用警告功能</translation>
<translation id="4989163558385430922">查看全部</translation>
<translation id="4989809363548539747">该插件不受支持</translation>
+<translation id="4996230189582812866">报告</translation>
<translation id="5002932099480077015">如果您选中此项,Chrome 会将您的卡的副本存储在此设备上,以加快表单填写速度。</translation>
<translation id="5014174725590676422">显示 Chrome 中的 Google 助理的首次运行屏幕</translation>
<translation id="5015510746216210676">设备名称:</translation>
@@ -652,6 +657,7 @@
<translation id="5089810972385038852">州/省/直辖市/自治区</translation>
<translation id="5094747076828555589">此服务器无法证明它是<ph name="DOMAIN" />;Chromium不信任其安全证书。出现此问题的原因可能是配置有误或您的连接被拦截了。</translation>
<translation id="5095208057601539847">省</translation>
+<translation id="5098222253617183465">您的设备由 <ph name="ENROLLMENT_DOMAIN" /> 管理,而您的帐号由 <ph name="ACCOUNT_DOMAIN" /> 管理。这意味着,您的管理员可能会远程配置您的设备和帐号。</translation>
<translation id="5115563688576182185">(64 位)</translation>
<translation id="5128122789703661928">无法删除此会话,因为它的名称无效。</translation>
<translation id="5135404736266831032">管理地址…</translation>
@@ -664,6 +670,7 @@
<translation id="5172758083709347301">本机</translation>
<translation id="5179510805599951267">不是<ph name="ORIGINAL_LANGUAGE" />?报告此错误</translation>
<translation id="5190835502935405962">书签栏</translation>
+<translation id="5200263511887412697">以列表的形式报告最近登录过的设备用户</translation>
<translation id="5201306358585911203">此网页上的嵌入式页面显示</translation>
<translation id="5205222826937269299">需要提供名称</translation>
<translation id="5215116848420601511">Google Pay 中存储的付款方式和地址信息</translation>
@@ -765,6 +772,7 @@
<translation id="5869405914158311789">无法访问此网站</translation>
<translation id="5869522115854928033">已保存的密码</translation>
<translation id="5887400589839399685">已保存卡片</translation>
+<translation id="5893718151540690985">以列表的形式报告网络接口及其类型和硬件地址</translation>
<translation id="5893752035575986141">接受信用卡。</translation>
<translation id="5901630391730855834">黄色</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" />(已同步)</translation>
@@ -778,6 +786,7 @@
<translation id="5967592137238574583">修改联系信息</translation>
<translation id="5967867314010545767">从历史记录中移除</translation>
<translation id="5975083100439434680">缩小</translation>
+<translation id="5977489021191000276">您的设备不受管理员管理。</translation>
<translation id="5977976211062815271">在这部设备上</translation>
<translation id="598637245381783098">无法打开付款应用</translation>
<translation id="5989320800837274978">固定代理服务器和 .pac 脚本网址均未指定。</translation>
@@ -789,6 +798,7 @@
<translation id="6017850046339264347"><ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 上的攻击者可能会安装欺骗性应用来冒充其他内容或收集可用于对您进行跟踪的数据。<ph name="BEGIN_LEARN_MORE_LINK" />了解详情<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />、<ph name="TYPE_2" />、<ph name="TYPE_3" />(已同步)</translation>
<translation id="6027201098523975773">请输入名称</translation>
+<translation id="6033927989869462158">报告硬件统计信息(例如 CPU/RAM 使用情况)</translation>
<translation id="6034000775414344507">浅灰色</translation>
<translation id="6039846035001940113">如果问题仍然存在,请与网站所有者联系。</translation>
<translation id="6040143037577758943">关闭</translation>
@@ -900,6 +910,8 @@
<translation id="6897140037006041989">用户代理</translation>
<translation id="6903319715792422884">您可以选择向 Google 发送一些<ph name="BEGIN_WHITEPAPER_LINK" />系统信息和网页内容<ph name="END_WHITEPAPER_LINK" />,以帮助我们改进安全浏览功能。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">用户:</translation>
+<translation id="6934672428414710184">此名称来自您的 Google 帐号</translation>
+<translation id="6939583532829045966">您的设备由 <ph name="ENROLLMENT_DOMAIN" /> 管理。这意味着,您的管理员可能会远程配置您的设备。</translation>
<translation id="6944692733090228304">您在一个不受 <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> 管理的网站上输入了您的密码。为了保护您的帐号,请不要在其他应用和网站上重复使用您的密码。</translation>
<translation id="6945221475159498467">选择</translation>
<translation id="6948701128805548767">要查看取货方式和要求,请选择相应地址</translation>
@@ -987,6 +999,7 @@
&lt;li&gt;依次点击&lt;strong&gt;应用&lt;/strong&gt;和&lt;strong&gt;确定&lt;/strong&gt;
&lt;li&gt;访问 &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome 帮助中心&lt;/a&gt;,了解如何从您的计算机中永久移除该软件
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399"><ph name="PRODUCT_NAME" />管理</translation>
<translation id="7416351320495623771">管理密码…</translation>
<translation id="7419106976560586862">个人资料路径</translation>
<translation id="7437289804838430631">添加联系信息</translation>
@@ -995,10 +1008,12 @@
<translation id="7442725080345379071">浅橙色</translation>
<translation id="7444046173054089907">此网站已被屏蔽</translation>
<translation id="7445762425076701745">无法完全验证您所连接到的服务器的身份。您在连接服务器时使用的服务器名称仅在您的网络中有效,而外部证书授权中心无法验证该名称的所有权。由于一些证书授权中心仍然会为这些名称颁发证书,因此无法确保您连接到想要访问的网站而不是攻击网站。</translation>
+<translation id="7449109375006139765">将系统日志发送到管理服务器</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />详细了解<ph name="END_LINK" />此问题。</translation>
<translation id="7455133967321480974">使用全局默认设置(阻止)</translation>
<translation id="7460618730930299168">此处显示的放映时间不同于您的选择。继续?</translation>
<translation id="7473891865547856676">不,谢谢</translation>
+<translation id="7475525192983021547">报告用户在设备上处于活跃状态的时间段</translation>
<translation id="7481312909269577407">前进</translation>
<translation id="7485870689360869515">找不到数据。</translation>
<translation id="7508255263130623398">返回的政策设备 ID 为空,或与当前的设备 ID 不一致</translation>
@@ -1091,6 +1106,7 @@
<translation id="7995512525968007366">未指定</translation>
<translation id="800218591365569300">请尝试关闭其他标签页或程序以释放内存。</translation>
<translation id="8009225694047762179">管理密码</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{这张卡及其帐单邮寄地址将被保存。登录 <ph name="USER_EMAIL" /> 后即可使用这张卡。}other{这些卡及其帐单邮寄地址将被保存。登录 <ph name="USER_EMAIL" /> 后即可使用这些卡。}}</translation>
<translation id="8012647001091218357">我们暂时无法与您父母取得联系,请重试。</translation>
<translation id="8025119109950072390">此网站上的攻击者可能会诱骗您做出一些诸如安装软件或泄露个人信息(例如:密码、电话号码或信用卡信息)之类的危险事情。</translation>
<translation id="8034522405403831421">此网页的源语言为<ph name="SOURCE_LANGUAGE" />,要将其翻译成<ph name="TARGET_LANGUAGE" />吗?</translation>
@@ -1101,6 +1117,7 @@
<translation id="8041940743680923270">使用全局默认设置(询问)</translation>
<translation id="8042918947222776840">选择取货方式</translation>
<translation id="8057711352706143257">“<ph name="SOFTWARE_NAME" />”的配置有误。卸载“<ph name="SOFTWARE_NAME" />”通常可解决此问题。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">您的设备已被配置为:</translation>
<translation id="8078141288243656252">无法在旋转后添加注释</translation>
<translation id="8079031581361219619">重新加载此网站?</translation>
<translation id="8088680233425245692">无法查看文章。</translation>
@@ -1151,6 +1168,7 @@
<translation id="8363502534493474904">关闭飞行模式</translation>
<translation id="8364627913115013041">未设置。</translation>
<translation id="8368476060205742148">Google Play 服务</translation>
+<translation id="8371889962595521444">自定义的根证书</translation>
<translation id="8380941800586852976">危险</translation>
<translation id="8381674639488873545">这些费用可能会一次性收取,也可能会周期性收取,而且可能不易察觉。<ph name="BEGIN_LINK" />仍然显示<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">您最近访问过的书签会显示在此处</translation>
@@ -1160,6 +1178,7 @@
<translation id="8416694386774425977">网络配置无效,因此无法导入。
更多详情:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">设备由 <ph name="ENROLLMENT_DOMAIN" /> 管理</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> - <ph name="SECOND_LABEL" /> - <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">更改</translation>
<translation id="8428213095426709021">设置</translation>
@@ -1221,6 +1240,7 @@
<translation id="8932102934695377596">您的时钟慢了</translation>
<translation id="893332455753468063">添加名称</translation>
<translation id="8938939909778640821">接受的信用卡和预付卡</translation>
+<translation id="894185898663964645">您的管理员配置了自定义根证书,这些证书可能会允许管理员查看您所访问的网站的内容。</translation>
<translation id="8943282376843390568">绿黄色</translation>
<translation id="8957210676456822347">强制门户授权</translation>
<translation id="8968766641738584599">保存卡片</translation>
diff --git a/chromium/components/strings/components_strings_zh-TW.xtb b/chromium/components/strings/components_strings_zh-TW.xtb
index f2ba1e50a4a..3d8e4c7acca 100644
--- a/chromium/components/strings/components_strings_zh-TW.xtb
+++ b/chromium/components/strings/components_strings_zh-TW.xtb
@@ -186,6 +186,7 @@
<translation id="2053111141626950936">系統不會翻譯<ph name="LANGUAGE" />網頁。</translation>
<translation id="2053553514270667976">郵遞區號</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 個建議項目}other{# 個建議項目}}</translation>
+<translation id="2068124040035837596">你的帳戶是由 <ph name="ENROLLMENT_DOMAIN" /> 管理,這表示你的系統管理員可以從遠端設定你的帳戶。</translation>
<translation id="2068663545051464999">已上傳的當機報告 ID <ph name="CRASH_ID" /> (本機當機 ID:<ph name="CRASH_LOCAL_ID" />)</translation>
<translation id="2079545284768500474">復原</translation>
<translation id="20817612488360358">雖然系統 Proxy 設定已設為使用,不過也指定了明確 Proxy 設定。</translation>
@@ -244,6 +245,7 @@
<translation id="239429038616798445">不支援所選的運送方式,請改選其他方式。</translation>
<translation id="2396249848217231973">復原刪除(&amp;U)</translation>
<translation id="2413528052993050574">伺服器無法證明其屬於 <ph name="DOMAIN" /> 網域;其安全性憑證已遭撤銷。這可能是因為設定錯誤,或有攻擊者攔截你的連線所致。</translation>
+<translation id="244665789865330679">你的裝置和帳戶是由 <ph name="ENROLLMENT_DOMAIN" /> 管理,這表示你的系統管理員可以從遠端設定你的裝置和帳戶。</translation>
<translation id="2463193859425327265">變更首頁</translation>
<translation id="2463739503403862330">填入</translation>
<translation id="2465655957518002998">選擇快遞方式</translation>
@@ -561,6 +563,7 @@
<translation id="4377125064752653719">你嘗試前往 <ph name="DOMAIN" />,但是發行者已撤銷伺服器提供的憑證。在這種情況下,請勿信任伺服器提供的安全性憑證,因為你的連線對象可能是攻擊者的電腦。</translation>
<translation id="4378154925671717803">電話</translation>
<translation id="4406896451731180161">搜尋結果</translation>
+<translation id="4406972042435603828">你的系統管理員已在瀏覽器中安裝功能強大的擴充功能。</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> 個 Cookie</translation>
<translation id="4415426530740016218">取件地址</translation>
<translation id="4424024547088906515">伺服器無法證明其屬於 <ph name="DOMAIN" /> 網域;其安全性憑證未取得 Chrome 的信任。這可能是因為設定錯誤,或有攻擊者攔截你的連線所致。</translation>
@@ -632,10 +635,12 @@
<translation id="4943872375798546930">沒有結果</translation>
<translation id="4950898438188848926">分頁切換按鈕,按下 Enter 鍵即可切換至開啟的分頁:<ph name="TAB_SWITCH_FOCUSED_FRIENDLY_MATCH_TEXT" /></translation>
<translation id="495170559598752135">動作</translation>
+<translation id="495832697253704892">擴充功能回報</translation>
<translation id="4958444002117714549">展開清單</translation>
<translation id="4974590756084640048">重新啟用警告功能</translation>
<translation id="4989163558385430922">查看全部</translation>
<translation id="4989809363548539747">這是不支援的外掛程式</translation>
+<translation id="4996230189582812866">回報功能</translation>
<translation id="5002932099480077015">啟用後,Chrome 會將您的信用卡複本儲存在這個裝置上,以加快表單填寫速度。</translation>
<translation id="5014174725590676422">目前顯示 Chrome 版 Google 助理首次執行的畫面</translation>
<translation id="5015510746216210676">裝置名稱:</translation>
@@ -656,6 +661,7 @@
<translation id="5089810972385038852">州</translation>
<translation id="5094747076828555589">伺服器無法證明其屬於 <ph name="DOMAIN" /> 網域;其安全性憑證未取得 Chromium 的信任。這可能是因為設定錯誤,或有攻擊者攔截你的連線所致。</translation>
<translation id="5095208057601539847">州/省</translation>
+<translation id="5098222253617183465">你的裝置是由 <ph name="ENROLLMENT_DOMAIN" /> 管理,而你的帳戶是由 <ph name="ACCOUNT_DOMAIN" /> 管理;這表示你的系統管理員可以從遠端設定你的裝置和帳戶。</translation>
<translation id="5115563688576182185">(64 位元)</translation>
<translation id="5128122789703661928">無法將使用這個名稱的工作階段刪除。</translation>
<translation id="5135404736266831032">管理地址...</translation>
@@ -668,6 +674,7 @@
<translation id="5172758083709347301">本機</translation>
<translation id="5179510805599951267">網頁內容不是<ph name="ORIGINAL_LANGUAGE" />嗎?請回報此錯誤</translation>
<translation id="5190835502935405962">書籤列</translation>
+<translation id="5200263511887412697">回報最近登入的裝置使用者名單</translation>
<translation id="5201306358585911203">這個網頁上的嵌入式網頁顯示</translation>
<translation id="5205222826937269299">請輸入名稱</translation>
<translation id="5215116848420601511">儲存在 Google Pay 的付款方式和地址資訊</translation>
@@ -769,6 +776,7 @@
<translation id="5869405914158311789">無法連上這個網站</translation>
<translation id="5869522115854928033">已儲存的密碼</translation>
<translation id="5887400589839399685">已儲存卡片</translation>
+<translation id="5893718151540690985">回報網路介面清單,當中包含網路介面類型和硬體位址資料</translation>
<translation id="5893752035575986141">接受簽帳金融卡。</translation>
<translation id="5901630391730855834">黃色</translation>
<translation id="5908541034548427511"><ph name="TYPE_1" /> (已同步)</translation>
@@ -782,6 +790,7 @@
<translation id="5967592137238574583">編輯聯絡資訊</translation>
<translation id="5967867314010545767">從記錄中移除</translation>
<translation id="5975083100439434680">縮小</translation>
+<translation id="5977489021191000276">你的裝置並非由系統管理員管理。</translation>
<translation id="5977976211062815271">在這部裝置上</translation>
<translation id="598637245381783098">無法開啟付款應用程式</translation>
<translation id="5989320800837274978">沒有指定固定的 Proxy 伺服器和 .pac 指令碼網址。</translation>
@@ -793,6 +802,7 @@
<translation id="6017850046339264347">目前在 <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> 上的攻擊者可能會讓你安裝身分不實的欺騙性應用程式,或是收集可用於追蹤你的資料。<ph name="BEGIN_LEARN_MORE_LINK" />瞭解詳情<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="6025416945513303461"><ph name="TYPE_1" />、<ph name="TYPE_2" />、<ph name="TYPE_3" /> (已同步)</translation>
<translation id="6027201098523975773">輸入名稱</translation>
+<translation id="6033927989869462158">回報 CPU/RAM 使用量等硬體統計資料</translation>
<translation id="6034000775414344507">淺灰色</translation>
<translation id="6039846035001940113">如果問題仍未解決,請與網站擁有者聯絡。</translation>
<translation id="6040143037577758943">關閉</translation>
@@ -905,6 +915,8 @@
<translation id="6897140037006041989">使用者代理程式</translation>
<translation id="6903319715792422884">將部分<ph name="BEGIN_WHITEPAPER_LINK" />系統資訊和網頁內容<ph name="END_WHITEPAPER_LINK" />傳送給 Google,協助我們改善安全瀏覽功能。<ph name="PRIVACY_PAGE_LINK" /></translation>
<translation id="6915804003454593391">使用者:</translation>
+<translation id="6934672428414710184">這是你在 Google 帳戶中設定的名稱</translation>
+<translation id="6939583532829045966">你的裝置是由 <ph name="ENROLLMENT_DOMAIN" /> 管理,這表示你的系統管理員可以從遠端設定你的裝置。</translation>
<translation id="6944692733090228304">你在不是由 <ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> 管理的網站上輸入了你的密碼。為確保帳戶安全,請勿在其他應用程式和網站上重複使用你的密碼。</translation>
<translation id="6945221475159498467">選取</translation>
<translation id="6948701128805548767">如要查看取件方式和相關規定,請選取一個地址</translation>
@@ -992,6 +1004,7 @@
&lt;li&gt;依序按一下 [套用]&lt;strong&gt;&lt;/strong&gt; 和 [確定]&lt;strong&gt;&lt;/strong&gt;
&lt;li&gt;前往 &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome 說明中心&lt;/a&gt;瞭解如何將該軟體從電腦上永久移除
&lt;/ol&gt;</translation>
+<translation id="7413422570546054399">管理 <ph name="PRODUCT_NAME" /></translation>
<translation id="7416351320495623771">管理密碼…</translation>
<translation id="7419106976560586862">設定檔路徑</translation>
<translation id="7437289804838430631">新增聯絡資訊</translation>
@@ -1000,10 +1013,12 @@
<translation id="7442725080345379071">淺橘色</translation>
<translation id="7444046173054089907">這個網站遭到封鎖</translation>
<translation id="7445762425076701745">你所連線的伺服器身分無法完全驗證,該伺服器所使用的名稱僅在你的網路中有效,無法驗證外部憑證授權單位的擁有權。即使某些憑證授權單位會核發這些憑證,不過無法就此確保你所連上的網站是正確的,而不會遭到網路攻擊。</translation>
+<translation id="7449109375006139765">將系統記錄傳送到管理伺服器</translation>
<translation id="7451311239929941790"><ph name="BEGIN_LINK" />進一步瞭解<ph name="END_LINK" />這個問題。</translation>
<translation id="7455133967321480974">使用全域預設值 (封鎖)</translation>
<translation id="7460618730930299168">放映場次細節與你所選取的不同。要繼續嗎?</translation>
<translation id="7473891865547856676">不用了,謝謝</translation>
+<translation id="7475525192983021547">回報使用者的裝置使用時間範圍</translation>
<translation id="7481312909269577407">往前</translation>
<translation id="7485870689360869515">找不到任何資料。</translation>
<translation id="7508255263130623398">傳回的政策裝置 ID 沒有任何內容,或是與目前的裝置 ID 不符</translation>
@@ -1096,6 +1111,7 @@
<translation id="7995512525968007366">未指定</translation>
<translation id="800218591365569300">嘗試關閉其他分頁或程式,以釋出記憶體。</translation>
<translation id="8009225694047762179">管理密碼</translation>
+<translation id="8012116502927253373">{NUM_CARDS,plural, =1{系統會儲存這張卡片和相應的帳單地址。只要登入 <ph name="USER_EMAIL" /> 即可使用。}other{系統會儲存這些卡片和相應的帳單地址。只要登入 <ph name="USER_EMAIL" /> 即可使用。}}</translation>
<translation id="8012647001091218357">我們暫時無法與您的家長聯絡,請再試一次。</translation>
<translation id="8025119109950072390">攻擊者可能會試圖透過這個網站誘使你做一些危險的行為,例如安裝軟體或提供個人資訊 (包括密碼、電話號碼或信用卡資料)。</translation>
<translation id="8034522405403831421">這是<ph name="SOURCE_LANGUAGE" />網頁,需要翻譯成<ph name="TARGET_LANGUAGE" />嗎?</translation>
@@ -1106,6 +1122,7 @@
<translation id="8041940743680923270">使用全域預設值 (要求確認)</translation>
<translation id="8042918947222776840">選擇取件方式</translation>
<translation id="8057711352706143257">「<ph name="SOFTWARE_NAME" />」的設定不正確。通常解除安裝「<ph name="SOFTWARE_NAME" />」即可修正這個問題。<ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="8068418091938640101">你的裝置已設定為:</translation>
<translation id="8078141288243656252">文件旋轉後無法加註</translation>
<translation id="8079031581361219619">要重新載入網站嗎?</translation>
<translation id="8088680233425245692">無法查看文章。</translation>
@@ -1156,6 +1173,7 @@
<translation id="8363502534493474904">關閉飛航模式</translation>
<translation id="8364627913115013041">未設定。</translation>
<translation id="8368476060205742148">Google Play 服務</translation>
+<translation id="8371889962595521444">自訂根憑證</translation>
<translation id="8380941800586852976">不安全</translation>
<translation id="8381674639488873545">這些費用可能是一次性或週期性的費用,而且可能難以察覺。<ph name="BEGIN_LINK" />仍要顯示<ph name="END_LINK" /></translation>
<translation id="8382348898565613901">這裡會顯示你最近造訪過的書籤</translation>
@@ -1165,6 +1183,7 @@
<translation id="8416694386774425977">網路設定無效,無法匯入。
其他詳細資料:
<ph name="DEBUG_INFO" /></translation>
+<translation id="8422642323886341533">由 <ph name="ENROLLMENT_DOMAIN" /> 管理的裝置</translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8425213833346101688">變更</translation>
<translation id="8428213095426709021">設定</translation>
@@ -1225,6 +1244,7 @@
<translation id="8932102934695377596">你的時鐘時間過慢</translation>
<translation id="893332455753468063">新增名稱</translation>
<translation id="8938939909778640821">接受的信用卡和預付卡</translation>
+<translation id="894185898663964645">你的系統管理員已設定自訂根憑證,這項設定將能允許系統管理員查看你所造訪網站的內容。</translation>
<translation id="8943282376843390568">萊姆綠</translation>
<translation id="8957210676456822347">監控式入口網站授權</translation>
<translation id="8968766641738584599">儲存卡片</translation>
diff --git a/chromium/components/translate/content/common/BUILD.gn b/chromium/components/translate/content/common/BUILD.gn
index a5b6a6787e8..ae521372300 100644
--- a/chromium/components/translate/content/common/BUILD.gn
+++ b/chromium/components/translate/content/common/BUILD.gn
@@ -11,6 +11,7 @@ mojom("common") {
public_deps = [
"//mojo/public/mojom/base",
+ "//services/network/public/mojom:mojom",
"//url/mojom:url_mojom_gurl",
]
}
diff --git a/chromium/components/translate/content/common/translate.mojom b/chromium/components/translate/content/common/translate.mojom
index 7d09c8fd949..0893def177e 100644
--- a/chromium/components/translate/content/common/translate.mojom
+++ b/chromium/components/translate/content/common/translate.mojom
@@ -6,6 +6,7 @@ module translate.mojom;
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/string16.mojom";
+import "services/network/public/mojom/url_loader_factory.mojom";
import "url/mojom/url.mojom";
enum TranslateError {
@@ -39,6 +40,12 @@ interface Page {
// Requests that the page be translated from |source_lang| to
// |target_lang|.
//
+ // |loader_factory_for_translate_script| should provide a factory that the
+ // translation scripts can use for making fetch requests associated with the
+ // "translate" origin (the default factory's |request_initiator_site_lock| is
+ // not compatible with |request_initiator| of fetch requests initiated by the
+ // "translate" origin).
+ //
// If a Translate request is already in progress with a matching
// |target_lang|, this request will respond with |cancelled| set
// to |true|.
@@ -49,7 +56,10 @@ interface Page {
//
// If |cancelled| is |true| all other response values should be
// ignored.
- Translate(string translate_script, string source_lang, string target_lang)
+ Translate(string translate_script,
+ network.mojom.URLLoaderFactory loader_factory_for_translate_script,
+ string source_lang,
+ string target_lang)
=> (bool cancelled, string original_lang, string translated_lang,
TranslateError error);
diff --git a/chromium/components/translate/content/renderer/BUILD.gn b/chromium/components/translate/content/renderer/BUILD.gn
index 8915865bc8f..72a887301bd 100644
--- a/chromium/components/translate/content/renderer/BUILD.gn
+++ b/chromium/components/translate/content/renderer/BUILD.gn
@@ -15,13 +15,17 @@ static_library("renderer") {
"//components/translate/content/common",
"//components/translate/core/common",
"//components/translate/core/language_detection",
- "//content/public/common",
- "//content/public/renderer",
"//services/service_manager/public/cpp",
"//third_party/blink/public:blink",
"//url",
"//v8",
]
+
+ public_deps = [
+ "//content/public/common",
+ "//content/public/renderer",
+ "//third_party/blink/public:blink_headers",
+ ]
}
source_set("unit_tests") {
diff --git a/chromium/components/ukm/ukm_recorder_impl.cc b/chromium/components/ukm/ukm_recorder_impl.cc
index 08b22965309..fe2b7319a9e 100644
--- a/chromium/components/ukm/ukm_recorder_impl.cc
+++ b/chromium/components/ukm/ukm_recorder_impl.cc
@@ -668,7 +668,7 @@ bool UkmRecorderImpl::IsSampledIn(int sampling_rate) {
// A sampling rate of 0 is "never"; everything else is 1-in-N but skip
// the RandInt() call if N==1.
return sampling_rate > 0 &&
- (sampling_rate == 1 || base::RandInt(1, sampling_rate) != 1);
+ (sampling_rate == 1 || base::RandInt(1, sampling_rate) == 1);
}
void UkmRecorderImpl::StoreWhitelistedEntries() {
diff --git a/chromium/components/ukm/ukm_recorder_impl.h b/chromium/components/ukm/ukm_recorder_impl.h
index 8a62b52e0ac..1732626d02a 100644
--- a/chromium/components/ukm/ukm_recorder_impl.h
+++ b/chromium/components/ukm/ukm_recorder_impl.h
@@ -105,6 +105,7 @@ class UkmRecorderImpl : public UkmRecorder {
friend ::ukm::debug::UkmDebugDataExtractor;
friend ::ukm::UkmRecorderImplTest;
friend ::ukm::UkmUtilsForTest;
+ FRIEND_TEST_ALL_PREFIXES(UkmRecorderImplTest, PageSamplingCondition);
struct MetricAggregate {
uint64_t total_count = 0;
diff --git a/chromium/components/ukm/ukm_recorder_impl_unittest.cc b/chromium/components/ukm/ukm_recorder_impl_unittest.cc
index 51b185d8af3..1314fe150a0 100644
--- a/chromium/components/ukm/ukm_recorder_impl_unittest.cc
+++ b/chromium/components/ukm/ukm_recorder_impl_unittest.cc
@@ -75,6 +75,26 @@ class UkmRecorderImplTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(UkmRecorderImplTest);
};
+TEST_F(UkmRecorderImplTest, PageSamplingCondition) {
+ EXPECT_FALSE(impl().UkmRecorderImpl::IsSampledIn(0));
+ EXPECT_TRUE(impl().UkmRecorderImpl::IsSampledIn(1));
+
+ // Actual sampling is "random" so there's no single operation to test.
+ // Instead, sample many times and expect that some, but less than 1/2,
+ // will be sampled-in. This is sufficient to ensure that the condition
+ // is not "dead" (always false) and has not been mistakenly reversed...
+ // without the test being flaky.
+ const int kRandomCheckCount = 1000;
+ int sampled_in_count = 0;
+ for (int i = 0; i < kRandomCheckCount; ++i) {
+ // Sample 1-in-10...
+ if (impl().UkmRecorderImpl::IsSampledIn(10))
+ sampled_in_count += 1;
+ }
+ EXPECT_LT(0, sampled_in_count);
+ EXPECT_GT(kRandomCheckCount / 2, sampled_in_count);
+}
+
TEST_F(UkmRecorderImplTest, PageSampling) {
SourceId page1_source =
ConvertToSourceId(101, base::UkmSourceId::Type::NAVIGATION_ID);
diff --git a/chromium/components/user_manager/known_user.cc b/chromium/components/user_manager/known_user.cc
index d3d54d262e1..44a5bdd9a33 100644
--- a/chromium/components/user_manager/known_user.cc
+++ b/chromium/components/user_manager/known_user.cc
@@ -490,19 +490,11 @@ bool IsUsingSAML(const AccountId& account_id) {
bool WasProfileEverInitialized(const AccountId& account_id) {
bool profile_ever_initialized;
- const bool pref_set = GetBooleanPref(account_id, kProfileEverInitialized,
- &profile_ever_initialized);
- // TODO(atwilson): Remove migration code below once this UMA stat reports
- // that migration is completed - crbug.com/736760.
- UMA_HISTOGRAM_BOOLEAN("UserManager.ProfileEverInitializedMigrationCompleted",
- pref_set);
- if (pref_set)
+ if (GetBooleanPref(account_id, kProfileEverInitialized,
+ &profile_ever_initialized)) {
return profile_ever_initialized;
-
- // Sessions created before we started setting the session_initialized flag
- // should default to "initialized = true".
- LOG(WARNING) << "Treating unmigrated user as profile_ever_initialized=true";
- return true;
+ }
+ return false;
}
void SetProfileEverInitialized(const AccountId& account_id, bool initialized) {
@@ -595,23 +587,6 @@ void CleanEphemeralUsers() {
}
}
-// Exported so tests can call this from other components.
-void RemoveSetProfileEverInitializedPrefForTesting(
- const AccountId& account_id) {
- const base::DictionaryValue* prefs = nullptr;
- if (!FindPrefs(account_id, &prefs))
- return;
-
- if (!prefs->HasKey(kProfileEverInitialized))
- return;
-
- std::unique_ptr<base::DictionaryValue> new_prefs(prefs->CreateDeepCopy());
- if (!new_prefs->RemoveKey(kProfileEverInitialized))
- return;
-
- UpdatePrefs(account_id, *new_prefs, true);
-}
-
void RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterListPref(kKnownUsers);
}
diff --git a/chromium/components/user_manager/known_user.h b/chromium/components/user_manager/known_user.h
index 0e8a53f9f93..52a92fb53a5 100644
--- a/chromium/components/user_manager/known_user.h
+++ b/chromium/components/user_manager/known_user.h
@@ -193,10 +193,6 @@ void RemovePrefs(const AccountId& account_id);
// Removes all ephemeral users.
void CleanEphemeralUsers();
-// Clears kProfileEverInitialized for a user.
-void USER_MANAGER_EXPORT
-RemoveSetProfileEverInitializedPrefForTesting(const AccountId& account_id);
-
// Register known user prefs.
void USER_MANAGER_EXPORT RegisterPrefs(PrefRegistrySimple* registry);
}
diff --git a/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc b/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
index 443499351fa..ae7a1c55b94 100644
--- a/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
+++ b/chromium/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
@@ -122,9 +122,8 @@ TEST(HitTestDataProviderDrawQuad, HitTestDataRenderer) {
hit_test_region_list->regions[0].transform);
}
-// Test to ensure that we skip regions with non-invertible transforms and with
-// updated FrameSinkId between fallback and primary when preparing for hit-test
-// data.
+// Test to ensure that we skip regions with non-invertible transforms when
+// preparing for hit-test data.
TEST(HitTestDataProviderDrawQuad, HitTestDataSkipQuads) {
std::unique_ptr<HitTestDataProvider> hit_test_data_provider =
std::make_unique<HitTestDataProviderDrawQuad>(
@@ -167,53 +166,45 @@ TEST(HitTestDataProviderDrawQuad, HitTestDataSkipQuads) {
invertible_transform);
pass_list.push_back(std::move(pass3));
- // The draw quad's FrameSinkId changed between fallback and primary.
- SurfaceId child_surface_id4 = CreateChildSurfaceId(5);
- SurfaceId fallback_child_surface_id4 = CreateChildSurfaceId(6);
- auto pass4 = CreateRenderPassWithChildSurface(
- 4, child_surface_id4, kFrameRect, child_rect, invertible_transform,
- invertible_transform, fallback_child_surface_id4);
- pass_list.push_back(std::move(pass4));
-
- auto pass5_root = RenderPass::Create();
- pass5_root->output_rect = kFrameRect;
- pass5_root->id = 5;
- auto* shared_quad_state5_root = pass5_root->CreateAndAppendSharedQuadState();
- gfx::Rect rect5_root(kFrameRect);
- shared_quad_state5_root->SetAll(
- gfx::Transform(), /*quad_layer_rect=*/rect5_root,
- /*visible_quad_layer_rect=*/rect5_root, /*clip_rect=*/rect5_root,
+ auto pass4_root = RenderPass::Create();
+ pass4_root->output_rect = kFrameRect;
+ pass4_root->id = 5;
+ auto* shared_quad_state4_root = pass4_root->CreateAndAppendSharedQuadState();
+ gfx::Rect rect4_root(kFrameRect);
+ shared_quad_state4_root->SetAll(
+ gfx::Transform(), /*quad_layer_rect=*/rect4_root,
+ /*visible_quad_layer_rect=*/rect4_root, /*clip_rect=*/rect4_root,
/*is_clipped=*/false, /*are_contents_opaque=*/false,
/*opacity=*/0.5f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
- auto* quad5_root_1 =
- pass5_root->quad_list.AllocateAndConstruct<RenderPassDrawQuad>();
- quad5_root_1->SetNew(shared_quad_state5_root, /*rect=*/rect5_root,
- /*visible_rect=*/rect5_root, /*render_pass_id=*/1,
+ auto* quad4_root_1 =
+ pass4_root->quad_list.AllocateAndConstruct<RenderPassDrawQuad>();
+ quad4_root_1->SetNew(shared_quad_state4_root, /*rect=*/rect4_root,
+ /*visible_rect=*/rect4_root, /*render_pass_id=*/1,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(),
gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false,
1.0f);
- auto* quad5_root_2 =
- pass5_root->quad_list.AllocateAndConstruct<RenderPassDrawQuad>();
- quad5_root_2->SetNew(shared_quad_state5_root, /*rect=*/rect5_root,
- /*visible_rect=*/rect5_root, /*render_pass_id=*/2,
+ auto* quad4_root_2 =
+ pass4_root->quad_list.AllocateAndConstruct<RenderPassDrawQuad>();
+ quad4_root_2->SetNew(shared_quad_state4_root, /*rect=*/rect4_root,
+ /*visible_rect=*/rect4_root, /*render_pass_id=*/2,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(),
gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false,
1.0f);
- auto* quad5_root_3 =
- pass5_root->quad_list.AllocateAndConstruct<RenderPassDrawQuad>();
- quad5_root_3->SetNew(shared_quad_state5_root, /*rect=*/rect5_root,
- /*visible_rect=*/rect5_root, /*render_pass_id=*/3,
+ auto* quad4_root_3 =
+ pass4_root->quad_list.AllocateAndConstruct<RenderPassDrawQuad>();
+ quad4_root_3->SetNew(shared_quad_state4_root, /*rect=*/rect4_root,
+ /*visible_rect=*/rect4_root, /*render_pass_id=*/3,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(),
gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false,
1.0f);
- auto* quad5_root_4 =
- pass5_root->quad_list.AllocateAndConstruct<RenderPassDrawQuad>();
- quad5_root_4->SetNew(shared_quad_state5_root, /*rect=*/rect5_root,
- /*visible_rect=*/rect5_root, /*render_pass_id=*/4,
+ auto* quad4_root_4 =
+ pass4_root->quad_list.AllocateAndConstruct<RenderPassDrawQuad>();
+ quad4_root_4->SetNew(shared_quad_state4_root, /*rect=*/rect4_root,
+ /*visible_rect=*/rect4_root, /*render_pass_id=*/4,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(),
gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false,
1.0f);
- pass_list.push_back(std::move(pass5_root));
+ pass_list.push_back(std::move(pass4_root));
auto compositor_frame =
CompositorFrameBuilder().SetRenderPassList(std::move(pass_list)).Build();
@@ -313,4 +304,109 @@ TEST(HitTestDataProviderDrawQuad, HitTestDataTransparent) {
hit_test_region_list->regions[0].transform);
}
+// Test to ensure that we account for shape-rects in hit-test data when it's
+// present in the filters of the RenderPass.
+TEST(HitTestDataProviderDrawQuad, HitTestDataShapeFilters) {
+ std::unique_ptr<HitTestDataProvider> hit_test_data_provider =
+ std::make_unique<HitTestDataProviderDrawQuad>(
+ true /* should_ask_for_child_region */,
+ true /* root_accepts_events */);
+
+ constexpr gfx::Rect kFrameRect(0, 0, 1024, 768);
+ gfx::Rect child_rect(200, 100);
+ gfx::Transform invertible_transform;
+ invertible_transform.Translate(200, 100);
+
+ RenderPassList pass_list;
+
+ // A render pass that has shape filters.
+ SurfaceId child_surface_id1 = CreateChildSurfaceId(2);
+ SurfaceId child_surface_id2 = CreateChildSurfaceId(3);
+
+ auto pass1 = RenderPass::Create();
+ pass1->SetNew(1, kFrameRect, kFrameRect, invertible_transform);
+ // Create a filter with three shapes, the first two are included in
+ // surface_quad_1 and the other one intersects sueface_quad_2. These rects are
+ // in DIP space.
+ cc::FilterOperations filters;
+ filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
+ {gfx::Rect(101, 51, 25, 25), gfx::Rect(151, 51, 25, 25),
+ gfx::Rect(325, 200, 200, 200)},
+ 0.f, 0.f));
+ pass1->filters = filters;
+ auto* shared_state_1 = pass1->CreateAndAppendSharedQuadState();
+ shared_state_1->SetAll(invertible_transform, kFrameRect, kFrameRect,
+ kFrameRect, false, false, 1, SkBlendMode::kSrcOver, 0);
+
+ auto* surface_quad_1 = pass1->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad_1->SetNew(
+ pass1->shared_quad_state_list.back(), child_rect, child_rect,
+ SurfaceRange(child_surface_id1), SK_ColorWHITE,
+ /*stretch_content_to_fill_bounds=*/false, /*ignores_input_event=*/false);
+
+ gfx::Rect child_rect2(400, 400, 100, 100);
+ auto* surface_quad_2 = pass1->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad_2->SetNew(
+ pass1->shared_quad_state_list.back(), child_rect2, child_rect2,
+ SurfaceRange(child_surface_id2), SK_ColorWHITE,
+ /*stretch_content_to_fill_bounds=*/false, /*ignores_input_event=*/false);
+
+ pass_list.push_back(std::move(pass1));
+
+ auto compositor_frame = CompositorFrameBuilder()
+ .SetRenderPassList(std::move(pass_list))
+ .SetDeviceScaleFactor(2.f)
+ .Build();
+ base::Optional<HitTestRegionList> hit_test_region_list =
+ hit_test_data_provider->GetHitTestData(compositor_frame);
+
+ // Expect three hit-test regions, two from the first draw-quad and the other
+ // from the second draw-quad.
+ EXPECT_EQ(3u, hit_test_region_list->regions.size());
+ EXPECT_EQ(child_surface_id1.frame_sink_id(),
+ hit_test_region_list->regions[0].frame_sink_id);
+ EXPECT_EQ(gfx::Rect(2, 2, 50, 50), hit_test_region_list->regions[0].rect);
+ EXPECT_EQ(child_surface_id1.frame_sink_id(),
+ hit_test_region_list->regions[1].frame_sink_id);
+ EXPECT_EQ(gfx::Rect(102, 2, 50, 50), hit_test_region_list->regions[1].rect);
+ EXPECT_EQ(child_surface_id2.frame_sink_id(),
+ hit_test_region_list->regions[2].frame_sink_id);
+ EXPECT_EQ(gfx::Rect(450, 400, 50, 100),
+ hit_test_region_list->regions[2].rect);
+
+ // Build another CompositorFrame with device-scale-factor=0.5f.
+ auto pass2 = RenderPass::Create();
+ pass2->SetNew(2, kFrameRect, kFrameRect, invertible_transform);
+ // Create a filter with a shapes included in surface_quad_3, in DIP space.
+ cc::FilterOperations filters2;
+ filters2.Append(cc::FilterOperation::CreateAlphaThresholdFilter(
+ {gfx::Rect(600, 200, 300, 300)}, 0.f, 0.f));
+ pass2->filters = filters2;
+ auto* shared_state_2 = pass2->CreateAndAppendSharedQuadState();
+ shared_state_2->SetAll(invertible_transform, kFrameRect, kFrameRect,
+ kFrameRect, false, false, 1, SkBlendMode::kSrcOver, 0);
+
+ auto* surface_quad_3 = pass2->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ surface_quad_3->SetNew(
+ pass2->shared_quad_state_list.back(), child_rect, child_rect,
+ SurfaceRange(child_surface_id1), SK_ColorWHITE,
+ /*stretch_content_to_fill_bounds=*/false, /*ignores_input_event=*/false);
+
+ pass_list.push_back(std::move(pass2));
+
+ auto compositor_frame_2 = CompositorFrameBuilder()
+ .SetRenderPassList(std::move(pass_list))
+ .SetDeviceScaleFactor(.5f)
+ .Build();
+ base::Optional<HitTestRegionList> hit_test_region_list_2 =
+ hit_test_data_provider->GetHitTestData(compositor_frame_2);
+
+ // Expect one region included in surface_quad_3.
+ EXPECT_EQ(1u, hit_test_region_list_2->regions.size());
+ EXPECT_EQ(child_surface_id1.frame_sink_id(),
+ hit_test_region_list_2->regions[0].frame_sink_id);
+ EXPECT_EQ(gfx::Rect(100, 0, 100, 100),
+ hit_test_region_list_2->regions[0].rect);
+}
+
} // namespace viz
diff --git a/chromium/components/viz/common/features.cc b/chromium/components/viz/common/features.cc
index f0c077da19a..1f35ba2f3c9 100644
--- a/chromium/components/viz/common/features.cc
+++ b/chromium/components/viz/common/features.cc
@@ -28,7 +28,7 @@ const base::Feature kEnableSurfaceSynchronization{
// (OOP-D).
// TODO(dnicoara): Look at enabling Chromecast support when ChromeOS support is
// ready.
-#if defined(OS_CHROMEOS) || defined(IS_CHROMECAST)
+#if defined(OS_CHROMEOS) || defined(IS_CHROMECAST) || defined(OS_ANDROID)
const base::Feature kVizDisplayCompositor{"VizDisplayCompositor",
base::FEATURE_DISABLED_BY_DEFAULT};
#else
diff --git a/chromium/components/viz/common/hit_test/hit_test_data_builder.cc b/chromium/components/viz/common/hit_test/hit_test_data_builder.cc
index 4751d12efc5..1d7ae75a599 100644
--- a/chromium/components/viz/common/hit_test/hit_test_data_builder.cc
+++ b/chromium/components/viz/common/hit_test/hit_test_data_builder.cc
@@ -5,30 +5,13 @@
#include "components/viz/common/hit_test/hit_test_data_builder.h"
#include "components/viz/common/quads/surface_draw_quad.h"
+#include "ui/gfx/geometry/rect_conversions.h"
namespace viz {
+namespace {
-// static
-base::Optional<HitTestRegionList> HitTestDataBuilder::CreateHitTestData(
- const CompositorFrame& compositor_frame,
- bool root_accepts_events,
- bool should_ask_for_child_region) {
- base::Optional<HitTestRegionList> hit_test_region_list(base::in_place);
- hit_test_region_list->flags =
- (root_accepts_events ? HitTestRegionFlags::kHitTestMine
- : HitTestRegionFlags::kHitTestIgnore) |
- HitTestRegionFlags::kHitTestMouse | HitTestRegionFlags::kHitTestTouch;
- hit_test_region_list->bounds.set_size(compositor_frame.size_in_pixels());
- AddHitTestDataFromRenderPass(
- compositor_frame, compositor_frame.render_pass_list.back()->id,
- &hit_test_region_list->regions, should_ask_for_child_region);
- return hit_test_region_list;
-}
-
-// static
-const RenderPass* HitTestDataBuilder::GetRenderPassInFrame(
- const CompositorFrame& frame,
- RenderPassId render_pass_id) {
+const RenderPass* GetRenderPassInFrame(const CompositorFrame& frame,
+ RenderPassId render_pass_id) {
if (!render_pass_id)
return frame.render_pass_list.back().get();
@@ -40,12 +23,65 @@ const RenderPass* HitTestDataBuilder::GetRenderPassInFrame(
return nullptr;
}
-// static
-void HitTestDataBuilder::AddHitTestDataFromRenderPass(
- const CompositorFrame& frame,
- RenderPassId render_pass_id,
- std::vector<HitTestRegion>* regions,
- bool should_ask_for_child_region) {
+void AddHitTestRegion(const FrameSinkId& frame_sink_id,
+ const gfx::Rect& visible_rect,
+ const gfx::Transform& hit_test_region_transform,
+ std::vector<HitTestRegion>* regions,
+ bool should_ask_for_child_region) {
+ regions->emplace_back();
+ HitTestRegion* hit_test_region = &regions->back();
+ hit_test_region->frame_sink_id = frame_sink_id;
+ hit_test_region->flags = HitTestRegionFlags::kHitTestMouse |
+ HitTestRegionFlags::kHitTestTouch |
+ HitTestRegionFlags::kHitTestChildSurface;
+ if (should_ask_for_child_region) {
+ hit_test_region->flags |= HitTestRegionFlags::kHitTestAsk;
+ hit_test_region->async_hit_test_reasons =
+ AsyncHitTestReasons::kUseDrawQuadData;
+ }
+ hit_test_region->rect = visible_rect;
+ hit_test_region->transform = hit_test_region_transform;
+}
+
+std::vector<gfx::Rect> ExtractAlphaRects(
+ const cc::FilterOperations& filters,
+ const gfx::Rect& surface_quad_rect,
+ const gfx::Transform& quad_to_target_transform,
+ const gfx::Transform& target_to_quad_transform,
+ float device_scale_factor) {
+ std::vector<gfx::Rect> filter_regions;
+ if (filters.IsEmpty())
+ return filter_regions;
+
+ size_t i = 0;
+ for (i = 0; i < filters.size(); ++i) {
+ const cc::FilterOperation& op = filters.at(i);
+ if (op.type() == cc::FilterOperation::ALPHA_THRESHOLD) {
+ if (op.shape().empty())
+ return filter_regions;
+
+ for (const gfx::Rect& rect : op.shape()) {
+ gfx::RectF rect_in_pixels(
+ gfx::ScaleRect(gfx::RectF(rect), device_scale_factor));
+ gfx::RectF surface_quad_rect_in_pass(surface_quad_rect);
+ quad_to_target_transform.TransformRect(&surface_quad_rect_in_pass);
+ if (surface_quad_rect_in_pass.Intersects(rect_in_pixels)) {
+ gfx::RectF visible_rect(surface_quad_rect_in_pass);
+ visible_rect.Intersect(rect_in_pixels);
+ target_to_quad_transform.TransformRect(&visible_rect);
+ filter_regions.push_back(gfx::ToNearestRect(visible_rect));
+ }
+ }
+ return filter_regions;
+ }
+ }
+ return filter_regions;
+}
+
+void AddHitTestDataFromRenderPass(const CompositorFrame& frame,
+ RenderPassId render_pass_id,
+ std::vector<HitTestRegion>* regions,
+ bool should_ask_for_child_region) {
const RenderPass* render_pass = GetRenderPassInFrame(frame, render_pass_id);
if (!render_pass)
return;
@@ -68,15 +104,6 @@ void HitTestDataBuilder::AddHitTestDataFromRenderPass(
if (surface_quad->ignores_input_event)
continue;
- // Skip the quad if the FrameSinkId between fallback and primary is not
- // the same, because we don't know which FrameSinkId would be used to
- // draw this quad.
- if (surface_quad->surface_range.start() &&
- surface_quad->surface_range.start()->frame_sink_id() !=
- surface_quad->surface_range.end().frame_sink_id()) {
- continue;
- }
-
// Skip the quad if the transform is not invertible (i.e. it will not
// be able to receive events).
gfx::Transform quad_to_target_transform =
@@ -86,22 +113,27 @@ void HitTestDataBuilder::AddHitTestDataFromRenderPass(
if (!quad_to_target_transform.GetInverse(&target_to_quad_transform)) {
continue;
}
+ gfx::Transform hit_test_region_transform =
+ target_to_quad_transform * transform_from_root_target;
- regions->emplace_back();
- HitTestRegion* hit_test_region = &regions->back();
- hit_test_region->frame_sink_id =
- surface_quad->surface_range.end().frame_sink_id();
- hit_test_region->flags = HitTestRegionFlags::kHitTestMouse |
- HitTestRegionFlags::kHitTestTouch |
- HitTestRegionFlags::kHitTestChildSurface;
- if (should_ask_for_child_region) {
- hit_test_region->flags |= HitTestRegionFlags::kHitTestAsk;
- hit_test_region->async_hit_test_reasons =
- AsyncHitTestReasons::kUseDrawQuadData;
+ // If |surface_range|.begin() and end() have different frame sinks, use
+ // end(). If there is no surface submitted for this FrameSinkId at
+ // aggregation time, an async hit test query will be sent to the client.
+ const auto& filters = render_pass->filters;
+ std::vector<gfx::Rect> filter_regions = ExtractAlphaRects(
+ filters, surface_quad->rect, quad_to_target_transform,
+ target_to_quad_transform, frame.device_scale_factor());
+ if (filter_regions.empty()) {
+ AddHitTestRegion(surface_quad->surface_range.end().frame_sink_id(),
+ surface_quad->rect, hit_test_region_transform, regions,
+ should_ask_for_child_region);
+ } else {
+ for (const auto& filter_region : filter_regions) {
+ AddHitTestRegion(surface_quad->surface_range.end().frame_sink_id(),
+ filter_region, hit_test_region_transform, regions,
+ should_ask_for_child_region);
+ }
}
- hit_test_region->rect = surface_quad->rect;
- hit_test_region->transform =
- target_to_quad_transform * transform_from_root_target;
} else if (quad->material == DrawQuad::RENDER_PASS) {
const RenderPassDrawQuad* render_quad =
RenderPassDrawQuad::MaterialCast(quad);
@@ -111,4 +143,23 @@ void HitTestDataBuilder::AddHitTestDataFromRenderPass(
}
}
+} // namespace
+
+// static
+base::Optional<HitTestRegionList> HitTestDataBuilder::CreateHitTestData(
+ const CompositorFrame& compositor_frame,
+ bool root_accepts_events,
+ bool should_ask_for_child_region) {
+ base::Optional<HitTestRegionList> hit_test_region_list(base::in_place);
+ hit_test_region_list->flags =
+ (root_accepts_events ? HitTestRegionFlags::kHitTestMine
+ : HitTestRegionFlags::kHitTestIgnore) |
+ HitTestRegionFlags::kHitTestMouse | HitTestRegionFlags::kHitTestTouch;
+ hit_test_region_list->bounds.set_size(compositor_frame.size_in_pixels());
+ AddHitTestDataFromRenderPass(
+ compositor_frame, compositor_frame.render_pass_list.back()->id,
+ &hit_test_region_list->regions, should_ask_for_child_region);
+ return hit_test_region_list;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/common/hit_test/hit_test_data_builder.h b/chromium/components/viz/common/hit_test/hit_test_data_builder.h
index 526101ed5ad..5eea8d9d536 100644
--- a/chromium/components/viz/common/hit_test/hit_test_data_builder.h
+++ b/chromium/components/viz/common/hit_test/hit_test_data_builder.h
@@ -23,14 +23,6 @@ class VIZ_COMMON_EXPORT HitTestDataBuilder {
bool should_ask_for_child_region);
private:
- static const RenderPass* GetRenderPassInFrame(const CompositorFrame& frame,
- RenderPassId render_pass_id);
-
- static void AddHitTestDataFromRenderPass(const CompositorFrame& frame,
- RenderPassId render_pass_id,
- std::vector<HitTestRegion>* regions,
- bool should_ask_for_child_region);
-
DISALLOW_COPY_AND_ASSIGN(HitTestDataBuilder);
};
diff --git a/chromium/components/viz/host/hit_test/hit_test_query.cc b/chromium/components/viz/host/hit_test/hit_test_query.cc
index 9d40b3f77e3..7e74fc7b994 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query.cc
+++ b/chromium/components/viz/host/hit_test/hit_test_query.cc
@@ -227,10 +227,6 @@ bool HitTestQuery::FindTargetInRegionForLocation(
size_t child_region = region_index + 1;
size_t child_region_end = child_region + region_child_count;
gfx::PointF location_in_target = location_transformed;
- if (!features::IsVizHitTestingSurfaceLayerEnabled() &&
- is_location_relative_to_parent) {
- location_in_target -= hit_test_data_[region_index].rect.OffsetFromOrigin();
- }
const uint32_t flags = hit_test_data_[region_index].flags;
@@ -291,10 +287,6 @@ bool HitTestQuery::TransformLocationForTargetRecursively(
}
hit_test_data_[region_index].transform().TransformPoint(location_in_target);
- if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
- location_in_target->Offset(-hit_test_data_[region_index].rect.x(),
- -hit_test_data_[region_index].rect.y());
- }
if (!target_ancestor)
return true;
@@ -333,10 +325,6 @@ bool HitTestQuery::GetTransformToTargetRecursively(
// found immediately.
if (hit_test_data_[region_index].frame_sink_id == target) {
*transform = hit_test_data_[region_index].transform();
- if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
- transform->Translate(-hit_test_data_[region_index].rect.x(),
- -hit_test_data_[region_index].rect.y());
- }
return true;
}
@@ -353,10 +341,6 @@ bool HitTestQuery::GetTransformToTargetRecursively(
if (GetTransformToTargetRecursively(target, child_region,
&transform_to_child)) {
gfx::Transform region_transform(hit_test_data_[region_index].transform());
- if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
- region_transform.Translate(-hit_test_data_[region_index].rect.x(),
- -hit_test_data_[region_index].rect.y());
- }
*transform = transform_to_child * region_transform;
return true;
}
diff --git a/chromium/components/viz/host/hit_test/hit_test_query.h b/chromium/components/viz/host/hit_test/hit_test_query.h
index df8e5da3ea3..8261e31a91d 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query.h
+++ b/chromium/components/viz/host/hit_test/hit_test_query.h
@@ -57,7 +57,9 @@ class VIZ_HOST_EXPORT HitTestQuery {
// 1. The list is in ascending (front to back) z-order.
// 2. Children count includes children of children.
// 3. After applying transform to the incoming point, point is in the same
- // coordinate system as the bounds it is comparing against.
+ // coordinate system as the bounds it is comparing against. We shouldn't
+ // need to apply rect's origin offset as it should be included in this
+ // transform.
// For example,
// +e-------------+
// | +c---------|
diff --git a/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc b/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
index 1b62a210c79..29c876f2a0a 100644
--- a/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
+++ b/chromium/components/viz/host/hit_test/hit_test_query_unittest.cc
@@ -361,12 +361,13 @@ TEST_F(HitTestQueryTest, ClippedChildWithChildUnderneathTransform) {
gfx::Rect e_bounds_in_e = gfx::Rect(0, 0, 600, 600);
gfx::Rect c_bounds_in_e = gfx::Rect(0, 0, 800, 800);
gfx::Rect a_bounds_in_c = gfx::Rect(0, 0, 200, 100);
- gfx::Rect b_bounds_in_c = gfx::Rect(0, 100, 800, 600);
+ gfx::Rect b_bounds_in_c = gfx::Rect(0, 0, 800, 600);
gfx::Rect d_bounds_in_e = gfx::Rect(0, 0, 800, 800);
gfx::Transform transform_e_to_e, transform_e_to_c, transform_c_to_a,
transform_c_to_b, transform_e_to_d;
transform_e_to_c.Translate(-200, -100);
transform_e_to_d.Translate(-400, -50);
+ transform_c_to_b.Translate(0, -100);
active_data_.push_back(AggregatedHitTestRegion(
e_id,
HitTestRegionFlags::kHitTestMine | HitTestRegionFlags::kHitTestMouse,
@@ -1097,14 +1098,15 @@ TEST_F(HitTestQueryTest, GetTransformToTarget) {
FrameSinkId b_id = FrameSinkId(4, 4);
FrameSinkId d_id = FrameSinkId(5, 5);
gfx::Rect e_bounds_in_e = gfx::Rect(0, 0, 600, 600);
- gfx::Rect c_bounds_in_e = gfx::Rect(0, 50, 800, 800);
+ gfx::Rect c_bounds_in_e = gfx::Rect(0, 0, 800, 800);
gfx::Rect a_bounds_in_c = gfx::Rect(0, 0, 200, 100);
- gfx::Rect b_bounds_in_c = gfx::Rect(0, 100, 800, 600);
+ gfx::Rect b_bounds_in_c = gfx::Rect(0, 0, 800, 600);
gfx::Rect d_bounds_in_e = gfx::Rect(0, 0, 800, 800);
gfx::Transform transform_e_to_e, transform_e_to_c, transform_c_to_a,
transform_c_to_b, transform_e_to_d;
- transform_e_to_c.Translate(-200, -100);
+ transform_e_to_c.Translate(-200, -150);
transform_e_to_d.Translate(-400, -50);
+ transform_c_to_b.Translate(0, -100);
transform_c_to_b.Skew(2, 3);
transform_c_to_b.Scale(.5f, .7f);
active_data_.push_back(AggregatedHitTestRegion(
@@ -1150,7 +1152,6 @@ TEST_F(HitTestQueryTest, GetTransformToTarget) {
gfx::Transform transform_to_b;
gfx::Transform expected_transform_to_b;
expected_transform_to_b.Translate(-200, -150);
- expected_transform_to_b.Translate(0, -100);
expected_transform_to_b.ConcatTransform(transform_c_to_b);
EXPECT_TRUE(hit_test_query().GetTransformToTarget(b_id, &transform_to_b));
// Use ToString so that we can compare float.
diff --git a/chromium/components/viz/service/display/display.cc b/chromium/components/viz/service/display/display.cc
index 08a8c58cc52..d5b094cbf73 100644
--- a/chromium/components/viz/service/display/display.cc
+++ b/chromium/components/viz/service/display/display.cc
@@ -117,6 +117,16 @@ Display::Display(
}
Display::~Display() {
+#if defined(OS_ANDROID)
+ // In certain cases, drivers hang when tearing down the display. Finishing
+ // before teardown appears to address this. As we're during display teardown,
+ // an additional finish should have minimal impact.
+ // TODO(ericrk): Add a more robust workaround. crbug.com/899705
+ if (auto* context = output_surface_->context_provider()) {
+ context->ContextGL()->Finish();
+ }
+#endif
+
for (auto& observer : observers_)
observer.OnDisplayDestroyed();
observers_.Clear();
diff --git a/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
index 0c7902dc627..10db1240649 100644
--- a/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -2974,4 +2974,199 @@ TEST_F(SurfaceSynchronizationTest, EvictSurface) {
EXPECT_FALSE(IsMarkedForDestruction(child_id3));
}
+// If a parent CompositorFrame is blocked on the child, don't throttle child's
+// surface to avoid a deadlock. In this variation of the test, parent's
+// CompositorFrame arrives first.
+TEST_F(SurfaceSynchronizationTest, ChildNotThrottledWhenParentBlocked1) {
+ const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+ const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1, 1);
+ const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink1, 1, 2);
+ const SurfaceId child_id3 = MakeSurfaceId(kChildFrameSink1, 2, 2);
+ const SurfaceId child_id4 = MakeSurfaceId(kChildFrameSink1, 2, 3);
+ const SurfaceId child_id5 = MakeSurfaceId(kChildFrameSink1, 2, 4);
+
+ // The parent embeds |child_surface3|. This should avoid the child getting
+ // throttled when it submits to |child_id2|.
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id3}, {SurfaceRange(base::nullopt, child_id3)},
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
+
+ // |child_id1| Surface should immediately activate because it's the child's
+ // first surface.
+ child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ Surface* child_surface1 = GetSurfaceForId(child_id1);
+ ASSERT_NE(nullptr, child_surface1);
+ EXPECT_FALSE(child_surface1->HasPendingFrame());
+ EXPECT_TRUE(child_surface1->HasActiveFrame());
+
+ // |child_id2| would normally get throttled, but in this case it shouldn't
+ // because the parent is blocked.
+ child_support1().SubmitCompositorFrame(
+ child_id2.local_surface_id(),
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(),
+ std::vector<TransferableResource>(),
+ MakeDeadline(1u)));
+ Surface* child_surface2 = GetSurfaceForId(child_id2);
+ ASSERT_NE(nullptr, child_surface2);
+ EXPECT_FALSE(child_surface2->HasPendingFrame());
+ EXPECT_TRUE(child_surface2->HasActiveFrame());
+
+ // After this submission, the parent will be unblocked.
+ Surface* parent_surface = GetSurfaceForId(parent_id);
+ ASSERT_NE(nullptr, parent_surface);
+ EXPECT_TRUE(parent_surface->HasPendingFrame());
+ EXPECT_FALSE(parent_surface->HasActiveFrame());
+ child_support1().SubmitCompositorFrame(child_id3.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ Surface* child_surface3 = GetSurfaceForId(child_id3);
+ ASSERT_NE(nullptr, child_surface3);
+ EXPECT_FALSE(child_surface3->HasPendingFrame());
+ EXPECT_TRUE(child_surface3->HasActiveFrame());
+ EXPECT_FALSE(parent_surface->HasPendingFrame());
+ EXPECT_TRUE(parent_surface->HasActiveFrame());
+
+ // This is the first surface after the parent got unblocked. It will not get
+ // throttled.
+ child_support1().SubmitCompositorFrame(child_id4.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ Surface* child_surface4 = GetSurfaceForId(child_id4);
+ ASSERT_NE(nullptr, child_surface4);
+ EXPECT_FALSE(child_surface4->HasPendingFrame());
+ EXPECT_TRUE(child_surface4->HasActiveFrame());
+
+ // This is the second surface after the parent got unblocked. It will get
+ // throttled.
+ child_support1().SubmitCompositorFrame(child_id5.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ Surface* child_surface5 = GetSurfaceForId(child_id5);
+ ASSERT_NE(nullptr, child_surface5);
+ EXPECT_TRUE(child_surface5->HasPendingFrame());
+ EXPECT_FALSE(child_surface5->HasActiveFrame());
+}
+
+// If a parent CompositorFrame is blocked on the child, don't throttle child's
+// surface to avoid a deadlock. In this variation of the test, child's
+// CompositorFrame arrives first.
+TEST_F(SurfaceSynchronizationTest, ChildNotThrottledWhenParentBlocked2) {
+ const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+ const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1, 1);
+ const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink1, 1, 2);
+ const SurfaceId child_id3 = MakeSurfaceId(kChildFrameSink1, 2, 1);
+ const SurfaceId child_id4 = MakeSurfaceId(kChildFrameSink1, 2, 2);
+ const SurfaceId child_id5 = MakeSurfaceId(kChildFrameSink1, 2, 3);
+ const SurfaceId child_id6 = MakeSurfaceId(kChildFrameSink1, 2, 4);
+
+ // |child_id1| Surface should immediately activate.
+ child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ Surface* child_surface1 = GetSurfaceForId(child_id1);
+ ASSERT_NE(nullptr, child_surface1);
+ EXPECT_FALSE(child_surface1->HasPendingFrame());
+ EXPECT_TRUE(child_surface1->HasActiveFrame());
+
+ // |child_id2| Surface should not activate because |child_id1| was never
+ // added as a dependency by a parent.
+ child_support1().SubmitCompositorFrame(
+ child_id2.local_surface_id(),
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(),
+ std::vector<TransferableResource>(),
+ MakeDeadline(1u)));
+ Surface* child_surface2 = GetSurfaceForId(child_id2);
+ ASSERT_NE(nullptr, child_surface2);
+ EXPECT_TRUE(child_surface2->HasPendingFrame());
+ EXPECT_FALSE(child_surface2->HasActiveFrame());
+ EXPECT_TRUE(child_surface2->has_deadline());
+
+ FrameDeadline deadline = MakeDefaultDeadline();
+ base::TimeTicks deadline_wall_time = deadline.ToWallTime();
+ EXPECT_EQ(deadline_wall_time, child_surface2->deadline_for_testing());
+
+ // The parent gets blocked on the child. The child should get unthrottled to
+ // avoid deadlocks.
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id3}, {SurfaceRange(base::nullopt, child_id3)},
+ std::vector<TransferableResource>(),
+ MakeDefaultDeadline()));
+ EXPECT_FALSE(child_surface2->HasPendingFrame());
+ EXPECT_TRUE(child_surface2->HasActiveFrame());
+
+ // After this submission, the parent will be unblocked.
+ Surface* parent_surface = GetSurfaceForId(parent_id);
+ ASSERT_NE(nullptr, parent_surface);
+ EXPECT_TRUE(parent_surface->HasPendingFrame());
+ EXPECT_FALSE(parent_surface->HasActiveFrame());
+ child_support1().SubmitCompositorFrame(child_id4.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ Surface* child_surface4 = GetSurfaceForId(child_id4);
+ ASSERT_NE(nullptr, child_surface4);
+ EXPECT_FALSE(child_surface4->HasPendingFrame());
+ EXPECT_TRUE(child_surface4->HasActiveFrame());
+ EXPECT_FALSE(parent_surface->HasPendingFrame());
+ EXPECT_TRUE(parent_surface->HasActiveFrame());
+
+ // This is the first surface after the parent got unblocked. It will not get
+ // throttled.
+ child_support1().SubmitCompositorFrame(child_id5.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ Surface* child_surface5 = GetSurfaceForId(child_id5);
+ ASSERT_NE(nullptr, child_surface5);
+ EXPECT_FALSE(child_surface5->HasPendingFrame());
+ EXPECT_TRUE(child_surface5->HasActiveFrame());
+
+ // This is the second surface after the parent got unblocked. It will get
+ // throttled.
+ child_support1().SubmitCompositorFrame(child_id6.local_surface_id(),
+ MakeDefaultCompositorFrame());
+ Surface* child_surface6 = GetSurfaceForId(child_id6);
+ ASSERT_NE(nullptr, child_surface6);
+ EXPECT_TRUE(child_surface6->HasPendingFrame());
+ EXPECT_FALSE(child_surface6->HasActiveFrame());
+}
+
+// Tests that in cases where a pending-deletion surface (surface A) is
+// activated during anothother surface (surface B)'s deletion, we don't attempt
+// to delete surface A twice.
+TEST_F(SurfaceSynchronizationTest, SurfaceActivationDuringDeletion) {
+ const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1, 1);
+ // Child-initiated synchronization event:
+ const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink1, 1, 2);
+
+ // Submit a CompositorFrame to |child_id1|.
+ child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
+ MakeDefaultCompositorFrame());
+
+ // Child 1 should not yet be active.
+ Surface* child_surface1 = GetSurfaceForId(child_id1);
+ ASSERT_NE(nullptr, child_surface1);
+ EXPECT_FALSE(child_surface1->HasPendingFrame());
+ EXPECT_TRUE(child_surface1->HasActiveFrame());
+
+ // Submit a CompositorFrame to |child_id2|.
+ child_support1().SubmitCompositorFrame(child_id2.local_surface_id(),
+ MakeDefaultCompositorFrame());
+
+ // Child 2 should not yet be active.
+ Surface* child_surface2 = GetSurfaceForId(child_id2);
+ ASSERT_NE(nullptr, child_surface2);
+ EXPECT_TRUE(child_surface2->HasPendingFrame());
+ EXPECT_FALSE(child_surface2->HasActiveFrame());
+
+ // Evict |child_id2|. both surfaces should be marked for deletion.
+ child_support1().EvictSurface(child_id1.local_surface_id());
+ EXPECT_TRUE(IsMarkedForDestruction(child_id1));
+ EXPECT_TRUE(IsMarkedForDestruction(child_id2));
+
+ // Garbage collect to delete the above surfaces. This will activate
+ // |child_id2|, which will cause it to attempt re-deletion.
+ ExpireAllTemporaryReferencesAndGarbageCollect();
+
+ // Neither should still be marked for deletion.
+ EXPECT_FALSE(IsMarkedForDestruction(child_id1));
+ EXPECT_FALSE(IsMarkedForDestruction(child_id2));
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator.cc b/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
index 847564602a4..ed7a0c36e91 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
@@ -64,7 +64,6 @@ void HitTestAggregator::Aggregate(const SurfaceId& display_surface_id,
aggregate_timer.Elapsed(),
base::TimeDelta::FromMicroseconds(1),
base::TimeDelta::FromSeconds(10), 50);
- referenced_child_regions_.clear();
SendHitTestData();
if (hit_test_debug_ && render_passes) {
@@ -180,6 +179,7 @@ void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
trace_id ? TRACE_EVENT_FLAG_FLOW_IN : TRACE_EVENT_FLAG_NONE, "step",
"AggregateHitTestData(Root)");
+ DCHECK(referenced_child_regions_.empty());
referenced_child_regions_.insert(surface_id.frame_sink_id());
size_t region_index = 1;
@@ -187,7 +187,9 @@ void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
if (region_index >= hit_test_data_capacity_ - 1)
break;
region_index = AppendRegion(region_index, region);
+ DCHECK_EQ(referenced_child_regions_.size(), 1u);
}
+ referenced_child_regions_.erase(referenced_child_regions_.begin());
DCHECK_GE(region_index, 1u);
int32_t child_count = region_index - 1;
@@ -269,6 +271,7 @@ size_t HitTestAggregator::AppendRegion(size_t region_index,
break;
}
}
+ referenced_child_regions_.erase(region.frame_sink_id);
}
DCHECK_GE(region_index - parent_index - 1, 0u);
int32_t child_count = region_index - parent_index - 1;
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator.h b/chromium/components/viz/service/hit_test/hit_test_aggregator.h
index 2b53f958bfd..3d09c6680d4 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator.h
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator.h
@@ -95,8 +95,10 @@ class VIZ_SERVICE_EXPORT HitTestAggregator {
bool hit_test_debug_ = false;
uint32_t hit_test_debug_ask_regions_ = 0;
- // This is the set of FrameSinkIds referenced in the aggregation so far, used
- // to detect cycles.
+ // This is the set of FrameSinkIds referenced in the aggregation in this tree
+ // chain so far, used to detect cycles. We can have regions that have the
+ // same FrameSinkId, e.g. when ALPHA_SHAPE is set in cc::FilterOperations,
+ // but only at the same hierarchy level.
base::flat_set<FrameSinkId> referenced_child_regions_;
base::flat_map<FrameSinkId, uint64_t> last_active_frame_index_;
diff --git a/chromium/components/viz/service/surfaces/surface.cc b/chromium/components/viz/service/surfaces/surface.cc
index fb8c3ea0681..196879a0219 100644
--- a/chromium/components/viz/service/surfaces/surface.cc
+++ b/chromium/components/viz/service/surfaces/surface.cc
@@ -229,9 +229,11 @@ bool Surface::QueueFrame(
surface_client_->ReceiveFromChild(frame.resource_list);
if (!seen_first_surface_dependency_) {
+ // We should not throttle this client if there is another client blocked on
+ // it, in order to avoid deadlocks.
seen_first_surface_dependency_ =
surface_manager_->dependency_tracker()->HasSurfaceBlockedOn(
- surface_id());
+ surface_id().frame_sink_id());
}
bool block_activation =
@@ -331,17 +333,6 @@ void Surface::NotifySurfaceIdAvailable(const SurfaceId& surface_id) {
ActivatePendingFrame(base::nullopt);
}
-bool Surface::IsBlockedOn(const SurfaceId& surface_id) const {
- for (const SurfaceId& dependency : activation_dependencies_) {
- if (dependency.frame_sink_id() != surface_id.frame_sink_id())
- continue;
-
- if (dependency.local_surface_id() <= surface_id.local_surface_id())
- return true;
- }
- return false;
-}
-
void Surface::ActivatePendingFrameForDeadline(
base::Optional<base::TimeDelta> duration) {
if (!pending_frame_data_)
diff --git a/chromium/components/viz/service/surfaces/surface.h b/chromium/components/viz/service/surfaces/surface.h
index cf47e9826fb..4ff0194ffb7 100644
--- a/chromium/components/viz/service/surfaces/surface.h
+++ b/chromium/components/viz/service/surfaces/surface.h
@@ -140,10 +140,6 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
// frame.
void NotifySurfaceIdAvailable(const SurfaceId& surface_id);
- // Returns whether the Surface is blocked on the provided |surface_id| or a
- // predecessor.
- bool IsBlockedOn(const SurfaceId& surface_id) const;
-
// Called if a deadline has been hit and this surface is not yet active but
// it's marked as respecting deadlines.
void ActivatePendingFrameForDeadline(
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_tracker.cc b/chromium/components/viz/service/surfaces/surface_dependency_tracker.cc
index b1435079d60..55542b48068 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_tracker.cc
+++ b/chromium/components/viz/service/surfaces/surface_dependency_tracker.cc
@@ -4,6 +4,7 @@
#include "components/viz/service/surfaces/surface_dependency_tracker.h"
+#include "build/build_config.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_manager.h"
@@ -50,18 +51,10 @@ void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
}
bool SurfaceDependencyTracker::HasSurfaceBlockedOn(
- const SurfaceId& surface_id) const {
- auto it = blocked_surfaces_from_dependency_.find(surface_id.frame_sink_id());
- if (it == blocked_surfaces_from_dependency_.end())
- return false;
-
- for (const SurfaceId& blocked_surface_by_id : it->second) {
- Surface* blocked_surface =
- surface_manager_->GetSurfaceForId(blocked_surface_by_id);
- if (blocked_surface && blocked_surface->IsBlockedOn(surface_id))
- return true;
- }
- return false;
+ const FrameSinkId& frame_sink_id) const {
+ auto it = blocked_surfaces_from_dependency_.find(frame_sink_id);
+ DCHECK(it == blocked_surfaces_from_dependency_.end() || !it->second.empty());
+ return it != blocked_surfaces_from_dependency_.end();
}
void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) {
@@ -86,7 +79,21 @@ void SurfaceDependencyTracker::OnSurfaceDependencyAdded(
base::flat_set<SurfaceId>& blocked_surfaces = it->second;
for (auto iter = blocked_surfaces.begin(); iter != blocked_surfaces.end();) {
- if (iter->local_surface_id() <= surface_id.local_surface_id()) {
+ bool should_notify =
+ iter->local_surface_id() <= surface_id.local_surface_id();
+#if defined(OS_ANDROID)
+ // On Android we work around a throttling bug by also firing if the
+ // immediately preceding surface has a dependency added.
+ // TODO(https://crbug.com/898460): Solve this generally.
+ bool is_same_parent =
+ iter->local_surface_id().parent_sequence_number() ==
+ surface_id.local_surface_id().parent_sequence_number();
+ bool is_next_child =
+ iter->local_surface_id().child_sequence_number() ==
+ surface_id.local_surface_id().child_sequence_number() + 1;
+ should_notify |= is_same_parent && is_next_child;
+#endif
+ if (should_notify) {
dependencies_to_notify.push_back(*iter);
iter = blocked_surfaces.erase(iter);
} else {
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_tracker.h b/chromium/components/viz/service/surfaces/surface_dependency_tracker.h
index 81542ac333f..e8fbd88f1ac 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_tracker.h
+++ b/chromium/components/viz/service/surfaces/surface_dependency_tracker.h
@@ -38,8 +38,8 @@ class VIZ_SERVICE_EXPORT SurfaceDependencyTracker {
void RequestSurfaceResolution(Surface* surface);
// Returns whether the dependency tracker has a surface blocked on the
- // provided |surface_id|.
- bool HasSurfaceBlockedOn(const SurfaceId& surface_id) const;
+ // provided |frame_sink_id|.
+ bool HasSurfaceBlockedOn(const FrameSinkId& frame_sink_id) const;
void OnSurfaceActivated(Surface* surface);
void OnSurfaceDependencyAdded(const SurfaceId& surface_id);
diff --git a/chromium/components/viz/service/surfaces/surface_manager.cc b/chromium/components/viz/service/surfaces/surface_manager.cc
index 4a4dd72224d..4698e8e19b1 100644
--- a/chromium/components/viz/service/surfaces/surface_manager.cc
+++ b/chromium/components/viz/service/surfaces/surface_manager.cc
@@ -205,6 +205,17 @@ void SurfaceManager::GarbageCollectSurfaces() {
// ~Surface() draw callback could modify |surfaces_to_destroy_|.
for (const SurfaceId& surface_id : surfaces_to_delete)
DestroySurfaceInternal(surface_id);
+
+ // Run another pass over surfaces_to_delete, all of which have just been
+ // deleted, making sure they are not present in |surfaces_to_destroy_|. This
+ // is necessary as ~Surface may re-add already-in-destruction surfaces to the
+ // set and we need to avoid double-deletion.
+ // TODO(ericrk): Removing surfaces both here and above allows for
+ // GarbageCollectSurfaces re-entrancy, which is exercised in tests and is
+ // hard to prove can't happen in the wild. Evaluate whether we should allow
+ // re-entrancy, and if not just remove here.
+ for (const SurfaceId& surface_id : surfaces_to_delete)
+ surfaces_to_destroy_.erase(surface_id);
}
const base::flat_set<SurfaceId>& SurfaceManager::GetSurfacesReferencedByParent(
diff --git a/chromium/content/app/strings/translations/content_strings_am.xtb b/chromium/content/app/strings/translations/content_strings_am.xtb
index 9ea13ab9040..4000a06bde5 100644
--- a/chromium/content/app/strings/translations/content_strings_am.xtb
+++ b/chromium/content/app/strings/translations/content_strings_am.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">የምናሌ አዝራር</translation>
<translation id="4446524499724042288">የሙዳየ ቃላት ዋቢ</translation>
<translation id="4522570452068850558">ዝርዝሮች</translation>
+<translation id="4542388879936266156">ቀሪ ጊዜ፦ <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">ቅጽ</translation>
<translation id="4661075872484491155">ዛፍ</translation>
<translation id="4664250907885839816">ከ«<ph name="ATSIGN" />» በኋላ የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">ዓዓዓዓ</translation>
<translation id="8284326494547611709">መግለጫ ጽሑፎች</translation>
<translation id="835897206747267392">ልክ ያልሆነ እሴት።</translation>
+<translation id="8403857369060869934">ያለፈው ጊዜ፦ <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">ክፍለ አካል</translation>
<translation id="8433900881053900389">የመሣሪያ አሞሌ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ፋይሎች</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ar.xtb b/chromium/content/app/strings/translations/content_strings_ar.xtb
index ab4f8eade1b..d4aa6aff188 100644
--- a/chromium/content/app/strings/translations/content_strings_ar.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ar.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">زر القائمة</translation>
<translation id="4446524499724042288">مرجع مسرد مصطلحات</translation>
<translation id="4522570452068850558">التفاصيل</translation>
+<translation id="4542388879936266156">الوقت المتبقي: <ph name="REMAINING_TIME" />ّ</translation>
<translation id="4597532268155981612">نموذج</translation>
<translation id="4661075872484491155">متفرع</translation>
<translation id="4664250907885839816">يجب ألا يشتمل الجزء الذي يلي العلامة "<ph name="ATSIGN" />" على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">سنة</translation>
<translation id="8284326494547611709">الترجمة والشرح</translation>
<translation id="835897206747267392">قيمة غير صحيحة</translation>
+<translation id="8403857369060869934">الوقت المنقضي: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">جزء</translation>
<translation id="8433900881053900389">شريط الأدوات</translation>
<translation id="8444882422881193423">عدد الملفات: <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_bg.xtb b/chromium/content/app/strings/translations/content_strings_bg.xtb
index af5c981a911..30de99754f1 100644
--- a/chromium/content/app/strings/translations/content_strings_bg.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bg.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">бутон за меню</translation>
<translation id="4446524499724042288">препратка към определение в терминологичния речник</translation>
<translation id="4522570452068850558">Подробности</translation>
+<translation id="4542388879936266156">оставащо време: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">формуляр</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Текстът след „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">гггг</translation>
<translation id="8284326494547611709">Надписи</translation>
<translation id="835897206747267392">Невалидна стойност.</translation>
+<translation id="8403857369060869934">изминало време: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">част</translation>
<translation id="8433900881053900389">лента с инструменти</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> файла</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_bn.xtb b/chromium/content/app/strings/translations/content_strings_bn.xtb
index 1687769f998..86895e57762 100644
--- a/chromium/content/app/strings/translations/content_strings_bn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bn.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">মেনু বোতাম</translation>
<translation id="4446524499724042288">শব্দকোষের রেফারেন্স</translation>
<translation id="4522570452068850558">বিশদ বিবরণ</translation>
+<translation id="4542388879936266156">বাকি সময়: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">ফর্ম</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">পরিচয়লিপিগুলি</translation>
<translation id="835897206747267392">অকার্যকর মান৷</translation>
+<translation id="8403857369060869934">অতিবাহিত সময়: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">অংশ</translation>
<translation id="8433900881053900389">টুল দণ্ড</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> টি ফাইল</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ca.xtb b/chromium/content/app/strings/translations/content_strings_ca.xtb
index b87d799eee0..92f873ba250 100644
--- a/chromium/content/app/strings/translations/content_strings_ca.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ca.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">botó de menú</translation>
<translation id="4446524499724042288">referència del glossari</translation>
<translation id="4522570452068850558">Detalls</translation>
+<translation id="4542388879936266156">temps restant: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulari</translation>
<translation id="4661075872484491155">arbre</translation>
<translation id="4664250907885839816">Un domini precedit per "<ph name="ATSIGN" />" no pot contenir el símbol "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtítols</translation>
<translation id="835897206747267392">Valor no vàlid.</translation>
+<translation id="8403857369060869934">temps transcorregut: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">part</translation>
<translation id="8433900881053900389">barra d'eines</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fitxers</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_cs.xtb b/chromium/content/app/strings/translations/content_strings_cs.xtb
index fa16a1c0f6b..542a503a1bc 100644
--- a/chromium/content/app/strings/translations/content_strings_cs.xtb
+++ b/chromium/content/app/strings/translations/content_strings_cs.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">tlačítko nabídky</translation>
<translation id="4446524499724042288">odkaz na glosář</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="4542388879936266156">zbývající čas: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulář</translation>
<translation id="4661075872484491155">strom</translation>
<translation id="4664250907885839816">Část za znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">rrrr</translation>
<translation id="8284326494547611709">Titulky</translation>
<translation id="835897206747267392">Neplatná hodnota.</translation>
+<translation id="8403857369060869934">uplynulý čas: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">část</translation>
<translation id="8433900881053900389">lišta</translation>
<translation id="8444882422881193423">Počet souborů: <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_da.xtb b/chromium/content/app/strings/translations/content_strings_da.xtb
index eb2a102da33..c735c9027fd 100644
--- a/chromium/content/app/strings/translations/content_strings_da.xtb
+++ b/chromium/content/app/strings/translations/content_strings_da.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menuknap</translation>
<translation id="4446524499724042288">reference på ordliste</translation>
<translation id="4522570452068850558">Detaljer</translation>
+<translation id="4542388879936266156">resterende tid: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formular</translation>
<translation id="4661075872484491155">træ</translation>
<translation id="4664250907885839816">Den del, der kommer efter "<ph name="ATSIGN" />", må ikke indeholde symbolet "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">åååå</translation>
<translation id="8284326494547611709">Undertekster</translation>
<translation id="835897206747267392">Ugyldig værdi.</translation>
+<translation id="8403857369060869934">forløbet tid: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">del</translation>
<translation id="8433900881053900389">værktøjslinje</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
@@ -228,7 +230,7 @@
<translation id="9093215626363556771">afslut integreret billede</translation>
<translation id="9108370397979208512">matematik</translation>
<translation id="9132465097189459683">Andet...</translation>
-<translation id="9138385573473225930">notifikation</translation>
+<translation id="9138385573473225930">underretning</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, med start <ph name="WEEK_START_DATE" /></translation>
<translation id="916607977885256133">Integreret billede</translation>
<translation id="9168329111483466115">fodnote</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_de.xtb b/chromium/content/app/strings/translations/content_strings_de.xtb
index 69a5d5d16bd..93e92a107bc 100644
--- a/chromium/content/app/strings/translations/content_strings_de.xtb
+++ b/chromium/content/app/strings/translations/content_strings_de.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">Menüschaltfläche</translation>
<translation id="4446524499724042288">Glossarreferenz</translation>
<translation id="4522570452068850558">Details</translation>
+<translation id="4542388879936266156">verbleibende Zeit: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">Formular</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Nach dem <ph name="ATSIGN" />-Zeichen darf das Zeichen "<ph name="INVALIDCHARACTER" />" nicht verwendet werden.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">jjjj</translation>
<translation id="8284326494547611709">Untertitel</translation>
<translation id="835897206747267392">Ungültiger Wert.</translation>
+<translation id="8403857369060869934">verstrichene Zeit: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">Teil</translation>
<translation id="8433900881053900389">Symbolleiste</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> Dateien</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_el.xtb b/chromium/content/app/strings/translations/content_strings_el.xtb
index 4793b07f2cf..33061048c2a 100644
--- a/chromium/content/app/strings/translations/content_strings_el.xtb
+++ b/chromium/content/app/strings/translations/content_strings_el.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">κουμπί μενού</translation>
<translation id="4446524499724042288">αναφορά στο γλωσσάρι</translation>
<translation id="4522570452068850558">Λεπτομέρειες</translation>
+<translation id="4542388879936266156">χρόνος που απομένει: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">φόρμα</translation>
<translation id="4661075872484491155">δέντρο</translation>
<translation id="4664250907885839816">Το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">εεεε</translation>
<translation id="8284326494547611709">Υπότιτλοι</translation>
<translation id="835897206747267392">Μη έγκυρη τιμή.</translation>
+<translation id="8403857369060869934">χρόνος που παρήλθε: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">τμήμα</translation>
<translation id="8433900881053900389">γραμμή εργαλείων</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> αρχεία</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_en-GB.xtb b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
index f8251cd02fc..c1ce0d6f28f 100644
--- a/chromium/content/app/strings/translations/content_strings_en-GB.xtb
+++ b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menu button</translation>
<translation id="4446524499724042288">glossary reference</translation>
<translation id="4522570452068850558">Details</translation>
+<translation id="4542388879936266156">remaining time: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">form</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">A part following '<ph name="ATSIGN" />' should not contain the symbol '<ph name="INVALIDCHARACTER" />'.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Captions</translation>
<translation id="835897206747267392">Invalid value.</translation>
+<translation id="8403857369060869934">elapsed time: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">part</translation>
<translation id="8433900881053900389">toolbar</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> files</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_es-419.xtb b/chromium/content/app/strings/translations/content_strings_es-419.xtb
index ac519857f9d..781b4382137 100644
--- a/chromium/content/app/strings/translations/content_strings_es-419.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es-419.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">botón de menú</translation>
<translation id="4446524499724042288">referencia de glosario</translation>
<translation id="4522570452068850558">Detalles</translation>
+<translation id="4542388879936266156">tiempo restante: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulario</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">El texto después del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtítulos</translation>
<translation id="835897206747267392">Valor no válido.</translation>
+<translation id="8403857369060869934">tiempo transcurrido: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra de herramientas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> archivos</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_es.xtb b/chromium/content/app/strings/translations/content_strings_es.xtb
index fe448681d7c..9bf9370b387 100644
--- a/chromium/content/app/strings/translations/content_strings_es.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">botón de menú</translation>
<translation id="4446524499724042288">referencia de glosario</translation>
<translation id="4522570452068850558">Detalles</translation>
+<translation id="4542388879936266156">tiempo restante: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulario</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">El texto detrás del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtítulos</translation>
<translation id="835897206747267392">Valor no válido</translation>
+<translation id="8403857369060869934">tiempo transcurrido: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra de herramientas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> archivos</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_et.xtb b/chromium/content/app/strings/translations/content_strings_et.xtb
index 70aa8ad210e..101bee26ab3 100644
--- a/chromium/content/app/strings/translations/content_strings_et.xtb
+++ b/chromium/content/app/strings/translations/content_strings_et.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menüünupp</translation>
<translation id="4446524499724042288">sõnastiku viide</translation>
<translation id="4522570452068850558">Üksikasjad</translation>
+<translation id="4542388879936266156">järelejäänud aeg: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">vorm</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Märgile „<ph name="ATSIGN" />” järgnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER" />”.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtiitrid</translation>
<translation id="835897206747267392">Kehtetu väärtus.</translation>
+<translation id="8403857369060869934">möödunud aeg: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">osa</translation>
<translation id="8433900881053900389">tööriistariba</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> faili</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fa.xtb b/chromium/content/app/strings/translations/content_strings_fa.xtb
index 53b474df401..75bd1385b31 100644
--- a/chromium/content/app/strings/translations/content_strings_fa.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fa.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">دکمه منو</translation>
<translation id="4446524499724042288">مرجع واژه‌نامه</translation>
<translation id="4522570452068850558">جزئیات</translation>
+<translation id="4542388879936266156">زمان باقی‌مانده: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">فرم</translation>
<translation id="4661075872484491155">درخت</translation>
<translation id="4664250907885839816">قسمت بعد از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">زیرنویس‌ها</translation>
<translation id="835897206747267392">مقدار نامعتبر.</translation>
+<translation id="8403857369060869934">زمان سپری‌شده: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">بخش</translation>
<translation id="8433900881053900389">نوار ابزار</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> فایل</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fi.xtb b/chromium/content/app/strings/translations/content_strings_fi.xtb
index 6cdaa8c7f85..11cd70a5c54 100644
--- a/chromium/content/app/strings/translations/content_strings_fi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fi.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">valikkopainike</translation>
<translation id="4446524499724042288">sanastoviittaus</translation>
<translation id="4522570452068850558">Tiedot</translation>
+<translation id="4542388879936266156">jäljellä oleva aika: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">lomake</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816"><ph name="ATSIGN" />-osan jälkeen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER" />.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">vvvv</translation>
<translation id="8284326494547611709">Tekstitykset</translation>
<translation id="835897206747267392">Virheellinen arvo.</translation>
+<translation id="8403857369060869934">kulunut aika: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">osa</translation>
<translation id="8433900881053900389">työkalupalkki</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> tiedostoa</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fil.xtb b/chromium/content/app/strings/translations/content_strings_fil.xtb
index 1c21a25328e..efd20a92d3e 100644
--- a/chromium/content/app/strings/translations/content_strings_fil.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fil.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">button ng menu</translation>
<translation id="4446524499724042288">sanggunian sa glosaryo</translation>
<translation id="4522570452068850558">Mga Detalye</translation>
+<translation id="4542388879936266156">natitirang oras: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">form</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER" />' ang bahagi pagkatapos ng '<ph name="ATSIGN" />.'</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Mga Caption</translation>
<translation id="835897206747267392">Di-wastong halaga.</translation>
+<translation id="8403857369060869934">lumipas na oras: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">bahagi</translation>
<translation id="8433900881053900389">toolbar</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> mga file</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_fr.xtb b/chromium/content/app/strings/translations/content_strings_fr.xtb
index 4f04a9ecb40..7ec7829a373 100644
--- a/chromium/content/app/strings/translations/content_strings_fr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fr.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">bouton de menu</translation>
<translation id="4446524499724042288">référence de glossaire</translation>
<translation id="4522570452068850558">Détails</translation>
+<translation id="4542388879936266156">temps restant : <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulaire</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">La partie précédée du symbole "<ph name="ATSIGN" />" ne doit pas contenir le caractère "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Sous-titres</translation>
<translation id="835897206747267392">Valeur incorrecte</translation>
+<translation id="8403857369060869934">temps écoulé : <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">partie</translation>
<translation id="8433900881053900389">barre d'outils</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fichiers</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_gu.xtb b/chromium/content/app/strings/translations/content_strings_gu.xtb
index dc4531c7421..bfe24a3853d 100644
--- a/chromium/content/app/strings/translations/content_strings_gu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_gu.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">મેનૂ બટન</translation>
<translation id="4446524499724042288">શબ્દાવલીનો સંદર્ભ</translation>
<translation id="4522570452068850558">વિગતો</translation>
+<translation id="4542388879936266156">બાકીનો સમય: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">ફોર્મ</translation>
<translation id="4661075872484491155">ટ્રી</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ને અનુસરી રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">કૅપ્શન્સ</translation>
<translation id="835897206747267392">અમાન્ય મૂલ્ય.</translation>
+<translation id="8403857369060869934">વીતેલો સમય: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">ભાગ</translation>
<translation id="8433900881053900389">ટુલબાર</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ફાઇલો</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hi.xtb b/chromium/content/app/strings/translations/content_strings_hi.xtb
index aad00a6c335..22e9a254ed4 100644
--- a/chromium/content/app/strings/translations/content_strings_hi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hi.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">मेनू बटन</translation>
<translation id="4446524499724042288">संदर्भ के लिए शब्दावली</translation>
<translation id="4522570452068850558">विवरण</translation>
+<translation id="4542388879936266156">बचा हुआ समय: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">फ़ॉर्म</translation>
<translation id="4661075872484491155">ट्री</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">कैप्शन</translation>
<translation id="835897206747267392">अमान्य मान.</translation>
+<translation id="8403857369060869934">बीता हुआ समय: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">भाग</translation>
<translation id="8433900881053900389">टूलबार</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फ़ाइल</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hr.xtb b/chromium/content/app/strings/translations/content_strings_hr.xtb
index 3107c0c4479..21756243dcf 100644
--- a/chromium/content/app/strings/translations/content_strings_hr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hr.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">gumb izbornika</translation>
<translation id="4446524499724042288">referenca iz pojmovnika</translation>
<translation id="4522570452068850558">Detalji</translation>
+<translation id="4542388879936266156">preostalo vrijeme: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">obrazac</translation>
<translation id="4661075872484491155">stablo</translation>
<translation id="4664250907885839816">Dio adrese iza znaka "<ph name="ATSIGN" />" ne smije sadržavati simbol "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">gggg</translation>
<translation id="8284326494547611709">Titlovi</translation>
<translation id="835897206747267392">Nevažeća vrijednost.</translation>
+<translation id="8403857369060869934">proteklo vrijeme: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">dio</translation>
<translation id="8433900881053900389">alatna traka</translation>
<translation id="8444882422881193423">Broj datoteka: <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_hu.xtb b/chromium/content/app/strings/translations/content_strings_hu.xtb
index c684f56d7b3..f2acce03ceb 100644
--- a/chromium/content/app/strings/translations/content_strings_hu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hu.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menügomb</translation>
<translation id="4446524499724042288">szószedet-hivatkozás</translation>
<translation id="4522570452068850558">Részletek</translation>
+<translation id="4542388879936266156">hátralévő idő: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">űrlap</translation>
<translation id="4661075872484491155">fa</translation>
<translation id="4664250907885839816">A „<ph name="ATSIGN" />” utáni rész nem tartalmazhat „<ph name="INVALIDCHARACTER" />” karaktert.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">éééé</translation>
<translation id="8284326494547611709">Feliratok</translation>
<translation id="835897206747267392">Érvénytelen érték.</translation>
+<translation id="8403857369060869934">eltelt idő: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">rész</translation>
<translation id="8433900881053900389">eszköztár</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fájl</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_id.xtb b/chromium/content/app/strings/translations/content_strings_id.xtb
index 1ca7cdf0705..73428820683 100644
--- a/chromium/content/app/strings/translations/content_strings_id.xtb
+++ b/chromium/content/app/strings/translations/content_strings_id.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">tombol menu</translation>
<translation id="4446524499724042288">referensi glosarium</translation>
<translation id="4522570452068850558">Detail</translation>
+<translation id="4542388879936266156">sisa waktu: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulir</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Bagian setelah '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">tttt</translation>
<translation id="8284326494547611709">Teks</translation>
<translation id="835897206747267392">Nilai tidak valid.</translation>
+<translation id="8403857369060869934">waktu berlalu: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">bagian</translation>
<translation id="8433900881053900389">bilah alat</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> file</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_it.xtb b/chromium/content/app/strings/translations/content_strings_it.xtb
index 14f37b6c814..52129365de0 100644
--- a/chromium/content/app/strings/translations/content_strings_it.xtb
+++ b/chromium/content/app/strings/translations/content_strings_it.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">pulsante di menu</translation>
<translation id="4446524499724042288">riferimento glossario</translation>
<translation id="4522570452068850558">Dettagli</translation>
+<translation id="4542388879936266156">Tempo rimanente: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">modulo</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Una parte che segue "<ph name="ATSIGN" />" non deve contenere il simbolo "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Sottotitoli</translation>
<translation id="835897206747267392">Valore non valido.</translation>
+<translation id="8403857369060869934">Tempo trascorso: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra degli strumenti</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> file</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_iw.xtb b/chromium/content/app/strings/translations/content_strings_iw.xtb
index 19117ec8609..a35f142a085 100644
--- a/chromium/content/app/strings/translations/content_strings_iw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_iw.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">לחצן תפריט</translation>
<translation id="4446524499724042288">הפניה למילון מונחים</translation>
<translation id="4522570452068850558">פרטים</translation>
+<translation id="4542388879936266156">הזמן שנותר: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">טופס</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">כתוביות</translation>
<translation id="835897206747267392">ערך לא חוקי.</translation>
+<translation id="8403857369060869934">הזמן שחלף: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">חלק</translation>
<translation id="8433900881053900389">סרגל כלים</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> קבצים</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ja.xtb b/chromium/content/app/strings/translations/content_strings_ja.xtb
index f3088626ed0..1996f553d5f 100644
--- a/chromium/content/app/strings/translations/content_strings_ja.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ja.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">メニューボタン</translation>
<translation id="4446524499724042288">用語参照</translation>
<translation id="4522570452068850558">詳細</translation>
+<translation id="4542388879936266156">残り時間: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">フォーム</translation>
<translation id="4661075872484491155">ツリー</translation>
<translation id="4664250907885839816">「<ph name="ATSIGN" />」に続く文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405"> 年 </translation>
<translation id="8284326494547611709">字幕</translation>
<translation id="835897206747267392">値が無効です。</translation>
+<translation id="8403857369060869934">経過時間: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">部</translation>
<translation id="8433900881053900389">ツールバー</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ファイル</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_kn.xtb b/chromium/content/app/strings/translations/content_strings_kn.xtb
index 45a2c335671..9d29ffd1b94 100644
--- a/chromium/content/app/strings/translations/content_strings_kn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_kn.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">ಮೆನು ಬಟನ್</translation>
<translation id="4446524499724042288">ಪದಕೋಶ ಉಲ್ಲೇಖ</translation>
<translation id="4522570452068850558">ವಿವರಗಳು</translation>
+<translation id="4542388879936266156">ಬಾಕಿ ಉಳಿದಿರುವ ಸಮಯ: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">ಫಾರ್ಮ್</translation>
<translation id="4661075872484491155">ಮರ</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">ವವವವ</translation>
<translation id="8284326494547611709">ಶೀರ್ಷಿಕೆಗಳು</translation>
<translation id="835897206747267392">ಅಮಾನ್ಯ ಮೌಲ್ಯ.</translation>
+<translation id="8403857369060869934">ಕಳೆದುಹೋದ ಸಮಯ: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">ಭಾಗ</translation>
<translation id="8433900881053900389">ಟೂಲ್‌ಬಾರ್</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ಫೈಲ್‌ಗಳು</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ko.xtb b/chromium/content/app/strings/translations/content_strings_ko.xtb
index 289e7f4ff30..6133baf54eb 100644
--- a/chromium/content/app/strings/translations/content_strings_ko.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ko.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">메뉴 버튼</translation>
<translation id="4446524499724042288">용어 참조</translation>
<translation id="4522570452068850558">세부정보</translation>
+<translation id="4542388879936266156">남은 시간: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">양식</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' 다음 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">연도</translation>
<translation id="8284326494547611709">자막</translation>
<translation id="835897206747267392">값이 잘못되었습니다.</translation>
+<translation id="8403857369060869934">경과 시간: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">부</translation>
<translation id="8433900881053900389">툴바</translation>
<translation id="8444882422881193423">파일 <ph name="NUMBER_OF_FILES" />개</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_lt.xtb b/chromium/content/app/strings/translations/content_strings_lt.xtb
index fba7f297325..c354878208d 100644
--- a/chromium/content/app/strings/translations/content_strings_lt.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lt.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">meniu mygtukas</translation>
<translation id="4446524499724042288">aiškinamojo terminų žodyno nuoroda</translation>
<translation id="4522570452068850558">Išsami informacija</translation>
+<translation id="4542388879936266156">likęs laikas: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">forma</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Po „<ph name="ATSIGN" />“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER" />“.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">mmmm</translation>
<translation id="8284326494547611709">Subtitrai</translation>
<translation id="835897206747267392">Neteisinga vertė.</translation>
+<translation id="8403857369060869934">praėjęs laikas: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">dalis</translation>
<translation id="8433900881053900389">įrankių juosta</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> failai (-ų)</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_lv.xtb b/chromium/content/app/strings/translations/content_strings_lv.xtb
index b4ebbac28d6..8902dff3cac 100644
--- a/chromium/content/app/strings/translations/content_strings_lv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lv.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">izvēlnes poga</translation>
<translation id="4446524499724042288">atsauce uz glosāriju</translation>
<translation id="4522570452068850558">Informācija</translation>
+<translation id="4542388879936266156">atlikušais laiks: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">veidlapa</translation>
<translation id="4661075872484491155">koks</translation>
<translation id="4664250907885839816">Daļā, kas atrodas aiz zīmes <ph name="ATSIGN" />, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER" />.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">gggg</translation>
<translation id="8284326494547611709">Paraksti</translation>
<translation id="835897206747267392">Nederīga vērtība.</translation>
+<translation id="8403857369060869934">pagājušais laiks: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">daļa</translation>
<translation id="8433900881053900389">rīkjosla</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> faili</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ml.xtb b/chromium/content/app/strings/translations/content_strings_ml.xtb
index 66a7cf9e342..ce5fa4e2a5f 100644
--- a/chromium/content/app/strings/translations/content_strings_ml.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ml.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">മെനു ബട്ടൺ</translation>
<translation id="4446524499724042288">പദസഞ്ചയ റെഫറൻസ്</translation>
<translation id="4522570452068850558">വിശദാംശങ്ങൾ‌</translation>
+<translation id="4542388879936266156">അവശേഷിക്കുന്ന സമയം: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">ഫോം</translation>
<translation id="4661075872484491155">ട്രീ</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">വർഷം</translation>
<translation id="8284326494547611709">അടിക്കുറിപ്പുകൾ</translation>
<translation id="835897206747267392">അസാധുവായ മൂല്യം.</translation>
+<translation id="8403857369060869934">കഴിഞ്ഞ സമയം: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">ഭാഗം</translation>
<translation id="8433900881053900389">ടൂൾബാർ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ഫയലുകള്‍</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_mr.xtb b/chromium/content/app/strings/translations/content_strings_mr.xtb
index 2e1d4935a66..c4ad1897491 100644
--- a/chromium/content/app/strings/translations/content_strings_mr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_mr.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">मेनू बटण</translation>
<translation id="4446524499724042288">शब्दावली संदर्भ</translation>
<translation id="4522570452068850558">तपशील</translation>
+<translation id="4542388879936266156">शिल्लक वेळ: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">फॉर्म</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' चे फॉलो करणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">मथळे</translation>
<translation id="835897206747267392">चुकीचे मूल्य.</translation>
+<translation id="8403857369060869934">गेलेला वेळ: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">भाग</translation>
<translation id="8433900881053900389">टूलबार</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फायली</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ms.xtb b/chromium/content/app/strings/translations/content_strings_ms.xtb
index d9eafeebd85..cd9cc99fc62 100644
--- a/chromium/content/app/strings/translations/content_strings_ms.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ms.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">butang menu</translation>
<translation id="4446524499724042288">rujukan glosari</translation>
<translation id="4522570452068850558">Butiran</translation>
+<translation id="4542388879936266156">masa yang tinggal: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">borang</translation>
<translation id="4661075872484491155">pohon</translation>
<translation id="4664250907885839816">Bahagian selepas '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Kapsyen</translation>
<translation id="835897206747267392">Nilai tidak sah.</translation>
+<translation id="8403857369060869934">masa berlalu: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">bahagian</translation>
<translation id="8433900881053900389">bar alat</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fail</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_nl.xtb b/chromium/content/app/strings/translations/content_strings_nl.xtb
index c31f713ced7..e0af6ed8d47 100644
--- a/chromium/content/app/strings/translations/content_strings_nl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_nl.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menuknop</translation>
<translation id="4446524499724042288">woordenlijstreferentie</translation>
<translation id="4522570452068850558">Details</translation>
+<translation id="4542388879936266156">resterende tijd: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulier</translation>
<translation id="4661075872484491155">structuur</translation>
<translation id="4664250907885839816">Het adresgedeelte na '<ph name="ATSIGN" />' mag niet het teken '<ph name="INVALIDCHARACTER" />' bevatten.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">jjjj</translation>
<translation id="8284326494547611709">Ondertiteling</translation>
<translation id="835897206747267392">Ongeldige waarde.</translation>
+<translation id="8403857369060869934">verstreken tijd: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">deel</translation>
<translation id="8433900881053900389">werkbalk</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> bestanden</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_no.xtb b/chromium/content/app/strings/translations/content_strings_no.xtb
index 3425a9ab99d..1466b040cd0 100644
--- a/chromium/content/app/strings/translations/content_strings_no.xtb
+++ b/chromium/content/app/strings/translations/content_strings_no.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menyknapp</translation>
<translation id="4446524499724042288">ordlistereferanse</translation>
<translation id="4522570452068850558">Detaljer</translation>
+<translation id="4542388879936266156">tid som gjenstår: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">skjema</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">En del etterfulgt av «<ph name="ATSIGN" />» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER" />».</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">åååå</translation>
<translation id="8284326494547611709">Teksting</translation>
<translation id="835897206747267392">Ugyldig verdi</translation>
+<translation id="8403857369060869934">medgått tid: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">del</translation>
<translation id="8433900881053900389">verktøyrad</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_pl.xtb b/chromium/content/app/strings/translations/content_strings_pl.xtb
index 606c51e09a9..7dd99a81fd7 100644
--- a/chromium/content/app/strings/translations/content_strings_pl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pl.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">przycisk menu</translation>
<translation id="4446524499724042288">odniesienie do słownika</translation>
<translation id="4522570452068850558">Szczegóły</translation>
+<translation id="4542388879936266156">pozostało: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formularz</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Część po znaku „<ph name="ATSIGN" />” nie może zawierać symbolu „<ph name="INVALIDCHARACTER" />”.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">rrrr</translation>
<translation id="8284326494547611709">Napisy</translation>
<translation id="835897206747267392">Nieprawidłowa wartość.</translation>
+<translation id="8403857369060869934">upłynęło: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">część</translation>
<translation id="8433900881053900389">pasek narzędzi</translation>
<translation id="8444882422881193423">Liczba plików: <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
index fe42f1147c5..d35546a4a62 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">botão de menu</translation>
<translation id="4446524499724042288">referência de glossário</translation>
<translation id="4522570452068850558">Detalhes</translation>
+<translation id="4542388879936266156">tempo restante: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulário</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">A parte depois de "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Legendas</translation>
<translation id="835897206747267392">Valor inválido.</translation>
+<translation id="8403857369060869934">tempo decorrido: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra de ferramentas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> arquivos</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
index c0f3275c561..491e03d0e20 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">botão de menu</translation>
<translation id="4446524499724042288">referência do glossário</translation>
<translation id="4522570452068850558">Detalhes</translation>
+<translation id="4542388879936266156">tempo restante: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulário</translation>
<translation id="4661075872484491155">árvore</translation>
<translation id="4664250907885839816">Uma parte a seguir a "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Legendas</translation>
<translation id="835897206747267392">Valor inválido.</translation>
+<translation id="8403857369060869934">tempo decorrido: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">barra de ferramentas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ficheiros</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ro.xtb b/chromium/content/app/strings/translations/content_strings_ro.xtb
index d4b11444778..ee95db287f5 100644
--- a/chromium/content/app/strings/translations/content_strings_ro.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ro.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">buton de meniu</translation>
<translation id="4446524499724042288">trimitere la glosar</translation>
<translation id="4522570452068850558">Detalii</translation>
+<translation id="4542388879936266156">timp rămas: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formular</translation>
<translation id="4661075872484491155">arbore</translation>
<translation id="4664250907885839816">Valoarea care urmează după semnul „<ph name="ATSIGN" />” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER" />”.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">aaaa</translation>
<translation id="8284326494547611709">Subtitrări</translation>
<translation id="835897206747267392">Valoare nevalidă.</translation>
+<translation id="8403857369060869934">timp scurs: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">parte</translation>
<translation id="8433900881053900389">bară de instrumente</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fișiere</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ru.xtb b/chromium/content/app/strings/translations/content_strings_ru.xtb
index 9c03dc341e8..b3b0e4b80bf 100644
--- a/chromium/content/app/strings/translations/content_strings_ru.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ru.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">кнопка меню</translation>
<translation id="4446524499724042288">ссылка на словарную статью</translation>
<translation id="4522570452068850558">Подробнее</translation>
+<translation id="4542388879936266156">осталось времени: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">форма</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Часть адреса после символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">гггг</translation>
<translation id="8284326494547611709">Титры</translation>
<translation id="835897206747267392">Недопустимые данные.</translation>
+<translation id="8403857369060869934">прошло времени: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">часть</translation>
<translation id="8433900881053900389">панель инструментов</translation>
<translation id="8444882422881193423">Число файлов: <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sk.xtb b/chromium/content/app/strings/translations/content_strings_sk.xtb
index b7346f5caaa..b03211ff1dc 100644
--- a/chromium/content/app/strings/translations/content_strings_sk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sk.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">tlačidlo ponuky</translation>
<translation id="4446524499724042288">glosárový termín</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="4542388879936266156">zostávajúci čas: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulár</translation>
<translation id="4661075872484491155">strom</translation>
<translation id="4664250907885839816">Časť za znakom <ph name="ATSIGN" /> by nemala obsahovať symbol <ph name="INVALIDCHARACTER" />.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">rrrr</translation>
<translation id="8284326494547611709">Titulky</translation>
<translation id="835897206747267392">Neplatná hodnota.</translation>
+<translation id="8403857369060869934">uplynutý čas: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">časť</translation>
<translation id="8433900881053900389">panel s nástrojmi</translation>
<translation id="8444882422881193423">Počet súborov: <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sl.xtb b/chromium/content/app/strings/translations/content_strings_sl.xtb
index ff44b9c97be..5d8dcba6f2d 100644
--- a/chromium/content/app/strings/translations/content_strings_sl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sl.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menijski gumb</translation>
<translation id="4446524499724042288">vnos v glosarju</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="4542388879936266156">preostali čas: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">obrazec</translation>
<translation id="4661075872484491155">drevo</translation>
<translation id="4664250907885839816">Del po »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">llll</translation>
<translation id="8284326494547611709">Napisi</translation>
<translation id="835897206747267392">Neveljavna vrednost.</translation>
+<translation id="8403857369060869934">pretečeni čas: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">del</translation>
<translation id="8433900881053900389">orodna vrstica</translation>
<translation id="8444882422881193423">Število datotek: <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sr.xtb b/chromium/content/app/strings/translations/content_strings_sr.xtb
index 1545c8324a1..54d5d8328e8 100644
--- a/chromium/content/app/strings/translations/content_strings_sr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sr.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">дугме менија</translation>
<translation id="4446524499724042288">референца речника термина</translation>
<translation id="4522570452068850558">Детаљи</translation>
+<translation id="4542388879936266156">преостало време: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">образац</translation>
<translation id="4661075872484491155">стабло</translation>
<translation id="4664250907885839816">Део после „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">гггг</translation>
<translation id="8284326494547611709">Титл</translation>
<translation id="835897206747267392">Неважећа вредност.</translation>
+<translation id="8403857369060869934">протекло време: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">део</translation>
<translation id="8433900881053900389">трака с алаткама</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> датотеке(а)</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sv.xtb b/chromium/content/app/strings/translations/content_strings_sv.xtb
index 04d1828e3c3..c7215b55249 100644
--- a/chromium/content/app/strings/translations/content_strings_sv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sv.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menyknapp</translation>
<translation id="4446524499724042288">hänvisning till ordlista</translation>
<translation id="4522570452068850558">Info</translation>
+<translation id="4542388879936266156">tid som återstår: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">formulär</translation>
<translation id="4661075872484491155">träd</translation>
<translation id="4664250907885839816">En del efter <ph name="ATSIGN" /> får inte innehålla symbolen <ph name="INVALIDCHARACTER" />.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">åååå</translation>
<translation id="8284326494547611709">Textning</translation>
<translation id="835897206747267392">Ogiltigt värde.</translation>
+<translation id="8403857369060869934">tid som gått: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">del</translation>
<translation id="8433900881053900389">verktygsfält</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_sw.xtb b/chromium/content/app/strings/translations/content_strings_sw.xtb
index 4ca647b930b..e7af6aff03f 100644
--- a/chromium/content/app/strings/translations/content_strings_sw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sw.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">kitufe cha menyu</translation>
<translation id="4446524499724042288">marejeleo ya farahasa</translation>
<translation id="4522570452068850558">Maelezo</translation>
+<translation id="4542388879936266156">muda uliosalia: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">fomu</translation>
<translation id="4661075872484491155">mti</translation>
<translation id="4664250907885839816">Sehemu inayofuata '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Manukuu</translation>
<translation id="835897206747267392">Thamani batili.</translation>
+<translation id="8403857369060869934">muda uliopita: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">sehemu</translation>
<translation id="8433900881053900389">upau wa vidhibiti</translation>
<translation id="8444882422881193423">faili <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_ta.xtb b/chromium/content/app/strings/translations/content_strings_ta.xtb
index 6701b515275..e7c94e110c9 100644
--- a/chromium/content/app/strings/translations/content_strings_ta.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ta.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">மெனு பொத்தான்</translation>
<translation id="4446524499724042288">அருஞ்சொல் திரட்டு மேற்கோள்</translation>
<translation id="4522570452068850558">விவரங்கள்</translation>
+<translation id="4542388879936266156">மீதமுள்ள நேரம்: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">படிவம்</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ஐத் தொடரும் பகுதியில், '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">வசனங்கள்</translation>
<translation id="835897206747267392">செல்லாத மதிப்பு.</translation>
+<translation id="8403857369060869934">முடிவடைந்த நேரம்: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">பகுதி</translation>
<translation id="8433900881053900389">கருவிப்பட்டி</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> கோப்புகள்</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_te.xtb b/chromium/content/app/strings/translations/content_strings_te.xtb
index ca634b131ae..5e3f7b9de09 100644
--- a/chromium/content/app/strings/translations/content_strings_te.xtb
+++ b/chromium/content/app/strings/translations/content_strings_te.xtb
@@ -43,7 +43,7 @@
<translation id="2311842470354187719">పేజీ విభజన</translation>
<translation id="2335594187091864976">తేదీ మరియు సమయం ఎంపిక</translation>
<translation id="248395913932153421">రోజు</translation>
-<translation id="2507943997699731163">దయచేసి ఈ ఫీల్డ్‌ని పూర్తి చెయ్యండి.</translation>
+<translation id="2507943997699731163">దయచేసి ఈ ఫీల్డ్‌ను పూర్తి చేయండి.</translation>
<translation id="2508569020611168319">ట్యాబ్ జాబితా</translation>
<translation id="2561842179657104141">మరిన్ని మీడియా నియంత్రణలను చూపు</translation>
<translation id="2572483411312390101">ప్లే చేయి</translation>
@@ -63,7 +63,7 @@
<translation id="2942448076852699108">హైలైట్ చేయబడిన కంటెంట్</translation>
<translation id="3040011195152428237">లింక్</translation>
<translation id="3049748772180311791"><ph name="QUANTITY" /> MB</translation>
-<translation id="3075154866155599887">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. ఫీల్డ్ అసంపూర్ణంగా ఉంది లేదా అందులోని తేదీ చెల్లదు.</translation>
+<translation id="3075154866155599887">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. ఫీల్డ్ అసంపూర్ణంగా ఉంది లేదా ఇందులోని తేదీ చెల్లదు.</translation>
<translation id="3078740164268491126">పట్టిక</translation>
<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">దయచేసి ఒక URLని ఎంటర్ చేయండి.</translation>
@@ -84,7 +84,7 @@
<translation id="3920932319529768807">ముగింపు</translation>
<translation id="3924558731517983934">అప్లికేషన్‌</translation>
<translation id="3944740393230681990">ప్రారంభం</translation>
-<translation id="3960700977367013758">స్క్రోల్ పట్టీ</translation>
+<translation id="3960700977367013758">స్క్రోల్ బార్</translation>
<translation id="4103419683916926126">మిల్లీసెకన్లు</translation>
<translation id="4151657705144244502">గ్రాఫిక్</translation>
<translation id="4193965531860883258">ముందుమాట</translation>
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">మెను బటన్</translation>
<translation id="4446524499724042288">పదకోశ సూచన</translation>
<translation id="4522570452068850558">వివరాలు</translation>
+<translation id="4542388879936266156">మిగిలి ఉన్న సమయం: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">ఫారమ్</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
@@ -161,7 +162,7 @@
<translation id="6709570249143506788">ప్లేబ్యాక్ నాణ్యత బాగాలేదు</translation>
<translation id="6755330956360078551">సాధన చిట్కా</translation>
<translation id="6790428901817661496">ప్లే చేయి</translation>
-<translation id="6820355525329141109">ప్లగిన్‌ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
+<translation id="6820355525329141109">ప్లగ్ఇన్‌‌ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
<translation id="6820615603175220800">వివరణపట్టి సూచన</translation>
<translation id="6843725295806269523">మ్యూట్ చేయి</translation>
<translation id="6885760532393684712">డైరెక్టరీ</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">ఉపశీర్షికలు</translation>
<translation id="835897206747267392">చెల్లని విలువ.</translation>
+<translation id="8403857369060869934">గడిచిన సమయం: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">భాగం</translation>
<translation id="8433900881053900389">సాధన పట్టీ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ఫైళ్ళు</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_th.xtb b/chromium/content/app/strings/translations/content_strings_th.xtb
index 5124b9820c6..d11b930ebea 100644
--- a/chromium/content/app/strings/translations/content_strings_th.xtb
+++ b/chromium/content/app/strings/translations/content_strings_th.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">ปุ่มเมนู</translation>
<translation id="4446524499724042288">ข้อมูลอ้างอิงอภิธานศัพท์</translation>
<translation id="4522570452068850558">รายละเอียด</translation>
+<translation id="4542388879936266156">เวลาที่เหลือ: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">ฟอร์ม</translation>
<translation id="4661075872484491155">แผนผัง</translation>
<translation id="4664250907885839816">ส่วนที่ต่อท้าย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">ปปปป</translation>
<translation id="8284326494547611709">คำบรรยาย</translation>
<translation id="835897206747267392">ค่าไม่ถูกต้อง</translation>
+<translation id="8403857369060869934">เวลาที่ผ่านไป: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">ภาค</translation>
<translation id="8433900881053900389">แถบเครื่องมือ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ไฟล์</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_tr.xtb b/chromium/content/app/strings/translations/content_strings_tr.xtb
index b2245f63d83..5fbb4fc8f29 100644
--- a/chromium/content/app/strings/translations/content_strings_tr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_tr.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">menü düğmesi</translation>
<translation id="4446524499724042288">terimler sözlüğü referansı</translation>
<translation id="4522570452068850558">Ayrıntılar</translation>
+<translation id="4542388879936266156">kalan süre: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">form</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Başında "<ph name="ATSIGN" />" bulunan kısımda "<ph name="INVALIDCHARACTER" />" simgesi bulunmamalıdır.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Altyazılar</translation>
<translation id="835897206747267392">Geçersiz değer.</translation>
+<translation id="8403857369060869934">geçen süre: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">bölüm</translation>
<translation id="8433900881053900389">araç çubuğu</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> dosya</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_uk.xtb b/chromium/content/app/strings/translations/content_strings_uk.xtb
index fa50a669c62..702f177e433 100644
--- a/chromium/content/app/strings/translations/content_strings_uk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_uk.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">кнопка меню</translation>
<translation id="4446524499724042288">посилання на глосарій</translation>
<translation id="4522570452068850558">Деталі</translation>
+<translation id="4542388879936266156">залишилося часу: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">форма</translation>
<translation id="4661075872484491155">дерево</translation>
<translation id="4664250907885839816">Частина після знака "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">рррр</translation>
<translation id="8284326494547611709">Субтитри</translation>
<translation id="835897206747267392">Недійсне значення</translation>
+<translation id="8403857369060869934">минуло часу: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">частина</translation>
<translation id="8433900881053900389">панель інструментів</translation>
<translation id="8444882422881193423">файлів: <ph name="NUMBER_OF_FILES" /></translation>
diff --git a/chromium/content/app/strings/translations/content_strings_vi.xtb b/chromium/content/app/strings/translations/content_strings_vi.xtb
index 48a3a977133..8f99cda416c 100644
--- a/chromium/content/app/strings/translations/content_strings_vi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_vi.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">nút menu</translation>
<translation id="4446524499724042288">tham chiếu bảng thuật ngữ</translation>
<translation id="4522570452068850558">Chi tiết</translation>
+<translation id="4542388879936266156">thời gian còn lại: <ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">biểu mẫu</translation>
<translation id="4661075872484491155">cây</translation>
<translation id="4664250907885839816">Phần đứng sau '<ph name="ATSIGN" />' không được chứa biểu tượng '<ph name="INVALIDCHARACTER" />'.</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405">yyyy</translation>
<translation id="8284326494547611709">Phụ đề</translation>
<translation id="835897206747267392">Giá trị không hợp lệ.</translation>
+<translation id="8403857369060869934">thời gian trôi qua: <ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">phần</translation>
<translation id="8433900881053900389">thanh công cụ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> tệp</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
index 6afd44e47ef..96ef950574f 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">菜单按钮</translation>
<translation id="4446524499724042288">词汇表参考资料</translation>
<translation id="4522570452068850558">详细信息</translation>
+<translation id="4542388879936266156">剩余时间:<ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">表单</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">“<ph name="ATSIGN" />”后面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405"> 年 </translation>
<translation id="8284326494547611709">字幕</translation>
<translation id="835897206747267392">值无效。</translation>
+<translation id="8403857369060869934">已播放时间:<ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">部分</translation>
<translation id="8433900881053900389">工具栏</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> 个文件</translation>
diff --git a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
index 905aecf9818..3debe6d97d2 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
@@ -97,6 +97,7 @@
<translation id="4413860115965805769">選單按鈕</translation>
<translation id="4446524499724042288">詞彙解釋參考資料</translation>
<translation id="4522570452068850558">詳細資訊</translation>
+<translation id="4542388879936266156">剩餘時間:<ph name="REMAINING_TIME" /></translation>
<translation id="4597532268155981612">表單</translation>
<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
@@ -200,6 +201,7 @@
<translation id="8199524924445686405"> 年 </translation>
<translation id="8284326494547611709">字幕</translation>
<translation id="835897206747267392">無效的值。</translation>
+<translation id="8403857369060869934">經過時間:<ph name="ELAPSED_TIME" /></translation>
<translation id="8415319359811155763">分輯</translation>
<translation id="8433900881053900389">工具列</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> 個檔案</translation>
diff --git a/chromium/content/browser/android/content_feature_list.cc b/chromium/content/browser/android/content_feature_list.cc
index 538ef50a446..4d1b275060e 100644
--- a/chromium/content/browser/android/content_feature_list.cc
+++ b/chromium/content/browser/android/content_feature_list.cc
@@ -24,6 +24,7 @@ namespace {
const base::Feature* kFeaturesExposedToJava[] = {
&features::kBackgroundMediaRendererHasModerateBinding,
&kEnhancedSelectionInsertionHandle,
+ &features::kServiceWorkerForegroundPriority,
};
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 81d99cb7f9e..5fd14e79ead 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -178,7 +178,6 @@
#if defined(OS_MACOSX)
#include "base/memory/memory_pressure_monitor_mac.h"
-#include "content/browser/cocoa/system_hotkey_helper_mac.h"
#include "content/browser/mach_broker_mac.h"
#include "content/browser/renderer_host/browser_compositor_view_mac.h"
#include "content/browser/theme_helper_mac.h"
@@ -1461,7 +1460,6 @@ int BrowserMainLoop::BrowserThreadsStarted() {
#if defined(OS_MACOSX)
ThemeHelperMac::GetInstance();
- SystemHotkeyHelperMac::GetInstance()->DeferredLoadSystemHotkeys();
#endif // defined(OS_MACOSX)
responsiveness_watcher_ = new responsiveness::Watcher;
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index fa1fb766fe3..19b747d2f1c 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -15,6 +15,7 @@
#include "base/process/launch.h"
#include "build/build_config.h"
#include "content/public/browser/child_process_launcher_utils.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "services/service_manager/embedder/result_codes.h"
@@ -167,6 +168,14 @@ ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
return ret;
}
+bool ChildProcessLauncherPriority::is_background() const {
+ return !visible && !has_media_stream &&
+ !(should_boost_for_pending_views && boost_for_pending_views) &&
+ !(has_foreground_service_worker &&
+ base::FeatureList::IsEnabled(
+ features::kServiceWorkerForegroundPriority));
+}
+
bool ChildProcessLauncherPriority::operator==(
const ChildProcessLauncherPriority& other) const {
// |should_boost_for_pending_views| is temporary and constant for all
@@ -175,6 +184,7 @@ bool ChildProcessLauncherPriority::operator==(
other.should_boost_for_pending_views);
return visible == other.visible &&
has_media_stream == other.has_media_stream &&
+ has_foreground_service_worker == other.has_foreground_service_worker &&
frame_depth == other.frame_depth &&
intersects_viewport == other.intersects_viewport &&
boost_for_pending_views == other.boost_for_pending_views
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index 415d916da31..f5fff8ff48c 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -58,6 +58,7 @@ static_assert(static_cast<int>(LAUNCH_RESULT_START) >
struct ChildProcessLauncherPriority {
ChildProcessLauncherPriority(bool visible,
bool has_media_stream,
+ bool has_foreground_service_worker,
unsigned int frame_depth,
bool intersects_viewport,
bool boost_for_pending_views,
@@ -69,6 +70,7 @@ struct ChildProcessLauncherPriority {
)
: visible(visible),
has_media_stream(has_media_stream),
+ has_foreground_service_worker(has_foreground_service_worker),
frame_depth(frame_depth),
intersects_viewport(intersects_viewport),
boost_for_pending_views(boost_for_pending_views),
@@ -81,10 +83,7 @@ struct ChildProcessLauncherPriority {
}
// Returns true if the child process is backgrounded.
- bool is_background() const {
- return !visible && !has_media_stream &&
- !(should_boost_for_pending_views && boost_for_pending_views);
- }
+ bool is_background() const;
bool operator==(const ChildProcessLauncherPriority& other) const;
bool operator!=(const ChildProcessLauncherPriority& other) const {
@@ -104,6 +103,11 @@ struct ChildProcessLauncherPriority {
// content.
bool has_media_stream;
+ // |has_foreground_service_worker| is true when the process has a service
+ // worker that may need to service timely events from other, possibly visible,
+ // processes.
+ bool has_foreground_service_worker;
+
// |frame_depth| is the depth of the shallowest frame this process is
// responsible for which has |visible| visibility. It only makes sense to
// compare this property for two ChildProcessLauncherPriority instances with
diff --git a/chromium/content/browser/child_process_launcher_helper_android.cc b/chromium/content/browser/child_process_launcher_helper_android.cc
index 04bfd4acf36..4aa0301d1a6 100644
--- a/chromium/content/browser/child_process_launcher_helper_android.cc
+++ b/chromium/content/browser/child_process_launcher_helper_android.cc
@@ -226,9 +226,9 @@ void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
DCHECK(env);
return Java_ChildProcessLauncherHelperImpl_setPriority(
env, java_peer_, process.Handle(), priority.visible,
- priority.has_media_stream, priority.frame_depth,
- priority.intersects_viewport, priority.boost_for_pending_views,
- static_cast<jint>(priority.importance));
+ priority.has_media_stream, priority.has_foreground_service_worker,
+ priority.frame_depth, priority.intersects_viewport,
+ priority.boost_for_pending_views, static_cast<jint>(priority.importance));
}
// static
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index 0e69ac487ca..79b62092482 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -1170,6 +1170,17 @@ bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
DELETE_FILE_GRANT);
}
+bool ChildProcessSecurityPolicyImpl::CanAccessDataForWebSocket(
+ int child_id,
+ const GURL& url) {
+ DCHECK(url.SchemeIsWSOrWSS());
+ GURL::Replacements replace_scheme;
+ replace_scheme.SetSchemeStr(url.SchemeIs(url::kWssScheme) ? url::kHttpsScheme
+ : url::kHttpScheme);
+ GURL url_to_check = url.ReplaceComponents(replace_scheme);
+ return CanAccessDataForOrigin(child_id, url_to_check);
+}
+
bool ChildProcessSecurityPolicyImpl::HasWebUIBindings(int child_id) {
base::AutoLock lock(lock_);
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index 93af81e6818..811557a3ec2 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -236,6 +236,10 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
bool CanDeleteFileSystemFile(int child_id,
const storage::FileSystemURL& filesystem_url);
+ // True if cookie headers may be exposed to renderer |child_id| for |url| for
+ // display in DevTools. |url| should be a WebSocket URL.
+ bool CanAccessDataForWebSocket(int child_id, const GURL& url);
+
// Returns true if the specified child_id has been granted ReadRawCookies.
bool CanReadRawCookies(int child_id);
diff --git a/chromium/content/browser/cocoa/system_hotkey_helper_mac.h b/chromium/content/browser/cocoa/system_hotkey_helper_mac.h
index 19ecb8889b9..b523430114d 100644
--- a/chromium/content/browser/cocoa/system_hotkey_helper_mac.h
+++ b/chromium/content/browser/cocoa/system_hotkey_helper_mac.h
@@ -5,54 +5,12 @@
#ifndef CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_HELPER_MAC_H_
#define CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_HELPER_MAC_H_
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/memory/weak_ptr.h"
-
-#ifdef __OBJC__
-@class NSDictionary;
-#else
-class NSDictionary;
-#endif
-
namespace content {
class SystemHotkeyMap;
-// This singleton holds a global mapping of hotkeys reserved by OSX.
-class SystemHotkeyHelperMac {
- public:
- // Return pointer to the singleton instance for the current process.
- static SystemHotkeyHelperMac* GetInstance();
-
- // Loads the system hot keys after a brief delay, to reduce file system access
- // immediately after launch.
- void DeferredLoadSystemHotkeys();
-
- // Guaranteed to not be NULL.
- SystemHotkeyMap* map() { return map_.get(); }
-
- private:
- friend struct base::DefaultSingletonTraits<SystemHotkeyHelperMac>;
-
- SystemHotkeyHelperMac();
- ~SystemHotkeyHelperMac();
-
- // Must be called from the FILE thread. Loads the file containing the system
- // hotkeys into a NSDictionary* object, and passes the result to FileDidLoad
- // on the UI thread.
- void LoadSystemHotkeys();
-
- // Must be called from the UI thread. This takes ownership of |dictionary|.
- // Parses the system hotkeys from the plist stored in |dictionary|.
- void FileDidLoad(NSDictionary* dictionary);
-
- std::unique_ptr<SystemHotkeyMap> map_;
-
- DISALLOW_COPY_AND_ASSIGN(SystemHotkeyHelperMac);
-};
+// Guaranteed to not be NULL.
+SystemHotkeyMap* GetSystemHotkeyMap();
} // namespace content
diff --git a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
index 27b8fae73bc..99a4d4d29ac 100644
--- a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
@@ -4,76 +4,37 @@
#include "content/browser/cocoa/system_hotkey_helper_mac.h"
-#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/mac/foundation_util.h"
#include "base/metrics/histogram_macros.h"
-#include "base/task/post_task.h"
-#include "base/task/task_traits.h"
-#include "base/threading/scoped_blocking_call.h"
+#include "base/no_destructor.h"
#include "content/browser/cocoa/system_hotkey_map.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
namespace {
-NSString* kSystemHotkeyPlistExtension =
- @"/Preferences/com.apple.symbolichotkeys.plist";
+constexpr auto* kSystemHotkeyPlistPath =
+ "Preferences/com.apple.symbolichotkeys.plist";
-// Amount of time to delay loading the hotkeys in seconds.
-const int kLoadHotkeysDelaySeconds = 10;
+content::SystemHotkeyMap LoadSystemHotkeyMap() {
+ auto* hotkey_plist_url = base::mac::FilePathToNSURL(
+ base::mac::GetUserLibraryPath().Append(kSystemHotkeyPlistPath));
+ NSDictionary* dictionary =
+ [NSDictionary dictionaryWithContentsOfURL:hotkey_plist_url];
+
+ content::SystemHotkeyMap map;
+ bool success = map.ParseDictionary(dictionary);
+ UMA_HISTOGRAM_BOOLEAN("OSX.SystemHotkeyMap.LoadSuccess", success);
+ return map;
+}
} // namespace
namespace content {
// static
-SystemHotkeyHelperMac* SystemHotkeyHelperMac::GetInstance() {
- return base::Singleton<SystemHotkeyHelperMac>::get();
-}
-
-void SystemHotkeyHelperMac::DeferredLoadSystemHotkeys() {
- base::PostDelayedTaskWithTraits(
- FROM_HERE,
- {base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()},
- base::Bind(&SystemHotkeyHelperMac::LoadSystemHotkeys,
- base::Unretained(this)),
- base::TimeDelta::FromSeconds(kLoadHotkeysDelaySeconds));
-}
-
-SystemHotkeyHelperMac::SystemHotkeyHelperMac() : map_(new SystemHotkeyMap) {
-}
-
-SystemHotkeyHelperMac::~SystemHotkeyHelperMac() {
-}
-
-void SystemHotkeyHelperMac::LoadSystemHotkeys() {
- base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
-
- std::string library_path(base::mac::GetUserLibraryPath().value());
- NSString* expanded_file_path =
- [NSString stringWithFormat:@"%s%@",
- library_path.c_str(),
- kSystemHotkeyPlistExtension];
-
- // Loads the file into memory.
- NSData* data = [NSData dataWithContentsOfFile:expanded_file_path];
- // Intentionally create the object with +1 retain count, as FileDidLoad
- // will destroy the object.
- NSDictionary* dictionary = [SystemHotkeyMap::DictionaryFromData(data) retain];
-
- base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
- base::Bind(&SystemHotkeyHelperMac::FileDidLoad,
- base::Unretained(this), dictionary));
-}
-
-void SystemHotkeyHelperMac::FileDidLoad(NSDictionary* dictionary) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- bool success = map()->ParseDictionary(dictionary);
- UMA_HISTOGRAM_BOOLEAN("OSX.SystemHotkeyMap.LoadSuccess", success);
- [dictionary release];
+SystemHotkeyMap* GetSystemHotkeyMap() {
+ static base::NoDestructor<SystemHotkeyMap> instance(LoadSystemHotkeyMap());
+ return instance.get();
}
} // namespace content
diff --git a/chromium/content/browser/cocoa/system_hotkey_map.h b/chromium/content/browser/cocoa/system_hotkey_map.h
index 1909aa53b88..e40c60edc83 100644
--- a/chromium/content/browser/cocoa/system_hotkey_map.h
+++ b/chromium/content/browser/cocoa/system_hotkey_map.h
@@ -22,12 +22,9 @@ struct SystemHotkey;
class CONTENT_EXPORT SystemHotkeyMap {
public:
SystemHotkeyMap();
+ SystemHotkeyMap(SystemHotkeyMap&&);
~SystemHotkeyMap();
- // Converts the plist stored in |data| into an NSDictionary. Returns nil on
- // error.
- static NSDictionary* DictionaryFromData(NSData* data);
-
// Parses the property list data commonly stored at
// ~/Library/Preferences/com.apple.symbolichotkeys.plist
// Returns false on encountering an irrecoverable error.
diff --git a/chromium/content/browser/cocoa/system_hotkey_map.mm b/chromium/content/browser/cocoa/system_hotkey_map.mm
index 6ee40574420..bf3484da4f3 100644
--- a/chromium/content/browser/cocoa/system_hotkey_map.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_map.mm
@@ -50,28 +50,9 @@ struct SystemHotkey {
#pragma mark - SystemHotkeyMap
-SystemHotkeyMap::SystemHotkeyMap() {
-}
-SystemHotkeyMap::~SystemHotkeyMap() {
-}
-
-NSDictionary* SystemHotkeyMap::DictionaryFromData(NSData* data) {
- if (!data)
- return nil;
-
- NSError* error = nil;
- NSPropertyListFormat format;
- NSDictionary* dictionary =
- [NSPropertyListSerialization propertyListWithData:data
- options:0
- format:&format
- error:&error];
-
- if (![dictionary isKindOfClass:[NSDictionary class]])
- return nil;
-
- return dictionary;
-}
+SystemHotkeyMap::SystemHotkeyMap() = default;
+SystemHotkeyMap::SystemHotkeyMap(SystemHotkeyMap&&) = default;
+SystemHotkeyMap::~SystemHotkeyMap() = default;
bool SystemHotkeyMap::ParseDictionary(NSDictionary* dictionary) {
system_hotkeys_.clear();
diff --git a/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm b/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
index d4b2a798c0c..cbae4c39866 100644
--- a/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
@@ -8,6 +8,7 @@
#import <Cocoa/Cocoa.h>
#include "base/files/file_path.h"
+#import "base/mac/foundation_util.h"
#include "base/mac/scoped_nsobject.h"
#include "base/path_service.h"
#import "content/browser/cocoa/system_hotkey_map.h"
@@ -19,17 +20,15 @@ class SystemHotkeyMapTest : public ::testing::Test {
protected:
SystemHotkeyMapTest() {}
- NSData* DataFromTestFile(const char* file) {
+ NSDictionary* DictionaryFromTestFile(const char* file) {
base::FilePath test_data_dir;
bool result = base::PathService::Get(DIR_TEST_DATA, &test_data_dir);
if (!result)
return nil;
base::FilePath test_path = test_data_dir.AppendASCII(file);
- std::string test_path_string = test_path.AsUTF8Unsafe();
- NSString* file_path =
- [NSString stringWithUTF8String:test_path_string.c_str()];
- return [NSData dataWithContentsOfFile:file_path];
+ return [NSDictionary
+ dictionaryWithContentsOfURL:base::mac::FilePathToNSURL(test_path)];
}
void AddEntryToDictionary(BOOL enabled,
@@ -84,10 +83,8 @@ class SystemHotkeyMapTest : public ::testing::Test {
TEST_F(SystemHotkeyMapTest, Parse) {
// This plist was pulled from a real machine. It is extensively populated,
// and has no missing or incomplete entries.
- NSData* data = DataFromTestFile("mac/mac_system_hotkeys.plist");
- ASSERT_TRUE(data);
-
- NSDictionary* dictionary = SystemHotkeyMap::DictionaryFromData(data);
+ NSDictionary* dictionary =
+ DictionaryFromTestFile("mac/mac_system_hotkeys.plist");
ASSERT_TRUE(dictionary);
SystemHotkeyMap map;
@@ -124,10 +121,8 @@ TEST_F(SystemHotkeyMapTest, ParseNil) {
TEST_F(SystemHotkeyMapTest, ParseMouse) {
// This plist was pulled from a real machine. It has missing entries,
// incomplete entries, and mouse hotkeys.
- NSData* data = DataFromTestFile("mac/mac_system_hotkeys_sparse.plist");
- ASSERT_TRUE(data);
-
- NSDictionary* dictionary = SystemHotkeyMap::DictionaryFromData(data);
+ NSDictionary* dictionary =
+ DictionaryFromTestFile("mac/mac_system_hotkeys_sparse.plist");
ASSERT_TRUE(dictionary);
SystemHotkeyMap map;
diff --git a/chromium/content/browser/contacts/contacts_manager_impl.cc b/chromium/content/browser/contacts/contacts_manager_impl.cc
index 7170bb338f0..f830af86e4a 100644
--- a/chromium/content/browser/contacts/contacts_manager_impl.cc
+++ b/chromium/content/browser/contacts/contacts_manager_impl.cc
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "build/build_config.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#if defined(OS_ANDROID)
@@ -22,6 +23,8 @@ namespace {
std::unique_ptr<ContactsProvider> CreateProvider(
RenderFrameHostImpl* render_frame_host) {
+ if (render_frame_host->GetParent())
+ return nullptr; // This API is only supported on the main frame.
#if defined(OS_ANDROID)
return std::make_unique<ContactsProviderAndroid>(render_frame_host);
#else
diff --git a/chromium/content/browser/contacts/contacts_provider_android.cc b/chromium/content/browser/contacts/contacts_provider_android.cc
index f698edab1fd..4fc2199def5 100644
--- a/chromium/content/browser/contacts/contacts_provider_android.cc
+++ b/chromium/content/browser/contacts/contacts_provider_android.cc
@@ -9,12 +9,15 @@
#include <utility>
#include <vector>
+#include "base/android/jni_string.h"
#include "base/callback.h"
+#include "components/url_formatter/elide_url.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/web_contents.h"
#include "jni/ContactsDialogHost_jni.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "ui/android/window_android.h"
+#include "url/origin.h"
namespace content {
@@ -29,6 +32,10 @@ ContactsProviderAndroid::ContactsProviderAndroid(
if (!web_contents->GetTopLevelNativeWindow())
return;
+ formatted_origin_ = url_formatter::FormatUrlForSecurityDisplay(
+ render_frame_host->GetLastCommittedOrigin().GetURL(),
+ url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
+
dialog_.Reset(Java_ContactsDialogHost_create(
env, web_contents->GetTopLevelNativeWindow()->GetJavaObject(),
reinterpret_cast<intptr_t>(this)));
@@ -54,8 +61,9 @@ void ContactsProviderAndroid::Select(
callback_ = std::move(callback);
JNIEnv* env = base::android::AttachCurrentThread();
- Java_ContactsDialogHost_showDialog(env, dialog_, multiple, include_names,
- include_emails, include_tel);
+ Java_ContactsDialogHost_showDialog(
+ env, dialog_, multiple, include_names, include_emails, include_tel,
+ base::android::ConvertUTF16ToJavaString(env, formatted_origin_));
}
void ContactsProviderAndroid::AddContact(
diff --git a/chromium/content/browser/contacts/contacts_provider_android.h b/chromium/content/browser/contacts/contacts_provider_android.h
index 9276052ba4f..60ed7854c88 100644
--- a/chromium/content/browser/contacts/contacts_provider_android.h
+++ b/chromium/content/browser/contacts/contacts_provider_android.h
@@ -7,6 +7,7 @@
#include "base/android/jni_array.h"
#include "base/android/scoped_java_ref.h"
+#include "base/strings/string16.h"
#include "content/browser/contacts/contacts_provider.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/mojom/contacts/contacts_manager.mojom.h"
@@ -56,6 +57,10 @@ class ContactsProviderAndroid : public ContactsProvider {
// The list of contacts to return.
std::vector<blink::mojom::ContactInfoPtr> contacts_;
+ // The origin that the contacts data will be shared with. Formatted for
+ // display with the scheme omitted.
+ base::string16 formatted_origin_;
+
DISALLOW_COPY_AND_ASSIGN(ContactsProviderAndroid);
};
diff --git a/chromium/content/browser/devtools/devtools_session.cc b/chromium/content/browser/devtools/devtools_session.cc
index f498b0db1ec..debd425dc04 100644
--- a/chromium/content/browser/devtools/devtools_session.cc
+++ b/chromium/content/browser/devtools/devtools_session.cc
@@ -143,6 +143,12 @@ void DevToolsSession::MojoConnectionDestroyed() {
}
bool DevToolsSession::DispatchProtocolMessage(const std::string& message) {
+ if (proxy_delegate_) {
+ // Note: we assume that child sessions are not forwarding.
+ proxy_delegate_->SendMessageToBackend(this, message);
+ return true;
+ }
+
std::unique_ptr<base::DictionaryValue> parsed_message =
base::DictionaryValue::From(base::JSONReader::Read(message));
@@ -154,6 +160,7 @@ bool DevToolsSession::DispatchProtocolMessage(const std::string& message) {
if (it == child_sessions_.end())
return false;
DevToolsSession* session = it->second;
+ DCHECK(!session->proxy_delegate_);
return session->DispatchProtocolMessageInternal(message,
std::move(parsed_message));
}
@@ -166,11 +173,6 @@ bool DevToolsSession::DispatchProtocolMessageInternal(
std::move(runtime_resume_).Run();
}
- if (proxy_delegate_) {
- proxy_delegate_->SendMessageToBackend(this, message);
- return true;
- }
-
DevToolsManagerDelegate* delegate =
DevToolsManager::GetInstance()->delegate();
if (delegate && parsed_message) {
diff --git a/chromium/content/browser/file_url_loader_factory.cc b/chromium/content/browser/file_url_loader_factory.cc
index 61494efeae4..5cc14df0b4a 100644
--- a/chromium/content/browser/file_url_loader_factory.cc
+++ b/chromium/content/browser/file_url_loader_factory.cc
@@ -850,6 +850,7 @@ void CreateFileURLLoader(
network::mojom::URLLoaderRequest loader,
network::mojom::URLLoaderClientPtr client,
std::unique_ptr<FileURLLoaderObserver> observer,
+ bool allow_directory_listing,
scoped_refptr<net::HttpResponseHeaders> extra_response_headers) {
// TODO(crbug.com/924416): Re-evaluate how TaskPriority is set here and in
// other file URL-loading-related code. Some callers require USER_VISIBLE
@@ -859,12 +860,13 @@ void CreateFileURLLoader(
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
task_runner->PostTask(
FROM_HERE,
- base::BindOnce(&FileURLLoader::CreateAndStart, base::FilePath(), request,
- std::move(loader), client.PassInterface(),
- DirectoryLoadingPolicy::kFail,
- FileAccessPolicy::kUnrestricted,
- LinkFollowingPolicy::kDoNotFollow, std::move(observer),
- std::move(extra_response_headers)));
+ base::BindOnce(
+ &FileURLLoader::CreateAndStart, base::FilePath(), request,
+ std::move(loader), client.PassInterface(),
+ allow_directory_listing ? DirectoryLoadingPolicy::kRespondWithListing
+ : DirectoryLoadingPolicy::kFail,
+ FileAccessPolicy::kUnrestricted, LinkFollowingPolicy::kDoNotFollow,
+ std::move(observer), std::move(extra_response_headers)));
}
std::unique_ptr<network::mojom::URLLoaderFactory> CreateFileURLLoaderFactory(
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index a97648ef717..de100cad56f 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -782,6 +782,7 @@ void InterstitialPageImpl::CreateNewWindow(
int32_t main_frame_route_id,
int32_t main_frame_widget_route_id,
const mojom::CreateNewWindowParams& params,
+ bool has_user_gesture,
SessionStorageNamespace* session_storage_namespace) {
NOTREACHED() << "InterstitialPage does not support showing popups.";
}
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index c3c81b842d3..783112ed2d0 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -130,6 +130,7 @@ class CONTENT_EXPORT InterstitialPageImpl : public InterstitialPage,
int32_t main_frame_route_id,
int32_t main_frame_widget_route_id,
const mojom::CreateNewWindowParams& params,
+ bool has_user_gesture,
SessionStorageNamespace* session_storage_namespace) override;
void ShowCreatedWindow(int process_id,
int main_frame_widget_route_id,
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index 744a1d2343f..a28b7c8a394 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -2522,6 +2522,12 @@ void NavigationControllerImpl::FindFramesToNavigate(
ReloadType reload_type,
std::vector<std::unique_ptr<NavigationRequest>>* same_document_loads,
std::vector<std::unique_ptr<NavigationRequest>>* different_document_loads) {
+ // A frame pending deletion is not allowed to navigate anymore. It has been
+ // deleted and the browser already committed to destroying this
+ // RenderFrameHost. See https://crbug.com/930278.
+ if (!frame->current_frame_host()->is_active())
+ return;
+
DCHECK(pending_entry_);
DCHECK_GE(last_committed_entry_index_, 0);
FrameNavigationEntry* new_item = pending_entry_->GetFrameEntry(frame);
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 877c18094e2..177d6106913 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -7631,6 +7631,26 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
controller.GetLastCommittedEntry()->GetVirtualURL());
}
+// Verifies that unsafe redirects to javascript: or other URLs create an error
+// page and don't make a spoof possible. See https://crbug.com/935175.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ UnsafeRedirectCreatesErrorPage) {
+ NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+
+ GURL start_url(embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+
+ // Navigating to URLs with unsafe redirects should create an error page so
+ // that the pending URL is not left in the address bar.
+ GURL redirect_to_unsafe_url(
+ embedded_test_server()->GetURL("/server-redirect?javascript:Hello!"));
+ EXPECT_FALSE(NavigateToURL(shell(), redirect_to_unsafe_url));
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(PAGE_TYPE_ERROR, controller.GetLastCommittedEntry()->GetPageType());
+}
+
// Verifies that redirecting to a blocked URL and going back does not allow a
// URL spoof. See https://crbug.com/777419.
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index 244992176f0..9381de48eaf 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -1149,10 +1149,12 @@ void NavigationHandleImpl::RestartCommitTimeout() {
RenderProcessHost* renderer_host =
GetRenderFrameHost()->GetRenderWidgetHost()->GetProcess();
- render_process_blocked_state_changed_subscription_ =
- renderer_host->RegisterBlockStateChangedCallback(base::BindRepeating(
- &NavigationHandleImpl::RenderProcessBlockedStateChanged,
- base::Unretained(this)));
+ if (!render_process_blocked_state_changed_subscription_) {
+ render_process_blocked_state_changed_subscription_ =
+ renderer_host->RegisterBlockStateChangedCallback(base::BindRepeating(
+ &NavigationHandleImpl::RenderProcessBlockedStateChanged,
+ base::Unretained(this)));
+ }
if (!renderer_host->IsBlocked())
commit_timeout_timer_.Start(
FROM_HERE, g_commit_timeout,
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index 559d0959cbf..bbb2ba40eca 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -897,8 +897,13 @@ void NavigationRequest::OnRequestRedirected(
redirect_info.new_url)) {
DVLOG(1) << "Denied redirect for "
<< redirect_info.new_url.possibly_invalid_spec();
- navigation_handle_->set_net_error_code(net::ERR_UNSAFE_REDIRECT);
- frame_tree_node_->ResetNavigationRequest(false, true);
+ // Show an error page rather than leaving the previous page in place.
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT),
+ false /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
@@ -911,8 +916,13 @@ void NavigationRequest::OnRequestRedirected(
redirect_info.new_url)) {
DVLOG(1) << "Denied unauthorized redirect for "
<< redirect_info.new_url.possibly_invalid_spec();
- navigation_handle_->set_net_error_code(net::ERR_UNSAFE_REDIRECT);
- frame_tree_node_->ResetNavigationRequest(false, true);
+ // Show an error page rather than leaving the previous page in place.
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT),
+ false /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
+ // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
+ // has destroyed the NavigationRequest.
return;
}
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.h b/chromium/content/browser/frame_host/render_frame_host_delegate.h
index b8e79580256..73ea2f77469 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -351,6 +351,7 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
int32_t main_frame_route_id,
int32_t main_frame_widget_route_id,
const mojom::CreateNewWindowParams& params,
+ bool has_user_gesture,
SessionStorageNamespace* session_storage_namespace) {}
// Show a previously created page with the specified disposition and bounds.
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.cc b/chromium/content/browser/frame_host/render_frame_host_impl.cc
index b4a3b637fa6..fcda9392b8a 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -1974,6 +1974,24 @@ void RenderFrameHostImpl::SetLastCommittedOriginForTesting(
SetLastCommittedOrigin(origin);
}
+void RenderFrameHostImpl::SetOriginOfNewFrame(
+ const url::Origin& new_frame_creator) {
+ // This method should only be called for *new* frames, that haven't committed
+ // a navigation yet.
+ DCHECK(!has_committed_any_navigation_);
+ DCHECK(GetLastCommittedOrigin().opaque());
+
+ // Calculate and set |new_frame_origin|.
+ bool new_frame_should_be_sandboxed =
+ blink::WebSandboxFlags::kOrigin ==
+ (frame_tree_node()->active_sandbox_flags() &
+ blink::WebSandboxFlags::kOrigin);
+ url::Origin new_frame_origin = new_frame_should_be_sandboxed
+ ? new_frame_creator.DeriveNewOpaqueOrigin()
+ : new_frame_creator;
+ SetLastCommittedOrigin(new_frame_origin);
+}
+
FrameTreeNode* RenderFrameHostImpl::AddChild(
std::unique_ptr<FrameTreeNode> child,
int process_id,
@@ -1994,8 +2012,12 @@ FrameTreeNode* RenderFrameHostImpl::AddChild(
// in a frame tree should have the same set of proxies.
frame_tree_node_->render_manager()->CreateProxiesForChildFrame(child.get());
- children_.push_back(std::move(child));
+ // When the child is added, it hasn't committed any navigation yet - its
+ // initial empty document should inherit the origin of its parent (the origin
+ // may change after the first commit). See also https://crbug.com/932067.
+ child->current_frame_host()->SetOriginOfNewFrame(GetLastCommittedOrigin());
+ children_.push_back(std::move(child));
return children_.back().get();
}
@@ -2303,16 +2325,15 @@ void RenderFrameHostImpl::DidCommitSameDocumentNavigation(
frame_tree_node()->frame_tree()->root()->current_origin());
ScopedCommitStateResetter commit_state_resetter(this);
- // If we're waiting for an unload ack from this frame and we receive a commit
- // message, then the frame was navigating before it received the unload
- // request. It will either respond to the unload request soon or our timer
- // will expire. Either way, we should ignore this message, because we have
- // already committed to destroying this RenderFrameHost. Note that we
- // intentionally do not ignore commits that happen while the current tab is
- // being closed - see https://crbug.com/805705.
+ // When the frame is pending deletion, the browser is waiting for it to unload
+ // properly. In the meantime, because of race conditions, it might tries to
+ // commit a same-document navigation before unloading. Similarly to what is
+ // done with cross-document navigations, such navigation are ignored. The
+ // browser already committed to destroying this RenderFrameHost.
+ // See https://crbug.com/805705 and https://crbug.com/930132.
// TODO(ahemery): Investigate to see if this can be removed when the
// NavigationClient interface is implemented.
- if (is_waiting_for_swapout_ack_)
+ if (!is_active())
return;
TRACE_EVENT2("navigation",
@@ -3728,10 +3749,11 @@ void RenderFrameHostImpl::CreateNewWindow(
effective_transient_activation_state, params->opener_suppressed,
&no_javascript_access);
+ bool was_consumed = false;
if (can_create_window) {
// Consume activation even w/o User Activation v2, to sync other renderers
// with calling renderer.
- frame_tree_node_->UpdateUserActivationState(
+ was_consumed = frame_tree_node_->UpdateUserActivationState(
blink::UserActivationUpdateType::kConsumeTransientActivation);
}
@@ -3800,9 +3822,13 @@ void RenderFrameHostImpl::CreateNewWindow(
DCHECK(IsRenderFrameLive());
+ bool opened_by_user_activation = params->mimic_user_gesture;
+ if (base::FeatureList::IsEnabled(features::kUserActivationV2))
+ opened_by_user_activation = was_consumed;
+
delegate_->CreateNewWindow(this, render_view_route_id, main_frame_route_id,
main_frame_widget_route_id, *params,
- cloned_namespace.get());
+ opened_by_user_activation, cloned_namespace.get());
if (main_frame_route_id == MSG_ROUTING_NONE) {
// Opener suppressed or Javascript access disabled. Never tell the renderer
@@ -3830,6 +3856,16 @@ void RenderFrameHostImpl::CreateNewWindow(
RenderFrameHostImpl::FromID(GetProcess()->GetID(), main_frame_route_id);
DCHECK(rfh);
+ // When the popup is created, it hasn't committed any navigation yet - its
+ // initial empty document should inherit the origin of its opener (the origin
+ // may change after the first commit). See also https://crbug.com/932067.
+ //
+ // Note that that origin of the new frame might depend on sandbox flags.
+ // Checking sandbox flags of the new frame should be safe at this point,
+ // because the flags should be already inherited by the CreateNewWindow call
+ // above.
+ rfh->SetOriginOfNewFrame(GetLastCommittedOrigin());
+
if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
rfh->waiting_for_init_) {
// Need to check |waiting_for_init_| as some paths inside CreateNewWindow
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.h b/chromium/content/browser/frame_host/render_frame_host_impl.h
index b7e5b4e09dc..62887439c36 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -1350,6 +1350,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Update this frame's last committed origin.
void SetLastCommittedOrigin(const url::Origin& origin);
+ // Set the |last_committed_origin_| of |this| frame, inheriting the origin
+ // from |new_frame_creator| as appropriate (e.g. depending on whether |this|
+ // frame should be sandboxed / should have an opaque origin instead).
+ void SetOriginOfNewFrame(const url::Origin& new_frame_creator);
+
// Called when a navigation commits succesfully to |url|. This will update
// |last_committed_site_url_| with the site URL corresponding to |url|.
// Note that this will recompute the site URL from |url| rather than using
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
index c108626dd91..d435492c4a1 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -2016,4 +2016,226 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
EXPECT_EQ(0, process->get_media_stream_count_for_testing());
}
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ OriginOfFreshFrame_Subframe_NavCancelledByDocWrite) {
+ WebContents* web_contents = shell()->web_contents();
+ NavigationController& controller = web_contents->GetController();
+ GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ EXPECT_EQ(1, controller.GetEntryCount());
+ url::Origin main_origin = url::Origin::Create(main_url);
+
+ // document.open should cancel the cross-origin navigation to '/hung' and the
+ // subframe should remain on the parent/initiator origin.
+ const char kScriptTemplate[] = R"(
+ const frame = document.createElement('iframe');
+ frame.src = $1;
+ document.body.appendChild(frame);
+
+ const html = '<!DOCTYPE html><html><body>Hello world!</body></html>';
+ const doc = frame.contentDocument;
+ doc.open();
+ doc.write(html);
+ doc.close();
+
+ frame.contentWindow.origin;
+ )";
+ GURL cross_site_url(embedded_test_server()->GetURL("bar.com", "/hung"));
+ std::string script = JsReplace(kScriptTemplate, cross_site_url);
+ EXPECT_EQ(main_origin.Serialize(), EvalJs(web_contents, script));
+
+ // The subframe navigation should be cancelled and therefore shouldn't
+ // contribute an extra history entry.
+ EXPECT_EQ(1, controller.GetEntryCount());
+
+ // Browser-side origin should match the renderer-side origin.
+ // See also https://crbug.com/932067.
+ ASSERT_EQ(2u, web_contents->GetAllFrames().size());
+ RenderFrameHost* subframe = web_contents->GetAllFrames()[1];
+ EXPECT_EQ(main_origin, subframe->GetLastCommittedOrigin());
+}
+
+class RenderFrameHostCreatedObserver : public WebContentsObserver {
+ public:
+ explicit RenderFrameHostCreatedObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+ RenderFrameHost* Wait() {
+ if (!new_frame_)
+ run_loop_.Run();
+
+ return new_frame_;
+ }
+
+ private:
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
+ new_frame_ = render_frame_host;
+ run_loop_.Quit();
+ }
+
+ base::RunLoop run_loop_;
+ RenderFrameHost* new_frame_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostCreatedObserver);
+};
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ OriginOfFreshFrame_SandboxedSubframe) {
+ WebContents* web_contents = shell()->web_contents();
+ NavigationController& controller = web_contents->GetController();
+ GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ EXPECT_EQ(1, controller.GetEntryCount());
+ url::Origin main_origin = url::Origin::Create(main_url);
+
+ // Navigate a sandboxed frame to a cross-origin '/hung'.
+ RenderFrameHostCreatedObserver subframe_observer(web_contents);
+ const char kScriptTemplate[] = R"(
+ const frame = document.createElement('iframe');
+ frame.sandbox = 'allow-scripts';
+ frame.src = $1;
+ document.body.appendChild(frame);
+ )";
+ GURL cross_site_url(embedded_test_server()->GetURL("bar.com", "/hung"));
+ std::string script = JsReplace(kScriptTemplate, cross_site_url);
+ EXPECT_TRUE(ExecJs(web_contents, script));
+
+ // Wait for a new subframe, but ignore the frame returned by
+ // |subframe_observer| (it might be the speculative one, not the current one).
+ subframe_observer.Wait();
+ ASSERT_EQ(2u, web_contents->GetAllFrames().size());
+ RenderFrameHost* subframe = web_contents->GetAllFrames()[1];
+
+ // The browser-side origin of the *sandboxed* subframe should be set to an
+ // *opaque* origin (with the parent's origin as the precursor origin).
+ EXPECT_TRUE(subframe->GetLastCommittedOrigin().opaque());
+ EXPECT_EQ(
+ main_origin.GetTupleOrPrecursorTupleIfOpaque(),
+ subframe->GetLastCommittedOrigin().GetTupleOrPrecursorTupleIfOpaque());
+
+ // Note that the test cannot check the renderer-side origin of the frame:
+ // - Scripts cannot be executed before the frame commits,
+ // - The parent cannot document.write into the *sandboxed* frame.
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ OriginOfFreshFrame_Subframe_AboutBlankAndThenDocWrite) {
+ WebContents* web_contents = shell()->web_contents();
+ NavigationController& controller = web_contents->GetController();
+ GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ EXPECT_EQ(1, controller.GetEntryCount());
+ url::Origin main_origin = url::Origin::Create(main_url);
+
+ // Create a new about:blank subframe and document.write into it.
+ TestNavigationObserver load_observer(web_contents);
+ RenderFrameHostCreatedObserver subframe_observer(web_contents);
+ const char kScript[] = R"(
+ const frame = document.createElement('iframe');
+ // Don't set |frame.src| - have the frame commit an initial about:blank.
+ document.body.appendChild(frame);
+
+ const html = '<!DOCTYPE html><html><body>Hello world!</body></html>';
+ const doc = frame.contentDocument;
+ doc.open();
+ doc.write(html);
+ doc.close();
+ )";
+ ExecuteScriptAsync(web_contents, kScript);
+
+ // Wait for the new subframe to be created - this will be still before the
+ // commit of about:blank.
+ RenderFrameHost* subframe = subframe_observer.Wait();
+ EXPECT_EQ(main_origin, subframe->GetLastCommittedOrigin());
+
+ // Wait for the about:blank navigation to finish.
+ load_observer.Wait();
+
+ // The subframe commit to about:blank should not contribute an extra history
+ // entry.
+ EXPECT_EQ(1, controller.GetEntryCount());
+
+ // Browser-side origin should match the renderer-side origin.
+ // See also https://crbug.com/932067.
+ ASSERT_EQ(2u, web_contents->GetAllFrames().size());
+ RenderFrameHost* subframe2 = web_contents->GetAllFrames()[1];
+ EXPECT_EQ(subframe, subframe2); // No swaps are expected.
+ EXPECT_EQ(main_origin, subframe2->GetLastCommittedOrigin());
+ EXPECT_EQ(main_origin.Serialize(), EvalJs(subframe2, "window.origin"));
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ OriginOfFreshFrame_Popup_NavCancelledByDocWrite) {
+ WebContents* web_contents = shell()->web_contents();
+ GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ url::Origin main_origin = url::Origin::Create(main_url);
+
+ // document.open should cancel the cross-origin navigation to '/hung' and the
+ // popup should remain on the initiator origin.
+ WebContentsAddedObserver popup_observer;
+ const char kScriptTemplate[] = R"(
+ var popup = window.open($1, 'popup');
+
+ const html = '<!DOCTYPE html><html><body>Hello world!</body></html>';
+ const doc = popup.document;
+ doc.open();
+ doc.write(html);
+ doc.close();
+
+ popup.origin;
+ )";
+ GURL cross_site_url(embedded_test_server()->GetURL("bar.com", "/hung"));
+ std::string script = JsReplace(kScriptTemplate, cross_site_url);
+ EXPECT_EQ(main_origin.Serialize(), EvalJs(web_contents, script));
+
+ // Browser-side origin should match the renderer-side origin.
+ // See also https://crbug.com/932067.
+ WebContents* popup = popup_observer.GetWebContents();
+ EXPECT_EQ(main_origin, popup->GetMainFrame()->GetLastCommittedOrigin());
+
+ // The popup navigation should be cancelled and therefore shouldn't
+ // contribute an extra history entry.
+ EXPECT_EQ(0, popup->GetController().GetEntryCount());
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+ OriginOfFreshFrame_Popup_AboutBlankAndThenDocWrite) {
+ WebContents* web_contents = shell()->web_contents();
+ GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ ASSERT_TRUE(NavigateToURL(shell(), main_url));
+ url::Origin main_origin = url::Origin::Create(main_url);
+
+ // Create a new about:blank popup and document.write into it.
+ WebContentsAddedObserver popup_observer;
+ TestNavigationObserver load_observer(web_contents);
+ const char kScript[] = R"(
+ // Empty |url| argument means that the popup will commit an initial
+ // about:blank.
+ var popup = window.open('', 'popup');
+
+ const html = '<!DOCTYPE html><html><body>Hello world!</body></html>';
+ const doc = popup.document;
+ doc.open();
+ doc.write(html);
+ doc.close();
+ )";
+ ExecuteScriptAsync(web_contents, kScript);
+
+ // Wait for the new popup to be created (this will be before the popup commits
+ // the initial about:blank page).
+ WebContents* popup = popup_observer.GetWebContents();
+ EXPECT_EQ(main_origin, popup->GetMainFrame()->GetLastCommittedOrigin());
+
+ // A round-trip to the renderer process is an indirect way to wait for
+ // DidCommitProvisionalLoad IPC for the initial about:blank page.
+ // WaitForLoadStop cannot be used, because this commit won't raise
+ // NOTIFICATION_LOAD_STOP.
+ EXPECT_EQ(123, EvalJs(popup, "123"));
+ EXPECT_EQ(main_origin, popup->GetMainFrame()->GetLastCommittedOrigin());
+
+ // The about:blank navigation shouldn't contribute an extra history entry.
+ EXPECT_EQ(0, popup->GetController().GetEntryCount());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.cc b/chromium/content/browser/frame_host/render_frame_host_manager.cc
index dce34d55315..f9f8e5204d1 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -515,9 +515,7 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// See https://crbug.com/926820 and https://crbug.com/927705.
if (!current_frame_host()->is_active()) {
NOTREACHED() << "Navigation in an inactive frame";
- NavigationHandle* handle = request.navigation_handle();
- DEBUG_ALIAS_FOR_GURL(url_from, handle->GetPreviousURL())
- DEBUG_ALIAS_FOR_GURL(url_to, handle->GetURL())
+ DEBUG_ALIAS_FOR_GURL(url, request.common_params().url);
base::debug::DumpWithoutCrashing();
}
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.cc b/chromium/content/browser/frame_host/render_frame_message_filter.cc
index 789c4061262..ec1c286b421 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -620,10 +620,14 @@ void RenderFrameMessageFilter::SetCookie(int32_t render_frame_id,
return;
}
+ // |callback| needs to be fired even if network process crashes as it's for
+ // sync IPC.
net::CookieStore::SetCookiesCallback net_callback =
- base::BindOnce([](SetCookieCallback callback,
- bool success) { std::move(callback).Run(); },
- std::move(callback));
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce([](SetCookieCallback callback,
+ bool success) { std::move(callback).Run(); },
+ std::move(callback)),
+ false);
(*GetCookieManager())
->SetCanonicalCookie(*cookie, url.SchemeIsCryptographic(),
!options.exclude_httponly(),
@@ -689,9 +693,11 @@ void RenderFrameMessageFilter::GetCookies(int render_frame_id,
(*GetCookieManager())
->GetCookieList(
url, options,
- base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
- render_frame_id, url, site_for_cookies,
- std::move(callback)));
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ base::BindOnce(&RenderFrameMessageFilter::CheckPolicyForCookies,
+ this, render_frame_id, url, site_for_cookies,
+ std::move(callback)),
+ net::CookieList()));
}
#if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.cc b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
index f075640df52..a5e18f465f7 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -302,9 +302,15 @@ void RenderFrameProxyHost::OnOpenURL(
GetSiteInstance()->GetBrowserContext(), std::move(blob_url_token));
}
+ RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host();
+
+ // The current_rfh may be pending deletion. In this case, ignore the
+ // navigation, because the frame is going to disappear soon anyway.
+ if (!current_rfh->is_active())
+ return;
+
// Verify that we are in the same BrowsingInstance as the current
// RenderFrameHost.
- RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host();
if (!site_instance_->IsRelatedSiteInstance(current_rfh->GetSiteInstance()))
return;
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index caf9e5fe26d..1c93dfbc345 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -242,7 +242,7 @@ static const char* const kSwitchNames[] = {
#endif
#if defined(USE_OZONE)
switches::kOzonePlatform,
- switches::kDisableExplicitDmaFences,
+ switches::kEnableExplicitDmaFences,
switches::kOzoneDumpFile,
#endif
#if defined(USE_X11)
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index 43c5c265a6c..7951ea25d94 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -8,10 +8,12 @@
#include <limits>
#include <utility>
+#include "base/big_endian.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_byteorder.h"
+#include "build/build_config.h"
// See leveldb_coding_scheme.md for detailed documentation of the coding
// scheme implemented here.
@@ -23,6 +25,14 @@ using blink::IndexedDBKeyPath;
namespace content {
namespace {
+inline uint64_t ByteSwapToBE64(uint64_t x) {
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+ return base::ByteSwap(x);
+#else
+ return x;
+#endif
+}
+
// As most of the IndexedDBKeys and encoded values are short, we
// initialize some std::vectors with a default inline buffer size to reduce
// the memory re-allocations when the std::vectors are appended.
@@ -1005,22 +1015,25 @@ int CompareIndexKeys(const StringPiece& a, const StringPiece& b) {
}
ScopeLockRange GetDatabaseLockRange(int64_t database_id) {
- uint64_t first[1] = {
- base::ByteSwapToLE64(static_cast<uint64_t>(database_id))};
- uint64_t next[1] = {
- base::ByteSwapToLE64(static_cast<uint64_t>(database_id + 1))};
+ // The numbers are transformed into big-endian to make them
+ // bytewise-comparable. Eventually, these lock ranges should just match the
+ // leveldb keys when they are bytewise-comparable.
+ uint64_t first[1] = {ByteSwapToBE64(static_cast<uint64_t>(database_id))};
+ uint64_t next[1] = {ByteSwapToBE64(static_cast<uint64_t>(database_id + 1))};
return {std::string(reinterpret_cast<char*>(&first), sizeof(first)),
std::string(reinterpret_cast<char*>(&next), sizeof(next))};
}
ScopeLockRange GetObjectStoreLockRange(int64_t database_id,
int64_t object_store_id) {
- uint64_t first[2] = {
- base::ByteSwapToLE64(static_cast<uint64_t>(database_id)),
- base::ByteSwapToLE64(static_cast<uint64_t>(object_store_id))};
+ // The numbers are transformed into big-endian to make them
+ // bytewise-comparable. Eventually, these lock ranges should just match the
+ // leveldb keys when they are bytewise-comparable.
+ uint64_t first[2] = {ByteSwapToBE64(static_cast<uint64_t>(database_id)),
+ ByteSwapToBE64(static_cast<uint64_t>(object_store_id))};
uint64_t next[2] = {
- base::ByteSwapToLE64(static_cast<uint64_t>(database_id)),
- base::ByteSwapToLE64(static_cast<uint64_t>(object_store_id + 1))};
+ ByteSwapToBE64(static_cast<uint64_t>(database_id)),
+ ByteSwapToBE64(static_cast<uint64_t>(object_store_id + 1))};
return {std::string(reinterpret_cast<char*>(&first), sizeof(first)),
std::string(reinterpret_cast<char*>(&next), sizeof(next))};
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
index afa5ce76dd6..539d31f59c1 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -112,9 +112,9 @@ const constexpr int kDatabaseRangeLockLevel = 0;
const constexpr int kObjectStoreRangeLockLevel = 1;
const constexpr int kIndexedDBLockLevelCount = 2;
-ScopeLockRange GetDatabaseLockRange(int64_t database_id);
-ScopeLockRange GetObjectStoreLockRange(int64_t database_id,
- int64_t object_store_id);
+CONTENT_EXPORT ScopeLockRange GetDatabaseLockRange(int64_t database_id);
+CONTENT_EXPORT ScopeLockRange GetObjectStoreLockRange(int64_t database_id,
+ int64_t object_store_id);
// TODO(dmurph): Modify all decoding methods to return something more sensible,
// as it is not obvious that they modify the input slice to remove the decoded
diff --git a/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc
index 17eea2e156e..8bebd1591b2 100644
--- a/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc
+++ b/chromium/content/browser/indexed_db/scopes/disjoint_range_lock_manager.cc
@@ -113,7 +113,7 @@ bool DisjointRangeLockManager::AcquireLock(
if (it == level_locks.end()) {
it = level_locks
.emplace(std::piecewise_construct,
- std::forward_as_tuple(request.range),
+ std::forward_as_tuple(std::move(request.range)),
std::forward_as_tuple())
.first;
}
@@ -127,7 +127,7 @@ bool DisjointRangeLockManager::AcquireLock(
lock.lock_mode = request.type;
auto released_callback = base::BindOnce(
&DisjointRangeLockManager::LockReleased, weak_factory_.GetWeakPtr(),
- request.level, request.range);
+ request.level, std::move(request.range));
std::move(acquired_callback)
.Run(ScopeLock(std::move(request.range), request.level,
std::move(released_callback)));
diff --git a/chromium/content/browser/indexed_db/scopes/scope_lock_range.h b/chromium/content/browser/indexed_db/scopes/scope_lock_range.h
index 1e68794aef5..bf276eae02f 100644
--- a/chromium/content/browser/indexed_db/scopes/scope_lock_range.h
+++ b/chromium/content/browser/indexed_db/scopes/scope_lock_range.h
@@ -4,8 +4,9 @@
#ifndef CONTENT_BROWSER_INDEXED_DB_SCOPES_SCOPE_LOCK_RANGE_H_
#define CONTENT_BROWSER_INDEXED_DB_SCOPES_SCOPE_LOCK_RANGE_H_
+#include <stdint.h>
#include <iosfwd>
-#include <string>
+#include <vector>
#include "base/logging.h"
#include "content/common/content_export.h"
@@ -21,6 +22,8 @@ struct CONTENT_EXPORT ScopeLockRange {
~ScopeLockRange() = default;
std::string begin;
std::string end;
+
+ bool IsValid() const { return begin < end; }
};
// Logging support.
diff --git a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h
index 7093b68dbf3..6b336b954e7 100644
--- a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h
+++ b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager.h
@@ -37,11 +37,10 @@ class CONTENT_EXPORT ScopesLockManager {
// Acquires locks for the given requests. Lock levels are treated as
// completely independent domains. The lock levels start at zero.
- // Returns false if any of the lock ranges were invalid or an invarient was
+ // Returns false if any of the lock ranges were invalid or an invariant was
// broken.
struct CONTENT_EXPORT ScopeLockRequest {
ScopeLockRequest(int level, ScopeLockRange range, LockType type);
- ~ScopeLockRequest() = default;
int level;
ScopeLockRange range;
LockType type;
diff --git a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc
index b4d9e42594e..c00ac488ea4 100644
--- a/chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc
+++ b/chromium/content/browser/indexed_db/scopes/scopes_lock_manager_unittest.cc
@@ -8,15 +8,45 @@
#include "base/bind.h"
#include "base/test/bind_test_util.h"
+#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
TEST(ScopesLockManager, TestRangePopulation) {
- ScopeLockRange range{"a", "b"};
- EXPECT_EQ("a", range.begin);
- EXPECT_EQ("b", range.end);
+ ScopeLockRange range = {"1", "2"};
+ EXPECT_EQ("1", range.begin);
+ EXPECT_EQ("2", range.end);
+ EXPECT_TRUE(range.IsValid());
+}
+
+TEST(ScopesLockManager, TestInvalidRange) {
+ ScopeLockRange range = {"2", "1"};
+ EXPECT_FALSE(range.IsValid());
+ range = {"2", "2"};
+ EXPECT_FALSE(range.IsValid());
+}
+
+TEST(ScopesLockManager, TestRangeDifferences) {
+ ScopeLockRange range_db1;
+ ScopeLockRange range_db2;
+ ScopeLockRange range_db1_os1;
+ ScopeLockRange range_db1_os2;
+ for (int64_t i = 0; i < 512; ++i) {
+ range_db1 = GetDatabaseLockRange(i);
+ range_db2 = GetDatabaseLockRange(i + 1);
+ range_db1_os1 = GetObjectStoreLockRange(i, i);
+ range_db1_os2 = GetObjectStoreLockRange(i, i + 1);
+ EXPECT_TRUE(range_db1.IsValid() && range_db2.IsValid() &&
+ range_db1_os1.IsValid() && range_db1_os2.IsValid());
+ EXPECT_LT(range_db1, range_db2);
+ EXPECT_LT(range_db1, range_db1_os1);
+ EXPECT_LT(range_db1, range_db1_os2);
+ EXPECT_LT(range_db1_os1, range_db1_os2);
+ EXPECT_LT(range_db1_os1, range_db2);
+ EXPECT_LT(range_db1_os2, range_db2);
+ }
}
} // namespace
diff --git a/chromium/content/browser/loader/loader_browsertest.cc b/chromium/content/browser/loader/loader_browsertest.cc
index cfe0b988b5a..f249009f172 100644
--- a/chromium/content/browser/loader/loader_browsertest.cc
+++ b/chromium/content/browser/loader/loader_browsertest.cc
@@ -152,6 +152,7 @@ IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SniffHTMLWithNoContentType) {
CheckTitleTest(
net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test0.html"),
"Content Sniffer Test 0");
+ EXPECT_EQ("text/html", shell()->web_contents()->GetContentsMimeType());
}
IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, RespectNoSniffDirective) {
@@ -161,16 +162,18 @@ IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, RespectNoSniffDirective) {
CheckTitleTest(net::URLRequestMockHTTPJob::GetMockUrl("nosniff-test.html"),
"mock.http/nosniff-test.html");
+ EXPECT_EQ("text/plain", shell()->web_contents()->GetContentsMimeType());
}
IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DoNotSniffHTMLFromTextPlain) {
- // Covered by URLLoaderTest.DoNotSniffHTMLFromTextPlain.
+ // Covered by URLLoaderTest.SniffTextPlainDoesNotResultInHTML.
if (base::FeatureList::IsEnabled(network::features::kNetworkService))
return;
CheckTitleTest(
net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test1.html"),
"mock.http/content-sniffer-test1.html");
+ EXPECT_EQ("text/plain", shell()->web_contents()->GetContentsMimeType());
}
IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DoNotSniffHTMLFromImageGIF) {
@@ -181,6 +184,7 @@ IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, DoNotSniffHTMLFromImageGIF) {
CheckTitleTest(
net::URLRequestMockHTTPJob::GetMockUrl("content-sniffer-test2.html"),
"mock.http/content-sniffer-test2.html");
+ EXPECT_EQ("image/gif", shell()->web_contents()->GetContentsMimeType());
}
IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, SniffNoContentTypeNoData) {
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 638d4f646f8..9b49c3f5d7c 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -32,6 +32,7 @@
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_navigation_url_loader_delegate.h"
#include "net/base/load_flags.h"
+#include "net/base/mock_network_change_notifier.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context.h"
@@ -294,6 +295,7 @@ class NavigationURLLoaderImplTest : public testing::Test {
base::test::ScopedFeatureList feature_list_;
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<TestBrowserContext> browser_context_;
+ net::test::MockNetworkChangeNotifier network_change_notifier_;
net::EmbeddedTestServer http_test_server_;
base::Optional<network::ResourceRequest> most_recent_resource_request_;
};
diff --git a/chromium/content/browser/loader/source_stream_to_data_pipe.cc b/chromium/content/browser/loader/source_stream_to_data_pipe.cc
index 569344921a8..c3923e59262 100644
--- a/chromium/content/browser/loader/source_stream_to_data_pipe.cc
+++ b/chromium/content/browser/loader/source_stream_to_data_pipe.cc
@@ -65,16 +65,12 @@ void SourceStreamToDataPipe::ReadMore() {
void SourceStreamToDataPipe::DidRead(int result) {
DCHECK(pending_write_);
- if (result < 0) {
- // An error case.
+ if (result <= 0) {
+ // An error, or end of the stream.
+ pending_write_->Complete(0); // Closes the data pipe.
OnComplete(result);
return;
}
- if (result == 0) {
- pending_write_->Complete(0);
- OnComplete(net::OK);
- return;
- }
dest_ = pending_write_->Complete(result);
pending_write_ = nullptr;
@@ -97,7 +93,7 @@ void SourceStreamToDataPipe::OnComplete(int result) {
// Resets the watchers, pipes and the exchange handler, so that
// we will never be called back.
writable_handle_watcher_.Cancel();
- pending_write_ = nullptr; // Closes the data pipe if this was holding it.
+ pending_write_ = nullptr;
dest_.reset();
std::move(completion_callback_).Run(result);
diff --git a/chromium/content/browser/media/session/media_session_impl.cc b/chromium/content/browser/media/session/media_session_impl.cc
index a83f7a50ea8..25867580366 100644
--- a/chromium/content/browser/media/session/media_session_impl.cc
+++ b/chromium/content/browser/media/session/media_session_impl.cc
@@ -214,6 +214,22 @@ void MediaSessionImpl::NotifyMediaSessionMetadataChange() {
});
}
+void MediaSessionImpl::OnWebContentsFocused(RenderWidgetHost*) {
+ focused_ = true;
+
+#if !defined(OS_ANDROID) && !defined(OS_MACOSX)
+ // If we have just gained focus and we have audio focus we should re-request
+ // system audio focus. This will ensure this media session is towards the top
+ // of the stack if we have multiple sessions active at the same time.
+ if (audio_focus_state_ == State::ACTIVE)
+ RequestSystemAudioFocus(desired_audio_focus_type_);
+#endif
+}
+
+void MediaSessionImpl::OnWebContentsLostFocus(RenderWidgetHost*) {
+ focused_ = false;
+}
+
bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
int player_id,
media::MediaContentType media_content_type) {
@@ -396,7 +412,7 @@ void MediaSessionImpl::Resume(SuspendType suspend_type) {
}
MediaSessionUmaHelper::RecordMediaSessionUserAction(
- MediaSessionUmaHelper::MediaSessionUserAction::PlayDefault);
+ MediaSessionUmaHelper::MediaSessionUserAction::PlayDefault, focused_);
}
// When the resume requests comes from another source than system, audio focus
@@ -432,7 +448,7 @@ void MediaSessionImpl::Suspend(SuspendType suspend_type) {
}
MediaSessionUmaHelper::RecordMediaSessionUserAction(
- MediaSessionUserAction::PauseDefault);
+ MediaSessionUserAction::PauseDefault, focused_);
}
OnSuspendInternal(suspend_type, State::SUSPENDED);
@@ -445,7 +461,7 @@ void MediaSessionImpl::Stop(SuspendType suspend_type) {
if (suspend_type == SuspendType::kUI) {
MediaSessionUmaHelper::RecordMediaSessionUserAction(
- MediaSessionUmaHelper::MediaSessionUserAction::StopDefault);
+ MediaSessionUmaHelper::MediaSessionUserAction::StopDefault, focused_);
}
// TODO(mlamouri): merge the logic between UI and SYSTEM.
@@ -677,6 +693,11 @@ MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
#if defined(OS_ANDROID)
session_android_.reset(new MediaSessionAndroid(this));
#endif // defined(OS_ANDROID)
+
+ if (web_contents && web_contents->GetMainFrame() &&
+ web_contents->GetMainFrame()->GetView()) {
+ focused_ = web_contents->GetMainFrame()->GetView()->HasFocus();
+ }
}
void MediaSessionImpl::Initialize() {
@@ -978,7 +999,7 @@ void MediaSessionImpl::OnMediaSessionActionsChanged(
void MediaSessionImpl::DidReceiveAction(
media_session::mojom::MediaSessionAction action) {
MediaSessionUmaHelper::RecordMediaSessionUserAction(
- MediaSessionActionToUserAction(action));
+ MediaSessionActionToUserAction(action), focused_);
// Pause all players in non-routed frames if the action is PAUSE.
//
diff --git a/chromium/content/browser/media/session/media_session_impl.h b/chromium/content/browser/media/session/media_session_impl.h
index af003f6e23f..84c26918664 100644
--- a/chromium/content/browser/media/session/media_session_impl.h
+++ b/chromium/content/browser/media/session/media_session_impl.h
@@ -136,6 +136,8 @@ class MediaSessionImpl : public MediaSession,
void WebContentsDestroyed() override;
void RenderFrameDeleted(RenderFrameHost* rfh) override;
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
+ void OnWebContentsFocused(RenderWidgetHost*) override;
+ void OnWebContentsLostFocus(RenderWidgetHost*) override;
// MediaSessionService-related methods
@@ -390,6 +392,9 @@ class MediaSessionImpl : public MediaSession,
base::ObserverList<MediaSessionObserver>::Unchecked observers_;
+ // True if the WebContents associated with this MediaSessionImpl is focused.
+ bool focused_ = false;
+
#if defined(OS_ANDROID)
std::unique_ptr<MediaSessionAndroid> session_android_;
#endif // defined(OS_ANDROID)
diff --git a/chromium/content/browser/media/session/media_session_impl_unittest.cc b/chromium/content/browser/media/session/media_session_impl_unittest.cc
index 97596a161ad..87971f07945 100644
--- a/chromium/content/browser/media/session/media_session_impl_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_impl_unittest.cc
@@ -575,6 +575,8 @@ TEST_F(MediaSessionImplTest, WebContentsDestroyed_StopsDucking) {
}
}
+#if defined(OS_MACOSX)
+
TEST_F(MediaSessionImplTest, TabFocusDoesNotCauseAudioFocus) {
MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
SetDelegateForTests(GetMediaSession(), delegate);
@@ -591,6 +593,59 @@ TEST_F(MediaSessionImplTest, TabFocusDoesNotCauseAudioFocus) {
EXPECT_EQ(1, delegate->request_audio_focus_count());
}
+#else // defined(OS_MACOSX)
+
+TEST_F(MediaSessionImplTest, RequestAudioFocus_OnFocus_Active) {
+ MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
+ SetDelegateForTests(GetMediaSession(), delegate);
+
+ {
+ MockMediaSessionMojoObserver observer(*GetMediaSession());
+ RequestAudioFocus(GetMediaSession(), AudioFocusType::kGain);
+ FlushForTesting(GetMediaSession());
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+ }
+
+ EXPECT_EQ(1, delegate->request_audio_focus_count());
+ GetMediaSession()->OnWebContentsFocused(nullptr);
+ EXPECT_EQ(2, delegate->request_audio_focus_count());
+}
+
+TEST_F(MediaSessionImplTest, RequestAudioFocus_OnFocus_Inactive) {
+ MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
+ SetDelegateForTests(GetMediaSession(), delegate);
+ EXPECT_EQ(MediaSessionInfo::SessionState::kInactive,
+ GetState(GetMediaSession()));
+
+ EXPECT_EQ(0, delegate->request_audio_focus_count());
+ GetMediaSession()->OnWebContentsFocused(nullptr);
+ EXPECT_EQ(0, delegate->request_audio_focus_count());
+}
+
+TEST_F(MediaSessionImplTest, RequestAudioFocus_OnFocus_Suspended) {
+ MockAudioFocusDelegate* delegate = new MockAudioFocusDelegate();
+ SetDelegateForTests(GetMediaSession(), delegate);
+
+ {
+ MockMediaSessionMojoObserver observer(*GetMediaSession());
+ RequestAudioFocus(GetMediaSession(), AudioFocusType::kGain);
+ FlushForTesting(GetMediaSession());
+ observer.WaitForState(MediaSessionInfo::SessionState::kActive);
+ }
+
+ {
+ MockMediaSessionMojoObserver observer(*GetMediaSession());
+ GetMediaSession()->Suspend(MediaSession::SuspendType::kSystem);
+ observer.WaitForState(MediaSessionInfo::SessionState::kSuspended);
+ }
+
+ EXPECT_EQ(1, delegate->request_audio_focus_count());
+ GetMediaSession()->OnWebContentsFocused(nullptr);
+ EXPECT_EQ(1, delegate->request_audio_focus_count());
+}
+
+#endif // defined(OS_MACOSX)
+
#endif // !defined(OS_ANDROID)
} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_uma_helper.cc b/chromium/content/browser/media/session/media_session_uma_helper.cc
index d9619173791..2b5359572b9 100644
--- a/chromium/content/browser/media/session/media_session_uma_helper.cc
+++ b/chromium/content/browser/media/session/media_session_uma_helper.cc
@@ -22,8 +22,10 @@ MediaSessionUmaHelper::~MediaSessionUmaHelper()
// static
void MediaSessionUmaHelper::RecordMediaSessionUserAction(
- MediaSessionUserAction action) {
+ MediaSessionUserAction action,
+ bool focused) {
UMA_HISTOGRAM_ENUMERATION("Media.Session.UserAction", action);
+ UMA_HISTOGRAM_BOOLEAN("Media.Session.UserAction.Focus", focused);
}
void MediaSessionUmaHelper::RecordSessionSuspended(
diff --git a/chromium/content/browser/media/session/media_session_uma_helper.h b/chromium/content/browser/media/session/media_session_uma_helper.h
index 4745e78ce45..1b8511ebfd8 100644
--- a/chromium/content/browser/media/session/media_session_uma_helper.h
+++ b/chromium/content/browser/media/session/media_session_uma_helper.h
@@ -48,7 +48,8 @@ class CONTENT_EXPORT MediaSessionUmaHelper {
MediaSessionUmaHelper();
~MediaSessionUmaHelper();
- static void RecordMediaSessionUserAction(MediaSessionUserAction action);
+ static void RecordMediaSessionUserAction(MediaSessionUserAction action,
+ bool focused);
void RecordSessionSuspended(MediaSessionSuspendedSource source) const;
diff --git a/chromium/content/browser/network_service_browsertest.cc b/chromium/content/browser/network_service_browsertest.cc
index 5b23582e8a5..7f32646708f 100644
--- a/chromium/content/browser/network_service_browsertest.cc
+++ b/chromium/content/browser/network_service_browsertest.cc
@@ -28,6 +28,7 @@
#include "net/http/http_response_headers.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/network_service_test.mojom.h"
@@ -300,6 +301,60 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
EXPECT_GT(base::ComputeDirectorySize(GetCacheIndexDirectory()),
directory_size);
}
+
+class NetworkConnectionObserver
+ : public network::NetworkConnectionTracker::NetworkConnectionObserver {
+ public:
+ NetworkConnectionObserver() {
+ content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this);
+ content::GetNetworkConnectionTracker()->GetConnectionType(
+ &last_connection_type_,
+ base::BindOnce(&NetworkConnectionObserver::OnConnectionChanged,
+ base::Unretained(this)));
+ }
+
+ ~NetworkConnectionObserver() override {
+ content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(
+ this);
+ }
+
+ void WaitForConnectionType(network::mojom::ConnectionType type) {
+ type_to_wait_for_ = type;
+ if (last_connection_type_ == type_to_wait_for_)
+ return;
+
+ run_loop_ = std::make_unique<base::RunLoop>();
+ run_loop_->Run();
+ }
+
+ // network::NetworkConnectionTracker::NetworkConnectionObserver:
+ void OnConnectionChanged(network::mojom::ConnectionType type) override {
+ last_connection_type_ = type;
+ if (run_loop_ && type_to_wait_for_ == type)
+ run_loop_->Quit();
+ }
+
+ private:
+ network::mojom::ConnectionType type_to_wait_for_ =
+ network::mojom::ConnectionType::CONNECTION_UNKNOWN;
+ network::mojom::ConnectionType last_connection_type_ =
+ network::mojom::ConnectionType::CONNECTION_UNKNOWN;
+ std::unique_ptr<base::RunLoop> run_loop_;
+};
+
+IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
+ ConnectionTypeChangeSyncedToNetworkProcess) {
+ NetworkConnectionObserver observer;
+ net::NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
+ net::NetworkChangeNotifier::CONNECTION_WIFI);
+ observer.WaitForConnectionType(
+ network::mojom::ConnectionType::CONNECTION_WIFI);
+
+ net::NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
+ net::NetworkChangeNotifier::CONNECTION_ETHERNET);
+ observer.WaitForConnectionType(
+ network::mojom::ConnectionType::CONNECTION_ETHERNET);
+}
#endif
IN_PROC_BROWSER_TEST_F(NetworkServiceBrowserTest,
@@ -363,6 +418,39 @@ IN_PROC_BROWSER_TEST_F(NetworkServiceInProcessBrowserTest, Basic) {
LoadBasicRequest(partition->GetNetworkContext(), test_url));
}
+class NetworkServiceInvalidLogBrowserTest : public ContentBrowserTest {
+ public:
+ NetworkServiceInvalidLogBrowserTest() {
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kNetworkService);
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII(network::switches::kLogNetLog, "/abc/def");
+ }
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ EXPECT_TRUE(embedded_test_server()->Start());
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkServiceInvalidLogBrowserTest);
+};
+
+// Verifies that an invalid --log-net-log flag won't crash the browser.
+IN_PROC_BROWSER_TEST_F(NetworkServiceInvalidLogBrowserTest, Basic) {
+ GURL test_url = embedded_test_server()->GetURL("foo.com", "/echo");
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+ BrowserContext::GetDefaultStoragePartition(
+ shell()->web_contents()->GetBrowserContext()));
+ NavigateToURL(shell(), test_url);
+ ASSERT_EQ(net::OK,
+ LoadBasicRequest(partition->GetNetworkContext(), test_url));
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/network_service_client.cc b/chromium/content/browser/network_service_client.cc
index 6fd435a3b14..207ebdd1551 100644
--- a/chromium/content/browser/network_service_client.cc
+++ b/chromium/content/browser/network_service_client.cc
@@ -442,12 +442,29 @@ NetworkServiceClient::NetworkServiceClient(
memory_pressure_listener_ =
std::make_unique<base::MemoryPressureListener>(base::BindRepeating(
&NetworkServiceClient::OnMemoryPressure, base::Unretained(this)));
+
+#if defined(OS_ANDROID)
+ DCHECK(net::NetworkChangeNotifier::HasNetworkChangeNotifier());
+ GetNetworkService()->GetNetworkChangeManager(
+ mojo::MakeRequest(&network_change_manager_));
+ net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
+ net::NetworkChangeNotifier::AddMaxBandwidthObserver(this);
+ net::NetworkChangeNotifier::AddIPAddressObserver(this);
+ net::NetworkChangeNotifier::AddDNSObserver(this);
+#endif
}
}
NetworkServiceClient::~NetworkServiceClient() {
- if (IsOutOfProcessNetworkService())
+ if (IsOutOfProcessNetworkService()) {
net::CertDatabase::GetInstance()->RemoveObserver(this);
+#if defined(OS_ANDROID)
+ net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
+ net::NetworkChangeNotifier::RemoveMaxBandwidthObserver(this);
+ net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
+ net::NetworkChangeNotifier::RemoveDNSObserver(this);
+#endif
+ }
}
void NetworkServiceClient::OnAuthRequired(
@@ -618,6 +635,62 @@ void NetworkServiceClient::OnApplicationStateChange(
base::android::ApplicationState state) {
GetNetworkService()->OnApplicationStateChange(state);
}
+
+void NetworkServiceClient::OnConnectionTypeChanged(
+ net::NetworkChangeNotifier::ConnectionType type) {
+ network_change_manager_->OnNetworkChanged(
+ false /* dns_changed */, false /* ip_address_changed */,
+ true /* connection_type_changed */, network::mojom::ConnectionType(type),
+ false /* connection_subtype_changed */,
+ network::mojom::ConnectionSubtype(
+ net::NetworkChangeNotifier::GetConnectionSubtype()));
+}
+
+void NetworkServiceClient::OnMaxBandwidthChanged(
+ double max_bandwidth_mbps,
+ net::NetworkChangeNotifier::ConnectionType type) {
+ // The connection subtype change will trigger a max bandwidth change in the
+ // network service notifier.
+ network_change_manager_->OnNetworkChanged(
+ false /* dns_changed */, false /* ip_address_changed */,
+ false /* connection_type_changed */, network::mojom::ConnectionType(type),
+ true /* connection_subtype_changed */,
+ network::mojom::ConnectionSubtype(
+ net::NetworkChangeNotifier::GetConnectionSubtype()));
+}
+
+void NetworkServiceClient::OnIPAddressChanged() {
+ network_change_manager_->OnNetworkChanged(
+ false /* dns_changed */, true /* ip_address_changed */,
+ false /* connection_type_changed */,
+ network::mojom::ConnectionType(
+ net::NetworkChangeNotifier::GetConnectionType()),
+ false /* connection_subtype_changed */,
+ network::mojom::ConnectionSubtype(
+ net::NetworkChangeNotifier::GetConnectionSubtype()));
+}
+
+void NetworkServiceClient::OnDNSChanged() {
+ network_change_manager_->OnNetworkChanged(
+ true /* dns_changed */, false /* ip_address_changed */,
+ false /* connection_type_changed */,
+ network::mojom::ConnectionType(
+ net::NetworkChangeNotifier::GetConnectionType()),
+ false /* connection_subtype_changed */,
+ network::mojom::ConnectionSubtype(
+ net::NetworkChangeNotifier::GetConnectionSubtype()));
+}
+
+void NetworkServiceClient::OnInitialDNSConfigRead() {
+ network_change_manager_->OnNetworkChanged(
+ true /* dns_changed */, false /* ip_address_changed */,
+ false /* connection_type_changed */,
+ network::mojom::ConnectionType(
+ net::NetworkChangeNotifier::GetConnectionType()),
+ false /* connection_subtype_changed */,
+ network::mojom::ConnectionSubtype(
+ net::NetworkChangeNotifier::GetConnectionSubtype()));
+}
#endif
void NetworkServiceClient::OnDataUseUpdate(
diff --git a/chromium/content/browser/network_service_client.h b/chromium/content/browser/network_service_client.h
index 2962736dd4c..6714aefc46d 100644
--- a/chromium/content/browser/network_service_client.h
+++ b/chromium/content/browser/network_service_client.h
@@ -22,6 +22,12 @@ namespace content {
class CONTENT_EXPORT NetworkServiceClient
: public network::mojom::NetworkServiceClient,
+#if defined(OS_ANDROID)
+ public net::NetworkChangeNotifier::ConnectionTypeObserver,
+ public net::NetworkChangeNotifier::MaxBandwidthObserver,
+ public net::NetworkChangeNotifier::IPAddressObserver,
+ public net::NetworkChangeNotifier::DNSObserver,
+#endif
public net::CertDatabase::Observer {
public:
explicit NetworkServiceClient(network::mojom::NetworkServiceClientRequest
@@ -103,6 +109,22 @@ class CONTENT_EXPORT NetworkServiceClient
#if defined(OS_ANDROID)
void OnApplicationStateChange(base::android::ApplicationState state);
+
+ // net::NetworkChangeNotifier::ConnectionTypeObserver implementation:
+ void OnConnectionTypeChanged(
+ net::NetworkChangeNotifier::ConnectionType type) override;
+
+ // net::NetworkChangeNotifier::MaxBandwidthObserver implementation:
+ void OnMaxBandwidthChanged(
+ double max_bandwidth_mbps,
+ net::NetworkChangeNotifier::ConnectionType type) override;
+
+ // net::NetworkChangeNotifier::IPAddressObserver implementation:
+ void OnIPAddressChanged() override;
+
+ // net::NetworkChangeNotifier::DNSObserver implementation:
+ void OnDNSChanged() override;
+ void OnInitialDNSConfigRead() override;
#endif
private:
@@ -113,6 +135,7 @@ class CONTENT_EXPORT NetworkServiceClient
#if defined(OS_ANDROID)
std::unique_ptr<base::android::ApplicationStatusListener>
app_status_listener_;
+ network::mojom::NetworkChangeManagerPtr network_change_manager_;
#endif
DISALLOW_COPY_AND_ASSIGN(NetworkServiceClient);
diff --git a/chromium/content/browser/network_service_instance.cc b/chromium/content/browser/network_service_instance.cc
index bf703662552..f45d1d89974 100644
--- a/chromium/content/browser/network_service_instance.cc
+++ b/chromium/content/browser/network_service_instance.cc
@@ -41,6 +41,18 @@ network::mojom::NetworkServicePtr* g_network_service_ptr = nullptr;
network::NetworkConnectionTracker* g_network_connection_tracker;
network::NetworkService* g_network_service;
+network::mojom::NetworkServiceParamsPtr CreateNetworkServiceParams() {
+ network::mojom::NetworkServiceParamsPtr network_service_params =
+ network::mojom::NetworkServiceParams::New();
+ network_service_params->initial_connection_type =
+ network::mojom::ConnectionType(
+ net::NetworkChangeNotifier::GetConnectionType());
+ network_service_params->initial_connection_subtype =
+ network::mojom::ConnectionSubtype(
+ net::NetworkChangeNotifier::GetConnectionSubtype());
+ return network_service_params;
+}
+
void CreateNetworkServiceOnIO(network::mojom::NetworkServiceRequest request) {
if (g_network_service) {
// GetNetworkServiceImpl() was already called and created the object, so
@@ -112,9 +124,14 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
}
network::mojom::NetworkServiceClientPtr client_ptr;
+ auto client_request = mojo::MakeRequest(&client_ptr);
+ // Call SetClient before creating NetworkServiceClient, as the latter might
+ // make requests to NetworkService that depend on initialization.
+ (*g_network_service_ptr)
+ ->SetClient(std::move(client_ptr), CreateNetworkServiceParams());
+
delete g_client; // In case we're recreating the network service.
- g_client = new NetworkServiceClient(mojo::MakeRequest(&client_ptr));
- (*g_network_service_ptr)->SetClient(std::move(client_ptr));
+ g_client = new NetworkServiceClient(std::move(client_request));
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
@@ -128,14 +145,15 @@ CONTENT_EXPORT network::mojom::NetworkService* GetNetworkServiceFromConnector(
base::File file(log_path, base::File::FLAG_CREATE_ALWAYS |
base::File::FLAG_WRITE);
- LOG_IF(ERROR, !file.IsValid())
- << "Failed opening: " << log_path.value();
-
- // TODO(mmenke): Get capture mode from the command line.
- (*g_network_service_ptr)
- ->StartNetLog(std::move(file),
- network::mojom::NetLogCaptureMode::DEFAULT,
- std::move(client_constants));
+ if (!file.IsValid()) {
+ LOG(ERROR) << "Failed opening: " << log_path.value();
+ } else {
+ // TODO(mmenke): Get capture mode from the command line.
+ (*g_network_service_ptr)
+ ->StartNetLog(std::move(file),
+ network::mojom::NetLogCaptureMode::DEFAULT,
+ std::move(client_constants));
+ }
}
}
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.cc b/chromium/content/browser/renderer_host/render_process_host_impl.cc
index 2841e44002e..04f816a43b8 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -1572,6 +1572,7 @@ RenderProcessHostImpl::RenderProcessHostImpl(
visible_clients_(0),
priority_(!blink::kLaunchingProcessIsBackgrounded,
false /* has_media_stream */,
+ false /* has_foreground_service_worker */,
frame_depth_,
false /* intersects_viewport */,
ShouldBoostPriorityForPendingViews(),
@@ -2786,6 +2787,17 @@ void RenderProcessHostImpl::OnMediaStreamRemoved() {
UpdateProcessPriority();
}
+void RenderProcessHostImpl::OnForegroundServiceWorkerAdded() {
+ foreground_service_worker_count_ += 1;
+ UpdateProcessPriority();
+}
+
+void RenderProcessHostImpl::OnForegroundServiceWorkerRemoved() {
+ DCHECK_GT(foreground_service_worker_count_, 0);
+ foreground_service_worker_count_ -= 1;
+ UpdateProcessPriority();
+}
+
// static
void RenderProcessHostImpl::set_render_process_host_factory_for_testing(
const RenderProcessHostFactory* rph_factory) {
@@ -4445,7 +4457,8 @@ void RenderProcessHostImpl::UpdateProcessPriority() {
const ChildProcessLauncherPriority priority(
visible_clients_ > 0 || base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererBackgrounding),
- media_stream_count_ > 0, frame_depth_, intersects_viewport_,
+ media_stream_count_ > 0, foreground_service_worker_count_ > 0,
+ frame_depth_, intersects_viewport_,
!!pending_views_ /* boost_for_pending_views */,
#if defined(OS_ANDROID)
// Same hack as in RenderProcessHostImpl::RenderProcessHostImpl.
@@ -4490,6 +4503,13 @@ void RenderProcessHostImpl::UpdateProcessPriority() {
if (!run_renderer_in_process()) {
DCHECK(child_process_launcher_.get());
DCHECK(!child_process_launcher_->IsStarting());
+ // Make sure to keep the pid in the trace so we can tell which process is
+ // being modified.
+ TRACE_EVENT2(
+ "renderer_host",
+ "RenderProcessHostImpl::UpdateProcessPriority.SetProcessPriority",
+ "pid", child_process_launcher_->GetProcess().Pid(),
+ "priority_is_background", priority.is_background());
child_process_launcher_->SetProcessPriority(priority_);
}
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.h b/chromium/content/browser/renderer_host/render_process_host_impl.h
index 9cbb089496a..1d6fb2e6592 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -420,6 +420,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
void OnMediaStreamRemoved() override;
int get_media_stream_count_for_testing() const { return media_stream_count_; }
+ void OnForegroundServiceWorkerAdded() override;
+ void OnForegroundServiceWorkerRemoved() override;
+
// Sets the global factory used to create new RenderProcessHosts in unit
// tests. It may be nullptr, in which case the default RenderProcessHost will
// be created (this is the behavior if you don't call this function). The
@@ -895,6 +898,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
// determine if if a process should be backgrounded.
int media_stream_count_ = 0;
+ // Tracks service workers that may need to respond to events from other
+ // processes in a timely manner. Used to determine if a process should
+ // not be backgrounded.
+ int foreground_service_worker_count_ = 0;
+
resource_coordinator::ProcessResourceCoordinator
process_resource_coordinator_;
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
index cffe3954f03..d6a5bfc5164 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -721,7 +721,7 @@ void RenderWidgetHostViewAura::WasOccluded() {
}
bool RenderWidgetHostViewAura::ShouldShowStaleContentOnEviction() {
- return host()->ShouldShowStaleContentOnEviction();
+ return host() && host()->ShouldShowStaleContentOnEviction();
}
gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
index 673c7dacfa3..89939596b25 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_cocoa.mm
@@ -92,9 +92,7 @@ NSString* const kWebContentTouchBarId = @"web-content";
// Whether a keyboard event has been reserved by OSX.
BOOL EventIsReservedBySystem(NSEvent* event) {
- content::SystemHotkeyHelperMac* helper =
- content::SystemHotkeyHelperMac::GetInstance();
- return helper->map()->IsEventReserved(event);
+ return content::GetSystemHotkeyMap()->IsEventReserved(event);
}
// TODO(suzhe): Upstream this function.
@@ -302,6 +300,8 @@ void ExtractUnderlines(NSAttributedString* string,
replacementRange.location += textSelectionOffset_;
[self insertText:selectedResult.replacementString
replacementRange:replacementRange];
+
+ ui::LogTouchBarUMA(ui::TouchBarAction::TEXT_SUGGESTION);
}
- (void)candidateListTouchBarItem:(NSCandidateListTouchBarItem*)anItem
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index a66848077ec..033853b765d 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -32,6 +32,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/renderer_preference_watcher.mojom.h"
#include "ipc/ipc_message.h"
@@ -323,6 +324,21 @@ bool HasSentStartWorker(EmbeddedWorkerInstance::StartingPhase phase) {
return false;
}
+void NotifyForegroundServiceWorkerOnUIThread(bool added, int process_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(
+ base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority));
+
+ RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
+ if (!rph)
+ return;
+
+ if (added)
+ rph->OnForegroundServiceWorkerAdded();
+ else
+ rph->OnForegroundServiceWorkerRemoved();
+}
+
} // namespace
// Created on UI thread and moved to IO thread. Proxies notifications to
@@ -649,7 +665,7 @@ EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
devtools_proxy_.reset();
if (registry_->GetWorker(embedded_worker_id_))
registry_->RemoveWorker(process_id(), embedded_worker_id_);
- process_handle_.reset();
+ ReleaseProcess();
}
void EmbeddedWorkerInstance::Start(mojom::EmbeddedWorkerStartParamsPtr params,
@@ -748,6 +764,7 @@ EmbeddedWorkerInstance::EmbeddedWorkerInstance(
instance_host_binding_(this),
devtools_attached_(false),
network_accessed_for_script_(false),
+ foreground_notified_(false),
weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
@@ -759,6 +776,9 @@ void EmbeddedWorkerInstance::OnProcessAllocated(
DCHECK(!process_handle_);
process_handle_ = std::move(handle);
+
+ UpdateForegroundPriority();
+
start_situation_ = start_situation;
for (auto& observer : listener_list_)
observer.OnProcessAllocated();
@@ -955,6 +975,16 @@ void EmbeddedWorkerInstance::Detach() {
observer.OnDetached(old_status);
}
+void EmbeddedWorkerInstance::UpdateForegroundPriority() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (process_handle_ &&
+ owner_version_->ShouldRequireForegroundPriority(process_id())) {
+ NotifyForegroundServiceWorkerAdded();
+ } else {
+ NotifyForegroundServiceWorkerRemoved();
+ }
+}
+
base::WeakPtr<EmbeddedWorkerInstance> EmbeddedWorkerInstance::AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
@@ -1020,6 +1050,8 @@ void EmbeddedWorkerInstance::ReleaseProcess() {
// Abort an inflight start task.
inflight_start_task_.reset();
+ NotifyForegroundServiceWorkerRemoved();
+
instance_host_binding_.Close();
devtools_proxy_.reset();
process_handle_.reset();
@@ -1101,4 +1133,37 @@ void EmbeddedWorkerInstance::SetNetworkFactoryForTesting(
GetNetworkFactoryCallbackForTest() = create_network_factory_callback;
}
+void EmbeddedWorkerInstance::NotifyForegroundServiceWorkerAdded() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(
+ base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority));
+
+ if (!process_handle_ || foreground_notified_)
+ return;
+
+ foreground_notified_ = true;
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&NotifyForegroundServiceWorkerOnUIThread, true /* added */,
+ process_id()));
+}
+
+void EmbeddedWorkerInstance::NotifyForegroundServiceWorkerRemoved() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(
+ !foreground_notified_ ||
+ base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority));
+
+ if (!process_handle_ || !foreground_notified_)
+ return;
+
+ foreground_notified_ = false;
+
+ base::PostTaskWithTraits(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&NotifyForegroundServiceWorkerOnUIThread,
+ false /* added */, process_id()));
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 63682344b8a..c89de1450b7 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -217,6 +217,11 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// worker.
void Detach();
+ // Examine the current state of the worker in order to determine if it should
+ // require foreground priority or not. This should be called whenever state
+ // changes such that the decision might change.
+ void UpdateForegroundPriority();
+
base::WeakPtr<EmbeddedWorkerInstance> AsWeakPtr();
private:
@@ -294,6 +299,11 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
void OnSetupFailed(StatusCallback callback,
blink::ServiceWorkerStatusCode status);
+ // Called when a foreground service worker is added/removed in a process.
+ // Called on the IO thread and dispatches task to the UI thread.
+ void NotifyForegroundServiceWorkerAdded();
+ void NotifyForegroundServiceWorkerRemoved();
+
base::WeakPtr<ServiceWorkerContextCore> context_;
scoped_refptr<EmbeddedWorkerRegistry> registry_;
ServiceWorkerVersion* owner_version_;
@@ -324,6 +334,10 @@ class CONTENT_EXPORT EmbeddedWorkerInstance
// served from HTTPCache or ServiceWorkerDatabase this value is false.
bool network_accessed_for_script_;
+ // True if the RenderProcessHost has been notified that this is a service
+ // worker requiring foreground priority.
+ bool foreground_notified_;
+
ListenerList listener_list_;
std::unique_ptr<DevToolsProxy> devtools_proxy_;
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index 79422c740bd..36adfd0a45c 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -1192,8 +1192,12 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetPurgeableResourceIds(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ClearPurgeableResourceIds(
const std::set<int64_t>& ids) {
+ Status status = LazyOpen(false);
+ if (IsNewOrNonexistentDatabase(status))
+ return STATUS_OK;
+
leveldb::WriteBatch batch;
- Status status = DeleteResourceIdsInBatch(
+ status = DeleteResourceIdsInBatch(
service_worker_internals::kPurgeableResIdKeyPrefix, ids, &batch);
if (status != STATUS_OK)
return status;
@@ -1203,8 +1207,12 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ClearPurgeableResourceIds(
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::PurgeUncommittedResourceIds(
const std::set<int64_t>& ids) {
+ Status status = LazyOpen(false);
+ if (IsNewOrNonexistentDatabase(status))
+ return STATUS_OK;
+
leveldb::WriteBatch batch;
- Status status = DeleteResourceIdsInBatch(
+ status = DeleteResourceIdsInBatch(
service_worker_internals::kUncommittedResIdKeyPrefix, ids, &batch);
if (status != STATUS_OK)
return status;
diff --git a/chromium/content/browser/service_worker/service_worker_new_script_loader.cc b/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
index fb7748bc5f7..8d825657621 100644
--- a/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
+++ b/chromium/content/browser/service_worker/service_worker_new_script_loader.cc
@@ -151,15 +151,18 @@ void ServiceWorkerNewScriptLoader::ProceedWithResponse() {
void ServiceWorkerNewScriptLoader::SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) {
- network_loader_->SetPriority(priority, intra_priority_value);
+ if (network_loader_)
+ network_loader_->SetPriority(priority, intra_priority_value);
}
void ServiceWorkerNewScriptLoader::PauseReadingBodyFromNet() {
- network_loader_->PauseReadingBodyFromNet();
+ if (network_loader_)
+ network_loader_->PauseReadingBodyFromNet();
}
void ServiceWorkerNewScriptLoader::ResumeReadingBodyFromNet() {
- network_loader_->ResumeReadingBodyFromNet();
+ if (network_loader_)
+ network_loader_->ResumeReadingBodyFromNet();
}
// URLLoaderClient for network loader ------------------------------------------
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index 9f6f4c1d04e..e08d663c03f 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -702,7 +702,11 @@ void ServiceWorkerVersion::AddControllee(
const std::string& uuid = provider_host->client_uuid();
CHECK(!provider_host->client_uuid().empty());
DCHECK(!base::ContainsKey(controllee_map_, uuid));
+
controllee_map_[uuid] = provider_host;
+
+ embedded_worker_->UpdateForegroundPriority();
+
// Keep the worker alive a bit longer right after a new controllee is added.
RestartTick(&idle_time_);
ClearTick(&no_controllees_time_);
@@ -728,6 +732,9 @@ void ServiceWorkerVersion::RemoveControllee(const std::string& client_uuid) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(base::ContainsKey(controllee_map_, client_uuid));
controllee_map_.erase(client_uuid);
+
+ embedded_worker_->UpdateForegroundPriority();
+
// Notify observers asynchronously since this gets called during
// ServiceWorkerProviderHost's destructor, and we don't want observers to do
// work during that.
@@ -2111,4 +2118,39 @@ std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker::PausedState>
ServiceWorkerVersion::TakePausedStateOfChangedScript(const GURL& script_url) {
return std::move(compared_script_info_map_[script_url].paused_state);
}
+
+bool ServiceWorkerVersion::ShouldRequireForegroundPriority(
+ int worker_process_id) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!base::FeatureList::IsEnabled(features::kServiceWorkerForegroundPriority))
+ return false;
+
+ // Currently FetchEvents are the only type of event we need to really process
+ // at foreground priority. If the service worker does not have a FetchEvent
+ // handler then we can always allow it to go to the background.
+ if (fetch_handler_existence_ != FetchHandlerExistence::EXISTS)
+ return false;
+
+ // Keep the service worker at foreground priority if its controlling clients
+ // from a different process. In this situation we are likely to need to
+ // quickly service FetchEvents when the worker's process does not have any
+ // visible windows and would have otherwise been moved to the background.
+ //
+ // Ideally we would check the visibility of all clients as well, but that
+ // would also require triggering additional checks on every visibility
+ // change of all clients. That would add a lot of complexity and its
+ // unclear we need to pay that cost yet. This may get easier once the
+ // service worker code runs on the UI thread directly. (crbug.com/824858)
+ //
+ // For now the requirement for cross-process clients should filter out most
+ // service workers. The impact of foreground service workers is further
+ // limited by the automatic shutdown mechanism.
+ for (const auto& controllee : controllee_map_) {
+ const ServiceWorkerProviderHost* host = controllee.second;
+ if (host->process_id() != worker_process_id)
+ return true;
+ }
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index 3b8282dbc4c..aebb003ea34 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -525,6 +525,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker::PausedState>
TakePausedStateOfChangedScript(const GURL& script_url);
+ // Called by the EmbeddedWorkerInstance to determine if its worker process
+ // should be kept at foreground priority.
+ bool ShouldRequireForegroundPriority(int worker_process_id) const;
+
private:
friend class base::RefCounted<ServiceWorkerVersion>;
friend class EmbeddedWorkerInstanceTest;
diff --git a/chromium/content/browser/service_worker/service_worker_version_unittest.cc b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
index 03b8dd1c932..1a1138c2438 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -13,6 +13,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
@@ -24,6 +25,7 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/common/content_features.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_service.mojom.h"
@@ -167,8 +169,7 @@ class ServiceWorkerVersionTest : public testing::Test {
version_->script_cache_map()->SetResources(records);
version_->SetMainScriptHttpResponseInfo(
EmbeddedWorkerTestHelper::CreateHttpResponseInfo());
- version_->set_fetch_handler_existence(
- ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+ version_->set_fetch_handler_existence(GetFetchHandlerExistence());
// Make the registration findable via storage functions.
base::Optional<blink::ServiceWorkerStatusCode> status;
@@ -223,6 +224,29 @@ class ServiceWorkerVersionTest : public testing::Test {
version_->SetTickClockForTesting(tick_clock);
}
+ virtual ServiceWorkerVersion::FetchHandlerExistence GetFetchHandlerExistence()
+ const {
+ return ServiceWorkerVersion::FetchHandlerExistence::EXISTS;
+ }
+
+ std::unique_ptr<ServiceWorkerProviderHost> ActivateWithControllee(
+ int controllee_process_id = 33) {
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration_->SetActiveVersion(version_);
+ ServiceWorkerRemoteProviderEndpoint remote_endpoint;
+ std::unique_ptr<ServiceWorkerProviderHost> host =
+ CreateProviderHostForWindow(
+ controllee_process_id, 1 /* dummy provider_id */,
+ true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr(),
+ &remote_endpoint);
+ host->UpdateUrls(registration_->scope(), registration_->scope());
+ host->SetControllerRegistration(registration_,
+ false /* notify_controllerchange */);
+ EXPECT_TRUE(version_->HasControllee());
+ EXPECT_TRUE(host->controller());
+ return host;
+ }
+
TestBrowserThreadBundle thread_bundle_;
std::unique_ptr<MessageReceiver> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
@@ -1346,6 +1370,135 @@ TEST_F(ServiceWorkerVersionTest, BadOrigin) {
EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorDisallowed, status.value());
}
+TEST_F(ServiceWorkerVersionTest,
+ ForegroundServiceWorkerCountUpdatedByControllee) {
+ base::test::ScopedFeatureList scoped_list;
+ scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
+
+ // Start the worker before we have a controllee.
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
+ EXPECT_EQ(
+ 0,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+
+ // Add a controllee in a different process from the service worker.
+ auto host = ActivateWithControllee();
+
+ // RenderProcessHost should be notified of foreground worker.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(
+ 1,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+
+ // Remove the controllee.
+ host.reset();
+ EXPECT_FALSE(version_->HasControllee());
+
+ // RenderProcessHost should be notified that there are no foreground workers.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(
+ 0,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+}
+
+TEST_F(ServiceWorkerVersionTest,
+ ForegroundServiceWorkerCountNotUpdatedBySameProcessControllee) {
+ base::test::ScopedFeatureList scoped_list;
+ scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
+
+ // Start the worker before we have a controllee.
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
+ EXPECT_EQ(
+ 0,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+
+ // Add a controllee in the same process as the service worker.
+ auto host = ActivateWithControllee(version_->embedded_worker()->process_id());
+
+ // RenderProcessHost should be notified of foreground worker.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(
+ 0,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+}
+
+TEST_F(ServiceWorkerVersionTest,
+ ForegroundServiceWorkerCountUpdatedByWorkerStatus) {
+ base::test::ScopedFeatureList scoped_list;
+ scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
+
+ // Add a controllee in a different process from the service worker.
+ auto host = ActivateWithControllee();
+
+ // RenderProcessHost should not be notified of foreground worker yet since
+ // there is no worker running.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(
+ 0,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+
+ // Starting the worker should notify the RenderProcessHost of the foreground
+ // worker.
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
+ EXPECT_EQ(
+ 1,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+
+ // Stopping the worker should notify the RenderProcessHost that the foreground
+ // worker has been removed.
+ version_->StopWorker(base::DoNothing());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(
+ 0,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+}
+
+class ServiceWorkerVersionNoFetchHandlerTest : public ServiceWorkerVersionTest {
+ protected:
+ ServiceWorkerVersion::FetchHandlerExistence GetFetchHandlerExistence()
+ const override {
+ return ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST;
+ }
+};
+
+TEST_F(ServiceWorkerVersionNoFetchHandlerTest,
+ ForegroundServiceWorkerCountNotUpdated) {
+ base::test::ScopedFeatureList scoped_list;
+ scoped_list.InitAndEnableFeature(features::kServiceWorkerForegroundPriority);
+
+ // Start the worker before we have a controllee.
+ base::Optional<blink::ServiceWorkerStatusCode> status;
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status.value());
+ EXPECT_EQ(
+ 0,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+
+ // Add a controllee in a different process from the service worker.
+ auto host = ActivateWithControllee();
+
+ // RenderProcessHost should not be notified if the service worker does not
+ // have a FetchEvent handler.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(
+ 0,
+ helper_->mock_render_process_host()->foreground_service_worker_count());
+}
+
TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
base::Optional<blink::ServiceWorkerStatusCode> status;
ServiceWorkerContextCore* context = helper_->context();
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index dfd5ce5ea83..58b8cb40a44 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -655,6 +655,21 @@ class DetachMessageFilter : public BrowserMessageFilter {
DISALLOW_COPY_AND_ASSIGN(DetachMessageFilter);
};
+// Observes navigation start.
+class DidStartNavigationObserver : public WebContentsObserver {
+ public:
+ explicit DidStartNavigationObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+ void DidStartNavigation(NavigationHandle* navigation_handle) override {
+ observed_ = true;
+ }
+ bool observed() { return observed_; }
+
+ private:
+ bool observed_ = false;
+ DISALLOW_COPY_AND_ASSIGN(DidStartNavigationObserver);
+};
+
} // namespace
//
@@ -15090,4 +15105,103 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_TRUE(delete_c.deleted());
}
+// An history navigation from the renderer process is received while the
+// RenderFrameHost is pending deletion.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ HistoryNavigationWhilePendingDeletion) {
+ GURL url_ab(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ GURL url_c(embedded_test_server()->GetURL("c.com", "/title1.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), url_ab));
+ RenderFrameHostImpl* rfh_a = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* rfh_b = rfh_a->child_at(0)->current_frame_host();
+ NavigateFrameToURL(rfh_b->frame_tree_node(), url_c);
+ RenderFrameHostImpl* rfh_c = rfh_a->child_at(0)->current_frame_host();
+
+ // Frame C has a unload handler. The browser process needs to wait before
+ // deleting it.
+ EXPECT_TRUE(ExecJs(rfh_c, "onunload=function(){}"));
+
+ RenderFrameDeletedObserver deleted_observer(rfh_c);
+ TestNavigationManager navigation_observer(web_contents(), url_ab);
+
+ // History navigation on C.
+ ExecuteScriptAsync(rfh_c, "history.back();");
+
+ // Simulate A deleting C.
+ // It starts before receiving the history navigation. The detach ACK is
+ // received after.
+ rfh_c->DetachFromProxy();
+ deleted_observer.WaitUntilDeleted();
+
+ // The NavigationController won't be able to find the subframe to navigate
+ // since it was just detached, so it should fall back to navigating the main
+ // frame
+ navigation_observer.WaitForNavigationFinished();
+ EXPECT_TRUE(navigation_observer.was_successful());
+}
+
+// A same document commit from the renderer process is received while the
+// RenderFrameHost is pending deletion.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SameDocumentCommitWhilePendingDeletion) {
+ GURL url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ RenderFrameHostImpl* rfh_a = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* rfh_b = rfh_a->child_at(0)->current_frame_host();
+
+ // Frame B has a unload handler. The browser process needs to wait before
+ // deleting it.
+ EXPECT_TRUE(ExecJs(rfh_b, "onunload=function(){}"));
+
+ RenderFrameDeletedObserver deleted_observer(rfh_b);
+ DidStartNavigationObserver did_start_navigation_observer(web_contents());
+
+ // Start a same-document navigation on B.
+ ExecuteScriptAsync(rfh_b, "location.href='#fragment'");
+
+ // Simulate A deleting B.
+ // It starts before receiving the same-document navigation. The detach ACK is
+ // received after.
+ rfh_b->DetachFromProxy();
+ deleted_observer.WaitUntilDeleted();
+
+ // The navigation was ignored.
+ EXPECT_FALSE(did_start_navigation_observer.observed());
+}
+
+// One frame navigates using window.open while it is pending deletion. The two
+// frames lives in different processes.
+// See https://crbug.com/932087.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ OpenUrlToRemoteFramePendingDeletion) {
+ GURL url_ab(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ GURL url_c(embedded_test_server()->GetURL("c.com", "/title1.html"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), url_ab));
+ RenderFrameHostImpl* rfh_a = web_contents()->GetMainFrame();
+ RenderFrameHostImpl* rfh_b = rfh_a->child_at(0)->current_frame_host();
+
+ // Frame B has a unload handler. The browser process needs to wait before
+ // deleting it.
+ EXPECT_TRUE(ExecJs(rfh_b, "onunload=function(){}"));
+ RenderFrameDeletedObserver deleted_observer(rfh_b);
+
+ // window.open from A in B to url_c.
+ DidStartNavigationObserver did_start_navigation_observer(web_contents());
+ EXPECT_TRUE(ExecuteScript(rfh_b, "window.name = 'name';"));
+ ExecuteScriptAsync(rfh_a, JsReplace("window.open($1, 'name');", url_c));
+
+ // Simulate A deleting C.
+ // It starts before receiving the navigation. The detach ACK is
+ // received after.
+ rfh_b->DetachFromProxy();
+ deleted_observer.WaitUntilDeleted();
+
+ EXPECT_FALSE(did_start_navigation_observer.observed());
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index bdc3ae99f2b..b0f41edaff5 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -2663,6 +2663,7 @@ void WebContentsImpl::CreateNewWindow(
int32_t main_frame_route_id,
int32_t main_frame_widget_route_id,
const mojom::CreateNewWindowParams& params,
+ bool has_user_gesture,
SessionStorageNamespace* session_storage_namespace) {
// We should have zero valid routing ids, or three valid routing IDs.
DCHECK_EQ((render_view_route_id == MSG_ROUTING_NONE),
@@ -2824,7 +2825,7 @@ void WebContentsImpl::CreateNewWindow(
gfx::Rect initial_rect; // Report an empty initial rect.
delegate_->AddNewContents(this, std::move(owning_contents_impl),
params.disposition, initial_rect,
- params.mimic_user_gesture, &was_blocked);
+ has_user_gesture, &was_blocked);
// The delegate may delete |new_contents_impl| during AddNewContents().
if (!weak_new_contents)
return;
@@ -2838,7 +2839,7 @@ void WebContentsImpl::CreateNewWindow(
load_params->referrer = params.referrer.To<Referrer>();
load_params->transition_type = ui::PAGE_TRANSITION_LINK;
load_params->is_renderer_initiated = true;
- load_params->has_user_gesture = params.mimic_user_gesture;
+ load_params->has_user_gesture = has_user_gesture;
if (delegate_ && !is_guest &&
!delegate_->ShouldResumeRequestsForCreatedWindow()) {
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index 5db7007f550..798e9d4d300 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -568,6 +568,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
int32_t main_frame_route_id,
int32_t main_frame_widget_route_id,
const mojom::CreateNewWindowParams& params,
+ bool has_user_gesture,
SessionStorageNamespace* session_storage_namespace) override;
void ShowCreatedWindow(int process_id,
int main_frame_widget_route_id,
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.mm b/chromium/content/browser/web_contents/web_contents_view_mac.mm
index 7f4308b56a1..2ff03cf86f7 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -561,7 +561,12 @@ void WebContentsViewMac::ViewsHostableAttach(ViewsHostableView::Host* host) {
} else if (factory_host_id != NSViewBridgeFactoryHost::kLocalDirectHostId) {
LOG(ERROR) << "Failed to look up NSViewBridgeFactoryHost!";
}
- ns_view_bridge_local_->SetParentNSView(views_host_->GetNSViewId(), token);
+
+ // TODO(https://crbug.com/933679): WebContentsNSViewBridge::SetParentView
+ // will look up the parent NSView by its id, but this has been observed to
+ // fail in the field, so assume that the caller handles updating the NSView
+ // hierarchy.
+ // ns_view_bridge_local_->SetParentNSView(views_host_->GetNSViewId(), token);
for (auto* rwhv_mac : GetChildViews()) {
rwhv_mac->MigrateNSViewBridge(factory_host, ns_view_id_);
diff --git a/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
index d996c81a4a8..55b5371aaae 100644
--- a/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
+++ b/chromium/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -510,6 +510,27 @@ IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerDownloadBrowserTest,
observer->observed_content_disposition());
}
+IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerDownloadBrowserTest,
+ DataURLDownload) {
+ const GURL sxg_url = GURL("data:application/signed-exchange,");
+ std::unique_ptr<DownloadObserver> observer =
+ std::make_unique<DownloadObserver>(BrowserContext::GetDownloadManager(
+ shell()->web_contents()->GetBrowserContext()));
+
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/empty.html"));
+
+ const std::string load_sxg = base::StringPrintf(
+ "const iframe = document.createElement('iframe');"
+ "iframe.src = '%s';"
+ "document.body.appendChild(iframe);",
+ sxg_url.spec().c_str());
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), load_sxg));
+ observer->WaitUntilDownloadCreated();
+ EXPECT_EQ(sxg_url, observer->observed_url());
+}
+
class SignedExchangeRequestHandlerRealCertVerifierBrowserTest
: public SignedExchangeRequestHandlerBrowserTestBase {
public:
diff --git a/chromium/content/browser/web_package/signed_exchange_utils.cc b/chromium/content/browser/web_package/signed_exchange_utils.cc
index 07653504db9..7b812b301e2 100644
--- a/chromium/content/browser/web_package/signed_exchange_utils.cc
+++ b/chromium/content/browser/web_package/signed_exchange_utils.cc
@@ -103,6 +103,10 @@ bool ShouldHandleAsSignedHTTPExchange(
return false;
if (!SignedExchangeRequestHandler::IsSupportedMimeType(head.mime_type))
return false;
+ // Do not handle responses without HttpResponseHeaders.
+ // (Example: data:application/signed-exchange,)
+ if (!head.headers.get())
+ return false;
if (download_utils::MustDownload(request_url, head.headers.get(),
head.mime_type)) {
return false;
diff --git a/chromium/content/browser/webauth/authenticator_impl.cc b/chromium/content/browser/webauth/authenticator_impl.cc
index 4241adbfae9..da770a5e7c2 100644
--- a/chromium/content/browser/webauth/authenticator_impl.cc
+++ b/chromium/content/browser/webauth/authenticator_impl.cc
@@ -580,10 +580,21 @@ void AuthenticatorImpl::MakeCredential(
blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
MakeCredentialCallback callback) {
if (request_) {
- std::move(callback).Run(blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
- nullptr);
- return;
+ if (OriginIsCryptoTokenExtension(
+ render_frame_host_->GetLastCommittedOrigin())) {
+ // Requests originating from cryptotoken will generally outlive any
+ // navigation events on the tab of the request's sender. Evict pending
+ // requests if cryptotoken sends a new one such that requests from before
+ // a navigation event do not prevent new requests. See
+ // https://crbug.com/935480.
+ Cancel();
+ } else {
+ std::move(callback).Run(
+ blink::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
+ return;
+ }
}
+ DCHECK(!request_);
UpdateRequestDelegate();
if (!request_delegate_) {
@@ -709,10 +720,21 @@ void AuthenticatorImpl::GetAssertion(
blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
GetAssertionCallback callback) {
if (request_) {
- std::move(callback).Run(blink::mojom::AuthenticatorStatus::PENDING_REQUEST,
- nullptr);
- return;
+ if (OriginIsCryptoTokenExtension(
+ render_frame_host_->GetLastCommittedOrigin())) {
+ // Requests originating from cryptotoken will generally outlive any
+ // navigation events on the tab of the request's sender. Evict pending
+ // requests if cryptotoken sends a new one such that requests from before
+ // a navigation event do not prevent new requests. See
+ // https://crbug.com/935480.
+ Cancel();
+ } else {
+ std::move(callback).Run(
+ blink::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
+ return;
+ }
}
+ DCHECK(!request_);
UpdateRequestDelegate();
if (!request_delegate_) {
diff --git a/chromium/content/browser/websockets/websocket_manager.cc b/chromium/content/browser/websockets/websocket_manager.cc
index a825a6d71bd..eebf0d65934 100644
--- a/chromium/content/browser/websockets/websocket_manager.cc
+++ b/chromium/content/browser/websockets/websocket_manager.cc
@@ -82,8 +82,10 @@ class WebSocketManager::Delegate final : public network::WebSocket::Delegate {
}
bool CanReadRawCookies(const GURL& url) override {
- return ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRawCookies(
- manager_->process_id_);
+ ChildProcessSecurityPolicyImpl* impl =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ return impl->CanReadRawCookies(manager_->process_id_) &&
+ impl->CanAccessDataForWebSocket(manager_->process_id_, url);
}
void OnCreateURLRequest(int child_id,
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
index 11de6b9e8ee..0aa429dda77 100644
--- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
+++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -105,11 +105,6 @@ HRESULT DWriteFontCollectionProxy::FindFamilyName(const WCHAR* family_name,
if (!GetFontProxy().FindFamily(name, &family_index)) {
LogFontProxyError(FIND_FAMILY_SEND_FAILED);
- // TODO(https://crbug.com/922403): We're inserting an assertion here to
- // gather crash reports and find more about clients in which this
- // fails. Investigate crash reports resulting from this failure, then
- // remove this assertion.
- CHECK(false);
return E_FAIL;
}
diff --git a/chromium/content/common/throttling_url_loader.cc b/chromium/content/common/throttling_url_loader.cc
index bf88ecaf7eb..6303159af21 100644
--- a/chromium/content/common/throttling_url_loader.cc
+++ b/chromium/content/common/throttling_url_loader.cc
@@ -613,6 +613,31 @@ void ThrottlingURLLoader::OnComplete(
DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
DCHECK(!loader_completed_);
+ // Only dispatch WillOnCompleteWithError() if status is not OK.
+ if (!throttles_.empty() && status.error_code != net::OK) {
+ pending_restart_flags_ = 0;
+ has_pending_restart_ = false;
+ bool deferred = false;
+ for (auto& entry : throttles_) {
+ auto* throttle = entry.throttle.get();
+ bool throttle_deferred = false;
+ throttle->WillOnCompleteWithError(status, &throttle_deferred);
+ if (!HandleThrottleResult(throttle, throttle_deferred, &deferred))
+ return;
+ }
+
+ if (deferred) {
+ deferred_stage_ = DEFERRED_COMPLETE;
+ client_binding_.PauseIncomingMethodCallProcessing();
+ return;
+ }
+
+ if (has_pending_restart_) {
+ RestartWithFlagsNow();
+ return;
+ }
+ }
+
// This is the last expected message. Pipe closure before this is an error
// (see OnClientConnectionError). After this it is expected and should be
// ignored. The owner of |this| is expected to destroy |this| when
@@ -679,6 +704,17 @@ void ThrottlingURLLoader::Resume() {
// Note: |this| may be deleted here.
break;
}
+ case DEFERRED_COMPLETE: {
+ // TODO(eroman): For simplicity we require throttles that defer during
+ // WillOnCompleteWithError() to do a restart. We could support deferring
+ // and choosing not to restart if needed, however the current consumers
+ // don't need that.
+ CHECK(has_pending_restart_);
+
+ RestartWithFlagsNow();
+ // Note: |this| may be deleted here.
+ break;
+ }
default:
NOTREACHED();
break;
diff --git a/chromium/content/common/throttling_url_loader.h b/chromium/content/common/throttling_url_loader.h
index 6255f8fff66..11c806f5011 100644
--- a/chromium/content/common/throttling_url_loader.h
+++ b/chromium/content/common/throttling_url_loader.h
@@ -151,7 +151,8 @@ class CONTENT_EXPORT ThrottlingURLLoader
DEFERRED_START,
DEFERRED_REDIRECT,
DEFERRED_BEFORE_RESPONSE,
- DEFERRED_RESPONSE
+ DEFERRED_RESPONSE,
+ DEFERRED_COMPLETE
};
DeferredStage deferred_stage_ = DEFERRED_NONE;
bool loader_completed_ = false;
diff --git a/chromium/content/public/browser/file_url_loader.h b/chromium/content/public/browser/file_url_loader.h
index 433dc0d26d1..cbf8a725f95 100644
--- a/chromium/content/public/browser/file_url_loader.h
+++ b/chromium/content/public/browser/file_url_loader.h
@@ -53,6 +53,7 @@ CONTENT_EXPORT void CreateFileURLLoader(
network::mojom::URLLoaderRequest loader,
network::mojom::URLLoaderClientPtr client,
std::unique_ptr<FileURLLoaderObserver> observer,
+ bool allow_directory_listing,
scoped_refptr<net::HttpResponseHeaders> extra_response_headers = nullptr);
// Helper to create a FileURLLoaderFactory instance. This exposes the ability
diff --git a/chromium/content/public/browser/render_process_host.h b/chromium/content/public/browser/render_process_host.h
index 0077970df82..771fadd4135 100644
--- a/chromium/content/public/browser/render_process_host.h
+++ b/chromium/content/public/browser/render_process_host.h
@@ -166,6 +166,12 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
virtual void OnMediaStreamAdded() = 0;
virtual void OnMediaStreamRemoved() = 0;
+ // Called when a service worker is executing in the process and may need
+ // to respond to events from other processes in a timely manner. This is
+ // used to determine if the process should be backgrounded or not.
+ virtual void OnForegroundServiceWorkerAdded() = 0;
+ virtual void OnForegroundServiceWorkerRemoved() = 0;
+
// Indicates whether the current RenderProcessHost is exclusively hosting
// guest RenderFrames. Not all guest RenderFrames are created equal. A guest,
// as indicated by BrowserPluginGuest::IsGuest, may coexist with other
diff --git a/chromium/content/public/common/content_features.cc b/chromium/content/public/common/content_features.cc
index 2b74bf36931..163f4055afb 100644
--- a/chromium/content/public/common/content_features.cc
+++ b/chromium/content/public/common/content_features.cc
@@ -387,6 +387,11 @@ const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{
const base::Feature kSecMetadata{"SecMetadata",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Keep processes with service workers controlling clients from other
+// processes at foreground priority. (crbug.com/928904)
+const base::Feature kServiceWorkerForegroundPriority{
+ "ServiceWorkerForegroundPriority", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables long running message dispatch for service workers.
// This is a temporary addition only to be used for the Android Messages
// integration with ChromeOS (http://crbug.com/823256).
diff --git a/chromium/content/public/common/content_features.h b/chromium/content/public/common/content_features.h
index 81e3f56e0aa..f20c4771478 100644
--- a/chromium/content/public/common/content_features.h
+++ b/chromium/content/public/common/content_features.h
@@ -93,6 +93,7 @@ CONTENT_EXPORT extern const base::Feature kScrollAnchorSerialization;
CONTENT_EXPORT extern const base::Feature
kSendBeaconThrowForBlobWithNonSimpleType;
CONTENT_EXPORT extern const base::Feature kSecMetadata;
+CONTENT_EXPORT extern const base::Feature kServiceWorkerForegroundPriority;
CONTENT_EXPORT extern const base::Feature kServiceWorkerLongRunningMessage;
CONTENT_EXPORT extern const base::Feature kServiceWorkerPaymentApps;
CONTENT_EXPORT extern const base::Feature kSharedArrayBuffer;
diff --git a/chromium/content/public/common/url_loader_throttle.cc b/chromium/content/public/common/url_loader_throttle.cc
index 39390acbdc4..1d172cb0fc7 100644
--- a/chromium/content/public/common/url_loader_throttle.cc
+++ b/chromium/content/public/common/url_loader_throttle.cc
@@ -54,6 +54,10 @@ void URLLoaderThrottle::BeforeWillProcessResponse(
const network::ResourceResponseHead& response_head,
bool* defer) {}
+void URLLoaderThrottle::WillOnCompleteWithError(
+ const network::URLLoaderCompletionStatus& status,
+ bool* defer) {}
+
URLLoaderThrottle::URLLoaderThrottle() {}
} // namespace content
diff --git a/chromium/content/public/common/url_loader_throttle.h b/chromium/content/public/common/url_loader_throttle.h
index e58acd2fe6d..7a0c347130d 100644
--- a/chromium/content/public/common/url_loader_throttle.h
+++ b/chromium/content/public/common/url_loader_throttle.h
@@ -156,6 +156,11 @@ class CONTENT_EXPORT URLLoaderThrottle {
const network::ResourceResponseHead& response_head,
bool* defer);
+ // Called if there is a non-OK net::Error in the completion status.
+ virtual void WillOnCompleteWithError(
+ const network::URLLoaderCompletionStatus& status,
+ bool* defer);
+
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
protected:
diff --git a/chromium/content/public/renderer/render_frame.h b/chromium/content/public/renderer/render_frame.h
index 95179687307..59f140736ee 100644
--- a/chromium/content/public/renderer/render_frame.h
+++ b/chromium/content/public/renderer/render_frame.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <memory>
+#include <string>
#include "base/callback_forward.h"
#include "base/single_thread_task_runner.h"
@@ -20,6 +21,7 @@
#include "ppapi/buildflags/buildflags.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/web/web_navigation_policy.h"
@@ -294,6 +296,16 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener,
virtual void SetRenderFrameMediaPlaybackOptions(
const RenderFrameMediaPlaybackOptions& opts) = 0;
+ // Requests that fetches initiated by |initiator_origin| should go through the
+ // provided |url_loader_factory|. This method should be called before
+ // executing scripts in a isolated world - such scripts are typically
+ // associated with a security origin different from the main world (and
+ // therefore fetches from such scripts set |request_initiator| that is
+ // incompatible with |request_initiator_site_lock|.
+ virtual void MarkInitiatorAsRequiringSeparateURLLoaderFactory(
+ const url::Origin& initiator_origin,
+ network::mojom::URLLoaderFactoryPtr url_loader_factory) = 0;
+
protected:
~RenderFrame() override {}
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index cef3cef6d04..218514962f4 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -16,6 +16,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -50,6 +51,7 @@
#include "content/renderer/render_view_impl.h"
#include "crypto/openssl_util.h"
#include "jingle/glue/thread_wrapper.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/base/media_permission.h"
#include "media/media_buildflags.h"
#include "media/video/gpu_video_accelerator_factories.h"
@@ -123,7 +125,8 @@ PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
signaling_thread_(nullptr),
worker_thread_(nullptr),
chrome_signaling_thread_("Chrome_libJingle_Signaling"),
- chrome_worker_thread_("Chrome_libJingle_WorkerThread") {
+ chrome_worker_thread_("Chrome_libJingle_WorkerThread"),
+ weak_factory_(this) {
TryScheduleStunProbeTrial();
}
@@ -200,18 +203,11 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
base::WaitableEvent create_network_manager_event(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
- std::unique_ptr<MdnsResponderAdapter> mdns_responder;
-#if BUILDFLAG(ENABLE_MDNS)
- if (base::FeatureList::IsEnabled(features::kWebRtcHideLocalIpsWithMdns)) {
- mdns_responder = std::make_unique<MdnsResponderAdapter>();
- }
-#endif // BUILDFLAG(ENABLE_MDNS)
chrome_worker_thread_.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&PeerConnectionDependencyFactory::
CreateIpcNetworkManagerOnWorkerThread,
- base::Unretained(this), &create_network_manager_event,
- std::move(mdns_responder)));
+ base::Unretained(this), &create_network_manager_event));
start_worker_event.Wait();
create_network_manager_event.Wait();
@@ -446,12 +442,15 @@ PeerConnectionDependencyFactory::CreatePortAllocator(
std::unique_ptr<rtc::NetworkManager> network_manager;
if (port_config.enable_multiple_routes) {
- FilteringNetworkManager* filtering_network_manager =
- new FilteringNetworkManager(network_manager_.get(), requesting_origin,
- media_permission);
- network_manager.reset(filtering_network_manager);
+ auto callback = media::BindToCurrentLoop(base::BindRepeating(
+ &PeerConnectionDependencyFactory::OnEnumeratePermissionChanged,
+ weak_factory_.GetWeakPtr()));
+ network_manager = std::make_unique<FilteringNetworkManager>(
+ network_manager_.get(), requesting_origin, media_permission,
+ std::move(callback));
} else {
- network_manager.reset(new EmptyNetworkManager(network_manager_.get()));
+ network_manager =
+ std::make_unique<EmptyNetworkManager>(network_manager_.get());
}
auto port_allocator = std::make_unique<P2PPortAllocator>(
p2p_socket_dispatcher_, std::move(network_manager), socket_factory_.get(),
@@ -553,11 +552,10 @@ void PeerConnectionDependencyFactory::StartStunProbeTrialOnWorkerThread(
}
void PeerConnectionDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
- base::WaitableEvent* event,
- std::unique_ptr<MdnsResponderAdapter> mdns_responder) {
+ base::WaitableEvent* event) {
DCHECK(chrome_worker_thread_.task_runner()->BelongsToCurrentThread());
- network_manager_ = std::make_unique<IpcNetworkManager>(
- p2p_socket_dispatcher_.get(), std::move(mdns_responder));
+ network_manager_ =
+ std::make_unique<IpcNetworkManager>(p2p_socket_dispatcher_.get());
event->Signal();
}
@@ -648,4 +646,24 @@ PeerConnectionDependencyFactory::GetReceiverCapabilities(
return nullptr;
}
+void PeerConnectionDependencyFactory::OnEnumeratePermissionChanged(
+ rtc::NetworkManager::EnumerationPermission new_state) {
+#if BUILDFLAG(ENABLE_MDNS)
+ std::unique_ptr<MdnsResponderAdapter> mdns_responder;
+ if (new_state == rtc::NetworkManager::ENUMERATION_BLOCKED &&
+ base::FeatureList::IsEnabled(features::kWebRtcHideLocalIpsWithMdns)) {
+ // Note that MdnsResponderAdapter is created on the main thread to have
+ // access to the connector to the service manager.
+ mdns_responder = std::make_unique<MdnsResponderAdapter>();
+ }
+ // base::Unretained is safe below because |network_manager_| will be destroyed
+ // only after |chrome_work_thread_| stops, which flushes all tasks. See
+ // PeerConnectionDependencyFactory::CleanupPeerConnectionFactory.
+ chrome_worker_thread_.task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&IpcNetworkManager::SetMdnsResponder,
+ base::Unretained(network_manager_.get()),
+ base::Passed(&mdns_responder)));
+#endif // BUILDFLAG(ENABLE_MDNS)
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index 137b36ac7b3..5182cabe9fa 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -9,6 +9,7 @@
#include "base/files/file.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop_current.h"
#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
@@ -42,7 +43,6 @@ namespace content {
class IpcNetworkManager;
class IpcPacketSocketFactory;
-class MdnsResponderAdapter;
class P2PPortAllocator;
class WebRtcAudioDeviceImpl;
@@ -150,12 +150,13 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
void InitializeWorkerThread(rtc::Thread** thread,
base::WaitableEvent* event);
- void CreateIpcNetworkManagerOnWorkerThread(
- base::WaitableEvent* event,
- std::unique_ptr<MdnsResponderAdapter> mdns_responder);
+ void CreateIpcNetworkManagerOnWorkerThread(base::WaitableEvent* event);
void DeleteIpcNetworkManager();
void CleanupPeerConnectionFactory();
+ void OnEnumeratePermissionChanged(
+ rtc::NetworkManager::EnumerationPermission new_state);
+
// network_manager_ must be deleted on the worker thread. The network manager
// uses |p2p_socket_dispatcher_|.
std::unique_ptr<IpcNetworkManager> network_manager_;
@@ -177,6 +178,9 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
SEQUENCE_CHECKER(sequence_checker_);
+ // The weak pointer MUST only be dereferenced on the main thread.
+ base::WeakPtrFactory<PeerConnectionDependencyFactory> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PeerConnectionDependencyFactory);
};
diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
index 25abe6654fb..28736ac7471 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -844,17 +844,16 @@ class RTCPeerConnectionHandler::Observer
handler_->OnRenegotiationNeeded();
}
}
-
- void OnIceConnectionChange(
- PeerConnectionInterface::IceConnectionState new_state) override {}
void OnStandardizedIceConnectionChange(
-
+ PeerConnectionInterface::IceConnectionState new_state) override {}
+ void OnIceConnectionChange(
PeerConnectionInterface::IceConnectionState new_state) override {
if (!main_thread_->BelongsToCurrentThread()) {
main_thread_->PostTask(
- FROM_HERE, base::BindOnce(&RTCPeerConnectionHandler::Observer::
- OnStandardizedIceConnectionChange,
- this, new_state));
+ FROM_HERE,
+ base::BindOnce(
+ &RTCPeerConnectionHandler::Observer::OnIceConnectionChange, this,
+ new_state));
} else if (handler_) {
handler_->OnIceConnectionChange(new_state);
}
diff --git a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
index 62251b627b7..eed9b23c50e 100644
--- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc
@@ -1047,7 +1047,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionNew));
- pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionChecking;
EXPECT_CALL(*mock_tracker_.get(),
@@ -1057,7 +1057,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionChecking));
- pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionConnected;
EXPECT_CALL(*mock_tracker_.get(),
@@ -1067,7 +1067,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionConnected));
- pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionCompleted;
EXPECT_CALL(*mock_tracker_.get(),
@@ -1077,7 +1077,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionCompleted));
- pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionFailed;
EXPECT_CALL(*mock_tracker_.get(),
@@ -1087,7 +1087,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionFailed));
- pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
EXPECT_CALL(*mock_tracker_.get(),
@@ -1097,7 +1097,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionDisconnected));
- pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionClosed;
EXPECT_CALL(*mock_tracker_.get(),
@@ -1107,7 +1107,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
EXPECT_CALL(*mock_client_.get(),
DidChangeIceConnectionState(
webrtc::PeerConnectionInterface::kIceConnectionClosed));
- pc_handler_->observer()->OnStandardizedIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
}
TEST_F(RTCPeerConnectionHandlerTest, OnIceGatheringChange) {
diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
index 1dc4927c824..57f11a0c8f5 100644
--- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
@@ -226,7 +226,6 @@ int32_t RTCVideoDecoderAdapter::Decode(
DVLOG(2) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(decoding_thread_checker_);
-#if defined(OS_WIN)
// Hardware VP9 decoders don't handle more than one spatial layer. Fall back
// to software decoding. See https://crbug.com/webrtc/9304.
if (codec_specific_info &&
@@ -235,7 +234,6 @@ int32_t RTCVideoDecoderAdapter::Decode(
codec_specific_info->codecSpecific.VP9.num_spatial_layers > 1) {
return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
}
-#endif // defined(OS_WIN)
if (missing_frames || !input_image._completeFrame) {
DVLOG(2) << "Missing or incomplete frames";
diff --git a/chromium/content/renderer/p2p/filtering_network_manager.cc b/chromium/content/renderer/p2p/filtering_network_manager.cc
index 66fb08a32c0..d09315da98b 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager.cc
+++ b/chromium/content/renderer/p2p/filtering_network_manager.cc
@@ -17,18 +17,20 @@ namespace content {
FilteringNetworkManager::FilteringNetworkManager(
rtc::NetworkManager* network_manager,
const GURL& requesting_origin,
- media::MediaPermission* media_permission)
+ media::MediaPermission* media_permission,
+ OnEnumerationPermissionCallback callback)
: network_manager_(network_manager),
media_permission_(media_permission),
requesting_origin_(requesting_origin),
+ on_enumeration_permission_cb_(std::move(callback)),
weak_ptr_factory_(this) {
thread_checker_.DetachFromThread();
- set_enumeration_permission(ENUMERATION_BLOCKED);
+ SetEnumerationPermissionAndNotify(ENUMERATION_BLOCKED);
// If the feature is not enabled, just return ALLOWED as it's requested.
if (!media_permission_) {
started_permission_check_ = true;
- set_enumeration_permission(ENUMERATION_ALLOWED);
+ SetEnumerationPermissionAndNotify(ENUMERATION_ALLOWED);
VLOG(3) << "media_permission is not passed, granting permission";
return;
}
@@ -123,7 +125,7 @@ void FilteringNetworkManager::OnPermissionStatus(bool granted) {
--pending_permission_checks_;
if (granted)
- set_enumeration_permission(ENUMERATION_ALLOWED);
+ SetEnumerationPermissionAndNotify(ENUMERATION_ALLOWED);
// If the IP permission status changed *and* we have an up-to-date network
// list, fire a network change event.
@@ -131,6 +133,16 @@ void FilteringNetworkManager::OnPermissionStatus(bool granted) {
FireEventIfStarted();
}
+void FilteringNetworkManager::SetEnumerationPermissionAndNotify(
+ EnumerationPermission state) {
+ EnumerationPermission old_state = enumeration_permission();
+ if (state != old_state) {
+ set_enumeration_permission(state);
+ if (on_enumeration_permission_cb_)
+ on_enumeration_permission_cb_.Run(state);
+ }
+}
+
void FilteringNetworkManager::OnNetworksChanged() {
DCHECK(thread_checker_.CalledOnValidThread());
pending_network_update_ = false;
diff --git a/chromium/content/renderer/p2p/filtering_network_manager.h b/chromium/content/renderer/p2p/filtering_network_manager.h
index 7d3b292ce16..47a9f6a9b54 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager.h
+++ b/chromium/content/renderer/p2p/filtering_network_manager.h
@@ -5,8 +5,10 @@
#ifndef CONTENT_RENDERER_P2P_FILTERING_NETWORK_MANAGER_H_
#define CONTENT_RENDERER_P2P_FILTERING_NETWORK_MANAGER_H_
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
@@ -37,12 +39,17 @@ namespace content {
class FilteringNetworkManager : public rtc::NetworkManagerBase,
public sigslot::has_slots<> {
public:
+ // A callback that will be executed when |enumeration_permission_| changes.
+ using OnEnumerationPermissionCallback =
+ base::RepeatingCallback<void(EnumerationPermission)>;
+
// This class is created by WebRTC's signaling thread but used by WebRTC's
// worker thread |task_runner|.
CONTENT_EXPORT FilteringNetworkManager(
rtc::NetworkManager* network_manager,
const GURL& requesting_origin,
- media::MediaPermission* media_permission);
+ media::MediaPermission* media_permission,
+ OnEnumerationPermissionCallback callback);
CONTENT_EXPORT ~FilteringNetworkManager() override;
@@ -64,6 +71,8 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
// available.
void OnPermissionStatus(bool granted);
+ void SetEnumerationPermissionAndNotify(EnumerationPermission state);
+
base::WeakPtr<FilteringNetworkManager> GetWeakPtr();
// Receive callback from the wrapped NetworkManager when the underneath
@@ -117,6 +126,8 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
GURL requesting_origin_;
+ OnEnumerationPermissionCallback on_enumeration_permission_cb_;
+
base::WeakPtrFactory<FilteringNetworkManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(FilteringNetworkManager);
diff --git a/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc b/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
index 87295ec00de..1a4c4247664 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
+++ b/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
@@ -9,6 +9,7 @@
#include <memory>
#include <utility>
+#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
@@ -137,7 +138,8 @@ class FilteringNetworkManagerTest : public testing::Test,
if (multiple_routes_requested) {
FilteringNetworkManager* filtering_network_manager =
new FilteringNetworkManager(mock_network_manager_.get(), GURL(),
- media_permission_.get());
+ media_permission_.get(),
+ base::DoNothing());
filtering_network_manager->Initialize();
network_manager_.reset(filtering_network_manager);
} else {
diff --git a/chromium/content/renderer/p2p/ipc_network_manager.cc b/chromium/content/renderer/p2p/ipc_network_manager.cc
index 4e6b5fb4297..987aa861874 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager.cc
+++ b/chromium/content/renderer/p2p/ipc_network_manager.cc
@@ -7,16 +7,19 @@
#include <string>
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/sys_byteorder.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "jingle/glue/utils.h"
#include "net/base/ip_address.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
+#include "net/net_buildflags.h"
#include "third_party/webrtc/rtc_base/socket_address.h"
namespace content {
@@ -43,12 +46,8 @@ rtc::AdapterType ConvertConnectionTypeToAdapterType(
} // namespace
-IpcNetworkManager::IpcNetworkManager(
- NetworkListManager* network_list_manager,
- std::unique_ptr<MdnsResponderAdapter> mdns_responder)
- : network_list_manager_(network_list_manager),
- mdns_responder_(std::move(mdns_responder)),
- weak_factory_(this) {
+IpcNetworkManager::IpcNetworkManager(NetworkListManager* network_list_manager)
+ : network_list_manager_(network_list_manager), weak_factory_(this) {
network_list_manager_->AddNetworkListObserver(this);
}
@@ -110,6 +109,7 @@ void IpcNetworkManager::OnNetworkListChanged(
std::unique_ptr<rtc::Network> network(new rtc::Network(
it->name, it->name, prefix, it->prefix_length, adapter_type));
network->set_default_local_address_provider(this);
+ network->set_mdns_responder_provider(this);
rtc::InterfaceAddress iface_addr;
if (it->address.IsIPv4()) {
@@ -153,6 +153,7 @@ void IpcNetworkManager::OnNetworkListChanged(
rtc::Network* network_v4 = new rtc::Network(
name_v4, name_v4, ip_address_v4, 32, rtc::ADAPTER_TYPE_UNKNOWN);
network_v4->set_default_local_address_provider(this);
+ network_v4->set_mdns_responder_provider(this);
network_v4->AddIP(ip_address_v4);
networks.push_back(network_v4);
@@ -167,6 +168,7 @@ void IpcNetworkManager::OnNetworkListChanged(
rtc::Network* network_v6 = new rtc::Network(
name_v6, name_v6, ip_address_v6, 64, rtc::ADAPTER_TYPE_UNKNOWN);
network_v6->set_default_local_address_provider(this);
+ network_v6->set_mdns_responder_provider(this);
network_v6->AddIP(ip_address_v6);
networks.push_back(network_v6);
}
@@ -185,6 +187,11 @@ void IpcNetworkManager::OnNetworkListChanged(
stats.ipv6_network_count);
}
+void IpcNetworkManager::SetMdnsResponder(
+ std::unique_ptr<MdnsResponderAdapter> mdns_responder) {
+ mdns_responder_ = std::move(mdns_responder);
+}
+
webrtc::MdnsResponderInterface* IpcNetworkManager::GetMdnsResponder() const {
return mdns_responder_.get();
}
diff --git a/chromium/content/renderer/p2p/ipc_network_manager.h b/chromium/content/renderer/p2p/ipc_network_manager.h
index c0395753dcb..3e1657bd458 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager.h
+++ b/chromium/content/renderer/p2p/ipc_network_manager.h
@@ -29,9 +29,7 @@ class IpcNetworkManager : public rtc::NetworkManagerBase,
public NetworkListObserver {
public:
// Constructor doesn't take ownership of the |network_list_manager|.
- CONTENT_EXPORT IpcNetworkManager(
- NetworkListManager* network_list_manager,
- std::unique_ptr<MdnsResponderAdapter> mdns_responder);
+ CONTENT_EXPORT IpcNetworkManager(NetworkListManager* network_list_manager);
~IpcNetworkManager() override;
// rtc:::NetworkManager:
@@ -45,6 +43,8 @@ class IpcNetworkManager : public rtc::NetworkManagerBase,
const net::IPAddress& default_ipv4_local_address,
const net::IPAddress& default_ipv6_local_address) override;
+ void SetMdnsResponder(std::unique_ptr<MdnsResponderAdapter> mdns_responder);
+
private:
void SendNetworksChangedSignal();
diff --git a/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc b/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc
index 26b96cf06d7..06bb29c9bfe 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc
+++ b/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc
@@ -41,8 +41,7 @@ class IpcNetworkManagerTest : public testing::Test {
public:
IpcNetworkManagerTest()
: network_list_manager_(new MockP2PSocketDispatcher()),
- network_manager_(
- new IpcNetworkManager(network_list_manager_.get(), nullptr)) {}
+ network_manager_(new IpcNetworkManager(network_list_manager_.get())) {}
protected:
std::unique_ptr<MockP2PSocketDispatcher> network_list_manager_;
diff --git a/chromium/content/renderer/p2p/mdns_responder_adapter.cc b/chromium/content/renderer/p2p/mdns_responder_adapter.cc
index 4ba765351d9..4fd88eea7b3 100644
--- a/chromium/content/renderer/p2p/mdns_responder_adapter.cc
+++ b/chromium/content/renderer/p2p/mdns_responder_adapter.cc
@@ -43,6 +43,8 @@ MdnsResponderAdapter::MdnsResponderAdapter() {
auto request = mojo::MakeRequest(&client);
thread_safe_client_ =
network::mojom::ThreadSafeMdnsResponderPtr::Create(std::move(client));
+ DCHECK(ChildThreadImpl::current());
+ DCHECK(ChildThreadImpl::current()->GetConnector());
ChildThreadImpl::current()->GetConnector()->BindInterface(
mojom::kBrowserServiceName, std::move(request));
}
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index 5b45214bdb3..73c2e6af3d9 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -3617,6 +3617,17 @@ void RenderFrameImpl::UpdateSubresourceLoaderFactories(
->UpdateThisAndAllClones(std::move(subresource_loaders));
}
+void RenderFrameImpl::MarkInitiatorAsRequiringSeparateURLLoaderFactory(
+ const url::Origin& initiator_origin,
+ network::mojom::URLLoaderFactoryPtr url_loader_factory) {
+ DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+
+ auto factory_bundle = std::make_unique<blink::URLLoaderFactoryBundleInfo>();
+ factory_bundle->initiator_specific_factory_infos()[initiator_origin] =
+ url_loader_factory.PassInterface();
+ UpdateSubresourceLoaderFactories(std::move(factory_bundle));
+}
+
void RenderFrameImpl::BindDevToolsAgent(
blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
blink::mojom::DevToolsAgentAssociatedRequest request) {
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index c8130291002..bfe6b75355a 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -586,6 +586,9 @@ class CONTENT_EXPORT RenderFrameImpl
void UpdateSubresourceLoaderFactories(
std::unique_ptr<blink::URLLoaderFactoryBundleInfo> subresource_loaders)
override;
+ void MarkInitiatorAsRequiringSeparateURLLoaderFactory(
+ const url::Origin& initiator_origin,
+ network::mojom::URLLoaderFactoryPtr url_loader_factory) override;
void BindDevToolsAgent(
blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
blink::mojom::DevToolsAgentAssociatedRequest request) override;
diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc
index 44df5d5461c..f376c3cbbce 100644
--- a/chromium/content/renderer/render_thread_impl.cc
+++ b/chromium/content/renderer/render_thread_impl.cc
@@ -1308,6 +1308,11 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
EstablishGpuChannelSync();
if (!gpu_channel_host)
return nullptr;
+ // Currently, VideoResourceUpdater can't convert hardware resources to
+ // software resources in software compositing mode. So, fall back to software
+ // video decoding if gpu compositing is off.
+ if (is_gpu_compositing_disabled_)
+ return nullptr;
// This context is only used to create textures and mailbox them, so
// use lower limits than the default.
gpu::SharedMemoryLimits limits = gpu::SharedMemoryLimits::ForMailboxContext();
diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc
index 676b344fe80..eb0a039e0fa 100644
--- a/chromium/content/renderer/render_view_impl.cc
+++ b/chromium/content/renderer/render_view_impl.cc
@@ -1319,6 +1319,10 @@ WebView* RenderViewImpl::CreateView(
base::FeatureList::IsEnabled(features::kUserActivationV2)
? false
: WebUserGestureIndicator::IsProcessingUserGesture(creator);
+ // TODO(mustaq): Investigate if mimic_user_gesture can wrongly expose presence
+ // of user activation w/o any user interaction, e.g. through
+ // |WebChromeClient#onCreateWindow|. One case to deep-dive: disabling popup
+ // blocker then calling window.open at onload event. crbug.com/929729
if (GetContentClient()->renderer()->AllowPopup())
params->mimic_user_gesture = true;
@@ -1375,8 +1379,10 @@ WebView* RenderViewImpl::CreateView(
// The browser allowed creation of a new window and consumed the user
// activation (UAv2 only).
- WebUserGestureIndicator::ConsumeUserGesture(
+ bool was_consumed = WebUserGestureIndicator::ConsumeUserGesture(
creator, blink::UserActivationUpdateSource::kBrowser);
+ if (base::FeatureList::IsEnabled(features::kUserActivationV2))
+ opened_by_user_gesture = was_consumed;
// While this view may be a background extension page, it can spawn a visible
// render view. So we just assume that the new one is not another background
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index a447dbf313a..5223ac9b878 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -2956,6 +2956,14 @@ cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings(
settings.wait_for_all_pipeline_stages_before_draw = true;
settings.enable_latency_recovery = false;
}
+#if defined(OS_ANDROID)
+ if (features::IsSurfaceSynchronizationEnabled()) {
+ // TODO(crbug.com/933846): LatencyRecovery is causing jank on Android.
+ // Disable in viz mode for now, with plant o disable more widely once
+ // viz launches.
+ settings.enable_latency_recovery = false;
+ }
+#endif
settings.enable_image_animation_resync =
!cmd.HasSwitch(switches::kDisableImageAnimationResync);
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.cc b/chromium/content/renderer/service_worker/service_worker_context_client.cc
index 97bea3f3820..dfde993488a 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.cc
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc
@@ -1860,8 +1860,11 @@ void ServiceWorkerContextClient::SetTimeoutTimerForTesting(
}
void ServiceWorkerContextClient::RecordDebugLog(const char* message) {
+ const size_t kMaxDebugLogSize = 512;
base::AutoLock lock(debug_log_lock_);
debug_log_.emplace_back(message);
+ if (debug_log_.size() > kMaxDebugLogSize)
+ debug_log_.pop_front();
}
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.h b/chromium/content/renderer/service_worker/service_worker_context_client.h
index e6816c90106..a885656b8c0 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.h
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.h
@@ -8,10 +8,10 @@
#include <stddef.h>
#include <stdint.h>
+#include <deque>
#include <map>
#include <memory>
#include <string>
-#include <vector>
#include "base/callback.h"
#include "base/containers/id_map.h"
@@ -429,7 +429,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient
// TODO(crbug.com/907311): Remove after we identified the cause of crash.
bool report_debug_log_ = true;
base::Lock debug_log_lock_;
- std::vector<std::string> debug_log_ GUARDED_BY(debug_log_lock_);
+ std::deque<std::string> debug_log_ GUARDED_BY(debug_log_lock_);
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextClient);
};
diff --git a/chromium/content/utility/utility_service_factory.cc b/chromium/content/utility/utility_service_factory.cc
index 4450cc71177..24a2644f008 100644
--- a/chromium/content/utility/utility_service_factory.cc
+++ b/chromium/content/utility/utility_service_factory.cc
@@ -178,7 +178,7 @@ void UtilityServiceFactory::RunNetworkServiceOnIOThread(
scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner) {
auto service = std::make_unique<network::NetworkService>(
std::move(network_registry_), nullptr /* request */,
- nullptr /* net_log */, std::move(service_request));
+ nullptr /* net_log */, std::move(service_request), true);
// Transfer ownership of the service to itself, and have it post to the main
// thread on self-termination to kill the process.
diff --git a/chromium/extensions/browser/api/web_request/web_request_api.cc b/chromium/extensions/browser/api/web_request/web_request_api.cc
index a07b722dd1b..7a2c83535e0 100644
--- a/chromium/extensions/browser/api/web_request/web_request_api.cc
+++ b/chromium/extensions/browser/api/web_request/web_request_api.cc
@@ -711,6 +711,7 @@ bool WebRequestAPI::MaybeProxyURLLoaderFactory(
}
bool WebRequestAPI::MaybeProxyAuthRequest(
+ content::BrowserContext* browser_context,
net::AuthChallengeInfo* auth_info,
scoped_refptr<net::HttpResponseHeaders> response_headers,
const content::GlobalRequestID& request_id,
@@ -722,10 +723,18 @@ bool WebRequestAPI::MaybeProxyAuthRequest(
content::GlobalRequestID proxied_request_id = request_id;
if (is_main_frame)
proxied_request_id.child_id = -1;
+
+ // NOTE: This request may be proxied on behalf of an incognito frame, but
+ // |this| will always be bound to a regular profile (see
+ // |BrowserContextKeyedAPI::kServiceRedirectedInIncognito|).
+ DCHECK(browser_context == browser_context_ ||
+ (browser_context->IsOffTheRecord() &&
+ ExtensionsBrowserClient::Get()->GetOriginalContext(browser_context) ==
+ browser_context_));
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::IO},
base::BindOnce(&MaybeProxyAuthRequestOnIO,
- browser_context_->GetResourceContext(),
+ browser_context->GetResourceContext(),
base::RetainedRef(auth_info), std::move(response_headers),
proxied_request_id, std::move(callback)));
return true;
diff --git a/chromium/extensions/browser/api/web_request/web_request_api.h b/chromium/extensions/browser/api/web_request/web_request_api.h
index ceeabfafe81..858deaad398 100644
--- a/chromium/extensions/browser/api/web_request/web_request_api.h
+++ b/chromium/extensions/browser/api/web_request/web_request_api.h
@@ -206,6 +206,7 @@ class WebRequestAPI : public BrowserContextKeyedAPI,
// If this returns |true|, |callback| will eventually be invoked on the UI
// thread.
bool MaybeProxyAuthRequest(
+ content::BrowserContext* browser_context,
net::AuthChallengeInfo* auth_info,
scoped_refptr<net::HttpResponseHeaders> response_headers,
const content::GlobalRequestID& request_id,
diff --git a/chromium/extensions/browser/extension_protocols.cc b/chromium/extensions/browser/extension_protocols.cc
index 01dcf5125a8..49bbfa0981f 100644
--- a/chromium/extensions/browser/extension_protocols.cc
+++ b/chromium/extensions/browser/extension_protocols.cc
@@ -981,7 +981,7 @@ class ExtensionURLLoaderFactory : public network::mojom::URLLoaderFactory {
content::CreateFileURLLoader(
request, std::move(loader), std::move(client),
std::make_unique<FileLoaderObserver>(std::move(verify_job)),
- std::move(response_headers));
+ /* allow_directory_listing */ false, std::move(response_headers));
}
content::BrowserContext* browser_context_;
diff --git a/chromium/extensions/renderer/bindings/api_request_handler.cc b/chromium/extensions/renderer/bindings/api_request_handler.cc
index f98de6e2681..586f97ebf33 100644
--- a/chromium/extensions/renderer/bindings/api_request_handler.cc
+++ b/chromium/extensions/renderer/bindings/api_request_handler.cc
@@ -76,12 +76,12 @@ APIRequestHandler::PendingRequest::PendingRequest(
const std::string& method_name,
v8::Local<v8::Function> request_callback,
const base::Optional<std::vector<v8::Local<v8::Value>>>&
- local_callback_args)
+ local_callback_args,
+ const base::Optional<blink::WebUserGestureToken>& gesture_token)
: isolate(isolate), context(isolate, context), method_name(method_name) {
if (!request_callback.IsEmpty()) {
callback.emplace(isolate, request_callback);
- user_gesture_token =
- blink::WebUserGestureIndicator::CurrentUserGestureToken();
+ user_gesture_token = gesture_token;
if (local_callback_args) {
callback_arguments = std::vector<v8::Global<v8::Value>>();
@@ -89,6 +89,11 @@ APIRequestHandler::PendingRequest::PendingRequest(
for (const auto& arg : *local_callback_args)
callback_arguments->emplace_back(isolate, arg);
}
+ } else {
+ DCHECK(!local_callback_args.has_value())
+ << "Cannot specify callback arguments without a callback.";
+ DCHECK(!user_gesture_token.has_value())
+ << "Cannot specify a user gesture token without a callback.";
}
}
@@ -133,6 +138,7 @@ int APIRequestHandler::StartRequest(v8::Local<v8::Context> context,
base::Optional<std::vector<v8::Local<v8::Value>>> callback_args;
v8::Isolate* isolate = context->GetIsolate();
+ base::Optional<blink::WebUserGestureToken> user_gesture_token;
if (!custom_callback.IsEmpty() || !callback.IsEmpty()) {
// In the JS bindings, custom callbacks are called with the arguments of
// name, the full request object (see below), the original callback, and
@@ -155,11 +161,13 @@ int APIRequestHandler::StartRequest(v8::Local<v8::Context> context,
callback = custom_callback;
}
+ user_gesture_token =
+ blink::WebUserGestureIndicator::CurrentUserGestureToken();
request->has_callback = true;
}
- pending_requests_.insert(std::make_pair(
- request_id,
- PendingRequest(isolate, context, method, callback, callback_args)));
+ pending_requests_.emplace(request_id,
+ PendingRequest(isolate, context, method, callback,
+ callback_args, user_gesture_token));
request->has_user_gesture = get_user_activation_state_callback_.Run(context);
request->arguments = std::move(arguments);
@@ -187,9 +195,17 @@ void APIRequestHandler::CompleteRequest(
int APIRequestHandler::AddPendingRequest(v8::Local<v8::Context> context,
v8::Local<v8::Function> callback) {
int request_id = next_request_id_++;
+
+ // NOTE(devlin): We ignore the UserGestureToken for synthesized requests like
+ // these that aren't sent to the browser. It is the caller's responsibility to
+ // handle any user gesture behavior. This prevents an issue where messaging
+ // handling would create an extra scoped user gesture, causing issues. See
+ // https://crbug.com/921141.
+ base::Optional<blink::WebUserGestureToken> null_user_gesture_token;
pending_requests_.emplace(
- request_id, PendingRequest(context->GetIsolate(), context, std::string(),
- callback, base::nullopt));
+ request_id,
+ PendingRequest(context->GetIsolate(), context, std::string(), callback,
+ base::nullopt, null_user_gesture_token));
return request_id;
}
@@ -261,7 +277,8 @@ void APIRequestHandler::CompleteRequestImpl(int request_id,
std::unique_ptr<blink::WebScopedUserGesture> user_gesture;
// UserActivationV2 replaces the concept of (scoped) tokens with a frame-wide
// state, hence skips token forwarding.
- if (!base::FeatureList::IsEnabled(features::kUserActivationV2)) {
+ if (!base::FeatureList::IsEnabled(features::kUserActivationV2) &&
+ pending_request.user_gesture_token) {
user_gesture = std::make_unique<blink::WebScopedUserGesture>(
*pending_request.user_gesture_token);
}
diff --git a/chromium/extensions/renderer/bindings/api_request_handler.h b/chromium/extensions/renderer/bindings/api_request_handler.h
index a273a4bec30..482ad340bff 100644
--- a/chromium/extensions/renderer/bindings/api_request_handler.h
+++ b/chromium/extensions/renderer/bindings/api_request_handler.h
@@ -74,6 +74,7 @@ class APIRequestHandler {
// CompleteRequest). This is used by renderer-side implementations that
// shouldn't be dispatched to the browser in the normal flow, but means other
// classes don't have to worry about context invalidation.
+ // Note: Unlike StartRequest(), this will not track user gesture state.
int AddPendingRequest(v8::Local<v8::Context> context,
v8::Local<v8::Function> callback);
@@ -111,7 +112,8 @@ class APIRequestHandler {
v8::Local<v8::Context> context,
const std::string& method_name,
v8::Local<v8::Function> callback,
- const base::Optional<std::vector<v8::Local<v8::Value>>>& callback_args);
+ const base::Optional<std::vector<v8::Local<v8::Value>>>& callback_args,
+ const base::Optional<blink::WebUserGestureToken>& user_gesture_token);
~PendingRequest();
PendingRequest(PendingRequest&&);
PendingRequest& operator=(PendingRequest&&);
diff --git a/chromium/extensions/strings/extensions_strings_id.xtb b/chromium/extensions/strings/extensions_strings_id.xtb
index 6dc980d98b9..c39d318ae34 100644
--- a/chromium/extensions/strings/extensions_strings_id.xtb
+++ b/chromium/extensions/strings/extensions_strings_id.xtb
@@ -8,7 +8,7 @@
<translation id="1445572445564823378">Ekstensi ini memperlambat <ph name="PRODUCT_NAME" />. Anda harus menonaktifkannya agar dapat memulihkan kinerja <ph name="PRODUCT_NAME" />.</translation>
<translation id="1468038450257740950">WebGL tidak didukung.</translation>
<translation id="149347756975725155">Tidak dapat memuat ikon ekstensi '<ph name="ICON" />'.</translation>
-<translation id="1803557475693955505">Tidak dapat memuat halaman latar belakang '<ph name="BACKGROUND_PAGE" />'.</translation>
+<translation id="1803557475693955505">Tidak dapat memuat halaman background '<ph name="BACKGROUND_PAGE" />'.</translation>
<translation id="2159915644201199628">Tidak dapat mendekode gambar: '<ph name="IMAGE_NAME" />'</translation>
<translation id="2350172092385603347">Lokalisasi digunakan, tetapi default_locale tidak ditentukan dalam manifes.</translation>
<translation id="2576842806987913196">Sudah ada file CRX dengan nama ini.</translation>
diff --git a/chromium/extensions/strings/extensions_strings_te.xtb b/chromium/extensions/strings/extensions_strings_te.xtb
index faa7dae9833..6764891ec5c 100644
--- a/chromium/extensions/strings/extensions_strings_te.xtb
+++ b/chromium/extensions/strings/extensions_strings_te.xtb
@@ -5,7 +5,7 @@
<translation id="1140871961407805696">పర్యావరణం వైపుగా</translation>
<translation id="1196338895211115272">ప్రైవేట్ కీని ఎగుమతి చేయడానికి విఫలమైంది.</translation>
<translation id="1420684932347524586">అరె! RSA ప్రైవేట్ కీని రాండమ్‌గా రూపొందించడంలో విఫలమైంది.</translation>
-<translation id="1445572445564823378">ఈ పొడిగింపు <ph name="PRODUCT_NAME" />ను మందగింప చేస్తోంది. <ph name="PRODUCT_NAME" /> యొక్క పనితీరును పునరుద్ధరించడానికి మీరు దీన్ని ఆపివేయాలి.</translation>
+<translation id="1445572445564823378">ఈ ఎక్స్‌టెన్ష‌న్‌ <ph name="PRODUCT_NAME" />ను మందగింప చేస్తోంది. <ph name="PRODUCT_NAME" /> యొక్క పనితీరును పునరుద్ధరించడానికి మీరు దీన్ని నిలిపివేయాలి.</translation>
<translation id="1468038450257740950">WebGLకి మద్దతు లేదు.</translation>
<translation id="149347756975725155">'<ph name="ICON" />' ఎక్స్‌టెన్షన్ చిహ్నాన్ని లోడ్ చేయడం సాధ్యపడలేదు.</translation>
<translation id="1803557475693955505">నేపథ్య పేజీ '<ph name="BACKGROUND_PAGE" />'ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
@@ -13,21 +13,21 @@
<translation id="2350172092385603347">స్థానికీకరణ ఉపయోగించబడుతుంది, అయితే మానిఫెస్ట్‌లో default_localeను పేర్కొనలేదు.</translation>
<translation id="2576842806987913196">ఈ పేరుతో ఇప్పటికే CRX ఫైల్ ఉంది.</translation>
<translation id="2753617847762399167">చట్టవిరుద్ధ పాథ్‌ (ఖచ్చితంగా లేదా '..'కు సంబంధిత): '<ph name="IMAGE_PATH" />'</translation>
-<translation id="2785530881066938471">కంటెంట్ స్క్రిప్ట్ కోసం '<ph name="RELATIVE_PATH" />' ఫైల్‌ను లోడ్ చేయలేకపోయింది. ఈ ఫైల్ UTF-8లో ఎన్‌కోడ్ కాలేదు.</translation>
-<translation id="2903070246402204397"><ph name="EXTENSION_NAME" /> (ఎక్స్‌టెన్షన్‌ ID "<ph name="EXTENSION_ID" />") నిర్వాహకుల ద్వారా బ్లాక్ చేయబడింది. <ph name="ADMIN_INFO" /></translation>
+<translation id="2785530881066938471">కంటెంట్ స్క్రిప్ట్‌కు '<ph name="RELATIVE_PATH" />' ఫైల్‌ను లోడ్ చేయలేకపోయింది. ఈ ఫైల్ UTF-8లో ఎన్‌కోడ్ కాలేదు.</translation>
+<translation id="2903070246402204397"><ph name="EXTENSION_NAME" /> (ఎక్స్‌టెన్ష‌న్‌ ID "<ph name="EXTENSION_ID" />") నిర్వాహకుల ద్వారా బ్లాక్ చేయబడింది. <ph name="ADMIN_INFO" /></translation>
<translation id="2988488679308982380">ప్యాకేజీని ఇన్‌స్టాల్ చేయడం సాధ్యపడలేదు: '<ph name="ERROR_CODE" />'</translation>
<translation id="3115238746683532089"><ph name="VENDOR_ID" /> విక్రేత నుండి తెలియని ఉత్పత్తి <ph name="PRODUCT_ID" /> (క్రమ సంఖ్య <ph name="SERIAL_NUMBER" />)</translation>
<translation id="3144135466825225871">crx ఫైల్ భర్తీ విఫలమైంది. ఫైల్ వినియోగంలో ఉందా అని తనిఖీ చేయండి.</translation>
<translation id="3163201441334626963"><ph name="VENDOR_ID" /> నుండి <ph name="PRODUCT_ID" /> తెలియని ఉత్పత్తి</translation>
-<translation id="3302709122321372472">కంటెంట్ స్క్రిప్ట్ కోసం css '<ph name="RELATIVE_PATH" />'ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
-<translation id="3369521687965833290">ఎక్స్‌టెన్‌షన్ అన్‌ప్యాక్ చేయబడదు. ఒక ఎక్స్‌టెన్‌షన్‌‌ను సురక్షితంగా అన్‌ప్యాక్ చేయడానికి, మీ ప్రొఫైల్ డైరెక్టరీకి ఒక డ్రైవ్ అక్షరంతో ప్రారంభమయ్యే మరియు జంక్షన్, మౌంట్ పాయింట్ లేదా సింలింక్ ఉండని పాథ్‌ తప్పనిసరిగా ఉండాలి. మీ ప్రొఫైల్‌కు అటువంటి పాథ్‌ లేదు.</translation>
+<translation id="3302709122321372472">కంటెంట్ స్క్రిప్ట్‌కు css '<ph name="RELATIVE_PATH" />'ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
+<translation id="3369521687965833290">ఎక్స్‌టెన్షన్‌ను అన్‌ప్యాక్ చేయడం సాధ్యపడలేదు. ఒక ఎక్స్‌టెన్షన్‌‌ను సురక్షితంగా అన్‌ప్యాక్ చేయడానికి, మీ ప్రొఫైల్ డైరెక్టరీకి ఒక డ్రైవ్ అక్షరంతో ప్రారంభమయ్యే మరియు జంక్షన్, మౌంట్ పాయింట్ లేదా సింలింక్ ఉండని పాత్ తప్పనిసరిగా ఉండాలి. మీ ప్రొఫైల్‌కు అటువంటి పాత్ లేదు.</translation>
<translation id="3393440416772303020"><ph name="PRODUCT_NAME" /> (క్రమ సంఖ్య <ph name="SERIAL_NUMBER" />)</translation>
<translation id="3466070586188012397"><ph name="VENDOR_ID" /> విక్రేత నుండి <ph name="PRODUCT_NAME" /> (క్రమ సంఖ్య <ph name="SERIAL_NUMBER" />)</translation>
<translation id="3561217442734750519">ప్రైవేట్ కీ కోసం ఇన్‌పుట్ విలువ తప్పనిసరిగా చెల్లుబాటు అయ్యే పాథ్‌గా ఉండాలి.</translation>
<translation id="388442998277590542">ఎంపికల పేజీ '<ph name="OPTIONS_PAGE" />'ను లోడ్ చేయడం సాధ్యం కాలేదు.</translation>
<translation id="3984413272403535372">ఎక్స్‌టెన్షన్‌కు సంతకం చేసేటప్పుడు ఎర్రర్.</translation>
-<translation id="39964277676607559">కంటెంట్ స్క్రిప్ట్‌ కోసం JavaScript '<ph name="RELATIVE_PATH" />'ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
-<translation id="4115165561519362854">ఈ మెషీన్ నిర్వాహకుడికి <ph name="EXTENSION_NAME" /> కనీస సంస్కరణ అయిన <ph name="EXTENSION_VERSION" /> ఉండటం అవసరం. ఇది ఆ సంస్కరణకు (లేదా తదుపరి దానికి) నవీకరించే వరకు ప్రారంభించబడదు.</translation>
+<translation id="39964277676607559">కంటెంట్ స్క్రిప్ట్‌కు JavaScript '<ph name="RELATIVE_PATH" />' లోడ్ చేయడం సాధ్యపడలేదు.</translation>
+<translation id="4115165561519362854"><ph name="EXTENSION_NAME" /> యొక్క వెర్షన్ కనీసం <ph name="EXTENSION_VERSION" /> ఉండాలని ఈ మెషీన్ నిర్వాహకుడు నిర్బంధించారు. ఇది ఆ వెర్షన్‌కు (లేదా తర్వాతి వెర్షన్‌కు) అప్‌డేట్ చేసే వరకు దీనిని ప్రారంభించడం సాధ్యపడదు.</translation>
<translation id="4233778200880751280">'<ph name="ABOUT_PAGE" />' పరిచయ పేజీని లోడ్ చేయడం సాధ్యపడలేదు.</translation>
<translation id="471800408830181311">ప్రైవేట్ కీని అవుట్‌పుట్ చేయడంలో విఫలమైంది.</translation>
<translation id="4811956658694082538">వినియోగ ప్రాసెస్ క్రాష్ అయినందున ప్యాకేజీని ఇన్‌స్టాల్ చేయలేకపోయింది. Chromeను పునఃప్రారంభించి, మళ్లీ ప్రయత్నించండి.</translation>
@@ -40,10 +40,10 @@
<translation id="5486326529110362464">ప్రైవేట్ కీ కోసం ఇన్‌పుట్ విలువ తప్పనిసరిగా ఉండాలి.</translation>
<translation id="5627523580512561598">పొడిగింపు <ph name="EXTENSION_NAME" /></translation>
<translation id="5960890139610307736">పొడిగింపు వీక్షణ: <ph name="EXTENSIONVIEW_TAG_NAME" /></translation>
-<translation id="5972529113578162692"><ph name="EXTENSION_NAME" />ని ఇన్‌స్టాల్ చేయడం ఈ మెషీన్ నిర్వాహకుడికి అవసరం. ఇది అన్ఇన్‌స్టాల్ చేయబడదు.</translation>
+<translation id="5972529113578162692"><ph name="EXTENSION_NAME" />ని ఇన్‌స్టాల్ చేయడం ఈ మెషిన్‌ నిర్వాహకుడికి అవసరం. ఇది అన్ఇన్‌స్టాల్ చేయబడదు.</translation>
<translation id="6027032947578871493"><ph name="VENDOR_NAME" /> నుండి తెలియని ఉత్పత్తి <ph name="PRODUCT_ID" /> (క్రమ సంఖ్య <ph name="SERIAL_NUMBER" />)</translation>
<translation id="6068932090455285721"><ph name="VENDOR_ID" /> విక్రేత నుండి <ph name="PRODUCT_NAME" /></translation>
-<translation id="6143635259298204954">ఎక్స్‌టెన్‌షన్‌ అన్‌ప్యాక్ చేయబడదు. ఒక ఎక్స్‌టెన్‌షన్‌‌ను సురక్షితంగా అన్‌ప్యాక్ చేయడానికి, మీ ప్రొఫైల్ డైరెక్టరీకి సింలింక్ ఉండని పాథ్‌ తప్పనిసరిగా ఉండాలి. మీ ప్రొఫైల్‌కు అటువంటి పాథ్‌ లేదు.</translation>
+<translation id="6143635259298204954">ఎక్స్‌టెన్షన్‌ను అన్‌ప్యాక్ చేయడం సాధ్యపడలేదు. ఒక ఎక్స్‌టెన్షన్‌‌ను సురక్షితంగా అన్‌ప్యాక్ చేయడానికి, మీ ప్రొఫైల్ డైరెక్టరీకి సింలింక్ ఉండని పాత్ తప్పనిసరిగా ఉండాలి. మీ ప్రొఫైల్‌కు అటువంటి పాత్ లేదు.</translation>
<translation id="6322279351188361895">ప్రైవేట్ కీని చదవడంలో విఫలమైంది.</translation>
<translation id="6391538222494443604">ఇన్‌పుట్ డైరెక్టరీ తప్పనిసరిగా ఉనికిలో ఉండాలి.</translation>
<translation id="641087317769093025">పొడిగింపు అన్‌జిప్ చేయబడదు</translation>
@@ -51,17 +51,17 @@
<translation id="6542618148162044354">"<ph name="APP_NAME" />" మీ ఒకటి లేదా అంతకంటే ఎక్కువ పరికరాలకు యాక్సెస్‌ను అభ్యర్థిస్తోంది:</translation>
<translation id="657064425229075395">'<ph name="BACKGROUND_SCRIPT" />' నేపథ్య స్క్రిప్ట్‌ను లోడ్ చేయడం సాధ్యం కాలేదు.</translation>
<translation id="6580950983454333167"><ph name="VENDOR_NAME" /> నుండి <ph name="PRODUCT_NAME" /> (క్రమ సంఖ్య <ph name="SERIAL_NUMBER" />)</translation>
-<translation id="6731255991101203740">దీనిలో అన్‌జిప్ చేయడానికి డైరెక్టరీ సృష్టించబడదు: '<ph name="DIRECTORY_PATH" />'</translation>
+<translation id="6731255991101203740">దీనిలో అన్‌జిప్ చేయడానికి డైరెక్టరీ సృష్టించబడదు: '<ph name="DIRECTORY_PATH" />'</translation>
<translation id="677806580227005219">Mime హ్యాండ్లర్: <ph name="MIMEHANDLERVIEW_TAG_NAME" /></translation>
<translation id="6840444547062817500">ఈ పొడిగింపు దానికదే చాలా తరచుగా రీలోడ్ అయ్యింది.</translation>
<translation id="7003844668372540529"><ph name="VENDOR_NAME" /> నుండి తెలియని ఉత్పత్తి <ph name="PRODUCT_ID" /></translation>
<translation id="7068383018033524534">మానిఫెస్ట్ ఫైల్ చెల్లదు</translation>
-<translation id="7217838517480956708">ఈ మెషీన్ యొక్క నిర్వాహకుడికి <ph name="EXTENSION_NAME" /> ఇన్‌స్టాల్ చేయబడి ఉండటం అవసరం. దీన్ని తీసివేయడం లేదా సవరించడం సాధ్యపడదు.</translation>
+<translation id="7217838517480956708">ఈ మెషిన్‌ యొక్క నిర్వాహకుడికి <ph name="EXTENSION_NAME" /> ఇన్‌స్టాల్ చేయబడి ఉండటం అవసరం. దీన్ని తీసివేయడం లేదా సవరించడం సాధ్యపడదు.</translation>
<translation id="7612608473764576263">ప్రైవేట్ కీ కోసం ఇన్‌పుట్ విలువ తప్పనిసరిగా చెల్లుబాటు అయ్యే ఫార్మాట్‌లో ఉండాలి. (PKCS#8-ఫార్మాట్‌లో, PEM-ఎన్‌కోడ్ చేసిన RSA కీ)</translation>
<translation id="7939686037314084444">ఎక్స్‌టెన్షన్ సరిగా లోడ్ అవ్వడంలో విఫలం అయ్యింది. కనుక ఇది నెట్‌వర్క్ అభ్యర్థనలను అడ్డగించలేకపోవచ్చు.</translation>
<translation id="7972881773422714442">ఎంపికలు: <ph name="EXTENSIONOPTIONS_TAG_NAME" /></translation>
<translation id="8035920974645200807">వినియోగదారు వైపుగా</translation>
-<translation id="8047248493720652249">ఈ పొడిగింపు డౌన్‌లోడ్ యొక్క పేరును "<ph name="ATTEMPTED_FILENAME" />"గా పేర్కొనడంలో విఫలమైంది ఎందుకంటే మరో పొడిగింపు (<ph name="EXTENSION_NAME" />) "<ph name="ACTUAL_FILENAME" />" అనే వేరే ఫైల్ పేరుని నిశ్చయించింది.</translation>
+<translation id="8047248493720652249">ఈ ఎక్స్‌టెన్ష‌న్‌ డౌన్‌లోడ్ యొక్క పేరును "<ph name="ATTEMPTED_FILENAME" />"గా పేర్కొనడంలో విఫలమైంది. ఎందుకంటే మరో ఎక్స్‌టెన్ష‌న్‌ (<ph name="EXTENSION_NAME" />) "<ph name="ACTUAL_FILENAME" />" అనే వేరే ఫైల్ పేరును నిశ్చయించింది.</translation>
<translation id="8284835137979141223"><ph name="VENDOR_NAME" /> నుండి <ph name="PRODUCT_NAME" /></translation>
<translation id="8517576857589387417">మానిఫెస్ట్ ఫైల్ లేదు లేదా చదవడం సాధ్యం కాదు</translation>
<translation id="8636666366616799973">ప్యాకేజీ చెల్లనిది. వివరాలు: '<ph name="ERROR_MESSAGE" />'.</translation>
diff --git a/chromium/google_apis/drive/base_requests_server_unittest.cc b/chromium/google_apis/drive/base_requests_server_unittest.cc
index 5dcd8b134f5..17aa745810a 100644
--- a/chromium/google_apis/drive/base_requests_server_unittest.cc
+++ b/chromium/google_apis/drive/base_requests_server_unittest.cc
@@ -52,7 +52,8 @@ class BaseRequestsServerTest : public testing::Test {
network_service_client_ =
std::make_unique<network::TestNetworkServiceClient>(
mojo::MakeRequest(&network_service_client_ptr));
- network_service_ptr->SetClient(std::move(network_service_client_ptr));
+ network_service_ptr->SetClient(std::move(network_service_client_ptr),
+ network::mojom::NetworkServiceParams::New());
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
diff --git a/chromium/google_apis/drive/base_requests_unittest.cc b/chromium/google_apis/drive/base_requests_unittest.cc
index d59489781b2..e38b5c14101 100644
--- a/chromium/google_apis/drive/base_requests_unittest.cc
+++ b/chromium/google_apis/drive/base_requests_unittest.cc
@@ -128,7 +128,8 @@ class BaseRequestsTest : public testing::Test {
network_service_client_ =
std::make_unique<network::TestNetworkServiceClient>(
mojo::MakeRequest(&network_service_client_ptr));
- network_service_ptr->SetClient(std::move(network_service_client_ptr));
+ network_service_ptr->SetClient(std::move(network_service_client_ptr),
+ network::mojom::NetworkServiceParams::New());
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
diff --git a/chromium/google_apis/drive/drive_api_requests_unittest.cc b/chromium/google_apis/drive/drive_api_requests_unittest.cc
index c40f6ca5924..19606e4be52 100644
--- a/chromium/google_apis/drive/drive_api_requests_unittest.cc
+++ b/chromium/google_apis/drive/drive_api_requests_unittest.cc
@@ -137,7 +137,8 @@ class DriveApiRequestsTest : public testing::Test {
network_service_client_ =
std::make_unique<network::TestNetworkServiceClient>(
mojo::MakeRequest(&network_service_client_ptr));
- network_service_ptr->SetClient(std::move(network_service_client_ptr));
+ network_service_ptr->SetClient(std::move(network_service_client_ptr),
+ network::mojom::NetworkServiceParams::New());
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
diff --git a/chromium/google_apis/drive/files_list_request_runner_unittest.cc b/chromium/google_apis/drive/files_list_request_runner_unittest.cc
index a612f0276d0..cecfe4f1b7b 100644
--- a/chromium/google_apis/drive/files_list_request_runner_unittest.cc
+++ b/chromium/google_apis/drive/files_list_request_runner_unittest.cc
@@ -84,7 +84,8 @@ class FilesListRequestRunnerTest : public testing::Test {
network_service_client_ =
std::make_unique<network::TestNetworkServiceClient>(
mojo::MakeRequest(&network_service_client_ptr));
- network_service_ptr->SetClient(std::move(network_service_client_ptr));
+ network_service_ptr->SetClient(std::move(network_service_client_ptr),
+ network::mojom::NetworkServiceParams::New());
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
diff --git a/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc b/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
index 49f3e0db052..4668c30dd5e 100644
--- a/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
+++ b/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
@@ -207,7 +207,8 @@ void OAuth2AccessTokenFetcherImpl::EndGetAccessToken(
bool net_failure = false;
int histogram_value;
- if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) {
+ if (url_loader_->NetError() == net::OK && url_loader_->ResponseInfo() &&
+ url_loader_->ResponseInfo()->headers) {
// Note that the SimpleURLLoader reports net::ERR_FAILED for HTTP codes
// other than 200s.
histogram_value = url_loader_->ResponseInfo()->headers->response_code();
@@ -226,6 +227,13 @@ void OAuth2AccessTokenFetcherImpl::EndGetAccessToken(
switch (response_code) {
case net::HTTP_OK:
break;
+ case net::HTTP_PROXY_AUTHENTICATION_REQUIRED:
+ NOTREACHED() << "HTTP 407 should be treated as a network error.";
+ // If this ever happens in production, we treat it as a temporary error as
+ // it is similar to a network error.
+ OnGetTokenFailure(
+ GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
+ return;
case net::HTTP_FORBIDDEN:
// HTTP_FORBIDDEN (403) is treated as temporary error, because it may be
// '403 Rate Limit Exeeded.'
diff --git a/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc b/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc
index 83c2fc75339..e4193273307 100644
--- a/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc
+++ b/chromium/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc
@@ -19,6 +19,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
+#include "services/network/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -102,6 +103,21 @@ class OAuth2AccessTokenFetcherImplTest : public testing::Test {
Intercept(resourceRequestUrlEquals(url)));
}
+ void SetupProxyError() {
+ GURL url(GaiaUrls::GetInstance()->oauth2_token_url());
+ url_loader_factory_.AddResponse(
+ url,
+ network::CreateResourceResponseHead(
+ net::HTTP_PROXY_AUTHENTICATION_REQUIRED),
+ std::string(),
+ network::URLLoaderCompletionStatus(net::ERR_TUNNEL_CONNECTION_FAILED),
+ network::TestURLLoaderFactory::Redirects(),
+ network::TestURLLoaderFactory::kSendHeadersOnNetworkError);
+
+ EXPECT_CALL(url_loader_factory_interceptor_,
+ Intercept(resourceRequestUrlEquals(url)));
+ }
+
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
MockOAuth2AccessTokenConsumer consumer_;
@@ -127,6 +143,18 @@ TEST_F(OAuth2AccessTokenFetcherImplTest, GetAccessTokenResponseCodeFailure) {
base::RunLoop().RunUntilIdle();
}
+// Regression test for https://crbug.com/914672
+TEST_F(OAuth2AccessTokenFetcherImplTest, ProxyFailure) {
+ GoogleServiceAuthError expected_error =
+ GoogleServiceAuthError::FromConnectionError(
+ net::ERR_TUNNEL_CONNECTION_FAILED);
+ ASSERT_TRUE(expected_error.IsTransientError());
+ SetupProxyError();
+ EXPECT_CALL(consumer_, OnGetTokenFailure(expected_error)).Times(1);
+ fetcher_.Start("client_id", "client_secret", ScopeList());
+ base::RunLoop().RunUntilIdle();
+}
+
TEST_F(OAuth2AccessTokenFetcherImplTest, Success) {
SetupGetAccessToken(net::OK, net::HTTP_OK, kValidTokenResponse);
EXPECT_CALL(consumer_, OnGetTokenSuccess(_)).Times(1);
diff --git a/chromium/gpu/command_buffer/client/raster_implementation.cc b/chromium/gpu/command_buffer/client/raster_implementation.cc
index a4ad95d85a2..2a8d060343f 100644
--- a/chromium/gpu/command_buffer/client/raster_implementation.cc
+++ b/chromium/gpu/command_buffer/client/raster_implementation.cc
@@ -191,11 +191,12 @@ class RasterImplementation::PaintOpSerializer {
TransferCacheSerializeHelperImpl* transfer_cache_helper,
ClientFontManager* font_manager)
: ri_(ri),
- buffer_(static_cast<char*>(ri_->MapRasterCHROMIUM(initial_size))),
stashing_image_provider_(stashing_image_provider),
transfer_cache_helper_(transfer_cache_helper),
- font_manager_(font_manager),
- free_bytes_(buffer_ ? initial_size : 0) {}
+ font_manager_(font_manager) {
+ buffer_ =
+ static_cast<char*>(ri_->MapRasterCHROMIUM(initial_size, &free_bytes_));
+ }
~PaintOpSerializer() {
// Need to call SendSerializedData;
@@ -213,12 +214,11 @@ class RasterImplementation::PaintOpSerializer {
ri_->paint_cache_->AbortPendingEntries();
SendSerializedData();
- buffer_ = static_cast<char*>(ri_->MapRasterCHROMIUM(kBlockAlloc));
+ buffer_ =
+ static_cast<char*>(ri_->MapRasterCHROMIUM(kBlockAlloc, &free_bytes_));
if (!buffer_) {
- free_bytes_ = 0;
return 0;
}
- free_bytes_ = kBlockAlloc;
size = op->Serialize(buffer_ + written_bytes_, free_bytes_, options);
}
DCHECK_LE(size, free_bytes_);
@@ -919,7 +919,9 @@ void RasterImplementation::WaitSyncTokenCHROMIUM(
gpu_control_->WaitSyncToken(verified_sync_token);
}
-void* RasterImplementation::MapRasterCHROMIUM(GLsizeiptr size) {
+void* RasterImplementation::MapRasterCHROMIUM(uint32_t size,
+ uint32_t* size_allocated) {
+ *size_allocated = 0u;
if (size < 0) {
SetGLError(GL_INVALID_VALUE, "glMapRasterCHROMIUM", "negative size");
return nullptr;
@@ -934,7 +936,7 @@ void* RasterImplementation::MapRasterCHROMIUM(GLsizeiptr size) {
raster_mapped_buffer_ = base::nullopt;
return nullptr;
}
-
+ *size_allocated = raster_mapped_buffer_->size();
return raster_mapped_buffer_->address();
}
diff --git a/chromium/gpu/command_buffer/client/raster_implementation.h b/chromium/gpu/command_buffer/client/raster_implementation.h
index 444379df337..c4e01fd8628 100644
--- a/chromium/gpu/command_buffer/client/raster_implementation.h
+++ b/chromium/gpu/command_buffer/client/raster_implementation.h
@@ -242,7 +242,9 @@ class RASTER_EXPORT RasterImplementation : public RasterInterface,
GLenum value,
const char* label);
- void* MapRasterCHROMIUM(GLsizeiptr size);
+ // Try to map a transfer buffer of |size|. Will return a pointer to a
+ // buffer of |size_allocated|, which will be equal to or lesser than |size|.
+ void* MapRasterCHROMIUM(uint32_t size, uint32_t* size_allocated);
// |raster_written_size| is the size of buffer used by raster commands.
// |total_written_size| is the total size of the buffer written to, including
diff --git a/chromium/gpu/command_buffer/client/raster_implementation_unittest.cc b/chromium/gpu/command_buffer/client/raster_implementation_unittest.cc
index d78df6c45af..99cf3a984ab 100644
--- a/chromium/gpu/command_buffer/client/raster_implementation_unittest.cc
+++ b/chromium/gpu/command_buffer/client/raster_implementation_unittest.cc
@@ -202,13 +202,6 @@ class RasterImplementationTest : public testing::Test {
QueryTracker* GetQueryTracker() { return gl_->query_tracker_.get(); }
- void* MapRasterCHROMIUM(GLsizeiptr size) {
- return gl_->MapRasterCHROMIUM(size);
- }
- void UnmapRasterCHROMIUM(GLsizeiptr written_size) {
- gl_->UnmapRasterCHROMIUM(written_size, written_size);
- }
-
struct ContextInitOptions {
ContextInitOptions()
: bind_generates_resource_client(true),
diff --git a/chromium/gpu/command_buffer/service/raster_decoder.cc b/chromium/gpu/command_buffer/service/raster_decoder.cc
index c16915d4e8b..b306574e4a5 100644
--- a/chromium/gpu/command_buffer/service/raster_decoder.cc
+++ b/chromium/gpu/command_buffer/service/raster_decoder.cc
@@ -95,6 +95,21 @@ namespace {
base::AtomicSequenceNumber g_raster_decoder_id;
+class ScopedProgressReporter {
+ public:
+ ScopedProgressReporter(gl::ProgressReporter* reporter) : reporter_(reporter) {
+ if (reporter_)
+ reporter_->ReportProgress();
+ }
+ ~ScopedProgressReporter() {
+ if (reporter_)
+ reporter_->ReportProgress();
+ }
+
+ private:
+ gl::ProgressReporter* reporter_;
+};
+
// This class prevents any GL errors that occur when it is in scope from
// being reported to the client.
class ScopedGLErrorSuppressor {
@@ -2206,6 +2221,8 @@ void RasterDecoderImpl::DoRasterCHROMIUM(GLuint raster_shm_id,
options.crash_dump_on_failure = true;
size_t paint_buffer_size = raster_shm_size;
+ ScopedProgressReporter report_progress(
+ shared_context_state_->progress_reporter());
while (paint_buffer_size > 0) {
size_t skip = 0;
cc::PaintOp* deserialized_op = cc::PaintOp::Deserialize(
@@ -2242,7 +2259,16 @@ void RasterDecoderImpl::DoEndRasterCHROMIUM() {
recorder_ = nullptr;
sk_surface_->draw(ddl.get());
}
- sk_surface_->prepareForExternalIO();
+
+ {
+ // This is a slow operation since skia will execute the GPU work for the
+ // complete tile. Make sure the progress reporter is notified to avoid
+ // hangs.
+ ScopedProgressReporter report_progress(
+ shared_context_state_->progress_reporter());
+ sk_surface_->prepareForExternalIO();
+ }
+
if (!shared_image_) {
// Test only path for SetUpForRasterCHROMIUMForTest.
sk_surface_.reset();
diff --git a/chromium/gpu/command_buffer/service/shared_context_state.cc b/chromium/gpu/command_buffer/service/shared_context_state.cc
index 7b4ccdbe188..02acb107330 100644
--- a/chromium/gpu/command_buffer/service/shared_context_state.cc
+++ b/chromium/gpu/command_buffer/service/shared_context_state.cc
@@ -74,6 +74,8 @@ void SharedContextState::InitializeGrContext(
GrContextOptions::PersistentCache* cache,
GpuProcessActivityFlags* activity_flags,
gl::ProgressReporter* progress_reporter) {
+ progress_reporter_ = progress_reporter;
+
if (!use_vulkan_gr_context_) {
DCHECK(context_->IsCurrent(nullptr));
sk_sp<GrGLInterface> interface(gl::init::CreateGrGLInterface(
diff --git a/chromium/gpu/command_buffer/service/shared_context_state.h b/chromium/gpu/command_buffer/service/shared_context_state.h
index 51a28b2ebc5..7883ac2af41 100644
--- a/chromium/gpu/command_buffer/service/shared_context_state.h
+++ b/chromium/gpu/command_buffer/service/shared_context_state.h
@@ -79,6 +79,7 @@ class GPU_GLES2_EXPORT SharedContextState
viz::VulkanContextProvider* vk_context_provider() {
return vk_context_provider_;
}
+ gl::ProgressReporter* progress_reporter() const { return progress_reporter_; }
GrContext* gr_context() { return gr_context_; }
gles2::FeatureInfo* feature_info() { return feature_info_.get(); }
gles2::ContextState* context_state() const { return context_state_.get(); }
@@ -143,6 +144,7 @@ class GPU_GLES2_EXPORT SharedContextState
// raster decoders and display compositor share this context_state_.
std::unique_ptr<gles2::ContextState> context_state_;
+ gl::ProgressReporter* progress_reporter_ = nullptr;
sk_sp<GrContext> owned_gr_context_;
std::unique_ptr<ServiceTransferCache> transfer_cache_;
size_t glyph_cache_max_texture_bytes_ = 0u;
diff --git a/chromium/gpu/config/gpu_driver_bug_list.json b/chromium/gpu/config/gpu_driver_bug_list.json
index 2ac3cf79c5e..4996becd8a7 100644
--- a/chromium/gpu/config/gpu_driver_bug_list.json
+++ b/chromium/gpu/config/gpu_driver_bug_list.json
@@ -3067,6 +3067,41 @@
"features": [
"disable_direct_composition"
]
+ },
+ {
+ "id": 293,
+ "cr_bugs": [931527],
+ "description": "Frequent crashes in glClear on Android N with driver 12.0.04rel0",
+ "os": {
+ "type": "android",
+ "version": {
+ "op": "<",
+ "value": "8.0"
+ }
+ },
+ "driver_version": {
+ "op": "=",
+ "value": "12.0.04rel0"
+ },
+ "features": [
+ "gl_clear_broken"
+ ]
+ },
+ {
+ "id": 294,
+ "cr_bugs": [932879],
+ "description": "Hardware overlays result in black videos on non-Intel GPUs",
+ "os": {
+ "type": "win"
+ },
+ "exceptions": [
+ {
+ "vendor_id": "0x8086"
+ }
+ ],
+ "features": [
+ "disable_direct_composition_layers"
+ ]
}
]
}
diff --git a/chromium/gpu/config/gpu_lists_version.h b/chromium/gpu/config/gpu_lists_version.h
index 545fc54a310..2e511214d9c 100644
--- a/chromium/gpu/config/gpu_lists_version.h
+++ b/chromium/gpu/config/gpu_lists_version.h
@@ -3,6 +3,6 @@
#ifndef GPU_CONFIG_GPU_LISTS_VERSION_H_
#define GPU_CONFIG_GPU_LISTS_VERSION_H_
-#define GPU_LISTS_VERSION "8cd51bd20244a019d86ed5092017a118e2ad962a"
+#define GPU_LISTS_VERSION "4564075605dd87605df1f8c00bf7161c9c4eb41b"
#endif // GPU_CONFIG_GPU_LISTS_VERSION_H_
diff --git a/chromium/gpu/config/gpu_util.cc b/chromium/gpu/config/gpu_util.cc
index c4f4b72d2c8..40115b2bcb0 100644
--- a/chromium/gpu/config/gpu_util.cc
+++ b/chromium/gpu/config/gpu_util.cc
@@ -232,9 +232,14 @@ void AppendWorkaroundsToCommandLine(const GpuFeatureInfo& gpu_feature_info,
if (gpu_feature_info.IsWorkaroundEnabled(DISABLE_ES3_GL_CONTEXT)) {
command_line->AppendSwitch(switches::kDisableES3GLContext);
}
+#if defined(OS_WIN)
if (gpu_feature_info.IsWorkaroundEnabled(DISABLE_DIRECT_COMPOSITION)) {
command_line->AppendSwitch(switches::kDisableDirectComposition);
}
+ if (gpu_feature_info.IsWorkaroundEnabled(DISABLE_DIRECT_COMPOSITION_LAYERS)) {
+ command_line->AppendSwitch(switches::kDisableDirectCompositionLayers);
+ }
+#endif
}
// Adjust gpu feature status based on enabled gpu driver bug workarounds.
diff --git a/chromium/gpu/config/gpu_workaround_list.txt b/chromium/gpu/config/gpu_workaround_list.txt
index 826c74a5e00..c8e2cbadd83 100644
--- a/chromium/gpu/config/gpu_workaround_list.txt
+++ b/chromium/gpu/config/gpu_workaround_list.txt
@@ -22,6 +22,7 @@ disable_d3d11
disable_delayed_copy_nv12
disable_depth_texture
disable_direct_composition
+disable_direct_composition_layers
disable_discard_framebuffer
disable_dxgi_zero_copy_video
disable_es3_gl_context
diff --git a/chromium/gpu/ipc/service/direct_composition_surface_win.cc b/chromium/gpu/ipc/service/direct_composition_surface_win.cc
index 46710ba1e6e..93e0fe4341a 100644
--- a/chromium/gpu/ipc/service/direct_composition_surface_win.cc
+++ b/chromium/gpu/ipc/service/direct_composition_surface_win.cc
@@ -1712,10 +1712,12 @@ bool DirectCompositionSurfaceWin::AreOverlaysSupported() {
InitializeHardwareOverlaySupport();
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kDisableDirectCompositionLayers))
- return false;
+ // Enable flag should be checked before the disable flag, so we could
+ // overwrite GPU driver bug workarounds in testing.
if (command_line->HasSwitch(switches::kEnableDirectCompositionLayers))
return true;
+ if (command_line->HasSwitch(switches::kDisableDirectCompositionLayers))
+ return false;
return g_supports_overlays;
}
diff --git a/chromium/ios/chrome/browser/ui/location_bar/BUILD.gn b/chromium/ios/chrome/browser/ui/location_bar/BUILD.gn
index eb17e1e24a9..d8d864392e6 100644
--- a/chromium/ios/chrome/browser/ui/location_bar/BUILD.gn
+++ b/chromium/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -40,6 +40,7 @@ source_set("location_bar") {
"//ios/chrome/browser/autocomplete",
"//ios/chrome/browser/browser_state:browser_state",
"//ios/chrome/browser/geolocation:geolocation_internal",
+ "//ios/chrome/browser/ntp",
"//ios/chrome/browser/search_engines",
"//ios/chrome/browser/ssl",
"//ios/chrome/browser/ui",
diff --git a/chromium/ios/chrome/browser/ui/orchestrator/BUILD.gn b/chromium/ios/chrome/browser/ui/orchestrator/BUILD.gn
index aa10b06225c..d7b2a2f891b 100644
--- a/chromium/ios/chrome/browser/ui/orchestrator/BUILD.gn
+++ b/chromium/ios/chrome/browser/ui/orchestrator/BUILD.gn
@@ -13,6 +13,7 @@ source_set("orchestrator") {
"toolbar_animatee.h",
]
deps = [
+ "//base",
"//ios/chrome/common:timing",
]
libs = [ "UIKit.framework" ]
diff --git a/chromium/ios/chrome/browser/ui/safe_mode/BUILD.gn b/chromium/ios/chrome/browser/ui/safe_mode/BUILD.gn
index a98d75fb404..8bd15874c19 100644
--- a/chromium/ios/chrome/browser/ui/safe_mode/BUILD.gn
+++ b/chromium/ios/chrome/browser/ui/safe_mode/BUILD.gn
@@ -57,6 +57,7 @@ source_set("unit_tests") {
deps = [
":safe_mode",
"//base",
+ "//base/test:test_support",
"//ios/chrome/browser/crash_report",
"//ios/chrome/test/base",
"//ios/chrome/test/ocmock",
diff --git a/chromium/ios/chrome/browser/web/BUILD.gn b/chromium/ios/chrome/browser/web/BUILD.gn
index fd24fcae9e8..b98ca5950b3 100644
--- a/chromium/ios/chrome/browser/web/BUILD.gn
+++ b/chromium/ios/chrome/browser/web/BUILD.gn
@@ -40,6 +40,7 @@ source_set("web") {
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state",
+ "//ios/chrome/browser/ntp",
"//ios/chrome/browser/snapshots",
"//ios/chrome/browser/ui",
"//ios/chrome/browser/ui/commands:commands",
@@ -105,7 +106,9 @@ source_set("unit_tests") {
"//components/search_engines",
"//components/services/unzip/public/interfaces",
"//components/strings:components_strings_grit",
+ "//ios/chrome/browser",
"//ios/chrome/browser/browser_state:test_support",
+ "//ios/chrome/browser/ntp",
"//ios/chrome/browser/snapshots",
"//ios/chrome/test:test_support",
"//ios/web",
diff --git a/chromium/media/base/audio_renderer_mixer_input.cc b/chromium/media/base/audio_renderer_mixer_input.cc
index f8444b49c8e..ee04a4677a7 100644
--- a/chromium/media/base/audio_renderer_mixer_input.cc
+++ b/chromium/media/base/audio_renderer_mixer_input.cc
@@ -16,6 +16,12 @@
namespace media {
+// TODO(dalecurtis): Merge with AudioDeviceDescription::IsDefaultDevice() once
+// that file has been moved to media/base.
+bool IsDefaultDevice(const std::string& device_id) {
+ return device_id.empty() || device_id == "default";
+}
+
AudioRendererMixerInput::AudioRendererMixerInput(
AudioRendererMixerPool* mixer_pool,
int owner_id,
@@ -37,6 +43,11 @@ AudioRendererMixerInput::~AudioRendererMixerInput() {
DCHECK(!mixer_);
if (sink_)
sink_->Stop();
+
+ // Because GetOutputDeviceInfoAsync() and SwitchOutputDevice() both use
+ // base::RetainedRef, it should be impossible to get here with these set.
+ DCHECK(!pending_device_info_cb_);
+ DCHECK(!pending_switch_cb_);
}
void AudioRendererMixerInput::Initialize(
@@ -124,6 +135,14 @@ void AudioRendererMixerInput::GetOutputDeviceInfoAsync(
return;
}
+ if (switch_output_device_in_progress_) {
+ DCHECK(!godia_in_progress_);
+ pending_device_info_cb_ = std::move(info_cb);
+ return;
+ }
+
+ godia_in_progress_ = true;
+
// We may have |device_info_|, but a Stop() has been called since if we don't
// have a |sink_| or a |mixer_|, so request the information again in case it
// has changed (which may occur due to browser side device changes).
@@ -151,11 +170,29 @@ bool AudioRendererMixerInput::CurrentThreadIsRenderingThread() {
void AudioRendererMixerInput::SwitchOutputDevice(
const std::string& device_id,
OutputDeviceStatusCB callback) {
- if (device_id == device_id_) {
+ // If a GODIA() call is in progress, defer until it's complete.
+ if (godia_in_progress_) {
+ DCHECK(!switch_output_device_in_progress_);
+
+ // Abort any previous device switch which may be pending.
+ if (pending_switch_cb_)
+ std::move(pending_switch_cb_).Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
+
+ pending_device_id_ = device_id;
+ pending_switch_cb_ = std::move(callback);
+ return;
+ }
+
+ // Some pages send "default" instead of the spec compliant empty string for
+ // the default device. Short circuit these here to avoid busy work.
+ if (device_id == device_id_ ||
+ (IsDefaultDevice(device_id_) && IsDefaultDevice(device_id))) {
std::move(callback).Run(OUTPUT_DEVICE_STATUS_OK);
return;
}
+ switch_output_device_in_progress_ = true;
+
// Request a new sink using the new device id. This process may fail, so to
// avoid interrupting working audio, don't set any class variables until we
// know it's a success.
@@ -200,17 +237,36 @@ void AudioRendererMixerInput::OnRenderError() {
void AudioRendererMixerInput::OnDeviceInfoReceived(
OutputDeviceInfoCB info_cb,
OutputDeviceInfo device_info) {
+ DCHECK(godia_in_progress_);
+ godia_in_progress_ = false;
+
device_info_ = device_info;
std::move(info_cb).Run(*device_info_);
+
+ // Complete any pending SwitchOutputDevice() if needed. We don't post this to
+ // ensure we don't reorder calls relative to what the page is expecting. I.e.,
+ // if we post we could end up with Switch(1) -> Switch(2) ending on Switch(1).
+ if (!pending_switch_cb_)
+ return;
+ SwitchOutputDevice(std::move(pending_device_id_),
+ std::move(pending_switch_cb_));
}
void AudioRendererMixerInput::OnDeviceSwitchReady(
OutputDeviceStatusCB switch_cb,
scoped_refptr<AudioRendererSink> sink,
OutputDeviceInfo device_info) {
+ DCHECK(switch_output_device_in_progress_);
+ switch_output_device_in_progress_ = false;
+
if (device_info.device_status() != OUTPUT_DEVICE_STATUS_OK) {
sink->Stop();
std::move(switch_cb).Run(device_info.device_status());
+
+ // Start any pending device info request.
+ if (pending_device_info_cb_)
+ GetOutputDeviceInfoAsync(std::move(pending_device_info_cb_));
+
return;
}
@@ -233,6 +289,10 @@ void AudioRendererMixerInput::OnDeviceSwitchReady(
}
std::move(switch_cb).Run(device_info.device_status());
+
+ // Start any pending device info request.
+ if (pending_device_info_cb_)
+ GetOutputDeviceInfoAsync(std::move(pending_device_info_cb_));
}
} // namespace media
diff --git a/chromium/media/base/audio_renderer_mixer_input.h b/chromium/media/base/audio_renderer_mixer_input.h
index bfbaa16e348..0e47c24d9b8 100644
--- a/chromium/media/base/audio_renderer_mixer_input.h
+++ b/chromium/media/base/audio_renderer_mixer_input.h
@@ -115,6 +115,23 @@ class MEDIA_EXPORT AudioRendererMixerInput
// Source of audio data which is provided to the mixer.
AudioRendererSink::RenderCallback* callback_ = nullptr;
+ // SwitchOutputDevice() and GetOutputDeviceInfoAsync() must be mutually
+ // exclusive when executing; these flags indicate whether one or the other is
+ // in progress. Each method will use the other method's to defer its action.
+ bool godia_in_progress_ = false;
+ bool switch_output_device_in_progress_ = false;
+
+ // Set by GetOutputDeviceInfoAsync() if a SwitchOutputDevice() call is in
+ // progress. GetOutputDeviceInfoAsync() will be invoked again with this value
+ // once OnDeviceSwitchReady() from the SwitchOutputDevice() call completes.
+ OutputDeviceInfoCB pending_device_info_cb_;
+
+ // Set by SwitchOutputDevice() if a GetOutputDeviceInfoAsync() call is in
+ // progress. SwitchOutputDevice() will be invoked again with these values once
+ // the OnDeviceInfoReceived() from the GODIA() call completes.
+ std::string pending_device_id_;
+ OutputDeviceStatusCB pending_switch_cb_;
+
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerInput);
};
diff --git a/chromium/media/base/audio_renderer_mixer_input_unittest.cc b/chromium/media/base/audio_renderer_mixer_input_unittest.cc
index f42decfd562..e1606f9ec6a 100644
--- a/chromium/media/base/audio_renderer_mixer_input_unittest.cc
+++ b/chromium/media/base/audio_renderer_mixer_input_unittest.cc
@@ -19,6 +19,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using testing::_;
+
namespace {
void LogUma(int value) {}
}
@@ -92,6 +94,7 @@ class AudioRendererMixerInputTest : public testing::Test,
MOCK_METHOD1(ReturnMixer, void(AudioRendererMixer*));
MOCK_METHOD1(SwitchCallbackCalled, void(OutputDeviceStatus));
+ MOCK_METHOD1(OnDeviceInfoReceived, void(OutputDeviceInfo));
void SwitchCallback(base::RunLoop* loop, OutputDeviceStatus result) {
SwitchCallbackCalled(result);
@@ -321,4 +324,129 @@ TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceBeforeInitialize) {
mixer_input_->Stop();
}
+// Test that calling SwitchOutputDevice() before
+// GetOutputDeviceInfoAsync() works correctly.
+TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceBeforeGODIA) {
+ mixer_input_->Stop();
+ mixer_input_ = new AudioRendererMixerInput(
+ this, kRenderFrameId, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
+
+ base::RunLoop run_loop;
+ EXPECT_CALL(*this, SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_OK));
+ mixer_input_->SwitchOutputDevice(
+ kAnotherDeviceId,
+ base::BindOnce(&AudioRendererMixerInputTest::SwitchCallback,
+ base::Unretained(this), &run_loop));
+ run_loop.Run();
+ mixer_input_->Stop();
+}
+
+// Test that calling SwitchOutputDevice() during an ongoing
+// GetOutputDeviceInfoAsync() call works correctly.
+TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceDuringGODIA) {
+ mixer_input_->Stop();
+ mixer_input_ = new AudioRendererMixerInput(
+ this, kRenderFrameId, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
+
+ mixer_input_->GetOutputDeviceInfoAsync(
+ base::BindOnce(&AudioRendererMixerInputTest::OnDeviceInfoReceived,
+ base::Unretained(this)));
+ mixer_input_->SwitchOutputDevice(
+ kAnotherDeviceId,
+ base::BindOnce(&AudioRendererMixerInputTest::SwitchCallbackCalled,
+ base::Unretained(this)));
+ {
+ // Verify that first the GODIA call returns, then the SwitchOutputDevice().
+ testing::InSequence sequence_required;
+ OutputDeviceInfo info;
+ constexpr auto kExpectedStatus = OUTPUT_DEVICE_STATUS_OK;
+ EXPECT_CALL(*this, OnDeviceInfoReceived(_))
+ .WillOnce(testing::SaveArg<0>(&info));
+ EXPECT_CALL(*this, SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_OK));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(kExpectedStatus, info.device_status());
+ EXPECT_EQ(kDefaultDeviceId, info.device_id());
+ }
+
+ mixer_input_->Stop();
+}
+
+// Test that calling GetOutputDeviceInfoAsync() during an ongoing
+// SwitchOutputDevice() call works correctly.
+TEST_F(AudioRendererMixerInputTest, GODIADuringSwitchOutputDevice) {
+ mixer_input_->Stop();
+ mixer_input_ = new AudioRendererMixerInput(
+ this, kRenderFrameId, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
+
+ mixer_input_->SwitchOutputDevice(
+ kAnotherDeviceId,
+ base::BindOnce(&AudioRendererMixerInputTest::SwitchCallbackCalled,
+ base::Unretained(this)));
+ mixer_input_->GetOutputDeviceInfoAsync(
+ base::BindOnce(&AudioRendererMixerInputTest::OnDeviceInfoReceived,
+ base::Unretained(this)));
+
+ {
+ // Verify that first the SwitchOutputDevice call returns, then the GODIA().
+ testing::InSequence sequence_required;
+ EXPECT_CALL(*this, SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_OK));
+ OutputDeviceInfo info;
+ constexpr auto kExpectedStatus = OUTPUT_DEVICE_STATUS_OK;
+ EXPECT_CALL(*this, OnDeviceInfoReceived(_))
+ .WillOnce(testing::SaveArg<0>(&info));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(kExpectedStatus, info.device_status());
+ EXPECT_EQ(kAnotherDeviceId, info.device_id());
+ }
+
+ mixer_input_->Stop();
+}
+
+// Test that calling GetOutputDeviceInfoAsync() during an ongoing
+// SwitchOutputDevice() call which eventually fails works correctly.
+TEST_F(AudioRendererMixerInputTest, GODIADuringSwitchOutputDeviceWhichFails) {
+ mixer_input_->Stop();
+ mixer_input_ = new AudioRendererMixerInput(
+ this, kRenderFrameId, kDefaultDeviceId, AudioLatency::LATENCY_PLAYBACK);
+
+ mixer_input_->SwitchOutputDevice(
+ kNonexistentDeviceId,
+ base::BindOnce(&AudioRendererMixerInputTest::SwitchCallbackCalled,
+ base::Unretained(this)));
+ mixer_input_->GetOutputDeviceInfoAsync(
+ base::BindOnce(&AudioRendererMixerInputTest::OnDeviceInfoReceived,
+ base::Unretained(this)));
+
+ {
+ // Verify that first the SwitchOutputDevice call returns, then the GODIA().
+ testing::InSequence sequence_required;
+ EXPECT_CALL(*this,
+ SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND));
+ OutputDeviceInfo info;
+ constexpr auto kExpectedStatus = OUTPUT_DEVICE_STATUS_OK;
+ EXPECT_CALL(*this, OnDeviceInfoReceived(_))
+ .WillOnce(testing::SaveArg<0>(&info));
+ scoped_task_environment_.RunUntilIdle();
+ EXPECT_EQ(kExpectedStatus, info.device_status());
+ EXPECT_EQ(kDefaultDeviceId, info.device_id());
+ }
+
+ mixer_input_->Stop();
+}
+
+// Test that calling SwitchOutputDevice() with an empty device id does nothing
+// when we're already on the default device.
+TEST_F(AudioRendererMixerInputTest, SwitchOutputDeviceEmptyDeviceId) {
+ EXPECT_CALL(*this, SwitchCallbackCalled(OUTPUT_DEVICE_STATUS_OK));
+ mixer_input_->SwitchOutputDevice(
+ std::string(),
+ base::BindOnce(&AudioRendererMixerInputTest::SwitchCallbackCalled,
+ base::Unretained(this)));
+
+ // No RunUntilIdle() since switch should immediately return success.
+ testing::Mock::VerifyAndClear(this);
+
+ mixer_input_->Stop();
+}
+
} // namespace media
diff --git a/chromium/media/base/media_switches.cc b/chromium/media/base/media_switches.cc
index 5a9a768a8e1..17b0e22c5eb 100644
--- a/chromium/media/base/media_switches.cc
+++ b/chromium/media/base/media_switches.cc
@@ -471,9 +471,16 @@ const base::Feature kPreloadMediaEngagementData{
const base::Feature kMediaLearningExperiment{"MediaLearningExperiment",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables flash to be ducked by audio focus.
-const base::Feature kAudioFocusDuckFlash{"AudioFocusDuckFlash",
- base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables flash to be ducked by audio focus. This is enabled on Chrome OS which
+// has audio focus enabled.
+const base::Feature kAudioFocusDuckFlash {
+ "AudioFocusDuckFlash",
+#if defined(OS_CHROMEOS)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
// Enables the internal Media Session logic without enabling the Media Session
// service.
diff --git a/chromium/media/blink/webmediaplayer_impl.cc b/chromium/media/blink/webmediaplayer_impl.cc
index a25744ab843..442800b8a20 100644
--- a/chromium/media/blink/webmediaplayer_impl.cc
+++ b/chromium/media/blink/webmediaplayer_impl.cc
@@ -1714,7 +1714,24 @@ void WebMediaPlayerImpl::OnError(PipelineStatus status) {
// URL, since MediaPlayer doesn't support data:// URLs, fail playback now.
const bool found_hls = status == PipelineStatus::DEMUXER_ERROR_DETECTED_HLS;
if (found_hls && mb_data_source_) {
- demuxer_found_hls_ = found_hls;
+ UMA_HISTOGRAM_BOOLEAN("Media.WebMediaPlayerImpl.HLS.IsCorsCrossOrigin",
+ mb_data_source_->IsCorsCrossOrigin());
+ // Note: Does not consider the full redirect chain. Redirecting through
+ // another origin will set WouldTaintOrigin() though, assuming that the
+ // crossorigin attribute is not set.
+ bool frame_url_is_cryptographic = url::Origin(frame_->GetSecurityOrigin())
+ .GetURL()
+ .SchemeIsCryptographic();
+ bool manifest_url_is_cryptographic =
+ loaded_url_.SchemeIsCryptographic() &&
+ mb_data_source_->GetUrlAfterRedirects().SchemeIsCryptographic();
+ UMA_HISTOGRAM_BOOLEAN(
+ "Media.WebMediaPlayerImpl.HLS.IsMixedContent",
+ frame_url_is_cryptographic && !manifest_url_is_cryptographic);
+ UMA_HISTOGRAM_BOOLEAN("Media.WebMediaPlayerImpl.HLS.WouldTaintOrigin",
+ WouldTaintOrigin());
+ // Note: Affects WouldTaintOrigin().
+ demuxer_found_hls_ = true;
renderer_factory_selector_->SetUseMediaPlayer(true);
@@ -2674,8 +2691,9 @@ void WebMediaPlayerImpl::StartPipeline() {
BindToCurrentLoop(base::BindOnce(
&WebMediaPlayerImpl::OnFirstFrame, AsWeakPtr()))));
- if (renderer_factory_selector_->GetCurrentFactory()
- ->GetRequiredMediaResourceType() == MediaResource::Type::URL) {
+ if (demuxer_found_hls_ ||
+ renderer_factory_selector_->GetCurrentFactory()
+ ->GetRequiredMediaResourceType() == MediaResource::Type::URL) {
// MediaPlayerRendererClient factory is the only factory that a
// MediaResource::Type::URL for the moment. This might no longer be true
// when we remove WebMediaPlayerCast.
diff --git a/chromium/media/gpu/accelerated_video_decoder.h b/chromium/media/gpu/accelerated_video_decoder.h
index fb7acd82a36..ee9dc93ee26 100644
--- a/chromium/media/gpu/accelerated_video_decoder.h
+++ b/chromium/media/gpu/accelerated_video_decoder.h
@@ -66,13 +66,11 @@ class MEDIA_GPU_EXPORT AcceleratedVideoDecoder {
// we need a new set of them, or when an error occurs.
virtual DecodeResult Decode() WARN_UNUSED_RESULT = 0;
- // Return dimensions/required number of pictures that client should be ready
- // to provide for the decoder to function properly (of which up to
- // GetNumReferenceFrames() might be needed for internal decoding). To be used
- // after Decode() returns kAllocateNewSurfaces.
+ // Return dimensions/required number of output surfaces that client should
+ // be ready to provide for the decoder to function properly.
+ // To be used after Decode() returns kAllocateNewSurfaces.
virtual gfx::Size GetPicSize() const = 0;
virtual size_t GetRequiredNumOfPictures() const = 0;
- virtual size_t GetNumReferenceFrames() const = 0;
// About 3 secs for 30 fps video. When the new sized keyframe is missed, the
// decoder cannot decode the frame. The number of frames are skipped until
diff --git a/chromium/media/gpu/h264_decoder.cc b/chromium/media/gpu/h264_decoder.cc
index 0fa017971f5..cc2450ba2b7 100644
--- a/chromium/media/gpu/h264_decoder.cc
+++ b/chromium/media/gpu/h264_decoder.cc
@@ -1418,17 +1418,7 @@ gfx::Size H264Decoder::GetPicSize() const {
}
size_t H264Decoder::GetRequiredNumOfPictures() const {
- constexpr size_t kPicsInPipeline = limits::kMaxVideoFrames + 1;
- return GetNumReferenceFrames() + kPicsInPipeline;
-}
-
-size_t H264Decoder::GetNumReferenceFrames() const {
- // Use the maximum number of pictures in the Decoded Picture Buffer plus one
- // for the one being currently egressed.
- // Another +1 is experimentally needed for high-to-high resolution changes.
- // TODO(mcasas): Figure out why +2 instead of +1, see crbug.com/909926 and
- // http://crrev.com/c/1363807/9/media/gpu/h264_decoder.cc#1449.
- return dpb_.max_num_pics() + 2;
+ return dpb_.max_num_pics() + kPicsInPipeline;
}
// static
diff --git a/chromium/media/gpu/h264_decoder.h b/chromium/media/gpu/h264_decoder.h
index 66bb08917ed..1b2afd5aec6 100644
--- a/chromium/media/gpu/h264_decoder.h
+++ b/chromium/media/gpu/h264_decoder.h
@@ -160,7 +160,6 @@ class MEDIA_GPU_EXPORT H264Decoder : public AcceleratedVideoDecoder {
DecodeResult Decode() override WARN_UNUSED_RESULT;
gfx::Size GetPicSize() const override;
size_t GetRequiredNumOfPictures() const override;
- size_t GetNumReferenceFrames() const override;
// Return true if we need to start a new picture.
static bool IsNewPrimaryCodedPicture(const H264Picture* curr_pic,
@@ -175,6 +174,17 @@ class MEDIA_GPU_EXPORT H264Decoder : public AcceleratedVideoDecoder {
H264Picture* pic);
private:
+ // We need to keep at most kDPBMaxSize pictures in DPB for
+ // reference/to display later and an additional one for the one currently
+ // being decoded. We also ask for some additional ones since VDA needs
+ // to accumulate a few ready-to-output pictures before it actually starts
+ // displaying and giving them back. +2 instead of +1 because of subjective
+ // smoothness improvement during testing.
+ enum {
+ kPicsInPipeline = limits::kMaxVideoFrames + 2,
+ kMaxNumReqPictures = H264DPB::kDPBMaxSize + kPicsInPipeline,
+ };
+
// Internal state of the decoder.
enum State {
// After initialization, need an SPS.
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
index 9d7842d6b9d..bf127150b5b 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
+++ b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -16,7 +16,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
-#include "base/numerics/ranges.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
@@ -74,8 +73,8 @@ void CloseGpuMemoryBufferHandle(const gfx::GpuMemoryBufferHandle& handle) {
}
#endif
-// Returns true if the CPU is an Intel Kaby/Gemini/Sky Lake or later.
-// Cpu platform id's are referenced from the following file in kernel source
+// Returns true if the CPU is an Intel Kaby Lake or later.
+// cpu platform id's are referenced from the following file in kernel source
// arch/x86/include/asm/intel-family.h
bool IsKabyLakeOrLater() {
constexpr int kPentiumAndLaterFamily = 0x06;
@@ -86,6 +85,7 @@ bool IsKabyLakeOrLater() {
cpuid.model() >= kFirstKabyLakeModelId;
return is_kaby_lake_or_later;
}
+
bool IsGeminiLakeOrLater() {
constexpr int kPentiumAndLaterFamily = 0x06;
constexpr int kGeminiLakeModelId = 0x7A;
@@ -95,16 +95,8 @@ bool IsGeminiLakeOrLater() {
cpuid.model() >= kGeminiLakeModelId;
return is_geminilake_or_later;
}
-bool IsSkyLakeOrLater() {
- constexpr int kPentiumAndLaterFamily = 0x06;
- constexpr int kFirstSkyLakeModelId = 0x4E;
- static base::CPU cpuid;
- static bool is_sky_lake_or_later = cpuid.family() == kPentiumAndLaterFamily &&
- cpuid.model() >= kFirstSkyLakeModelId;
- return is_sky_lake_or_later;
-}
-// Decides if the current platform and |profile| may decode using the client's
+// Decides if the current platform and profile may decode using the client's
// PictureBuffers, or engage the Vpp to adapt VaApi's and the client's format.
bool ShouldDecodeOnclientPictureBuffers(
VideoDecodeAccelerator::Config::OutputMode output_mode,
@@ -114,14 +106,6 @@ bool ShouldDecodeOnclientPictureBuffers(
profile == VP9PROFILE_PROFILE0;
}
-// Decides if the current platform and |output_mode| may used a reduced number
-// of buffer allocations. See https://crbug.com/920510 for more information.
-bool ShouldUseReducedNumberOfAllocations(
- VideoDecodeAccelerator::Config::OutputMode output_mode) {
- return output_mode == VideoDecodeAccelerator::Config::OutputMode::ALLOCATE &&
- IsSkyLakeOrLater();
-}
-
} // namespace
#define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \
@@ -190,14 +174,11 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
vaapi_picture_factory_(new VaapiPictureFactory()),
surfaces_available_(&lock_),
decode_using_client_picture_buffers_(false),
- use_reduced_number_of_allocations_(false),
task_runner_(base::ThreadTaskRunnerHandle::Get()),
decoder_thread_("VaapiDecoderThread"),
finish_flush_pending_(false),
awaiting_va_surfaces_recycle_(false),
requested_num_pics_(0),
- requested_num_reference_frames_(0),
- previously_requested_num_reference_frames_(0),
profile_(VIDEO_CODEC_PROFILE_UNKNOWN),
make_context_current_cb_(make_context_current_cb),
bind_image_cb_(bind_image_cb),
@@ -269,10 +250,6 @@ bool VaapiVideoDecodeAccelerator::Initialize(const Config& config,
output_mode_ = config.output_mode;
decode_using_client_picture_buffers_ =
ShouldDecodeOnclientPictureBuffers(output_mode_, profile_);
- use_reduced_number_of_allocations_ =
- !decode_using_client_picture_buffers_ &&
- ShouldUseReducedNumberOfAllocations(output_mode_);
- previously_requested_num_reference_frames_ = 0;
return true;
}
@@ -501,8 +478,7 @@ void VaapiVideoDecodeAccelerator::DecodeTask() {
FROM_HERE,
base::Bind(&VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange,
weak_this_, decoder_->GetRequiredNumOfPictures(),
- decoder_->GetPicSize(),
- decoder_->GetNumReferenceFrames()));
+ decoder_->GetPicSize()));
// We'll get rescheduled once ProvidePictureBuffers() finishes.
return;
@@ -539,37 +515,23 @@ void VaapiVideoDecodeAccelerator::DecodeTask() {
}
}
-void VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange(
- size_t num_pics,
- gfx::Size size,
- size_t num_reference_frames) {
+void VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange(size_t num_pics,
+ gfx::Size size) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!awaiting_va_surfaces_recycle_);
- DCHECK_GT(num_pics, num_reference_frames);
// At this point decoder has stopped running and has already posted onto our
// loop any remaining output request callbacks, which executed before we got
- // here. Some of them might have been pended though, because we might not have
- // had enough PictureBuffers to output surfaces to. Initiate a wait cycle,
+ // here. Some of them might have been pended though, because we might not
+ // have had enough TFPictures to output surfaces to. Initiate a wait cycle,
// which will wait for client to return enough PictureBuffers to us, so that
// we can finish all pending output callbacks, releasing associated surfaces.
+ VLOGF(2) << "Initiating surface set change";
awaiting_va_surfaces_recycle_ = true;
+ requested_num_pics_ = num_pics;
requested_pic_size_ = size;
- // If we can |use_reduced_number_of_allocations_|, split the requested
- // |num_pics| between VA reference frames and client PictureBuffers proper.
- if (use_reduced_number_of_allocations_)
- requested_num_reference_frames_ = num_reference_frames;
- else
- requested_num_reference_frames_ = 0;
-
- requested_num_pics_ = num_pics - requested_num_reference_frames_;
-
- VLOGF(2) << " |requested_num_pics_| = " << requested_num_pics_
- << "; |requested_num_reference_frames_| = "
- << requested_num_reference_frames_;
-
TryFinishSurfaceSetChange();
}
@@ -580,19 +542,14 @@ void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
return;
base::AutoLock auto_lock(lock_);
- const size_t expected_max_available_va_surfaces =
- use_reduced_number_of_allocations_
- ? previously_requested_num_reference_frames_
- : pictures_.size();
-
if (!pending_output_cbs_.empty() ||
- expected_max_available_va_surfaces != available_va_surfaces_.size()) {
- // If we're here the stream resolution has changed; we need to wait until:
- // - all |pending_output_cbs_| have been executed
- // - all VASurfaces are back to |available_va_surfaces_|; we can't use
- // |requested_num_reference_frames_| for comparison, since it might have
- // changed in the previous call to InitiateSurfaceSetChange(), so we use
- // |previously_requested_num_reference_frames_| instead.
+ pictures_.size() != available_va_surfaces_.size()) {
+ // Either:
+ // 1. Not all pending pending output callbacks have been executed yet.
+ // Wait for the client to return enough pictures and retry later.
+ // 2. The above happened and all surface release callbacks have been posted
+ // as the result, but not all have executed yet. Post ourselves after them
+ // to let them release surfaces.
DVLOGF(2) << "Awaiting pending output/surface release callbacks to finish";
task_runner_->PostTask(
FROM_HERE,
@@ -601,8 +558,6 @@ void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
return;
}
- previously_requested_num_reference_frames_ = requested_num_reference_frames_;
-
// All surfaces released, destroy them and dismiss all PictureBuffers.
awaiting_va_surfaces_recycle_ = false;
available_va_surfaces_.clear();
@@ -626,7 +581,6 @@ void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
base::BindOnce(&Client::ProvidePictureBuffers, client_,
requested_num_pics_, format, 1, requested_pic_size_,
vaapi_picture_factory_->GetGLTextureTarget()));
- // |client_| may respond via AssignPictureBuffers().
}
void VaapiVideoDecodeAccelerator::Decode(
@@ -721,19 +675,14 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
RETURN_AND_NOTIFY_ON_FAILURE(
vaapi_wrapper_->CreateContext(va_format, requested_pic_size_),
"Failed creating VA Context", PLATFORM_FAILURE, );
- DCHECK_EQ(va_surface_ids.size(), buffers.size());
} else {
- const size_t requested_num_surfaces = use_reduced_number_of_allocations_
- ? requested_num_reference_frames_
- : pictures_.size();
- CHECK_NE(requested_num_surfaces, 0u);
va_surface_ids.clear();
- RETURN_AND_NOTIFY_ON_FAILURE(vaapi_wrapper_->CreateContextAndSurfaces(
- va_format, requested_pic_size_,
- requested_num_surfaces, &va_surface_ids),
- "Failed creating VA Surfaces",
- PLATFORM_FAILURE, );
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ vaapi_wrapper_->CreateContextAndSurfaces(
+ va_format, requested_pic_size_, buffers.size(), &va_surface_ids),
+ "Failed creating VA Surfaces", PLATFORM_FAILURE, );
}
+ DCHECK_EQ(va_surface_ids.size(), buffers.size());
available_va_surfaces_.assign(va_surface_ids.begin(), va_surface_ids.end());
@@ -1046,12 +995,9 @@ scoped_refptr<VASurface> VaapiVideoDecodeAccelerator::CreateSurface() {
const VASurfaceID id = available_va_surfaces_.front();
available_va_surfaces_.pop_front();
- TRACE_COUNTER_ID2(
- "media,gpu", "Vaapi VASurfaceIDs", this, "used",
- (use_reduced_number_of_allocations_ ? requested_num_reference_frames_
- : pictures_.size()) -
- available_va_surfaces_.size(),
- "available", available_va_surfaces_.size());
+ TRACE_COUNTER_ID2("media,gpu", "Vaapi VASurfaceIDs", this, "used",
+ pictures_.size() - available_va_surfaces_.size(),
+ "available", available_va_surfaces_.size());
return new VASurface(id, requested_pic_size_,
vaapi_wrapper_->va_surface_format(),
@@ -1081,17 +1027,13 @@ scoped_refptr<VASurface> VaapiVideoDecodeAccelerator::CreateSurface() {
void VaapiVideoDecodeAccelerator::RecycleVASurfaceID(
VASurfaceID va_surface_id) {
DCHECK(task_runner_->BelongsToCurrentThread());
-
{
base::AutoLock auto_lock(lock_);
available_va_surfaces_.push_back(va_surface_id);
if (!decode_using_client_picture_buffers_) {
- TRACE_COUNTER_ID2(
- "media,gpu", "Vaapi VASurfaceIDs", this, "used",
- (use_reduced_number_of_allocations_ ? requested_num_reference_frames_
- : pictures_.size()) -
- available_va_surfaces_.size(),
- "available", available_va_surfaces_.size());
+ TRACE_COUNTER_ID2("media,gpu", "Vaapi VASurfaceIDs", this, "used",
+ pictures_.size() - available_va_surfaces_.size(),
+ "available", available_va_surfaces_.size());
}
surfaces_available_.Signal();
}
@@ -1103,7 +1045,7 @@ bool VaapiVideoDecodeAccelerator::OnMemoryDump(
base::trace_event::ProcessMemoryDump* pmd) {
using base::trace_event::MemoryAllocatorDump;
base::AutoLock auto_lock(lock_);
- if (decode_using_client_picture_buffers_ || !requested_num_reference_frames_)
+ if (decode_using_client_picture_buffers_ || pictures_.empty())
return false;
auto dump_name = base::StringPrintf("gpu/vaapi/decoder/0x%" PRIxPTR,
@@ -1118,20 +1060,16 @@ bool VaapiVideoDecodeAccelerator::OnMemoryDump(
const float va_surface_bytes_per_pixel =
va_surface_format == VA_RT_FORMAT_YUV420 ? kNumBytesPerPixelYUV420
: kNumBytesPerPixelYUV420_10bpp;
- // Report |requested_num_surfaces| and the associated memory size. The
- // calculated size is an estimation since we don't know the internal VA
+ // Report |pictures_.size()| and the associated memory size.
+ // The calculated size is an estimation since we don't know the internal VA
// strides, texture compression, headers, etc, but is a good lower boundary.
- const size_t requested_num_surfaces = use_reduced_number_of_allocations_
- ? requested_num_reference_frames_
- : pictures_.size();
- dump->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes,
- static_cast<uint64_t>(requested_num_surfaces *
- requested_pic_size_.GetArea() *
- va_surface_bytes_per_pixel));
+ dump->AddScalar(
+ MemoryAllocatorDump::kNameSize, MemoryAllocatorDump::kUnitsBytes,
+ static_cast<uint64_t>(pictures_.size() * requested_pic_size_.GetArea() *
+ va_surface_bytes_per_pixel));
dump->AddScalar(MemoryAllocatorDump::kNameObjectCount,
MemoryAllocatorDump::kUnitsObjects,
- static_cast<uint64_t>(requested_num_surfaces));
+ static_cast<uint64_t>(pictures_.size()));
return true;
}
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h
index 10c9da07fd2..abc8c527cb8 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h
+++ b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator.h
@@ -178,12 +178,9 @@ class MEDIA_GPU_EXPORT VaapiVideoDecodeAccelerator
// |available_va_surfaces_|
void RecycleVASurfaceID(VASurfaceID va_surface_id);
- // Request a new set of |num_pics| PictureBuffers to be allocated by
- // |client_|. Up to |num_reference_frames| out of |num_pics_| might be needed
- // by |decoder_|.
- void InitiateSurfaceSetChange(size_t num_pics,
- gfx::Size size,
- size_t num_reference_frames);
+ // Initiate wait cycle for surfaces to be released before we release them
+ // and allocate new ones, as requested by the decoder.
+ void InitiateSurfaceSetChange(size_t num_pics, gfx::Size size);
// Check if the surfaces have been released or post ourselves for later.
void TryFinishSurfaceSetChange();
@@ -255,13 +252,9 @@ class MEDIA_GPU_EXPORT VaapiVideoDecodeAccelerator
// Only used on |task_runner_|.
base::queue<base::OnceClosure> pending_output_cbs_;
- // TODO(crbug.com/912295): Enable these two for IMPORT |output_mode_| as well.
// Under some circumstances, we can pass to libva our own VASurfaceIDs to
- // decode onto, which skips one copy. see https://crbug.com/822346.
+ // decode onto, which skips one copy. Only used on |task_runner_|.
bool decode_using_client_picture_buffers_;
- // When |decode_using_client_picture_buffers_| is false and under certain
- // conditions, we can reduce the number of necessary allocated buffers.
- bool use_reduced_number_of_allocations_;
// WeakPtr<> pointing to |this| for use in posting tasks from the decoder
// thread back to the ChildThread. Because the decoder thread is a member of
@@ -296,14 +289,10 @@ class MEDIA_GPU_EXPORT VaapiVideoDecodeAccelerator
// to be returned before we can free them. Only used on |task_runner_|.
bool awaiting_va_surfaces_recycle_;
- // Last requested number/resolution of output PictureBuffers.
+ // Last requested number/resolution of output picture buffers and their
+ // format.
size_t requested_num_pics_;
gfx::Size requested_pic_size_;
- // Max number of reference frames needed by |decoder_|. Only used on
- // |task_runner_| and when |use_reduced_number_of_allocations_| is true.
- size_t requested_num_reference_frames_;
- size_t previously_requested_num_reference_frames_;
-
VideoCodecProfile profile_;
// Callback to make GL context current.
diff --git a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc
index cdd47320824..a3294363198 100644
--- a/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc
+++ b/chromium/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc
@@ -40,7 +40,7 @@ struct TestParams {
constexpr int32_t kBitstreamId = 123;
constexpr size_t kInputSize = 256;
-constexpr size_t kNumPictures = 4;
+constexpr size_t kNumPictures = 2;
const gfx::Size kPictureSize(64, 48);
constexpr size_t kNewNumPictures = 3;
@@ -61,7 +61,6 @@ class MockAcceleratedVideoDecoder : public AcceleratedVideoDecoder {
MOCK_METHOD0(Decode, DecodeResult());
MOCK_CONST_METHOD0(GetPicSize, gfx::Size());
MOCK_CONST_METHOD0(GetRequiredNumOfPictures, size_t());
- MOCK_CONST_METHOD0(GetNumReferenceFrames, size_t());
};
class MockVaapiWrapper : public VaapiWrapper {
@@ -154,8 +153,7 @@ class VaapiVideoDecodeAcceleratorTest : public TestWithParam<TestParams>,
decoder_thread_.Start();
// Don't want to go through a vda_->Initialize() because it binds too many
- // items of the environment. Instead, do all the necessary steps here.
-
+ // items of the environment. Instead, just start the decoder thread.
vda_.decoder_thread_task_runner_ = decoder_thread_.task_runner();
// Plug in all the mocks and ourselves as the |client_|.
@@ -165,15 +163,10 @@ class VaapiVideoDecodeAcceleratorTest : public TestWithParam<TestParams>,
vda_.vpp_vaapi_wrapper_ = mock_vpp_vaapi_wrapper_;
vda_.vaapi_picture_factory_.reset(mock_vaapi_picture_factory_);
- // TODO(crbug.com/917999): add IMPORT mode to test variations.
vda_.output_mode_ = VideoDecodeAccelerator::Config::OutputMode::ALLOCATE;
vda_.decode_using_client_picture_buffers_ =
GetParam().decode_using_client_picture_buffers;
- vda_.use_reduced_number_of_allocations_ =
- !vda_.decode_using_client_picture_buffers_ &&
- vda_.output_mode_ ==
- VideoDecodeAccelerator::Config::OutputMode::ALLOCATE;
vda_.state_ = VaapiVideoDecodeAccelerator::kIdle;
}
@@ -228,9 +221,6 @@ class VaapiVideoDecodeAcceleratorTest : public TestWithParam<TestParams>,
EXPECT_CALL(*mock_decoder_, GetRequiredNumOfPictures())
.WillOnce(Return(num_pictures));
EXPECT_CALL(*mock_decoder_, GetPicSize()).WillOnce(Return(picture_size));
- const size_t kNumReferenceFrames = num_pictures / 2;
- EXPECT_CALL(*mock_decoder_, GetNumReferenceFrames())
- .WillOnce(Return(kNumReferenceFrames));
EXPECT_CALL(*mock_vaapi_wrapper_, DestroyContextAndSurfaces());
if (expect_dismiss_picture_buffers) {
@@ -238,14 +228,8 @@ class VaapiVideoDecodeAcceleratorTest : public TestWithParam<TestParams>,
.Times(num_picture_buffers_to_dismiss);
}
- const size_t expected_num_picture_buffers_requested =
- vda_.use_reduced_number_of_allocations_
- ? num_pictures - kNumReferenceFrames
- : num_pictures;
-
EXPECT_CALL(*this,
- ProvidePictureBuffers(expected_num_picture_buffers_requested, _,
- 1, picture_size, _))
+ ProvidePictureBuffers(num_pictures, _, 1, picture_size, _))
.WillOnce(RunClosure(quit_closure));
base::SharedMemoryHandle handle;
@@ -279,18 +263,17 @@ class VaapiVideoDecodeAcceleratorTest : public TestWithParam<TestParams>,
MockCreateVaapiPicture(mock_vaapi_wrapper_.get(), picture_size))
.Times(num_pictures);
} else {
- const size_t kNumReferenceFrames = num_pictures / 2;
- EXPECT_CALL(
- *mock_vaapi_wrapper_,
- CreateContextAndSurfaces(_, picture_size, kNumReferenceFrames, _))
+ EXPECT_CALL(*mock_vaapi_wrapper_,
+ CreateContextAndSurfaces(_, picture_size, num_pictures, _))
.WillOnce(DoAll(
- WithArg<3>(Invoke([kNumReferenceFrames](
- std::vector<VASurfaceID>* va_surface_ids) {
- va_surface_ids->resize(kNumReferenceFrames);
- })),
+ WithArg<3>(Invoke(
+ [num_pictures](std::vector<VASurfaceID>* va_surface_ids) {
+ va_surface_ids->resize(num_pictures);
+ })),
Return(true)));
- EXPECT_CALL(*mock_vaapi_picture_factory_,
- MockCreateVaapiPicture(_, picture_size))
+ EXPECT_CALL(
+ *mock_vaapi_picture_factory_,
+ MockCreateVaapiPicture(mock_vpp_vaapi_wrapper_.get(), picture_size))
.Times(num_pictures);
}
diff --git a/chromium/media/gpu/vp8_decoder.cc b/chromium/media/gpu/vp8_decoder.cc
index c86f7182560..33a181d0d4e 100644
--- a/chromium/media/gpu/vp8_decoder.cc
+++ b/chromium/media/gpu/vp8_decoder.cc
@@ -7,10 +7,6 @@
namespace media {
-namespace {
-constexpr size_t kVP8NumFramesActive = 4;
-};
-
VP8Decoder::VP8Accelerator::VP8Accelerator() {}
VP8Decoder::VP8Accelerator::~VP8Accelerator() {}
@@ -169,14 +165,9 @@ gfx::Size VP8Decoder::GetPicSize() const {
}
size_t VP8Decoder::GetRequiredNumOfPictures() const {
- constexpr size_t kPicsInPipeline = limits::kMaxVideoFrames + 1;
+ const size_t kVP8NumFramesActive = 4;
+ const size_t kPicsInPipeline = limits::kMaxVideoFrames + 2;
return kVP8NumFramesActive + kPicsInPipeline;
}
-size_t VP8Decoder::GetNumReferenceFrames() const {
- // Maximum number of reference frames needed plus one for the one being
- // currently egressed.
- return kVP8NumFramesActive + 1;
-}
-
} // namespace media
diff --git a/chromium/media/gpu/vp8_decoder.h b/chromium/media/gpu/vp8_decoder.h
index 8ed398b89f6..f08a8126cf1 100644
--- a/chromium/media/gpu/vp8_decoder.h
+++ b/chromium/media/gpu/vp8_decoder.h
@@ -72,7 +72,6 @@ class MEDIA_GPU_EXPORT VP8Decoder : public AcceleratedVideoDecoder {
DecodeResult Decode() override WARN_UNUSED_RESULT;
gfx::Size GetPicSize() const override;
size_t GetRequiredNumOfPictures() const override;
- size_t GetNumReferenceFrames() const override;
private:
bool DecodeAndOutputCurrentFrame(scoped_refptr<VP8Picture> pic);
diff --git a/chromium/media/gpu/vp9_decoder.cc b/chromium/media/gpu/vp9_decoder.cc
index a8d2f2ac2b6..a16c6a9ea30 100644
--- a/chromium/media/gpu/vp9_decoder.cc
+++ b/chromium/media/gpu/vp9_decoder.cc
@@ -261,14 +261,9 @@ gfx::Size VP9Decoder::GetPicSize() const {
}
size_t VP9Decoder::GetRequiredNumOfPictures() const {
- constexpr size_t kPicsInPipeline = limits::kMaxVideoFrames + 1;
- return kPicsInPipeline + GetNumReferenceFrames();
-}
-
-size_t VP9Decoder::GetNumReferenceFrames() const {
- // Maximum number of reference frames needed plus one for the one being
- // currently egressed.
- return kVp9NumRefFrames + 1;
+ // kMaxVideoFrames to keep higher level media pipeline populated, +2 for the
+ // pictures being parsed and decoded currently.
+ return limits::kMaxVideoFrames + kVp9NumRefFrames + 2;
}
} // namespace media
diff --git a/chromium/media/gpu/vp9_decoder.h b/chromium/media/gpu/vp9_decoder.h
index b4422f0031e..3bf200618d8 100644
--- a/chromium/media/gpu/vp9_decoder.h
+++ b/chromium/media/gpu/vp9_decoder.h
@@ -106,7 +106,6 @@ class MEDIA_GPU_EXPORT VP9Decoder : public AcceleratedVideoDecoder {
DecodeResult Decode() override WARN_UNUSED_RESULT;
gfx::Size GetPicSize() const override;
size_t GetRequiredNumOfPictures() const override;
- size_t GetNumReferenceFrames() const override;
private:
// Update ref_frames_ based on the information in current frame header.
diff --git a/chromium/media/midi/fuzz/corpus/broken_data_1 b/chromium/media/midi/fuzz/corpus/broken_data_1
deleted file mode 100644
index 3818ded670e..00000000000
--- a/chromium/media/midi/fuzz/corpus/broken_data_1
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/broken_data_2 b/chromium/media/midi/fuzz/corpus/broken_data_2
deleted file mode 100644
index 009080e8e0b..00000000000
--- a/chromium/media/midi/fuzz/corpus/broken_data_2
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/broken_data_3 b/chromium/media/midi/fuzz/corpus/broken_data_3
deleted file mode 100644
index eeb2f47d79d..00000000000
--- a/chromium/media/midi/fuzz/corpus/broken_data_3
+++ /dev/null
Binary files differ
diff --git a/chromium/media/midi/fuzz/corpus/channel_pressure b/chromium/media/midi/fuzz/corpus/channel_pressure
deleted file mode 100644
index 8885ddbf6a8..00000000000
--- a/chromium/media/midi/fuzz/corpus/channel_pressure
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/channel_pressure_with_running_status b/chromium/media/midi/fuzz/corpus/channel_pressure_with_running_status
deleted file mode 100644
index 285f9391513..00000000000
--- a/chromium/media/midi/fuzz/corpus/channel_pressure_with_running_status
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/data_byte_0 b/chromium/media/midi/fuzz/corpus/data_byte_0
deleted file mode 100644
index f76dd238ade..00000000000
--- a/chromium/media/midi/fuzz/corpus/data_byte_0
+++ /dev/null
Binary files differ
diff --git a/chromium/media/midi/fuzz/corpus/gm_on b/chromium/media/midi/fuzz/corpus/gm_on
deleted file mode 100644
index 40504f96944..00000000000
--- a/chromium/media/midi/fuzz/corpus/gm_on
+++ /dev/null
@@ -1 +0,0 @@
-~  \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/gm_on_with_real_time_clock b/chromium/media/midi/fuzz/corpus/gm_on_with_real_time_clock
deleted file mode 100644
index e21e736aa84..00000000000
--- a/chromium/media/midi/fuzz/corpus/gm_on_with_real_time_clock
+++ /dev/null
@@ -1 +0,0 @@
-~  \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/gs_on b/chromium/media/midi/fuzz/corpus/gs_on
deleted file mode 100644
index 2bc453a6d22..00000000000
--- a/chromium/media/midi/fuzz/corpus/gs_on
+++ /dev/null
Binary files differ
diff --git a/chromium/media/midi/fuzz/corpus/mtc_frame b/chromium/media/midi/fuzz/corpus/mtc_frame
deleted file mode 100644
index b39f7915357..00000000000
--- a/chromium/media/midi/fuzz/corpus/mtc_frame
+++ /dev/null
Binary files differ
diff --git a/chromium/media/midi/fuzz/corpus/note_on b/chromium/media/midi/fuzz/corpus/note_on
deleted file mode 100644
index f9fc411c2fe..00000000000
--- a/chromium/media/midi/fuzz/corpus/note_on
+++ /dev/null
@@ -1 +0,0 @@
-< \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/note_on_with_real_time_clock b/chromium/media/midi/fuzz/corpus/note_on_with_real_time_clock
deleted file mode 100644
index 0d8d9bd7f3d..00000000000
--- a/chromium/media/midi/fuzz/corpus/note_on_with_real_time_clock
+++ /dev/null
@@ -1 +0,0 @@
-<< \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/note_on_with_running_status b/chromium/media/midi/fuzz/corpus/note_on_with_running_status
deleted file mode 100644
index 48090e7b44a..00000000000
--- a/chromium/media/midi/fuzz/corpus/note_on_with_running_status
+++ /dev/null
@@ -1 +0,0 @@
-<<< \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/partial_gm_on_1 b/chromium/media/midi/fuzz/corpus/partial_gm_on_1
deleted file mode 100644
index 04f7b5be698..00000000000
--- a/chromium/media/midi/fuzz/corpus/partial_gm_on_1
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/partial_gm_on_2 b/chromium/media/midi/fuzz/corpus/partial_gm_on_2
deleted file mode 100644
index 5d933eb4152..00000000000
--- a/chromium/media/midi/fuzz/corpus/partial_gm_on_2
+++ /dev/null
@@ -1 +0,0 @@
-~  \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/partial_gm_on_3 b/chromium/media/midi/fuzz/corpus/partial_gm_on_3
deleted file mode 100644
index 009080e8e0b..00000000000
--- a/chromium/media/midi/fuzz/corpus/partial_gm_on_3
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/partial_note_on_1 b/chromium/media/midi/fuzz/corpus/partial_note_on_1
deleted file mode 100644
index 9e99dd5ec98..00000000000
--- a/chromium/media/midi/fuzz/corpus/partial_note_on_1
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/partial_note_on_2 b/chromium/media/midi/fuzz/corpus/partial_note_on_2
deleted file mode 100644
index c5fa78456db..00000000000
--- a/chromium/media/midi/fuzz/corpus/partial_note_on_2
+++ /dev/null
@@ -1 +0,0 @@
-< \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/partial_note_on_3 b/chromium/media/midi/fuzz/corpus/partial_note_on_3
deleted file mode 100644
index 16e0e90df08..00000000000
--- a/chromium/media/midi/fuzz/corpus/partial_note_on_3
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/reserved_message_1 b/chromium/media/midi/fuzz/corpus/reserved_message_1
deleted file mode 100644
index 3a6e607aa5a..00000000000
--- a/chromium/media/midi/fuzz/corpus/reserved_message_1
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/reserved_message_1_with_data_bytes b/chromium/media/midi/fuzz/corpus/reserved_message_1_with_data_bytes
deleted file mode 100644
index b780aae2d44..00000000000
--- a/chromium/media/midi/fuzz/corpus/reserved_message_1_with_data_bytes
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/reserved_message_2 b/chromium/media/midi/fuzz/corpus/reserved_message_2
deleted file mode 100644
index bb7d13c5e9a..00000000000
--- a/chromium/media/midi/fuzz/corpus/reserved_message_2
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/system_common_message_tune_request b/chromium/media/midi/fuzz/corpus/system_common_message_tune_request
deleted file mode 100644
index f7a8cadeb57..00000000000
--- a/chromium/media/midi/fuzz/corpus/system_common_message_tune_request
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/fuzz/corpus/timing_clock b/chromium/media/midi/fuzz/corpus/timing_clock
deleted file mode 100644
index 0022a3ee843..00000000000
--- a/chromium/media/midi/fuzz/corpus/timing_clock
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/chromium/media/midi/midi_manager_alsa.cc b/chromium/media/midi/midi_manager_alsa.cc
index b13df63d200..361d9604482 100644
--- a/chromium/media/midi/midi_manager_alsa.cc
+++ b/chromium/media/midi/midi_manager_alsa.cc
@@ -169,17 +169,18 @@ MidiManagerAlsa::~MidiManagerAlsa() {
// because of SND_SEQ_EVENT_CLIENT_EXIT.
out_client_.reset();
}
-
// Ensure that no task is running any more.
- bool result = service()->task_service()->UnbindInstance();
- CHECK(result);
+ if (!service()->task_service()->UnbindInstance())
+ return;
+
+ // |out_client_| should be reset before UnbindInstance() call to avoid
+ // a deadlock, but other finalization steps should be implemented after the
+ // UnbindInstance() call above, if we need.
}
void MidiManagerAlsa::StartInitialization() {
- if (!service()->task_service()->BindInstance()) {
- NOTREACHED();
+ if (!service()->task_service()->BindInstance())
return CompleteInitialization(Result::INITIALIZATION_ERROR);
- }
// Create client handles and name the clients.
int err;
diff --git a/chromium/media/midi/midi_manager_android.cc b/chromium/media/midi/midi_manager_android.cc
index dee877e07cc..405725a7cad 100644
--- a/chromium/media/midi/midi_manager_android.cc
+++ b/chromium/media/midi/midi_manager_android.cc
@@ -50,18 +50,17 @@ MidiManagerAndroid::MidiManagerAndroid(MidiService* service)
: MidiManager(service) {}
MidiManagerAndroid::~MidiManagerAndroid() {
+ if (!service()->task_service()->UnbindInstance())
+ return;
+
+ // Finalization steps should be implemented after the UnbindInstance() call.
JNIEnv* env = base::android::AttachCurrentThread();
Java_MidiManagerAndroid_stop(env, raw_manager_);
- bool result = service()->task_service()->UnbindInstance();
- CHECK(result);
}
void MidiManagerAndroid::StartInitialization() {
- if (!service()->task_service()->BindInstance()) {
- NOTREACHED();
- CompleteInitialization(Result::INITIALIZATION_ERROR);
- return;
- }
+ if (!service()->task_service()->BindInstance())
+ return CompleteInitialization(Result::INITIALIZATION_ERROR);
JNIEnv* env = base::android::AttachCurrentThread();
diff --git a/chromium/media/midi/midi_manager_mac.cc b/chromium/media/midi/midi_manager_mac.cc
index ecd6e9d46bd..df322462923 100644
--- a/chromium/media/midi/midi_manager_mac.cc
+++ b/chromium/media/midi/midi_manager_mac.cc
@@ -118,9 +118,10 @@ MidiManager* MidiManager::Create(MidiService* service) {
MidiManagerMac::MidiManagerMac(MidiService* service) : MidiManager(service) {}
MidiManagerMac::~MidiManagerMac() {
- bool result = service()->task_service()->UnbindInstance();
- CHECK(result);
+ if (!service()->task_service()->UnbindInstance())
+ return;
+ // Finalization steps should be implemented after the UnbindInstance() call.
// Do not need to dispose |coremidi_input_| and |coremidi_output_| explicitly.
// CoreMIDI automatically disposes them on the client disposal.
base::AutoLock lock(midi_client_lock_);
@@ -129,10 +130,9 @@ MidiManagerMac::~MidiManagerMac() {
}
void MidiManagerMac::StartInitialization() {
- if (!service()->task_service()->BindInstance()) {
- NOTREACHED();
+ if (!service()->task_service()->BindInstance())
return CompleteInitialization(Result::INITIALIZATION_ERROR);
- }
+
service()->task_service()->PostBoundTask(
kClientTaskRunner, base::BindOnce(&MidiManagerMac::InitializeCoreMIDI,
base::Unretained(this)));
diff --git a/chromium/media/midi/midi_manager_unittest.cc b/chromium/media/midi/midi_manager_unittest.cc
index 8bf23625a4a..d7bceb13910 100644
--- a/chromium/media/midi/midi_manager_unittest.cc
+++ b/chromium/media/midi/midi_manager_unittest.cc
@@ -19,8 +19,13 @@
#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "media/midi/midi_service.h"
+#include "media/midi/task_service.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_WIN)
+#include "media/midi/midi_manager_win.h"
+#endif // defined(OS_WIN)
+
namespace midi {
namespace {
@@ -315,40 +320,79 @@ TEST_F(MidiManagerTest, AbortSession) {
run_loop.RunUntilIdle();
}
-#if defined(OS_ANDROID)
-// The test sometimes fails on Android. https://crbug.com/844027
-#define MAYBE_CreatePlatformMidiManager DISABLED_CreatePlatformMidiManager
-#else
-#define MAYBE_CreatePlatformMidiManager CreatePlatformMidiManager
-#endif
-TEST_F(MidiManagerTest, MAYBE_CreatePlatformMidiManager) {
- // SystemMonitor is needed on Windows.
- base::SystemMonitor system_monitor;
+class PlatformMidiManagerTest : public ::testing::Test {
+ public:
+ PlatformMidiManagerTest()
+ : client_(std::make_unique<FakeMidiManagerClient>()),
+ service_(std::make_unique<MidiService>()) {
+ //
+ }
- std::unique_ptr<FakeMidiManagerClient> client =
- std::make_unique<FakeMidiManagerClient>();
+ ~PlatformMidiManagerTest() override {
+ service_->Shutdown();
+ base::RunLoop run_loop;
+ run_loop.RunUntilIdle();
+ }
+
+ MidiService* service() { return service_.get(); }
- // Use own MidiService instance to construct a real platform dependent
- // MidiManager instance.
- std::unique_ptr<MidiService> service = std::make_unique<MidiService>();
- service->StartSession(client.get());
+ void StartSession() { service_->StartSession(client_.get()); }
+ void EndSession() { service_->EndSession(client_.get()); }
+ Result WaitForResult() { return client_->WaitForResult(); }
- Result result = client->WaitForResult();
// This #ifdef needs to be identical to the one in media/midi/midi_manager.cc.
// Do not change the condition for disabling this test.
+ bool IsSupported() {
#if !defined(OS_MACOSX) && !defined(OS_WIN) && \
!(defined(USE_ALSA) && defined(USE_UDEV)) && !defined(OS_ANDROID)
- EXPECT_EQ(Result::NOT_SUPPORTED, result);
-#elif defined(USE_ALSA)
+ return false;
+#else
+ return true;
+#endif
+ }
+
+ private:
+ // SystemMonitor is needed on Windows.
+ base::SystemMonitor system_monitor;
+
+ base::test::ScopedTaskEnvironment env_;
+
+ std::unique_ptr<FakeMidiManagerClient> client_;
+ std::unique_ptr<MidiService> service_;
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformMidiManagerTest);
+};
+
+#if defined(OS_ANDROID)
+// The test sometimes fails on Android. https://crbug.com/844027
+#define MAYBE_CreatePlatformMidiManager DISABLED_CreatePlatformMidiManager
+#else
+#define MAYBE_CreatePlatformMidiManager CreatePlatformMidiManager
+#endif
+TEST_F(PlatformMidiManagerTest, MAYBE_CreatePlatformMidiManager) {
+ StartSession();
+ Result result = WaitForResult();
+
+#if defined(USE_ALSA)
// Temporary until http://crbug.com/371230 is resolved.
EXPECT_TRUE(result == Result::OK || result == Result::INITIALIZATION_ERROR);
#else
- EXPECT_EQ(Result::OK, result);
+ EXPECT_EQ(IsSupported() ? Result::OK : Result::NOT_SUPPORTED, result);
#endif
+}
- service->Shutdown();
- base::RunLoop run_loop;
- run_loop.RunUntilIdle();
+TEST_F(PlatformMidiManagerTest, InstanceIdOverflow) {
+ service()->task_service()->OverflowInstanceIdForTesting();
+#if defined(OS_WIN)
+ MidiManagerWin::OverflowInstanceIdForTesting();
+#endif // defined(OS_WIN)
+
+ StartSession();
+ EXPECT_EQ(
+ IsSupported() ? Result::INITIALIZATION_ERROR : Result::NOT_SUPPORTED,
+ WaitForResult());
+
+ EndSession();
}
} // namespace
diff --git a/chromium/media/midi/midi_manager_usb.cc b/chromium/media/midi/midi_manager_usb.cc
index fc6421e281a..d57f374d8b0 100644
--- a/chromium/media/midi/midi_manager_usb.cc
+++ b/chromium/media/midi/midi_manager_usb.cc
@@ -24,16 +24,16 @@ MidiManagerUsb::MidiManagerUsb(MidiService* service,
: MidiManager(service), device_factory_(std::move(factory)) {}
MidiManagerUsb::~MidiManagerUsb() {
- bool result = service()->task_service()->UnbindInstance();
- CHECK(result);
+ if (!service()->task_service()->UnbindInstance())
+ return;
+
+ // Finalization steps should be implemented after the UnbindInstance() call
+ // above, if we need.
}
void MidiManagerUsb::StartInitialization() {
- if (!service()->task_service()->BindInstance()) {
- NOTREACHED();
- CompleteInitialization(Result::INITIALIZATION_ERROR);
- return;
- }
+ if (!service()->task_service()->BindInstance())
+ return CompleteInitialization(Result::INITIALIZATION_ERROR);
Initialize();
}
diff --git a/chromium/media/midi/midi_manager_win.cc b/chromium/media/midi/midi_manager_win.cc
index 902399f011b..94c5bbc6c1a 100644
--- a/chromium/media/midi/midi_manager_win.cc
+++ b/chromium/media/midi/midi_manager_win.cc
@@ -12,11 +12,13 @@
#include <mmsystem.h>
#include <algorithm>
+#include <limits>
#include <string>
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
+#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
@@ -103,8 +105,8 @@ constexpr size_t kSysExSizeLimit = 256 * 1024;
constexpr size_t kBufferLength = 32 * 1024;
// Global variables to identify MidiManager instance.
-constexpr int kInvalidInstanceId = -1;
-int g_active_instance_id = kInvalidInstanceId;
+constexpr int64_t kInvalidInstanceId = -1;
+int64_t g_active_instance_id = kInvalidInstanceId;
MidiManagerWin* g_manager_instance = nullptr;
// Obtains base::Lock instance pointer to lock instance_id.
@@ -114,8 +116,15 @@ base::Lock* GetInstanceIdLock() {
}
// Issues unique MidiManager instance ID.
-int IssueNextInstanceId() {
- static int id = kInvalidInstanceId;
+int64_t IssueNextInstanceId(base::Optional<int64_t> override_id) {
+ static int64_t id = kInvalidInstanceId;
+ if (override_id) {
+ int64_t result = ++id;
+ id = *override_id;
+ return result;
+ }
+ if (id == std::numeric_limits<int64_t>::max())
+ return kInvalidInstanceId;
return ++id;
}
@@ -686,9 +695,14 @@ MidiManagerWin::PortManager::HandleMidiOutCallback(HMIDIOUT hmo,
}
}
+// static
+void MidiManagerWin::OverflowInstanceIdForTesting() {
+ IssueNextInstanceId(std::numeric_limits<int64_t>::max());
+}
+
MidiManagerWin::MidiManagerWin(MidiService* service)
: MidiManager(service),
- instance_id_(IssueNextInstanceId()),
+ instance_id_(IssueNextInstanceId(base::nullopt)),
port_manager_(std::make_unique<PortManager>()) {
base::AutoLock lock(*GetInstanceIdLock());
CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
@@ -698,6 +712,11 @@ MidiManagerWin::MidiManagerWin(MidiService* service)
}
MidiManagerWin::~MidiManagerWin() {
+ // Initialization failed. Exit without running actual finalization that should
+ // not be needed.
+ if (instance_id_ == kInvalidInstanceId)
+ return;
+
// Unregisters on the I/O thread. OnDevicesChanged() won't be called any more.
CHECK(thread_runner_->BelongsToCurrentThread());
base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
@@ -732,6 +751,9 @@ MidiManagerWin::~MidiManagerWin() {
void MidiManagerWin::StartInitialization() {
{
base::AutoLock lock(*GetInstanceIdLock());
+ if (instance_id_ == kInvalidInstanceId)
+ return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR);
+
CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
g_active_instance_id = instance_id_;
CHECK_EQ(nullptr, g_manager_instance);
diff --git a/chromium/media/midi/midi_manager_win.h b/chromium/media/midi/midi_manager_win.h
index 3516a14364a..978abface10 100644
--- a/chromium/media/midi/midi_manager_win.h
+++ b/chromium/media/midi/midi_manager_win.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/system/system_monitor.h"
+#include "media/midi/midi_export.h"
#include "media/midi/midi_manager.h"
namespace base {
@@ -28,6 +29,8 @@ class MidiManagerWin final
public:
class PortManager;
+ MIDI_EXPORT static void OverflowInstanceIdForTesting();
+
explicit MidiManagerWin(MidiService* service);
~MidiManagerWin() override;
@@ -83,7 +86,7 @@ class MidiManagerWin final
const std::vector<uint8_t>& data);
// Holds an unique instance ID.
- const int instance_id_;
+ const int64_t instance_id_;
// Keeps a TaskRunner for the I/O thread.
scoped_refptr<base::SingleThreadTaskRunner> thread_runner_;
diff --git a/chromium/media/midi/midi_manager_winrt.cc b/chromium/media/midi/midi_manager_winrt.cc
index c1310aa077c..4c0fdedefef 100644
--- a/chromium/media/midi/midi_manager_winrt.cc
+++ b/chromium/media/midi/midi_manager_winrt.cc
@@ -777,8 +777,8 @@ MidiManagerWinrt::MidiManagerWinrt(MidiService* service)
MidiManagerWinrt::~MidiManagerWinrt() {
// Unbind and take a lock to ensure that InitializeOnComRunner should not run
// after here.
- bool result = service()->task_service()->UnbindInstance();
- CHECK(result);
+ if (!service()->task_service()->UnbindInstance())
+ return;
base::AutoLock auto_lock(lazy_init_member_lock_);
service()->task_service()->PostStaticTask(
@@ -788,11 +788,8 @@ MidiManagerWinrt::~MidiManagerWinrt() {
}
void MidiManagerWinrt::StartInitialization() {
- if (!service()->task_service()->BindInstance()) {
- NOTREACHED();
- CompleteInitialization(Result::INITIALIZATION_ERROR);
- return;
- }
+ if (!service()->task_service()->BindInstance())
+ return CompleteInitialization(Result::INITIALIZATION_ERROR);
service()->task_service()->PostBoundTask(
kComTaskRunner, base::BindOnce(&MidiManagerWinrt::InitializeOnComRunner,
diff --git a/chromium/media/midi/task_service.cc b/chromium/media/midi/task_service.cc
index 3bb3baf01b5..4ba79ddbece 100644
--- a/chromium/media/midi/task_service.cc
+++ b/chromium/media/midi/task_service.cc
@@ -4,6 +4,9 @@
#include "media/midi/task_service.h"
+#include <limits>
+
+#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
@@ -12,19 +15,10 @@
namespace midi {
-namespace {
-
-constexpr TaskService::InstanceId kInvalidInstanceId = -1;
-
-} // namespace
-
constexpr TaskService::RunnerId TaskService::kDefaultRunnerId;
+constexpr TaskService::InstanceId TaskService::kInvalidInstanceId;
-TaskService::TaskService()
- : no_tasks_in_flight_cv_(&tasks_in_flight_lock_),
- tasks_in_flight_(0),
- next_instance_id_(0),
- bound_instance_id_(kInvalidInstanceId) {
+TaskService::TaskService() : no_tasks_in_flight_cv_(&tasks_in_flight_lock_) {
DETACH_FROM_SEQUENCE(instance_binding_sequence_checker_);
}
@@ -45,10 +39,17 @@ bool TaskService::BindInstance() {
base::AutoLock lock(lock_);
if (bound_instance_id_ != kInvalidInstanceId)
return false;
- bound_instance_id_ = next_instance_id_++;
+
+ // If the InstanceId reaches to the limit, just fail rather than doing
+ // something nicer for such impractical case.
+ if (std::numeric_limits<InstanceId>::max() == next_instance_id_)
+ return false;
+
+ bound_instance_id_ = ++next_instance_id_;
DCHECK(!default_task_runner_);
default_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+
return true;
}
@@ -58,16 +59,17 @@ bool TaskService::UnbindInstance() {
base::AutoLock lock(lock_);
if (bound_instance_id_ == kInvalidInstanceId)
return false;
+
+ DCHECK_EQ(next_instance_id_, bound_instance_id_);
bound_instance_id_ = kInvalidInstanceId;
DCHECK(default_task_runner_);
default_task_runner_ = nullptr;
}
-
// From now on RunTask will never run any task bound to the instance id.
// But invoked tasks might be still running here. To ensure no task runs on
// quitting this method, wait for all tasks to complete.
- base::AutoLock tasks_in_flight_auto_lock(tasks_in_flight_lock_);
+ base::AutoLock tasks_in_flight_lock(tasks_in_flight_lock_);
// TODO(https://crbug.com/796830): Remove sync operations on the I/O thread.
base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
while (tasks_in_flight_ > 0)
@@ -126,6 +128,10 @@ void TaskService::PostBoundDelayedTask(RunnerId runner_id,
delay);
}
+void TaskService::OverflowInstanceIdForTesting() {
+ next_instance_id_ = std::numeric_limits<InstanceId>::max();
+}
+
scoped_refptr<base::SingleThreadTaskRunner> TaskService::GetTaskRunner(
RunnerId runner_id) {
base::AutoLock lock(lock_);
@@ -154,7 +160,7 @@ void TaskService::RunTask(InstanceId instance_id,
RunnerId runner_id,
base::OnceClosure task) {
{
- base::AutoLock tasks_in_flight_auto_lock(tasks_in_flight_lock_);
+ base::AutoLock tasks_in_flight_lock(tasks_in_flight_lock_);
++tasks_in_flight_;
}
@@ -162,7 +168,7 @@ void TaskService::RunTask(InstanceId instance_id,
std::move(task).Run();
{
- base::AutoLock tasks_in_flight_auto_lock(tasks_in_flight_lock_);
+ base::AutoLock tasks_in_flight_lock(tasks_in_flight_lock_);
--tasks_in_flight_;
DCHECK_GE(tasks_in_flight_, 0);
if (tasks_in_flight_ == 0)
diff --git a/chromium/media/midi/task_service.h b/chromium/media/midi/task_service.h
index 0845b966bdc..4ee02fe3435 100644
--- a/chromium/media/midi/task_service.h
+++ b/chromium/media/midi/task_service.h
@@ -5,13 +5,18 @@
#ifndef MEDIA_MIDI_TASK_SERVICE_H_
#define MEDIA_MIDI_TASK_SERVICE_H_
+#include <memory>
+#include <vector>
+
#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "media/midi/midi_export.h"
@@ -23,7 +28,7 @@ namespace midi {
class MIDI_EXPORT TaskService final {
public:
using RunnerId = size_t;
- using InstanceId = int;
+ using InstanceId = int64_t;
static constexpr RunnerId kDefaultRunnerId = 0;
@@ -36,9 +41,10 @@ class MIDI_EXPORT TaskService final {
// invoked any more.
// Returns true if call is bound or unbound correctly. Otherwise returns
// false, that happens when the BindInstance() is called twice without
- // unbinding the previous instance.
- bool BindInstance();
- bool UnbindInstance();
+ // unbinding the previous instance, or the UnbindInstance() is called without
+ // any successful BindInstance() call.
+ bool BindInstance() WARN_UNUSED_RESULT;
+ bool UnbindInstance() WARN_UNUSED_RESULT;
// Checks if the current thread belongs to the specified runner.
bool IsOnTaskRunner(RunnerId runner_id);
@@ -58,7 +64,11 @@ class MIDI_EXPORT TaskService final {
base::OnceClosure task,
base::TimeDelta delay);
+ void OverflowInstanceIdForTesting();
+
private:
+ static constexpr TaskService::InstanceId kInvalidInstanceId = -1;
+
// Returns a SingleThreadTaskRunner reference. Each TaskRunner will be
// constructed on demand.
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(RunnerId runner_id);
@@ -71,31 +81,32 @@ class MIDI_EXPORT TaskService final {
// Returns true if |instance_id| is equal to |bound_instance_id_|.
bool IsInstanceIdStillBound(InstanceId instance_id);
+ // Holds InstanceId for the next bound instance, accessed on the BindInstance
+ // call thread without any protection.
+ InstanceId next_instance_id_ = kInvalidInstanceId;
+
// Keeps a TaskRunner for the thread that calls BindInstance() as a default
// task runner to run posted tasks.
- scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_
+ GUARDED_BY(lock_);
// Holds threads to host SingleThreadTaskRunners.
- std::vector<std::unique_ptr<base::Thread>> threads_;
+ std::vector<std::unique_ptr<base::Thread>> threads_ GUARDED_BY(lock_);
- // Protects |tasks_in_flight_|.
- base::Lock tasks_in_flight_lock_;
+ // Holds InstanceId for the current bound instance.
+ InstanceId bound_instance_id_ GUARDED_BY(lock_) = kInvalidInstanceId;
+
+ base::Lock lock_;
// Signalled when the number of tasks in flight is 0 and ensures that
// UnbindInstance() does not return until all tasks have completed.
- base::ConditionVariable no_tasks_in_flight_cv_;
+ base::ConditionVariable no_tasks_in_flight_cv_
+ GUARDED_BY(tasks_in_flight_lock_);
// Number of tasks in flight.
- int tasks_in_flight_;
-
- // Holds InstanceId for the next bound instance.
- InstanceId next_instance_id_;
-
- // Holds InstanceId for the current bound instance.
- InstanceId bound_instance_id_;
+ int tasks_in_flight_ GUARDED_BY(tasks_in_flight_lock_) = 0;
- // Protects all members other than |tasks_in_flight_|.
- base::Lock lock_;
+ base::Lock tasks_in_flight_lock_;
// Verifies all UnbindInstance() calls occur on the same sequence as
// BindInstance().
diff --git a/chromium/net/BUILD.gn b/chromium/net/BUILD.gn
index 35012c34cae..43dd5286438 100644
--- a/chromium/net/BUILD.gn
+++ b/chromium/net/BUILD.gn
@@ -474,8 +474,6 @@ component("net") {
"base/network_activity_monitor.h",
"base/network_change_notifier.cc",
"base/network_change_notifier.h",
- "base/network_change_notifier_chromeos.cc",
- "base/network_change_notifier_chromeos.h",
"base/network_change_notifier_factory.h",
"base/network_change_notifier_linux.cc",
"base/network_change_notifier_linux.h",
@@ -1869,6 +1867,13 @@ component("net") {
}
}
+ if (is_android || is_chromeos) {
+ sources += [
+ "base/network_change_notifier_posix.cc",
+ "base/network_change_notifier_posix.h",
+ ]
+ }
+
if (is_win) {
sources -= [
"ntlm/ntlm.cc",
@@ -4774,7 +4779,6 @@ test("net_unittests") {
"base/mime_util_unittest.cc",
"base/net_string_util_unittest.cc",
"base/network_activity_monitor_unittest.cc",
- "base/network_change_notifier_chromeos_unittest.cc",
"base/network_change_notifier_unittest.cc",
"base/network_change_notifier_win_unittest.cc",
"base/network_interfaces_linux_unittest.cc",
@@ -5404,6 +5408,10 @@ test("net_unittests") {
sources += [ "socket/udp_socket_posix_unittest.cc" ]
}
+ if (is_android || is_chromeos) {
+ sources += [ "base/network_change_notifier_posix_unittest.cc" ]
+ }
+
if (enable_reporting) {
sources += [
"network_error_logging/network_error_logging_service_unittest.cc",
diff --git a/chromium/net/android/network_change_notifier_android.h b/chromium/net/android/network_change_notifier_android.h
index b7fcf5897c0..6317acef864 100644
--- a/chromium/net/android/network_change_notifier_android.h
+++ b/chromium/net/android/network_change_notifier_android.h
@@ -75,6 +75,8 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierAndroid
// delegate class.
using NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype;
+ static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsAndroid();
+
protected:
void OnFinalizingMetricsLogRecord() override;
@@ -90,8 +92,6 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierAndroid
explicit NetworkChangeNotifierAndroid(
NetworkChangeNotifierDelegateAndroid* delegate);
- static NetworkChangeCalculatorParams NetworkChangeCalculatorParamsAndroid();
-
NetworkChangeNotifierDelegateAndroid* const delegate_;
std::unique_ptr<DnsConfigServiceThread> dns_config_service_thread_;
bool force_network_handles_supported_for_testing_;
diff --git a/chromium/net/base/load_timing_info.h b/chromium/net/base/load_timing_info.h
index d5df508c7ec..73ff26a9df5 100644
--- a/chromium/net/base/load_timing_info.h
+++ b/chromium/net/base/load_timing_info.h
@@ -58,7 +58,7 @@ namespace net {
// have SSL times. One exception to this is when a proxy server itself returns
// a redirect response. In this case, the connect times treat the proxy as the
// host. The send and receive times will all be null, however.
-// See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
+// See HttpNetworkTransaction::OnHttpsProxyTunnelResponseRedirect.
// TODO(mmenke): Is this worth fixing?
//
struct NET_EXPORT LoadTimingInfo {
diff --git a/chromium/net/base/net_error_list.h b/chromium/net/base/net_error_list.h
index 61fbd8e7c14..b7b7063fc0e 100644
--- a/chromium/net/base/net_error_list.h
+++ b/chromium/net/base/net_error_list.h
@@ -261,9 +261,12 @@ NET_ERROR(NETWORK_ACCESS_DENIED, -138)
NET_ERROR(TEMPORARILY_THROTTLED, -139)
// A request to create an SSL tunnel connection through the HTTPS proxy
-// received a non-200 (OK) and non-407 (Proxy Auth) response. The response
-// body might include a description of why the request failed.
-NET_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE, -140)
+// received a 302 (temporary redirect) response. The response body might
+// include a description of why the request failed.
+//
+// TODO(https://crbug.com/928551): This is deprecated and should not be used by
+// new code.
+NET_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT, -140)
// We were unable to sign the CertificateVerify data of an SSL client auth
// handshake with the client certificate's private key.
diff --git a/chromium/net/base/network_change_notifier.cc b/chromium/net/base/network_change_notifier.cc
index a4c5486a888..55772fc82a6 100644
--- a/chromium/net/base/network_change_notifier.cc
+++ b/chromium/net/base/network_change_notifier.cc
@@ -34,7 +34,7 @@
#elif defined(OS_MACOSX)
#include "net/base/network_change_notifier_mac.h"
#elif defined(OS_CHROMEOS)
-#include "net/base/network_change_notifier_chromeos.h"
+#include "net/base/network_change_notifier_posix.h"
#elif defined(OS_FUCHSIA)
#include "net/base/network_change_notifier_fuchsia.h"
#endif
@@ -213,7 +213,7 @@ NetworkChangeNotifier* NetworkChangeNotifier::Create() {
CHECK(false);
return NULL;
#elif defined(OS_CHROMEOS)
- return new NetworkChangeNotifierChromeos();
+ return new NetworkChangeNotifierPosix(CONNECTION_UNKNOWN, SUBTYPE_UNKNOWN);
#elif defined(OS_LINUX)
return new NetworkChangeNotifierLinux(std::unordered_set<std::string>());
#elif defined(OS_MACOSX)
diff --git a/chromium/net/base/network_change_notifier_chromeos.cc b/chromium/net/base/network_change_notifier_chromeos.cc
deleted file mode 100644
index 6eb948b6a22..00000000000
--- a/chromium/net/base/network_change_notifier_chromeos.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "base/bind.h"
-#include "net/base/network_change_notifier_chromeos.h"
-#include "net/dns/dns_config_service_posix.h"
-
-namespace net {
-
-// DNS config services on Chrome OS are signalled by the network state handler
-// rather than relying on watching files in /etc.
-class NetworkChangeNotifierChromeos::DnsConfigService
- : public net::internal::DnsConfigServicePosix {
- public:
- DnsConfigService() = default;
- ~DnsConfigService() override = default;
-
- // net::internal::DnsConfigService() overrides.
- bool StartWatching() override {
- // DNS config changes are handled and notified by the network
- // state handlers.
- return true;
- }
-
- void OnNetworkChange() {
- InvalidateConfig();
- InvalidateHosts();
- ReadNow();
- }
-};
-
-NetworkChangeNotifierChromeos::NotifierThread::NotifierThread()
- : base::Thread("NetworkChangeNotifier") {
- DETACH_FROM_SEQUENCE(sequence_checker_);
-}
-
-NetworkChangeNotifierChromeos::NotifierThread::~NotifierThread() {
- DCHECK(!Thread::IsRunning());
-}
-
-void NetworkChangeNotifierChromeos::NotifierThread::OnNetworkChange() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- dns_config_service_->OnNetworkChange();
-}
-
-void NetworkChangeNotifierChromeos::NotifierThread::Init() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- dns_config_service_.reset(new DnsConfigService());
- dns_config_service_->WatchConfig(
- base::BindRepeating(&NetworkChangeNotifier::SetDnsConfig));
- dns_config_service_->OnNetworkChange();
-}
-
-void NetworkChangeNotifierChromeos::NotifierThread::CleanUp() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- dns_config_service_.reset();
-}
-
-NetworkChangeNotifierChromeos::NetworkChangeNotifierChromeos()
- : NetworkChangeNotifier(NetworkChangeCalculatorParamsChromeos()),
- connection_type_(CONNECTION_NONE),
- max_bandwidth_mbps_(
- NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
- SUBTYPE_NONE)) {
- notifier_thread_.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
-}
-
-NetworkChangeNotifierChromeos::~NetworkChangeNotifierChromeos() {
- notifier_thread_.Stop();
-}
-
-void NetworkChangeNotifierChromeos::OnDNSChanged() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- // The Unretained thread pointer is ok here because if the thread gets
- // deleted, the callback won't be called.
- notifier_thread_.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(
- &NetworkChangeNotifierChromeos::NotifierThread::OnNetworkChange,
- base::Unretained(&notifier_thread_)));
-}
-
-void NetworkChangeNotifierChromeos::OnIPAddressChanged() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
-}
-
-void NetworkChangeNotifierChromeos::OnConnectionChanged(
- NetworkChangeNotifier::ConnectionType connection_type) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- {
- base::AutoLock scoped_lock(lock_);
- connection_type_ = connection_type;
- }
- NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange();
-}
-
-void NetworkChangeNotifierChromeos::OnConnectionSubtypeChanged(
- NetworkChangeNotifier::ConnectionType connection_type,
- NetworkChangeNotifier::ConnectionSubtype connection_subtype) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- double max_bandwidth_mbps =
- GetMaxBandwidthMbpsForConnectionSubtype(connection_subtype);
- {
- base::AutoLock scoped_lock(lock_);
- max_bandwidth_mbps_ = max_bandwidth_mbps;
- }
- NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps,
- connection_type);
-}
-
-NetworkChangeNotifier::ConnectionType
-NetworkChangeNotifierChromeos::GetCurrentConnectionType() const {
- base::AutoLock scoped_lock(lock_);
- return connection_type_;
-}
-
-void NetworkChangeNotifierChromeos::GetCurrentMaxBandwidthAndConnectionType(
- double* max_bandwidth_mbps,
- ConnectionType* connection_type) const {
- base::AutoLock scoped_lock(lock_);
- *connection_type = connection_type_;
- *max_bandwidth_mbps = max_bandwidth_mbps_;
-}
-
-// static
-NetworkChangeNotifier::NetworkChangeCalculatorParams
-NetworkChangeNotifierChromeos::NetworkChangeCalculatorParamsChromeos() {
- NetworkChangeCalculatorParams params;
- // Delay values arrived at by simple experimentation and adjusted so as to
- // produce a single signal when switching between network connections.
- params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(4000);
- params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(1000);
- params.connection_type_offline_delay_ =
- base::TimeDelta::FromMilliseconds(500);
- params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500);
- return params;
-}
-
-} // namespace net
diff --git a/chromium/net/base/network_change_notifier_chromeos.h b/chromium/net/base/network_change_notifier_chromeos.h
deleted file mode 100644
index 822d3f6cf65..00000000000
--- a/chromium/net/base/network_change_notifier_chromeos.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_BASE_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_
-#define NET_BASE_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_checker.h"
-#include "net/base/net_export.h"
-#include "net/base/network_change_notifier.h"
-
-namespace net {
-
-// A NetworkChangeNotifier that needs to be told about network changes by some
-// other object. This class can't directly listen for network changes because
-// on ChromeOS only objects running in the browser process can listen for
-// network state changes.
-class NET_EXPORT NetworkChangeNotifierChromeos : public NetworkChangeNotifier {
- public:
- NetworkChangeNotifierChromeos();
- ~NetworkChangeNotifierChromeos() override;
-
- // These methods are used to notify this object that a network property has
- // changed. These must be called from the thread that owns this object.
- void OnDNSChanged();
- void OnIPAddressChanged();
- void OnConnectionChanged(
- NetworkChangeNotifier::ConnectionType connection_type);
- void OnConnectionSubtypeChanged(
- NetworkChangeNotifier::ConnectionType connection_type,
- NetworkChangeNotifier::ConnectionSubtype connection_subtype);
-
- protected:
- // NetworkChangeNotifier overrides.
- NetworkChangeNotifier::ConnectionType GetCurrentConnectionType()
- const override;
- void GetCurrentMaxBandwidthAndConnectionType(
- double* max_bandwidth_mbps,
- ConnectionType* connection_type) const override;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(NetworkChangeNotifierChromeosTest,
- ConnectionTypeFromShill);
- friend class NetworkChangeNotifierChromeosTest;
-
- class DnsConfigService;
-
- // Thread on which we can run DnsConfigService, which requires a TYPE_IO
- // message loop.
- class NotifierThread : public base::Thread {
- public:
- NotifierThread();
- ~NotifierThread() override;
-
- void OnNetworkChange();
-
- protected:
- // base::Thread
- void Init() override;
- void CleanUp() override;
-
- private:
- std::unique_ptr<DnsConfigService> dns_config_service_;
- SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(NotifierThread);
- };
-
- // Calculates parameters used for network change notifier online/offline
- // signals.
- static NetworkChangeNotifier::NetworkChangeCalculatorParams
- NetworkChangeCalculatorParamsChromeos();
-
- THREAD_CHECKER(thread_checker_);
-
- mutable base::Lock lock_;
- NetworkChangeNotifier::ConnectionType
- connection_type_; // Guarded by |lock_|.
- double max_bandwidth_mbps_; // Guarded by |lock_|.
-
- NotifierThread notifier_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierChromeos);
-};
-
-} // namespace net
-
-#endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_CHROMEOS_H_
diff --git a/chromium/net/base/network_change_notifier_chromeos_unittest.cc b/chromium/net/base/network_change_notifier_chromeos_unittest.cc
deleted file mode 100644
index 00d7ad234fa..00000000000
--- a/chromium/net/base/network_change_notifier_chromeos_unittest.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/base/network_change_notifier_chromeos.h"
-
-#include "base/test/scoped_task_environment.h"
-#include "net/base/network_change_notifier.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace net {
-
-class NetworkChangeNotifierChromeosTest : public testing::Test {
- public:
- NetworkChangeNotifierChromeosTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
- notifier_(new NetworkChangeNotifierChromeos()) {}
-
- void FastForwardUntilIdle() {
- scoped_task_environment_.FastForwardUntilNoTasksRemain();
- }
-
- NetworkChangeNotifierChromeos* notifier() { return notifier_.get(); }
-
- private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- net::NetworkChangeNotifier::DisableForTest mock_notifier_disabler_;
- std::unique_ptr<NetworkChangeNotifierChromeos> notifier_;
-};
-
-class MockIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver {
- public:
- MOCK_METHOD0(OnIPAddressChanged, void());
-};
-
-TEST_F(NetworkChangeNotifierChromeosTest, OnIPAddressChanged) {
- testing::StrictMock<MockIPAddressObserver> observer;
- NetworkChangeNotifier::AddIPAddressObserver(&observer);
-
- EXPECT_CALL(observer, OnIPAddressChanged());
- notifier()->OnIPAddressChanged();
- FastForwardUntilIdle();
-
- NetworkChangeNotifier::RemoveIPAddressObserver(&observer);
-}
-
-class MockNetworkChangeObserver
- : public NetworkChangeNotifier::NetworkChangeObserver {
- public:
- MOCK_METHOD1(OnNetworkChanged, void(NetworkChangeNotifier::ConnectionType));
-};
-
-TEST_F(NetworkChangeNotifierChromeosTest, OnNetworkChanged) {
- testing::StrictMock<MockNetworkChangeObserver> observer;
- NetworkChangeNotifier::AddNetworkChangeObserver(&observer);
-
- EXPECT_CALL(observer,
- OnNetworkChanged(NetworkChangeNotifier::CONNECTION_NONE));
- EXPECT_CALL(observer, OnNetworkChanged(NetworkChangeNotifier::CONNECTION_3G));
- notifier()->OnConnectionChanged(NetworkChangeNotifier::CONNECTION_3G);
- FastForwardUntilIdle();
-
- NetworkChangeNotifier::RemoveNetworkChangeObserver(&observer);
-}
-
-class MockMaxBandwidthObserver
- : public NetworkChangeNotifier::MaxBandwidthObserver {
- public:
- MOCK_METHOD2(OnMaxBandwidthChanged,
- void(double, NetworkChangeNotifier::ConnectionType));
-};
-
-TEST_F(NetworkChangeNotifierChromeosTest, OnMaxBandwidthChanged) {
- testing::StrictMock<MockMaxBandwidthObserver> observer;
- NetworkChangeNotifier::AddMaxBandwidthObserver(&observer);
-
- EXPECT_CALL(observer,
- OnMaxBandwidthChanged(3.6, NetworkChangeNotifier::CONNECTION_4G));
- notifier()->OnConnectionSubtypeChanged(NetworkChangeNotifier::CONNECTION_4G,
- NetworkChangeNotifier::SUBTYPE_HSPA);
- FastForwardUntilIdle();
-
- NetworkChangeNotifier::RemoveMaxBandwidthObserver(&observer);
-}
-
-} // namespace net
diff --git a/chromium/net/base/network_change_notifier_posix.cc b/chromium/net/base/network_change_notifier_posix.cc
new file mode 100644
index 00000000000..89a1ff461ce
--- /dev/null
+++ b/chromium/net/base/network_change_notifier_posix.cc
@@ -0,0 +1,158 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/bind.h"
+#include "build/build_config.h"
+#include "net/base/network_change_notifier_posix.h"
+#include "net/dns/dns_config_service_posix.h"
+
+#if defined(OS_ANDROID)
+#include "net/android/network_change_notifier_android.h"
+#endif
+
+namespace net {
+
+// DNS config services on Chrome OS and Android are signalled by the network
+// state handler rather than relying on watching files in /etc.
+class NetworkChangeNotifierPosix::DnsConfigService
+ : public net::internal::DnsConfigServicePosix {
+ public:
+ DnsConfigService() = default;
+ ~DnsConfigService() override = default;
+
+ // net::internal::DnsConfigService() overrides.
+ bool StartWatching() override {
+ // DNS config changes are handled and notified by the network
+ // state handlers.
+ return true;
+ }
+
+ void OnNetworkChange() {
+ InvalidateConfig();
+ InvalidateHosts();
+ ReadNow();
+ }
+};
+
+NetworkChangeNotifierPosix::NotifierThread::NotifierThread()
+ : base::Thread("NetworkChangeNotifier") {
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
+NetworkChangeNotifierPosix::NotifierThread::~NotifierThread() {
+ DCHECK(!Thread::IsRunning());
+}
+
+void NetworkChangeNotifierPosix::NotifierThread::OnNetworkChange() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ dns_config_service_->OnNetworkChange();
+}
+
+void NetworkChangeNotifierPosix::NotifierThread::Init() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ dns_config_service_.reset(new DnsConfigService());
+ dns_config_service_->WatchConfig(
+ base::BindRepeating(&NetworkChangeNotifier::SetDnsConfig));
+ dns_config_service_->OnNetworkChange();
+}
+
+void NetworkChangeNotifierPosix::NotifierThread::CleanUp() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ dns_config_service_.reset();
+}
+
+NetworkChangeNotifierPosix::NetworkChangeNotifierPosix(
+ NetworkChangeNotifier::ConnectionType initial_connection_type,
+ NetworkChangeNotifier::ConnectionSubtype initial_connection_subtype)
+ : NetworkChangeNotifier(NetworkChangeCalculatorParamsPosix()),
+ connection_type_(initial_connection_type),
+ max_bandwidth_mbps_(
+ NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
+ initial_connection_subtype)) {
+ notifier_thread_.StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+}
+
+NetworkChangeNotifierPosix::~NetworkChangeNotifierPosix() {
+ notifier_thread_.Stop();
+}
+
+void NetworkChangeNotifierPosix::OnDNSChanged() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // The Unretained thread pointer is ok here because if the thread gets
+ // deleted, the callback won't be called.
+ notifier_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &NetworkChangeNotifierPosix::NotifierThread::OnNetworkChange,
+ base::Unretained(&notifier_thread_)));
+}
+
+void NetworkChangeNotifierPosix::OnIPAddressChanged() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
+}
+
+void NetworkChangeNotifierPosix::OnConnectionChanged(
+ NetworkChangeNotifier::ConnectionType connection_type) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ {
+ base::AutoLock scoped_lock(lock_);
+ connection_type_ = connection_type;
+ }
+ NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange();
+}
+
+void NetworkChangeNotifierPosix::OnConnectionSubtypeChanged(
+ NetworkChangeNotifier::ConnectionType connection_type,
+ NetworkChangeNotifier::ConnectionSubtype connection_subtype) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ double max_bandwidth_mbps =
+ GetMaxBandwidthMbpsForConnectionSubtype(connection_subtype);
+ {
+ base::AutoLock scoped_lock(lock_);
+ max_bandwidth_mbps_ = max_bandwidth_mbps;
+ }
+ NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps,
+ connection_type);
+}
+
+NetworkChangeNotifier::ConnectionType
+NetworkChangeNotifierPosix::GetCurrentConnectionType() const {
+ base::AutoLock scoped_lock(lock_);
+ return connection_type_;
+}
+
+void NetworkChangeNotifierPosix::GetCurrentMaxBandwidthAndConnectionType(
+ double* max_bandwidth_mbps,
+ ConnectionType* connection_type) const {
+ base::AutoLock scoped_lock(lock_);
+ *connection_type = connection_type_;
+ *max_bandwidth_mbps = max_bandwidth_mbps_;
+}
+
+// static
+NetworkChangeNotifier::NetworkChangeCalculatorParams
+NetworkChangeNotifierPosix::NetworkChangeCalculatorParamsPosix() {
+ NetworkChangeCalculatorParams params;
+#if defined(OS_CHROMEOS)
+ // Delay values arrived at by simple experimentation and adjusted so as to
+ // produce a single signal when switching between network connections.
+ params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(4000);
+ params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(1000);
+ params.connection_type_offline_delay_ =
+ base::TimeDelta::FromMilliseconds(500);
+ params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500);
+#elif defined(OS_ANDROID)
+ params =
+ net::NetworkChangeNotifierAndroid::NetworkChangeCalculatorParamsAndroid();
+#else
+ NOTIMPLEMENTED();
+#endif
+ return params;
+}
+
+} // namespace net
diff --git a/chromium/net/base/network_change_notifier_posix.h b/chromium/net/base/network_change_notifier_posix.h
new file mode 100644
index 00000000000..37e6ae405ad
--- /dev/null
+++ b/chromium/net/base/network_change_notifier_posix.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_NETWORK_CHANGE_NOTIFIER_POSIX_H_
+#define NET_BASE_NETWORK_CHANGE_NOTIFIER_POSIX_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
+#include "net/base/net_export.h"
+#include "net/base/network_change_notifier.h"
+
+namespace net {
+
+// A NetworkChangeNotifier that needs to be told about network changes by some
+// other object. This class can't directly listen for network changes because on
+// ChromeOS and Android only objects running in the browser process can listen
+// for network state changes.
+class NET_EXPORT NetworkChangeNotifierPosix : public NetworkChangeNotifier {
+ public:
+ NetworkChangeNotifierPosix(
+ NetworkChangeNotifier::ConnectionType initial_connection_type,
+ NetworkChangeNotifier::ConnectionSubtype initial_connection_subtype);
+ ~NetworkChangeNotifierPosix() override;
+
+ // These methods are used to notify this object that a network property has
+ // changed. These must be called from the thread that owns this object.
+ void OnDNSChanged();
+ void OnIPAddressChanged();
+ void OnConnectionChanged(
+ NetworkChangeNotifier::ConnectionType connection_type);
+ void OnConnectionSubtypeChanged(
+ NetworkChangeNotifier::ConnectionType connection_type,
+ NetworkChangeNotifier::ConnectionSubtype connection_subtype);
+
+ protected:
+ // NetworkChangeNotifier overrides.
+ NetworkChangeNotifier::ConnectionType GetCurrentConnectionType()
+ const override;
+ void GetCurrentMaxBandwidthAndConnectionType(
+ double* max_bandwidth_mbps,
+ ConnectionType* connection_type) const override;
+
+ private:
+ friend class NetworkChangeNotifierPosixTest;
+
+ class DnsConfigService;
+
+ // Thread on which we can run DnsConfigService, which requires a TYPE_IO
+ // message loop.
+ class NotifierThread : public base::Thread {
+ public:
+ NotifierThread();
+ ~NotifierThread() override;
+
+ void OnNetworkChange();
+
+ protected:
+ // base::Thread
+ void Init() override;
+ void CleanUp() override;
+
+ private:
+ std::unique_ptr<DnsConfigService> dns_config_service_;
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(NotifierThread);
+ };
+
+ // Calculates parameters used for network change notifier online/offline
+ // signals.
+ static NetworkChangeNotifier::NetworkChangeCalculatorParams
+ NetworkChangeCalculatorParamsPosix();
+
+ THREAD_CHECKER(thread_checker_);
+
+ mutable base::Lock lock_;
+ NetworkChangeNotifier::ConnectionType
+ connection_type_; // Guarded by |lock_|.
+ double max_bandwidth_mbps_; // Guarded by |lock_|.
+
+ NotifierThread notifier_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkChangeNotifierPosix);
+};
+
+} // namespace net
+
+#endif // NET_BASE_NETWORK_CHANGE_NOTIFIER_POSIX_H_
diff --git a/chromium/net/base/network_change_notifier_posix_unittest.cc b/chromium/net/base/network_change_notifier_posix_unittest.cc
new file mode 100644
index 00000000000..c540877f651
--- /dev/null
+++ b/chromium/net/base/network_change_notifier_posix_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/network_change_notifier_posix.h"
+
+#include "base/test/scoped_task_environment.h"
+#include "net/base/network_change_notifier.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace net {
+
+class NetworkChangeNotifierPosixTest : public testing::Test {
+ public:
+ NetworkChangeNotifierPosixTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+ notifier_(new NetworkChangeNotifierPosix(
+ NetworkChangeNotifier::CONNECTION_UNKNOWN,
+ NetworkChangeNotifier::SUBTYPE_UNKNOWN)) {}
+
+ void FastForwardUntilIdle() {
+ scoped_task_environment_.FastForwardUntilNoTasksRemain();
+ }
+
+ NetworkChangeNotifierPosix* notifier() { return notifier_.get(); }
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ net::NetworkChangeNotifier::DisableForTest mock_notifier_disabler_;
+ std::unique_ptr<NetworkChangeNotifierPosix> notifier_;
+};
+
+class MockIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver {
+ public:
+ MOCK_METHOD0(OnIPAddressChanged, void());
+};
+
+TEST_F(NetworkChangeNotifierPosixTest, OnIPAddressChanged) {
+ testing::StrictMock<MockIPAddressObserver> observer;
+ NetworkChangeNotifier::AddIPAddressObserver(&observer);
+
+ EXPECT_CALL(observer, OnIPAddressChanged());
+ notifier()->OnIPAddressChanged();
+ FastForwardUntilIdle();
+
+ NetworkChangeNotifier::RemoveIPAddressObserver(&observer);
+}
+
+class MockNetworkChangeObserver
+ : public NetworkChangeNotifier::NetworkChangeObserver {
+ public:
+ MOCK_METHOD1(OnNetworkChanged, void(NetworkChangeNotifier::ConnectionType));
+};
+
+TEST_F(NetworkChangeNotifierPosixTest, OnNetworkChanged) {
+ testing::StrictMock<MockNetworkChangeObserver> observer;
+ NetworkChangeNotifier::AddNetworkChangeObserver(&observer);
+
+ EXPECT_CALL(observer,
+ OnNetworkChanged(NetworkChangeNotifier::CONNECTION_NONE));
+ EXPECT_CALL(observer, OnNetworkChanged(NetworkChangeNotifier::CONNECTION_3G));
+ notifier()->OnConnectionChanged(NetworkChangeNotifier::CONNECTION_3G);
+ FastForwardUntilIdle();
+
+ NetworkChangeNotifier::RemoveNetworkChangeObserver(&observer);
+}
+
+class MockMaxBandwidthObserver
+ : public NetworkChangeNotifier::MaxBandwidthObserver {
+ public:
+ MOCK_METHOD2(OnMaxBandwidthChanged,
+ void(double, NetworkChangeNotifier::ConnectionType));
+};
+
+TEST_F(NetworkChangeNotifierPosixTest, OnMaxBandwidthChanged) {
+ testing::StrictMock<MockMaxBandwidthObserver> observer;
+ NetworkChangeNotifier::AddMaxBandwidthObserver(&observer);
+
+ EXPECT_CALL(observer,
+ OnMaxBandwidthChanged(3.6, NetworkChangeNotifier::CONNECTION_4G));
+ notifier()->OnConnectionSubtypeChanged(NetworkChangeNotifier::CONNECTION_4G,
+ NetworkChangeNotifier::SUBTYPE_HSPA);
+ FastForwardUntilIdle();
+
+ NetworkChangeNotifier::RemoveMaxBandwidthObserver(&observer);
+}
+
+} // namespace net
diff --git a/chromium/net/base/registry_controlled_domains/effective_tld_names.dat b/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
index 69c78881f08..59db7d0c52f 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
@@ -4663,9 +4663,6 @@ web.ni
// ccTLD for the Netherlands
nl
-// BV.nl will be a registry for dutch BV's (besloten vennootschap)
-bv.nl
-
// no : http://www.norid.no/regelverk/index.en.html
// The Norwegian registry has declined to notify us of updates. The web pages
// referenced below are the official source of the data. There is also an
@@ -7111,9 +7108,6 @@ accountants
// aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG
aco
-// active : 2014-05-01 Active Network, LLC
-active
-
// actor : 2013-12-12 United TLD Holdco Ltd.
actor
@@ -7414,9 +7408,6 @@ black
// blackfriday : 2014-01-16 Uniregistry, Corp.
blackfriday
-// blanco : 2015-07-16 BLANCO GmbH + Co KG
-blanco
-
// blockbuster : 2015-07-30 Dish DBS Corporation
blockbuster
@@ -8026,9 +8017,6 @@ engineering
// enterprises : 2013-09-20 Binky Moon, LLC
enterprises
-// epost : 2015-07-23 Deutsche Post AG
-epost
-
// epson : 2014-12-04 Seiko Epson Corporation
epson
@@ -9850,9 +9838,6 @@ soy
// space : 2014-04-03 DotSpace Inc.
space
-// spiegel : 2014-02-05 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG
-spiegel
-
// sport : 2017-11-16 Global Association of International Sports Federations (GAISF)
sport
@@ -10687,9 +10672,6 @@ zero
// zip : 2014-05-08 Charleston Road Registry Inc.
zip
-// zippo : 2015-07-02 Zadco Company
-zippo
-
// zone : 2013-11-14 Binky Moon, LLC
zone
@@ -11092,6 +11074,11 @@ firm.dk
reg.dk
store.dk
+// dapps.earth : https://dapps.earth/
+// Submitted by Daniil Burdakov <icqkill@gmail.com>
+*.dapps.earth
+*.bzz.dapps.earth
+
// Debian : https://www.debian.org/
// Submitted by Peter Palfrader / Debian Sysadmin Team <dsa-publicsuffixlist@debian.org>
debian.net
@@ -11638,6 +11625,7 @@ channelsdvr.net
// Fastly Inc. : http://www.fastly.com/
// Submitted by Fastly Security <security@fastly.com>
+fastly-terrarium.com
fastlylb.net
map.fastlylb.net
freetls.fastly.net
@@ -11672,6 +11660,12 @@ mydobiss.com
// Filegear Inc. : https://www.filegear.com
// Submitted by Jason Zhu <jason@owtware.com>
filegear.me
+filegear-au.me
+filegear-de.me
+filegear-gb.me
+filegear-ie.me
+filegear-jp.me
+filegear-sg.me
// Firebase, Inc.
// Submitted by Chris Raynor <chris@firebase.com>
@@ -11734,6 +11728,8 @@ goip.de
// Google, Inc.
// Submitted by Eduardo Vela <evn@google.com>
+run.app
+a.run.app
*.0emm.com
appspot.com
blogspot.ae
@@ -11853,6 +11849,19 @@ moonscale.net
// Submitted by Hannu Aronsson <haa@iki.fi>
iki.fi
+// Individual Network Berlin e.V. : https://www.in-berlin.de/
+// Submitted by Christian Seitz <chris@in-berlin.de>
+dyn-berlin.de
+in-berlin.de
+in-brb.de
+in-butter.de
+in-dsl.de
+in-dsl.net
+in-dsl.org
+in-vpn.de
+in-vpn.net
+in-vpn.org
+
// info.at : http://www.info.at/
biz.at
info.at
@@ -11939,6 +11948,22 @@ git-repos.de
lcube-server.de
svn-repos.de
+// Leadpages : https://www.leadpages.net
+// Submitted by Greg Dallavalle <domains@leadpages.net>
+leadpages.co
+lpages.co
+lpusercontent.com
+
+// Lifetime Hosting : https://Lifetime.Hosting/
+// Submitted by Mike Fillator <support@lifetime.hosting>
+co.business
+co.education
+co.events
+co.financial
+co.network
+co.place
+co.technology
+
// Lightmaker Property Manager, Inc. : https://app.lmpm.com/
// Submitted by Greg Holland <greg.holland@lmpm.com>
app.lmpm.com
@@ -12494,6 +12519,10 @@ spacekit.io
// Submitted by Stefan Neufeind <info@speedpartner.de>
customer.speedpartner.de
+// Standard Library : https://stdlib.com
+// Submitted by Jacob Lee <jacob@stdlib.com>
+api.stdlib.com
+
// Storj Labs Inc. : https://storj.io/
// Submitted by Philip Hutchins <hostmaster@storj.io>
storj.farm
@@ -12506,6 +12535,11 @@ utwente.io
// Submitted by Dan Miller <dm@sub6.com>
temp-dns.com
+// Swisscom Application Cloud: https://developer.swisscom.com
+// Submitted by Matthias.Winzeler <matthias.winzeler@swisscom.com>
+applicationcloud.io
+scapp.io
+
// Synology, Inc. : https://www.synology.com/
// Submitted by Rony Weng <ronyweng@synology.com>
diskstation.me
@@ -12534,6 +12568,12 @@ gdynia.pl
med.pl
sopot.pl
+// Telebit : https://telebit.cloud
+// Submitted by AJ ONeal <aj@telebit.cloud>
+telebit.app
+telebit.io
+*.telebit.xyz
+
// The Gwiddle Foundation : https://gwiddlefoundation.org.uk
// Submitted by Joshua Bayfield <joshua.bayfield@gwiddlefoundation.org.uk>
gwiddle.co.uk
@@ -12693,6 +12733,10 @@ za.org
// Submitted by Olli Vanhoja <olli@zeit.co>
now.sh
+// Zine EOOD : https://zine.bg/
+// Submitted by Martin Angelov <martin@zine.bg>
+bss.design
+
// Zone.id : https://zone.id/
// Submitted by Su Hendro <admin@zone.id>
zone.id
diff --git a/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf b/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
index 9443898779d..56f3713b15e 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
@@ -44,6 +44,7 @@ struct DomainRule {
9guacu.br, 0
a.bg, 0
a.prod.fastly.net, 4
+a.run.app, 4
a.se, 0
a.ssl.fastly.net, 4
aa.no, 0
@@ -129,7 +130,6 @@ achi.nagano.jp, 0
aco, 0
act.au, 0
act.edu.au, 0
-active, 0
actor, 0
ad, 0
ad.jp, 0
@@ -337,6 +337,7 @@ ap.it, 0
ap.leg.br, 4
aparecida.br, 0
apartments, 0
+api.stdlib.com, 4
apigee.io, 4
app, 0
app.lmpm.com, 4
@@ -344,6 +345,7 @@ app.os.fedoraproject.org, 4
app.os.stg.fedoraproject.org, 4
appchizi.com, 4
apple, 0
+applicationcloud.io, 4
applinzi.com, 4
apps.fbsbx.com, 4
apps.lair.io, 4
@@ -732,7 +734,6 @@ bl.it, 0
black, 0
blackbaudcdn.net, 4
blackfriday, 0
-blanco, 0
blockbuster, 0
blog, 0
blog.bo, 0
@@ -910,6 +911,7 @@ bryne.no, 0
bs, 0
bs.it, 0
bsb.br, 0
+bss.design, 4
bt, 0
bt.it, 0
bu.no, 0
@@ -936,7 +938,6 @@ buyshouses.net, 4
buzen.fukuoka.jp, 0
buzz, 0
bv, 0
-bv.nl, 0
bw, 0
by, 0
bydgoszcz.pl, 0
@@ -947,6 +948,7 @@ bytom.pl, 0
bz, 0
bz.it, 0
bzh, 0
+bzz.dapps.earth, 6
c.bg, 0
c.cdn77.org, 4
c.la, 4
@@ -1275,6 +1277,7 @@ co.ao, 0
co.at, 0
co.bb, 0
co.bi, 0
+co.business, 4
co.bw, 0
co.ca, 4
co.ci, 0
@@ -1284,6 +1287,9 @@ co.com, 4
co.cr, 0
co.cz, 4
co.dk, 4
+co.education, 4
+co.events, 4
+co.financial, 4
co.gg, 0
co.gl, 0
co.gy, 0
@@ -1308,18 +1314,21 @@ co.mu, 0
co.mw, 0
co.mz, 0
co.na, 0
+co.network, 4
co.ni, 0
co.nl, 4
co.no, 4
co.nz, 0
co.om, 0
co.pl, 4
+co.place, 4
co.pn, 0
co.pw, 0
co.rs, 0
co.rw, 0
co.st, 0
co.sz, 0
+co.technology, 4
co.th, 0
co.tj, 0
co.tm, 0
@@ -1625,6 +1634,7 @@ dallas.museum, 0
damnserver.com, 4
dance, 0
daplie.me, 4
+dapps.earth, 6
data, 0
database.museum, 0
date, 0
@@ -1801,6 +1811,7 @@ dvr, 0
dvrcam.info, 4
dvrdns.org, 4
dy.fi, 4
+dyn-berlin.de, 4
dyn-ip24.de, 4
dyn-o-saur.com, 4
dyn-vpn.de, 4
@@ -2061,7 +2072,6 @@ entomology.museum, 0
environment.museum, 0
environmentalconservation.museum, 0
epilepsy.museum, 0
-epost, 0
epson, 0
equipment, 0
equipment.aero, 0
@@ -2156,6 +2166,7 @@ farmstead.museum, 0
farsund.no, 0
fashion, 0
fast, 0
+fastly-terrarium.com, 4
fastlylb.net, 4
fastpanel.direct, 4
fastvps-server.com, 4
@@ -2196,6 +2207,12 @@ fie.ee, 0
field.museum, 0
figueres.museum, 0
filatelia.museum, 0
+filegear-au.me, 4
+filegear-de.me, 4
+filegear-gb.me, 4
+filegear-ie.me, 4
+filegear-jp.me, 4
+filegear-sg.me, 4
filegear.me, 4
film, 0
film.hu, 0
@@ -3268,7 +3285,16 @@ immobilien, 0
imperia.it, 0
in, 0
in-addr.arpa, 0
+in-berlin.de, 4
+in-brb.de, 4
+in-butter.de, 4
+in-dsl.de, 4
+in-dsl.net, 4
+in-dsl.org, 4
in-the-band.net, 4
+in-vpn.de, 4
+in-vpn.net, 4
+in-vpn.org, 4
in.eu.org, 4
in.futurecms.at, 6
in.na, 0
@@ -4153,6 +4179,7 @@ lc.it, 0
lcube-server.de, 4
lds, 0
le.it, 0
+leadpages.co, 4
leangaviika.no, 0
lease, 0
leasing.aero, 0
@@ -4322,8 +4349,10 @@ louvre.museum, 0
love, 0
lowicz.pl, 0
loyalist.museum, 0
+lpages.co, 4
lpl, 0
lplfinancial, 0
+lpusercontent.com, 4
lr, 0
ls, 0
lt, 0
@@ -6378,6 +6407,7 @@ ru.net, 4
rugby, 0
ruhr, 0
run, 0
+run.app, 4
ruovat.no, 0
russia.museum, 0
rv.ua, 0
@@ -6587,6 +6617,7 @@ sc.tz, 0
sc.ug, 0
sc.us, 0
sca, 0
+scapp.io, 4
scb, 0
sch.ae, 0
sch.id, 0
@@ -6979,7 +7010,6 @@ spdns.de, 4
spdns.eu, 4
spdns.org, 4
spectrum.myjino.ru, 6
-spiegel, 0
spjelkavik.no, 0
sport, 0
sport.hu, 0
@@ -7267,6 +7297,9 @@ tecnologia.bo, 0
tel, 0
tel.tr, 0
tele.amune.org, 4
+telebit.app, 4
+telebit.io, 4
+telebit.xyz, 6
telefonica, 0
telekommunikation.museum, 0
television.museum, 0
@@ -8636,7 +8669,6 @@ zgorzelec.pl, 0
zhitomir.ua, 0
zhytomyr.ua, 0
zip, 0
-zippo, 0
zj.cn, 0
zlg.br, 0
zm, 0
diff --git a/chromium/net/dns/BUILD.gn b/chromium/net/dns/BUILD.gn
index 741a5b5685c..3b87b89a687 100644
--- a/chromium/net/dns/BUILD.gn
+++ b/chromium/net/dns/BUILD.gn
@@ -210,7 +210,7 @@ source_set("host_resolver_impl") {
# Whitelist-only access so we can keep track of all usage external to the
# network stack.
friend = [
- # chromeos/network/network_change_notifier_chromeos.cc
+ # chromeos/network/network_change_notifier_posix.cc
# ChromeOS-specific change notifier with some overrides for DnsConfigService
# TODO(crbug.com/882610): Remove/cleanup once we figure out servicification.
"//chromeos/network",
diff --git a/chromium/net/http/bidirectional_stream.cc b/chromium/net/http/bidirectional_stream.cc
index 404602b0e92..ecb0c63bfa6 100644
--- a/chromium/net/http/bidirectional_stream.cc
+++ b/chromium/net/http/bidirectional_stream.cc
@@ -420,14 +420,14 @@ void BidirectionalStream::OnNeedsClientAuth(const SSLConfig& used_ssl_config,
StartRequest(ssl_config);
}
-void BidirectionalStream::OnHttpsProxyTunnelResponse(
+void BidirectionalStream::OnHttpsProxyTunnelResponseRedirect(
const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
std::unique_ptr<HttpStream> stream) {
DCHECK(stream_request_);
- NotifyFailed(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
+ NotifyFailed(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT);
}
void BidirectionalStream::OnQuicBroken() {}
diff --git a/chromium/net/http/bidirectional_stream.h b/chromium/net/http/bidirectional_stream.h
index 61fa08cae12..2cfeca08b6c 100644
--- a/chromium/net/http/bidirectional_stream.h
+++ b/chromium/net/http/bidirectional_stream.h
@@ -218,10 +218,11 @@ class NET_EXPORT BidirectionalStream : public BidirectionalStreamImpl::Delegate,
HttpAuthController* auth_controller) override;
void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
SSLCertRequestInfo* cert_info) override;
- void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<HttpStream> stream) override;
+ void OnHttpsProxyTunnelResponseRedirect(
+ const HttpResponseInfo& response_info,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ std::unique_ptr<HttpStream> stream) override;
void OnQuicBroken() override;
// Helper method to notify delegate if there is an error.
diff --git a/chromium/net/http/http_network_transaction.cc b/chromium/net/http/http_network_transaction.cc
index 19631949abf..ce86e621144 100644
--- a/chromium/net/http/http_network_transaction.cc
+++ b/chromium/net/http/http_network_transaction.cc
@@ -650,7 +650,7 @@ void HttpNetworkTransaction::OnNeedsClientAuth(
OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
}
-void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
+void HttpNetworkTransaction::OnHttpsProxyTunnelResponseRedirect(
const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
@@ -670,7 +670,7 @@ void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
stream_ = std::move(stream);
stream_->SetRequestHeadersCallback(request_headers_callback_);
stream_request_.reset(); // we're done with the stream request
- OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
+ OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT);
}
void HttpNetworkTransaction::OnQuicBroken() {
@@ -856,11 +856,12 @@ int HttpNetworkTransaction::DoCreateStream() {
}
int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
- // If |result| is ERR_HTTPS_PROXY_TUNNEL_RESPONSE, then
- // DoCreateStreamComplete is being called from OnHttpsProxyTunnelResponse,
- // which resets the stream request first. Therefore, we have to grab the
- // connection attempts in *that* function instead of here in that case.
- if (result != ERR_HTTPS_PROXY_TUNNEL_RESPONSE)
+ // If |result| is ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT, then
+ // DoCreateStreamComplete is being called from
+ // OnHttpsProxyTunnelResponseRedirect, which resets the stream request first.
+ // Therefore, we have to grab the connection attempts in *that* function
+ // instead of here in that case.
+ if (result != ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT)
CopyConnectionAttemptsFromStreamRequest();
if (result == OK) {
@@ -868,10 +869,8 @@ int HttpNetworkTransaction::DoCreateStreamComplete(int result) {
DCHECK(stream_.get());
} else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
result = HandleCertificateRequest(result);
- } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
- // Return OK and let the caller read the proxy's error page
- next_state_ = STATE_NONE;
- return OK;
+ } else if (result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) {
+ return DoCreateStreamCompletedTunnelResponseRedirect();
} else if (result == ERR_HTTP_1_1_REQUIRED ||
result == ERR_PROXY_HTTP_1_1_REQUIRED) {
return HandleHttp11Required(result);
@@ -1937,4 +1936,45 @@ bool HttpNetworkTransaction::ContentEncodingsValid() const {
return result;
}
+static HttpNetworkTransaction::TunnelRedirectHistogramValue
+GetTunnelRedirectHistogramValue(bool is_main_frame, bool was_auto_detected) {
+ if (!is_main_frame && !was_auto_detected)
+ return HttpNetworkTransaction::kSubresourceByExplicitProxy;
+ if (is_main_frame && !was_auto_detected)
+ return HttpNetworkTransaction::kMainFrameByExplicitProxy;
+ if (!is_main_frame && was_auto_detected)
+ return HttpNetworkTransaction::kSubresourceByAutoDetectedProxy;
+ return HttpNetworkTransaction::kMainFrameByAutoDetectedProxy;
+}
+
+// TODO(https://crbug.com/928551): Support for redirect on CONNECT is
+// deprecated, and support will be removed.
+//
+// The code in this method handles the temporary histogramming and
+// compatibility-mode policy during the phase-out.
+int HttpNetworkTransaction::DoCreateStreamCompletedTunnelResponseRedirect() {
+ bool is_main_frame = (request_->load_flags & LOAD_MAIN_FRAME_DEPRECATED) ==
+ LOAD_MAIN_FRAME_DEPRECATED;
+ bool was_auto_detected = proxy_info_.did_use_auto_detected_pac_script();
+
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.Proxy.RedirectDuringConnect",
+ GetTunnelRedirectHistogramValue(is_main_frame, was_auto_detected));
+
+ // For legacy compatibility, the proxy is allowed to redirect CONNECT
+ // if:
+ // (a) the request was for a top-level frame
+ // (b) the proxy server was explicitly configured (i.e. not
+ // auto-detected).
+ if (is_main_frame && !was_auto_detected) {
+ // Return OK and let the caller read the proxy's error page
+ next_state_ = STATE_NONE;
+ return OK;
+ }
+
+ // Otherwise let the request fail.
+ stream_.reset();
+ return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT;
+}
+
} // namespace net
diff --git a/chromium/net/http/http_network_transaction.h b/chromium/net/http/http_network_transaction.h
index 7ccc5f9b681..736c98f3de3 100644
--- a/chromium/net/http/http_network_transaction.h
+++ b/chromium/net/http/http_network_transaction.h
@@ -50,6 +50,16 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
: public HttpTransaction,
public HttpStreamRequest::Delegate {
public:
+ // Enumeration used by Net.Proxy.RedirectDuringConnect. Exposed here for
+ // sharing by unit-tests.
+ enum TunnelRedirectHistogramValue {
+ kSubresourceByExplicitProxy = 0,
+ kMainFrameByExplicitProxy = 1,
+ kSubresourceByAutoDetectedProxy = 2,
+ kMainFrameByAutoDetectedProxy = 3,
+ kMaxValue = kMainFrameByAutoDetectedProxy
+ };
+
HttpNetworkTransaction(RequestPriority priority,
HttpNetworkSession* session);
@@ -117,10 +127,11 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
HttpAuthController* auth_controller) override;
void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
SSLCertRequestInfo* cert_info) override;
- void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<HttpStream> stream) override;
+ void OnHttpsProxyTunnelResponseRedirect(
+ const HttpResponseInfo& response_info,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ std::unique_ptr<HttpStream> stream) override;
void OnQuicBroken() override;
void GetConnectionAttempts(ConnectionAttempts* out) const override;
@@ -309,6 +320,10 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// "Accept-Encoding".
bool ContentEncodingsValid() const;
+ // Logic for handling ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT seen during
+ // DoCreateStreamCompletedTunnel().
+ int DoCreateStreamCompletedTunnelResponseRedirect();
+
scoped_refptr<HttpAuthController>
auth_controllers_[HttpAuth::AUTH_NUM_TARGETS];
diff --git a/chromium/net/http/http_network_transaction_unittest.cc b/chromium/net/http/http_network_transaction_unittest.cc
index ae5b2324085..0a9d165ded9 100644
--- a/chromium/net/http/http_network_transaction_unittest.cc
+++ b/chromium/net/http/http_network_transaction_unittest.cc
@@ -9514,7 +9514,7 @@ TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
CONNECT_TIMING_HAS_SSL_TIMES);
}
-// Test an HTTPS Proxy's ability to redirect a CONNECT request
+// Test that an HTTPS Proxy can redirect a CONNECT request for main frames.
TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
session_deps_.proxy_resolution_service =
ProxyResolutionService::CreateFixedFromPacResult(
@@ -9523,6 +9523,7 @@ TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
session_deps_.net_log = &net_log;
HttpRequestInfo request;
+ request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
request.method = "GET";
request.url = GURL("https://www.example.org/");
request.traffic_annotation =
@@ -9569,7 +9570,7 @@ TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
// In the case of redirects from proxies, HttpNetworkTransaction returns
// timing for the proxy connection instead of the connection to the host,
// and no send / receive times.
- // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
+ // See HttpNetworkTransaction::OnHttpsProxyTunnelResponseRedirect.
LoadTimingInfo load_timing_info;
EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
@@ -9590,13 +9591,120 @@ TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}
-// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
+// Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
+TEST_F(HttpNetworkTransactionTest,
+ RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
+ base::HistogramTester histograms;
+ session_deps_.proxy_resolution_service =
+ ProxyResolutionService::CreateFixedFromPacResult(
+ "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
+ TestNetLog net_log;
+ session_deps_.net_log = &net_log;
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("https://www.example.org/");
+ request.traffic_annotation =
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
+
+ MockWrite data_writes[] = {
+ MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
+ "Host: www.example.org:443\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ };
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 302 Redirect\r\n"),
+ MockRead("Location: http://login.example.com/\r\n"),
+ MockRead("Content-Length: 0\r\n\r\n"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+
+ StaticSocketDataProvider data(data_reads, data_writes);
+ SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
+
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
+
+ TestCompletionCallback callback;
+
+ std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
+
+ int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
+ EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+
+ rv = callback.WaitForResult();
+ EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT));
+
+ histograms.ExpectUniqueSample(
+ "Net.Proxy.RedirectDuringConnect",
+ HttpNetworkTransaction::kSubresourceByExplicitProxy, 1);
+}
+
+// Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
+// request for main frames.
+TEST_F(HttpNetworkTransactionTest,
+ RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
+ base::HistogramTester histograms;
+ session_deps_.proxy_resolution_service =
+ ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
+ "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
+ TestNetLog net_log;
+ session_deps_.net_log = &net_log;
+
+ HttpRequestInfo request;
+ request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
+ request.method = "GET";
+ request.url = GURL("https://www.example.org/");
+ request.traffic_annotation =
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
+
+ MockWrite data_writes[] = {
+ MockWrite(ASYNC, 0,
+ "CONNECT www.example.org:443 HTTP/1.1\r\n"
+ "Host: www.example.org:443\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ };
+
+ MockRead data_reads[] = {
+ MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
+ MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
+ MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
+ };
+
+ SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
+ SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
+
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+ session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
+
+ TestCompletionCallback callback;
+
+ std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
+
+ int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
+ EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+
+ rv = callback.WaitForResult();
+ EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT));
+
+ histograms.ExpectUniqueSample(
+ "Net.Proxy.RedirectDuringConnect",
+ HttpNetworkTransaction::kMainFrameByAutoDetectedProxy, 1);
+}
+
+// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request for main
+// frames.
TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
+ base::HistogramTester histograms;
session_deps_.proxy_resolution_service = ProxyResolutionService::CreateFixed(
"https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
HttpRequestInfo request;
request.method = "GET";
+ request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
request.url = GURL("https://www.example.org/");
request.traffic_annotation =
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
@@ -9645,6 +9753,10 @@ TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
std::string url;
EXPECT_TRUE(response->headers->IsRedirect(&url));
EXPECT_EQ("http://login.example.com/", url);
+
+ histograms.ExpectUniqueSample(
+ "Net.Proxy.RedirectDuringConnect",
+ HttpNetworkTransaction::kMainFrameByExplicitProxy, 1);
}
// Test that an HTTPS proxy's response to a CONNECT request is filtered.
diff --git a/chromium/net/http/http_proxy_client_socket.cc b/chromium/net/http/http_proxy_client_socket.cc
index 12cfb3dfea9..dd877223a03 100644
--- a/chromium/net/http/http_proxy_client_socket.cc
+++ b/chromium/net/http/http_proxy_client_socket.cc
@@ -484,7 +484,7 @@ int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
&redirect_load_timing_info_);
transport_.reset();
http_stream_parser_.reset();
- return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
+ return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT;
case 407: // Proxy Authentication Required
// We need this status code to allow proxy authentication. Our
diff --git a/chromium/net/http/http_proxy_client_socket_pool.cc b/chromium/net/http/http_proxy_client_socket_pool.cc
index 21ace98a69e..d7d704f4f57 100644
--- a/chromium/net/http/http_proxy_client_socket_pool.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool.cc
@@ -293,7 +293,7 @@ int HttpProxyConnectJob::HandleConnectResult(int result) {
error_response_info_ = client_socket_->GetAdditionalErrorState();
if (result == OK || result == ERR_PROXY_AUTH_REQUESTED ||
- result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
+ result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) {
SetSocket(std::move(client_socket_));
}
return result;
diff --git a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
index 4397ae6c31c..3fbd7ab86a7 100644
--- a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -793,7 +793,7 @@ TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
EXPECT_FALSE(handle_.socket());
} else {
// Expect ProxyClientSocket to return the proxy's response, sanitized.
- EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE));
+ EXPECT_THAT(rv, IsError(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT));
EXPECT_TRUE(handle_.is_initialized());
ASSERT_TRUE(handle_.socket());
diff --git a/chromium/net/http/http_stream_factory_job.cc b/chromium/net/http/http_stream_factory_job.cc
index 5579cae972a..8c4eb8ec46d 100644
--- a/chromium/net/http/http_stream_factory_job.cc
+++ b/chromium/net/http/http_stream_factory_job.cc
@@ -532,13 +532,13 @@ void HttpStreamFactory::Job::OnNeedsClientAuthCallback(
// |this| may be deleted after this call.
}
-void HttpStreamFactory::Job::OnHttpsProxyTunnelResponseCallback(
+void HttpStreamFactory::Job::OnHttpsProxyTunnelResponseRedirectCallback(
const HttpResponseInfo& response_info,
std::unique_ptr<HttpStream> stream) {
DCHECK_NE(job_type_, PRECONNECT);
- delegate_->OnHttpsProxyTunnelResponse(this, response_info, server_ssl_config_,
- proxy_info_, std::move(stream));
+ delegate_->OnHttpsProxyTunnelResponseRedirect(
+ this, response_info, server_ssl_config_, proxy_info_, std::move(stream));
// |this| may be deleted after this call.
}
@@ -638,7 +638,7 @@ void HttpStreamFactory::Job::RunLoop(int result) {
connection_->ssl_error_response_info().cert_request_info)));
return;
- case ERR_HTTPS_PROXY_TUNNEL_RESPONSE: {
+ case ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT: {
DCHECK(connection_.get());
DCHECK(connection_->socket());
DCHECK(establishing_tunnel_);
@@ -647,8 +647,8 @@ void HttpStreamFactory::Job::RunLoop(int result) {
static_cast<ProxyClientSocket*>(connection_->socket());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(
- &Job::OnHttpsProxyTunnelResponseCallback,
+ base::BindOnce(
+ &Job::OnHttpsProxyTunnelResponseRedirectCallback,
ptr_factory_.GetWeakPtr(),
*proxy_socket->GetConnectResponseInfo(),
base::Passed(proxy_socket->CreateConnectResponseStream())));
@@ -1090,7 +1090,7 @@ int HttpStreamFactory::Job::DoInitConnectionComplete(int result) {
}
if (result == ERR_PROXY_AUTH_REQUESTED ||
- result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
+ result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) {
DCHECK(!ssl_started);
// Other state (i.e. |using_ssl_|) suggests that |connection_| will have an
// SSL socket, but there was an error before that could happen. This
diff --git a/chromium/net/http/http_stream_factory_job.h b/chromium/net/http/http_stream_factory_job.h
index 4d50b0c75f7..7dc0399a4aa 100644
--- a/chromium/net/http/http_stream_factory_job.h
+++ b/chromium/net/http/http_stream_factory_job.h
@@ -92,9 +92,9 @@ class HttpStreamFactory::Job {
const SSLConfig& used_ssl_config,
const SSLInfo& ssl_info) = 0;
- // Invoked when |job| has a failure of the CONNECT request through an HTTPS
- // proxy.
- virtual void OnHttpsProxyTunnelResponse(
+ // Invoked when |job| has a failure of the CONNECT request (due to a 302
+ // redirect) through an HTTPS proxy.
+ virtual void OnHttpsProxyTunnelResponseRedirect(
Job* job,
const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
@@ -302,8 +302,9 @@ class HttpStreamFactory::Job {
void OnNeedsProxyAuthCallback(const HttpResponseInfo& response_info,
HttpAuthController* auth_controller);
void OnNeedsClientAuthCallback(SSLCertRequestInfo* cert_info);
- void OnHttpsProxyTunnelResponseCallback(const HttpResponseInfo& response_info,
- std::unique_ptr<HttpStream> stream);
+ void OnHttpsProxyTunnelResponseRedirectCallback(
+ const HttpResponseInfo& response_info,
+ std::unique_ptr<HttpStream> stream);
void OnPreconnectsComplete();
void OnIOComplete(int result);
diff --git a/chromium/net/http/http_stream_factory_job_controller.cc b/chromium/net/http/http_stream_factory_job_controller.cc
index dd79f0a3be1..c76c66df273 100644
--- a/chromium/net/http/http_stream_factory_job_controller.cc
+++ b/chromium/net/http/http_stream_factory_job_controller.cc
@@ -414,7 +414,7 @@ void HttpStreamFactory::JobController::OnCertificateError(
delegate_->OnCertificateError(status, used_ssl_config, ssl_info);
}
-void HttpStreamFactory::JobController::OnHttpsProxyTunnelResponse(
+void HttpStreamFactory::JobController::OnHttpsProxyTunnelResponseRedirect(
Job* job,
const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
@@ -433,8 +433,8 @@ void HttpStreamFactory::JobController::OnHttpsProxyTunnelResponse(
BindJob(job);
if (!request_)
return;
- delegate_->OnHttpsProxyTunnelResponse(response_info, used_ssl_config,
- used_proxy_info, std::move(stream));
+ delegate_->OnHttpsProxyTunnelResponseRedirect(
+ response_info, used_ssl_config, used_proxy_info, std::move(stream));
}
void HttpStreamFactory::JobController::OnNeedsClientAuth(
diff --git a/chromium/net/http/http_stream_factory_job_controller.h b/chromium/net/http/http_stream_factory_job_controller.h
index 6c4c2b0acac..5a7b0ff4da3 100644
--- a/chromium/net/http/http_stream_factory_job_controller.h
+++ b/chromium/net/http/http_stream_factory_job_controller.h
@@ -120,13 +120,14 @@ class HttpStreamFactory::JobController
const SSLConfig& used_ssl_config,
const SSLInfo& ssl_info) override;
- // Invoked when |job| has a failure of the CONNECT request through an HTTPS
- // proxy.
- void OnHttpsProxyTunnelResponse(Job* job,
- const HttpResponseInfo& response_info,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<HttpStream> stream) override;
+ // Invoked when |job| has a failure of the CONNECT request (due to 302
+ // redirect) through an HTTPS proxy.
+ void OnHttpsProxyTunnelResponseRedirect(
+ Job* job,
+ const HttpResponseInfo& response_info,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ std::unique_ptr<HttpStream> stream) override;
// Invoked when |job| raises failure for SSL Client Auth.
void OnNeedsClientAuth(Job* job,
diff --git a/chromium/net/http/http_stream_factory_test_util.h b/chromium/net/http/http_stream_factory_test_util.h
index c186f1006ca..c944019712d 100644
--- a/chromium/net/http/http_stream_factory_test_util.h
+++ b/chromium/net/http/http_stream_factory_test_util.h
@@ -93,11 +93,11 @@ class MockHttpStreamRequestDelegate : public HttpStreamRequest::Delegate {
SSLCertRequestInfo* cert_info));
// std::unique_ptr is not copyable and therefore cannot be mocked.
- void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<HttpStream> stream) override {
- }
+ void OnHttpsProxyTunnelResponseRedirect(
+ const HttpResponseInfo& response_info,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ std::unique_ptr<HttpStream> stream) override {}
MOCK_METHOD0(OnQuicBroken, void());
diff --git a/chromium/net/http/http_stream_factory_unittest.cc b/chromium/net/http/http_stream_factory_unittest.cc
index 1166709885a..6a37330b031 100644
--- a/chromium/net/http/http_stream_factory_unittest.cc
+++ b/chromium/net/http/http_stream_factory_unittest.cc
@@ -262,11 +262,11 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate {
void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
SSLCertRequestInfo* cert_info) override {}
- void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<HttpStream> stream) override {
- }
+ void OnHttpsProxyTunnelResponseRedirect(
+ const HttpResponseInfo& response_info,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ std::unique_ptr<HttpStream> stream) override {}
void OnQuicBroken() override {}
diff --git a/chromium/net/http/http_stream_request.h b/chromium/net/http/http_stream_request.h
index c07e7f62d5f..602854c7387 100644
--- a/chromium/net/http/http_stream_request.h
+++ b/chromium/net/http/http_stream_request.h
@@ -125,9 +125,9 @@ class NET_EXPORT_PRIVATE HttpStreamRequest {
virtual void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
SSLCertRequestInfo* cert_info) = 0;
- // This is the failure of the CONNECT request through an HTTPS proxy.
- // Headers can be read from |response_info|, while the body can be read
- // from |stream|.
+ // This is the failure of the CONNECT request through an HTTPS proxy due to
+ // a 302 redirect. Headers can be read from |response_info|, while the body
+ // can be read from |stream|.
//
// |used_ssl_config| indicates the actual SSL configuration used for this
// stream, since the HttpStreamRequest may have modified the configuration
@@ -137,7 +137,7 @@ class NET_EXPORT_PRIVATE HttpStreamRequest {
// since the HttpStreamRequest performs the proxy resolution.
//
// Ownership of |stream| is transferred to the delegate.
- virtual void OnHttpsProxyTunnelResponse(
+ virtual void OnHttpsProxyTunnelResponseRedirect(
const HttpResponseInfo& response_info,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
diff --git a/chromium/net/nqe/network_quality_estimator.cc b/chromium/net/nqe/network_quality_estimator.cc
index 0ebf546963e..93831e7a160 100644
--- a/chromium/net/nqe/network_quality_estimator.cc
+++ b/chromium/net/nqe/network_quality_estimator.cc
@@ -747,6 +747,8 @@ void NetworkQualityEstimator::ComputeEffectiveConnectionType() {
.downstream_throughput_kbps());
}
+ ClampKbpsBasedOnEct();
+
UMA_HISTOGRAM_ENUMERATION("NQE.EffectiveConnectionType.OnECTComputation",
effective_connection_type_,
EFFECTIVE_CONNECTION_TYPE_LAST);
@@ -791,6 +793,38 @@ void NetworkQualityEstimator::ComputeEffectiveConnectionType() {
new_throughput_observations_since_last_ect_computation_ = 0;
}
+void NetworkQualityEstimator::ClampKbpsBasedOnEct() {
+ // No need to clamp when ECT is unknown or if the connection speed is fast.
+ if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
+ effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_OFFLINE ||
+ effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_4G) {
+ return;
+ }
+
+ if (params_->upper_bound_typical_kbps_multiplier() <= 0.0)
+ return;
+
+ DCHECK_LT(0, params_->TypicalNetworkQuality(effective_connection_type_)
+ .downstream_throughput_kbps());
+ // For a given ECT, upper bound on Kbps can't be less than the typical Kbps
+ // for that ECT.
+ DCHECK_LE(1.0, params_->upper_bound_typical_kbps_multiplier());
+
+ if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_SLOW_2G ||
+ effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_2G ||
+ effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_3G) {
+ // Put an upper bound on Kbps.
+ network_quality_.set_downstream_throughput_kbps(
+ std::min(network_quality_.downstream_throughput_kbps(),
+ static_cast<int>(
+ params_->TypicalNetworkQuality(effective_connection_type_)
+ .downstream_throughput_kbps() *
+ params_->upper_bound_typical_kbps_multiplier())));
+ return;
+ }
+ NOTREACHED();
+}
+
EffectiveConnectionType
NetworkQualityEstimator::GetCappedECTBasedOnSignalStrength() const {
if (!params_->cap_ect_based_on_signal_strength())
diff --git a/chromium/net/nqe/network_quality_estimator.h b/chromium/net/nqe/network_quality_estimator.h
index 02da7517318..556ad97786e 100644
--- a/chromium/net/nqe/network_quality_estimator.h
+++ b/chromium/net/nqe/network_quality_estimator.h
@@ -521,6 +521,10 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// value lower than |effective_connection_type_| may be returned.
EffectiveConnectionType GetCappedECTBasedOnSignalStrength() const;
+ // Clamps the throughput estimate based on the current effective connection
+ // type.
+ void ClampKbpsBasedOnEct();
+
// Determines if the requests to local host can be used in estimating the
// network quality. Set to true only for tests.
bool use_localhost_requests_;
diff --git a/chromium/net/nqe/network_quality_estimator_params.cc b/chromium/net/nqe/network_quality_estimator_params.cc
index e4c5d1a76d4..8b4ba3020fb 100644
--- a/chromium/net/nqe/network_quality_estimator_params.cc
+++ b/chromium/net/nqe/network_quality_estimator_params.cc
@@ -505,6 +505,11 @@ NetworkQualityEstimatorParams::NetworkQualityEstimatorParams(
params_,
"cap_ect_based_on_signal_strength",
"false") == "true"),
+ upper_bound_typical_kbps_multiplier_(
+ GetDoubleValueForVariationParamWithDefaultValue(
+ params_,
+ "upper_bound_typical_kbps_multiplier",
+ 3.5)),
use_small_responses_(false) {
DCHECK(hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ == -1 ||
hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ > 0);
diff --git a/chromium/net/nqe/network_quality_estimator_params.h b/chromium/net/nqe/network_quality_estimator_params.h
index f5f53ff0ebf..f98a2848c08 100644
--- a/chromium/net/nqe/network_quality_estimator_params.h
+++ b/chromium/net/nqe/network_quality_estimator_params.h
@@ -246,6 +246,15 @@ class NET_EXPORT NetworkQualityEstimatorParams {
return cap_ect_based_on_signal_strength_;
}
+ // Returns a multiplier which is used to clamp Kbps on slow connections. For
+ // a given ECT, the upper bound on Kbps is computed based on this returned
+ // multiplier and the typical Kbps for the given ECT. If
+ // upper_bound_typical_kbps_multiplier() is -1, then clamping should be
+ // disabled.
+ double upper_bound_typical_kbps_multiplier() const {
+ return upper_bound_typical_kbps_multiplier_;
+ }
+
// Sets the forced effective connection type as |type|.
void SetForcedEffectiveConnectionTypeForTesting(EffectiveConnectionType type);
@@ -278,6 +287,7 @@ class NET_EXPORT NetworkQualityEstimatorParams {
const base::TimeDelta socket_watchers_min_notification_interval_;
const bool use_end_to_end_rtt_;
const bool cap_ect_based_on_signal_strength_;
+ const double upper_bound_typical_kbps_multiplier_;
bool use_small_responses_;
diff --git a/chromium/net/nqe/network_quality_estimator_unittest.cc b/chromium/net/nqe/network_quality_estimator_unittest.cc
index b92ee2b5055..3456778806e 100644
--- a/chromium/net/nqe/network_quality_estimator_unittest.cc
+++ b/chromium/net/nqe/network_quality_estimator_unittest.cc
@@ -811,7 +811,7 @@ TEST_F(NetworkQualityEstimatorTest, DefaultObservationsOverridden) {
std::map<std::string, std::string> variation_params;
variation_params["Unknown.DefaultMedianKbps"] = "100";
variation_params["WiFi.DefaultMedianKbps"] = "200";
- variation_params["2G.DefaultMedianKbps"] = "300";
+ variation_params["2G.DefaultMedianKbps"] = "250";
variation_params["Unknown.DefaultMedianRTTMsec"] = "1000";
variation_params["WiFi.DefaultMedianRTTMsec"] = "2000";
@@ -878,7 +878,7 @@ TEST_F(NetworkQualityEstimatorTest, DefaultObservationsOverridden) {
EXPECT_EQ(rtt, estimator.GetTransportRTT().value());
EXPECT_TRUE(
estimator.GetRecentDownlinkThroughputKbps(base::TimeTicks(), &kbps));
- EXPECT_EQ(300, kbps);
+ EXPECT_EQ(250, kbps);
EXPECT_EQ(kbps, estimator.GetDownstreamThroughputKbps().value());
// Simulate network change to 3G. Default estimates should be available.
@@ -970,6 +970,78 @@ TEST_F(NetworkQualityEstimatorTest, ObtainThresholdsOnlyRTT) {
}
}
+TEST_F(NetworkQualityEstimatorTest, ClampKbpsBasedOnEct) {
+ const int32_t kTypicalDownlinkKbpsEffectiveConnectionType
+ [net::EFFECTIVE_CONNECTION_TYPE_LAST] = {0, 0, 40, 75, 400, 1600};
+
+ const struct {
+ std::string upper_bound_typical_kbps_multiplier;
+ int32_t set_rtt_msec;
+ int32_t set_downstream_kbps;
+ EffectiveConnectionType expected_ect;
+ int32_t expected_downstream_throughput;
+ } tests[] = {
+ // Clamping multiplier set to 3.5 by default.
+ {"", 3000, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
+ kTypicalDownlinkKbpsEffectiveConnectionType
+ [EFFECTIVE_CONNECTION_TYPE_SLOW_2G] *
+ 3.5},
+ // Clamping disabled.
+ {"-1", 3000, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_SLOW_2G, INT32_MAX},
+ // Clamping multiplier overridden to 1000.
+ {"1000.0", 3000, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
+ kTypicalDownlinkKbpsEffectiveConnectionType
+ [EFFECTIVE_CONNECTION_TYPE_SLOW_2G] *
+ 1000},
+ // Clamping multiplier overridden to 1000.
+ {"1000.0", 1500, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_2G,
+ kTypicalDownlinkKbpsEffectiveConnectionType
+ [EFFECTIVE_CONNECTION_TYPE_2G] *
+ 1000},
+ // Clamping multiplier overridden to 1000.
+ {"1000.0", 700, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_3G,
+ kTypicalDownlinkKbpsEffectiveConnectionType
+ [EFFECTIVE_CONNECTION_TYPE_3G] *
+ 1000},
+ // Clamping multiplier set to 3.5 by default.
+ {"", 500, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_3G,
+ kTypicalDownlinkKbpsEffectiveConnectionType
+ [EFFECTIVE_CONNECTION_TYPE_3G] *
+ 3.5},
+ // Clamping ineffective when the observed throughput is lower than the
+ // clamped throughput.
+ {"", 500, 100, EFFECTIVE_CONNECTION_TYPE_3G, 100},
+ // Clamping disabled on 4G ECT.
+ {"1.0", 40, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_4G, INT32_MAX},
+ // Clamping disabled on 4G ECT.
+ {"1.0", 40, 100, EFFECTIVE_CONNECTION_TYPE_4G, 100},
+ };
+
+ for (const auto& test : tests) {
+ std::map<std::string, std::string> variation_params;
+ variation_params["upper_bound_typical_kbps_multiplier"] =
+ test.upper_bound_typical_kbps_multiplier;
+ TestNetworkQualityEstimator estimator(variation_params);
+
+ // Simulate the connection type as Wi-Fi so that GetEffectiveConnectionType
+ // does not return Offline if the device is offline.
+ estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI,
+ "test");
+
+ estimator.set_recent_http_rtt(
+ base::TimeDelta::FromMilliseconds(test.set_rtt_msec));
+ estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
+ estimator.set_recent_downlink_throughput_kbps(test.set_downstream_kbps);
+ estimator.set_start_time_null_downlink_throughput_kbps(
+ test.set_downstream_kbps);
+ estimator.SetStartTimeNullHttpRtt(
+ base::TimeDelta::FromMilliseconds(test.set_rtt_msec));
+ EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
+ EXPECT_EQ(test.expected_downstream_throughput,
+ estimator.GetDownstreamThroughputKbps().value());
+ }
+}
+
// Tests that default HTTP RTT thresholds for different effective
// connection types are correctly set.
TEST_F(NetworkQualityEstimatorTest, DefaultHttpRTTBasedThresholds) {
@@ -1356,7 +1428,7 @@ TEST_F(NetworkQualityEstimatorTest, MAYBE_TestEffectiveConnectionTypeObserver) {
EXPECT_EQ(0U, observer.effective_connection_types().size());
estimator.SetStartTimeNullHttpRtt(base::TimeDelta::FromMilliseconds(1500));
- estimator.set_start_time_null_downlink_throughput_kbps(100000);
+ estimator.set_start_time_null_downlink_throughput_kbps(164);
tick_clock.Advance(base::TimeDelta::FromMinutes(60));
@@ -1380,9 +1452,9 @@ TEST_F(NetworkQualityEstimatorTest, MAYBE_TestEffectiveConnectionTypeObserver) {
EXPECT_EQ(-1,
estimator.GetNetLogLastIntegerValue(
NetLogEventType::NETWORK_QUALITY_CHANGED, "transport_rtt_ms"));
- EXPECT_EQ(100000, estimator.GetNetLogLastIntegerValue(
- NetLogEventType::NETWORK_QUALITY_CHANGED,
- "downstream_throughput_kbps"));
+ EXPECT_EQ(164, estimator.GetNetLogLastIntegerValue(
+ NetLogEventType::NETWORK_QUALITY_CHANGED,
+ "downstream_throughput_kbps"));
histogram_tester.ExpectUniqueSample("NQE.MainFrame.EffectiveConnectionType",
EFFECTIVE_CONNECTION_TYPE_2G, 1);
diff --git a/chromium/net/proxy_resolution/pac_file_decider.cc b/chromium/net/proxy_resolution/pac_file_decider.cc
index 8b5b37c72b3..2999df80a80 100644
--- a/chromium/net/proxy_resolution/pac_file_decider.cc
+++ b/chromium/net/proxy_resolution/pac_file_decider.cc
@@ -42,8 +42,6 @@ bool LooksLikePacScript(const base::string16& script) {
base::string16::npos;
}
-} // anonymous namespace
-
// This is the hard-coded location used by the DNS portion of web proxy
// auto-discovery.
//
@@ -56,10 +54,17 @@ bool LooksLikePacScript(const base::string16& script) {
//
// For more details, also check out this comment:
// http://code.google.com/p/chromium/issues/detail?id=18575#c20
-namespace {
const char kWpadUrl[] = "http://wpad/wpad.dat";
const int kQuickCheckDelayMs = 1000;
-}; // namespace
+
+} // namespace
+
+PacFileDataWithSource::PacFileDataWithSource() = default;
+PacFileDataWithSource::~PacFileDataWithSource() = default;
+PacFileDataWithSource::PacFileDataWithSource(const PacFileDataWithSource&) =
+ default;
+PacFileDataWithSource& PacFileDataWithSource::operator=(
+ const PacFileDataWithSource&) = default;
std::unique_ptr<base::Value> PacFileDecider::PacSource::NetLogCallback(
const GURL* effective_pac_url,
@@ -156,7 +161,7 @@ const ProxyConfigWithAnnotation& PacFileDecider::effective_config() const {
return effective_config_;
}
-const scoped_refptr<PacFileData>& PacFileDecider::script_data() const {
+const PacFileDataWithSource& PacFileDecider::script_data() const {
DCHECK_EQ(STATE_NONE, next_state_);
return script_data_;
}
@@ -375,12 +380,13 @@ int PacFileDecider::DoVerifyPacScriptComplete(int result) {
const PacSource& pac_source = current_pac_source();
// Extract the current script data.
+ script_data_.from_auto_detect = pac_source.type != PacSource::CUSTOM;
if (fetch_pac_bytes_) {
- script_data_ = PacFileData::FromUTF16(pac_script_);
+ script_data_.data = PacFileData::FromUTF16(pac_script_);
} else {
- script_data_ = pac_source.type == PacSource::CUSTOM
- ? PacFileData::FromURL(pac_source.url)
- : PacFileData::ForAutoDetect();
+ script_data_.data = pac_source.type == PacSource::CUSTOM
+ ? PacFileData::FromURL(pac_source.url)
+ : PacFileData::ForAutoDetect();
}
// Let the caller know which automatic setting we ended up initializing the
diff --git a/chromium/net/proxy_resolution/pac_file_decider.h b/chromium/net/proxy_resolution/pac_file_decider.h
index e1f038d5a69..b41b78a5162 100644
--- a/chromium/net/proxy_resolution/pac_file_decider.h
+++ b/chromium/net/proxy_resolution/pac_file_decider.h
@@ -36,6 +36,24 @@ class NetLogCaptureMode;
class ProxyResolver;
class PacFileFetcher;
+// Structure that encapsulates the result a PacFileData along with an
+// indication of its origin: was it obtained implicitly from auto-detect,
+// or was it read from a more explicitly configured URL.
+//
+// Note that |!from_auto_detect| does NOT imply the script was securely
+// delivered. Most commonly PAC scripts are configured from http:// URLs,
+// both for auto-detect and not.
+struct NET_EXPORT_PRIVATE PacFileDataWithSource {
+ PacFileDataWithSource();
+ explicit PacFileDataWithSource(const PacFileDataWithSource&);
+ ~PacFileDataWithSource();
+
+ PacFileDataWithSource& operator=(const PacFileDataWithSource&);
+
+ scoped_refptr<PacFileData> data;
+ bool from_auto_detect = false;
+};
+
// PacFileDecider is a helper class used by ProxyResolutionService to
// determine which PAC script to use given our proxy configuration.
//
@@ -87,7 +105,7 @@ class NET_EXPORT_PRIVATE PacFileDecider {
const ProxyConfigWithAnnotation& effective_config() const;
- const scoped_refptr<PacFileData>& script_data() const;
+ const PacFileDataWithSource& script_data() const;
void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; }
@@ -197,7 +215,7 @@ class NET_EXPORT_PRIVATE PacFileDecider {
// Results.
ProxyConfigWithAnnotation effective_config_;
- scoped_refptr<PacFileData> script_data_;
+ PacFileDataWithSource script_data_;
std::unique_ptr<HostResolver::ResolveHostRequest> resolve_request_;
diff --git a/chromium/net/proxy_resolution/pac_file_decider_unittest.cc b/chromium/net/proxy_resolution/pac_file_decider_unittest.cc
index fd10db4204b..3d736718386 100644
--- a/chromium/net/proxy_resolution/pac_file_decider_unittest.cc
+++ b/chromium/net/proxy_resolution/pac_file_decider_unittest.cc
@@ -215,7 +215,8 @@ TEST(PacFileDeciderTest, CustomPacSucceeds) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsOk());
- EXPECT_EQ(rule.text(), decider.script_data()->utf16());
+ EXPECT_EQ(rule.text(), decider.script_data().data->utf16());
+ EXPECT_FALSE(decider.script_data().from_auto_detect);
// Check the NetLog was filled correctly.
TestNetLogEntry::List entries;
@@ -253,7 +254,7 @@ TEST(PacFileDeciderTest, CustomPacFails1) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsError(kFailedDownloading));
- EXPECT_FALSE(decider.script_data());
+ EXPECT_FALSE(decider.script_data().data);
// Check the NetLog was filled correctly.
TestNetLogEntry::List entries;
@@ -289,7 +290,7 @@ TEST(PacFileDeciderTest, CustomPacFails2) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsError(kFailedParsing));
- EXPECT_FALSE(decider.script_data());
+ EXPECT_FALSE(decider.script_data().data);
}
// Fail downloading the custom PAC script, because the fetcher was NULL.
@@ -306,7 +307,7 @@ TEST(PacFileDeciderTest, HasNullPacFileFetcher) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsError(ERR_UNEXPECTED));
- EXPECT_FALSE(decider.script_data());
+ EXPECT_FALSE(decider.script_data().data);
}
// Succeeds in choosing autodetect (WPAD DNS).
@@ -326,7 +327,8 @@ TEST(PacFileDeciderTest, AutodetectSuccess) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsOk());
- EXPECT_EQ(rule.text(), decider.script_data()->utf16());
+ EXPECT_EQ(rule.text(), decider.script_data().data->utf16());
+ EXPECT_TRUE(decider.script_data().from_auto_detect);
EXPECT_TRUE(decider.effective_config().value().has_pac_url());
EXPECT_EQ(rule.url, decider.effective_config().value().pac_url());
@@ -371,7 +373,8 @@ TEST_F(PacFileDeciderQuickCheckTest, SyncSuccess) {
resolver_.rules_map()[HostResolverSource::SYSTEM]->AddRule("wpad", "1.2.3.4");
EXPECT_THAT(StartDecider(), IsOk());
- EXPECT_EQ(rule_.text(), decider_->script_data()->utf16());
+ EXPECT_EQ(rule_.text(), decider_->script_data().data->utf16());
+ EXPECT_TRUE(decider_->script_data().from_auto_detect);
EXPECT_TRUE(decider_->effective_config().value().has_pac_url());
EXPECT_EQ(rule_.url, decider_->effective_config().value().pac_url());
@@ -388,7 +391,8 @@ TEST_F(PacFileDeciderQuickCheckTest, AsyncSuccess) {
resolver_.ResolveAllPending();
callback_.WaitForResult();
EXPECT_FALSE(resolver_.has_pending_requests());
- EXPECT_EQ(rule_.text(), decider_->script_data()->utf16());
+ EXPECT_EQ(rule_.text(), decider_->script_data().data->utf16());
+ EXPECT_TRUE(decider_->script_data().from_auto_detect);
EXPECT_TRUE(decider_->effective_config().value().has_pac_url());
EXPECT_EQ(rule_.url, decider_->effective_config().value().pac_url());
}
@@ -500,7 +504,8 @@ TEST(PacFileDeciderTest, AutodetectFailCustomSuccess1) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsOk());
- EXPECT_EQ(rule.text(), decider.script_data()->utf16());
+ EXPECT_EQ(rule.text(), decider.script_data().data->utf16());
+ EXPECT_FALSE(decider.script_data().from_auto_detect);
EXPECT_TRUE(decider.effective_config().value().has_pac_url());
EXPECT_EQ(rule.url, decider.effective_config().value().pac_url());
@@ -529,7 +534,8 @@ TEST(PacFileDeciderTest, AutodetectFailCustomSuccess2) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsOk());
- EXPECT_EQ(rule.text(), decider.script_data()->utf16());
+ EXPECT_EQ(rule.text(), decider.script_data().data->utf16());
+ EXPECT_FALSE(decider.script_data().from_auto_detect);
// Verify that the effective configuration no longer contains auto detect or
// any of the manual settings.
@@ -592,7 +598,7 @@ TEST(PacFileDeciderTest, AutodetectFailCustomFails1) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsError(kFailedDownloading));
- EXPECT_FALSE(decider.script_data());
+ EXPECT_FALSE(decider.script_data().data);
}
// Fails at WPAD (downloading), and fails at custom PAC (parsing).
@@ -614,7 +620,7 @@ TEST(PacFileDeciderTest, AutodetectFailCustomFails2) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsError(kFailedParsing));
- EXPECT_FALSE(decider.script_data());
+ EXPECT_FALSE(decider.script_data().data);
}
// This is a copy-paste of CustomPacFails1, with the exception that we give it
@@ -642,7 +648,7 @@ TEST(PacFileDeciderTest, CustomPacFails1_WithPositiveDelay) {
IsError(ERR_IO_PENDING));
EXPECT_THAT(callback.WaitForResult(), IsError(kFailedDownloading));
- EXPECT_FALSE(decider.script_data());
+ EXPECT_FALSE(decider.script_data().data);
// Check the NetLog was filled correctly.
TestNetLogEntry::List entries;
@@ -684,7 +690,7 @@ TEST(PacFileDeciderTest, CustomPacFails1_WithNegativeDelay) {
ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta::FromSeconds(-5), true, callback.callback()),
IsError(kFailedDownloading));
- EXPECT_FALSE(decider.script_data());
+ EXPECT_FALSE(decider.script_data().data);
// Check the NetLog was filled correctly.
TestNetLogEntry::List entries;
@@ -752,7 +758,8 @@ TEST(PacFileDeciderTest, AutodetectDhcpSuccess) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsOk());
- EXPECT_EQ(dhcp_fetcher.expected_text(), decider.script_data()->utf16());
+ EXPECT_EQ(dhcp_fetcher.expected_text(), decider.script_data().data->utf16());
+ EXPECT_TRUE(decider.script_data().from_auto_detect);
EXPECT_TRUE(decider.effective_config().value().has_pac_url());
EXPECT_EQ(GURL("http://dhcppac/"),
@@ -779,7 +786,7 @@ TEST(PacFileDeciderTest, AutodetectDhcpFailParse) {
config, TRAFFIC_ANNOTATION_FOR_TESTS),
base::TimeDelta(), true, callback.callback()),
IsError(kFailedDownloading));
- EXPECT_FALSE(decider.script_data());
+ EXPECT_FALSE(decider.script_data().data);
EXPECT_FALSE(decider.effective_config().value().has_pac_url());
}
diff --git a/chromium/net/proxy_resolution/proxy_info.cc b/chromium/net/proxy_resolution/proxy_info.cc
index cb0bf4eb0f6..762756d9a4e 100644
--- a/chromium/net/proxy_resolution/proxy_info.cc
+++ b/chromium/net/proxy_resolution/proxy_info.cc
@@ -8,7 +8,10 @@
namespace net {
-ProxyInfo::ProxyInfo() : did_bypass_proxy_(false), did_use_pac_script_(false) {}
+ProxyInfo::ProxyInfo()
+ : did_bypass_proxy_(false),
+ did_use_pac_script_(false),
+ did_use_auto_detected_pac_script_(false) {}
ProxyInfo::ProxyInfo(const ProxyInfo& other) = default;
@@ -22,6 +25,7 @@ void ProxyInfo::Use(const ProxyInfo& other) {
traffic_annotation_ = other.traffic_annotation_;
did_bypass_proxy_ = other.did_bypass_proxy_;
did_use_pac_script_ = other.did_use_pac_script_;
+ did_use_auto_detected_pac_script_ = other.did_use_auto_detected_pac_script_;
}
void ProxyInfo::UseDirect() {
@@ -88,6 +92,7 @@ void ProxyInfo::Reset() {
traffic_annotation_.reset();
did_bypass_proxy_ = false;
did_use_pac_script_ = false;
+ did_use_auto_detected_pac_script_ = false;
}
} // namespace net
diff --git a/chromium/net/proxy_resolution/proxy_info.h b/chromium/net/proxy_resolution/proxy_info.h
index e3ea8da6a07..daa5862ebda 100644
--- a/chromium/net/proxy_resolution/proxy_info.h
+++ b/chromium/net/proxy_resolution/proxy_info.h
@@ -127,6 +127,12 @@ class NET_EXPORT ProxyInfo {
return did_use_pac_script_;
}
+ // Returns true if the proxy list was obtained from a PAC script that
+ // was auto-detected.
+ bool did_use_auto_detected_pac_script() const {
+ return did_use_auto_detected_pac_script_;
+ }
+
// Returns the first valid proxy server. is_empty() must be false to be able
// to call this function.
const ProxyServer& proxy_server() const { return proxy_list_.Get(); }
@@ -203,6 +209,7 @@ class NET_EXPORT ProxyInfo {
// Whether we used a PAC script for resolving the proxy.
bool did_use_pac_script_;
+ bool did_use_auto_detected_pac_script_;
// How long it took to resolve the proxy. Times are both null if proxy was
// determined synchronously without running a PAC.
diff --git a/chromium/net/proxy_resolution/proxy_resolution_service.cc b/chromium/net/proxy_resolution/proxy_resolution_service.cc
index cf2a9621221..155119ff73c 100644
--- a/chromium/net/proxy_resolution/proxy_resolution_service.cc
+++ b/chromium/net/proxy_resolution/proxy_resolution_service.cc
@@ -432,6 +432,7 @@ class ProxyResolutionService::InitProxyResolver {
InitProxyResolver()
: proxy_resolver_factory_(nullptr),
proxy_resolver_(NULL),
+ resolver_using_auto_detected_script_(nullptr),
next_state_(STATE_NONE),
quick_check_enabled_(true) {}
@@ -442,8 +443,12 @@ class ProxyResolutionService::InitProxyResolver {
// Begins initializing the proxy resolver; calls |callback| when done. A
// ProxyResolver instance will be created using |proxy_resolver_factory| and
- // returned via |proxy_resolver| if the final result is OK.
+ // assigned to |*proxy_resolver| if the final result is OK.
+ // |*resolver_using_auto_detected_script| will be set to true if
+ // |proxy_resolver| was initialized using script data that originates from
+ // proxy auto-detection.
int Start(std::unique_ptr<ProxyResolver>* proxy_resolver,
+ bool* resolver_using_auto_detected_script,
ProxyResolverFactory* proxy_resolver_factory,
PacFileFetcher* pac_file_fetcher,
DhcpPacFileFetcher* dhcp_pac_file_fetcher,
@@ -453,6 +458,7 @@ class ProxyResolutionService::InitProxyResolver {
CompletionOnceCallback callback) {
DCHECK_EQ(STATE_NONE, next_state_);
proxy_resolver_ = proxy_resolver;
+ resolver_using_auto_detected_script_ = resolver_using_auto_detected_script;
proxy_resolver_factory_ = proxy_resolver_factory;
decider_.reset(
@@ -469,16 +475,21 @@ class ProxyResolutionService::InitProxyResolver {
// Similar to Start(), however it skips the PacFileDecider stage. Instead
// |effective_config|, |decider_result| and |script_data| will be used as the
// inputs for initializing the ProxyResolver. A ProxyResolver instance will
- // be created using |proxy_resolver_factory| and returned via
- // |proxy_resolver| if the final result is OK.
+ // be created using |proxy_resolver_factory| and assigned to
+ // |*proxy_resolver| if the final result is OK.
+ // |*resolver_using_auto_detected_script| will be set to true if
+ // |proxy_resolver| was initialized using script data that originates from
+ // proxy auto-detection.
int StartSkipDecider(std::unique_ptr<ProxyResolver>* proxy_resolver,
+ bool* resolver_using_auto_detected_script,
ProxyResolverFactory* proxy_resolver_factory,
const ProxyConfigWithAnnotation& effective_config,
int decider_result,
- PacFileData* script_data,
+ const PacFileDataWithSource& script_data,
CompletionOnceCallback callback) {
DCHECK_EQ(STATE_NONE, next_state_);
proxy_resolver_ = proxy_resolver;
+ resolver_using_auto_detected_script_ = resolver_using_auto_detected_script;
proxy_resolver_factory_ = proxy_resolver_factory;
effective_config_ = effective_config;
@@ -501,7 +512,7 @@ class ProxyResolutionService::InitProxyResolver {
// Returns the PAC script data that was selected by PacFileDecider.
// Should only be called upon completion of the initialization.
- const scoped_refptr<PacFileData>& script_data() {
+ const PacFileDataWithSource& script_data() {
DCHECK_EQ(STATE_NONE, next_state_);
return script_data_;
}
@@ -583,18 +594,21 @@ class ProxyResolutionService::InitProxyResolver {
}
int DoCreateResolver() {
- DCHECK(script_data_.get());
+ DCHECK(script_data_.data);
// TODO(eroman): Should log this latency to the NetLog.
next_state_ = STATE_CREATE_RESOLVER_COMPLETE;
return proxy_resolver_factory_->CreateProxyResolver(
- script_data_, proxy_resolver_,
+ script_data_.data, proxy_resolver_,
base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)),
&create_resolver_request_);
}
int DoCreateResolverComplete(int result) {
- if (result != OK)
+ if (result == OK) {
+ *resolver_using_auto_detected_script_ = script_data_.from_auto_detect;
+ } else {
proxy_resolver_->reset();
+ }
return result;
}
@@ -607,12 +621,13 @@ class ProxyResolutionService::InitProxyResolver {
ProxyConfigWithAnnotation config_;
ProxyConfigWithAnnotation effective_config_;
- scoped_refptr<PacFileData> script_data_;
+ PacFileDataWithSource script_data_;
TimeDelta wait_delay_;
std::unique_ptr<PacFileDecider> decider_;
ProxyResolverFactory* proxy_resolver_factory_;
std::unique_ptr<ProxyResolverFactory::Request> create_resolver_request_;
std::unique_ptr<ProxyResolver>* proxy_resolver_;
+ bool* resolver_using_auto_detected_script_;
CompletionOnceCallback callback_;
State next_state_;
bool quick_check_enabled_;
@@ -629,7 +644,7 @@ class ProxyResolutionService::InitProxyResolver {
class ProxyResolutionService::PacFileDeciderPoller {
public:
typedef base::Callback<
- void(int, PacFileData*, const ProxyConfigWithAnnotation&)>
+ void(int, const PacFileDataWithSource&, const ProxyConfigWithAnnotation&)>
ChangeCallback;
// Builds a poller helper, and starts polling for updates. Whenever a change
@@ -658,7 +673,7 @@ class ProxyResolutionService::PacFileDeciderPoller {
PacFileFetcher* pac_file_fetcher,
DhcpPacFileFetcher* dhcp_pac_file_fetcher,
int init_net_error,
- const scoped_refptr<PacFileData>& init_script_data,
+ const PacFileDataWithSource& init_script_data,
NetLog* net_log)
: change_callback_(callback),
config_(config),
@@ -768,7 +783,7 @@ class ProxyResolutionService::PacFileDeciderPoller {
}
bool HasScriptDataChanged(int result,
- const scoped_refptr<PacFileData>& script_data) {
+ const PacFileDataWithSource& script_data) {
if (result != last_error_) {
// Something changed -- it was failing before and now it succeeded, or
// conversely it succeeded before and now it failed. Or it failed in
@@ -785,16 +800,17 @@ class ProxyResolutionService::PacFileDeciderPoller {
// Otherwise if it succeeded both this time and last time, we need to look
// closer and see if we ended up downloading different content for the PAC
// script.
- return !script_data->Equals(last_script_data_.get());
+ return !script_data.data->Equals(last_script_data_.data.get()) ||
+ (script_data.from_auto_detect != last_script_data_.from_auto_detect);
}
void NotifyProxyResolutionServiceOfChange(
int result,
- const scoped_refptr<PacFileData>& script_data,
+ const PacFileDataWithSource& script_data,
const ProxyConfigWithAnnotation& effective_config) {
// Note that |this| may be deleted after calling into the
// ProxyResolutionService.
- change_callback_.Run(result, script_data.get(), effective_config);
+ change_callback_.Run(result, script_data, effective_config);
}
ChangeCallback change_callback_;
@@ -804,7 +820,7 @@ class ProxyResolutionService::PacFileDeciderPoller {
DhcpPacFileFetcher* dhcp_pac_file_fetcher_;
int last_error_;
- scoped_refptr<PacFileData> last_script_data_;
+ PacFileDataWithSource last_script_data_;
std::unique_ptr<PacFileDecider> decider_;
TimeDelta next_poll_delay_;
@@ -879,6 +895,7 @@ class ProxyResolutionService::RequestImpl
// Outstanding requests are cancelled during ~ProxyResolutionService, so this
// is guaranteed to be valid throughout our lifetime.
ProxyResolutionService* service_;
+ bool resolver_using_auto_detected_script_;
CompletionOnceCallback user_callback_;
ProxyInfo* results_;
GURL url_;
@@ -937,6 +954,8 @@ int ProxyResolutionService::RequestImpl::Start() {
if (service_->ApplyPacBypassRules(url_, results_))
return OK;
+ resolver_using_auto_detected_script_ =
+ service_->resolver_using_auto_detected_script_;
return resolver()->GetProxyForURL(
url_, results_,
base::Bind(&ProxyResolutionService::RequestImpl::QueryComplete,
@@ -974,6 +993,8 @@ int ProxyResolutionService::RequestImpl::QueryDidComplete(int result_code) {
// Make a note in the results which configuration was in use at the
// time of the resolve.
results_->did_use_pac_script_ = true;
+ results_->did_use_auto_detected_pac_script_ =
+ resolver_using_auto_detected_script_;
results_->proxy_resolve_start_time_ = creation_time_;
results_->proxy_resolve_end_time_ = TimeTicks::Now();
@@ -1105,6 +1126,22 @@ ProxyResolutionService::CreateFixedFromPacResult(
// ProxyResolver dependency we give it will never be used.
std::unique_ptr<ProxyConfigService> proxy_config_service(
new ProxyConfigServiceFixed(ProxyConfigWithAnnotation(
+ ProxyConfig::CreateFromCustomPacURL(
+ GURL("https://my-pac-script.invalid/wpad.dat")),
+ traffic_annotation)));
+
+ return std::make_unique<ProxyResolutionService>(
+ std::move(proxy_config_service),
+ std::make_unique<ProxyResolverFactoryForPacResult>(pac_string), nullptr);
+}
+
+// static
+std::unique_ptr<ProxyResolutionService>
+ProxyResolutionService::CreateFixedFromAutoDetectedPacResult(
+ const std::string& pac_string,
+ const NetworkTrafficAnnotationTag& traffic_annotation) {
+ std::unique_ptr<ProxyConfigService> proxy_config_service(
+ new ProxyConfigServiceFixed(ProxyConfigWithAnnotation(
ProxyConfig::CreateAutoDetect(), traffic_annotation)));
return std::make_unique<ProxyResolutionService>(
@@ -1655,7 +1692,8 @@ void ProxyResolutionService::InitializeUsingLastFetchedConfig() {
init_proxy_resolver_.reset(new InitProxyResolver());
init_proxy_resolver_->set_quick_check_enabled(quick_check_enabled_);
int rv = init_proxy_resolver_->Start(
- &resolver_, resolver_factory_.get(), pac_file_fetcher_.get(),
+ &resolver_, &resolver_using_auto_detected_script_,
+ resolver_factory_.get(), pac_file_fetcher_.get(),
dhcp_pac_file_fetcher_.get(), net_log_, fetched_config_.value(),
wait_delay,
base::Bind(&ProxyResolutionService::OnInitProxyResolverComplete,
@@ -1667,7 +1705,7 @@ void ProxyResolutionService::InitializeUsingLastFetchedConfig() {
void ProxyResolutionService::InitializeUsingDecidedConfig(
int decider_result,
- PacFileData* script_data,
+ const PacFileDataWithSource& script_data,
const ProxyConfigWithAnnotation& effective_config) {
DCHECK(fetched_config_);
DCHECK(fetched_config_->value().HasAutomaticSettings());
@@ -1678,8 +1716,8 @@ void ProxyResolutionService::InitializeUsingDecidedConfig(
init_proxy_resolver_.reset(new InitProxyResolver());
int rv = init_proxy_resolver_->StartSkipDecider(
- &resolver_, resolver_factory_.get(), effective_config, decider_result,
- script_data,
+ &resolver_, &resolver_using_auto_detected_script_,
+ resolver_factory_.get(), effective_config, decider_result, script_data,
base::Bind(&ProxyResolutionService::OnInitProxyResolverComplete,
base::Unretained(this)));
diff --git a/chromium/net/proxy_resolution/proxy_resolution_service.h b/chromium/net/proxy_resolution/proxy_resolution_service.h
index 6d7f7ed301a..3ead15516ce 100644
--- a/chromium/net/proxy_resolution/proxy_resolution_service.h
+++ b/chromium/net/proxy_resolution/proxy_resolution_service.h
@@ -41,10 +41,10 @@ namespace net {
class DhcpPacFileFetcher;
class NetLog;
+class PacFileFetcher;
class ProxyDelegate;
class ProxyResolverFactory;
-class PacFileData;
-class PacFileFetcher;
+struct PacFileDataWithSource;
// This class can be used to resolve the proxy server to use when loading a
// HTTP(S) URL. It uses the given ProxyResolver to handle the actual proxy
@@ -270,6 +270,13 @@ class NET_EXPORT ProxyResolutionService
const std::string& pac_string,
const NetworkTrafficAnnotationTag& traffic_annotation);
+ // Same as CreateFixedFromPacResult(), except the resulting ProxyInfo from
+ // resolutions will be tagged as having been auto-detected.
+ static std::unique_ptr<ProxyResolutionService>
+ CreateFixedFromAutoDetectedPacResult(
+ const std::string& pac_string,
+ const NetworkTrafficAnnotationTag& traffic_annotation);
+
// Creates a config service appropriate for this platform that fetches the
// system proxy settings. |main_task_runner| is the thread where the consumer
// of the ProxyConfigService will live.
@@ -374,7 +381,7 @@ class NET_EXPORT ProxyResolutionService
// Start the initialization skipping past the "decision" phase.
void InitializeUsingDecidedConfig(
int decider_result,
- PacFileData* script_data,
+ const PacFileDataWithSource& script_data,
const ProxyConfigWithAnnotation& effective_config);
// NetworkChangeNotifier::IPAddressObserver
@@ -398,7 +405,12 @@ class NET_EXPORT ProxyResolutionService
std::unique_ptr<ProxyConfigService> config_service_;
std::unique_ptr<ProxyResolverFactory> resolver_factory_;
+
+ // If non-null, the initialized ProxyResolver to use for requests, and a
+ // boolean indicating whether it was initialized using an auto-detected
+ // script.
std::unique_ptr<ProxyResolver> resolver_;
+ bool resolver_using_auto_detected_script_;
// We store the proxy configuration that was last fetched from the
// ProxyConfigService, as well as the resulting "effective" configuration.
diff --git a/chromium/net/quic/quic_proxy_client_socket.cc b/chromium/net/quic/quic_proxy_client_socket.cc
index f870a8b72c4..2d04bdf4411 100644
--- a/chromium/net/quic/quic_proxy_client_socket.cc
+++ b/chromium/net/quic/quic_proxy_client_socket.cc
@@ -415,7 +415,7 @@ int QuicProxyClientSocket::DoReadReplyComplete(int result) {
redirect_has_load_timing_info_ =
GetLoadTimingInfo(&redirect_load_timing_info_);
next_state_ = STATE_DISCONNECTED;
- return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
+ return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT;
case 407: // Proxy Authentication Required
next_state_ = STATE_CONNECT_COMPLETE;
diff --git a/chromium/net/quic/quic_proxy_client_socket_unittest.cc b/chromium/net/quic/quic_proxy_client_socket_unittest.cc
index 0c4411f1b8d..a385cc1df87 100644
--- a/chromium/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/chromium/net/quic/quic_proxy_client_socket_unittest.cc
@@ -656,7 +656,7 @@ TEST_P(QuicProxyClientSocketTest, ConnectRedirects) {
Initialize();
- AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
+ AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT);
const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
ASSERT_TRUE(response != nullptr);
diff --git a/chromium/net/socket/ssl_client_socket_pool.cc b/chromium/net/socket/ssl_client_socket_pool.cc
index 190b096dcf9..6b78c0de20c 100644
--- a/chromium/net/socket/ssl_client_socket_pool.cc
+++ b/chromium/net/socket/ssl_client_socket_pool.cc
@@ -310,7 +310,7 @@ int SSLConnectJob::DoTunnelConnectComplete(int result) {
if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
error_response_info_ = transport_socket_handle_->ssl_error_response_info();
} else if (result == ERR_PROXY_AUTH_REQUESTED ||
- result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
+ result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT) {
StreamSocket* socket = transport_socket_handle_->socket();
ProxyClientSocket* tunnel_socket = static_cast<ProxyClientSocket*>(socket);
error_response_info_ = *tunnel_socket->GetConnectResponseInfo();
diff --git a/chromium/net/spdy/fuzzing/hpack_decoder_fuzzer.cc b/chromium/net/spdy/fuzzing/hpack_decoder_fuzzer.cc
deleted file mode 100644
index 16df5e09e8a..00000000000
--- a/chromium/net/spdy/fuzzing/hpack_decoder_fuzzer.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <list>
-#include <vector>
-
-#include "base/test/fuzzed_data_provider.h"
-#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h"
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- // At least 4 bytes of fuzz data are needed to generate a max string size.
- if (size < 4)
- return 0;
-
- base::FuzzedDataProvider fuzzed_data_provider(data, size);
- size_t max_string_size =
- fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 10 * size);
- http2::HpackDecoder decoder(http2::HpackDecoderNoOpListener::NoOpListener(),
- max_string_size);
- decoder.StartDecodingBlock();
-
- // Store all chunks in a function scope list, as the API requires the caller
- // to make sure the fragment chunks data is accessible during the whole
- // decoding process. |http2::DecodeBuffer| does not copy the data, it is just
- // a wrapper for the chunk provided in its constructor.
- std::list<std::vector<char>> all_chunks;
- while (fuzzed_data_provider.remaining_bytes() > 0) {
- size_t chunk_size = fuzzed_data_provider.ConsumeIntegralInRange(1, 32);
- all_chunks.emplace_back(
- fuzzed_data_provider.ConsumeBytes<char>(chunk_size));
- const auto& chunk = all_chunks.back();
-
- // http2::DecodeBuffer constructor does not accept nullptr buffer.
- if (chunk.data() == nullptr)
- continue;
-
- http2::DecodeBuffer fragment(chunk.data(), chunk.size());
- decoder.DecodeFragment(&fragment);
- }
- decoder.EndDecodingBlock();
- return 0;
-}
diff --git a/chromium/net/spdy/fuzzing/hpack_example_generator.cc b/chromium/net/spdy/fuzzing/hpack_example_generator.cc
deleted file mode 100644
index c38b28870f3..00000000000
--- a/chromium/net/spdy/fuzzing/hpack_example_generator.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "net/spdy/fuzzing/hpack_fuzz_util.h"
-#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
-#include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h"
-#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
-
-namespace {
-
-// Target file for generated HPACK header sets.
-const char kFileToWrite[] = "file-to-write";
-
-// Number of header sets to generate.
-const char kExampleCount[] = "example-count";
-
-} // namespace
-
-using spdy::HpackFuzzUtil;
-using spdy::SpdyString;
-using std::map;
-
-// Generates a configurable number of header sets (using HpackFuzzUtil), and
-// sequentially encodes each header set with an HpackEncoder. Encoded header
-// sets are written to the output file in length-prefixed blocks.
-int main(int argc, char** argv) {
- base::AtExitManager exit_manager;
-
- base::CommandLine::Init(argc, argv);
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
-
- if (!command_line.HasSwitch(kFileToWrite) ||
- !command_line.HasSwitch(kExampleCount)) {
- LOG(ERROR) << "Usage: " << argv[0] << " --" << kFileToWrite
- << "=/path/to/file.out"
- << " --" << kExampleCount << "=1000";
- return -1;
- }
- spdy::SpdyString file_to_write =
- command_line.GetSwitchValueASCII(kFileToWrite);
-
- int example_count = 0;
- base::StringToInt(command_line.GetSwitchValueASCII(kExampleCount),
- &example_count);
-
- DVLOG(1) << "Writing output to " << file_to_write;
- base::File file_out(base::FilePath::FromUTF8Unsafe(file_to_write),
- base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- CHECK(file_out.IsValid()) << file_out.error_details();
-
- HpackFuzzUtil::GeneratorContext context;
- HpackFuzzUtil::InitializeGeneratorContext(&context);
- spdy::HpackEncoder encoder(spdy::ObtainHpackHuffmanTable());
-
- for (int i = 0; i != example_count; ++i) {
- spdy::SpdyHeaderBlock headers =
- HpackFuzzUtil::NextGeneratedHeaderSet(&context);
-
- spdy::SpdyString buffer;
- CHECK(encoder.EncodeHeaderSet(headers, &buffer));
-
- spdy::SpdyString prefix = HpackFuzzUtil::HeaderBlockPrefix(buffer.size());
-
- CHECK_LT(0, file_out.WriteAtCurrentPos(prefix.data(), prefix.size()));
- CHECK_LT(0, file_out.WriteAtCurrentPos(buffer.data(), buffer.size()));
- }
- CHECK(file_out.Flush());
- DVLOG(1) << "Generated " << example_count << " blocks.";
- return 0;
-}
diff --git a/chromium/net/spdy/fuzzing/hpack_fuzz_util.cc b/chromium/net/spdy/fuzzing/hpack_fuzz_util.cc
deleted file mode 100644
index 400ed0dde09..00000000000
--- a/chromium/net/spdy/fuzzing/hpack_fuzz_util.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/spdy/fuzzing/hpack_fuzz_util.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include "base/rand_util.h"
-#include "base/sys_byteorder.h"
-#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
-
-namespace spdy {
-
-namespace {
-
-// Sampled exponential distribution parameters:
-// Number of headers in each header set.
-const size_t kHeaderCountMean = 7;
-const size_t kHeaderCountMax = 50;
-// Selected index within list of headers.
-const size_t kHeaderIndexMean = 20;
-const size_t kHeaderIndexMax = 200;
-// Approximate distribution of header name lengths.
-const size_t kNameLengthMean = 5;
-const size_t kNameLengthMax = 30;
-// Approximate distribution of header value lengths.
-const size_t kValueLengthMean = 15;
-const size_t kValueLengthMax = 75;
-
-} // namespace
-
-using base::RandBytesAsString;
-using std::map;
-
-HpackFuzzUtil::GeneratorContext::GeneratorContext() = default;
-HpackFuzzUtil::GeneratorContext::~GeneratorContext() = default;
-
-HpackFuzzUtil::Input::Input() : offset(0) {}
-HpackFuzzUtil::Input::~Input() = default;
-
-HpackFuzzUtil::FuzzerContext::FuzzerContext() = default;
-HpackFuzzUtil::FuzzerContext::~FuzzerContext() = default;
-
-// static
-void HpackFuzzUtil::InitializeGeneratorContext(GeneratorContext* context) {
- // Seed the generator with common header fixtures.
- context->names.push_back(":authority");
- context->names.push_back(":path");
- context->names.push_back(":status");
- context->names.push_back("cookie");
- context->names.push_back("content-type");
- context->names.push_back("cache-control");
- context->names.push_back("date");
- context->names.push_back("user-agent");
- context->names.push_back("via");
-
- context->values.push_back("/");
- context->values.push_back("/index.html");
- context->values.push_back("200");
- context->values.push_back("404");
- context->values.push_back("");
- context->values.push_back("baz=bing; foo=bar; garbage");
- context->values.push_back("baz=bing; fizzle=fazzle; garbage");
- context->values.push_back("rudolph=the-red-nosed-reindeer");
- context->values.push_back("had=a;very_shiny=nose");
- context->values.push_back("and\0if\0you\0ever\1saw\0it;");
- context->values.push_back("u; would=even;say-it\xffglows");
-}
-
-// static
-SpdyHeaderBlock HpackFuzzUtil::NextGeneratedHeaderSet(
- GeneratorContext* context) {
- SpdyHeaderBlock headers;
-
- size_t header_count =
- 1 + SampleExponential(kHeaderCountMean, kHeaderCountMax);
- for (size_t j = 0; j != header_count; ++j) {
- size_t name_index = SampleExponential(kHeaderIndexMean, kHeaderIndexMax);
- size_t value_index = SampleExponential(kHeaderIndexMean, kHeaderIndexMax);
- SpdyString name, value;
- if (name_index >= context->names.size()) {
- context->names.push_back(RandBytesAsString(
- 1 + SampleExponential(kNameLengthMean, kNameLengthMax)));
- name = context->names.back();
- } else {
- name = context->names[name_index];
- }
- if (value_index >= context->values.size()) {
- context->values.push_back(RandBytesAsString(
- 1 + SampleExponential(kValueLengthMean, kValueLengthMax)));
- value = context->values.back();
- } else {
- value = context->values[value_index];
- }
- headers[name] = value;
- }
- return headers;
-}
-
-// static
-size_t HpackFuzzUtil::SampleExponential(size_t mean, size_t sanity_bound) {
- return std::min(static_cast<size_t>(-std::log(base::RandDouble()) * mean),
- sanity_bound);
-}
-
-// static
-bool HpackFuzzUtil::NextHeaderBlock(Input* input, SpdyStringPiece* out) {
- // ClusterFuzz may truncate input files if the fuzzer ran out of allocated
- // disk space. Be tolerant of these.
- CHECK_LE(input->offset, input->input.size());
- if (input->remaining() < sizeof(uint32_t)) {
- return false;
- }
-
- size_t length =
- base::NetToHost32(*reinterpret_cast<const uint32_t*>(input->ptr()));
- input->offset += sizeof(uint32_t);
-
- if (input->remaining() < length) {
- return false;
- }
- *out = SpdyStringPiece(input->ptr(), length);
- input->offset += length;
- return true;
-}
-
-// static
-SpdyString HpackFuzzUtil::HeaderBlockPrefix(size_t block_size) {
- uint32_t length = base::HostToNet32(static_cast<uint32_t>(block_size));
- return SpdyString(reinterpret_cast<char*>(&length), sizeof(uint32_t));
-}
-
-// static
-void HpackFuzzUtil::InitializeFuzzerContext(FuzzerContext* context) {
- context->first_stage = SpdyMakeUnique<HpackDecoderAdapter>();
- context->second_stage =
- SpdyMakeUnique<HpackEncoder>(ObtainHpackHuffmanTable());
- context->third_stage = SpdyMakeUnique<HpackDecoderAdapter>();
-}
-
-// static
-bool HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(
- FuzzerContext* context,
- SpdyStringPiece input_block) {
- // First stage: Decode the input header block. This may fail on invalid input.
- if (!context->first_stage->HandleControlFrameHeadersData(
- input_block.data(), input_block.size())) {
- return false;
- }
- if (!context->first_stage->HandleControlFrameHeadersComplete(nullptr)) {
- return false;
- }
- // Second stage: Re-encode the decoded header block. This must succeed.
- SpdyString second_stage_out;
- CHECK(context->second_stage->EncodeHeaderSet(
- context->first_stage->decoded_block(), &second_stage_out));
-
- // Third stage: Expect a decoding of the re-encoded block to succeed, but
- // don't require it. It's possible for the stage-two encoder to produce an
- // output which violates decoder size tolerances.
- if (!context->third_stage->HandleControlFrameHeadersData(
- second_stage_out.data(), second_stage_out.length())) {
- return false;
- }
- if (!context->third_stage->HandleControlFrameHeadersComplete(nullptr)) {
- return false;
- }
- return true;
-}
-
-// static
-void HpackFuzzUtil::FlipBits(uint8_t* buffer,
- size_t buffer_length,
- size_t flip_per_thousand) {
- uint64_t buffer_bit_length = buffer_length * 8u;
- uint64_t bits_to_flip = flip_per_thousand * (1 + buffer_bit_length / 1024);
-
- // Iteratively identify & flip offsets in the buffer bit-sequence.
- for (uint64_t i = 0; i != bits_to_flip; ++i) {
- uint64_t bit_offset = base::RandUint64() % buffer_bit_length;
- buffer[bit_offset / 8u] ^= (1 << (bit_offset % 8u));
- }
-}
-
-} // namespace spdy
diff --git a/chromium/net/spdy/fuzzing/hpack_fuzz_util.h b/chromium/net/spdy/fuzzing/hpack_fuzz_util.h
deleted file mode 100644
index 5d95ca22d29..00000000000
--- a/chromium/net/spdy/fuzzing/hpack_fuzz_util.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_
-#define NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h"
-#include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
-
-namespace spdy {
-
-class HpackFuzzUtil {
- public:
- // A GeneratorContext holds ordered header names & values which are
- // initially seeded and then expanded with dynamically generated data.
- struct GeneratorContext {
- GeneratorContext();
- ~GeneratorContext();
- std::vector<SpdyString> names;
- std::vector<SpdyString> values;
- };
-
- // Initializes a GeneratorContext with a random seed and name/value fixtures.
- static void InitializeGeneratorContext(GeneratorContext* context);
-
- // Generates a header set from the generator context.
- static SpdyHeaderBlock NextGeneratedHeaderSet(GeneratorContext* context);
-
- // Samples a size from the exponential distribution with mean |mean|,
- // upper-bounded by |sanity_bound|.
- static size_t SampleExponential(size_t mean, size_t sanity_bound);
-
- // Holds an input SpdyString, and manages an offset into that SpdyString.
- struct Input {
- Input(); // Initializes |offset| to zero.
- ~Input();
-
- size_t remaining() { return input.size() - offset; }
- const char* ptr() { return input.data() + offset; }
-
- SpdyString input;
- size_t offset;
- };
-
- // Returns true if the next header block was set at |out|. Returns
- // false if no input header blocks remain.
- static bool NextHeaderBlock(Input* input, SpdyStringPiece* out);
-
- // Returns the serialized header block length prefix for a block of
- // |block_size| bytes.
- static SpdyString HeaderBlockPrefix(size_t block_size);
-
- // A FuzzerContext holds fuzzer input, as well as each of the decoder and
- // encoder stages which fuzzed header blocks are processed through.
- struct FuzzerContext {
- FuzzerContext();
- ~FuzzerContext();
- std::unique_ptr<HpackDecoderAdapter> first_stage;
- std::unique_ptr<HpackEncoder> second_stage;
- std::unique_ptr<HpackDecoderAdapter> third_stage;
- };
-
- static void InitializeFuzzerContext(FuzzerContext* context);
-
- // Runs |input_block| through |first_stage| and, iff that succeeds,
- // |second_stage| and |third_stage| as well. Returns whether all stages
- // processed the input without error.
- static bool RunHeaderBlockThroughFuzzerStages(FuzzerContext* context,
- SpdyStringPiece input_block);
-
- // Flips random bits within |buffer|. The total number of flips is
- // |flip_per_thousand| bits for every 1,024 bytes of |buffer_length|,
- // rounding up.
- static void FlipBits(uint8_t* buffer,
- size_t buffer_length,
- size_t flip_per_thousand);
-};
-
-} // namespace spdy
-
-#endif // NET_SPDY_FUZZING_HPACK_FUZZ_UTIL_H_
diff --git a/chromium/net/spdy/fuzzing/hpack_fuzz_util_test.cc b/chromium/net/spdy/fuzzing/hpack_fuzz_util_test.cc
deleted file mode 100644
index 8294fd4eb1f..00000000000
--- a/chromium/net/spdy/fuzzing/hpack_fuzz_util_test.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/spdy/fuzzing/hpack_fuzz_util.h"
-
-#include <map>
-
-#include "base/base_paths.h"
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/stl_util.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace spdy {
-namespace test {
-
-using std::map;
-
-TEST(HpackFuzzUtilTest, GeneratorContextInitialization) {
- HpackFuzzUtil::GeneratorContext context;
- HpackFuzzUtil::InitializeGeneratorContext(&context);
-
- // Context was seeded with initial name & value fixtures.
- EXPECT_LT(0u, context.names.size());
- EXPECT_LT(0u, context.values.size());
-}
-
-TEST(HpackFuzzUtil, GeneratorContextExpansion) {
- HpackFuzzUtil::GeneratorContext context;
-
- SpdyHeaderBlock headers = HpackFuzzUtil::NextGeneratedHeaderSet(&context);
-
- // Headers were generated, and the generator context was expanded.
- EXPECT_LT(0u, headers.size());
- EXPECT_LT(0u, context.names.size());
- EXPECT_LT(0u, context.values.size());
-}
-
-// TODO(jgraettinger): A better test would mock a random generator and
-// evaluate SampleExponential along fixed points of the [0,1] domain.
-TEST(HpackFuzzUtilTest, SampleExponentialRegression) {
- // TODO(jgraettinger): Upstream uses a seeded random generator here to pin
- // the behavior of SampleExponential. Chromium's random generation utilities
- // are strongly secure, but provide no way to seed the generator.
- for (size_t i = 0; i != 100; ++i) {
- EXPECT_GE(30u, HpackFuzzUtil::SampleExponential(10, 30));
- }
-}
-
-TEST(HpackFuzzUtilTest, ParsesSequenceOfHeaderBlocks) {
- char fixture[] =
- "\x00\x00\x00\x05"
- "aaaaa"
- "\x00\x00\x00\x04"
- "bbbb"
- "\x00\x00\x00\x03"
- "ccc"
- "\x00\x00\x00\x02"
- "dd"
- "\x00\x00\x00\x01"
- "e"
- "\x00\x00\x00\x00"
- ""
- "\x00\x00\x00\x03"
- "fin";
-
- HpackFuzzUtil::Input input;
- input.input.assign(fixture, base::size(fixture) - 1);
-
- SpdyStringPiece block;
-
- EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
- EXPECT_EQ("aaaaa", block);
- EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
- EXPECT_EQ("bbbb", block);
- EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
- EXPECT_EQ("ccc", block);
- EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
- EXPECT_EQ("dd", block);
- EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
- EXPECT_EQ("e", block);
- EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
- EXPECT_EQ("", block);
- EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
- EXPECT_EQ("fin", block);
- EXPECT_FALSE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
-}
-
-TEST(HpackFuzzUtilTest, SerializedHeaderBlockPrefixes) {
- EXPECT_EQ(SpdyString("\x00\x00\x00\x00", 4),
- HpackFuzzUtil::HeaderBlockPrefix(0));
- EXPECT_EQ(SpdyString("\x00\x00\x00\x05", 4),
- HpackFuzzUtil::HeaderBlockPrefix(5));
- EXPECT_EQ("\x4f\xb3\x0a\x91", HpackFuzzUtil::HeaderBlockPrefix(1337133713));
-}
-
-TEST(HpackFuzzUtilTest, PassValidInputThroughAllStages) {
- // Example lifted from HpackDecoderTest.SectionD4RequestHuffmanExamples.
- SpdyString input = SpdyHexDecode("828684418cf1e3c2e5f23a6ba0ab90f4ff");
-
- HpackFuzzUtil::FuzzerContext context;
- HpackFuzzUtil::InitializeFuzzerContext(&context);
-
- EXPECT_TRUE(
- HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(&context, input));
-
- SpdyHeaderBlock expect;
- expect[":method"] = "GET";
- expect[":scheme"] = "http";
- expect[":path"] = "/";
- expect[":authority"] = "www.example.com";
- EXPECT_EQ(expect, context.third_stage->decoded_block());
-}
-
-TEST(HpackFuzzUtilTest, ValidFuzzExamplesRegressionTest) {
- base::FilePath source_root;
- ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &source_root));
-
- // Load the example fixtures versioned with the source tree.
- HpackFuzzUtil::Input input;
- ASSERT_TRUE(base::ReadFileToString(
- source_root.Append(FILE_PATH_LITERAL("net"))
- .Append(FILE_PATH_LITERAL("data"))
- .Append(FILE_PATH_LITERAL("spdy_tests"))
- .Append(FILE_PATH_LITERAL("examples_07.hpack")),
- &input.input));
-
- HpackFuzzUtil::FuzzerContext context;
- HpackFuzzUtil::InitializeFuzzerContext(&context);
-
- SpdyStringPiece block;
- while (HpackFuzzUtil::NextHeaderBlock(&input, &block)) {
- // As these are valid examples, all fuzz stages should succeed.
- EXPECT_TRUE(
- HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(&context, block));
- }
-}
-
-TEST(HpackFuzzUtilTest, FlipBitsMutatesBuffer) {
- char buffer[] = "testbuffer1234567890";
- SpdyString unmodified(buffer, base::size(buffer) - 1);
-
- EXPECT_EQ(unmodified, buffer);
- HpackFuzzUtil::FlipBits(reinterpret_cast<uint8_t*>(buffer),
- base::size(buffer) - 1, 1);
- EXPECT_NE(unmodified, buffer);
-}
-
-} // namespace test
-} // namespace spdy
diff --git a/chromium/net/spdy/fuzzing/http2_frame_decoder_fuzzer.cc b/chromium/net/spdy/fuzzing/http2_frame_decoder_fuzzer.cc
deleted file mode 100644
index f89de197d6e..00000000000
--- a/chromium/net/spdy/fuzzing/http2_frame_decoder_fuzzer.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <list>
-#include <vector>
-
-#include "base/test/fuzzed_data_provider.h"
-#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h"
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- base::FuzzedDataProvider fuzzed_data_provider(data, size);
- http2::Http2FrameDecoder decoder;
-
- // Store all chunks in a function scope list, as the API requires the caller
- // to make sure the fragment chunks data is accessible during the whole
- // decoding process. |http2::DecodeBuffer| does not copy the data, it is just
- // a wrapper for the chunk provided in its constructor.
- std::list<std::vector<char>> all_chunks;
- while (fuzzed_data_provider.remaining_bytes() > 0) {
- size_t chunk_size = fuzzed_data_provider.ConsumeIntegralInRange(1, 32);
- all_chunks.emplace_back(
- fuzzed_data_provider.ConsumeBytes<char>(chunk_size));
- const auto& chunk = all_chunks.back();
-
- // http2::DecodeBuffer constructor does not accept nullptr buffer.
- if (chunk.data() == nullptr)
- continue;
-
- http2::DecodeBuffer frame_data(chunk.data(), chunk.size());
- decoder.DecodeFrame(&frame_data);
- }
- return 0;
-}
diff --git a/chromium/net/spdy/spdy_proxy_client_socket.cc b/chromium/net/spdy/spdy_proxy_client_socket.cc
index 724bbd81e90..f8d4713d0ab 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket.cc
+++ b/chromium/net/spdy/spdy_proxy_client_socket.cc
@@ -418,7 +418,7 @@ int SpdyProxyClientSocket::DoReadReplyComplete(int result) {
// Note that this triggers a spdy::ERROR_CODE_CANCEL.
spdy_stream_->DetachDelegate();
next_state_ = STATE_DISCONNECTED;
- return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
+ return ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT;
case 407: // Proxy Authentication Required
next_state_ = STATE_OPEN;
diff --git a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
index 0f31adca336..8e53e3084bc 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -498,7 +498,7 @@ TEST_P(SpdyProxyClientSocketTest, ConnectRedirects) {
Initialize(reads, writes);
- AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE);
+ AssertConnectFails(ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT);
const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
ASSERT_TRUE(response != NULL);
diff --git a/chromium/net/url_request/http_with_dns_over_https_unittest.cc b/chromium/net/url_request/http_with_dns_over_https_unittest.cc
index 70754b4f34c..59a42d3b156 100644
--- a/chromium/net/url_request/http_with_dns_over_https_unittest.cc
+++ b/chromium/net/url_request/http_with_dns_over_https_unittest.cc
@@ -162,11 +162,11 @@ class TestHttpDelegate : public HttpStreamRequest::Delegate {
void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
SSLCertRequestInfo* cert_info) override {}
- void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- std::unique_ptr<HttpStream> stream) override {
- }
+ void OnHttpsProxyTunnelResponseRedirect(
+ const HttpResponseInfo& response_info,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ std::unique_ptr<HttpStream> stream) override {}
void OnQuicBroken() override {}
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
index a4124ba74ef..ba2d363a225 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
@@ -140,9 +140,6 @@ ResultExpr BaselinePolicyAndroid::EvaluateSyscall(int sysno) const {
case __NR_socket:
#endif
- // Ptrace is allowed so the Breakpad Microdumper can fork in a renderer
- // and then ptrace the parent.
- case __NR_ptrace:
override_and_allow = true;
break;
}
@@ -152,6 +149,12 @@ ResultExpr BaselinePolicyAndroid::EvaluateSyscall(int sysno) const {
return Allow();
}
+ // Ptrace is allowed so the crash reporter can fork in a renderer
+ // and then ptrace the parent. https://crbug.com/933418
+ if (sysno == __NR_ptrace) {
+ return RestrictPtrace();
+ }
+
// https://crbug.com/644759
if (sysno == __NR_rt_tgsigqueueinfo) {
const Arg<pid_t> tgid(0);
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index 5adc1a7a4d4..7514f9a4a0a 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -33,6 +33,7 @@
#define SECCOMP_MESSAGE_IOCTL_CONTENT "ioctl() failure"
#define SECCOMP_MESSAGE_KILL_CONTENT "(tg)kill() failure"
#define SECCOMP_MESSAGE_FUTEX_CONTENT "futex() failure"
+#define SECCOMP_MESSAGE_PTRACE_CONTENT "ptrace() failure"
namespace {
@@ -305,6 +306,19 @@ intptr_t SIGSYSFutexFailure(const struct arch_seccomp_data& args,
_exit(1);
}
+intptr_t SIGSYSPtraceFailure(const struct arch_seccomp_data& args,
+ void* /* aux */) {
+ static const char kSeccompPtraceError[] =
+ __FILE__ ":**CRASHING**:" SECCOMP_MESSAGE_PTRACE_CONTENT "\n";
+ WriteToStdErr(kSeccompPtraceError, sizeof(kSeccompPtraceError) - 1);
+ SetSeccompCrashKey(args);
+ volatile int ptrace_op = args.args[0];
+ volatile char* addr = reinterpret_cast<volatile char*>(ptrace_op & 0xFFF);
+ *addr = '\0';
+ for (;;)
+ _exit(1);
+}
+
intptr_t SIGSYSSchedHandler(const struct arch_seccomp_data& args,
void* aux) {
switch (args.nr) {
@@ -363,6 +377,10 @@ bpf_dsl::ResultExpr CrashSIGSYSFutex() {
return bpf_dsl::Trap(SIGSYSFutexFailure, NULL);
}
+bpf_dsl::ResultExpr CrashSIGSYSPtrace() {
+ return bpf_dsl::Trap(SIGSYSPtraceFailure, NULL);
+}
+
bpf_dsl::ResultExpr RewriteSchedSIGSYS() {
return bpf_dsl::Trap(SIGSYSSchedHandler, NULL);
}
@@ -401,4 +419,8 @@ const char* GetFutexErrorMessageContentForTests() {
return SECCOMP_MESSAGE_FUTEX_CONTENT;
}
+const char* GetPtraceErrorMessageContentForTests() {
+ return SECCOMP_MESSAGE_PTRACE_CONTENT;
+}
+
} // namespace sandbox.
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
index b32fd6fedd4..baac3b61447 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
@@ -25,8 +25,8 @@ struct arch_seccomp_data;
SANDBOX_EXPORT intptr_t
CrashSIGSYS_Handler(const struct arch_seccomp_data& args, void* aux);
-// The following three handlers are suitable to report failures with the
-// clone(), prctl() and ioctl() system calls respectively.
+// The following seven handlers are suitable to report failures for specific
+// system calls with additional information.
// The crashing address will be (clone_flags & 0xFFFFFF), where clone_flags is
// the clone(2) argument, extracted from |args|.
@@ -48,6 +48,10 @@ SANDBOX_EXPORT intptr_t
// argument.
SANDBOX_EXPORT intptr_t
SIGSYSFutexFailure(const struct arch_seccomp_data& args, void* aux);
+// The crashing address will be (op & 0xFFF), where op is the second
+// argument.
+SANDBOX_EXPORT intptr_t
+SIGSYSPtraceFailure(const struct arch_seccomp_data& args, void* aux);
// If the syscall is not being called on the current tid, crashes in the same
// way as CrashSIGSYS_Handler. Otherwise, returns the result of calling the
// syscall with the pid argument set to 0 (which for these calls means the
@@ -66,6 +70,7 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSPrctl();
SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSIoctl();
SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSKill();
SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSFutex();
+SANDBOX_EXPORT bpf_dsl::ResultExpr CrashSIGSYSPtrace();
SANDBOX_EXPORT bpf_dsl::ResultExpr RewriteSchedSIGSYS();
// Allocates a crash key so that Seccomp information can be recorded.
@@ -79,6 +84,7 @@ SANDBOX_EXPORT const char* GetPrctlErrorMessageContentForTests();
SANDBOX_EXPORT const char* GetIoctlErrorMessageContentForTests();
SANDBOX_EXPORT const char* GetKillErrorMessageContentForTests();
SANDBOX_EXPORT const char* GetFutexErrorMessageContentForTests();
+SANDBOX_EXPORT const char* GetPtraceErrorMessageContentForTests();
} // namespace sandbox.
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 2577f02f2e9..55394a791a5 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -6,7 +6,6 @@
#include <errno.h>
#include <fcntl.h>
-#include <fcntl.h>
#include <linux/net.h>
#include <sched.h>
#include <signal.h>
@@ -31,10 +30,17 @@
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/system_headers/linux_time.h"
-// PNaCl toolchain does not provide sys/ioctl.h header.
+// PNaCl toolchain does not provide sys/ioctl.h and sys/ptrace.h headers.
#if !defined(OS_NACL_NONSFI)
#include <sys/ioctl.h>
-#endif
+#include <sys/ptrace.h>
+#if !defined(PTRACE_GET_THREAD_AREA) && defined(OS_LINUX) && \
+ !defined(OS_CHROMEOS)
+// Also include asm/ptrace-abi.h since ptrace.h in older libc (for instance
+// the one in Ubuntu 16.04 LTS) is missing PTRACE_GET_THREAD_AREA.
+#include <asm/ptrace-abi.h>
+#endif // !PTRACE_GET_THREAD_AREA && OS_LINUX && !OS_CHROMEOS
+#endif // !OS_NACL_NONSFI
#if defined(OS_ANDROID)
@@ -383,4 +389,25 @@ ResultExpr RestrictPrlimit(pid_t target_pid) {
return If(AnyOf(pid == 0, pid == target_pid), Allow()).Else(Error(EPERM));
}
+#if !defined(OS_NACL_NONSFI)
+ResultExpr RestrictPtrace() {
+ const Arg<int> request(0);
+ return Switch(request).CASES((
+#if !defined(__aarch64__)
+ PTRACE_GETREGS,
+ PTRACE_GETFPREGS,
+ PTRACE_GET_THREAD_AREA,
+#endif
+#if defined(__arm__)
+ PTRACE_GETVFPREGS,
+#endif
+ PTRACE_GETREGSET,
+ PTRACE_PEEKDATA,
+ PTRACE_ATTACH,
+ PTRACE_DETACH),
+ Allow())
+ .Default(CrashSIGSYSPtrace());
+}
+#endif // defined(OS_NACL_NONSFI)
+
} // namespace sandbox.
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
index 71c56093d92..cb563dfc550 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
@@ -103,6 +103,10 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictGetRandom();
// gracefully; see crbug.com/160157.
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPrlimit(pid_t target_pid);
+// Restrict ptrace() to just read operations that are needed for crash
+// reporting. See https://crbug.com/933418 for details.
+SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPtrace();
+
} // namespace sandbox.
#endif // SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_PARAMETERS_RESTRICTIONS_H_
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
index 327da2bea41..d109c6186c9 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
@@ -5,14 +5,20 @@
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include <errno.h>
+#include <fcntl.h>
+#include <linux/elf.h>
#include <sched.h>
+#include <sys/prctl.h>
+#include <sys/ptrace.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/types.h>
+#include <sys/user.h>
#include <time.h>
#include <unistd.h>
#include "base/bind.h"
+#include "base/posix/eintr_wrapper.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
@@ -242,6 +248,231 @@ BPF_DEATH_TEST_C(ParameterRestrictions,
getrusage(RUSAGE_CHILDREN, &usage);
}
+// ptace() Tests ///////////////////////////////////////////////////////////////
+
+// Tests for ptrace involve a slightly complex setup in order to properly test
+// ptrace and the variety of ways it is access-checked. The BPF_TEST macro,
+// the body of which already runs in its own process, spawns another process
+// called the "tracee". The "tracee" then spawns another process called the
+// "tracer". The child then traces the parent and performs the test operations.
+// The tracee must be careful to un-stop the tracer if the tracee expects to
+// die.
+
+class RestrictPtracePolicy : public bpf_dsl::Policy {
+ public:
+ RestrictPtracePolicy() = default;
+ ~RestrictPtracePolicy() override = default;
+
+ ResultExpr EvaluateSyscall(int sysno) const override {
+ switch (sysno) {
+ case __NR_ptrace:
+ return RestrictPtrace();
+ default:
+ return Allow();
+ }
+ }
+};
+
+constexpr char kExitPtraceChildClean = '!';
+
+class PtraceTestHarness {
+ public:
+ using PtraceChildTracerFunc = void (*)(pid_t tracee);
+
+ PtraceTestHarness(PtraceChildTracerFunc tracer_func, bool expect_death)
+ : tracer_func_(tracer_func), expect_death_(expect_death) {}
+ ~PtraceTestHarness() = default;
+
+ void Run() {
+ // Fork the tracee process that will be traced by its child.
+ pid_t pid = fork();
+ BPF_ASSERT_GE(pid, 0);
+
+ if (pid == 0) {
+ RunTracee();
+ } else {
+ // The tracee should always exit cleanly.
+ int status = 0;
+ int rv = waitpid(pid, &status, 0);
+ BPF_ASSERT_EQ(pid, rv);
+ BPF_ASSERT_EQ(0, WEXITSTATUS(status));
+ }
+ }
+
+ private:
+ void RunTracee() {
+ // Create a communications pipe between tracer and tracee.
+ int rv = pipe2(pipes_, O_NONBLOCK);
+ BPF_ASSERT_EQ(0, rv);
+
+ // Pipes for redirecting output.
+ int output_pipes[2];
+ BPF_ASSERT_EQ(0, pipe(output_pipes));
+
+ // Create the tracer process.
+ pid_t pid = fork();
+ BPF_ASSERT_GE(pid, 0);
+
+ if (pid == 0) {
+ // Close the pipe read ends and redirect output.
+ close(pipes_[0]);
+ close(output_pipes[0]);
+
+ close(STDOUT_FILENO);
+ dup2(output_pipes[1], STDOUT_FILENO);
+
+ close(STDERR_FILENO);
+ dup2(output_pipes[1], STDERR_FILENO);
+
+ RunTracer();
+
+ close(output_pipes[1]);
+ } else {
+ close(pipes_[1]);
+ close(output_pipes[1]);
+
+ // Ensure the tracer can trace the tracee. This may fail on systems
+ // without YAMA, so the result is not checked.
+ prctl(PR_SET_PTRACER, pid);
+
+ char c = 0;
+ while (c != kExitPtraceChildClean) {
+ // Read from the control channel in a non-blocking fashion.
+ // If no data are present, loop.
+ ignore_result(read(pipes_[0], &c, 1));
+
+ // Poll the exit status of the child.
+ int status = 0;
+ rv = waitpid(pid, &status, WNOHANG);
+ if (rv != 0) {
+ BPF_ASSERT_EQ(pid, rv);
+ CheckTracerStatus(status, output_pipes[0]);
+ _exit(0);
+ }
+ }
+
+ _exit(0);
+ }
+ }
+
+ void RunTracer() {
+ pid_t ppid = getppid();
+ BPF_ASSERT_NE(0, ppid);
+
+ // Attach to the tracee and then call out to the test function.
+ BPF_ASSERT_EQ(0, ptrace(PTRACE_ATTACH, ppid, nullptr, nullptr));
+
+ tracer_func_(ppid);
+
+ BPF_ASSERT_EQ(1, HANDLE_EINTR(write(pipes_[1], &kExitPtraceChildClean, 1)));
+ close(pipes_[1]);
+
+ _exit(0);
+ }
+
+ void CheckTracerStatus(int status, int output_pipe) {
+ // The child has exited. Test that it did so in the way we were
+ // expecting.
+ if (expect_death_) {
+ // This duplicates a bit of what //sandbox/linux/tests/unit_tests.cc does
+ // but that code is not shareable here.
+ std::string output;
+ const size_t kBufferSize = 1024;
+ size_t total_bytes_read = 0;
+ ssize_t read_this_pass = 0;
+ do {
+ output.resize(output.size() + kBufferSize);
+ read_this_pass = HANDLE_EINTR(
+ read(output_pipe, &output[total_bytes_read], kBufferSize));
+ if (read_this_pass >= 0) {
+ total_bytes_read += read_this_pass;
+ output.resize(total_bytes_read);
+ }
+ } while (read_this_pass > 0);
+
+#if !defined(SANDBOX_USES_BASE_TEST_SUITE)
+ const bool subprocess_got_sigsegv =
+ WIFSIGNALED(status) && (SIGSEGV == WTERMSIG(status));
+#else
+ // This hack is required when a signal handler is installed
+ // for SEGV that will _exit(1).
+ const bool subprocess_got_sigsegv =
+ WIFEXITED(status) && (1 == WEXITSTATUS(status));
+#endif
+ BPF_ASSERT(subprocess_got_sigsegv);
+ BPF_ASSERT_NE(output.find(GetPtraceErrorMessageContentForTests()),
+ std::string::npos);
+ } else {
+ BPF_ASSERT(WIFEXITED(status));
+ BPF_ASSERT_EQ(0, WEXITSTATUS(status));
+ }
+ }
+
+ PtraceChildTracerFunc tracer_func_;
+ bool expect_death_;
+ int pipes_[2];
+
+ DISALLOW_COPY_AND_ASSIGN(PtraceTestHarness);
+};
+
+BPF_TEST_C(ParameterRestrictions,
+ ptrace_getregs_allowed,
+ RestrictPtracePolicy) {
+ auto tracer = [](pid_t pid) {
+#if defined(__arm__)
+ user_regs regs;
+#else
+ user_regs_struct regs;
+#endif
+ iovec iov;
+ iov.iov_base = &regs;
+ iov.iov_len = sizeof(regs);
+ BPF_ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid,
+ reinterpret_cast<void*>(NT_PRSTATUS), &iov));
+
+ BPF_ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, nullptr, nullptr));
+ };
+ PtraceTestHarness(tracer, false).Run();
+}
+
+BPF_TEST_C(ParameterRestrictions,
+ ptrace_syscall_blocked,
+ RestrictPtracePolicy) {
+ auto tracer = [](pid_t pid) {
+ // The tracer is about to die. Make sure the tracee is not stopped so it
+ // can reap it and inspect its death signal.
+ kill(pid, SIGCONT);
+
+ BPF_ASSERT_NE(0, ptrace(PTRACE_SYSCALL, 0, nullptr, nullptr));
+ };
+ PtraceTestHarness(tracer, true).Run();
+}
+
+BPF_TEST_C(ParameterRestrictions,
+ ptrace_setregs_blocked,
+ RestrictPtracePolicy) {
+ auto tracer = [](pid_t pid) {
+#if defined(__arm__)
+ user_regs regs;
+#else
+ user_regs_struct regs;
+#endif
+ iovec iov;
+ iov.iov_base = &regs;
+ iov.iov_len = sizeof(regs);
+ BPF_ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid,
+ reinterpret_cast<void*>(NT_PRSTATUS), &iov));
+
+ // The tracer is about to die. Make sure the tracee is not stopped so it
+ // can reap it and inspect its death signal.
+ kill(pid, SIGCONT);
+
+ BPF_ASSERT_NE(0, ptrace(PTRACE_SETREGSET, pid,
+ reinterpret_cast<void*>(NT_PRSTATUS), &iov));
+ };
+ PtraceTestHarness(tracer, true).Run();
+}
+
} // namespace
} // namespace sandbox
diff --git a/chromium/sandbox/win/fuzzer/fuzzer_types.h b/chromium/sandbox/win/fuzzer/fuzzer_types.h
deleted file mode 100644
index 8ff06d0d15c..00000000000
--- a/chromium/sandbox/win/fuzzer/fuzzer_types.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_FUZZER_TYPES_H_
-#define SANDBOX_FUZZER_TYPES_H_
-
-#include <stdint.h>
-
-// This file defines Windows types for the sandbox_ipc_fuzzer target when
-// compiled on Linux.
-//
-// It also disables Windows exception handling to ensure any crashes are
-// captured by the fuzzing harness.
-
-// Disable exceptions.
-#if defined(__try)
-#undef __try
-#endif
-#define __try if(true)
-#if defined(__except)
-#undef __except
-#endif
-#define __except(...) if(false)
-
-// Windows types used in sandbox.
-typedef void* HANDLE;
-typedef uint32_t DWORD;
-typedef int32_t LONG;
-typedef uint32_t ULONG;
-typedef uint32_t* ULONG_PTR;
-typedef LONG NTSTATUS;
-typedef void PROCESS_INFORMATION;
-
-// __stdcall is used in one place. TODO(wfh): replace with WINAPI.
-#define __stdcall
-
-#endif // SANDBOX_FUZZER_TYPES_H_
diff --git a/chromium/sandbox/win/fuzzer/sandbox_ipc_fuzzer.cc b/chromium/sandbox/win/fuzzer/sandbox_ipc_fuzzer.cc
deleted file mode 100644
index 1c2ea8c5430..00000000000
--- a/chromium/sandbox/win/fuzzer/sandbox_ipc_fuzzer.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "sandbox/win/src/crosscall_server.h"
-#include "sandbox/win/src/ipc_args.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- using namespace sandbox;
-
- uint32_t output_size = 0;
- std::unique_ptr<CrossCallParamsEx> params(CrossCallParamsEx::CreateFromBuffer(
- const_cast<uint8_t*>(data), size, &output_size));
-
- if (!params.get())
- return 0;
-
- uint32_t tag = params->GetTag();
- IPCParams ipc_params = {0};
- ipc_params.ipc_tag = tag;
- void* args[kMaxIpcParams];
- GetArgs(params.get(), &ipc_params, args);
- ReleaseArgs(&ipc_params, args);
- return 0;
-}
diff --git a/chromium/services/media_session/audio_focus_manager.cc b/chromium/services/media_session/audio_focus_manager.cc
index e6b952fd4ab..a1eeb647078 100644
--- a/chromium/services/media_session/audio_focus_manager.cc
+++ b/chromium/services/media_session/audio_focus_manager.cc
@@ -98,7 +98,17 @@ class AudioFocusManager::StackRow : public mojom::AudioFocusRequestClient {
}
void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr info) override {
+ bool suspended_change =
+ (info->state == mojom::MediaSessionInfo::SessionState::kSuspended ||
+ IsSuspended()) &&
+ info->state != session_info_->state;
+
SetSessionInfo(std::move(info));
+
+ // If we have transitioned to/from a suspended state then we should
+ // re-enforce audio focus.
+ if (suspended_change)
+ owner_->EnforceAudioFocus();
}
void GetRequestId(GetRequestIdCallback callback) override {
@@ -118,6 +128,11 @@ class AudioFocusManager::StackRow : public mojom::AudioFocusRequestClient {
mojom::MediaSessionInfo::SessionState::kActive;
}
+ bool IsSuspended() const {
+ return session_info_->state ==
+ mojom::MediaSessionInfo::SessionState::kSuspended;
+ }
+
RequestId id() const { return id_; }
const std::string& source_name() const { return source_name_; }
@@ -301,7 +316,7 @@ void AudioFocusManager::AbandonAudioFocusInternal(RequestId id) {
return;
}
- EnforceAudioFocusAbandon();
+ EnforceAudioFocus();
MaybeUpdateActiveSession();
// Notify observers that we lost audio focus.
@@ -400,27 +415,6 @@ void AudioFocusManager::RequestAudioFocusInternal(
std::move(callback).Run();
}
-void AudioFocusManager::EnforceAudioFocusAbandon() {
- // Allow the top-most MediaSession having force duck to unduck even if
- // it is not active.
- if (enforcement_mode_ != mojom::EnforcementMode::kNone) {
- for (auto iter = audio_focus_stack_.rbegin();
- iter != audio_focus_stack_.rend(); ++iter) {
- if (!(*iter)->info()->force_duck)
- continue;
-
- // TODO(beccahughes): Replace with std::rotate.
- auto duck_row = std::move(*iter);
- duck_row->session()->StopDucking();
- audio_focus_stack_.erase(std::next(iter).base());
- audio_focus_stack_.push_back(std::move(duck_row));
- return;
- }
- }
-
- EnforceAudioFocus();
-}
-
void AudioFocusManager::EnforceAudioFocus() {
DCHECK_NE(mojom::EnforcementMode::kDefault, enforcement_mode_);
if (audio_focus_stack_.empty())
@@ -431,16 +425,20 @@ void AudioFocusManager::EnforceAudioFocus() {
for (auto& session : base::Reversed(audio_focus_stack_)) {
EnforceSingleSession(session.get(), state);
- // Update the flags based on the audio focus type of this session.
+ // Update the flags based on the audio focus type of this session. If the
+ // session is suspended then any transient audio focus type should not have
+ // an effect.
switch (session->audio_focus_type()) {
case mojom::AudioFocusType::kGain:
state.should_stop = true;
break;
case mojom::AudioFocusType::kGainTransient:
- state.should_suspend = true;
+ if (!session->IsSuspended())
+ state.should_suspend = true;
break;
case mojom::AudioFocusType::kGainTransientMayDuck:
- state.should_duck = true;
+ if (!session->IsSuspended())
+ state.should_duck = true;
break;
}
}
diff --git a/chromium/services/media_session/audio_focus_manager.h b/chromium/services/media_session/audio_focus_manager.h
index 50d72f6ad7f..fb71e664f97 100644
--- a/chromium/services/media_session/audio_focus_manager.h
+++ b/chromium/services/media_session/audio_focus_manager.h
@@ -107,7 +107,6 @@ class AudioFocusManager : public mojom::AudioFocusManager,
base::OnceCallback<void()>);
void AbandonAudioFocusInternal(RequestId);
- void EnforceAudioFocusAbandon();
void EnforceAudioFocus();
void MaybeUpdateActiveSession();
diff --git a/chromium/services/media_session/audio_focus_manager_unittest.cc b/chromium/services/media_session/audio_focus_manager_unittest.cc
index c8b9b49eb8d..de29923817e 100644
--- a/chromium/services/media_session/audio_focus_manager_unittest.cc
+++ b/chromium/services/media_session/audio_focus_manager_unittest.cc
@@ -122,9 +122,8 @@ class AudioFocusManagerTest
mojom::MediaSessionInfo::SessionState state = session->GetState();
if (!IsEnforcementEnabled()) {
- // If audio focus enforcement is disabled then we should never see these
- // states in the tests.
- EXPECT_NE(mojom::MediaSessionInfo::SessionState::kSuspended, state);
+ // If audio focus enforcement is disabled then we should never see ducking
+ // in the tests.
EXPECT_NE(mojom::MediaSessionInfo::SessionState::kDucking, state);
}
@@ -676,8 +675,7 @@ TEST_P(AudioFocusManagerTest, GainDucksForceDuck) {
GetState(&media_session_1));
}
-TEST_P(AudioFocusManagerTest,
- AbandoningGainFocusRevokesTopMostForceDuckSession) {
+TEST_P(AudioFocusManagerTest, ForceDuckSessionShouldAlwaysBeDuckedFromGain) {
test::MockMediaSession media_session_1(true /* force_duck */);
test::MockMediaSession media_session_2;
test::MockMediaSession media_session_3;
@@ -698,8 +696,34 @@ TEST_P(AudioFocusManagerTest,
GetState(&media_session_1));
media_session_3.AbandonAudioFocusFromClient();
- EXPECT_EQ(IsEnforcementEnabled() ? request_id_1 : request_id_2,
- GetAudioFocusedSession());
+ EXPECT_EQ(request_id_2, GetAudioFocusedSession());
+ EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
+ GetState(&media_session_1));
+
+ media_session_2.AbandonAudioFocusFromClient();
+ EXPECT_EQ(request_id_1, GetAudioFocusedSession());
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_1));
+}
+
+TEST_P(AudioFocusManagerTest,
+ ForceDuckSessionShouldAlwaysBeDuckedFromTransient) {
+ test::MockMediaSession media_session_1(true /* force_duck */);
+ test::MockMediaSession media_session_2;
+
+ AudioFocusManager::RequestId request_id_1 =
+ RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
+ RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
+
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_2));
+ EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
+ GetState(&media_session_1));
+
+ media_session_2.AbandonAudioFocusFromClient();
+ EXPECT_EQ(request_id_1, GetAudioFocusedSession());
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_1));
}
TEST_P(AudioFocusManagerTest, AudioFocusObserver_RequestNoop) {
@@ -1061,7 +1085,7 @@ TEST_P(AudioFocusManagerTest, ObserverActiveSessionChanged) {
}
}
-TEST_P(AudioFocusManagerTest, AudioFocusGrouping_AllowDucking) {
+TEST_P(AudioFocusManagerTest, AudioFocusGrouping_LayeredFocus) {
test::MockMediaSession media_session_1;
test::MockMediaSession media_session_2;
test::MockMediaSession media_session_3;
@@ -1078,11 +1102,20 @@ TEST_P(AudioFocusManagerTest, AudioFocusGrouping_AllowDucking) {
EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
GetState(&media_session_1));
- RequestGroupedAudioFocus(&media_session_3, mojom::AudioFocusType::kGain,
- group_id);
+ // When we request audio focus for media_session_3 the group will take audio
+ // focus and we suspend the ducking session.
+ RequestGroupedAudioFocus(&media_session_3,
+ mojom::AudioFocusType::kGainTransient, group_id);
EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
GetState(&media_session_3));
- EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
+
+ EXPECT_EQ(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
+ GetState(&media_session_2));
+ EXPECT_EQ(GetStateFromParam(
+ IsGroupingEnabled()
+ ? mojom::MediaSessionInfo::SessionState::kActive
+ : mojom::MediaSessionInfo::SessionState::kSuspended),
GetState(&media_session_1));
}
@@ -1234,4 +1267,218 @@ TEST_P(AudioFocusManagerTest,
GetState(&media_session_1));
}
+TEST_P(AudioFocusManagerTest, GainFocusTypeHasEffectEvenIfSuspended) {
+ test::MockMediaSession media_session_1;
+ test::MockMediaSession media_session_2;
+ test::MockMediaSession media_session_3;
+
+ AudioFocusManager::RequestId request_id_1 =
+ RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
+ EXPECT_EQ(request_id_1, GetAudioFocusedSession());
+
+ RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
+ EXPECT_EQ(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
+ GetState(&media_session_1));
+
+ // When the second session becomes suspended and that event originated from
+ // the session itself then we should keep the other session suspended.
+ media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ // When the second session is resumed then we should still keep the other
+ // session suspended.
+ media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ // If a new session takes focus then this should suspend all sessions.
+ RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_2);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ // If the second session regains focus then it should suspend all sessions.
+ RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGain);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_3);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+}
+
+TEST_P(AudioFocusManagerTest, TransientFocusTypeHasNoEffectIfSuspended) {
+ test::MockMediaSession media_session_1;
+ test::MockMediaSession media_session_2;
+ test::MockMediaSession media_session_3;
+
+ AudioFocusManager::RequestId request_id_1 =
+ RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
+ EXPECT_EQ(request_id_1, GetAudioFocusedSession());
+
+ RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
+ EXPECT_EQ(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended),
+ GetState(&media_session_1));
+
+ // When the transient session becomes suspended and that event originates from
+ // the session itself then we should stop pausing the other session.
+ media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
+ }
+
+ // When the transient session is resumed then we should pause the other
+ // session again.
+ media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ // If we have a new session take focus then this should suspend all the other
+ // sessions and the transient session should have no effect.
+ RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_2);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ // If the second session regains focus then it should start pausing again.
+ RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_3);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+}
+
+TEST_P(AudioFocusManagerTest, TransientDuckFocusTypeHasNoEffectIfSuspended) {
+ test::MockMediaSession media_session_1;
+ test::MockMediaSession media_session_2;
+ test::MockMediaSession media_session_3;
+
+ AudioFocusManager::RequestId request_id_1 =
+ RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain);
+ EXPECT_EQ(request_id_1, GetAudioFocusedSession());
+
+ RequestAudioFocus(&media_session_2,
+ mojom::AudioFocusType::kGainTransientMayDuck);
+ EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking),
+ GetState(&media_session_1));
+
+ // When the ducking session becomes suspended and that event originates from
+ // the session itself then we should stop ducking.
+ media_session_2.Suspend(mojom::MediaSession::SuspendType::kUI);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kSuspended,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
+ }
+
+ // When the ducking session is resumed then we should resume ducking.
+ media_session_2.Resume(mojom::MediaSession::SuspendType::kUI);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
+ }
+
+ // If we have a new session take focus then this should suspend all the other
+ // sessions and we should not have any ducking from the ducking session (since
+ // it is suspended).
+ RequestAudioFocus(&media_session_3, mojom::AudioFocusType::kGainTransient);
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_2);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kSuspended));
+ }
+
+ // If the ducking session regains focus then it should start ducking again.
+ RequestAudioFocus(&media_session_2,
+ mojom::AudioFocusType::kGainTransientMayDuck);
+ EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive,
+ GetState(&media_session_2));
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_1);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
+ }
+
+ {
+ test::MockMediaSessionMojoObserver observer(media_session_3);
+ observer.WaitForState(
+ GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking));
+ }
+}
+
} // namespace media_session
diff --git a/chromium/services/network/network_change_manager.cc b/chromium/services/network/network_change_manager.cc
index a1ed97863de..089bce06c6a 100644
--- a/chromium/services/network/network_change_manager.cc
+++ b/chromium/services/network/network_change_manager.cc
@@ -9,7 +9,7 @@
#include "base/logging.h"
#include "net/base/network_change_notifier.h"
-#include "net/base/network_change_notifier_chromeos.h"
+#include "net/base/network_change_notifier_posix.h"
namespace network {
@@ -44,7 +44,7 @@ void NetworkChangeManager::RequestNotifications(
clients_.push_back(std::move(client_ptr));
}
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
void NetworkChangeManager::OnNetworkChanged(
bool dns_changed,
bool ip_address_changed,
@@ -53,8 +53,8 @@ void NetworkChangeManager::OnNetworkChanged(
bool connection_subtype_changed,
mojom::ConnectionSubtype new_connection_subtype) {
DCHECK(network_change_notifier_);
- net::NetworkChangeNotifierChromeos* notifier =
- static_cast<net::NetworkChangeNotifierChromeos*>(
+ net::NetworkChangeNotifierPosix* notifier =
+ static_cast<net::NetworkChangeNotifierPosix*>(
network_change_notifier_.get());
if (dns_changed)
notifier->OnDNSChanged();
diff --git a/chromium/services/network/network_change_manager.h b/chromium/services/network/network_change_manager.h
index 6dd4dc9feee..bf975f21e58 100644
--- a/chromium/services/network/network_change_manager.h
+++ b/chromium/services/network/network_change_manager.h
@@ -41,7 +41,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkChangeManager
void RequestNotifications(
mojom::NetworkChangeManagerClientPtr client_ptr) override;
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
void OnNetworkChanged(
bool dns_changed,
bool ip_address_changed,
diff --git a/chromium/services/network/network_service.cc b/chromium/services/network/network_service.cc
index fbe344a3dd8..ffa129c237e 100644
--- a/chromium/services/network/network_service.cc
+++ b/chromium/services/network/network_service.cc
@@ -22,6 +22,7 @@
#include "mojo/public/cpp/bindings/type_converter.h"
#include "net/base/logging_network_change_observer.h"
#include "net/base/network_change_notifier.h"
+#include "net/base/network_change_notifier_posix.h"
#include "net/base/port_util.h"
#include "net/cert/cert_database.h"
#include "net/cert/ct_log_response_parser.h"
@@ -83,15 +84,17 @@ net::NetLog* GetNetLog() {
constexpr auto kUpdateLoadStatesInterval =
base::TimeDelta::FromMilliseconds(250);
-std::unique_ptr<net::NetworkChangeNotifier>
-CreateNetworkChangeNotifierIfNeeded() {
+std::unique_ptr<net::NetworkChangeNotifier> CreateNetworkChangeNotifierIfNeeded(
+ net::NetworkChangeNotifier::ConnectionType initial_connection_type,
+ net::NetworkChangeNotifier::ConnectionSubtype initial_connection_subtype) {
// There is a global singleton net::NetworkChangeNotifier if NetworkService
// is running inside of the browser process.
if (!net::NetworkChangeNotifier::HasNetworkChangeNotifier()) {
-#if defined(OS_ANDROID)
- // On Android, NetworkChangeNotifier objects are always set up in process
- // before NetworkService is run.
- return nullptr;
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+ // On Android and ChromeOS, network change events are synced from the
+ // browser process.
+ return std::make_unique<net::NetworkChangeNotifierPosix>(
+ initial_connection_type, initial_connection_subtype);
#elif defined(OS_IOS) || defined(OS_FUCHSIA)
// iOS doesn't embed //content. Fuchsia doesn't have an implementation yet.
// TODO(xunjieli): Figure out what to do for these 2 platforms.
@@ -208,7 +211,8 @@ NetworkService::NetworkService(
std::unique_ptr<service_manager::BinderRegistry> registry,
mojom::NetworkServiceRequest request,
net::NetLog* net_log,
- service_manager::mojom::ServiceRequest service_request)
+ service_manager::mojom::ServiceRequest service_request,
+ bool delay_initialization_until_set_client)
: registry_(std::move(registry)), binding_(this) {
DCHECK(!g_network_service);
g_network_service = this;
@@ -229,6 +233,22 @@ NetworkService::NetworkService(
Bind(std::move(request));
}
+ if (net_log) {
+ net_log_ = net_log;
+ } else {
+ net_log_ = GetNetLog();
+ }
+
+ if (!delay_initialization_until_set_client)
+ Initialize(mojom::NetworkServiceParams::New());
+}
+
+void NetworkService::Initialize(mojom::NetworkServiceParamsPtr params) {
+ if (initialized_)
+ return;
+
+ initialized_ = true;
+
#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
// Make sure OpenSSL is initialized before using it to histogram data.
crypto::EnsureOpenSSLInit();
@@ -257,13 +277,11 @@ NetworkService::NetworkService(
command_line->HasSwitch(switches::kIgnoreCertificateErrorsSPKIList));
network_change_manager_ = std::make_unique<NetworkChangeManager>(
- CreateNetworkChangeNotifierIfNeeded());
-
- if (net_log) {
- net_log_ = net_log;
- } else {
- net_log_ = GetNetLog();
- }
+ CreateNetworkChangeNotifierIfNeeded(
+ net::NetworkChangeNotifier::ConnectionType(
+ params->initial_connection_type),
+ net::NetworkChangeNotifier::ConnectionSubtype(
+ params->initial_connection_subtype)));
trace_net_log_observer_.WatchForTraceStart(net_log_);
@@ -380,8 +398,10 @@ void NetworkService::CreateNetLogEntriesForActiveObjects(
return net::CreateNetLogEntriesForActiveObjects(contexts, observer);
}
-void NetworkService::SetClient(mojom::NetworkServiceClientPtr client) {
+void NetworkService::SetClient(mojom::NetworkServiceClientPtr client,
+ mojom::NetworkServiceParamsPtr params) {
client_ = std::move(client);
+ Initialize(std::move(params));
}
void NetworkService::StartNetLog(base::File file,
diff --git a/chromium/services/network/network_service.h b/chromium/services/network/network_service.h
index 9e398323c2d..a04970001c2 100644
--- a/chromium/services/network/network_service.h
+++ b/chromium/services/network/network_service.h
@@ -76,7 +76,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
std::unique_ptr<service_manager::BinderRegistry> registry,
mojom::NetworkServiceRequest request = nullptr,
net::NetLog* net_log = nullptr,
- service_manager::mojom::ServiceRequest service_request = nullptr);
+ service_manager::mojom::ServiceRequest service_request = nullptr,
+ bool delay_initialization_until_set_client = false);
~NetworkService() override;
@@ -111,6 +112,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
// constructor.
void Bind(mojom::NetworkServiceRequest request);
+ // Allows the browser process to synchronously initialize the NetworkService.
+ // TODO(jam): remove this once the old path is gone.
+ void Initialize(mojom::NetworkServiceParamsPtr params);
+
// Creates a NetworkService instance on the current thread, optionally using
// the passed-in NetLog. Does not take ownership of |net_log|. Must be
// destroyed before |net_log|.
@@ -146,7 +151,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
net::NetLog::ThreadSafeObserver* observer);
// mojom::NetworkService implementation:
- void SetClient(mojom::NetworkServiceClientPtr client) override;
+ void SetClient(mojom::NetworkServiceClientPtr client,
+ mojom::NetworkServiceParamsPtr params) override;
void StartNetLog(base::File file,
mojom::NetLogCaptureMode capture_mode,
base::Value constants) override;
@@ -259,6 +265,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
service_manager::ServiceBinding service_binding_{this};
+ bool initialized_ = false;
+
net::NetLog* net_log_ = nullptr;
std::unique_ptr<net::FileNetLogObserver> file_net_log_observer_;
@@ -268,13 +276,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
KeepaliveStatisticsRecorder keepalive_statistics_recorder_;
+ std::unique_ptr<NetworkChangeManager> network_change_manager_;
+
// Observer that logs network changes to the NetLog. Must be below the NetLog
// and the NetworkChangeNotifier (Once this class creates it), so it's
- // destroyed before them.
+ // destroyed before them. Must be below the |network_change_manager_|, which
+ // it references.
std::unique_ptr<net::LoggingNetworkChangeObserver> network_change_observer_;
- std::unique_ptr<NetworkChangeManager> network_change_manager_;
-
std::unique_ptr<service_manager::BinderRegistry> registry_;
mojo::Binding<mojom::NetworkService> binding_;
diff --git a/chromium/services/network/network_service_unittest.cc b/chromium/services/network/network_service_unittest.cc
index b61dd2c1c03..9d19c198aa9 100644
--- a/chromium/services/network/network_service_unittest.cc
+++ b/chromium/services/network/network_service_unittest.cc
@@ -1294,12 +1294,6 @@ class NetworkChangeTest : public testing::Test {
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
-#if defined(OS_ANDROID)
- // On Android, NetworkChangeNotifier setup is more involved and needs to
- // to be split between UI thread and network thread. Use a mock
- // NetworkChangeNotifier in tests, so the test setup is simpler.
- net::test::MockNetworkChangeNotifier network_change_notifier_;
-#endif
std::unique_ptr<NetworkService> service_;
};
@@ -1342,12 +1336,6 @@ class NetworkServiceNetworkChangeTest : public testing::Test {
std::unique_ptr<NetworkService> service_;
mojom::NetworkServicePtr network_service_;
-#if defined(OS_ANDROID)
- // On Android, NetworkChangeNotifier setup is more involved and needs
- // to be split between UI thread and network thread. Use a mock
- // NetworkChangeNotifier in tests, so the test setup is simpler.
- net::test::MockNetworkChangeNotifier network_change_notifier_;
-#endif
DISALLOW_COPY_AND_ASSIGN(NetworkServiceNetworkChangeTest);
};
@@ -1525,7 +1513,8 @@ TEST_F(NetworkServiceNetworkDelegateTest, ClearSiteDataNetworkServiceCient) {
mojom::NetworkServiceClientPtr client_ptr;
auto client_impl = std::make_unique<ClearSiteDataNetworkServiceClient>(
mojo::MakeRequest(&client_ptr));
- service()->SetClient(std::move(client_ptr));
+ service()->SetClient(std::move(client_ptr),
+ network::mojom::NetworkServiceParams::New());
url = https_server()->GetURL("/bar");
url = AddQuery(url, "header", kClearCookiesHeader);
EXPECT_EQ(0, client_impl->on_clear_site_data_counter());
@@ -1543,7 +1532,8 @@ TEST_F(NetworkServiceNetworkDelegateTest, HandleClearSiteDataHeaders) {
mojom::NetworkServiceClientPtr client_ptr;
auto client_impl = std::make_unique<ClearSiteDataNetworkServiceClient>(
mojo::MakeRequest(&client_ptr));
- service()->SetClient(std::move(client_ptr));
+ service()->SetClient(std::move(client_ptr),
+ network::mojom::NetworkServiceParams::New());
// |passed_header_value| are only checked if |should_call_client| is true.
const struct TestCase {
diff --git a/chromium/services/network/proxy_config_service_mojo_unittest.cc b/chromium/services/network/proxy_config_service_mojo_unittest.cc
index ed7b315df2f..207694c930c 100644
--- a/chromium/services/network/proxy_config_service_mojo_unittest.cc
+++ b/chromium/services/network/proxy_config_service_mojo_unittest.cc
@@ -62,26 +62,48 @@ class TestProxyConfigServiceObserver
DISALLOW_COPY_AND_ASSIGN(TestProxyConfigServiceObserver);
};
+// Test fixture for notifying ProxyConfigServiceMojo of changes through the
+// client interface, and watching the subsequent values it emits to registered
+// net::ProxyConfigService::Observers.
+class ProxyConfigServiceMojoTest : public testing::Test {
+ public:
+ ProxyConfigServiceMojoTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::IO),
+ proxy_config_service_(mojo::MakeRequest(&config_client_),
+ base::Optional<net::ProxyConfigWithAnnotation>(),
+ nullptr),
+ observer_(&proxy_config_service_) {
+ proxy_config_service_.AddObserver(&observer_);
+ }
+
+ ~ProxyConfigServiceMojoTest() override {
+ proxy_config_service_.RemoveObserver(&observer_);
+ }
+
+ protected:
+ // After notifying a new configuration through |config_client_|, waits for the
+ // observers to have been notified.
+ void WaitForConfig() { scoped_task_environment_.RunUntilIdle(); }
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ mojom::ProxyConfigClientPtr config_client_;
+ ProxyConfigServiceMojo proxy_config_service_;
+ TestProxyConfigServiceObserver observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceMojoTest);
+};
+
// Most tests of this class are in network_context_unittests.
// Makes sure that a ProxyConfigService::Observer is correctly notified of
// changes when the ProxyConfig changes, and is not informed of them in the case
// of "changes" that result in the same ProxyConfig as before.
-TEST(ProxyConfigServiceMojoTest, ObserveProxyChanges) {
- base::test::ScopedTaskEnvironment scoped_task_environment(
- base::test::ScopedTaskEnvironment::MainThreadType::IO);
-
- mojom::ProxyConfigClientPtr config_client;
- ProxyConfigServiceMojo proxy_config_service(
- mojo::MakeRequest(&config_client),
- base::Optional<net::ProxyConfigWithAnnotation>(), nullptr);
- TestProxyConfigServiceObserver observer(&proxy_config_service);
- proxy_config_service.AddObserver(&observer);
-
+TEST_F(ProxyConfigServiceMojoTest, ObserveProxyChanges) {
net::ProxyConfigWithAnnotation proxy_config;
// The service should start without a config.
EXPECT_EQ(net::ProxyConfigService::CONFIG_PENDING,
- proxy_config_service.GetLatestProxyConfig(&proxy_config));
+ proxy_config_service_.GetLatestProxyConfig(&proxy_config));
net::ProxyConfig proxy_configs[3];
proxy_configs[0].proxy_rules().ParseFromString("http=foopy:80");
@@ -90,29 +112,62 @@ TEST(ProxyConfigServiceMojoTest, ObserveProxyChanges) {
for (const auto& proxy_config : proxy_configs) {
// Set the proxy configuration to something that does not match the old one.
- config_client->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation(
+ config_client_->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation(
proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
- scoped_task_environment.RunUntilIdle();
- EXPECT_EQ(1, observer.GetAndResetConfigChanges());
- EXPECT_TRUE(proxy_config.Equals(observer.observed_config().value()));
+ WaitForConfig();
+ EXPECT_EQ(1, observer_.GetAndResetConfigChanges());
+ EXPECT_TRUE(proxy_config.Equals(observer_.observed_config().value()));
net::ProxyConfigWithAnnotation retrieved_config;
EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID,
- proxy_config_service.GetLatestProxyConfig(&retrieved_config));
+ proxy_config_service_.GetLatestProxyConfig(&retrieved_config));
EXPECT_TRUE(proxy_config.Equals(retrieved_config.value()));
// Set the proxy configuration to the same value again. There should be not
// be another proxy config changed notification.
- config_client->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation(
+ config_client_->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation(
proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
- scoped_task_environment.RunUntilIdle();
- EXPECT_EQ(0, observer.GetAndResetConfigChanges());
- EXPECT_TRUE(proxy_config.Equals(observer.observed_config().value()));
+ WaitForConfig();
+ EXPECT_EQ(0, observer_.GetAndResetConfigChanges());
+ EXPECT_TRUE(proxy_config.Equals(observer_.observed_config().value()));
EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID,
- proxy_config_service.GetLatestProxyConfig(&retrieved_config));
+ proxy_config_service_.GetLatestProxyConfig(&retrieved_config));
EXPECT_TRUE(proxy_config.Equals(retrieved_config.value()));
}
+}
+
+// Creates a URL that has length |url::kMaxURLChars + 1|.
+GURL CreateLargeURL() {
+ std::string spec;
+ spec.reserve(url::kMaxURLChars + 1);
+ spec.assign("http://test.invalid/");
+ spec.append(url::kMaxURLChars + 1 - spec.size(), 'x');
+ return GURL(spec);
+}
- proxy_config_service.RemoveObserver(&observer);
+// Tests what happens when ProxyConfigServiceMojo is updated to using a
+// ProxyConfig with a large URL. GURL does not impose size limits, however some
+// internals like url.mojom.Url do.
+TEST_F(ProxyConfigServiceMojoTest, LargePacUrlNotTruncated) {
+ // Create a config using a large, valid, PAC URL.
+ net::ProxyConfig orig_config;
+ GURL large_url = CreateLargeURL();
+ EXPECT_TRUE(large_url.is_valid());
+ EXPECT_EQ(url::kMaxURLChars + 1, large_url.possibly_invalid_spec().size());
+ orig_config.set_pac_url(large_url);
+
+ // Notify the ProxyConfigServiceMojo of this URL through the client interface.
+ config_client_->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation(
+ orig_config, TRAFFIC_ANNOTATION_FOR_TESTS));
+
+ WaitForConfig();
+
+ // Read back the ProxyConfig that was observed (which has been serialized
+ // through a Mojo pipe).
+ const GURL& observed_url = observer_.observed_config().value().pac_url();
+
+ // The URL should be unchanged, and not changed by the Mojo serialization.
+ EXPECT_EQ(large_url, observed_url);
+ EXPECT_EQ(url::kMaxURLChars + 1, observed_url.possibly_invalid_spec().size());
}
} // namespace
diff --git a/chromium/services/network/public/cpp/network_ipc_param_traits.h b/chromium/services/network/public/cpp/network_ipc_param_traits.h
index 68e7ca593c2..a291d8405cf 100644
--- a/chromium/services/network/public/cpp/network_ipc_param_traits.h
+++ b/chromium/services/network/public/cpp/network_ipc_param_traits.h
@@ -132,6 +132,7 @@ IPC_STRUCT_TRAITS_BEGIN(network::URLLoaderCompletionStatus)
IPC_STRUCT_TRAITS_MEMBER(cors_error_status)
IPC_STRUCT_TRAITS_MEMBER(ssl_info)
IPC_STRUCT_TRAITS_MEMBER(should_report_corb_blocking)
+ IPC_STRUCT_TRAITS_MEMBER(proxy_server)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(network::ResourceResponseInfo)
diff --git a/chromium/services/network/public/cpp/proxy_config_mojom_traits.cc b/chromium/services/network/public/cpp/proxy_config_mojom_traits.cc
index f0bb5ea1f36..15b58d9196e 100644
--- a/chromium/services/network/public/cpp/proxy_config_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/proxy_config_mojom_traits.cc
@@ -109,12 +109,12 @@ bool StructTraits<network::mojom::ProxyRulesDataView,
bool StructTraits<network::mojom::ProxyConfigDataView, net::ProxyConfig>::Read(
network::mojom::ProxyConfigDataView data,
net::ProxyConfig* out_proxy_config) {
- GURL pac_url;
+ std::string pac_url;
if (!data.ReadPacUrl(&pac_url) ||
!data.ReadProxyRules(&out_proxy_config->proxy_rules())) {
return false;
}
- out_proxy_config->set_pac_url(pac_url);
+ out_proxy_config->set_pac_url(GURL(pac_url));
out_proxy_config->set_auto_detect(data.auto_detect());
out_proxy_config->set_pac_mandatory(data.pac_mandatory());
diff --git a/chromium/services/network/public/cpp/proxy_config_mojom_traits.h b/chromium/services/network/public/cpp/proxy_config_mojom_traits.h
index 70457300a0d..6d60b0d5d24 100644
--- a/chromium/services/network/public/cpp/proxy_config_mojom_traits.h
+++ b/chromium/services/network/public/cpp/proxy_config_mojom_traits.h
@@ -6,6 +6,8 @@
#define SERVICES_NETWORK_PUBLIC_CPP_PROXY_CONFIG_MOJOM_TRAITS_H_
#include "base/component_export.h"
+#include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
+#include "mojo/public/cpp/base/big_string_mojom_traits.h"
#include "net/proxy_resolution/proxy_bypass_rules.h"
#include "net/proxy_resolution/proxy_config.h"
#include "net/proxy_resolution/proxy_list.h"
@@ -93,7 +95,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
StructTraits<network::mojom::ProxyConfigDataView, net::ProxyConfig> {
public:
static bool auto_detect(const net::ProxyConfig& r) { return r.auto_detect(); }
- static const GURL& pac_url(const net::ProxyConfig& r) { return r.pac_url(); }
+ static const std::string& pac_url(const net::ProxyConfig& r) {
+ return r.pac_url().possibly_invalid_spec();
+ }
static bool pac_mandatory(const net::ProxyConfig& r) {
return r.pac_mandatory();
}
diff --git a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
index a71782b60b6..f19f1c55664 100644
--- a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -584,7 +584,8 @@ class SimpleURLLoaderTestBase {
network::mojom::NetworkServiceClientPtr network_service_client_ptr;
network_service_client_ = std::make_unique<TestNetworkServiceClient>(
mojo::MakeRequest(&network_service_client_ptr));
- network_service_ptr->SetClient(std::move(network_service_client_ptr));
+ network_service_ptr->SetClient(std::move(network_service_client_ptr),
+ network::mojom::NetworkServiceParams::New());
mojom::URLLoaderFactoryParamsPtr params =
mojom::URLLoaderFactoryParams::New();
diff --git a/chromium/services/network/public/cpp/url_loader_completion_status.cc b/chromium/services/network/public/cpp/url_loader_completion_status.cc
index 7cfe6e1af4b..f6fb2d80630 100644
--- a/chromium/services/network/public/cpp/url_loader_completion_status.cc
+++ b/chromium/services/network/public/cpp/url_loader_completion_status.cc
@@ -34,7 +34,8 @@ bool URLLoaderCompletionStatus::operator==(
encoded_body_length == rhs.encoded_body_length &&
decoded_body_length == rhs.decoded_body_length &&
cors_error_status == rhs.cors_error_status &&
- should_report_corb_blocking == rhs.should_report_corb_blocking;
+ should_report_corb_blocking == rhs.should_report_corb_blocking &&
+ proxy_server == rhs.proxy_server;
}
} // namespace network
diff --git a/chromium/services/network/public/cpp/url_loader_completion_status.h b/chromium/services/network/public/cpp/url_loader_completion_status.h
index 6ca5b2377be..cbc81c87d38 100644
--- a/chromium/services/network/public/cpp/url_loader_completion_status.h
+++ b/chromium/services/network/public/cpp/url_loader_completion_status.h
@@ -70,6 +70,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) URLLoaderCompletionStatus {
// Set when response blocked by CORB needs to be reported to the DevTools
// console.
bool should_report_corb_blocking = false;
+
+ // The proxy server used for this request, if any.
+ net::ProxyServer proxy_server;
};
} // namespace network
diff --git a/chromium/services/network/public/mojom/BUILD.gn b/chromium/services/network/public/mojom/BUILD.gn
index 9f8792d3dd9..5b13c2b725e 100644
--- a/chromium/services/network/public/mojom/BUILD.gn
+++ b/chromium/services/network/public/mojom/BUILD.gn
@@ -141,4 +141,8 @@ mojom("mojom") {
if (is_linux && !is_chromeos) {
enabled_features += [ "needs_crypt_config" ]
}
+
+ if (is_android || is_chromeos) {
+ enabled_features += [ "network_change_notifier_in_browser" ]
+ }
}
diff --git a/chromium/services/network/public/mojom/network_change_manager.mojom b/chromium/services/network/public/mojom/network_change_manager.mojom
index ed0c245bc25..269cceb8950 100644
--- a/chromium/services/network/public/mojom/network_change_manager.mojom
+++ b/chromium/services/network/public/mojom/network_change_manager.mojom
@@ -91,7 +91,7 @@ interface NetworkChangeManager {
// changes from Shill, and currently that has to be the browser process. This
// allows the browser process to forward the network changes to the network
// service.
- [EnableIf=is_chromeos]
+ [EnableIf=network_change_notifier_in_browser]
OnNetworkChanged(
bool dns_changed,
bool ip_address_changed,
diff --git a/chromium/services/network/public/mojom/network_service.mojom b/chromium/services/network/public/mojom/network_service.mojom
index e991c54c613..a025436d949 100644
--- a/chromium/services/network/public/mojom/network_service.mojom
+++ b/chromium/services/network/public/mojom/network_service.mojom
@@ -235,12 +235,18 @@ struct CryptConfig {
mojo_base.mojom.FilePath user_data_path;
};
+// Parameters needed to initialize the network service.
+struct NetworkServiceParams {
+ ConnectionType initial_connection_type = CONNECTION_UNKNOWN;
+ ConnectionSubtype initial_connection_subtype = SUBTYPE_UNKNOWN;
+};
+
// Browser interface to the network service.
interface NetworkService {
// Sets client used by all |NetworkContext|s creating by |NetworkService|.
// Pending requests may hang if the |client| pipe is closed before they
// complete.
- SetClient(NetworkServiceClient client);
+ SetClient(NetworkServiceClient client, NetworkServiceParams params);
// Starts observing the NetLog event stream and writing entries to |file|.
// |constants| is a legend used for decoding constant values in the log; it
diff --git a/chromium/services/network/public/mojom/proxy_config.mojom b/chromium/services/network/public/mojom/proxy_config.mojom
index d728e82a72c..a1965d2022a 100644
--- a/chromium/services/network/public/mojom/proxy_config.mojom
+++ b/chromium/services/network/public/mojom/proxy_config.mojom
@@ -4,8 +4,7 @@
module network.mojom;
-import "url/mojom/url.mojom";
-
+import "mojo/public/mojom/base/big_string.mojom";
// This corresponds to the string representation of net::ProxyConfigBypassRules.
struct ProxyBypassRules {
array<string> rules;
@@ -39,7 +38,10 @@ struct ProxyRules {
// These fields mirror those of net::ProxyConfig.
struct ProxyConfig {
bool auto_detect;
- url.mojom.Url pac_url;
+ // Note that a |BigString| is used rather than a |url.mojom.Url|, since
+ // |url.mojom.Url| imposes a smaller limit on URL size than GURL, and
+ // ProxyConfig::pac_url may contain large data: URLs that exceed this limit.
+ mojo_base.mojom.BigString pac_url;
bool pac_mandatory;
ProxyRules proxy_rules;
-}; \ No newline at end of file
+};
diff --git a/chromium/services/network/url_loader.cc b/chromium/services/network/url_loader.cc
index 1121d7b3b1a..a54048b9fb2 100644
--- a/chromium/services/network/url_loader.cc
+++ b/chromium/services/network/url_loader.cc
@@ -842,9 +842,15 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
corb_analyzer_->LogAllowedResponse();
}
}
- if ((options_ & mojom::kURLLoadOptionSniffMimeType) &&
- ShouldSniffContent(url_request_.get(), response_.get())) {
- is_more_mime_sniffing_needed_ = true;
+ if ((options_ & mojom::kURLLoadOptionSniffMimeType)) {
+ if (ShouldSniffContent(url_request_.get(), response_.get())) {
+ is_more_mime_sniffing_needed_ = true;
+ } else if (response_->head.mime_type.empty()) {
+ // Ugg. The server told us not to sniff the content but didn't give us
+ // a mime type. What's a browser to do? Turns out, we're supposed to
+ // treat the response as "text/plain". This is the most secure option.
+ response_->head.mime_type.assign("text/plain");
+ }
}
if (!is_more_mime_sniffing_needed_ && !is_more_corb_sniffing_needed_) {
// Treat feed types as text/plain.
@@ -1128,6 +1134,7 @@ void URLLoader::NotifyCompleted(int error_code) {
status.encoded_data_length = url_request_->GetTotalReceivedBytes();
status.encoded_body_length = url_request_->GetRawBodyBytes();
status.decoded_body_length = total_written_bytes_;
+ status.proxy_server = url_request_->proxy_server();
if ((options_ & mojom::kURLLoadOptionSendSSLInfoForCertificateError) &&
net::IsCertStatusError(url_request_->ssl_info().cert_status) &&
diff --git a/chromium/services/network/url_loader_unittest.cc b/chromium/services/network/url_loader_unittest.cc
index e218d8ac089..f0b7edbd3e6 100644
--- a/chromium/services/network/url_loader_unittest.cc
+++ b/chromium/services/network/url_loader_unittest.cc
@@ -827,7 +827,7 @@ TEST_F(URLLoaderTest, RespectNoSniff) {
set_sniff();
EXPECT_EQ(net::OK, Load(test_server()->GetURL("/nosniff-test.html")));
EXPECT_FALSE(did_mime_sniff());
- ASSERT_TRUE(mime_type().empty());
+ ASSERT_EQ(std::string("text/plain"), mime_type());
}
TEST_F(URLLoaderTest, SniffTextPlainDoesNotResultInHTML) {
diff --git a/chromium/services/network/websocket.cc b/chromium/services/network/websocket.cc
index feda8658aae..16c598c706b 100644
--- a/chromium/services/network/websocket.cc
+++ b/chromium/services/network/websocket.cc
@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -252,17 +253,19 @@ void WebSocket::WebSocketEventHandler::OnFinishOpeningHandshake(
response_to_pass->socket_address = response->socket_address;
size_t iter = 0;
std::string name, value;
+ std::string headers_text =
+ base::StrCat({response->headers->GetStatusLine(), "\r\n"});
while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) {
if (can_read_raw_cookies ||
!net::HttpResponseHeaders::IsCookieResponseHeader(name)) {
// We drop cookie-related headers such as "set-cookie" when the
// renderer doesn't have access.
response_to_pass->headers.push_back(mojom::HttpHeader::New(name, value));
+ base::StrAppend(&headers_text, {name, ": ", value, "\r\n"});
}
}
- response_to_pass->headers_text =
- net::HttpUtil::ConvertHeadersBackToHTTPResponse(
- response->headers->raw_headers());
+ headers_text.append("\r\n");
+ response_to_pass->headers_text = headers_text;
impl_->client_->OnFinishOpeningHandshake(std::move(response_to_pass));
}
diff --git a/chromium/services/network/websocket_factory.cc b/chromium/services/network/websocket_factory.cc
index fd21e41daec..10e053e032b 100644
--- a/chromium/services/network/websocket_factory.cc
+++ b/chromium/services/network/websocket_factory.cc
@@ -11,6 +11,7 @@
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/websocket.h"
#include "url/origin.h"
+#include "url/url_constants.h"
namespace network {
@@ -60,8 +61,13 @@ class WebSocketFactory::Delegate final : public WebSocket::Delegate {
}
bool CanReadRawCookies(const GURL& url) override {
+ DCHECK(url.SchemeIsWSOrWSS());
+ GURL::Replacements replace_scheme;
+ replace_scheme.SetSchemeStr(
+ url.SchemeIs(url::kWssScheme) ? url::kHttpsScheme : url::kHttpScheme);
+ GURL url_to_check = url.ReplaceComponents(replace_scheme);
return factory_->context_->network_service()->HasRawHeadersAccess(
- process_id_, url);
+ process_id_, url_to_check);
}
void OnCreateURLRequest(int child_id,
diff --git a/chromium/services/tracing/public/cpp/traced_process_impl.cc b/chromium/services/tracing/public/cpp/traced_process_impl.cc
index daa05310fa4..e380d010dbc 100644
--- a/chromium/services/tracing/public/cpp/traced_process_impl.cc
+++ b/chromium/services/tracing/public/cpp/traced_process_impl.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/no_destructor.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "services/tracing/public/cpp/base_agent.h"
#include "services/tracing/public/cpp/perfetto/producer_client.h"
#include "services/tracing/public/cpp/trace_event_agent.h"
@@ -74,6 +75,12 @@ void TracedProcessImpl::ConnectToTracingService(
mojom::ConnectToTracingRequestPtr request) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Tracing requires a running TaskScheduler; disable tracing
+ // for processes without it.
+ if (!base::TaskScheduler::GetInstance()) {
+ return;
+ }
+
// Ensure the TraceEventAgent has been created.
TraceEventAgent::GetInstance();
diff --git a/chromium/skia/ext/skia_commit_hash.h b/chromium/skia/ext/skia_commit_hash.h
index 27bb85ca77a..f430ab2e8d0 100644
--- a/chromium/skia/ext/skia_commit_hash.h
+++ b/chromium/skia/ext/skia_commit_hash.h
@@ -3,6 +3,6 @@
#ifndef SKIA_EXT_SKIA_COMMIT_HASH_H_
#define SKIA_EXT_SKIA_COMMIT_HASH_H_
-#define SKIA_COMMIT_HASH "fda8139b467c26d85af7de898afb57dca20d80ca-"
+#define SKIA_COMMIT_HASH "84c5c846e543066678a8fd8391171fb730886852-"
#endif // SKIA_EXT_SKIA_COMMIT_HASH_H_
diff --git a/chromium/testing/variations/fieldtrial_testing_config.json b/chromium/testing/variations/fieldtrial_testing_config.json
index 0aaf151ddd7..6d56ec0f533 100644
--- a/chromium/testing/variations/fieldtrial_testing_config.json
+++ b/chromium/testing/variations/fieldtrial_testing_config.json
@@ -4315,6 +4315,26 @@
]
}
],
+ "ServiceWorkerForegroundPriority": [
+ {
+ "platforms": [
+ "android",
+ "android_webview",
+ "chromeos",
+ "linux",
+ "mac",
+ "windows"
+ ],
+ "experiments": [
+ {
+ "name": "Enabled",
+ "enable_features": [
+ "ServiceWorkerForegroundPriority"
+ ]
+ }
+ ]
+ }
+ ],
"ServiceWorkerServicification": [
{
"platforms": [
diff --git a/chromium/third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp b/chromium/third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp
deleted file mode 100644
index 910af8be6f0..00000000000
--- a/chromium/third_party/angle/src/compiler/fuzz/translator_fuzzer.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// translator_fuzzer.cpp: A libfuzzer fuzzer for the shader translator.
-
-#include <cstddef>
-#include <cstdint>
-#include <iostream>
-#include <memory>
-#include <unordered_map>
-
-#include "angle_gl.h"
-#include "compiler/translator/Compiler.h"
-#include "compiler/translator/util.h"
-
-using namespace sh;
-
-struct TranslatorCacheKey
-{
- bool operator==(const TranslatorCacheKey &other) const
- {
- return type == other.type && spec == other.spec && output == other.output;
- }
-
- uint32_t type = 0;
- uint32_t spec = 0;
- uint32_t output = 0;
-};
-
-namespace std
-{
-
-template <>
-struct hash<TranslatorCacheKey>
-{
- std::size_t operator()(const TranslatorCacheKey &k) const
- {
- return (hash<uint32_t>()(k.type) << 1) ^ (hash<uint32_t>()(k.spec) >> 1) ^
- hash<uint32_t>()(k.output);
- }
-};
-} // namespace std
-
-struct TCompilerDeleter
-{
- void operator()(TCompiler *compiler) const { DeleteCompiler(compiler); }
-};
-
-using UniqueTCompiler = std::unique_ptr<TCompiler, TCompilerDeleter>;
-
-static std::unordered_map<TranslatorCacheKey, UniqueTCompiler> translators;
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
-{
- // Reserve some size for future compile options
- const size_t kHeaderSize = 128;
-
- if (size <= kHeaderSize)
- {
- return 0;
- }
-
- // Make sure the rest of data will be a valid C string so that we don't have to copy it.
- if (data[size - 1] != 0)
- {
- return 0;
- }
-
- uint32_t type = *reinterpret_cast<const uint32_t *>(data);
- uint32_t spec = *reinterpret_cast<const uint32_t *>(data + 4);
- uint32_t output = *reinterpret_cast<const uint32_t *>(data + 8);
- uint64_t options = *reinterpret_cast<const uint64_t *>(data + 12);
-
- if (type != GL_FRAGMENT_SHADER && type != GL_VERTEX_SHADER)
- {
- return 0;
- }
-
- if (spec != SH_GLES2_SPEC && type != SH_WEBGL_SPEC && spec != SH_GLES3_SPEC &&
- spec != SH_WEBGL2_SPEC)
- {
- return 0;
- }
-
- ShShaderOutput shaderOutput = static_cast<ShShaderOutput>(output);
- if (!(IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput)) &&
- (options & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
- {
- // This compiler option is only available in ESSL and GLSL.
- return 0;
- }
-
- std::vector<uint32_t> validOutputs;
- validOutputs.push_back(SH_ESSL_OUTPUT);
- validOutputs.push_back(SH_GLSL_COMPATIBILITY_OUTPUT);
- validOutputs.push_back(SH_GLSL_130_OUTPUT);
- validOutputs.push_back(SH_GLSL_140_OUTPUT);
- validOutputs.push_back(SH_GLSL_150_CORE_OUTPUT);
- validOutputs.push_back(SH_GLSL_330_CORE_OUTPUT);
- validOutputs.push_back(SH_GLSL_400_CORE_OUTPUT);
- validOutputs.push_back(SH_GLSL_410_CORE_OUTPUT);
- validOutputs.push_back(SH_GLSL_420_CORE_OUTPUT);
- validOutputs.push_back(SH_GLSL_430_CORE_OUTPUT);
- validOutputs.push_back(SH_GLSL_440_CORE_OUTPUT);
- validOutputs.push_back(SH_GLSL_450_CORE_OUTPUT);
- validOutputs.push_back(SH_HLSL_3_0_OUTPUT);
- validOutputs.push_back(SH_HLSL_4_1_OUTPUT);
- validOutputs.push_back(SH_HLSL_4_0_FL9_3_OUTPUT);
- bool found = false;
- for (auto valid : validOutputs)
- {
- found = found || (valid == output);
- }
- if (!found)
- {
- return 0;
- }
-
- size -= kHeaderSize;
- data += kHeaderSize;
-
- if (!sh::Initialize())
- {
- return 0;
- }
-
- TranslatorCacheKey key;
- key.type = type;
- key.spec = spec;
- key.output = output;
-
- if (translators.find(key) == translators.end())
- {
- UniqueTCompiler translator(
- ConstructCompiler(type, static_cast<ShShaderSpec>(spec), shaderOutput));
-
- if (translator == nullptr)
- {
- return 0;
- }
-
- ShBuiltInResources resources;
- sh::InitBuiltInResources(&resources);
-
- // Enable all the extensions to have more coverage
- resources.OES_standard_derivatives = 1;
- resources.OES_EGL_image_external = 1;
- resources.OES_EGL_image_external_essl3 = 1;
- resources.NV_EGL_stream_consumer_external = 1;
- resources.ARB_texture_rectangle = 1;
- resources.EXT_blend_func_extended = 1;
- resources.EXT_draw_buffers = 1;
- resources.EXT_frag_depth = 1;
- resources.EXT_shader_texture_lod = 1;
- resources.WEBGL_debug_shader_precision = 1;
- resources.EXT_shader_framebuffer_fetch = 1;
- resources.NV_shader_framebuffer_fetch = 1;
- resources.ARM_shader_framebuffer_fetch = 1;
- resources.EXT_YUV_target = 1;
- resources.MaxDualSourceDrawBuffers = 1;
-
- if (!translator->Init(resources))
- {
- return 0;
- }
-
- translators[key] = std::move(translator);
- }
-
- auto &translator = translators[key];
-
- const char *shaderStrings[] = {reinterpret_cast<const char *>(data)};
- translator->compile(shaderStrings, 1, options);
-
- return 0;
-}
diff --git a/chromium/third_party/blink/common/features.cc b/chromium/third_party/blink/common/features.cc
index 0c0ea5ae8d9..abc3b1525a6 100644
--- a/chromium/third_party/blink/common/features.cc
+++ b/chromium/third_party/blink/common/features.cc
@@ -81,6 +81,11 @@ const base::Feature kPlzDedicatedWorker{"PlzDedicatedWorker",
// Enable Portals. https://crbug.com/865123.
const base::Feature kPortals{"Portals", base::FEATURE_DISABLED_BY_DEFAULT};
+// Enable limiting previews loading hints to specific resource types.
+const base::Feature kPreviewsResourceLoadingHintsSpecificResourceTypes{
+ "PreviewsResourceLoadingHintsSpecificResourceTypes",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enable Implicit Root Scroller. https://crbug.com/903260.
const base::Feature kImplicitRootScroller{"ImplicitRootScroller",
base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chromium/third_party/blink/common/frame/user_activation_state.cc b/chromium/third_party/blink/common/frame/user_activation_state.cc
index ace8e4569cc..88686ae3b3a 100644
--- a/chromium/third_party/blink/common/frame/user_activation_state.cc
+++ b/chromium/third_party/blink/common/frame/user_activation_state.cc
@@ -9,7 +9,7 @@ namespace blink {
// The expiry time should be long enough to allow network round trips even in a
// very slow connection (to support xhr-like calls with user activation), yet
// not too long to make an "unattneded" page feel activated.
-constexpr base::TimeDelta kActivationLifespan = base::TimeDelta::FromSeconds(1);
+constexpr base::TimeDelta kActivationLifespan = base::TimeDelta::FromSeconds(5);
void UserActivationState::Activate() {
has_been_active_ = true;
diff --git a/chromium/third_party/blink/common/frame/user_activation_state_unittest.cc b/chromium/third_party/blink/common/frame/user_activation_state_unittest.cc
index 30bc7b472c3..16780b43733 100644
--- a/chromium/third_party/blink/common/frame/user_activation_state_unittest.cc
+++ b/chromium/third_party/blink/common/frame/user_activation_state_unittest.cc
@@ -65,7 +65,7 @@ TEST_F(UserActivationStateTest, ExpirationTest) {
user_activation_state.Activate();
// Right before activation expiry, both bits remain set.
- AdvanceClock(base::TimeDelta::FromMilliseconds(999));
+ AdvanceClock(base::TimeDelta::FromMilliseconds(4999));
EXPECT_TRUE(user_activation_state.HasBeenActive());
EXPECT_TRUE(user_activation_state.IsActive());
@@ -99,7 +99,7 @@ TEST_F(UserActivationStateTest, ConsumptionPlusExpirationTest) {
// An activation is not consumable after expiry.
user_activation_state.Activate();
- AdvanceClock(base::TimeDelta::FromSeconds(1));
+ AdvanceClock(base::TimeDelta::FromSeconds(5));
EXPECT_FALSE(user_activation_state.ConsumeIfActive());
// Consecutive activations within expiry is consumable only once.
diff --git a/chromium/third_party/blink/public/BUILD.gn b/chromium/third_party/blink/public/BUILD.gn
index e8fd60eedb8..fd5db06cd50 100644
--- a/chromium/third_party/blink/public/BUILD.gn
+++ b/chromium/third_party/blink/public/BUILD.gn
@@ -652,7 +652,6 @@ mojom("mojo_bindings") {
"platform/modules/notifications/notification_service.mojom",
"platform/modules/permissions/permission.mojom",
"platform/modules/permissions/permission_status.mojom",
- "platform/modules/webauthn/virtual_authenticator.mojom",
"platform/modules/webdatabase/web_database.mojom",
"platform/oom_intervention.mojom",
"platform/reporting.mojom",
@@ -665,6 +664,7 @@ mojom("mojo_bindings") {
]
public_deps = [
":android_mojo_bindings",
+ ":authenticator_test_mojo_bindings",
":web_client_hints_types_mojo_bindings",
":web_feature_mojo_bindings",
"//components/services/font/public/interfaces",
@@ -700,8 +700,14 @@ mojom("mojo_bindings") {
}
mojom("android_mojo_bindings") {
- visibility = [ ":mojo_bindings" ]
- visibility_blink = [ ":mojo_bindings_blink" ]
+ visibility = [
+ ":mojo_bindings",
+ ":authenticator_test_mojo_bindings",
+ ]
+ visibility_blink = [
+ ":mojo_bindings_blink",
+ ":authenticator_test_mojo_bindings_blink",
+ ]
sources = [
"platform/input_host.mojom",
"platform/input_messages.mojom",
@@ -736,6 +742,9 @@ mojom("android_mojo_bindings") {
export_class_attribute_blink = "BLINK_PLATFORM_EXPORT"
export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1"
export_header_blink = "third_party/blink/public/platform/web_common.h"
+
+ # Don't scramble message IDs so they are redistributable to external tests.
+ scramble_message_ids = false
}
# The embedded_frame_sink_mojo_bindings is separated from the rest of mojom
@@ -829,3 +838,18 @@ mojom("web_client_hints_types_mojo_bindings") {
"platform/web_client_hints_types.mojom",
]
}
+
+# This is a separate target because it needs unscrambled message IDs.
+mojom("authenticator_test_mojo_bindings") {
+ sources = [
+ "platform/modules/webauthn/virtual_authenticator.mojom",
+ ]
+
+ public_deps = [
+ ":android_mojo_bindings",
+ "//url/mojom:url_mojom_gurl",
+ ]
+
+ # Don't scramble message IDs so they are redistributable to external tests.
+ scramble_message_ids = false
+}
diff --git a/chromium/third_party/blink/public/common/features.h b/chromium/third_party/blink/public/common/features.h
index 7eec8dc5299..dd18e8e40a8 100644
--- a/chromium/third_party/blink/public/common/features.h
+++ b/chromium/third_party/blink/public/common/features.h
@@ -30,6 +30,8 @@ BLINK_COMMON_EXPORT extern const base::Feature kNavigationPredictor;
BLINK_COMMON_EXPORT extern const base::Feature kOnionSoupDOMStorage;
BLINK_COMMON_EXPORT extern const base::Feature kPlzDedicatedWorker;
BLINK_COMMON_EXPORT extern const base::Feature kPortals;
+BLINK_COMMON_EXPORT extern const base::Feature
+ kPreviewsResourceLoadingHintsSpecificResourceTypes;
BLINK_COMMON_EXPORT extern const base::Feature kRTCGetDisplayMedia;
BLINK_COMMON_EXPORT extern const base::Feature kRTCUnifiedPlanByDefault;
BLINK_COMMON_EXPORT extern const base::Feature kRTCOfferExtmapAllowMixed;
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
index 04860137a09..e06325a44bd 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
@@ -164,6 +164,7 @@ def member_context(dictionary, member):
'has_explicit_presence': has_explicit_presence,
'has_method_name': has_method_name_for_dictionary_member(member),
'idl_type': idl_type.base_type,
+ 'is_callback_function_type': idl_type.is_callback_function,
'is_interface_type': idl_type.is_interface_type and not is_deprecated_dictionary,
'is_nullable': idl_type.is_nullable,
'is_object': unwrapped_idl_type.name == 'Object' or is_deprecated_dictionary,
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl
index 5562da43f2d..a32227277a3 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cc.tmpl
@@ -84,6 +84,12 @@ void {{v8_class}}::ToImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8_value, {
{% if member.deprecate_as %}
Deprecation::CountDeprecation(CurrentExecutionContext(isolate), WebFeature::k{{member.deprecate_as}});
{% endif %}
+ {% if member.is_callback_function_type %}
+ if (!{{member.v8_value}}->IsFunction()) {
+ exception_state.ThrowTypeError("member {{member.name}} is not a function.");
+ return;
+ }
+ {% endif %}
{{v8_value_to_local_cpp_value(member) | trim | indent}}
{% if member.is_interface_type %}
if (!{{member.cpp_value}}) {
diff --git a/chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc b/chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc
index 680dd044269..a1f7a5caa61 100644
--- a/chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc
+++ b/chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc
@@ -82,12 +82,15 @@ void OomInterventionImpl::Check(TimerBase*) {
if (oom_detected) {
if (navigate_ads_enabled_ || purge_v8_memory_enabled_) {
for (const auto& page : Page::OrdinaryPages()) {
- if (page->MainFrame()->IsLocalFrame()) {
- LocalFrame* frame = ToLocalFrame(page->MainFrame());
+ for (Frame* frame = page->MainFrame(); frame;
+ frame = frame->Tree().TraverseNext()) {
+ if (!frame->IsLocalFrame())
+ continue;
+ LocalFrame* local_frame = ToLocalFrame(frame);
if (navigate_ads_enabled_)
- frame->GetDocument()->NavigateLocalAdsFrames();
+ local_frame->GetDocument()->NavigateLocalAdsFrames();
if (purge_v8_memory_enabled_)
- frame->ForciblyPurgeV8Memory();
+ local_frame->ForciblyPurgeV8Memory();
}
}
}
diff --git a/chromium/third_party/blink/renderer/core/css/style_engine.cc b/chromium/third_party/blink/renderer/core/css/style_engine.cc
index db393e393ab..8248be742a1 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.cc
@@ -511,6 +511,15 @@ const ActiveStyleSheetVector StyleEngine::ActiveStyleSheetsForInspector() {
return active_style_sheets;
}
+void StyleEngine::ShadowRootInsertedToDocument(ShadowRoot& shadow_root) {
+ DCHECK(shadow_root.isConnected());
+ if (GetDocument().IsDetached() || !shadow_root.HasAdoptedStyleSheets())
+ return;
+ EnsureStyleSheetCollectionFor(shadow_root);
+ SetNeedsActiveStyleUpdate(shadow_root);
+ active_tree_scopes_.insert(&shadow_root);
+}
+
void StyleEngine::ShadowRootRemovedFromDocument(ShadowRoot* shadow_root) {
style_sheet_collection_map_.erase(shadow_root);
active_tree_scopes_.erase(shadow_root);
diff --git a/chromium/third_party/blink/renderer/core/css/style_engine.h b/chromium/third_party/blink/renderer/core/css/style_engine.h
index d05f7cbc72d..b8b17e964e7 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.h
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.h
@@ -217,6 +217,7 @@ class CORE_EXPORT StyleEngine final
void ResetCSSFeatureFlags(const RuleFeatureSet&);
+ void ShadowRootInsertedToDocument(ShadowRoot&);
void ShadowRootRemovedFromDocument(ShadowRoot*);
void AddTreeBoundaryCrossingScope(const TreeScope&);
const TreeOrderedList& TreeBoundaryCrossingScopes() const {
diff --git a/chromium/third_party/blink/renderer/core/dom/container_node.cc b/chromium/third_party/blink/renderer/core/dom/container_node.cc
index 59467cf7652..09def33064f 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.cc
@@ -688,6 +688,10 @@ Node* ContainerNode::RemoveChild(Node* old_child,
WillRemoveChild(*child);
+ // TODO(crbug.com/927646): |WillRemoveChild()| may dispatch events that set
+ // focus to a node that will be detached, leaving behind a detached focused
+ // node. Fix it.
+
// Mutation events might have moved this child into a different parent.
if (child->parentNode() != this) {
exception_state.ThrowDOMException(
diff --git a/chromium/third_party/blink/renderer/core/dom/document.cc b/chromium/third_party/blink/renderer/core/dom/document.cc
index e5d02bd5288..1aa4f77b363 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document.cc
@@ -3182,6 +3182,7 @@ void Document::open() {
if (frame_ && frame_->Client())
frame_->Client()->AbortClientNavigation();
}
+ javascript_url_task_handle_.Cancel();
// For each shadow-including inclusive descendant |node| of |document|, erase
// all event listeners and handlers given |node|.
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
index 39d2eed15fc..0788dc8db18 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -170,6 +170,8 @@ Node::InsertionNotificationRequest ShadowRoot::InsertedInto(
if (!insertion_point.isConnected())
return kInsertionDone;
+ GetDocument().GetStyleEngine().ShadowRootInsertedToDocument(*this);
+
GetDocument().GetSlotAssignmentEngine().Connected(*this);
// FIXME: When parsing <video controls>, InsertedInto() is called many times
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
index 6cd63bbe743..b3c08463402 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_buffer.cc
@@ -225,7 +225,8 @@ void FindBuffer::CollectTextUntilBlockBoundary(Node& start_node) {
if (ShouldIgnoreContents(*node)) {
// Move the node so we wouldn't encounter this node or its descendants
// later.
- buffer_.push_back(kObjectReplacementCharacter);
+ if (!IsHTMLWBRElement(ToHTMLElement(*node)))
+ buffer_.push_back(kObjectReplacementCharacter);
node = FlatTreeTraversal::NextSkippingChildren(*node);
continue;
}
diff --git a/chromium/third_party/blink/renderer/core/editing/frame_caret.cc b/chromium/third_party/blink/renderer/core/editing/frame_caret.cc
index 95cce009cde..55e590dc927 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_caret.cc
+++ b/chromium/third_party/blink/renderer/core/editing/frame_caret.cc
@@ -74,6 +74,7 @@ const PositionWithAffinity FrameCaret::CaretPosition() const {
selection_editor_->ComputeVisibleSelectionInDOMTree();
if (!selection.IsCaret())
return PositionWithAffinity();
+ DCHECK(selection.Start().IsValidFor(*frame_->GetDocument()));
return PositionWithAffinity(selection.Start(), selection.Affinity());
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
index 4bac8b63743..e6917e62f31 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -134,6 +134,7 @@
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scoped_page_pauser.h"
+#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
@@ -11594,6 +11595,88 @@ TEST_F(WebFrameSimTest, TestScrollFocusedEditableElementIntoView) {
EXPECT_EQ(1, WebView().FakePageScaleAnimationPageScaleForTesting());
}
+// Ensures scrolling a focused editable text into view that's located in the
+// root scroller works by scrolling the root scroller.
+TEST_F(WebFrameSimTest, TestScrollFocusedEditableInRootScroller) {
+ WebView().MainFrameWidget()->Resize(WebSize(500, 300));
+ WebView().SetDefaultPageScaleLimits(1.f, 4);
+ WebView().EnableFakePageScaleAnimationForTesting(true);
+ WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false);
+ WebView().GetPage()->GetSettings().SetViewportEnabled(false);
+ WebView().GetSettings()->SetAutoZoomFocusedNodeToLegibleScale(true);
+
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ ::-webkit-scrollbar {
+ width: 0px;
+ height: 0px;
+ }
+ body,html {
+ width: 100%;
+ height: 100%;
+ margin: 0px;
+ }
+ input {
+ border: 0;
+ padding: 0;
+ margin-left: 200px;
+ margin-top: 700px;
+ width: 100px;
+ height: 20px;
+ }
+ #scroller {
+ background: silver;
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+ }
+ </style>
+ <div id="scroller" tabindex="-1">
+ <input type="text">
+ </div>
+ )HTML");
+
+ Compositor().BeginFrame();
+
+ TopDocumentRootScrollerController& rs_controller =
+ GetDocument().GetPage()->GlobalRootScrollerController();
+
+ Element* scroller = GetDocument().getElementById("scroller");
+ ASSERT_EQ(scroller, rs_controller.GlobalRootScroller());
+
+ LocalFrame* frame = ToLocalFrame(WebView().GetPage()->MainFrame());
+ VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport();
+
+ WebView().AdvanceFocus(false);
+
+ rs_controller.RootScrollerArea()->SetScrollOffset(ScrollOffset(0, 300),
+ kProgrammaticScroll);
+
+ FloatRect inputRect(200, 700, 100, 20);
+ ASSERT_EQ(1, visual_viewport.Scale());
+ ASSERT_EQ(FloatPoint(0, 300),
+ visual_viewport.VisibleRectInDocument().Location());
+ ASSERT_FALSE(visual_viewport.VisibleRectInDocument().Contains(inputRect));
+
+ WebView()
+ .MainFrameImpl()
+ ->FrameWidget()
+ ->ScrollFocusedEditableElementIntoView();
+
+ EXPECT_EQ(1, WebView().FakePageScaleAnimationPageScaleForTesting());
+
+ ScrollOffset target_offset = ToFloatSize(
+ FloatPoint(WebView().FakePageScaleAnimationTargetPositionForTesting()));
+
+ rs_controller.RootScrollerArea()->SetScrollOffset(target_offset,
+ kProgrammaticScroll);
+
+ EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains(inputRect));
+}
+
TEST_F(WebFrameSimTest, ScrollFocusedIntoViewClipped) {
// The Android On-Screen Keyboard (OSK) resizes the Widget Blink is hosted
// in. When the keyboard is shown, we scroll and zoom in on the currently
diff --git a/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc
index 2455c372862..8dde30b743e 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -2148,6 +2148,25 @@ void WebViewImpl::ComputeScaleAndScrollForEditableElementRects(
bool& need_animation) {
VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
+ TopDocumentRootScrollerController& controller =
+ GetPage()->GlobalRootScrollerController();
+ Node* root_scroller = controller.GlobalRootScroller();
+
+ IntRect element_bounds_in_content = element_bounds_in_document;
+ IntRect caret_bounds_in_content = caret_bounds_in_document;
+
+ // If the page has a non-default root scroller then we need to scroll that
+ // rather than the "real" viewport. However, the given coordinates are in the
+ // real viewport's document space rather than the root scroller's so we
+ // perform the conversion here. TODO(bokan): Convert this function to take
+ // coordinates in absolute/root-frame coordinates to make this more
+ // consistent. https://crbug.com/931447.
+ if (root_scroller != MainFrameImpl()->GetFrame()->GetDocument()) {
+ ScrollOffset offset = controller.RootScrollerArea()->GetScrollOffset();
+ element_bounds_in_content.Move(FlooredIntSize(offset));
+ caret_bounds_in_content.Move(FlooredIntSize(offset));
+ }
+
if (!zoom_into_legible_scale) {
new_scale = PageScaleFactor();
} else {
@@ -2155,14 +2174,14 @@ void WebViewImpl::ComputeScaleAndScrollForEditableElementRects(
// the caret height will become minReadableCaretHeightForNode (adjusted
// for dpi and font scale factor).
const int min_readable_caret_height_for_node =
- (element_bounds_in_document.Height() >=
- 2 * caret_bounds_in_document.Height()
+ (element_bounds_in_content.Height() >=
+ 2 * caret_bounds_in_content.Height()
? minReadableCaretHeightForTextArea
: minReadableCaretHeight) *
MainFrameImpl()->GetFrame()->PageZoomFactor();
new_scale = ClampPageScaleFactorToLimits(
MaximumLegiblePageScale() * min_readable_caret_height_for_node /
- caret_bounds_in_document.Height());
+ caret_bounds_in_content.Height());
new_scale = std::max(new_scale, PageScaleFactor());
}
const float delta_scale = new_scale / PageScaleFactor();
@@ -2177,17 +2196,17 @@ void WebViewImpl::ComputeScaleAndScrollForEditableElementRects(
// If the caret is offscreen, then animate.
if (!visual_viewport.VisibleRectInDocument().Contains(
- caret_bounds_in_document))
+ caret_bounds_in_content))
need_animation = true;
// If the box is partially offscreen and it's possible to bring it fully
// onscreen, then animate.
if (visual_viewport.VisibleRect().Width() >=
- element_bounds_in_document.Width() &&
+ element_bounds_in_content.Width() &&
visual_viewport.VisibleRect().Height() >=
- element_bounds_in_document.Height() &&
+ element_bounds_in_content.Height() &&
!visual_viewport.VisibleRectInDocument().Contains(
- element_bounds_in_document))
+ element_bounds_in_content))
need_animation = true;
if (!need_animation)
@@ -2196,36 +2215,36 @@ void WebViewImpl::ComputeScaleAndScrollForEditableElementRects(
FloatSize target_viewport_size(visual_viewport.Size());
target_viewport_size.Scale(1 / new_scale);
- if (element_bounds_in_document.Width() <= target_viewport_size.Width()) {
+ if (element_bounds_in_content.Width() <= target_viewport_size.Width()) {
// Field is narrower than screen. Try to leave padding on left so field's
// label is visible, but it's more important to ensure entire field is
// onscreen.
int ideal_left_padding = target_viewport_size.Width() * leftBoxRatio;
int max_left_padding_keeping_box_onscreen =
- target_viewport_size.Width() - element_bounds_in_document.Width();
- new_scroll.SetX(element_bounds_in_document.X() -
+ target_viewport_size.Width() - element_bounds_in_content.Width();
+ new_scroll.SetX(element_bounds_in_content.X() -
std::min<int>(ideal_left_padding,
max_left_padding_keeping_box_onscreen));
} else {
// Field is wider than screen. Try to left-align field, unless caret would
// be offscreen, in which case right-align the caret.
new_scroll.SetX(std::max<int>(
- element_bounds_in_document.X(),
- caret_bounds_in_document.X() + caret_bounds_in_document.Width() +
+ element_bounds_in_content.X(),
+ caret_bounds_in_content.X() + caret_bounds_in_content.Width() +
caretPadding - target_viewport_size.Width()));
}
- if (element_bounds_in_document.Height() <= target_viewport_size.Height()) {
+ if (element_bounds_in_content.Height() <= target_viewport_size.Height()) {
// Field is shorter than screen. Vertically center it.
new_scroll.SetY(
- element_bounds_in_document.Y() -
- (target_viewport_size.Height() - element_bounds_in_document.Height()) /
+ element_bounds_in_content.Y() -
+ (target_viewport_size.Height() - element_bounds_in_content.Height()) /
2);
} else {
// Field is taller than screen. Try to top align field, unless caret would
// be offscreen, in which case bottom-align the caret.
new_scroll.SetY(std::max<int>(
- element_bounds_in_document.Y(),
- caret_bounds_in_document.Y() + caret_bounds_in_document.Height() +
+ element_bounds_in_content.Y(),
+ caret_bounds_in_content.Y() + caret_bounds_in_content.Height() +
caretPadding - target_viewport_size.Height()));
}
}
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
index 5a1cc40c235..36491a4b86f 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
@@ -143,14 +143,16 @@ DOMArrayBuffer* FileReaderLoader::ArrayBufferResult() {
if (!raw_data_ || error_code_ != FileErrorCode::kOK)
return nullptr;
- DOMArrayBuffer* result = DOMArrayBuffer::Create(raw_data_->ToArrayBuffer());
- if (finished_loading_) {
- array_buffer_result_ = result;
- AdjustReportedMemoryUsageToV8(
- -1 * static_cast<int64_t>(raw_data_->ByteLength()));
- raw_data_.reset();
+ if (!finished_loading_) {
+ return DOMArrayBuffer::Create(
+ ArrayBuffer::Create(raw_data_->Data(), raw_data_->ByteLength()));
}
- return result;
+
+ array_buffer_result_ = DOMArrayBuffer::Create(raw_data_->ToArrayBuffer());
+ AdjustReportedMemoryUsageToV8(-1 *
+ static_cast<int64_t>(raw_data_->ByteLength()));
+ raw_data_.reset();
+ return array_buffer_result_;
}
String FileReaderLoader::StringResult() {
diff --git a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 5a9963e8ed5..6197e91bd3c 100644
--- a/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1496,7 +1496,6 @@ void WebLocalFrameImpl::DispatchPrintEventRecursively(
int WebLocalFrameImpl::PrintBegin(const WebPrintParams& print_params,
const WebNode& constrain_to_node) {
- DCHECK(!GetFrame()->GetDocument()->IsFrameSet());
WebPluginContainerImpl* plugin_container = nullptr;
if (constrain_to_node.IsNull()) {
// If this is a plugin document, check if the plugin supports its own
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index c9a271fdd85..2ef7a11feae 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -984,44 +984,47 @@ void HTMLCanvasElement::PushFrame(scoped_refptr<CanvasResource> image,
}
bool HTMLCanvasElement::ShouldAccelerate(AccelerationCriteria criteria) const {
- if (base::FeatureList::IsEnabled(features::kAlwaysAccelerateCanvas))
- return true;
-
- if (context_ && !Is2d())
- return false;
-
- // The following is necessary for handling the special case of canvases in the
- // dev tools overlay, which run in a process that supports accelerated 2d
- // canvas but in a special compositing context that does not.
- if (GetLayoutBox() && !GetLayoutBox()->HasAcceleratedCompositing())
- return false;
-
- base::CheckedNumeric<int> checked_canvas_pixel_count = Size().Width();
- checked_canvas_pixel_count *= Size().Height();
- if (!checked_canvas_pixel_count.IsValid())
- return false;
- int canvas_pixel_count = checked_canvas_pixel_count.ValueOrDie();
-
- // Do not use acceleration for small canvas.
- if (criteria != kIgnoreResourceLimitCriteria) {
- Settings* settings = GetDocument().GetSettings();
- if (!settings ||
- canvas_pixel_count < settings->GetMinimumAccelerated2dCanvasSize()) {
+ // With this feature enabled we want to accelerate canvases whenever we can.
+ // This does not include when the context_provider CANNOT accelerated
+ // canvases.
+ if (!base::FeatureList::IsEnabled(features::kAlwaysAccelerateCanvas)) {
+ if (context_ && !Is2d())
return false;
- }
- // When GPU allocated memory runs low (due to having created too many
- // accelerated canvases), the compositor starves and browser becomes laggy.
- // Thus, we should stop allocating more GPU memory to new canvases created
- // when the current memory usage exceeds the threshold.
- if (global_gpu_memory_usage_ >= kMaxGlobalGPUMemoryUsage)
+ // The following is necessary for handling the special case of canvases in
+ // the dev tools overlay, which run in a process that supports accelerated
+ // 2d canvas but in a special compositing context that does not.
+ if (GetLayoutBox() && !GetLayoutBox()->HasAcceleratedCompositing())
return false;
- // Allocating too many GPU resources can makes us run into the driver's
- // resource limits. So we need to keep the number of texture resources
- // under tight control
- if (global_accelerated_context_count_ >= kMaxGlobalAcceleratedResourceCount)
+ base::CheckedNumeric<int> checked_canvas_pixel_count = Size().Width();
+ checked_canvas_pixel_count *= Size().Height();
+ if (!checked_canvas_pixel_count.IsValid())
return false;
+ int canvas_pixel_count = checked_canvas_pixel_count.ValueOrDie();
+
+ // Do not use acceleration for small canvas.
+ if (criteria != kIgnoreResourceLimitCriteria) {
+ Settings* settings = GetDocument().GetSettings();
+ if (!settings ||
+ canvas_pixel_count < settings->GetMinimumAccelerated2dCanvasSize()) {
+ return false;
+ }
+
+ // When GPU allocated memory runs low (due to having created too many
+ // accelerated canvases), the compositor starves and browser becomes
+ // laggy. Thus, we should stop allocating more GPU memory to new canvases
+ // created when the current memory usage exceeds the threshold.
+ if (global_gpu_memory_usage_ >= kMaxGlobalGPUMemoryUsage)
+ return false;
+
+ // Allocating too many GPU resources can makes us run into the driver's
+ // resource limits. So we need to keep the number of texture resources
+ // under tight control
+ if (global_accelerated_context_count_ >=
+ kMaxGlobalAcceleratedResourceCount)
+ return false;
+ }
}
// Avoid creating |contextProvider| until we're sure we want to try use it,
diff --git a/chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js b/chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js
index d4b6856b22f..b5071055647 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js
+++ b/chromium/third_party/blink/renderer/core/html/forms/resources/pickerCommon.js
@@ -141,7 +141,14 @@ function _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeigh
var availableSpaceBelow = availRect.maxY - anchorRect.maxY;
availableSpaceBelow = Math.max(0, Math.min(availRect.height, availableSpaceBelow));
- if (windowRect.height > availableSpaceBelow && availableSpaceBelow < availableSpaceAbove) {
+
+ // In some situations, there may be no space available. This can happen on
+ // Linux when using a buggy window manager (https://crbug.com/774232). When
+ // this happens, don't try to constrain the window at all.
+ if (availableSpaceAbove == 0 && availableSpaceBelow == 0) {
+ windowRect.height = Math.max(minHeight, windowRect.height);
+ windowRect.y = anchorRect.maxY;
+ } else if (windowRect.height > availableSpaceBelow && availableSpaceBelow < availableSpaceAbove) {
windowRect.height = Math.min(windowRect.height, availableSpaceAbove);
windowRect.height = Math.max(windowRect.height, minHeight);
windowRect.y = anchorRect.y - windowRect.height;
@@ -156,6 +163,11 @@ function _adjustWindowRectVertically(windowRect, availRect, anchorRect, minHeigh
* Arguments are DIPs.
*/
function _adjustWindowRectHorizontally(windowRect, availRect, anchorRect, minWidth) {
+ if (anchorRect.maxX <= availRect.x || availRect.maxX <= anchorRect.x) {
+ windowRect.width = Math.max(minWidth, windowRect.width);
+ windowRect.x = anchorRect.x
+ return;
+ }
windowRect.width = Math.min(windowRect.width, availRect.width);
windowRect.width = Math.max(windowRect.width, minWidth);
windowRect.x = anchorRect.x;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc b/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
index add2d09f30b..3eec0b9eb69 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -429,7 +429,9 @@ bool TextControlElement::SetSelectionRange(
direction = kSelectionHasForwardDirection;
bool did_change = CacheSelection(start, end, direction);
- if (GetDocument().FocusedElement() != this)
+ // TODO(crbug.com/927646): The focused element should always be connected, but
+ // we fail to ensure so in some cases. Fix it.
+ if (GetDocument().FocusedElement() != this || !isConnected())
return did_change;
HTMLElement* inner_editor = InnerEditorElement();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_box.cc
index ce5f73c0eea..f2a3d68ff60 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.cc
@@ -656,8 +656,12 @@ LayoutRect LayoutBox::ScrollRectToVisibleRecursive(
if (!GetFrameView())
return absolute_rect;
- if (params.stop_at_main_frame_layout_viewport && IsLayoutView() &&
- GetFrame()->IsMainFrame())
+ // If we've reached the main frame's layout viewport (which is always set to
+ // the global root scroller, see ViewportScrollCallback::SetScroller), abort
+ // if the stop_at_main_frame_layout_viewport option is set. We do this so
+ // that we can allow a smooth "scroll and zoom" animation to do the final
+ // scroll in cases like scrolling a focused editable box into view.
+ if (params.stop_at_main_frame_layout_viewport && IsGlobalRootScroller())
return absolute_rect;
// Presumably the same issue as in setScrollTop. See crbug.com/343132.
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc
index f17f377b405..42fcaab49c5 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -523,9 +523,12 @@ LayoutUnit LayoutFlexibleBox::ChildIntrinsicLogicalWidth(
// If our height is auto, make sure that our returned height is unaffected by
// earlier layouts by returning the shrink-to-fit size.
if (!CrossAxisLengthIsDefinite(child, child.StyleRef().LogicalWidth())) {
+ LayoutUnit available_size =
+ ContentLogicalWidth() - child.MarginLogicalWidth();
MinMaxSize sizes{child.MinPreferredLogicalWidth(),
child.MaxPreferredLogicalWidth()};
- return sizes.ShrinkToFit(ContentLogicalWidth());
+ return child.ConstrainLogicalWidthByMinMax(
+ sizes.ShrinkToFit(available_size), available_size, this);
}
return child.LogicalWidth();
@@ -1236,20 +1239,6 @@ void LayoutFlexibleBox::SetOverrideMainAxisContentSizeForChild(FlexItem& item) {
}
}
-bool LayoutFlexibleBox::ChildLogicalHeightStretchesToFlexboxSize(
- FlexItem& item) const {
- if (IsMultiline())
- return false;
- if (!NeedToStretchChildLogicalHeight(*item.box))
- return false;
- if (HasAutoMarginsInCrossAxis(*item.box))
- return false;
- if (item.box->IntrinsicContentLogicalHeight() == -1)
- return false;
-
- return HasDefiniteLogicalHeight();
-}
-
LayoutUnit LayoutFlexibleBox::StaticMainAxisPositionForPositionedChild(
const LayoutBox& child) {
const LayoutUnit available_space =
@@ -1408,35 +1397,6 @@ void LayoutFlexibleBox::LayoutLineItems(FlexLine* current_line,
child->SetShouldCheckForPaintInvalidation();
SetOverrideMainAxisContentSizeForChild(flex_item);
-
- // We may have already forced relayout for orthogonal flowing children in
- // computeInnerFlexBaseSizeForChild.
- bool force_child_relayout =
- relayout_children && !relaid_out_children_.Contains(child);
-
- // Apply optimization 1 from section 9.8 for row flexboxes by overriding
- // the logical height of stretchable children to the parent's definite
- // height, if present (https://crbug.com/703512).
- if (ChildLogicalHeightStretchesToFlexboxSize(flex_item)) {
- LogicalExtentComputedValues computed_values;
- ComputeLogicalHeight(computed_values);
- LayoutUnit cross_axis_extent = computed_values.extent_;
- DCHECK_NE(cross_axis_extent, LayoutUnit(-1));
-
- // Compute the maximum possible cross axis extent available, since we
- // don't optimize for intrinsically sized children.
- LayoutUnit stretched_logical_height =
- std::max(child->BorderAndPaddingLogicalHeight(),
- cross_axis_extent - flex_item.CrossAxisMarginExtent());
- LayoutUnit clamped_logical_height = child->ConstrainLogicalHeightByMinMax(
- stretched_logical_height, child->IntrinsicContentLogicalHeight());
-
- child->SetOverrideLogicalHeight(clamped_logical_height);
- if (clamped_logical_height != child->LogicalHeight()) {
- force_child_relayout = true;
- }
- }
-
// The flexed content size and the override size include the scrollbar
// width, so we need to compare to the size including the scrollbar.
if (flex_item.flexed_content_size !=
@@ -1447,6 +1407,10 @@ void LayoutFlexibleBox::LayoutLineItems(FlexLine* current_line,
// updateAutoMarginsInCrossAxis, we reset the margins here.
ResetAutoMarginsAndLogicalTopInCrossAxis(*child);
}
+ // We may have already forced relayout for orthogonal flowing children in
+ // computeInnerFlexBaseSizeForChild.
+ bool force_child_relayout =
+ relayout_children && !relaid_out_children_.Contains(child);
// TODO(dgrogan): Broaden the NG part of this check once NG types other
// than Mixin derivatives are cached.
if (child->IsLayoutBlock() &&
@@ -1655,7 +1619,7 @@ void LayoutFlexibleBox::ApplyStretchAlignmentToChild(FlexItem& flex_item) {
flex_item.cross_axis_size != child.LogicalHeight();
if (child.IsLayoutBlock() &&
ToLayoutBlock(child).HasPercentHeightDescendants() &&
- !CanAvoidLayoutForNGChild(child) && !child.HasOverrideLogicalHeight()) {
+ !CanAvoidLayoutForNGChild(child)) {
// Have to force another relayout even though the child is sized
// correctly, because its descendants are not sized correctly yet. Our
// previous layout of the child was done without an override height set.
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h
index 0d340bb8f49..d1ad9b9b649 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h
@@ -189,7 +189,6 @@ class CORE_EXPORT LayoutFlexibleBox : public LayoutBlock {
void ResetAutoMarginsAndLogicalTopInCrossAxis(LayoutBox& child);
void SetOverrideMainAxisContentSizeForChild(FlexItem&);
- bool ChildLogicalHeightStretchesToFlexboxSize(FlexItem&) const;
void PrepareChildForPositionedLayout(LayoutBox& child);
void LayoutLineItems(FlexLine*, bool relayout_children, SubtreeLayoutScope&);
void ApplyLineItemsPosition(FlexLine*);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object.cc b/chromium/third_party/blink/renderer/core/layout/layout_object.cc
index 161a879c44d..33be8a2e95b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1503,10 +1503,17 @@ bool LayoutObject::HasDistortingVisualEffects() const {
}
bool LayoutObject::HasNonZeroEffectiveOpacity() const {
- PropertyTreeState paint_properties = EnclosingLayer()
- ->GetLayoutObject()
- .FirstFragment()
- .LocalBorderBoxProperties();
+ const FragmentData& fragment =
+ EnclosingLayer()->GetLayoutObject().FirstFragment();
+
+ // This can happen for an iframe element which is outside the viewport and has
+ // therefore never been painted. In that case, we do the safe thing -- report
+ // it as having non-zero opacity -- since this method is used by
+ // IntersectionObserver to detect occlusion.
+ if (!fragment.HasLocalBorderBoxProperties())
+ return true;
+
+ PropertyTreeState paint_properties = fragment.LocalBorderBoxProperties();
for (const auto* effect = SafeUnalias(paint_properties.Effect()); effect;
effect = SafeUnalias(effect->Parent())) {
diff --git a/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc b/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
index 040374a5e0e..a90cdf13423 100644
--- a/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
+++ b/chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -380,7 +380,7 @@ BaseFetchContext::CanRequestInternal(
// Loading of a subresource may be blocked by previews resource loading hints.
if (GetPreviewsResourceLoadingHints() &&
!GetPreviewsResourceLoadingHints()->AllowLoad(
- url, resource_request.Priority())) {
+ type, url, resource_request.Priority())) {
return ResourceRequestBlockedReason::kOther;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc
index a8ff441153f..68c172eb04a 100644
--- a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc
+++ b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.cc
@@ -4,9 +4,11 @@
#include "third_party/blink/renderer/core/loader/previews_resource_loading_hints.h"
+#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -14,6 +16,7 @@
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -48,16 +51,44 @@ PreviewsResourceLoadingHints::PreviewsResourceLoadingHints(
subresource_patterns_to_block_usage_.assign(
subresource_patterns_to_block.size(), false);
blocked_resource_load_priority_counts_.fill(0);
+
+ // Populate which specific resource types are eligible for blocking.
+ // Certain resource types are blocked by default since their blocking
+ // is currently verified by the server verification pipeline. Note that
+ // the blocking of these resource types can be overridden using field trial.
+ block_resource_type_[static_cast<int>(ResourceType::kCSSStyleSheet)] = true;
+ block_resource_type_[static_cast<int>(ResourceType::kScript)] = true;
+ block_resource_type_[static_cast<int>(ResourceType::kRaw)] = true;
+ for (int i = 0; i < static_cast<int>(ResourceType::kLast) + 1; ++i) {
+ // Parameter names are of format: "block_resource_type_%d". The value
+ // should be either "true" or "false".
+ block_resource_type_[i] = base::GetFieldTrialParamByFeatureAsBool(
+ features::kPreviewsResourceLoadingHintsSpecificResourceTypes,
+ String::Format("block_resource_type_%d", i).Ascii().data(),
+ block_resource_type_[i]);
+ }
+
+ // Ensure that the ResourceType enums have not changed. These should not be
+ // changed since the resource type integer values are used as field trial
+ // params.
+ static_assert(static_cast<int>(ResourceType::kImage) == 1 &&
+ static_cast<int>(ResourceType::kCSSStyleSheet) == 2 &&
+ static_cast<int>(ResourceType::kScript) == 3,
+ "ResourceType enums can't be changed");
}
PreviewsResourceLoadingHints::~PreviewsResourceLoadingHints() = default;
bool PreviewsResourceLoadingHints::AllowLoad(
+ ResourceType type,
const KURL& resource_url,
ResourceLoadPriority resource_load_priority) const {
if (!resource_url.ProtocolIsInHTTPFamily())
return true;
+ if (!block_resource_type_[static_cast<int>(type)])
+ return true;
+
WTF::String resource_url_string = resource_url.GetString();
resource_url_string = resource_url_string.Left(resource_url.PathEnd());
bool allow_load = true;
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h
index 2ad7cc24cf1..db3febbe135 100644
--- a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h
+++ b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints.h
@@ -7,9 +7,11 @@
#include <vector>
+#include "base/feature_list.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -38,9 +40,11 @@ class CORE_EXPORT PreviewsResourceLoadingHints final
const std::vector<WTF::String>& subresource_patterns_to_block);
~PreviewsResourceLoadingHints();
- // Returns true if load of resource with URL |resource_url| and priority
- // |resource_load_priority| is allowed as per resource loading hints.
- bool AllowLoad(const KURL& resource_url,
+ // Returns true if load of resource with type |type|, URL |resource_url|
+ // and priority |resource_load_priority| is allowed as per resource loading
+ // hints.
+ bool AllowLoad(ResourceType type,
+ const KURL& resource_url,
ResourceLoadPriority resource_load_priority) const;
virtual void Trace(blink::Visitor*);
@@ -64,6 +68,10 @@ class CORE_EXPORT PreviewsResourceLoadingHints final
// be blocked.
const std::vector<WTF::String> subresource_patterns_to_block_;
+ // True if resource blocking hints should apply to resource of a given type.
+ bool block_resource_type_[static_cast<int>(ResourceType::kLast) + 1] = {
+ false};
+
// |subresource_patterns_to_block_usage_| records whether the pattern located
// at the same index in |subresource_patterns_to_block_| was ever blocked.
mutable std::vector<bool> subresource_patterns_to_block_usage_;
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc
index 4d5a001a2e6..03869ad50d8 100644
--- a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_test.cc
@@ -8,15 +8,18 @@
#include <vector>
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -42,7 +45,8 @@ TEST_F(PreviewsResourceLoadingHintsTest, NoPatterns) {
PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
dummy_page_holder_->GetDocument(), ukm::UkmRecorder::GetNewSourceID(),
subresources_to_block);
- EXPECT_TRUE(hints->AllowLoad(KURL("https://www.example.com/"),
+ EXPECT_TRUE(hints->AllowLoad(ResourceType::kScript,
+ KURL("https://www.example.com/"),
ResourceLoadPriority::kHighest));
}
@@ -72,16 +76,24 @@ TEST_F(PreviewsResourceLoadingHintsTest, OnePattern) {
for (const auto& test : tests) {
base::HistogramTester histogram_tester;
+ // By default, resource blocking hints do not apply to images.
+ EXPECT_TRUE(hints->AllowLoad(ResourceType::kImage, test.url,
+ ResourceLoadPriority::kHighest));
+ // By default, resource blocking hints apply to CSS and Scripts.
EXPECT_EQ(test.allow_load_expected,
- hints->AllowLoad(test.url, ResourceLoadPriority::kHighest));
+ hints->AllowLoad(ResourceType::kCSSStyleSheet, test.url,
+ ResourceLoadPriority::kHighest));
+ EXPECT_EQ(test.allow_load_expected,
+ hints->AllowLoad(ResourceType::kScript, test.url,
+ ResourceLoadPriority::kHighest));
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceLoadingBlocked",
- !test.allow_load_expected, 1);
+ !test.allow_load_expected, 2);
if (!test.allow_load_expected) {
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority."
"Blocked",
- ResourceLoadPriority::kHighest, 1);
+ ResourceLoadPriority::kHighest, 2);
histogram_tester.ExpectTotalCount(
"ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority."
"Allowed",
@@ -94,7 +106,7 @@ TEST_F(PreviewsResourceLoadingHintsTest, OnePattern) {
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority."
"Allowed",
- ResourceLoadPriority::kHighest, 1);
+ ResourceLoadPriority::kHighest, 2);
}
}
}
@@ -128,7 +140,8 @@ TEST_F(PreviewsResourceLoadingHintsTest, MultiplePatterns) {
for (const auto& test : tests) {
EXPECT_EQ(test.allow_load_expected,
- hints->AllowLoad(test.url, ResourceLoadPriority::kHighest));
+ hints->AllowLoad(ResourceType::kScript, test.url,
+ ResourceLoadPriority::kHighest));
}
}
@@ -158,7 +171,8 @@ TEST_F(PreviewsResourceLoadingHintsTest, OnePatternHistogramChecker) {
for (const auto& test : tests) {
base::HistogramTester histogram_tester;
EXPECT_EQ(test.allow_load_expected,
- hints->AllowLoad(test.url, test.resource_load_priority));
+ hints->AllowLoad(ResourceType::kScript, test.url,
+ test.resource_load_priority));
histogram_tester.ExpectUniqueSample(
"ResourceLoadingHints.ResourceLoadingBlocked",
!test.allow_load_expected, 1);
@@ -235,7 +249,7 @@ TEST_F(PreviewsResourceLoadingHintsTest, MultiplePatternUKMChecker) {
};
for (const auto& resource_to_load : resources_to_load) {
- hints->AllowLoad(resource_to_load.url,
+ hints->AllowLoad(ResourceType::kScript, resource_to_load.url,
resource_to_load.resource_load_priority);
}
@@ -262,6 +276,122 @@ TEST_F(PreviewsResourceLoadingHintsTest, MultiplePatternUKMChecker) {
entry, UkmEntry::kblocked_very_high_priorityName, 1);
}
+// Test class that overrides field trial so that resource blocking hints apply
+// to images as well.
+class PreviewsResourceLoadingHintsTestBlockImages
+ : public PreviewsResourceLoadingHintsTest {
+ public:
+ PreviewsResourceLoadingHintsTestBlockImages() = default;
+
+ void SetUp() override {
+ std::map<std::string, std::string> feature_parameters;
+ feature_parameters["block_resource_type_1"] = "true";
+
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ blink::features::kPreviewsResourceLoadingHintsSpecificResourceTypes,
+ feature_parameters);
+ }
+
+ protected:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(PreviewsResourceLoadingHintsTestBlockImages,
+ OnePatternWithResourceSubtype) {
+ std::vector<WTF::String> subresources_to_block;
+ subresources_to_block.push_back("foo.jpg");
+
+ PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
+ dummy_page_holder_->GetDocument(), ukm::UkmRecorder::GetNewSourceID(),
+ subresources_to_block);
+
+ const struct {
+ KURL url;
+ bool allow_load_expected;
+ } tests[] = {
+ {KURL("https://www.example.com/"), true},
+ {KURL("https://www.example.com/foo.js"), true},
+ {KURL("https://www.example.com/foo.jpg"), false},
+ {KURL("https://www.example.com/pages/foo.jpg"), false},
+ {KURL("https://www.example.com/foobar.jpg"), true},
+ {KURL("https://www.example.com/barfoo.jpg"), false},
+ {KURL("http://www.example.com/foo.jpg"), false},
+ {KURL("http://www.example.com/foo.jpg?q=alpha"), false},
+ {KURL("http://www.example.com/bar.jpg?q=foo.jpg"), true},
+ {KURL("http://www.example.com/bar.jpg?q=foo.jpg#foo.jpg"), true},
+ };
+
+ for (const auto& test : tests) {
+ // By default, resource blocking hints do not apply to fonts.
+ EXPECT_TRUE(hints->AllowLoad(ResourceType::kFont, test.url,
+ ResourceLoadPriority::kHighest));
+ // Feature override should cause resource blocking hints to apply to images.
+ EXPECT_EQ(test.allow_load_expected,
+ hints->AllowLoad(ResourceType::kImage, test.url,
+ ResourceLoadPriority::kHighest));
+ EXPECT_EQ(test.allow_load_expected,
+ hints->AllowLoad(ResourceType::kScript, test.url,
+ ResourceLoadPriority::kHighest));
+ }
+}
+
+// Test class that overrides field trial so that resource blocking hints do not
+// apply to CSS.
+class PreviewsResourceLoadingHintsTestAllowCSS
+ : public PreviewsResourceLoadingHintsTestBlockImages {
+ public:
+ PreviewsResourceLoadingHintsTestAllowCSS() = default;
+
+ void SetUp() override {
+ std::map<std::string, std::string> feature_parameters;
+ feature_parameters["block_resource_type_2"] = "false";
+
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ blink::features::kPreviewsResourceLoadingHintsSpecificResourceTypes,
+ feature_parameters);
+ }
+};
+
+TEST_F(PreviewsResourceLoadingHintsTestAllowCSS,
+ OnePatternWithResourceSubtype) {
+ std::vector<WTF::String> subresources_to_block;
+ subresources_to_block.push_back("foo.jpg");
+
+ PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create(
+ dummy_page_holder_->GetDocument(), ukm::UkmRecorder::GetNewSourceID(),
+ subresources_to_block);
+
+ const struct {
+ KURL url;
+ bool allow_load_expected;
+ } tests[] = {
+ {KURL("https://www.example.com/"), true},
+ {KURL("https://www.example.com/foo.js"), true},
+ {KURL("https://www.example.com/foo.jpg"), false},
+ {KURL("https://www.example.com/pages/foo.jpg"), false},
+ {KURL("https://www.example.com/foobar.jpg"), true},
+ {KURL("https://www.example.com/barfoo.jpg"), false},
+ {KURL("http://www.example.com/foo.jpg"), false},
+ {KURL("http://www.example.com/foo.jpg?q=alpha"), false},
+ {KURL("http://www.example.com/bar.jpg?q=foo.jpg"), true},
+ {KURL("http://www.example.com/bar.jpg?q=foo.jpg#foo.jpg"), true},
+ };
+
+ for (const auto& test : tests) {
+ // Feature override should cause resource blocking hints to apply to only
+ // scripts.
+ EXPECT_TRUE(hints->AllowLoad(ResourceType::kFont, test.url,
+ ResourceLoadPriority::kHighest));
+ EXPECT_TRUE(hints->AllowLoad(ResourceType::kImage, test.url,
+ ResourceLoadPriority::kHighest));
+ EXPECT_TRUE(hints->AllowLoad(ResourceType::kCSSStyleSheet, test.url,
+ ResourceLoadPriority::kHighest));
+ EXPECT_EQ(test.allow_load_expected,
+ hints->AllowLoad(ResourceType::kScript, test.url,
+ ResourceLoadPriority::kHighest));
+ }
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/chrome_client.cc b/chromium/third_party/blink/renderer/core/page/chrome_client.cc
index fa1e5f91ffb..bfa0cd319f7 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.cc
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.cc
@@ -105,10 +105,14 @@ Page* ChromeClient::CreateWindow(
NavigationPolicy navigation_policy,
SandboxFlags sandbox_flags,
const SessionStorageNamespaceId& session_storage_namespace_id) {
+// Popups during page unloading is a feature being put behind a policy and
+// needing an easily-mergeable change. See https://crbug.com/936080 .
+#if 0
if (!CanOpenUIElementIfDuringPageDismissal(
frame->Tree().Top(), UIElementType::kPopup, g_empty_string)) {
return nullptr;
}
+#endif
return CreateWindowDelegate(frame, r, features, navigation_policy,
sandbox_flags, session_storage_namespace_id);
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
index ab766f46f64..ab2162bbe33 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
@@ -10,11 +10,15 @@
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/frame/find_in_page.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
#include "third_party/blink/renderer/core/frame/scroll_into_view_options.h"
#include "third_party/blink/renderer/core/frame/scroll_to_options.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -528,6 +532,83 @@ TEST_F(ScrollIntoViewTest, ApplyRootElementScrollBehaviorToViewport) {
ASSERT_EQ(Window().scrollY(), content->OffsetTop());
}
+// This test ensures the stop-at-layout viewport option works correctly when a
+// non-default root scroller is set as the layout viewport.
+TEST_F(ScrollIntoViewTest, StopAtLayoutViewportOption) {
+ v8::HandleScope HandleScope(v8::Isolate::GetCurrent());
+ WebView().MainFrameWidget()->Resize(WebSize(800, 600));
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ body,html {
+ margin: 0;
+ width: 100%;
+ height: 100%;
+ }
+ #root {
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+ }
+ #inner {
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+ margin-top: 1000px;
+ }
+ #target {
+ margin-top: 1000px;
+ margin-bottom: 1000px;
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id='root'>
+ <div id='inner'>
+ <div id='target'></div>
+ <div>
+ </div>
+ )HTML");
+
+ Compositor().BeginFrame();
+
+ Element* root = GetDocument().getElementById("root");
+ Element* inner = GetDocument().getElementById("inner");
+
+ // Make sure the root scroller is set since that's what we're trying to test
+ // here.
+ {
+ TopDocumentRootScrollerController& rs_controller =
+ GetDocument().GetPage()->GlobalRootScrollerController();
+ ASSERT_EQ(root, rs_controller.GlobalRootScroller());
+ }
+
+ // Use ScrollRectToVisible on the #target element, specifying
+ // stop_at_main_frame_layout_viewport.
+ LayoutObject* target =
+ GetDocument().getElementById("target")->GetLayoutObject();
+ WebScrollIntoViewParams params(
+ ScrollAlignment::kAlignLeftAlways, ScrollAlignment::kAlignTopAlways,
+ kProgrammaticScroll, false, kScrollBehaviorInstant);
+ params.stop_at_main_frame_layout_viewport = true;
+ target->ScrollRectToVisible(LayoutRect(target->AbsoluteBoundingBoxRect()),
+ params);
+
+ ScrollableArea* root_scroller =
+ ToLayoutBox(root->GetLayoutObject())->GetScrollableArea();
+ ScrollableArea* inner_scroller =
+ ToLayoutBox(inner->GetLayoutObject())->GetScrollableArea();
+
+ // Only the inner scroller should have scrolled. The root_scroller shouldn't
+ // scroll because it is the layout viewport.
+ ASSERT_EQ(root_scroller,
+ &GetDocument().View()->GetRootFrameViewport()->LayoutViewport());
+ EXPECT_EQ(ScrollOffset(), root_scroller->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 1000), inner_scroller->GetScrollOffset());
+}
+
// This test passes if it doesn't crash/hit an ASAN check.
TEST_F(ScrollIntoViewTest, RemoveSequencedScrollableArea) {
v8::HandleScope HandleScope(v8::Isolate::GetCurrent());
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
index fcbbf061270..6f39524b7fe 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy.h
@@ -56,7 +56,7 @@ class CORE_EXPORT TrustedTypePolicy final : public ScriptWrappable {
private:
String name_;
- Member<TrustedTypePolicyOptions> policy_options_;
+ TraceWrapperMember<TrustedTypePolicyOptions> policy_options_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
index c103e7d062a..b36807b368e 100644
--- a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h
@@ -57,7 +57,7 @@ class CORE_EXPORT TrustedTypePolicyFactory final : public ScriptWrappable,
const WrapperTypeInfo* GetWrapperTypeInfoFromScriptValue(ScriptState*,
const ScriptValue&);
- HeapHashMap<String, Member<TrustedTypePolicy>> policy_map_;
+ HeapHashMap<String, TraceWrapperMember<TrustedTypePolicy>> policy_map_;
bool hadAssignmentError = false;
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js b/chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js
index 010108b9903..31901d0dd9d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js
@@ -1373,7 +1373,7 @@
*/
function getRemoteMajorVersion() {
try {
- const remoteVersion = new URLSearchParams(window.location.href).get('remoteVersion');
+ const remoteVersion = new URLSearchParams(window.location.search).get('remoteVersion');
if (!remoteVersion)
return null;
const majorVersion = parseInt(remoteVersion.split('.')[0], 10);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js
index c62906af703..ee9fd7c7181 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/DOMLinkifier.js
@@ -89,7 +89,7 @@ Elements.DOMLinkifier.linkifyDeferredNodeReference = function(deferredNode) {
const root = createElement('div');
const shadowRoot = UI.createShadowRootWithCoreStyles(root, 'elements/domLinkifier.css');
const link = shadowRoot.createChild('div', 'node-link');
- link.createChild('content');
+ link.createChild('slot');
link.addEventListener('click', deferredNode.resolve.bind(deferredNode, onDeferredNodeResolved), false);
link.addEventListener('mousedown', e => e.consume(), false);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
index 215f897f63d..ac9405c1b4a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
@@ -563,7 +563,6 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
return;
element.select();
- event.consume(true);
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js
index e2b85ba9af8..b0fa4033d67 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/RequestHTMLView.js
@@ -38,7 +38,7 @@ Network.RequestHTMLView = class extends UI.VBox {
constructor(dataURL) {
super(true);
this.registerRequiredCSS('network/requestHTMLView.css');
- this._dataURL = dataURL;
+ this._dataURL = encodeURI(dataURL).replace(/#/g, '%23');
this.contentElement.classList.add('html', 'request-view');
}
@@ -63,7 +63,7 @@ Network.RequestHTMLView = class extends UI.VBox {
const iframe = createElement('iframe');
iframe.className = 'html-preview-frame';
iframe.setAttribute('sandbox', ''); // Forbid to run JavaScript and set unique origin.
- iframe.setAttribute('src', encodeURI(this._dataURL));
+ iframe.setAttribute('src', this._dataURL);
iframe.setAttribute('tabIndex', -1);
this.contentElement.appendChild(iframe);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js
index 9aeaf150395..f0ecc9cbfa6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js
@@ -415,7 +415,7 @@ UI.TextPrompt = class extends Common.Object {
const expressionRange = wordQueryRange.cloneRange();
expressionRange.collapse(true);
- expressionRange.setStartBefore(this._proxyElement);
+ expressionRange.setStartBefore(this._element);
const completionRequestId = ++this._completionRequestId;
const completions = await this._loadCompletions(expressionRange.toString(), wordQueryRange.toString(), !!force);
this._completionsReady(completionRequestId, selection, wordQueryRange, !!force, completions);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/View.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/View.js
index 0cf76eef38e..ca8234177dd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/View.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/View.js
@@ -632,8 +632,7 @@ UI.ViewManager._TabbedLocation = class extends UI.ViewManager._Location {
this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabClosed, this._tabClosed, this);
this._closeableTabSetting = Common.settings.createSetting(location + '-closeableTabs', {});
this._tabOrderSetting = Common.settings.createSetting(location + '-tabOrder', {});
- this._tabbedPane.addEventListener(
- UI.TabbedPane.Events.TabOrderChanged, event => this._persistTabOrder(event.data['tabId']));
+ this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabOrderChanged, this._persistTabOrder, this);
if (restoreSelection)
this._lastSelectedTabSetting = Common.settings.createSetting(location + '-selectedTab', '');
this._defaultTab = defaultTab;
@@ -766,7 +765,7 @@ UI.ViewManager._TabbedLocation = class extends UI.ViewManager._Location {
this._closeableTabSetting.set(tabs);
}
}
- this._persistTabOrder(view.viewId());
+ this._persistTabOrder();
}
/**
@@ -822,20 +821,23 @@ UI.ViewManager._TabbedLocation = class extends UI.ViewManager._Location {
this._views.get(id).disposeView();
}
- /**
- * @param {string} tabId
- */
- _persistTabOrder(tabId) {
+ _persistTabOrder() {
const tabIds = this._tabbedPane.tabIds();
- const previousId = tabIds[tabIds.indexOf(tabId) - 1];
- const orders = this._tabOrderSetting.get();
- orders[tabId] = previousId && orders[previousId] ? orders[previousId] + 1 : 0;
- const keys = Object.keys(orders);
- keys.sort((a, b) => orders[a] - orders[b]);
-
const tabOrders = {};
- for (let i = 0; i < keys.length; i++)
- tabOrders[keys[i]] = (i + 1) * UI.ViewManager._TabbedLocation.orderStep;
+ for (let i = 0; i < tabIds.length; i++)
+ tabOrders[tabIds[i]] = (i + 1) * UI.ViewManager._TabbedLocation.orderStep;
+
+ const oldTabOrder = this._tabOrderSetting.get();
+ const oldTabArray = Object.keys(oldTabOrder);
+ oldTabArray.sort((a, b) => oldTabOrder[a] - oldTabOrder[b]);
+ let lastOrder = 0;
+ for (const key of oldTabArray) {
+ if (key in tabOrders) {
+ lastOrder = tabOrders[key];
+ continue;
+ }
+ tabOrders[key] = ++lastOrder;
+ }
this._tabOrderSetting.set(tabOrders);
}
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.idl b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.idl
index 0d89b5bf68c..47ac42c3247 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.idl
@@ -9,7 +9,7 @@
ConstructorCallWith=ExecutionContext,
Exposed=(Window,Worker),
MeasureAs=ShapeDetection_BarcodeDetectorConstructor,
- OriginTrialEnabled=ShapeDetection
+ RuntimeEnabled=ShapeDetection
] interface BarcodeDetector {
[CallWith=ScriptState, MeasureAs=ShapeDetectionAPI] Promise<sequence<DetectedBarcode>> detect(ImageBitmapSource image);
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl b/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl
index e9ac10817c8..12682c87744 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl
@@ -7,7 +7,7 @@
[
Constructor,
Serializable,
- OriginTrialEnabled=ShapeDetection
+ RuntimeEnabled=ShapeDetection
] interface DetectedBarcode {
// TODO(mcasas): Implement missing fields. https://crbug.com/646083
[SameObject] readonly attribute DOMString rawValue;
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl b/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl
index d7f7985dd85..c4b2559051b 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl
@@ -7,7 +7,7 @@
[
Constructor,
Serializable,
- OriginTrialEnabled=ShapeDetection
+ RuntimeEnabled=ShapeDetection
] interface DetectedFace {
// TODO(xianglu): Implement any other fields. https://crbug.com/646083
[SameObject] readonly attribute DOMRectReadOnly boundingBox;
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl b/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl
index b549c86666d..dcbc270ad3d 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl
@@ -7,7 +7,7 @@
[
Constructor,
Serializable,
- OriginTrialEnabled=ShapeDetection
+ RuntimeEnabled=ShapeDetection
] interface DetectedText {
[SameObject] readonly attribute DOMString rawValue;
[SameObject] readonly attribute DOMRectReadOnly boundingBox;
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.idl b/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.idl
index 32218dff569..7b943fdb492 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.idl
@@ -9,7 +9,7 @@
ConstructorCallWith=ExecutionContext,
Exposed=(Window,Worker),
MeasureAs=ShapeDetection_FaceDetectorConstructor,
- OriginTrialEnabled=ShapeDetection
+ RuntimeEnabled=ShapeDetection
] interface FaceDetector {
[CallWith=ScriptState, MeasureAs=ShapeDetectionAPI] Promise<sequence<DetectedFace>> detect(ImageBitmapSource image);
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.idl b/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.idl
index 0c7000514e6..e24bf9acd1a 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.idl
@@ -9,7 +9,7 @@
ConstructorCallWith=ExecutionContext,
Exposed=(Window,Worker),
MeasureAs=ShapeDetection_TextDetectorConstructor,
- OriginTrialEnabled=ShapeDetection
+ RuntimeEnabled=ShapeDetection
] interface TextDetector {
[CallWith=ScriptState, MeasureAs=ShapeDetectionAPI] Promise<sequence<DetectedText>> detect(ImageBitmapSource image);
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc b/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc
index 73a48b721be..8e0ab9f3e51 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc
@@ -116,6 +116,12 @@ void SkFontGetBoundsForGlyph(const SkFont& font, Glyph glyph, SkRect* bounds) {
SkPath path;
font.getPath(glyph, &path);
*bounds = path.getBounds();
+ // For Apple Color Emoji path bounds are returning empty rectangles, see
+ // https://bugs.chromium.org/p/skia/issues/detail?id=8779
+ // OpenTypeVerticalData::GetVerticalTranslationsForGlyphs needs a non-empty
+ // rectangle for vertical origin computation, hence fall back to bounds here.
+ if (UNLIKELY(bounds->isEmpty()))
+ font.getWidths(&glyph, 1, nullptr, bounds);
#else
font.getWidths(&glyph, 1, nullptr, bounds);
#endif
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc b/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
index 055f2dc71ba..e0934160dac 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
@@ -383,11 +383,13 @@ bool HeapCompact::ShouldCompact(ThreadHeap* heap,
if (reason != BlinkGC::GCReason::kIdleGC &&
reason != BlinkGC::GCReason::kPreciseGC &&
- reason != BlinkGC::GCReason::kIncrementalIdleGC &&
- reason != BlinkGC::GCReason::kIncrementalV8FollowupGC &&
reason != BlinkGC::GCReason::kForcedGC)
return false;
+ // TODO(keishi): crbug.com/918064 Heap compaction for incremental marking
+ // needs to be disabled until this crash is fixed.
+ CHECK_NE(marking_type, BlinkGC::kIncrementalMarking);
+
// Compaction enable rules:
// - It's been a while since the last time.
// - "Considerable" amount of heap memory is bound up in freelist
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
index ac52ace54cd..5a19bdf3329 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -84,7 +84,8 @@ enum class ResourceType : uint8_t {
kAudio,
kVideo,
kManifest,
- kMock // Only for testing
+ kMock, // Only for testing
+ kLast = kMock
};
// A resource that is held in the cache. Classes who want to use this object
diff --git a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 8f577c5c879..9771c74c96f 100644
--- a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1230,7 +1230,6 @@
},
{
name: "ShapeDetection",
- origin_trial_feature_name: "ShapeDetection",
status: "experimental",
},
{
diff --git a/chromium/third_party/brotli/fuzz/DEPS b/chromium/third_party/brotli/fuzz/DEPS
deleted file mode 100644
index 2e39551801c..00000000000
--- a/chromium/third_party/brotli/fuzz/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+third_party/brotli/dec",
-]
diff --git a/chromium/third_party/brotli/fuzz/decode_fuzzer.cc b/chromium/third_party/brotli/fuzz/decode_fuzzer.cc
deleted file mode 100644
index 60c6f8e4d4d..00000000000
--- a/chromium/third_party/brotli/fuzz/decode_fuzzer.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <brotli/decode.h>
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- size_t addend = 0;
- if (size > 0)
- addend = data[size - 1] & 7;
- const uint8_t* next_in = data;
-
- const int kBufferSize = 1024;
- uint8_t* buffer = new uint8_t[kBufferSize];
- /* The biggest "magic number" in brotli is 16MiB - 16, so no need to check
- the cases with much longer output. */
- const size_t total_out_limit = (addend == 0) ? (1 << 26) : (1 << 24);
- size_t total_out = 0;
-
- BrotliDecoderState* state = BrotliDecoderCreateInstance(0, 0, 0);
-
- if (addend == 0)
- addend = size;
- /* Test both fast (addend == size) and slow (addend <= 7) decoding paths. */
- for (size_t i = 0; i < size;) {
- size_t next_i = i + addend;
- if (next_i > size)
- next_i = size;
- size_t avail_in = next_i - i;
- i = next_i;
- BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
- while (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
- size_t avail_out = kBufferSize;
- uint8_t* next_out = buffer;
- result = BrotliDecoderDecompressStream(
- state, &avail_in, &next_in, &avail_out, &next_out, &total_out);
- if (total_out > total_out_limit)
- break;
- }
- if (total_out > total_out_limit)
- break;
- if (result != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT)
- break;
- }
-
- BrotliDecoderDestroyInstance(state);
- delete[] buffer;
- return 0;
-}
diff --git a/chromium/third_party/catapult/catapult_build/PRESUBMIT.py b/chromium/third_party/catapult/catapult_build/PRESUBMIT.py
new file mode 100644
index 00000000000..1a8eb2cdead
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/PRESUBMIT.py
@@ -0,0 +1,40 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return _CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return _CommonChecks(input_api, output_api)
+
+
+def _CommonChecks(input_api, output_api):
+ results = []
+ results += input_api.RunTests(input_api.canned_checks.GetPylint(
+ input_api, output_api, extra_paths_list=_GetPathsToPrepend(input_api),
+ pylintrc='../pylintrc'))
+ return results
+
+
+def _GetPathsToPrepend(input_api):
+ project_dir = input_api.PresubmitLocalPath()
+ catapult_dir = input_api.os_path.join(project_dir, '..')
+ return [
+ project_dir,
+
+ input_api.os_path.join(catapult_dir, 'common', 'eslint'),
+ input_api.os_path.join(catapult_dir, 'common', 'py_utils'),
+ input_api.os_path.join(catapult_dir, 'common', 'py_vulcanize'),
+ input_api.os_path.join(catapult_dir, 'dashboard'),
+ input_api.os_path.join(catapult_dir, 'netlog_viewer'),
+ input_api.os_path.join(catapult_dir, 'third_party', 'Paste'),
+ input_api.os_path.join(catapult_dir, 'third_party', 'beautifulsoup4'),
+ input_api.os_path.join(catapult_dir, 'third_party', 'mock'),
+ input_api.os_path.join(catapult_dir, 'third_party', 'typ'),
+ input_api.os_path.join(catapult_dir, 'third_party', 'webapp2'),
+ input_api.os_path.join(catapult_dir, 'third_party', 'WebOb'),
+ input_api.os_path.join(catapult_dir, 'tracing'),
+ ]
diff --git a/chromium/third_party/catapult/catapult_build/__init__.py b/chromium/third_party/catapult/catapult_build/__init__.py
new file mode 100644
index 00000000000..15b3468775a
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/__init__.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+def _UpdateSysPathIfNeeded():
+ catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ catapult_third_party_path = os.path.abspath(os.path.join(
+ catapult_path, 'third_party'))
+ _AddToPathIfNeeded(os.path.join(catapult_path, 'common', 'eslint'))
+ _AddToPathIfNeeded(os.path.join(catapult_path, 'common', 'py_utils'))
+ _AddToPathIfNeeded(os.path.join(catapult_path, 'common', 'py_vulcanize'))
+ _AddToPathIfNeeded(os.path.join(catapult_third_party_path, 'beautifulsoup4'))
+ _AddToPathIfNeeded(os.path.join(catapult_third_party_path, 'html5lib-python'))
+ _AddToPathIfNeeded(os.path.join(catapult_third_party_path, 'six'))
+ _AddToPathIfNeeded(os.path.join(catapult_third_party_path, 'Paste'))
+ _AddToPathIfNeeded(os.path.join(catapult_third_party_path, 'webapp2'))
+ _AddToPathIfNeeded(os.path.join(catapult_third_party_path, 'WebOb'))
+ _AddToPathIfNeeded(os.path.join(catapult_path, 'tracing'))
+ _AddToPathIfNeeded(os.path.join(catapult_path, 'perf_insights'))
+ _AddToPathIfNeeded(os.path.join(catapult_path, 'dashboard'))
+ _AddToPathIfNeeded(os.path.join(catapult_path, 'netlog_viewer'))
+
+
+_UpdateSysPathIfNeeded()
diff --git a/chromium/third_party/catapult/catapult_build/appengine_deploy.py b/chromium/third_party/catapult/catapult_build/appengine_deploy.py
new file mode 100644
index 00000000000..c776de083f7
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/appengine_deploy.py
@@ -0,0 +1,69 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(qyearsley): Add a step to vulcanize each template HTML file.
+# TODO(qyearsley): Add a step to put static files in a versioned
+# directory and modify app.yaml and request_handler as needed.
+
+import os
+import subprocess
+import sys
+
+from catapult_build import temp_deployment_dir
+
+
+def Deploy(paths, args, version=None):
+ """Deploys a new version of an App Engine app from a temporary directory.
+
+ Args:
+ paths: List of paths to files and directories that should be linked
+ (or copied) in the deployment directory.
+ args: Arguments passed to "gcloud app deploy".
+ """
+ if version is None:
+ version = _VersionName()
+ with temp_deployment_dir.TempDeploymentDir(
+ paths, use_symlinks=False) as temp_dir:
+ print 'Deploying from "%s".' % temp_dir
+
+ # google-cloud-sdk/bin/gcloud is a shell script, which we can't subprocess
+ # on Windows with shell=False. So, execute the Python script directly.
+ if os.name == 'nt':
+ script_path = _FindScriptInPath('gcloud.cmd')
+ else:
+ script_path = _FindScriptInPath('gcloud')
+ if not script_path:
+ print 'This script requires the Google Cloud SDK to be in PATH.'
+ print 'Install at https://cloud.google.com/sdk and then run'
+ print '`gcloud components install app-engine-python`'
+ sys.exit(1)
+
+ subprocess.call([script_path, 'app', 'deploy', '--no-promote', '--quiet',
+ '--version', version] + args,
+ cwd=temp_dir)
+
+
+def _FindScriptInPath(script_name):
+ for path in os.environ['PATH'].split(os.pathsep):
+ script_path = os.path.join(path, script_name)
+ if os.path.exists(script_path):
+ return script_path
+
+ return None
+
+
+def _VersionName():
+ is_synced = not _Run(
+ ['git', 'diff', 'origin/master', '--no-ext-diff']).strip()
+ deployment_type = 'clean' if is_synced else 'dev'
+ email = _Run(['git', 'config', '--get', 'user.email'])
+ username = email[0:email.find('@')]
+ commit_hash = _Run(['git', 'rev-parse', '--short=8', 'HEAD']).strip()
+ return '%s-%s-%s' % (deployment_type, username, commit_hash)
+
+
+def _Run(command):
+ proc = subprocess.Popen(command, stdout=subprocess.PIPE)
+ output, _ = proc.communicate()
+ return output
diff --git a/chromium/third_party/catapult/catapult_build/appengine_dev_server.py b/chromium/third_party/catapult/catapult_build/appengine_dev_server.py
new file mode 100644
index 00000000000..e79c559b1c2
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/appengine_dev_server.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import sys
+
+from catapult_build import temp_deployment_dir
+
+
+def DevAppserver(paths, args):
+ """Starts a dev server for an App Engine app.
+
+ Args:
+ paths: List of paths to files and directories that should be linked
+ (or copied) in the deployment directory.
+ args: List of additional arguments to pass to the dev server.
+ """
+ with temp_deployment_dir.TempDeploymentDir(paths) as temp_dir:
+ print 'Running dev server on "%s".' % temp_dir
+
+ script_path = _FindScriptInPath('dev_appserver.py')
+ if not script_path:
+ print 'This script requires the App Engine SDK to be in PATH.'
+ sys.exit(1)
+
+ subprocess.call([sys.executable, script_path] + args + [temp_dir])
+
+
+def _FindScriptInPath(script_name):
+ for path in os.environ['PATH'].split(os.pathsep):
+ script_path = os.path.join(path, script_name)
+ if os.path.exists(script_path):
+ return script_path
+
+ return None
diff --git a/chromium/third_party/catapult/catapult_build/bin/run_py_tests b/chromium/third_party/catapult/catapult_build/bin/run_py_tests
new file mode 100755
index 00000000000..baed4330134
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/bin/run_py_tests
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs all Python unit tests in catapult_build/."""
+
+import os
+import sys
+
+_CATAPULT = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir))
+
+
+if __name__ == '__main__':
+ sys.path.append(_CATAPULT)
+
+ from hooks import install
+ if '--no-install-hooks' in sys.argv:
+ sys.argv.remove('--no-install-hooks')
+ else:
+ install.InstallHooks()
+
+ from catapult_build import run_with_typ
+ sys.exit(run_with_typ.Run(
+ os.path.join(_CATAPULT, 'catapult_build'),
+ path=[_CATAPULT]))
diff --git a/chromium/third_party/catapult/catapult_build/bin_checks.py b/chromium/third_party/catapult/catapult_build/bin_checks.py
new file mode 100644
index 00000000000..b2fd7c091c5
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/bin_checks.py
@@ -0,0 +1,29 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import re
+
+
+def RunChecks(input_api, output_api, excluded_paths=()):
+ excluded_paths = list(excluded_paths) + [r'.*PRESUBMIT\.py']
+ root = input_api.change.RepositoryRoot()
+
+ def ShouldCheck(filepath):
+ if os.path.split(os.path.dirname(filepath))[1] != 'bin':
+ return False
+ if any(re.match(pattern, filepath) for pattern in excluded_paths):
+ return False
+ return True
+
+ results = []
+
+ for f in input_api.AffectedFiles():
+ filepath = os.path.join(root, f.LocalPath())
+ if (ShouldCheck(filepath) and os.path.exists(filepath)
+ and not os.access(filepath, os.X_OK)):
+ results += [output_api.PresubmitError(
+ '%r must be executable.' % filepath)]
+
+ return results
diff --git a/chromium/third_party/catapult/catapult_build/build_steps.py b/chromium/third_party/catapult/catapult_build/build_steps.py
new file mode 100644
index 00000000000..339e2174252
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/build_steps.py
@@ -0,0 +1,289 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import json
+import os
+import sys
+
+# This is the list of tests to run. It is a dictionary with the following
+# fields:
+#
+# name (required): The name of the step, to show on the buildbot status page.
+# path (required): The path to the executable which runs the tests.
+# additional_args (optional): An array of optional arguments.
+# uses_app_engine_sdk (optional): True if app engine SDK must be in PYTHONPATH.
+# uses_sandbox_env (optional): True if CHROME_DEVEL_SANDBOX must be in
+# environment.
+# disabled (optional): List of platforms the test is disabled on. May contain
+# 'win', 'mac', 'linux', or 'android'.
+# outputs_presentation_json (optional): If True, pass in --presentation-json
+# argument to the test executable to allow it to update the buildbot status
+# page. More details here:
+# github.com/luci/recipes-py/blob/master/recipe_modules/generator_script/api.py
+_CATAPULT_TESTS = [
+ {
+ 'name': 'Build Python Tests',
+ 'path': 'catapult_build/bin/run_py_tests',
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Common Tests',
+ 'path': 'common/bin/run_tests',
+ },
+ {
+ 'name': 'Dashboard Dev Server Tests Canary',
+ 'path': 'dashboard/bin/run_dev_server_tests',
+ 'additional_args': [
+ '--no-install-hooks',
+ '--no-use-local-chrome',
+ '--channel=canary'
+ ],
+ 'outputs_presentation_json': True,
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Dashboard Dev Server Tests Stable',
+ 'path': 'dashboard/bin/run_dev_server_tests',
+ 'additional_args': [
+ '--no-install-hooks',
+ '--no-use-local-chrome',
+ '--channel=stable',
+ ],
+ 'outputs_presentation_json': True,
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Dashboard Python Tests',
+ 'path': 'dashboard/bin/run_py_tests',
+ 'additional_args': ['--no-install-hooks'],
+ 'uses_app_engine_sdk': True,
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Dashboard WCT Tests',
+ 'path': 'dashboard/bin/run_wct_tests',
+ 'disabled': ['android', 'win', 'mac'],
+ },
+ {
+ 'name': 'Dependency Manager Tests',
+ 'path': 'dependency_manager/bin/run_tests',
+ },
+ {
+ 'name': 'Devil Device Tests',
+ 'path': 'devil/bin/run_py_devicetests',
+ 'disabled': ['win', 'mac', 'linux']
+ },
+ {
+ 'name': 'Devil Python Tests',
+ 'path': 'devil/bin/run_py_tests',
+ 'disabled': ['mac', 'win'],
+ },
+ {
+ 'name': 'eslint Tests',
+ 'path': 'common/eslint/bin/run_tests',
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Native Heap Symbolizer Tests',
+ 'path': 'tracing/bin/run_symbolizer_tests',
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Py-vulcanize Tests',
+ 'path': 'common/py_vulcanize/bin/run_py_tests',
+ 'additional_args': ['--no-install-hooks'],
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Systrace Tests',
+ 'path': 'systrace/bin/run_tests',
+ },
+ {
+ 'name': 'Snap-it Tests',
+ 'path': 'telemetry/bin/run_snap_it_unittest',
+ 'additional_args': [
+ '--browser=reference',
+ ],
+ 'uses_sandbox_env': True,
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Soundwave Tests',
+ 'path': 'experimental/soundwave/bin/run_tests',
+ },
+ {
+ 'name': 'Telemetry Tests with Stable Browser (Desktop)',
+ 'path': 'catapult_build/fetch_telemetry_deps_and_run_tests',
+ 'additional_args': [
+ '--browser=reference',
+ '--start-xvfb'
+ ],
+ 'uses_sandbox_env': True,
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Telemetry Tests with Stable Browser (Android)',
+ 'path': 'catapult_build/fetch_telemetry_deps_and_run_tests',
+ 'additional_args': [
+ '--browser=reference',
+ '--device=android',
+ '--jobs=1'
+ ],
+ 'uses_sandbox_env': True,
+ 'disabled': ['win', 'mac', 'linux']
+ },
+ {
+ 'name': 'Telemetry Integration Tests with Stable Browser',
+ 'path': 'telemetry/bin/run_browser_tests',
+ 'additional_args': [
+ 'SimpleBrowserTest',
+ '--browser=reference',
+ ],
+ 'uses_sandbox_env': True,
+ 'disabled': ['android', 'linux'], # TODO(nedn): enable this on linux
+ },
+ {
+ 'name': 'Tracing Dev Server Tests Canary',
+ 'path': 'tracing/bin/run_dev_server_tests',
+ 'additional_args': [
+ '--no-install-hooks',
+ '--no-use-local-chrome',
+ '--channel=canary'
+ ],
+ 'outputs_presentation_json': True,
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Tracing Dev Server Tests Stable',
+ 'path': 'tracing/bin/run_dev_server_tests',
+ 'additional_args': [
+ '--no-install-hooks',
+ '--no-use-local-chrome',
+ '--channel=stable',
+ ],
+ 'outputs_presentation_json': True,
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Tracing D8 Tests',
+ 'path': 'tracing/bin/run_vinn_tests',
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Tracing Python Tests',
+ 'path': 'tracing/bin/run_py_tests',
+ 'additional_args': ['--no-install-hooks'],
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'Typ unittest',
+ 'path': 'third_party/typ/run',
+ 'additional_args': ['tests'],
+ 'disabled': [
+ 'android',
+ 'win'], # TODO(crbug.com/851498): enable typ unittests on Win
+ },
+ {
+ 'name': 'Vinn Tests',
+ 'path': 'third_party/vinn/bin/run_tests',
+ 'disabled': ['android'],
+ },
+ {
+ 'name': 'NetLog Viewer Dev Server Tests',
+ 'path': 'netlog_viewer/bin/run_dev_server_tests',
+ 'additional_args': [
+ '--no-install-hooks',
+ '--no-use-local-chrome',
+ ],
+ 'disabled': ['android', 'win', 'mac', 'linux'],
+ },
+]
+
+_STALE_FILE_TYPES = ['.pyc', '.pseudo_lock']
+
+
+def main(args=None):
+ """Send list of test to run to recipes generator_script.
+
+ See documentation at:
+ github.com/luci/recipes-py/blob/master/recipe_modules/generator_script/api.py
+ """
+ parser = argparse.ArgumentParser(description='Run catapult tests.')
+ parser.add_argument('--api-path-checkout', help='Path to catapult checkout')
+ parser.add_argument('--app-engine-sdk-pythonpath',
+ help='PYTHONPATH to include app engine SDK path')
+ parser.add_argument('--wct-path', help='Path to infra/testing/wct binary')
+ parser.add_argument('--platform',
+ help='Platform name (linux, mac, or win)')
+ parser.add_argument('--output-json', help='Output for buildbot status page')
+ args = parser.parse_args(args)
+
+ steps = [{
+ # Always remove stale files first. Not listed as a test above
+ # because it is a step and not a test, and must be first.
+ 'name': 'Remove Stale files',
+ 'cmd': ['python',
+ os.path.join(args.api_path_checkout,
+ 'catapult_build', 'remove_stale_files.py'),
+ args.api_path_checkout, ','.join(_STALE_FILE_TYPES)]
+ }]
+ if args.platform == 'android':
+ # On Android, we need to prepare the devices a bit before using them in
+ # tests. These steps are not listed as tests above because they aren't
+ # tests and because they must precede all tests.
+ steps.extend([
+ {
+ 'name': 'Android: Recover Devices',
+ 'cmd': ['python',
+ os.path.join(args.api_path_checkout, 'devil', 'devil',
+ 'android', 'tools', 'device_recovery.py')],
+ },
+ {
+ 'name': 'Android: Provision Devices',
+ 'cmd': ['python',
+ os.path.join(args.api_path_checkout, 'devil', 'devil',
+ 'android', 'tools', 'provision_devices.py')],
+ },
+ {
+ 'name': 'Android: Device Status',
+ 'cmd': ['python',
+ os.path.join(args.api_path_checkout, 'devil', 'devil',
+ 'android', 'tools', 'device_status.py')],
+ },
+ ])
+
+ for test in _CATAPULT_TESTS:
+ if args.platform in test.get('disabled', []):
+ continue
+ step = {
+ 'name': test['name'],
+ 'env': {}
+ }
+
+ # vpython doesn't integrate well with app engine SDK yet
+ if test.get('uses_app_engine_sdk'):
+ executable = 'python'
+ else:
+ executable = 'vpython.bat' if sys.platform == 'win32' else 'vpython'
+
+ step['cmd'] = [
+ executable, os.path.join(args.api_path_checkout, test['path'])]
+ if step['name'] == 'Systrace Tests':
+ step['cmd'] += ['--device=' + args.platform]
+ if test.get('additional_args'):
+ step['cmd'] += test['additional_args']
+ if test.get('uses_app_engine_sdk'):
+ step['env']['PYTHONPATH'] = args.app_engine_sdk_pythonpath
+ if test.get('uses_sandbox_env'):
+ step['env']['CHROME_DEVEL_SANDBOX'] = '/opt/chromium/chrome_sandbox'
+ if test.get('outputs_presentation_json'):
+ step['outputs_presentation_json'] = True
+ steps.append(step)
+ with open(args.output_json, 'w') as outfile:
+ json.dump(steps, outfile)
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/chromium/third_party/catapult/catapult_build/build_steps_unittest.py b/chromium/third_party/catapult/catapult_build/build_steps_unittest.py
new file mode 100644
index 00000000000..4d76e811997
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/build_steps_unittest.py
@@ -0,0 +1,44 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import unittest
+
+from catapult_build import build_steps
+
+
+class BuildStepsTest(unittest.TestCase):
+
+ def testCatapultTestList(self):
+ catapult_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+ for test in build_steps._CATAPULT_TESTS:
+ self.assertIn('name', test, msg=(
+ 'All tests in build_steps._CATAPULT_TESTS must have a name;'
+ ' error in:\n %s' % test))
+ self.assertIsInstance(test['name'], str, msg=(
+ 'Test name %s in build_steps._CATAPULT_TESTS must be a string.'
+ % test['name']))
+ self.assertIn('path', test, msg=(
+ 'All tests in build_steps._CATAPULT_TESTS must have a path '
+ 'relative to catapult/; error in:\n %s' % test))
+ abs_path = os.path.join(catapult_dir, test['path'])
+ self.assertTrue(os.path.exists(abs_path), msg=(
+ 'Bad path %s in build_steps._CATAPULT_TESTS; '
+ ' should be relative to catapult/' % test['path']))
+ if test.get('additional_args'):
+ self.assertIsInstance(test['additional_args'], list, msg=(
+ 'additional_args %s in build_steps._CATAPULT_TESTS %s not a list'
+ % (test['additional_args'], test['name'])
+ ))
+ if test.get('disabled'):
+ self.assertIsInstance(test['disabled'], list, msg=(
+ 'disabled %s in build_steps._CATAPULT_TESTS for %s not a list'
+ % (test['disabled'], test['name'])
+ ))
+ for platform in test['disabled']:
+ self.assertIn(platform, ['win', 'mac', 'linux', 'android'], msg=(
+ 'Bad platform %s in build_steps._CATAPULT_TESTS for %s;'
+ 'should be one of "linux", "win", "mac"' % (
+ platform, test['name'])
+ ))
diff --git a/chromium/third_party/catapult/catapult_build/dev_server.py b/chromium/third_party/catapult/catapult_build/dev_server.py
new file mode 100644
index 00000000000..d9145949eee
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/dev_server.py
@@ -0,0 +1,324 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import json
+import os
+import sys
+import urlparse
+
+from hooks import install
+
+from paste import fileapp
+from paste import httpserver
+
+import webapp2
+from webapp2 import Route, RedirectHandler
+
+from dashboard_build import dashboard_dev_server_config
+from tracing_build import tracing_dev_server_config
+from netlog_viewer_build import netlog_viewer_dev_server_config
+
+_MAIN_HTML = """<html><body>
+<h1>Run Unit Tests</h1>
+<ul>
+%s
+</ul>
+<h1>Quick links</h1>
+<ul>
+%s
+</ul>
+</body></html>
+"""
+
+_QUICK_LINKS = [
+ ('Trace File Viewer',
+ '/tracing_examples/trace_viewer.html'),
+ ('Metrics debugger',
+ '/tracing_examples/metrics_debugger.html'),
+]
+
+_LINK_ITEM = '<li><a href="%s">%s</a></li>'
+
+def _GetFilesIn(basedir):
+ data_files = []
+ for dirpath, dirnames, filenames in os.walk(basedir, followlinks=True):
+ new_dirnames = [d for d in dirnames if not d.startswith('.')]
+ del dirnames[:]
+ dirnames += new_dirnames
+
+ for f in filenames:
+ if f.startswith('.'):
+ continue
+ if f == 'README.md':
+ continue
+ full_f = os.path.join(dirpath, f)
+ rel_f = os.path.relpath(full_f, basedir)
+ data_files.append(rel_f)
+
+ data_files.sort()
+ return data_files
+
+
+def _RelPathToUnixPath(p):
+ return p.replace(os.sep, '/')
+
+
+class TestResultHandler(webapp2.RequestHandler):
+ def post(self, *args, **kwargs): # pylint: disable=unused-argument
+ msg = self.request.body
+ ostream = sys.stdout if 'PASSED' in msg else sys.stderr
+ ostream.write(msg + '\n')
+ return self.response.write('')
+
+
+class TestsCompletedHandler(webapp2.RequestHandler):
+ def post(self, *args, **kwargs): # pylint: disable=unused-argument
+ msg = self.request.body
+ sys.stdout.write(msg + '\n')
+ exit_code = 0 if 'ALL_PASSED' in msg else 1
+ if hasattr(self.app.server, 'please_exit'):
+ self.app.server.please_exit(exit_code)
+ return self.response.write('')
+
+
+class DirectoryListingHandler(webapp2.RequestHandler):
+ def get(self, *args, **kwargs): # pylint: disable=unused-argument
+ source_path = kwargs.pop('_source_path', None)
+ mapped_path = kwargs.pop('_mapped_path', None)
+ assert mapped_path.endswith('/')
+
+ data_files_relative_to_top = _GetFilesIn(source_path)
+ data_files = [mapped_path + x
+ for x in data_files_relative_to_top]
+
+ files_as_json = json.dumps(data_files)
+ self.response.content_type = 'application/json'
+ return self.response.write(files_as_json)
+
+
+class FileAppWithGZipHandling(fileapp.FileApp):
+ def guess_type(self):
+ content_type, content_encoding = \
+ super(FileAppWithGZipHandling, self).guess_type()
+ if not self.filename.endswith('.gz'):
+ return content_type, content_encoding
+ # By default, FileApp serves gzip files as their underlying type with
+ # Content-Encoding of gzip. That causes them to show up on the client
+ # decompressed. That ends up being surprising to our xhr.html system.
+ return None, None
+
+class SourcePathsHandler(webapp2.RequestHandler):
+ def get(self, *args, **kwargs): # pylint: disable=unused-argument
+ source_paths = kwargs.pop('_source_paths', [])
+
+ path = self.request.path
+ # This is how we do it. Its... strange, but its what we've done since
+ # the dawn of time. Aka 4 years ago, lol.
+ for mapped_path in source_paths:
+ rel = os.path.relpath(path, '/')
+ candidate = os.path.join(mapped_path, rel)
+ if os.path.exists(candidate):
+ app = FileAppWithGZipHandling(candidate)
+ app.cache_control(no_cache=True)
+ return app
+ self.abort(404)
+
+ @staticmethod
+ def GetServingPathForAbsFilename(source_paths, filename):
+ if not os.path.isabs(filename):
+ raise Exception('filename must be an absolute path')
+
+ for mapped_path in source_paths:
+ if not filename.startswith(mapped_path):
+ continue
+ rel = os.path.relpath(filename, mapped_path)
+ unix_rel = _RelPathToUnixPath(rel)
+ return unix_rel
+ return None
+
+
+class SimpleDirectoryHandler(webapp2.RequestHandler):
+ def get(self, *args, **kwargs): # pylint: disable=unused-argument
+ top_path = os.path.abspath(kwargs.pop('_top_path', None))
+ if not top_path.endswith(os.path.sep):
+ top_path += os.path.sep
+
+ joined_path = os.path.abspath(
+ os.path.join(top_path, kwargs.pop('rest_of_path')))
+ if not joined_path.startswith(top_path):
+ self.response.set_status(403)
+ return
+ app = FileAppWithGZipHandling(joined_path)
+ app.cache_control(no_cache=True)
+ return app
+
+
+class TestOverviewHandler(webapp2.RequestHandler):
+ def get(self, *args, **kwargs): # pylint: disable=unused-argument
+ test_links = []
+ for name, path in kwargs.pop('pds').iteritems():
+ test_links.append(_LINK_ITEM % (path, name))
+ quick_links = []
+ for name, path in _QUICK_LINKS:
+ quick_links.append(_LINK_ITEM % (path, name))
+ self.response.out.write(_MAIN_HTML % ('\n'.join(test_links),
+ '\n'.join(quick_links)))
+
+class DevServerApp(webapp2.WSGIApplication):
+ def __init__(self, pds, args):
+ super(DevServerApp, self).__init__(debug=True)
+ self.pds = pds
+ self._server = None
+ self._all_source_paths = []
+ self._all_mapped_test_data_paths = []
+ self._InitFromArgs(args)
+
+ @property
+ def server(self):
+ return self._server
+
+ @server.setter
+ def server(self, server):
+ self._server = server
+
+ def _InitFromArgs(self, args):
+ default_tests = dict((pd.GetName(), pd.GetRunUnitTestsUrl())
+ for pd in self.pds)
+ routes = [
+ Route('/tests.html', TestOverviewHandler,
+ defaults={'pds': default_tests}),
+ Route('', RedirectHandler, defaults={'_uri': '/tests.html'}),
+ Route('/', RedirectHandler, defaults={'_uri': '/tests.html'}),
+ ]
+ for pd in self.pds:
+ routes += pd.GetRoutes(args)
+ routes += [
+ Route('/%s/notify_test_result' % pd.GetName(),
+ TestResultHandler),
+ Route('/%s/notify_tests_completed' % pd.GetName(),
+ TestsCompletedHandler)
+ ]
+
+ for pd in self.pds:
+ # Test data system.
+ for mapped_path, source_path in pd.GetTestDataPaths(args):
+ self._all_mapped_test_data_paths.append((mapped_path, source_path))
+ routes.append(Route('%s__file_list__' % mapped_path,
+ DirectoryListingHandler,
+ defaults={
+ '_source_path': source_path,
+ '_mapped_path': mapped_path
+ }))
+ routes.append(Route('%s<rest_of_path:.+>' % mapped_path,
+ SimpleDirectoryHandler,
+ defaults={'_top_path': source_path}))
+
+ # This must go last, because its catch-all.
+ #
+ # Its funky that we have to add in the root path. The long term fix is to
+ # stop with the crazy multi-source-pathing thing.
+ for pd in self.pds:
+ self._all_source_paths += pd.GetSourcePaths(args)
+ routes.append(
+ Route('/<:.+>', SourcePathsHandler,
+ defaults={'_source_paths': self._all_source_paths}))
+
+ for route in routes:
+ self.router.add(route)
+
+ def GetAbsFilenameForHref(self, href):
+ for source_path in self._all_source_paths:
+ full_source_path = os.path.abspath(source_path)
+ expanded_href_path = os.path.abspath(os.path.join(full_source_path,
+ href.lstrip('/')))
+ if (os.path.exists(expanded_href_path) and
+ os.path.commonprefix([full_source_path,
+ expanded_href_path]) == full_source_path):
+ return expanded_href_path
+ return None
+
+ def GetURLForAbsFilename(self, filename):
+ assert self.server is not None
+ for mapped_path, source_path in self._all_mapped_test_data_paths:
+ if not filename.startswith(source_path):
+ continue
+ rel = os.path.relpath(filename, source_path)
+ unix_rel = _RelPathToUnixPath(rel)
+ url = urlparse.urljoin(mapped_path, unix_rel)
+ return url
+
+ path = SourcePathsHandler.GetServingPathForAbsFilename(
+ self._all_source_paths, filename)
+ if path is None:
+ return None
+ return urlparse.urljoin('/', path)
+
+
+def _AddPleaseExitMixinToServer(server):
+ # Shutting down httpserver gracefully and yielding a return code requires
+ # a bit of mixin code.
+
+ exit_code_attempt = []
+ def PleaseExit(exit_code):
+ if len(exit_code_attempt) > 0:
+ return
+ exit_code_attempt.append(exit_code)
+ server.running = False
+
+ real_serve_forever = server.serve_forever
+
+ def ServeForever():
+ try:
+ real_serve_forever()
+ except KeyboardInterrupt:
+ # allow CTRL+C to shutdown
+ return 255
+
+ if len(exit_code_attempt) == 1:
+ return exit_code_attempt[0]
+ # The serve_forever returned for some reason separate from
+ # exit_please.
+ return 0
+
+ server.please_exit = PleaseExit
+ server.serve_forever = ServeForever
+
+
+def _AddCommandLineArguments(pds, argv):
+ parser = argparse.ArgumentParser(description='Run development server')
+ parser.add_argument(
+ '--no-install-hooks', dest='install_hooks', action='store_false')
+ parser.add_argument('-p', '--port', default=8003, type=int)
+ for pd in pds:
+ g = parser.add_argument_group(pd.GetName())
+ pd.AddOptionstToArgParseGroup(g)
+ args = parser.parse_args(args=argv[1:])
+ return args
+
+
+def Main(argv):
+ pds = [
+ dashboard_dev_server_config.DashboardDevServerConfig(),
+ tracing_dev_server_config.TracingDevServerConfig(),
+ netlog_viewer_dev_server_config.NetlogViewerDevServerConfig(),
+ ]
+
+ args = _AddCommandLineArguments(pds, argv)
+
+ if args.install_hooks:
+ install.InstallHooks()
+
+ app = DevServerApp(pds, args=args)
+
+ server = httpserver.serve(app, host='127.0.0.1', port=args.port,
+ start_loop=False, daemon_threads=True)
+ _AddPleaseExitMixinToServer(server)
+ # pylint: disable=no-member
+ server.urlbase = 'http://127.0.0.1:%i' % server.server_port
+ app.server = server
+
+ sys.stderr.write('Now running on %s\n' % server.urlbase)
+
+ return server.serve_forever()
diff --git a/chromium/third_party/catapult/catapult_build/dev_server_unittest.py b/chromium/third_party/catapult/catapult_build/dev_server_unittest.py
new file mode 100644
index 00000000000..010bb2696bd
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/dev_server_unittest.py
@@ -0,0 +1,90 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import os
+import unittest
+
+
+from catapult_build import dev_server
+from tracing_build import tracing_dev_server_config
+import webapp2
+
+class DevServerTests(unittest.TestCase):
+
+ def setUp(self):
+ self.pds = [
+ tracing_dev_server_config.TracingDevServerConfig(),
+ ]
+
+ self.args = dev_server._AddCommandLineArguments(self.pds, [])
+
+ def testStaticDirectoryHandling(self):
+ app = dev_server.DevServerApp(self.pds, self.args)
+ request = webapp2.Request.blank('/tracing/tests.html')
+ response = request.get_response(app)
+
+ self.assertEqual(response.status_int, 200)
+
+ def testGetURLForAbsFilename(self):
+ app = dev_server.DevServerApp(self.pds, self.args)
+ class FakeServer(object):
+ pass
+ app.server = FakeServer()
+
+ cfg = tracing_dev_server_config.TracingDevServerConfig()
+ base_html_filename = os.path.join(cfg.project.tracing_src_path,
+ 'base', 'base.html')
+ url = app.GetURLForAbsFilename(base_html_filename)
+ self.assertEqual(url, '/tracing/base/base.html')
+
+ url = app.GetURLForAbsFilename('/tmp/foo')
+ self.assertIsNone(url)
+
+ def testGetAbsFilenameForHref(self):
+ app = dev_server.DevServerApp(self.pds, self.args)
+
+ cfg = tracing_dev_server_config.TracingDevServerConfig()
+ base_html_filename = os.path.join(cfg.project.tracing_src_path,
+ 'base', 'base.html')
+
+ filename = app.GetAbsFilenameForHref('/tracing/base/base.html')
+ self.assertEqual(base_html_filename, filename)
+
+ filename = app.GetAbsFilenameForHref('/etc/passwd')
+ self.assertIsNone(filename)
+
+ def testTestDataDirectory(self):
+ app = dev_server.DevServerApp(self.pds, self.args)
+ request = webapp2.Request.blank('/tracing/test_data/trivial_trace.json')
+ response = request.get_response(app)
+
+ self.assertEqual(response.status_int, 200)
+
+ def testTestDataDirectoryListing(self):
+ app = dev_server.DevServerApp(self.pds, self.args)
+ request = webapp2.Request.blank('/tracing/test_data/__file_list__')
+ response = request.get_response(app)
+
+ self.assertEqual(response.status_int, 200)
+ res = json.loads(response.body)
+ assert '/tracing/test_data/trivial_trace.json' in res
+
+ def testSkpDataDirectoryListing(self):
+ app = dev_server.DevServerApp(self.pds, self.args)
+ request = webapp2.Request.blank('/tracing/skp_data/__file_list__')
+ response = request.get_response(app)
+
+ self.assertEqual(response.status_int, 200)
+ res = json.loads(response.body)
+ assert '/tracing/skp_data/lthi_cats.skp' in res
+
+ def testTestListingHandler(self):
+ app = dev_server.DevServerApp(self.pds, self.args)
+ request = webapp2.Request.blank('/tracing/tests')
+ response = request.get_response(app)
+
+ self.assertEqual(response.status_int, 200)
+ res = json.loads(response.body)
+ self.assertTrue('test_relpaths' in res)
+ self.assertTrue(len(res['test_relpaths']) > 0)
diff --git a/chromium/third_party/catapult/catapult_build/fetch_telemetry_deps_and_run_tests b/chromium/third_party/catapult/catapult_build/fetch_telemetry_deps_and_run_tests
new file mode 100755
index 00000000000..5c03bf9590b
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/fetch_telemetry_deps_and_run_tests
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import sys
+
+
+_TELEMETRY_BIN_DIR = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..', 'telemetry', 'bin'))
+
+
+def main(args):
+ print 'Fetching Telemetry dependencies...'
+ subprocess.check_call(
+ [sys.executable,
+ os.path.join(_TELEMETRY_BIN_DIR, 'fetch_telemetry_binary_dependencies')])
+
+ print 'Done fetching Telemetry dependencies.'
+ print 'Running Telemetry tests...'
+ subprocess.check_call(
+ [sys.executable, os.path.join(_TELEMETRY_BIN_DIR, 'run_tests')] + args)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/third_party/catapult/catapult_build/html_checks.py b/chromium/third_party/catapult/catapult_build/html_checks.py
new file mode 100644
index 00000000000..bd3d9f0568e
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/html_checks.py
@@ -0,0 +1,72 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Checks to use in PRESUBMIT.py for HTML style violations."""
+
+import collections
+import difflib
+import re
+
+import bs4
+
+from catapult_build import parse_html
+
+
+def RunChecks(input_api, output_api, excluded_paths=None):
+
+ def ShouldCheck(affected_file):
+ path = affected_file.LocalPath()
+ if not path.endswith('.html'):
+ return False
+ if not excluded_paths:
+ return True
+ return not any(re.match(pattern, path) for pattern in excluded_paths)
+
+ affected_files = input_api.AffectedFiles(
+ file_filter=ShouldCheck, include_deletes=False)
+ results = []
+ for f in affected_files:
+ CheckAffectedFile(f, results, output_api)
+ return results
+
+
+def CheckAffectedFile(affected_file, results, output_api):
+ path = affected_file.LocalPath()
+ soup = parse_html.BeautifulSoup('\n'.join(affected_file.NewContents()))
+ for check in [CheckDoctype, CheckImportOrder]:
+ check(path, soup, results, output_api)
+
+
+def CheckDoctype(path, soup, results, output_api):
+ if _HasHtml5Declaration(soup):
+ return
+ error_text = 'Could not find "<!DOCTYPE html>" in %s.' % path
+ results.append(output_api.PresubmitError(error_text))
+
+
+def _HasHtml5Declaration(soup):
+ for item in soup.contents:
+ if isinstance(item, bs4.Doctype) and item.lower() == 'html':
+ return True
+ return False
+
+
+def CheckImportOrder(path, soup, results, output_api):
+ grouped_hrefs = collections.defaultdict(list) # Link rel -> [link hrefs].
+ for link in soup.find_all('link'):
+ if link.get('data-suppress-import-order') is not None:
+ continue
+
+ grouped_hrefs[','.join(link.get('rel'))].append(link.get('href'))
+
+ for rel, actual_hrefs in grouped_hrefs.iteritems():
+ expected_hrefs = list(sorted(set(actual_hrefs)))
+ if actual_hrefs != expected_hrefs:
+ error_text = (
+ 'Invalid "%s" link sort order in %s:\n' % (rel, path) + ' ' +
+ '\n '.join(difflib.ndiff(actual_hrefs, expected_hrefs)) +
+ '\nIf this error is invalid, you can suppress it by adding a ' +
+ '"data-suppress-import-order" attribute to the out-of-order <link> ' +
+ 'element.')
+ results.append(output_api.PresubmitError(error_text))
diff --git a/chromium/third_party/catapult/catapult_build/html_checks_unittest.py b/chromium/third_party/catapult/catapult_build/html_checks_unittest.py
new file mode 100644
index 00000000000..18a0e62380c
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/html_checks_unittest.py
@@ -0,0 +1,94 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from catapult_build import html_checks
+
+
+class MockAffectedFile(object):
+
+ def __init__(self, path, lines):
+ self.path = path
+ self.lines = lines
+
+ def NewContents(self):
+ return (l for l in self.lines)
+
+ def LocalPath(self):
+ return self.path
+
+
+class MockInputApi(object):
+
+ def __init__(self, affected_files):
+ self.affected_files = affected_files
+
+ def AffectedFiles(self, file_filter=None, **_):
+ if file_filter:
+ return [f for f in self.affected_files if file_filter(f)]
+ return self.affected_files
+
+
+class MockOutputApi(object):
+
+ def PresubmitError(self, error_text):
+ return error_text
+
+
+class HtmlChecksTest(unittest.TestCase):
+
+ def testRunChecksShowsErrorForWrongDoctype(self):
+ f = MockAffectedFile('foo/x.html', ['<!DOCTYPE XHTML1.0>'])
+ errors = html_checks.RunChecks(MockInputApi([f]), MockOutputApi())
+ self.assertEqual(1, len(errors))
+
+ def testRunChecksReturnsErrorForEmptyFile(self):
+ f = MockAffectedFile('foo/x.html', [])
+ errors = html_checks.RunChecks(MockInputApi([f]), MockOutputApi())
+ self.assertEqual(1, len(errors))
+
+ def testRunChecksNoErrorsForFileWithCorrectDocstring(self):
+ f = MockAffectedFile('foo/x.html', ['<!DOCTYPE html> '])
+ errors = html_checks.RunChecks(MockInputApi([f]), MockOutputApi())
+ self.assertEqual([], errors)
+
+ def testRunChecksAcceptsDifferentCapitalization(self):
+ f = MockAffectedFile('foo/x.html', ['<!doctype HtMl> '])
+ errors = html_checks.RunChecks(MockInputApi([f]), MockOutputApi())
+ self.assertEqual([], errors)
+
+ def testRunChecksAcceptsCommentsBeforeDoctype(self):
+ f = MockAffectedFile('foo/x.html', ['<!-- asdf -->\n<!doctype html> '])
+ errors = html_checks.RunChecks(MockInputApi([f]), MockOutputApi())
+ self.assertEqual([], errors)
+
+ def testRunChecksSkipsFilesInExcludedPaths(self):
+ f = MockAffectedFile('foo/x.html', ['<!DOCTYPE html XHTML1.0>'])
+ errors = html_checks.RunChecks(
+ MockInputApi([f]), MockOutputApi(), excluded_paths=['^foo/.*'])
+ self.assertEqual([], errors)
+
+ def testRunChecksSkipsNonHtmlFiles(self):
+ f = MockAffectedFile('foo/bar.py', ['#!/usr/bin/python', 'print 10'])
+ errors = html_checks.RunChecks(MockInputApi([f]), MockOutputApi())
+ self.assertEqual([], errors)
+
+ def testRunChecksShowsErrorForOutOfOrderImports(self):
+ f = MockAffectedFile('foo/x.html', [
+ '<!DOCTYPE html>',
+ '<link rel="import" href="b.html">',
+ '<link rel="import" href="a.html">',
+ ])
+ errors = html_checks.RunChecks(MockInputApi([f]), MockOutputApi())
+ self.assertEqual(1, len(errors))
+
+ def testRunChecksSkipsSuppressedOutOfOrderImports(self):
+ f = MockAffectedFile('foo/x.html', [
+ '<!DOCTYPE html>',
+ '<link rel="import" href="b.html" data-suppress-import-order>',
+ '<link rel="import" href="a.html">',
+ ])
+ errors = html_checks.RunChecks(MockInputApi([f]), MockOutputApi())
+ self.assertEqual([], errors)
diff --git a/chromium/third_party/catapult/catapult_build/js_checks.py b/chromium/third_party/catapult/catapult_build/js_checks.py
new file mode 100644
index 00000000000..d5a3714f67f
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/js_checks.py
@@ -0,0 +1,113 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+
+import eslint
+from py_vulcanize import strip_js_comments
+
+from catapult_build import parse_html
+
+
+class JSChecker(object):
+
+ def __init__(self, input_api, output_api, file_filter=None):
+ self.input_api = input_api
+ self.output_api = output_api
+ if file_filter:
+ self.file_filter = file_filter
+ else:
+ self.file_filter = lambda x: True
+
+ def RunChecks(self):
+ """Checks for violations of the Chromium JavaScript style guide.
+
+ See:
+ http://chromium.org/developers/web-development-style-guide#TOC-JavaScript
+ """
+ results = []
+
+ affected_files = self.input_api.AffectedFiles(
+ file_filter=self.file_filter,
+ include_deletes=False)
+
+ def ShouldCheck(f):
+ if f.LocalPath().endswith('.js'):
+ return True
+ if f.LocalPath().endswith('.html'):
+ return True
+ return False
+
+ affected_js_files = [f for f in affected_files if ShouldCheck(f)]
+ error_lines = []
+ for f in affected_js_files:
+ contents = list(f.NewContents())
+ error_lines += CheckStrictMode(
+ '\n'.join(contents),
+ is_html_file=f.LocalPath().endswith('.html'))
+
+ if affected_js_files:
+ success, eslint_output = eslint.RunEslint(
+ [f.AbsoluteLocalPath() for f in affected_js_files])
+
+ if not success:
+ error_lines.append('\neslint found lint errors:')
+ error_lines.append(eslint_output)
+
+ if error_lines:
+ error_lines.insert(0, 'Found JavaScript style violations:')
+ results.append(
+ _MakeErrorOrWarning(self.output_api, '\n'.join(error_lines)))
+
+ return results
+
+
+def _ErrorHighlight(start, length):
+ """Produces a row of '^'s to underline part of a string."""
+ return start * ' ' + length * '^'
+
+
+def _MakeErrorOrWarning(output_api, error_text):
+ return output_api.PresubmitError(error_text)
+
+
+def CheckStrictMode(contents, is_html_file=False):
+ statements_to_check = []
+ if is_html_file:
+ statements_to_check.extend(_FirstStatementsInScriptElements(contents))
+ else:
+ statements_to_check.append(_FirstStatement(contents))
+ error_lines = []
+ for s in statements_to_check:
+ if s != "'use strict'":
+ error_lines.append('Expected "\'use strict\'" as first statement, '
+ 'but found "%s" instead.' % s)
+ return error_lines
+
+
+def _FirstStatementsInScriptElements(contents):
+ """Returns a list of first statements found in each <script> element."""
+ soup = parse_html.BeautifulSoup(contents)
+ script_elements = soup.find_all('script', src=None)
+ return [_FirstStatement(e.get_text()) for e in script_elements]
+
+
+def _FirstStatement(contents):
+ """Extracts the first statement in some JS source code."""
+ stripped_contents = strip_js_comments.StripJSComments(contents).strip()
+ matches = re.match('^(.*?);', stripped_contents, re.DOTALL)
+ if not matches:
+ return ''
+ return matches.group(1).strip()
+
+
+def RunChecks(input_api, output_api, excluded_paths=None):
+
+ def ShouldCheck(affected_file):
+ if not excluded_paths:
+ return True
+ path = affected_file.LocalPath()
+ return not any(re.match(pattern, path) for pattern in excluded_paths)
+
+ return JSChecker(input_api, output_api, file_filter=ShouldCheck).RunChecks()
diff --git a/chromium/third_party/catapult/catapult_build/js_checks_unittest.py b/chromium/third_party/catapult/catapult_build/js_checks_unittest.py
new file mode 100644
index 00000000000..290091f208c
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/js_checks_unittest.py
@@ -0,0 +1,78 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from catapult_build import js_checks
+
+
+class JsChecksTest(unittest.TestCase):
+
+ def testCheckStrictModeReturnsNoErrorsWhenAllScriptElementsAreStrict(self):
+ contents = """
+ <script> 'use strict'; var a = 1 + 1;
+ </script>
+ <br>
+ <script>
+ 'use strict';
+ var b = 2 + 2;
+ </script>
+ """
+ self.assertEqual(
+ [], js_checks.CheckStrictMode(contents, is_html_file=True))
+
+ def testCheckStrictModeReturnsNoErrorsWhenThereAreNoScriptTags(self):
+ contents = """
+ <div></div>
+ """
+ self.assertEqual(
+ [], js_checks.CheckStrictMode(contents, is_html_file=True))
+
+ def testCheckStrictModeReturnsNoErrorsWhenJSFileIsStrict(self):
+ contents = """
+ 'use strict';
+ var a = 1 + 1;
+ var b = 2 + 2;
+ """
+ self.assertEqual(
+ [], js_checks.CheckStrictMode(contents, is_html_file=False))
+
+ def testCheckStrictModeWhenThereIsACommentAboveTheDeclaration(self):
+ contents = """
+ // This is a comment at the top
+ /* another comment which
+ spans two lines */
+ 'use strict';
+ var a = 1 + 1;
+ var b = 2 + 2;
+ """
+ self.assertEqual(
+ [], js_checks.CheckStrictMode(contents, is_html_file=False))
+
+ def testCheckStrictModeDoesntCheckExternalScriptElements(self):
+ contents = """
+ <script src="external.js"></script>
+ """
+ self.assertEqual(
+ [], js_checks.CheckStrictMode(contents, is_html_file=True))
+
+ def testCheckStrictModeReturnsAnErrorWhenOneScriptElementIsNotStrict(self):
+ contents = """
+ <script> 'use strict'; var a = 1 + 1;
+ </script>
+ <br>
+ <script>
+ var b = 2 + 2;
+ </script>
+ """
+ self.assertEqual(
+ 1, len(js_checks.CheckStrictMode(contents, is_html_file=True)))
+
+ def testCheckStrictModeReturnsAnErrorWhenJSFileIsNonStrict(self):
+ contents = """
+ var a = 1 + 1;
+ var b = 2 + 2;
+ """
+ self.assertEqual(
+ 1, len(js_checks.CheckStrictMode(contents, is_html_file=False)))
diff --git a/chromium/third_party/catapult/catapult_build/node_bootstrap.js b/chromium/third_party/catapult/catapult_build/node_bootstrap.js
new file mode 100644
index 00000000000..d36fde3570d
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/node_bootstrap.js
@@ -0,0 +1,83 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * @fileoverview Lets node import catapult HTML-imports-authored modules.
+ *
+ */
+var isNode = global.process && global.process.versions.node;
+if (!isNode)
+ throw new Error('Only works inside node');
+
+var fs = require('fs');
+var path = require('path');
+var process = require('process');
+var child_process = require('child_process');
+
+var catapultPath = fs.realpathSync(path.join(__dirname, '..'));
+var catapultBuildPath = path.join(catapultPath, 'catapult_build');
+
+var vinnPath = path.join(catapultPath, 'third_party', 'vinn');
+
+function loadAndEval(fileName) {
+ var contents = fs.readFileSync(fileName, 'utf8');
+ (function() {
+ eval(contents);
+ }).call(global);
+}
+
+function initialize() {
+ loadAndEval(path.join(vinnPath, 'vinn', 'base64_compat.js'));
+
+ // First, we need to hand-load the HTML imports loader from Vinn,
+ // plus a few of its supporting files. These all assume that 'this' is the
+ // global object, so eval them with 'this' redirected.
+ loadAndEval(path.join(vinnPath, 'third_party', 'parse5', 'parse5.js'));
+ loadAndEval(path.join(vinnPath, 'vinn', 'html_to_js_generator.js'));
+ loadAndEval(path.join(vinnPath, 'vinn', 'html_imports_loader.js'));
+ loadAndEval(path.join(vinnPath, 'vinn', 'path_utils.js'));
+
+ // Now that everything is loaded, we need to set up the loader.
+ var pathUtils = new global.PathUtils(
+ {
+ currentWorkingDirectory: process.cwd(),
+ exists: function(fileName) {
+ return fs.existsSync(fileName);
+ }
+ });
+ global.HTMLImportsLoader.setPathUtils(pathUtils);
+}
+
+
+/**
+ * Gets the source search paths for a catapult project module.
+ *
+ * @param {String} projectName The project in question.
+ * @return {Array} A list of search paths.
+ */
+module.exports.getSourcePathsForProject = function(projectName) {
+ var sourcePathsString = child_process.execFileSync(
+ path.join(catapultBuildPath, 'print_project_info'),
+ ['--source-paths', projectName]);
+ return JSON.parse(sourcePathsString);
+};
+
+
+/**
+ * Gets the headless test module filenames for a catapult project module.
+ *
+ * @param {String} projectName The project in question.
+ * @return {Array} A list of module filenames.
+ */
+module.exports.getHeadlessTestModuleFilenamesForProject =
+ function(projectName) {
+ var sourcePathsString = child_process.execFileSync(
+ path.join(catapultBuildPath, 'print_project_info'),
+ ['--headless-test-module-filenames', projectName]);
+ return JSON.parse(sourcePathsString);
+};
+
+initialize();
diff --git a/chromium/third_party/catapult/catapult_build/parse_html.py b/chromium/third_party/catapult/catapult_build/parse_html.py
new file mode 100644
index 00000000000..a8f19be0a32
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/parse_html.py
@@ -0,0 +1,18 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Code for parsing HTML.
+
+The purpose of this module is to ensure consistency of HTML parsing
+in catapult_build.
+"""
+
+import bs4
+
+
+def BeautifulSoup(contents):
+ # html5lib is a lenient parser; compared with the default parser,
+ # it is more similar to how a web browser parses. See:
+ # http://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser
+ return bs4.BeautifulSoup(markup=contents, features='html5lib')
diff --git a/chromium/third_party/catapult/catapult_build/perfbot_stats/__init__.py b/chromium/third_party/catapult/catapult_build/perfbot_stats/__init__.py
new file mode 100644
index 00000000000..50b23dff631
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/perfbot_stats/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_stats.py b/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_stats.py
new file mode 100755
index 00000000000..e98fddfd37d
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_stats.py
@@ -0,0 +1,155 @@
+#!/usr/bin/env python2.7
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Script to pull chromium.perf stats from chrome-infra-stats API.
+
+Currently this just pulls success rates from the API, averages daily per
+builder, and uploads to perf dashboard. It could be improved to provide more
+detailed success rates.
+
+The API documentation for chrome-infra-stats is at:
+https://apis-explorer.appspot.com/apis-explorer/?
+ base=https://chrome-infra-stats.appspot.com/_ah/api#p/
+"""
+
+import calendar
+import datetime
+import json
+import sys
+import urllib
+import urllib2
+
+BUILDER_LIST_URL = ('https://chrome-infra-stats.appspot.com/'
+ '_ah/api/stats/v1/masters/chromium.perf')
+
+BUILDER_STATS_URL = ('https://chrome-infra-stats.appspot.com/_ah/api/stats/v1/'
+ 'stats/chromium.perf/%s/overall__build__result__/%s')
+
+USAGE = ('Usage: chrome_perf_stats.py <year> <month> <day>. If date is not '
+ 'specified, yesterday will be used.')
+
+
+def main():
+ if len(sys.argv) == 2 and sys.argv[0] == '--help':
+ print USAGE
+ sys.exit(0)
+ year = None
+ month = None
+ days = None
+ if len(sys.argv) == 4 or len(sys.argv) == 3:
+ year = int(sys.argv[1])
+ if year > 2016 or year < 2014:
+ print USAGE
+ sys.exit(0)
+ month = int(sys.argv[2])
+ if month > 12 or month <= 0:
+ print USAGE
+ sys.exit(0)
+ if len(sys.argv) == 3:
+ days = range(1, calendar.monthrange(year, month)[1] + 1)
+ else:
+ day = int(sys.argv[3])
+ if day > 31 or day <= 0:
+ print USAGE
+ sys.exit(0)
+ days = [day]
+ elif len(sys.argv) != 1:
+ print USAGE
+ sys.exit(0)
+ else:
+ yesterday = datetime.date.today() - datetime.timedelta(days=1)
+ year = yesterday.year
+ month = yesterday.month
+ days = [yesterday.day]
+
+ response = urllib2.urlopen(BUILDER_LIST_URL)
+ builders = [builder['name'] for builder in json.load(response)['builders']]
+ success_rates = CalculateSuccessRates(year, month, days, builders)
+ UploadToPerfDashboard(success_rates)
+
+
+def _UpdateSuccessRatesWithResult(
+ success_rates, results, date_dict_str, builder):
+ count = int(results['count'])
+ if count == 0:
+ return
+ success_count = count - int(results['failure_count'])
+ success_rates.setdefault(date_dict_str, {})
+ success_rates[date_dict_str].setdefault(builder, {
+ 'count': 0,
+ 'success_count': 0
+ })
+ success_rates[date_dict_str][builder]['count'] += count
+ success_rates[date_dict_str][builder]['success_count'] += success_count
+
+
+def _SummarizeSuccessRates(success_rates):
+ overall_success_rates = []
+ for day, results in success_rates.iteritems():
+ success_rate_sum = 0
+ success_rate_count = 0
+ for rates in results.values():
+ if rates['count'] == 0:
+ continue
+ success_rate_sum += (
+ float(rates['success_count']) / float(rates['count']))
+ success_rate_count += 1
+ overall_success_rates.append(
+ [day, float(success_rate_sum) / float(success_rate_count)])
+ return overall_success_rates
+
+
+def UploadToPerfDashboard(success_rates):
+ for success_rate in success_rates:
+ date_str = '%s-%s-%s' % (success_rate[0][0:4],
+ success_rate[0][4:6],
+ success_rate[0][6:8])
+ dashboard_data = {
+ 'master': 'WaterfallStats',
+ 'bot': 'ChromiumPerf',
+ 'point_id': int(success_rate[0]),
+ 'supplemental': {},
+ 'versions': {
+ 'date': date_str,
+ },
+ 'chart_data': {
+ 'benchmark_name': 'success_rate',
+ 'benchmark_description': 'Success rates averaged per-builder',
+ 'format_version': 1.0,
+ 'charts': {
+ 'overall_success_rate': {
+ 'summary': {
+ 'name': 'overall_success_rate',
+ 'type': 'scalar',
+ 'units': '%',
+ 'value': success_rate[1]
+ }
+ }
+ }
+ }
+ }
+ url = 'https://chromeperf.appspot.com/add_point'
+ data = urllib.urlencode({'data': json.dumps(dashboard_data)})
+ urllib2.urlopen(url=url, data=data).read()
+
+
+def CalculateSuccessRates(year, month, days, builders):
+ success_rates = {}
+ for day in days:
+ for hour in range(24):
+ date_str = '%d-%02d-%02dT%02d:00Z' % (year, month, day, hour)
+ date_dict_str = '%d%02d%02d' % (year, month, day)
+ for builder in builders:
+ url = BUILDER_STATS_URL % (
+ urllib.quote(builder), urllib.quote(date_str))
+ response = urllib2.urlopen(url)
+ results = json.load(response)
+ _UpdateSuccessRatesWithResult(
+ success_rates, results, date_dict_str, builder)
+ return _SummarizeSuccessRates(success_rates)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_stats_unittest.py b/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_stats_unittest.py
new file mode 100644
index 00000000000..bb72bf19039
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_stats_unittest.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python2.7
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from perfbot_stats import chrome_perf_stats
+
+
+class TestChromePerfStats(unittest.TestCase):
+
+ def testUpdateSuccessRatesWithResult(self):
+ success_rates = {}
+ chrome_perf_stats._UpdateSuccessRatesWithResult(
+ success_rates,
+ {'count': 0},
+ 'invalid_date_str',
+ 'invalid_builder')
+ self.assertDictEqual({}, success_rates)
+ chrome_perf_stats._UpdateSuccessRatesWithResult(
+ success_rates,
+ {'count': 5, 'failure_count': 3},
+ '20151010',
+ 'android_nexus_10')
+ self.assertDictEqual(
+ {'20151010': {'android_nexus_10': {'count': 5, 'success_count': 2}}},
+ success_rates)
+ chrome_perf_stats._UpdateSuccessRatesWithResult(
+ success_rates,
+ {'count': 5, 'failure_count': 4},
+ '20151010',
+ 'android_nexus_4')
+ self.assertDictEqual(
+ {
+ '20151010': {
+ 'android_nexus_10': {'count': 5, 'success_count': 2},
+ 'android_nexus_4': {'count': 5, 'success_count': 1},
+ }
+ },
+ success_rates)
+ chrome_perf_stats._UpdateSuccessRatesWithResult(
+ success_rates,
+ {'count': 5, 'failure_count': 0},
+ '20151009',
+ 'win_xp')
+ self.assertDictEqual(
+ {
+ '20151010': {
+ 'android_nexus_10': {'count': 5, 'success_count': 2},
+ 'android_nexus_4': {'count': 5, 'success_count': 1},
+ },
+ '20151009': {
+ 'win_xp': {'count': 5, 'success_count': 5},
+ },
+ },
+ success_rates)
+
+ def testSummarizeSuccessRates(self):
+ rates = chrome_perf_stats._SummarizeSuccessRates(
+ {
+ '20151010': {
+ 'android_nexus_10': {'count': 5, 'success_count': 2},
+ 'android_nexus_4': {'count': 5, 'success_count': 3},
+ },
+ '20151009': {
+ 'win_xp': {'count': 5, 'success_count': 5},
+ },
+ })
+ self.assertListEqual([['20151010', 0.5], ['20151009', 1.0]], rates)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_step_timings.py b/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_step_timings.py
new file mode 100755
index 00000000000..30558abd1f6
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/perfbot_stats/chrome_perf_step_timings.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python2.7
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Script to pull chromium.perf step timings from chrome-infra-stats API.
+
+Currently this pulls the list of steps per builder. For each step, if it is not
+a setup step, we get the step stats for the last 20 runs for that builder.
+
+The API documentation for chrome-infra-stats is at:
+https://apis-explorer.appspot.com/apis-explorer/?
+ base=https://chrome-infra-stats.appspot.com/_ah/api#p/
+"""
+
+import csv
+import datetime
+import json
+import sys
+import urllib
+import urllib2
+
+
+BUILDER_STEPS_URL = ('https://chrome-infra-stats.appspot.com/_ah/api/stats/v1/'
+ 'masters/chromium.perf/%s')
+
+
+STEP_ACTIVE_URL = ('https://chrome-infra-stats.appspot.com/_ah/api/stats/v1/'
+ 'steps/last/chromium.perf/%s/%s/1')
+
+
+STEP_STATS_URL = ('https://chrome-infra-stats.appspot.com/_ah/api/stats/v1/'
+ 'stats/last/chromium.perf/%s/%s/20')
+
+
+IGNORED_STEPS = [
+ 'List Perf Tests',
+ 'Sharded Perf Tests',
+ 'authorize_adb_devices',
+ 'bot_update',
+ 'build__schedule__time__',
+ 'clean local files',
+ 'cleanup_temp',
+ 'device_status_check',
+ 'extract build',
+ 'gclient runhooks',
+ 'get compile targets for scripts',
+ 'get perf test list',
+ 'gsutil download_build_product',
+ 'host_info',
+ 'install ChromeShell.apk',
+ 'json.output cache',
+ 'json.output cache',
+ 'overall__build__result__',
+ 'overall__queued__time__',
+ 'provision_devices',
+ 'read test spec',
+ 'rmtree build directory',
+ 'setup_build',
+ 'spawn_logcat_monitor',
+ 'stack_tool_for_tombstones',
+ 'stack_tool_with_logcat_dump',
+ 'steps',
+ 'test_report',
+ 'unzip_build_product',
+ 'update_scripts'
+]
+
+KNOWN_TESTERS_LIST = [
+ 'Android Nexus4 Perf',
+ 'Android Nexus5 Perf',
+ 'Android Nexus6 Perf',
+ 'Android Nexus10 Perf',
+ 'Android Nexus7v2 Perf',
+ 'Android One Perf',
+ 'Linux Perf (1)',
+ 'Linux Perf (2)',
+ 'Linux Perf (3)',
+ 'Linux Perf (4)',
+ 'Linux Perf (5)',
+ 'Mac 10.8 Perf (1)',
+ 'Mac 10.8 Perf (2)',
+ 'Mac 10.8 Perf (3)',
+ 'Mac 10.8 Perf (4)',
+ 'Mac 10.8 Perf (5)',
+ 'Mac 10.9 Perf (1)',
+ 'Mac 10.9 Perf (2)',
+ 'Mac 10.9 Perf (3)',
+ 'Mac 10.9 Perf (4)',
+ 'Mac 10.9 Perf (5)',
+ 'Win 7 ATI GPU Perf',
+ 'Win 7 Intel GPU Perf',
+ 'Win 7 Low-End Perf (1)',
+ 'Win 7 Low-End Perf (2)',
+ 'Win 7 Nvidia GPU Perf',
+ 'Win 7 Perf (1)',
+ 'Win 7 Perf (2)',
+ 'Win 7 Perf (3)',
+ 'Win 7 Perf (4)',
+ 'Win 7 Perf (5)',
+ 'Win 7 x64 Perf (1)',
+ 'Win 7 x64 Perf (2)',
+ 'Win 8 Perf (1)',
+ 'Win 8 Perf (2)',
+ 'Win XP Perf (1)',
+ 'Win XP Perf (2)',
+ 'Win XP Perf (3)',
+ 'Win XP Perf (4)',
+ 'Win XP Perf (5)'
+]
+
+
+USAGE = 'Usage: chrome-perf-step-timings.py <outfilename>'
+
+
+def main():
+ if len(sys.argv) != 2:
+ print USAGE
+ sys.exit(0)
+ outfilename = sys.argv[1]
+
+ threshold_time = datetime.datetime.now() - datetime.timedelta(days=2)
+
+ col_names = [('builder', 'step', 'run_count', 'stddev', 'mean', 'maximum',
+ 'median', 'seventyfive', 'ninety', 'ninetynine')]
+ with open(outfilename, 'wb') as f:
+ writer = csv.writer(f)
+ writer.writerows(col_names)
+
+ for builder in KNOWN_TESTERS_LIST:
+ step_timings = []
+ url = BUILDER_STEPS_URL % urllib.quote(builder)
+ response = urllib2.urlopen(url)
+ results = json.load(response)
+ steps = results['steps']
+ steps.sort() # to group tests and their references together.
+ for step in steps:
+ if step in IGNORED_STEPS:
+ continue
+ url = STEP_ACTIVE_URL % (urllib.quote(builder), urllib.quote(step))
+ response = urllib2.urlopen(url)
+ results = json.load(response)
+ if ('step_records' not in results.keys() or
+ len(results['step_records']) == 0):
+ continue
+ first_record = results['step_records'][0]
+ last_step_time = datetime.datetime.strptime(
+ first_record['step_start'], "%Y-%m-%dT%H:%M:%S.%f")
+ # ignore steps that did not run for more than 2 days
+ if last_step_time < threshold_time:
+ continue
+ url = STEP_STATS_URL % (urllib.quote(builder), urllib.quote(step))
+ response = urllib2.urlopen(url)
+ results = json.load(response)
+ step_timings.append(
+ [builder, step, results['count'], results['stddev'],
+ results['mean'], results['maximum'], results['median'],
+ results['seventyfive'], results['ninety'],
+ results['ninetynine']])
+ with open(outfilename, 'ab') as f:
+ writer = csv.writer(f)
+ writer.writerows(step_timings)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/catapult_build/print_project_info b/chromium/third_party/catapult/catapult_build/print_project_info
new file mode 100755
index 00000000000..79be6ebdc4e
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/print_project_info
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import sys
+import os
+import json
+
+"""
+Prints the source path of the provided project name.
+
+This utility loads the specified x_project.py from one of our standard
+module folders, constructs its project module, and prints the source paths that
+it uses.
+
+This is used by the node_bootstrap.js to load the tracing code into node.
+"""
+
+def _ToUpperCamelCase(name):
+ in_parts = name.split('_')
+ out_parts = []
+ for part in in_parts:
+ out_part = part[0].upper() + part[1:]
+ out_parts.append(out_part)
+ return ''.join(out_parts)
+
+def _RelPathToUnixPath(p):
+ return p.replace(os.sep, '/')
+
+def Main(args):
+ parser = argparse.ArgumentParser(
+ usage='%(prog)s project_name',
+ epilog='Prints the source paths for the provided catapult project\n')
+ parser.add_argument('--source-paths', action='store_true')
+ parser.add_argument('--headless-test-module-filenames', action='store_true')
+ parser.add_argument('project_name', nargs=1)
+ args = parser.parse_args(args)
+
+ catapult_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ '..'))
+
+ project_name = args.project_name[0]
+ project_path = os.path.join(catapult_path, project_name)
+ sys.path.append(project_path)
+
+ project_module_name = project_name + '_project'
+ try:
+ project_module = __import__(project_module_name, fromlist=[True])
+ except:
+ sys.stderr.write('Could not import %s from %s' % (project_module_name,
+ project_path))
+ return 1
+
+ project_module.UpdateSysPathIfNeeded()
+
+ class_name = _ToUpperCamelCase(project_name) + 'Project'
+
+ try:
+ project_class = project_module.__dict__[class_name]
+ except:
+ sys.stderr.write('Could not find %s in %s' % (class_name,
+ project_module_name))
+ return 1
+
+ project = project_class()
+
+ if args.source_paths:
+ print json.dumps(project.source_paths)
+
+ if args.headless_test_module_filenames:
+ headless_test_module_filenames = ['/' + _RelPathToUnixPath(x)
+ for x in project.FindAllD8TestModuleRelPaths()]
+ headless_test_module_filenames.sort()
+ print json.dumps(headless_test_module_filenames)
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:])) \ No newline at end of file
diff --git a/chromium/third_party/catapult/catapult_build/remove_stale_files.py b/chromium/third_party/catapult/catapult_build/remove_stale_files.py
new file mode 100644
index 00000000000..76329f08461
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/remove_stale_files.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import sys
+
+
+def RemoveAllStaleFiles(base_dir, types_to_purge):
+ """Scan directories for old files and delete them."""
+ for type_ext in types_to_purge:
+ for dirname, _, filenames in os.walk(base_dir):
+ if '.git' in dirname:
+ continue
+ for filename in filenames:
+ _, ext = os.path.splitext(filename)
+ if ext != type_ext:
+ continue
+
+ full_path = os.path.join(dirname, filename)
+
+ try:
+ os.remove(full_path)
+ except OSError:
+ # Wrap OS calls in try/except in case another process touched this
+ # file.
+ pass
+
+ try:
+ os.removedirs(dirname)
+ except OSError:
+ # Wrap OS calls in try/except in case another process touched this dir.
+ pass
+
+
+def Main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('path', help='Path to clear stale files from.')
+ parser.add_argument('types', help='Comma separated list of types to purge.')
+ args = parser.parse_args(sys.argv[1:])
+
+ RemoveAllStaleFiles(args.path, args.types.split(','))
+
+
+if __name__ == '__main__':
+ Main()
diff --git a/chromium/third_party/catapult/catapult_build/repo_checks.py b/chromium/third_party/catapult/catapult_build/repo_checks.py
new file mode 100644
index 00000000000..8fc765a88ee
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/repo_checks.py
@@ -0,0 +1,17 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Checks to use in PRESUBMIT.py for general repository violations."""
+
+
+def RunChecks(input_api, output_api):
+ orig_files = [f.LocalPath()
+ for f in input_api.AffectedFiles(include_deletes=False)
+ if f.LocalPath().endswith('.orig')]
+ if orig_files:
+ return [output_api.PresubmitError(
+ 'Files with ".orig" suffix must not be checked into the '
+ 'repository:\n ' + '\n '.join(orig_files))]
+ else:
+ return []
diff --git a/chromium/third_party/catapult/catapult_build/run_dev_server_tests.py b/chromium/third_party/catapult/catapult_build/run_dev_server_tests.py
new file mode 100644
index 00000000000..596f3458219
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/run_dev_server_tests.py
@@ -0,0 +1,234 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import json
+import logging
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+
+from hooks import install
+
+from py_utils import binary_manager
+from py_utils import dependency_util
+from py_utils import xvfb
+
+
+# Path to dependency manager config containing chrome binary data.
+CHROME_BINARIES_CONFIG = dependency_util.ChromeBinariesConfigPath()
+
+CHROME_CONFIG_URL = (
+ 'https://code.google.com/p/chromium/codesearch#chromium/src/third_party/'
+ 'catapult/py_utils/py_utils/chrome_binaries.json')
+
+# Default port to run on if not auto-assigning from OS
+DEFAULT_PORT = '8111'
+
+# Mapping of sys.platform -> platform-specific names and paths.
+PLATFORM_MAPPING = {
+ 'linux2': {
+ 'omaha': 'linux',
+ 'prefix': 'Linux_x64',
+ 'zip_prefix': 'linux',
+ 'chromepath': 'chrome-linux/chrome'
+ },
+ 'win32': {
+ 'omaha': 'win',
+ 'prefix': 'Win',
+ 'zip_prefix': 'win32',
+ 'chromepath': 'chrome-win32\\chrome.exe',
+ },
+ 'darwin': {
+ 'omaha': 'mac',
+ 'prefix': 'Mac',
+ 'zip_prefix': 'mac',
+ 'chromepath': ('chrome-mac/Chromium.app/Contents/MacOS/Chromium'),
+ 'version_path': 'chrome-mac/Chromium.app/Contents/Versions/',
+ 'additional_paths': [
+ ('chrome-mac/Chromium.app/Contents/Versions/%VERSION%/'
+ 'Chromium Helper.app/Contents/MacOS/Chromium Helper'),
+ ],
+ },
+}
+
+
+def IsDepotToolsPath(path):
+ return os.path.isfile(os.path.join(path, 'gclient'))
+
+
+def FindDepotTools():
+ # Check if depot_tools is already in PYTHONPATH
+ for path in sys.path:
+ if path.rstrip(os.sep).endswith('depot_tools') and IsDepotToolsPath(path):
+ return path
+
+ # Check if depot_tools is in the path
+ for path in os.environ['PATH'].split(os.pathsep):
+ if IsDepotToolsPath(path):
+ return path.rstrip(os.sep)
+
+ return None
+
+
+def GetLocalChromePath(path_from_command_line):
+ if path_from_command_line:
+ return path_from_command_line
+
+ if sys.platform == 'darwin': # Mac
+ chrome_path = (
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome')
+ if os.path.isfile(chrome_path):
+ return chrome_path
+ elif sys.platform.startswith('linux'):
+ found = False
+ try:
+ with open(os.devnull, 'w') as devnull:
+ found = subprocess.call(['google-chrome', '--version'],
+ stdout=devnull, stderr=devnull) == 0
+ except OSError:
+ pass
+ if found:
+ return 'google-chrome'
+ elif sys.platform == 'win32':
+ search_paths = [os.getenv('PROGRAMFILES(X86)'),
+ os.getenv('PROGRAMFILES'),
+ os.getenv('LOCALAPPDATA')]
+ chrome_path = os.path.join('Google', 'Chrome', 'Application', 'chrome.exe')
+ for search_path in search_paths:
+ test_path = os.path.join(search_path, chrome_path)
+ if os.path.isfile(test_path):
+ return test_path
+ return None
+
+
+def Main(argv):
+ try:
+ parser = argparse.ArgumentParser(
+ description='Run dev_server tests for a project.')
+ parser.add_argument('--chrome_path', type=str,
+ help='Path to Chrome browser binary.')
+ parser.add_argument('--no-use-local-chrome',
+ dest='use_local_chrome', action='store_false')
+ parser.add_argument(
+ '--no-install-hooks', dest='install_hooks', action='store_false')
+ parser.add_argument('--tests', type=str,
+ help='Set of tests to run (tracing or perf_insights)')
+ parser.add_argument('--channel', type=str, default='stable',
+ help='Chrome channel to run (stable or canary)')
+ parser.add_argument('--presentation-json', type=str,
+ help='Recipe presentation-json output file path')
+ parser.set_defaults(install_hooks=True)
+ parser.set_defaults(use_local_chrome=True)
+ args = parser.parse_args(argv[1:])
+
+ if args.install_hooks:
+ install.InstallHooks()
+
+ user_data_dir = tempfile.mkdtemp()
+ tmpdir = None
+ xvfb_process = None
+
+ server_path = os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), os.pardir, 'bin', 'run_dev_server')
+ # TODO(anniesullie): Make OS selection of port work on Windows. See #1235.
+ if sys.platform == 'win32':
+ port = DEFAULT_PORT
+ else:
+ port = '0'
+ server_command = [server_path, '--no-install-hooks', '--port', port]
+ if sys.platform.startswith('win'):
+ server_command = ['python.exe'] + server_command
+ print "Starting dev_server..."
+ server_process = subprocess.Popen(
+ server_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ bufsize=1)
+ time.sleep(1)
+ if sys.platform != 'win32':
+ output = server_process.stderr.readline()
+ port = re.search(
+ r'Now running on http://127.0.0.1:([\d]+)', output).group(1)
+
+ chrome_info = None
+ if args.use_local_chrome:
+ chrome_path = GetLocalChromePath(args.chrome_path)
+ if not chrome_path:
+ logging.error('Could not find path to chrome.')
+ sys.exit(1)
+ chrome_info = 'with command `%s`' % chrome_path
+ else:
+ channel = args.channel
+ if sys.platform == 'linux2' and channel == 'canary':
+ channel = 'dev'
+ assert channel in ['stable', 'beta', 'dev', 'canary']
+
+ print 'Fetching the %s chrome binary via the binary_manager.' % channel
+ chrome_manager = binary_manager.BinaryManager([CHROME_BINARIES_CONFIG])
+ arch, os_name = dependency_util.GetOSAndArchForCurrentDesktopPlatform()
+ chrome_path, version = chrome_manager.FetchPathWithVersion(
+ 'chrome_%s' % channel, arch, os_name)
+ print 'Finished fetching the chrome binary to %s' % chrome_path
+ if xvfb.ShouldStartXvfb():
+ print 'Starting xvfb...'
+ xvfb_process = xvfb.StartXvfb()
+ chrome_info = 'version %s from channel %s' % (version, channel)
+ chrome_command = [
+ chrome_path,
+ '--user-data-dir=%s' % user_data_dir,
+ '--no-sandbox',
+ '--no-experiments',
+ '--no-first-run',
+ '--noerrdialogs',
+ '--window-size=1280,1024',
+ ('http://localhost:%s/%s/tests.html?' % (port, args.tests)) +
+ 'headless=true&testTypeToRun=all',
+ ]
+ print "Starting Chrome %s..." % chrome_info
+ chrome_process = subprocess.Popen(
+ chrome_command, stdout=sys.stdout, stderr=sys.stderr)
+ print 'chrome process command: %s' % ' '.join(chrome_command)
+ print "Waiting for tests to finish..."
+ server_out, server_err = server_process.communicate()
+ print "Killing Chrome..."
+ if sys.platform == 'win32':
+ # Use taskkill on Windows to make sure Chrome and all subprocesses are
+ # killed.
+ subprocess.call(['taskkill', '/F', '/T', '/PID', str(chrome_process.pid)])
+ else:
+ chrome_process.kill()
+ if server_process.returncode != 0:
+ logging.error('Tests failed!')
+ logging.error('Server stdout:\n%s', server_out)
+ logging.error('Server stderr:\n%s', server_err)
+ else:
+ print server_out
+ if args.presentation_json:
+ with open(args.presentation_json, 'w') as recipe_out:
+ # Add a link to the buildbot status for the step saying which version
+ # of Chrome the test ran on. The actual linking feature is not used,
+ # but there isn't a way to just add text.
+ link_name = 'Chrome Version %s' % version
+ presentation_info = {'links': {link_name: CHROME_CONFIG_URL}}
+ json.dump(presentation_info, recipe_out)
+ finally:
+ # Wait for Chrome to be killed before deleting temp Chrome dir. Only have
+ # this timing issue on Windows.
+ if sys.platform == 'win32':
+ time.sleep(5)
+ if tmpdir:
+ try:
+ shutil.rmtree(tmpdir)
+ shutil.rmtree(user_data_dir)
+ except OSError as e:
+ logging.error('Error cleaning up temp dirs %s and %s: %s',
+ tmpdir, user_data_dir, e)
+ if xvfb_process:
+ xvfb_process.kill()
+
+ sys.exit(server_process.returncode)
diff --git a/chromium/third_party/catapult/catapult_build/run_wct.py b/chromium/third_party/catapult/catapult_build/run_wct.py
new file mode 100644
index 00000000000..75c783367f9
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/run_wct.py
@@ -0,0 +1,31 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import subprocess
+import sys
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+_CATAPULT_PATH = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+_AddToPathIfNeeded(os.path.join(_CATAPULT_PATH, 'common', 'node_runner'))
+from node_runner import node_util # pylint: disable=wrong-import-position,import-error
+
+NODE_MODULES = node_util.GetNodeModulesPath()
+RUN_WCT = os.path.join(NODE_MODULES, 'chops-wct-runner', 'src', 'run-wct.js')
+
+
+def RunWct(base_dir, dep_dirs, debug=False, prefix=''):
+ command = [node_util.GetNodePath(), RUN_WCT]
+ command += ['--base', base_dir]
+ command += ['--prefix', prefix]
+ if debug:
+ command += ['--debug']
+ for dep in dep_dirs:
+ command += ['--dep', dep]
+ logging.info('Starting WCT: %r', command)
+ return subprocess.call(command)
diff --git a/chromium/third_party/catapult/catapult_build/run_with_typ.py b/chromium/third_party/catapult/catapult_build/run_with_typ.py
new file mode 100644
index 00000000000..b90398edfa1
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/run_with_typ.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A wrapper around typ (test your projects)."""
+
+import os
+import sys
+
+
+def Run(top_level_dir, path=None, suffixes=None):
+ """Runs a set of Python tests using typ.
+
+ Args:
+ top_level_dir: Directory to look for Python unit tests in.
+ path: A list of extra paths to add to sys.path when running the tests.
+
+ Returns:
+ An exit code (0 for success, otherwise non-zero).
+ """
+ if not suffixes:
+ suffixes = ['*_test.py', '*_unittest.py']
+ typ_path = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), os.path.pardir, 'third_party', 'typ'))
+ _AddToPathIfNeeded(typ_path)
+ import typ
+ return typ.main(
+ top_level_dir=top_level_dir,
+ path=(path or []),
+ coverage_source=[top_level_dir],
+ suffixes=suffixes)
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
diff --git a/chromium/third_party/catapult/catapult_build/temp_deployment_dir.py b/chromium/third_party/catapult/catapult_build/temp_deployment_dir.py
new file mode 100644
index 00000000000..92ad20f6a43
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/temp_deployment_dir.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import contextlib
+import os
+import shutil
+import tempfile
+
+
+@contextlib.contextmanager
+def TempDeploymentDir(paths, use_symlinks=True):
+ """Sets up and tears down a directory for deploying an app."""
+ if use_symlinks:
+ link_func = os.symlink
+ else:
+ link_func = _Copy
+
+ try:
+ deployment_dir = tempfile.mkdtemp(prefix='deploy-')
+ _PopulateDeploymentDir(deployment_dir, paths, link_func)
+ yield deployment_dir
+ finally:
+ shutil.rmtree(deployment_dir)
+
+
+def _Copy(src, dst):
+ if os.path.isdir(src):
+ shutil.copytree(src, dst)
+ else:
+ shutil.copy2(src, dst)
+
+
+def _PopulateDeploymentDir(deployment_dir, paths, link_func):
+ """Fills the deployment directory using the link_func specified."""
+ for path in paths:
+ destination = os.path.join(deployment_dir, os.path.basename(path))
+ link_func(path, destination)
diff --git a/chromium/third_party/catapult/catapult_build/test_runner.py b/chromium/third_party/catapult/catapult_build/test_runner.py
new file mode 100644
index 00000000000..d3286a8fdfe
--- /dev/null
+++ b/chromium/third_party/catapult/catapult_build/test_runner.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import subprocess
+import sys
+
+FAIL_EMOJI = u'\U0001F631'.encode('utf-8')
+PASS_EMOJI = u'\U0001F601'.encode('utf-8')
+
+GREEN = '\033[92m'
+RED = '\033[91m'
+END_CODE = '\033[0m'
+
+
+def _Color(s, color):
+ """Adds ANSI escape codes to color a string printed to the terminal."""
+ return color + s + END_CODE
+
+
+def _RunTest(test, chrome_command):
+ if sys.platform in test.get('disabled_platforms', {}):
+ return 0
+ command = [test['path']]
+ if sys.platform == 'win32':
+ command = ['python'] + command
+ if test.get('chrome_path_arg') and chrome_command:
+ command += ['--chrome_path', chrome_command]
+ try:
+ return subprocess.call(command)
+ except OSError:
+ return 1
+
+
+def Main(name, tests, argv):
+ parser = argparse.ArgumentParser(
+ description='Run all tests of %s project.' % name)
+ parser.add_argument(
+ '--chrome_path', type=str,
+ help='Path to Chrome browser binary for dev_server tests.')
+ args = parser.parse_args(argv[1:])
+
+ exit_code = 0
+ errors = []
+ for test in tests:
+ new_exit_code = _RunTest(test, args.chrome_path)
+ if new_exit_code != 0:
+ exit_code |= new_exit_code
+ errors += '%s failed some tests. Re-run %s script to see those.\n' % (
+ os.path.basename(test['path']), test['path'])
+
+ if exit_code:
+ print _Color('Oops! Some tests failed.', RED), FAIL_EMOJI
+ sys.stderr.writelines(errors)
+ else:
+ print _Color('Woho! All tests passed.', GREEN), PASS_EMOJI
+
+ sys.exit(exit_code)
diff --git a/chromium/third_party/catapult/common/OWNERS b/chromium/third_party/catapult/common/OWNERS
new file mode 100644
index 00000000000..f75c24ae194
--- /dev/null
+++ b/chromium/third_party/catapult/common/OWNERS
@@ -0,0 +1,4 @@
+dtu@chromium.org
+fmeawad@chromium.org
+simonhatch@chromium.org
+sullivan@chromium.org
diff --git a/chromium/third_party/catapult/common/bin/run_tests b/chromium/third_party/catapult/common/bin/run_tests
new file mode 100755
index 00000000000..3021755a4f4
--- /dev/null
+++ b/chromium/third_party/catapult/common/bin/run_tests
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+_CATAPULT_PATH = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..', '..'))
+
+_PY_UTILS_PATH = os.path.abspath(
+ os.path.join(_CATAPULT_PATH, 'common', 'py_utils'))
+
+
+def _RunTestsOrDie(top_level_dir):
+ exit_code = run_with_typ.Run(top_level_dir, path=[_PY_UTILS_PATH])
+ if exit_code:
+ sys.exit(exit_code)
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+if __name__ == '__main__':
+ _AddToPathIfNeeded(_CATAPULT_PATH)
+
+ from hooks import install
+ if '--no-install-hooks' in sys.argv:
+ sys.argv.remove('--no-install-hooks')
+ else:
+ install.InstallHooks()
+
+ from catapult_build import run_with_typ
+ _RunTestsOrDie(_PY_UTILS_PATH)
+ sys.exit(0)
diff --git a/chromium/third_party/catapult/common/bin/update_chrome_reference_binaries b/chromium/third_party/catapult/common/bin/update_chrome_reference_binaries
new file mode 100755
index 00000000000..02070f0849c
--- /dev/null
+++ b/chromium/third_party/catapult/common/bin/update_chrome_reference_binaries
@@ -0,0 +1,189 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Updates the Chrome reference builds.
+
+Usage:
+ $ /path/to/update_reference_build.py
+ $ git commit -a
+ $ git cl upload
+"""
+
+import collections
+import logging
+import os
+import shutil
+import subprocess
+import sys
+import urllib2
+import zipfile
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'py_utils'))
+
+from py_utils import cloud_storage
+from dependency_manager import base_config
+
+
+def BuildNotFoundError(error_string):
+ raise ValueError(error_string)
+
+
+_CHROME_BINARIES_CONFIG = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), '..', '..', 'common',
+ 'py_utils', 'py_utils', 'chrome_binaries.json')
+
+CHROME_GS_BUCKET = 'chrome-unsigned'
+
+
+# Remove a platform name from this list to disable updating it.
+# Add one to enable updating it. (Must also update _PLATFORM_MAP.)
+_PLATFORMS_TO_UPDATE = ['mac_x86_64', 'win_x86', 'win_AMD64', 'linux_x86_64',
+ 'android_k_armeabi-v7a', 'android_l_arm64-v8a',
+ 'android_l_armeabi-v7a', 'android_n_armeabi-v7a']
+
+# Remove a channal name from this list to disable updating it.
+# Add one to enable updating it.
+_CHANNELS_TO_UPDATE = ['stable', 'canary', 'dev']
+
+
+# Omaha is Chrome's autoupdate server. It reports the current versions used
+# by each platform on each channel.
+_OMAHA_PLATFORMS = { 'stable': ['mac', 'linux', 'win', 'android'],
+ 'dev': ['linux'], 'canary': ['mac', 'win']}
+
+
+# All of the information we need to update each platform.
+# omaha: name omaha uses for the plaftorms.
+# zip_name: name of the zip file to be retrieved from cloud storage.
+# gs_build: name of the Chrome build platform used in cloud storage.
+# destination: Name of the folder to download the reference build to.
+UpdateInfo = collections.namedtuple('UpdateInfo',
+ 'omaha, gs_folder, gs_build, zip_name')
+_PLATFORM_MAP = {'mac_x86_64': UpdateInfo(omaha='mac',
+ gs_folder='desktop-*',
+ gs_build='mac64',
+ zip_name='chrome-mac.zip'),
+ 'win_x86': UpdateInfo(omaha='win',
+ gs_folder='desktop-*',
+ gs_build='win-clang',
+ zip_name='chrome-win-clang.zip'),
+ 'win_AMD64': UpdateInfo(omaha='win',
+ gs_folder='desktop-*',
+ gs_build='win64-clang',
+ zip_name='chrome-win64-clang.zip'),
+ 'linux_x86_64': UpdateInfo(omaha='linux',
+ gs_folder='desktop-*',
+ gs_build='linux64',
+ zip_name='chrome-linux64.zip'),
+ 'android_k_armeabi-v7a': UpdateInfo(omaha='android',
+ gs_folder='android-*',
+ gs_build='arm',
+ zip_name='Chrome.apk'),
+ 'android_l_arm64-v8a': UpdateInfo(omaha='android',
+ gs_folder='android-*',
+ gs_build='arm_64',
+ zip_name='ChromeModern.apk'),
+ 'android_l_armeabi-v7a': UpdateInfo(omaha='android',
+ gs_folder='android-*',
+ gs_build='arm',
+ zip_name='Chrome.apk'),
+ 'android_n_armeabi-v7a': UpdateInfo(omaha='android',
+ gs_folder='android-*',
+ gs_build='arm',
+ zip_name='Monochrome.apk'),
+
+}
+
+
+def _ChannelVersionsMap(channel):
+ rows = _OmahaReportVersionInfo(channel)
+ omaha_versions_map = _OmahaVersionsMap(rows, channel)
+ channel_versions_map = {}
+ for platform in _PLATFORMS_TO_UPDATE:
+ omaha_platform = _PLATFORM_MAP[platform].omaha
+ if omaha_platform in omaha_versions_map:
+ channel_versions_map[platform] = omaha_versions_map[omaha_platform]
+ return channel_versions_map
+
+
+def _OmahaReportVersionInfo(channel):
+ url ='https://omahaproxy.appspot.com/all?channel=%s' % channel
+ lines = urllib2.urlopen(url).readlines()
+ return [l.split(',') for l in lines]
+
+
+def _OmahaVersionsMap(rows, channel):
+ platforms = _OMAHA_PLATFORMS.get(channel, [])
+ if (len(rows) < 1 or
+ not rows[0][0:3] == ['os', 'channel', 'current_version']):
+ raise ValueError(
+ 'Omaha report is not in the expected form: %s.' % rows)
+ versions_map = {}
+ for row in rows[1:]:
+ if row[1] != channel:
+ raise ValueError(
+ 'Omaha report contains a line with the channel %s' % row[1])
+ if row[0] in platforms:
+ versions_map[row[0]] = row[2]
+ logging.warn('versions map: %s' % versions_map)
+ if not all(platform in versions_map for platform in platforms):
+ raise ValueError(
+ 'Omaha report did not contain all desired platforms for channel %s' % channel)
+ return versions_map
+
+
+def _QueuePlatformUpdate(platform, version, config, channel):
+ """ platform: the name of the platform for the browser to
+ be downloaded & updated from cloud storage. """
+ platform_info = _PLATFORM_MAP[platform]
+ filename = platform_info.zip_name
+ # remote_path example: desktop-*/30.0.1595.0/precise32/chrome-precise32.zip
+ remote_path = '%s/%s/%s/%s' % (
+ platform_info.gs_folder, version, platform_info.gs_build, filename)
+ if not cloud_storage.Exists(CHROME_GS_BUCKET, remote_path):
+ cloud_storage_path = 'gs://%s/%s' % (CHROME_GS_BUCKET, remote_path)
+ raise BuildNotFoundError(
+ 'Failed to find %s build for version %s at path %s.' % (
+ platform, version, cloud_storage_path))
+ reference_builds_folder = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), 'chrome_telemetry_build',
+ 'reference_builds', channel)
+ if not os.path.exists(reference_builds_folder):
+ os.makedirs(reference_builds_folder)
+ local_dest_path = os.path.join(reference_builds_folder, filename)
+ cloud_storage.Get(CHROME_GS_BUCKET, remote_path, local_dest_path)
+ config.AddCloudStorageDependencyUpdateJob(
+ 'chrome_%s' % channel, platform, local_dest_path, version=version,
+ execute_job=False)
+
+
+def UpdateBuilds():
+ config = base_config.BaseConfig(_CHROME_BINARIES_CONFIG, writable=True)
+ for channel in _CHANNELS_TO_UPDATE:
+ channel_versions_map = _ChannelVersionsMap(channel)
+ for platform in channel_versions_map:
+ print 'Downloading Chrome (%s channel) on %s' % (channel, platform)
+ current_version = config.GetVersion('chrome_%s' % channel, platform)
+ channel_version = channel_versions_map.get(platform)
+ print 'current: %s, channel: %s' % (current_version, channel_version)
+ if current_version and current_version == channel_version:
+ continue
+ _QueuePlatformUpdate(platform, channel_version, config, channel)
+ # TODO: move execute update jobs here, and add committing/uploading the cl.
+
+ print 'Updating chrome builds with downloaded binaries'
+ config.ExecuteUpdateJobs(force=True)
+
+
+def main():
+ logging.getLogger().setLevel(logging.DEBUG)
+ #TODO(aiolos): alert sheriffs via email when an error is seen.
+ #This should be added when alerts are added when updating the build.
+ UpdateBuilds()
+ # TODO(aiolos): Add --commit flag. crbug.com/547229
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/common/eslint/LICENSE b/chromium/third_party/catapult/common/eslint/LICENSE
new file mode 100644
index 00000000000..f9434474db2
--- /dev/null
+++ b/chromium/third_party/catapult/common/eslint/LICENSE
@@ -0,0 +1,20 @@
+ESLint
+Copyright jQuery Foundation and other contributors, https://jquery.org/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. \ No newline at end of file
diff --git a/chromium/third_party/catapult/common/eslint/OWNERS b/chromium/third_party/catapult/common/eslint/OWNERS
new file mode 100644
index 00000000000..731c5c6a99a
--- /dev/null
+++ b/chromium/third_party/catapult/common/eslint/OWNERS
@@ -0,0 +1 @@
+charliea@chromium.org
diff --git a/chromium/third_party/catapult/common/eslint/README.md b/chromium/third_party/catapult/common/eslint/README.md
new file mode 100644
index 00000000000..8ba5b6324c9
--- /dev/null
+++ b/chromium/third_party/catapult/common/eslint/README.md
@@ -0,0 +1,5 @@
+This directory contains the Catapult eslint config, custom Catapult eslint rules,
+and tests for those rules.
+
+Some of our custom rules are modified versions of those included with eslint, as
+suggested in https://goo.gl/uAxFHq.
diff --git a/chromium/third_party/catapult/common/eslint/bin/run_eslint b/chromium/third_party/catapult/common/eslint/bin/run_eslint
new file mode 100755
index 00000000000..933415be67b
--- /dev/null
+++ b/chromium/third_party/catapult/common/eslint/bin/run_eslint
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import sys
+
+
+_CATAPULT_PATH = os.path.abspath(
+ os.path.join(os.path.dirname(__file__),
+ os.path.pardir, os.path.pardir, os.path.pardir))
+
+
+_ESLINT_PATH = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), os.path.pardir))
+
+
+DIRECTORIES_TO_LINT = [
+ os.path.join(_CATAPULT_PATH, 'dashboard', 'dashboard'),
+ os.path.join(_CATAPULT_PATH, 'tracing', 'tracing')
+]
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+if __name__ == '__main__':
+ _AddToPathIfNeeded(_ESLINT_PATH)
+ import eslint
+
+ parser = argparse.ArgumentParser(
+ description='Wrapper script to run eslint on Catapult code')
+ parser.add_argument('--paths', '-p', default=None, nargs='+', metavar='PATH',
+ help='List of paths to lint')
+ parser.add_argument('--all', default=None, action='store_true',
+ help='Runs eslint on all applicable Catapult code')
+ parser.add_argument('--extra-args', default=None, type=str,
+ help='A string of extra arguments to pass to eslint')
+
+ args = parser.parse_args(sys.argv[1:])
+ if ((args.paths is not None and args.all is not None) or
+ (args.paths is None and args.all is None)):
+ print 'Either --paths or --all must be used, but not both.\n'
+ parser.print_help()
+ sys.exit(1)
+
+ paths = DIRECTORIES_TO_LINT if args.all else args.paths
+ success, output = eslint.RunEslint(paths, extra_args=args.extra_args)
+ print output
+ sys.exit(not success)
diff --git a/chromium/third_party/catapult/common/eslint/bin/run_tests b/chromium/third_party/catapult/common/eslint/bin/run_tests
new file mode 100755
index 00000000000..db1067913d7
--- /dev/null
+++ b/chromium/third_party/catapult/common/eslint/bin/run_tests
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+
+_CATAPULT_PATH = os.path.abspath(
+ os.path.join(os.path.dirname(__file__),
+ os.path.pardir, os.path.pardir, os.path.pardir))
+
+
+_ESLINT_PATH = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), os.path.pardir))
+
+
+def _RunTestsOrDie(top_level_dir):
+ exit_code = run_with_typ.Run(top_level_dir, path=[_ESLINT_PATH])
+ if exit_code:
+ sys.exit(exit_code)
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+if __name__ == '__main__':
+ _AddToPathIfNeeded(_CATAPULT_PATH)
+
+ from catapult_build import run_with_typ
+
+ _RunTestsOrDie(os.path.join(_ESLINT_PATH, 'eslint'))
diff --git a/chromium/third_party/catapult/common/eslint/eslint/__init__.py b/chromium/third_party/catapult/common/eslint/eslint/__init__.py
new file mode 100644
index 00000000000..082178a28c9
--- /dev/null
+++ b/chromium/third_party/catapult/common/eslint/eslint/__init__.py
@@ -0,0 +1,68 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import sys
+
+
+_CATAPULT_PATH = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ os.path.pardir, os.path.pardir, os.path.pardir)
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+def _UpdateSysPathIfNeeded():
+ _AddToPathIfNeeded(os.path.join(_CATAPULT_PATH, 'common', 'node_runner'))
+ _AddToPathIfNeeded(os.path.join(_CATAPULT_PATH, 'common', 'py_utils'))
+
+
+_UpdateSysPathIfNeeded()
+
+
+import py_utils
+from node_runner import node_util
+
+
+BASE_ESLINT_CMD = [
+ node_util.GetNodePath(),
+ os.path.join(node_util.GetNodeModulesPath(), 'eslint', 'bin', 'eslint.js'),
+ '--color'
+]
+
+
+DEFAULT_ESLINT_RULES_DIR = os.path.join(
+ py_utils.GetCatapultDir(), 'common', 'eslint', 'rules')
+
+
+def _CreateEslintCommand(rulesdir, extra_args):
+ eslint_cmd = BASE_ESLINT_CMD + [
+ '--rulesdir', rulesdir, '--ext', '.js,.html'
+ ]
+ if extra_args:
+ eslint_cmd.extend(extra_args.strip().split(' '))
+ return eslint_cmd
+
+
+def RunEslint(paths, rules_dir=DEFAULT_ESLINT_RULES_DIR, extra_args=None):
+ """Runs eslint on a list of paths.
+
+ Args:
+ paths: A list of paths to run eslint on.
+ rules_dir: A directory of custom eslint rules.
+ extra_args: A string to append to the end of the eslint command.
+ """
+ if type(paths) is not list or len(paths) == 0:
+ raise ValueError('Must specify a non-empty list of paths to lint.')
+
+ try:
+ eslint_cmd = _CreateEslintCommand(rules_dir, extra_args)
+ return True, subprocess.check_output(eslint_cmd + paths,
+ stderr=subprocess.STDOUT).rstrip()
+ except subprocess.CalledProcessError as e:
+ return False, e.output.rstrip()
diff --git a/chromium/third_party/catapult/common/eslint/eslint/smoke_test.py b/chromium/third_party/catapult/common/eslint/eslint/smoke_test.py
new file mode 100644
index 00000000000..9a0f442488d
--- /dev/null
+++ b/chromium/third_party/catapult/common/eslint/eslint/smoke_test.py
@@ -0,0 +1,36 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import eslint
+import os
+import tempfile
+import unittest
+
+
+_TEMP_FILE_CONTENTS = '''<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<script>
+// This should cause a linter error because we require camelCase.
+var non_camel_case = 0;
+</script>
+'''
+
+
+class SmokeTest(unittest.TestCase):
+ def testEslintFindsError(self):
+ try:
+ tmp_file = tempfile.NamedTemporaryFile(
+ delete=False, dir=os.path.dirname(__file__), suffix=".html")
+ tmp_file.write(_TEMP_FILE_CONTENTS)
+ tmp_file.close()
+
+ success, output = eslint.RunEslint([tmp_file.name])
+ self.assertFalse(success)
+ self.assertTrue('is not in camel case' in output)
+ finally:
+ os.remove(tmp_file.name)
diff --git a/chromium/third_party/catapult/common/eslint/rules/catapult-camelcase.js b/chromium/third_party/catapult/common/eslint/rules/catapult-camelcase.js
new file mode 100644
index 00000000000..bf3105218b2
--- /dev/null
+++ b/chromium/third_party/catapult/common/eslint/rules/catapult-camelcase.js
@@ -0,0 +1,154 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+/* eslint-disable */
+
+/**
+ * @fileoverview Rule to flag non-camelcased identifiers
+ * @author Nicholas C. Zakas
+ */
+
+'use strict';
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce Catapult camelcase naming convention",
+ category: "Stylistic Issues",
+ recommended: false
+ },
+
+ schema: [
+ {
+ type: "object",
+ properties: {
+ properties: {
+ enum: ["always", "never"]
+ }
+ },
+ additionalProperties: false
+ }
+ ]
+ },
+
+ create(context) {
+
+ //--------------------------------------------------------------------------
+ // Helpers
+ //--------------------------------------------------------------------------
+
+ // contains reported nodes to avoid reporting twice on destructuring with shorthand notation
+ var reported = [];
+
+ /**
+ * Checks if a string contains an underscore and isn't all upper-case
+ * @param {string} name The string to check.
+ * @returns {boolean} if the string is underscored
+ * @private
+ */
+ function isUnderscored(name) {
+
+ // if there's an underscore, it might be A_VARANT, which is okay
+ return name.indexOf("_") > -1 && name !== name.toUpperCase();
+ }
+
+ /**
+ * Reports an AST node as a rule violation.
+ * @param {ASTNode} node The node to report.
+ * @returns {void}
+ * @private
+ */
+ function report(node) {
+ if (reported.indexOf(node) < 0) {
+ reported.push(node);
+ context.report(node, "Identifier '{{name}}' is not in camel case.", { name: node.name });
+ }
+ }
+
+ var options = context.options[0] || {};
+ let properties = options.properties || "";
+
+ if (properties !== "always" && properties !== "never") {
+ properties = "always";
+ }
+
+ return {
+
+ Identifier(node) {
+
+ /*
+ * Leading and trailing underscores are commonly used to flag
+ * private/protected identifiers, strip them.
+ *
+ * NOTE: This has four Catapult-specific style exceptions:
+ *
+ * - The prefix opt_
+ * - The prefix g_
+ * - The suffix _smallerIsBetter
+ * - The suffix _biggerIsBetter
+ */
+ var name = node.name.replace(/(?:^opt_)|^(?:^g_)|^_+|_+$|(?:_smallerIsBetter)$|(?:_biggerIsBetter)$/g, ""),
+ effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
+
+ // MemberExpressions get special rules
+ if (node.parent.type === "MemberExpression") {
+
+ // "never" check properties
+ if (properties === "never") {
+ return;
+ }
+
+ // Always report underscored object names
+ if (node.parent.object.type === "Identifier" &&
+ node.parent.object.name === node.name &&
+ isUnderscored(name)) {
+ report(node);
+
+ // Report AssignmentExpressions only if they are the left side of the assignment
+ } else if (effectiveParent.type === "AssignmentExpression" &&
+ isUnderscored(name) &&
+ (effectiveParent.right.type !== "MemberExpression" ||
+ effectiveParent.left.type === "MemberExpression" &&
+ effectiveParent.left.property.name === node.name)) {
+ report(node);
+ }
+
+ // Properties have their own rules
+ } else if (node.parent.type === "Property") {
+
+ // "never" check properties
+ if (properties === "never") {
+ return;
+ }
+
+ if (node.parent.parent && node.parent.parent.type === "ObjectPattern" &&
+ node.parent.key === node && node.parent.value !== node) {
+ return;
+ }
+
+ if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {
+ report(node);
+ }
+
+ // Check if it's an import specifier
+ } else if (["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"].indexOf(node.parent.type) >= 0) {
+
+ // Report only if the local imported identifier is underscored
+ if (node.parent.local && node.parent.local.name === node.name && isUnderscored(name)) {
+ report(node);
+ }
+
+ // Report anything that is underscored that isn't a CallExpression
+ } else if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {
+ report(node);
+ }
+ }
+
+ };
+
+ }
+};
diff --git a/chromium/third_party/catapult/common/lab/commits.py b/chromium/third_party/catapult/common/lab/commits.py
new file mode 100755
index 00000000000..6d47b9166e3
--- /dev/null
+++ b/chromium/third_party/catapult/common/lab/commits.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Print statistics about the rate of commits to a repository."""
+
+import datetime
+import itertools
+import json
+import math
+import urllib
+import urllib2
+
+
+_BASE_URL = 'https://chromium.googlesource.com'
+# Can be up to 10,000.
+_REVISION_COUNT = 10000
+
+_REPOSITORIES = [
+ 'chromium/src',
+ 'angle/angle',
+ 'skia',
+ 'v8/v8',
+]
+
+
+def Pairwise(iterable):
+ """s -> (s0,s1), (s1,s2), (s2, s3), ..."""
+ a, b = itertools.tee(iterable)
+ next(b, None)
+ return itertools.izip(a, b)
+
+
+def Percentile(data, percentile):
+ """Find a percentile of a list of values.
+
+ Parameters:
+ data: A sorted list of values.
+ percentile: The percentile to look up, from 0.0 to 1.0.
+
+ Returns:
+ The percentile.
+
+ Raises:
+ ValueError: If data is empty.
+ """
+ if not data:
+ raise ValueError()
+
+ k = (len(data) - 1) * percentile
+ f = math.floor(k)
+ c = math.ceil(k)
+
+ if f == c:
+ return data[int(k)]
+ return data[int(f)] * (c - k) + data[int(c)] * (k - f)
+
+
+def CommitTimes(repository, revision_count):
+ parameters = urllib.urlencode((('n', revision_count), ('format', 'JSON')))
+ url = '%s/%s/+log?%s' % (_BASE_URL, urllib.quote(repository), parameters)
+ data = json.loads(''.join(urllib2.urlopen(url).read().splitlines()[1:]))
+
+ commit_times = []
+ for revision in data['log']:
+ commit_time_string = revision['committer']['time']
+ commit_time = datetime.datetime.strptime(
+ commit_time_string, '%a %b %d %H:%M:%S %Y')
+ commit_times.append(commit_time - datetime.timedelta(hours=7))
+
+ return commit_times
+
+
+def IsWeekday(time):
+ return time.weekday() >= 0 and time.weekday() < 5
+
+
+def main():
+ for repository in _REPOSITORIES:
+ commit_times = CommitTimes(repository, _REVISION_COUNT)
+
+ commit_durations = []
+ for time1, time2 in Pairwise(commit_times):
+ #if not (IsWeekday(time1) and IsWeekday(time2)):
+ # continue
+ commit_durations.append((time1 - time2).total_seconds() / 60.)
+ commit_durations.sort()
+
+ print 'REPOSITORY:', repository
+ print 'Start Date:', min(commit_times), 'PDT'
+ print ' End Date:', max(commit_times), 'PDT'
+ print ' Duration:', max(commit_times) - min(commit_times)
+ print ' n:', len(commit_times)
+
+ for p in (0.25, 0.50, 0.90):
+ percentile = Percentile(commit_durations, p)
+ print '%3d%% commit duration:' % (p * 100), '%6.1fm' % percentile
+ mean = math.fsum(commit_durations) / len(commit_durations)
+ print 'Mean commit duration:', '%6.1fm' % mean
+ print
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/common/lab/hardware.py b/chromium/third_party/catapult/common/lab/hardware.py
new file mode 100755
index 00000000000..5e49c5c86ba
--- /dev/null
+++ b/chromium/third_party/catapult/common/lab/hardware.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Query build slave hardware info, and print it to stdout as csv."""
+
+import csv
+import json
+import logging
+import sys
+import urllib2
+
+
+_MASTERS = [
+ 'chromium.perf',
+ 'chromium.perf.fyi',
+ 'client.catapult',
+ 'tryserver.chromium.perf',
+ 'tryserver.client.catapult',
+]
+
+
+_KEYS = [
+ 'master', 'builder', 'hostname',
+
+ 'os family', 'os version', 'bitness (userland)',
+
+ 'product name', 'architecture', 'processor count', 'processor type',
+ 'memory total',
+
+ 'facter version', 'git version', 'puppet version', 'python version',
+ 'ruby version',
+
+ 'android device 1', 'android device 2', 'android device 3',
+ 'android device 4', 'android device 5', 'android device 6',
+ 'android device 7', 'android device 8',
+]
+_EXCLUDED_KEYS = frozenset([
+ 'architecture (userland)',
+ 'b directory',
+ 'last puppet run',
+ 'uptime',
+ 'windows version',
+])
+
+
+def main():
+ writer = csv.DictWriter(sys.stdout, _KEYS)
+ writer.writeheader()
+
+ for master_name in _MASTERS:
+ master_data = json.load(urllib2.urlopen(
+ 'http://build.chromium.org/p/%s/json/slaves' % master_name))
+
+ slaves = sorted(master_data.iteritems(),
+ key=lambda x: (x[1]['builders'].keys(), x[0]))
+ for slave_name, slave_data in slaves:
+ for builder_name in slave_data['builders']:
+ row = {
+ 'master': master_name,
+ 'builder': builder_name,
+ 'hostname': slave_name,
+ }
+
+ host_data = slave_data['host']
+ if host_data:
+ host_data = host_data.splitlines()
+ if len(host_data) > 1:
+ for line in host_data:
+ if not line:
+ continue
+ key, value = line.split(': ')
+ if key in _EXCLUDED_KEYS:
+ continue
+ row[key] = value
+
+ # Munge keys.
+ row = {key.replace('_', ' '): value for key, value in row.iteritems()}
+ if 'osfamily' in row:
+ row['os family'] = row.pop('osfamily')
+ if 'product name' not in row and slave_name.startswith('slave'):
+ row['product name'] = 'Google Compute Engine'
+
+ try:
+ writer.writerow(row)
+ except ValueError:
+ logging.error(row)
+ raise
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/common/lab/keychain_unlock.sh b/chromium/third_party/catapult/common/lab/keychain_unlock.sh
new file mode 100755
index 00000000000..e550f8d813d
--- /dev/null
+++ b/chromium/third_party/catapult/common/lab/keychain_unlock.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Script to SSH into a list of bots and set up their keychains for Telemetry.
+# https://www.chromium.org/developers/telemetry/telemetry-mac-keychain-setup
+
+for hostname in "$@"
+do
+ ssh -t "$hostname" 'security unlock-keychain login.keychain
+security delete-generic-password -s "Chrome Safe Storage" login.keychain
+security add-generic-password -a Chrome -w "+NTclOvR4wLMgRlLIL9bHQ==" \
+ -s "Chrome Safe Storage" -A login.keychain'
+done
diff --git a/chromium/third_party/catapult/common/node_runner/node_runner/README.md b/chromium/third_party/catapult/common/node_runner/node_runner/README.md
new file mode 100644
index 00000000000..47c85ba4bcd
--- /dev/null
+++ b/chromium/third_party/catapult/common/node_runner/node_runner/README.md
@@ -0,0 +1,11 @@
+Update binaries:
+
+1. Download archives pre-compiled binaries.
+2. Unzip archives.
+3. Re-zip just the binary:
+ `zip new.zip node-v10.14.1-linux-x64/bin/node`
+4. Use the update script:
+ `./dependency_manager/bin/update --config
+ common/node_runner/node_runner/node_binaries.json --dependency node --path
+ new.zip --platform linux_x86_64`
+5. Mail out the automated change to `node_binaries.json` for review and CQ.
diff --git a/chromium/third_party/catapult/common/node_runner/node_runner/__init__.py b/chromium/third_party/catapult/common/node_runner/node_runner/__init__.py
new file mode 100644
index 00000000000..ce33e059a6e
--- /dev/null
+++ b/chromium/third_party/catapult/common/node_runner/node_runner/__init__.py
@@ -0,0 +1,4 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
diff --git a/chromium/third_party/catapult/common/node_runner/node_runner/minify b/chromium/third_party/catapult/common/node_runner/node_runner/minify
new file mode 100755
index 00000000000..a5a24cf2020
--- /dev/null
+++ b/chromium/third_party/catapult/common/node_runner/node_runner/minify
@@ -0,0 +1,53 @@
+#!/usr/bin/env node
+'use strict';
+/*
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+
+This script wraps common HTML transformations including stripping whitespace and
+comments from HTML, CSS, and Javascript.
+*/
+const dom5 = require('dom5');
+const escodegen = require('escodegen');
+const espree = require('espree');
+const fs = require('fs');
+const nopt = require('nopt');
+
+const args = nopt();
+const filename = args.argv.remain[0];
+
+let html = fs.readFileSync(filename).toString('utf8');
+let parsedHtml = dom5.parse(html);
+// First, collapse text nodes around comments (by removing comment nodes,
+// re-serializing, and re-parsing) in order to prevent multiple extraneous
+// newlines.
+for (const node of dom5.nodeWalkAll(parsedHtml, () => true)) {
+ if (dom5.isCommentNode(node)) {
+ dom5.remove(node);
+ }
+}
+html = dom5.serialize(parsedHtml);
+parsedHtml = dom5.parse(html);
+// Some of these transformations are based on polyclean:
+// https://github.com/googlearchive/polyclean
+for (const node of dom5.nodeWalkAll(parsedHtml, () => true)) {
+ if (dom5.isTextNode(node)) {
+ dom5.setTextContent(node, dom5.getTextContent(node)
+ .replace(/ *\n+ */g, '\n')
+ .replace(/\n+/g, '\n'));
+ } else if (dom5.predicates.hasTagName('script')(node) &&
+ !dom5.predicates.hasAttr('src')(node)) {
+ let text = dom5.getTextContent(node);
+ const ast = espree.parse(text, {ecmaVersion: 2018});
+ text = escodegen.generate(ast, {format: {indent: {style: ''}}});
+ dom5.setTextContent(node, text);
+ } else if (dom5.predicates.hasTagName('style')(node)) {
+ dom5.setTextContent(node, dom5.getTextContent(node)
+ .replace(/[\r\n]/g, '')
+ .replace(/ {2,}/g, ' ')
+ .replace(/(^|[;,\:\{\}]) /g, '$1')
+ .replace(/ ($|[;,\{\}])/g, '$1'));
+ }
+}
+fs.writeFileSync(filename, dom5.serialize(parsedHtml));
diff --git a/chromium/third_party/catapult/common/node_runner/node_runner/node_binaries.json b/chromium/third_party/catapult/common/node_runner/node_runner/node_binaries.json
new file mode 100644
index 00000000000..3a17db02dc0
--- /dev/null
+++ b/chromium/third_party/catapult/common/node_runner/node_runner/node_binaries.json
@@ -0,0 +1,53 @@
+{
+ "config_type": "BaseConfig",
+ "dependencies": {
+ "node": {
+ "cloud_storage_base_folder": "binary_dependencies",
+ "cloud_storage_bucket": "chromium-telemetry",
+ "file_info": {
+ "linux_x86_64": {
+ "cloud_storage_hash": "27ad092b0ce59d2da32090a00f717f0c31e65240",
+ "download_path": "bin/node/node-linux64.zip",
+ "path_within_archive": "node-v10.14.1-linux-x64/bin/node",
+ "version_in_cs": "6.7.0"
+ },
+ "mac_x86_64": {
+ "cloud_storage_hash": "1af7c221e530165af8a6ab8ff7ccb1f2dd54036d",
+ "download_path": "bin/node/node-mac64.zip",
+ "path_within_archive": "node-v6.7.0-darwin-x64/bin/node",
+ "version_in_cs": "6.7.0"
+ },
+ "win_AMD64": {
+ "cloud_storage_hash": "23f21bfb2edf874a8b6bdb6c1acb408bc7edeced",
+ "download_path": "bin/node/node-win64.zip",
+ "path_within_archive": "node-v6.7.0-win-x64/node.exe",
+ "version_in_cs": "6.7.0"
+ }
+ }
+ },
+ "npm": {
+ "cloud_storage_base_folder": "binary_dependencies",
+ "cloud_storage_bucket": "chromium-telemetry",
+ "file_info": {
+ "linux_x86_64": {
+ "cloud_storage_hash": "5750e968975e7f5ab8cb694f5e92a34a890e129d",
+ "download_path": "bin/node/node-linux64.zip",
+ "path_within_archive": "node-v6.7.0-linux-x64/lib/node_modules/npm/bin/npm-cli.js",
+ "version_in_cs": "6.7.0"
+ },
+ "mac_x86_64": {
+ "cloud_storage_hash": "1af7c221e530165af8a6ab8ff7ccb1f2dd54036d",
+ "download_path": "bin/node/node-mac64.zip",
+ "path_within_archive": "node-v6.7.0-darwin-x64/lib/node_modules/npm/bin/npm-cli.js",
+ "version_in_cs": "6.7.0"
+ },
+ "win_AMD64": {
+ "cloud_storage_hash": "23f21bfb2edf874a8b6bdb6c1acb408bc7edeced",
+ "download_path": "bin/node/node-win64.zip",
+ "path_within_archive": "node-v6.7.0-win-x64\\node_modules\\npm\\bin\\npm-cli.js",
+ "version_in_cs": "6.7.0"
+ }
+ }
+ }
+ }
+}
diff --git a/chromium/third_party/catapult/common/node_runner/node_runner/node_util.py b/chromium/third_party/catapult/common/node_runner/node_runner/node_util.py
new file mode 100644
index 00000000000..05d0084bb6a
--- /dev/null
+++ b/chromium/third_party/catapult/common/node_runner/node_runner/node_util.py
@@ -0,0 +1,60 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import sys
+
+import py_utils
+from py_utils import binary_manager
+from py_utils import dependency_util
+
+
+def _NodeBinariesConfigPath():
+ return os.path.realpath(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), 'node_binaries.json'))
+
+
+class _NodeManager(object):
+ def __init__(self):
+ self.bm = binary_manager.BinaryManager(
+ [_NodeBinariesConfigPath()])
+ self.os_name = dependency_util.GetOSNameForCurrentDesktopPlatform()
+ self.arch_name = dependency_util.GetArchForCurrentDesktopPlatform(
+ self.os_name)
+ self.node_path = self.bm.FetchPath('node', self.os_name, self.arch_name)
+ self.npm_path = self.bm.FetchPath('npm', self.os_name, self.arch_name)
+
+ self.node_initialized = False
+
+ def InitNode(self):
+ if self.node_initialized:
+ return # So we only init once per run
+ self.node_initialized = True
+ old_dir = os.path.abspath(os.curdir)
+ os.chdir(os.path.join(os.path.abspath(
+ py_utils.GetCatapultDir()), 'common', 'node_runner', 'node_runner'))
+ subprocess.call([self.node_path, self.npm_path, 'install'])
+ os.chdir(old_dir)
+
+
+_NODE_MANAGER = _NodeManager()
+
+
+def InitNode():
+ _NODE_MANAGER.InitNode()
+
+
+def GetNodePath():
+ return _NODE_MANAGER.node_path
+
+
+def GetNodeModulesPath():
+ _NODE_MANAGER.InitNode()
+ path = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ 'node_modules'))
+ if sys.platform.startswith('win'):
+ # Escape path on Windows because it's very long and must be passed to NTFS.
+ path = u'\\\\?\\' + path
+ return path
diff --git a/chromium/third_party/catapult/common/node_runner/node_runner/package-lock.json b/chromium/third_party/catapult/common/node_runner/node_runner/package-lock.json
new file mode 100644
index 00000000000..f623716dfbb
--- /dev/null
+++ b/chromium/third_party/catapult/common/node_runner/node_runner/package-lock.json
@@ -0,0 +1,5915 @@
+{
+ "name": "catapult_base",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@popeindustries/lit-html-server": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@popeindustries/lit-html-server/-/lit-html-server-0.13.0.tgz",
+ "integrity": "sha512-Ne/0scb5kPkCNu/OA7sSDcsypT8QtAMYmSuUyz31i8fbSb2i8Ib/UEEQ6lN4tG2zBztpMrVv5fanUQ+6Ab0Xlg==",
+ "requires": {
+ "get-stream": "^4.1.0",
+ "he": "^1.2.0",
+ "readable-stream": "^3.0.6"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "readable-stream": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.0.tgz",
+ "integrity": "sha512-vpydAvIJvPODZNagCPuHG87O9JNPtvFEtjHHRVwNVsVVRBqemvPJkc2SYbxJsiZXawJdtZNmkmnsPuE3IgsG0A==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "@types/clone": {
+ "version": "0.1.30",
+ "resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz",
+ "integrity": "sha1-5zZWSMG0ITalnH1QQGN7O1yDthQ="
+ },
+ "@types/node": {
+ "version": "4.2.23",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-4.2.23.tgz",
+ "integrity": "sha1-kkHwDWTrkQhPaDZ3Ru8Q1fsvL8Q="
+ },
+ "@types/parse5": {
+ "version": "0.0.31",
+ "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-0.0.31.tgz",
+ "integrity": "sha1-6Cekk6RDsVbhtYKi5MO9wAQPLuc=",
+ "requires": {
+ "@types/node": "6.0.*"
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "6.0.116",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.116.tgz",
+ "integrity": "sha1-L5zWK07MSSfjlC4mVcGC7s9bRfE="
+ }
+ }
+ },
+ "@webassemblyjs/ast": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.10.tgz",
+ "integrity": "sha1-DPxh1hKGJAty/FIst1VhNpnupAo=",
+ "requires": {
+ "@webassemblyjs/helper-module-context": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/wast-parser": "1.7.10"
+ }
+ },
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.10.tgz",
+ "integrity": "sha1-7mPXKcYxGoWGPjaaRz+Zg/mE5Nk="
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.10.tgz",
+ "integrity": "sha1-v8s7vll3U1dHV5CirXsonwmy8Zg="
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.10.tgz",
+ "integrity": "sha1-CoxiTGetCyFNLgA4WZIaGYjLFRs="
+ },
+ "@webassemblyjs/helper-code-frame": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.10.tgz",
+ "integrity": "sha1-CrfiL60CQaFzF4xzl2/A7fUIMs4=",
+ "requires": {
+ "@webassemblyjs/wast-printer": "1.7.10"
+ }
+ },
+ "@webassemblyjs/helper-fsm": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.10.tgz",
+ "integrity": "sha1-CRXncT+7tzViCp0+T6PXlR+XrGQ="
+ },
+ "@webassemblyjs/helper-module-context": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.10.tgz",
+ "integrity": "sha1-m+uD9ydA9ayAdTE7XKxeeWUQ91U="
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.10.tgz",
+ "integrity": "sha1-eXsec0u8/eqDmWac3FgwjvHH/8A="
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.10.tgz",
+ "integrity": "sha1-wOo3A8YV17w+NQfDt5kch2ey8g4=",
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-buffer": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/wasm-gen": "1.7.10"
+ }
+ },
+ "@webassemblyjs/ieee754": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.10.tgz",
+ "integrity": "sha1-YsFyi37w9m74Ih4pZqCv1120MN8=",
+ "requires": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "@webassemblyjs/leb128": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.10.tgz",
+ "integrity": "sha1-Fn4LtLBtdwFYV3KnP7qfTfhUOfY=",
+ "requires": {
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.10.tgz",
+ "integrity": "sha1-tnKPW29QNkq8FVvgKflnDmaFYFo="
+ },
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.10.tgz",
+ "integrity": "sha1-g/4xQPWlj1owuRRwK+nw5Zo5kJI=",
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-buffer": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/helper-wasm-section": "1.7.10",
+ "@webassemblyjs/wasm-gen": "1.7.10",
+ "@webassemblyjs/wasm-opt": "1.7.10",
+ "@webassemblyjs/wasm-parser": "1.7.10",
+ "@webassemblyjs/wast-printer": "1.7.10"
+ }
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.10.tgz",
+ "integrity": "sha1-TeADgGrinJerNwd4JGm1MplXAXQ=",
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/ieee754": "1.7.10",
+ "@webassemblyjs/leb128": "1.7.10",
+ "@webassemblyjs/utf8": "1.7.10"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.10.tgz",
+ "integrity": "sha1-0VHjFhGTSlVsgnif3uxBqBSZPCo=",
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-buffer": "1.7.10",
+ "@webassemblyjs/wasm-gen": "1.7.10",
+ "@webassemblyjs/wasm-parser": "1.7.10"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.10.tgz",
+ "integrity": "sha1-A2e+e/jwnj5qvJX45IO5IGSH7GU=",
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-api-error": "1.7.10",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.10",
+ "@webassemblyjs/ieee754": "1.7.10",
+ "@webassemblyjs/leb128": "1.7.10",
+ "@webassemblyjs/utf8": "1.7.10"
+ }
+ },
+ "@webassemblyjs/wast-parser": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.10.tgz",
+ "integrity": "sha1-BY9Zi1L3MLI/yHTUd1tihrYkcmQ=",
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/floating-point-hex-parser": "1.7.10",
+ "@webassemblyjs/helper-api-error": "1.7.10",
+ "@webassemblyjs/helper-code-frame": "1.7.10",
+ "@webassemblyjs/helper-fsm": "1.7.10",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.7.10",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.10.tgz",
+ "integrity": "sha1-2BeQnSRQrpbGa3YHYk2YozuEIjs=",
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/wast-parser": "1.7.10",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webpack-contrib/config-loader": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@webpack-contrib/config-loader/-/config-loader-1.2.1.tgz",
+ "integrity": "sha1-Wz3UdOIHQ3k50pTSAMaLewAAjgQ=",
+ "requires": {
+ "@webpack-contrib/schema-utils": "^1.0.0-beta.0",
+ "chalk": "^2.1.0",
+ "cosmiconfig": "^5.0.2",
+ "is-plain-obj": "^1.1.0",
+ "loud-rejection": "^1.6.0",
+ "merge-options": "^1.0.1",
+ "minimist": "^1.2.0",
+ "resolve": "^1.6.0",
+ "webpack-log": "^1.1.2"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ }
+ }
+ },
+ "@webpack-contrib/schema-utils": {
+ "version": "1.0.0-beta.0",
+ "resolved": "https://registry.npmjs.org/@webpack-contrib/schema-utils/-/schema-utils-1.0.0-beta.0.tgz",
+ "integrity": "sha1-v5Y4yUZNF3tIIJ6EIJ4jvuLrT2U=",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0",
+ "chalk": "^2.3.2",
+ "strip-ansi": "^4.0.0",
+ "text-table": "^0.2.0",
+ "webpack-log": "^1.1.2"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
+ "integrity": "sha1-JH1SdBENtlNwa1UPzCt5fKKM/Fk=",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
+ "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA="
+ }
+ }
+ },
+ "@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A="
+ },
+ "@xtuc/long": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz",
+ "integrity": "sha1-XIXWYvdvodNFdXZsXc1mFavNMNg="
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg="
+ },
+ "acorn": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz",
+ "integrity": "sha1-8JWCkpdwanyXdpWMCvyJMKm52dg="
+ },
+ "acorn-dynamic-import": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
+ "integrity": "sha1-kBzu5Mf6rvfgetKkfokGddpQong=",
+ "requires": {
+ "acorn": "^5.0.0"
+ }
+ },
+ "acorn-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+ "requires": {
+ "acorn": "^3.0.4"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
+ }
+ }
+ },
+ "agent-base": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+ "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ },
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "requires": {
+ "co": "^4.6.0",
+ "fast-deep-equal": "^1.0.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.3.0"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I="
+ },
+ "ansi-align": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
+ "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
+ "requires": {
+ "string-width": "^2.0.0"
+ }
+ },
+ "ansi-escapes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
+ "integrity": "sha1-9zIHu4EgfXX9bIPxJa8m7qN4yjA="
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=",
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo="
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=",
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE="
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "requires": {
+ "array-uniq": "^1.0.1"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
+ },
+ "asn1.js": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+ "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+ "requires": {
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
+ },
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0="
+ },
+ "async-limiter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+ "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k="
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "babel-polyfill": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
+ "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "core-js": "^2.5.0",
+ "regenerator-runtime": "^0.10.5"
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk="
+ }
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-js": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
+ "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM="
+ },
+ "big.js": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+ "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4="
+ },
+ "binary-extensions": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz",
+ "integrity": "sha1-wteA9T1Fu6gxeokC1M7q86Y4WxQ="
+ },
+ "bluebird": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz",
+ "integrity": "sha1-G+CQjgVKdRdUVJwnBInBUF1KsVo="
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8="
+ },
+ "boxen": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
+ "integrity": "sha1-VcbDmouljZxhrSLNh3Uy3rZlogs=",
+ "requires": {
+ "ansi-align": "^2.0.0",
+ "camelcase": "^4.0.0",
+ "chalk": "^2.0.1",
+ "cli-boxes": "^1.0.0",
+ "string-width": "^2.0.0",
+ "term-size": "^1.2.0",
+ "widest-line": "^2.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=",
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=",
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "requires": {
+ "bn.js": "^4.1.1",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.2",
+ "elliptic": "^6.0.0",
+ "inherits": "^2.0.1",
+ "parse-asn1": "^5.0.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=",
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8="
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
+ },
+ "cacache": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+ "integrity": "sha1-ZFI2eZnv+dQYiu/ZoU6dfGomNGA=",
+ "requires": {
+ "bluebird": "^3.5.1",
+ "chownr": "^1.0.1",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.1.11",
+ "lru-cache": "^4.1.1",
+ "mississippi": "^2.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.2",
+ "ssri": "^5.2.4",
+ "unique-filename": "^1.1.0",
+ "y18n": "^4.0.0"
+ }
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "caller-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+ "requires": {
+ "callsites": "^0.2.0"
+ }
+ },
+ "callsites": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo="
+ },
+ "camelcase": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
+ "integrity": "sha1-AylVJ9WL081Kp1Nj81sujZe+L0I="
+ },
+ "camelcase-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz",
+ "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=",
+ "requires": {
+ "camelcase": "^4.1.0",
+ "map-obj": "^2.0.0",
+ "quick-lru": "^1.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+ }
+ }
+ },
+ "capture-stack-trace": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
+ "integrity": "sha1-psC74fOPOqC5Ijjstv9Cw0TUE10="
+ },
+ "chalk": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+ "integrity": "sha1-GMSasWoDe26wFSzIPjRxM4IVtm4=",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "chardet": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
+ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="
+ },
+ "chokidar": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
+ "integrity": "sha1-NW/04rDo5D4yLRijckYLvPOszSY=",
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.0",
+ "braces": "^2.3.0",
+ "fsevents": "^1.2.2",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.1",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "lodash.debounce": "^4.0.8",
+ "normalize-path": "^2.1.1",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.0.0",
+ "upath": "^1.0.5"
+ }
+ },
+ "chops-wct-runner": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/chops-wct-runner/-/chops-wct-runner-0.0.1.tgz",
+ "integrity": "sha512-oqDf1EqdwolEjKDgrR+hu3LWrhwrxCp9D+862nCw0RKevWWoF+oiyFSoLlZD4xG0jR7yK1B5KMyj93anl8hh3A==",
+ "requires": {
+ "@popeindustries/lit-html-server": "^0.13.0",
+ "connect": "^3.6.6",
+ "puppeteer": "^1.10.0",
+ "puppeteer-to-istanbul": "^1.2.2",
+ "serve-static": "^1.13.2",
+ "yargs": "^12.0.2"
+ }
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+ "integrity": "sha1-VHJri4//TfBTxCGH6AH7RBLfFJQ="
+ },
+ "chrome-trace-event": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz",
+ "integrity": "sha1-Rakb0sIMlBHwljtarrmhuV4JzEg=",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "ci-info": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+ "integrity": "sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc="
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "circular-json": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY="
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "cli-boxes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
+ "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "requires": {
+ "restore-cursor": "^2.0.0"
+ }
+ },
+ "cli-spinners": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz",
+ "integrity": "sha1-ACwZkJEtDVlYDJO9NsBW3pnkJZo="
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ }
+ },
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
+ "integrity": "sha1-SYgbj7pn3xKpa98/VsCqueeRMUc=",
+ "requires": {
+ "color-name": "1.1.1"
+ }
+ },
+ "color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok="
+ },
+ "commander": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
+ "integrity": "sha1-aWS8pnaF33wfFDDFhPB9dZeIW5w="
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
+ },
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "configstore": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
+ "integrity": "sha1-xvJd767vJt8S3TNBSwAf6BpUP48=",
+ "requires": {
+ "dot-prop": "^4.1.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^1.0.0",
+ "unique-string": "^1.0.0",
+ "write-file-atomic": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ }
+ },
+ "connect": {
+ "version": "3.6.6",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
+ "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=",
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.0",
+ "parseurl": "~1.3.2",
+ "utils-merge": "1.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "requires": {
+ "date-now": "^0.1.4"
+ }
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+ "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=",
+ "requires": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
+ },
+ "core-js": {
+ "version": "2.5.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
+ "integrity": "sha1-+XJgj/DOrWi4QaFqky0LGDeRgU4="
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cosmiconfig": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.6.tgz",
+ "integrity": "sha1-3KbPaAoL0DWJr/aEcAhYyBq+6zk=",
+ "requires": {
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.9.0",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+ "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.0.0"
+ }
+ },
+ "create-error-class": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
+ "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
+ "requires": {
+ "capture-stack-trace": "^1.0.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=",
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=",
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "crypto-random-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
+ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "requires": {
+ "array-find-index": "^1.0.1"
+ }
+ },
+ "cyclist": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
+ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA="
+ },
+ "d": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
+ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
+ "requires": {
+ "es5-ext": "^0.10.9"
+ }
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz",
+ "integrity": "sha1-ZW17vICUxMeI6lPFhAkIycfQY8c=",
+ "requires": {
+ "xregexp": "4.0.0"
+ }
+ },
+ "decamelize-keys": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+ "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
+ "requires": {
+ "decamelize": "^1.1.0",
+ "map-obj": "^1.0.0"
+ },
+ "dependencies": {
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
+ }
+ }
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw="
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
+ },
+ "defaults": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
+ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+ "requires": {
+ "clone": "^1.0.2"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=",
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=",
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+ "requires": {
+ "globby": "^5.0.0",
+ "is-path-cwd": "^1.0.0",
+ "is-path-in-cwd": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=",
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+ "requires": {
+ "domelementtype": "~1.1.1",
+ "entities": "~1.1.1"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+ "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
+ }
+ }
+ },
+ "dom5": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/dom5/-/dom5-1.3.6.tgz",
+ "integrity": "sha1-pwiKn8XzsI3J9u2kx6uuskGUXg0=",
+ "requires": {
+ "@types/clone": "^0.1.29",
+ "@types/node": "^4.0.30",
+ "@types/parse5": "^0.0.31",
+ "clone": "^1.0.2",
+ "parse5": "^1.4.1"
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto="
+ },
+ "domelementtype": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+ "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI="
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=",
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha1-Vuo0HoNOBuZ0ivehyyXaZ+qfjCo=",
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "dot-prop": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+ "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=",
+ "requires": {
+ "is-obj": "^1.0.0"
+ }
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
+ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
+ },
+ "duplexify": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz",
+ "integrity": "sha1-saeinEq/1jlYXvrszoDWZrHjQSU=",
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "elliptic": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
+ "integrity": "sha1-wtC3d2kRuGcixjLDwGxg8vgZk5o=",
+ "requires": {
+ "bn.js": "^4.4.0",
+ "brorand": "^1.0.1",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.0"
+ }
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=",
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha1-Qcfgv9/nSsH/4eV61qXGyfN0Kn8=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "entities": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
+ "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA="
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+ "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=",
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=",
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
+ "integrity": "sha1-nbvdJ8aFbwABQhyhh4LXhr+KYWU=",
+ "requires": {
+ "es-to-primitive": "^1.1.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.1",
+ "is-callable": "^1.1.3",
+ "is-regex": "^1.0.4"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=",
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.46",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz",
+ "integrity": "sha1-79mfZ8Wn7Hibqj2qf3mHA4j39XI=",
+ "requires": {
+ "es6-iterator": "~2.0.3",
+ "es6-symbol": "~3.1.1",
+ "next-tick": "1"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "es6-promise": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz",
+ "integrity": "sha1-lu258v2wGZWCKyY92KratnSBgbw="
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+ "requires": {
+ "es6-promise": "^4.0.3"
+ },
+ "dependencies": {
+ "es6-promise": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz",
+ "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg=="
+ }
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "escodegen": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz",
+ "integrity": "sha1-snqTiUgdW/1b7Hb3ux6z+PRVZYk=",
+ "requires": {
+ "esprima": "^3.1.3",
+ "estraverse": "^4.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1",
+ "source-map": "~0.6.1"
+ }
+ },
+ "eslint": {
+ "version": "4.19.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
+ "integrity": "sha1-MtHWU+HZBAiFS/spbwdux+GGowA=",
+ "requires": {
+ "ajv": "^5.3.0",
+ "babel-code-frame": "^6.22.0",
+ "chalk": "^2.1.0",
+ "concat-stream": "^1.6.0",
+ "cross-spawn": "^5.1.0",
+ "debug": "^3.1.0",
+ "doctrine": "^2.1.0",
+ "eslint-scope": "^3.7.1",
+ "eslint-visitor-keys": "^1.0.0",
+ "espree": "^3.5.4",
+ "esquery": "^1.0.0",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^2.0.0",
+ "functional-red-black-tree": "^1.0.1",
+ "glob": "^7.1.2",
+ "globals": "^11.0.1",
+ "ignore": "^3.3.3",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^3.0.6",
+ "is-resolvable": "^1.0.0",
+ "js-yaml": "^3.9.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.3.0",
+ "lodash": "^4.17.4",
+ "minimatch": "^3.0.2",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.8.2",
+ "path-is-inside": "^1.0.2",
+ "pluralize": "^7.0.0",
+ "progress": "^2.0.0",
+ "regexpp": "^1.0.1",
+ "require-uncached": "^1.0.3",
+ "semver": "^5.3.0",
+ "strip-ansi": "^4.0.0",
+ "strip-json-comments": "~2.0.1",
+ "table": "4.0.2",
+ "text-table": "~0.2.0"
+ }
+ },
+ "eslint-config-google": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.6.0.tgz",
+ "integrity": "sha1-xULsGPsyR5g6wWu6MWYtAWJbdj8=",
+ "requires": {
+ "eslint-config-xo": "^0.13.0"
+ }
+ },
+ "eslint-config-xo": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.13.0.tgz",
+ "integrity": "sha1-+RZ2VDK6Z9L8enF3uLz+8/brBWQ="
+ },
+ "eslint-plugin-html": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.5.tgz",
+ "integrity": "sha1-6Ox+FkhRJEYPO/8xIBb+sKVNllk=",
+ "requires": {
+ "htmlparser2": "^3.8.2"
+ }
+ },
+ "eslint-scope": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
+ "integrity": "sha1-u1ByANPRf2AkdjYWC0gmKEsQhTU=",
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0="
+ },
+ "espree": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
+ "integrity": "sha1-sPRHGHyKi+2US4FaZgvd9d610ac=",
+ "requires": {
+ "acorn": "^5.5.0",
+ "acorn-jsx": "^3.0.0"
+ }
+ },
+ "esprima": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
+ },
+ "esquery": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
+ "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=",
+ "requires": {
+ "estraverse": "^4.0.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+ "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=",
+ "requires": {
+ "estraverse": "^4.1.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=",
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "external-editor": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
+ "integrity": "sha1-BFURz9jRM/OEZnPRBHwVTiFK09U=",
+ "requires": {
+ "chardet": "^0.4.0",
+ "iconv-lite": "^0.4.17",
+ "tmp": "^0.0.33"
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=",
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "extract-zip": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
+ "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=",
+ "requires": {
+ "concat-stream": "1.6.2",
+ "debug": "2.6.9",
+ "mkdirp": "0.5.1",
+ "yauzl": "2.4.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
+ },
+ "fd-slicer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
+ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+ "requires": {
+ "pend": "~1.2.0"
+ }
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "requires": {
+ "flat-cache": "^1.2.1",
+ "object-assign": "^4.0.1"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
+ "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.1",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "statuses": "~1.3.1",
+ "unpipe": "~1.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "find-cache-dir": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
+ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^1.0.0",
+ "pkg-dir": "^2.0.0"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "flat-cache": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
+ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+ "requires": {
+ "circular-json": "^0.3.1",
+ "del": "^2.0.2",
+ "graceful-fs": "^4.1.2",
+ "write": "^0.2.1"
+ }
+ },
+ "flush-write-stream": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
+ "integrity": "sha1-xdWG7zivYJdlC0m8QbVfq7GfNb0=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.4"
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
+ "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
+ "optional": true,
+ "requires": {
+ "nan": "^2.9.2",
+ "node-pre-gyp": "^0.10.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.5.1",
+ "bundled": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.21",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true
+ },
+ "minipass": {
+ "version": "2.2.4",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "^5.1.1",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.1.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.2.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "debug": "^2.1.2",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.10.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.0",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.1.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.3",
+ "bundled": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.1.10",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.7",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.5.1",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.0.5"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "bundled": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.5.0",
+ "bundled": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.0.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.2.4",
+ "minizlib": "^1.1.0",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.1",
+ "yallist": "^3.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "yallist": {
+ "version": "3.0.2",
+ "bundled": true
+ }
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0="
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "global-dirs": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
+ "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
+ "requires": {
+ "ini": "^1.3.4"
+ }
+ },
+ "globals": {
+ "version": "11.7.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
+ "integrity": "sha1-pYP6pDBVsayncZFL9oJY4vwSVnM="
+ },
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "requires": {
+ "array-union": "^1.0.1",
+ "arrify": "^1.0.0",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "got": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
+ "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+ "requires": {
+ "create-error-class": "^3.0.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-redirect": "^1.0.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "lowercase-keys": "^1.0.0",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "unzip-response": "^2.0.1",
+ "url-parse-lax": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=",
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz",
+ "integrity": "sha1-44q0uF37HgxA/pJlwOm1SFTCOBI=",
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+ "integrity": "sha1-l/I2l3vW4SVAiTD/bePuxigewEc="
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ },
+ "dependencies": {
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ }
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+ },
+ "https-proxy-agent": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
+ "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+ "requires": {
+ "agent-base": "^4.1.0",
+ "debug": "^3.1.0"
+ }
+ },
+ "hydrolysis": {
+ "version": "1.25.0",
+ "resolved": "https://registry.npmjs.org/hydrolysis/-/hydrolysis-1.25.0.tgz",
+ "integrity": "sha1-pPsUo3oeA7DbUtiqpXxoInKhTYQ=",
+ "requires": {
+ "acorn": "^3.2.0",
+ "babel-polyfill": "^6.2.0",
+ "doctrine": "^0.7.0",
+ "dom5": "1.1.0",
+ "escodegen": "^1.7.0",
+ "espree": "^3.1.3",
+ "estraverse": "^3.1.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
+ },
+ "doctrine": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz",
+ "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=",
+ "requires": {
+ "esutils": "^1.1.6",
+ "isarray": "0.0.1"
+ }
+ },
+ "dom5": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/dom5/-/dom5-1.1.0.tgz",
+ "integrity": "sha1-Ogx3AMCDq0xNJpOKeLDwxtzDd5Q=",
+ "requires": {
+ "parse5": "^1.4.1"
+ }
+ },
+ "estraverse": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-3.1.0.tgz",
+ "integrity": "sha1-FeKKRGuLgrxwDMyLlseK9NoNbLo="
+ },
+ "esutils": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz",
+ "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U="
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+ }
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+ "integrity": "sha1-KXhx9jvlB63Pv8pxXQzQ7thOmmM=",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ieee754": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
+ "integrity": "sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs="
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE="
+ },
+ "ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM="
+ },
+ "import-lazy": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+ "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
+ },
+ "import-local": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz",
+ "integrity": "sha1-Xk/9wD9P5sAJxnKb6yljHC+CJ7w=",
+ "requires": {
+ "pkg-dir": "^2.0.0",
+ "resolve-cwd": "^2.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+ },
+ "indent-string": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+ "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok="
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc="
+ },
+ "inquirer": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
+ "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=",
+ "requires": {
+ "ansi-escapes": "^3.0.0",
+ "chalk": "^2.0.0",
+ "cli-cursor": "^2.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^2.0.4",
+ "figures": "^2.0.0",
+ "lodash": "^4.3.0",
+ "mute-stream": "0.0.7",
+ "run-async": "^2.2.0",
+ "rx-lite": "^4.0.8",
+ "rx-lite-aggregates": "^4.0.8",
+ "string-width": "^2.1.0",
+ "strip-ansi": "^4.0.0",
+ "through": "^2.3.6"
+ }
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
+ },
+ "irregular-plurals": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz",
+ "integrity": "sha1-OdQPBbAPZW0Lf6RxIw3TtxSvKHI="
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4="
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "requires": {
+ "builtin-modules": "^1.0.0"
+ }
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU="
+ },
+ "is-ci": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+ "integrity": "sha1-43ecjuF/zPQoSI9uKBGH8uYyhBw=",
+ "requires": {
+ "ci-info": "^1.5.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0="
+ }
+ }
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "is-glob": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
+ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-installed-globally": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
+ "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
+ "requires": {
+ "global-dirs": "^0.1.0",
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-npm": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
+ "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ="
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0="
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+ "integrity": "sha1-WsSLNF72dTOb1sekipEhELJBz1I=",
+ "requires": {
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
+ },
+ "is-redirect": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
+ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
+ "is-resolvable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+ "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg="
+ },
+ "is-retry-allowed": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz",
+ "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ="
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=",
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0="
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+ },
+ "js-yaml": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
+ "integrity": "sha1-6u1lbsg0TxD1J8a/obbiJE3hZ9E=",
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha1-E7BM2z5sXRnfkatph6hpVhmwqnE="
+ }
+ }
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk="
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha1-ARRrNqYhjmTljzqNZt5df8b20FE="
+ },
+ "latest-version": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
+ "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
+ "requires": {
+ "package-json": "^4.0.0"
+ }
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "requires": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ }
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ }
+ }
+ },
+ "loader-runner": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz",
+ "integrity": "sha1-Am8S/nwxFZkolqwCugIrqSlxuXk="
+ },
+ "loader-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
+ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
+ "requires": {
+ "big.js": "^3.1.3",
+ "emojis-list": "^2.0.0",
+ "json5": "^0.5.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.10",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
+ "integrity": "sha1-G3eTz3JZ6jj7NmHU04syYK+K5Oc="
+ },
+ "lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
+ },
+ "log-symbols": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+ "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=",
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ },
+ "loglevelnext": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz",
+ "integrity": "sha1-NvxPWZbWZA9Tn/IDuoGWQWgNdaI=",
+ "requires": {
+ "es6-symbol": "^3.1.1",
+ "object.assign": "^4.1.0"
+ }
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "requires": {
+ "currently-unhandled": "^0.4.1",
+ "signal-exit": "^3.0.0"
+ }
+ },
+ "lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha1-b54wtHCE2XGnyCD/FabFFnt0wm8="
+ },
+ "lru-cache": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
+ "integrity": "sha1-oRdc80lt/IQ2wVbDNLSVWZK85pw=",
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha1-ecEDO4BRW9bSTsmTPoYMp17ifww=",
+ "requires": {
+ "pify": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ }
+ }
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
+ },
+ "map-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz",
+ "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk="
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "meant": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/meant/-/meant-1.0.1.tgz",
+ "integrity": "sha1-ZgRP6i8jIw7IBvtRXv6inETSEV0="
+ },
+ "mem": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "meow": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz",
+ "integrity": "sha1-38c9Y6mvxxSl43F2DrXIi5EHiqQ=",
+ "requires": {
+ "camelcase-keys": "^4.0.0",
+ "decamelize-keys": "^1.0.0",
+ "loud-rejection": "^1.0.0",
+ "minimist-options": "^3.0.1",
+ "normalize-package-data": "^2.3.4",
+ "read-pkg-up": "^3.0.0",
+ "redent": "^2.0.0",
+ "trim-newlines": "^2.0.0",
+ "yargs-parser": "^10.0.0"
+ }
+ },
+ "merge-options": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz",
+ "integrity": "sha1-KmSyRFe+zU5NxggoMkfpTOWJqjI=",
+ "requires": {
+ "is-plain-obj": "^1.1"
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ }
+ },
+ "mime": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz",
+ "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w=="
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI="
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc="
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ },
+ "minimist-options": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz",
+ "integrity": "sha1-+6TIGRM54T7PTWG+sD8HAQPz2VQ=",
+ "requires": {
+ "arrify": "^1.0.1",
+ "is-plain-obj": "^1.1.0"
+ }
+ },
+ "mississippi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
+ "integrity": "sha1-NEKlCPr8KFAEhv7qmUCWduTuWm8=",
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^2.0.1",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
+ "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=",
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+ "requires": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
+ },
+ "nan": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
+ "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=",
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
+ },
+ "neo-async": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz",
+ "integrity": "sha1-udFeTXHGdikIZUtRg+04t1M0CDU="
+ },
+ "next-tick": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+ },
+ "node-libs-browser": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
+ "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=",
+ "requires": {
+ "assert": "^1.1.1",
+ "browserify-zlib": "^0.2.0",
+ "buffer": "^4.3.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "^1.0.0",
+ "crypto-browserify": "^3.11.0",
+ "domain-browser": "^1.1.1",
+ "events": "^1.0.0",
+ "https-browserify": "^1.0.0",
+ "os-browserify": "^0.3.0",
+ "path-browserify": "0.0.0",
+ "process": "^0.11.10",
+ "punycode": "^1.2.4",
+ "querystring-es3": "^0.2.0",
+ "readable-stream": "^2.3.3",
+ "stream-browserify": "^2.0.1",
+ "stream-http": "^2.7.2",
+ "string_decoder": "^1.0.0",
+ "timers-browserify": "^2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "^0.11.0",
+ "util": "^0.10.3",
+ "vm-browserify": "0.0.4"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ }
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=",
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "is-builtin-module": "^1.0.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-keys": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
+ "integrity": "sha1-CcU4VTd1dTEMymL1W7M0q/97PtI="
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=",
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "object.values": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz",
+ "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=",
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.6.1",
+ "function-bind": "^1.1.0",
+ "has": "^1.0.1"
+ }
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "opn": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz",
+ "integrity": "sha1-y1Reeqt4VivrEao7+rxwQuF2EDU=",
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "requires": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.4",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "wordwrap": "~1.0.0"
+ }
+ },
+ "ora": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-2.1.0.tgz",
+ "integrity": "sha1-bK8oMOuSSUGGHsU6FzeZ4Ai1Hls=",
+ "requires": {
+ "chalk": "^2.3.1",
+ "cli-cursor": "^2.1.0",
+ "cli-spinners": "^1.1.0",
+ "log-symbols": "^2.2.0",
+ "strip-ansi": "^4.0.0",
+ "wcwidth": "^1.0.1"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
+ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
+ "requires": {
+ "execa": "^0.7.0",
+ "lcid": "^1.0.0",
+ "mem": "^1.1.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+ },
+ "p-is-promise": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
+ "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4="
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=",
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
+ },
+ "package-json": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
+ "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
+ "requires": {
+ "got": "^6.7.1",
+ "registry-auth-token": "^3.0.1",
+ "registry-url": "^3.0.3",
+ "semver": "^5.1.0"
+ }
+ },
+ "pako": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
+ "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg="
+ },
+ "parallel-transform": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
+ "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+ "requires": {
+ "cyclist": "~0.2.2",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
+ "integrity": "sha1-9r8pOBgzK9DatU77Fgh3JHRebKg=",
+ "requires": {
+ "asn1.js": "^4.0.0",
+ "browserify-aes": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "parse5": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz",
+ "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ="
+ },
+ "parseurl": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+ "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
+ },
+ "path-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo="
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw="
+ },
+ "path-posix": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz",
+ "integrity": "sha1-BrJhE/Vr6rBCVFojv6iAA8ysJg8="
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=",
+ "requires": {
+ "pify": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ }
+ }
+ },
+ "pbkdf2": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
+ "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=",
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ },
+ "plur": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/plur/-/plur-3.0.1.tgz",
+ "integrity": "sha1-JoZS1gX4FmmbQrhiSN5zyazQanw=",
+ "requires": {
+ "irregular-plurals": "^2.0.0"
+ }
+ },
+ "pluralize": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
+ "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c="
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
+ },
+ "pretty-bytes": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.1.0.tgz",
+ "integrity": "sha1-Yjfs+9xlJb6u9N5yLMYKWK4ObG0="
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o="
+ },
+ "progress": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
+ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8="
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
+ },
+ "proxy-from-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
+ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=",
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew="
+ },
+ "puppeteer": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.11.0.tgz",
+ "integrity": "sha512-iG4iMOHixc2EpzqRV+pv7o3GgmU2dNYEMkvKwSaQO/vMZURakwSOn/EYJ6OIRFYOque1qorzIBvrytPIQB3YzQ==",
+ "requires": {
+ "debug": "^4.1.0",
+ "extract-zip": "^1.6.6",
+ "https-proxy-agent": "^2.2.1",
+ "mime": "^2.0.3",
+ "progress": "^2.0.1",
+ "proxy-from-env": "^1.0.0",
+ "rimraf": "^2.6.1",
+ "ws": "^6.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
+ "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
+ }
+ }
+ },
+ "puppeteer-to-istanbul": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/puppeteer-to-istanbul/-/puppeteer-to-istanbul-1.2.2.tgz",
+ "integrity": "sha512-uXj2WKvcrszD0BHBp6Ht3FDed4Kfzvzn1fP4IdrYLjZ9Gbxc/YRhT1JBdTz1TMHZVs+HHT/Bbwz3KwSLLK4UBg==",
+ "requires": {
+ "clone": "^2.1.1",
+ "mkdirp": "^0.5.1",
+ "v8-to-istanbul": "^1.2.0",
+ "yargs": "^11.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+ },
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
+ },
+ "yargs": {
+ "version": "11.1.0",
+ "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
+ "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.1.1",
+ "find-up": "^2.1.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^2.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^9.0.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
+ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=",
+ "requires": {
+ "camelcase": "^4.1.0"
+ }
+ }
+ }
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "quick-lru": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
+ "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g="
+ },
+ "randombytes": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
+ "integrity": "sha1-0wLFIpSFiISKjTAMkytEwkIx2oA=",
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=",
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+ },
+ "rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=",
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
+ "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
+ "requires": {
+ "find-up": "^2.0.0",
+ "read-pkg": "^3.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=",
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "redent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
+ "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=",
+ "requires": {
+ "indent-string": "^3.0.0",
+ "strip-indent": "^2.0.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.10.5",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
+ "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=",
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexpp": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
+ "integrity": "sha1-DjUW3Qt5BPQT0tQZPc5GGMOmias="
+ },
+ "registry-auth-token": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
+ "integrity": "sha1-hR/UkDjuy1hpERFa+EUmDuyYPyA=",
+ "requires": {
+ "rc": "^1.1.6",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "registry-url": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
+ "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
+ "requires": {
+ "rc": "^1.0.1"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
+ "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4="
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
+ },
+ "require-uncached": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+ "requires": {
+ "caller-path": "^0.1.0",
+ "resolve-from": "^1.0.0"
+ }
+ },
+ "resolve": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
+ "integrity": "sha1-gvHsGaQjrB+9CAsLqwa6NuhKeiY=",
+ "requires": {
+ "path-parse": "^1.0.5"
+ }
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "requires": {
+ "resolve-from": "^3.0.0"
+ },
+ "dependencies": {
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
+ }
+ }
+ },
+ "resolve-from": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+ "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY="
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "requires": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w="
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=",
+ "requires": {
+ "glob": "^7.0.5"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "run-async": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+ "requires": {
+ "is-promise": "^2.1.0"
+ }
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+ "requires": {
+ "aproba": "^1.1.1"
+ }
+ },
+ "rx-lite": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
+ "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ="
+ },
+ "rx-lite-aggregates": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
+ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+ "requires": {
+ "rx-lite": "*"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
+ },
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha1-unT1l9K+LqiAExdG7hfQoJPGgYc=",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
+ "integrity": "sha1-JH1SdBENtlNwa1UPzCt5fKKM/Fk=",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
+ "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA="
+ }
+ }
+ },
+ "semver": {
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
+ "integrity": "sha1-ff3YgUvbfKvHvg+x1zTPtmyUBHc="
+ },
+ "semver-diff": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
+ "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
+ "requires": {
+ "semver": "^5.0.3"
+ }
+ },
+ "send": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
+ "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.6.2",
+ "mime": "1.4.1",
+ "ms": "2.0.0",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.0",
+ "statuses": "~1.4.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "mime": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
+ },
+ "statuses": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+ "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
+ }
+ }
+ },
+ "serialize-javascript": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz",
+ "integrity": "sha1-GqM2FiyIqJDdrVOEuuvJOmVRYf4="
+ },
+ "serve-static": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
+ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.2",
+ "send": "0.16.2"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "set-value": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
+ "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "slice-ansi": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
+ "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=",
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0"
+ }
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=",
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+ "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ="
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM="
+ },
+ "source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=",
+ "requires": {
+ "atob": "^2.1.1",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
+ },
+ "spdx-correct": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz",
+ "integrity": "sha1-GbtAnpG0exrVQVkkP3MSqFjbPC4=",
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc="
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=",
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz",
+ "integrity": "sha1-4qMDI2ysVLBAMfp6WnnH5wHfhS8="
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "ssri": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
+ "integrity": "sha1-ujhyycbTOgcEp9cf8EXl7EiZnQY=",
+ "requires": {
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
+ },
+ "stream-browserify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+ "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+ "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=",
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ }
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
+ },
+ "strip-indent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
+ "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g="
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ },
+ "table": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
+ "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=",
+ "requires": {
+ "ajv": "^5.2.3",
+ "ajv-keywords": "^2.1.0",
+ "chalk": "^2.1.0",
+ "lodash": "^4.17.4",
+ "slice-ansi": "1.0.0",
+ "string-width": "^2.1.1"
+ }
+ },
+ "tapable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz",
+ "integrity": "sha1-DQdqFy49m6CI/SJysmaPuNGUt4w="
+ },
+ "term-size": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
+ "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
+ "requires": {
+ "execa": "^0.7.0"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
+ "through2": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
+ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
+ "requires": {
+ "readable-stream": "^2.1.5",
+ "xtend": "~4.0.1"
+ }
+ },
+ "timed-out": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+ "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
+ },
+ "timers-browserify": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
+ "integrity": "sha1-HSjj0qrfHVpZlsTp+VYBzQU0gK4=",
+ "requires": {
+ "setimmediate": "^1.0.4"
+ }
+ },
+ "titleize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.1.tgz",
+ "integrity": "sha1-Ibwk/Mpljq3G0708OPK9FzdptMU="
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=",
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=",
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "trim-newlines": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz",
+ "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA="
+ },
+ "tslib": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+ "integrity": "sha1-1+TdeSRdhUKMTX5IIqeZF5VMooY="
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "requires": {
+ "prelude-ls": "~1.1.2"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
+ "uglify-es": {
+ "version": "3.3.9",
+ "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
+ "integrity": "sha1-DBxPBwC+2NvBJM2zBNJZLKID5nc=",
+ "requires": {
+ "commander": "~2.13.0",
+ "source-map": "~0.6.1"
+ }
+ },
+ "uglifyjs-webpack-plugin": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz",
+ "integrity": "sha1-dfVIFghYFjoIZD4IbV/v4YpdZ94=",
+ "requires": {
+ "cacache": "^10.0.4",
+ "find-cache-dir": "^1.0.0",
+ "schema-utils": "^0.4.5",
+ "serialize-javascript": "^1.4.0",
+ "source-map": "^0.6.1",
+ "uglify-es": "^3.3.4",
+ "webpack-sources": "^1.1.0",
+ "worker-farm": "^1.5.2"
+ }
+ },
+ "union-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
+ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^0.4.3"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "set-value": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
+ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.1",
+ "to-object-path": "^0.3.0"
+ }
+ }
+ }
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=",
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz",
+ "integrity": "sha1-Xp7cbRzo+yZNsYpQfvm9hURFHKY=",
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "unique-string": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
+ "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
+ "requires": {
+ "crypto-random-string": "^1.0.0"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
+ }
+ }
+ },
+ "unzip-response": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
+ "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c="
+ },
+ "upath": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
+ "integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0="
+ },
+ "update-notifier": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
+ "integrity": "sha1-0HRFk+E/Fh5AassdlAi3LK0Ir/Y=",
+ "requires": {
+ "boxen": "^1.2.1",
+ "chalk": "^2.0.1",
+ "configstore": "^3.0.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^1.0.10",
+ "is-installed-globally": "^0.1.0",
+ "is-npm": "^1.0.0",
+ "latest-version": "^3.0.0",
+ "semver-diff": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ }
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=",
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ }
+ }
+ },
+ "url-parse-lax": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
+ "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
+ "requires": {
+ "prepend-http": "^1.0.1"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8="
+ },
+ "util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha1-OqASW/5mikZy3liFfTrOJ+y3aQE=",
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE="
+ },
+ "v8-compile-cache": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz",
+ "integrity": "sha1-pCiyi7JnkHNMT8i8n6EG/M6/amw="
+ },
+ "v8-to-istanbul": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-1.2.1.tgz",
+ "integrity": "sha512-NglPycIwSQeSJj7VJ6L8vTsPKC9MG5Lcx4n3SvYqNHzklbMI4dGcLJnkLPEPJ3uB8UyTdWviMhM0Ptq+xD5UFQ=="
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=",
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "requires": {
+ "indexof": "0.0.1"
+ }
+ },
+ "vulcanize": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/vulcanize/-/vulcanize-1.16.0.tgz",
+ "integrity": "sha1-sM47AETRlK1JCK5PGmxhEKbk1eY=",
+ "requires": {
+ "dom5": "^1.3.1",
+ "es6-promise": "^2.1.0",
+ "hydrolysis": "^1.19.1",
+ "nopt": "^3.0.1",
+ "path-posix": "^1.0.0"
+ }
+ },
+ "watchpack": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
+ "integrity": "sha1-S8EsLr6KonenHx0/FNaFx7RGzQA=",
+ "requires": {
+ "chokidar": "^2.0.2",
+ "graceful-fs": "^4.1.2",
+ "neo-async": "^2.5.0"
+ }
+ },
+ "wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
+ "requires": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "webpack": {
+ "version": "4.23.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.23.1.tgz",
+ "integrity": "sha1-23RnsRZ3GuAgxYvf4qCCJ4W7gjk=",
+ "requires": {
+ "@webassemblyjs/ast": "1.7.10",
+ "@webassemblyjs/helper-module-context": "1.7.10",
+ "@webassemblyjs/wasm-edit": "1.7.10",
+ "@webassemblyjs/wasm-parser": "1.7.10",
+ "acorn": "^5.6.2",
+ "acorn-dynamic-import": "^3.0.0",
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0",
+ "chrome-trace-event": "^1.0.0",
+ "enhanced-resolve": "^4.1.0",
+ "eslint-scope": "^4.0.0",
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^2.3.0",
+ "loader-utils": "^1.1.0",
+ "memory-fs": "~0.4.1",
+ "micromatch": "^3.1.8",
+ "mkdirp": "~0.5.0",
+ "neo-async": "^2.5.0",
+ "node-libs-browser": "^2.0.0",
+ "schema-utils": "^0.4.4",
+ "tapable": "^1.1.0",
+ "uglifyjs-webpack-plugin": "^1.2.4",
+ "watchpack": "^1.5.0",
+ "webpack-sources": "^1.3.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz",
+ "integrity": "sha1-JH1SdBENtlNwa1UPzCt5fKKM/Fk=",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
+ "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
+ },
+ "eslint-scope": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
+ "integrity": "sha1-UL8wcekzi83EMzF5Sgy1M/ATYXI=",
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA="
+ }
+ }
+ },
+ "webpack-command": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/webpack-command/-/webpack-command-0.4.1.tgz",
+ "integrity": "sha1-P4iq6HwoKS7QqXKTYVouliocZvQ=",
+ "requires": {
+ "@webpack-contrib/config-loader": "^1.2.0",
+ "@webpack-contrib/schema-utils": "^1.0.0-beta.0",
+ "camelcase": "^5.0.0",
+ "chalk": "^2.3.2",
+ "debug": "^3.1.0",
+ "decamelize": "^2.0.0",
+ "enhanced-resolve": "^4.0.0",
+ "import-local": "^1.0.0",
+ "isobject": "^3.0.1",
+ "loader-utils": "^1.1.0",
+ "log-symbols": "^2.2.0",
+ "loud-rejection": "^1.6.0",
+ "meant": "^1.0.1",
+ "meow": "^5.0.0",
+ "merge-options": "^1.0.0",
+ "object.values": "^1.0.4",
+ "opn": "^5.3.0",
+ "ora": "^2.1.0",
+ "plur": "^3.0.0",
+ "pretty-bytes": "^5.0.0",
+ "strip-ansi": "^4.0.0",
+ "text-table": "^0.2.0",
+ "titleize": "^1.0.1",
+ "update-notifier": "^2.3.0",
+ "v8-compile-cache": "^2.0.0",
+ "webpack-log": "^1.1.2",
+ "wordwrap": "^1.0.0"
+ }
+ },
+ "webpack-log": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz",
+ "integrity": "sha1-pLNM2msitRjbsKsy5WeWLVxypD0=",
+ "requires": {
+ "chalk": "^2.1.0",
+ "log-symbols": "^2.1.0",
+ "loglevelnext": "^1.0.1",
+ "uuid": "^3.1.0"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz",
+ "integrity": "sha1-KijcufH0X+lg2PFJMlK17mUw+oU=",
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+ },
+ "widest-line": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
+ "integrity": "sha1-dDh2RzDsfvQ4HOTfgvuYpTFCo/w=",
+ "requires": {
+ "string-width": "^2.1.1"
+ }
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
+ },
+ "worker-farm": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz",
+ "integrity": "sha1-rsxAWXb6talVJhgIRvDboojzpKA=",
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "write": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "requires": {
+ "mkdirp": "^0.5.1"
+ }
+ },
+ "write-file-atomic": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
+ "integrity": "sha1-H/YVdcLipOjlENb6TiQ8zhg5mas=",
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ws": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz",
+ "integrity": "sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==",
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "xdg-basedir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
+ "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ="
+ },
+ "xregexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz",
+ "integrity": "sha1-5pgYneSd0qGMxWh7BeF8jkOUMCA="
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms="
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ },
+ "yargs": {
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "execa": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+ "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "mem": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz",
+ "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==",
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^1.0.0",
+ "p-is-promise": "^1.1.0"
+ }
+ },
+ "os-locale": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz",
+ "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==",
+ "requires": {
+ "execa": "^0.10.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
+ "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
+ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ=="
+ },
+ "yargs-parser": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz",
+ "integrity": "sha1-cgImW4n36eny5XZeD+c1qQXtuqg=",
+ "requires": {
+ "camelcase": "^4.1.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+ }
+ }
+ },
+ "yauzl": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
+ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
+ "requires": {
+ "fd-slicer": "~1.0.1"
+ }
+ }
+ }
+}
diff --git a/chromium/third_party/catapult/common/node_runner/node_runner/package.json b/chromium/third_party/catapult/common/node_runner/node_runner/package.json
new file mode 100644
index 00000000000..3a6ab5f7a9b
--- /dev/null
+++ b/chromium/third_party/catapult/common/node_runner/node_runner/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "catapult_base",
+ "version": "1.0.0",
+ "description": "Catapult project base",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/catapult-project/catapult/tree/master/catapult_base"
+ },
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "The Chromium Authors",
+ "license": "BSD-2-Clause",
+ "gypfile": false,
+ "private": true,
+ "dependencies": {
+ "chops-wct-runner": "^0.0.1",
+ "dom5": "^1.0.0",
+ "escodegen": "^1.11.0",
+ "eslint": "^4.0.0",
+ "eslint-config-google": "^0.6.0",
+ "eslint-plugin-html": "^4.0.0",
+ "espree": "^3.0.0",
+ "vulcanize": "^1.16.0",
+ "webpack": "^4.16.1",
+ "webpack-command": "^0.4.1"
+ }
+}
diff --git a/chromium/third_party/catapult/common/py_trace_event/README.txt b/chromium/third_party/catapult/common/py_trace_event/README.txt
new file mode 100644
index 00000000000..2f0d33d3dab
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/README.txt
@@ -0,0 +1,7 @@
+py_trace_event allows low-overhead instrumentation of a multi-threaded,
+multi-process application in order to study its global performance
+characteristics. It uses the trace event format used in Chromium/Chrome's
+about:tracing system.
+
+Trace files generated by py_trace_event can be viewed and manipulated by
+trace_event_viewer.
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/__init__.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/__init__.py
new file mode 100644
index 00000000000..b8b6630125a
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/__init__.py
@@ -0,0 +1,9 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
+PY_UTILS = os.path.abspath(os.path.join(SCRIPT_DIR, '..', '..', 'py_utils'))
+sys.path.append(PY_UTILS)
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/run_tests b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/run_tests
new file mode 100755
index 00000000000..7f9673dd5cd
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/run_tests
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import optparse
+import os
+import platform
+import re
+import sys
+import types
+import traceback
+import unittest
+
+
+def discover(dir, filters):
+ if hasattr(unittest.TestLoader, 'discover'):
+ return unittest.TestLoader().discover(dir, '*')
+
+ # poor mans unittest.discover
+ loader = unittest.TestLoader()
+ subsuites = []
+
+ for (dirpath, dirnames, filenames) in os.walk(dir):
+ for filename in [x for x in filenames if re.match('.*_test\.py$', x)]:
+ if filename.startswith('.') or filename.startswith('_'):
+ continue
+ fqn = dirpath.replace(
+ '/', '.') + '.' + re.match('(.+)\.py$', filename).group(1)
+
+ # load the test
+ try:
+ module = __import__(fqn,fromlist=[True])
+ except:
+ print "While importing [%s]\n" % fqn
+ traceback.print_exc()
+ continue
+
+ def test_is_selected(name):
+ for f in filters:
+ if re.search(f,name):
+ return True
+ return False
+
+ if hasattr(module, 'suite'):
+ base_suite = module.suite()
+ else:
+ base_suite = loader.loadTestsFromModule(module)
+ new_suite = unittest.TestSuite()
+ for t in base_suite:
+ if isinstance(t, unittest.TestSuite):
+ for i in t:
+ if test_is_selected(i.id()):
+ new_suite.addTest(i)
+ elif isinstance(t, unittest.TestCase):
+ if test_is_selected(t.id()):
+ new_suite.addTest(t)
+ else:
+ raise Exception("Wtf, expected TestSuite or TestCase, got %s" % t)
+
+ if new_suite.countTestCases():
+ subsuites.append(new_suite)
+
+ return unittest.TestSuite(subsuites)
+
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option(
+ '-v', '--verbose', action='count', default=0,
+ help='Increase verbosity level (repeat as needed)')
+ parser.add_option('--debug', dest='debug', action='store_true', default=False,
+ help='Break into pdb when an assertion fails')
+ parser.add_option('--incremental', dest='incremental', action='store_true',
+ default=False, help='Run tests one at a time.')
+ parser.add_option('--stop', dest='stop_on_error', action='store_true',
+ default=False, help='Stop running tests on error.')
+ (options, args) = parser.parse_args()
+
+ if options.verbose >= 2:
+ logging.basicConfig(level=logging.DEBUG)
+ elif options.verbose:
+ logging.basicConfig(level=logging.INFO)
+ else:
+ logging.basicConfig(level=logging.WARNING)
+
+ # install hook on set_trace if --debug
+ if options.debug:
+ import exceptions
+ class DebuggingAssertionError(exceptions.AssertionError):
+ def __init__(self, *args):
+ exceptions.AssertionError.__init__(self, *args)
+ print "Assertion failed, entering PDB..."
+ import pdb
+ if hasattr(sys, '_getframe'):
+ pdb.Pdb().set_trace(sys._getframe().f_back.f_back)
+ else:
+ pdb.set_trace()
+ unittest.TestCase.failureException = DebuggingAssertionError
+
+ def hook(*args):
+ import traceback, pdb
+ traceback.print_exception(*args)
+ pdb.pm()
+ sys.excepthook = hook
+
+ import browser
+ browser.debug_mode = True
+
+ else:
+ def hook(exc, value, tb):
+ import traceback
+ if not str(value).startswith("_noprint"):
+ traceback.print_exception(exc, value, tb)
+ import src.message_loop
+ if src.message_loop.is_main_loop_running():
+ if not str(value).startswith("_noprint"):
+ print "Untrapped exception! Exiting message loop with exception."
+ src.message_loop.quit_main_loop(quit_with_exception=True)
+
+ sys.excepthook = hook
+
+ # make sure cwd is the base directory!
+ os.chdir(os.path.dirname(__file__))
+
+ if len(args) > 0:
+ suites = discover('trace_event_impl', args)
+ else:
+ suites = discover('trace_event_impl', ['.*'])
+
+ r = unittest.TextTestRunner()
+ if not options.incremental:
+ res = r.run(suites)
+ if res.wasSuccessful():
+ return 0
+ return 255
+ else:
+ ok = True
+ for s in suites:
+ if isinstance(s, unittest.TestSuite):
+ for t in s:
+ print '--------------------------------------------------------------'
+ print 'Running %s' % str(t)
+ res = r.run(t)
+ if not res.wasSuccessful():
+ ok = False
+ if options.stop_on_error:
+ break
+ if ok == False and options.stop_on_error:
+ break
+ else:
+ res = r.run(s)
+ if not res.wasSuccessful():
+ ok = False
+ if options.stop_on_error:
+ break
+ if ok:
+ return 0
+ return 255
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/setup.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/setup.py
new file mode 100644
index 00000000000..0b0070a01b0
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/setup.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+# Copyright 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from distutils.core import setup
+setup(
+ name='py_trace_event',
+ packages=['trace_event_impl'],
+ version='0.1.0',
+ description='Performance tracing for python',
+ author='Nat Duca'
+)
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event.py
new file mode 100644
index 00000000000..77459634d64
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event.py
@@ -0,0 +1,282 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from py_trace_event import trace_time
+
+
+r"""Instrumentation-based profiling for Python.
+
+trace_event allows you to hand-instrument your code with areas of interest.
+When enabled, trace_event logs the start and stop times of these events to a
+logfile. These resulting logfiles can be viewed with either Chrome's
+about:tracing UI or with the standalone trace_event_viewer available at
+ http://www.github.com/natduca/trace_event_viewer/
+
+To use trace event, call trace_event_enable and start instrumenting your code:
+ from trace_event import *
+
+ if "--trace" in sys.argv:
+ trace_enable("myfile.trace")
+
+ @traced
+ def foo():
+ ...
+
+ class MyFoo(object):
+ @traced
+ def bar(self):
+ ...
+
+trace_event records trace events to an in-memory buffer. If your application is
+long running and you want to see the results of a trace before it exits, you can
+call trace_flush to write any in-memory events to disk.
+
+To help intregrating trace_event into existing codebases that dont want to add
+trace_event as a dependancy, trace_event is split into an import shim
+(trace_event.py) and an implementaiton (trace_event_impl/*). You can copy the
+shim, trace_event.py, directly into your including codebase. If the
+trace_event_impl is not found, the shim will simply noop.
+
+trace_event is safe with regard to Python threads. Simply trace as you normally
+would and each thread's timing will show up in the trace file.
+
+Multiple processes can safely output into a single trace_event logfile. If you
+fork after enabling tracing, the child process will continue outputting to the
+logfile. Use of the multiprocessing module will work as well. In both cases,
+however, note that disabling tracing in the parent process will not stop tracing
+in the child processes.
+"""
+
+try:
+ import trace_event_impl
+except ImportError:
+ trace_event_impl = None
+
+
+def trace_can_enable():
+ """
+ Returns True if a trace_event_impl was found. If false,
+ trace_enable will fail. Regular tracing methods, including
+ trace_begin and trace_end, will simply be no-ops.
+ """
+ return trace_event_impl != None
+
+# Default TracedMetaClass to type incase trace_event_impl is not defined.
+# This is to avoid exception during import time since TracedMetaClass typically
+# used in class definition scope.
+TracedMetaClass = type
+
+if trace_event_impl:
+ import time
+
+
+ def trace_is_enabled():
+ return trace_event_impl.trace_is_enabled()
+
+ def trace_enable(logfile):
+ return trace_event_impl.trace_enable(logfile)
+
+ def trace_disable():
+ return trace_event_impl.trace_disable()
+
+ def trace_flush():
+ trace_event_impl.trace_flush()
+
+ def trace_begin(name, **kwargs):
+ args_to_log = {key: repr(value) for key, value in kwargs.iteritems()}
+ trace_event_impl.add_trace_event("B", trace_time.Now(), "python", name,
+ args_to_log)
+
+ def trace_end(name):
+ trace_event_impl.add_trace_event("E", trace_time.Now(), "python", name)
+
+ def trace_set_thread_name(thread_name):
+ trace_event_impl.add_trace_event("M", trace_time.Now(), "__metadata",
+ "thread_name", {"name": thread_name})
+
+ def trace(name, **kwargs):
+ return trace_event_impl.trace(name, **kwargs)
+
+ TracedMetaClass = trace_event_impl.TracedMetaClass
+
+ def traced(fn):
+ return trace_event_impl.traced(fn)
+
+ def clock_sync(sync_id, issue_ts=None):
+ '''
+ Add a clock sync event to the trace log.
+
+ Args:
+ sync_id: ID of clock sync event.
+ issue_ts: Time at which clock sync was issued, in microseconds.
+ '''
+ time_stamp = trace_time.Now()
+ args_to_log = {'sync_id': sync_id}
+ if issue_ts: # Issuer if issue_ts is set, else reciever.
+ assert issue_ts <= time_stamp
+ args_to_log['issue_ts'] = issue_ts
+ trace_event_impl.add_trace_event(
+ "c", time_stamp, "python", "clock_sync", args_to_log)
+
+ def is_tracing_controllable():
+ return trace_event_impl.is_tracing_controllable()
+
+else:
+ import contextlib
+
+ def trace_enable():
+ raise TraceException(
+ "Cannot enable trace_event. No trace_event_impl module found.")
+
+ def trace_disable():
+ pass
+
+ def trace_is_enabled():
+ return False
+
+ def trace_flush():
+ pass
+
+ def trace_begin(name, **kwargs):
+ del name # unused.
+ del kwargs # unused.
+ pass
+
+ def trace_end(name):
+ del name # unused.
+ pass
+
+ def trace_set_thread_name(thread_name):
+ del thread_name # unused.
+ pass
+
+ @contextlib.contextmanager
+ def trace(name, **kwargs):
+ del name # unused
+ del kwargs # unused
+ yield
+
+ def traced(fn):
+ return fn
+
+ def clock_sync(sync_id, issue_ts=None):
+ del sync_id # unused.
+ pass
+
+ def is_tracing_controllable():
+ return False
+
+trace_enable.__doc__ = """Enables tracing.
+
+ Once enabled, the enabled bit propagates to forked processes and
+ multiprocessing subprocesses. Regular child processes, e.g. those created via
+ os.system/popen, or subprocess.Popen instances, will not get traced. You can,
+ however, enable tracing on those subprocess manually.
+
+ Trace files are multiprocess safe, so you can have multiple processes
+ outputting to the same tracelog at once.
+
+ log_file can be one of three things:
+
+ None: a logfile is opened based on sys[argv], namely
+ "./" + sys.argv[0] + ".json"
+
+ string: a logfile of the given name is opened.
+
+ file-like object: the fileno() is is used. The underlying file descriptor
+ must support fcntl.lockf() operations.
+ """
+
+trace_disable.__doc__ = """Disables tracing, if enabled.
+
+ Will not disable tracing on any existing child proceses that were forked
+ from this process. You must disable them yourself.
+ """
+
+trace_flush.__doc__ = """Flushes any currently-recorded trace data to disk.
+
+ trace_event records traces into an in-memory buffer for efficiency. Flushing
+ is only done at process exit or when this method is called.
+ """
+
+trace_is_enabled.__doc__ = """Returns whether tracing is enabled.
+ """
+
+trace_begin.__doc__ = """Records the beginning of an event of the given name.
+
+ The building block for performance tracing. A typical example is:
+ from trace_event import *
+ def something_heavy():
+ trace_begin("something_heavy")
+
+ trace_begin("read")
+ try:
+ lines = open().readlines()
+ finally:
+ trace_end("read")
+
+ trace_begin("parse")
+ try:
+ parse(lines)
+ finally:
+ trace_end("parse")
+
+ trace_end("something_heavy")
+
+ Note that a trace_end call must be issued for every trace_begin call. When
+ tracing around blocks that might throw exceptions, you should use the trace
+ function, or a try-finally pattern to ensure that the trace_end method is
+ called.
+
+ See the documentation for the @traced decorator for a simpler way to
+ instrument functions and methods.
+ """
+
+trace_end.__doc__ = """Records the end of an event of the given name.
+
+ See the documentation for trace_begin for more information.
+
+ Make sure to issue a trace_end for every trace_begin issued. Failure to pair
+ these calls will lead to bizarrely tall looking traces in the
+ trace_event_viewer UI.
+ """
+
+trace_set_thread_name.__doc__ = """Sets the trace's name for the current thread.
+ """
+
+trace.__doc__ = """Traces a block of code using a with statement.
+
+ Example usage:
+ from trace_event import *
+ def something_heavy(lines):
+ with trace("parse_lines", lines=lines):
+ parse(lines)
+
+ If tracing an entire function call, prefer the @traced decorator.
+ """
+
+traced.__doc__ = """
+ Traces the provided function, using the function name for the actual generated
+ event.
+
+ Prefer this decorator over the explicit trace_begin and trace_end functions
+ whenever you are tracing the start and stop of a function. It automatically
+ issues trace_begin/end events, even when the wrapped function throws.
+
+ You can also pass the function's argument names to traced, and the argument
+ values will be added to the trace. Example usage:
+ from trace_event import *
+ @traced("url")
+ def send_request(url):
+ urllib2.urlopen(url).read()
+ """
+
+clock_sync.__doc__ = """
+ Issues a clock sync marker event.
+
+ Clock sync markers are used to synchronize the clock domains of different
+ traces so that they can be used together. It takes a sync_id, and if it is
+ the issuer of a clock sync event it will also require an issue_ts. The
+ issue_ts is a timestamp from when the clocksync was first issued. This is used
+ to calculate the time difference between clock domains.
+ """
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/__init__.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/__init__.py
new file mode 100644
index 00000000000..d250e0312e4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/__init__.py
@@ -0,0 +1,7 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from log import *
+from decorators import *
+from meta_class import *
+import multiprocessing_shim
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators.py
new file mode 100644
index 00000000000..dc753f1f61b
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators.py
@@ -0,0 +1,87 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import contextlib
+import inspect
+import time
+import functools
+
+import log
+from py_trace_event import trace_time
+
+
+@contextlib.contextmanager
+def trace(name, **kwargs):
+ category = "python"
+ start = trace_time.Now()
+ args_to_log = {key: repr(value) for key, value in kwargs.iteritems()}
+ log.add_trace_event("B", start, category, name, args_to_log)
+ try:
+ yield
+ finally:
+ end = trace_time.Now()
+ log.add_trace_event("E", end, category, name)
+
+def traced(*args):
+ def get_wrapper(func):
+ if inspect.isgeneratorfunction(func):
+ raise Exception("Can not trace generators.")
+
+ category = "python"
+
+ arg_spec = inspect.getargspec(func)
+ is_method = arg_spec.args and arg_spec.args[0] == "self"
+
+ def arg_spec_tuple(name):
+ arg_index = arg_spec.args.index(name)
+ defaults_length = len(arg_spec.defaults) if arg_spec.defaults else 0
+ default_index = arg_index + defaults_length - len(arg_spec.args)
+ if default_index >= 0:
+ default = arg_spec.defaults[default_index]
+ else:
+ default = None
+ return (name, arg_index, default)
+
+ args_to_log = map(arg_spec_tuple, arg_names)
+
+ @functools.wraps(func)
+ def traced_function(*args, **kwargs):
+ # Everything outside traced_function is done at decoration-time.
+ # Everything inside traced_function is done at run-time and must be fast.
+ if not log._enabled: # This check must be at run-time.
+ return func(*args, **kwargs)
+
+ def get_arg_value(name, index, default):
+ if name in kwargs:
+ return kwargs[name]
+ elif index < len(args):
+ return args[index]
+ else:
+ return default
+
+ if is_method:
+ name = "%s.%s" % (args[0].__class__.__name__, func.__name__)
+ else:
+ name = "%s.%s" % (func.__module__, func.__name__)
+
+ # Be sure to repr before calling func. Argument values may change.
+ arg_values = {
+ name: repr(get_arg_value(name, index, default))
+ for name, index, default in args_to_log}
+
+ start = trace_time.Now()
+ log.add_trace_event("B", start, category, name, arg_values)
+ try:
+ return func(*args, **kwargs)
+ finally:
+ end = trace_time.Now()
+ log.add_trace_event("E", end, category, name)
+ return traced_function
+
+ no_decorator_arguments = len(args) == 1 and callable(args[0])
+ if no_decorator_arguments:
+ arg_names = ()
+ return get_wrapper(args[0])
+ else:
+ arg_names = args
+ return get_wrapper
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators_test.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators_test.py
new file mode 100644
index 00000000000..5bb13ad8859
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators_test.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import decorators
+import logging
+import unittest
+
+from trace_test import TraceTest
+#from .trace_test import TraceTest
+
+def generator():
+ yield 1
+ yield 2
+
+class DecoratorTests(unittest.TestCase):
+ def test_tracing_object_fails(self):
+ self.assertRaises(Exception, lambda: decorators.trace(1))
+ self.assertRaises(Exception, lambda: decorators.trace(""))
+ self.assertRaises(Exception, lambda: decorators.trace([]))
+
+ def test_tracing_generators_fail(self):
+ self.assertRaises(Exception, lambda: decorators.trace(generator))
+
+class ClassToTest(object):
+ @decorators.traced
+ def method1(self):
+ return 1
+
+ @decorators.traced
+ def method2(self):
+ return 1
+
+@decorators.traced
+def traced_func():
+ return 1
+
+class DecoratorTests(TraceTest):
+ def _get_decorated_method_name(self, f):
+ res = self.go(f)
+ events = res.findEventsOnThread(res.findThreadIds()[0])
+
+ # Sanity checks.
+ self.assertEquals(2, len(events))
+ self.assertEquals(events[0]["name"], events[1]["name"])
+ return events[1]["name"]
+
+
+ def test_func_names_work(self):
+ self.assertEquals('__main__.traced_func',
+ self._get_decorated_method_name(traced_func))
+
+ def test_method_names_work(self):
+ ctt = ClassToTest()
+ self.assertEquals('ClassToTest.method1',
+ self._get_decorated_method_name(ctt.method1))
+ self.assertEquals('ClassToTest.method2',
+ self._get_decorated_method_name(ctt.method2))
+
+if __name__ == '__main__':
+ logging.getLogger().setLevel(logging.DEBUG)
+ unittest.main(verbosity=2)
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log.py
new file mode 100644
index 00000000000..2d69f083af0
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log.py
@@ -0,0 +1,183 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import atexit
+import json
+import os
+import sys
+import time
+import threading
+
+from py_trace_event import trace_time
+
+from py_utils import lock
+
+
+_lock = threading.Lock()
+
+_enabled = False
+_log_file = None
+
+_cur_events = [] # events that have yet to be buffered
+
+_tls = threading.local() # tls used to detect forking/etc
+_atexit_regsitered_for_pid = None
+
+_control_allowed = True
+
+
+class TraceException(Exception):
+ pass
+
+def _note(msg, *args):
+ pass
+# print "%i: %s" % (os.getpid(), msg)
+
+
+def _locked(fn):
+ def locked_fn(*args,**kwargs):
+ _lock.acquire()
+ try:
+ ret = fn(*args,**kwargs)
+ finally:
+ _lock.release()
+ return ret
+ return locked_fn
+
+def _disallow_tracing_control():
+ global _control_allowed
+ _control_allowed = False
+
+def trace_enable(log_file=None):
+ _trace_enable(log_file)
+
+@_locked
+def _trace_enable(log_file=None):
+ global _enabled
+ if _enabled:
+ raise TraceException("Already enabled")
+ if not _control_allowed:
+ raise TraceException("Tracing control not allowed in child processes.")
+ _enabled = True
+ global _log_file
+ if log_file == None:
+ if sys.argv[0] == '':
+ n = 'trace_event'
+ else:
+ n = sys.argv[0]
+ log_file = open("%s.json" % n, "ab", False)
+ _note("trace_event: tracelog name is %s.json" % n)
+ elif isinstance(log_file, basestring):
+ _note("trace_event: tracelog name is %s" % log_file)
+ log_file = open("%s" % log_file, "ab", False)
+ elif not hasattr(log_file, 'fileno'):
+ raise TraceException(
+ "Log file must be None, a string, or file-like object with a fileno()")
+
+ _log_file = log_file
+ with lock.FileLock(_log_file, lock.LOCK_EX):
+ _log_file.seek(0, os.SEEK_END)
+
+ lastpos = _log_file.tell()
+ creator = lastpos == 0
+ if creator:
+ _note("trace_event: Opened new tracelog, lastpos=%i", lastpos)
+ _log_file.write('[')
+
+ tid = threading.current_thread().ident
+ if not tid:
+ tid = os.getpid()
+ x = {"ph": "M", "category": "process_argv",
+ "pid": os.getpid(), "tid": threading.current_thread().ident,
+ "ts": trace_time.Now(),
+ "name": "process_argv", "args": {"argv": sys.argv}}
+ _log_file.write("%s\n" % json.dumps(x))
+ else:
+ _note("trace_event: Opened existing tracelog")
+ _log_file.flush()
+
+@_locked
+def trace_flush():
+ if _enabled:
+ _flush()
+
+@_locked
+def trace_disable():
+ global _enabled
+ if not _control_allowed:
+ raise TraceException("Tracing control not allowed in child processes.")
+ if not _enabled:
+ return
+ _enabled = False
+ _flush(close=True)
+
+def _flush(close=False):
+ global _log_file
+ with lock.FileLock(_log_file, lock.LOCK_EX):
+ _log_file.seek(0, os.SEEK_END)
+ if len(_cur_events):
+ _log_file.write(",\n")
+ _log_file.write(",\n".join([json.dumps(e) for e in _cur_events]))
+ del _cur_events[:]
+
+ if close:
+ # We might not be the only process writing to this logfile. So,
+ # we will simply close the file rather than writign the trailing ] that
+ # it technically requires. The trace viewer understands that this may
+ # happen and will insert a trailing ] during loading.
+ pass
+ _log_file.flush()
+
+ if close:
+ _note("trace_event: Closed")
+ _log_file.close()
+ _log_file = None
+ else:
+ _note("trace_event: Flushed")
+
+@_locked
+def trace_is_enabled():
+ return _enabled
+
+@_locked
+def add_trace_event(ph, ts, category, name, args=None):
+ global _enabled
+ if not _enabled:
+ return
+ if not hasattr(_tls, 'pid') or _tls.pid != os.getpid():
+ _tls.pid = os.getpid()
+ global _atexit_regsitered_for_pid
+ if _tls.pid != _atexit_regsitered_for_pid:
+ _atexit_regsitered_for_pid = _tls.pid
+ atexit.register(_trace_disable_atexit)
+ _tls.pid = os.getpid()
+ del _cur_events[:] # we forked, clear the event buffer!
+ tid = threading.current_thread().ident
+ if not tid:
+ tid = os.getpid()
+ _tls.tid = tid
+
+ _cur_events.append({"ph": ph,
+ "category": category,
+ "pid": _tls.pid,
+ "tid": _tls.tid,
+ "ts": ts,
+ "name": name,
+ "args": args or {}});
+
+def trace_begin(name, args=None):
+ add_trace_event("B", trace_time.Now(), "python", name, args)
+
+def trace_end(name, args=None):
+ add_trace_event("E", trace_time.Now(), "python", name, args)
+
+def trace_set_thread_name(thread_name):
+ add_trace_event("M", trace_time.Now(), "__metadata", "thread_name",
+ {"name": thread_name})
+
+def _trace_disable_atexit():
+ trace_disable()
+
+def is_tracing_controllable():
+ global _control_allowed
+ return _control_allowed
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log_io_test.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log_io_test.py
new file mode 100644
index 00000000000..99a062115bc
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log_io_test.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import sys
+import tempfile
+import unittest
+
+from log import *
+from parsed_trace_events import *
+
+
+class LogIOTest(unittest.TestCase):
+ def test_enable_with_file(self):
+ file = tempfile.NamedTemporaryFile()
+ trace_enable(open(file.name, 'w+'))
+ trace_disable()
+ e = ParsedTraceEvents(trace_filename = file.name)
+ file.close()
+ self.assertTrue(len(e) > 0)
+
+ def test_enable_with_filename(self):
+ file = tempfile.NamedTemporaryFile()
+ trace_enable(file.name)
+ trace_disable()
+ e = ParsedTraceEvents(trace_filename = file.name)
+ file.close()
+ self.assertTrue(len(e) > 0)
+
+ def test_enable_with_implicit_filename(self):
+ expected_filename = "%s.json" % sys.argv[0]
+ def do_work():
+ file = tempfile.NamedTemporaryFile()
+ trace_enable()
+ trace_disable()
+ e = ParsedTraceEvents(trace_filename = expected_filename)
+ file.close()
+ self.assertTrue(len(e) > 0)
+ try:
+ do_work()
+ finally:
+ if os.path.exists(expected_filename):
+ os.unlink(expected_filename)
+
+if __name__ == '__main__':
+ logging.getLogger().setLevel(logging.DEBUG)
+ unittest.main(verbosity=2)
+
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/meta_class.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/meta_class.py
new file mode 100644
index 00000000000..4ede79bd338
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/meta_class.py
@@ -0,0 +1,16 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import types
+
+from py_trace_event.trace_event_impl import decorators
+
+
+class TracedMetaClass(type):
+ def __new__(cls, name, bases, attrs):
+ for attr_name, attr_value in attrs.iteritems():
+ if isinstance(attr_value, types.FunctionType):
+ attrs[attr_name] = decorators.traced(attr_value)
+
+ return super(TracedMetaClass, cls).__new__(cls, name, bases, attrs)
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/multiprocessing_shim.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/multiprocessing_shim.py
new file mode 100644
index 00000000000..9796bdf9665
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/multiprocessing_shim.py
@@ -0,0 +1,92 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import multiprocessing
+import log
+import time
+
+
+_RealProcess = multiprocessing.Process
+__all__ = []
+
+
+class ProcessSubclass(_RealProcess):
+ def __init__(self, shim, *args, **kwards):
+ _RealProcess.__init__(self, *args, **kwards)
+ self._shim = shim
+
+ def run(self,*args,**kwargs):
+ log._disallow_tracing_control()
+ try:
+ r = _RealProcess.run(self, *args, **kwargs)
+ finally:
+ if log.trace_is_enabled():
+ log.trace_flush() # todo, reduce need for this...
+ return r
+
+class ProcessShim():
+ def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
+ self._proc = ProcessSubclass(self, group, target, name, args, kwargs)
+ # hint to testing code that the shimming worked
+ self._shimmed_by_trace_event = True
+
+ def run(self):
+ self._proc.run()
+
+ def start(self):
+ self._proc.start()
+
+ def terminate(self):
+ if log.trace_is_enabled():
+ # give the flush a chance to finish --> TODO: find some other way.
+ time.sleep(0.25)
+ self._proc.terminate()
+
+ def join(self, timeout=None):
+ self._proc.join( timeout)
+
+ def is_alive(self):
+ return self._proc.is_alive()
+
+ @property
+ def name(self):
+ return self._proc.name
+
+ @name.setter
+ def name(self, name):
+ self._proc.name = name
+
+ @property
+ def daemon(self):
+ return self._proc.daemon
+
+ @daemon.setter
+ def daemon(self, daemonic):
+ self._proc.daemon = daemonic
+
+ @property
+ def authkey(self):
+ return self._proc._authkey
+
+ @authkey.setter
+ def authkey(self, authkey):
+ self._proc.authkey = AuthenticationString(authkey)
+
+ @property
+ def exitcode(self):
+ return self._proc.exitcode
+
+ @property
+ def ident(self):
+ return self._proc.ident
+
+ @property
+ def pid(self):
+ return self._proc.pid
+
+ def __repr__(self):
+ return self._proc.__repr__()
+
+# Monkeypatch in our process replacement.
+if multiprocessing.Process != ProcessShim:
+ multiprocessing.Process = ProcessShim
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/parsed_trace_events.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/parsed_trace_events.py
new file mode 100644
index 00000000000..fdc7514542d
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/parsed_trace_events.py
@@ -0,0 +1,98 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import math
+import json
+
+
+class ParsedTraceEvents(object):
+ def __init__(self, events = None, trace_filename = None):
+ """
+ Utility class for filtering and manipulating trace data.
+
+ events -- An iterable object containing trace events
+ trace_filename -- A file object that contains a complete trace.
+
+ """
+ if trace_filename and events:
+ raise Exception("Provide either a trace file or event list")
+ if not trace_filename and events == None:
+ raise Exception("Provide either a trace file or event list")
+
+ if trace_filename:
+ f = open(trace_filename, 'r')
+ t = f.read()
+ f.close()
+
+ # If the event data begins with a [, then we know it should end with a ].
+ # The reason we check for this is because some tracing implementations
+ # cannot guarantee that a ']' gets written to the trace file. So, we are
+ # forgiving and if this is obviously the case, we fix it up before
+ # throwing the string at JSON.parse.
+ if t[0] == '[':
+ n = len(t);
+ if t[n - 1] != ']' and t[n - 1] != '\n':
+ t = t + ']'
+ elif t[n - 2] != ']' and t[n - 1] == '\n':
+ t = t + ']'
+ elif t[n - 3] != ']' and t[n - 2] == '\r' and t[n - 1] == '\n':
+ t = t + ']'
+
+ try:
+ events = json.loads(t)
+ except ValueError:
+ raise Exception("Corrupt trace, did not parse. Value: %s" % t)
+
+ if 'traceEvents' in events:
+ events = events['traceEvents']
+
+ if not hasattr(events, '__iter__'):
+ raise Exception, 'events must be iteraable.'
+ self.events = events
+ self.pids = None
+ self.tids = None
+
+ def __len__(self):
+ return len(self.events)
+
+ def __getitem__(self, i):
+ return self.events[i]
+
+ def __setitem__(self, i, v):
+ self.events[i] = v
+
+ def __repr__(self):
+ return "[%s]" % ",\n ".join([repr(e) for e in self.events])
+
+ def findProcessIds(self):
+ if self.pids:
+ return self.pids
+ pids = set()
+ for e in self.events:
+ if "pid" in e and e["pid"]:
+ pids.add(e["pid"])
+ self.pids = list(pids)
+ return self.pids
+
+ def findThreadIds(self):
+ if self.tids:
+ return self.tids
+ tids = set()
+ for e in self.events:
+ if "tid" in e and e["tid"]:
+ tids.add(e["tid"])
+ self.tids = list(tids)
+ return self.tids
+
+ def findEventsOnProcess(self, pid):
+ return ParsedTraceEvents([e for e in self.events if e["pid"] == pid])
+
+ def findEventsOnThread(self, tid):
+ return ParsedTraceEvents(
+ [e for e in self.events if e["ph"] != "M" and e["tid"] == tid])
+
+ def findByPhase(self, ph):
+ return ParsedTraceEvents([e for e in self.events if e["ph"] == ph])
+
+ def findByName(self, n):
+ return ParsedTraceEvents([e for e in self.events if e["name"] == n])
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/trace_test.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/trace_test.py
new file mode 100644
index 00000000000..7047e0eae86
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/trace_test.py
@@ -0,0 +1,48 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import tempfile
+import unittest
+
+#from .log import *
+#from .parsed_trace_events import *
+
+from log import *
+from parsed_trace_events import *
+
+class TraceTest(unittest.TestCase):
+ def __init__(self, *args):
+ """
+ Infrastructure for running tests of the tracing system.
+
+ Does not actually run any tests. Look at subclasses for those.
+ """
+ unittest.TestCase.__init__(self, *args)
+ self._file = None
+
+ def go(self, cb):
+ """
+ Enables tracing, runs the provided callback, and if successful, returns a
+ TraceEvents object with the results.
+ """
+ self._file = tempfile.NamedTemporaryFile()
+ trace_enable(open(self._file.name, 'a+'))
+
+ try:
+ cb()
+ finally:
+ trace_disable()
+ e = ParsedTraceEvents(trace_filename = self._file.name)
+ self._file.close()
+ self._file = None
+ return e
+
+ @property
+ def trace_filename(self):
+ return self._file.name
+
+ def tearDown(self):
+ if trace_is_enabled():
+ trace_disable()
+ if self._file:
+ self._file.close()
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_unittest.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_unittest.py
new file mode 100644
index 00000000000..f88ef953a31
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_event_unittest.py
@@ -0,0 +1,423 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import contextlib
+import json
+import logging
+import math
+import multiprocessing
+import os
+import tempfile
+import time
+import unittest
+
+from py_trace_event import trace_event
+from py_trace_event import trace_time
+from py_trace_event.trace_event_impl import log
+
+
+class TraceEventTests(unittest.TestCase):
+
+ def setUp(self):
+ tf = tempfile.NamedTemporaryFile(delete=False)
+ self._log_path = tf.name
+ tf.close()
+
+ def tearDown(self):
+ if os.path.exists(self._log_path):
+ os.remove(self._log_path)
+
+ @contextlib.contextmanager
+ def _test_trace(self, disable=True):
+ try:
+ trace_event.trace_enable(self._log_path)
+ yield
+ finally:
+ if disable:
+ trace_event.trace_disable()
+
+ def testNoImpl(self):
+ orig_impl = trace_event.trace_event_impl
+ try:
+ trace_event.trace_event_impl = None
+ self.assertFalse(trace_event.trace_can_enable())
+ finally:
+ trace_event.trace_event_impl = orig_impl
+
+ def testImpl(self):
+ self.assertTrue(trace_event.trace_can_enable())
+
+ def testIsEnabledFalse(self):
+ self.assertFalse(trace_event.trace_is_enabled())
+
+ def testIsEnabledTrue(self):
+ with self._test_trace():
+ self.assertTrue(trace_event.trace_is_enabled())
+
+ def testEnable(self):
+ with self._test_trace():
+ with open(self._log_path, 'r') as f:
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 1)
+ self.assertTrue(trace_event.trace_is_enabled())
+ log_output = log_output.pop()
+ self.assertEquals(log_output['category'], 'process_argv')
+ self.assertEquals(log_output['name'], 'process_argv')
+ self.assertTrue(log_output['args']['argv'])
+ self.assertEquals(log_output['ph'], 'M')
+
+ def testDoubleEnable(self):
+ try:
+ with self._test_trace():
+ with self._test_trace():
+ pass
+ except log.TraceException:
+ return
+ assert False
+
+ def testDisable(self):
+ with self._test_trace(disable=False):
+ with open(self._log_path, 'r') as f:
+ self.assertTrue(trace_event.trace_is_enabled())
+ trace_event.trace_disable()
+ self.assertEquals(len(json.loads(f.read() + ']')), 1)
+ self.assertFalse(trace_event.trace_is_enabled())
+
+ def testDoubleDisable(self):
+ with self._test_trace():
+ pass
+ trace_event.trace_disable()
+
+ def testFlushChanges(self):
+ with self._test_trace():
+ with open(self._log_path, 'r') as f:
+ trace_event.clock_sync('1')
+ self.assertEquals(len(json.loads(f.read() + ']')), 1)
+ f.seek(0)
+ trace_event.trace_flush()
+ self.assertEquals(len(json.loads(f.read() + ']')), 2)
+
+ def testFlushNoChanges(self):
+ with self._test_trace():
+ with open(self._log_path, 'r') as f:
+ self.assertEquals(len(json.loads(f.read() + ']')),1)
+ f.seek(0)
+ trace_event.trace_flush()
+ self.assertEquals(len(json.loads(f.read() + ']')), 1)
+
+ def testDoubleFlush(self):
+ with self._test_trace():
+ with open(self._log_path, 'r') as f:
+ trace_event.clock_sync('1')
+ self.assertEquals(len(json.loads(f.read() + ']')), 1)
+ f.seek(0)
+ trace_event.trace_flush()
+ trace_event.trace_flush()
+ self.assertEquals(len(json.loads(f.read() + ']')), 2)
+
+ def testTraceBegin(self):
+ with self._test_trace():
+ with open(self._log_path, 'r') as f:
+ trace_event.trace_begin('test_event', this='that')
+ trace_event.trace_flush()
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 2)
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'process_argv')
+ self.assertEquals(current_entry['name'], 'process_argv')
+ self.assertTrue( current_entry['args']['argv'])
+ self.assertEquals( current_entry['ph'], 'M')
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'python')
+ self.assertEquals(current_entry['name'], 'test_event')
+ self.assertEquals(current_entry['args']['this'], '\'that\'')
+ self.assertEquals(current_entry['ph'], 'B')
+
+ def testTraceEnd(self):
+ with self._test_trace():
+ with open(self._log_path, 'r') as f:
+ trace_event.trace_end('test_event')
+ trace_event.trace_flush()
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 2)
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'process_argv')
+ self.assertEquals(current_entry['name'], 'process_argv')
+ self.assertTrue(current_entry['args']['argv'])
+ self.assertEquals(current_entry['ph'], 'M')
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'python')
+ self.assertEquals(current_entry['name'], 'test_event')
+ self.assertEquals(current_entry['args'], {})
+ self.assertEquals(current_entry['ph'], 'E')
+
+ def testTrace(self):
+ with self._test_trace():
+ with trace_event.trace('test_event', this='that'):
+ pass
+ trace_event.trace_flush()
+ with open(self._log_path, 'r') as f:
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 3)
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'process_argv')
+ self.assertEquals(current_entry['name'], 'process_argv')
+ self.assertTrue(current_entry['args']['argv'])
+ self.assertEquals(current_entry['ph'], 'M')
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'python')
+ self.assertEquals(current_entry['name'], 'test_event')
+ self.assertEquals(current_entry['args']['this'], '\'that\'')
+ self.assertEquals(current_entry['ph'], 'B')
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'python')
+ self.assertEquals(current_entry['name'], 'test_event')
+ self.assertEquals(current_entry['args'], {})
+ self.assertEquals(current_entry['ph'], 'E')
+
+ def testTracedDecorator(self):
+ @trace_event.traced("this")
+ def test_decorator(this="that"):
+ pass
+
+ with self._test_trace():
+ test_decorator()
+ trace_event.trace_flush()
+ with open(self._log_path, 'r') as f:
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 3)
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'process_argv')
+ self.assertEquals(current_entry['name'], 'process_argv')
+ self.assertTrue(current_entry['args']['argv'])
+ self.assertEquals(current_entry['ph'], 'M')
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'python')
+ self.assertEquals(current_entry['name'], '__main__.test_decorator')
+ self.assertEquals(current_entry['args']['this'], '\'that\'')
+ self.assertEquals(current_entry['ph'], 'B')
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'python')
+ self.assertEquals(current_entry['name'], '__main__.test_decorator')
+ self.assertEquals(current_entry['args'], {})
+ self.assertEquals(current_entry['ph'], 'E')
+
+ def testClockSyncWithTs(self):
+ with self._test_trace():
+ with open(self._log_path, 'r') as f:
+ trace_event.clock_sync('id', issue_ts=trace_time.Now())
+ trace_event.trace_flush()
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 2)
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'process_argv')
+ self.assertEquals(current_entry['name'], 'process_argv')
+ self.assertTrue(current_entry['args']['argv'])
+ self.assertEquals(current_entry['ph'], 'M')
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'python')
+ self.assertEquals(current_entry['name'], 'clock_sync')
+ self.assertTrue(current_entry['args']['issue_ts'])
+ self.assertEquals(current_entry['ph'], 'c')
+
+ def testClockSyncWithoutTs(self):
+ with self._test_trace():
+ with open(self._log_path, 'r') as f:
+ trace_event.clock_sync('id')
+ trace_event.trace_flush()
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 2)
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'process_argv')
+ self.assertEquals(current_entry['name'], 'process_argv')
+ self.assertTrue(current_entry['args']['argv'])
+ self.assertEquals(current_entry['ph'], 'M')
+ current_entry = log_output.pop(0)
+ self.assertEquals(current_entry['category'], 'python')
+ self.assertEquals(current_entry['name'], 'clock_sync')
+ self.assertFalse(current_entry['args'].get('issue_ts'))
+ self.assertEquals(current_entry['ph'], 'c')
+
+ def testTime(self):
+ actual_diff = []
+ def func1():
+ trace_begin("func1")
+ start = time.time()
+ time.sleep(0.25)
+ end = time.time()
+ actual_diff.append(end-start) # Pass via array because of Python scoping
+ trace_end("func1")
+
+ with self._test_trace():
+ start_ts = time.time()
+ trace_event.trace_begin('test')
+ end_ts = time.time()
+ trace_event.trace_end('test')
+ trace_event.trace_flush()
+ with open(self._log_path, 'r') as f:
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 3)
+ meta_data = log_output[0]
+ open_data = log_output[1]
+ close_data = log_output[2]
+ self.assertEquals(meta_data['category'], 'process_argv')
+ self.assertEquals(meta_data['name'], 'process_argv')
+ self.assertTrue(meta_data['args']['argv'])
+ self.assertEquals(meta_data['ph'], 'M')
+ self.assertEquals(open_data['category'], 'python')
+ self.assertEquals(open_data['name'], 'test')
+ self.assertEquals(open_data['ph'], 'B')
+ self.assertEquals(close_data['category'], 'python')
+ self.assertEquals(close_data['name'], 'test')
+ self.assertEquals(close_data['ph'], 'E')
+ event_time_diff = close_data['ts'] - open_data['ts']
+ recorded_time_diff = (end_ts - start_ts) * 1000000
+ self.assertLess(math.fabs(event_time_diff - recorded_time_diff), 1000)
+
+ def testNestedCalls(self):
+ with self._test_trace():
+ trace_event.trace_begin('one')
+ trace_event.trace_begin('two')
+ trace_event.trace_end('two')
+ trace_event.trace_end('one')
+ trace_event.trace_flush()
+ with open(self._log_path, 'r') as f:
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 5)
+ meta_data = log_output[0]
+ one_open = log_output[1]
+ two_open = log_output[2]
+ two_close = log_output[3]
+ one_close = log_output[4]
+ self.assertEquals(meta_data['category'], 'process_argv')
+ self.assertEquals(meta_data['name'], 'process_argv')
+ self.assertTrue(meta_data['args']['argv'])
+ self.assertEquals(meta_data['ph'], 'M')
+
+ self.assertEquals(one_open['category'], 'python')
+ self.assertEquals(one_open['name'], 'one')
+ self.assertEquals(one_open['ph'], 'B')
+ self.assertEquals(one_close['category'], 'python')
+ self.assertEquals(one_close['name'], 'one')
+ self.assertEquals(one_close['ph'], 'E')
+
+ self.assertEquals(two_open['category'], 'python')
+ self.assertEquals(two_open['name'], 'two')
+ self.assertEquals(two_open['ph'], 'B')
+ self.assertEquals(two_close['category'], 'python')
+ self.assertEquals(two_close['name'], 'two')
+ self.assertEquals(two_close['ph'], 'E')
+
+ self.assertLessEqual(one_open['ts'], two_open['ts'])
+ self.assertGreaterEqual(one_close['ts'], two_close['ts'])
+
+ def testInterleavedCalls(self):
+ with self._test_trace():
+ trace_event.trace_begin('one')
+ trace_event.trace_begin('two')
+ trace_event.trace_end('one')
+ trace_event.trace_end('two')
+ trace_event.trace_flush()
+ with open(self._log_path, 'r') as f:
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 5)
+ meta_data = log_output[0]
+ one_open = log_output[1]
+ two_open = log_output[2]
+ two_close = log_output[4]
+ one_close = log_output[3]
+ self.assertEquals(meta_data['category'], 'process_argv')
+ self.assertEquals(meta_data['name'], 'process_argv')
+ self.assertTrue(meta_data['args']['argv'])
+ self.assertEquals(meta_data['ph'], 'M')
+
+ self.assertEquals(one_open['category'], 'python')
+ self.assertEquals(one_open['name'], 'one')
+ self.assertEquals(one_open['ph'], 'B')
+ self.assertEquals(one_close['category'], 'python')
+ self.assertEquals(one_close['name'], 'one')
+ self.assertEquals(one_close['ph'], 'E')
+
+ self.assertEquals(two_open['category'], 'python')
+ self.assertEquals(two_open['name'], 'two')
+ self.assertEquals(two_open['ph'], 'B')
+ self.assertEquals(two_close['category'], 'python')
+ self.assertEquals(two_close['name'], 'two')
+ self.assertEquals(two_close['ph'], 'E')
+
+ self.assertLessEqual(one_open['ts'], two_open['ts'])
+ self.assertLessEqual(one_close['ts'], two_close['ts'])
+
+ def testMultiprocess(self):
+ def child_function():
+ with trace_event.trace('child_event'):
+ pass
+
+ with self._test_trace():
+ trace_event.trace_begin('parent_event')
+ trace_event.trace_flush()
+ p = multiprocessing.Process(target=child_function)
+ p.start()
+ self.assertTrue(hasattr(p, "_shimmed_by_trace_event"))
+ p.join()
+ trace_event.trace_end('parent_event')
+ trace_event.trace_flush()
+ with open(self._log_path, 'r') as f:
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 5)
+ meta_data = log_output[0]
+ parent_open = log_output[1]
+ child_open = log_output[2]
+ child_close = log_output[3]
+ parent_close = log_output[4]
+ self.assertEquals(meta_data['category'], 'process_argv')
+ self.assertEquals(meta_data['name'], 'process_argv')
+ self.assertTrue(meta_data['args']['argv'])
+ self.assertEquals(meta_data['ph'], 'M')
+
+ self.assertEquals(parent_open['category'], 'python')
+ self.assertEquals(parent_open['name'], 'parent_event')
+ self.assertEquals(parent_open['ph'], 'B')
+
+ self.assertEquals(child_open['category'], 'python')
+ self.assertEquals(child_open['name'], 'child_event')
+ self.assertEquals(child_open['ph'], 'B')
+
+ self.assertEquals(child_close['category'], 'python')
+ self.assertEquals(child_close['name'], 'child_event')
+ self.assertEquals(child_close['ph'], 'E')
+
+ self.assertEquals(parent_close['category'], 'python')
+ self.assertEquals(parent_close['name'], 'parent_event')
+ self.assertEquals(parent_close['ph'], 'E')
+
+ def testMultiprocessExceptionInChild(self):
+ def bad_child():
+ trace_event.trace_disable()
+
+ with self._test_trace():
+ p = multiprocessing.Pool(1)
+ trace_event.trace_begin('parent')
+ self.assertRaises(Exception, lambda: p.apply(bad_child, ()))
+ p.close()
+ p.terminate()
+ p.join()
+ trace_event.trace_end('parent')
+ trace_event.trace_flush()
+ with open(self._log_path, 'r') as f:
+ log_output = json.loads(f.read() + ']')
+ self.assertEquals(len(log_output), 3)
+ meta_data = log_output[0]
+ parent_open = log_output[1]
+ parent_close = log_output[2]
+ self.assertEquals(parent_open['category'], 'python')
+ self.assertEquals(parent_open['name'], 'parent')
+ self.assertEquals(parent_open['ph'], 'B')
+ self.assertEquals(parent_close['category'], 'python')
+ self.assertEquals(parent_close['name'], 'parent')
+ self.assertEquals(parent_close['ph'], 'E')
+
+if __name__ == '__main__':
+ logging.getLogger().setLevel(logging.DEBUG)
+ unittest.main(verbosity=2)
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_time.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_time.py
new file mode 100644
index 00000000000..c5e3fe1ed92
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_time.py
@@ -0,0 +1,234 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import ctypes
+import ctypes.util
+import logging
+import os
+import platform
+import sys
+import time
+import threading
+
+
+GET_TICK_COUNT_LAST_NOW = 0
+# If GET_TICK_COUNTER_LAST_NOW is less than the current time, the clock has
+# rolled over, and this needs to be accounted for.
+GET_TICK_COUNT_WRAPAROUNDS = 0
+# The current detected platform
+_CLOCK = None
+_NOW_FUNCTION = None
+# Mapping of supported platforms and what is returned by sys.platform.
+_PLATFORMS = {
+ 'mac': 'darwin',
+ 'linux': 'linux',
+ 'windows': 'win32',
+ 'cygwin': 'cygwin',
+ 'freebsd': 'freebsd',
+ 'sunos': 'sunos5',
+ 'bsd': 'bsd'
+}
+# Mapping of what to pass get_clocktime based on platform.
+_CLOCK_MONOTONIC = {
+ 'linux': 1,
+ 'freebsd': 4,
+ 'bsd': 3,
+ 'sunos5': 4
+}
+
+_LINUX_CLOCK = 'LINUX_CLOCK_MONOTONIC'
+_MAC_CLOCK = 'MAC_MACH_ABSOLUTE_TIME'
+_WIN_HIRES = 'WIN_QPC'
+_WIN_LORES = 'WIN_ROLLOVER_PROTECTED_TIME_GET_TIME'
+
+def InitializeMacNowFunction(plat):
+ """Sets a monotonic clock for the Mac platform.
+
+ Args:
+ plat: Platform that is being run on. Unused in GetMacNowFunction. Passed
+ for consistency between initilaizers.
+ """
+ del plat # Unused
+ global _CLOCK # pylint: disable=global-statement
+ global _NOW_FUNCTION # pylint: disable=global-statement
+ _CLOCK = _MAC_CLOCK
+ libc = ctypes.CDLL('/usr/lib/libc.dylib', use_errno=True)
+ class MachTimebaseInfoData(ctypes.Structure):
+ """System timebase info. Defined in <mach/mach_time.h>."""
+ _fields_ = (('numer', ctypes.c_uint32),
+ ('denom', ctypes.c_uint32))
+
+ mach_absolute_time = libc.mach_absolute_time
+ mach_absolute_time.restype = ctypes.c_uint64
+
+ timebase = MachTimebaseInfoData()
+ libc.mach_timebase_info(ctypes.byref(timebase))
+ ticks_per_second = timebase.numer / timebase.denom * 1.0e9
+
+ def MacNowFunctionImpl():
+ return mach_absolute_time() / ticks_per_second
+ _NOW_FUNCTION = MacNowFunctionImpl
+
+
+def GetClockGetTimeClockNumber(plat):
+ for key in _CLOCK_MONOTONIC:
+ if plat.startswith(key):
+ return _CLOCK_MONOTONIC[key]
+ raise LookupError('Platform not in clock dicitonary')
+
+def InitializeLinuxNowFunction(plat):
+ """Sets a monotonic clock for linux platforms.
+
+ Args:
+ plat: Platform that is being run on.
+ """
+ global _CLOCK # pylint: disable=global-statement
+ global _NOW_FUNCTION # pylint: disable=global-statement
+ _CLOCK = _LINUX_CLOCK
+ clock_monotonic = GetClockGetTimeClockNumber(plat)
+ try:
+ # Attempt to find clock_gettime in the C library.
+ clock_gettime = ctypes.CDLL(ctypes.util.find_library('c'),
+ use_errno=True).clock_gettime
+ except AttributeError:
+ # If not able to find int in the C library, look in rt library.
+ clock_gettime = ctypes.CDLL(ctypes.util.find_library('rt'),
+ use_errno=True).clock_gettime
+
+ class Timespec(ctypes.Structure):
+ """Time specification, as described in clock_gettime(3)."""
+ _fields_ = (('tv_sec', ctypes.c_long),
+ ('tv_nsec', ctypes.c_long))
+
+ def LinuxNowFunctionImpl():
+ ts = Timespec()
+ if clock_gettime(clock_monotonic, ctypes.pointer(ts)):
+ errno = ctypes.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return ts.tv_sec + ts.tv_nsec / 1.0e9
+
+ _NOW_FUNCTION = LinuxNowFunctionImpl
+
+
+def IsQPCUsable():
+ """Determines if system can query the performance counter.
+ The performance counter is a high resolution timer on windows systems.
+ Some chipsets have unreliable performance counters, so this checks that one
+ of those chipsets is not present.
+
+ Returns:
+ True if QPC is useable, false otherwise.
+ """
+
+ # Sample output: 'Intel64 Family 6 Model 23 Stepping 6, GenuineIntel'
+ info = platform.processor()
+ if 'AuthenticAMD' in info and 'Family 15' in info:
+ return False
+ if not hasattr(ctypes, 'windll'):
+ return False
+ try: # If anything goes wrong during this, assume QPC isn't available.
+ frequency = ctypes.c_int64()
+ ctypes.windll.Kernel32.QueryPerformanceFrequency(
+ ctypes.byref(frequency))
+ if float(frequency.value) <= 0:
+ return False
+ except Exception: # pylint: disable=broad-except
+ logging.exception('Error when determining if QPC is usable.')
+ return False
+ return True
+
+
+def InitializeWinNowFunction(plat):
+ """Sets a monotonic clock for windows platforms.
+
+ Args:
+ plat: Platform that is being run on.
+ """
+ global _CLOCK # pylint: disable=global-statement
+ global _NOW_FUNCTION # pylint: disable=global-statement
+
+ if IsQPCUsable():
+ _CLOCK = _WIN_HIRES
+ qpc_return = ctypes.c_int64()
+ qpc_frequency = ctypes.c_int64()
+ ctypes.windll.Kernel32.QueryPerformanceFrequency(
+ ctypes.byref(qpc_frequency))
+ qpc_frequency = float(qpc_frequency.value)
+ qpc = ctypes.windll.Kernel32.QueryPerformanceCounter
+
+ def WinNowFunctionImpl():
+ qpc(ctypes.byref(qpc_return))
+ return qpc_return.value / qpc_frequency
+
+ else:
+ _CLOCK = _WIN_LORES
+ kernel32 = (ctypes.cdll.kernel32
+ if plat.startswith(_PLATFORMS['cygwin'])
+ else ctypes.windll.kernel32)
+ get_tick_count_64 = getattr(kernel32, 'GetTickCount64', None)
+
+ # Windows Vista or newer
+ if get_tick_count_64:
+ get_tick_count_64.restype = ctypes.c_ulonglong
+
+ def WinNowFunctionImpl():
+ return get_tick_count_64() / 1000.0
+
+ else: # Pre Vista.
+ get_tick_count = kernel32.GetTickCount
+ get_tick_count.restype = ctypes.c_uint32
+ get_tick_count_lock = threading.Lock()
+
+ def WinNowFunctionImpl():
+ global GET_TICK_COUNT_LAST_NOW # pylint: disable=global-statement
+ global GET_TICK_COUNT_WRAPAROUNDS # pylint: disable=global-statement
+ with get_tick_count_lock:
+ current_sample = get_tick_count()
+ if current_sample < GET_TICK_COUNT_LAST_NOW:
+ GET_TICK_COUNT_WRAPAROUNDS += 1
+ GET_TICK_COUNT_LAST_NOW = current_sample
+ final_ms = GET_TICK_COUNT_WRAPAROUNDS << 32
+ final_ms += GET_TICK_COUNT_LAST_NOW
+ return final_ms / 1000.0
+
+ _NOW_FUNCTION = WinNowFunctionImpl
+
+
+def InitializeNowFunction(plat):
+ """Sets a monotonic clock for the current platform.
+
+ Args:
+ plat: Platform that is being run on.
+ """
+ if plat.startswith(_PLATFORMS['mac']):
+ InitializeMacNowFunction(plat)
+
+ elif (plat.startswith(_PLATFORMS['linux'])
+ or plat.startswith(_PLATFORMS['freebsd'])
+ or plat.startswith(_PLATFORMS['bsd'])
+ or plat.startswith(_PLATFORMS['sunos'])):
+ InitializeLinuxNowFunction(plat)
+
+ elif (plat.startswith(_PLATFORMS['windows'])
+ or plat.startswith(_PLATFORMS['cygwin'])):
+ InitializeWinNowFunction(plat)
+
+ else:
+ raise RuntimeError('%s is not a supported platform.' % plat)
+
+ global _NOW_FUNCTION
+ global _CLOCK
+ assert _NOW_FUNCTION, 'Now function not properly set during initialization.'
+ assert _CLOCK, 'Clock not properly set during initialization.'
+
+
+def Now():
+ return _NOW_FUNCTION() * 1e6 # convert from seconds to microseconds
+
+
+def GetClock():
+ return _CLOCK
+
+
+InitializeNowFunction(sys.platform)
diff --git a/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_time_unittest.py b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_time_unittest.py
new file mode 100644
index 00000000000..ab54bd6d47c
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_trace_event/py_trace_event/trace_time_unittest.py
@@ -0,0 +1,123 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import contextlib
+import logging
+import platform
+import sys
+import unittest
+
+from py_trace_event import trace_time
+
+
+class TimerTest(unittest.TestCase):
+ # Helper methods.
+ @contextlib.contextmanager
+ def ReplacePlatformProcessorCall(self, f):
+ try:
+ old_proc = platform.processor
+ platform.processor = f
+ yield
+ finally:
+ platform.processor = old_proc
+
+ @contextlib.contextmanager
+ def ReplaceQPCCheck(self, f):
+ try:
+ old_qpc = trace_time.IsQPCUsable
+ trace_time.IsQPCUsable = f
+ yield
+ finally:
+ trace_time.IsQPCUsable = old_qpc
+
+ # Platform detection tests.
+ def testInitializeNowFunction_platformNotSupported(self):
+ with self.assertRaises(RuntimeError):
+ trace_time.InitializeNowFunction('invalid_platform')
+
+ def testInitializeNowFunction_windows(self):
+ if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
+ or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
+ return True
+ trace_time.InitializeNowFunction(sys.platform)
+ self.assertTrue(trace_time.GetClock() == trace_time._WIN_HIRES
+ or trace_time.GetClock() == trace_time._WIN_LORES)
+
+ def testInitializeNowFunction_linux(self):
+ if not sys.platform.startswith(trace_time._PLATFORMS['linux']):
+ return True
+ trace_time.InitializeNowFunction(sys.platform)
+ self.assertEqual(trace_time.GetClock(), trace_time._LINUX_CLOCK)
+
+ def testInitializeNowFunction_mac(self):
+ if not sys.platform.startswith(trace_time._PLATFORMS['mac']):
+ return True
+ trace_time.InitializeNowFunction(sys.platform)
+ self.assertEqual(trace_time.GetClock(), trace_time._MAC_CLOCK)
+
+ # Windows Tests
+ def testIsQPCUsable_buggyAthlonProcReturnsFalse(self):
+ if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
+ or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
+ return True
+
+ def BuggyAthlonProc():
+ return 'AMD64 Family 15 Model 23 Stepping 6, AuthenticAMD'
+
+ with self.ReplacePlatformProcessorCall(BuggyAthlonProc):
+ self.assertFalse(trace_time.IsQPCUsable())
+
+ def testIsQPCUsable_returnsTrueOnWindows(self):
+ if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
+ or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
+ return True
+
+ def Proc():
+ return 'Intel64 Family 15 Model 23 Stepping 6, GenuineIntel'
+
+ with self.ReplacePlatformProcessorCall(Proc):
+ self.assertTrue(trace_time.IsQPCUsable())
+
+ def testGetWinNowFunction_QPC(self):
+ if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
+ or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
+ return True
+ # Test requires QPC to be available on platform.
+ if not trace_time.IsQPCUsable():
+ return True
+ self.assertGreater(trace_time.monotonic(), 0)
+
+ # Works even if QPC would work.
+ def testGetWinNowFunction_GetTickCount(self):
+ if not (sys.platform.startswith(trace_time._PLATFORMS['windows'])
+ or sys.platform.startswith(trace_time._PLATFORMS['cygwin'])):
+ return True
+ with self.ReplaceQPCCheck(lambda: False):
+ self.assertGreater(trace_time.monotonic(), 0)
+
+ # Linux tests.
+ def testGetClockGetTimeClockNumber_linux(self):
+ self.assertEquals(trace_time.GetClockGetTimeClockNumber('linux'), 1)
+
+ def testGetClockGetTimeClockNumber_freebsd(self):
+ self.assertEquals(trace_time.GetClockGetTimeClockNumber('freebsd'), 4)
+
+ def testGetClockGetTimeClockNumber_bsd(self):
+ self.assertEquals(trace_time.GetClockGetTimeClockNumber('bsd'), 3)
+
+ def testGetClockGetTimeClockNumber_sunos(self):
+ self.assertEquals(trace_time.GetClockGetTimeClockNumber('sunos5'), 4)
+
+ # Smoke Test.
+ def testMonotonic(self):
+ time_one = trace_time.Now()
+ for _ in xrange(1000):
+ time_two = trace_time.Now()
+ self.assertLessEqual(time_one, time_two)
+ time_one = time_two
+
+
+if __name__ == '__main__':
+ logging.getLogger().setLevel(logging.DEBUG)
+ unittest.main(verbosity=2)
diff --git a/chromium/third_party/catapult/common/py_utils/PRESUBMIT.py b/chromium/third_party/catapult/common/py_utils/PRESUBMIT.py
new file mode 100644
index 00000000000..c1d92fe0031
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/PRESUBMIT.py
@@ -0,0 +1,31 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return _CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return _CommonChecks(input_api, output_api)
+
+
+def _CommonChecks(input_api, output_api):
+ results = []
+ results += input_api.RunTests(input_api.canned_checks.GetPylint(
+ input_api, output_api, extra_paths_list=_GetPathsToPrepend(input_api),
+ pylintrc='../../pylintrc'))
+ return results
+
+
+def _GetPathsToPrepend(input_api):
+ project_dir = input_api.PresubmitLocalPath()
+ catapult_dir = input_api.os_path.join(project_dir, '..', '..')
+ return [
+ project_dir,
+ input_api.os_path.join(catapult_dir, 'dependency_manager'),
+ input_api.os_path.join(catapult_dir, 'devil'),
+ input_api.os_path.join(catapult_dir, 'third_party', 'mock'),
+ input_api.os_path.join(catapult_dir, 'third_party', 'pyfakefs'),
+ ]
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/__init__.py b/chromium/third_party/catapult/common/py_utils/py_utils/__init__.py
new file mode 100644
index 00000000000..0d7b052af6f
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/__init__.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import functools
+import inspect
+import os
+import sys
+import time
+import platform
+
+
+def GetCatapultDir():
+ return os.path.normpath(
+ os.path.join(os.path.dirname(__file__), '..', '..', '..'))
+
+
+def IsRunningOnCrosDevice():
+ """Returns True if we're on a ChromeOS device."""
+ lsb_release = '/etc/lsb-release'
+ if sys.platform.startswith('linux') and os.path.exists(lsb_release):
+ with open(lsb_release, 'r') as f:
+ res = f.read()
+ if res.count('CHROMEOS_RELEASE_NAME'):
+ return True
+ return False
+
+
+def GetHostOsName():
+ if IsRunningOnCrosDevice():
+ return 'chromeos'
+ elif sys.platform.startswith('linux'):
+ return 'linux'
+ elif sys.platform == 'darwin':
+ return 'mac'
+ elif sys.platform == 'win32':
+ return 'win'
+
+
+def GetHostArchName():
+ return platform.machine()
+
+
+def _ExecutableExtensions():
+ # pathext is, e.g. '.com;.exe;.bat;.cmd'
+ exts = os.getenv('PATHEXT').split(';') #e.g. ['.com','.exe','.bat','.cmd']
+ return [x[1:].upper() for x in exts] #e.g. ['COM','EXE','BAT','CMD']
+
+
+def IsExecutable(path):
+ if os.path.isfile(path):
+ if hasattr(os, 'name') and os.name == 'nt':
+ return path.split('.')[-1].upper() in _ExecutableExtensions()
+ else:
+ return os.access(path, os.X_OK)
+ else:
+ return False
+
+
+def _AddDirToPythonPath(*path_parts):
+ path = os.path.abspath(os.path.join(*path_parts))
+ if os.path.isdir(path) and path not in sys.path:
+ # Some callsite that use telemetry assumes that sys.path[0] is the directory
+ # containing the script, so we add these extra paths to right after it.
+ sys.path.insert(1, path)
+
+_AddDirToPythonPath(os.path.join(GetCatapultDir(), 'devil'))
+_AddDirToPythonPath(os.path.join(GetCatapultDir(), 'dependency_manager'))
+_AddDirToPythonPath(os.path.join(GetCatapultDir(), 'third_party', 'mock'))
+# mox3 is needed for pyfakefs usage, but not for pylint.
+_AddDirToPythonPath(os.path.join(GetCatapultDir(), 'third_party', 'mox3'))
+_AddDirToPythonPath(
+ os.path.join(GetCatapultDir(), 'third_party', 'pyfakefs'))
+
+from devil.utils import timeout_retry # pylint: disable=wrong-import-position
+from devil.utils import reraiser_thread # pylint: disable=wrong-import-position
+
+
+# Decorator that adds timeout functionality to a function.
+def Timeout(default_timeout):
+ return lambda func: TimeoutDeco(func, default_timeout)
+
+# Note: Even though the "timeout" keyword argument is the only
+# keyword argument that will need to be given to the decorated function,
+# we still have to use the **kwargs syntax, because we have to use
+# the *args syntax here before (since the decorator decorates functions
+# with different numbers of positional arguments) and Python doesn't allow
+# a single named keyword argument after *args.
+# (e.g., 'def foo(*args, bar=42):' is a syntax error)
+
+def TimeoutDeco(func, default_timeout):
+ @functools.wraps(func)
+ def RunWithTimeout(*args, **kwargs):
+ if 'timeout' in kwargs:
+ timeout = kwargs['timeout']
+ else:
+ timeout = default_timeout
+ try:
+ return timeout_retry.Run(func, timeout, 0, args=args)
+ except reraiser_thread.TimeoutError:
+ print('%s timed out.' % func.__name__)
+ return False
+ return RunWithTimeout
+
+
+MIN_POLL_INTERVAL_IN_SECONDS = 0.1
+MAX_POLL_INTERVAL_IN_SECONDS = 5
+OUTPUT_INTERVAL_IN_SECONDS = 300
+
+def WaitFor(condition, timeout):
+ """Waits for up to |timeout| secs for the function |condition| to return True.
+
+ Polling frequency is (elapsed_time / 10), with a min of .1s and max of 5s.
+
+ Returns:
+ Result of |condition| function (if present).
+ """
+ def GetConditionString():
+ if condition.__name__ == '<lambda>':
+ try:
+ return inspect.getsource(condition).strip()
+ except IOError:
+ pass
+ return condition.__name__
+
+ # Do an initial check to see if its true.
+ res = condition()
+ if res:
+ return res
+ start_time = time.time()
+ last_output_time = start_time
+ elapsed_time = time.time() - start_time
+ while elapsed_time < timeout:
+ res = condition()
+ if res:
+ return res
+ now = time.time()
+ elapsed_time = now - start_time
+ last_output_elapsed_time = now - last_output_time
+ if last_output_elapsed_time > OUTPUT_INTERVAL_IN_SECONDS:
+ last_output_time = time.time()
+ poll_interval = min(max(elapsed_time / 10., MIN_POLL_INTERVAL_IN_SECONDS),
+ MAX_POLL_INTERVAL_IN_SECONDS)
+ time.sleep(poll_interval)
+ raise TimeoutException('Timed out while waiting %ds for %s.' %
+ (timeout, GetConditionString()))
+
+class TimeoutException(Exception):
+ """The operation failed to complete because of a timeout.
+
+ It is possible that waiting for a longer period of time would result in a
+ successful operation.
+ """
+ pass
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/atexit_with_log.py b/chromium/third_party/catapult/common/py_utils/py_utils/atexit_with_log.py
new file mode 100644
index 00000000000..f217c094366
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/atexit_with_log.py
@@ -0,0 +1,21 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import atexit
+import logging
+
+
+def _WrapFunction(function):
+ def _WrappedFn(*args, **kwargs):
+ logging.debug('Try running %s', repr(function))
+ try:
+ function(*args, **kwargs)
+ logging.debug('Did run %s', repr(function))
+ except Exception: # pylint: disable=broad-except
+ logging.exception('Exception running %s', repr(function))
+ return _WrappedFn
+
+
+def Register(function, *args, **kwargs):
+ atexit.register(_WrapFunction(function), *args, **kwargs)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/binary_manager.py b/chromium/third_party/catapult/common/py_utils/py_utils/binary_manager.py
new file mode 100644
index 00000000000..2d3ac8a6cf6
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/binary_manager.py
@@ -0,0 +1,61 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+
+import dependency_manager
+
+
+class BinaryManager(object):
+ """ This class is effectively a subclass of dependency_manager, but uses a
+ different number of arguments for FetchPath and LocalPath.
+ """
+
+ def __init__(self, config_files):
+ if not config_files or not isinstance(config_files, list):
+ raise ValueError(
+ 'Must supply a list of config files to the BinaryManager')
+ configs = [dependency_manager.BaseConfig(config) for config in config_files]
+ self._dependency_manager = dependency_manager.DependencyManager(configs)
+
+ def FetchPathWithVersion(self, binary_name, os_name, arch, os_version=None):
+ """ Return a path to the executable for <binary_name>, or None if not found.
+
+ Will attempt to download from cloud storage if needed.
+ """
+ return self._WrapDependencyManagerFunction(
+ self._dependency_manager.FetchPathWithVersion, binary_name, os_name,
+ arch, os_version)
+
+ def FetchPath(self, binary_name, os_name, arch, os_version=None):
+ """ Return a path to the executable for <binary_name>, or None if not found.
+
+ Will attempt to download from cloud storage if needed.
+ """
+ return self._WrapDependencyManagerFunction(
+ self._dependency_manager.FetchPath, binary_name, os_name, arch,
+ os_version)
+
+ def LocalPath(self, binary_name, os_name, arch, os_version=None):
+ """ Return a local path to the given binary name, or None if not found.
+
+ Will not download from cloud_storage.
+ """
+ return self._WrapDependencyManagerFunction(
+ self._dependency_manager.LocalPath, binary_name, os_name, arch,
+ os_version)
+
+ def _WrapDependencyManagerFunction(
+ self, function, binary_name, os_name, arch, os_version):
+ platform = '%s_%s' % (os_name, arch)
+ if os_version:
+ try:
+ versioned_platform = '%s_%s_%s' % (os_name, os_version, arch)
+ return function(binary_name, versioned_platform)
+ except dependency_manager.NoPathFoundError:
+ logging.warning(
+ 'Cannot find path for %s on platform %s. Falling back to %s.',
+ binary_name, versioned_platform, platform)
+ return function(binary_name, platform)
+
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/binary_manager_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/binary_manager_unittest.py
new file mode 100644
index 00000000000..ccf21ad11c9
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/binary_manager_unittest.py
@@ -0,0 +1,214 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+
+from pyfakefs import fake_filesystem_unittest
+from dependency_manager import exceptions
+
+from py_utils import binary_manager
+
+class BinaryManagerTest(fake_filesystem_unittest.TestCase):
+ # TODO(aiolos): disable cloud storage use during this test.
+
+ def setUp(self):
+ self.setUpPyfakefs()
+ # pylint: disable=bad-continuation
+ self.expected_dependencies = {
+ 'dep_1': {
+ 'cloud_storage_base_folder': 'dependencies/fake_config',
+ 'cloud_storage_bucket': 'chrome-tel',
+ 'file_info': {
+ 'linux_x86_64': {
+ 'cloud_storage_hash': '661ce936b3276f7ec3d687ab62be05b96d796f21',
+ 'download_path': 'bin/linux/x86_64/dep_1'
+ },
+ 'mac_x86_64': {
+ 'cloud_storage_hash': 'c7b1bfc6399dc683058e88dac1ef0f877edea74b',
+ 'download_path': 'bin/mac/x86_64/dep_1'
+ },
+ 'win_AMD64': {
+ 'cloud_storage_hash': 'ac4fee89a51662b9d920bce443c19b9b2929b198',
+ 'download_path': 'bin/win/AMD64/dep_1.exe'
+ },
+ 'win_x86': {
+ 'cloud_storage_hash': 'e246e183553ea26967d7b323ea269e3357b9c837',
+ 'download_path': 'bin/win/x86/dep_1.exe'
+ }
+ }
+ },
+ 'dep_2': {
+ 'cloud_storage_base_folder': 'dependencies/fake_config',
+ 'cloud_storage_bucket': 'chrome-tel',
+ 'file_info': {
+ 'linux_x86_64': {
+ 'cloud_storage_hash': '13a57efae9a680ac0f160b3567e02e81f4ac493c',
+ 'download_path': 'bin/linux/x86_64/dep_2',
+ 'local_paths': [
+ '../../example/location/linux/dep_2',
+ '../../example/location2/linux/dep_2'
+ ]
+ },
+ 'mac_x86_64': {
+ 'cloud_storage_hash': 'd10c0ddaa8586b20449e951216bee852fa0f8850',
+ 'download_path': 'bin/mac/x86_64/dep_2',
+ 'local_paths': [
+ '../../example/location/mac/dep_2',
+ '../../example/location2/mac/dep_2'
+ ]
+ },
+ 'win_AMD64': {
+ 'cloud_storage_hash': 'fd5b417f78c7f7d9192a98967058709ded1d399d',
+ 'download_path': 'bin/win/AMD64/dep_2.exe',
+ 'local_paths': [
+ '../../example/location/win64/dep_2',
+ '../../example/location2/win64/dep_2'
+ ]
+ },
+ 'win_x86': {
+ 'cloud_storage_hash': 'cf5c8fe920378ce30d057e76591d57f63fd31c1a',
+ 'download_path': 'bin/win/x86/dep_2.exe',
+ 'local_paths': [
+ '../../example/location/win32/dep_2',
+ '../../example/location2/win32/dep_2'
+ ]
+ },
+ 'android_k_x64': {
+ 'cloud_storage_hash': '09177be2fed00b44df0e777932828425440b23b3',
+ 'download_path': 'bin/android/x64/k/dep_2.apk',
+ 'local_paths': [
+ '../../example/location/android_x64/k/dep_2',
+ '../../example/location2/android_x64/k/dep_2'
+ ]
+ },
+ 'android_l_x64': {
+ 'cloud_storage_hash': '09177be2fed00b44df0e777932828425440b23b3',
+ 'download_path': 'bin/android/x64/l/dep_2.apk',
+ 'local_paths': [
+ '../../example/location/android_x64/l/dep_2',
+ '../../example/location2/android_x64/l/dep_2'
+ ]
+ },
+ 'android_k_x86': {
+ 'cloud_storage_hash': 'bcf02af039713a48b69b89bd7f0f9c81ed8183a4',
+ 'download_path': 'bin/android/x86/k/dep_2.apk',
+ 'local_paths': [
+ '../../example/location/android_x86/k/dep_2',
+ '../../example/location2/android_x86/k/dep_2'
+ ]
+ },
+ 'android_l_x86': {
+ 'cloud_storage_hash': '12a74cec071017ba11655b5740b8a58e2f52a219',
+ 'download_path': 'bin/android/x86/l/dep_2.apk',
+ 'local_paths': [
+ '../../example/location/android_x86/l/dep_2',
+ '../../example/location2/android_x86/l/dep_2'
+ ]
+ }
+ }
+ },
+ 'dep_3': {
+ 'file_info': {
+ 'linux_x86_64': {
+ 'local_paths': [
+ '../../example/location/linux/dep_3',
+ '../../example/location2/linux/dep_3'
+ ]
+ },
+ 'mac_x86_64': {
+ 'local_paths': [
+ '../../example/location/mac/dep_3',
+ '../../example/location2/mac/dep_3'
+ ]
+ },
+ 'win_AMD64': {
+ 'local_paths': [
+ '../../example/location/win64/dep_3',
+ '../../example/location2/win64/dep_3'
+ ]
+ },
+ 'win_x86': {
+ 'local_paths': [
+ '../../example/location/win32/dep_3',
+ '../../example/location2/win32/dep_3'
+ ]
+ }
+ }
+ }
+ }
+ # pylint: enable=bad-continuation
+ fake_config = {
+ 'config_type': 'BaseConfig',
+ 'dependencies': self.expected_dependencies
+ }
+
+ self.base_config = os.path.join(os.path.dirname(__file__),
+ 'example_config.json')
+ self.fs.CreateFile(self.base_config, contents=json.dumps(fake_config))
+ linux_file = os.path.join(
+ os.path.dirname(self.base_config),
+ os.path.join('..', '..', 'example', 'location2', 'linux', 'dep_2'))
+ android_file = os.path.join(
+ os.path.dirname(self.base_config),
+ '..', '..', 'example', 'location', 'android_x86', 'l', 'dep_2')
+ self.expected_dep2_linux_file = os.path.abspath(linux_file)
+ self.expected_dep2_android_file = os.path.abspath(android_file)
+ self.fs.CreateFile(self.expected_dep2_linux_file)
+ self.fs.CreateFile(self.expected_dep2_android_file)
+
+ def tearDown(self):
+ self.tearDownPyfakefs()
+
+ def testInitializationNoConfig(self):
+ with self.assertRaises(ValueError):
+ binary_manager.BinaryManager(None)
+
+ def testInitializationMissingConfig(self):
+ with self.assertRaises(ValueError):
+ binary_manager.BinaryManager(os.path.join('missing', 'path'))
+
+ def testInitializationWithConfig(self):
+ with self.assertRaises(ValueError):
+ manager = binary_manager.BinaryManager(self.base_config)
+ manager = binary_manager.BinaryManager([self.base_config])
+ self.assertItemsEqual(self.expected_dependencies,
+ manager._dependency_manager._lookup_dict)
+
+ def testSuccessfulFetchPathNoOsVersion(self):
+ manager = binary_manager.BinaryManager([self.base_config])
+ found_path = manager.FetchPath('dep_2', 'linux', 'x86_64')
+ self.assertEqual(self.expected_dep2_linux_file, found_path)
+
+ def testSuccessfulFetchPathOsVersion(self):
+ manager = binary_manager.BinaryManager([self.base_config])
+ found_path = manager.FetchPath('dep_2', 'android', 'x86', 'l')
+ self.assertEqual(self.expected_dep2_android_file, found_path)
+
+ def testSuccessfulFetchPathFallbackToNoOsVersion(self):
+ manager = binary_manager.BinaryManager([self.base_config])
+ found_path = manager.FetchPath('dep_2', 'linux', 'x86_64', 'fake_version')
+ self.assertEqual(self.expected_dep2_linux_file, found_path)
+
+ def testFailedFetchPathMissingDep(self):
+ manager = binary_manager.BinaryManager([self.base_config])
+ with self.assertRaises(exceptions.NoPathFoundError):
+ manager.FetchPath('missing_dep', 'linux', 'x86_64')
+ with self.assertRaises(exceptions.NoPathFoundError):
+ manager.FetchPath('missing_dep', 'android', 'x86', 'l')
+ with self.assertRaises(exceptions.NoPathFoundError):
+ manager.FetchPath('dep_1', 'linux', 'bad_arch')
+ with self.assertRaises(exceptions.NoPathFoundError):
+ manager.FetchPath('dep_1', 'bad_os', 'x86')
+
+ def testSuccessfulLocalPathNoOsVersion(self):
+ manager = binary_manager.BinaryManager([self.base_config])
+ found_path = manager.LocalPath('dep_2', 'linux', 'x86_64')
+ self.assertEqual(self.expected_dep2_linux_file, found_path)
+
+ def testSuccessfulLocalPathOsVersion(self):
+ manager = binary_manager.BinaryManager([self.base_config])
+ found_path = manager.LocalPath('dep_2', 'android', 'x86', 'l')
+ self.assertEqual(self.expected_dep2_android_file, found_path)
+
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/camel_case.py b/chromium/third_party/catapult/common/py_utils/py_utils/camel_case.py
new file mode 100644
index 00000000000..9a76890222d
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/camel_case.py
@@ -0,0 +1,30 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+
+
+def ToUnderscore(obj):
+ """Converts a string, list, or dict from camelCase to lower_with_underscores.
+
+ Descends recursively into lists and dicts, converting all dict keys.
+ Returns a newly allocated object of the same structure as the input.
+ """
+ if isinstance(obj, basestring):
+ return re.sub('(?!^)([A-Z]+)', r'_\1', obj).lower()
+
+ elif isinstance(obj, list):
+ return [ToUnderscore(item) for item in obj]
+
+ elif isinstance(obj, dict):
+ output = {}
+ for k, v in obj.iteritems():
+ if isinstance(v, list) or isinstance(v, dict):
+ output[ToUnderscore(k)] = ToUnderscore(v)
+ else:
+ output[ToUnderscore(k)] = v
+ return output
+
+ else:
+ return obj
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/camel_case_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/camel_case_unittest.py
new file mode 100644
index 00000000000..c748ba2f433
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/camel_case_unittest.py
@@ -0,0 +1,50 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from py_utils import camel_case
+
+
+class CamelCaseTest(unittest.TestCase):
+
+ def testString(self):
+ self.assertEqual(camel_case.ToUnderscore('camelCase'), 'camel_case')
+ self.assertEqual(camel_case.ToUnderscore('CamelCase'), 'camel_case')
+ self.assertEqual(camel_case.ToUnderscore('Camel2Case'), 'camel2_case')
+ self.assertEqual(camel_case.ToUnderscore('Camel2Case2'), 'camel2_case2')
+ self.assertEqual(camel_case.ToUnderscore('2012Q3'), '2012_q3')
+
+ def testList(self):
+ camel_case_list = ['CamelCase', ['NestedList']]
+ underscore_list = ['camel_case', ['nested_list']]
+ self.assertEqual(camel_case.ToUnderscore(camel_case_list), underscore_list)
+
+ def testDict(self):
+ camel_case_dict = {
+ 'gpu': {
+ 'vendorId': 1000,
+ 'deviceId': 2000,
+ 'vendorString': 'aString',
+ 'deviceString': 'bString'},
+ 'secondaryGpus': [
+ {'vendorId': 3000, 'deviceId': 4000,
+ 'vendorString': 'k', 'deviceString': 'l'}
+ ]
+ }
+ underscore_dict = {
+ 'gpu': {
+ 'vendor_id': 1000,
+ 'device_id': 2000,
+ 'vendor_string': 'aString',
+ 'device_string': 'bString'},
+ 'secondary_gpus': [
+ {'vendor_id': 3000, 'device_id': 4000,
+ 'vendor_string': 'k', 'device_string': 'l'}
+ ]
+ }
+ self.assertEqual(camel_case.ToUnderscore(camel_case_dict), underscore_dict)
+
+ def testOther(self):
+ self.assertEqual(camel_case.ToUnderscore(self), self)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/chrome_binaries.json b/chromium/third_party/catapult/common/py_utils/py_utils/chrome_binaries.json
new file mode 100644
index 00000000000..8a9b6bfe29a
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/chrome_binaries.json
@@ -0,0 +1,91 @@
+{
+ "config_type": "BaseConfig",
+ "dependencies": {
+ "chrome_canary": {
+ "cloud_storage_base_folder": "binary_dependencies",
+ "cloud_storage_bucket": "chrome-telemetry",
+ "file_info": {
+ "mac_x86_64": {
+ "cloud_storage_hash": "6278cf24b700076fd17ae8616fd980d18f33ed5d",
+ "download_path": "bin/reference_builds/chrome-mac64.zip",
+ "path_within_archive": "chrome-mac/Google Chrome.app/Contents/MacOS/Google Chrome",
+ "version_in_cs": "70.0.3509.0"
+ },
+ "win_AMD64": {
+ "cloud_storage_hash": "a78facdb295d2ee36aaf5af89e54b5c5fcd48f7c",
+ "download_path": "bin\\reference_build\\chrome-win64-clang.zip",
+ "path_within_archive": "chrome-win64-clang\\chrome.exe",
+ "version_in_cs": "70.0.3509.0"
+ },
+ "win_x86": {
+ "cloud_storage_hash": "348e8133c5fa687864a3d8eff13ed5be6852e95d",
+ "download_path": "bin\\reference_build\\chrome-win32-clang.zip",
+ "path_within_archive": "chrome-win32-clang\\chrome.exe",
+ "version_in_cs": "70.0.3509.0"
+ }
+ }
+ },
+ "chrome_dev": {
+ "cloud_storage_base_folder": "binary_dependencies",
+ "cloud_storage_bucket": "chrome-telemetry",
+ "file_info": {
+ "linux_x86_64": {
+ "cloud_storage_hash": "1ef8d8ebf114b47aecf11a36c21377376ced3794",
+ "download_path": "bin/reference_build/chrome-linux64.zip",
+ "path_within_archive": "chrome-linux64/chrome",
+ "version_in_cs": "69.0.3497.23"
+ }
+ }
+ },
+ "chrome_stable": {
+ "cloud_storage_base_folder": "binary_dependencies",
+ "cloud_storage_bucket": "chrome-telemetry",
+ "file_info": {
+ "android_k_armeabi-v7a": {
+ "cloud_storage_hash": "5a4cc68b2ef5e6073f9f8f42987155d5fc8a3c48",
+ "download_path": "bin/reference_build/android_k_armeabi-v7a/ChromeStable.apk",
+ "version_in_cs": "68.0.3440.85"
+ },
+ "android_l_arm64-v8a": {
+ "cloud_storage_hash": "42d527ca74e99fb9398826204db09c8740df7fd4",
+ "download_path": "bin/reference_build/android_l_arm64-v8a/ChromeStable.apk",
+ "version_in_cs": "68.0.3440.85"
+ },
+ "android_l_armeabi-v7a": {
+ "cloud_storage_hash": "5a4cc68b2ef5e6073f9f8f42987155d5fc8a3c48",
+ "download_path": "bin/reference_build/android_l_armeabi-v7a/ChromeStable.apk",
+ "version_in_cs": "68.0.3440.85"
+ },
+ "android_n_armeabi-v7a": {
+ "cloud_storage_hash": "d37f47a804e815daf001f65d0c13a2cf38641f3e",
+ "download_path": "bin/reference_build/android_n_armeabi-v7a/Monochrome.apk",
+ "version_in_cs": "68.0.3440.85"
+ },
+ "linux_x86_64": {
+ "cloud_storage_hash": "aab60e4a4ee4f3d638aa6a33e52ffb6423fa7080",
+ "download_path": "bin/reference_build/chrome-linux64.zip",
+ "path_within_archive": "chrome-linux64/chrome",
+ "version_in_cs": "68.0.3440.84"
+ },
+ "mac_x86_64": {
+ "cloud_storage_hash": "8a020bc9caa2526408dc23044e8dcfaaf6b6948e",
+ "download_path": "bin/reference_builds/chrome-mac64.zip",
+ "path_within_archive": "chrome-mac/Google Chrome.app/Contents/MacOS/Google Chrome",
+ "version_in_cs": "68.0.3440.84"
+ },
+ "win_AMD64": {
+ "cloud_storage_hash": "19da10346662d8e791076a0ddcfbf2a435b6915a",
+ "download_path": "bin\\reference_build\\chrome-win64-clang.zip",
+ "path_within_archive": "chrome-win64-clang\\chrome.exe",
+ "version_in_cs": "68.0.3440.84"
+ },
+ "win_x86": {
+ "cloud_storage_hash": "760ff8661550f6aebadedba99075efe6adae3414",
+ "download_path": "bin\\reference_build\\chrome-win-clang.zip",
+ "path_within_archive": "chrome-win-clang\\chrome.exe",
+ "version_in_cs": "68.0.3440.84"
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/class_util.py b/chromium/third_party/catapult/common/py_utils/py_utils/class_util.py
new file mode 100644
index 00000000000..4cec430038b
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/class_util.py
@@ -0,0 +1,26 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import inspect
+
+def IsMethodOverridden(parent_cls, child_cls, method_name):
+ assert inspect.isclass(parent_cls), '%s should be a class' % parent_cls
+ assert inspect.isclass(child_cls), '%s should be a class' % child_cls
+ assert parent_cls.__dict__.get(method_name), '%s has no method %s' % (
+ parent_cls, method_name)
+
+ if child_cls.__dict__.get(method_name):
+ # It's overridden
+ return True
+
+ if parent_cls in child_cls.__bases__:
+ # The parent is the base class of the child, we did not find the
+ # overridden method.
+ return False
+
+ # For all the base classes of this class that are not object, check if
+ # they override the method.
+ base_cls = [cls for cls in child_cls.__bases__ if cls and cls != object]
+ return any(
+ IsMethodOverridden(parent_cls, base, method_name) for base in base_cls)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/class_util_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/class_util_unittest.py
new file mode 100644
index 00000000000..938bcdc7b81
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/class_util_unittest.py
@@ -0,0 +1,138 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from py_utils import class_util
+
+
+class ClassUtilTest(unittest.TestCase):
+
+ def testClassOverridden(self):
+ class Parent(object):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ class Child(Parent):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ self.assertTrue(class_util.IsMethodOverridden(
+ Parent, Child, 'MethodShouldBeOverridden'))
+
+ def testGrandchildOverridden(self):
+ class Parent(object):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ class Child(Parent):
+ pass
+
+ class Grandchild(Child):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ self.assertTrue(class_util.IsMethodOverridden(
+ Parent, Grandchild, 'MethodShouldBeOverridden'))
+
+ def testClassNotOverridden(self):
+ class Parent(object):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ class Child(Parent):
+ def SomeOtherMethod(self):
+ pass
+
+ self.assertFalse(class_util.IsMethodOverridden(
+ Parent, Child, 'MethodShouldBeOverridden'))
+
+ def testGrandchildNotOverridden(self):
+ class Parent(object):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ class Child(Parent):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ class Grandchild(Child):
+ def SomeOtherMethod(self):
+ pass
+
+ self.assertTrue(class_util.IsMethodOverridden(
+ Parent, Grandchild, 'MethodShouldBeOverridden'))
+
+ def testClassNotPresentInParent(self):
+ class Parent(object):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ class Child(Parent):
+ def MethodShouldBeOverridden(self):
+ pass
+
+ self.assertRaises(
+ AssertionError, class_util.IsMethodOverridden,
+ Parent, Child, 'WrongMethod')
+
+ def testInvalidClass(self):
+ class Foo(object):
+ def Bar(self):
+ pass
+
+ self.assertRaises(
+ AssertionError, class_util.IsMethodOverridden, 'invalid', Foo, 'Bar')
+
+ self.assertRaises(
+ AssertionError, class_util.IsMethodOverridden, Foo, 'invalid', 'Bar')
+
+ def testMultipleInheritance(self):
+ class Aaa(object):
+ def One(self):
+ pass
+
+ class Bbb(object):
+ def Two(self):
+ pass
+
+ class Ccc(Aaa, Bbb):
+ pass
+
+ class Ddd(object):
+ def Three(self):
+ pass
+
+ class Eee(Ddd):
+ def Three(self):
+ pass
+
+ class Fff(Ccc, Eee):
+ def One(self):
+ pass
+
+ class Ggg(object):
+ def Four(self):
+ pass
+
+ class Hhh(Fff, Ggg):
+ def Two(self):
+ pass
+
+ class Iii(Hhh):
+ pass
+
+ class Jjj(Iii):
+ pass
+
+ self.assertFalse(class_util.IsMethodOverridden(Aaa, Ccc, 'One'))
+ self.assertTrue(class_util.IsMethodOverridden(Aaa, Fff, 'One'))
+ self.assertTrue(class_util.IsMethodOverridden(Aaa, Hhh, 'One'))
+ self.assertTrue(class_util.IsMethodOverridden(Aaa, Jjj, 'One'))
+ self.assertFalse(class_util.IsMethodOverridden(Bbb, Ccc, 'Two'))
+ self.assertTrue(class_util.IsMethodOverridden(Bbb, Hhh, 'Two'))
+ self.assertTrue(class_util.IsMethodOverridden(Bbb, Jjj, 'Two'))
+ self.assertFalse(class_util.IsMethodOverridden(Eee, Fff, 'Three'))
+
+
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage.py b/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage.py
new file mode 100644
index 00000000000..df5589b7e10
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage.py
@@ -0,0 +1,502 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Wrappers for gsutil, for basic interaction with Google Cloud Storage."""
+
+import collections
+import contextlib
+import hashlib
+import logging
+import os
+import shutil
+import stat
+import subprocess
+import re
+import sys
+import tempfile
+import time
+
+import py_utils
+from py_utils import lock
+
+# Do a no-op import here so that cloud_storage_global_lock dep is picked up
+# by https://cs.chromium.org/chromium/src/build/android/test_runner.pydeps.
+# TODO(nedn, jbudorick): figure out a way to get rid of this ugly hack.
+from py_utils import cloud_storage_global_lock # pylint: disable=unused-import
+
+logger = logging.getLogger(__name__) # pylint: disable=invalid-name
+
+
+PUBLIC_BUCKET = 'chromium-telemetry'
+PARTNER_BUCKET = 'chrome-partner-telemetry'
+INTERNAL_BUCKET = 'chrome-telemetry'
+TELEMETRY_OUTPUT = 'chrome-telemetry-output'
+
+# Uses ordered dict to make sure that bucket's key-value items are ordered from
+# the most open to the most restrictive.
+BUCKET_ALIASES = collections.OrderedDict((
+ ('public', PUBLIC_BUCKET),
+ ('partner', PARTNER_BUCKET),
+ ('internal', INTERNAL_BUCKET),
+ ('output', TELEMETRY_OUTPUT),
+))
+
+BUCKET_ALIAS_NAMES = BUCKET_ALIASES.keys()
+
+
+_GSUTIL_PATH = os.path.join(py_utils.GetCatapultDir(), 'third_party', 'gsutil',
+ 'gsutil')
+
+# TODO(tbarzic): A workaround for http://crbug.com/386416 and
+# http://crbug.com/359293. See |_RunCommand|.
+_CROS_GSUTIL_HOME_WAR = '/home/chromeos-test/'
+
+
+# If Environment variables has DISABLE_CLOUD_STORAGE_IO set to '1', any method
+# calls that invoke cloud storage network io will throw exceptions.
+DISABLE_CLOUD_STORAGE_IO = 'DISABLE_CLOUD_STORAGE_IO'
+
+# The maximum number of seconds to wait to acquire the pseudo lock for a cloud
+# storage file before raising an exception.
+LOCK_ACQUISITION_TIMEOUT = 10
+
+
+class CloudStorageError(Exception):
+
+ @staticmethod
+ def _GetConfigInstructions():
+ command = _GSUTIL_PATH
+ if py_utils.IsRunningOnCrosDevice():
+ command = 'HOME=%s %s' % (_CROS_GSUTIL_HOME_WAR, _GSUTIL_PATH)
+ return ('To configure your credentials:\n'
+ ' 1. Run "%s config" and follow its instructions.\n'
+ ' 2. If you have a @google.com account, use that account.\n'
+ ' 3. For the project-id, just enter 0.' % command)
+
+
+class PermissionError(CloudStorageError):
+
+ def __init__(self):
+ super(PermissionError, self).__init__(
+ 'Attempted to access a file from Cloud Storage but you don\'t '
+ 'have permission. ' + self._GetConfigInstructions())
+
+
+class CredentialsError(CloudStorageError):
+
+ def __init__(self):
+ super(CredentialsError, self).__init__(
+ 'Attempted to access a file from Cloud Storage but you have no '
+ 'configured credentials. ' + self._GetConfigInstructions())
+
+
+class CloudStorageIODisabled(CloudStorageError):
+ pass
+
+
+class NotFoundError(CloudStorageError):
+ pass
+
+
+class ServerError(CloudStorageError):
+ pass
+
+
+# TODO(tonyg/dtu): Can this be replaced with distutils.spawn.find_executable()?
+def _FindExecutableInPath(relative_executable_path, *extra_search_paths):
+ search_paths = list(extra_search_paths) + os.environ['PATH'].split(os.pathsep)
+ for search_path in search_paths:
+ executable_path = os.path.join(search_path, relative_executable_path)
+ if py_utils.IsExecutable(executable_path):
+ return executable_path
+ return None
+
+
+def _EnsureExecutable(gsutil):
+ """chmod +x if gsutil is not executable."""
+ st = os.stat(gsutil)
+ if not st.st_mode & stat.S_IEXEC:
+ os.chmod(gsutil, st.st_mode | stat.S_IEXEC)
+
+
+def _IsRunningOnSwarming():
+ return os.environ.get('SWARMING_HEADLESS') is not None
+
+def _RunCommand(args):
+ # On cros device, as telemetry is running as root, home will be set to /root/,
+ # which is not writable. gsutil will attempt to create a download tracker dir
+ # in home dir and fail. To avoid this, override HOME dir to something writable
+ # when running on cros device.
+ #
+ # TODO(tbarzic): Figure out a better way to handle gsutil on cros.
+ # http://crbug.com/386416, http://crbug.com/359293.
+ gsutil_env = None
+ if py_utils.IsRunningOnCrosDevice():
+ gsutil_env = os.environ.copy()
+ gsutil_env['HOME'] = _CROS_GSUTIL_HOME_WAR
+ elif _IsRunningOnSwarming():
+ gsutil_env = os.environ.copy()
+
+ if os.name == 'nt':
+ # If Windows, prepend python. Python scripts aren't directly executable.
+ args = [sys.executable, _GSUTIL_PATH] + args
+ else:
+ # Don't do it on POSIX, in case someone is using a shell script to redirect.
+ args = [_GSUTIL_PATH] + args
+ _EnsureExecutable(_GSUTIL_PATH)
+
+ if args[0] not in ('help', 'hash', 'version') and not IsNetworkIOEnabled():
+ raise CloudStorageIODisabled(
+ "Environment variable DISABLE_CLOUD_STORAGE_IO is set to 1. "
+ 'Command %s is not allowed to run' % args)
+
+ gsutil = subprocess.Popen(args, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, env=gsutil_env)
+ stdout, stderr = gsutil.communicate()
+
+ if gsutil.returncode:
+ raise GetErrorObjectForCloudStorageStderr(stderr)
+
+ return stdout
+
+
+def GetErrorObjectForCloudStorageStderr(stderr):
+ if (stderr.startswith((
+ 'You are attempting to access protected data with no configured',
+ 'Failure: No handler was ready to authenticate.')) or
+ re.match('.*401.*does not have .* access to .*', stderr)):
+ return CredentialsError()
+ if ('status=403' in stderr or 'status 403' in stderr or
+ '403 Forbidden' in stderr or
+ re.match('.*403.*does not have .* access to .*', stderr)):
+ return PermissionError()
+ if (stderr.startswith('InvalidUriError') or 'No such object' in stderr or
+ 'No URLs matched' in stderr or 'One or more URLs matched no' in stderr):
+ return NotFoundError(stderr)
+ if '500 Internal Server Error' in stderr:
+ return ServerError(stderr)
+ return CloudStorageError(stderr)
+
+
+def IsNetworkIOEnabled():
+ """Returns true if cloud storage is enabled."""
+ disable_cloud_storage_env_val = os.getenv(DISABLE_CLOUD_STORAGE_IO)
+
+ if disable_cloud_storage_env_val and disable_cloud_storage_env_val != '1':
+ logger.error(
+ 'Unsupported value of environment variable '
+ 'DISABLE_CLOUD_STORAGE_IO. Expected None or \'1\' but got %s.',
+ disable_cloud_storage_env_val)
+
+ return disable_cloud_storage_env_val != '1'
+
+
+def List(bucket):
+ query = 'gs://%s/' % bucket
+ stdout = _RunCommand(['ls', query])
+ return [url[len(query):] for url in stdout.splitlines()]
+
+
+def Exists(bucket, remote_path):
+ try:
+ _RunCommand(['ls', 'gs://%s/%s' % (bucket, remote_path)])
+ return True
+ except NotFoundError:
+ return False
+
+
+def Move(bucket1, bucket2, remote_path):
+ url1 = 'gs://%s/%s' % (bucket1, remote_path)
+ url2 = 'gs://%s/%s' % (bucket2, remote_path)
+ logger.info('Moving %s to %s', url1, url2)
+ _RunCommand(['mv', url1, url2])
+
+
+def Copy(bucket_from, bucket_to, remote_path_from, remote_path_to):
+ """Copy a file from one location in CloudStorage to another.
+
+ Args:
+ bucket_from: The cloud storage bucket where the file is currently located.
+ bucket_to: The cloud storage bucket it is being copied to.
+ remote_path_from: The file path where the file is located in bucket_from.
+ remote_path_to: The file path it is being copied to in bucket_to.
+
+ It should: cause no changes locally or to the starting file, and will
+ overwrite any existing files in the destination location.
+ """
+ url1 = 'gs://%s/%s' % (bucket_from, remote_path_from)
+ url2 = 'gs://%s/%s' % (bucket_to, remote_path_to)
+ logger.info('Copying %s to %s', url1, url2)
+ _RunCommand(['cp', url1, url2])
+
+
+def Delete(bucket, remote_path):
+ url = 'gs://%s/%s' % (bucket, remote_path)
+ logger.info('Deleting %s', url)
+ _RunCommand(['rm', url])
+
+
+def Get(bucket, remote_path, local_path):
+ with _FileLock(local_path):
+ _GetLocked(bucket, remote_path, local_path)
+
+
+_CLOUD_STORAGE_GLOBAL_LOCK = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), 'cloud_storage_global_lock.py')
+
+
+@contextlib.contextmanager
+def _FileLock(base_path):
+ pseudo_lock_path = '%s.pseudo_lock' % base_path
+ _CreateDirectoryIfNecessary(os.path.dirname(pseudo_lock_path))
+
+ # Make sure that we guard the creation, acquisition, release, and removal of
+ # the pseudo lock all with the same guard (_CLOUD_STORAGE_GLOBAL_LOCK).
+ # Otherwise, we can get nasty interleavings that result in multiple processes
+ # thinking they have an exclusive lock, like:
+ #
+ # (Process 1) Create and acquire the pseudo lock
+ # (Process 1) Release the pseudo lock
+ # (Process 1) Release the file lock
+ # (Process 2) Open and acquire the existing pseudo lock
+ # (Process 1) Delete the (existing) pseudo lock
+ # (Process 3) Create and acquire a new pseudo lock
+ #
+ # Using the same guard for creation and removal of the pseudo lock guarantees
+ # that all processes are referring to the same lock.
+ pseudo_lock_fd = None
+ pseudo_lock_fd_return = []
+ py_utils.WaitFor(lambda: _AttemptPseudoLockAcquisition(pseudo_lock_path,
+ pseudo_lock_fd_return),
+ LOCK_ACQUISITION_TIMEOUT)
+ pseudo_lock_fd = pseudo_lock_fd_return[0]
+
+ try:
+ yield
+ finally:
+ py_utils.WaitFor(lambda: _AttemptPseudoLockRelease(pseudo_lock_fd),
+ LOCK_ACQUISITION_TIMEOUT)
+
+def _AttemptPseudoLockAcquisition(pseudo_lock_path, pseudo_lock_fd_return):
+ """Try to acquire the lock and return a boolean indicating whether the attempt
+ was successful. If the attempt was successful, pseudo_lock_fd_return, which
+ should be an empty array, will be modified to contain a single entry: the file
+ descriptor of the (now acquired) lock file.
+
+ This whole operation is guarded with the global cloud storage lock, which
+ prevents race conditions that might otherwise cause multiple processes to
+ believe they hold the same pseudo lock (see _FileLock for more details).
+ """
+ pseudo_lock_fd = None
+ try:
+ with open(_CLOUD_STORAGE_GLOBAL_LOCK) as global_file:
+ with lock.FileLock(global_file, lock.LOCK_EX | lock.LOCK_NB):
+ # Attempt to acquire the lock in a non-blocking manner. If we block,
+ # then we'll cause deadlock because another process will be unable to
+ # acquire the cloud storage global lock in order to release the pseudo
+ # lock.
+ pseudo_lock_fd = open(pseudo_lock_path, 'w')
+ lock.AcquireFileLock(pseudo_lock_fd, lock.LOCK_EX | lock.LOCK_NB)
+ pseudo_lock_fd_return.append(pseudo_lock_fd)
+ return True
+ except (lock.LockException, IOError):
+ # We failed to acquire either the global cloud storage lock or the pseudo
+ # lock.
+ if pseudo_lock_fd:
+ pseudo_lock_fd.close()
+ return False
+
+
+def _AttemptPseudoLockRelease(pseudo_lock_fd):
+ """Try to release the pseudo lock and return a boolean indicating whether
+ the release was succesful.
+
+ This whole operation is guarded with the global cloud storage lock, which
+ prevents race conditions that might otherwise cause multiple processes to
+ believe they hold the same pseudo lock (see _FileLock for more details).
+ """
+ pseudo_lock_path = pseudo_lock_fd.name
+ try:
+ with open(_CLOUD_STORAGE_GLOBAL_LOCK) as global_file:
+ with lock.FileLock(global_file, lock.LOCK_EX | lock.LOCK_NB):
+ lock.ReleaseFileLock(pseudo_lock_fd)
+ pseudo_lock_fd.close()
+ try:
+ os.remove(pseudo_lock_path)
+ except OSError:
+ # We don't care if the pseudo lock gets removed elsewhere before
+ # we have a chance to do so.
+ pass
+ return True
+ except (lock.LockException, IOError):
+ # We failed to acquire the global cloud storage lock and are thus unable to
+ # release the pseudo lock.
+ return False
+
+
+def _CreateDirectoryIfNecessary(directory):
+ if not os.path.exists(directory):
+ os.makedirs(directory)
+
+
+def _GetLocked(bucket, remote_path, local_path):
+ url = 'gs://%s/%s' % (bucket, remote_path)
+ logger.info('Downloading %s to %s', url, local_path)
+ _CreateDirectoryIfNecessary(os.path.dirname(local_path))
+ with tempfile.NamedTemporaryFile(
+ dir=os.path.dirname(local_path),
+ delete=False) as partial_download_path:
+ try:
+ # Windows won't download to an open file.
+ partial_download_path.close()
+ try:
+ _RunCommand(['cp', url, partial_download_path.name])
+ except ServerError:
+ logger.info('Cloud Storage server error, retrying download')
+ _RunCommand(['cp', url, partial_download_path.name])
+ shutil.move(partial_download_path.name, local_path)
+ finally:
+ if os.path.exists(partial_download_path.name):
+ os.remove(partial_download_path.name)
+
+
+def Insert(bucket, remote_path, local_path, publicly_readable=False):
+ """ Upload file in |local_path| to cloud storage.
+ Args:
+ bucket: the google cloud storage bucket name.
+ remote_path: the remote file path in |bucket|.
+ local_path: path of the local file to be uploaded.
+ publicly_readable: whether the uploaded file has publicly readable
+ permission.
+
+ Returns:
+ The url where the file is uploaded to.
+ """
+ url = 'gs://%s/%s' % (bucket, remote_path)
+ command_and_args = ['cp']
+ extra_info = ''
+ if publicly_readable:
+ command_and_args += ['-a', 'public-read']
+ extra_info = ' (publicly readable)'
+ command_and_args += [local_path, url]
+ logger.info('Uploading %s to %s%s', local_path, url, extra_info)
+ _RunCommand(command_and_args)
+ return 'https://console.developers.google.com/m/cloudstorage/b/%s/o/%s' % (
+ bucket, remote_path)
+
+
+def GetIfHashChanged(cs_path, download_path, bucket, file_hash):
+ """Downloads |download_path| to |file_path| if |file_path| doesn't exist or
+ it's hash doesn't match |file_hash|.
+
+ Returns:
+ True if the binary was changed.
+ Raises:
+ CredentialsError if the user has no configured credentials.
+ PermissionError if the user does not have permission to access the bucket.
+ NotFoundError if the file is not in the given bucket in cloud_storage.
+ """
+ with _FileLock(download_path):
+ if (os.path.exists(download_path) and
+ CalculateHash(download_path) == file_hash):
+ return False
+ _GetLocked(bucket, cs_path, download_path)
+ return True
+
+
+def GetIfChanged(file_path, bucket):
+ """Gets the file at file_path if it has a hash file that doesn't match or
+ if there is no local copy of file_path, but there is a hash file for it.
+
+ Returns:
+ True if the binary was changed.
+ Raises:
+ CredentialsError if the user has no configured credentials.
+ PermissionError if the user does not have permission to access the bucket.
+ NotFoundError if the file is not in the given bucket in cloud_storage.
+ """
+ with _FileLock(file_path):
+ hash_path = file_path + '.sha1'
+ fetch_ts_path = file_path + '.fetchts'
+ if not os.path.exists(hash_path):
+ logger.warning('Hash file not found: %s', hash_path)
+ return False
+
+ expected_hash = ReadHash(hash_path)
+
+ # To save the time required computing binary hash (which is an expensive
+ # operation, see crbug.com/793609#c2 for details), any time we fetch a new
+ # binary, we save not only that binary but the time of the fetch in
+ # |fetch_ts_path|. Anytime the file needs updated (its
+ # hash in |hash_path| change), we can just need to compare the timestamp of
+ # |hash_path| with the timestamp in |fetch_ts_path| to figure out
+ # if the update operation has been done.
+ #
+ # Notes: for this to work, we make the assumption that only
+ # cloud_storage.GetIfChanged modifies the local |file_path| binary.
+
+ if os.path.exists(fetch_ts_path) and os.path.exists(file_path):
+ with open(fetch_ts_path) as f:
+ data = f.read().strip()
+ last_binary_fetch_ts = float(data)
+
+ if last_binary_fetch_ts > os.path.getmtime(hash_path):
+ return False
+
+ # Whether the binary stored in local already has hash matched
+ # expected_hash or we need to fetch new binary from cloud, update the
+ # timestamp in |fetch_ts_path| with current time anyway since it is
+ # outdated compared with sha1's last modified time.
+ with open(fetch_ts_path, 'w') as f:
+ f.write(str(time.time()))
+
+ if os.path.exists(file_path) and CalculateHash(file_path) == expected_hash:
+ return False
+ _GetLocked(bucket, expected_hash, file_path)
+ if CalculateHash(file_path) != expected_hash:
+ os.remove(fetch_ts_path)
+ raise RuntimeError(
+ 'Binary stored in cloud storage does not have hash matching .sha1 '
+ 'file. Please make sure that the binary file is uploaded using '
+ 'depot_tools/upload_to_google_storage.py script or through automatic '
+ 'framework.')
+ return True
+
+
+def GetFilesInDirectoryIfChanged(directory, bucket):
+ """ Scan the directory for .sha1 files, and download them from the given
+ bucket in cloud storage if the local and remote hash don't match or
+ there is no local copy.
+ """
+ if not os.path.isdir(directory):
+ raise ValueError(
+ '%s does not exist. Must provide a valid directory path.' % directory)
+ # Don't allow the root directory to be a serving_dir.
+ if directory == os.path.abspath(os.sep):
+ raise ValueError('Trying to serve root directory from HTTP server.')
+ for dirpath, _, filenames in os.walk(directory):
+ for filename in filenames:
+ path_name, extension = os.path.splitext(
+ os.path.join(dirpath, filename))
+ if extension != '.sha1':
+ continue
+ GetIfChanged(path_name, bucket)
+
+
+def CalculateHash(file_path):
+ """Calculates and returns the hash of the file at file_path."""
+ sha1 = hashlib.sha1()
+ with open(file_path, 'rb') as f:
+ while True:
+ # Read in 1mb chunks, so it doesn't all have to be loaded into memory.
+ chunk = f.read(1024 * 1024)
+ if not chunk:
+ break
+ sha1.update(chunk)
+ return sha1.hexdigest()
+
+
+def ReadHash(hash_path):
+ with open(hash_path, 'rb') as f:
+ return f.read(1024).rstrip()
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage_global_lock.py b/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage_global_lock.py
new file mode 100644
index 00000000000..5718e108c2f
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage_global_lock.py
@@ -0,0 +1,5 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is used by cloud_storage._FileLock implementation, don't delete it!
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage_unittest.py
new file mode 100644
index 00000000000..7648db6b8b9
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/cloud_storage_unittest.py
@@ -0,0 +1,387 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+import mock
+from pyfakefs import fake_filesystem_unittest
+
+import py_utils
+from py_utils import cloud_storage
+from py_utils import lock
+
+_CLOUD_STORAGE_GLOBAL_LOCK_PATH = os.path.join(
+ os.path.dirname(__file__), 'cloud_storage_global_lock.py')
+
+def _FakeReadHash(_):
+ return 'hashthis!'
+
+
+def _FakeCalulateHashMatchesRead(_):
+ return 'hashthis!'
+
+
+def _FakeCalulateHashNewHash(_):
+ return 'omgnewhash'
+
+
+class BaseFakeFsUnitTest(fake_filesystem_unittest.TestCase):
+
+ def setUp(self):
+ self.original_environ = os.environ.copy()
+ os.environ['DISABLE_CLOUD_STORAGE_IO'] = ''
+ self.setUpPyfakefs()
+ self.fs.CreateFile(
+ os.path.join(py_utils.GetCatapultDir(),
+ 'third_party', 'gsutil', 'gsutil'))
+
+ def CreateFiles(self, file_paths):
+ for f in file_paths:
+ self.fs.CreateFile(f)
+
+ def tearDown(self):
+ self.tearDownPyfakefs()
+ os.environ = self.original_environ
+
+ def _FakeRunCommand(self, cmd):
+ pass
+
+ def _FakeGet(self, bucket, remote_path, local_path):
+ pass
+
+
+class CloudStorageFakeFsUnitTest(BaseFakeFsUnitTest):
+
+ def _AssertRunCommandRaisesError(self, communicate_strs, error):
+ with mock.patch('py_utils.cloud_storage.subprocess.Popen') as popen:
+ p_mock = mock.Mock()
+ popen.return_value = p_mock
+ p_mock.returncode = 1
+ for stderr in communicate_strs:
+ p_mock.communicate.return_value = ('', stderr)
+ self.assertRaises(error, cloud_storage._RunCommand, [])
+
+ def testRunCommandCredentialsError(self):
+ strs = ['You are attempting to access protected data with no configured',
+ 'Failure: No handler was ready to authenticate.']
+ self._AssertRunCommandRaisesError(strs, cloud_storage.CredentialsError)
+
+ def testRunCommandPermissionError(self):
+ strs = ['status=403', 'status 403', '403 Forbidden']
+ self._AssertRunCommandRaisesError(strs, cloud_storage.PermissionError)
+
+ def testRunCommandNotFoundError(self):
+ strs = ['InvalidUriError', 'No such object', 'No URLs matched',
+ 'One or more URLs matched no', 'InvalidUriError']
+ self._AssertRunCommandRaisesError(strs, cloud_storage.NotFoundError)
+
+ def testRunCommandServerError(self):
+ strs = ['500 Internal Server Error']
+ self._AssertRunCommandRaisesError(strs, cloud_storage.ServerError)
+
+ def testRunCommandGenericError(self):
+ strs = ['Random string']
+ self._AssertRunCommandRaisesError(strs, cloud_storage.CloudStorageError)
+
+ def testInsertCreatesValidCloudUrl(self):
+ orig_run_command = cloud_storage._RunCommand
+ try:
+ cloud_storage._RunCommand = self._FakeRunCommand
+ remote_path = 'test-remote-path.html'
+ local_path = 'test-local-path.html'
+ cloud_url = cloud_storage.Insert(cloud_storage.PUBLIC_BUCKET,
+ remote_path, local_path)
+ self.assertEqual('https://console.developers.google.com/m/cloudstorage'
+ '/b/chromium-telemetry/o/test-remote-path.html',
+ cloud_url)
+ finally:
+ cloud_storage._RunCommand = orig_run_command
+
+ @mock.patch('py_utils.cloud_storage.subprocess')
+ def testExistsReturnsFalse(self, subprocess_mock):
+ p_mock = mock.Mock()
+ subprocess_mock.Popen.return_value = p_mock
+ p_mock.communicate.return_value = (
+ '',
+ 'CommandException: One or more URLs matched no objects.\n')
+ p_mock.returncode_result = 1
+ self.assertFalse(cloud_storage.Exists('fake bucket',
+ 'fake remote path'))
+
+ @unittest.skipIf(sys.platform.startswith('win'),
+ 'https://github.com/catapult-project/catapult/issues/1861')
+ def testGetFilesInDirectoryIfChanged(self):
+ self.CreateFiles([
+ 'real_dir_path/dir1/1file1.sha1',
+ 'real_dir_path/dir1/1file2.txt',
+ 'real_dir_path/dir1/1file3.sha1',
+ 'real_dir_path/dir2/2file.txt',
+ 'real_dir_path/dir3/3file1.sha1'])
+
+ def IncrementFilesUpdated(*_):
+ IncrementFilesUpdated.files_updated += 1
+ IncrementFilesUpdated.files_updated = 0
+ orig_get_if_changed = cloud_storage.GetIfChanged
+ cloud_storage.GetIfChanged = IncrementFilesUpdated
+ try:
+ self.assertRaises(ValueError, cloud_storage.GetFilesInDirectoryIfChanged,
+ os.path.abspath(os.sep), cloud_storage.PUBLIC_BUCKET)
+ self.assertEqual(0, IncrementFilesUpdated.files_updated)
+ self.assertRaises(ValueError, cloud_storage.GetFilesInDirectoryIfChanged,
+ 'fake_dir_path', cloud_storage.PUBLIC_BUCKET)
+ self.assertEqual(0, IncrementFilesUpdated.files_updated)
+ cloud_storage.GetFilesInDirectoryIfChanged('real_dir_path',
+ cloud_storage.PUBLIC_BUCKET)
+ self.assertEqual(3, IncrementFilesUpdated.files_updated)
+ finally:
+ cloud_storage.GetIfChanged = orig_get_if_changed
+
+ def testCopy(self):
+ orig_run_command = cloud_storage._RunCommand
+
+ def AssertCorrectRunCommandArgs(args):
+ self.assertEqual(expected_args, args)
+ cloud_storage._RunCommand = AssertCorrectRunCommandArgs
+ expected_args = ['cp', 'gs://bucket1/remote_path1',
+ 'gs://bucket2/remote_path2']
+ try:
+ cloud_storage.Copy('bucket1', 'bucket2', 'remote_path1', 'remote_path2')
+ finally:
+ cloud_storage._RunCommand = orig_run_command
+
+ @mock.patch('py_utils.cloud_storage.subprocess.Popen')
+ def testSwarmingUsesExistingEnv(self, mock_popen):
+ os.environ['SWARMING_HEADLESS'] = '1'
+
+ mock_gsutil = mock_popen()
+ mock_gsutil.communicate = mock.MagicMock(return_value=('a', 'b'))
+ mock_gsutil.returncode = None
+
+ cloud_storage.Copy('bucket1', 'bucket2', 'remote_path1', 'remote_path2')
+
+ mock_popen.assert_called_with(
+ mock.ANY, stderr=-1, env=os.environ, stdout=-1)
+
+ @mock.patch('py_utils.cloud_storage._FileLock')
+ def testDisableCloudStorageIo(self, unused_lock_mock):
+ os.environ['DISABLE_CLOUD_STORAGE_IO'] = '1'
+ dir_path = 'real_dir_path'
+ self.fs.CreateDirectory(dir_path)
+ file_path = os.path.join(dir_path, 'file1')
+ file_path_sha = file_path + '.sha1'
+
+ def CleanTimeStampFile():
+ os.remove(file_path + '.fetchts')
+
+ self.CreateFiles([file_path, file_path_sha])
+ with open(file_path_sha, 'w') as f:
+ f.write('hash1234')
+ with self.assertRaises(cloud_storage.CloudStorageIODisabled):
+ cloud_storage.Copy('bucket1', 'bucket2', 'remote_path1', 'remote_path2')
+ with self.assertRaises(cloud_storage.CloudStorageIODisabled):
+ cloud_storage.Get('bucket', 'foo', file_path)
+ with self.assertRaises(cloud_storage.CloudStorageIODisabled):
+ cloud_storage.GetIfChanged(file_path, 'foo')
+ with self.assertRaises(cloud_storage.CloudStorageIODisabled):
+ cloud_storage.GetIfHashChanged('bar', file_path, 'bucket', 'hash1234')
+ with self.assertRaises(cloud_storage.CloudStorageIODisabled):
+ cloud_storage.Insert('bucket', 'foo', file_path)
+
+ CleanTimeStampFile()
+ with self.assertRaises(cloud_storage.CloudStorageIODisabled):
+ cloud_storage.GetFilesInDirectoryIfChanged(dir_path, 'bucket')
+
+
+class GetIfChangedTests(BaseFakeFsUnitTest):
+
+ def setUp(self):
+ super(GetIfChangedTests, self).setUp()
+ self._orig_read_hash = cloud_storage.ReadHash
+ self._orig_calculate_hash = cloud_storage.CalculateHash
+
+ def tearDown(self):
+ super(GetIfChangedTests, self).tearDown()
+ cloud_storage.CalculateHash = self._orig_calculate_hash
+ cloud_storage.ReadHash = self._orig_read_hash
+
+ @mock.patch('py_utils.cloud_storage._FileLock')
+ @mock.patch('py_utils.cloud_storage._GetLocked')
+ def testHashPathDoesNotExists(self, unused_get_locked, unused_lock_mock):
+ cloud_storage.ReadHash = _FakeReadHash
+ cloud_storage.CalculateHash = _FakeCalulateHashMatchesRead
+ file_path = 'test-file-path.wpr'
+
+ cloud_storage._GetLocked = self._FakeGet
+ # hash_path doesn't exist.
+ self.assertFalse(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+
+ @mock.patch('py_utils.cloud_storage._FileLock')
+ @mock.patch('py_utils.cloud_storage._GetLocked')
+ def testHashPathExistsButFilePathDoesNot(
+ self, unused_get_locked, unused_lock_mock):
+ cloud_storage.ReadHash = _FakeReadHash
+ cloud_storage.CalculateHash = _FakeCalulateHashMatchesRead
+ file_path = 'test-file-path.wpr'
+ hash_path = file_path + '.sha1'
+
+ # hash_path exists, but file_path doesn't.
+ self.CreateFiles([hash_path])
+ self.assertTrue(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+
+ @mock.patch('py_utils.cloud_storage._FileLock')
+ @mock.patch('py_utils.cloud_storage._GetLocked')
+ def testHashPathAndFileHashExistWithSameHash(
+ self, unused_get_locked, unused_lock_mock):
+ cloud_storage.ReadHash = _FakeReadHash
+ cloud_storage.CalculateHash = _FakeCalulateHashMatchesRead
+ file_path = 'test-file-path.wpr'
+
+ # hash_path and file_path exist, and have same hash.
+ self.CreateFiles([file_path])
+ self.assertFalse(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+
+ @mock.patch('py_utils.cloud_storage._FileLock')
+ @mock.patch('py_utils.cloud_storage._GetLocked')
+ def testHashPathAndFileHashExistWithDifferentHash(
+ self, mock_get_locked, unused_get_locked):
+ cloud_storage.ReadHash = _FakeReadHash
+ cloud_storage.CalculateHash = _FakeCalulateHashNewHash
+ file_path = 'test-file-path.wpr'
+ hash_path = file_path + '.sha1'
+
+ def _FakeGetLocked(bucket, expected_hash, file_path):
+ del bucket, expected_hash, file_path # unused
+ cloud_storage.CalculateHash = _FakeCalulateHashMatchesRead
+
+ mock_get_locked.side_effect = _FakeGetLocked
+
+ self.CreateFiles([file_path, hash_path])
+ # hash_path and file_path exist, and have different hashes.
+ self.assertTrue(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+
+ @mock.patch('py_utils.cloud_storage._FileLock')
+ @mock.patch('py_utils.cloud_storage.CalculateHash')
+ @mock.patch('py_utils.cloud_storage._GetLocked')
+ def testNoHashComputationNeededUponSecondCall(
+ self, mock_get_locked, mock_calculate_hash, unused_get_locked):
+ mock_calculate_hash.side_effect = _FakeCalulateHashNewHash
+ cloud_storage.ReadHash = _FakeReadHash
+ file_path = 'test-file-path.wpr'
+ hash_path = file_path + '.sha1'
+
+ def _FakeGetLocked(bucket, expected_hash, file_path):
+ del bucket, expected_hash, file_path # unused
+ cloud_storage.CalculateHash = _FakeCalulateHashMatchesRead
+
+ mock_get_locked.side_effect = _FakeGetLocked
+
+ self.CreateFiles([file_path, hash_path])
+ # hash_path and file_path exist, and have different hashes. This first call
+ # will invoke a fetch.
+ self.assertTrue(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+
+ # The fetch left a .fetchts file on machine.
+ self.assertTrue(os.path.exists(file_path + '.fetchts'))
+
+ # Subsequent invocations of GetIfChanged should not invoke CalculateHash.
+ mock_calculate_hash.assert_not_called()
+ self.assertFalse(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+ self.assertFalse(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+
+ @mock.patch('py_utils.cloud_storage._FileLock')
+ @mock.patch('py_utils.cloud_storage.CalculateHash')
+ @mock.patch('py_utils.cloud_storage._GetLocked')
+ def testRefetchingFileUponHashFileChange(
+ self, mock_get_locked, mock_calculate_hash, unused_get_locked):
+ mock_calculate_hash.side_effect = _FakeCalulateHashNewHash
+ cloud_storage.ReadHash = _FakeReadHash
+ file_path = 'test-file-path.wpr'
+ hash_path = file_path + '.sha1'
+
+ def _FakeGetLocked(bucket, expected_hash, file_path):
+ del bucket, expected_hash, file_path # unused
+ cloud_storage.CalculateHash = _FakeCalulateHashMatchesRead
+
+ mock_get_locked.side_effect = _FakeGetLocked
+
+ self.CreateFiles([file_path, hash_path])
+ # hash_path and file_path exist, and have different hashes. This first call
+ # will invoke a fetch.
+ self.assertTrue(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+
+ # The fetch left a .fetchts file on machine.
+ self.assertTrue(os.path.exists(file_path + '.fetchts'))
+
+ with open(file_path + '.fetchts') as f:
+ fetchts = float(f.read())
+
+ # Updating the .sha1 hash_path file with the new hash after .fetchts
+ # is created.
+ file_obj = self.fs.GetObject(hash_path)
+ file_obj.SetMTime(fetchts + 100)
+
+ cloud_storage.ReadHash = lambda _: 'hashNeW'
+ def _FakeGetLockedNewHash(bucket, expected_hash, file_path):
+ del bucket, expected_hash, file_path # unused
+ cloud_storage.CalculateHash = lambda _: 'hashNeW'
+
+ mock_get_locked.side_effect = _FakeGetLockedNewHash
+
+ # hash_path and file_path exist, and have different hashes. This first call
+ # will invoke a fetch.
+ self.assertTrue(cloud_storage.GetIfChanged(file_path,
+ cloud_storage.PUBLIC_BUCKET))
+
+
+class CloudStorageRealFsUnitTest(unittest.TestCase):
+
+ def setUp(self):
+ self.original_environ = os.environ.copy()
+ os.environ['DISABLE_CLOUD_STORAGE_IO'] = ''
+
+ def tearDown(self):
+ os.environ = self.original_environ
+
+ @mock.patch('py_utils.cloud_storage.LOCK_ACQUISITION_TIMEOUT', .005)
+ def testGetPseudoLockUnavailableCausesTimeout(self):
+ with tempfile.NamedTemporaryFile(suffix='.pseudo_lock') as pseudo_lock_fd:
+ with lock.FileLock(pseudo_lock_fd, lock.LOCK_EX | lock.LOCK_NB):
+ with self.assertRaises(py_utils.TimeoutException):
+ file_path = pseudo_lock_fd.name.replace('.pseudo_lock', '')
+ cloud_storage.GetIfChanged(file_path, cloud_storage.PUBLIC_BUCKET)
+
+ @mock.patch('py_utils.cloud_storage.LOCK_ACQUISITION_TIMEOUT', .005)
+ def testGetGlobalLockUnavailableCausesTimeout(self):
+ with open(_CLOUD_STORAGE_GLOBAL_LOCK_PATH) as global_lock_fd:
+ with lock.FileLock(global_lock_fd, lock.LOCK_EX | lock.LOCK_NB):
+ tmp_dir = tempfile.mkdtemp()
+ try:
+ file_path = os.path.join(tmp_dir, 'foo')
+ with self.assertRaises(py_utils.TimeoutException):
+ cloud_storage.GetIfChanged(file_path, cloud_storage.PUBLIC_BUCKET)
+ finally:
+ shutil.rmtree(tmp_dir)
+
+
+class CloudStorageErrorHandlingTest(unittest.TestCase):
+ def runTest(self):
+ self.assertIsInstance(cloud_storage.GetErrorObjectForCloudStorageStderr(
+ 'ServiceException: 401 Anonymous users does not have '
+ 'storage.objects.get access to object chrome-partner-telemetry'),
+ cloud_storage.CredentialsError)
+ self.assertIsInstance(cloud_storage.GetErrorObjectForCloudStorageStderr(
+ '403 Caller does not have storage.objects.list access to bucket '
+ 'chrome-telemetry'), cloud_storage.PermissionError)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/contextlib_ext.py b/chromium/third_party/catapult/common/py_utils/py_utils/contextlib_ext.py
new file mode 100644
index 00000000000..922d27d548b
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/contextlib_ext.py
@@ -0,0 +1,33 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class _OptionalContextManager(object):
+
+ def __init__(self, manager, condition):
+ self._manager = manager
+ self._condition = condition
+
+ def __enter__(self):
+ if self._condition:
+ return self._manager.__enter__()
+ return None
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ if self._condition:
+ return self._manager.__exit__(exc_type, exc_val, exc_tb)
+ return None
+
+
+def Optional(manager, condition):
+ """Wraps the provided context manager and runs it if condition is True.
+
+ Args:
+ manager: A context manager to conditionally run.
+ condition: If true, runs the given context manager.
+ Returns:
+ A context manager that conditionally executes the given manager.
+ """
+ return _OptionalContextManager(manager, condition)
+
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/contextlib_ext_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/contextlib_ext_unittest.py
new file mode 100644
index 00000000000..b83e7e5e018
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/contextlib_ext_unittest.py
@@ -0,0 +1,34 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from py_utils import contextlib_ext
+
+
+class OptionalUnittest(unittest.TestCase):
+
+ class SampleContextMgr(object):
+
+ def __init__(self):
+ self.entered = False
+ self.exited = False
+
+ def __enter__(self):
+ self.entered = True
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.exited = True
+
+ def testConditionTrue(self):
+ c = self.SampleContextMgr()
+ with contextlib_ext.Optional(c, True):
+ self.assertTrue(c.entered)
+ self.assertTrue(c.exited)
+
+ def testConditionFalse(self):
+ c = self.SampleContextMgr()
+ with contextlib_ext.Optional(c, False):
+ self.assertFalse(c.entered)
+ self.assertFalse(c.exited)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/dependency_util.py b/chromium/third_party/catapult/common/py_utils/py_utils/dependency_util.py
new file mode 100644
index 00000000000..d3cfe89c389
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/dependency_util.py
@@ -0,0 +1,49 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import platform
+import sys
+
+import py_utils
+
+def GetOSAndArchForCurrentDesktopPlatform():
+ os_name = GetOSNameForCurrentDesktopPlatform()
+ return os_name, GetArchForCurrentDesktopPlatform(os_name)
+
+
+def GetOSNameForCurrentDesktopPlatform():
+ if py_utils.IsRunningOnCrosDevice():
+ return 'chromeos'
+ if sys.platform.startswith('linux'):
+ return 'linux'
+ if sys.platform == 'darwin':
+ return 'mac'
+ if sys.platform == 'win32':
+ return 'win'
+ return sys.platform
+
+
+def GetArchForCurrentDesktopPlatform(os_name):
+ if os_name == 'chromeos':
+ # Current tests outside of telemetry don't run on chromeos, and
+ # platform.machine is not the way telemetry gets the arch name on chromeos.
+ raise NotImplementedError()
+ return platform.machine()
+
+
+def GetChromeApkOsVersion(version_name):
+ version = version_name[0]
+ assert version.isupper(), (
+ 'First character of versions name %s was not an uppercase letter.')
+ if version < 'L':
+ return 'k'
+ elif version > 'M':
+ return 'n'
+ return 'l'
+
+
+def ChromeBinariesConfigPath():
+ return os.path.realpath(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), 'chrome_binaries.json'))
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/discover.py b/chromium/third_party/catapult/common/py_utils/py_utils/discover.py
new file mode 100644
index 00000000000..09d5c5e2f18
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/discover.py
@@ -0,0 +1,191 @@
+# Copyright 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import fnmatch
+import importlib
+import inspect
+import os
+import re
+import sys
+
+from py_utils import camel_case
+
+
+def DiscoverModules(start_dir, top_level_dir, pattern='*'):
+ """Discover all modules in |start_dir| which match |pattern|.
+
+ Args:
+ start_dir: The directory to recursively search.
+ top_level_dir: The top level of the package, for importing.
+ pattern: Unix shell-style pattern for filtering the filenames to import.
+
+ Returns:
+ list of modules.
+ """
+ # start_dir and top_level_dir must be consistent with each other.
+ start_dir = os.path.realpath(start_dir)
+ top_level_dir = os.path.realpath(top_level_dir)
+
+ modules = []
+ sub_paths = list(os.walk(start_dir))
+ # We sort the directories & file paths to ensure a deterministic ordering when
+ # traversing |top_level_dir|.
+ sub_paths.sort(key=lambda paths_tuple: paths_tuple[0])
+ for dir_path, _, filenames in sub_paths:
+ # Sort the directories to walk recursively by the directory path.
+ filenames.sort()
+ for filename in filenames:
+ # Filter out unwanted filenames.
+ if filename.startswith('.') or filename.startswith('_'):
+ continue
+ if os.path.splitext(filename)[1] != '.py':
+ continue
+ if not fnmatch.fnmatch(filename, pattern):
+ continue
+
+ # Find the module.
+ module_rel_path = os.path.relpath(
+ os.path.join(dir_path, filename), top_level_dir)
+ module_name = re.sub(r'[/\\]', '.', os.path.splitext(module_rel_path)[0])
+
+ # Import the module.
+ try:
+ # Make sure that top_level_dir is the first path in the sys.path in case
+ # there are naming conflict in module parts.
+ original_sys_path = sys.path[:]
+ sys.path.insert(0, top_level_dir)
+ module = importlib.import_module(module_name)
+ modules.append(module)
+ finally:
+ sys.path = original_sys_path
+ return modules
+
+
+def AssertNoKeyConflicts(classes_by_key_1, classes_by_key_2):
+ for k in classes_by_key_1:
+ if k in classes_by_key_2:
+ assert classes_by_key_1[k] is classes_by_key_2[k], (
+ 'Found conflicting classes for the same key: '
+ 'key=%s, class_1=%s, class_2=%s' % (
+ k, classes_by_key_1[k], classes_by_key_2[k]))
+
+
+# TODO(dtu): Normalize all discoverable classes to have corresponding module
+# and class names, then always index by class name.
+def DiscoverClasses(start_dir,
+ top_level_dir,
+ base_class,
+ pattern='*',
+ index_by_class_name=True,
+ directly_constructable=False):
+ """Discover all classes in |start_dir| which subclass |base_class|.
+
+ Base classes that contain subclasses are ignored by default.
+
+ Args:
+ start_dir: The directory to recursively search.
+ top_level_dir: The top level of the package, for importing.
+ base_class: The base class to search for.
+ pattern: Unix shell-style pattern for filtering the filenames to import.
+ index_by_class_name: If True, use class name converted to
+ lowercase_with_underscores instead of module name in return dict keys.
+ directly_constructable: If True, will only return classes that can be
+ constructed without arguments
+
+ Returns:
+ dict of {module_name: class} or {underscored_class_name: class}
+ """
+ modules = DiscoverModules(start_dir, top_level_dir, pattern)
+ classes = {}
+ for module in modules:
+ new_classes = DiscoverClassesInModule(
+ module, base_class, index_by_class_name, directly_constructable)
+ # TODO(nednguyen): we should remove index_by_class_name once
+ # benchmark_smoke_unittest in chromium/src/tools/perf no longer relied
+ # naming collisions to reduce the number of smoked benchmark tests.
+ # crbug.com/548652
+ if index_by_class_name:
+ AssertNoKeyConflicts(classes, new_classes)
+ classes = dict(classes.items() + new_classes.items())
+ return classes
+
+
+# TODO(nednguyen): we should remove index_by_class_name once
+# benchmark_smoke_unittest in chromium/src/tools/perf no longer relied
+# naming collisions to reduce the number of smoked benchmark tests.
+# crbug.com/548652
+def DiscoverClassesInModule(module,
+ base_class,
+ index_by_class_name=False,
+ directly_constructable=False):
+ """Discover all classes in |module| which subclass |base_class|.
+
+ Base classes that contain subclasses are ignored by default.
+
+ Args:
+ module: The module to search.
+ base_class: The base class to search for.
+ index_by_class_name: If True, use class name converted to
+ lowercase_with_underscores instead of module name in return dict keys.
+
+ Returns:
+ dict of {module_name: class} or {underscored_class_name: class}
+ """
+ classes = {}
+ for _, obj in inspect.getmembers(module):
+ # Ensure object is a class.
+ if not inspect.isclass(obj):
+ continue
+ # Include only subclasses of base_class.
+ if not issubclass(obj, base_class):
+ continue
+ # Exclude the base_class itself.
+ if obj is base_class:
+ continue
+ # Exclude protected or private classes.
+ if obj.__name__.startswith('_'):
+ continue
+ # Include only the module in which the class is defined.
+ # If a class is imported by another module, exclude those duplicates.
+ if obj.__module__ != module.__name__:
+ continue
+
+ if index_by_class_name:
+ key_name = camel_case.ToUnderscore(obj.__name__)
+ else:
+ key_name = module.__name__.split('.')[-1]
+ if not directly_constructable or IsDirectlyConstructable(obj):
+ if key_name in classes and index_by_class_name:
+ assert classes[key_name] is obj, (
+ 'Duplicate key_name with different objs detected: '
+ 'key=%s, obj1=%s, obj2=%s' % (key_name, classes[key_name], obj))
+ else:
+ classes[key_name] = obj
+
+ return classes
+
+
+def IsDirectlyConstructable(cls):
+ """Returns True if instance of |cls| can be construct without arguments."""
+ assert inspect.isclass(cls)
+ if not hasattr(cls, '__init__'):
+ # Case |class A: pass|.
+ return True
+ if cls.__init__ is object.__init__:
+ # Case |class A(object): pass|.
+ return True
+ # Case |class (object):| with |__init__| other than |object.__init__|.
+ args, _, _, defaults = inspect.getargspec(cls.__init__)
+ if defaults is None:
+ defaults = ()
+ # Return true if |self| is only arg without a default.
+ return len(args) == len(defaults) + 1
+
+
+_COUNTER = [0]
+
+
+def _GetUniqueModuleName():
+ _COUNTER[0] += 1
+ return "module_" + str(_COUNTER[0])
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/discover_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/discover_unittest.py
new file mode 100644
index 00000000000..137d85f7ba4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/discover_unittest.py
@@ -0,0 +1,146 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from py_utils import discover
+
+
+class DiscoverTest(unittest.TestCase):
+
+ def setUp(self):
+ self._base_dir = os.path.join(os.path.dirname(__file__), 'test_data')
+ self._start_dir = os.path.join(self._base_dir, 'discoverable_classes')
+ self._base_class = Exception
+
+ def testDiscoverClassesWithIndexByModuleName(self):
+ classes = discover.DiscoverClasses(self._start_dir,
+ self._base_dir,
+ self._base_class,
+ index_by_class_name=False)
+
+ actual_classes = dict((name, cls.__name__)
+ for name, cls in classes.iteritems())
+ expected_classes = {
+ 'another_discover_dummyclass': 'DummyExceptionWithParameterImpl1',
+ 'discover_dummyclass': 'DummyException',
+ 'parameter_discover_dummyclass': 'DummyExceptionWithParameterImpl2'
+ }
+ self.assertEqual(actual_classes, expected_classes)
+
+ def testDiscoverDirectlyConstructableClassesWithIndexByClassName(self):
+ classes = discover.DiscoverClasses(self._start_dir,
+ self._base_dir,
+ self._base_class,
+ directly_constructable=True)
+
+ actual_classes = dict((name, cls.__name__)
+ for name, cls in classes.iteritems())
+ expected_classes = {
+ 'dummy_exception': 'DummyException',
+ 'dummy_exception_impl1': 'DummyExceptionImpl1',
+ 'dummy_exception_impl2': 'DummyExceptionImpl2',
+ }
+ self.assertEqual(actual_classes, expected_classes)
+
+ def testDiscoverClassesWithIndexByClassName(self):
+ classes = discover.DiscoverClasses(self._start_dir, self._base_dir,
+ self._base_class)
+
+ actual_classes = dict((name, cls.__name__)
+ for name, cls in classes.iteritems())
+ expected_classes = {
+ 'dummy_exception': 'DummyException',
+ 'dummy_exception_impl1': 'DummyExceptionImpl1',
+ 'dummy_exception_impl2': 'DummyExceptionImpl2',
+ 'dummy_exception_with_parameter_impl1':
+ 'DummyExceptionWithParameterImpl1',
+ 'dummy_exception_with_parameter_impl2':
+ 'DummyExceptionWithParameterImpl2'
+ }
+ self.assertEqual(actual_classes, expected_classes)
+
+ def testDiscoverClassesWithPatternAndIndexByModule(self):
+ classes = discover.DiscoverClasses(self._start_dir,
+ self._base_dir,
+ self._base_class,
+ pattern='another*',
+ index_by_class_name=False)
+
+ actual_classes = dict((name, cls.__name__)
+ for name, cls in classes.iteritems())
+ expected_classes = {
+ 'another_discover_dummyclass': 'DummyExceptionWithParameterImpl1'
+ }
+ self.assertEqual(actual_classes, expected_classes)
+
+ def testDiscoverDirectlyConstructableClassesWithPatternAndIndexByClassName(
+ self):
+ classes = discover.DiscoverClasses(self._start_dir,
+ self._base_dir,
+ self._base_class,
+ pattern='another*',
+ directly_constructable=True)
+
+ actual_classes = dict((name, cls.__name__)
+ for name, cls in classes.iteritems())
+ expected_classes = {
+ 'dummy_exception_impl1': 'DummyExceptionImpl1',
+ 'dummy_exception_impl2': 'DummyExceptionImpl2',
+ }
+ self.assertEqual(actual_classes, expected_classes)
+
+ def testDiscoverClassesWithPatternAndIndexByClassName(self):
+ classes = discover.DiscoverClasses(self._start_dir,
+ self._base_dir,
+ self._base_class,
+ pattern='another*')
+
+ actual_classes = dict((name, cls.__name__)
+ for name, cls in classes.iteritems())
+ expected_classes = {
+ 'dummy_exception_impl1': 'DummyExceptionImpl1',
+ 'dummy_exception_impl2': 'DummyExceptionImpl2',
+ 'dummy_exception_with_parameter_impl1':
+ 'DummyExceptionWithParameterImpl1',
+ }
+ self.assertEqual(actual_classes, expected_classes)
+
+
+class ClassWithoutInitDefOne: # pylint: disable=old-style-class, no-init
+ pass
+
+
+class ClassWithoutInitDefTwo(object):
+ pass
+
+
+class ClassWhoseInitOnlyHasSelf(object):
+ def __init__(self):
+ pass
+
+
+class ClassWhoseInitWithDefaultArguments(object):
+ def __init__(self, dog=1, cat=None, cow=None, fud='a'):
+ pass
+
+
+class ClassWhoseInitWithDefaultArgumentsAndNonDefaultArguments(object):
+ def __init__(self, x, dog=1, cat=None, fish=None, fud='a'):
+ pass
+
+
+class IsDirectlyConstructableTest(unittest.TestCase):
+
+ def testIsDirectlyConstructableReturnsTrue(self):
+ self.assertTrue(discover.IsDirectlyConstructable(ClassWithoutInitDefOne))
+ self.assertTrue(discover.IsDirectlyConstructable(ClassWithoutInitDefTwo))
+ self.assertTrue(discover.IsDirectlyConstructable(ClassWhoseInitOnlyHasSelf))
+ self.assertTrue(
+ discover.IsDirectlyConstructable(ClassWhoseInitWithDefaultArguments))
+
+ def testIsDirectlyConstructableReturnsFalse(self):
+ self.assertFalse(
+ discover.IsDirectlyConstructable(
+ ClassWhoseInitWithDefaultArgumentsAndNonDefaultArguments))
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/expectations_parser.py b/chromium/third_party/catapult/common/py_utils/py_utils/expectations_parser.py
new file mode 100644
index 00000000000..6fa94070ded
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/expectations_parser.py
@@ -0,0 +1,124 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+
+
+class ParseError(Exception):
+ pass
+
+
+class Expectation(object):
+ def __init__(self, reason, test, conditions, results):
+ """Constructor for expectations.
+
+ Args:
+ reason: String that indicates the reason for disabling.
+ test: String indicating which test is being disabled.
+ conditions: List of tags indicating which conditions to disable for.
+ Conditions are combined using logical and. Example: ['Mac', 'Debug']
+ results: List of outcomes for test. Example: ['Skip', 'Pass']
+ """
+ assert isinstance(reason, basestring) or reason is None
+ self._reason = reason
+ assert isinstance(test, basestring)
+ self._test = test
+ assert isinstance(conditions, list)
+ self._conditions = conditions
+ assert isinstance(results, list)
+ self._results = results
+
+ def __eq__(self, other):
+ return (self.reason == other.reason and
+ self.test == other.test and
+ self.conditions == other.conditions and
+ self.results == other.results)
+
+ @property
+ def reason(self):
+ return self._reason
+
+ @property
+ def test(self):
+ return self._test
+
+ @property
+ def conditions(self):
+ return self._conditions
+
+ @property
+ def results(self):
+ return self._results
+
+
+class TestExpectationParser(object):
+ """Parse expectations data in TA/DA format.
+
+ This parser covers the 'tagged' test lists format in:
+ bit.ly/chromium-test-list-format
+
+ Takes raw expectations data as a string read from the TA/DA expectation file
+ in the format:
+
+ # This is an example expectation file.
+ #
+ # tags: Mac Mac10.10 Mac10.11
+ # tags: Win Win8
+
+ crbug.com/123 [ Win ] benchmark/story [ Skip ]
+ ...
+ """
+
+ TAG_TOKEN = '# tags:'
+ _MATCH_STRING = r'^(?:(crbug.com/\d+) )?' # The bug field (optional).
+ _MATCH_STRING += r'(?:\[ (.+) \] )?' # The label field (optional).
+ _MATCH_STRING += r'(\S+) ' # The test path field.
+ _MATCH_STRING += r'\[ ([^\[.]+) \]' # The expectation field.
+ _MATCH_STRING += r'(\s+#.*)?$' # End comment (optional).
+ MATCHER = re.compile(_MATCH_STRING)
+
+ def __init__(self, raw_data):
+ self._tags = []
+ self._expectations = []
+ self._ParseRawExpectationData(raw_data)
+
+ def _ParseRawExpectationData(self, raw_data):
+ for count, line in list(enumerate(raw_data.splitlines(), start=1)):
+ # Handle metadata and comments.
+ if line.startswith(self.TAG_TOKEN):
+ for word in line[len(self.TAG_TOKEN):].split():
+ # Expectations must be after all tags are declared.
+ if self._expectations:
+ raise ParseError('Tag found after first expectation.')
+ self._tags.append(word)
+ elif line.startswith('#') or not line:
+ continue # Ignore, it is just a comment or empty.
+ else:
+ self._expectations.append(
+ self._ParseExpectationLine(count, line, self._tags))
+
+ def _ParseExpectationLine(self, line_number, line, tags):
+ match = self.MATCHER.match(line)
+ if not match:
+ raise ParseError(
+ 'Expectation has invalid syntax on line %d: %s'
+ % (line_number, line))
+ # Unused group is optional trailing comment.
+ reason, raw_conditions, test, results, _ = match.groups()
+ conditions = [c for c in raw_conditions.split()] if raw_conditions else []
+
+ for c in conditions:
+ if c not in tags:
+ raise ParseError(
+ 'Condition %s not found in expectations tag data. Line %d'
+ % (c, line_number))
+ return Expectation(reason, test, conditions, [r for r in results.split()])
+
+ @property
+ def expectations(self):
+ return self._expectations
+
+ @property
+ def tags(self):
+ return self._tags
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/expectations_parser_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/expectations_parser_unittest.py
new file mode 100644
index 00000000000..a842c4c960c
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/expectations_parser_unittest.py
@@ -0,0 +1,165 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import unittest
+
+from py_utils import expectations_parser
+
+
+class TestExpectationParserTest(unittest.TestCase):
+
+ def testInitWithGoodData(self):
+ good_data = """
+# This is a test expectation file.
+#
+# tags: tag1 tag2 tag3
+# tags: tag4 Mac Win Debug
+
+crbug.com/12345 [ Mac ] b1/s1 [ Skip ]
+crbug.com/23456 [ Mac Debug ] b1/s2 [ Skip ]
+"""
+ parser = expectations_parser.TestExpectationParser(good_data)
+ tags = ['tag1', 'tag2', 'tag3', 'tag4', 'Mac', 'Win', 'Debug']
+ self.assertEqual(parser.tags, tags)
+ expected_outcome = [
+ expectations_parser.Expectation(
+ 'crbug.com/12345', 'b1/s1', ['Mac'], ['Skip']),
+ expectations_parser.Expectation(
+ 'crbug.com/23456', 'b1/s2', ['Mac', 'Debug'], ['Skip'])
+ ]
+ for i in range(len(parser.expectations)):
+ self.assertEqual(parser.expectations[i], expected_outcome[i])
+
+ def testInitWithBadData(self):
+ bad_data = """
+# This is a test expectation file.
+#
+# tags: tag1 tag2 tag3
+# tags: tag4
+
+crbug.com/12345 [ Mac b1/s1 [ Skip ]
+"""
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(bad_data)
+
+ def testTagAfterExpectationsStart(self):
+ bad_data = """
+# This is a test expectation file.
+#
+# tags: tag1 tag2 tag3
+
+crbug.com/12345 [ tag1 ] b1/s1 [ Skip ]
+
+# tags: tag4
+"""
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(bad_data)
+
+ def testParseExpectationLineEverythingThere(self):
+ raw_data = '# tags: Mac\ncrbug.com/23456 [ Mac ] b1/s2 [ Skip ]'
+ parser = expectations_parser.TestExpectationParser(raw_data)
+ expected_outcome = [
+ expectations_parser.Expectation(
+ 'crbug.com/23456', 'b1/s2', ['Mac'], ['Skip'])
+ ]
+ for i in range(len(parser.expectations)):
+ self.assertEqual(parser.expectations[i], expected_outcome[i])
+
+ def testParseExpectationLineBadTag(self):
+ raw_data = '# tags: None\ncrbug.com/23456 [ Mac ] b1/s2 [ Skip ]'
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(raw_data)
+
+ def testParseExpectationLineNoConditions(self):
+ raw_data = '# tags: All\ncrbug.com/12345 b1/s1 [ Skip ]'
+ parser = expectations_parser.TestExpectationParser(raw_data)
+ expected_outcome = [
+ expectations_parser.Expectation(
+ 'crbug.com/12345', 'b1/s1', [], ['Skip']),
+ ]
+ for i in range(len(parser.expectations)):
+ self.assertEqual(parser.expectations[i], expected_outcome[i])
+
+ def testParseExpectationLineNoBug(self):
+ raw_data = '# tags: All\n[ All ] b1/s1 [ Skip ]'
+ parser = expectations_parser.TestExpectationParser(raw_data)
+ expected_outcome = [
+ expectations_parser.Expectation(
+ None, 'b1/s1', ['All'], ['Skip']),
+ ]
+ for i in range(len(parser.expectations)):
+ self.assertEqual(parser.expectations[i], expected_outcome[i])
+
+ def testParseExpectationLineNoBugNoConditions(self):
+ raw_data = '# tags: All\nb1/s1 [ Skip ]'
+ parser = expectations_parser.TestExpectationParser(raw_data)
+ expected_outcome = [
+ expectations_parser.Expectation(
+ None, 'b1/s1', [], ['Skip']),
+ ]
+ for i in range(len(parser.expectations)):
+ self.assertEqual(parser.expectations[i], expected_outcome[i])
+
+ def testParseExpectationLineMultipleConditions(self):
+ raw_data = ('# tags:All None Batman\n'
+ 'crbug.com/123 [ All None Batman ] b1/s1 [ Skip ]')
+ parser = expectations_parser.TestExpectationParser(raw_data)
+ expected_outcome = [
+ expectations_parser.Expectation(
+ 'crbug.com/123', 'b1/s1', ['All', 'None', 'Batman'], ['Skip']),
+ ]
+ for i in range(len(parser.expectations)):
+ self.assertEqual(parser.expectations[i], expected_outcome[i])
+
+ def testParseExpectationLineBadConditionBracket(self):
+ raw_data = '# tags: Mac\ncrbug.com/23456 ] Mac ] b1/s2 [ Skip ]'
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(raw_data)
+
+ def testParseExpectationLineBadResultBracket(self):
+ raw_data = '# tags: Mac\ncrbug.com/23456 ] Mac ] b1/s2 ] Skip ]'
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(raw_data)
+
+ def testParseExpectationLineBadConditionBracketSpacing(self):
+ raw_data = '# tags: Mac\ncrbug.com/2345 [Mac] b1/s1 [ Skip ]'
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(raw_data)
+
+ def testParseExpectationLineBadResultBracketSpacing(self):
+ raw_data = '# tags: Mac\ncrbug.com/2345 [ Mac ] b1/s1 [Skip]'
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(raw_data)
+
+ def testParseExpectationLineNoClosingConditionBracket(self):
+ raw_data = '# tags: Mac\ncrbug.com/2345 [ Mac b1/s1 [ Skip ]'
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(raw_data)
+
+ def testParseExpectationLineNoClosingResultBracket(self):
+ raw_data = '# tags: Mac\ncrbug.com/2345 [ Mac ] b1/s1 [ Skip'
+ with self.assertRaises(expectations_parser.ParseError):
+ expectations_parser.TestExpectationParser(raw_data)
+
+ def testParseExpectationLineUrlInTestName(self):
+ raw_data = (
+ '# tags: Mac\ncrbug.com/123 [ Mac ] b.1/http://google.com [ Skip ]')
+ expected_outcomes = [
+ expectations_parser.Expectation(
+ 'crbug.com/123', 'b.1/http://google.com', ['Mac'], ['Skip'])
+ ]
+ parser = expectations_parser.TestExpectationParser(raw_data)
+ for i in range(len(parser.expectations)):
+ self.assertEqual(parser.expectations[i], expected_outcomes[i])
+
+ def testParseExpectationLineEndingComment(self):
+ raw_data = '# tags: Mac\ncrbug.com/23456 [ Mac ] b1/s2 [ Skip ] # abc 123'
+ parser = expectations_parser.TestExpectationParser(raw_data)
+ expected_outcome = [
+ expectations_parser.Expectation(
+ 'crbug.com/23456', 'b1/s2', ['Mac'], ['Skip'])
+ ]
+ for i in range(len(parser.expectations)):
+ self.assertEqual(parser.expectations[i], expected_outcome[i])
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/file_util.py b/chromium/third_party/catapult/common/py_utils/py_utils/file_util.py
new file mode 100644
index 00000000000..b1602c97de8
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/file_util.py
@@ -0,0 +1,23 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import errno
+import os
+import shutil
+
+
+def CopyFileWithIntermediateDirectories(source_path, dest_path):
+ """Copies a file and creates intermediate directories as needed.
+
+ Args:
+ source_path: Path to the source file.
+ dest_path: Path to the destination where the source file should be copied.
+ """
+ assert os.path.exists(source_path)
+ try:
+ os.makedirs(os.path.dirname(dest_path))
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+ shutil.copy(source_path, dest_path)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/file_util_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/file_util_unittest.py
new file mode 100644
index 00000000000..4bb19a14225
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/file_util_unittest.py
@@ -0,0 +1,66 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import errno
+import os
+import shutil
+import tempfile
+import unittest
+
+from py_utils import file_util
+
+
+class FileUtilTest(unittest.TestCase):
+
+ def setUp(self):
+ self._tempdir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self._tempdir)
+
+ def testCopySimple(self):
+ source_path = os.path.join(self._tempdir, 'source')
+ with open(source_path, 'w') as f:
+ f.write('data')
+
+ dest_path = os.path.join(self._tempdir, 'dest')
+
+ self.assertFalse(os.path.exists(dest_path))
+ file_util.CopyFileWithIntermediateDirectories(source_path, dest_path)
+ self.assertTrue(os.path.exists(dest_path))
+ self.assertEqual('data', open(dest_path, 'r').read())
+
+ def testCopyMakeDirectories(self):
+ source_path = os.path.join(self._tempdir, 'source')
+ with open(source_path, 'w') as f:
+ f.write('data')
+
+ dest_path = os.path.join(self._tempdir, 'path', 'to', 'dest')
+
+ self.assertFalse(os.path.exists(dest_path))
+ file_util.CopyFileWithIntermediateDirectories(source_path, dest_path)
+ self.assertTrue(os.path.exists(dest_path))
+ self.assertEqual('data', open(dest_path, 'r').read())
+
+ def testCopyOverwrites(self):
+ source_path = os.path.join(self._tempdir, 'source')
+ with open(source_path, 'w') as f:
+ f.write('source_data')
+
+ dest_path = os.path.join(self._tempdir, 'dest')
+ with open(dest_path, 'w') as f:
+ f.write('existing_data')
+
+ file_util.CopyFileWithIntermediateDirectories(source_path, dest_path)
+ self.assertEqual('source_data', open(dest_path, 'r').read())
+
+ def testRaisesError(self):
+ source_path = os.path.join(self._tempdir, 'source')
+ with open(source_path, 'w') as f:
+ f.write('data')
+
+ dest_path = ""
+ with self.assertRaises(OSError) as cm:
+ file_util.CopyFileWithIntermediateDirectories(source_path, dest_path)
+ self.assertEqual(errno.ENOENT, cm.exception.error_code)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/lock.py b/chromium/third_party/catapult/common/py_utils/py_utils/lock.py
new file mode 100644
index 00000000000..ade4d1f0376
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/lock.py
@@ -0,0 +1,121 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import contextlib
+import os
+
+LOCK_EX = None # Exclusive lock
+LOCK_SH = None # Shared lock
+LOCK_NB = None # Non-blocking (LockException is raised if resource is locked)
+
+
+class LockException(Exception):
+ pass
+
+
+# pylint: disable=import-error
+# pylint: disable=wrong-import-position
+if os.name == 'nt':
+ import win32con
+ import win32file
+ import pywintypes
+ LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
+ LOCK_SH = 0 # the default
+ LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
+ _OVERLAPPED = pywintypes.OVERLAPPED()
+elif os.name == 'posix':
+ import fcntl
+ LOCK_EX = fcntl.LOCK_EX
+ LOCK_SH = fcntl.LOCK_SH
+ LOCK_NB = fcntl.LOCK_NB
+# pylint: enable=import-error
+# pylint: enable=wrong-import-position
+
+
+@contextlib.contextmanager
+def FileLock(target_file, flags):
+ """ Lock the target file. Similar to AcquireFileLock but allow user to write:
+ with FileLock(f, LOCK_EX):
+ ...do stuff on file f without worrying about race condition
+ Args: see AcquireFileLock's documentation.
+ """
+ AcquireFileLock(target_file, flags)
+ try:
+ yield
+ finally:
+ ReleaseFileLock(target_file)
+
+
+def AcquireFileLock(target_file, flags):
+ """ Lock the target file. Note that if |target_file| is closed, the lock is
+ automatically released.
+ Args:
+ target_file: file handle of the file to acquire lock.
+ flags: can be any of the type LOCK_EX, LOCK_SH, LOCK_NB, or a bitwise
+ OR combination of flags.
+ """
+ assert flags in (
+ LOCK_EX, LOCK_SH, LOCK_NB, LOCK_EX | LOCK_NB, LOCK_SH | LOCK_NB)
+ if os.name == 'nt':
+ _LockImplWin(target_file, flags)
+ elif os.name == 'posix':
+ _LockImplPosix(target_file, flags)
+ else:
+ raise NotImplementedError('%s is not supported' % os.name)
+
+
+def ReleaseFileLock(target_file):
+ """ Unlock the target file.
+ Args:
+ target_file: file handle of the file to release the lock.
+ """
+ if os.name == 'nt':
+ _UnlockImplWin(target_file)
+ elif os.name == 'posix':
+ _UnlockImplPosix(target_file)
+ else:
+ raise NotImplementedError('%s is not supported' % os.name)
+
+# These implementations are based on
+# http://code.activestate.com/recipes/65203/
+
+def _LockImplWin(target_file, flags):
+ hfile = win32file._get_osfhandle(target_file.fileno())
+ try:
+ win32file.LockFileEx(hfile, flags, 0, -0x10000, _OVERLAPPED)
+ except pywintypes.error as exc_value:
+ if exc_value[0] == 33:
+ raise LockException('Error trying acquiring lock of %s: %s' %
+ (target_file.name, exc_value[2]))
+ else:
+ raise
+
+
+def _UnlockImplWin(target_file):
+ hfile = win32file._get_osfhandle(target_file.fileno())
+ try:
+ win32file.UnlockFileEx(hfile, 0, -0x10000, _OVERLAPPED)
+ except pywintypes.error as exc_value:
+ if exc_value[0] == 158:
+ # error: (158, 'UnlockFileEx', 'The segment is already unlocked.')
+ # To match the 'posix' implementation, silently ignore this error
+ pass
+ else:
+ # Q: Are there exceptions/codes we should be dealing with here?
+ raise
+
+
+def _LockImplPosix(target_file, flags):
+ try:
+ fcntl.flock(target_file.fileno(), flags)
+ except IOError as exc_value:
+ if exc_value[0] == 11 or exc_value[0] == 35:
+ raise LockException('Error trying acquiring lock of %s: %s' %
+ (target_file.name, exc_value[1]))
+ else:
+ raise
+
+
+def _UnlockImplPosix(target_file):
+ fcntl.flock(target_file.fileno(), fcntl.LOCK_UN)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/lock_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/lock_unittest.py
new file mode 100644
index 00000000000..a260621a0ab
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/lock_unittest.py
@@ -0,0 +1,165 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import multiprocessing
+import os
+import time
+import unittest
+import tempfile
+
+
+from py_utils import lock
+
+
+def _AppendTextToFile(file_name):
+ with open(file_name, 'a') as f:
+ lock.AcquireFileLock(f, lock.LOCK_EX)
+ # Sleep 100 ms to increase the chance of another process trying to acquire
+ # the lock of file as the same time.
+ time.sleep(0.1)
+ f.write('Start')
+ for _ in range(10000):
+ f.write('*')
+ f.write('End')
+
+
+def _ReadFileWithSharedLockBlockingThenWrite(read_file, write_file):
+ with open(read_file, 'r') as f:
+ lock.AcquireFileLock(f, lock.LOCK_SH)
+ content = f.read()
+ with open(write_file, 'a') as f2:
+ lock.AcquireFileLock(f2, lock.LOCK_EX)
+ f2.write(content)
+
+
+def _ReadFileWithExclusiveLockNonBlocking(target_file, status_file):
+ with open(target_file, 'r') as f:
+ try:
+ lock.AcquireFileLock(f, lock.LOCK_EX | lock.LOCK_NB)
+ with open(status_file, 'w') as f2:
+ f2.write('LockException was not raised')
+ except lock.LockException:
+ with open(status_file, 'w') as f2:
+ f2.write('LockException raised')
+
+
+class FileLockTest(unittest.TestCase):
+ def setUp(self):
+ tf = tempfile.NamedTemporaryFile(delete=False)
+ tf.close()
+ self.temp_file_path = tf.name
+
+ def tearDown(self):
+ os.remove(self.temp_file_path)
+
+ def testExclusiveLock(self):
+ processess = []
+ for _ in range(10):
+ p = multiprocessing.Process(
+ target=_AppendTextToFile, args=(self.temp_file_path,))
+ p.start()
+ processess.append(p)
+ for p in processess:
+ p.join()
+
+ # If the file lock works as expected, there should be 10 atomic writes of
+ # 'Start***...***End' to the file in some order, which lead to the final
+ # file content as below.
+ expected_file_content = ''.join((['Start'] + ['*']*10000 + ['End']) * 10)
+ with open(self.temp_file_path, 'r') as f:
+ # Use assertTrue instead of assertEquals since the strings are big, hence
+ # assertEquals's assertion failure will contain huge strings.
+ self.assertTrue(expected_file_content == f.read())
+
+ def testSharedLock(self):
+ tf = tempfile.NamedTemporaryFile(delete=False)
+ tf.close()
+ temp_write_file = tf.name
+ try:
+ with open(self.temp_file_path, 'w') as f:
+ f.write('0123456789')
+ with open(self.temp_file_path, 'r') as f:
+ # First, acquire a shared lock on temp_file_path
+ lock.AcquireFileLock(f, lock.LOCK_SH)
+
+ processess = []
+ # Create 10 processes that also try to acquire shared lock from
+ # temp_file_path then append temp_file_path's content to temp_write_file
+ for _ in range(10):
+ p = multiprocessing.Process(
+ target=_ReadFileWithSharedLockBlockingThenWrite,
+ args=(self.temp_file_path, temp_write_file))
+ p.start()
+ processess.append(p)
+ for p in processess:
+ p.join()
+
+ # temp_write_file should contains 10 copy of temp_file_path's content.
+ with open(temp_write_file, 'r') as f:
+ self.assertEquals('0123456789'*10, f.read())
+ finally:
+ os.remove(temp_write_file)
+
+ def testNonBlockingLockAcquiring(self):
+ tf = tempfile.NamedTemporaryFile(delete=False)
+ tf.close()
+ temp_status_file = tf.name
+ try:
+ with open(self.temp_file_path, 'w') as f:
+ lock.AcquireFileLock(f, lock.LOCK_EX)
+ p = multiprocessing.Process(
+ target=_ReadFileWithExclusiveLockNonBlocking,
+ args=(self.temp_file_path, temp_status_file))
+ p.start()
+ p.join()
+ with open(temp_status_file, 'r') as f:
+ self.assertEquals('LockException raised', f.read())
+ finally:
+ os.remove(temp_status_file)
+
+ def testUnlockBeforeClosingFile(self):
+ tf = tempfile.NamedTemporaryFile(delete=False)
+ tf.close()
+ temp_status_file = tf.name
+ try:
+ with open(self.temp_file_path, 'r') as f:
+ lock.AcquireFileLock(f, lock.LOCK_SH)
+ lock.ReleaseFileLock(f)
+ p = multiprocessing.Process(
+ target=_ReadFileWithExclusiveLockNonBlocking,
+ args=(self.temp_file_path, temp_status_file))
+ p.start()
+ p.join()
+ with open(temp_status_file, 'r') as f:
+ self.assertEquals('LockException was not raised', f.read())
+ finally:
+ os.remove(temp_status_file)
+
+ def testContextualLock(self):
+ tf = tempfile.NamedTemporaryFile(delete=False)
+ tf.close()
+ temp_status_file = tf.name
+ try:
+ with open(self.temp_file_path, 'r') as f:
+ with lock.FileLock(f, lock.LOCK_EX):
+ # Within this block, accessing self.temp_file_path from another
+ # process should raise exception.
+ p = multiprocessing.Process(
+ target=_ReadFileWithExclusiveLockNonBlocking,
+ args=(self.temp_file_path, temp_status_file))
+ p.start()
+ p.join()
+ with open(temp_status_file, 'r') as f:
+ self.assertEquals('LockException raised', f.read())
+
+ # Accessing self.temp_file_path here should not raise exception.
+ p = multiprocessing.Process(
+ target=_ReadFileWithExclusiveLockNonBlocking,
+ args=(self.temp_file_path, temp_status_file))
+ p.start()
+ p.join()
+ with open(temp_status_file, 'r') as f:
+ self.assertEquals('LockException was not raised', f.read())
+ finally:
+ os.remove(temp_status_file)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/logging_util.py b/chromium/third_party/catapult/common/py_utils/py_utils/logging_util.py
new file mode 100644
index 00000000000..435785116bc
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/logging_util.py
@@ -0,0 +1,35 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Logging util functions.
+
+It would be named logging, but other modules in this directory use the default
+logging module, so that would break them.
+"""
+
+import contextlib
+import logging
+
+@contextlib.contextmanager
+def CaptureLogs(file_stream):
+ if not file_stream:
+ # No file stream given, just don't capture logs.
+ yield
+ return
+
+ fh = logging.StreamHandler(file_stream)
+
+ logger = logging.getLogger()
+ # Try to copy the current log format, if one is set.
+ if logger.handlers and hasattr(logger.handlers[0], 'formatter'):
+ fh.formatter = logger.handlers[0].formatter
+ else:
+ fh.setFormatter(logging.Formatter(
+ '(%(levelname)s) %(asctime)s %(message)s'))
+ logger.addHandler(fh)
+
+ try:
+ yield
+ finally:
+ logger = logging.getLogger()
+ logger.removeHandler(fh)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/logging_util_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/logging_util_unittest.py
new file mode 100644
index 00000000000..59e61077984
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/logging_util_unittest.py
@@ -0,0 +1,27 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import unittest
+
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+from py_utils import logging_util
+
+
+class LoggingUtilTest(unittest.TestCase):
+ def testCapture(self):
+ s = StringIO()
+ with logging_util.CaptureLogs(s):
+ logging.fatal('test')
+
+ # Only assert ends with, since the logging message by default has the date
+ # in it.
+ self.assertTrue(s.getvalue().endswith('test\n'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/memory_debug.py b/chromium/third_party/catapult/common/py_utils/py_utils/memory_debug.py
new file mode 100755
index 00000000000..e63938f38ef
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/memory_debug.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import heapq
+import logging
+import os
+import sys
+try:
+ import psutil
+except ImportError:
+ psutil = None
+
+
+BYTE_UNITS = ['B', 'KiB', 'MiB', 'GiB']
+
+
+def FormatBytes(value):
+ def GetValueAndUnit(value):
+ for unit in BYTE_UNITS[:-1]:
+ if abs(value) < 1024.0:
+ return value, unit
+ value /= 1024.0
+ return value, BYTE_UNITS[-1]
+
+ if value is not None:
+ return '%.1f %s' % GetValueAndUnit(value)
+ else:
+ return 'N/A'
+
+
+def _GetProcessInfo(p):
+ pinfo = p.as_dict(attrs=['pid', 'name', 'memory_info'])
+ pinfo['mem_rss'] = getattr(pinfo['memory_info'], 'rss', 0)
+ return pinfo
+
+
+def _LogProcessInfo(pinfo, level):
+ pinfo['mem_rss_fmt'] = FormatBytes(pinfo['mem_rss'])
+ logging.log(level, '%(mem_rss_fmt)s (pid=%(pid)s)', pinfo)
+
+
+def LogHostMemoryUsage(top_n=10, level=logging.INFO):
+ if not psutil:
+ logging.warning('psutil module is not found, skipping logging memory info')
+ return
+ if psutil.version_info < (2, 0):
+ logging.warning('psutil %s too old, upgrade to version 2.0 or higher'
+ ' for memory usage information.', psutil.__version__)
+ return
+
+ # TODO(crbug.com/777865): Remove the following pylint disable. Even if we
+ # check for a recent enough psutil version above, the catapult presubmit
+ # builder (still running some old psutil) fails pylint checks due to API
+ # changes in psutil.
+ # pylint: disable=no-member
+ mem = psutil.virtual_memory()
+ logging.log(level, 'Used %s out of %s memory available.',
+ FormatBytes(mem.used), FormatBytes(mem.total))
+ logging.log(level, 'Memory usage of top %i processes groups', top_n)
+ pinfos_by_names = {}
+ for p in psutil.process_iter():
+ try:
+ pinfo = _GetProcessInfo(p)
+ except psutil.NoSuchProcess:
+ logging.exception('process %s no longer exists', p)
+ continue
+ pname = pinfo['name']
+ if pname not in pinfos_by_names:
+ pinfos_by_names[pname] = {'name': pname, 'total_mem_rss': 0, 'pids': []}
+ pinfos_by_names[pname]['total_mem_rss'] += pinfo['mem_rss']
+ pinfos_by_names[pname]['pids'].append(str(pinfo['pid']))
+
+ sorted_pinfo_groups = heapq.nlargest(
+ top_n, pinfos_by_names.values(), key=lambda item: item['total_mem_rss'])
+ for group in sorted_pinfo_groups:
+ group['total_mem_rss_fmt'] = FormatBytes(group['total_mem_rss'])
+ group['pids_fmt'] = ', '.join(group['pids'])
+ logging.log(
+ level, '- %(name)s - %(total_mem_rss_fmt)s - pids: %(pids)s', group)
+ logging.log(level, 'Current process:')
+ pinfo = _GetProcessInfo(psutil.Process(os.getpid()))
+ _LogProcessInfo(pinfo, level)
+
+
+def main():
+ logging.basicConfig(level=logging.INFO)
+ LogHostMemoryUsage()
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/modules_util.py b/chromium/third_party/catapult/common/py_utils/py_utils/modules_util.py
new file mode 100644
index 00000000000..6c1106d77f4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/modules_util.py
@@ -0,0 +1,35 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from distutils import version # pylint: disable=no-name-in-module
+
+
+def RequireVersion(module, min_version, max_version=None):
+ """Ensure that an imported module's version is within a required range.
+
+ Version strings are parsed with LooseVersion, so versions like "1.8.0rc1"
+ (default numpy on macOS Sierra) and "2.4.13.2" (a version of OpenCV 2.x)
+ are allowed.
+
+ Args:
+ module: An already imported python module.
+ min_version: The module must have this or a higher version.
+ max_version: Optional, the module should not have this or a higher version.
+
+ Raises:
+ ImportError if the module's __version__ is not within the allowed range.
+ """
+ module_version = version.LooseVersion(module.__version__)
+ min_version = version.LooseVersion(str(min_version))
+ valid_version = min_version <= module_version
+
+ if max_version is not None:
+ max_version = version.LooseVersion(str(max_version))
+ valid_version = valid_version and (module_version < max_version)
+ wants_version = 'at or above %s and below %s' % (min_version, max_version)
+ else:
+ wants_version = '%s or higher' % min_version
+
+ if not valid_version:
+ raise ImportError('%s has version %s, but version %s is required' % (
+ module.__name__, module_version, wants_version))
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/modules_util_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/modules_util_unittest.py
new file mode 100644
index 00000000000..ad910357f82
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/modules_util_unittest.py
@@ -0,0 +1,42 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from py_utils import modules_util
+
+
+class FakeModule(object):
+ def __init__(self, name, version):
+ self.__name__ = name
+ self.__version__ = version
+
+
+class ModulesUitlTest(unittest.TestCase):
+ def testRequireVersion_valid(self):
+ numpy = FakeModule('numpy', '2.3')
+ try:
+ modules_util.RequireVersion(numpy, '1.0')
+ except ImportError:
+ self.fail('ImportError raised unexpectedly')
+
+ def testRequireVersion_versionTooLow(self):
+ numpy = FakeModule('numpy', '2.3')
+ with self.assertRaises(ImportError) as error:
+ modules_util.RequireVersion(numpy, '2.5')
+ self.assertEqual(
+ error.exception.message,
+ 'numpy has version 2.3, but version 2.5 or higher is required')
+
+ def testRequireVersion_versionTooHigh(self):
+ numpy = FakeModule('numpy', '2.3')
+ with self.assertRaises(ImportError) as error:
+ modules_util.RequireVersion(numpy, '1.0', '2.0')
+ self.assertEqual(
+ error.exception.message,
+ 'numpy has version 2.3, but version'
+ ' at or above 1.0 and below 2.0 is required')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/py_utils_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/py_utils_unittest.py
new file mode 100644
index 00000000000..588a5d57572
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/py_utils_unittest.py
@@ -0,0 +1,56 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+import unittest
+
+import py_utils
+
+
+class PathTest(unittest.TestCase):
+
+ def testIsExecutable(self):
+ self.assertFalse(py_utils.IsExecutable('nonexistent_file'))
+ # We use actual files on disk instead of pyfakefs because the executable is
+ # set different on win that posix platforms and pyfakefs doesn't support
+ # win platform well.
+ self.assertFalse(py_utils.IsExecutable(_GetFileInTestDir('foo.txt')))
+ self.assertTrue(py_utils.IsExecutable(sys.executable))
+
+
+def _GetFileInTestDir(file_name):
+ return os.path.join(os.path.dirname(__file__), 'test_data', file_name)
+
+
+class WaitForTest(unittest.TestCase):
+
+ def testWaitForTrue(self):
+ def ReturnTrue():
+ return True
+ self.assertTrue(py_utils.WaitFor(ReturnTrue, .1))
+
+ def testWaitForFalse(self):
+ def ReturnFalse():
+ return False
+
+ with self.assertRaises(py_utils.TimeoutException):
+ py_utils.WaitFor(ReturnFalse, .1)
+
+ def testWaitForEventuallyTrue(self):
+ # Use list to pass to inner function in order to allow modifying the
+ # variable from the outer scope.
+ c = [0]
+ def ReturnCounterBasedValue():
+ c[0] += 1
+ return c[0] > 2
+
+ self.assertTrue(py_utils.WaitFor(ReturnCounterBasedValue, .5))
+
+ def testWaitForTrueLambda(self):
+ self.assertTrue(py_utils.WaitFor(lambda: True, .1))
+
+ def testWaitForFalseLambda(self):
+ with self.assertRaises(py_utils.TimeoutException):
+ py_utils.WaitFor(lambda: False, .1)
+
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/__init__.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/__init__.py
new file mode 100644
index 00000000000..e3fbb5faf63
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/__init__.py
@@ -0,0 +1,28 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Style-preserving Python code transforms.
+
+This module provides components for modifying and querying Python code. They can
+be used to build custom refactorings and linters.
+"""
+
+import functools
+import multiprocessing
+
+# pylint: disable=wildcard-import
+from py_utils.refactor.annotated_symbol import *
+from py_utils.refactor.module import Module
+
+
+def _TransformFile(transform, file_path):
+ module = Module(file_path)
+ result = transform(module)
+ module.Write()
+ return result
+
+
+def Transform(transform, file_paths):
+ transform = functools.partial(_TransformFile, transform)
+ return multiprocessing.Pool().map(transform, file_paths)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/__init__.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/__init__.py
new file mode 100644
index 00000000000..c39118030e0
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/__init__.py
@@ -0,0 +1,71 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# pylint: disable=wildcard-import
+from py_utils.refactor.annotated_symbol.class_definition import *
+from py_utils.refactor.annotated_symbol.function_definition import *
+from py_utils.refactor.annotated_symbol.import_statement import *
+from py_utils.refactor.annotated_symbol.reference import *
+from py_utils.refactor import snippet
+
+
+__all__ = [
+ 'Annotate',
+
+ 'Class',
+ 'Function',
+ 'Import',
+ 'Reference',
+]
+
+
+# Specific symbol types with extra methods for manipulating them.
+# Python's full grammar is here:
+# https://docs.python.org/2/reference/grammar.html
+
+# Annotated Symbols have an Annotate classmethod that takes a symbol type and
+# list of children, and returns an instance of that annotated Symbol.
+
+ANNOTATED_SYMBOLS = (
+ AsName,
+ Class,
+ DottedName,
+ ImportFrom,
+ ImportName,
+ Function,
+)
+
+
+# Unfortunately, some logical groupings are not represented by a node in the
+# parse tree. To work around this, some annotated Symbols have an Annotate
+# classmethod that takes and returns a list of Snippets instead.
+
+ANNOTATED_GROUPINGS = (
+ Reference,
+)
+
+
+def Annotate(f):
+ """Return the syntax tree of the given file."""
+ return _AnnotateNode(snippet.Snippetize(f))
+
+
+def _AnnotateNode(node):
+ if not isinstance(node, snippet.Symbol):
+ return node
+
+ children = [_AnnotateNode(c) for c in node.children]
+
+ for symbol_type in ANNOTATED_GROUPINGS:
+ annotated_grouping = symbol_type.Annotate(children)
+ if annotated_grouping:
+ children = annotated_grouping
+ break
+
+ for symbol_type in ANNOTATED_SYMBOLS:
+ annotated_symbol = symbol_type.Annotate(node.type, children)
+ if annotated_symbol:
+ return annotated_symbol
+
+ return snippet.Symbol(node.type, children)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/base_symbol.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/base_symbol.py
new file mode 100644
index 00000000000..2e28e89f692
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/base_symbol.py
@@ -0,0 +1,36 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from py_utils.refactor import snippet
+
+
+class AnnotatedSymbol(snippet.Symbol):
+ def __init__(self, symbol_type, children):
+ super(AnnotatedSymbol, self).__init__(symbol_type, children)
+ self._modified = False
+
+ @property
+ def modified(self):
+ if self._modified:
+ return True
+ return super(AnnotatedSymbol, self).modified
+
+ def __setattr__(self, name, value):
+ if (hasattr(self.__class__, name) and
+ isinstance(getattr(self.__class__, name), property)):
+ self._modified = True
+ return super(AnnotatedSymbol, self).__setattr__(name, value)
+
+ def Cut(self, child):
+ for i in xrange(len(self._children)):
+ if self._children[i] == child:
+ self._modified = True
+ del self._children[i]
+ break
+ else:
+ raise ValueError('%s is not in %s.' % (child, self))
+
+ def Paste(self, child):
+ self._modified = True
+ self._children.append(child)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/class_definition.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/class_definition.py
new file mode 100644
index 00000000000..a83ac96d895
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/class_definition.py
@@ -0,0 +1,49 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import symbol
+
+from py_utils.refactor.annotated_symbol import base_symbol
+
+
+__all__ = [
+ 'Class',
+]
+
+
+class Class(base_symbol.AnnotatedSymbol):
+ @classmethod
+ def Annotate(cls, symbol_type, children):
+ if symbol_type != symbol.stmt:
+ return None
+
+ compound_statement = children[0]
+ if compound_statement.type != symbol.compound_stmt:
+ return None
+
+ statement = compound_statement.children[0]
+ if statement.type == symbol.classdef:
+ return cls(statement.type, statement.children)
+ elif (statement.type == symbol.decorated and
+ statement.children[-1].type == symbol.classdef):
+ return cls(statement.type, statement.children)
+ else:
+ return None
+
+ @property
+ def suite(self):
+ # TODO: Complete.
+ raise NotImplementedError()
+
+ def FindChild(self, snippet_type, **kwargs):
+ return self.suite.FindChild(snippet_type, **kwargs)
+
+ def FindChildren(self, snippet_type):
+ return self.suite.FindChildren(snippet_type)
+
+ def Cut(self, child):
+ self.suite.Cut(child)
+
+ def Paste(self, child):
+ self.suite.Paste(child)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/function_definition.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/function_definition.py
new file mode 100644
index 00000000000..384d3cf134d
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/function_definition.py
@@ -0,0 +1,49 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import symbol
+
+from py_utils.refactor.annotated_symbol import base_symbol
+
+
+__all__ = [
+ 'Function',
+]
+
+
+class Function(base_symbol.AnnotatedSymbol):
+ @classmethod
+ def Annotate(cls, symbol_type, children):
+ if symbol_type != symbol.stmt:
+ return None
+
+ compound_statement = children[0]
+ if compound_statement.type != symbol.compound_stmt:
+ return None
+
+ statement = compound_statement.children[0]
+ if statement.type == symbol.funcdef:
+ return cls(statement.type, statement.children)
+ elif (statement.type == symbol.decorated and
+ statement.children[-1].type == symbol.funcdef):
+ return cls(statement.type, statement.children)
+ else:
+ return None
+
+ @property
+ def suite(self):
+ # TODO: Complete.
+ raise NotImplementedError()
+
+ def FindChild(self, snippet_type, **kwargs):
+ return self.suite.FindChild(snippet_type, **kwargs)
+
+ def FindChildren(self, snippet_type):
+ return self.suite.FindChildren(snippet_type)
+
+ def Cut(self, child):
+ self.suite.Cut(child)
+
+ def Paste(self, child):
+ self.suite.Paste(child)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/import_statement.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/import_statement.py
new file mode 100644
index 00000000000..94e608ccfe7
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/import_statement.py
@@ -0,0 +1,327 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import itertools
+import keyword
+import symbol
+import token
+
+from py_utils.refactor.annotated_symbol import base_symbol
+from py_utils.refactor import snippet
+
+
+__all__ = [
+ 'AsName',
+ 'DottedName',
+ 'Import',
+ 'ImportFrom',
+ 'ImportName',
+]
+
+
+class DottedName(base_symbol.AnnotatedSymbol):
+ @classmethod
+ def Annotate(cls, symbol_type, children):
+ if symbol_type != symbol.dotted_name:
+ return None
+ return cls(symbol_type, children)
+
+ @property
+ def value(self):
+ return ''.join(token_snippet.value for token_snippet in self._children)
+
+ @value.setter
+ def value(self, value):
+ value_parts = value.split('.')
+ for value_part in value_parts:
+ if keyword.iskeyword(value_part):
+ raise ValueError('%s is a reserved keyword.' % value_part)
+
+ # If we have too many children, cut the list down to size.
+ # pylint: disable=attribute-defined-outside-init
+ self._children = self._children[:len(value_parts)*2-1]
+
+ # Update child nodes.
+ for child, value_part in itertools.izip_longest(
+ self._children[::2], value_parts):
+ if child:
+ # Modify existing children. This helps preserve comments and spaces.
+ child.value = value_part
+ else:
+ # Add children as needed.
+ self._children.append(snippet.TokenSnippet.Create(token.DOT, '.'))
+ self._children.append(
+ snippet.TokenSnippet.Create(token.NAME, value_part))
+
+
+class AsName(base_symbol.AnnotatedSymbol):
+ @classmethod
+ def Annotate(cls, symbol_type, children):
+ if (symbol_type != symbol.dotted_as_name and
+ symbol_type != symbol.import_as_name):
+ return None
+ return cls(symbol_type, children)
+
+ @property
+ def name(self):
+ return self.children[0].value
+
+ @name.setter
+ def name(self, value):
+ self.children[0].value = value
+
+ @property
+ def alias(self):
+ if len(self.children) < 3:
+ return None
+ return self.children[2].value
+
+ @alias.setter
+ def alias(self, value):
+ if keyword.iskeyword(value):
+ raise ValueError('%s is a reserved keyword.' % value)
+
+ if value:
+ # pylint: disable=access-member-before-definition
+ if len(self.children) < 3:
+ # If we currently have no alias, add one.
+ # pylint: disable=access-member-before-definition
+ self.children.append(
+ snippet.TokenSnippet.Create(token.NAME, 'as', (0, 1)))
+ # pylint: disable=access-member-before-definition
+ self.children.append(
+ snippet.TokenSnippet.Create(token.NAME, value, (0, 1)))
+ else:
+ # We already have an alias. Just update the value.
+ # pylint: disable=access-member-before-definition
+ self.children[2].value = value
+ else:
+ # Removing the alias. Strip the "as foo".
+ self.children = [self.children[0]] # pylint: disable=line-too-long, attribute-defined-outside-init
+
+
+class Import(base_symbol.AnnotatedSymbol):
+ """An import statement.
+
+ Example:
+ import a.b.c as d
+ from a.b import c as d
+
+ In these examples,
+ path == 'a.b.c'
+ alias == 'd'
+ root == 'a.b' (only for "from" imports)
+ module == 'c' (only for "from" imports)
+ name (read-only) == the name used by references to the module, which is the
+ alias if there is one, the full module path in "full" imports, and the
+ module name in "from" imports.
+ """
+ @property
+ def has_from(self):
+ """Returns True iff the import statment is of the form "from x import y"."""
+ raise NotImplementedError()
+
+ @property
+ def values(self):
+ raise NotImplementedError()
+
+ @property
+ def paths(self):
+ raise NotImplementedError()
+
+ @property
+ def aliases(self):
+ raise NotImplementedError()
+
+ @property
+ def path(self):
+ """The full dotted path of the module."""
+ raise NotImplementedError()
+
+ @path.setter
+ def path(self, value):
+ raise NotImplementedError()
+
+ @property
+ def alias(self):
+ """The alias, if the module is renamed with "as". None otherwise."""
+ raise NotImplementedError()
+
+ @alias.setter
+ def alias(self, value):
+ raise NotImplementedError()
+
+ @property
+ def name(self):
+ """The name used to reference this import's module."""
+ raise NotImplementedError()
+
+
+class ImportName(Import):
+ @classmethod
+ def Annotate(cls, symbol_type, children):
+ if symbol_type != symbol.import_stmt:
+ return None
+ if children[0].type != symbol.import_name:
+ return None
+ assert len(children) == 1
+ return cls(symbol_type, children[0].children)
+
+ @property
+ def has_from(self):
+ return False
+
+ @property
+ def values(self):
+ dotted_as_names = self.children[1]
+ return tuple((dotted_as_name.name, dotted_as_name.alias)
+ for dotted_as_name in dotted_as_names.children[::2])
+
+ @property
+ def paths(self):
+ return tuple(path for path, _ in self.values)
+
+ @property
+ def aliases(self):
+ return tuple(alias for _, alias in self.values)
+
+ @property
+ def _dotted_as_name(self):
+ dotted_as_names = self.children[1]
+ if len(dotted_as_names.children) != 1:
+ raise NotImplementedError(
+ 'This method only works if the statement has one import.')
+ return dotted_as_names.children[0]
+
+ @property
+ def path(self):
+ return self._dotted_as_name.name
+
+ @path.setter
+ def path(self, value): # pylint: disable=arguments-differ
+ self._dotted_as_name.name = value
+
+ @property
+ def alias(self):
+ return self._dotted_as_name.alias
+
+ @alias.setter
+ def alias(self, value): # pylint: disable=arguments-differ
+ self._dotted_as_name.alias = value
+
+ @property
+ def name(self):
+ if self.alias:
+ return self.alias
+ else:
+ return self.path
+
+
+class ImportFrom(Import):
+ @classmethod
+ def Annotate(cls, symbol_type, children):
+ if symbol_type != symbol.import_stmt:
+ return None
+ if children[0].type != symbol.import_from:
+ return None
+ assert len(children) == 1
+ return cls(symbol_type, children[0].children)
+
+ @property
+ def has_from(self):
+ return True
+
+ @property
+ def values(self):
+ try:
+ import_as_names = self.FindChild(symbol.import_as_names)
+ except ValueError:
+ return (('*', None),)
+
+ return tuple((import_as_name.name, import_as_name.alias)
+ for import_as_name in import_as_names.children[::2])
+
+ @property
+ def paths(self):
+ module = self.module
+ return tuple('.'.join((module, name)) for name, _ in self.values)
+
+ @property
+ def aliases(self):
+ return tuple(alias for _, alias in self.values)
+
+ @property
+ def root(self):
+ return self.FindChild(symbol.dotted_name).value
+
+ @root.setter
+ def root(self, value):
+ self.FindChild(symbol.dotted_name).value = value
+
+ @property
+ def _import_as_name(self):
+ try:
+ import_as_names = self.FindChild(symbol.import_as_names)
+ except ValueError:
+ return None
+
+ if len(import_as_names.children) != 1:
+ raise NotImplementedError(
+ 'This method only works if the statement has one import.')
+
+ return import_as_names.children[0]
+
+ @property
+ def module(self):
+ import_as_name = self._import_as_name
+ if import_as_name:
+ return import_as_name.name
+ else:
+ return '*'
+
+ @module.setter
+ def module(self, value):
+ if keyword.iskeyword(value):
+ raise ValueError('%s is a reserved keyword.' % value)
+
+ import_as_name = self._import_as_name
+ if value == '*':
+ # TODO: Implement this.
+ raise NotImplementedError()
+ else:
+ if import_as_name:
+ import_as_name.name = value
+ else:
+ # TODO: Implement this.
+ raise NotImplementedError()
+
+ @property
+ def path(self):
+ return '.'.join((self.root, self.module))
+
+ @path.setter
+ def path(self, value): # pylint: disable=arguments-differ
+ self.root, _, self.module = value.rpartition('.')
+
+ @property
+ def alias(self):
+ import_as_name = self._import_as_name
+ if import_as_name:
+ return import_as_name.alias
+ else:
+ return None
+
+ @alias.setter
+ def alias(self, value): # pylint: disable=arguments-differ
+ import_as_name = self._import_as_name
+ if not import_as_name:
+ raise NotImplementedError('Cannot change alias for "import *".')
+ import_as_name.alias = value
+
+ @property
+ def name(self):
+ if self.alias:
+ return self.alias
+ else:
+ return self.module
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/reference.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/reference.py
new file mode 100644
index 00000000000..9102c8601c4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/annotated_symbol/reference.py
@@ -0,0 +1,76 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import itertools
+import symbol
+import token
+
+from py_utils.refactor.annotated_symbol import base_symbol
+from py_utils.refactor import snippet
+
+
+__all__ = [
+ 'Reference',
+]
+
+
+class Reference(base_symbol.AnnotatedSymbol):
+ @classmethod
+ def Annotate(cls, nodes):
+ if not nodes:
+ return None
+ if nodes[0].type != symbol.atom:
+ return None
+ if not nodes[0].children or nodes[0].children[0].type != token.NAME:
+ return None
+
+ for i in xrange(1, len(nodes)):
+ if not nodes:
+ break
+ if nodes[i].type != symbol.trailer:
+ break
+ if len(nodes[i].children) != 2:
+ break
+ if (nodes[i].children[0].type != token.DOT or
+ nodes[i].children[1].type != token.NAME):
+ break
+ else:
+ i = len(nodes)
+
+ return [cls(nodes[:i])] + nodes[i:]
+
+ def __init__(self, children):
+ super(Reference, self).__init__(-1, children)
+
+ @property
+ def type_name(self):
+ return 'attribute_reference'
+
+ @property
+ def value(self):
+ return ''.join(token_snippet.value
+ for child in self.children
+ for token_snippet in child.children)
+
+ @value.setter
+ def value(self, value):
+ value_parts = value.split('.')
+
+ # If we have too many children, cut the list down to size.
+ # pylint: disable=attribute-defined-outside-init
+ self._children = self._children[:len(value_parts)]
+
+ # Update child nodes.
+ for child, value_part in itertools.izip_longest(
+ self._children, value_parts):
+ if child:
+ # Modify existing children. This helps preserve comments and spaces.
+ child.children[-1].value = value_part
+ else:
+ # Add children as needed.
+ token_snippets = [
+ snippet.TokenSnippet.Create(token.DOT, '.'),
+ snippet.TokenSnippet.Create(token.NAME, value_part),
+ ]
+ self._children.append(snippet.Symbol(symbol.trailer, token_snippets))
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/module.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/module.py
new file mode 100644
index 00000000000..d6eae00cdb4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/module.py
@@ -0,0 +1,39 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from py_utils.refactor import annotated_symbol
+
+
+class Module(object):
+
+ def __init__(self, file_path):
+ self._file_path = file_path
+
+ with open(self._file_path, 'r') as f:
+ self._snippet = annotated_symbol.Annotate(f)
+
+ @property
+ def file_path(self):
+ return self._file_path
+
+ @property
+ def modified(self):
+ return self._snippet.modified
+
+ def FindAll(self, snippet_type):
+ return self._snippet.FindAll(snippet_type)
+
+ def FindChildren(self, snippet_type):
+ return self._snippet.FindChildren(snippet_type)
+
+ def Write(self):
+ """Write modifications to the file."""
+ if not self.modified:
+ return
+
+ # Stringify before opening the file for writing.
+ # If we fail, we won't truncate the file.
+ string = str(self._snippet)
+ with open(self._file_path, 'w') as f:
+ f.write(string)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/offset_token.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/offset_token.py
new file mode 100644
index 00000000000..5fa953e93fb
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/offset_token.py
@@ -0,0 +1,115 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import itertools
+import token
+import tokenize
+
+
+def _Pairwise(iterable):
+ """s -> (None, s0), (s0, s1), (s1, s2), (s2, s3), ..."""
+ a, b = itertools.tee(iterable)
+ a = itertools.chain((None,), a)
+ return itertools.izip(a, b)
+
+
+class OffsetToken(object):
+ """A Python token with a relative position.
+
+ A token is represented by a type defined in Python's token module, a string
+ representing the content, and an offset. Using relative positions makes it
+ easy to insert and remove tokens.
+ """
+
+ def __init__(self, token_type, string, offset):
+ self._type = token_type
+ self._string = string
+ self._offset = offset
+
+ @property
+ def type(self):
+ return self._type
+
+ @property
+ def type_name(self):
+ return token.tok_name[self._type]
+
+ @property
+ def string(self):
+ return self._string
+
+ @string.setter
+ def string(self, value):
+ self._string = value
+
+ @property
+ def offset(self):
+ return self._offset
+
+ def __str__(self):
+ return str((self.type_name, self.string, self.offset))
+
+
+def Tokenize(f):
+ """Read tokens from a file-like object.
+
+ Args:
+ f: Any object that has a readline method.
+
+ Returns:
+ A collections.deque containing OffsetTokens. Deques are cheaper and easier
+ to manipulate sequentially than lists.
+ """
+ f.seek(0)
+ tokenize_tokens = tokenize.generate_tokens(f.readline)
+
+ offset_tokens = collections.deque()
+ for prev_token, next_token in _Pairwise(tokenize_tokens):
+ token_type, string, (srow, scol), _, _ = next_token
+ if not prev_token:
+ offset_tokens.append(OffsetToken(token_type, string, (0, 0)))
+ else:
+ erow, ecol = prev_token[3]
+ if erow == srow:
+ offset_tokens.append(OffsetToken(token_type, string, (0, scol - ecol)))
+ else:
+ offset_tokens.append(OffsetToken(
+ token_type, string, (srow - erow, scol)))
+
+ return offset_tokens
+
+
+def Untokenize(offset_tokens):
+ """Return the string representation of an iterable of OffsetTokens."""
+ # Make a copy. Don't modify the original.
+ offset_tokens = collections.deque(offset_tokens)
+
+ # Strip leading NL tokens.
+ while offset_tokens[0].type == tokenize.NL:
+ offset_tokens.popleft()
+
+ # Strip leading vertical whitespace.
+ first_token = offset_tokens.popleft()
+ # Take care not to modify the existing token. Create a new one in its place.
+ first_token = OffsetToken(first_token.type, first_token.string,
+ (0, first_token.offset[1]))
+ offset_tokens.appendleft(first_token)
+
+ # Convert OffsetTokens to tokenize tokens.
+ tokenize_tokens = []
+ row = 1
+ col = 0
+ for t in offset_tokens:
+ offset_row, offset_col = t.offset
+ if offset_row == 0:
+ col += offset_col
+ else:
+ row += offset_row
+ col = offset_col
+ tokenize_tokens.append((t.type, t.string, (row, col), (row, col), None))
+
+ # tokenize can't handle whitespace before line continuations.
+ # So add a space.
+ return tokenize.untokenize(tokenize_tokens).replace('\\\n', ' \\\n')
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor/snippet.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/snippet.py
new file mode 100644
index 00000000000..7056abf74a0
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor/snippet.py
@@ -0,0 +1,246 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import parser
+import symbol
+import sys
+import token
+import tokenize
+
+from py_utils.refactor import offset_token
+
+
+class Snippet(object):
+ """A node in the Python parse tree.
+
+ The Python grammar is defined at:
+ https://docs.python.org/2/reference/grammar.html
+
+ There are two types of Snippets:
+ TokenSnippets are leaf nodes containing actual text.
+ Symbols are internal nodes representing higher-level groupings, and are
+ defined by the left-hand sides of the BNFs in the above link.
+ """
+ @property
+ def type(self):
+ raise NotImplementedError()
+
+ @property
+ def type_name(self):
+ raise NotImplementedError()
+
+ @property
+ def children(self):
+ """Return a list of this node's children."""
+ raise NotImplementedError()
+
+ @property
+ def tokens(self):
+ """Return a tuple of the tokens this Snippet contains."""
+ raise NotImplementedError()
+
+ def PrintTree(self, indent=0, stream=sys.stdout):
+ """Spew a pretty-printed parse tree. Mostly useful for debugging."""
+ raise NotImplementedError()
+
+ def __str__(self):
+ return offset_token.Untokenize(self.tokens)
+
+ def FindAll(self, snippet_type):
+ if isinstance(snippet_type, int):
+ if self.type == snippet_type:
+ yield self
+ else:
+ if isinstance(self, snippet_type):
+ yield self
+
+ for child in self.children:
+ for snippet in child.FindAll(snippet_type):
+ yield snippet
+
+ def FindChild(self, snippet_type, **kwargs):
+ for child in self.children:
+ if isinstance(snippet_type, int):
+ if child.type != snippet_type:
+ continue
+ else:
+ if not isinstance(child, snippet_type):
+ continue
+
+ for attribute, value in kwargs:
+ if getattr(child, attribute) != value:
+ break
+ else:
+ return child
+ raise ValueError('%s is not in %s. Children are: %s' %
+ (snippet_type, self, self.children))
+
+ def FindChildren(self, snippet_type):
+ if isinstance(snippet_type, int):
+ for child in self.children:
+ if child.type == snippet_type:
+ yield child
+ else:
+ for child in self.children:
+ if isinstance(child, snippet_type):
+ yield child
+
+
+class TokenSnippet(Snippet):
+ """A Snippet containing a list of tokens.
+
+ A list of tokens may start with any number of comments and non-terminating
+ newlines, but must end with a syntactically meaningful token.
+ """
+
+ def __init__(self, token_type, tokens):
+ # For operators and delimiters, the TokenSnippet's type may be more specific
+ # than the type of the constituent token. E.g. the TokenSnippet type is
+ # token.DOT, but the token type is token.OP. This is because the parser
+ # has more context than the tokenizer.
+ self._type = token_type
+ self._tokens = tokens
+ self._modified = False
+
+ @classmethod
+ def Create(cls, token_type, string, offset=(0, 0)):
+ return cls(token_type,
+ [offset_token.OffsetToken(token_type, string, offset)])
+
+ @property
+ def type(self):
+ return self._type
+
+ @property
+ def type_name(self):
+ return token.tok_name[self.type]
+
+ @property
+ def value(self):
+ return self._tokens[-1].string
+
+ @value.setter
+ def value(self, value):
+ self._tokens[-1].string = value
+ self._modified = True
+
+ @property
+ def children(self):
+ return []
+
+ @property
+ def tokens(self):
+ return tuple(self._tokens)
+
+ @property
+ def modified(self):
+ return self._modified
+
+ def PrintTree(self, indent=0, stream=sys.stdout):
+ stream.write(' ' * indent)
+ if not self.tokens:
+ print(self.type_name, file=stream)
+ return
+
+ print('%-4s' % self.type_name, repr(self.tokens[0].string), file=stream)
+ for tok in self.tokens[1:]:
+ stream.write(' ' * indent)
+ print(' ' * max(len(self.type_name), 4), repr(tok.string), file=stream)
+
+
+class Symbol(Snippet):
+ """A Snippet containing sub-Snippets.
+
+ The possible types and type_names are defined in Python's symbol module."""
+
+ def __init__(self, symbol_type, children):
+ self._type = symbol_type
+ self._children = children
+
+ @property
+ def type(self):
+ return self._type
+
+ @property
+ def type_name(self):
+ return symbol.sym_name[self.type]
+
+ @property
+ def children(self):
+ return self._children
+
+ @children.setter
+ def children(self, value): # pylint: disable=arguments-differ
+ self._children = value
+
+ @property
+ def tokens(self):
+ tokens = []
+ for child in self.children:
+ tokens += child.tokens
+ return tuple(tokens)
+
+ @property
+ def modified(self):
+ return any(child.modified for child in self.children)
+
+ def PrintTree(self, indent=0, stream=sys.stdout):
+ stream.write(' ' * indent)
+
+ # If there's only one child, collapse it onto the same line.
+ node = self
+ while len(node.children) == 1 and len(node.children[0].children) == 1:
+ print(node.type_name, end=' ', file=stream)
+ node = node.children[0]
+
+ print(node.type_name, file=stream)
+ for child in node.children:
+ child.PrintTree(indent + 2, stream)
+
+
+def Snippetize(f):
+ """Return the syntax tree of the given file."""
+ f.seek(0)
+ syntax_tree = parser.st2list(parser.suite(f.read()))
+ tokens = offset_token.Tokenize(f)
+
+ snippet = _SnippetizeNode(syntax_tree, tokens)
+ assert not tokens
+ return snippet
+
+
+def _SnippetizeNode(node, tokens):
+ # The parser module gives a syntax tree that discards comments,
+ # non-terminating newlines, and whitespace information. Use the tokens given
+ # by the tokenize module to annotate the syntax tree with the information
+ # needed to exactly reproduce the original source code.
+ node_type = node[0]
+
+ if node_type >= token.NT_OFFSET:
+ # Symbol.
+ children = tuple(_SnippetizeNode(child, tokens) for child in node[1:])
+ return Symbol(node_type, children)
+ else:
+ # Token.
+ grabbed_tokens = []
+ while tokens and (
+ tokens[0].type == tokenize.COMMENT or tokens[0].type == tokenize.NL):
+ grabbed_tokens.append(tokens.popleft())
+
+ # parser has 2 NEWLINEs right before the end.
+ # tokenize has 0 or 1 depending on if the file has one.
+ # Create extra nodes without consuming tokens to account for this.
+ if node_type == token.NEWLINE:
+ for tok in tokens:
+ if tok.type == token.ENDMARKER:
+ return TokenSnippet(node_type, grabbed_tokens)
+ if tok.type != token.DEDENT:
+ break
+
+ assert tokens[0].type == token.OP or node_type == tokens[0].type
+
+ grabbed_tokens.append(tokens.popleft())
+ return TokenSnippet(node_type, grabbed_tokens)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/__init__.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/__init__.py
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py b/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py
new file mode 100644
index 00000000000..6d0a7cb813e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/refactor_util/move.py
@@ -0,0 +1,118 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import functools
+import os
+import sys
+
+from py_utils import refactor
+
+
+def Run(sources, target, files_to_update):
+ """Move modules and update imports.
+
+ Args:
+ sources: List of source module or package paths.
+ target: Destination module or package path.
+ files_to_update: Modules whose imports we should check for changes.
+ """
+ # TODO(dtu): Support moving classes and functions.
+ moves = tuple(_Move(source, target) for source in sources)
+
+ # Update imports and references.
+ refactor.Transform(functools.partial(_Update, moves), files_to_update)
+
+ # Move files.
+ for move in moves:
+ os.rename(move.source_path, move.target_path)
+
+
+def _Update(moves, module):
+ for import_statement in module.FindAll(refactor.Import):
+ for move in moves:
+ try:
+ if move.UpdateImportAndReferences(module, import_statement):
+ break
+ except NotImplementedError as e:
+ print('Error updating %s: %s' % (module.file_path, e), file=sys.stderr)
+
+
+class _Move(object):
+
+ def __init__(self, source, target):
+ self._source_path = os.path.realpath(source)
+ self._target_path = os.path.realpath(target)
+
+ if os.path.isdir(self._target_path):
+ self._target_path = os.path.join(
+ self._target_path, os.path.basename(self._source_path))
+
+ @property
+ def source_path(self):
+ return self._source_path
+
+ @property
+ def target_path(self):
+ return self._target_path
+
+ @property
+ def source_module_path(self):
+ return _ModulePath(self._source_path)
+
+ @property
+ def target_module_path(self):
+ return _ModulePath(self._target_path)
+
+ def UpdateImportAndReferences(self, module, import_statement):
+ """Update an import statement in a module and all its references..
+
+ Args:
+ module: The refactor.Module to update.
+ import_statement: The refactor.Import to update.
+
+ Returns:
+ True if the import statement was updated, or False if the import statement
+ needed no updating.
+ """
+ statement_path_parts = import_statement.path.split('.')
+ source_path_parts = self.source_module_path.split('.')
+ if source_path_parts != statement_path_parts[:len(source_path_parts)]:
+ return False
+
+ # Update import statement.
+ old_name_parts = import_statement.name.split('.')
+ new_name_parts = ([self.target_module_path] +
+ statement_path_parts[len(source_path_parts):])
+ import_statement.path = '.'.join(new_name_parts)
+ new_name = import_statement.name
+
+ # Update references.
+ for reference in module.FindAll(refactor.Reference):
+ reference_parts = reference.value.split('.')
+ if old_name_parts != reference_parts[:len(old_name_parts)]:
+ continue
+
+ new_reference_parts = [new_name] + reference_parts[len(old_name_parts):]
+ reference.value = '.'.join(new_reference_parts)
+
+ return True
+
+
+def _BaseDir(module_path):
+ if not os.path.isdir(module_path):
+ module_path = os.path.dirname(module_path)
+
+ while '__init__.py' in os.listdir(module_path):
+ module_path = os.path.dirname(module_path)
+
+ return module_path
+
+
+def _ModulePath(module_path):
+ if os.path.split(module_path)[1] == '__init__.py':
+ module_path = os.path.dirname(module_path)
+ rel_path = os.path.relpath(module_path, _BaseDir(module_path))
+ return os.path.splitext(rel_path)[0].replace(os.sep, '.')
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/retry_util.py b/chromium/third_party/catapult/common/py_utils/py_utils/retry_util.py
new file mode 100644
index 00000000000..e5826cabe61
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/retry_util.py
@@ -0,0 +1,57 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import functools
+import logging
+import time
+
+
+def RetryOnException(exc_type, retries):
+ """Decorator to retry running a function if an exception is raised.
+
+ Implements exponential backoff to wait between each retry attempt, starting
+ with 1 second.
+
+ Note: the default number of retries is defined on the decorator, the decorated
+ function *must* also receive a "retries" argument (although its assigned
+ default value is ignored), and clients of the funtion may override the actual
+ number of retries at the call site.
+
+ The "unused" retries argument on the decorated function must be given to
+ keep pylint happy and to avoid breaking the Principle of Least Astonishment
+ if the decorator were to change the signature of the function.
+
+ For example:
+
+ @retry_util.RetryOnException(OSError, retries=3) # default no. of retries
+ def ProcessSomething(thing, retries=None): # this default value is ignored
+ del retries # Unused. Handled by the decorator.
+ # Do your thing processing here, maybe sometimes raising exeptions.
+
+ ProcessSomething(a_thing) # retries 3 times.
+ ProcessSomething(b_thing, retries=5) # retries 5 times.
+
+ Args:
+ exc_type: An exception type (or a tuple of them), on which to retry.
+ retries: Default number of extra attempts to try, the caller may also
+ override this number. If an exception is raised during the last try,
+ then the exception is not caught and passed back to the caller.
+ """
+ def Decorator(f):
+ @functools.wraps(f)
+ def Wrapper(*args, **kwargs):
+ wait = 1
+ kwargs.setdefault('retries', retries)
+ for _ in xrange(kwargs['retries']):
+ try:
+ return f(*args, **kwargs)
+ except exc_type as exc:
+ logging.warning(
+ '%s raised %s, will retry in %d second%s ...',
+ f.__name__, type(exc).__name__, wait, '' if wait == 1 else 's')
+ time.sleep(wait)
+ wait *= 2
+ # Last try with no exception catching.
+ return f(*args, **kwargs)
+ return Wrapper
+ return Decorator
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/retry_util_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/retry_util_unittest.py
new file mode 100644
index 00000000000..f24577f0ea6
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/retry_util_unittest.py
@@ -0,0 +1,119 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+import mock
+
+from py_utils import retry_util
+
+
+class RetryOnExceptionTest(unittest.TestCase):
+ def setUp(self):
+ self.num_calls = 0
+ # Patch time.sleep to make tests run faster (skip waits) and also check
+ # that exponential backoff is implemented correctly.
+ patcher = mock.patch('time.sleep')
+ self.time_sleep = patcher.start()
+ self.addCleanup(patcher.stop)
+
+ def testNoExceptionsReturnImmediately(self):
+ @retry_util.RetryOnException(Exception, retries=3)
+ def Test(retries=None):
+ del retries
+ self.num_calls += 1
+ return 'OK!'
+
+ # The function is called once and returns the expected value.
+ self.assertEqual(Test(), 'OK!')
+ self.assertEqual(self.num_calls, 1)
+
+ def testRaisesExceptionIfAlwaysFailing(self):
+ @retry_util.RetryOnException(KeyError, retries=5)
+ def Test(retries=None):
+ del retries
+ self.num_calls += 1
+ raise KeyError('oops!')
+
+ # The exception is eventually raised.
+ with self.assertRaises(KeyError):
+ Test()
+ # The function is called the expected number of times.
+ self.assertEqual(self.num_calls, 6)
+ # Waits between retries do follow exponential backoff.
+ self.assertEqual(
+ self.time_sleep.call_args_list,
+ [mock.call(i) for i in (1, 2, 4, 8, 16)])
+
+ def testOtherExceptionsAreNotCaught(self):
+ @retry_util.RetryOnException(KeyError, retries=3)
+ def Test(retries=None):
+ del retries
+ self.num_calls += 1
+ raise ValueError('oops!')
+
+ # The exception is raised immediately on the first try.
+ with self.assertRaises(ValueError):
+ Test()
+ self.assertEqual(self.num_calls, 1)
+
+ def testCallerMayOverrideRetries(self):
+ @retry_util.RetryOnException(KeyError, retries=3)
+ def Test(retries=None):
+ del retries
+ self.num_calls += 1
+ raise KeyError('oops!')
+
+ with self.assertRaises(KeyError):
+ Test(retries=10)
+ # The value on the caller overrides the default on the decorator.
+ self.assertEqual(self.num_calls, 11)
+
+ def testCanEventuallySucceed(self):
+ @retry_util.RetryOnException(KeyError, retries=5)
+ def Test(retries=None):
+ del retries
+ self.num_calls += 1
+ if self.num_calls < 3:
+ raise KeyError('oops!')
+ else:
+ return 'OK!'
+
+ # The value is returned after the expected number of calls.
+ self.assertEqual(Test(), 'OK!')
+ self.assertEqual(self.num_calls, 3)
+
+ def testRetriesCanBeSwitchedOff(self):
+ @retry_util.RetryOnException(KeyError, retries=5)
+ def Test(retries=None):
+ del retries
+ self.num_calls += 1
+ if self.num_calls < 3:
+ raise KeyError('oops!')
+ else:
+ return 'OK!'
+
+ # We fail immediately on the first try.
+ with self.assertRaises(KeyError):
+ Test(retries=0)
+ self.assertEqual(self.num_calls, 1)
+
+ def testCanRetryOnMultipleExceptions(self):
+ @retry_util.RetryOnException((KeyError, ValueError), retries=3)
+ def Test(retries=None):
+ del retries
+ self.num_calls += 1
+ if self.num_calls == 1:
+ raise KeyError('oops!')
+ elif self.num_calls == 2:
+ raise ValueError('uh oh!')
+ else:
+ return 'OK!'
+
+ # Call eventually succeeds after enough tries.
+ self.assertEqual(Test(retries=5), 'OK!')
+ self.assertEqual(self.num_calls, 3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/shell_util.py b/chromium/third_party/catapult/common/py_utils/py_utils/shell_util.py
new file mode 100644
index 00000000000..6af7f8e2827
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/shell_util.py
@@ -0,0 +1,42 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Shell scripting helpers (created for Telemetry dependency roll scripts).
+
+from __future__ import print_function
+
+import os as _os
+import shutil as _shutil
+import subprocess as _subprocess
+import tempfile as _tempfile
+from contextlib import contextmanager as _contextmanager
+
+@_contextmanager
+def ScopedChangeDir(new_path):
+ old_path = _os.getcwd()
+ _os.chdir(new_path)
+ print('> cd', _os.getcwd())
+ try:
+ yield
+ finally:
+ _os.chdir(old_path)
+ print('> cd', old_path)
+
+@_contextmanager
+def ScopedTempDir():
+ temp_dir = _tempfile.mkdtemp()
+ try:
+ with ScopedChangeDir(temp_dir):
+ yield
+ finally:
+ _shutil.rmtree(temp_dir)
+
+def CallProgram(path_parts, *args, **kwargs):
+ '''Call an executable os.path.join(*path_parts) with the arguments specified
+ by *args. Any keyword arguments are passed as environment variables.'''
+ args = [_os.path.join(*path_parts)] + list(args)
+ env = dict(_os.environ)
+ env.update(kwargs)
+ print('>', ' '.join(args))
+ _subprocess.check_call(args, env=env)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/slots_metaclass.py b/chromium/third_party/catapult/common/py_utils/py_utils/slots_metaclass.py
new file mode 100644
index 00000000000..ae36c6778d9
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/slots_metaclass.py
@@ -0,0 +1,27 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class SlotsMetaclass(type):
+ """This metaclass requires all subclasses to define __slots__.
+
+ Usage:
+ class Foo(object):
+ __metaclass__ = slots_metaclass.SlotsMetaclass
+ __slots__ = '_property0', '_property1',
+
+ __slots__ must be a tuple containing string names of all properties that the
+ class contains.
+ Defining __slots__ reduces memory usage, accelerates property access, and
+ prevents dynamically adding unlisted properties.
+ If you need to dynamically add unlisted properties to a class with this
+ metaclass, then take a step back and rethink your goals. If you really really
+ need to dynamically add unlisted properties to a class with this metaclass,
+ add '__dict__' to its __slots__.
+ """
+
+ def __new__(mcs, name, bases, attrs):
+ assert '__slots__' in attrs, 'Class "%s" must define __slots__' % name
+ assert isinstance(attrs['__slots__'], tuple), '__slots__ must be a tuple'
+
+ return super(SlotsMetaclass, mcs).__new__(mcs, name, bases, attrs)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/slots_metaclass_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/slots_metaclass_unittest.py
new file mode 100644
index 00000000000..79bb343d771
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/slots_metaclass_unittest.py
@@ -0,0 +1,41 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from py_utils import slots_metaclass
+
+class SlotsMetaclassUnittest(unittest.TestCase):
+
+ def testSlotsMetaclass(self):
+ class NiceClass(object):
+ __metaclass__ = slots_metaclass.SlotsMetaclass
+ __slots__ = '_nice',
+
+ def __init__(self, nice):
+ self._nice = nice
+
+ NiceClass(42)
+
+ with self.assertRaises(AssertionError):
+ class NaughtyClass(NiceClass):
+ def __init__(self, naughty):
+ super(NaughtyClass, self).__init__(42)
+ self._naughty = naughty
+
+ # Metaclasses are called when the class is defined, so no need to
+ # instantiate it.
+
+ with self.assertRaises(AttributeError):
+ class NaughtyClass2(NiceClass):
+ __slots__ = ()
+
+ def __init__(self, naughty):
+ super(NaughtyClass2, self).__init__(42)
+ self._naughty = naughty # pylint: disable=assigning-non-slot
+
+ # SlotsMetaclass is happy that __slots__ is defined, but python won't be
+ # happy about assigning _naughty when the class is instantiated because it
+ # isn't listed in __slots__, even if you disable the pylint error.
+ NaughtyClass2(666)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/tempfile_ext.py b/chromium/third_party/catapult/common/py_utils/py_utils/tempfile_ext.py
new file mode 100644
index 00000000000..394ad5b7f06
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/tempfile_ext.py
@@ -0,0 +1,30 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import contextlib
+import shutil
+import tempfile
+
+
+@contextlib.contextmanager
+def NamedTemporaryDirectory(suffix='', prefix='tmp', dir=None):
+ """A context manager that manages a temporary directory.
+
+ This is a context manager version of tempfile.mkdtemp. The arguments to this
+ function are the same as the arguments for that one.
+
+ This can be used to automatically manage the lifetime of a temporary file
+ without maintaining an open file handle on it. Doing so can be useful in
+ scenarios where a parent process calls a child process to create a temporary
+ file and then does something with the resulting file.
+ """
+ # This uses |dir| as a parameter name for consistency with mkdtemp.
+ # pylint: disable=redefined-builtin
+
+ d = tempfile.mkdtemp(suffix=suffix, prefix=prefix, dir=dir)
+ try:
+ yield d
+ finally:
+ shutil.rmtree(d)
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/tempfile_ext_unittest.py b/chromium/third_party/catapult/common/py_utils/py_utils/tempfile_ext_unittest.py
new file mode 100644
index 00000000000..684462354ba
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/tempfile_ext_unittest.py
@@ -0,0 +1,39 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+from py_utils import tempfile_ext
+from pyfakefs import fake_filesystem_unittest
+
+
+class NamedTemporaryDirectoryTest(fake_filesystem_unittest.TestCase):
+
+ def setUp(self):
+ self.setUpPyfakefs()
+
+ def tearDown(self):
+ self.tearDownPyfakefs()
+
+ def testBasic(self):
+ with tempfile_ext.NamedTemporaryDirectory() as d:
+ self.assertTrue(os.path.exists(d))
+ self.assertTrue(os.path.isdir(d))
+ self.assertFalse(os.path.exists(d))
+
+ def testSuffix(self):
+ test_suffix = 'foo'
+ with tempfile_ext.NamedTemporaryDirectory(suffix=test_suffix) as d:
+ self.assertTrue(os.path.basename(d).endswith(test_suffix))
+
+ def testPrefix(self):
+ test_prefix = 'bar'
+ with tempfile_ext.NamedTemporaryDirectory(prefix=test_prefix) as d:
+ self.assertTrue(os.path.basename(d).startswith(test_prefix))
+
+ def testDir(self):
+ test_dir = '/baz'
+ self.fs.CreateDirectory(test_dir)
+ with tempfile_ext.NamedTemporaryDirectory(dir=test_dir) as d:
+ self.assertEquals(test_dir, os.path.dirname(d))
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/__init__.py b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/__init__.py
new file mode 100644
index 00000000000..9228df89b0e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/another_discover_dummyclass.py b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/another_discover_dummyclass.py
new file mode 100644
index 00000000000..0459ccf7148
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/another_discover_dummyclass.py
@@ -0,0 +1,33 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""More dummy exception subclasses used by core/discover.py's unit tests."""
+
+# Import class instead of module explicitly so that inspect.getmembers() returns
+# two Exception subclasses in this current file.
+# Suppress complaints about unable to import class. The directory path is
+# added at runtime by telemetry test runner.
+#pylint: disable=import-error
+from discoverable_classes import discover_dummyclass
+
+
+class _PrivateDummyException(discover_dummyclass.DummyException):
+ def __init__(self):
+ super(_PrivateDummyException, self).__init__()
+
+
+class DummyExceptionImpl1(_PrivateDummyException):
+ def __init__(self):
+ super(DummyExceptionImpl1, self).__init__()
+
+
+class DummyExceptionImpl2(_PrivateDummyException):
+ def __init__(self):
+ super(DummyExceptionImpl2, self).__init__()
+
+
+class DummyExceptionWithParameterImpl1(_PrivateDummyException):
+ def __init__(self, parameter):
+ super(DummyExceptionWithParameterImpl1, self).__init__()
+ del parameter
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/discover_dummyclass.py b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/discover_dummyclass.py
new file mode 100644
index 00000000000..15dcb35a4d5
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/discover_dummyclass.py
@@ -0,0 +1,9 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A dummy exception subclass used by core/discover.py's unit tests."""
+
+class DummyException(Exception):
+ def __init__(self):
+ super(DummyException, self).__init__()
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/parameter_discover_dummyclass.py b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/parameter_discover_dummyclass.py
new file mode 100644
index 00000000000..c37f4a99765
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/discoverable_classes/parameter_discover_dummyclass.py
@@ -0,0 +1,11 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A dummy exception subclass used by core/discover.py's unit tests."""
+from discoverable_classes import discover_dummyclass
+
+class DummyExceptionWithParameterImpl2(discover_dummyclass.DummyException):
+ def __init__(self, parameter1, parameter2):
+ super(DummyExceptionWithParameterImpl2, self).__init__()
+ del parameter1, parameter2
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/test_data/foo.txt b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/foo.txt
new file mode 100644
index 00000000000..a9cac3ec4e0
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/test_data/foo.txt
@@ -0,0 +1 @@
+This file is not executable.
diff --git a/chromium/third_party/catapult/common/py_utils/py_utils/xvfb.py b/chromium/third_party/catapult/common/py_utils/py_utils/xvfb.py
new file mode 100644
index 00000000000..c09f3e333ab
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_utils/py_utils/xvfb.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import logging
+import subprocess
+import platform
+import time
+
+
+def ShouldStartXvfb():
+ return platform.system() == 'Linux'
+
+
+def StartXvfb():
+ display = ':99'
+ xvfb_command = ['Xvfb', display, '-screen', '0', '1024x769x24', '-ac']
+ xvfb_process = subprocess.Popen(
+ xvfb_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ time.sleep(0.2)
+ returncode = xvfb_process.poll()
+ if returncode is None:
+ os.environ['DISPLAY'] = display
+ else:
+ logging.error('Xvfb did not start, returncode: %s, stdout:\n%s',
+ returncode, xvfb_process.stdout.read())
+ xvfb_process = None
+ return xvfb_process
diff --git a/chromium/third_party/catapult/common/py_vulcanize/README.chromium b/chromium/third_party/catapult/common/py_vulcanize/README.chromium
new file mode 100644
index 00000000000..0b32761b781
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/README.chromium
@@ -0,0 +1,8 @@
+Name: py_vulcanize
+URL: N/A
+Version: N/A
+
+Description:
+Py-vulcanize, formerly known as TVCM (trace-viewer component model).
+This code doesn't actually live anywhere else currently, but it may
+be split out into a separate repository in the future.
diff --git a/chromium/third_party/catapult/common/py_vulcanize/bin/run_py_tests b/chromium/third_party/catapult/common/py_vulcanize/bin/run_py_tests
new file mode 100755
index 00000000000..904c2138b5f
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/bin/run_py_tests
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+_CATAPULT = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), os.path.pardir, os.path.pardir, os.path.pardir))
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+if __name__ == '__main__':
+ _AddToPathIfNeeded(_CATAPULT)
+
+ from hooks import install
+ if '--no-install-hooks' in sys.argv:
+ sys.argv.remove('--no-install-hooks')
+ else:
+ install.InstallHooks()
+
+ from catapult_build import run_with_typ
+ sys.exit(run_with_typ.Run(
+ os.path.join(_CATAPULT, 'common', 'py_vulcanize')))
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/__init__.py
new file mode 100644
index 00000000000..f3a4bd1bb15
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Trace-viewer component model.
+
+This module implements trace-viewer's component model.
+"""
+
+from py_vulcanize.generate import * # pylint: disable=wildcard-import
+from py_vulcanize.project import Project
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/fake_fs.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/fake_fs.py
new file mode 100644
index 00000000000..dfcb5e60bf4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/fake_fs.py
@@ -0,0 +1,146 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import codecs
+import os
+import sys
+import collections
+import StringIO
+
+
+class WithableStringIO(StringIO.StringIO):
+
+ def __enter__(self, *args):
+ return self
+
+ def __exit__(self, *args):
+ pass
+
+
+class FakeFS(object):
+
+ def __init__(self, initial_filenames_and_contents=None):
+ self._file_contents = {}
+ if initial_filenames_and_contents:
+ for k, v in initial_filenames_and_contents.iteritems():
+ self._file_contents[k] = v
+
+ self._bound = False
+ self._real_codecs_open = codecs.open
+ self._real_open = sys.modules['__builtin__'].open
+ self._real_abspath = os.path.abspath
+ self._real_exists = os.path.exists
+ self._real_walk = os.walk
+ self._real_listdir = os.listdir
+
+ def __enter__(self):
+ self.Bind()
+ return self
+
+ def __exit__(self, *args):
+ self.Unbind()
+
+ def Bind(self):
+ assert not self._bound
+ codecs.open = self._FakeCodecsOpen
+ sys.modules['__builtin__'].open = self._FakeOpen
+ os.path.abspath = self._FakeAbspath
+ os.path.exists = self._FakeExists
+ os.walk = self._FakeWalk
+ os.listdir = self._FakeListDir
+ self._bound = True
+
+ def Unbind(self):
+ assert self._bound
+ codecs.open = self._real_codecs_open
+ sys.modules['__builtin__'].open = self._real_open
+ os.path.abspath = self._real_abspath
+ os.path.exists = self._real_exists
+ os.walk = self._real_walk
+ os.listdir = self._real_listdir
+ self._bound = False
+
+ def AddFile(self, path, contents):
+ assert path not in self._file_contents
+ path = os.path.normpath(path)
+ self._file_contents[path] = contents
+
+ def _FakeOpen(self, path, mode=None):
+ if mode is None:
+ mode = 'r'
+ if mode == 'r' or mode == 'rU' or mode == 'rb':
+ if path not in self._file_contents:
+ return self._real_open(path, mode)
+ return WithableStringIO(self._file_contents[path])
+
+ raise NotImplementedError()
+
+ def _FakeCodecsOpen(self, path, mode=None,
+ encoding=None): # pylint: disable=unused-argument
+ if mode is None:
+ mode = 'r'
+ if mode == 'r' or mode == 'rU' or mode == 'rb':
+ if path not in self._file_contents:
+ return self._real_open(path, mode)
+ return WithableStringIO(self._file_contents[path])
+
+ raise NotImplementedError()
+
+ def _FakeAbspath(self, path):
+ """Normalize the path and ensure it starts with os.path.sep.
+
+ The tests all assume paths start with things like '/my/project',
+ and this abspath implementaion makes that assumption work correctly
+ on Windows.
+ """
+ normpath = os.path.normpath(path)
+ if not normpath.startswith(os.path.sep):
+ normpath = os.path.sep + normpath
+ return normpath
+
+ def _FakeExists(self, path):
+ if path in self._file_contents:
+ return True
+ return self._real_exists(path)
+
+ def _FakeWalk(self, top):
+ assert os.path.isabs(top)
+ all_filenames = self._file_contents.keys()
+ pending_prefixes = collections.deque()
+ pending_prefixes.append(top)
+ visited_prefixes = set()
+ while len(pending_prefixes):
+ prefix = pending_prefixes.popleft()
+ if prefix in visited_prefixes:
+ continue
+ visited_prefixes.add(prefix)
+ if prefix.endswith(os.path.sep):
+ prefix_with_trailing_sep = prefix
+ else:
+ prefix_with_trailing_sep = prefix + os.path.sep
+
+ dirs = set()
+ files = []
+ for filename in all_filenames:
+ if not filename.startswith(prefix_with_trailing_sep):
+ continue
+ relative_to_prefix = os.path.relpath(filename, prefix)
+
+ dirpart = os.path.dirname(relative_to_prefix)
+ if len(dirpart) == 0:
+ files.append(relative_to_prefix)
+ continue
+ parts = dirpart.split(os.sep)
+ if len(parts) == 0:
+ dirs.add(dirpart)
+ else:
+ pending = os.path.join(prefix, parts[0])
+ dirs.add(parts[0])
+ pending_prefixes.appendleft(pending)
+
+ dirs = sorted(dirs)
+ yield prefix, dirs, files
+
+ def _FakeListDir(self, dirname):
+ raise NotImplementedError()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/fake_fs_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/fake_fs_unittest.py
new file mode 100644
index 00000000000..08250138a5e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/fake_fs_unittest.py
@@ -0,0 +1,52 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import unittest
+
+from py_vulcanize import fake_fs
+
+
+class FakeFSUnittest(unittest.TestCase):
+
+ def testBasic(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/blah/x', 'foobar')
+ with fs:
+ assert os.path.exists(os.path.normpath('/blah/x'))
+ self.assertEquals(
+ 'foobar',
+ open(os.path.normpath('/blah/x'), 'r').read())
+
+ def testWithableOpen(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/blah/x', 'foobar')
+ with fs:
+ with open(os.path.normpath('/blah/x'), 'r') as f:
+ self.assertEquals('foobar', f.read())
+
+ def testWalk(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/x/w2/w3/z3.txt', '')
+ fs.AddFile('/x/w/z.txt', '')
+ fs.AddFile('/x/y.txt', '')
+ fs.AddFile('/a.txt', 'foobar')
+ with fs:
+ gen = os.walk(os.path.normpath('/'))
+ r = gen.next()
+ self.assertEquals((os.path.normpath('/'), ['x'], ['a.txt']), r)
+
+ r = gen.next()
+ self.assertEquals((os.path.normpath('/x'), ['w', 'w2'], ['y.txt']), r)
+
+ r = gen.next()
+ self.assertEquals((os.path.normpath('/x/w'), [], ['z.txt']), r)
+
+ r = gen.next()
+ self.assertEquals((os.path.normpath('/x/w2'), ['w3'], []), r)
+
+ r = gen.next()
+ self.assertEquals((os.path.normpath('/x/w2/w3'), [], ['z3.txt']), r)
+
+ self.assertRaises(StopIteration, gen.next)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/generate.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/generate.py
new file mode 100644
index 00000000000..f6accb4b328
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/generate.py
@@ -0,0 +1,274 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import subprocess
+import tempfile
+
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+from py_vulcanize import html_generation_controller
+
+
+html_warning_message = """
+
+
+<!--
+WARNING: This file is auto generated.
+
+ Do not edit directly.
+-->
+"""
+
+js_warning_message = """
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/* WARNING: This file is auto generated.
+ *
+ * Do not edit directly.
+ */
+"""
+
+css_warning_message = """
+/* Copyright 2015 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/* WARNING: This file is auto-generated.
+ *
+ * Do not edit directly.
+ */
+"""
+
+
+def _AssertIsUTF8(f):
+ if isinstance(f, StringIO):
+ return
+ assert f.encoding == 'utf-8'
+
+
+def _MinifyJS(input_js):
+ py_vulcanize_path = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '..'))
+ rjsmin_path = os.path.abspath(
+ os.path.join(py_vulcanize_path, 'third_party', 'rjsmin', 'rjsmin.py'))
+
+ with tempfile.NamedTemporaryFile() as _:
+ args = [
+ 'python',
+ rjsmin_path
+ ]
+ p = subprocess.Popen(args,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ res = p.communicate(input=input_js)
+ errorcode = p.wait()
+ if errorcode != 0:
+ sys.stderr.write('rJSmin exited with error code %d' % errorcode)
+ sys.stderr.write(res[1])
+ raise Exception('Failed to minify, omgah')
+ return res[0]
+
+
+def GenerateJS(load_sequence,
+ use_include_tags_for_scripts=False,
+ dir_for_include_tag_root=None,
+ minify=False,
+ report_sizes=False):
+ f = StringIO()
+ GenerateJSToFile(f,
+ load_sequence,
+ use_include_tags_for_scripts,
+ dir_for_include_tag_root,
+ minify=minify,
+ report_sizes=report_sizes)
+
+ return f.getvalue()
+
+
+def GenerateJSToFile(f,
+ load_sequence,
+ use_include_tags_for_scripts=False,
+ dir_for_include_tag_root=None,
+ minify=False,
+ report_sizes=False):
+ _AssertIsUTF8(f)
+ if use_include_tags_for_scripts and dir_for_include_tag_root is None:
+ raise Exception('Must provide dir_for_include_tag_root')
+
+ f.write(js_warning_message)
+ f.write('\n')
+
+ if not minify:
+ flatten_to_file = f
+ else:
+ flatten_to_file = StringIO()
+
+ for module in load_sequence:
+ module.AppendJSContentsToFile(flatten_to_file,
+ use_include_tags_for_scripts,
+ dir_for_include_tag_root)
+ if minify:
+ js = flatten_to_file.getvalue()
+ minified_js = _MinifyJS(js)
+ f.write(minified_js)
+ f.write('\n')
+
+ if report_sizes:
+ for module in load_sequence:
+ s = StringIO()
+ module.AppendJSContentsToFile(s,
+ use_include_tags_for_scripts,
+ dir_for_include_tag_root)
+
+ # Add minified size info.
+ js = s.getvalue()
+ min_js_size = str(len(_MinifyJS(js)))
+
+ # Print names for this module. Some domain-specific simplifications
+ # are included to make pivoting more obvious.
+ parts = module.name.split('.')
+ if parts[:2] == ['base', 'ui']:
+ parts = ['base_ui'] + parts[2:]
+ if parts[:2] == ['tracing', 'importer']:
+ parts = ['importer'] + parts[2:]
+ tln = parts[0]
+ sln = '.'.join(parts[:2])
+
+ # Output
+ print('%i\t%s\t%s\t%s\t%s' % (
+ len(js), min_js_size, module.name, tln, sln))
+ sys.stdout.flush()
+
+
+class ExtraScript(object):
+
+ def __init__(self, script_id=None, text_content=None, content_type=None):
+ if script_id is not None:
+ assert script_id[0] != '#'
+ self.script_id = script_id
+ self.text_content = text_content
+ self.content_type = content_type
+
+ def WriteToFile(self, output_file):
+ _AssertIsUTF8(output_file)
+ attrs = []
+ if self.script_id:
+ attrs.append('id="%s"' % self.script_id)
+ if self.content_type:
+ attrs.append('content-type="%s"' % self.content_type)
+
+ if len(attrs) > 0:
+ output_file.write('<script %s>\n' % ' '.join(attrs))
+ else:
+ output_file.write('<script>\n')
+ if self.text_content:
+ output_file.write(self.text_content)
+ output_file.write('</script>\n')
+
+
+def _MinifyCSS(css_text):
+ py_vulcanize_path = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '..'))
+ rcssmin_path = os.path.abspath(
+ os.path.join(py_vulcanize_path, 'third_party', 'rcssmin', 'rcssmin.py'))
+
+ with tempfile.NamedTemporaryFile() as _:
+ rcssmin_args = ['python', rcssmin_path]
+ p = subprocess.Popen(rcssmin_args,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ res = p.communicate(input=css_text)
+ errorcode = p.wait()
+ if errorcode != 0:
+ sys.stderr.write('rCSSmin exited with error code %d' % errorcode)
+ sys.stderr.write(res[1])
+ raise Exception('Failed to generate css for %s.' % css_text)
+ return res[0]
+
+
+def GenerateStandaloneHTMLAsString(*args, **kwargs):
+ f = StringIO()
+ GenerateStandaloneHTMLToFile(f, *args, **kwargs)
+ return f.getvalue()
+
+
+def GenerateStandaloneHTMLToFile(output_file,
+ load_sequence,
+ title=None,
+ flattened_js_url=None,
+ extra_scripts=None,
+ minify=False,
+ report_sizes=False,
+ output_html_head_and_body=True):
+ """Writes a HTML file with the content of all modules in a load sequence.
+
+ The load_sequence is a list of (HTML or JS) Module objects; the order that
+ they're inserted into the file depends on their type and position in the load
+ sequence.
+ """
+ _AssertIsUTF8(output_file)
+ extra_scripts = extra_scripts or []
+
+ if output_html_head_and_body:
+ output_file.write(
+ '<!DOCTYPE html>\n'
+ '<html>\n'
+ ' <head i18n-values="dir:textdirection;">\n'
+ ' <meta http-equiv="Content-Type" content="text/html;'
+ 'charset=utf-8">\n')
+ if title:
+ output_file.write(' <title>%s</title>\n ' % title)
+ else:
+ assert title is None
+
+ loader = load_sequence[0].loader
+
+ written_style_sheets = set()
+
+ class HTMLGenerationController(
+ html_generation_controller.HTMLGenerationController):
+
+ def __init__(self, module):
+ self.module = module
+
+ def GetHTMLForStylesheetHRef(self, href):
+ resource = self.module.HRefToResource(
+ href, '<link rel="stylesheet" href="%s">' % href)
+ style_sheet = loader.LoadStyleSheet(resource.name)
+
+ if style_sheet in written_style_sheets:
+ return None
+ written_style_sheets.add(style_sheet)
+
+ text = style_sheet.contents_with_inlined_images
+ if minify:
+ text = _MinifyCSS(text)
+ return '<style>\n%s\n</style>' % text
+
+ for module in load_sequence:
+ controller = HTMLGenerationController(module)
+ module.AppendHTMLContentsToFile(output_file, controller, minify=minify)
+
+ if flattened_js_url:
+ output_file.write('<script src="%s"></script>\n' % flattened_js_url)
+ else:
+ output_file.write('<script>\n')
+ js = GenerateJS(load_sequence, minify=minify, report_sizes=report_sizes)
+ output_file.write(js)
+ output_file.write('</script>\n')
+
+ for extra_script in extra_scripts:
+ extra_script.WriteToFile(output_file)
+
+ if output_html_head_and_body:
+ output_file.write('</head>\n <body>\n </body>\n</html>\n')
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/generate_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/generate_unittest.py
new file mode 100644
index 00000000000..1e83cb48c21
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/generate_unittest.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import unittest
+
+from py_vulcanize import generate
+from py_vulcanize import fake_fs
+from py_vulcanize import project as project_module
+
+
+class GenerateTests(unittest.TestCase):
+
+ def setUp(self):
+ self.fs = fake_fs.FakeFS()
+ self.fs.AddFile(
+ '/x/foo/my_module.html',
+ ('<!DOCTYPE html>\n'
+ '<link rel="import" href="/foo/other_module.html">\n'))
+ self.fs.AddFile(
+ '/x/foo/other_module.html',
+ ('<!DOCTYPE html>\n'
+ '<script src="/foo/raw/raw_script.js"></script>\n'
+ '<script>\n'
+ ' \'use strict\';\n'
+ ' HelloWorld();\n'
+ '</script>\n'))
+ self.fs.AddFile('/x/foo/raw/raw_script.js', '\n/* raw script */\n')
+ self.fs.AddFile('/x/components/polymer/polymer.min.js', '\n')
+
+ self.fs.AddFile('/x/foo/external_script.js', 'External()')
+ self.fs.AddFile('/x/foo/inline_and_external_module.html',
+ ('<!DOCTYPE html>\n'
+ '<script>Script1()</script>'
+ '<script src=/foo/external_script.js></script>'
+ '<script>Script2()</script>'))
+
+ self.project = project_module.Project([os.path.normpath('/x')])
+
+ def testJSGeneration(self):
+ with self.fs:
+ load_sequence = self.project.CalcLoadSequenceForModuleNames(
+ [os.path.normpath('foo.my_module')])
+ generate.GenerateJS(load_sequence)
+
+ def testHTMLGeneration(self):
+ with self.fs:
+ load_sequence = self.project.CalcLoadSequenceForModuleNames(
+ [os.path.normpath('foo.my_module')])
+ result = generate.GenerateStandaloneHTMLAsString(load_sequence)
+ self.assertIn('HelloWorld();', result)
+
+ def testExtraScriptWithWriteContentsFunc(self):
+ with self.fs:
+ load_sequence = self.project.CalcLoadSequenceForModuleNames(
+ [os.path.normpath('foo.my_module')])
+
+ class ExtraScript(generate.ExtraScript):
+
+ def WriteToFile(self, f):
+ f.write('<script>ExtraScript!</script>')
+
+ result = generate.GenerateStandaloneHTMLAsString(
+ load_sequence, title='Title', extra_scripts=[ExtraScript()])
+ self.assertIn('ExtraScript', result)
+
+ def testScriptOrdering(self):
+ with self.fs:
+ load_sequence = self.project.CalcLoadSequenceForModuleNames(
+ [os.path.normpath('foo.inline_and_external_module')])
+ result = generate.GenerateStandaloneHTMLAsString(load_sequence)
+ script1_pos = result.index('Script1()')
+ script2_pos = result.index('Script2()')
+ external_pos = result.index('External()')
+ self.assertTrue(script1_pos < external_pos < script2_pos)
+
+ def testScriptOrderingWithIncludeTag(self):
+ with self.fs:
+ load_sequence = self.project.CalcLoadSequenceForModuleNames(
+ [os.path.normpath('foo.inline_and_external_module')])
+ result = generate.GenerateJS(load_sequence,
+ use_include_tags_for_scripts = True,
+ dir_for_include_tag_root='/x/')
+ script1_pos = result.index('Script1()')
+ script2_pos = result.index('Script2()')
+ external_path = os.path.join('foo', 'external_script.js')
+ external_pos = result.index('<include src="{0}">'.format(external_path))
+ self.assertTrue(script1_pos < external_pos < script2_pos)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_generation_controller.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_generation_controller.py
new file mode 100644
index 00000000000..c804fe8ca3e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_generation_controller.py
@@ -0,0 +1,28 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import re
+from py_vulcanize import style_sheet
+
+
+class HTMLGenerationController(object):
+
+ def __init__(self):
+ self.current_module = None
+
+ def GetHTMLForStylesheetHRef(self, href): # pylint: disable=unused-argument
+ return None
+
+ def GetHTMLForInlineStylesheet(self, contents):
+ if self.current_module is None:
+ if re.search('url\(.+\)', contents):
+ raise Exception(
+ 'Default HTMLGenerationController cannot handle inline style urls')
+ return contents
+
+ module_dirname = os.path.dirname(self.current_module.resource.absolute_path)
+ ss = style_sheet.ParsedStyleSheet(
+ self.current_module.loader, module_dirname, contents)
+ return ss.contents_with_inlined_images
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_module.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_module.py
new file mode 100644
index 00000000000..5e1c7541c53
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_module.py
@@ -0,0 +1,154 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import re
+
+from py_vulcanize import js_utils
+from py_vulcanize import module
+from py_vulcanize import parse_html_deps
+from py_vulcanize import style_sheet
+
+
+def IsHTMLResourceTheModuleGivenConflictingResourceNames(
+ js_resource, html_resource): # pylint: disable=unused-argument
+ return 'polymer-element' in html_resource.contents
+
+
+class HTMLModule(module.Module):
+
+ @property
+ def _module_dir_name(self):
+ return os.path.dirname(self.resource.absolute_path)
+
+ def Parse(self, excluded_scripts):
+ try:
+ parser_results = parse_html_deps.HTMLModuleParser().Parse(self.contents)
+ except Exception as ex:
+ raise Exception('While parsing %s: %s' % (self.name, str(ex)))
+
+ self.dependency_metadata = Parse(self.loader,
+ self.name,
+ self._module_dir_name,
+ self.IsThirdPartyComponent(),
+ parser_results,
+ excluded_scripts)
+ self._parser_results = parser_results
+ self.scripts = parser_results.scripts
+
+ def Load(self, excluded_scripts):
+ super(HTMLModule, self).Load(excluded_scripts=excluded_scripts)
+
+ reachable_names = set([m.name
+ for m in self.all_dependent_modules_recursive])
+ if 'tr.exportTo' in self.contents:
+ if 'tracing.base.base' not in reachable_names:
+ raise Exception('%s: Does not have a dependency on base' %
+ os.path.relpath(self.resource.absolute_path))
+
+ for script in self.scripts:
+ if script.is_external:
+ if excluded_scripts and any(re.match(pattern, script.src) for
+ pattern in excluded_scripts):
+ continue
+
+ resource = _HRefToResource(self.loader, self.name, self._module_dir_name,
+ script.src,
+ tag_for_err_msg='<script src="%s">' % script.src)
+ path = resource.unix_style_relative_path
+ raw_script = self.loader.LoadRawScript(path)
+ self.dependent_raw_scripts.append(raw_script)
+ script.loaded_raw_script = raw_script
+
+ def GetTVCMDepsModuleType(self):
+ return 'py_vulcanize.HTML_MODULE_TYPE'
+
+ def AppendHTMLContentsToFile(self, f, ctl, minify=False):
+ super(HTMLModule, self).AppendHTMLContentsToFile(f, ctl)
+
+ ctl.current_module = self
+ try:
+ for piece in self._parser_results.YieldHTMLInPieces(ctl, minify=minify):
+ f.write(piece)
+ finally:
+ ctl.current_module = None
+
+ def HRefToResource(self, href, tag_for_err_msg):
+ return _HRefToResource(self.loader, self.name, self._module_dir_name,
+ href, tag_for_err_msg)
+
+ def AppendDirectlyDependentFilenamesTo(
+ self, dependent_filenames, include_raw_scripts=True):
+ super(HTMLModule, self).AppendDirectlyDependentFilenamesTo(
+ dependent_filenames, include_raw_scripts)
+ for contents in self._parser_results.inline_stylesheets:
+ module_dirname = os.path.dirname(self.resource.absolute_path)
+ ss = style_sheet.ParsedStyleSheet(
+ self.loader, module_dirname, contents)
+ ss.AppendDirectlyDependentFilenamesTo(dependent_filenames)
+
+def _HRefToResource(
+ loader, module_name, module_dir_name, href, tag_for_err_msg):
+ if href[0] == '/':
+ resource = loader.FindResourceGivenRelativePath(
+ os.path.normpath(href[1:]))
+ else:
+ abspath = os.path.normpath(os.path.join(module_dir_name,
+ os.path.normpath(href)))
+ resource = loader.FindResourceGivenAbsolutePath(abspath)
+
+ if not resource:
+ raise module.DepsException(
+ 'In %s, the %s cannot be loaded because '
+ 'it is not in the search path' % (module_name, tag_for_err_msg))
+ try:
+ resource.contents
+ except:
+ raise module.DepsException('In %s, %s points at a nonexistent file ' % (
+ module_name, tag_for_err_msg))
+ return resource
+
+
+def Parse(loader, module_name, module_dir_name, is_component, parser_results,
+ exclude_scripts=None):
+ res = module.ModuleDependencyMetadata()
+ if is_component:
+ return res
+
+ # External script references.
+ for href in parser_results.scripts_external:
+ if exclude_scripts and any(re.match(pattern, href) for
+ pattern in exclude_scripts):
+ continue
+
+ resource = _HRefToResource(loader, module_name, module_dir_name,
+ href,
+ tag_for_err_msg='<script src="%s">' % href)
+ res.dependent_raw_script_relative_paths.append(
+ resource.unix_style_relative_path)
+
+ # External imports. Mostly the same as <script>, but we know its a module.
+ for href in parser_results.imports:
+ if exclude_scripts and any(re.match(pattern, href) for
+ pattern in exclude_scripts):
+ continue
+
+ if not href.endswith('.html'):
+ raise Exception(
+ 'In %s, the <link rel="import" href="%s"> must point at a '
+ 'file with an html suffix' % (module_name, href))
+
+ resource = _HRefToResource(
+ loader, module_name, module_dir_name, href,
+ tag_for_err_msg='<link rel="import" href="%s">' % href)
+ res.dependent_module_names.append(resource.name)
+
+ # Style sheets.
+ for href in parser_results.stylesheets:
+ resource = _HRefToResource(
+ loader, module_name, module_dir_name, href,
+ tag_for_err_msg='<link rel="stylesheet" href="%s">' % href)
+ res.style_sheet_names.append(resource.name)
+
+ return res
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py
new file mode 100644
index 00000000000..fb4af16c8d7
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/html_module_unittest.py
@@ -0,0 +1,321 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import unittest
+import StringIO
+
+from py_vulcanize import fake_fs
+from py_vulcanize import generate
+from py_vulcanize import html_generation_controller
+from py_vulcanize import html_module
+from py_vulcanize import parse_html_deps
+from py_vulcanize import project as project_module
+from py_vulcanize import resource
+from py_vulcanize import resource_loader as resource_loader
+
+
+class ResourceWithFakeContents(resource.Resource):
+
+ def __init__(self, toplevel_dir, absolute_path, fake_contents):
+ """A resource with explicitly provided contents.
+
+ If the resource does not exist, then pass fake_contents=None. This will
+ cause accessing the resource contents to raise an exception mimicking the
+ behavior of regular resources."""
+ super(ResourceWithFakeContents, self).__init__(toplevel_dir, absolute_path)
+ self._fake_contents = fake_contents
+
+ @property
+ def contents(self):
+ if self._fake_contents is None:
+ raise Exception('File not found')
+ return self._fake_contents
+
+
+class FakeLoader(object):
+
+ def __init__(self, source_paths, initial_filenames_and_contents=None):
+ self._source_paths = source_paths
+ self._file_contents = {}
+ if initial_filenames_and_contents:
+ for k, v in initial_filenames_and_contents.iteritems():
+ self._file_contents[k] = v
+
+ def FindResourceGivenAbsolutePath(self, absolute_path):
+ candidate_paths = []
+ for source_path in self._source_paths:
+ if absolute_path.startswith(source_path):
+ candidate_paths.append(source_path)
+ if len(candidate_paths) == 0:
+ return None
+
+ # Sort by length. Longest match wins.
+ candidate_paths.sort(lambda x, y: len(x) - len(y))
+ longest_candidate = candidate_paths[-1]
+
+ return ResourceWithFakeContents(
+ longest_candidate, absolute_path,
+ self._file_contents.get(absolute_path, None))
+
+ def FindResourceGivenRelativePath(self, relative_path):
+ absolute_path = None
+ for script_path in self._source_paths:
+ absolute_path = os.path.join(script_path, relative_path)
+ if absolute_path in self._file_contents:
+ return ResourceWithFakeContents(script_path, absolute_path,
+ self._file_contents[absolute_path])
+ return None
+
+
+class ParseTests(unittest.TestCase):
+
+ def testValidExternalScriptReferenceToRawScript(self):
+ parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html>
+ <script src="../foo.js">
+ """)
+
+ file_contents = {}
+ file_contents[os.path.normpath('/tmp/a/foo.js')] = """
+'i am just some raw script';
+"""
+
+ metadata = html_module.Parse(
+ FakeLoader([os.path.normpath('/tmp')], file_contents),
+ 'a.b.start',
+ '/tmp/a/b/',
+ is_component=False,
+ parser_results=parse_results)
+ self.assertEquals([], metadata.dependent_module_names)
+ self.assertEquals(
+ ['a/foo.js'], metadata.dependent_raw_script_relative_paths)
+
+ def testExternalScriptReferenceToModuleOutsideScriptPath(self):
+ parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html>
+ <script src="/foo.js">
+ """)
+
+ file_contents = {}
+ file_contents[os.path.normpath('/foo.js')] = ''
+
+ def DoIt():
+ html_module.Parse(FakeLoader([os.path.normpath('/tmp')], file_contents),
+ 'a.b.start',
+ '/tmp/a/b/',
+ is_component=False,
+ parser_results=parse_results)
+ self.assertRaises(Exception, DoIt)
+
+ def testExternalScriptReferenceToFileThatDoesntExist(self):
+ parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html>
+ <script src="/foo.js">
+ """)
+
+ file_contents = {}
+
+ def DoIt():
+ html_module.Parse(FakeLoader([os.path.normpath('/tmp')], file_contents),
+ 'a.b.start',
+ '/tmp/a/b/',
+ is_component=False,
+ parser_results=parse_results)
+ self.assertRaises(Exception, DoIt)
+
+ def testValidImportOfModule(self):
+ parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html>
+ <link rel="import" href="../foo.html">
+ """)
+
+ file_contents = {}
+ file_contents[os.path.normpath('/tmp/a/foo.html')] = """
+"""
+
+ metadata = html_module.Parse(
+ FakeLoader([os.path.normpath('/tmp')], file_contents),
+ 'a.b.start',
+ '/tmp/a/b/',
+ is_component=False,
+ parser_results=parse_results)
+ self.assertEquals(['a.foo'], metadata.dependent_module_names)
+
+ def testStyleSheetImport(self):
+ parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html>
+ <link rel="stylesheet" href="../foo.css">
+ """)
+
+ file_contents = {}
+ file_contents[os.path.normpath('/tmp/a/foo.css')] = """
+"""
+ metadata = html_module.Parse(
+ FakeLoader([os.path.normpath('/tmp')], file_contents),
+ 'a.b.start',
+ '/tmp/a/b/',
+ is_component=False,
+ parser_results=parse_results)
+ self.assertEquals([], metadata.dependent_module_names)
+ self.assertEquals(['a.foo'], metadata.style_sheet_names)
+
+ def testUsingAbsoluteHref(self):
+ parse_results = parse_html_deps.HTMLModuleParserResults("""<!DOCTYPE html>
+ <script src="/foo.js">
+ """)
+
+ file_contents = {}
+ file_contents[os.path.normpath('/src/foo.js')] = ''
+
+ metadata = html_module.Parse(
+ FakeLoader([os.path.normpath("/tmp"), os.path.normpath("/src")],
+ file_contents),
+ "a.b.start",
+ "/tmp/a/b/",
+ is_component=False,
+ parser_results=parse_results)
+ self.assertEquals(['foo.js'], metadata.dependent_raw_script_relative_paths)
+
+
+class HTMLModuleTests(unittest.TestCase):
+
+ def testBasicModuleGeneration(self):
+ file_contents = {}
+ file_contents[os.path.normpath('/tmp/a/b/start.html')] = """
+<!DOCTYPE html>
+<link rel="import" href="/widget.html">
+<link rel="stylesheet" href="../common.css">
+<script src="/raw_script.js"></script>
+<script src="/excluded_script.js"></script>
+<dom-module id="start">
+ <template>
+ </template>
+ <script>
+ 'use strict';
+ console.log('inline script for start.html got written');
+ </script>
+</dom-module>
+"""
+ file_contents[os.path.normpath('/py_vulcanize/py_vulcanize.html')] = """<!DOCTYPE html>
+"""
+ file_contents[os.path.normpath('/components/widget.html')] = """
+<!DOCTYPE html>
+<link rel="import" href="/py_vulcanize.html">
+<widget name="widget.html"></widget>
+<script>
+'use strict';
+console.log('inline script for widget.html');
+</script>
+"""
+ file_contents[os.path.normpath('/tmp/a/common.css')] = """
+/* /tmp/a/common.css was written */
+"""
+ file_contents[os.path.normpath('/raw/raw_script.js')] = """
+console.log('/raw/raw_script.js was written');
+"""
+ file_contents[os.path.normpath(
+ '/raw/components/polymer/polymer.min.js')] = """
+"""
+
+ with fake_fs.FakeFS(file_contents):
+ project = project_module.Project(
+ [os.path.normpath('/py_vulcanize/'),
+ os.path.normpath('/tmp/'),
+ os.path.normpath('/components/'),
+ os.path.normpath('/raw/')])
+ loader = resource_loader.ResourceLoader(project)
+ a_b_start_module = loader.LoadModule(
+ module_name='a.b.start', excluded_scripts=['\/excluded_script.js'])
+ load_sequence = project.CalcLoadSequenceForModules([a_b_start_module])
+
+ # Check load sequence names.
+ load_sequence_names = [x.name for x in load_sequence]
+ self.assertEquals(['py_vulcanize',
+ 'widget',
+ 'a.b.start'], load_sequence_names)
+
+ # Check module_deps on a_b_start_module
+ def HasDependentModule(module, name):
+ return [x for x in module.dependent_modules
+ if x.name == name]
+ assert HasDependentModule(a_b_start_module, 'widget')
+
+ # Check JS generation.
+ js = generate.GenerateJS(load_sequence)
+ assert 'inline script for start.html' in js
+ assert 'inline script for widget.html' in js
+ assert '/raw/raw_script.js' in js
+ assert 'excluded_script.js' not in js
+
+ # Check HTML generation.
+ html = generate.GenerateStandaloneHTMLAsString(
+ load_sequence, title='', flattened_js_url='/blah.js')
+ assert '<dom-module id="start">' in html
+ assert 'inline script for widget.html' not in html
+ assert 'common.css' in html
+
+ def testPolymerConversion(self):
+ file_contents = {}
+ file_contents[os.path.normpath('/tmp/a/b/my_component.html')] = """
+<!DOCTYPE html>
+<dom-module id="my-component">
+ <template>
+ </template>
+ <script>
+ 'use strict';
+ Polymer ( {
+ is: "my-component"
+ });
+ </script>
+</dom-module>
+"""
+ with fake_fs.FakeFS(file_contents):
+ project = project_module.Project([
+ os.path.normpath('/py_vulcanize/'), os.path.normpath('/tmp/')])
+ loader = resource_loader.ResourceLoader(project)
+ my_component = loader.LoadModule(module_name='a.b.my_component')
+
+ f = StringIO.StringIO()
+ my_component.AppendJSContentsToFile(
+ f,
+ use_include_tags_for_scripts=False,
+ dir_for_include_tag_root=None)
+ js = f.getvalue().rstrip()
+ expected_js = """
+ 'use strict';
+ Polymer ( {
+ is: "my-component"
+ });
+""".rstrip()
+ self.assertEquals(expected_js, js)
+
+ def testInlineStylesheetURLs(self):
+ file_contents = {}
+ file_contents[os.path.normpath('/tmp/a/b/my_component.html')] = """
+<!DOCTYPE html>
+<style>
+.some-rule {
+ background-image: url('../something.jpg');
+}
+</style>
+"""
+ file_contents[os.path.normpath('/tmp/a/something.jpg')] = 'jpgdata'
+ with fake_fs.FakeFS(file_contents):
+ project = project_module.Project([
+ os.path.normpath('/py_vulcanize/'), os.path.normpath('/tmp/')])
+ loader = resource_loader.ResourceLoader(project)
+ my_component = loader.LoadModule(module_name='a.b.my_component')
+
+ computed_deps = []
+ my_component.AppendDirectlyDependentFilenamesTo(computed_deps)
+ self.assertEquals(set(computed_deps),
+ set([os.path.normpath('/tmp/a/b/my_component.html'),
+ os.path.normpath('/tmp/a/something.jpg')]))
+
+ f = StringIO.StringIO()
+ ctl = html_generation_controller.HTMLGenerationController()
+ my_component.AppendHTMLContentsToFile(f, ctl)
+ html = f.getvalue().rstrip()
+ # FIXME: This is apparently not used.
+ expected_html = """
+.some-rule {
+ background-image: url(data:image/jpg;base64,anBnZGF0YQ==);
+}
+""".rstrip()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/js_utils.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/js_utils.py
new file mode 100644
index 00000000000..6e6ca9db674
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/js_utils.py
@@ -0,0 +1,7 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+def EscapeJSIfNeeded(js):
+ return js.replace('</script>', '<\/script>')
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/js_utils_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/js_utils_unittest.py
new file mode 100644
index 00000000000..cb8025c97db
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/js_utils_unittest.py
@@ -0,0 +1,18 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from py_vulcanize import js_utils
+
+
+class ValidateStrictModeTests(unittest.TestCase):
+
+ def testEscapeJSIfNeeded(self):
+ self.assertEqual(
+ '<script>var foo;<\/script>',
+ js_utils.EscapeJSIfNeeded('<script>var foo;</script>'))
+ self.assertEqual(
+ '<script>var foo;<\/script>',
+ js_utils.EscapeJSIfNeeded('<script>var foo;<\/script>'))
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/module.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/module.py
new file mode 100644
index 00000000000..bd6a68fa442
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/module.py
@@ -0,0 +1,262 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This module contains the Module class and other classes for resources.
+
+The Module class represents a module in the trace viewer system. A module has
+a name, and may require a variety of other resources, such as stylesheets,
+template objects, raw JavaScript, or other modules.
+
+Other resources include HTML templates, raw JavaScript files, and stylesheets.
+"""
+
+import os
+import inspect
+import codecs
+
+from py_vulcanize import js_utils
+
+
+class DepsException(Exception):
+ """Exceptions related to module dependency resolution."""
+
+ def __init__(self, fmt, *args):
+ from py_vulcanize import style_sheet as style_sheet_module
+ context = []
+ frame = inspect.currentframe()
+ while frame:
+ frame_locals = frame.f_locals
+
+ module_name = None
+ if 'self' in frame_locals:
+ s = frame_locals['self']
+ if isinstance(s, Module):
+ module_name = s.name
+ if isinstance(s, style_sheet_module.StyleSheet):
+ module_name = s.name + '.css'
+ if not module_name:
+ if 'module' in frame_locals:
+ module = frame_locals['module']
+ if isinstance(s, Module):
+ module_name = module.name
+ elif 'm' in frame_locals:
+ module = frame_locals['m']
+ if isinstance(s, Module):
+ module_name = module.name
+
+ if module_name:
+ if len(context):
+ if context[-1] != module_name:
+ context.append(module_name)
+ else:
+ context.append(module_name)
+
+ frame = frame.f_back
+
+ context.reverse()
+ self.context = context
+ context_str = '\n'.join(' %s' % x for x in context)
+ Exception.__init__(
+ self, 'While loading:\n%s\nGot: %s' % (context_str, (fmt % args)))
+
+
+class ModuleDependencyMetadata(object):
+
+ def __init__(self):
+ self.dependent_module_names = []
+ self.dependent_raw_script_relative_paths = []
+ self.style_sheet_names = []
+
+ def AppendMetdata(self, other):
+ self.dependent_module_names += other.dependent_module_names
+ self.dependent_raw_script_relative_paths += \
+ other.dependent_raw_script_relative_paths
+ self.style_sheet_names += other.style_sheet_names
+
+
+_next_module_id = 1
+
+
+class Module(object):
+ """Represents a JavaScript module.
+
+ Interesting properties include:
+ name: Module name, may include a namespace, e.g. 'py_vulcanize.foo'.
+ filename: The filename of the actual module.
+ contents: The text contents of the module.
+ dependent_modules: Other modules that this module depends on.
+
+ In addition to these properties, a Module also contains lists of other
+ resources that it depends on.
+ """
+
+ def __init__(self, loader, name, resource, load_resource=True):
+ assert isinstance(name, basestring), 'Got %s instead' % repr(name)
+
+ global _next_module_id
+ self._id = _next_module_id
+ _next_module_id += 1
+
+ self.loader = loader
+ self.name = name
+ self.resource = resource
+
+ if load_resource:
+ f = codecs.open(self.filename, mode='r', encoding='utf-8')
+ self.contents = f.read()
+ f.close()
+ else:
+ self.contents = None
+
+ # Dependency metadata, set up during Parse().
+ self.dependency_metadata = None
+
+ # Actual dependencies, set up during load().
+ self.dependent_modules = []
+ self.dependent_raw_scripts = []
+ self.scripts = []
+ self.style_sheets = []
+
+ # Caches.
+ self._all_dependent_modules_recursive = None
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, self.name)
+
+ @property
+ def id(self):
+ return self._id
+
+ @property
+ def filename(self):
+ return self.resource.absolute_path
+
+ def IsThirdPartyComponent(self):
+ """Checks whether this module is a third-party Polymer component."""
+ if os.path.join('third_party', 'components') in self.filename:
+ return True
+ if os.path.join('third_party', 'polymer', 'components') in self.filename:
+ return True
+ return False
+
+ def Parse(self, excluded_scripts):
+ """Parses self.contents and fills in the module's dependency metadata."""
+ raise NotImplementedError()
+
+ def GetTVCMDepsModuleType(self):
+ """Returns the py_vulcanize.setModuleInfo type for this module"""
+ raise NotImplementedError()
+
+ def AppendJSContentsToFile(self,
+ f,
+ use_include_tags_for_scripts,
+ dir_for_include_tag_root):
+ """Appends the js for this module to the provided file."""
+ for script in self.scripts:
+ script.AppendJSContentsToFile(f, use_include_tags_for_scripts,
+ dir_for_include_tag_root)
+
+ def AppendHTMLContentsToFile(self, f, ctl, minify=False):
+ """Appends the HTML for this module [without links] to the provided file."""
+ pass
+
+ def Load(self, excluded_scripts=None):
+ """Loads the sub-resources that this module depends on from its dependency
+ metadata.
+
+ Raises:
+ DepsException: There was a problem finding one of the dependencies.
+ Exception: There was a problem parsing a module that this one depends on.
+ """
+ assert self.name, 'Module name must be set before dep resolution.'
+ assert self.filename, 'Module filename must be set before dep resolution.'
+ assert self.name in self.loader.loaded_modules, (
+ 'Module must be registered in resource loader before loading.')
+
+ metadata = self.dependency_metadata
+ for name in metadata.dependent_module_names:
+ module = self.loader.LoadModule(module_name=name,
+ excluded_scripts=excluded_scripts)
+ self.dependent_modules.append(module)
+
+ for name in metadata.style_sheet_names:
+ style_sheet = self.loader.LoadStyleSheet(name)
+ self.style_sheets.append(style_sheet)
+
+ @property
+ def all_dependent_modules_recursive(self):
+ if self._all_dependent_modules_recursive:
+ return self._all_dependent_modules_recursive
+
+ self._all_dependent_modules_recursive = set(self.dependent_modules)
+ for dependent_module in self.dependent_modules:
+ self._all_dependent_modules_recursive.update(
+ dependent_module.all_dependent_modules_recursive)
+ return self._all_dependent_modules_recursive
+
+ def ComputeLoadSequenceRecursive(self, load_sequence, already_loaded_set,
+ depth=0):
+ """Recursively builds up a load sequence list.
+
+ Args:
+ load_sequence: A list which will be incrementally built up.
+ already_loaded_set: A set of modules that has already been added to the
+ load sequence list.
+ depth: The depth of recursion. If it too deep, that indicates a loop.
+ """
+ if depth > 32:
+ raise Exception('Include loop detected on %s', self.name)
+ for dependent_module in self.dependent_modules:
+ if dependent_module.name in already_loaded_set:
+ continue
+ dependent_module.ComputeLoadSequenceRecursive(
+ load_sequence, already_loaded_set, depth + 1)
+ if self.name not in already_loaded_set:
+ already_loaded_set.add(self.name)
+ load_sequence.append(self)
+
+ def GetAllDependentFilenamesRecursive(self, include_raw_scripts=True):
+ dependent_filenames = []
+
+ visited_modules = set()
+
+ def Get(module):
+ module.AppendDirectlyDependentFilenamesTo(
+ dependent_filenames, include_raw_scripts)
+ visited_modules.add(module)
+ for m in module.dependent_modules:
+ if m in visited_modules:
+ continue
+ Get(m)
+
+ Get(self)
+ return dependent_filenames
+
+ def AppendDirectlyDependentFilenamesTo(
+ self, dependent_filenames, include_raw_scripts=True):
+ dependent_filenames.append(self.resource.absolute_path)
+ if include_raw_scripts:
+ for raw_script in self.dependent_raw_scripts:
+ dependent_filenames.append(raw_script.resource.absolute_path)
+ for style_sheet in self.style_sheets:
+ style_sheet.AppendDirectlyDependentFilenamesTo(dependent_filenames)
+
+
+class RawScript(object):
+ """Represents a raw script resource referenced by a module via the
+ py_vulcanize.requireRawScript(xxx) directive."""
+
+ def __init__(self, resource):
+ self.resource = resource
+
+ @property
+ def filename(self):
+ return self.resource.absolute_path
+
+ @property
+ def contents(self):
+ return self.resource.contents
+
+ def __repr__(self):
+ return 'RawScript(%s)' % self.filename
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/module_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/module_unittest.py
new file mode 100644
index 00000000000..ed92db35362
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/module_unittest.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for the module module, which contains Module and related classes."""
+
+import os
+import unittest
+
+from py_vulcanize import fake_fs
+from py_vulcanize import module
+from py_vulcanize import resource_loader
+from py_vulcanize import project as project_module
+
+
+class ModuleIntegrationTests(unittest.TestCase):
+
+ def test_module(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/src/x.html', """
+<!DOCTYPE html>
+<link rel="import" href="/y.html">
+<link rel="import" href="/z.html">
+<script>
+'use strict';
+</script>
+""")
+ fs.AddFile('/src/y.html', """
+<!DOCTYPE html>
+<link rel="import" href="/z.html">
+""")
+ fs.AddFile('/src/z.html', """
+<!DOCTYPE html>
+""")
+ fs.AddFile('/src/py_vulcanize.html', '<!DOCTYPE html>')
+ with fs:
+ project = project_module.Project([os.path.normpath('/src/')])
+ loader = resource_loader.ResourceLoader(project)
+ x_module = loader.LoadModule('x')
+
+ self.assertEquals([loader.loaded_modules['y'],
+ loader.loaded_modules['z']],
+ x_module.dependent_modules)
+
+ already_loaded_set = set()
+ load_sequence = []
+ x_module.ComputeLoadSequenceRecursive(load_sequence, already_loaded_set)
+
+ self.assertEquals([loader.loaded_modules['z'],
+ loader.loaded_modules['y'],
+ x_module],
+ load_sequence)
+
+ def testBasic(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/x/src/my_module.html', """
+<!DOCTYPE html>
+<link rel="import" href="/py_vulcanize/foo.html">
+});
+""")
+ fs.AddFile('/x/py_vulcanize/foo.html', """
+<!DOCTYPE html>
+});
+""")
+ project = project_module.Project([os.path.normpath('/x')])
+ loader = resource_loader.ResourceLoader(project)
+ with fs:
+ my_module = loader.LoadModule(module_name='src.my_module')
+ dep_names = [x.name for x in my_module.dependent_modules]
+ self.assertEquals(['py_vulcanize.foo'], dep_names)
+
+ def testDepsExceptionContext(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/x/src/my_module.html', """
+<!DOCTYPE html>
+<link rel="import" href="/py_vulcanize/foo.html">
+""")
+ fs.AddFile('/x/py_vulcanize/foo.html', """
+<!DOCTYPE html>
+<link rel="import" href="missing.html">
+""")
+ project = project_module.Project([os.path.normpath('/x')])
+ loader = resource_loader.ResourceLoader(project)
+ with fs:
+ exc = None
+ try:
+ loader.LoadModule(module_name='src.my_module')
+ assert False, 'Expected an exception'
+ except module.DepsException as e:
+ exc = e
+ self.assertEquals(
+ ['src.my_module', 'py_vulcanize.foo'],
+ exc.context)
+
+ def testGetAllDependentFilenamesRecursive(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/x/y/z/foo.html', """
+<!DOCTYPE html>
+<link rel="import" href="/z/foo2.html">
+<link rel="stylesheet" href="/z/foo.css">
+<script src="/bar.js"></script>
+""")
+ fs.AddFile('/x/y/z/foo.css', """
+.x .y {
+ background-image: url(foo.jpeg);
+}
+""")
+ fs.AddFile('/x/y/z/foo.jpeg', '')
+ fs.AddFile('/x/y/z/foo2.html', """
+<!DOCTYPE html>
+""")
+ fs.AddFile('/x/raw/bar.js', 'hello')
+ project = project_module.Project([
+ os.path.normpath('/x/y'), os.path.normpath('/x/raw/')])
+ loader = resource_loader.ResourceLoader(project)
+ with fs:
+ my_module = loader.LoadModule(module_name='z.foo')
+ self.assertEquals(1, len(my_module.dependent_raw_scripts))
+
+ dependent_filenames = my_module.GetAllDependentFilenamesRecursive()
+ self.assertEquals(
+ [
+ os.path.normpath('/x/y/z/foo.html'),
+ os.path.normpath('/x/raw/bar.js'),
+ os.path.normpath('/x/y/z/foo.css'),
+ os.path.normpath('/x/y/z/foo.jpeg'),
+ os.path.normpath('/x/y/z/foo2.html'),
+ ],
+ dependent_filenames)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/parse_html_deps.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/parse_html_deps.py
new file mode 100644
index 00000000000..4a0888ca1dc
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/parse_html_deps.py
@@ -0,0 +1,283 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+from py_vulcanize import js_utils
+from py_vulcanize import module
+from py_vulcanize import strip_js_comments
+from py_vulcanize import html_generation_controller
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+def _InitBeautifulSoup():
+ catapult_path = os.path.abspath(
+ os.path.join(os.path.dirname(__file__),
+ os.path.pardir, os.path.pardir, os.path.pardir))
+ bs_path = os.path.join(catapult_path, 'third_party', 'beautifulsoup4')
+ _AddToPathIfNeeded(bs_path)
+
+ html5lib_path = os.path.join(catapult_path, 'third_party', 'html5lib-python')
+ _AddToPathIfNeeded(html5lib_path)
+
+ six_path = os.path.join(catapult_path, 'third_party', 'six')
+ _AddToPathIfNeeded(six_path)
+
+
+_InitBeautifulSoup()
+import bs4
+
+class Script(object):
+
+ def __init__(self, soup):
+ if not soup:
+ raise module.DepsException('Script object created without soup')
+ self._soup = soup
+
+ def AppendJSContentsToFile(self, f, *args, **kwargs):
+ raise NotImplementedError()
+
+class InlineScript(Script):
+
+ def __init__(self, soup):
+ super(InlineScript, self).__init__(soup)
+ self._stripped_contents = None
+ self._open_tags = None
+ self.is_external = False
+
+ @property
+ def contents(self):
+ return unicode(self._soup.string)
+
+ @property
+ def stripped_contents(self):
+ if not self._stripped_contents:
+ self._stripped_contents = strip_js_comments.StripJSComments(
+ self.contents)
+ return self._stripped_contents
+
+ @property
+ def open_tags(self):
+ if self._open_tags:
+ return self._open_tags
+ open_tags = []
+ cur = self._soup.parent
+ while cur:
+ if isinstance(cur, bs4.BeautifulSoup):
+ break
+
+ open_tags.append(_Tag(cur.name, cur.attrs))
+ cur = cur.parent
+
+ open_tags.reverse()
+ assert open_tags[-1].tag == 'script'
+ del open_tags[-1]
+
+ self._open_tags = open_tags
+ return self._open_tags
+
+ def AppendJSContentsToFile(self, f, *args, **kwargs):
+ js = self.contents
+ escaped_js = js_utils.EscapeJSIfNeeded(js)
+ f.write(escaped_js)
+ f.write('\n')
+
+class ExternalScript(Script):
+
+ def __init__(self, soup):
+ super(ExternalScript, self).__init__(soup)
+ if 'src' not in soup.attrs:
+ raise Exception("{0} is not an external script.".format(soup))
+ self.is_external = True
+ self._loaded_raw_script = None
+
+ @property
+ def loaded_raw_script(self):
+ if self._loaded_raw_script:
+ return self._loaded_raw_script
+
+ return None
+
+ @loaded_raw_script.setter
+ def loaded_raw_script(self, value):
+ self._loaded_raw_script = value
+
+ @property
+ def src(self):
+ return self._soup.attrs['src']
+
+ def AppendJSContentsToFile(self,
+ f,
+ use_include_tags_for_scripts,
+ dir_for_include_tag_root):
+ raw_script = self.loaded_raw_script
+ if not raw_script:
+ return
+
+ if use_include_tags_for_scripts:
+ rel_filename = os.path.relpath(raw_script.filename,
+ dir_for_include_tag_root)
+ f.write("""<include src="%s">\n""" % rel_filename)
+ else:
+ f.write(js_utils.EscapeJSIfNeeded(raw_script.contents))
+ f.write('\n')
+
+def _CreateSoupWithoutHeadOrBody(html):
+ soupCopy = bs4.BeautifulSoup(html, 'html5lib')
+ soup = bs4.BeautifulSoup()
+ soup.reset()
+ if soupCopy.head:
+ for n in soupCopy.head.contents:
+ n.extract()
+ soup.append(n)
+ if soupCopy.body:
+ for n in soupCopy.body.contents:
+ n.extract()
+ soup.append(n)
+ return soup
+
+
+class HTMLModuleParserResults(object):
+
+ def __init__(self, html):
+ self._soup = bs4.BeautifulSoup(html, 'html5lib')
+ self._inline_scripts = None
+ self._scripts = None
+
+ @property
+ def scripts_external(self):
+ tags = self._soup.findAll('script', src=True)
+ return [t['src'] for t in tags]
+
+ @property
+ def inline_scripts(self):
+ if not self._inline_scripts:
+ tags = self._soup.findAll('script', src=None)
+ self._inline_scripts = [InlineScript(t.string) for t in tags]
+ return self._inline_scripts
+
+ @property
+ def scripts(self):
+ if not self._scripts:
+ self._scripts = []
+ script_elements = self._soup.findAll('script')
+ for element in script_elements:
+ if 'src' in element.attrs:
+ self._scripts.append(ExternalScript(element))
+ else:
+ self._scripts.append(InlineScript(element))
+ return self._scripts
+
+ @property
+ def imports(self):
+ tags = self._soup.findAll('link', rel='import')
+ return [t['href'] for t in tags]
+
+ @property
+ def stylesheets(self):
+ tags = self._soup.findAll('link', rel='stylesheet')
+ return [t['href'] for t in tags]
+
+ @property
+ def inline_stylesheets(self):
+ tags = self._soup.findAll('style')
+ return [unicode(t.string) for t in tags]
+
+ def YieldHTMLInPieces(self, controller, minify=False):
+ yield self.GenerateHTML(controller, minify)
+
+ def GenerateHTML(self, controller, minify=False, prettify=False):
+ soup = _CreateSoupWithoutHeadOrBody(unicode(self._soup))
+
+ # Remove declaration.
+ for x in soup.contents:
+ if isinstance(x, bs4.Doctype):
+ x.extract()
+
+ # Remove declaration.
+ for x in soup.contents:
+ if isinstance(x, bs4.Declaration):
+ x.extract()
+
+ # Remove all imports.
+ imports = soup.findAll('link', rel='import')
+ for imp in imports:
+ imp.extract()
+
+ # Remove all script links.
+ scripts_external = soup.findAll('script', src=True)
+ for script in scripts_external:
+ script.extract()
+
+ # Remove all in-line scripts.
+ scripts_external = soup.findAll('script', src=None)
+ for script in scripts_external:
+ script.extract()
+
+ # Process all in-line styles.
+ inline_styles = soup.findAll('style')
+ for style in inline_styles:
+ html = controller.GetHTMLForInlineStylesheet(unicode(style.string))
+ if html:
+ ns = soup.new_tag('style')
+ ns.append(bs4.NavigableString(html))
+ style.replaceWith(ns)
+ else:
+ style.extract()
+
+ # Rewrite all external stylesheet hrefs or remove, as needed.
+ stylesheet_links = soup.findAll('link', rel='stylesheet')
+ for stylesheet_link in stylesheet_links:
+ html = controller.GetHTMLForStylesheetHRef(stylesheet_link['href'])
+ if html:
+ tmp = bs4.BeautifulSoup(html, 'html5lib').findAll('style')
+ assert len(tmp) == 1
+ stylesheet_link.replaceWith(tmp[0])
+ else:
+ stylesheet_link.extract()
+
+ # Remove comments if minifying.
+ if minify:
+ comments = soup.findAll(
+ text=lambda text: isinstance(text, bs4.Comment))
+ for comment in comments:
+ comment.extract()
+ if prettify:
+ return soup.prettify('utf-8').strip()
+
+ # We are done.
+ return unicode(soup).strip()
+
+ @property
+ def html_contents_without_links_and_script(self):
+ return self.GenerateHTML(
+ html_generation_controller.HTMLGenerationController())
+
+
+class _Tag(object):
+
+ def __init__(self, tag, attrs):
+ self.tag = tag
+ self.attrs = attrs
+
+ def __repr__(self):
+ attr_string = ' '.join('%s="%s"' % (x[0], x[1]) for x in self.attrs)
+ return '<%s %s>' % (self.tag, attr_string)
+
+
+class HTMLModuleParser():
+
+ def Parse(self, html):
+ if html is None:
+ html = ''
+ else:
+ if html.find('< /script>') != -1:
+ raise Exception('Escape script tags with <\/script>')
+
+ return HTMLModuleParserResults(html)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/parse_html_deps_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/parse_html_deps_unittest.py
new file mode 100755
index 00000000000..2a30a29b059
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/parse_html_deps_unittest.py
@@ -0,0 +1,292 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import unittest
+
+from py_vulcanize import parse_html_deps
+from py_vulcanize import html_generation_controller
+
+
+class ParseTests(unittest.TestCase):
+
+ def test_parse_empty(self):
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse('')
+ self.assertEquals([], module.scripts_external)
+ self.assertEquals([], module.inline_scripts)
+ self.assertEquals([], module.stylesheets)
+ self.assertEquals([], module.imports)
+
+ def test_parse_none(self):
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(None)
+ self.assertEquals([], module.scripts_external)
+ self.assertEquals([], module.inline_scripts)
+ self.assertEquals([], module.stylesheets)
+ self.assertEquals([], module.imports)
+
+ def test_parse_script_src_basic(self):
+ html = """<!DOCTYPE html>
+ <html>
+ <head>
+ <script src="polymer.min.js"></script>
+ <script src="foo.js"></script>
+ </head>
+ <body>
+ </body>
+ </html>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals(['polymer.min.js', 'foo.js'], module.scripts_external)
+ self.assertEquals([], module.inline_scripts)
+ self.assertEquals([], module.stylesheets)
+ self.assertEquals([], module.imports)
+ self.assertNotIn(
+ 'DOCTYPE html',
+ module.html_contents_without_links_and_script)
+
+ def test_parse_link_rel_import(self):
+ html = """<!DOCTYPE html>
+ <html>
+ <head>
+ <link rel="import" href="x-foo.html">
+ </head>
+ <body>
+ </body>
+ </html>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals([], module.scripts_external)
+ self.assertEquals([], module.inline_scripts)
+ self.assertEquals([], module.stylesheets)
+ self.assertEquals(['x-foo.html'], module.imports)
+
+ def test_parse_script_inline(self):
+ html = """<polymer-element name="tk-element-proto">
+ <template>
+ </template>
+ <script>
+ py_vulcanize.require("foo");
+ py_vulcanize.require('bar');
+ </script>
+ </polymer-element>"""
+
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals([], module.scripts_external)
+ self.assertEquals(1, len(module.inline_scripts))
+ self.assertEquals([], module.stylesheets)
+ self.assertEquals([], module.imports)
+
+ script0 = module.inline_scripts[0]
+ val = re.sub(r'\s+', '', script0.contents)
+ inner_script = """py_vulcanize.require("foo");py_vulcanize.require('bar');"""
+ self.assertEquals(inner_script, val)
+
+ self.assertEquals(3, len(script0.open_tags))
+ self.assertEquals('polymer-element', script0.open_tags[2].tag)
+
+ self.assertNotIn(
+ 'py_vulcanize.require("foo");',
+ module.html_contents_without_links_and_script)
+
+ def test_parse_script_inline_and_external(self):
+ html = """<polymer-element name="tk-element-proto">
+ <template>
+ </template>
+ <script>window = {}</script>
+ <script src="foo.js"></script>
+ <script>window = undefined</script>
+ </polymer-element>"""
+
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals(3, len(module.scripts))
+ self.assertEquals('window = {}', module.scripts[0].contents)
+ self.assertEquals("foo.js",module.scripts[1].src)
+ self.assertTrue(module.scripts[1].is_external)
+ self.assertEquals('window = undefined', module.scripts[2].contents)
+ self.assertEquals([], module.imports)
+
+ def test_parse_script_src_sripping(self):
+ html = """
+<script src="blah.js"></script>
+"""
+ module = parse_html_deps.HTMLModuleParser().Parse(html)
+ self.assertEquals('',
+ module.html_contents_without_links_and_script)
+
+ def test_parse_link_rel_stylesheet(self):
+ html = """<polymer-element name="hi">
+ <template>
+ <link rel="stylesheet" href="frameworkstyles.css">
+ </template>
+ </polymer-element>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals([], module.scripts_external)
+ self.assertEquals([], module.inline_scripts)
+ self.assertEquals(['frameworkstyles.css'], module.stylesheets)
+ self.assertEquals([], module.imports)
+
+ class Ctl(html_generation_controller.HTMLGenerationController):
+
+ def GetHTMLForStylesheetHRef(self, href):
+ if href == 'frameworkstyles.css':
+ return '<style>FRAMEWORK</style>'
+ return None
+
+ gen_html = module.GenerateHTML(Ctl())
+ ghtm = """<polymer-element name="hi">
+ <template>
+ <style>FRAMEWORK</style>
+ </template>
+ </polymer-element>"""
+ self.assertEquals(ghtm, gen_html)
+
+ def test_parse_inline_style(self):
+ html = """<style>
+ hello
+</style>"""
+ module = parse_html_deps.HTMLModuleParser().Parse(html)
+ self.assertEquals(html, module.html_contents_without_links_and_script)
+
+ class Ctl(html_generation_controller.HTMLGenerationController):
+
+ def GetHTMLForInlineStylesheet(self, contents):
+ if contents == '\n hello\n':
+ return '\n HELLO\n'
+ return None
+
+ gen_html = module.GenerateHTML(Ctl())
+ ghtm = """<style>
+ HELLO
+</style>"""
+ self.assertEquals(ghtm, gen_html)
+
+ def test_parse_style_import(self):
+ html = """<polymer-element name="x-blink">
+ <template>
+ <style>
+ @import url(awesome.css);
+ </style>
+ </template>
+ </polymer-element>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ self.assertRaises(lambda: parser.Parse(html))
+
+ def test_nested_templates(self):
+ orig_html = """<template>
+ <template>
+ <div id="foo"></div>
+ </template>
+ </template>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ res = parser.Parse(orig_html)
+ html = res.html_contents_without_links_and_script
+ self.assertEquals(html, orig_html)
+
+ def test_html_contents_basic(self):
+ html = """<a b="c">d</a>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals(html, module.html_contents_without_links_and_script)
+
+ def test_html_contents_with_entity(self):
+ html = """<a>&rarr;</a>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals(u'<a>\u2192</a>',
+ module.html_contents_without_links_and_script)
+
+ def test_html_content_with_charref(self):
+ html = """<a>&#62;</a>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals('<a>&gt;</a>',
+ module.html_contents_without_links_and_script)
+
+ def test_html_content_start_end_br(self):
+ html = """<a><br /></a>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals('<a><br/></a>',
+ module.html_contents_without_links_and_script)
+
+ def test_html_content_start_end_img(self):
+ html = """<a><img src="foo.png" id="bar" /></a>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals('<a><img id="bar" src="foo.png"/></a>',
+ module.html_contents_without_links_and_script)
+
+ def test_html_contents_with_link_stripping(self):
+ html = """<a b="c">d</a>
+ <link rel="import" href="x-foo.html">"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals("""<a b="c">d</a>""",
+ module.html_contents_without_links_and_script.strip())
+
+ def test_html_contents_with_style_link_stripping(self):
+ html = """<a b="c">d</a>
+ <link rel="stylesheet" href="frameworkstyles.css">"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals("""<a b="c">d</a>""",
+ module.html_contents_without_links_and_script.strip())
+
+ def test_br_does_not_raise(self):
+ html = """<div><br/></div>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ parser.Parse(html)
+
+ def test_p_does_not_raises(self):
+ html = """<div></p></div>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ parser.Parse(html)
+
+ def test_link_endlink_does_not_raise(self):
+ html = """<link rel="stylesheet" href="foo.css"></link>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ parser.Parse(html)
+
+ def test_link_script_does_not_raise(self):
+ html = """<link rel="stylesheet" href="foo.css">
+ <script>
+ </script>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ parser.Parse(html)
+
+ def test_script_with_script_inside_as_js(self):
+ html = """<script>
+ var html_lines = [
+ '<script>',
+ '<\/script>',
+ ];
+ </script>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ parser.Parse(html)
+
+ def test_invalid_script_escaping_raises(self):
+ html = """<script>
+ var html_lines = [
+ '<script>',
+ '< /script>',
+ ];
+ </script>"""
+ parser = parse_html_deps.HTMLModuleParser()
+
+ def DoIt():
+ parser.Parse(html)
+ self.assertRaises(Exception, DoIt)
+
+ def test_script_with_cdata(self):
+ html = """<script></h2></script>"""
+ parser = parse_html_deps.HTMLModuleParser()
+ module = parser.Parse(html)
+ self.assertEquals(1, len(module.inline_scripts))
+ self.assertEquals('</h2>', module.inline_scripts[0].contents)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/project.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/project.py
new file mode 100644
index 00000000000..6b65784eb0e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/project.py
@@ -0,0 +1,235 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import os
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+from py_vulcanize import resource_loader
+
+
+def _FindAllFilesRecursive(source_paths):
+ all_filenames = set()
+ for source_path in source_paths:
+ for dirpath, _, filenames in os.walk(source_path):
+ for f in filenames:
+ if f.startswith('.'):
+ continue
+ x = os.path.abspath(os.path.join(dirpath, f))
+ all_filenames.add(x)
+ return all_filenames
+
+
+class AbsFilenameList(object):
+
+ def __init__(self, willDirtyCallback):
+ self._willDirtyCallback = willDirtyCallback
+ self._filenames = []
+ self._filenames_set = set()
+
+ def _WillBecomeDirty(self):
+ if self._willDirtyCallback:
+ self._willDirtyCallback()
+
+ def append(self, filename):
+ assert os.path.isabs(filename)
+ self._WillBecomeDirty()
+ self._filenames.append(filename)
+ self._filenames_set.add(filename)
+
+ def extend(self, iterable):
+ self._WillBecomeDirty()
+ for filename in iterable:
+ assert os.path.isabs(filename)
+ self._filenames.append(filename)
+ self._filenames_set.add(filename)
+
+ def appendRel(self, basedir, filename):
+ assert os.path.isabs(basedir)
+ self._WillBecomeDirty()
+ n = os.path.abspath(os.path.join(basedir, filename))
+ self._filenames.append(n)
+ self._filenames_set.add(n)
+
+ def extendRel(self, basedir, iterable):
+ self._WillBecomeDirty()
+ assert os.path.isabs(basedir)
+ for filename in iterable:
+ n = os.path.abspath(os.path.join(basedir, filename))
+ self._filenames.append(n)
+ self._filenames_set.add(n)
+
+ def __contains__(self, x):
+ return x in self._filenames_set
+
+ def __len__(self):
+ return self._filenames.__len__()
+
+ def __iter__(self):
+ return iter(self._filenames)
+
+ def __repr__(self):
+ return repr(self._filenames)
+
+ def __str__(self):
+ return str(self._filenames)
+
+
+class Project(object):
+
+ py_vulcanize_path = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '..'))
+
+ def __init__(self, source_paths=None):
+ """
+ source_paths: A list of top-level directories in which modules and raw
+ scripts can be found. Module paths are relative to these directories.
+ """
+ self._loader = None
+ self._frozen = False
+ self.source_paths = AbsFilenameList(self._WillPartOfPathChange)
+
+ if source_paths is not None:
+ self.source_paths.extend(source_paths)
+
+ def Freeze(self):
+ self._frozen = True
+
+ def _WillPartOfPathChange(self):
+ if self._frozen:
+ raise Exception('The project is frozen. You cannot edit it now')
+ self._loader = None
+
+ @staticmethod
+ def FromDict(d):
+ return Project(d['source_paths'])
+
+ def AsDict(self):
+ return {
+ 'source_paths': list(self.source_paths)
+ }
+
+ def __repr__(self):
+ return "Project(%s)" % repr(self.source_paths)
+
+ def AddSourcePath(self, path):
+ self.source_paths.append(path)
+
+ @property
+ def loader(self):
+ if self._loader is None:
+ self._loader = resource_loader.ResourceLoader(self)
+ return self._loader
+
+ def ResetLoader(self):
+ self._loader = None
+
+ def _Load(self, filenames):
+ return [self.loader.LoadModule(module_filename=filename) for
+ filename in filenames]
+
+ def LoadModule(self, module_name=None, module_filename=None):
+ return self.loader.LoadModule(module_name=module_name,
+ module_filename=module_filename)
+
+ def CalcLoadSequenceForModuleNames(self, module_names,
+ excluded_scripts=None):
+ modules = [self.loader.LoadModule(module_name=name,
+ excluded_scripts=excluded_scripts) for
+ name in module_names]
+ return self.CalcLoadSequenceForModules(modules)
+
+ def CalcLoadSequenceForModules(self, modules):
+ already_loaded_set = set()
+ load_sequence = []
+ for m in modules:
+ m.ComputeLoadSequenceRecursive(load_sequence, already_loaded_set)
+ return load_sequence
+
+ def GetDepsGraphFromModuleNames(self, module_names):
+ modules = [self.loader.LoadModule(module_name=name) for
+ name in module_names]
+ return self.GetDepsGraphFromModules(modules)
+
+ def GetDepsGraphFromModules(self, modules):
+ load_sequence = self.CalcLoadSequenceForModules(modules)
+ g = _Graph()
+ for m in load_sequence:
+ g.AddModule(m)
+
+ for dep in m.dependent_modules:
+ g.AddEdge(m, dep.id)
+
+ # FIXME: _GetGraph is not defined. Maybe `return g` is intended?
+ return _GetGraph(load_sequence)
+
+ def GetDominatorGraphForModulesNamed(self, module_names, load_sequence):
+ modules = [self.loader.LoadModule(module_name=name)
+ for name in module_names]
+ return self.GetDominatorGraphForModules(modules, load_sequence)
+
+ def GetDominatorGraphForModules(self, start_modules, load_sequence):
+ modules_by_id = {}
+ for m in load_sequence:
+ modules_by_id[m.id] = m
+
+ module_referrers = collections.defaultdict(list)
+ for m in load_sequence:
+ for dep in m.dependent_modules:
+ module_referrers[dep].append(m)
+
+ # Now start at the top module and reverse.
+ visited = set()
+ g = _Graph()
+
+ pending = collections.deque()
+ pending.extend(start_modules)
+ while len(pending):
+ cur = pending.pop()
+
+ g.AddModule(cur)
+ visited.add(cur)
+
+ for out_dep in module_referrers[cur]:
+ if out_dep in visited:
+ continue
+ g.AddEdge(out_dep, cur)
+ visited.add(out_dep)
+ pending.append(out_dep)
+
+ # Visited -> Dot
+ return g.GetDot()
+
+
+class _Graph(object):
+
+ def __init__(self):
+ self.nodes = []
+ self.edges = []
+
+ def AddModule(self, m):
+ f = StringIO()
+ m.AppendJSContentsToFile(f, False, None)
+
+ attrs = {
+ 'label': '%s (%i)' % (m.name, f.tell())
+ }
+
+ f.close()
+
+ attr_items = ['%s="%s"' % (x, y) for x, y in attrs.iteritems()]
+ node = 'M%i [%s];' % (m.id, ','.join(attr_items))
+ self.nodes.append(node)
+
+ def AddEdge(self, mFrom, mTo):
+ edge = 'M%i -> M%i;' % (mFrom.id, mTo.id)
+ self.edges.append(edge)
+
+ def GetDot(self):
+ return 'digraph deps {\n\n%s\n\n%s\n}\n' % (
+ '\n'.join(self.nodes), '\n'.join(self.edges))
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource.py
new file mode 100644
index 00000000000..853dff94437
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource.py
@@ -0,0 +1,57 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A Resource is a file and its various associated canonical names."""
+
+import codecs
+import os
+
+
+class Resource(object):
+ """Represents a file found via a path search."""
+
+ def __init__(self, toplevel_dir, absolute_path, binary=False):
+ self.toplevel_dir = toplevel_dir
+ self.absolute_path = absolute_path
+ self._contents = None
+ self._binary = binary
+
+ @property
+ def relative_path(self):
+ """The path to the file from the top-level directory"""
+ return os.path.relpath(self.absolute_path, self.toplevel_dir)
+
+ @property
+ def unix_style_relative_path(self):
+ return self.relative_path.replace(os.sep, '/')
+
+ @property
+ def name(self):
+ """The dotted name for this resource based on its relative path."""
+ return self.name_from_relative_path(self.relative_path)
+
+ @staticmethod
+ def name_from_relative_path(relative_path):
+ dirname = os.path.dirname(relative_path)
+ basename = os.path.basename(relative_path)
+ modname = os.path.splitext(basename)[0]
+ if len(dirname):
+ name = dirname.replace(os.path.sep, '.') + '.' + modname
+ else:
+ name = modname
+ return name
+
+ @property
+ def contents(self):
+ if self._contents:
+ return self._contents
+ if not os.path.exists(self.absolute_path):
+ raise Exception('%s not found.' % self.absolute_path)
+ if self._binary:
+ f = open(self.absolute_path, mode='rb')
+ else:
+ f = codecs.open(self.absolute_path, mode='r', encoding='utf-8')
+ self._contents = f.read()
+ f.close()
+ return self._contents
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource_loader.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource_loader.py
new file mode 100644
index 00000000000..015adaa6608
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource_loader.py
@@ -0,0 +1,228 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""ResourceFinder is a helper class for finding resources given their name."""
+
+import codecs
+import os
+
+from py_vulcanize import module
+from py_vulcanize import style_sheet as style_sheet_module
+from py_vulcanize import resource as resource_module
+from py_vulcanize import html_module
+from py_vulcanize import strip_js_comments
+
+
+class ResourceLoader(object):
+ """Manges loading modules and their dependencies from files.
+
+ Modules handle parsing and the construction of their individual dependency
+ pointers. The loader deals with bookkeeping of what has been loaded, and
+ mapping names to file resources.
+ """
+
+ def __init__(self, project):
+ self.project = project
+ self.stripped_js_by_filename = {}
+ self.loaded_modules = {}
+ self.loaded_raw_scripts = {}
+ self.loaded_style_sheets = {}
+ self.loaded_images = {}
+
+ @property
+ def source_paths(self):
+ """A list of base directories to search for modules under."""
+ return self.project.source_paths
+
+ def FindResource(self, some_path, binary=False):
+ """Finds a Resource for the given path.
+
+ Args:
+ some_path: A relative or absolute path to a file.
+
+ Returns:
+ A Resource or None.
+ """
+ if os.path.isabs(some_path):
+ return self.FindResourceGivenAbsolutePath(some_path, binary)
+ else:
+ return self.FindResourceGivenRelativePath(some_path, binary)
+
+ def FindResourceGivenAbsolutePath(self, absolute_path, binary=False):
+ """Returns a Resource for the given absolute path."""
+ candidate_paths = []
+ for source_path in self.source_paths:
+ if absolute_path.startswith(source_path):
+ candidate_paths.append(source_path)
+ if len(candidate_paths) == 0:
+ return None
+
+ # Sort by length. Longest match wins.
+ candidate_paths.sort(lambda x, y: len(x) - len(y))
+ longest_candidate = candidate_paths[-1]
+ return resource_module.Resource(longest_candidate, absolute_path, binary)
+
+ def FindResourceGivenRelativePath(self, relative_path, binary=False):
+ """Returns a Resource for the given relative path."""
+ absolute_path = None
+ for script_path in self.source_paths:
+ absolute_path = os.path.join(script_path, relative_path)
+ if os.path.exists(absolute_path):
+ return resource_module.Resource(script_path, absolute_path, binary)
+ return None
+
+ def _FindResourceGivenNameAndSuffix(
+ self, requested_name, extension, return_resource=False):
+ """Searches for a file and reads its contents.
+
+ Args:
+ requested_name: The name of the resource that was requested.
+ extension: The extension for this requested resource.
+
+ Returns:
+ A (path, contents) pair.
+ """
+ pathy_name = requested_name.replace('.', os.sep)
+ filename = pathy_name + extension
+
+ resource = self.FindResourceGivenRelativePath(filename)
+ if return_resource:
+ return resource
+ if not resource:
+ return None, None
+ return _read_file(resource.absolute_path)
+
+ def FindModuleResource(self, requested_module_name):
+ """Finds a module javascript file and returns a Resource, or none."""
+ js_resource = self._FindResourceGivenNameAndSuffix(
+ requested_module_name, '.js', return_resource=True)
+ html_resource = self._FindResourceGivenNameAndSuffix(
+ requested_module_name, '.html', return_resource=True)
+ if js_resource and html_resource:
+ if html_module.IsHTMLResourceTheModuleGivenConflictingResourceNames(
+ js_resource, html_resource):
+ return html_resource
+ return js_resource
+ elif js_resource:
+ return js_resource
+ return html_resource
+
+ def LoadModule(self, module_name=None, module_filename=None,
+ excluded_scripts=None):
+ assert bool(module_name) ^ bool(module_filename), (
+ 'Must provide either module_name or module_filename.')
+ if module_filename:
+ resource = self.FindResource(module_filename)
+ if not resource:
+ raise Exception('Could not find %s in %s' % (
+ module_filename, repr(self.source_paths)))
+ module_name = resource.name
+ else:
+ resource = None # Will be set if we end up needing to load.
+
+ if module_name in self.loaded_modules:
+ assert self.loaded_modules[module_name].contents
+ return self.loaded_modules[module_name]
+
+ if not resource: # happens when module_name was given
+ resource = self.FindModuleResource(module_name)
+ if not resource:
+ raise module.DepsException('No resource for module "%s"' % module_name)
+
+ m = html_module.HTMLModule(self, module_name, resource)
+ self.loaded_modules[module_name] = m
+
+ # Fake it, this is probably either polymer.min.js or platform.js which are
+ # actually .js files....
+ if resource.absolute_path.endswith('.js'):
+ return m
+
+ m.Parse(excluded_scripts)
+ m.Load(excluded_scripts)
+ return m
+
+ def LoadRawScript(self, relative_raw_script_path):
+ resource = None
+ for source_path in self.source_paths:
+ possible_absolute_path = os.path.join(
+ source_path, os.path.normpath(relative_raw_script_path))
+ if os.path.exists(possible_absolute_path):
+ resource = resource_module.Resource(
+ source_path, possible_absolute_path)
+ break
+ if not resource:
+ raise module.DepsException(
+ 'Could not find a file for raw script %s in %s' %
+ (relative_raw_script_path, self.source_paths))
+ assert relative_raw_script_path == resource.unix_style_relative_path, (
+ 'Expected %s == %s' % (relative_raw_script_path,
+ resource.unix_style_relative_path))
+
+ if resource.absolute_path in self.loaded_raw_scripts:
+ return self.loaded_raw_scripts[resource.absolute_path]
+
+ raw_script = module.RawScript(resource)
+ self.loaded_raw_scripts[resource.absolute_path] = raw_script
+ return raw_script
+
+ def LoadStyleSheet(self, name):
+ if name in self.loaded_style_sheets:
+ return self.loaded_style_sheets[name]
+
+ resource = self._FindResourceGivenNameAndSuffix(
+ name, '.css', return_resource=True)
+ if not resource:
+ raise module.DepsException(
+ 'Could not find a file for stylesheet %s' % name)
+
+ style_sheet = style_sheet_module.StyleSheet(self, name, resource)
+ style_sheet.load()
+ self.loaded_style_sheets[name] = style_sheet
+ return style_sheet
+
+ def LoadImage(self, abs_path):
+ if abs_path in self.loaded_images:
+ return self.loaded_images[abs_path]
+
+ if not os.path.exists(abs_path):
+ raise module.DepsException("url('%s') did not exist" % abs_path)
+
+ res = self.FindResourceGivenAbsolutePath(abs_path, binary=True)
+ if res is None:
+ raise module.DepsException("url('%s') was not in search path" % abs_path)
+
+ image = style_sheet_module.Image(res)
+ self.loaded_images[abs_path] = image
+ return image
+
+ def GetStrippedJSForFilename(self, filename, early_out_if_no_py_vulcanize):
+ if filename in self.stripped_js_by_filename:
+ return self.stripped_js_by_filename[filename]
+
+ with open(filename, 'r') as f:
+ contents = f.read(4096)
+ if early_out_if_no_py_vulcanize and ('py_vulcanize' not in contents):
+ return None
+
+ s = strip_js_comments.StripJSComments(contents)
+ self.stripped_js_by_filename[filename] = s
+ return s
+
+
+def _read_file(absolute_path):
+ """Reads a file and returns a (path, contents) pair.
+
+ Args:
+ absolute_path: Absolute path to a file.
+
+ Raises:
+ Exception: The given file doesn't exist.
+ IOError: There was a problem opening or reading the file.
+ """
+ if not os.path.exists(absolute_path):
+ raise Exception('%s not found.' % absolute_path)
+ f = codecs.open(absolute_path, mode='r', encoding='utf-8')
+ contents = f.read()
+ f.close()
+ return absolute_path, contents
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource_unittest.py
new file mode 100644
index 00000000000..4da23556f24
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/resource_unittest.py
@@ -0,0 +1,17 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import unittest
+
+from py_vulcanize import resource
+
+
+class ResourceUnittest(unittest.TestCase):
+
+ def testBasic(self):
+ r = resource.Resource('/a', '/a/b/c.js')
+ self.assertEquals('b.c', r.name)
+ self.assertEquals(os.path.join('b', 'c.js'), r.relative_path)
+ self.assertEquals('b/c.js', r.unix_style_relative_path)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/strip_js_comments.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/strip_js_comments.py
new file mode 100644
index 00000000000..d63c667531a
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/strip_js_comments.py
@@ -0,0 +1,81 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility function for stripping comments out of JavaScript source code."""
+
+import re
+
+
+def _TokenizeJS(text):
+ """Splits source code text into segments in preparation for comment stripping.
+
+ Note that this doesn't tokenize for parsing. There is no notion of statements,
+ variables, etc. The only tokens of interest are comment-related tokens.
+
+ Args:
+ text: The contents of a JavaScript file.
+
+ Yields:
+ A succession of strings in the file, including all comment-related symbols.
+ """
+ rest = text
+ tokens = ['//', '/*', '*/', '\n']
+ next_tok = re.compile('|'.join(re.escape(x) for x in tokens))
+ while len(rest):
+ m = next_tok.search(rest)
+ if not m:
+ # end of string
+ yield rest
+ return
+ min_index = m.start()
+ end_index = m.end()
+
+ if min_index > 0:
+ yield rest[:min_index]
+
+ yield rest[min_index:end_index]
+ rest = rest[end_index:]
+
+
+def StripJSComments(text):
+ """Strips comments out of JavaScript source code.
+
+ Args:
+ text: JavaScript source text.
+
+ Returns:
+ JavaScript source text with comments stripped out.
+ """
+ result_tokens = []
+ token_stream = _TokenizeJS(text).__iter__()
+ while True:
+ try:
+ t = token_stream.next()
+ except StopIteration:
+ break
+
+ if t == '//':
+ while True:
+ try:
+ t2 = token_stream.next()
+ if t2 == '\n':
+ break
+ except StopIteration:
+ break
+ elif t == '/*':
+ nesting = 1
+ while True:
+ try:
+ t2 = token_stream.next()
+ if t2 == '/*':
+ nesting += 1
+ elif t2 == '*/':
+ nesting -= 1
+ if nesting == 0:
+ break
+ except StopIteration:
+ break
+ else:
+ result_tokens.append(t)
+ return ''.join(result_tokens)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/strip_js_comments_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/strip_js_comments_unittest.py
new file mode 100644
index 00000000000..685cb824a24
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/strip_js_comments_unittest.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for strip_js_comments module."""
+
+import unittest
+
+from py_vulcanize import strip_js_comments
+
+
+# This test case tests a protected method.
+# pylint: disable=W0212
+class JavaScriptStripCommentTests(unittest.TestCase):
+ """Test case for _strip_js_comments and _TokenizeJS."""
+
+ def test_strip_comments(self):
+ self.assertEquals(
+ 'A ', strip_js_comments.StripJSComments('A // foo'))
+ self.assertEquals(
+ 'A bar', strip_js_comments.StripJSComments('A // foo\nbar'))
+ self.assertEquals(
+ 'A b', strip_js_comments.StripJSComments('A /* foo */ b'))
+ self.assertEquals(
+ 'A b', strip_js_comments.StripJSComments('A /* foo\n */ b'))
+
+ def test_tokenize_empty(self):
+ tokens = list(strip_js_comments._TokenizeJS(''))
+ self.assertEquals([], tokens)
+
+ def test_tokenize_nl(self):
+ tokens = list(strip_js_comments._TokenizeJS('\n'))
+ self.assertEquals(['\n'], tokens)
+
+ def test_tokenize_slashslash_comment(self):
+ tokens = list(strip_js_comments._TokenizeJS('A // foo'))
+ self.assertEquals(['A ', '//', ' foo'], tokens)
+
+ def test_tokenize_slashslash_comment_then_newline(self):
+ tokens = list(strip_js_comments._TokenizeJS('A // foo\nbar'))
+ self.assertEquals(['A ', '//', ' foo', '\n', 'bar'], tokens)
+
+ def test_tokenize_cstyle_comment_one_line(self):
+ tokens = list(strip_js_comments._TokenizeJS('A /* foo */'))
+ self.assertEquals(['A ', '/*', ' foo ', '*/'], tokens)
+
+ def test_tokenize_cstyle_comment_multi_line(self):
+ tokens = list(strip_js_comments._TokenizeJS('A /* foo\n*bar\n*/'))
+ self.assertEquals(['A ', '/*', ' foo', '\n', '*bar', '\n', '*/'], tokens)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/style_sheet.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/style_sheet.py
new file mode 100644
index 00000000000..5338762588e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/style_sheet.py
@@ -0,0 +1,138 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import base64
+import os
+import re
+
+
+class Image(object):
+
+ def __init__(self, resource):
+ self.resource = resource
+ self.aliases = []
+
+ @property
+ def relative_path(self):
+ return self.resource.relative_path
+
+ @property
+ def absolute_path(self):
+ return self.resource.absolute_path
+
+ @property
+ def contents(self):
+ return self.resource.contents
+
+
+class ParsedStyleSheet(object):
+
+ def __init__(self, loader, containing_dirname, contents):
+ self.loader = loader
+ self.contents = contents
+ self._images = None
+ self._Load(containing_dirname)
+
+ @property
+ def images(self):
+ return self._images
+
+ def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
+ for i in self.images:
+ dependent_filenames.append(i.resource.absolute_path)
+
+ @property
+ def contents_with_inlined_images(self):
+ images_by_url = {}
+ for i in self.images:
+ for a in i.aliases:
+ images_by_url[a] = i
+
+ def InlineUrl(m):
+ url = m.group('url')
+ image = images_by_url[url]
+
+ ext = os.path.splitext(image.absolute_path)[1]
+ data = base64.standard_b64encode(image.contents)
+
+ return 'url(data:image/%s;base64,%s)' % (ext[1:], data)
+
+ # I'm assuming we only have url()'s associated with images
+ return re.sub('url\((?P<quote>"|\'|)(?P<url>[^"\'()]*)(?P=quote)\)',
+ InlineUrl, self.contents)
+
+ def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
+ for i in self.images:
+ dependent_filenames.append(i.resource.absolute_path)
+
+ def _Load(self, containing_dirname):
+ if self.contents.find('@import') != -1:
+ raise Exception('@imports are not supported')
+
+ matches = re.findall(
+ 'url\((?:["|\']?)([^"\'()]*)(?:["|\']?)\)',
+ self.contents)
+
+ def resolve_url(url):
+ if os.path.isabs(url):
+ # FIXME: module is used here, but py_vulcanize.module is never imported.
+ # However, py_vulcanize.module cannot be imported since py_vulcanize.module may import
+ # style_sheet, leading to an import loop.
+ raise module.DepsException('URL references must be relative')
+ # URLS are relative to this module's directory
+ abs_path = os.path.abspath(os.path.join(containing_dirname, url))
+ image = self.loader.LoadImage(abs_path)
+ image.aliases.append(url)
+ return image
+
+ self._images = [resolve_url(x) for x in matches]
+
+
+class StyleSheet(object):
+ """Represents a stylesheet resource referenced by a module via the
+ base.requireStylesheet(xxx) directive."""
+
+ def __init__(self, loader, name, resource):
+ self.loader = loader
+ self.name = name
+ self.resource = resource
+ self._parsed_style_sheet = None
+
+ @property
+ def filename(self):
+ return self.resource.absolute_path
+
+ @property
+ def contents(self):
+ return self.resource.contents
+
+ def __repr__(self):
+ return 'StyleSheet(%s)' % self.name
+
+ @property
+ def images(self):
+ self._InitParsedStyleSheetIfNeeded()
+ return self._parsed_style_sheet.images
+
+ def AppendDirectlyDependentFilenamesTo(self, dependent_filenames):
+ self._InitParsedStyleSheetIfNeeded()
+
+ dependent_filenames.append(self.resource.absolute_path)
+ self._parsed_style_sheet.AppendDirectlyDependentFilenamesTo(
+ dependent_filenames)
+
+ @property
+ def contents_with_inlined_images(self):
+ self._InitParsedStyleSheetIfNeeded()
+ return self._parsed_style_sheet.contents_with_inlined_images
+
+ def load(self):
+ self._InitParsedStyleSheetIfNeeded()
+
+ def _InitParsedStyleSheetIfNeeded(self):
+ if self._parsed_style_sheet:
+ return
+ module_dirname = os.path.dirname(self.resource.absolute_path)
+ self._parsed_style_sheet = ParsedStyleSheet(
+ self.loader, module_dirname, self.contents)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/style_sheet_unittest.py b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/style_sheet_unittest.py
new file mode 100644
index 00000000000..4ebc71d5651
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/py_vulcanize/style_sheet_unittest.py
@@ -0,0 +1,67 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import base64
+import os
+import unittest
+
+from py_vulcanize import project as project_module
+from py_vulcanize import resource_loader
+from py_vulcanize import fake_fs
+from py_vulcanize import module
+
+
+class StyleSheetUnittest(unittest.TestCase):
+
+ def testImages(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/src/foo/x.css', """
+.x .y {
+ background-image: url(../images/bar.jpeg);
+}
+""")
+ fs.AddFile('/src/images/bar.jpeg', 'hello world')
+ with fs:
+ project = project_module.Project([os.path.normpath('/src/')])
+ loader = resource_loader.ResourceLoader(project)
+
+ foo_x = loader.LoadStyleSheet('foo.x')
+ self.assertEquals(1, len(foo_x.images))
+
+ r0 = foo_x.images[0]
+ self.assertEquals(os.path.normpath('/src/images/bar.jpeg'),
+ r0.absolute_path)
+
+ inlined = foo_x.contents_with_inlined_images
+ self.assertEquals("""
+.x .y {
+ background-image: url(data:image/jpeg;base64,%s);
+}
+""" % base64.standard_b64encode('hello world'), inlined)
+
+ def testURLResolveFails(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/src/foo/x.css', """
+.x .y {
+ background-image: url(../images/missing.jpeg);
+}
+""")
+ with fs:
+ project = project_module.Project([os.path.normpath('/src')])
+ loader = resource_loader.ResourceLoader(project)
+
+ self.assertRaises(module.DepsException,
+ lambda: loader.LoadStyleSheet('foo.x'))
+
+ def testImportsCauseFailure(self):
+ fs = fake_fs.FakeFS()
+ fs.AddFile('/src/foo/x.css', """
+@import url(awesome.css);
+""")
+ with fs:
+ project = project_module.Project([os.path.normpath('/src')])
+ loader = resource_loader.ResourceLoader(project)
+
+ self.assertRaises(Exception,
+ lambda: loader.LoadStyleSheet('foo.x'))
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/LICENSE b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/LICENSE
new file mode 100644
index 00000000000..261eeb9e9f8
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/MANIFEST b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/MANIFEST
new file mode 100644
index 00000000000..a0384d9c1b4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/MANIFEST
@@ -0,0 +1,354 @@
+LICENSE
+MANIFEST
+PKG-INFO
+README.rst
+_setup/__init__.py
+_setup/include/cext.h
+_setup/py2/__init__.py
+_setup/py2/commands.py
+_setup/py2/data.py
+_setup/py2/dist.py
+_setup/py2/ext.py
+_setup/py2/setup.py
+_setup/py2/shell.py
+_setup/py2/term/__init__.py
+_setup/py2/term/_term.py
+_setup/py2/util.py
+_setup/py3/__init__.py
+_setup/py3/commands.py
+_setup/py3/data.py
+_setup/py3/dist.py
+_setup/py3/ext.py
+_setup/py3/setup.py
+_setup/py3/shell.py
+_setup/py3/term/__init__.py
+_setup/py3/term/_term.py
+_setup/py3/util.py
+bench
+bench.sh
+bench/LICENSE.cssmin
+bench/__init__.py
+bench/cssmin.py
+bench/main.py
+bench/wikipedia.css
+bench/wikipedia.min.css
+bench/write.py
+docs/BENCHMARKS
+docs/CHANGES
+docs/CLASSIFIERS
+docs/DESCRIPTION
+docs/PROVIDES
+docs/SUMMARY
+docs/apidoc/api-objects.txt
+docs/apidoc/crarr.png
+docs/apidoc/epydoc.css
+docs/apidoc/epydoc.js
+docs/apidoc/help.html
+docs/apidoc/identifier-index.html
+docs/apidoc/index.html
+docs/apidoc/module-tree.html
+docs/apidoc/rcssmin-module.html
+docs/apidoc/rcssmin-pysrc.html
+docs/apidoc/redirect.html
+package.cfg
+rcssmin.c
+rcssmin.py
+run_tests.py
+setup.py
+tests
+tests/main/atgroup_00.css
+tests/main/atgroup_01.css
+tests/main/atgroup_02.css
+tests/main/atgroup_03.css
+tests/main/atgroup_04.css
+tests/main/atgroup_05.css
+tests/main/atgroup_06.css
+tests/main/atgroup_07.css
+tests/main/atgroup_08.css
+tests/main/atgroup_09.css
+tests/main/atgroup_10.css
+tests/main/atgroup_11.css
+tests/main/comment_00.css
+tests/main/comment_01.css
+tests/main/comment_02.css
+tests/main/comment_03.css
+tests/main/comment_04.css
+tests/main/escape_00.css
+tests/main/escape_01.css
+tests/main/escape_02.css
+tests/main/escape_03.css
+tests/main/escape_04.css
+tests/main/escape_05.css
+tests/main/escape_06.css
+tests/main/first_00.css
+tests/main/first_01.css
+tests/main/first_02.css
+tests/main/out/atgroup_00.out
+tests/main/out/atgroup_00.out.b
+tests/main/out/atgroup_01.out
+tests/main/out/atgroup_01.out.b
+tests/main/out/atgroup_02.out
+tests/main/out/atgroup_02.out.b
+tests/main/out/atgroup_03.out
+tests/main/out/atgroup_03.out.b
+tests/main/out/atgroup_04.out
+tests/main/out/atgroup_04.out.b
+tests/main/out/atgroup_05.out
+tests/main/out/atgroup_05.out.b
+tests/main/out/atgroup_06.out
+tests/main/out/atgroup_06.out.b
+tests/main/out/atgroup_07.out
+tests/main/out/atgroup_07.out.b
+tests/main/out/atgroup_08.out
+tests/main/out/atgroup_08.out.b
+tests/main/out/atgroup_09.out
+tests/main/out/atgroup_09.out.b
+tests/main/out/atgroup_10.out
+tests/main/out/atgroup_10.out.b
+tests/main/out/atgroup_11.out
+tests/main/out/atgroup_11.out.b
+tests/main/out/comment_00.out
+tests/main/out/comment_00.out.b
+tests/main/out/comment_01.out
+tests/main/out/comment_01.out.b
+tests/main/out/comment_02.out
+tests/main/out/comment_02.out.b
+tests/main/out/comment_03.out
+tests/main/out/comment_03.out.b
+tests/main/out/comment_04.out
+tests/main/out/comment_04.out.b
+tests/main/out/escape_00.out
+tests/main/out/escape_00.out.b
+tests/main/out/escape_01.out
+tests/main/out/escape_01.out.b
+tests/main/out/escape_02.out
+tests/main/out/escape_02.out.b
+tests/main/out/escape_03.out
+tests/main/out/escape_03.out.b
+tests/main/out/escape_04.out
+tests/main/out/escape_04.out.b
+tests/main/out/escape_05.out
+tests/main/out/escape_05.out.b
+tests/main/out/escape_06.out
+tests/main/out/escape_06.out.b
+tests/main/out/first_00.out
+tests/main/out/first_00.out.b
+tests/main/out/first_01.out
+tests/main/out/first_01.out.b
+tests/main/out/first_02.out
+tests/main/out/first_02.out.b
+tests/main/out/url_00.out
+tests/main/out/url_00.out.b
+tests/main/out/url_01.out
+tests/main/out/url_01.out.b
+tests/main/out/url_02.out
+tests/main/out/url_02.out.b
+tests/main/out/url_03.out
+tests/main/out/url_03.out.b
+tests/main/out/url_04.out
+tests/main/out/url_04.out.b
+tests/main/out/url_05.out
+tests/main/out/url_05.out.b
+tests/main/out/url_06.out
+tests/main/out/url_06.out.b
+tests/main/out/url_07.out
+tests/main/out/url_07.out.b
+tests/main/out/url_08.out
+tests/main/out/url_08.out.b
+tests/main/out/url_09.out
+tests/main/out/url_09.out.b
+tests/main/url_00.css
+tests/main/url_01.css
+tests/main/url_02.css
+tests/main/url_03.css
+tests/main/url_04.css
+tests/main/url_05.css
+tests/main/url_06.css
+tests/main/url_07.css
+tests/main/url_08.css
+tests/main/url_09.css
+tests/yui/README
+tests/yui/background-position.css
+tests/yui/background-position.css.min
+tests/yui/border-none.css
+tests/yui/border-none.css.min
+tests/yui/box-model-hack.css
+tests/yui/box-model-hack.css.min
+tests/yui/bug2527974.css
+tests/yui/bug2527974.css.min
+tests/yui/bug2527991.css
+tests/yui/bug2527991.css.min
+tests/yui/bug2527998.css
+tests/yui/bug2527998.css.min
+tests/yui/bug2528034.css
+tests/yui/bug2528034.css.min
+tests/yui/charset-media.css
+tests/yui/charset-media.css.min
+tests/yui/color-simple.css
+tests/yui/color-simple.css.min
+tests/yui/color.css
+tests/yui/color.css.min
+tests/yui/comment.css
+tests/yui/comment.css.min
+tests/yui/concat-charset.css
+tests/yui/concat-charset.css.min
+tests/yui/dataurl-base64-doublequotes.css
+tests/yui/dataurl-base64-doublequotes.css.min
+tests/yui/dataurl-base64-eof.css
+tests/yui/dataurl-base64-eof.css.min
+tests/yui/dataurl-base64-linebreakindata.css
+tests/yui/dataurl-base64-linebreakindata.css.min
+tests/yui/dataurl-base64-noquotes.css
+tests/yui/dataurl-base64-noquotes.css.min
+tests/yui/dataurl-base64-singlequotes.css
+tests/yui/dataurl-base64-singlequotes.css.min
+tests/yui/dataurl-base64-twourls.css
+tests/yui/dataurl-base64-twourls.css.min
+tests/yui/dataurl-dbquote-font.css
+tests/yui/dataurl-dbquote-font.css.min
+tests/yui/dataurl-nonbase64-doublequotes.css
+tests/yui/dataurl-nonbase64-doublequotes.css.min
+tests/yui/dataurl-nonbase64-noquotes.css
+tests/yui/dataurl-nonbase64-noquotes.css.min
+tests/yui/dataurl-nonbase64-singlequotes.css
+tests/yui/dataurl-nonbase64-singlequotes.css.min
+tests/yui/dataurl-noquote-multiline-font.css
+tests/yui/dataurl-noquote-multiline-font.css.min
+tests/yui/dataurl-realdata-doublequotes.css
+tests/yui/dataurl-realdata-doublequotes.css.min
+tests/yui/dataurl-realdata-noquotes.css
+tests/yui/dataurl-realdata-noquotes.css.min
+tests/yui/dataurl-realdata-singlequotes.css
+tests/yui/dataurl-realdata-singlequotes.css.min
+tests/yui/dataurl-realdata-yuiapp.css
+tests/yui/dataurl-realdata-yuiapp.css.min
+tests/yui/dataurl-singlequote-font.css
+tests/yui/dataurl-singlequote-font.css.min
+tests/yui/decimals.css
+tests/yui/decimals.css.min
+tests/yui/dollar-header.css
+tests/yui/dollar-header.css.min
+tests/yui/font-face.css
+tests/yui/font-face.css.min
+tests/yui/ie5mac.css
+tests/yui/ie5mac.css.min
+tests/yui/media-empty-class.css
+tests/yui/media-empty-class.css.min
+tests/yui/media-multi.css
+tests/yui/media-multi.css.min
+tests/yui/media-test.css
+tests/yui/media-test.css.min
+tests/yui/opacity-filter.css
+tests/yui/opacity-filter.css.min
+tests/yui/out/background-position.out
+tests/yui/out/background-position.out.b
+tests/yui/out/border-none.out
+tests/yui/out/border-none.out.b
+tests/yui/out/box-model-hack.out
+tests/yui/out/box-model-hack.out.b
+tests/yui/out/bug2527974.out
+tests/yui/out/bug2527974.out.b
+tests/yui/out/bug2527991.out
+tests/yui/out/bug2527991.out.b
+tests/yui/out/bug2527998.out
+tests/yui/out/bug2527998.out.b
+tests/yui/out/bug2528034.out
+tests/yui/out/bug2528034.out.b
+tests/yui/out/charset-media.out
+tests/yui/out/charset-media.out.b
+tests/yui/out/color-simple.out
+tests/yui/out/color-simple.out.b
+tests/yui/out/color.out
+tests/yui/out/color.out.b
+tests/yui/out/comment.out
+tests/yui/out/comment.out.b
+tests/yui/out/concat-charset.out
+tests/yui/out/concat-charset.out.b
+tests/yui/out/dataurl-base64-doublequotes.out
+tests/yui/out/dataurl-base64-doublequotes.out.b
+tests/yui/out/dataurl-base64-eof.out
+tests/yui/out/dataurl-base64-eof.out.b
+tests/yui/out/dataurl-base64-linebreakindata.out
+tests/yui/out/dataurl-base64-linebreakindata.out.b
+tests/yui/out/dataurl-base64-noquotes.out
+tests/yui/out/dataurl-base64-noquotes.out.b
+tests/yui/out/dataurl-base64-singlequotes.out
+tests/yui/out/dataurl-base64-singlequotes.out.b
+tests/yui/out/dataurl-base64-twourls.out
+tests/yui/out/dataurl-base64-twourls.out.b
+tests/yui/out/dataurl-dbquote-font.out
+tests/yui/out/dataurl-dbquote-font.out.b
+tests/yui/out/dataurl-nonbase64-doublequotes.out
+tests/yui/out/dataurl-nonbase64-doublequotes.out.b
+tests/yui/out/dataurl-nonbase64-noquotes.out
+tests/yui/out/dataurl-nonbase64-noquotes.out.b
+tests/yui/out/dataurl-nonbase64-singlequotes.out
+tests/yui/out/dataurl-nonbase64-singlequotes.out.b
+tests/yui/out/dataurl-noquote-multiline-font.out
+tests/yui/out/dataurl-noquote-multiline-font.out.b
+tests/yui/out/dataurl-realdata-doublequotes.out
+tests/yui/out/dataurl-realdata-doublequotes.out.b
+tests/yui/out/dataurl-realdata-noquotes.out
+tests/yui/out/dataurl-realdata-noquotes.out.b
+tests/yui/out/dataurl-realdata-singlequotes.out
+tests/yui/out/dataurl-realdata-singlequotes.out.b
+tests/yui/out/dataurl-realdata-yuiapp.out
+tests/yui/out/dataurl-realdata-yuiapp.out.b
+tests/yui/out/dataurl-singlequote-font.out
+tests/yui/out/dataurl-singlequote-font.out.b
+tests/yui/out/decimals.out
+tests/yui/out/decimals.out.b
+tests/yui/out/dollar-header.out
+tests/yui/out/dollar-header.out.b
+tests/yui/out/font-face.out
+tests/yui/out/font-face.out.b
+tests/yui/out/ie5mac.out
+tests/yui/out/ie5mac.out.b
+tests/yui/out/media-empty-class.out
+tests/yui/out/media-empty-class.out.b
+tests/yui/out/media-multi.out
+tests/yui/out/media-multi.out.b
+tests/yui/out/media-test.out
+tests/yui/out/media-test.out.b
+tests/yui/out/opacity-filter.out
+tests/yui/out/opacity-filter.out.b
+tests/yui/out/preserve-case.out
+tests/yui/out/preserve-case.out.b
+tests/yui/out/preserve-new-line.out
+tests/yui/out/preserve-new-line.out.b
+tests/yui/out/preserve-strings.out
+tests/yui/out/preserve-strings.out.b
+tests/yui/out/pseudo-first.out
+tests/yui/out/pseudo-first.out.b
+tests/yui/out/pseudo.out
+tests/yui/out/pseudo.out.b
+tests/yui/out/special-comments.out
+tests/yui/out/special-comments.out.b
+tests/yui/out/star-underscore-hacks.out
+tests/yui/out/star-underscore-hacks.out.b
+tests/yui/out/string-in-comment.out
+tests/yui/out/string-in-comment.out.b
+tests/yui/out/webkit-transform.out
+tests/yui/out/webkit-transform.out.b
+tests/yui/out/zeros.out
+tests/yui/out/zeros.out.b
+tests/yui/preserve-case.css
+tests/yui/preserve-case.css.min
+tests/yui/preserve-new-line.css
+tests/yui/preserve-new-line.css.min
+tests/yui/preserve-strings.css
+tests/yui/preserve-strings.css.min
+tests/yui/pseudo-first.css
+tests/yui/pseudo-first.css.min
+tests/yui/pseudo.css
+tests/yui/pseudo.css.min
+tests/yui/special-comments.css
+tests/yui/special-comments.css.min
+tests/yui/star-underscore-hacks.css
+tests/yui/star-underscore-hacks.css.min
+tests/yui/string-in-comment.css
+tests/yui/string-in-comment.css.min
+tests/yui/webkit-transform.css
+tests/yui/webkit-transform.css.min
+tests/yui/zeros.css
+tests/yui/zeros.css.min
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/PKG-INFO b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/PKG-INFO
new file mode 100644
index 00000000000..d4ee866c986
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/PKG-INFO
@@ -0,0 +1,316 @@
+Metadata-Version: 1.1
+Name: rcssmin
+Version: 1.0.5
+Summary: CSS Minifier
+Home-page: http://opensource.perlig.de/rcssmin/
+Author: André Malo
+Author-email: nd@perlig.de
+License: Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+Download-URL: http://storage.perlig.de/rcssmin/
+Description: ==============
+ CSS Minifier
+ ==============
+
+ RCSSmin is a CSS minifier.
+
+ The minifier is based on the semantics of the `YUI compressor`_\, which itself
+ is based on `the rule list by Isaac Schlueter`_\.
+
+ This module is a re-implementation aiming for speed instead of maximum
+ compression, so it can be used at runtime (rather than during a preprocessing
+ step). RCSSmin does syntactical compression only (removing spaces, comments
+ and possibly semicolons). It does not provide semantic compression (like
+ removing empty blocks, collapsing redundant properties etc). It does, however,
+ support various CSS hacks (by keeping them working as intended).
+
+ Here's a feature list:
+
+ - Strings are kept, except that escaped newlines are stripped
+ - Space/Comments before the very end or before various characters are
+ stripped: ``:{});=>+],!`` (The colon (``:``) is a special case, a single
+ space is kept if it's outside a ruleset.)
+ - Space/Comments at the very beginning or after various characters are
+ stripped: ``{}(=:>+[,!``
+ - Optional space after unicode escapes is kept, resp. replaced by a simple
+ space
+ - whitespaces inside ``url()`` definitions are stripped
+ - Comments starting with an exclamation mark (``!``) can be kept optionally.
+ - All other comments and/or whitespace characters are replaced by a single
+ space.
+ - Multiple consecutive semicolons are reduced to one
+ - The last semicolon within a ruleset is stripped
+ - CSS Hacks supported:
+
+ - IE7 hack (``>/**/``)
+ - Mac-IE5 hack (``/*\*/.../**/``)
+ - The boxmodelhack is supported naturally because it relies on valid CSS2
+ strings
+ - Between ``:first-line`` and the following comma or curly brace a space is
+ inserted. (apparently it's needed for IE6)
+ - Same for ``:first-letter``
+
+ rcssmin.c is a reimplementation of rcssmin.py in C and improves runtime up to
+ factor 100 or so (depending on the input). docs/BENCHMARKS in the source
+ distribution contains the details.
+
+ Both python 2 (>= 2.4) and python 3 are supported.
+
+ .. _YUI compressor: https://github.com/yui/yuicompressor/
+
+ .. _the rule list by Isaac Schlueter: https://github.com/isaacs/cssmin/
+
+
+ Copyright and License
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ Copyright 2011 - 2014
+ André Malo or his licensors, as applicable.
+
+ The whole package (except for the files in the bench/ directory) is
+ distributed under the Apache License Version 2.0. You'll find a copy in the
+ root directory of the distribution or online at:
+ <http://www.apache.org/licenses/LICENSE-2.0>.
+
+
+ Bugs
+ ~~~~
+
+ No bugs, of course. ;-)
+ But if you've found one or have an idea how to improve rcssmin, feel free
+ to send a pull request on `github <https://github.com/ndparker/rcssmin>`_
+ or send a mail to <rcssmin-bugs@perlig.de>.
+
+
+ Author Information
+ ~~~~~~~~~~~~~~~~~~
+
+ André "nd" Malo <nd perlig.de>
+ GPG: 0x8103A37E
+
+
+ If God intended people to be naked, they would be born that way.
+ -- Oscar Wilde
+
+ .. vim:tw=72 syntax=rest
+Keywords: CSS,Minimization
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved
+Classifier: License :: OSI Approved :: Apache License, Version 2.0
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: Jython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Text Processing
+Classifier: Topic :: Text Processing :: Filters
+Classifier: Topic :: Utilities
+Provides: rcssmin (1.0)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/README.chromium b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/README.chromium
new file mode 100644
index 00000000000..b1350fc9fa4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/README.chromium
@@ -0,0 +1,16 @@
+Name: rCSSmin
+Short Name: rcssmin
+URL: http://opensource.perlig.de/rcssmin/
+Version: 1.0.5
+License: Apache 2.0
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+rCSSmin is a CSS minifier written in python.
+The minifier is based on the semantics of the YUI compressor, which itself is
+based on the rule list by Isaac Schlueter.
+
+Modifications made:
+ - Removed the bench.sh since the file doesn't have the licensing info and
+ caused license checker to fail.
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/README.rst b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/README.rst
new file mode 100644
index 00000000000..95fb3083a89
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/README.rst
@@ -0,0 +1,153 @@
+.. -*- coding: utf-8 -*-
+
+=====================================
+ rCSSmin - A CSS Minifier For Python
+=====================================
+
+TABLE OF CONTENTS
+-----------------
+
+1. Introduction
+2. Copyright and License
+3. System Requirements
+4. Installation
+5. Documentation
+6. Bugs
+7. Author Information
+
+
+INTRODUCTION
+------------
+
+RCSSmin is a CSS minifier written in python.
+
+The minifier is based on the semantics of the `YUI compressor`_\, which itself
+is based on `the rule list by Isaac Schlueter`_\.
+
+This module is a re-implementation aiming for speed instead of maximum
+compression, so it can be used at runtime (rather than during a preprocessing
+step). RCSSmin does syntactical compression only (removing spaces, comments
+and possibly semicolons). It does not provide semantic compression (like
+removing empty blocks, collapsing redundant properties etc). It does, however,
+support various CSS hacks (by keeping them working as intended).
+
+Here's a feature list:
+
+- Strings are kept, except that escaped newlines are stripped
+- Space/Comments before the very end or before various characters are
+ stripped: ``:{});=>+],!`` (The colon (``:``) is a special case, a single
+ space is kept if it's outside a ruleset.)
+- Space/Comments at the very beginning or after various characters are
+ stripped: ``{}(=:>+[,!``
+- Optional space after unicode escapes is kept, resp. replaced by a simple
+ space
+- whitespaces inside ``url()`` definitions are stripped
+- Comments starting with an exclamation mark (``!``) can be kept optionally.
+- All other comments and/or whitespace characters are replaced by a single
+ space.
+- Multiple consecutive semicolons are reduced to one
+- The last semicolon within a ruleset is stripped
+- CSS Hacks supported:
+
+ - IE7 hack (``>/**/``)
+ - Mac-IE5 hack (``/*\*/.../**/``)
+ - The boxmodelhack is supported naturally because it relies on valid CSS2
+ strings
+ - Between ``:first-line`` and the following comma or curly brace a space is
+ inserted. (apparently it's needed for IE6)
+ - Same for ``:first-letter``
+
+rcssmin.c is a reimplementation of rcssmin.py in C and improves runtime up to
+factor 100 or so (depending on the input). docs/BENCHMARKS in the source
+distribution contains the details.
+
+.. _YUI compressor: https://github.com/yui/yuicompressor/
+
+.. _the rule list by Isaac Schlueter: https://github.com/isaacs/cssmin/
+
+
+COPYRIGHT AND LICENSE
+---------------------
+
+Copyright 2011 - 2014
+André Malo or his licensors, as applicable.
+
+The whole package (except for the files in the bench/ directory)
+is distributed under the Apache License Version 2.0. You'll find a copy in the
+root directory of the distribution or online at:
+<http://www.apache.org/licenses/LICENSE-2.0>.
+
+
+SYSTEM REQUIREMENTS
+-------------------
+
+Both python 2 (>=2.4) and python 3 are supported.
+
+
+INSTALLATION
+------------
+
+Using pip
+~~~~~~~~~
+
+$ pip install rcssmin
+
+
+Using distutils
+~~~~~~~~~~~~~~~
+
+$ python setup.py install
+
+The following extra options to the install command may be of interest:
+
+ --without-c-extensions Don't install C extensions
+ --without-docs Do not install documentation files
+
+
+Drop-in
+~~~~~~~
+
+rCSSmin effectively consists of two files: rcssmin.py and rcssmin.c, the
+latter being entirely optional. So, for simple integration you can just
+copy rcssmin.py into your project and use it.
+
+
+DOCUMENTATION
+-------------
+
+A generated API documentation is available in the docs/apidoc/ directory.
+But you can just look into the module. It provides a simple function,
+called cssmin which takes the CSS as a string and returns the minified
+CSS as a string.
+
+The module additionally provides a "streamy" interface:
+
+$ python -mrcssmin <css >minified
+
+It takes two options:
+
+ -b Keep bang-comments (Comments starting with an exclamation mark)
+ -p Force using the python implementation (not the C implementation)
+
+The latest documentation is also available online at
+<http://opensource.perlig.de/rcssmin/>.
+
+
+BUGS
+----
+
+No bugs, of course. ;-)
+But if you've found one or have an idea how to improve rcssmin, feel free to
+send a pull request on `github <https://github.com/ndparker/rcssmin>`_ or
+send a mail to <rcssmin-bugs@perlig.de>.
+
+
+AUTHOR INFORMATION
+------------------
+
+André "nd" Malo <nd@perlig.de>
+GPG: 0x8103A37E
+
+
+ If God intended people to be naked, they would be born that way.
+ -- Oscar Wilde
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/__init__.py
new file mode 100644
index 00000000000..77dc23c8412
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/__init__.py
@@ -0,0 +1,39 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ Package _setup
+================
+
+This package provides tools for main package setup.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import os as _os
+import sys as _sys
+
+if _sys.version_info[0] == 2:
+ __path__ = [_os.path.join(__path__[0], 'py2')]
+ __author__ = __author__.decode('latin-1')
+elif _sys.version_info[0] == 3:
+ __path__ = [_os.path.join(__path__[0], 'py3')]
+else:
+ raise RuntimeError("Unsupported python version")
+del _os, _sys
+
+from _setup.setup import run # pylint: disable = W0611
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/include/cext.h b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/include/cext.h
new file mode 100644
index 00000000000..47b6f5b9c11
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/include/cext.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2006 - 2014
+ * Andr\xe9 Malo or his licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * central naming stuff
+ */
+
+#ifndef SETUP_CEXT_H
+#define SETUP_CEXT_H
+
+#ifndef EXT_MODULE
+#error EXT_MODULE must be defined outside of this file (-DEXT_MODULE=...)
+#endif
+
+/*
+ * include core header files
+ */
+#define PY_SSIZE_T_CLEAN
+
+#include "Python.h"
+#include "structmember.h"
+
+/*
+ * define our helper macros depending on the stuff above
+ */
+#define STRINGIFY(n) STRINGIFY_HELPER(n)
+#define STRINGIFY_HELPER(n) #n
+#define CONCATENATE(first, second) CONCATENATE_HELPER(first, second)
+#define CONCATENATE_HELPER(first, second) first##second
+
+#define EXT_MODULE_NAME STRINGIFY(EXT_MODULE)
+#ifdef EXT_PACKAGE
+#define EXT_PACKAGE_NAME STRINGIFY(EXT_PACKAGE)
+#define EXT_MODULE_PATH EXT_PACKAGE_NAME "." EXT_MODULE_NAME
+#else
+#define EXT_PACKAGE_NAME ""
+#define EXT_MODULE_PATH EXT_MODULE_NAME
+#endif
+
+#define EXT_DOCS_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, __doc__))
+#define EXT_METHODS_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, _methods))
+#define EXT_METHODS static PyMethodDef EXT_METHODS_VAR[]
+
+#define EXT_DEFINE_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, _module))
+
+/* Py3K Support */
+#if PY_MAJOR_VERSION >= 3
+
+#define EXT3
+
+#ifndef PyMODINIT_FUNC
+#define EXT_INIT_FUNC PyObject *CONCATENATE(PyInit_, EXT_MODULE)(void)
+#else
+#define EXT_INIT_FUNC PyMODINIT_FUNC CONCATENATE(PyInit_, EXT_MODULE)(void)
+#endif
+
+#define EXT_DEFINE(name, methods, doc) \
+static struct PyModuleDef EXT_DEFINE_VAR = { \
+ PyModuleDef_HEAD_INIT, \
+ name, \
+ doc, \
+ -1, \
+ methods, \
+ NULL, \
+ NULL, \
+ NULL, \
+ NULL \
+}
+
+#define EXT_CREATE(def) (PyModule_Create(def))
+#define EXT_INIT_ERROR(module) do {Py_XDECREF(module); return NULL;} while(0)
+#define EXT_INIT_RETURN(module) return module
+
+#else /* end py3k */
+
+#define EXT2
+
+#ifndef PyMODINIT_FUNC
+#define EXT_INIT_FUNC void CONCATENATE(init, EXT_MODULE)(void)
+#else
+#define EXT_INIT_FUNC PyMODINIT_FUNC CONCATENATE(init, EXT_MODULE)(void)
+#endif
+
+#define EXT_DEFINE__STRUCT \
+ CONCATENATE(struct, CONCATENATE(EXT_MODULE, _module))
+
+struct EXT_DEFINE__STRUCT {
+ char *m_name;
+ char *m_doc;
+ PyMethodDef *m_methods;
+};
+#define EXT_DEFINE(name, methods, doc) \
+static struct EXT_DEFINE__STRUCT EXT_DEFINE_VAR = { \
+ name, \
+ doc, \
+ methods \
+}
+
+#define EXT_CREATE(def) ((def)->m_doc \
+ ? Py_InitModule3((def)->m_name, (def)->m_methods, (def)->m_doc) \
+ : Py_InitModule((def)->m_name, (def)->m_methods) \
+)
+#define EXT_INIT_ERROR(module) return
+#define EXT_INIT_RETURN(module) return
+
+#endif /* end py2K */
+
+#define EXT_INIT_TYPE(module, type) do { \
+ if (PyType_Ready(type) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+#define EXT_ADD_TYPE(module, name, type) do { \
+ Py_INCREF(type); \
+ if (PyModule_AddObject(module, name, (PyObject *)(type)) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+#define EXT_ADD_UNICODE(module, name, string, encoding) do { \
+ if (PyModule_AddObject( \
+ module, \
+ name, \
+ PyUnicode_Decode( \
+ string, \
+ sizeof(string) - 1, \
+ encoding, \
+ "strict" \
+ )) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+#define EXT_ADD_STRING(module, name, string) do { \
+ if (PyModule_AddStringConstant(module, name, string) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+#define EXT_ADD_INT(module, name, number) do { \
+ if (PyModule_AddIntConstant(module, name, number) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+
+/* PEP 353 support, implemented as of python 2.5 */
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#define PyInt_FromSsize_t(arg) PyInt_FromLong((long)arg)
+#define PyInt_AsSsize_t(arg) (int)PyInt_AsLong(arg)
+#define PY_SSIZE_T_MAX ((Py_ssize_t)INT_MAX)
+#endif
+
+/*
+ * some helper macros (Python 2.4)
+ */
+#ifndef Py_VISIT
+#define Py_VISIT(op) do { \
+ if (op) { \
+ int vret = visit((op), arg); \
+ if (vret) return vret; \
+ } \
+} while (0)
+#endif
+
+#ifdef Py_CLEAR
+#undef Py_CLEAR
+#endif
+#define Py_CLEAR(op) do { \
+ if (op) { \
+ PyObject *tmp__ = (PyObject *)(op); \
+ (op) = NULL; \
+ Py_DECREF(tmp__); \
+ } \
+} while (0)
+
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
+#endif
+
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
+#endif
+
+/* Macros for inline documentation. (Python 2.3) */
+#ifndef PyDoc_VAR
+#define PyDoc_VAR(name) static char name[]
+#endif
+
+#ifndef PyDoc_STRVAR
+#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str)
+#endif
+
+#ifndef PyDoc_STR
+#ifdef WITH_DOC_STRINGS
+#define PyDoc_STR(str) str
+#else
+#define PyDoc_STR(str) ""
+#endif
+#endif
+
+/* Basestring check (basestring introduced in Python 2.3) */
+#if PY_VERSION_HEX < 0x02030000
+#define BaseString_Check(type) ( \
+ PyObject_TypeCheck((type), &PyString_Type) \
+ || PyObject_TypeCheck((type), &PyUnicode_Type) \
+)
+#else
+#define BaseString_Check(type) PyObject_TypeCheck((type), &PyBaseString_Type)
+#endif
+
+#define GENERIC_ALLOC(type) \
+ ((void *)((PyTypeObject *)type)->tp_alloc(type, (Py_ssize_t)0))
+
+/* PyPy doesn't define it */
+#ifndef PyType_IS_GC
+#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
+#endif
+
+#define DEFINE_GENERIC_DEALLOC(prefix) \
+static void prefix##_dealloc(void *self) \
+{ \
+ if (PyType_IS_GC(((PyObject *)self)->ob_type)) \
+ PyObject_GC_UnTrack(self); \
+ (void)prefix##_clear(self); \
+ ((PyObject *)self)->ob_type->tp_free((PyObject *)self); \
+}
+
+#endif /* SETUP_CEXT_H */
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/__init__.py
new file mode 100644
index 00000000000..9582ecc1087
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/__init__.py
@@ -0,0 +1,27 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ Package _setup
+================
+
+This package provides tools for main package setup.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from _setup.setup import run # pylint: disable = W0611
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/commands.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/commands.py
new file mode 100644
index 00000000000..a41b166e0a5
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/commands.py
@@ -0,0 +1,267 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Command extenders
+===================
+
+Command extenders.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+__test__ = False
+
+from distutils import fancy_getopt as _fancy_getopt
+from distutils.command import build as _build
+from distutils.command import build_ext as _build_ext
+from distutils.command import install as _install
+from distutils.command import install_data as _install_data
+from distutils.command import install_lib as _install_lib
+import os as _os
+
+from _setup.util import log
+
+_option_defaults = {}
+_option_inherits = {}
+_option_finalizers = {}
+_command_mapping = {
+ 'install': 'Install',
+ 'install_data': 'InstallData',
+ 'install_lib': 'InstallLib',
+ 'build': 'Build',
+ 'build_ext': 'BuildExt',
+}
+
+
+def add_option(command, long_name, help_text, short_name=None, default=None,
+ inherit=None):
+ """ Add an option """
+ try:
+ command_class = globals()[_command_mapping[command]]
+ except KeyError:
+ raise ValueError("Unknown command %r" % (command,))
+ for opt in command_class.user_options:
+ if opt[0] == long_name:
+ break
+ else:
+ opt = (long_name, short_name, help_text)
+ command_class.user_options.append(opt)
+ if not long_name.endswith('='):
+ command_class.boolean_options.append(long_name)
+ attr_name = _fancy_getopt.translate_longopt(long_name)
+ else:
+ attr_name = _fancy_getopt.translate_longopt(long_name[:-1])
+ if not _option_defaults.has_key(command):
+ _option_defaults[command] = []
+ if inherit is not None:
+ if isinstance(inherit, (str, unicode)):
+ inherit = [inherit]
+ for i_inherit in inherit:
+ add_option(
+ i_inherit, long_name, help_text, short_name, default
+ )
+ default = None
+ if not _option_inherits.has_key(command):
+ _option_inherits[command] = []
+ for i_inherit in inherit:
+ for i_command, opt_name in _option_inherits[command]:
+ if i_command == i_inherit and opt_name == attr_name:
+ break
+ else:
+ _option_inherits[command].append((i_inherit, attr_name))
+ _option_defaults[command].append((attr_name, default))
+
+
+def add_finalizer(command, key, func):
+ """ Add finalizer """
+ if not _option_finalizers.has_key(command):
+ _option_finalizers[command] = {}
+ if not _option_finalizers[command].has_key(key):
+ _option_finalizers[command][key] = func
+
+
+class Install(_install.install):
+ """ Extended installer to reflect the additional data options """
+ user_options = _install.install.user_options + [
+ ('single-version-externally-managed', None,
+ "Compat option. Does not a thing."),
+ ]
+ boolean_options = _install.install.boolean_options + [
+ 'single-version-externally-managed'
+ ]
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install.install.initialize_options(self)
+ self.single_version_externally_managed = None
+ if _option_defaults.has_key('install'):
+ for opt_name, default in _option_defaults['install']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install.install.finalize_options(self)
+ if _option_inherits.has_key('install'):
+ for parent, opt_name in _option_inherits['install']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('install'):
+ for func in _option_finalizers['install'].values():
+ func(self)
+
+
+class InstallData(_install_data.install_data):
+ """ Extended data installer """
+ user_options = _install_data.install_data.user_options + []
+ boolean_options = _install_data.install_data.boolean_options + []
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install_data.install_data.initialize_options(self)
+ if _option_defaults.has_key('install_data'):
+ for opt_name, default in _option_defaults['install_data']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install_data.install_data.finalize_options(self)
+ if _option_inherits.has_key('install_data'):
+ for parent, opt_name in _option_inherits['install_data']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('install_data'):
+ for func in _option_finalizers['install_data'].values():
+ func(self)
+
+
+class InstallLib(_install_lib.install_lib):
+ """ Extended lib installer """
+ user_options = _install_lib.install_lib.user_options + []
+ boolean_options = _install_lib.install_lib.boolean_options + []
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install_lib.install_lib.initialize_options(self)
+ if _option_defaults.has_key('install_lib'):
+ for opt_name, default in _option_defaults['install_lib']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install_lib.install_lib.finalize_options(self)
+ if _option_inherits.has_key('install_lib'):
+ for parent, opt_name in _option_inherits['install_lib']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('install_lib'):
+ for func in _option_finalizers['install_lib'].values():
+ func(self)
+
+
+class BuildExt(_build_ext.build_ext):
+ """
+ Extended extension builder class
+
+ This class allows extensions to provide a ``check_prerequisites`` method
+ which is called before actually building it. The method takes the
+ `BuildExt` instance and returns whether the extension should be skipped or
+ not.
+ """
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _build_ext.build_ext.initialize_options(self)
+ if _option_defaults.has_key('build_ext'):
+ for opt_name, default in _option_defaults['build_ext']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _build_ext.build_ext.finalize_options(self)
+ if _option_inherits.has_key('build_ext'):
+ for parent, opt_name in _option_inherits['build_ext']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('build_ext'):
+ for func in _option_finalizers['build_ext'].values():
+ func(self)
+
+ def build_extension(self, ext):
+ """
+ Build C extension - with extended functionality
+
+ The following features are added here:
+
+ - ``ext.check_prerequisites`` is called before the extension is being
+ built. See `Extension` for details. If the method does not exist,
+ simply no check will be run.
+ - The macros ``EXT_PACKAGE`` and ``EXT_MODULE`` will be filled (or
+ unset) depending on the extensions name, but only if they are not
+ already defined.
+
+ :Parameters:
+ `ext` : `Extension`
+ The extension to build. If it's a pure
+ ``distutils.core.Extension``, simply no prequisites check is
+ applied.
+
+ :Return: whatever ``distutils.command.build_ext.build_ext`` returns
+ :Rtype: any
+ """
+ # handle name macros
+ macros = dict(ext.define_macros or ())
+ tup = ext.name.split('.')
+ if len(tup) == 1:
+ pkg, mod = None, tup[0]
+ else:
+ pkg, mod = '.'.join(tup[:-1]), tup[-1]
+ if pkg is not None and 'EXT_PACKAGE' not in macros:
+ ext.define_macros.append(('EXT_PACKAGE', pkg))
+ if 'EXT_MODULE' not in macros:
+ ext.define_macros.append(('EXT_MODULE', mod))
+ if pkg is None:
+ macros = dict(ext.undef_macros or ())
+ if 'EXT_PACKAGE' not in macros:
+ ext.undef_macros.append('EXT_PACKAGE')
+
+ # handle prereq checks
+ try:
+ checker = ext.check_prerequisites
+ except AttributeError:
+ pass
+ else:
+ if checker(self):
+ log.info("Skipping %s extension" % ext.name)
+ return
+
+ return _build_ext.build_ext.build_extension(self, ext)
+
+
+class Build(_build.build):
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _build.build.initialize_options(self)
+ if _option_defaults.has_key('build'):
+ for opt_name, default in _option_defaults['build']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _build.build.finalize_options(self)
+ if _option_inherits.has_key('build'):
+ for parent, opt_name in _option_inherits['build']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('build'):
+ for func in _option_finalizers['build'].values():
+ func(self)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/data.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/data.py
new file mode 100644
index 00000000000..9cf04e104c2
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/data.py
@@ -0,0 +1,165 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Data distribution
+===================
+
+This module provides tools to simplify data distribution.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from distutils import filelist as _filelist
+import os as _os
+import posixpath as _posixpath
+import sys as _sys
+
+from _setup import commands as _commands
+
+
+def splitpath(path):
+ """ Split a path """
+ drive, path = '', _os.path.normpath(path)
+ try:
+ splitunc = _os.path.splitunc
+ except AttributeError:
+ pass
+ else:
+ drive, path = splitunc(path)
+ if not drive:
+ drive, path = _os.path.splitdrive(path)
+ elems = []
+ try:
+ sep = _os.path.sep
+ except AttributeError:
+ sep = _os.path.join('1', '2')[1:-1]
+ while 1:
+ prefix, path = _os.path.split(path)
+ elems.append(path)
+ if prefix in ('', sep):
+ drive = _os.path.join(drive, prefix)
+ break
+ path = prefix
+ elems.reverse()
+ return drive, elems
+
+
+def finalizer(installer):
+ """ Finalize install_data """
+ data_files = []
+ for item in installer.data_files:
+ if not isinstance(item, Data):
+ data_files.append(item)
+ continue
+ data_files.extend(item.flatten(installer))
+ installer.data_files = data_files
+
+
+class Data(object):
+ """ File list container """
+
+ def __init__(self, files, target=None, preserve=0, strip=0,
+ prefix=None):
+ """ Initialization """
+ self._files = files
+ self._target = target
+ self._preserve = preserve
+ self._strip = strip
+ self._prefix = prefix
+ self.fixup_commands()
+
+ def fixup_commands(self):
+ pass
+
+ def from_templates(cls, *templates, **kwargs):
+ """ Initialize from template """
+ files = _filelist.FileList()
+ for tpl in templates:
+ for line in tpl.split(';'):
+ files.process_template_line(line.strip())
+ files.sort()
+ files.remove_duplicates()
+ result = []
+ for filename in files.files:
+ _, elems = splitpath(filename)
+ if '.svn' in elems or '.git' in elems:
+ continue
+ result.append(filename)
+ return cls(result, **kwargs)
+ from_templates = classmethod(from_templates)
+
+ def flatten(self, installer):
+ """ Flatten the file list to (target, file) tuples """
+ # pylint: disable = W0613
+ if self._prefix:
+ _, prefix = splitpath(self._prefix)
+ telems = prefix
+ else:
+ telems = []
+
+ tmap = {}
+ for fname in self._files:
+ (_, name), target = splitpath(fname), telems
+ if self._preserve:
+ if self._strip:
+ name = name[max(0, min(self._strip, len(name) - 1)):]
+ if len(name) > 1:
+ target = telems + name[:-1]
+ tmap.setdefault(_posixpath.join(*target), []).append(fname)
+ return tmap.items()
+
+
+class Documentation(Data):
+ """ Documentation container """
+
+ def fixup_commands(self):
+ _commands.add_option('install_data', 'without-docs',
+ help_text='Do not install documentation files',
+ inherit='install',
+ )
+ _commands.add_finalizer('install_data', 'documentation', finalizer)
+
+ def flatten(self, installer):
+ """ Check if docs should be installed at all """
+ if installer.without_docs:
+ return []
+ return Data.flatten(self, installer)
+
+
+class Manpages(Documentation):
+ """ Manpages container """
+
+ def dispatch(cls, files):
+ """ Automatically dispatch manpages to their target directories """
+ mpmap = {}
+ for manpage in files:
+ normalized = _os.path.normpath(manpage)
+ _, ext = _os.path.splitext(normalized)
+ if ext.startswith(_os.path.extsep):
+ ext = ext[len(_os.path.extsep):]
+ mpmap.setdefault(ext, []).append(manpage)
+ return [cls(manpages, prefix=_posixpath.join(
+ 'share', 'man', 'man%s' % section,
+ )) for section, manpages in mpmap.items()]
+ dispatch = classmethod(dispatch)
+
+ def flatten(self, installer):
+ """ Check if manpages are suitable """
+ if _sys.platform == 'win32':
+ return []
+ return Documentation.flatten(self, installer)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/dist.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/dist.py
new file mode 100644
index 00000000000..21a65415185
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/dist.py
@@ -0,0 +1,51 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ dist utilities
+================
+
+dist utilities.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import sys as _sys
+
+from _setup import shell as _shell
+
+
+def run_setup(*args, **kwargs):
+ """ Run setup """
+ if 'setup' in kwargs:
+ script = kwargs.get('setup') or 'setup.py'
+ del kwargs['setup']
+ else:
+ script = 'setup.py'
+ if 'fakeroot' in kwargs:
+ fakeroot = kwargs['fakeroot']
+ del kwargs['fakeroot']
+ else:
+ fakeroot = None
+ if kwargs:
+ raise TypeError("Unrecognized keyword parameters")
+
+ script = _shell.native(script)
+ argv = [_sys.executable, script] + list(args)
+ if fakeroot:
+ argv.insert(0, fakeroot)
+ return not _shell.spawn(*argv)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/ext.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/ext.py
new file mode 100644
index 00000000000..bcc0209a53a
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/ext.py
@@ -0,0 +1,254 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ C extension tools
+===================
+
+C extension tools.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+__test__ = False
+
+from distutils import core as _core
+from distutils import errors as _distutils_errors
+import os as _os
+import posixpath as _posixpath
+import shutil as _shutil
+import tempfile as _tempfile
+
+from _setup import commands as _commands
+from _setup.util import log
+
+
+def _install_finalizer(installer):
+ if installer.without_c_extensions:
+ installer.distribution.ext_modules = []
+
+def _build_finalizer(builder):
+ if builder.without_c_extensions:
+ builder.extensions = []
+
+
+class Extension(_core.Extension):
+ """
+ Extension with prerequisite check interface
+
+ If your check is cacheable (during the setup run), override
+ `cached_check_prerequisites`, `check_prerequisites` otherwise.
+
+ :IVariables:
+ `cached_check` : ``bool``
+ The cached check result
+ """
+ cached_check = None
+
+ def __init__(self, *args, **kwargs):
+ """ Initialization """
+ if kwargs.has_key('depends'):
+ self.depends = kwargs['depends'] or []
+ else:
+ self.depends = []
+ _core.Extension.__init__(self, *args, **kwargs)
+
+ # add include path
+ included = _posixpath.join('_setup', 'include')
+ if included not in self.include_dirs:
+ self.include_dirs.append(included)
+
+ # add cext.h to the dependencies
+ cext_h = _posixpath.join(included, 'cext.h')
+ if cext_h not in self.depends:
+ self.depends.append(cext_h)
+
+ _commands.add_option('install_lib', 'without-c-extensions',
+ help_text='Don\'t install C extensions',
+ inherit='install',
+ )
+ _commands.add_finalizer('install_lib', 'c-extensions',
+ _install_finalizer
+ )
+ _commands.add_option('build_ext', 'without-c-extensions',
+ help_text='Don\'t build C extensions',
+ inherit=('build', 'install_lib'),
+ )
+ _commands.add_finalizer('build_ext', 'c-extensions', _build_finalizer)
+
+ def check_prerequisites(self, build):
+ """
+ Check prerequisites
+
+ The check should cover all dependencies needed for the extension to
+ be built and run. The method can do the following:
+
+ - return a false value: the extension will be built
+ - return a true value: the extension will be skipped. This is useful
+ for optional extensions
+ - raise an exception. This is useful for mandatory extensions
+
+ If the check result is cacheable (during the setup run), override
+ `cached_check_prerequisites` instead.
+
+ :Parameters:
+ `build` : `BuildExt`
+ The extension builder
+
+ :Return: Skip the extension?
+ :Rtype: ``bool``
+ """
+ if self.cached_check is None:
+ log.debug("PREREQ check for %s" % self.name)
+ self.cached_check = self.cached_check_prerequisites(build)
+ else:
+ log.debug("PREREQ check for %s (cached)" % self.name)
+ return self.cached_check
+
+ def cached_check_prerequisites(self, build):
+ """
+ Check prerequisites
+
+ The check should cover all dependencies needed for the extension to
+ be built and run. The method can do the following:
+
+ - return a false value: the extension will be built
+ - return a true value: the extension will be skipped. This is useful
+ for optional extensions
+ - raise an exception. This is useful for mandatory extensions
+
+ If the check result is *not* cacheable (during the setup run),
+ override `check_prerequisites` instead.
+
+ :Parameters:
+ `build` : `BuildExt`
+ The extension builder
+
+ :Return: Skip the extension?
+ :Rtype: ``bool``
+ """
+ # pylint: disable = W0613
+ log.debug("Nothing to check for %s!" % self.name)
+ return False
+
+
+class ConfTest(object):
+ """
+ Single conftest abstraction
+
+ :IVariables:
+ `_tempdir` : ``str``
+ The tempdir created for this test
+
+ `src` : ``str``
+ Name of the source file
+
+ `target` : ``str``
+ Target filename
+
+ `compiler` : ``CCompiler``
+ compiler instance
+
+ `obj` : ``list``
+ List of object filenames (``[str, ...]``)
+ """
+ _tempdir = None
+
+ def __init__(self, build, source):
+ """
+ Initialization
+
+ :Parameters:
+ `build` : ``distuils.command.build_ext.build_ext``
+ builder instance
+
+ `source` : ``str``
+ Source of the file to compile
+ """
+ self._tempdir = tempdir = _tempfile.mkdtemp()
+ src = _os.path.join(tempdir, 'conftest.c')
+ fp = open(src, 'w')
+ try:
+ fp.write(source)
+ finally:
+ fp.close()
+ self.src = src
+ self.compiler = compiler = build.compiler
+ self.target = _os.path.join(tempdir, 'conftest')
+ self.obj = compiler.object_filenames([src], output_dir=tempdir)
+
+ def __del__(self):
+ """ Destruction """
+ self.destroy()
+
+ def destroy(self):
+ """ Destroy the conftest leftovers on disk """
+ tempdir, self._tempdir = self._tempdir, None
+ if tempdir is not None:
+ _shutil.rmtree(tempdir)
+
+ def compile(self, **kwargs):
+ """
+ Compile the conftest
+
+ :Parameters:
+ `kwargs` : ``dict``
+ Optional keyword parameters for the compiler call
+
+ :Return: Was the compilation successful?
+ :Rtype: ``bool``
+ """
+ kwargs['output_dir'] = self._tempdir
+ try:
+ self.compiler.compile([self.src], **kwargs)
+ except _distutils_errors.CompileError:
+ return False
+ return True
+
+ def link(self, **kwargs):
+ r"""
+ Link the conftest
+
+ Before you can link the conftest objects they need to be `compile`\d.
+
+ :Parameters:
+ `kwargs` : ``dict``
+ Optional keyword parameters for the linker call
+
+ :Return: Was the linking successful?
+ :Rtype: ``bool``
+ """
+ try:
+ self.compiler.link_executable(self.obj, self.target, **kwargs)
+ except _distutils_errors.LinkError:
+ return False
+ return True
+
+ def pipe(self, mode="r"):
+ r"""
+ Execute the conftest binary and connect to it using a pipe
+
+ Before you can pipe to or from the conftest binary it needs to
+ be `link`\ed.
+
+ :Parameters:
+ `mode` : ``str``
+ Pipe mode - r/w
+
+ :Return: The open pipe
+ :Rtype: ``file``
+ """
+ return _os.popen(self.compiler.executable_filename(self.target), mode)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/setup.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/setup.py
new file mode 100644
index 00000000000..fd86f62f9bc
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/setup.py
@@ -0,0 +1,419 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Main setup runner
+===================
+
+This module provides a wrapper around the distutils core setup.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import ConfigParser as _config_parser
+from distutils import core as _core
+import os as _os
+import posixpath as _posixpath
+import sys as _sys
+
+from _setup import commands as _commands
+from _setup import data as _data
+from _setup import ext as _ext
+from _setup import util as _util
+from _setup import shell as _shell
+
+
+def check_python_version(impl, version_min, version_max):
+ """ Check python version """
+ if impl == 'python':
+ version_info = _sys.version_info
+ elif impl == 'pypy':
+ version_info = getattr(_sys, 'pypy_version_info', None)
+ if not version_info:
+ return
+ elif impl == 'jython':
+ if not 'java' in _sys.platform.lower():
+ return
+ version_info = _sys.version_info
+ else:
+ raise AssertionError("impl not in ('python', 'pypy', 'jython')")
+
+ pyversion = map(int, version_info[:3])
+ if version_min:
+ min_required = \
+ map(int, '.'.join((version_min, '0.0.0')).split('.')[:3])
+ if pyversion < min_required:
+ raise EnvironmentError("Need at least %s %s (vs. %s)" % (
+ impl, version_min, '.'.join(map(str, pyversion))
+ ))
+ if version_max:
+ max_required = map(int, version_max.split('.'))
+ max_required[-1] += 1
+ if pyversion >= max_required:
+ raise EnvironmentError("Need at max %s %s (vs. %s)" % (
+ impl,
+ version_max,
+ '.'.join(map(str, pyversion))
+ ))
+
+
+def find_description(docs):
+ """
+ Determine the package description from DESCRIPTION
+
+ :Parameters:
+ `docs` : ``dict``
+ Docs config section
+
+ :Return: Tuple of summary, description and license
+ (``('summary', 'description', 'license')``)
+ (all may be ``None``)
+ :Rtype: ``tuple``
+ """
+ summary = None
+ filename = docs.get('meta.summary', 'SUMMARY').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ try:
+ summary = fp.read().strip().splitlines()[0].rstrip()
+ except IndexError:
+ summary = ''
+ finally:
+ fp.close()
+
+ description = None
+ filename = docs.get('meta.description', 'DESCRIPTION').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ description = fp.read().rstrip()
+ finally:
+ fp.close()
+
+ if summary is None and description:
+ from docutils import core
+ summary = core.publish_parts(
+ source=description,
+ source_path=filename,
+ writer_name='html',
+ )['title'].encode('utf-8')
+
+ return summary, description
+
+
+def find_classifiers(docs):
+ """
+ Determine classifiers from CLASSIFIERS
+
+ :return: List of classifiers (``['classifier', ...]``)
+ :rtype: ``list``
+ """
+ filename = docs.get('meta.classifiers', 'CLASSIFIERS').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ content = fp.read()
+ finally:
+ fp.close()
+ content = [item.strip() for item in content.splitlines()]
+ return [item for item in content if item and not item.startswith('#')]
+ return []
+
+
+def find_provides(docs):
+ """
+ Determine provides from PROVIDES
+
+ :return: List of provides (``['provides', ...]``)
+ :rtype: ``list``
+ """
+ filename = docs.get('meta.provides', 'PROVIDES').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ content = fp.read()
+ finally:
+ fp.close()
+ content = [item.strip() for item in content.splitlines()]
+ return [item for item in content if item and not item.startswith('#')]
+ return []
+
+
+def find_license(docs):
+ """
+ Determine license from LICENSE
+
+ :return: License text
+ :rtype: ``str``
+ """
+ filename = docs.get('meta.license', 'LICENSE').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ return fp.read().rstrip()
+ finally:
+ fp.close()
+ return None
+
+
+def find_packages(manifest):
+ """ Determine packages and subpackages """
+ packages = {}
+ collect = manifest.get('packages.collect', '').split()
+ lib = manifest.get('packages.lib', '.')
+ try:
+ sep = _os.path.sep
+ except AttributeError:
+ sep = _os.path.join('1', '2')[1:-1]
+ for root in collect:
+ for dirpath, _, filenames in _shell.walk(_os.path.join(lib, root)):
+ if dirpath.find('.svn') >= 0 or dirpath.find('.git') >= 0:
+ continue
+ if '__init__.py' in filenames:
+ packages[
+ _os.path.normpath(dirpath).replace(sep, '.')
+ ] = None
+ packages = packages.keys()
+ packages.sort()
+ return packages
+
+
+def find_data(name, docs):
+ """ Determine data files """
+ result = []
+ if docs.get('extra', '').strip():
+ result.append(_data.Documentation(docs['extra'].split(),
+ prefix='share/doc/%s' % name,
+ ))
+ if docs.get('examples.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['examples.dir']]
+ if docs.get('examples.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['examples.ignore'].split()
+ ])
+ strip = int(docs.get('examples.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('userdoc.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['userdoc.dir']]
+ if docs.get('userdoc.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['userdoc.ignore'].split()
+ ])
+ strip = int(docs.get('userdoc.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('apidoc.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['apidoc.dir']]
+ if docs.get('apidoc.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['apidoc.ignore'].split()
+ ])
+ strip = int(docs.get('apidoc.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('man', '').strip():
+ result.extend(_data.Manpages.dispatch(docs['man'].split()))
+ return result
+
+
+def make_manifest(manifest, config, docs, kwargs):
+ """ Create file list to pack up """
+ # pylint: disable = R0912
+ kwargs = kwargs.copy()
+ kwargs['script_args'] = ['install']
+ kwargs['packages'] = list(kwargs.get('packages') or ()) + [
+ '_setup', '_setup.py2', '_setup.py3',
+ ] + list(manifest.get('packages.extra', '').split() or ())
+ _core._setup_stop_after = "commandline"
+ try:
+ dist = _core.setup(**kwargs)
+ finally:
+ _core._setup_stop_after = None
+
+ result = ['MANIFEST', 'PKG-INFO', 'setup.py'] + list(config)
+ # TODO: work with default values:
+ for key in ('classifiers', 'description', 'summary', 'provides',
+ 'license'):
+ filename = docs.get('meta.' + key, '').strip()
+ if filename and _os.path.isfile(filename):
+ result.append(filename)
+
+ cmd = dist.get_command_obj("build_py")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("build_py", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+
+ cmd = dist.get_command_obj("build_ext")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("build_ext", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+ for ext in cmd.extensions:
+ if ext.depends:
+ result.extend([_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ) for item in ext.depends])
+
+ cmd = dist.get_command_obj("build_clib")
+ cmd.ensure_finalized()
+ if cmd.libraries:
+ #import pprint; pprint.pprint(("build_clib", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+ for lib in cmd.libraries:
+ if lib[1].get('depends'):
+ result.extend([_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ) for item in lib[1]['depends']])
+
+ cmd = dist.get_command_obj("build_scripts")
+ cmd.ensure_finalized()
+ #import pprint; pprint.pprint(("build_scripts", cmd.get_source_files()))
+ if cmd.get_source_files():
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+
+ cmd = dist.get_command_obj("install_data")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("install_data", cmd.get_inputs()))
+ try:
+ strings = basestring
+ except NameError:
+ strings = (str, unicode)
+
+ for item in cmd.get_inputs():
+ if isinstance(item, strings):
+ result.append(item)
+ else:
+ result.extend(item[1])
+
+ for item in manifest.get('dist', '').split():
+ result.append(item)
+ if _os.path.isdir(item):
+ for filename in _shell.files(item):
+ result.append(filename)
+
+ result = dict([(item, None) for item in result]).keys()
+ result.sort()
+ return result
+
+
+def run(config=('package.cfg',), ext=None, script_args=None, manifest_only=0):
+ """ Main runner """
+ if ext is None:
+ ext = []
+
+ cfg = _util.SafeConfigParser()
+ cfg.read(config)
+ pkg = dict(cfg.items('package'))
+ python_min = pkg.get('python.min') or None
+ python_max = pkg.get('python.max') or None
+ check_python_version('python', python_min, python_max)
+ pypy_min = pkg.get('pypy.min') or None
+ pypy_max = pkg.get('pypy.max') or None
+ check_python_version('pypy', pypy_min, pypy_max)
+ jython_min = pkg.get('jython.min') or None
+ jython_max = pkg.get('jython.max') or None
+ check_python_version('jython', jython_min, jython_max)
+
+ manifest = dict(cfg.items('manifest'))
+ try:
+ docs = dict(cfg.items('docs'))
+ except _config_parser.NoSectionError:
+ docs = {}
+
+ summary, description = find_description(docs)
+ scripts = manifest.get('scripts', '').strip() or None
+ if scripts:
+ scripts = scripts.split()
+ modules = manifest.get('modules', '').strip() or None
+ if modules:
+ modules = modules.split()
+ keywords = docs.get('meta.keywords', '').strip() or None
+ if keywords:
+ keywords = keywords.split()
+ revision = pkg.get('version.revision', '').strip()
+ if revision:
+ revision = "-r%s" % (revision,)
+
+ kwargs = {
+ 'name': pkg['name'],
+ 'version': "%s%s" % (
+ pkg['version.number'],
+ ["", "-dev%s" % (revision,)][_util.humanbool(
+ 'version.dev', pkg.get('version.dev', 'false')
+ )],
+ ),
+ 'provides': find_provides(docs),
+ 'description': summary,
+ 'long_description': description,
+ 'classifiers': find_classifiers(docs),
+ 'keywords': keywords,
+ 'author': pkg['author.name'],
+ 'author_email': pkg['author.email'],
+ 'maintainer': pkg.get('maintainer.name'),
+ 'maintainer_email': pkg.get('maintainer.email'),
+ 'url': pkg.get('url.homepage'),
+ 'download_url': pkg.get('url.download'),
+ 'license': find_license(docs),
+ 'package_dir': {'': manifest.get('packages.lib', '.')},
+ 'packages': find_packages(manifest),
+ 'py_modules': modules,
+ 'ext_modules': ext,
+ 'scripts': scripts,
+ 'script_args': script_args,
+ 'data_files': find_data(pkg['name'], docs),
+ 'cmdclass': {
+ 'build' : _commands.Build,
+ 'build_ext' : _commands.BuildExt,
+ 'install' : _commands.Install,
+ 'install_data': _commands.InstallData,
+ 'install_lib' : _commands.InstallLib,
+ }
+ }
+ for key in ('provides',):
+ if key not in _core.setup_keywords:
+ del kwargs[key]
+
+ if manifest_only:
+ return make_manifest(manifest, config, docs, kwargs)
+
+ # monkey-patch crappy manifest writer away.
+ from distutils.command import sdist
+ sdist.sdist.get_file_list = sdist.sdist.read_manifest
+
+ return _core.setup(**kwargs)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/shell.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/shell.py
new file mode 100644
index 00000000000..4eafb9c8647
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/shell.py
@@ -0,0 +1,478 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Shell utilities
+=================
+
+Shell utilities.
+"""
+from __future__ import generators
+
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import errno as _errno
+import fnmatch as _fnmatch
+import os as _os
+import shutil as _shutil
+import sys as _sys
+import tempfile as _tempfile
+
+cwd = _os.path.dirname(_os.path.abspath(_sys.argv[0]))
+
+class ExitError(RuntimeError):
+ """ Exit error """
+ def __init__(self, code):
+ RuntimeError.__init__(self, code)
+ self.code = code
+ self.signal = None
+
+
+class SignalError(ExitError):
+ """ Signal error """
+ def __init__(self, code, signal):
+ ExitError.__init__(self, code)
+ import signal as _signal
+ self.signal = signal
+ for key, val in vars(_signal).iteritems():
+ if key.startswith('SIG') and not key.startswith('SIG_'):
+ if val == signal:
+ self.signalstr = key[3:]
+ break
+ else:
+ self.signalstr = '%04d' % signal
+
+
+def native(path):
+ """ Convert slash path to native """
+ path = _os.path.sep.join(path.split('/'))
+ return _os.path.normpath(_os.path.join(cwd, path))
+
+
+def cp(src, dest):
+ """ Copy src to dest """
+ _shutil.copy2(native(src), native(dest))
+
+
+def cp_r(src, dest):
+ """ Copy -r src to dest """
+ _shutil.copytree(native(src), native(dest))
+
+
+def rm(dest):
+ """ Remove a file """
+ try:
+ _os.unlink(native(dest))
+ except OSError, e:
+ if _errno.ENOENT != e.errno:
+ raise
+
+def rm_rf(dest):
+ """ Remove a tree """
+ dest = native(dest)
+ if _os.path.exists(dest):
+ for path in files(dest, '*'):
+ _os.chmod(native(path), 0644)
+ _shutil.rmtree(dest)
+
+
+try:
+ mkstemp = _tempfile.mkstemp
+except AttributeError:
+ # helpers stolen from 2.4 tempfile module
+ try:
+ import fcntl as _fcntl
+ except ImportError:
+ def _set_cloexec(fd):
+ """ Set close-on-exec (not implemented, but not an error) """
+ # pylint: disable = W0613
+ pass
+ else:
+ def _set_cloexec(fd):
+ """ Set close-on-exec """
+ try:
+ flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
+ except IOError:
+ pass
+ else:
+ # flags read successfully, modify
+ flags |= _fcntl.FD_CLOEXEC
+ _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
+
+ _text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
+ _text_openflags |= getattr(_os, 'O_NOINHERIT', 0)
+ _text_openflags |= getattr(_os, 'O_NOFOLLOW', 0)
+
+ _bin_openflags = _text_openflags
+ _bin_openflags |= getattr(_os, 'O_BINARY', 0)
+
+ def mkstemp(suffix="", prefix=_tempfile.gettempprefix(), dir=None,
+ text=False):
+ """ Create secure temp file """
+ # pylint: disable = W0622
+ if dir is None:
+ dir = _tempfile.gettempdir()
+ if text:
+ flags = _text_openflags
+ else:
+ flags = _bin_openflags
+ count = 100
+ while count > 0:
+ j = _tempfile._counter.get_next() # pylint: disable = E1101, W0212
+ fname = _os.path.join(dir, prefix + str(j) + suffix)
+ try:
+ fd = _os.open(fname, flags, 0600)
+ except OSError, e:
+ if e.errno == _errno.EEXIST:
+ count -= 1
+ continue
+ raise
+ _set_cloexec(fd)
+ return fd, _os.path.abspath(fname)
+ raise IOError, (_errno.EEXIST, "No usable temporary file name found")
+
+
+def _pipespawn(argv, env):
+ """ Pipe spawn """
+ # pylint: disable = R0912
+ import pickle as _pickle
+ fd, name = mkstemp('.py')
+ try:
+ _os.write(fd, (r"""
+import os
+import pickle
+try:
+ import subprocess
+except ImportError:
+ subprocess = None
+import sys
+
+argv = pickle.loads(%(argv)s)
+env = pickle.loads(%(env)s)
+if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+if subprocess is None:
+ pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
+ result = os.waitpid(pid, 0)[1]
+else:
+ p = subprocess.Popen(argv, env=env)
+ result = p.wait()
+ if result < 0:
+ print "\n%%d 1" %% (-result)
+ sys.exit(2)
+
+if result == 0:
+ sys.exit(0)
+signalled = getattr(os, 'WIFSIGNALED', None)
+if signalled is not None:
+ if signalled(result):
+ print "\n%%d %%d" %% (os.WTERMSIG(result), result & 7)
+ sys.exit(2)
+print "\n%%d" %% (result & 7,)
+sys.exit(3)
+ """.strip() + "\n") % {
+ 'argv': repr(_pickle.dumps(argv)),
+ 'env': repr(_pickle.dumps(env)),
+ })
+ fd, _ = None, _os.close(fd)
+ if _sys.platform == 'win32':
+ argv = []
+ for arg in [_sys.executable, name]:
+ if ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ argv.append(arg)
+ argv = ' '.join(argv)
+ shell = True
+ close_fds = False
+ else:
+ argv = [_sys.executable, name]
+ shell = False
+ close_fds = True
+
+ res = 0
+ try:
+ import subprocess
+ except ImportError:
+ import popen2 as _popen2
+ proc = _popen2.Popen3(argv, False)
+ try:
+ proc.tochild.close()
+ result = proc.fromchild.read()
+ finally:
+ res = proc.wait()
+ else:
+ if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+ proc = subprocess.Popen(argv,
+ shell=shell,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ close_fds=close_fds,
+ env=env,
+ )
+ try:
+ proc.stdin.close()
+ result = proc.stdout.read()
+ finally:
+ res = proc.wait()
+ if res != 0:
+ if res == 2:
+ signal, code = map(int, result.splitlines()[-1].split())
+ raise SignalError(code, signal)
+ elif res == 3:
+ code = int(result.splitlines()[-1].strip())
+ raise ExitError(code)
+ raise ExitError(res)
+
+ return result
+ finally:
+ try:
+ if fd is not None:
+ _os.close(fd)
+ finally:
+ _os.unlink(name)
+
+
+def _filepipespawn(infile, outfile, argv, env):
+ """ File Pipe spawn """
+ try:
+ import subprocess
+ except ImportError:
+ subprocess = None
+ import pickle as _pickle
+ fd, name = mkstemp('.py')
+ try:
+ _os.write(fd, ("""
+import os
+import pickle
+import sys
+
+infile = pickle.loads(%(infile)s)
+outfile = pickle.loads(%(outfile)s)
+argv = pickle.loads(%(argv)s)
+env = pickle.loads(%(env)s)
+
+if infile is not None:
+ infile = open(infile, 'rb')
+ os.dup2(infile.fileno(), 0)
+ infile.close()
+if outfile is not None:
+ outfile = open(outfile, 'wb')
+ os.dup2(outfile.fileno(), 1)
+ outfile.close()
+
+pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
+result = os.waitpid(pid, 0)[1]
+sys.exit(result & 7)
+ """.strip() + "\n") % {
+ 'infile': repr(_pickle.dumps(_os.path.abspath(infile))),
+ 'outfile': repr(_pickle.dumps(_os.path.abspath(outfile))),
+ 'argv': repr(_pickle.dumps(argv)),
+ 'env': repr(_pickle.dumps(env)),
+ })
+ fd, _ = None, _os.close(fd)
+ if _sys.platform == 'win32':
+ argv = []
+ for arg in [_sys.executable, name]:
+ if ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ argv.append(arg)
+ argv = ' '.join(argv)
+ close_fds = False
+ shell = True
+ else:
+ argv = [_sys.executable, name]
+ close_fds = True
+ shell = False
+
+ if subprocess is None:
+ pid = _os.spawnve(_os.P_NOWAIT, argv[0], argv, env)
+ return _os.waitpid(pid, 0)[1]
+ else:
+ p = subprocess.Popen(
+ argv, env=env, shell=shell, close_fds=close_fds
+ )
+ return p.wait()
+ finally:
+ try:
+ if fd is not None:
+ _os.close(fd)
+ finally:
+ _os.unlink(name)
+
+
+def spawn(*argv, **kwargs):
+ """ Spawn a process """
+ try:
+ import subprocess
+ except ImportError:
+ subprocess = None
+
+ if _sys.platform == 'win32':
+ newargv = []
+ for arg in argv:
+ if not arg or ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ newargv.append(arg)
+ argv = newargv
+ close_fds = False
+ shell = True
+ else:
+ close_fds = True
+ shell = False
+
+ env = kwargs.get('env')
+ if env is None:
+ env = dict(_os.environ)
+ if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+ echo = kwargs.get('echo')
+ if echo:
+ print ' '.join(argv)
+ filepipe = kwargs.get('filepipe')
+ if filepipe:
+ return _filepipespawn(
+ kwargs.get('stdin'), kwargs.get('stdout'), argv, env
+ )
+ pipe = kwargs.get('stdout')
+ if pipe:
+ return _pipespawn(argv, env)
+
+ if subprocess is None:
+ pid = _os.spawnve(_os.P_NOWAIT, argv[0], argv, env)
+ return _os.waitpid(pid, 0)[1]
+ else:
+ p = subprocess.Popen(argv, env=env, shell=shell, close_fds=close_fds)
+ return p.wait()
+
+
+try:
+ walk = _os.walk
+except AttributeError:
+ # copy from python 2.4 sources (modulo docs and comments)
+ def walk(top, topdown=True, onerror=None):
+ """ directory tree walker """
+ # pylint: disable = C0103
+ join, isdir, islink = _os.path.join, _os.path.isdir, _os.path.islink
+ listdir, error = _os.listdir, _os.error
+
+ try:
+ names = listdir(top)
+ except error, err:
+ if onerror is not None:
+ onerror(err)
+ return
+
+ dirs, nondirs = [], []
+ for name in names:
+ if isdir(join(top, name)):
+ dirs.append(name)
+ else:
+ nondirs.append(name)
+
+ if topdown:
+ yield top, dirs, nondirs
+ for name in dirs:
+ path = join(top, name)
+ if not islink(path):
+ for x in walk(path, topdown, onerror):
+ yield x
+ if not topdown:
+ yield top, dirs, nondirs
+
+
+def files(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
+ """ Determine a filelist """
+ for dirpath, dirnames, filenames in walk(native(base)):
+ for item in prune:
+ if item in dirnames:
+ dirnames.remove(item)
+
+ filenames.sort()
+ for name in _fnmatch.filter(filenames, wildcard):
+ dest = _os.path.join(dirpath, name)
+ if dest.startswith(cwd):
+ dest = dest.replace(cwd, '', 1)
+ aslist = []
+ head, tail = _os.path.split(dest)
+ while tail:
+ aslist.append(tail)
+ head, tail = _os.path.split(head)
+ aslist.reverse()
+ dest = '/'.join(aslist)
+ yield dest
+
+ if not recursive:
+ break
+ dirnames.sort()
+
+
+def dirs(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
+ """ Determine a filelist """
+ for dirpath, dirnames, filenames in walk(native(base)):
+ for item in prune:
+ if item in dirnames:
+ dirnames.remove(item)
+
+ dirnames.sort()
+ for name in _fnmatch.filter(dirnames, wildcard):
+ dest = _os.path.join(dirpath, name)
+ if dest.startswith(cwd):
+ dest = dest.replace(cwd, '', 1)
+ aslist = []
+ head, tail = _os.path.split(dest)
+ while tail:
+ aslist.append(tail)
+ head, tail = _os.path.split(head)
+ aslist.reverse()
+ dest = '/'.join(aslist)
+ yield dest
+
+ if not recursive:
+ break
+
+
+def frompath(executable):
+ """ Find executable in PATH """
+ # Based on distutils.spawn.find_executable.
+ path = _os.environ.get('PATH', '')
+ paths = [
+ _os.path.expanduser(item)
+ for item in path.split(_os.pathsep)
+ ]
+ ext = _os.path.splitext(executable)[1]
+ exts = ['']
+ if _sys.platform == 'win32' or _os.name == 'os2':
+ eext = ['.exe', '.bat', '.py']
+ if ext not in eext:
+ exts.extend(eext)
+
+ for ext in exts:
+ if not _os.path.isfile(executable + ext):
+ for path in paths:
+ fname = _os.path.join(path, executable + ext)
+ if _os.path.isfile(fname):
+ # the file exists, we have a shot at spawn working
+ return fname
+ else:
+ return executable + ext
+
+ return None
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/term/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/term/__init__.py
new file mode 100644
index 00000000000..4e50ec37493
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/term/__init__.py
@@ -0,0 +1,28 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=====================
+ Package _setup.term
+=====================
+
+Terminal tools, not distributed.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+# pylint: disable = W0611
+from _setup.term._term import terminfo, write, green, red, yellow, announce
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/term/_term.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/term/_term.py
new file mode 100644
index 00000000000..72b727c1a95
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/term/_term.py
@@ -0,0 +1,115 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Terminal writer
+=================
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import sys as _sys
+
+
+class _INFO(dict):
+ """ Terminal info dict """
+
+ def __init__(self):
+ """ Initialization """
+ dict.__init__(self, {
+ 'NORMAL': '',
+ 'BOLD': '',
+ 'ERASE': '\n',
+ 'RED': '',
+ 'YELLOW': '',
+ 'GREEN': '',
+ })
+ try:
+ import curses as _curses
+ except ImportError:
+ # fixup if a submodule of curses failed.
+ if 'curses' in _sys.modules:
+ del _sys.modules['curses']
+ else:
+ try:
+ _curses.setupterm()
+ except (TypeError, _curses.error):
+ pass
+ else:
+ def make_color(color):
+ """ Make color control string """
+ seq = _curses.tigetstr('setaf')
+ if seq is not None:
+ # XXX may fail - need better logic
+ seq = seq.replace("%p1", "") % color
+ return seq
+
+ self['NORMAL'] = _curses.tigetstr('sgr0')
+ self['BOLD'] = _curses.tigetstr('bold')
+
+ erase = _curses.tigetstr('el1')
+ if erase is not None:
+ self['ERASE'] = erase + _curses.tigetstr('cr')
+
+ self['RED'] = make_color(_curses.COLOR_RED)
+ self['YELLOW'] = make_color(_curses.COLOR_YELLOW)
+ self['GREEN'] = make_color(_curses.COLOR_GREEN)
+
+ def __getitem__(self, key):
+ """ Deliver always """
+ dict.get(self, key) or ""
+
+
+def terminfo():
+ """ Get info singleton """
+ # pylint: disable = E1101, W0612
+ if terminfo.info is None:
+ terminfo.info = _INFO()
+ return terminfo.info
+terminfo.info = None
+
+
+def write(fmt, **kwargs):
+ """ Write stuff on the terminal """
+ parm = dict(terminfo())
+ parm.update(kwargs)
+ _sys.stdout.write(fmt % parm)
+ _sys.stdout.flush()
+
+
+def green(bmt, **kwargs):
+ """ Write something in green on screen """
+ announce("%%(GREEN)s%s%%(NORMAL)s" % bmt, **kwargs)
+
+
+def red(bmt, **kwargs):
+ """ Write something in red on the screen """
+ announce("%%(BOLD)s%%(RED)s%s%%(NORMAL)s" % bmt, **kwargs)
+
+
+def yellow(fmt, **kwargs):
+ """ Write something in yellow on the screen """
+ announce("%%(BOLD)s%%(YELLOW)s%s%%(NORMAL)s" % fmt, **kwargs)
+
+
+def announce(fmt, **kwargs):
+ """ Announce something """
+ write(fmt, **kwargs)
+ _sys.stdout.write("\n")
+ _sys.stdout.flush()
+
+
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/util.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/util.py
new file mode 100644
index 00000000000..5c05fac6e4c
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py2/util.py
@@ -0,0 +1,73 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Setup utilities
+=================
+
+Setup utilities.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+try:
+ from distutils import log
+except ImportError:
+ class log(object):
+ def info(self, value):
+ print value
+ def debug(self, value):
+ pass
+ log = log()
+
+from distutils import util as _util
+try:
+ from ConfigParser import SafeConfigParser
+except ImportError:
+ import ConfigParser as _config_parser
+ class SafeConfigParser(_config_parser.ConfigParser):
+ """ Safe config parser """
+ def _interpolate(self, section, option, rawval, vars):
+ return rawval
+
+ def items(self, section):
+ return [(key, self.get(section, key))
+ for key in self.options(section)
+ ]
+
+
+def humanbool(name, value):
+ """
+ Determine human boolean value
+
+ :Parameters:
+ `name` : ``str``
+ The config key (used for error message)
+
+ `value` : ``str``
+ The config value
+
+ :Return: The boolean value
+ :Rtype: ``bool``
+
+ :Exceptions:
+ - `ValueError` : The value could not be recognized
+ """
+ try:
+ return _util.strtobool(str(value).strip().lower() or 'no')
+ except ValueError:
+ raise ValueError("Unrecognized config value: %s = %s" % (name, value))
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/__init__.py
new file mode 100644
index 00000000000..6139d510a10
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/__init__.py
@@ -0,0 +1,27 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ Package _setup
+================
+
+This package provides tools for main package setup.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from _setup.setup import run # pylint: disable = W0611
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/commands.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/commands.py
new file mode 100644
index 00000000000..7bfacbc86ef
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/commands.py
@@ -0,0 +1,266 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Command extenders
+===================
+
+Command extenders.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+__test__ = False
+
+from distutils import fancy_getopt as _fancy_getopt
+from distutils import log
+from distutils.command import build as _build
+from distutils.command import build_ext as _build_ext
+from distutils.command import install as _install
+from distutils.command import install_data as _install_data
+from distutils.command import install_lib as _install_lib
+import os as _os
+
+_option_defaults = {}
+_option_inherits = {}
+_option_finalizers = {}
+_command_mapping = {
+ 'install': 'Install',
+ 'install_data': 'InstallData',
+ 'install_lib': 'InstallLib',
+ 'build': 'Build',
+ 'build_ext': 'BuildExt',
+}
+
+
+def add_option(command, long_name, help_text, short_name=None, default=None,
+ inherit=None):
+ """ Add an option """
+ try:
+ command_class = globals()[_command_mapping[command]]
+ except KeyError:
+ raise ValueError("Unknown command %r" % (command,))
+ for opt in command_class.user_options:
+ if opt[0] == long_name:
+ break
+ else:
+ opt = (long_name, short_name, help_text)
+ command_class.user_options.append(opt)
+ if not long_name.endswith('='):
+ command_class.boolean_options.append(long_name)
+ attr_name = _fancy_getopt.translate_longopt(long_name)
+ else:
+ attr_name = _fancy_getopt.translate_longopt(long_name[:-1])
+ if command not in _option_defaults:
+ _option_defaults[command] = []
+ if inherit is not None:
+ if isinstance(inherit, str):
+ inherit = [inherit]
+ for i_inherit in inherit:
+ add_option(
+ i_inherit, long_name, help_text, short_name, default
+ )
+ default = None
+ if command not in _option_inherits:
+ _option_inherits[command] = []
+ for i_inherit in inherit:
+ for i_command, opt_name in _option_inherits[command]:
+ if i_command == i_inherit and opt_name == attr_name:
+ break
+ else:
+ _option_inherits[command].append((i_inherit, attr_name))
+ _option_defaults[command].append((attr_name, default))
+
+
+def add_finalizer(command, key, func):
+ """ Add finalizer """
+ if command not in _option_finalizers:
+ _option_finalizers[command] = {}
+ if key not in _option_finalizers[command]:
+ _option_finalizers[command][key] = func
+
+
+class Install(_install.install):
+ """ Extended installer to reflect the additional data options """
+ user_options = _install.install.user_options + [
+ ('single-version-externally-managed', None,
+ "Compat option. Does not a thing."),
+ ]
+ boolean_options = _install.install.boolean_options + [
+ 'single-version-externally-managed'
+ ]
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install.install.initialize_options(self)
+ self.single_version_externally_managed = None
+ if 'install' in _option_defaults:
+ for opt_name, default in _option_defaults['install']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install.install.finalize_options(self)
+ if 'install' in _option_inherits:
+ for parent, opt_name in _option_inherits['install']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'install' in _option_finalizers:
+ for func in list(_option_finalizers['install'].values()):
+ func(self)
+
+
+class InstallData(_install_data.install_data):
+ """ Extended data installer """
+ user_options = _install_data.install_data.user_options + []
+ boolean_options = _install_data.install_data.boolean_options + []
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install_data.install_data.initialize_options(self)
+ if 'install_data' in _option_defaults:
+ for opt_name, default in _option_defaults['install_data']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install_data.install_data.finalize_options(self)
+ if 'install_data' in _option_inherits:
+ for parent, opt_name in _option_inherits['install_data']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'install_data' in _option_finalizers:
+ for func in list(_option_finalizers['install_data'].values()):
+ func(self)
+
+
+class InstallLib(_install_lib.install_lib):
+ """ Extended lib installer """
+ user_options = _install_lib.install_lib.user_options + []
+ boolean_options = _install_lib.install_lib.boolean_options + []
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install_lib.install_lib.initialize_options(self)
+ if 'install_lib' in _option_defaults:
+ for opt_name, default in _option_defaults['install_lib']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install_lib.install_lib.finalize_options(self)
+ if 'install_lib' in _option_inherits:
+ for parent, opt_name in _option_inherits['install_lib']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'install_lib' in _option_finalizers:
+ for func in list(_option_finalizers['install_lib'].values()):
+ func(self)
+
+
+class BuildExt(_build_ext.build_ext):
+ """
+ Extended extension builder class
+
+ This class allows extensions to provide a ``check_prerequisites`` method
+ which is called before actually building it. The method takes the
+ `BuildExt` instance and returns whether the extension should be skipped or
+ not.
+ """
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _build_ext.build_ext.initialize_options(self)
+ if 'build_ext' in _option_defaults:
+ for opt_name, default in _option_defaults['build_ext']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _build_ext.build_ext.finalize_options(self)
+ if 'build_ext' in _option_inherits:
+ for parent, opt_name in _option_inherits['build_ext']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'build_ext' in _option_finalizers:
+ for func in list(_option_finalizers['build_ext'].values()):
+ func(self)
+
+ def build_extension(self, ext):
+ """
+ Build C extension - with extended functionality
+
+ The following features are added here:
+
+ - ``ext.check_prerequisites`` is called before the extension is being
+ built. See `Extension` for details. If the method does not exist,
+ simply no check will be run.
+ - The macros ``EXT_PACKAGE`` and ``EXT_MODULE`` will be filled (or
+ unset) depending on the extensions name, but only if they are not
+ already defined.
+
+ :Parameters:
+ `ext` : `Extension`
+ The extension to build. If it's a pure
+ ``distutils.core.Extension``, simply no prequisites check is
+ applied.
+
+ :Return: whatever ``distutils.command.build_ext.build_ext`` returns
+ :Rtype: any
+ """
+ # handle name macros
+ macros = dict(ext.define_macros or ())
+ tup = ext.name.split('.')
+ if len(tup) == 1:
+ pkg, mod = None, tup[0]
+ else:
+ pkg, mod = '.'.join(tup[:-1]), tup[-1]
+ if pkg is not None and 'EXT_PACKAGE' not in macros:
+ ext.define_macros.append(('EXT_PACKAGE', pkg))
+ if 'EXT_MODULE' not in macros:
+ ext.define_macros.append(('EXT_MODULE', mod))
+ if pkg is None:
+ macros = dict(ext.undef_macros or ())
+ if 'EXT_PACKAGE' not in macros:
+ ext.undef_macros.append('EXT_PACKAGE')
+
+ # handle prereq checks
+ try:
+ checker = ext.check_prerequisites
+ except AttributeError:
+ pass
+ else:
+ if checker(self):
+ log.info("Skipping %s extension" % ext.name)
+ return
+
+ return _build_ext.build_ext.build_extension(self, ext)
+
+
+class Build(_build.build):
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _build.build.initialize_options(self)
+ if 'build' in _option_defaults:
+ for opt_name, default in _option_defaults['build']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _build.build.finalize_options(self)
+ if 'build' in _option_inherits:
+ for parent, opt_name in _option_inherits['build']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'build' in _option_finalizers:
+ for func in list(_option_finalizers['build'].values()):
+ func(self)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/data.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/data.py
new file mode 100644
index 00000000000..d4221735768
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/data.py
@@ -0,0 +1,165 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Data distribution
+===================
+
+This module provides tools to simplify data distribution.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from distutils import filelist as _filelist
+import os as _os
+import posixpath as _posixpath
+import sys as _sys
+
+from _setup import commands as _commands
+
+
+def splitpath(path):
+ """ Split a path """
+ drive, path = '', _os.path.normpath(path)
+ try:
+ splitunc = _os.path.splitunc
+ except AttributeError:
+ pass
+ else:
+ drive, path = splitunc(path)
+ if not drive:
+ drive, path = _os.path.splitdrive(path)
+ elems = []
+ try:
+ sep = _os.path.sep
+ except AttributeError:
+ sep = _os.path.join('1', '2')[1:-1]
+ while 1:
+ prefix, path = _os.path.split(path)
+ elems.append(path)
+ if prefix in ('', sep):
+ drive = _os.path.join(drive, prefix)
+ break
+ path = prefix
+ elems.reverse()
+ return drive, elems
+
+
+def finalizer(installer):
+ """ Finalize install_data """
+ data_files = []
+ for item in installer.data_files:
+ if not isinstance(item, Data):
+ data_files.append(item)
+ continue
+ data_files.extend(item.flatten(installer))
+ installer.data_files = data_files
+
+
+class Data(object):
+ """ File list container """
+
+ def __init__(self, files, target=None, preserve=0, strip=0,
+ prefix=None):
+ """ Initialization """
+ self._files = files
+ self._target = target
+ self._preserve = preserve
+ self._strip = strip
+ self._prefix = prefix
+ self.fixup_commands()
+
+ def fixup_commands(self):
+ pass
+
+ def from_templates(cls, *templates, **kwargs):
+ """ Initialize from template """
+ files = _filelist.FileList()
+ for tpl in templates:
+ for line in tpl.split(';'):
+ files.process_template_line(line.strip())
+ files.sort()
+ files.remove_duplicates()
+ result = []
+ for filename in files.files:
+ _, elems = splitpath(filename)
+ if '.svn' in elems or '.git' in elems:
+ continue
+ result.append(filename)
+ return cls(result, **kwargs)
+ from_templates = classmethod(from_templates)
+
+ def flatten(self, installer):
+ """ Flatten the file list to (target, file) tuples """
+ # pylint: disable = W0613
+ if self._prefix:
+ _, prefix = splitpath(self._prefix)
+ telems = prefix
+ else:
+ telems = []
+
+ tmap = {}
+ for fname in self._files:
+ (_, name), target = splitpath(fname), telems
+ if self._preserve:
+ if self._strip:
+ name = name[max(0, min(self._strip, len(name) - 1)):]
+ if len(name) > 1:
+ target = telems + name[:-1]
+ tmap.setdefault(_posixpath.join(*target), []).append(fname)
+ return list(tmap.items())
+
+
+class Documentation(Data):
+ """ Documentation container """
+
+ def fixup_commands(self):
+ _commands.add_option('install_data', 'without-docs',
+ help_text='Do not install documentation files',
+ inherit='install',
+ )
+ _commands.add_finalizer('install_data', 'documentation', finalizer)
+
+ def flatten(self, installer):
+ """ Check if docs should be installed at all """
+ if installer.without_docs:
+ return []
+ return Data.flatten(self, installer)
+
+
+class Manpages(Documentation):
+ """ Manpages container """
+
+ def dispatch(cls, files):
+ """ Automatically dispatch manpages to their target directories """
+ mpmap = {}
+ for manpage in files:
+ normalized = _os.path.normpath(manpage)
+ _, ext = _os.path.splitext(normalized)
+ if ext.startswith(_os.path.extsep):
+ ext = ext[len(_os.path.extsep):]
+ mpmap.setdefault(ext, []).append(manpage)
+ return [cls(manpages, prefix=_posixpath.join(
+ 'share', 'man', 'man%s' % section,
+ )) for section, manpages in list(mpmap.items())]
+ dispatch = classmethod(dispatch)
+
+ def flatten(self, installer):
+ """ Check if manpages are suitable """
+ if _sys.platform == 'win32':
+ return []
+ return Documentation.flatten(self, installer)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/dist.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/dist.py
new file mode 100644
index 00000000000..cce21e57a63
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/dist.py
@@ -0,0 +1,51 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ dist utilities
+================
+
+dist utilities.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import sys as _sys
+
+from _setup import shell as _shell
+
+
+def run_setup(*args, **kwargs):
+ """ Run setup """
+ if 'setup' in kwargs:
+ script = kwargs.get('setup') or 'setup.py'
+ del kwargs['setup']
+ else:
+ script = 'setup.py'
+ if 'fakeroot' in kwargs:
+ fakeroot = kwargs['fakeroot']
+ del kwargs['fakeroot']
+ else:
+ fakeroot = None
+ if kwargs:
+ raise TypeError("Unrecognized keyword parameters")
+
+ script = _shell.native(script)
+ argv = [_sys.executable, script] + list(args)
+ if fakeroot:
+ argv.insert(0, fakeroot)
+ return not _shell.spawn(*argv)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/ext.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/ext.py
new file mode 100644
index 00000000000..852c466547e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/ext.py
@@ -0,0 +1,253 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ C extension tools
+===================
+
+C extension tools.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+__test__ = False
+
+from distutils import core as _core
+from distutils import errors as _distutils_errors
+from distutils import log
+import os as _os
+import posixpath as _posixpath
+import shutil as _shutil
+import tempfile as _tempfile
+
+from _setup import commands as _commands
+
+def _install_finalizer(installer):
+ if installer.without_c_extensions:
+ installer.distribution.ext_modules = []
+
+def _build_finalizer(builder):
+ if builder.without_c_extensions:
+ builder.extensions = []
+
+
+class Extension(_core.Extension):
+ """
+ Extension with prerequisite check interface
+
+ If your check is cacheable (during the setup run), override
+ `cached_check_prerequisites`, `check_prerequisites` otherwise.
+
+ :IVariables:
+ `cached_check` : ``bool``
+ The cached check result
+ """
+ cached_check = None
+
+ def __init__(self, *args, **kwargs):
+ """ Initialization """
+ if 'depends' in kwargs:
+ self.depends = kwargs['depends'] or []
+ else:
+ self.depends = []
+ _core.Extension.__init__(self, *args, **kwargs)
+
+ # add include path
+ included = _posixpath.join('_setup', 'include')
+ if included not in self.include_dirs:
+ self.include_dirs.append(included)
+
+ # add cext.h to the dependencies
+ cext_h = _posixpath.join(included, 'cext.h')
+ if cext_h not in self.depends:
+ self.depends.append(cext_h)
+
+ _commands.add_option('install_lib', 'without-c-extensions',
+ help_text='Don\'t install C extensions',
+ inherit='install',
+ )
+ _commands.add_finalizer('install_lib', 'c-extensions',
+ _install_finalizer
+ )
+ _commands.add_option('build_ext', 'without-c-extensions',
+ help_text='Don\'t build C extensions',
+ inherit=('build', 'install_lib'),
+ )
+ _commands.add_finalizer('build_ext', 'c-extensions', _build_finalizer)
+
+ def check_prerequisites(self, build):
+ """
+ Check prerequisites
+
+ The check should cover all dependencies needed for the extension to
+ be built and run. The method can do the following:
+
+ - return a false value: the extension will be built
+ - return a true value: the extension will be skipped. This is useful
+ for optional extensions
+ - raise an exception. This is useful for mandatory extensions
+
+ If the check result is cacheable (during the setup run), override
+ `cached_check_prerequisites` instead.
+
+ :Parameters:
+ `build` : `BuildExt`
+ The extension builder
+
+ :Return: Skip the extension?
+ :Rtype: ``bool``
+ """
+ if self.cached_check is None:
+ log.debug("PREREQ check for %s" % self.name)
+ self.cached_check = self.cached_check_prerequisites(build)
+ else:
+ log.debug("PREREQ check for %s (cached)" % self.name)
+ return self.cached_check
+
+ def cached_check_prerequisites(self, build):
+ """
+ Check prerequisites
+
+ The check should cover all dependencies needed for the extension to
+ be built and run. The method can do the following:
+
+ - return a false value: the extension will be built
+ - return a true value: the extension will be skipped. This is useful
+ for optional extensions
+ - raise an exception. This is useful for mandatory extensions
+
+ If the check result is *not* cacheable (during the setup run),
+ override `check_prerequisites` instead.
+
+ :Parameters:
+ `build` : `BuildExt`
+ The extension builder
+
+ :Return: Skip the extension?
+ :Rtype: ``bool``
+ """
+ # pylint: disable = W0613
+ log.debug("Nothing to check for %s!" % self.name)
+ return False
+
+
+class ConfTest(object):
+ """
+ Single conftest abstraction
+
+ :IVariables:
+ `_tempdir` : ``str``
+ The tempdir created for this test
+
+ `src` : ``str``
+ Name of the source file
+
+ `target` : ``str``
+ Target filename
+
+ `compiler` : ``CCompiler``
+ compiler instance
+
+ `obj` : ``list``
+ List of object filenames (``[str, ...]``)
+ """
+ _tempdir = None
+
+ def __init__(self, build, source):
+ """
+ Initialization
+
+ :Parameters:
+ `build` : ``distuils.command.build_ext.build_ext``
+ builder instance
+
+ `source` : ``str``
+ Source of the file to compile
+ """
+ self._tempdir = tempdir = _tempfile.mkdtemp()
+ src = _os.path.join(tempdir, 'conftest.c')
+ fp = open(src, 'w', encoding='utf-8')
+ try:
+ fp.write(source)
+ finally:
+ fp.close()
+ self.src = src
+ self.compiler = compiler = build.compiler
+ self.target = _os.path.join(tempdir, 'conftest')
+ self.obj = compiler.object_filenames([src], output_dir=tempdir)
+
+ def __del__(self):
+ """ Destruction """
+ self.destroy()
+
+ def destroy(self):
+ """ Destroy the conftest leftovers on disk """
+ tempdir, self._tempdir = self._tempdir, None
+ if tempdir is not None:
+ _shutil.rmtree(tempdir)
+
+ def compile(self, **kwargs):
+ """
+ Compile the conftest
+
+ :Parameters:
+ `kwargs` : ``dict``
+ Optional keyword parameters for the compiler call
+
+ :Return: Was the compilation successful?
+ :Rtype: ``bool``
+ """
+ kwargs['output_dir'] = self._tempdir
+ try:
+ self.compiler.compile([self.src], **kwargs)
+ except _distutils_errors.CompileError:
+ return False
+ return True
+
+ def link(self, **kwargs):
+ r"""
+ Link the conftest
+
+ Before you can link the conftest objects they need to be `compile`\d.
+
+ :Parameters:
+ `kwargs` : ``dict``
+ Optional keyword parameters for the linker call
+
+ :Return: Was the linking successful?
+ :Rtype: ``bool``
+ """
+ try:
+ self.compiler.link_executable(self.obj, self.target, **kwargs)
+ except _distutils_errors.LinkError:
+ return False
+ return True
+
+ def pipe(self, mode="r"):
+ r"""
+ Execute the conftest binary and connect to it using a pipe
+
+ Before you can pipe to or from the conftest binary it needs to
+ be `link`\ed.
+
+ :Parameters:
+ `mode` : ``str``
+ Pipe mode - r/w
+
+ :Return: The open pipe
+ :Rtype: ``file``
+ """
+ return _os.popen(self.compiler.executable_filename(self.target), mode)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/setup.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/setup.py
new file mode 100644
index 00000000000..83f1c21d544
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/setup.py
@@ -0,0 +1,420 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Main setup runner
+===================
+
+This module provides a wrapper around the distutils core setup.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import configparser as _config_parser
+from distutils import core as _core
+import os as _os
+import posixpath as _posixpath
+import sys as _sys
+
+from _setup import commands as _commands
+from _setup import data as _data
+from _setup import ext as _ext
+from _setup import util as _util
+from _setup import shell as _shell
+
+
+def check_python_version(impl, version_min, version_max):
+ """ Check python version """
+ if impl == 'python':
+ version_info = _sys.version_info
+ elif impl == 'pypy':
+ version_info = getattr(_sys, 'pypy_version_info', None)
+ if not version_info:
+ return
+ elif impl == 'jython':
+ if not 'java' in _sys.platform.lower():
+ return
+ version_info = _sys.version_info
+ else:
+ raise AssertionError("impl not in ('python', 'pypy', 'jython')")
+
+ pyversion = list(map(int, version_info[:3]))
+ if version_min:
+ min_required = list(
+ map(int, '.'.join((version_min, '0.0.0')).split('.')[:3])
+ )
+ if pyversion < min_required:
+ raise EnvironmentError("Need at least %s %s (vs. %s)" % (
+ impl, version_min, '.'.join(map(str, pyversion))
+ ))
+ if version_max:
+ max_required = list(map(int, version_max.split('.')))
+ max_required[-1] += 1
+ if pyversion >= max_required:
+ raise EnvironmentError("Need at max %s %s (vs. %s)" % (
+ impl,
+ version_max,
+ '.'.join(map(str, pyversion))
+ ))
+
+
+def find_description(docs):
+ """
+ Determine the package description from DESCRIPTION
+
+ :Parameters:
+ `docs` : ``dict``
+ Docs config section
+
+ :Return: Tuple of summary, description and license
+ (``('summary', 'description', 'license')``)
+ (all may be ``None``)
+ :Rtype: ``tuple``
+ """
+ summary = None
+ filename = docs.get('meta.summary', 'SUMMARY').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ try:
+ summary = fp.read().strip().splitlines()[0].rstrip()
+ except IndexError:
+ summary = ''
+ finally:
+ fp.close()
+
+ description = None
+ filename = docs.get('meta.description', 'DESCRIPTION').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ description = fp.read().rstrip()
+ finally:
+ fp.close()
+
+ if summary is None and description:
+ from docutils import core
+ summary = core.publish_parts(
+ source=description,
+ source_path=filename,
+ writer_name='html',
+ )['title'].encode('utf-8')
+
+ return summary, description
+
+
+def find_classifiers(docs):
+ """
+ Determine classifiers from CLASSIFIERS
+
+ :return: List of classifiers (``['classifier', ...]``)
+ :rtype: ``list``
+ """
+ filename = docs.get('meta.classifiers', 'CLASSIFIERS').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ content = fp.read()
+ finally:
+ fp.close()
+ content = [item.strip() for item in content.splitlines()]
+ return [item for item in content if item and not item.startswith('#')]
+ return []
+
+
+def find_provides(docs):
+ """
+ Determine provides from PROVIDES
+
+ :return: List of provides (``['provides', ...]``)
+ :rtype: ``list``
+ """
+ filename = docs.get('meta.provides', 'PROVIDES').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ content = fp.read()
+ finally:
+ fp.close()
+ content = [item.strip() for item in content.splitlines()]
+ return [item for item in content if item and not item.startswith('#')]
+ return []
+
+
+def find_license(docs):
+ """
+ Determine license from LICENSE
+
+ :return: License text
+ :rtype: ``str``
+ """
+ filename = docs.get('meta.license', 'LICENSE').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ return fp.read().rstrip()
+ finally:
+ fp.close()
+ return None
+
+
+def find_packages(manifest):
+ """ Determine packages and subpackages """
+ packages = {}
+ collect = manifest.get('packages.collect', '').split()
+ lib = manifest.get('packages.lib', '.')
+ try:
+ sep = _os.path.sep
+ except AttributeError:
+ sep = _os.path.join('1', '2')[1:-1]
+ for root in collect:
+ for dirpath, _, filenames in _shell.walk(_os.path.join(lib, root)):
+ if dirpath.find('.svn') >= 0 or dirpath.find('.git') >= 0:
+ continue
+ if '__init__.py' in filenames:
+ packages[
+ _os.path.normpath(dirpath).replace(sep, '.')
+ ] = None
+ packages = list(packages.keys())
+ packages.sort()
+ return packages
+
+
+def find_data(name, docs):
+ """ Determine data files """
+ result = []
+ if docs.get('extra', '').strip():
+ result.append(_data.Documentation(docs['extra'].split(),
+ prefix='share/doc/%s' % name,
+ ))
+ if docs.get('examples.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['examples.dir']]
+ if docs.get('examples.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['examples.ignore'].split()
+ ])
+ strip = int(docs.get('examples.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('userdoc.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['userdoc.dir']]
+ if docs.get('userdoc.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['userdoc.ignore'].split()
+ ])
+ strip = int(docs.get('userdoc.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('apidoc.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['apidoc.dir']]
+ if docs.get('apidoc.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['apidoc.ignore'].split()
+ ])
+ strip = int(docs.get('apidoc.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('man', '').strip():
+ result.extend(_data.Manpages.dispatch(docs['man'].split()))
+ return result
+
+
+def make_manifest(manifest, config, docs, kwargs):
+ """ Create file list to pack up """
+ # pylint: disable = R0912
+ kwargs = kwargs.copy()
+ kwargs['script_args'] = ['install']
+ kwargs['packages'] = list(kwargs.get('packages') or ()) + [
+ '_setup', '_setup.py2', '_setup.py3',
+ ] + list(manifest.get('packages.extra', '').split() or ())
+ _core._setup_stop_after = "commandline"
+ try:
+ dist = _core.setup(**kwargs)
+ finally:
+ _core._setup_stop_after = None
+
+ result = ['MANIFEST', 'PKG-INFO', 'setup.py'] + list(config)
+ # TODO: work with default values:
+ for key in ('classifiers', 'description', 'summary', 'provides',
+ 'license'):
+ filename = docs.get('meta.' + key, '').strip()
+ if filename and _os.path.isfile(filename):
+ result.append(filename)
+
+ cmd = dist.get_command_obj("build_py")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("build_py", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+
+ cmd = dist.get_command_obj("build_ext")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("build_ext", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+ for ext in cmd.extensions:
+ if ext.depends:
+ result.extend([_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ) for item in ext.depends])
+
+ cmd = dist.get_command_obj("build_clib")
+ cmd.ensure_finalized()
+ if cmd.libraries:
+ #import pprint; pprint.pprint(("build_clib", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+ for lib in cmd.libraries:
+ if lib[1].get('depends'):
+ result.extend([_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ) for item in lib[1]['depends']])
+
+ cmd = dist.get_command_obj("build_scripts")
+ cmd.ensure_finalized()
+ #import pprint; pprint.pprint(("build_scripts", cmd.get_source_files()))
+ if cmd.get_source_files():
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+
+ cmd = dist.get_command_obj("install_data")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("install_data", cmd.get_inputs()))
+ try:
+ strings = str
+ except NameError:
+ strings = (str, str)
+
+ for item in cmd.get_inputs():
+ if isinstance(item, strings):
+ result.append(item)
+ else:
+ result.extend(item[1])
+
+ for item in manifest.get('dist', '').split():
+ result.append(item)
+ if _os.path.isdir(item):
+ for filename in _shell.files(item):
+ result.append(filename)
+
+ result = list(dict([(item, None) for item in result]).keys())
+ result.sort()
+ return result
+
+
+def run(config=('package.cfg',), ext=None, script_args=None, manifest_only=0):
+ """ Main runner """
+ if ext is None:
+ ext = []
+
+ cfg = _util.SafeConfigParser()
+ cfg.read(config, encoding='utf-8')
+ pkg = dict(cfg.items('package'))
+ python_min = pkg.get('python.min') or None
+ python_max = pkg.get('python.max') or None
+ check_python_version('python', python_min, python_max)
+ pypy_min = pkg.get('pypy.min') or None
+ pypy_max = pkg.get('pypy.max') or None
+ check_python_version('pypy', pypy_min, pypy_max)
+ jython_min = pkg.get('jython.min') or None
+ jython_max = pkg.get('jython.max') or None
+ check_python_version('jython', jython_min, jython_max)
+
+ manifest = dict(cfg.items('manifest'))
+ try:
+ docs = dict(cfg.items('docs'))
+ except _config_parser.NoSectionError:
+ docs = {}
+
+ summary, description = find_description(docs)
+ scripts = manifest.get('scripts', '').strip() or None
+ if scripts:
+ scripts = scripts.split()
+ modules = manifest.get('modules', '').strip() or None
+ if modules:
+ modules = modules.split()
+ keywords = docs.get('meta.keywords', '').strip() or None
+ if keywords:
+ keywords = keywords.split()
+ revision = pkg.get('version.revision', '').strip()
+ if revision:
+ revision = "-r%s" % (revision,)
+
+ kwargs = {
+ 'name': pkg['name'],
+ 'version': "%s%s" % (
+ pkg['version.number'],
+ ["", "-dev%s" % (revision,)][_util.humanbool(
+ 'version.dev', pkg.get('version.dev', 'false')
+ )],
+ ),
+ 'provides': find_provides(docs),
+ 'description': summary,
+ 'long_description': description,
+ 'classifiers': find_classifiers(docs),
+ 'keywords': keywords,
+ 'author': pkg['author.name'],
+ 'author_email': pkg['author.email'],
+ 'maintainer': pkg.get('maintainer.name'),
+ 'maintainer_email': pkg.get('maintainer.email'),
+ 'url': pkg.get('url.homepage'),
+ 'download_url': pkg.get('url.download'),
+ 'license': find_license(docs),
+ 'package_dir': {'': manifest.get('packages.lib', '.')},
+ 'packages': find_packages(manifest),
+ 'py_modules': modules,
+ 'ext_modules': ext,
+ 'scripts': scripts,
+ 'script_args': script_args,
+ 'data_files': find_data(pkg['name'], docs),
+ 'cmdclass': {
+ 'build' : _commands.Build,
+ 'build_ext' : _commands.BuildExt,
+ 'install' : _commands.Install,
+ 'install_data': _commands.InstallData,
+ 'install_lib' : _commands.InstallLib,
+ }
+ }
+ for key in ('provides',):
+ if key not in _core.setup_keywords:
+ del kwargs[key]
+
+ if manifest_only:
+ return make_manifest(manifest, config, docs, kwargs)
+
+ # monkey-patch crappy manifest writer away.
+ from distutils.command import sdist
+ sdist.sdist.get_file_list = sdist.sdist.read_manifest
+
+ return _core.setup(**kwargs)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/shell.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/shell.py
new file mode 100644
index 00000000000..91f2ebc5b40
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/shell.py
@@ -0,0 +1,351 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Shell utilities
+=================
+
+Shell utilities.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import errno as _errno
+import fnmatch as _fnmatch
+import os as _os
+import shutil as _shutil
+import subprocess as _subprocess
+import sys as _sys
+import tempfile as _tempfile
+
+cwd = _os.path.dirname(_os.path.abspath(_sys.argv[0]))
+
+class ExitError(RuntimeError):
+ """ Exit error """
+ def __init__(self, code):
+ RuntimeError.__init__(self, code)
+ self.code = code
+ self.signal = None
+
+
+class SignalError(ExitError):
+ """ Signal error """
+ def __init__(self, code, signal):
+ ExitError.__init__(self, code)
+ import signal as _signal
+ self.signal = signal
+ for key, val in vars(_signal).items():
+ if key.startswith('SIG') and not key.startswith('SIG_'):
+ if val == signal:
+ self.signalstr = key[3:]
+ break
+ else:
+ self.signalstr = '%04d' % signal
+
+
+def native(path):
+ """ Convert slash path to native """
+ path = _os.path.sep.join(path.split('/'))
+ return _os.path.normpath(_os.path.join(cwd, path))
+
+
+def cp(src, dest):
+ """ Copy src to dest """
+ _shutil.copy2(native(src), native(dest))
+
+
+def cp_r(src, dest):
+ """ Copy -r src to dest """
+ _shutil.copytree(native(src), native(dest))
+
+
+def rm(dest):
+ """ Remove a file """
+ try:
+ _os.unlink(native(dest))
+ except OSError as e:
+ if _errno.ENOENT != e.errno:
+ raise
+
+def rm_rf(dest):
+ """ Remove a tree """
+ dest = native(dest)
+ if _os.path.exists(dest):
+ for path in files(dest, '*'):
+ _os.chmod(native(path), 0o644)
+ _shutil.rmtree(dest)
+
+
+mkstemp = _tempfile.mkstemp
+
+
+def _pipespawn(argv, env):
+ """ Pipe spawn """
+ # pylint: disable = R0912
+ import pickle as _pickle
+ fd, name = mkstemp('.py')
+ try:
+ _os.write(fd, ((r"""
+import os
+import pickle
+import subprocess
+import sys
+
+argv = pickle.loads(%(argv)s)
+env = pickle.loads(%(env)s)
+if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+p = subprocess.Popen(argv, env=env)
+result = p.wait()
+if result < 0:
+ print("\n%%d 1" %% (-result))
+ sys.exit(2)
+if result == 0:
+ sys.exit(0)
+print("\n%%d" %% (result & 7,))
+sys.exit(3)
+ """.strip() + "\n") % {
+ 'argv': repr(_pickle.dumps(argv)),
+ 'env': repr(_pickle.dumps(dict(env))),
+ }).encode('utf-8'))
+ fd, _ = None, _os.close(fd)
+ if _sys.platform == 'win32':
+ argv = []
+ for arg in [_sys.executable, name]:
+ if ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ argv.append(arg)
+ argv = ' '.join(argv)
+ shell = True
+ close_fds = False
+ else:
+ argv = [_sys.executable, name]
+ shell = False
+ close_fds = True
+
+ res = 0
+ if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+ proc = _subprocess.Popen(argv,
+ shell=shell,
+ stdin=_subprocess.PIPE,
+ stdout=_subprocess.PIPE,
+ close_fds=close_fds,
+ env=env,
+ )
+ try:
+ proc.stdin.close()
+ result = proc.stdout.read()
+ finally:
+ res = proc.wait()
+ if res != 0:
+ if res == 2:
+ signal, code = list(map(int, result.splitlines()[-1].split()))
+ raise SignalError(code, signal)
+ elif res == 3:
+ code = int(result.splitlines()[-1].strip())
+ raise ExitError(code)
+ raise ExitError(res)
+
+ return result.decode('latin-1')
+ finally:
+ try:
+ if fd is not None:
+ _os.close(fd)
+ finally:
+ _os.unlink(name)
+
+
+def _filepipespawn(infile, outfile, argv, env):
+ """ File Pipe spawn """
+ import pickle as _pickle
+ fd, name = mkstemp('.py')
+ try:
+ _os.write(fd, (("""
+import os
+import pickle
+import sys
+
+infile = pickle.loads(%(infile)s)
+outfile = pickle.loads(%(outfile)s)
+argv = pickle.loads(%(argv)s)
+env = pickle.loads(%(env)s)
+
+if infile is not None:
+ infile = open(infile, 'rb')
+ os.dup2(infile.fileno(), 0)
+ infile.close()
+if outfile is not None:
+ outfile = open(outfile, 'wb')
+ os.dup2(outfile.fileno(), 1)
+ outfile.close()
+
+pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
+result = os.waitpid(pid, 0)[1]
+sys.exit(result & 7)
+ """.strip() + "\n") % {
+ 'infile': repr(_pickle.dumps(_os.path.abspath(infile))),
+ 'outfile': repr(_pickle.dumps(_os.path.abspath(outfile))),
+ 'argv': repr(_pickle.dumps(argv)),
+ 'env': repr(_pickle.dumps(env)),
+ }).encode('utf-8'))
+ fd, _ = None, _os.close(fd)
+ if _sys.platform == 'win32':
+ argv = []
+ for arg in [_sys.executable, name]:
+ if ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ argv.append(arg)
+ argv = ' '.join(argv)
+ close_fds = False
+ shell = True
+ else:
+ argv = [_sys.executable, name]
+ close_fds = True
+ shell = False
+
+ p = _subprocess.Popen(
+ argv, env=env, shell=shell, close_fds=close_fds
+ )
+ return p.wait()
+ finally:
+ try:
+ if fd is not None:
+ _os.close(fd)
+ finally:
+ _os.unlink(name)
+
+
+def spawn(*argv, **kwargs):
+ """ Spawn a process """
+ if _sys.platform == 'win32':
+ newargv = []
+ for arg in argv:
+ if not arg or ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ newargv.append(arg)
+ argv = newargv
+ close_fds = False
+ shell = True
+ else:
+ close_fds = True
+ shell = False
+
+ env = kwargs.get('env')
+ if env is None:
+ env = dict(_os.environ)
+ if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+ echo = kwargs.get('echo')
+ if echo:
+ print(' '.join(argv))
+ filepipe = kwargs.get('filepipe')
+ if filepipe:
+ return _filepipespawn(
+ kwargs.get('stdin'), kwargs.get('stdout'), argv, env
+ )
+ pipe = kwargs.get('stdout')
+ if pipe:
+ return _pipespawn(argv, env)
+
+ p = _subprocess.Popen(argv, env=env, shell=shell, close_fds=close_fds)
+ return p.wait()
+
+
+walk = _os.walk
+
+
+def files(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
+ """ Determine a filelist """
+ for dirpath, dirnames, filenames in walk(native(base)):
+ for item in prune:
+ if item in dirnames:
+ dirnames.remove(item)
+
+ filenames.sort()
+ for name in _fnmatch.filter(filenames, wildcard):
+ dest = _os.path.join(dirpath, name)
+ if dest.startswith(cwd):
+ dest = dest.replace(cwd, '', 1)
+ aslist = []
+ head, tail = _os.path.split(dest)
+ while tail:
+ aslist.append(tail)
+ head, tail = _os.path.split(head)
+ aslist.reverse()
+ dest = '/'.join(aslist)
+ yield dest
+
+ if not recursive:
+ break
+ dirnames.sort()
+
+
+def dirs(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
+ """ Determine a filelist """
+ for dirpath, dirnames, filenames in walk(native(base)):
+ for item in prune:
+ if item in dirnames:
+ dirnames.remove(item)
+
+ dirnames.sort()
+ for name in _fnmatch.filter(dirnames, wildcard):
+ dest = _os.path.join(dirpath, name)
+ if dest.startswith(cwd):
+ dest = dest.replace(cwd, '', 1)
+ aslist = []
+ head, tail = _os.path.split(dest)
+ while tail:
+ aslist.append(tail)
+ head, tail = _os.path.split(head)
+ aslist.reverse()
+ dest = '/'.join(aslist)
+ yield dest
+
+ if not recursive:
+ break
+
+
+def frompath(executable):
+ """ Find executable in PATH """
+ # Based on distutils.spawn.find_executable.
+ path = _os.environ.get('PATH', '')
+ paths = [
+ _os.path.expanduser(item)
+ for item in path.split(_os.pathsep)
+ ]
+ ext = _os.path.splitext(executable)[1]
+ exts = ['']
+ if _sys.platform == 'win32' or _os.name == 'os2':
+ eext = ['.exe', '.bat', '.py']
+ if ext not in eext:
+ exts.extend(eext)
+
+ for ext in exts:
+ if not _os.path.isfile(executable + ext):
+ for path in paths:
+ fname = _os.path.join(path, executable + ext)
+ if _os.path.isfile(fname):
+ # the file exists, we have a shot at spawn working
+ return fname
+ else:
+ return executable + ext
+
+ return None
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/term/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/term/__init__.py
new file mode 100644
index 00000000000..5459454514b
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/term/__init__.py
@@ -0,0 +1,28 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=====================
+ Package _setup.term
+=====================
+
+Terminal tools, not distributed.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+# pylint: disable = W0611
+from _setup.term._term import terminfo, write, green, red, yellow, announce
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/term/_term.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/term/_term.py
new file mode 100644
index 00000000000..b94f58e27f1
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/term/_term.py
@@ -0,0 +1,116 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Terminal writer
+=================
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import sys as _sys
+
+
+class _INFO(dict):
+ """ Terminal info dict """
+
+ def __init__(self):
+ """ Initialization """
+ dict.__init__(self, {
+ 'NORMAL': '',
+ 'BOLD': '',
+ 'ERASE': '\n',
+ 'RED': '',
+ 'YELLOW': '',
+ 'GREEN': '',
+ })
+ try:
+ import curses as _curses
+ except ImportError:
+ # fixup if a submodule of curses failed.
+ if 'curses' in _sys.modules:
+ del _sys.modules['curses']
+ else:
+ try:
+ _curses.setupterm()
+ except (TypeError, _curses.error):
+ pass
+ else:
+ def make_color(color):
+ """ Make color control string """
+ seq = _curses.tigetstr('setaf').decode('ascii')
+ if seq is not None:
+ # XXX may fail - need better logic
+ seq = seq.replace("%p1", "") % color
+ return seq
+
+ self['NORMAL'] = _curses.tigetstr('sgr0').decode('ascii')
+ self['BOLD'] = _curses.tigetstr('bold').decode('ascii')
+
+ erase = _curses.tigetstr('el1').decode('ascii')
+ if erase is not None:
+ self['ERASE'] = erase + \
+ _curses.tigetstr('cr').decode('ascii')
+
+ self['RED'] = make_color(_curses.COLOR_RED)
+ self['YELLOW'] = make_color(_curses.COLOR_YELLOW)
+ self['GREEN'] = make_color(_curses.COLOR_GREEN)
+
+ def __getitem__(self, key):
+ """ Deliver always """
+ dict.get(self, key) or ""
+
+
+def terminfo():
+ """ Get info singleton """
+ # pylint: disable = E1101, W0612
+ if terminfo.info is None:
+ terminfo.info = _INFO()
+ return terminfo.info
+terminfo.info = None
+
+
+def write(fmt, **kwargs):
+ """ Write stuff on the terminal """
+ parm = dict(terminfo())
+ parm.update(kwargs)
+ _sys.stdout.write(fmt % parm)
+ _sys.stdout.flush()
+
+
+def green(bmt, **kwargs):
+ """ Write something in green on screen """
+ announce("%%(GREEN)s%s%%(NORMAL)s" % bmt, **kwargs)
+
+
+def red(bmt, **kwargs):
+ """ Write something in red on the screen """
+ announce("%%(BOLD)s%%(RED)s%s%%(NORMAL)s" % bmt, **kwargs)
+
+
+def yellow(fmt, **kwargs):
+ """ Write something in yellow on the screen """
+ announce("%%(BOLD)s%%(YELLOW)s%s%%(NORMAL)s" % fmt, **kwargs)
+
+
+def announce(fmt, **kwargs):
+ """ Announce something """
+ write(fmt, **kwargs)
+ _sys.stdout.write("\n")
+ _sys.stdout.flush()
+
+
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/util.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/util.py
new file mode 100644
index 00000000000..a07daa812fe
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/_setup/py3/util.py
@@ -0,0 +1,63 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Setup utilities
+=================
+
+Setup utilities.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from distutils import util as _util
+try:
+ from configparser import SafeConfigParser
+except ImportError:
+ import configparser as _config_parser
+ class SafeConfigParser(_config_parser.ConfigParser):
+ """ Safe config parser """
+ def _interpolate(self, section, option, rawval, vars):
+ return rawval
+
+ def items(self, section):
+ return [(key, self.get(section, key))
+ for key in self.options(section)
+ ]
+
+
+def humanbool(name, value):
+ """
+ Determine human boolean value
+
+ :Parameters:
+ `name` : ``str``
+ The config key (used for error message)
+
+ `value` : ``str``
+ The config value
+
+ :Return: The boolean value
+ :Rtype: ``bool``
+
+ :Exceptions:
+ - `ValueError` : The value could not be recognized
+ """
+ try:
+ return _util.strtobool(str(value).strip().lower() or 'no')
+ except ValueError:
+ raise ValueError("Unrecognized config value: %s = %s" % (name, value))
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/LICENSE.cssmin b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/LICENSE.cssmin
new file mode 100644
index 00000000000..c10ccb05c7a
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/LICENSE.cssmin
@@ -0,0 +1,64 @@
+`cssmin.py` - A Python port of the YUI CSS compressor.
+
+Copyright (c) 2010 Zachary Voase
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+-------------------------------------------------------------------------------
+
+This software contains portions of the YUI CSS Compressor, notably some regular
+expressions for reducing the size of CSS. The YUI Compressor source code can be
+found at <http://github.com/yui/yuicompressor>, and is licensed as follows:
+
+> YUI Compressor Copyright License Agreement (BSD License)
+>
+> Copyright (c) 2009, Yahoo! Inc.
+> All rights reserved.
+>
+> Redistribution and use of this software in source and binary forms,
+> with or without modification, are permitted provided that the following
+> conditions are met:
+>
+> * Redistributions of source code must retain the above
+> copyright notice, this list of conditions and the
+> following disclaimer.
+>
+> * Redistributions in binary form must reproduce the above
+> copyright notice, this list of conditions and the
+> following disclaimer in the documentation and/or other
+> materials provided with the distribution.
+>
+> * Neither the name of Yahoo! Inc. nor the names of its
+> contributors may be used to endorse or promote products
+> derived from this software without specific prior
+> written permission of Yahoo! Inc.
+>
+> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+> DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+> FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+> OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/__init__.py
new file mode 100644
index 00000000000..705dd0ccd1b
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/__init__.py
@@ -0,0 +1,30 @@
+# -*- coding: ascii -*-
+r"""
+=================================
+ Benchmark cssmin implementations
+=================================
+
+Benchmark cssmin implementations.
+
+:Copyright:
+
+ Copyright 2011 - 2014
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+"""
+if __doc__:
+ __doc__ = __doc__.encode('ascii').decode('unicode_escape')
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/cssmin.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/cssmin.py
new file mode 100644
index 00000000000..cbfbf8d4966
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/cssmin.py
@@ -0,0 +1,246 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""`cssmin` - A Python port of the YUI CSS compressor.
+
+:Copyright:
+
+ Copyright 2011 - 2014
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+"""
+
+try:
+ from StringIO import StringIO # The pure-Python StringIO supports unicode.
+except ImportError:
+ from io import StringIO
+import re
+
+
+__version__ = '0.2.0'
+
+
+def remove_comments(css):
+ """Remove all CSS comment blocks."""
+
+ iemac = False
+ preserve = False
+ comment_start = css.find("/*")
+ while comment_start >= 0:
+ # Preserve comments that look like `/*!...*/`.
+ # Slicing is used to make sure we don"t get an IndexError.
+ preserve = css[comment_start + 2:comment_start + 3] == "!"
+
+ comment_end = css.find("*/", comment_start + 2)
+ if comment_end < 0:
+ if not preserve:
+ css = css[:comment_start]
+ break
+ elif comment_end >= (comment_start + 2):
+ if css[comment_end - 1] == "\\":
+ # This is an IE Mac-specific comment; leave this one and the
+ # following one alone.
+ comment_start = comment_end + 2
+ iemac = True
+ elif iemac:
+ comment_start = comment_end + 2
+ iemac = False
+ elif not preserve:
+ css = css[:comment_start] + css[comment_end + 2:]
+ else:
+ comment_start = comment_end + 2
+ comment_start = css.find("/*", comment_start)
+
+ return css
+
+
+def remove_unnecessary_whitespace(css):
+ """Remove unnecessary whitespace characters."""
+
+ def pseudoclasscolon(css):
+
+ """
+ Prevents 'p :link' from becoming 'p:link'.
+
+ Translates 'p :link' into 'p ___PSEUDOCLASSCOLON___link'; this is
+ translated back again later.
+ """
+
+ regex = re.compile(r"(^|\})(([^\{\:])+\:)+([^\{]*\{)")
+ match = regex.search(css)
+ while match:
+ css = ''.join([
+ css[:match.start()],
+ match.group().replace(":", "___PSEUDOCLASSCOLON___"),
+ css[match.end():]])
+ match = regex.search(css)
+ return css
+
+ css = pseudoclasscolon(css)
+ # Remove spaces from before things.
+ css = re.sub(r"\s+([!{};:>+\(\)\],])", r"\1", css)
+
+ # If there is a `@charset`, then only allow one, and move to the beginning.
+ css = re.sub(r"^(.*)(@charset \"[^\"]*\";)", r"\2\1", css)
+ css = re.sub(r"^(\s*@charset [^;]+;\s*)+", r"\1", css)
+
+ # Put the space back in for a few cases, such as `@media screen` and
+ # `(-webkit-min-device-pixel-ratio:0)`.
+ css = re.sub(r"\band\(", "and (", css)
+
+ # Put the colons back.
+ css = css.replace('___PSEUDOCLASSCOLON___', ':')
+
+ # Remove spaces from after things.
+ css = re.sub(r"([!{}:;>+\(\[,])\s+", r"\1", css)
+
+ return css
+
+
+def remove_unnecessary_semicolons(css):
+ """Remove unnecessary semicolons."""
+
+ return re.sub(r";+\}", "}", css)
+
+
+def remove_empty_rules(css):
+ """Remove empty rules."""
+
+ return re.sub(r"[^\}\{]+\{\}", "", css)
+
+
+def normalize_rgb_colors_to_hex(css):
+ """Convert `rgb(51,102,153)` to `#336699`."""
+
+ regex = re.compile(r"rgb\s*\(\s*([0-9,\s]+)\s*\)")
+ match = regex.search(css)
+ while match:
+ colors = map(lambda s: s.strip(), match.group(1).split(","))
+ hexcolor = '#%.2x%.2x%.2x' % tuple(map(int, colors))
+ css = css.replace(match.group(), hexcolor)
+ match = regex.search(css)
+ return css
+
+
+def condense_zero_units(css):
+ """Replace `0(px, em, %, etc)` with `0`."""
+
+ return re.sub(r"([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)", r"\1\2", css)
+
+
+def condense_multidimensional_zeros(css):
+ """Replace `:0 0 0 0;`, `:0 0 0;` etc. with `:0;`."""
+
+ css = css.replace(":0 0 0 0;", ":0;")
+ css = css.replace(":0 0 0;", ":0;")
+ css = css.replace(":0 0;", ":0;")
+
+ # Revert `background-position:0;` to the valid `background-position:0 0;`.
+ css = css.replace("background-position:0;", "background-position:0 0;")
+
+ return css
+
+
+def condense_floating_points(css):
+ """Replace `0.6` with `.6` where possible."""
+
+ return re.sub(r"(:|\s)0+\.(\d+)", r"\1.\2", css)
+
+
+def condense_hex_colors(css):
+ """Shorten colors from #AABBCC to #ABC where possible."""
+
+ regex = re.compile(r"([^\"'=\s])(\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])")
+ match = regex.search(css)
+ while match:
+ first = match.group(3) + match.group(5) + match.group(7)
+ second = match.group(4) + match.group(6) + match.group(8)
+ if first.lower() == second.lower():
+ css = css.replace(match.group(), match.group(1) + match.group(2) + '#' + first)
+ match = regex.search(css, match.end() - 3)
+ else:
+ match = regex.search(css, match.end())
+ return css
+
+
+def condense_whitespace(css):
+ """Condense multiple adjacent whitespace characters into one."""
+
+ return re.sub(r"\s+", " ", css)
+
+
+def condense_semicolons(css):
+ """Condense multiple adjacent semicolon characters into one."""
+
+ return re.sub(r";;+", ";", css)
+
+
+def wrap_css_lines(css, line_length):
+ """Wrap the lines of the given CSS to an approximate length."""
+
+ lines = []
+ line_start = 0
+ for i, char in enumerate(css):
+ # It's safe to break after `}` characters.
+ if char == '}' and (i - line_start >= line_length):
+ lines.append(css[line_start:i + 1])
+ line_start = i + 1
+
+ if line_start < len(css):
+ lines.append(css[line_start:])
+ return '\n'.join(lines)
+
+
+def cssmin(css, wrap=None):
+ css = remove_comments(css)
+ css = condense_whitespace(css)
+ # A pseudo class for the Box Model Hack
+ # (see http://tantek.com/CSS/Examples/boxmodelhack.html)
+ css = css.replace('"\\"}\\""', "___PSEUDOCLASSBMH___")
+ css = remove_unnecessary_whitespace(css)
+ css = remove_unnecessary_semicolons(css)
+ css = condense_zero_units(css)
+ css = condense_multidimensional_zeros(css)
+ css = condense_floating_points(css)
+ css = normalize_rgb_colors_to_hex(css)
+ css = condense_hex_colors(css)
+ if wrap is not None:
+ css = wrap_css_lines(css, wrap)
+ css = css.replace("___PSEUDOCLASSBMH___", '"\\"}\\""')
+ css = condense_semicolons(css)
+ return css.strip()
+
+
+def main():
+ import optparse
+ import sys
+
+ p = optparse.OptionParser(
+ prog="cssmin", version=__version__,
+ usage="%prog [--wrap N]",
+ description="""Reads raw CSS from stdin, and writes compressed CSS to stdout.""")
+
+ p.add_option(
+ '-w', '--wrap', type='int', default=None, metavar='N',
+ help="Wrap output to approximately N chars per line.")
+
+ options, args = p.parse_args()
+ sys.stdout.write(cssmin(sys.stdin.read(), wrap=options.wrap))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/main.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/main.py
new file mode 100644
index 00000000000..078150629f2
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/main.py
@@ -0,0 +1,236 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+r"""
+==================================
+ Benchmark cssmin implementations
+==================================
+
+Benchmark cssmin implementations.
+
+:Copyright:
+
+ Copyright 2011 - 2014
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+Usage::
+
+ python -mbench.main [-c COUNT] [-p file] cssfile ...
+
+ -c COUNT number of runs per cssfile and minifier. Defaults to 10.
+ -p file File to write the benchmark results in (pickled)
+
+"""
+if __doc__:
+ __doc__ = __doc__.encode('ascii').decode('unicode_escape')
+__author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
+__docformat__ = "restructuredtext en"
+__license__ = "Apache License, Version 2.0"
+__version__ = "1.0.0"
+
+import sys as _sys
+import time as _time
+
+import_notes = []
+class _p_02__rcssmin(object):
+ def __init__(self):
+ import rcssmin
+ cssmin = rcssmin._make_cssmin(python_only=True)
+ self.cssmin = lambda x: cssmin(x, keep_bang_comments=True)
+
+class _p_03__rcssmin(object):
+ def __init__(self):
+ import _rcssmin
+ cssmin = _rcssmin.cssmin
+ self.cssmin = lambda x: cssmin(x, keep_bang_comments=True)
+
+class cssmins(object):
+ from bench import cssmin as p_01_cssmin
+ p_02_rcssmin = _p_02__rcssmin()
+ try:
+ p_03__rcssmin = _p_03__rcssmin()
+ except ImportError:
+ import_notes.append("_rcssmin (C-Port) not available")
+ print(import_notes[-1])
+
+print("Python Release: %s" % ".".join(map(str, _sys.version_info[:3])))
+print("")
+
+
+def slurp(filename):
+ """ Load a file """
+ fp = open(filename)
+ try:
+ return fp.read()
+ finally:
+ fp.close()
+
+
+def print_(*value, **kwargs):
+ """ Print stuff """
+ (kwargs.get('file') or _sys.stdout).write(
+ ''.join(value) + kwargs.get('end', '\n')
+ )
+
+
+def bench(filenames, count):
+ """
+ Benchmark the minifiers with given css samples
+
+ :Parameters:
+ `filenames` : sequence
+ List of filenames
+
+ `count` : ``int``
+ Number of runs per css file and minifier
+
+ :Exceptions:
+ - `RuntimeError` : empty filenames sequence
+ """
+ if not filenames:
+ raise RuntimeError("Missing files to benchmark")
+ try:
+ xrange
+ except NameError:
+ xrange = range
+ try:
+ cmp
+ except NameError:
+ cmp = lambda a, b: (a > b) - (a < b)
+
+ ports = [item for item in dir(cssmins) if item.startswith('p_')]
+ ports.sort()
+ space = max(map(len, ports)) - 4
+ ports = [(item[5:], getattr(cssmins, item).cssmin) for item in ports]
+ flush = _sys.stdout.flush
+
+ struct = []
+ inputs = [(filename, slurp(filename)) for filename in filenames]
+ for filename, style in inputs:
+ print_("Benchmarking %r..." % filename, end=" ")
+ flush()
+ outputs = []
+ for _, cssmin in ports:
+ try:
+ outputs.append(cssmin(style))
+ except (SystemExit, KeyboardInterrupt):
+ raise
+ except:
+ outputs.append(None)
+ struct.append(dict(
+ filename=filename,
+ sizes=[
+ (item is not None and len(item) or None) for item in outputs
+ ],
+ size=len(style),
+ messages=[],
+ times=[],
+ ))
+ print_("(%.1f KiB)" % (struct[-1]['size'] / 1024.0,))
+ flush()
+ times = []
+ for idx, (name, cssmin) in enumerate(ports):
+ if outputs[idx] is None:
+ print_(" FAILED %s" % (name,))
+ struct[-1]['times'].append((name, None))
+ else:
+ print_(" Timing %s%s... (%5.1f KiB %s)" % (
+ name,
+ " " * (space - len(name)),
+ len(outputs[idx]) / 1024.0,
+ idx == 0 and '*' or ['=', '>', '<'][
+ cmp(len(outputs[idx]), len(outputs[0]))
+ ],
+ ), end=" ")
+ flush()
+
+ xcount = count
+ while True:
+ counted = [None for _ in xrange(xcount)]
+ start = _time.time()
+ for _ in counted:
+ cssmin(style)
+ end = _time.time()
+ result = (end - start) * 1000
+ if result < 10: # avoid measuring within the error range
+ xcount *= 10
+ continue
+ times.append(result / xcount)
+ break
+
+ print_("%8.2f ms" % times[-1], end=" ")
+ flush()
+ if len(times) <= 1:
+ print_()
+ else:
+ print_("(factor: %s)" % (', '.join([
+ '%.2f' % (timed / times[-1]) for timed in times[:-1]
+ ])))
+ struct[-1]['times'].append((name, times[-1]))
+
+ flush()
+ print_()
+
+ return struct
+
+
+def main(argv=None):
+ """ Main """
+ import getopt as _getopt
+ import os as _os
+ import pickle as _pickle
+
+ if argv is None:
+ argv = _sys.argv[1:]
+ try:
+ opts, args = _getopt.getopt(argv, "hc:p:", ["help"])
+ except getopt.GetoptError:
+ e = _sys.exc_info()[0](_sys.exc_info()[1])
+ print >> _sys.stderr, "%s\nTry %s -mbench.main --help" % (
+ e,
+ _os.path.basename(_sys.executable),
+ )
+ _sys.exit(2)
+
+ count, pickle = 10, None
+ for key, value in opts:
+ if key in ("-h", "--help"):
+ print >> _sys.stderr, (
+ "%s -mbench.main [-c count] [-p file] cssfile ..." % (
+ _os.path.basename(_sys.executable),
+ )
+ )
+ _sys.exit(0)
+ elif key == '-c':
+ count = int(value)
+ elif key == '-p':
+ pickle = str(value)
+
+ struct = bench(args, count)
+ if pickle:
+ fp = open(pickle, 'wb')
+ try:
+ fp.write(_pickle.dumps((
+ ".".join(map(str, _sys.version_info[:3])),
+ import_notes,
+ struct,
+ ), 0))
+ finally:
+ fp.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/wikipedia.css b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/wikipedia.css
new file mode 100644
index 00000000000..03079e35a6f
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/wikipedia.css
@@ -0,0 +1,3861 @@
+/*
+ * This CSS is taken from wikipedia / mediawiki, it's the combined files of
+ * the vector skin described at:
+ *
+ * http://en.wikipedia.org/wiki/Wikipedia:Catalogue_of_CSS_classes
+ */
+
+/*
+ * Any rules which should not be flipped automatically in right-to-left situations should be
+ * prepended with @noflip in a comment block. Images that should be embedded as base64 data-URLs
+ * should be prepended with @embed in a comment block.
+ *
+ * This style-sheet employs a few CSS trick to accomplish compatibility with a wide range of web
+ * browsers. The most common trick is to use some styles in IE6 only. This is accomplished by using
+ * a rule that makes things work in IE6, and then following it with a rule that begins with
+ * "html > body" or use a child selector ">", which is ignored by IE6 because it does not support
+ * the child selector. You can spot this by looking for the "OVERRIDDEN BY COMPLIANT BROWSERS" and
+ * "IGNORED BY IE6" comments.
+ */
+
+/* Framework */
+html,
+body {
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+body {
+ background-color: #f3f3f3;
+ /* @embed */
+ background-image: url(images/page-base.png);
+}
+/* Content */
+div#content {
+ margin-left: 10em;
+ padding: 1em;
+ /* @embed */
+ background-image: url(images/border.png);
+ background-position: top left;
+ background-repeat: repeat-y;
+ background-color: white;
+ color: black;
+ direction: ltr;
+}
+/* Head */
+#mw-page-base {
+ height: 5em;
+ background-color: white;
+ /* @embed */
+ background-image: url(images/page-fade.png);
+ background-position: bottom left;
+ background-repeat: repeat-x;
+}
+#mw-head-base {
+ margin-top: -5em;
+ margin-left: 10em;
+ height: 5em;
+ /* @embed */
+ background-image: url(images/border.png);
+ background-position: bottom left;
+ background-repeat: repeat-x;
+}
+div#mw-head {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 100%;
+}
+div#mw-head h5 {
+ margin: 0;
+ padding: 0;
+}
+/* Hide empty portlets */
+div.emptyPortlet {
+ display: none;
+}
+/* Personal */
+#p-personal {
+ position: absolute;
+ top: 0;
+ right: 0.75em;
+}
+#p-personal h5 {
+ display: none;
+}
+#p-personal ul {
+ list-style: none;
+ margin: 0;
+ padding-left: 10em; /* Keep from overlapping logo */
+}
+/* @noflip */
+#p-personal li {
+ line-height: 1.125em;
+ float: left;
+}
+/* This one flips! */
+#p-personal li {
+ margin-left: 0.75em;
+ margin-top: 0.5em;
+ font-size: 0.75em;
+ white-space: nowrap;
+}
+/* Navigation Containers */
+#left-navigation {
+ position: absolute;
+ left: 10em;
+ top: 2.5em;
+}
+#right-navigation {
+ float: right;
+ margin-top: 2.5em;
+}
+/* Navigation Labels */
+div.vectorTabs h5,
+div.vectorMenu h5 span {
+ display: none;
+}
+/* Namespaces and Views */
+/* @noflip */
+div.vectorTabs {
+ float: left;
+ height: 2.5em;
+}
+div.vectorTabs {
+ /* @embed */
+ background-image: url(images/tab-break.png);
+ background-position: bottom left;
+ background-repeat: no-repeat;
+ padding-left: 1px;
+}
+/* @noflip */
+div.vectorTabs ul {
+ float: left;
+}
+div.vectorTabs ul {
+ height: 100%;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+/* @noflip */
+div.vectorTabs ul li {
+ float: left;
+}
+/* OVERRIDDEN BY COMPLIANT BROWSERS */
+div.vectorTabs ul li {
+ line-height: 1.125em;
+ display: inline-block;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ background-color: #f3f3f3;
+ /* @embed */
+ background-image: url(images/tab-normal-fade.png);
+ background-position: bottom left;
+ background-repeat: repeat-x;
+ white-space:nowrap;
+}
+/* IGNORED BY IE6 */
+div.vectorTabs ul > li {
+ display: block;
+}
+div.vectorTabs li.selected {
+ /* @embed */
+ background-image: url(images/tab-current-fade.png);
+}
+/* OVERRIDDEN BY COMPLIANT BROWSERS */
+div.vectorTabs li a {
+ display: inline-block;
+ height: 1.9em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ color: #0645ad;
+ cursor: pointer;
+ font-size: 0.8em;
+}
+/* IGNORED BY IE6 */
+div.vectorTabs li > a {
+ display: block;
+}
+div.vectorTabs li.icon a {
+ background-position: bottom right;
+ background-repeat: no-repeat;
+}
+/* OVERRIDDEN BY COMPLIANT BROWSERS */
+div.vectorTabs span a {
+ display: inline-block;
+ padding-top: 1.25em;
+}
+/* IGNORED BY IE6 */
+/* @noflip */
+div.vectorTabs span > a {
+ float: left;
+ display: block;
+}
+div.vectorTabs span {
+ display: inline-block;
+ /* @embed */
+ background-image: url(images/tab-break.png);
+ background-position: bottom right;
+ background-repeat: no-repeat;
+}
+div.vectorTabs li.selected a,
+div.vectorTabs li.selected a:visited{
+ color: #333333;
+ text-decoration: none;
+}
+div.vectorTabs li.new a,
+div.vectorTabs li.new a:visited{
+ color: #a55858;
+}
+/* Variants and Actions */
+/* @noflip */
+div.vectorMenu {
+ direction: ltr;
+ float: left;
+ /* @embed */
+ background-image: url(images/arrow-down-icon.png);
+ background-position: 100% 60%;
+ background-repeat: no-repeat;
+ cursor: pointer;
+}
+div.vectorMenuFocus {
+ /* @embed */
+ background-image: url(images/arrow-down-focus-icon.png);
+ background-position: 100% 60%;
+}
+/* @noflip */
+body.rtl div.vectorMenu {
+ direction: rtl;
+}
+/* OVERRIDDEN BY COMPLIANT BROWSERS */
+/* @noflip */
+div#mw-head div.vectorMenu h5 {
+ float: left;
+ /* @embed */
+ background-image: url(images/tab-break.png);
+ background-repeat: no-repeat;
+}
+/* This will be flipped - unlike the one above it */
+div#mw-head div.vectorMenu h5 {
+ background-position: bottom left;
+ margin-left: -1px;
+}
+/* IGNORED BY IE6 */
+div#mw-head div.vectorMenu > h5 {
+ background-image: none;
+}
+div#mw-head div.vectorMenu h4 {
+ display: inline-block;
+ float: left;
+ font-size: 0.8em;
+ padding-left: 0.5em;
+ padding-top: 1.375em;
+ font-weight: normal;
+ border: none;
+}
+/* OVERRIDDEN BY COMPLIANT BROWSERS */
+/* @noflip */
+div.vectorMenu h5 a {
+ display: inline-block;
+ width: 24px;
+ height: 2.5em;
+ text-decoration: none;
+ /* @embed */
+ background-image: url(images/tab-break.png);
+ background-repeat: no-repeat;
+}
+/* This will be flipped - unlike the one above it */
+div.vectorMenu h5 a {
+ background-position: bottom right;
+}
+/* IGNORED BY IE6 */
+div.vectorMenu h5 > a {
+ display: block;
+}
+div.vectorMenu div.menu {
+ position: relative;
+ display: none;
+ clear: both;
+ text-align: left;
+}
+/* OVERRIDDEN BY COMPLIANT BROWSERS */
+/* @noflip */
+body.rtl div.vectorMenu div.menu {
+ margin-left: 24px;
+}
+/* IGNORED BY IE6 */
+/* @noflip */
+body.rtl div.vectorMenu > div.menu {
+ margin-left: auto;
+}
+/* IGNORED BY IE6 */
+/* Also fixes old versions of FireFox */
+/* @noflip */
+body.rtl div.vectorMenu > div.menu,
+x:-moz-any-link {
+ margin-left: 23px;
+}
+/* Enable forcing showing of the menu for accessibility */
+div.vectorMenu:hover div.menu,
+div.vectorMenu div.menuForceShow {
+ display: block;
+}
+div.vectorMenu ul {
+ position: absolute;
+ background-color: white;
+ border: solid 1px silver;
+ border-top-width: 0;
+ list-style: none;
+ list-style-image: none;
+ list-style-type: none;
+ padding: 0;
+ margin: 0;
+ margin-left: -1px;
+ text-align: left;
+}
+/* Fixes old versions of FireFox */
+div.vectorMenu ul,
+x:-moz-any-link {
+ min-width: 5em;
+}
+/* Returns things back to normal in modern versions of FireFox */
+div.vectorMenu ul,
+x:-moz-any-link,
+x:default {
+ min-width: 0;
+}
+div.vectorMenu li {
+ padding: 0;
+ margin: 0;
+ text-align: left;
+ line-height: 1em;
+}
+/* OVERRIDDEN BY COMPLIANT BROWSERS */
+div.vectorMenu li a {
+ display: inline-block;
+ padding: 0.5em;
+ white-space: nowrap;
+ color: #0645ad;
+ cursor: pointer;
+ font-size: 0.8em;
+}
+/* IGNORED BY IE6 */
+div.vectorMenu li > a {
+ display: block;
+}
+div.vectorMenu li.selected a,
+div.vectorMenu li.selected a:visited {
+ color: #333333;
+ text-decoration: none;
+}
+/* Search */
+#p-search h5 {
+ display: none;
+}
+/* @noflip */
+#p-search {
+ float: left;
+}
+#p-search {
+ margin-right: 0.5em;
+ margin-left: 0.5em;
+}
+#p-search form,
+#p-search input {
+ margin: 0;
+ margin-top: 0.4em;
+}
+div#simpleSearch {
+ display: block;
+ width: 14em;
+ height: 1.4em;
+ margin-top: 0.65em;
+ position: relative;
+ min-height: 1px; /* Gotta trigger hasLayout for IE7 */
+ border: solid 1px #AAAAAA;
+ color: black;
+ background-color: white;
+ /* @embed */
+ background-image: url(images/search-fade.png);
+ background-position: top left;
+ background-repeat: repeat-x;
+}
+div#simpleSearch label {
+ /*
+ * DON'T PANIC! Browsers that won't scale this properly are the same browsers that have JS issues that prevent
+ * this from ever being shown anyways.
+ */
+ font-size: 13px;
+ top: 0.25em;
+ direction: ltr;
+}
+div#simpleSearch input {
+ color: black;
+ direction: ltr;
+}
+div#simpleSearch input:focus {
+ outline: none;
+}
+div#simpleSearch input.placeholder {
+ color: #999999;
+}
+div#simpleSearch input::-webkit-input-placeholder {
+ color: #999999;
+}
+div#simpleSearch input#searchInput {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 90%;
+ margin: 0;
+ padding: 0;
+ padding-left: 0.2em;
+ padding-top: 0.2em;
+ padding-bottom: 0.2em;
+ outline: none;
+ border: none;
+ /*
+ * DON'T PANIC! Browsers that won't scale this properly are the same browsers that have JS issues that prevent
+ * this from ever being shown anyways.
+ */
+ font-size: 13px;
+ background-color: transparent;
+ direction: ltr;
+}
+div#simpleSearch button#searchButton {
+ position: absolute;
+ width: 10%;
+ right: 0;
+ top: 0;
+ padding: 0;
+ padding-top: 0.3em;
+ padding-bottom: 0.2em;
+ padding-right: 0.4em;
+ margin: 0;
+ border: none;
+ cursor: pointer;
+ background-color: transparent;
+ background-image: none;
+}
+/* OVERRIDDEN BY COMPLIANT BROWSERS */
+div#simpleSearch button#searchButton img {
+ border: none;
+ margin: 0;
+ margin-top: -3px;
+ padding: 0;
+}
+/* IGNORED BY IE6 */
+div#simpleSearch button#searchButton > img {
+ margin: 0;
+}
+/* Panel */
+div#mw-panel {
+ position: absolute;
+ top: 160px;
+ padding-top: 1em;
+ width: 10em;
+ left: 0;
+}
+div#mw-panel div.portal {
+ padding-bottom: 1.5em;
+ direction: ltr;
+}
+div#mw-panel div.portal h5 {
+ font-weight: normal;
+ color: #444444;
+ padding: 0.25em;
+ padding-top: 0;
+ padding-left: 1.75em;
+ cursor: default;
+ border: none;
+ font-size: 0.75em;
+}
+div#mw-panel div.portal div.body {
+ margin: 0;
+ padding-top: 0.5em;
+ margin-left: 1.25em;
+ /* @embed */
+ background-image: url(images/portal-break.png);
+ background-repeat: no-repeat;
+ background-position: top left;
+}
+div#mw-panel div.portal div.body ul {
+ list-style: none;
+ list-style-image: none;
+ list-style-type: none;
+ padding: 0;
+ margin: 0;
+}
+div#mw-panel div.portal div.body ul li {
+ line-height: 1.125em;
+ padding: 0;
+ padding-bottom: 0.5em;
+ margin: 0;
+ overflow: hidden;
+ font-size: 0.75em;
+}
+div#mw-panel div.portal div.body ul li a {
+ color: #0645ad;
+}
+div#mw-panel div.portal div.body ul li a:visited {
+ color: #0b0080;
+}
+/* Footer */
+div#footer {
+ margin-left: 10em;
+ margin-top: 0;
+ padding: 0.75em;
+ /* @embed */
+ background-image: url(images/border.png);
+ background-position: top left;
+ background-repeat: repeat-x;
+ direction: ltr;
+}
+div#footer ul {
+ list-style: none;
+ list-style-image: none;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+div#footer ul li {
+ margin: 0;
+ padding: 0;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ color: #333333;
+ font-size: 0.7em;
+}
+div#footer #footer-icons {
+ float: right;
+}
+/* @noflip */
+body.ltr div#footer #footer-places {
+ float: left;
+}
+div#footer #footer-info li {
+ line-height: 1.4em;
+}
+div#footer #footer-icons li {
+ float: left;
+ margin-left: 0.5em;
+ line-height: 2em;
+ text-align: right;
+}
+div#footer #footer-places li {
+ float: left;
+ margin-right: 1em;
+ line-height: 2em;
+}
+/* Logo */
+#p-logo {
+ position: absolute;
+ top: -160px;
+ left: 0;
+ width: 10em;
+ height: 160px;
+}
+#p-logo a {
+ display: block;
+ width: 10em;
+ height: 160px;
+ background-repeat: no-repeat;
+ background-position: center center;
+ text-decoration: none;
+}
+
+/*
+ *
+ * The following code is highly modified from monobook. It would be nice if the
+ * preftoc id was more human readable like preferences-toc for instance,
+ * howerver this would require backporting the other skins.
+ */
+
+/* Preferences */
+#preftoc {
+ /* Tabs */
+ width: 100%;
+ float: left;
+ clear: both;
+ margin: 0 !important;
+ padding: 0 !important;
+ /* @embed */
+ background-image: url(images/preferences-break.png);
+ background-position: bottom left;
+ background-repeat: no-repeat;
+}
+ #preftoc li {
+ /* Tab */
+ float: left;
+ margin: 0;
+ padding: 0;
+ padding-right: 1px;
+ height: 2.25em;
+ white-space: nowrap;
+ list-style-type: none;
+ list-style-image: none;
+ /* @embed */
+ background-image: url(images/preferences-break.png);
+ background-position: bottom right;
+ background-repeat: no-repeat;
+ }
+ /* Sadly, IE6 won't understand this */
+ #preftoc li:first-child {
+ margin-left: 1px;
+ }
+ #preftoc a,
+ #preftoc a:active {
+ display: inline-block;
+ position: relative;
+ color: #0645ad;
+ padding: 0.5em;
+ text-decoration: none;
+ background-image: none;
+ font-size: 0.9em;
+ }
+ #preftoc a:hover,
+ #preftoc a:focus {
+ text-decoration: underline;
+ }
+ #preftoc li.selected a {
+ /* @embed */
+ background-image: url(images/preferences-fade.png);
+ background-position: bottom;
+ background-repeat: repeat-x;
+ color: #333333;
+ text-decoration: none;
+ }
+#preferences {
+ float: left;
+ width: 100%;
+ margin: 0;
+ margin-top: -2px;
+ clear: both;
+ border: solid 1px #cccccc;
+ background-color: #f9f9f9;
+ /* @embed */
+ background-image: url(images/preferences-base.png);
+}
+#preferences fieldset {
+ border: none;
+ border-top: solid 1px #cccccc;
+}
+#preferences fieldset.prefsection {
+ border: none;
+ padding: 0;
+ margin: 1em;
+}
+#preferences legend {
+ color: #666666;
+}
+#preferences fieldset.prefsection legend.mainLegend {
+ display: none;
+}
+#preferences td {
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+}
+#preferences td.htmlform-tip {
+ font-size: x-small;
+ padding: .2em 2em;
+ color: #666666;
+}
+#preferences div.mw-prefs-buttons {
+ padding: 1em;
+}
+#preferences div.mw-prefs-buttons input {
+ margin-right: 0.25em;
+}
+
+/**
+ * The following code is slightly modified from monobook
+ */
+div#content {
+ line-height: 1.5em;
+}
+#bodyContent {
+ font-size: 0.8em;
+}
+
+.editsection {
+ float: right;
+}
+
+ul {
+ /* @embed */
+ list-style-image: url(images/bullet-icon.png);
+}
+
+pre {
+ line-height: 1.3em;
+}
+
+/* Site Notice (includes notices from CentralNotice extension) */
+#siteNotice {
+ font-size: 0.8em;
+}
+#firstHeading {
+ padding-top: 0;
+ margin-top: 0;
+ padding-top: 0;
+ font-size: 1.6em;
+}
+div#content a.external,
+div#content a.external[href ^="gopher://"] {
+ /* @embed */
+ background: url(images/external-link-ltr-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+div#content a.external[href ^="https://"],
+.link-https {
+ /* @embed */
+ background: url(images/lock-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+div#content a.external[href ^="mailto:"],
+.link-mailto {
+ /* @embed */
+ background: url(images/mail-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+div#content a.external[href ^="news:"] {
+ /* @embed */
+ background: url(images/news-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+div#content a.external[href ^="ftp://"],
+.link-ftp {
+ /* @embed */
+ background: url(images/file-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+div#content a.external[href ^="irc://"],
+div#content a.external[href ^="ircs://"],
+.link-irc {
+ /* @embed */
+ background: url(images/talk-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+div#content a.external[href $=".ogg"], div#content a.external[href $=".OGG"],
+div#content a.external[href $=".mid"], div#content a.external[href $=".MID"],
+div#content a.external[href $=".midi"], div#content a.external[href $=".MIDI"],
+div#content a.external[href $=".mp3"], div#content a.external[href $=".MP3"],
+div#content a.external[href $=".wav"], div#content a.external[href $=".WAV"],
+div#content a.external[href $=".wma"], div#content a.external[href $=".WMA"],
+.link-audio {
+ /* @embed */
+ background: url(images/audio-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+div#content a.external[href $=".ogm"], div#content a.external[href $=".OGM"],
+div#content a.external[href $=".avi"], div#content a.external[href $=".AVI"],
+div#content a.external[href $=".mpeg"], div#content a.external[href $=".MPEG"],
+div#content a.external[href $=".mpg"], div#content a.external[href $=".MPG"],
+.link-video {
+ /* @embed */
+ background: url(images/video-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+div#content a.external[href $=".pdf"], div#content a.external[href $=".PDF"],
+div#content a.external[href *=".pdf#"], div#content a.external[href *=".PDF#"],
+div#content a.external[href *=".pdf?"], div#content a.external[href *=".PDF?"],
+.link-document {
+ /* @embed */
+ background: url(images/document-icon.png) center right no-repeat;
+ padding-right: 13px;
+}
+
+/* Icon for Usernames */
+#pt-userpage,
+#pt-anonuserpage,
+#pt-login {
+ /* @embed */
+ background: url(images/user-icon.png) left top no-repeat;
+ padding-left: 15px !important;
+ text-transform: none;
+}
+
+.redirectText {
+ font-size: 140%;
+}
+
+.redirectMsg img {
+ vertical-align: text-bottom;
+}
+
+#bodyContent {
+ position: relative;
+ width: 100%;
+}
+#mw-js-message {
+ font-size: 0.8em;
+}
+div#bodyContent {
+ line-height: 1.5em;
+}
+
+/* Watch/Unwatch Icon Styling */
+#ca-unwatch.icon a,
+#ca-watch.icon a {
+ margin: 0;
+ padding: 0;
+ outline: none;
+ display: block;
+ width: 26px;
+ /* This hides the text but shows the background image */
+ padding-top: 3.1em;
+ margin-top: 0;
+ /* Only applied in IE6 */
+ margin-top: -0.8em !ie;
+ height: 0;
+ overflow: hidden;
+ /* @embed */
+ background-image: url(images/watch-icons.png);
+}
+#ca-unwatch.icon a {
+ background-position: -43px 60%;
+}
+#ca-watch.icon a {
+ background-position: 5px 60%;
+}
+#ca-unwatch.icon a:hover,
+#ca-unwatch.icon a:focus {
+ background-position: -67px 60%;
+}
+#ca-watch.icon a:hover,
+#ca-watch.icon a:focus {
+ background-position: -19px 60%;
+}
+#ca-unwatch.icon a.loading,
+#ca-watch.icon a.loading {
+ /* @embed */
+ background-image: url(images/watch-icon-loading.gif);
+ background-position: 5px 60%;
+}
+#ca-unwatch.icon a span,
+#ca-watch.icon a span {
+ display: none;
+}
+div.vectorTabs ul {
+ /* @embed */
+ background-image:url(images/tab-break.png);
+ background-position:right bottom;
+ background-repeat:no-repeat;
+}
+
+/* Tooltips are outside of the normal body code, so this helps make the size of the text sensible */
+.tipsy {
+ font-size: 0.8em;
+}
+/**
+ * CSS in this file is used by *all* skins (that have any CSS at all). Be
+ * careful what you put in here, since what looks good in one skin may not in
+ * another, but don't ignore the poor pre-Monobook users either.
+ */
+
+/* GENERAL CLASSES FOR DIRECTIONALITY SUPPORT */
+
+/**
+ * These classes should be used for text depending on the content direction.
+ * Content stuff like editsection, ul/ol and TOC depend on this.
+ */
+.mw-content-ltr {
+ /* @noflip */
+ direction: ltr;
+}
+.mw-content-rtl {
+ /* @noflip */
+ direction: rtl;
+}
+
+/* Most input fields should be in site direction */
+.sitedir-ltr textarea,
+.sitedir-ltr input {
+ /* @noflip */
+ direction: ltr;
+}
+.sitedir-rtl textarea,
+.sitedir-rtl input {
+ /* @noflip */
+ direction: rtl;
+}
+
+/* Input types that should follow user direction, like buttons */
+/* TODO: What about buttons in wikipage content ? */
+input[type="submit"],
+input[type="button"],
+input[type="reset"],
+input[type="file"] {
+ direction: ltr;
+}
+
+/* Override default values */
+textarea[dir="ltr"],
+input[dir="ltr"] {
+ /* @noflip */
+ direction: ltr;
+}
+textarea[dir="rtl"],
+input[dir="rtl"] {
+ /* @noflip */
+ direction: rtl;
+}
+
+/* Default style for semantic tags */
+abbr,
+acronym,
+.explain {
+ border-bottom: 1px dotted;
+ cursor: help;
+}
+
+/* Colored watchlist and recent changes numbers */
+.mw-plusminus-pos {
+ color: #006400; /* dark green */
+}
+.mw-plusminus-neg {
+ color: #8b0000; /* dark red */
+}
+.mw-plusminus-null {
+ color: #aaa; /* gray */
+}
+
+/**
+ * Links to redirects appear italicized on [[Special:AllPages]], [[Special:PrefixIndex]],
+ * [[Special:Watchlist/edit]] and in category listings.
+ */
+.allpagesredirect,
+.redirect-in-category,
+.watchlistredir {
+ font-style: italic;
+}
+
+/* Comment and username portions of RC entries */
+span.comment {
+ font-style: italic;
+}
+
+span.changedby {
+ font-size: 95%;
+}
+
+/* Math */
+.texvc {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+img.tex {
+ vertical-align: middle;
+}
+span.texhtml {
+ font-family: serif;
+}
+
+/**
+ * Add a bit of margin space between the preview and the toolbar.
+ * This replaces the ugly <p><br /></p> we used to insert into the page source
+ */
+#wikiPreview.ontop {
+ margin-bottom: 1em;
+}
+
+/* Stop floats from intruding into edit area in previews */
+#editform,
+#toolbar,
+#wpTextbox1 {
+ clear: both;
+}
+#toolbar img {
+ cursor: pointer;
+}
+div#mw-js-message {
+ margin: 1em 5%;
+ padding: 0.5em 2.5%;
+ border: solid 1px #ddd;
+ background-color: #fcfcfc;
+}
+
+/* Edit section links */
+.editsection {
+ float: right;
+ margin-left: 5px;
+}
+/* Correct directionality when page dir is different from site/user dir */
+.mw-content-ltr .editsection,
+.mw-content-rtl .mw-content-ltr .editsection {
+ /* @noflip */
+ float: right;
+}
+.mw-content-rtl .editsection,
+.mw-content-ltr .mw-content-rtl .editsection {
+ /* @noflip */
+ float: left;
+}
+
+/**
+ * File description page
+ */
+
+div.mw-filepage-resolutioninfo {
+ font-size: smaller;
+}
+
+/**
+ * File histories
+ */
+h2#filehistory {
+ clear: both;
+}
+
+table.filehistory th,
+table.filehistory td {
+ vertical-align: top;
+}
+table.filehistory th {
+ text-align: left;
+}
+table.filehistory td.mw-imagepage-filesize,
+table.filehistory th.mw-imagepage-filesize {
+ white-space: nowrap;
+}
+
+table.filehistory td.filehistory-selected {
+ font-weight: bold;
+}
+
+/**
+ * Add a checkered background image on hover for file
+ * description pages. (bug 26470)
+ */
+.filehistory a img,
+#file img:hover {
+ /* @embed */
+ background: white url(images/Checker-16x16.png) repeat;
+}
+
+/**
+ * rev_deleted stuff
+ */
+li span.deleted,
+span.history-deleted {
+ text-decoration: line-through;
+ color: #888;
+ font-style: italic;
+}
+
+/**
+ * Patrol stuff
+ */
+.not-patrolled {
+ background-color: #ffa;
+}
+
+.unpatrolled {
+ font-weight: bold;
+ color: red;
+}
+
+div.patrollink {
+ font-size: 75%;
+ text-align: right;
+}
+
+/**
+ * Forms
+ */
+td.mw-label {
+ text-align: right;
+}
+td.mw-input {
+ text-align: left;
+}
+td.mw-submit {
+ text-align: left;
+}
+
+td.mw-label {
+ vertical-align: top;
+}
+.prefsection td.mw-label {
+ width: 20%;
+}
+.prefsection table {
+ width: 100%;
+}
+td.mw-submit {
+ white-space: nowrap;
+}
+
+table.mw-htmlform-nolabel td.mw-label {
+ width: 1px;
+}
+
+tr.mw-htmlform-vertical-label td.mw-label {
+ text-align: left !important;
+}
+
+.mw-htmlform-invalid-input td.mw-input input {
+ border-color: red;
+}
+
+.mw-htmlform-flatlist div.mw-htmlform-flatlist-item {
+ display: inline;
+ margin-right: 1em;
+ white-space: nowrap;
+}
+
+input#wpSummary {
+ width: 80%;
+}
+
+/**
+ * Image captions
+ */
+.thumbcaption {
+ text-align: left;
+}
+.magnify {
+ float: right;
+}
+
+/**
+ * Categories
+ */
+#catlinks {
+ /**
+ * Overrides text justification (user preference)
+ * See bug 31990
+ */
+ text-align: left;
+}
+.catlinks ul {
+ display: inline;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ list-style-type: none;
+ list-style-image: none;
+ vertical-align: middle !ie;
+}
+
+.catlinks li {
+ display: inline-block;
+ line-height: 1.25em;
+ border-left: 1px solid #AAA;
+ margin: 0.125em 0;
+ padding: 0 0.5em;
+ zoom: 1;
+ display: inline !ie;
+}
+
+.catlinks li:first-child {
+ padding-left: 0.25em;
+ border-left: none;
+}
+/**
+ * Hidden categories
+ */
+.mw-hidden-cats-hidden {
+ display: none;
+}
+.catlinks-allhidden {
+ display: none;
+}
+
+/* Convenience links to edit block, delete and protect reasons */
+p.mw-ipb-conveniencelinks,
+p.mw-protect-editreasons,
+p.mw-filedelete-editreasons,
+p.mw-delete-editreasons,
+p.mw-revdel-editreasons {
+ font-size: 90%;
+ text-align: right;
+}
+
+/**
+ * OpenSearch ajax suggestions
+ */
+.os-suggest {
+ overflow: auto;
+ overflow-x: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 0;
+ background-color: white;
+ border-style: solid;
+ border-color: #AAAAAA;
+ border-width: 1px;
+ z-index:99;
+ font-size:95%;
+}
+
+table.os-suggest-results {
+ font-size: 95%;
+ cursor: pointer;
+ border: 0;
+ border-collapse: collapse;
+ width: 100%;
+}
+
+.os-suggest-result,
+.os-suggest-result-hl {
+ white-space: nowrap;
+ background-color: white;
+ color: black;
+ padding: 2px;
+}
+.os-suggest-result-hl,
+.os-suggest-result-hl-webkit {
+ background-color: #4C59A6;
+ color: white;
+}
+
+.os-suggest-toggle {
+ position: relative;
+ left: 1ex;
+ font-size: 65%;
+}
+.os-suggest-toggle-def {
+ position: absolute;
+ top: 0;
+ left: 0;
+ font-size: 65%;
+ visibility: hidden;
+}
+
+/* Page history styling */
+
+/* The auto-generated edit comments */
+.autocomment {
+ color: gray;
+}
+#pagehistory .history-user {
+ margin-left: 0.4em;
+ margin-right: 0.2em;
+}
+#pagehistory span.minor {
+ font-weight: bold;
+}
+#pagehistory li {
+ border: 1px solid white;
+}
+#pagehistory li.selected {
+ background-color: #f9f9f9;
+ border: 1px dashed #aaa;
+}
+
+.mw-history-revisiondelete-button, #mw-fileduplicatesearch-icon {
+ float: right;
+}
+
+/** Generic minor/bot/newpage styling (recent changes) */
+.newpage,
+.minoredit,
+.botedit {
+ font-weight: bold;
+}
+
+#shared-image-dup,
+#shared-image-conflict {
+ font-style: italic;
+}
+
+/**
+ * Recreating deleted page warning
+ * Reupload file warning
+ * Page protection warning
+ * incl. log entries for these warnings
+ */
+div.mw-warning-with-logexcerpt {
+ padding: 3px;
+ margin-bottom: 3px;
+ border: 2px solid #2F6FAB;
+ clear: both;
+}
+div.mw-warning-with-logexcerpt ul li {
+ font-size: 90%;
+}
+
+/* (show/hide) revision deletion links */
+span.mw-revdelundel-link,
+strong.mw-revdelundel-link {
+ font-size: 90%;
+}
+span.mw-revdelundel-hidden,
+input.mw-revdelundel-hidden {
+ visibility: hidden;
+}
+
+td.mw-revdel-checkbox,
+th.mw-revdel-checkbox {
+ padding-right: 10px;
+ text-align: center;
+}
+
+/* feed links */
+a.feedlink {
+ /* @embed */
+ background: url(images/feed-icon.png) center left no-repeat;
+ padding-left: 16px;
+}
+
+/* Plainlinks - this can be used to switch
+ * off special external link styling */
+.plainlinks a {
+ background: none !important;
+ padding: 0 !important;
+}
+/* External URLs should always be treated as LTR (bug 4330) */
+/* @noflip */ .rtl a.external.free,
+.rtl a.external.autonumber {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+
+/**
+ * wikitable class for skinning normal tables
+ * keep in sync with commonPrint.css
+ */
+table.wikitable {
+ margin: 1em 1em 1em 0;
+ background-color: #f9f9f9;
+ border: 1px #aaa solid;
+ border-collapse: collapse;
+ color: black;
+}
+table.wikitable > tr > th,
+table.wikitable > tr > td,
+table.wikitable > * > tr > th,
+table.wikitable > * > tr > td {
+ border: 1px #aaa solid;
+ padding: 0.2em;
+}
+table.wikitable > tr > th,
+table.wikitable > * > tr > th {
+ background-color: #f2f2f2;
+ text-align: center;
+}
+table.wikitable > caption {
+ font-weight: bold;
+}
+
+/* hide initially collapsed collapsable tables */
+table.collapsed tr.collapsable {
+ display: none;
+}
+
+/* success and error messages */
+.success {
+ color: green;
+ font-size: larger;
+}
+.warning {
+ color: #FFA500; /* orange */
+ font-size: larger;
+}
+.error {
+ color: red;
+ font-size: larger;
+}
+.errorbox,
+.warningbox,
+.successbox {
+ font-size: larger;
+ border: 2px solid;
+ padding: .5em 1em;
+ float: left;
+ margin-bottom: 2em;
+ color: #000;
+}
+.errorbox {
+ border-color: red;
+ background-color: #fff2f2;
+}
+.warningbox {
+ border-color: #FF8C00; /* darkorange */
+ background-color: #FFFFC0;
+}
+.successbox {
+ border-color: green;
+ background-color: #dfd;
+}
+.errorbox h2,
+.warningbox h2,
+.successbox h2 {
+ font-size: 1em;
+ font-weight: bold;
+ display: inline;
+ margin: 0 .5em 0 0;
+ border: none;
+}
+
+/* general info/warning box for SP */
+.mw-infobox {
+ border: 2px solid #ff7f00;
+ margin: 0.5em;
+ clear: left;
+ overflow: hidden;
+}
+
+.mw-infobox-left {
+ margin: 7px;
+ float: left;
+ width: 35px;
+}
+
+.mw-infobox-right {
+ margin: 0.5em 0.5em 0.5em 49px;
+}
+
+/* Note on preview page */
+.previewnote {
+ color: #c00;
+ margin-bottom: 1em;
+}
+
+.previewnote p {
+ text-indent: 3em;
+ margin: 0.8em 0;
+}
+
+.visualClear {
+ clear: both;
+}
+
+#mw_trackbacks {
+ border: solid 1px #bbbbff;
+ background-color: #eeeeff;
+ padding: 0.2em;
+}
+
+/**
+ * Data table style
+ *
+ * Transparent table with suddle borders
+ * and blue row-highlighting.
+ */
+.mw-datatable {
+ border-collapse: collapse;
+}
+.mw-datatable,
+.mw-datatable td,
+.mw-datatable th {
+ border: 1px solid #aaaaaa;
+ padding: 0 0.15em 0 0.15em;
+}
+.mw-datatable th {
+ background-color: #ddddff;
+}
+.mw-datatable td {
+ background-color: #ffffff;
+}
+.mw-datatable tr:hover td {
+ background-color: #eeeeff;
+}
+
+
+/**
+ * TablePager tables generated by the TablePager PHP class
+ * in MediaWiki (e.g. Special:ListFiles).
+ */
+.TablePager {
+ min-width: 80%;
+}
+.TablePager_nav {
+ margin: 0 auto;
+}
+.TablePager_nav td {
+ padding: 3px;
+ text-align: center;
+}
+.TablePager_nav a {
+ text-decoration: none;
+}
+
+.imagelist td,
+.imagelist th {
+ white-space: nowrap;
+}
+.imagelist .TablePager_col_links {
+ background-color: #eeeeff;
+}
+.imagelist .TablePager_col_img_description {
+ white-space: normal;
+}
+.imagelist th.TablePager_sort {
+ background-color: #ccccff;
+}
+
+/* filetoc */
+ul#filetoc {
+ text-align: center;
+ border: 1px solid #aaaaaa;
+ background-color: #f9f9f9;
+ padding: 5px;
+ font-size: 95%;
+ margin-bottom: 0.5em;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+#filetoc li {
+ display: inline;
+ list-style-type: none;
+ padding-right: 2em;
+}
+
+/* Classes for EXIF data display */
+table.mw_metadata {
+ font-size: 0.8em;
+ margin-left: 0.5em;
+ margin-bottom: 0.5em;
+ width: 400px;
+}
+
+table.mw_metadata caption {
+ font-weight: bold;
+}
+
+table.mw_metadata th {
+ font-weight: normal;
+}
+
+table.mw_metadata td {
+ padding: 0.1em;
+}
+
+table.mw_metadata {
+ border: none;
+ border-collapse: collapse;
+}
+
+table.mw_metadata td,
+table.mw_metadata th {
+ text-align: center;
+ border: 1px solid #aaaaaa;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+table.mw_metadata th {
+ background-color: #f9f9f9;
+}
+
+table.mw_metadata td {
+ background-color: #fcfcfc;
+}
+
+table.mw_metadata ul.metadata-langlist {
+ list-style-type: none;
+ list-style-image: none;
+ padding-right: 5px;
+ padding-left: 5px;
+ margin: 0;
+}
+
+/* Correct directionality when page dir is different from site/user dir */
+.mw-content-ltr ul,
+.mw-content-rtl .mw-content-ltr ul {
+ /* @noflip */
+ margin: 0.3em 0 0 1.6em;
+ padding: 0;
+}
+.mw-content-rtl ul,
+.mw-content-ltr .mw-content-rtl ul {
+ /* @noflip */
+ margin: 0.3em 1.6em 0 0;
+ padding: 0;
+}
+.mw-content-ltr ol,
+.mw-content-rtl .mw-content-ltr ol {
+ /* @noflip */
+ margin: 0.3em 0 0 3.2em;
+ padding: 0;
+}
+.mw-content-rtl ol,
+.mw-content-ltr .mw-content-rtl ol {
+ /* @noflip */
+ margin: 0.3em 3.2em 0 0;
+ padding: 0;
+}
+/* @noflip */
+.mw-content-ltr dd,
+.mw-content-rtl .mw-content-ltr dd {
+ margin-left: 1.6em;
+ margin-right: 0;
+}
+/* @noflip */
+.mw-content-rtl dd,
+.mw-content-ltr .mw-content-rtl dd {
+ margin-right: 1.6em;
+ margin-left: 0;
+}
+
+/* Galleries */
+/* These display attributes look nonsensical, but are needed to support IE and FF2 */
+/* Don't forget to update commonPrint.css */
+li.gallerybox {
+ vertical-align: top;
+ border: solid 2px white;
+ display: -moz-inline-box;
+ display: inline-block;
+}
+
+ul.gallery,
+li.gallerybox {
+ zoom: 1;
+ *display: inline;
+}
+
+ul.gallery {
+ margin: 2px;
+ padding: 2px;
+ display: block;
+}
+
+li.gallerycaption {
+ font-weight: bold;
+ text-align: center;
+ display: block;
+ word-wrap: break-word;
+}
+
+li.gallerybox div.thumb {
+ text-align: center;
+ border: 1px solid #ccc;
+ background-color: #f9f9f9;
+ margin: 2px;
+}
+
+li.gallerybox div.thumb img {
+ display: block;
+ margin: 0 auto;
+}
+
+div.gallerytext {
+ overflow: hidden;
+ font-size: 94%;
+ padding: 2px 4px;
+ word-wrap: break-word;
+}
+
+.mw-ajax-loader {
+ /* @embed */
+ background-image: url(images/ajax-loader.gif);
+ background-position: center center;
+ background-repeat: no-repeat;
+ padding: 16px;
+ position: relative;
+ top: -16px;
+}
+
+.mw-small-spinner {
+ padding: 10px !important;
+ margin-right: 0.6em;
+ /* @embed */
+ background-image: url(images/spinner.gif);
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+
+/* Language specific height correction for titles. Ref Bug 29405 and Bug 30809 */
+/* Languages like hi or ml require slightly more vertical space to show diacritics properly */
+h1:lang(as),
+h1:lang(bh), /* Macrolanguage, used on bh.wikipedia.org, should be removed one day */
+h1:lang(bho),
+h1:lang(bn),
+h1:lang(gu),
+h1:lang(hi),
+h1:lang(kn),
+h1:lang(ml),
+h1:lang(mr),
+h1:lang(or),
+h1:lang(pa),
+h1:lang(sa),
+h1:lang(ta),
+h1:lang(te) {
+ line-height: 1.5em !important;
+}
+h2:lang(as), h3:lang(as), h4:lang(as), h5:lang(as), h6:lang(as),
+h2:lang(bho), h3:lang(bho), h4:lang(bho), h5:lang(bho), h6:lang(bho),
+h2:lang(bh), h3:lang(bh), h4:lang(bh), h5:lang(bh), h6:lang(bh),
+h2:lang(bn), h3:lang(bn), h4:lang(bn), h5:lang(bn), h6:lang(bn),
+h2:lang(gu), h3:lang(gu), h4:lang(gu), h5:lang(gu), h6:lang(gu),
+h2:lang(hi), h3:lang(hi), h4:lang(hi), h5:lang(hi), h6:lang(hi),
+h2:lang(kn), h3:lang(kn), h4:lang(kn), h5:lang(kn), h6:lang(kn),
+h2:lang(ml), h3:lang(ml), h4:lang(ml), h5:lang(ml), h6:lang(ml),
+h2:lang(mr), h3:lang(mr), h4:lang(mr), h5:lang(mr), h6:lang(mr),
+h2:lang(or), h3:lang(or), h4:lang(or), h5:lang(or), h6:lang(or),
+h2:lang(pa), h3:lang(pa), h4:lang(pa), h5:lang(pa), h6:lang(pa),
+h2:lang(sa), h3:lang(sa), h4:lang(sa), h5:lang(sa), h6:lang(sa),
+h2:lang(ta), h3:lang(ta), h4:lang(ta), h5:lang(ta), h6:lang(ta),
+h2:lang(te), h3:lang(te), h4:lang(te), h5:lang(te), h6:lang(te) {
+ line-height: 1.2em;
+}
+
+/* Localised ordered list numbering for some languages */
+ol:lang(bcc) li,
+ol:lang(bqi) li,
+ol:lang(fa) li,
+ol:lang(glk) li,
+ol:lang(kk-arab) li,
+ol:lang(mzn) li {
+ list-style-type: -moz-persian;
+ list-style-type: persian;
+}
+
+ol:lang(ckb) li {
+ list-style-type: -moz-arabic-indic;
+ list-style-type: arabic-indic;
+}
+
+ol:lang(hi) li,
+ol:lang(mr) li {
+ list-style-type: -moz-devanagari;
+ list-style-type: devanagari;
+}
+
+ol:lang(as) li,
+ol:lang(bn) li {
+ list-style-type: -moz-bengali;
+ list-style-type: bengali;
+}
+
+ol:lang(or) li {
+ list-style-type: -moz-oriya;
+ list-style-type: oriya;
+}
+
+#toc ul, .toc ul {
+ margin: .3em 0;
+}
+
+/* Correct directionality when page dir is different from site/user dir */
+/* @noflip */ .mw-content-ltr .toc ul,
+.mw-content-ltr #toc ul,
+.mw-content-rtl .mw-content-ltr .toc ul,
+.mw-content-rtl .mw-content-ltr #toc ul {
+ text-align: left;
+}
+/* @noflip */ .mw-content-rtl .toc ul,
+.mw-content-rtl #toc ul,
+.mw-content-ltr .mw-content-rtl .toc ul,
+.mw-content-ltr .mw-content-rtl #toc ul {
+ text-align: right;
+}
+/* @noflip */ .mw-content-ltr .toc ul ul,
+.mw-content-ltr #toc ul ul,
+.mw-content-rtl .mw-content-ltr .toc ul ul,
+.mw-content-rtl .mw-content-ltr #toc ul ul {
+ margin: 0 0 0 2em;
+}
+/* @noflip */ .mw-content-rtl .toc ul ul,
+.mw-content-rtl #toc ul ul,
+.mw-content-ltr .mw-content-rtl .toc ul ul,
+.mw-content-ltr .mw-content-rtl #toc ul ul {
+ margin: 0 2em 0 0;
+}
+
+#toc #toctitle,
+.toc #toctitle,
+#toc .toctitle,
+.toc .toctitle {
+ direction: ltr;
+}
+
+/* tooltip styles */
+.mw-help-field-hint {
+ display: none;
+ margin-left: 2px;
+ margin-bottom: -8px;
+ padding: 0 0 0 15px;
+ /* @embed */
+ background-image: url('images/help-question.gif');
+ background-position: left center;
+ background-repeat: no-repeat;
+ cursor: pointer;
+ font-size: .8em;
+ text-decoration: underline;
+ color: #0645ad;
+}
+.mw-help-field-hint:hover {
+ /* @embed */
+ background-image: url('images/help-question-hover.gif');
+}
+.mw-help-field-data {
+ display: block;
+ background-color: #d6f3ff;
+ padding:5px 8px 4px 8px;
+ border: 1px solid #5dc9f4;
+ margin-left: 20px;
+}
+.tipsy {
+ padding: 5px 5px 10px;
+ font-size: 12px;
+ position: absolute;
+ z-index: 100000;
+ overflow: visible;
+}
+.tipsy-inner {
+ padding: 5px 8px 4px 8px;
+ background-color: #d6f3ff;
+ color: black;
+ border: 1px solid #5dc9f4;
+ max-width: 300px;
+ text-align: left;
+}
+.tipsy-arrow {
+ position: absolute;
+ /* @embed */
+ background: url(images/tipsy-arrow.gif) no-repeat top left;
+ width: 13px;
+ height: 13px;
+}
+.tipsy-se .tipsy-arrow {
+ bottom: -2px;
+ right: 10px;
+ background-position: 0% 100%;
+}
+
+#mw-clearyourcache,
+#mw-sitecsspreview,
+#mw-sitejspreview,
+#mw-usercsspreview,
+#mw-userjspreview {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+
+/* Correct user & content directionality when viewing a diff */
+.diff-currentversion-title,
+.diff {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+/* @noflip */ .diff-contentalign-right td {
+ direction: rtl;
+ unicode-bidi: embed;
+}
+/* @noflip */ .diff-contentalign-left td {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+.diff-otitle,
+.diff-ntitle,
+.diff-lineno {
+ direction: ltr !important;
+ unicode-bidi: embed;
+}
+
+#mw-revision-info,
+#mw-revision-info-current,
+#mw-revision-nav {
+ direction: ltr;
+ display: inline;
+}
+
+/* Images */
+
+/* @noflip */ div.tright,
+div.floatright,
+table.floatright {
+ clear: right;
+ float: right;
+}
+/* @noflip */ div.tleft,
+div.floatleft,
+table.floatleft {
+ float: left;
+ clear: left;
+}
+div.floatright,
+table.floatright,
+div.floatleft,
+table.floatleft {
+ position: relative;
+}
+
+/* bug 12205 */
+#mw-credits a {
+ unicode-bidi: embed;
+}
+
+/* Accessibility */
+.mw-jump,
+#jump-to-nav {
+ overflow: hidden;
+ height: 0;
+ zoom: 1; /* http://webaim.org/techniques/skipnav/#iequirk */
+}
+
+/* Print footer should be hidden by default in screen. */
+.printfooter {
+ display: none;
+}
+
+/* For developpers */
+.xdebug-error {
+ position: absolute;
+ z-index: 99;
+}
+
+.editsection, .toctoggle {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+/**
+ * MediaWiki Print style sheet for CSS2-capable browsers.
+ * Copyright Gabriel Wicke, http://www.aulinx.de/
+ *
+ * Derived from the plone (http://plone.org/) styles
+ * Copyright Alexander Limi
+ */
+
+/* Thanks to A List Apart (http://alistapart.com/) for useful extras */
+a.stub,
+a.new {
+ color: #ba0000;
+ text-decoration: none;
+}
+
+#toc {
+ border: 1px solid #aaaaaa;
+ background-color: #f9f9f9;
+ padding: 5px;
+}
+
+/* images */
+div.floatright {
+ float: right;
+ clear: right;
+ position: relative;
+ margin: 0.5em 0 0.8em 1.4em;
+}
+div.floatright p {
+ font-style: italic;
+}
+div.floatleft {
+ float: left;
+ clear: left;
+ position: relative;
+ margin: 0.5em 1.4em 0.8em 0;
+}
+div.floatleft p {
+ font-style: italic;
+}
+div.center {
+ text-align: center;
+}
+
+/* thumbnails */
+div.thumb {
+ border: none;
+ width: auto;
+ margin-top: 0.5em;
+ margin-bottom: 0.8em;
+ background-color: transparent;
+}
+div.thumbinner {
+ border:1px solid #cccccc;
+ padding: 3px !important;
+ background-color: White;
+ font-size: 94%;
+ text-align: center;
+ overflow: hidden;
+}
+html .thumbimage {
+ border: 1px solid #cccccc;
+}
+html .thumbcaption {
+ border: none;
+ text-align: left;
+ line-height: 1.4em;
+ padding: 3px !important;
+ font-size: 94%;
+}
+
+div.magnify {
+ display: none;
+}
+/* @noflip */
+div.tright {
+ float: right;
+ clear: right;
+ margin: 0.5em 0 0.8em 1.4em;
+}
+/* @noflip */
+div.tleft {
+ float: left;
+ clear: left;
+ margin: 0.5em 1.4em 0.8em 0;
+}
+img.thumbborder {
+ border: 1px solid #dddddd;
+}
+
+/* table standards */
+table.rimage {
+ float: right;
+ width: 1pt;
+ position: relative;
+ margin-left: 1em;
+ margin-bottom: 1em;
+ text-align: center;
+}
+
+body {
+ background: white;
+ color: black;
+ margin: 0;
+ padding: 0;
+}
+
+.noprint,
+div#jump-to-nav,
+.mw-jump,
+div.top,
+div#column-one,
+#colophon,
+.editsection,
+.toctoggle,
+.tochidden,
+div#f-poweredbyico,
+div#f-copyrightico,
+li#viewcount,
+li#about,
+li#disclaimer,
+li#mobileview,
+li#privacy,
+#footer-places,
+.mw-hidden-catlinks,
+tr.mw-metadata-show-hide-extended,
+span.mw-filepage-other-resolutions,
+#filetoc {
+ /* Hides all the elements irrelevant for printing */
+ display: none;
+}
+
+ul {
+ list-style-type: square;
+}
+
+#content {
+ background: none;
+ border: none !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ direction: ltr;
+}
+#footer {
+ background : white;
+ color : black;
+ margin-top: 1em;
+ border-top: 1px solid #AAA;
+ direction: ltr;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-weight: bold;
+}
+
+p {
+ margin: 1em 0;
+ line-height: 1.2em;
+}
+
+pre {
+ border: 1pt dashed black;
+ white-space: pre;
+ font-size: 8pt;
+ overflow: auto;
+ padding: 1em 0;
+ background: white;
+ color: black;
+}
+
+table.listing,
+table.listing td {
+ border: 1pt solid black;
+ border-collapse: collapse;
+}
+
+a {
+ color: black !important;
+ background: none !important;
+ padding: 0 !important;
+}
+
+a:link, a:visited {
+ color: #520;
+ background: transparent;
+ text-decoration: underline;
+}
+
+#content a.external.text:after,
+#content a.external.autonumber:after {
+ /* Expand URLs for printing */
+ content: " (" attr(href) ") ";
+}
+
+#globalWrapper {
+ width: 100% !important;
+ min-width: 0 !important;
+}
+
+#content {
+ background: white;
+ color: black;
+}
+
+#column-content {
+ margin: 0 !important;
+}
+
+#column-content #content {
+ padding: 1em;
+ margin: 0 !important;
+}
+
+/* MSIE/Win doesn't understand 'inherit' */
+a,
+a.external,
+a.new,
+a.stub {
+ color: black !important;
+ text-decoration: none !important;
+}
+
+/* Continue ... */
+a,
+a.external,
+a.new,
+a.stub {
+ color: inherit !important;
+ text-decoration: inherit !important;
+}
+
+img {
+ border: none;
+ vertical-align: middle;
+}
+
+/* math */
+span.texhtml {
+ font-family: serif;
+}
+
+#siteNotice {
+ display: none;
+}
+
+/* Galleries (see shared.css for more info) */
+li.gallerybox {
+ vertical-align: top;
+ border: solid 2px white;
+ display: -moz-inline-box;
+ display: inline-block;
+}
+
+ul.gallery, li.gallerybox {
+ zoom: 1;
+ *display: inline;
+}
+
+ul.gallery {
+ margin: 2px;
+ padding: 2px;
+ display: block;
+}
+
+li.gallerycaption {
+ font-weight: bold;
+ text-align: center;
+ display: block;
+ word-wrap: break-word;
+}
+
+li.gallerybox div.thumb {
+ text-align: center;
+ border: 1px solid #ccc;
+ margin: 2px;
+}
+
+div.gallerytext {
+ overflow: hidden;
+ font-size: 94%;
+ padding: 2px 4px;
+ word-wrap: break-word;
+}
+
+/**
+ * Diff rendering
+ */
+table.diff {
+ background: white;
+}
+td.diff-otitle {
+ background: #ffffff;
+}
+td.diff-ntitle {
+ background: #ffffff;
+}
+td.diff-addedline {
+ background: #ccffcc;
+ font-size: smaller;
+ border: solid 2px black;
+}
+td.diff-deletedline {
+ background: #ffffaa;
+ font-size: smaller;
+ border: dotted 2px black;
+}
+td.diff-context {
+ background: #eeeeee;
+ font-size: smaller;
+}
+.diffchange {
+ color: silver;
+ font-weight: bold;
+ text-decoration: underline;
+}
+
+/**
+ * Table rendering
+ * As on shared.css but with white background.
+ */
+table.wikitable,
+table.mw_metadata {
+ margin: 1em 1em 1em 0;
+ border: 1px #aaa solid;
+ background: white;
+ border-collapse: collapse;
+}
+table.wikitable > tr > th, table.wikitable > tr > td,
+table.wikitable > * > tr > th, table.wikitable > * > tr > td,
+.mw_metadata th, .mw_metadata td {
+ border: 1px #aaa solid;
+ padding: 0.2em;
+}
+table.wikitable > tr > th,
+table.wikitable > * > tr > th,
+.mw_metadata th {
+ text-align: center;
+ background: white;
+ font-weight: bold;
+}
+table.wikitable > caption,
+.mw_metadata caption {
+ font-weight: bold;
+}
+
+a.sortheader {
+ margin: 0 0.3em;
+}
+
+/* Some pagination options */
+.wikitable, .thumb, img {
+ page-break-inside: avoid;
+}
+h2, h3, h4, h5, h6, h7 {
+ page-break-after: avoid;
+}
+p {
+ widows: 3;
+ orphans: 3;
+}
+
+/**
+ * Categories
+ */
+.catlinks ul {
+ display: inline;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ list-style-type: none;
+ list-style-image: none;
+ vertical-align: middle !ie;
+}
+
+.catlinks li {
+ display: inline-block;
+ line-height: 1.15em;
+ padding: 0 .4em;
+ border-left: 1px solid #AAA;
+ margin: 0.1em 0;
+ zoom: 1;
+ display: inline !ie;
+}
+
+.catlinks li:first-child {
+ padding-left: .2em;
+ border-left: none;
+}
+/* Default styling for HTML elements */
+dfn {
+ font-style: inherit; /* Reset default styling for <dfn> */
+}
+sup, sub {
+ line-height: 1em; /* Reduce line-height for <sup> and <sub> */
+}
+
+/* Main page fixes */
+#interwiki-completelist {
+ font-weight: bold;
+}
+body.page-Main_Page #ca-delete {
+ display: none !important;
+}
+body.page-Main_Page #mp-topbanner {
+ clear: both;
+}
+
+/* Edit window toolbar */
+#toolbar {
+ height: 22px;
+ margin-bottom: 6px;
+}
+
+/* Highlight data points in the info action if specified in the URL */
+body.action-info :target {
+ background: #DEF;
+}
+
+/* Make the list of references smaller */
+ol.references,
+div.reflist,
+div.refbegin {
+ font-size: 90%; /* Default font-size */
+ margin-bottom: 0.5em;
+}
+div.refbegin-100 {
+ font-size: 100%; /* Option for normal fontsize in {{refbegin}} */
+}
+div.reflist ol.references {
+ font-size: 100%; /* Reset font-size when nested in div.reflist */
+ list-style-type: inherit; /* Enable custom list style types */
+}
+
+/* Reset top margin for lists embedded in columns */
+div.columns {
+ margin-top: 0.3em;
+}
+div.columns dl,
+div.columns ol,
+div.columns ul {
+ margin-top: 0;
+}
+
+/* Avoid list items from breaking between columns */
+div.columns li,
+div.columns dd dd {
+ -webkit-column-break-inside: avoid;
+ page-break-inside: avoid;
+ break-inside: avoid-column;
+}
+
+/* Highlight clicked reference in blue to help navigation */
+ol.references li:target,
+sup.reference:target,
+span.citation:target {
+ background-color: #DEF;
+}
+
+/* Ensure refs in table headers and the like aren't bold or italic */
+sup.reference {
+ font-weight: normal;
+ font-style: normal;
+}
+
+/* Allow hidden ref errors to be shown by user CSS */
+span.brokenref {
+ display: none;
+}
+
+/* Styling for citations (CSS3). Breaks long urls, etc., rather than overflowing box */
+.citation {
+ word-wrap: break-word;
+}
+
+/* For linked citation numbers and document IDs, where
+ the number need not be shown on a screen or a handheld,
+ but should be included in the printed version */
+@media screen, handheld {
+ .citation *.printonly {
+ display: none;
+ }
+}
+
+/* Style for [[Template:Flowlist]] that Lets lists flow around floating objecs */
+.flowlist ul {
+ overflow-x: hidden;
+ margin-left: 0em;
+ padding-left: 1.6em;
+}
+.flowlist ol {
+ overflow-x: hidden;
+ margin-left: 0em;
+ padding-left: 3.2em;
+}
+.flowlist dl {
+ overflow-x: hidden;
+}
+
+/* Style for horizontal lists (separator following item).
+ IE8-specific classes are assigned in [[MediaWiki:Common.js/IEFixes.js]].
+ @source mediawiki.org/wiki/Snippets/Horizontal_lists
+ @revision 4.3 (2014-01-06)
+ @author [[User:Edokter]]
+ */
+.hlist dl,
+.hlist ol,
+.hlist ul {
+ margin: 0;
+ padding: 0;
+}
+/* Display list items inline */
+.hlist dd,
+.hlist dt,
+.hlist li {
+ margin: 0;
+ display: inline;
+}
+/* Display nested lists inline */
+.hlist dl dl, .hlist dl ol, .hlist dl ul,
+.hlist ol dl, .hlist ol ol, .hlist ol ul,
+.hlist ul dl, .hlist ul ol, .hlist ul ul {
+ display: inline;
+}
+/* Generate interpuncts */
+.hlist dt:after {
+ content: ": ";
+}
+.hlist dd:after,
+.hlist li:after {
+ content: " · ";
+ font-weight: bold;
+}
+.hlist dd:last-child:after,
+.hlist dt:last-child:after,
+.hlist li:last-child:after {
+ content: none;
+}
+/* For IE8 */
+.hlist dd.hlist-last-child:after,
+.hlist dt.hlist-last-child:after,
+.hlist li.hlist-last-child:after {
+ content: none;
+}
+/* Add parentheses around nested lists */
+.hlist dd dd:first-child:before, .hlist dd dt:first-child:before, .hlist dd li:first-child:before,
+.hlist dt dd:first-child:before, .hlist dt dt:first-child:before, .hlist dt li:first-child:before,
+.hlist li dd:first-child:before, .hlist li dt:first-child:before, .hlist li li:first-child:before {
+ content: " (";
+ font-weight: normal;
+}
+.hlist dd dd:last-child:after, .hlist dd dt:last-child:after, .hlist dd li:last-child:after,
+.hlist dt dd:last-child:after, .hlist dt dt:last-child:after, .hlist dt li:last-child:after,
+.hlist li dd:last-child:after, .hlist li dt:last-child:after, .hlist li li:last-child:after {
+ content: ") ";
+ font-weight: normal;
+}
+/* For IE8 */
+.hlist dd dd.hlist-last-child:after, .hlist dd dt.hlist-last-child:after, .hlist dd li.hlist-last-child:after,
+.hlist dt dd.hlist-last-child:after, .hlist dt dt.hlist-last-child:after, .hlist dt li.hlist-last-child:after,
+.hlist li dd.hlist-last-child:after, .hlist li dt.hlist-last-child:after, .hlist li li.hlist-last-child:after {
+ content: ") ";
+ font-weight: normal;
+}
+/* Put ordinals in front of ordered list items */
+.hlist ol {
+ counter-reset: listitem;
+}
+.hlist ol > li {
+ counter-increment: listitem;
+}
+.hlist ol > li:before {
+ content: " " counter(listitem) " ";
+}
+.hlist dd ol > li:first-child:before,
+.hlist dt ol > li:first-child:before,
+.hlist li ol > li:first-child:before {
+ content: " (" counter(listitem) " ";
+}
+
+/* Unbulleted lists */
+.plainlist ul {
+ line-height: inherit;
+ list-style: none none;
+ margin: 0;
+}
+.plainlist ul li {
+ margin-bottom: 0;
+}
+
+/* Default style for navigation boxes */
+.navbox { /* Navbox container style */
+ border: 1px solid #aaa;
+ width: 100%;
+ margin: auto;
+ clear: both;
+ font-size: 88%;
+ text-align: center;
+ padding: 1px;
+}
+.navbox-inner,
+.navbox-subgroup {
+ width: 100%;
+}
+.navbox-group,
+.navbox-title,
+.navbox-abovebelow {
+ padding: 0.25em 1em; /* Title, group and above/below styles */
+ line-height: 1.5em;
+ text-align: center;
+}
+th.navbox-group { /* Group style */
+ white-space: nowrap;
+ /* @noflip */
+ text-align: right;
+}
+.navbox,
+.navbox-subgroup {
+ background: #fdfdfd; /* Background color */
+}
+.navbox-list {
+ line-height: 1.8em;
+ border-color: #fdfdfd; /* Must match background color */
+}
+.navbox th,
+.navbox-title {
+ background: #ccccff; /* Level 1 color */
+}
+.navbox-abovebelow,
+th.navbox-group,
+.navbox-subgroup .navbox-title {
+ background: #ddddff; /* Level 2 color */
+}
+.navbox-subgroup .navbox-group,
+.navbox-subgroup .navbox-abovebelow {
+ background: #e6e6ff; /* Level 3 color */
+}
+.navbox-even {
+ background: #f7f7f7; /* Even row striping */
+}
+.navbox-odd {
+ background: transparent; /* Odd row striping */
+}
+table.navbox + table.navbox { /* Single pixel border between adjacent navboxes */
+ margin-top: -1px; /* (doesn't work for IE6, but that's okay) */
+}
+.navbox .hlist td dl,
+.navbox .hlist td ol,
+.navbox .hlist td ul,
+.navbox td.hlist dl,
+.navbox td.hlist ol,
+.navbox td.hlist ul {
+ padding: 0.125em 0; /* Adjust hlist padding in navboxes */
+}
+ol + table.navbox,
+ul + table.navbox {
+ margin-top: 0.5em; /* Prevent lists from clinging to navboxes */
+}
+
+/* Default styling for Navbar template */
+.navbar {
+ display: inline;
+ font-size: 88%;
+ font-weight: normal;
+}
+.navbar ul {
+ display: inline;
+ white-space: nowrap;
+}
+.navbar li {
+ word-spacing: -0.125em;
+}
+.navbar.mini li span {
+ font-variant: small-caps;
+}
+/* Navbar styling when nested in infobox and navbox */
+.infobox .navbar {
+ font-size: 100%;
+}
+.navbox .navbar {
+ display: block;
+ font-size: 100%;
+}
+.navbox-title .navbar {
+ /* @noflip */
+ float: left;
+ /* @noflip */
+ text-align: left;
+ /* @noflip */
+ margin-right: 0.5em;
+ width: 6em;
+}
+
+/* 'show'/'hide' buttons created dynamically by the CollapsibleTables javascript
+ in [[MediaWiki:Common.js]] are styled here so they can be customised. */
+.collapseButton {
+ /* @noflip */
+ float: right;
+ font-weight: normal;
+ /* @noflip */
+ margin-left: 0.5em;
+ /* @noflip */
+ text-align: right;
+ width: auto;
+}
+/* In navboxes, the show/hide button balances the v·d·e links
+ from [[Template:Navbar]], so they need to be the same width. */
+.navbox .collapseButton {
+ width: 6em;
+}
+
+/* Styling for JQuery makeCollapsible, matching that of collapseButton */
+.mw-collapsible-toggle {
+ font-weight: normal;
+ /* @noflip */
+ text-align: right;
+}
+.navbox .mw-collapsible-toggle {
+ width: 6em;
+}
+
+/* Infobox template style */
+.infobox {
+ border: 1px solid #aaa;
+ background-color: #f9f9f9;
+ color: black;
+ /* @noflip */
+ margin: 0.5em 0 0.5em 1em;
+ padding: 0.2em;
+ /* @noflip */
+ float: right;
+ /* @noflip */
+ clear: right;
+ /* @noflip */
+ text-align: left;
+ font-size: 88%;
+ line-height: 1.5em;
+}
+.infobox caption {
+ font-size: 125%;
+ font-weight: bold;
+}
+.infobox td,
+.infobox th {
+ vertical-align: top;
+}
+.infobox.bordered {
+ border-collapse: collapse;
+}
+.infobox.bordered td,
+.infobox.bordered th {
+ border: 1px solid #aaa;
+}
+.infobox.bordered .borderless td,
+.infobox.bordered .borderless th {
+ border: 0;
+}
+
+.infobox.sisterproject {
+ width: 20em;
+ font-size: 90%;
+}
+
+.infobox.standard-talk {
+ border: 1px solid #c0c090;
+ background-color: #f8eaba;
+}
+.infobox.standard-talk.bordered td,
+.infobox.standard-talk.bordered th {
+ border: 1px solid #c0c090;
+}
+
+/* styles for bordered infobox with merged rows */
+.infobox.bordered .mergedtoprow td,
+.infobox.bordered .mergedtoprow th {
+ border: 0;
+ border-top: 1px solid #aaa;
+ /* @noflip */
+ border-right: 1px solid #aaa;
+}
+
+.infobox.bordered .mergedrow td,
+.infobox.bordered .mergedrow th {
+ border: 0;
+ /* @noflip */
+ border-right: 1px solid #aaa;
+}
+
+/* Styles for geography infoboxes, eg countries,
+ country subdivisions, cities, etc. */
+.infobox.geography {
+ border-collapse: collapse;
+ line-height: 1.2em;
+ font-size: 90%;
+}
+
+.infobox.geography td,
+.infobox.geography th {
+ border-top: 1px solid #aaa;
+ padding: 0.4em 0.6em 0.4em 0.6em;
+}
+.infobox.geography .mergedtoprow td,
+.infobox.geography .mergedtoprow th {
+ border-top: 1px solid #aaa;
+ padding: 0.4em 0.6em 0.2em 0.6em;
+}
+
+.infobox.geography .mergedrow td,
+.infobox.geography .mergedrow th {
+ border: 0;
+ padding: 0 0.6em 0.2em 0.6em;
+}
+
+.infobox.geography .mergedbottomrow td,
+.infobox.geography .mergedbottomrow th {
+ border-top: 0;
+ border-bottom: 1px solid #aaa;
+ padding: 0 0.6em 0.4em 0.6em;
+}
+
+.infobox.geography .maptable td,
+.infobox.geography .maptable th {
+ border: 0;
+ padding: 0;
+}
+
+/* Normal font styling for table row headers with scope="row" tag */
+.wikitable.plainrowheaders th[scope=row] {
+ font-weight: normal;
+ /* @noflip */
+ text-align: left;
+}
+
+/* Lists in data cells are always left-aligned */
+.wikitable td ul,
+.wikitable td ol,
+.wikitable td dl {
+ /* @noflip */
+ text-align: left;
+}
+/* ...unless they also use the hlist class */
+.wikitable.hlist td ul,
+.wikitable.hlist td ol,
+.wikitable.hlist td dl {
+ text-align: inherit;
+}
+
+/* Icons for medialist templates [[Template:Listen]],
+ [[Template:Multi-listen_start]], [[Template:Video]],
+ [[Template:Multi-video_start]] */
+div.listenlist {
+ background: url("//upload.wikimedia.org/wikipedia/commons/4/47/Sound-icon.svg") no-repeat scroll 0% 0% transparent;
+ background-size: 30px;
+ padding-left: 40px;
+}
+
+/* Fix for hieroglyphs specificality issue in infoboxes ([[Bugzilla:41869]]) */
+table.mw-hiero-table td {
+ vertical-align: middle;
+}
+
+/* Style rules for media list templates */
+div.medialist {
+ min-height: 50px;
+ margin: 1em;
+ /* @noflip */
+ background-position: top left;
+ background-repeat: no-repeat;
+}
+div.medialist ul {
+ list-style-type: none;
+ list-style-image: none;
+ margin: 0;
+}
+div.medialist ul li {
+ padding-bottom: 0.5em;
+}
+div.medialist ul li li {
+ font-size: 91%;
+ padding-bottom: 0;
+}
+
+/* Change the external link icon to an Adobe icon for all PDF files
+ in browsers that support these CSS selectors, like Mozilla and Opera */
+div#content a[href$=".pdf"].external,
+div#content a[href*=".pdf?"].external,
+div#content a[href*=".pdf#"].external,
+div#content a[href$=".PDF"].external,
+div#content a[href*=".PDF?"].external,
+div#content a[href*=".PDF#"].external,
+div#mw_content a[href$=".pdf"].external,
+div#mw_content a[href*=".pdf?"].external,
+div#mw_content a[href*=".pdf#"].external,
+div#mw_content a[href$=".PDF"].external,
+div#mw_content a[href*=".PDF?"].external,
+div#mw_content a[href*=".PDF#"].external {
+ background: url("//upload.wikimedia.org/wikipedia/commons/2/23/Icons-mini-file_acrobat.gif") no-repeat right;
+ /* @noflip */
+ padding-right: 18px;
+}
+
+/* Change the external link icon to an Adobe icon anywhere the PDFlink class
+ is used (notably Template:PDFlink). This works in IE, unlike the above. */
+div#content span.PDFlink a,
+div#mw_content span.PDFlink a {
+ background: url("//upload.wikimedia.org/wikipedia/commons/2/23/Icons-mini-file_acrobat.gif") no-repeat right;
+ /* @noflip */
+ padding-right: 18px;
+}
+
+/* Content in columns with CSS instead of tables ([[Template:Columns]]) */
+div.columns-2 div.column {
+ /* @noflip */
+ float: left;
+ width: 50%;
+ min-width: 300px;
+}
+div.columns-3 div.column {
+ /* @noflip */
+ float: left;
+ width: 33.3%;
+ min-width: 200px;
+}
+div.columns-4 div.column {
+ /* @noflip */
+ float: left;
+ width: 25%;
+ min-width: 150px;
+}
+div.columns-5 div.column {
+ /* @noflip */
+ float: left;
+ width: 20%;
+ min-width: 120px;
+}
+
+/* Messagebox templates */
+.messagebox {
+ border: 1px solid #aaa;
+ background-color: #f9f9f9;
+ width: 80%;
+ margin: 0 auto 1em auto;
+ padding: .2em;
+}
+.messagebox.merge {
+ border: 1px solid #c0b8cc;
+ background-color: #f0e5ff;
+ text-align: center;
+}
+.messagebox.cleanup {
+ border: 1px solid #9f9fff;
+ background-color: #efefff;
+ text-align: center;
+}
+.messagebox.standard-talk {
+ border: 1px solid #c0c090;
+ background-color: #f8eaba;
+ margin: 4px auto;
+}
+/* For old WikiProject banners inside banner shells. */
+.mbox-inside .standard-talk,
+.messagebox.nested-talk {
+ border: 1px solid #c0c090;
+ background-color: #f8eaba;
+ width: 100%;
+ margin: 2px 0;
+ padding: 2px;
+}
+.messagebox.small {
+ width: 238px;
+ font-size: 85%;
+ /* @noflip */
+ float: right;
+ clear: both;
+ /* @noflip */
+ margin: 0 0 1em 1em;
+ line-height: 1.25em;
+}
+.messagebox.small-talk {
+ width: 238px;
+ font-size: 85%;
+ /* @noflip */
+ float: right;
+ clear: both;
+ /* @noflip */
+ margin: 0 0 1em 1em;
+ line-height: 1.25em;
+ background: #F8EABA;
+}
+
+/* Cell sizes for ambox/tmbox/imbox/cmbox/ombox/fmbox/dmbox message boxes */
+th.mbox-text, td.mbox-text { /* The message body cell(s) */
+ border: none;
+ /* @noflip */
+ padding: 0.25em 0.9em; /* 0.9em left/right */
+ width: 100%; /* Make all mboxes the same width regardless of text length */
+}
+td.mbox-image { /* The left image cell */
+ border: none;
+ /* @noflip */
+ padding: 2px 0 2px 0.9em; /* 0.9em left, 0px right */
+ text-align: center;
+}
+td.mbox-imageright { /* The right image cell */
+ border: none;
+ /* @noflip */
+ padding: 2px 0.9em 2px 0; /* 0px left, 0.9em right */
+ text-align: center;
+}
+td.mbox-empty-cell { /* An empty narrow cell */
+ border: none;
+ padding: 0px;
+ width: 1px;
+}
+
+/* Article message box styles */
+table.ambox {
+ margin: 0px 10%; /* 10% = Will not overlap with other elements */
+ border: 1px solid #aaa;
+ /* @noflip */
+ border-left: 10px solid #1e90ff; /* Default "notice" blue */
+ background: #fbfbfb;
+}
+table.ambox + table.ambox { /* Single border between stacked boxes. */
+ margin-top: -1px;
+}
+.ambox th.mbox-text,
+.ambox td.mbox-text { /* The message body cell(s) */
+ padding: 0.25em 0.5em; /* 0.5em left/right */
+}
+.ambox td.mbox-image { /* The left image cell */
+ /* @noflip */
+ padding: 2px 0 2px 0.5em; /* 0.5em left, 0px right */
+}
+.ambox td.mbox-imageright { /* The right image cell */
+ /* @noflip */
+ padding: 2px 0.5em 2px 0; /* 0px left, 0.5em right */
+}
+
+table.ambox-notice {
+ /* @noflip */
+ border-left: 10px solid #1e90ff; /* Blue */
+}
+table.ambox-speedy {
+ /* @noflip */
+ border-left: 10px solid #b22222; /* Red */
+ background: #fee; /* Pink */
+}
+table.ambox-delete {
+ /* @noflip */
+ border-left: 10px solid #b22222; /* Red */
+}
+table.ambox-content {
+ /* @noflip */
+ border-left: 10px solid #f28500; /* Orange */
+}
+table.ambox-style {
+ /* @noflip */
+ border-left: 10px solid #f4c430; /* Yellow */
+}
+table.ambox-move {
+ /* @noflip */
+ border-left: 10px solid #9932cc; /* Purple */
+}
+table.ambox-protection {
+ /* @noflip */
+ border-left: 10px solid #bba; /* Gray-gold */
+}
+
+/* Image message box styles */
+table.imbox {
+ margin: 4px 10%;
+ border-collapse: collapse;
+ border: 3px solid #1e90ff; /* Default "notice" blue */
+ background: #fbfbfb;
+}
+.imbox .mbox-text .imbox { /* For imboxes inside imbox-text cells. */
+ margin: 0 -0.5em; /* 0.9 - 0.5 = 0.4em left/right. */
+ display: block; /* Fix for webkit to force 100% width. */
+}
+.mbox-inside .imbox { /* For imboxes inside other templates. */
+ margin: 4px;
+}
+
+table.imbox-notice {
+ border: 3px solid #1e90ff; /* Blue */
+}
+table.imbox-speedy {
+ border: 3px solid #b22222; /* Red */
+ background: #fee; /* Pink */
+}
+table.imbox-delete {
+ border: 3px solid #b22222; /* Red */
+}
+table.imbox-content {
+ border: 3px solid #f28500; /* Orange */
+}
+table.imbox-style {
+ border: 3px solid #f4c430; /* Yellow */
+}
+table.imbox-move {
+ border: 3px solid #9932cc; /* Purple */
+}
+table.imbox-protection {
+ border: 3px solid #bba; /* Gray-gold */
+}
+table.imbox-license {
+ border: 3px solid #88a; /* Dark gray */
+ background: #f7f8ff; /* Light gray */
+}
+table.imbox-featured {
+ border: 3px solid #cba135; /* Brown-gold */
+}
+
+/* Category message box styles */
+table.cmbox {
+ margin: 3px 10%;
+ border-collapse: collapse;
+ border: 1px solid #aaa;
+ background: #DFE8FF; /* Default "notice" blue */
+}
+
+table.cmbox-notice {
+ background: #D8E8FF; /* Blue */
+}
+table.cmbox-speedy {
+ margin-top: 4px;
+ margin-bottom: 4px;
+ border: 4px solid #b22222; /* Red */
+ background: #FFDBDB; /* Pink */
+}
+table.cmbox-delete {
+ background: #FFDBDB; /* Red */
+}
+table.cmbox-content {
+ background: #FFE7CE; /* Orange */
+}
+table.cmbox-style {
+ background: #FFF9DB; /* Yellow */
+}
+table.cmbox-move {
+ background: #E4D8FF; /* Purple */
+}
+table.cmbox-protection {
+ background: #EFEFE1; /* Gray-gold */
+}
+
+/* Other pages message box styles */
+table.ombox {
+ margin: 4px 10%;
+ border-collapse: collapse;
+ border: 1px solid #aaa; /* Default "notice" gray */
+ background: #f9f9f9;
+}
+
+table.ombox-notice {
+ border: 1px solid #aaa; /* Gray */
+}
+table.ombox-speedy {
+ border: 2px solid #b22222; /* Red */
+ background: #fee; /* Pink */
+}
+table.ombox-delete {
+ border: 2px solid #b22222; /* Red */
+}
+table.ombox-content {
+ border: 1px solid #f28500; /* Orange */
+}
+table.ombox-style {
+ border: 1px solid #f4c430; /* Yellow */
+}
+table.ombox-move {
+ border: 1px solid #9932cc; /* Purple */
+}
+table.ombox-protection {
+ border: 2px solid #bba; /* Gray-gold */
+}
+
+/* Talk page message box styles */
+table.tmbox {
+ margin: 4px 10%;
+ border-collapse: collapse;
+ border: 1px solid #c0c090; /* Default "notice" gray-brown */
+ background: #f8eaba;
+}
+.mediawiki .mbox-inside .tmbox { /* For tmboxes inside other templates. The "mediawiki" class ensures that */
+ margin: 2px 0; /* this declaration overrides other styles (including mbox-small above) */
+ width: 100%; /* For Safari and Opera */
+}
+.mbox-inside .tmbox.mbox-small { /* "small" tmboxes should not be small when */
+ line-height: 1.5em; /* also "nested", so reset styles that are */
+ font-size: 100%; /* set in "mbox-small" above. */
+}
+
+table.tmbox-speedy {
+ border: 2px solid #b22222; /* Red */
+ background: #fee; /* Pink */
+}
+table.tmbox-delete {
+ border: 2px solid #b22222; /* Red */
+}
+table.tmbox-content {
+ border: 2px solid #f28500; /* Orange */
+}
+table.tmbox-style {
+ border: 2px solid #f4c430; /* Yellow */
+}
+table.tmbox-move {
+ border: 2px solid #9932cc; /* Purple */
+}
+table.tmbox-protection,
+table.tmbox-notice {
+ border: 1px solid #c0c090; /* Gray-brown */
+}
+
+/* Disambig and set index box styles */
+table.dmbox {
+ clear: both;
+ margin: 0.9em 1em;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ background: transparent;
+}
+
+/* Footer and header message box styles */
+table.fmbox {
+ clear: both;
+ margin: 0.2em 0;
+ width: 100%;
+ border: 1px solid #aaa;
+ background: #f9f9f9; /* Default "system" gray */
+}
+table.fmbox-system {
+ background: #f9f9f9;
+}
+table.fmbox-warning {
+ border: 1px solid #bb7070; /* Dark pink */
+ background: #ffdbdb; /* Pink */
+}
+table.fmbox-editnotice {
+ background: transparent;
+}
+/* Div based "warning" style fmbox messages. */
+div.mw-warning-with-logexcerpt,
+div.mw-lag-warn-high,
+div.mw-cascadeprotectedwarning,
+div#mw-protect-cascadeon {
+ clear: both;
+ margin: 0.2em 0;
+ border: 1px solid #bb7070;
+ background: #ffdbdb;
+ padding: 0.25em 0.9em;
+}
+/* Div based "system" style fmbox messages.
+ Used in [[MediaWiki:Readonly lag]]. */
+div.mw-lag-warn-normal,
+div.fmbox-system {
+ clear: both;
+ margin: 0.2em 0;
+ border: 1px solid #aaa;
+ background: #f9f9f9;
+ padding: 0.25em 0.9em;
+}
+
+/* These mbox-small classes must be placed after all other
+ ambox/tmbox/ombox etc classes. "body.mediawiki" is so
+ they override "table.ambox + table.ambox" above. */
+body.mediawiki table.mbox-small { /* For the "small=yes" option. */
+ /* @noflip */
+ clear: right;
+ /* @noflip */
+ float: right;
+ /* @noflip */
+ margin: 4px 0 4px 1em;
+ width: 238px;
+ font-size: 88%;
+ line-height: 1.25em;
+}
+body.mediawiki table.mbox-small-left { /* For the "small=left" option. */
+ /* @noflip */
+ margin: 4px 1em 4px 0;
+ width: 238px;
+ border-collapse: collapse;
+ font-size: 88%;
+ line-height: 1.25em;
+}
+
+/* Style for compact ambox */
+/* Hide the images */
+.compact-ambox table .mbox-image,
+.compact-ambox table .mbox-imageright,
+.compact-ambox table .mbox-empty-cell {
+ display: none;
+}
+/* Remove borders, backgrounds, padding, etc. */
+.compact-ambox table.ambox {
+ border: none;
+ border-collapse: collapse;
+ background: transparent;
+ margin: 0 0 0 1.6em !important;
+ padding: 0 !important;
+ width: auto;
+ display: block;
+}
+body.mediawiki .compact-ambox table.mbox-small-left {
+ font-size: 100%;
+ width: auto;
+ margin: 0;
+}
+/* Style the text cell as a list item and remove its padding */
+.compact-ambox table .mbox-text {
+ padding: 0 !important;
+ margin: 0 !important;
+}
+.compact-ambox table .mbox-text-span {
+ display: list-item;
+ line-height: 1.5em;
+ list-style-type: square;
+ list-style-image: url(//bits.wikimedia.org/skins/common/images/bullet.gif);
+}
+.skin-vector .compact-ambox table .mbox-text-span {
+ list-style-type: circle;
+ list-style-image: url(//bits.wikimedia.org/skins/vector/images/bullet-icon.png)
+}
+/* Allow for hiding text in compact form */
+.compact-ambox .hide-when-compact {
+ display: none;
+}
+
+/* Remove default styles for [[MediaWiki:Noarticletext]]. */
+div.noarticletext {
+ border: none;
+ background: transparent;
+ padding: 0;
+}
+
+/* Hide (formatting) elements from screen, but not from screenreaders */
+.visualhide {
+ position: absolute;
+ left: -10000px;
+ top: auto;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+}
+
+/* Bold save button */
+#wpSave {
+ font-weight: bold;
+}
+
+/* class hiddenStructure is defunct. See [[Wikipedia:hiddenStructure]] */
+.hiddenStructure {
+ display: inline !important;
+ color: #f00;
+ background-color: #0f0;
+}
+
+/* suppress missing interwiki image links where #ifexist cannot
+ be used due to high number of requests see .hidden-redlink on
+ [[m:MediaWiki:Common.css]] */
+.check-icon a.new {
+ display: none;
+ speak: none;
+}
+
+/* Removes underlines from certain links */
+.nounderlines a,
+.IPA a:link, .IPA a:visited {
+ text-decoration: none !important;
+}
+
+/* Standard Navigationsleisten, aka box hiding thingy
+ from .de. Documentation at [[Wikipedia:NavFrame]]. */
+div.NavFrame {
+ margin: 0;
+ padding: 4px;
+ border: 1px solid #aaa;
+ text-align: center;
+ border-collapse: collapse;
+ font-size: 95%;
+}
+div.NavFrame + div.NavFrame {
+ border-top-style: none;
+ border-top-style: hidden;
+}
+div.NavPic {
+ background-color: #fff;
+ margin: 0;
+ padding: 2px;
+ /* @noflip */
+ float: left;
+}
+div.NavFrame div.NavHead {
+ height: 1.6em;
+ font-weight: bold;
+ background-color: #ccf;
+ position: relative;
+}
+div.NavFrame p,
+div.NavFrame div.NavContent,
+div.NavFrame div.NavContent p {
+ font-size: 100%;
+}
+div.NavEnd {
+ margin: 0;
+ padding: 0;
+ line-height: 1px;
+ clear: both;
+}
+a.NavToggle {
+ position: absolute;
+ top: 0;
+ /* @noflip */
+ right: 3px;
+ font-weight: normal;
+ font-size: 90%;
+}
+
+/* Hatnotes and disambiguation notices */
+.rellink,
+.dablink {
+ font-style: italic;
+ /* @noflip */
+ padding-left: 1.6em;
+ margin-bottom: 0.5em;
+}
+.rellink i,
+.dablink i {
+ font-style: normal;
+}
+
+/* Allow transcluded pages to display in lists rather than a table.
+ Compatible in Firefox; incompatible in IE6. */
+.listify td { display: list-item; }
+.listify tr { display: block; }
+.listify table { display: block; }
+
+/* Geographical coordinates defaults. See [[Template:Coord/link]]
+ for how these are used. The classes "geo", "longitude", and
+ "latitude" are used by the [[Geo microformat]]. */
+.geo-default, .geo-dms, .geo-dec { display: inline; }
+.geo-nondefault, .geo-multi-punct { display: none; }
+.longitude, .latitude { white-space: nowrap; }
+
+/* When <div class="nonumtoc"> is used on the table of contents,
+ the ToC will display without numbers */
+.nonumtoc .tocnumber { display: none; }
+.nonumtoc #toc ul,
+.nonumtoc .toc ul {
+ line-height: 1.5em;
+ list-style: none none;
+ margin: .3em 0 0;
+ padding: 0;
+}
+.nonumtoc #toc ul ul,
+.nonumtoc .toc ul ul {
+ /* @noflip */
+ margin: 0 0 0 2em;
+}
+
+/* Allow limiting of which header levels are shown in a TOC;
+ <div class="toclimit-3">, for instance, will limit to
+ showing ==headings== and ===headings=== but no further
+ (as long as there are no =headings= on the page, which
+ there shouldn't be according to the MoS). */
+.toclimit-2 .toclevel-1 ul,
+.toclimit-3 .toclevel-2 ul,
+.toclimit-4 .toclevel-3 ul,
+.toclimit-5 .toclevel-4 ul,
+.toclimit-6 .toclevel-5 ul,
+.toclimit-7 .toclevel-6 ul {
+ display: none;
+}
+
+/* Styling for Template:Quote */
+blockquote.templatequote {
+ margin-top: 0;
+}
+blockquote.templatequote div.templatequotecite {
+ line-height: 1em;
+ /* @noflip */
+ text-align: left;
+ /* @noflip */
+ padding-left: 2em;
+ margin-top: 0;
+}
+blockquote.templatequote div.templatequotecite cite {
+ font-size: 85%;
+}
+
+/* User block messages */
+div.user-block {
+ padding: 5px;
+ margin-bottom: 0.5em;
+ border: 1px solid #A9A9A9;
+ background-color: #FFEFD5;
+}
+
+/* Prevent line breaks in silly places:
+ 1) Where desired
+ 2) Links when we don't want them to
+ 3) Bold "links" to the page itself
+ 4) Ref tags with group names <ref group="Note"> --> "[Note 1]" */
+.nowrap,
+.nowraplinks a,
+.nowraplinks .selflink,
+sup.reference a {
+ white-space: nowrap;
+}
+/* But allow wrapping where desired: */
+.wrap,
+.wraplinks a {
+ white-space: normal;
+}
+
+/* For template documentation */
+.template-documentation {
+ clear: both;
+ margin: 1em 0 0 0;
+ border: 1px solid #aaa;
+ background-color: #ecfcf4;
+ padding: 1em;
+}
+
+/* Inline divs in ImageMaps (code borrowed from de.wiki) */
+.imagemap-inline div {
+ display: inline;
+}
+
+/* Increase the height of the image upload box */
+#wpUploadDescription {
+ height: 13em;
+}
+
+/* Minimum thumb width */
+.thumbinner {
+ min-width: 100px;
+}
+
+/* Makes the background of a framed image white instead of gray.
+ Only visible with transparent images. */
+div.thumb .thumbimage {
+ background-color: #fff;
+}
+
+/* The backgrounds for galleries. */
+div#content .gallerybox div.thumb {
+ /* Light gray padding */
+ background-color: #F9F9F9;
+}
+/* Put a chequered background behind images, only visible if they have transparency.
+ '.filehistory a img' and '#file img:hover' are handled by MediaWiki core (as of 1.19) */
+.gallerybox .thumb img {
+ background: #fff url(//bits.wikimedia.org/skins/common/images/Checker-16x16.png) repeat;
+}
+/* But not on articles, user pages, portals or with opt-out. */
+.ns-0 .gallerybox .thumb img,
+.ns-2 .gallerybox .thumb img,
+.ns-100 .gallerybox .thumb img,
+.nochecker .gallerybox .thumb img {
+ background: #fff;
+}
+
+/* Prevent floating boxes from overlapping any category listings,
+ file histories, edit previews, and edit [Show changes] views. */
+#mw-subcategories, #mw-pages, #mw-category-media,
+#filehistory, #wikiPreview, #wikiDiff {
+ clear: both;
+}
+
+body.rtl #mw-articlefeedbackv5, body.rtl #mw-articlefeedback {
+ display: block; /* Override inline block mode */
+ margin-bottom: 1em;
+ /* @noflip */
+ clear: right; /* Clear any info boxes that stick out */
+ /* @noflip */
+ float: right; /* Prevents margin collapsing */
+}
+
+/* Selectively hide headers in WikiProject banners */
+.wpb .wpb-header { display: none; }
+.wpbs-inner .wpb .wpb-header { display: block; } /* for IE */
+.wpbs-inner .wpb .wpb-header { display: table-row; } /* for real browsers */
+.wpbs-inner .wpb-outside { display: none; } /* hide things that should only display outside shells */
+
+/* Styling for Abuse Filter tags */
+.mw-tag-markers {
+ font-family:sans-serif;
+ font-style:italic;
+ font-size:90%;
+}
+
+/* Hide stuff meant for accounts with special permissions. Made visible again in
+ [[MediaWiki:Group-sysop.css]], [[MediaWiki:Group-accountcreator.css]],
+ [[MediaWiki:Group-templateeditor.css]] and [[Mediawiki:Group-autoconfirmed.css]]. */
+.sysop-show,
+.accountcreator-show,
+.templateeditor-show,
+.autoconfirmed-show {
+ display: none;
+}
+
+/**
+ * Hide the redlink generated by {{Editnotice}},
+ * this overrides the ".sysop-show { display: none; }" above that applies
+ * to the same link as well.
+ */
+.ve-init-mw-viewPageTarget-toolbar-editNotices-notice .editnotice-redlink {
+ display: none !important;
+}
+
+/* Remove bullets when there are multiple edit page warnings */
+ul.permissions-errors > li {
+ list-style: none none;
+}
+ul.permissions-errors {
+ margin: 0;
+}
+
+/* No linewrap on the labels of the login/signup page */
+body.page-Special_UserLogin .mw-label label,
+body.page-Special_UserLogin_signup .mw-label label {
+ white-space: nowrap;
+}
+
+/* Pie chart test: Transparent borders */
+.transborder {
+ border: solid transparent;
+}
+* html .transborder { /* IE6 */
+ border: solid #000001;
+ filter: chroma(color=#000001);
+}
+
+/* Styling for updated markers on watchlist, history and recent/related changes.
+ Bullets are handled in skin-specific stylesheets. */
+.updatedmarker {
+ background-color: transparent;
+ color: #006400;
+}
+li.mw-changeslist-line-watched .mw-title,
+table.mw-changeslist-line-watched .mw-title,
+table.mw-enhanced-watch .mw-enhanced-rctime {
+ font-weight: normal;
+}
+
+/* Adjust font for inline HTML generated formulae */
+span.texhtml {
+ font-family: "Times New Roman", "Nimbus Roman No9 L", Times, serif;
+ font-size: 118%;
+ white-space: nowrap;
+}
+span.texhtml span.texhtml {
+ font-size: 100%;
+}
+
+/* Fix so <syntaxhighlight> tags and .css and .js pages get normal text size.
+ [[Bugzilla:26204]]. See also [[Wikipedia:Typography#The monospace 'bug']] */
+div.mw-geshi div,
+div.mw-geshi div pre,
+span.mw-geshi,
+pre.source-css,
+pre.source-javascript,
+pre.source-lua {
+ font-family: monospace, Courier !important;
+}
+
+/* Fix styling of transcluded prefindex tables */
+table#mw-prefixindex-list-table,
+table#mw-prefixindex-nav-table {
+ width: 98%;
+}
+
+/* For portals, added 2011-12-07 -bv
+ On wide screens, show these as two columns
+ On narrow and mobile screens, let them collapse into a single column */
+.portal-column-left {
+ float: left;
+ width: 50%;
+}
+.portal-column-right {
+ float: right;
+ width: 49%;
+}
+.portal-column-left-wide {
+ float: left;
+ width: 60%;
+}
+.portal-column-right-narrow {
+ float: right;
+ width: 39%;
+}
+.portal-column-left-extra-wide {
+ float: left;
+ width: 70%;
+}
+.portal-column-right-extra-narrow {
+ float: right;
+ width: 29%;
+}
+@media only screen and (max-width: 800px) {
+ /* Decouple the columns on narrow screens */
+ .portal-column-left,
+ .portal-column-right,
+ .portal-column-left-wide,
+ .portal-column-right-narrow,
+ .portal-column-left-extra-wide,
+ .portal-column-right-extra-narrow {
+ float: inherit;
+ width: inherit;
+ }
+}
+
+/* For announcements */
+#bodyContent .letterhead {
+ background-image:url('//upload.wikimedia.org/wikipedia/commons/e/e0/Tan-page-corner.png');
+ background-repeat:no-repeat;
+ padding: 2em;
+ background-color: #faf9f2;
+}
+
+/* Tree style lists */
+.treeview ul {
+ padding: 0;
+ margin: 0;
+}
+.treeview li {
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
+ list-style-image: none;
+ zoom: 1; /* BE KIND TO IE6 */;
+}
+.treeview li li {
+ background: url("//upload.wikimedia.org/wikipedia/commons/f/f2/Treeview-grey-line.png") no-repeat 0 -2981px;
+ /* @noflip */
+ padding-left: 20px;
+ text-indent: 0.3em;
+}
+.treeview li li.lastline {
+ background-position: 0 -5971px
+}
+.treeview li.emptyline > ul {
+ /* @noflip */
+ margin-left: -1px;
+}
+.treeview li.emptyline > ul > li:first-child {
+ background-position: 0 9px
+}
+
+/* hidden sortkey for tablesorter */
+td .sortkey,
+th .sortkey {
+ display: none;
+ speak: none;
+}
+
+/* Make it possible to hide checkboxes in <inputbox> */
+.inputbox-hidecheckboxes form .inputbox-element {
+ display: none !important;
+}
+
+/* Hide charinsert base for those not using the gadget */
+#editpage-specialchars {
+ display: none;
+}
+
+/* work-around for [[bugzilla:23965]] (Kaltura advertisement) */
+.k-player .k-attribution {
+ visibility: hidden;
+}
+
+/* [[MediaZilla:35337]] */
+@media (-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (min-resolution: 1.5dppx), (min-resolution: 144dpi) {
+ #p-logo a {
+ background-image: url("//upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Wikipedia-logo-v2-en.svg/204px-Wikipedia-logo-v2-en.svg.png") !important;
+ background-size: 136px auto;
+ }
+}
+@media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (min-resolution: 2dppx), (min-resolution: 192dpi) {
+ #p-logo a {
+ background-image: url("//upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Wikipedia-logo-v2-en.svg/270px-Wikipedia-logo-v2-en.svg.png") !important;
+ background-size: 135px auto;
+ }
+}
+/* Do not print:
+ 1: When in mainspace: Article message boxes,
+ navboxes, sister project boxes, disambig links,
+ and items marked as metadata.
+ 2: section edit links.
+ 3: navbar links.
+ 4: Show/hide toggles for collapsible items.
+*/
+.ns-0 .ambox,
+.ns-0 .navbox,
+.ns-0 .vertical-navbox,
+.ns-0 .infobox.sisterproject,
+.ns-0 .dablink,
+.ns-0 .metadata,
+.editlink,
+.navbar,
+a.NavToggle, span.collapseButton, span.mw-collapsible-toggle,
+th .sortkey, td .sortkey {
+ display: none !important;
+}
+
+/* Add formatting to make sure that "external references" from templates
+ like [[Template:Ref]] do not get URL expansion, not even when printed.
+ The anchor itself has class "external autonumber" and the url expansion
+ is inserted when printing (see the common printing style sheet at
+ http://en.wikipedia.org/skins-1.5/common/commonPrint.css) using the
+ ":after" pseudo-element of CSS. Also hide in <cite> elements.
+*/
+#content cite a.external.text:after,
+.nourlexpansion a.external.text:after,
+.nourlexpansion a.external.autonumber:after {
+ display: none !important;
+}
+
+/* Uncollapse collapsible tables/divs.
+ The proper way to do this for tables is to use display:table-row,
+ but this is not supported by all browsers, so use display:block as fallback.
+*/
+table.collapsible tr, div.NavPic, div.NavContent {
+ display: block !important;
+}
+table.collapsible tr {
+ display: table-row !important;
+}
+
+/* On websites with siteSub visible, the margin on the firstHeading is not needed. */
+#firstHeading {
+ margin: 0px;
+}
+
+/* We don't want very long URLs (that are added to the content in print) to widen the canvas */
+#content a.external.text:after,
+#content a.external.autonumber:after {
+ word-wrap: break-word;
+}
+/* Don't display some stuff on the main page */
+body.page-Main_Page #deleteconfirm,
+body.page-Main_Page #t-cite,
+body.page-Main_Page #footer-info-lastmod,
+body.action-view.page-Main_Page #siteSub,
+body.action-view.page-Main_Page #contentSub,
+body.action-view.page-Main_Page h1.firstHeading {
+ display: none !important;
+}
+
+/* Position Main Page top banner */
+body.page-Main_Page #mp-topbanner {
+ margin-top: 0 !important;
+}
+
+/* Position coordinates */
+#coordinates {
+ position: absolute;
+ top: 0em;
+ right: 0em;
+ float: right;
+ margin: 0em;
+ padding: 0em;
+ line-height: 1.5em;
+ text-align: right;
+ text-indent: 0;
+ font-size: 85%;
+ text-transform: none;
+ white-space: nowrap;
+}
+
+/* For positioning icons at top-right, used in Templates
+ "Spoken Article" and "Featured Article" */
+div.topicon {
+ position: absolute;
+ top: -2em;
+ margin-right: -10px;
+ display: block !important;
+}
+
+/* FR topicon position */
+div.flaggedrevs_short {
+ position: absolute;
+ top: -3em;
+ right: 80px;
+ z-index: 1;
+ margin-left: 0;
+ /* Because this is not yet a topicon, we emulate it's behavior,
+ this ensure compatibility with edit lead section gadget. */
+ margin-right: -10px;
+}
+
+/* On rtl interfaces, we need to override the defaults.
+ It is content included (so ltr), but positioned in part of the rtl interface. */
+body.rtl #protected-icon {
+ /* @noflip */
+ left: 55px;
+}
+body.rtl #spoken-icon,
+body.rtl #commons-icon {
+ /* @noflip */
+ left: 30px;
+}
+body.rtl #featured-star {
+ /* @noflip */
+ left: 10px;
+}
+
+/* Menu over FR box */
+div.vectorMenu div {
+ z-index: 2;
+}
+
+/* Display "From Wikipedia, the free encyclopedia" */
+#siteSub {
+ display: inline;
+ font-size: 92%;
+}
+
+/* Bullets for Good and Featured interwiki links */
+li.GA {
+ list-style-image: url(//upload.wikimedia.org/wikipedia/commons/4/42/Monobook-bullet-ga.png);
+}
+li.FA {
+ list-style-image: url(//upload.wikimedia.org/wikipedia/commons/d/d4/Monobook-bullet-star.png);
+}
+
+/* Styling for updated markers on watchlist, history and recent/related changes */
+li.mw-changeslist-line-watched,
+li.mw-history-line-updated {
+ list-style-image: url(//upload.wikimedia.org/wikipedia/commons/c/c2/ChangedBulletVector.png);
+}
+
+/* Blue instead of yellow padlock for secure links. */
+#bodyContent a.external[href ^="https://"],
+.link-https {
+ background: url(//upload.wikimedia.org/wikipedia/en/0/00/Lock_icon_blue.gif) center right no-repeat;
+ /* @noflip */
+ padding-right: 16px;
+}
+
+/* (Soft) redirect styling (bug:26544) */
+div.redirectMsg img {
+ vertical-align: text-bottom;
+}
+.redirectText {
+ font-size: 150%;
+ margin: 5px;
+}
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/wikipedia.min.css b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/wikipedia.min.css
new file mode 100644
index 00000000000..eecfc919430
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/wikipedia.min.css
@@ -0,0 +1 @@
+html,body{height:100%;margin:0;padding:0;font-family:sans-serif;font-size:1em}body{background-color:#f3f3f3;background-image:url(images/page-base.png)}div#content{margin-left:10em;padding:1em;background-image:url(images/border.png);background-position:top left;background-repeat:repeat-y;background-color:white;color:black;direction:ltr}#mw-page-base{height:5em;background-color:white;background-image:url(images/page-fade.png);background-position:bottom left;background-repeat:repeat-x}#mw-head-base{margin-top:-5em;margin-left:10em;height:5em;background-image:url(images/border.png);background-position:bottom left;background-repeat:repeat-x}div#mw-head{position:absolute;top:0;right:0;width:100%}div#mw-head h5{margin:0;padding:0}div.emptyPortlet{display:none}#p-personal{position:absolute;top:0;right:.75em}#p-personal h5{display:none}#p-personal ul{list-style:none;margin:0;padding-left:10em}#p-personal li{line-height:1.125em;float:left}#p-personal li{margin-left:.75em;margin-top:.5em;font-size:.75em;white-space:nowrap}#left-navigation{position:absolute;left:10em;top:2.5em}#right-navigation{float:right;margin-top:2.5em}div.vectorTabs h5,div.vectorMenu h5 span{display:none}div.vectorTabs{float:left;height:2.5em}div.vectorTabs{background-image:url(images/tab-break.png);background-position:bottom left;background-repeat:no-repeat;padding-left:1px}div.vectorTabs ul{float:left}div.vectorTabs ul{height:100%;list-style:none;margin:0;padding:0}div.vectorTabs ul li{float:left}div.vectorTabs ul li{line-height:1.125em;display:inline-block;height:100%;margin:0;padding:0;background-color:#f3f3f3;background-image:url(images/tab-normal-fade.png);background-position:bottom left;background-repeat:repeat-x;white-space:nowrap}div.vectorTabs ul>li{display:block}div.vectorTabs li.selected{background-image:url(images/tab-current-fade.png)}div.vectorTabs li a{display:inline-block;height:1.9em;padding-left:.5em;padding-right:.5em;color:#0645ad;cursor:pointer;font-size:.8em}div.vectorTabs li>a{display:block}div.vectorTabs li.icon a{background-position:bottom right;background-repeat:no-repeat}div.vectorTabs span a{display:inline-block;padding-top:1.25em}div.vectorTabs span>a{float:left;display:block}div.vectorTabs span{display:inline-block;background-image:url(images/tab-break.png);background-position:bottom right;background-repeat:no-repeat}div.vectorTabs li.selected a,div.vectorTabs li.selected a:visited{color:#333;text-decoration:none}div.vectorTabs li.new a,div.vectorTabs li.new a:visited{color:#a55858}div.vectorMenu{direction:ltr;float:left;background-image:url(images/arrow-down-icon.png);background-position:100% 60%;background-repeat:no-repeat;cursor:pointer}div.vectorMenuFocus{background-image:url(images/arrow-down-focus-icon.png);background-position:100% 60%}body.rtl div.vectorMenu{direction:rtl}div#mw-head div.vectorMenu h5{float:left;background-image:url(images/tab-break.png);background-repeat:no-repeat}div#mw-head div.vectorMenu h5{background-position:bottom left;margin-left:-1px}div#mw-head div.vectorMenu>h5{background-image:none}div#mw-head div.vectorMenu h4{display:inline-block;float:left;font-size:.8em;padding-left:.5em;padding-top:1.375em;font-weight:normal;border:none}div.vectorMenu h5 a{display:inline-block;width:24px;height:2.5em;text-decoration:none;background-image:url(images/tab-break.png);background-repeat:no-repeat}div.vectorMenu h5 a{background-position:bottom right}div.vectorMenu h5>a{display:block}div.vectorMenu div.menu{position:relative;display:none;clear:both;text-align:left}body.rtl div.vectorMenu div.menu{margin-left:24px}body.rtl div.vectorMenu>div.menu{margin-left:auto}body.rtl div.vectorMenu>div.menu,x:-moz-any-link{margin-left:23px}div.vectorMenu:hover div.menu,div.vectorMenu div.menuForceShow{display:block}div.vectorMenu ul{position:absolute;background-color:white;border:solid 1px silver;border-top-width:0;list-style:none;list-style-image:none;list-style-type:none;padding:0;margin:0;margin-left:-1px;text-align:left}div.vectorMenu ul,x:-moz-any-link{min-width:5em}div.vectorMenu ul,x:-moz-any-link,x:default{min-width:0}div.vectorMenu li{padding:0;margin:0;text-align:left;line-height:1em}div.vectorMenu li a{display:inline-block;padding:.5em;white-space:nowrap;color:#0645ad;cursor:pointer;font-size:.8em}div.vectorMenu li>a{display:block}div.vectorMenu li.selected a,div.vectorMenu li.selected a:visited{color:#333;text-decoration:none}#p-search h5{display:none}#p-search{float:left}#p-search{margin-right:.5em;margin-left:.5em}#p-search form,#p-search input{margin:0;margin-top:.4em}div#simpleSearch{display:block;width:14em;height:1.4em;margin-top:.65em;position:relative;min-height:1px;border:solid 1px #AAA;color:black;background-color:white;background-image:url(images/search-fade.png);background-position:top left;background-repeat:repeat-x}div#simpleSearch label{font-size:13px;top:.25em;direction:ltr}div#simpleSearch input{color:black;direction:ltr}div#simpleSearch input:focus{outline:none}div#simpleSearch input.placeholder{color:#999}div#simpleSearch input::-webkit-input-placeholder{color:#999}div#simpleSearch input#searchInput{position:absolute;top:0;left:0;width:90%;margin:0;padding:0;padding-left:.2em;padding-top:.2em;padding-bottom:.2em;outline:none;border:none;font-size:13px;background-color:transparent;direction:ltr}div#simpleSearch button#searchButton{position:absolute;width:10%;right:0;top:0;padding:0;padding-top:.3em;padding-bottom:.2em;padding-right:.4em;margin:0;border:none;cursor:pointer;background-color:transparent;background-image:none}div#simpleSearch button#searchButton img{border:none;margin:0;margin-top:-3px;padding:0}div#simpleSearch button#searchButton>img{margin:0}div#mw-panel{position:absolute;top:160px;padding-top:1em;width:10em;left:0}div#mw-panel div.portal{padding-bottom:1.5em;direction:ltr}div#mw-panel div.portal h5{font-weight:normal;color:#444;padding:.25em;padding-top:0;padding-left:1.75em;cursor:default;border:none;font-size:.75em}div#mw-panel div.portal div.body{margin:0;padding-top:.5em;margin-left:1.25em;background-image:url(images/portal-break.png);background-repeat:no-repeat;background-position:top left}div#mw-panel div.portal div.body ul{list-style:none;list-style-image:none;list-style-type:none;padding:0;margin:0}div#mw-panel div.portal div.body ul li{line-height:1.125em;padding:0;padding-bottom:.5em;margin:0;overflow:hidden;font-size:.75em}div#mw-panel div.portal div.body ul li a{color:#0645ad}div#mw-panel div.portal div.body ul li a:visited{color:#0b0080}div#footer{margin-left:10em;margin-top:0;padding:.75em;background-image:url(images/border.png);background-position:top left;background-repeat:repeat-x;direction:ltr}div#footer ul{list-style:none;list-style-image:none;list-style-type:none;margin:0;padding:0}div#footer ul li{margin:0;padding:0;padding-top:.5em;padding-bottom:.5em;color:#333;font-size:.7em}div#footer #footer-icons{float:right}body.ltr div#footer #footer-places{float:left}div#footer #footer-info li{line-height:1.4em}div#footer #footer-icons li{float:left;margin-left:.5em;line-height:2em;text-align:right}div#footer #footer-places li{float:left;margin-right:1em;line-height:2em}#p-logo{position:absolute;top:-160px;left:0;width:10em;height:160px}#p-logo a{display:block;width:10em;height:160px;background-repeat:no-repeat;background-position:center center;text-decoration:none}#preftoc{width:100%;float:left;clear:both;margin:0!important;padding:0!important;background-image:url(images/preferences-break.png);background-position:bottom left;background-repeat:no-repeat}#preftoc li{float:left;margin:0;padding:0;padding-right:1px;height:2.25em;white-space:nowrap;list-style-type:none;list-style-image:none;background-image:url(images/preferences-break.png);background-position:bottom right;background-repeat:no-repeat}#preftoc li:first-child{margin-left:1px}#preftoc a,#preftoc a:active{display:inline-block;position:relative;color:#0645ad;padding:.5em;text-decoration:none;background-image:none;font-size:.9em}#preftoc a:hover,#preftoc a:focus{text-decoration:underline}#preftoc li.selected a{background-image:url(images/preferences-fade.png);background-position:bottom;background-repeat:repeat-x;color:#333;text-decoration:none}#preferences{float:left;width:100%;margin:0;margin-top:-2px;clear:both;border:solid 1px #ccc;background-color:#f9f9f9;background-image:url(images/preferences-base.png)}#preferences fieldset{border:none;border-top:solid 1px #ccc}#preferences fieldset.prefsection{border:none;padding:0;margin:1em}#preferences legend{color:#666}#preferences fieldset.prefsection legend.mainLegend{display:none}#preferences td{padding-left:.5em;padding-right:.5em}#preferences td.htmlform-tip{font-size:x-small;padding:.2em 2em;color:#666}#preferences div.mw-prefs-buttons{padding:1em}#preferences div.mw-prefs-buttons input{margin-right:.25em}div#content{line-height:1.5em}#bodyContent{font-size:.8em}.editsection{float:right}ul{list-style-image:url(images/bullet-icon.png)}pre{line-height:1.3em}#siteNotice{font-size:.8em}#firstHeading{padding-top:0;margin-top:0;padding-top:0;font-size:1.6em}div#content a.external,div#content a.external[href ^="gopher://"]{background:url(images/external-link-ltr-icon.png) center right no-repeat;padding-right:13px}div#content a.external[href ^="https://"],.link-https{background:url(images/lock-icon.png) center right no-repeat;padding-right:13px}div#content a.external[href ^="mailto:"],.link-mailto{background:url(images/mail-icon.png) center right no-repeat;padding-right:13px}div#content a.external[href ^="news:"]{background:url(images/news-icon.png) center right no-repeat;padding-right:13px}div#content a.external[href ^="ftp://"],.link-ftp{background:url(images/file-icon.png) center right no-repeat;padding-right:13px}div#content a.external[href ^="irc://"],div#content a.external[href ^="ircs://"],.link-irc{background:url(images/talk-icon.png) center right no-repeat;padding-right:13px}div#content a.external[href $=".ogg"],div#content a.external[href $=".OGG"],div#content a.external[href $=".mid"],div#content a.external[href $=".MID"],div#content a.external[href $=".midi"],div#content a.external[href $=".MIDI"],div#content a.external[href $=".mp3"],div#content a.external[href $=".MP3"],div#content a.external[href $=".wav"],div#content a.external[href $=".WAV"],div#content a.external[href $=".wma"],div#content a.external[href $=".WMA"],.link-audio{background:url(images/audio-icon.png) center right no-repeat;padding-right:13px}div#content a.external[href $=".ogm"],div#content a.external[href $=".OGM"],div#content a.external[href $=".avi"],div#content a.external[href $=".AVI"],div#content a.external[href $=".mpeg"],div#content a.external[href $=".MPEG"],div#content a.external[href $=".mpg"],div#content a.external[href $=".MPG"],.link-video{background:url(images/video-icon.png) center right no-repeat;padding-right:13px}div#content a.external[href $=".pdf"],div#content a.external[href $=".PDF"],div#content a.external[href *=".pdf#"],div#content a.external[href *=".PDF#"],div#content a.external[href *=".pdf?"],div#content a.external[href *=".PDF?"],.link-document{background:url(images/document-icon.png) center right no-repeat;padding-right:13px}#pt-userpage,#pt-anonuserpage,#pt-login{background:url(images/user-icon.png) left top no-repeat;padding-left:15px!important;text-transform:none}.redirectText{font-size:140%}.redirectMsg img{vertical-align:text-bottom}#bodyContent{position:relative;width:100%}#mw-js-message{font-size:.8em}div#bodyContent{line-height:1.5em}#ca-unwatch.icon a,#ca-watch.icon a{margin:0;padding:0;outline:none;display:block;width:26px;padding-top:3.1em;margin-top:0;margin-top:-0.8em!ie;height:0;overflow:hidden;background-image:url(images/watch-icons.png)}#ca-unwatch.icon a{background-position:-43px 60%}#ca-watch.icon a{background-position:5px 60%}#ca-unwatch.icon a:hover,#ca-unwatch.icon a:focus{background-position:-67px 60%}#ca-watch.icon a:hover,#ca-watch.icon a:focus{background-position:-19px 60%}#ca-unwatch.icon a.loading,#ca-watch.icon a.loading{background-image:url(images/watch-icon-loading.gif);background-position:5px 60%}#ca-unwatch.icon a span,#ca-watch.icon a span{display:none}div.vectorTabs ul{background-image:url(images/tab-break.png);background-position:right bottom;background-repeat:no-repeat}.tipsy{font-size:.8em}.mw-content-ltr{direction:ltr}.mw-content-rtl{direction:rtl}.sitedir-ltr textarea,.sitedir-ltr input{direction:ltr}.sitedir-rtl textarea,.sitedir-rtl input{direction:rtl}input[type="submit"],input[type="button"],input[type="reset"],input[type="file"]{direction:ltr}textarea[dir="ltr"],input[dir="ltr"]{direction:ltr}textarea[dir="rtl"],input[dir="rtl"]{direction:rtl}abbr,acronym,.explain{border-bottom:1px dotted;cursor:help}.mw-plusminus-pos{color:#006400}.mw-plusminus-neg{color:#8b0000}.mw-plusminus-null{color:#aaa}.allpagesredirect,.redirect-in-category,.watchlistredir{font-style:italic}span.comment{font-style:italic}span.changedby{font-size:95%}.texvc{direction:ltr;unicode-bidi:embed}img.tex{vertical-align:middle}span.texhtml{font-family:serif}#wikiPreview.ontop{margin-bottom:1em}#editform,#toolbar,#wpTextbox1{clear:both}#toolbar img{cursor:pointer}div#mw-js-message{margin:1em 5%;padding:.5em 2.5%;border:solid 1px #ddd;background-color:#fcfcfc}.editsection{float:right;margin-left:5px}.mw-content-ltr .editsection,.mw-content-rtl .mw-content-ltr .editsection{float:right}.mw-content-rtl .editsection,.mw-content-ltr .mw-content-rtl .editsection{float:left}div.mw-filepage-resolutioninfo{font-size:smaller}h2#filehistory{clear:both}table.filehistory th,table.filehistory td{vertical-align:top}table.filehistory th{text-align:left}table.filehistory td.mw-imagepage-filesize,table.filehistory th.mw-imagepage-filesize{white-space:nowrap}table.filehistory td.filehistory-selected{font-weight:bold}.filehistory a img,#file img:hover{background:white url(images/Checker-16x16.png) repeat}li span.deleted,span.history-deleted{text-decoration:line-through;color:#888;font-style:italic}.not-patrolled{background-color:#ffa}.unpatrolled{font-weight:bold;color:red}div.patrollink{font-size:75%;text-align:right}td.mw-label{text-align:right}td.mw-input{text-align:left}td.mw-submit{text-align:left}td.mw-label{vertical-align:top}.prefsection td.mw-label{width:20%}.prefsection table{width:100%}td.mw-submit{white-space:nowrap}table.mw-htmlform-nolabel td.mw-label{width:1px}tr.mw-htmlform-vertical-label td.mw-label{text-align:left!important}.mw-htmlform-invalid-input td.mw-input input{border-color:red}.mw-htmlform-flatlist div.mw-htmlform-flatlist-item{display:inline;margin-right:1em;white-space:nowrap}input#wpSummary{width:80%}.thumbcaption{text-align:left}.magnify{float:right}#catlinks{text-align:left}.catlinks ul{display:inline;margin:0;padding:0;list-style:none;list-style-type:none;list-style-image:none;vertical-align:middle!ie}.catlinks li{display:inline-block;line-height:1.25em;border-left:1px solid #AAA;margin:.125em 0;padding:0 .5em;zoom:1;display:inline!ie}.catlinks li:first-child{padding-left:.25em;border-left:none}.mw-hidden-cats-hidden{display:none}.catlinks-allhidden{display:none}p.mw-ipb-conveniencelinks,p.mw-protect-editreasons,p.mw-filedelete-editreasons,p.mw-delete-editreasons,p.mw-revdel-editreasons{font-size:90%;text-align:right}.os-suggest{overflow:auto;overflow-x:hidden;position:absolute;top:0;left:0;width:0;background-color:white;border-style:solid;border-color:#AAA;border-width:1px;z-index:99;font-size:95%}table.os-suggest-results{font-size:95%;cursor:pointer;border:0;border-collapse:collapse;width:100%}.os-suggest-result,.os-suggest-result-hl{white-space:nowrap;background-color:white;color:black;padding:2px}.os-suggest-result-hl,.os-suggest-result-hl-webkit{background-color:#4C59A6;color:white}.os-suggest-toggle{position:relative;left:1ex;font-size:65%}.os-suggest-toggle-def{position:absolute;top:0;left:0;font-size:65%;visibility:hidden}.autocomment{color:gray}#pagehistory .history-user{margin-left:.4em;margin-right:.2em}#pagehistory span.minor{font-weight:bold}#pagehistory li{border:1px solid white}#pagehistory li.selected{background-color:#f9f9f9;border:1px dashed #aaa}.mw-history-revisiondelete-button,#mw-fileduplicatesearch-icon{float:right}.newpage,.minoredit,.botedit{font-weight:bold}#shared-image-dup,#shared-image-conflict{font-style:italic}div.mw-warning-with-logexcerpt{padding:3px;margin-bottom:3px;border:2px solid #2F6FAB;clear:both}div.mw-warning-with-logexcerpt ul li{font-size:90%}span.mw-revdelundel-link,strong.mw-revdelundel-link{font-size:90%}span.mw-revdelundel-hidden,input.mw-revdelundel-hidden{visibility:hidden}td.mw-revdel-checkbox,th.mw-revdel-checkbox{padding-right:10px;text-align:center}a.feedlink{background:url(images/feed-icon.png) center left no-repeat;padding-left:16px}.plainlinks a{background:none!important;padding:0!important}.rtl a.external.free,.rtl a.external.autonumber{direction:ltr;unicode-bidi:embed}table.wikitable{margin:1em 1em 1em 0;background-color:#f9f9f9;border:1px #aaa solid;border-collapse:collapse;color:black}table.wikitable>tr>th,table.wikitable>tr>td,table.wikitable>*>tr>th,table.wikitable>*>tr>td{border:1px #aaa solid;padding:.2em}table.wikitable>tr>th,table.wikitable>*>tr>th{background-color:#f2f2f2;text-align:center}table.wikitable>caption{font-weight:bold}table.collapsed tr.collapsable{display:none}.success{color:green;font-size:larger}.warning{color:#FFA500;font-size:larger}.error{color:red;font-size:larger}.errorbox,.warningbox,.successbox{font-size:larger;border:2px solid;padding:.5em 1em;float:left;margin-bottom:2em;color:#000}.errorbox{border-color:red;background-color:#fff2f2}.warningbox{border-color:#FF8C00;background-color:#FFFFC0}.successbox{border-color:green;background-color:#dfd}.errorbox h2,.warningbox h2,.successbox h2{font-size:1em;font-weight:bold;display:inline;margin:0 .5em 0 0;border:none}.mw-infobox{border:2px solid #ff7f00;margin:.5em;clear:left;overflow:hidden}.mw-infobox-left{margin:7px;float:left;width:35px}.mw-infobox-right{margin:.5em .5em .5em 49px}.previewnote{color:#c00;margin-bottom:1em}.previewnote p{text-indent:3em;margin:.8em 0}.visualClear{clear:both}#mw_trackbacks{border:solid 1px #bbf;background-color:#eef;padding:.2em}.mw-datatable{border-collapse:collapse}.mw-datatable,.mw-datatable td,.mw-datatable th{border:1px solid #aaa;padding:0 .15em 0 .15em}.mw-datatable th{background-color:#ddf}.mw-datatable td{background-color:#fff}.mw-datatable tr:hover td{background-color:#eef}.TablePager{min-width:80%}.TablePager_nav{margin:0 auto}.TablePager_nav td{padding:3px;text-align:center}.TablePager_nav a{text-decoration:none}.imagelist td,.imagelist th{white-space:nowrap}.imagelist .TablePager_col_links{background-color:#eef}.imagelist .TablePager_col_img_description{white-space:normal}.imagelist th.TablePager_sort{background-color:#ccf}ul#filetoc{text-align:center;border:1px solid #aaa;background-color:#f9f9f9;padding:5px;font-size:95%;margin-bottom:.5em;margin-left:0;margin-right:0}#filetoc li{display:inline;list-style-type:none;padding-right:2em}table.mw_metadata{font-size:.8em;margin-left:.5em;margin-bottom:.5em;width:400px}table.mw_metadata caption{font-weight:bold}table.mw_metadata th{font-weight:normal}table.mw_metadata td{padding:.1em}table.mw_metadata{border:none;border-collapse:collapse}table.mw_metadata td,table.mw_metadata th{text-align:center;border:1px solid #aaa;padding-left:5px;padding-right:5px}table.mw_metadata th{background-color:#f9f9f9}table.mw_metadata td{background-color:#fcfcfc}table.mw_metadata ul.metadata-langlist{list-style-type:none;list-style-image:none;padding-right:5px;padding-left:5px;margin:0}.mw-content-ltr ul,.mw-content-rtl .mw-content-ltr ul{margin:.3em 0 0 1.6em;padding:0}.mw-content-rtl ul,.mw-content-ltr .mw-content-rtl ul{margin:.3em 1.6em 0 0;padding:0}.mw-content-ltr ol,.mw-content-rtl .mw-content-ltr ol{margin:.3em 0 0 3.2em;padding:0}.mw-content-rtl ol,.mw-content-ltr .mw-content-rtl ol{margin:.3em 3.2em 0 0;padding:0}.mw-content-ltr dd,.mw-content-rtl .mw-content-ltr dd{margin-left:1.6em;margin-right:0}.mw-content-rtl dd,.mw-content-ltr .mw-content-rtl dd{margin-right:1.6em;margin-left:0}li.gallerybox{vertical-align:top;border:solid 2px white;display:-moz-inline-box;display:inline-block}ul.gallery,li.gallerybox{zoom:1;*display:inline}ul.gallery{margin:2px;padding:2px;display:block}li.gallerycaption{font-weight:bold;text-align:center;display:block;word-wrap:break-word}li.gallerybox div.thumb{text-align:center;border:1px solid #ccc;background-color:#f9f9f9;margin:2px}li.gallerybox div.thumb img{display:block;margin:0 auto}div.gallerytext{overflow:hidden;font-size:94%;padding:2px 4px;word-wrap:break-word}.mw-ajax-loader{background-image:url(images/ajax-loader.gif);background-position:center center;background-repeat:no-repeat;padding:16px;position:relative;top:-16px}.mw-small-spinner{padding:10px!important;margin-right:.6em;background-image:url(images/spinner.gif);background-position:center center;background-repeat:no-repeat}h1:lang(as),h1:lang(bh),h1:lang(bho),h1:lang(bn),h1:lang(gu),h1:lang(hi),h1:lang(kn),h1:lang(ml),h1:lang(mr),h1:lang(or),h1:lang(pa),h1:lang(sa),h1:lang(ta),h1:lang(te){line-height:1.5em!important}h2:lang(as),h3:lang(as),h4:lang(as),h5:lang(as),h6:lang(as),h2:lang(bho),h3:lang(bho),h4:lang(bho),h5:lang(bho),h6:lang(bho),h2:lang(bh),h3:lang(bh),h4:lang(bh),h5:lang(bh),h6:lang(bh),h2:lang(bn),h3:lang(bn),h4:lang(bn),h5:lang(bn),h6:lang(bn),h2:lang(gu),h3:lang(gu),h4:lang(gu),h5:lang(gu),h6:lang(gu),h2:lang(hi),h3:lang(hi),h4:lang(hi),h5:lang(hi),h6:lang(hi),h2:lang(kn),h3:lang(kn),h4:lang(kn),h5:lang(kn),h6:lang(kn),h2:lang(ml),h3:lang(ml),h4:lang(ml),h5:lang(ml),h6:lang(ml),h2:lang(mr),h3:lang(mr),h4:lang(mr),h5:lang(mr),h6:lang(mr),h2:lang(or),h3:lang(or),h4:lang(or),h5:lang(or),h6:lang(or),h2:lang(pa),h3:lang(pa),h4:lang(pa),h5:lang(pa),h6:lang(pa),h2:lang(sa),h3:lang(sa),h4:lang(sa),h5:lang(sa),h6:lang(sa),h2:lang(ta),h3:lang(ta),h4:lang(ta),h5:lang(ta),h6:lang(ta),h2:lang(te),h3:lang(te),h4:lang(te),h5:lang(te),h6:lang(te){line-height:1.2em}ol:lang(bcc) li,ol:lang(bqi) li,ol:lang(fa) li,ol:lang(glk) li,ol:lang(kk-arab) li,ol:lang(mzn) li{list-style-type:-moz-persian;list-style-type:persian}ol:lang(ckb) li{list-style-type:-moz-arabic-indic;list-style-type:arabic-indic}ol:lang(hi) li,ol:lang(mr) li{list-style-type:-moz-devanagari;list-style-type:devanagari}ol:lang(as) li,ol:lang(bn) li{list-style-type:-moz-bengali;list-style-type:bengali}ol:lang(or) li{list-style-type:-moz-oriya;list-style-type:oriya}#toc ul,.toc ul{margin:.3em 0}.mw-content-ltr .toc ul,.mw-content-ltr #toc ul,.mw-content-rtl .mw-content-ltr .toc ul,.mw-content-rtl .mw-content-ltr #toc ul{text-align:left}.mw-content-rtl .toc ul,.mw-content-rtl #toc ul,.mw-content-ltr .mw-content-rtl .toc ul,.mw-content-ltr .mw-content-rtl #toc ul{text-align:right}.mw-content-ltr .toc ul ul,.mw-content-ltr #toc ul ul,.mw-content-rtl .mw-content-ltr .toc ul ul,.mw-content-rtl .mw-content-ltr #toc ul ul{margin:0 0 0 2em}.mw-content-rtl .toc ul ul,.mw-content-rtl #toc ul ul,.mw-content-ltr .mw-content-rtl .toc ul ul,.mw-content-ltr .mw-content-rtl #toc ul ul{margin:0 2em 0 0}#toc #toctitle,.toc #toctitle,#toc .toctitle,.toc .toctitle{direction:ltr}.mw-help-field-hint{display:none;margin-left:2px;margin-bottom:-8px;padding:0 0 0 15px;background-image:url('images/help-question.gif');background-position:left center;background-repeat:no-repeat;cursor:pointer;font-size:.8em;text-decoration:underline;color:#0645ad}.mw-help-field-hint:hover{background-image:url('images/help-question-hover.gif')}.mw-help-field-data{display:block;background-color:#d6f3ff;padding:5px 8px 4px 8px;border:1px solid #5dc9f4;margin-left:20px}.tipsy{padding:5px 5px 10px;font-size:12px;position:absolute;z-index:100000;overflow:visible}.tipsy-inner{padding:5px 8px 4px 8px;background-color:#d6f3ff;color:black;border:1px solid #5dc9f4;max-width:300px;text-align:left}.tipsy-arrow{position:absolute;background:url(images/tipsy-arrow.gif) no-repeat top left;width:13px;height:13px}.tipsy-se .tipsy-arrow{bottom:-2px;right:10px;background-position:0 100%}#mw-clearyourcache,#mw-sitecsspreview,#mw-sitejspreview,#mw-usercsspreview,#mw-userjspreview{direction:ltr;unicode-bidi:embed}.diff-currentversion-title,.diff{direction:ltr;unicode-bidi:embed}.diff-contentalign-right td{direction:rtl;unicode-bidi:embed}.diff-contentalign-left td{direction:ltr;unicode-bidi:embed}.diff-otitle,.diff-ntitle,.diff-lineno{direction:ltr!important;unicode-bidi:embed}#mw-revision-info,#mw-revision-info-current,#mw-revision-nav{direction:ltr;display:inline}div.tright,div.floatright,table.floatright{clear:right;float:right}div.tleft,div.floatleft,table.floatleft{float:left;clear:left}div.floatright,table.floatright,div.floatleft,table.floatleft{position:relative}#mw-credits a{unicode-bidi:embed}.mw-jump,#jump-to-nav{overflow:hidden;height:0;zoom:1}.printfooter{display:none}.xdebug-error{position:absolute;z-index:99}.editsection,.toctoggle{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}a.stub,a.new{color:#ba0000;text-decoration:none}#toc{border:1px solid #aaa;background-color:#f9f9f9;padding:5px}div.floatright{float:right;clear:right;position:relative;margin:.5em 0 .8em 1.4em}div.floatright p{font-style:italic}div.floatleft{float:left;clear:left;position:relative;margin:.5em 1.4em .8em 0}div.floatleft p{font-style:italic}div.center{text-align:center}div.thumb{border:none;width:auto;margin-top:.5em;margin-bottom:.8em;background-color:transparent}div.thumbinner{border:1px solid #ccc;padding:3px!important;background-color:White;font-size:94%;text-align:center;overflow:hidden}html .thumbimage{border:1px solid #ccc}html .thumbcaption{border:none;text-align:left;line-height:1.4em;padding:3px!important;font-size:94%}div.magnify{display:none}div.tright{float:right;clear:right;margin:.5em 0 .8em 1.4em}div.tleft{float:left;clear:left;margin:.5em 1.4em .8em 0}img.thumbborder{border:1px solid #ddd}table.rimage{float:right;width:1pt;position:relative;margin-left:1em;margin-bottom:1em;text-align:center}body{background:white;color:black;margin:0;padding:0}.noprint,div#jump-to-nav,.mw-jump,div.top,div#column-one,#colophon,.editsection,.toctoggle,.tochidden,div#f-poweredbyico,div#f-copyrightico,li#viewcount,li#about,li#disclaimer,li#mobileview,li#privacy,#footer-places,.mw-hidden-catlinks,tr.mw-metadata-show-hide-extended,span.mw-filepage-other-resolutions,#filetoc{display:none}ul{list-style-type:square}#content{background:none;border:none!important;padding:0!important;margin:0!important;direction:ltr}#footer{background:white;color:black;margin-top:1em;border-top:1px solid #AAA;direction:ltr}h1,h2,h3,h4,h5,h6{font-weight:bold}p{margin:1em 0;line-height:1.2em}pre{border:1pt dashed black;white-space:pre;font-size:8pt;overflow:auto;padding:1em 0;background:white;color:black}table.listing,table.listing td{border:1pt solid black;border-collapse:collapse}a{color:black!important;background:none!important;padding:0!important}a:link,a:visited{color:#520;background:transparent;text-decoration:underline}#content a.external.text:after,#content a.external.autonumber:after{content:"(" attr(href) ") "}#globalWrapper{width:100%!important;min-width:0!important}#content{background:white;color:black}#column-content{margin:0!important}#column-content #content{padding:1em;margin:0!important}a,a.external,a.new,a.stub{color:black!important;text-decoration:none!important}a,a.external,a.new,a.stub{color:inherit!important;text-decoration:inherit!important}img{border:none;vertical-align:middle}span.texhtml{font-family:serif}#siteNotice{display:none}li.gallerybox{vertical-align:top;border:solid 2px white;display:-moz-inline-box;display:inline-block}ul.gallery,li.gallerybox{zoom:1;*display:inline}ul.gallery{margin:2px;padding:2px;display:block}li.gallerycaption{font-weight:bold;text-align:center;display:block;word-wrap:break-word}li.gallerybox div.thumb{text-align:center;border:1px solid #ccc;margin:2px}div.gallerytext{overflow:hidden;font-size:94%;padding:2px 4px;word-wrap:break-word}table.diff{background:white}td.diff-otitle{background:#fff}td.diff-ntitle{background:#fff}td.diff-addedline{background:#cfc;font-size:smaller;border:solid 2px black}td.diff-deletedline{background:#ffa;font-size:smaller;border:dotted 2px black}td.diff-context{background:#eee;font-size:smaller}.diffchange{color:silver;font-weight:bold;text-decoration:underline}table.wikitable,table.mw_metadata{margin:1em 1em 1em 0;border:1px #aaa solid;background:white;border-collapse:collapse}table.wikitable>tr>th,table.wikitable>tr>td,table.wikitable>*>tr>th,table.wikitable>*>tr>td,.mw_metadata th,.mw_metadata td{border:1px #aaa solid;padding:.2em}table.wikitable>tr>th,table.wikitable>*>tr>th,.mw_metadata th{text-align:center;background:white;font-weight:bold}table.wikitable>caption,.mw_metadata caption{font-weight:bold}a.sortheader{margin:0 .3em}.wikitable,.thumb,img{page-break-inside:avoid}h2,h3,h4,h5,h6,h7{page-break-after:avoid}p{widows:3;orphans:3}.catlinks ul{display:inline;margin:0;padding:0;list-style:none;list-style-type:none;list-style-image:none;vertical-align:middle!ie}.catlinks li{display:inline-block;line-height:1.15em;padding:0 .4em;border-left:1px solid #AAA;margin:.1em 0;zoom:1;display:inline!ie}.catlinks li:first-child{padding-left:.2em;border-left:none}dfn{font-style:inherit}sup,sub{line-height:1em}#interwiki-completelist{font-weight:bold}body.page-Main_Page #ca-delete{display:none!important}body.page-Main_Page #mp-topbanner{clear:both}#toolbar{height:22px;margin-bottom:6px}body.action-info :target{background:#DEF}ol.references,div.reflist,div.refbegin{font-size:90%;margin-bottom:.5em}div.refbegin-100{font-size:100%}div.reflist ol.references{font-size:100%;list-style-type:inherit}div.columns{margin-top:.3em}div.columns dl,div.columns ol,div.columns ul{margin-top:0}div.columns li,div.columns dd dd{-webkit-column-break-inside:avoid;page-break-inside:avoid;break-inside:avoid-column}ol.references li:target,sup.reference:target,span.citation:target{background-color:#DEF}sup.reference{font-weight:normal;font-style:normal}span.brokenref{display:none}.citation{word-wrap:break-word}@media screen,handheld{.citation *.printonly{display:none}}.flowlist ul{overflow-x:hidden;margin-left:0;padding-left:1.6em}.flowlist ol{overflow-x:hidden;margin-left:0;padding-left:3.2em}.flowlist dl{overflow-x:hidden}.hlist dl,.hlist ol,.hlist ul{margin:0;padding:0}.hlist dd,.hlist dt,.hlist li{margin:0;display:inline}.hlist dl dl,.hlist dl ol,.hlist dl ul,.hlist ol dl,.hlist ol ol,.hlist ol ul,.hlist ul dl,.hlist ul ol,.hlist ul ul{display:inline}.hlist dt:after{content:":"}.hlist dd:after,.hlist li:after{content:" · ";font-weight:bold}.hlist dd:last-child:after,.hlist dt:last-child:after,.hlist li:last-child:after{content:none}.hlist dd.hlist-last-child:after,.hlist dt.hlist-last-child:after,.hlist li.hlist-last-child:after{content:none}.hlist dd dd:first-child:before,.hlist dd dt:first-child:before,.hlist dd li:first-child:before,.hlist dt dd:first-child:before,.hlist dt dt:first-child:before,.hlist dt li:first-child:before,.hlist li dd:first-child:before,.hlist li dt:first-child:before,.hlist li li:first-child:before{content:"(";font-weight:normal}.hlist dd dd:last-child:after,.hlist dd dt:last-child:after,.hlist dd li:last-child:after,.hlist dt dd:last-child:after,.hlist dt dt:last-child:after,.hlist dt li:last-child:after,.hlist li dd:last-child:after,.hlist li dt:last-child:after,.hlist li li:last-child:after{content:") ";font-weight:normal}.hlist dd dd.hlist-last-child:after,.hlist dd dt.hlist-last-child:after,.hlist dd li.hlist-last-child:after,.hlist dt dd.hlist-last-child:after,.hlist dt dt.hlist-last-child:after,.hlist dt li.hlist-last-child:after,.hlist li dd.hlist-last-child:after,.hlist li dt.hlist-last-child:after,.hlist li li.hlist-last-child:after{content:") ";font-weight:normal}.hlist ol{counter-reset:listitem}.hlist ol>li{counter-increment:listitem}.hlist ol>li:before{content:" " counter(listitem) " "}.hlist dd ol>li:first-child:before,.hlist dt ol>li:first-child:before,.hlist li ol>li:first-child:before{content:"(" counter(listitem) " "}.plainlist ul{line-height:inherit;list-style:none none;margin:0}.plainlist ul li{margin-bottom:0}.navbox{border:1px solid #aaa;width:100%;margin:auto;clear:both;font-size:88%;text-align:center;padding:1px}.navbox-inner,.navbox-subgroup{width:100%}.navbox-group,.navbox-title,.navbox-abovebelow{padding:.25em 1em;line-height:1.5em;text-align:center}th.navbox-group{white-space:nowrap;text-align:right}.navbox,.navbox-subgroup{background:#fdfdfd}.navbox-list{line-height:1.8em;border-color:#fdfdfd}.navbox th,.navbox-title{background:#ccf}.navbox-abovebelow,th.navbox-group,.navbox-subgroup .navbox-title{background:#ddf}.navbox-subgroup .navbox-group,.navbox-subgroup .navbox-abovebelow{background:#e6e6ff}.navbox-even{background:#f7f7f7}.navbox-odd{background:transparent}table.navbox+table.navbox{margin-top:-1px}.navbox .hlist td dl,.navbox .hlist td ol,.navbox .hlist td ul,.navbox td.hlist dl,.navbox td.hlist ol,.navbox td.hlist ul{padding:.125em 0}ol+table.navbox,ul+table.navbox{margin-top:.5em}.navbar{display:inline;font-size:88%;font-weight:normal}.navbar ul{display:inline;white-space:nowrap}.navbar li{word-spacing:-0.125em}.navbar.mini li span{font-variant:small-caps}.infobox .navbar{font-size:100%}.navbox .navbar{display:block;font-size:100%}.navbox-title .navbar{float:left;text-align:left;margin-right:.5em;width:6em}.collapseButton{float:right;font-weight:normal;margin-left:.5em;text-align:right;width:auto}.navbox .collapseButton{width:6em}.mw-collapsible-toggle{font-weight:normal;text-align:right}.navbox .mw-collapsible-toggle{width:6em}.infobox{border:1px solid #aaa;background-color:#f9f9f9;color:black;margin:.5em 0 .5em 1em;padding:.2em;float:right;clear:right;text-align:left;font-size:88%;line-height:1.5em}.infobox caption{font-size:125%;font-weight:bold}.infobox td,.infobox th{vertical-align:top}.infobox.bordered{border-collapse:collapse}.infobox.bordered td,.infobox.bordered th{border:1px solid #aaa}.infobox.bordered .borderless td,.infobox.bordered .borderless th{border:0}.infobox.sisterproject{width:20em;font-size:90%}.infobox.standard-talk{border:1px solid #c0c090;background-color:#f8eaba}.infobox.standard-talk.bordered td,.infobox.standard-talk.bordered th{border:1px solid #c0c090}.infobox.bordered .mergedtoprow td,.infobox.bordered .mergedtoprow th{border:0;border-top:1px solid #aaa;border-right:1px solid #aaa}.infobox.bordered .mergedrow td,.infobox.bordered .mergedrow th{border:0;border-right:1px solid #aaa}.infobox.geography{border-collapse:collapse;line-height:1.2em;font-size:90%}.infobox.geography td,.infobox.geography th{border-top:1px solid #aaa;padding:.4em .6em .4em .6em}.infobox.geography .mergedtoprow td,.infobox.geography .mergedtoprow th{border-top:1px solid #aaa;padding:.4em .6em .2em .6em}.infobox.geography .mergedrow td,.infobox.geography .mergedrow th{border:0;padding:0 .6em .2em .6em}.infobox.geography .mergedbottomrow td,.infobox.geography .mergedbottomrow th{border-top:0;border-bottom:1px solid #aaa;padding:0 .6em .4em .6em}.infobox.geography .maptable td,.infobox.geography .maptable th{border:0;padding:0}.wikitable.plainrowheaders th[scope=row]{font-weight:normal;text-align:left}.wikitable td ul,.wikitable td ol,.wikitable td dl{text-align:left}.wikitable.hlist td ul,.wikitable.hlist td ol,.wikitable.hlist td dl{text-align:inherit}div.listenlist{background:url("//upload.wikimedia.org/wikipedia/commons/4/47/Sound-icon.svg") no-repeat scroll 0 0 transparent;background-size:30px;padding-left:40px}table.mw-hiero-table td{vertical-align:middle}div.medialist{min-height:50px;margin:1em;background-position:top left;background-repeat:no-repeat}div.medialist ul{list-style-type:none;list-style-image:none;margin:0}div.medialist ul li{padding-bottom:.5em}div.medialist ul li li{font-size:91%;padding-bottom:0}div#content a[href$=".pdf"].external,div#content a[href*=".pdf?"].external,div#content a[href*=".pdf#"].external,div#content a[href$=".PDF"].external,div#content a[href*=".PDF?"].external,div#content a[href*=".PDF#"].external,div#mw_content a[href$=".pdf"].external,div#mw_content a[href*=".pdf?"].external,div#mw_content a[href*=".pdf#"].external,div#mw_content a[href$=".PDF"].external,div#mw_content a[href*=".PDF?"].external,div#mw_content a[href*=".PDF#"].external{background:url("//upload.wikimedia.org/wikipedia/commons/2/23/Icons-mini-file_acrobat.gif") no-repeat right;padding-right:18px}div#content span.PDFlink a,div#mw_content span.PDFlink a{background:url("//upload.wikimedia.org/wikipedia/commons/2/23/Icons-mini-file_acrobat.gif") no-repeat right;padding-right:18px}div.columns-2 div.column{float:left;width:50%;min-width:300px}div.columns-3 div.column{float:left;width:33.3%;min-width:200px}div.columns-4 div.column{float:left;width:25%;min-width:150px}div.columns-5 div.column{float:left;width:20%;min-width:120px}.messagebox{border:1px solid #aaa;background-color:#f9f9f9;width:80%;margin:0 auto 1em auto;padding:.2em}.messagebox.merge{border:1px solid #c0b8cc;background-color:#f0e5ff;text-align:center}.messagebox.cleanup{border:1px solid #9f9fff;background-color:#efefff;text-align:center}.messagebox.standard-talk{border:1px solid #c0c090;background-color:#f8eaba;margin:4px auto}.mbox-inside .standard-talk,.messagebox.nested-talk{border:1px solid #c0c090;background-color:#f8eaba;width:100%;margin:2px 0;padding:2px}.messagebox.small{width:238px;font-size:85%;float:right;clear:both;margin:0 0 1em 1em;line-height:1.25em}.messagebox.small-talk{width:238px;font-size:85%;float:right;clear:both;margin:0 0 1em 1em;line-height:1.25em;background:#F8EABA}th.mbox-text,td.mbox-text{border:none;padding:.25em .9em;width:100%}td.mbox-image{border:none;padding:2px 0 2px .9em;text-align:center}td.mbox-imageright{border:none;padding:2px .9em 2px 0;text-align:center}td.mbox-empty-cell{border:none;padding:0;width:1px}table.ambox{margin:0 10%;border:1px solid #aaa;border-left:10px solid #1e90ff;background:#fbfbfb}table.ambox+table.ambox{margin-top:-1px}.ambox th.mbox-text,.ambox td.mbox-text{padding:.25em .5em}.ambox td.mbox-image{padding:2px 0 2px .5em}.ambox td.mbox-imageright{padding:2px .5em 2px 0}table.ambox-notice{border-left:10px solid #1e90ff}table.ambox-speedy{border-left:10px solid #b22222;background:#fee}table.ambox-delete{border-left:10px solid #b22222}table.ambox-content{border-left:10px solid #f28500}table.ambox-style{border-left:10px solid #f4c430}table.ambox-move{border-left:10px solid #9932cc}table.ambox-protection{border-left:10px solid #bba}table.imbox{margin:4px 10%;border-collapse:collapse;border:3px solid #1e90ff;background:#fbfbfb}.imbox .mbox-text .imbox{margin:0 -0.5em;display:block}.mbox-inside .imbox{margin:4px}table.imbox-notice{border:3px solid #1e90ff}table.imbox-speedy{border:3px solid #b22222;background:#fee}table.imbox-delete{border:3px solid #b22222}table.imbox-content{border:3px solid #f28500}table.imbox-style{border:3px solid #f4c430}table.imbox-move{border:3px solid #9932cc}table.imbox-protection{border:3px solid #bba}table.imbox-license{border:3px solid #88a;background:#f7f8ff}table.imbox-featured{border:3px solid #cba135}table.cmbox{margin:3px 10%;border-collapse:collapse;border:1px solid #aaa;background:#DFE8FF}table.cmbox-notice{background:#D8E8FF}table.cmbox-speedy{margin-top:4px;margin-bottom:4px;border:4px solid #b22222;background:#FFDBDB}table.cmbox-delete{background:#FFDBDB}table.cmbox-content{background:#FFE7CE}table.cmbox-style{background:#FFF9DB}table.cmbox-move{background:#E4D8FF}table.cmbox-protection{background:#EFEFE1}table.ombox{margin:4px 10%;border-collapse:collapse;border:1px solid #aaa;background:#f9f9f9}table.ombox-notice{border:1px solid #aaa}table.ombox-speedy{border:2px solid #b22222;background:#fee}table.ombox-delete{border:2px solid #b22222}table.ombox-content{border:1px solid #f28500}table.ombox-style{border:1px solid #f4c430}table.ombox-move{border:1px solid #9932cc}table.ombox-protection{border:2px solid #bba}table.tmbox{margin:4px 10%;border-collapse:collapse;border:1px solid #c0c090;background:#f8eaba}.mediawiki .mbox-inside .tmbox{margin:2px 0;width:100%}.mbox-inside .tmbox.mbox-small{line-height:1.5em;font-size:100%}table.tmbox-speedy{border:2px solid #b22222;background:#fee}table.tmbox-delete{border:2px solid #b22222}table.tmbox-content{border:2px solid #f28500}table.tmbox-style{border:2px solid #f4c430}table.tmbox-move{border:2px solid #9932cc}table.tmbox-protection,table.tmbox-notice{border:1px solid #c0c090}table.dmbox{clear:both;margin:.9em 1em;border-top:1px solid #ccc;border-bottom:1px solid #ccc;background:transparent}table.fmbox{clear:both;margin:.2em 0;width:100%;border:1px solid #aaa;background:#f9f9f9}table.fmbox-system{background:#f9f9f9}table.fmbox-warning{border:1px solid #bb7070;background:#ffdbdb}table.fmbox-editnotice{background:transparent}div.mw-warning-with-logexcerpt,div.mw-lag-warn-high,div.mw-cascadeprotectedwarning,div#mw-protect-cascadeon{clear:both;margin:.2em 0;border:1px solid #bb7070;background:#ffdbdb;padding:.25em .9em}div.mw-lag-warn-normal,div.fmbox-system{clear:both;margin:.2em 0;border:1px solid #aaa;background:#f9f9f9;padding:.25em .9em}body.mediawiki table.mbox-small{clear:right;float:right;margin:4px 0 4px 1em;width:238px;font-size:88%;line-height:1.25em}body.mediawiki table.mbox-small-left{margin:4px 1em 4px 0;width:238px;border-collapse:collapse;font-size:88%;line-height:1.25em}.compact-ambox table .mbox-image,.compact-ambox table .mbox-imageright,.compact-ambox table .mbox-empty-cell{display:none}.compact-ambox table.ambox{border:none;border-collapse:collapse;background:transparent;margin:0 0 0 1.6em!important;padding:0!important;width:auto;display:block}body.mediawiki .compact-ambox table.mbox-small-left{font-size:100%;width:auto;margin:0}.compact-ambox table .mbox-text{padding:0!important;margin:0!important}.compact-ambox table .mbox-text-span{display:list-item;line-height:1.5em;list-style-type:square;list-style-image:url(//bits.wikimedia.org/skins/common/images/bullet.gif)}.skin-vector .compact-ambox table .mbox-text-span{list-style-type:circle;list-style-image:url(//bits.wikimedia.org/skins/vector/images/bullet-icon.png)}.compact-ambox .hide-when-compact{display:none}div.noarticletext{border:none;background:transparent;padding:0}.visualhide{position:absolute;left:-10000px;top:auto;width:1px;height:1px;overflow:hidden}#wpSave{font-weight:bold}.hiddenStructure{display:inline!important;color:#f00;background-color:#0f0}.check-icon a.new{display:none;speak:none}.nounderlines a,.IPA a:link,.IPA a:visited{text-decoration:none!important}div.NavFrame{margin:0;padding:4px;border:1px solid #aaa;text-align:center;border-collapse:collapse;font-size:95%}div.NavFrame+div.NavFrame{border-top-style:none;border-top-style:hidden}div.NavPic{background-color:#fff;margin:0;padding:2px;float:left}div.NavFrame div.NavHead{height:1.6em;font-weight:bold;background-color:#ccf;position:relative}div.NavFrame p,div.NavFrame div.NavContent,div.NavFrame div.NavContent p{font-size:100%}div.NavEnd{margin:0;padding:0;line-height:1px;clear:both}a.NavToggle{position:absolute;top:0;right:3px;font-weight:normal;font-size:90%}.rellink,.dablink{font-style:italic;padding-left:1.6em;margin-bottom:.5em}.rellink i,.dablink i{font-style:normal}.listify td{display:list-item}.listify tr{display:block}.listify table{display:block}.geo-default,.geo-dms,.geo-dec{display:inline}.geo-nondefault,.geo-multi-punct{display:none}.longitude,.latitude{white-space:nowrap}.nonumtoc .tocnumber{display:none}.nonumtoc #toc ul,.nonumtoc .toc ul{line-height:1.5em;list-style:none none;margin:.3em 0 0;padding:0}.nonumtoc #toc ul ul,.nonumtoc .toc ul ul{margin:0 0 0 2em}.toclimit-2 .toclevel-1 ul,.toclimit-3 .toclevel-2 ul,.toclimit-4 .toclevel-3 ul,.toclimit-5 .toclevel-4 ul,.toclimit-6 .toclevel-5 ul,.toclimit-7 .toclevel-6 ul{display:none}blockquote.templatequote{margin-top:0}blockquote.templatequote div.templatequotecite{line-height:1em;text-align:left;padding-left:2em;margin-top:0}blockquote.templatequote div.templatequotecite cite{font-size:85%}div.user-block{padding:5px;margin-bottom:.5em;border:1px solid #A9A9A9;background-color:#FFEFD5}.nowrap,.nowraplinks a,.nowraplinks .selflink,sup.reference a{white-space:nowrap}.wrap,.wraplinks a{white-space:normal}.template-documentation{clear:both;margin:1em 0 0 0;border:1px solid #aaa;background-color:#ecfcf4;padding:1em}.imagemap-inline div{display:inline}#wpUploadDescription{height:13em}.thumbinner{min-width:100px}div.thumb .thumbimage{background-color:#fff}div#content .gallerybox div.thumb{background-color:#F9F9F9}.gallerybox .thumb img{background:#fff url(//bits.wikimedia.org/skins/common/images/Checker-16x16.png) repeat}.ns-0 .gallerybox .thumb img,.ns-2 .gallerybox .thumb img,.ns-100 .gallerybox .thumb img,.nochecker .gallerybox .thumb img{background:#fff}#mw-subcategories,#mw-pages,#mw-category-media,#filehistory,#wikiPreview,#wikiDiff{clear:both}body.rtl #mw-articlefeedbackv5,body.rtl #mw-articlefeedback{display:block;margin-bottom:1em;clear:right;float:right}.wpb .wpb-header{display:none}.wpbs-inner .wpb .wpb-header{display:block}.wpbs-inner .wpb .wpb-header{display:table-row}.wpbs-inner .wpb-outside{display:none}.mw-tag-markers{font-family:sans-serif;font-style:italic;font-size:90%}.sysop-show,.accountcreator-show,.templateeditor-show,.autoconfirmed-show{display:none}.ve-init-mw-viewPageTarget-toolbar-editNotices-notice .editnotice-redlink{display:none!important}ul.permissions-errors>li{list-style:none none}ul.permissions-errors{margin:0}body.page-Special_UserLogin .mw-label label,body.page-Special_UserLogin_signup .mw-label label{white-space:nowrap}.transborder{border:solid transparent}* html .transborder{border:solid #000001;filter:chroma(color=#000001)}.updatedmarker{background-color:transparent;color:#006400}li.mw-changeslist-line-watched .mw-title,table.mw-changeslist-line-watched .mw-title,table.mw-enhanced-watch .mw-enhanced-rctime{font-weight:normal}span.texhtml{font-family:"Times New Roman","Nimbus Roman No9 L",Times,serif;font-size:118%;white-space:nowrap}span.texhtml span.texhtml{font-size:100%}div.mw-geshi div,div.mw-geshi div pre,span.mw-geshi,pre.source-css,pre.source-javascript,pre.source-lua{font-family:monospace,Courier!important}table#mw-prefixindex-list-table,table#mw-prefixindex-nav-table{width:98%}.portal-column-left{float:left;width:50%}.portal-column-right{float:right;width:49%}.portal-column-left-wide{float:left;width:60%}.portal-column-right-narrow{float:right;width:39%}.portal-column-left-extra-wide{float:left;width:70%}.portal-column-right-extra-narrow{float:right;width:29%}@media only screen and (max-width:800px){.portal-column-left,.portal-column-right,.portal-column-left-wide,.portal-column-right-narrow,.portal-column-left-extra-wide,.portal-column-right-extra-narrow{float:inherit;width:inherit}}#bodyContent .letterhead{background-image:url('//upload.wikimedia.org/wikipedia/commons/e/e0/Tan-page-corner.png');background-repeat:no-repeat;padding:2em;background-color:#faf9f2}.treeview ul{padding:0;margin:0}.treeview li{padding:0;margin:0;list-style-type:none;list-style-image:none;zoom:1}.treeview li li{background:url("//upload.wikimedia.org/wikipedia/commons/f/f2/Treeview-grey-line.png") no-repeat 0 -2981px;padding-left:20px;text-indent:.3em}.treeview li li.lastline{background-position:0 -5971px}.treeview li.emptyline>ul{margin-left:-1px}.treeview li.emptyline>ul>li:first-child{background-position:0 9px}td .sortkey,th .sortkey{display:none;speak:none}.inputbox-hidecheckboxes form .inputbox-element{display:none!important}#editpage-specialchars{display:none}.k-player .k-attribution{visibility:hidden}@media(-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(min-resolution:1.5dppx),(min-resolution:144dpi){#p-logo a{background-image:url("//upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Wikipedia-logo-v2-en.svg/204px-Wikipedia-logo-v2-en.svg.png")!important;background-size:136px auto}}@media(-webkit-min-device-pixel-ratio:2),(min--moz-device-pixel-ratio:2),(min-resolution:2dppx),(min-resolution:192dpi){#p-logo a{background-image:url("//upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Wikipedia-logo-v2-en.svg/270px-Wikipedia-logo-v2-en.svg.png")!important;background-size:135px auto}}.ns-0 .ambox,.ns-0 .navbox,.ns-0 .vertical-navbox,.ns-0 .infobox.sisterproject,.ns-0 .dablink,.ns-0 .metadata,.editlink,.navbar,a.NavToggle,span.collapseButton,span.mw-collapsible-toggle,th .sortkey,td .sortkey{display:none!important}#content cite a.external.text:after,.nourlexpansion a.external.text:after,.nourlexpansion a.external.autonumber:after{display:none!important}table.collapsible tr,div.NavPic,div.NavContent{display:block!important}table.collapsible tr{display:table-row!important}#firstHeading{margin:0}#content a.external.text:after,#content a.external.autonumber:after{word-wrap:break-word}body.page-Main_Page #deleteconfirm,body.page-Main_Page #t-cite,body.page-Main_Page #footer-info-lastmod,body.action-view.page-Main_Page #siteSub,body.action-view.page-Main_Page #contentSub,body.action-view.page-Main_Page h1.firstHeading{display:none!important}body.page-Main_Page #mp-topbanner{margin-top:0!important}#coordinates{position:absolute;top:0;right:0;float:right;margin:0;padding:0;line-height:1.5em;text-align:right;text-indent:0;font-size:85%;text-transform:none;white-space:nowrap}div.topicon{position:absolute;top:-2em;margin-right:-10px;display:block!important}div.flaggedrevs_short{position:absolute;top:-3em;right:80px;z-index:1;margin-left:0;margin-right:-10px}body.rtl #protected-icon{left:55px}body.rtl #spoken-icon,body.rtl #commons-icon{left:30px}body.rtl #featured-star{left:10px}div.vectorMenu div{z-index:2}#siteSub{display:inline;font-size:92%}li.GA{list-style-image:url(//upload.wikimedia.org/wikipedia/commons/4/42/Monobook-bullet-ga.png)}li.FA{list-style-image:url(//upload.wikimedia.org/wikipedia/commons/d/d4/Monobook-bullet-star.png)}li.mw-changeslist-line-watched,li.mw-history-line-updated{list-style-image:url(//upload.wikimedia.org/wikipedia/commons/c/c2/ChangedBulletVector.png)}#bodyContent a.external[href ^="https://"],.link-https{background:url(//upload.wikimedia.org/wikipedia/en/0/00/Lock_icon_blue.gif) center right no-repeat;padding-right:16px}div.redirectMsg img{vertical-align:text-bottom}.redirectText{font-size:150%;margin:5px} \ No newline at end of file
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/write.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/write.py
new file mode 100644
index 00000000000..939e11d5910
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/bench/write.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+r"""
+=========================
+ Write benchmark results
+=========================
+
+Write benchmark results.
+
+:Copyright:
+
+ Copyright 2014
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+Usage::
+
+ python -mbench.write [-p plain] [-t table] <pickled
+
+ -p plain Plain file to write to (like docs/BENCHMARKS).
+ -t table Table file to write to (like docs/_userdoc/benchmark.txt).
+
+"""
+if __doc__:
+ __doc__ = __doc__.encode('ascii').decode('unicode_escape')
+__author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
+__docformat__ = "restructuredtext en"
+__license__ = "Apache License, Version 2.0"
+__version__ = "1.0.0"
+
+import os as _os
+import re as _re
+import sys as _sys
+
+
+try:
+ unicode
+except NameError:
+ def uni(v):
+ if hasattr(v, 'decode'):
+ return v.decode('latin-1')
+ return str(v)
+else:
+ def uni(v):
+ if isinstance(v, unicode):
+ return v.encode('utf-8')
+ return str(v)
+
+
+def write_table(filename, results):
+ """
+ Output tabled benchmark results
+
+ :Parameters:
+ `filename` : ``str``
+ Filename to write to
+
+ `results` : ``list``
+ Results
+ """
+ try:
+ next
+ except NameError:
+ next = lambda i: (getattr(i, 'next', None) or i.__next__)()
+ try:
+ cmp
+ except NameError:
+ cmp = lambda a, b: (a > b) - (a < b)
+
+ names = [
+ ('cssmin', 'YUI Port'),
+ ('rcssmin', '|rcssmin|'),
+ ('_rcssmin', r'_\ |rcssmin|'),
+ ]
+ benched_per_table = 2
+
+ results = sorted(results, reverse=True)
+
+ # First we transform our data into a table (list of lists)
+ pythons, widths = [], [0] * (benched_per_table + 1)
+ last_version = None
+ for version, _, result in results:
+ version = uni(version)
+ if not(last_version is None or version.startswith('2.')):
+ continue
+ last_version = version
+
+ namesub = _re.compile(r'(?:-\d+(?:\.\d+)*)?\.css$').sub
+ result = iter(result)
+ tables = []
+
+ # given our data it's easier to create the table transposed...
+ for benched in result:
+ rows = [['Name'] + [desc for _, desc in names]]
+ for _ in range(benched_per_table):
+ if _:
+ try:
+ benched = next(result)
+ except StopIteration:
+ rows.append([''] + ['' for _ in names])
+ continue
+
+ times = dict((
+ uni(port), (time, benched['sizes'][idx])
+ ) for idx, (port, time) in enumerate(benched['times']))
+ columns = ['%s (%.1f)' % (
+ namesub('', _os.path.basename(uni(benched['filename']))),
+ benched['size'] / 1024.0,
+ )]
+ for idx, (port, _) in enumerate(names):
+ if port not in times:
+ columns.append('n/a')
+ continue
+ time, size = times[port]
+ if time is None:
+ columns.append('(failed)')
+ continue
+ columns.append('%s%.2f ms (%.1f %s)' % (
+ idx == 0 and ' ' or '',
+ time,
+ size / 1024.0,
+ idx == 0 and '\\*' or ['=', '>', '<'][
+ cmp(size, benched['sizes'][0])
+ ],
+ ))
+ rows.append(columns)
+
+ # calculate column widths (global for all tables)
+ for idx, row in enumerate(rows):
+ widths[idx] = max(widths[idx], max(map(len, row)))
+
+ # ... and transpose it back.
+ tables.append(zip(*rows))
+ pythons.append((version, tables))
+
+ if last_version.startswith('2.'):
+ break
+
+ # Second we create a rest table from it
+ lines = []
+ separator = lambda c='-': '+'.join([''] + [
+ c * (width + 2) for width in widths
+ ] + [''])
+
+ for idx, (version, tables) in enumerate(pythons):
+ if idx:
+ lines.append('')
+ lines.append('')
+
+ line = 'Python %s' % (version,)
+ lines.append(line)
+ lines.append('~' * len(line))
+
+ for table in tables:
+ lines.append('')
+ lines.append('.. rst-class:: benchmark')
+ lines.append('')
+
+ for idx, row in enumerate(table):
+ if idx == 0:
+ # header
+ lines.append(separator())
+ lines.append('|'.join([''] + [
+ ' %s%*s ' % (col, len(col) - width, '')
+ for width, col in zip(widths, row)
+ ] + ['']))
+ lines.append(separator('='))
+ else: # data
+ lines.append('|'.join([''] + [
+ j == 0 and (
+ ' %s%*s ' % (col, len(col) - widths[j], '')
+ ) or (
+ ['%*s ', ' %*s '][idx == 1] % (widths[j], col)
+ )
+ for j, col in enumerate(row)
+ ] + ['']))
+ lines.append(separator())
+
+ fplines = []
+ fp = open(filename)
+ try:
+ fpiter = iter(fp)
+ for line in fpiter:
+ line = line.rstrip()
+ if line == '.. begin tables':
+ buf = []
+ for line in fpiter:
+ line = line.rstrip()
+ if line == '.. end tables':
+ fplines.append('.. begin tables')
+ fplines.append('')
+ fplines.extend(lines)
+ fplines.append('')
+ fplines.append('.. end tables')
+ buf = []
+ break
+ else:
+ buf.append(line)
+ else:
+ fplines.extend(buf)
+ _sys.stderr.write("Placeholder container not found!\n")
+ else:
+ fplines.append(line)
+ finally:
+ fp.close()
+
+ fp = open(filename, 'w')
+ try:
+ fp.write('\n'.join(fplines) + '\n')
+ finally:
+ fp.close()
+
+
+def write_plain(filename, results):
+ """
+ Output plain benchmark results
+
+ :Parameters:
+ `filename` : ``str``
+ Filename to write to
+
+ `results` : ``list``
+ Results
+ """
+ lines = []
+ results = sorted(results, reverse=True)
+ for idx, (version, import_notes, result) in enumerate(results):
+ if idx:
+ lines.append('')
+ lines.append('')
+
+ lines.append('$ python%s -OO bench/main.py bench/*.css' % (
+ '.'.join(version.split('.')[:2])
+ ))
+ lines.append('~' * 72)
+ for note in import_notes:
+ lines.append(uni(note))
+ lines.append('Python Release: %s' % (version,))
+
+ for single in result:
+ lines.append('')
+ lines.append('Benchmarking %r... (%.1f KiB)' % (
+ uni(single['filename']), single['size'] / 1024.0
+ ))
+ for msg in single['messages']:
+ lines.append(msg)
+ times = []
+ space = max([len(uni(port)) for port, _ in single['times']])
+ for idx, (port, time) in enumerate(single['times']):
+ port = uni(port)
+ if time is None:
+ lines.append(" FAILED %s" % (port,))
+ else:
+ times.append(time)
+ lines.append(
+ " Timing %s%s ... (%5.1f KiB %s) %8.2f ms" % (
+ port,
+ " " * (space - len(port)),
+ single['sizes'][idx] / 1024.0,
+ idx == 0 and '*' or ['=', '>', '<'][
+ cmp(single['sizes'][idx], single['sizes'][0])
+ ],
+ time
+ )
+ )
+ if len(times) > 1:
+ lines[-1] += " (factor: %s)" % (', '.join([
+ '%.2f' % (timed / time) for timed in times[:-1]
+ ]))
+
+ lines.append('')
+ lines.append('')
+ lines.append('# vim: nowrap')
+ fp = open(filename, 'w')
+ try:
+ fp.write('\n'.join(lines) + '\n')
+ finally:
+ fp.close()
+
+
+def main(argv=None):
+ """ Main """
+ import getopt as _getopt
+ import pickle as _pickle
+
+ if argv is None:
+ argv = _sys.argv[1:]
+ try:
+ opts, args = _getopt.getopt(argv, "hp:t:", ["help"])
+ except getopt.GetoptError:
+ e = _sys.exc_info()[0](_sys.exc_info()[1])
+ print >> _sys.stderr, "%s\nTry %s -mbench.write --help" % (
+ e,
+ _os.path.basename(_sys.executable),
+ )
+ _sys.exit(2)
+
+ plain, table = None, None
+ for key, value in opts:
+ if key in ("-h", "--help"):
+ print >> _sys.stderr, (
+ "%s -mbench.write [-p plain] [-t table] <pickled" % (
+ _os.path.basename(_sys.executable),
+ )
+ )
+ _sys.exit(0)
+ elif key == '-p':
+ plain = str(value)
+ elif key == '-t':
+ table = str(value)
+
+ struct = []
+ _sys.stdin = getattr(_sys.stdin, 'detach', lambda: _sys.stdin)()
+ try:
+ while True:
+ version, import_notes, result = _pickle.load(_sys.stdin)
+ if hasattr(version, 'decode'):
+ version = version.decode('latin-1')
+ struct.append((version, import_notes, result))
+ except EOFError:
+ pass
+
+ if plain:
+ write_plain(plain, struct)
+
+ if table:
+ write_table(table, struct)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/BENCHMARKS b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/BENCHMARKS
new file mode 100644
index 00000000000..9a49e9b51bf
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/BENCHMARKS
@@ -0,0 +1,61 @@
+$ python3.4 -OO bench/main.py bench/*.css
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python Release: 3.4.2
+
+Benchmarking 'bench/wikipedia.css'... (81.0 KiB)
+ Timing cssmin ... ( 49.4 KiB *) 163.11 ms
+ Timing rcssmin ... ( 49.6 KiB >) 45.48 ms (factor: 3.59)
+ Timing _rcssmin ... ( 49.6 KiB >) 0.43 ms (factor: 378.93, 105.66)
+
+Benchmarking 'bench/wikipedia.min.css'... (49.4 KiB)
+ Timing cssmin ... ( 49.4 KiB *) 119.00 ms
+ Timing rcssmin ... ( 49.4 KiB =) 20.94 ms (factor: 5.68)
+ Timing _rcssmin ... ( 49.4 KiB =) 0.26 ms (factor: 454.45, 79.98)
+
+
+$ python3.3 -OO bench/main.py bench/*.css
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python Release: 3.3.5
+
+Benchmarking 'bench/wikipedia.css'... (81.0 KiB)
+ Timing cssmin ... ( 49.4 KiB *) 185.01 ms
+ Timing rcssmin ... ( 49.6 KiB >) 59.30 ms (factor: 3.12)
+ Timing _rcssmin ... ( 49.6 KiB >) 0.52 ms (factor: 356.38, 114.23)
+
+Benchmarking 'bench/wikipedia.min.css'... (49.4 KiB)
+ Timing cssmin ... ( 49.4 KiB *) 136.26 ms
+ Timing rcssmin ... ( 49.4 KiB =) 25.51 ms (factor: 5.34)
+ Timing _rcssmin ... ( 49.4 KiB =) 0.26 ms (factor: 515.24, 96.47)
+
+
+$ python3.2 -OO bench/main.py bench/*.css
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python Release: 3.2.5
+
+Benchmarking 'bench/wikipedia.css'... (81.0 KiB)
+ Timing cssmin ... ( 49.4 KiB *) 225.32 ms
+ Timing rcssmin ... ( 49.6 KiB >) 57.51 ms (factor: 3.92)
+ Timing _rcssmin ... ( 49.6 KiB >) 0.43 ms (factor: 527.98, 134.77)
+
+Benchmarking 'bench/wikipedia.min.css'... (49.4 KiB)
+ Timing cssmin ... ( 49.4 KiB *) 129.43 ms
+ Timing rcssmin ... ( 49.4 KiB =) 24.45 ms (factor: 5.29)
+ Timing _rcssmin ... ( 49.4 KiB =) 0.25 ms (factor: 526.94, 99.55)
+
+
+$ python2.7 -OO bench/main.py bench/*.css
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python Release: 2.7.7
+
+Benchmarking 'bench/wikipedia.css'... (81.0 KiB)
+ Timing cssmin ... ( 49.4 KiB *) 175.98 ms
+ Timing rcssmin ... ( 49.6 KiB >) 46.22 ms (factor: 3.81)
+ Timing _rcssmin ... ( 49.6 KiB >) 0.45 ms (factor: 390.95, 102.68)
+
+Benchmarking 'bench/wikipedia.min.css'... (49.4 KiB)
+ Timing cssmin ... ( 49.4 KiB *) 126.19 ms
+ Timing rcssmin ... ( 49.4 KiB =) 19.92 ms (factor: 6.33)
+ Timing _rcssmin ... ( 49.4 KiB =) 0.27 ms (factor: 469.78, 74.17)
+
+
+# vim: nowrap
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/CHANGES b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/CHANGES
new file mode 100644
index 00000000000..e179dce99dd
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/CHANGES
@@ -0,0 +1,42 @@
+Changes with version 1.0.5
+
+ *) Added support for pypy 2.2
+
+ *) Updated benchmarks
+
+ *) Relint with newer pylint
+
+ *) Fix locale problem with the setup script on python3.
+ Submitted by https://github.com/svenstaro
+
+
+Changes with version 1.0.4
+
+ *) Documentation and benchmark updates
+
+
+Changes with version 1.0.3
+
+ *) Added support for the following grouping @-rules:
+ @supports, @document, @keyframes
+
+ *) Added support for Python 3.4 and Jython 2.7
+
+
+Changes with version 1.0.2
+
+ *) Added compat option to setup.py supporting the pip installer
+
+ *) Added support for pypy (1.9, 2.0)
+
+ *) Added support for jython (2.5)
+
+
+Changes with version 1.0.1
+
+ *) Added support for Python 3.3
+
+
+Changes with version 1.0.0
+
+ *) First stable release.
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/CLASSIFIERS b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/CLASSIFIERS
new file mode 100644
index 00000000000..10d59650380
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/CLASSIFIERS
@@ -0,0 +1,19 @@
+Development Status :: 5 - Production/Stable
+Environment :: Web Environment
+Intended Audience :: Developers
+License :: OSI Approved
+License :: OSI Approved :: Apache License, Version 2.0
+Operating System :: OS Independent
+Programming Language :: C
+Programming Language :: Python
+Programming Language :: Python :: 2
+Programming Language :: Python :: 3
+Programming Language :: Python :: Implementation :: CPython
+Programming Language :: Python :: Implementation :: Jython
+Programming Language :: Python :: Implementation :: PyPy
+Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Topic :: Software Development :: Libraries
+Topic :: Software Development :: Libraries :: Python Modules
+Topic :: Text Processing
+Topic :: Text Processing :: Filters
+Topic :: Utilities
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/DESCRIPTION b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/DESCRIPTION
new file mode 100644
index 00000000000..b51a7fdb837
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/DESCRIPTION
@@ -0,0 +1,85 @@
+==============
+ CSS Minifier
+==============
+
+RCSSmin is a CSS minifier.
+
+The minifier is based on the semantics of the `YUI compressor`_\, which itself
+is based on `the rule list by Isaac Schlueter`_\.
+
+This module is a re-implementation aiming for speed instead of maximum
+compression, so it can be used at runtime (rather than during a preprocessing
+step). RCSSmin does syntactical compression only (removing spaces, comments
+and possibly semicolons). It does not provide semantic compression (like
+removing empty blocks, collapsing redundant properties etc). It does, however,
+support various CSS hacks (by keeping them working as intended).
+
+Here's a feature list:
+
+- Strings are kept, except that escaped newlines are stripped
+- Space/Comments before the very end or before various characters are
+ stripped: ``:{});=>+],!`` (The colon (``:``) is a special case, a single
+ space is kept if it's outside a ruleset.)
+- Space/Comments at the very beginning or after various characters are
+ stripped: ``{}(=:>+[,!``
+- Optional space after unicode escapes is kept, resp. replaced by a simple
+ space
+- whitespaces inside ``url()`` definitions are stripped
+- Comments starting with an exclamation mark (``!``) can be kept optionally.
+- All other comments and/or whitespace characters are replaced by a single
+ space.
+- Multiple consecutive semicolons are reduced to one
+- The last semicolon within a ruleset is stripped
+- CSS Hacks supported:
+
+ - IE7 hack (``>/**/``)
+ - Mac-IE5 hack (``/*\*/.../**/``)
+ - The boxmodelhack is supported naturally because it relies on valid CSS2
+ strings
+ - Between ``:first-line`` and the following comma or curly brace a space is
+ inserted. (apparently it's needed for IE6)
+ - Same for ``:first-letter``
+
+rcssmin.c is a reimplementation of rcssmin.py in C and improves runtime up to
+factor 100 or so (depending on the input). docs/BENCHMARKS in the source
+distribution contains the details.
+
+Both python 2 (>= 2.4) and python 3 are supported.
+
+.. _YUI compressor: https://github.com/yui/yuicompressor/
+
+.. _the rule list by Isaac Schlueter: https://github.com/isaacs/cssmin/
+
+
+Copyright and License
+~~~~~~~~~~~~~~~~~~~~~
+
+Copyright 2011 - 2014
+André Malo or his licensors, as applicable.
+
+The whole package (except for the files in the bench/ directory) is
+distributed under the Apache License Version 2.0. You'll find a copy in the
+root directory of the distribution or online at:
+<http://www.apache.org/licenses/LICENSE-2.0>.
+
+
+Bugs
+~~~~
+
+No bugs, of course. ;-)
+But if you've found one or have an idea how to improve rcssmin, feel free
+to send a pull request on `github <https://github.com/ndparker/rcssmin>`_
+or send a mail to <rcssmin-bugs@perlig.de>.
+
+
+Author Information
+~~~~~~~~~~~~~~~~~~
+
+André "nd" Malo <nd perlig.de>
+GPG: 0x8103A37E
+
+
+ If God intended people to be naked, they would be born that way.
+ -- Oscar Wilde
+
+.. vim:tw=72 syntax=rest
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/PROVIDES b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/PROVIDES
new file mode 100644
index 00000000000..d6d4e9ebe93
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/PROVIDES
@@ -0,0 +1 @@
+rcssmin (1.0)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/SUMMARY b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/SUMMARY
new file mode 100644
index 00000000000..490e5373442
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/SUMMARY
@@ -0,0 +1 @@
+CSS Minifier
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/api-objects.txt b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/api-objects.txt
new file mode 100644
index 00000000000..f4ed223ee65
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/api-objects.txt
@@ -0,0 +1,6 @@
+rcssmin rcssmin-module.html
+rcssmin.__license__ rcssmin-module.html#__license__
+rcssmin._make_cssmin rcssmin-module.html#_make_cssmin
+rcssmin.__doc__ rcssmin-module.html#__doc__
+rcssmin.__package__ rcssmin-module.html#__package__
+rcssmin.cssmin rcssmin-module.html#cssmin
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/crarr.png b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/crarr.png
new file mode 100644
index 00000000000..26b43c52433
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/crarr.png
Binary files differ
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/epydoc.css b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/epydoc.css
new file mode 100644
index 00000000000..86d41706824
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/epydoc.css
@@ -0,0 +1,322 @@
+
+
+/* Epydoc CSS Stylesheet
+ *
+ * This stylesheet can be used to customize the appearance of epydoc's
+ * HTML output.
+ *
+ */
+
+/* Default Colors & Styles
+ * - Set the default foreground & background color with 'body'; and
+ * link colors with 'a:link' and 'a:visited'.
+ * - Use bold for decision list terms.
+ * - The heading styles defined here are used for headings *within*
+ * docstring descriptions. All headings used by epydoc itself use
+ * either class='epydoc' or class='toc' (CSS styles for both
+ * defined below).
+ */
+body { background: #ffffff; color: #000000; }
+p { margin-top: 0.5em; margin-bottom: 0.5em; }
+a:link { color: #0000ff; }
+a:visited { color: #204080; }
+dt { font-weight: bold; }
+h1 { font-size: +140%; font-style: italic;
+ font-weight: bold; }
+h2 { font-size: +125%; font-style: italic;
+ font-weight: bold; }
+h3 { font-size: +110%; font-style: italic;
+ font-weight: normal; }
+code { font-size: 100%; }
+/* N.B.: class, not pseudoclass */
+a.link { font-family: monospace; }
+
+/* Page Header & Footer
+ * - The standard page header consists of a navigation bar (with
+ * pointers to standard pages such as 'home' and 'trees'); a
+ * breadcrumbs list, which can be used to navigate to containing
+ * classes or modules; options links, to show/hide private
+ * variables and to show/hide frames; and a page title (using
+ * <h1>). The page title may be followed by a link to the
+ * corresponding source code (using 'span.codelink').
+ * - The footer consists of a navigation bar, a timestamp, and a
+ * pointer to epydoc's homepage.
+ */
+h1.epydoc { margin: 0; font-size: +140%; font-weight: bold; }
+h2.epydoc { font-size: +130%; font-weight: bold; }
+h3.epydoc { font-size: +115%; font-weight: bold;
+ margin-top: 0.2em; }
+td h3.epydoc { font-size: +115%; font-weight: bold;
+ margin-bottom: 0; }
+table.navbar { background: #a0c0ff; color: #000000;
+ border: 2px groove #c0d0d0; }
+table.navbar table { color: #000000; }
+th.navbar-select { background: #70b0ff;
+ color: #000000; }
+table.navbar a { text-decoration: none; }
+table.navbar a:link { color: #0000ff; }
+table.navbar a:visited { color: #204080; }
+span.breadcrumbs { font-size: 85%; font-weight: bold; }
+span.options { font-size: 70%; }
+span.codelink { font-size: 85%; }
+td.footer { font-size: 85%; }
+
+/* Table Headers
+ * - Each summary table and details section begins with a 'header'
+ * row. This row contains a section title (marked by
+ * 'span.table-header') as well as a show/hide private link
+ * (marked by 'span.options', defined above).
+ * - Summary tables that contain user-defined groups mark those
+ * groups using 'group header' rows.
+ */
+td.table-header { background: #70b0ff; color: #000000;
+ border: 1px solid #608090; }
+td.table-header table { color: #000000; }
+td.table-header table a:link { color: #0000ff; }
+td.table-header table a:visited { color: #204080; }
+span.table-header { font-size: 120%; font-weight: bold; }
+th.group-header { background: #c0e0f8; color: #000000;
+ text-align: left; font-style: italic;
+ font-size: 115%;
+ border: 1px solid #608090; }
+
+/* Summary Tables (functions, variables, etc)
+ * - Each object is described by a single row of the table with
+ * two cells. The left cell gives the object's type, and is
+ * marked with 'code.summary-type'. The right cell gives the
+ * object's name and a summary description.
+ * - CSS styles for the table's header and group headers are
+ * defined above, under 'Table Headers'
+ */
+table.summary { border-collapse: collapse;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #608090;
+ margin-bottom: 0.5em; }
+td.summary { border: 1px solid #608090; }
+code.summary-type { font-size: 85%; }
+table.summary a:link { color: #0000ff; }
+table.summary a:visited { color: #204080; }
+
+
+/* Details Tables (functions, variables, etc)
+ * - Each object is described in its own div.
+ * - A single-row summary table w/ table-header is used as
+ * a header for each details section (CSS style for table-header
+ * is defined above, under 'Table Headers').
+ */
+table.details { border-collapse: collapse;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #608090;
+ margin: .2em 0 0 0; }
+table.details table { color: #000000; }
+table.details a:link { color: #0000ff; }
+table.details a:visited { color: #204080; }
+
+/* Fields */
+dl.fields { margin-left: 2em; margin-top: 1em;
+ margin-bottom: 1em; }
+dl.fields dd ul { margin-left: 0em; padding-left: 0em; }
+dl.fields dd ul li ul { margin-left: 2em; padding-left: 0em; }
+div.fields { margin-left: 2em; }
+div.fields p { margin-bottom: 0.5em; }
+
+/* Index tables (identifier index, term index, etc)
+ * - link-index is used for indices containing lists of links
+ * (namely, the identifier index & term index).
+ * - index-where is used in link indices for the text indicating
+ * the container/source for each link.
+ * - metadata-index is used for indices containing metadata
+ * extracted from fields (namely, the bug index & todo index).
+ */
+table.link-index { border-collapse: collapse;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #608090; }
+td.link-index { border-width: 0px; }
+table.link-index a:link { color: #0000ff; }
+table.link-index a:visited { color: #204080; }
+span.index-where { font-size: 70%; }
+table.metadata-index { border-collapse: collapse;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #608090;
+ margin: .2em 0 0 0; }
+td.metadata-index { border-width: 1px; border-style: solid; }
+table.metadata-index a:link { color: #0000ff; }
+table.metadata-index a:visited { color: #204080; }
+
+/* Function signatures
+ * - sig* is used for the signature in the details section.
+ * - .summary-sig* is used for the signature in the summary
+ * table, and when listing property accessor functions.
+ * */
+.sig-name { color: #006080; }
+.sig-arg { color: #008060; }
+.sig-default { color: #602000; }
+.summary-sig { font-family: monospace; }
+.summary-sig-name { color: #006080; font-weight: bold; }
+table.summary a.summary-sig-name:link
+ { color: #006080; font-weight: bold; }
+table.summary a.summary-sig-name:visited
+ { color: #006080; font-weight: bold; }
+.summary-sig-arg { color: #006040; }
+.summary-sig-default { color: #501800; }
+
+/* Subclass list
+ */
+ul.subclass-list { display: inline; }
+ul.subclass-list li { display: inline; }
+
+/* To render variables, classes etc. like functions */
+table.summary .summary-name { color: #006080; font-weight: bold;
+ font-family: monospace; }
+table.summary
+ a.summary-name:link { color: #006080; font-weight: bold;
+ font-family: monospace; }
+table.summary
+ a.summary-name:visited { color: #006080; font-weight: bold;
+ font-family: monospace; }
+
+/* Variable values
+ * - In the 'variable details' sections, each varaible's value is
+ * listed in a 'pre.variable' box. The width of this box is
+ * restricted to 80 chars; if the value's repr is longer than
+ * this it will be wrapped, using a backslash marked with
+ * class 'variable-linewrap'. If the value's repr is longer
+ * than 3 lines, the rest will be ellided; and an ellipsis
+ * marker ('...' marked with 'variable-ellipsis') will be used.
+ * - If the value is a string, its quote marks will be marked
+ * with 'variable-quote'.
+ * - If the variable is a regexp, it is syntax-highlighted using
+ * the re* CSS classes.
+ */
+pre.variable { padding: .5em; margin: 0;
+ background: #dce4ec; color: #000000;
+ border: 1px solid #708890; }
+.variable-linewrap { color: #604000; font-weight: bold; }
+.variable-ellipsis { color: #604000; font-weight: bold; }
+.variable-quote { color: #604000; font-weight: bold; }
+.variable-group { color: #008000; font-weight: bold; }
+.variable-op { color: #604000; font-weight: bold; }
+.variable-string { color: #006030; }
+.variable-unknown { color: #a00000; font-weight: bold; }
+.re { color: #000000; }
+.re-char { color: #006030; }
+.re-op { color: #600000; }
+.re-group { color: #003060; }
+.re-ref { color: #404040; }
+
+/* Base tree
+ * - Used by class pages to display the base class hierarchy.
+ */
+pre.base-tree { font-size: 80%; margin: 0; }
+
+/* Frames-based table of contents headers
+ * - Consists of two frames: one for selecting modules; and
+ * the other listing the contents of the selected module.
+ * - h1.toc is used for each frame's heading
+ * - h2.toc is used for subheadings within each frame.
+ */
+h1.toc { text-align: center; font-size: 105%;
+ margin: 0; font-weight: bold;
+ padding: 0; }
+h2.toc { font-size: 100%; font-weight: bold;
+ margin: 0.5em 0 0 -0.3em; }
+
+/* Syntax Highlighting for Source Code
+ * - doctest examples are displayed in a 'pre.py-doctest' block.
+ * If the example is in a details table entry, then it will use
+ * the colors specified by the 'table pre.py-doctest' line.
+ * - Source code listings are displayed in a 'pre.py-src' block.
+ * Each line is marked with 'span.py-line' (used to draw a line
+ * down the left margin, separating the code from the line
+ * numbers). Line numbers are displayed with 'span.py-lineno'.
+ * The expand/collapse block toggle button is displayed with
+ * 'a.py-toggle' (Note: the CSS style for 'a.py-toggle' should not
+ * modify the font size of the text.)
+ * - If a source code page is opened with an anchor, then the
+ * corresponding code block will be highlighted. The code
+ * block's header is highlighted with 'py-highlight-hdr'; and
+ * the code block's body is highlighted with 'py-highlight'.
+ * - The remaining py-* classes are used to perform syntax
+ * highlighting (py-string for string literals, py-name for names,
+ * etc.)
+ */
+pre.py-doctest { padding: .5em; margin: 1em;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #708890; }
+table pre.py-doctest { background: #dce4ec;
+ color: #000000; }
+pre.py-src { border: 2px solid #000000;
+ background: #f0f0f0; color: #000000; }
+.py-line { border-left: 2px solid #000000;
+ margin-left: .2em; padding-left: .4em; }
+.py-lineno { font-style: italic; font-size: 90%;
+ padding-left: .5em; }
+a.py-toggle { text-decoration: none; }
+div.py-highlight-hdr { border-top: 2px solid #000000;
+ border-bottom: 2px solid #000000;
+ background: #d8e8e8; }
+div.py-highlight { border-bottom: 2px solid #000000;
+ background: #d0e0e0; }
+.py-prompt { color: #005050; font-weight: bold;}
+.py-more { color: #005050; font-weight: bold;}
+.py-string { color: #006030; }
+.py-comment { color: #003060; }
+.py-keyword { color: #600000; }
+.py-output { color: #404040; }
+.py-name { color: #000050; }
+.py-name:link { color: #000050 !important; }
+.py-name:visited { color: #000050 !important; }
+.py-number { color: #005000; }
+.py-defname { color: #000060; font-weight: bold; }
+.py-def-name { color: #000060; font-weight: bold; }
+.py-base-class { color: #000060; }
+.py-param { color: #000060; }
+.py-docstring { color: #006030; }
+.py-decorator { color: #804020; }
+/* Use this if you don't want links to names underlined: */
+/*a.py-name { text-decoration: none; }*/
+
+/* Graphs & Diagrams
+ * - These CSS styles are used for graphs & diagrams generated using
+ * Graphviz dot. 'img.graph-without-title' is used for bare
+ * diagrams (to remove the border created by making the image
+ * clickable).
+ */
+img.graph-without-title { border: none; }
+img.graph-with-title { border: 1px solid #000000; }
+span.graph-title { font-weight: bold; }
+span.graph-caption { }
+
+/* General-purpose classes
+ * - 'p.indent-wrapped-lines' defines a paragraph whose first line
+ * is not indented, but whose subsequent lines are.
+ * - The 'nomargin-top' class is used to remove the top margin (e.g.
+ * from lists). The 'nomargin' class is used to remove both the
+ * top and bottom margin (but not the left or right margin --
+ * for lists, that would cause the bullets to disappear.)
+ */
+p.indent-wrapped-lines { padding: 0 0 0 7em; text-indent: -7em;
+ margin: 0; }
+.nomargin-top { margin-top: 0; }
+.nomargin { margin-top: 0; margin-bottom: 0; }
+
+/* HTML Log */
+div.log-block { padding: 0; margin: .5em 0 .5em 0;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #000000; }
+div.log-error { padding: .1em .3em .1em .3em; margin: 4px;
+ background: #ffb0b0; color: #000000;
+ border: 1px solid #000000; }
+div.log-warning { padding: .1em .3em .1em .3em; margin: 4px;
+ background: #ffffb0; color: #000000;
+ border: 1px solid #000000; }
+div.log-info { padding: .1em .3em .1em .3em; margin: 4px;
+ background: #b0ffb0; color: #000000;
+ border: 1px solid #000000; }
+h2.log-hdr { background: #70b0ff; color: #000000;
+ margin: 0; padding: 0em 0.5em 0em 0.5em;
+ border-bottom: 1px solid #000000; font-size: 110%; }
+p.log { font-weight: bold; margin: .5em 0 .5em 0; }
+tr.opt-changed { color: #000000; font-weight: bold; }
+tr.opt-default { color: #606060; }
+pre.log { margin: 0; padding: 0; padding-left: 1em; }
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/epydoc.js b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/epydoc.js
new file mode 100644
index 00000000000..e787dbcf471
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/epydoc.js
@@ -0,0 +1,293 @@
+function toggle_private() {
+ // Search for any private/public links on this page. Store
+ // their old text in "cmd," so we will know what action to
+ // take; and change their text to the opposite action.
+ var cmd = "?";
+ var elts = document.getElementsByTagName("a");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "privatelink") {
+ cmd = elts[i].innerHTML;
+ elts[i].innerHTML = ((cmd && cmd.substr(0,4)=="show")?
+ "hide&nbsp;private":"show&nbsp;private");
+ }
+ }
+ // Update all DIVs containing private objects.
+ var elts = document.getElementsByTagName("div");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "private") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"block");
+ }
+ else if (elts[i].className == "public") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"block":"none");
+ }
+ }
+ // Update all table rows containing private objects. Note, we
+ // use "" instead of "block" becaue IE & firefox disagree on what
+ // this should be (block vs table-row), and "" just gives the
+ // default for both browsers.
+ var elts = document.getElementsByTagName("tr");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "private") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"");
+ }
+ }
+ // Update all list items containing private objects.
+ var elts = document.getElementsByTagName("li");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "private") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?
+ "none":"");
+ }
+ }
+ // Update all list items containing private objects.
+ var elts = document.getElementsByTagName("ul");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "private") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"block");
+ }
+ }
+ // Set a cookie to remember the current option.
+ document.cookie = "EpydocPrivate="+cmd;
+ }
+function show_private() {
+ var elts = document.getElementsByTagName("a");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "privatelink") {
+ cmd = elts[i].innerHTML;
+ if (cmd && cmd.substr(0,4)=="show")
+ toggle_private();
+ }
+ }
+ }
+function getCookie(name) {
+ var dc = document.cookie;
+ var prefix = name + "=";
+ var begin = dc.indexOf("; " + prefix);
+ if (begin == -1) {
+ begin = dc.indexOf(prefix);
+ if (begin != 0) return null;
+ } else
+ { begin += 2; }
+ var end = document.cookie.indexOf(";", begin);
+ if (end == -1)
+ { end = dc.length; }
+ return unescape(dc.substring(begin + prefix.length, end));
+ }
+function setFrame(url1, url2) {
+ parent.frames[1].location.href = url1;
+ parent.frames[2].location.href = url2;
+ }
+function checkCookie() {
+ var cmd=getCookie("EpydocPrivate");
+ if (cmd && cmd.substr(0,4)!="show" && location.href.indexOf("#_") < 0)
+ toggle_private();
+ }
+function toggleCallGraph(id) {
+ var elt = document.getElementById(id);
+ if (elt.style.display == "none")
+ elt.style.display = "block";
+ else
+ elt.style.display = "none";
+ }
+function expand(id) {
+ var elt = document.getElementById(id+"-expanded");
+ if (elt) elt.style.display = "block";
+ var elt = document.getElementById(id+"-expanded-linenums");
+ if (elt) elt.style.display = "block";
+ var elt = document.getElementById(id+"-collapsed");
+ if (elt) { elt.innerHTML = ""; elt.style.display = "none"; }
+ var elt = document.getElementById(id+"-collapsed-linenums");
+ if (elt) { elt.innerHTML = ""; elt.style.display = "none"; }
+ var elt = document.getElementById(id+"-toggle");
+ if (elt) { elt.innerHTML = "-"; }
+}
+
+function collapse(id) {
+ var elt = document.getElementById(id+"-expanded");
+ if (elt) elt.style.display = "none";
+ var elt = document.getElementById(id+"-expanded-linenums");
+ if (elt) elt.style.display = "none";
+ var elt = document.getElementById(id+"-collapsed-linenums");
+ if (elt) { elt.innerHTML = "<br />"; elt.style.display="block"; }
+ var elt = document.getElementById(id+"-toggle");
+ if (elt) { elt.innerHTML = "+"; }
+ var elt = document.getElementById(id+"-collapsed");
+ if (elt) {
+ elt.style.display = "block";
+
+ var indent = elt.getAttribute("indent");
+ var pad = elt.getAttribute("pad");
+ var s = "<tt class='py-lineno'>";
+ for (var i=0; i<pad.length; i++) { s += "&nbsp;" }
+ s += "</tt>";
+ s += "&nbsp;&nbsp;<tt class='py-line'>";
+ for (var i=0; i<indent.length; i++) { s += "&nbsp;" }
+ s += "<a href='#' onclick='expand(\"" + id;
+ s += "\");return false'>...</a></tt><br />";
+ elt.innerHTML = s;
+ }
+}
+
+function toggle(id) {
+ elt = document.getElementById(id+"-toggle");
+ if (elt.innerHTML == "-")
+ collapse(id);
+ else
+ expand(id);
+ return false;
+}
+
+function highlight(id) {
+ var elt = document.getElementById(id+"-def");
+ if (elt) elt.className = "py-highlight-hdr";
+ var elt = document.getElementById(id+"-expanded");
+ if (elt) elt.className = "py-highlight";
+ var elt = document.getElementById(id+"-collapsed");
+ if (elt) elt.className = "py-highlight";
+}
+
+function num_lines(s) {
+ var n = 1;
+ var pos = s.indexOf("\n");
+ while ( pos > 0) {
+ n += 1;
+ pos = s.indexOf("\n", pos+1);
+ }
+ return n;
+}
+
+// Collapse all blocks that mave more than `min_lines` lines.
+function collapse_all(min_lines) {
+ var elts = document.getElementsByTagName("div");
+ for (var i=0; i<elts.length; i++) {
+ var elt = elts[i];
+ var split = elt.id.indexOf("-");
+ if (split > 0)
+ if (elt.id.substring(split, elt.id.length) == "-expanded")
+ if (num_lines(elt.innerHTML) > min_lines)
+ collapse(elt.id.substring(0, split));
+ }
+}
+
+function expandto(href) {
+ var start = href.indexOf("#")+1;
+ if (start != 0 && start != href.length) {
+ if (href.substring(start, href.length) != "-") {
+ collapse_all(4);
+ pos = href.indexOf(".", start);
+ while (pos != -1) {
+ var id = href.substring(start, pos);
+ expand(id);
+ pos = href.indexOf(".", pos+1);
+ }
+ var id = href.substring(start, href.length);
+ expand(id);
+ highlight(id);
+ }
+ }
+}
+
+function kill_doclink(id) {
+ var parent = document.getElementById(id);
+ parent.removeChild(parent.childNodes.item(0));
+}
+function auto_kill_doclink(ev) {
+ if (!ev) var ev = window.event;
+ if (!this.contains(ev.toElement)) {
+ var parent = document.getElementById(this.parentID);
+ parent.removeChild(parent.childNodes.item(0));
+ }
+}
+
+function doclink(id, name, targets_id) {
+ var elt = document.getElementById(id);
+
+ // If we already opened the box, then destroy it.
+ // (This case should never occur, but leave it in just in case.)
+ if (elt.childNodes.length > 1) {
+ elt.removeChild(elt.childNodes.item(0));
+ }
+ else {
+ // The outer box: relative + inline positioning.
+ var box1 = document.createElement("div");
+ box1.style.position = "relative";
+ box1.style.display = "inline";
+ box1.style.top = 0;
+ box1.style.left = 0;
+
+ // A shadow for fun
+ var shadow = document.createElement("div");
+ shadow.style.position = "absolute";
+ shadow.style.left = "-1.3em";
+ shadow.style.top = "-1.3em";
+ shadow.style.background = "#404040";
+
+ // The inner box: absolute positioning.
+ var box2 = document.createElement("div");
+ box2.style.position = "relative";
+ box2.style.border = "1px solid #a0a0a0";
+ box2.style.left = "-.2em";
+ box2.style.top = "-.2em";
+ box2.style.background = "white";
+ box2.style.padding = ".3em .4em .3em .4em";
+ box2.style.fontStyle = "normal";
+ box2.onmouseout=auto_kill_doclink;
+ box2.parentID = id;
+
+ // Get the targets
+ var targets_elt = document.getElementById(targets_id);
+ var targets = targets_elt.getAttribute("targets");
+ var links = "";
+ target_list = targets.split(",");
+ for (var i=0; i<target_list.length; i++) {
+ var target = target_list[i].split("=");
+ links += "<li><a href='" + target[1] +
+ "' style='text-decoration:none'>" +
+ target[0] + "</a></li>";
+ }
+
+ // Put it all together.
+ elt.insertBefore(box1, elt.childNodes.item(0));
+ //box1.appendChild(box2);
+ box1.appendChild(shadow);
+ shadow.appendChild(box2);
+ box2.innerHTML =
+ "Which <b>"+name+"</b> do you want to see documentation for?" +
+ "<ul style='margin-bottom: 0;'>" +
+ links +
+ "<li><a href='#' style='text-decoration:none' " +
+ "onclick='kill_doclink(\""+id+"\");return false;'>"+
+ "<i>None of the above</i></a></li></ul>";
+ }
+ return false;
+}
+
+function get_anchor() {
+ var href = location.href;
+ var start = href.indexOf("#")+1;
+ if ((start != 0) && (start != href.length))
+ return href.substring(start, href.length);
+ }
+function redirect_url(dottedName) {
+ // Scan through each element of the "pages" list, and check
+ // if "name" matches with any of them.
+ for (var i=0; i<pages.length; i++) {
+
+ // Each page has the form "<pagename>-m" or "<pagename>-c";
+ // extract the <pagename> portion & compare it to dottedName.
+ var pagename = pages[i].substring(0, pages[i].length-2);
+ if (pagename == dottedName.substring(0,pagename.length)) {
+
+ // We've found a page that matches `dottedName`;
+ // construct its URL, using leftover `dottedName`
+ // content to form an anchor.
+ var pagetype = pages[i].charAt(pages[i].length-1);
+ var url = pagename + ((pagetype=="m")?"-module.html":
+ "-class.html");
+ if (dottedName.length > pagename.length)
+ url += "#" + dottedName.substring(pagename.length+1,
+ dottedName.length);
+ return url;
+ }
+ }
+ }
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/help.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/help.html
new file mode 100644
index 00000000000..d1bf1c8766d
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/help.html
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Help</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rcssmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Help&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">&nbsp;</td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+
+<h1 class="epydoc"> API Documentation </h1>
+
+<p> This document contains the API (Application Programming Interface)
+documentation for this project. Documentation for the Python
+objects defined by the project is divided into separate pages for each
+package, module, and class. The API documentation also includes two
+pages containing information about the project as a whole: a trees
+page, and an index page. </p>
+
+<h2> Object Documentation </h2>
+
+ <p>Each <strong>Package Documentation</strong> page contains: </p>
+ <ul>
+ <li> A description of the package. </li>
+ <li> A list of the modules and sub-packages contained by the
+ package. </li>
+ <li> A summary of the classes defined by the package. </li>
+ <li> A summary of the functions defined by the package. </li>
+ <li> A summary of the variables defined by the package. </li>
+ <li> A detailed description of each function defined by the
+ package. </li>
+ <li> A detailed description of each variable defined by the
+ package. </li>
+ </ul>
+
+ <p>Each <strong>Module Documentation</strong> page contains:</p>
+ <ul>
+ <li> A description of the module. </li>
+ <li> A summary of the classes defined by the module. </li>
+ <li> A summary of the functions defined by the module. </li>
+ <li> A summary of the variables defined by the module. </li>
+ <li> A detailed description of each function defined by the
+ module. </li>
+ <li> A detailed description of each variable defined by the
+ module. </li>
+ </ul>
+
+ <p>Each <strong>Class Documentation</strong> page contains: </p>
+ <ul>
+ <li> A class inheritance diagram. </li>
+ <li> A list of known subclasses. </li>
+ <li> A description of the class. </li>
+ <li> A summary of the methods defined by the class. </li>
+ <li> A summary of the instance variables defined by the class. </li>
+ <li> A summary of the class (static) variables defined by the
+ class. </li>
+ <li> A detailed description of each method defined by the
+ class. </li>
+ <li> A detailed description of each instance variable defined by the
+ class. </li>
+ <li> A detailed description of each class (static) variable defined
+ by the class. </li>
+ </ul>
+
+<h2> Project Documentation </h2>
+
+ <p> The <strong>Trees</strong> page contains the module and class hierarchies: </p>
+ <ul>
+ <li> The <em>module hierarchy</em> lists every package and module, with
+ modules grouped into packages. At the top level, and within each
+ package, modules and sub-packages are listed alphabetically. </li>
+ <li> The <em>class hierarchy</em> lists every class, grouped by base
+ class. If a class has more than one base class, then it will be
+ listed under each base class. At the top level, and under each base
+ class, classes are listed alphabetically. </li>
+ </ul>
+
+ <p> The <strong>Index</strong> page contains indices of terms and
+ identifiers: </p>
+ <ul>
+ <li> The <em>term index</em> lists every term indexed by any object's
+ documentation. For each term, the index provides links to each
+ place where the term is indexed. </li>
+ <li> The <em>identifier index</em> lists the (short) name of every package,
+ module, class, method, function, variable, and parameter. For each
+ identifier, the index provides a short description, and a link to
+ its documentation. </li>
+ </ul>
+
+<h2> The Table of Contents </h2>
+
+<p> The table of contents occupies the two frames on the left side of
+the window. The upper-left frame displays the <em>project
+contents</em>, and the lower-left frame displays the <em>module
+contents</em>: </p>
+
+<table class="help summary" border="1" cellspacing="0" cellpadding="3">
+ <tr style="height: 30%">
+ <td align="center" style="font-size: small">
+ Project<br />Contents<hr />...</td>
+ <td align="center" style="font-size: small" rowspan="2" width="70%">
+ API<br />Documentation<br />Frame<br /><br /><br />
+ </td>
+ </tr>
+ <tr>
+ <td align="center" style="font-size: small">
+ Module<br />Contents<hr />&nbsp;<br />...<br />&nbsp;
+ </td>
+ </tr>
+</table><br />
+
+<p> The <strong>project contents frame</strong> contains a list of all packages
+and modules that are defined by the project. Clicking on an entry
+will display its contents in the module contents frame. Clicking on a
+special entry, labeled "Everything," will display the contents of
+the entire project. </p>
+
+<p> The <strong>module contents frame</strong> contains a list of every
+submodule, class, type, exception, function, and variable defined by a
+module or package. Clicking on an entry will display its
+documentation in the API documentation frame. Clicking on the name of
+the module, at the top of the frame, will display the documentation
+for the module itself. </p>
+
+<p> The "<strong>frames</strong>" and "<strong>no frames</strong>" buttons below the top
+navigation bar can be used to control whether the table of contents is
+displayed or not. </p>
+
+<h2> The Navigation Bar </h2>
+
+<p> A navigation bar is located at the top and bottom of every page.
+It indicates what type of page you are currently viewing, and allows
+you to go to related pages. The following table describes the labels
+on the navigation bar. Note that not some labels (such as
+[Parent]) are not displayed on all pages. </p>
+
+<table class="summary" border="1" cellspacing="0" cellpadding="3" width="100%">
+<tr class="summary">
+ <th>Label</th>
+ <th>Highlighted when...</th>
+ <th>Links to...</th>
+</tr>
+ <tr><td valign="top"><strong>[Parent]</strong></td>
+ <td valign="top"><em>(never highlighted)</em></td>
+ <td valign="top"> the parent of the current package </td></tr>
+ <tr><td valign="top"><strong>[Package]</strong></td>
+ <td valign="top">viewing a package</td>
+ <td valign="top">the package containing the current object
+ </td></tr>
+ <tr><td valign="top"><strong>[Module]</strong></td>
+ <td valign="top">viewing a module</td>
+ <td valign="top">the module containing the current object
+ </td></tr>
+ <tr><td valign="top"><strong>[Class]</strong></td>
+ <td valign="top">viewing a class </td>
+ <td valign="top">the class containing the current object</td></tr>
+ <tr><td valign="top"><strong>[Trees]</strong></td>
+ <td valign="top">viewing the trees page</td>
+ <td valign="top"> the trees page </td></tr>
+ <tr><td valign="top"><strong>[Index]</strong></td>
+ <td valign="top">viewing the index page</td>
+ <td valign="top"> the index page </td></tr>
+ <tr><td valign="top"><strong>[Help]</strong></td>
+ <td valign="top">viewing the help page</td>
+ <td valign="top"> the help page </td></tr>
+</table>
+
+<p> The "<strong>show private</strong>" and "<strong>hide private</strong>" buttons below
+the top navigation bar can be used to control whether documentation
+for private objects is displayed. Private objects are usually defined
+as objects whose (short) names begin with a single underscore, but do
+not end with an underscore. For example, "<code>_x</code>",
+"<code>__pprint</code>", and "<code>epydoc.epytext._tokenize</code>"
+are private objects; but "<code>re.sub</code>",
+"<code>__init__</code>", and "<code>type_</code>" are not. However,
+if a module defines the "<code>__all__</code>" variable, then its
+contents are used to decide which objects are private. </p>
+
+<p> A timestamp below the bottom navigation bar indicates when each
+page was last updated. </p>
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rcssmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Help&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/identifier-index.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/identifier-index.html
new file mode 100644
index 00000000000..82acafdbb7c
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/identifier-index.html
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Identifier Index</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rcssmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Indices&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">&nbsp;</td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<table border="0" width="100%">
+<tr valign="bottom"><td>
+<h1 class="epydoc">Identifier Index</h1>
+</td><td>
+[
+ A
+ B
+ <a href="#C">C</a>
+ D
+ E
+ F
+ G
+ H
+ I
+ J
+ K
+ L
+ M
+ N
+ O
+ P
+ Q
+ <a href="#R">R</a>
+ S
+ T
+ U
+ V
+ W
+ X
+ Y
+ Z
+ <a href="#_">_</a>
+]
+</td></table>
+<table border="0" width="100%">
+<tr valign="top"><td valign="top" width="1%"><h2 class="epydoc"><a name="C">C</a></h2></td>
+<td valign="top">
+<table class="link-index" width="100%" border="1">
+<tr>
+<td width="33%" class="link-index"><a href="rcssmin-module.html#cssmin">cssmin()</a><br />
+<span class="index-where">(in&nbsp;<a href="rcssmin-module.html">rcssmin</a>)</span></td>
+<td width="33%" class="link-index">&nbsp;</td>
+<td width="33%" class="link-index">&nbsp;</td>
+</tr>
+<tr><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td></tr>
+</table>
+</td></tr>
+<tr valign="top"><td valign="top" width="1%"><h2 class="epydoc"><a name="R">R</a></h2></td>
+<td valign="top">
+<table class="link-index" width="100%" border="1">
+<tr>
+<td width="33%" class="link-index"><a href="rcssmin-module.html">rcssmin</a></td>
+<td width="33%" class="link-index">&nbsp;</td>
+<td width="33%" class="link-index">&nbsp;</td>
+</tr>
+<tr><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td></tr>
+</table>
+</td></tr>
+<tr valign="top"><td valign="top" width="1%"><h2 class="epydoc"><a name="_">_</a></h2></td>
+<td valign="top">
+<table class="link-index" width="100%" border="1">
+<tr>
+<td width="33%" class="link-index"><a href="rcssmin-module.html#__doc__">__doc__</a><br />
+<span class="index-where">(in&nbsp;<a href="rcssmin-module.html">rcssmin</a>)</span></td>
+<td width="33%" class="link-index"><a href="rcssmin-module.html#__license__">__license__</a><br />
+<span class="index-where">(in&nbsp;<a href="rcssmin-module.html">rcssmin</a>)</span></td>
+<td width="33%" class="link-index"><a href="rcssmin-module.html#__package__">__package__</a><br />
+<span class="index-where">(in&nbsp;<a href="rcssmin-module.html">rcssmin</a>)</span></td>
+</tr>
+<tr><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td></tr>
+</table>
+</td></tr>
+</table>
+<br /><br /><!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rcssmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Indices&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/index.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/index.html
new file mode 100644
index 00000000000..84ffddda734
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/index.html
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>rcssmin</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">
+ <span class="breadcrumbs">
+ Module&nbsp;rcssmin
+ </span>
+ </td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<!-- ==================== MODULE DESCRIPTION ==================== -->
+<h1 class="epydoc">Module rcssmin</h1><p class="nomargin-top"><span class="codelink"><a href="rcssmin-pysrc.html">source&nbsp;code</a></span></p>
+<p>CSS Minifier.</p>
+<p>The minifier is based on the semantics of the <a class="rst-reference external" href="https://github.com/yui/yuicompressor/" target="_top">YUI compressor</a>, which
+itself is based on <a class="rst-reference external" href="https://github.com/isaacs/cssmin/" target="_top">the rule list by Isaac Schlueter</a>.</p>
+<p>This module is a re-implementation aiming for speed instead of maximum
+compression, so it can be used at runtime (rather than during a preprocessing
+step). RCSSmin does syntactical compression only (removing spaces, comments
+and possibly semicolons). It does not provide semantic compression (like
+removing empty blocks, collapsing redundant properties etc). It does, however,
+support various CSS hacks (by keeping them working as intended).</p>
+<p>Here's a feature list:</p>
+<ul class="rst-simple">
+<li>Strings are kept, except that escaped newlines are stripped</li>
+<li>Space/Comments before the very end or before various characters are
+stripped: <tt class="rst-docutils literal"><span class="pre">:{});=&gt;+],!</span></tt> (The colon (<tt class="rst-docutils literal">:</tt>) is a special case, a single
+space is kept if it's outside a ruleset.)</li>
+<li>Space/Comments at the very beginning or after various characters are
+stripped: <tt class="rst-docutils literal"><span class="pre">{}(=:&gt;+[,!</span></tt></li>
+<li>Optional space after unicode escapes is kept, resp. replaced by a simple
+space</li>
+<li>whitespaces inside <tt class="rst-docutils literal">url()</tt> definitions are stripped</li>
+<li>Comments starting with an exclamation mark (<tt class="rst-docutils literal">!</tt>) can be kept optionally.</li>
+<li>All other comments and/or whitespace characters are replaced by a single
+space.</li>
+<li>Multiple consecutive semicolons are reduced to one</li>
+<li>The last semicolon within a ruleset is stripped</li>
+<li>CSS Hacks supported:<ul>
+<li>IE7 hack (<tt class="rst-docutils literal"><span class="pre">&gt;/**/</span></tt>)</li>
+<li>Mac-IE5 hack (<tt class="rst-docutils literal"><span class="pre">/*\*/.../**/</span></tt>)</li>
+<li>The boxmodelhack is supported naturally because it relies on valid CSS2
+strings</li>
+<li>Between <tt class="rst-docutils literal"><span class="pre">:first-line</span></tt> and the following comma or curly brace a space is
+inserted. (apparently it's needed for IE6)</li>
+<li>Same for <tt class="rst-docutils literal"><span class="pre">:first-letter</span></tt></li>
+</ul>
+</li>
+</ul>
+<p>rcssmin.c is a reimplementation of rcssmin.py in C and improves runtime up to
+factor 100 or so (depending on the input). docs/BENCHMARKS in the source
+distribution contains the details.</p>
+<p>Both python 2 (&gt;= 2.4) and python 3 are supported.</p>
+
+<hr />
+<div class="fields"> <p><strong>Copyright:</strong>
+ Copyright 2011 - 2014
+Andr&#233; Malo or his licensors, as applicable
+ </p>
+ <p><strong>License:</strong>
+ <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at</p>
+<blockquote>
+<a class="rst-reference external" href="http://www.apache.org/licenses/LICENSE-2.0" target="_top">http://www.apache.org/licenses/LICENSE-2.0</a></blockquote>
+<p>Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.</p>
+ </p>
+ <p><strong>Version:</strong>
+ 1.0.5
+ </p>
+ <p><strong>Author:</strong>
+ Andr&#233; Malo
+ </p>
+</div><!-- ==================== FUNCTIONS ==================== -->
+<a name="section-Functions"></a>
+<table class="summary" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr bgcolor="#70b0f0" class="table-header">
+ <td align="left" colspan="2" class="table-header">
+ <span class="table-header">Functions</span></td>
+</tr>
+<tr>
+ <td width="15%" align="right" valign="top" class="summary">
+ <span class="summary-type"><tt class="rst-docutils literal">str</tt></span>
+ </td><td class="summary">
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td><span class="summary-sig"><a href="rcssmin-module.html#cssmin" class="summary-sig-name">cssmin</a>(<span class="summary-sig-arg">style</span>,
+ <span class="summary-sig-arg">keep_bang_comments</span>=<span class="summary-sig-default">False</span>)</span><br />
+ Minify CSS.</td>
+ <td align="right" valign="top">
+ <span class="codelink"><a href="rcssmin-pysrc.html#cssmin">source&nbsp;code</a></span>
+
+ </td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+</table>
+<!-- ==================== FUNCTION DETAILS ==================== -->
+<a name="section-FunctionDetails"></a>
+<table class="details" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr bgcolor="#70b0f0" class="table-header">
+ <td align="left" colspan="2" class="table-header">
+ <span class="table-header">Function Details</span></td>
+</tr>
+</table>
+<a name="cssmin"></a>
+<div>
+<table class="details" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr><td>
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr valign="top"><td>
+ <h3 class="epydoc"><span class="sig"><span class="sig-name">cssmin</span>(<span class="sig-arg">style</span>,
+ <span class="sig-arg">keep_bang_comments</span>=<span class="sig-default">False</span>)</span>
+ </h3>
+ </td><td align="right" valign="top"
+ ><span class="codelink"><a href="rcssmin-pysrc.html#cssmin">source&nbsp;code</a></span>&nbsp;
+ </td>
+ </tr></table>
+
+ Minify CSS.
+ <dl class="fields">
+ <dt>Parameters:</dt>
+ <dd><ul class="nomargin-top">
+ <li><strong class="pname"><code>style</code></strong> (<tt class="rst-docutils literal">str</tt>) - CSS to minify</li>
+ <li><strong class="pname"><code>keep_bang_comments</code></strong> (<tt class="rst-docutils literal">bool</tt>) - Keep comments starting with an exclamation mark? (<tt class="rst-docutils literal"><span class="pre">/*!...*/</span></tt>)</li>
+ </ul></dd>
+ <dt>Returns: <tt class="rst-docutils literal">str</tt></dt>
+ <dd>Minified style</dd>
+ </dl>
+</td></tr></table>
+</div>
+<br />
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/module-tree.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/module-tree.html
new file mode 100644
index 00000000000..e522dd1721b
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/module-tree.html
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Module Hierarchy</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rcssmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Trees&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">&nbsp;</td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<h1 class="epydoc">Module Hierarchy</h1>
+<ul class="nomargin-top">
+ <li> <strong class="uidlink"><a href="rcssmin-module.html">rcssmin</a></strong>: <em class="summary">CSS Minifier.</em> </li>
+</ul>
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rcssmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Trees&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/rcssmin-module.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/rcssmin-module.html
new file mode 100644
index 00000000000..84ffddda734
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/rcssmin-module.html
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>rcssmin</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">
+ <span class="breadcrumbs">
+ Module&nbsp;rcssmin
+ </span>
+ </td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<!-- ==================== MODULE DESCRIPTION ==================== -->
+<h1 class="epydoc">Module rcssmin</h1><p class="nomargin-top"><span class="codelink"><a href="rcssmin-pysrc.html">source&nbsp;code</a></span></p>
+<p>CSS Minifier.</p>
+<p>The minifier is based on the semantics of the <a class="rst-reference external" href="https://github.com/yui/yuicompressor/" target="_top">YUI compressor</a>, which
+itself is based on <a class="rst-reference external" href="https://github.com/isaacs/cssmin/" target="_top">the rule list by Isaac Schlueter</a>.</p>
+<p>This module is a re-implementation aiming for speed instead of maximum
+compression, so it can be used at runtime (rather than during a preprocessing
+step). RCSSmin does syntactical compression only (removing spaces, comments
+and possibly semicolons). It does not provide semantic compression (like
+removing empty blocks, collapsing redundant properties etc). It does, however,
+support various CSS hacks (by keeping them working as intended).</p>
+<p>Here's a feature list:</p>
+<ul class="rst-simple">
+<li>Strings are kept, except that escaped newlines are stripped</li>
+<li>Space/Comments before the very end or before various characters are
+stripped: <tt class="rst-docutils literal"><span class="pre">:{});=&gt;+],!</span></tt> (The colon (<tt class="rst-docutils literal">:</tt>) is a special case, a single
+space is kept if it's outside a ruleset.)</li>
+<li>Space/Comments at the very beginning or after various characters are
+stripped: <tt class="rst-docutils literal"><span class="pre">{}(=:&gt;+[,!</span></tt></li>
+<li>Optional space after unicode escapes is kept, resp. replaced by a simple
+space</li>
+<li>whitespaces inside <tt class="rst-docutils literal">url()</tt> definitions are stripped</li>
+<li>Comments starting with an exclamation mark (<tt class="rst-docutils literal">!</tt>) can be kept optionally.</li>
+<li>All other comments and/or whitespace characters are replaced by a single
+space.</li>
+<li>Multiple consecutive semicolons are reduced to one</li>
+<li>The last semicolon within a ruleset is stripped</li>
+<li>CSS Hacks supported:<ul>
+<li>IE7 hack (<tt class="rst-docutils literal"><span class="pre">&gt;/**/</span></tt>)</li>
+<li>Mac-IE5 hack (<tt class="rst-docutils literal"><span class="pre">/*\*/.../**/</span></tt>)</li>
+<li>The boxmodelhack is supported naturally because it relies on valid CSS2
+strings</li>
+<li>Between <tt class="rst-docutils literal"><span class="pre">:first-line</span></tt> and the following comma or curly brace a space is
+inserted. (apparently it's needed for IE6)</li>
+<li>Same for <tt class="rst-docutils literal"><span class="pre">:first-letter</span></tt></li>
+</ul>
+</li>
+</ul>
+<p>rcssmin.c is a reimplementation of rcssmin.py in C and improves runtime up to
+factor 100 or so (depending on the input). docs/BENCHMARKS in the source
+distribution contains the details.</p>
+<p>Both python 2 (&gt;= 2.4) and python 3 are supported.</p>
+
+<hr />
+<div class="fields"> <p><strong>Copyright:</strong>
+ Copyright 2011 - 2014
+Andr&#233; Malo or his licensors, as applicable
+ </p>
+ <p><strong>License:</strong>
+ <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at</p>
+<blockquote>
+<a class="rst-reference external" href="http://www.apache.org/licenses/LICENSE-2.0" target="_top">http://www.apache.org/licenses/LICENSE-2.0</a></blockquote>
+<p>Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.</p>
+ </p>
+ <p><strong>Version:</strong>
+ 1.0.5
+ </p>
+ <p><strong>Author:</strong>
+ Andr&#233; Malo
+ </p>
+</div><!-- ==================== FUNCTIONS ==================== -->
+<a name="section-Functions"></a>
+<table class="summary" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr bgcolor="#70b0f0" class="table-header">
+ <td align="left" colspan="2" class="table-header">
+ <span class="table-header">Functions</span></td>
+</tr>
+<tr>
+ <td width="15%" align="right" valign="top" class="summary">
+ <span class="summary-type"><tt class="rst-docutils literal">str</tt></span>
+ </td><td class="summary">
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td><span class="summary-sig"><a href="rcssmin-module.html#cssmin" class="summary-sig-name">cssmin</a>(<span class="summary-sig-arg">style</span>,
+ <span class="summary-sig-arg">keep_bang_comments</span>=<span class="summary-sig-default">False</span>)</span><br />
+ Minify CSS.</td>
+ <td align="right" valign="top">
+ <span class="codelink"><a href="rcssmin-pysrc.html#cssmin">source&nbsp;code</a></span>
+
+ </td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+</table>
+<!-- ==================== FUNCTION DETAILS ==================== -->
+<a name="section-FunctionDetails"></a>
+<table class="details" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr bgcolor="#70b0f0" class="table-header">
+ <td align="left" colspan="2" class="table-header">
+ <span class="table-header">Function Details</span></td>
+</tr>
+</table>
+<a name="cssmin"></a>
+<div>
+<table class="details" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr><td>
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr valign="top"><td>
+ <h3 class="epydoc"><span class="sig"><span class="sig-name">cssmin</span>(<span class="sig-arg">style</span>,
+ <span class="sig-arg">keep_bang_comments</span>=<span class="sig-default">False</span>)</span>
+ </h3>
+ </td><td align="right" valign="top"
+ ><span class="codelink"><a href="rcssmin-pysrc.html#cssmin">source&nbsp;code</a></span>&nbsp;
+ </td>
+ </tr></table>
+
+ Minify CSS.
+ <dl class="fields">
+ <dt>Parameters:</dt>
+ <dd><ul class="nomargin-top">
+ <li><strong class="pname"><code>style</code></strong> (<tt class="rst-docutils literal">str</tt>) - CSS to minify</li>
+ <li><strong class="pname"><code>keep_bang_comments</code></strong> (<tt class="rst-docutils literal">bool</tt>) - Keep comments starting with an exclamation mark? (<tt class="rst-docutils literal"><span class="pre">/*!...*/</span></tt>)</li>
+ </ul></dd>
+ <dt>Returns: <tt class="rst-docutils literal">str</tt></dt>
+ <dd>Minified style</dd>
+ </dl>
+</td></tr></table>
+</div>
+<br />
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/rcssmin-pysrc.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/rcssmin-pysrc.html
new file mode 100644
index 00000000000..6856baca0e6
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/rcssmin-pysrc.html
@@ -0,0 +1,477 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>rcssmin</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">
+ <span class="breadcrumbs">
+ Module&nbsp;rcssmin
+ </span>
+ </td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<h1 class="epydoc">Source Code for <a href="rcssmin-module.html">Module rcssmin</a></h1>
+<pre class="py-src">
+<a name="L1"></a><tt class="py-lineno"> 1</tt> <tt class="py-line"><tt class="py-comment">#!/usr/bin/env python</tt> </tt>
+<a name="L2"></a><tt class="py-lineno"> 2</tt> <tt class="py-line"><tt class="py-comment"># -*- coding: ascii -*-</tt> </tt>
+<a name="L3"></a><tt class="py-lineno"> 3</tt> <tt class="py-line"><tt class="py-docstring">r"""</tt> </tt>
+<a name="L4"></a><tt class="py-lineno"> 4</tt> <tt class="py-line"><tt class="py-docstring">==============</tt> </tt>
+<a name="L5"></a><tt class="py-lineno"> 5</tt> <tt class="py-line"><tt class="py-docstring"> CSS Minifier</tt> </tt>
+<a name="L6"></a><tt class="py-lineno"> 6</tt> <tt class="py-line"><tt class="py-docstring">==============</tt> </tt>
+<a name="L7"></a><tt class="py-lineno"> 7</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L8"></a><tt class="py-lineno"> 8</tt> <tt class="py-line"><tt class="py-docstring">CSS Minifier.</tt> </tt>
+<a name="L9"></a><tt class="py-lineno"> 9</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L10"></a><tt class="py-lineno"> 10</tt> <tt class="py-line"><tt class="py-docstring">The minifier is based on the semantics of the `YUI compressor`_\\, which</tt> </tt>
+<a name="L11"></a><tt class="py-lineno"> 11</tt> <tt class="py-line"><tt class="py-docstring">itself is based on `the rule list by Isaac Schlueter`_\\.</tt> </tt>
+<a name="L12"></a><tt class="py-lineno"> 12</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L13"></a><tt class="py-lineno"> 13</tt> <tt class="py-line"><tt class="py-docstring">:Copyright:</tt> </tt>
+<a name="L14"></a><tt class="py-lineno"> 14</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L15"></a><tt class="py-lineno"> 15</tt> <tt class="py-line"><tt class="py-docstring"> Copyright 2011 - 2014</tt> </tt>
+<a name="L16"></a><tt class="py-lineno"> 16</tt> <tt class="py-line"><tt class="py-docstring"> Andr\xe9 Malo or his licensors, as applicable</tt> </tt>
+<a name="L17"></a><tt class="py-lineno"> 17</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L18"></a><tt class="py-lineno"> 18</tt> <tt class="py-line"><tt class="py-docstring">:License:</tt> </tt>
+<a name="L19"></a><tt class="py-lineno"> 19</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L20"></a><tt class="py-lineno"> 20</tt> <tt class="py-line"><tt class="py-docstring"> Licensed under the Apache License, Version 2.0 (the "License");</tt> </tt>
+<a name="L21"></a><tt class="py-lineno"> 21</tt> <tt class="py-line"><tt class="py-docstring"> you may not use this file except in compliance with the License.</tt> </tt>
+<a name="L22"></a><tt class="py-lineno"> 22</tt> <tt class="py-line"><tt class="py-docstring"> You may obtain a copy of the License at</tt> </tt>
+<a name="L23"></a><tt class="py-lineno"> 23</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L24"></a><tt class="py-lineno"> 24</tt> <tt class="py-line"><tt class="py-docstring"> http://www.apache.org/licenses/LICENSE-2.0</tt> </tt>
+<a name="L25"></a><tt class="py-lineno"> 25</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L26"></a><tt class="py-lineno"> 26</tt> <tt class="py-line"><tt class="py-docstring"> Unless required by applicable law or agreed to in writing, software</tt> </tt>
+<a name="L27"></a><tt class="py-lineno"> 27</tt> <tt class="py-line"><tt class="py-docstring"> distributed under the License is distributed on an "AS IS" BASIS,</tt> </tt>
+<a name="L28"></a><tt class="py-lineno"> 28</tt> <tt class="py-line"><tt class="py-docstring"> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</tt> </tt>
+<a name="L29"></a><tt class="py-lineno"> 29</tt> <tt class="py-line"><tt class="py-docstring"> See the License for the specific language governing permissions and</tt> </tt>
+<a name="L30"></a><tt class="py-lineno"> 30</tt> <tt class="py-line"><tt class="py-docstring"> limitations under the License.</tt> </tt>
+<a name="L31"></a><tt class="py-lineno"> 31</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L32"></a><tt class="py-lineno"> 32</tt> <tt class="py-line"><tt class="py-docstring">This module is a re-implementation aiming for speed instead of maximum</tt> </tt>
+<a name="L33"></a><tt class="py-lineno"> 33</tt> <tt class="py-line"><tt class="py-docstring">compression, so it can be used at runtime (rather than during a preprocessing</tt> </tt>
+<a name="L34"></a><tt class="py-lineno"> 34</tt> <tt class="py-line"><tt class="py-docstring">step). RCSSmin does syntactical compression only (removing spaces, comments</tt> </tt>
+<a name="L35"></a><tt class="py-lineno"> 35</tt> <tt class="py-line"><tt class="py-docstring">and possibly semicolons). It does not provide semantic compression (like</tt> </tt>
+<a name="L36"></a><tt class="py-lineno"> 36</tt> <tt class="py-line"><tt class="py-docstring">removing empty blocks, collapsing redundant properties etc). It does, however,</tt> </tt>
+<a name="L37"></a><tt class="py-lineno"> 37</tt> <tt class="py-line"><tt class="py-docstring">support various CSS hacks (by keeping them working as intended).</tt> </tt>
+<a name="L38"></a><tt class="py-lineno"> 38</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L39"></a><tt class="py-lineno"> 39</tt> <tt class="py-line"><tt class="py-docstring">Here's a feature list:</tt> </tt>
+<a name="L40"></a><tt class="py-lineno"> 40</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L41"></a><tt class="py-lineno"> 41</tt> <tt class="py-line"><tt class="py-docstring">- Strings are kept, except that escaped newlines are stripped</tt> </tt>
+<a name="L42"></a><tt class="py-lineno"> 42</tt> <tt class="py-line"><tt class="py-docstring">- Space/Comments before the very end or before various characters are</tt> </tt>
+<a name="L43"></a><tt class="py-lineno"> 43</tt> <tt class="py-line"><tt class="py-docstring"> stripped: ``:{});=&gt;+],!`` (The colon (``:``) is a special case, a single</tt> </tt>
+<a name="L44"></a><tt class="py-lineno"> 44</tt> <tt class="py-line"><tt class="py-docstring"> space is kept if it's outside a ruleset.)</tt> </tt>
+<a name="L45"></a><tt class="py-lineno"> 45</tt> <tt class="py-line"><tt class="py-docstring">- Space/Comments at the very beginning or after various characters are</tt> </tt>
+<a name="L46"></a><tt class="py-lineno"> 46</tt> <tt class="py-line"><tt class="py-docstring"> stripped: ``{}(=:&gt;+[,!``</tt> </tt>
+<a name="L47"></a><tt class="py-lineno"> 47</tt> <tt class="py-line"><tt class="py-docstring">- Optional space after unicode escapes is kept, resp. replaced by a simple</tt> </tt>
+<a name="L48"></a><tt class="py-lineno"> 48</tt> <tt class="py-line"><tt class="py-docstring"> space</tt> </tt>
+<a name="L49"></a><tt class="py-lineno"> 49</tt> <tt class="py-line"><tt class="py-docstring">- whitespaces inside ``url()`` definitions are stripped</tt> </tt>
+<a name="L50"></a><tt class="py-lineno"> 50</tt> <tt class="py-line"><tt class="py-docstring">- Comments starting with an exclamation mark (``!``) can be kept optionally.</tt> </tt>
+<a name="L51"></a><tt class="py-lineno"> 51</tt> <tt class="py-line"><tt class="py-docstring">- All other comments and/or whitespace characters are replaced by a single</tt> </tt>
+<a name="L52"></a><tt class="py-lineno"> 52</tt> <tt class="py-line"><tt class="py-docstring"> space.</tt> </tt>
+<a name="L53"></a><tt class="py-lineno"> 53</tt> <tt class="py-line"><tt class="py-docstring">- Multiple consecutive semicolons are reduced to one</tt> </tt>
+<a name="L54"></a><tt class="py-lineno"> 54</tt> <tt class="py-line"><tt class="py-docstring">- The last semicolon within a ruleset is stripped</tt> </tt>
+<a name="L55"></a><tt class="py-lineno"> 55</tt> <tt class="py-line"><tt class="py-docstring">- CSS Hacks supported:</tt> </tt>
+<a name="L56"></a><tt class="py-lineno"> 56</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L57"></a><tt class="py-lineno"> 57</tt> <tt class="py-line"><tt class="py-docstring"> - IE7 hack (``&gt;/**/``)</tt> </tt>
+<a name="L58"></a><tt class="py-lineno"> 58</tt> <tt class="py-line"><tt class="py-docstring"> - Mac-IE5 hack (``/*\\*/.../**/``)</tt> </tt>
+<a name="L59"></a><tt class="py-lineno"> 59</tt> <tt class="py-line"><tt class="py-docstring"> - The boxmodelhack is supported naturally because it relies on valid CSS2</tt> </tt>
+<a name="L60"></a><tt class="py-lineno"> 60</tt> <tt class="py-line"><tt class="py-docstring"> strings</tt> </tt>
+<a name="L61"></a><tt class="py-lineno"> 61</tt> <tt class="py-line"><tt class="py-docstring"> - Between ``:first-line`` and the following comma or curly brace a space is</tt> </tt>
+<a name="L62"></a><tt class="py-lineno"> 62</tt> <tt class="py-line"><tt class="py-docstring"> inserted. (apparently it's needed for IE6)</tt> </tt>
+<a name="L63"></a><tt class="py-lineno"> 63</tt> <tt class="py-line"><tt class="py-docstring"> - Same for ``:first-letter``</tt> </tt>
+<a name="L64"></a><tt class="py-lineno"> 64</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L65"></a><tt class="py-lineno"> 65</tt> <tt class="py-line"><tt class="py-docstring">rcssmin.c is a reimplementation of rcssmin.py in C and improves runtime up to</tt> </tt>
+<a name="L66"></a><tt class="py-lineno"> 66</tt> <tt class="py-line"><tt class="py-docstring">factor 100 or so (depending on the input). docs/BENCHMARKS in the source</tt> </tt>
+<a name="L67"></a><tt class="py-lineno"> 67</tt> <tt class="py-line"><tt class="py-docstring">distribution contains the details.</tt> </tt>
+<a name="L68"></a><tt class="py-lineno"> 68</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L69"></a><tt class="py-lineno"> 69</tt> <tt class="py-line"><tt class="py-docstring">Both python 2 (&gt;= 2.4) and python 3 are supported.</tt> </tt>
+<a name="L70"></a><tt class="py-lineno"> 70</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L71"></a><tt class="py-lineno"> 71</tt> <tt class="py-line"><tt class="py-docstring">.. _YUI compressor: https://github.com/yui/yuicompressor/</tt> </tt>
+<a name="L72"></a><tt class="py-lineno"> 72</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L73"></a><tt class="py-lineno"> 73</tt> <tt class="py-line"><tt class="py-docstring">.. _the rule list by Isaac Schlueter: https://github.com/isaacs/cssmin/</tt> </tt>
+<a name="L74"></a><tt class="py-lineno"> 74</tt> <tt class="py-line"><tt class="py-docstring">"""</tt> </tt>
+<a name="L75"></a><tt class="py-lineno"> 75</tt> <tt class="py-line"><tt class="py-keyword">if</tt> <tt id="link-0" class="py-name" targets="Variable rcssmin.__doc__=rcssmin-module.html#__doc__"><a title="rcssmin.__doc__" class="py-name" href="#" onclick="return doclink('link-0', '__doc__', 'link-0');">__doc__</a></tt><tt class="py-op">:</tt> </tt>
+<a name="L76"></a><tt class="py-lineno"> 76</tt> <tt class="py-line"> <tt class="py-comment"># pylint: disable = W0622</tt> </tt>
+<a name="L77"></a><tt class="py-lineno"> 77</tt> <tt class="py-line"> <tt id="link-1" class="py-name"><a title="rcssmin.__doc__" class="py-name" href="#" onclick="return doclink('link-1', '__doc__', 'link-0');">__doc__</a></tt> <tt class="py-op">=</tt> <tt id="link-2" class="py-name"><a title="rcssmin.__doc__" class="py-name" href="#" onclick="return doclink('link-2', '__doc__', 'link-0');">__doc__</a></tt><tt class="py-op">.</tt><tt class="py-name">encode</tt><tt class="py-op">(</tt><tt class="py-string">'ascii'</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">decode</tt><tt class="py-op">(</tt><tt class="py-string">'unicode_escape'</tt><tt class="py-op">)</tt> </tt>
+<a name="L78"></a><tt class="py-lineno"> 78</tt> <tt class="py-line"><tt class="py-name">__author__</tt> <tt class="py-op">=</tt> <tt class="py-string">r"Andr\xe9 Malo"</tt><tt class="py-op">.</tt><tt class="py-name">encode</tt><tt class="py-op">(</tt><tt class="py-string">'ascii'</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">decode</tt><tt class="py-op">(</tt><tt class="py-string">'unicode_escape'</tt><tt class="py-op">)</tt> </tt>
+<a name="L79"></a><tt class="py-lineno"> 79</tt> <tt class="py-line"><tt class="py-name">__docformat__</tt> <tt class="py-op">=</tt> <tt class="py-string">"restructuredtext en"</tt> </tt>
+<a name="L80"></a><tt class="py-lineno"> 80</tt> <tt class="py-line"><tt id="link-3" class="py-name" targets="Variable rcssmin.__license__=rcssmin-module.html#__license__"><a title="rcssmin.__license__" class="py-name" href="#" onclick="return doclink('link-3', '__license__', 'link-3');">__license__</a></tt> <tt class="py-op">=</tt> <tt class="py-string">"Apache License, Version 2.0"</tt> </tt>
+<a name="L81"></a><tt class="py-lineno"> 81</tt> <tt class="py-line"><tt class="py-name">__version__</tt> <tt class="py-op">=</tt> <tt class="py-string">'1.0.5'</tt> </tt>
+<a name="L82"></a><tt class="py-lineno"> 82</tt> <tt class="py-line"><tt class="py-name">__all__</tt> <tt class="py-op">=</tt> <tt class="py-op">[</tt><tt class="py-string">'cssmin'</tt><tt class="py-op">]</tt> </tt>
+<a name="L83"></a><tt class="py-lineno"> 83</tt> <tt class="py-line"> </tt>
+<a name="L84"></a><tt class="py-lineno"> 84</tt> <tt class="py-line"><tt class="py-keyword">import</tt> <tt class="py-name">re</tt> <tt class="py-keyword">as</tt> <tt class="py-name">_re</tt> </tt>
+<a name="L85"></a><tt class="py-lineno"> 85</tt> <tt class="py-line"> </tt>
+<a name="L86"></a><tt class="py-lineno"> 86</tt> <tt class="py-line"> </tt>
+<a name="_make_cssmin"></a><div id="_make_cssmin-def"><a name="L87"></a><tt class="py-lineno"> 87</tt> <a class="py-toggle" href="#" id="_make_cssmin-toggle" onclick="return toggle('_make_cssmin');">-</a><tt class="py-line"><tt class="py-keyword">def</tt> <a class="py-def-name" href="rcssmin-module.html#_make_cssmin">_make_cssmin</a><tt class="py-op">(</tt><tt class="py-param">python_only</tt><tt class="py-op">=</tt><tt class="py-name">False</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+</div><div id="_make_cssmin-collapsed" style="display:none;" pad="+++" indent="++++"></div><div id="_make_cssmin-expanded"><a name="L88"></a><tt class="py-lineno"> 88</tt> <tt class="py-line"> <tt class="py-docstring">"""</tt> </tt>
+<a name="L89"></a><tt class="py-lineno"> 89</tt> <tt class="py-line"><tt class="py-docstring"> Generate CSS minifier.</tt> </tt>
+<a name="L90"></a><tt class="py-lineno"> 90</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L91"></a><tt class="py-lineno"> 91</tt> <tt class="py-line"><tt class="py-docstring"> :Parameters:</tt> </tt>
+<a name="L92"></a><tt class="py-lineno"> 92</tt> <tt class="py-line"><tt class="py-docstring"> `python_only` : ``bool``</tt> </tt>
+<a name="L93"></a><tt class="py-lineno"> 93</tt> <tt class="py-line"><tt class="py-docstring"> Use only the python variant. If true, the c extension is not even</tt> </tt>
+<a name="L94"></a><tt class="py-lineno"> 94</tt> <tt class="py-line"><tt class="py-docstring"> tried to be loaded.</tt> </tt>
+<a name="L95"></a><tt class="py-lineno"> 95</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L96"></a><tt class="py-lineno"> 96</tt> <tt class="py-line"><tt class="py-docstring"> :Return: Minifier</tt> </tt>
+<a name="L97"></a><tt class="py-lineno"> 97</tt> <tt class="py-line"><tt class="py-docstring"> :Rtype: ``callable``</tt> </tt>
+<a name="L98"></a><tt class="py-lineno"> 98</tt> <tt class="py-line"><tt class="py-docstring"> """</tt> </tt>
+<a name="L99"></a><tt class="py-lineno"> 99</tt> <tt class="py-line"> <tt class="py-comment"># pylint: disable = R0912, R0914, W0612</tt> </tt>
+<a name="L100"></a><tt class="py-lineno">100</tt> <tt class="py-line"> </tt>
+<a name="L101"></a><tt class="py-lineno">101</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-keyword">not</tt> <tt class="py-name">python_only</tt><tt class="py-op">:</tt> </tt>
+<a name="L102"></a><tt class="py-lineno">102</tt> <tt class="py-line"> <tt class="py-keyword">try</tt><tt class="py-op">:</tt> </tt>
+<a name="L103"></a><tt class="py-lineno">103</tt> <tt class="py-line"> <tt class="py-keyword">import</tt> <tt class="py-name">_rcssmin</tt> </tt>
+<a name="L104"></a><tt class="py-lineno">104</tt> <tt class="py-line"> <tt class="py-keyword">except</tt> <tt class="py-name">ImportError</tt><tt class="py-op">:</tt> </tt>
+<a name="L105"></a><tt class="py-lineno">105</tt> <tt class="py-line"> <tt class="py-keyword">pass</tt> </tt>
+<a name="L106"></a><tt class="py-lineno">106</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L107"></a><tt class="py-lineno">107</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">_rcssmin</tt><tt class="py-op">.</tt><tt id="link-4" class="py-name" targets="Function rcssmin.cssmin()=rcssmin-module.html#cssmin"><a title="rcssmin.cssmin" class="py-name" href="#" onclick="return doclink('link-4', 'cssmin', 'link-4');">cssmin</a></tt> </tt>
+<a name="L108"></a><tt class="py-lineno">108</tt> <tt class="py-line"> </tt>
+<a name="L109"></a><tt class="py-lineno">109</tt> <tt class="py-line"> <tt class="py-name">nl</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:[\n\f]|\r\n?)'</tt> <tt class="py-comment"># pylint: disable = C0103</tt> </tt>
+<a name="L110"></a><tt class="py-lineno">110</tt> <tt class="py-line"> <tt class="py-name">spacechar</tt> <tt class="py-op">=</tt> <tt class="py-string">r'[\r\n\f\040\t]'</tt> </tt>
+<a name="L111"></a><tt class="py-lineno">111</tt> <tt class="py-line"> </tt>
+<a name="L112"></a><tt class="py-lineno">112</tt> <tt class="py-line"> <tt class="py-name">unicoded</tt> <tt class="py-op">=</tt> <tt class="py-string">r'[0-9a-fA-F]{1,6}(?:[\040\n\t\f]|\r\n?)?'</tt> </tt>
+<a name="L113"></a><tt class="py-lineno">113</tt> <tt class="py-line"> <tt class="py-name">escaped</tt> <tt class="py-op">=</tt> <tt class="py-string">r'[^\n\r\f0-9a-fA-F]'</tt> </tt>
+<a name="L114"></a><tt class="py-lineno">114</tt> <tt class="py-line"> <tt class="py-name">escape</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:\\(?:%(unicoded)s|%(escaped)s))'</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L115"></a><tt class="py-lineno">115</tt> <tt class="py-line"> </tt>
+<a name="L116"></a><tt class="py-lineno">116</tt> <tt class="py-line"> <tt class="py-name">nmchar</tt> <tt class="py-op">=</tt> <tt class="py-string">r'[^\000-\054\056\057\072-\100\133-\136\140\173-\177]'</tt> </tt>
+<a name="L117"></a><tt class="py-lineno">117</tt> <tt class="py-line"> <tt class="py-comment">#nmstart = r'[^\000-\100\133-\136\140\173-\177]'</tt> </tt>
+<a name="L118"></a><tt class="py-lineno">118</tt> <tt class="py-line"> <tt class="py-comment">#ident = (r'(?:'</tt> </tt>
+<a name="L119"></a><tt class="py-lineno">119</tt> <tt class="py-line"> <tt class="py-comment"># r'-?(?:%(nmstart)s|%(escape)s)%(nmchar)s*(?:%(escape)s%(nmchar)s*)*'</tt> </tt>
+<a name="L120"></a><tt class="py-lineno">120</tt> <tt class="py-line"> <tt class="py-comment">#r')') % locals()</tt> </tt>
+<a name="L121"></a><tt class="py-lineno">121</tt> <tt class="py-line"> </tt>
+<a name="L122"></a><tt class="py-lineno">122</tt> <tt class="py-line"> <tt class="py-name">comment</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'</tt> </tt>
+<a name="L123"></a><tt class="py-lineno">123</tt> <tt class="py-line"> </tt>
+<a name="L124"></a><tt class="py-lineno">124</tt> <tt class="py-line"> <tt class="py-comment"># only for specific purposes. The bang is grouped:</tt> </tt>
+<a name="L125"></a><tt class="py-lineno">125</tt> <tt class="py-line"> <tt class="py-name">_bang_comment</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:/\*(!?)[^*]*\*+(?:[^/*][^*]*\*+)*/)'</tt> </tt>
+<a name="L126"></a><tt class="py-lineno">126</tt> <tt class="py-line"> </tt>
+<a name="L127"></a><tt class="py-lineno">127</tt> <tt class="py-line"> <tt class="py-name">string1</tt> <tt class="py-op">=</tt> \ </tt>
+<a name="L128"></a><tt class="py-lineno">128</tt> <tt class="py-line"> <tt class="py-string">r'(?:\047[^\047\\\r\n\f]*(?:\\[^\r\n\f][^\047\\\r\n\f]*)*\047)'</tt> </tt>
+<a name="L129"></a><tt class="py-lineno">129</tt> <tt class="py-line"> <tt class="py-name">string2</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:"[^"\\\r\n\f]*(?:\\[^\r\n\f][^"\\\r\n\f]*)*")'</tt> </tt>
+<a name="L130"></a><tt class="py-lineno">130</tt> <tt class="py-line"> <tt class="py-name">strings</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:%s|%s)'</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt><tt class="py-name">string1</tt><tt class="py-op">,</tt> <tt class="py-name">string2</tt><tt class="py-op">)</tt> </tt>
+<a name="L131"></a><tt class="py-lineno">131</tt> <tt class="py-line"> </tt>
+<a name="L132"></a><tt class="py-lineno">132</tt> <tt class="py-line"> <tt class="py-name">nl_string1</tt> <tt class="py-op">=</tt> \ </tt>
+<a name="L133"></a><tt class="py-lineno">133</tt> <tt class="py-line"> <tt class="py-string">r'(?:\047[^\047\\\r\n\f]*(?:\\(?:[^\r]|\r\n?)[^\047\\\r\n\f]*)*\047)'</tt> </tt>
+<a name="L134"></a><tt class="py-lineno">134</tt> <tt class="py-line"> <tt class="py-name">nl_string2</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:"[^"\\\r\n\f]*(?:\\(?:[^\r]|\r\n?)[^"\\\r\n\f]*)*")'</tt> </tt>
+<a name="L135"></a><tt class="py-lineno">135</tt> <tt class="py-line"> <tt class="py-name">nl_strings</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:%s|%s)'</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt><tt class="py-name">nl_string1</tt><tt class="py-op">,</tt> <tt class="py-name">nl_string2</tt><tt class="py-op">)</tt> </tt>
+<a name="L136"></a><tt class="py-lineno">136</tt> <tt class="py-line"> </tt>
+<a name="L137"></a><tt class="py-lineno">137</tt> <tt class="py-line"> <tt class="py-name">uri_nl_string1</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:\047[^\047\\]*(?:\\(?:[^\r]|\r\n?)[^\047\\]*)*\047)'</tt> </tt>
+<a name="L138"></a><tt class="py-lineno">138</tt> <tt class="py-line"> <tt class="py-name">uri_nl_string2</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:"[^"\\]*(?:\\(?:[^\r]|\r\n?)[^"\\]*)*")'</tt> </tt>
+<a name="L139"></a><tt class="py-lineno">139</tt> <tt class="py-line"> <tt class="py-name">uri_nl_strings</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:%s|%s)'</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt><tt class="py-name">uri_nl_string1</tt><tt class="py-op">,</tt> <tt class="py-name">uri_nl_string2</tt><tt class="py-op">)</tt> </tt>
+<a name="L140"></a><tt class="py-lineno">140</tt> <tt class="py-line"> </tt>
+<a name="L141"></a><tt class="py-lineno">141</tt> <tt class="py-line"> <tt class="py-name">nl_escaped</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:\\%(nl)s)'</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L142"></a><tt class="py-lineno">142</tt> <tt class="py-line"> </tt>
+<a name="L143"></a><tt class="py-lineno">143</tt> <tt class="py-line"> <tt class="py-name">space</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:%(spacechar)s|%(comment)s)'</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L144"></a><tt class="py-lineno">144</tt> <tt class="py-line"> </tt>
+<a name="L145"></a><tt class="py-lineno">145</tt> <tt class="py-line"> <tt class="py-name">ie7hack</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:&gt;/\*\*/)'</tt> </tt>
+<a name="L146"></a><tt class="py-lineno">146</tt> <tt class="py-line"> </tt>
+<a name="L147"></a><tt class="py-lineno">147</tt> <tt class="py-line"> <tt class="py-name">uri</tt> <tt class="py-op">=</tt> <tt class="py-op">(</tt><tt class="py-string">r'(?:'</tt> </tt>
+<a name="L148"></a><tt class="py-lineno">148</tt> <tt class="py-line"> <tt class="py-comment"># noqa pylint: disable = C0330</tt> </tt>
+<a name="L149"></a><tt class="py-lineno">149</tt> <tt class="py-line"> <tt class="py-string">r'(?:[^\000-\040"\047()\\\177]*'</tt> </tt>
+<a name="L150"></a><tt class="py-lineno">150</tt> <tt class="py-line"> <tt class="py-string">r'(?:%(escape)s[^\000-\040"\047()\\\177]*)*)'</tt> </tt>
+<a name="L151"></a><tt class="py-lineno">151</tt> <tt class="py-line"> <tt class="py-string">r'(?:'</tt> </tt>
+<a name="L152"></a><tt class="py-lineno">152</tt> <tt class="py-line"> <tt class="py-string">r'(?:%(spacechar)s+|%(nl_escaped)s+)'</tt> </tt>
+<a name="L153"></a><tt class="py-lineno">153</tt> <tt class="py-line"> <tt class="py-string">r'(?:'</tt> </tt>
+<a name="L154"></a><tt class="py-lineno">154</tt> <tt class="py-line"> <tt class="py-string">r'(?:[^\000-\040"\047()\\\177]|%(escape)s|%(nl_escaped)s)'</tt> </tt>
+<a name="L155"></a><tt class="py-lineno">155</tt> <tt class="py-line"> <tt class="py-string">r'[^\000-\040"\047()\\\177]*'</tt> </tt>
+<a name="L156"></a><tt class="py-lineno">156</tt> <tt class="py-line"> <tt class="py-string">r'(?:%(escape)s[^\000-\040"\047()\\\177]*)*'</tt> </tt>
+<a name="L157"></a><tt class="py-lineno">157</tt> <tt class="py-line"> <tt class="py-string">r')+'</tt> </tt>
+<a name="L158"></a><tt class="py-lineno">158</tt> <tt class="py-line"> <tt class="py-string">r')*'</tt> </tt>
+<a name="L159"></a><tt class="py-lineno">159</tt> <tt class="py-line"> <tt class="py-string">r')'</tt><tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L160"></a><tt class="py-lineno">160</tt> <tt class="py-line"> </tt>
+<a name="L161"></a><tt class="py-lineno">161</tt> <tt class="py-line"> <tt class="py-name">nl_unesc_sub</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-name">nl_escaped</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L162"></a><tt class="py-lineno">162</tt> <tt class="py-line"> </tt>
+<a name="L163"></a><tt class="py-lineno">163</tt> <tt class="py-line"> <tt class="py-name">uri_space_sub</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-op">(</tt> </tt>
+<a name="L164"></a><tt class="py-lineno">164</tt> <tt class="py-line"> <tt class="py-string">r'(%(escape)s+)|%(spacechar)s+|%(nl_escaped)s+'</tt> </tt>
+<a name="L165"></a><tt class="py-lineno">165</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L166"></a><tt class="py-lineno">166</tt> <tt class="py-line"> <tt class="py-name">uri_space_subber</tt> <tt class="py-op">=</tt> <tt class="py-keyword">lambda</tt> <tt class="py-name">m</tt><tt class="py-op">:</tt> <tt class="py-name">m</tt><tt class="py-op">.</tt><tt class="py-name">groups</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt> </tt>
+<a name="L167"></a><tt class="py-lineno">167</tt> <tt class="py-line"> </tt>
+<a name="L168"></a><tt class="py-lineno">168</tt> <tt class="py-line"> <tt class="py-name">space_sub_simple</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-op">(</tt> </tt>
+<a name="L169"></a><tt class="py-lineno">169</tt> <tt class="py-line"> <tt class="py-string">r'[\r\n\f\040\t;]+|(%(comment)s+)'</tt> </tt>
+<a name="L170"></a><tt class="py-lineno">170</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L171"></a><tt class="py-lineno">171</tt> <tt class="py-line"> <tt class="py-name">space_sub_banged</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-op">(</tt> </tt>
+<a name="L172"></a><tt class="py-lineno">172</tt> <tt class="py-line"> <tt class="py-string">r'[\r\n\f\040\t;]+|(%(_bang_comment)s+)'</tt> </tt>
+<a name="L173"></a><tt class="py-lineno">173</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L174"></a><tt class="py-lineno">174</tt> <tt class="py-line"> </tt>
+<a name="L175"></a><tt class="py-lineno">175</tt> <tt class="py-line"> <tt class="py-name">post_esc_sub</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-string">r'[\r\n\f\t]+'</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L176"></a><tt class="py-lineno">176</tt> <tt class="py-line"> </tt>
+<a name="L177"></a><tt class="py-lineno">177</tt> <tt class="py-line"> <tt class="py-name">main_sub</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-op">(</tt> </tt>
+<a name="L178"></a><tt class="py-lineno">178</tt> <tt class="py-line"> <tt class="py-comment"># noqa pylint: disable = C0330</tt> </tt>
+<a name="L179"></a><tt class="py-lineno">179</tt> <tt class="py-line"> <tt class="py-string">r'([^\\"\047u&gt;@\r\n\f\040\t/;:{}]+)'</tt> </tt>
+<a name="L180"></a><tt class="py-lineno">180</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=[{}(=:&gt;+[,!])(%(space)s+)'</tt> </tt>
+<a name="L181"></a><tt class="py-lineno">181</tt> <tt class="py-line"> <tt class="py-string">r'|^(%(space)s+)'</tt> </tt>
+<a name="L182"></a><tt class="py-lineno">182</tt> <tt class="py-line"> <tt class="py-string">r'|(%(space)s+)(?=(([:{});=&gt;+\],!])|$)?)'</tt> </tt>
+<a name="L183"></a><tt class="py-lineno">183</tt> <tt class="py-line"> <tt class="py-string">r'|;(%(space)s*(?:;%(space)s*)*)(?=(\})?)'</tt> </tt>
+<a name="L184"></a><tt class="py-lineno">184</tt> <tt class="py-line"> <tt class="py-string">r'|(\{)'</tt> </tt>
+<a name="L185"></a><tt class="py-lineno">185</tt> <tt class="py-line"> <tt class="py-string">r'|(\})'</tt> </tt>
+<a name="L186"></a><tt class="py-lineno">186</tt> <tt class="py-line"> <tt class="py-string">r'|(%(strings)s)'</tt> </tt>
+<a name="L187"></a><tt class="py-lineno">187</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;!%(nmchar)s)url\(%(spacechar)s*('</tt> </tt>
+<a name="L188"></a><tt class="py-lineno">188</tt> <tt class="py-line"> <tt class="py-string">r'%(uri_nl_strings)s'</tt> </tt>
+<a name="L189"></a><tt class="py-lineno">189</tt> <tt class="py-line"> <tt class="py-string">r'|%(uri)s'</tt> </tt>
+<a name="L190"></a><tt class="py-lineno">190</tt> <tt class="py-line"> <tt class="py-string">r')%(spacechar)s*\)'</tt> </tt>
+<a name="L191"></a><tt class="py-lineno">191</tt> <tt class="py-line"> <tt class="py-string">r'|(@(?:'</tt> </tt>
+<a name="L192"></a><tt class="py-lineno">192</tt> <tt class="py-line"> <tt class="py-string">r'[mM][eE][dD][iI][aA]'</tt> </tt>
+<a name="L193"></a><tt class="py-lineno">193</tt> <tt class="py-line"> <tt class="py-string">r'|[sS][uU][pP][pP][oO][rR][tT][sS]'</tt> </tt>
+<a name="L194"></a><tt class="py-lineno">194</tt> <tt class="py-line"> <tt class="py-string">r'|[dD][oO][cC][uU][mM][eE][nN][tT]'</tt> </tt>
+<a name="L195"></a><tt class="py-lineno">195</tt> <tt class="py-line"> <tt class="py-string">r'|(?:-(?:'</tt> </tt>
+<a name="L196"></a><tt class="py-lineno">196</tt> <tt class="py-line"> <tt class="py-string">r'[wW][eE][bB][kK][iI][tT]|[mM][oO][zZ]|[oO]|[mM][sS]'</tt> </tt>
+<a name="L197"></a><tt class="py-lineno">197</tt> <tt class="py-line"> <tt class="py-string">r')-)?'</tt> </tt>
+<a name="L198"></a><tt class="py-lineno">198</tt> <tt class="py-line"> <tt class="py-string">r'[kK][eE][yY][fF][rR][aA][mM][eE][sS]'</tt> </tt>
+<a name="L199"></a><tt class="py-lineno">199</tt> <tt class="py-line"> <tt class="py-string">r'))(?!%(nmchar)s)'</tt> </tt>
+<a name="L200"></a><tt class="py-lineno">200</tt> <tt class="py-line"> <tt class="py-string">r'|(%(ie7hack)s)(%(space)s*)'</tt> </tt>
+<a name="L201"></a><tt class="py-lineno">201</tt> <tt class="py-line"> <tt class="py-string">r'|(:[fF][iI][rR][sS][tT]-[lL]'</tt> </tt>
+<a name="L202"></a><tt class="py-lineno">202</tt> <tt class="py-line"> <tt class="py-string">r'(?:[iI][nN][eE]|[eE][tT][tT][eE][rR]))'</tt> </tt>
+<a name="L203"></a><tt class="py-lineno">203</tt> <tt class="py-line"> <tt class="py-string">r'(%(space)s*)(?=[{,])'</tt> </tt>
+<a name="L204"></a><tt class="py-lineno">204</tt> <tt class="py-line"> <tt class="py-string">r'|(%(nl_strings)s)'</tt> </tt>
+<a name="L205"></a><tt class="py-lineno">205</tt> <tt class="py-line"> <tt class="py-string">r'|(%(escape)s[^\\"\047u&gt;@\r\n\f\040\t/;:{}]*)'</tt> </tt>
+<a name="L206"></a><tt class="py-lineno">206</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L207"></a><tt class="py-lineno">207</tt> <tt class="py-line"> </tt>
+<a name="L208"></a><tt class="py-lineno">208</tt> <tt class="py-line"> <tt class="py-comment">#print main_sub.__self__.pattern</tt> </tt>
+<a name="L209"></a><tt class="py-lineno">209</tt> <tt class="py-line"> </tt>
+<a name="L210"></a><tt class="py-lineno">210</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">main_subber</tt><tt class="py-op">(</tt><tt class="py-param">keep_bang_comments</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L211"></a><tt class="py-lineno">211</tt> <tt class="py-line"> <tt class="py-docstring">""" Make main subber """</tt> </tt>
+<a name="L212"></a><tt class="py-lineno">212</tt> <tt class="py-line"> <tt class="py-name">in_macie5</tt><tt class="py-op">,</tt> <tt class="py-name">in_rule</tt><tt class="py-op">,</tt> <tt class="py-name">at_group</tt> <tt class="py-op">=</tt> <tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> <tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> <tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> </tt>
+<a name="L213"></a><tt class="py-lineno">213</tt> <tt class="py-line"> </tt>
+<a name="L214"></a><tt class="py-lineno">214</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">keep_bang_comments</tt><tt class="py-op">:</tt> </tt>
+<a name="L215"></a><tt class="py-lineno">215</tt> <tt class="py-line"> <tt class="py-name">space_sub</tt> <tt class="py-op">=</tt> <tt class="py-name">space_sub_banged</tt> </tt>
+<a name="L216"></a><tt class="py-lineno">216</tt> <tt class="py-line"> </tt>
+<a name="L217"></a><tt class="py-lineno">217</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">space_subber</tt><tt class="py-op">(</tt><tt class="py-param">match</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L218"></a><tt class="py-lineno">218</tt> <tt class="py-line"> <tt class="py-docstring">""" Space|Comment subber """</tt> </tt>
+<a name="L219"></a><tt class="py-lineno">219</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">lastindex</tt><tt class="py-op">:</tt> </tt>
+<a name="L220"></a><tt class="py-lineno">220</tt> <tt class="py-line"> <tt class="py-name">group1</tt><tt class="py-op">,</tt> <tt class="py-name">group2</tt> <tt class="py-op">=</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">1</tt><tt class="py-op">,</tt> <tt class="py-number">2</tt><tt class="py-op">)</tt> </tt>
+<a name="L221"></a><tt class="py-lineno">221</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">group2</tt><tt class="py-op">:</tt> </tt>
+<a name="L222"></a><tt class="py-lineno">222</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">group1</tt><tt class="py-op">.</tt><tt class="py-name">endswith</tt><tt class="py-op">(</tt><tt class="py-string">r'\*/'</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L223"></a><tt class="py-lineno">223</tt> <tt class="py-line"> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">1</tt> </tt>
+<a name="L224"></a><tt class="py-lineno">224</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L225"></a><tt class="py-lineno">225</tt> <tt class="py-line"> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">0</tt> </tt>
+<a name="L226"></a><tt class="py-lineno">226</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">group1</tt> </tt>
+<a name="L227"></a><tt class="py-lineno">227</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">group1</tt><tt class="py-op">:</tt> </tt>
+<a name="L228"></a><tt class="py-lineno">228</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">group1</tt><tt class="py-op">.</tt><tt class="py-name">endswith</tt><tt class="py-op">(</tt><tt class="py-string">r'\*/'</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L229"></a><tt class="py-lineno">229</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L230"></a><tt class="py-lineno">230</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">''</tt> </tt>
+<a name="L231"></a><tt class="py-lineno">231</tt> <tt class="py-line"> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">1</tt> </tt>
+<a name="L232"></a><tt class="py-lineno">232</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">r'/*\*/'</tt> </tt>
+<a name="L233"></a><tt class="py-lineno">233</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L234"></a><tt class="py-lineno">234</tt> <tt class="py-line"> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">0</tt> </tt>
+<a name="L235"></a><tt class="py-lineno">235</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">'/**/'</tt> </tt>
+<a name="L236"></a><tt class="py-lineno">236</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">''</tt> </tt>
+</div><a name="L237"></a><tt class="py-lineno">237</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L238"></a><tt class="py-lineno">238</tt> <tt class="py-line"> <tt class="py-name">space_sub</tt> <tt class="py-op">=</tt> <tt class="py-name">space_sub_simple</tt> </tt>
+<a name="L239"></a><tt class="py-lineno">239</tt> <tt class="py-line"> </tt>
+<a name="L240"></a><tt class="py-lineno">240</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">space_subber</tt><tt class="py-op">(</tt><tt class="py-param">match</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L241"></a><tt class="py-lineno">241</tt> <tt class="py-line"> <tt class="py-docstring">""" Space|Comment subber """</tt> </tt>
+<a name="L242"></a><tt class="py-lineno">242</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">lastindex</tt><tt class="py-op">:</tt> </tt>
+<a name="L243"></a><tt class="py-lineno">243</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">1</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">endswith</tt><tt class="py-op">(</tt><tt class="py-string">r'\*/'</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L244"></a><tt class="py-lineno">244</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L245"></a><tt class="py-lineno">245</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">''</tt> </tt>
+<a name="L246"></a><tt class="py-lineno">246</tt> <tt class="py-line"> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">1</tt> </tt>
+<a name="L247"></a><tt class="py-lineno">247</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">r'/*\*/'</tt> </tt>
+<a name="L248"></a><tt class="py-lineno">248</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L249"></a><tt class="py-lineno">249</tt> <tt class="py-line"> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">0</tt> </tt>
+<a name="L250"></a><tt class="py-lineno">250</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">'/**/'</tt> </tt>
+<a name="L251"></a><tt class="py-lineno">251</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">''</tt> </tt>
+</div><a name="L252"></a><tt class="py-lineno">252</tt> <tt class="py-line"> </tt>
+<a name="L253"></a><tt class="py-lineno">253</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">fn_space_post</tt><tt class="py-op">(</tt><tt class="py-param">group</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L254"></a><tt class="py-lineno">254</tt> <tt class="py-line"> <tt class="py-docstring">""" space with token after """</tt> </tt>
+<a name="L255"></a><tt class="py-lineno">255</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">5</tt><tt class="py-op">)</tt> <tt class="py-keyword">is</tt> <tt class="py-name">None</tt> <tt class="py-keyword">or</tt> <tt class="py-op">(</tt> </tt>
+<a name="L256"></a><tt class="py-lineno">256</tt> <tt class="py-line"> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">6</tt><tt class="py-op">)</tt> <tt class="py-op">==</tt> <tt class="py-string">':'</tt> <tt class="py-keyword">and</tt> <tt class="py-keyword">not</tt> <tt class="py-name">in_rule</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-keyword">not</tt> <tt class="py-name">at_group</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L257"></a><tt class="py-lineno">257</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">' '</tt> <tt class="py-op">+</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">4</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+<a name="L258"></a><tt class="py-lineno">258</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">4</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L259"></a><tt class="py-lineno">259</tt> <tt class="py-line"> </tt>
+<a name="L260"></a><tt class="py-lineno">260</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">fn_semicolon</tt><tt class="py-op">(</tt><tt class="py-param">group</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L261"></a><tt class="py-lineno">261</tt> <tt class="py-line"> <tt class="py-docstring">""" ; handler """</tt> </tt>
+<a name="L262"></a><tt class="py-lineno">262</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">';'</tt> <tt class="py-op">+</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">7</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L263"></a><tt class="py-lineno">263</tt> <tt class="py-line"> </tt>
+<a name="L264"></a><tt class="py-lineno">264</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">fn_semicolon2</tt><tt class="py-op">(</tt><tt class="py-param">group</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L265"></a><tt class="py-lineno">265</tt> <tt class="py-line"> <tt class="py-docstring">""" ; handler """</tt> </tt>
+<a name="L266"></a><tt class="py-lineno">266</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">in_rule</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L267"></a><tt class="py-lineno">267</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">7</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+<a name="L268"></a><tt class="py-lineno">268</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">';'</tt> <tt class="py-op">+</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">7</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L269"></a><tt class="py-lineno">269</tt> <tt class="py-line"> </tt>
+<a name="L270"></a><tt class="py-lineno">270</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">fn_open</tt><tt class="py-op">(</tt><tt class="py-param">_</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L271"></a><tt class="py-lineno">271</tt> <tt class="py-line"> <tt class="py-docstring">""" { handler """</tt> </tt>
+<a name="L272"></a><tt class="py-lineno">272</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">at_group</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L273"></a><tt class="py-lineno">273</tt> <tt class="py-line"> <tt class="py-name">at_group</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">-=</tt> <tt class="py-number">1</tt> </tt>
+<a name="L274"></a><tt class="py-lineno">274</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L275"></a><tt class="py-lineno">275</tt> <tt class="py-line"> <tt class="py-name">in_rule</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">1</tt> </tt>
+<a name="L276"></a><tt class="py-lineno">276</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">'{'</tt> </tt>
+</div><a name="L277"></a><tt class="py-lineno">277</tt> <tt class="py-line"> </tt>
+<a name="L278"></a><tt class="py-lineno">278</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">fn_close</tt><tt class="py-op">(</tt><tt class="py-param">_</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L279"></a><tt class="py-lineno">279</tt> <tt class="py-line"> <tt class="py-docstring">""" } handler """</tt> </tt>
+<a name="L280"></a><tt class="py-lineno">280</tt> <tt class="py-line"> <tt class="py-name">in_rule</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">0</tt> </tt>
+<a name="L281"></a><tt class="py-lineno">281</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">'}'</tt> </tt>
+</div><a name="L282"></a><tt class="py-lineno">282</tt> <tt class="py-line"> </tt>
+<a name="L283"></a><tt class="py-lineno">283</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">fn_at_group</tt><tt class="py-op">(</tt><tt class="py-param">group</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L284"></a><tt class="py-lineno">284</tt> <tt class="py-line"> <tt class="py-docstring">""" @xxx group handler """</tt> </tt>
+<a name="L285"></a><tt class="py-lineno">285</tt> <tt class="py-line"> <tt class="py-name">at_group</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">+=</tt> <tt class="py-number">1</tt> </tt>
+<a name="L286"></a><tt class="py-lineno">286</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">13</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L287"></a><tt class="py-lineno">287</tt> <tt class="py-line"> </tt>
+<a name="L288"></a><tt class="py-lineno">288</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">fn_ie7hack</tt><tt class="py-op">(</tt><tt class="py-param">group</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L289"></a><tt class="py-lineno">289</tt> <tt class="py-line"> <tt class="py-docstring">""" IE7 Hack handler """</tt> </tt>
+<a name="L290"></a><tt class="py-lineno">290</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-keyword">not</tt> <tt class="py-name">in_rule</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-keyword">not</tt> <tt class="py-name">at_group</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L291"></a><tt class="py-lineno">291</tt> <tt class="py-line"> <tt class="py-name">in_macie5</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-op">=</tt> <tt class="py-number">0</tt> </tt>
+<a name="L292"></a><tt class="py-lineno">292</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">14</tt><tt class="py-op">)</tt> <tt class="py-op">+</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">15</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+<a name="L293"></a><tt class="py-lineno">293</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">'&gt;'</tt> <tt class="py-op">+</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">15</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L294"></a><tt class="py-lineno">294</tt> <tt class="py-line"> </tt>
+<a name="L295"></a><tt class="py-lineno">295</tt> <tt class="py-line"> <tt class="py-name">table</tt> <tt class="py-op">=</tt> <tt class="py-op">(</tt> </tt>
+<a name="L296"></a><tt class="py-lineno">296</tt> <tt class="py-line"> <tt class="py-comment"># noqa pylint: disable = C0330</tt> </tt>
+<a name="L297"></a><tt class="py-lineno">297</tt> <tt class="py-line"> <tt class="py-name">None</tt><tt class="py-op">,</tt> </tt>
+<a name="L298"></a><tt class="py-lineno">298</tt> <tt class="py-line"> <tt class="py-name">None</tt><tt class="py-op">,</tt> </tt>
+<a name="L299"></a><tt class="py-lineno">299</tt> <tt class="py-line"> <tt class="py-name">None</tt><tt class="py-op">,</tt> </tt>
+<a name="L300"></a><tt class="py-lineno">300</tt> <tt class="py-line"> <tt class="py-name">None</tt><tt class="py-op">,</tt> </tt>
+<a name="L301"></a><tt class="py-lineno">301</tt> <tt class="py-line"> <tt class="py-name">fn_space_post</tt><tt class="py-op">,</tt> <tt class="py-comment"># space with token after</tt> </tt>
+<a name="L302"></a><tt class="py-lineno">302</tt> <tt class="py-line"> <tt class="py-name">fn_space_post</tt><tt class="py-op">,</tt> <tt class="py-comment"># space with token after</tt> </tt>
+<a name="L303"></a><tt class="py-lineno">303</tt> <tt class="py-line"> <tt class="py-name">fn_space_post</tt><tt class="py-op">,</tt> <tt class="py-comment"># space with token after</tt> </tt>
+<a name="L304"></a><tt class="py-lineno">304</tt> <tt class="py-line"> <tt class="py-name">fn_semicolon</tt><tt class="py-op">,</tt> <tt class="py-comment"># semicolon</tt> </tt>
+<a name="L305"></a><tt class="py-lineno">305</tt> <tt class="py-line"> <tt class="py-name">fn_semicolon2</tt><tt class="py-op">,</tt> <tt class="py-comment"># semicolon</tt> </tt>
+<a name="L306"></a><tt class="py-lineno">306</tt> <tt class="py-line"> <tt class="py-name">fn_open</tt><tt class="py-op">,</tt> <tt class="py-comment"># {</tt> </tt>
+<a name="L307"></a><tt class="py-lineno">307</tt> <tt class="py-line"> <tt class="py-name">fn_close</tt><tt class="py-op">,</tt> <tt class="py-comment"># }</tt> </tt>
+<a name="L308"></a><tt class="py-lineno">308</tt> <tt class="py-line"> <tt class="py-keyword">lambda</tt> <tt class="py-name">g</tt><tt class="py-op">:</tt> <tt class="py-name">g</tt><tt class="py-op">(</tt><tt class="py-number">11</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> <tt class="py-comment"># string</tt> </tt>
+<a name="L309"></a><tt class="py-lineno">309</tt> <tt class="py-line"> <tt class="py-keyword">lambda</tt> <tt class="py-name">g</tt><tt class="py-op">:</tt> <tt class="py-string">'url(%s)'</tt> <tt class="py-op">%</tt> <tt class="py-name">uri_space_sub</tt><tt class="py-op">(</tt><tt class="py-name">uri_space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">g</tt><tt class="py-op">(</tt><tt class="py-number">12</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L310"></a><tt class="py-lineno">310</tt> <tt class="py-line"> <tt class="py-comment"># url(...)</tt> </tt>
+<a name="L311"></a><tt class="py-lineno">311</tt> <tt class="py-line"> <tt class="py-name">fn_at_group</tt><tt class="py-op">,</tt> <tt class="py-comment"># @xxx expecting {...}</tt> </tt>
+<a name="L312"></a><tt class="py-lineno">312</tt> <tt class="py-line"> <tt class="py-name">None</tt><tt class="py-op">,</tt> </tt>
+<a name="L313"></a><tt class="py-lineno">313</tt> <tt class="py-line"> <tt class="py-name">fn_ie7hack</tt><tt class="py-op">,</tt> <tt class="py-comment"># ie7hack</tt> </tt>
+<a name="L314"></a><tt class="py-lineno">314</tt> <tt class="py-line"> <tt class="py-name">None</tt><tt class="py-op">,</tt> </tt>
+<a name="L315"></a><tt class="py-lineno">315</tt> <tt class="py-line"> <tt class="py-keyword">lambda</tt> <tt class="py-name">g</tt><tt class="py-op">:</tt> <tt class="py-name">g</tt><tt class="py-op">(</tt><tt class="py-number">16</tt><tt class="py-op">)</tt> <tt class="py-op">+</tt> <tt class="py-string">' '</tt> <tt class="py-op">+</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">g</tt><tt class="py-op">(</tt><tt class="py-number">17</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L316"></a><tt class="py-lineno">316</tt> <tt class="py-line"> <tt class="py-comment"># :first-line|letter followed</tt> </tt>
+<a name="L317"></a><tt class="py-lineno">317</tt> <tt class="py-line"> <tt class="py-comment"># by [{,] (apparently space</tt> </tt>
+<a name="L318"></a><tt class="py-lineno">318</tt> <tt class="py-line"> <tt class="py-comment"># needed for IE6)</tt> </tt>
+<a name="L319"></a><tt class="py-lineno">319</tt> <tt class="py-line"> <tt class="py-keyword">lambda</tt> <tt class="py-name">g</tt><tt class="py-op">:</tt> <tt class="py-name">nl_unesc_sub</tt><tt class="py-op">(</tt><tt class="py-string">''</tt><tt class="py-op">,</tt> <tt class="py-name">g</tt><tt class="py-op">(</tt><tt class="py-number">18</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> <tt class="py-comment"># nl_string</tt> </tt>
+<a name="L320"></a><tt class="py-lineno">320</tt> <tt class="py-line"> <tt class="py-keyword">lambda</tt> <tt class="py-name">g</tt><tt class="py-op">:</tt> <tt class="py-name">post_esc_sub</tt><tt class="py-op">(</tt><tt class="py-string">' '</tt><tt class="py-op">,</tt> <tt class="py-name">g</tt><tt class="py-op">(</tt><tt class="py-number">19</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> <tt class="py-comment"># escape</tt> </tt>
+<a name="L321"></a><tt class="py-lineno">321</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L322"></a><tt class="py-lineno">322</tt> <tt class="py-line"> </tt>
+<a name="L323"></a><tt class="py-lineno">323</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">func</tt><tt class="py-op">(</tt><tt class="py-param">match</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L324"></a><tt class="py-lineno">324</tt> <tt class="py-line"> <tt class="py-docstring">""" Main subber """</tt> </tt>
+<a name="L325"></a><tt class="py-lineno">325</tt> <tt class="py-line"> <tt class="py-name">idx</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt> <tt class="py-op">=</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">lastindex</tt><tt class="py-op">,</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">group</tt> </tt>
+<a name="L326"></a><tt class="py-lineno">326</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">idx</tt> <tt class="py-op">&gt;</tt> <tt class="py-number">3</tt><tt class="py-op">:</tt> </tt>
+<a name="L327"></a><tt class="py-lineno">327</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">table</tt><tt class="py-op">[</tt><tt class="py-name">idx</tt><tt class="py-op">]</tt><tt class="py-op">(</tt><tt class="py-name">group</tt><tt class="py-op">)</tt> </tt>
+<a name="L328"></a><tt class="py-lineno">328</tt> <tt class="py-line"> </tt>
+<a name="L329"></a><tt class="py-lineno">329</tt> <tt class="py-line"> <tt class="py-comment"># shortcuts for frequent operations below:</tt> </tt>
+<a name="L330"></a><tt class="py-lineno">330</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">idx</tt> <tt class="py-op">==</tt> <tt class="py-number">1</tt><tt class="py-op">:</tt> <tt class="py-comment"># not interesting</tt> </tt>
+<a name="L331"></a><tt class="py-lineno">331</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">1</tt><tt class="py-op">)</tt> </tt>
+<a name="L332"></a><tt class="py-lineno">332</tt> <tt class="py-line"> <tt class="py-comment">#else: # space with token before or at the beginning</tt> </tt>
+<a name="L333"></a><tt class="py-lineno">333</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">space_sub</tt><tt class="py-op">(</tt><tt class="py-name">space_subber</tt><tt class="py-op">,</tt> <tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-name">idx</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L334"></a><tt class="py-lineno">334</tt> <tt class="py-line"> </tt>
+<a name="L335"></a><tt class="py-lineno">335</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">func</tt> </tt>
+</div><a name="L336"></a><tt class="py-lineno">336</tt> <tt class="py-line"> </tt>
+<a name="L337"></a><tt class="py-lineno">337</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">cssmin</tt><tt class="py-op">(</tt><tt class="py-param">style</tt><tt class="py-op">,</tt> <tt class="py-param">keep_bang_comments</tt><tt class="py-op">=</tt><tt class="py-name">False</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> <tt class="py-comment"># pylint: disable = W0621</tt> </tt>
+<a name="L338"></a><tt class="py-lineno">338</tt> <tt class="py-line"> <tt class="py-docstring">"""</tt> </tt>
+<a name="L339"></a><tt class="py-lineno">339</tt> <tt class="py-line"><tt class="py-docstring"> Minify CSS.</tt> </tt>
+<a name="L340"></a><tt class="py-lineno">340</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L341"></a><tt class="py-lineno">341</tt> <tt class="py-line"><tt class="py-docstring"> :Parameters:</tt> </tt>
+<a name="L342"></a><tt class="py-lineno">342</tt> <tt class="py-line"><tt class="py-docstring"> `style` : ``str``</tt> </tt>
+<a name="L343"></a><tt class="py-lineno">343</tt> <tt class="py-line"><tt class="py-docstring"> CSS to minify</tt> </tt>
+<a name="L344"></a><tt class="py-lineno">344</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L345"></a><tt class="py-lineno">345</tt> <tt class="py-line"><tt class="py-docstring"> `keep_bang_comments` : ``bool``</tt> </tt>
+<a name="L346"></a><tt class="py-lineno">346</tt> <tt class="py-line"><tt class="py-docstring"> Keep comments starting with an exclamation mark? (``/*!...*/``)</tt> </tt>
+<a name="L347"></a><tt class="py-lineno">347</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L348"></a><tt class="py-lineno">348</tt> <tt class="py-line"><tt class="py-docstring"> :Return: Minified style</tt> </tt>
+<a name="L349"></a><tt class="py-lineno">349</tt> <tt class="py-line"><tt class="py-docstring"> :Rtype: ``str``</tt> </tt>
+<a name="L350"></a><tt class="py-lineno">350</tt> <tt class="py-line"><tt class="py-docstring"> """</tt> </tt>
+<a name="L351"></a><tt class="py-lineno">351</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">main_sub</tt><tt class="py-op">(</tt><tt class="py-name">main_subber</tt><tt class="py-op">(</tt><tt class="py-name">keep_bang_comments</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> <tt class="py-name">style</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L352"></a><tt class="py-lineno">352</tt> <tt class="py-line"> </tt>
+<a name="L353"></a><tt class="py-lineno">353</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt id="link-5" class="py-name"><a title="rcssmin.cssmin" class="py-name" href="#" onclick="return doclink('link-5', 'cssmin', 'link-4');">cssmin</a></tt> </tt>
+</div><a name="L354"></a><tt class="py-lineno">354</tt> <tt class="py-line"> </tt>
+<a name="L355"></a><tt class="py-lineno">355</tt> <tt class="py-line"><tt id="link-6" class="py-name"><a title="rcssmin.cssmin" class="py-name" href="#" onclick="return doclink('link-6', 'cssmin', 'link-4');">cssmin</a></tt> <tt class="py-op">=</tt> <tt class="py-name">_make_cssmin</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L356"></a><tt class="py-lineno">356</tt> <tt class="py-line"> </tt>
+<a name="L357"></a><tt class="py-lineno">357</tt> <tt class="py-line"> </tt>
+<a name="L358"></a><tt class="py-lineno">358</tt> <tt class="py-line"><tt class="py-keyword">if</tt> <tt class="py-name">__name__</tt> <tt class="py-op">==</tt> <tt class="py-string">'__main__'</tt><tt class="py-op">:</tt> </tt>
+<a name="main"></a><div id="main-def"><a name="L359"></a><tt class="py-lineno">359</tt> <a class="py-toggle" href="#" id="main-toggle" onclick="return toggle('main');">-</a><tt class="py-line"> <tt class="py-keyword">def</tt> <a class="py-def-name" href="rcssmin-module.html#main">main</a><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+</div><div id="main-collapsed" style="display:none;" pad="+++" indent="++++++++"></div><div id="main-expanded"><a name="L360"></a><tt class="py-lineno">360</tt> <tt class="py-line"> <tt class="py-docstring">""" Main """</tt> </tt>
+<a name="L361"></a><tt class="py-lineno">361</tt> <tt class="py-line"> <tt class="py-keyword">import</tt> <tt class="py-name">sys</tt> <tt class="py-keyword">as</tt> <tt class="py-name">_sys</tt> </tt>
+<a name="L362"></a><tt class="py-lineno">362</tt> <tt class="py-line"> <tt class="py-name">keep_bang_comments</tt> <tt class="py-op">=</tt> <tt class="py-op">(</tt> </tt>
+<a name="L363"></a><tt class="py-lineno">363</tt> <tt class="py-line"> <tt class="py-string">'-b'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">argv</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">:</tt><tt class="py-op">]</tt> </tt>
+<a name="L364"></a><tt class="py-lineno">364</tt> <tt class="py-line"> <tt class="py-keyword">or</tt> <tt class="py-string">'-bp'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">argv</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">:</tt><tt class="py-op">]</tt> </tt>
+<a name="L365"></a><tt class="py-lineno">365</tt> <tt class="py-line"> <tt class="py-keyword">or</tt> <tt class="py-string">'-pb'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">argv</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">:</tt><tt class="py-op">]</tt> </tt>
+<a name="L366"></a><tt class="py-lineno">366</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L367"></a><tt class="py-lineno">367</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-string">'-p'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">argv</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">:</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-string">'-bp'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">argv</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">:</tt><tt class="py-op">]</tt> \ </tt>
+<a name="L368"></a><tt class="py-lineno">368</tt> <tt class="py-line"> <tt class="py-keyword">or</tt> <tt class="py-string">'-pb'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">argv</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">:</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L369"></a><tt class="py-lineno">369</tt> <tt class="py-line"> <tt class="py-keyword">global</tt> <tt id="link-7" class="py-name"><a title="rcssmin.cssmin" class="py-name" href="#" onclick="return doclink('link-7', 'cssmin', 'link-4');">cssmin</a></tt> <tt class="py-comment"># pylint: disable = W0603</tt> </tt>
+<a name="L370"></a><tt class="py-lineno">370</tt> <tt class="py-line"> <tt id="link-8" class="py-name"><a title="rcssmin.cssmin" class="py-name" href="#" onclick="return doclink('link-8', 'cssmin', 'link-4');">cssmin</a></tt> <tt class="py-op">=</tt> <tt class="py-name">_make_cssmin</tt><tt class="py-op">(</tt><tt class="py-name">python_only</tt><tt class="py-op">=</tt><tt class="py-name">True</tt><tt class="py-op">)</tt> </tt>
+<a name="L371"></a><tt class="py-lineno">371</tt> <tt class="py-line"> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">stdout</tt><tt class="py-op">.</tt><tt class="py-name">write</tt><tt class="py-op">(</tt><tt id="link-9" class="py-name"><a title="rcssmin.cssmin" class="py-name" href="#" onclick="return doclink('link-9', 'cssmin', 'link-4');">cssmin</a></tt><tt class="py-op">(</tt> </tt>
+<a name="L372"></a><tt class="py-lineno">372</tt> <tt class="py-line"> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">stdin</tt><tt class="py-op">.</tt><tt class="py-name">read</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> <tt class="py-name">keep_bang_comments</tt><tt class="py-op">=</tt><tt class="py-name">keep_bang_comments</tt> </tt>
+<a name="L373"></a><tt class="py-lineno">373</tt> <tt class="py-line"> <tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L374"></a><tt class="py-lineno">374</tt> <tt class="py-line"> <tt class="py-name">main</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L375"></a><tt class="py-lineno">375</tt> <tt class="py-line"> </tt><script type="text/javascript">
+<!--
+expandto(location.href);
+// -->
+</script>
+</pre>
+<br />
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rcssmin/" target="_top">Visit rcssmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/redirect.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/redirect.html
new file mode 100644
index 00000000000..95728fdf177
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/docs/apidoc/redirect.html
@@ -0,0 +1,38 @@
+<html><head><title>Epydoc Redirect Page</title>
+<meta http-equiv="cache-control" content="no-cache" />
+<meta http-equiv="expires" content="0" />
+<meta http-equiv="pragma" content="no-cache" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+<body>
+<script type="text/javascript">
+<!--
+var pages = ["rcssmin-m"];
+var dottedName = get_anchor();
+if (dottedName) {
+ var target = redirect_url(dottedName);
+ if (target) window.location.replace(target);
+}
+// -->
+</script>
+
+<h3>Epydoc Auto-redirect page</h3>
+
+<p>When javascript is enabled, this page will redirect URLs of
+the form <tt>redirect.html#<i>dotted.name</i></tt> to the
+documentation for the object with the given fully-qualified
+dotted name.</p>
+<p><a id="message"> &nbsp; </a></p>
+
+<script type="text/javascript">
+<!--
+if (dottedName) {
+ var msg = document.getElementById("message");
+ msg.innerHTML = "No documentation found for <tt>"+
+ dottedName+"</tt>";
+}
+// -->
+</script>
+
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/package.cfg b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/package.cfg
new file mode 100644
index 00000000000..c09bbd0365b
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/package.cfg
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 - 2014
+# André Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[package]
+name = rcssmin
+
+python.min = 2.3
+python.max = 3.4
+pypy.min = 1.9
+pypy.max = 2.2
+jython.min = 2.5
+jython.max = 2.7
+
+version.number = 1.0.5
+
+author.name = André Malo
+author.email = nd@perlig.de
+#maintainer.name =
+#maintainer.email =
+url.homepage = http://opensource.perlig.de/rcssmin/
+url.download = http://storage.perlig.de/rcssmin/
+
+
+[docs]
+meta.classifiers = docs/CLASSIFIERS
+meta.description = docs/DESCRIPTION
+meta.summary = docs/SUMMARY
+meta.provides = docs/PROVIDES
+meta.license = LICENSE
+meta.keywords =
+ CSS
+ Minimization
+
+apidoc.dir = docs/apidoc
+apidoc.strip = 1
+#apidoc.ignore =
+
+#userdoc.dir = docs/userdoc
+#userdoc.strip = 1
+#userdoc.ignore =
+# .buildinfo
+
+#examples.dir = docs/examples
+#examples.strip = 1
+#examples.ignore =
+
+#man =
+
+extra =
+ README.rst
+ docs/CHANGES
+ docs/BENCHMARKS
+
+
+[manifest]
+#packages.lib = .
+#packages.collect =
+modules = rcssmin
+
+packages.extra =
+ _setup.py2.term
+ _setup.py3.term
+
+#scripts =
+
+dist =
+ tests
+ run_tests.py
+ bench
+ bench.sh
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/rcssmin.c b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/rcssmin.c
new file mode 100644
index 00000000000..a722fc276a9
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/rcssmin.c
@@ -0,0 +1,1163 @@
+/*
+ * Copyright 2011 - 2014
+ * Andr\xe9 Malo or his licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cext.h"
+EXT_INIT_FUNC;
+
+#ifdef EXT3
+typedef Py_UNICODE rchar;
+#else
+typedef unsigned char rchar;
+#endif
+#define U(c) ((rchar)(c))
+
+typedef struct {
+ const rchar *start;
+ const rchar *sentinel;
+ const rchar *tsentinel;
+ Py_ssize_t at_group;
+ int in_macie5;
+ int in_rule;
+ int keep_bang_comments;
+} rcssmin_ctx_t;
+
+typedef enum {
+ NEED_SPACE_MAYBE = 0,
+ NEED_SPACE_NEVER
+} need_space_flag;
+
+
+#define RCSSMIN_DULL_BIT (1 << 0)
+#define RCSSMIN_HEX_BIT (1 << 1)
+#define RCSSMIN_ESC_BIT (1 << 2)
+#define RCSSMIN_SPACE_BIT (1 << 3)
+#define RCSSMIN_STRING_DULL_BIT (1 << 4)
+#define RCSSMIN_NMCHAR_BIT (1 << 5)
+#define RCSSMIN_URI_DULL_BIT (1 << 6)
+#define RCSSMIN_PRE_CHAR_BIT (1 << 7)
+#define RCSSMIN_POST_CHAR_BIT (1 << 8)
+
+static const unsigned short rcssmin_charmask[128] = {
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 28, 8, 21, 8, 8, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 28, 469, 4, 85, 85, 85, 85, 4,
+ 149, 277, 85, 469, 469, 117, 85, 84,
+ 115, 115, 115, 115, 115, 115, 115, 115,
+ 115, 115, 468, 340, 85, 469, 468, 85,
+ 84, 115, 115, 115, 115, 115, 115, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 213, 4, 341, 85, 117,
+ 85, 115, 115, 115, 115, 115, 115, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 116, 117, 117,
+ 117, 117, 117, 468, 85, 468, 85, 21
+};
+
+#define RCSSMIN_IS_DULL(c) ((U(c) > 127) || \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_DULL_BIT))
+
+#define RCSSMIN_IS_HEX(c) ((U(c) <= 127) && \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_HEX_BIT))
+
+#define RCSSMIN_IS_ESC(c) ((U(c) > 127) || \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_ESC_BIT))
+
+#define RCSSMIN_IS_SPACE(c) ((U(c) <= 127) && \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_SPACE_BIT))
+
+#define RCSSMIN_IS_STRING_DULL(c) ((U(c) > 127) || \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_STRING_DULL_BIT))
+
+#define RCSSMIN_IS_NMCHAR(c) ((U(c) > 127) || \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_NMCHAR_BIT))
+
+#define RCSSMIN_IS_URI_DULL(c) ((U(c) > 127) || \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_URI_DULL_BIT))
+
+#define RCSSMIN_IS_PRE_CHAR(c) ((U(c) <= 127) && \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_PRE_CHAR_BIT))
+
+#define RCSSMIN_IS_POST_CHAR(c) ((U(c) <= 127) && \
+ (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_POST_CHAR_BIT))
+
+
+static const rchar pattern_url[] = {
+ /*U('u'),*/ U('r'), U('l'), U('(')
+};
+
+static const rchar pattern_ie7[] = {
+ /*U('>'),*/ U('/'), U('*'), U('*'), U('/')
+};
+
+static const rchar pattern_media[] = {
+ U('m'), U('e'), U('d'), U('i'), U('a'),
+ U('M'), U('E'), U('D'), U('I'), U('A')
+};
+
+static const rchar pattern_document[] = {
+ U('d'), U('o'), U('c'), U('u'), U('m'), U('e'), U('n'), U('t'),
+ U('D'), U('O'), U('C'), U('U'), U('M'), U('E'), U('N'), U('T')
+};
+
+static const rchar pattern_supports[] = {
+ U('s'), U('u'), U('p'), U('p'), U('o'), U('r'), U('t'), U('s'),
+ U('S'), U('U'), U('P'), U('P'), U('O'), U('R'), U('T'), U('S')
+};
+
+static const rchar pattern_keyframes[] = {
+ U('k'), U('e'), U('y'), U('f'), U('r'), U('a'), U('m'), U('e'), U('s'),
+ U('K'), U('E'), U('Y'), U('F'), U('R'), U('A'), U('M'), U('E'), U('S')
+};
+
+static const rchar pattern_vendor_o[] = {
+ U('-'), U('o'), U('-'),
+ U('-'), U('O'), U('-')
+};
+
+static const rchar pattern_vendor_moz[] = {
+ U('-'), U('m'), U('o'), U('z'), U('-'),
+ U('-'), U('M'), U('O'), U('Z'), U('-')
+};
+
+static const rchar pattern_vendor_webkit[] = {
+ U('-'), U('w'), U('e'), U('b'), U('k'), U('i'), U('t'), U('-'),
+ U('-'), U('W'), U('E'), U('B'), U('K'), U('I'), U('T'), U('-')
+};
+
+static const rchar pattern_vendor_ms[] = {
+ U('-'), U('m'), U('s'), U('-'),
+ U('-'), U('M'), U('S'), U('-')
+};
+
+static const rchar pattern_first[] = {
+ U('f'), U('i'), U('r'), U('s'), U('t'), U('-'), U('l'),
+ U('F'), U('I'), U('R'), U('S'), U('T'), U('-'), U('L')
+};
+
+static const rchar pattern_line[] = {
+ U('i'), U('n'), U('e'),
+ U('I'), U('N'), U('E'),
+};
+
+static const rchar pattern_letter[] = {
+ U('e'), U('t'), U('t'), U('e'), U('r'),
+ U('E'), U('T'), U('T'), U('E'), U('R')
+};
+
+static const rchar pattern_macie5_init[] = {
+ U('/'), U('*'), U('\\'), U('*'), U('/')
+};
+
+static const rchar pattern_macie5_exit[] = {
+ U('/'), U('*'), U('*'), U('/')
+};
+
+/*
+ * Match a pattern (and copy immediately to target)
+ */
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-overflow"
+#endif
+static int
+copy_match(const rchar *pattern, const rchar *psentinel,
+ const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_;
+ rchar *target = *target_;
+ rchar c;
+
+ while (pattern < psentinel
+ && source < ctx->sentinel && target < ctx->tsentinel
+ && ((c = *source++) == *pattern++))
+ *target++ = c;
+
+ *source_ = source;
+ *target_ = target;
+
+ return (pattern == psentinel);
+}
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#pragma GCC diagnostic pop
+#endif
+
+#define MATCH(PAT, source, target, ctx) ( \
+ copy_match(pattern_##PAT, \
+ pattern_##PAT + sizeof(pattern_##PAT) / sizeof(rchar), \
+ source, target, ctx) \
+)
+
+
+/*
+ * Match a pattern (and copy immediately to target) - CI version
+ */
+static int
+copy_imatch(const rchar *pattern, const rchar *psentinel,
+ const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_, *pstart = pattern;
+ rchar *target = *target_;
+ rchar c;
+
+ while (pattern < psentinel
+ && source < ctx->sentinel && target < ctx->tsentinel
+ && ((c = *source++) == *pattern
+ || c == pstart[(pattern - pstart) + (psentinel - pstart)])) {
+ ++pattern;
+ *target++ = c;
+ }
+
+ *source_ = source;
+ *target_ = target;
+
+ return (pattern == psentinel);
+}
+
+#define IMATCH(PAT, source, target, ctx) ( \
+ copy_imatch(pattern_##PAT, \
+ pattern_##PAT + sizeof(pattern_##PAT) / sizeof(rchar) / 2, \
+ source, target, ctx) \
+)
+
+
+/*
+ * Copy characters
+ */
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-overflow"
+#endif
+static int
+copy(const rchar *source, const rchar *sentinel, rchar **target_,
+ rcssmin_ctx_t *ctx)
+{
+ rchar *target = *target_;
+
+ while (source < sentinel && target < ctx->tsentinel)
+ *target++ = *source++;
+
+ *target_ = target;
+
+ return (source == sentinel);
+}
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#pragma GCC diagnostic pop
+#endif
+
+#define COPY_PAT(PAT, target, ctx) ( \
+ copy(pattern_##PAT, \
+ pattern_##PAT + sizeof(pattern_##PAT) / sizeof(rchar), \
+ target, ctx) \
+)
+
+
+/*
+ * The ABORT macros work with known local variables!
+ */
+#define ABORT_(RET) do { \
+ if (source < ctx->sentinel && !(target < ctx->tsentinel)) { \
+ *source_ = source; \
+ *target_ = target; \
+ } \
+ return RET; \
+} while(0)
+
+
+#define CRAPPY_C90_COMPATIBLE_EMPTY
+#define ABORT ABORT_(CRAPPY_C90_COMPATIBLE_EMPTY)
+#define RABORT(RET) ABORT_((RET))
+
+
+/*
+ * Copy escape
+ */
+static void
+copy_escape(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_, *hsentinel;
+ rchar *target = *target_;
+ rchar c;
+
+ *target++ = U('\\');
+ *target_ = target;
+
+ if (source < ctx->sentinel && target < ctx->tsentinel) {
+ c = *source++;
+ if (RCSSMIN_IS_ESC(c)) {
+ *target++ = c;
+ }
+ else if (RCSSMIN_IS_HEX(c)) {
+ *target++ = c;
+
+ /* 6 hex chars max, one we got already */
+ if (ctx->sentinel - source > 5)
+ hsentinel = source + 5;
+ else
+ hsentinel = ctx->sentinel;
+
+ while (source < hsentinel && target < ctx->tsentinel
+ && (c = *source, RCSSMIN_IS_HEX(c))) {
+ ++source;
+ *target++ = c;
+ }
+
+ /* One optional space after */
+ if (source < ctx->sentinel && target < ctx->tsentinel) {
+ if (source == hsentinel)
+ c = *source;
+ if (RCSSMIN_IS_SPACE(c)) {
+ ++source;
+ *target++ = U(' ');
+ if (c == U('\r') && source < ctx->sentinel
+ && *source == U('\n'))
+ ++source;
+ }
+ }
+ }
+ }
+
+ *target_ = target;
+ *source_ = source;
+}
+
+
+/*
+ * Copy string
+ */
+static void
+copy_string(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_;
+ rchar *target = *target_;
+ rchar c, quote = source[-1];
+
+ *target++ = quote;
+ *target_ = target;
+
+ while (source < ctx->sentinel && target < ctx->tsentinel) {
+ c = *target++ = *source++;
+ if (RCSSMIN_IS_STRING_DULL(c))
+ continue;
+
+ switch (c) {
+ case U('\''): case U('"'):
+ if (c == quote) {
+ *target_ = target;
+ *source_ = source;
+ return;
+ }
+ continue;
+
+ case U('\\'):
+ if (source < ctx->sentinel && target < ctx->tsentinel) {
+ c = *source++;
+ switch (c) {
+ case U('\r'):
+ if (source < ctx->sentinel && *source == U('\n'))
+ ++source;
+ /* fall through */
+
+ case U('\n'): case U('\f'):
+ --target;
+ break;
+
+ default:
+ *target++ = c;
+ }
+ }
+ continue;
+ }
+ break; /* forbidden characters */
+ }
+
+ ABORT;
+}
+
+
+/*
+ * Copy URI string
+ */
+static int
+copy_uri_string(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_;
+ rchar *target = *target_;
+ rchar c, quote = source[-1];
+
+ *target++ = quote;
+ *target_ = target;
+
+ while (source < ctx->sentinel && target < ctx->tsentinel) {
+ c = *source++;
+ if (RCSSMIN_IS_SPACE(c))
+ continue;
+ *target++ = c;
+ if (RCSSMIN_IS_STRING_DULL(c))
+ continue;
+
+ switch (c) {
+ case U('\''): case U('"'):
+ if (c == quote) {
+ *target_ = target;
+ *source_ = source;
+ return 0;
+ }
+ continue;
+
+ case U('\\'):
+ if (source < ctx->sentinel && target < ctx->tsentinel) {
+ c = *source;
+ switch (c) {
+ case U('\r'):
+ if ((source + 1) < ctx->sentinel && source[1] == U('\n'))
+ ++source;
+ /* fall through */
+
+ case U('\n'): case U('\f'):
+ --target;
+ ++source;
+ break;
+
+ default:
+ --target;
+ copy_escape(&source, &target, ctx);
+ }
+ }
+ continue;
+ }
+
+ break; /* forbidden characters */
+ }
+
+ RABORT(-1);
+}
+
+
+/*
+ * Copy URI (unquoted)
+ */
+static int
+copy_uri_unquoted(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_;
+ rchar *target = *target_;
+ rchar c;
+
+ *target++ = source[-1];
+ *target_ = target;
+
+ while (source < ctx->sentinel && target < ctx->tsentinel) {
+ c = *source++;
+ if (RCSSMIN_IS_SPACE(c))
+ continue;
+ *target++ = c;
+ if (RCSSMIN_IS_URI_DULL(c))
+ continue;
+
+ switch (c) {
+
+ case U(')'):
+ *target_ = target - 1;
+ *source_ = source - 1;
+ return 0;
+
+ case U('\\'):
+ if (source < ctx->sentinel && target < ctx->tsentinel) {
+ c = *source;
+ switch (c) {
+ case U('\r'):
+ if ((source + 1) < ctx->sentinel && source[1] == U('\n'))
+ ++source;
+ /* fall through */
+
+ case U('\n'): case U('\f'):
+ --target;
+ ++source;
+ break;
+
+ default:
+ --target;
+ copy_escape(&source, &target, ctx);
+ }
+ }
+ continue;
+ }
+
+ break; /* forbidden characters */
+ }
+
+ RABORT(-1);
+}
+
+
+/*
+ * Copy url
+ */
+static void
+copy_url(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_;
+ rchar *target = *target_;
+ rchar c;
+
+ *target++ = U('u');
+ *target_ = target;
+
+ /* Must not be inside an identifier */
+ if ((source != ctx->start + 1) && RCSSMIN_IS_NMCHAR(source[-2]))
+ return;
+
+ if (!MATCH(url, &source, &target, ctx)
+ || !(source < ctx->sentinel && target < ctx->tsentinel))
+ ABORT;
+
+ while (source < ctx->sentinel && RCSSMIN_IS_SPACE(*source))
+ ++source;
+
+ if (!(source < ctx->sentinel))
+ ABORT;
+
+ c = *source++;
+ switch (c) {
+ case U('"'): case U('\''):
+ if (copy_uri_string(&source, &target, ctx) == -1)
+ ABORT;
+
+ while (source < ctx->sentinel && RCSSMIN_IS_SPACE(*source))
+ ++source;
+ break;
+
+ default:
+ if (copy_uri_unquoted(&source, &target, ctx) == -1)
+ ABORT;
+ }
+
+ if (!(source < ctx->sentinel && target < ctx->tsentinel))
+ ABORT;
+
+ if ((*target++ = *source++) != U(')'))
+ ABORT;
+
+ *target_ = target;
+ *source_ = source;
+}
+
+
+/*
+ * Copy @-group
+ */
+static void
+copy_at_group(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_;
+ rchar *target = *target_;
+
+ *target++ = U('@');
+ *target_ = target;
+
+#define REMATCH(what) ( \
+ source = *source_, \
+ target = *target_, \
+ IMATCH(what, &source, &target, ctx) \
+)
+#define CMATCH(what) IMATCH(what, &source, &target, ctx)
+
+ if (( !CMATCH(media)
+ && !REMATCH(supports)
+ && !REMATCH(document)
+ && !REMATCH(keyframes)
+ && !(REMATCH(vendor_webkit) && CMATCH(keyframes))
+ && !(REMATCH(vendor_moz) && CMATCH(keyframes))
+ && !(REMATCH(vendor_o) && CMATCH(keyframes))
+ && !(REMATCH(vendor_ms) && CMATCH(keyframes)))
+ || !(source < ctx->sentinel && target < ctx->tsentinel)
+ || RCSSMIN_IS_NMCHAR(*source))
+ ABORT;
+
+#undef CMATCH
+#undef REMATCH
+
+ ++ctx->at_group;
+
+ *target_ = target;
+ *source_ = source;
+}
+
+
+/*
+ * Skip space
+ */
+static const rchar *
+skip_space(const rchar *source, rcssmin_ctx_t *ctx)
+{
+ const rchar *begin = source;
+ int res;
+ rchar c;
+
+ while (source < ctx->sentinel) {
+ c = *source;
+ if (RCSSMIN_IS_SPACE(c)) {
+ ++source;
+ continue;
+ }
+ else if (c == U('/')) {
+ ++source;
+ if (!(source < ctx->sentinel && *source == U('*'))) {
+ --source;
+ break;
+ }
+ ++source;
+ res = 0;
+ while (source < ctx->sentinel) {
+ c = *source++;
+ if (c != U('*'))
+ continue;
+ if (!(source < ctx->sentinel))
+ return begin;
+ if (*source != U('/'))
+ continue;
+
+ /* Comment complete */
+ ++source;
+ res = 1;
+ break;
+ }
+ if (!res)
+ return begin;
+
+ continue;
+ }
+
+ break;
+ }
+
+ return source;
+}
+
+
+/*
+ * Copy space
+ */
+static void
+copy_space(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx,
+ need_space_flag need_space)
+{
+ const rchar *source = *source_, *end, *comment;
+ rchar *target = *target_;
+ int res;
+ rchar c;
+
+ --source;
+ if (need_space == NEED_SPACE_MAYBE
+ && source > ctx->start
+ && !RCSSMIN_IS_PRE_CHAR(source[-1])
+ && (end = skip_space(source, ctx)) < ctx->sentinel
+ && (!RCSSMIN_IS_POST_CHAR(*end)
+ || (*end == U(':') && !ctx->in_rule && !ctx->at_group))) {
+
+ if (!(target < ctx->tsentinel))
+ ABORT;
+ *target++ = U(' ');
+ }
+
+ while (source < ctx->sentinel) {
+ switch (c = *source) {
+
+ /* comment */
+ case U('/'):
+ comment = source++;
+ if (!((source < ctx->sentinel && *source == U('*')))) {
+ --source;
+ break;
+ }
+ ++source;
+ res = 0;
+ while (source < ctx->sentinel) {
+ c = *source++;
+ if (c != U('*'))
+ continue;
+ if (!(source < ctx->sentinel))
+ ABORT;
+ if (*source != U('/'))
+ continue;
+
+ /* Comment complete */
+ ++source;
+ res = 1;
+
+ if (ctx->keep_bang_comments && comment[2] == U('!')) {
+ ctx->in_macie5 = (source[-3] == U('\\'));
+ if (!copy(comment, source, &target, ctx))
+ ABORT;
+ }
+ else if (source[-3] == U('\\')) {
+ if (!ctx->in_macie5) {
+ if (!COPY_PAT(macie5_init, &target, ctx))
+ ABORT;
+ }
+ ctx->in_macie5 = 1;
+ }
+ else if (ctx->in_macie5) {
+ if (!COPY_PAT(macie5_exit, &target, ctx))
+ ABORT;
+ ctx->in_macie5 = 0;
+ }
+ /* else don't copy anything */
+ break;
+ }
+ if (!res)
+ ABORT;
+ continue;
+
+ /* space */
+ case U(' '): case U('\t'): case U('\r'): case U('\n'): case U('\f'):
+ ++source;
+ continue;
+ }
+
+ break;
+ }
+
+ *source_ = source;
+ *target_ = target;
+}
+
+
+/*
+ * Copy space if comment
+ */
+static int
+copy_space_comment(const rchar **source_, rchar **target_,
+ rcssmin_ctx_t *ctx, need_space_flag need_space)
+{
+ const rchar *source = *source_;
+ rchar *target = *target_;
+
+ if (source < ctx->sentinel && *source == U('*')) {
+ copy_space(source_, target_, ctx, need_space);
+ if (*source_ > source)
+ return 0;
+ }
+ if (!(target < ctx->tsentinel))
+ RABORT(-1);
+
+ *target++ = source[-1];
+
+ /* *source_ = source; <-- unchanged */
+ *target_ = target;
+
+ return -1;
+}
+
+
+/*
+ * Copy space if exists
+ */
+static int
+copy_space_optional(const rchar **source_, rchar **target_,
+ rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_;
+
+ if (!(source < ctx->sentinel))
+ return -1;
+
+ if (*source == U('/')) {
+ *source_ = source + 1;
+ return copy_space_comment(source_, target_, ctx, NEED_SPACE_NEVER);
+ }
+ else if (RCSSMIN_IS_SPACE(*source)) {
+ *source_ = source + 1;
+ copy_space(source_, target_, ctx, NEED_SPACE_NEVER);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+/*
+ * Copy :first-line|letter
+ */
+static void
+copy_first(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_, *next, *source_fork;
+ rchar *target = *target_, *target_fork;
+
+ *target++ = U(':');
+ *target_ = target;
+
+ if (!IMATCH(first, &source, &target, ctx)
+ || !(source < ctx->sentinel && target < ctx->tsentinel))
+ ABORT;
+
+ source_fork = source;
+ target_fork = target;
+
+ if (!IMATCH(line, &source, &target, ctx)) {
+ source = source_fork;
+ target = target_fork;
+
+ if (!IMATCH(letter, &source, &target, ctx)
+ || !(source < ctx->sentinel && target < ctx->tsentinel))
+ ABORT;
+ }
+
+ next = skip_space(source, ctx);
+ if (!(next < ctx->sentinel && target < ctx->tsentinel
+ && (*next == U('{') || *next == U(','))))
+ ABORT;
+
+ *target++ = U(' ');
+ *target_ = target;
+ *source_ = source;
+ (void)copy_space_optional(source_, target_, ctx);
+}
+
+
+/*
+ * Copy IE7 hack
+ */
+static void
+copy_ie7hack(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_;
+ rchar *target = *target_;
+
+ *target++ = U('>');
+ *target_ = target;
+
+ if (ctx->in_rule || ctx->at_group)
+ return; /* abort */
+
+ if (!MATCH(ie7, &source, &target, ctx))
+ ABORT;
+
+ ctx->in_macie5 = 0;
+
+ *target_ = target;
+ *source_ = source;
+
+ (void)copy_space_optional(source_, target_, ctx);
+}
+
+
+/*
+ * Copy semicolon; miss out duplicates or even this one (before '}')
+ */
+static void
+copy_semicolon(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
+{
+ const rchar *source = *source_, *begin, *end;
+ rchar *target = *target_;
+
+ begin = source;
+ while (source < ctx->sentinel) {
+ end = skip_space(source, ctx);
+ if (!(end < ctx->sentinel)) {
+ if (!(target < ctx->tsentinel))
+ ABORT;
+ *target++ = U(';');
+ break;
+ }
+ switch (*end) {
+ case U(';'):
+ source = end + 1;
+ continue;
+
+ case U('}'):
+ if (ctx->in_rule)
+ break;
+
+ /* fall through */
+ default:
+ if (!(target < ctx->tsentinel))
+ ABORT;
+ *target++ = U(';');
+ break;
+ }
+
+ break;
+ }
+
+ source = begin;
+ *target_ = target;
+ while (source < ctx->sentinel) {
+ if (*source == U(';')) {
+ ++source;
+ continue;
+ }
+
+ if (copy_space_optional(&source, target_, ctx) == 0)
+ continue;
+
+ break;
+ }
+
+ *source_ = source;
+}
+
+
+/*
+ * Main function
+ *
+ * The return value determines the result length (kept in the target buffer).
+ * However, if the target buffer is too small, the return value is greater
+ * than tlength. The difference to tlength is the number of unconsumed source
+ * characters at the time the buffer was full. In this case you should resize
+ * the target buffer to the return value and call rcssmin again. Repeat as
+ * often as needed.
+ */
+static Py_ssize_t
+rcssmin(const rchar *source, rchar *target, Py_ssize_t slength,
+ Py_ssize_t tlength, int keep_bang_comments)
+{
+ rcssmin_ctx_t ctx_, *ctx = &ctx_;
+ const rchar *tstart = target;
+ rchar c;
+
+ ctx->start = source;
+ ctx->sentinel = source + slength;
+ ctx->tsentinel = target + tlength;
+ ctx->at_group = 0;
+ ctx->in_macie5 = 0;
+ ctx->in_rule = 0;
+ ctx->keep_bang_comments = keep_bang_comments;
+
+ while (source < ctx->sentinel && target < ctx->tsentinel) {
+ c = *source++;
+ if (RCSSMIN_IS_DULL(c)) {
+ *target++ = c;
+ continue;
+ }
+ else if (RCSSMIN_IS_SPACE(c)) {
+ copy_space(&source, &target, ctx, NEED_SPACE_MAYBE);
+ continue;
+ }
+
+ switch (c) {
+
+ /* Escape */
+ case U('\\'):
+ copy_escape(&source, &target, ctx);
+ continue;
+
+ /* String */
+ case U('"'): case U('\''):
+ copy_string(&source, &target, ctx);
+ continue;
+
+ /* URL */
+ case U('u'):
+ copy_url(&source, &target, ctx);
+ continue;
+
+ /* IE7hack */
+ case U('>'):
+ copy_ie7hack(&source, &target, ctx);
+ continue;
+
+ /* @-group */
+ case U('@'):
+ copy_at_group(&source, &target, ctx);
+ continue;
+
+ /* ; */
+ case U(';'):
+ copy_semicolon(&source, &target, ctx);
+ continue;
+
+ /* :first-line|letter followed by [{,] */
+ /* (apparently needed for IE6) */
+ case U(':'):
+ copy_first(&source, &target, ctx);
+ continue;
+
+ /* { */
+ case U('{'):
+ if (ctx->at_group)
+ --ctx->at_group;
+ else
+ ++ctx->in_rule;
+ *target++ = c;
+ continue;
+
+ /* } */
+ case U('}'):
+ if (ctx->in_rule)
+ --ctx->in_rule;
+ *target++ = c;
+ continue;
+
+ /* space starting with comment */
+ case U('/'):
+ (void)copy_space_comment(&source, &target, ctx, NEED_SPACE_MAYBE);
+ continue;
+
+ /* Fallback: copy character. Better safe than sorry. Should not be
+ * reached, though */
+ default:
+ *target++ = c;
+ continue;
+ }
+ }
+
+ return
+ (Py_ssize_t)(target - tstart) + (Py_ssize_t)(ctx->sentinel - source);
+}
+
+
+PyDoc_STRVAR(rcssmin_cssmin__doc__,
+"cssmin(style, keep_bang_comments=False)\n\
+\n\
+Minify CSS.\n\
+\n\
+:Note: This is a hand crafted C implementation built on the regex\n\
+ semantics.\n\
+\n\
+:Parameters:\n\
+ `style` : ``str``\n\
+ CSS to minify\n\
+\n\
+:Return: Minified style\n\
+:Rtype: ``str``");
+
+static PyObject *
+rcssmin_cssmin(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *style, *keep_bang_comments_ = NULL, *result;
+ static char *kwlist[] = {"style", "keep_bang_comments", NULL};
+ Py_ssize_t rlength, slength, length;
+ int keep_bang_comments;
+#ifdef EXT2
+ int uni;
+#define UOBJ "O"
+#endif
+#ifdef EXT3
+#define UOBJ "U"
+#endif
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, UOBJ "|O", kwlist,
+ &style, &keep_bang_comments_))
+ return NULL;
+
+ if (!keep_bang_comments_)
+ keep_bang_comments = 0;
+ else {
+ keep_bang_comments = PyObject_IsTrue(keep_bang_comments_);
+ if (keep_bang_comments == -1)
+ return NULL;
+ }
+
+#ifdef EXT2
+ if (PyUnicode_Check(style)) {
+ if (!(style = PyUnicode_AsUTF8String(style)))
+ return NULL;
+ uni = 1;
+ }
+ else {
+ if (!(style = PyObject_Str(style)))
+ return NULL;
+ uni = 0;
+ }
+#endif
+
+#ifdef EXT3
+ Py_INCREF(style);
+#define PyString_GET_SIZE PyUnicode_GET_SIZE
+#define PyString_AS_STRING PyUnicode_AS_UNICODE
+#define _PyString_Resize PyUnicode_Resize
+#define PyString_FromStringAndSize PyUnicode_FromUnicode
+#endif
+
+ rlength = slength = PyString_GET_SIZE(style);
+
+again:
+ if (!(result = PyString_FromStringAndSize(NULL, rlength))) {
+ Py_DECREF(style);
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ length = rcssmin((rchar *)PyString_AS_STRING(style),
+ (rchar *)PyString_AS_STRING(result),
+ slength, rlength, keep_bang_comments);
+ Py_END_ALLOW_THREADS
+
+ if (length > rlength) {
+ Py_DECREF(result);
+ rlength = length;
+ goto again;
+ }
+
+ Py_DECREF(style);
+ if (length < 0) {
+ Py_DECREF(result);
+ return NULL;
+ }
+ if (length != rlength && _PyString_Resize(&result, length) == -1)
+ return NULL;
+
+#ifdef EXT2
+ if (uni) {
+ style = PyUnicode_DecodeUTF8(PyString_AS_STRING(result),
+ PyString_GET_SIZE(result), "strict");
+ Py_DECREF(result);
+ if (!style)
+ return NULL;
+ result = style;
+ }
+#endif
+ return result;
+}
+
+/* ------------------------ BEGIN MODULE DEFINITION ------------------------ */
+
+EXT_METHODS = {
+ {"cssmin",
+ (PyCFunction)rcssmin_cssmin, METH_VARARGS | METH_KEYWORDS,
+ rcssmin_cssmin__doc__},
+
+ {NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(EXT_DOCS_VAR,
+"C implementation of rcssmin\n\
+===========================\n\
+\n\
+C implementation of rcssmin.");
+
+
+EXT_DEFINE(EXT_MODULE_NAME, EXT_METHODS_VAR, EXT_DOCS_VAR);
+
+EXT_INIT_FUNC {
+ PyObject *m;
+
+ /* Create the module and populate stuff */
+ if (!(m = EXT_CREATE(&EXT_DEFINE_VAR)))
+ EXT_INIT_ERROR(NULL);
+
+ EXT_ADD_UNICODE(m, "__author__", "Andr\xe9 Malo", "latin-1");
+ EXT_ADD_STRING(m, "__docformat__", "restructuredtext en");
+
+ EXT_INIT_RETURN(m);
+}
+
+/* ------------------------- END MODULE DEFINITION ------------------------- */
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/rcssmin.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/rcssmin.py
new file mode 100644
index 00000000000..ae1cefc3396
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/rcssmin.py
@@ -0,0 +1,374 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+r"""
+==============
+ CSS Minifier
+==============
+
+CSS Minifier.
+
+The minifier is based on the semantics of the `YUI compressor`_\\, which
+itself is based on `the rule list by Isaac Schlueter`_\\.
+
+:Copyright:
+
+ Copyright 2011 - 2014
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+This module is a re-implementation aiming for speed instead of maximum
+compression, so it can be used at runtime (rather than during a preprocessing
+step). RCSSmin does syntactical compression only (removing spaces, comments
+and possibly semicolons). It does not provide semantic compression (like
+removing empty blocks, collapsing redundant properties etc). It does, however,
+support various CSS hacks (by keeping them working as intended).
+
+Here's a feature list:
+
+- Strings are kept, except that escaped newlines are stripped
+- Space/Comments before the very end or before various characters are
+ stripped: ``:{});=>+],!`` (The colon (``:``) is a special case, a single
+ space is kept if it's outside a ruleset.)
+- Space/Comments at the very beginning or after various characters are
+ stripped: ``{}(=:>+[,!``
+- Optional space after unicode escapes is kept, resp. replaced by a simple
+ space
+- whitespaces inside ``url()`` definitions are stripped
+- Comments starting with an exclamation mark (``!``) can be kept optionally.
+- All other comments and/or whitespace characters are replaced by a single
+ space.
+- Multiple consecutive semicolons are reduced to one
+- The last semicolon within a ruleset is stripped
+- CSS Hacks supported:
+
+ - IE7 hack (``>/**/``)
+ - Mac-IE5 hack (``/*\\*/.../**/``)
+ - The boxmodelhack is supported naturally because it relies on valid CSS2
+ strings
+ - Between ``:first-line`` and the following comma or curly brace a space is
+ inserted. (apparently it's needed for IE6)
+ - Same for ``:first-letter``
+
+rcssmin.c is a reimplementation of rcssmin.py in C and improves runtime up to
+factor 100 or so (depending on the input). docs/BENCHMARKS in the source
+distribution contains the details.
+
+Both python 2 (>= 2.4) and python 3 are supported.
+
+.. _YUI compressor: https://github.com/yui/yuicompressor/
+
+.. _the rule list by Isaac Schlueter: https://github.com/isaacs/cssmin/
+"""
+if __doc__:
+ # pylint: disable = W0622
+ __doc__ = __doc__.encode('ascii').decode('unicode_escape')
+__author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
+__docformat__ = "restructuredtext en"
+__license__ = "Apache License, Version 2.0"
+__version__ = '1.0.5'
+__all__ = ['cssmin']
+
+import re as _re
+
+
+def _make_cssmin(python_only=False):
+ """
+ Generate CSS minifier.
+
+ :Parameters:
+ `python_only` : ``bool``
+ Use only the python variant. If true, the c extension is not even
+ tried to be loaded.
+
+ :Return: Minifier
+ :Rtype: ``callable``
+ """
+ # pylint: disable = R0912, R0914, W0612
+
+ if not python_only:
+ try:
+ import _rcssmin
+ except ImportError:
+ pass
+ else:
+ return _rcssmin.cssmin
+
+ nl = r'(?:[\n\f]|\r\n?)' # pylint: disable = C0103
+ spacechar = r'[\r\n\f\040\t]'
+
+ unicoded = r'[0-9a-fA-F]{1,6}(?:[\040\n\t\f]|\r\n?)?'
+ escaped = r'[^\n\r\f0-9a-fA-F]'
+ escape = r'(?:\\(?:%(unicoded)s|%(escaped)s))' % locals()
+
+ nmchar = r'[^\000-\054\056\057\072-\100\133-\136\140\173-\177]'
+ #nmstart = r'[^\000-\100\133-\136\140\173-\177]'
+ #ident = (r'(?:'
+ # r'-?(?:%(nmstart)s|%(escape)s)%(nmchar)s*(?:%(escape)s%(nmchar)s*)*'
+ #r')') % locals()
+
+ comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
+
+ # only for specific purposes. The bang is grouped:
+ _bang_comment = r'(?:/\*(!?)[^*]*\*+(?:[^/*][^*]*\*+)*/)'
+
+ string1 = \
+ r'(?:\047[^\047\\\r\n\f]*(?:\\[^\r\n\f][^\047\\\r\n\f]*)*\047)'
+ string2 = r'(?:"[^"\\\r\n\f]*(?:\\[^\r\n\f][^"\\\r\n\f]*)*")'
+ strings = r'(?:%s|%s)' % (string1, string2)
+
+ nl_string1 = \
+ r'(?:\047[^\047\\\r\n\f]*(?:\\(?:[^\r]|\r\n?)[^\047\\\r\n\f]*)*\047)'
+ nl_string2 = r'(?:"[^"\\\r\n\f]*(?:\\(?:[^\r]|\r\n?)[^"\\\r\n\f]*)*")'
+ nl_strings = r'(?:%s|%s)' % (nl_string1, nl_string2)
+
+ uri_nl_string1 = r'(?:\047[^\047\\]*(?:\\(?:[^\r]|\r\n?)[^\047\\]*)*\047)'
+ uri_nl_string2 = r'(?:"[^"\\]*(?:\\(?:[^\r]|\r\n?)[^"\\]*)*")'
+ uri_nl_strings = r'(?:%s|%s)' % (uri_nl_string1, uri_nl_string2)
+
+ nl_escaped = r'(?:\\%(nl)s)' % locals()
+
+ space = r'(?:%(spacechar)s|%(comment)s)' % locals()
+
+ ie7hack = r'(?:>/\*\*/)'
+
+ uri = (r'(?:'
+ # noqa pylint: disable = C0330
+ r'(?:[^\000-\040"\047()\\\177]*'
+ r'(?:%(escape)s[^\000-\040"\047()\\\177]*)*)'
+ r'(?:'
+ r'(?:%(spacechar)s+|%(nl_escaped)s+)'
+ r'(?:'
+ r'(?:[^\000-\040"\047()\\\177]|%(escape)s|%(nl_escaped)s)'
+ r'[^\000-\040"\047()\\\177]*'
+ r'(?:%(escape)s[^\000-\040"\047()\\\177]*)*'
+ r')+'
+ r')*'
+ r')') % locals()
+
+ nl_unesc_sub = _re.compile(nl_escaped).sub
+
+ uri_space_sub = _re.compile((
+ r'(%(escape)s+)|%(spacechar)s+|%(nl_escaped)s+'
+ ) % locals()).sub
+ uri_space_subber = lambda m: m.groups()[0] or ''
+
+ space_sub_simple = _re.compile((
+ r'[\r\n\f\040\t;]+|(%(comment)s+)'
+ ) % locals()).sub
+ space_sub_banged = _re.compile((
+ r'[\r\n\f\040\t;]+|(%(_bang_comment)s+)'
+ ) % locals()).sub
+
+ post_esc_sub = _re.compile(r'[\r\n\f\t]+').sub
+
+ main_sub = _re.compile((
+ # noqa pylint: disable = C0330
+ r'([^\\"\047u>@\r\n\f\040\t/;:{}]+)'
+ r'|(?<=[{}(=:>+[,!])(%(space)s+)'
+ r'|^(%(space)s+)'
+ r'|(%(space)s+)(?=(([:{});=>+\],!])|$)?)'
+ r'|;(%(space)s*(?:;%(space)s*)*)(?=(\})?)'
+ r'|(\{)'
+ r'|(\})'
+ r'|(%(strings)s)'
+ r'|(?<!%(nmchar)s)url\(%(spacechar)s*('
+ r'%(uri_nl_strings)s'
+ r'|%(uri)s'
+ r')%(spacechar)s*\)'
+ r'|(@(?:'
+ r'[mM][eE][dD][iI][aA]'
+ r'|[sS][uU][pP][pP][oO][rR][tT][sS]'
+ r'|[dD][oO][cC][uU][mM][eE][nN][tT]'
+ r'|(?:-(?:'
+ r'[wW][eE][bB][kK][iI][tT]|[mM][oO][zZ]|[oO]|[mM][sS]'
+ r')-)?'
+ r'[kK][eE][yY][fF][rR][aA][mM][eE][sS]'
+ r'))(?!%(nmchar)s)'
+ r'|(%(ie7hack)s)(%(space)s*)'
+ r'|(:[fF][iI][rR][sS][tT]-[lL]'
+ r'(?:[iI][nN][eE]|[eE][tT][tT][eE][rR]))'
+ r'(%(space)s*)(?=[{,])'
+ r'|(%(nl_strings)s)'
+ r'|(%(escape)s[^\\"\047u>@\r\n\f\040\t/;:{}]*)'
+ ) % locals()).sub
+
+ #print main_sub.__self__.pattern
+
+ def main_subber(keep_bang_comments):
+ """ Make main subber """
+ in_macie5, in_rule, at_group = [0], [0], [0]
+
+ if keep_bang_comments:
+ space_sub = space_sub_banged
+
+ def space_subber(match):
+ """ Space|Comment subber """
+ if match.lastindex:
+ group1, group2 = match.group(1, 2)
+ if group2:
+ if group1.endswith(r'\*/'):
+ in_macie5[0] = 1
+ else:
+ in_macie5[0] = 0
+ return group1
+ elif group1:
+ if group1.endswith(r'\*/'):
+ if in_macie5[0]:
+ return ''
+ in_macie5[0] = 1
+ return r'/*\*/'
+ elif in_macie5[0]:
+ in_macie5[0] = 0
+ return '/**/'
+ return ''
+ else:
+ space_sub = space_sub_simple
+
+ def space_subber(match):
+ """ Space|Comment subber """
+ if match.lastindex:
+ if match.group(1).endswith(r'\*/'):
+ if in_macie5[0]:
+ return ''
+ in_macie5[0] = 1
+ return r'/*\*/'
+ elif in_macie5[0]:
+ in_macie5[0] = 0
+ return '/**/'
+ return ''
+
+ def fn_space_post(group):
+ """ space with token after """
+ if group(5) is None or (
+ group(6) == ':' and not in_rule[0] and not at_group[0]):
+ return ' ' + space_sub(space_subber, group(4))
+ return space_sub(space_subber, group(4))
+
+ def fn_semicolon(group):
+ """ ; handler """
+ return ';' + space_sub(space_subber, group(7))
+
+ def fn_semicolon2(group):
+ """ ; handler """
+ if in_rule[0]:
+ return space_sub(space_subber, group(7))
+ return ';' + space_sub(space_subber, group(7))
+
+ def fn_open(_):
+ """ { handler """
+ if at_group[0]:
+ at_group[0] -= 1
+ else:
+ in_rule[0] = 1
+ return '{'
+
+ def fn_close(_):
+ """ } handler """
+ in_rule[0] = 0
+ return '}'
+
+ def fn_at_group(group):
+ """ @xxx group handler """
+ at_group[0] += 1
+ return group(13)
+
+ def fn_ie7hack(group):
+ """ IE7 Hack handler """
+ if not in_rule[0] and not at_group[0]:
+ in_macie5[0] = 0
+ return group(14) + space_sub(space_subber, group(15))
+ return '>' + space_sub(space_subber, group(15))
+
+ table = (
+ # noqa pylint: disable = C0330
+ None,
+ None,
+ None,
+ None,
+ fn_space_post, # space with token after
+ fn_space_post, # space with token after
+ fn_space_post, # space with token after
+ fn_semicolon, # semicolon
+ fn_semicolon2, # semicolon
+ fn_open, # {
+ fn_close, # }
+ lambda g: g(11), # string
+ lambda g: 'url(%s)' % uri_space_sub(uri_space_subber, g(12)),
+ # url(...)
+ fn_at_group, # @xxx expecting {...}
+ None,
+ fn_ie7hack, # ie7hack
+ None,
+ lambda g: g(16) + ' ' + space_sub(space_subber, g(17)),
+ # :first-line|letter followed
+ # by [{,] (apparently space
+ # needed for IE6)
+ lambda g: nl_unesc_sub('', g(18)), # nl_string
+ lambda g: post_esc_sub(' ', g(19)), # escape
+ )
+
+ def func(match):
+ """ Main subber """
+ idx, group = match.lastindex, match.group
+ if idx > 3:
+ return table[idx](group)
+
+ # shortcuts for frequent operations below:
+ elif idx == 1: # not interesting
+ return group(1)
+ #else: # space with token before or at the beginning
+ return space_sub(space_subber, group(idx))
+
+ return func
+
+ def cssmin(style, keep_bang_comments=False): # pylint: disable = W0621
+ """
+ Minify CSS.
+
+ :Parameters:
+ `style` : ``str``
+ CSS to minify
+
+ `keep_bang_comments` : ``bool``
+ Keep comments starting with an exclamation mark? (``/*!...*/``)
+
+ :Return: Minified style
+ :Rtype: ``str``
+ """
+ return main_sub(main_subber(keep_bang_comments), style)
+
+ return cssmin
+
+cssmin = _make_cssmin()
+
+
+if __name__ == '__main__':
+ def main():
+ """ Main """
+ import sys as _sys
+ keep_bang_comments = (
+ '-b' in _sys.argv[1:]
+ or '-bp' in _sys.argv[1:]
+ or '-pb' in _sys.argv[1:]
+ )
+ if '-p' in _sys.argv[1:] or '-bp' in _sys.argv[1:] \
+ or '-pb' in _sys.argv[1:]:
+ global cssmin # pylint: disable = W0603
+ cssmin = _make_cssmin(python_only=True)
+ _sys.stdout.write(cssmin(
+ _sys.stdin.read(), keep_bang_comments=keep_bang_comments
+ ))
+ main()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/run_tests.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/run_tests.py
new file mode 100755
index 00000000000..9128d743586
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/run_tests.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+#
+# Copyright 2014
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===========
+ Run tests
+===========
+
+Run tests.
+"""
+__author__ = "Andr\xe9 Malo"
+__author__ = getattr(__author__, 'decode', lambda x: __author__)('latin-1')
+__docformat__ = "restructuredtext en"
+
+import os as _os
+import re as _re
+import sys as _sys
+
+from _setup import shell
+from _setup import term
+
+
+def run_tests(basedir, libdir):
+ """ Run output based tests """
+ import rcssmin as _rcssmin
+ py_cssmin = _rcssmin._make_cssmin(python_only=True)
+ c_cssmin = _rcssmin._make_cssmin(python_only=False)
+
+ def run_test(example, output_file):
+ """ Run it """
+ try:
+ fp = open(example, 'r')
+ except IOError:
+ return
+ else:
+ try:
+ input = fp.read()
+ finally:
+ fp.close()
+
+ def load_output(filename):
+ try:
+ fp = open(filename, 'r')
+ except IOError:
+ return None
+ else:
+ try:
+ output = fp.read()
+ finally:
+ fp.close()
+ output = output.strip()
+ if _re.search(r'(?<!\\)(?:\\\\)*\\[0-9a-zA-Z]{1,6}$', output):
+ output += ' '
+ return output
+
+ output = load_output(output_file)
+ output_b = load_output(output_file + '.b')
+
+ def do_test(cssmin, output, **options):
+ try:
+ genout = cssmin(input, **options)
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except:
+ return 1, "%(RED)s exc%(NORMAL)s "
+ else:
+ if output is None:
+ return 1, "%(RED)smiss%(NORMAL)s "
+ elif genout == output or genout == output.rstrip():
+ return 0, "%(GREEN)sOK%(NORMAL)s "
+ else:
+ return 1, "%(RED)sfail%(NORMAL)s "
+
+ erred, out = do_test(py_cssmin, output)
+ erred, c_out = do_test(c_cssmin, output)
+ erred, out_b = do_test(py_cssmin, output_b, keep_bang_comments=True)
+ erred, c_out_b = do_test(c_cssmin, output_b, keep_bang_comments=True)
+
+ term.write(
+ "%(out)s %(out_b)s | %(c_out)s %(c_out_b)s - %%(example)s\n"
+ % locals(),
+ example=_os.path.basename(example),
+ )
+ return erred
+
+ # end
+ # begin main test code
+
+ erred = 0
+ basedir = shell.native(basedir)
+ strip = len(basedir) - len(_os.path.basename(basedir))
+ for dirname, dirs, files in shell.walk(basedir):
+ dirs[:] = [
+ item for item in dirs if item not in ('.svn', '.git', 'out')
+ ]
+ dirs.sort()
+ files = [item for item in files if item.endswith('.css')]
+ if not files:
+ continue
+ if not _os.path.isdir(_os.path.join(basedir, dirname, 'out')):
+ continue
+ term.yellow("---> %s" % (dirname[strip:],))
+ files.sort()
+ for filename in files:
+ if run_test(
+ _os.path.join(dirname, filename),
+ _os.path.join(dirname, 'out', filename[:-4] + '.out'),
+ ): erred = 1
+ term.yellow("<--- %s" % (dirname[strip:],))
+ return erred
+
+
+def main():
+ """ Main """
+ basedir, libdir = None, None
+ accept_opts = True
+ args = []
+ for arg in _sys.argv[1:]:
+ if accept_opts:
+ if arg == '--':
+ accept_opts = False
+ continue
+ elif arg == '-q':
+ term.write = term.green = term.red = term.yellow = \
+ term.announce = \
+ lambda fmt, **kwargs: None
+ continue
+ elif arg == '-p':
+ info = {}
+ for key in term.terminfo():
+ info[key] = ''
+ info['ERASE'] = '\n'
+ term.terminfo.info = info
+ continue
+ elif arg.startswith('-'):
+ _sys.stderr.write("Unrecognized option %r\n" % (arg,))
+ return 2
+ args.append(arg)
+ if len(args) > 2:
+ _sys.stderr.write("Too many arguments\n")
+ return 2
+ elif len(args) < 1:
+ _sys.stderr.write("Missing arguments\n")
+ return 2
+ basedir = args[0]
+ if len(args) > 1:
+ libdir = args[1]
+ return run_tests(basedir, libdir)
+
+
+if __name__ == '__main__':
+ _sys.exit(main())
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/setup.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/setup.py
new file mode 100644
index 00000000000..d4ca570bf29
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rcssmin/setup.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+#
+# Copyright 2006 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys as _sys
+from _setup import run
+
+
+def setup(args=None, _manifest=0):
+ """ Main setup function """
+ from _setup.ext import Extension
+
+ if 'java' in _sys.platform.lower():
+ # no c extension for jython
+ ext = None
+ else:
+ ext=[Extension('_rcssmin', sources=['rcssmin.c'])]
+
+ return run(script_args=args, ext=ext, manifest_only=_manifest)
+
+
+def manifest():
+ """ Create List of packaged files """
+ return setup((), _manifest=1)
+
+
+if __name__ == '__main__':
+ setup()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/LICENSE b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/LICENSE
new file mode 100644
index 00000000000..261eeb9e9f8
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/MANIFEST b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/MANIFEST
new file mode 100644
index 00000000000..474e6f6ff30
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/MANIFEST
@@ -0,0 +1,57 @@
+LICENSE
+MANIFEST
+PKG-INFO
+README.rst
+_setup/__init__.py
+_setup/include/cext.h
+_setup/py2/__init__.py
+_setup/py2/commands.py
+_setup/py2/data.py
+_setup/py2/dist.py
+_setup/py2/ext.py
+_setup/py2/setup.py
+_setup/py2/shell.py
+_setup/py2/util.py
+_setup/py3/__init__.py
+_setup/py3/commands.py
+_setup/py3/data.py
+_setup/py3/dist.py
+_setup/py3/ext.py
+_setup/py3/setup.py
+_setup/py3/shell.py
+_setup/py3/util.py
+bench
+bench.sh
+bench/DateTimeShortcuts.js
+bench/__init__.py
+bench/apiviewer.js
+bench/bootstrap.js
+bench/jquery-1.7.1.js
+bench/jsmin.c
+bench/jsmin.py
+bench/jsmin_2_0_9.py
+bench/knockout-2.0.0.js
+bench/main.py
+bench/markermanager.js
+bench/write.py
+docs/BENCHMARKS
+docs/CHANGES
+docs/CLASSIFIERS
+docs/DESCRIPTION
+docs/PROVIDES
+docs/SUMMARY
+docs/apidoc/api-objects.txt
+docs/apidoc/crarr.png
+docs/apidoc/epydoc.css
+docs/apidoc/epydoc.js
+docs/apidoc/help.html
+docs/apidoc/identifier-index.html
+docs/apidoc/index.html
+docs/apidoc/module-tree.html
+docs/apidoc/redirect.html
+docs/apidoc/rjsmin-module.html
+docs/apidoc/rjsmin-pysrc.html
+package.cfg
+rjsmin.c
+rjsmin.py
+setup.py
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/PKG-INFO b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/PKG-INFO
new file mode 100644
index 00000000000..983bc4f381f
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/PKG-INFO
@@ -0,0 +1,304 @@
+Metadata-Version: 1.1
+Name: rjsmin
+Version: 1.0.12
+Summary: Javascript Minifier
+Home-page: http://opensource.perlig.de/rjsmin/
+Author: André Malo
+Author-email: nd@perlig.de
+License: Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+Download-URL: http://storage.perlig.de/rjsmin/
+Description: =====================
+ Javascript Minifier
+ =====================
+
+ rJSmin is a javascript minifier written in python.
+
+ The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\.
+
+ The module is a re-implementation aiming for speed, so it can be used at
+ runtime (rather than during a preprocessing step). Usually it produces the
+ same results as the original ``jsmin.c``. It differs in the following ways:
+
+ - there is no error detection: unterminated string, regex and comment
+ literals are treated as regular javascript code and minified as such.
+ - Control characters inside string and regex literals are left untouched; they
+ are not converted to spaces (nor to \n)
+ - Newline characters are not allowed inside string and regex literals, except
+ for line continuations in string literals (ECMA-5).
+ - "return /regex/" is recognized correctly.
+ - Line terminators after regex literals are handled more sensibly
+ - "+ +" and "- -" sequences are not collapsed to '++' or '--'
+ - Newlines before ! operators are removed more sensibly
+ - Comments starting with an exclamation mark (``!``) can be kept optionally
+ - rJSmin does not handle streams, but only complete strings. (However, the
+ module provides a "streamy" interface).
+
+ Since most parts of the logic are handled by the regex engine it's way faster
+ than the original python port of ``jsmin.c`` by Baruch Even. The speed factor
+ varies between about 6 and 55 depending on input and python version (it gets
+ faster the more compressed the input already is). Compared to the
+ speed-refactored python port by Dave St.Germain the performance gain is less
+ dramatic but still between 3 and 50 (for huge inputs)). See the
+ docs/BENCHMARKS file for details.
+
+ rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
+
+ Both python 2 (>=2.4) and python 3 are supported.
+
+ .. _jsmin.c by Douglas Crockford: http://www.crockford.com/javascript/jsmin.c
+
+
+ Copyright and License
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ Copyright 2011 - 2015
+ André Malo or his licensors, as applicable.
+
+ The whole package (except for the files in the bench/ directory) is
+ distributed under the Apache License Version 2.0. You'll find a copy in the
+ root directory of the distribution or online at:
+ <http://www.apache.org/licenses/LICENSE-2.0>.
+
+
+ Bugs
+ ~~~~
+
+ No bugs, of course. ;-)
+ But if you've found one or have an idea how to improve rjsmin, feel free
+ to send a pull request on `github <https://github.com/ndparker/rjsmin>`_
+ or send a mail to <rjsmin-bugs@perlig.de>.
+
+
+ Author Information
+ ~~~~~~~~~~~~~~~~~~
+
+ André "nd" Malo <nd perlig.de>
+ GPG: 0x8103A37E
+
+
+ If God intended people to be naked, they would be born that way.
+ -- Oscar Wilde
+
+ .. vim:tw=72 syntax=rest
+Keywords: Javascript,Minimization
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved
+Classifier: License :: OSI Approved :: Apache License, Version 2.0
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: Jython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Text Processing
+Classifier: Topic :: Text Processing :: Filters
+Classifier: Topic :: Utilities
+Provides: rjsmin (1.0)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/README.chromium b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/README.chromium
new file mode 100644
index 00000000000..256518fd917
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/README.chromium
@@ -0,0 +1,18 @@
+Short Name: rJSmin
+URL: http://opensource.perlig.de/rjsmin/
+Version: 1.0.12
+License: Apache 2.0
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+rJSmin is a javascript minifier written in python.
+The minifier is based on the semantics of jsmin.c by Douglas Crockford.
+The module is a re-implementation aiming for speed, so it can be used at runtime (rather than during a preprocessing step). Usually it produces the same results as the original jsmin.c.
+
+Modifications made:
+ - Removed the bench.sh since the file doesn't have the licensing info and
+ caused license checker to fail.
+ - Added a small hack to not clobber template strings. (Not a complete solution
+ since it won't handle nesting. E.g. `${'`'} foo` would probably cause
+ problems).
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/README.rst b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/README.rst
new file mode 100644
index 00000000000..27ae5a1ecb0
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/README.rst
@@ -0,0 +1,142 @@
+.. -*- coding: utf-8 -*-
+
+===========================================
+ rJSmin - A Javascript Minifier For Python
+===========================================
+
+TABLE OF CONTENTS
+-----------------
+
+1. Introduction
+2. Copyright and License
+3. System Requirements
+4. Installation
+5. Documentation
+6. Bugs
+7. Author Information
+
+
+INTRODUCTION
+------------
+
+rJSmin is a javascript minifier written in python.
+
+The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\.
+
+The module is a re-implementation aiming for speed, so it can be used at
+runtime (rather than during a preprocessing step). Usually it produces the
+same results as the original ``jsmin.c``. It differs in the following ways:
+
+- there is no error detection: unterminated string, regex and comment
+ literals are treated as regular javascript code and minified as such.
+- Control characters inside string and regex literals are left untouched; they
+ are not converted to spaces (nor to \\n)
+- Newline characters are not allowed inside string and regex literals, except
+ for line continuations in string literals (ECMA-5).
+- "return /regex/" is recognized correctly.
+- Line terminators after regex literals are handled more sensibly
+- "+ +" and "- -" sequences are not collapsed to '++' or '--'
+- Newlines before ! operators are removed more sensibly
+- Comments starting with an exclamation mark (``!``) can be kept optionally
+- rJSmin does not handle streams, but only complete strings. (However, the
+ module provides a "streamy" interface).
+
+Since most parts of the logic are handled by the regex engine it's way faster
+than the original python port of ``jsmin.c`` by Baruch Even. The speed factor
+varies between about 6 and 55 depending on input and python version (it gets
+faster the more compressed the input already is). Compared to the
+speed-refactored python port by Dave St.Germain the performance gain is less
+dramatic but still between 3 and 50 (for huge inputs). See the docs/BENCHMARKS
+file for details.
+
+rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
+
+.. _jsmin.c by Douglas Crockford: http://www.crockford.com/javascript/jsmin.c
+
+
+COPYRIGHT AND LICENSE
+---------------------
+
+Copyright 2011 - 2015
+André Malo or his licensors, as applicable.
+
+The whole package (except for the files in the bench/ directory)
+is distributed under the Apache License Version 2.0. You'll find a copy in the
+root directory of the distribution or online at:
+<http://www.apache.org/licenses/LICENSE-2.0>.
+
+
+SYSTEM REQUIREMENTS
+-------------------
+
+Both python 2 (>=2.4) and python 3 are supported.
+
+
+INSTALLATION
+------------
+
+Using pip
+~~~~~~~~~
+
+$ pip install rjsmin
+
+
+Using distutils
+~~~~~~~~~~~~~~~
+
+$ python setup.py install
+
+The following extra options to the install command may be of interest:
+
+ --without-c-extensions Don't install C extensions
+ --without-docs Do not install documentation files
+
+
+Drop-in
+~~~~~~~
+
+rJSmin effectively consists of two files: rjsmin.py and rjsmin.c, the
+latter being entirely optional. So, for simple integration you can just
+copy rjsmin.py into your project and use it.
+
+
+DOCUMENTATION
+-------------
+
+A generated API documentation is available in the docs/apidoc/ directory.
+But you can just look into the module. It provides a simple function,
+called jsmin which takes the script as a string and returns the minified
+script as a string.
+
+The module additionally provides a "streamy" interface similar to the one
+jsmin.c provides:
+
+$ python -mrjsmin <script >minified
+
+It takes two options:
+
+ -b Keep bang-comments (Comments starting with an exclamation mark)
+ -p Force using the python implementation (not the C implementation)
+
+The latest documentation is also available online at
+<http://opensource.perlig.de/rjsmin/>.
+
+
+BUGS
+----
+
+No bugs, of course. ;-)
+But if you've found one or have an idea how to improve rjsmin, feel free
+to send a pull request on `github <https://github.com/ndparker/rjsmin>`_
+or send a mail to <rjsmin-bugs@perlig.de>.
+
+
+AUTHOR INFORMATION
+------------------
+
+André "nd" Malo <nd@perlig.de>
+GPG: 0x8103A37E
+
+
+ If God intended people to be naked, they would be born that way.
+ -- Oscar Wilde
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/__init__.py
new file mode 100644
index 00000000000..77dc23c8412
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/__init__.py
@@ -0,0 +1,39 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ Package _setup
+================
+
+This package provides tools for main package setup.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import os as _os
+import sys as _sys
+
+if _sys.version_info[0] == 2:
+ __path__ = [_os.path.join(__path__[0], 'py2')]
+ __author__ = __author__.decode('latin-1')
+elif _sys.version_info[0] == 3:
+ __path__ = [_os.path.join(__path__[0], 'py3')]
+else:
+ raise RuntimeError("Unsupported python version")
+del _os, _sys
+
+from _setup.setup import run # pylint: disable = W0611
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/include/cext.h b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/include/cext.h
new file mode 100644
index 00000000000..78fa7f53ab3
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/include/cext.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2006 - 2014
+ * Andr\xe9 Malo or his licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * central naming stuff
+ */
+
+#ifndef SETUP_CEXT_H
+#define SETUP_CEXT_H
+
+#ifndef EXT_MODULE
+#error EXT_MODULE must be defined outside of this file (-DEXT_MODULE=...)
+#endif
+
+/*
+ * include core header files
+ */
+#define PY_SSIZE_T_CLEAN
+
+#include "Python.h"
+#include "structmember.h"
+
+/*
+ * define our helper macros depending on the stuff above
+ */
+#define STRINGIFY(n) STRINGIFY_HELPER(n)
+#define STRINGIFY_HELPER(n) #n
+#define CONCATENATE(first, second) CONCATENATE_HELPER(first, second)
+#define CONCATENATE_HELPER(first, second) first##second
+
+#define EXT_MODULE_NAME STRINGIFY(EXT_MODULE)
+#ifdef EXT_PACKAGE
+#define EXT_PACKAGE_NAME STRINGIFY(EXT_PACKAGE)
+#define EXT_MODULE_PATH EXT_PACKAGE_NAME "." EXT_MODULE_NAME
+#else
+#define EXT_PACKAGE_NAME ""
+#define EXT_MODULE_PATH EXT_MODULE_NAME
+#endif
+
+#define EXT_DOCS_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, __doc__))
+#define EXT_METHODS_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, _methods))
+#define EXT_METHODS static PyMethodDef EXT_METHODS_VAR[]
+
+#define EXT_DEFINE_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, _module))
+
+/* Py3K Support */
+#if PY_MAJOR_VERSION >= 3
+
+#define EXT3
+
+#ifndef Py_TPFLAGS_HAVE_CLASS
+#define Py_TPFLAGS_HAVE_CLASS (0)
+#endif
+
+#ifndef Py_TPFLAGS_HAVE_WEAKREFS
+#define Py_TPFLAGS_HAVE_WEAKREFS (0)
+#endif
+
+#ifndef Py_TPFLAGS_HAVE_ITER
+#define Py_TPFLAGS_HAVE_ITER (0)
+#endif
+
+#ifndef PyMODINIT_FUNC
+#define EXT_INIT_FUNC PyObject *CONCATENATE(PyInit_, EXT_MODULE)(void)
+#else
+#define EXT_INIT_FUNC PyMODINIT_FUNC CONCATENATE(PyInit_, EXT_MODULE)(void)
+#endif
+
+#define EXT_DEFINE(name, methods, doc) \
+static struct PyModuleDef EXT_DEFINE_VAR = { \
+ PyModuleDef_HEAD_INIT, \
+ name, \
+ doc, \
+ -1, \
+ methods, \
+ NULL, \
+ NULL, \
+ NULL, \
+ NULL \
+}
+
+#define EXT_CREATE(def) (PyModule_Create(def))
+#define EXT_INIT_ERROR(module) do {Py_XDECREF(module); return NULL;} while(0)
+#define EXT_INIT_RETURN(module) return module
+
+#define EXT_DOC_UNICODE(m)
+
+#else /* end py3k */
+
+#define EXT2
+
+#ifndef PyVarObject_HEAD_INIT
+ #define PyVarObject_HEAD_INIT(type, size) \
+ PyObject_HEAD_INIT(type) size,
+#endif
+
+#ifndef PyMODINIT_FUNC
+#define EXT_INIT_FUNC void CONCATENATE(init, EXT_MODULE)(void)
+#else
+#define EXT_INIT_FUNC PyMODINIT_FUNC CONCATENATE(init, EXT_MODULE)(void)
+#endif
+
+#define EXT_DEFINE__STRUCT \
+ CONCATENATE(struct, CONCATENATE(EXT_MODULE, _module))
+
+struct EXT_DEFINE__STRUCT {
+ char *m_name;
+ char *m_doc;
+ PyMethodDef *m_methods;
+};
+#define EXT_DEFINE(name, methods, doc) \
+static struct EXT_DEFINE__STRUCT EXT_DEFINE_VAR = { \
+ name, \
+ doc, \
+ methods \
+}
+
+#define EXT_CREATE(def) ((def)->m_doc \
+ ? Py_InitModule3((def)->m_name, (def)->m_methods, (def)->m_doc) \
+ : Py_InitModule((def)->m_name, (def)->m_methods) \
+)
+#define EXT_INIT_ERROR(module) return
+#define EXT_INIT_RETURN(module) return
+
+#define EXT_DOC_UNICODE(m) do { \
+ PyObject *doc__, *uni__; \
+ int res__; \
+ \
+ if ((doc__ = PyObject_GetAttrString(m, "__doc__"))) { \
+ uni__ = PyUnicode_FromEncodedObject(doc__, "utf-8", "strict"); \
+ Py_DECREF(doc__); \
+ if (!uni__) \
+ EXT_INIT_ERROR(m); \
+ res__ = PyObject_SetAttrString(m, "__doc__", uni__); \
+ Py_DECREF(uni__); \
+ if (res__ == -1) \
+ EXT_INIT_ERROR(m); \
+ } \
+ else if (!(PyErr_Occurred() \
+ && PyErr_ExceptionMatches(PyExc_AttributeError))) \
+ EXT_INIT_ERROR(m); \
+} while(0)
+
+#endif /* end py2K */
+
+#define EXT_INIT_TYPE(module, type) do { \
+ if (PyType_Ready(type) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+#define EXT_ADD_TYPE(module, name, type) do { \
+ Py_INCREF(type); \
+ if (PyModule_AddObject(module, name, (PyObject *)(type)) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+#define EXT_ADD_UNICODE(module, name, string, encoding) do { \
+ if (PyModule_AddObject( \
+ module, \
+ name, \
+ PyUnicode_Decode( \
+ string, \
+ sizeof(string) - 1, \
+ encoding, \
+ "strict" \
+ )) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+#define EXT_ADD_STRING(module, name, string) do { \
+ if (PyModule_AddStringConstant(module, name, string) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+#define EXT_ADD_INT(module, name, number) do { \
+ if (PyModule_AddIntConstant(module, name, number) < 0) \
+ EXT_INIT_ERROR(module); \
+} while (0)
+
+
+/* PEP 353 support, implemented as of python 2.5 */
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#define PyInt_FromSsize_t(arg) PyInt_FromLong((long)arg)
+#define PyInt_AsSsize_t(arg) (int)PyInt_AsLong(arg)
+#define PY_SSIZE_T_MAX ((Py_ssize_t)INT_MAX)
+#endif
+
+/*
+ * some helper macros (Python 2.4)
+ */
+#ifndef Py_VISIT
+#define Py_VISIT(op) do { \
+ if (op) { \
+ int vret = visit((op), arg); \
+ if (vret) return vret; \
+ } \
+} while (0)
+#endif
+
+#ifdef Py_CLEAR
+#undef Py_CLEAR
+#endif
+#define Py_CLEAR(op) do { \
+ if (op) { \
+ PyObject *tmp__ = (PyObject *)(op); \
+ (op) = NULL; \
+ Py_DECREF(tmp__); \
+ } \
+} while (0)
+
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
+#endif
+
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
+#endif
+
+/* Macros for inline documentation. (Python 2.3) */
+#ifndef PyDoc_VAR
+#define PyDoc_VAR(name) static char name[]
+#endif
+
+#ifndef PyDoc_STRVAR
+#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str)
+#endif
+
+#ifndef PyDoc_STR
+#ifdef WITH_DOC_STRINGS
+#define PyDoc_STR(str) str
+#else
+#define PyDoc_STR(str) ""
+#endif
+#endif
+
+/* Basestring check (basestring introduced in Python 2.3) */
+#if PY_VERSION_HEX < 0x02030000
+#define BaseString_Check(type) ( \
+ PyObject_TypeCheck((type), &PyString_Type) \
+ || PyObject_TypeCheck((type), &PyUnicode_Type) \
+)
+#else
+#define BaseString_Check(type) PyObject_TypeCheck((type), &PyBaseString_Type)
+#endif
+
+#define GENERIC_ALLOC(type) \
+ ((void *)((PyTypeObject *)type)->tp_alloc(type, (Py_ssize_t)0))
+
+/* PyPy doesn't define it */
+#ifndef PyType_IS_GC
+#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
+#endif
+
+#ifndef Py_TYPE
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+
+#define DEFINE_GENERIC_DEALLOC(prefix) \
+static void prefix##_dealloc(void *self) \
+{ \
+ if (PyType_IS_GC(Py_TYPE(self))) \
+ PyObject_GC_UnTrack(self); \
+ (void)prefix##_clear(self); \
+ (Py_TYPE(self))->tp_free((PyObject *)self); \
+}
+
+#endif /* SETUP_CEXT_H */
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/__init__.py
new file mode 100644
index 00000000000..9582ecc1087
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/__init__.py
@@ -0,0 +1,27 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ Package _setup
+================
+
+This package provides tools for main package setup.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from _setup.setup import run # pylint: disable = W0611
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/commands.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/commands.py
new file mode 100644
index 00000000000..a41b166e0a5
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/commands.py
@@ -0,0 +1,267 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Command extenders
+===================
+
+Command extenders.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+__test__ = False
+
+from distutils import fancy_getopt as _fancy_getopt
+from distutils.command import build as _build
+from distutils.command import build_ext as _build_ext
+from distutils.command import install as _install
+from distutils.command import install_data as _install_data
+from distutils.command import install_lib as _install_lib
+import os as _os
+
+from _setup.util import log
+
+_option_defaults = {}
+_option_inherits = {}
+_option_finalizers = {}
+_command_mapping = {
+ 'install': 'Install',
+ 'install_data': 'InstallData',
+ 'install_lib': 'InstallLib',
+ 'build': 'Build',
+ 'build_ext': 'BuildExt',
+}
+
+
+def add_option(command, long_name, help_text, short_name=None, default=None,
+ inherit=None):
+ """ Add an option """
+ try:
+ command_class = globals()[_command_mapping[command]]
+ except KeyError:
+ raise ValueError("Unknown command %r" % (command,))
+ for opt in command_class.user_options:
+ if opt[0] == long_name:
+ break
+ else:
+ opt = (long_name, short_name, help_text)
+ command_class.user_options.append(opt)
+ if not long_name.endswith('='):
+ command_class.boolean_options.append(long_name)
+ attr_name = _fancy_getopt.translate_longopt(long_name)
+ else:
+ attr_name = _fancy_getopt.translate_longopt(long_name[:-1])
+ if not _option_defaults.has_key(command):
+ _option_defaults[command] = []
+ if inherit is not None:
+ if isinstance(inherit, (str, unicode)):
+ inherit = [inherit]
+ for i_inherit in inherit:
+ add_option(
+ i_inherit, long_name, help_text, short_name, default
+ )
+ default = None
+ if not _option_inherits.has_key(command):
+ _option_inherits[command] = []
+ for i_inherit in inherit:
+ for i_command, opt_name in _option_inherits[command]:
+ if i_command == i_inherit and opt_name == attr_name:
+ break
+ else:
+ _option_inherits[command].append((i_inherit, attr_name))
+ _option_defaults[command].append((attr_name, default))
+
+
+def add_finalizer(command, key, func):
+ """ Add finalizer """
+ if not _option_finalizers.has_key(command):
+ _option_finalizers[command] = {}
+ if not _option_finalizers[command].has_key(key):
+ _option_finalizers[command][key] = func
+
+
+class Install(_install.install):
+ """ Extended installer to reflect the additional data options """
+ user_options = _install.install.user_options + [
+ ('single-version-externally-managed', None,
+ "Compat option. Does not a thing."),
+ ]
+ boolean_options = _install.install.boolean_options + [
+ 'single-version-externally-managed'
+ ]
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install.install.initialize_options(self)
+ self.single_version_externally_managed = None
+ if _option_defaults.has_key('install'):
+ for opt_name, default in _option_defaults['install']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install.install.finalize_options(self)
+ if _option_inherits.has_key('install'):
+ for parent, opt_name in _option_inherits['install']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('install'):
+ for func in _option_finalizers['install'].values():
+ func(self)
+
+
+class InstallData(_install_data.install_data):
+ """ Extended data installer """
+ user_options = _install_data.install_data.user_options + []
+ boolean_options = _install_data.install_data.boolean_options + []
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install_data.install_data.initialize_options(self)
+ if _option_defaults.has_key('install_data'):
+ for opt_name, default in _option_defaults['install_data']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install_data.install_data.finalize_options(self)
+ if _option_inherits.has_key('install_data'):
+ for parent, opt_name in _option_inherits['install_data']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('install_data'):
+ for func in _option_finalizers['install_data'].values():
+ func(self)
+
+
+class InstallLib(_install_lib.install_lib):
+ """ Extended lib installer """
+ user_options = _install_lib.install_lib.user_options + []
+ boolean_options = _install_lib.install_lib.boolean_options + []
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install_lib.install_lib.initialize_options(self)
+ if _option_defaults.has_key('install_lib'):
+ for opt_name, default in _option_defaults['install_lib']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install_lib.install_lib.finalize_options(self)
+ if _option_inherits.has_key('install_lib'):
+ for parent, opt_name in _option_inherits['install_lib']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('install_lib'):
+ for func in _option_finalizers['install_lib'].values():
+ func(self)
+
+
+class BuildExt(_build_ext.build_ext):
+ """
+ Extended extension builder class
+
+ This class allows extensions to provide a ``check_prerequisites`` method
+ which is called before actually building it. The method takes the
+ `BuildExt` instance and returns whether the extension should be skipped or
+ not.
+ """
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _build_ext.build_ext.initialize_options(self)
+ if _option_defaults.has_key('build_ext'):
+ for opt_name, default in _option_defaults['build_ext']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _build_ext.build_ext.finalize_options(self)
+ if _option_inherits.has_key('build_ext'):
+ for parent, opt_name in _option_inherits['build_ext']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('build_ext'):
+ for func in _option_finalizers['build_ext'].values():
+ func(self)
+
+ def build_extension(self, ext):
+ """
+ Build C extension - with extended functionality
+
+ The following features are added here:
+
+ - ``ext.check_prerequisites`` is called before the extension is being
+ built. See `Extension` for details. If the method does not exist,
+ simply no check will be run.
+ - The macros ``EXT_PACKAGE`` and ``EXT_MODULE`` will be filled (or
+ unset) depending on the extensions name, but only if they are not
+ already defined.
+
+ :Parameters:
+ `ext` : `Extension`
+ The extension to build. If it's a pure
+ ``distutils.core.Extension``, simply no prequisites check is
+ applied.
+
+ :Return: whatever ``distutils.command.build_ext.build_ext`` returns
+ :Rtype: any
+ """
+ # handle name macros
+ macros = dict(ext.define_macros or ())
+ tup = ext.name.split('.')
+ if len(tup) == 1:
+ pkg, mod = None, tup[0]
+ else:
+ pkg, mod = '.'.join(tup[:-1]), tup[-1]
+ if pkg is not None and 'EXT_PACKAGE' not in macros:
+ ext.define_macros.append(('EXT_PACKAGE', pkg))
+ if 'EXT_MODULE' not in macros:
+ ext.define_macros.append(('EXT_MODULE', mod))
+ if pkg is None:
+ macros = dict(ext.undef_macros or ())
+ if 'EXT_PACKAGE' not in macros:
+ ext.undef_macros.append('EXT_PACKAGE')
+
+ # handle prereq checks
+ try:
+ checker = ext.check_prerequisites
+ except AttributeError:
+ pass
+ else:
+ if checker(self):
+ log.info("Skipping %s extension" % ext.name)
+ return
+
+ return _build_ext.build_ext.build_extension(self, ext)
+
+
+class Build(_build.build):
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _build.build.initialize_options(self)
+ if _option_defaults.has_key('build'):
+ for opt_name, default in _option_defaults['build']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _build.build.finalize_options(self)
+ if _option_inherits.has_key('build'):
+ for parent, opt_name in _option_inherits['build']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if _option_finalizers.has_key('build'):
+ for func in _option_finalizers['build'].values():
+ func(self)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/data.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/data.py
new file mode 100644
index 00000000000..9cf04e104c2
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/data.py
@@ -0,0 +1,165 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Data distribution
+===================
+
+This module provides tools to simplify data distribution.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from distutils import filelist as _filelist
+import os as _os
+import posixpath as _posixpath
+import sys as _sys
+
+from _setup import commands as _commands
+
+
+def splitpath(path):
+ """ Split a path """
+ drive, path = '', _os.path.normpath(path)
+ try:
+ splitunc = _os.path.splitunc
+ except AttributeError:
+ pass
+ else:
+ drive, path = splitunc(path)
+ if not drive:
+ drive, path = _os.path.splitdrive(path)
+ elems = []
+ try:
+ sep = _os.path.sep
+ except AttributeError:
+ sep = _os.path.join('1', '2')[1:-1]
+ while 1:
+ prefix, path = _os.path.split(path)
+ elems.append(path)
+ if prefix in ('', sep):
+ drive = _os.path.join(drive, prefix)
+ break
+ path = prefix
+ elems.reverse()
+ return drive, elems
+
+
+def finalizer(installer):
+ """ Finalize install_data """
+ data_files = []
+ for item in installer.data_files:
+ if not isinstance(item, Data):
+ data_files.append(item)
+ continue
+ data_files.extend(item.flatten(installer))
+ installer.data_files = data_files
+
+
+class Data(object):
+ """ File list container """
+
+ def __init__(self, files, target=None, preserve=0, strip=0,
+ prefix=None):
+ """ Initialization """
+ self._files = files
+ self._target = target
+ self._preserve = preserve
+ self._strip = strip
+ self._prefix = prefix
+ self.fixup_commands()
+
+ def fixup_commands(self):
+ pass
+
+ def from_templates(cls, *templates, **kwargs):
+ """ Initialize from template """
+ files = _filelist.FileList()
+ for tpl in templates:
+ for line in tpl.split(';'):
+ files.process_template_line(line.strip())
+ files.sort()
+ files.remove_duplicates()
+ result = []
+ for filename in files.files:
+ _, elems = splitpath(filename)
+ if '.svn' in elems or '.git' in elems:
+ continue
+ result.append(filename)
+ return cls(result, **kwargs)
+ from_templates = classmethod(from_templates)
+
+ def flatten(self, installer):
+ """ Flatten the file list to (target, file) tuples """
+ # pylint: disable = W0613
+ if self._prefix:
+ _, prefix = splitpath(self._prefix)
+ telems = prefix
+ else:
+ telems = []
+
+ tmap = {}
+ for fname in self._files:
+ (_, name), target = splitpath(fname), telems
+ if self._preserve:
+ if self._strip:
+ name = name[max(0, min(self._strip, len(name) - 1)):]
+ if len(name) > 1:
+ target = telems + name[:-1]
+ tmap.setdefault(_posixpath.join(*target), []).append(fname)
+ return tmap.items()
+
+
+class Documentation(Data):
+ """ Documentation container """
+
+ def fixup_commands(self):
+ _commands.add_option('install_data', 'without-docs',
+ help_text='Do not install documentation files',
+ inherit='install',
+ )
+ _commands.add_finalizer('install_data', 'documentation', finalizer)
+
+ def flatten(self, installer):
+ """ Check if docs should be installed at all """
+ if installer.without_docs:
+ return []
+ return Data.flatten(self, installer)
+
+
+class Manpages(Documentation):
+ """ Manpages container """
+
+ def dispatch(cls, files):
+ """ Automatically dispatch manpages to their target directories """
+ mpmap = {}
+ for manpage in files:
+ normalized = _os.path.normpath(manpage)
+ _, ext = _os.path.splitext(normalized)
+ if ext.startswith(_os.path.extsep):
+ ext = ext[len(_os.path.extsep):]
+ mpmap.setdefault(ext, []).append(manpage)
+ return [cls(manpages, prefix=_posixpath.join(
+ 'share', 'man', 'man%s' % section,
+ )) for section, manpages in mpmap.items()]
+ dispatch = classmethod(dispatch)
+
+ def flatten(self, installer):
+ """ Check if manpages are suitable """
+ if _sys.platform == 'win32':
+ return []
+ return Documentation.flatten(self, installer)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/dist.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/dist.py
new file mode 100644
index 00000000000..21a65415185
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/dist.py
@@ -0,0 +1,51 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ dist utilities
+================
+
+dist utilities.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import sys as _sys
+
+from _setup import shell as _shell
+
+
+def run_setup(*args, **kwargs):
+ """ Run setup """
+ if 'setup' in kwargs:
+ script = kwargs.get('setup') or 'setup.py'
+ del kwargs['setup']
+ else:
+ script = 'setup.py'
+ if 'fakeroot' in kwargs:
+ fakeroot = kwargs['fakeroot']
+ del kwargs['fakeroot']
+ else:
+ fakeroot = None
+ if kwargs:
+ raise TypeError("Unrecognized keyword parameters")
+
+ script = _shell.native(script)
+ argv = [_sys.executable, script] + list(args)
+ if fakeroot:
+ argv.insert(0, fakeroot)
+ return not _shell.spawn(*argv)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/ext.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/ext.py
new file mode 100644
index 00000000000..bcc0209a53a
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/ext.py
@@ -0,0 +1,254 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ C extension tools
+===================
+
+C extension tools.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+__test__ = False
+
+from distutils import core as _core
+from distutils import errors as _distutils_errors
+import os as _os
+import posixpath as _posixpath
+import shutil as _shutil
+import tempfile as _tempfile
+
+from _setup import commands as _commands
+from _setup.util import log
+
+
+def _install_finalizer(installer):
+ if installer.without_c_extensions:
+ installer.distribution.ext_modules = []
+
+def _build_finalizer(builder):
+ if builder.without_c_extensions:
+ builder.extensions = []
+
+
+class Extension(_core.Extension):
+ """
+ Extension with prerequisite check interface
+
+ If your check is cacheable (during the setup run), override
+ `cached_check_prerequisites`, `check_prerequisites` otherwise.
+
+ :IVariables:
+ `cached_check` : ``bool``
+ The cached check result
+ """
+ cached_check = None
+
+ def __init__(self, *args, **kwargs):
+ """ Initialization """
+ if kwargs.has_key('depends'):
+ self.depends = kwargs['depends'] or []
+ else:
+ self.depends = []
+ _core.Extension.__init__(self, *args, **kwargs)
+
+ # add include path
+ included = _posixpath.join('_setup', 'include')
+ if included not in self.include_dirs:
+ self.include_dirs.append(included)
+
+ # add cext.h to the dependencies
+ cext_h = _posixpath.join(included, 'cext.h')
+ if cext_h not in self.depends:
+ self.depends.append(cext_h)
+
+ _commands.add_option('install_lib', 'without-c-extensions',
+ help_text='Don\'t install C extensions',
+ inherit='install',
+ )
+ _commands.add_finalizer('install_lib', 'c-extensions',
+ _install_finalizer
+ )
+ _commands.add_option('build_ext', 'without-c-extensions',
+ help_text='Don\'t build C extensions',
+ inherit=('build', 'install_lib'),
+ )
+ _commands.add_finalizer('build_ext', 'c-extensions', _build_finalizer)
+
+ def check_prerequisites(self, build):
+ """
+ Check prerequisites
+
+ The check should cover all dependencies needed for the extension to
+ be built and run. The method can do the following:
+
+ - return a false value: the extension will be built
+ - return a true value: the extension will be skipped. This is useful
+ for optional extensions
+ - raise an exception. This is useful for mandatory extensions
+
+ If the check result is cacheable (during the setup run), override
+ `cached_check_prerequisites` instead.
+
+ :Parameters:
+ `build` : `BuildExt`
+ The extension builder
+
+ :Return: Skip the extension?
+ :Rtype: ``bool``
+ """
+ if self.cached_check is None:
+ log.debug("PREREQ check for %s" % self.name)
+ self.cached_check = self.cached_check_prerequisites(build)
+ else:
+ log.debug("PREREQ check for %s (cached)" % self.name)
+ return self.cached_check
+
+ def cached_check_prerequisites(self, build):
+ """
+ Check prerequisites
+
+ The check should cover all dependencies needed for the extension to
+ be built and run. The method can do the following:
+
+ - return a false value: the extension will be built
+ - return a true value: the extension will be skipped. This is useful
+ for optional extensions
+ - raise an exception. This is useful for mandatory extensions
+
+ If the check result is *not* cacheable (during the setup run),
+ override `check_prerequisites` instead.
+
+ :Parameters:
+ `build` : `BuildExt`
+ The extension builder
+
+ :Return: Skip the extension?
+ :Rtype: ``bool``
+ """
+ # pylint: disable = W0613
+ log.debug("Nothing to check for %s!" % self.name)
+ return False
+
+
+class ConfTest(object):
+ """
+ Single conftest abstraction
+
+ :IVariables:
+ `_tempdir` : ``str``
+ The tempdir created for this test
+
+ `src` : ``str``
+ Name of the source file
+
+ `target` : ``str``
+ Target filename
+
+ `compiler` : ``CCompiler``
+ compiler instance
+
+ `obj` : ``list``
+ List of object filenames (``[str, ...]``)
+ """
+ _tempdir = None
+
+ def __init__(self, build, source):
+ """
+ Initialization
+
+ :Parameters:
+ `build` : ``distuils.command.build_ext.build_ext``
+ builder instance
+
+ `source` : ``str``
+ Source of the file to compile
+ """
+ self._tempdir = tempdir = _tempfile.mkdtemp()
+ src = _os.path.join(tempdir, 'conftest.c')
+ fp = open(src, 'w')
+ try:
+ fp.write(source)
+ finally:
+ fp.close()
+ self.src = src
+ self.compiler = compiler = build.compiler
+ self.target = _os.path.join(tempdir, 'conftest')
+ self.obj = compiler.object_filenames([src], output_dir=tempdir)
+
+ def __del__(self):
+ """ Destruction """
+ self.destroy()
+
+ def destroy(self):
+ """ Destroy the conftest leftovers on disk """
+ tempdir, self._tempdir = self._tempdir, None
+ if tempdir is not None:
+ _shutil.rmtree(tempdir)
+
+ def compile(self, **kwargs):
+ """
+ Compile the conftest
+
+ :Parameters:
+ `kwargs` : ``dict``
+ Optional keyword parameters for the compiler call
+
+ :Return: Was the compilation successful?
+ :Rtype: ``bool``
+ """
+ kwargs['output_dir'] = self._tempdir
+ try:
+ self.compiler.compile([self.src], **kwargs)
+ except _distutils_errors.CompileError:
+ return False
+ return True
+
+ def link(self, **kwargs):
+ r"""
+ Link the conftest
+
+ Before you can link the conftest objects they need to be `compile`\d.
+
+ :Parameters:
+ `kwargs` : ``dict``
+ Optional keyword parameters for the linker call
+
+ :Return: Was the linking successful?
+ :Rtype: ``bool``
+ """
+ try:
+ self.compiler.link_executable(self.obj, self.target, **kwargs)
+ except _distutils_errors.LinkError:
+ return False
+ return True
+
+ def pipe(self, mode="r"):
+ r"""
+ Execute the conftest binary and connect to it using a pipe
+
+ Before you can pipe to or from the conftest binary it needs to
+ be `link`\ed.
+
+ :Parameters:
+ `mode` : ``str``
+ Pipe mode - r/w
+
+ :Return: The open pipe
+ :Rtype: ``file``
+ """
+ return _os.popen(self.compiler.executable_filename(self.target), mode)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/setup.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/setup.py
new file mode 100644
index 00000000000..8b15d497af2
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/setup.py
@@ -0,0 +1,421 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Main setup runner
+===================
+
+This module provides a wrapper around the distutils core setup.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import ConfigParser as _config_parser
+from distutils import core as _core
+import os as _os
+import posixpath as _posixpath
+import sys as _sys
+
+from _setup import commands as _commands
+from _setup import data as _data
+from _setup import ext as _ext
+from _setup import util as _util
+from _setup import shell as _shell
+
+
+def check_python_version(impl, version_min, version_max):
+ """ Check python version """
+ if impl == 'python':
+ version_info = _sys.version_info
+ elif impl == 'pypy':
+ version_info = getattr(_sys, 'pypy_version_info', None)
+ if not version_info:
+ return
+ elif impl == 'jython':
+ if not 'java' in _sys.platform.lower():
+ return
+ version_info = _sys.version_info
+ else:
+ raise AssertionError("impl not in ('python', 'pypy', 'jython')")
+
+ pyversion = map(int, version_info[:3])
+ if version_min:
+ min_required = \
+ map(int, '.'.join((version_min, '0.0.0')).split('.')[:3])
+ if pyversion < min_required:
+ raise EnvironmentError("Need at least %s %s (vs. %s)" % (
+ impl, version_min, '.'.join(map(str, pyversion))
+ ))
+ if version_max:
+ max_required = map(int, version_max.split('.'))
+ max_required[-1] += 1
+ if pyversion >= max_required:
+ raise EnvironmentError("Need at max %s %s (vs. %s)" % (
+ impl,
+ version_max,
+ '.'.join(map(str, pyversion))
+ ))
+
+
+def find_description(docs):
+ """
+ Determine the package description from DESCRIPTION
+
+ :Parameters:
+ `docs` : ``dict``
+ Docs config section
+
+ :Return: Tuple of summary, description and license
+ (``('summary', 'description', 'license')``)
+ (all may be ``None``)
+ :Rtype: ``tuple``
+ """
+ summary = None
+ filename = docs.get('meta.summary', 'SUMMARY').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ try:
+ summary = fp.read().strip().splitlines()[0].rstrip()
+ except IndexError:
+ summary = ''
+ finally:
+ fp.close()
+
+ description = None
+ filename = docs.get('meta.description', 'DESCRIPTION').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ description = fp.read().rstrip()
+ finally:
+ fp.close()
+
+ if summary is None and description:
+ from docutils import core
+ summary = core.publish_parts(
+ source=description,
+ source_path=filename,
+ writer_name='html',
+ )['title'].encode('utf-8')
+
+ return summary, description
+
+
+def find_classifiers(docs):
+ """
+ Determine classifiers from CLASSIFIERS
+
+ :return: List of classifiers (``['classifier', ...]``)
+ :rtype: ``list``
+ """
+ filename = docs.get('meta.classifiers', 'CLASSIFIERS').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ content = fp.read()
+ finally:
+ fp.close()
+ content = [item.strip() for item in content.splitlines()]
+ return [item for item in content if item and not item.startswith('#')]
+ return []
+
+
+def find_provides(docs):
+ """
+ Determine provides from PROVIDES
+
+ :return: List of provides (``['provides', ...]``)
+ :rtype: ``list``
+ """
+ filename = docs.get('meta.provides', 'PROVIDES').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ content = fp.read()
+ finally:
+ fp.close()
+ content = [item.strip() for item in content.splitlines()]
+ return [item for item in content if item and not item.startswith('#')]
+ return []
+
+
+def find_license(docs):
+ """
+ Determine license from LICENSE
+
+ :return: License text
+ :rtype: ``str``
+ """
+ filename = docs.get('meta.license', 'LICENSE').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename)
+ try:
+ return fp.read().rstrip()
+ finally:
+ fp.close()
+ return None
+
+
+def find_packages(manifest):
+ """ Determine packages and subpackages """
+ packages = {}
+ collect = manifest.get('packages.collect', '').split()
+ lib = manifest.get('packages.lib', '.')
+ try:
+ sep = _os.path.sep
+ except AttributeError:
+ sep = _os.path.join('1', '2')[1:-1]
+ for root in collect:
+ for dirpath, _, filenames in _shell.walk(_os.path.join(lib, root)):
+ if dirpath.find('.svn') >= 0 or dirpath.find('.git') >= 0:
+ continue
+ if '__init__.py' in filenames:
+ packages[
+ _os.path.normpath(dirpath).replace(sep, '.')
+ ] = None
+ packages = packages.keys()
+ packages.sort()
+ return packages
+
+
+def find_data(name, docs):
+ """ Determine data files """
+ result = []
+ if docs.get('extra', '').strip():
+ result.append(_data.Documentation(docs['extra'].split(),
+ prefix='share/doc/%s' % name,
+ ))
+ if docs.get('examples.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['examples.dir']]
+ if docs.get('examples.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['examples.ignore'].split()
+ ])
+ strip = int(docs.get('examples.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('userdoc.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['userdoc.dir']]
+ if docs.get('userdoc.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['userdoc.ignore'].split()
+ ])
+ strip = int(docs.get('userdoc.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('apidoc.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['apidoc.dir']]
+ if docs.get('apidoc.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['apidoc.ignore'].split()
+ ])
+ strip = int(docs.get('apidoc.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('man', '').strip():
+ result.extend(_data.Manpages.dispatch(docs['man'].split()))
+ return result
+
+
+def make_manifest(manifest, config, docs, kwargs):
+ """ Create file list to pack up """
+ # pylint: disable = R0912
+ kwargs = kwargs.copy()
+ kwargs['script_args'] = ['install']
+ kwargs['packages'] = list(kwargs.get('packages') or ()) + [
+ '_setup', '_setup.py2', '_setup.py3',
+ ] + list(manifest.get('packages.extra', '').split() or ())
+ _core._setup_stop_after = "commandline"
+ try:
+ dist = _core.setup(**kwargs)
+ finally:
+ _core._setup_stop_after = None
+
+ result = ['MANIFEST', 'PKG-INFO', 'setup.py'] + list(config)
+ # TODO: work with default values:
+ for key in ('classifiers', 'description', 'summary', 'provides',
+ 'license'):
+ filename = docs.get('meta.' + key, '').strip()
+ if filename and _os.path.isfile(filename):
+ result.append(filename)
+
+ cmd = dist.get_command_obj("build_py")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("build_py", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+
+ cmd = dist.get_command_obj("build_ext")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("build_ext", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+ for ext in cmd.extensions:
+ if ext.depends:
+ result.extend([_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ) for item in ext.depends])
+
+ cmd = dist.get_command_obj("build_clib")
+ cmd.ensure_finalized()
+ if cmd.libraries:
+ #import pprint; pprint.pprint(("build_clib", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+ for lib in cmd.libraries:
+ if lib[1].get('depends'):
+ result.extend([_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ) for item in lib[1]['depends']])
+
+ cmd = dist.get_command_obj("build_scripts")
+ cmd.ensure_finalized()
+ #import pprint; pprint.pprint(("build_scripts", cmd.get_source_files()))
+ if cmd.get_source_files():
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+
+ cmd = dist.get_command_obj("install_data")
+ cmd.ensure_finalized()
+ #from pprint import pprint; pprint(("install_data", cmd.get_inputs()))
+ try:
+ strings = basestring
+ except NameError:
+ strings = (str, unicode)
+
+ for item in cmd.get_inputs():
+ if isinstance(item, strings):
+ result.append(item)
+ else:
+ result.extend(item[1])
+
+ for item in manifest.get('dist', '').split():
+ result.append(item)
+ if _os.path.isdir(item):
+ for filename in _shell.files(item):
+ result.append(filename)
+
+ result = dict([(item, None) for item in result]).keys()
+ result.sort()
+ return result
+
+
+def run(config=('package.cfg',), ext=None, script_args=None, manifest_only=0):
+ """ Main runner """
+ if ext is None:
+ ext = []
+
+ cfg = _util.SafeConfigParser()
+ cfg.read(config)
+ pkg = dict(cfg.items('package'))
+ python_min = pkg.get('python.min') or None
+ python_max = pkg.get('python.max') or None
+ check_python_version('python', python_min, python_max)
+ pypy_min = pkg.get('pypy.min') or None
+ pypy_max = pkg.get('pypy.max') or None
+ check_python_version('pypy', pypy_min, pypy_max)
+ jython_min = pkg.get('jython.min') or None
+ jython_max = pkg.get('jython.max') or None
+ check_python_version('jython', jython_min, jython_max)
+
+ manifest = dict(cfg.items('manifest'))
+ try:
+ docs = dict(cfg.items('docs'))
+ except _config_parser.NoSectionError:
+ docs = {}
+
+ summary, description = find_description(docs)
+ scripts = manifest.get('scripts', '').strip() or None
+ if scripts:
+ scripts = scripts.split()
+ modules = manifest.get('modules', '').strip() or None
+ if modules:
+ modules = modules.split()
+ keywords = docs.get('meta.keywords', '').strip() or None
+ if keywords:
+ keywords = keywords.split()
+ revision = pkg.get('version.revision', '').strip()
+ if revision:
+ revision = int(revision)
+ else:
+ revision = 0
+
+ kwargs = {
+ 'name': pkg['name'],
+ 'version': "%s%s" % (
+ pkg['version.number'],
+ ["", ".dev%d" % (revision,)][_util.humanbool(
+ 'version.dev', pkg.get('version.dev', 'false')
+ )],
+ ),
+ 'provides': find_provides(docs),
+ 'description': summary,
+ 'long_description': description,
+ 'classifiers': find_classifiers(docs),
+ 'keywords': keywords,
+ 'author': pkg['author.name'],
+ 'author_email': pkg['author.email'],
+ 'maintainer': pkg.get('maintainer.name'),
+ 'maintainer_email': pkg.get('maintainer.email'),
+ 'url': pkg.get('url.homepage'),
+ 'download_url': pkg.get('url.download'),
+ 'license': find_license(docs),
+ 'package_dir': {'': manifest.get('packages.lib', '.')},
+ 'packages': find_packages(manifest),
+ 'py_modules': modules,
+ 'ext_modules': ext,
+ 'scripts': scripts,
+ 'script_args': script_args,
+ 'data_files': find_data(pkg['name'], docs),
+ 'cmdclass': {
+ 'build' : _commands.Build,
+ 'build_ext' : _commands.BuildExt,
+ 'install' : _commands.Install,
+ 'install_data': _commands.InstallData,
+ 'install_lib' : _commands.InstallLib,
+ }
+ }
+ for key in ('provides',):
+ if key not in _core.setup_keywords:
+ del kwargs[key]
+
+ if manifest_only:
+ return make_manifest(manifest, config, docs, kwargs)
+
+ # monkey-patch crappy manifest writer away.
+ from distutils.command import sdist
+ sdist.sdist.get_file_list = sdist.sdist.read_manifest
+
+ return _core.setup(**kwargs)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/shell.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/shell.py
new file mode 100644
index 00000000000..4eafb9c8647
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/shell.py
@@ -0,0 +1,478 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Shell utilities
+=================
+
+Shell utilities.
+"""
+from __future__ import generators
+
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import errno as _errno
+import fnmatch as _fnmatch
+import os as _os
+import shutil as _shutil
+import sys as _sys
+import tempfile as _tempfile
+
+cwd = _os.path.dirname(_os.path.abspath(_sys.argv[0]))
+
+class ExitError(RuntimeError):
+ """ Exit error """
+ def __init__(self, code):
+ RuntimeError.__init__(self, code)
+ self.code = code
+ self.signal = None
+
+
+class SignalError(ExitError):
+ """ Signal error """
+ def __init__(self, code, signal):
+ ExitError.__init__(self, code)
+ import signal as _signal
+ self.signal = signal
+ for key, val in vars(_signal).iteritems():
+ if key.startswith('SIG') and not key.startswith('SIG_'):
+ if val == signal:
+ self.signalstr = key[3:]
+ break
+ else:
+ self.signalstr = '%04d' % signal
+
+
+def native(path):
+ """ Convert slash path to native """
+ path = _os.path.sep.join(path.split('/'))
+ return _os.path.normpath(_os.path.join(cwd, path))
+
+
+def cp(src, dest):
+ """ Copy src to dest """
+ _shutil.copy2(native(src), native(dest))
+
+
+def cp_r(src, dest):
+ """ Copy -r src to dest """
+ _shutil.copytree(native(src), native(dest))
+
+
+def rm(dest):
+ """ Remove a file """
+ try:
+ _os.unlink(native(dest))
+ except OSError, e:
+ if _errno.ENOENT != e.errno:
+ raise
+
+def rm_rf(dest):
+ """ Remove a tree """
+ dest = native(dest)
+ if _os.path.exists(dest):
+ for path in files(dest, '*'):
+ _os.chmod(native(path), 0644)
+ _shutil.rmtree(dest)
+
+
+try:
+ mkstemp = _tempfile.mkstemp
+except AttributeError:
+ # helpers stolen from 2.4 tempfile module
+ try:
+ import fcntl as _fcntl
+ except ImportError:
+ def _set_cloexec(fd):
+ """ Set close-on-exec (not implemented, but not an error) """
+ # pylint: disable = W0613
+ pass
+ else:
+ def _set_cloexec(fd):
+ """ Set close-on-exec """
+ try:
+ flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
+ except IOError:
+ pass
+ else:
+ # flags read successfully, modify
+ flags |= _fcntl.FD_CLOEXEC
+ _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
+
+ _text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
+ _text_openflags |= getattr(_os, 'O_NOINHERIT', 0)
+ _text_openflags |= getattr(_os, 'O_NOFOLLOW', 0)
+
+ _bin_openflags = _text_openflags
+ _bin_openflags |= getattr(_os, 'O_BINARY', 0)
+
+ def mkstemp(suffix="", prefix=_tempfile.gettempprefix(), dir=None,
+ text=False):
+ """ Create secure temp file """
+ # pylint: disable = W0622
+ if dir is None:
+ dir = _tempfile.gettempdir()
+ if text:
+ flags = _text_openflags
+ else:
+ flags = _bin_openflags
+ count = 100
+ while count > 0:
+ j = _tempfile._counter.get_next() # pylint: disable = E1101, W0212
+ fname = _os.path.join(dir, prefix + str(j) + suffix)
+ try:
+ fd = _os.open(fname, flags, 0600)
+ except OSError, e:
+ if e.errno == _errno.EEXIST:
+ count -= 1
+ continue
+ raise
+ _set_cloexec(fd)
+ return fd, _os.path.abspath(fname)
+ raise IOError, (_errno.EEXIST, "No usable temporary file name found")
+
+
+def _pipespawn(argv, env):
+ """ Pipe spawn """
+ # pylint: disable = R0912
+ import pickle as _pickle
+ fd, name = mkstemp('.py')
+ try:
+ _os.write(fd, (r"""
+import os
+import pickle
+try:
+ import subprocess
+except ImportError:
+ subprocess = None
+import sys
+
+argv = pickle.loads(%(argv)s)
+env = pickle.loads(%(env)s)
+if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+if subprocess is None:
+ pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
+ result = os.waitpid(pid, 0)[1]
+else:
+ p = subprocess.Popen(argv, env=env)
+ result = p.wait()
+ if result < 0:
+ print "\n%%d 1" %% (-result)
+ sys.exit(2)
+
+if result == 0:
+ sys.exit(0)
+signalled = getattr(os, 'WIFSIGNALED', None)
+if signalled is not None:
+ if signalled(result):
+ print "\n%%d %%d" %% (os.WTERMSIG(result), result & 7)
+ sys.exit(2)
+print "\n%%d" %% (result & 7,)
+sys.exit(3)
+ """.strip() + "\n") % {
+ 'argv': repr(_pickle.dumps(argv)),
+ 'env': repr(_pickle.dumps(env)),
+ })
+ fd, _ = None, _os.close(fd)
+ if _sys.platform == 'win32':
+ argv = []
+ for arg in [_sys.executable, name]:
+ if ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ argv.append(arg)
+ argv = ' '.join(argv)
+ shell = True
+ close_fds = False
+ else:
+ argv = [_sys.executable, name]
+ shell = False
+ close_fds = True
+
+ res = 0
+ try:
+ import subprocess
+ except ImportError:
+ import popen2 as _popen2
+ proc = _popen2.Popen3(argv, False)
+ try:
+ proc.tochild.close()
+ result = proc.fromchild.read()
+ finally:
+ res = proc.wait()
+ else:
+ if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+ proc = subprocess.Popen(argv,
+ shell=shell,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ close_fds=close_fds,
+ env=env,
+ )
+ try:
+ proc.stdin.close()
+ result = proc.stdout.read()
+ finally:
+ res = proc.wait()
+ if res != 0:
+ if res == 2:
+ signal, code = map(int, result.splitlines()[-1].split())
+ raise SignalError(code, signal)
+ elif res == 3:
+ code = int(result.splitlines()[-1].strip())
+ raise ExitError(code)
+ raise ExitError(res)
+
+ return result
+ finally:
+ try:
+ if fd is not None:
+ _os.close(fd)
+ finally:
+ _os.unlink(name)
+
+
+def _filepipespawn(infile, outfile, argv, env):
+ """ File Pipe spawn """
+ try:
+ import subprocess
+ except ImportError:
+ subprocess = None
+ import pickle as _pickle
+ fd, name = mkstemp('.py')
+ try:
+ _os.write(fd, ("""
+import os
+import pickle
+import sys
+
+infile = pickle.loads(%(infile)s)
+outfile = pickle.loads(%(outfile)s)
+argv = pickle.loads(%(argv)s)
+env = pickle.loads(%(env)s)
+
+if infile is not None:
+ infile = open(infile, 'rb')
+ os.dup2(infile.fileno(), 0)
+ infile.close()
+if outfile is not None:
+ outfile = open(outfile, 'wb')
+ os.dup2(outfile.fileno(), 1)
+ outfile.close()
+
+pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
+result = os.waitpid(pid, 0)[1]
+sys.exit(result & 7)
+ """.strip() + "\n") % {
+ 'infile': repr(_pickle.dumps(_os.path.abspath(infile))),
+ 'outfile': repr(_pickle.dumps(_os.path.abspath(outfile))),
+ 'argv': repr(_pickle.dumps(argv)),
+ 'env': repr(_pickle.dumps(env)),
+ })
+ fd, _ = None, _os.close(fd)
+ if _sys.platform == 'win32':
+ argv = []
+ for arg in [_sys.executable, name]:
+ if ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ argv.append(arg)
+ argv = ' '.join(argv)
+ close_fds = False
+ shell = True
+ else:
+ argv = [_sys.executable, name]
+ close_fds = True
+ shell = False
+
+ if subprocess is None:
+ pid = _os.spawnve(_os.P_NOWAIT, argv[0], argv, env)
+ return _os.waitpid(pid, 0)[1]
+ else:
+ p = subprocess.Popen(
+ argv, env=env, shell=shell, close_fds=close_fds
+ )
+ return p.wait()
+ finally:
+ try:
+ if fd is not None:
+ _os.close(fd)
+ finally:
+ _os.unlink(name)
+
+
+def spawn(*argv, **kwargs):
+ """ Spawn a process """
+ try:
+ import subprocess
+ except ImportError:
+ subprocess = None
+
+ if _sys.platform == 'win32':
+ newargv = []
+ for arg in argv:
+ if not arg or ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ newargv.append(arg)
+ argv = newargv
+ close_fds = False
+ shell = True
+ else:
+ close_fds = True
+ shell = False
+
+ env = kwargs.get('env')
+ if env is None:
+ env = dict(_os.environ)
+ if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+ echo = kwargs.get('echo')
+ if echo:
+ print ' '.join(argv)
+ filepipe = kwargs.get('filepipe')
+ if filepipe:
+ return _filepipespawn(
+ kwargs.get('stdin'), kwargs.get('stdout'), argv, env
+ )
+ pipe = kwargs.get('stdout')
+ if pipe:
+ return _pipespawn(argv, env)
+
+ if subprocess is None:
+ pid = _os.spawnve(_os.P_NOWAIT, argv[0], argv, env)
+ return _os.waitpid(pid, 0)[1]
+ else:
+ p = subprocess.Popen(argv, env=env, shell=shell, close_fds=close_fds)
+ return p.wait()
+
+
+try:
+ walk = _os.walk
+except AttributeError:
+ # copy from python 2.4 sources (modulo docs and comments)
+ def walk(top, topdown=True, onerror=None):
+ """ directory tree walker """
+ # pylint: disable = C0103
+ join, isdir, islink = _os.path.join, _os.path.isdir, _os.path.islink
+ listdir, error = _os.listdir, _os.error
+
+ try:
+ names = listdir(top)
+ except error, err:
+ if onerror is not None:
+ onerror(err)
+ return
+
+ dirs, nondirs = [], []
+ for name in names:
+ if isdir(join(top, name)):
+ dirs.append(name)
+ else:
+ nondirs.append(name)
+
+ if topdown:
+ yield top, dirs, nondirs
+ for name in dirs:
+ path = join(top, name)
+ if not islink(path):
+ for x in walk(path, topdown, onerror):
+ yield x
+ if not topdown:
+ yield top, dirs, nondirs
+
+
+def files(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
+ """ Determine a filelist """
+ for dirpath, dirnames, filenames in walk(native(base)):
+ for item in prune:
+ if item in dirnames:
+ dirnames.remove(item)
+
+ filenames.sort()
+ for name in _fnmatch.filter(filenames, wildcard):
+ dest = _os.path.join(dirpath, name)
+ if dest.startswith(cwd):
+ dest = dest.replace(cwd, '', 1)
+ aslist = []
+ head, tail = _os.path.split(dest)
+ while tail:
+ aslist.append(tail)
+ head, tail = _os.path.split(head)
+ aslist.reverse()
+ dest = '/'.join(aslist)
+ yield dest
+
+ if not recursive:
+ break
+ dirnames.sort()
+
+
+def dirs(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
+ """ Determine a filelist """
+ for dirpath, dirnames, filenames in walk(native(base)):
+ for item in prune:
+ if item in dirnames:
+ dirnames.remove(item)
+
+ dirnames.sort()
+ for name in _fnmatch.filter(dirnames, wildcard):
+ dest = _os.path.join(dirpath, name)
+ if dest.startswith(cwd):
+ dest = dest.replace(cwd, '', 1)
+ aslist = []
+ head, tail = _os.path.split(dest)
+ while tail:
+ aslist.append(tail)
+ head, tail = _os.path.split(head)
+ aslist.reverse()
+ dest = '/'.join(aslist)
+ yield dest
+
+ if not recursive:
+ break
+
+
+def frompath(executable):
+ """ Find executable in PATH """
+ # Based on distutils.spawn.find_executable.
+ path = _os.environ.get('PATH', '')
+ paths = [
+ _os.path.expanduser(item)
+ for item in path.split(_os.pathsep)
+ ]
+ ext = _os.path.splitext(executable)[1]
+ exts = ['']
+ if _sys.platform == 'win32' or _os.name == 'os2':
+ eext = ['.exe', '.bat', '.py']
+ if ext not in eext:
+ exts.extend(eext)
+
+ for ext in exts:
+ if not _os.path.isfile(executable + ext):
+ for path in paths:
+ fname = _os.path.join(path, executable + ext)
+ if _os.path.isfile(fname):
+ # the file exists, we have a shot at spawn working
+ return fname
+ else:
+ return executable + ext
+
+ return None
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/util.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/util.py
new file mode 100644
index 00000000000..5c05fac6e4c
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py2/util.py
@@ -0,0 +1,73 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Setup utilities
+=================
+
+Setup utilities.
+"""
+__author__ = u"Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+try:
+ from distutils import log
+except ImportError:
+ class log(object):
+ def info(self, value):
+ print value
+ def debug(self, value):
+ pass
+ log = log()
+
+from distutils import util as _util
+try:
+ from ConfigParser import SafeConfigParser
+except ImportError:
+ import ConfigParser as _config_parser
+ class SafeConfigParser(_config_parser.ConfigParser):
+ """ Safe config parser """
+ def _interpolate(self, section, option, rawval, vars):
+ return rawval
+
+ def items(self, section):
+ return [(key, self.get(section, key))
+ for key in self.options(section)
+ ]
+
+
+def humanbool(name, value):
+ """
+ Determine human boolean value
+
+ :Parameters:
+ `name` : ``str``
+ The config key (used for error message)
+
+ `value` : ``str``
+ The config value
+
+ :Return: The boolean value
+ :Rtype: ``bool``
+
+ :Exceptions:
+ - `ValueError` : The value could not be recognized
+ """
+ try:
+ return _util.strtobool(str(value).strip().lower() or 'no')
+ except ValueError:
+ raise ValueError("Unrecognized config value: %s = %s" % (name, value))
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/__init__.py
new file mode 100644
index 00000000000..6139d510a10
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/__init__.py
@@ -0,0 +1,27 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ Package _setup
+================
+
+This package provides tools for main package setup.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from _setup.setup import run # pylint: disable = W0611
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/commands.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/commands.py
new file mode 100644
index 00000000000..7bfacbc86ef
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/commands.py
@@ -0,0 +1,266 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Command extenders
+===================
+
+Command extenders.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+__test__ = False
+
+from distutils import fancy_getopt as _fancy_getopt
+from distutils import log
+from distutils.command import build as _build
+from distutils.command import build_ext as _build_ext
+from distutils.command import install as _install
+from distutils.command import install_data as _install_data
+from distutils.command import install_lib as _install_lib
+import os as _os
+
+_option_defaults = {}
+_option_inherits = {}
+_option_finalizers = {}
+_command_mapping = {
+ 'install': 'Install',
+ 'install_data': 'InstallData',
+ 'install_lib': 'InstallLib',
+ 'build': 'Build',
+ 'build_ext': 'BuildExt',
+}
+
+
+def add_option(command, long_name, help_text, short_name=None, default=None,
+ inherit=None):
+ """ Add an option """
+ try:
+ command_class = globals()[_command_mapping[command]]
+ except KeyError:
+ raise ValueError("Unknown command %r" % (command,))
+ for opt in command_class.user_options:
+ if opt[0] == long_name:
+ break
+ else:
+ opt = (long_name, short_name, help_text)
+ command_class.user_options.append(opt)
+ if not long_name.endswith('='):
+ command_class.boolean_options.append(long_name)
+ attr_name = _fancy_getopt.translate_longopt(long_name)
+ else:
+ attr_name = _fancy_getopt.translate_longopt(long_name[:-1])
+ if command not in _option_defaults:
+ _option_defaults[command] = []
+ if inherit is not None:
+ if isinstance(inherit, str):
+ inherit = [inherit]
+ for i_inherit in inherit:
+ add_option(
+ i_inherit, long_name, help_text, short_name, default
+ )
+ default = None
+ if command not in _option_inherits:
+ _option_inherits[command] = []
+ for i_inherit in inherit:
+ for i_command, opt_name in _option_inherits[command]:
+ if i_command == i_inherit and opt_name == attr_name:
+ break
+ else:
+ _option_inherits[command].append((i_inherit, attr_name))
+ _option_defaults[command].append((attr_name, default))
+
+
+def add_finalizer(command, key, func):
+ """ Add finalizer """
+ if command not in _option_finalizers:
+ _option_finalizers[command] = {}
+ if key not in _option_finalizers[command]:
+ _option_finalizers[command][key] = func
+
+
+class Install(_install.install):
+ """ Extended installer to reflect the additional data options """
+ user_options = _install.install.user_options + [
+ ('single-version-externally-managed', None,
+ "Compat option. Does not a thing."),
+ ]
+ boolean_options = _install.install.boolean_options + [
+ 'single-version-externally-managed'
+ ]
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install.install.initialize_options(self)
+ self.single_version_externally_managed = None
+ if 'install' in _option_defaults:
+ for opt_name, default in _option_defaults['install']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install.install.finalize_options(self)
+ if 'install' in _option_inherits:
+ for parent, opt_name in _option_inherits['install']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'install' in _option_finalizers:
+ for func in list(_option_finalizers['install'].values()):
+ func(self)
+
+
+class InstallData(_install_data.install_data):
+ """ Extended data installer """
+ user_options = _install_data.install_data.user_options + []
+ boolean_options = _install_data.install_data.boolean_options + []
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install_data.install_data.initialize_options(self)
+ if 'install_data' in _option_defaults:
+ for opt_name, default in _option_defaults['install_data']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install_data.install_data.finalize_options(self)
+ if 'install_data' in _option_inherits:
+ for parent, opt_name in _option_inherits['install_data']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'install_data' in _option_finalizers:
+ for func in list(_option_finalizers['install_data'].values()):
+ func(self)
+
+
+class InstallLib(_install_lib.install_lib):
+ """ Extended lib installer """
+ user_options = _install_lib.install_lib.user_options + []
+ boolean_options = _install_lib.install_lib.boolean_options + []
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _install_lib.install_lib.initialize_options(self)
+ if 'install_lib' in _option_defaults:
+ for opt_name, default in _option_defaults['install_lib']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _install_lib.install_lib.finalize_options(self)
+ if 'install_lib' in _option_inherits:
+ for parent, opt_name in _option_inherits['install_lib']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'install_lib' in _option_finalizers:
+ for func in list(_option_finalizers['install_lib'].values()):
+ func(self)
+
+
+class BuildExt(_build_ext.build_ext):
+ """
+ Extended extension builder class
+
+ This class allows extensions to provide a ``check_prerequisites`` method
+ which is called before actually building it. The method takes the
+ `BuildExt` instance and returns whether the extension should be skipped or
+ not.
+ """
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _build_ext.build_ext.initialize_options(self)
+ if 'build_ext' in _option_defaults:
+ for opt_name, default in _option_defaults['build_ext']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _build_ext.build_ext.finalize_options(self)
+ if 'build_ext' in _option_inherits:
+ for parent, opt_name in _option_inherits['build_ext']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'build_ext' in _option_finalizers:
+ for func in list(_option_finalizers['build_ext'].values()):
+ func(self)
+
+ def build_extension(self, ext):
+ """
+ Build C extension - with extended functionality
+
+ The following features are added here:
+
+ - ``ext.check_prerequisites`` is called before the extension is being
+ built. See `Extension` for details. If the method does not exist,
+ simply no check will be run.
+ - The macros ``EXT_PACKAGE`` and ``EXT_MODULE`` will be filled (or
+ unset) depending on the extensions name, but only if they are not
+ already defined.
+
+ :Parameters:
+ `ext` : `Extension`
+ The extension to build. If it's a pure
+ ``distutils.core.Extension``, simply no prequisites check is
+ applied.
+
+ :Return: whatever ``distutils.command.build_ext.build_ext`` returns
+ :Rtype: any
+ """
+ # handle name macros
+ macros = dict(ext.define_macros or ())
+ tup = ext.name.split('.')
+ if len(tup) == 1:
+ pkg, mod = None, tup[0]
+ else:
+ pkg, mod = '.'.join(tup[:-1]), tup[-1]
+ if pkg is not None and 'EXT_PACKAGE' not in macros:
+ ext.define_macros.append(('EXT_PACKAGE', pkg))
+ if 'EXT_MODULE' not in macros:
+ ext.define_macros.append(('EXT_MODULE', mod))
+ if pkg is None:
+ macros = dict(ext.undef_macros or ())
+ if 'EXT_PACKAGE' not in macros:
+ ext.undef_macros.append('EXT_PACKAGE')
+
+ # handle prereq checks
+ try:
+ checker = ext.check_prerequisites
+ except AttributeError:
+ pass
+ else:
+ if checker(self):
+ log.info("Skipping %s extension" % ext.name)
+ return
+
+ return _build_ext.build_ext.build_extension(self, ext)
+
+
+class Build(_build.build):
+
+ def initialize_options(self):
+ """ Prepare for new options """
+ _build.build.initialize_options(self)
+ if 'build' in _option_defaults:
+ for opt_name, default in _option_defaults['build']:
+ setattr(self, opt_name, default)
+
+ def finalize_options(self):
+ """ Finalize options """
+ _build.build.finalize_options(self)
+ if 'build' in _option_inherits:
+ for parent, opt_name in _option_inherits['build']:
+ self.set_undefined_options(parent, (opt_name, opt_name))
+ if 'build' in _option_finalizers:
+ for func in list(_option_finalizers['build'].values()):
+ func(self)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/data.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/data.py
new file mode 100644
index 00000000000..d4221735768
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/data.py
@@ -0,0 +1,165 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Data distribution
+===================
+
+This module provides tools to simplify data distribution.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from distutils import filelist as _filelist
+import os as _os
+import posixpath as _posixpath
+import sys as _sys
+
+from _setup import commands as _commands
+
+
+def splitpath(path):
+ """ Split a path """
+ drive, path = '', _os.path.normpath(path)
+ try:
+ splitunc = _os.path.splitunc
+ except AttributeError:
+ pass
+ else:
+ drive, path = splitunc(path)
+ if not drive:
+ drive, path = _os.path.splitdrive(path)
+ elems = []
+ try:
+ sep = _os.path.sep
+ except AttributeError:
+ sep = _os.path.join('1', '2')[1:-1]
+ while 1:
+ prefix, path = _os.path.split(path)
+ elems.append(path)
+ if prefix in ('', sep):
+ drive = _os.path.join(drive, prefix)
+ break
+ path = prefix
+ elems.reverse()
+ return drive, elems
+
+
+def finalizer(installer):
+ """ Finalize install_data """
+ data_files = []
+ for item in installer.data_files:
+ if not isinstance(item, Data):
+ data_files.append(item)
+ continue
+ data_files.extend(item.flatten(installer))
+ installer.data_files = data_files
+
+
+class Data(object):
+ """ File list container """
+
+ def __init__(self, files, target=None, preserve=0, strip=0,
+ prefix=None):
+ """ Initialization """
+ self._files = files
+ self._target = target
+ self._preserve = preserve
+ self._strip = strip
+ self._prefix = prefix
+ self.fixup_commands()
+
+ def fixup_commands(self):
+ pass
+
+ def from_templates(cls, *templates, **kwargs):
+ """ Initialize from template """
+ files = _filelist.FileList()
+ for tpl in templates:
+ for line in tpl.split(';'):
+ files.process_template_line(line.strip())
+ files.sort()
+ files.remove_duplicates()
+ result = []
+ for filename in files.files:
+ _, elems = splitpath(filename)
+ if '.svn' in elems or '.git' in elems:
+ continue
+ result.append(filename)
+ return cls(result, **kwargs)
+ from_templates = classmethod(from_templates)
+
+ def flatten(self, installer):
+ """ Flatten the file list to (target, file) tuples """
+ # pylint: disable = W0613
+ if self._prefix:
+ _, prefix = splitpath(self._prefix)
+ telems = prefix
+ else:
+ telems = []
+
+ tmap = {}
+ for fname in self._files:
+ (_, name), target = splitpath(fname), telems
+ if self._preserve:
+ if self._strip:
+ name = name[max(0, min(self._strip, len(name) - 1)):]
+ if len(name) > 1:
+ target = telems + name[:-1]
+ tmap.setdefault(_posixpath.join(*target), []).append(fname)
+ return list(tmap.items())
+
+
+class Documentation(Data):
+ """ Documentation container """
+
+ def fixup_commands(self):
+ _commands.add_option('install_data', 'without-docs',
+ help_text='Do not install documentation files',
+ inherit='install',
+ )
+ _commands.add_finalizer('install_data', 'documentation', finalizer)
+
+ def flatten(self, installer):
+ """ Check if docs should be installed at all """
+ if installer.without_docs:
+ return []
+ return Data.flatten(self, installer)
+
+
+class Manpages(Documentation):
+ """ Manpages container """
+
+ def dispatch(cls, files):
+ """ Automatically dispatch manpages to their target directories """
+ mpmap = {}
+ for manpage in files:
+ normalized = _os.path.normpath(manpage)
+ _, ext = _os.path.splitext(normalized)
+ if ext.startswith(_os.path.extsep):
+ ext = ext[len(_os.path.extsep):]
+ mpmap.setdefault(ext, []).append(manpage)
+ return [cls(manpages, prefix=_posixpath.join(
+ 'share', 'man', 'man%s' % section,
+ )) for section, manpages in list(mpmap.items())]
+ dispatch = classmethod(dispatch)
+
+ def flatten(self, installer):
+ """ Check if manpages are suitable """
+ if _sys.platform == 'win32':
+ return []
+ return Documentation.flatten(self, installer)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/dist.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/dist.py
new file mode 100644
index 00000000000..cce21e57a63
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/dist.py
@@ -0,0 +1,51 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+================
+ dist utilities
+================
+
+dist utilities.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import sys as _sys
+
+from _setup import shell as _shell
+
+
+def run_setup(*args, **kwargs):
+ """ Run setup """
+ if 'setup' in kwargs:
+ script = kwargs.get('setup') or 'setup.py'
+ del kwargs['setup']
+ else:
+ script = 'setup.py'
+ if 'fakeroot' in kwargs:
+ fakeroot = kwargs['fakeroot']
+ del kwargs['fakeroot']
+ else:
+ fakeroot = None
+ if kwargs:
+ raise TypeError("Unrecognized keyword parameters")
+
+ script = _shell.native(script)
+ argv = [_sys.executable, script] + list(args)
+ if fakeroot:
+ argv.insert(0, fakeroot)
+ return not _shell.spawn(*argv)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/ext.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/ext.py
new file mode 100644
index 00000000000..852c466547e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/ext.py
@@ -0,0 +1,253 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ C extension tools
+===================
+
+C extension tools.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+__test__ = False
+
+from distutils import core as _core
+from distutils import errors as _distutils_errors
+from distutils import log
+import os as _os
+import posixpath as _posixpath
+import shutil as _shutil
+import tempfile as _tempfile
+
+from _setup import commands as _commands
+
+def _install_finalizer(installer):
+ if installer.without_c_extensions:
+ installer.distribution.ext_modules = []
+
+def _build_finalizer(builder):
+ if builder.without_c_extensions:
+ builder.extensions = []
+
+
+class Extension(_core.Extension):
+ """
+ Extension with prerequisite check interface
+
+ If your check is cacheable (during the setup run), override
+ `cached_check_prerequisites`, `check_prerequisites` otherwise.
+
+ :IVariables:
+ `cached_check` : ``bool``
+ The cached check result
+ """
+ cached_check = None
+
+ def __init__(self, *args, **kwargs):
+ """ Initialization """
+ if 'depends' in kwargs:
+ self.depends = kwargs['depends'] or []
+ else:
+ self.depends = []
+ _core.Extension.__init__(self, *args, **kwargs)
+
+ # add include path
+ included = _posixpath.join('_setup', 'include')
+ if included not in self.include_dirs:
+ self.include_dirs.append(included)
+
+ # add cext.h to the dependencies
+ cext_h = _posixpath.join(included, 'cext.h')
+ if cext_h not in self.depends:
+ self.depends.append(cext_h)
+
+ _commands.add_option('install_lib', 'without-c-extensions',
+ help_text='Don\'t install C extensions',
+ inherit='install',
+ )
+ _commands.add_finalizer('install_lib', 'c-extensions',
+ _install_finalizer
+ )
+ _commands.add_option('build_ext', 'without-c-extensions',
+ help_text='Don\'t build C extensions',
+ inherit=('build', 'install_lib'),
+ )
+ _commands.add_finalizer('build_ext', 'c-extensions', _build_finalizer)
+
+ def check_prerequisites(self, build):
+ """
+ Check prerequisites
+
+ The check should cover all dependencies needed for the extension to
+ be built and run. The method can do the following:
+
+ - return a false value: the extension will be built
+ - return a true value: the extension will be skipped. This is useful
+ for optional extensions
+ - raise an exception. This is useful for mandatory extensions
+
+ If the check result is cacheable (during the setup run), override
+ `cached_check_prerequisites` instead.
+
+ :Parameters:
+ `build` : `BuildExt`
+ The extension builder
+
+ :Return: Skip the extension?
+ :Rtype: ``bool``
+ """
+ if self.cached_check is None:
+ log.debug("PREREQ check for %s" % self.name)
+ self.cached_check = self.cached_check_prerequisites(build)
+ else:
+ log.debug("PREREQ check for %s (cached)" % self.name)
+ return self.cached_check
+
+ def cached_check_prerequisites(self, build):
+ """
+ Check prerequisites
+
+ The check should cover all dependencies needed for the extension to
+ be built and run. The method can do the following:
+
+ - return a false value: the extension will be built
+ - return a true value: the extension will be skipped. This is useful
+ for optional extensions
+ - raise an exception. This is useful for mandatory extensions
+
+ If the check result is *not* cacheable (during the setup run),
+ override `check_prerequisites` instead.
+
+ :Parameters:
+ `build` : `BuildExt`
+ The extension builder
+
+ :Return: Skip the extension?
+ :Rtype: ``bool``
+ """
+ # pylint: disable = W0613
+ log.debug("Nothing to check for %s!" % self.name)
+ return False
+
+
+class ConfTest(object):
+ """
+ Single conftest abstraction
+
+ :IVariables:
+ `_tempdir` : ``str``
+ The tempdir created for this test
+
+ `src` : ``str``
+ Name of the source file
+
+ `target` : ``str``
+ Target filename
+
+ `compiler` : ``CCompiler``
+ compiler instance
+
+ `obj` : ``list``
+ List of object filenames (``[str, ...]``)
+ """
+ _tempdir = None
+
+ def __init__(self, build, source):
+ """
+ Initialization
+
+ :Parameters:
+ `build` : ``distuils.command.build_ext.build_ext``
+ builder instance
+
+ `source` : ``str``
+ Source of the file to compile
+ """
+ self._tempdir = tempdir = _tempfile.mkdtemp()
+ src = _os.path.join(tempdir, 'conftest.c')
+ fp = open(src, 'w', encoding='utf-8')
+ try:
+ fp.write(source)
+ finally:
+ fp.close()
+ self.src = src
+ self.compiler = compiler = build.compiler
+ self.target = _os.path.join(tempdir, 'conftest')
+ self.obj = compiler.object_filenames([src], output_dir=tempdir)
+
+ def __del__(self):
+ """ Destruction """
+ self.destroy()
+
+ def destroy(self):
+ """ Destroy the conftest leftovers on disk """
+ tempdir, self._tempdir = self._tempdir, None
+ if tempdir is not None:
+ _shutil.rmtree(tempdir)
+
+ def compile(self, **kwargs):
+ """
+ Compile the conftest
+
+ :Parameters:
+ `kwargs` : ``dict``
+ Optional keyword parameters for the compiler call
+
+ :Return: Was the compilation successful?
+ :Rtype: ``bool``
+ """
+ kwargs['output_dir'] = self._tempdir
+ try:
+ self.compiler.compile([self.src], **kwargs)
+ except _distutils_errors.CompileError:
+ return False
+ return True
+
+ def link(self, **kwargs):
+ r"""
+ Link the conftest
+
+ Before you can link the conftest objects they need to be `compile`\d.
+
+ :Parameters:
+ `kwargs` : ``dict``
+ Optional keyword parameters for the linker call
+
+ :Return: Was the linking successful?
+ :Rtype: ``bool``
+ """
+ try:
+ self.compiler.link_executable(self.obj, self.target, **kwargs)
+ except _distutils_errors.LinkError:
+ return False
+ return True
+
+ def pipe(self, mode="r"):
+ r"""
+ Execute the conftest binary and connect to it using a pipe
+
+ Before you can pipe to or from the conftest binary it needs to
+ be `link`\ed.
+
+ :Parameters:
+ `mode` : ``str``
+ Pipe mode - r/w
+
+ :Return: The open pipe
+ :Rtype: ``file``
+ """
+ return _os.popen(self.compiler.executable_filename(self.target), mode)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/setup.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/setup.py
new file mode 100644
index 00000000000..bb1e2eedf25
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/setup.py
@@ -0,0 +1,426 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+===================
+ Main setup runner
+===================
+
+This module provides a wrapper around the distutils core setup.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import configparser as _config_parser
+from distutils import core as _core
+import os as _os
+import posixpath as _posixpath
+import sys as _sys
+
+from _setup import commands as _commands
+from _setup import data as _data
+from _setup import ext as _ext
+from _setup import util as _util
+from _setup import shell as _shell
+
+
+def check_python_version(impl, version_min, version_max):
+ """ Check python version """
+ if impl == 'python':
+ version_info = _sys.version_info
+ elif impl == 'pypy3':
+ version_info = getattr(_sys, 'pypy_version_info', None)
+ if not version_info:
+ return
+ elif impl == 'jython':
+ if not 'java' in _sys.platform.lower():
+ return
+ version_info = _sys.version_info
+ else:
+ raise AssertionError("impl not in ('python', 'pypy3', 'jython')")
+
+ pyversion = list(map(int, version_info[:3]))
+ if version_min:
+ min_required = list(
+ map(int, '.'.join((version_min, '0.0.0')).split('.')[:3])
+ )
+ if pyversion < min_required:
+ raise EnvironmentError("Need at least %s %s (vs. %s)" % (
+ impl, version_min, '.'.join(map(str, pyversion))
+ ))
+ if version_max:
+ max_required = list(map(int, version_max.split('.')))
+ max_required[-1] += 1
+ if pyversion >= max_required:
+ raise EnvironmentError("Need at max %s %s (vs. %s)" % (
+ impl,
+ version_max,
+ '.'.join(map(str, pyversion))
+ ))
+
+
+def find_description(docs):
+ """
+ Determine the package description from DESCRIPTION
+
+ :Parameters:
+ `docs` : ``dict``
+ Docs config section
+
+ :Return: Tuple of summary, description and license
+ (``('summary', 'description', 'license')``)
+ (all may be ``None``)
+ :Rtype: ``tuple``
+ """
+ summary = None
+ filename = docs.get('meta.summary', 'SUMMARY').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ try:
+ summary = fp.read().strip().splitlines()[0].rstrip()
+ except IndexError:
+ summary = ''
+ finally:
+ fp.close()
+
+ description = None
+ filename = docs.get('meta.description', 'DESCRIPTION').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ description = fp.read().rstrip()
+ finally:
+ fp.close()
+
+ if summary is None and description:
+ from docutils import core
+ summary = core.publish_parts(
+ source=description,
+ source_path=filename,
+ writer_name='html',
+ )['title'].encode('utf-8')
+
+ return summary, description
+
+
+def find_classifiers(docs):
+ """
+ Determine classifiers from CLASSIFIERS
+
+ :return: List of classifiers (``['classifier', ...]``)
+ :rtype: ``list``
+ """
+ filename = docs.get('meta.classifiers', 'CLASSIFIERS').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ content = fp.read()
+ finally:
+ fp.close()
+ content = [item.strip() for item in content.splitlines()]
+ return [item for item in content if item and not item.startswith('#')]
+ return []
+
+
+def find_provides(docs):
+ """
+ Determine provides from PROVIDES
+
+ :return: List of provides (``['provides', ...]``)
+ :rtype: ``list``
+ """
+ filename = docs.get('meta.provides', 'PROVIDES').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ content = fp.read()
+ finally:
+ fp.close()
+ content = [item.strip() for item in content.splitlines()]
+ return [item for item in content if item and not item.startswith('#')]
+ return []
+
+
+def find_license(docs):
+ """
+ Determine license from LICENSE
+
+ :return: License text
+ :rtype: ``str``
+ """
+ filename = docs.get('meta.license', 'LICENSE').strip()
+ if filename and _os.path.isfile(filename):
+ fp = open(filename, encoding='utf-8')
+ try:
+ return fp.read().rstrip()
+ finally:
+ fp.close()
+ return None
+
+
+def find_packages(manifest):
+ """ Determine packages and subpackages """
+ packages = {}
+ collect = manifest.get('packages.collect', '').split()
+ lib = manifest.get('packages.lib', '.')
+ try:
+ sep = _os.path.sep
+ except AttributeError:
+ sep = _os.path.join('1', '2')[1:-1]
+ for root in collect:
+ for dirpath, _, filenames in _shell.walk(_os.path.join(lib, root)):
+ if dirpath.find('.svn') >= 0 or dirpath.find('.git') >= 0:
+ continue
+ if '__init__.py' in filenames:
+ packages[
+ _os.path.normpath(dirpath).replace(sep, '.')
+ ] = None
+ packages = list(packages.keys())
+ packages.sort()
+ return packages
+
+
+def find_data(name, docs):
+ """ Determine data files """
+ result = []
+ if docs.get('extra', '').strip():
+ result.append(_data.Documentation(docs['extra'].split(),
+ prefix='share/doc/%s' % name,
+ ))
+ if docs.get('examples.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['examples.dir']]
+ if docs.get('examples.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['examples.ignore'].split()
+ ])
+ strip = int(docs.get('examples.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('userdoc.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['userdoc.dir']]
+ if docs.get('userdoc.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['userdoc.ignore'].split()
+ ])
+ strip = int(docs.get('userdoc.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('apidoc.dir', '').strip():
+ tpl = ['recursive-include %s *' % docs['apidoc.dir']]
+ if docs.get('apidoc.ignore', '').strip():
+ tpl.extend(["global-exclude %s" % item
+ for item in docs['apidoc.ignore'].split()
+ ])
+ strip = int(docs.get('apidoc.strip', '') or 0)
+ result.append(_data.Documentation.from_templates(*tpl, **{
+ 'strip': strip,
+ 'prefix': 'share/doc/%s' % name,
+ 'preserve': 1,
+ }))
+ if docs.get('man', '').strip():
+ result.extend(_data.Manpages.dispatch(docs['man'].split()))
+ return result
+
+
+def make_manifest(manifest, config, docs, kwargs):
+ """ Create file list to pack up """
+ # pylint: disable = R0912
+ kwargs = kwargs.copy()
+ kwargs['script_args'] = ['install']
+ kwargs['packages'] = list(kwargs.get('packages') or ()) + [
+ '_setup', '_setup.py2', '_setup.py3',
+ ] + list(manifest.get('packages.extra', '').split() or ())
+ _core._setup_stop_after = "commandline" # noqa pylint: disable = protected-access
+ try:
+ dist = _core.setup(**kwargs)
+ finally:
+ _core._setup_stop_after = None # pylint: disable = protected-access
+
+ result = ['MANIFEST', 'PKG-INFO', 'setup.py'] + list(config)
+ # xx: work with default values?
+ for key in ('classifiers', 'description', 'summary', 'provides',
+ 'license'):
+ filename = docs.get('meta.' + key, '').strip()
+ if filename and _os.path.isfile(filename):
+ result.append(filename)
+
+ cmd = dist.get_command_obj("build_py")
+ cmd.ensure_finalized()
+ # from pprint import pprint; pprint(("build_py", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+
+ cmd = dist.get_command_obj("build_ext")
+ cmd.ensure_finalized()
+ # from pprint import pprint; pprint(("build_ext", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+ for ext in cmd.extensions:
+ if ext.depends:
+ result.extend([_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ) for item in ext.depends])
+
+ cmd = dist.get_command_obj("build_clib")
+ cmd.ensure_finalized()
+ if cmd.libraries:
+ # import pprint; pprint.pprint(("build_clib", cmd.get_source_files()))
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+ for lib in cmd.libraries:
+ if lib[1].get('depends'):
+ result.extend([_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ) for item in lib[1]['depends']])
+
+ cmd = dist.get_command_obj("build_scripts")
+ cmd.ensure_finalized()
+ # import pprint; pprint.pprint(("build_scripts", cmd.get_source_files()))
+ if cmd.get_source_files():
+ for item in cmd.get_source_files():
+ result.append(_posixpath.sep.join(
+ _os.path.normpath(item).split(_os.path.sep)
+ ))
+
+ cmd = dist.get_command_obj("install_data")
+ cmd.ensure_finalized()
+ # from pprint import pprint; pprint(("install_data", cmd.get_inputs()))
+ try:
+ strings = str
+ except NameError:
+ strings = (str, str)
+
+ for item in cmd.get_inputs():
+ if isinstance(item, strings):
+ result.append(item)
+ else:
+ result.extend(item[1])
+
+ for item in manifest.get('dist', '').split():
+ result.append(item)
+ if _os.path.isdir(item):
+ for filename in _shell.files(item):
+ result.append(filename)
+
+ result = list(dict([(item, None) for item in result]).keys())
+ result.sort()
+ return result
+
+
+def run(config=('package.cfg',), ext=None, script_args=None, manifest_only=0):
+ """ Main runner """
+ # pylint: disable = too-many-locals
+ if ext is None:
+ ext = []
+
+ cfg = _util.SafeConfigParser()
+ if (3, 0, 0) <= _sys.version_info < (3, 2, 0):
+ cfg.read(config)
+ else:
+ cfg.read(config, encoding='utf-8')
+ pkg = dict(cfg.items('package'))
+ python_min = pkg.get('python.min') or None
+ python_max = pkg.get('python.max') or None
+ check_python_version('python', python_min, python_max)
+ pypy_min = pkg.get('pypy3.min') or None
+ pypy_max = pkg.get('pypy3.max') or None
+ check_python_version('pypy3', pypy_min, pypy_max)
+ jython_min = pkg.get('jython.min') or None
+ jython_max = pkg.get('jython.max') or None
+ check_python_version('jython', jython_min, jython_max)
+
+ manifest = dict(cfg.items('manifest'))
+ try:
+ docs = dict(cfg.items('docs'))
+ except _config_parser.NoSectionError:
+ docs = {}
+
+ summary, description = find_description(docs)
+ scripts = manifest.get('scripts', '').strip() or None
+ if scripts:
+ scripts = scripts.split()
+ modules = manifest.get('modules', '').strip() or None
+ if modules:
+ modules = modules.split()
+ keywords = docs.get('meta.keywords', '').strip() or None
+ if keywords:
+ keywords = keywords.split()
+ revision = pkg.get('version.revision', '').strip()
+ if revision:
+ revision = int(revision)
+ else:
+ revision = 0
+
+ kwargs = {
+ 'name': pkg['name'],
+ 'version': "%s%s" % (
+ pkg['version.number'],
+ ["", ".dev%d" % (revision,)][_util.humanbool(
+ 'version.dev', pkg.get('version.dev', 'false')
+ )],
+ ),
+ 'provides': find_provides(docs),
+ 'description': summary,
+ 'long_description': description,
+ 'classifiers': find_classifiers(docs),
+ 'keywords': keywords,
+ 'author': pkg['author.name'],
+ 'author_email': pkg['author.email'],
+ 'maintainer': pkg.get('maintainer.name'),
+ 'maintainer_email': pkg.get('maintainer.email'),
+ 'url': pkg.get('url.homepage'),
+ 'download_url': pkg.get('url.download'),
+ 'license': find_license(docs),
+ 'package_dir': {'': manifest.get('packages.lib', '.')},
+ 'packages': find_packages(manifest),
+ 'py_modules': modules,
+ 'ext_modules': ext,
+ 'scripts': scripts,
+ 'script_args': script_args,
+ 'data_files': find_data(pkg['name'], docs),
+ 'cmdclass': {
+ 'build' : _commands.Build,
+ 'build_ext' : _commands.BuildExt,
+ 'install' : _commands.Install,
+ 'install_data': _commands.InstallData,
+ 'install_lib' : _commands.InstallLib,
+ }
+ }
+ for key in ('provides',):
+ if key not in _core.setup_keywords:
+ del kwargs[key]
+
+ if manifest_only:
+ return make_manifest(manifest, config, docs, kwargs)
+
+ # monkey-patch crappy manifest writer away.
+ from distutils.command import sdist
+ sdist.sdist.get_file_list = sdist.sdist.read_manifest
+
+ return _core.setup(**kwargs)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/shell.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/shell.py
new file mode 100644
index 00000000000..91f2ebc5b40
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/shell.py
@@ -0,0 +1,351 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Shell utilities
+=================
+
+Shell utilities.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+import errno as _errno
+import fnmatch as _fnmatch
+import os as _os
+import shutil as _shutil
+import subprocess as _subprocess
+import sys as _sys
+import tempfile as _tempfile
+
+cwd = _os.path.dirname(_os.path.abspath(_sys.argv[0]))
+
+class ExitError(RuntimeError):
+ """ Exit error """
+ def __init__(self, code):
+ RuntimeError.__init__(self, code)
+ self.code = code
+ self.signal = None
+
+
+class SignalError(ExitError):
+ """ Signal error """
+ def __init__(self, code, signal):
+ ExitError.__init__(self, code)
+ import signal as _signal
+ self.signal = signal
+ for key, val in vars(_signal).items():
+ if key.startswith('SIG') and not key.startswith('SIG_'):
+ if val == signal:
+ self.signalstr = key[3:]
+ break
+ else:
+ self.signalstr = '%04d' % signal
+
+
+def native(path):
+ """ Convert slash path to native """
+ path = _os.path.sep.join(path.split('/'))
+ return _os.path.normpath(_os.path.join(cwd, path))
+
+
+def cp(src, dest):
+ """ Copy src to dest """
+ _shutil.copy2(native(src), native(dest))
+
+
+def cp_r(src, dest):
+ """ Copy -r src to dest """
+ _shutil.copytree(native(src), native(dest))
+
+
+def rm(dest):
+ """ Remove a file """
+ try:
+ _os.unlink(native(dest))
+ except OSError as e:
+ if _errno.ENOENT != e.errno:
+ raise
+
+def rm_rf(dest):
+ """ Remove a tree """
+ dest = native(dest)
+ if _os.path.exists(dest):
+ for path in files(dest, '*'):
+ _os.chmod(native(path), 0o644)
+ _shutil.rmtree(dest)
+
+
+mkstemp = _tempfile.mkstemp
+
+
+def _pipespawn(argv, env):
+ """ Pipe spawn """
+ # pylint: disable = R0912
+ import pickle as _pickle
+ fd, name = mkstemp('.py')
+ try:
+ _os.write(fd, ((r"""
+import os
+import pickle
+import subprocess
+import sys
+
+argv = pickle.loads(%(argv)s)
+env = pickle.loads(%(env)s)
+if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+p = subprocess.Popen(argv, env=env)
+result = p.wait()
+if result < 0:
+ print("\n%%d 1" %% (-result))
+ sys.exit(2)
+if result == 0:
+ sys.exit(0)
+print("\n%%d" %% (result & 7,))
+sys.exit(3)
+ """.strip() + "\n") % {
+ 'argv': repr(_pickle.dumps(argv)),
+ 'env': repr(_pickle.dumps(dict(env))),
+ }).encode('utf-8'))
+ fd, _ = None, _os.close(fd)
+ if _sys.platform == 'win32':
+ argv = []
+ for arg in [_sys.executable, name]:
+ if ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ argv.append(arg)
+ argv = ' '.join(argv)
+ shell = True
+ close_fds = False
+ else:
+ argv = [_sys.executable, name]
+ shell = False
+ close_fds = True
+
+ res = 0
+ if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+ proc = _subprocess.Popen(argv,
+ shell=shell,
+ stdin=_subprocess.PIPE,
+ stdout=_subprocess.PIPE,
+ close_fds=close_fds,
+ env=env,
+ )
+ try:
+ proc.stdin.close()
+ result = proc.stdout.read()
+ finally:
+ res = proc.wait()
+ if res != 0:
+ if res == 2:
+ signal, code = list(map(int, result.splitlines()[-1].split()))
+ raise SignalError(code, signal)
+ elif res == 3:
+ code = int(result.splitlines()[-1].strip())
+ raise ExitError(code)
+ raise ExitError(res)
+
+ return result.decode('latin-1')
+ finally:
+ try:
+ if fd is not None:
+ _os.close(fd)
+ finally:
+ _os.unlink(name)
+
+
+def _filepipespawn(infile, outfile, argv, env):
+ """ File Pipe spawn """
+ import pickle as _pickle
+ fd, name = mkstemp('.py')
+ try:
+ _os.write(fd, (("""
+import os
+import pickle
+import sys
+
+infile = pickle.loads(%(infile)s)
+outfile = pickle.loads(%(outfile)s)
+argv = pickle.loads(%(argv)s)
+env = pickle.loads(%(env)s)
+
+if infile is not None:
+ infile = open(infile, 'rb')
+ os.dup2(infile.fileno(), 0)
+ infile.close()
+if outfile is not None:
+ outfile = open(outfile, 'wb')
+ os.dup2(outfile.fileno(), 1)
+ outfile.close()
+
+pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
+result = os.waitpid(pid, 0)[1]
+sys.exit(result & 7)
+ """.strip() + "\n") % {
+ 'infile': repr(_pickle.dumps(_os.path.abspath(infile))),
+ 'outfile': repr(_pickle.dumps(_os.path.abspath(outfile))),
+ 'argv': repr(_pickle.dumps(argv)),
+ 'env': repr(_pickle.dumps(env)),
+ }).encode('utf-8'))
+ fd, _ = None, _os.close(fd)
+ if _sys.platform == 'win32':
+ argv = []
+ for arg in [_sys.executable, name]:
+ if ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ argv.append(arg)
+ argv = ' '.join(argv)
+ close_fds = False
+ shell = True
+ else:
+ argv = [_sys.executable, name]
+ close_fds = True
+ shell = False
+
+ p = _subprocess.Popen(
+ argv, env=env, shell=shell, close_fds=close_fds
+ )
+ return p.wait()
+ finally:
+ try:
+ if fd is not None:
+ _os.close(fd)
+ finally:
+ _os.unlink(name)
+
+
+def spawn(*argv, **kwargs):
+ """ Spawn a process """
+ if _sys.platform == 'win32':
+ newargv = []
+ for arg in argv:
+ if not arg or ' ' in arg or arg.startswith('"'):
+ arg = '"%s"' % arg.replace('"', '\\"')
+ newargv.append(arg)
+ argv = newargv
+ close_fds = False
+ shell = True
+ else:
+ close_fds = True
+ shell = False
+
+ env = kwargs.get('env')
+ if env is None:
+ env = dict(_os.environ)
+ if 'X_JYTHON_WA_PATH' in env:
+ env['PATH'] = env['X_JYTHON_WA_PATH']
+
+ echo = kwargs.get('echo')
+ if echo:
+ print(' '.join(argv))
+ filepipe = kwargs.get('filepipe')
+ if filepipe:
+ return _filepipespawn(
+ kwargs.get('stdin'), kwargs.get('stdout'), argv, env
+ )
+ pipe = kwargs.get('stdout')
+ if pipe:
+ return _pipespawn(argv, env)
+
+ p = _subprocess.Popen(argv, env=env, shell=shell, close_fds=close_fds)
+ return p.wait()
+
+
+walk = _os.walk
+
+
+def files(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
+ """ Determine a filelist """
+ for dirpath, dirnames, filenames in walk(native(base)):
+ for item in prune:
+ if item in dirnames:
+ dirnames.remove(item)
+
+ filenames.sort()
+ for name in _fnmatch.filter(filenames, wildcard):
+ dest = _os.path.join(dirpath, name)
+ if dest.startswith(cwd):
+ dest = dest.replace(cwd, '', 1)
+ aslist = []
+ head, tail = _os.path.split(dest)
+ while tail:
+ aslist.append(tail)
+ head, tail = _os.path.split(head)
+ aslist.reverse()
+ dest = '/'.join(aslist)
+ yield dest
+
+ if not recursive:
+ break
+ dirnames.sort()
+
+
+def dirs(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
+ """ Determine a filelist """
+ for dirpath, dirnames, filenames in walk(native(base)):
+ for item in prune:
+ if item in dirnames:
+ dirnames.remove(item)
+
+ dirnames.sort()
+ for name in _fnmatch.filter(dirnames, wildcard):
+ dest = _os.path.join(dirpath, name)
+ if dest.startswith(cwd):
+ dest = dest.replace(cwd, '', 1)
+ aslist = []
+ head, tail = _os.path.split(dest)
+ while tail:
+ aslist.append(tail)
+ head, tail = _os.path.split(head)
+ aslist.reverse()
+ dest = '/'.join(aslist)
+ yield dest
+
+ if not recursive:
+ break
+
+
+def frompath(executable):
+ """ Find executable in PATH """
+ # Based on distutils.spawn.find_executable.
+ path = _os.environ.get('PATH', '')
+ paths = [
+ _os.path.expanduser(item)
+ for item in path.split(_os.pathsep)
+ ]
+ ext = _os.path.splitext(executable)[1]
+ exts = ['']
+ if _sys.platform == 'win32' or _os.name == 'os2':
+ eext = ['.exe', '.bat', '.py']
+ if ext not in eext:
+ exts.extend(eext)
+
+ for ext in exts:
+ if not _os.path.isfile(executable + ext):
+ for path in paths:
+ fname = _os.path.join(path, executable + ext)
+ if _os.path.isfile(fname):
+ # the file exists, we have a shot at spawn working
+ return fname
+ else:
+ return executable + ext
+
+ return None
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/util.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/util.py
new file mode 100644
index 00000000000..a07daa812fe
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/_setup/py3/util.py
@@ -0,0 +1,63 @@
+# -*- coding: ascii -*-
+#
+# Copyright 2007, 2008, 2009, 2010, 2011
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+=================
+ Setup utilities
+=================
+
+Setup utilities.
+"""
+__author__ = "Andr\xe9 Malo"
+__docformat__ = "restructuredtext en"
+
+from distutils import util as _util
+try:
+ from configparser import SafeConfigParser
+except ImportError:
+ import configparser as _config_parser
+ class SafeConfigParser(_config_parser.ConfigParser):
+ """ Safe config parser """
+ def _interpolate(self, section, option, rawval, vars):
+ return rawval
+
+ def items(self, section):
+ return [(key, self.get(section, key))
+ for key in self.options(section)
+ ]
+
+
+def humanbool(name, value):
+ """
+ Determine human boolean value
+
+ :Parameters:
+ `name` : ``str``
+ The config key (used for error message)
+
+ `value` : ``str``
+ The config value
+
+ :Return: The boolean value
+ :Rtype: ``bool``
+
+ :Exceptions:
+ - `ValueError` : The value could not be recognized
+ """
+ try:
+ return _util.strtobool(str(value).strip().lower() or 'no')
+ except ValueError:
+ raise ValueError("Unrecognized config value: %s = %s" % (name, value))
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/DateTimeShortcuts.js b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/DateTimeShortcuts.js
new file mode 100644
index 00000000000..d347d6d6f16
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/DateTimeShortcuts.js
@@ -0,0 +1,388 @@
+/*! Taken from django release 1.8.5
+
+Copyright (c) Django Software Foundation and individual contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of Django nor the names of its contributors may be used
+ to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// Inserts shortcut buttons after all of the following:
+// <input type="text" class="vDateField">
+// <input type="text" class="vTimeField">
+
+var DateTimeShortcuts = {
+ calendars: [],
+ calendarInputs: [],
+ clockInputs: [],
+ dismissClockFunc: [],
+ dismissCalendarFunc: [],
+ calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
+ calendarDivName2: 'calendarin', // name of <div> that contains calendar
+ calendarLinkName: 'calendarlink',// name of the link that is used to toggle
+ clockDivName: 'clockbox', // name of clock <div> that gets toggled
+ clockLinkName: 'clocklink', // name of the link that is used to toggle
+ shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts
+ timezoneWarningClass: 'timezonewarning', // class of the warning for timezone mismatch
+ timezoneOffset: 0,
+ admin_media_prefix: '',
+ init: function() {
+ // Get admin_media_prefix by grabbing it off the window object. It's
+ // set in the admin/base.html template, so if it's not there, someone's
+ // overridden the template. In that case, we'll set a clearly-invalid
+ // value in the hopes that someone will examine HTTP requests and see it.
+ if (window.__admin_media_prefix__ != undefined) {
+ DateTimeShortcuts.admin_media_prefix = window.__admin_media_prefix__;
+ } else {
+ DateTimeShortcuts.admin_media_prefix = '/missing-admin-media-prefix/';
+ }
+
+ if (window.__admin_utc_offset__ != undefined) {
+ var serverOffset = window.__admin_utc_offset__;
+ var localOffset = new Date().getTimezoneOffset() * -60;
+ DateTimeShortcuts.timezoneOffset = localOffset - serverOffset;
+ }
+
+ var inputs = document.getElementsByTagName('input');
+ for (i=0; i<inputs.length; i++) {
+ var inp = inputs[i];
+ if (inp.getAttribute('type') == 'text' && inp.className.match(/vTimeField/)) {
+ DateTimeShortcuts.addClock(inp);
+ DateTimeShortcuts.addTimezoneWarning(inp);
+ }
+ else if (inp.getAttribute('type') == 'text' && inp.className.match(/vDateField/)) {
+ DateTimeShortcuts.addCalendar(inp);
+ DateTimeShortcuts.addTimezoneWarning(inp);
+ }
+ }
+ },
+ // Return the current time while accounting for the server timezone.
+ now: function() {
+ if (window.__admin_utc_offset__ != undefined) {
+ var serverOffset = window.__admin_utc_offset__;
+ var localNow = new Date();
+ var localOffset = localNow.getTimezoneOffset() * -60;
+ localNow.setTime(localNow.getTime() + 1000 * (serverOffset - localOffset));
+ return localNow;
+ } else {
+ return new Date();
+ }
+ },
+ // Add a warning when the time zone in the browser and backend do not match.
+ addTimezoneWarning: function(inp) {
+ var $ = django.jQuery;
+ var warningClass = DateTimeShortcuts.timezoneWarningClass;
+ var timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600;
+
+ // Only warn if there is a time zone mismatch.
+ if (!timezoneOffset)
+ return;
+
+ // Check if warning is already there.
+ if ($(inp).siblings('.' + warningClass).length)
+ return;
+
+ var message;
+ if (timezoneOffset > 0) {
+ message = ngettext(
+ 'Note: You are %s hour ahead of server time.',
+ 'Note: You are %s hours ahead of server time.',
+ timezoneOffset
+ );
+ }
+ else {
+ timezoneOffset *= -1
+ message = ngettext(
+ 'Note: You are %s hour behind server time.',
+ 'Note: You are %s hours behind server time.',
+ timezoneOffset
+ );
+ }
+ message = interpolate(message, [timezoneOffset]);
+
+ var $warning = $('<span>');
+ $warning.attr('class', warningClass);
+ $warning.text(message);
+
+ $(inp).parent()
+ .append($('<br>'))
+ .append($warning)
+ },
+ // Add clock widget to a given field
+ addClock: function(inp) {
+ var num = DateTimeShortcuts.clockInputs.length;
+ DateTimeShortcuts.clockInputs[num] = inp;
+ DateTimeShortcuts.dismissClockFunc[num] = function() { DateTimeShortcuts.dismissClock(num); return true; };
+
+ // Shortcut links (clock icon and "Now" link)
+ var shortcuts_span = document.createElement('span');
+ shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
+ inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
+ var now_link = document.createElement('a');
+ now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", -1);");
+ now_link.appendChild(document.createTextNode(gettext('Now')));
+ var clock_link = document.createElement('a');
+ clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
+ clock_link.id = DateTimeShortcuts.clockLinkName + num;
+ quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/icon_clock.gif', 'alt', gettext('Clock'));
+ shortcuts_span.appendChild(document.createTextNode('\240'));
+ shortcuts_span.appendChild(now_link);
+ shortcuts_span.appendChild(document.createTextNode('\240|\240'));
+ shortcuts_span.appendChild(clock_link);
+
+ // Create clock link div
+ //
+ // Markup looks like:
+ // <div id="clockbox1" class="clockbox module">
+ // <h2>Choose a time</h2>
+ // <ul class="timelist">
+ // <li><a href="#">Now</a></li>
+ // <li><a href="#">Midnight</a></li>
+ // <li><a href="#">6 a.m.</a></li>
+ // <li><a href="#">Noon</a></li>
+ // </ul>
+ // <p class="calendar-cancel"><a href="#">Cancel</a></p>
+ // </div>
+
+ var clock_box = document.createElement('div');
+ clock_box.style.display = 'none';
+ clock_box.style.position = 'absolute';
+ clock_box.className = 'clockbox module';
+ clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
+ document.body.appendChild(clock_box);
+ addEvent(clock_box, 'click', cancelEventPropagation);
+
+ quickElement('h2', clock_box, gettext('Choose a time'));
+ var time_list = quickElement('ul', clock_box);
+ time_list.className = 'timelist';
+ quickElement("a", quickElement("li", time_list), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", -1);");
+ quickElement("a", quickElement("li", time_list), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 0);");
+ quickElement("a", quickElement("li", time_list), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 6);");
+ quickElement("a", quickElement("li", time_list), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 12);");
+
+ var cancel_p = quickElement('p', clock_box);
+ cancel_p.className = 'calendar-cancel';
+ quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
+ django.jQuery(document).bind('keyup', function(event) {
+ if (event.which == 27) {
+ // ESC key closes popup
+ DateTimeShortcuts.dismissClock(num);
+ event.preventDefault();
+ }
+ });
+ },
+ openClock: function(num) {
+ var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
+ var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
+
+ // Recalculate the clockbox position
+ // is it left-to-right or right-to-left layout ?
+ if (getStyle(document.body,'direction')!='rtl') {
+ clock_box.style.left = findPosX(clock_link) + 17 + 'px';
+ }
+ else {
+ // since style's width is in em, it'd be tough to calculate
+ // px value of it. let's use an estimated px for now
+ // TODO: IE returns wrong value for findPosX when in rtl mode
+ // (it returns as it was left aligned), needs to be fixed.
+ clock_box.style.left = findPosX(clock_link) - 110 + 'px';
+ }
+ clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px';
+
+ // Show the clock box
+ clock_box.style.display = 'block';
+ addEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]);
+ },
+ dismissClock: function(num) {
+ document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
+ removeEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]);
+ },
+ handleClockQuicklink: function(num, val) {
+ var d;
+ if (val == -1) {
+ d = DateTimeShortcuts.now();
+ }
+ else {
+ d = new Date(1970, 1, 1, val, 0, 0, 0)
+ }
+ DateTimeShortcuts.clockInputs[num].value = d.strftime(get_format('TIME_INPUT_FORMATS')[0]);
+ DateTimeShortcuts.clockInputs[num].focus();
+ DateTimeShortcuts.dismissClock(num);
+ },
+ // Add calendar widget to a given field.
+ addCalendar: function(inp) {
+ var num = DateTimeShortcuts.calendars.length;
+
+ DateTimeShortcuts.calendarInputs[num] = inp;
+ DateTimeShortcuts.dismissCalendarFunc[num] = function() { DateTimeShortcuts.dismissCalendar(num); return true; };
+
+ // Shortcut links (calendar icon and "Today" link)
+ var shortcuts_span = document.createElement('span');
+ shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
+ inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
+ var today_link = document.createElement('a');
+ today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
+ today_link.appendChild(document.createTextNode(gettext('Today')));
+ var cal_link = document.createElement('a');
+ cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
+ cal_link.id = DateTimeShortcuts.calendarLinkName + num;
+ quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/icon_calendar.gif', 'alt', gettext('Calendar'));
+ shortcuts_span.appendChild(document.createTextNode('\240'));
+ shortcuts_span.appendChild(today_link);
+ shortcuts_span.appendChild(document.createTextNode('\240|\240'));
+ shortcuts_span.appendChild(cal_link);
+
+ // Create calendarbox div.
+ //
+ // Markup looks like:
+ //
+ // <div id="calendarbox3" class="calendarbox module">
+ // <h2>
+ // <a href="#" class="link-previous">&lsaquo;</a>
+ // <a href="#" class="link-next">&rsaquo;</a> February 2003
+ // </h2>
+ // <div class="calendar" id="calendarin3">
+ // <!-- (cal) -->
+ // </div>
+ // <div class="calendar-shortcuts">
+ // <a href="#">Yesterday</a> | <a href="#">Today</a> | <a href="#">Tomorrow</a>
+ // </div>
+ // <p class="calendar-cancel"><a href="#">Cancel</a></p>
+ // </div>
+ var cal_box = document.createElement('div');
+ cal_box.style.display = 'none';
+ cal_box.style.position = 'absolute';
+ cal_box.className = 'calendarbox module';
+ cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
+ document.body.appendChild(cal_box);
+ addEvent(cal_box, 'click', cancelEventPropagation);
+
+ // next-prev links
+ var cal_nav = quickElement('div', cal_box);
+ var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');');
+ cal_nav_prev.className = 'calendarnav-previous';
+ var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
+ cal_nav_next.className = 'calendarnav-next';
+
+ // main box
+ var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
+ cal_main.className = 'calendar';
+ DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
+ DateTimeShortcuts.calendars[num].drawCurrent();
+
+ // calendar shortcuts
+ var shortcuts = quickElement('div', cal_box);
+ shortcuts.className = 'calendar-shortcuts';
+ quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
+ shortcuts.appendChild(document.createTextNode('\240|\240'));
+ quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
+ shortcuts.appendChild(document.createTextNode('\240|\240'));
+ quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');
+
+ // cancel bar
+ var cancel_p = quickElement('p', cal_box);
+ cancel_p.className = 'calendar-cancel';
+ quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
+ django.jQuery(document).bind('keyup', function(event) {
+ if (event.which == 27) {
+ // ESC key closes popup
+ DateTimeShortcuts.dismissCalendar(num);
+ event.preventDefault();
+ }
+ });
+ },
+ openCalendar: function(num) {
+ var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
+ var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
+ var inp = DateTimeShortcuts.calendarInputs[num];
+
+ // Determine if the current value in the input has a valid date.
+ // If so, draw the calendar with that date's year and month.
+ if (inp.value) {
+ var format = get_format('DATE_INPUT_FORMATS')[0];
+ var selected = inp.value.strptime(format);
+ var year = selected.getFullYear();
+ var month = selected.getMonth() + 1;
+ var re = /\d{4}/
+ if (re.test(year.toString()) && month >= 1 && month <= 12) {
+ DateTimeShortcuts.calendars[num].drawDate(month, year, selected);
+ }
+ }
+
+ // Recalculate the clockbox position
+ // is it left-to-right or right-to-left layout ?
+ if (getStyle(document.body,'direction')!='rtl') {
+ cal_box.style.left = findPosX(cal_link) + 17 + 'px';
+ }
+ else {
+ // since style's width is in em, it'd be tough to calculate
+ // px value of it. let's use an estimated px for now
+ // TODO: IE returns wrong value for findPosX when in rtl mode
+ // (it returns as it was left aligned), needs to be fixed.
+ cal_box.style.left = findPosX(cal_link) - 180 + 'px';
+ }
+ cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px';
+
+ cal_box.style.display = 'block';
+ addEvent(document, 'click', DateTimeShortcuts.dismissCalendarFunc[num]);
+ },
+ dismissCalendar: function(num) {
+ document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none';
+ removeEvent(document, 'click', DateTimeShortcuts.dismissCalendarFunc[num]);
+ },
+ drawPrev: function(num) {
+ DateTimeShortcuts.calendars[num].drawPreviousMonth();
+ },
+ drawNext: function(num) {
+ DateTimeShortcuts.calendars[num].drawNextMonth();
+ },
+ handleCalendarCallback: function(num) {
+ var format = get_format('DATE_INPUT_FORMATS')[0];
+ // the format needs to be escaped a little
+ format = format.replace('\\', '\\\\');
+ format = format.replace('\r', '\\r');
+ format = format.replace('\n', '\\n');
+ format = format.replace('\t', '\\t');
+ format = format.replace("'", "\\'");
+ return ["function(y, m, d) { DateTimeShortcuts.calendarInputs[",
+ num,
+ "].value = new Date(y, m-1, d).strftime('",
+ format,
+ "');DateTimeShortcuts.calendarInputs[",
+ num,
+ "].focus();document.getElementById(DateTimeShortcuts.calendarDivName1+",
+ num,
+ ").style.display='none';}"].join('');
+ },
+ handleCalendarQuickLink: function(num, offset) {
+ var d = DateTimeShortcuts.now();
+ d.setDate(d.getDate() + offset)
+ DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]);
+ DateTimeShortcuts.calendarInputs[num].focus();
+ DateTimeShortcuts.dismissCalendar(num);
+ }
+}
+
+addEvent(window, 'load', DateTimeShortcuts.init);
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/__init__.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/__init__.py
new file mode 100644
index 00000000000..a9b2847935c
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/__init__.py
@@ -0,0 +1,30 @@
+# -*- coding: ascii -*-
+r"""
+=================================
+ Benchmark jsmin implementations
+=================================
+
+Benchmark jsmin implementations.
+
+:Copyright:
+
+ Copyright 2011 - 2015
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+"""
+if __doc__:
+ __doc__ = __doc__.encode('ascii').decode('unicode_escape')
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/apiviewer.js b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/apiviewer.js
new file mode 100644
index 00000000000..e70ebf87e9d
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/apiviewer.js
@@ -0,0 +1,178 @@
+/*
+This file is part of the qooxdoo framework.
+
+qooxdoo is dual-licensed under the GNU Lesser General Public License (LGPL) and the Eclipse Public License (EPL). As a recipient of qooxdoo, you may choose which license to receive the code under.
+*/
+
+(function(){
+
+if (!window.qx) window.qx = {};
+
+qx.$$start = new Date();
+
+if (!window.qxsettings) qxsettings = {};
+var settings = {"qx.application":"apiviewer.Application","qx.nativeScrollBars":true,"qx.theme":"apiviewer.Theme","qx.version":"1.3"};
+for (var k in settings) qxsettings[k] = settings[k];
+
+if (!window.qxvariants) qxvariants = {};
+var variants = {"qx.aspects":"off","qx.debug":"off"};
+for (var k in variants) qxvariants[k] = variants[k];
+
+if (!qx.$$libraries) qx.$$libraries = {};
+var libinfo = {"__out__":{"sourceUri":"script"},"apiviewer":{"resourceUri":"resource","sourceUri":"script","version":"trunk"},"qx":{"resourceUri":"resource","sourceUri":"script","version":"1.3"}};
+for (var k in libinfo) qx.$$libraries[k] = libinfo[k];
+
+qx.$$resources = {};
+qx.$$translations = {};
+qx.$$locales = {};
+qx.$$packageData = {};
+
+qx.$$loader = {
+ parts : {"boot":[0]},
+ uris : [["__out__:apiviewer.js"]],
+ urisBefore : [],
+ packageHashes : {"0":"9b3309ed13dc"},
+ boot : "boot",
+ closureParts : {},
+ bootIsInline : true,
+ addNoCacheParam : true,
+
+ decodeUris : function(compressedUris)
+ {
+ var libs = qx.$$libraries;
+ var uris = [];
+ for (var i=0; i<compressedUris.length; i++)
+ {
+ var uri = compressedUris[i].split(":");
+ var euri;
+ if (uri.length==2 && uri[0] in libs) {
+ var prefix = libs[uri[0]].sourceUri;
+ euri = prefix + "/" + uri[1];
+ } else {
+ euri = compressedUris[i];
+ }
+ if (qx.$$loader.addNoCacheParam) {
+ euri += "?nocache=" + Math.random();
+ }
+
+ uris.push(euri);
+ }
+ return uris;
+ }
+};
+
+function loadScript(uri, callback) {
+ var elem = document.createElement("script");
+ elem.charset = "utf-8";
+ elem.src = uri;
+ elem.onreadystatechange = elem.onload = function()
+ {
+ if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete")
+ {
+ elem.onreadystatechange = elem.onload = null;
+ callback();
+ }
+ };
+ var head = document.getElementsByTagName("head")[0];
+ head.appendChild(elem);
+}
+
+var isWebkit = /AppleWebKit\/([^ ]+)/.test(navigator.userAgent);
+
+function loadScriptList(list, callback) {
+ if (list.length == 0) {
+ callback();
+ return;
+ }
+ loadScript(list.shift(), function() {
+ if (isWebkit) {
+ // force asynchronous load
+ // Safari fails with an "maximum recursion depth exceeded" error if it is
+ // called sync.
+ window.setTimeout(function() {
+ loadScriptList(list, callback);
+ }, 0);
+ } else {
+ loadScriptList(list, callback);
+ }
+ });
+}
+
+var fireContentLoadedEvent = function() {
+ qx.$$domReady = true;
+ document.removeEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
+};
+if (document.addEventListener) {
+ document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
+}
+
+qx.$$loader.importPackageData = function (dataMap) {
+ if (dataMap["resources"]){
+ var resMap = dataMap["resources"];
+ for (var k in resMap) qx.$$resources[k] = resMap[k];
+ }
+ if (dataMap["locales"]){
+ var locMap = dataMap["locales"];
+ var qxlocs = qx.$$locales;
+ for (var lang in locMap){
+ if (!qxlocs[lang]) qxlocs[lang] = locMap[lang];
+ else
+ for (var k in locMap[lang]) qxlocs[lang][k] = locMap[lang][k];
+ }
+ }
+ if (dataMap["translations"]){
+ var trMap = dataMap["translations"];
+ var qxtrans = qx.$$translations;
+ for (var lang in trMap){
+ if (!qxtrans[lang]) qxtrans[lang] = trMap[lang];
+ else
+ for (var k in trMap[lang]) qxtrans[lang][k] = trMap[lang][k];
+ }
+ }
+}
+
+qx.$$loader.signalStartup = function ()
+{
+ qx.$$loader.scriptLoaded = true;
+ if (window.qx && qx.event && qx.event.handler && qx.event.handler.Application) {
+ qx.event.handler.Application.onScriptLoaded();
+ qx.$$loader.applicationHandlerReady = true;
+ } else {
+ qx.$$loader.applicationHandlerReady = false;
+ }
+}
+
+qx.$$loader.init = function(){
+ var l=qx.$$loader;
+ if (l.urisBefore.length>0){
+ loadScriptList(l.urisBefore, function(){
+ l.initUris();
+ });
+ } else {
+ l.initUris();
+ }
+}
+
+qx.$$loader.initUris = function(){
+ var l=qx.$$loader;
+ var bootPackageHash=l.packageHashes[l.parts[l.boot][0]];
+ if (l.bootIsInline){
+ l.importPackageData(qx.$$packageData[bootPackageHash]);
+ l.signalStartup();
+ } else {
+ loadScriptList(l.decodeUris(l.uris[l.parts[l.boot]]), function(){
+ // Opera needs this extra time to parse the scripts
+ window.setTimeout(function(){
+ l.importPackageData(qx.$$packageData[bootPackageHash] || {});
+ l.signalStartup();
+ }, 0);
+ });
+ }
+}
+})();
+
+qx.$$packageData['9b3309ed13dc']={"locales":{"C":{"alternateQuotationEnd":"’","alternateQuotationStart":"‘","cldr_am":"AM","cldr_date_format_full":"EEEE, MMMM d, y","cldr_date_format_long":"MMMM d, y","cldr_date_format_medium":"MMM d, y","cldr_date_format_short":"M/d/yy","cldr_date_time_format_EEEd":"d EEE","cldr_date_time_format_Hm":"H:mm","cldr_date_time_format_Hms":"H:mm:ss","cldr_date_time_format_M":"L","cldr_date_time_format_MEd":"E, M/d","cldr_date_time_format_MMM":"LLL","cldr_date_time_format_MMMEd":"E, MMM d","cldr_date_time_format_MMMMEd":"E, MMMM d","cldr_date_time_format_MMMMd":"MMMM d","cldr_date_time_format_MMMd":"MMM d","cldr_date_time_format_Md":"M/d","cldr_date_time_format_d":"d","cldr_date_time_format_hm":"h:mm a","cldr_date_time_format_ms":"mm:ss","cldr_date_time_format_y":"y","cldr_date_time_format_yM":"M/yyyy","cldr_date_time_format_yMEd":"EEE, M/d/yyyy","cldr_date_time_format_yMMM":"MMM y","cldr_date_time_format_yMMMEd":"EEE, MMM d, y","cldr_date_time_format_yMMMM":"MMMM y","cldr_date_time_format_yQ":"Q yyyy","cldr_date_time_format_yQQQ":"QQQ y","cldr_day_format_abbreviated_fri":"Fri","cldr_day_format_abbreviated_mon":"Mon","cldr_day_format_abbreviated_sat":"Sat","cldr_day_format_abbreviated_sun":"Sun","cldr_day_format_abbreviated_thu":"Thu","cldr_day_format_abbreviated_tue":"Tue","cldr_day_format_abbreviated_wed":"Wed","cldr_day_format_narrow_fri":"F","cldr_day_format_narrow_mon":"M","cldr_day_format_narrow_sat":"S","cldr_day_format_narrow_sun":"S","cldr_day_format_narrow_thu":"T","cldr_day_format_narrow_tue":"T","cldr_day_format_narrow_wed":"W","cldr_day_format_wide_fri":"Friday","cldr_day_format_wide_mon":"Monday","cldr_day_format_wide_sat":"Saturday","cldr_day_format_wide_sun":"Sunday","cldr_day_format_wide_thu":"Thursday","cldr_day_format_wide_tue":"Tuesday","cldr_day_format_wide_wed":"Wednesday","cldr_day_stand-alone_abbreviated_fri":"Fri","cldr_day_stand-alone_abbreviated_mon":"Mon","cldr_day_stand-alone_abbreviated_sat":"Sat","cldr_day_stand-alone_abbreviated_sun":"Sun","cldr_day_stand-alone_abbreviated_thu":"Thu","cldr_day_stand-alone_abbreviated_tue":"Tue","cldr_day_stand-alone_abbreviated_wed":"Wed","cldr_day_stand-alone_narrow_fri":"F","cldr_day_stand-alone_narrow_mon":"M","cldr_day_stand-alone_narrow_sat":"S","cldr_day_stand-alone_narrow_sun":"S","cldr_day_stand-alone_narrow_thu":"T","cldr_day_stand-alone_narrow_tue":"T","cldr_day_stand-alone_narrow_wed":"W","cldr_day_stand-alone_wide_fri":"Friday","cldr_day_stand-alone_wide_mon":"Monday","cldr_day_stand-alone_wide_sat":"Saturday","cldr_day_stand-alone_wide_sun":"Sunday","cldr_day_stand-alone_wide_thu":"Thursday","cldr_day_stand-alone_wide_tue":"Tuesday","cldr_day_stand-alone_wide_wed":"Wednesday","cldr_month_format_abbreviated_1":"Jan","cldr_month_format_abbreviated_10":"Oct","cldr_month_format_abbreviated_11":"Nov","cldr_month_format_abbreviated_12":"Dec","cldr_month_format_abbreviated_2":"Feb","cldr_month_format_abbreviated_3":"Mar","cldr_month_format_abbreviated_4":"Apr","cldr_month_format_abbreviated_5":"May","cldr_month_format_abbreviated_6":"Jun","cldr_month_format_abbreviated_7":"Jul","cldr_month_format_abbreviated_8":"Aug","cldr_month_format_abbreviated_9":"Sep","cldr_month_format_wide_1":"January","cldr_month_format_wide_10":"October","cldr_month_format_wide_11":"November","cldr_month_format_wide_12":"December","cldr_month_format_wide_2":"February","cldr_month_format_wide_3":"March","cldr_month_format_wide_4":"April","cldr_month_format_wide_5":"May","cldr_month_format_wide_6":"June","cldr_month_format_wide_7":"July","cldr_month_format_wide_8":"August","cldr_month_format_wide_9":"September","cldr_month_stand-alone_narrow_1":"J","cldr_month_stand-alone_narrow_10":"O","cldr_month_stand-alone_narrow_11":"N","cldr_month_stand-alone_narrow_12":"D","cldr_month_stand-alone_narrow_2":"F","cldr_month_stand-alone_narrow_3":"M","cldr_month_stand-alone_narrow_4":"A","cldr_month_stand-alone_narrow_5":"M","cldr_month_stand-alone_narrow_6":"J","cldr_month_stand-alone_narrow_7":"J","cldr_month_stand-alone_narrow_8":"A","cldr_month_stand-alone_narrow_9":"S","cldr_number_decimal_separator":".","cldr_number_group_separator":",","cldr_number_percent_format":"#,##0%","cldr_pm":"PM","cldr_time_format_full":"h:mm:ss a zzzz","cldr_time_format_long":"h:mm:ss a z","cldr_time_format_medium":"h:mm:ss a","cldr_time_format_short":"h:mm a","quotationEnd":"”","quotationStart":"“"}},"resources":{"apiviewer/css/apiviewer.css":"apiviewer","apiviewer/image/blank.gif":[1,1,"gif","apiviewer"],"apiviewer/image/childcontrol18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-540],"apiviewer/image/class18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-324],"apiviewer/image/class_abstract18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-486],"apiviewer/image/class_abstract_warning18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-306],"apiviewer/image/class_singleton18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-612],"apiviewer/image/class_singleton_warning18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-252],"apiviewer/image/class_static18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-234],"apiviewer/image/class_static_warning18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-144],"apiviewer/image/class_warning18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-342],"apiviewer/image/close.gif":[17,13,"gif","apiviewer"],"apiviewer/image/colorstrip.gif":[192,10,"gif","apiviewer"],"apiviewer/image/constant18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-504],"apiviewer/image/constructor18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-558],"apiviewer/image/cross.gif":[18,18,"gif","apiviewer"],"apiviewer/image/event18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-198],"apiviewer/image/information18.png":[18,18,"png","apiviewer"],"apiviewer/image/interface18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-432],"apiviewer/image/interface_warning18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-450],"apiviewer/image/method_private18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-270],"apiviewer/image/method_protected18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-216],"apiviewer/image/method_public18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-126],"apiviewer/image/method_public_inherited18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-18],"apiviewer/image/mixin18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-162],"apiviewer/image/mixin_warning18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-108],"apiviewer/image/nextlevel.gif":[18,18,"gif","apiviewer"],"apiviewer/image/open.gif":[17,13,"gif","apiviewer"],"apiviewer/image/overlay_abstract18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,0],"apiviewer/image/overlay_constructor18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-36],"apiviewer/image/overlay_error18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-414],"apiviewer/image/overlay_inherited18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-576],"apiviewer/image/overlay_mixin18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-180],"apiviewer/image/overlay_overridden18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-288],"apiviewer/image/overlay_static18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-378],"apiviewer/image/overlay_themeable18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-360],"apiviewer/image/overlay_warning18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-594],"apiviewer/image/package18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-54],"apiviewer/image/package_warning18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-90],"apiviewer/image/property18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-522],"apiviewer/image/property_private18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-72],"apiviewer/image/property_protected18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-468],"apiviewer/image/property_themeable18.gif":[18,18,"gif","apiviewer","apiviewer/imagesCombined/symbols.gif",0,-396],"apiviewer/image/search18.png":[18,18,"png","apiviewer"],"apiviewer/image/vline.gif":[18,18,"gif","apiviewer"],"apiviewer/imagesCombined/symbols.gif":[18,630,"gif","apiviewer"],"qx/decoration/Modern/app-header.png":[110,20,"png","qx"],"qx/decoration/Modern/arrows-combined.png":[87,8,"png","qx"],"qx/decoration/Modern/arrows/down-invert.png":[8,5,"png","qx","qx/decoration/Modern/arrows-combined.png",-74,0],"qx/decoration/Modern/arrows/down-small-invert.png":[5,3,"png","qx","qx/decoration/Modern/arrows-combined.png",-69,0],"qx/decoration/Modern/arrows/down-small.png":[5,3,"png","qx","qx/decoration/Modern/arrows-combined.png",-49,0],"qx/decoration/Modern/arrows/down.png":[8,5,"png","qx","qx/decoration/Modern/arrows-combined.png",-20,0],"qx/decoration/Modern/arrows/forward.png":[10,8,"png","qx","qx/decoration/Modern/arrows-combined.png",-59,0],"qx/decoration/Modern/arrows/left-invert.png":[5,8,"png","qx","qx/decoration/Modern/arrows-combined.png",0,0],"qx/decoration/Modern/arrows/left.png":[5,8,"png","qx","qx/decoration/Modern/arrows-combined.png",-44,0],"qx/decoration/Modern/arrows/rewind.png":[10,8,"png","qx","qx/decoration/Modern/arrows-combined.png",-10,0],"qx/decoration/Modern/arrows/right-invert.png":[5,8,"png","qx","qx/decoration/Modern/arrows-combined.png",-5,0],"qx/decoration/Modern/arrows/right.png":[5,8,"png","qx","qx/decoration/Modern/arrows-combined.png",-54,0],"qx/decoration/Modern/arrows/up-invert.png":[8,5,"png","qx","qx/decoration/Modern/arrows-combined.png",-28,0],"qx/decoration/Modern/arrows/up-small.png":[5,3,"png","qx","qx/decoration/Modern/arrows-combined.png",-82,0],"qx/decoration/Modern/arrows/up.png":[8,5,"png","qx","qx/decoration/Modern/arrows-combined.png",-36,0],"qx/decoration/Modern/button-lr-combined.png":[72,52,"png","qx"],"qx/decoration/Modern/button-tb-combined.png":[4,216,"png","qx"],"qx/decoration/Modern/checkradio-combined.png":[504,14,"png","qx"],"qx/decoration/Modern/colorselector-combined.gif":[46,11,"gif","qx"],"qx/decoration/Modern/colorselector/brightness-field.png":[19,256,"png","qx"],"qx/decoration/Modern/colorselector/brightness-handle.gif":[35,11,"gif","qx","qx/decoration/Modern/colorselector-combined.gif",0,0],"qx/decoration/Modern/colorselector/huesaturation-field.jpg":[256,256,"jpeg","qx"],"qx/decoration/Modern/colorselector/huesaturation-handle.gif":[11,11,"gif","qx","qx/decoration/Modern/colorselector-combined.gif",-35,0],"qx/decoration/Modern/cursors-combined.gif":[71,20,"gif","qx"],"qx/decoration/Modern/cursors/alias.gif":[19,15,"gif","qx","qx/decoration/Modern/cursors-combined.gif",-52,0],"qx/decoration/Modern/cursors/copy.gif":[19,15,"gif","qx","qx/decoration/Modern/cursors-combined.gif",-33,0],"qx/decoration/Modern/cursors/move.gif":[13,9,"gif","qx","qx/decoration/Modern/cursors-combined.gif",-20,0],"qx/decoration/Modern/cursors/nodrop.gif":[20,20,"gif","qx","qx/decoration/Modern/cursors-combined.gif",0,0],"qx/decoration/Modern/form/button-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-72],"qx/decoration/Modern/form/button-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-204],"qx/decoration/Modern/form/button-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-188],"qx/decoration/Modern/form/button-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-checked-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-36],"qx/decoration/Modern/form/button-checked-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-84],"qx/decoration/Modern/form/button-checked-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-184],"qx/decoration/Modern/form/button-checked-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-checked-focused-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-156],"qx/decoration/Modern/form/button-checked-focused-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-208],"qx/decoration/Modern/form/button-checked-focused-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-160],"qx/decoration/Modern/form/button-checked-focused-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-checked-focused-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-40,0],"qx/decoration/Modern/form/button-checked-focused-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-32,0],"qx/decoration/Modern/form/button-checked-focused-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-28],"qx/decoration/Modern/form/button-checked-focused-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-24],"qx/decoration/Modern/form/button-checked-focused-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-48],"qx/decoration/Modern/form/button-checked-focused.png":[80,60,"png","qx"],"qx/decoration/Modern/form/button-checked-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-16,0],"qx/decoration/Modern/form/button-checked-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-60,0],"qx/decoration/Modern/form/button-checked-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-140],"qx/decoration/Modern/form/button-checked-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-56],"qx/decoration/Modern/form/button-checked-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-112],"qx/decoration/Modern/form/button-checked.png":[80,60,"png","qx"],"qx/decoration/Modern/form/button-disabled-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-40],"qx/decoration/Modern/form/button-disabled-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-136],"qx/decoration/Modern/form/button-disabled-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-16],"qx/decoration/Modern/form/button-disabled-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-disabled-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-68,0],"qx/decoration/Modern/form/button-disabled-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-4,0],"qx/decoration/Modern/form/button-disabled-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-116],"qx/decoration/Modern/form/button-disabled-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-168],"qx/decoration/Modern/form/button-disabled-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-60],"qx/decoration/Modern/form/button-disabled.png":[80,60,"png","qx"],"qx/decoration/Modern/form/button-focused-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-68],"qx/decoration/Modern/form/button-focused-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-144],"qx/decoration/Modern/form/button-focused-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-8],"qx/decoration/Modern/form/button-focused-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-focused-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-24,0],"qx/decoration/Modern/form/button-focused-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-44,0],"qx/decoration/Modern/form/button-focused-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-192],"qx/decoration/Modern/form/button-focused-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-148],"qx/decoration/Modern/form/button-focused-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-104],"qx/decoration/Modern/form/button-focused.png":[80,60,"png","qx"],"qx/decoration/Modern/form/button-hovered-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-108],"qx/decoration/Modern/form/button-hovered-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-32],"qx/decoration/Modern/form/button-hovered-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-128],"qx/decoration/Modern/form/button-hovered-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-hovered-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-20,0],"qx/decoration/Modern/form/button-hovered-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-48,0],"qx/decoration/Modern/form/button-hovered-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-44],"qx/decoration/Modern/form/button-hovered-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-76],"qx/decoration/Modern/form/button-hovered-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-88],"qx/decoration/Modern/form/button-hovered.png":[80,60,"png","qx"],"qx/decoration/Modern/form/button-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-56,0],"qx/decoration/Modern/form/button-preselected-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-124],"qx/decoration/Modern/form/button-preselected-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-176],"qx/decoration/Modern/form/button-preselected-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-200],"qx/decoration/Modern/form/button-preselected-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-preselected-focused-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,0],"qx/decoration/Modern/form/button-preselected-focused-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-4],"qx/decoration/Modern/form/button-preselected-focused-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-152],"qx/decoration/Modern/form/button-preselected-focused-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-preselected-focused-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-28,0],"qx/decoration/Modern/form/button-preselected-focused-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-36,0],"qx/decoration/Modern/form/button-preselected-focused-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-196],"qx/decoration/Modern/form/button-preselected-focused-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-164],"qx/decoration/Modern/form/button-preselected-focused-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-212],"qx/decoration/Modern/form/button-preselected-focused.png":[80,60,"png","qx"],"qx/decoration/Modern/form/button-preselected-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-8,0],"qx/decoration/Modern/form/button-preselected-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-64,0],"qx/decoration/Modern/form/button-preselected-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-96],"qx/decoration/Modern/form/button-preselected-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-80],"qx/decoration/Modern/form/button-preselected-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-132],"qx/decoration/Modern/form/button-preselected.png":[80,60,"png","qx"],"qx/decoration/Modern/form/button-pressed-b.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-12],"qx/decoration/Modern/form/button-pressed-bl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-52],"qx/decoration/Modern/form/button-pressed-br.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-20],"qx/decoration/Modern/form/button-pressed-c.png":[40,52,"png","qx"],"qx/decoration/Modern/form/button-pressed-l.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-52,0],"qx/decoration/Modern/form/button-pressed-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",-12,0],"qx/decoration/Modern/form/button-pressed-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-100],"qx/decoration/Modern/form/button-pressed-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-172],"qx/decoration/Modern/form/button-pressed-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-64],"qx/decoration/Modern/form/button-pressed.png":[80,60,"png","qx"],"qx/decoration/Modern/form/button-r.png":[4,52,"png","qx","qx/decoration/Modern/button-lr-combined.png",0,0],"qx/decoration/Modern/form/button-t.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-92],"qx/decoration/Modern/form/button-tl.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-120],"qx/decoration/Modern/form/button-tr.png":[4,4,"png","qx","qx/decoration/Modern/button-tb-combined.png",0,-180],"qx/decoration/Modern/form/button.png":[80,60,"png","qx"],"qx/decoration/Modern/form/checkbox-checked-disabled.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-126,0],"qx/decoration/Modern/form/checkbox-checked-focused-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-322,0],"qx/decoration/Modern/form/checkbox-checked-focused.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-294,0],"qx/decoration/Modern/form/checkbox-checked-hovered-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-364,0],"qx/decoration/Modern/form/checkbox-checked-hovered.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-490,0],"qx/decoration/Modern/form/checkbox-checked-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-224,0],"qx/decoration/Modern/form/checkbox-checked-pressed-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-378,0],"qx/decoration/Modern/form/checkbox-checked-pressed.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-84,0],"qx/decoration/Modern/form/checkbox-checked.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-182,0],"qx/decoration/Modern/form/checkbox-disabled.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-42,0],"qx/decoration/Modern/form/checkbox-focused-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-392,0],"qx/decoration/Modern/form/checkbox-focused.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-210,0],"qx/decoration/Modern/form/checkbox-hovered-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-14,0],"qx/decoration/Modern/form/checkbox-hovered.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-238,0],"qx/decoration/Modern/form/checkbox-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-462,0],"qx/decoration/Modern/form/checkbox-pressed-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-112,0],"qx/decoration/Modern/form/checkbox-pressed.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-448,0],"qx/decoration/Modern/form/checkbox-undetermined-disabled.png":[14,14,"png","qx"],"qx/decoration/Modern/form/checkbox-undetermined-focused-invalid.png":[14,14,"png","qx"],"qx/decoration/Modern/form/checkbox-undetermined-focused.png":[14,14,"png","qx"],"qx/decoration/Modern/form/checkbox-undetermined-hovered-invalid.png":[14,14,"png","qx"],"qx/decoration/Modern/form/checkbox-undetermined-hovered.png":[14,14,"png","qx"],"qx/decoration/Modern/form/checkbox-undetermined-invalid.png":[14,14,"png","qx"],"qx/decoration/Modern/form/checkbox-undetermined.png":[14,14,"png","qx"],"qx/decoration/Modern/form/checkbox.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-140,0],"qx/decoration/Modern/form/input-focused.png":[40,12,"png","qx"],"qx/decoration/Modern/form/input.png":[84,12,"png","qx"],"qx/decoration/Modern/form/radiobutton-checked-disabled.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-196,0],"qx/decoration/Modern/form/radiobutton-checked-focused-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-168,0],"qx/decoration/Modern/form/radiobutton-checked-focused.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-98,0],"qx/decoration/Modern/form/radiobutton-checked-hovered-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-308,0],"qx/decoration/Modern/form/radiobutton-checked-hovered.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-406,0],"qx/decoration/Modern/form/radiobutton-checked-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-28,0],"qx/decoration/Modern/form/radiobutton-checked-pressed-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-350,0],"qx/decoration/Modern/form/radiobutton-checked-pressed.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-266,0],"qx/decoration/Modern/form/radiobutton-checked.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-252,0],"qx/decoration/Modern/form/radiobutton-disabled.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-336,0],"qx/decoration/Modern/form/radiobutton-focused-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-476,0],"qx/decoration/Modern/form/radiobutton-focused.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-420,0],"qx/decoration/Modern/form/radiobutton-hovered-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-56,0],"qx/decoration/Modern/form/radiobutton-hovered.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",0,0],"qx/decoration/Modern/form/radiobutton-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-154,0],"qx/decoration/Modern/form/radiobutton-pressed-invalid.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-434,0],"qx/decoration/Modern/form/radiobutton-pressed.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-280,0],"qx/decoration/Modern/form/radiobutton.png":[14,14,"png","qx","qx/decoration/Modern/checkradio-combined.png",-70,0],"qx/decoration/Modern/form/tooltip-error-arrow.png":[11,14,"png","qx"],"qx/decoration/Modern/form/tooltip-error-b.png":[6,6,"png","qx","qx/decoration/Modern/tooltip-error-tb-combined.png",0,-30],"qx/decoration/Modern/form/tooltip-error-bl.png":[6,6,"png","qx","qx/decoration/Modern/tooltip-error-tb-combined.png",0,-24],"qx/decoration/Modern/form/tooltip-error-br.png":[6,6,"png","qx","qx/decoration/Modern/tooltip-error-tb-combined.png",0,0],"qx/decoration/Modern/form/tooltip-error-c.png":[40,18,"png","qx"],"qx/decoration/Modern/form/tooltip-error-l.png":[6,18,"png","qx","qx/decoration/Modern/tooltip-error-lr-combined.png",-6,0],"qx/decoration/Modern/form/tooltip-error-r.png":[6,18,"png","qx","qx/decoration/Modern/tooltip-error-lr-combined.png",0,0],"qx/decoration/Modern/form/tooltip-error-t.png":[6,6,"png","qx","qx/decoration/Modern/tooltip-error-tb-combined.png",0,-6],"qx/decoration/Modern/form/tooltip-error-tl.png":[6,6,"png","qx","qx/decoration/Modern/tooltip-error-tb-combined.png",0,-18],"qx/decoration/Modern/form/tooltip-error-tr.png":[6,6,"png","qx","qx/decoration/Modern/tooltip-error-tb-combined.png",0,-12],"qx/decoration/Modern/form/tooltip-error.png":[127,30,"png","qx"],"qx/decoration/Modern/group-item.png":[110,20,"png","qx"],"qx/decoration/Modern/groupbox-lr-combined.png":[8,51,"png","qx"],"qx/decoration/Modern/groupbox-tb-combined.png":[4,24,"png","qx"],"qx/decoration/Modern/groupbox/groupbox-b.png":[4,4,"png","qx","qx/decoration/Modern/groupbox-tb-combined.png",0,-12],"qx/decoration/Modern/groupbox/groupbox-bl.png":[4,4,"png","qx","qx/decoration/Modern/groupbox-tb-combined.png",0,-16],"qx/decoration/Modern/groupbox/groupbox-br.png":[4,4,"png","qx","qx/decoration/Modern/groupbox-tb-combined.png",0,-8],"qx/decoration/Modern/groupbox/groupbox-c.png":[40,51,"png","qx"],"qx/decoration/Modern/groupbox/groupbox-l.png":[4,51,"png","qx","qx/decoration/Modern/groupbox-lr-combined.png",-4,0],"qx/decoration/Modern/groupbox/groupbox-r.png":[4,51,"png","qx","qx/decoration/Modern/groupbox-lr-combined.png",0,0],"qx/decoration/Modern/groupbox/groupbox-t.png":[4,4,"png","qx","qx/decoration/Modern/groupbox-tb-combined.png",0,-4],"qx/decoration/Modern/groupbox/groupbox-tl.png":[4,4,"png","qx","qx/decoration/Modern/groupbox-tb-combined.png",0,0],"qx/decoration/Modern/groupbox/groupbox-tr.png":[4,4,"png","qx","qx/decoration/Modern/groupbox-tb-combined.png",0,-20],"qx/decoration/Modern/groupbox/groupbox.png":[255,59,"png","qx"],"qx/decoration/Modern/menu-background-combined.png":[80,49,"png","qx"],"qx/decoration/Modern/menu-checkradio-combined.gif":[64,7,"gif","qx"],"qx/decoration/Modern/menu/background.png":[40,49,"png","qx","qx/decoration/Modern/menu-background-combined.png",-40,0],"qx/decoration/Modern/menu/bar-background.png":[40,20,"png","qx","qx/decoration/Modern/menu-background-combined.png",0,0],"qx/decoration/Modern/menu/checkbox-invert.gif":[16,7,"gif","qx","qx/decoration/Modern/menu-checkradio-combined.gif",-16,0],"qx/decoration/Modern/menu/checkbox.gif":[16,7,"gif","qx","qx/decoration/Modern/menu-checkradio-combined.gif",-48,0],"qx/decoration/Modern/menu/radiobutton-invert.gif":[16,5,"gif","qx","qx/decoration/Modern/menu-checkradio-combined.gif",-32,0],"qx/decoration/Modern/menu/radiobutton.gif":[16,5,"gif","qx","qx/decoration/Modern/menu-checkradio-combined.gif",0,0],"qx/decoration/Modern/pane-lr-combined.png":[12,238,"png","qx"],"qx/decoration/Modern/pane-tb-combined.png":[6,36,"png","qx"],"qx/decoration/Modern/pane/pane-b.png":[6,6,"png","qx","qx/decoration/Modern/pane-tb-combined.png",0,-30],"qx/decoration/Modern/pane/pane-bl.png":[6,6,"png","qx","qx/decoration/Modern/pane-tb-combined.png",0,-18],"qx/decoration/Modern/pane/pane-br.png":[6,6,"png","qx","qx/decoration/Modern/pane-tb-combined.png",0,-12],"qx/decoration/Modern/pane/pane-c.png":[40,238,"png","qx"],"qx/decoration/Modern/pane/pane-l.png":[6,238,"png","qx","qx/decoration/Modern/pane-lr-combined.png",0,0],"qx/decoration/Modern/pane/pane-r.png":[6,238,"png","qx","qx/decoration/Modern/pane-lr-combined.png",-6,0],"qx/decoration/Modern/pane/pane-t.png":[6,6,"png","qx","qx/decoration/Modern/pane-tb-combined.png",0,0],"qx/decoration/Modern/pane/pane-tl.png":[6,6,"png","qx","qx/decoration/Modern/pane-tb-combined.png",0,-24],"qx/decoration/Modern/pane/pane-tr.png":[6,6,"png","qx","qx/decoration/Modern/pane-tb-combined.png",0,-6],"qx/decoration/Modern/pane/pane.png":[185,250,"png","qx"],"qx/decoration/Modern/scrollbar-combined.png":[54,12,"png","qx"],"qx/decoration/Modern/scrollbar/scrollbar-bg-horizontal.png":[76,15,"png","qx"],"qx/decoration/Modern/scrollbar/scrollbar-bg-pressed-horizontal.png":[19,10,"png","qx"],"qx/decoration/Modern/scrollbar/scrollbar-bg-pressed-vertical.png":[10,19,"png","qx"],"qx/decoration/Modern/scrollbar/scrollbar-bg-vertical.png":[15,76,"png","qx"],"qx/decoration/Modern/scrollbar/scrollbar-button-bg-horizontal.png":[12,10,"png","qx","qx/decoration/Modern/scrollbar-combined.png",-34,0],"qx/decoration/Modern/scrollbar/scrollbar-button-bg-vertical.png":[10,12,"png","qx","qx/decoration/Modern/scrollbar-combined.png",-6,0],"qx/decoration/Modern/scrollbar/scrollbar-down.png":[6,4,"png","qx","qx/decoration/Modern/scrollbar-combined.png",-28,0],"qx/decoration/Modern/scrollbar/scrollbar-left.png":[4,6,"png","qx","qx/decoration/Modern/scrollbar-combined.png",-50,0],"qx/decoration/Modern/scrollbar/scrollbar-right.png":[4,6,"png","qx","qx/decoration/Modern/scrollbar-combined.png",-46,0],"qx/decoration/Modern/scrollbar/scrollbar-up.png":[6,4,"png","qx","qx/decoration/Modern/scrollbar-combined.png",0,0],"qx/decoration/Modern/scrollbar/slider-knob-background.png":[12,10,"png","qx","qx/decoration/Modern/scrollbar-combined.png",-16,0],"qx/decoration/Modern/selection.png":[110,20,"png","qx"],"qx/decoration/Modern/shadow-lr-combined.png":[30,382,"png","qx"],"qx/decoration/Modern/shadow-small-lr-combined.png":[10,136,"png","qx"],"qx/decoration/Modern/shadow-small-tb-combined.png":[5,30,"png","qx"],"qx/decoration/Modern/shadow-tb-combined.png":[15,90,"png","qx"],"qx/decoration/Modern/shadow/shadow-b.png":[15,15,"png","qx","qx/decoration/Modern/shadow-tb-combined.png",0,-30],"qx/decoration/Modern/shadow/shadow-bl.png":[15,15,"png","qx","qx/decoration/Modern/shadow-tb-combined.png",0,-15],"qx/decoration/Modern/shadow/shadow-br.png":[15,15,"png","qx","qx/decoration/Modern/shadow-tb-combined.png",0,-45],"qx/decoration/Modern/shadow/shadow-c.png":[40,382,"png","qx"],"qx/decoration/Modern/shadow/shadow-l.png":[15,382,"png","qx","qx/decoration/Modern/shadow-lr-combined.png",0,0],"qx/decoration/Modern/shadow/shadow-r.png":[15,382,"png","qx","qx/decoration/Modern/shadow-lr-combined.png",-15,0],"qx/decoration/Modern/shadow/shadow-small-b.png":[5,5,"png","qx","qx/decoration/Modern/shadow-small-tb-combined.png",0,-20],"qx/decoration/Modern/shadow/shadow-small-bl.png":[5,5,"png","qx","qx/decoration/Modern/shadow-small-tb-combined.png",0,-15],"qx/decoration/Modern/shadow/shadow-small-br.png":[5,5,"png","qx","qx/decoration/Modern/shadow-small-tb-combined.png",0,-10],"qx/decoration/Modern/shadow/shadow-small-c.png":[40,136,"png","qx"],"qx/decoration/Modern/shadow/shadow-small-l.png":[5,136,"png","qx","qx/decoration/Modern/shadow-small-lr-combined.png",0,0],"qx/decoration/Modern/shadow/shadow-small-r.png":[5,136,"png","qx","qx/decoration/Modern/shadow-small-lr-combined.png",-5,0],"qx/decoration/Modern/shadow/shadow-small-t.png":[5,5,"png","qx","qx/decoration/Modern/shadow-small-tb-combined.png",0,-5],"qx/decoration/Modern/shadow/shadow-small-tl.png":[5,5,"png","qx","qx/decoration/Modern/shadow-small-tb-combined.png",0,0],"qx/decoration/Modern/shadow/shadow-small-tr.png":[5,5,"png","qx","qx/decoration/Modern/shadow-small-tb-combined.png",0,-25],"qx/decoration/Modern/shadow/shadow-small.png":[114,146,"png","qx"],"qx/decoration/Modern/shadow/shadow-t.png":[15,15,"png","qx","qx/decoration/Modern/shadow-tb-combined.png",0,-60],"qx/decoration/Modern/shadow/shadow-tl.png":[15,15,"png","qx","qx/decoration/Modern/shadow-tb-combined.png",0,-75],"qx/decoration/Modern/shadow/shadow-tr.png":[15,15,"png","qx","qx/decoration/Modern/shadow-tb-combined.png",0,0],"qx/decoration/Modern/shadow/shadow.png":[381,412,"png","qx"],"qx/decoration/Modern/splitpane-knobs-combined.png":[8,9,"png","qx"],"qx/decoration/Modern/splitpane/knob-horizontal.png":[1,8,"png","qx","qx/decoration/Modern/splitpane-knobs-combined.png",0,-1],"qx/decoration/Modern/splitpane/knob-vertical.png":[8,1,"png","qx","qx/decoration/Modern/splitpane-knobs-combined.png",0,0],"qx/decoration/Modern/table-combined.png":[94,18,"png","qx"],"qx/decoration/Modern/table/ascending.png":[8,5,"png","qx","qx/decoration/Modern/table-combined.png",0,0],"qx/decoration/Modern/table/boolean-false.png":[14,14,"png","qx","qx/decoration/Modern/table-combined.png",-80,0],"qx/decoration/Modern/table/boolean-true.png":[14,14,"png","qx","qx/decoration/Modern/table-combined.png",-26,0],"qx/decoration/Modern/table/descending.png":[8,5,"png","qx","qx/decoration/Modern/table-combined.png",-18,0],"qx/decoration/Modern/table/header-cell.png":[40,18,"png","qx","qx/decoration/Modern/table-combined.png",-40,0],"qx/decoration/Modern/table/select-column-order.png":[10,9,"png","qx","qx/decoration/Modern/table-combined.png",-8,0],"qx/decoration/Modern/tabview-button-bottom-active-lr-combined.png":[10,14,"png","qx"],"qx/decoration/Modern/tabview-button-bottom-active-tb-combined.png":[5,30,"png","qx"],"qx/decoration/Modern/tabview-button-bottom-inactive-b-combined.png":[3,9,"png","qx"],"qx/decoration/Modern/tabview-button-bottom-inactive-lr-combined.png":[6,15,"png","qx"],"qx/decoration/Modern/tabview-button-bottom-inactive-t-combined.png":[3,9,"png","qx"],"qx/decoration/Modern/tabview-button-left-active-lr-combined.png":[10,37,"png","qx"],"qx/decoration/Modern/tabview-button-left-active-tb-combined.png":[5,30,"png","qx"],"qx/decoration/Modern/tabview-button-left-inactive-b-combined.png":[3,9,"png","qx"],"qx/decoration/Modern/tabview-button-left-inactive-lr-combined.png":[6,39,"png","qx"],"qx/decoration/Modern/tabview-button-left-inactive-t-combined.png":[3,9,"png","qx"],"qx/decoration/Modern/tabview-button-right-active-lr-combined.png":[10,37,"png","qx"],"qx/decoration/Modern/tabview-button-right-active-tb-combined.png":[5,30,"png","qx"],"qx/decoration/Modern/tabview-button-right-inactive-b-combined.png":[3,9,"png","qx"],"qx/decoration/Modern/tabview-button-right-inactive-lr-combined.png":[6,39,"png","qx"],"qx/decoration/Modern/tabview-button-right-inactive-t-combined.png":[3,9,"png","qx"],"qx/decoration/Modern/tabview-button-top-active-lr-combined.png":[10,12,"png","qx"],"qx/decoration/Modern/tabview-button-top-active-tb-combined.png":[5,30,"png","qx"],"qx/decoration/Modern/tabview-button-top-inactive-b-combined.png":[3,9,"png","qx"],"qx/decoration/Modern/tabview-button-top-inactive-lr-combined.png":[6,15,"png","qx"],"qx/decoration/Modern/tabview-button-top-inactive-t-combined.png":[3,9,"png","qx"],"qx/decoration/Modern/tabview-pane-lr-combined.png":[60,2,"png","qx"],"qx/decoration/Modern/tabview-pane-tb-combined.png":[30,180,"png","qx"],"qx/decoration/Modern/tabview/tab-button-bottom-active-b.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-bottom-active-tb-combined.png",0,-10],"qx/decoration/Modern/tabview/tab-button-bottom-active-bl.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-bottom-active-tb-combined.png",0,-15],"qx/decoration/Modern/tabview/tab-button-bottom-active-br.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-bottom-active-tb-combined.png",0,-5],"qx/decoration/Modern/tabview/tab-button-bottom-active-c.png":[40,14,"png","qx"],"qx/decoration/Modern/tabview/tab-button-bottom-active-l.png":[5,14,"png","qx","qx/decoration/Modern/tabview-button-bottom-active-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-bottom-active-r.png":[5,14,"png","qx","qx/decoration/Modern/tabview-button-bottom-active-lr-combined.png",-5,0],"qx/decoration/Modern/tabview/tab-button-bottom-active-t.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-bottom-active-tb-combined.png",0,-20],"qx/decoration/Modern/tabview/tab-button-bottom-active-tl.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-bottom-active-tb-combined.png",0,-25],"qx/decoration/Modern/tabview/tab-button-bottom-active-tr.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-bottom-active-tb-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-bottom-active.png":[49,24,"png","qx"],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-b.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-bottom-inactive-b-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-bl.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-bottom-inactive-b-combined.png",0,-6],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-br.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-bottom-inactive-b-combined.png",0,-3],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-c.png":[40,15,"png","qx"],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-l.png":[3,15,"png","qx","qx/decoration/Modern/tabview-button-bottom-inactive-lr-combined.png",-3,0],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-r.png":[3,15,"png","qx","qx/decoration/Modern/tabview-button-bottom-inactive-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-t.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-bottom-inactive-t-combined.png",0,-3],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-tl.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-bottom-inactive-t-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-bottom-inactive-tr.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-bottom-inactive-t-combined.png",0,-6],"qx/decoration/Modern/tabview/tab-button-bottom-inactive.png":[45,21,"png","qx"],"qx/decoration/Modern/tabview/tab-button-left-active-b.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-left-active-tb-combined.png",0,-5],"qx/decoration/Modern/tabview/tab-button-left-active-bl.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-left-active-tb-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-left-active-br.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-left-active-tb-combined.png",0,-25],"qx/decoration/Modern/tabview/tab-button-left-active-c.png":[40,37,"png","qx"],"qx/decoration/Modern/tabview/tab-button-left-active-l.png":[5,37,"png","qx","qx/decoration/Modern/tabview-button-left-active-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-left-active-r.png":[5,37,"png","qx","qx/decoration/Modern/tabview-button-left-active-lr-combined.png",-5,0],"qx/decoration/Modern/tabview/tab-button-left-active-t.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-left-active-tb-combined.png",0,-15],"qx/decoration/Modern/tabview/tab-button-left-active-tl.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-left-active-tb-combined.png",0,-10],"qx/decoration/Modern/tabview/tab-button-left-active-tr.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-left-active-tb-combined.png",0,-20],"qx/decoration/Modern/tabview/tab-button-left-active.png":[22,47,"png","qx"],"qx/decoration/Modern/tabview/tab-button-left-inactive-b.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-left-inactive-b-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-left-inactive-bl.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-left-inactive-b-combined.png",0,-6],"qx/decoration/Modern/tabview/tab-button-left-inactive-br.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-left-inactive-b-combined.png",0,-3],"qx/decoration/Modern/tabview/tab-button-left-inactive-c.png":[40,39,"png","qx"],"qx/decoration/Modern/tabview/tab-button-left-inactive-l.png":[3,39,"png","qx","qx/decoration/Modern/tabview-button-left-inactive-lr-combined.png",-3,0],"qx/decoration/Modern/tabview/tab-button-left-inactive-r.png":[3,39,"png","qx","qx/decoration/Modern/tabview-button-left-inactive-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-left-inactive-t.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-left-inactive-t-combined.png",0,-3],"qx/decoration/Modern/tabview/tab-button-left-inactive-tl.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-left-inactive-t-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-left-inactive-tr.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-left-inactive-t-combined.png",0,-6],"qx/decoration/Modern/tabview/tab-button-left-inactive.png":[20,45,"png","qx"],"qx/decoration/Modern/tabview/tab-button-right-active-b.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-right-active-tb-combined.png",0,-25],"qx/decoration/Modern/tabview/tab-button-right-active-bl.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-right-active-tb-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-right-active-br.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-right-active-tb-combined.png",0,-20],"qx/decoration/Modern/tabview/tab-button-right-active-c.png":[40,37,"png","qx"],"qx/decoration/Modern/tabview/tab-button-right-active-l.png":[5,37,"png","qx","qx/decoration/Modern/tabview-button-right-active-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-right-active-r.png":[5,37,"png","qx","qx/decoration/Modern/tabview-button-right-active-lr-combined.png",-5,0],"qx/decoration/Modern/tabview/tab-button-right-active-t.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-right-active-tb-combined.png",0,-5],"qx/decoration/Modern/tabview/tab-button-right-active-tl.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-right-active-tb-combined.png",0,-15],"qx/decoration/Modern/tabview/tab-button-right-active-tr.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-right-active-tb-combined.png",0,-10],"qx/decoration/Modern/tabview/tab-button-right-active.png":[22,47,"png","qx"],"qx/decoration/Modern/tabview/tab-button-right-inactive-b.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-right-inactive-b-combined.png",0,-3],"qx/decoration/Modern/tabview/tab-button-right-inactive-bl.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-right-inactive-b-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-right-inactive-br.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-right-inactive-b-combined.png",0,-6],"qx/decoration/Modern/tabview/tab-button-right-inactive-c.png":[40,39,"png","qx"],"qx/decoration/Modern/tabview/tab-button-right-inactive-l.png":[3,39,"png","qx","qx/decoration/Modern/tabview-button-right-inactive-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-right-inactive-r.png":[3,39,"png","qx","qx/decoration/Modern/tabview-button-right-inactive-lr-combined.png",-3,0],"qx/decoration/Modern/tabview/tab-button-right-inactive-t.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-right-inactive-t-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-right-inactive-tl.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-right-inactive-t-combined.png",0,-3],"qx/decoration/Modern/tabview/tab-button-right-inactive-tr.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-right-inactive-t-combined.png",0,-6],"qx/decoration/Modern/tabview/tab-button-right-inactive.png":[20,45,"png","qx"],"qx/decoration/Modern/tabview/tab-button-top-active-b.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-top-active-tb-combined.png",0,-20],"qx/decoration/Modern/tabview/tab-button-top-active-bl.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-top-active-tb-combined.png",0,-15],"qx/decoration/Modern/tabview/tab-button-top-active-br.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-top-active-tb-combined.png",0,-10],"qx/decoration/Modern/tabview/tab-button-top-active-c.png":[40,14,"png","qx"],"qx/decoration/Modern/tabview/tab-button-top-active-l.png":[5,12,"png","qx","qx/decoration/Modern/tabview-button-top-active-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-top-active-r.png":[5,12,"png","qx","qx/decoration/Modern/tabview-button-top-active-lr-combined.png",-5,0],"qx/decoration/Modern/tabview/tab-button-top-active-t.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-top-active-tb-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-top-active-tl.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-top-active-tb-combined.png",0,-25],"qx/decoration/Modern/tabview/tab-button-top-active-tr.png":[5,5,"png","qx","qx/decoration/Modern/tabview-button-top-active-tb-combined.png",0,-5],"qx/decoration/Modern/tabview/tab-button-top-active.png":[48,22,"png","qx"],"qx/decoration/Modern/tabview/tab-button-top-inactive-b.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-top-inactive-b-combined.png",0,-6],"qx/decoration/Modern/tabview/tab-button-top-inactive-bl.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-top-inactive-b-combined.png",0,-3],"qx/decoration/Modern/tabview/tab-button-top-inactive-br.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-top-inactive-b-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-top-inactive-c.png":[40,15,"png","qx"],"qx/decoration/Modern/tabview/tab-button-top-inactive-l.png":[3,15,"png","qx","qx/decoration/Modern/tabview-button-top-inactive-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-top-inactive-r.png":[3,15,"png","qx","qx/decoration/Modern/tabview-button-top-inactive-lr-combined.png",-3,0],"qx/decoration/Modern/tabview/tab-button-top-inactive-t.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-top-inactive-t-combined.png",0,-3],"qx/decoration/Modern/tabview/tab-button-top-inactive-tl.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-top-inactive-t-combined.png",0,0],"qx/decoration/Modern/tabview/tab-button-top-inactive-tr.png":[3,3,"png","qx","qx/decoration/Modern/tabview-button-top-inactive-t-combined.png",0,-6],"qx/decoration/Modern/tabview/tab-button-top-inactive.png":[45,21,"png","qx"],"qx/decoration/Modern/tabview/tabview-pane-b.png":[30,30,"png","qx","qx/decoration/Modern/tabview-pane-tb-combined.png",0,-60],"qx/decoration/Modern/tabview/tabview-pane-bl.png":[30,30,"png","qx","qx/decoration/Modern/tabview-pane-tb-combined.png",0,0],"qx/decoration/Modern/tabview/tabview-pane-br.png":[30,30,"png","qx","qx/decoration/Modern/tabview-pane-tb-combined.png",0,-120],"qx/decoration/Modern/tabview/tabview-pane-c.png":[40,120,"png","qx"],"qx/decoration/Modern/tabview/tabview-pane-l.png":[30,2,"png","qx","qx/decoration/Modern/tabview-pane-lr-combined.png",0,0],"qx/decoration/Modern/tabview/tabview-pane-r.png":[30,2,"png","qx","qx/decoration/Modern/tabview-pane-lr-combined.png",-30,0],"qx/decoration/Modern/tabview/tabview-pane-t.png":[30,30,"png","qx","qx/decoration/Modern/tabview-pane-tb-combined.png",0,-150],"qx/decoration/Modern/tabview/tabview-pane-tl.png":[30,30,"png","qx","qx/decoration/Modern/tabview-pane-tb-combined.png",0,-30],"qx/decoration/Modern/tabview/tabview-pane-tr.png":[30,30,"png","qx","qx/decoration/Modern/tabview-pane-tb-combined.png",0,-90],"qx/decoration/Modern/tabview/tabview-pane.png":[185,250,"png","qx"],"qx/decoration/Modern/toolbar-combined.png":[80,130,"png","qx"],"qx/decoration/Modern/toolbar/toolbar-gradient-blue.png":[40,130,"png","qx","qx/decoration/Modern/toolbar-combined.png",-40,0],"qx/decoration/Modern/toolbar/toolbar-gradient.png":[40,130,"png","qx","qx/decoration/Modern/toolbar-combined.png",0,0],"qx/decoration/Modern/toolbar/toolbar-handle-knob.gif":[1,8,"gif","qx"],"qx/decoration/Modern/toolbar/toolbar-part.gif":[7,1,"gif","qx"],"qx/decoration/Modern/tooltip-error-lr-combined.png":[12,18,"png","qx"],"qx/decoration/Modern/tooltip-error-tb-combined.png":[6,36,"png","qx"],"qx/decoration/Modern/tree-combined.png":[32,8,"png","qx"],"qx/decoration/Modern/tree/closed-selected.png":[8,8,"png","qx","qx/decoration/Modern/tree-combined.png",-24,0],"qx/decoration/Modern/tree/closed.png":[8,8,"png","qx","qx/decoration/Modern/tree-combined.png",-16,0],"qx/decoration/Modern/tree/open-selected.png":[8,8,"png","qx","qx/decoration/Modern/tree-combined.png",-8,0],"qx/decoration/Modern/tree/open.png":[8,8,"png","qx","qx/decoration/Modern/tree-combined.png",0,0],"qx/decoration/Modern/window-captionbar-buttons-combined.png":[108,9,"png","qx"],"qx/decoration/Modern/window-captionbar-lr-active-combined.png":[12,9,"png","qx"],"qx/decoration/Modern/window-captionbar-lr-inactive-combined.png":[12,9,"png","qx"],"qx/decoration/Modern/window-captionbar-tb-active-combined.png":[6,36,"png","qx"],"qx/decoration/Modern/window-captionbar-tb-inactive-combined.png":[6,36,"png","qx"],"qx/decoration/Modern/window-statusbar-lr-combined.png":[8,7,"png","qx"],"qx/decoration/Modern/window-statusbar-tb-combined.png":[4,24,"png","qx"],"qx/decoration/Modern/window/captionbar-active-b.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-active-combined.png",0,-18],"qx/decoration/Modern/window/captionbar-active-bl.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-active-combined.png",0,-24],"qx/decoration/Modern/window/captionbar-active-br.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-active-combined.png",0,-12],"qx/decoration/Modern/window/captionbar-active-c.png":[40,9,"png","qx"],"qx/decoration/Modern/window/captionbar-active-l.png":[6,9,"png","qx","qx/decoration/Modern/window-captionbar-lr-active-combined.png",-6,0],"qx/decoration/Modern/window/captionbar-active-r.png":[6,9,"png","qx","qx/decoration/Modern/window-captionbar-lr-active-combined.png",0,0],"qx/decoration/Modern/window/captionbar-active-t.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-active-combined.png",0,-6],"qx/decoration/Modern/window/captionbar-active-tl.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-active-combined.png",0,0],"qx/decoration/Modern/window/captionbar-active-tr.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-active-combined.png",0,-30],"qx/decoration/Modern/window/captionbar-active.png":[69,21,"png","qx"],"qx/decoration/Modern/window/captionbar-inactive-b.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-inactive-combined.png",0,-24],"qx/decoration/Modern/window/captionbar-inactive-bl.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-inactive-combined.png",0,-6],"qx/decoration/Modern/window/captionbar-inactive-br.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-inactive-combined.png",0,-30],"qx/decoration/Modern/window/captionbar-inactive-c.png":[40,9,"png","qx"],"qx/decoration/Modern/window/captionbar-inactive-l.png":[6,9,"png","qx","qx/decoration/Modern/window-captionbar-lr-inactive-combined.png",0,0],"qx/decoration/Modern/window/captionbar-inactive-r.png":[6,9,"png","qx","qx/decoration/Modern/window-captionbar-lr-inactive-combined.png",-6,0],"qx/decoration/Modern/window/captionbar-inactive-t.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-inactive-combined.png",0,0],"qx/decoration/Modern/window/captionbar-inactive-tl.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-inactive-combined.png",0,-12],"qx/decoration/Modern/window/captionbar-inactive-tr.png":[6,6,"png","qx","qx/decoration/Modern/window-captionbar-tb-inactive-combined.png",0,-18],"qx/decoration/Modern/window/captionbar-inactive.png":[69,21,"png","qx"],"qx/decoration/Modern/window/close-active-hovered.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-27,0],"qx/decoration/Modern/window/close-active.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-9,0],"qx/decoration/Modern/window/close-inactive.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-90,0],"qx/decoration/Modern/window/maximize-active-hovered.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-18,0],"qx/decoration/Modern/window/maximize-active.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-81,0],"qx/decoration/Modern/window/maximize-inactive.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-54,0],"qx/decoration/Modern/window/minimize-active-hovered.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-63,0],"qx/decoration/Modern/window/minimize-active.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-72,0],"qx/decoration/Modern/window/minimize-inactive.png":[9,9,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-36,0],"qx/decoration/Modern/window/restore-active-hovered.png":[9,8,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",0,0],"qx/decoration/Modern/window/restore-active.png":[9,8,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-99,0],"qx/decoration/Modern/window/restore-inactive.png":[9,8,"png","qx","qx/decoration/Modern/window-captionbar-buttons-combined.png",-45,0],"qx/decoration/Modern/window/statusbar-b.png":[4,4,"png","qx","qx/decoration/Modern/window-statusbar-tb-combined.png",0,-16],"qx/decoration/Modern/window/statusbar-bl.png":[4,4,"png","qx","qx/decoration/Modern/window-statusbar-tb-combined.png",0,-20],"qx/decoration/Modern/window/statusbar-br.png":[4,4,"png","qx","qx/decoration/Modern/window-statusbar-tb-combined.png",0,-4],"qx/decoration/Modern/window/statusbar-c.png":[40,7,"png","qx"],"qx/decoration/Modern/window/statusbar-l.png":[4,7,"png","qx","qx/decoration/Modern/window-statusbar-lr-combined.png",-4,0],"qx/decoration/Modern/window/statusbar-r.png":[4,7,"png","qx","qx/decoration/Modern/window-statusbar-lr-combined.png",0,0],"qx/decoration/Modern/window/statusbar-t.png":[4,4,"png","qx","qx/decoration/Modern/window-statusbar-tb-combined.png",0,0],"qx/decoration/Modern/window/statusbar-tl.png":[4,4,"png","qx","qx/decoration/Modern/window-statusbar-tb-combined.png",0,-8],"qx/decoration/Modern/window/statusbar-tr.png":[4,4,"png","qx","qx/decoration/Modern/window-statusbar-tb-combined.png",0,-12],"qx/decoration/Modern/window/statusbar.png":[369,15,"png","qx"],"qx/icon/Tango/16/actions/dialog-cancel.png":[16,16,"png","qx"],"qx/icon/Tango/16/actions/dialog-ok.png":[16,16,"png","qx"],"qx/icon/Tango/16/actions/view-refresh.png":[16,16,"png","qx"],"qx/icon/Tango/16/actions/window-close.png":[16,16,"png","qx"],"qx/icon/Tango/16/apps/office-calendar.png":[16,16,"png","qx"],"qx/icon/Tango/16/apps/utilities-color-chooser.png":[16,16,"png","qx"],"qx/icon/Tango/16/mimetypes/office-document.png":[16,16,"png","qx"],"qx/icon/Tango/16/places/folder-open.png":[16,16,"png","qx"],"qx/icon/Tango/16/places/folder.png":[16,16,"png","qx"],"qx/icon/Tango/22/actions/edit-find.png":[22,22,"png","qx"],"qx/icon/Tango/22/actions/media-seek-forward.png":[22,22,"png","qx"],"qx/icon/Tango/22/apps/utilities-dictionary.png":[22,22,"png","qx"],"qx/icon/Tango/22/apps/utilities-graphics-viewer.png":[22,22,"png","qx"],"qx/icon/Tango/22/apps/utilities-help.png":[22,22,"png","qx"],"qx/icon/Tango/22/mimetypes/office-document.png":[22,22,"png","qx"],"qx/icon/Tango/22/places/folder-open.png":[22,22,"png","qx"],"qx/icon/Tango/22/places/folder.png":[22,22,"png","qx"],"qx/icon/Tango/32/mimetypes/office-document.png":[32,32,"png","qx"],"qx/icon/Tango/32/places/folder-open.png":[32,32,"png","qx"],"qx/icon/Tango/32/places/folder.png":[32,32,"png","qx"],"qx/static/blank.gif":[1,1,"gif","qx"],"qx/static/blank.html":"qx"},"translations":{"C":{}}};
+(function(){var m="toString",k=".",j="default",h="Object",g='"',f="Array",e="()",d="String",c="Function",b=".prototype",L="function",K="Boolean",J="Error",I="constructor",H="warn",G="hasOwnProperty",F="string",E="toLocaleString",D="RegExp",C='\", "',t="info",u="BROKEN_IE",r="isPrototypeOf",s="Date",p="",q="qx.Bootstrap",n="]",o="Class",v="error",w="[Class ",y="valueOf",x="Number",A="count",z="debug",B="ES5";if(!window.qx){window.qx={};}qx.Bootstrap={genericToString:function(){return w+this.classname+n;},createNamespace:function(name,M){var O=name.split(k);var parent=window;var N=O[0];for(var i=0,P=O.length-1;i<P;i++,N=O[i]){if(!parent[N]){parent=parent[N]={};}else{parent=parent[N];}}parent[N]=M;return N;},setDisplayName:function(Q,R,name){Q.displayName=R+k+name+e;},setDisplayNames:function(S,T){for(var name in S){var U=S[name];if(U instanceof Function){U.displayName=T+k+name+e;}}},define:function(name,V){if(!V){var V={statics:{}};}var bb;var Y=null;qx.Bootstrap.setDisplayNames(V.statics,name);if(V.members||V.extend){qx.Bootstrap.setDisplayNames(V.members,name+b);bb=V.construct||new Function;if(V.extend){this.extendClass(bb,bb,V.extend,name,ba);}var W=V.statics||{};for(var i=0,bc=qx.Bootstrap.getKeys(W),l=bc.length;i<l;i++){var bd=bc[i];bb[bd]=W[bd];}Y=bb.prototype;var X=V.members||{};for(var i=0,bc=qx.Bootstrap.getKeys(X),l=bc.length;i<l;i++){var bd=bc[i];Y[bd]=X[bd];}}else{bb=V.statics||{};}var ba=this.createNamespace(name,bb);bb.name=bb.classname=name;bb.basename=ba;bb.$$type=o;if(!bb.hasOwnProperty(m)){bb.toString=this.genericToString;}if(V.defer){V.defer(bb,Y);}qx.Bootstrap.$$registry[name]=V.statics;return bb;}};qx.Bootstrap.define(q,{statics:{LOADSTART:qx.$$start||new Date(),createNamespace:qx.Bootstrap.createNamespace,define:qx.Bootstrap.define,setDisplayName:qx.Bootstrap.setDisplayName,setDisplayNames:qx.Bootstrap.setDisplayNames,genericToString:qx.Bootstrap.genericToString,extendClass:function(be,bf,bg,name,bh){var bk=bg.prototype;var bj=new Function;bj.prototype=bk;var bi=new bj;be.prototype=bi;bi.name=bi.classname=name;bi.basename=bh;bf.base=be.superclass=bg;bf.self=be.constructor=bi.constructor=be;},getByName:function(name){return qx.Bootstrap.$$registry[name];},$$registry:{},objectGetLength:({"count":function(bl){return bl.__count__;},"default":function(bm){var length=0;for(var bn in bm){length++;}return length;}})[(({}).__count__==0)?A:j],objectMergeWith:function(bo,bp,bq){if(bq===undefined){bq=true;}for(var br in bp){if(bq||bo[br]===undefined){bo[br]=bp[br];}}return bo;},__id:[r,G,E,m,y,I],getKeys:({"ES5":Object.keys,"BROKEN_IE":function(bs){var bt=[];var bv=Object.prototype.hasOwnProperty;for(var bw in bs){if(bv.call(bs,bw)){bt.push(bw);}}var bu=qx.Bootstrap.__id;for(var i=0,a=bu,l=a.length;i<l;i++){if(bv.call(bs,a[i])){bt.push(a[i]);}}return bt;},"default":function(bx){var by=[];var bz=Object.prototype.hasOwnProperty;for(var bA in bx){if(bz.call(bx,bA)){by.push(bA);}}return by;}})[typeof (Object.keys)==L?B:(function(){for(var bB in {toString:1}){return bB;}})()!==m?u:j],getKeysAsString:function(bC){var bD=qx.Bootstrap.getKeys(bC);if(bD.length==0){return p;}return g+bD.join(C)+g;},__ie:{"[object String]":d,"[object Array]":f,"[object Object]":h,"[object RegExp]":D,"[object Number]":x,"[object Boolean]":K,"[object Date]":s,"[object Function]":c,"[object Error]":J},bind:function(bE,self,bF){var bG=Array.prototype.slice.call(arguments,2,arguments.length);return function(){var bH=Array.prototype.slice.call(arguments,0,arguments.length);return bE.apply(self,bG.concat(bH));};},firstUp:function(bI){return bI.charAt(0).toUpperCase()+bI.substr(1);},firstLow:function(bJ){return bJ.charAt(0).toLowerCase()+bJ.substr(1);},getClass:function(bK){var bL=Object.prototype.toString.call(bK);return (qx.Bootstrap.__ie[bL]||bL.slice(8,-1));},isString:function(bM){return (bM!==null&&(typeof bM===F||qx.Bootstrap.getClass(bM)==d||bM instanceof String||(!!bM&&!!bM.$$isString)));},isArray:function(bN){return (bN!==null&&(bN instanceof Array||(bN&&qx.data&&qx.data.IListData&&qx.Bootstrap.hasInterface(bN.constructor,qx.data.IListData))||qx.Bootstrap.getClass(bN)==f||(!!bN&&!!bN.$$isArray)));},isObject:function(bO){return (bO!==undefined&&bO!==null&&qx.Bootstrap.getClass(bO)==h);},isFunction:function(bP){return qx.Bootstrap.getClass(bP)==c;},classIsDefined:function(name){return qx.Bootstrap.getByName(name)!==undefined;},getPropertyDefinition:function(bQ,name){while(bQ){if(bQ.$$properties&&bQ.$$properties[name]){return bQ.$$properties[name];}bQ=bQ.superclass;}return null;},hasProperty:function(bR,name){return !!qx.Bootstrap.getPropertyDefinition(bR,name);},getEventType:function(bS,name){var bS=bS.constructor;while(bS.superclass){if(bS.$$events&&bS.$$events[name]!==undefined){return bS.$$events[name];}bS=bS.superclass;}return null;},supportsEvent:function(bT,name){return !!qx.Bootstrap.getEventType(bT,name);},getByInterface:function(bU,bV){var bW,i,l;while(bU){if(bU.$$implements){bW=bU.$$flatImplements;for(i=0,l=bW.length;i<l;i++){if(bW[i]===bV){return bU;}}}bU=bU.superclass;}return null;},hasInterface:function(bX,bY){return !!qx.Bootstrap.getByInterface(bX,bY);},getMixins:function(ca){var cb=[];while(ca){if(ca.$$includes){cb.push.apply(cb,ca.$$flatIncludes);}ca=ca.superclass;}return cb;},$$logs:[],debug:function(cc,cd){qx.Bootstrap.$$logs.push([z,arguments]);},info:function(ce,cf){qx.Bootstrap.$$logs.push([t,arguments]);},warn:function(cg,ch){qx.Bootstrap.$$logs.push([H,arguments]);},error:function(ci,cj){qx.Bootstrap.$$logs.push([v,arguments]);},trace:function(ck){}}});})();(function(){var g="qx.Mixin",f=".prototype",e="constructor",d="[Mixin ",c="]",b="destruct",a="Mixin";qx.Bootstrap.define(g,{statics:{define:function(name,h){if(h){if(h.include&&!(h.include instanceof Array)){h.include=[h.include];}{};var k=h.statics?h.statics:{};qx.Bootstrap.setDisplayNames(k,name);for(var j in k){if(k[j] instanceof Function){k[j].$$mixin=k;}}if(h.construct){k.$$constructor=h.construct;qx.Bootstrap.setDisplayName(h.construct,name,e);}if(h.include){k.$$includes=h.include;}if(h.properties){k.$$properties=h.properties;}if(h.members){k.$$members=h.members;qx.Bootstrap.setDisplayNames(h.members,name+f);}for(var j in k.$$members){if(k.$$members[j] instanceof Function){k.$$members[j].$$mixin=k;}}if(h.events){k.$$events=h.events;}if(h.destruct){k.$$destructor=h.destruct;qx.Bootstrap.setDisplayName(h.destruct,name,b);}}else{var k={};}k.$$type=a;k.name=name;k.toString=this.genericToString;k.basename=qx.Bootstrap.createNamespace(name,k);this.$$registry[name]=k;return k;},checkCompatibility:function(m){var p=this.flatten(m);var q=p.length;if(q<2){return true;}var t={};var s={};var r={};var o;for(var i=0;i<q;i++){o=p[i];for(var n in o.events){if(r[n]){throw new Error('Conflict between mixin "'+o.name+'" and "'+r[n]+'" in member "'+n+'"!');}r[n]=o.name;}for(var n in o.properties){if(t[n]){throw new Error('Conflict between mixin "'+o.name+'" and "'+t[n]+'" in property "'+n+'"!');}t[n]=o.name;}for(var n in o.members){if(s[n]){throw new Error('Conflict between mixin "'+o.name+'" and "'+s[n]+'" in member "'+n+'"!');}s[n]=o.name;}}return true;},isCompatible:function(u,v){var w=qx.Bootstrap.getMixins(v);w.push(u);return qx.Mixin.checkCompatibility(w);},getByName:function(name){return this.$$registry[name];},isDefined:function(name){return this.getByName(name)!==undefined;},getTotalNumber:function(){return qx.Bootstrap.objectGetLength(this.$$registry);},flatten:function(x){if(!x){return [];}var y=x.concat();for(var i=0,l=x.length;i<l;i++){if(x[i].$$includes){y.push.apply(y,this.flatten(x[i].$$includes));}}return y;},genericToString:function(){return d+this.name+c;},$$registry:{},__er:null,__es:function(){}}});})();(function(){var h="qx.allowUrlSettings",g="&",f="qx.core.Setting",e="qx.allowUrlVariants",d="qx.propertyDebugLevel",c="qxsetting",b=":",a=".";qx.Bootstrap.define(f,{statics:{__eu:{},define:function(j,k){if(k===undefined){throw new Error('Default value of setting "'+j+'" must be defined!');}if(!this.__eu[j]){this.__eu[j]={};}else if(this.__eu[j].defaultValue!==undefined){throw new Error('Setting "'+j+'" is already defined!');}this.__eu[j].defaultValue=k;},get:function(l){var m=this.__eu[l];if(m===undefined){throw new Error('Setting "'+l+'" is not defined.');}if(m.value!==undefined){return m.value;}return m.defaultValue;},set:function(n,o){if((n.split(a)).length<2){throw new Error('Malformed settings key "'+n+'". Must be following the schema "namespace.key".');}if(!this.__eu[n]){this.__eu[n]={};}this.__eu[n].value=o;},__ev:function(){if(window.qxsettings){for(var p in window.qxsettings){this.set(p,window.qxsettings[p]);}window.qxsettings=undefined;try{delete window.qxsettings;}catch(q){}this.__ew();}},__ew:function(){if(this.get(h)!=true){return;}var s=document.location.search.slice(1).split(g);for(var i=0;i<s.length;i++){var r=s[i].split(b);if(r.length!=3||r[0]!=c){continue;}this.set(r[1],decodeURIComponent(r[2]));}}},defer:function(t){t.define(h,false);t.define(e,false);t.define(d,0);t.__ev();}});})();(function(){var h="function",g="Boolean",f="qx.Interface",e="]",d="toggle",c="Interface",b="is",a="[Interface ";qx.Bootstrap.define(f,{statics:{define:function(name,j){if(j){if(j.extend&&!(j.extend instanceof Array)){j.extend=[j.extend];}{};var k=j.statics?j.statics:{};if(j.extend){k.$$extends=j.extend;}if(j.properties){k.$$properties=j.properties;}if(j.members){k.$$members=j.members;}if(j.events){k.$$events=j.events;}}else{var k={};}k.$$type=c;k.name=name;k.toString=this.genericToString;k.basename=qx.Bootstrap.createNamespace(name,k);qx.Interface.$$registry[name]=k;return k;},getByName:function(name){return this.$$registry[name];},isDefined:function(name){return this.getByName(name)!==undefined;},getTotalNumber:function(){return qx.Bootstrap.objectGetLength(this.$$registry);},flatten:function(m){if(!m){return [];}var n=m.concat();for(var i=0,l=m.length;i<l;i++){if(m[i].$$extends){n.push.apply(n,this.flatten(m[i].$$extends));}}return n;},__fI:function(o,p,q,r){var v=q.$$members;if(v){for(var u in v){if(qx.Bootstrap.isFunction(v[u])){var t=this.__fJ(p,u);var s=t||qx.Bootstrap.isFunction(o[u]);if(!s){throw new Error('Implementation of method "'+u+'" is missing in class "'+p.classname+'" required by interface "'+q.name+'"');}var w=r===true&&!t&&!qx.Bootstrap.hasInterface(p,q);if(w){o[u]=this.__fM(q,o[u],u,v[u]);}}else{if(typeof o[u]===undefined){if(typeof o[u]!==h){throw new Error('Implementation of member "'+u+'" is missing in class "'+p.classname+'" required by interface "'+q.name+'"');}}}}}},__fJ:function(x,y){var C=y.match(/^(is|toggle|get|set|reset)(.*)$/);if(!C){return false;}var z=qx.Bootstrap.firstLow(C[2]);var A=qx.Bootstrap.getPropertyDefinition(x,z);if(!A){return false;}var B=C[0]==b||C[0]==d;if(B){return qx.Bootstrap.getPropertyDefinition(x,z).check==g;}return true;},__fK:function(D,E){if(E.$$properties){for(var F in E.$$properties){if(!qx.Bootstrap.getPropertyDefinition(D,F)){throw new Error('The property "'+F+'" is not supported by Class "'+D.classname+'"!');}}}},__fL:function(G,H){if(H.$$events){for(var I in H.$$events){if(!qx.Bootstrap.supportsEvent(G,I)){throw new Error('The event "'+I+'" is not supported by Class "'+G.classname+'"!');}}}},assertObject:function(J,K){var M=J.constructor;this.__fI(J,M,K,false);this.__fK(M,K);this.__fL(M,K);var L=K.$$extends;if(L){for(var i=0,l=L.length;i<l;i++){this.assertObject(J,L[i]);}}},assert:function(N,O,P){this.__fI(N.prototype,N,O,P);this.__fK(N,O);this.__fL(N,O);var Q=O.$$extends;if(Q){for(var i=0,l=Q.length;i<l;i++){this.assert(N,Q[i],P);}}},genericToString:function(){return a+this.name+e;},$$registry:{},__fM:function(){},__fN:null,__fO:function(){}}});})();(function(){var g="emulated",f="native",e='"',d="qx.lang.Core",c="\\\\",b="\\\"",a="[object Error]";qx.Bootstrap.define(d,{statics:{errorToString:{"native":Error.prototype.toString,"emulated":function(){return this.message;}}[(!Error.prototype.toString||Error.prototype.toString()==a)?g:f],arrayIndexOf:{"native":Array.prototype.indexOf,"emulated":function(h,j){if(j==null){j=0;}else if(j<0){j=Math.max(0,this.length+j);}for(var i=j;i<this.length;i++){if(this[i]===h){return i;}}return -1;}}[Array.prototype.indexOf?f:g],arrayLastIndexOf:{"native":Array.prototype.lastIndexOf,"emulated":function(k,m){if(m==null){m=this.length-1;}else if(m<0){m=Math.max(0,this.length+m);}for(var i=m;i>=0;i--){if(this[i]===k){return i;}}return -1;}}[Array.prototype.lastIndexOf?f:g],arrayForEach:{"native":Array.prototype.forEach,"emulated":function(n,o){var l=this.length;for(var i=0;i<l;i++){var p=this[i];if(p!==undefined){n.call(o||window,p,i,this);}}}}[Array.prototype.forEach?f:g],arrayFilter:{"native":Array.prototype.filter,"emulated":function(q,r){var s=[];var l=this.length;for(var i=0;i<l;i++){var t=this[i];if(t!==undefined){if(q.call(r||window,t,i,this)){s.push(this[i]);}}}return s;}}[Array.prototype.filter?f:g],arrayMap:{"native":Array.prototype.map,"emulated":function(u,v){var w=[];var l=this.length;for(var i=0;i<l;i++){var x=this[i];if(x!==undefined){w[i]=u.call(v||window,x,i,this);}}return w;}}[Array.prototype.map?f:g],arraySome:{"native":Array.prototype.some,"emulated":function(y,z){var l=this.length;for(var i=0;i<l;i++){var A=this[i];if(A!==undefined){if(y.call(z||window,A,i,this)){return true;}}}return false;}}[Array.prototype.some?f:g],arrayEvery:{"native":Array.prototype.every,"emulated":function(B,C){var l=this.length;for(var i=0;i<l;i++){var D=this[i];if(D!==undefined){if(!B.call(C||window,D,i,this)){return false;}}}return true;}}[Array.prototype.every?f:g],stringQuote:{"native":String.prototype.quote,"emulated":function(){return e+this.replace(/\\/g,c).replace(/\"/g,b)+e;}}[String.prototype.quote?f:g]}});Error.prototype.toString=qx.lang.Core.errorToString;Array.prototype.indexOf=qx.lang.Core.arrayIndexOf;Array.prototype.lastIndexOf=qx.lang.Core.arrayLastIndexOf;Array.prototype.forEach=qx.lang.Core.arrayForEach;Array.prototype.filter=qx.lang.Core.arrayFilter;Array.prototype.map=qx.lang.Core.arrayMap;Array.prototype.some=qx.lang.Core.arraySome;Array.prototype.every=qx.lang.Core.arrayEvery;String.prototype.quote=qx.lang.Core.stringQuote;})();(function(){var cv=';',cu='computed=this.',ct='=value;',cs='this.',cr="set",cq="setThemed",cp="setRuntime",co="init",cn='if(this.',cm='delete this.',bw='!==undefined)',bv='}',bu="resetThemed",bt='else if(this.',bs="string",br='return this.',bq="reset",bp="boolean",bo="resetRuntime",bn='!==undefined){',cC="",cD="refresh",cA='=true;',cB="this.",cy=";",cz='old=this.',cw="();",cx='else ',cE='if(old===undefined)old=this.',cF='old=computed=this.',bU="return this.",bT="get",bW='(value);',bV="(a[",bY='if(old===computed)return value;',bX='if(old===undefined)old=null;',cb=' of an instance of ',ca=' is not (yet) ready!");',bS="]);",bR='!==inherit){',c='qx.lang.Type.isString(value) && qx.util.ColorUtil.isValidPropertyValue(value)',d='value !== null && qx.theme.manager.Font.getInstance().isDynamic(value)',e='value !== null && value.nodeType === 9 && value.documentElement',f='===value)return value;',g='value !== null && value.$$type === "Mixin"',h='return init;',j='var init=this.',k='value !== null && value.nodeType === 1 && value.attributes',m="var parent = this.getLayoutParent();",n="Error in property ",cT='var a=this._getChildren();if(a)for(var i=0,l=a.length;i<l;i++){',cS='.validate.call(this, value);',cR='qx.core.Assert.assertInstance(value, Date, msg) || true',cQ='else{',cX="if (!parent) return;",cW=" in method ",cV='qx.core.Assert.assertInstance(value, Error, msg) || true',cU='=computed;',da='Undefined value is not allowed!',cY='(backup);',M="MSIE 6.0",N='if(computed===inherit){',K="inherit",L='Is invalid!',Q='if(value===undefined)prop.error(this,2,"',R='var computed, old=this.',O='else if(computed===undefined)',P="': ",I=" of class ",J='value !== null && value.nodeType !== undefined',v='===undefined)return;',u='value !== null && qx.theme.manager.Decoration.getInstance().isValidPropertyValue(value)',x="')){",w='qx.core.Assert.assertPositiveInteger(value, msg) || true',r='else this.',q='value=this.',t='","',s='if(init==qx.core.Property.$$inherit)init=null;',p='value !== null && value.$$type === "Interface"',o='var inherit=prop.$$inherit;',W="', qx.event.type.Data, [computed, old]",X="var value = parent.",Y="$$useinit_",ba='computed=undefined;delete this.',S="(value);",T='Requires exactly one argument!',U='",value);',V='computed=value;',bb="$$runtime_",bc=';}',F="$$user_",E='){',D='qx.core.Assert.assertArray(value, msg) || true',C='if(computed===undefined||computed===inherit){',B='qx.core.Assert.assertPositiveNumber(value, msg) || true',A=".prototype",z="Boolean",y=")}",H='(computed, old, "',G='return value;',bd='if(init==qx.core.Property.$$inherit)throw new Error("Inheritable property ',be="if(reg.hasListener(this, '",bf='Does not allow any arguments!',bg=')a[i].',bh="()",bi="var a=arguments[0] instanceof Array?arguments[0]:arguments;",bj='.$$properties.',bk='value !== null && value.$$type === "Theme"',bl="var reg=qx.event.Registration;",bm="())",bA='return null;',bz='qx.core.Assert.assertObject(value, msg) || true',by='");',bx='qx.core.Assert.assertString(value, msg) || true',bE='var pa=this.getLayoutParent();if(pa)computed=pa.',bD="if (value===undefined) value = parent.",bC='value !== null && value.$$type === "Class"',bB='qx.core.Assert.assertFunction(value, msg) || true',bG='!==undefined&&',bF='var computed, old;',bN='var backup=computed;',bO='}else{',bL="object",bM="$$init_",bJ="$$theme_",bK='if(computed===undefined)computed=null;',bH='qx.core.Assert.assertMap(value, msg) || true',bI='qx.core.Assert.assertNumber(value, msg) || true',bP='if((computed===undefined||computed===inherit)&&',bQ="reg.fireEvent(this, '",cf='Null value is not allowed!',ce='qx.core.Assert.assertInteger(value, msg) || true',ch="value",cg="rv:1.8.1",cj="shorthand",ci='qx.core.Assert.assertInstance(value, RegExp, msg) || true',cl='value !== null && value.type !== undefined',ck='value !== null && value.document',cd='throw new Error("Property ',cc="(!this.",cM='qx.core.Assert.assertBoolean(value, msg) || true',cN='if(a[i].',cO="toggle",cP="$$inherit_",cI='var prop=qx.core.Property;',cJ=" with incoming value '",cK="a=qx.lang.Array.fromShortHand(qx.lang.Array.fromArguments(a));",cL='if(computed===undefined||computed==inherit)computed=null;',cG="qx.core.Property",cH="is",b='Could not change or apply init value after constructing phase!';qx.Bootstrap.define(cG,{statics:{__lF:{"Boolean":cM,"String":bx,"Number":bI,"Integer":ce,"PositiveNumber":B,"PositiveInteger":w,"Error":cV,"RegExp":ci,"Object":bz,"Array":D,"Map":bH,"Function":bB,"Date":cR,"Node":J,"Element":k,"Document":e,"Window":ck,"Event":cl,"Class":bC,"Mixin":g,"Interface":p,"Theme":bk,"Color":c,"Decorator":u,"Font":d},__lG:{"Node":true,"Element":true,"Document":true,"Window":true,"Event":true},$$inherit:K,$$store:{runtime:{},user:{},theme:{},inherit:{},init:{},useinit:{}},$$method:{get:{},set:{},reset:{},init:{},refresh:{},setRuntime:{},resetRuntime:{},setThemed:{},resetThemed:{}},$$allowedKeys:{name:bs,dereference:bp,inheritable:bp,nullable:bp,themeable:bp,refine:bp,init:null,apply:bs,event:bs,check:null,transform:bs,deferredInit:bp,validate:null},$$allowedGroupKeys:{name:bs,group:bL,mode:bs,themeable:bp},$$inheritable:{},__lH:function(db){var dc=this.__lI(db);if(!dc.length){var dd=qx.lang.Function.empty;}else{dd=this.__lJ(dc);}db.prototype.$$refreshInheritables=dd;},__lI:function(de){var dg=[];while(de){var df=de.$$properties;if(df){for(var name in this.$$inheritable){if(df[name]&&df[name].inheritable){dg.push(name);}}}de=de.superclass;}return dg;},__lJ:function(dh){var dl=this.$$store.inherit;var dk=this.$$store.init;var dj=this.$$method.refresh;var di=[m,cX];for(var i=0,l=dh.length;i<l;i++){var name=dh[i];di.push(X,dl[name],cy,bD,dk[name],cy,cB,dj[name],S);}return new Function(di.join(cC));},attachRefreshInheritables:function(dm){dm.prototype.$$refreshInheritables=function(){qx.core.Property.__lH(dm);return this.$$refreshInheritables();};},attachMethods:function(dn,name,dp){dp.group?this.__lK(dn,dp,name):this.__lL(dn,dp,name);},__lK:function(dq,dr,name){var dy=qx.Bootstrap.firstUp(name);var dx=dq.prototype;var dz=dr.themeable===true;{};var dA=[];var du=[];if(dz){var ds=[];var dw=[];}var dv=bi;dA.push(dv);if(dz){ds.push(dv);}if(dr.mode==cj){var dt=cK;dA.push(dt);if(dz){ds.push(dt);}}for(var i=0,a=dr.group,l=a.length;i<l;i++){{};dA.push(cB,this.$$method.set[a[i]],bV,i,bS);du.push(cB,this.$$method.reset[a[i]],cw);if(dz){{};ds.push(cB,this.$$method.setThemed[a[i]],bV,i,bS);dw.push(cB,this.$$method.resetThemed[a[i]],cw);}}this.$$method.set[name]=cr+dy;dx[this.$$method.set[name]]=new Function(dA.join(cC));this.$$method.reset[name]=bq+dy;dx[this.$$method.reset[name]]=new Function(du.join(cC));if(dz){this.$$method.setThemed[name]=cq+dy;dx[this.$$method.setThemed[name]]=new Function(ds.join(cC));this.$$method.resetThemed[name]=bu+dy;dx[this.$$method.resetThemed[name]]=new Function(dw.join(cC));}},__lL:function(dB,dC,name){var dE=qx.Bootstrap.firstUp(name);var dG=dB.prototype;{};if(dC.dereference===undefined&&typeof dC.check===bs){dC.dereference=this.__lM(dC.check);}var dF=this.$$method;var dD=this.$$store;dD.runtime[name]=bb+name;dD.user[name]=F+name;dD.theme[name]=bJ+name;dD.init[name]=bM+name;dD.inherit[name]=cP+name;dD.useinit[name]=Y+name;dF.get[name]=bT+dE;dG[dF.get[name]]=function(){return qx.core.Property.executeOptimizedGetter(this,dB,name,bT);};dF.set[name]=cr+dE;dG[dF.set[name]]=function(dH){return qx.core.Property.executeOptimizedSetter(this,dB,name,cr,arguments);};dF.reset[name]=bq+dE;dG[dF.reset[name]]=function(){return qx.core.Property.executeOptimizedSetter(this,dB,name,bq);};if(dC.inheritable||dC.apply||dC.event||dC.deferredInit){dF.init[name]=co+dE;dG[dF.init[name]]=function(dI){return qx.core.Property.executeOptimizedSetter(this,dB,name,co,arguments);};}if(dC.inheritable){dF.refresh[name]=cD+dE;dG[dF.refresh[name]]=function(dJ){return qx.core.Property.executeOptimizedSetter(this,dB,name,cD,arguments);};}dF.setRuntime[name]=cp+dE;dG[dF.setRuntime[name]]=function(dK){return qx.core.Property.executeOptimizedSetter(this,dB,name,cp,arguments);};dF.resetRuntime[name]=bo+dE;dG[dF.resetRuntime[name]]=function(){return qx.core.Property.executeOptimizedSetter(this,dB,name,bo);};if(dC.themeable){dF.setThemed[name]=cq+dE;dG[dF.setThemed[name]]=function(dL){return qx.core.Property.executeOptimizedSetter(this,dB,name,cq,arguments);};dF.resetThemed[name]=bu+dE;dG[dF.resetThemed[name]]=function(){return qx.core.Property.executeOptimizedSetter(this,dB,name,bu);};}if(dC.check===z){dG[cO+dE]=new Function(bU+dF.set[name]+cc+dF.get[name]+bm);dG[cH+dE]=new Function(bU+dF.get[name]+bh);}},__lM:function(dM){return !!this.__lG[dM];},__lN:function(dN){return this.__lG[dN]||qx.Bootstrap.classIsDefined(dN)||(qx.Interface&&qx.Interface.isDefined(dN));},__lO:{0:b,1:T,2:da,3:bf,4:cf,5:L},error:function(dO,dP,dQ,dR,dS){var dT=dO.constructor.classname;var dU=n+dQ+I+dT+cW+this.$$method[dR][dQ]+cJ+dS+P;throw new Error(dU+(this.__lO[dP]||"Unknown reason: "+dP));},__lP:function(dV,dW,name,dX,dY,ea){var eb=this.$$method[dX][name];{dW[eb]=new Function(ch,dY.join(cC));};{};qx.Bootstrap.setDisplayName(dW[eb],dV.classname+A,eb);if(ea===undefined){return dV[eb]();}else{return dV[eb](ea[0]);}},executeOptimizedGetter:function(ec,ed,name,ee){var eg=ed.$$properties[name];var ei=ed.prototype;var ef=[];var eh=this.$$store;ef.push(cn,eh.runtime[name],bw);ef.push(br,eh.runtime[name],cv);if(eg.inheritable){ef.push(bt,eh.inherit[name],bw);ef.push(br,eh.inherit[name],cv);ef.push(cx);}ef.push(cn,eh.user[name],bw);ef.push(br,eh.user[name],cv);if(eg.themeable){ef.push(bt,eh.theme[name],bw);ef.push(br,eh.theme[name],cv);}if(eg.deferredInit&&eg.init===undefined){ef.push(bt,eh.init[name],bw);ef.push(br,eh.init[name],cv);}ef.push(cx);if(eg.init!==undefined){if(eg.inheritable){ef.push(j,eh.init[name],cv);if(eg.nullable){ef.push(s);}else if(eg.init!==undefined){ef.push(br,eh.init[name],cv);}else{ef.push(bd,name,cb,ed.classname,ca);}ef.push(h);}else{ef.push(br,eh.init[name],cv);}}else if(eg.inheritable||eg.nullable){ef.push(bA);}else{ef.push(cd,name,cb,ed.classname,ca);}return this.__lP(ec,ei,name,ee,ef);},executeOptimizedSetter:function(ej,ek,name,el,em){var er=ek.$$properties[name];var eq=ek.prototype;var eo=[];var en=el===cr||el===cq||el===cp||(el===co&&er.init===undefined);var ep=er.apply||er.event||er.inheritable;var es=this.__lQ(el,name);this.__lR(eo,er,name,el,en);if(en){this.__lS(eo,ek,er,name);}if(ep){this.__lT(eo,en,es,el);}if(er.inheritable){eo.push(o);}{};if(!ep){this.__lV(eo,name,el,en);}else{this.__lW(eo,er,name,el,en);}if(er.inheritable){this.__lX(eo,er,name,el);}else if(ep){this.__lY(eo,er,name,el);}if(ep){this.__ma(eo,er,name);if(er.inheritable&&eq._getChildren){this.__mb(eo,name);}}if(en){eo.push(G);}return this.__lP(ej,eq,name,el,eo,em);},__lQ:function(et,name){if(et===cp||et===bo){var eu=this.$$store.runtime[name];}else if(et===cq||et===bu){eu=this.$$store.theme[name];}else if(et===co){eu=this.$$store.init[name];}else{eu=this.$$store.user[name];}return eu;},__lR:function(ev,ew,name,ex,ey){{if(!ew.nullable||ew.check||ew.inheritable){ev.push(cI);}if(ex===cr){ev.push(Q,name,t,ex,U);}};},__lS:function(ez,eA,eB,name){if(eB.transform){ez.push(q,eB.transform,bW);}if(eB.validate){if(typeof eB.validate===bs){ez.push(cs,eB.validate,bW);}else if(eB.validate instanceof Function){ez.push(eA.classname,bj,name);ez.push(cS);}}},__lT:function(eC,eD,eE,eF){var eG=(eF===bq||eF===bu||eF===bo);if(eD){eC.push(cn,eE,f);}else if(eG){eC.push(cn,eE,v);}},__lU:undefined,__lV:function(eH,name,eI,eJ){if(eI===cp){eH.push(cs,this.$$store.runtime[name],ct);}else if(eI===bo){eH.push(cn,this.$$store.runtime[name],bw);eH.push(cm,this.$$store.runtime[name],cv);}else if(eI===cr){eH.push(cs,this.$$store.user[name],ct);}else if(eI===bq){eH.push(cn,this.$$store.user[name],bw);eH.push(cm,this.$$store.user[name],cv);}else if(eI===cq){eH.push(cs,this.$$store.theme[name],ct);}else if(eI===bu){eH.push(cn,this.$$store.theme[name],bw);eH.push(cm,this.$$store.theme[name],cv);}else if(eI===co&&eJ){eH.push(cs,this.$$store.init[name],ct);}},__lW:function(eK,eL,name,eM,eN){if(eL.inheritable){eK.push(R,this.$$store.inherit[name],cv);}else{eK.push(bF);}eK.push(cn,this.$$store.runtime[name],bn);if(eM===cp){eK.push(cu,this.$$store.runtime[name],ct);}else if(eM===bo){eK.push(cm,this.$$store.runtime[name],cv);eK.push(cn,this.$$store.user[name],bw);eK.push(cu,this.$$store.user[name],cv);eK.push(bt,this.$$store.theme[name],bw);eK.push(cu,this.$$store.theme[name],cv);eK.push(bt,this.$$store.init[name],bn);eK.push(cu,this.$$store.init[name],cv);eK.push(cs,this.$$store.useinit[name],cA);eK.push(bv);}else{eK.push(cF,this.$$store.runtime[name],cv);if(eM===cr){eK.push(cs,this.$$store.user[name],ct);}else if(eM===bq){eK.push(cm,this.$$store.user[name],cv);}else if(eM===cq){eK.push(cs,this.$$store.theme[name],ct);}else if(eM===bu){eK.push(cm,this.$$store.theme[name],cv);}else if(eM===co&&eN){eK.push(cs,this.$$store.init[name],ct);}}eK.push(bv);eK.push(bt,this.$$store.user[name],bn);if(eM===cr){if(!eL.inheritable){eK.push(cz,this.$$store.user[name],cv);}eK.push(cu,this.$$store.user[name],ct);}else if(eM===bq){if(!eL.inheritable){eK.push(cz,this.$$store.user[name],cv);}eK.push(cm,this.$$store.user[name],cv);eK.push(cn,this.$$store.runtime[name],bw);eK.push(cu,this.$$store.runtime[name],cv);eK.push(cn,this.$$store.theme[name],bw);eK.push(cu,this.$$store.theme[name],cv);eK.push(bt,this.$$store.init[name],bn);eK.push(cu,this.$$store.init[name],cv);eK.push(cs,this.$$store.useinit[name],cA);eK.push(bv);}else{if(eM===cp){eK.push(cu,this.$$store.runtime[name],ct);}else if(eL.inheritable){eK.push(cu,this.$$store.user[name],cv);}else{eK.push(cF,this.$$store.user[name],cv);}if(eM===cq){eK.push(cs,this.$$store.theme[name],ct);}else if(eM===bu){eK.push(cm,this.$$store.theme[name],cv);}else if(eM===co&&eN){eK.push(cs,this.$$store.init[name],ct);}}eK.push(bv);if(eL.themeable){eK.push(bt,this.$$store.theme[name],bn);if(!eL.inheritable){eK.push(cz,this.$$store.theme[name],cv);}if(eM===cp){eK.push(cu,this.$$store.runtime[name],ct);}else if(eM===cr){eK.push(cu,this.$$store.user[name],ct);}else if(eM===cq){eK.push(cu,this.$$store.theme[name],ct);}else if(eM===bu){eK.push(cm,this.$$store.theme[name],cv);eK.push(cn,this.$$store.init[name],bn);eK.push(cu,this.$$store.init[name],cv);eK.push(cs,this.$$store.useinit[name],cA);eK.push(bv);}else if(eM===co){if(eN){eK.push(cs,this.$$store.init[name],ct);}eK.push(cu,this.$$store.theme[name],cv);}else if(eM===cD){eK.push(cu,this.$$store.theme[name],cv);}eK.push(bv);}eK.push(bt,this.$$store.useinit[name],E);if(!eL.inheritable){eK.push(cz,this.$$store.init[name],cv);}if(eM===co){if(eN){eK.push(cu,this.$$store.init[name],ct);}else{eK.push(cu,this.$$store.init[name],cv);}}else if(eM===cr||eM===cp||eM===cq||eM===cD){eK.push(cm,this.$$store.useinit[name],cv);if(eM===cp){eK.push(cu,this.$$store.runtime[name],ct);}else if(eM===cr){eK.push(cu,this.$$store.user[name],ct);}else if(eM===cq){eK.push(cu,this.$$store.theme[name],ct);}else if(eM===cD){eK.push(cu,this.$$store.init[name],cv);}}eK.push(bv);if(eM===cr||eM===cp||eM===cq||eM===co){eK.push(cQ);if(eM===cp){eK.push(cu,this.$$store.runtime[name],ct);}else if(eM===cr){eK.push(cu,this.$$store.user[name],ct);}else if(eM===cq){eK.push(cu,this.$$store.theme[name],ct);}else if(eM===co){if(eN){eK.push(cu,this.$$store.init[name],ct);}else{eK.push(cu,this.$$store.init[name],cv);}eK.push(cs,this.$$store.useinit[name],cA);}eK.push(bv);}},__lX:function(eO,eP,name,eQ){eO.push(C);if(eQ===cD){eO.push(V);}else{eO.push(bE,this.$$store.inherit[name],cv);}eO.push(bP);eO.push(cs,this.$$store.init[name],bG);eO.push(cs,this.$$store.init[name],bR);eO.push(cu,this.$$store.init[name],cv);eO.push(cs,this.$$store.useinit[name],cA);eO.push(bO);eO.push(cm,this.$$store.useinit[name],bc);eO.push(bv);eO.push(bY);eO.push(N);eO.push(ba,this.$$store.inherit[name],cv);eO.push(bv);eO.push(O);eO.push(cm,this.$$store.inherit[name],cv);eO.push(r,this.$$store.inherit[name],cU);eO.push(bN);if(eP.init!==undefined&&eQ!==co){eO.push(cE,this.$$store.init[name],cy);}else{eO.push(bX);}eO.push(cL);},__lY:function(eR,eS,name,eT){if(eT!==cr&&eT!==cp&&eT!==cq){eR.push(bK);}eR.push(bY);if(eS.init!==undefined&&eT!==co){eR.push(cE,this.$$store.init[name],cy);}else{eR.push(bX);}},__ma:function(eU,eV,name){if(eV.apply){eU.push(cs,eV.apply,H,name,by);}if(eV.event){eU.push(bl,be,eV.event,x,bQ,eV.event,W,y);}},__mb:function(eW,name){eW.push(cT);eW.push(cN,this.$$method.refresh[name],bg,this.$$method.refresh[name],cY);eW.push(bv);}},defer:function(eX){var fa=navigator.userAgent.indexOf(M)!=-1;var eY=navigator.userAgent.indexOf(cg)!=-1;if(fa||eY){eX.__lM=eX.__lN;}}});})();(function(){var q="[Class ",p="]",o="$$init_",n="toString",m="constructor",k="singleton",j=".prototype",h="extend",g="Class",f="destruct",c="qx.Class",e=".",d="static",b="qx.event.type.Data";qx.Bootstrap.define(c,{statics:{define:function(name,r){if(!r){var r={};}if(r.include&&!(r.include instanceof Array)){r.include=[r.include];}if(r.implement&&!(r.implement instanceof Array)){r.implement=[r.implement];}var s=false;if(!r.hasOwnProperty(h)&&!r.type){r.type=d;s=true;}{};var t=this.__bX(name,r.type,r.extend,r.statics,r.construct,r.destruct,r.include);if(r.extend){if(r.properties){this.__ca(t,r.properties,true);}if(r.members){this.__cc(t,r.members,true,true,false);}if(r.events){this.__bY(t,r.events,true);}if(r.include){for(var i=0,l=r.include.length;i<l;i++){this.__cg(t,r.include[i],false);}}}if(r.settings){for(var u in r.settings){qx.core.Setting.define(u,r.settings[u]);}}if(r.variants){for(var u in r.variants){qx.core.Variant.define(u,r.variants[u].allowedValues,r.variants[u].defaultValue);}}if(r.implement){for(var i=0,l=r.implement.length;i<l;i++){this.__ce(t,r.implement[i]);}}{};if(r.defer){r.defer.self=t;r.defer(t,t.prototype,{add:function(name,v){var w={};w[name]=v;qx.Class.__ca(t,w,true);}});}return t;},undefine:function(name){delete this.$$registry[name];var x=name.split(e);var z=[window];for(var i=0;i<x.length;i++){z.push(z[i][x[i]]);}for(var i=z.length-1;i>=1;i--){var y=z[i];var parent=z[i-1];if(qx.Bootstrap.isFunction(y)||qx.Bootstrap.objectGetLength(y)===0){delete parent[x[i-1]];}else{break;}}},isDefined:qx.Bootstrap.classIsDefined,getTotalNumber:function(){return qx.Bootstrap.objectGetLength(this.$$registry);},getByName:qx.Bootstrap.getByName,include:function(A,B){{};qx.Class.__cg(A,B,false);},patch:function(C,D){{};qx.Class.__cg(C,D,true);},isSubClassOf:function(E,F){if(!E){return false;}if(E==F){return true;}if(E.prototype instanceof F){return true;}return false;},getPropertyDefinition:qx.Bootstrap.getPropertyDefinition,getProperties:function(G){var H=[];while(G){if(G.$$properties){H.push.apply(H,qx.Bootstrap.getKeys(G.$$properties));}G=G.superclass;}return H;},getByProperty:function(I,name){while(I){if(I.$$properties&&I.$$properties[name]){return I;}I=I.superclass;}return null;},hasProperty:qx.Bootstrap.hasProperty,getEventType:qx.Bootstrap.getEventType,supportsEvent:qx.Bootstrap.supportsEvent,hasOwnMixin:function(J,K){return J.$$includes&&J.$$includes.indexOf(K)!==-1;},getByMixin:function(L,M){var N,i,l;while(L){if(L.$$includes){N=L.$$flatIncludes;for(i=0,l=N.length;i<l;i++){if(N[i]===M){return L;}}}L=L.superclass;}return null;},getMixins:qx.Bootstrap.getMixins,hasMixin:function(O,P){return !!this.getByMixin(O,P);},hasOwnInterface:function(Q,R){return Q.$$implements&&Q.$$implements.indexOf(R)!==-1;},getByInterface:qx.Bootstrap.getByInterface,getInterfaces:function(S){var T=[];while(S){if(S.$$implements){T.push.apply(T,S.$$flatImplements);}S=S.superclass;}return T;},hasInterface:qx.Bootstrap.hasInterface,implementsInterface:function(U,V){var W=U.constructor;if(this.hasInterface(W,V)){return true;}try{qx.Interface.assertObject(U,V);return true;}catch(X){}try{qx.Interface.assert(W,V,false);return true;}catch(Y){}return false;},getInstance:function(){if(!this.$$instance){this.$$allowconstruct=true;this.$$instance=new this;delete this.$$allowconstruct;}return this.$$instance;},genericToString:function(){return q+this.classname+p;},$$registry:qx.Bootstrap.$$registry,__bT:null,__bU:null,__bV:function(){},__bW:function(){},__bX:function(name,ba,bb,bc,bd,be,bf){var bi;if(!bb&&true){bi=bc||{};qx.Bootstrap.setDisplayNames(bi,name);}else{var bi={};if(bb){if(!bd){bd=this.__ch();}if(this.__cj(bb,bf)){bi=this.__ck(bd,name,ba);}else{bi=bd;}if(ba===k){bi.getInstance=this.getInstance;}qx.Bootstrap.setDisplayName(bd,name,m);}if(bc){qx.Bootstrap.setDisplayNames(bc,name);var bj;for(var i=0,a=qx.Bootstrap.getKeys(bc),l=a.length;i<l;i++){bj=a[i];var bg=bc[bj];{bi[bj]=bg;};}}}var bh=qx.Bootstrap.createNamespace(name,bi);bi.name=bi.classname=name;bi.basename=bh;bi.$$type=g;if(ba){bi.$$classtype=ba;}if(!bi.hasOwnProperty(n)){bi.toString=this.genericToString;}if(bb){qx.Bootstrap.extendClass(bi,bd,bb,name,bh);if(be){{};bi.$$destructor=be;qx.Bootstrap.setDisplayName(be,name,f);}}this.$$registry[name]=bi;return bi;},__bY:function(bk,bl,bm){var bn,bn;{};if(bk.$$events){for(var bn in bl){bk.$$events[bn]=bl[bn];}}else{bk.$$events=bl;}},__ca:function(bo,bp,bq){var br;if(bq===undefined){bq=false;}var bs=bo.prototype;for(var name in bp){br=bp[name];{};br.name=name;if(!br.refine){if(bo.$$properties===undefined){bo.$$properties={};}bo.$$properties[name]=br;}if(br.init!==undefined){bo.prototype[o+name]=br.init;}if(br.event!==undefined){var event={};event[br.event]=b;this.__bY(bo,event,bq);}if(br.inheritable){qx.core.Property.$$inheritable[name]=true;if(!bs.$$refreshInheritables){qx.core.Property.attachRefreshInheritables(bo);}}if(!br.refine){qx.core.Property.attachMethods(bo,name,br);}}},__cb:null,__cc:function(bt,bu,bv,bw,bx){var by=bt.prototype;var bA,bz;qx.Bootstrap.setDisplayNames(bu,bt.classname+j);for(var i=0,a=qx.Bootstrap.getKeys(bu),l=a.length;i<l;i++){bA=a[i];bz=bu[bA];{};if(bw!==false&&bz instanceof Function&&bz.$$type==null){if(bx==true){bz=this.__cd(bz,by[bA]);}else{if(by[bA]){bz.base=by[bA];}bz.self=bt;}{};}by[bA]=bz;}},__cd:function(bB,bC){if(bC){return function(){var bE=bB.base;bB.base=bC;var bD=bB.apply(this,arguments);bB.base=bE;return bD;};}else{return bB;}},__ce:function(bF,bG){{};var bH=qx.Interface.flatten([bG]);if(bF.$$implements){bF.$$implements.push(bG);bF.$$flatImplements.push.apply(bF.$$flatImplements,bH);}else{bF.$$implements=[bG];bF.$$flatImplements=bH;}},__cf:function(bI){var name=bI.classname;var bJ=this.__ck(bI,name,bI.$$classtype);for(var i=0,a=qx.Bootstrap.getKeys(bI),l=a.length;i<l;i++){bK=a[i];bJ[bK]=bI[bK];}bJ.prototype=bI.prototype;var bM=bI.prototype;for(var i=0,a=qx.Bootstrap.getKeys(bM),l=a.length;i<l;i++){bK=a[i];var bN=bM[bK];if(bN&&bN.self==bI){bN.self=bJ;}}for(var bK in this.$$registry){var bL=this.$$registry[bK];if(!bL){continue;}if(bL.base==bI){bL.base=bJ;}if(bL.superclass==bI){bL.superclass=bJ;}if(bL.$$original){if(bL.$$original.base==bI){bL.$$original.base=bJ;}if(bL.$$original.superclass==bI){bL.$$original.superclass=bJ;}}}qx.Bootstrap.createNamespace(name,bJ);this.$$registry[name]=bJ;return bJ;},__cg:function(bO,bP,bQ){{};if(this.hasMixin(bO,bP)){return;}var bT=bO.$$original;if(bP.$$constructor&&!bT){bO=this.__cf(bO);}var bS=qx.Mixin.flatten([bP]);var bR;for(var i=0,l=bS.length;i<l;i++){bR=bS[i];if(bR.$$events){this.__bY(bO,bR.$$events,bQ);}if(bR.$$properties){this.__ca(bO,bR.$$properties,bQ);}if(bR.$$members){this.__cc(bO,bR.$$members,bQ,bQ,bQ);}}if(bO.$$includes){bO.$$includes.push(bP);bO.$$flatIncludes.push.apply(bO.$$flatIncludes,bS);}else{bO.$$includes=[bP];bO.$$flatIncludes=bS;}},__ch:function(){function bU(){bU.base.apply(this,arguments);}return bU;},__ci:function(){return function(){};},__cj:function(bV,bW){{};if(bV&&bV.$$includes){var bX=bV.$$flatIncludes;for(var i=0,l=bX.length;i<l;i++){if(bX[i].$$constructor){return true;}}}if(bW){var bY=qx.Mixin.flatten(bW);for(var i=0,l=bY.length;i<l;i++){if(bY[i].$$constructor){return true;}}}return false;},__ck:function(ca,name,cb){var cc;var cd=function(){var cg=cd;{};var cf=cg.$$original.apply(this,arguments);if(cg.$$includes){var ce=cg.$$flatIncludes;for(var i=0,l=ce.length;i<l;i++){if(ce[i].$$constructor){ce[i].$$constructor.apply(this,arguments);}}}{};return cf;};{};cd.$$original=ca;ca.wrapper=cd;return cd;}},defer:function(){var ch,ci,cj;{};}});})();(function(){var s="gecko",r="1.9.0.0",q=".",p="[object Opera]",o="function",n="[^\\.0-9]",m="525.26",l="",k="mshtml",j="AppleWebKit/",d="unknown",i="9.6.0",g="4.0",c="Gecko",b="opera",f="webkit",e="0.0.0",h="8.0",a="qx.bom.client.Engine";qx.Bootstrap.define(a,{statics:{NAME:"",FULLVERSION:"0.0.0",VERSION:0.0,OPERA:false,WEBKIT:false,GECKO:false,MSHTML:false,UNKNOWN_ENGINE:false,UNKNOWN_VERSION:false,DOCUMENT_MODE:null,__et:function(){var t=d;var x=e;var w=window.navigator.userAgent;var z=false;var v=false;if(window.opera&&Object.prototype.toString.call(window.opera)==p){t=b;this.OPERA=true;if(/Opera[\s\/]([0-9]+)\.([0-9])([0-9]*)/.test(w)){x=RegExp.$1+q+RegExp.$2;if(RegExp.$3!=l){x+=q+RegExp.$3;}}else{v=true;x=i;}}else if(window.navigator.userAgent.indexOf(j)!=-1){t=f;this.WEBKIT=true;if(/AppleWebKit\/([^ ]+)/.test(w)){x=RegExp.$1;var y=RegExp(n).exec(x);if(y){x=x.slice(0,y.index);}}else{v=true;x=m;}}else if(window.controllers&&window.navigator.product===c){t=s;this.GECKO=true;if(/rv\:([^\);]+)(\)|;)/.test(w)){x=RegExp.$1;}else{v=true;x=r;}}else if(window.navigator.cpuClass&&/MSIE\s+([^\);]+)(\)|;)/.test(w)){t=k;x=RegExp.$1;if(document.documentMode){this.DOCUMENT_MODE=document.documentMode;}if(x<8&&/Trident\/([^\);]+)(\)|;)/.test(w)){if(RegExp.$1===g){x=h;}}this.MSHTML=true;}else{var u=window.qxFail;if(u&&typeof u===o){var t=u();if(t.NAME&&t.FULLVERSION){t=t.NAME;this[t.toUpperCase()]=true;x=t.FULLVERSION;}}else{z=true;v=true;x=r;t=s;this.GECKO=true;qx.Bootstrap.warn("Unsupported client: "+w+"! Assumed gecko version 1.9.0.0 (Firefox 3.0).");}}this.UNKNOWN_ENGINE=z;this.UNKNOWN_VERSION=v;this.NAME=t;this.FULLVERSION=x;this.VERSION=parseFloat(x);}},defer:function(A){A.__et();}});})();(function(){var x="off",w="on",u="|",t="default",s="object",r="&",q="qx.aspects",p="qx.mobile.nativescroll",o="qx.mobile.emulatetouch",n="$",e="qx.allowUrlVariants",m="qx.debug",h="qx.client",c="qx.dynlocale",b="webkit",g="qxvariant",f="opera",j=":",a="qx.core.Variant",k="mshtml",d="gecko";qx.Bootstrap.define(a,{statics:{__kX:{},__kY:{},compilerIsSet:function(){return true;},define:function(y,z,A){{};if(!this.__kX[y]){this.__kX[y]={};}else{}this.__kX[y].allowedValues=z;this.__kX[y].defaultValue=A;},get:function(B){var C=this.__kX[B];{};if(C.value!==undefined){return C.value;}return C.defaultValue;},__la:function(){if(window.qxvariants){for(var D in qxvariants){{};if(!this.__kX[D]){this.__kX[D]={};}this.__kX[D].value=qxvariants[D];}window.qxvariants=undefined;try{delete window.qxvariants;}catch(E){}this.__lb(this.__kX);}},__lb:function(){if(qx.core.Setting.get(e)!=true){return;}var F=document.location.search.slice(1).split(r);for(var i=0;i<F.length;i++){var G=F[i].split(j);if(G.length!=3||G[0]!=g){continue;}var H=G[1];if(!this.__kX[H]){this.__kX[H]={};}this.__kX[H].value=decodeURIComponent(G[2]);}},select:function(I,J){{};for(var K in J){if(this.isSet(I,K)){return J[K];}}if(J[t]!==undefined){return J[t];}{};},isSet:function(L,M){var N=L+n+M;if(this.__kY[N]!==undefined){return this.__kY[N];}var P=false;if(M.indexOf(u)<0){P=this.get(L)===M;}else{var O=M.split(u);for(var i=0,l=O.length;i<l;i++){if(this.get(L)===O[i]){P=true;break;}}}this.__kY[N]=P;return P;},__lc:function(v){return typeof v===s&&v!==null&&v instanceof Array;},__ld:function(v){return typeof v===s&&v!==null&&!(v instanceof Array);},__le:function(Q,R){for(var i=0,l=Q.length;i<l;i++){if(Q[i]==R){return true;}}return false;}},defer:function(S){S.define(h,[d,k,f,b],qx.bom.client.Engine.NAME);S.define(m,[w,x],w);S.define(q,[w,x],x);S.define(c,[w,x],w);S.define(o,[w,x],x);S.define(p,[w,x],x);S.__la();}});})();(function(){var d="qx.dom.Node",c="qx.client",b="";qx.Class.define(d,{statics:{ELEMENT:1,ATTRIBUTE:2,TEXT:3,CDATA_SECTION:4,ENTITY_REFERENCE:5,ENTITY:6,PROCESSING_INSTRUCTION:7,COMMENT:8,DOCUMENT:9,DOCUMENT_TYPE:10,DOCUMENT_FRAGMENT:11,NOTATION:12,getDocument:function(e){return e.nodeType===this.DOCUMENT?e:e.ownerDocument||e.document;},getWindow:qx.core.Variant.select(c,{"mshtml":function(f){if(f.nodeType==null){return f;}if(f.nodeType!==this.DOCUMENT){f=f.ownerDocument;}return f.parentWindow;},"default":function(g){if(g.nodeType==null){return g;}if(g.nodeType!==this.DOCUMENT){g=g.ownerDocument;}return g.defaultView;}}),getDocumentElement:function(h){return this.getDocument(h).documentElement;},getBodyElement:function(j){return this.getDocument(j).body;},isNode:function(k){return !!(k&&k.nodeType!=null);},isElement:function(l){return !!(l&&l.nodeType===this.ELEMENT);},isDocument:function(m){return !!(m&&m.nodeType===this.DOCUMENT);},isText:function(n){return !!(n&&n.nodeType===this.TEXT);},isWindow:function(o){return !!(o&&o.history&&o.location&&o.document);},isNodeName:function(p,q){if(!q||!p||!p.nodeName){return false;}return q.toLowerCase()==qx.dom.Node.getName(p);},getName:function(r){if(!r||!r.nodeName){return null;}return r.nodeName.toLowerCase();},getText:function(s){if(!s||!s.nodeType){return null;}switch(s.nodeType){case 1:var i,a=[],t=s.childNodes,length=t.length;for(i=0;i<length;i++){a[i]=this.getText(t[i]);}return a.join(b);case 2:return s.nodeValue;break;case 3:return s.nodeValue;break;}return null;},isBlockNode:function(u){if(!qx.dom.Node.isElement(u)){return false;}u=qx.dom.Node.getName(u);return /^(body|form|textarea|fieldset|ul|ol|dl|dt|dd|li|div|hr|p|h[1-6]|quote|pre|table|thead|tbody|tfoot|tr|td|th|iframe|address|blockquote)$/.test(u);}}});})();(function(){var j="on",i="qx.client",h="gecko",g="function",f="HTMLEvents",d="mousedown",c="qx.bom.Event",b="return;",a="mouseover";qx.Class.define(c,{statics:{addNativeListener:function(k,l,m,n){if(k.addEventListener){k.addEventListener(l,m,!!n);}else if(k.attachEvent){k.attachEvent(j+l,m);}},removeNativeListener:function(o,p,q,r){if(o.removeEventListener){o.removeEventListener(p,q,!!r);}else if(o.detachEvent){try{o.detachEvent(j+p,q);}catch(e){if(e.number!==-2146828218){throw e;}}}},getTarget:function(e){return e.target||e.srcElement;},getRelatedTarget:function(e){if(e.relatedTarget!==undefined){if(qx.core.Variant.isSet(i,h)){try{e.relatedTarget&&e.relatedTarget.nodeType;}catch(e){return null;}}return e.relatedTarget;}else if(e.fromElement!==undefined&&e.type===a){return e.fromElement;}else if(e.toElement!==undefined){return e.toElement;}else{return null;}},preventDefault:function(e){if(e.preventDefault){if(qx.core.Variant.isSet(i,h)&&qx.bom.client.Engine.VERSION>=1.9&&e.type==d&&e.button==2){return;}e.preventDefault();if(qx.core.Variant.isSet(i,h)&&qx.bom.client.Engine.VERSION<1.9){try{e.keyCode=0;}catch(s){}}}else{try{e.keyCode=0;}catch(t){}e.returnValue=false;}},stopPropagation:function(e){if(e.stopPropagation){e.stopPropagation();}else{e.cancelBubble=true;}},fire:function(u,v){if(document.createEvent){var w=document.createEvent(f);w.initEvent(v,true,true);return !u.dispatchEvent(w);}else{var w=document.createEventObject();return u.fireEvent(j+v,w);}},supportsEvent:qx.core.Variant.select(i,{"webkit":function(x,y){return x.hasOwnProperty(j+y);},"default":function(z,A){var B=j+A;var C=(B in z);if(!C){C=typeof z[B]==g;if(!C&&z.setAttribute){z.setAttribute(B,b);C=typeof z[B]==g;z.removeAttribute(B);}}return C;}})}});})();(function(){var r="|bubble",q="|capture",p="|",o="",n="_",m="unload",k="UNKNOWN_",j="__fs",h="c",g="DOM_",c="__ft",f="WIN_",e="QX_",b="qx.event.Manager",a="capture",d="DOCUMENT_";qx.Class.define(b,{extend:Object,construct:function(s,t){this.__fo=s;this.__fp=qx.core.ObjectRegistry.toHashCode(s);this.__fq=t;if(s.qx!==qx){var self=this;qx.bom.Event.addNativeListener(s,m,qx.event.GlobalError.observeMethod(function(){qx.bom.Event.removeNativeListener(s,m,arguments.callee);self.dispose();}));}this.__fr={};this.__fs={};this.__ft={};this.__fu={};},statics:{__fv:0,getNextUniqueId:function(){return (this.__fv++)+o;}},members:{__fq:null,__fr:null,__ft:null,__fw:null,__fs:null,__fu:null,__fo:null,__fp:null,getWindow:function(){return this.__fo;},getWindowId:function(){return this.__fp;},getHandler:function(u){var v=this.__fs[u.classname];if(v){return v;}return this.__fs[u.classname]=new u(this);},getDispatcher:function(w){var x=this.__ft[w.classname];if(x){return x;}return this.__ft[w.classname]=new w(this,this.__fq);},getListeners:function(y,z,A){var B=y.$$hash||qx.core.ObjectRegistry.toHashCode(y);var D=this.__fr[B];if(!D){return null;}var E=z+(A?q:r);var C=D[E];return C?C.concat():null;},serializeListeners:function(F){var M=F.$$hash||qx.core.ObjectRegistry.toHashCode(F);var O=this.__fr[M];var K=[];if(O){var I,N,G,J,L;for(var H in O){I=H.indexOf(p);N=H.substring(0,I);G=H.charAt(I+1)==h;J=O[H];for(var i=0,l=J.length;i<l;i++){L=J[i];K.push({self:L.context,handler:L.handler,type:N,capture:G});}}}return K;},toggleAttachedEvents:function(P,Q){var V=P.$$hash||qx.core.ObjectRegistry.toHashCode(P);var X=this.__fr[V];if(X){var S,W,R,T;for(var U in X){S=U.indexOf(p);W=U.substring(0,S);R=U.charCodeAt(S+1)===99;T=X[U];if(Q){this.__fx(P,W,R);}else{this.__fy(P,W,R);}}}},hasListener:function(Y,ba,bb){{};var bc=Y.$$hash||qx.core.ObjectRegistry.toHashCode(Y);var be=this.__fr[bc];if(!be){return false;}var bf=ba+(bb?q:r);var bd=be[bf];return bd&&bd.length>0;},importListeners:function(bg,bh){{};var bn=bg.$$hash||qx.core.ObjectRegistry.toHashCode(bg);var bo=this.__fr[bn]={};var bk=qx.event.Manager;for(var bi in bh){var bl=bh[bi];var bm=bl.type+(bl.capture?q:r);var bj=bo[bm];if(!bj){bj=bo[bm]=[];this.__fx(bg,bl.type,bl.capture);}bj.push({handler:bl.listener,context:bl.self,unique:bl.unique||(bk.__fv++)+o});}},addListener:function(bp,bq,br,self,bs){var bw;{};var bx=bp.$$hash||qx.core.ObjectRegistry.toHashCode(bp);var bz=this.__fr[bx];if(!bz){bz=this.__fr[bx]={};}var bv=bq+(bs?q:r);var bu=bz[bv];if(!bu){bu=bz[bv]=[];}if(bu.length===0){this.__fx(bp,bq,bs);}var by=(qx.event.Manager.__fv++)+o;var bt={handler:br,context:self,unique:by};bu.push(bt);return bv+p+by;},findHandler:function(bA,bB){var bN=false,bF=false,bO=false,bC=false;var bL;if(bA.nodeType===1){bN=true;bL=g+bA.tagName.toLowerCase()+n+bB;}else if(bA.nodeType===9){bC=true;bL=d+bB;}else if(bA==this.__fo){bF=true;bL=f+bB;}else if(bA.classname){bO=true;bL=e+bA.classname+n+bB;}else{bL=k+bA+n+bB;}var bH=this.__fu;if(bH[bL]){return bH[bL];}var bK=this.__fq.getHandlers();var bG=qx.event.IEventHandler;var bI,bJ,bE,bD;for(var i=0,l=bK.length;i<l;i++){bI=bK[i];bE=bI.SUPPORTED_TYPES;if(bE&&!bE[bB]){continue;}bD=bI.TARGET_CHECK;if(bD){var bM=false;if(bN&&((bD&bG.TARGET_DOMNODE)!=0)){bM=true;}else if(bF&&((bD&bG.TARGET_WINDOW)!=0)){bM=true;}else if(bO&&((bD&bG.TARGET_OBJECT)!=0)){bM=true;}else if(bC&&((bD&bG.TARGET_DOCUMENT)!=0)){bM=true;}if(!bM){continue;}}bJ=this.getHandler(bK[i]);if(bI.IGNORE_CAN_HANDLE||bJ.canHandleEvent(bA,bB)){bH[bL]=bJ;return bJ;}}return null;},__fx:function(bP,bQ,bR){var bS=this.findHandler(bP,bQ);if(bS){bS.registerEvent(bP,bQ,bR);return;}{};},removeListener:function(bT,bU,bV,self,bW){var cb;{};var cc=bT.$$hash||qx.core.ObjectRegistry.toHashCode(bT);var cd=this.__fr[cc];if(!cd){return false;}var bX=bU+(bW?q:r);var bY=cd[bX];if(!bY){return false;}var ca;for(var i=0,l=bY.length;i<l;i++){ca=bY[i];if(ca.handler===bV&&ca.context===self){qx.lang.Array.removeAt(bY,i);if(bY.length==0){this.__fy(bT,bU,bW);}return true;}}return false;},removeListenerById:function(ce,cf){var cl;{};var cj=cf.split(p);var co=cj[0];var cg=cj[1].charCodeAt(0)==99;var cn=cj[2];var cm=ce.$$hash||qx.core.ObjectRegistry.toHashCode(ce);var cp=this.__fr[cm];if(!cp){return false;}var ck=co+(cg?q:r);var ci=cp[ck];if(!ci){return false;}var ch;for(var i=0,l=ci.length;i<l;i++){ch=ci[i];if(ch.unique===cn){qx.lang.Array.removeAt(ci,i);if(ci.length==0){this.__fy(ce,co,cg);}return true;}}return false;},removeAllListeners:function(cq){var cu=cq.$$hash||qx.core.ObjectRegistry.toHashCode(cq);var cw=this.__fr[cu];if(!cw){return false;}var cs,cv,cr;for(var ct in cw){if(cw[ct].length>0){cs=ct.split(p);cv=cs[0];cr=cs[1]===a;this.__fy(cq,cv,cr);}}delete this.__fr[cu];return true;},deleteAllListeners:function(cx){delete this.__fr[cx];},__fy:function(cy,cz,cA){var cB=this.findHandler(cy,cz);if(cB){cB.unregisterEvent(cy,cz,cA);return;}{};},dispatchEvent:function(cC,event){var cH;{};var cI=event.getType();if(!event.getBubbles()&&!this.hasListener(cC,cI)){qx.event.Pool.getInstance().poolObject(event);return true;}if(!event.getTarget()){event.setTarget(cC);}var cG=this.__fq.getDispatchers();var cF;var cE=false;for(var i=0,l=cG.length;i<l;i++){cF=this.getDispatcher(cG[i]);if(cF.canDispatchEvent(cC,event,cI)){cF.dispatchEvent(cC,event,cI);cE=true;break;}}if(!cE){{};return true;}var cD=event.getDefaultPrevented();qx.event.Pool.getInstance().poolObject(event);return !cD;},dispose:function(){this.__fq.removeManager(this);qx.util.DisposeUtil.disposeMap(this,j);qx.util.DisposeUtil.disposeMap(this,c);this.__fr=this.__fo=this.__fw=null;this.__fq=this.__fu=null;}}});})();(function(){var g="mshtml",f="qx.client",e="[object Array]",d="qx.lang.Array",c="qx",b="number",a="string";qx.Class.define(d,{statics:{toArray:function(h,j){return this.cast(h,Array,j);},cast:function(k,m,n){if(k.constructor===m){return k;}if(qx.Class.hasInterface(k,qx.data.IListData)){var k=k.toArray();}var o=new m;if(qx.core.Variant.isSet(f,g)){if(k.item){for(var i=n||0,l=k.length;i<l;i++){o.push(k[i]);}return o;}}if(Object.prototype.toString.call(k)===e&&n==null){o.push.apply(o,k);}else{o.push.apply(o,Array.prototype.slice.call(k,n||0));}return o;},fromArguments:function(p,q){return Array.prototype.slice.call(p,q||0);},fromCollection:function(r){if(qx.core.Variant.isSet(f,g)){if(r.item){var s=[];for(var i=0,l=r.length;i<l;i++){s[i]=r[i];}return s;}}return Array.prototype.slice.call(r,0);},fromShortHand:function(t){var v=t.length;var u=qx.lang.Array.clone(t);switch(v){case 1:u[1]=u[2]=u[3]=u[0];break;case 2:u[2]=u[0];case 3:u[3]=u[1];}return u;},clone:function(w){return w.concat();},insertAt:function(x,y,i){x.splice(i,0,y);return x;},insertBefore:function(z,A,B){var i=z.indexOf(B);if(i==-1){z.push(A);}else{z.splice(i,0,A);}return z;},insertAfter:function(C,D,E){var i=C.indexOf(E);if(i==-1||i==(C.length-1)){C.push(D);}else{C.splice(i+1,0,D);}return C;},removeAt:function(F,i){return F.splice(i,1)[0];},removeAll:function(G){G.length=0;return this;},append:function(H,I){{};Array.prototype.push.apply(H,I);return H;},exclude:function(J,K){{};for(var i=0,M=K.length,L;i<M;i++){L=J.indexOf(K[i]);if(L!=-1){J.splice(L,1);}}return J;},remove:function(N,O){var i=N.indexOf(O);if(i!=-1){N.splice(i,1);return O;}},contains:function(P,Q){return P.indexOf(Q)!==-1;},equals:function(R,S){var length=R.length;if(length!==S.length){return false;}for(var i=0;i<length;i++){if(R[i]!==S[i]){return false;}}return true;},sum:function(T){var U=0;for(var i=0,l=T.length;i<l;i++){U+=T[i];}return U;},max:function(V){{};var i,X=V.length,W=V[0];for(i=1;i<X;i++){if(V[i]>W){W=V[i];}}return W===undefined?null:W;},min:function(Y){{};var i,bb=Y.length,ba=Y[0];for(i=1;i<bb;i++){if(Y[i]<ba){ba=Y[i];}}return ba===undefined?null:ba;},unique:function(bc){var bm=[],be={},bh={},bj={};var bi,bd=0;var bn=c+qx.lang.Date.now();var bf=false,bl=false,bo=false;for(var i=0,bk=bc.length;i<bk;i++){bi=bc[i];if(bi===null){if(!bf){bf=true;bm.push(bi);}}else if(bi===undefined){}else if(bi===false){if(!bl){bl=true;bm.push(bi);}}else if(bi===true){if(!bo){bo=true;bm.push(bi);}}else if(typeof bi===a){if(!be[bi]){be[bi]=1;bm.push(bi);}}else if(typeof bi===b){if(!bh[bi]){bh[bi]=1;bm.push(bi);}}else{bg=bi[bn];if(bg==null){bg=bi[bn]=bd++;}if(!bj[bg]){bj[bg]=bi;bm.push(bi);}}}for(var bg in bj){try{delete bj[bg][bn];}catch(bp){try{bj[bg][bn]=null;}catch(bq){throw new Error("Cannot clean-up map entry doneObjects["+bg+"]["+bn+"]");}}}return bm;}}});})();(function(){var f="()",e=".",d=".prototype.",c='anonymous()',b="qx.lang.Function",a=".constructor()";qx.Class.define(b,{statics:{getCaller:function(g){return g.caller?g.caller.callee:g.callee.caller;},getName:function(h){if(h.displayName){return h.displayName;}if(h.$$original||h.wrapper||h.classname){return h.classname+a;}if(h.$$mixin){for(var j in h.$$mixin.$$members){if(h.$$mixin.$$members[j]==h){return h.$$mixin.name+d+j+f;}}for(var j in h.$$mixin){if(h.$$mixin[j]==h){return h.$$mixin.name+e+j+f;}}}if(h.self){var k=h.self.constructor;if(k){for(var j in k.prototype){if(k.prototype[j]==h){return k.classname+d+j+f;}}for(var j in k){if(k[j]==h){return k.classname+e+j+f;}}}}var i=h.toString().match(/function\s*(\w*)\s*\(.*/);if(i&&i.length>=1&&i[1]){return i[1]+f;}return c;},globalEval:function(l){if(window.execScript){return window.execScript(l);}else{return eval.call(window,l);}},empty:function(){},returnTrue:function(){return true;},returnFalse:function(){return false;},returnNull:function(){return null;},returnThis:function(){return this;},returnZero:function(){return 0;},create:function(m,n){{};if(!n){return m;}if(!(n.self||n.args||n.delay!=null||n.periodical!=null||n.attempt)){return m;}return function(event){{};var p=qx.lang.Array.fromArguments(arguments);if(n.args){p=n.args.concat(p);}if(n.delay||n.periodical){var o=qx.event.GlobalError.observeMethod(function(){return m.apply(n.self||this,p);});if(n.delay){return window.setTimeout(o,n.delay);}if(n.periodical){return window.setInterval(o,n.periodical);}}else if(n.attempt){var q=false;try{q=m.apply(n.self||this,p);}catch(r){}return q;}else{return m.apply(n.self||this,p);}};},bind:function(s,self,t){return this.create(s,{self:self,args:arguments.length>2?qx.lang.Array.fromArguments(arguments,2):null});},curry:function(u,v){return this.create(u,{args:arguments.length>1?qx.lang.Array.fromArguments(arguments,1):null});},listener:function(w,self,x){if(arguments.length<3){return function(event){return w.call(self||this,event||window.event);};}else{var y=qx.lang.Array.fromArguments(arguments,2);return function(event){var z=[event||window.event];z.push.apply(z,y);w.apply(self||this,z);};}},attempt:function(A,self,B){return this.create(A,{self:self,attempt:true,args:arguments.length>2?qx.lang.Array.fromArguments(arguments,2):null})();},delay:function(C,D,self,E){return this.create(C,{delay:D,self:self,args:arguments.length>3?qx.lang.Array.fromArguments(arguments,3):null})();},periodical:function(F,G,self,H){return this.create(F,{periodical:G,self:self,args:arguments.length>3?qx.lang.Array.fromArguments(arguments,3):null})();}}});})();(function(){var c="qx.event.Registration";qx.Class.define(c,{statics:{__fc:{},getManager:function(d){if(d==null){{};d=window;}else if(d.nodeType){d=qx.dom.Node.getWindow(d);}else if(!qx.dom.Node.isWindow(d)){d=window;}var f=d.$$hash||qx.core.ObjectRegistry.toHashCode(d);var e=this.__fc[f];if(!e){e=new qx.event.Manager(d,this);this.__fc[f]=e;}return e;},removeManager:function(g){var h=g.getWindowId();delete this.__fc[h];},addListener:function(i,j,k,self,l){return this.getManager(i).addListener(i,j,k,self,l);},removeListener:function(m,n,o,self,p){return this.getManager(m).removeListener(m,n,o,self,p);},removeListenerById:function(q,r){return this.getManager(q).removeListenerById(q,r);},removeAllListeners:function(s){return this.getManager(s).removeAllListeners(s);},deleteAllListeners:function(t){var u=t.$$hash;if(u){this.getManager(t).deleteAllListeners(u);}},hasListener:function(v,w,x){return this.getManager(v).hasListener(v,w,x);},serializeListeners:function(y){return this.getManager(y).serializeListeners(y);},createEvent:function(z,A,B){{};if(A==null){A=qx.event.type.Event;}var C=qx.event.Pool.getInstance().getObject(A);B?C.init.apply(C,B):C.init();if(z){C.setType(z);}return C;},dispatchEvent:function(D,event){return this.getManager(D).dispatchEvent(D,event);},fireEvent:function(E,F,G,H){var I;{};var J=this.createEvent(F,G||null,H);return this.getManager(E).dispatchEvent(E,J);},fireNonBubblingEvent:function(K,L,M,N){{};var O=this.getManager(K);if(!O.hasListener(K,L,false)){return true;}var P=this.createEvent(L,M||null,N);return O.dispatchEvent(K,P);},PRIORITY_FIRST:-32000,PRIORITY_NORMAL:0,PRIORITY_LAST:32000,__fd:[],addHandler:function(Q){{};this.__fd.push(Q);this.__fd.sort(function(a,b){return a.PRIORITY-b.PRIORITY;});},getHandlers:function(){return this.__fd;},__fe:[],addDispatcher:function(R,S){{};this.__fe.push(R);this.__fe.sort(function(a,b){return a.PRIORITY-b.PRIORITY;});},getDispatchers:function(){return this.__fe;}}});})();(function(){var e="$$hash",d="",c="qx.core.ObjectRegistry";qx.Class.define(c,{statics:{inShutDown:false,__cM:{},__cN:0,__cO:[],register:function(f){var j=this.__cM;if(!j){return;}var h=f.$$hash;if(h==null){var g=this.__cO;if(g.length>0){h=g.pop();}else{h=(this.__cN++)+d;}f.$$hash=h;}{};j[h]=f;},unregister:function(k){var m=k.$$hash;if(m==null){return;}var n=this.__cM;if(n&&n[m]){delete n[m];this.__cO.push(m);}try{delete k.$$hash;}catch(o){if(k.removeAttribute){k.removeAttribute(e);}}},toHashCode:function(p){{};var r=p.$$hash;if(r!=null){return r;}var q=this.__cO;if(q.length>0){r=q.pop();}else{r=(this.__cN++)+d;}return p.$$hash=r;},clearHashCode:function(s){{};var t=s.$$hash;if(t!=null){this.__cO.push(t);try{delete s.$$hash;}catch(u){if(s.removeAttribute){s.removeAttribute(e);}}}},fromHashCode:function(v){return this.__cM[v]||null;},shutdown:function(){this.inShutDown=true;var x=this.__cM;var z=[];for(var y in x){z.push(y);}z.sort(function(a,b){return parseInt(b,10)-parseInt(a,10);});var w,i=0,l=z.length;while(true){try{for(;i<l;i++){y=z[i];w=x[y];if(w&&w.dispose){w.dispose();}}}catch(A){qx.Bootstrap.error(this,"Could not dispose object "+w.toString()+": "+A);if(i!==l){i++;continue;}}break;}qx.Bootstrap.debug(this,"Disposed "+l+" objects");delete this.__cM;},getRegistry:function(){return this.__cM;}}});})();(function(){var a="qx.data.MBinding";qx.Mixin.define(a,{members:{bind:function(b,c,d,e){return qx.data.SingleValueBinding.bind(this,b,c,d,e);},removeBinding:function(f){qx.data.SingleValueBinding.removeBindingFromObject(this,f);},removeAllBindings:function(){qx.data.SingleValueBinding.removeAllBindingsForObject(this);},getBindings:function(){return qx.data.SingleValueBinding.getAllBindingsForObject(this);}}});})();(function(){var a="qx.lang.RingBuffer";qx.Class.define(a,{extend:Object,construct:function(b){this.setMaxEntries(b||50);},members:{__iq:0,__ir:0,__is:false,__it:0,__iu:null,__iv:null,setMaxEntries:function(c){this.__iv=c;this.clear();},getMaxEntries:function(){return this.__iv;},addEntry:function(d){this.__iu[this.__iq]=d;this.__iq=this.__iw(this.__iq,1);var e=this.getMaxEntries();if(this.__ir<e){this.__ir++;}if(this.__is&&(this.__it<e)){this.__it++;}},mark:function(){this.__is=true;this.__it=0;},clearMark:function(){this.__is=false;},getAllEntries:function(){return this.getEntries(this.getMaxEntries(),false);},getEntries:function(f,g){if(f>this.__ir){f=this.__ir;}if(g&&this.__is&&(f>this.__it)){f=this.__it;}if(f>0){var i=this.__iw(this.__iq,-1);var h=this.__iw(i,-f+1);var j;if(h<=i){j=this.__iu.slice(h,i+1);}else{j=this.__iu.slice(h,this.__ir).concat(this.__iu.slice(0,i+1));}}else{j=[];}return j;},clear:function(){this.__iu=new Array(this.getMaxEntries());this.__ir=0;this.__it=0;this.__iq=0;},__iw:function(k,l){var m=this.getMaxEntries();var n=(k+l)%m;if(n<0){n+=m;}return n;}}});})();(function(){var a="qx.log.appender.RingBuffer";qx.Class.define(a,{extend:qx.lang.RingBuffer,construct:function(b){this.setMaxMessages(b||50);},members:{setMaxMessages:function(c){this.setMaxEntries(c);},getMaxMessages:function(){return this.getMaxEntries();},process:function(d){this.addEntry(d);},getAllLogEvents:function(){return this.getAllEntries();},retrieveLogEvents:function(e,f){return this.getEntries(e,f);},clearHistory:function(){this.clear();}}});})();(function(){var j=":",h="qx.client",g="anonymous",f="...",e="qx.dev.StackTrace",d="",c="\n",b="/source/class/",a=".";qx.Class.define(e,{statics:{getStackTrace:qx.core.Variant.select(h,{"gecko":function(){try{throw new Error();}catch(x){var r=this.getStackTraceFromError(x);qx.lang.Array.removeAt(r,0);var p=this.getStackTraceFromCaller(arguments);var n=p.length>r.length?p:r;for(var i=0;i<Math.min(p.length,r.length);i++){var o=p[i];if(o.indexOf(g)>=0){continue;}var v=o.split(j);if(v.length!=2){continue;}var t=v[0];var m=v[1];var l=r[i];var w=l.split(j);var s=w[0];var k=w[1];if(qx.Class.getByName(s)){var q=s;}else{q=t;}var u=q+j;if(m){u+=m+j;}u+=k;n[i]=u;}return n;}},"mshtml|webkit":function(){return this.getStackTraceFromCaller(arguments);},"opera":function(){var y;try{y.bar();}catch(A){var z=this.getStackTraceFromError(A);qx.lang.Array.removeAt(z,0);return z;}return [];}}),getStackTraceFromCaller:qx.core.Variant.select(h,{"opera":function(B){return [];},"default":function(C){var H=[];var G=qx.lang.Function.getCaller(C);var D={};while(G){var E=qx.lang.Function.getName(G);H.push(E);try{G=G.caller;}catch(I){break;}if(!G){break;}var F=qx.core.ObjectRegistry.toHashCode(G);if(D[F]){H.push(f);break;}D[F]=G;}return H;}}),getStackTraceFromError:qx.core.Variant.select(h,{"gecko":function(J){if(!J.stack){return [];}var P=/@(.+):(\d+)$/gm;var K;var L=[];while((K=P.exec(J.stack))!=null){var M=K[1];var O=K[2];var N=this.__kR(M);L.push(N+j+O);}return L;},"webkit":function(Q){if(Q.sourceURL&&Q.line){return [this.__kR(Q.sourceURL)+j+Q.line];}else{return [];}},"opera":function(R){if(R.message.indexOf("Backtrace:")<0){return [];}var T=[];var U=qx.lang.String.trim(R.message.split("Backtrace:")[1]);var V=U.split(c);for(var i=0;i<V.length;i++){var S=V[i].match(/\s*Line ([0-9]+) of.* (\S.*)/);if(S&&S.length>=2){var X=S[1];var W=this.__kR(S[2]);T.push(W+j+X);}}return T;},"default":function(){return [];}}),__kR:function(Y){var bc=b;var ba=Y.indexOf(bc);var bb=(ba==-1)?Y:Y.substring(ba+bc.length).replace(/\//g,a).replace(/\.js$/,d);return bb;}}});})();(function(){var k="",j="g",h="0",g='\\$1',f="%",e='-',d="qx.lang.String",c=' ',b='\n',a="undefined";qx.Class.define(d,{statics:{camelCase:function(l){return l.replace(/\-([a-z])/g,function(m,n){return n.toUpperCase();});},hyphenate:function(o){return o.replace(/[A-Z]/g,function(p){return (e+p.charAt(0).toLowerCase());});},capitalize:function(q){return q.replace(/\b[a-z]/g,function(r){return r.toUpperCase();});},clean:function(s){return this.trim(s.replace(/\s+/g,c));},trimLeft:function(t){return t.replace(/^\s+/,k);},trimRight:function(u){return u.replace(/\s+$/,k);},trim:function(v){return v.replace(/^\s+|\s+$/g,k);},startsWith:function(w,x){return w.indexOf(x)===0;},endsWith:function(y,z){return y.substring(y.length-z.length,y.length)===z;},repeat:function(A,B){return A.length>0?new Array(B+1).join(A):k;},pad:function(C,length,D){var E=length-C.length;if(E>0){if(typeof D===a){D=h;}return this.repeat(D,E)+C;}else{return C;}},firstUp:qx.Bootstrap.firstUp,firstLow:qx.Bootstrap.firstLow,contains:function(F,G){return F.indexOf(G)!=-1;},format:function(H,I){var J=H;for(var i=0;i<I.length;i++){J=J.replace(new RegExp(f+(i+1),j),I[i]+k);}return J;},escapeRegexpChars:function(K){return K.replace(/([.*+?^${}()|[\]\/\\])/g,g);},toArray:function(L){return L.split(/\B|\b/g);},stripTags:function(M){return M.replace(/<\/?[^>]+>/gi,k);},stripScripts:function(N,O){var Q=k;var P=N.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(){Q+=arguments[1]+b;return k;});if(O===true){qx.lang.Function.globalEval(Q);}return P;}}});})();(function(){var k="node",j="error",h="...(+",g="array",f=")",e="info",d="instance",c="string",b="null",a="class",H="number",G="stringify",F="]",E="date",D="unknown",C="function",B="boolean",A="debug",z="map",y="undefined",s="qx.log.Logger",t="[",q="#",r="warn",o="document",p="{...(",m="text[",n="[...(",u="\n",v=")}",x=")]",w="object";qx.Class.define(s,{statics:{__ff:A,setLevel:function(I){this.__ff=I;},getLevel:function(){return this.__ff;},setTreshold:function(J){this.__fi.setMaxMessages(J);},getTreshold:function(){return this.__fi.getMaxMessages();},__fg:{},__fh:0,register:function(K){if(K.$$id){return;}var M=this.__fh++;this.__fg[M]=K;K.$$id=M;var L=this.__fj;var N=this.__fi.getAllLogEvents();for(var i=0,l=N.length;i<l;i++){if(L[N[i].level]>=L[this.__ff]){K.process(N[i]);}}},unregister:function(O){var P=O.$$id;if(P==null){return;}delete this.__fg[P];delete O.$$id;},debug:function(Q,R){qx.log.Logger.__fk(A,arguments);},info:function(S,T){qx.log.Logger.__fk(e,arguments);},warn:function(U,V){qx.log.Logger.__fk(r,arguments);},error:function(W,X){qx.log.Logger.__fk(j,arguments);},trace:function(Y){qx.log.Logger.__fk(e,[Y,qx.dev.StackTrace.getStackTrace().join(u)]);},deprecatedMethodWarning:function(ba,bb){var bc;{};},deprecatedClassWarning:function(bd,be){var bf;{};},deprecatedEventWarning:function(bg,event,bh){var bi;{};},deprecatedMixinWarning:function(bj,bk){var bl;{};},deprecatedConstantWarning:function(bm,bn,bo){var self,bp;{};},deprecateMethodOverriding:function(bq,br,bs,bt){var bu;{};},clear:function(){this.__fi.clearHistory();},__fi:new qx.log.appender.RingBuffer(50),__fj:{debug:0,info:1,warn:2,error:3},__fk:function(bv,bw){var bB=this.__fj;if(bB[bv]<bB[this.__ff]){return;}var by=bw.length<2?null:bw[0];var bA=by?1:0;var bx=[];for(var i=bA,l=bw.length;i<l;i++){bx.push(this.__fm(bw[i],true));}var bC=new Date;var bD={time:bC,offset:bC-qx.Bootstrap.LOADSTART,level:bv,items:bx,win:window};if(by){if(by.$$hash!==undefined){bD.object=by.$$hash;}else if(by.$$type){bD.clazz=by;}}this.__fi.process(bD);var bE=this.__fg;for(var bz in bE){bE[bz].process(bD);}},__fl:function(bF){if(bF===undefined){return y;}else if(bF===null){return b;}if(bF.$$type){return a;}var bG=typeof bF;if(bG===C||bG==c||bG===H||bG===B){return bG;}else if(bG===w){if(bF.nodeType){return k;}else if(bF.classname){return d;}else if(bF instanceof Array){return g;}else if(bF instanceof Error){return j;}else if(bF instanceof Date){return E;}else{return z;}}if(bF.toString){return G;}return D;},__fm:function(bH,bI){var bP=this.__fl(bH);var bL=D;var bK=[];switch(bP){case b:case y:bL=bP;break;case c:case H:case B:case E:bL=bH;break;case k:if(bH.nodeType===9){bL=o;}else if(bH.nodeType===3){bL=m+bH.nodeValue+F;}else if(bH.nodeType===1){bL=bH.nodeName.toLowerCase();if(bH.id){bL+=q+bH.id;}}else{bL=k;}break;case C:bL=qx.lang.Function.getName(bH)||bP;break;case d:bL=bH.basename+t+bH.$$hash+F;break;case a:case G:bL=bH.toString();break;case j:bK=qx.dev.StackTrace.getStackTraceFromError(bH);bL=bH.toString();break;case g:if(bI){bL=[];for(var i=0,l=bH.length;i<l;i++){if(bL.length>20){bL.push(h+(l-i)+f);break;}bL.push(this.__fm(bH[i],false));}}else{bL=n+bH.length+x;}break;case z:if(bI){var bJ;var bO=[];for(var bN in bH){bO.push(bN);}bO.sort();bL=[];for(var i=0,l=bO.length;i<l;i++){if(bL.length>20){bL.push(h+(l-i)+f);break;}bN=bO[i];bJ=this.__fm(bH[bN],false);bJ.key=bN;bL.push(bJ);}}else{var bM=0;for(var bN in bH){bM++;}bL=p+bM+v;}break;}return {type:bP,text:bL,trace:bK};}},defer:function(bQ){var bR=qx.Bootstrap.$$logs;for(var i=0;i<bR.length;i++){bQ.__fk(bR[i][0],bR[i][1]);}qx.Bootstrap.debug=bQ.debug;qx.Bootstrap.info=bQ.info;qx.Bootstrap.warn=bQ.warn;qx.Bootstrap.error=bQ.error;qx.Bootstrap.trace=bQ.trace;}});})();(function(){var q="set",p="get",o="reset",n="MSIE 6.0",m="info",k="qx.core.Object",j="error",h="warn",g="]",f="debug",b="[",d="$$user_",c="rv:1.8.1",a="Object";qx.Class.define(k,{extend:Object,include:[qx.data.MBinding],construct:function(){qx.core.ObjectRegistry.register(this);},statics:{$$type:a},members:{toHashCode:function(){return this.$$hash;},toString:function(){return this.classname+b+this.$$hash+g;},base:function(r,s){{};if(arguments.length===1){return r.callee.base.call(this);}else{return r.callee.base.apply(this,Array.prototype.slice.call(arguments,1));}},self:function(t){return t.callee.self;},clone:function(){var v=this.constructor;var u=new v;var x=qx.Class.getProperties(v);var w=qx.core.Property.$$store.user;var y=qx.core.Property.$$method.set;var name;for(var i=0,l=x.length;i<l;i++){name=x[i];if(this.hasOwnProperty(w[name])){u[y[name]](this[w[name]]);}}return u;},set:function(z,A){var C=qx.core.Property.$$method.set;if(qx.Bootstrap.isString(z)){if(!this[C[z]]){if(this[q+qx.Bootstrap.firstUp(z)]!=undefined){this[q+qx.Bootstrap.firstUp(z)](A);return this;}{};}return this[C[z]](A);}else{for(var B in z){if(!this[C[B]]){if(this[q+qx.Bootstrap.firstUp(B)]!=undefined){this[q+qx.Bootstrap.firstUp(B)](z[B]);continue;}{};}this[C[B]](z[B]);}return this;}},get:function(D){var E=qx.core.Property.$$method.get;if(!this[E[D]]){if(this[p+qx.Bootstrap.firstUp(D)]!=undefined){return this[p+qx.Bootstrap.firstUp(D)]();}{};}return this[E[D]]();},reset:function(F){var G=qx.core.Property.$$method.reset;if(!this[G[F]]){if(this[o+qx.Bootstrap.firstUp(F)]!=undefined){this[o+qx.Bootstrap.firstUp(F)]();return;}{};}this[G[F]]();},__lw:qx.event.Registration,addListener:function(H,I,self,J){if(!this.$$disposed){return this.__lw.addListener(this,H,I,self,J);}return null;},addListenerOnce:function(K,L,self,M){var N=function(e){this.removeListener(K,N,this,M);L.call(self||this,e);};return this.addListener(K,N,this,M);},removeListener:function(O,P,self,Q){if(!this.$$disposed){return this.__lw.removeListener(this,O,P,self,Q);}return false;},removeListenerById:function(R){if(!this.$$disposed){return this.__lw.removeListenerById(this,R);}return false;},hasListener:function(S,T){return this.__lw.hasListener(this,S,T);},dispatchEvent:function(U){if(!this.$$disposed){return this.__lw.dispatchEvent(this,U);}return true;},fireEvent:function(V,W,X){if(!this.$$disposed){return this.__lw.fireEvent(this,V,W,X);}return true;},fireNonBubblingEvent:function(Y,ba,bb){if(!this.$$disposed){return this.__lw.fireNonBubblingEvent(this,Y,ba,bb);}return true;},fireDataEvent:function(bc,bd,be,bf){if(!this.$$disposed){if(be===undefined){be=null;}return this.__lw.fireNonBubblingEvent(this,bc,qx.event.type.Data,[bd,be,!!bf]);}return true;},__lx:null,setUserData:function(bg,bh){if(!this.__lx){this.__lx={};}this.__lx[bg]=bh;},getUserData:function(bi){if(!this.__lx){return null;}var bj=this.__lx[bi];return bj===undefined?null:bj;},__ly:qx.log.Logger,debug:function(bk){this.__lz(f,arguments);},info:function(bl){this.__lz(m,arguments);},warn:function(bm){this.__lz(h,arguments);},error:function(bn){this.__lz(j,arguments);},trace:function(){this.__ly.trace(this);},__lz:function(bo,bp){var bq=qx.lang.Array.fromArguments(bp);bq.unshift(this);this.__ly[bo].apply(this.__ly,bq);},isDisposed:function(){return this.$$disposed||false;},dispose:function(){var bv,bt,bs,bw;if(this.$$disposed){return;}this.$$disposed=true;this.$$instance=null;this.$$allowconstruct=null;{};var bu=this.constructor;var br;while(bu.superclass){if(bu.$$destructor){bu.$$destructor.call(this);}if(bu.$$includes){br=bu.$$flatIncludes;for(var i=0,l=br.length;i<l;i++){if(br[i].$$destructor){br[i].$$destructor.call(this);}}}bu=bu.superclass;}if(this.__lA){this.__lA();}{};},__lA:null,__lB:function(){var bx=qx.Class.getProperties(this.constructor);for(var i=0,l=bx.length;i<l;i++){delete this[d+bx[i]];}},_disposeObjects:function(by){qx.util.DisposeUtil.disposeObjects(this,arguments);},_disposeSingletonObjects:function(bz){qx.util.DisposeUtil.disposeObjects(this,arguments,true);},_disposeArray:function(bA){qx.util.DisposeUtil.disposeArray(this,bA);},_disposeMap:function(bB){qx.util.DisposeUtil.disposeMap(this,bB);}},settings:{"qx.disposerDebugLevel":0},defer:function(bC,bD){{};var bF=navigator.userAgent.indexOf(n)!=-1;var bE=navigator.userAgent.indexOf(c)!=-1;if(bF||bE){bD.__lA=bD.__lB;}},destruct:function(){if(!qx.core.ObjectRegistry.inShutDown){qx.event.Registration.removeAllListeners(this);}else{qx.event.Registration.deleteAllListeners(this);}qx.core.ObjectRegistry.unregister(this);this.__lx=null;var bI=this.constructor;var bM;var bN=qx.core.Property.$$store;var bK=bN.user;var bL=bN.theme;var bG=bN.inherit;var bJ=bN.useinit;var bH=bN.init;while(bI){bM=bI.$$properties;if(bM){for(var name in bM){if(bM[name].dereference){this[bK[name]]=this[bL[name]]=this[bG[name]]=this[bJ[name]]=this[bH[name]]=undefined;}}}bI=bI.superclass;}}});})();(function(){var f="changeSelection",e="qx.event.type.Data",d="tabView",c="apiviewer.TabViewController",b="classLinkClicked",a="itemName";qx.Class.define(c,{extend:qx.core.Object,construct:function(g){qx.core.Object.call(this);apiviewer.TabViewController.instance=this;this._tabView=g.getWidgetById(d);this._tabView.addListener(f,this.__Sm,this);},events:{"classLinkClicked":e,"changeSelection":e},members:{showTabView:function(){this._tabView.show();},onSelectItem:function(h){this.fireDataEvent(b,h);},showItem:function(i){qx.ui.core.queue.Manager.flush();var j=this._tabView.getSelection()[0];j.setUserData(a,i);return j.getChildren()[0].showItem(i);},openPackage:function(k,l){this.__Sj(k,apiviewer.ui.tabview.PackagePage,l);},openClass:function(m,n){this.__Sj(m,apiviewer.ui.tabview.ClassPage,n);},__Sj:function(o,p,q){var r=this._tabView.getSelection()[0];if(q==true||r==null){this.__Sk(p,o);}else{if(r instanceof p){r.setClassNode(o);}else{this.__Sk(p,o);this.__Sl(r);}}},__Sk:function(s,t){var u=new s(t);this._tabView.add(u);this._tabView.setSelection([u]);},__Sl:function(v){this._tabView.remove(v);v.destroy();},__Sm:function(event){var w=event.getOldData();var x=event.getData();this.fireDataEvent(f,x,w);},__Sn:function(y,z){var A=new qx.event.type.Mouse();A.init(y,z,null,true,true);A.stop();return A;}},destruct:function(){this._tabView.destroy();this._tabView=null;}});})();(function(){var a="qx.event.type.Event";qx.Class.define(a,{extend:qx.core.Object,statics:{CAPTURING_PHASE:1,AT_TARGET:2,BUBBLING_PHASE:3},members:{init:function(b,c){{};this._type=null;this._target=null;this._currentTarget=null;this._relatedTarget=null;this._originalTarget=null;this._stopPropagation=false;this._preventDefault=false;this._bubbles=!!b;this._cancelable=!!c;this._timeStamp=(new Date()).getTime();this._eventPhase=null;return this;},clone:function(d){if(d){var e=d;}else{var e=qx.event.Pool.getInstance().getObject(this.constructor);}e._type=this._type;e._target=this._target;e._currentTarget=this._currentTarget;e._relatedTarget=this._relatedTarget;e._originalTarget=this._originalTarget;e._stopPropagation=this._stopPropagation;e._bubbles=this._bubbles;e._preventDefault=this._preventDefault;e._cancelable=this._cancelable;return e;},stop:function(){if(this._bubbles){this.stopPropagation();}if(this._cancelable){this.preventDefault();}},stopPropagation:function(){{};this._stopPropagation=true;},getPropagationStopped:function(){return !!this._stopPropagation;},preventDefault:function(){{};this._preventDefault=true;},getDefaultPrevented:function(){return !!this._preventDefault;},getType:function(){return this._type;},setType:function(f){this._type=f;},getEventPhase:function(){return this._eventPhase;},setEventPhase:function(g){this._eventPhase=g;},getTimeStamp:function(){return this._timeStamp;},getTarget:function(){return this._target;},setTarget:function(h){this._target=h;},getCurrentTarget:function(){return this._currentTarget||this._target;},setCurrentTarget:function(i){this._currentTarget=i;},getRelatedTarget:function(){return this._relatedTarget;},setRelatedTarget:function(j){this._relatedTarget=j;},getOriginalTarget:function(){return this._originalTarget;},setOriginalTarget:function(k){this._originalTarget=k;},getBubbles:function(){return this._bubbles;},setBubbles:function(l){this._bubbles=l;},isCancelable:function(){return this._cancelable;},setCancelable:function(m){this._cancelable=m;}},destruct:function(){this._target=this._currentTarget=this._relatedTarget=this._originalTarget=null;}});})();(function(){var a="qx.event.type.Data";qx.Class.define(a,{extend:qx.event.type.Event,members:{__jO:null,__jP:null,init:function(b,c,d){qx.event.type.Event.prototype.init.call(this,false,d);this.__jO=b;this.__jP=c;return this;},clone:function(e){var f=qx.event.type.Event.prototype.clone.call(this,e);f.__jO=this.__jO;f.__jP=this.__jP;return f;},getData:function(){return this.__jO;},getOldData:function(){return this.__jP;}},destruct:function(){this.__jO=this.__jP=null;}});})();(function(){var c="qx.globalErrorHandling",b="on",a="qx.event.GlobalError";qx.Bootstrap.define(a,{statics:{setErrorHandler:function(d,f){this.__kx=d||null;this.__ky=f||window;if(qx.core.Setting.get(c)===b){if(d&&window.onerror){var g=qx.Bootstrap.bind(this.__kA,this);if(this.__kz==null){this.__kz=window.onerror;}var self=this;window.onerror=function(e){self.__kz(e);g(e);};}if(d&&!window.onerror){window.onerror=qx.Bootstrap.bind(this.__kA,this);}if(this.__kx==null){if(this.__kz!=null){window.onerror=this.__kz;this.__kz=null;}else{window.onerror=null;}}}},__kA:function(h,i,j){if(this.__kx){this.handleError(new qx.core.WindowError(h,i,j));return true;}},observeMethod:function(k){if(qx.core.Setting.get(c)===b){var self=this;return function(){if(!self.__kx){return k.apply(this,arguments);}try{return k.apply(this,arguments);}catch(l){self.handleError(new qx.core.GlobalError(l,arguments));}};}else{return k;}},handleError:function(m){if(this.__kx){this.__kx.call(this.__ky,m);}}},defer:function(n){qx.core.Setting.define(c,b);n.setErrorHandler(null,null);}});})();(function(){var b="",a="qx.core.WindowError";qx.Bootstrap.define(a,{extend:Error,construct:function(c,d,e){Error.call(this,c);this.__cW=c;this.__cX=d||b;this.__cY=e===undefined?-1:e;},members:{__cW:null,__cX:null,__cY:null,toString:function(){return this.__cW;},getUri:function(){return this.__cX;},getLineNumber:function(){return this.__cY;}}});})();(function(){var b="GlobalError: ",a="qx.core.GlobalError";qx.Bootstrap.define(a,{extend:Error,construct:function(c,d){{};this.__kS=b+(c&&c.message?c.message:c);Error.call(this,this.__kS);this.__kT=d;this.__kU=c;},members:{__kU:null,__kT:null,__kS:null,toString:function(){return this.__kS;},getArguments:function(){return this.__kT;},getSourceException:function(){return this.__kU;}},destruct:function(){this.__kU=null;this.__kT=null;this.__kS=null;}});})();(function(){var a="qx.event.IEventHandler";qx.Interface.define(a,{statics:{TARGET_DOMNODE:1,TARGET_WINDOW:2,TARGET_OBJECT:4,TARGET_DOCUMENT:8},members:{canHandleEvent:function(b,c){},registerEvent:function(d,e,f){},unregisterEvent:function(g,h,i){}}});})();(function(){var c="qx.event.type.Data",b="qx.event.type.Event",a="qx.data.IListData";qx.Interface.define(a,{events:{"change":c,"changeLength":b},members:{getItem:function(d){},setItem:function(e,f){},splice:function(g,h,i){},contains:function(j){},getLength:function(){},toArray:function(){}}});})();(function(){var a="qx.lang.Date";qx.Class.define(a,{statics:{now:function(){return +new Date;}}});})();(function(){var b="qx.util.ObjectPool",a="Integer";qx.Class.define(b,{extend:qx.core.Object,construct:function(c){qx.core.Object.call(this);this.__fH={};if(c!=null){this.setSize(c);}},properties:{size:{check:a,init:Infinity}},members:{__fH:null,getObject:function(d){if(this.$$disposed){return new d;}if(!d){throw new Error("Class needs to be defined!");}var e=null;var f=this.__fH[d.classname];if(f){e=f.pop();}if(e){e.$$pooled=false;}else{e=new d;}return e;},poolObject:function(g){if(!this.__fH){return;}var h=g.classname;var j=this.__fH[h];if(g.$$pooled){throw new Error("Object is already pooled: "+g);}if(!j){this.__fH[h]=j=[];}if(j.length>this.getSize()){if(g.destroy){g.destroy();}else{g.dispose();}return;}g.$$pooled=true;j.push(g);}},destruct:function(){var n=this.__fH;var k,m,i,l;for(k in n){m=n[k];for(i=0,l=m.length;i<l;i++){m[i].dispose();}}delete this.__fH;}});})();(function(){var b="singleton",a="qx.event.Pool";qx.Class.define(a,{extend:qx.util.ObjectPool,type:b,construct:function(){qx.util.ObjectPool.call(this,30);}});})();(function(){var a="qx.util.DisposeUtil";qx.Class.define(a,{statics:{disposeObjects:function(b,c,d){var name;for(var i=0,l=c.length;i<l;i++){name=c[i];if(b[name]==null||!b.hasOwnProperty(name)){continue;}if(!qx.core.ObjectRegistry.inShutDown){if(b[name].dispose){if(!d&&b[name].constructor.$$instance){throw new Error("The object stored in key "+name+" is a singleton! Please use disposeSingleton instead.");}else{b[name].dispose();}}else{throw new Error("Has no disposable object under key: "+name+"!");}}b[name]=null;}},disposeArray:function(e,f){var h=e[f];if(!h){return;}if(qx.core.ObjectRegistry.inShutDown){e[f]=null;return;}try{var g;for(var i=h.length-1;i>=0;i--){g=h[i];if(g){g.dispose();}}}catch(j){throw new Error("The array field: "+f+" of object: "+e+" has non disposable entries: "+j);}h.length=0;e[f]=null;},disposeMap:function(k,m){var o=k[m];if(!o){return;}if(qx.core.ObjectRegistry.inShutDown){k[m]=null;return;}try{var n;for(var p in o){n=o[p];if(o.hasOwnProperty(p)&&n){n.dispose();}}}catch(q){throw new Error("The map field: "+m+" of object: "+k+" has non disposable entries: "+q);}k[m]=null;},disposeTriggeredBy:function(r,s){var t=s.dispose;s.dispose=function(){t.call(s);r.dispose();};}}});})();(function(){var m="get",l="",k="[",h="last",g="change",f="]",d=".",c="Number",b="String",a="set",D="deepBinding",C="item",B="reset",A="' (",z="Boolean",y=") to the object '",x="Integer",w=" of object ",v="qx.data.SingleValueBinding",u="Binding property ",s="Binding from '",t="PositiveNumber",q="PositiveInteger",r="Binding does not exist!",o=").",p="Date",n=" not possible: No event available. ";qx.Class.define(v,{statics:{DEBUG_ON:false,__gl:{},bind:function(E,F,G,H,I){var S=this.__gn(E,F,G,H,I);var N=F.split(d);var K=this.__gt(N);var R=[];var O=[];var P=[];var L=[];var M=E;for(var i=0;i<N.length;i++){if(K[i]!==l){L.push(g);}else{L.push(this.__go(M,N[i]));}R[i]=M;if(i==N.length-1){if(K[i]!==l){var V=K[i]===h?M.length-1:K[i];var J=M.getItem(V);this.__gs(J,G,H,I,E);P[i]=this.__gu(M,L[i],G,H,I,K[i]);}else{if(N[i]!=null&&M[m+qx.lang.String.firstUp(N[i])]!=null){var J=M[m+qx.lang.String.firstUp(N[i])]();this.__gs(J,G,H,I,E);}P[i]=this.__gu(M,L[i],G,H,I);}}else{var T={index:i,propertyNames:N,sources:R,listenerIds:P,arrayIndexValues:K,targetObject:G,targetPropertyChain:H,options:I,listeners:O};var Q=qx.lang.Function.bind(this.__gm,this,T);O.push(Q);P[i]=M.addListener(L[i],Q);}if(M[m+qx.lang.String.firstUp(N[i])]==null){M=null;}else if(K[i]!==l){M=M[m+qx.lang.String.firstUp(N[i])](K[i]);}else{M=M[m+qx.lang.String.firstUp(N[i])]();}if(!M){break;}}var U={type:D,listenerIds:P,sources:R,targetListenerIds:S.listenerIds,targets:S.targets};this.__gv(U,E,F,G,H);return U;},__gm:function(W){if(W.options&&W.options.onUpdate){W.options.onUpdate(W.sources[W.index],W.targetObject);}for(var j=W.index+1;j<W.propertyNames.length;j++){var bb=W.sources[j];W.sources[j]=null;if(!bb){continue;}bb.removeListenerById(W.listenerIds[j]);}var bb=W.sources[W.index];for(var j=W.index+1;j<W.propertyNames.length;j++){if(W.arrayIndexValues[j-1]!==l){bb=bb[m+qx.lang.String.firstUp(W.propertyNames[j-1])](W.arrayIndexValues[j-1]);}else{bb=bb[m+qx.lang.String.firstUp(W.propertyNames[j-1])]();}W.sources[j]=bb;if(!bb){this.__gp(W.targetObject,W.targetPropertyChain);break;}if(j==W.propertyNames.length-1){if(qx.Class.implementsInterface(bb,qx.data.IListData)){var bc=W.arrayIndexValues[j]===h?bb.length-1:W.arrayIndexValues[j];var Y=bb.getItem(bc);this.__gs(Y,W.targetObject,W.targetPropertyChain,W.options,W.sources[W.index]);W.listenerIds[j]=this.__gu(bb,g,W.targetObject,W.targetPropertyChain,W.options,W.arrayIndexValues[j]);}else{if(W.propertyNames[j]!=null&&bb[m+qx.lang.String.firstUp(W.propertyNames[j])]!=null){var Y=bb[m+qx.lang.String.firstUp(W.propertyNames[j])]();this.__gs(Y,W.targetObject,W.targetPropertyChain,W.options,W.sources[W.index]);}var ba=this.__go(bb,W.propertyNames[j]);W.listenerIds[j]=this.__gu(bb,ba,W.targetObject,W.targetPropertyChain,W.options);}}else{if(W.listeners[j]==null){var X=qx.lang.Function.bind(this.__gm,this,W);W.listeners.push(X);}if(qx.Class.implementsInterface(bb,qx.data.IListData)){var ba=g;}else{var ba=this.__go(bb,W.propertyNames[j]);}W.listenerIds[j]=bb.addListener(ba,W.listeners[j]);}}},__gn:function(bd,be,bf,bg,bh){var bl=bg.split(d);var bj=this.__gt(bl);var bq=[];var bp=[];var bn=[];var bm=[];var bk=bf;for(var i=0;i<bl.length-1;i++){if(bj[i]!==l){bm.push(g);}else{try{bm.push(this.__go(bk,bl[i]));}catch(e){break;}}bq[i]=bk;var bo=function(){for(var j=i+1;j<bl.length-1;j++){var bt=bq[j];bq[j]=null;if(!bt){continue;}bt.removeListenerById(bn[j]);}var bt=bq[i];for(var j=i+1;j<bl.length-1;j++){var br=qx.lang.String.firstUp(bl[j-1]);if(bj[j-1]!==l){var bu=bj[j-1]===h?bt.getLength()-1:bj[j-1];bt=bt[m+br](bu);}else{bt=bt[m+br]();}bq[j]=bt;if(bp[j]==null){bp.push(bo);}if(qx.Class.implementsInterface(bt,qx.data.IListData)){var bs=g;}else{try{var bs=qx.data.SingleValueBinding.__go(bt,bl[j]);}catch(e){break;}}bn[j]=bt.addListener(bs,bp[j]);}qx.data.SingleValueBinding.updateTarget(bd,be,bf,bg,bh);};bp.push(bo);bn[i]=bk.addListener(bm[i],bo);var bi=qx.lang.String.firstUp(bl[i]);if(bk[m+bi]==null){bk=null;}else if(bj[i]!==l){bk=bk[m+bi](bj[i]);}else{bk=bk[m+bi]();}if(!bk){break;}}return {listenerIds:bn,targets:bq};},updateTarget:function(bv,bw,bx,by,bz){var bD=this.__gr(bv,bw);if(bD!=null){var bF=bw.substring(bw.lastIndexOf(d)+1,bw.length);if(bF.charAt(bF.length-1)==f){var bA=bF.substring(bF.lastIndexOf(k)+1,bF.length-1);var bC=bF.substring(0,bF.lastIndexOf(k));var bE=bD[m+qx.lang.String.firstUp(bC)]();if(bA==h){bA=bE.length-1;}if(bE!=null){var bB=bE.getItem(bA);}}else{var bB=bD[m+qx.lang.String.firstUp(bF)]();}}bB=qx.data.SingleValueBinding.__gw(bB,bx,by,bz);this.__gq(bx,by,bB);},__go:function(bG,bH){var bI=this.__gx(bG,bH);if(bI==null){if(qx.Class.supportsEvent(bG.constructor,bH)){bI=bH;}else if(qx.Class.supportsEvent(bG.constructor,g+qx.lang.String.firstUp(bH))){bI=g+qx.lang.String.firstUp(bH);}else{throw new qx.core.AssertionError(u+bH+w+bG+n);}}return bI;},__gp:function(bJ,bK){var bL=this.__gr(bJ,bK);if(bL!=null){var bM=bK.substring(bK.lastIndexOf(d)+1,bK.length);if(bM.charAt(bM.length-1)==f){this.__gq(bJ,bK,null);return;}if(bL[B+qx.lang.String.firstUp(bM)]!=undefined){bL[B+qx.lang.String.firstUp(bM)]();}else{bL[a+qx.lang.String.firstUp(bM)](null);}}},__gq:function(bN,bO,bP){var bT=this.__gr(bN,bO);if(bT!=null){var bU=bO.substring(bO.lastIndexOf(d)+1,bO.length);if(bU.charAt(bU.length-1)==f){var bQ=bU.substring(bU.lastIndexOf(k)+1,bU.length-1);var bS=bU.substring(0,bU.lastIndexOf(k));var bR=bT[m+qx.lang.String.firstUp(bS)]();if(bQ==h){bQ=bR.length-1;}if(bR!=null){bR.setItem(bQ,bP);}}else{bT[a+qx.lang.String.firstUp(bU)](bP);}}},__gr:function(bV,bW){var ca=bW.split(d);var cb=bV;for(var i=0;i<ca.length-1;i++){try{var bY=ca[i];if(bY.indexOf(f)==bY.length-1){var bX=bY.substring(bY.indexOf(k)+1,bY.length-1);bY=bY.substring(0,bY.indexOf(k));}cb=cb[m+qx.lang.String.firstUp(bY)]();if(bX!=null){if(bX==h){bX=cb.length-1;}cb=cb.getItem(bX);bX=null;}}catch(cc){return null;}}return cb;},__gs:function(cd,ce,cf,cg,ch){cd=this.__gw(cd,ce,cf,cg);if(cd===undefined){this.__gp(ce,cf);}if(cd!==undefined){try{this.__gq(ce,cf,cd);if(cg&&cg.onUpdate){cg.onUpdate(ch,ce,cd);}}catch(e){if(!(e instanceof qx.core.ValidationError)){throw e;}if(cg&&cg.onSetFail){cg.onSetFail(e);}else{qx.log.Logger.warn("Failed so set value "+cd+" on "+ce+". Error message: "+e);}}}},__gt:function(ci){var cj=[];for(var i=0;i<ci.length;i++){var name=ci[i];if(qx.lang.String.endsWith(name,f)){var ck=name.substring(name.indexOf(k)+1,name.indexOf(f));if(name.indexOf(f)!=name.length-1){throw new Error("Please use only one array at a time: "+name+" does not work.");}if(ck!==h){if(ck==l||isNaN(parseInt(ck,10))){throw new Error("No number or 'last' value hast been given"+" in a array binding: "+name+" does not work.");}}if(name.indexOf(k)!=0){ci[i]=name.substring(0,name.indexOf(k));cj[i]=l;cj[i+1]=ck;ci.splice(i+1,0,C);i++;}else{cj[i]=ck;ci.splice(i,1,C);}}else{cj[i]=l;}}return cj;},__gu:function(cl,cm,cn,co,cp,cq){var cr;{};var ct=function(cu,e){if(cu!==l){if(cu===h){cu=cl.length-1;}var cx=cl.getItem(cu);if(cx===undefined){qx.data.SingleValueBinding.__gp(cn,co);}var cv=e.getData().start;var cw=e.getData().end;if(cu<cv||cu>cw){return;}}else{var cx=e.getData();}if(qx.data.SingleValueBinding.DEBUG_ON){qx.log.Logger.debug("Binding executed from "+cl+" by "+cm+" to "+cn+" ("+co+")");qx.log.Logger.debug("Data before conversion: "+cx);}cx=qx.data.SingleValueBinding.__gw(cx,cn,co,cp);if(qx.data.SingleValueBinding.DEBUG_ON){qx.log.Logger.debug("Data after conversion: "+cx);}try{if(cx!==undefined){qx.data.SingleValueBinding.__gq(cn,co,cx);}else{qx.data.SingleValueBinding.__gp(cn,co);}if(cp&&cp.onUpdate){cp.onUpdate(cl,cn,cx);}}catch(e){if(!(e instanceof qx.core.ValidationError)){throw e;}if(cp&&cp.onSetFail){cp.onSetFail(e);}else{qx.log.Logger.warn("Failed so set value "+cx+" on "+cn+". Error message: "+e);}}};if(!cq){cq=l;}ct=qx.lang.Function.bind(ct,cl,cq);var cs=cl.addListener(cm,ct);return cs;},__gv:function(cy,cz,cA,cB,cC){if(this.__gl[cz.toHashCode()]===undefined){this.__gl[cz.toHashCode()]=[];}this.__gl[cz.toHashCode()].push([cy,cz,cA,cB,cC]);},__gw:function(cD,cE,cF,cG){if(cG&&cG.converter){var cI;if(cE.getModel){cI=cE.getModel();}return cG.converter(cD,cI);}else{var cK=this.__gr(cE,cF);var cL=cF.substring(cF.lastIndexOf(d)+1,cF.length);if(cK==null){return cD;}var cJ=qx.Class.getPropertyDefinition(cK.constructor,cL);var cH=cJ==null?l:cJ.check;return this.__gy(cD,cH);}},__gx:function(cM,cN){var cO=qx.Class.getPropertyDefinition(cM.constructor,cN);if(cO==null){return null;}return cO.event;},__gy:function(cP,cQ){var cR=qx.lang.Type.getClass(cP);if((cR==c||cR==b)&&(cQ==x||cQ==q)){cP=parseInt(cP,10);}if((cR==z||cR==c||cR==p)&&cQ==b){cP=cP+l;}if((cR==c||cR==b)&&(cQ==c||cQ==t)){cP=parseFloat(cP);}return cP;},removeBindingFromObject:function(cS,cT){if(cT.type==D){for(var i=0;i<cT.sources.length;i++){if(cT.sources[i]){cT.sources[i].removeListenerById(cT.listenerIds[i]);}}for(var i=0;i<cT.targets.length;i++){if(cT.targets[i]){cT.targets[i].removeListenerById(cT.targetListenerIds[i]);}}}else{cS.removeListenerById(cT);}var cU=this.__gl[cS.toHashCode()];if(cU!=undefined){for(var i=0;i<cU.length;i++){if(cU[i][0]==cT){qx.lang.Array.remove(cU,cU[i]);return;}}}throw new Error("Binding could not be found!");},removeAllBindingsForObject:function(cV){{};var cW=this.__gl[cV.toHashCode()];if(cW!=undefined){for(var i=cW.length-1;i>=0;i--){this.removeBindingFromObject(cV,cW[i][0]);}}},getAllBindingsForObject:function(cX){if(this.__gl[cX.toHashCode()]===undefined){this.__gl[cX.toHashCode()]=[];}return this.__gl[cX.toHashCode()];},removeAllBindings:function(){for(var da in this.__gl){var cY=qx.core.ObjectRegistry.fromHashCode(da);if(cY==null){delete this.__gl[da];continue;}this.removeAllBindingsForObject(cY);}this.__gl={};},getAllBindings:function(){return this.__gl;},showBindingInLog:function(db,dc){var de;for(var i=0;i<this.__gl[db.toHashCode()].length;i++){if(this.__gl[db.toHashCode()][i][0]==dc){de=this.__gl[db.toHashCode()][i];break;}}if(de===undefined){var dd=r;}else{var dd=s+de[1]+A+de[2]+y+de[3]+A+de[4]+o;}qx.log.Logger.debug(dd);},showAllBindingsInLog:function(){for(var dg in this.__gl){var df=qx.core.ObjectRegistry.fromHashCode(dg);for(var i=0;i<this.__gl[dg].length;i++){this.showBindingInLog(df,this.__gl[dg][i][0]);}}}}});})();(function(){var c=": ",b="qx.type.BaseError",a="";qx.Class.define(b,{extend:Error,construct:function(d,e){Error.call(this,e);this.__cL=d||a;this.message=e||qx.type.BaseError.DEFAULTMESSAGE;},statics:{DEFAULTMESSAGE:"error"},members:{__cL:null,message:null,getComment:function(){return this.__cL;},toString:function(){return this.__cL+c+this.message;}}});})();(function(){var a="qx.core.AssertionError";qx.Class.define(a,{extend:qx.type.BaseError,construct:function(b,c){qx.type.BaseError.call(this,b,c);this.__lC=qx.dev.StackTrace.getStackTrace();},members:{__lC:null,getStackTrace:function(){return this.__lC;}}});})();(function(){var a="qx.core.ValidationError";qx.Class.define(a,{extend:qx.type.BaseError});})();(function(){var f="qx.lang.Type",e="Error",d="RegExp",c="Date",b="Number",a="Boolean";qx.Class.define(f,{statics:{getClass:qx.Bootstrap.getClass,isString:qx.Bootstrap.isString,isArray:qx.Bootstrap.isArray,isObject:qx.Bootstrap.isObject,isFunction:qx.Bootstrap.isFunction,isRegExp:function(g){return this.getClass(g)==d;},isNumber:function(h){return (h!==null&&(this.getClass(h)==b||h instanceof Number));},isBoolean:function(i){return (i!==null&&(this.getClass(i)==a||i instanceof Boolean));},isDate:function(j){return (j!==null&&(this.getClass(j)==c||j instanceof Date));},isError:function(k){return (k!==null&&(this.getClass(k)==e||k instanceof Error));}}});})();(function(){var a="qx.event.IEventDispatcher";qx.Interface.define(a,{members:{canDispatchEvent:function(b,event,c){this.assertInstance(event,qx.event.type.Event);this.assertString(c);},dispatchEvent:function(d,event,e){this.assertInstance(event,qx.event.type.Event);this.assertString(e);}}});})();(function(){var a="qx.event.dispatch.Direct";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventDispatcher,construct:function(b){this._manager=b;},statics:{PRIORITY:qx.event.Registration.PRIORITY_LAST},members:{canDispatchEvent:function(c,event,d){return !event.getBubbles();},dispatchEvent:function(e,event,f){var j,g;{};event.setEventPhase(qx.event.type.Event.AT_TARGET);var k=this._manager.getListeners(e,f,false);if(k){for(var i=0,l=k.length;i<l;i++){var h=k[i].context||e;k[i].handler.call(h,event);}}}},defer:function(m){qx.event.Registration.addDispatcher(m);}});})();(function(){var a="qx.event.handler.Object";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventHandler,statics:{PRIORITY:qx.event.Registration.PRIORITY_LAST,SUPPORTED_TYPES:null,TARGET_CHECK:qx.event.IEventHandler.TARGET_OBJECT,IGNORE_CAN_HANDLE:false},members:{canHandleEvent:function(b,c){return qx.Class.supportsEvent(b.constructor,c);},registerEvent:function(d,e,f){},unregisterEvent:function(g,h,i){}},defer:function(j){qx.event.Registration.addHandler(j);}});})();(function(){var k="indexOf",j="lastIndexOf",h="slice",g="concat",f="join",e="toLocaleUpperCase",d="shift",c="substr",b="filter",a="unshift",I="match",H="quote",G="qx.lang.Generics",F="localeCompare",E="sort",D="some",C="charAt",B="split",A="substring",z="pop",t="toUpperCase",u="replace",q="push",r="charCodeAt",o="every",p="reverse",m="search",n="forEach",v="map",w="toLowerCase",y="splice",x="toLocaleLowerCase";qx.Class.define(G,{statics:{__eY:{"Array":[f,p,E,q,z,d,a,y,g,h,k,j,n,v,b,D,o],"String":[H,A,w,t,C,r,k,j,x,e,F,I,m,u,B,c,g,h]},__fa:function(J,K){return function(s){return J.prototype[K].apply(s,Array.prototype.slice.call(arguments,1));};},__fb:function(){var L=qx.lang.Generics.__eY;for(var P in L){var N=window[P];var M=L[P];for(var i=0,l=M.length;i<l;i++){var O=M[i];if(!N[O]){N[O]=qx.lang.Generics.__fa(N,O);}}}}},defer:function(Q){Q.__fb();}});})();(function(){var b="qx.util.DeferredCallManager",a="singleton";qx.Class.define(b,{extend:qx.core.Object,type:a,construct:function(){this.__gf={};this.__gg=qx.lang.Function.bind(this.__gk,this);this.__gh=false;},members:{__gi:null,__gj:null,__gf:null,__gh:null,__gg:null,schedule:function(c){if(this.__gi==null){this.__gi=window.setTimeout(this.__gg,0);}var d=c.toHashCode();if(this.__gj&&this.__gj[d]){return;}this.__gf[d]=c;this.__gh=true;},cancel:function(e){var f=e.toHashCode();if(this.__gj&&this.__gj[f]){this.__gj[f]=null;return;}delete this.__gf[f];if(qx.lang.Object.isEmpty(this.__gf)&&this.__gi!=null){window.clearTimeout(this.__gi);this.__gi=null;}},__gk:qx.event.GlobalError.observeMethod(function(){this.__gi=null;while(this.__gh){this.__gj=qx.lang.Object.clone(this.__gf);this.__gf={};this.__gh=false;for(var h in this.__gj){var g=this.__gj[h];if(g){this.__gj[h]=null;g.call();}}}this.__gj=null;})},destruct:function(){if(this.__gi!=null){window.clearTimeout(this.__gi);}this.__gg=this.__gf=null;}});})();(function(){var a="qx.util.DeferredCall";qx.Class.define(a,{extend:qx.core.Object,construct:function(b,c){qx.core.Object.call(this);this.__ia=b;this.__ib=c||null;this.__ic=qx.util.DeferredCallManager.getInstance();},members:{__ia:null,__ib:null,__ic:null,cancel:function(){this.__ic.cancel(this);},schedule:function(){this.__ic.schedule(this);},call:function(){this.__ib?this.__ia.apply(this.__ib):this.__ia();}},destruct:function(d,e){this.cancel();this.__ib=this.__ia=this.__ic=null;}});})();(function(){var m="element",k="qx.client",j="qxSelectable",h="off",g="on",f="text",d="div",c="",b="mshtml",a="none",F="scroll",E="qx.html.Element",D="|capture|",C="activate",B="__dz",A="blur",z="deactivate",w="capture",v="userSelect",u="-moz-none",s="visible",t="releaseCapture",q="|bubble|",r="tabIndex",o="focus",p="MozUserSelect",n="hidden";qx.Class.define(E,{extend:qx.core.Object,construct:function(G,H,I){qx.core.Object.call(this);this.__dd=G||d;this.__de=H||null;this.__df=I||null;},statics:{DEBUG:false,_modified:{},_visibility:{},_scroll:{},_actions:[],__dg:{},_scheduleFlush:function(J){qx.html.Element.__dK.schedule();},flush:function(){var U;{};var M=this.__dh();var L=M.getFocus();if(L&&this.__dl(L)){M.blur(L);}var bc=M.getActive();if(bc&&this.__dl(bc)){qx.bom.Element.deactivate(bc);}var P=this.__dj();if(P&&this.__dl(P)){qx.bom.Element.releaseCapture(P);}var V=[];var W=this._modified;for(var T in W){U=W[T];if(U.__dD()){if(U.__dm&&qx.dom.Hierarchy.isRendered(U.__dm)){V.push(U);}else{{};U.__dC();}delete W[T];}}for(var i=0,l=V.length;i<l;i++){U=V[i];{};U.__dC();}var R=this._visibility;for(var T in R){U=R[T];var X=U.__dm;if(!X){delete R[T];continue;}{};if(!U.$$disposed){X.style.display=U.__dp?c:a;if(qx.core.Variant.isSet(k,b)){if(!(document.documentMode>=8)){X.style.visibility=U.__dp?s:n;}}}delete R[T];}var scroll=this._scroll;for(var T in scroll){U=scroll[T];var bd=U.__dm;if(bd&&bd.offsetWidth){var O=true;if(U.__ds!=null){U.__dm.scrollLeft=U.__ds;delete U.__ds;}if(U.__dt!=null){U.__dm.scrollTop=U.__dt;delete U.__dt;}var Y=U.__dq;if(Y!=null){var S=Y.element.getDomElement();if(S&&S.offsetWidth){qx.bom.element.Scroll.intoViewX(S,bd,Y.align);delete U.__dq;}else{O=false;}}var ba=U.__dr;if(ba!=null){var S=ba.element.getDomElement();if(S&&S.offsetWidth){qx.bom.element.Scroll.intoViewY(S,bd,ba.align);delete U.__dr;}else{O=false;}}if(O){delete scroll[T];}}}var N={"releaseCapture":1,"blur":1,"deactivate":1};for(var i=0;i<this._actions.length;i++){var bb=this._actions[i];var X=bb.element.__dm;if(!X||!N[bb.type]&&!bb.element.__dD()){continue;}var Q=bb.args;Q.unshift(X);qx.bom.Element[bb.type].apply(qx.bom.Element,Q);}this._actions=[];for(var T in this.__dg){var K=this.__dg[T];var bd=K.element.__dm;if(bd){qx.bom.Selection.set(bd,K.start,K.end);delete this.__dg[T];}}qx.event.handler.Appear.refresh();},__dh:function(){if(!this.__di){var be=qx.event.Registration.getManager(window);this.__di=be.getHandler(qx.event.handler.Focus);}return this.__di;},__dj:function(){if(!this.__dk){var bf=qx.event.Registration.getManager(window);this.__dk=bf.getDispatcher(qx.event.dispatch.MouseCapture);}return this.__dk.getCaptureElement();},__dl:function(bg){var bh=qx.core.ObjectRegistry.fromHashCode(bg.$$element);return bh&&!bh.__dD();}},members:{__dd:null,__dm:null,__dn:false,__do:true,__dp:true,__dq:null,__dr:null,__ds:null,__dt:null,__du:null,__dv:null,__dw:null,__de:null,__df:null,__dx:null,__dy:null,__dz:null,__dA:null,__dB:null,_scheduleChildrenUpdate:function(){if(this.__dA){return;}this.__dA=true;qx.html.Element._modified[this.$$hash]=this;qx.html.Element._scheduleFlush(m);},_createDomElement:function(){return qx.bom.Element.create(this.__dd);},__dC:function(){{};var length;var bi=this.__dz;if(bi){length=bi.length;var bj;for(var i=0;i<length;i++){bj=bi[i];if(bj.__dp&&bj.__do&&!bj.__dm){bj.__dC();}}}if(!this.__dm){this.__dm=this._createDomElement();this.__dm.$$element=this.$$hash;this._copyData(false);if(bi&&length>0){this._insertChildren();}}else{this._syncData();if(this.__dA){this._syncChildren();}}delete this.__dA;},_insertChildren:function(){var bk=this.__dz;var length=bk.length;var bm;if(length>2){var bl=document.createDocumentFragment();for(var i=0;i<length;i++){bm=bk[i];if(bm.__dm&&bm.__do){bl.appendChild(bm.__dm);}}this.__dm.appendChild(bl);}else{var bl=this.__dm;for(var i=0;i<length;i++){bm=bk[i];if(bm.__dm&&bm.__do){bl.appendChild(bm.__dm);}}}},_syncChildren:function(){var br;var bw=qx.core.ObjectRegistry;var bn=this.__dz;var bu=bn.length;var bo;var bs;var bq=this.__dm;var bt=bq.childNodes;var bp=0;var bv;{};for(var i=bt.length-1;i>=0;i--){bv=bt[i];bs=bw.fromHashCode(bv.$$element);if(!bs||!bs.__do||bs.__dB!==this){bq.removeChild(bv);{};}}for(var i=0;i<bu;i++){bo=bn[i];if(bo.__do){bs=bo.__dm;bv=bt[bp];if(!bs){continue;}if(bs!=bv){if(bv){bq.insertBefore(bs,bv);}else{bq.appendChild(bs);}{};}bp++;}}{};},_copyData:function(bx){var bB=this.__dm;var bA=this.__df;if(bA){var by=qx.bom.element.Attribute;for(var bC in bA){by.set(bB,bC,bA[bC]);}}var bA=this.__de;if(bA){var bz=qx.bom.element.Style;if(bx){bz.setStyles(bB,bA);}else{bz.setCss(bB,bz.compile(bA));}}var bA=this.__dx;if(bA){for(var bC in bA){this._applyProperty(bC,bA[bC]);}}var bA=this.__dy;if(bA){qx.event.Registration.getManager(bB).importListeners(bB,bA);delete this.__dy;}},_syncData:function(){var bH=this.__dm;var bG=qx.bom.element.Attribute;var bE=qx.bom.element.Style;var bF=this.__dv;if(bF){var bK=this.__df;if(bK){var bI;for(var bJ in bF){bI=bK[bJ];if(bI!==undefined){bG.set(bH,bJ,bI);}else{bG.reset(bH,bJ);}}}this.__dv=null;}var bF=this.__du;if(bF){var bK=this.__de;if(bK){var bD={};for(var bJ in bF){bD[bJ]=bK[bJ];}bE.setStyles(bH,bD);}this.__du=null;}var bF=this.__dw;if(bF){var bK=this.__dx;if(bK){var bI;for(var bJ in bF){this._applyProperty(bJ,bK[bJ]);}}this.__dw=null;}},__dD:function(){var bL=this;while(bL){if(bL.__dn){return true;}if(!bL.__do||!bL.__dp){return false;}bL=bL.__dB;}return false;},__dE:function(bM){if(bM.__dB===this){throw new Error("Child is already in: "+bM);}if(bM.__dn){throw new Error("Root elements could not be inserted into other ones.");}if(bM.__dB){bM.__dB.remove(bM);}bM.__dB=this;if(!this.__dz){this.__dz=[];}if(this.__dm){this._scheduleChildrenUpdate();}},__dF:function(bN){if(bN.__dB!==this){throw new Error("Has no child: "+bN);}if(this.__dm){this._scheduleChildrenUpdate();}delete bN.__dB;},__dG:function(bO){if(bO.__dB!==this){throw new Error("Has no child: "+bO);}if(this.__dm){this._scheduleChildrenUpdate();}},getChildren:function(){return this.__dz||null;},getChild:function(bP){var bQ=this.__dz;return bQ&&bQ[bP]||null;},hasChildren:function(){var bR=this.__dz;return bR&&bR[0]!==undefined;},indexOf:function(bS){var bT=this.__dz;return bT?bT.indexOf(bS):-1;},hasChild:function(bU){var bV=this.__dz;return bV&&bV.indexOf(bU)!==-1;},add:function(bW){if(arguments[1]){for(var i=0,l=arguments.length;i<l;i++){this.__dE(arguments[i]);}this.__dz.push.apply(this.__dz,arguments);}else{this.__dE(bW);this.__dz.push(bW);}return this;},addAt:function(bX,bY){this.__dE(bX);qx.lang.Array.insertAt(this.__dz,bX,bY);return this;},remove:function(ca){var cb=this.__dz;if(!cb){return;}if(arguments[1]){var cc;for(var i=0,l=arguments.length;i<l;i++){cc=arguments[i];this.__dF(cc);qx.lang.Array.remove(cb,cc);}}else{this.__dF(ca);qx.lang.Array.remove(cb,ca);}return this;},removeAt:function(cd){var ce=this.__dz;if(!ce){throw new Error("Has no children!");}var cf=ce[cd];if(!cf){throw new Error("Has no child at this position!");}this.__dF(cf);qx.lang.Array.removeAt(this.__dz,cd);return this;},removeAll:function(){var cg=this.__dz;if(cg){for(var i=0,l=cg.length;i<l;i++){this.__dF(cg[i]);}cg.length=0;}return this;},getParent:function(){return this.__dB||null;},insertInto:function(parent,ch){parent.__dE(this);if(ch==null){parent.__dz.push(this);}else{qx.lang.Array.insertAt(this.__dz,this,ch);}return this;},insertBefore:function(ci){var parent=ci.__dB;parent.__dE(this);qx.lang.Array.insertBefore(parent.__dz,this,ci);return this;},insertAfter:function(cj){var parent=cj.__dB;parent.__dE(this);qx.lang.Array.insertAfter(parent.__dz,this,cj);return this;},moveTo:function(ck){var parent=this.__dB;parent.__dG(this);var cl=parent.__dz.indexOf(this);if(cl===ck){throw new Error("Could not move to same index!");}else if(cl<ck){ck--;}qx.lang.Array.removeAt(parent.__dz,cl);qx.lang.Array.insertAt(parent.__dz,this,ck);return this;},moveBefore:function(cm){var parent=this.__dB;return this.moveTo(parent.__dz.indexOf(cm));},moveAfter:function(cn){var parent=this.__dB;return this.moveTo(parent.__dz.indexOf(cn)+1);},free:function(){var parent=this.__dB;if(!parent){throw new Error("Has no parent to remove from.");}if(!parent.__dz){return;}parent.__dF(this);qx.lang.Array.remove(parent.__dz,this);return this;},getDomElement:function(){return this.__dm||null;},getNodeName:function(){return this.__dd;},setNodeName:function(name){this.__dd=name;},setRoot:function(co){this.__dn=co;},useMarkup:function(cp){if(this.__dm){throw new Error("Could not overwrite existing element!");}if(qx.core.Variant.isSet(k,b)){var cq=document.createElement(d);}else{var cq=qx.bom.Element.getHelperElement();}cq.innerHTML=cp;this.useElement(cq.firstChild);return this.__dm;},useElement:function(cr){if(this.__dm){throw new Error("Could not overwrite existing element!");}this.__dm=cr;this.__dm.$$element=this.$$hash;this._copyData(true);},isFocusable:function(){var ct=this.getAttribute(r);if(ct>=1){return true;}var cs=qx.event.handler.Focus.FOCUSABLE_ELEMENTS;if(ct>=0&&cs[this.__dd]){return true;}return false;},setSelectable:qx.core.Variant.select(k,{"webkit":function(cu){this.setAttribute(j,cu?g:h);this.setStyle(v,cu?f:a);},"gecko":function(cv){this.setAttribute(j,cv?g:h);this.setStyle(p,cv?f:u);},"default":function(cw){this.setAttribute(j,cw?g:h);}}),isNativelyFocusable:function(){return !!qx.event.handler.Focus.FOCUSABLE_ELEMENTS[this.__dd];},include:function(){if(this.__do){return;}delete this.__do;if(this.__dB){this.__dB._scheduleChildrenUpdate();}return this;},exclude:function(){if(!this.__do){return;}this.__do=false;if(this.__dB){this.__dB._scheduleChildrenUpdate();}return this;},isIncluded:function(){return this.__do===true;},show:function(){if(this.__dp){return;}if(this.__dm){qx.html.Element._visibility[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}if(this.__dB){this.__dB._scheduleChildrenUpdate();}delete this.__dp;},hide:function(){if(!this.__dp){return;}if(this.__dm){qx.html.Element._visibility[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}this.__dp=false;},isVisible:function(){return this.__dp===true;},scrollChildIntoViewX:function(cx,cy,cz){var cA=this.__dm;var cB=cx.getDomElement();if(cz!==false&&cA&&cA.offsetWidth&&cB&&cB.offsetWidth){qx.bom.element.Scroll.intoViewX(cB,cA,cy);}else{this.__dq={element:cx,align:cy};qx.html.Element._scroll[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}delete this.__ds;},scrollChildIntoViewY:function(cC,cD,cE){var cF=this.__dm;var cG=cC.getDomElement();if(cE!==false&&cF&&cF.offsetWidth&&cG&&cG.offsetWidth){qx.bom.element.Scroll.intoViewY(cG,cF,cD);}else{this.__dr={element:cC,align:cD};qx.html.Element._scroll[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}delete this.__dt;},scrollToX:function(x,cH){var cI=this.__dm;if(cH!==true&&cI&&cI.offsetWidth){cI.scrollLeft=x;}else{this.__ds=x;qx.html.Element._scroll[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}delete this.__dq;},getScrollX:function(){var cJ=this.__dm;if(cJ){return cJ.scrollLeft;}return this.__ds||0;},scrollToY:function(y,cK){var cL=this.__dm;if(cK!==true&&cL&&cL.offsetWidth){cL.scrollTop=y;}else{this.__dt=y;qx.html.Element._scroll[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}delete this.__dr;},getScrollY:function(){var cM=this.__dm;if(cM){return cM.scrollTop;}return this.__dt||0;},disableScrolling:function(){this.enableScrolling();this.scrollToX(0);this.scrollToY(0);this.addListener(F,this.__dI,this);},enableScrolling:function(){this.removeListener(F,this.__dI,this);},__dH:null,__dI:function(e){if(!this.__dH){this.__dH=true;this.__dm.scrollTop=0;this.__dm.scrollLeft=0;delete this.__dH;}},getTextSelection:function(){var cN=this.__dm;if(cN){return qx.bom.Selection.get(cN);}return null;},getTextSelectionLength:function(){var cO=this.__dm;if(cO){return qx.bom.Selection.getLength(cO);}return null;},getTextSelectionStart:function(){var cP=this.__dm;if(cP){return qx.bom.Selection.getStart(cP);}return null;},getTextSelectionEnd:function(){var cQ=this.__dm;if(cQ){return qx.bom.Selection.getEnd(cQ);}return null;},setTextSelection:function(cR,cS){var cT=this.__dm;if(cT){qx.bom.Selection.set(cT,cR,cS);return;}qx.html.Element.__dg[this.toHashCode()]={element:this,start:cR,end:cS};qx.html.Element._scheduleFlush(m);},clearTextSelection:function(){var cU=this.__dm;if(cU){qx.bom.Selection.clear(cU);}delete qx.html.Element.__dg[this.toHashCode()];},__dJ:function(cV,cW){var cX=qx.html.Element._actions;cX.push({type:cV,element:this,args:cW||[]});qx.html.Element._scheduleFlush(m);},focus:function(){this.__dJ(o);},blur:function(){this.__dJ(A);},activate:function(){this.__dJ(C);},deactivate:function(){this.__dJ(z);},capture:function(cY){this.__dJ(w,[cY!==false]);},releaseCapture:function(){this.__dJ(t);},setStyle:function(da,dc,dd){if(!this.__de){this.__de={};}if(this.__de[da]==dc){return;}if(dc==null){delete this.__de[da];}else{this.__de[da]=dc;}if(this.__dm){if(dd){qx.bom.element.Style.set(this.__dm,da,dc);return this;}if(!this.__du){this.__du={};}this.__du[da]=true;qx.html.Element._modified[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}return this;},setStyles:function(de,df){var dg=qx.bom.element.Style;if(!this.__de){this.__de={};}if(this.__dm){if(!this.__du){this.__du={};}for(var di in de){var dh=de[di];if(this.__de[di]==dh){continue;}if(dh==null){delete this.__de[di];}else{this.__de[di]=dh;}if(df){dg.set(this.__dm,di,dh);continue;}this.__du[di]=true;}qx.html.Element._modified[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}else{for(var di in de){var dh=de[di];if(this.__de[di]==dh){continue;}if(dh==null){delete this.__de[di];}else{this.__de[di]=dh;}}}return this;},removeStyle:function(dj,dk){this.setStyle(dj,null,dk);},getStyle:function(dl){return this.__de?this.__de[dl]:null;},getAllStyles:function(){return this.__de||null;},setAttribute:function(dm,dn,dp){if(!this.__df){this.__df={};}if(this.__df[dm]==dn){return;}if(dn==null){delete this.__df[dm];}else{this.__df[dm]=dn;}if(this.__dm){if(dp){qx.bom.element.Attribute.set(this.__dm,dm,dn);return this;}if(!this.__dv){this.__dv={};}this.__dv[dm]=true;qx.html.Element._modified[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}return this;},setAttributes:function(dq,dr){for(var ds in dq){this.setAttribute(ds,dq[ds],dr);}return this;},removeAttribute:function(dt,du){this.setAttribute(dt,null,du);},getAttribute:function(dv){return this.__df?this.__df[dv]:null;},_applyProperty:function(name,dw){},_setProperty:function(dx,dy,dz){if(!this.__dx){this.__dx={};}if(this.__dx[dx]==dy){return;}if(dy==null){delete this.__dx[dx];}else{this.__dx[dx]=dy;}if(this.__dm){if(dz){this._applyProperty(dx,dy);return this;}if(!this.__dw){this.__dw={};}this.__dw[dx]=true;qx.html.Element._modified[this.$$hash]=this;qx.html.Element._scheduleFlush(m);}return this;},_removeProperty:function(dA,dB){this._setProperty(dA,null,dB);},_getProperty:function(dC){var dD=this.__dx;if(!dD){return null;}var dE=dD[dC];return dE==null?null:dE;},addListener:function(dF,dG,self,dH){var dI;if(this.$$disposed){return null;}{};if(this.__dm){return qx.event.Registration.addListener(this.__dm,dF,dG,self,dH);}if(!this.__dy){this.__dy={};}if(dH==null){dH=false;}var dJ=qx.event.Manager.getNextUniqueId();var dK=dF+(dH?D:q)+dJ;this.__dy[dK]={type:dF,listener:dG,self:self,capture:dH,unique:dJ};return dK;},removeListener:function(dL,dM,self,dN){var dO;if(this.$$disposed){return null;}{};if(this.__dm){qx.event.Registration.removeListener(this.__dm,dL,dM,self,dN);}else{var dQ=this.__dy;var dP;if(dN==null){dN=false;}for(var dR in dQ){dP=dQ[dR];if(dP.listener===dM&&dP.self===self&&dP.capture===dN&&dP.type===dL){delete dQ[dR];break;}}}return this;},removeListenerById:function(dS){if(this.$$disposed){return null;}if(this.__dm){qx.event.Registration.removeListenerById(this.__dm,dS);}else{delete this.__dy[dS];}return this;},hasListener:function(dT,dU){if(this.$$disposed){return false;}if(this.__dm){return qx.event.Registration.hasListener(this.__dm,dT,dU);}var dW=this.__dy;var dV;if(dU==null){dU=false;}for(var dX in dW){dV=dW[dX];if(dV.capture===dU&&dV.type===dT){return true;}}return false;}},defer:function(dY){dY.__dK=new qx.util.DeferredCall(dY.flush,dY);},destruct:function(){var ea=this.__dm;if(ea){qx.event.Registration.getManager(ea).removeAllListeners(ea);ea.$$element=c;}if(!qx.core.ObjectRegistry.inShutDown){var parent=this.__dB;if(parent&&!parent.$$disposed){parent.remove(this);}}this._disposeArray(B);this.__df=this.__de=this.__dy=this.__dx=this.__dv=this.__du=this.__dw=this.__dm=this.__dB=this.__dq=this.__dr=null;}});})();(function(){var g="qx.bom.client.Feature",f="CSS1Compat",d="label",c="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",b="input",a="pointerEvents";qx.Bootstrap.define(g,{statics:{STANDARD_MODE:false,QUIRKS_MODE:false,CONTENT_BOX:false,BORDER_BOX:false,SVG:false,CANVAS:!!window.CanvasRenderingContext2D,VML:false,XPATH:!!document.evaluate,AIR:navigator.userAgent.indexOf("adobeair")!==-1,GEARS:!!(window.google&&window.google.gears),SSL:window.location.protocol==="https:",ECMA_OBJECT_COUNT:(({}).__count__==0),CSS_POINTER_EVENTS:false,XUL:false,CSS_TEXT_OVERFLOW:("textOverflow" in document.documentElement.style||"OTextOverflow" in document.documentElement.style),HTML5_CLASSLIST:!!(document.documentElement.classList&&qx.Bootstrap.getClass(document.documentElement.classList)==="DOMTokenList"),TOUCH:("ontouchstart" in window),PLACEHOLDER:false,__gG:function(){this.QUIRKS_MODE=this.__gH();this.STANDARD_MODE=!this.QUIRKS_MODE;this.CONTENT_BOX=!qx.bom.client.Engine.MSHTML||this.STANDARD_MODE;this.BORDER_BOX=!this.CONTENT_BOX;this.SVG=document.implementation&&document.implementation.hasFeature&&(document.implementation.hasFeature("org.w3c.dom.svg","1.0")||document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"));this.VML=qx.bom.client.Engine.MSHTML;try{document.createElementNS(c,d);this.XUL=true;}catch(e){this.XUL=false;}var i=document.createElement(b);this.PLACEHOLDER="placeholder" in i;if(a in document.documentElement.style){if(qx.bom.client.Engine.OPERA){this.CSS_POINTER_EVENTS=false;}else{this.CSS_POINTER_EVENTS=true;}}},__gH:function(){if(qx.bom.client.Engine.MSHTML&&qx.bom.client.Engine.VERSION>=8){return qx.bom.client.Engine.DOCUMENT_MODE===5;}else{return document.compatMode!==f;}}},defer:function(h){h.__gG();}});})();(function(){var a="qx.event.handler.UserAction";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(b){qx.core.Object.call(this);this.__kB=b;this.__kC=b.getWindow();},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{useraction:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_WINDOW,IGNORE_CAN_HANDLE:true},members:{__kB:null,__kC:null,canHandleEvent:function(c,d){},registerEvent:function(e,f,g){},unregisterEvent:function(h,i,j){}},destruct:function(){this.__kB=this.__kC=null;},defer:function(k){qx.event.Registration.addHandler(k);}});})();(function(){var d='ie',c="qx.ui.core.queue.Manager",b="useraction",a="touchend";qx.Class.define(c,{statics:{__lg:false,__lh:{},__li:0,MAX_RETRIES:10,scheduleFlush:function(f){var self=qx.ui.core.queue.Manager;self.__lh[f]=true;if(!self.__lg){self.__ln.schedule();self.__lg=true;}},flush:function(){if(qx.ui.core.queue.Manager.PAUSE){return;}var self=qx.ui.core.queue.Manager;if(self.__lj){return;}self.__lj=true;self.__ln.cancel();var g=self.__lh;self.__lk(function(){while(g.visibility||g.widget||g.appearance||g.layout||g.element){if(g.widget){delete g.widget;qx.ui.core.queue.Widget.flush();}if(g.visibility){delete g.visibility;qx.ui.core.queue.Visibility.flush();}if(g.appearance){delete g.appearance;qx.ui.core.queue.Appearance.flush();}if(g.widget||g.visibility||g.appearance){continue;}if(g.layout){delete g.layout;qx.ui.core.queue.Layout.flush();}if(g.widget||g.visibility||g.appearance||g.layout){continue;}if(g.element){delete g.element;qx.html.Element.flush();}}},function(){self.__lg=false;});self.__lk(function(){if(g.dispose){delete g.dispose;qx.ui.core.queue.Dispose.flush();}},function(){self.__lj=false;});self.__li=0;},__lk:function(h,i){var self=qx.ui.core.queue.Manager;try{h();}catch(e){{};self.__lg=false;self.__lj=false;self.__li+=1;if(qx.bom.client.Browser.NAME==d&&qx.bom.client.Browser.VERSION<=7){i();}if(self.__li<=self.MAX_RETRIES){self.scheduleFlush();}else{throw new Error("Fatal Error: Flush terminated "+(self.__li-1)+" times in a row"+" due to exceptions in user code. The application has to be reloaded!");}throw e;}finally{i();}},__ll:function(e){var j=qx.ui.core.queue.Manager;if(e.getData()==a){j.PAUSE=true;if(j.__lm){window.clearTimeout(j.__lm);}j.__lm=window.setTimeout(function(){j.PAUSE=false;j.__lm=null;j.flush();},500);}else{j.flush();}}},defer:function(k){k.__ln=new qx.util.DeferredCall(k.flush);qx.html.Element._scheduleFlush=k.scheduleFlush;qx.event.Registration.addListener(window,b,qx.bom.client.Feature.TOUCH?k.__ll:k.flush);}});})();(function(){var a="qx.lang.Object";qx.Class.define(a,{statics:{empty:function(b){{};for(var c in b){if(b.hasOwnProperty(c)){delete b[c];}}},isEmpty:(qx.bom.client.Feature.ECMA_OBJECT_COUNT)?function(d){{};return d.__count__===0;}:function(e){{};for(var f in e){return false;}return true;},hasMinLength:(qx.bom.client.Feature.ECMA_OBJECT_COUNT)?function(g,h){{};return g.__count__>=h;}:function(j,k){{};if(k<=0){return true;}var length=0;for(var m in j){if((++length)>=k){return true;}}return false;},getLength:qx.Bootstrap.objectGetLength,getKeys:qx.Bootstrap.getKeys,getKeysAsString:qx.Bootstrap.getKeysAsString,getValues:function(n){{};var p=[];var o=this.getKeys(n);for(var i=0,l=o.length;i<l;i++){p.push(n[o[i]]);}return p;},mergeWith:qx.Bootstrap.objectMergeWith,carefullyMergeWith:function(q,r){{};return qx.lang.Object.mergeWith(q,r,false);},merge:function(s,t){{};var u=arguments.length;for(var i=1;i<u;i++){qx.lang.Object.mergeWith(s,arguments[i]);}return s;},clone:function(v){{};var w={};for(var x in v){w[x]=v[x];}return w;},invert:function(y){{};var z={};for(var A in y){z[y[A].toString()]=A;}return z;},getKeyFromValue:function(B,C){{};for(var D in B){if(B.hasOwnProperty(D)&&B[D]===C){return D;}}return null;},contains:function(E,F){{};return this.getKeyFromValue(E,F)!==null;},select:function(G,H){{};return H[G];},fromArray:function(I){{};var J={};for(var i=0,l=I.length;i<l;i++){{};J[I[i].toString()]=true;}return J;}}});})();(function(){var b="-",a="qx.event.handler.Element";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(c){qx.core.Object.call(this);this._manager=c;this._registeredEvents={};},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{abort:true,scroll:true,select:true,reset:true,submit:true},TARGET_CHECK:qx.event.IEventHandler.TARGET_DOMNODE,IGNORE_CAN_HANDLE:true},members:{canHandleEvent:function(d,e){},registerEvent:function(f,g,h){var k=qx.core.ObjectRegistry.toHashCode(f);var i=k+b+g;var j=qx.lang.Function.listener(this._onNative,this,i);qx.bom.Event.addNativeListener(f,g,j);this._registeredEvents[i]={element:f,type:g,listener:j};},unregisterEvent:function(l,m,n){var q=this._registeredEvents;if(!q){return;}var r=qx.core.ObjectRegistry.toHashCode(l);var o=r+b+m;var p=this._registeredEvents[o];if(p){qx.bom.Event.removeNativeListener(l,m,p.listener);}delete this._registeredEvents[o];},_onNative:qx.event.GlobalError.observeMethod(function(s,t){var v=this._registeredEvents;if(!v){return;}var u=v[t];qx.event.Registration.fireNonBubblingEvent(u.element,u.type,qx.event.type.Native,[s]);})},destruct:function(){var w;var x=this._registeredEvents;for(var y in x){w=x[y];qx.bom.Event.removeNativeListener(w.element,w.type,w.listener);}this._manager=this._registeredEvents=null;},defer:function(z){qx.event.Registration.addHandler(z);}});})();(function(){var e="orientationchange",d="resize",c="landscape",b="portrait",a="qx.event.handler.Orientation";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(f){qx.core.Object.call(this);this.__hU=f;this.__hV=f.getWindow();this._initObserver();},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{orientationchange:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_WINDOW,IGNORE_CAN_HANDLE:true},members:{__hU:null,__hV:null,__hW:null,__hX:null,__hY:null,canHandleEvent:function(g,h){},registerEvent:function(i,j,k){},unregisterEvent:function(l,m,n){},_initObserver:function(){this.__hY=qx.lang.Function.listener(this._onNative,this);this.__hW=qx.bom.Event.supportsEvent(this.__hV,e)?e:d;var Event=qx.bom.Event;Event.addNativeListener(this.__hV,this.__hW,this.__hY);},_stopObserver:function(){var Event=qx.bom.Event;Event.removeNativeListener(this.__hV,this.__hW,this.__hY);},_onNative:qx.event.GlobalError.observeMethod(function(o){var q=qx.bom.Viewport;var p=q.getOrientation();if(this.__hX!=p){this.__hX=p;var r=q.isLandscape()?c:b;qx.event.Registration.fireEvent(this.__hV,e,qx.event.type.Orientation,[p,r]);}})},destruct:function(){this._stopObserver();this.__hU=this.__hV=null;},defer:function(s){qx.event.Registration.addHandler(s);}});})();(function(){var t="qx.mobile.emulatetouch",s="touchend",r="touchstart",q="touchmove",p="mousemove",o="touchcancel",n="mouseup",m="mousedown",l="qx.client",k="mshtml",d="qx.event.handler.Touch",j="useraction",h="swipe",c="qx.mobile.nativescroll",b="webkit",g="off",f="tap",i="x",a="y";qx.Class.define(d,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(u){qx.core.Object.call(this);this.__hc=u;this.__hd=u.getWindow();this.__he=this.__hd.document;this._initTouchObserver();this._initMouseObserver();},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{touchstart:1,touchmove:1,touchend:1,touchcancel:1,tap:1,swipe:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_DOMNODE+qx.event.IEventHandler.TARGET_DOCUMENT,IGNORE_CAN_HANDLE:true,MOUSE_TO_TOUCH_MAPPING:{"mousedown":"touchstart","mousemove":"touchmove","mouseup":"touchend"},SWIPE_DIRECTION:{x:["left","right"],y:["up","down"]},TAP_MAX_DISTANCE:10,SWIPE_MIN_DISTANCE:11,SWIPE_MIN_VELOCITY:0},members:{__hf:null,__hg:null,__hc:null,__hd:null,__he:null,__hh:null,__hi:null,__hj:null,__hk:null,__hl:false,__hm:null,canHandleEvent:function(v,w){},registerEvent:function(x,y,z){},unregisterEvent:function(A,B,C){},__hn:function(D){var E=qx.bom.Event.getTarget(D);if(qx.core.Variant.isSet(l,b)){if(E&&E.nodeType==3){E=E.parentNode;}}return E;},__ho:function(F,G,H,I){if(!H){H=this.__hn(F);}var G=G||F.type;if(H&&H.nodeType){qx.event.Registration.fireEvent(H,G,I||qx.event.type.Touch,[F,H,null,true,true]);}qx.event.Registration.fireEvent(this.__hd,j,qx.event.type.Data,[G]);},__hp:function(J,K,L){if(!L){L=this.__hn(J);}var K=K||J.type;if(K==r){this.__hq(J,L);}else if(K==q){this.__hr(J,L);}else if(K==s){this.__hs(J,L);}},__hq:function(M,N){var O=M.changedTouches[0];this.__hh=O.screenX;this.__hi=O.screenY;this.__hj=new Date().getTime();this.__hk=M.changedTouches.length===1;},__hr:function(P,Q){if(this.__hk&&P.changedTouches.length>1){this.__hk=false;}},__hs:function(R,S){if(this.__hk){var T=R.changedTouches[0];var V={x:T.screenX-this.__hh,y:T.screenY-this.__hi};var W=qx.event.handler.Touch;if(this.__hm==S&&Math.abs(V.x)<=W.TAP_MAX_DISTANCE&&Math.abs(V.y)<=W.TAP_MAX_DISTANCE){this.__ho(R,f,S,qx.event.type.Tap);}else{var U=this.__ht(R,S,V);if(U){R.swipe=U;this.__ho(R,h,S,qx.event.type.Swipe);}}}},__ht:function(X,Y,ba){var be=qx.event.handler.Touch;var bf=new Date().getTime()-this.__hj;var bh=(Math.abs(ba.x)>=Math.abs(ba.y))?i:a;var bb=ba[bh];var bc=be.SWIPE_DIRECTION[bh][bb<0?0:1];var bg=(bf!==0)?bb/bf:0;var bd=null;if(Math.abs(bg)>=be.SWIPE_MIN_VELOCITY&&Math.abs(bb)>=be.SWIPE_MIN_DISTANCE){bd={startTime:this.__hj,duration:bf,axis:bh,direction:bc,distance:bb,velocity:bg};}return bd;},__hu:qx.core.Variant.select(t,{"on":function(bi){var bj=bi.type;var bl=qx.event.handler.Touch.MOUSE_TO_TOUCH_MAPPING;if(bl[bj]){bj=bl[bj];if(bj==r&&this.__hv(bi)){this.__hl=true;}else if(bj==s){this.__hl=false;}var bm=this.__hw(bi);var bk=(bj==s?[]:[bm]);bi.touches=bk;bi.targetTouches=bk;bi.changedTouches=[bm];}return bj;},"default":qx.lang.Function.empty}),__hv:qx.core.Variant.select(t,{"on":function(bn){if(qx.core.Variant.isSet(l,k)){var bo=1;}else{var bo=0;}return bn.button==bo;},"default":qx.lang.Function.empty}),__hw:qx.core.Variant.select(t,{"on":function(bp){var bq=this.__hn(bp);return {clientX:bp.clientX,clientY:bp.clientY,screenX:bp.screenX,screenY:bp.screenY,pageX:bp.pageX,pageY:bp.pageY,identifier:1,target:bq};},"default":qx.lang.Function.empty}),_initTouchObserver:function(){this.__hf=qx.lang.Function.listener(this._onTouchEvent,this);var Event=qx.bom.Event;Event.addNativeListener(this.__he,r,this.__hf);Event.addNativeListener(this.__he,q,this.__hf);Event.addNativeListener(this.__he,s,this.__hf);Event.addNativeListener(this.__he,o,this.__hf);},_initMouseObserver:qx.core.Variant.select(t,{"on":function(){if(!qx.bom.client.Feature.TOUCH){this.__hg=qx.lang.Function.listener(this._onMouseEvent,this);var Event=qx.bom.Event;Event.addNativeListener(this.__he,m,this.__hg);Event.addNativeListener(this.__he,p,this.__hg);Event.addNativeListener(this.__he,n,this.__hg);}},"default":qx.lang.Function.empty}),_stopTouchObserver:function(){var Event=qx.bom.Event;Event.removeNativeListener(this.__he,r,this.__hf);Event.removeNativeListener(this.__he,q,this.__hf);Event.removeNativeListener(this.__he,s,this.__hf);Event.removeNativeListener(this.__he,o,this.__hf);},_stopMouseObserver:qx.core.Variant.select(t,{"on":function(){if(!qx.bom.client.Feature.TOUCH){var Event=qx.bom.Event;Event.removeNativeListener(this.__he,m,this.__hg);Event.removeNativeListener(this.__he,p,this.__hg);Event.removeNativeListener(this.__he,n,this.__hg);}},"default":qx.lang.Function.empty}),_onTouchEvent:qx.event.GlobalError.observeMethod(function(br){this._commonTouchEventHandler(br);}),_onMouseEvent:qx.core.Variant.select(t,{"on":qx.event.GlobalError.observeMethod(function(bs){if(!qx.bom.client.Feature.TOUCH){if(bs.type==p&&!this.__hl){return;}var bt=this.__hu(bs);this._commonTouchEventHandler(bs,bt);}}),"default":qx.lang.Function.empty}),_commonTouchEventHandler:function(bu,bv){var bv=bv||bu.type;if(bv==r){this.__hm=this.__hn(bu);}this.__ho(bu,bv);this.__hp(bu,bv);}},destruct:function(){this._stopTouchObserver();this._stopMouseObserver();this.__hc=this.__hd=this.__he=this.__hm=null;},defer:function(bw){qx.event.Registration.addHandler(bw);if(qx.bom.client.Feature.TOUCH){if(qx.core.Variant.isSet(c,g)){document.addEventListener(q,function(e){e.preventDefault();});}qx.event.Registration.getManager(document).getHandler(bw);}}});})();(function(){var n="iPod",m="Win32",l="",k="Win64",j="Linux",i="BSD",h="Macintosh",g="iPhone",f="Windows",e="qx.bom.client.Platform",b="iPad",d="X11",c="MacIntel",a="MacPPC";qx.Class.define(e,{statics:{NAME:"",WIN:false,MAC:false,UNIX:false,UNKNOWN_PLATFORM:false,__kH:function(){var o=navigator.platform;if(o==null||o===l){o=navigator.userAgent;}if(o.indexOf(f)!=-1||o.indexOf(m)!=-1||o.indexOf(k)!=-1){this.WIN=true;this.NAME="win";}else if(o.indexOf(h)!=-1||o.indexOf(a)!=-1||o.indexOf(c)!=-1||o.indexOf(n)!=-1||o.indexOf(g)!=-1||o.indexOf(b)!=-1){this.MAC=true;this.NAME="mac";}else if(o.indexOf(d)!=-1||o.indexOf(j)!=-1||o.indexOf(i)!=-1){this.UNIX=true;this.NAME="unix";}else{this.UNKNOWN_PLATFORM=true;this.WIN=true;this.NAME="win";}}},defer:function(p){p.__kH();}});})();(function(){var j="win98",i="osx2",h="osx0",g="osx4",f="win95",e="win2000",d="osx1",c="osx5",b="osx3",a="Windows NT 5.01",I=")",H="winxp",G="freebsd",F="sunos",E="SV1",D="|",C="nintendods",B="winnt4",A="wince",z="winme",q="os9",r="\.",o="osx",p="linux",m="netbsd",n="winvista",k="openbsd",l="(",s="win2003",t="iPad",v="symbian",u="win7",x="g",w="qx.bom.client.System",y=" Mobile/";qx.Bootstrap.define(w,{statics:{NAME:"",SP1:false,SP2:false,WIN95:false,WIN98:false,WINME:false,WINNT4:false,WIN2000:false,WINXP:false,WIN2003:false,WINVISTA:false,WIN7:false,WINCE:false,LINUX:false,SUNOS:false,FREEBSD:false,NETBSD:false,OPENBSD:false,OSX:false,OS9:false,SYMBIAN:false,NINTENDODS:false,PSP:false,IPHONE:false,IPAD:false,UNKNOWN_SYSTEM:false,__lu:{"Windows NT 6.1":u,"Windows NT 6.0":n,"Windows NT 5.2":s,"Windows NT 5.1":H,"Windows NT 5.0":e,"Windows 2000":e,"Windows NT 4.0":B,"Win 9x 4.90":z,"Windows CE":A,"Windows 98":j,"Win98":j,"Windows 95":f,"Win95":f,"Linux":p,"FreeBSD":G,"NetBSD":m,"OpenBSD":k,"SunOS":F,"Symbian System":v,"Nitro":C,"PSP":"sonypsp","Mac OS X 10_5":c,"Mac OS X 10.5":c,"Mac OS X 10_4":g,"Mac OS X 10.4":g,"Mac OS X 10_3":b,"Mac OS X 10.3":b,"Mac OS X 10_2":i,"Mac OS X 10.2":i,"Mac OS X 10_1":d,"Mac OS X 10.1":d,"Mac OS X 10_0":h,"Mac OS X 10.0":h,"Mac OS X":o,"Mac OS 9":q},__lv:function(){var L=navigator.userAgent;var K=[];for(var J in this.__lu){K.push(J);}var M=new RegExp(l+K.join(D).replace(/\./g,r)+I,x);if(!M.test(L)){this.UNKNOWN_SYSTEM=true;if(!qx.bom.client.Platform.UNKNOWN_PLATFORM){if(qx.bom.client.Platform.UNIX){this.NAME="linux";this.LINUX=true;}else if(qx.bom.client.Platform.MAC){this.NAME="osx5";this.OSX=true;}else{this.NAME="winxp";this.WINXP=true;}}else{this.NAME="winxp";this.WINXP=true;}return;}if(qx.bom.client.Engine.WEBKIT&&RegExp(y).test(navigator.userAgent)){if(RegExp(t).test(navigator.userAgent)){this.IPAD=true;this.NAME="ipad";}else{this.IPHONE=true;this.NAME="iphone";}}else{this.NAME=this.__lu[RegExp.$1];this[this.NAME.toUpperCase()]=true;if(qx.bom.client.Platform.WIN){if(L.indexOf(a)!==-1){this.SP1=true;}else if(qx.bom.client.Engine.MSHTML&&L.indexOf(E)!==-1){this.SP2=true;}}}}},defer:function(N){N.__lv();}});})();(function(){var p="mouseup",o="click",n="qx.client",m="mousedown",l="contextmenu",k="mousewheel",j="dblclick",h="mouseover",g="mouseout",f="mousemove",c="on",e="useraction",d="DOMMouseScroll",b="gecko|webkit",a="qx.event.handler.Mouse";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(q){qx.core.Object.call(this);this.__eD=q;this.__eE=q.getWindow();this.__eF=this.__eE.document;this._initButtonObserver();this._initMoveObserver();this._initWheelObserver();},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{mousemove:1,mouseover:1,mouseout:1,mousedown:1,mouseup:1,click:1,dblclick:1,contextmenu:1,mousewheel:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_DOMNODE,IGNORE_CAN_HANDLE:true},members:{__eG:null,__eH:null,__eI:null,__eJ:null,__eK:null,__eD:null,__eE:null,__eF:null,canHandleEvent:function(r,s){},registerEvent:qx.bom.client.System.IPHONE?function(t,u,v){t[c+u]=qx.lang.Function.returnNull;}:qx.lang.Function.returnNull,unregisterEvent:qx.bom.client.System.IPHONE?function(w,x,y){w[c+x]=undefined;}:qx.lang.Function.returnNull,__eL:function(z,A,B){if(!B){B=qx.bom.Event.getTarget(z);}if(B&&B.nodeType){qx.event.Registration.fireEvent(B,A||z.type,A==k?qx.event.type.MouseWheel:qx.event.type.Mouse,[z,B,null,true,true]);}qx.event.Registration.fireEvent(this.__eE,e,qx.event.type.Data,[A||z.type]);},__eM:function(){var D=[this.__eE,this.__eF,this.__eF.body];var E=this.__eE;var C=d;for(var i=0;i<D.length;i++){if(qx.bom.Event.supportsEvent(D[i],k)){C=k;E=D[i];break;}}return {type:C,target:E};},_initButtonObserver:function(){this.__eG=qx.lang.Function.listener(this._onButtonEvent,this);var Event=qx.bom.Event;Event.addNativeListener(this.__eF,m,this.__eG);Event.addNativeListener(this.__eF,p,this.__eG);Event.addNativeListener(this.__eF,o,this.__eG);Event.addNativeListener(this.__eF,j,this.__eG);Event.addNativeListener(this.__eF,l,this.__eG);},_initMoveObserver:function(){this.__eH=qx.lang.Function.listener(this._onMoveEvent,this);var Event=qx.bom.Event;Event.addNativeListener(this.__eF,f,this.__eH);Event.addNativeListener(this.__eF,h,this.__eH);Event.addNativeListener(this.__eF,g,this.__eH);},_initWheelObserver:function(){this.__eI=qx.lang.Function.listener(this._onWheelEvent,this);var F=this.__eM();qx.bom.Event.addNativeListener(F.target,F.type,this.__eI);},_stopButtonObserver:function(){var Event=qx.bom.Event;Event.removeNativeListener(this.__eF,m,this.__eG);Event.removeNativeListener(this.__eF,p,this.__eG);Event.removeNativeListener(this.__eF,o,this.__eG);Event.removeNativeListener(this.__eF,j,this.__eG);Event.removeNativeListener(this.__eF,l,this.__eG);},_stopMoveObserver:function(){var Event=qx.bom.Event;Event.removeNativeListener(this.__eF,f,this.__eH);Event.removeNativeListener(this.__eF,h,this.__eH);Event.removeNativeListener(this.__eF,g,this.__eH);},_stopWheelObserver:function(){var G=this.__eM();qx.bom.Event.removeNativeListener(G.target,G.type,this.__eI);},_onMoveEvent:qx.event.GlobalError.observeMethod(function(H){this.__eL(H);}),_onButtonEvent:qx.event.GlobalError.observeMethod(function(I){var J=I.type;var K=qx.bom.Event.getTarget(I);if(qx.core.Variant.isSet(n,b)){if(K&&K.nodeType==3){K=K.parentNode;}}if(this.__eN){this.__eN(I,J,K);}if(this.__eP){this.__eP(I,J,K);}this.__eL(I,J,K);if(this.__eO){this.__eO(I,J,K);}if(this.__eQ){this.__eQ(I,J,K);}this.__eJ=J;}),_onWheelEvent:qx.event.GlobalError.observeMethod(function(L){this.__eL(L,k);}),__eN:qx.core.Variant.select(n,{"webkit":function(M,N,O){if(qx.bom.client.Engine.VERSION<530){if(N==l){this.__eL(M,p,O);}}},"default":null}),__eO:qx.core.Variant.select(n,{"opera":function(P,Q,R){if(Q==p&&P.button==2){this.__eL(P,l,R);}},"default":null}),__eP:qx.core.Variant.select(n,{"mshtml":function(S,T,U){if(S.target!==undefined){return;}if(T==p&&this.__eJ==o){this.__eL(S,m,U);}else if(T==j){this.__eL(S,o,U);}},"default":null}),__eQ:qx.core.Variant.select(n,{"mshtml":null,"default":function(V,W,X){switch(W){case m:this.__eK=X;break;case p:if(X!==this.__eK){var Y=qx.dom.Hierarchy.getCommonParent(X,this.__eK);this.__eL(V,o,Y);}}}})},destruct:function(){this._stopButtonObserver();this._stopMoveObserver();this._stopWheelObserver();this.__eD=this.__eE=this.__eF=this.__eK=null;},defer:function(ba){qx.event.Registration.addHandler(ba);}});})();(function(){var m="keydown",l="qx.client",k="keypress",j="NumLock",i="keyup",h="Enter",g="0",f="9",e="-",d="PageUp",bu="+",bt="PrintScreen",bs="gecko",br="A",bq="Z",bp="Left",bo="F5",bn="Down",bm="Up",bl="F11",t="F6",u="useraction",r="F3",s="keyinput",p="Insert",q="F8",n="End",o="/",B="Delete",C="*",O="cmd",K="F1",W="F4",R="Home",bh="F2",bc="F12",G="PageDown",bk="F7",bj="Win",bi="F9",F="F10",I="Right",J="text",M="Escape",P="webkit",S="5",Y="3",be="Meta",v="7",w="CapsLock",H="input",V="Control",U="Space",T="Tab",bb="Shift",ba="Pause",Q="Unidentified",X="qx.event.handler.Keyboard",a="mshtml|webkit",bd="6",x="off",y="Apps",L="4",b="Alt",c="mshtml",E="2",z="Scroll",A="1",D="8",N="autoComplete",bg=",",bf="Backspace";qx.Class.define(X,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(bv){qx.core.Object.call(this);this.__gO=bv;this.__gP=bv.getWindow();if(qx.core.Variant.isSet(l,bs)){this.__gQ=this.__gP;}else{this.__gQ=this.__gP.document.documentElement;}this.__gR={};this._initKeyObserver();},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{keyup:1,keydown:1,keypress:1,keyinput:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_DOMNODE,IGNORE_CAN_HANDLE:true,isValidKeyIdentifier:function(bw){if(this._identifierToKeyCodeMap[bw]){return true;}if(bw.length!=1){return false;}if(bw>=g&&bw<=f){return true;}if(bw>=br&&bw<=bq){return true;}switch(bw){case bu:case e:case C:case o:return true;default:return false;}}},members:{__gS:null,__gO:null,__gP:null,__gQ:null,__gR:null,__gT:null,__gU:null,__gV:null,canHandleEvent:function(bx,by){},registerEvent:function(bz,bA,bB){},unregisterEvent:function(bC,bD,bE){},_fireInputEvent:function(bF,bG){var bH=this.__gW();if(bH&&bH.offsetWidth!=0){var event=qx.event.Registration.createEvent(s,qx.event.type.KeyInput,[bF,bH,bG]);this.__gO.dispatchEvent(bH,event);}if(this.__gP){qx.event.Registration.fireEvent(this.__gP,u,qx.event.type.Data,[s]);}},_fireSequenceEvent:function(bI,bJ,bK){var bL=this.__gW();var bM=bI.keyCode;var event=qx.event.Registration.createEvent(bJ,qx.event.type.KeySequence,[bI,bL,bK]);this.__gO.dispatchEvent(bL,event);if(qx.core.Variant.isSet(l,a)){if(bJ==m&&event.getDefaultPrevented()){if(!this._isNonPrintableKeyCode(bM)&&!this._emulateKeyPress[bM]){this._fireSequenceEvent(bI,k,bK);}}}if(this.__gP){qx.event.Registration.fireEvent(this.__gP,u,qx.event.type.Data,[bJ]);}},__gW:function(){var bN=this.__gO.getHandler(qx.event.handler.Focus);var bO=bN.getActive();if(!bO||bO.offsetWidth==0){bO=bN.getFocus();}if(!bO||bO.offsetWidth==0){bO=this.__gO.getWindow().document.body;}return bO;},_initKeyObserver:function(){this.__gS=qx.lang.Function.listener(this.__gX,this);this.__gV=qx.lang.Function.listener(this.__ha,this);var Event=qx.bom.Event;Event.addNativeListener(this.__gQ,i,this.__gS);Event.addNativeListener(this.__gQ,m,this.__gS);Event.addNativeListener(this.__gQ,k,this.__gV);},_stopKeyObserver:function(){var Event=qx.bom.Event;Event.removeNativeListener(this.__gQ,i,this.__gS);Event.removeNativeListener(this.__gQ,m,this.__gS);Event.removeNativeListener(this.__gQ,k,this.__gV);for(var bQ in (this.__gU||{})){var bP=this.__gU[bQ];Event.removeNativeListener(bP.target,k,bP.callback);}delete (this.__gU);},__gX:qx.event.GlobalError.observeMethod(qx.core.Variant.select(l,{"mshtml":function(bR){bR=window.event||bR;var bU=bR.keyCode;var bS=0;var bT=bR.type;if(!(this.__gR[bU]==m&&bT==m)){this._idealKeyHandler(bU,bS,bT,bR);}if(bT==m){if(this._isNonPrintableKeyCode(bU)||this._emulateKeyPress[bU]){this._idealKeyHandler(bU,bS,k,bR);}}this.__gR[bU]=bT;},"gecko":function(bV){var ca=this._keyCodeFix[bV.keyCode]||bV.keyCode;var bX=0;var bY=bV.type;if(qx.bom.client.Platform.WIN){var bW=ca?this._keyCodeToIdentifier(ca):this._charCodeToIdentifier(bX);if(!(this.__gR[bW]==m&&bY==m)){this._idealKeyHandler(ca,bX,bY,bV);}this.__gR[bW]=bY;}else{this._idealKeyHandler(ca,bX,bY,bV);}this.__gY(bV.target,bY,ca);},"webkit":function(cb){var ce=0;var cc=0;var cd=cb.type;if(qx.bom.client.Engine.VERSION<525.13){if(cd==i||cd==m){ce=this._charCode2KeyCode[cb.charCode]||cb.keyCode;}else{if(this._charCode2KeyCode[cb.charCode]){ce=this._charCode2KeyCode[cb.charCode];}else{cc=cb.charCode;}}this._idealKeyHandler(ce,cc,cd,cb);}else{ce=cb.keyCode;this._idealKeyHandler(ce,cc,cd,cb);if(cd==m){if(this._isNonPrintableKeyCode(ce)||this._emulateKeyPress[ce]){this._idealKeyHandler(ce,cc,k,cb);}}this.__gR[ce]=cd;}},"opera":function(cf){this.__gT=cf.keyCode;this._idealKeyHandler(cf.keyCode,0,cf.type,cf);}})),__gY:qx.core.Variant.select(l,{"gecko":function(cg,ch,ci){if(ch===m&&(ci==33||ci==34||ci==38||ci==40)&&cg.type==J&&cg.tagName.toLowerCase()===H&&cg.getAttribute(N)!==x){if(!this.__gU){this.__gU={};}var ck=qx.core.ObjectRegistry.toHashCode(cg);if(this.__gU[ck]){return;}var self=this;this.__gU[ck]={target:cg,callback:function(cl){qx.bom.Event.stopPropagation(cl);self.__ha(cl);}};var cj=qx.event.GlobalError.observeMethod(this.__gU[ck].callback);qx.bom.Event.addNativeListener(cg,k,cj);}},"default":null}),__ha:qx.event.GlobalError.observeMethod(qx.core.Variant.select(l,{"mshtml":function(cm){cm=window.event||cm;if(this._charCode2KeyCode[cm.keyCode]){this._idealKeyHandler(this._charCode2KeyCode[cm.keyCode],0,cm.type,cm);}else{this._idealKeyHandler(0,cm.keyCode,cm.type,cm);}},"gecko":function(cn){var cq=this._keyCodeFix[cn.keyCode]||cn.keyCode;var co=cn.charCode;var cp=cn.type;this._idealKeyHandler(cq,co,cp,cn);},"webkit":function(cr){if(qx.bom.client.Engine.VERSION<525.13){var cu=0;var cs=0;var ct=cr.type;if(ct==i||ct==m){cu=this._charCode2KeyCode[cr.charCode]||cr.keyCode;}else{if(this._charCode2KeyCode[cr.charCode]){cu=this._charCode2KeyCode[cr.charCode];}else{cs=cr.charCode;}}this._idealKeyHandler(cu,cs,ct,cr);}else{if(this._charCode2KeyCode[cr.keyCode]){this._idealKeyHandler(this._charCode2KeyCode[cr.keyCode],0,cr.type,cr);}else{this._idealKeyHandler(0,cr.keyCode,cr.type,cr);}}},"opera":function(cv){var cx=cv.keyCode;var cw=cv.type;if(cx!=this.__gT){this._idealKeyHandler(0,this.__gT,cw,cv);}else{if(this._keyCodeToIdentifierMap[cv.keyCode]){this._idealKeyHandler(cv.keyCode,0,cv.type,cv);}else{this._idealKeyHandler(0,cv.keyCode,cv.type,cv);}}}})),_idealKeyHandler:function(cy,cz,cA,cB){var cC;if(cy||(!cy&&!cz)){cC=this._keyCodeToIdentifier(cy);this._fireSequenceEvent(cB,cA,cC);}else{cC=this._charCodeToIdentifier(cz);this._fireSequenceEvent(cB,k,cC);this._fireInputEvent(cB,cz);}},_specialCharCodeMap:{8:bf,9:T,13:h,27:M,32:U},_emulateKeyPress:qx.core.Variant.select(l,{"mshtml":{8:true,9:true},"webkit":{8:true,9:true,27:true},"default":{}}),_keyCodeToIdentifierMap:{16:bb,17:V,18:b,20:w,224:be,37:bp,38:bm,39:I,40:bn,33:d,34:G,35:n,36:R,45:p,46:B,112:K,113:bh,114:r,115:W,116:bo,117:t,118:bk,119:q,120:bi,121:F,122:bl,123:bc,144:j,44:bt,145:z,19:ba,91:qx.bom.client.Platform.MAC?O:bj,92:bj,93:qx.bom.client.Platform.MAC?O:y},_numpadToCharCode:{96:g.charCodeAt(0),97:A.charCodeAt(0),98:E.charCodeAt(0),99:Y.charCodeAt(0),100:L.charCodeAt(0),101:S.charCodeAt(0),102:bd.charCodeAt(0),103:v.charCodeAt(0),104:D.charCodeAt(0),105:f.charCodeAt(0),106:C.charCodeAt(0),107:bu.charCodeAt(0),109:e.charCodeAt(0),110:bg.charCodeAt(0),111:o.charCodeAt(0)},_charCodeA:br.charCodeAt(0),_charCodeZ:bq.charCodeAt(0),_charCode0:g.charCodeAt(0),_charCode9:f.charCodeAt(0),_isNonPrintableKeyCode:function(cD){return this._keyCodeToIdentifierMap[cD]?true:false;},_isIdentifiableKeyCode:function(cE){if(cE>=this._charCodeA&&cE<=this._charCodeZ){return true;}if(cE>=this._charCode0&&cE<=this._charCode9){return true;}if(this._specialCharCodeMap[cE]){return true;}if(this._numpadToCharCode[cE]){return true;}if(this._isNonPrintableKeyCode(cE)){return true;}return false;},_keyCodeToIdentifier:function(cF){if(this._isIdentifiableKeyCode(cF)){var cG=this._numpadToCharCode[cF];if(cG){return String.fromCharCode(cG);}return (this._keyCodeToIdentifierMap[cF]||this._specialCharCodeMap[cF]||String.fromCharCode(cF));}else{return Q;}},_charCodeToIdentifier:function(cH){return this._specialCharCodeMap[cH]||String.fromCharCode(cH).toUpperCase();},_identifierToKeyCode:function(cI){return qx.event.handler.Keyboard._identifierToKeyCodeMap[cI]||cI.charCodeAt(0);}},destruct:function(){this._stopKeyObserver();this.__gT=this.__gO=this.__gP=this.__gQ=this.__gR=null;},defer:function(cJ,cK){qx.event.Registration.addHandler(cJ);if(!cJ._identifierToKeyCodeMap){cJ._identifierToKeyCodeMap={};for(var cL in cK._keyCodeToIdentifierMap){cJ._identifierToKeyCodeMap[cK._keyCodeToIdentifierMap[cL]]=parseInt(cL,10);}for(var cL in cK._specialCharCodeMap){cJ._identifierToKeyCodeMap[cK._specialCharCodeMap[cL]]=parseInt(cL,10);}}if(qx.core.Variant.isSet(l,c)){cK._charCode2KeyCode={13:13,27:27};}else if(qx.core.Variant.isSet(l,bs)){cK._keyCodeFix={12:cK._identifierToKeyCode(j)};}else if(qx.core.Variant.isSet(l,P)){if(qx.bom.client.Engine.VERSION<525.13){cK._charCode2KeyCode={63289:cK._identifierToKeyCode(j),63276:cK._identifierToKeyCode(d),63277:cK._identifierToKeyCode(G),63275:cK._identifierToKeyCode(n),63273:cK._identifierToKeyCode(R),63234:cK._identifierToKeyCode(bp),63232:cK._identifierToKeyCode(bm),63235:cK._identifierToKeyCode(I),63233:cK._identifierToKeyCode(bn),63272:cK._identifierToKeyCode(B),63302:cK._identifierToKeyCode(p),63236:cK._identifierToKeyCode(K),63237:cK._identifierToKeyCode(bh),63238:cK._identifierToKeyCode(r),63239:cK._identifierToKeyCode(W),63240:cK._identifierToKeyCode(bo),63241:cK._identifierToKeyCode(t),63242:cK._identifierToKeyCode(bk),63243:cK._identifierToKeyCode(q),63244:cK._identifierToKeyCode(bi),63245:cK._identifierToKeyCode(F),63246:cK._identifierToKeyCode(bl),63247:cK._identifierToKeyCode(bc),63248:cK._identifierToKeyCode(bt),3:cK._identifierToKeyCode(h),12:cK._identifierToKeyCode(j),13:cK._identifierToKeyCode(h)};}else{cK._charCode2KeyCode={13:13,27:27};}}}});})();(function(){var a="qx.event.handler.Capture";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventHandler,statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{capture:true,losecapture:true},TARGET_CHECK:qx.event.IEventHandler.TARGET_DOMNODE,IGNORE_CAN_HANDLE:true},members:{canHandleEvent:function(b,c){},registerEvent:function(d,e,f){},unregisterEvent:function(g,h,i){}},defer:function(j){qx.event.Registration.addHandler(j);}});})();(function(){var k="alias",j="copy",i="blur",h="mouseout",g="keydown",f="Ctrl",d="Shift",c="mousemove",b="move",a="mouseover",A="Alt",z="keyup",y="mouseup",x="dragend",w="on",v="mousedown",u="qxDraggable",t="drag",s="drop",r="qxDroppable",p="qx.event.handler.DragDrop",q="droprequest",n="dragstart",o="dragchange",l="dragleave",m="dragover";qx.Class.define(p,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(B){qx.core.Object.call(this);this.__jt=B;this.__ju=B.getWindow().document.documentElement;this.__jt.addListener(this.__ju,v,this._onMouseDown,this);this.__jG();},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{dragstart:1,dragend:1,dragover:1,dragleave:1,drop:1,drag:1,dragchange:1,droprequest:1},IGNORE_CAN_HANDLE:true},members:{__jt:null,__ju:null,__jv:null,__jw:null,__jx:null,__jy:null,__jz:null,__jA:null,__jB:null,__jC:null,__jD:false,__jE:0,__jF:0,canHandleEvent:function(C,D){},registerEvent:function(E,F,G){},unregisterEvent:function(H,I,J){},addType:function(K){this.__jx[K]=true;},addAction:function(L){this.__jy[L]=true;},supportsType:function(M){return !!this.__jx[M];},supportsAction:function(N){return !!this.__jy[N];},getData:function(O){if(!this.__jN||!this.__jv){throw new Error("This method must not be used outside the drop event listener!");}if(!this.__jx[O]){throw new Error("Unsupported data type: "+O+"!");}if(!this.__jA[O]){this.__jB=O;this.__jI(q,this.__jw,this.__jv,false);}if(!this.__jA[O]){throw new Error("Please use a droprequest listener to the drag source to fill the manager with data!");}return this.__jA[O]||null;},getCurrentAction:function(){return this.__jC;},addData:function(P,Q){this.__jA[P]=Q;},getCurrentType:function(){return this.__jB;},isSessionActive:function(){return this.__jD;},__jG:function(){this.__jx={};this.__jy={};this.__jz={};this.__jA={};},__jH:function(){if(this.__jw==null){return;}var T=this.__jy;var R=this.__jz;var S=null;if(this.__jN){if(R.Shift&&R.Ctrl&&T.alias){S=k;}else if(R.Shift&&R.Alt&&T.copy){S=j;}else if(R.Shift&&T.move){S=b;}else if(R.Alt&&T.alias){S=k;}else if(R.Ctrl&&T.copy){S=j;}else if(T.move){S=b;}else if(T.copy){S=j;}else if(T.alias){S=k;}}if(S!=this.__jC){this.__jC=S;this.__jI(o,this.__jw,this.__jv,false);}},__jI:function(U,V,W,X,Y){var bb=qx.event.Registration;var ba=bb.createEvent(U,qx.event.type.Drag,[X,Y]);if(V!==W){ba.setRelatedTarget(W);}return bb.dispatchEvent(V,ba);},__jJ:function(bc){while(bc&&bc.nodeType==1){if(bc.getAttribute(u)==w){return bc;}bc=bc.parentNode;}return null;},__jK:function(bd){while(bd&&bd.nodeType==1){if(bd.getAttribute(r)==w){return bd;}bd=bd.parentNode;}return null;},__jL:function(){this.__jw=null;this.__jt.removeListener(this.__ju,c,this._onMouseMove,this,true);this.__jt.removeListener(this.__ju,y,this._onMouseUp,this,true);qx.event.Registration.removeListener(window,i,this._onWindowBlur,this);this.__jG();},__jM:function(){if(this.__jD){this.__jt.removeListener(this.__ju,a,this._onMouseOver,this,true);this.__jt.removeListener(this.__ju,h,this._onMouseOut,this,true);this.__jt.removeListener(this.__ju,g,this._onKeyDown,this,true);this.__jt.removeListener(this.__ju,z,this._onKeyUp,this,true);this.__jI(x,this.__jw,this.__jv,false);this.__jD=false;}this.__jN=false;this.__jv=null;this.__jL();},__jN:false,_onWindowBlur:function(e){this.__jM();},_onKeyDown:function(e){var be=e.getKeyIdentifier();switch(be){case A:case f:case d:if(!this.__jz[be]){this.__jz[be]=true;this.__jH();}}},_onKeyUp:function(e){var bf=e.getKeyIdentifier();switch(bf){case A:case f:case d:if(this.__jz[bf]){this.__jz[bf]=false;this.__jH();}}},_onMouseDown:function(e){if(this.__jD){return;}var bg=this.__jJ(e.getTarget());if(bg){this.__jE=e.getDocumentLeft();this.__jF=e.getDocumentTop();this.__jw=bg;this.__jt.addListener(this.__ju,c,this._onMouseMove,this,true);this.__jt.addListener(this.__ju,y,this._onMouseUp,this,true);qx.event.Registration.addListener(window,i,this._onWindowBlur,this);}},_onMouseUp:function(e){if(this.__jN){this.__jI(s,this.__jv,this.__jw,false,e);}if(this.__jD){e.stopPropagation();}this.__jM();},_onMouseMove:function(e){if(this.__jD){if(!this.__jI(t,this.__jw,this.__jv,true,e)){this.__jM();}}else{if(Math.abs(e.getDocumentLeft()-this.__jE)>3||Math.abs(e.getDocumentTop()-this.__jF)>3){if(this.__jI(n,this.__jw,this.__jv,true,e)){this.__jD=true;this.__jt.addListener(this.__ju,a,this._onMouseOver,this,true);this.__jt.addListener(this.__ju,h,this._onMouseOut,this,true);this.__jt.addListener(this.__ju,g,this._onKeyDown,this,true);this.__jt.addListener(this.__ju,z,this._onKeyUp,this,true);var bh=this.__jz;bh.Ctrl=e.isCtrlPressed();bh.Shift=e.isShiftPressed();bh.Alt=e.isAltPressed();this.__jH();}else{this.__jI(x,this.__jw,this.__jv,false);this.__jL();}}}},_onMouseOver:function(e){var bi=e.getTarget();var bj=this.__jK(bi);if(bj&&bj!=this.__jv){this.__jN=this.__jI(m,bj,this.__jw,true,e);this.__jv=bj;this.__jH();}},_onMouseOut:function(e){var bl=this.__jK(e.getTarget());var bk=this.__jK(e.getRelatedTarget());if(bl&&bl!==bk&&bl==this.__jv){this.__jI(l,this.__jv,bk,false,e);this.__jv=null;this.__jN=false;qx.event.Timer.once(this.__jH,this,0);}}},destruct:function(){this.__jw=this.__jv=this.__jt=this.__ju=this.__jx=this.__jy=this.__jz=this.__jA=null;},defer:function(bm){qx.event.Registration.addHandler(bm);}});})();(function(){var c="qx.event.handler.Appear",b="disappear",a="appear";qx.Class.define(c,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(d){qx.core.Object.call(this);this.__cl=d;this.__cm={};qx.event.handler.Appear.__cn[this.$$hash]=this;},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{appear:true,disappear:true},TARGET_CHECK:qx.event.IEventHandler.TARGET_DOMNODE,IGNORE_CAN_HANDLE:true,__cn:{},refresh:function(){var e=this.__cn;for(var f in e){e[f].refresh();}}},members:{__cl:null,__cm:null,canHandleEvent:function(g,h){},registerEvent:function(i,j,k){var l=qx.core.ObjectRegistry.toHashCode(i)+j;var m=this.__cm;if(m&&!m[l]){m[l]=i;i.$$displayed=i.offsetWidth>0;}},unregisterEvent:function(n,o,p){var q=qx.core.ObjectRegistry.toHashCode(n)+o;var r=this.__cm;if(!r){return;}if(r[q]){delete r[q];}},refresh:function(){var v=this.__cm;var w;for(var u in v){w=v[u];var s=w.offsetWidth>0;if((!!w.$$displayed)!==s){w.$$displayed=s;var t=qx.event.Registration.createEvent(s?a:b);this.__cl.dispatchEvent(w,t);}}}},destruct:function(){this.__cl=this.__cm=null;delete qx.event.handler.Appear.__cn[this.$$hash];},defer:function(x){qx.event.Registration.addHandler(x);}});})();(function(){var b="abstract",a="qx.event.dispatch.AbstractBubbling";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventDispatcher,type:b,construct:function(c){this._manager=c;},members:{_getParent:function(d){throw new Error("Missing implementation");},canDispatchEvent:function(e,event,f){return event.getBubbles();},dispatchEvent:function(g,event,h){var parent=g;var s=this._manager;var p,w;var n;var r,u;var t;var v=[];p=s.getListeners(g,h,true);w=s.getListeners(g,h,false);if(p){v.push(p);}if(w){v.push(w);}var parent=this._getParent(g);var l=[];var k=[];var m=[];var q=[];while(parent!=null){p=s.getListeners(parent,h,true);if(p){m.push(p);q.push(parent);}w=s.getListeners(parent,h,false);if(w){l.push(w);k.push(parent);}parent=this._getParent(parent);}event.setEventPhase(qx.event.type.Event.CAPTURING_PHASE);for(var i=m.length-1;i>=0;i--){t=q[i];event.setCurrentTarget(t);n=m[i];for(var j=0,o=n.length;j<o;j++){r=n[j];u=r.context||t;r.handler.call(u,event);}if(event.getPropagationStopped()){return;}}event.setEventPhase(qx.event.type.Event.AT_TARGET);event.setCurrentTarget(g);for(var i=0,x=v.length;i<x;i++){n=v[i];for(var j=0,o=n.length;j<o;j++){r=n[j];u=r.context||g;r.handler.call(u,event);}if(event.getPropagationStopped()){return;}}event.setEventPhase(qx.event.type.Event.BUBBLING_PHASE);for(var i=0,x=l.length;i<x;i++){t=k[i];event.setCurrentTarget(t);n=l[i];for(var j=0,o=n.length;j<o;j++){r=n[j];u=r.context||t;r.handler.call(u,event);}if(event.getPropagationStopped()){return;}}}}});})();(function(){var a="qx.event.dispatch.DomBubbling";qx.Class.define(a,{extend:qx.event.dispatch.AbstractBubbling,statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL},members:{_getParent:function(b){return b.parentNode;},canDispatchEvent:function(c,event,d){return c.nodeType!==undefined&&event.getBubbles();}},defer:function(e){qx.event.Registration.addDispatcher(e);}});})();(function(){var q="mshtml",p="",o="qx.client",n=" ",m=">",k="<",h="='",g="none",f="<INPUT TYPE='RADIO' NAME='RADIOTEST' VALUE='Second Choice'>",d="qx.bom.Element",a="' ",c="div",b="></";qx.Class.define(d,{statics:{__kI:{"onload":true,"onpropertychange":true,"oninput":true,"onchange":true,"name":true,"type":true,"checked":true,"disabled":true},__kJ:{},__kK:{},allowCreationWithMarkup:function(r){if(!r){r=window;}var s=r.location.href;if(qx.bom.Element.__kK[s]==undefined){try{r.document.createElement(f);qx.bom.Element.__kK[s]=true;}catch(e){qx.bom.Element.__kK[s]=false;}}return qx.bom.Element.__kK[s];},getHelperElement:function(t){if(!t){t=window;}var v=t.location.href;if(!qx.bom.Element.__kJ[v]){var u=qx.bom.Element.__kJ[v]=t.document.createElement(c);if(qx.bom.client.Engine.WEBKIT){u.style.display=g;t.document.body.appendChild(u);}}return qx.bom.Element.__kJ[v];},create:function(name,w,x){if(!x){x=window;}if(!name){throw new Error("The tag name is missing!");}var z=this.__kI;var y=p;for(var B in w){if(z[B]){y+=B+h+w[B]+a;}}var C;if(y!=p){if(qx.bom.Element.allowCreationWithMarkup(x)){C=x.document.createElement(k+name+n+y+m);}else{var A=qx.bom.Element.getHelperElement(x);A.innerHTML=k+name+n+y+b+name+m;C=A.firstChild;}}else{C=x.document.createElement(name);}for(var B in w){if(!z[B]){qx.bom.element.Attribute.set(C,B,w[B]);}}return C;},empty:function(D){return D.innerHTML=p;},addListener:function(E,F,G,self,H){return qx.event.Registration.addListener(E,F,G,self,H);},removeListener:function(I,J,K,self,L){return qx.event.Registration.removeListener(I,J,K,self,L);},removeListenerById:function(M,N){return qx.event.Registration.removeListenerById(M,N);},hasListener:function(O,P,Q){return qx.event.Registration.hasListener(O,P,Q);},focus:function(R){qx.event.Registration.getManager(R).getHandler(qx.event.handler.Focus).focus(R);},blur:function(S){qx.event.Registration.getManager(S).getHandler(qx.event.handler.Focus).blur(S);},activate:function(T){qx.event.Registration.getManager(T).getHandler(qx.event.handler.Focus).activate(T);},deactivate:function(U){qx.event.Registration.getManager(U).getHandler(qx.event.handler.Focus).deactivate(U);},capture:function(V,W){qx.event.Registration.getManager(V).getDispatcher(qx.event.dispatch.MouseCapture).activateCapture(V,W);},releaseCapture:function(X){qx.event.Registration.getManager(X).getDispatcher(qx.event.dispatch.MouseCapture).releaseCapture(X);},matchesSelector:function(Y,ba){if(ba){return qx.bom.Selector.query(ba,Y.parentNode).length>0;}else{return false;}},clone:function(bb,bc){var bf;if(bc||(qx.core.Variant.isSet(o,q)&&!qx.xml.Document.isXmlDocument(bb))){var bj=qx.event.Registration.getManager(bb);var bd=qx.dom.Hierarchy.getDescendants(bb);bd.push(bb);}if(qx.core.Variant.isSet(o,q)){for(var i=0,l=bd.length;i<l;i++){bj.toggleAttachedEvents(bd[i],false);}}var bf=bb.cloneNode(true);if(qx.core.Variant.isSet(o,q)){for(var i=0,l=bd.length;i<l;i++){bj.toggleAttachedEvents(bd[i],true);}}if(bc===true){var bm=qx.dom.Hierarchy.getDescendants(bf);bm.push(bf);var be,bh,bl,bg;for(var i=0,bk=bd.length;i<bk;i++){bl=bd[i];be=bj.serializeListeners(bl);if(be.length>0){bh=bm[i];for(var j=0,bi=be.length;j<bi;j++){bg=be[j];bj.addListener(bh,bg.type,bg.handler,bg.self,bg.capture);}}}}return bf;}}});})();(function(){var a="qx.event.type.Native";qx.Class.define(a,{extend:qx.event.type.Event,members:{init:function(b,c,d,e,f){qx.event.type.Event.prototype.init.call(this,e,f);this._target=c||qx.bom.Event.getTarget(b);this._relatedTarget=d||qx.bom.Event.getRelatedTarget(b);if(b.timeStamp){this._timeStamp=b.timeStamp;}this._native=b;this._returnValue=null;return this;},clone:function(g){var h=qx.event.type.Event.prototype.clone.call(this,g);var i={};h._native=this._cloneNativeEvent(this._native,i);h._returnValue=this._returnValue;return h;},_cloneNativeEvent:function(j,k){k.preventDefault=qx.lang.Function.empty;return k;},preventDefault:function(){qx.event.type.Event.prototype.preventDefault.call(this);qx.bom.Event.preventDefault(this._native);},getNativeEvent:function(){return this._native;},setReturnValue:function(l){this._returnValue=l;},getReturnValue:function(){return this._returnValue;}},destruct:function(){this._native=this._returnValue=null;}});})();(function(){var b="qx.client",a="qx.bom.Viewport";qx.Class.define(a,{statics:{getWidth:qx.core.Variant.select(b,{"opera":function(c){if(qx.bom.client.Engine.VERSION<9.5){return (c||window).document.body.clientWidth;}else{var d=(c||window).document;return qx.bom.Document.isStandardMode(c)?d.documentElement.clientWidth:d.body.clientWidth;}},"webkit":function(e){if(qx.bom.client.Engine.VERSION<523.15){return (e||window).innerWidth;}else{var f=(e||window).document;return qx.bom.Document.isStandardMode(e)?f.documentElement.clientWidth:f.body.clientWidth;}},"default":function(g){var h=(g||window).document;return qx.bom.Document.isStandardMode(g)?h.documentElement.clientWidth:h.body.clientWidth;}}),getHeight:qx.core.Variant.select(b,{"opera":function(i){if(qx.bom.client.Engine.VERSION<9.5){return (i||window).document.body.clientHeight;}else{var j=(i||window).document;return qx.bom.Document.isStandardMode(i)?j.documentElement.clientHeight:j.body.clientHeight;}},"webkit":function(k){if(qx.bom.client.Engine.VERSION<523.15){return (k||window).innerHeight;}else{var l=(k||window).document;return qx.bom.Document.isStandardMode(k)?l.documentElement.clientHeight:l.body.clientHeight;}},"default":function(m){var n=(m||window).document;return qx.bom.Document.isStandardMode(m)?n.documentElement.clientHeight:n.body.clientHeight;}}),getScrollLeft:qx.core.Variant.select(b,{"mshtml":function(o){var p=(o||window).document;return p.documentElement.scrollLeft||p.body.scrollLeft;},"default":function(q){return (q||window).pageXOffset;}}),getScrollTop:qx.core.Variant.select(b,{"mshtml":function(r){var s=(r||window).document;return s.documentElement.scrollTop||s.body.scrollTop;},"default":function(t){return (t||window).pageYOffset;}}),getOrientation:function(u){var v=(u||window).orientation;if(v==null){v=this.getWidth(u)>this.getHeight(u)?90:0;}return v;},isLandscape:function(w){return Math.abs(this.getOrientation(w))==90;},isPortrait:function(x){var y=this.getOrientation(x);return (y==0||y==180);}}});})();(function(){var f="CSS1Compat",e="position:absolute;width:0;height:0;width:1",d="qx.bom.Document",c="1px",b="qx.client",a="div";qx.Class.define(d,{statics:{isQuirksMode:qx.core.Variant.select(b,{"mshtml":function(g){if(qx.bom.client.Engine.VERSION>=8){return (g||window).document.documentMode===5;}else{return (g||window).document.compatMode!==f;}},"webkit":function(h){if(document.compatMode===undefined){var i=(h||window).document.createElement(a);i.style.cssText=e;return i.style.width===c?true:false;}else{return (h||window).document.compatMode!==f;}},"default":function(j){return (j||window).document.compatMode!==f;}}),isStandardMode:function(k){return !this.isQuirksMode(k);},getWidth:function(l){var m=(l||window).document;var n=qx.bom.Viewport.getWidth(l);var scroll=this.isStandardMode(l)?m.documentElement.scrollWidth:m.body.scrollWidth;return Math.max(scroll,n);},getHeight:function(o){var p=(o||window).document;var q=qx.bom.Viewport.getHeight(o);var scroll=this.isStandardMode(o)?p.documentElement.scrollHeight:p.body.scrollHeight;return Math.max(scroll,q);}}});})();(function(){var c="landscape",b="qx.event.type.Orientation",a="portrait";qx.Class.define(b,{extend:qx.event.type.Event,members:{__eB:null,__eC:null,init:function(d,e){qx.event.type.Event.prototype.init.call(this,false,false);this.__eB=d;this.__eC=e;return this;},clone:function(f){var g=qx.event.type.Event.prototype.clone.call(this,f);g.__eB=this.__eB;g.__eC=this.__eC;return g;},getOrientation:function(){return this.__eB;},isLandscape:function(){return this.__eC==c;},isPortrait:function(){return this.__eC==a;}}});})();(function(){var a="qx.event.type.Dom";qx.Class.define(a,{extend:qx.event.type.Native,statics:{SHIFT_MASK:1,CTRL_MASK:2,ALT_MASK:4,META_MASK:8},members:{_cloneNativeEvent:function(b,c){var c=qx.event.type.Native.prototype._cloneNativeEvent.call(this,b,c);c.shiftKey=b.shiftKey;c.ctrlKey=b.ctrlKey;c.altKey=b.altKey;c.metaKey=b.metaKey;return c;},getModifiers:function(){var e=0;var d=this._native;if(d.shiftKey){e|=qx.event.type.Dom.SHIFT_MASK;}if(d.ctrlKey){e|=qx.event.type.Dom.CTRL_MASK;}if(d.altKey){e|=qx.event.type.Dom.ALT_MASK;}if(d.metaKey){e|=qx.event.type.Dom.META_MASK;}return e;},isCtrlPressed:function(){return this._native.ctrlKey;},isShiftPressed:function(){return this._native.shiftKey;},isAltPressed:function(){return this._native.altKey;},isMetaPressed:function(){return this._native.metaKey;},isCtrlOrCommandPressed:function(){if(qx.bom.client.Platform.MAC){return this._native.metaKey;}else{return this._native.ctrlKey;}}}});})();(function(){var c="touchcancel",b="qx.event.type.Touch",a="touchend";qx.Class.define(b,{extend:qx.event.type.Dom,members:{_cloneNativeEvent:function(d,e){var e=qx.event.type.Dom.prototype._cloneNativeEvent.call(this,d,e);e.pageX=d.pageX;e.pageY=d.pageY;e.layerX=d.layerX;e.layerY=d.layerY;e.scale=d.scale;e.rotation=d.rotation;e.srcElement=d.srcElement;e.targetTouches=[];for(var i=0;i<d.targetTouches.length;i++){e.targetTouches[i]=d.targetTouches[i];}e.changedTouches=[];for(var i=0;i<d.changedTouches.length;i++){e.changedTouches[i]=d.changedTouches[i];}e.touches=[];for(var i=0;i<d.touches.length;i++){e.touches[i]=d.touches[i];}return e;},stop:function(){this.stopPropagation();},getAllTouches:function(){return this._native.touches;},getTargetTouches:function(){return this._native.targetTouches;},getChangedTargetTouches:function(){return this._native.changedTouches;},isMultiTouch:function(){return this.__cG().length>1;},getScale:function(){return this._native.scale;},getRotation:function(){return this._native.rotation;},getDocumentLeft:function(f){return this.__cF(f).pageX;},getDocumentTop:function(g){return this.__cF(g).pageY;},getScreenLeft:function(h){return this.__cF(h).screenX;},getScreenTop:function(j){return this.__cF(j).screenY;},getViewportLeft:function(k){return this.__cF(k).clientX;},getViewportTop:function(l){return this.__cF(l).clientY;},getIdentifier:function(m){return this.__cF(m).identifier;},__cF:function(n){n=n==null?0:n;return this.__cG()[n];},__cG:function(){var o=(this._isTouchEnd()?this.getChangedTargetTouches():this.getTargetTouches());return o;},_isTouchEnd:function(){return (this.getType()==a||this.getType()==c);}}});})();(function(){var a="qx.event.type.Tap";qx.Class.define(a,{extend:qx.event.type.Touch,members:{_isTouchEnd:function(){return true;}}});})();(function(){var a="qx.event.type.Swipe";qx.Class.define(a,{extend:qx.event.type.Touch,members:{_cloneNativeEvent:function(b,c){var c=qx.event.type.Touch.prototype._cloneNativeEvent.call(this,b,c);c.swipe=b.swipe;return c;},_isTouchEnd:function(){return true;},getStartTime:function(){return this._native.swipe.startTime;},getDuration:function(){return this._native.swipe.duration;},getAxis:function(){return this._native.swipe.axis;},getDirection:function(){return this._native.swipe.direction;},getVelocity:function(){return this._native.swipe.velocity;},getDistance:function(){return this._native.swipe.distance;}}});})();(function(){var h="left",g="right",f="middle",e="none",d="click",c="contextmenu",b="qx.event.type.Mouse",a="qx.client";qx.Class.define(b,{extend:qx.event.type.Dom,members:{_cloneNativeEvent:function(i,j){var j=qx.event.type.Dom.prototype._cloneNativeEvent.call(this,i,j);j.button=i.button;j.clientX=i.clientX;j.clientY=i.clientY;j.pageX=i.pageX;j.pageY=i.pageY;j.screenX=i.screenX;j.screenY=i.screenY;j.wheelDelta=i.wheelDelta;j.detail=i.detail;j.srcElement=i.srcElement;j.target=i.target;return j;},__kD:{0:h,2:g,1:f},__kE:{1:h,2:g,4:f},stop:function(){this.stopPropagation();},getButton:function(){switch(this._type){case c:return g;case d:if(this.__kF){return this.__kF();}default:if(this._native.target!==undefined){return this.__kD[this._native.button]||e;}else{return this.__kE[this._native.button]||e;}}},__kF:qx.core.Variant.select(a,{"mshtml":function(){return h;},"default":null}),isLeftPressed:function(){return this.getButton()===h;},isMiddlePressed:function(){return this.getButton()===f;},isRightPressed:function(){return this.getButton()===g;},getRelatedTarget:function(){return this._relatedTarget;},getViewportLeft:function(){return this._native.clientX;},getViewportTop:function(){return this._native.clientY;},getDocumentLeft:function(){if(this._native.pageX!==undefined){return this._native.pageX;}else{var k=qx.dom.Node.getWindow(this._native.srcElement);return this._native.clientX+qx.bom.Viewport.getScrollLeft(k);}},getDocumentTop:function(){if(this._native.pageY!==undefined){return this._native.pageY;}else{var l=qx.dom.Node.getWindow(this._native.srcElement);return this._native.clientY+qx.bom.Viewport.getScrollTop(l);}},getScreenLeft:function(){return this._native.screenX;},getScreenTop:function(){return this._native.screenY;}}});})();(function(){var c="qx.client",b="chrome",a="qx.event.type.MouseWheel";qx.Class.define(a,{extend:qx.event.type.Mouse,members:{stop:function(){this.stopPropagation();this.preventDefault();},getWheelDelta:qx.core.Variant.select(c,{"default":function(){return -(this._native.wheelDelta/40);},"gecko":function(){return this._native.detail;},"webkit":function(){if(qx.bom.client.Browser.NAME==b){if(qx.bom.client.Platform.MAC){return -(this._native.wheelDelta/1200);}else{return -(this._native.wheelDelta/120);}}else{if(qx.bom.client.Platform.WIN){var d=120;if(qx.bom.client.Engine.VERSION==533.16){d=1200;}}else{d=40;if(qx.bom.client.Engine.VERSION==533.16||qx.bom.client.Engine.VERSION==533.17||qx.bom.client.Engine.VERSION==533.18){d=1200;}}return -(this._native.wheelDelta/d);}}})}});})();(function(){var j="qx.client",i="ie",h="msie",g="android",f="operamini",e="mobile chrome",d=")(/| )([0-9]+\.[0-9])",c="iemobile",b="opera mobi",a="Mobile Safari",x="operamobile",w="mobile safari",v="IEMobile|Maxthon|MSIE",u="qx.bom.client.Browser",t="opera mini",s="(",r="opera",q="mshtml",p="Opera Mini|Opera Mobi|Opera",o="AdobeAIR|Titanium|Fluid|Chrome|Android|Epiphany|Konqueror|iCab|OmniWeb|Maxthon|Pre|Mobile Safari|Safari",m="webkit",n="5.0",k="prism|Fennec|Camino|Kmeleon|Galeon|Netscape|SeaMonkey|Firefox",l="Mobile/";qx.Bootstrap.define(u,{statics:{UNKNOWN:true,NAME:"unknown",TITLE:"unknown 0.0",VERSION:0.0,FULLVERSION:"0.0.0",__lE:function(y){var z=navigator.userAgent;var B=new RegExp(s+y+d);var C=z.match(B);if(!C){return;}var name=C[1].toLowerCase();var A=C[3];if(z.match(/Version(\/| )([0-9]+\.[0-9])/)){A=RegExp.$2;}if(qx.core.Variant.isSet(j,m)){if(name===g){name=e;}else if(z.indexOf(a)!==-1||z.indexOf(l)!==-1){name=w;}}else if(qx.core.Variant.isSet(j,q)){if(name===h){name=i;if(qx.bom.client.System.WINCE&&name===i){name=c;A=n;}}}else if(qx.core.Variant.isSet(j,r)){if(name===b){name=x;}else if(name===t){name=f;}}this.NAME=name;this.FULLVERSION=A;this.VERSION=parseFloat(A,10);this.TITLE=name+" "+this.VERSION;this.UNKNOWN=false;}},defer:qx.core.Variant.select(j,{"webkit":function(D){D.__lE(o);},"gecko":function(E){E.__lE(k);},"mshtml":function(F){F.__lE(v);},"opera":function(G){G.__lE(p);}})});})();(function(){var f="qx.client",e="qx.dom.Hierarchy",d="previousSibling",c="*",b="nextSibling",a="parentNode";qx.Class.define(e,{statics:{getNodeIndex:function(g){var h=0;while(g&&(g=g.previousSibling)){h++;}return h;},getElementIndex:function(i){var j=0;var k=qx.dom.Node.ELEMENT;while(i&&(i=i.previousSibling)){if(i.nodeType==k){j++;}}return j;},getNextElementSibling:function(l){while(l&&(l=l.nextSibling)&&!qx.dom.Node.isElement(l)){continue;}return l||null;},getPreviousElementSibling:function(m){while(m&&(m=m.previousSibling)&&!qx.dom.Node.isElement(m)){continue;}return m||null;},contains:qx.core.Variant.select(f,{"webkit|mshtml|opera":function(n,o){if(qx.dom.Node.isDocument(n)){var p=qx.dom.Node.getDocument(o);return n&&p==n;}else if(qx.dom.Node.isDocument(o)){return false;}else{return n.contains(o);}},"gecko":function(q,r){return !!(q.compareDocumentPosition(r)&16);},"default":function(s,t){while(t){if(s==t){return true;}t=t.parentNode;}return false;}}),isRendered:qx.core.Variant.select(f,{"mshtml":function(u){if(!u.parentNode||!u.offsetParent){return false;}var v=u.ownerDocument||u.document;return v.body.contains(u);},"gecko":function(w){var x=w.ownerDocument||w.document;return !!(x.compareDocumentPosition(w)&16);},"default":function(y){if(!y.parentNode||!y.offsetParent){return false;}var z=y.ownerDocument||y.document;return z.body.contains(y);}}),isDescendantOf:function(A,B){return this.contains(B,A);},getCommonParent:qx.core.Variant.select(f,{"mshtml|opera":function(C,D){if(C===D){return C;}while(C&&qx.dom.Node.isElement(C)){if(C.contains(D)){return C;}C=C.parentNode;}return null;},"default":function(E,F){if(E===F){return E;}var G={};var J=qx.core.ObjectRegistry;var I,H;while(E||F){if(E){I=J.toHashCode(E);if(G[I]){return G[I];}G[I]=E;E=E.parentNode;}if(F){H=J.toHashCode(F);if(G[H]){return G[H];}G[H]=F;F=F.parentNode;}}return null;}}),getAncestors:function(K){return this._recursivelyCollect(K,a);},getChildElements:function(L){L=L.firstChild;if(!L){return [];}var M=this.getNextSiblings(L);if(L.nodeType===1){M.unshift(L);}return M;},getDescendants:function(N){return qx.lang.Array.fromCollection(N.getElementsByTagName(c));},getFirstDescendant:function(O){O=O.firstChild;while(O&&O.nodeType!=1){O=O.nextSibling;}return O;},getLastDescendant:function(P){P=P.lastChild;while(P&&P.nodeType!=1){P=P.previousSibling;}return P;},getPreviousSiblings:function(Q){return this._recursivelyCollect(Q,d);},getNextSiblings:function(R){return this._recursivelyCollect(R,b);},_recursivelyCollect:function(S,T){var U=[];while(S=S[T]){if(S.nodeType==1){U.push(S);}}return U;},getSiblings:function(V){return this.getPreviousSiblings(V).reverse().concat(this.getNextSiblings(V));},isEmpty:function(W){W=W.firstChild;while(W){if(W.nodeType===qx.dom.Node.ELEMENT||W.nodeType===qx.dom.Node.TEXT){return false;}W=W.nextSibling;}return true;},cleanWhitespace:function(X){var Y=X.firstChild;while(Y){var ba=Y.nextSibling;if(Y.nodeType==3&&!/\S/.test(Y.nodeValue)){X.removeChild(Y);}Y=ba;}}}});})();(function(){var a="qx.event.type.KeyInput";qx.Class.define(a,{extend:qx.event.type.Dom,members:{init:function(b,c,d){qx.event.type.Dom.prototype.init.call(this,b,c,null,true,true);this._charCode=d;return this;},clone:function(e){var f=qx.event.type.Dom.prototype.clone.call(this,e);f._charCode=this._charCode;return f;},getCharCode:function(){return this._charCode;},getChar:function(){return String.fromCharCode(this._charCode);}}});})();(function(){var a="qx.event.type.KeySequence";qx.Class.define(a,{extend:qx.event.type.Dom,members:{init:function(b,c,d){qx.event.type.Dom.prototype.init.call(this,b,c,null,true,true);this._keyCode=b.keyCode;this._identifier=d;return this;},clone:function(e){var f=qx.event.type.Dom.prototype.clone.call(this,e);f._keyCode=this._keyCode;f._identifier=this._identifier;return f;},getKeyIdentifier:function(){return this._identifier;},getKeyCode:function(){return this._keyCode;}}});})();(function(){var j="qx.client",i="mousedown",h="mouseup",g="blur",f="focus",e="on",d="selectstart",c="DOMFocusOut",b="focusin",a="focusout",z="DOMFocusIn",y="draggesture",x="qx.event.handler.Focus",w="_applyFocus",v="deactivate",u="textarea",t="_applyActive",s='character',r="input",q="qxSelectable",o="tabIndex",p="off",m="activate",n="mshtml",k="qxKeepFocus",l="qxKeepActive";qx.Class.define(x,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(A){qx.core.Object.call(this);this._manager=A;this._window=A.getWindow();this._document=this._window.document;this._root=this._document.documentElement;this._body=this._document.body;this._initObserver();},properties:{active:{apply:t,nullable:true},focus:{apply:w,nullable:true}},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{focus:1,blur:1,focusin:1,focusout:1,activate:1,deactivate:1},IGNORE_CAN_HANDLE:true,FOCUSABLE_ELEMENTS:qx.core.Variant.select("qx.client",{"mshtml|gecko":{a:1,body:1,button:1,frame:1,iframe:1,img:1,input:1,object:1,select:1,textarea:1},"opera|webkit":{button:1,input:1,select:1,textarea:1}})},members:{__jQ:null,__jR:null,__jS:null,__jT:null,__jU:null,__jV:null,__jW:null,__jX:null,__jY:null,__ka:null,canHandleEvent:function(B,C){},registerEvent:function(D,E,F){},unregisterEvent:function(G,H,I){},focus:function(J){if(qx.core.Variant.isSet(j,n)){window.setTimeout(function(){try{J.focus();var K=qx.bom.Selection.get(J);if(K.length==0){var L=J.createTextRange();L.moveStart(s,J.value.length);L.collapse();L.select();}}catch(M){}},0);}else{try{J.focus();}catch(N){}}this.setFocus(J);this.setActive(J);},activate:function(O){this.setActive(O);},blur:function(P){try{P.blur();}catch(Q){}if(this.getActive()===P){this.resetActive();}if(this.getFocus()===P){this.resetFocus();}},deactivate:function(R){if(this.getActive()===R){this.resetActive();}},tryActivate:function(S){var T=this.__kp(S);if(T){this.setActive(T);}},__kb:function(U,V,W,X){var ba=qx.event.Registration;var Y=ba.createEvent(W,qx.event.type.Focus,[U,V,X]);ba.dispatchEvent(U,Y);},_windowFocused:true,__kc:function(){if(this._windowFocused){this._windowFocused=false;this.__kb(this._window,null,g,false);}},__kd:function(){if(!this._windowFocused){this._windowFocused=true;this.__kb(this._window,null,f,false);}},_initObserver:qx.core.Variant.select(j,{"gecko":function(){this.__jQ=qx.lang.Function.listener(this.__kj,this);this.__jR=qx.lang.Function.listener(this.__kk,this);this.__jS=qx.lang.Function.listener(this.__ki,this);this.__jT=qx.lang.Function.listener(this.__kh,this);this.__jU=qx.lang.Function.listener(this.__ke,this);qx.bom.Event.addNativeListener(this._document,i,this.__jQ,true);qx.bom.Event.addNativeListener(this._document,h,this.__jR,true);qx.bom.Event.addNativeListener(this._window,f,this.__jS,true);qx.bom.Event.addNativeListener(this._window,g,this.__jT,true);qx.bom.Event.addNativeListener(this._window,y,this.__jU,true);},"mshtml":function(){this.__jQ=qx.lang.Function.listener(this.__kj,this);this.__jR=qx.lang.Function.listener(this.__kk,this);this.__jW=qx.lang.Function.listener(this.__kf,this);this.__jX=qx.lang.Function.listener(this.__kg,this);this.__jV=qx.lang.Function.listener(this.__km,this);qx.bom.Event.addNativeListener(this._document,i,this.__jQ);qx.bom.Event.addNativeListener(this._document,h,this.__jR);qx.bom.Event.addNativeListener(this._document,b,this.__jW);qx.bom.Event.addNativeListener(this._document,a,this.__jX);qx.bom.Event.addNativeListener(this._document,d,this.__jV);},"webkit":function(){this.__jQ=qx.lang.Function.listener(this.__kj,this);this.__jR=qx.lang.Function.listener(this.__kk,this);this.__jX=qx.lang.Function.listener(this.__kg,this);this.__jS=qx.lang.Function.listener(this.__ki,this);this.__jT=qx.lang.Function.listener(this.__kh,this);this.__jV=qx.lang.Function.listener(this.__km,this);qx.bom.Event.addNativeListener(this._document,i,this.__jQ,true);qx.bom.Event.addNativeListener(this._document,h,this.__jR,true);qx.bom.Event.addNativeListener(this._document,d,this.__jV,false);qx.bom.Event.addNativeListener(this._window,c,this.__jX,true);qx.bom.Event.addNativeListener(this._window,f,this.__jS,true);qx.bom.Event.addNativeListener(this._window,g,this.__jT,true);},"opera":function(){this.__jQ=qx.lang.Function.listener(this.__kj,this);this.__jR=qx.lang.Function.listener(this.__kk,this);this.__jW=qx.lang.Function.listener(this.__kf,this);this.__jX=qx.lang.Function.listener(this.__kg,this);qx.bom.Event.addNativeListener(this._document,i,this.__jQ,true);qx.bom.Event.addNativeListener(this._document,h,this.__jR,true);qx.bom.Event.addNativeListener(this._window,z,this.__jW,true);qx.bom.Event.addNativeListener(this._window,c,this.__jX,true);}}),_stopObserver:qx.core.Variant.select(j,{"gecko":function(){qx.bom.Event.removeNativeListener(this._document,i,this.__jQ,true);qx.bom.Event.removeNativeListener(this._document,h,this.__jR,true);qx.bom.Event.removeNativeListener(this._window,f,this.__jS,true);qx.bom.Event.removeNativeListener(this._window,g,this.__jT,true);qx.bom.Event.removeNativeListener(this._window,y,this.__jU,true);},"mshtml":function(){qx.bom.Event.removeNativeListener(this._document,i,this.__jQ);qx.bom.Event.removeNativeListener(this._document,h,this.__jR);qx.bom.Event.removeNativeListener(this._document,b,this.__jW);qx.bom.Event.removeNativeListener(this._document,a,this.__jX);qx.bom.Event.removeNativeListener(this._document,d,this.__jV);},"webkit":function(){qx.bom.Event.removeNativeListener(this._document,i,this.__jQ,true);qx.bom.Event.removeNativeListener(this._document,h,this.__jR,true);qx.bom.Event.removeNativeListener(this._document,d,this.__jV,false);qx.bom.Event.removeNativeListener(this._window,c,this.__jX,true);qx.bom.Event.removeNativeListener(this._window,f,this.__jS,true);qx.bom.Event.removeNativeListener(this._window,g,this.__jT,true);},"opera":function(){qx.bom.Event.removeNativeListener(this._document,i,this.__jQ,true);qx.bom.Event.removeNativeListener(this._document,h,this.__jR,true);qx.bom.Event.removeNativeListener(this._window,z,this.__jW,true);qx.bom.Event.removeNativeListener(this._window,c,this.__jX,true);}}),__ke:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"gecko":function(bb){var bc=qx.bom.Event.getTarget(bb);if(!this.__kq(bc)){qx.bom.Event.preventDefault(bb);}},"default":null})),__kf:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"mshtml":function(bd){this.__kd();var bf=qx.bom.Event.getTarget(bd);var be=this.__ko(bf);if(be){this.setFocus(be);}this.tryActivate(bf);},"opera":function(bg){var bh=qx.bom.Event.getTarget(bg);if(bh==this._document||bh==this._window){this.__kd();if(this.__jY){this.setFocus(this.__jY);delete this.__jY;}if(this.__ka){this.setActive(this.__ka);delete this.__ka;}}else{this.setFocus(bh);this.tryActivate(bh);if(!this.__kq(bh)){bh.selectionStart=0;bh.selectionEnd=0;}}},"default":null})),__kg:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"mshtml":function(bi){if(!bi.toElement){this.__kc();this.resetFocus();this.resetActive();}},"webkit":function(bj){var bk=qx.bom.Event.getTarget(bj);if(bk===this.getFocus()){this.resetFocus();}if(bk===this.getActive()){this.resetActive();}},"opera":function(bl){var bm=qx.bom.Event.getTarget(bl);if(bm==this._document){this.__kc();this.__jY=this.getFocus();this.__ka=this.getActive();this.resetFocus();this.resetActive();}else{if(bm===this.getFocus()){this.resetFocus();}if(bm===this.getActive()){this.resetActive();}}},"default":null})),__kh:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"gecko":function(bn){var bo=qx.bom.Event.getTarget(bn);if(bo===this._window||bo===this._document){this.__kc();this.resetActive();this.resetFocus();}},"webkit":function(bp){var bq=qx.bom.Event.getTarget(bp);if(bq===this._window||bq===this._document){this.__kc();this.__jY=this.getFocus();this.__ka=this.getActive();this.resetActive();this.resetFocus();}},"default":null})),__ki:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"gecko":function(br){var bs=qx.bom.Event.getTarget(br);if(bs===this._window||bs===this._document){this.__kd();bs=this._body;}this.setFocus(bs);this.tryActivate(bs);},"webkit":function(bt){var bu=qx.bom.Event.getTarget(bt);if(bu===this._window||bu===this._document){this.__kd();if(this.__jY){this.setFocus(this.__jY);delete this.__jY;}if(this.__ka){this.setActive(this.__ka);delete this.__ka;}}else{this.setFocus(bu);this.tryActivate(bu);}},"default":null})),__kj:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"gecko":function(bv){var bx=qx.bom.Event.getTarget(bv);var bw=this.__ko(bx);if(!bw){qx.bom.Event.preventDefault(bv);}else if(bw===this._body){this.setFocus(bw);}},"mshtml":function(by){var bA=qx.bom.Event.getTarget(by);var bz=this.__ko(bA);if(bz){if(!this.__kq(bA)){bA.unselectable=e;try{document.selection.empty();}catch(bB){}try{bz.focus();}catch(bC){}}}else{qx.bom.Event.preventDefault(by);if(!this.__kq(bA)){bA.unselectable=e;}}},"webkit":function(bD){var bF=qx.bom.Event.getTarget(bD);var bE=this.__ko(bF);if(bE){this.setFocus(bE);}else{qx.bom.Event.preventDefault(bD);}},"opera":function(bG){var bJ=qx.bom.Event.getTarget(bG);var bH=this.__ko(bJ);if(!this.__kq(bJ)){qx.bom.Event.preventDefault(bG);if(bH){var bI=this.getFocus();if(bI&&bI.selectionEnd){bI.selectionStart=0;bI.selectionEnd=0;bI.blur();}if(bH){this.setFocus(bH);}}}else if(bH){this.setFocus(bH);}},"default":null})),__kk:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"mshtml":function(bK){var bL=qx.bom.Event.getTarget(bK);if(bL.unselectable){bL.unselectable=p;}this.tryActivate(this.__kl(bL));},"gecko":function(bM){var bN=qx.bom.Event.getTarget(bM);while(bN&&bN.offsetWidth===undefined){bN=bN.parentNode;}if(bN){this.tryActivate(bN);}},"webkit|opera":function(bO){var bP=qx.bom.Event.getTarget(bO);this.tryActivate(this.__kl(bP));},"default":null})),__kl:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"mshtml|webkit":function(bQ){var bR=this.getFocus();if(bR&&bQ!=bR&&(bR.nodeName.toLowerCase()===r||bR.nodeName.toLowerCase()===u)){bQ=bR;}return bQ;},"default":function(bS){return bS;}})),__km:qx.event.GlobalError.observeMethod(qx.core.Variant.select(j,{"mshtml|webkit":function(bT){var bU=qx.bom.Event.getTarget(bT);if(!this.__kq(bU)){qx.bom.Event.preventDefault(bT);}},"default":null})),__kn:function(bV){var bW=qx.bom.element.Attribute.get(bV,o);if(bW>=1){return true;}var bX=qx.event.handler.Focus.FOCUSABLE_ELEMENTS;if(bW>=0&&bX[bV.tagName]){return true;}return false;},__ko:function(bY){while(bY&&bY.nodeType===1){if(bY.getAttribute(k)==e){return null;}if(this.__kn(bY)){return bY;}bY=bY.parentNode;}return this._body;},__kp:function(ca){var cb=ca;while(ca&&ca.nodeType===1){if(ca.getAttribute(l)==e){return null;}ca=ca.parentNode;}return cb;},__kq:function(cc){while(cc&&cc.nodeType===1){var cd=cc.getAttribute(q);if(cd!=null){return cd===e;}cc=cc.parentNode;}return true;},_applyActive:function(ce,cf){if(cf){this.__kb(cf,ce,v,true);}if(ce){this.__kb(ce,cf,m,true);}},_applyFocus:function(cg,ch){if(ch){this.__kb(ch,cg,a,true);}if(cg){this.__kb(cg,ch,b,true);}if(ch){this.__kb(ch,cg,g,false);}if(cg){this.__kb(cg,ch,f,false);}}},destruct:function(){this._stopObserver();this._manager=this._window=this._document=this._root=this._body=this.__kr=null;},defer:function(ci){qx.event.Registration.addHandler(ci);var cj=ci.FOCUSABLE_ELEMENTS;for(var ck in cj){cj[ck.toUpperCase()]=1;}}});})();(function(){var k="qx.client",j="character",i="EndToEnd",h="input",g="textarea",f="StartToStart",e='character',d="qx.bom.Selection",c="button",b="#text",a="body";qx.Class.define(d,{statics:{getSelectionObject:qx.core.Variant.select(k,{"mshtml":function(l){return l.selection;},"default":function(m){return qx.dom.Node.getWindow(m).getSelection();}}),get:qx.core.Variant.select(k,{"mshtml":function(n){var o=qx.bom.Range.get(qx.dom.Node.getDocument(n));return o.text;},"default":function(p){if(this.__lf(p)){return p.value.substring(p.selectionStart,p.selectionEnd);}else{return this.getSelectionObject(qx.dom.Node.getDocument(p)).toString();}}}),getLength:qx.core.Variant.select(k,{"mshtml":function(q){var s=this.get(q);var r=qx.util.StringSplit.split(s,/\r\n/);return s.length-(r.length-1);},"opera":function(t){var y,w,u;if(this.__lf(t)){var x=t.selectionStart;var v=t.selectionEnd;y=t.value.substring(x,v);w=v-x;}else{y=qx.bom.Selection.get(t);w=y.length;}u=qx.util.StringSplit.split(y,/\r\n/);return w-(u.length-1);},"default":function(z){if(this.__lf(z)){return z.selectionEnd-z.selectionStart;}else{return this.get(z).length;}}}),getStart:qx.core.Variant.select(k,{"mshtml":function(A){if(this.__lf(A)){var F=qx.bom.Range.get();if(!A.contains(F.parentElement())){return -1;}var G=qx.bom.Range.get(A);var E=A.value.length;G.moveToBookmark(F.getBookmark());G.moveEnd(e,E);return E-G.text.length;}else{var G=qx.bom.Range.get(A);var C=G.parentElement();var H=qx.bom.Range.get();H.moveToElementText(C);var B=qx.bom.Range.get(qx.dom.Node.getBodyElement(A));B.setEndPoint(f,G);B.setEndPoint(i,H);if(H.compareEndPoints(f,B)==0){return 0;}var D;var I=0;while(true){D=B.moveStart(j,-1);if(H.compareEndPoints(f,B)==0){break;}if(D==0){break;}else{I++;}}return ++I;}},"gecko|webkit":function(J){if(this.__lf(J)){return J.selectionStart;}else{var L=qx.dom.Node.getDocument(J);var K=this.getSelectionObject(L);if(K.anchorOffset<K.focusOffset){return K.anchorOffset;}else{return K.focusOffset;}}},"default":function(M){if(this.__lf(M)){return M.selectionStart;}else{return qx.bom.Selection.getSelectionObject(qx.dom.Node.getDocument(M)).anchorOffset;}}}),getEnd:qx.core.Variant.select(k,{"mshtml":function(N){if(this.__lf(N)){var S=qx.bom.Range.get();if(!N.contains(S.parentElement())){return -1;}var T=qx.bom.Range.get(N);var R=N.value.length;T.moveToBookmark(S.getBookmark());T.moveStart(e,-R);return T.text.length;}else{var T=qx.bom.Range.get(N);var P=T.parentElement();var U=qx.bom.Range.get();U.moveToElementText(P);var R=U.text.length;var O=qx.bom.Range.get(qx.dom.Node.getBodyElement(N));O.setEndPoint(i,T);O.setEndPoint(f,U);if(U.compareEndPoints(i,O)==0){return R-1;}var Q;var V=0;while(true){Q=O.moveEnd(j,1);if(U.compareEndPoints(i,O)==0){break;}if(Q==0){break;}else{V++;}}return R-(++V);}},"gecko|webkit":function(W){if(this.__lf(W)){return W.selectionEnd;}else{var Y=qx.dom.Node.getDocument(W);var X=this.getSelectionObject(Y);if(X.focusOffset>X.anchorOffset){return X.focusOffset;}else{return X.anchorOffset;}}},"default":function(ba){if(this.__lf(ba)){return ba.selectionEnd;}else{return qx.bom.Selection.getSelectionObject(qx.dom.Node.getDocument(ba)).focusOffset;}}}),__lf:function(bb){return qx.dom.Node.isElement(bb)&&(bb.nodeName.toLowerCase()==h||bb.nodeName.toLowerCase()==g);},set:qx.core.Variant.select(k,{"mshtml":function(bc,bd,be){var bf;if(qx.dom.Node.isDocument(bc)){bc=bc.body;}if(qx.dom.Node.isElement(bc)||qx.dom.Node.isText(bc)){switch(bc.nodeName.toLowerCase()){case h:case g:case c:if(be===undefined){be=bc.value.length;}if(bd>=0&&bd<=bc.value.length&&be>=0&&be<=bc.value.length){bf=qx.bom.Range.get(bc);bf.collapse(true);bf.moveStart(j,bd);bf.moveEnd(j,be-bd);bf.select();return true;}break;case b:if(be===undefined){be=bc.nodeValue.length;}if(bd>=0&&bd<=bc.nodeValue.length&&be>=0&&be<=bc.nodeValue.length){bf=qx.bom.Range.get(qx.dom.Node.getBodyElement(bc));bf.moveToElementText(bc.parentNode);bf.collapse(true);bf.moveStart(j,bd);bf.moveEnd(j,be-bd);bf.select();return true;}break;default:if(be===undefined){be=bc.childNodes.length-1;}if(bc.childNodes[bd]&&bc.childNodes[be]){bf=qx.bom.Range.get(qx.dom.Node.getBodyElement(bc));bf.moveToElementText(bc.childNodes[bd]);bf.collapse(true);var bg=qx.bom.Range.get(qx.dom.Node.getBodyElement(bc));bg.moveToElementText(bc.childNodes[be]);bf.setEndPoint(i,bg);bf.select();return true;}}}return false;},"default":function(bh,bi,bj){var bn=bh.nodeName.toLowerCase();if(qx.dom.Node.isElement(bh)&&(bn==h||bn==g)){if(bj===undefined){bj=bh.value.length;}if(bi>=0&&bi<=bh.value.length&&bj>=0&&bj<=bh.value.length){bh.focus();bh.select();bh.setSelectionRange(bi,bj);return true;}}else{var bl=false;var bm=qx.dom.Node.getWindow(bh).getSelection();var bk=qx.bom.Range.get(bh);if(qx.dom.Node.isText(bh)){if(bj===undefined){bj=bh.length;}if(bi>=0&&bi<bh.length&&bj>=0&&bj<=bh.length){bl=true;}}else if(qx.dom.Node.isElement(bh)){if(bj===undefined){bj=bh.childNodes.length-1;}if(bi>=0&&bh.childNodes[bi]&&bj>=0&&bh.childNodes[bj]){bl=true;}}else if(qx.dom.Node.isDocument(bh)){bh=bh.body;if(bj===undefined){bj=bh.childNodes.length-1;}if(bi>=0&&bh.childNodes[bi]&&bj>=0&&bh.childNodes[bj]){bl=true;}}if(bl){if(!bm.isCollapsed){bm.collapseToStart();}bk.setStart(bh,bi);if(qx.dom.Node.isText(bh)){bk.setEnd(bh,bj);}else{bk.setEndAfter(bh.childNodes[bj]);}if(bm.rangeCount>0){bm.removeAllRanges();}bm.addRange(bk);return true;}}return false;}}),setAll:function(bo){return qx.bom.Selection.set(bo,0);},clear:qx.core.Variant.select(k,{"mshtml":function(bp){var bq=qx.bom.Selection.getSelectionObject(qx.dom.Node.getDocument(bp));var br=qx.bom.Range.get(bp);var parent=br.parentElement();var bs=qx.bom.Range.get(qx.dom.Node.getDocument(bp));if(parent==bs.parentElement()&&parent==bp){bq.empty();}},"default":function(bt){var bv=qx.bom.Selection.getSelectionObject(qx.dom.Node.getDocument(bt));var bx=bt.nodeName.toLowerCase();if(qx.dom.Node.isElement(bt)&&(bx==h||bx==g)){bt.setSelectionRange(0,0);qx.bom.Element.blur(bt);}else if(qx.dom.Node.isDocument(bt)||bx==a){bv.collapse(bt.body?bt.body:bt,0);}else{var bw=qx.bom.Range.get(bt);if(!bw.collapsed){var by;var bu=bw.commonAncestorContainer;if(qx.dom.Node.isElement(bt)&&qx.dom.Node.isText(bu)){by=bu.parentNode;}else{by=bu;}if(by==bt){bv.collapse(bt,0);}}}}})}});})();(function(){var l="button",k="qx.bom.Range",j="text",i="password",h="file",g="submit",f="reset",e="textarea",d="input",c="hidden",a="qx.client",b="body";qx.Class.define(k,{statics:{get:qx.core.Variant.select(a,{"mshtml":function(m){if(qx.dom.Node.isElement(m)){switch(m.nodeName.toLowerCase()){case d:switch(m.type){case j:case i:case c:case l:case f:case h:case g:return m.createTextRange();break;default:return qx.bom.Selection.getSelectionObject(qx.dom.Node.getDocument(m)).createRange();}break;case e:case b:case l:return m.createTextRange();break;default:return qx.bom.Selection.getSelectionObject(qx.dom.Node.getDocument(m)).createRange();}}else{if(m==null){m=window;}return qx.bom.Selection.getSelectionObject(qx.dom.Node.getDocument(m)).createRange();}},"default":function(n){var o=qx.dom.Node.getDocument(n);var p=qx.bom.Selection.getSelectionObject(o);if(p.rangeCount>0){return p.getRangeAt(0);}else{return o.createRange();}}})}});})();(function(){var j="",h="m",g="g",f="^",e="qx.util.StringSplit",d="i",c="$(?!\\s)",b="[object RegExp]",a="y";qx.Class.define(e,{statics:{split:function(k,l,m){if(Object.prototype.toString.call(l)!==b){return String.prototype.split.call(k,l,m);}var t=[],n=0,r=(l.ignoreCase?d:j)+(l.multiline?h:j)+(l.sticky?a:j),l=RegExp(l.source,r+g),q,u,o,p,s=/()??/.exec(j)[1]===undefined;k=k+j;if(!s){q=RegExp(f+l.source+c,r);}if(m===undefined||+m<0){m=Infinity;}else{m=Math.floor(+m);if(!m){return [];}}while(u=l.exec(k)){o=u.index+u[0].length;if(o>n){t.push(k.slice(n,u.index));if(!s&&u.length>1){u[0].replace(q,function(){for(var i=1;i<arguments.length-2;i++){if(arguments[i]===undefined){u[i]=undefined;}}});}if(u.length>1&&u.index<k.length){Array.prototype.push.apply(t,u.slice(1));}p=u[0].length;n=o;if(t.length>=m){break;}}if(l.lastIndex===u.index){l.lastIndex++;}}if(n===k.length){if(p||!l.test(j)){t.push(j);}}else{t.push(k.slice(n));}return t.length>m?t.slice(0,m):t;}}});})();(function(){var a="qx.event.type.Focus";qx.Class.define(a,{extend:qx.event.type.Event,members:{init:function(b,c,d){qx.event.type.Event.prototype.init.call(this,d,false);this._target=b;this._relatedTarget=c;return this;}}});})();(function(){var j="",i="undefined",h="qx.client",g="readOnly",f="accessKey",e="qx.bom.element.Attribute",d="rowSpan",c="vAlign",b="className",a="textContent",y="'",x="htmlFor",w="longDesc",v="cellSpacing",u="frameBorder",t="='",s="useMap",r="innerText",q="innerHTML",p="tabIndex",n="dateTime",o="maxLength",l="mshtml",m="cellPadding",k="colSpan";qx.Class.define(e,{statics:{__hb:{names:{"class":b,"for":x,html:q,text:qx.core.Variant.isSet(h,l)?r:a,colspan:k,rowspan:d,valign:c,datetime:n,accesskey:f,tabindex:p,maxlength:o,readonly:g,longdesc:w,cellpadding:m,cellspacing:v,frameborder:u,usemap:s},runtime:{"html":1,"text":1},bools:{compact:1,nowrap:1,ismap:1,declare:1,noshade:1,checked:1,disabled:1,readOnly:1,multiple:1,selected:1,noresize:1,defer:1,allowTransparency:1},property:{$$html:1,$$widget:1,disabled:1,checked:1,readOnly:1,multiple:1,selected:1,value:1,maxLength:1,className:1,innerHTML:1,innerText:1,textContent:1,htmlFor:1,tabIndex:1},qxProperties:{$$widget:1,$$html:1},propertyDefault:{disabled:false,checked:false,readOnly:false,multiple:false,selected:false,value:j,className:j,innerHTML:j,innerText:j,textContent:j,htmlFor:j,tabIndex:0,maxLength:qx.core.Variant.select(h,{"mshtml":2147483647,"webkit":524288,"default":-1})},removeableProperties:{disabled:1,multiple:1,maxLength:1},original:{href:1,src:1,type:1}},compile:function(z){var A=[];var C=this.__hb.runtime;for(var B in z){if(!C[B]){A.push(B,t,z[B],y);}}return A.join(j);},get:qx.core.Variant.select(h,{"mshtml":function(D,name){var F=this.__hb;var E;name=F.names[name]||name;if(F.original[name]){E=D.getAttribute(name,2);}else if(F.property[name]){E=D[name];if(typeof F.propertyDefault[name]!==i&&E==F.propertyDefault[name]){if(typeof F.bools[name]===i){return null;}else{return E;}}}else{E=D.getAttribute(name);}if(F.bools[name]){return !!E;}return E;},"default":function(G,name){var I=this.__hb;var H;name=I.names[name]||name;if(I.property[name]){H=G[name];if(typeof I.propertyDefault[name]!==i&&H==I.propertyDefault[name]){if(typeof I.bools[name]===i){return null;}else{return H;}}}else{H=G.getAttribute(name);}if(I.bools[name]){return !!H;}return H;}}),set:function(J,name,K){if(typeof K===i){return;}var L=this.__hb;name=L.names[name]||name;if(L.bools[name]){K=!!K;}if(L.property[name]&&(!(J[name]===undefined)||L.qxProperties[name])){if(K==null){if(L.removeableProperties[name]){J.removeAttribute(name);return;}else if(typeof L.propertyDefault[name]!==i){K=L.propertyDefault[name];}}J[name]=K;}else{if(K===true){J.setAttribute(name,name);}else if(K===false||K===null){J.removeAttribute(name);}else{J.setAttribute(name,K);}}},reset:function(M,name){this.set(M,name,null);}}});})();(function(){var a="qx.event.type.Drag";qx.Class.define(a,{extend:qx.event.type.Event,members:{init:function(b,c){qx.event.type.Event.prototype.init.call(this,true,b);if(c){this._native=c.getNativeEvent()||null;this._originalTarget=c.getTarget()||null;}else{this._native=null;this._originalTarget=null;}return this;},clone:function(d){var e=qx.event.type.Event.prototype.clone.call(this,d);e._native=this._native;return e;},getDocumentLeft:function(){if(this._native==null){return 0;}if(this._native.pageX!==undefined){return this._native.pageX;}else{var f=qx.dom.Node.getWindow(this._native.srcElement);return this._native.clientX+qx.bom.Viewport.getScrollLeft(f);}},getDocumentTop:function(){if(this._native==null){return 0;}if(this._native.pageY!==undefined){return this._native.pageY;}else{var g=qx.dom.Node.getWindow(this._native.srcElement);return this._native.clientY+qx.bom.Viewport.getScrollTop(g);}},getManager:function(){return qx.event.Registration.getManager(this.getTarget()).getHandler(qx.event.handler.DragDrop);},addType:function(h){this.getManager().addType(h);},addAction:function(i){this.getManager().addAction(i);},supportsType:function(j){return this.getManager().supportsType(j);},supportsAction:function(k){return this.getManager().supportsAction(k);},addData:function(l,m){this.getManager().addData(l,m);},getData:function(n){return this.getManager().getData(n);},getCurrentType:function(){return this.getManager().getCurrentType();},getCurrentAction:function(){return this.getManager().getCurrentAction();}}});})();(function(){var h="interval",g="qx.event.Timer",f="_applyInterval",d="_applyEnabled",c="Boolean",b="qx.event.type.Event",a="Integer";qx.Class.define(g,{extend:qx.core.Object,construct:function(i){qx.core.Object.call(this);this.setEnabled(false);if(i!=null){this.setInterval(i);}var self=this;this.__ey=function(){self._oninterval.call(self);};},events:{"interval":b},statics:{once:function(j,k,l){var m=new qx.event.Timer(l);m.__ez=j;m.addListener(h,function(e){m.stop();j.call(k,e);m.dispose();k=null;},k);m.start();return m;}},properties:{enabled:{init:true,check:c,apply:d},interval:{check:a,init:1000,apply:f}},members:{__eA:null,__ey:null,_applyInterval:function(n,o){if(this.getEnabled()){this.restart();}},_applyEnabled:function(p,q){if(q){window.clearInterval(this.__eA);this.__eA=null;}else if(p){this.__eA=window.setInterval(this.__ey,this.getInterval());}},start:function(){this.setEnabled(true);},startWith:function(r){this.setInterval(r);this.start();},stop:function(){this.setEnabled(false);},restart:function(){this.stop();this.start();},restartWith:function(s){this.stop();this.startWith(s);},_oninterval:qx.event.GlobalError.observeMethod(function(){if(this.$$disposed){return;}if(this.getEnabled()){this.fireEvent(h);}})},destruct:function(){if(this.__eA){window.clearInterval(this.__eA);}this.__eA=this.__ey=null;}});})();(function(){var h="losecapture",g="qx.client",f="blur",e="focus",d="click",c="qx.event.dispatch.MouseCapture",b="capture",a="scroll";qx.Class.define(c,{extend:qx.event.dispatch.AbstractBubbling,construct:function(i,j){qx.event.dispatch.AbstractBubbling.call(this,i);this.__ix=i.getWindow();this.__iy=j;i.addListener(this.__ix,f,this.releaseCapture,this);i.addListener(this.__ix,e,this.releaseCapture,this);i.addListener(this.__ix,a,this.releaseCapture,this);},statics:{PRIORITY:qx.event.Registration.PRIORITY_FIRST},members:{__iy:null,__iz:null,__iA:true,__ix:null,_getParent:function(k){return k.parentNode;},canDispatchEvent:function(l,event,m){return (this.__iz&&this.__iB[m]);},dispatchEvent:function(n,event,o){if(o==d){event.stopPropagation();this.releaseCapture();return;}if(this.__iA||!qx.dom.Hierarchy.contains(this.__iz,n)){n=this.__iz;}qx.event.dispatch.AbstractBubbling.prototype.dispatchEvent.call(this,n,event,o);},__iB:{"mouseup":1,"mousedown":1,"click":1,"dblclick":1,"mousemove":1,"mouseout":1,"mouseover":1},activateCapture:function(p,q){var q=q!==false;if(this.__iz===p&&this.__iA==q){return;}if(this.__iz){this.releaseCapture();}this.nativeSetCapture(p,q);if(this.hasNativeCapture){var self=this;qx.bom.Event.addNativeListener(p,h,function(){qx.bom.Event.removeNativeListener(p,h,arguments.callee);self.releaseCapture();});}this.__iA=q;this.__iz=p;this.__iy.fireEvent(p,b,qx.event.type.Event,[true,false]);},getCaptureElement:function(){return this.__iz;},releaseCapture:function(){var r=this.__iz;if(!r){return;}this.__iz=null;this.__iy.fireEvent(r,h,qx.event.type.Event,[true,false]);this.nativeReleaseCapture(r);},hasNativeCapture:qx.bom.client.Engine.MSHTML,nativeSetCapture:qx.core.Variant.select(g,{"mshtml":function(s,t){qx.event.Timer.once(function(){s.setCapture(t!==false);},this,0);},"default":qx.lang.Function.empty}),nativeReleaseCapture:qx.core.Variant.select(g,{"mshtml":function(u){qx.event.Timer.once(function(){u.releaseCapture();},this,0);},"default":qx.lang.Function.empty})},destruct:function(){this.__iz=this.__ix=this.__iy=null;},defer:function(v){qx.event.Registration.addDispatcher(v);}});})();(function(){var a="qx.event.handler.Window";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(b){qx.core.Object.call(this);this._manager=b;this._window=b.getWindow();this._initWindowObserver();},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{error:1,load:1,beforeunload:1,unload:1,resize:1,scroll:1,beforeshutdown:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_WINDOW,IGNORE_CAN_HANDLE:true},members:{canHandleEvent:function(c,d){},registerEvent:function(f,g,h){},unregisterEvent:function(i,j,k){},_initWindowObserver:function(){this._onNativeWrapper=qx.lang.Function.listener(this._onNative,this);var m=qx.event.handler.Window.SUPPORTED_TYPES;for(var l in m){qx.bom.Event.addNativeListener(this._window,l,this._onNativeWrapper);}},_stopWindowObserver:function(){var o=qx.event.handler.Window.SUPPORTED_TYPES;for(var n in o){qx.bom.Event.removeNativeListener(this._window,n,this._onNativeWrapper);}},_onNative:qx.event.GlobalError.observeMethod(function(e){if(this.isDisposed()){return;}var q=this._window;try{var t=q.document;}catch(e){return ;}var r=t.documentElement;var p=qx.bom.Event.getTarget(e);if(p==null||p===q||p===t||p===r){var event=qx.event.Registration.createEvent(e.type,qx.event.type.Native,[e,q]);qx.event.Registration.dispatchEvent(q,event);var s=event.getReturnValue();if(s!=null){e.returnValue=s;return s;}}})},destruct:function(){this._stopWindowObserver();this._manager=this._window=null;},defer:function(u){qx.event.Registration.addHandler(u);}});})();(function(){var c="qx.bom.Selector";qx.Class.define(c,{statics:{query:null,matches:null}});(function(){var o=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,v=0,r=Object.prototype.toString,p=false,x=true;[0,0].sort(function(){x=false;return 0;});var g=function(z,A,B,C){B=B||[];A=A||document;var L=A;if(A.nodeType!==1&&A.nodeType!==9){return [];}if(!z||typeof z!=="string"){return B;}var m,F,D,H,J,G,M,i,N=true,E=g.isXML(A),I=[],K=z;do{o.exec("");m=o.exec(K);if(m){K=m[3];I.push(m[1]);if(m[2]){H=m[3];break;}}}while(m);if(I.length>1&&q.exec(z)){if(I.length===2&&k.relative[I[0]]){F=h(I[0]+I[1],A);}else{F=k.relative[I[0]]?[A]:g(I.shift(),A);while(I.length){z=I.shift();if(k.relative[z]){z+=I.shift();}F=h(z,F);}}}else{if(!C&&I.length>1&&A.nodeType===9&&!E&&k.match.ID.test(I[0])&&!k.match.ID.test(I[I.length-1])){J=g.find(I.shift(),A,E);A=J.expr?g.filter(J.expr,J.set)[0]:J.set[0];}if(A){J=C?{expr:I.pop(),set:f(C)}:g.find(I.pop(),I.length===1&&(I[0]==="~"||I[0]==="+")&&A.parentNode?A.parentNode:A,E);F=J.expr?g.filter(J.expr,J.set):J.set;if(I.length>0){D=f(F);}else{N=false;}while(I.length){G=I.pop();M=G;if(!k.relative[G]){G="";}else{M=I.pop();}if(M==null){M=A;}k.relative[G](D,M,E);}}else{D=I=[];}}if(!D){D=F;}if(!D){g.error(G||z);}if(r.call(D)==="[object Array]"){if(!N){B.push.apply(B,D);}else if(A&&A.nodeType===1){for(i=0;D[i]!=null;i++){if(D[i]&&(D[i]===true||D[i].nodeType===1&&g.contains(A,D[i]))){B.push(F[i]);}}}else{for(i=0;D[i]!=null;i++){if(D[i]&&D[i].nodeType===1){B.push(F[i]);}}}}else{f(D,B);}if(H){g(H,L,B,C);g.uniqueSort(B);}return B;};g.uniqueSort=function(O){if(s){p=x;O.sort(s);if(p){for(var i=1;i<O.length;i++){if(O[i]===O[i-1]){O.splice(i--,1);}}}}return O;};g.matches=function(P,Q){return g(P,null,null,Q);};g.matchesSelector=function(R,S){return g(S,null,null,[R]).length>0;};g.find=function(T,U,V){var W;if(!T){return [];}for(var i=0,l=k.order.length;i<l;i++){var Y,X=k.order[i];if((Y=k.leftMatch[X].exec(T))){var ba=Y[1];Y.splice(1,1);if(ba.substr(ba.length-1)!=="\\"){Y[1]=(Y[1]||"").replace(/\\/g,"");W=k.find[X](Y,U,V);if(W!=null){T=T.replace(k.match[X],"");break;}}}}if(!W){W=U.getElementsByTagName("*");}return {set:W,expr:T};};g.filter=function(bb,bc,bd,be){var br,bq,bf=bb,bk=[],bg=bc,bh=bc&&bc[0]&&g.isXML(bc[0]);while(bb&&bc.length){for(var bo in k.filter){if((br=k.leftMatch[bo].exec(bb))!=null&&br[2]){var bn,bj,bi=k.filter[bo],bs=br[1];bq=false;br.splice(1,1);if(bs.substr(bs.length-1)==="\\"){continue;}if(bg===bk){bk=[];}if(k.preFilter[bo]){br=k.preFilter[bo](br,bg,bd,bk,be,bh);if(!br){bq=bn=true;}else if(br===true){continue;}}if(br){for(var i=0;(bj=bg[i])!=null;i++){if(bj){bn=bi(bj,br,i,bg);var bm=be^!!bn;if(bd&&bn!=null){if(bm){bq=true;}else{bg[i]=false;}}else if(bm){bk.push(bj);bq=true;}}}}if(bn!==undefined){if(!bd){bg=bk;}bb=bb.replace(k.match[bo],"");if(!bq){return [];}break;}}}if(bb===bf){if(bq==null){g.error(bb);}else{break;}}bf=bb;}return bg;};g.error=function(bt){throw "Syntax error, unrecognized expression: "+bt;};var k=g.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(bu){return bu.getAttribute("href");}},relative:{"+":function(bv,bw){var bx=typeof bw==="string",bz=bx&&!/\W/.test(bw),bA=bx&&!bz;if(bz){bw=bw.toLowerCase();}for(var i=0,l=bv.length,by;i<l;i++){if((by=bv[i])){while((by=by.previousSibling)&&by.nodeType!==1){}bv[i]=bA||by&&by.nodeName.toLowerCase()===bw?by||false:by===bw;}}if(bA){g.filter(bw,bv,true);}},">":function(bB,bC){var bE,bD=typeof bC==="string",i=0,l=bB.length;if(bD&&!/\W/.test(bC)){bC=bC.toLowerCase();for(;i<l;i++){bE=bB[i];if(bE){var parent=bE.parentNode;bB[i]=parent.nodeName.toLowerCase()===bC?parent:false;}}}else{for(;i<l;i++){bE=bB[i];if(bE){bB[i]=bD?bE.parentNode:bE.parentNode===bC;}}if(bD){g.filter(bC,bB,true);}}},"":function(bF,bG,bH){var bK,bI=v++,bJ=w;if(typeof bG==="string"&&!/\W/.test(bG)){bG=bG.toLowerCase();bK=bG;bJ=y;}bJ("parentNode",bG,bI,bF,bK,bH);},"~":function(bL,bM,bN){var bQ,bO=v++,bP=w;if(typeof bM==="string"&&!/\W/.test(bM)){bM=bM.toLowerCase();bQ=bM;bP=y;}bP("previousSibling",bM,bO,bL,bQ,bN);}},find:{ID:function(bR,bS,bT){if(typeof bS.getElementById!=="undefined"&&!bT){var m=bS.getElementById(bR[1]);return m&&m.parentNode?[m]:[];}},NAME:function(bU,bV){if(typeof bV.getElementsByName!=="undefined"){var bX=[],bW=bV.getElementsByName(bU[1]);for(var i=0,l=bW.length;i<l;i++){if(bW[i].getAttribute("name")===bU[1]){bX.push(bW[i]);}}return bX.length===0?null:bX;}},TAG:function(bY,ca){return ca.getElementsByTagName(bY[1]);}},preFilter:{CLASS:function(cb,cc,cd,ce,cf,cg){cb=" "+cb[1].replace(/\\/g,"")+" ";if(cg){return cb;}for(var i=0,ch;(ch=cc[i])!=null;i++){if(ch){if(cf^(ch.className&&(" "+ch.className+" ").replace(/[\t\n]/g," ").indexOf(cb)>=0)){if(!cd){ce.push(ch);}}else if(cd){cc[i]=false;}}}return false;},ID:function(ci){return ci[1].replace(/\\/g,"");},TAG:function(cj,ck){return cj[1].toLowerCase();},CHILD:function(cl){if(cl[1]==="nth"){var cm=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(cl[2]==="even"&&"2n"||cl[2]==="odd"&&"2n+1"||!/\D/.test(cl[2])&&"0n+"+cl[2]||cl[2]);cl[2]=(cm[1]+(cm[2]||1))-0;cl[3]=cm[3]-0;}cl[0]=v++;return cl;},ATTR:function(cn,co,cp,cq,cr,cs){var name=cn[1].replace(/\\/g,"");if(!cs&&k.attrMap[name]){cn[1]=k.attrMap[name];}if(cn[2]==="~="){cn[4]=" "+cn[4]+" ";}return cn;},PSEUDO:function(ct,cu,cv,cw,cx){if(ct[1]==="not"){if((o.exec(ct[3])||"").length>1||/^\w/.test(ct[3])){ct[3]=g(ct[3],null,null,cu);}else{var cy=g.filter(ct[3],cu,cv,true^cx);if(!cv){cw.push.apply(cw,cy);}return false;}}else if(k.match.POS.test(ct[0])||k.match.CHILD.test(ct[0])){return true;}return ct;},POS:function(cz){cz.unshift(true);return cz;}},filters:{enabled:function(cA){return cA.disabled===false&&cA.type!=="hidden";},disabled:function(cB){return cB.disabled===true;},checked:function(cC){return cC.checked===true;},selected:function(cD){cD.parentNode.selectedIndex;return cD.selected===true;},parent:function(cE){return !!cE.firstChild;},empty:function(cF){return !cF.firstChild;},has:function(cG,i,cH){return !!g(cH[3],cG).length;},header:function(cI){return (/h\d/i).test(cI.nodeName);},text:function(cJ){return "text"===cJ.type;},radio:function(cK){return "radio"===cK.type;},checkbox:function(cL){return "checkbox"===cL.type;},file:function(cM){return "file"===cM.type;},password:function(cN){return "password"===cN.type;},submit:function(cO){return "submit"===cO.type;},image:function(cP){return "image"===cP.type;},reset:function(cQ){return "reset"===cQ.type;},button:function(cR){return "button"===cR.type||cR.nodeName.toLowerCase()==="button";},input:function(cS){return (/input|select|textarea|button/i).test(cS.nodeName);}},setFilters:{first:function(cT,i){return i===0;},last:function(cU,i,cV,cW){return i===cW.length-1;},even:function(cX,i){return i%2===0;},odd:function(cY,i){return i%2===1;},lt:function(da,i,db){return i<db[3]-0;},gt:function(dc,i,dd){return i>dd[3]-0;},nth:function(de,i,df){return df[3]-0===i;},eq:function(dg,i,dh){return dh[3]-0===i;}},filter:{PSEUDO:function(di,dj,i,dk){var name=dj[1],dl=k.filters[name];if(dl){return dl(di,i,dj,dk);}else if(name==="contains"){return (di.textContent||di.innerText||g.getText([di])||"").indexOf(dj[3])>=0;}else if(name==="not"){var dm=dj[3];for(var j=0,l=dm.length;j<l;j++){if(dm[j]===di){return false;}}return true;}else{g.error("Syntax error, unrecognized expression: "+name);}},CHILD:function(dn,dp){var dv=dp[1],dq=dn;switch(dv){case "only":case "first":while((dq=dq.previousSibling)){if(dq.nodeType===1){return false;}}if(dv==="first"){return true;}dq=dn;case "last":while((dq=dq.nextSibling)){if(dq.nodeType===1){return false;}}return true;case "nth":var dw=dp[2],ds=dp[3];if(dw===1&&ds===0){return true;}var du=dp[0],parent=dn.parentNode;if(parent&&(parent.sizcache!==du||!dn.nodeIndex)){var dr=0;for(dq=parent.firstChild;dq;dq=dq.nextSibling){if(dq.nodeType===1){dq.nodeIndex=++dr;}}parent.sizcache=du;}var dt=dn.nodeIndex-ds;if(dw===0){return dt===0;}else{return (dt%dw===0&&dt/dw>=0);}}},ID:function(dx,dy){return dx.nodeType===1&&dx.getAttribute("id")===dy;},TAG:function(dz,dA){return (dA==="*"&&dz.nodeType===1)||dz.nodeName.toLowerCase()===dA;},CLASS:function(dB,dC){return (" "+(dB.className||dB.getAttribute("class"))+" ").indexOf(dC)>-1;},ATTR:function(dD,dE){var name=dE[1],dI=k.attrHandle[name]?k.attrHandle[name](dD):dD[name]!=null?dD[name]:dD.getAttribute(name),dH=dI+"",dG=dE[2],dF=dE[4];return dI==null?dG==="!=":dG==="="?dH===dF:dG==="*="?dH.indexOf(dF)>=0:dG==="~="?(" "+dH+" ").indexOf(dF)>=0:!dF?dH&&dI!==false:dG==="!="?dH!==dF:dG==="^="?dH.indexOf(dF)===0:dG==="$="?dH.substr(dH.length-dF.length)===dF:dG==="|="?dH===dF||dH.substr(0,dF.length+1)===dF+"-":false;},POS:function(dJ,dK,i,dL){var name=dK[2],dM=k.setFilters[name];if(dM){return dM(dJ,i,dK,dL);}}}};var q=k.match.POS,d=function(dN,dO){return "\\"+(dO-0+1);};for(var u in k.match){k.match[u]=new RegExp(k.match[u].source+(/(?![^\[]*\])(?![^\(]*\))/.source));k.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+k.match[u].source.replace(/\\(\d+)/g,d));}var f=function(dP,dQ){dP=Array.prototype.slice.call(dP,0);if(dQ){dQ.push.apply(dQ,dP);return dQ;}return dP;};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType;}catch(e){f=function(dR,dS){var i=0,dT=dS||[];if(r.call(dR)==="[object Array]"){Array.prototype.push.apply(dT,dR);}else{if(typeof dR.length==="number"){for(var l=dR.length;i<l;i++){dT.push(dR[i]);}}else{for(;dR[i];i++){dT.push(dR[i]);}}}return dT;};}var s,n;if(document.documentElement.compareDocumentPosition){s=function(a,b){if(a===b){p=true;return 0;}if(!a.compareDocumentPosition||!b.compareDocumentPosition){return a.compareDocumentPosition?-1:1;}return a.compareDocumentPosition(b)&4?-1:1;};}else{s=function(a,b){var dY,dW,ea=[],eb=[],dV=a.parentNode,dX=b.parentNode,dU=dV;if(a===b){p=true;return 0;}else if(dV===dX){return n(a,b);}else if(!dV){return -1;}else if(!dX){return 1;}while(dU){ea.unshift(dU);dU=dU.parentNode;}dU=dX;while(dU){eb.unshift(dU);dU=dU.parentNode;}dY=ea.length;dW=eb.length;for(var i=0;i<dY&&i<dW;i++){if(ea[i]!==eb[i]){return n(ea[i],eb[i]);}}return i===dY?n(a,eb[i],-1):n(ea[i],b,1);};n=function(a,b,ec){if(a===b){return ec;}var ed=a.nextSibling;while(ed){if(ed===b){return -1;}ed=ed.nextSibling;}return 1;};}g.getText=function(ee){var eg="",ef;for(var i=0;ee[i];i++){ef=ee[i];if(ef.nodeType===3||ef.nodeType===4){eg+=ef.nodeValue;}else if(ef.nodeType!==8){eg+=g.getText(ef.childNodes);}}return eg;};(function(){var ej=document.createElement("div"),ei="script"+(new Date()).getTime(),eh=document.documentElement;ej.innerHTML="<a name='"+ei+"'/>";eh.insertBefore(ej,eh.firstChild);if(document.getElementById(ei)){k.find.ID=function(ek,el,em){if(typeof el.getElementById!=="undefined"&&!em){var m=el.getElementById(ek[1]);return m?m.id===ek[1]||typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id").nodeValue===ek[1]?[m]:undefined:[];}};k.filter.ID=function(en,eo){var ep=typeof en.getAttributeNode!=="undefined"&&en.getAttributeNode("id");return en.nodeType===1&&ep&&ep.nodeValue===eo;};}eh.removeChild(ej);eh=ej=null;})();(function(){var eq=document.createElement("div");eq.appendChild(document.createComment(""));if(eq.getElementsByTagName("*").length>0){k.find.TAG=function(er,es){var eu=es.getElementsByTagName(er[1]);if(er[1]==="*"){var et=[];for(var i=0;eu[i];i++){if(eu[i].nodeType===1){et.push(eu[i]);}}eu=et;}return eu;};}eq.innerHTML="<a href='#'></a>";if(eq.firstChild&&typeof eq.firstChild.getAttribute!=="undefined"&&eq.firstChild.getAttribute("href")!=="#"){k.attrHandle.href=function(ev){return ev.getAttribute("href",2);};}eq=null;})();if(document.querySelectorAll){(function(){var ex=g,ew=document.createElement("div"),ey="__sizzle__";ew.innerHTML="<p class='TEST'></p>";if(ew.querySelectorAll&&ew.querySelectorAll(".TEST").length===0){return;}g=function(eA,eB,eC,eD){eB=eB||document;eA=eA.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!eD&&!g.isXML(eB)){if(eB.nodeType===9){try{return f(eB.querySelectorAll(eA),eC);}catch(eG){}}else if(eB.nodeType===1&&eB.nodeName.toLowerCase()!=="object"){var eE=eB.getAttribute("id"),eF=eE||ey;if(!eE){eB.setAttribute("id",eF);}try{return f(eB.querySelectorAll("#"+eF+" "+eA),eC);}catch(eH){}finally{if(!eE){eB.removeAttribute("id");}}}}return ex(eA,eB,eC,eD);};for(var ez in ex){g[ez]=ex[ez];}ew=null;})();}(function(){var eK=document.documentElement,eI=eK.matchesSelector||eK.mozMatchesSelector||eK.webkitMatchesSelector||eK.msMatchesSelector,eJ=false;try{eI.call(document.documentElement,"[test!='']:sizzle");}catch(eL){eJ=true;}if(eI){g.matchesSelector=function(eM,eN){eN=eN.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!g.isXML(eM)){try{if(eJ||!k.match.PSEUDO.test(eN)&&!/!=/.test(eN)){return eI.call(eM,eN);}}catch(e){}}return g(eN,null,null,[eM]).length>0;};}})();(function(){var eO=document.createElement("div");eO.innerHTML="<div class='test e'></div><div class='test'></div>";if(!eO.getElementsByClassName||eO.getElementsByClassName("e").length===0){return;}eO.lastChild.className="e";if(eO.getElementsByClassName("e").length===1){return;}k.order.splice(1,0,"CLASS");k.find.CLASS=function(eP,eQ,eR){if(typeof eQ.getElementsByClassName!=="undefined"&&!eR){return eQ.getElementsByClassName(eP[1]);}};eO=null;})();function y(eS,eT,eU,eV,eW,eX){for(var i=0,l=eV.length;i<l;i++){var fa=eV[i];if(fa){var eY=false;fa=fa[eS];while(fa){if(fa.sizcache===eU){eY=eV[fa.sizset];break;}if(fa.nodeType===1&&!eX){fa.sizcache=eU;fa.sizset=i;}if(fa.nodeName.toLowerCase()===eT){eY=fa;break;}fa=fa[eS];}eV[i]=eY;}}}function w(fb,fc,fd,fe,ff,fg){for(var i=0,l=fe.length;i<l;i++){var fi=fe[i];if(fi){var fh=false;fi=fi[fb];while(fi){if(fi.sizcache===fd){fh=fe[fi.sizset];break;}if(fi.nodeType===1){if(!fg){fi.sizcache=fd;fi.sizset=i;}if(typeof fc!=="string"){if(fi===fc){fh=true;break;}}else if(g.filter(fc,[fi]).length>0){fh=fi;break;}}fi=fi[fb];}fe[i]=fh;}}}if(document.documentElement.contains){g.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):true);};}else if(document.documentElement.compareDocumentPosition){g.contains=function(a,b){return !!(a.compareDocumentPosition(b)&16);};}else{g.contains=function(){return false;};}g.isXML=function(fj){var fk=(fj?fj.ownerDocument||fj:0).documentElement;return fk?fk.nodeName!=="HTML":false;};var h=function(fl,fm){var fq,fo=[],fn="",fp=fm.nodeType?[fm]:fm;while((fq=k.match.PSEUDO.exec(fl))){fn+=fq[0];fl=fl.replace(k.match.PSEUDO,"");}fl=k.relative[fl]?fl+"*":fl;for(var i=0,l=fp.length;i<l;i++){g(fl,fp[i],fo);}return g.filter(fn,fo);};var t=qx.bom.Selector;t.query=function(fr,fs){return g(fr,fs);};t.matches=function(ft,fu){return g(ft,null,null,fu);};})();})();(function(){var r="qx.client",q="",p="mshtml",o="'",n="SelectionLanguage",m="qx.xml.Document",k=" />",j="MSXML2.DOMDocument.3.0",h='<\?xml version="1.0" encoding="utf-8"?>\n<',g="MSXML2.XMLHTTP.3.0",c="MSXML2.XMLHTTP.6.0",f=" xmlns='",e="text/xml",b="XPath",a="MSXML2.DOMDocument.6.0",d="HTML";qx.Class.define(m,{statics:{DOMDOC:null,XMLHTTP:null,isXmlDocument:function(s){if(s.nodeType===9){return s.documentElement.nodeName!==d;}else if(s.ownerDocument){return this.isXmlDocument(s.ownerDocument);}else{return false;}},create:qx.core.Variant.select(r,{"mshtml":function(t,u){var v=new ActiveXObject(this.DOMDOC);v.setProperty(n,b);if(u){var w=h;w+=u;if(t){w+=f+t+o;}w+=k;v.loadXML(w);}return v;},"default":function(x,y){return document.implementation.createDocument(x||q,y||q,null);}}),fromString:qx.core.Variant.select(r,{"mshtml":function(z){var A=qx.xml.Document.create();A.loadXML(z);return A;},"default":function(B){var C=new DOMParser();return C.parseFromString(B,e);}})},defer:function(D){if(qx.core.Variant.isSet(r,p)){var E=[a,j];var F=[c,g];for(var i=0,l=E.length;i<l;i++){try{new ActiveXObject(E[i]);new ActiveXObject(F[i]);}catch(G){continue;}D.DOMDOC=E[i];D.XMLHTTP=F[i];break;}}}});})();(function(){var k="visible",j="scroll",i="borderBottomWidth",h="borderTopWidth",g="left",f="borderLeftWidth",e="bottom",d="top",c="right",b="qx.bom.element.Scroll",a="borderRightWidth";qx.Class.define(b,{statics:{intoViewX:function(l,stop,m){var parent=l.parentNode;var r=qx.dom.Node.getDocument(l);var n=r.body;var z,x,u;var B,s,C;var v,D,G;var E,p,y,o;var t,F,w;var q=m===g;var A=m===c;stop=stop?stop.parentNode:r;while(parent&&parent!=stop){if(parent.scrollWidth>parent.clientWidth&&(parent===n||qx.bom.element.Overflow.getY(parent)!=k)){if(parent===n){x=parent.scrollLeft;u=x+qx.bom.Viewport.getWidth();B=qx.bom.Viewport.getWidth();s=parent.clientWidth;C=parent.scrollWidth;v=0;D=0;G=0;}else{z=qx.bom.element.Location.get(parent);x=z.left;u=z.right;B=parent.offsetWidth;s=parent.clientWidth;C=parent.scrollWidth;v=parseInt(qx.bom.element.Style.get(parent,f),10)||0;D=parseInt(qx.bom.element.Style.get(parent,a),10)||0;G=B-s-v-D;}E=qx.bom.element.Location.get(l);p=E.left;y=E.right;o=l.offsetWidth;t=p-x-v;F=y-u+D;w=0;if(q){w=t;}else if(A){w=F+G;}else if(t<0||o>s){w=t;}else if(F>0){w=F+G;}parent.scrollLeft+=w;if(qx.bom.client.Engine.GECKO||qx.bom.client.Engine.OPERA){qx.event.Registration.fireNonBubblingEvent(parent,j);}}if(parent===n){break;}parent=parent.parentNode;}},intoViewY:function(H,stop,I){var parent=H.parentNode;var O=qx.dom.Node.getDocument(H);var J=O.body;var W,K,S;var Y,V,Q;var M,N,L;var bb,bc,X,R;var U,P,bd;var ba=I===d;var T=I===e;stop=stop?stop.parentNode:O;while(parent&&parent!=stop){if(parent.scrollHeight>parent.clientHeight&&(parent===J||qx.bom.element.Overflow.getY(parent)!=k)){if(parent===J){K=parent.scrollTop;S=K+qx.bom.Viewport.getHeight();Y=qx.bom.Viewport.getHeight();V=parent.clientHeight;Q=parent.scrollHeight;M=0;N=0;L=0;}else{W=qx.bom.element.Location.get(parent);K=W.top;S=W.bottom;Y=parent.offsetHeight;V=parent.clientHeight;Q=parent.scrollHeight;M=parseInt(qx.bom.element.Style.get(parent,h),10)||0;N=parseInt(qx.bom.element.Style.get(parent,i),10)||0;L=Y-V-M-N;}bb=qx.bom.element.Location.get(H);bc=bb.top;X=bb.bottom;R=H.offsetHeight;U=bc-K-M;P=X-S+N;bd=0;if(ba){bd=U;}else if(T){bd=P+L;}else if(U<0||R>V){bd=U;}else if(P>0){bd=P+L;}parent.scrollTop+=bd;if(qx.bom.client.Engine.GECKO||qx.bom.client.Engine.OPERA){qx.event.Registration.fireNonBubblingEvent(parent,j);}}if(parent===J){break;}parent=parent.parentNode;}},intoView:function(be,stop,bf,bg){this.intoViewX(be,stop,bf);this.intoViewY(be,stop,bg);}}});})();(function(){var k="",j="qx.client",i="hidden",h="-moz-scrollbars-none",g="overflow",f=";",e="overflowY",d=":",b="overflowX",a="overflow:",y="none",x="scroll",w="borderLeftStyle",v="borderRightStyle",u="div",r="borderRightWidth",q="overflow-y",p="borderLeftWidth",o="-moz-scrollbars-vertical",n="100px",l="qx.bom.element.Overflow",m="overflow-x";qx.Class.define(l,{statics:{__kL:null,getScrollbarWidth:function(){if(this.__kL!==null){return this.__kL;}var z=qx.bom.element.Style;var B=function(F,G){return parseInt(z.get(F,G),10)||0;};var C=function(H){return (z.get(H,v)==y?0:B(H,r));};var A=function(I){return (z.get(I,w)==y?0:B(I,p));};var E=qx.core.Variant.select(j,{"mshtml":function(J){if(z.get(J,e)==i||J.clientWidth==0){return C(J);}return Math.max(0,J.offsetWidth-J.clientLeft-J.clientWidth);},"default":function(K){if(K.clientWidth==0){var L=z.get(K,g);var M=(L==x||L==o?16:0);return Math.max(0,C(K)+M);}return Math.max(0,(K.offsetWidth-K.clientWidth-A(K)));}});var D=function(N){return E(N)-C(N);};var t=document.createElement(u);var s=t.style;s.height=s.width=n;s.overflow=x;document.body.appendChild(t);var c=D(t);this.__kL=c?c:16;document.body.removeChild(t);return this.__kL;},_compile:qx.core.Variant.select(j,{"gecko":qx.bom.client.Engine.VERSION<1.8?function(O,P){if(P==i){P=h;}return a+P+f;}:function(Q,R){return Q+d+R+f;},"opera":qx.bom.client.Engine.VERSION<9.5?function(S,T){return a+T+f;}:function(U,V){return U+d+V+f;},"default":function(W,X){return W+d+X+f;}}),compileX:function(Y){return this._compile(m,Y);},compileY:function(ba){return this._compile(q,ba);},getX:qx.core.Variant.select(j,{"gecko":qx.bom.client.Engine.VERSION<1.8?function(bb,bc){var bd=qx.bom.element.Style.get(bb,g,bc,false);if(bd===h){bd=i;}return bd;}:function(be,bf){return qx.bom.element.Style.get(be,b,bf,false);},"opera":qx.bom.client.Engine.VERSION<9.5?function(bg,bh){return qx.bom.element.Style.get(bg,g,bh,false);}:function(bi,bj){return qx.bom.element.Style.get(bi,b,bj,false);},"default":function(bk,bl){return qx.bom.element.Style.get(bk,b,bl,false);}}),setX:qx.core.Variant.select(j,{"gecko":qx.bom.client.Engine.VERSION<1.8?function(bm,bn){if(bn==i){bn=h;}bm.style.overflow=bn;}:function(bo,bp){bo.style.overflowX=bp;},"opera":qx.bom.client.Engine.VERSION<9.5?function(bq,br){bq.style.overflow=br;}:function(bs,bt){bs.style.overflowX=bt;},"default":function(bu,bv){bu.style.overflowX=bv;}}),resetX:qx.core.Variant.select(j,{"gecko":qx.bom.client.Engine.VERSION<1.8?function(bw){bw.style.overflow=k;}:function(bx){bx.style.overflowX=k;},"opera":qx.bom.client.Engine.VERSION<9.5?function(by,bz){by.style.overflow=k;}:function(bA,bB){bA.style.overflowX=k;},"default":function(bC){bC.style.overflowX=k;}}),getY:qx.core.Variant.select(j,{"gecko":qx.bom.client.Engine.VERSION<1.8?function(bD,bE){var bF=qx.bom.element.Style.get(bD,g,bE,false);if(bF===h){bF=i;}return bF;}:function(bG,bH){return qx.bom.element.Style.get(bG,e,bH,false);},"opera":qx.bom.client.Engine.VERSION<9.5?function(bI,bJ){return qx.bom.element.Style.get(bI,g,bJ,false);}:function(bK,bL){return qx.bom.element.Style.get(bK,e,bL,false);},"default":function(bM,bN){return qx.bom.element.Style.get(bM,e,bN,false);}}),setY:qx.core.Variant.select(j,{"gecko":qx.bom.client.Engine.VERSION<1.8?function(bO,bP){if(bP===i){bP=h;}bO.style.overflow=bP;}:function(bQ,bR){bQ.style.overflowY=bR;},"opera":qx.bom.client.Engine.VERSION<9.5?function(bS,bT){bS.style.overflow=bT;}:function(bU,bV){bU.style.overflowY=bV;},"default":function(bW,bX){bW.style.overflowY=bX;}}),resetY:qx.core.Variant.select(j,{"gecko":qx.bom.client.Engine.VERSION<1.8?function(bY){bY.style.overflow=k;}:function(ca){ca.style.overflowY=k;},"opera":qx.bom.client.Engine.VERSION<9.5?function(cb,cc){cb.style.overflow=k;}:function(cd,ce){cd.style.overflowY=k;},"default":function(cf){cf.style.overflowY=k;}})}});})();(function(){var q="qx.client",p="",o="boxSizing",n="box-sizing",m=":",k="border-box",j="qx.bom.element.BoxSizing",h="KhtmlBoxSizing",g="-moz-box-sizing",f="WebkitBoxSizing",c=";",e="-khtml-box-sizing",d="content-box",b="-webkit-box-sizing",a="MozBoxSizing";qx.Class.define(j,{statics:{__cH:qx.core.Variant.select(q,{"mshtml":null,"webkit":[o,h,f],"gecko":[a],"opera":[o]}),__cI:qx.core.Variant.select(q,{"mshtml":null,"webkit":[n,e,b],"gecko":[g],"opera":[n]}),__cJ:{tags:{button:true,select:true},types:{search:true,button:true,submit:true,reset:true,checkbox:true,radio:true}},__cK:function(r){var s=this.__cJ;return s.tags[r.tagName.toLowerCase()]||s.types[r.type];},compile:qx.core.Variant.select(q,{"mshtml":function(t){{};},"default":function(u){var w=this.__cI;var v=p;if(w){for(var i=0,l=w.length;i<l;i++){v+=w[i]+m+u+c;}}return v;}}),get:qx.core.Variant.select(q,{"mshtml":function(x){if(qx.bom.Document.isStandardMode(qx.dom.Node.getDocument(x))){if(!this.__cK(x)){return d;}}return k;},"default":function(y){var A=this.__cH;var z;if(A){for(var i=0,l=A.length;i<l;i++){z=qx.bom.element.Style.get(y,A[i],null,false);if(z!=null&&z!==p){return z;}}}return p;}}),set:qx.core.Variant.select(q,{"mshtml":function(B,C){{};},"default":function(D,E){var F=this.__cH;if(F){for(var i=0,l=F.length;i<l;i++){D.style[F[i]]=E;}}}}),reset:function(G){this.set(G,p);}}});})();(function(){var k="n-resize",j="e-resize",i="nw-resize",h="ne-resize",g="",f="cursor:",e="qx.client",d=";",c="qx.bom.element.Cursor",b="cursor",a="hand";qx.Class.define(c,{statics:{__eR:qx.core.Variant.select(e,{"mshtml":{"cursor":a,"ew-resize":j,"ns-resize":k,"nesw-resize":h,"nwse-resize":i},"opera":{"col-resize":j,"row-resize":k,"ew-resize":j,"ns-resize":k,"nesw-resize":h,"nwse-resize":i},"default":{}}),compile:function(l){return f+(this.__eR[l]||l)+d;},get:function(m,n){return qx.bom.element.Style.get(m,b,n,false);},set:function(o,p){o.style.cursor=this.__eR[p]||p;},reset:function(q){q.style.cursor=g;}}});})();(function(){var o="auto",n="px",m=",",l="clip:auto;",k="rect(",j=");",i="",h=")",g="qx.bom.element.Clip",f="string",c="clip:rect(",e=" ",d="clip",b="rect(auto,auto,auto,auto)",a="rect(auto, auto, auto, auto)";qx.Class.define(g,{statics:{compile:function(p){if(!p){return l;}var u=p.left;var top=p.top;var t=p.width;var s=p.height;var q,r;if(u==null){q=(t==null?o:t+n);u=o;}else{q=(t==null?o:u+t+n);u=u+n;}if(top==null){r=(s==null?o:s+n);top=o;}else{r=(s==null?o:top+s+n);top=top+n;}return c+top+m+q+m+r+m+u+j;},get:function(v,w){var y=qx.bom.element.Style.get(v,d,w,false);var E,top,C,B;var x,z;if(typeof y===f&&y!==o&&y!==i){y=qx.lang.String.trim(y);if(/\((.*)\)/.test(y)){var D=RegExp.$1;if(/,/.test(D)){var A=D.split(m);}else{var A=D.split(e);}top=qx.lang.String.trim(A[0]);x=qx.lang.String.trim(A[1]);z=qx.lang.String.trim(A[2]);E=qx.lang.String.trim(A[3]);if(E===o){E=null;}if(top===o){top=null;}if(x===o){x=null;}if(z===o){z=null;}if(top!=null){top=parseInt(top,10);}if(x!=null){x=parseInt(x,10);}if(z!=null){z=parseInt(z,10);}if(E!=null){E=parseInt(E,10);}if(x!=null&&E!=null){C=x-E;}else if(x!=null){C=x;}if(z!=null&&top!=null){B=z-top;}else if(z!=null){B=z;}}else{throw new Error("Could not parse clip string: "+y);}}return {left:E||null,top:top||null,width:C||null,height:B||null};},set:function(F,G){if(!G){F.style.clip=b;return;}var L=G.left;var top=G.top;var K=G.width;var J=G.height;var H,I;if(L==null){H=(K==null?o:K+n);L=o;}else{H=(K==null?o:L+K+n);L=L+n;}if(top==null){I=(J==null?o:J+n);top=o;}else{I=(J==null?o:top+J+n);top=top+n;}F.style.clip=k+top+m+H+m+I+m+L+h;},reset:function(M){M.style.clip=a;}}});})();(function(){var m="",l="qx.client",k=";",j="opacity:",i="opacity",h="filter",g="MozOpacity",f=");",e=")",d="zoom:1;filter:alpha(opacity=",a="qx.bom.element.Opacity",c="alpha(opacity=",b="-moz-opacity:";qx.Class.define(a,{statics:{SUPPORT_CSS3_OPACITY:false,compile:qx.core.Variant.select(l,{"mshtml":function(n){if(n>=1){n=1;}if(n<0.00001){n=0;}if(qx.bom.element.Opacity.SUPPORT_CSS3_OPACITY){return j+n+k;}else{return d+(n*100)+f;}},"gecko":function(o){if(o>=1){o=0.999999;}if(!qx.bom.element.Opacity.SUPPORT_CSS3_OPACITY){return b+o+k;}else{return j+o+k;}},"default":function(p){if(p>=1){return m;}return j+p+k;}}),set:qx.core.Variant.select(l,{"mshtml":function(q,r){if(qx.bom.element.Opacity.SUPPORT_CSS3_OPACITY){if(r>=1){r=m;}q.style.opacity=r;}else{var s=qx.bom.element.Style.get(q,h,qx.bom.element.Style.COMPUTED_MODE,false);if(r>=1){r=1;}if(r<0.00001){r=0;}if(!q.currentStyle||!q.currentStyle.hasLayout){q.style.zoom=1;}q.style.filter=s.replace(/alpha\([^\)]*\)/gi,m)+c+r*100+e;}},"gecko":function(t,u){if(u>=1){u=0.999999;}if(!qx.bom.element.Opacity.SUPPORT_CSS3_OPACITY){t.style.MozOpacity=u;}else{t.style.opacity=u;}},"default":function(v,w){if(w>=1){w=m;}v.style.opacity=w;}}),reset:qx.core.Variant.select(l,{"mshtml":function(x){if(qx.bom.element.Opacity.SUPPORT_CSS3_OPACITY){x.style.opacity=m;}else{var y=qx.bom.element.Style.get(x,h,qx.bom.element.Style.COMPUTED_MODE,false);x.style.filter=y.replace(/alpha\([^\)]*\)/gi,m);}},"gecko":function(z){if(!qx.bom.element.Opacity.SUPPORT_CSS3_OPACITY){z.style.MozOpacity=m;}else{z.style.opacity=m;}},"default":function(A){A.style.opacity=m;}}),get:qx.core.Variant.select(l,{"mshtml":function(B,C){if(qx.bom.element.Opacity.SUPPORT_CSS3_OPACITY){var D=qx.bom.element.Style.get(B,i,C,false);if(D!=null){return parseFloat(D);}return 1.0;}else{var E=qx.bom.element.Style.get(B,h,C,false);if(E){var D=E.match(/alpha\(opacity=(.*)\)/);if(D&&D[1]){return parseFloat(D[1])/100;}}return 1.0;}},"gecko":function(F,G){var H=qx.bom.element.Style.get(F,!qx.bom.element.Opacity.SUPPORT_CSS3_OPACITY?g:i,G,false);if(H==0.999999){H=1.0;}if(H!=null){return parseFloat(H);}return 1.0;},"default":function(I,J){var K=qx.bom.element.Style.get(I,i,J,false);if(K!=null){return parseFloat(K);}return 1.0;}})},defer:function(L){L.SUPPORT_CSS3_OPACITY=(typeof document.documentElement.style.opacity=="string");}});})();(function(){var m="",k="qx.client",h="userSelect",g="style",f="MozUserModify",e="px",d="float",c="borderImage",b="styleFloat",a="appearance",F="pixelHeight",E='Ms',D=":",C="cssFloat",B="pixelTop",A="pixelLeft",z='O',y="qx.bom.element.Style",x='Khtml',w='string',t="pixelRight",u='Moz',r="pixelWidth",s="pixelBottom",p=";",q="textOverflow",n="userModify",o='Webkit',v="WebkitUserModify";qx.Class.define(y,{statics:{__cr:function(){var G=[a,h,q,c];var K={};var H=document.documentElement.style;var L=[u,o,x,z,E];for(var i=0,l=G.length;i<l;i++){var M=G[i];var I=M;if(H[M]){K[I]=M;continue;}M=qx.lang.String.firstUp(M);for(var j=0,N=L.length;j<N;j++){var J=L[j]+M;if(typeof H[J]==w){K[I]=J;break;}}}this.__cs=K;this.__cs[n]=qx.core.Variant.select(k,{"gecko":f,"webkit":v,"default":h});this.__ct={};for(var I in K){this.__ct[I]=this.__cx(K[I]);}this.__cs[d]=qx.core.Variant.select(k,{"mshtml":b,"default":C});},__cu:{width:r,height:F,left:A,right:t,top:B,bottom:s},__cv:{clip:qx.bom.element.Clip,cursor:qx.bom.element.Cursor,opacity:qx.bom.element.Opacity,boxSizing:qx.bom.element.BoxSizing,overflowX:{set:qx.lang.Function.bind(qx.bom.element.Overflow.setX,qx.bom.element.Overflow),get:qx.lang.Function.bind(qx.bom.element.Overflow.getX,qx.bom.element.Overflow),reset:qx.lang.Function.bind(qx.bom.element.Overflow.resetX,qx.bom.element.Overflow),compile:qx.lang.Function.bind(qx.bom.element.Overflow.compileX,qx.bom.element.Overflow)},overflowY:{set:qx.lang.Function.bind(qx.bom.element.Overflow.setY,qx.bom.element.Overflow),get:qx.lang.Function.bind(qx.bom.element.Overflow.getY,qx.bom.element.Overflow),reset:qx.lang.Function.bind(qx.bom.element.Overflow.resetY,qx.bom.element.Overflow),compile:qx.lang.Function.bind(qx.bom.element.Overflow.compileY,qx.bom.element.Overflow)}},compile:function(O){var Q=[];var S=this.__cv;var R=this.__ct;var name,P;for(name in O){P=O[name];if(P==null){continue;}name=R[name]||name;if(S[name]){Q.push(S[name].compile(P));}else{Q.push(this.__cx(name),D,P,p);}}return Q.join(m);},__cw:{},__cx:function(T){var U=this.__cw;var V=U[T];if(!V){V=U[T]=qx.lang.String.hyphenate(T);}return V;},setCss:qx.core.Variant.select(k,{"mshtml":function(W,X){W.style.cssText=X;},"default":function(Y,ba){Y.setAttribute(g,ba);}}),getCss:qx.core.Variant.select(k,{"mshtml":function(bb){return bb.style.cssText.toLowerCase();},"default":function(bc){return bc.getAttribute(g);}}),isPropertySupported:function(bd){return (this.__cv[bd]||this.__cs[bd]||bd in document.documentElement.style);},COMPUTED_MODE:1,CASCADED_MODE:2,LOCAL_MODE:3,set:function(be,name,bf,bg){{};name=this.__cs[name]||name;if(bg!==false&&this.__cv[name]){return this.__cv[name].set(be,bf);}else{be.style[name]=bf!==null?bf:m;}},setStyles:function(bh,bi,bj){{};var bm=this.__cs;var bo=this.__cv;var bk=bh.style;for(var bn in bi){var bl=bi[bn];var name=bm[bn]||bn;if(bl===undefined){if(bj!==false&&bo[name]){bo[name].reset(bh);}else{bk[name]=m;}}else{if(bj!==false&&bo[name]){bo[name].set(bh,bl);}else{bk[name]=bl!==null?bl:m;}}}},reset:function(bp,name,bq){name=this.__cs[name]||name;if(bq!==false&&this.__cv[name]){return this.__cv[name].reset(bp);}else{bp.style[name]=m;}},get:qx.core.Variant.select(k,{"mshtml":function(br,name,bs,bt){name=this.__cs[name]||name;if(bt!==false&&this.__cv[name]){return this.__cv[name].get(br,bs);}if(!br.currentStyle){return br.style[name]||m;}switch(bs){case this.LOCAL_MODE:return br.style[name]||m;case this.CASCADED_MODE:return br.currentStyle[name]||m;default:var bx=br.currentStyle[name]||m;if(/^-?[\.\d]+(px)?$/i.test(bx)){return bx;}var bw=this.__cu[name];if(bw){var bu=br.style[name];br.style[name]=bx||0;var bv=br.style[bw]+e;br.style[name]=bu;return bv;}if(/^-?[\.\d]+(em|pt|%)?$/i.test(bx)){throw new Error("Untranslated computed property value: "+name+". Only pixel values work well across different clients.");}return bx;}},"default":function(by,name,bz,bA){name=this.__cs[name]||name;if(bA!==false&&this.__cv[name]){return this.__cv[name].get(by,bz);}switch(bz){case this.LOCAL_MODE:return by.style[name]||m;case this.CASCADED_MODE:if(by.currentStyle){return by.currentStyle[name]||m;}throw new Error("Cascaded styles are not supported in this browser!");default:var bB=qx.dom.Node.getDocument(by);var bC=bB.defaultView.getComputedStyle(by,null);return bC?bC[name]:m;}}})},defer:function(bD){bD.__cr();}});})();(function(){var j="borderTopWidth",i="borderLeftWidth",h="marginTop",g="marginLeft",f="scroll",e="qx.client",d="border-box",c="borderBottomWidth",b="borderRightWidth",a="auto",y="padding",x="qx.bom.element.Location",w="paddingLeft",v="static",u="marginBottom",t="visible",s="BODY",r="paddingBottom",q="paddingTop",p="marginRight",n="position",o="margin",l="overflow",m="paddingRight",k="border";qx.Class.define(x,{statics:{__iY:function(z,A){return qx.bom.element.Style.get(z,A,qx.bom.element.Style.COMPUTED_MODE,false);},__ja:function(B,C){return parseInt(qx.bom.element.Style.get(B,C,qx.bom.element.Style.COMPUTED_MODE,false),10)||0;},__jb:function(D){var G=0,top=0;if(D.getBoundingClientRect&&!qx.bom.client.Engine.OPERA){var F=qx.dom.Node.getWindow(D);G-=qx.bom.Viewport.getScrollLeft(F);top-=qx.bom.Viewport.getScrollTop(F);}else{var E=qx.dom.Node.getDocument(D).body;D=D.parentNode;while(D&&D!=E){G+=D.scrollLeft;top+=D.scrollTop;D=D.parentNode;}}return {left:G,top:top};},__jc:qx.core.Variant.select(e,{"mshtml":function(H){var J=qx.dom.Node.getDocument(H);var I=J.body;var K=0;var top=0;K-=I.clientLeft+J.documentElement.clientLeft;top-=I.clientTop+J.documentElement.clientTop;if(qx.bom.client.Feature.STANDARD_MODE){K+=this.__ja(I,i);top+=this.__ja(I,j);}return {left:K,top:top};},"webkit":function(L){var N=qx.dom.Node.getDocument(L);var M=N.body;var O=M.offsetLeft;var top=M.offsetTop;if(qx.bom.client.Engine.VERSION<530.17){O+=this.__ja(M,i);top+=this.__ja(M,j);}return {left:O,top:top};},"gecko":function(P){var Q=qx.dom.Node.getDocument(P).body;var R=Q.offsetLeft;var top=Q.offsetTop;if(qx.bom.client.Engine.VERSION<1.9){R+=this.__ja(Q,g);top+=this.__ja(Q,h);}if(qx.bom.element.BoxSizing.get(Q)!==d){R+=this.__ja(Q,i);top+=this.__ja(Q,j);}return {left:R,top:top};},"default":function(S){var T=qx.dom.Node.getDocument(S).body;var U=T.offsetLeft;var top=T.offsetTop;return {left:U,top:top};}}),__jd:qx.core.Variant.select(e,{"mshtml|webkit":function(V){var X=qx.dom.Node.getDocument(V);if(V.getBoundingClientRect){var Y=V.getBoundingClientRect();var ba=Y.left;var top=Y.top;}else{var ba=V.offsetLeft;var top=V.offsetTop;V=V.offsetParent;var W=X.body;while(V&&V!=W){ba+=V.offsetLeft;top+=V.offsetTop;ba+=this.__ja(V,i);top+=this.__ja(V,j);V=V.offsetParent;}}return {left:ba,top:top};},"gecko":function(bb){if(bb.getBoundingClientRect){var be=bb.getBoundingClientRect();var bf=Math.round(be.left);var top=Math.round(be.top);}else{var bf=0;var top=0;var bc=qx.dom.Node.getDocument(bb).body;var bd=qx.bom.element.BoxSizing;if(bd.get(bb)!==d){bf-=this.__ja(bb,i);top-=this.__ja(bb,j);}while(bb&&bb!==bc){bf+=bb.offsetLeft;top+=bb.offsetTop;if(bd.get(bb)!==d){bf+=this.__ja(bb,i);top+=this.__ja(bb,j);}if(bb.parentNode&&this.__iY(bb.parentNode,l)!=t){bf+=this.__ja(bb.parentNode,i);top+=this.__ja(bb.parentNode,j);}bb=bb.offsetParent;}}return {left:bf,top:top};},"default":function(bg){var bi=0;var top=0;var bh=qx.dom.Node.getDocument(bg).body;while(bg&&bg!==bh){bi+=bg.offsetLeft;top+=bg.offsetTop;bg=bg.offsetParent;}return {left:bi,top:top};}}),get:function(bj,bk){if(bj.tagName==s){var location=this.__je(bj);var br=location.left;var top=location.top;}else{var bl=this.__jc(bj);var bq=this.__jd(bj);var scroll=this.__jb(bj);var br=bq.left+bl.left-scroll.left;var top=bq.top+bl.top-scroll.top;}var bm=br+bj.offsetWidth;var bn=top+bj.offsetHeight;if(bk){if(bk==y||bk==f){var bo=qx.bom.element.Overflow.getX(bj);if(bo==f||bo==a){bm+=bj.scrollWidth-bj.offsetWidth+this.__ja(bj,i)+this.__ja(bj,b);}var bp=qx.bom.element.Overflow.getY(bj);if(bp==f||bp==a){bn+=bj.scrollHeight-bj.offsetHeight+this.__ja(bj,j)+this.__ja(bj,c);}}switch(bk){case y:br+=this.__ja(bj,w);top+=this.__ja(bj,q);bm-=this.__ja(bj,m);bn-=this.__ja(bj,r);case f:br-=bj.scrollLeft;top-=bj.scrollTop;bm-=bj.scrollLeft;bn-=bj.scrollTop;case k:br+=this.__ja(bj,i);top+=this.__ja(bj,j);bm-=this.__ja(bj,b);bn-=this.__ja(bj,c);break;case o:br-=this.__ja(bj,g);top-=this.__ja(bj,h);bm+=this.__ja(bj,p);bn+=this.__ja(bj,u);break;}}return {left:br,top:top,right:bm,bottom:bn};},__je:qx.core.Variant.select(e,{"default":function(bs){var top=bs.offsetTop+this.__ja(bs,h);var bt=bs.offsetLeft+this.__ja(bs,g);return {left:bt,top:top};},"mshtml":function(bu){var top=bu.offsetTop;var bv=bu.offsetLeft;if(!((qx.bom.client.Engine.VERSION<8||qx.bom.client.Engine.DOCUMENT_MODE<8)&&!qx.bom.client.Feature.QUIRKS_MODE)){top+=this.__ja(bu,h);bv+=this.__ja(bu,g);}return {left:bv,top:top};},"gecko":function(bw){var top=bw.offsetTop+this.__ja(bw,h)+this.__ja(bw,i);var bx=bw.offsetLeft+this.__ja(bw,g)+this.__ja(bw,j);return {left:bx,top:top};}}),getLeft:function(by,bz){return this.get(by,bz).left;},getTop:function(bA,bB){return this.get(bA,bB).top;},getRight:function(bC,bD){return this.get(bC,bD).right;},getBottom:function(bE,bF){return this.get(bE,bF).bottom;},getRelative:function(bG,bH,bI,bJ){var bL=this.get(bG,bI);var bK=this.get(bH,bJ);return {left:bL.left-bK.left,top:bL.top-bK.top,right:bL.right-bK.right,bottom:bL.bottom-bK.bottom};},getPosition:function(bM){return this.getRelative(bM,this.getOffsetParent(bM));},getOffsetParent:function(bN){var bP=bN.offsetParent||document.body;var bO=qx.bom.element.Style;while(bP&&(!/^body|html$/i.test(bP.tagName)&&bO.get(bP,n)===v)){bP=bP.offsetParent;}return bP;}}});})();(function(){var b="qx.ui.core.queue.Widget",a="widget";qx.Class.define(b,{statics:{__iQ:{},remove:function(c){delete this.__iQ[c.$$hash];},add:function(d){var e=this.__iQ;if(e[d.$$hash]){return;}e[d.$$hash]=d;qx.ui.core.queue.Manager.scheduleFlush(a);},flush:function(){var f=this.__iQ;var h;for(var g in f){h=f[g];delete f[g];h.syncWidget();}for(var g in f){return;}this.__iQ={};}}});})();(function(){var b="qx.ui.core.queue.Visibility",a="visibility";qx.Class.define(b,{statics:{__iC:{},__iD:{},remove:function(c){var d=c.$$hash;delete this.__iD[d];delete this.__iC[d];},isVisible:function(e){return this.__iD[e.$$hash]||false;},__iE:function(f){var h=this.__iD;var g=f.$$hash;var i;if(f.isExcluded()){i=false;}else{var parent=f.$$parent;if(parent){i=this.__iE(parent);}else{i=f.isRootWidget();}}return h[g]=i;},add:function(j){var k=this.__iC;if(k[j.$$hash]){return;}k[j.$$hash]=j;qx.ui.core.queue.Manager.scheduleFlush(a);},flush:function(){var l=this.__iC;var p=this.__iD;for(var m in l){if(p[m]!=null){l[m].addChildrenToQueue(l);}}var o={};for(var m in l){o[m]=p[m];p[m]=null;}for(var m in l){var n=l[m];delete l[m];if(p[m]==null){this.__iE(n);}if(p[m]&&p[m]!=o[m]){n.checkAppearanceNeeds();}}this.__iC={};}}});})();(function(){var b="appearance",a="qx.ui.core.queue.Appearance";qx.Class.define(a,{statics:{__hL:{},remove:function(c){delete this.__hL[c.$$hash];},add:function(d){var e=this.__hL;if(e[d.$$hash]){return;}e[d.$$hash]=d;qx.ui.core.queue.Manager.scheduleFlush(b);},has:function(f){return !!this.__hL[f.$$hash];},flush:function(){var j=qx.ui.core.queue.Visibility;var g=this.__hL;var i;for(var h in g){i=g[h];delete g[h];if(j.isVisible(i)){i.syncAppearance();}else{i.$$stateChanges=true;}}}}});})();(function(){var b="qx.ui.core.queue.Layout",a="layout";qx.Class.define(b,{statics:{__if:{},remove:function(c){delete this.__if[c.$$hash];},add:function(d){this.__if[d.$$hash]=d;qx.ui.core.queue.Manager.scheduleFlush(a);},flush:function(){var e=this.__ii();for(var i=e.length-1;i>=0;i--){var f=e[i];if(f.hasValidLayout()){continue;}if(f.isRootWidget()&&!f.hasUserBounds()){var h=f.getSizeHint();f.renderLayout(0,0,h.width,h.height);}else{var g=f.getBounds();f.renderLayout(g.left,g.top,g.width,g.height);}}},getNestingLevel:function(j){var k=this.__ih;var m=0;var parent=j;while(true){if(k[parent.$$hash]!=null){m+=k[parent.$$hash];break;}if(!parent.$$parent){break;}parent=parent.$$parent;m+=1;}var l=m;while(j&&j!==parent){k[j.$$hash]=l--;j=j.$$parent;}return m;},__ig:function(){var s=qx.ui.core.queue.Visibility;this.__ih={};var r=[];var q=this.__if;var n,p;for(var o in q){n=q[o];if(s.isVisible(n)){p=this.getNestingLevel(n);if(!r[p]){r[p]={};}r[p][o]=n;delete q[o];}}return r;},__ii:function(){var w=[];var y=this.__ig();for(var v=y.length-1;v>=0;v--){if(!y[v]){continue;}for(var u in y[v]){var t=y[v][u];if(v==0||t.isRootWidget()||t.hasUserBounds()){w.push(t);t.invalidateLayoutCache();continue;}var A=t.getSizeHint(false);if(A){t.invalidateLayoutCache();var x=t.getSizeHint();var z=(!t.getBounds()||A.minWidth!==x.minWidth||A.width!==x.width||A.maxWidth!==x.maxWidth||A.minHeight!==x.minHeight||A.height!==x.height||A.maxHeight!==x.maxHeight);}else{z=true;}if(z){var parent=t.getLayoutParent();if(!y[v-1]){y[v-1]={};}y[v-1][parent.$$hash]=parent;}else{w.push(t);}}}return w;}}});})();(function(){var b="dispose",a="qx.ui.core.queue.Dispose";qx.Class.define(a,{statics:{__eX:{},add:function(c){var d=this.__eX;if(d[c.$$hash]){return;}d[c.$$hash]=c;qx.ui.core.queue.Manager.scheduleFlush(b);},flush:function(){var e=this.__eX;for(var g in e){var f=e[g];delete e[g];f.dispose();}for(var g in e){return;}this.__eX={};}}});})();(function(){var a="qx.ui.core.MChildrenHandling";qx.Mixin.define(a,{members:{getChildren:function(){return this._getChildren();},hasChildren:function(){return this._hasChildren();},indexOf:function(b){return this._indexOf(b);},add:function(c,d){this._add(c,d);},addAt:function(e,f,g){this._addAt(e,f,g);},addBefore:function(h,i,j){this._addBefore(h,i,j);},addAfter:function(k,l,m){this._addAfter(k,l,m);},remove:function(n){this._remove(n);},removeAt:function(o){return this._removeAt(o);},removeAll:function(){this._removeAll();}},statics:{remap:function(p){p.getChildren=p._getChildren;p.hasChildren=p._hasChildren;p.indexOf=p._indexOf;p.add=p._add;p.addAt=p._addAt;p.addBefore=p._addBefore;p.addAfter=p._addAfter;p.remove=p._remove;p.removeAt=p._removeAt;p.removeAll=p._removeAll;}}});})();(function(){var a="qx.ui.core.MLayoutHandling";qx.Mixin.define(a,{members:{setLayout:function(b){return this._setLayout(b);},getLayout:function(){return this._getLayout();}},statics:{remap:function(c){c.getLayout=c._getLayout;c.setLayout=c._setLayout;}}});})();(function(){var j="Integer",i="_applyDimension",h="Boolean",g="_applyStretching",f="_applyMargin",e="shorthand",d="_applyAlign",c="allowShrinkY",b="bottom",a="baseline",x="marginBottom",w="qx.ui.core.LayoutItem",v="center",u="marginTop",t="allowGrowX",s="middle",r="marginLeft",q="allowShrinkX",p="top",o="right",m="marginRight",n="abstract",k="allowGrowY",l="left";qx.Class.define(w,{type:n,extend:qx.core.Object,properties:{minWidth:{check:j,nullable:true,apply:i,init:null,themeable:true},width:{check:j,nullable:true,apply:i,init:null,themeable:true},maxWidth:{check:j,nullable:true,apply:i,init:null,themeable:true},minHeight:{check:j,nullable:true,apply:i,init:null,themeable:true},height:{check:j,nullable:true,apply:i,init:null,themeable:true},maxHeight:{check:j,nullable:true,apply:i,init:null,themeable:true},allowGrowX:{check:h,apply:g,init:true,themeable:true},allowShrinkX:{check:h,apply:g,init:true,themeable:true},allowGrowY:{check:h,apply:g,init:true,themeable:true},allowShrinkY:{check:h,apply:g,init:true,themeable:true},allowStretchX:{group:[t,q],mode:e,themeable:true},allowStretchY:{group:[k,c],mode:e,themeable:true},marginTop:{check:j,init:0,apply:f,themeable:true},marginRight:{check:j,init:0,apply:f,themeable:true},marginBottom:{check:j,init:0,apply:f,themeable:true},marginLeft:{check:j,init:0,apply:f,themeable:true},margin:{group:[u,m,x,r],mode:e,themeable:true},alignX:{check:[l,v,o],nullable:true,apply:d,themeable:true},alignY:{check:[p,s,b,a],nullable:true,apply:d,themeable:true}},members:{__fz:null,__fA:null,__fB:null,__fC:null,__fD:null,__fE:null,__fF:null,getBounds:function(){return this.__fE||this.__fA||null;},clearSeparators:function(){},renderSeparator:function(y,z){},renderLayout:function(A,top,B,C){var D;{};var E=null;if(this.getHeight()==null&&this._hasHeightForWidth()){var E=this._getHeightForWidth(B);}if(E!=null&&E!==this.__fz){this.__fz=E;qx.ui.core.queue.Layout.add(this);return null;}var G=this.__fA;if(!G){G=this.__fA={};}var F={};if(A!==G.left||top!==G.top){F.position=true;G.left=A;G.top=top;}if(B!==G.width||C!==G.height){F.size=true;G.width=B;G.height=C;}if(this.__fB){F.local=true;delete this.__fB;}if(this.__fD){F.margin=true;delete this.__fD;}return F;},isExcluded:function(){return false;},hasValidLayout:function(){return !this.__fB;},scheduleLayoutUpdate:function(){qx.ui.core.queue.Layout.add(this);},invalidateLayoutCache:function(){this.__fB=true;this.__fC=null;},getSizeHint:function(H){var I=this.__fC;if(I){return I;}if(H===false){return null;}I=this.__fC=this._computeSizeHint();if(this._hasHeightForWidth()&&this.__fz&&this.getHeight()==null){I.height=this.__fz;}if(I.minWidth>I.width){I.width=I.minWidth;}if(I.maxWidth<I.width){I.width=I.maxWidth;}if(!this.getAllowGrowX()){I.maxWidth=I.width;}if(!this.getAllowShrinkX()){I.minWidth=I.width;}if(I.minHeight>I.height){I.height=I.minHeight;}if(I.maxHeight<I.height){I.height=I.maxHeight;}if(!this.getAllowGrowY()){I.maxHeight=I.height;}if(!this.getAllowShrinkY()){I.minHeight=I.height;}return I;},_computeSizeHint:function(){var N=this.getMinWidth()||0;var K=this.getMinHeight()||0;var O=this.getWidth()||N;var M=this.getHeight()||K;var J=this.getMaxWidth()||Infinity;var L=this.getMaxHeight()||Infinity;return {minWidth:N,width:O,maxWidth:J,minHeight:K,height:M,maxHeight:L};},_hasHeightForWidth:function(){var P=this._getLayout();if(P){return P.hasHeightForWidth();}return false;},_getHeightForWidth:function(Q){var R=this._getLayout();if(R&&R.hasHeightForWidth()){return R.getHeightForWidth(Q);}return null;},_getLayout:function(){return null;},_applyMargin:function(){this.__fD=true;var parent=this.$$parent;if(parent){parent.updateLayoutProperties();}},_applyAlign:function(){var parent=this.$$parent;if(parent){parent.updateLayoutProperties();}},_applyDimension:function(){qx.ui.core.queue.Layout.add(this);},_applyStretching:function(){qx.ui.core.queue.Layout.add(this);},hasUserBounds:function(){return !!this.__fE;},setUserBounds:function(S,top,T,U){this.__fE={left:S,top:top,width:T,height:U};qx.ui.core.queue.Layout.add(this);},resetUserBounds:function(){delete this.__fE;qx.ui.core.queue.Layout.add(this);},__fG:{},setLayoutProperties:function(V){if(V==null){return;}var W=this.__fF;if(!W){W=this.__fF={};}var parent=this.getLayoutParent();if(parent){parent.updateLayoutProperties(V);}for(var X in V){if(V[X]==null){delete W[X];}else{W[X]=V[X];}}},getLayoutProperties:function(){return this.__fF||this.__fG;},clearLayoutProperties:function(){delete this.__fF;},updateLayoutProperties:function(Y){var ba=this._getLayout();if(ba){var bb;{};ba.invalidateChildrenCache();}qx.ui.core.queue.Layout.add(this);},getApplicationRoot:function(){return qx.core.Init.getApplication().getRoot();},getLayoutParent:function(){return this.$$parent||null;},setLayoutParent:function(parent){if(this.$$parent===parent){return;}this.$$parent=parent||null;qx.ui.core.queue.Visibility.add(this);},isRootWidget:function(){return false;},_getRoot:function(){var parent=this;while(parent){if(parent.isRootWidget()){return parent;}parent=parent.$$parent;}return null;},clone:function(){var bc=qx.core.Object.prototype.clone.call(this);var bd=this.__fF;if(bd){bc.__fF=qx.lang.Object.clone(bd);}return bc;}},destruct:function(){this.$$parent=this.$$subparent=this.__fF=this.__fA=this.__fE=this.__fC=null;}});})();(function(){var a="qx.locale.MTranslation";qx.Mixin.define(a,{members:{tr:function(b,c){var d=qx.locale.Manager;if(d){return d.tr.apply(d,arguments);}throw new Error("To enable localization please include qx.locale.Manager into your build!");},trn:function(e,f,g,h){var i=qx.locale.Manager;if(i){return i.trn.apply(i,arguments);}throw new Error("To enable localization please include qx.locale.Manager into your build!");},trc:function(j,k,l){var m=qx.locale.Manager;if(m){return m.trc.apply(m,arguments);}throw new Error("To enable localization please include qx.locale.Manager into your build!");},marktr:function(n){var o=qx.locale.Manager;if(o){return o.marktr.apply(o,arguments);}throw new Error("To enable localization please include qx.locale.Manager into your build!");}}});})();(function(){var b="qx.ui.core.DecoratorFactory",a="$$nopool$$";qx.Class.define(b,{extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__cU={};},statics:{MAX_SIZE:15,__cV:a},members:{__cU:null,getDecoratorElement:function(c){var h=qx.ui.core.DecoratorFactory;if(qx.lang.Type.isString(c)){var f=c;var e=qx.theme.manager.Decoration.getInstance().resolve(c);}else{var f=h.__cV;e=c;}var g=this.__cU;if(g[f]&&g[f].length>0){var d=g[f].pop();}else{var d=this._createDecoratorElement(e,f);}d.$$pooled=false;return d;},poolDecorator:function(i){if(!i||i.$$pooled||i.isDisposed()){return;}var l=qx.ui.core.DecoratorFactory;var j=i.getId();if(j==l.__cV){i.dispose();return;}var k=this.__cU;if(!k[j]){k[j]=[];}if(k[j].length>l.MAX_SIZE){i.dispose();}else{i.$$pooled=true;k[j].push(i);}},_createDecoratorElement:function(m,n){var o=new qx.html.Decorator(m,n);{};return o;},toString:function(){return qx.core.Object.prototype.toString.call(this);}},destruct:function(){if(!qx.core.ObjectRegistry.inShutDown){var q=this.__cU;for(var p in q){qx.util.DisposeUtil.disposeArray(q,p);}}this.__cU=null;}});})();(function(){var bV="px",bU="Boolean",bT="qx.event.type.Drag",bS="qx.event.type.Mouse",bR="visible",bQ="qx.event.type.Focus",bP="on",bO="Integer",bN="qx.event.type.Touch",bM="excluded",bx="qx.event.type.Data",bw="_applyPadding",bv="qx.event.type.Event",bu="hidden",bt="contextmenu",bs="String",br="tabIndex",bq="focused",bp="changeVisibility",bo="mshtml",cd="hovered",ce="qx.event.type.KeySequence",cb="qx.client",cc="absolute",bY="backgroundColor",ca="drag",bW="div",bX="disabled",cf="move",cg="dragstart",bF="qx.dynlocale",bE="dragchange",bH="dragend",bG="resize",bJ="Decorator",bI="zIndex",bL="opacity",bK="default",bD="Color",bC="changeToolTipText",c="beforeContextmenuOpen",d="_applyNativeContextMenu",f="_applyBackgroundColor",g="_applyFocusable",h="changeShadow",j="qx.event.type.KeyInput",k="createChildControl",m="__dQ",n="Font",o="_applyShadow",ck="_applyEnabled",cj="_applySelectable",ci="Number",ch="_applyKeepActive",co="__ea",cn="_applyVisibility",cm="repeat",cl="qxDraggable",cq="__dR",cp="syncAppearance",N="paddingLeft",O="_applyDroppable",L="__ec",M="#",R="qx.event.type.MouseWheel",S="_applyCursor",P="_applyDraggable",Q="changeTextColor",J="$$widget",K="changeContextMenu",w="paddingTop",v="changeSelectable",y="hideFocus",x="none",s="outline",r="_applyAppearance",u="_applyOpacity",t="url(",q=")",p="qx.ui.core.Widget",X="_applyFont",Y="cursor",ba="qxDroppable",bb="changeZIndex",T="changeEnabled",U="changeFont",V="__ee",W="__dU",bc="_applyDecorator",bd="_applyZIndex",G="_applyTextColor",F="qx.ui.menu.Menu",E="_applyToolTipText",D="true",C="widget",B="changeDecorator",A="__dV",z="_applyTabIndex",I="changeAppearance",H="shorthand",be="/",bf="",bg="_applyContextMenu",bh="paddingBottom",bi="__dW",bj="changeNativeContextMenu",bk="qx.ui.tooltip.ToolTip",bl="qxKeepActive",bm="_applyKeepFocus",bn="paddingRight",bB="changeBackgroundColor",bA="changeLocale",bz="qxKeepFocus",by="qx/static/blank.gif";qx.Class.define(p,{extend:qx.ui.core.LayoutItem,include:[qx.locale.MTranslation],construct:function(){qx.ui.core.LayoutItem.call(this);this.__dQ=this._createContainerElement();this.__dR=this.__ed();this.__dQ.add(this.__dR);this.initFocusable();this.initSelectable();this.initNativeContextMenu();},events:{appear:bv,disappear:bv,createChildControl:bx,resize:bx,move:bx,syncAppearance:bx,mousemove:bS,mouseover:bS,mouseout:bS,mousedown:bS,mouseup:bS,click:bS,dblclick:bS,contextmenu:bS,beforeContextmenuOpen:bx,mousewheel:R,touchstart:bN,touchend:bN,touchmove:bN,touchcancel:bN,tap:bN,swipe:bN,keyup:ce,keydown:ce,keypress:ce,keyinput:j,focus:bQ,blur:bQ,focusin:bQ,focusout:bQ,activate:bQ,deactivate:bQ,capture:bv,losecapture:bv,drop:bT,dragleave:bT,dragover:bT,drag:bT,dragstart:bT,dragend:bT,dragchange:bT,droprequest:bT},properties:{paddingTop:{check:bO,init:0,apply:bw,themeable:true},paddingRight:{check:bO,init:0,apply:bw,themeable:true},paddingBottom:{check:bO,init:0,apply:bw,themeable:true},paddingLeft:{check:bO,init:0,apply:bw,themeable:true},padding:{group:[w,bn,bh,N],mode:H,themeable:true},zIndex:{nullable:true,init:null,apply:bd,event:bb,check:bO,themeable:true},decorator:{nullable:true,init:null,apply:bc,event:B,check:bJ,themeable:true},shadow:{nullable:true,init:null,apply:o,event:h,check:bJ,themeable:true},backgroundColor:{nullable:true,check:bD,apply:f,event:bB,themeable:true},textColor:{nullable:true,check:bD,apply:G,event:Q,themeable:true,inheritable:true},font:{nullable:true,apply:X,check:n,event:U,themeable:true,inheritable:true,dereference:true},opacity:{check:ci,apply:u,themeable:true,nullable:true,init:null},cursor:{check:bs,apply:S,themeable:true,inheritable:true,nullable:true,init:null},toolTip:{check:bk,nullable:true},toolTipText:{check:bs,nullable:true,event:bC,apply:E},toolTipIcon:{check:bs,nullable:true,event:bC},blockToolTip:{check:bU,init:false},visibility:{check:[bR,bu,bM],init:bR,apply:cn,event:bp},enabled:{init:true,check:bU,inheritable:true,apply:ck,event:T},anonymous:{init:false,check:bU},tabIndex:{check:bO,nullable:true,apply:z},focusable:{check:bU,init:false,apply:g},keepFocus:{check:bU,init:false,apply:bm},keepActive:{check:bU,init:false,apply:ch},draggable:{check:bU,init:false,apply:P},droppable:{check:bU,init:false,apply:O},selectable:{check:bU,init:false,event:v,apply:cj},contextMenu:{check:F,apply:bg,nullable:true,event:K},nativeContextMenu:{check:bU,init:false,themeable:true,event:bj,apply:d},appearance:{check:bs,init:C,apply:r,event:I}},statics:{DEBUG:false,getWidgetByElement:function(cr,cs){while(cr){var ct=cr.$$widget;if(ct!=null){var cu=qx.core.ObjectRegistry.fromHashCode(ct);if(!cs||!cu.getAnonymous()){return cu;}}try{cr=cr.parentNode;}catch(e){return null;}}return null;},contains:function(parent,cv){while(cv){if(parent==cv){return true;}cv=cv.getLayoutParent();}return false;},__dS:new qx.ui.core.DecoratorFactory(),__dT:new qx.ui.core.DecoratorFactory()},members:{__dQ:null,__dR:null,__dU:null,__dV:null,__dW:null,__dX:null,__dY:null,__ea:null,_getLayout:function(){return this.__ea;},_setLayout:function(cw){{};if(this.__ea){this.__ea.connectToWidget(null);}if(cw){cw.connectToWidget(this);}this.__ea=cw;qx.ui.core.queue.Layout.add(this);},setLayoutParent:function(parent){if(this.$$parent===parent){return;}var cx=this.getContainerElement();if(this.$$parent&&!this.$$parent.$$disposed){this.$$parent.getContentElement().remove(cx);}this.$$parent=parent||null;if(parent&&!parent.$$disposed){this.$$parent.getContentElement().add(cx);}this.$$refreshInheritables();qx.ui.core.queue.Visibility.add(this);},_updateInsets:null,__eb:function(a,b){if(a==b){return false;}if(a==null||b==null){return true;}var cy=qx.theme.manager.Decoration.getInstance();var cA=cy.resolve(a).getInsets();var cz=cy.resolve(b).getInsets();if(cA.top!=cz.top||cA.right!=cz.right||cA.bottom!=cz.bottom||cA.left!=cz.left){return true;}return false;},renderLayout:function(cB,top,cC,cD){var cM=qx.ui.core.LayoutItem.prototype.renderLayout.call(this,cB,top,cC,cD);if(!cM){return null;}var cF=this.getContainerElement();var content=this.getContentElement();var cJ=cM.size||this._updateInsets;var cN=bV;var cK={};if(cM.position){cK.left=cB+cN;cK.top=top+cN;}if(cM.size){cK.width=cC+cN;cK.height=cD+cN;}if(cM.position||cM.size){cF.setStyles(cK);}if(cJ||cM.local||cM.margin){var cE=this.getInsets();var innerWidth=cC-cE.left-cE.right;var innerHeight=cD-cE.top-cE.bottom;innerWidth=innerWidth<0?0:innerWidth;innerHeight=innerHeight<0?0:innerHeight;}var cH={};if(this._updateInsets){cH.left=cE.left+cN;cH.top=cE.top+cN;}if(cJ){cH.width=innerWidth+cN;cH.height=innerHeight+cN;}if(cJ||this._updateInsets){content.setStyles(cH);}if(cM.size){var cL=this.__dW;if(cL){cL.setStyles({width:cC+bV,height:cD+bV});}}if(cM.size||this._updateInsets){if(this.__dU){this.__dU.resize(cC,cD);}}if(cM.size){if(this.__dV){var cE=this.__dV.getInsets();var cI=cC+cE.left+cE.right;var cG=cD+cE.top+cE.bottom;this.__dV.resize(cI,cG);}}if(cJ||cM.local||cM.margin){if(this.__ea&&this.hasLayoutChildren()){this.__ea.renderLayout(innerWidth,innerHeight);}else if(this.hasLayoutChildren()){throw new Error("At least one child in control "+this._findTopControl()+" requires a layout, but no one was defined!");}}if(cM.position&&this.hasListener(cf)){this.fireDataEvent(cf,this.getBounds());}if(cM.size&&this.hasListener(bG)){this.fireDataEvent(bG,this.getBounds());}delete this._updateInsets;return cM;},__ec:null,clearSeparators:function(){var cP=this.__ec;if(!cP){return;}var cQ=qx.ui.core.Widget.__dS;var content=this.getContentElement();var cO;for(var i=0,l=cP.length;i<l;i++){cO=cP[i];cQ.poolDecorator(cO);content.remove(cO);}cP.length=0;},renderSeparator:function(cR,cS){var cT=qx.ui.core.Widget.__dS.getDecoratorElement(cR);this.getContentElement().add(cT);cT.resize(cS.width,cS.height);cT.setStyles({left:cS.left+bV,top:cS.top+bV});if(!this.__ec){this.__ec=[cT];}else{this.__ec.push(cT);}},_computeSizeHint:function(){var db=this.getWidth();var da=this.getMinWidth();var cV=this.getMaxWidth();var cY=this.getHeight();var cW=this.getMinHeight();var cX=this.getMaxHeight();{};var dc=this._getContentHint();var cU=this.getInsets();var de=cU.left+cU.right;var dd=cU.top+cU.bottom;if(db==null){db=dc.width+de;}if(cY==null){cY=dc.height+dd;}if(da==null){da=de;if(dc.minWidth!=null){da+=dc.minWidth;}}if(cW==null){cW=dd;if(dc.minHeight!=null){cW+=dc.minHeight;}}if(cV==null){if(dc.maxWidth==null){cV=Infinity;}else{cV=dc.maxWidth+de;}}if(cX==null){if(dc.maxHeight==null){cX=Infinity;}else{cX=dc.maxHeight+dd;}}return {width:db,minWidth:da,maxWidth:cV,height:cY,minHeight:cW,maxHeight:cX};},invalidateLayoutCache:function(){qx.ui.core.LayoutItem.prototype.invalidateLayoutCache.call(this);if(this.__ea){this.__ea.invalidateLayoutCache();}},_getContentHint:function(){var dg=this.__ea;if(dg){if(this.hasLayoutChildren()){var df;var dh=dg.getSizeHint();{};return dh;}else{return {width:0,height:0};}}else{return {width:100,height:50};}},_getHeightForWidth:function(di){var dm=this.getInsets();var dq=dm.left+dm.right;var dp=dm.top+dm.bottom;var dn=di-dq;var dk=this._getLayout();if(dk&&dk.hasHeightForWidth()){var dj=dk.getHeightForWidth(di);}else{dj=this._getContentHeightForWidth(dn);}var dl=dj+dp;return dl;},_getContentHeightForWidth:function(dr){throw new Error("Abstract method call: _getContentHeightForWidth()!");},getInsets:function(){var top=this.getPaddingTop();var dt=this.getPaddingRight();var dv=this.getPaddingBottom();var du=this.getPaddingLeft();if(this.__dU){var ds=this.__dU.getInsets();{};top+=ds.top;dt+=ds.right;dv+=ds.bottom;du+=ds.left;}return {"top":top,"right":dt,"bottom":dv,"left":du};},getInnerSize:function(){var dx=this.getBounds();if(!dx){return null;}var dw=this.getInsets();return {width:dx.width-dw.left-dw.right,height:dx.height-dw.top-dw.bottom};},show:function(){this.setVisibility(bR);},hide:function(){this.setVisibility(bu);},exclude:function(){this.setVisibility(bM);},isVisible:function(){return this.getVisibility()===bR;},isHidden:function(){return this.getVisibility()!==bR;},isExcluded:function(){return this.getVisibility()===bM;},isSeeable:function(){var dz=this.getContainerElement().getDomElement();if(dz){return dz.offsetWidth>0;}var dy=this;do{if(!dy.isVisible()){return false;}if(dy.isRootWidget()){return true;}dy=dy.getLayoutParent();}while(dy);return false;},_createContainerElement:function(){var dB={"$$widget":this.toHashCode()};{};var dA={zIndex:0,position:cc};return new qx.html.Element(bW,dA,dB);},__ed:function(){var dC=this._createContentElement();{};dC.setStyles({"position":cc,"zIndex":10});return dC;},_createContentElement:function(){return new qx.html.Element(bW,{overflowX:bu,overflowY:bu});},getContainerElement:function(){return this.__dQ;},getContentElement:function(){return this.__dR;},getDecoratorElement:function(){return this.__dU||null;},getShadowElement:function(){return this.__dV||null;},__ee:null,getLayoutChildren:function(){var dE=this.__ee;if(!dE){return this.__ef;}var dF;for(var i=0,l=dE.length;i<l;i++){var dD=dE[i];if(dD.hasUserBounds()||dD.isExcluded()){if(dF==null){dF=dE.concat();}qx.lang.Array.remove(dF,dD);}}return dF||dE;},scheduleLayoutUpdate:function(){qx.ui.core.queue.Layout.add(this);},invalidateLayoutChildren:function(){var dG=this.__ea;if(dG){dG.invalidateChildrenCache();}qx.ui.core.queue.Layout.add(this);},hasLayoutChildren:function(){var dH=this.__ee;if(!dH){return false;}var dI;for(var i=0,l=dH.length;i<l;i++){dI=dH[i];if(!dI.hasUserBounds()&&!dI.isExcluded()){return true;}}return false;},getChildrenContainer:function(){return this;},__ef:[],_getChildren:function(){return this.__ee||this.__ef;},_indexOf:function(dJ){var dK=this.__ee;if(!dK){return -1;}return dK.indexOf(dJ);},_hasChildren:function(){var dL=this.__ee;return dL!=null&&(!!dL[0]);},addChildrenToQueue:function(dM){var dN=this.__ee;if(!dN){return;}var dO;for(var i=0,l=dN.length;i<l;i++){dO=dN[i];dM[dO.$$hash]=dO;dO.addChildrenToQueue(dM);}},_add:function(dP,dQ){if(dP.getLayoutParent()==this){qx.lang.Array.remove(this.__ee,dP);}if(this.__ee){this.__ee.push(dP);}else{this.__ee=[dP];}this.__eg(dP,dQ);},_addAt:function(dR,dS,dT){if(!this.__ee){this.__ee=[];}if(dR.getLayoutParent()==this){qx.lang.Array.remove(this.__ee,dR);}var dU=this.__ee[dS];if(dU===dR){dR.setLayoutProperties(dT);}if(dU){qx.lang.Array.insertBefore(this.__ee,dR,dU);}else{this.__ee.push(dR);}this.__eg(dR,dT);},_addBefore:function(dV,dW,dX){{};if(dV==dW){return;}if(!this.__ee){this.__ee=[];}if(dV.getLayoutParent()==this){qx.lang.Array.remove(this.__ee,dV);}qx.lang.Array.insertBefore(this.__ee,dV,dW);this.__eg(dV,dX);},_addAfter:function(dY,ea,eb){{};if(dY==ea){return;}if(!this.__ee){this.__ee=[];}if(dY.getLayoutParent()==this){qx.lang.Array.remove(this.__ee,dY);}qx.lang.Array.insertAfter(this.__ee,dY,ea);this.__eg(dY,eb);},_remove:function(ec){if(!this.__ee){throw new Error("This widget has no children!");}qx.lang.Array.remove(this.__ee,ec);this.__eh(ec);},_removeAt:function(ed){if(!this.__ee){throw new Error("This widget has no children!");}var ee=this.__ee[ed];qx.lang.Array.removeAt(this.__ee,ed);this.__eh(ee);return ee;},_removeAll:function(){if(!this.__ee){return;}var ef=this.__ee.concat();this.__ee.length=0;for(var i=ef.length-1;i>=0;i--){this.__eh(ef[i]);}qx.ui.core.queue.Layout.add(this);},_afterAddChild:null,_afterRemoveChild:null,__eg:function(eg,eh){{};var parent=eg.getLayoutParent();if(parent&&parent!=this){parent._remove(eg);}eg.setLayoutParent(this);if(eh){eg.setLayoutProperties(eh);}else{this.updateLayoutProperties();}if(this._afterAddChild){this._afterAddChild(eg);}},__eh:function(ei){{};if(ei.getLayoutParent()!==this){throw new Error("Remove Error: "+ei+" is not a child of this widget!");}ei.setLayoutParent(null);if(this.__ea){this.__ea.invalidateChildrenCache();}qx.ui.core.queue.Layout.add(this);if(this._afterRemoveChild){this._afterRemoveChild(ei);}},capture:function(ej){this.getContainerElement().capture(ej);},releaseCapture:function(){this.getContainerElement().releaseCapture();},_applyPadding:function(ek,em,name){this._updateInsets=true;qx.ui.core.queue.Layout.add(this);},_createProtectorElement:function(){if(this.__dW){return;}var en=this.__dW=new qx.html.Element;{};en.setStyles({position:cc,top:0,left:0,zIndex:7});var eo=this.getBounds();if(eo){this.__dW.setStyles({width:eo.width+bV,height:eo.height+bV});}if(qx.core.Variant.isSet(cb,bo)){en.setStyles({backgroundImage:t+qx.util.ResourceManager.getInstance().toUri(by)+q,backgroundRepeat:cm});}this.getContainerElement().add(en);},_applyDecorator:function(ep,eq){{};var et=qx.ui.core.Widget.__dS;var er=this.getContainerElement();if(!this.__dW&&!qx.bom.client.Feature.CSS_POINTER_EVENTS){this._createProtectorElement();}if(eq){er.remove(this.__dU);et.poolDecorator(this.__dU);}if(ep){var es=this.__dU=et.getDecoratorElement(ep);es.setStyle(bI,5);er.add(es);}else{delete this.__dU;}this._applyBackgroundColor(this.getBackgroundColor());if(this.__eb(eq,ep)){this._updateInsets=true;qx.ui.core.queue.Layout.add(this);}else if(ep){var eu=this.getBounds();if(eu){es.resize(eu.width,eu.height);this.__dW&&this.__dW.setStyles({width:eu.width+bV,height:eu.height+bV});}}},_applyShadow:function(ev,ew){var eD=qx.ui.core.Widget.__dT;var ey=this.getContainerElement();if(ew){ey.remove(this.__dV);eD.poolDecorator(this.__dV);}if(ev){var eA=this.__dV=eD.getDecoratorElement(ev);ey.add(eA);var eC=eA.getInsets();eA.setStyles({left:(-eC.left)+bV,top:(-eC.top)+bV});var eB=this.getBounds();if(eB){var ez=eB.width+eC.left+eC.right;var ex=eB.height+eC.top+eC.bottom;eA.resize(ez,ex);}eA.tint(null);}else{delete this.__dV;}},_applyToolTipText:function(eE,eF){if(qx.core.Variant.isSet(bF,bP)){if(this.__dY){return;}var eG=qx.locale.Manager.getInstance();this.__dY=eG.addListener(bA,function(){var eH=this.getToolTipText();if(eH&&eH.translate){this.setToolTipText(eH.translate());}},this);}},_applyTextColor:function(eI,eJ){},_applyZIndex:function(eK,eL){this.getContainerElement().setStyle(bI,eK==null?0:eK);},_applyVisibility:function(eM,eN){var eO=this.getContainerElement();if(eM===bR){eO.show();}else{eO.hide();}var parent=this.$$parent;if(parent&&(eN==null||eM==null||eN===bM||eM===bM)){parent.invalidateLayoutChildren();}qx.ui.core.queue.Visibility.add(this);},_applyOpacity:function(eP,eQ){this.getContainerElement().setStyle(bL,eP==1?null:eP);if(qx.core.Variant.isSet(cb,bo)&&qx.bom.element.Decoration.isAlphaImageLoaderEnabled()){if(!qx.Class.isSubClassOf(this.getContentElement().constructor,qx.html.Image)){var eR=(eP==1||eP==null)?null:0.99;this.getContentElement().setStyle(bL,eR);}}},_applyCursor:function(eS,eT){if(eS==null&&!this.isSelectable()){eS=bK;}this.getContainerElement().setStyle(Y,eS,qx.bom.client.Engine.OPERA);},_applyBackgroundColor:function(eU,eV){var eW=this.getBackgroundColor();var eY=this.getContainerElement();if(this.__dU){this.__dU.tint(eW);eY.setStyle(bY,null);}else{var eX=qx.theme.manager.Color.getInstance().resolve(eW);eY.setStyle(bY,eX);}},_applyFont:function(fa,fb){},__ei:null,$$stateChanges:null,_forwardStates:null,hasState:function(fc){var fd=this.__ei;return !!fd&&!!fd[fc];},addState:function(fe){var ff=this.__ei;if(!ff){ff=this.__ei={};}if(ff[fe]){return;}this.__ei[fe]=true;if(fe===cd){this.syncAppearance();}else if(!qx.ui.core.queue.Visibility.isVisible(this)){this.$$stateChanges=true;}else{qx.ui.core.queue.Appearance.add(this);}var forward=this._forwardStates;var fi=this.__el;if(forward&&forward[fe]&&fi){var fg;for(var fh in fi){fg=fi[fh];if(fg instanceof qx.ui.core.Widget){fi[fh].addState(fe);}}}},removeState:function(fj){var fk=this.__ei;if(!fk||!fk[fj]){return;}delete this.__ei[fj];if(fj===cd){this.syncAppearance();}else if(!qx.ui.core.queue.Visibility.isVisible(this)){this.$$stateChanges=true;}else{qx.ui.core.queue.Appearance.add(this);}var forward=this._forwardStates;var fn=this.__el;if(forward&&forward[fj]&&fn){for(var fm in fn){var fl=fn[fm];if(fl instanceof qx.ui.core.Widget){fl.removeState(fj);}}}},replaceState:function(fo,fp){var fq=this.__ei;if(!fq){fq=this.__ei={};}if(!fq[fp]){fq[fp]=true;}if(fq[fo]){delete fq[fo];}if(!qx.ui.core.queue.Visibility.isVisible(this)){this.$$stateChanges=true;}else{qx.ui.core.queue.Appearance.add(this);}var forward=this._forwardStates;var ft=this.__el;if(forward&&forward[fp]&&ft){for(var fs in ft){var fr=ft[fs];if(fr instanceof qx.ui.core.Widget){fr.replaceState(fo,fp);}}}},__ej:null,__ek:null,syncAppearance:function(){var fy=this.__ei;var fx=this.__ej;var fz=qx.theme.manager.Appearance.getInstance();var fv=qx.core.Property.$$method.setThemed;var fD=qx.core.Property.$$method.resetThemed;if(this.__ek){delete this.__ek;if(fx){var fu=fz.styleFrom(fx,fy,null,this.getAppearance());if(fu){fx=null;}}}if(!fx){var fw=this;var fC=[];do{fC.push(fw.$$subcontrol||fw.getAppearance());}while(fw=fw.$$subparent);fx=fC.reverse().join(be).replace(/#[0-9]+/g,bf);this.__ej=fx;}var fA=fz.styleFrom(fx,fy,null,this.getAppearance());if(fA){var fB;if(fu){for(var fB in fu){if(fA[fB]===undefined){this[fD[fB]]();}}}{};for(var fB in fA){fA[fB]===undefined?this[fD[fB]]():this[fv[fB]](fA[fB]);}}else if(fu){for(var fB in fu){this[fD[fB]]();}}this.fireDataEvent(cp,this.__ei);},_applyAppearance:function(fE,fF){this.updateAppearance();},checkAppearanceNeeds:function(){if(!this.__dX){qx.ui.core.queue.Appearance.add(this);this.__dX=true;}else if(this.$$stateChanges){qx.ui.core.queue.Appearance.add(this);delete this.$$stateChanges;}},updateAppearance:function(){this.__ek=true;qx.ui.core.queue.Appearance.add(this);var fI=this.__el;if(fI){var fG;for(var fH in fI){fG=fI[fH];if(fG instanceof qx.ui.core.Widget){fG.updateAppearance();}}}},syncWidget:function(){},getEventTarget:function(){var fJ=this;while(fJ.getAnonymous()){fJ=fJ.getLayoutParent();if(!fJ){return null;}}return fJ;},getFocusTarget:function(){var fK=this;if(!fK.getEnabled()){return null;}while(fK.getAnonymous()||!fK.getFocusable()){fK=fK.getLayoutParent();if(!fK||!fK.getEnabled()){return null;}}return fK;},getFocusElement:function(){return this.getContainerElement();},isTabable:function(){return (!!this.getContainerElement().getDomElement())&&this.isFocusable();},_applyFocusable:function(fL,fM){var fN=this.getFocusElement();if(fL){var fO=this.getTabIndex();if(fO==null){fO=1;}fN.setAttribute(br,fO);if(qx.core.Variant.isSet(cb,bo)){fN.setAttribute(y,D);}else{fN.setStyle(s,x);}}else{if(fN.isNativelyFocusable()){fN.setAttribute(br,-1);}else if(fM){fN.setAttribute(br,null);}}},_applyKeepFocus:function(fP){var fQ=this.getFocusElement();fQ.setAttribute(bz,fP?bP:null);},_applyKeepActive:function(fR){var fS=this.getContainerElement();fS.setAttribute(bl,fR?bP:null);},_applyTabIndex:function(fT){if(fT==null){fT=1;}else if(fT<1||fT>32000){throw new Error("TabIndex property must be between 1 and 32000");}if(this.getFocusable()&&fT!=null){this.getFocusElement().setAttribute(br,fT);}},_applySelectable:function(fU,fV){if(fV!==null){this._applyCursor(this.getCursor());}this.getContentElement().setSelectable(fU);},_applyEnabled:function(fW,fX){if(fW===false){this.addState(bX);this.removeState(cd);if(this.isFocusable()){this.removeState(bq);this._applyFocusable(false,true);}if(this.isDraggable()){this._applyDraggable(false,true);}if(this.isDroppable()){this._applyDroppable(false,true);}}else{this.removeState(bX);if(this.isFocusable()){this._applyFocusable(true,false);}if(this.isDraggable()){this._applyDraggable(true,false);}if(this.isDroppable()){this._applyDroppable(true,false);}}},_applyNativeContextMenu:function(fY,ga,name){},_applyContextMenu:function(gb,gc){if(gc){gc.removeState(bt);if(gc.getOpener()==this){gc.resetOpener();}if(!gb){this.removeListener(bt,this._onContextMenuOpen);gc.removeListener(bp,this._onBeforeContextMenuOpen,this);}}if(gb){gb.setOpener(this);gb.addState(bt);if(!gc){this.addListener(bt,this._onContextMenuOpen);gb.addListener(bp,this._onBeforeContextMenuOpen,this);}}},_onContextMenuOpen:function(e){this.getContextMenu().openAtMouse(e);e.stop();},_onBeforeContextMenuOpen:function(e){if(e.getData()==bR&&this.hasListener(c)){this.fireDataEvent(c,e);}},_onStopEvent:function(e){e.stopPropagation();},_applyDraggable:function(gd,ge){if(!this.isEnabled()&&gd===true){gd=false;}qx.ui.core.DragDropCursor.getInstance();if(gd){this.addListener(cg,this._onDragStart);this.addListener(ca,this._onDrag);this.addListener(bH,this._onDragEnd);this.addListener(bE,this._onDragChange);}else{this.removeListener(cg,this._onDragStart);this.removeListener(ca,this._onDrag);this.removeListener(bH,this._onDragEnd);this.removeListener(bE,this._onDragChange);}this.getContainerElement().setAttribute(cl,gd?bP:null);},_applyDroppable:function(gf,gg){if(!this.isEnabled()&&gf===true){gf=false;}this.getContainerElement().setAttribute(ba,gf?bP:null);},_onDragStart:function(e){qx.ui.core.DragDropCursor.getInstance().placeToMouse(e);this.getApplicationRoot().setGlobalCursor(bK);},_onDrag:function(e){qx.ui.core.DragDropCursor.getInstance().placeToMouse(e);},_onDragEnd:function(e){qx.ui.core.DragDropCursor.getInstance().moveTo(-1000,-1000);this.getApplicationRoot().resetGlobalCursor();},_onDragChange:function(e){var gh=qx.ui.core.DragDropCursor.getInstance();var gi=e.getCurrentAction();gi?gh.setAction(gi):gh.resetAction();},visualizeFocus:function(){this.addState(bq);},visualizeBlur:function(){this.removeState(bq);},scrollChildIntoView:function(gj,gk,gl,gm){this.scrollChildIntoViewX(gj,gk,gm);this.scrollChildIntoViewY(gj,gl,gm);},scrollChildIntoViewX:function(gn,go,gp){this.getContentElement().scrollChildIntoViewX(gn.getContainerElement(),go,gp);},scrollChildIntoViewY:function(gq,gr,gs){this.getContentElement().scrollChildIntoViewY(gq.getContainerElement(),gr,gs);},focus:function(){if(this.isFocusable()){this.getFocusElement().focus();}else{throw new Error("Widget is not focusable!");}},blur:function(){if(this.isFocusable()){this.getFocusElement().blur();}else{throw new Error("Widget is not focusable!");}},activate:function(){this.getContainerElement().activate();},deactivate:function(){this.getContainerElement().deactivate();},tabFocus:function(){this.getFocusElement().focus();},hasChildControl:function(gt){if(!this.__el){return false;}return !!this.__el[gt];},__el:null,_getCreatedChildControls:function(){return this.__el;},getChildControl:function(gu,gv){if(!this.__el){if(gv){return null;}this.__el={};}var gw=this.__el[gu];if(gw){return gw;}if(gv===true){return null;}return this._createChildControl(gu);},_showChildControl:function(gx){var gy=this.getChildControl(gx);gy.show();return gy;},_excludeChildControl:function(gz){var gA=this.getChildControl(gz,true);if(gA){gA.exclude();}},_isChildControlVisible:function(gB){var gC=this.getChildControl(gB,true);if(gC){return gC.isVisible();}return false;},_createChildControl:function(gD){if(!this.__el){this.__el={};}else if(this.__el[gD]){throw new Error("Child control '"+gD+"' already created!");}var gH=gD.indexOf(M);if(gH==-1){var gE=this._createChildControlImpl(gD);}else{var gE=this._createChildControlImpl(gD.substring(0,gH),gD.substring(gH+1,gD.length));}if(!gE){throw new Error("Unsupported control: "+gD);}gE.$$subcontrol=gD;gE.$$subparent=this;var gF=this.__ei;var forward=this._forwardStates;if(gF&&forward&&gE instanceof qx.ui.core.Widget){for(var gG in gF){if(forward[gG]){gE.addState(gG);}}}this.fireDataEvent(k,gE);return this.__el[gD]=gE;},_createChildControlImpl:function(gI,gJ){return null;},_disposeChildControls:function(){var gN=this.__el;if(!gN){return;}var gL=qx.ui.core.Widget;for(var gM in gN){var gK=gN[gM];if(!gL.contains(this,gK)){gK.destroy();}else{gK.dispose();}}delete this.__el;},_findTopControl:function(){var gO=this;while(gO){if(!gO.$$subparent){return gO;}gO=gO.$$subparent;}return null;},getContainerLocation:function(gP){var gQ=this.getContainerElement().getDomElement();return gQ?qx.bom.element.Location.get(gQ,gP):null;},getContentLocation:function(gR){var gS=this.getContentElement().getDomElement();return gS?qx.bom.element.Location.get(gS,gR):null;},setDomLeft:function(gT){var gU=this.getContainerElement().getDomElement();if(gU){gU.style.left=gT+bV;}else{throw new Error("DOM element is not yet created!");}},setDomTop:function(gV){var gW=this.getContainerElement().getDomElement();if(gW){gW.style.top=gV+bV;}else{throw new Error("DOM element is not yet created!");}},setDomPosition:function(gX,top){var gY=this.getContainerElement().getDomElement();if(gY){gY.style.left=gX+bV;gY.style.top=top+bV;}else{throw new Error("DOM element is not yet created!");}},destroy:function(){if(this.$$disposed){return;}var parent=this.$$parent;if(parent){parent._remove(this);}qx.ui.core.queue.Dispose.add(this);},clone:function(){var ha=qx.ui.core.LayoutItem.prototype.clone.call(this);if(this.getChildren){var hb=this.getChildren();for(var i=0,l=hb.length;i<l;i++){ha.add(hb[i].clone());}}return ha;}},destruct:function(){if(!qx.core.ObjectRegistry.inShutDown){if(qx.core.Variant.isSet(bF,bP)){if(this.__dY){qx.locale.Manager.getInstance().removeListenerById(this.__dY);}}this.getContainerElement().setAttribute(J,null,true);this._disposeChildControls();qx.ui.core.queue.Appearance.remove(this);qx.ui.core.queue.Layout.remove(this);qx.ui.core.queue.Visibility.remove(this);qx.ui.core.queue.Widget.remove(this);}if(!qx.core.ObjectRegistry.inShutDown){var hd=qx.ui.core.Widget;var hc=this.getContainerElement();if(this.__dU){hc.remove(this.__dU);hd.__dS.poolDecorator(this.__dU);}if(this.__dV){hc.remove(this.__dV);hd.__dT.poolDecorator(this.__dV);}this.clearSeparators();this.__dU=this.__dV=this.__ec=null;}else{this._disposeArray(L);this._disposeObjects(W,A);}this._disposeArray(V);this.__ei=this.__el=null;this._disposeObjects(co,m,cq,bi);}});})();(function(){var d="qx.event.type.Data",c="qx.ui.container.Composite",b="addChildWidget",a="removeChildWidget";qx.Class.define(c,{extend:qx.ui.core.Widget,include:[qx.ui.core.MChildrenHandling,qx.ui.core.MLayoutHandling],construct:function(e){qx.ui.core.Widget.call(this);if(e!=null){this._setLayout(e);}},events:{addChildWidget:d,removeChildWidget:d},members:{_afterAddChild:function(f){this.fireNonBubblingEvent(b,qx.event.type.Data,[f]);},_afterRemoveChild:function(g){this.fireNonBubblingEvent(a,qx.event.type.Data,[g]);}},defer:function(h,i){qx.ui.core.MChildrenHandling.remap(i);qx.ui.core.MLayoutHandling.remap(i);}});})();(function(){var l="button",k="",j="close",i="String",h="_applyIcon",g="page",f="qx.event.type.Event",e="_applyShowCloseButton",d="tabview-page",c="qx.ui.tabview.Page",a="_applyLabel",b="Boolean";qx.Class.define(c,{extend:qx.ui.container.Composite,construct:function(m,n){qx.ui.container.Composite.call(this);this._createChildControl(l);if(m!=null){this.setLabel(m);}if(n!=null){this.setIcon(n);}},events:{"close":f},properties:{appearance:{refine:true,init:d},label:{check:i,init:k,apply:a},icon:{check:i,init:k,apply:h},showCloseButton:{check:b,init:false,apply:e}},members:{_forwardStates:{barTop:1,barRight:1,barBottom:1,barLeft:1,firstTab:1,lastTab:1},_applyIcon:function(o,p){this.getChildControl(l).setIcon(o);},_applyLabel:function(q,r){this.getChildControl(l).setLabel(q);},_applyEnabled:function(s,t){qx.ui.container.Composite.prototype._applyEnabled.call(this,s,t);var u=this.getChildControl(l);s==null?u.resetEnabled():u.setEnabled(s);},_createChildControlImpl:function(v,w){var x;switch(v){case l:x=new qx.ui.tabview.TabButton;x.setAllowGrowX(true);x.setAllowGrowY(true);x.setUserData(g,this);x.addListener(j,this._onButtonClose,this);break;}return x||qx.ui.container.Composite.prototype._createChildControlImpl.call(this,v);},_applyShowCloseButton:function(y,z){this.getChildControl(l).setShowCloseButton(y);},_onButtonClose:function(){this.fireEvent(j);},getButton:function(){return this.getChildControl(l);}}});})();(function(){var i="showPrivate",h="expandProperties",g="showInherited",f="showProtected",d="_applyClassNode",c="apiviewer.ui.tabview.AbstractPage",b="nodeName",a="abstract";qx.Class.define(c,{extend:qx.ui.tabview.Page,type:a,construct:function(j){qx.ui.tabview.Page.call(this);this.setLayout(new qx.ui.layout.Canvas());this.setShowCloseButton(true);this._bindings=[];this._viewer=this._createViewer();this.add(this._viewer,{edge:0});this.__So(this._viewer);this.setClassNode(j);},properties:{classNode:{apply:d}},members:{_viewer:null,_bindings:null,_createViewer:function(){throw new Error("Abstract method call!");},_applyClassNode:function(k,l){this._viewer.setDocNode(k);this.setLabel(k.getFullName());this.setIcon(apiviewer.TreeUtil.getIconUrl(k));this.setUserData(b,k.getFullName());qx.event.Timer.once(function(e){this._viewer.getContentElement().scrollToY(0);},this,0);},__So:function(m){var n=apiviewer.UiModel.getInstance();var o=this._bindings;o.push(n.bind(g,m,g));o.push(n.bind(h,m,h));o.push(n.bind(f,m,f));o.push(n.bind(i,m,i));},__Sp:function(){var p=apiviewer.UiModel.getInstance();var q=this._bindings;while(q.length>0){var r=q.pop();p.removeBinding(r);}}},destruct:function(){this.__Sp();this._viewer.destroy();this._viewer=null;}});})();(function(){var a="apiviewer.ui.tabview.PackagePage";qx.Class.define(a,{extend:apiviewer.ui.tabview.AbstractPage,members:{_createViewer:function(){return new apiviewer.ui.PackageViewer();}}});})();(function(){var m="ready",l="qx.client",k="mshtml",j="load",i="unload",h="qx.event.handler.Application",g="complete",f="qx.application",d="gecko|opera|webkit",c="left",a="DOMContentLoaded",b="shutdown";qx.Class.define(h,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(n){qx.core.Object.call(this);this._window=n.getWindow();this.__ij=false;this.__ik=false;this._initObserver();qx.event.handler.Application.$$instance=this;},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{ready:1,shutdown:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_WINDOW,IGNORE_CAN_HANDLE:true,onScriptLoaded:function(){var o=qx.event.handler.Application.$$instance;if(o){o.__in();}}},members:{canHandleEvent:function(p,q){},registerEvent:function(r,s,t){},unregisterEvent:function(u,v,w){},__il:null,__ij:null,__ik:null,__im:null,__in:function(){if(!this.__il&&this.__ij&&qx.$$loader.scriptLoaded){try{var x=qx.core.Setting.get(f);if(!qx.Class.getByName(x)){return;}}catch(e){}if(qx.core.Variant.isSet(l,k)){if(qx.event.Registration.hasListener(this._window,m)){this.__il=true;qx.event.Registration.fireEvent(this._window,m);}}else{this.__il=true;qx.event.Registration.fireEvent(this._window,m);}}},isApplicationReady:function(){return this.__il;},_initObserver:function(){if(qx.$$domReady||document.readyState==g||document.readyState==m){this.__ij=true;this.__in();}else{this._onNativeLoadWrapped=qx.lang.Function.bind(this._onNativeLoad,this);if(qx.core.Variant.isSet(l,d)){qx.bom.Event.addNativeListener(this._window,a,this._onNativeLoadWrapped);}else if(qx.core.Variant.isSet(l,k)){var self=this;var y=function(){try{document.documentElement.doScroll(c);if(document.body){self._onNativeLoadWrapped();}}catch(z){window.setTimeout(y,100);}};y();}qx.bom.Event.addNativeListener(this._window,j,this._onNativeLoadWrapped);}this._onNativeUnloadWrapped=qx.lang.Function.bind(this._onNativeUnload,this);qx.bom.Event.addNativeListener(this._window,i,this._onNativeUnloadWrapped);},_stopObserver:function(){if(this._onNativeLoadWrapped){qx.bom.Event.removeNativeListener(this._window,j,this._onNativeLoadWrapped);}qx.bom.Event.removeNativeListener(this._window,i,this._onNativeUnloadWrapped);this._onNativeLoadWrapped=null;this._onNativeUnloadWrapped=null;},_onNativeLoad:qx.event.GlobalError.observeMethod(function(){this.__ij=true;this.__in();}),_onNativeUnload:qx.event.GlobalError.observeMethod(function(){if(!this.__im){this.__im=true;try{qx.event.Registration.fireEvent(this._window,b);}catch(e){throw e;}finally{qx.core.ObjectRegistry.shutdown();}}})},destruct:function(){this._stopObserver();this._window=null;},defer:function(A){qx.event.Registration.addHandler(A);}});})();(function(){var f="ready",d="qx.application",c="beforeunload",b="qx.core.Init",a="shutdown";qx.Class.define(b,{statics:{getApplication:function(){return this.__ku||null;},ready:function(){if(this.__ku){return;}if(qx.bom.client.Engine.UNKNOWN_ENGINE){qx.log.Logger.warn("Could not detect engine!");}if(qx.bom.client.Engine.UNKNOWN_VERSION){qx.log.Logger.warn("Could not detect the version of the engine!");}if(qx.bom.client.Platform.UNKNOWN_PLATFORM){qx.log.Logger.warn("Could not detect platform!");}if(qx.bom.client.System.UNKNOWN_SYSTEM){qx.log.Logger.warn("Could not detect system!");}qx.log.Logger.debug(this,"Load runtime: "+(new Date-qx.Bootstrap.LOADSTART)+"ms");var h=qx.core.Setting.get(d);var i=qx.Class.getByName(h);if(i){this.__ku=new i;var g=new Date;this.__ku.main();qx.log.Logger.debug(this,"Main runtime: "+(new Date-g)+"ms");var g=new Date;this.__ku.finalize();qx.log.Logger.debug(this,"Finalize runtime: "+(new Date-g)+"ms");}else{qx.log.Logger.warn("Missing application class: "+h);}},__kv:function(e){var j=this.__ku;if(j){e.setReturnValue(j.close());}},__kw:function(){var k=this.__ku;if(k){k.terminate();}}},defer:function(l){qx.event.Registration.addListener(window,f,l.ready,l);qx.event.Registration.addListener(window,a,l.__kw,l);qx.event.Registration.addListener(window,c,l.__kv,l);}});})();(function(){var h="object",g="__cq",f="_applyTheme",e="qx.theme.manager.Decoration",d="Theme",c="changeTheme",b="string",a="singleton";qx.Class.define(e,{type:a,extend:qx.core.Object,properties:{theme:{check:d,nullable:true,apply:f,event:c}},members:{__cq:null,resolve:function(i){if(!i){return null;}if(typeof i===h){return i;}var l=this.getTheme();if(!l){return null;}var l=this.getTheme();if(!l){return null;}var m=this.__cq;if(!m){m=this.__cq={};}var j=m[i];if(j){return j;}var k=l.decorations[i];if(!k){return null;}var n=k.decorator;if(n==null){throw new Error("Missing definition of which decorator to use in entry: "+i+"!");}return m[i]=(new n).set(k.style);},isValidPropertyValue:function(o){if(typeof o===b){return this.isDynamic(o);}else if(typeof o===h){var p=o.constructor;return qx.Class.hasInterface(p,qx.ui.decoration.IDecorator);}return false;},isDynamic:function(q){if(!q){return false;}var r=this.getTheme();if(!r){return false;}return !!r.decorations[q];},_applyTheme:function(s,t){var v=qx.util.AliasManager.getInstance();if(t){for(var u in t.aliases){v.remove(u);}}if(s){for(var u in s.aliases){v.add(u,s.aliases[u]);}}if(!s){this.__cq={};}}},destruct:function(){this._disposeMap(g);}});})();(function(){var a="qx.ui.decoration.IDecorator";qx.Interface.define(a,{members:{getMarkup:function(){},resize:function(b,c,d){},tint:function(e,f){},getInsets:function(){}}});})();(function(){var b="qx.util.ValueManager",a="abstract";qx.Class.define(b,{type:a,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this._dynamic={};},members:{_dynamic:null,resolveDynamic:function(c){return this._dynamic[c];},isDynamic:function(d){return !!this._dynamic[d];},resolve:function(e){if(e&&this._dynamic[e]){return this._dynamic[e];}return e;},_setDynamic:function(f){this._dynamic=f;},_getDynamic:function(){return this._dynamic;}},destruct:function(){this._dynamic=null;}});})();(function(){var j="/",i="0",h="qx/static",g="http://",f="https://",e="file://",d="qx.util.AliasManager",c="singleton",b=".",a="static";qx.Class.define(d,{type:c,extend:qx.util.ValueManager,construct:function(){qx.util.ValueManager.call(this);this.__gF={};this.add(a,h);},members:{__gF:null,_preprocess:function(k){var n=this._getDynamic();if(n[k]===false){return k;}else if(n[k]===undefined){if(k.charAt(0)===j||k.charAt(0)===b||k.indexOf(g)===0||k.indexOf(f)===i||k.indexOf(e)===0){n[k]=false;return k;}if(this.__gF[k]){return this.__gF[k];}var m=k.substring(0,k.indexOf(j));var l=this.__gF[m];if(l!==undefined){n[k]=l+k.substring(m.length);}}return k;},add:function(o,p){this.__gF[o]=p;var r=this._getDynamic();for(var q in r){if(q.substring(0,q.indexOf(j))===o){r[q]=p+q.substring(o.length);}}},remove:function(s){delete this.__gF[s];},resolve:function(t){var u=this._getDynamic();if(t!=null){t=this._preprocess(t);}return u[t]||t;}},destruct:function(){this.__gF=null;}});})();(function(){var c="none",b="qx.html.Decorator",a="absolute";qx.Class.define(b,{extend:qx.html.Element,construct:function(d,e){var f={position:a,top:0,left:0};if(qx.bom.client.Feature.CSS_POINTER_EVENTS){f.pointerEvents=c;}qx.html.Element.call(this,null,f);this.__ks=d;this.__kt=e||d.toHashCode();this.useMarkup(d.getMarkup());},members:{__kt:null,__ks:null,getId:function(){return this.__kt;},getDecorator:function(){return this.__ks;},resize:function(g,h){this.__ks.resize(this.getDomElement(),g,h);},tint:function(i){this.__ks.tint(this.getDomElement(),i);},getInsets:function(){return this.__ks.getInsets();}},destruct:function(){this.__ks=null;}});})();(function(){var f="blur",e="focus",d="input",c="load",b="qx.ui.core.EventHandler",a="activate";qx.Class.define(b,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(){qx.core.Object.call(this);this.__em=qx.event.Registration.getManager(window);},statics:{PRIORITY:qx.event.Registration.PRIORITY_FIRST,SUPPORTED_TYPES:{mousemove:1,mouseover:1,mouseout:1,mousedown:1,mouseup:1,click:1,dblclick:1,contextmenu:1,mousewheel:1,keyup:1,keydown:1,keypress:1,keyinput:1,capture:1,losecapture:1,focusin:1,focusout:1,focus:1,blur:1,activate:1,deactivate:1,appear:1,disappear:1,dragstart:1,dragend:1,dragover:1,dragleave:1,drop:1,drag:1,dragchange:1,droprequest:1,touchstart:1,touchend:1,touchmove:1,touchcancel:1,tap:1,swipe:1},IGNORE_CAN_HANDLE:false},members:{__em:null,__en:{focusin:1,focusout:1,focus:1,blur:1},__eo:{mouseover:1,mouseout:1,appear:1,disappear:1},canHandleEvent:function(g,h){return g instanceof qx.ui.core.Widget;},_dispatchEvent:function(j){var p=j.getTarget();var o=qx.ui.core.Widget.getWidgetByElement(p);var q=false;while(o&&o.isAnonymous()){var q=true;o=o.getLayoutParent();}if(o&&q&&j.getType()==a){o.getContainerElement().activate();}if(this.__en[j.getType()]){o=o&&o.getFocusTarget();if(!o){return;}}if(j.getRelatedTarget){var x=j.getRelatedTarget();var w=qx.ui.core.Widget.getWidgetByElement(x);while(w&&w.isAnonymous()){w=w.getLayoutParent();}if(w){if(this.__en[j.getType()]){w=w.getFocusTarget();}if(w===o){return;}}}var s=j.getCurrentTarget();var u=qx.ui.core.Widget.getWidgetByElement(s);if(!u||u.isAnonymous()){return;}if(this.__en[j.getType()]){u=u.getFocusTarget();}var v=j.getType();if(!u||!(u.isEnabled()||this.__eo[v])){return;}var k=j.getEventPhase()==qx.event.type.Event.CAPTURING_PHASE;var r=this.__em.getListeners(u,v,k);if(!r||r.length===0){return;}var m=qx.event.Pool.getInstance().getObject(j.constructor);j.clone(m);m.setTarget(o);m.setRelatedTarget(w||null);m.setCurrentTarget(u);var y=j.getOriginalTarget();if(y){var n=qx.ui.core.Widget.getWidgetByElement(y);while(n&&n.isAnonymous()){n=n.getLayoutParent();}m.setOriginalTarget(n);}else{m.setOriginalTarget(p);}for(var i=0,l=r.length;i<l;i++){var t=r[i].context||u;r[i].handler.call(t,m);}if(m.getPropagationStopped()){j.stopPropagation();}if(m.getDefaultPrevented()){j.preventDefault();}qx.event.Pool.getInstance().poolObject(m);},registerEvent:function(z,A,B){var C;if(A===e||A===f){C=z.getFocusElement();}else if(A===c||A===d){C=z.getContentElement();}else{C=z.getContainerElement();}if(C){C.addListener(A,this._dispatchEvent,this,B);}},unregisterEvent:function(D,E,F){var G;if(E===e||E===f){G=D.getFocusElement();}else if(E===c||E===d){G=D.getContentElement();}else{G=D.getContainerElement();}if(G){G.removeListener(E,this._dispatchEvent,this,F);}}},destruct:function(){this.__em=null;},defer:function(H){qx.event.Registration.addHandler(H);}});})();(function(){var i="",h="/",g="mshtml",f="qx.client",e="//",d="?",c="string",b="qx.util.ResourceManager",a="singleton";qx.Class.define(b,{extend:qx.core.Object,type:a,statics:{__co:qx.$$resources||{},__cp:{}},members:{has:function(j){return !!this.self(arguments).__co[j];},getData:function(k){return this.self(arguments).__co[k]||null;},getImageWidth:function(l){var m=this.self(arguments).__co[l];return m?m[0]:null;},getImageHeight:function(n){var o=this.self(arguments).__co[n];return o?o[1]:null;},getImageFormat:function(p){var q=this.self(arguments).__co[p];return q?q[2]:null;},isClippedImage:function(r){var s=this.self(arguments).__co[r];return s&&s.length>4;},toUri:function(t){if(t==null){return t;}var u=this.self(arguments).__co[t];if(!u){return t;}if(typeof u===c){var w=u;}else{var w=u[3];if(!w){return t;}}var v=i;if(qx.core.Variant.isSet(f,g)&&qx.bom.client.Feature.SSL){v=this.self(arguments).__cp[w];}return v+qx.$$libraries[w].resourceUri+h+t;}},defer:function(x){if(qx.core.Variant.isSet(f,g)){if(qx.bom.client.Feature.SSL){for(var B in qx.$$libraries){var z;if(qx.$$libraries[B].resourceUri){z=qx.$$libraries[B].resourceUri;}else{x.__cp[B]=i;continue;}if(z.match(/^\/\//)!=null){x.__cp[B]=window.location.protocol;}else if(z.match(/^\//)!=null){x.__cp[B]=window.location.protocol+e+window.location.host;}else if(z.match(/^\.\//)!=null){var y=document.URL;x.__cp[B]=y.substring(0,y.lastIndexOf(h)+1);}else if(z.match(/^http/)!=null){x.__cp[B]=i;}else{var C=window.location.href.indexOf(d);var A;if(C==-1){A=window.location.href;}else{A=window.location.href.substring(0,C);}x.__cp[B]=A.substring(0,A.lastIndexOf(h)+1);}}}}}});})();(function(){var c="qx.bom.client.Locale",b="-",a="";qx.Class.define(c,{statics:{LOCALE:"",VARIANT:"",__lD:function(){var d=(navigator.userLanguage||navigator.language).toLowerCase();var f=a;var e=d.indexOf(b);if(e!=-1){f=d.substr(e+1);d=d.substr(0,e);}this.LOCALE=d;this.VARIANT=f;}},defer:function(g){g.__lD();}});})();(function(){var t="",s='indexOf',r='slice',q='concat',p='toLocaleLowerCase',o="qx.type.BaseString",n='match',m='toLocaleUpperCase',k='search',j='replace',c='toLowerCase',h='charCodeAt',f='split',b='substring',a='lastIndexOf',e='substr',d='toUpperCase',g='charAt';qx.Class.define(o,{extend:Object,construct:function(u){var u=u||t;this.__mc=u;this.length=u.length;},members:{$$isString:true,length:0,__mc:null,toString:function(){return this.__mc;},charAt:null,valueOf:null,charCodeAt:null,concat:null,indexOf:null,lastIndexOf:null,match:null,replace:null,search:null,slice:null,split:null,substr:null,substring:null,toLowerCase:null,toUpperCase:null,toHashCode:function(){return qx.core.ObjectRegistry.toHashCode(this);},toLocaleLowerCase:null,toLocaleUpperCase:null,base:function(v,w){return qx.core.Object.prototype.base.apply(this,arguments);}},defer:function(x,y){{};var z=[g,h,q,s,a,n,j,k,r,f,e,b,c,d,p,m];y.valueOf=y.toString;if(new x(t).valueOf()==null){delete y.valueOf;}for(var i=0,l=z.length;i<l;i++){y[z[i]]=String.prototype[z[i]];}}});})();(function(){var a="qx.locale.LocalizedString";qx.Class.define(a,{extend:qx.type.BaseString,construct:function(b,c,d){qx.type.BaseString.call(this,b);this.__ep=c;this.__eq=d;},members:{__ep:null,__eq:null,translate:function(){return qx.locale.Manager.getInstance().translate(this.__ep,this.__eq);}}});})();(function(){var k="_",j="",h="_applyLocale",g="changeLocale",f="C",e="qx.dynlocale",d="on",c="qx.locale.Manager",b="String",a="singleton";qx.Class.define(c,{type:a,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__jf=qx.$$translations||{};this.__jg=qx.$$locales||{};var n=qx.bom.client.Locale;var l=n.LOCALE;var m=n.VARIANT;if(m!==j){l+=k+m;}this.__jh=l;this.setLocale(l||this.__ji);},statics:{tr:function(o,p){var q=qx.lang.Array.fromArguments(arguments);q.splice(0,1);return qx.locale.Manager.getInstance().translate(o,q);},trn:function(r,s,t,u){var v=qx.lang.Array.fromArguments(arguments);v.splice(0,3);if(t!=1){return qx.locale.Manager.getInstance().translate(s,v);}else{return qx.locale.Manager.getInstance().translate(r,v);}},trc:function(w,x,y){var z=qx.lang.Array.fromArguments(arguments);z.splice(0,2);return qx.locale.Manager.getInstance().translate(x,z);},marktr:function(A){return A;}},properties:{locale:{check:b,nullable:true,apply:h,event:g}},members:{__ji:f,__jj:null,__jk:null,__jf:null,__jg:null,__jh:null,getLanguage:function(){return this.__jk;},getTerritory:function(){return this.getLocale().split(k)[1]||j;},getAvailableLocales:function(){var C=[];for(var B in this.__jg){if(B!=this.__ji){C.push(B);}}return C;},__jl:function(D){var F;var E=D.indexOf(k);if(E==-1){F=D;}else{F=D.substring(0,E);}return F;},_applyLocale:function(G,H){{};this.__jj=G;this.__jk=this.__jl(G);},addTranslation:function(I,J){var K=this.__jf;if(K[I]){for(var L in J){K[I][L]=J[L];}}else{K[I]=J;}},addLocale:function(M,N){var O=this.__jg;if(O[M]){for(var P in N){O[M][P]=N[P];}}else{O[M]=N;}},translate:function(Q,R,S){var T=this.__jf;return this.__jm(T,Q,R,S);},localize:function(U,V,W){var X=this.__jg;return this.__jm(X,U,V,W);},__jm:function(Y,ba,bb,bc){var bd;if(!Y){return ba;}if(bc){var bf=this.__jl(bc);}else{bc=this.__jj;bf=this.__jk;}if(!bd&&Y[bc]){bd=Y[bc][ba];}if(!bd&&Y[bf]){bd=Y[bf][ba];}if(!bd&&Y[this.__ji]){bd=Y[this.__ji][ba];}if(!bd){bd=ba;}if(bb.length>0){var be=[];for(var i=0;i<bb.length;i++){var bg=bb[i];if(bg&&bg.translate){be[i]=bg.translate();}else{be[i]=bg;}}bd=qx.lang.String.format(bd,be);}if(qx.core.Variant.isSet(e,d)){bd=new qx.locale.LocalizedString(bd,ba,bb);}return bd;}},destruct:function(){this.__jf=this.__jg=null;}});})();(function(){var k="px",j="qx.client",i="div",h="img",g="",f="no-repeat",d="scale-x",c="mshtml",b="scale",a="scale-y",G="qx/icon",F="repeat",E=".png",D="crop",C="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='",B='<div style="',A="repeat-y",z='<img src="',y="qx.bom.element.Decoration",x="', sizingMethod='",r="png",s="')",p='"></div>',q='"/>',n='" style="',o="none",l="webkit",m=" ",t="repeat-x",u="DXImageTransform.Microsoft.AlphaImageLoader",w="qx/static/blank.gif",v="absolute";qx.Class.define(y,{statics:{DEBUG:false,__hx:{},__hy:qx.core.Variant.isSet(j,c)&&qx.bom.client.Engine.VERSION<9,__hz:qx.core.Variant.select(j,{"mshtml":{"scale-x":true,"scale-y":true,"scale":true,"no-repeat":true},"default":null}),__hA:{"scale-x":h,"scale-y":h,"scale":h,"repeat":i,"no-repeat":i,"repeat-x":i,"repeat-y":i},update:function(H,I,J,K){var M=this.getTagName(J,I);if(M!=H.tagName.toLowerCase()){throw new Error("Image modification not possible because elements could not be replaced at runtime anymore!");}var N=this.getAttributes(I,J,K);if(M===h){H.src=N.src||qx.util.ResourceManager.getInstance().toUri(w);}if(H.style.backgroundPosition!=g&&N.style.backgroundPosition===undefined){N.style.backgroundPosition=null;}if(H.style.clip!=g&&N.style.clip===undefined){N.style.clip=null;}var L=qx.bom.element.Style;L.setStyles(H,N.style);if(this.__hy){try{H.filters[u].apply();}catch(e){}}},create:function(O,P,Q){var R=this.getTagName(P,O);var T=this.getAttributes(O,P,Q);var S=qx.bom.element.Style.compile(T.style);if(R===h){return z+T.src+n+S+q;}else{return B+S+p;}},getTagName:function(U,V){if(qx.core.Variant.isSet(j,c)){if(V&&this.__hy&&this.__hz[U]&&qx.lang.String.endsWith(V,E)){return i;}}return this.__hA[U];},getAttributes:function(W,X,Y){if(!Y){Y={};}if(!Y.position){Y.position=v;}if(qx.core.Variant.isSet(j,c)){Y.fontSize=0;Y.lineHeight=0;}else if(qx.core.Variant.isSet(j,l)){Y.WebkitUserDrag=o;}var bb=qx.util.ResourceManager.getInstance().getImageFormat(W)||qx.io.ImageLoader.getFormat(W);{};var ba;if(this.__hy&&this.__hz[X]&&bb===r){ba=this.__hD(Y,X,W);}else{if(X===b){ba=this.__hE(Y,X,W);}else if(X===d||X===a){ba=this.__hF(Y,X,W);}else{ba=this.__hI(Y,X,W);}}return ba;},__hB:function(bc,bd,be){if(bc.width==null&&bd!=null){bc.width=bd+k;}if(bc.height==null&&be!=null){bc.height=be+k;}return bc;},__hC:function(bf){var bh=qx.util.ResourceManager.getInstance().getImageWidth(bf)||qx.io.ImageLoader.getWidth(bf);var bi=qx.util.ResourceManager.getInstance().getImageHeight(bf)||qx.io.ImageLoader.getHeight(bf);return {width:bh,height:bi};},__hD:function(bj,bk,bl){var bo=this.__hC(bl);bj=this.__hB(bj,bo.width,bo.height);var bn=bk==f?D:b;var bm=C+qx.util.ResourceManager.getInstance().toUri(bl)+x+bn+s;bj.filter=bm;bj.backgroundImage=bj.backgroundRepeat=g;return {style:bj};},__hE:function(bp,bq,br){var bs=qx.util.ResourceManager.getInstance().toUri(br);var bt=this.__hC(br);bp=this.__hB(bp,bt.width,bt.height);return {src:bs,style:bp};},__hF:function(bu,bv,bw){var bA=qx.util.ResourceManager.getInstance();var bz=bA.isClippedImage(bw);var bB=this.__hC(bw);if(bz){var by=bA.getData(bw);var bx=bA.toUri(by[4]);if(bv===d){bu=this.__hG(bu,by,bB.height);}else{bu=this.__hH(bu,by,bB.width);}return {src:bx,style:bu};}else{{};if(bv==d){bu.height=bB.height==null?null:bB.height+k;}else if(bv==a){bu.width=bB.width==null?null:bB.width+k;}var bx=bA.toUri(bw);return {src:bx,style:bu};}},__hG:function(bC,bD,bE){var bF=qx.util.ResourceManager.getInstance().getImageHeight(bD[4]);bC.clip={top:-bD[6],height:bE};bC.height=bF+k;if(bC.top!=null){bC.top=(parseInt(bC.top,10)+bD[6])+k;}else if(bC.bottom!=null){bC.bottom=(parseInt(bC.bottom,10)+bE-bF-bD[6])+k;}return bC;},__hH:function(bG,bH,bI){var bJ=qx.util.ResourceManager.getInstance().getImageWidth(bH[4]);bG.clip={left:-bH[5],width:bI};bG.width=bJ+k;if(bG.left!=null){bG.left=(parseInt(bG.left,10)+bH[5])+k;}else if(bG.right!=null){bG.right=(parseInt(bG.right,10)+bI-bJ-bH[5])+k;}return bG;},__hI:function(bK,bL,bM){var bR=qx.util.ResourceManager.getInstance().isClippedImage(bM);var bQ=this.__hC(bM);if(bR&&bL!==F){var bP=qx.util.ResourceManager.getInstance().getData(bM);var bO=qx.bom.element.Background.getStyles(bP[4],bL,bP[5],bP[6]);for(var bN in bO){bK[bN]=bO[bN];}if(bQ.width!=null&&bK.width==null&&(bL==A||bL===f)){bK.width=bQ.width+k;}if(bQ.height!=null&&bK.height==null&&(bL==t||bL===f)){bK.height=bQ.height+k;}return {style:bK};}else{{};bK=this.__hB(bK,bQ.width,bQ.height);bK=this.__hJ(bK,bM,bL);return {style:bK};}},__hJ:function(bS,bT,bU){var top=null;var bY=null;if(bS.backgroundPosition){var bV=bS.backgroundPosition.split(m);bY=parseInt(bV[0],10);if(isNaN(bY)){bY=bV[0];}top=parseInt(bV[1],10);if(isNaN(top)){top=bV[1];}}var bX=qx.bom.element.Background.getStyles(bT,bU,bY,top);for(var bW in bX){bS[bW]=bX[bW];}if(bS.filter){bS.filter=g;}return bS;},__hK:function(ca){if(this.DEBUG&&qx.util.ResourceManager.getInstance().has(ca)&&ca.indexOf(G)==-1){if(!this.__hx[ca]){qx.log.Logger.debug("Potential clipped image candidate: "+ca);this.__hx[ca]=true;}}},isAlphaImageLoaderEnabled:qx.core.Variant.select(j,{"mshtml":function(){return qx.bom.element.Decoration.__hy;},"default":function(){return false;}})}});})();(function(){var c="qx.client",b="load",a="qx.io.ImageLoader";qx.Bootstrap.define(a,{statics:{__lo:{},__lp:{width:null,height:null},__lq:/\.(png|gif|jpg|jpeg|bmp)\b/i,isLoaded:function(d){var e=this.__lo[d];return !!(e&&e.loaded);},isFailed:function(f){var g=this.__lo[f];return !!(g&&g.failed);},isLoading:function(h){var j=this.__lo[h];return !!(j&&j.loading);},getFormat:function(k){var m=this.__lo[k];return m?m.format:null;},getSize:function(n){var o=this.__lo[n];return o?{width:o.width,height:o.height}:this.__lp;},getWidth:function(p){var q=this.__lo[p];return q?q.width:null;},getHeight:function(r){var s=this.__lo[r];return s?s.height:null;},load:function(t,u,v){var w=this.__lo[t];if(!w){w=this.__lo[t]={};}if(u&&!v){v=window;}if(w.loaded||w.loading||w.failed){if(u){if(w.loading){w.callbacks.push(u,v);}else{u.call(v,t,w);}}}else{w.loading=true;w.callbacks=[];if(u){w.callbacks.push(u,v);}var y=new Image();var x=qx.lang.Function.listener(this.__lr,this,y,t);y.onload=x;y.onerror=x;y.src=t;w.element=y;}},abort:function(z){var A=this.__lo[z];if(A&&!A.loaded){A.aborted=true;var C=A.callbacks;var B=A.element;B.onload=B.onerror=null;delete A.callbacks;delete A.element;delete A.loading;for(var i=0,l=C.length;i<l;i+=2){C[i].call(C[i+1],z,A);}}this.__lo[z]=null;},__lr:qx.event.GlobalError.observeMethod(function(event,D,E){var F=this.__lo[E];if(event.type===b){F.loaded=true;F.width=this.__ls(D);F.height=this.__lt(D);var G=this.__lq.exec(E);if(G!=null){F.format=G[1];}}else{F.failed=true;}D.onload=D.onerror=null;var H=F.callbacks;delete F.loading;delete F.callbacks;delete F.element;for(var i=0,l=H.length;i<l;i+=2){H[i].call(H[i+1],E,F);}}),__ls:qx.core.Variant.select(c,{"gecko":function(I){return I.naturalWidth;},"default":function(J){return J.width;}}),__lt:qx.core.Variant.select(c,{"gecko":function(K){return K.naturalHeight;},"default":function(L){return L.height;}})}});})();(function(){var m="number",l="0",k="px",j=";",i="background-image:url(",h=");",g="",f=")",e="background-repeat:",d=" ",a="qx.bom.element.Background",c="url(",b="background-position:";qx.Class.define(a,{statics:{__da:[i,null,h,b,null,j,e,null,j],__db:{backgroundImage:null,backgroundPosition:null,backgroundRepeat:null},__dc:function(n,top){var o=qx.bom.client.Engine;if(o.GECKO&&o.VERSION<1.9&&n==top&&typeof n==m){top+=0.01;}if(n){var p=(typeof n==m)?n+k:n;}else{p=l;}if(top){var q=(typeof top==m)?top+k:top;}else{q=l;}return p+d+q;},compile:function(r,s,t,top){var u=this.__dc(t,top);var v=qx.util.ResourceManager.getInstance().toUri(r);var w=this.__da;w[1]=v;w[4]=u;w[7]=s;return w.join(g);},getStyles:function(x,y,z,top){if(!x){return this.__db;}var A=this.__dc(z,top);var B=qx.util.ResourceManager.getInstance().toUri(x);var C={backgroundPosition:A,backgroundImage:c+B+f};if(y!=null){C.backgroundRepeat=y;}return C;},set:function(D,E,F,G,top){var H=this.getStyles(E,F,G,top);for(var I in H){D.style[I]=H[I];}}}});})();(function(){var j="source",i="scale",h="no-repeat",g="qx.client",f="mshtml",e="webkit",d="backgroundImage",c="div",b="qx.html.Image",a="qx/static/blank.gif";qx.Class.define(b,{extend:qx.html.Element,members:{tagNameHint:null,_applyProperty:function(name,k){qx.html.Element.prototype._applyProperty.call(this,name,k);if(name===j){var o=this.getDomElement();var l=this.getAllStyles();if(this.getNodeName()==c&&this.getStyle(d)){l.backgroundPosition=null;l.backgroundRepeat=null;}var m=this._getProperty(j);var n=this._getProperty(i);var p=n?i:h;if(m!=null){qx.bom.element.Decoration.update(o,m,p,l);}}},_createDomElement:function(){var r=this._getProperty(i);var s=r?i:h;if(qx.core.Variant.isSet(g,f)){var q=this._getProperty(j);if(this.tagNameHint!=null){this.setNodeName(this.tagNameHint);}else{this.setNodeName(qx.bom.element.Decoration.getTagName(s,q));}}else{this.setNodeName(qx.bom.element.Decoration.getTagName(s));}return qx.html.Element.prototype._createDomElement.call(this);},_copyData:function(t){return qx.html.Element.prototype._copyData.call(this,true);},setSource:function(u){this._setProperty(j,u);return this;},getSource:function(){return this._getProperty(j);},resetSource:function(){if(qx.core.Variant.isSet(g,e)){this._setProperty(j,qx.util.ResourceManager.getInstance().toUri(a));}else{this._removeProperty(j,true);}return this;},setScale:function(v){this._setProperty(i,v);return this;},getScale:function(){return this._getProperty(i);}}});})();(function(){var f="_applyTheme",e="qx.theme.manager.Color",d="Theme",c="changeTheme",b="string",a="singleton";qx.Class.define(e,{type:a,extend:qx.util.ValueManager,properties:{theme:{check:d,nullable:true,apply:f,event:c}},members:{_applyTheme:function(g){var h={};if(g){var i=g.colors;var j=qx.util.ColorUtil;var k;for(var l in i){k=i[l];if(typeof k===b){if(!j.isCssString(k)){throw new Error("Could not parse color: "+k);}}else if(k instanceof Array){k=j.rgbToRgbString(k);}else{throw new Error("Could not parse color: "+k);}h[l]=k;}}this._setDynamic(h);},resolve:function(m){var p=this._dynamic;var n=p[m];if(n){return n;}var o=this.getTheme();if(o!==null&&o.colors[m]){return p[m]=o.colors[m];}return m;},isDynamic:function(q){var s=this._dynamic;if(q&&(s[q]!==undefined)){return true;}var r=this.getTheme();if(r!==null&&q&&(r.colors[q]!==undefined)){s[q]=r.colors[q];return true;}return false;}}});})();(function(){var h=",",e="rgb(",d=")",c="qx.theme.manager.Color",a="qx.util.ColorUtil";qx.Class.define(a,{statics:{REGEXP:{hex3:/^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,rgb:/^rgb\(\s*([0-9]{1,3}\.{0,1}[0-9]*)\s*,\s*([0-9]{1,3}\.{0,1}[0-9]*)\s*,\s*([0-9]{1,3}\.{0,1}[0-9]*)\s*\)$/,rgba:/^rgba\(\s*([0-9]{1,3}\.{0,1}[0-9]*)\s*,\s*([0-9]{1,3}\.{0,1}[0-9]*)\s*,\s*([0-9]{1,3}\.{0,1}[0-9]*)\s*,\s*([0-9]{1,3}\.{0,1}[0-9]*)\s*\)$/},SYSTEM:{activeborder:true,activecaption:true,appworkspace:true,background:true,buttonface:true,buttonhighlight:true,buttonshadow:true,buttontext:true,captiontext:true,graytext:true,highlight:true,highlighttext:true,inactiveborder:true,inactivecaption:true,inactivecaptiontext:true,infobackground:true,infotext:true,menu:true,menutext:true,scrollbar:true,threeddarkshadow:true,threedface:true,threedhighlight:true,threedlightshadow:true,threedshadow:true,window:true,windowframe:true,windowtext:true},NAMED:{black:[0,0,0],silver:[192,192,192],gray:[128,128,128],white:[255,255,255],maroon:[128,0,0],red:[255,0,0],purple:[128,0,128],fuchsia:[255,0,255],green:[0,128,0],lime:[0,255,0],olive:[128,128,0],yellow:[255,255,0],navy:[0,0,128],blue:[0,0,255],teal:[0,128,128],aqua:[0,255,255],transparent:[-1,-1,-1],magenta:[255,0,255],orange:[255,165,0],brown:[165,42,42]},isNamedColor:function(j){return this.NAMED[j]!==undefined;},isSystemColor:function(k){return this.SYSTEM[k]!==undefined;},supportsThemes:function(){return qx.Class.isDefined(c);},isThemedColor:function(l){if(!this.supportsThemes()){return false;}return qx.theme.manager.Color.getInstance().isDynamic(l);},stringToRgb:function(m){if(this.supportsThemes()&&this.isThemedColor(m)){var m=qx.theme.manager.Color.getInstance().resolveDynamic(m);}if(this.isNamedColor(m)){return this.NAMED[m];}else if(this.isSystemColor(m)){throw new Error("Could not convert system colors to RGB: "+m);}else if(this.isRgbString(m)){return this.__gB();}else if(this.isHex3String(m)){return this.__gD();}else if(this.isHex6String(m)){return this.__gE();}throw new Error("Could not parse color: "+m);},cssStringToRgb:function(n){if(this.isNamedColor(n)){return this.NAMED[n];}else if(this.isSystemColor(n)){throw new Error("Could not convert system colors to RGB: "+n);}else if(this.isRgbString(n)){return this.__gB();}else if(this.isRgbaString(n)){return this.__gC();}else if(this.isHex3String(n)){return this.__gD();}else if(this.isHex6String(n)){return this.__gE();}throw new Error("Could not parse color: "+n);},stringToRgbString:function(o){return this.rgbToRgbString(this.stringToRgb(o));},rgbToRgbString:function(s){return e+s[0]+h+s[1]+h+s[2]+d;},rgbToHexString:function(u){return (qx.lang.String.pad(u[0].toString(16).toUpperCase(),2)+qx.lang.String.pad(u[1].toString(16).toUpperCase(),2)+qx.lang.String.pad(u[2].toString(16).toUpperCase(),2));},isValidPropertyValue:function(v){return this.isThemedColor(v)||this.isNamedColor(v)||this.isHex3String(v)||this.isHex6String(v)||this.isRgbString(v);},isCssString:function(w){return this.isSystemColor(w)||this.isNamedColor(w)||this.isHex3String(w)||this.isHex6String(w)||this.isRgbString(w);},isHex3String:function(x){return this.REGEXP.hex3.test(x);},isHex6String:function(y){return this.REGEXP.hex6.test(y);},isRgbString:function(z){return this.REGEXP.rgb.test(z);},isRgbaString:function(A){return this.REGEXP.rgba.test(A);},__gB:function(){var D=parseInt(RegExp.$1,10);var C=parseInt(RegExp.$2,10);var B=parseInt(RegExp.$3,10);return [D,C,B];},__gC:function(){var G=parseInt(RegExp.$1,10);var F=parseInt(RegExp.$2,10);var E=parseInt(RegExp.$3,10);return [G,F,E];},__gD:function(){var J=parseInt(RegExp.$1,16)*17;var I=parseInt(RegExp.$2,16)*17;var H=parseInt(RegExp.$3,16)*17;return [J,I,H];},__gE:function(){var M=(parseInt(RegExp.$1,16)*16)+parseInt(RegExp.$2,16);var L=(parseInt(RegExp.$3,16)*16)+parseInt(RegExp.$4,16);var K=(parseInt(RegExp.$5,16)*16)+parseInt(RegExp.$6,16);return [M,L,K];},hex3StringToRgb:function(N){if(this.isHex3String(N)){return this.__gD(N);}throw new Error("Invalid hex3 value: "+N);},hex6StringToRgb:function(O){if(this.isHex6String(O)){return this.__gE(O);}throw new Error("Invalid hex6 value: "+O);},hexStringToRgb:function(P){if(this.isHex3String(P)){return this.__gD(P);}if(this.isHex6String(P)){return this.__gE(P);}throw new Error("Invalid hex value: "+P);},rgbToHsb:function(Q){var S,T,V;var bc=Q[0];var Y=Q[1];var R=Q[2];var bb=(bc>Y)?bc:Y;if(R>bb){bb=R;}var U=(bc<Y)?bc:Y;if(R<U){U=R;}V=bb/255.0;if(bb!=0){T=(bb-U)/bb;}else{T=0;}if(T==0){S=0;}else{var X=(bb-bc)/(bb-U);var ba=(bb-Y)/(bb-U);var W=(bb-R)/(bb-U);if(bc==bb){S=W-ba;}else if(Y==bb){S=2.0+X-W;}else{S=4.0+ba-X;}S=S/6.0;if(S<0){S=S+1.0;}}return [Math.round(S*360),Math.round(T*100),Math.round(V*100)];},hsbToRgb:function(bd){var i,f,p,q,t;var be=bd[0]/360;var bf=bd[1]/100;var bg=bd[2]/100;if(be>=1.0){be%=1.0;}if(bf>1.0){bf=1.0;}if(bg>1.0){bg=1.0;}var bh=Math.floor(255*bg);var bi={};if(bf==0.0){bi.red=bi.green=bi.blue=bh;}else{be*=6.0;i=Math.floor(be);f=be-i;p=Math.floor(bh*(1.0-bf));q=Math.floor(bh*(1.0-(bf*f)));t=Math.floor(bh*(1.0-(bf*(1.0-f))));switch(i){case 0:bi.red=bh;bi.green=t;bi.blue=p;break;case 1:bi.red=q;bi.green=bh;bi.blue=p;break;case 2:bi.red=p;bi.green=bh;bi.blue=t;break;case 3:bi.red=p;bi.green=q;bi.blue=bh;break;case 4:bi.red=t;bi.green=p;bi.blue=bh;break;case 5:bi.red=bh;bi.green=p;bi.blue=q;break;}}return [bi.red,bi.green,bi.blue];},randomColor:function(){var r=Math.round(Math.random()*255);var g=Math.round(Math.random()*255);var b=Math.round(Math.random()*255);return this.rgbToRgbString([r,g,b]);}}});})();(function(){var h="string",g="_applyTheme",f="qx.theme.manager.Appearance",e=":",d="Theme",c="changeTheme",b="/",a="singleton";qx.Class.define(f,{type:a,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__dL={};this.__dM={};},properties:{theme:{check:d,nullable:true,event:c,apply:g}},members:{__dN:{},__dL:null,__dM:null,_applyTheme:function(j,k){this.__dM={};this.__dL={};},__dO:function(l,m,n){var s=m.appearances;var v=s[l];if(!v){var w=b;var p=[];var u=l.split(w);var t;while(!v&&u.length>0){p.unshift(u.pop());var q=u.join(w);v=s[q];if(v){t=v.alias||v;if(typeof t===h){var r=t+w+p.join(w);return this.__dO(r,m,n);}}}for(var i=0;i<p.length-1;i++){p.shift();var q=p.join(w);var o=this.__dO(q,m);if(o){return o;}}if(n!=null){return this.__dO(n,m);}return null;}else if(typeof v===h){return this.__dO(v,m,n);}else if(v.include&&!v.style){return this.__dO(v.include,m,n);}return l;},styleFrom:function(x,y,z,A){if(!z){z=this.getTheme();}var G=this.__dM;var B=G[x];if(!B){B=G[x]=this.__dO(x,z,A);}var L=z.appearances[B];if(!L){this.warn("Missing appearance: "+x);return null;}if(!L.style){return null;}var M=B;if(y){var N=L.$$bits;if(!N){N=L.$$bits={};L.$$length=0;}var E=0;for(var H in y){if(!y[H]){continue;}if(N[H]==null){N[H]=1<<L.$$length++;}E+=N[H];}if(E>0){M+=e+E;}}var F=this.__dL;if(F[M]!==undefined){return F[M];}if(!y){y=this.__dN;}var J;if(L.include||L.base){var D=L.style(y);var C;if(L.include){C=this.styleFrom(L.include,y,z,A);}J={};if(L.base){var I=this.styleFrom(B,y,L.base,A);if(L.include){for(var K in I){if(!C.hasOwnProperty(K)&&!D.hasOwnProperty(K)){J[K]=I[K];}}}else{for(var K in I){if(!D.hasOwnProperty(K)){J[K]=I[K];}}}}if(L.include){for(var K in C){if(!D.hasOwnProperty(K)){J[K]=C[K];}}}for(var K in D){J[K]=D[K];}}else{J=L.style(y);}return F[M]=J||null;}},destruct:function(){this.__dL=this.__dM=null;}});})();(function(){var j="nonScaled",i="scaled",h="alphaScaled",g=".png",f="qx.client",e="div",d="replacement",c="qx.event.type.Event",b="hidden",a="Boolean",y="px",x="scale",w="changeSource",v="__fP",u="qx.ui.basic.Image",t="loaded",s="-disabled.$1",r="loadingFailed",q="String",p="_applySource",n="img",o="image",l="mshtml",m="_applyScale",k="no-repeat";qx.Class.define(u,{extend:qx.ui.core.Widget,construct:function(z){this.__fP={};qx.ui.core.Widget.call(this);if(z){this.setSource(z);}},properties:{source:{check:q,init:null,nullable:true,event:w,apply:p,themeable:true},scale:{check:a,init:false,themeable:true,apply:m},appearance:{refine:true,init:o},allowShrinkX:{refine:true,init:false},allowShrinkY:{refine:true,init:false},allowGrowX:{refine:true,init:false},allowGrowY:{refine:true,init:false}},events:{loadingFailed:c,loaded:c},members:{__fQ:null,__fR:null,__fS:null,__fP:null,getContentElement:function(){return this.__fW();},_createContentElement:function(){return this.__fW();},_getContentHint:function(){return {width:this.__fQ||0,height:this.__fR||0};},_applyEnabled:function(A,B){qx.ui.core.Widget.prototype._applyEnabled.call(this,A,B);if(this.getSource()){this._styleSource();}},_applySource:function(C){this._styleSource();},_applyScale:function(D){this._styleSource();},__fT:function(E){this.__fS=E;},__fU:function(){if(this.__fS==null){var G=this.getSource();var F=false;if(G!=null){F=qx.lang.String.endsWith(G,g);}if(this.getScale()&&F&&qx.bom.element.Decoration.isAlphaImageLoaderEnabled()){this.__fS=h;}else if(this.getScale()){this.__fS=i;}else{this.__fS=j;}}return this.__fS;},__fV:function(H){var I;var J;if(H==h){I=true;J=e;}else if(H==j){I=false;J=e;}else{I=true;J=n;}var K=new qx.html.Image(J);K.setScale(I);K.setStyles({"overflowX":b,"overflowY":b});return K;},__fW:function(){var L=this.__fU();if(this.__fP[L]==null){this.__fP[L]=this.__fV(L);}return this.__fP[L];},_styleSource:function(){var M=qx.util.AliasManager.getInstance().resolve(this.getSource());if(!M){this.getContentElement().resetSource();return;}this.__fX(M);if(qx.core.Variant.isSet(f,l)){var N=this.getScale()?x:k;this.getContentElement().tagNameHint=qx.bom.element.Decoration.getTagName(N,M);}if(qx.util.ResourceManager.getInstance().has(M)){this.__ga(this.getContentElement(),M);}else if(qx.io.ImageLoader.isLoaded(M)){this.__gb(this.getContentElement(),M);}else{this.__gc(this.getContentElement(),M);}},__fX:qx.core.Variant.select(f,{"mshtml":function(O){var Q=qx.bom.element.Decoration.isAlphaImageLoaderEnabled();var P=qx.lang.String.endsWith(O,g);if(Q&&P){if(this.getScale()&&this.__fU()!=h){this.__fT(h);}else if(!this.getScale()&&this.__fU()!=j){this.__fT(j);}}else{if(this.getScale()&&this.__fU()!=i){this.__fT(i);}else if(!this.getScale()&&this.__fU()!=j){this.__fT(j);}}this.__fY(this.__fW());},"default":function(R){if(this.getScale()&&this.__fU()!=i){this.__fT(i);}else if(!this.getScale()&&this.__fU(j)){this.__fT(j);}this.__fY(this.__fW());}}),__fY:function(S){var V=this.getContainerElement();var W=V.getChild(0);if(W!=S){if(W!=null){var Y=y;var T={};var U=this.getInnerSize();if(U!=null){T.width=U.width+Y;T.height=U.height+Y;}var X=this.getInsets();T.left=X.left+Y;T.top=X.top+Y;T.zIndex=10;S.setStyles(T,true);S.setSelectable(this.getSelectable());}V.removeAt(0);V.addAt(S,0);}},__ga:function(ba,bb){var bd=qx.util.ResourceManager.getInstance();if(!this.getEnabled()){var bc=bb.replace(/\.([a-z]+)$/,s);if(bd.has(bc)){bb=bc;this.addState(d);}else{this.removeState(d);}}if(ba.getSource()===bb){return;}ba.setSource(bb);this.__ge(bd.getImageWidth(bb),bd.getImageHeight(bb));},__gb:function(be,bf){var bh=qx.io.ImageLoader;be.setSource(bf);var bg=bh.getWidth(bf);var bi=bh.getHeight(bf);this.__ge(bg,bi);},__gc:function(bj,bk){var self;var bl=qx.io.ImageLoader;{};if(!bl.isFailed(bk)){bl.load(bk,this.__gd,this);}else{if(bj!=null){bj.resetSource();}}},__gd:function(bm,bn){if(this.$$disposed===true){return;}if(bm!==qx.util.AliasManager.getInstance().resolve(this.getSource())){return;}if(bn.failed){this.warn("Image could not be loaded: "+bm);this.fireEvent(r);}else{this.fireEvent(t);}this._styleSource();},__ge:function(bo,bp){if(bo!==this.__fQ||bp!==this.__fR){this.__fQ=bo;this.__fR=bp;qx.ui.core.queue.Layout.add(this);}}},destruct:function(){this._disposeMap(v);}});})();(function(){var j="Integer",i="interval",h="keep-align",g="disappear",f="best-fit",e="mouse",d="bottom-left",c="direct",b="Boolean",a="bottom-right",x="widget",w="qx.ui.core.MPlacement",v="left-top",u="offsetRight",t="shorthand",s="offsetLeft",r="top-left",q="appear",p="offsetBottom",o="top-right",m="offsetTop",n="right-bottom",k="right-top",l="left-bottom";qx.Mixin.define(w,{statics:{__iR:null,setVisibleElement:function(y){this.__iR=y;},getVisibleElement:function(){return this.__iR;}},properties:{position:{check:[r,o,d,a,v,l,k,n],init:d,themeable:true},placeMethod:{check:[x,e],init:e,themeable:true},domMove:{check:b,init:false},placementModeX:{check:[c,h,f],init:h,themeable:true},placementModeY:{check:[c,h,f],init:h,themeable:true},offsetLeft:{check:j,init:0,themeable:true},offsetTop:{check:j,init:0,themeable:true},offsetRight:{check:j,init:0,themeable:true},offsetBottom:{check:j,init:0,themeable:true},offset:{group:[m,u,p,s],mode:t,themeable:true}},members:{__iS:null,__iT:null,__iU:null,getLayoutLocation:function(z){var C,B,D,top;B=z.getBounds();D=B.left;top=B.top;var E=B;z=z.getLayoutParent();while(z&&!z.isRootWidget()){B=z.getBounds();D+=B.left;top+=B.top;C=z.getInsets();D+=C.left;top+=C.top;z=z.getLayoutParent();}if(z.isRootWidget()){var A=z.getContainerLocation();if(A){D+=A.left;top+=A.top;}}return {left:D,top:top,right:D+E.width,bottom:top+E.height};},moveTo:function(F,top){var H=qx.ui.core.MPlacement.getVisibleElement();if(H){var J=this.getBounds();var G=H.getContentLocation();if(J&&G){var K=top+J.height;var I=F+J.width;if((I>G.left&&F<G.right)&&(K>G.top&&top<G.bottom)){F=Math.max(G.left-J.width,0);}}}if(this.getDomMove()){this.setDomPosition(F,top);}else{this.setLayoutProperties({left:F,top:top});}},placeToWidget:function(L,M){if(M){this.__iV();this.__iS=qx.lang.Function.bind(this.placeToWidget,this,L,false);qx.event.Idle.getInstance().addListener(i,this.__iS);this.__iU=function(){this.__iV();};this.addListener(g,this.__iU,this);}var N=L.getContainerLocation()||this.getLayoutLocation(L);this.__iX(N);},__iV:function(){if(this.__iS){qx.event.Idle.getInstance().removeListener(i,this.__iS);this.__iS=null;}if(this.__iU){this.removeListener(g,this.__iU,this);this.__iU=null;}},placeToMouse:function(event){var P=event.getDocumentLeft();var top=event.getDocumentTop();var O={left:P,top:top,right:P,bottom:top};this.__iX(O);},placeToElement:function(Q,R){var location=qx.bom.element.Location.get(Q);var S={left:location.left,top:location.top,right:location.left+Q.offsetWidth,bottom:location.top+Q.offsetHeight};if(R){this.__iS=qx.lang.Function.bind(this.placeToElement,this,Q,false);qx.event.Idle.getInstance().addListener(i,this.__iS);this.addListener(g,function(){if(this.__iS){qx.event.Idle.getInstance().removeListener(i,this.__iS);this.__iS=null;}},this);}this.__iX(S);},placeToPoint:function(T){var U={left:T.left,top:T.top,right:T.left,bottom:T.top};this.__iX(U);},_getPlacementOffsets:function(){return {left:this.getOffsetLeft(),top:this.getOffsetTop(),right:this.getOffsetRight(),bottom:this.getOffsetBottom()};},__iW:function(V){var W=null;if(this._computePlacementSize){var W=this._computePlacementSize();}else if(this.isVisible()){var W=this.getBounds();}if(W==null){this.addListenerOnce(q,function(){this.__iW(V);},this);}else{V.call(this,W);}},__iX:function(X){this.__iW(function(Y){var ba=qx.util.placement.Placement.compute(Y,this.getLayoutParent().getBounds(),X,this._getPlacementOffsets(),this.getPosition(),this.getPlacementModeX(),this.getPlacementModeY());this.moveTo(ba.left,ba.top);});}},destruct:function(){this.__iV();}});})();(function(){var g="dragdrop-cursor",f="_applyAction",e="alias",d="qx.ui.core.DragDropCursor",c="move",b="singleton",a="copy";qx.Class.define(d,{extend:qx.ui.basic.Image,include:qx.ui.core.MPlacement,type:b,construct:function(){qx.ui.basic.Image.call(this);this.setZIndex(1e8);this.setDomMove(true);var h=this.getApplicationRoot();h.add(this,{left:-1000,top:-1000});},properties:{appearance:{refine:true,init:g},action:{check:[e,a,c],apply:f,nullable:true}},members:{_applyAction:function(i,j){if(j){this.removeState(j);}if(i){this.addState(i);}}}});})();(function(){var f="interval",e="Number",d="_applyTimeoutInterval",c="qx.event.type.Event",b="qx.event.Idle",a="singleton";qx.Class.define(b,{extend:qx.core.Object,type:a,construct:function(){qx.core.Object.call(this);var g=new qx.event.Timer(this.getTimeoutInterval());g.addListener(f,this._onInterval,this);g.start();this.__kM=g;},events:{"interval":c},properties:{timeoutInterval:{check:e,init:100,apply:d}},members:{__kM:null,_applyTimeoutInterval:function(h){this.__kM.setInterval(h);},_onInterval:function(){this.fireEvent(f);}},destruct:function(){if(this.__kM){this.__kM.stop();}this.__kM=null;}});})();(function(){var o="top",n="right",m="bottom",l="left",k="align-start",j="qx.util.placement.AbstractAxis",i="edge-start",h="align-end",g="edge-end",f="-",c="best-fit",e="qx.util.placement.Placement",d="keep-align",b="direct",a='__hM';qx.Class.define(e,{extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__hM=new qx.util.placement.DirectAxis();},properties:{axisX:{check:j},axisY:{check:j},edge:{check:[o,n,m,l],init:o},align:{check:[o,n,m,l],init:n}},statics:{__hN:null,compute:function(p,q,r,s,t,u,v){this.__hN=this.__hN||new qx.util.placement.Placement();var y=t.split(f);var x=y[0];var w=y[1];this.__hN.set({axisX:this.__hR(u),axisY:this.__hR(v),edge:x,align:w});return this.__hN.compute(p,q,r,s);},__hO:null,__hP:null,__hQ:null,__hR:function(z){switch(z){case b:this.__hO=this.__hO||new qx.util.placement.DirectAxis();return this.__hO;case d:this.__hP=this.__hP||new qx.util.placement.KeepAlignAxis();return this.__hP;case c:this.__hQ=this.__hQ||new qx.util.placement.BestFitAxis();return this.__hQ;default:throw new Error("Invalid 'mode' argument!'");}}},members:{__hM:null,compute:function(A,B,C,D){{};var E=this.getAxisX()||this.__hM;var G=E.computeStart(A.width,{start:C.left,end:C.right},{start:D.left,end:D.right},B.width,this.__hS());var F=this.getAxisY()||this.__hM;var top=F.computeStart(A.height,{start:C.top,end:C.bottom},{start:D.top,end:D.bottom},B.height,this.__hT());return {left:G,top:top};},__hS:function(){var I=this.getEdge();var H=this.getAlign();if(I==l){return i;}else if(I==n){return g;}else if(H==l){return k;}else if(H==n){return h;}},__hT:function(){var K=this.getEdge();var J=this.getAlign();if(K==o){return i;}else if(K==m){return g;}else if(J==o){return k;}else if(J==m){return h;}}},destruct:function(){this._disposeObjects(a);}});})();(function(){var e="edge-start",d="align-start",c="align-end",b="edge-end",a="qx.util.placement.AbstractAxis";qx.Class.define(a,{extend:qx.core.Object,members:{computeStart:function(f,g,h,i,j){throw new Error("abstract method call!");},_moveToEdgeAndAlign:function(k,l,m,n){switch(n){case e:return l.start-m.end-k;case b:return l.end+m.start;case d:return l.start+m.start;case c:return l.end-m.end-k;}},_isInRange:function(o,p,q){return o>=0&&o+p<=q;}}});})();(function(){var a="qx.util.placement.DirectAxis";qx.Class.define(a,{extend:qx.util.placement.AbstractAxis,members:{computeStart:function(b,c,d,e,f){return this._moveToEdgeAndAlign(b,c,d,f);}}});})();(function(){var c="qx.util.placement.KeepAlignAxis",b="edge-start",a="edge-end";qx.Class.define(c,{extend:qx.util.placement.AbstractAxis,members:{computeStart:function(d,e,f,g,h){var i=this._moveToEdgeAndAlign(d,e,f,h);var j,k;if(this._isInRange(i,d,g)){return i;}if(h==b||h==a){j=e.start-f.end;k=e.end+f.start;}else{j=e.end-f.end;k=e.start+f.start;}if(j>g-k){i=j-d;}else{i=k;}return i;}}});})();(function(){var a="qx.util.placement.BestFitAxis";qx.Class.define(a,{extend:qx.util.placement.AbstractAxis,members:{computeStart:function(b,c,d,e,f){var g=this._moveToEdgeAndAlign(b,c,d,f);if(this._isInRange(g,b,e)){return g;}if(g<0){g=Math.min(0,e-b);}if(g+b>e){g=Math.max(0,e-b);}return g;}}});})();(function(){var b="qx.ui.form.IRadioItem",a="qx.event.type.Data";qx.Interface.define(b,{events:{"changeValue":a},members:{setValue:function(c){},getValue:function(){},setGroup:function(d){this.assertInstance(d,qx.ui.form.RadioGroup);},getGroup:function(){}}});})();(function(){var b="changeModel",a="qx.ui.form.MModelProperty";qx.Mixin.define(a,{properties:{model:{nullable:true,event:b,dereference:true}}});})();(function(){var b="qx.ui.form.IBooleanForm",a="qx.event.type.Data";qx.Interface.define(b,{events:{"changeValue":a},members:{setValue:function(c){return arguments.length==1;},resetValue:function(){},getValue:function(){}}});})();(function(){var b="qx.ui.form.IModel",a="qx.event.type.Data";qx.Interface.define(b,{events:{"changeModel":a},members:{setModel:function(c){},getModel:function(){},resetModel:function(){}}});})();(function(){var b="qx.event.type.Data",a="qx.ui.form.IForm";qx.Interface.define(a,{events:{"changeEnabled":b,"changeValid":b,"changeInvalidMessage":b,"changeRequired":b},members:{setEnabled:function(c){return arguments.length==1;},getEnabled:function(){},setRequired:function(d){return arguments.length==1;},getRequired:function(){},setValid:function(e){return arguments.length==1;},getValid:function(){},setInvalidMessage:function(f){return arguments.length==1;},getInvalidMessage:function(){},setRequiredInvalidMessage:function(g){return arguments.length==1;},getRequiredInvalidMessage:function(){}}});})();(function(){var b="qx.ui.form.IExecutable",a="qx.event.type.Data";qx.Interface.define(b,{events:{"execute":a},members:{setCommand:function(c){return arguments.length==1;},getCommand:function(){},execute:function(){}}});})();(function(){var n="execute",m="toolTipText",l="icon",k="label",j="qx.ui.core.MExecutable",h="value",g="qx.event.type.Event",f="_applyCommand",d="enabled",c="menu",a="changeCommand",b="qx.ui.core.Command";qx.Mixin.define(j,{events:{"execute":g},properties:{command:{check:b,apply:f,event:a,nullable:true}},members:{__kN:null,__kO:false,__kP:null,_bindableProperties:[d,k,l,m,h,c],execute:function(){var o=this.getCommand();if(o){if(this.__kO){this.__kO=false;}else{this.__kO=true;o.execute(this);}}this.fireEvent(n);},__kQ:function(e){if(this.__kO){this.__kO=false;return;}this.__kO=true;this.execute();},_applyCommand:function(p,q){if(q!=null){q.removeListenerById(this.__kP);}if(p!=null){this.__kP=p.addListener(n,this.__kQ,this);}var t=this.__kN;if(t==null){this.__kN=t={};}for(var i=0;i<this._bindableProperties.length;i++){var s=this._bindableProperties[i];if(q!=null&&t[s]!=null){q.removeBinding(t[s]);t[s]=null;}if(p!=null&&qx.Class.hasProperty(this.constructor,s)){var r=p.get(s);if(r==null){var u=this.get(s);}t[s]=p.bind(s,this,s);if(u){this.set(s,u);}}}}},destruct:function(){this.__kN=null;}});})();(function(){var j="label",i="icon",h="Boolean",g="both",f="String",e="left",d="changeGap",c="changeShow",b="bottom",a="_applyCenter",y="changeIcon",x="qx.ui.basic.Atom",w="changeLabel",v="Integer",u="_applyIconPosition",t="bottom-left",s="top-left",r="top",q="right",p="_applyRich",n="_applyIcon",o="_applyShow",l="_applyLabel",m="_applyGap",k="atom";qx.Class.define(x,{extend:qx.ui.core.Widget,construct:function(z,A){{};qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.layout.Atom());if(z!=null){this.setLabel(z);}if(A!=null){this.setIcon(A);}},properties:{appearance:{refine:true,init:k},label:{apply:l,nullable:true,check:f,event:w},rich:{check:h,init:false,apply:p},icon:{check:f,apply:n,nullable:true,themeable:true,event:y},gap:{check:v,nullable:false,event:d,apply:m,themeable:true,init:4},show:{init:g,check:[g,j,i],themeable:true,inheritable:true,apply:o,event:c},iconPosition:{init:e,check:[r,q,b,e,s,t],themeable:true,apply:u},center:{init:false,check:h,themeable:true,apply:a}},members:{_createChildControlImpl:function(B,C){var D;switch(B){case j:D=new qx.ui.basic.Label(this.getLabel());D.setAnonymous(true);D.setRich(this.getRich());this._add(D);if(this.getLabel()==null||this.getShow()===i){D.exclude();}break;case i:D=new qx.ui.basic.Image(this.getIcon());D.setAnonymous(true);this._addAt(D,0);if(this.getIcon()==null||this.getShow()===j){D.exclude();}break;}return D||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,B);},_forwardStates:{focused:true,hovered:true},_handleLabel:function(){if(this.getLabel()==null||this.getShow()===i){this._excludeChildControl(j);}else{this._showChildControl(j);}},_handleIcon:function(){if(this.getIcon()==null||this.getShow()===j){this._excludeChildControl(i);}else{this._showChildControl(i);}},_applyLabel:function(E,F){var G=this.getChildControl(j,true);if(G){G.setValue(E);}this._handleLabel();},_applyRich:function(H,I){var J=this.getChildControl(j,true);if(J){J.setRich(H);}},_applyIcon:function(K,L){var M=this.getChildControl(i,true);if(M){M.setSource(K);}this._handleIcon();},_applyGap:function(N,O){this._getLayout().setGap(N);},_applyShow:function(P,Q){this._handleLabel();this._handleIcon();},_applyIconPosition:function(R,S){this._getLayout().setIconPosition(R);},_applyCenter:function(T,U){this._getLayout().setCenter(T);}}});})();(function(){var o="pressed",n="abandoned",m="hovered",l="Enter",k="Space",j="dblclick",i="qx.ui.form.Button",h="mouseup",g="mousedown",f="mouseover",b="mouseout",d="keydown",c="button",a="keyup";qx.Class.define(i,{extend:qx.ui.basic.Atom,include:[qx.ui.core.MExecutable],implement:[qx.ui.form.IExecutable],construct:function(p,q,r){qx.ui.basic.Atom.call(this,p,q);if(r!=null){this.setCommand(r);}this.addListener(f,this._onMouseOver);this.addListener(b,this._onMouseOut);this.addListener(g,this._onMouseDown);this.addListener(h,this._onMouseUp);this.addListener(d,this._onKeyDown);this.addListener(a,this._onKeyUp);this.addListener(j,this._onStopEvent);},properties:{appearance:{refine:true,init:c},focusable:{refine:true,init:true}},members:{_forwardStates:{focused:true,hovered:true,pressed:true,disabled:true},press:function(){if(this.hasState(n)){return;}this.addState(o);},release:function(){if(this.hasState(o)){this.removeState(o);}},reset:function(){this.removeState(o);this.removeState(n);this.removeState(m);},_onMouseOver:function(e){if(!this.isEnabled()||e.getTarget()!==this){return;}if(this.hasState(n)){this.removeState(n);this.addState(o);}this.addState(m);},_onMouseOut:function(e){if(!this.isEnabled()||e.getTarget()!==this){return;}this.removeState(m);if(this.hasState(o)){this.removeState(o);this.addState(n);}},_onMouseDown:function(e){if(!e.isLeftPressed()){return;}e.stopPropagation();this.capture();this.removeState(n);this.addState(o);},_onMouseUp:function(e){this.releaseCapture();var s=this.hasState(o);var t=this.hasState(n);if(s){this.removeState(o);}if(t){this.removeState(n);}else{this.addState(m);if(s){this.execute();}}e.stopPropagation();},_onKeyDown:function(e){switch(e.getKeyIdentifier()){case l:case k:this.removeState(n);this.addState(o);e.stopPropagation();}},_onKeyUp:function(e){switch(e.getKeyIdentifier()){case l:case k:if(this.hasState(o)){this.removeState(n);this.removeState(o);this.execute();e.stopPropagation();}}}}});})();(function(){var m="qx.dynlocale",l="Boolean",k="changeLocale",j="changeInvalidMessage",i="on",h="String",g="invalid",f="",d="qx.ui.form.MForm",c="_applyValid",a="changeRequired",b="changeValid";qx.Mixin.define(d,{construct:function(){if(qx.core.Variant.isSet(m,i)){qx.locale.Manager.getInstance().addListener(k,this.__fn,this);}},properties:{valid:{check:l,init:true,apply:c,event:b},required:{check:l,init:false,event:a},invalidMessage:{check:h,init:f,event:j},requiredInvalidMessage:{check:h,nullable:true,event:j}},members:{_applyValid:function(n,o){n?this.removeState(g):this.addState(g);},__fn:qx.core.Variant.select(m,{"on":function(e){var p=this.getInvalidMessage();if(p&&p.translate){this.setInvalidMessage(p.translate());}var q=this.getRequiredInvalidMessage();if(q&&q.translate){this.setRequiredInvalidMessage(q.translate());}},"off":null})},destruct:function(){if(qx.core.Variant.isSet(m,i)){qx.locale.Manager.getInstance().removeListener(k,this.__fn,this);}}});})();(function(){var o="checked",n="keypress",m="Boolean",l="Right",k="_applyValue",j="changeValue",i="qx.ui.form.RadioButton",h="radiobutton",g="Left",f="qx.ui.form.RadioGroup",b="Down",d="_applyGroup",c="Up",a="execute";qx.Class.define(i,{extend:qx.ui.form.Button,include:[qx.ui.form.MForm,qx.ui.form.MModelProperty],implement:[qx.ui.form.IRadioItem,qx.ui.form.IForm,qx.ui.form.IBooleanForm,qx.ui.form.IModel],construct:function(p){{};qx.ui.form.Button.call(this,p);this.addListener(a,this._onExecute);this.addListener(n,this._onKeyPress);},properties:{group:{check:f,nullable:true,apply:d},value:{check:m,nullable:true,event:j,apply:k,init:false},appearance:{refine:true,init:h},allowGrowX:{refine:true,init:false}},members:{_applyValue:function(q,r){q?this.addState(o):this.removeState(o);if(q&&this.getFocusable()){this.focus();}},_applyGroup:function(s,t){if(t){t.remove(this);}if(s){s.add(this);}},_onExecute:function(e){this.setValue(true);},_onKeyPress:function(e){var u=this.getGroup();if(!u){return;}switch(e.getKeyIdentifier()){case g:case c:u.selectPrevious();break;case l:case b:u.selectNext();break;}}}});})();(function(){var o="close-button",n="middle",m="left",l="icon",k="label",j="right",i="click",h="Boolean",g="bottom",f="qx.ui.tabview.TabButton",c="center",e="_applyShowCloseButton",d="top",b="close",a="qx.event.type.Data";qx.Class.define(f,{extend:qx.ui.form.RadioButton,implement:qx.ui.form.IRadioItem,construct:function(){qx.ui.form.RadioButton.call(this);var p=new qx.ui.layout.Grid(2,0);p.setRowAlign(0,m,n);p.setColumnAlign(0,j,n);this._getLayout().dispose();this._setLayout(p);this.initShowCloseButton();},events:{"close":a},properties:{showCloseButton:{check:h,init:false,apply:e}},members:{_forwardStates:{focused:true,checked:true},_applyIconPosition:function(q,r){var s={icon:this.getChildControl(l),label:this.getChildControl(k),closeButton:this.getShowCloseButton()?this.getChildControl(o):null};for(var t in s){if(s[t]){this._remove(s[t]);}}switch(q){case d:this._add(s.label,{row:3,column:2});this._add(s.icon,{row:1,column:2});if(s.closeButton){this._add(s.closeButton,{row:0,column:4});}break;case g:this._add(s.label,{row:1,column:2});this._add(s.icon,{row:3,column:2});if(s.closeButton){this._add(s.closeButton,{row:0,column:4});}break;case m:this._add(s.label,{row:0,column:2});this._add(s.icon,{row:0,column:0});if(s.closeButton){this._add(s.closeButton,{row:0,column:4});}break;case j:this._add(s.label,{row:0,column:0});this._add(s.icon,{row:0,column:2});if(s.closeButton){this._add(s.closeButton,{row:0,column:4});}break;}},_createChildControlImpl:function(u,v){var w;switch(u){case k:var w=new qx.ui.basic.Label(this.getLabel());w.setAnonymous(true);this._add(w,{row:0,column:2});this._getLayout().setColumnFlex(2,1);break;case l:w=new qx.ui.basic.Image(this.getIcon());w.setAnonymous(true);this._add(w,{row:0,column:0});break;case o:w=new qx.ui.form.Button();w.addListener(i,this._onCloseButtonClick,this);this._add(w,{row:0,column:4});if(!this.getShowCloseButton()){w.exclude();}break;}return w||qx.ui.form.RadioButton.prototype._createChildControlImpl.call(this,u);},_onCloseButtonClick:function(){this.fireDataEvent(b,this);},_applyShowCloseButton:function(x,y){if(x){this._showChildControl(o);}else{this._excludeChildControl(o);}},_applyCenter:function(z){var A=this._getLayout();if(z){A.setColumnAlign(2,c,n);}else{A.setColumnAlign(2,m,n);}}}});})();(function(){var e="change",d="__mp",c="qx.event.type.Data",b="qx.ui.form.MModelSelection",a="changeSelection";qx.Mixin.define(b,{construct:function(){this.__mp=new qx.data.Array();this.__mp.addListener(e,this.__ms,this);this.addListener(a,this.__mr,this);},events:{changeModelSelection:c},members:{__mp:null,__mq:false,__mr:function(){if(this.__mq){return;}var h=this.getSelection();var f=[];for(var i=0;i<h.length;i++){var k=h[i];var g=k.getModel?k.getModel():null;if(g!==null){f.push(g);}}if(f.length===h.length){this.setModelSelection(f);}},__ms:function(){this.__mq=true;var m=this.getSelectables(true);var o=[];var n=this.__mp.toArray();for(var i=0;i<n.length;i++){var q=n[i];for(var j=0;j<m.length;j++){var r=m[j];var l=r.getModel?r.getModel():null;if(q===l){o.push(r);break;}}}this.setSelection(o);this.__mq=false;var p=this.getSelection();if(!qx.lang.Array.equals(p,o)){this.__mr();}},getModelSelection:function(){return this.__mp;},setModelSelection:function(s){if(!s){this.__mp.removeAll();return;}{};s.unshift(this.__mp.getLength());s.unshift(0);var t=this.__mp.splice.apply(this.__mp,s);t.dispose();}},destruct:function(){this._disposeObjects(d);}});})();(function(){var a="qx.ui.form.IModelSelection";qx.Interface.define(a,{members:{setModelSelection:function(b){},getModelSelection:function(){}}});})();(function(){var b="qx.ui.core.ISingleSelection",a="qx.event.type.Data";qx.Interface.define(b,{events:{"changeSelection":a},members:{getSelection:function(){return true;},setSelection:function(c){return arguments.length==1;},resetSelection:function(){return true;},isSelected:function(d){return arguments.length==1;},isSelectionEmpty:function(){return true;},getSelectables:function(e){return arguments.length==1;}}});})();(function(){var f="qx.ui.core.MSingleSelectionHandling",d="__my",c="changeSelection",b="changeSelected",a="qx.event.type.Data";qx.Mixin.define(f,{events:{"changeSelection":a},members:{__my:null,getSelection:function(){var g=this.__mz().getSelected();if(g){return [g];}else{return [];}},setSelection:function(h){switch(h.length){case 0:this.resetSelection();break;case 1:this.__mz().setSelected(h[0]);break;default:throw new Error("Could only select one item, but the selection "+" array contains "+h.length+" items!");}},resetSelection:function(){this.__mz().resetSelected();},isSelected:function(i){return this.__mz().isSelected(i);},isSelectionEmpty:function(){return this.__mz().isSelectionEmpty();},getSelectables:function(j){return this.__mz().getSelectables(j);},_onChangeSelected:function(e){var l=e.getData();var k=e.getOldData();l==null?l=[]:l=[l];k==null?k=[]:k=[k];this.fireDataEvent(c,l,k);},__mz:function(){if(this.__my==null){var m=this;this.__my=new qx.ui.core.SingleSelectionManager({getItems:function(){return m._getItems();},isItemSelectable:function(n){if(m._isItemSelectable){return m._isItemSelectable(n);}else{return n.isVisible();}}});this.__my.addListener(b,this._onChangeSelected,this);}this.__my.setAllowEmptySelection(this._isAllowEmptySelection());return this.__my;}},destruct:function(){this._disposeObjects(d);}});})();(function(){var r="Boolean",q="changeInvalidMessage",p="changeValue",o="String",n="_applyAllowEmptySelection",m="_applyInvalidMessage",k="qx.ui.form.RadioGroup",j="_applyValid",h="",g="changeRequired",c="changeValid",f="changeEnabled",d="__a",b="changeSelection",a="_applyEnabled";qx.Class.define(k,{extend:qx.core.Object,implement:[qx.ui.core.ISingleSelection,qx.ui.form.IForm,qx.ui.form.IModelSelection],include:[qx.ui.core.MSingleSelectionHandling,qx.ui.form.MModelSelection],construct:function(s){qx.core.Object.call(this);this.__a=[];this.addListener(b,this.__b,this);if(s!=null){this.add.apply(this,arguments);}},properties:{enabled:{check:r,apply:a,event:f,init:true},wrap:{check:r,init:true},allowEmptySelection:{check:r,init:false,apply:n},valid:{check:r,init:true,apply:j,event:c},required:{check:r,init:false,event:g},invalidMessage:{check:o,init:h,event:q,apply:m},requiredInvalidMessage:{check:o,nullable:true,event:q}},members:{__a:null,getItems:function(){return this.__a;},add:function(t){var u=this.__a;var v;for(var i=0,l=arguments.length;i<l;i++){v=arguments[i];if(qx.lang.Array.contains(u,v)){continue;}v.addListener(p,this._onItemChangeChecked,this);u.push(v);v.setGroup(this);if(v.getValue()){this.setSelection([v]);}}if(!this.isAllowEmptySelection()&&u.length>0&&!this.getSelection()[0]){this.setSelection([u[0]]);}},remove:function(w){var x=this.__a;if(qx.lang.Array.contains(x,w)){qx.lang.Array.remove(x,w);if(w.getGroup()===this){w.resetGroup();}w.removeListener(p,this._onItemChangeChecked,this);if(w.getValue()){this.resetSelection();}}},getChildren:function(){return this.__a;},_onItemChangeChecked:function(e){var y=e.getTarget();if(y.getValue()){this.setSelection([y]);}else if(this.getSelection()[0]==y){this.resetSelection();}},_applyInvalidMessage:function(z,A){for(var i=0;i<this.__a.length;i++){this.__a[i].setInvalidMessage(z);}},_applyValid:function(B,C){for(var i=0;i<this.__a.length;i++){this.__a[i].setValid(B);}},_applyEnabled:function(D,E){var F=this.__a;if(D==null){for(var i=0,l=F.length;i<l;i++){F[i].resetEnabled();}}else{for(var i=0,l=F.length;i<l;i++){F[i].setEnabled(D);}}},_applyAllowEmptySelection:function(G,H){if(!G&&this.isSelectionEmpty()){this.resetSelection();}},selectNext:function(){var I=this.getSelection()[0];var K=this.__a;var J=K.indexOf(I);if(J==-1){return;}var i=0;var length=K.length;if(this.getWrap()){J=(J+1)%length;}else{J=Math.min(J+1,length-1);}while(i<length&&!K[J].getEnabled()){J=(J+1)%length;i++;}this.setSelection([K[J]]);},selectPrevious:function(){var L=this.getSelection()[0];var N=this.__a;var M=N.indexOf(L);if(M==-1){return;}var i=0;var length=N.length;if(this.getWrap()){M=(M-1+length)%length;}else{M=Math.max(M-1,0);}while(i<length&&!N[M].getEnabled()){M=(M-1+length)%length;i++;}this.setSelection([N[M]]);},_getItems:function(){return this.getItems();},_isAllowEmptySelection:function(){return this.isAllowEmptySelection();},__b:function(e){var P=e.getData()[0];var O=e.getOldData()[0];if(O){O.setValue(false);}if(P){P.setValue(true);}}},destruct:function(){this._disposeArray(d);}});})();(function(){var h="[",g="]",f=".",d="idBubble",c="changeBubble",b="qx.data.marshal.MEventBubbling",a="qx.event.type.Data";qx.Mixin.define(b,{events:{"changeBubble":a},members:{_applyEventPropagation:function(i,j,name){this.fireDataEvent(c,{value:i,name:name,old:j});this._registerEventChaining(i,j,name);},_registerEventChaining:function(k,l,name){if((k instanceof qx.core.Object)&&qx.Class.hasMixin(k.constructor,qx.data.marshal.MEventBubbling)){var m=qx.lang.Function.bind(this.__mA,this,name);var n=k.addListener(c,m,this);k.setUserData(d,n);}if(l!=null&&l.getUserData&&l.getUserData(d)!=null){l.removeListenerById(l.getUserData(d));}},__mA:function(name,e){var v=e.getData();var r=v.value;var p=v.old;if(qx.Class.hasInterface(e.getTarget().constructor,qx.data.IListData)){if(v.name.indexOf){var u=v.name.indexOf(f)!=-1?v.name.indexOf(f):v.name.length;var s=v.name.indexOf(h)!=-1?v.name.indexOf(h):v.name.length;if(u<s){var o=v.name.substring(0,u);var t=v.name.substring(u+1,v.name.length);if(t[0]!=h){t=f+t;}var q=name+h+o+g+t;}else if(s<u){var o=v.name.substring(0,s);var t=v.name.substring(s,v.name.length);var q=name+h+o+g+t;}else{var q=name+h+v.name+g;}}else{var q=name+h+v.name+g;}}else{var q=name+f+v.name;}this.fireDataEvent(c,{value:r,name:q,old:p});}}});})();(function(){var l="change",k="add",j="remove",h="order",g="qx.event.type.Data",f="",e="qx.data.Array",d="?",c="changeBubble",b="number",a="changeLength";qx.Class.define(e,{extend:qx.core.Object,include:qx.data.marshal.MEventBubbling,implement:[qx.data.IListData],construct:function(m){qx.core.Object.call(this);if(m==undefined){this.__mm=[];}else if(arguments.length>1){this.__mm=[];for(var i=0;i<arguments.length;i++){this.__mm.push(arguments[i]);}}else if(typeof m==b){this.__mm=new Array(m);}else if(m instanceof Array){this.__mm=qx.lang.Array.clone(m);}else{this.__mm=[];throw new Error("Type of the parameter not supported!");}for(var i=0;i<this.__mm.length;i++){this._applyEventPropagation(this.__mm[i],null,i);}this.__mn();},events:{"change":g,"changeLength":g},members:{__mm:null,concat:function(n){if(n){var o=this.__mm.concat(n);}else{var o=this.__mm.concat();}return new qx.data.Array(o);},join:function(p){return this.__mm.join(p);},pop:function(){var q=this.__mm.pop();this.__mn();this._applyEventPropagation(null,q,this.length-1);this.fireDataEvent(l,{start:this.length-1,end:this.length-1,type:j,items:[q]},null);return q;},push:function(r){for(var i=0;i<arguments.length;i++){this.__mm.push(arguments[i]);this.__mn();this._applyEventPropagation(arguments[i],null,this.length-1);this.fireDataEvent(l,{start:this.length-1,end:this.length-1,type:k,items:[arguments[i]]},null);}return this.length;},reverse:function(){this.__mm.reverse();this.fireDataEvent(l,{start:0,end:this.length-1,type:h,items:null},null);},shift:function(){var s=this.__mm.shift();this.__mn();this._applyEventPropagation(null,s,this.length-1);this.fireDataEvent(l,{start:0,end:this.length-1,type:j,items:[s]},null);return s;},slice:function(t,u){return new qx.data.Array(this.__mm.slice(t,u));},splice:function(v,w,x){var D=this.__mm.length;var A=this.__mm.splice.apply(this.__mm,arguments);if(this.__mm.length!=D){this.__mn();}var B=w>0;var y=arguments.length>2;var z=null;if(B||y){if(this.__mm.length>D){var C=k;}else if(this.__mm.length<D){var C=j;z=A;}else{var C=h;}this.fireDataEvent(l,{start:v,end:this.length-1,type:C,items:z},null);}for(var i=2;i<arguments.length;i++){this._registerEventChaining(arguments[i],null,v+i);}this.fireDataEvent(c,{value:this,name:d,old:A});for(var i=0;i<A.length;i++){this._applyEventPropagation(null,A[i],i);}return (new qx.data.Array(A));},sort:function(E){this.__mm.sort.apply(this.__mm,arguments);this.fireDataEvent(l,{start:0,end:this.length-1,type:h,items:null},null);},unshift:function(F){for(var i=arguments.length-1;i>=0;i--){this.__mm.unshift(arguments[i]);this.__mn();this._applyEventPropagation(arguments[i],null,0);this.fireDataEvent(l,{start:0,end:this.length-1,type:k,items:[arguments[i]]},null);}return this.length;},toArray:function(){return this.__mm;},getItem:function(G){return this.__mm[G];},setItem:function(H,I){var J=this.__mm[H];if(J===I){return;}this.__mm[H]=I;this._applyEventPropagation(I,J,H);if(this.length!=this.__mm.length){this.__mn();}this.fireDataEvent(l,{start:H,end:H,type:k,items:[I]},null);},getLength:function(){return this.length;},indexOf:function(K){return this.__mm.indexOf(K);},toString:function(){if(this.__mm!=null){return this.__mm.toString();}return f;},contains:function(L){return this.__mm.indexOf(L)!==-1;},copy:function(){return this.concat();},insertAt:function(M,N){this.splice(M,0,N);},insertBefore:function(O,P){var Q=this.indexOf(O);if(Q==-1){this.push(P);}else{this.splice(Q,0,P);}},insertAfter:function(R,S){var T=this.indexOf(R);if(T==-1||T==(this.length-1)){this.push(S);}else{this.splice(T+1,0,S);}},removeAt:function(U){return this.splice(U,1).getItem(0);},removeAll:function(){for(var i=0;i<this.__mm.length;i++){this._applyEventPropagation(null,this.__mm[i],i);}var W=this.getLength();var V=this.__mm.concat();this.__mm.length=0;this.__mn();this.fireDataEvent(l,{start:0,end:W-1,type:j,items:V},null);},append:function(X){if(X instanceof qx.data.Array){X=X.toArray();}{};for(var i=0;i<X.length;i++){this._applyEventPropagation(X[i],null,this.__mm.length+i);}Array.prototype.push.apply(this.__mm,X);var Y=this.length;this.__mn();this.fireDataEvent(l,{start:Y,end:this.length-1,type:k,items:X},null);},remove:function(ba){var bb=this.indexOf(ba);if(bb!=-1){this.splice(bb,1);return ba;}},equals:function(bc){if(this.length!==bc.length){return false;}for(var i=0;i<this.length;i++){if(this.getItem(i)!==bc.getItem(i)){return false;}}return true;},sum:function(){var bd=0;for(var i=0;i<this.length;i++){bd+=this.getItem(i);}return bd;},max:function(){var be=this.getItem(0);for(var i=1;i<this.length;i++){if(this.getItem(i)>be){be=this.getItem(i);}}return be===undefined?null:be;},min:function(){var bf=this.getItem(0);for(var i=1;i<this.length;i++){if(this.getItem(i)<bf){bf=this.getItem(i);}}return bf===undefined?null:bf;},forEach:function(bg,bh){for(var i=0;i<this.__mm.length;i++){bg.call(bh,this.__mm[i]);}},__mn:function(){var bi=this.length;this.length=this.__mm.length;this.fireDataEvent(a,this.length,bi);}},destruct:function(){for(var i=0;i<this.__mm.length;i++){this._applyEventPropagation(null,this.__mm[i],i);}this.__mm=null;}});})();(function(){var g="Boolean",f="qx.ui.core.SingleSelectionManager",e="__mv",d="__mt",c="__mu",b="changeSelected",a="qx.event.type.Data";qx.Class.define(f,{extend:qx.core.Object,construct:function(h){qx.core.Object.call(this);{};this.__mt=h;},events:{"changeSelected":a},properties:{allowEmptySelection:{check:g,init:true,apply:e}},members:{__mu:null,__mt:null,getSelected:function(){return this.__mu;},setSelected:function(j){if(!this.__mx(j)){throw new Error("Could not select "+j+", because it is not a child element!");}this.__mw(j);},resetSelected:function(){this.__mw(null);},isSelected:function(k){if(!this.__mx(k)){throw new Error("Could not check if "+k+" is selected,"+" because it is not a child element!");}return this.__mu===k;},isSelectionEmpty:function(){return this.__mu==null;},getSelectables:function(l){var m=this.__mt.getItems();var n=[];for(var i=0;i<m.length;i++){if(this.__mt.isItemSelectable(m[i])){n.push(m[i]);}}if(!l){for(var i=n.length-1;i>=0;i--){if(!n[i].getEnabled()){n.splice(i,1);}}}return n;},__mv:function(o,p){if(!o){this.__mw(this.__mu);}},__mw:function(q){var t=this.__mu;var s=q;if(s!=null&&t===s){return;}if(!this.isAllowEmptySelection()&&s==null){var r=this.getSelectables(true)[0];if(r){s=r;}}this.__mu=s;this.fireDataEvent(b,s,t);},__mx:function(u){var v=this.__mt.getItems();for(var i=0;i<v.length;i++){if(v[i]===u){return true;}}return false;}},destruct:function(){if(this.__mt.toHashCode){this._disposeObjects(d);}else{this.__mt=null;}this._disposeObjects(c);}});})();(function(){var b="abstract",a="qx.ui.layout.Abstract";qx.Class.define(a,{type:b,extend:qx.core.Object,members:{__gz:null,_invalidChildrenCache:null,__gA:null,invalidateLayoutCache:function(){this.__gz=null;},renderLayout:function(c,d){this.warn("Missing renderLayout() implementation!");},getSizeHint:function(){if(this.__gz){return this.__gz;}return this.__gz=this._computeSizeHint();},hasHeightForWidth:function(){return false;},getHeightForWidth:function(e){this.warn("Missing getHeightForWidth() implementation!");return null;},_computeSizeHint:function(){return null;},invalidateChildrenCache:function(){this._invalidChildrenCache=true;},verifyLayoutProperty:null,_clearSeparators:function(){var f=this.__gA;if(f instanceof qx.ui.core.LayoutItem){f.clearSeparators();}},_renderSeparator:function(g,h){this.__gA.renderSeparator(g,h);},connectToWidget:function(i){if(i&&this.__gA){throw new Error("It is not possible to manually set the connected widget.");}this.__gA=i;this.invalidateChildrenCache();},_getWidget:function(){return this.__gA;},_applyLayoutChange:function(){if(this.__gA){this.__gA.scheduleLayoutUpdate();}},_getLayoutChildren:function(){return this.__gA.getLayoutChildren();}},destruct:function(){this.__gA=this.__gz=null;}});})();(function(){var m="bottom",l="top",k="_applyLayoutChange",j="top-left",h="bottom-left",g="left",f="right",e="middle",d="center",c="qx.ui.layout.Atom",a="Integer",b="Boolean";qx.Class.define(c,{extend:qx.ui.layout.Abstract,properties:{gap:{check:a,init:4,apply:k},iconPosition:{check:[g,l,f,m,j,h],init:g,apply:k},center:{check:b,init:false,apply:k}},members:{verifyLayoutProperty:null,renderLayout:function(n,o){var x=qx.ui.layout.Util;var q=this.getIconPosition();var t=this._getLayoutChildren();var length=t.length;var I,top,y,r;var D,w;var B=this.getGap();var G=this.getCenter();if(q===m||q===f){var z=length-1;var u=-1;var s=-1;}else{var z=0;var u=length;var s=1;}if(q==l||q==m){if(G){var C=0;for(var i=z;i!=u;i+=s){r=t[i].getSizeHint().height;if(r>0){C+=r;if(i!=z){C+=B;}}}top=Math.round((o-C)/2);}else{top=0;}for(var i=z;i!=u;i+=s){D=t[i];w=D.getSizeHint();y=Math.min(w.maxWidth,Math.max(n,w.minWidth));r=w.height;I=x.computeHorizontalAlignOffset(d,y,n);D.renderLayout(I,top,y,r);if(r>0){top+=r+B;}}}else{var v=n;var p=null;var F=0;for(var i=z;i!=u;i+=s){D=t[i];y=D.getSizeHint().width;if(y>0){if(!p&&D instanceof qx.ui.basic.Label){p=D;}else{v-=y;}F++;}}if(F>1){var E=(F-1)*B;v-=E;}if(p){var w=p.getSizeHint();var A=Math.max(w.minWidth,Math.min(v,w.maxWidth));v-=A;}if(G&&v>0){I=Math.round(v/2);}else{I=0;}for(var i=z;i!=u;i+=s){D=t[i];w=D.getSizeHint();r=Math.min(w.maxHeight,Math.max(o,w.minHeight));if(D===p){y=A;}else{y=w.width;}var H=e;if(q==j){H=l;}else if(q==h){H=m;}top=x.computeVerticalAlignOffset(H,w.height,o);D.renderLayout(I,top,y,r);if(y>0){I+=y+B;}}}},_computeSizeHint:function(){var T=this._getLayoutChildren();var length=T.length;var L,R;if(length===1){var L=T[0].getSizeHint();R={width:L.width,height:L.height,minWidth:L.minWidth,minHeight:L.minHeight};}else{var P=0,Q=0;var M=0,O=0;var N=this.getIconPosition();var S=this.getGap();if(N===l||N===m){var J=0;for(var i=0;i<length;i++){L=T[i].getSizeHint();Q=Math.max(Q,L.width);P=Math.max(P,L.minWidth);if(L.height>0){O+=L.height;M+=L.minHeight;J++;}}if(J>1){var K=(J-1)*S;O+=K;M+=K;}}else{var J=0;for(var i=0;i<length;i++){L=T[i].getSizeHint();O=Math.max(O,L.height);M=Math.max(M,L.minHeight);if(L.width>0){Q+=L.width;P+=L.minWidth;J++;}}if(J>1){var K=(J-1)*S;Q+=K;P+=K;}}R={minWidth:P,width:Q,minHeight:M,height:O};}return R;}}});})();(function(){var g="middle",f="qx.ui.layout.Util",e="left",d="center",c="top",b="bottom",a="right";qx.Class.define(f,{statics:{PERCENT_VALUE:/[0-9]+(?:\.[0-9]+)?%/,computeFlexOffsets:function(h,j,k){var n,r,m,s;var o=j>k;var t=Math.abs(j-k);var u,p;var q={};for(r in h){n=h[r];q[r]={potential:o?n.max-n.value:n.value-n.min,flex:o?n.flex:1/n.flex,offset:0};}while(t!=0){s=Infinity;m=0;for(r in q){n=q[r];if(n.potential>0){m+=n.flex;s=Math.min(s,n.potential/n.flex);}}if(m==0){break;}s=Math.min(t,s*m)/m;u=0;for(r in q){n=q[r];if(n.potential>0){p=Math.min(t,n.potential,Math.ceil(s*n.flex));u+=p-s*n.flex;if(u>=1){u-=1;p-=1;}n.potential-=p;if(o){n.offset+=p;}else{n.offset-=p;}t-=p;}}}return q;},computeHorizontalAlignOffset:function(v,w,x,y,z){if(y==null){y=0;}if(z==null){z=0;}var A=0;switch(v){case e:A=y;break;case a:A=x-w-z;break;case d:A=Math.round((x-w)/2);if(A<y){A=y;}else if(A<z){A=Math.max(y,x-w-z);}break;}return A;},computeVerticalAlignOffset:function(B,C,D,E,F){if(E==null){E=0;}if(F==null){F=0;}var G=0;switch(B){case c:G=E;break;case b:G=D-C-F;break;case g:G=Math.round((D-C)/2);if(G<E){G=E;}else if(G<F){G=Math.max(E,D-C-F);}break;}return G;},collapseMargins:function(H){var I=0,K=0;for(var i=0,l=arguments.length;i<l;i++){var J=arguments[i];if(J<0){K=Math.min(K,J);}else if(J>0){I=Math.max(I,J);}}return I+K;},computeHorizontalGaps:function(L,M,N){if(M==null){M=0;}var O=0;if(N){O+=L[0].getMarginLeft();for(var i=1,l=L.length;i<l;i+=1){O+=this.collapseMargins(M,L[i-1].getMarginRight(),L[i].getMarginLeft());}O+=L[l-1].getMarginRight();}else{for(var i=1,l=L.length;i<l;i+=1){O+=L[i].getMarginLeft()+L[i].getMarginRight();}O+=(M*(l-1));}return O;},computeVerticalGaps:function(P,Q,R){if(Q==null){Q=0;}var S=0;if(R){S+=P[0].getMarginTop();for(var i=1,l=P.length;i<l;i+=1){S+=this.collapseMargins(Q,P[i-1].getMarginBottom(),P[i].getMarginTop());}S+=P[l-1].getMarginBottom();}else{for(var i=1,l=P.length;i<l;i+=1){S+=P[i].getMarginTop()+P[i].getMarginBottom();}S+=(Q*(l-1));}return S;},computeHorizontalSeparatorGaps:function(T,U,V){var Y=qx.theme.manager.Decoration.getInstance().resolve(V);var X=Y.getInsets();var W=X.left+X.right;var ba=0;for(var i=0,l=T.length;i<l;i++){var bb=T[i];ba+=bb.getMarginLeft()+bb.getMarginRight();}ba+=(U+W+U)*(l-1);return ba;},computeVerticalSeparatorGaps:function(bc,bd,be){var bh=qx.theme.manager.Decoration.getInstance().resolve(be);var bg=bh.getInsets();var bf=bg.top+bg.bottom;var bi=0;for(var i=0,l=bc.length;i<l;i++){var bj=bc[i];bi+=bj.getMarginTop()+bj.getMarginBottom();}bi+=(bd+bf+bd)*(l-1);return bi;},arrangeIdeals:function(bk,bl,bm,bn,bo,bp){if(bl<bk||bo<bn){if(bl<bk&&bo<bn){bl=bk;bo=bn;}else if(bl<bk){bo-=(bk-bl);bl=bk;if(bo<bn){bo=bn;}}else if(bo<bn){bl-=(bn-bo);bo=bn;if(bl<bk){bl=bk;}}}if(bl>bm||bo>bp){if(bl>bm&&bo>bp){bl=bm;bo=bp;}else if(bl>bm){bo+=(bl-bm);bl=bm;if(bo>bp){bo=bp;}}else if(bo>bp){bl+=(bo-bp);bo=bp;if(bl>bm){bl=bm;}}}return {begin:bl,end:bo};}}});})();(function(){var b="qx.event.type.Data",a="qx.ui.form.IStringForm";qx.Interface.define(a,{events:{"changeValue":b},members:{setValue:function(c){return arguments.length==1;},resetValue:function(){},getValue:function(){}}});})();(function(){var k="qx.dynlocale",j="Boolean",i="color",h="changeLocale",g="enabled",f="on",d="_applyTextAlign",c="qx.ui.core.Widget",b="nowrap",a="changeTextAlign",C="_applyWrap",B="A",A="changeContent",z="qx.ui.basic.Label",y="whiteSpace",x="_applyValue",w="center",v="_applyBuddy",u="String",t="textAlign",r="right",s="changeRich",p="normal",q="_applyRich",n="click",o="label",l="left",m="changeValue";qx.Class.define(z,{extend:qx.ui.core.Widget,implement:[qx.ui.form.IStringForm],construct:function(D){qx.ui.core.Widget.call(this);if(D!=null){this.setValue(D);}if(qx.core.Variant.isSet(k,f)){qx.locale.Manager.getInstance().addListener(h,this._onChangeLocale,this);}},properties:{rich:{check:j,init:false,event:s,apply:q},wrap:{check:j,init:true,apply:C},value:{check:u,apply:x,event:m,nullable:true},buddy:{check:c,apply:v,nullable:true,init:null,dereference:true},textAlign:{check:[l,w,r],nullable:true,themeable:true,apply:d,event:a},appearance:{refine:true,init:o},selectable:{refine:true,init:false},allowGrowX:{refine:true,init:false},allowGrowY:{refine:true,init:false},allowShrinkY:{refine:true,init:false}},members:{__gI:null,__gJ:null,__gK:null,__gL:null,_getContentHint:function(){if(this.__gJ){this.__gM=this.__gN();delete this.__gJ;}return {width:this.__gM.width,height:this.__gM.height};},_hasHeightForWidth:function(){return this.getRich()&&this.getWrap();},_applySelectable:function(E){if(!qx.bom.client.Feature.CSS_TEXT_OVERFLOW&&qx.bom.client.Feature.XUL){if(E&&!this.isRich()){{};return;}}qx.ui.core.Widget.prototype._applySelectable.call(this,E);},_getContentHeightForWidth:function(F){if(!this.getRich()&&!this.getWrap()){return null;}return this.__gN(F).height;},_createContentElement:function(){return new qx.html.Label;},_applyTextAlign:function(G,H){this.getContentElement().setStyle(t,G);},_applyTextColor:function(I,J){if(I){this.getContentElement().setStyle(i,qx.theme.manager.Color.getInstance().resolve(I));}else{this.getContentElement().removeStyle(i);}},__gM:{width:0,height:0},_applyFont:function(K,L){var M;if(K){this.__gI=qx.theme.manager.Font.getInstance().resolve(K);M=this.__gI.getStyles();}else{this.__gI=null;M=qx.bom.Font.getDefaultStyles();}this.getContentElement().setStyles(M);this.__gJ=true;qx.ui.core.queue.Layout.add(this);},__gN:function(N){var R=qx.bom.Label;var P=this.getFont();var O=P?this.__gI.getStyles():qx.bom.Font.getDefaultStyles();var content=this.getValue()||B;var Q=this.getRich();return Q?R.getHtmlSize(content,O,N):R.getTextSize(content,O);},_applyBuddy:function(S,T){if(T!=null){T.removeBinding(this.__gK);this.__gK=null;this.removeListenerById(this.__gL);this.__gL=null;}if(S!=null){this.__gK=S.bind(g,this,g);this.__gL=this.addListener(n,function(){if(S.isFocusable()){S.focus.apply(S);}},this);}},_applyRich:function(U){this.getContentElement().setRich(U);this.__gJ=true;qx.ui.core.queue.Layout.add(this);},_applyWrap:function(V,W){if(V&&!this.isRich()){{};}if(this.isRich()){var X=V?p:b;this.getContentElement().setStyle(y,X);}},_onChangeLocale:qx.core.Variant.select(k,{"on":function(e){var content=this.getValue();if(content&&content.translate){this.setValue(content.translate());}},"off":null}),_applyValue:function(Y,ba){this.getContentElement().setValue(Y);this.__gJ=true;qx.ui.core.queue.Layout.add(this);this.fireDataEvent(A,Y,ba);}},destruct:function(){if(qx.core.Variant.isSet(k,f)){qx.locale.Manager.getInstance().removeListener(h,this._onChangeLocale,this);}if(this.__gK!=null){var bb=this.getBuddy();if(bb!=null&&!bb.isDisposed()){bb.removeBinding(this.__gK);}}this.__gI=this.__gK=null;}});})();(function(){var b="value",a="qx.html.Label";qx.Class.define(a,{extend:qx.html.Element,members:{__dP:null,_applyProperty:function(name,c){qx.html.Element.prototype._applyProperty.call(this,name,c);if(name==b){var d=this.getDomElement();qx.bom.Label.setValue(d,c);}},_createDomElement:function(){var f=this.__dP;var e=qx.bom.Label.create(this._content,f);return e;},_copyData:function(g){return qx.html.Element.prototype._copyData.call(this,true);},setRich:function(h){var i=this.getDomElement();if(i){throw new Error("The label mode cannot be modified after initial creation");}h=!!h;if(this.__dP==h){return;}this.__dP=h;return this;},setValue:function(j){this._setProperty(b,j);return this;},getValue:function(){return this._getProperty(b);}}});})();(function(){var j="div",i="inherit",h="text",g="qx.client",f="value",e="",d="hidden",c="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",b="nowrap",a="auto",z="0",y="ellipsis",x="normal",w="label",v="px",u="crop",t="gecko",s="end",r="100%",q="visible",o="qx.bom.Label",p="opera",m="mshtml",n="block",k="-1000px",l="absolute";qx.Class.define(o,{statics:{__jn:{fontFamily:1,fontSize:1,fontWeight:1,fontStyle:1,lineHeight:1},__jo:function(){var A=this.__jq(false);document.body.insertBefore(A,document.body.firstChild);return this._textElement=A;},__jp:function(){var B=this.__jq(true);document.body.insertBefore(B,document.body.firstChild);return this._htmlElement=B;},__jq:function(C){var D=qx.bom.Element.create(j);var E=D.style;E.width=E.height=a;E.left=E.top=k;E.visibility=d;E.position=l;E.overflow=q;if(C){E.whiteSpace=x;}else{E.whiteSpace=b;if(!qx.bom.client.Feature.CSS_TEXT_OVERFLOW&&qx.bom.client.Feature.XUL){var F=document.createElementNS(c,w);var E=F.style;E.padding=z;for(var G in this.__jn){E[G]=i;}D.appendChild(F);}}return D;},__jr:function(H){var I={};if(H){I.whiteSpace=x;}else if(!qx.bom.client.Feature.CSS_TEXT_OVERFLOW&&qx.bom.client.Feature.XUL){I.display=n;}else{I.overflow=d;I.whiteSpace=b;I.textOverflow=y;if(qx.core.Variant.isSet(g,p)){I.OTextOverflow=y;}}return I;},create:function(content,J,K){if(!K){K=window;}if(J){var L=K.document.createElement(j);L.useHtml=true;}else if(!qx.bom.client.Feature.CSS_TEXT_OVERFLOW&&qx.bom.client.Feature.XUL){var L=K.document.createElement(j);var N=K.document.createElementNS(c,w);var M=N.style;M.cursor=i;M.color=i;M.overflow=d;M.maxWidth=r;M.padding=z;for(var O in this.__jn){N.style[O]=i;}N.setAttribute(u,s);L.appendChild(N);}else{var L=K.document.createElement(j);qx.bom.element.Style.setStyles(L,this.__jr(J));}if(content){this.setValue(L,content);}return L;},setValue:function(P,Q){Q=Q||e;if(P.useHtml){P.innerHTML=Q;}else if(!qx.bom.client.Feature.CSS_TEXT_OVERFLOW&&qx.bom.client.Feature.XUL){P.firstChild.setAttribute(f,Q);}else{qx.bom.element.Attribute.set(P,h,Q);}},getValue:function(R){if(R.useHtml){return R.innerHTML;}else if(!qx.bom.client.Feature.CSS_TEXT_OVERFLOW&&qx.bom.client.Feature.XUL){return R.firstChild.getAttribute(f)||e;}else{return qx.bom.element.Attribute.get(R,h);}},getHtmlSize:function(content,S,T){var U=this._htmlElement||this.__jp();U.style.width=T!==undefined?T+v:a;U.innerHTML=content;return this.__js(U,S);},getTextSize:function(V,W){var X=this._textElement||this.__jo();if(!qx.bom.client.Feature.CSS_TEXT_OVERFLOW&&qx.bom.client.Feature.XUL){X.firstChild.setAttribute(f,V);}else{qx.bom.element.Attribute.set(X,h,V);}return this.__js(X,W);},__js:function(Y,ba){var bb=this.__jn;if(!ba){ba={};}for(var bc in bb){Y.style[bc]=ba[bc]||e;}var bd=qx.bom.element.Dimension.getSize(Y);if(qx.core.Variant.isSet(g,t)){if(!qx.bom.client.Platform.WIN){bd.width++;}}if(qx.core.Variant.isSet(g,m)&&qx.bom.client.Engine.VERSION>=9){bd.width++;}return bd;}}});})();(function(){var i="0px",h="qx.client",g="mshtml",f="qx.bom.element.Dimension",e="paddingRight",d="paddingLeft",c="opera",b="paddingTop",a="paddingBottom";qx.Class.define(f,{statics:{getWidth:qx.core.Variant.select(h,{"gecko":function(j){if(j.getBoundingClientRect){var k=j.getBoundingClientRect();return Math.round(k.right)-Math.round(k.left);}else{return j.offsetWidth;}},"default":function(l){return l.offsetWidth;}}),getHeight:qx.core.Variant.select(h,{"gecko":function(m){if(m.getBoundingClientRect){var n=m.getBoundingClientRect();return Math.round(n.bottom)-Math.round(n.top);}else{return m.offsetHeight;}},"default":function(o){return o.offsetHeight;}}),getSize:function(p){return {width:this.getWidth(p),height:this.getHeight(p)};},__ip:{visible:true,hidden:true},getContentWidth:function(q){var s=qx.bom.element.Style;var t=qx.bom.element.Overflow.getX(q);var u=parseInt(s.get(q,d)||i,10);var x=parseInt(s.get(q,e)||i,10);if(this.__ip[t]){var w=q.clientWidth;if(qx.core.Variant.isSet(h,c)){w=w-u-x;}else{if(qx.dom.Node.isBlockNode(q)){w=w-u-x;}}return w;}else{if(q.clientWidth>=q.scrollWidth){return Math.max(q.clientWidth,q.scrollWidth)-u-x;}else{var v=q.scrollWidth-u;var r=qx.bom.client.Engine;if(r.NAME===g&&r.VERSION==6){v-=x;}return v;}}},getContentHeight:function(y){var A=qx.bom.element.Style;var C=qx.bom.element.Overflow.getY(y);var D=parseInt(A.get(y,b)||i,10);var B=parseInt(A.get(y,a)||i,10);if(this.__ip[C]){return y.clientHeight-D-B;}else{if(y.clientHeight>=y.scrollHeight){return Math.max(y.clientHeight,y.scrollHeight)-D-B;}else{var E=y.scrollHeight-D;var z=qx.bom.client.Engine;if(z.NAME===g&&z.VERSION==6){E-=B;}return E;}}},getContentSize:function(F){return {width:this.getContentWidth(F),height:this.getContentHeight(F)};}}});})();(function(){var e="qx.theme.manager.Font",d="Theme",c="changeTheme",b="_applyTheme",a="singleton";qx.Class.define(e,{type:a,extend:qx.util.ValueManager,properties:{theme:{check:d,nullable:true,apply:b,event:c}},members:{resolveDynamic:function(f){var g=this._dynamic;return f instanceof qx.bom.Font?f:g[f];},resolve:function(h){var k=this._dynamic;var i=k[h];if(i){return i;}var j=this.getTheme();if(j!==null&&j.fonts[h]){return k[h]=(new qx.bom.Font).set(j.fonts[h]);}return h;},isDynamic:function(l){var n=this._dynamic;if(l&&(l instanceof qx.bom.Font||n[l]!==undefined)){return true;}var m=this.getTheme();if(m!==null&&l&&m.fonts[l]){n[l]=(new qx.bom.Font).set(m.fonts[l]);return true;}return false;},__io:function(o,p){if(o[p].include){var q=o[o[p].include];o[p].include=null;delete o[p].include;o[p]=qx.lang.Object.mergeWith(o[p],q,false);this.__io(o,p);}},_applyTheme:function(r){var s=this._getDynamic();for(var v in s){if(s[v].themed){s[v].dispose();delete s[v];}}if(r){var t=r.fonts;var u=qx.bom.Font;for(var v in t){if(t[v].include&&t[t[v].include]){this.__io(t,v);}s[v]=(new u).set(t[v]);s[v].themed=true;}}this._setDynamic(s);}}});})();(function(){var k="",j="underline",h="Boolean",g="px",f='"',e="italic",d="normal",c="bold",b="_applyItalic",a="_applyBold",x="Integer",w="_applyFamily",v="_applyLineHeight",u="Array",t="overline",s="line-through",r="qx.bom.Font",q="Number",p="_applyDecoration",o=" ",m="_applySize",n=",";qx.Class.define(r,{extend:qx.core.Object,construct:function(y,z){qx.core.Object.call(this);if(y!==undefined){this.setSize(y);}if(z!==undefined){this.setFamily(z);}},statics:{fromString:function(A){var E=new qx.bom.Font();var C=A.split(/\s+/);var name=[];var D;for(var i=0;i<C.length;i++){switch(D=C[i]){case c:E.setBold(true);break;case e:E.setItalic(true);break;case j:E.setDecoration(j);break;default:var B=parseInt(D,10);if(B==D||qx.lang.String.contains(D,g)){E.setSize(B);}else{name.push(D);}break;}}if(name.length>0){E.setFamily(name);}return E;},fromConfig:function(F){var G=new qx.bom.Font;G.set(F);return G;},__cy:{fontFamily:k,fontSize:k,fontWeight:k,fontStyle:k,textDecoration:k,lineHeight:1.2},getDefaultStyles:function(){return this.__cy;}},properties:{size:{check:x,nullable:true,apply:m},lineHeight:{check:q,nullable:true,apply:v},family:{check:u,nullable:true,apply:w},bold:{check:h,nullable:true,apply:a},italic:{check:h,nullable:true,apply:b},decoration:{check:[j,s,t],nullable:true,apply:p}},members:{__cz:null,__cA:null,__cB:null,__cC:null,__cD:null,__cE:null,_applySize:function(H,I){this.__cz=H===null?null:H+g;},_applyLineHeight:function(J,K){this.__cE=J===null?null:J;},_applyFamily:function(L,M){var N=k;for(var i=0,l=L.length;i<l;i++){if(L[i].indexOf(o)>0){N+=f+L[i]+f;}else{N+=L[i];}if(i!==l-1){N+=n;}}this.__cA=N;},_applyBold:function(O,P){this.__cB=O===null?null:O?c:d;},_applyItalic:function(Q,R){this.__cC=Q===null?null:Q?e:d;},_applyDecoration:function(S,T){this.__cD=S===null?null:S;},getStyles:function(){return {fontFamily:this.__cA,fontSize:this.__cz,fontWeight:this.__cB,fontStyle:this.__cC,textDecoration:this.__cD,lineHeight:this.__cE};}}});})();(function(){var r="left",q="top",p="_applyLayoutChange",o="hAlign",n="flex",m="vAlign",h="Integer",g="minWidth",f="width",e="minHeight",b="qx.ui.layout.Grid",d="height",c="maxHeight",a="maxWidth";qx.Class.define(b,{extend:qx.ui.layout.Abstract,construct:function(s,t){qx.ui.layout.Abstract.call(this);this.__iF=[];this.__iG=[];if(s){this.setSpacingX(s);}if(t){this.setSpacingY(t);}},properties:{spacingX:{check:h,init:0,apply:p},spacingY:{check:h,init:0,apply:p}},members:{__iH:null,__iF:null,__iG:null,__iI:null,__iJ:null,__iK:null,__iL:null,__iM:null,__iN:null,verifyLayoutProperty:null,__iO:function(){var B=[];var A=[];var C=[];var w=-1;var v=-1;var E=this._getLayoutChildren();for(var i=0,l=E.length;i<l;i++){var z=E[i];var D=z.getLayoutProperties();var F=D.row;var u=D.column;D.colSpan=D.colSpan||1;D.rowSpan=D.rowSpan||1;if(F==null||u==null){throw new Error("The layout properties 'row' and 'column' of the child widget '"+z+"' must be defined!");}if(B[F]&&B[F][u]){throw new Error("Cannot add widget '"+z+"'!. "+"There is already a widget '"+B[F][u]+"' in this cell ("+F+", "+u+")");}for(var x=u;x<u+D.colSpan;x++){for(var y=F;y<F+D.rowSpan;y++){if(B[y]==undefined){B[y]=[];}B[y][x]=z;v=Math.max(v,x);w=Math.max(w,y);}}if(D.rowSpan>1){C.push(z);}if(D.colSpan>1){A.push(z);}}for(var y=0;y<=w;y++){if(B[y]==undefined){B[y]=[];}}this.__iH=B;this.__iI=A;this.__iJ=C;this.__iK=w;this.__iL=v;this.__iM=null;this.__iN=null;delete this._invalidChildrenCache;},_setRowData:function(G,H,I){var J=this.__iF[G];if(!J){this.__iF[G]={};this.__iF[G][H]=I;}else{J[H]=I;}},_setColumnData:function(K,L,M){var N=this.__iG[K];if(!N){this.__iG[K]={};this.__iG[K][L]=M;}else{N[L]=M;}},setSpacing:function(O){this.setSpacingY(O);this.setSpacingX(O);return this;},setColumnAlign:function(P,Q,R){{};this._setColumnData(P,o,Q);this._setColumnData(P,m,R);this._applyLayoutChange();return this;},getColumnAlign:function(S){var T=this.__iG[S]||{};return {vAlign:T.vAlign||q,hAlign:T.hAlign||r};},setRowAlign:function(U,V,W){{};this._setRowData(U,o,V);this._setRowData(U,m,W);this._applyLayoutChange();return this;},getRowAlign:function(X){var Y=this.__iF[X]||{};return {vAlign:Y.vAlign||q,hAlign:Y.hAlign||r};},getCellWidget:function(ba,bb){if(this._invalidChildrenCache){this.__iO();}var ba=this.__iH[ba]||{};return ba[bb]||null;},getRowCount:function(){if(this._invalidChildrenCache){this.__iO();}return this.__iK+1;},getColumnCount:function(){if(this._invalidChildrenCache){this.__iO();}return this.__iL+1;},getCellAlign:function(bc,bd){var bj=q;var bh=r;var bi=this.__iF[bc];var bf=this.__iG[bd];var be=this.__iH[bc][bd];if(be){var bg={vAlign:be.getAlignY(),hAlign:be.getAlignX()};}else{bg={};}if(bg.vAlign){bj=bg.vAlign;}else if(bi&&bi.vAlign){bj=bi.vAlign;}else if(bf&&bf.vAlign){bj=bf.vAlign;}if(bg.hAlign){bh=bg.hAlign;}else if(bf&&bf.hAlign){bh=bf.hAlign;}else if(bi&&bi.hAlign){bh=bi.hAlign;}return {vAlign:bj,hAlign:bh};},setColumnFlex:function(bk,bl){this._setColumnData(bk,n,bl);this._applyLayoutChange();return this;},getColumnFlex:function(bm){var bn=this.__iG[bm]||{};return bn.flex!==undefined?bn.flex:0;},setRowFlex:function(bo,bp){this._setRowData(bo,n,bp);this._applyLayoutChange();return this;},getRowFlex:function(bq){var br=this.__iF[bq]||{};var bs=br.flex!==undefined?br.flex:0;return bs;},setColumnMaxWidth:function(bt,bu){this._setColumnData(bt,a,bu);this._applyLayoutChange();return this;},getColumnMaxWidth:function(bv){var bw=this.__iG[bv]||{};return bw.maxWidth!==undefined?bw.maxWidth:Infinity;},setColumnWidth:function(bx,by){this._setColumnData(bx,f,by);this._applyLayoutChange();return this;},getColumnWidth:function(bz){var bA=this.__iG[bz]||{};return bA.width!==undefined?bA.width:null;},setColumnMinWidth:function(bB,bC){this._setColumnData(bB,g,bC);this._applyLayoutChange();return this;},getColumnMinWidth:function(bD){var bE=this.__iG[bD]||{};return bE.minWidth||0;},setRowMaxHeight:function(bF,bG){this._setRowData(bF,c,bG);this._applyLayoutChange();return this;},getRowMaxHeight:function(bH){var bI=this.__iF[bH]||{};return bI.maxHeight||Infinity;},setRowHeight:function(bJ,bK){this._setRowData(bJ,d,bK);this._applyLayoutChange();return this;},getRowHeight:function(bL){var bM=this.__iF[bL]||{};return bM.height!==undefined?bM.height:null;},setRowMinHeight:function(bN,bO){this._setRowData(bN,e,bO);this._applyLayoutChange();return this;},getRowMinHeight:function(bP){var bQ=this.__iF[bP]||{};return bQ.minHeight||0;},__iP:function(bR){var bV=bR.getSizeHint();var bU=bR.getMarginLeft()+bR.getMarginRight();var bT=bR.getMarginTop()+bR.getMarginBottom();var bS={height:bV.height+bT,width:bV.width+bU,minHeight:bV.minHeight+bT,minWidth:bV.minWidth+bU,maxHeight:bV.maxHeight+bT,maxWidth:bV.maxWidth+bU};return bS;},_fixHeightsRowSpan:function(bW){var ck=this.getSpacingY();for(var i=0,l=this.__iJ.length;i<l;i++){var ca=this.__iJ[i];var cc=this.__iP(ca);var cd=ca.getLayoutProperties();var bY=cd.row;var ci=ck*(cd.rowSpan-1);var bX=ci;var cf={};for(var j=0;j<cd.rowSpan;j++){var cm=cd.row+j;var cb=bW[cm];var cl=this.getRowFlex(cm);if(cl>0){cf[cm]={min:cb.minHeight,value:cb.height,max:cb.maxHeight,flex:cl};}ci+=cb.height;bX+=cb.minHeight;}if(ci<cc.height){if(!qx.lang.Object.isEmpty(cf)){var cj=qx.ui.layout.Util.computeFlexOffsets(cf,cc.height,ci);for(var k=0;k<cd.rowSpan;k++){var ce=cj[bY+k]?cj[bY+k].offset:0;bW[bY+k].height+=ce;}}else{var cg=ck*(cd.rowSpan-1);var ch=cc.height-cg;var cb=Math.floor(ch/cd.rowSpan);for(var k=0;k<cd.rowSpan;k++){bW[bY+k].height=cb;}}}if(bX<cc.minHeight){var cj=qx.ui.layout.Util.computeFlexOffsets(cf,cc.minHeight,bX);for(var j=0;j<cd.rowSpan;j++){var ce=cj[bY+j]?cj[bY+j].offset:0;bW[bY+j].minHeight+=ce;}}}},_fixWidthsColSpan:function(cn){var cr=this.getSpacingX();for(var i=0,l=this.__iI.length;i<l;i++){var co=this.__iI[i];var cq=this.__iP(co);var ct=co.getLayoutProperties();var cp=ct.column;var cz=cr*(ct.colSpan-1);var cs=cz;var cu={};var cw;for(var j=0;j<ct.colSpan;j++){var cA=ct.column+j;var cy=cn[cA];var cx=this.getColumnFlex(cA);if(cx>0){cu[cA]={min:cy.minWidth,value:cy.width,max:cy.maxWidth,flex:cx};}cz+=cy.width;cs+=cy.minWidth;}if(cz<cq.width){var cv=qx.ui.layout.Util.computeFlexOffsets(cu,cq.width,cz);for(var j=0;j<ct.colSpan;j++){cw=cv[cp+j]?cv[cp+j].offset:0;cn[cp+j].width+=cw;}}if(cs<cq.minWidth){var cv=qx.ui.layout.Util.computeFlexOffsets(cu,cq.minWidth,cs);for(var j=0;j<ct.colSpan;j++){cw=cv[cp+j]?cv[cp+j].offset:0;cn[cp+j].minWidth+=cw;}}}},_getRowHeights:function(){if(this.__iM!=null){return this.__iM;}var cK=[];var cD=this.__iK;var cC=this.__iL;for(var cL=0;cL<=cD;cL++){var cE=0;var cG=0;var cF=0;for(var cJ=0;cJ<=cC;cJ++){var cB=this.__iH[cL][cJ];if(!cB){continue;}var cH=cB.getLayoutProperties().rowSpan||0;if(cH>1){continue;}var cI=this.__iP(cB);if(this.getRowFlex(cL)>0){cE=Math.max(cE,cI.minHeight);}else{cE=Math.max(cE,cI.height);}cG=Math.max(cG,cI.height);}var cE=Math.max(cE,this.getRowMinHeight(cL));var cF=this.getRowMaxHeight(cL);if(this.getRowHeight(cL)!==null){var cG=this.getRowHeight(cL);}else{var cG=Math.max(cE,Math.min(cG,cF));}cK[cL]={minHeight:cE,height:cG,maxHeight:cF};}if(this.__iJ.length>0){this._fixHeightsRowSpan(cK);}this.__iM=cK;return cK;},_getColWidths:function(){if(this.__iN!=null){return this.__iN;}var cQ=[];var cN=this.__iL;var cP=this.__iK;for(var cV=0;cV<=cN;cV++){var cT=0;var cS=0;var cO=Infinity;for(var cW=0;cW<=cP;cW++){var cM=this.__iH[cW][cV];if(!cM){continue;}var cR=cM.getLayoutProperties().colSpan||0;if(cR>1){continue;}var cU=this.__iP(cM);if(this.getColumnFlex(cV)>0){cS=Math.max(cS,cU.minWidth);}else{cS=Math.max(cS,cU.width);}cT=Math.max(cT,cU.width);}var cS=Math.max(cS,this.getColumnMinWidth(cV));var cO=this.getColumnMaxWidth(cV);if(this.getColumnWidth(cV)!==null){var cT=this.getColumnWidth(cV);}else{var cT=Math.max(cS,Math.min(cT,cO));}cQ[cV]={minWidth:cS,width:cT,maxWidth:cO};}if(this.__iI.length>0){this._fixWidthsColSpan(cQ);}this.__iN=cQ;return cQ;},_getColumnFlexOffsets:function(cX){var cY=this.getSizeHint();var dd=cX-cY.width;if(dd==0){return {};}var db=this._getColWidths();var da={};for(var i=0,l=db.length;i<l;i++){var de=db[i];var dc=this.getColumnFlex(i);if((dc<=0)||(de.width==de.maxWidth&&dd>0)||(de.width==de.minWidth&&dd<0)){continue;}da[i]={min:de.minWidth,value:de.width,max:de.maxWidth,flex:dc};}return qx.ui.layout.Util.computeFlexOffsets(da,cX,cY.width);},_getRowFlexOffsets:function(df){var dg=this.getSizeHint();var dj=df-dg.height;if(dj==0){return {};}var dk=this._getRowHeights();var dh={};for(var i=0,l=dk.length;i<l;i++){var dl=dk[i];var di=this.getRowFlex(i);if((di<=0)||(dl.height==dl.maxHeight&&dj>0)||(dl.height==dl.minHeight&&dj<0)){continue;}dh[i]={min:dl.minHeight,value:dl.height,max:dl.maxHeight,flex:di};}return qx.ui.layout.Util.computeFlexOffsets(dh,df,dg.height);},renderLayout:function(dm,dn){if(this._invalidChildrenCache){this.__iO();}var dC=qx.ui.layout.Util;var dq=this.getSpacingX();var dw=this.getSpacingY();var dH=this._getColWidths();var dG=this._getColumnFlexOffsets(dm);var dr=[];var dJ=this.__iL;var dp=this.__iK;var dI;for(var dK=0;dK<=dJ;dK++){dI=dG[dK]?dG[dK].offset:0;dr[dK]=dH[dK].width+dI;}var dz=this._getRowHeights();var dB=this._getRowFlexOffsets(dn);var dQ=[];for(var dx=0;dx<=dp;dx++){dI=dB[dx]?dB[dx].offset:0;dQ[dx]=dz[dx].height+dI;}var dR=0;for(var dK=0;dK<=dJ;dK++){var top=0;for(var dx=0;dx<=dp;dx++){var dE=this.__iH[dx][dK];if(!dE){top+=dQ[dx]+dw;continue;}var ds=dE.getLayoutProperties();if(ds.row!==dx||ds.column!==dK){top+=dQ[dx]+dw;continue;}var dP=dq*(ds.colSpan-1);for(var i=0;i<ds.colSpan;i++){dP+=dr[dK+i];}var dF=dw*(ds.rowSpan-1);for(var i=0;i<ds.rowSpan;i++){dF+=dQ[dx+i];}var dt=dE.getSizeHint();var dN=dE.getMarginTop();var dD=dE.getMarginLeft();var dA=dE.getMarginBottom();var dv=dE.getMarginRight();var dy=Math.max(dt.minWidth,Math.min(dP-dD-dv,dt.maxWidth));var dO=Math.max(dt.minHeight,Math.min(dF-dN-dA,dt.maxHeight));var dL=this.getCellAlign(dx,dK);var dM=dR+dC.computeHorizontalAlignOffset(dL.hAlign,dy,dP,dD,dv);var du=top+dC.computeVerticalAlignOffset(dL.vAlign,dO,dF,dN,dA);dE.renderLayout(dM,du,dy,dO);top+=dQ[dx]+dw;}dR+=dr[dK]+dq;}},invalidateLayoutCache:function(){qx.ui.layout.Abstract.prototype.invalidateLayoutCache.call(this);this.__iN=null;this.__iM=null;},_computeSizeHint:function(){if(this._invalidChildrenCache){this.__iO();}var dW=this._getColWidths();var dY=0,ea=0;for(var i=0,l=dW.length;i<l;i++){var eb=dW[i];if(this.getColumnFlex(i)>0){dY+=eb.minWidth;}else{dY+=eb.width;}ea+=eb.width;}var ec=this._getRowHeights();var dU=0,dX=0;for(var i=0,l=ec.length;i<l;i++){var ed=ec[i];if(this.getRowFlex(i)>0){dU+=ed.minHeight;}else{dU+=ed.height;}dX+=ed.height;}var dT=this.getSpacingX()*(dW.length-1);var dS=this.getSpacingY()*(ec.length-1);var dV={minWidth:dY+dT,width:ea+dT,minHeight:dU+dS,height:dX+dS};return dV;}},destruct:function(){this.__iH=this.__iF=this.__iG=this.__iI=this.__iJ=this.__iN=this.__iM=null;}});})();(function(){var b="number",a="qx.ui.layout.Canvas";qx.Class.define(a,{extend:qx.ui.layout.Abstract,members:{verifyLayoutProperty:null,renderLayout:function(c,d){var q=this._getLayoutChildren();var g,p,n;var s,top,e,f,j,h;var o,m,r,k;for(var i=0,l=q.length;i<l;i++){g=q[i];p=g.getSizeHint();n=g.getLayoutProperties();o=g.getMarginTop();m=g.getMarginRight();r=g.getMarginBottom();k=g.getMarginLeft();s=n.left!=null?n.left:n.edge;if(qx.lang.Type.isString(s)){s=Math.round(parseFloat(s)*c/100);}e=n.right!=null?n.right:n.edge;if(qx.lang.Type.isString(e)){e=Math.round(parseFloat(e)*c/100);}top=n.top!=null?n.top:n.edge;if(qx.lang.Type.isString(top)){top=Math.round(parseFloat(top)*d/100);}f=n.bottom!=null?n.bottom:n.edge;if(qx.lang.Type.isString(f)){f=Math.round(parseFloat(f)*d/100);}if(s!=null&&e!=null){j=c-s-e-k-m;if(j<p.minWidth){j=p.minWidth;}else if(j>p.maxWidth){j=p.maxWidth;}s+=k;}else{j=n.width;if(j==null){j=p.width;}else{j=Math.round(parseFloat(j)*c/100);if(j<p.minWidth){j=p.minWidth;}else if(j>p.maxWidth){j=p.maxWidth;}}if(e!=null){s=c-j-e-m-k;}else if(s==null){s=k;}else{s+=k;}}if(top!=null&&f!=null){h=d-top-f-o-r;if(h<p.minHeight){h=p.minHeight;}else if(h>p.maxHeight){h=p.maxHeight;}top+=o;}else{h=n.height;if(h==null){h=p.height;}else{h=Math.round(parseFloat(h)*d/100);if(h<p.minHeight){h=p.minHeight;}else if(h>p.maxHeight){h=p.maxHeight;}}if(f!=null){top=d-h-f-r-o;}else if(top==null){top=o;}else{top+=o;}}g.renderLayout(s,top,j,h);}},_computeSizeHint:function(){var I=0,H=0;var F=0,D=0;var B,A;var z,x;var t=this._getLayoutChildren();var w,G,v;var J,top,u,y;for(var i=0,l=t.length;i<l;i++){w=t[i];G=w.getLayoutProperties();v=w.getSizeHint();var E=w.getMarginLeft()+w.getMarginRight();var C=w.getMarginTop()+w.getMarginBottom();B=v.width+E;A=v.minWidth+E;J=G.left!=null?G.left:G.edge;if(J&&typeof J===b){B+=J;A+=J;}u=G.right!=null?G.right:G.edge;if(u&&typeof u===b){B+=u;A+=u;}I=Math.max(I,B);H=Math.max(H,A);z=v.height+C;x=v.minHeight+C;top=G.top!=null?G.top:G.edge;if(top&&typeof top===b){z+=top;x+=top;}y=G.bottom!=null?G.bottom:G.edge;if(y&&typeof y===b){z+=y;x+=y;}F=Math.max(F,z);D=Math.max(D,x);}return {width:I,minWidth:H,height:F,minHeight:D};}}});})();(function(){var k="_",j="_PROT",h="_PUB",g="mixin",f="_PRIV",e="_ABSTRACT",d="_STATIC",c="_INHERITED",b="OVERLAY_",a="_THEMEABLE",F="ICON_CHILDCONTROL",E="_ERROR",D="_OVERRIDDEN",C="ICON_PACKAGE",B="interface",A="ICON_CTOR",z="PROT",y="ICON_CLASS",x="ICON_INTERFACE",w="apiviewer.TreeUtil",r="_MIXIN",s="PUB",p="ICON_EVENT",q="ICON_PROPERTY",n="_WARN",o="ICON_METHOD",l="ICON_MIXIN",m="ICON_APPEARANCE",t="PRIV",u="ICON_CONSTANT",v="_SINGLETON";qx.Class.define(w,{extend:qx.core.Object,construct:function(){qx.core.Object.call(this);},statics:{getChild:function(G,H){if(G!=null&&G.children!=null){for(var i=0;i<G.children.length;i++){if(G.children[i].type==H){return G.children[i];}}}return null;},getChildByAttribute:function(I,J,K){if(I.children!=null){for(var i=0;i<I.children.length;i++){var L=I.children[i];if(L.attributes&&L.attributes[J]==K){return L;}}}return null;},getIconUrl:function(M,N){var O;var P=apiviewer.dao;if(M instanceof P.Package){O=C;}else if(M instanceof P.Class){switch(M.getType()){case g:O=l;break;case B:O=x;break;default:O=y;if(M.isStatic()){O+=d;}else if(M.isAbstract()){O+=e;}else if(M.isSingleton()){O+=v;}}}else if(M instanceof P.Property){O=q;if(M.isPublic()){O+=h;}else if(M.isProtected()){O+=j;}else if(M.isPrivate()||M.isInternal()){O+=f;}if(M.isThemeable()){O+=a;}}else if(M instanceof P.Event){O=p;}else if(M instanceof P.Method){if(M.isConstructor()){var O=A;}else{O=o;if(M.isPublic()){O+=h;}else if(M.isProtected()){O+=j;}else if(M.isPrivate()||M.isInternal()){O+=f;}}if(M.isStatic()){O+=d;}else if(M.isAbstract()){O+=e;}if(M.getClass().getType()==g){O+=r;}}else if(M instanceof P.Constant){O=u;}else if(M instanceof P.Appearance){O=m;}else if(M instanceof P.ChildControl){O=F;}else{throw new Error("Unknown node type: "+M.type);}if(M instanceof P.ClassItem){if(N){O+=c;}else if(M.getOverriddenFrom&&M.getOverriddenFrom()){O+=D;}if(M.getErrors().length>0){O+=E;}}if(M.hasWarning()){O+=n;}return apiviewer.TreeUtil.iconNameToIconPath(O);},iconNameToIconPath:function(Q){var T=apiviewer.TreeUtil[Q];if(!T){var S=Q.split(k);var V=S[0]+k+S[1];if(S[2]==s||S[2]==z||S[2]==t){V+=k+S[2];var U=3;}else{U=2;}T=[apiviewer.TreeUtil[V]];if(T[0]==null){throw new Error("Unknown img constant: "+V);}for(var i=U;i<S.length;i++){var R=apiviewer.TreeUtil[b+S[i]];if(R==null){throw new Error("Unknown img constant: OVERLAY_"+S[i]);}T.push(R);}}return T;},ICON_BLANK:"apiviewer/image/blank.gif",OVERLAY_ABSTRACT:"apiviewer/image/overlay_abstract18.gif",OVERLAY_ERROR:"apiviewer/image/overlay_error18.gif",OVERLAY_INHERITED:"apiviewer/image/overlay_inherited18.gif",OVERLAY_OVERRIDDEN:"apiviewer/image/overlay_overridden18.gif",OVERLAY_THEMEABLE:"apiviewer/image/overlay_themeable18.gif",OVERLAY_STATIC:"apiviewer/image/overlay_static18.gif",OVERLAY_WARN:"apiviewer/image/overlay_warning18.gif",OVERLAY_MIXIN:"apiviewer/image/overlay_mixin18.gif",ICON_PACKAGE:"apiviewer/image/package18.gif",ICON_PACKAGE_WARN:"apiviewer/image/package_warning18.gif",ICON_CLASS:"apiviewer/image/class18.gif",ICON_CLASS_WARN:"apiviewer/image/class_warning18.gif",ICON_CLASS_ERROR:"apiviewer/image/class_warning18.gif",ICON_CLASS_STATIC:"apiviewer/image/class_static18.gif",ICON_CLASS_STATIC_WARN:"apiviewer/image/class_static_warning18.gif",ICON_CLASS_STATIC_ERROR:"apiviewer/image/class_static_warning18.gif",ICON_CLASS_ABSTRACT:"apiviewer/image/class_abstract18.gif",ICON_CLASS_ABSTRACT_WARN:"apiviewer/image/class_abstract_warning18.gif",ICON_CLASS_ABSTRACT_ERROR:"apiviewer/image/class_abstract_warning18.gif",ICON_CLASS_SINGLETON:"apiviewer/image/class_singleton18.gif",ICON_CLASS_SINGLETON_WARN:"apiviewer/image/class_singleton_warning18.gif",ICON_CLASS_SINGLETON_ERROR:"apiviewer/image/class_singleton_warning18.gif",ICON_PROPERTY_PUB:"apiviewer/image/property18.gif",ICON_PROPERTY_PROT:"apiviewer/image/property_protected18.gif",ICON_PROPERTY_PRIV:"apiviewer/image/property_private18.gif",ICON_PROPERTY_PUB_THEMEABLE:"apiviewer/image/property_themeable18.gif",ICON_EVENT:"apiviewer/image/event18.gif",ICON_INTERFACE:"apiviewer/image/interface18.gif",ICON_INTERFACE_WARN:"apiviewer/image/interface_warning18.gif",ICON_MIXIN:"apiviewer/image/mixin18.gif",ICON_MIXIN_WARN:"apiviewer/image/mixin_warning18.gif",ICON_METHOD_PUB:"apiviewer/image/method_public18.gif",ICON_METHOD_PUB_INHERITED:"apiviewer/image/method_public_inherited18.gif",ICON_CTOR:"apiviewer/image/constructor18.gif",ICON_METHOD_PROT:"apiviewer/image/method_protected18.gif",ICON_METHOD_PRIV:"apiviewer/image/method_private18.gif",ICON_CONSTANT:"apiviewer/image/constant18.gif",ICON_APPEARANCE:"apiviewer/image/constant18.gif",ICON_CHILDCONTROL:"apiviewer/image/childcontrol18.gif"},defer:function(W,X,Y){W.PRELOAD_IMAGES=[W.ICON_INFO,W.ICON_SEARCH,W.OVERLAY_ABSTRACT,W.OVERLAY_ERROR,W.OVERLAY_INHERITED,W.OVERLAY_OVERRIDDEN,W.OVERLAY_STATIC,W.OVERLAY_WARN,W.OVERLAY_MIXIN,W.OVERLAY_THEMEABLE,W.ICON_PACKAGE,W.ICON_PACKAGE_WARN,W.ICON_CLASS,W.ICON_CLASS_WARN,W.ICON_CLASS_ERROR,W.ICON_CLASS_STATIC,W.ICON_CLASS_STATIC_WARN,W.ICON_CLASS_STATIC_ERROR,W.ICON_CLASS_ABSTRACT,W.ICON_CLASS_ABSTRACT_WARN,W.ICON_CLASS_ABSTRACT_ERROR,W.ICON_CLASS_SINGLETON,W.ICON_CLASS_SINGLETON_WARN,W.ICON_CLASS_SINGLETON_ERROR,W.ICON_PROPERTY_PUB,W.ICON_PROPERTY_PROT,W.ICON_PROPERTY_PRIV,W.ICON_PROPERTY_PUB_THEMEABLE,W.ICON_EVENT,W.ICON_INTERFACE,W.ICON_INTERFACE_WARN,W.ICON_MIXIN,W.ICON_MIXIN_WARN,W.ICON_METHOD_PUB,W.ICON_METHOD_PUB_INHERITED,W.ICON_CTOR,W.ICON_METHOD_PROT,W.ICON_METHOD_PRIV,W.ICON_CONSTANT,W.ICON_CHILDCONTROL];}});})();(function(){var g="Boolean",f="changeShowInherited",e="changeShowProtected",d="changeExpandProperties",c="apiviewer.UiModel",b="changeShowPrivate",a="singleton";qx.Class.define(c,{extend:qx.core.Object,type:a,properties:{showInherited:{check:g,init:false,event:f},expandProperties:{check:g,init:false,event:d},showProtected:{check:g,init:false,event:e},showPrivate:{check:g,init:false,event:b}}});})();(function(){var i="auto",h="overflowX",g="visible",f="hidden",e="scroll",d="overflowY",c="_applyOverflowX",b="_applyOverflowY",a="qx.ui.core.MNativeOverflow";qx.Mixin.define(a,{properties:{overflowX:{check:[f,g,e,i],nullable:true,apply:c},overflowY:{check:[f,g,e,i],nullable:true,apply:b},overflow:{group:[h,d]}},members:{_applyOverflowX:function(j){this.getContentElement().setStyle(h,j);},_applyOverflowY:function(k){this.getContentElement().setStyle(d,k);}}});})();(function(){var o="none",n="text",m="",l="userSelect",k="color",j="String",i="0px",h="webkit",g="changeHtml",f="_applyCssClass",c="class",e="qx.ui.embed.Html",d="_applyHtml",b="qx.client",a="html";qx.Class.define(e,{extend:qx.ui.core.Widget,include:[qx.ui.core.MNativeOverflow],construct:function(p){qx.ui.core.Widget.call(this);if(p!=null){this.setHtml(p);}},properties:{html:{check:j,apply:d,event:g,nullable:true},cssClass:{check:j,init:m,apply:f},selectable:{refine:true,init:true},focusable:{refine:true,init:true}},members:{getFocusElement:function(){return this.getContentElement();},_applyHtml:function(q,r){var s=this.getContentElement();s.setAttribute(a,q||m);s.setStyles({"padding":i,"border":o});},_applyCssClass:function(t,u){this.getContentElement().setAttribute(c,t);},_applySelectable:function(v){qx.ui.core.Widget.prototype._applySelectable.call(this,v);if(qx.core.Variant.isSet(b,h)){this.getContainerElement().setStyle(l,v?n:o);this.getContentElement().setStyle(l,v?n:o);}},_applyFont:function(w,x){var y=w?qx.theme.manager.Font.getInstance().resolve(w).getStyles():qx.bom.Font.getDefaultStyles();this.getContentElement().setStyles(y);},_applyTextColor:function(z,A){if(z){this.getContentElement().setStyle(k,qx.theme.manager.Color.getInstance().resolve(z));}else{this.getContentElement().removeStyle(k);}}}});})();(function(){var l="Boolean",k="_updatePanels",j="auto",h='</div>',g='<div>',f='apiviewer/image/close.gif',e="javascript",d='<div style="padding:24px;">',c="_blank",b="apiviewer.dao.Node",y="string",x="http://",w="pre",v="_infoPanels",u='apiviewer/image/open.gif',t="appear",s="img",r="_applyDocNode",q="detailviewer",p='<h1></h1>',n="abstract",o="apiviewer.ui.AbstractViewer",m="a";qx.Class.define(o,{type:n,extend:qx.ui.embed.Html,construct:function(){qx.ui.embed.Html.call(this);this._infoPanelHash={};this._infoPanels=[];this.setOverflowX(j);this.setOverflowY(j);this.setAppearance(q);this._infoPanelHash={};this._infoPanels=[];apiviewer.ObjectRegistry.register(this);},properties:{docNode:{check:b,init:null,nullable:true,apply:r},showInherited:{check:l,init:false,apply:k},expandProperties:{check:l,init:false,apply:k},showProtected:{check:l,init:false,apply:k},showPrivate:{check:l,init:false,apply:k}},statics:{fixLinks:function(z){var a=z.getElementsByTagName(m);for(var i=0;i<a.length;i++){if(typeof a[i].href==y&&a[i].href.indexOf(x)==0){a[i].target=c;}}},highlightCode:function(A){var B=A.getElementsByTagName(w);for(var i=0;i<B.length;i++){var C=B[i];if(C.className!==e){continue;}C.innerHTML=qx.dev.Tokenizer.javaScriptToHtml(C.innerHTML);}}},members:{_infoPanelHash:null,_infoPanels:null,__Sq:null,_init:function(D){this.__Sr();this.setDocNode(D);this.addListenerOnce(t,function(){this._syncHtml();this._applyDocNode(this.__Sq);},this);},__Sr:function(){var F=new qx.util.StringBuilder();F.add(d);F.add(p);F.add(g,h);var E=this.getPanels();for(var i=0;i<E.length;i++){var G=E[i];F.add(G.getPanelHtml(this));}F.add(h);this.setHtml(F.get());},_getTitleHtml:function(H){throw new Error("Abstract method called!");},_getDescriptionHtml:function(I){throw new Error("Abstract method called!");},_syncHtml:function(){var M=this.getContentElement().getDomElement().firstChild;var J=M.childNodes;var K=this.getPanels();apiviewer.ui.AbstractViewer.fixLinks(M);this._titleElem=J[0];this._classDescElem=J[1];for(var i=0;i<K.length;i++){var L=K[i];L.setElement(J[i+2]);}},addInfoPanel:function(N){this._infoPanelHash[N.toHashCode()]=N;this._infoPanels.push(N);},getPanels:function(){return this._infoPanels;},getPanelFromHashCode:function(O){return this._infoPanelHash[O];},_updatePanels:function(){var P=this.getPanels();for(var i=0;i<P.length;i++){var Q=P[i];Q.update(this,this.__Sq);}},_applyDocNode:function(R){this.__Sq=R;if(!this._titleElem){return ;}this._titleElem.innerHTML=this._getTitleHtml(R);this._classDescElem.innerHTML=this._getDescriptionHtml(R);apiviewer.ui.AbstractViewer.fixLinks(this._classDescElem);apiviewer.ui.AbstractViewer.highlightCode(this._classDescElem);this._updatePanels();},togglePanelVisibility:function(S){try{S.setIsOpen(!S.getIsOpen());var T=S.getTitleElement().getElementsByTagName(s)[0];T.src=qx.util.ResourceManager.getInstance().toUri(S.getIsOpen()?f:u);S.update(this,this.getDocNode());}catch(U){this.error("Toggling info body failed",U);}}},destruct:function(){this._classDescElem=this._titleElem=this._infoPanelHash=this.__Sq=null;this._disposeArray(v,1);}});})();(function(){var n="classes",m="functions",l="",k="packages",j="class",i="interfaces",h='<div class="class-description">',g='<small>package</small>',f='</div>',e="ClassViewer",b="mixins",d="interface",c="apiviewer.ui.PackageViewer",a="mixin";qx.Class.define(c,{extend:apiviewer.ui.AbstractViewer,construct:function(){apiviewer.ui.AbstractViewer.call(this);this.addInfoPanel(new apiviewer.ui.panels.MethodPanel(m,m));this.addInfoPanel(new apiviewer.ui.panels.ClassPanel(n,n,j));this.addInfoPanel(new apiviewer.ui.panels.ClassPanel(n,i,d));this.addInfoPanel(new apiviewer.ui.panels.ClassPanel(n,b,a));this.addInfoPanel(new apiviewer.ui.panels.PackagePanel(k,k));this.getContentElement().setAttribute(j,e);this._init(new apiviewer.dao.Package({}));},members:{_getTitleHtml:function(o){var p=l;p+=g;p+=o.getFullName();return p;},_getDescriptionHtml:function(q){var r=new qx.util.StringBuilder();var s=q.getDescription();if(s!=l){r.add(h,apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(s,q),f);}return r.get();}}});})();(function(){var a="apiviewer.ObjectRegistry";qx.Class.define(a,{statics:{__Ss:{},register:function(b){var c=qx.core.ObjectRegistry.toHashCode(b);this.__Ss[c]=b;},getObjectFromHashCode:function(d){return this.__Ss[d];}}});})();(function(){var l="</span>",k="sym",j="nl",h="qxkey",g="ws",f=">",e="qqstr",d="<",c="qstr",b="linecomment",bg="ident",bf="keyword",be="regexp",bd="&",bc="|",bb="fullcomment",ba="atom",Y="\\r\\n|\\r|\\n",X="\\s*\\)*",W="\\s",s="^",t='["][^"]*["]',q="real",r="\\s*[,\\)]",o="<span class='string'>",p="[a-zA-Z_][a-zA-Z0-9_]*\\b",m="<span class='comment'>",n="[+-]?\\d+",w="\\s*\\(*\\s*",x="&nbsp;",F="qx.dev.Tokenizer",D="\\t",M="\\s*\\)*\\s*\\)",H="\\.(?:replace)\\s*\\(\\s*\\(*\\s*",S="\\)*\\.(?:test|exec)\\s*\\(\\s*",Q="<span class='regexp'>",z="int",V="'>",U="<span class='",T="(?:\\/(?!\\*)[^\\t\\n\\r\\f\\v\\/]+?\\/[mgi]*)",y=".",B="\\s*\\)*\\s*?,?",C="[\\(,]\\s*",E="<span class='ident'>",G="g",I="[+-]?\\d+(([.]\\d+)*([eE][+-]?\\d+))?",N="\\/\\*(?:.|[\\n\\r])*?\\*\\/",R="\n",u="$",v="['][^']*[']",A="tab",L="\\/\\/.*?[\\n\\r$]",K="<br>",J=" ",P="(?::|=|\\?)\\s*\\(*\\s*",O="\\.(?:match|search|split)\\s*\\(\\s*\\(*\\s*";qx.Class.define(F,{extend:qx.core.Object,statics:{tokenizeJavaScript:function(bh){var bL={"break":1,"case":1,"catch":1,"continue":1,"default":1,"delete":1,"do":1,"else":1,"finally":1,"for":1,"function":1,"if":1,"in":1,"instanceof":1,"new":1,"return":1,"switch":1,"throw":1,"try":1,"typeof":1,"var":1,"while":1,"with":1};var bB={"void":1,"null":1,"true":1,"false":1,"NaN":1,"Infinity":1,"this":1};var bx={"statics":1,"members":1,"construct":1,"destruct":1,"events":1,"properties":1,"extend":1,"implement":1};var bt=function(bM){return new RegExp(s+bM+u);};var bE=L;var bu=N;var bo=p;var bw=n;var br=I;var bz=t;var by=v;var bm=D;var bH=Y;var bJ=W;var bs=T;var bv=[O+bs+M,H+bs+B,w+bs+S,P+bs+X,C+bs+r].join(bc);var bF=bt(bE);var bp=bt(bu);var bC=bt(bo);var bl=bt(bw);var bI=bt(br);var bk=bt(bz);var bj=bt(by);var bD=bt(bm);var bq=bt(bH);var bi=bt(bJ);var bn=bt(bv);var bA=new RegExp([bE,bu,bo,bw,br,bz,by,by,bm,bH,bJ,bv,y].join(bc),G);var bG=[];var a=bh.match(bA);for(var i=0;i<a.length;i++){var bK=a[i];if(bK.match(bF)){bG.push({type:b,value:bK});}else if(bK.match(bp)){bG.push({type:bb,value:bK});}else if(bK.match(bn)){bG.push({type:be,value:bK});}else if(bK.match(bj)){bG.push({type:c,value:bK});}else if(bK.match(bk)){bG.push({type:e,value:bK});}else if(bL[bK]){bG.push({type:bf,value:bK});}else if(bB[bK]){bG.push({type:ba,value:bK});}else if(bx[bK]){bG.push({type:h,value:bK});}else if(bK.match(bC)){bG.push({type:bg,value:bK});}else if(bK.match(bI)){bG.push({type:q,value:bK});}else if(bK.match(bl)){bG.push({type:z,value:bK});}else if(bK.match(bq)){bG.push({type:j,value:bK});}else if(bK.match(bt(bi))){bG.push({type:g,value:bK});}else if(bK.match(bD)){bG.push({type:A,value:bK});}else if(bK==f){bG.push({type:k,value:f});}else if(bK==d){bG.push({type:k,value:d});}else if(bK==bd){bG.push({type:k,value:bd});}else{bG.push({type:k,value:bK});}}return bG;},javaScriptToHtml:function(bN){var bR=qx.dev.Tokenizer.tokenizeJavaScript(bN);var bQ=new qx.util.StringBuilder();for(var i=0;i<bR.length;i++){var bS=bR[i];var bP=qx.bom.String.escape(bS.value);switch(bS.type){case be:bQ.add(Q,bP,l);break;case bg:bQ.add(E,bP,l);break;case b:case bb:bQ.add(m,bP,l);break;case c:case e:bQ.add(o,bP,l);break;case bf:case ba:case h:bQ.add(U,bS.type,V,bP,l);break;case j:var bO=qx.bom.client.Engine.MSHTML?K:R;bQ.add(bO);break;case g:var bT=qx.bom.client.Engine.MSHTML?x:J;bQ.add(bT);break;default:bQ.add(bP);}}return bQ.get();}}});})();(function(){var f="mshtml",e="pop.push.reverse.shift.sort.splice.unshift.join.slice",d="number",c="qx.type.BaseArray",b="qx.client",a=".";qx.Class.define(c,{extend:Array,construct:function(g){},members:{toArray:null,valueOf:null,pop:null,push:null,reverse:null,shift:null,sort:null,splice:null,unshift:null,concat:null,join:null,slice:null,toString:null,indexOf:null,lastIndexOf:null,forEach:null,filter:null,map:null,some:null,every:null}});(function(){function k(l){if(qx.core.Variant.isSet(b,f)){j.prototype={length:0,$$isArray:true};var o=e.split(a);for(var length=o.length;length;){j.prototype[o[--length]]=Array.prototype[o[length]];}}var p=Array.prototype.slice;j.prototype.concat=function(){var r=this.slice(0);for(var i=0,length=arguments.length;i<length;i++){var q;if(arguments[i] instanceof j){q=p.call(arguments[i],0);}else if(arguments[i] instanceof Array){q=arguments[i];}else{q=[arguments[i]];}r.push.apply(r,q);}return r;};j.prototype.toString=function(){return p.call(this,0).toString();};j.prototype.toLocaleString=function(){return p.call(this,0).toLocaleString();};j.prototype.constructor=j;j.prototype.indexOf=qx.lang.Core.arrayIndexOf;j.prototype.lastIndexOf=qx.lang.Core.arrayLastIndexOf;j.prototype.forEach=qx.lang.Core.arrayForEach;j.prototype.some=qx.lang.Core.arraySome;j.prototype.every=qx.lang.Core.arrayEvery;var m=qx.lang.Core.arrayFilter;var n=qx.lang.Core.arrayMap;j.prototype.filter=function(){var s=new this.constructor;s.push.apply(s,m.apply(this,arguments));return s;};j.prototype.map=function(){var t=new this.constructor;t.push.apply(t,n.apply(this,arguments));return t;};j.prototype.slice=function(){var u=new this.constructor;u.push.apply(u,Array.prototype.slice.apply(this,arguments));return u;};j.prototype.splice=function(){var v=new this.constructor;v.push.apply(v,Array.prototype.splice.apply(this,arguments));return v;};j.prototype.toArray=function(){return Array.prototype.slice.call(this,0);};j.prototype.valueOf=function(){return this.length;};return j;}function j(length){if(arguments.length===1&&typeof length===d){this.length=-1<length&&length===length>>.5?length:this.push(length);}else if(arguments.length){this.push.apply(this,arguments);}}function h(){}h.prototype=[];j.prototype=new h;j.prototype.length=0;qx.type.BaseArray=k(j);})();})();(function(){var b="",a="qx.util.StringBuilder";qx.Class.define(a,{extend:qx.type.BaseArray,members:{clear:function(){this.length=0;},get:function(){return this.join(b);},add:null,isEmpty:function(){return this.length===0;},size:function(){return this.join(b).length;}},defer:function(c,d){d.add=d.push;d.toString=d.get;d.valueOf=d.get;}});})();(function(){var p="",o="!",n="'!",m="'",k="Expected '",j="' (rgb(",h=",",g=")), but found value '",f="Event (",d="Expected value to be the CSS color '",bw="' but found ",bv="The value '",bu=" != ",bt="qx.core.Object",bs="Expected value to be an array but found ",br=") was fired.",bq="Expected value to be an integer >= 0 but found ",bp="' to be not equal with '",bo="' to '",bn="qx.ui.core.Widget",w="Called assertTrue with '",x="Expected value to be a map but found ",u="The function did not raise an exception!",v="Expected value to be undefined but found ",s="Expected value to be a DOM element but found '",t="Expected value to be a regular expression but found ",q="' to implement the interface '",r="Expected value to be null but found ",E="Invalid argument 'type'",F="Called assert with 'false'",R="Assertion error! ",N="Expected value to be a string but found ",ba="null",U="' but found '",bj="' must must be a key of the map '",bf="The String '",J="Expected value not to be undefined but found ",bm="qx.util.ColorUtil",bl=": ",bk="The raised exception does not have the expected type! ",I=") not fired.",L="qx.core.Assert",M="Expected value to be typeof object but found ",P="' (identical) but found '",S="' must have any of the values defined in the array '",V="Expected value to be a number but found ",bc="Called assertFalse with '",bh="]",y="Expected value to be a qooxdoo object but found ",z="' arguments.",K="Expected value not to be null but found ",Y="Array[",X="' does not match the regular expression '",W="' to be not identical with '",be="' arguments but found '",bd="', which cannot be converted to a CSS color!",T="Expected object '",bb="qx.core.AssertionError",a="Expected value to be a boolean but found ",bg="))!",A="Expected value to be a qooxdoo widget but found ",B="Expected value '%1' to be in the range '%2'..'%3'!",O="Expected value to be typeof '",b="Expected value to be typeof function but found ",c="Expected value to be an integer but found ",H="Called fail().",C="The parameter 're' must be a string or a regular expression.",D="Expected value to be a number >= 0 but found ",G="Expected value to be instanceof '",Q="Wrong number of arguments given. Expected '",bi="object";qx.Class.define(L,{statics:{__tN:true,__tO:function(bx,by){var bz=p;for(var i=1,l=arguments.length;i<l;i++){bz=bz+this.__tP(arguments[i]);}var bB=R+bx+bl+bz;if(this.__tN){qx.Bootstrap.error(bB);}if(qx.Class.isDefined(bb)){var bA=new qx.core.AssertionError(bx,bz);if(this.__tN){qx.Bootstrap.error("Stack trace: \n"+bA.getStackTrace());}throw bA;}else{throw new Error(bB);}},__tP:function(bC){var bD;if(bC===null){bD=ba;}else if(qx.lang.Type.isArray(bC)&&bC.length>10){bD=Y+bC.length+bh;}else if((bC instanceof Object)&&(bC.toString==null)){bD=qx.lang.Json.stringify(bC,null,2);}else{try{bD=bC.toString();}catch(e){bD=p;}}return bD;},assert:function(bE,bF){bE==true||this.__tO(bF||p,F);},fail:function(bG){this.__tO(bG||p,H);},assertTrue:function(bH,bI){(bH===true)||this.__tO(bI||p,w,bH,m);},assertFalse:function(bJ,bK){(bJ===false)||this.__tO(bK||p,bc,bJ,m);},assertEquals:function(bL,bM,bN){bL==bM||this.__tO(bN||p,k,bL,U,bM,n);},assertNotEquals:function(bO,bP,bQ){bO!=bP||this.__tO(bQ||p,k,bO,bp,bP,n);},assertIdentical:function(bR,bS,bT){bR===bS||this.__tO(bT||p,k,bR,P,bS,n);},assertNotIdentical:function(bU,bV,bW){bU!==bV||this.__tO(bW||p,k,bU,W,bV,n);},assertNotUndefined:function(bX,bY){bX!==undefined||this.__tO(bY||p,J,bX,o);},assertUndefined:function(ca,cb){ca===undefined||this.__tO(cb||p,v,ca,o);},assertNotNull:function(cc,cd){cc!==null||this.__tO(cd||p,K,cc,o);},assertNull:function(ce,cf){ce===null||this.__tO(cf||p,r,ce,o);},assertJsonEquals:function(cg,ch,ci){this.assertEquals(qx.lang.Json.stringify(cg),qx.lang.Json.stringify(ch),ci);},assertMatch:function(cj,ck,cl){this.assertString(cj);this.assert(qx.lang.Type.isRegExp(ck)||qx.lang.Type.isString(ck),C);cj.search(ck)>=0||this.__tO(cl||p,bf,cj,X,ck.toString(),n);},assertArgumentsCount:function(cm,cn,co,cp){var cq=cm.length;(cq>=cn&&cq<=co)||this.__tO(cp||p,Q,cn,bo,co,be,arguments.length,z);},assertEventFired:function(cr,event,cs,ct,cu){var cw=false;var cv=function(e){if(ct){ct.call(cr,e);}cw=true;};var cx;try{cx=cr.addListener(event,cv,cr);cs.call();}catch(cy){throw cy;}finally{try{cr.removeListenerById(cx);}catch(cz){}}cw===true||this.__tO(cu||p,f,event,I);},assertEventNotFired:function(cA,event,cB,cC){var cE=false;var cD=function(e){cE=true;};var cF=cA.addListener(event,cD,cA);cB.call();cE===false||this.__tO(cC||p,f,event,br);cA.removeListenerById(cF);},assertException:function(cG,cH,cI,cJ){var cH=cH||Error;var cK;try{this.__tN=false;cG();}catch(cL){cK=cL;}finally{this.__tN=true;}if(cK==null){this.__tO(cJ||p,u);}cK instanceof cH||this.__tO(cJ||p,bk,cH,bu,cK);if(cI){this.assertMatch(cK.toString(),cI,cJ);}},assertInArray:function(cM,cN,cO){cN.indexOf(cM)!==-1||this.__tO(cO||p,bv,cM,S,cN,m);},assertArrayEquals:function(cP,cQ,cR){this.assertArray(cP,cR);this.assertArray(cQ,cR);this.assertEquals(cP.length,cQ.length,cR);for(var i=0;i<cP.length;i++){this.assertIdentical(cP[i],cQ[i],cR);}},assertKeyInMap:function(cS,cT,cU){cT[cS]!==undefined||this.__tO(cU||p,bv,cS,bj,cT,m);},assertFunction:function(cV,cW){qx.lang.Type.isFunction(cV)||this.__tO(cW||p,b,cV,o);},assertString:function(cX,cY){qx.lang.Type.isString(cX)||this.__tO(cY||p,N,cX,o);},assertBoolean:function(da,db){qx.lang.Type.isBoolean(da)||this.__tO(db||p,a,da,o);},assertNumber:function(dc,dd){(qx.lang.Type.isNumber(dc)&&isFinite(dc))||this.__tO(dd||p,V,dc,o);},assertPositiveNumber:function(de,df){(qx.lang.Type.isNumber(de)&&isFinite(de)&&de>=0)||this.__tO(df||p,D,de,o);},assertInteger:function(dg,dh){(qx.lang.Type.isNumber(dg)&&isFinite(dg)&&dg%1===0)||this.__tO(dh||p,c,dg,o);},assertPositiveInteger:function(di,dj){var dk=(qx.lang.Type.isNumber(di)&&isFinite(di)&&di%1===0&&di>=0);dk||this.__tO(dj||p,bq,di,o);},assertInRange:function(dl,dm,dn,dp){(dl>=dm&&dl<=dn)||this.__tO(dp||p,qx.lang.String.format(B,[dl,dm,dn]));},assertObject:function(dq,dr){var ds=dq!==null&&(qx.lang.Type.isObject(dq)||typeof dq===bi);ds||this.__tO(dr||p,M,(dq),o);},assertArray:function(dt,du){qx.lang.Type.isArray(dt)||this.__tO(du||p,bs,dt,o);},assertMap:function(dv,dw){qx.lang.Type.isObject(dv)||this.__tO(dw||p,x,dv,o);},assertRegExp:function(dx,dy){qx.lang.Type.isRegExp(dx)||this.__tO(dy||p,t,dx,o);},assertType:function(dz,dA,dB){this.assertString(dA,E);typeof (dz)===dA||this.__tO(dB||p,O,dA,bw,dz,o);},assertInstance:function(dC,dD,dE){var dF=dD.classname||dD+p;dC instanceof dD||this.__tO(dE||p,G,dF,bw,dC,o);},assertInterface:function(dG,dH,dI){qx.Class.implementsInterface(dG,dH)||this.__tO(dI||p,T,dG,q,dH,n);},assertCssColor:function(dJ,dK,dL){var dM=qx.Class.getByName(bm);if(!dM){throw new Error("qx.util.ColorUtil not available! Your code must have a dependency on 'qx.util.ColorUtil'");}var dO=dM.stringToRgb(dJ);try{var dN=dM.stringToRgb(dK);}catch(dQ){this.__tO(dL||p,d,dJ,j,dO.join(h),g,dK,bd);}var dP=dO[0]==dN[0]&&dO[1]==dN[1]&&dO[2]==dN[2];dP||this.__tO(dL||p,d,dO,j,dO.join(h),g,dK,j,dN.join(h),bg);},assertElement:function(dR,dS){!!(dR&&dR.nodeType===1)||this.__tO(dS||p,s,dR,n);},assertQxObject:function(dT,dU){this.__tQ(dT,bt)||this.__tO(dU||p,y,dT,o);},assertQxWidget:function(dV,dW){this.__tQ(dV,bn)||this.__tO(dW||p,A,dV,o);},__tQ:function(dX,dY){if(!dX){return false;}var ea=dX.constructor;while(ea){if(ea.classname===dY){return true;}ea=ea.superclass;}return false;}}});})();(function(){var p='',o='"',m=':',l=']',h='null',g=': ',f='object',e='function',d=',',b='\n',ba='\\u',Y=',\n',X='0000',W='string',V="Cannot stringify a recursive object.",U='0',T='-',S='}',R='String',Q='Boolean',x='\\\\',y='\\f',u='\\t',w='{\n',s='[]',t="qx.lang.JsonImpl",q='Z',r='\\n',z='Object',A='{}',H='@',F='.',K='(',J='Array',M='T',L='\\r',C='{',P='JSON.parse',O=' ',N='[',B='Number',D=')',E='[\n',G='\\"',I='\\b';qx.Class.define(t,{extend:Object,construct:function(){this.stringify=qx.lang.Function.bind(this.stringify,this);this.parse=qx.lang.Function.bind(this.parse,this);},members:{__tT:null,__tU:null,__tV:null,__tW:null,stringify:function(bb,bc,bd){this.__tT=p;this.__tU=p;this.__tW=[];if(qx.lang.Type.isNumber(bd)){var bd=Math.min(10,Math.floor(bd));for(var i=0;i<bd;i+=1){this.__tU+=O;}}else if(qx.lang.Type.isString(bd)){if(bd.length>10){bd=bd.slice(0,10);}this.__tU=bd;}if(bc&&(qx.lang.Type.isFunction(bc)||qx.lang.Type.isArray(bc))){this.__tV=bc;}else{this.__tV=null;}return this.__tX(p,{'':bb});},__tX:function(be,bf){var bi=this.__tT,bg,bj=bf[be];if(bj&&qx.lang.Type.isFunction(bj.toJSON)){bj=bj.toJSON(be);}else if(qx.lang.Type.isDate(bj)){bj=this.dateToJSON(bj);}if(typeof this.__tV===e){bj=this.__tV.call(bf,be,bj);}if(bj===null){return h;}if(bj===undefined){return undefined;}switch(qx.lang.Type.getClass(bj)){case R:return this.__tY(bj);case B:return isFinite(bj)?String(bj):h;case Q:return String(bj);case J:this.__tT+=this.__tU;bg=[];if(this.__tW.indexOf(bj)!==-1){throw new TypeError(V);}this.__tW.push(bj);var length=bj.length;for(var i=0;i<length;i+=1){bg[i]=this.__tX(i,bj)||h;}this.__tW.pop();if(bg.length===0){var bh=s;}else if(this.__tT){bh=E+this.__tT+bg.join(Y+this.__tT)+b+bi+l;}else{bh=N+bg.join(d)+l;}this.__tT=bi;return bh;case z:this.__tT+=this.__tU;bg=[];if(this.__tW.indexOf(bj)!==-1){throw new TypeError(V);}this.__tW.push(bj);if(this.__tV&&typeof this.__tV===f){var length=this.__tV.length;for(var i=0;i<length;i+=1){var k=this.__tV[i];if(typeof k===W){var v=this.__tX(k,bj);if(v){bg.push(this.__tY(k)+(this.__tT?g:m)+v);}}}}else{for(var k in bj){if(Object.hasOwnProperty.call(bj,k)){var v=this.__tX(k,bj);if(v){bg.push(this.__tY(k)+(this.__tT?g:m)+v);}}}}this.__tW.pop();if(bg.length===0){var bh=A;}else if(this.__tT){bh=w+this.__tT+bg.join(Y+this.__tT)+b+bi+S;}else{bh=C+bg.join(d)+S;}this.__tT=bi;return bh;}},dateToJSON:function(bk){var bl=function(n){return n<10?U+n:n;};var bm=function(n){var bn=bl(n);return n<100?U+bn:bn;};return isFinite(bk.valueOf())?bk.getUTCFullYear()+T+bl(bk.getUTCMonth()+1)+T+bl(bk.getUTCDate())+M+bl(bk.getUTCHours())+m+bl(bk.getUTCMinutes())+m+bl(bk.getUTCSeconds())+F+bm(bk.getUTCMilliseconds())+q:null;},__tY:function(bo){var bp={'\b':I,'\t':u,'\n':r,'\f':y,'\r':L,'"':G,'\\':x};var bq=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;bq.lastIndex=0;if(bq.test(bo)){return o+bo.replace(bq,function(a){var c=bp[a];return typeof c===W?c:ba+(X+a.charCodeAt(0).toString(16)).slice(-4);})+o;}else{return o+bo+o;}},parse:function(br,bs){var bt=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;bt.lastIndex=0;if(bt.test(br)){br=br.replace(bt,function(a){return ba+(X+a.charCodeAt(0).toString(16)).slice(-4);});}if(/^[\],:{}\s]*$/.test(br.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,H).replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,l).replace(/(?:^|:|,)(?:\s*\[)+/g,p))){var j=eval(K+br+D);return typeof bs===e?this.__ua({'':j},p,bs):j;}throw new SyntaxError(P);},__ua:function(bu,bv,bw){var bx=bu[bv];if(bx&&typeof bx===f){for(var k in bx){if(Object.hasOwnProperty.call(bx,k)){var v=this.__ua(bx,k,bw);if(v!==undefined){bx[k]=v;}else{delete bx[k];}}}}return bw.call(bu,bv,bx);}}});})();(function(){var a="qx.lang.Json";qx.Class.define(a,{statics:{JSON:(qx.lang.Type.getClass(window.JSON)=="JSON"&&JSON.parse('{"x":1}').x===1)?window.JSON:new qx.lang.JsonImpl(),stringify:null,parse:null},defer:function(b){b.stringify=b.JSON.stringify;b.parse=b.JSON.parse;}});})();(function(){var g="",f="<br",e=" &nbsp;",d="<br>",c=" ",b="\n",a="qx.bom.String";qx.Class.define(a,{statics:{TO_CHARCODE:{"quot":34,"amp":38,"lt":60,"gt":62,"nbsp":160,"iexcl":161,"cent":162,"pound":163,"curren":164,"yen":165,"brvbar":166,"sect":167,"uml":168,"copy":169,"ordf":170,"laquo":171,"not":172,"shy":173,"reg":174,"macr":175,"deg":176,"plusmn":177,"sup2":178,"sup3":179,"acute":180,"micro":181,"para":182,"middot":183,"cedil":184,"sup1":185,"ordm":186,"raquo":187,"frac14":188,"frac12":189,"frac34":190,"iquest":191,"Agrave":192,"Aacute":193,"Acirc":194,"Atilde":195,"Auml":196,"Aring":197,"AElig":198,"Ccedil":199,"Egrave":200,"Eacute":201,"Ecirc":202,"Euml":203,"Igrave":204,"Iacute":205,"Icirc":206,"Iuml":207,"ETH":208,"Ntilde":209,"Ograve":210,"Oacute":211,"Ocirc":212,"Otilde":213,"Ouml":214,"times":215,"Oslash":216,"Ugrave":217,"Uacute":218,"Ucirc":219,"Uuml":220,"Yacute":221,"THORN":222,"szlig":223,"agrave":224,"aacute":225,"acirc":226,"atilde":227,"auml":228,"aring":229,"aelig":230,"ccedil":231,"egrave":232,"eacute":233,"ecirc":234,"euml":235,"igrave":236,"iacute":237,"icirc":238,"iuml":239,"eth":240,"ntilde":241,"ograve":242,"oacute":243,"ocirc":244,"otilde":245,"ouml":246,"divide":247,"oslash":248,"ugrave":249,"uacute":250,"ucirc":251,"uuml":252,"yacute":253,"thorn":254,"yuml":255,"fnof":402,"Alpha":913,"Beta":914,"Gamma":915,"Delta":916,"Epsilon":917,"Zeta":918,"Eta":919,"Theta":920,"Iota":921,"Kappa":922,"Lambda":923,"Mu":924,"Nu":925,"Xi":926,"Omicron":927,"Pi":928,"Rho":929,"Sigma":931,"Tau":932,"Upsilon":933,"Phi":934,"Chi":935,"Psi":936,"Omega":937,"alpha":945,"beta":946,"gamma":947,"delta":948,"epsilon":949,"zeta":950,"eta":951,"theta":952,"iota":953,"kappa":954,"lambda":955,"mu":956,"nu":957,"xi":958,"omicron":959,"pi":960,"rho":961,"sigmaf":962,"sigma":963,"tau":964,"upsilon":965,"phi":966,"chi":967,"psi":968,"omega":969,"thetasym":977,"upsih":978,"piv":982,"bull":8226,"hellip":8230,"prime":8242,"Prime":8243,"oline":8254,"frasl":8260,"weierp":8472,"image":8465,"real":8476,"trade":8482,"alefsym":8501,"larr":8592,"uarr":8593,"rarr":8594,"darr":8595,"harr":8596,"crarr":8629,"lArr":8656,"uArr":8657,"rArr":8658,"dArr":8659,"hArr":8660,"forall":8704,"part":8706,"exist":8707,"empty":8709,"nabla":8711,"isin":8712,"notin":8713,"ni":8715,"prod":8719,"sum":8721,"minus":8722,"lowast":8727,"radic":8730,"prop":8733,"infin":8734,"ang":8736,"and":8743,"or":8744,"cap":8745,"cup":8746,"int":8747,"there4":8756,"sim":8764,"cong":8773,"asymp":8776,"ne":8800,"equiv":8801,"le":8804,"ge":8805,"sub":8834,"sup":8835,"sube":8838,"supe":8839,"oplus":8853,"otimes":8855,"perp":8869,"sdot":8901,"lceil":8968,"rceil":8969,"lfloor":8970,"rfloor":8971,"lang":9001,"rang":9002,"loz":9674,"spades":9824,"clubs":9827,"hearts":9829,"diams":9830,"OElig":338,"oelig":339,"Scaron":352,"scaron":353,"Yuml":376,"circ":710,"tilde":732,"ensp":8194,"emsp":8195,"thinsp":8201,"zwnj":8204,"zwj":8205,"lrm":8206,"rlm":8207,"ndash":8211,"mdash":8212,"lsquo":8216,"rsquo":8217,"sbquo":8218,"ldquo":8220,"rdquo":8221,"bdquo":8222,"dagger":8224,"Dagger":8225,"permil":8240,"lsaquo":8249,"rsaquo":8250,"euro":8364},escape:function(h){return qx.util.StringEscape.escape(h,qx.bom.String.FROM_CHARCODE);},unescape:function(i){return qx.util.StringEscape.unescape(i,qx.bom.String.TO_CHARCODE);},fromText:function(j){return qx.bom.String.escape(j).replace(/( |\n)/g,function(k){var l={" ":e,"\n":d};return l[k]||k;});},toText:function(m){return qx.bom.String.unescape(m.replace(/\s+|<([^>])+>/gi,function(n){if(n.indexOf(f)===0){return b;}else if(n.length>0&&n.replace(/^\s*/,g).replace(/\s*$/,g)==g){return c;}else{return g;}}));}},defer:function(o){o.FROM_CHARCODE=qx.lang.Object.invert(o.TO_CHARCODE);}});})();(function(){var g=";",f="&",e='X',d="",c='#',b="&#",a="qx.util.StringEscape";qx.Class.define(a,{statics:{escape:function(h,j){var m,o=d;for(var i=0,l=h.length;i<l;i++){var n=h.charAt(i);var k=n.charCodeAt(0);if(j[k]){m=f+j[k]+g;}else{if(k>0x7F){m=b+k+g;}else{m=n;}}o+=m;}return o;},unescape:function(p,q){return p.replace(/&[#\w]+;/gi,function(r){var s=r;var r=r.substring(1,r.length-1);var t=q[r];if(t){s=String.fromCharCode(t);}else{if(r.charAt(0)==c){if(r.charAt(1).toUpperCase()==e){t=r.substring(2);if(t.match(/^[0-9A-Fa-f]+$/gi)){s=String.fromCharCode(parseInt(t,16));}}else{t=r.substring(1);if(t.match(/^\d+$/gi)){s=String.fromCharCode(parseInt(t,10));}}}}return s;});}}});})();(function(){var bU="",bT='</div>',bS='<div class="item-detail-text">',bR='<div class="item-detail-headline">',bQ="#",bP='</td>',bO="'",bN="(",bM='">',bL=" ",bv=".",bu=",'",bt=")",bs=".toggleShowItemDetails('",br='"',bq="&nbsp;",bp='<div class="item-detail-error">',bo="none",bn="</p>",bm='" onclick="',cc=')">',cd="properties",ca='>',cb="events",bX="methods",bY="mixin",bV='.togglePanelVisibility(',bW='</span>',ce="apiviewer.ObjectRegistry.getObjectFromHashCode('",cf='<td class="type">',bE='<td class="toggle">',bD="apiviewer/image/open.gif",bG='<div class="info-panel"><h2>',bF="apiviewer.dao.Node",bI="Inherited from:",bH='open.gif',bK='\'); return false;"',bJ=' title="',bC='//',bB="</span>",a="'>",b="Documentation errors:",c="<span class='",d='package',e='#',f='" onmouseup="apiviewer.TabViewController.instance.onSelectItem(\'',g='" href="',h="Included from mixin:",k=' onclick="',m=", Column:",cj="; ",ci="&#160;",ch="margin-left:18px;",cg='<td class="text">',cn=" <br/>",cm="See also:",cl="Deprecated:",ck='<a style="',cp='<img src="',co=" is deprecated!",L='apiviewer/image/',M='apiviewer/image/open.gif',J="[]",K="apiviewer.ui.panels.InfoPanel",P='close.gif',Q="_itemName",N='<',O='" alt="',H="Boolean",I="Line: ",u='<h3',t="This ",w='</h2><div></div></div>',v='<span onclick="',q="item-private",p="class",s="item-internal",r="Access:",o="interface",n='title="',V='<td class="icon" ',W='" onclick="return false;"',X='</h3>',Y="')",R=" | ",S=", ",T="private",U="Element",ba='<tr class="',bb='apiviewer/image/close.gif',E='</tr>',D="item-deprecated",C="item-protected",B='<div _itemName="',A='',z='</a></span>',y="qx.client",x="Required by:",G=')"/>',F="overlay_",bc='<img class="openclose" src="',bd="String",be="Overrides:",bf="_applyElement",bg="internal",bh='<span style="white-space: nowrap;">',bi="TBODY",bj='<div class="item-desc">',bk='<table cellspacing="0" cellpadding="0" class="info" width="100%">',bl=')"/> ',bz="abstract",by="protected",bx="webkit",bw='</table>',bA="undefined";qx.Class.define(K,{type:bz,extend:qx.core.Object,construct:function(cq,cr){qx.core.Object.call(this);this.setListName(cq);this._labelText=cr;apiviewer.ObjectRegistry.register(this);},properties:{element:{check:U,init:null,nullable:true,apply:bf},listName:{check:bd},isOpen:{check:H,init:true},docNode:{check:bF,nullable:true}},statics:{ITEM_SPEC_REGEX:/^(([\w\.]+)?(#\w+(\([^\)]*\))?)?)(\s+(.*))?$/,SENTENCE_END_REGEX:/[^\.].\.(\s|<)/,resolveLinkAttributes:function(cs,ct){var cw=/\{@link([^\}]*)\}/mg;var cv=new qx.util.StringBuilder();var cu;var cx=0;while((cu=cw.exec(cs))!=null){cv.add(cs.substring(cx,cu.index)+this.createItemLinkHtml(cu[1],ct));cx=cu.index+cu[0].length;}cv.add(cs.substring(cx,cs.length));return cv.get();},createItemLinkHtml:function(cy,cz,cA,cB){if(cA==null){cA=true;}cy=qx.lang.String.trim(cy);if(cy.charAt(0)==br||cy.charAt(0)==N){return cy;}else{var cE=this.ITEM_SPEC_REGEX.exec(cy);if(cE==null){return cy;}else{var cK=cE[2];var cS=cE[3];var cJ=cE[6];var cD=bU;if(cK==null||cK.length==0){cK=cz.getFullName();}else if(cz&&cK.indexOf(bv)==-1){var name=cz.getName();if(cz instanceof apiviewer.dao.Package){var cG=cz.getFullName();}else{var cQ=cz.getFullName();var cG=cQ.substring(0,cQ.length-name.length-1);}cK=cG+bv+cK;}if(cJ==null||cJ.length==0){cJ=cE[1];}if(cA){var cO=apiviewer.dao.Class.getClassByName(cK);if(cO){var cT;if(cS){var cI=cS.substring(1);var cM=cI.indexOf(bN);if(cM!=-1){cI=qx.lang.String.trim(cI.substring(0,cM));}cT=this.__St(cI,cO);}else{cT=cO;}if(cT){if(cT.getNodeType()!==d){cK=cT.getClass().getFullName();}var cL=apiviewer.TreeUtil.getIconUrl(cT);var cC=apiviewer.ui.ClassViewer.createImageHtml(cL);if(qx.core.Variant.isSet(y,bx)){if(cC.indexOf(F)!==-1){cD=ch;}}}}}var cR=cK+(cS?cS:bU);var cP,cH,cN;if(qx.bom.client.Engine.OPERA&&qx.bom.client.Engine.VERSION>9){cP=location.protocol;cH=location.host;cN=location.pathname;}else{cP=window.location.protocol;cH=window.location.host;cN=window.location.pathname;}var cF=[bh,(typeof cC!=bA?cC:bU),ck+cD+g+cP,bC,cH,cN,e,cR,W,f,cR,bK,bJ,cR,bM,cJ,z];return cF.join(bU);}}},createSeeAlsoHtml:function(cU){var cV=cU.getSee();if(cV.length>0){var cX=new qx.util.StringBuilder();for(var i=0;i<cV.length;i++){if(cX.length!=0){cX.add(S);}cX.add(this.createItemLinkHtml(cV[i],cU.getClass()));}if(!cX.isEmpty()){var cW=new qx.util.StringBuilder();cW.add(bR,cm,bT,bS,cX,bT);return cW.get();}}return bU;},createInheritedFromHtml:function(cY,da){if(cY.getClass().getType()!=bY&&cY.getClass()!=da){var db=new qx.util.StringBuilder(bR,bI,bT,bS,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(cY.getClass().getFullName()+bQ+cY.getName()),bT);return db.get();}else{return bU;}},createOverwriddenFromHtml:function(dc){if(dc.getOverriddenFrom()){var dd=new qx.util.StringBuilder(bR,be,bT,bS,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(dc.getOverriddenFrom().getFullName()+bQ+dc.getName()),bT);return dd.get();}else{return bU;}},createIncludedFromHtml:function(de,df){if(de.getClass()!=df){if(de.getClass().getType()==bY){var dg=new qx.util.StringBuilder(bR,h,bT,bS,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(de.getClass().getFullName()+bQ+de.getName()),bT);return dg.get();}}else{return bU;}},__St:function(dh,di){var dk=di.getItem(dh);if(dk){return dk;}else{var dl=di.getClassHierarchy();for(var i=0,l=dl.length;i<l;i++){var dj=dl[i];dk=dj.getItem(dh);if(dk){break;}}return dk;}},createDescriptionHtml:function(dm,dn,dp){var dq=dm.getDescription();if(dq){if(!dp){dq=this.__Su(dq);}return bj+this.resolveLinkAttributes(dq,dn)+bT;}else{return bU;}},__Su:function(dr){var du=dr;var dt=du.indexOf(bn);if(dt!=-1){du=du.substr(0,dt+4);var ds=this.SENTENCE_END_REGEX.exec(du);if(ds!=null){du=dr.substring(0,ds.index+ds[0].length-1)+bn;}}return du;},descriptionHasDetails:function(dv){var dw=dv.getDescription();if(dw){return this.__Su(dw)!=dw;}else{return false;}},createTypeHtml:function(dx,dy,dz){if(dz==null){dz=true;}var dF=[];var dA,dB,dC;if(dx){dF=dx.getTypes();}var dD=new qx.util.StringBuilder();if(dF.length==0){dD.add(dy);}else{if(dF.length>1){dD.add(bN);}for(var j=0;j<dF.length;j++){if(j>0){dD.add(R);}dB=dF[j].type;dA=dF[j].dimensions;if(apiviewer.ui.ClassViewer.PRIMITIVES[dB]){dD.add(dB);}else{dC=dB;if(dz){var dE=dB.lastIndexOf(bv);if(dE!=-1){dC+=bL+dB.substring(dE+1);}}dD.add(apiviewer.ui.panels.InfoPanel.createItemLinkHtml(dC,dx.getClass(),false,true));}if(dA){for(var i=0;i<parseInt(dA);i++){dD.add(J);}}}if(dF.length>1){dD.add(bt);}}return dD.get();},createErrorHtml:function(dG,dH){var dI=dG.getDocNode();var dJ=dI.getErrors();if(dJ.length>0){var dK=new qx.util.StringBuilder(bp,b,bT);for(var i=0;i<dJ.length;i++){dK.add(bS,dJ[i].attributes.msg,cn);dK.add(bN);if(dG.getClass()!=dH){dK.add(dG.getClass().getFullName(),cj);}dK.add(I,dJ[i].attributes.line,m,dJ[i].attributes.column+bt,bT);}return dK.get();}else{return bU;}},createDeprecationHtml:function(dL,dM){if(!dL.isDeprecated()){return bU;}var dN=new qx.util.StringBuilder();dN.add(bp,cl,bT);dN.add(bS);var dO=dL.getDeprecationText();if(dO){dN.add(dO);}else{dN.add(t,dM,co);}dN.add(bT);return dN.get();},createAccessHtml:function(dP){if(dP.isPublic()){return bU;}var dR=new qx.util.StringBuilder();dR.add(bR,r,bT);dR.add(bS);var dQ=[];if(dP.isPrivate()){dQ.push(T);}if(dP.isInternal()){dQ.push(bg);}if(dP.isProtected()){dQ.push(by);}dR.add(dQ.join(bL));dR.add(bT);return dR.get();},createInfoRequiredByHtml:function(dS){var dU=new qx.util.StringBuilder();var dT=dS.getRequiredBy();if(dT.length>0){dU.add(bR,x,bT);for(var i=0;i<dT.length;i++){dU.add(bS,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(dT[i].getFullName()+bQ+dS.getName()),bT);}}return dU.get();},setTitleClass:function(dV,dW){var dX=[c,bU,a,dW,bB];dX[1]=this.getItemCssClasses(dV);return dX.join(bU);},getItemCssClasses:function(dY){var ea=[];if(dY.isDeprecated()){ea.push(D);}if(dY.isPrivate()){ea.push(q);}if(dY.isInternal()){ea.push(s);}if(dY.isProtected()){ea.push(C);}return ea.join(bL);}},members:{canDisplayItem:function(eb){return (eb.getListName()==this.getListName());},getItemTypeHtml:function(ec,ed){throw new Error("Abstract method called!");},getItemTitleHtml:function(ee,ef){throw new Error("Abstract method called!");},getItemTextHtml:function(eg,eh,ei){throw new Error("Abstract method called!");},getItemTooltip:function(ej,ek){return bU;},getItemHtml:function(el,em,en){if((el instanceof apiviewer.dao.Class)||el instanceof apiviewer.dao.Package){var es=el.getPackage();}else{var es=el.getClass();}var er=new qx.util.StringBuilder();var et=(es!=em)&&es.getType()==p;var eq=apiviewer.TreeUtil.getIconUrl(el,et);er.add(ba,apiviewer.ui.panels.InfoPanel.getItemCssClasses(el),bM);var eu=this.getItemTooltip(el,em);var ep=eu?n+eu+O+eu+br:A;er.add(V,ep,ca,apiviewer.ui.ClassViewer.createImageHtml(eq),bP);var eo=this.getItemTypeHtml(el,em);er.add(cf,((eo)?(eo+bq):bq),bP);er.add(bE);if(this.itemHasDetails(el,em)){er.add(cp,qx.util.ResourceManager.getInstance().toUri(bD),bm,this.__Sv(this),bs,el.getName(),bO,((es!=em)?bu+es.getFullName()+bO:bU),G);}else{er.add(ci);}er.add(bP);er.add(cg);er.add(u);if(this.itemHasDetails(el,em)){er.add(k,this.__Sv(this),bs,el.getName(),bO,((es!=em)?bu+es.getFullName()+bO:bU),cc);}else{er.add(ca);}er.add(this.getItemTitleHtml(el,em));er.add(X);er.add(B,el.getName(),bM);er.add(this.getItemTextHtml(el,em,en));er.add(bT);er.add(bP);er.add(E);return er.get();},itemHasDetails:qx.lang.Function.returnTrue,__Sv:function(ev){return ce+ev.toHashCode()+Y;},getPanelHtml:function(ew){var ey=this._labelText.charAt(0).toUpperCase()+this._labelText.substring(1);var ex=new qx.util.StringBuilder(bG);ex.add(bc,qx.util.ResourceManager.getInstance().toUri(L+(this.getIsOpen()?P:bH)),bm,this.__Sv(ew),bV+this.__Sv(this),bl,v,this.__Sv(ew),bV,this.__Sv(this),cc,ey,bW);ex.add(w);return ex.get();},_getPanelItems:function(ez,eA){if(!eA){return [];}var eB=this.getListName();var eD=[];var eG={};if(ez&&(eB==cb||eB==cd||eB==bX)){if(eA.getType()==o){var eE=eA.getInterfaceHierarchy();}else{var eE=eA.getClassHierarchy();}}else{eE=[eA];}for(var eH=0;eH<eE.length;eH++){var eF=eE[eH];var eC=eF.getItemList(eB);if(eB==cb||eB==cd||eB==bX){qx.lang.Array.append(eC,eF.getNodesOfTypeFromMixins(this.getListName()));}for(var i=0;i<eC.length;i++){var name=eC[i].getName();if(!(Object.prototype.hasOwnProperty.call(eG,name))){eG[name]=eF;eD.push(eC[i]);}}}return eD;},__Sw:function(eI,eJ,eK,eL,eM){var eO=eI.concat();for(var i=eI.length-1;i>=0;i--){var eN=eI[i];if(eN.isPropertyGenerated()&&!eJ){qx.lang.Array.removeAt(eO,i);}else if(eN.isPrivate()&&!eL){qx.lang.Array.removeAt(eO,i);}else if(eN.isProtected()&&!eK){qx.lang.Array.removeAt(eO,i);}else if(eN.isInternal()&&!eM){qx.lang.Array.removeAt(eO,i);}}return eO;},_sortItems:function(eP){eP.sort(function(eQ,eR){var eU=0;if(eQ.isInternal()){eU+=4;}if(eQ.isPrivate()){eU+=2;}if(eQ.isProtected()){eU+=1;}var eT=0;if(eR.isInternal()){eT+=4;}if(eR.isPrivate()){eT+=2;}if(eR.isProtected()){eT+=1;}if(eU==eT){var eV=eQ.getName();var eS=eR.getName();return eV.toLowerCase()<eS.toLowerCase()?-1:1;}else{return eU-eT;}});},_displayNodes:function(eW,eX){if(eW&&eW.length>0){var eY=new qx.util.StringBuilder(bk);for(var i=0;i<eW.length;i++){eY.add(this.getItemHtml(eW[i],eX,false));}eY.add(bw);this.getBodyElement().innerHTML=eY.get();apiviewer.ui.AbstractViewer.fixLinks(this.getBodyElement());apiviewer.ui.AbstractViewer.highlightCode(this.getBodyElement());this.getBodyElement().style.display=!this.getIsOpen()?bo:bU;this.getElement().style.display=bU;}else{this.getElement().style.display=bo;}},update:function(fa,fb){if(!this.getElement()){return;}this.setDocNode(fb);var ff=fa.getShowInherited();var fc=this._getPanelItems(ff,fb);if(fc&&fc.length>0){var fh=fa.getExpandProperties();var fd=fa.getShowProtected();var fg=fa.getShowPrivate();var fe=fg;fc=this.__Sw(fc,fh,fd,fg,fe);this._sortItems(fc);}this._displayNodes(fc,fb);},_applyElement:function(fi){this._titleElement=fi.firstChild;this._bodyElement=fi.lastChild;},getTitleElement:function(){return this._titleElement;},getBodyElement:function(){return this._bodyElement;},getItemElement:function(name){var fj=this.getBodyElement().getElementsByTagName(bi)[0].childNodes;for(var i=0;i<fj.length;i++){if(fj[i].childNodes[3].childNodes[1].getAttribute(Q)==name){return fj[i].childNodes[3].childNodes[1];}}},toggleShowItemDetails:function(fk,fl){try{var fn=this.getItemElement(fk);if(!fn){throw Error("Element for name '"+fk+"' not found!");}var fm=fn._showDetails?!fn._showDetails:true;fn._showDetails=fm;if(fl){var fq=apiviewer.dao.Class.getClassByName(fl);}else{fq=this.getDocNode();}var fo=fq.getItemByListAndName(this.getListName(),fk);var fp=fn.parentNode.previousSibling.firstChild;fp.src=qx.util.ResourceManager.getInstance().toUri(fm?bb:M);fn.innerHTML=this.getItemTextHtml(fo,this.getDocNode(),fm);apiviewer.ui.AbstractViewer.fixLinks(fn);apiviewer.ui.AbstractViewer.highlightCode(fn);}catch(fr){this.error("Toggling item details failed");this.error(fr);}}},destruct:function(){this._titleElement=this._bodyElement=null;}});})();(function(){var k='</div>',j='<div class="item-detail-text">',h='<div class="item-detail-headline">',g='</span>',f="var",e='<span class="parameter-type">',d=" ",c="function",b='</span> <code>',a="<code>",D="Parameters:",C="Throws:",B="Apply method of property:",A='</code>',z=") ",y="</code>",x="apiviewer.ui.panels.MethodPanel",w="void",v='<span class="method-signature"><span class="parenthesis">(</span>',u="Returns:",r=" (default: ",s="[]",p='<span class="separator">,</span> ',q='<span class="parenthesis">)</span></span>',n="Creates a new instance of ",o='<span class="item-detail-optional">',l="?",m="abstract ",t=".";qx.Class.define(x,{extend:apiviewer.ui.panels.InfoPanel,members:{getItemTitleHtml:function(E){if(E.isConstructor()){var I=E.getClass().getName();}else{I=E.getName();}var F=new qx.util.StringBuilder(apiviewer.ui.panels.InfoPanel.setTitleClass(E,I));F.add(v);var G=E.getParams();for(var i=0;i<G.length;i++){var H=G[i];if(i!=0){F.add(p);}F.add(e,apiviewer.ui.panels.InfoPanel.createTypeHtml(H,f),b,H.getName(),A);if(H.getDefaultValue()){F.add(l);}}F.add(q);return F.get();},getItemTypeHtml:function(J){var K=new qx.util.StringBuilder();if(J.isAbstract()){K.add(m);}if(!J.isConstructor()){K.add(apiviewer.ui.panels.InfoPanel.createTypeHtml(J.getDocNode().getReturn(),w));}return K.get();},getItemTextHtml:function(L,M,N){var U=L.getClass();var X=new qx.util.StringBuilder();if(L.isConstructor()&&!L.getDescription()){X.add(n,U.getName(),t);}else{X.add(apiviewer.ui.panels.InfoPanel.createDescriptionHtml(L,U,N));}if(N){var V=L.getDocNode().getParams();if(V.length>0){X.add(h,D,k);for(var i=0;i<V.length;i++){var R=V[i];var O=R.getType()?R.getType():f;var T=R.getArrayDimensions();if(T){for(var i=0;i<T;i++){O+=s;}}var Y=R.getDefaultValue();X.add(j);if(Y){X.add(o);}X.add(a,R.getName(),y);if(Y){X.add(r,Y,z,g);}var ba=R.getDescription();if(ba){X.add(d,apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(ba,U));}X.add(k);}}var P=L.getDocNode().getReturn();if(P){var ba=P.getDescription();if(ba){X.add(h,u,k,j,apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(ba,U),k);}}if(L.getApply()){X.add(h,B,k,j,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(L.getApply(),L.getClass(),true,true),k);}var S=L.getDocNode().getThrows();if(S.length>0){X.add(h,C,k);for(var i=0;i<S.length;i++){var W=S[i];var Q=W.getType()?W.getType():W.getDefaultType();X.add(j);X.add(e,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(Q),g);var ba=W.getDescription();if(ba){X.add(d,apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(ba,U));}X.add(k);}}X.add(apiviewer.ui.panels.InfoPanel.createAccessHtml(L));X.add(apiviewer.ui.panels.InfoPanel.createIncludedFromHtml(L,M));X.add(apiviewer.ui.panels.InfoPanel.createOverwriddenFromHtml(L));X.add(apiviewer.ui.panels.InfoPanel.createInheritedFromHtml(L,M));X.add(apiviewer.ui.panels.InfoPanel.createInfoRequiredByHtml(L));X.add(apiviewer.ui.panels.InfoPanel.createSeeAlsoHtml(L));X.add(apiviewer.ui.panels.InfoPanel.createErrorHtml(L,M));X.add(apiviewer.ui.panels.InfoPanel.createDeprecationHtml(L,c));}return X.get();},itemHasDetails:function(bb,bc){var bd=bb.getDocNode();var be=bd.getReturn()&&bd.getReturn().getDescription();return (bb.getClass()!=bc||bb.getOverriddenFrom()!=null||bb.getRequiredBy().length>0||bd.getParams().length>0||bd.getThrows().length>0||be||bb.getSee().length>0||bb.getErrors().length>0||bb.isDeprecated()||bb.getApply()||apiviewer.ui.panels.InfoPanel.descriptionHasDetails(bb));}}});})();(function(){var h="",g="deprecated",f="internal",e="protected",d="errors",c="apiviewer.dao.Node",b="string",a="private";qx.Class.define(c,{extend:qx.core.Object,construct:function(j){qx.core.Object.call(this);this._docNode=j;j.children=j.children||[];j.attributes=j.attributes||{};j.cls=this;this._initializeFields();for(var i=0;i<j.children.length;i++){var k=j.children[i];if(!this._addChildNode(k)){throw new Error("Unknown child type: "+k.type+" node: "+qx.util.Json.stringify(k));}}},members:{getNode:function(){return this._docNode;},getNodeType:function(){return this._docNode.type;},getErrors:function(){return this._errors;},getDeprecationText:function(){return this._deprecated||h;},isDeprecated:function(){return typeof (this._deprecated)==b?true:false;},isInternal:function(){return this._docNode.attributes.access==f;},isPrivate:function(){return this._docNode.attributes.access==a;},isProtected:function(){return this._docNode.attributes.access==e;},isPropertyGenerated:function(){return this._docNode.attributes.fromProperty!=null;},isPublic:function(){return (!this.isPrivate()&&!this.isProtected()&&!this.isInternal());},hasWarning:function(){return this._docNode.attributes.hasWarning||false;},_createNodeList:function(l,m,n,o){if(m){var p=[];for(var i=0;i<l.children.length;i++){p.push(new m(l.children[i],n,o));}return p;}else{return l.children;}},_initializeFields:function(){this._errors=[];},_addChildNode:function(q){switch(q.type){case g:this._deprecated=q.children?q.children[0].attributes.text||h:h;break;case d:this._errors=this._createNodeList(q);break;default:return false;}return true;}},destruct:function(){this._docNode=this._errors=null;}});})();(function(){var k="",h="getClasses",g="getPackages",f="functions",e="getFunctions",d="packages",c="desc",b="classes",a="apiviewer.dao.Package";qx.Class.define(a,{extend:apiviewer.dao.Node,construct:function(l,m){apiviewer.dao.Node.call(this,l);this._package=m;apiviewer.dao.Class.registerClass(this);},members:{getName:function(){return this._docNode.attributes.name;},getFullName:function(){return this._docNode.attributes.fullName||k;},getDescription:function(){return this._desc||k;},getClasses:function(){return this._classes;},getFunctions:function(){return this._functions;},getPackages:function(){return this._packages;},getPackage:function(){return this._package;},addClass:function(n){var o=n.getFullName();var p=this.getClasses();for(var i=0;i<p.length;i++){if(p[i].getFullName()==o){p[i]=n;return;}}p.push(n);},getItem:function(q){var r=[h,g];for(var i=0;i<r.length;i++){var s=this[r[i]]();for(var j=0;j<s.length;j++){if(q==s[j].getName()){return s[j];}}}},getItemList:function(t){var u={"classes":h,"packages":g,"functions":e};return this[u[t]]();},getItemByListAndName:function(v,w){var x=this.getItemList(v);for(var j=0;j<x.length;j++){if(w==x[j].getName()){return x[j];}}},_initializeFields:function(){apiviewer.dao.Node.prototype._initializeFields.call(this);this._classes=[];this._packages=[];this._functions=[];},_addChildNode:function(y){switch(y.type){case b:this._classes=this._createNodeList(y,apiviewer.dao.Class,this);break;case f:this._functions=this._createNodeList(y,apiviewer.dao.Method,this);break;case d:this._packages=this._createNodeList(y,apiviewer.dao.Package,this);break;case c:this._desc=y.attributes.text||k;break;default:return apiviewer.dao.Node.prototype._addChildNode.call(this,y);}return true;}},destruct:function(){this._package=this._classes=this._functions=this._packages=null;}});})();(function(){var n=",",m="",k="string",j="null",h='"',g=':',f="qx.jsonDebugging",e='-',d='\\u00',c="__qL",N="new Date(Date.UTC(",M='\\\\',L='\\f',K='\\"',J='Z',I="))",H="__qB",G="__qD",F="}",E='(',u='.',v="{",s='\\r',t=":",q='\\t',r="]",o="[",p="__qE",w="qx.jsonEncodeUndefined",x='T',z='\\b',y="__qC",B="qx.util.Json",A=')',D='\\n',C="__qM";qx.Class.define(B,{statics:{__qz:null,BEAUTIFYING_INDENT:" ",BEAUTIFYING_LINE_END:"\n",CONVERT_DATES:null,__qA:{"function":H,"boolean":y,"number":G,"string":p,"object":c,"undefined":C},__qB:function(O,P){return String(O);},__qC:function(Q,R){return String(Q);},__qD:function(S,T){return isFinite(S)?String(S):j;},__qE:function(U,V){var W;if(/["\\\x00-\x1f]/.test(U)){W=U.replace(/([\x00-\x1f\\"])/g,qx.util.Json.__qG);}else{W=U;}return h+W+h;},__qF:{'\b':z,'\t':q,'\n':D,'\f':L,'\r':s,'"':K,'\\':M},__qG:function(a,b){var X=qx.util.Json.__qF[b];if(X){return X;}X=b.charCodeAt();return d+Math.floor(X/16).toString(16)+(X%16).toString(16);},__qH:function(Y,ba){var bc=[],bf=true,be,bb;var bd=qx.util.Json.__qO;bc.push(o);if(bd){qx.util.Json.__qI+=qx.util.Json.BEAUTIFYING_INDENT;bc.push(qx.util.Json.__qI);}for(var i=0,l=Y.length;i<l;i++){bb=Y[i];be=this.__qA[typeof bb];if(be){bb=this[be](bb,i+m);if(typeof bb==k){if(!bf){bc.push(n);if(bd){bc.push(qx.util.Json.__qI);}}bc.push(bb);bf=false;}}}if(bd){qx.util.Json.__qI=qx.util.Json.__qI.substring(0,qx.util.Json.__qI.length-qx.util.Json.BEAUTIFYING_INDENT.length);bc.push(qx.util.Json.__qI);}bc.push(r);return bc.join(m);},__qJ:function(bg,bh){if(!qx.util.Json.CONVERT_DATES){if(bg.toJSON&&!qx.bom.client.Engine.OPERA){return bg.toJSON();}var bi=qx.util.format.NumberFormat.getInstance();bi.setMinimumIntegerDigits(2);var bk=bg.getUTCFullYear()+e+bi.format(bg.getUTCMonth()+1)+e+bi.format(bg.getUTCDate())+x+bi.format(bg.getUTCHours())+g+bi.format(bg.getUTCMinutes())+g+bi.format(bg.getUTCSeconds())+u;bi.setMinimumIntegerDigits(3);return bk+bi.format(bg.getUTCMilliseconds())+J;}else{var bj=bg.getUTCFullYear()+n+bg.getUTCMonth()+n+bg.getUTCDate()+n+bg.getUTCHours()+n+bg.getUTCMinutes()+n+bg.getUTCSeconds()+n+bg.getUTCMilliseconds();return N+bj+I;}},__qK:function(bl,bm){var bp=[],br=true,bo,bn;var bq=qx.util.Json.__qO;bp.push(v);if(bq){qx.util.Json.__qI+=qx.util.Json.BEAUTIFYING_INDENT;bp.push(qx.util.Json.__qI);}for(var bm in bl){bn=bl[bm];bo=this.__qA[typeof bn];if(bo){bn=this[bo](bn,bm);if(typeof bn==k){if(!br){bp.push(n);if(bq){bp.push(qx.util.Json.__qI);}}bp.push(this.__qE(bm),t,bn);br=false;}}}if(bq){qx.util.Json.__qI=qx.util.Json.__qI.substring(0,qx.util.Json.__qI.length-qx.util.Json.BEAUTIFYING_INDENT.length);bp.push(qx.util.Json.__qI);}bp.push(F);return bp.join(m);},__qL:function(bs,bt){if(bs){if(qx.lang.Type.isFunction(bs.toJSON)&&bs.toJSON!==this.__qz){return this.__qN(bs.toJSON(bt),bt);}else if(qx.lang.Type.isDate(bs)){return this.__qJ(bs,bt);}else if(qx.lang.Type.isArray(bs)){return this.__qH(bs,bt);}else if(qx.lang.Type.isObject(bs)){return this.__qK(bs,bt);}return m;}return j;},__qM:function(bu,bv){if(qx.core.Setting.get(w)){return j;}},__qN:function(bw,bx){return this[this.__qA[typeof bw]](bw,bx);},stringify:function(by,bz){this.__qO=bz;this.__qI=this.BEAUTIFYING_LINE_END;var bA=this.__qN(by,m);if(typeof bA!=k){bA=null;}if(qx.core.Setting.get(f)){qx.log.Logger.debug(this,"JSON request: "+bA);}return bA;},parse:function(bB,bC){if(bC===undefined){bC=true;}if(qx.core.Setting.get(f)){qx.log.Logger.debug(this,"JSON response: "+bB);}if(bC){if(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(bB.replace(/"(\\.|[^"\\])*"/g,m))){throw new Error("Could not parse JSON string!");}}try{var bD=(bB&&bB.length>0)?eval(E+bB+A):null;return bD;}catch(bE){throw new Error("Could not evaluate JSON string: "+bE.message);}}},settings:{"qx.jsonEncodeUndefined":true,"qx.jsonDebugging":false},defer:function(bF){bF.__qz=Date.prototype.toJSON;}});})();(function(){var a="qx.util.format.IFormat";qx.Interface.define(a,{members:{format:function(b){},parse:function(c){}}});})();(function(){var t="",s="Number",r="-",q="0",p="String",o="changeNumberFormat",n='(',m="g",l="Boolean",k="$",d="NaN",j='([0-9]{1,3}(?:',g='{0,1}[0-9]{3}){0,})',c='\\d+){0,1}',b="qx.util.format.NumberFormat",f="Infinity",e="^",h=".",a="-Infinity",i='([-+]){0,1}';qx.Class.define(b,{extend:qx.core.Object,implement:qx.util.format.IFormat,construct:function(u){qx.core.Object.call(this);this.__ro=u;},statics:{getIntegerInstance:function(){var v=qx.util.format.NumberFormat;if(v._integerInstance==null){v._integerInstance=new v();v._integerInstance.setMaximumFractionDigits(0);}return v._integerInstance;},getInstance:function(){if(!this._instance){this._instance=new this;}return this._instance;}},properties:{minimumIntegerDigits:{check:s,init:0},maximumIntegerDigits:{check:s,nullable:true},minimumFractionDigits:{check:s,init:0},maximumFractionDigits:{check:s,nullable:true},groupingUsed:{check:l,init:true},prefix:{check:p,init:t,event:o},postfix:{check:p,init:t,event:o}},members:{__ro:null,format:function(w){switch(w){case Infinity:return f;case -Infinity:return a;case NaN:return d;}var A=(w<0);if(A){w=-w;}if(this.getMaximumFractionDigits()!=null){var H=Math.pow(10,this.getMaximumFractionDigits());w=Math.round(w*H)/H;}var G=String(Math.floor(w)).length;var x=t+w;var D=x.substring(0,G);while(D.length<this.getMinimumIntegerDigits()){D=q+D;}if(this.getMaximumIntegerDigits()!=null&&D.length>this.getMaximumIntegerDigits()){D=D.substring(D.length-this.getMaximumIntegerDigits());}var C=x.substring(G+1);while(C.length<this.getMinimumFractionDigits()){C+=q;}if(this.getMaximumFractionDigits()!=null&&C.length>this.getMaximumFractionDigits()){C=C.substring(0,this.getMaximumFractionDigits());}if(this.getGroupingUsed()){var z=D;D=t;var F;for(F=z.length;F>3;F-=3){D=t+qx.locale.Number.getGroupSeparator(this.__ro)+z.substring(F-3,F)+D;}D=z.substring(0,F)+D;}var B=this.getPrefix()?this.getPrefix():t;var y=this.getPostfix()?this.getPostfix():t;var E=B+(A?r:t)+D;if(C.length>0){E+=t+qx.locale.Number.getDecimalSeparator(this.__ro)+C;}E+=y;return E;},parse:function(I){var N=qx.lang.String.escapeRegexpChars(qx.locale.Number.getGroupSeparator(this.__ro)+t);var L=qx.lang.String.escapeRegexpChars(qx.locale.Number.getDecimalSeparator(this.__ro)+t);var J=new RegExp(e+qx.lang.String.escapeRegexpChars(this.getPrefix())+i+j+N+g+n+L+c+qx.lang.String.escapeRegexpChars(this.getPostfix())+k);var M=J.exec(I);if(M==null){throw new Error("Number string '"+I+"' does not match the number format");}var O=(M[1]==r);var Q=M[2];var P=M[3];Q=Q.replace(new RegExp(N,m),t);var K=(O?r:t)+Q;if(P!=null&&P.length!=0){P=P.replace(new RegExp(L),t);K+=h+P;}return parseFloat(K);}}});})();(function(){var d="cldr_number_decimal_separator",c="cldr_number_percent_format",b="qx.locale.Number",a="cldr_number_group_separator";qx.Class.define(b,{statics:{getDecimalSeparator:function(e){return qx.locale.Manager.getInstance().localize(d,[],e);},getGroupSeparator:function(f){return qx.locale.Manager.getInstance().localize(a,[],f);},getPercentFormat:function(g){return qx.locale.Manager.getInstance().localize(c,[],g);}}});})();(function(){var m="",k=",",h="constructor",g="appearances",f="getAppearances",e="getStatics",d="getChildControls",c="constants",b="getProperties",a="methods",D="properties",C="getEvents",B="getMembers",A="events",z="methods-static",y="getConstants",x="apiviewer.dao.Class",w="superMixins",v="childControls",u="class",s="_constructor",t="desc",q="see",r="getConstructor",o="getSuperInterfaces",p="superInterfaces",n="getSuperMixins";qx.Class.define(x,{extend:apiviewer.dao.Node,construct:function(E,F){apiviewer.dao.Node.call(this,E);this.self(arguments).registerClass(this);this._package=F;},statics:{_class_registry:{},_top_level_classes:[],registerClass:function(G){if(!G.getFullName()){return;}this._class_registry[G.getFullName()]=G;if(!G._docNode.attributes.superClass){this._top_level_classes.push(G);}},getClassByName:function(H){return this._class_registry[H];},getAllTopLevelClasses:function(){return this._top_level_classes;}},members:{getName:function(){return this._docNode.attributes.name;},getClass:function(){return this;},getPackage:function(){return this._package;},isLoaded:function(){return this._docNode.attributes.externalRef!=true;},getFullName:function(){return this._docNode.attributes.fullName||m;},getPackageName:function(){return this._docNode.attributes.packageName||m;},getDescription:function(){return this._desc||m;},getType:function(){return this._docNode.attributes.type||u;},isAbstract:function(){return this._docNode.attributes.isAbstract||false;},isStatic:function(){return this._docNode.attributes.isStatic||false;},isSingleton:function(){return this._docNode.attributes.isSingleton||false;},getSee:function(){return this._see;},getSuperClass:function(){return this.self(arguments).getClassByName(this._docNode.attributes.superClass);},getChildClasses:function(){return this._docNode.attributes.childClasses?this._docNode.attributes.childClasses.split(k):[];},getInterfaces:function(){return this._docNode.attributes.interfaces?this._docNode.attributes.interfaces.split(k):[];},getMixins:function(){return this._docNode.attributes.mixins?this._docNode.attributes.mixins.split(k):[];},getImplementations:function(){return this._docNode.attributes.implementations?this._docNode.attributes.implementations.split(k):[];},getIncluder:function(){return this._docNode.attributes.includer?this._docNode.attributes.includer.split(k):[];},getConstructor:function(){if(this._constructor!=null){return this._constructor;}var I=apiviewer.TreeUtil.getChild(this.getNode(),h);if(I){this._constructor=new apiviewer.dao.Method(I.children[0],this,I.type);}else{this._constructor=m;var K=this.getSuperClass();while(K){var J=K.getConstructor();if(J){var I=J.getNode();this._constructor=new apiviewer.dao.Method(I,this,h);break;}K=K.getSuperClass();}}return this._constructor;},getMembers:function(){if(this._members!=null){return this._members;}else{var L=apiviewer.TreeUtil.getChild(this.getNode(),a);this._members=L?this._createNodeList(L,apiviewer.dao.Method,this,L.type):[];return this._members;}},getStatics:function(){if(this._statics!=null){return this._statics;}else{var M=apiviewer.TreeUtil.getChild(this.getNode(),z);this._statics=M?this._createNodeList(M,apiviewer.dao.Method,this,M.type):[];return this._statics;}},getEvents:function(){if(this._events!=null){return this._events;}else{var N=apiviewer.TreeUtil.getChild(this.getNode(),A);this._events=N?this._createNodeList(N,apiviewer.dao.Event,this,N.type):[];return this._events;}},getProperties:function(){if(this._properties!=null){return this._properties;}else{var O=apiviewer.TreeUtil.getChild(this.getNode(),D);this._properties=O?this._createNodeList(O,apiviewer.dao.Property,this,O.type):[];return this._properties;}},getConstants:function(){if(this._constants!=null){return this._constants;}else{var P=apiviewer.TreeUtil.getChild(this.getNode(),c);this._constants=P?this._createNodeList(P,apiviewer.dao.Constant,this,P.type):[];return this._constants;}},getAppearances:function(){if(this._appearances!=null){return this._appearances;}else{var Q=apiviewer.TreeUtil.getChild(this.getNode(),g);this._appearances=Q?this._createNodeList(Q,apiviewer.dao.Appearance,this,Q.type):[];return this._appearances;}},getSuperInterfaces:function(){return this._superInterfaces;},getSuperMixins:function(){return this._superMixins;},getChildControls:function(){return this._childControls;},getClassHierarchy:function(){var S=[];var R=this;while(R){S.push(R);R=R.getSuperClass();}return S;},getInterfaceHierarchy:function(){var W=this;var U=[W];var V=W.getSuperInterfaces();while(V&&V.length>0){for(var i=0,l=V.length;i<l;i++){var T=apiviewer.dao.Class.getClassByName(V[i].getName());U.push(T);V=T.getSuperInterfaces();}}return U;},getItem:function(X){var Y=[B,e,C,b,y,f,d];for(var i=0;i<Y.length;i++){var ba=this[Y[i]]();for(var j=0;j<ba.length;j++){if(X==ba[j].getName()){return ba[j];}}}},getItemList:function(bb){var bc={"events":C,"constructor":r,"properties":b,"methods":B,"methods-static":e,"constants":y,"appearances":f,"superInterfaces":o,"superMixins":n,"childControls":d};if(bb==h){return this.getConstructor()?[this.getConstructor()]:[];}else{return this[bc[bb]]();}},getItemByListAndName:function(bd,be){var bf=this.getItemList(bd);for(var j=0;j<bf.length;j++){if(be==bf[j].getName()){return bf[j];}}},getClassAppearance:function(){var bg=this.getAppearances();for(var i=0;i<bg.length;i++){if(bg[i].getType()==this){return bg[i];}}return null;},getAllInterfaces:function(bh){if(bh){var bk=this.getClassHierarchy();}else{bk=[this];}var bn=[];for(var bm=0;bm<bk.length;bm++){var bl=bk[bm];var bi=function(bo){var bp=apiviewer.dao.Class.getClassByName(bo);bn.push(bp);var bq=bp.getSuperInterfaces();for(var i=0;i<bq.length;i++){bi(bq[i].getName());}};var bj=bl.getInterfaces();for(var i=0;i<bj.length;i++){bi(bj[i]);}}return bn;},getNodesOfTypeFromMixins:function(br){var bu=this.getMixins();var bv=[];for(var bw=0;bw<bu.length;bw++){var bs=function(bx){var by=bx.getItemList(br);for(var i=0;i<by.length;i++){bv.push(by[i]);}var bz=bx.getSuperMixins();for(var i=0;i<bz.length;i++){bs(apiviewer.dao.Class.getClassByName(bz[i].getName()));}};var bt=apiviewer.dao.Class.getClassByName(bu[bw]);bs(bt);}return bv;},getDependendClasses:function(){return this._findClasses(this,[]);},getDocNode:function(){return this;},_findClasses:function(bA,bB){bB.push(bA);var bJ=bA.getSuperClass();if(bJ){this._findClasses(bJ,bB);}var bG=bA.getMixins();for(var i=0;i<bG.length;i++){var bK=apiviewer.dao.Class.getClassByName(bG[i]);if(bK){this._findClasses(bK,bB);}else{this.warn("Missing mixin: "+bG[i]);}}var bH=bA.getSuperMixins();for(var i=0;i<bH.length;i++){var bI=apiviewer.dao.Class.getClassByName(bH[i]);if(bI){this._findClasses(bI,bB);}else{this.warn("Missing super mixin: "+bH[i]);}}var bF=bA.getInterfaces();for(var i=0;i<bF.length;i++){var bD=apiviewer.dao.Class.getClassByName(bF[i]);if(bD){this._findClasses(bD,bB);}else{this.warn("Missing interface: "+bF[i]);}}var bE=bA.getSuperInterfaces();for(var i=0;i<bE.length;i++){var bC=apiviewer.dao.Class.getClassByName(bE[i]);if(bC){this._findClasses(bC,bB);}else{this.warn("Missing super interface: "+bE[i]);}}return bB;},_initializeFields:function(){apiviewer.dao.Node.prototype._initializeFields.call(this);this._desc=m;this._see=[];this._superInterfaces=[];this._superMixins=[];this._childControls=[];},_addChildNode:function(bL){switch(bL.type){case h:case a:case z:case A:case D:case c:case g:break;case p:this._superInterfaces=this._createNodeList(bL,apiviewer.dao.ClassItem,this,bL.type);break;case w:this._superMixins=this._createNodeList(bL,apiviewer.dao.ClassItem,this,bL.type);break;case v:this._childControls=this._createNodeList(bL,apiviewer.dao.ChildControl,this,bL.type);break;case t:this._desc=bL.attributes.text||m;break;case q:this._see.push(bL.attributes.name);break;default:return apiviewer.dao.Node.prototype._addChildNode.call(this,bL);}return true;}},destruct:function(){this._see=this._superInterfaces=this._superMixins=this._events=this._statics=this._properties=this._constants=this._appearances=this._members=this._package=null;this._disposeObjects(s);}});})();(function(){var f="",e="name",d="desc",c="see",b="types",a="apiviewer.dao.ClassItem";qx.Class.define(a,{extend:apiviewer.dao.Node,construct:function(g,h,k){this._class=h;this._listName=k;apiviewer.dao.Node.call(this,g);},members:{getClass:function(){return this._class;},getName:function(){return this._docNode.attributes.name;},getListName:function(){return this._listName;},getDescription:function(){return this.getDocNode()._desc||f;},getTypes:function(){var m=[];for(var i=0;i<this._types.length;i++){var l={};if(this._types[i].attributes.dimensions){l.dimensions=this._types[i].attributes.dimensions;}l.type=this._types[i].attributes.type;m.push(l);}return m;},getSee:function(){return this._see;},getOverriddenFrom:function(){return apiviewer.dao.Class.getClassByName(this._docNode.attributes.overriddenFrom);},getDocNode:function(){if(this._itemDocNode){return this._itemDocNode;}this._itemDocNode=this;var n=apiviewer.dao.Class.getClassByName(this._docNode.attributes.docFrom);if(n){var o=n.getItemList(this._listName);for(var i=0;i<o.length;i++){if(o[i].getName()==this.getName()){this._itemDocNode=o[i];break;}}}return this._itemDocNode;},isRequiredByInterface:function(p){var r=apiviewer.TreeUtil.getChild(p.getNode(),this._listName);if(r){var q=apiviewer.TreeUtil.getChildByAttribute(r,e,this.getName());return q?true:false;}return false;},getRequiredBy:function(){if(this._requiredBy){return this._requiredBy;}var s=[];var t=this.getClass().getAllInterfaces(true);for(var j=0;j<t.length;j++){if(this.isRequiredByInterface(t[j])){s.push(t[j]);}}this._requiredBy=s;return s;},_initializeFields:function(){apiviewer.dao.Node.prototype._initializeFields.call(this);this._see=[];this._types=[];},_addChildNode:function(u){switch(u.type){case d:this._desc=u.attributes.text||f;break;case c:this._see.push(u.attributes.name);break;case b:this._types=this._createNodeList(u);break;default:return apiviewer.dao.Node.prototype._addChildNode.call(this,u);}return true;}},destruct:function(){this._class=this._itemDocNode=this._requiredBy=this._see=this._types=null;}});})();(function(){var h="params",g="return",f="throws",e="",d="apiviewer.dao.Method",c="_return",b="construct",a="properties";qx.Class.define(d,{extend:apiviewer.dao.ClassItem,construct:function(i,j,k){apiviewer.dao.ClassItem.call(this,i,j,k);},members:{getName:function(){if(this.isConstructor()){return b;}else{return this._docNode.attributes.name;}},isStatic:function(){return this._docNode.attributes.isStatic||false;},isAbstract:function(){return this._docNode.attributes.isAbstract||false;},isConstructor:function(){return this._docNode.attributes.isCtor||false;},isFromProperty:function(){return !!this._docNode.attributes.fromProperty;},getParams:function(){if(this._params!=null){return this._params;}else{var l=apiviewer.TreeUtil.getChild(this.getDocNode().getNode(),h);this._params=l?this._createNodeList(l,apiviewer.dao.Param,this.getClass(),this):[];return this._params;}},getReturn:function(){if(this._return!=null){return this._return;}else{var m=apiviewer.TreeUtil.getChild(this.getDocNode().getNode(),g);this._return=m?new apiviewer.dao.Param(m,this.getClass(),this):e;return this._return;}},getThrows:function(){if(this._throws!=null){return this._throws;}else{var n=apiviewer.TreeUtil.getChild(this.getDocNode().getNode(),f);this._throws=n?this._createNodeList(n,apiviewer.dao.ThrowsEntry,this.getClass(),this):[];return this._throws;}},getApply:function(){return this._docNode.attributes.apply;},getFromProperty:function(){return this.getClass().getItemByListAndName(a,this._docNode.attributes.fromProperty);},_addChildNode:function(o){switch(o.type){case h:case g:case f:break;default:return apiviewer.dao.ClassItem.prototype._addChildNode.call(this,o);}return true;}},destruct:function(){this._params=this._throws=null;this._disposeObjects(c);}});})();(function(){var b="apiviewer.dao.Param",a="properties";qx.Class.define(b,{extend:apiviewer.dao.ClassItem,construct:function(c,d,e){apiviewer.dao.ClassItem.call(this,c,d);this._method=e;},members:{getTypes:function(){var i=this.getMethod().getFromProperty();if(i){if(i.isPropertyGroup()){var g=this.getClass().getItemByListAndName(a,this.getName());if(g){return g.getTypes();}}else{return i.getTypes();}}var h=apiviewer.dao.ClassItem.prototype.getTypes.call(this);var f=this._docNode.attributes;if(f.type){h.push({type:f.type,dimensions:f.dimensions});}return h;},getMethod:function(){return this._method;},getArrayDimensions:function(){return this._docNode.attributes.arrayDimensions;},getType:function(){return this._docNode.attributes.type;},getDefaultValue:function(){return this._docNode.attributes.defaultValue;}},destruct:function(){this._method=null;}});})();(function(){var b="apiviewer.dao.ThrowsEntry",a="Error";qx.Class.define(b,{extend:apiviewer.dao.ClassItem,construct:function(c,d,e){apiviewer.dao.ClassItem.call(this,c,d);},members:{getType:function(){return this._docNode.attributes.type||null;},getDefaultType:function(){return a;},getDescription:function(){return this._docNode.attributes.text;}}});})();(function(){var b="types",a="apiviewer.dao.Event";qx.Class.define(a,{extend:apiviewer.dao.ClassItem,construct:function(c,d,e){apiviewer.dao.ClassItem.call(this,c,d,e);},members:{getType:function(){return apiviewer.dao.Class.getClassByName(this._type);},getTypes:function(){if(this._type){return [{type:this._type}];}else{return null;}},_addChildNode:function(f){switch(f.type){case b:this._type=f.children[0].attributes.type;break;default:return apiviewer.dao.ClassItem.prototype._addChildNode.call(this,f);}return true;}}});})();(function(){var d=",",c="new",b="true",a="apiviewer.dao.Property";qx.Class.define(a,{extend:apiviewer.dao.ClassItem,members:{getTypes:function(){var g=apiviewer.dao.ClassItem.prototype.getTypes.call(this);var e=this.getDocNode();var f=e.getType();if(f){g.push({type:f,dimensions:e.getNode().attributes.dimensions});}return g;},getCheck:function(){var h=this.getDocNode()._docNode.attributes;if(h.check){if(!apiviewer.dao.Class.getClassByName(h.check)&&!apiviewer.ui.ClassViewer.PRIMITIVES[h.check]){return h.check;}}return null;},getClassname:function(){return this._docNode.attributes.classname;},getInstance:function(){return this._docNode.attributes.instance;},getPossibleValues:function(){var i=this._docNode.attributes.possibleValues;if(i){i=i.split(d);return i;}else{return [];}},getGroup:function(){var j=this.getDocNode()._docNode.attributes.group;if(j){return j.split(d);}return [];},isPropertyGroup:function(){return !!this.getDocNode()._docNode.attributes.group;},getType:function(){var k=this._docNode.attributes;if(k.type){return k.type;}if(k.check){if(apiviewer.dao.Class.getClassByName(k.check)||apiviewer.ui.ClassViewer.PRIMITIVES[k.check]){return k.check;}}return null;},getPropertyType:function(){return this.getDocNode()._docNode.attributes.propertyType||c;},getEvent:function(){return this.getDocNode()._docNode.attributes.event;},getApplyMethod:function(){return this.getDocNode()._docNode.attributes.apply;},isNullable:function(){return this.getDocNode()._docNode.attributes.allowNull===b;},getDefaultValue:function(){return this._docNode.attributes.defaultValue;},isInheritable:function(){return this.getDocNode()._docNode.attributes.inheritable||false;},isThemeable:function(){return this.getDocNode()._docNode.attributes.themeable||false;},isRefined:function(){return this._docNode.attributes.refine||false;}}});})();(function(){var bv="mixin",bu="",bt='</div>',bs="<h2>",br="</h2>",bq="interface",bp='',bo="constructor",bn=';',bm="events",bb='</h2>',ba="apiviewer/image/nextlevel.gif",Y='px',X='<p>',W='"',V='">',U="appearances",T='</p>',S="constants",R="This ",bC='px;height:',bD='<h2 class="warning">',bA="properties",bB=' style="',by='<div class="class-description">',bz="methods",bw="Inheritance hierarchy:",bx='</span>',bE="Implementations of this interface:",bF="childControls",bf="sub interfaces",be=";vertical-align:top",bh='" src="',bg=' title="',bj="Internal:",bi="width:18px",bl="Included mixins:",bk="margin-right:-18px;",bd="Interface",bc="apiviewer/image/cross.gif",a='/>',b=' </span>',c='<span style="display:inline-block;display:inline;padding-right:18px;position:relative;top:-2px;left:0;width:',d="superMixins",f="methods-static",g="string",h="<br />\n",k="Deprecated:",l="sub mixins",m=":",bJ='<img src="',bI='</small>',bH=" is deprecated!",bG="position:absolute;top:0px;left:0px",bN="Singleton ",bM='" class="img"',bL='"/>',bK="Direct ",bP="position:absolute;top:0px;left:0px;padding-right:18px;",bO="apiviewer/image/blank.gif",B="apiviewer/image/class18.gif",C='<span style="display:inline;position:relative;top:-2px;width:',z=" is internal!",A="px",F='<span class="type">',G="Classes including this mixin:",D='<img',E="class",x="Implemented interfaces:",y="Class",u="top",t="Object<br/>",w=", ",v="margin-left:",q="construct",p="left",s='<div>',r="child controls",o="Abstract ",n="sub classes",L="vertical-align:top",M="static methods",N="ClassViewer",O="Static ",H="apiviewer.ui.ClassViewer",I='<small>',J="Mixin",K="marked",P="apiviewer/image/vline.gif",Q="superInterfaces";qx.Class.define(H,{extend:apiviewer.ui.AbstractViewer,construct:function(){apiviewer.ui.AbstractViewer.call(this);this.addInfoPanel(new apiviewer.ui.panels.MethodPanel(bo,bo));this.addInfoPanel(new apiviewer.ui.panels.EventPanel(bm,bm,true,true));this.addInfoPanel(new apiviewer.ui.panels.PropertyPanel(bA,bA,true,true));this.addInfoPanel(new apiviewer.ui.panels.MethodPanel(bz,bz));this.addInfoPanel(new apiviewer.ui.panels.MethodPanel(f,M));this.addInfoPanel(new apiviewer.ui.panels.ConstantPanel(S,S,false,true));this.addInfoPanel(new apiviewer.ui.panels.AppearancePanel(U,U,false,true));this.addInfoPanel(new apiviewer.ui.panels.ChildControlsPanel(bF,r));this.getContentElement().setAttribute(E,N);this._init(new apiviewer.dao.Class({}));},statics:{PRIMITIVES:{"var":true,"void":true,"undefined":true,"arguments":true,"null":true,"varargs":true,"Boolean":true,"String":true,"Number":true,"Integer":true,"PositiveNumber":true,"PositiveInteger":true,"Float":true,"Double":true,"Error":true,"RegExp":true,"Object":true,"Array":true,"Map":true,"Function":true,"Date":true,"Node":true,"Element":true,"Document":true,"Window":true,"Event":true,"Class":true,"Bootstrap":true,"List":true,"Mixin":true,"Interface":true,"Theme":true,"Color":true,"Decorator":true,"Font":true},createImageHtml:function(bQ,bR,bS){if(typeof bQ==g){return bJ+qx.util.ResourceManager.getInstance().toUri(bQ)+bM+(bS?bB+bS+W:bu)+a;}else{if(bS){bS+=be;}else{bS=L;}return apiviewer.ui.ClassViewer.createOverlayImageHtml(18,18,bQ,bR,bS);}},createOverlayImageHtml:function(bT,bU,bV,bW,bX){var ca=bp;var bY;if(qx.bom.client.Engine.WEBKIT){ca=C+bT+bC+bU+Y+((bX==null)?bp:(bn+bX))+V;}else{ca=c+bT+bC+bU+Y+((bX==null)?bp:(bn+bX))+V;}if(qx.bom.client.Engine.WEBKIT){bY=bP;}else if(qx.bom.client.Engine.OPERA){bY=bk;}else{bY=bG;}for(var i=0;i<bV.length;i++){ca+=D;if(bW!=null){ca+=bg+bW+W;}ca+=bB+bY+bh+qx.util.ResourceManager.getInstance().toUri(bV[i])+bL;}ca+=bx;return ca;}},members:{_getTitleHtml:function(cb){switch(cb.getType()){case bv:var cd=J;break;case bq:var cd=bd;break;default:var cd=y;break;}var cc=new qx.util.StringBuilder();cc.add(I,cb.getPackageName(),bI);cc.add(F);if(cb.isAbstract()){cc.add(o);}else if(cb.isStatic()){cc.add(O);}else if(cb.isSingleton()){cc.add(bN);}cc.add(cd,b);cc.add(apiviewer.ui.panels.InfoPanel.setTitleClass(cb,cb.getName()));return cc.get();},_getDescriptionHtml:function(ce){switch(ce.getType()){case bv:var cf=l;break;case bq:var cf=bf;break;default:var cf=n;break;}var ch=new qx.util.StringBuilder();var ci=ce.getDescription();if(ci!=bu){ch.add(by,apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(ci,ce),bt);}if(ce.getErrors().length>0){ch.add(by,apiviewer.ui.panels.InfoPanel.createErrorHtml(ce,ce),bt);}switch(ce.getType()){case bv:case bq:ch.add(this.__Sz(ce));break;default:ch.add(this.__Sy(ce));break;}ch.add(this.__Sx(ce.getChildClasses(),bK+cf+m));ch.add(this.__Sx(ce.getInterfaces(),x));ch.add(this.__Sx(ce.getMixins(),bl));ch.add(this.__Sx(ce.getImplementations(),bE));ch.add(this.__Sx(ce.getIncluder(),G));var cg=ce.getConstructor();if(cg){ch.add(apiviewer.ui.panels.InfoPanel.createSeeAlsoHtml(cg));}if(ce.isDeprecated()){ch.add(bD,k,bb);ch.add(X);var ci=ce.getDeprecationText();if(ci){ch.add(ci);}else{ch.add(R,ce.getType(),bH);}ch.add(T);}if(ce.isInternal()){ch.add(bD,bj,bb);ch.add(X);ch.add(R,ce.getType(),z);ch.add(T);}return ch.get();},__Sx:function(cj,ck){if(cj.length>0){var cl=new qx.util.StringBuilder(bs,ck,br);for(var i=0;i<cj.length;i++){if(i!=0){cl.add(w);}cl.add(apiviewer.ui.panels.InfoPanel.createItemLinkHtml(cj[i],null,true,false));}cl=cl.get();}else{cl=bu;}return cl;},__Sy:function(cm){var co=apiviewer.ui.ClassViewer;var cp=new qx.util.StringBuilder(bs,bw,br);var cq=cm.getClassHierarchy();cp.add(co.createImageHtml(B),t);var cn=0;for(var i=cq.length-1;i>=0;i--){cp.add(s);cp.add(co.createImageHtml(ba,null,v+cn+A),co.createImageHtml(apiviewer.TreeUtil.getIconUrl(cq[i])));if(i!=0){cp.add(apiviewer.ui.panels.InfoPanel.createItemLinkHtml(cq[i].getFullName(),null,false));}else{cp.add(cq[i].getFullName());}cn+=18;cp.add(bt);}return cp.get();},__Sz:function(cr){if(cr.getType()==bv){var cs=d;}else{cs=Q;}var cu=apiviewer.ui.ClassViewer;var ct=cu.createImageHtml(bO,null,bi);var cw=function(cx,cy){var cA=[];for(var cz=0;cz<cx.length;cz++){var cD=new qx.util.StringBuilder();var cB=cx[cz];if(!cy){if(cz==cx.length-1){cD.add(cu.createImageHtml(ba));}else{cD.add(cu.createImageHtml(bc));}}else{if(!cy){cD.add(ct);}}cD.add(cu.createImageHtml(apiviewer.TreeUtil.getIconUrl(cB)));if(!cy){cD.add(apiviewer.ui.panels.InfoPanel.createItemLinkHtml(cB.getFullName(),null,false));}else{cD.add(cB.getFullName());}cA.push(cD.get());var cC=qx.lang.Array.clone(cB.getItemList(cs));for(var j=0;j<cC.length;j++){cC[j]=apiviewer.dao.Class.getClassByName(cC[j].getName());}if(cC.length>0){var cE=cw(cC);for(var i=0;i<cE.length;i++){if(cz==cx.length-1){if(cy){cA.push(cE[i]);}else{cA.push(ct+cE[i]);}}else{cA.push(cu.createImageHtml(P)+cE[i]);}}}}return cA;};var cv=new qx.util.StringBuilder();if(cr.getItemList(cs).length>0){cv.add(bs,bw,br);cv.add(cw([cr],true).join(h));}return cv.get();},showItem:function(cF){var cI;if(cF==q){cI=this.getDocNode().getConstructor();}else{cI=this.getDocNode().getItem(cF);}if(!cI){return false;}this.__SA(cI,cF);var cJ=this._getPanelForItemNode(cI);var cG=cJ.getItemElement(cI.getName());if(!cG){return false;}var cH=cG.parentNode.parentNode;if(this._markedElement){this._markedElement.className=bu;}cH.className=K;this._markedElement=cH;qx.event.Timer.once(function(e){qx.bom.element.Scroll.intoView(cH,null,p,u);},this,0);return true;},__SA:function(cK,cL){var cM=apiviewer.UiModel.getInstance();if(cK.isFromProperty&&cK.isFromProperty()){cM.setExpandProperties(true);if(cK.isProtected()){cM.setShowProtected(true);}if(cK.isPrivate()){cM.setShowPrivate(true);}}else if(cK.getListName()=="methods"){if(cL.indexOf("__")===0){cM.setShowPrivate(true);}else if(cL.indexOf("_")===0){cM.setShowProtected(true);}}},_getPanelForItemNode:function(cN){var cO=this.getPanels();for(var i=0;i<cO.length;i++){var cP=cO[i];if(cP.canDisplayItem(cN)){return cP;}}}},destruct:function(){this._titleElem=this._classDescElem=this._markedElement=null;}});})();(function(){var c="apiviewer.ui.panels.EventPanel",b="var",a="event";qx.Class.define(c,{extend:apiviewer.ui.panels.InfoPanel,members:{itemHasDetails:function(d,e){return (d.getClass()!=e||d.getSee().length>0||d.getErrors().length>0||apiviewer.ui.panels.InfoPanel.descriptionHasDetails(d));},getItemTypeHtml:function(f){return apiviewer.ui.panels.InfoPanel.createTypeHtml(f,b);},getItemTitleHtml:function(g){return apiviewer.ui.panels.InfoPanel.setTitleClass(g,g.getName());},getItemTextHtml:function(h,i,j){var k=new qx.util.StringBuilder(apiviewer.ui.panels.InfoPanel.createDescriptionHtml(h,h.getClass(),j));if(j){k.add(apiviewer.ui.panels.InfoPanel.createInheritedFromHtml(h,i));k.add(apiviewer.ui.panels.InfoPanel.createSeeAlsoHtml(h));k.add(apiviewer.ui.panels.InfoPanel.createErrorHtml(h,i));k.add(apiviewer.ui.panels.InfoPanel.createDeprecationHtml(h,a));}return k.get();}}});})();(function(){var j='</div>',i='<div class="item-detail-headline">',h='<div class="item-detail-text">',g="#",f="null",e="instances of ",d="apiviewer.ui.panels.PropertyPanel",c='<div class="javascript">',b="var",a="Apply method:",v="property",u="Check:",t="Allowed values:",s='</code>',r="</code>",q="any ",p="Init value:",o='<code>',n="<code>",m="</code>, <code>",k="Change event:",l=" or sub classes";qx.Class.define(d,{extend:apiviewer.ui.panels.InfoPanel,members:{__SB:function(w,x){if(w.isRefined()){return "";}if(w.isPrivate()){var y="__";var name=w.getName().substring(2);}else if(w.isProtected()){y="_";name=w.getName().substring(1);}else{y="";name=w.getName();}name=qx.lang.String.firstUp(name);var A=[];if(w.getPropertyType()=="fast"){A.push("{@link #"+y+"get"+name+"}</td><td> Get the property value.");}else{A.push("{@link #"+y+"set"+name+"}</td><td> Set the property value.");if(!w.isPropertyGroup()){A.push("{@link #"+y+"get"+name+"}</td><td> Get the property value.");A.push("{@link #"+y+"init"+name+"}</td><td> Call apply method with the init value.");}A.push("{@link #"+y+"reset"+name+"}</td><td> Reset the property value.");if(w.getType()=="Boolean"){A.push("{@link #"+y+"toggle"+name+"}</td><td> Toggle the property value.");A.push("{@link #"+y+"is"+name+"}</td><td> Check whether the property equals <code>true</code>.");}}var z=new qx.util.StringBuilder();z.add('<div class="item-detail-headline">',"Generated methods:",'</div>','<div class="item-detail-text">');z.add("<table><tr><td>");z.add(A.join("</td></tr><tr><td>"));z.add("</td></tr></table>");z.add('</div>');return apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(z.get(),x);},__SC:function(B){var C=[];if(B.isNullable()){C.push("This property allows 'null' values");}if(B.isInheritable()){C.push("The property value can be inherited from a parent object.");}if(B.isThemeable()){C.push("The property value can be set using appearance themes.");}if(B.isPropertyGroup()){C.push("The property is a property group.");}if(B.isRefined()){C.push("The property refines the init value of an existing property.");}if(C.length>0){var D=new qx.util.StringBuilder();D.add('<div class="item-detail-headline">',"Property attributes:",'</div>','<div class="item-detail-text">');D.add("<ul><li>");D.add(C.join("</li><li>"));D.add("</li></ul>");D.add('</div>');return D.get();}else{return "";}},__SD:function(E){if(E.isRefined()){var F=new qx.util.StringBuilder('<div class="item-detail-headline">',"Refined property:",'</div>','<div class="item-detail-text">',apiviewer.ui.panels.InfoPanel.createItemLinkHtml(E.getOverriddenFrom().getFullName()+"#"+E.getName()),'</div>');return F.get();}else{return "";}},getItemTypeHtml:function(G){return apiviewer.ui.panels.InfoPanel.createTypeHtml(G,b);},getItemTitleHtml:function(H){return apiviewer.ui.panels.InfoPanel.setTitleClass(H,H.getName());},getItemTextHtml:function(I,J,K){var L=I.getDocNode();var N=new qx.util.StringBuilder(apiviewer.ui.panels.InfoPanel.createDescriptionHtml(I,I.getClass(),K));if(K){var O=null;var M=qx.lang.Array.clone(I.getPossibleValues());if(M.length>0){if(I.isNullable()){M.push(f);}O=n+M.join(m)+r;}else if(I.getClassname()){O=e+I.getClassname();}else if(I.getInstance()){O=e+I.getInstance()+l;}else if(I.getType()){O=q+I.getType();}if(O){N.add(i,t,j,h);N.add(O,j);}if(I.getCheck()){N.add(i,u,j,c,qx.dev.Tokenizer.javaScriptToHtml(I.getCheck()),j);}if(!I.isPropertyGroup()){N.add(i,p,j,h,o,(I.getDefaultValue()?I.getDefaultValue():f),s,j);}if(I.getEvent()&&!I.isRefined()){N.add(i,k,j,h,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(g+I.getEvent(),I.getClass(),true,true),j);}if(I.getApplyMethod()&&!I.isRefined()){N.add(i,a,j,h,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(g+I.getApplyMethod(),I.getClass(),true,true),j);}N.add(this.__SC(I));N.add(this.__SB(I,J));N.add(apiviewer.ui.panels.InfoPanel.createIncludedFromHtml(I,J));N.add(this.__SD(I));N.add(apiviewer.ui.panels.InfoPanel.createInheritedFromHtml(I,J));N.add(apiviewer.ui.panels.InfoPanel.createInfoRequiredByHtml(I));N.add(apiviewer.ui.panels.InfoPanel.createSeeAlsoHtml(L));N.add(apiviewer.ui.panels.InfoPanel.createErrorHtml(I,J));N.add(apiviewer.ui.panels.InfoPanel.createDeprecationHtml(L,v));}return N.get();}}});})();(function(){var c="apiviewer.ui.panels.ConstantPanel",b="var",a="constant";qx.Class.define(c,{extend:apiviewer.ui.panels.InfoPanel,members:{itemHasDetails:function(d,e){return (d.getSee().length>0||d.getErrors().length>0||apiviewer.ui.panels.InfoPanel.descriptionHasDetails(d)||this.__SE(d));},getItemTypeHtml:function(f){return apiviewer.ui.panels.InfoPanel.createTypeHtml(f,b);},getItemTitleHtml:function(g){return apiviewer.ui.panels.InfoPanel.setTitleClass(g,g.getName());},getItemTextHtml:function(h,i,j){var k=apiviewer.ui.panels.InfoPanel.createDescriptionHtml(h,h.getClass(),j);if(j){k+=this.__SF(h);k+=apiviewer.ui.panels.InfoPanel.createSeeAlsoHtml(h);k+=apiviewer.ui.panels.InfoPanel.createErrorHtml(h,i);k+=apiviewer.ui.panels.InfoPanel.createDeprecationHtml(h,a);}return k;},__SE:function(l){return l.getValue()?true:false;},__SF:function(m){if(this.__SE(m)){var n=new qx.util.StringBuilder('<div class="item-detail-headline">',"Value: ",'</div>','<div class="item-detail-text">',qx.bom.String.escape(qx.util.Json.stringify(m.getValue())),'</div>');return n.get();}else{return "";}}}});})();(function(){var m='</div>',l=" <span class='item-detail-define'>defined by ",k=" (default appearance of the class)",j="</p></div>",h="</span>: ",g='<div class="item-desc">',f=" ",e="apiviewer.ui.panels.AppearancePanel",d='<div class="item-detail-headline">',c="</code><p>",a="<div class='item-detail-text'><code>",b="States:";qx.Class.define(e,{extend:apiviewer.ui.panels.InfoPanel,members:{__SG:function(n){var r=n.getStates();if(r.length>0){var t=qx.lang.Array.clone(r);}else{t=[];}var u=n.getType();var v=n.getClass();var s=1;if(u!=v){v=u;s=0;}var q=v.getClassHierarchy();for(var i=s;i<q.length;i++){v=q[i];var o=v.getClassAppearance();if(o){var p=o.getStates();if(p){qx.lang.Array.append(t,p);}}}return t;},_getPanelItems:function(w,x){var z=apiviewer.ui.panels.InfoPanel.prototype._getPanelItems.call(this,w,x);if(!w){return z;}var A=x.getClassHierarchy();for(var i=0;i<A.length;i++){var B=A[i];var y=B.getClassAppearance();if(y){if(y.getType()!=x){z.push(y);}return z;}}},getItemTypeHtml:function(C){var E=C.getName();if(C.getType()==C.getClass()){var D=E+k;}else{var D=E;}return D;},getItemTitleHtml:function(F){return apiviewer.ui.panels.InfoPanel.setTitleClass(F,F.getName());},getItemTextHtml:function(G,H,I){var M=new qx.util.StringBuilder();M.add(g,apiviewer.ui.panels.InfoPanel.createDescriptionHtml(G,G.getClass(),true),m);if(I){var K=this.__SG(G);if(K.length>0){M.add(d,b,m);for(var i=0;i<K.length;i++){var L=K[i];M.add(a,L.getName(),c);var J=L.getAppearance();if(J.getType()!=G.getClass()){M.add(l,apiviewer.ui.panels.InfoPanel.createItemLinkHtml(J.getType().getFullName()),h);}var N=L.getDescription();if(N){M.add(f,apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(N,L.getClass()));}M.add(j);}M.add(m);}}return M.get();},itemHasDetails:function(O,P){return this.__SG(O).length>0;}}});})();(function(){var i='</div>',h="apiviewer.ui.panels.ChildControlsPanel",g="null",f="var",e='<div class="item-detail-headline">',d='</code>',c='<code>',b="Default value:",a='<div class="item-detail-text">';qx.Class.define(h,{extend:apiviewer.ui.panels.InfoPanel,members:{getItemTypeHtml:function(j,k){return apiviewer.ui.panels.InfoPanel.createTypeHtml(j,f,true);},getItemTitleHtml:function(l,m){return apiviewer.ui.panels.InfoPanel.setTitleClass(l,l.getName());},getItemTextHtml:function(n,o,p){var q=new qx.util.StringBuilder(n.getDescription());if(p){q.add(e,b,i,a,c,(n.getDefaultValue()?n.getDefaultValue():g),d,i);}return q.get();}}});})();(function(){var a="apiviewer.dao.Constant";qx.Class.define(a,{extend:apiviewer.dao.ClassItem,construct:function(b,c,d){apiviewer.dao.ClassItem.call(this,b,c,d);},members:{getValue:function(){return this._docNode.attributes.value;}}});})();(function(){var b="states",a="apiviewer.dao.Appearance";qx.Class.define(a,{extend:apiviewer.dao.ClassItem,construct:function(c,d,e){apiviewer.dao.ClassItem.call(this,c,d,e);},members:{getType:function(){return apiviewer.dao.Class.getClassByName(this._docNode.attributes.type);},getTypes:function(){return [{type:this._docNode.attributes.type}];},getAppearance:function(){return this.getClass();},getStates:function(){return this._states||[];},_addChildNode:function(f){switch(f.type){case b:this._states=this._createNodeList(f,apiviewer.dao.State,this);break;default:return apiviewer.dao.ClassItem.prototype._addChildNode.call(this,f);}return true;}}});})();(function(){var a="apiviewer.dao.State";qx.Class.define(a,{extend:apiviewer.dao.ClassItem,construct:function(b,parent){apiviewer.dao.ClassItem.call(this,b,parent);},members:{getClass:function(){return this._class.getClass();},getAppearance:function(){return this._class;}}});})();(function(){var a="apiviewer.dao.ChildControl";qx.Class.define(a,{extend:apiviewer.dao.ClassItem,construct:function(b,c,d){apiviewer.dao.ClassItem.call(this,b,c);this._listName=d;},members:{getTypes:function(){var f=apiviewer.dao.ClassItem.prototype.getTypes.call(this);var e=this._docNode.attributes;if(e.type){f.push({type:e.type});}return f;},getType:function(){return this._docNode.attributes.type;},getDefaultValue:function(){return this._docNode.attributes.defaultValue;}}});})();(function(){var n="class",m="interface",l="mixin",k="list",j="",h="apiviewer.ui.panels.ClassPanel",g="Singleton ",f="Abstract ",e="bootstrap",d="Static ",a="Class",c="Interface",b="Mixin";qx.Class.define(h,{extend:apiviewer.ui.panels.InfoPanel,construct:function(o,p,q){apiviewer.ui.panels.InfoPanel.call(this,o,p);this.setType(q);},properties:{type:{check:[n,l,m]}},members:{getItemTypeHtml:function(r){return apiviewer.ui.panels.InfoPanel.createItemLinkHtml(r.getName(),r,false,true);},getItemTitleHtml:function(s){return s.getFullName();},getItemTextHtml:function(t,u,v){if(v){return apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(t.getDescription(),t);}else{return apiviewer.ui.panels.InfoPanel.createDescriptionHtml(t,t.getClass(),v);}},getItemTooltip:function(w,x){if(w.isAbstract()){var y=f;}else if(w.isStatic()){var y=d;}else if(w.isSingleton()){var y=g;}else{var y=j;}switch(w.getType()){case l:y+=b;break;case m:y+=c;break;default:y+=a;break;}return y;},itemHasDetails:function(z,A){return apiviewer.ui.panels.InfoPanel.descriptionHasDetails(z);},update:function(B,C){if(!this.getElement()){return;}this.setDocNode(C);var E=C.getClasses();var D=[];var F;for(var i=0;i<E.length;i++){F=E[i].getType();if(F===e||F===k){F=n;}if(F===this.getType()){D.push(E[i]);}}if(D&&D.length>0){this._sortItems(D);}this._displayNodes(D,C);}}});})();(function(){var b="Package",a="apiviewer.ui.panels.PackagePanel";qx.Class.define(a,{extend:apiviewer.ui.panels.InfoPanel,members:{getItemTypeHtml:function(c){return apiviewer.ui.panels.InfoPanel.createItemLinkHtml(c.getFullName(),null,false,true);},getItemTitleHtml:function(d){return d.getFullName();},getItemTextHtml:function(e,f,g){if(g){return apiviewer.ui.panels.InfoPanel.resolveLinkAttributes(e.getDescription(),e);}else{return apiviewer.ui.panels.InfoPanel.createDescriptionHtml(e,e.getPackage(),g);}},getItemTooltip:function(h,i){return b;},itemHasDetails:function(j,k){return apiviewer.ui.panels.InfoPanel.descriptionHasDetails(j);},update:function(l,m){if(!this.getElement()){return;}this.setDocNode(m);var n=m.getPackages();if(n&&n.length>0){this._sortItems(n);}this._displayNodes(n,m);}}});})();(function(){var a="apiviewer.ui.tabview.ClassPage";qx.Class.define(a,{extend:apiviewer.ui.tabview.AbstractPage,members:{_createViewer:function(){return new apiviewer.ui.ClassViewer();}}});})();(function(){var m="value",l="separator-vertical",k="_tabView",j="qooxdoo",h="_packageViewer",g="_searchView",f="_tree",d="_detailLoader",c="apiviewer.Viewer",b="_classViewer",a="tree";qx.Class.define(c,{extend:qx.ui.container.Composite,construct:function(){qx.ui.container.Composite.call(this);this.__SH={};var p=new qx.ui.layout.VBox;p.setSeparator(l);this.setLayout(p);this.add(this.__SQ());this.add(this.__SM());var n=new apiviewer.ui.PackageTree();n.setId(a);this._searchView=new apiviewer.ui.SearchView();var q=new apiviewer.ui.LegendView();var r=this.__SL(n,this._searchView,q);var o=this.__SN();this.add(this.__SP(r,o),{flex:1});},members:{__SI:null,__SJ:null,__SH:null,__SK:null,__SL:function(s,t,u){var v=new qx.ui.container.Stack;v.setAppearance("toggleview");v.add(s);v.add(t);v.add(u);this.__SK.addListener("changeSelection",function(e){var w=e.getData()[0];var x=w!=null?w.getUserData("value"):null;switch(x){case "packages":v.setSelection([s]);v.show();break;case "search":v.setSelection([t]);v.show();qx.lang.Function.delay(this._onShowSearch,100,this);break;case "legend":v.setSelection([u]);v.show();break;default:v.exclude();}},this);return v;},__SM:function(){var toolbar=new qx.ui.toolbar.ToolBar;var B=new qx.ui.toolbar.Part;toolbar.add(B);this.__SI=B.toHashCode();var E=new qx.ui.toolbar.RadioButton(this.tr("Content"),"icon/22/apps/utilities-dictionary.png");E.setUserData("value","packages");E.setValue(true);E.setToolTipText(this.tr("Show/hide the packages."));B.add(E);var H=new qx.ui.toolbar.RadioButton(this.tr("Search"),"icon/22/actions/edit-find.png");H.setUserData("value","search");H.setToolTipText(this.tr("Search for packages, classes and members."));B.add(H);var y=new qx.ui.toolbar.RadioButton(this.tr("Legend"),"icon/22/apps/utilities-help.png");y.setUserData("value","legend");y.setToolTipText(this.tr("Show/hide the legend."));B.add(y);var z=new qx.ui.form.RadioGroup(E,H,y);z.setAllowEmptySelection(true);this.__SK=z;toolbar.addSpacer();var B=new qx.ui.toolbar.Part;toolbar.add(B);var F=new qx.ui.toolbar.CheckBox(this.tr("Properties"),"apiviewer/image/property18.gif");F.setId("btn_expand");F.setValue(true);F.setToolTipText(this.tr("Show/hide all generated property methods."));B.add(F);var D=new qx.ui.toolbar.CheckBox(this.tr("Inherited"),"apiviewer/image/method_public_inherited18.gif");D.setId("btn_inherited");D.setToolTipText(this.tr("Show/hide inherited members of the current class."));B.add(D);var A=new qx.ui.toolbar.CheckBox(this.tr("Protected"),"apiviewer/image/method_protected18.gif");A.setId("btn_protected");A.setToolTipText(this.tr("Show/hide protected members of the current class."));B.add(A);var G=new qx.ui.toolbar.CheckBox(this.tr("Private"),"apiviewer/image/method_private18.gif");G.setId("btn_private");G.setToolTipText(this.tr("Show/hide private members of the current class."));B.add(G);toolbar.setOverflowHandling(true);var C=new qx.ui.toolbar.MenuButton(null,"icon/22/actions/media-seek-forward.png");C.setAppearance("toolbar-button");toolbar.add(C);toolbar.setOverflowIndicator(C);this.__SJ=new qx.ui.menu.Menu();C.setMenu(this.__SJ);toolbar.addListener("hideItem",function(e){var I=e.getData();var J=this._getMenuItems(I);for(var i=0;i<J.length;i++){J[i].setVisibility("visible");}},this);toolbar.addListener("showItem",function(e){var K=e.getData();var L=this._getMenuItems(K);for(var i=0;i<L.length;i++){L[i].setVisibility("excluded");}},this);return toolbar;},_getMenuItems:function(M){var O=M.getChildren();var P=[];if(M.toHashCode()===this.__SI){var N=this.__SH[M.toHashCode()];if(!N){N=new qx.ui.menu.Separator();this.__SJ.addAt(N,0);this.__SH[M.toHashCode()]=N;}P.push(N);}for(var i=O.length-1;i>=0;i--){var Q=O[i];N=this.__SH[Q.toHashCode()];if(!N){if(Q instanceof qx.ui.toolbar.RadioButton){var N=new qx.ui.menu.RadioButton(Q.getLabel());}else{N=new qx.ui.menu.CheckBox(Q.getLabel());}Q.bind(m,N,m);N.bind(m,Q,m);this.__SJ.addAt(N,0);this.__SH[Q.toHashCode()]=N;}P.push(N);}return P;},__SN:function(){var R=new qx.ui.container.Composite(new qx.ui.layout.Canvas);R.getContentElement().setAttribute("class","content");this._detailLoader=new qx.ui.embed.Html('<div style="padding:10px;"><h1><small>please wait</small>Loading data...</h1></div>');this._detailLoader.getContentElement().setAttribute("id","SplashScreen");this._detailLoader.setAppearance("detailviewer");this._detailLoader.setId("detail_loader");R.add(this._detailLoader,{edge:0});this._tabView=new qx.ui.tabview.TabView();this._tabView.setId("tabView");this._tabView.exclude();R.add(this._tabView,{edge:0});return R;},__SO:function(toolbar,S){var T=new qx.ui.container.Composite;T.setLayout(new qx.ui.layout.VBox);T.add(toolbar);T.add(S,{flex:1});return T;},__SP:function(U,V){var W=new qx.ui.splitpane.Pane("horizontal");W.add(U,0);W.add(V,1);return W;},__SQ:function(){var ba=new qx.ui.layout.HBox();var X=new qx.ui.container.Composite(ba);X.setAppearance("app-header");var bb=new qx.ui.basic.Label("API Documentation");var Y=new qx.ui.basic.Label("qooxdoo "+qx.core.Setting.get("qx.version"));X.add(bb);X.add(new qx.ui.core.Spacer,{flex:1});X.add(Y);return X;},_onShowSearch:function(){this._searchView.sinput.focus();}},settings:{"apiviewer.title":j,"apiviewer.initialTreeDepth":1},destruct:function(){this._classTreeNodeHash=this.__SK=null;this._disposeObjects(f,d,b,h,g,k);}});})();(function(){var n="_applyLayoutChange",m="top",k="left",j="middle",h="Decorator",g="center",f="_applyReversed",e="bottom",d="qx.ui.layout.VBox",c="Integer",a="right",b="Boolean";qx.Class.define(d,{extend:qx.ui.layout.Abstract,construct:function(o,p,q){qx.ui.layout.Abstract.call(this);if(o){this.setSpacing(o);}if(p){this.setAlignY(p);}if(q){this.setSeparator(q);}},properties:{alignY:{check:[m,j,e],init:m,apply:n},alignX:{check:[k,g,a],init:k,apply:n},spacing:{check:c,init:0,apply:n},separator:{check:h,nullable:true,apply:n},reversed:{check:b,init:false,apply:f}},members:{__eS:null,__eT:null,__eU:null,__eV:null,_applyReversed:function(){this._invalidChildrenCache=true;this._applyLayoutChange();},__eW:function(){var w=this._getLayoutChildren();var length=w.length;var s=false;var r=this.__eS&&this.__eS.length!=length&&this.__eT&&this.__eS;var u;var t=r?this.__eS:new Array(length);var v=r?this.__eT:new Array(length);if(this.getReversed()){w=w.concat().reverse();}for(var i=0;i<length;i++){u=w[i].getLayoutProperties();if(u.height!=null){t[i]=parseFloat(u.height)/100;}if(u.flex!=null){v[i]=u.flex;s=true;}else{v[i]=0;}}if(!r){this.__eS=t;this.__eT=v;}this.__eU=s;this.__eV=w;delete this._invalidChildrenCache;},verifyLayoutProperty:null,renderLayout:function(x,y){if(this._invalidChildrenCache){this.__eW();}var F=this.__eV;var length=F.length;var P=qx.ui.layout.Util;var O=this.getSpacing();var S=this.getSeparator();if(S){var C=P.computeVerticalSeparatorGaps(F,O,S);}else{var C=P.computeVerticalGaps(F,O,true);}var i,A,B,J;var K=[];var Q=C;for(i=0;i<length;i+=1){J=this.__eS[i];B=J!=null?Math.floor((y-C)*J):F[i].getSizeHint().height;K.push(B);Q+=B;}if(this.__eU&&Q!=y){var H={};var N,R;for(i=0;i<length;i+=1){N=this.__eT[i];if(N>0){G=F[i].getSizeHint();H[i]={min:G.minHeight,value:K[i],max:G.maxHeight,flex:N};}}var D=P.computeFlexOffsets(H,y,Q);for(i in D){R=D[i].offset;K[i]+=R;Q+=R;}}var top=F[0].getMarginTop();if(Q<y&&this.getAlignY()!=m){top=y-Q;if(this.getAlignY()===j){top=Math.round(top/2);}}var G,U,L,B,I,M,E;this._clearSeparators();if(S){var T=qx.theme.manager.Decoration.getInstance().resolve(S).getInsets();var z=T.top+T.bottom;}for(i=0;i<length;i+=1){A=F[i];B=K[i];G=A.getSizeHint();M=A.getMarginLeft();E=A.getMarginRight();L=Math.max(G.minWidth,Math.min(x-M-E,G.maxWidth));U=P.computeHorizontalAlignOffset(A.getAlignX()||this.getAlignX(),L,x,M,E);if(i>0){if(S){top+=I+O;this._renderSeparator(S,{top:top,left:0,height:z,width:x});top+=z+O+A.getMarginTop();}else{top+=P.collapseMargins(O,I,A.getMarginTop());}}A.renderLayout(U,top,L,B);top+=B;I=A.getMarginBottom();}},_computeSizeHint:function(){if(this._invalidChildrenCache){this.__eW();}var bc=qx.ui.layout.Util;var bk=this.__eV;var X=0,bb=0,ba=0;var V=0,bd=0;var bh,W,bj;for(var i=0,l=bk.length;i<l;i+=1){bh=bk[i];W=bh.getSizeHint();bb+=W.height;var bg=this.__eT[i];var Y=this.__eS[i];if(bg){X+=W.minHeight;}else if(Y){ba=Math.max(ba,Math.round(W.minHeight/Y));}else{X+=W.height;}bj=bh.getMarginLeft()+bh.getMarginRight();if((W.width+bj)>bd){bd=W.width+bj;}if((W.minWidth+bj)>V){V=W.minWidth+bj;}}X+=ba;var bf=this.getSpacing();var bi=this.getSeparator();if(bi){var be=bc.computeVerticalSeparatorGaps(bk,bf,bi);}else{var be=bc.computeVerticalGaps(bk,bf,true);}return {minHeight:X+be,height:bb+be,minWidth:V,width:bd};}},destruct:function(){this.__eS=this.__eT=this.__eV=null;}});})();(function(){var b="qx.nativeScrollBars",a="qx.ui.core.scroll.MScrollBarFactory";qx.core.Setting.define(b,false);qx.Mixin.define(a,{members:{_createScrollBar:function(c){if(qx.core.Setting.get(b)){return new qx.ui.core.scroll.NativeScrollBar(c);}else{return new qx.ui.core.scroll.ScrollBar(c);}}}});})();(function(){var k="scrollbar-y",j="scrollbar-x",i="pane",h="auto",g="corner",f="scrollbar-",d="on",c="_computeScrollbars",b="getDocument",a="changeVisibility",D="off",C="x",B="scroll",A="touchmove",z="scrollY",y="Left",x="mousewheel",w="scrollbarX",v="scrollarea",u="y",r="vertical",s="scrollX",p="touchstart",q="horizontal",n="qx.ui.core.scroll.AbstractScrollArea",o="abstract",l="update",m="scrollbarY",t="Top";qx.Class.define(n,{extend:qx.ui.core.Widget,include:qx.ui.core.scroll.MScrollBarFactory,type:o,construct:function(){qx.ui.core.Widget.call(this);var E=new qx.ui.layout.Grid();E.setColumnFlex(0,1);E.setRowFlex(0,1);this._setLayout(E);this.addListener(x,this._onMouseWheel,this);if(qx.bom.client.Feature.TOUCH){this.addListener(A,this._onTouchMove,this);this.addListener(p,function(){this.__qP={"x":0,"y":0};},this);this.__qP={};this.__qQ={};}},properties:{appearance:{refine:true,init:v},width:{refine:true,init:100},height:{refine:true,init:200},scrollbarX:{check:[h,d,D],init:h,themeable:true,apply:c},scrollbarY:{check:[h,d,D],init:h,themeable:true,apply:c},scrollbar:{group:[w,m]}},members:{__qP:null,__qQ:null,_createChildControlImpl:function(F,G){var H;switch(F){case i:H=new qx.ui.core.scroll.ScrollPane();H.addListener(l,this._computeScrollbars,this);H.addListener(s,this._onScrollPaneX,this);H.addListener(z,this._onScrollPaneY,this);this._add(H,{row:0,column:0});break;case j:H=this._createScrollBar(q);H.setMinWidth(0);H.exclude();H.addListener(B,this._onScrollBarX,this);H.addListener(a,this._onChangeScrollbarXVisibility,this);this._add(H,{row:1,column:0});break;case k:H=this._createScrollBar(r);H.setMinHeight(0);H.exclude();H.addListener(B,this._onScrollBarY,this);H.addListener(a,this._onChangeScrollbarYVisibility,this);this._add(H,{row:0,column:1});break;case g:H=new qx.ui.core.Widget();H.setWidth(0);H.setHeight(0);H.exclude();this._add(H,{row:1,column:1});break;}return H||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,F);},getPaneSize:function(){return this.getChildControl(i).getInnerSize();},getItemTop:function(I){return this.getChildControl(i).getItemTop(I);},getItemBottom:function(J){return this.getChildControl(i).getItemBottom(J);},getItemLeft:function(K){return this.getChildControl(i).getItemLeft(K);},getItemRight:function(L){return this.getChildControl(i).getItemRight(L);},scrollToX:function(M){qx.ui.core.queue.Manager.flush();this.getChildControl(j).scrollTo(M);},scrollByX:function(N){qx.ui.core.queue.Manager.flush();this.getChildControl(j).scrollBy(N);},getScrollX:function(){var O=this.getChildControl(j,true);return O?O.getPosition():0;},scrollToY:function(P){qx.ui.core.queue.Manager.flush();this.getChildControl(k).scrollTo(P);},scrollByY:function(Q){qx.ui.core.queue.Manager.flush();this.getChildControl(k).scrollBy(Q);},getScrollY:function(){var R=this.getChildControl(k,true);return R?R.getPosition():0;},_onScrollBarX:function(e){this.getChildControl(i).scrollToX(e.getData());},_onScrollBarY:function(e){this.getChildControl(i).scrollToY(e.getData());},_onScrollPaneX:function(e){this.scrollToX(e.getData());},_onScrollPaneY:function(e){this.scrollToY(e.getData());},_onMouseWheel:function(e){var T=this._isChildControlVisible(j);var U=this._isChildControlVisible(k);var S=(U)?this.getChildControl(k,true):(T?this.getChildControl(j,true):null);if(S){S.scrollBySteps(e.getWheelDelta());e.stop();}},_onTouchMove:function(e){this._onTouchMoveDirectional(C,e);this._onTouchMoveDirectional(u,e);e.stop();},_onTouchMoveDirectional:function(V,e){var W=(V==C?y:t);var Y=this.getChildControl(f+V,true);var ba=this._isChildControlVisible(f+V);if(ba&&Y){if(this.__qP[V]==0){var X=0;}else{var X=-(e[b+W]()-this.__qP[V]);}this.__qP[V]=e[b+W]();Y.scrollBy(X);if(this.__qQ[V]){clearTimeout(this.__qQ[V]);this.__qQ[V]=null;}this.__qQ[V]=setTimeout(qx.lang.Function.bind(function(bb){this.__qR(bb,V);},this,X),100);}},__qR:function(bc,bd){this.__qQ[bd]=null;var bf=this._isChildControlVisible(f+bd);if(bc==0||!bf){return;}if(bc>0){bc=Math.max(0,bc-3);}else{bc=Math.min(0,bc+3);}this.__qQ[bd]=setTimeout(qx.lang.Function.bind(function(bg,bh){this.__qR(bg,bh);},this,bc,bd),20);var be=this.getChildControl(f+bd,true);be.scrollBy(bc);},_onChangeScrollbarXVisibility:function(e){var bi=this._isChildControlVisible(j);var bj=this._isChildControlVisible(k);if(!bi){this.scrollToX(0);}bi&&bj?this._showChildControl(g):this._excludeChildControl(g);},_onChangeScrollbarYVisibility:function(e){var bk=this._isChildControlVisible(j);var bl=this._isChildControlVisible(k);if(!bl){this.scrollToY(0);}bk&&bl?this._showChildControl(g):this._excludeChildControl(g);},_computeScrollbars:function(){var bs=this.getChildControl(i);var content=bs.getChildren()[0];if(!content){this._excludeChildControl(j);this._excludeChildControl(k);return;}var bm=this.getInnerSize();var br=bs.getInnerSize();var bp=bs.getScrollSize();if(!br||!bp){return;}var bt=this.getScrollbarX();var bu=this.getScrollbarY();if(bt===h&&bu===h){var bq=bp.width>bm.width;var bv=bp.height>bm.height;if((bq||bv)&&!(bq&&bv)){if(bq){bv=bp.height>br.height;}else if(bv){bq=bp.width>br.width;}}}else{var bq=bt===d;var bv=bu===d;if(bp.width>(bq?br.width:bm.width)&&bt===h){bq=true;}if(bp.height>(bq?br.height:bm.height)&&bu===h){bv=true;}}if(bq){var bo=this.getChildControl(j);bo.show();bo.setMaximum(Math.max(0,bp.width-br.width));bo.setKnobFactor((bp.width===0)?0:br.width/bp.width);}else{this._excludeChildControl(j);}if(bv){var bn=this.getChildControl(k);bn.show();bn.setMaximum(Math.max(0,bp.height-br.height));bn.setKnobFactor((bp.height===0)?0:br.height/bp.height);}else{this._excludeChildControl(k);}}}});})();(function(){var p="Integer",o="_applyContentPadding",n="resetPaddingRight",m="setPaddingBottom",l="resetPaddingTop",k="qx.ui.core.MContentPadding",j="resetPaddingLeft",i="setPaddingTop",h="setPaddingRight",g="resetPaddingBottom",c="contentPaddingLeft",f="setPaddingLeft",e="contentPaddingTop",b="shorthand",a="contentPaddingRight",d="contentPaddingBottom";qx.Mixin.define(k,{properties:{contentPaddingTop:{check:p,init:0,apply:o,themeable:true},contentPaddingRight:{check:p,init:0,apply:o,themeable:true},contentPaddingBottom:{check:p,init:0,apply:o,themeable:true},contentPaddingLeft:{check:p,init:0,apply:o,themeable:true},contentPadding:{group:[e,a,d,c],mode:b,themeable:true}},members:{__kV:{contentPaddingTop:i,contentPaddingRight:h,contentPaddingBottom:m,contentPaddingLeft:f},__kW:{contentPaddingTop:l,contentPaddingRight:n,contentPaddingBottom:g,contentPaddingLeft:j},_applyContentPadding:function(q,r,name){var s=this._getContentPaddingTarget();if(q==null){var t=this.__kW[name];s[t]();}else{var u=this.__kV[name];s[u](q);}}}});})();(function(){var v="single",u="Boolean",t="one",s="changeSelection",r="__nt",q="mouseup",p="mousedown",o="losecapture",n="multi",m="_applyQuickSelection",d="mouseover",l="_applySelectionMode",h="_applyDragSelection",c="qx.ui.core.MMultiSelectionHandling",b="removeItem",g="keypress",f="qx.event.type.Data",j="addItem",a="additive",k="mousemove";qx.Mixin.define(c,{construct:function(){var x=this.SELECTION_MANAGER;var w=this.__nt=new x(this);this.addListener(p,w.handleMouseDown,w);this.addListener(q,w.handleMouseUp,w);this.addListener(d,w.handleMouseOver,w);this.addListener(k,w.handleMouseMove,w);this.addListener(o,w.handleLoseCapture,w);this.addListener(g,w.handleKeyPress,w);this.addListener(j,w.handleAddItem,w);this.addListener(b,w.handleRemoveItem,w);w.addListener(s,this._onSelectionChange,this);},events:{"changeSelection":f},properties:{selectionMode:{check:[v,n,a,t],init:v,apply:l},dragSelection:{check:u,init:false,apply:h},quickSelection:{check:u,init:false,apply:m}},members:{__nt:null,selectAll:function(){this.__nt.selectAll();},isSelected:function(y){if(!qx.ui.core.Widget.contains(this,y)){throw new Error("Could not test if "+y+" is selected, because it is not a child element!");}return this.__nt.isItemSelected(y);},addToSelection:function(z){if(!qx.ui.core.Widget.contains(this,z)){throw new Error("Could not add + "+z+" to selection, because it is not a child element!");}this.__nt.addItem(z);},removeFromSelection:function(A){if(!qx.ui.core.Widget.contains(this,A)){throw new Error("Could not remove "+A+" from selection, because it is not a child element!");}this.__nt.removeItem(A);},selectRange:function(B,C){this.__nt.selectItemRange(B,C);},resetSelection:function(){this.__nt.clearSelection();},setSelection:function(D){for(var i=0;i<D.length;i++){if(!qx.ui.core.Widget.contains(this,D[i])){throw new Error("Could not select "+D[i]+", because it is not a child element!");}}if(D.length===0){this.resetSelection();}else{var E=this.getSelection();if(!qx.lang.Array.equals(E,D)){this.__nt.replaceSelection(D);}}},getSelection:function(){return this.__nt.getSelection();},getSortedSelection:function(){return this.__nt.getSortedSelection();},isSelectionEmpty:function(){return this.__nt.isSelectionEmpty();},getSelectionContext:function(){return this.__nt.getSelectionContext();},_getManager:function(){return this.__nt;},getSelectables:function(F){return this.__nt.getSelectables(F);},invertSelection:function(){this.__nt.invertSelection();},_getLeadItem:function(){var G=this.__nt.getMode();if(G===v||G===t){return this.__nt.getSelectedItem();}else{return this.__nt.getLeadItem();}},_applySelectionMode:function(H,I){this.__nt.setMode(H);},_applyDragSelection:function(J,K){this.__nt.setDrag(J);},_applyQuickSelection:function(L,M){this.__nt.setQuick(L);},_onSelectionChange:function(e){this.fireDataEvent(s,e.getData());}},destruct:function(){this._disposeObjects(r);}});})();(function(){var a="qx.ui.core.IMultiSelection";qx.Interface.define(a,{extend:qx.ui.core.ISingleSelection,members:{selectAll:function(){return true;},addToSelection:function(b){return arguments.length==1;},removeFromSelection:function(c){return arguments.length==1;}}});})();(function(){var o="one",n="single",m="selected",k="additive",j="multi",h="PageUp",g="under",f="Left",d="lead",c="Down",M="Up",L="Boolean",K="PageDown",J="anchor",I="End",H="Home",G="Right",F="right",E="click",D="above",v="left",w="Escape",t="A",u="Space",r="_applyMode",s="interval",p="changeSelection",q="qx.event.type.Data",x="quick",y="__oG",A="key",z="abstract",C="drag",B="qx.ui.core.selection.Abstract";qx.Class.define(B,{type:z,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__oD={};},events:{"changeSelection":q},properties:{mode:{check:[n,j,k,o],init:n,apply:r},drag:{check:L,init:false},quick:{check:L,init:false}},members:{__oE:0,__oF:0,__oG:null,__oH:null,__oI:null,__oJ:null,__oK:null,__oL:null,__oM:null,__oN:null,__oO:null,__oP:null,__oQ:null,__oR:null,__oS:null,__oT:null,__oU:null,__oD:null,__oV:null,__oW:null,_userInteraction:false,__oX:null,getSelectionContext:function(){return this.__oT;},selectAll:function(){var N=this.getMode();if(N==n||N==o){throw new Error("Can not select all items in selection mode: "+N);}this._selectAllItems();this._fireChange();},selectItem:function(O){this._setSelectedItem(O);var P=this.getMode();if(P!==n&&P!==o){this._setLeadItem(O);this._setAnchorItem(O);}this._scrollItemIntoView(O);this._fireChange();},addItem:function(Q){var R=this.getMode();if(R===n||R===o){this._setSelectedItem(Q);}else{if(!this._getAnchorItem()){this._setAnchorItem(Q);}this._setLeadItem(Q);this._addToSelection(Q);}this._scrollItemIntoView(Q);this._fireChange();},removeItem:function(S){this._removeFromSelection(S);if(this.getMode()===o&&this.isSelectionEmpty()){var T=this._getFirstSelectable();if(T){this.addItem(T);}if(T==S){return;}}if(this.getLeadItem()==S){this._setLeadItem(null);}if(this._getAnchorItem()==S){this._setAnchorItem(null);}this._fireChange();},selectItemRange:function(U,V){var W=this.getMode();if(W==n||W==o){throw new Error("Can not select multiple items in selection mode: "+W);}this._selectItemRange(U,V);this._setAnchorItem(U);this._setLeadItem(V);this._scrollItemIntoView(V);this._fireChange();},clearSelection:function(){if(this.getMode()==o){return;}this._clearSelection();this._setLeadItem(null);this._setAnchorItem(null);this._fireChange();},replaceSelection:function(X){var Y=this.getMode();if(Y==o||Y===n){if(X.length>1){throw new Error("Could not select more than one items in mode: "+Y+"!");}if(X.length==1){this.selectItem(X[0]);}else{this.clearSelection();}return;}else{this._replaceMultiSelection(X);}},getSelectedItem:function(){var ba=this.getMode();if(ba===n||ba===o){return this._getSelectedItem()||null;}throw new Error("The method getSelectedItem() is only supported in 'single' and 'one' selection mode!");},getSelection:function(){return qx.lang.Object.getValues(this.__oD);},getSortedSelection:function(){var bc=this.getSelectables();var bb=qx.lang.Object.getValues(this.__oD);bb.sort(function(a,b){return bc.indexOf(a)-bc.indexOf(b);});return bb;},isItemSelected:function(bd){var be=this._selectableToHashCode(bd);return this.__oD[be]!==undefined;},isSelectionEmpty:function(){return qx.lang.Object.isEmpty(this.__oD);},invertSelection:function(){var bg=this.getMode();if(bg===n||bg===o){throw new Error("The method invertSelection() is only supported in 'multi' and 'additive' selection mode!");}var bf=this.getSelectables();for(var i=0;i<bf.length;i++){this._toggleInSelection(bf[i]);}this._fireChange();},_setLeadItem:function(bh){var bi=this.__oU;if(bi!==null){this._styleSelectable(bi,d,false);}if(bh!==null){this._styleSelectable(bh,d,true);}this.__oU=bh;},getLeadItem:function(){return this.__oU!==null?this.__oU:null;},_setAnchorItem:function(bj){var bk=this.__oV;if(bk){this._styleSelectable(bk,J,false);}if(bj){this._styleSelectable(bj,J,true);}this.__oV=bj;},_getAnchorItem:function(){return this.__oV!==null?this.__oV:null;},_isSelectable:function(bl){throw new Error("Abstract method call: _isSelectable()");},_getSelectableFromMouseEvent:function(event){var bm=event.getTarget();if(bm&&this._isSelectable(bm)){return bm;}return null;},_selectableToHashCode:function(bn){throw new Error("Abstract method call: _selectableToHashCode()");},_styleSelectable:function(bo,bp,bq){throw new Error("Abstract method call: _styleSelectable()");},_capture:function(){throw new Error("Abstract method call: _capture()");},_releaseCapture:function(){throw new Error("Abstract method call: _releaseCapture()");},_getLocation:function(){throw new Error("Abstract method call: _getLocation()");},_getDimension:function(){throw new Error("Abstract method call: _getDimension()");},_getSelectableLocationX:function(br){throw new Error("Abstract method call: _getSelectableLocationX()");},_getSelectableLocationY:function(bs){throw new Error("Abstract method call: _getSelectableLocationY()");},_getScroll:function(){throw new Error("Abstract method call: _getScroll()");},_scrollBy:function(bt,bu){throw new Error("Abstract method call: _scrollBy()");},_scrollItemIntoView:function(bv){throw new Error("Abstract method call: _scrollItemIntoView()");},getSelectables:function(bw){throw new Error("Abstract method call: getSelectables()");},_getSelectableRange:function(bx,by){throw new Error("Abstract method call: _getSelectableRange()");},_getFirstSelectable:function(){throw new Error("Abstract method call: _getFirstSelectable()");},_getLastSelectable:function(){throw new Error("Abstract method call: _getLastSelectable()");},_getRelatedSelectable:function(bz,bA){throw new Error("Abstract method call: _getRelatedSelectable()");},_getPage:function(bB,bC){throw new Error("Abstract method call: _getPage()");},_applyMode:function(bD,bE){this._setLeadItem(null);this._setAnchorItem(null);this._clearSelection();if(bD===o){var bF=this._getFirstSelectable();if(bF){this._setSelectedItem(bF);this._scrollItemIntoView(bF);}}this._fireChange();},handleMouseOver:function(event){if(this.__oX!=null&&this.__oX!=this._getScroll().top){this.__oX=null;return;}this._userInteraction=true;if(!this.getQuick()){this._userInteraction=false;return;}var bH=this.getMode();if(bH!==o&&bH!==n){this._userInteraction=false;return;}var bG=this._getSelectableFromMouseEvent(event);if(bG===null){this._userInteraction=false;return;}this._setSelectedItem(bG);this._fireChange(x);this._userInteraction=false;},handleMouseDown:function(event){this._userInteraction=true;var bJ=this._getSelectableFromMouseEvent(event);if(bJ===null){this._userInteraction=false;return;}var bL=event.isCtrlPressed()||(qx.bom.client.Platform.MAC&&event.isMetaPressed());var bI=event.isShiftPressed();if(this.isItemSelected(bJ)&&!bI&&!bL&&!this.getDrag()){this.__oW=bJ;this._userInteraction=false;return;}else{this.__oW=null;}this._scrollItemIntoView(bJ);switch(this.getMode()){case n:case o:this._setSelectedItem(bJ);break;case k:this._setLeadItem(bJ);this._setAnchorItem(bJ);this._toggleInSelection(bJ);break;case j:this._setLeadItem(bJ);if(bI){var bK=this._getAnchorItem();if(bK===null){bK=this._getFirstSelectable();this._setAnchorItem(bK);}this._selectItemRange(bK,bJ,bL);}else if(bL){this._setAnchorItem(bJ);this._toggleInSelection(bJ);}else{this._setAnchorItem(bJ);this._setSelectedItem(bJ);}break;}var bM=this.getMode();if(this.getDrag()&&bM!==n&&bM!==o&&!bI&&!bL){this.__oK=this._getLocation();this.__oH=this._getScroll();this.__oL=event.getDocumentLeft()+this.__oH.left;this.__oM=event.getDocumentTop()+this.__oH.top;this.__oN=true;this._capture();}this._fireChange(E);this._userInteraction=false;},handleMouseUp:function(event){this._userInteraction=true;var bQ=event.isCtrlPressed()||(qx.bom.client.Platform.MAC&&event.isMetaPressed());var bN=event.isShiftPressed();if(!bQ&&!bN&&this.__oW){var bO=this._getSelectableFromMouseEvent(event);if(bO===null||!this.isItemSelected(bO)){this._userInteraction=false;return;}var bP=this.getMode();if(bP===k){this._removeFromSelection(bO);}else{this._setSelectedItem(bO);if(this.getMode()===j){this._setLeadItem(bO);this._setAnchorItem(bO);}}this._userInteraction=false;}this._cleanup();},handleLoseCapture:function(event){this._cleanup();},handleMouseMove:function(event){if(!this.__oN){return;}this.__oO=event.getDocumentLeft();this.__oP=event.getDocumentTop();this._userInteraction=true;var bS=this.__oO+this.__oH.left;if(bS>this.__oL){this.__oQ=1;}else if(bS<this.__oL){this.__oQ=-1;}else{this.__oQ=0;}var bR=this.__oP+this.__oH.top;if(bR>this.__oM){this.__oR=1;}else if(bR<this.__oM){this.__oR=-1;}else{this.__oR=0;}var location=this.__oK;if(this.__oO<location.left){this.__oE=this.__oO-location.left;}else if(this.__oO>location.right){this.__oE=this.__oO-location.right;}else{this.__oE=0;}if(this.__oP<location.top){this.__oF=this.__oP-location.top;}else if(this.__oP>location.bottom){this.__oF=this.__oP-location.bottom;}else{this.__oF=0;}if(!this.__oG){this.__oG=new qx.event.Timer(100);this.__oG.addListener(s,this._onInterval,this);}this.__oG.start();this._autoSelect();event.stopPropagation();this._userInteraction=false;},handleAddItem:function(e){var bT=e.getData();if(this.getMode()===o&&this.isSelectionEmpty()){this.addItem(bT);}},handleRemoveItem:function(e){this.removeItem(e.getData());},_cleanup:function(){if(!this.getDrag()&&this.__oN){return;}if(this.__oS){this._fireChange(E);}delete this.__oN;delete this.__oI;delete this.__oJ;this._releaseCapture();if(this.__oG){this.__oG.stop();}},_onInterval:function(e){this._scrollBy(this.__oE,this.__oF);this.__oH=this._getScroll();this._autoSelect();},_autoSelect:function(){var cd=this._getDimension();var bV=Math.max(0,Math.min(this.__oO-this.__oK.left,cd.width))+this.__oH.left;var bU=Math.max(0,Math.min(this.__oP-this.__oK.top,cd.height))+this.__oH.top;if(this.__oI===bV&&this.__oJ===bU){return;}this.__oI=bV;this.__oJ=bU;var cf=this._getAnchorItem();var bX=cf;var cb=this.__oQ;var ce,bW;while(cb!==0){ce=cb>0?this._getRelatedSelectable(bX,F):this._getRelatedSelectable(bX,v);if(ce!==null){bW=this._getSelectableLocationX(ce);if((cb>0&&bW.left<=bV)||(cb<0&&bW.right>=bV)){bX=ce;continue;}}break;}var cc=this.__oR;var ca,bY;while(cc!==0){ca=cc>0?this._getRelatedSelectable(bX,g):this._getRelatedSelectable(bX,D);if(ca!==null){bY=this._getSelectableLocationY(ca);if((cc>0&&bY.top<=bU)||(cc<0&&bY.bottom>=bU)){bX=ca;continue;}}break;}var cg=this.getMode();if(cg===j){this._selectItemRange(cf,bX);}else if(cg===k){if(this.isItemSelected(cf)){this._selectItemRange(cf,bX,true);}else{this._deselectItemRange(cf,bX);}this._setAnchorItem(bX);}this._fireChange(C);},__oY:{Home:1,Down:1,Right:1,PageDown:1,End:1,Up:1,Left:1,PageUp:1},handleKeyPress:function(event){this._userInteraction=true;var cm,cl;var co=event.getKeyIdentifier();var cn=this.getMode();var ci=event.isCtrlPressed()||(qx.bom.client.Platform.MAC&&event.isMetaPressed());var cj=event.isShiftPressed();var ck=false;if(co===t&&ci){if(cn!==n&&cn!==o){this._selectAllItems();ck=true;}}else if(co===w){if(cn!==n&&cn!==o){this._clearSelection();ck=true;}}else if(co===u){var ch=this.getLeadItem();if(ch&&!cj){if(ci||cn===k){this._toggleInSelection(ch);}else{this._setSelectedItem(ch);}ck=true;}}else if(this.__oY[co]){ck=true;if(cn===n||cn==o){cm=this._getSelectedItem();}else{cm=this.getLeadItem();}if(cm!==null){switch(co){case H:cl=this._getFirstSelectable();break;case I:cl=this._getLastSelectable();break;case M:cl=this._getRelatedSelectable(cm,D);break;case c:cl=this._getRelatedSelectable(cm,g);break;case f:cl=this._getRelatedSelectable(cm,v);break;case G:cl=this._getRelatedSelectable(cm,F);break;case h:cl=this._getPage(cm,true);break;case K:cl=this._getPage(cm,false);break;}}else{switch(co){case H:case c:case G:case K:cl=this._getFirstSelectable();break;case I:case M:case f:case h:cl=this._getLastSelectable();break;}}if(cl!==null){switch(cn){case n:case o:this._setSelectedItem(cl);break;case k:this._setLeadItem(cl);break;case j:if(cj){var cp=this._getAnchorItem();if(cp===null){this._setAnchorItem(cp=this._getFirstSelectable());}this._setLeadItem(cl);this._selectItemRange(cp,cl,ci);}else{this._setAnchorItem(cl);this._setLeadItem(cl);if(!ci){this._setSelectedItem(cl);}}break;}this.__oX=this._getScroll().top;this._scrollItemIntoView(cl);}}if(ck){event.stop();this._fireChange(A);}this._userInteraction=false;},_selectAllItems:function(){var cq=this.getSelectables();for(var i=0,l=cq.length;i<l;i++){this._addToSelection(cq[i]);}},_clearSelection:function(){var cr=this.__oD;for(var cs in cr){this._removeFromSelection(cr[cs]);}this.__oD={};},_selectItemRange:function(ct,cu,cv){var cy=this._getSelectableRange(ct,cu);if(!cv){var cx=this.__oD;var cz=this.__pa(cy);for(var cw in cx){if(!cz[cw]){this._removeFromSelection(cx[cw]);}}}for(var i=0,l=cy.length;i<l;i++){this._addToSelection(cy[i]);}},_deselectItemRange:function(cA,cB){var cC=this._getSelectableRange(cA,cB);for(var i=0,l=cC.length;i<l;i++){this._removeFromSelection(cC[i]);}},__pa:function(cD){var cF={};var cE;for(var i=0,l=cD.length;i<l;i++){cE=cD[i];cF[this._selectableToHashCode(cE)]=cE;}return cF;},_getSelectedItem:function(){for(var cG in this.__oD){return this.__oD[cG];}return null;},_setSelectedItem:function(cH){if(this._isSelectable(cH)){var cI=this.__oD;var cJ=this._selectableToHashCode(cH);if(!cI[cJ]||qx.lang.Object.hasMinLength(cI,2)){this._clearSelection();this._addToSelection(cH);}}},_addToSelection:function(cK){var cL=this._selectableToHashCode(cK);if(!this.__oD[cL]&&this._isSelectable(cK)){this.__oD[cL]=cK;this._styleSelectable(cK,m,true);this.__oS=true;}},_toggleInSelection:function(cM){var cN=this._selectableToHashCode(cM);if(!this.__oD[cN]){this.__oD[cN]=cM;this._styleSelectable(cM,m,true);}else{delete this.__oD[cN];this._styleSelectable(cM,m,false);}this.__oS=true;},_removeFromSelection:function(cO){var cP=this._selectableToHashCode(cO);if(this.__oD[cP]!=null){delete this.__oD[cP];this._styleSelectable(cO,m,false);this.__oS=true;}},_replaceMultiSelection:function(cQ){var cT=false;var cW,cV;var cR={};for(var i=0,l=cQ.length;i<l;i++){cW=cQ[i];if(this._isSelectable(cW)){cV=this._selectableToHashCode(cW);cR[cV]=cW;}}var cX=cQ[0];var cS=cW;var cU=this.__oD;for(var cV in cU){if(cR[cV]){delete cR[cV];}else{cW=cU[cV];delete cU[cV];this._styleSelectable(cW,m,false);cT=true;}}for(var cV in cR){cW=cU[cV]=cR[cV];this._styleSelectable(cW,m,true);cT=true;}if(!cT){return false;}this._scrollItemIntoView(cS);this._setLeadItem(cX);this._setAnchorItem(cX);this.__oS=true;this._fireChange();},_fireChange:function(cY){if(this.__oS){this.__oT=cY||null;this.fireDataEvent(p,this.getSelection());delete this.__oS;}}},destruct:function(){this._disposeObjects(y);this.__oD=this.__oW=this.__oV=null;this.__oU=null;}});})();(function(){var f="vertical",e="under",d="above",c="qx.ui.core.selection.Widget",b="left",a="right";qx.Class.define(c,{extend:qx.ui.core.selection.Abstract,construct:function(g){qx.ui.core.selection.Abstract.call(this);this.__nW=g;},members:{__nW:null,_isSelectable:function(h){return this._isItemSelectable(h)&&h.getLayoutParent()===this.__nW;},_selectableToHashCode:function(j){return j.$$hash;},_styleSelectable:function(k,m,n){n?k.addState(m):k.removeState(m);},_capture:function(){this.__nW.capture();},_releaseCapture:function(){this.__nW.releaseCapture();},_isItemSelectable:function(o){if(this._userInteraction){return o.isVisible()&&o.isEnabled();}else{return o.isVisible();}},_getWidget:function(){return this.__nW;},_getLocation:function(){var p=this.__nW.getContentElement().getDomElement();return p?qx.bom.element.Location.get(p):null;},_getDimension:function(){return this.__nW.getInnerSize();},_getSelectableLocationX:function(q){var r=q.getBounds();if(r){return {left:r.left,right:r.left+r.width};}},_getSelectableLocationY:function(s){var t=s.getBounds();if(t){return {top:t.top,bottom:t.top+t.height};}},_getScroll:function(){return {left:0,top:0};},_scrollBy:function(u,v){},_scrollItemIntoView:function(w){this.__nW.scrollChildIntoView(w);},getSelectables:function(x){var y=false;if(!x){y=this._userInteraction;this._userInteraction=true;}var B=this.__nW.getChildren();var z=[];var A;for(var i=0,l=B.length;i<l;i++){A=B[i];if(this._isItemSelectable(A)){z.push(A);}}this._userInteraction=y;return z;},_getSelectableRange:function(C,D){if(C===D){return [C];}var H=this.__nW.getChildren();var E=[];var G=false;var F;for(var i=0,l=H.length;i<l;i++){F=H[i];if(F===C||F===D){if(G){E.push(F);break;}else{G=true;}}if(G&&this._isItemSelectable(F)){E.push(F);}}return E;},_getFirstSelectable:function(){var I=this.__nW.getChildren();for(var i=0,l=I.length;i<l;i++){if(this._isItemSelectable(I[i])){return I[i];}}return null;},_getLastSelectable:function(){var J=this.__nW.getChildren();for(var i=J.length-1;i>0;i--){if(this._isItemSelectable(J[i])){return J[i];}}return null;},_getRelatedSelectable:function(K,L){var O=this.__nW.getOrientation()===f;var N=this.__nW.getChildren();var M=N.indexOf(K);var P;if((O&&L===d)||(!O&&L===b)){for(var i=M-1;i>=0;i--){P=N[i];if(this._isItemSelectable(P)){return P;}}}else if((O&&L===e)||(!O&&L===a)){for(var i=M+1;i<N.length;i++){P=N[i];if(this._isItemSelectable(P)){return P;}}}return null;},_getPage:function(Q,R){if(R){return this._getFirstSelectable();}else{return this._getLastSelectable();}}},destruct:function(){this.__nW=null;}});})();(function(){var a="qx.ui.core.selection.ScrollArea";qx.Class.define(a,{extend:qx.ui.core.selection.Widget,members:{_isSelectable:function(b){return this._isItemSelectable(b)&&b.getLayoutParent()===this._getWidget().getChildrenContainer();},_getDimension:function(){return this._getWidget().getPaneSize();},_getScroll:function(){var c=this._getWidget();return {left:c.getScrollX(),top:c.getScrollY()};},_scrollBy:function(d,e){var f=this._getWidget();f.scrollByX(d);f.scrollByY(e);},_getPage:function(g,h){var m=this.getSelectables();var length=m.length;var p=m.indexOf(g);if(p===-1){throw new Error("Invalid lead item: "+g);}var j=this._getWidget();var r=j.getScrollY();var innerHeight=j.getInnerSize().height;var top,l,q;if(h){var o=r;var i=p;while(1){for(;i>=0;i--){top=j.getItemTop(m[i]);if(top<o){q=i+1;break;}}if(q==null){var s=this._getFirstSelectable();return s==g?null:s;}if(q>=p){o-=innerHeight+r-j.getItemBottom(g);q=null;continue;}return m[q];}}else{var n=innerHeight+r;var i=p;while(1){for(;i<length;i++){l=j.getItemBottom(m[i]);if(l>n){q=i-1;break;}}if(q==null){var k=this._getLastSelectable();return k==g?null:k;}if(q<=p){n+=j.getItemTop(g)-r;q=null;continue;}return m[q];}}}}});})();(function(){var e="right",d="above",c="left",b="under",a="qx.ui.tree.SelectionManager";qx.Class.define(a,{extend:qx.ui.core.selection.ScrollArea,members:{_getSelectableLocationY:function(f){var g=f.getBounds();if(g){var top=this._getWidget().getItemTop(f);return {top:top,bottom:top+g.height};}},_isSelectable:function(h){return this._isItemSelectable(h)&&h instanceof qx.ui.tree.AbstractTreeItem;},_getSelectableFromMouseEvent:function(event){return this._getWidget().getTreeItem(event.getTarget());},getSelectables:function(j){var m=false;if(!j){m=this._userInteraction;this._userInteraction=true;}var l=this._getWidget();var n=[];if(l.getRoot()!=null){var k=l.getRoot().getItems(true,!!j,l.getHideRoot());for(var i=0;i<k.length;i++){if(this._isSelectable(k[i])){n.push(k[i]);}}}this._userInteraction=m;return n;},_getSelectableRange:function(o,p){if(o===p){return [o];}var q=this.getSelectables();var r=q.indexOf(o);var s=q.indexOf(p);if(r<0||s<0){return [];}if(r<s){return q.slice(r,s+1);}else{return q.slice(s,r+1);}},_getFirstSelectable:function(){return this.getSelectables()[0]||null;},_getLastSelectable:function(){var t=this.getSelectables();if(t.length>0){return t[t.length-1];}else{return null;}},_getRelatedSelectable:function(u,v){var w=this._getWidget();var x=null;switch(v){case d:x=w.getPreviousNodeOf(u,false);break;case b:x=w.getNextNodeOf(u,false);break;case c:case e:break;}if(!x){return null;}if(this._isSelectable(x)){return x;}else{return this._getRelatedSelectable(x,v);}}}});})();(function(){var l="dblclick",k="click",j="Boolean",h="excluded",g="visible",f="qx.event.type.Data",d="_applyOpenMode",c="Space",b="Left",a="Enter",z="changeOpenMode",y="_applyRootOpenClose",x="changeSelection",w="qx.ui.tree.Tree",v="tree",u="_applyHideRoot",t="changeRoot",s="_applyRoot",r="keypress",q="none",o="pane",p="Right",m="qx.ui.tree.AbstractTreeItem",n="__sv";qx.Class.define(w,{extend:qx.ui.core.scroll.AbstractScrollArea,implement:[qx.ui.core.IMultiSelection,qx.ui.form.IModelSelection,qx.ui.form.IForm],include:[qx.ui.core.MMultiSelectionHandling,qx.ui.core.MContentPadding,qx.ui.form.MModelSelection,qx.ui.form.MForm],construct:function(){qx.ui.core.scroll.AbstractScrollArea.call(this);this.__sv=new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({allowShrinkY:false,allowGrowX:true});this.getChildControl(o).add(this.__sv);this.initOpenMode();this.initRootOpenClose();this.addListener(x,this._onChangeSelection,this);this.addListener(r,this._onKeyPress,this);},events:{addItem:f,removeItem:f},properties:{openMode:{check:[k,l,q],init:l,apply:d,event:z,themeable:true},root:{check:m,init:null,nullable:true,event:t,apply:s},hideRoot:{check:j,init:false,apply:u},rootOpenClose:{check:j,init:false,apply:y},appearance:{refine:true,init:v},focusable:{refine:true,init:true}},members:{__sv:null,SELECTION_MANAGER:qx.ui.tree.SelectionManager,getChildrenContainer:function(){return this.__sv;},_applyRoot:function(A,B){var C=this.getChildrenContainer();if(B){C.remove(B);if(B.hasChildren()){C.remove(B.getChildrenContainer());}}if(A){C.add(A);if(A.hasChildren()){C.add(A.getChildrenContainer());}A.setVisibility(this.getHideRoot()?h:g);A.recursiveAddToWidgetQueue();}},_applyHideRoot:function(D,E){var F=this.getRoot();if(!F){return;}F.setVisibility(D?h:g);F.recursiveAddToWidgetQueue();},_applyRootOpenClose:function(G,H){var I=this.getRoot();if(!I){return;}I.recursiveAddToWidgetQueue();},_getContentPaddingTarget:function(){return this.__sv;},getNextNodeOf:function(J,K){if((K!==false||J.isOpen())&&J.hasChildren()){return J.getChildren()[0];}while(J){var parent=J.getParent();if(!parent){return null;}var M=parent.getChildren();var L=M.indexOf(J);if(L>-1&&L<M.length-1){return M[L+1];}J=parent;}return null;},getPreviousNodeOf:function(N,O){var parent=N.getParent();if(!parent){return null;}if(this.getHideRoot()){if(parent==this.getRoot()){if(parent.getChildren()[0]==N){return null;}}}else{if(N==this.getRoot()){return null;}}var R=parent.getChildren();var P=R.indexOf(N);if(P>0){var Q=R[P-1];while((O!==false||Q.isOpen())&&Q.hasChildren()){var S=Q.getChildren();Q=S[S.length-1];}return Q;}else{return parent;}},getNextSiblingOf:function(T){if(T==this.getRoot()){return null;}var parent=T.getParent();var U=parent.getChildren();var V=U.indexOf(T);if(V<U.length-1){return U[V+1];}return null;},getPreviousSiblingOf:function(W){if(W==this.getRoot()){return null;}var parent=W.getParent();var X=parent.getChildren();var Y=X.indexOf(W);if(Y>0){return X[Y-1];}return null;},getItems:function(ba,bb){if(this.getRoot()!=null){return this.getRoot().getItems(ba,bb,this.getHideRoot());}else{return [];}},getChildren:function(){if(this.getRoot()!=null){return [this.getRoot()];}else{return [];}},getTreeItem:function(bc){while(bc){if(bc==this){return null;}if(bc instanceof qx.ui.tree.AbstractTreeItem){return bc;}bc=bc.getLayoutParent();}return null;},_applyOpenMode:function(bd,be){if(be==k){this.removeListener(k,this._onOpen,this);}else if(be==l){this.removeListener(l,this._onOpen,this);}if(bd==k){this.addListener(k,this._onOpen,this);}else if(bd==l){this.addListener(l,this._onOpen,this);}},_onOpen:function(e){var bf=this.getTreeItem(e.getTarget());if(!bf||!bf.isOpenable()){return;}bf.setOpen(!bf.isOpen());e.stopPropagation();},_onChangeSelection:function(e){var bh=e.getData();for(var i=0;i<bh.length;i++){var bg=bh[i];while(bg.getParent()!=null){bg=bg.getParent();bg.setOpen(true);}}},_onKeyPress:function(e){var bi=this._getLeadItem();if(bi!==null){switch(e.getKeyIdentifier()){case b:if(bi.isOpenable()&&bi.isOpen()){bi.setOpen(false);}break;case p:if(bi.isOpenable()&&!bi.isOpen()){bi.setOpen(true);}break;case a:case c:if(bi.isOpenable()){bi.toggleOpen();}break;}}}},destruct:function(){this._disposeObjects(n);}});})();(function(){var d=".",c="apiviewer.ui.PackageTree",b="Documentation",a="__SR";qx.Class.define(c,{extend:qx.ui.tree.Tree,construct:function(){qx.ui.tree.Tree.call(this,b);this.setDecorator(null);this.__SR=new qx.ui.tree.TreeFolder("Packages");this.__SR.setOpen(true);this.setRoot(this.__SR);this.setSelection([this.__SR]);this._classTreeNodeHash={};},members:{__SR:null,setTreeData:function(e){this._docTree=e;this.__ST(this.__SR,e,0);if(this._wantedClassName){this.selectTreeNodeByClassName(this._wantedClassName);this._wantedClassName=null;}},selectTreeNodeByClassName:function(f){if(this._docTree==null){this._wantedClassName=f;return true;}var j=f.split(d);var h=j[0];var i=0;do{var g=this._classTreeNodeHash[h];if(!g){return false;}if(!g.loaded){g.setOpen(true);}i++;h+=d+j[i];}while(i<j.length);this.setSelection([g]);this.scrollChildIntoView(g);return true;},__SS:function(k,l,m){var self=this;return function(){if(!k.loaded){self.__ST(k,l,m+1);k.setOpenSymbolMode("always");}};},__ST:function(n,o,p){n.loaded=true;var s=apiviewer.ui.PackageTree;var q=o.getPackages();for(var i=0;i<q.length;i++){var r=q[i];var v=apiviewer.TreeUtil.getIconUrl(r);var w=new qx.ui.tree.TreeFolder(r.getName());w.setIcon(v);w.setOpenSymbolMode("always");w.setUserData("nodeName",r.getFullName());n.add(w);w.addListener("changeOpen",this.__SS(w,r,p+1),this);if(p<qx.core.Setting.get("apiviewer.initialTreeDepth")&&r.getPackages().length>0){w.setOpen(true);}this._classTreeNodeHash[r.getFullName()]=w;}var x=o.getClasses();for(var i=0;i<x.length;i++){var u=x[i];var v=apiviewer.TreeUtil.getIconUrl(u);var t=new qx.ui.tree.TreeFolder(u.getName());t.setIcon(v);t.setUserData("nodeName",u.getFullName());t.treeType=s.PACKAGE_TREE;n.add(t);this._classTreeNodeHash[u.getFullName()]=t;}}},destruct:function(){this._docTree=this._classTreeNodeHash=null;this._disposeObjects(a);}});})();(function(){var b="qx.ui.core.scroll.IScrollBar",a="qx.event.type.Data";qx.Interface.define(b,{events:{"scroll":a},properties:{orientation:{},maximum:{},position:{},knobFactor:{}},members:{scrollTo:function(c){this.assertNumber(c);},scrollBy:function(d){this.assertNumber(d);},scrollBySteps:function(e){this.assertNumber(e);}}});})();(function(){var k="horizontal",j="px",i="scroll",h="vertical",g="-1px",f="qx.client",d="0",c="hidden",b="mousedown",a="qx.ui.core.scroll.NativeScrollBar",z="PositiveNumber",y="__pT",x="Integer",w="mousemove",v="_applyMaximum",u="_applyOrientation",t="appear",s="opera",r="PositiveInteger",q="mshtml",o="mouseup",p="Number",m="_applyPosition",n="scrollbar",l="native";qx.Class.define(a,{extend:qx.ui.core.Widget,implement:qx.ui.core.scroll.IScrollBar,construct:function(A){qx.ui.core.Widget.call(this);this.addState(l);this.getContentElement().addListener(i,this._onScroll,this);this.addListener(b,this._stopPropagation,this);this.addListener(o,this._stopPropagation,this);this.addListener(w,this._stopPropagation,this);if(qx.core.Variant.isSet(f,s)){this.addListener(t,this._onAppear,this);}this.getContentElement().add(this._getScrollPaneElement());if(A!=null){this.setOrientation(A);}else{this.initOrientation();}},properties:{appearance:{refine:true,init:n},orientation:{check:[k,h],init:k,apply:u},maximum:{check:r,apply:v,init:100},position:{check:p,init:0,apply:m,event:i},singleStep:{check:x,init:20},knobFactor:{check:z,nullable:true}},members:{__pS:null,__pT:null,_getScrollPaneElement:function(){if(!this.__pT){this.__pT=new qx.html.Element();}return this.__pT;},renderLayout:function(B,top,C,D){var E=qx.ui.core.Widget.prototype.renderLayout.call(this,B,top,C,D);this._updateScrollBar();return E;},_getContentHint:function(){var F=qx.bom.element.Overflow.getScrollbarWidth();return {width:this.__pS?100:F,maxWidth:this.__pS?null:F,minWidth:this.__pS?null:F,height:this.__pS?F:100,maxHeight:this.__pS?F:null,minHeight:this.__pS?F:null};},_applyEnabled:function(G,H){qx.ui.core.Widget.prototype._applyEnabled.call(this,G,H);this._updateScrollBar();},_applyMaximum:function(I){this._updateScrollBar();},_applyPosition:function(J){var content=this.getContentElement();if(this.__pS){content.scrollToX(J);}else{content.scrollToY(J);}},_applyOrientation:function(K,L){var M=this.__pS=K===k;this.set({allowGrowX:M,allowShrinkX:M,allowGrowY:!M,allowShrinkY:!M});if(M){this.replaceState(h,k);}else{this.replaceState(k,h);}this.getContentElement().setStyles({overflowX:M?i:c,overflowY:M?c:i});qx.ui.core.queue.Layout.add(this);},_updateScrollBar:function(){var O=this.__pS;var P=this.getBounds();if(!P){return;}if(this.isEnabled()){var Q=O?P.width:P.height;var N=this.getMaximum()+Q;}else{N=0;}if(qx.core.Variant.isSet(f,q)){var P=this.getBounds();this.getContentElement().setStyles({left:O?d:g,top:O?g:d,width:(O?P.width:P.width+1)+j,height:(O?P.height+1:P.height)+j});}this._getScrollPaneElement().setStyles({left:0,top:0,width:(O?N:1)+j,height:(O?1:N)+j});this.scrollTo(this.getPosition());},scrollTo:function(R){this.setPosition(Math.max(0,Math.min(this.getMaximum(),R)));},scrollBy:function(S){this.scrollTo(this.getPosition()+S);},scrollBySteps:function(T){var U=this.getSingleStep();this.scrollBy(T*U);},_onScroll:function(e){var W=this.getContentElement();var V=this.__pS?W.getScrollX():W.getScrollY();this.setPosition(V);},_onAppear:function(e){this.scrollTo(this.getPosition());},_stopPropagation:function(e){e.stopPropagation();}},destruct:function(){this._disposeObjects(y);}});})();(function(){var k="slider",j="horizontal",i="button-begin",h="vertical",g="button-end",f="Integer",d="execute",c="right",b="left",a="down",z="up",y="PositiveNumber",x="changeValue",w="qx.lang.Type.isNumber(value)&&value>=0&&value<=this.getMaximum()",v="_applyKnobFactor",u="knob",t="qx.ui.core.scroll.ScrollBar",s="resize",r="_applyOrientation",q="_applyPageStep",o="PositiveInteger",p="scroll",m="_applyPosition",n="scrollbar",l="_applyMaximum";qx.Class.define(t,{extend:qx.ui.core.Widget,implement:qx.ui.core.scroll.IScrollBar,construct:function(A){qx.ui.core.Widget.call(this);this._createChildControl(i);this._createChildControl(k).addListener(s,this._onResizeSlider,this);this._createChildControl(g);if(A!=null){this.setOrientation(A);}else{this.initOrientation();}},properties:{appearance:{refine:true,init:n},orientation:{check:[j,h],init:j,apply:r},maximum:{check:o,apply:l,init:100},position:{check:w,init:0,apply:m,event:p},singleStep:{check:f,init:20},pageStep:{check:f,init:10,apply:q},knobFactor:{check:y,apply:v,nullable:true}},members:{__oC:2,_createChildControlImpl:function(B,C){var D;switch(B){case k:D=new qx.ui.core.scroll.ScrollSlider();D.setPageStep(100);D.setFocusable(false);D.addListener(x,this._onChangeSliderValue,this);this._add(D,{flex:1});break;case i:D=new qx.ui.form.RepeatButton();D.setFocusable(false);D.addListener(d,this._onExecuteBegin,this);this._add(D);break;case g:D=new qx.ui.form.RepeatButton();D.setFocusable(false);D.addListener(d,this._onExecuteEnd,this);this._add(D);break;}return D||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,B);},_applyMaximum:function(E){this.getChildControl(k).setMaximum(E);},_applyPosition:function(F){this.getChildControl(k).setValue(F);},_applyKnobFactor:function(G){this.getChildControl(k).setKnobFactor(G);},_applyPageStep:function(H){this.getChildControl(k).setPageStep(H);},_applyOrientation:function(I,J){var K=this._getLayout();if(K){K.dispose();}if(I===j){this._setLayout(new qx.ui.layout.HBox());this.setAllowStretchX(true);this.setAllowStretchY(false);this.replaceState(h,j);this.getChildControl(i).replaceState(z,b);this.getChildControl(g).replaceState(a,c);}else{this._setLayout(new qx.ui.layout.VBox());this.setAllowStretchX(false);this.setAllowStretchY(true);this.replaceState(j,h);this.getChildControl(i).replaceState(b,z);this.getChildControl(g).replaceState(c,a);}this.getChildControl(k).setOrientation(I);},scrollTo:function(L){this.getChildControl(k).slideTo(L);},scrollBy:function(M){this.getChildControl(k).slideBy(M);},scrollBySteps:function(N){var O=this.getSingleStep();this.getChildControl(k).slideBy(N*O);},_onExecuteBegin:function(e){this.scrollBy(-this.getSingleStep());},_onExecuteEnd:function(e){this.scrollBy(this.getSingleStep());},_onChangeSliderValue:function(e){this.setPosition(e.getData());},_onResizeSlider:function(e){var P=this.getChildControl(k).getChildControl(u);var S=P.getSizeHint();var Q=false;var R=this.getChildControl(k).getInnerSize();if(this.getOrientation()==h){if(R.height<S.minHeight+this.__oC){Q=true;}}else{if(R.width<S.minWidth+this.__oC){Q=true;}}if(Q){P.exclude();}else{P.show();}}}});})();(function(){var a="qx.ui.form.IRange";qx.Interface.define(a,{members:{setMinimum:function(b){return arguments.length==1;},getMinimum:function(){},setMaximum:function(c){return arguments.length==1;},getMaximum:function(){},setSingleStep:function(d){return arguments.length==1;},getSingleStep:function(){},setPageStep:function(e){return arguments.length==1;},getPageStep:function(){}}});})();(function(){var b="qx.ui.form.INumberForm",a="qx.event.type.Data";qx.Interface.define(b,{events:{"changeValue":a},members:{setValue:function(c){return arguments.length==1;},resetValue:function(){},getValue:function(){}}});})();(function(){var k="knob",j="horizontal",i="vertical",h="Integer",g="hovered",f="left",d="top",c="mouseup",b="pressed",a="px",V="changeValue",U="interval",T="mousemove",S="resize",R="slider",Q="mousedown",P="PageUp",O="mouseout",N='qx.event.type.Data',M="Left",r="Down",s="Up",p="dblclick",q="qx.ui.form.Slider",n="PageDown",o="mousewheel",l="_applyValue",m="_applyKnobFactor",t="End",u="height",B="Right",z="width",F="_applyOrientation",D="Home",I="mouseover",H="floor",w="_applyMinimum",L="click",K="typeof value==='number'&&value>=this.getMinimum()&&value<=this.getMaximum()",J="keypress",v="ceil",x="losecapture",y="contextmenu",A="_applyMaximum",C="Number",E="changeMaximum",G="changeMinimum";qx.Class.define(q,{extend:qx.ui.core.Widget,implement:[qx.ui.form.IForm,qx.ui.form.INumberForm,qx.ui.form.IRange],include:[qx.ui.form.MForm],construct:function(W){qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.layout.Canvas());this.addListener(J,this._onKeyPress);this.addListener(o,this._onMouseWheel);this.addListener(Q,this._onMouseDown);this.addListener(c,this._onMouseUp);this.addListener(x,this._onMouseUp);this.addListener(S,this._onUpdate);this.addListener(y,this._onStopEvent);this.addListener(L,this._onStopEvent);this.addListener(p,this._onStopEvent);if(W!=null){this.setOrientation(W);}else{this.initOrientation();}},events:{changeValue:N},properties:{appearance:{refine:true,init:R},focusable:{refine:true,init:true},orientation:{check:[j,i],init:j,apply:F},value:{check:K,init:0,apply:l,nullable:true},minimum:{check:h,init:0,apply:w,event:G},maximum:{check:h,init:100,apply:A,event:E},singleStep:{check:h,init:1},pageStep:{check:h,init:10},knobFactor:{check:C,apply:m,nullable:true}},members:{__nA:null,__nB:null,__nC:null,__nD:null,__nE:null,__nF:null,__nG:null,__nH:null,__nI:null,__nJ:null,__nK:null,__nL:null,_forwardStates:{invalid:true},_createChildControlImpl:function(X,Y){var ba;switch(X){case k:ba=new qx.ui.core.Widget();ba.addListener(S,this._onUpdate,this);ba.addListener(I,this._onMouseOver);ba.addListener(O,this._onMouseOut);this._add(ba);break;}return ba||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,X);},_onMouseOver:function(e){this.addState(g);},_onMouseOut:function(e){this.removeState(g);},_onMouseWheel:function(e){var bb=e.getWheelDelta()>0?1:-1;this.slideBy(bb*this.getSingleStep());e.stop();},_onKeyPress:function(e){var bd=this.getOrientation()===j;var bc=bd?M:s;var forward=bd?B:r;switch(e.getKeyIdentifier()){case forward:this.slideForward();break;case bc:this.slideBack();break;case n:this.slidePageForward();break;case P:this.slidePageBack();break;case D:this.slideToBegin();break;case t:this.slideToEnd();break;default:return;}e.stop();},_onMouseDown:function(e){if(this.__nD){return;}var bg=this.__nN;var be=this.getChildControl(k);var bf=bg?f:d;var bi=bg?e.getDocumentLeft():e.getDocumentTop();var bj=this.__nA=qx.bom.element.Location.get(this.getContentElement().getDomElement())[bf];var bh=this.__nB=qx.bom.element.Location.get(be.getContainerElement().getDomElement())[bf];if(e.getTarget()===be){this.__nD=true;if(!this.__nJ){this.__nJ=new qx.event.Timer(100);this.__nJ.addListener(U,this._fireValue,this);}this.__nJ.start();this.__nE=bi+bj-bh;be.addState(b);}else{this.__nF=true;this.__nG=bi<=bh?-1:1;this.__nO(e);this._onInterval();if(!this.__nI){this.__nI=new qx.event.Timer(100);this.__nI.addListener(U,this._onInterval,this);}this.__nI.start();}this.addListener(T,this._onMouseMove);this.capture();e.stopPropagation();},_onMouseUp:function(e){if(this.__nD){this.releaseCapture();delete this.__nD;this.__nJ.stop();this._fireValue();delete this.__nE;this.getChildControl(k).removeState(b);if(e.getType()===c){var bl;var bm;var bk;if(this.__nN){bl=e.getDocumentLeft()-(this._valueToPosition(this.getValue())+this.__nA);bk=qx.bom.element.Location.get(this.getContentElement().getDomElement())[d];bm=e.getDocumentTop()-(bk+this.getChildControl(k).getBounds().top);}else{bl=e.getDocumentTop()-(this._valueToPosition(this.getValue())+this.__nA);bk=qx.bom.element.Location.get(this.getContentElement().getDomElement())[f];bm=e.getDocumentLeft()-(bk+this.getChildControl(k).getBounds().left);}if(bm<0||bm>this.__nC||bl<0||bl>this.__nC){this.getChildControl(k).removeState(g);}}}else if(this.__nF){this.__nI.stop();this.releaseCapture();delete this.__nF;delete this.__nG;delete this.__nH;}this.removeListener(T,this._onMouseMove);if(e.getType()===c){e.stopPropagation();}},_onMouseMove:function(e){if(this.__nD){var bo=this.__nN?e.getDocumentLeft():e.getDocumentTop();var bn=bo-this.__nE;this.slideTo(this._positionToValue(bn));}else if(this.__nF){this.__nO(e);}e.stopPropagation();},_onInterval:function(e){var bp=this.getValue()+(this.__nG*this.getPageStep());if(bp<this.getMinimum()){bp=this.getMinimum();}else if(bp>this.getMaximum()){bp=this.getMaximum();}var bq=this.__nG==-1;if((bq&&bp<=this.__nH)||(!bq&&bp>=this.__nH)){bp=this.__nH;}this.slideTo(bp);},_onUpdate:function(e){var bs=this.getInnerSize();var bt=this.getChildControl(k).getBounds();var br=this.__nN?z:u;this._updateKnobSize();this.__nM=bs[br]-bt[br];this.__nC=bt[br];this._updateKnobPosition();},__nN:false,__nM:0,__nO:function(e){var bu=this.__nN;var bB=bu?e.getDocumentLeft():e.getDocumentTop();var bD=this.__nA;var bv=this.__nB;var bF=this.__nC;var bC=bB-bD;if(bB>=bv){bC-=bF;}var bz=this._positionToValue(bC);var bw=this.getMinimum();var bx=this.getMaximum();if(bz<bw){bz=bw;}else if(bz>bx){bz=bx;}else{var bA=this.getValue();var by=this.getPageStep();var bE=this.__nG<0?H:v;bz=bA+(Math[bE]((bz-bA)/by)*by);}if(this.__nH==null||(this.__nG==-1&&bz<=this.__nH)||(this.__nG==1&&bz>=this.__nH)){this.__nH=bz;}},_positionToValue:function(bG){var bH=this.__nM;if(bH==null||bH==0){return 0;}var bJ=bG/bH;if(bJ<0){bJ=0;}else if(bJ>1){bJ=1;}var bI=this.getMaximum()-this.getMinimum();return this.getMinimum()+Math.round(bI*bJ);},_valueToPosition:function(bK){var bL=this.__nM;if(bL==null){return 0;}var bM=this.getMaximum()-this.getMinimum();if(bM==0){return 0;}var bK=bK-this.getMinimum();var bN=bK/bM;if(bN<0){bN=0;}else if(bN>1){bN=1;}return Math.round(bL*bN);},_updateKnobPosition:function(){this._setKnobPosition(this._valueToPosition(this.getValue()));},_setKnobPosition:function(bO){var bP=this.getChildControl(k).getContainerElement();if(this.__nN){bP.setStyle(f,bO+a,true);}else{bP.setStyle(d,bO+a,true);}},_updateKnobSize:function(){var bR=this.getKnobFactor();if(bR==null){return;}var bQ=this.getInnerSize();if(bQ==null){return;}if(this.__nN){this.getChildControl(k).setWidth(Math.round(bR*bQ.width));}else{this.getChildControl(k).setHeight(Math.round(bR*bQ.height));}},slideToBegin:function(){this.slideTo(this.getMinimum());},slideToEnd:function(){this.slideTo(this.getMaximum());},slideForward:function(){this.slideBy(this.getSingleStep());},slideBack:function(){this.slideBy(-this.getSingleStep());},slidePageForward:function(){this.slideBy(this.getPageStep());},slidePageBack:function(){this.slideBy(-this.getPageStep());},slideBy:function(bS){this.slideTo(this.getValue()+bS);},slideTo:function(bT){if(bT<this.getMinimum()){bT=this.getMinimum();}else if(bT>this.getMaximum()){bT=this.getMaximum();}else{bT=this.getMinimum()+Math.round((bT-this.getMinimum())/this.getSingleStep())*this.getSingleStep();}this.setValue(bT);},_applyOrientation:function(bU,bV){var bW=this.getChildControl(k);this.__nN=bU===j;if(this.__nN){this.removeState(i);bW.removeState(i);this.addState(j);bW.addState(j);bW.setLayoutProperties({top:0,right:null,bottom:0});}else{this.removeState(j);bW.removeState(j);this.addState(i);bW.addState(i);bW.setLayoutProperties({right:0,bottom:null,left:0});}this._updateKnobPosition();},_applyKnobFactor:function(bX,bY){if(bX!=null){this._updateKnobSize();}else{if(this.__nN){this.getChildControl(k).resetWidth();}else{this.getChildControl(k).resetHeight();}}},_applyValue:function(ca,cb){if(ca!=null){this._updateKnobPosition();if(this.__nD){this.__nL=[ca,cb];}else{this.fireEvent(V,qx.event.type.Data,[ca,cb]);}}else{this.resetValue();}},_fireValue:function(){if(!this.__nL){return;}var cc=this.__nL;this.__nL=null;this.fireEvent(V,qx.event.type.Data,cc);},_applyMinimum:function(cd,ce){if(this.getValue()<cd){this.setValue(cd);}this._updateKnobPosition();},_applyMaximum:function(cf,cg){if(this.getValue()>cf){this.setValue(cf);}this._updateKnobPosition();}}});})();(function(){var d="horizontal",c="mousewheel",b="qx.ui.core.scroll.ScrollSlider",a="keypress";qx.Class.define(b,{extend:qx.ui.form.Slider,construct:function(e){qx.ui.form.Slider.call(this,e);this.removeListener(a,this._onKeyPress);this.removeListener(c,this._onMouseWheel);},members:{getSizeHint:function(f){var g=qx.ui.form.Slider.prototype.getSizeHint.call(this);if(this.getOrientation()===d){g.width=0;}else{g.height=0;}return g;}}});})();(function(){var n="pressed",m="abandoned",l="Integer",k="hovered",j="qx.event.type.Event",i="Enter",h="Space",g="press",f="qx.ui.form.RepeatButton",d="release",a="interval",c="__nS",b="execute";qx.Class.define(f,{extend:qx.ui.form.Button,construct:function(o,p){qx.ui.form.Button.call(this,o,p);this.__nS=new qx.event.AcceleratingTimer();this.__nS.addListener(a,this._onInterval,this);},events:{"execute":j,"press":j,"release":j},properties:{interval:{check:l,init:100},firstInterval:{check:l,init:500},minTimer:{check:l,init:20},timerDecrease:{check:l,init:2}},members:{__nT:null,__nS:null,press:function(){if(this.isEnabled()){if(!this.hasState(n)){this.__nU();}this.removeState(m);this.addState(n);}},release:function(q){if(!this.isEnabled()){return;}if(this.hasState(n)){if(!this.__nT){this.execute();}}this.removeState(n);this.removeState(m);this.__nV();},_applyEnabled:function(r,s){qx.ui.form.Button.prototype._applyEnabled.call(this,r,s);if(!r){this.removeState(n);this.removeState(m);this.__nV();}},_onMouseOver:function(e){if(!this.isEnabled()||e.getTarget()!==this){return;}if(this.hasState(m)){this.removeState(m);this.addState(n);this.__nS.start();}this.addState(k);},_onMouseOut:function(e){if(!this.isEnabled()||e.getTarget()!==this){return;}this.removeState(k);if(this.hasState(n)){this.removeState(n);this.addState(m);this.__nS.stop();}},_onMouseDown:function(e){if(!e.isLeftPressed()){return;}this.capture();this.__nU();e.stopPropagation();},_onMouseUp:function(e){this.releaseCapture();if(!this.hasState(m)){this.addState(k);if(this.hasState(n)&&!this.__nT){this.execute();}}this.__nV();e.stopPropagation();},_onKeyUp:function(e){switch(e.getKeyIdentifier()){case i:case h:if(this.hasState(n)){if(!this.__nT){this.execute();}this.removeState(n);this.removeState(m);e.stopPropagation();this.__nV();}}},_onKeyDown:function(e){switch(e.getKeyIdentifier()){case i:case h:this.removeState(m);this.addState(n);e.stopPropagation();this.__nU();}},_onInterval:function(e){this.__nT=true;this.fireEvent(b);},__nU:function(){this.fireEvent(g);this.__nT=false;this.__nS.set({interval:this.getInterval(),firstInterval:this.getFirstInterval(),minimum:this.getMinTimer(),decrease:this.getTimerDecrease()}).start();this.removeState(m);this.addState(n);},__nV:function(){this.fireEvent(d);this.__nS.stop();this.removeState(m);this.removeState(n);}},destruct:function(){this._disposeObjects(c);}});})();(function(){var e="Integer",d="interval",c="qx.event.type.Event",b="qx.event.AcceleratingTimer",a="__qn";qx.Class.define(b,{extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__qn=new qx.event.Timer(this.getInterval());this.__qn.addListener(d,this._onInterval,this);},events:{"interval":c},properties:{interval:{check:e,init:100},firstInterval:{check:e,init:500},minimum:{check:e,init:20},decrease:{check:e,init:2}},members:{__qn:null,__qo:null,start:function(){this.__qn.setInterval(this.getFirstInterval());this.__qn.start();},stop:function(){this.__qn.stop();this.__qo=null;},_onInterval:function(){this.__qn.stop();if(this.__qo==null){this.__qo=this.getInterval();}this.__qo=Math.max(this.getMinimum(),this.__qo-this.getDecrease());this.__qn.setInterval(this.__qo);this.__qn.start();this.fireEvent(d);}},destruct:function(){this._disposeObjects(a);}});})();(function(){var n="_applyLayoutChange",m="left",k="center",j="top",h="Decorator",g="middle",f="_applyReversed",e="bottom",d="Boolean",c="right",a="Integer",b="qx.ui.layout.HBox";qx.Class.define(b,{extend:qx.ui.layout.Abstract,construct:function(o,p,q){qx.ui.layout.Abstract.call(this);if(o){this.setSpacing(o);}if(p){this.setAlignX(p);}if(q){this.setSeparator(q);}},properties:{alignX:{check:[m,k,c],init:m,apply:n},alignY:{check:[j,g,e],init:j,apply:n},spacing:{check:a,init:0,apply:n},separator:{check:h,nullable:true,apply:n},reversed:{check:d,init:false,apply:f}},members:{__cP:null,__cQ:null,__cR:null,__cS:null,_applyReversed:function(){this._invalidChildrenCache=true;this._applyLayoutChange();},__cT:function(){var w=this._getLayoutChildren();var length=w.length;var t=false;var r=this.__cP&&this.__cP.length!=length&&this.__cQ&&this.__cP;var u;var s=r?this.__cP:new Array(length);var v=r?this.__cQ:new Array(length);if(this.getReversed()){w=w.concat().reverse();}for(var i=0;i<length;i++){u=w[i].getLayoutProperties();if(u.width!=null){s[i]=parseFloat(u.width)/100;}if(u.flex!=null){v[i]=u.flex;t=true;}else{v[i]=0;}}if(!r){this.__cP=s;this.__cQ=v;}this.__cR=t;this.__cS=w;delete this._invalidChildrenCache;},verifyLayoutProperty:null,renderLayout:function(x,y){if(this._invalidChildrenCache){this.__cT();}var E=this.__cS;var length=E.length;var N=qx.ui.layout.Util;var M=this.getSpacing();var Q=this.getSeparator();if(Q){var B=N.computeHorizontalSeparatorGaps(E,M,Q);}else{var B=N.computeHorizontalGaps(E,M,true);}var i,z,K,J;var P=[];var F=B;for(i=0;i<length;i+=1){J=this.__cP[i];K=J!=null?Math.floor((x-B)*J):E[i].getSizeHint().width;P.push(K);F+=K;}if(this.__cR&&F!=x){var H={};var L,O;for(i=0;i<length;i+=1){L=this.__cQ[i];if(L>0){G=E[i].getSizeHint();H[i]={min:G.minWidth,value:P[i],max:G.maxWidth,flex:L};}}var C=N.computeFlexOffsets(H,x,F);for(i in C){O=C[i].offset;P[i]+=O;F+=O;}}var U=E[0].getMarginLeft();if(F<x&&this.getAlignX()!=m){U=x-F;if(this.getAlignX()===k){U=Math.round(U/2);}}var G,top,A,K,D,S,I;var M=this.getSpacing();this._clearSeparators();if(Q){var R=qx.theme.manager.Decoration.getInstance().resolve(Q).getInsets();var T=R.left+R.right;}for(i=0;i<length;i+=1){z=E[i];K=P[i];G=z.getSizeHint();S=z.getMarginTop();I=z.getMarginBottom();A=Math.max(G.minHeight,Math.min(y-S-I,G.maxHeight));top=N.computeVerticalAlignOffset(z.getAlignY()||this.getAlignY(),A,y,S,I);if(i>0){if(Q){U+=D+M;this._renderSeparator(Q,{left:U,top:0,width:T,height:y});U+=T+M+z.getMarginLeft();}else{U+=N.collapseMargins(M,D,z.getMarginLeft());}}z.renderLayout(U,top,K,A);U+=K;D=z.getMarginRight();}},_computeSizeHint:function(){if(this._invalidChildrenCache){this.__cT();}var bc=qx.ui.layout.Util;var bk=this.__cS;var V=0,bd=0,ba=0;var Y=0,bb=0;var bh,W,bj;for(var i=0,l=bk.length;i<l;i+=1){bh=bk[i];W=bh.getSizeHint();bd+=W.width;var bg=this.__cQ[i];var X=this.__cP[i];if(bg){V+=W.minWidth;}else if(X){ba=Math.max(ba,Math.round(W.minWidth/X));}else{V+=W.width;}bj=bh.getMarginTop()+bh.getMarginBottom();if((W.height+bj)>bb){bb=W.height+bj;}if((W.minHeight+bj)>Y){Y=W.minHeight+bj;}}V+=ba;var bf=this.getSpacing();var bi=this.getSeparator();if(bi){var be=bc.computeHorizontalSeparatorGaps(bk,bf,bi);}else{var be=bc.computeHorizontalGaps(bk,bf,true);}return {minWidth:V+be,width:bd+be,minHeight:Y,height:bb};}},destruct:function(){this.__cP=this.__cQ=this.__cS=null;}});})();(function(){var m="resize",l="scrollY",k="update",j="scrollX",i="_applyScrollX",h="_applyScrollY",g="qx.lang.Type.isNumber(value)&&value>=0&&value<=this.getScrollMaxX()",f="appear",d="qx.lang.Type.isNumber(value)&&value>=0&&value<=this.getScrollMaxY()",c="qx.event.type.Event",a="qx.ui.core.scroll.ScrollPane",b="scroll";qx.Class.define(a,{extend:qx.ui.core.Widget,construct:function(){qx.ui.core.Widget.call(this);this.set({minWidth:0,minHeight:0});this._setLayout(new qx.ui.layout.Grow());this.addListener(m,this._onUpdate);var n=this.getContentElement();n.addListener(b,this._onScroll,this);n.addListener(f,this._onAppear,this);},events:{update:c},properties:{scrollX:{check:g,apply:i,event:j,init:0},scrollY:{check:d,apply:h,event:l,init:0}},members:{add:function(o){var p=this._getChildren()[0];if(p){this._remove(p);p.removeListener(m,this._onUpdate,this);}if(o){this._add(o);o.addListener(m,this._onUpdate,this);}},remove:function(q){if(q){this._remove(q);q.removeListener(m,this._onUpdate,this);}},getChildren:function(){return this._getChildren();},_onUpdate:function(e){this.fireEvent(k);},_onScroll:function(e){var r=this.getContentElement();this.setScrollX(r.getScrollX());this.setScrollY(r.getScrollY());},_onAppear:function(e){var v=this.getContentElement();var s=this.getScrollX();var t=v.getScrollX();if(s!=t){v.scrollToX(s);}var w=this.getScrollY();var u=v.getScrollY();if(w!=u){v.scrollToY(w);}},getItemTop:function(z){var top=0;do{top+=z.getBounds().top;z=z.getLayoutParent();}while(z&&z!==this);return top;},getItemBottom:function(A){return this.getItemTop(A)+A.getBounds().height;},getItemLeft:function(B){var C=0;var parent;do{C+=B.getBounds().left;parent=B.getLayoutParent();if(parent){C+=parent.getInsets().left;}B=parent;}while(B&&B!==this);return C;},getItemRight:function(D){return this.getItemLeft(D)+D.getBounds().width;},getScrollSize:function(){return this.getChildren()[0].getBounds();},getScrollMaxX:function(){var F=this.getInnerSize();var E=this.getScrollSize();if(F&&E){return Math.max(0,E.width-F.width);}return 0;},getScrollMaxY:function(){var H=this.getInnerSize();var G=this.getScrollSize();if(H&&G){return Math.max(0,G.height-H.height);}return 0;},scrollToX:function(I){var J=this.getScrollMaxX();if(I<0){I=0;}else if(I>J){I=J;}this.setScrollX(I);},scrollToY:function(K){var L=this.getScrollMaxY();if(K<0){K=0;}else if(K>L){K=L;}this.setScrollY(K);},scrollByX:function(x){this.scrollToX(this.getScrollX()+x);},scrollByY:function(y){this.scrollToY(this.getScrollY()+y);},_applyScrollX:function(M){this.getContentElement().scrollToX(M);},_applyScrollY:function(N){this.getContentElement().scrollToY(N);}}});})();(function(){var a="qx.ui.layout.Grow";qx.Class.define(a,{extend:qx.ui.layout.Abstract,members:{verifyLayoutProperty:null,renderLayout:function(b,c){var g=this._getLayoutChildren();var f,h,e,d;for(var i=0,l=g.length;i<l;i++){f=g[i];h=f.getSizeHint();e=b;if(e<h.minWidth){e=h.minWidth;}else if(e>h.maxWidth){e=h.maxWidth;}d=c;if(d<h.minHeight){d=h.minHeight;}else if(d>h.maxHeight){d=h.maxHeight;}f.renderLayout(0,0,e,d);}},_computeSizeHint:function(){var q=this._getLayoutChildren();var o,s;var r=0,p=0;var n=0,k=0;var j=Infinity,m=Infinity;for(var i=0,l=q.length;i<l;i++){o=q[i];s=o.getSizeHint();r=Math.max(r,s.width);p=Math.max(p,s.height);n=Math.max(n,s.minWidth);k=Math.max(k,s.minHeight);j=Math.min(j,s.maxWidth);m=Math.min(m,s.maxHeight);}return {width:r,height:p,minWidth:n,minHeight:k,maxWidth:j,maxHeight:m};}}});})();(function(){var m="open",k="icon",j="auto",h="middle",g="String",f="label",d="changeOpen",c="excluded",b="visible",a="opened",H="always",G="qx.ui.tree.AbstractTreeItem",F="_applyIconOpened",E="Boolean",D="__px",C="Integer",B="_applyIndent",A="changeOpenSymbolMode",z="_applyOpenSymbolMode",y="__pu",t="__pt",u="resize",r="",s="removeItem",p="addItem",q="iconOpened",n="abstract",o="never",v="_applyIcon",w="_applyOpen",x="_applyLabel";qx.Class.define(G,{extend:qx.ui.core.Widget,type:n,include:[qx.ui.form.MModelProperty],implement:[qx.ui.form.IModel],construct:function(){qx.ui.core.Widget.call(this);this.__pt=[];this._setLayout(new qx.ui.layout.HBox());this._addWidgets();this.initOpen();},properties:{open:{check:E,init:false,event:d,apply:w},openSymbolMode:{check:[H,o,j],init:j,event:A,apply:z},indent:{check:C,init:19,apply:B,themeable:true},parent:{check:G,nullable:true},icon:{check:g,apply:v,nullable:true,themeable:true},iconOpened:{check:g,apply:F,nullable:true,themeable:true},label:{check:g,apply:x,init:r}},members:{__pt:null,__pu:null,__pv:null,__pw:null,__px:null,__py:null,_addWidgets:function(){throw new Error("Abstract method call.");},_createChildControlImpl:function(I,J){var K;switch(I){case f:K=new qx.ui.basic.Label().set({alignY:h,value:this.getLabel()});break;case k:K=new qx.ui.basic.Image().set({alignY:h,source:this.getIcon()});break;case m:K=new qx.ui.tree.FolderOpenButton().set({alignY:h});K.addListener(d,this._onChangeOpen,this);K.addListener(u,this._updateIndent,this);break;}return K||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,I);},getTree:function(){var M=this;while(M.getParent()){M=M.getParent();}var L=M.getLayoutParent()?M.getLayoutParent().getLayoutParent():0;if(L&&L instanceof qx.ui.core.scroll.ScrollPane){return L.getLayoutParent();}return null;},addWidget:function(N,O){this._add(N,O);},addSpacer:function(){if(!this.__px){this.__px=new qx.ui.core.Spacer();}else{this._remove(this.__px);}this._add(this.__px);},addOpenButton:function(){this._add(this.getChildControl(m));},_onChangeOpen:function(e){if(this.isOpenable()){this.setOpen(e.getData());}},addIcon:function(){var P=this.getChildControl(k);if(this.__pw){this._remove(P);}this._add(P);this.__pw=true;},addLabel:function(Q){var R=this.getChildControl(f);if(this.__pv){this._remove(R);}if(Q){this.setLabel(Q);}else{R.setValue(this.getLabel());}this._add(R);this.__pv=true;},addState:function(S){qx.ui.core.Widget.prototype.addState.call(this,S);var U=this._getChildren();for(var i=0,l=U.length;i<l;i++){var T=U[i];if(T.addState){U[i].addState(S);}}},removeState:function(V){qx.ui.core.Widget.prototype.removeState.call(this,V);var X=this._getChildren();for(var i=0,l=X.length;i<l;i++){var W=X[i];if(W.addState){X[i].removeState(V);}}},_applyIcon:function(Y,ba){if(!this.__pA()){this.__pB(Y);}else if(!this.isOpen()){this.__pB(Y);}},_applyIconOpened:function(bb,bc){if(this.isOpen()){if(this.__pz()&&this.__pA()){this.__pB(bb);}else if(!this.__pz()&&this.__pA()){this.__pB(bb);}}},_applyLabel:function(bd,be){var bf=this.getChildControl(f,true);if(bf){bf.setValue(bd);}},_applyOpen:function(bg,bh){if(this.hasChildren()){this.getChildrenContainer().setVisibility(bg?b:c);}var open=this.getChildControl(m,true);if(open){open.setOpen(bg);}var bi;if(bg){bi=this.__pA()?this.getIconOpened():null;}else{bi=this.getIcon();}if(bi){this.__pB(bi);}bg?this.addState(a):this.removeState(a);},__pz:function(){return qx.util.PropertyUtil.getUserValue(this,k);},__pA:function(){return qx.util.PropertyUtil.getUserValue(this,q);},__pB:function(bj){var bk=this.getChildControl(k,true);if(bk){bk.setSource(bj);}},isOpenable:function(){var bl=this.getOpenSymbolMode();return (bl===H||bl===j&&this.hasChildren());},_shouldShowOpenSymbol:function(){var open=this.getChildControl(m,true);if(!open){return false;}var bm=this.getTree();if(!bm.getRootOpenClose()){if(bm.getHideRoot()){if(bm.getRoot()==this.getParent()){return false;}}else{if(bm.getRoot()==this){return false;}}}return this.isOpenable();},_applyOpenSymbolMode:function(bn,bo){this._updateIndent();},_updateIndent:function(){if(!this.getTree()){return;}var bq=0;var open=this.getChildControl(m,true);if(open){if(this._shouldShowOpenSymbol()){open.show();var bp=open.getBounds();if(bp){bq=bp.width;}else{return;}}else{open.exclude();}}if(this.__px){this.__px.setWidth((this.getLevel()+1)*this.getIndent()-bq);}},_applyIndent:function(br,bs){this._updateIndent();},getLevel:function(){var bt=this.getTree();if(!bt){return;}var bu=this;var bv=-1;while(bu){bu=bu.getParent();bv+=1;}if(bt.getHideRoot()){bv-=1;}if(!bt.getRootOpenClose()){bv-=1;}return bv;},syncWidget:function(){this._updateIndent();},getChildrenContainer:function(){if(!this.__pu){this.__pu=new qx.ui.container.Composite(new qx.ui.layout.VBox()).set({visibility:this.isOpen()?b:c});}return this.__pu;},hasChildrenContainer:function(){return this.__pu;},getParentChildrenContainer:function(){if(this.getParent()){return this.getParent().getChildrenContainer();}else if(this.getLayoutParent()){return this.getLayoutParent();}else{return null;}},getChildren:function(){return this.__pt;},hasChildren:function(){return this.__pt?this.__pt.length>0:false;},getItems:function(bw,bx,by){if(by!==false){var bz=[];}else{var bz=[this];}var bC=this.hasChildren()&&(bx!==false||this.isOpen());if(bC){var bB=this.getChildren();if(bw===false){bz=bz.concat(bB);}else{for(var i=0,bA=bB.length;i<bA;i++){bz=bz.concat(bB[i].getItems(bw,bx,false));}}}return bz;},recursiveAddToWidgetQueue:function(){var bD=this.getItems(true,true,false);for(var i=0,l=bD.length;i<l;i++){qx.ui.core.queue.Widget.add(bD[i]);}},__pC:function(){if(this.getParentChildrenContainer()){this.getParentChildrenContainer()._addAfter(this.getChildrenContainer(),this);}},add:function(bE){var bF=this.getChildrenContainer();var bI=this.getTree();for(var i=0,l=arguments.length;i<l;i++){var bJ=arguments[i];var bH=bJ.getParent();if(bH){bH.remove(bJ);}bJ.setParent(this);var bG=this.hasChildren();bF.add(bJ);if(bJ.hasChildren()){bF.add(bJ.getChildrenContainer());}this.__pt.push(bJ);if(!bG){this.__pC();}if(bI){bJ.recursiveAddToWidgetQueue();bI.fireNonBubblingEvent(p,qx.event.type.Data,[bJ]);}}if(bI){qx.ui.core.queue.Widget.add(this);}},addAt:function(bK,bL){{};if(bL==this.__pt.length){this.add(bK);return;}var bP=bK.getParent();if(bP){bP.remove(bK);}var bN=this.getChildrenContainer();bK.setParent(this);var bO=this.hasChildren();var bM=this.__pt[bL];bN.addBefore(bK,bM);if(bK.hasChildren()){bN.addAfter(bK.getChildrenContainer(),bK);}qx.lang.Array.insertAt(this.__pt,bK,bL);if(!bO){this.__pC();}if(this.getTree()){bK.recursiveAddToWidgetQueue();qx.ui.core.queue.Widget.add(this);}},addBefore:function(bQ,bR){{};var bS=bQ.getParent();if(bS){bS.remove(bQ);}this.addAt(bQ,this.__pt.indexOf(bR));},addAfter:function(bT,bU){{};var bV=bT.getParent();if(bV){bV.remove(bT);}this.addAt(bT,this.__pt.indexOf(bU)+1);},addAtBegin:function(bW){this.addAt(bW,0);},remove:function(bX){for(var i=0,l=arguments.length;i<l;i++){var cc=arguments[i];if(this.__pt.indexOf(cc)==-1){this.warn("Cannot remove treeitem '"+cc+"'. It is not a child of this tree item.");return;}var bY=this.getChildrenContainer();if(cc.hasChildrenContainer()){var cb=cc.getChildrenContainer();if(bY.getChildren().indexOf(cb)>=0){bY.remove(cb);}}qx.lang.Array.remove(this.__pt,cc);cc.setParent(null);bY.remove(cc);}var ca=this.getTree();if(ca){ca.fireNonBubblingEvent(s,qx.event.type.Data,[cc]);}qx.ui.core.queue.Widget.add(this);},removeAt:function(cd){var ce=this.__pt[cd];if(ce){this.remove(ce);}},removeAll:function(){for(var i=this.__pt.length-1;i>=0;i--){this.remove(this.__pt[i]);}}},destruct:function(){this._disposeArray(t);this._disposeObjects(D,y);}});})();(function(){var i="opened",h="click",g="changeOpen",f="Boolean",d="qx.ui.tree.FolderOpenButton",c="_applyOpen",b="mouseup",a="mousedown";qx.Class.define(d,{extend:qx.ui.basic.Image,include:qx.ui.core.MExecutable,construct:function(){qx.ui.basic.Image.call(this);this.initOpen();this.addListener(h,this._onClick);this.addListener(a,this._stopPropagation,this);this.addListener(b,this._stopPropagation,this);},properties:{open:{check:f,init:false,event:g,apply:c}},members:{_applyOpen:function(j,k){j?this.addState(i):this.removeState(i);this.execute();},_stopPropagation:function(e){e.stopPropagation();},_onClick:function(e){this.toggleOpen();e.stopPropagation();}}});})();(function(){var a="qx.ui.core.Spacer";qx.Class.define(a,{extend:qx.ui.core.LayoutItem,construct:function(b,c){qx.ui.core.LayoutItem.call(this);this.setWidth(b!=null?b:0);this.setHeight(c!=null?c:0);},members:{checkAppearanceNeeds:function(){},addChildrenToQueue:function(d){},destroy:function(){if(this.$$disposed){return;}var parent=this.$$parent;if(parent){parent._remove(this);}qx.ui.core.queue.Dispose.add(this);}}});})();(function(){var d="$$theme_",c="$$user_",b="$$init_",a="qx.util.PropertyUtil";qx.Class.define(a,{statics:{getProperties:function(e){return e.$$properties;},getAllProperties:function(f){var i={};var j=f;while(j!=qx.core.Object){var h=this.getProperties(j);for(var g in h){i[g]=h[g];}j=j.superclass;}return i;},getUserValue:function(k,l){return k[c+l];},setUserValue:function(m,n,o){m[c+n]=o;},deleteUserValue:function(p,q){delete (p[c+q]);},getInitValue:function(r,s){return r[b+s];},setInitValue:function(t,u,v){t[b+u]=v;},deleteInitValue:function(w,x){delete (w[b+x]);},getThemeValue:function(y,z){return y[d+z];},setThemeValue:function(A,B,C){A[d+B]=C;},deleteThemeValue:function(D,E){delete (D[d+E]);},setThemed:function(F,G,H){var I=qx.core.Property.$$method.setThemed;F[I[G]](H);},resetThemed:function(J,K){var L=qx.core.Property.$$method.resetThemed;J[L[K]]();}}});})();(function(){var b="tree-folder",a="qx.ui.tree.TreeFolder";qx.Class.define(a,{extend:qx.ui.tree.AbstractTreeItem,construct:function(c){qx.ui.tree.AbstractTreeItem.call(this);if(c){this.setLabel(c);}},properties:{appearance:{refine:true,init:b}},members:{_addWidgets:function(){this.addSpacer();this.addOpenButton();this.addIcon();this.addLabel();}}});})();(function(){var o="",n="/",m="i",k="ICON_",j="separator-vertical",h="sinput",g=")",f="failed",d="CLASS",c="INTERFACE",H="__SV",G="listdata",F="1*",E="#",D="PACKAGE",C="0*",B="changeSelection",A="Search...",z="Results",y="__SW",v="(",w="completed",t="./script/apiindex.json",u="keyup",r="s",s=" Result",p="apiviewer.ui.SearchView",q="appear",x="disappear";qx.Class.define(p,{extend:qx.ui.container.Composite,construct:function(){qx.ui.container.Composite.call(this);var I=new qx.ui.layout.VBox();I.setSeparator(j);this.setLayout(I);this.__SU=false;this.listdata=[];this.apiindex={};this._showSearchForm();},members:{__SV:null,__SW:null,__SU:null,__SX:null,_showSearchForm:function(){var Q=new qx.ui.layout.HBox(4);var K=new qx.ui.container.Composite(Q);K.setPadding(10);this.sinput=new qx.ui.form.TextField().set({allowGrowY:true,placeholder:A});this.__SW=new qx.ui.form.Button("Find");this.__SW.setEnabled(false);K.add(this.sinput,{flex:1});K.add(this.__SW);this.add(K);var O=[];var N=this._tableModel=new qx.ui.table.model.Simple();N.setColumns([o,z]);N.setData(O);var J={tableColumnModel:function(R){return new qx.ui.table.columnmodel.Resize(R);}};var P=new qx.ui.table.Table(N,J);P.setDecorator(null);P.setShowCellFocusIndicator(false);P.setStatusBarVisible(false);P.setColumnVisibilityButtonVisible(false);this._selectionModel=P.getSelectionManager().getSelectionModel();this._selectionModel.addListener(B,this._callDetailFrame,this);this._table=P;var M=P.getTableColumnModel();var L=M.getBehavior();L.set(0,{width:C,minWidth:42,maxWidth:100});L.set(1,{width:F});var M=P.getTableColumnModel();M.setDataCellRenderer(0,new qx.ui.table.cellrenderer.Image());this.__SU=true;this.__SX=P;P.addListener(q,this.__Ta,this);P.addListener(x,function(e){this.__SV.hide();},this);this.add(P,{flex:1});qx.event.Timer.once(this._load,this,0);this.sinput.focus();this.sinput.addListener(u,function(e){this._searchResult(this.sinput.getValue()||o);},this);},_searchResult:function(S){var S=qx.lang.String.trim(S);if(S.length>0){this.__SV.hide();}else{this.__SV.show();}if(S.length<3){if(this.__SU){this.listdata.splice(0,this.listdata.length);}this._resetElements();return;}else{var U=[];try{var T=this._validateInput(S);new RegExp(T[0]);this.__SW.setEnabled(true);}catch(V){if(this.__SU){this.listdata.splice(0,this.listdata.length);}this._resetElements();return;}U=this._searchIndex(T[0],T[1]);this._tableModel.setColumns([o,(U.length+s+((U.length!=1)?r:o))]);this._tableModel.setData(U);this._table.resetSelection();}},_validateInput:function(W){var X=[];if(/^([\w\.]*\w+)(#\w+|\.\w+\(\)|#\.[\*|\+|\?]?)?$/.test(W)){if(RegExp.$2&&RegExp.$2.length>1){X=[RegExp.$2,RegExp.$1];}else if(RegExp.$1.length>1){X=[RegExp.$1,null];}else{return null;}}else{X=[W,null];}return X;},_searchIndex:function(Y,ba){var bf=[];var bd=new RegExp(Y,(/^.*[A-Z].*$/).test(Y)?o:m);var bb=this.apiindex.__index__;var be=this.apiindex.__fullNames__;var bi=this.apiindex.__types__;for(var bg in bb){if(bd.test(bg)){if(ba){for(var i=0,l=bb[bg].length;i<l;i++){var bh=be[bb[bg][i][1]];if(new RegExp(ba,m).test(bh)){var bc=bi[bb[bg][i][0]].toUpperCase();var bj=apiviewer.TreeUtil[k+bc];bf.push([bj,bh+bg]);}}}else{for(var i=0,l=bb[bg].length;i<l;i++){bc=bi[bb[bg][i][0]].toUpperCase();bh=be[bb[bg][i][1]];if(bc==d){bj=apiviewer.TreeUtil.getIconUrl(apiviewer.dao.Class.getClassByName(bh));}else{if(bc!=D&&bc!=c){bh+=bg;}bj=apiviewer.TreeUtil[k+bc];}bf.push([bj,bh]);}}}}return bf;},_setListdata:function(bk){bk.sort(function(a,b){if(a[1]<b[1]){return -1;}if(a[1]>b[1]){return 1;}return 0;});for(var i=0,l=bk.length;i<l;i++){var bl=bk[i][0];var bm={icon:bl,html:o,iconWidth:18,iconHeight:18};this.listdata.push({icon:bm,result:{text:bk[i][1]}});}},_sortByIcons:function(a,b){var bp={"package":0,"class":1,"interface":2,"mixin":3,"method_public":4,"method_protected":5,"method_private":6,"property":7,"property_protected":8,"property_private":9,"event":10,"constructor":11,"constant":12,"childControl":13};var bn=a.substr(a.lastIndexOf(n)+1);var bo=b.substr(b.lastIndexOf(n)+1);a=bp[bn.substr(0,bn.length-6)];b=bp[bo.substr(0,bo.length-6)];return a-b;},_load:function(){var bq=t;var br=new qx.io.remote.Request(bq);br.setAsynchronous(true);br.setTimeout(30000);br.setProhibitCaching(false);br.addListener(w,function(bs){this.apiindex=eval(v+bs.getContent()+g);},this);br.addListener(f,function(bt){this.warn("Couldn't load file: "+bq);},this);br.send();},_callDetailFrame:function(){var bv=this._selectionModel.getAnchorSelectionIndex();var by=this._tableModel.getData()[bv];var bA=qx.core.Init.getApplication().controller;var bu=apiviewer.UiModel.getInstance();if(by!=undefined){var bB=by[1];var bw=by[0];var bz=bB;var bC=null;var bx=bB.indexOf(E);if(bx!=-1){bz=bB.substring(0,bx);bC=bB.substring(bx+1);}if(/protected/.test(bw)){bu.setShowProtected(true);}else if(/private/.test(bw)){bu.setShowPrivate(true);}bA._updateHistory(bB);}},_resetElements:function(){this._tableModel.setData([]);this._tableModel.setColumns([o,o]);this.__SW.setEnabled(false);},__SY:function(bD){this.__SV=new qx.ui.popup.Popup(new qx.ui.layout.Canvas).set({autoHide:false,width:170});var bE=this.tr("Hint: You can use regular expressions in the search field.");var bF=new qx.ui.basic.Label(bE);bF.setRich(true);this.__SV.add(bF,{edge:3});this.__SV.setPosition("bottom-left");this.__SV.placeToWidget(this.sinput,false);this.__SV.show();},__Ta:function(e){if(this.__SV){if(qx.lang.String.trim(this.sinput.getValue()||o).length==0){this.__SV.show();}}else{this.__SY();}}},destruct:function(){this.apiindex=this._table=this.__SX=this._tableModel=this._selectionModel=null;this._disposeObjects(h,y,H);this._disposeArray(G);}});})();(function(){var k="showingPlaceholder",j="",i="none",h="qx.dynlocale",g="Boolean",f="qx.client",d="color",c="qx.event.type.Data",b="readonly",a="placeholder",Y="input",X="focusin",W="visibility",V="focusout",U="changeLocale",T="on",S="readOnly",R="text",Q="_applyTextAlign",P="px",r="RegExp",s=")",p="syncAppearance",q="change",n="textAlign",o="focused",l="center",m="visible",v="disabled",w="url(",D="off",B="String",H="resize",F="qx.ui.form.AbstractField",L="transparent",J="spellcheck",y="false",O="right",N="PositiveInteger",M="mshtml",x="abstract",z="block",A="webkit",C="_applyReadOnly",E="_applyPlaceholder",G="hidden",I="left",K="qx/static/blank.gif",t="changeReadOnly",u="absolute";qx.Class.define(F,{extend:qx.ui.core.Widget,implement:[qx.ui.form.IStringForm,qx.ui.form.IForm],include:[qx.ui.form.MForm],type:x,construct:function(ba){qx.ui.core.Widget.call(this);this.__H=!qx.bom.client.Feature.PLACEHOLDER;if(ba!=null){this.setValue(ba);}this.getContentElement().addListener(q,this._onChangeContent,this);if(this.__H){this.addListener(p,this._syncPlaceholder,this);}if(qx.core.Variant.isSet(h,T)){qx.locale.Manager.getInstance().addListener(U,this._onChangeLocale,this);}},events:{"input":c,"changeValue":c},properties:{textAlign:{check:[I,l,O],nullable:true,themeable:true,apply:Q},readOnly:{check:g,apply:C,event:t,init:false},selectable:{refine:true,init:true},focusable:{refine:true,init:true},maxLength:{check:N,init:Infinity},liveUpdate:{check:g,init:false},placeholder:{check:B,nullable:true,apply:E},filter:{check:r,nullable:true,init:null}},members:{__I:true,__J:null,__K:null,__L:null,__H:true,getFocusElement:function(){var bb=this.getContentElement();if(bb){return bb;}},_createInputElement:function(){return new qx.html.Input(R);},renderLayout:function(bc,top,bd,be){var bf=this._updateInsets;var bj=qx.ui.core.Widget.prototype.renderLayout.call(this,bc,top,bd,be);if(!bj){return;}var bh=bj.size||bf;var bk=P;if(bh||bj.local||bj.margin){var bg=this.getInsets();var innerWidth=bd-bg.left-bg.right;var innerHeight=be-bg.top-bg.bottom;innerWidth=innerWidth<0?0:innerWidth;innerHeight=innerHeight<0?0:innerHeight;}var bi=this.getContentElement();if(bf&&this.__H){this.__O().setStyles({"left":bg.left+bk,"top":bg.top+bk});}if(bh){if(this.__H){this.__O().setStyles({"width":innerWidth+bk,"height":innerHeight+bk});}bi.setStyles({"width":innerWidth+bk,"height":innerHeight+bk});this._renderContentElement(innerHeight,bi);}},_renderContentElement:function(innerHeight,bl){},_createContentElement:function(){var bm=this._createInputElement();bm.setStyles({"border":i,"padding":0,"margin":0,"display":z,"background":L,"outline":i,"appearance":i,"position":u,"autoComplete":D});bm.setSelectable(this.getSelectable());bm.setEnabled(this.getEnabled());bm.addListener(Y,this._onHtmlInput,this);bm.setAttribute(J,y);if(qx.core.Variant.isSet(f,A)){bm.setStyle(H,i);}if(qx.core.Variant.isSet(f,M)){bm.setStyles({backgroundImage:w+qx.util.ResourceManager.getInstance().toUri(K)+s});}return bm;},_applyEnabled:function(bn,bo){qx.ui.core.Widget.prototype._applyEnabled.call(this,bn,bo);this.getContentElement().setEnabled(bn);if(this.__H){if(bn){this._showPlaceholder();}else{this._removePlaceholder();}}else{var bp=this.getContentElement();bp.setAttribute(a,bn?this.getPlaceholder():j);}},__M:{width:16,height:16},_getContentHint:function(){return {width:this.__M.width*10,height:this.__M.height||16};},_applyFont:function(bq,br){var bs;if(bq){var bt=qx.theme.manager.Font.getInstance().resolve(bq);bs=bt.getStyles();}else{bs=qx.bom.Font.getDefaultStyles();}this.getContentElement().setStyles(bs);if(this.__H){this.__O().setStyles(bs);}if(bq){this.__M=qx.bom.Label.getTextSize("A",bs);}else{delete this.__M;}qx.ui.core.queue.Layout.add(this);},_applyTextColor:function(bu,bv){if(bu){this.getContentElement().setStyle(d,qx.theme.manager.Color.getInstance().resolve(bu));}else{this.getContentElement().removeStyle(d);}},tabFocus:function(){qx.ui.core.Widget.prototype.tabFocus.call(this);this.selectAllText();},_getTextSize:function(){return this.__M;},_onHtmlInput:function(e){var bz=e.getData();var by=true;this.__I=false;if(this.getFilter()!=null){var bA=j;var bw=bz.search(this.getFilter());var bx=bz;while(bw>=0){bA=bA+(bx.charAt(bw));bx=bx.substring(bw+1,bx.length);bw=bx.search(this.getFilter());}if(bA!=bz){by=false;bz=bA;this.getContentElement().setValue(bz);}}if(bz.length>this.getMaxLength()){var by=false;this.getContentElement().setValue(bz.substr(0,this.getMaxLength()));}if(by){this.fireDataEvent(Y,bz,this.__L);this.__L=bz;if(this.getLiveUpdate()){this.__N(bz);}}},__N:function(bB){var bC=this.__K;this.__K=bB;if(bC!=bB){this.fireNonBubblingEvent("changeValue",qx.event.type.Data,[bB,bC]);}},setValue:function(bD){if(bD===null){if(this.__I){return bD;}bD=j;this.__I=true;}else{this.__I=false;if(this.__H){this._removePlaceholder();}}if(qx.lang.Type.isString(bD)){var bF=this.getContentElement();if(bD.length>this.getMaxLength()){bD=bD.substr(0,this.getMaxLength());}if(bF.getValue()!=bD){var bG=bF.getValue();bF.setValue(bD);var bE=this.__I?null:bD;this.__K=bG;this.__N(bE);}if(this.__H){this._showPlaceholder();}return bD;}throw new Error("Invalid value type: "+bD);},getValue:function(){var bH=this.getContentElement().getValue();return this.__I?null:bH;},resetValue:function(){this.setValue(null);},_onChangeContent:function(e){this.__I=e.getData()===null;this.__N(e.getData());},getTextSelection:function(){return this.getContentElement().getTextSelection();},getTextSelectionLength:function(){return this.getContentElement().getTextSelectionLength();},getTextSelectionStart:function(){return this.getContentElement().getTextSelectionStart();},getTextSelectionEnd:function(){return this.getContentElement().getTextSelectionEnd();},setTextSelection:function(bI,bJ){this.getContentElement().setTextSelection(bI,bJ);},clearTextSelection:function(){this.getContentElement().clearTextSelection();},selectAllText:function(){this.setTextSelection(0);},_showPlaceholder:function(){var bL=this.getValue()||j;var bK=this.getPlaceholder();if(bK!=null&&bL==j&&!this.hasState(o)&&!this.hasState(v)){if(this.hasState(k)){this._syncPlaceholder();}else{this.addState(k);}}},_removePlaceholder:function(){if(this.hasState(k)){this.__O().setStyle(W,G);this.removeState(k);}},_syncPlaceholder:function(){if(this.hasState(k)){this.__O().setStyle(W,m);}},__O:function(){if(this.__J==null){this.__J=new qx.html.Label();var bM=qx.theme.manager.Color.getInstance();this.__J.setStyles({"visibility":"hidden","zIndex":6,"position":"absolute","color":bM.resolve("text-placeholder")});this.getContainerElement().add(this.__J);}return this.__J;},_onChangeLocale:qx.core.Variant.select(h,{"on":function(e){var content=this.getPlaceholder();if(content&&content.translate){this.setPlaceholder(content.translate());}},"off":null}),_applyPlaceholder:function(bN,bO){if(this.__H){this.__O().setValue(bN);if(bN!=null){this.addListener(X,this._removePlaceholder,this);this.addListener(V,this._showPlaceholder,this);this._showPlaceholder();}else{this.removeListener(X,this._removePlaceholder,this);this.removeListener(V,this._showPlaceholder,this);this._removePlaceholder();}}else{if(this.getEnabled()){this.getContentElement().setAttribute(a,bN);}}},_applyTextAlign:function(bP,bQ){this.getContentElement().setStyle(n,bP);},_applyReadOnly:function(bR,bS){var bT=this.getContentElement();bT.setAttribute(S,bR);if(bR){this.addState(b);this.setFocusable(false);}else{this.removeState(b);this.setFocusable(true);}}},destruct:function(){this.__J=null;if(qx.core.Variant.isSet(h,T)){qx.locale.Manager.getInstance().removeListener(U,this._onChangeLocale,this);}}});})();(function(){var b="qx.ui.form.TextField",a="textfield";qx.Class.define(b,{extend:qx.ui.form.AbstractField,properties:{appearance:{refine:true,init:a},allowGrowY:{refine:true,init:false},allowShrinkY:{refine:true,init:false}},members:{_renderContentElement:function(innerHeight,c){}}});})();(function(){var k="wrap",j="value",i="textarea",h="none",g="qx.client",f="",e="input",d="qx.html.Input",c="select",b="disabled",a="read-only";qx.Class.define(d,{extend:qx.html.Element,construct:function(l,m,n){if(l===c||l===i){var o=l;}else{o=e;}qx.html.Element.call(this,o,m,n);this.__c=l;},members:{__c:null,__d:null,__e:null,_createDomElement:function(){return qx.bom.Input.create(this.__c);},_applyProperty:function(name,p){qx.html.Element.prototype._applyProperty.call(this,name,p);var q=this.getDomElement();if(name===j){qx.bom.Input.setValue(q,p);}else if(name===k){qx.bom.Input.setWrap(q,p);}},setEnabled:qx.core.Variant.select(g,{"webkit":function(r){this.__e=r;if(!r){this.setStyles({"userModify":a,"userSelect":h});}else{this.setStyles({"userModify":null,"userSelect":this.__d?null:h});}},"default":function(s){this.setAttribute(b,s===false);}}),setSelectable:qx.core.Variant.select(g,{"webkit":function(t){this.__d=t;qx.html.Element.prototype.setSelectable.call(this,this.__e&&t);},"default":function(u){qx.html.Element.prototype.setSelectable.call(this,u);}}),setValue:function(v){var w=this.getDomElement();if(w){if(w.value!=v){qx.bom.Input.setValue(w,v);}}else{this._setProperty(j,v);}return this;},getValue:function(){var x=this.getDomElement();if(x){return qx.bom.Input.getValue(x);}return this._getProperty(j)||f;},setWrap:function(y){if(this.__c===i){this._setProperty(k,y);}else{throw new Error("Text wrapping is only support by textareas!");}return this;},getWrap:function(){if(this.__c===i){return this._getProperty(k);}else{throw new Error("Text wrapping is only support by textareas!");}}}});})();(function(){var w="change",v="input",u="qx.client",t="text",s="password",r="checkbox",q="radio",p="textarea",n="keypress",m="opera",d="propertychange",k="blur",h="keydown",c="keyup",b="select-multiple",g="checked",f="value",j="select",a="qx.event.handler.Input";qx.Class.define(a,{extend:qx.core.Object,implement:qx.event.IEventHandler,construct:function(){qx.core.Object.call(this);this._onChangeCheckedWrapper=qx.lang.Function.listener(this._onChangeChecked,this);this._onChangeValueWrapper=qx.lang.Function.listener(this._onChangeValue,this);this._onInputWrapper=qx.lang.Function.listener(this._onInput,this);this._onPropertyWrapper=qx.lang.Function.listener(this._onProperty,this);if(qx.core.Variant.isSet(u,m)){this._onKeyDownWrapper=qx.lang.Function.listener(this._onKeyDown,this);this._onKeyUpWrapper=qx.lang.Function.listener(this._onKeyUp,this);this._onBlurWrapper=qx.lang.Function.listener(this._onBlur,this);}},statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{input:1,change:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_DOMNODE,IGNORE_CAN_HANDLE:false},members:{__g:false,__h:null,__i:null,canHandleEvent:function(x,y){var z=x.tagName.toLowerCase();if(y===v&&(z===v||z===p)){return true;}if(y===w&&(z===v||z===p||z===j)){return true;}return false;},registerEvent:qx.core.Variant.select(u,{"mshtml":function(A,B,C){if(!A.__j){var D=A.tagName.toLowerCase();var E=A.type;if(E===t||E===s||D===p||E===r||E===q){qx.bom.Event.addNativeListener(A,d,this._onPropertyWrapper);}if(E!==r&&E!==q){qx.bom.Event.addNativeListener(A,w,this._onChangeValueWrapper);}if(E===t||E===s){this._onKeyPressWrapped=qx.lang.Function.listener(this._onKeyPress,this,A);qx.bom.Event.addNativeListener(A,n,this._onKeyPressWrapped);}A.__j=true;}},"default":function(F,G,H){if(G===v){this.__k(F);}else if(G===w){if(F.type===q||F.type===r){qx.bom.Event.addNativeListener(F,w,this._onChangeCheckedWrapper);}else{qx.bom.Event.addNativeListener(F,w,this._onChangeValueWrapper);}if(qx.core.Variant.isSet(u,m)){if(F.type===t||F.type===s){this._onKeyPressWrapped=qx.lang.Function.listener(this._onKeyPress,this,F);qx.bom.Event.addNativeListener(F,n,this._onKeyPressWrapped);}}}}}),__k:qx.core.Variant.select(u,{"mshtml":null,"webkit":function(I){var J=I.tagName.toLowerCase();if(qx.bom.client.Engine.VERSION<532&&J==p){qx.bom.Event.addNativeListener(I,n,this._onInputWrapper);}qx.bom.Event.addNativeListener(I,v,this._onInputWrapper);},"opera":function(K){qx.bom.Event.addNativeListener(K,c,this._onKeyUpWrapper);qx.bom.Event.addNativeListener(K,h,this._onKeyDownWrapper);qx.bom.Event.addNativeListener(K,k,this._onBlurWrapper);qx.bom.Event.addNativeListener(K,v,this._onInputWrapper);},"default":function(L){qx.bom.Event.addNativeListener(L,v,this._onInputWrapper);}}),unregisterEvent:qx.core.Variant.select(u,{"mshtml":function(M,N){if(M.__j){var O=M.tagName.toLowerCase();var P=M.type;if(P===t||P===s||O===p||P===r||P===q){qx.bom.Event.removeNativeListener(M,d,this._onPropertyWrapper);}if(P!==r&&P!==q){qx.bom.Event.removeNativeListener(M,w,this._onChangeValueWrapper);}if(P===t||P===s){qx.bom.Event.removeNativeListener(M,n,this._onKeyPressWrapped);}try{delete M.__j;}catch(Q){M.__j=null;}}},"default":function(R,S){if(S===v){this.__k(R);}else if(S===w){if(R.type===q||R.type===r){qx.bom.Event.removeNativeListener(R,w,this._onChangeCheckedWrapper);}else{qx.bom.Event.removeNativeListener(R,w,this._onChangeValueWrapper);}}if(qx.core.Variant.isSet(u,m)){if(R.type===t||R.type===s){qx.bom.Event.removeNativeListener(R,n,this._onKeyPressWrapped);}}}}),__l:qx.core.Variant.select(u,{"mshtml":null,"webkit":function(T){var U=T.tagName.toLowerCase();if(qx.bom.client.Engine.VERSION<532&&U==p){qx.bom.Event.removeNativeListener(T,n,this._onInputWrapper);}qx.bom.Event.removeNativeListener(T,v,this._onInputWrapper);},"opera":function(V){qx.bom.Event.removeNativeListener(V,c,this._onKeyUpWrapper);qx.bom.Event.removeNativeListener(V,h,this._onKeyDownWrapper);qx.bom.Event.removeNativeListener(V,k,this._onBlurWrapper);qx.bom.Event.removeNativeListener(V,v,this._onInputWrapper);},"default":function(W){qx.bom.Event.removeNativeListener(W,v,this._onInputWrapper);}}),_onKeyPress:qx.core.Variant.select(u,{"mshtml|opera":function(e,X){if(e.keyCode===13){if(X.value!==this.__i){this.__i=X.value;qx.event.Registration.fireEvent(X,w,qx.event.type.Data,[X.value]);}}},"default":null}),_onKeyDown:qx.core.Variant.select(u,{"opera":function(e){if(e.keyCode===13){this.__g=true;}},"default":null}),_onKeyUp:qx.core.Variant.select(u,{"opera":function(e){if(e.keyCode===13){this.__g=false;}},"default":null}),_onBlur:qx.core.Variant.select(u,{"opera":function(e){if(this.__h){window.clearTimeout(this.__h);}},"default":null}),_onInput:qx.event.GlobalError.observeMethod(function(e){var Y=qx.bom.Event.getTarget(e);if(!this.__g){if(qx.core.Variant.isSet(u,m)){this.__h=window.setTimeout(function(){qx.event.Registration.fireEvent(Y,v,qx.event.type.Data,[Y.value]);},0);}else{qx.event.Registration.fireEvent(Y,v,qx.event.type.Data,[Y.value]);}}}),_onChangeValue:qx.event.GlobalError.observeMethod(function(e){var bb=qx.bom.Event.getTarget(e);var ba=bb.value;if(bb.type===b){var ba=[];for(var i=0,o=bb.options,l=o.length;i<l;i++){if(o[i].selected){ba.push(o[i].value);}}}qx.event.Registration.fireEvent(bb,w,qx.event.type.Data,[ba]);}),_onChangeChecked:qx.event.GlobalError.observeMethod(function(e){var bc=qx.bom.Event.getTarget(e);if(bc.type===q){if(bc.checked){qx.event.Registration.fireEvent(bc,w,qx.event.type.Data,[bc.value]);}}else{qx.event.Registration.fireEvent(bc,w,qx.event.type.Data,[bc.checked]);}}),_onProperty:qx.core.Variant.select(u,{"mshtml":qx.event.GlobalError.observeMethod(function(e){var bd=qx.bom.Event.getTarget(e);var be=e.propertyName;if(be===f&&(bd.type===t||bd.type===s||bd.tagName.toLowerCase()===p)){if(!bd.$$inValueSet){qx.event.Registration.fireEvent(bd,v,qx.event.type.Data,[bd.value]);}}else if(be===g){if(bd.type===r){qx.event.Registration.fireEvent(bd,w,qx.event.type.Data,[bd.checked]);}else if(bd.checked){qx.event.Registration.fireEvent(bd,w,qx.event.type.Data,[bd.value]);}}}),"default":function(){}})},defer:function(bf){qx.event.Registration.addHandler(bf);}});})();(function(){var v="",u="select",t="soft",s="off",r="qx.client",q="textarea",p="wrap",o="text",n="mshtml",m="number",d="checkbox",k="select-one",g="input",c="option",b="value",f="radio",e="qx.bom.Input",h="nowrap",a="auto",j="normal";qx.Class.define(e,{statics:{__f:{text:1,textarea:1,select:1,checkbox:1,radio:1,password:1,hidden:1,submit:1,image:1,file:1,search:1,reset:1,button:1},create:function(w,x,y){{};var x=x?qx.lang.Object.clone(x):{};var z;if(w===q||w===u){z=w;}else{z=g;x.type=w;}return qx.bom.Element.create(z,x,y);},setValue:function(A,B){var G=A.nodeName.toLowerCase();var D=A.type;var Array=qx.lang.Array;var H=qx.lang.Type;if(typeof B===m){B+=v;}if((D===d||D===f)){if(H.isArray(B)){A.checked=Array.contains(B,A.value);}else{A.checked=A.value==B;}}else if(G===u){var C=H.isArray(B);var I=A.options;var E,F;for(var i=0,l=I.length;i<l;i++){E=I[i];F=E.getAttribute(b);if(F==null){F=E.text;}E.selected=C?Array.contains(B,F):B==F;}if(C&&B.length==0){A.selectedIndex=-1;}}else if((D===o||D===q)&&qx.core.Variant.isSet(r,n)){A.$$inValueSet=true;A.value=B;A.$$inValueSet=null;}else{A.value=B;}},getValue:function(J){var P=J.nodeName.toLowerCase();if(P===c){return (J.attributes.value||{}).specified?J.value:J.text;}if(P===u){var K=J.selectedIndex;if(K<0){return null;}var Q=[];var S=J.options;var R=J.type==k;var O=qx.bom.Input;var N;for(var i=R?K:0,M=R?K+1:S.length;i<M;i++){var L=S[i];if(L.selected){N=O.getValue(L);if(R){return N;}Q.push(N);}}return Q;}else{return (J.value||v).replace(/\r/g,v);}},setWrap:qx.core.Variant.select(r,{"mshtml":function(T,U){T.wrap=U?t:s;},"gecko|webkit":function(V,W){var Y=W?t:s;var X=W?v:a;V.setAttribute(p,Y);V.style.overflow=X;},"default":function(ba,bb){ba.style.whiteSpace=bb?j:h;}})}});})();(function(){var c="qx.event.type.Data",b="qx.event.type.Event",a="qx.ui.table.ITableModel";qx.Interface.define(a,{events:{"dataChanged":c,"metaDataChanged":b,"sorted":c},members:{getRowCount:function(){},getRowData:function(d){},getColumnCount:function(){},getColumnId:function(e){},getColumnIndexById:function(f){},getColumnName:function(g){},isColumnEditable:function(h){},isColumnSortable:function(i){},sortByColumn:function(j,k){},getSortColumnIndex:function(){},isSortAscending:function(){},prefetchRows:function(l,m){},getValue:function(n,o){},getValueById:function(p,q){},setValue:function(r,s,t){},setValueById:function(u,v,w){}}});})();(function(){var e="metaDataChanged",d="qx.event.type.Data",c="qx.event.type.Event",b="abstract",a="qx.ui.table.model.Abstract";qx.Class.define(a,{type:b,extend:qx.core.Object,implement:qx.ui.table.ITableModel,events:{"dataChanged":d,"metaDataChanged":c,"sorted":d},construct:function(){qx.core.Object.call(this);this.__vM=[];this.__vN=[];this.__vO={};},members:{__vM:null,__vN:null,__vO:null,__vP:null,init:function(f){},getRowCount:function(){throw new Error("getRowCount is abstract");},getRowData:function(g){return null;},isColumnEditable:function(h){return false;},isColumnSortable:function(j){return false;},sortByColumn:function(k,l){},getSortColumnIndex:function(){return -1;},isSortAscending:function(){return true;},prefetchRows:function(m,n){},getValue:function(o,p){throw new Error("getValue is abstract");},getValueById:function(q,r){return this.getValue(this.getColumnIndexById(q),r);},setValue:function(s,t,u){throw new Error("setValue is abstract");},setValueById:function(v,w,x){this.setValue(this.getColumnIndexById(v),w,x);},getColumnCount:function(){return this.__vM.length;},getColumnIndexById:function(y){return this.__vO[y];},getColumnId:function(z){return this.__vM[z];},getColumnName:function(A){return this.__vN[A];},setColumnIds:function(B){this.__vM=B;this.__vO={};for(var i=0;i<B.length;i++){this.__vO[B[i]]=i;}this.__vN=new Array(B.length);if(!this.__vP){this.fireEvent(e);}},setColumnNamesByIndex:function(C){if(this.__vM.length!=C.length){throw new Error("this.__columnIdArr and columnNameArr have different length: "+this.__vM.length+" != "+C.length);}this.__vN=C;this.fireEvent(e);},setColumnNamesById:function(D){this.__vN=new Array(this.__vM.length);for(var i=0;i<this.__vM.length;++i){this.__vN[i]=D[this.__vM[i]];}},setColumns:function(E,F){var G=this.__vM.length==0||F;if(F==null){if(this.__vM.length==0){F=E;}else{F=this.__vM;}}if(F.length!=E.length){throw new Error("columnIdArr and columnNameArr have different length: "+F.length+" != "+E.length);}if(G){this.__vP=true;this.setColumnIds(F);this.__vP=false;}this.setColumnNamesByIndex(E);}},destruct:function(){this.__vM=this.__vN=this.__vO=null;}});})();(function(){var e="dataChanged",d="metaDataChanged",c="qx.ui.table.model.Simple",b="Boolean",a="sorted";qx.Class.define(c,{extend:qx.ui.table.model.Abstract,construct:function(){qx.ui.table.model.Abstract.call(this);this.__xM=[];this.__xN=-1;this.__xO=[];this.__xP=null;},properties:{caseSensitiveSorting:{check:b,init:true}},statics:{_defaultSortComparatorAscending:function(f,g){var h=f[arguments.callee.columnIndex];var k=g[arguments.callee.columnIndex];if(qx.lang.Type.isNumber(h)&&qx.lang.Type.isNumber(k)){var l=isNaN(h)?isNaN(k)?0:1:isNaN(k)?-1:null;if(l!=null){return l;}}return (h>k)?1:((h==k)?0:-1);},_defaultSortComparatorInsensitiveAscending:function(m,n){var o=(m[arguments.callee.columnIndex].toLowerCase?m[arguments.callee.columnIndex].toLowerCase():m[arguments.callee.columnIndex]);var p=(n[arguments.callee.columnIndex].toLowerCase?n[arguments.callee.columnIndex].toLowerCase():n[arguments.callee.columnIndex]);if(qx.lang.Type.isNumber(o)&&qx.lang.Type.isNumber(p)){var q=isNaN(o)?isNaN(p)?0:1:isNaN(p)?-1:null;if(q!=null){return q;}}return (o>p)?1:((o==p)?0:-1);},_defaultSortComparatorDescending:function(r,s){var t=r[arguments.callee.columnIndex];var u=s[arguments.callee.columnIndex];if(qx.lang.Type.isNumber(t)&&qx.lang.Type.isNumber(u)){var v=isNaN(t)?isNaN(u)?0:1:isNaN(u)?-1:null;if(v!=null){return v;}}return (t<u)?1:((t==u)?0:-1);},_defaultSortComparatorInsensitiveDescending:function(w,x){var y=(w[arguments.callee.columnIndex].toLowerCase?w[arguments.callee.columnIndex].toLowerCase():w[arguments.callee.columnIndex]);var z=(x[arguments.callee.columnIndex].toLowerCase?x[arguments.callee.columnIndex].toLowerCase():x[arguments.callee.columnIndex]);if(qx.lang.Type.isNumber(y)&&qx.lang.Type.isNumber(z)){var A=isNaN(y)?isNaN(z)?0:1:isNaN(z)?-1:null;if(A!=null){return A;}}return (y<z)?1:((y==z)?0:-1);}},members:{__xM:null,__xP:null,__xQ:null,__xO:null,__xN:null,__xR:null,getRowData:function(B){var C=this.__xM[B];if(C==null||C.originalData==null){return C;}else{return C.originalData;}},getRowDataAsMap:function(D){var F=this.__xM[D];if(F!=null){var E={};for(var G=0;G<this.getColumnCount();G++){E[this.getColumnId(G)]=F[G];}if(F.originalData!=null){for(var H in F.originalData){if(E[H]==undefined){E[H]=F.originalData[H];}}}return E;}return (F&&F.originalData)?F.originalData:null;},getDataAsMapArray:function(){var J=this.getRowCount();var I=[];for(var i=0;i<J;i++){I.push(this.getRowDataAsMap(i));}return I;},setEditable:function(K){this.__xP=[];for(var L=0;L<this.getColumnCount();L++){this.__xP[L]=K;}this.fireEvent(d);},setColumnEditable:function(M,N){if(N!=this.isColumnEditable(M)){if(this.__xP==null){this.__xP=[];}this.__xP[M]=N;this.fireEvent(d);}},isColumnEditable:function(O){return this.__xP?(this.__xP[O]==true):false;},setColumnSortable:function(P,Q){if(Q!=this.isColumnSortable(P)){if(this.__xQ==null){this.__xQ=[];}this.__xQ[P]=Q;this.fireEvent(d);}},isColumnSortable:function(R){return (this.__xQ?(this.__xQ[R]!==false):true);},sortByColumn:function(S,T){var W;var V=this.__xO[S];if(V){W=(T?V.ascending:V.descending);}else{if(this.getCaseSensitiveSorting()){W=(T?qx.ui.table.model.Simple._defaultSortComparatorAscending:qx.ui.table.model.Simple._defaultSortComparatorDescending);}else{W=(T?qx.ui.table.model.Simple._defaultSortComparatorInsensitiveAscending:qx.ui.table.model.Simple._defaultSortComparatorInsensitiveDescending);}}W.columnIndex=S;this.__xM.sort(W);this.__xN=S;this.__xR=T;var U={columnIndex:S,ascending:T};this.fireDataEvent(a,U);this.fireEvent(d);},setSortMethods:function(X,Y){var ba;if(qx.lang.Type.isFunction(Y)){ba={ascending:Y,descending:function(bb,bc){return Y(bc,bb);}};}else{ba=Y;}this.__xO[X]=ba;},getSortMethods:function(bd){return this.__xO[bd];},clearSorting:function(){if(this.__xN!=-1){this.__xN=-1;this.__xR=true;this.fireEvent(d);}},getSortColumnIndex:function(){return this.__xN;},_setSortColumnIndex:function(be){this.__xN=be;},isSortAscending:function(){return this.__xR;},_setSortAscending:function(bf){this.__xR=bf;},getRowCount:function(){return this.__xM.length;},getValue:function(bg,bh){if(bh<0||bh>=this.__xM.length){throw new Error("this.__rowArr out of bounds: "+bh+" (0.."+this.__xM.length+")");}return this.__xM[bh][bg];},setValue:function(bi,bj,bk){if(this.__xM[bj][bi]!=bk){this.__xM[bj][bi]=bk;if(this.hasListener(e)){var bl={firstRow:bj,lastRow:bj,firstColumn:bi,lastColumn:bi};this.fireDataEvent(e,bl);}if(bi==this.__xN){this.clearSorting();}}},setData:function(bm,bn){this.__xM=bm;if(this.hasListener(e)){var bo={firstRow:0,lastRow:bm.length-1,firstColumn:0,lastColumn:this.getColumnCount()-1};this.fireDataEvent(e,bo);}if(bn!==false){this.clearSorting();}},getData:function(){return this.__xM;},setDataAsMapArray:function(bp,bq,br){this.setData(this._mapArray2RowArr(bp,bq),br);},addRows:function(bs,bt,bu){if(bt==null){bt=this.__xM.length;}bs.splice(0,0,bt,0);Array.prototype.splice.apply(this.__xM,bs);var bv={firstRow:bt,lastRow:this.__xM.length-1,firstColumn:0,lastColumn:this.getColumnCount()-1};this.fireDataEvent(e,bv);if(bu!==false){this.clearSorting();}},addRowsAsMapArray:function(bw,bx,by,bz){this.addRows(this._mapArray2RowArr(bw,by),bx,bz);},setRows:function(bA,bB,bC){if(bB==null){bB=0;}bA.splice(0,0,bB,bA.length);Array.prototype.splice.apply(this.__xM,bA);var bD={firstRow:bB,lastRow:this.__xM.length-1,firstColumn:0,lastColumn:this.getColumnCount()-1};this.fireDataEvent(e,bD);if(bC!==false){this.clearSorting();}},setRowsAsMapArray:function(bE,bF,bG,bH){this.setRows(this._mapArray2RowArr(bE,bG),bF,bH);},removeRows:function(bI,bJ,bK){this.__xM.splice(bI,bJ);var bL={firstRow:bI,lastRow:this.__xM.length-1,firstColumn:0,lastColumn:this.getColumnCount()-1,removeStart:bI,removeCount:bJ};this.fireDataEvent(e,bL);if(bK!==false){this.clearSorting();}},_mapArray2RowArr:function(bM,bN){var bR=bM.length;var bO=this.getColumnCount();var bQ=new Array(bR);var bP;for(var i=0;i<bR;++i){bP=[];if(bN){bP.originalData=bM[i];}for(var j=0;j<bO;++j){bP[j]=bM[i][this.getColumnId(j)];}bQ[i]=bP;}return bQ;}},destruct:function(){this.__xM=this.__xP=this.__xO=this.__xQ=null;}});})();(function(){var a="qx.ui.table.ICellEditorFactory";qx.Interface.define(a,{members:{createCellEditor:function(b){return true;},getCellEditorValue:function(c){return true;}}});})();(function(){var f="",e="Function",d="abstract",c="number",b="appear",a="qx.ui.table.celleditor.AbstractField";qx.Class.define(a,{extend:qx.core.Object,implement:qx.ui.table.ICellEditorFactory,type:d,properties:{validationFunction:{check:e,nullable:true,init:null}},members:{_createEditor:function(){throw new Error("Abstract method call!");},createCellEditor:function(g){var h=this._createEditor();h.originalValue=g.value;if(g.value===null||g.value===undefined){g.value=f;}h.setValue(f+g.value);h.addListener(b,function(){h.selectAllText();});return h;},getCellEditorValue:function(i){var k=i.getValue();var j=this.getValidationFunction();if(j){k=j(k,i.originalValue);}if(typeof i.originalValue==c){k=parseFloat(k);}return k;}}});})();(function(){var c="number",b="qx.ui.table.celleditor.TextField",a="table-editor-textfield";qx.Class.define(b,{extend:qx.ui.table.celleditor.AbstractField,members:{getCellEditorValue:function(d){var f=d.getValue();var e=this.getValidationFunction();if(e){f=e(f,d.originalValue);}if(typeof d.originalValue==c){if(f!=null){f=parseFloat(f);}}return f;},_createEditor:function(){var g=new qx.ui.form.TextField();g.setAppearance(a);return g;}}});})();(function(){var a="qx.ui.table.IHeaderRenderer";qx.Interface.define(a,{members:{createHeaderCell:function(b){return true;},updateHeaderCell:function(c,d){return true;}}});})();(function(){var b="qx.ui.table.headerrenderer.Default",a="String";qx.Class.define(b,{extend:qx.core.Object,implement:qx.ui.table.IHeaderRenderer,statics:{STATE_SORTED:"sorted",STATE_SORTED_ASCENDING:"sortedAscending"},properties:{toolTip:{check:a,init:null,nullable:true}},members:{createHeaderCell:function(c){var d=new qx.ui.table.headerrenderer.HeaderCell();this.updateHeaderCell(c,d);return d;},updateHeaderCell:function(e,f){var g=qx.ui.table.headerrenderer.Default;if(e.name&&e.name.translate){f.setLabel(e.name.translate());}else{f.setLabel(e.name);}var h=f.getToolTip();if(this.getToolTip()!=null){if(h==null){h=new qx.ui.tooltip.ToolTip(this.getToolTip());f.setToolTip(h);qx.util.DisposeUtil.disposeTriggeredBy(h,f);}else{h.setLabel(this.getToolTip());}}e.sorted?f.addState(g.STATE_SORTED):f.removeState(g.STATE_SORTED);e.sortedAscending?f.addState(g.STATE_SORTED_ASCENDING):f.removeState(g.STATE_SORTED_ASCENDING);}}});})();(function(){var l="qx.client",k="head",j="text/css",h="stylesheet",g="}",f='@import "',e="{",d='";',c="qx.bom.Stylesheet",b="link",a="style";qx.Class.define(c,{statics:{includeFile:function(m,n){if(!n){n=document;}var o=n.createElement(b);o.type=j;o.rel=h;o.href=qx.util.ResourceManager.getInstance().toUri(m);var p=n.getElementsByTagName(k)[0];p.appendChild(o);},createElement:qx.core.Variant.select(l,{"mshtml":function(q){var r=document.createStyleSheet();if(q){r.cssText=q;}return r;},"default":function(s){var t=document.createElement(a);t.type=j;if(s){t.appendChild(document.createTextNode(s));}document.getElementsByTagName(k)[0].appendChild(t);return t.sheet;}}),addRule:qx.core.Variant.select(l,{"mshtml":function(u,v,w){u.addRule(v,w);},"default":function(x,y,z){x.insertRule(y+e+z+g,x.cssRules.length);}}),removeRule:qx.core.Variant.select(l,{"mshtml":function(A,B){var C=A.rules;var D=C.length;for(var i=D-1;i>=0;--i){if(C[i].selectorText==B){A.removeRule(i);}}},"default":function(E,F){var G=E.cssRules;var H=G.length;for(var i=H-1;i>=0;--i){if(G[i].selectorText==F){E.deleteRule(i);}}}}),removeAllRules:qx.core.Variant.select(l,{"mshtml":function(I){var J=I.rules;var K=J.length;for(var i=K-1;i>=0;i--){I.removeRule(i);}},"default":function(L){var M=L.cssRules;var N=M.length;for(var i=N-1;i>=0;i--){L.deleteRule(i);}}}),addImport:qx.core.Variant.select(l,{"mshtml":function(O,P){O.addImport(P);},"default":function(Q,R){Q.insertRule(f+R+d,Q.cssRules.length);}}),removeImport:qx.core.Variant.select(l,{"mshtml":function(S,T){var U=S.imports;var V=U.length;for(var i=V-1;i>=0;i--){if(U[i].href==T){S.removeImport(i);}}},"default":function(W,X){var Y=W.cssRules;var ba=Y.length;for(var i=ba-1;i>=0;i--){if(Y[i].href==X){W.deleteRule(i);}}}}),removeAllImports:qx.core.Variant.select(l,{"mshtml":function(bb){var bc=bb.imports;var bd=bc.length;for(var i=bd-1;i>=0;i--){bb.removeImport(i);}},"default":function(be){var bf=be.cssRules;var bg=bf.length;for(var i=bg-1;i>=0;i--){if(bf[i].type==bf[i].IMPORT_RULE){be.deleteRule(i);}}}})}});})();(function(){var a="qx.ui.table.ICellRenderer";qx.Interface.define(a,{members:{createDataCellHtml:function(b,c){return true;}}});})();(function(){var j="",i="px;",h=".qooxdoo-table-cell {",g="qooxdoo-table-cell",f='" ',e="nowrap",d="default",c="qx.client",b="}",a="width:",H=".qooxdoo-table-cell-right { text-align:right } ",G="0px 6px",F='<div class="',E="0px",D="height:",C="1px solid ",B=".qooxdoo-table-cell-bold { font-weight:bold } ",A="table-row-line",z="String",y='>',q="mshtml",r='</div>',o="ellipsis",p="content-box",m='left:',n="qx.ui.table.cellrenderer.Abstract",k='" style="',l="abstract",s="none",t="hidden",v="} ",u='px;',x=".qooxdoo-table-cell-italic { font-style:italic} ",w="absolute";qx.Class.define(n,{type:l,implement:qx.ui.table.ICellRenderer,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);var I=qx.ui.table.cellrenderer.Abstract;if(!I.__wp){var K=qx.theme.manager.Color.getInstance();I.__wp=this.self(arguments);var J=h+qx.bom.element.Style.compile({position:w,top:E,overflow:t,whiteSpace:e,borderRight:C+K.resolve(A),padding:G,cursor:d,textOverflow:o,userSelect:s})+v+H+x+B;if(!qx.core.Variant.isSet(c,q)){J+=h+qx.bom.element.BoxSizing.compile(p)+b;}I.__wp.stylesheet=qx.bom.Stylesheet.createElement(J);}},properties:{defaultCellStyle:{init:null,check:z,nullable:true}},members:{_insetX:6+6+1,_insetY:0,_getCellClass:function(L){return g;},_getCellStyle:function(M){return M.style||j;},_getCellAttributes:function(N){return j;},_getContentHtml:function(O){return O.value||j;},_getCellSizeStyle:function(P,Q,R,S){var T=j;if(qx.bom.client.Feature.CONTENT_BOX){P-=R;Q-=S;}T+=a+Math.max(P,0)+i;T+=D+Math.max(Q,0)+i;return T;},createDataCellHtml:function(U,V){V.push(F,this._getCellClass(U),k,m,U.styleLeft,u,this._getCellSizeStyle(U.styleWidth,U.styleHeight,this._insetX,this._insetY),this._getCellStyle(U),f,this._getCellAttributes(U),y+this._getContentHtml(U),r);}}});})();(function(){var h="",g="number",f="Boolean",e="qx.ui.table.cellrenderer.Default",d=" qooxdoo-table-cell-bold",c=" qooxdoo-table-cell-right",b=" qooxdoo-table-cell-italic",a="string";qx.Class.define(e,{extend:qx.ui.table.cellrenderer.Abstract,statics:{STYLEFLAG_ALIGN_RIGHT:1,STYLEFLAG_BOLD:2,STYLEFLAG_ITALIC:4,_numberFormat:null},properties:{useAutoAlign:{check:f,init:true}},members:{_getStyleFlags:function(i){if(this.getUseAutoAlign()){if(typeof i.value==g){return qx.ui.table.cellrenderer.Default.STYLEFLAG_ALIGN_RIGHT;}}return 0;},_getCellClass:function(j){var k=qx.ui.table.cellrenderer.Abstract.prototype._getCellClass.call(this,j);if(!k){return h;}var l=this._getStyleFlags(j);if(l&qx.ui.table.cellrenderer.Default.STYLEFLAG_ALIGN_RIGHT){k+=c;}if(l&qx.ui.table.cellrenderer.Default.STYLEFLAG_BOLD){k+=d;}if(l&qx.ui.table.cellrenderer.Default.STYLEFLAG_ITALIC){k+=b;}return k;},_getContentHtml:function(m){return qx.bom.String.escape(this._formatValue(m));},_formatValue:function(n){var p=n.value;var o;if(p==null){return h;}if(typeof p==a){return p;}else if(typeof p==g){if(!qx.ui.table.cellrenderer.Default._numberFormat){qx.ui.table.cellrenderer.Default._numberFormat=new qx.util.format.NumberFormat();qx.ui.table.cellrenderer.Default._numberFormat.setMaximumFractionDigits(2);}var o=qx.ui.table.cellrenderer.Default._numberFormat.format(p);}else if(p instanceof Date){o=qx.util.format.DateFormat.getDateInstance().format(p);}else{o=p;}return o;}}});})();(function(){var k="qx.event.type.Data",j="visibilityChanged",h="orderChanged",g="visibilityChangedPre",f="__wv",e="__ww",d="widthChanged",c="qx.ui.table.columnmodel.Basic",b="__wx",a="headerCellRendererChanged";qx.Class.define(c,{extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__wq=[];this.__wr=[];},events:{"widthChanged":k,"visibilityChangedPre":k,"visibilityChanged":k,"orderChanged":k,"headerCellRendererChanged":k},statics:{DEFAULT_WIDTH:100,DEFAULT_HEADER_RENDERER:qx.ui.table.headerrenderer.Default,DEFAULT_DATA_RENDERER:qx.ui.table.cellrenderer.Default,DEFAULT_EDITOR_FACTORY:qx.ui.table.celleditor.TextField},members:{__ws:null,__wt:null,__wr:null,__wq:null,__wu:null,__wv:null,__ww:null,__wx:null,init:function(l,m){{};this.__wu=[];var q=qx.ui.table.columnmodel.Basic.DEFAULT_WIDTH;var r=this.__wv||(this.__wv=new qx.ui.table.columnmodel.Basic.DEFAULT_HEADER_RENDERER());var o=this.__ww||(this.__ww=new qx.ui.table.columnmodel.Basic.DEFAULT_DATA_RENDERER());var n=this.__wx||(this.__wx=new qx.ui.table.columnmodel.Basic.DEFAULT_EDITOR_FACTORY());this.__wq=[];this.__wr=[];var t;if(m){t=m.getInitiallyHiddenColumns();}t=t||[];for(var u=0;u<l;u++){this.__wu[u]={width:q,headerRenderer:r,dataRenderer:o,editorFactory:n};this.__wq[u]=u;this.__wr[u]=u;}this.__wt=null;this.__ws=true;for(var s=0;s<t.length;s++){this.setColumnVisible(t[s],false);}this.__ws=false;for(u=0;u<l;u++){var p={col:u,visible:this.isColumnVisible(u)};this.fireDataEvent(g,p);this.fireDataEvent(j,p);}},getVisibleColumns:function(){return this.__wr!=null?this.__wr:[];},setColumnWidth:function(v,w,y){{};var A=this.__wu[v].width;if(A!=w){this.__wu[v].width=w;var z={col:v,newWidth:w,oldWidth:A,isMouseAction:y||false};this.fireDataEvent(d,z);}},getColumnWidth:function(B){{};return this.__wu[B].width;},setHeaderCellRenderer:function(C,D){{};var E=this.__wu[C].headerRenderer;if(E!==this.__wv){E.dispose();}this.__wu[C].headerRenderer=D;this.fireDataEvent(a,{col:C});},getHeaderCellRenderer:function(F){{};return this.__wu[F].headerRenderer;},setDataCellRenderer:function(G,H){{};this.__wu[G].dataRenderer=H;var I=this.__wu[G].dataRenderer;if(I!==this.__ww){return I;}return null;},getDataCellRenderer:function(J){{};return this.__wu[J].dataRenderer;},setCellEditorFactory:function(K,L){{};var M=this.__wu[K].headerRenderer;if(M!==this.__wx){M.dispose();}this.__wu[K].editorFactory=L;},getCellEditorFactory:function(N){{};return this.__wu[N].editorFactory;},_getColToXPosMap:function(){if(this.__wt==null){this.__wt={};for(var Q=0;Q<this.__wq.length;Q++){var P=this.__wq[Q];this.__wt[P]={overX:Q};}for(var O=0;O<this.__wr.length;O++){var P=this.__wr[O];this.__wt[P].visX=O;}}return this.__wt;},getVisibleColumnCount:function(){return this.__wr!=null?this.__wr.length:0;},getVisibleColumnAtX:function(R){{};return this.__wr[R];},getVisibleX:function(S){{};return this._getColToXPosMap()[S].visX;},getOverallColumnCount:function(){return this.__wq.length;},getOverallColumnAtX:function(T){{};return this.__wq[T];},getOverallX:function(U){{};return this._getColToXPosMap()[U].overX;},isColumnVisible:function(V){{};return (this._getColToXPosMap()[V].visX!=null);},setColumnVisible:function(W,X){{};if(X!=this.isColumnVisible(W)){if(X){var be=this._getColToXPosMap();var bb=be[W].overX;if(bb==null){throw new Error("Showing column failed: "+W+". The column is not added to this TablePaneModel.");}var bc;for(var x=bb+1;x<this.__wq.length;x++){var bd=this.__wq[x];var Y=be[bd].visX;if(Y!=null){bc=Y;break;}}if(bc==null){bc=this.__wr.length;}this.__wr.splice(bc,0,W);}else{var ba=this.getVisibleX(W);this.__wr.splice(ba,1);}this.__wt=null;if(!this.__ws){var bf={col:W,visible:X};this.fireDataEvent(g,bf);this.fireDataEvent(j,bf);}}},moveColumn:function(bg,bh){{};this.__ws=true;var bk=this.__wq[bg];var bi=this.isColumnVisible(bk);if(bi){this.setColumnVisible(bk,false);}this.__wq.splice(bg,1);this.__wq.splice(bh,0,bk);this.__wt=null;if(bi){this.setColumnVisible(bk,true);}this.__ws=false;var bj={col:bk,fromOverXPos:bg,toOverXPos:bh};this.fireDataEvent(h,bj);},setColumnsOrder:function(bl){{};if(bl.length==this.__wq.length){this.__ws=true;var bo=new Array(bl.length);for(var bm=0;bm<this.__wq.length;bm++){var bn=this.isColumnVisible(bm);bo[bm]=bn;if(bn){this.setColumnVisible(bm,false);}}this.__wq=qx.lang.Array.clone(bl);this.__wt=null;for(var bm=0;bm<this.__wq.length;bm++){if(bo[bm]){this.setColumnVisible(bm,true);}}this.__ws=false;this.fireDataEvent(h);}else{throw new Error("setColumnsOrder: Invalid number of column positions given, expected "+this.__wq.length+", got "+bl.length);}}},destruct:function(){for(var i=0;i<this.__wu.length;i++){this.__wu[i].headerRenderer.dispose();this.__wu[i].dataRenderer.dispose();this.__wu[i].editorFactory.dispose();}this.__wq=this.__wr=this.__wu=this.__wt=null;this._disposeObjects(f,e,b);}});})();(function(){var n="appear",m="columnVisibilityMenuCreateEnd",l="tableWidthChanged",k="verticalScrollBarChanged",j="qx.ui.table.columnmodel.resizebehavior.Abstract",i="qx.ui.table.columnmodel.Resize",h="_applyBehavior",g="separator",f="visibilityChanged",e="Reset column widths",b="changeBehavior",d="user-button",c="widthChanged",a="execute";qx.Class.define(i,{extend:qx.ui.table.columnmodel.Basic,include:qx.locale.MTranslation,construct:function(){qx.ui.table.columnmodel.Basic.call(this);this.__yb=false;this.__yc=false;},properties:{behavior:{check:j,init:null,nullable:true,apply:h,event:b}},members:{__yc:null,__yb:null,__yd:null,_applyBehavior:function(p,q){if(q!=null){q.dispose();q=null;}p._setNumColumns(this.getOverallColumnCount());p.setTableColumnModel(this);},init:function(r,s){qx.ui.table.columnmodel.Basic.prototype.init.call(this,r,s);if(this.__yd==null){this.__yd=s;s.addListener(n,this._onappear,this);s.addListener(l,this._onTableWidthChanged,this);s.addListener(k,this._onverticalscrollbarchanged,this);s.addListener(m,this._addResetColumnWidthButton,this);this.addListener(c,this._oncolumnwidthchanged,this);this.addListener(f,this._onvisibilitychanged,this);}if(this.getBehavior()==null){this.setBehavior(new qx.ui.table.columnmodel.resizebehavior.Default());}this.getBehavior()._setNumColumns(r);},getTable:function(){return this.__yd;},_addResetColumnWidthButton:function(event){var v=event.getData();var u=v.columnButton;var t=v.menu;var o;o=u.factory(g);t.add(o);o=u.factory(d,{text:this.tr(e)});t.add(o);o.addListener(a,this._onappear,this);},_onappear:function(event){if(this.__yb){return ;}this.__yb=true;{};this.getBehavior().onAppear(event,event.getType()!==n);this.__yd._updateScrollerWidths();this.__yd._updateScrollBarVisibility();this.__yb=false;this.__yc=true;},_onTableWidthChanged:function(event){if(this.__yb||!this.__yc){return ;}this.__yb=true;{};this.getBehavior().onTableWidthChanged(event);this.__yb=false;},_onverticalscrollbarchanged:function(event){if(this.__yb||!this.__yc){return ;}this.__yb=true;{};this.getBehavior().onVerticalScrollBarChanged(event);qx.event.Timer.once(function(){if(this.__yd&&!this.__yd.isDisposed()){this.__yd._updateScrollerWidths();this.__yd._updateScrollBarVisibility();}},this,0);this.__yb=false;},_oncolumnwidthchanged:function(event){if(this.__yb||!this.__yc){return ;}this.__yb=true;{};this.getBehavior().onColumnWidthChanged(event);this.__yb=false;},_onvisibilitychanged:function(event){if(this.__yb||!this.__yc){return ;}this.__yb=true;{};this.getBehavior().onVisibilityChanged(event);this.__yb=false;}},destruct:function(){this.__yd=null;}});})();(function(){var i="icon",h="label",g="String",f="sort-icon",e="_applySortIcon",d="_applyIcon",c="table-header-cell",b="qx.ui.table.headerrenderer.HeaderCell",a="_applyLabel";qx.Class.define(b,{extend:qx.ui.container.Composite,construct:function(){qx.ui.container.Composite.call(this);var j=new qx.ui.layout.Grid();j.setRowFlex(0,1);j.setColumnFlex(1,1);j.setColumnFlex(2,1);this.setLayout(j);},properties:{appearance:{refine:true,init:c},label:{check:g,init:null,nullable:true,apply:a},sortIcon:{check:g,init:null,nullable:true,apply:e,themeable:true},icon:{check:g,init:null,nullable:true,apply:d}},members:{_applyLabel:function(k,l){if(k){this._showChildControl(h).setValue(k);}else{this._excludeChildControl(h);}},_applySortIcon:function(m,n){if(m){this._showChildControl(f).setSource(m);}else{this._excludeChildControl(f);}},_applyIcon:function(o,p){if(o){this._showChildControl(i).setSource(o);}else{this._excludeChildControl(i);}},_createChildControlImpl:function(q,r){var s;switch(q){case h:s=new qx.ui.basic.Label(this.getLabel()).set({anonymous:true,allowShrinkX:true});this._add(s,{row:0,column:1});break;case f:s=new qx.ui.basic.Image(this.getSortIcon());s.setAnonymous(true);this._add(s,{row:0,column:2});break;case i:s=new qx.ui.basic.Image(this.getIcon()).set({anonymous:true,allowShrinkX:true});this._add(s,{row:0,column:0});break;}return s||qx.ui.container.Composite.prototype._createChildControlImpl.call(this,q);}}});})();(function(){var e="qx.ui.popup.Popup",d="visible",c="excluded",b="popup",a="Boolean";qx.Class.define(e,{extend:qx.ui.container.Composite,include:qx.ui.core.MPlacement,construct:function(f){qx.ui.container.Composite.call(this,f);qx.core.Init.getApplication().getRoot().add(this);this.initVisibility();},properties:{appearance:{refine:true,init:b},visibility:{refine:true,init:c},autoHide:{check:a,init:true}},members:{_applyVisibility:function(g,h){qx.ui.container.Composite.prototype._applyVisibility.call(this,g,h);var i=qx.ui.popup.Manager.getInstance();g===d?i.add(this):i.remove(this);}},destruct:function(){qx.ui.popup.Manager.getInstance().remove(this);}});})();(function(){var l="atom",k="Integer",j="String",i="_applyRich",h="qx.ui.tooltip.ToolTip",g="_applyIcon",f="tooltip",d="qx.ui.core.Widget",c="mouseover",b="Boolean",a="_applyLabel";qx.Class.define(h,{extend:qx.ui.popup.Popup,construct:function(m,n){qx.ui.popup.Popup.call(this);this.setLayout(new qx.ui.layout.Grow);this._createChildControl(l);if(m!=null){this.setLabel(m);}if(n!=null){this.setIcon(n);}this.addListener(c,this._onMouseOver,this);},properties:{appearance:{refine:true,init:f},showTimeout:{check:k,init:700,themeable:true},hideTimeout:{check:k,init:4000,themeable:true},label:{check:j,nullable:true,apply:a},icon:{check:j,nullable:true,apply:g,themeable:true},rich:{check:b,init:false,apply:i},opener:{check:d,nullable:true}},members:{_createChildControlImpl:function(o,p){var q;switch(o){case l:q=new qx.ui.basic.Atom;this._add(q);break;}return q||qx.ui.popup.Popup.prototype._createChildControlImpl.call(this,o);},_onMouseOver:function(e){this.hide();},_applyIcon:function(r,s){var t=this.getChildControl(l);r==null?t.resetIcon():t.setIcon(r);},_applyLabel:function(u,v){var w=this.getChildControl(l);u==null?w.resetLabel():w.setLabel(u);},_applyRich:function(x,y){var z=this.getChildControl(l);z.setRich(x);}}});})();(function(){var f="mousedown",d="__rz",c="blur",b="singleton",a="qx.ui.popup.Manager";qx.Class.define(a,{type:b,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__rz=[];qx.event.Registration.addListener(document.documentElement,f,this.__rB,this,true);qx.bom.Element.addListener(window,c,this.hideAll,this);},members:{__rz:null,add:function(g){{};this.__rz.push(g);this.__rA();},remove:function(h){{};if(this.__rz){qx.lang.Array.remove(this.__rz,h);this.__rA();}},hideAll:function(){if(this.__rz){for(var i=0;i<this.__rz.length;i++){this.__rz[i].exclude();}}},__rA:function(){var j=1e7;for(var i=0;i<this.__rz.length;i++){this.__rz[i].setZIndex(j++);}},__rB:function(e){var l=qx.ui.core.Widget.getWidgetByElement(e.getTarget());var m=this.__rz;for(var i=0;i<m.length;i++){var k=m[i];if(!k.getAutoHide()||l==k||qx.ui.core.Widget.contains(k,l)){continue;}k.exclude();}}},destruct:function(){qx.event.Registration.removeListener(document.documentElement,f,this.__rB,this,true);this._disposeArray(d);}});})();(function(){var bD="(\\d\\d?)",bC="format",bB="",bA="abbreviated",bz="wide",by="(",bx=")",bw="|",bv="stand-alone",bu="wildcard",bj="default",bi="literal",bh="'",bg="hour",bf="(\\d\\d?\\d?)",be="ms",bd="narrow",bc="-",bb="quoted_literal",ba='a',bK="HH:mm:ss",bL="+",bI="HHmmss",bJ="long",bG='z',bH="0",bE="sec",bF="day",bM='Z',bN=" ",bn="min",bm="mm",bp="(\\d+)",bo="h",br="KK",bq='L',bt="Z",bs="(\\d\\d+)",bl="EEEE",bk="^",a=":",b='y',c="K",d="a",e="([\\+\\-]\\d\\d:?\\d\\d)",f="GMT",g="dd",h="qx.util.format.DateFormat",j="yyy",k="H",bR="YYYY",bQ="y",bP="HH",bO="EE",bV='h',bU="S",bT='s',bS='A',bX="yyyyyy",bW="kk",J="ss",K='H',H='S',I="MMMM",N='c',O="d",L="([a-zA-Z]+)",M='k',F="m",G='Y',s='D',r="yyyyy",u='K',t="hh",o="SSS",n="MM",q="yy",p="(\\d\\d\\d\\d\\d\\d+)",m="yyyy-MM-dd HH:mm:ss",l="(\\d\\d\\d\\d\\d+)",T="short",U='d',V="unkown",W='m',P="(\\d\\d\\d\\d)",Q="(\\d\\d\\d+)",R="k",S='M',X="(\\d\\d\\d\\d+)",Y="SS",C="MMM",B="s",A="M",z='w',y="EEE",x="$",w="?",v='E',E="z",D="yyyy";qx.Class.define(h,{extend:qx.core.Object,implement:qx.util.format.IFormat,construct:function(bY,ca){qx.core.Object.call(this);if(!ca){this.__wy=qx.locale.Manager.getInstance().getLocale();}else{this.__wy=ca;}if(bY!=null){this.__wz=bY.toString();}else{this.__wz=qx.locale.Date.getDateFormat(bJ,this.__wy)+bN+qx.locale.Date.getDateTimeFormat(bI,bK,this.__wy);}},statics:{getDateTimeInstance:function(){var cc=qx.util.format.DateFormat;var cb=qx.locale.Date.getDateFormat(bJ)+bN+qx.locale.Date.getDateTimeFormat(bI,bK);if(cc._dateInstance==null||cc._dateInstance.__wz!=cb){cc._dateTimeInstance=new cc();}return cc._dateTimeInstance;},getDateInstance:function(){var ce=qx.util.format.DateFormat;var cd=qx.locale.Date.getDateFormat(T)+bB;if(ce._dateInstance==null||ce._dateInstance.__wz!=cd){ce._dateInstance=new ce(cd);}return ce._dateInstance;},ASSUME_YEAR_2000_THRESHOLD:30,LOGGING_DATE_TIME__format:m,AM_MARKER:"am",PM_MARKER:"pm",MEDIUM_TIMEZONE_NAMES:["GMT"],FULL_TIMEZONE_NAMES:["Greenwich Mean Time"]},members:{__wy:null,__wz:null,__wA:null,__wB:null,__wC:null,__wD:function(cf,cg){var ch=bB+cf;while(ch.length<cg){ch=bH+ch;}return ch;},__wE:function(ci){var cj=new Date(ci.getTime());var ck=cj.getDate();while(cj.getMonth()!=0){cj.setDate(-1);ck+=cj.getDate()+1;}return ck;},__wF:function(cl){return new Date(cl.getTime()+(3-((cl.getDay()+6)%7))*86400000);},__wG:function(cm){var co=this.__wF(cm);var cp=co.getFullYear();var cn=this.__wF(new Date(cp,0,4));return Math.floor(1.5+(co.getTime()-cn.getTime())/86400000/7);},format:function(cq){if(cq==null){return null;}var cw=qx.util.format.DateFormat;var cx=this.__wy;var cH=cq.getFullYear();var cB=cq.getMonth();var cJ=cq.getDate();var cr=cq.getDay();var cC=cq.getHours();var cy=cq.getMinutes();var cD=cq.getSeconds();var cF=cq.getMilliseconds();var cI=cq.getTimezoneOffset();var cu=cI>0?1:-1;var cs=Math.floor(Math.abs(cI)/60);var cz=Math.abs(cI)%60;this.__wH();var cG=bB;for(var i=0;i<this.__wC.length;i++){var cE=this.__wC[i];if(cE.type==bi){cG+=cE.text;}else{var cv=cE.character;var cA=cE.size;var ct=w;switch(cv){case b:case G:if(cA==2){ct=this.__wD(cH%100,2);}else{ct=cH+bB;if(cA>ct.length){for(var i=ct.length;i<cA;i++){ct=bH+ct;}}}break;case s:ct=this.__wD(this.__wE(cq),cA);break;case U:ct=this.__wD(cJ,cA);break;case z:ct=this.__wD(this.__wG(cq),cA);break;case v:if(cA==2){ct=qx.locale.Date.getDayName(bd,cr,cx,bC);}else if(cA==3){ct=qx.locale.Date.getDayName(bA,cr,cx,bC);}else if(cA==4){ct=qx.locale.Date.getDayName(bz,cr,cx,bC);}break;case N:if(cA==2){ct=qx.locale.Date.getDayName(bd,cr,cx,bv);}else if(cA==3){ct=qx.locale.Date.getDayName(bA,cr,cx,bv);}else if(cA==4){ct=qx.locale.Date.getDayName(bz,cr,cx,bv);}break;case S:if(cA==1||cA==2){ct=this.__wD(cB+1,cA);}else if(cA==3){ct=qx.locale.Date.getMonthName(bA,cB,cx,bC);}else if(cA==4){ct=qx.locale.Date.getMonthName(bz,cB,cx,bC);}break;case bq:if(cA==1||cA==2){ct=this.__wD(cB+1,cA);}else if(cA==3){ct=qx.locale.Date.getMonthName(bA,cB,cx,bv);}else if(cA==4){ct=qx.locale.Date.getMonthName(bz,cB,cx,bv);}break;case ba:ct=(cC<12)?qx.locale.Date.getAmMarker(cx):qx.locale.Date.getPmMarker(cx);break;case K:ct=this.__wD(cC,cA);break;case M:ct=this.__wD((cC==0)?24:cC,cA);break;case u:ct=this.__wD(cC%12,cA);break;case bV:ct=this.__wD(((cC%12)==0)?12:(cC%12),cA);break;case W:ct=this.__wD(cy,cA);break;case bT:ct=this.__wD(cD,cA);break;case H:ct=this.__wD(cF,cA);break;case bG:if(cA==1){ct=f+((cu>0)?bc:bL)+this.__wD(Math.abs(cs))+a+this.__wD(cz,2);}else if(cA==2){ct=cw.MEDIUM_TIMEZONE_NAMES[cs];}else if(cA==3){ct=cw.FULL_TIMEZONE_NAMES[cs];}break;case bM:ct=((cu>0)?bc:bL)+this.__wD(Math.abs(cs),2)+this.__wD(cz,2);break;}cG+=ct;}}return cG;},parse:function(cK){this.__wI();var cQ=this.__wA.regex.exec(cK);if(cQ==null){throw new Error("Date string '"+cK+"' does not match the date format: "+this.__wz);}var cL={year:1970,month:0,day:1,hour:0,ispm:false,min:0,sec:0,ms:0};var cM=1;for(var i=0;i<this.__wA.usedRules.length;i++){var cO=this.__wA.usedRules[i];var cN=cQ[cM];if(cO.field!=null){cL[cO.field]=parseInt(cN,10);}else{cO.manipulator(cL,cN);}cM+=(cO.groups==null)?1:cO.groups;}var cP=new Date(cL.year,cL.month,cL.day,(cL.ispm)?(cL.hour+12):cL.hour,cL.min,cL.sec,cL.ms);if(cL.month!=cP.getMonth()||cL.year!=cP.getFullYear()){throw new Error("Error parsing date '"+cK+"': the value for day or month is too large");}return cP;},__wH:function(){if(this.__wC!=null){return;}this.__wC=[];var cV;var cT=0;var cX=bB;var cR=this.__wz;var cU=bj;var i=0;while(i<cR.length){var cW=cR.charAt(i);switch(cU){case bb:if(cW==bh){if(i+1>=cR.length){i++;break;}var cS=cR.charAt(i+1);if(cS==bh){cX+=cW;i++;}else{i++;cU=V;}}else{cX+=cW;i++;}break;case bu:if(cW==cV){cT++;i++;}else{this.__wC.push({type:bu,character:cV,size:cT});cV=null;cT=0;cU=bj;}break;default:if((cW>=ba&&cW<=bG)||(cW>=bS&&cW<=bM)){cV=cW;cU=bu;}else if(cW==bh){if(i+1>=cR.length){cX+=cW;i++;break;}var cS=cR.charAt(i+1);if(cS==bh){cX+=cW;i++;}i++;cU=bb;}else{cU=bj;}if(cU!=bj){if(cX.length>0){this.__wC.push({type:bi,text:cX});cX=bB;}}else{cX+=cW;i++;}break;}}if(cV!=null){this.__wC.push({type:bu,character:cV,size:cT});}else if(cX.length>0){this.__wC.push({type:bi,text:cX});}},__wI:function(){if(this.__wA!=null){return ;}var dc=this.__wz;this.__wJ();this.__wH();var di=[];var de=bk;for(var da=0;da<this.__wC.length;da++){var dj=this.__wC[da];if(dj.type==bi){de+=qx.lang.String.escapeRegexpChars(dj.text);}else{var db=dj.character;var df=dj.size;var dd;for(var dk=0;dk<this.__wB.length;dk++){var dg=this.__wB[dk];if(db==dg.pattern.charAt(0)&&df==dg.pattern.length){dd=dg;break;}}if(dd==null){var dh=bB;for(var i=0;i<df;i++){dh+=db;}throw new Error("Malformed date format: "+dc+". Wildcard "+dh+" is not supported");}else{di.push(dd);de+=dd.regex;}}}de+=x;var cY;try{cY=new RegExp(de);}catch(dl){throw new Error("Malformed date format: "+dc);}this.__wA={regex:cY,"usedRules":di,pattern:de};},__wJ:function(){var dw=qx.util.format.DateFormat;var dz=qx.lang.String;if(this.__wB!=null){return ;}var dx=this.__wB=[];var dn=qx.locale.Date.getAmMarker(this.__wy).toString()||dw.AM_MARKER;var dE=qx.locale.Date.getPmMarker(this.__wy).toString()||dw.PM_MARKER;var ds=function(dI,dJ){dJ=parseInt(dJ,10);if(dJ<dw.ASSUME_YEAR_2000_THRESHOLD){dJ+=2000;}else if(dJ<100){dJ+=1900;}dI.year=dJ;};var du=function(dK,dL){dK.month=parseInt(dL,10)-1;};var dq=function(dM,dN){var dO=qx.locale.Date.getPmMarker(this.__wy).toString()||dw.PM_MARKER;dM.ispm=(dN==dO);};var dG=function(dP,dQ){dP.hour=parseInt(dQ,10)%24;};var dp=function(dR,dS){dR.hour=parseInt(dS,10)%12;};var dB=function(dT,dU){return;};var dH=qx.locale.Date.getMonthNames(bA,this.__wy,bC);for(var i=0;i<dH.length;i++){dH[i]=dz.escapeRegexpChars(dH[i].toString());}var dr=function(dV,dW){dW=dz.escapeRegexpChars(dW);dV.month=dH.indexOf(dW);};var dy=qx.locale.Date.getMonthNames(bz,this.__wy,bC);for(var i=0;i<dy.length;i++){dy[i]=dz.escapeRegexpChars(dy[i].toString());}var dC=function(dX,dY){dY=dz.escapeRegexpChars(dY);dX.month=dy.indexOf(dY);};var dm=qx.locale.Date.getDayNames(bd,this.__wy,bC);for(var i=0;i<dm.length;i++){dm[i]=dz.escapeRegexpChars(dm[i].toString());}var dF=function(ea,eb){eb=dz.escapeRegexpChars(eb);ea.month=dm.indexOf(eb);};var dD=qx.locale.Date.getDayNames(bA,this.__wy,bC);for(var i=0;i<dD.length;i++){dD[i]=dz.escapeRegexpChars(dD[i].toString());}var dt=function(ec,ed){ed=dz.escapeRegexpChars(ed);ec.month=dD.indexOf(ed);};var dA=qx.locale.Date.getDayNames(bz,this.__wy,bC);for(var i=0;i<dA.length;i++){dA[i]=dz.escapeRegexpChars(dA[i].toString());}var dv=function(ee,ef){ef=dz.escapeRegexpChars(ef);ee.month=dA.indexOf(ef);};dx.push({pattern:bR,regex:P,manipulator:ds});dx.push({pattern:bQ,regex:bp,manipulator:ds});dx.push({pattern:q,regex:bs,manipulator:ds});dx.push({pattern:j,regex:Q,manipulator:ds});dx.push({pattern:D,regex:X,manipulator:ds});dx.push({pattern:r,regex:l,manipulator:ds});dx.push({pattern:bX,regex:p,manipulator:ds});dx.push({pattern:A,regex:bD,manipulator:du});dx.push({pattern:n,regex:bD,manipulator:du});dx.push({pattern:C,regex:by+dH.join(bw)+bx,manipulator:dr});dx.push({pattern:I,regex:by+dy.join(bw)+bx,manipulator:dC});dx.push({pattern:g,regex:bD,field:bF});dx.push({pattern:O,regex:bD,field:bF});dx.push({pattern:bO,regex:by+dm.join(bw)+bx,manipulator:dF});dx.push({pattern:y,regex:by+dD.join(bw)+bx,manipulator:dt});dx.push({pattern:bl,regex:by+dA.join(bw)+bx,manipulator:dv});dx.push({pattern:d,regex:by+dn+bw+dE+bx,manipulator:dq});dx.push({pattern:bP,regex:bD,field:bg});dx.push({pattern:k,regex:bD,field:bg});dx.push({pattern:bW,regex:bD,manipulator:dG});dx.push({pattern:R,regex:bD,manipulator:dG});dx.push({pattern:br,regex:bD,field:bg});dx.push({pattern:c,regex:bD,field:bg});dx.push({pattern:t,regex:bD,manipulator:dp});dx.push({pattern:bo,regex:bD,manipulator:dp});dx.push({pattern:bm,regex:bD,field:bn});dx.push({pattern:F,regex:bD,field:bn});dx.push({pattern:J,regex:bD,field:bE});dx.push({pattern:B,regex:bD,field:bE});dx.push({pattern:o,regex:bf,field:be});dx.push({pattern:Y,regex:bf,field:be});dx.push({pattern:bU,regex:bf,field:be});dx.push({pattern:bt,regex:e,manipulator:dB});dx.push({pattern:E,regex:L,manipulator:dB});}},destruct:function(){this.__wC=this.__wA=this.__wB=null;}});})();(function(){var k="_",j="format",h="thu",g="sat",f="cldr_day_",e="cldr_month_",d="wed",c="fri",b="tue",a="mon",B="sun",A="short",z="HH:mm",y="HHmmsszz",x="HHmm",w="HHmmss",v="cldr_date_format_",u="HH:mm:ss zz",t="full",s="cldr_pm",q="long",r="medium",o="cldr_am",p="qx.locale.Date",m="cldr_date_time_format_",n="cldr_time_format_",l="HH:mm:ss";qx.Class.define(p,{statics:{__wK:qx.locale.Manager.getInstance(),getAmMarker:function(C){return this.__wK.localize(o,[],C);},getPmMarker:function(D){return this.__wK.localize(s,[],D);},getDayNames:function(length,E,F){var F=F?F:j;{};var H=[B,a,b,d,h,c,g];var I=[];for(var i=0;i<H.length;i++){var G=f+F+k+length+k+H[i];I.push(this.__wK.localize(G,[],E));}return I;},getDayName:function(length,J,K,L){var L=L?L:j;{};var N=[B,a,b,d,h,c,g];var M=f+L+k+length+k+N[J];return this.__wK.localize(M,[],K);},getMonthNames:function(length,O,P){var P=P?P:j;{};var R=[];for(var i=0;i<12;i++){var Q=e+P+k+length+k+(i+1);R.push(this.__wK.localize(Q,[],O));}return R;},getMonthName:function(length,S,T,U){var U=U?U:j;{};var V=e+U+k+length+k+(S+1);return this.__wK.localize(V,[],T);},getDateFormat:function(W,X){{};var Y=v+W;return this.__wK.localize(Y,[],X);},getDateTimeFormat:function(ba,bb,bc){var be=m+ba;var bd=this.__wK.localize(be,[],bc);if(bd==be){bd=bb;}return bd;},getTimeFormat:function(bf,bg){{};var bi=n+bf;var bh=this.__wK.localize(bi,[],bg);if(bh!=bi){return bh;}switch(bf){case A:case r:return qx.locale.Date.getDateTimeFormat(x,z);case q:return qx.locale.Date.getDateTimeFormat(w,l);case t:return qx.locale.Date.getDateTimeFormat(y,u);default:throw new Error("This case should never happen.");}},getWeekStart:function(bj){var bk={"MV":5,"AE":6,"AF":6,"BH":6,"DJ":6,"DZ":6,"EG":6,"ER":6,"ET":6,"IQ":6,"IR":6,"JO":6,"KE":6,"KW":6,"LB":6,"LY":6,"MA":6,"OM":6,"QA":6,"SA":6,"SD":6,"SO":6,"TN":6,"YE":6,"AS":0,"AU":0,"AZ":0,"BW":0,"CA":0,"CN":0,"FO":0,"GE":0,"GL":0,"GU":0,"HK":0,"IE":0,"IL":0,"IS":0,"JM":0,"JP":0,"KG":0,"KR":0,"LA":0,"MH":0,"MN":0,"MO":0,"MP":0,"MT":0,"NZ":0,"PH":0,"PK":0,"SG":0,"TH":0,"TT":0,"TW":0,"UM":0,"US":0,"UZ":0,"VI":0,"ZA":0,"ZW":0,"MW":0,"NG":0,"TJ":0};var bl=qx.locale.Date._getTerritory(bj);return bk[bl]!=null?bk[bl]:1;},getWeekendStart:function(bm){var bo={"EG":5,"IL":5,"SY":5,"IN":0,"AE":4,"BH":4,"DZ":4,"IQ":4,"JO":4,"KW":4,"LB":4,"LY":4,"MA":4,"OM":4,"QA":4,"SA":4,"SD":4,"TN":4,"YE":4};var bn=qx.locale.Date._getTerritory(bm);return bo[bn]!=null?bo[bn]:6;},getWeekendEnd:function(bp){var bq={"AE":5,"BH":5,"DZ":5,"IQ":5,"JO":5,"KW":5,"LB":5,"LY":5,"MA":5,"OM":5,"QA":5,"SA":5,"SD":5,"TN":5,"YE":5,"AF":5,"IR":5,"EG":6,"IL":6,"SY":6};var br=qx.locale.Date._getTerritory(bp);return bq[br]!=null?bq[br]:0;},isWeekend:function(bs,bt){var bv=qx.locale.Date.getWeekendStart(bt);var bu=qx.locale.Date.getWeekendEnd(bt);if(bu>bv){return ((bs>=bv)&&(bs<=bu));}else{return ((bs>=bv)||(bs<=bu));}},_getTerritory:function(bw){if(bw){var bx=bw.split(k)[1]||bw;}else{bx=this.__wK.getTerritory()||this.__wK.getLanguage();}return bx.toUpperCase();}}});})();(function(){var e="auto",d="string",c="number",b="*",a="qx.ui.core.ColumnData";qx.Class.define(a,{extend:qx.ui.core.LayoutItem,construct:function(){qx.ui.core.LayoutItem.call(this);this.setColumnWidth(e);},members:{__ye:null,renderLayout:function(f,top,g,h){this.__ye=g;},getComputedWidth:function(){return this.__ye;},getFlex:function(){return this.getLayoutProperties().flex||0;},setColumnWidth:function(i,j){var j=j||0;var k=null;if(typeof i==c){this.setWidth(i);}else if(typeof i==d){if(i==e){j=1;}else{var l=i.match(/^[0-9]+(?:\.[0-9]+)?([%\*])$/);if(l){if(l[1]==b){j=parseFloat(i);}else{k=i;}}}}this.setLayoutProperties({flex:j,width:k});}},settings:{"qx.tableResizeDebug":false}});})();(function(){var b="qx.ui.table.columnmodel.resizebehavior.Abstract",a="abstract";qx.Class.define(b,{type:a,extend:qx.core.Object,members:{_setNumColumns:function(c){throw new Error("_setNumColumns is abstract");},onAppear:function(event,d){throw new Error("onAppear is abstract");},onTableWidthChanged:function(event){throw new Error("onTableWidthChanged is abstract");},onVerticalScrollBarChanged:function(event){throw new Error("onVerticalScrollBarChanged is abstract");},onColumnWidthChanged:function(event){throw new Error("onColumnWidthChanged is abstract");},onVisibilityChanged:function(event){throw new Error("onVisibilityChanged is abstract");},_getAvailableWidth:function(){var f=this.getTableColumnModel();var i=f.getTable();var e=i._getPaneScrollerArr();if(!e[0]||!e[0].getLayoutParent().getBounds()){return null;}var h=e[0].getLayoutParent().getBounds().width;var g=e[e.length-1];h-=g.getPaneInsetRight();return h;}}});})();(function(){var j="Function",h="Boolean",g="minWidth",f="width",e="__yg",d="qx.ui.table.columnmodel.Resize",c="qx.ui.table.columnmodel.resizebehavior.Default",b="__yh",a="maxWidth";qx.Class.define(c,{extend:qx.ui.table.columnmodel.resizebehavior.Abstract,construct:function(){qx.ui.table.columnmodel.resizebehavior.Abstract.call(this);this.__yf=[];this.__yg=new qx.ui.layout.HBox();this.__yg.connectToWidget(this);this.__yh=new qx.util.DeferredCall(this._computeColumnsFlexWidth,this);},properties:{newResizeBehaviorColumnData:{check:j,init:function(k){return new qx.ui.core.ColumnData();}},initializeWidthsOnEveryAppear:{check:h,init:false},tableColumnModel:{check:d}},members:{__yg:null,__yi:null,__yf:null,__yh:null,__yj:false,setWidth:function(m,n,o){if(m>=this.__yf.length){throw new Error("Column number out of range");}this.__yf[m].setColumnWidth(n,o);this.__yh.schedule();},setMinWidth:function(p,q){if(p>=this.__yf.length){throw new Error("Column number out of range");}this.__yf[p].setMinWidth(q);this.__yh.schedule();},setMaxWidth:function(r,s){if(r>=this.__yf.length){throw new Error("Column number out of range");}this.__yf[r].setMaxWidth(s);this.__yh.schedule();},set:function(t,u){for(var v in u){switch(v){case f:this.setWidth(t,u[v]);break;case g:this.setMinWidth(t,u[v]);break;case a:this.setMaxWidth(t,u[v]);break;default:throw new Error("Unknown property: "+v);}}},onAppear:function(event,w){if(w===true||!this.__yj||this.getInitializeWidthsOnEveryAppear()){this._computeColumnsFlexWidth();this.__yj=true;}},onTableWidthChanged:function(event){this._computeColumnsFlexWidth();},onVerticalScrollBarChanged:function(event){this._computeColumnsFlexWidth();},onColumnWidthChanged:function(event){this._extendNextColumn(event);},onVisibilityChanged:function(event){var x=event.getData();if(x.visible){this._computeColumnsFlexWidth();return;}this._extendLastColumn(event);},_setNumColumns:function(y){var z=this.__yf;if(y<=z.length){z.splice(y,z.length);return;}for(var i=z.length;i<y;i++){z[i]=this.getNewResizeBehaviorColumnData()();z[i].columnNumber=i;}},getLayoutChildren:function(){return this.__yi;},_computeColumnsFlexWidth:function(){this.__yh.cancel();var E=this._getAvailableWidth();if(E===null){return;}var A=this.getTableColumnModel();var C=A.getVisibleColumns();var D=C.length;var B=this.__yf;var i,l;if(D===0){return;}var G=[];for(i=0;i<D;i++){G.push(B[C[i]]);}this.__yi=G;this.__yk();this.__yg.renderLayout(E,100);for(i=0,l=G.length;i<l;i++){var F=G[i].getComputedWidth();A.setColumnWidth(C[i],F);}},__yk:function(){this.__yg.invalidateChildrenCache();var H=this.__yi;for(var i=0,l=H.length;i<l;i++){H[i].invalidateLayoutCache();}},_extendNextColumn:function(event){var M=this.getTableColumnModel();var P=event.getData();var K=M.getVisibleColumns();var J=this._getAvailableWidth();var I=K.length;if(P.newWidth>P.oldWidth){return ;}var i;var L;var O=0;for(i=0;i<I;i++){O+=M.getColumnWidth(K[i]);}if(O<J){for(i=0;i<K.length;i++){if(K[i]==P.col){L=K[i+1];break;}}if(L){var N=(J-(O-M.getColumnWidth(L)));M.setColumnWidth(L,N);}}},_extendLastColumn:function(event){var T=this.getTableColumnModel();var X=event.getData();if(X.visible){return;}var S=T.getVisibleColumns();if(S.length==0){return;}var R=this._getAvailableWidth(T);var Q=S.length;var i;var V;var W=0;for(i=0;i<Q;i++){W+=T.getColumnWidth(S[i]);}if(W<R){V=S[S.length-1];var U=(R-(W-T.getColumnWidth(V)));T.setColumnWidth(V,U);}},_getResizeColumnData:function(){return this.__yf;}},destruct:function(){this.__yf=this.__yi=null;this._disposeObjects(e,b);}});})();(function(){var p="Boolean",o="column-button",n="Function",m="qx.event.type.Data",k="statusbar",j="qx.ui.table.pane.CellEvent",h="function",g="PageUp",f="dataChanged",e='"',bF="changeLocale",bE="changeSelection",bD="qx.dynlocale",bC="__wd",bB="Enter",bA="metaDataChanged",bz="on",by="_applyStatusBarVisible",bx="columnVisibilityMenuCreateStart",bw="blur",w="qx.ui.table.Table",y="columnVisibilityMenuCreateEnd",u="changeVisible",v="_applyResetSelectionOnHeaderClick",s="_applyMetaColumnCounts",t="focus",q="changeDataRowRenderer",r="changeHeaderCellHeight",F="Escape",G="A",X="changeSelectionModel",T="Left",bg="__vS",bb="Down",bs="Integer",bm="_applyHeaderCellHeight",N="__wb",bv="visibilityChanged",bu="qx.ui.table.ITableModel",bt="orderChanged",L="_applySelectionModel",P="menu-button",R="menu",V="_applyAdditionalStatusBarText",Y="_applyFocusCellOnMouseMove",bc="table",bi="_applyColumnVisibilityButtonVisible",bo="changeTableModel",z="qx.event.type.Event",A="tableWidthChanged",O="_applyHeaderCellsVisible",bf="Object",be="_applyShowCellFocusIndicator",bd="resize",bk="verticalScrollBarChanged",bj="__wc",ba="changeScrollY",bh="_applyTableModel",a="End",bn="_applyKeepFirstVisibleRowComplete",B="widthChanged",C="one of one row",U="Home",b="_applyRowHeight",d="F2",K="appear",D="Up",E="%1 rows",I="qx.ui.table.selection.Model",W="one row",bq="PageDown",bp="%1 of %2 rows",Q="keypress",br="changeRowHeight",M="__vT",bl="Number",H="header",J="qx.ui.table.IRowRenderer",c="Right",S="Space";qx.Class.define(w,{extend:qx.ui.core.Widget,construct:function(bG,bH){qx.ui.core.Widget.call(this);if(!bH){bH={};}if(bH.initiallyHiddenColumns){this.setInitiallyHiddenColumns(bH.initiallyHiddenColumns);}if(bH.selectionManager){this.setNewSelectionManager(bH.selectionManager);}if(bH.selectionModel){this.setNewSelectionModel(bH.selectionModel);}if(bH.tableColumnModel){this.setNewTableColumnModel(bH.tableColumnModel);}if(bH.tablePane){this.setNewTablePane(bH.tablePane);}if(bH.tablePaneHeader){this.setNewTablePaneHeader(bH.tablePaneHeader);}if(bH.tablePaneScroller){this.setNewTablePaneScroller(bH.tablePaneScroller);}if(bH.tablePaneModel){this.setNewTablePaneModel(bH.tablePaneModel);}if(bH.columnMenu){this.setNewColumnMenu(bH.columnMenu);}this._setLayout(new qx.ui.layout.VBox());this.__vS=new qx.ui.container.Composite(new qx.ui.layout.HBox());this._add(this.__vS,{flex:1});this.setDataRowRenderer(new qx.ui.table.rowrenderer.Default(this));this.__vT=this.getNewSelectionManager()(this);this.setSelectionModel(this.getNewSelectionModel()(this));this.setTableModel(bG||this.getEmptyTableModel());this.setMetaColumnCounts([-1]);this.setTabIndex(1);this.addListener(Q,this._onKeyPress);this.addListener(t,this._onFocusChanged);this.addListener(bw,this._onFocusChanged);var bI=new qx.ui.core.Widget().set({height:0});this._add(bI);bI.addListener(bd,this._onResize,this);this.__vU=null;this.__vV=null;if(qx.core.Variant.isSet(bD,bz)){qx.locale.Manager.getInstance().addListener(bF,this._onChangeLocale,this);}this.initStatusBarVisible();bG=this.getTableModel();if(bG.init&&typeof (bG.init)==h){bG.init(this);}},events:{"columnVisibilityMenuCreateStart":m,"columnVisibilityMenuCreateEnd":m,"tableWidthChanged":z,"verticalScrollBarChanged":m,"cellClick":j,"cellDblclick":j,"cellContextmenu":j,"dataEdited":m},statics:{__vW:{cellClick:1,cellDblclick:1,cellContextmenu:1}},properties:{appearance:{refine:true,init:bc},focusable:{refine:true,init:true},minWidth:{refine:true,init:50},initiallyHiddenColumns:{init:null},selectable:{refine:true,init:false},selectionModel:{check:I,apply:L,event:X},tableModel:{check:bu,apply:bh,event:bo},rowHeight:{check:bl,init:20,apply:b,event:br},forceLineHeight:{check:p,init:true},headerCellsVisible:{check:p,init:true,apply:O},headerCellHeight:{check:bs,init:16,apply:bm,event:r,nullable:true},statusBarVisible:{check:p,init:true,apply:by},additionalStatusBarText:{nullable:true,init:null,apply:V},columnVisibilityButtonVisible:{check:p,init:true,apply:bi},metaColumnCounts:{check:bf,apply:s},focusCellOnMouseMove:{check:p,init:false,apply:Y},rowFocusChangeModifiesSelection:{check:p,init:true},showCellFocusIndicator:{check:p,init:true,apply:be},keepFirstVisibleRowComplete:{check:p,init:true,apply:bn},alwaysUpdateCells:{check:p,init:false},resetSelectionOnHeaderClick:{check:p,init:true,apply:v},dataRowRenderer:{check:J,init:null,nullable:true,event:q},modalCellEditorPreOpenFunction:{check:n,init:null,nullable:true},newColumnMenu:{check:n,init:function(){return new qx.ui.table.columnmenu.Button();}},newSelectionManager:{check:n,init:function(bJ){return new qx.ui.table.selection.Manager(bJ);}},newSelectionModel:{check:n,init:function(bK){return new qx.ui.table.selection.Model(bK);}},newTableColumnModel:{check:n,init:function(bL){return new qx.ui.table.columnmodel.Basic(bL);}},newTablePane:{check:n,init:function(bM){return new qx.ui.table.pane.Pane(bM);}},newTablePaneHeader:{check:n,init:function(bN){return new qx.ui.table.pane.Header(bN);}},newTablePaneScroller:{check:n,init:function(bO){return new qx.ui.table.pane.Scroller(bO);}},newTablePaneModel:{check:n,init:function(bP){return new qx.ui.table.pane.Model(bP);}}},members:{__vU:null,__vV:null,__vS:null,__vT:null,__vX:null,__vY:null,__wa:null,__wb:null,__wc:null,__wd:null,_createChildControlImpl:function(bQ,bR){var bS;switch(bQ){case k:bS=new qx.ui.basic.Label();bS.set({allowGrowX:true});this._add(bS);break;case o:bS=this.getNewColumnMenu()();bS.set({focusable:false});var bT=bS.factory(R,{table:this});bT.addListener(K,this._initColumnMenu,this);break;}return bS||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,bQ);},_applySelectionModel:function(bU,bV){this.__vT.setSelectionModel(bU);if(bV!=null){bV.removeListener(bE,this._onSelectionChanged,this);}bU.addListener(bE,this._onSelectionChanged,this);},_applyRowHeight:function(bW,bX){var bY=this._getPaneScrollerArr();for(var i=0;i<bY.length;i++){bY[i].updateVerScrollBarMaximum();}},_applyHeaderCellsVisible:function(ca,cb){var cc=this._getPaneScrollerArr();for(var i=0;i<cc.length;i++){cc[i]._excludeChildControl(H);}},_applyHeaderCellHeight:function(cd,ce){var cf=this._getPaneScrollerArr();for(var i=0;i<cf.length;i++){cf[i].getHeader().setHeight(cd);}},getEmptyTableModel:function(){if(!this.__wd){this.__wd=new qx.ui.table.model.Simple();this.__wd.setColumns([]);this.__wd.setData([]);}return this.__wd;},_applyTableModel:function(cg,ch){this.getTableColumnModel().init(cg.getColumnCount(),this);if(ch!=null){ch.removeListener(bA,this._onTableModelMetaDataChanged,this);ch.removeListener(f,this._onTableModelDataChanged,this);}cg.addListener(bA,this._onTableModelMetaDataChanged,this);cg.addListener(f,this._onTableModelDataChanged,this);this._updateStatusBar();this._updateTableData(0,cg.getRowCount(),0,cg.getColumnCount());this._onTableModelMetaDataChanged();if(ch&&cg.init&&typeof (cg.init)==h){cg.init(this);}},getTableColumnModel:function(){if(!this.__wc){var ck=this.__wc=this.getNewTableColumnModel()(this);ck.addListener(bv,this._onColVisibilityChanged,this);ck.addListener(B,this._onColWidthChanged,this);ck.addListener(bt,this._onColOrderChanged,this);var cj=this.getTableModel();ck.init(cj.getColumnCount(),this);var ci=this._getPaneScrollerArr();for(var i=0;i<ci.length;i++){var cl=ci[i];var cm=cl.getTablePaneModel();cm.setTableColumnModel(ck);}}return this.__wc;},_applyStatusBarVisible:function(cn,co){if(cn){this._showChildControl(k);}else{this._excludeChildControl(k);}if(cn){this._updateStatusBar();}},_applyAdditionalStatusBarText:function(cp,cq){this.__vX=cp;this._updateStatusBar();},_applyColumnVisibilityButtonVisible:function(cr,cs){if(cr){this._showChildControl(o);}else{this._excludeChildControl(o);}},_applyMetaColumnCounts:function(ct,cu){var cB=ct;var cv=this._getPaneScrollerArr();var cz={};if(ct>cu){var cD=qx.event.Registration.getManager(cv[0]);for(var cE in qx.ui.table.Table.__vW){cz[cE]={};cz[cE].capture=cD.getListeners(cv[0],cE,true);cz[cE].bubble=cD.getListeners(cv[0],cE,false);}}this._cleanUpMetaColumns(cB.length);var cA=0;for(var i=0;i<cv.length;i++){var cF=cv[i];var cC=cF.getTablePaneModel();cC.setFirstColumnX(cA);cC.setMaxColumnCount(cB[i]);cA+=cB[i];}if(cB.length>cv.length){var cy=this.getTableColumnModel();for(var i=cv.length;i<cB.length;i++){var cC=this.getNewTablePaneModel()(cy);cC.setFirstColumnX(cA);cC.setMaxColumnCount(cB[i]);cA+=cB[i];var cF=this.getNewTablePaneScroller()(this);cF.setTablePaneModel(cC);cF.addListener(ba,this._onScrollY,this);for(cE in qx.ui.table.Table.__vW){if(!cz[cE]){break;}if(cz[cE].capture&&cz[cE].capture.length>0){var cw=cz[cE].capture;for(var i=0;i<cw.length;i++){var cx=cw[i].context;if(!cx){cx=this;}else if(cx==cv[0]){cx=cF;}cF.addListener(cE,cw[i].handler,cx,true);}}if(cz[cE].bubble&&cz[cE].bubble.length>0){var cH=cz[cE].bubble;for(var i=0;i<cH.length;i++){var cx=cH[i].context;if(!cx){cx=this;}else if(cx==cv[0]){cx=cF;}cF.addListener(cE,cH[i].handler,cx,false);}}}var cG=(i==cB.length-1)?1:0;this.__vS.add(cF,{flex:cG});cv=this._getPaneScrollerArr();}}for(var i=0;i<cv.length;i++){var cF=cv[i];var cI=(i==(cv.length-1));cF.getHeader().setHeight(this.getHeaderCellHeight());cF.setTopRightWidget(cI?this.getChildControl(o):null);}if(!this.isColumnVisibilityButtonVisible()){this._excludeChildControl(o);}this._updateScrollerWidths();this._updateScrollBarVisibility();},_applyFocusCellOnMouseMove:function(cJ,cK){var cL=this._getPaneScrollerArr();for(var i=0;i<cL.length;i++){cL[i].setFocusCellOnMouseMove(cJ);}},_applyShowCellFocusIndicator:function(cM,cN){var cO=this._getPaneScrollerArr();for(var i=0;i<cO.length;i++){cO[i].setShowCellFocusIndicator(cM);}},_applyKeepFirstVisibleRowComplete:function(cP,cQ){var cR=this._getPaneScrollerArr();for(var i=0;i<cR.length;i++){cR[i].onKeepFirstVisibleRowCompleteChanged();}},_applyResetSelectionOnHeaderClick:function(cS,cT){var cU=this._getPaneScrollerArr();for(var i=0;i<cU.length;i++){cU[i].setResetSelectionOnHeaderClick(cS);}},getSelectionManager:function(){return this.__vT;},_getPaneScrollerArr:function(){return this.__vS.getChildren();},getPaneScroller:function(cV){return this._getPaneScrollerArr()[cV];},_cleanUpMetaColumns:function(cW){var cX=this._getPaneScrollerArr();if(cX!=null){for(var i=cX.length-1;i>=cW;i--){cX[i].destroy();}}},_onChangeLocale:function(cY){this.updateContent();this._updateStatusBar();},_onSelectionChanged:function(da){var db=this._getPaneScrollerArr();for(var i=0;i<db.length;i++){db[i].onSelectionChanged();}this._updateStatusBar();},_onTableModelMetaDataChanged:function(dc){var dd=this._getPaneScrollerArr();for(var i=0;i<dd.length;i++){dd[i].onTableModelMetaDataChanged();}this._updateStatusBar();},_onTableModelDataChanged:function(de){var df=de.getData();this._updateTableData(df.firstRow,df.lastRow,df.firstColumn,df.lastColumn,df.removeStart,df.removeCount);},_updateTableData:function(dg,dh,di,dj,dk,dl){var dm=this._getPaneScrollerArr();if(dl){this.getSelectionModel().removeSelectionInterval(dk,dk+dl);if(this.__vV>=dk&&this.__vV<(dk+dl)){this.setFocusedCell();}}for(var i=0;i<dm.length;i++){dm[i].onTableModelDataChanged(dg,dh,di,dj);}var dn=this.getTableModel().getRowCount();if(dn!=this.__vY){this.__vY=dn;this._updateScrollBarVisibility();this._updateStatusBar();}},_onScrollY:function(dp){if(!this.__wa){this.__wa=true;var dq=this._getPaneScrollerArr();for(var i=0;i<dq.length;i++){dq[i].setScrollY(dp.getData());}this.__wa=false;}},_onKeyPress:function(dr){if(!this.getEnabled()){return;}var dy=this.__vV;var dv=true;var dz=dr.getKeyIdentifier();if(this.isEditing()){if(dr.getModifiers()==0){switch(dz){case bB:this.stopEditing();var dy=this.__vV;this.moveFocusedCell(0,1);if(this.__vV!=dy){dv=this.startEditing();}break;case F:this.cancelEditing();this.focus();break;default:dv=false;break;}}}else{if(dr.isCtrlPressed()){dv=true;switch(dz){case G:var dw=this.getTableModel().getRowCount();if(dw>0){this.getSelectionModel().setSelectionInterval(0,dw-1);}break;default:dv=false;break;}}else{switch(dz){case S:this.__vT.handleSelectKeyDown(this.__vV,dr);break;case d:case bB:this.startEditing();dv=true;break;case U:this.setFocusedCell(this.__vU,0,true);break;case a:var dw=this.getTableModel().getRowCount();this.setFocusedCell(this.__vU,dw-1,true);break;case T:this.moveFocusedCell(-1,0);break;case c:this.moveFocusedCell(1,0);break;case D:this.moveFocusedCell(0,-1);break;case bb:this.moveFocusedCell(0,1);break;case g:case bq:var du=this.getPaneScroller(0);var dx=du.getTablePane();var dt=this.getRowHeight();var ds=(dz==g)?-1:1;dw=dx.getVisibleRowCount()-1;du.setScrollY(du.getScrollY()+ds*dw*dt);this.moveFocusedCell(0,ds*dw);break;default:dv=false;}}}if(dy!=this.__vV&&this.getRowFocusChangeModifiesSelection()){this.__vT.handleMoveKeyDown(this.__vV,dr);}if(dv){dr.preventDefault();dr.stopPropagation();}},_onFocusChanged:function(dA){var dB=this._getPaneScrollerArr();for(var i=0;i<dB.length;i++){dB[i].onFocusChanged();}},_onColVisibilityChanged:function(dC){var dD=this._getPaneScrollerArr();for(var i=0;i<dD.length;i++){dD[i].onColVisibilityChanged();}var dE=dC.getData();if(this.__wb!=null&&dE.col!=null&&dE.visible!=null){this.__wb[dE.col].setVisible(dE.visible);}this._updateScrollerWidths();this._updateScrollBarVisibility();},_onColWidthChanged:function(dF){var dG=this._getPaneScrollerArr();for(var i=0;i<dG.length;i++){var dH=dF.getData();dG[i].setColumnWidth(dH.col,dH.newWidth);}this._updateScrollerWidths();this._updateScrollBarVisibility();},_onColOrderChanged:function(dI){var dJ=this._getPaneScrollerArr();for(var i=0;i<dJ.length;i++){dJ[i].onColOrderChanged();}this._updateScrollerWidths();this._updateScrollBarVisibility();},getTablePaneScrollerAtPageX:function(dK){var dL=this._getMetaColumnAtPageX(dK);return (dL!=-1)?this.getPaneScroller(dL):null;},setFocusedCell:function(dM,dN,dO){if(!this.isEditing()&&(dM!=this.__vU||dN!=this.__vV)){if(dM===null){dM=0;}this.__vU=dM;this.__vV=dN;var dP=this._getPaneScrollerArr();for(var i=0;i<dP.length;i++){dP[i].setFocusedCell(dM,dN);}if(dM!==null&&dO){this.scrollCellVisible(dM,dN);}}},resetSelection:function(){this.getSelectionModel().resetSelection();},resetCellFocus:function(){this.setFocusedCell(null,null,false);},getFocusedColumn:function(){return this.__vU;},getFocusedRow:function(){return this.__vV;},highlightFocusedRow:function(dQ){this.getDataRowRenderer().setHighlightFocusRow(dQ);},clearFocusedRowHighlight:function(dR){if(dR){var dT=dR.getRelatedTarget();if(dT instanceof qx.ui.table.pane.Pane||dT instanceof qx.ui.table.pane.FocusIndicator){return;}}this.resetCellFocus();var dS=this._getPaneScrollerArr();for(var i=0;i<dS.length;i++){dS[i].onFocusChanged();}},moveFocusedCell:function(dU,dV){var ea=this.__vU;var eb=this.__vV;if(ea===null||eb===null){return;}if(dU!=0){var dY=this.getTableColumnModel();var x=dY.getVisibleX(ea);var dX=dY.getVisibleColumnCount();x=qx.lang.Number.limit(x+dU,0,dX-1);ea=dY.getVisibleColumnAtX(x);}if(dV!=0){var dW=this.getTableModel();eb=qx.lang.Number.limit(eb+dV,0,dW.getRowCount()-1);}this.setFocusedCell(ea,eb,true);},scrollCellVisible:function(ec,ed){var ee=this.getTableColumnModel();var x=ee.getVisibleX(ec);var ef=this._getMetaColumnAtColumnX(x);if(ef!=-1){this.getPaneScroller(ef).scrollCellVisible(ec,ed);}},isEditing:function(){if(this.__vU!=null){var x=this.getTableColumnModel().getVisibleX(this.__vU);var eg=this._getMetaColumnAtColumnX(x);return this.getPaneScroller(eg).isEditing();}return false;},startEditing:function(){if(this.__vU!=null){var x=this.getTableColumnModel().getVisibleX(this.__vU);var ei=this._getMetaColumnAtColumnX(x);var eh=this.getPaneScroller(ei).startEditing();return eh;}return false;},stopEditing:function(){if(this.__vU!=null){var x=this.getTableColumnModel().getVisibleX(this.__vU);var ej=this._getMetaColumnAtColumnX(x);this.getPaneScroller(ej).stopEditing();}},cancelEditing:function(){if(this.__vU!=null){var x=this.getTableColumnModel().getVisibleX(this.__vU);var ek=this._getMetaColumnAtColumnX(x);this.getPaneScroller(ek).cancelEditing();}},updateContent:function(){var el=this._getPaneScrollerArr();for(var i=0;i<el.length;i++){el[i].getTablePane().updateContent(true);}},blockHeaderElements:function(){var em=this._getPaneScrollerArr();for(var i=0;i<em.length;i++){em[i].getHeader().getBlocker().blockContent(20);}this.getChildControl(o).getBlocker().blockContent(20);},unblockHeaderElements:function(){var en=this._getPaneScrollerArr();for(var i=0;i<en.length;i++){en[i].getHeader().getBlocker().unblockContent();}this.getChildControl(o).getBlocker().unblockContent();},_getMetaColumnAtPageX:function(eo){var ep=this._getPaneScrollerArr();for(var i=0;i<ep.length;i++){var eq=ep[i].getContainerLocation();if(eo>=eq.left&&eo<=eq.right){return i;}}return -1;},_getMetaColumnAtColumnX:function(er){var et=this.getMetaColumnCounts();var eu=0;for(var i=0;i<et.length;i++){var es=et[i];eu+=es;if(es==-1||er<eu){return i;}}return -1;},_updateStatusBar:function(){var ev=this.getTableModel();if(this.getStatusBarVisible()){var ew=this.getSelectionModel().getSelectedCount();var ey=ev.getRowCount();var ex;if(ey>=0){if(ew==0){ex=this.trn(W,E,ey,ey);}else{ex=this.trn(C,bp,ey,ew,ey);}}if(this.__vX){if(ex){ex+=this.__vX;}else{ex=this.__vX;}}if(ex){this.getChildControl(k).setValue(ex);}}},_updateScrollerWidths:function(){var ez=this._getPaneScrollerArr();for(var i=0;i<ez.length;i++){var eB=(i==(ez.length-1));var eC=ez[i].getTablePaneModel().getTotalWidth();ez[i].setPaneWidth(eC);var eA=eB?1:0;ez[i].setLayoutProperties({flex:eA});}},_updateScrollBarVisibility:function(){if(!this.getBounds()){return;}var eG=qx.ui.table.pane.Scroller.HORIZONTAL_SCROLLBAR;var eJ=qx.ui.table.pane.Scroller.VERTICAL_SCROLLBAR;var eD=this._getPaneScrollerArr();var eF=false;var eI=false;for(var i=0;i<eD.length;i++){var eK=(i==(eD.length-1));var eE=eD[i].getNeededScrollBars(eF,!eK);if(eE&eG){eF=true;}if(eK&&(eE&eJ)){eI=true;}}for(var i=0;i<eD.length;i++){var eK=(i==(eD.length-1));var eH;eD[i].setHorizontalScrollBarVisible(eF);if(eK){eH=eD[i].getVerticalScrollBarVisible();}eD[i].setVerticalScrollBarVisible(eK&&eI);if(eK&&eI!=eH){this.fireDataEvent(bk,eI);}}},_initColumnMenu:function(){var eN=this.getTableModel();var eO=this.getTableColumnModel();var eP=this.getChildControl(o);eP.empty();var eM=eP.getMenu();var eQ={table:this,menu:eM,columnButton:eP};this.fireDataEvent(bx,eQ);this.__wb={};for(var eR=0,l=eN.getColumnCount();eR<l;eR++){var eL=eP.factory(P,{text:eN.getColumnName(eR),column:eR,bVisible:eO.isColumnVisible(eR)});qx.core.Assert.assertInterface(eL,qx.ui.table.IColumnMenuItem);eL.addListener(u,this._createColumnVisibilityCheckBoxHandler(eR),this);this.__wb[eR]=eL;}eQ={table:this,menu:eM,columnButton:eP};this.fireDataEvent(y,eQ);},_createColumnVisibilityCheckBoxHandler:function(eS){return function(eT){var eU=this.getTableColumnModel();eU.setColumnVisible(eS,eT.getData());};},setColumnWidth:function(eV,eW){this.getTableColumnModel().setColumnWidth(eV,eW);},_onResize:function(){this.fireEvent(A);this._updateScrollerWidths();this._updateScrollBarVisibility();},addListener:function(eX,eY,self,fa){if(this.self(arguments).__vW[eX]){var fc=[eX];for(var i=0,fb=this._getPaneScrollerArr();i<fb.length;i++){fc.push(fb[i].addListener.apply(fb[i],arguments));}return fc.join(e);}else{return qx.ui.core.Widget.prototype.addListener.call(this,eX,eY,self,fa);}},removeListener:function(fd,fe,self,ff){if(this.self(arguments).__vW[fd]){for(var i=0,fg=this._getPaneScrollerArr();i<fg.length;i++){fg[i].removeListener.apply(fg[i],arguments);}}else{qx.ui.core.Widget.prototype.removeListener.call(this,fd,fe,self,ff);}},removeListenerById:function(fh){var fl=fh.split(e);var fk=fl.shift();if(this.self(arguments).__vW[fk]){var fj=true;for(var i=0,fi=this._getPaneScrollerArr();i<fi.length;i++){fj=fi[i].removeListenerById.call(fi[i],fl[i])&&fj;}return fj;}else{return qx.ui.core.Widget.prototype.removeListenerById.call(this,fh);}},destroy:function(){this.getChildControl(o).getMenu().destroy();qx.ui.core.Widget.prototype.destroy.call(this);}},destruct:function(){if(qx.core.Variant.isSet(bD,bz)){qx.locale.Manager.getInstance().removeListener(bF,this._onChangeLocale,this);}var fn=this.getSelectionModel();if(fn){fn.dispose();}var fm=this.getDataRowRenderer();if(fm){fm.dispose();}this._cleanUpMetaColumns(0);this.getTableColumnModel().dispose();this._disposeObjects(M,bg,bC,bC,bj);this._disposeMap(N);}});})();(function(){var a="qx.ui.table.IRowRenderer";qx.Interface.define(a,{members:{updateDataRowElement:function(b,c){},getRowHeightStyle:function(d){},createRowStyle:function(e){},getRowClass:function(f){}}});})();(function(){var t="",s="table-row-background-even",r="table-row-background-selected",q="table-row",p="background-color:",o="table-row-background-focused",n=';border-bottom: 1px solid ',m=';color:',l="table-row-selected",k="table-row-background-odd",d="default",j="table-row-background-focused-selected",g="qx.ui.table.rowrenderer.Default",c="table-row-line",b="'",f="height:",e=";",h="px;",a="1px solid ",i="Boolean";qx.Class.define(g,{extend:qx.core.Object,implement:qx.ui.table.IRowRenderer,construct:function(){qx.core.Object.call(this);this.__wi=t;this.__wi={};this.__wj={};this._renderFont(qx.theme.manager.Font.getInstance().resolve(d));var u=qx.theme.manager.Color.getInstance();this.__wj.bgcolFocusedSelected=u.resolve(j);this.__wj.bgcolFocused=u.resolve(o);this.__wj.bgcolSelected=u.resolve(r);this.__wj.bgcolEven=u.resolve(s);this.__wj.bgcolOdd=u.resolve(k);this.__wj.colSelected=u.resolve(l);this.__wj.colNormal=u.resolve(q);this.__wj.horLine=u.resolve(c);},properties:{highlightFocusRow:{check:i,init:true}},members:{__wj:null,__wk:null,__wi:null,_insetY:1,_renderFont:function(v){if(v){this.__wk=v.getStyles();this.__wi=qx.bom.element.Style.compile(this.__wk);this.__wi=this.__wi.replace(/"/g,b);}else{this.__wi=t;this.__wk=qx.bom.Font.getDefaultStyles();}},updateDataRowElement:function(w,x){var z=this.__wk;var y=x.style;qx.bom.element.Style.setStyles(x,z);if(w.focusedRow&&this.getHighlightFocusRow()){y.backgroundColor=w.selected?this.__wj.bgcolFocusedSelected:this.__wj.bgcolFocused;}else{if(w.selected){y.backgroundColor=this.__wj.bgcolSelected;}else{y.backgroundColor=(w.row%2==0)?this.__wj.bgcolEven:this.__wj.bgcolOdd;}}y.color=w.selected?this.__wj.colSelected:this.__wj.colNormal;y.borderBottom=a+this.__wj.horLine;},getRowHeightStyle:function(A){if(qx.bom.client.Feature.CONTENT_BOX){A-=this._insetY;}return f+A+h;},createRowStyle:function(B){var C=[];C.push(e);C.push(this.__wi);C.push(p);if(B.focusedRow&&this.getHighlightFocusRow()){C.push(B.selected?this.__wj.bgcolFocusedSelected:this.__wj.bgcolFocused);}else{if(B.selected){C.push(this.__wj.bgcolSelected);}else{C.push((B.row%2==0)?this.__wj.bgcolEven:this.__wj.bgcolOdd);}}C.push(m);C.push(B.selected?this.__wj.colSelected:this.__wj.colNormal);C.push(n,this.__wj.horLine);return C.join(t);},getRowClass:function(D){return t;},getRowAttributes:function(E){return t;}},destruct:function(){this.__wj=this.__wk=this.__wi=null;}});})();(function(){var a="qx.ui.table.IColumnMenuButton";qx.Interface.define(a,{properties:{menu:{}},members:{factory:function(b,c){return true;},empty:function(){return true;}}});})();(function(){var l="pressed",k="hovered",j="changeVisibility",i="qx.ui.menu.Menu",h="submenu",g="Enter",f="contextmenu",d="changeMenu",c="qx.ui.form.MenuButton",b="abandoned",a="_applyMenu";qx.Class.define(c,{extend:qx.ui.form.Button,construct:function(m,n,o){qx.ui.form.Button.call(this,m,n);if(o!=null){this.setMenu(o);}},properties:{menu:{check:i,nullable:true,apply:a,event:d}},members:{_applyMenu:function(p,q){if(q){q.removeListener(j,this._onMenuChange,this);q.resetOpener();}if(p){p.addListener(j,this._onMenuChange,this);p.setOpener(this);p.removeState(h);p.removeState(f);}},open:function(r){var s=this.getMenu();if(s){qx.ui.menu.Manager.getInstance().hideAll();s.setOpener(this);s.open();if(r){var t=s.getSelectables()[0];if(t){s.setSelectedButton(t);}}}},_onMenuChange:function(e){var u=this.getMenu();if(u.isVisible()){this.addState(l);}else{this.removeState(l);}},_onMouseDown:function(e){qx.ui.form.Button.prototype._onMouseDown.call(this,e);var v=this.getMenu();if(v){if(!v.isVisible()){this.open();}else{v.exclude();}e.stopPropagation();}},_onMouseUp:function(e){qx.ui.form.Button.prototype._onMouseUp.call(this,e);e.stopPropagation();},_onMouseOver:function(e){this.addState(k);},_onMouseOut:function(e){this.removeState(k);},_onKeyDown:function(e){switch(e.getKeyIdentifier()){case g:this.removeState(b);this.addState(l);var w=this.getMenu();if(w){if(!w.isVisible()){this.open();}else{w.exclude();}}e.stopPropagation();}},_onKeyUp:function(e){}},destruct:function(){if(this.getMenu()){if(!qx.core.ObjectRegistry.inShutDown){this.getMenu().destroy();}}}});})();(function(){var f="menu-button",e="table-column-reset-button",d="separator",c="user-button",b="qx.ui.table.columnmenu.Button",a="menu";qx.Class.define(b,{extend:qx.ui.form.MenuButton,implement:qx.ui.table.IColumnMenuButton,construct:function(){qx.ui.form.MenuButton.call(this);this.__wl=new qx.ui.core.Blocker(this);},members:{__wm:null,__wl:null,factory:function(g,h){switch(g){case a:var j=new qx.ui.menu.Menu();this.setMenu(j);return j;case f:var m=new qx.ui.table.columnmenu.MenuItem(h.text);m.setVisible(h.bVisible);this.getMenu().add(m);return m;case c:var k=new qx.ui.menu.Button(h.text);k.set({appearance:e});return k;case d:return new qx.ui.menu.Separator();default:throw new Error("Unrecognized factory request: "+g);}},getBlocker:function(){return this.__wl;},empty:function(){var n=this.getMenu();var o=n.getChildren();for(var i=0,l=o.length;i<l;i++){o[0].destroy();}}},destruct:function(){this.__wl.dispose();}});})();(function(){var t="keypress",s="interval",r="keydown",q="mousedown",p="keyup",o="__on",n="blur",m="Enter",l="__oo",k="Up",c="Escape",j="qx.ui.menu.Manager",g="Left",b="__om",a="Down",f="Right",d="singleton",h="Space";qx.Class.define(j,{type:d,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__om=[];var u=document.body;var v=qx.event.Registration;v.addListener(window.document.documentElement,q,this._onMouseDown,this,true);v.addListener(u,r,this._onKeyUpDown,this,true);v.addListener(u,p,this._onKeyUpDown,this,true);v.addListener(u,t,this._onKeyPress,this,true);if(!qx.bom.client.Feature.TOUCH){qx.bom.Element.addListener(window,n,this.hideAll,this);}this.__on=new qx.event.Timer;this.__on.addListener(s,this._onOpenInterval,this);this.__oo=new qx.event.Timer;this.__oo.addListener(s,this._onCloseInterval,this);},members:{__op:null,__oq:null,__on:null,__oo:null,__om:null,_getChild:function(w,x,y,z){var A=w.getChildren();var length=A.length;var B;for(var i=x;i<length&&i>=0;i+=y){B=A[i];if(B.isEnabled()&&!B.isAnonymous()){return B;}}if(z){i=i==length?0:length-1;for(;i!=x;i+=y){B=A[i];if(B.isEnabled()&&!B.isAnonymous()){return B;}}}return null;},_isInMenu:function(C){while(C){if(C instanceof qx.ui.menu.Menu){return true;}C=C.getLayoutParent();}return false;},_getMenuButton:function(D){while(D){if(D instanceof qx.ui.menu.AbstractButton){return D;}D=D.getLayoutParent();}return null;},add:function(E){{};var F=this.__om;F.push(E);E.setZIndex(1e6+F.length);},remove:function(G){{};var H=this.__om;if(H){qx.lang.Array.remove(H,G);}},hideAll:function(){var I=this.__om;if(I){for(var i=I.length-1;i>=0;i--){I[i].exclude();}}},getActiveMenu:function(){var J=this.__om;return J.length>0?J[J.length-1]:null;},scheduleOpen:function(K){this.cancelClose(K);if(K.isVisible()){if(this.__op){this.cancelOpen(this.__op);}}else if(this.__op!=K){this.__op=K;this.__on.restartWith(K.getOpenInterval());}},scheduleClose:function(L){this.cancelOpen(L);if(!L.isVisible()){if(this.__oq){this.cancelClose(this.__oq);}}else if(this.__oq!=L){this.__oq=L;this.__oo.restartWith(L.getCloseInterval());}},cancelOpen:function(M){if(this.__op==M){this.__on.stop();this.__op=null;}},cancelClose:function(N){if(this.__oq==N){this.__oo.stop();this.__oq=null;}},_onOpenInterval:function(e){this.__on.stop();this.__op.open();this.__op=null;},_onCloseInterval:function(e){this.__oo.stop();this.__oq.exclude();this.__oq=null;},_onMouseDown:function(e){var O=e.getTarget();O=qx.ui.core.Widget.getWidgetByElement(O,true);if(O==null){this.hideAll();return;}if(O.getMenu&&O.getMenu()&&O.getMenu().isVisible()){return;}if(this.__om.length>0&&!this._isInMenu(O)){this.hideAll();}},__or:{"Enter":1,"Space":1},__os:{"Escape":1,"Up":1,"Down":1,"Left":1,"Right":1},_onKeyUpDown:function(e){var P=this.getActiveMenu();if(!P){return;}var Q=e.getKeyIdentifier();if(this.__os[Q]||(this.__or[Q]&&P.getSelectedButton())){e.stopPropagation();}},_onKeyPress:function(e){var R=this.getActiveMenu();if(!R){return;}var S=e.getKeyIdentifier();var U=this.__os[S];var T=this.__or[S];if(U){switch(S){case k:this._onKeyPressUp(R);break;case a:this._onKeyPressDown(R);break;case g:this._onKeyPressLeft(R);break;case f:this._onKeyPressRight(R);break;case c:this.hideAll();break;}e.stopPropagation();e.preventDefault();}else if(T){var V=R.getSelectedButton();if(V){switch(S){case m:this._onKeyPressEnter(R,V,e);break;case h:this._onKeyPressSpace(R,V,e);break;}e.stopPropagation();e.preventDefault();}}},_onKeyPressUp:function(W){var X=W.getSelectedButton();var Y=W.getChildren();var bb=X?W.indexOf(X)-1:Y.length-1;var ba=this._getChild(W,bb,-1,true);if(ba){W.setSelectedButton(ba);}else{W.resetSelectedButton();}},_onKeyPressDown:function(bc){var bd=bc.getSelectedButton();var bf=bd?bc.indexOf(bd)+1:0;var be=this._getChild(bc,bf,1,true);if(be){bc.setSelectedButton(be);}else{bc.resetSelectedButton();}},_onKeyPressLeft:function(bg){var bl=bg.getOpener();if(!bl){return;}if(bl instanceof qx.ui.menu.AbstractButton){var bi=bl.getLayoutParent();bi.resetOpenedButton();bi.setSelectedButton(bl);}else if(bl instanceof qx.ui.menubar.Button){var bk=bl.getMenuBar().getMenuButtons();var bh=bk.indexOf(bl);if(bh===-1){return;}var bm=null;var length=bk.length;for(var i=1;i<=length;i++){var bj=bk[(bh-i+length)%length];if(bj.isEnabled()){bm=bj;break;}}if(bm&&bm!=bl){bm.open(true);}}},_onKeyPressRight:function(bn){var bp=bn.getSelectedButton();if(bp){var bo=bp.getMenu();if(bo){bn.setOpenedButton(bp);var bv=this._getChild(bo,0,1);if(bv){bo.setSelectedButton(bv);}return;}}else if(!bn.getOpenedButton()){var bv=this._getChild(bn,0,1);if(bv){bn.setSelectedButton(bv);if(bv.getMenu()){bn.setOpenedButton(bv);}return;}}var bt=bn.getOpener();if(bt instanceof qx.ui.menu.Button&&bp){while(bt){bt=bt.getLayoutParent();if(bt instanceof qx.ui.menu.Menu){bt=bt.getOpener();if(bt instanceof qx.ui.menubar.Button){break;}}else{break;}}if(!bt){return;}}if(bt instanceof qx.ui.menubar.Button){var bs=bt.getMenuBar().getMenuButtons();var bq=bs.indexOf(bt);if(bq===-1){return;}var bu=null;var length=bs.length;for(var i=1;i<=length;i++){var br=bs[(bq+i)%length];if(br.isEnabled()){bu=br;break;}}if(bu&&bu!=bt){bu.open(true);}}},_onKeyPressEnter:function(bw,bx,e){if(bx.hasListener(t)){var by=e.clone();by.setBubbles(false);by.setTarget(bx);bx.dispatchEvent(by);}this.hideAll();},_onKeyPressSpace:function(bz,bA,e){if(bA.hasListener(t)){var bB=e.clone();bB.setBubbles(false);bB.setTarget(bA);bA.dispatchEvent(bB);}}},destruct:function(){var bD=qx.event.Registration;var bC=document.body;bD.removeListener(window.document.documentElement,q,this._onMouseDown,this,true);bD.removeListener(bC,r,this._onKeyUpDown,this,true);bD.removeListener(bC,p,this._onKeyUpDown,this,true);bD.removeListener(bC,t,this._onKeyPress,this,true);this._disposeObjects(o,l);this._disposeArray(b);}});})();(function(){var l="indexOf",k="addAfter",j="add",i="addBefore",h="_",g="addAt",f="hasChildren",e="removeAt",d="removeAll",c="getChildren",a="remove",b="qx.ui.core.MRemoteChildrenHandling";qx.Mixin.define(b,{members:{__ex:function(m,n,o,p){var q=this.getChildrenContainer();if(q===this){m=h+m;}return (q[m])(n,o,p);},getChildren:function(){return this.__ex(c);},hasChildren:function(){return this.__ex(f);},add:function(r,s){return this.__ex(j,r,s);},remove:function(t){return this.__ex(a,t);},removeAll:function(){return this.__ex(d);},indexOf:function(u){return this.__ex(l,u);},addAt:function(v,w,x){this.__ex(g,v,w,x);},addBefore:function(y,z,A){this.__ex(i,y,z,A);},addAfter:function(B,C,D){this.__ex(k,B,C,D);},removeAt:function(E){this.__ex(e,E);}}});})();(function(){var l="slidebar",k="Integer",j="resize",h="qx.ui.core.Widget",g="selected",f="visible",d="Boolean",c="mouseout",b="excluded",a="menu",A="_applySelectedButton",z="_applyOpenInterval",y="_applySpacingY",x="_blocker",w="_applyCloseInterval",v="_applyBlockerColor",u="_applyIconColumnWidth",t="mouseover",s="qx.ui.menu.Menu",r="Color",p="Number",q="_applyOpenedButton",n="_applySpacingX",o="_applyBlockerOpacity",m="_applyArrowColumnWidth";qx.Class.define(s,{extend:qx.ui.core.Widget,include:[qx.ui.core.MPlacement,qx.ui.core.MRemoteChildrenHandling],construct:function(){qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.menu.Layout);var B=this.getApplicationRoot();B.add(this);this.addListener(t,this._onMouseOver);this.addListener(c,this._onMouseOut);this.addListener(j,this._onResize,this);B.addListener(j,this._onResize,this);this._blocker=new qx.ui.core.Blocker(B);this.initVisibility();this.initKeepFocus();this.initKeepActive();},properties:{appearance:{refine:true,init:a},allowGrowX:{refine:true,init:false},allowGrowY:{refine:true,init:false},visibility:{refine:true,init:b},keepFocus:{refine:true,init:true},keepActive:{refine:true,init:true},spacingX:{check:k,apply:n,init:0,themeable:true},spacingY:{check:k,apply:y,init:0,themeable:true},iconColumnWidth:{check:k,init:0,themeable:true,apply:u},arrowColumnWidth:{check:k,init:0,themeable:true,apply:m},blockerColor:{check:r,init:null,nullable:true,apply:v,themeable:true},blockerOpacity:{check:p,init:1,apply:o,themeable:true},selectedButton:{check:h,nullable:true,apply:A},openedButton:{check:h,nullable:true,apply:q},opener:{check:h,nullable:true},openInterval:{check:k,themeable:true,init:250,apply:z},closeInterval:{check:k,themeable:true,init:250,apply:w},blockBackground:{check:d,themeable:true,init:false}},members:{__qv:null,__qw:null,_blocker:null,open:function(){if(this.getOpener()!=null){this.placeToWidget(this.getOpener());this.__qy();this.show();this._placementTarget=this.getOpener();}else{this.warn("The menu instance needs a configured 'opener' widget!");}},openAtMouse:function(e){this.placeToMouse(e);this.__qy();this.show();this._placementTarget={left:e.getDocumentLeft(),top:e.getDocumentTop()};},openAtPoint:function(C){this.placeToPoint(C);this.__qy();this.show();this._placementTarget=C;},addSeparator:function(){this.add(new qx.ui.menu.Separator);},getColumnSizes:function(){return this._getMenuLayout().getColumnSizes();},getSelectables:function(){var D=[];var E=this.getChildren();for(var i=0;i<E.length;i++){if(E[i].isEnabled()){D.push(E[i]);}}return D;},_applyIconColumnWidth:function(F,G){this._getMenuLayout().setIconColumnWidth(F);},_applyArrowColumnWidth:function(H,I){this._getMenuLayout().setArrowColumnWidth(H);},_applySpacingX:function(J,K){this._getMenuLayout().setColumnSpacing(J);},_applySpacingY:function(L,M){this._getMenuLayout().setSpacing(L);},_applyVisibility:function(N,O){qx.ui.core.Widget.prototype._applyVisibility.call(this,N,O);var P=qx.ui.menu.Manager.getInstance();if(N===f){P.add(this);var Q=this.getParentMenu();if(Q){Q.setOpenedButton(this.getOpener());}}else if(O===f){P.remove(this);var Q=this.getParentMenu();if(Q&&Q.getOpenedButton()==this.getOpener()){Q.resetOpenedButton();}this.resetOpenedButton();this.resetSelectedButton();}this.__qx();},__qx:function(){if(this.isVisible()){if(this.getBlockBackground()){var R=this.getZIndex();this._blocker.blockContent(R-1);}}else{if(this._blocker.isContentBlocked()){this._blocker.unblockContent();}}},getParentMenu:function(){var S=this.getOpener();if(!S||!(S instanceof qx.ui.menu.AbstractButton)){return null;}while(S&&!(S instanceof qx.ui.menu.Menu)){S=S.getLayoutParent();}return S;},_applySelectedButton:function(T,U){if(U){U.removeState(g);}if(T){T.addState(g);}},_applyOpenedButton:function(V,W){if(W){W.getMenu().exclude();}if(V){V.getMenu().open();}},_applyBlockerColor:function(X,Y){this._blocker.setColor(X);},_applyBlockerOpacity:function(ba,bb){this._blocker.setOpacity(ba);},getChildrenContainer:function(){return this.getChildControl(l,true)||this;},_createChildControlImpl:function(bc,bd){var be;switch(bc){case l:var be=new qx.ui.menu.MenuSlideBar();var bg=this._getLayout();this._setLayout(new qx.ui.layout.Grow());var bf=be.getLayout();be.setLayout(bg);bf.dispose();var bh=qx.lang.Array.clone(this.getChildren());for(var i=0;i<bh.length;i++){be.add(bh[i]);}this.removeListener(j,this._onResize,this);be.getChildrenContainer().addListener(j,this._onResize,this);this._add(be);break;}return be||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,bc);},_getMenuLayout:function(){if(this.hasChildControl(l)){return this.getChildControl(l).getChildrenContainer().getLayout();}else{return this._getLayout();}},_getMenuBounds:function(){if(this.hasChildControl(l)){return this.getChildControl(l).getChildrenContainer().getBounds();}else{return this.getBounds();}},_computePlacementSize:function(){return this._getMenuBounds();},__qy:function(){var bj=this._getMenuBounds();if(!bj){this.addListenerOnce(j,this.__qy,this);return;}var bi=this.getLayoutParent().getBounds().height;var top=this.getLayoutProperties().top;var bk=this.getLayoutProperties().left;if(top<0){this._assertSlideBar(function(){this.setHeight(bj.height+top);this.moveTo(bk,0);});}else if(top+bj.height>bi){this._assertSlideBar(function(){this.setHeight(bi-top);});}else{this.setHeight(null);}},_assertSlideBar:function(bl){if(this.hasChildControl(l)){return bl.call(this);}this.__qw=bl;qx.ui.core.queue.Widget.add(this);},syncWidget:function(){this.getChildControl(l);if(this.__qw){this.__qw.call(this);delete this.__qw;}},_onResize:function(){if(this.isVisible()){var bm=this._placementTarget;if(!bm){return;}else if(bm instanceof qx.ui.core.Widget){this.placeToWidget(bm);}else if(bm.top!==undefined){this.placeToPoint(bm);}else{throw new Error("Unknown target: "+bm);}this.__qy();}},_onMouseOver:function(e){var bo=qx.ui.menu.Manager.getInstance();bo.cancelClose(this);var bp=e.getTarget();if(bp.isEnabled()&&bp instanceof qx.ui.menu.AbstractButton){this.setSelectedButton(bp);var bn=bp.getMenu&&bp.getMenu();if(bn){bn.setOpener(bp);bo.scheduleOpen(bn);this.__qv=bn;}else{var bq=this.getOpenedButton();if(bq){bo.scheduleClose(bq.getMenu());}if(this.__qv){bo.cancelOpen(this.__qv);this.__qv=null;}}}else if(!this.getOpenedButton()){this.resetSelectedButton();}},_onMouseOut:function(e){var br=qx.ui.menu.Manager.getInstance();if(!qx.ui.core.Widget.contains(this,e.getRelatedTarget())){var bs=this.getOpenedButton();bs?this.setSelectedButton(bs):this.resetSelectedButton();if(bs){br.cancelClose(bs.getMenu());}if(this.__qv){br.cancelOpen(this.__qv);}}}},destruct:function(){if(!qx.core.ObjectRegistry.inShutDown){qx.ui.menu.Manager.getInstance().remove(this);}this.getApplicationRoot().removeListener(j,this._onResize,this);this._placementTarget=null;this._disposeObjects(x);}});})();(function(){var c="Integer",b="_applyLayoutChange",a="qx.ui.menu.Layout";qx.Class.define(a,{extend:qx.ui.layout.VBox,properties:{columnSpacing:{check:c,init:0,apply:b},spanColumn:{check:c,init:1,nullable:true,apply:b},iconColumnWidth:{check:c,init:0,themeable:true,apply:b},arrowColumnWidth:{check:c,init:0,themeable:true,apply:b}},members:{__qm:null,_computeSizeHint:function(){var q=this._getLayoutChildren();var o,g,j;var e=this.getSpanColumn();var h=this.__qm=[0,0,0,0];var m=this.getColumnSpacing();var k=0;var f=0;for(var i=0,l=q.length;i<l;i++){o=q[i];if(o.isAnonymous()){continue;}g=o.getChildrenSizes();for(var n=0;n<g.length;n++){if(e!=null&&n==e&&g[e+1]==0){k=Math.max(k,g[n]);}else{h[n]=Math.max(h[n],g[n]);}}var d=q[i].getInsets();f=Math.max(f,d.left+d.right);}if(e!=null&&h[e]+m+h[e+1]<k){h[e]=k-h[e+1]-m;}if(k==0){j=m*2;}else{j=m*3;}if(h[0]==0){h[0]=this.getIconColumnWidth();}if(h[3]==0){h[3]=this.getArrowColumnWidth();}var p=qx.ui.layout.VBox.prototype._computeSizeHint.call(this).height;return {minHeight:p,height:p,width:qx.lang.Array.sum(h)+f+j};},getColumnSizes:function(){return this.__qm||null;}},destruct:function(){this.__qm=null;}});})();(function(){var l="zIndex",k="px",j="keydown",h="deactivate",g="resize",f="keyup",d="keypress",c="backgroundColor",b="_applyOpacity",a="Boolean",x="__sg",w="__se",v="opacity",u="interval",t="Tab",s="Color",r="qx.ui.root.Page",q="Number",p="qx.ui.core.Blocker",o="__sc",m="qx.ui.root.Application",n="_applyColor";qx.Class.define(p,{extend:qx.core.Object,construct:function(y){qx.core.Object.call(this);this._widget=y;this._isPageRoot=(qx.Class.isDefined(r)&&y instanceof qx.ui.root.Page);if(this._isPageRoot){y.addListener(g,this.__sh,this);}if(qx.Class.isDefined(m)&&y instanceof qx.ui.root.Application){this.setKeepBlockerActive(true);}this.__rY=[];this.__sa=[];this.__sb=[];},properties:{color:{check:s,init:null,nullable:true,apply:n,themeable:true},opacity:{check:q,init:1,apply:b,themeable:true},keepBlockerActive:{check:a,init:false}},members:{__sc:null,__sd:0,__se:null,__sb:null,__rY:null,__sa:null,__sf:null,__sg:null,_isPageRoot:false,_widget:null,__sh:function(e){var z=e.getData();if(this.isContentBlocked()){this.getContentBlockerElement().setStyles({width:z.width,height:z.height});}if(this.isBlocked()){this.getBlockerElement().setStyles({width:z.width,height:z.height});}},_applyColor:function(A,B){var C=qx.theme.manager.Color.getInstance().resolve(A);this.__si(c,C);},_applyOpacity:function(D,E){this.__si(v,D);},__si:function(F,G){var H=[];this.__sc&&H.push(this.__sc);this.__se&&H.push(this.__se);for(var i=0;i<H.length;i++){H[i].setStyle(F,G);}},_backupActiveWidget:function(){var I=qx.event.Registration.getManager(window).getHandler(qx.event.handler.Focus);this.__rY.push(I.getActive());this.__sa.push(I.getFocus());if(this._widget.isFocusable()){this._widget.focus();}},_restoreActiveWidget:function(){var L=this.__rY.length;if(L>0){var K=this.__rY[L-1];if(K){qx.bom.Element.activate(K);}this.__rY.pop();}var J=this.__sa.length;if(J>0){var K=this.__sa[J-1];if(K){qx.bom.Element.focus(this.__sa[J-1]);}this.__sa.pop();}},__sj:function(){return new qx.html.Blocker(this.getColor(),this.getOpacity());},getBlockerElement:function(){if(!this.__sc){this.__sc=this.__sj();this.__sc.setStyle(l,15);this._widget.getContainerElement().add(this.__sc);this.__sc.exclude();}return this.__sc;},block:function(){this.__sd++;if(this.__sd<2){this._backupActiveWidget();var M=this.getBlockerElement();M.include();M.activate();M.addListener(h,this.__so,this);M.addListener(d,this.__sn,this);M.addListener(j,this.__sn,this);M.addListener(f,this.__sn,this);}},isBlocked:function(){return this.__sd>0;},unblock:function(){if(!this.isBlocked()){return;}this.__sd--;if(this.__sd<1){this.__sk();this.__sd=0;}},forceUnblock:function(){if(!this.isBlocked()){return;}this.__sd=0;this.__sk();},__sk:function(){this._restoreActiveWidget();var N=this.getBlockerElement();N.removeListener(h,this.__so,this);N.removeListener(d,this.__sn,this);N.removeListener(j,this.__sn,this);N.removeListener(f,this.__sn,this);N.exclude();},getContentBlockerElement:function(){if(!this.__se){this.__se=this.__sj();this._widget.getContentElement().add(this.__se);this.__se.exclude();}return this.__se;},blockContent:function(O){var P=this.getContentBlockerElement();P.setStyle(l,O);this.__sb.push(O);if(this.__sb.length<2){P.include();if(this._isPageRoot){if(!this.__sg){this.__sg=new qx.event.Timer(300);this.__sg.addListener(u,this.__sm,this);}this.__sg.start();this.__sm();}}},isContentBlocked:function(){return this.__sb.length>0;},unblockContent:function(){if(!this.isContentBlocked()){return;}this.__sb.pop();var Q=this.__sb[this.__sb.length-1];var R=this.getContentBlockerElement();R.setStyle(l,Q);if(this.__sb.length<1){this.__sl();this.__sb=[];}},forceUnblockContent:function(){if(!this.isContentBlocked()){return;}this.__sb=[];var S=this.getContentBlockerElement();S.setStyle(l,null);this.__sl();},__sl:function(){this.getContentBlockerElement().exclude();if(this._isPageRoot){this.__sg.stop();}},__sm:function(){var T=this._widget.getContainerElement().getDomElement();var U=qx.dom.Node.getDocument(T);this.getContentBlockerElement().setStyles({height:U.documentElement.scrollHeight+k,width:U.documentElement.scrollWidth+k});},__sn:function(e){if(e.getKeyIdentifier()==t){e.stop();}},__so:function(){if(this.getKeepBlockerActive()){this.getBlockerElement().activate();}}},destruct:function(){if(this._isPageRoot){this._widget.removeListener(g,this.__sh,this);}this._disposeObjects(w,o,x);this.__sf=this.__rY=this.__sa=this._widget=this.__sb=null;}});})();(function(){var i="qx.ui.window.Window",h="changeModal",g="changeVisibility",f="changeActive",d="_applyActiveWindow",c="__og",b="__of",a="qx.ui.window.MDesktop";qx.Mixin.define(a,{properties:{activeWindow:{check:i,apply:d,init:null,nullable:true}},members:{__of:null,__og:null,getWindowManager:function(){if(!this.__og){this.setWindowManager(new qx.ui.window.Window.DEFAULT_MANAGER_CLASS());}return this.__og;},supportsMaximize:function(){return true;},setWindowManager:function(j){if(this.__og){this.__og.setDesktop(null);}j.setDesktop(this);this.__og=j;},_onChangeActive:function(e){if(e.getData()){this.setActiveWindow(e.getTarget());}else if(this.getActiveWindow()==e.getTarget()){this.setActiveWindow(null);}},_applyActiveWindow:function(k,l){this.getWindowManager().changeActiveWindow(k,l);this.getWindowManager().updateStack();},_onChangeModal:function(e){this.getWindowManager().updateStack();},_onChangeVisibility:function(){this.getWindowManager().updateStack();},_afterAddChild:function(m){if(qx.Class.isDefined(i)&&m instanceof qx.ui.window.Window){this._addWindow(m);}},_addWindow:function(n){if(!qx.lang.Array.contains(this.getWindows(),n)){this.getWindows().push(n);n.addListener(f,this._onChangeActive,this);n.addListener(h,this._onChangeModal,this);n.addListener(g,this._onChangeVisibility,this);}if(n.getActive()){this.setActiveWindow(n);}this.getWindowManager().updateStack();},_afterRemoveChild:function(o){if(qx.Class.isDefined(i)&&o instanceof qx.ui.window.Window){this._removeWindow(o);}},_removeWindow:function(p){qx.lang.Array.remove(this.getWindows(),p);p.removeListener(f,this._onChangeActive,this);p.removeListener(h,this._onChangeModal,this);p.removeListener(g,this._onChangeVisibility,this);this.getWindowManager().updateStack();},getWindows:function(){if(!this.__of){this.__of=[];}return this.__of;}},destruct:function(){this._disposeArray(b);this._disposeObjects(c);}});})();(function(){var f="_applyBlockerColor",e="Number",d="__rQ",c="qx.ui.core.MBlocker",b="_applyBlockerOpacity",a="Color";qx.Mixin.define(c,{construct:function(){this.__rQ=new qx.ui.core.Blocker(this);},properties:{blockerColor:{check:a,init:null,nullable:true,apply:f,themeable:true},blockerOpacity:{check:e,init:1,apply:b,themeable:true}},members:{__rQ:null,_applyBlockerColor:function(g,h){this.__rQ.setColor(g);},_applyBlockerOpacity:function(i,j){this.__rQ.setOpacity(i);},block:function(){this.__rQ.block();},isBlocked:function(){return this.__rQ.isBlocked();},unblock:function(){this.__rQ.unblock();},forceUnblock:function(){this.__rQ.forceUnblock();},blockContent:function(k){this.__rQ.blockContent(k);},isContentBlocked:function(){return this.__rQ.isContentBlocked();},unblockContent:function(){this.__rQ.unblockContent();},forceUnblockContent:function(){this.__rQ.forceUnblockContent();},getBlocker:function(){return this.__rQ;}},destruct:function(){this._disposeObjects(d);}});})();(function(){var p="contextmenu",o="help",n="qx.client",m="changeGlobalCursor",l="abstract",k="Boolean",j="root",i="",h=" !important",g="_applyGlobalCursor",c="_applyNativeHelp",f=";",d="qx.ui.root.Abstract",b="String",a="*";qx.Class.define(d,{type:l,extend:qx.ui.core.Widget,include:[qx.ui.core.MChildrenHandling,qx.ui.core.MBlocker,qx.ui.window.MDesktop],construct:function(){qx.ui.core.Widget.call(this);qx.ui.core.FocusHandler.getInstance().addRoot(this);qx.ui.core.queue.Visibility.add(this);this.initNativeHelp();},properties:{appearance:{refine:true,init:j},enabled:{refine:true,init:true},focusable:{refine:true,init:true},globalCursor:{check:b,nullable:true,themeable:true,apply:g,event:m},nativeContextMenu:{refine:true,init:false},nativeHelp:{check:k,init:false,apply:c}},members:{__mS:null,isRootWidget:function(){return true;},getLayout:function(){return this._getLayout();},_applyGlobalCursor:qx.core.Variant.select(n,{"mshtml":function(q,r){},"default":function(s,t){var u=qx.bom.Stylesheet;var v=this.__mS;if(!v){this.__mS=v=u.createElement();}u.removeAllRules(v);if(s){u.addRule(v,a,qx.bom.element.Cursor.compile(s).replace(f,i)+h);}}}),_applyNativeContextMenu:function(w,x){if(w){this.removeListener(p,this._onNativeContextMenu,this,true);}else{this.addListener(p,this._onNativeContextMenu,this,true);}},_onNativeContextMenu:function(e){if(e.getTarget().getNativeContextMenu()){return;}e.preventDefault();},_applyNativeHelp:qx.core.Variant.select(n,{"mshtml":function(y,z){if(z===false){qx.bom.Event.removeNativeListener(document,o,qx.lang.Function.returnFalse);}if(y===false){qx.bom.Event.addNativeListener(document,o,qx.lang.Function.returnFalse);}},"default":function(){}})},destruct:function(){this.__mS=null;},defer:function(A,B){qx.ui.core.MChildrenHandling.remap(B);}});})();(function(){var n="resize",m="position",l="0px",k="webkit",j="paddingLeft",i="$$widget",h="qx.ui.root.Application",g="hidden",f="qx.client",d="div",a="paddingTop",c="100%",b="absolute";qx.Class.define(h,{extend:qx.ui.root.Abstract,construct:function(o){this.__pj=qx.dom.Node.getWindow(o);this.__pk=o;qx.ui.root.Abstract.call(this);qx.event.Registration.addListener(this.__pj,n,this._onResize,this);this._setLayout(new qx.ui.layout.Canvas());qx.ui.core.queue.Layout.add(this);qx.ui.core.FocusHandler.getInstance().connectTo(this);this.getContentElement().disableScrolling();},members:{__pj:null,__pk:null,_createContainerElement:function(){var p=this.__pk;if(qx.core.Variant.isSet(f,k)){if(!p.body){alert("The application could not be started due to a missing body tag in the HTML file!");}}var t=p.documentElement.style;var q=p.body.style;t.overflow=q.overflow=g;t.padding=t.margin=q.padding=q.margin=l;t.width=t.height=q.width=q.height=c;var s=p.createElement(d);p.body.appendChild(s);var r=new qx.html.Root(s);r.setStyle(m,b);r.setAttribute(i,this.toHashCode());return r;},_onResize:function(e){qx.ui.core.queue.Layout.add(this);},_computeSizeHint:function(){var u=qx.bom.Viewport.getWidth(this.__pj);var v=qx.bom.Viewport.getHeight(this.__pj);return {minWidth:u,width:u,maxWidth:u,minHeight:v,height:v,maxHeight:v};},_applyPadding:function(w,x,name){if(w&&(name==a||name==j)){throw new Error("The root widget does not support 'left', or 'top' paddings!");}qx.ui.root.Abstract.prototype._applyPadding.call(this,w,x,name);},_applyDecorator:function(y,z){qx.ui.root.Abstract.prototype._applyDecorator.call(this,y,z);if(!y){return;}var A=this.getDecoratorElement().getInsets();if(A.left||A.top){throw new Error("The root widget does not support decorators with 'left', or 'top' insets!");}}},destruct:function(){this.__pj=this.__pk=null;}});})();(function(){var k="keypress",j="focusout",h="activate",g="Tab",f="singleton",d="__bE",c="deactivate",b="focusin",a="qx.ui.core.FocusHandler";qx.Class.define(a,{extend:qx.core.Object,type:f,construct:function(){qx.core.Object.call(this);this.__bE={};},members:{__bE:null,__bF:null,__bG:null,__bH:null,connectTo:function(m){m.addListener(k,this.__bI,this);m.addListener(b,this._onFocusIn,this,true);m.addListener(j,this._onFocusOut,this,true);m.addListener(h,this._onActivate,this,true);m.addListener(c,this._onDeactivate,this,true);},addRoot:function(n){this.__bE[n.$$hash]=n;},removeRoot:function(o){delete this.__bE[o.$$hash];},getActiveWidget:function(){return this.__bF;},isActive:function(p){return this.__bF==p;},getFocusedWidget:function(){return this.__bG;},isFocused:function(q){return this.__bG==q;},isFocusRoot:function(r){return !!this.__bE[r.$$hash];},_onActivate:function(e){var t=e.getTarget();this.__bF=t;var s=this.__bJ(t);if(s!=this.__bH){this.__bH=s;}},_onDeactivate:function(e){var u=e.getTarget();if(this.__bF==u){this.__bF=null;}},_onFocusIn:function(e){var v=e.getTarget();if(v!=this.__bG){this.__bG=v;v.visualizeFocus();}},_onFocusOut:function(e){var w=e.getTarget();if(w==this.__bG){this.__bG=null;w.visualizeBlur();}},__bI:function(e){if(e.getKeyIdentifier()!=g){return;}if(!this.__bH){return;}e.stopPropagation();e.preventDefault();var x=this.__bG;if(!e.isShiftPressed()){var y=x?this.__bN(x):this.__bL();}else{var y=x?this.__bO(x):this.__bM();}if(y){y.tabFocus();}},__bJ:function(z){var A=this.__bE;while(z){if(A[z.$$hash]){return z;}z=z.getLayoutParent();}return null;},__bK:function(B,C){if(B===C){return 0;}var E=B.getTabIndex()||0;var D=C.getTabIndex()||0;if(E!=D){return E-D;}var J=B.getContainerElement().getDomElement();var I=C.getContainerElement().getDomElement();var H=qx.bom.element.Location;var G=H.get(J);var F=H.get(I);if(G.top!=F.top){return G.top-F.top;}if(G.left!=F.left){return G.left-F.left;}var K=B.getZIndex();var L=C.getZIndex();if(K!=L){return K-L;}return 0;},__bL:function(){return this.__bR(this.__bH,null);},__bM:function(){return this.__bS(this.__bH,null);},__bN:function(M){var N=this.__bH;if(N==M){return this.__bL();}while(M&&M.getAnonymous()){M=M.getLayoutParent();}if(M==null){return [];}var O=[];this.__bP(N,M,O);O.sort(this.__bK);var P=O.length;return P>0?O[0]:this.__bL();},__bO:function(Q){var R=this.__bH;if(R==Q){return this.__bM();}while(Q&&Q.getAnonymous()){Q=Q.getLayoutParent();}if(Q==null){return [];}var S=[];this.__bQ(R,Q,S);S.sort(this.__bK);var T=S.length;return T>0?S[T-1]:this.__bM();},__bP:function(parent,U,V){var W=parent.getLayoutChildren();var X;for(var i=0,l=W.length;i<l;i++){X=W[i];if(!(X instanceof qx.ui.core.Widget)){continue;}if(!this.isFocusRoot(X)&&X.isEnabled()&&X.isVisible()){if(X.isTabable()&&this.__bK(U,X)<0){V.push(X);}this.__bP(X,U,V);}}},__bQ:function(parent,Y,ba){var bb=parent.getLayoutChildren();var bc;for(var i=0,l=bb.length;i<l;i++){bc=bb[i];if(!(bc instanceof qx.ui.core.Widget)){continue;}if(!this.isFocusRoot(bc)&&bc.isEnabled()&&bc.isVisible()){if(bc.isTabable()&&this.__bK(Y,bc)>0){ba.push(bc);}this.__bQ(bc,Y,ba);}}},__bR:function(parent,bd){var be=parent.getLayoutChildren();var bf;for(var i=0,l=be.length;i<l;i++){bf=be[i];if(!(bf instanceof qx.ui.core.Widget)){continue;}if(!this.isFocusRoot(bf)&&bf.isEnabled()&&bf.isVisible()){if(bf.isTabable()){if(bd==null||this.__bK(bf,bd)<0){bd=bf;}}bd=this.__bR(bf,bd);}}return bd;},__bS:function(parent,bg){var bh=parent.getLayoutChildren();var bi;for(var i=0,l=bh.length;i<l;i++){bi=bh[i];if(!(bi instanceof qx.ui.core.Widget)){continue;}if(!this.isFocusRoot(bi)&&bi.isEnabled()&&bi.isVisible()){if(bi.isTabable()){if(bg==null||this.__bK(bi,bg)>0){bg=bi;}}bg=this.__bS(bi,bg);}}return bg;}},destruct:function(){this._disposeMap(d);this.__bG=this.__bF=this.__bH=null;}});})();(function(){var a="qx.html.Root";qx.Class.define(a,{extend:qx.html.Element,construct:function(b){qx.html.Element.call(this);if(b!=null){this.useElement(b);}},members:{useElement:function(c){qx.html.Element.prototype.useElement.call(this,c);this.setRoot(true);qx.html.Element._modified[this.$$hash]=this;}}});})();(function(){var k="cursor",j="100%",i="repeat",h="mousedown",g="url(",f=")",d="mouseout",c="qx.client",b="div",a="dblclick",w="mousewheel",v="qx.html.Blocker",u="mousemove",t="mouseover",s="appear",r="click",q="mshtml",p="mouseup",o="contextmenu",n="disappear",l="qx/static/blank.gif",m="absolute";qx.Class.define(v,{extend:qx.html.Element,construct:function(x,y){var x=x?qx.theme.manager.Color.getInstance().resolve(x):null;var z={position:m,width:j,height:j,opacity:y||0,backgroundColor:x};if(qx.core.Variant.isSet(c,q)){z.backgroundImage=g+qx.util.ResourceManager.getInstance().toUri(l)+f;z.backgroundRepeat=i;}qx.html.Element.call(this,b,z);this.addListener(h,this._stopPropagation,this);this.addListener(p,this._stopPropagation,this);this.addListener(r,this._stopPropagation,this);this.addListener(a,this._stopPropagation,this);this.addListener(u,this._stopPropagation,this);this.addListener(t,this._stopPropagation,this);this.addListener(d,this._stopPropagation,this);this.addListener(w,this._stopPropagation,this);this.addListener(o,this._stopPropagation,this);this.addListener(s,this.__qp,this);this.addListener(n,this.__qp,this);},members:{_stopPropagation:function(e){e.stopPropagation();},__qp:function(){var A=this.getStyle(k);this.setStyle(k,null,true);this.setStyle(k,A,true);}}});})();(function(){var b="menu-separator",a="qx.ui.menu.Separator";qx.Class.define(a,{extend:qx.ui.core.Widget,properties:{appearance:{refine:true,init:b},anonymous:{refine:true,init:true}}});})();(function(){var t="icon",s="label",r="arrow",q="shortcut",p="changeLocale",o="qx.dynlocale",n="submenu",m="on",l="String",k="qx.ui.menu.Menu",d="qx.ui.menu.AbstractButton",j="keypress",h="",c="_applyIcon",b="mouseup",g="abstract",f="_applyLabel",i="_applyMenu",a="changeCommand";qx.Class.define(d,{extend:qx.ui.core.Widget,include:[qx.ui.core.MExecutable],implement:[qx.ui.form.IExecutable],type:g,construct:function(){qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.menu.ButtonLayout);this.addListener(b,this._onMouseUp);this.addListener(j,this._onKeyPress);this.addListener(a,this._onChangeCommand,this);},properties:{blockToolTip:{refine:true,init:true},label:{check:l,apply:f,nullable:true},menu:{check:k,apply:i,nullable:true,dereference:true},icon:{check:l,apply:c,themeable:true,nullable:true}},members:{_createChildControlImpl:function(u,v){var w;switch(u){case t:w=new qx.ui.basic.Image;w.setAnonymous(true);this._add(w,{column:0});break;case s:w=new qx.ui.basic.Label;w.setAnonymous(true);this._add(w,{column:1});break;case q:w=new qx.ui.basic.Label;w.setAnonymous(true);this._add(w,{column:2});break;case r:w=new qx.ui.basic.Image;w.setAnonymous(true);this._add(w,{column:3});break;}return w||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,u);},_forwardStates:{selected:1},getChildrenSizes:function(){var x=0,y=0,z=0,D=0;if(this._isChildControlVisible(t)){var E=this.getChildControl(t);x=E.getMarginLeft()+E.getSizeHint().width+E.getMarginRight();}if(this._isChildControlVisible(s)){var B=this.getChildControl(s);y=B.getMarginLeft()+B.getSizeHint().width+B.getMarginRight();}if(this._isChildControlVisible(q)){var A=this.getChildControl(q);z=A.getMarginLeft()+A.getSizeHint().width+A.getMarginRight();}if(this._isChildControlVisible(r)){var C=this.getChildControl(r);D=C.getMarginLeft()+C.getSizeHint().width+C.getMarginRight();}return [x,y,z,D];},_onMouseUp:function(e){},_onKeyPress:function(e){},_onChangeCommand:function(e){var H=e.getData();if(qx.core.Variant.isSet(o,m)){var F=e.getOldData();if(!F){qx.locale.Manager.getInstance().addListener(p,this._onChangeLocale,this);}if(!H){qx.locale.Manager.getInstance().removeListener(p,this._onChangeLocale,this);}}var G=H!=null?H.toString():h;this.getChildControl(q).setValue(G);},_onChangeLocale:qx.core.Variant.select(o,{"on":function(e){var I=this.getCommand();if(I!=null){this.getChildControl(q).setValue(I.toString());}},"off":null}),_applyIcon:function(J,K){if(J){this._showChildControl(t).setSource(J);}else{this._excludeChildControl(t);}},_applyLabel:function(L,M){if(L){this._showChildControl(s).setValue(L);}else{this._excludeChildControl(s);}},_applyMenu:function(N,O){if(O){O.resetOpener();O.removeState(n);}if(N){this._showChildControl(r);N.setOpener(this);N.addState(n);}else{this._excludeChildControl(r);}}},destruct:function(){if(this.getMenu()){if(!qx.core.ObjectRegistry.inShutDown){this.getMenu().destroy();}}if(qx.core.Variant.isSet(o,m)){qx.locale.Manager.getInstance().removeListener(p,this._onChangeLocale,this);}}});})();(function(){var c="middle",b="qx.ui.menu.ButtonLayout",a="left";qx.Class.define(b,{extend:qx.ui.layout.Abstract,members:{verifyLayoutProperty:null,renderLayout:function(d,e){var q=this._getLayoutChildren();var p;var g;var h=[];for(var i=0,l=q.length;i<l;i++){p=q[i];g=p.getLayoutProperties().column;h[g]=p;}var o=this.__ob(q[0]);var r=o.getColumnSizes();var k=o.getSpacingX();var j=qx.lang.Array.sum(r)+k*(r.length-1);if(j<d){r[1]+=d-j;}var s=0,top=0;var m=qx.ui.layout.Util;for(var i=0,l=r.length;i<l;i++){p=h[i];if(p){var f=p.getSizeHint();var top=m.computeVerticalAlignOffset(p.getAlignY()||c,f.height,e,0,0);var n=m.computeHorizontalAlignOffset(p.getAlignX()||a,f.width,r[i],p.getMarginLeft(),p.getMarginRight());p.renderLayout(s+n,top,f.width,f.height);}s+=r[i]+k;}},__ob:function(t){while(!(t instanceof qx.ui.menu.Menu)){t=t.getLayoutParent();}return t;},_computeSizeHint:function(){var w=this._getLayoutChildren();var v=0;var x=0;for(var i=0,l=w.length;i<l;i++){var u=w[i].getSizeHint();x+=u.width;v=Math.max(v,u.height);}return {width:x,height:v};}}});})();(function(){var a="qx.ui.core.MRemoteLayoutHandling";qx.Mixin.define(a,{members:{setLayout:function(b){return this.getChildrenContainer().setLayout(b);},getLayout:function(){return this.getChildrenContainer().getLayout();}}});})();(function(){var q="horizontal",p="scrollpane",o="vertical",n="button-backward",m="button-forward",l="content",k="execute",j="qx.ui.container.SlideBar",i="scrollY",h="removeChildWidget",c="scrollX",g="_applyOrientation",f="mousewheel",b="Integer",a="slidebar",d="update";qx.Class.define(j,{extend:qx.ui.core.Widget,include:[qx.ui.core.MRemoteChildrenHandling,qx.ui.core.MRemoteLayoutHandling],construct:function(r){qx.ui.core.Widget.call(this);var s=this.getChildControl(p);this._add(s,{flex:1});if(r!=null){this.setOrientation(r);}else{this.initOrientation();}this.addListener(f,this._onMouseWheel,this);},properties:{appearance:{refine:true,init:a},orientation:{check:[q,o],init:q,apply:g},scrollStep:{check:b,init:15,themeable:true}},members:{getChildrenContainer:function(){return this.getChildControl(l);},_createChildControlImpl:function(t,u){var v;switch(t){case m:v=new qx.ui.form.RepeatButton;v.addListener(k,this._onExecuteForward,this);v.setFocusable(false);this._addAt(v,2);break;case n:v=new qx.ui.form.RepeatButton;v.addListener(k,this._onExecuteBackward,this);v.setFocusable(false);this._addAt(v,0);break;case l:v=new qx.ui.container.Composite();if(qx.bom.client.Engine.GECKO){v.addListener(h,this._onRemoveChild,this);}this.getChildControl(p).add(v);break;case p:v=new qx.ui.core.scroll.ScrollPane();v.addListener(d,this._onResize,this);v.addListener(c,this._onScroll,this);v.addListener(i,this._onScroll,this);break;}return v||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,t);},_forwardStates:{barLeft:true,barTop:true,barRight:true,barBottom:true},scrollBy:function(w){var x=this.getChildControl(p);if(this.getOrientation()===q){x.scrollByX(w);}else{x.scrollByY(w);}},scrollTo:function(y){var z=this.getChildControl(p);if(this.getOrientation()===q){z.scrollToX(y);}else{z.scrollToY(y);}},_applyOrientation:function(A,B){var E=[this.getLayout(),this._getLayout()];var D=this.getChildControl(m);var C=this.getChildControl(n);if(B==o){D.removeState(o);C.removeState(o);D.addState(q);C.addState(q);}else if(B==q){D.removeState(q);C.removeState(q);D.addState(o);C.addState(o);}if(A==q){this._setLayout(new qx.ui.layout.HBox());this.setLayout(new qx.ui.layout.HBox());}else{this._setLayout(new qx.ui.layout.VBox());this.setLayout(new qx.ui.layout.VBox());}if(E[0]){E[0].dispose();}if(E[1]){E[1].dispose();}},_onMouseWheel:function(e){this.scrollBy(e.getWheelDelta()*this.getScrollStep());e.stop();},_onScroll:function(){this._updateArrowsEnabled();},_onResize:function(e){var content=this.getChildControl(p).getChildren()[0];if(!content){return;}var F=this.getInnerSize();var H=content.getBounds();var G=(this.getOrientation()===q)?H.width>F.width:H.height>F.height;if(G){this._showArrows();this._updateArrowsEnabled();}else{this._hideArrows();}},_onExecuteBackward:function(){this.scrollBy(-this.getScrollStep());},_onExecuteForward:function(){this.scrollBy(this.getScrollStep());},_onRemoveChild:function(){qx.event.Timer.once(function(){this.scrollBy(this.getChildControl(p).getScrollX());},this,50);},_updateArrowsEnabled:function(){var J=this.getChildControl(p);if(this.getOrientation()===q){var I=J.getScrollX();var K=J.getScrollMaxX();}else{var I=J.getScrollY();var K=J.getScrollMaxY();}this.getChildControl(n).setEnabled(I>0);this.getChildControl(m).setEnabled(I<K);},_showArrows:function(){this._showChildControl(m);this._showChildControl(n);},_hideArrows:function(){this._excludeChildControl(m);this._excludeChildControl(n);this.scrollTo(0);}}});})();(function(){var f="execute",e="button-backward",d="vertical",c="button-forward",b="menu-slidebar",a="qx.ui.menu.MenuSlideBar";qx.Class.define(a,{extend:qx.ui.container.SlideBar,construct:function(){qx.ui.container.SlideBar.call(this,d);},properties:{appearance:{refine:true,init:b}},members:{_createChildControlImpl:function(g,h){var i;switch(g){case c:i=new qx.ui.form.HoverButton();i.addListener(f,this._onExecuteForward,this);this._addAt(i,2);break;case e:i=new qx.ui.form.HoverButton();i.addListener(f,this._onExecuteBackward,this);this._addAt(i,0);break;}return i||qx.ui.container.SlideBar.prototype._createChildControlImpl.call(this,g);}}});})();(function(){var i="Integer",h="hovered",g="hover-button",f="interval",d="mouseover",c="mouseout",b="__nk",a="qx.ui.form.HoverButton";qx.Class.define(a,{extend:qx.ui.basic.Atom,include:[qx.ui.core.MExecutable],implement:[qx.ui.form.IExecutable],construct:function(j,k){qx.ui.basic.Atom.call(this,j,k);this.addListener(d,this._onMouseOver,this);this.addListener(c,this._onMouseOut,this);this.__nk=new qx.event.AcceleratingTimer();this.__nk.addListener(f,this._onInterval,this);},properties:{appearance:{refine:true,init:g},interval:{check:i,init:80},firstInterval:{check:i,init:200},minTimer:{check:i,init:20},timerDecrease:{check:i,init:2}},members:{__nk:null,_onMouseOver:function(e){if(!this.isEnabled()||e.getTarget()!==this){return;}this.__nk.set({interval:this.getInterval(),firstInterval:this.getFirstInterval(),minimum:this.getMinTimer(),decrease:this.getTimerDecrease()}).start();this.addState(h);},_onMouseOut:function(e){this.__nk.stop();this.removeState(h);if(!this.isEnabled()||e.getTarget()!==this){return;}},_onInterval:function(){if(this.isEnabled()){this.execute();}else{this.__nk.stop();}}},destruct:function(){this._disposeObjects(b);}});})();(function(){var h="pressed",g="hovered",f="inherit",d="qx.ui.menubar.Button",c="keydown",b="menubar-button",a="keyup";qx.Class.define(d,{extend:qx.ui.form.MenuButton,construct:function(i,j,k){qx.ui.form.MenuButton.call(this,i,j,k);this.removeListener(c,this._onKeyDown);this.removeListener(a,this._onKeyUp);},properties:{appearance:{refine:true,init:b},show:{refine:true,init:f},focusable:{refine:true,init:false}},members:{getMenuBar:function(){var parent=this;while(parent){if(parent instanceof qx.ui.toolbar.ToolBar){return parent;}parent=parent.getLayoutParent();}return null;},open:function(l){qx.ui.form.MenuButton.prototype.open.call(this,l);var menubar=this.getMenuBar();menubar._setAllowMenuOpenHover(true);},_onMenuChange:function(e){var m=this.getMenu();var menubar=this.getMenuBar();if(m.isVisible()){this.addState(h);if(menubar){menubar.setOpenMenu(m);}}else{this.removeState(h);if(menubar&&menubar.getOpenMenu()==m){menubar.resetOpenMenu();menubar._setAllowMenuOpenHover(false);}}},_onMouseUp:function(e){qx.ui.form.MenuButton.prototype._onMouseUp.call(this,e);var n=this.getMenu();if(n&&n.isVisible()&&!this.hasState(h)){this.addState(h);}},_onMouseOver:function(e){this.addState(g);if(this.getMenu()){var menubar=this.getMenuBar();if(menubar._isAllowMenuOpenHover()){qx.ui.menu.Manager.getInstance().hideAll();menubar._setAllowMenuOpenHover(true);if(this.isEnabled()){this.open();}}}}}});})();(function(){var w="visible",v="excluded",u="resize",t="qx.event.type.Data",s="both",r="qx.ui.menu.Menu",q="_applySpacing",p="showItem",o="Boolean",n="icon",d="label",m="qx.ui.core.Widget",h="_applyOverflowIndicator",c="_applyOverflowHandling",b="changeShow",g="Integer",f="qx.ui.toolbar.ToolBar",j="hideItem",a="toolbar",k="changeOpenMenu";qx.Class.define(f,{extend:qx.ui.core.Widget,include:qx.ui.core.MChildrenHandling,construct:function(){qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.layout.HBox());this.__rp=[];this.__rq=[];},properties:{appearance:{refine:true,init:a},openMenu:{check:r,event:k,nullable:true},show:{init:s,check:[s,d,n],inheritable:true,event:b},spacing:{nullable:true,check:g,themeable:true,apply:q},overflowIndicator:{check:m,nullable:true,apply:h},overflowHandling:{init:false,check:o,apply:c}},events:{"hideItem":t,"showItem":t},members:{__rp:null,__rq:null,_computeSizeHint:function(){var z=qx.ui.core.Widget.prototype._computeSizeHint.call(this);if(true&&this.getOverflowHandling()){var x=0;var y=this.getOverflowIndicator();if(y){x=y.getSizeHint().width+this.getSpacing();}z.minWidth=x;}return z;},_onResize:function(e){this._recalculateOverflow(e.getData().width);},_recalculateOverflow:function(A){if(!this.getOverflowHandling()){return;}var C=this.getSizeHint().width;var B=this.getOverflowIndicator();var F=0;if(B){F=B.getSizeHint().width;}if(A<C){do{var G=this._getNextToHide();if(!G){return;}var H=G.getMarginLeft()+G.getMarginRight();var E=G.getSizeHint().width+H;this.__rs(G);C-=E;if(B&&B.getVisibility()!=w){B.setVisibility(w);C+=F;}}while(C>A);}else{do{var I=this.__rp[0];if(I){var H=I.getMarginLeft()+I.getMarginRight();var D=I.getSizeHint().width+H;if(A>C+D+this.getSpacing()||(this.__rp.length==1&&A>C+D-F+this.getSpacing())){this.__rr(I);A+=D;if(B&&this.__rp.length==0){B.setVisibility(v);}}else{return;}}}while(A>=C&&this.__rp.length>0);}},__rr:function(J){J.setVisibility(w);this.__rp.shift();this.fireDataEvent(p,J);},__rs:function(K){if(!K){return;}this.__rp.unshift(K);K.setVisibility(v);this.fireDataEvent(j,K);},_getNextToHide:function(){for(var i=this.__rq.length-1;i>=0;i--){var L=this.__rq[i];if(L&&L.getVisibility&&L.getVisibility()==w){return L;}}var M=this._getChildren();for(var i=M.length-1;i>=0;i--){var N=M[i];if(N==this.getOverflowIndicator()){continue;}if(N.getVisibility&&N.getVisibility()==w){return N;}}},setRemovePriority:function(O,P,Q){if(!Q&&this.__rq[P]!=undefined){throw new Error("Priority already in use!");}this.__rq[P]=O;},_applyOverflowHandling:function(R,S){this.invalidateLayoutCache();var parent=this.getLayoutParent();if(parent){parent.invalidateLayoutCache();}var U=this.getBounds();if(U&&U.width){this._recalculateOverflow(U.width);}if(R){this.addListener(u,this._onResize,this);}else{this.removeListener(u,this._onResize,this);var T=this.getOverflowIndicator();if(T){T.setVisibility(v);}for(var i=0;i<this.__rp.length;i++){this.__rp[i].setVisibility(w);}this.__rp=[];}},_applyOverflowIndicator:function(V,W){if(W){this._remove(W);}if(V){if(this._indexOf(V)==-1){throw new Error("Widget must be child of the toolbar.");}V.setVisibility(v);}},__rt:false,_setAllowMenuOpenHover:function(X){this.__rt=X;},_isAllowMenuOpenHover:function(){return this.__rt;},_applySpacing:function(Y,ba){var bb=this._getLayout();Y==null?bb.resetSpacing():bb.setSpacing(Y);},addSpacer:function(){var bc=new qx.ui.core.Spacer;this._add(bc,{flex:1});return bc;},addSeparator:function(){this.add(new qx.ui.toolbar.Separator);},getMenuButtons:function(){var be=this.getChildren();var bd=[];var bf;for(var i=0,l=be.length;i<l;i++){bf=be[i];if(bf instanceof qx.ui.menubar.Button){bd.push(bf);}else if(bf instanceof qx.ui.toolbar.Part){bd.push.apply(bd,bf.getMenuButtons());}}return bd;}},destruct:function(){if(this.hasListener(u)){this.removeListener(u,this._onResize,this);}}});})();(function(){var b="toolbar-separator",a="qx.ui.toolbar.Separator";qx.Class.define(a,{extend:qx.ui.core.Widget,properties:{appearance:{refine:true,init:b},anonymous:{refine:true,init:true},width:{refine:true,init:0},height:{refine:true,init:0}}});})();(function(){var m="container",k="handle",j="both",h="Integer",g="middle",f="qx.ui.toolbar.Part",e="icon",d="label",c="changeShow",b="_applySpacing",a="toolbar/part";qx.Class.define(f,{extend:qx.ui.core.Widget,include:[qx.ui.core.MRemoteChildrenHandling],construct:function(){qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.layout.HBox);this._createChildControl(k);},properties:{appearance:{refine:true,init:a},show:{init:j,check:[j,d,e],inheritable:true,event:c},spacing:{nullable:true,check:h,themeable:true,apply:b}},members:{_createChildControlImpl:function(n,o){var p;switch(n){case k:p=new qx.ui.basic.Image();p.setAlignY(g);this._add(p);break;case m:p=new qx.ui.toolbar.PartContainer;this._add(p);break;}return p||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,n);},getChildrenContainer:function(){return this.getChildControl(m);},_applySpacing:function(q,r){var s=this.getChildControl(m).getLayout();q==null?s.resetSpacing():s.setSpacing(q);},addSeparator:function(){this.add(new qx.ui.toolbar.Separator);},getMenuButtons:function(){var u=this.getChildren();var t=[];var v;for(var i=0,l=u.length;i<l;i++){v=u[i];if(v instanceof qx.ui.menubar.Button){t.push(v);}}return t;}}});})();(function(){var f="both",e="toolbar/part/container",d="icon",c="changeShow",b="qx.ui.toolbar.PartContainer",a="label";qx.Class.define(b,{extend:qx.ui.container.Composite,construct:function(){qx.ui.container.Composite.call(this);this._setLayout(new qx.ui.layout.HBox);},properties:{appearance:{refine:true,init:e},show:{init:f,check:[f,a,d],inheritable:true,event:c}}});})();(function(){var b="qx.ui.menu.Button",a="menu-button";qx.Class.define(b,{extend:qx.ui.menu.AbstractButton,construct:function(c,d,f,g){qx.ui.menu.AbstractButton.call(this);if(c!=null){this.setLabel(c);}if(d!=null){this.setIcon(d);}if(f!=null){this.setCommand(f);}if(g!=null){this.setMenu(g);}},properties:{appearance:{refine:true,init:a}},members:{_onMouseUp:function(e){if(e.isLeftPressed()){this.execute();if(this.getMenu()){return;}}qx.ui.menu.Manager.getInstance().hideAll();},_onKeyPress:function(e){this.execute();}}});})();(function(){var b="qx.ui.table.IColumnMenuItem",a="qx.event.type.Data";qx.Interface.define(b,{properties:{visible:{}},events:{changeVisible:a}});})();(function(){var h="checked",g="menu-checkbox",f="Boolean",d="_applyValue",c="changeValue",b="qx.ui.menu.CheckBox",a="execute";qx.Class.define(b,{extend:qx.ui.menu.AbstractButton,implement:[qx.ui.form.IBooleanForm],construct:function(i,j){qx.ui.menu.AbstractButton.call(this);if(i!=null){if(i.translate){this.setLabel(i.translate());}else{this.setLabel(i);}}if(j!=null){this.setMenu(j);}this.addListener(a,this._onExecute,this);},properties:{appearance:{refine:true,init:g},value:{check:f,init:false,apply:d,event:c,nullable:true}},members:{_applyValue:function(k,l){k?this.addState(h):this.removeState(h);},_onExecute:function(e){this.toggleValue();},_onMouseUp:function(e){if(e.isLeftPressed()){this.execute();}qx.ui.menu.Manager.getInstance().hideAll();},_onKeyPress:function(e){this.execute();}}});})();(function(){var f="changeVisible",d="qx.ui.table.columnmenu.MenuItem",c="_applyVisible",b="Boolean",a="changeValue";qx.Class.define(d,{extend:qx.ui.menu.CheckBox,implement:qx.ui.table.IColumnMenuItem,properties:{visible:{check:b,init:true,apply:c,event:f}},construct:function(g){qx.ui.menu.CheckBox.call(this,g);this.addListener(a,function(e){this.bInListener=true;this.setVisible(e.getData());this.bInListener=false;});},members:{__wn:false,_applyVisible:function(h,i){if(!this.bInListener){this.setValue(h);}}}});})();(function(){var b="qx.ui.table.selection.Model",a="qx.ui.table.selection.Manager";qx.Class.define(a,{extend:qx.core.Object,construct:function(){qx.core.Object.call(this);},properties:{selectionModel:{check:b}},members:{__wo:null,handleMouseDown:function(c,d){if(d.isLeftPressed()){var e=this.getSelectionModel();if(!e.isSelectedIndex(c)){this._handleSelectEvent(c,d);this.__wo=true;}else{this.__wo=false;}}else if(d.isRightPressed()&&d.getModifiers()==0){var e=this.getSelectionModel();if(!e.isSelectedIndex(c)){e.setSelectionInterval(c,c);}}},handleMouseUp:function(f,g){if(g.isLeftPressed()&&!this.__wo){this._handleSelectEvent(f,g);}},handleClick:function(h,i){},handleSelectKeyDown:function(j,k){this._handleSelectEvent(j,k);},handleMoveKeyDown:function(l,m){var o=this.getSelectionModel();switch(m.getModifiers()){case 0:o.setSelectionInterval(l,l);break;case qx.event.type.Dom.SHIFT_MASK:var n=o.getAnchorSelectionIndex();if(n==-1){o.setSelectionInterval(l,l);}else{o.setSelectionInterval(n,l);}break;}},_handleSelectEvent:function(p,q){var t=this.getSelectionModel();var r=t.getLeadSelectionIndex();var s=t.getAnchorSelectionIndex();if(q.isShiftPressed()){if(p!=r||t.isSelectionEmpty()){if(s==-1){s=p;}if(q.isCtrlOrCommandPressed()){t.addSelectionInterval(s,p);}else{t.setSelectionInterval(s,p);}}}else if(q.isCtrlOrCommandPressed()){if(t.isSelectedIndex(p)){t.removeSelectionInterval(p,p);}else{t.addSelectionInterval(p,p);}}else{t.setSelectionInterval(p,p);}}}});})();(function(){var l="]",k="..",h="changeSelection",g="_applySelectionMode",f='ie',d="qx.event.type.Event",c="Ranges:",b="qx.ui.table.selection.Model",a=" [";qx.Class.define(b,{extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__we=[];this.__wf=-1;this.__wg=-1;this.hasBatchModeRefCount=0;this.__wh=false;},events:{"changeSelection":d},statics:{NO_SELECTION:1,SINGLE_SELECTION:2,SINGLE_INTERVAL_SELECTION:3,MULTIPLE_INTERVAL_SELECTION:4,MULTIPLE_INTERVAL_SELECTION_TOGGLE:5},properties:{selectionMode:{init:2,check:[1,2,3,4,5],apply:g}},members:{__wh:null,__wf:null,__wg:null,__we:null,_applySelectionMode:function(m){this.resetSelection();},setBatchMode:function(n){if(n){this.hasBatchModeRefCount+=1;}else{if(this.hasBatchModeRefCount==0){throw new Error("Try to turn off batch mode althoug it was not turned on.");}this.hasBatchModeRefCount-=1;if(this.__wh){this.__wh=false;this._fireChangeSelection();}}return this.hasBatchMode();},hasBatchMode:function(){return this.hasBatchModeRefCount>0;},getAnchorSelectionIndex:function(){return this.__wf;},_setAnchorSelectionIndex:function(o){this.__wf=o;},getLeadSelectionIndex:function(){return this.__wg;},_setLeadSelectionIndex:function(p){this.__wg=p;},_getSelectedRangeArr:function(){return this.__we;},resetSelection:function(){if(!this.isSelectionEmpty()){this._resetSelection();this._fireChangeSelection();}},isSelectionEmpty:function(){return this.__we.length==0;},getSelectedCount:function(){var r=0;for(var i=0;i<this.__we.length;i++){var q=this.__we[i];r+=q.maxIndex-q.minIndex+1;}return r;},isSelectedIndex:function(s){for(var i=0;i<this.__we.length;i++){var t=this.__we[i];if(s>=t.minIndex&&s<=t.maxIndex){return true;}}return false;},getSelectedRanges:function(){var u=[];for(var i=0;i<this.__we.length;i++){u.push({minIndex:this.__we[i].minIndex,maxIndex:this.__we[i].maxIndex});}return u;},iterateSelection:function(v,w){for(var i=0;i<this.__we.length;i++){for(var j=this.__we[i].minIndex;j<=this.__we[i].maxIndex;j++){v.call(w,j);}}},setSelectionInterval:function(x,y){var z=this.self(arguments);switch(this.getSelectionMode()){case z.NO_SELECTION:return;case z.SINGLE_SELECTION:if(this.isSelectedIndex(y)){return;}x=y;break;case z.MULTIPLE_INTERVAL_SELECTION_TOGGLE:this.setBatchMode(true);try{for(var i=x;i<=y;i++){if(!this.isSelectedIndex(i)){this._addSelectionInterval(i,i);}else{this.removeSelectionInterval(i,i);}}}catch(e){if(qx.bom.client.Browser.NAME==f&&qx.bom.client.Browser.VERSION<=7){this.setBatchMode(false);}throw e;}finally{this.setBatchMode(false);}this._fireChangeSelection();return;}this._resetSelection();this._addSelectionInterval(x,y);this._fireChangeSelection();},addSelectionInterval:function(A,B){var C=qx.ui.table.selection.Model;switch(this.getSelectionMode()){case C.NO_SELECTION:return;case C.MULTIPLE_INTERVAL_SELECTION:case C.MULTIPLE_INTERVAL_SELECTION_TOGGLE:this._addSelectionInterval(A,B);this._fireChangeSelection();break;default:this.setSelectionInterval(A,B);break;}},removeSelectionInterval:function(D,E){this.__wf=D;this.__wg=E;var F=Math.min(D,E);var H=Math.max(D,E);for(var i=0;i<this.__we.length;i++){var J=this.__we[i];if(J.minIndex>H){break;}else if(J.maxIndex>=F){var K=(J.minIndex>=F)&&(J.minIndex<=H);var I=(J.maxIndex>=F)&&(J.maxIndex<=H);if(K&&I){this.__we.splice(i,1);i--;}else if(K){J.minIndex=H+1;}else if(I){J.maxIndex=F-1;}else{var G={minIndex:H+1,maxIndex:J.maxIndex};this.__we.splice(i+1,0,G);J.maxIndex=F-1;break;}}}this._fireChangeSelection();},_resetSelection:function(){this.__we=[];this.__wf=-1;this.__wg=-1;},_addSelectionInterval:function(L,M){this.__wf=L;this.__wg=M;var N=Math.min(L,M);var P=Math.max(L,M);var O=0;for(;O<this.__we.length;O++){var Q=this.__we[O];if(Q.minIndex>N){break;}}this.__we.splice(O,0,{minIndex:N,maxIndex:P});var R=this.__we[0];for(var i=1;i<this.__we.length;i++){var Q=this.__we[i];if(R.maxIndex+1>=Q.minIndex){R.maxIndex=Math.max(R.maxIndex,Q.maxIndex);this.__we.splice(i,1);i--;}else{R=Q;}}},_dumpRanges:function(){var S=c;for(var i=0;i<this.__we.length;i++){var T=this.__we[i];S+=a+T.minIndex+k+T.maxIndex+l;}this.debug(S);},_fireChangeSelection:function(){if(this.hasBatchMode()){this.__wh=true;}else{this.fireEvent(h);}}},destruct:function(){this.__we=null;}});})();(function(){var k="",j="Number",h='</div>',g='" ',f="paneUpdated",e='<div>',d="</div>",c="overflow: hidden;",b="qx.event.type.Data",a="paneReloadsData",E="div",D='style="',C="_applyMaxCacheLines",B="qx.ui.table.pane.Pane",A="width: 100%;",z="qx.event.type.Event",w="_applyVisibleRowCount",v='>',u="line-height: ",t="appear",r='class="',s="width:100%;",p="px;",q='<div ',n="'>",o="_applyFirstVisibleRow",l="<div style='",m=";position:relative;";qx.Class.define(B,{extend:qx.ui.core.Widget,construct:function(F){qx.ui.core.Widget.call(this);this.__wL=F;this.__wM=0;this.__wN=0;this.__wO=[];},events:{"paneReloadsData":b,"paneUpdated":z},properties:{firstVisibleRow:{check:j,init:0,apply:o},visibleRowCount:{check:j,init:0,apply:w},maxCacheLines:{check:j,init:1000,apply:C},allowShrinkX:{refine:true,init:false}},members:{__wN:null,__wM:null,__wL:null,__wP:null,__wQ:null,__wR:null,__wO:null,__wS:0,_applyFirstVisibleRow:function(G,H){this.updateContent(false,G-H);},_applyVisibleRowCount:function(I,J){this.updateContent(true);},_getContentHint:function(){return {width:this.getPaneScroller().getTablePaneModel().getTotalWidth(),height:400};},getPaneScroller:function(){return this.__wL;},getTable:function(){return this.__wL.getTable();},setFocusedCell:function(K,L,M){if(K!=this.__wR||L!=this.__wQ){var N=this.__wQ;this.__wR=K;this.__wQ=L;if(L!=N&&!M){if(N!==null){this.updateContent(false,null,N,true);}if(L!==null){this.updateContent(false,null,L,true);}}}},onSelectionChanged:function(){this.updateContent(false,null,null,true);},onFocusChanged:function(){this.updateContent(false,null,null,true);},setColumnWidth:function(O,P){this.updateContent(true);},onColOrderChanged:function(){this.updateContent(true);},onPaneModelChanged:function(){this.updateContent(true);},onTableModelDataChanged:function(Q,R,S,T){this.__wT();var V=this.getFirstVisibleRow();var U=this.getVisibleRowCount();if(R==-1||R>=V&&Q<V+U){this.updateContent();}},onTableModelMetaDataChanged:function(){this.updateContent(true);},_applyMaxCacheLines:function(W,X){if(this.__wS>=W&&W!==-1){this.__wT();}},__wT:function(){this.__wO=[];this.__wS=0;},__wU:function(Y,ba,bb){if(!ba&&!bb&&this.__wO[Y]){return this.__wO[Y];}else{return null;}},__wV:function(bc,bd,be,bf){var bg=this.getMaxCacheLines();if(!be&&!bf&&!this.__wO[bc]&&bg>0){this._applyMaxCacheLines(bg);this.__wO[bc]=bd;this.__wS+=1;}},updateContent:function(bh,bi,bj,bk){if(bh){this.__wT();}if(bi&&Math.abs(bi)<=Math.min(10,this.getVisibleRowCount())){this._scrollContent(bi);}else if(bk&&!this.getTable().getAlwaysUpdateCells()){this._updateRowStyles(bj);}else{this._updateAllRows();}},_updateRowStyles:function(bl){var bp=this.getContentElement().getDomElement();if(!bp||!bp.firstChild){this._updateAllRows();return;}var bt=this.getTable();var bn=bt.getSelectionModel();var bq=bt.getTableModel();var bu=bt.getDataRowRenderer();var bo=bp.firstChild.childNodes;var bs={table:bt};var bv=this.getFirstVisibleRow();var y=0;var bm=bo.length;if(bl!=null){var br=bl-bv;if(br>=0&&br<bm){bv=bl;y=br;bm=br+1;}else{return;}}for(;y<bm;y++,bv++){bs.row=bv;bs.selected=bn.isSelectedIndex(bv);bs.focusedRow=(this.__wQ==bv);bs.rowData=bq.getRowData(bv);bu.updateDataRowElement(bs,bo[y]);}},_getRowsHtml:function(bw,bx){var bD=this.getTable();var bG=bD.getSelectionModel();var bA=bD.getTableModel();var bB=bD.getTableColumnModel();var bV=this.getPaneScroller().getTablePaneModel();var bL=bD.getDataRowRenderer();bA.prefetchRows(bw,bw+bx-1);var bS=bD.getRowHeight();var bU=bV.getColumnCount();var bC=0;var bz=[];for(var x=0;x<bU;x++){var bY=bV.getColumnAtX(x);var bF=bB.getColumnWidth(bY);bz.push({col:bY,xPos:x,editable:bA.isColumnEditable(bY),focusedCol:this.__wR==bY,styleLeft:bC,styleWidth:bF});bC+=bF;}var bX=[];var ca=false;for(var bE=bw;bE<bw+bx;bE++){var bH=bG.isSelectedIndex(bE);var bK=(this.__wQ==bE);var bP=this.__wU(bE,bH,bK);if(bP){bX.push(bP);continue;}var by=[];var bR={table:bD};bR.styleHeight=bS;bR.row=bE;bR.selected=bH;bR.focusedRow=bK;bR.rowData=bA.getRowData(bE);if(!bR.rowData){ca=true;}by.push(q);var bO=bL.getRowAttributes(bR);if(bO){by.push(bO);}var bN=bL.getRowClass(bR);if(bN){by.push(r,bN,g);}var bM=bL.createRowStyle(bR);bM+=m+bL.getRowHeightStyle(bS)+s;if(bM){by.push(D,bM,g);}by.push(v);var bW=false;for(x=0;x<bU&&!bW;x++){var bI=bz[x];for(var bT in bI){bR[bT]=bI[bT];}var bY=bR.col;bR.value=bA.getValue(bY,bE);var bJ=bB.getDataCellRenderer(bY);bR.style=bJ.getDefaultCellStyle();bW=bJ.createDataCellHtml(bR,by)||false;}by.push(h);var bQ=by.join(k);this.__wV(bE,bQ,bH,bK);bX.push(bQ);}this.fireDataEvent(a,ca);return bX.join(k);},_scrollContent:function(cb){var cc=this.getContentElement().getDomElement();if(!(cc&&cc.firstChild)){this._updateAllRows();return;}var cl=cc.firstChild;var cd=cl.childNodes;var cj=this.getVisibleRowCount();var ci=this.getFirstVisibleRow();var cg=this.getTable().getTableModel();var cm=0;cm=cg.getRowCount();if(ci+cj>cm){this._updateAllRows();return;}var cn=cb<0?cj+cb:0;var ce=cb<0?0:cj-cb;for(i=Math.abs(cb)-1;i>=0;i--){var ch=cd[cn];try{cl.removeChild(ch);}catch(co){break;}}if(!this.__wP){this.__wP=document.createElement(E);}var ck=e;ck+=this._getRowsHtml(ci+ce,Math.abs(cb));ck+=h;this.__wP.innerHTML=ck;var cf=this.__wP.firstChild.childNodes;if(cb>0){for(var i=cf.length-1;i>=0;i--){var ch=cf[0];cl.appendChild(ch);}}else{for(var i=cf.length-1;i>=0;i--){var ch=cf[cf.length-1];cl.insertBefore(ch,cl.firstChild);}}if(this.__wQ!==null){this._updateRowStyles(this.__wQ-cb);this._updateRowStyles(this.__wQ);}this.fireEvent(f);},_updateAllRows:function(){var cs=this.getContentElement().getDomElement();if(!cs){this.addListenerOnce(t,arguments.callee,this);return;}var cy=this.getTable();var cv=cy.getTableModel();var cx=this.getPaneScroller().getTablePaneModel();var cw=cx.getColumnCount();var cp=cy.getRowHeight();var ct=this.getFirstVisibleRow();var cq=this.getVisibleRowCount();var cz=cv.getRowCount();if(ct+cq>cz){cq=Math.max(0,cz-ct);}var cr=cx.getTotalWidth();var cu;if(cq>0){cu=[l,A,(cy.getForceLineHeight()?u+cp+p:k),c,n,this._getRowsHtml(ct,cq),d];}else{cu=[];}var cA=cu.join(k);cs.innerHTML=cA;this.setWidth(cr);this.__wM=cw;this.__wN=cq;this.fireEvent(f);}},destruct:function(){this.__wP=this.__wL=this.__wO=null;}});})();(function(){var c="hovered",b="__wX",a="qx.ui.table.pane.Header";qx.Class.define(a,{extend:qx.ui.core.Widget,construct:function(d){qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.layout.HBox());this.__wW=new qx.ui.core.Blocker(this);this.__wX=d;},members:{__wX:null,__wY:null,__xa:null,__wW:null,getPaneScroller:function(){return this.__wX;},getTable:function(){return this.__wX.getTable();},getBlocker:function(){return this.__wW;},onColOrderChanged:function(){this._updateContent(true);},onPaneModelChanged:function(){this._updateContent(true);},onTableModelMetaDataChanged:function(){this._updateContent();},setColumnWidth:function(e,f,g){var h=this.getHeaderWidgetAtColumn(e);if(h!=null){h.setWidth(f);}},setMouseOverColumn:function(i){if(i!=this.__xa){if(this.__xa!=null){var j=this.getHeaderWidgetAtColumn(this.__xa);if(j!=null){j.removeState(c);}}if(i!=null){this.getHeaderWidgetAtColumn(i).addState(c);}this.__xa=i;}},getHeaderWidgetAtColumn:function(k){var l=this.getPaneScroller().getTablePaneModel().getX(k);return this._getChildren()[l];},showColumnMoveFeedback:function(m,x){var q=this.getContainerLocation();if(this.__wY==null){var v=this.getTable();var n=this.getPaneScroller().getTablePaneModel().getX(m);var p=this._getChildren()[n];var r=v.getTableModel();var t=v.getTableColumnModel();var u={xPos:n,col:m,name:r.getColumnName(m),table:v};var s=t.getHeaderCellRenderer(m);var o=s.createHeaderCell(u);var w=p.getBounds();o.setWidth(w.width);o.setHeight(w.height);o.setZIndex(1000000);o.setOpacity(0.8);o.setLayoutProperties({top:q.top});this.getApplicationRoot().add(o);this.__wY=o;}this.__wY.setLayoutProperties({left:q.left+x});this.__wY.show();},hideColumnMoveFeedback:function(){if(this.__wY!=null){this.__wY.destroy();this.__wY=null;}},isShowingColumnMoveFeedback:function(){return this.__wY!=null;},_updateContent:function(y){var I=this.getTable();var C=I.getTableModel();var F=I.getTableColumnModel();var H=this.getPaneScroller().getTablePaneModel();var K=this._getChildren();var D=H.getColumnCount();var G=C.getSortColumnIndex();if(y){this._cleanUpCells();}var z={};z.sortedAscending=C.isSortAscending();for(var x=0;x<D;x++){var B=H.getColumnAtX(x);if(B===undefined){continue;}var J=F.getColumnWidth(B);var E=F.getHeaderCellRenderer(B);z.xPos=x;z.col=B;z.name=C.getColumnName(B);z.editable=C.isColumnEditable(B);z.sorted=(B==G);z.table=I;var A=K[x];if(A==null){A=E.createHeaderCell(z);A.set({width:J});this._add(A);}else{E.updateHeaderCell(z,A);}}},_cleanUpCells:function(){var M=this._getChildren();for(var x=M.length-1;x>=0;x--){var L=M[x];L.destroy();}}},destruct:function(){this.__wW.dispose();this._disposeObjects(b);}});})();(function(){var m="Boolean",l="resize-line",k="mousedown",j="qx.event.type.Data",i="mouseup",h="qx.ui.table.pane.CellEvent",g="scroll",d="focus-indicator",c="excluded",b="scrollbar-y",bm="table-scroller-focus-indicator",bl="visible",bk="mousemove",bj="header",bi="editing",bh="click",bg="modelChanged",bf="scrollbar-x",be="cellClick",bd="pane",t="__xi",u="__xc",r="mouseout",s="__xh",p="changeHorizontalScrollBarVisible",q="bottom",n="_applyScrollTimeout",o="changeScrollX",z="_applyTablePaneModel",A="Integer",I="__xg",G="dblclick",Q="dataEdited",L="mousewheel",Y="interval",V="qx.ui.table.pane.Scroller",C="__xk",bc="_applyShowCellFocusIndicator",bb="__xe",ba="resize",B="vertical",E="changeScrollY",F="appear",H="table-scroller",J="beforeSort",M="__xd",S="cellDblclick",X="horizontal",v="losecapture",w="contextmenu",D="col-resize",P="disappear",O="_applyVerticalScrollBarVisible",N="_applyHorizontalScrollBarVisible",U="cellContextmenu",T="__xj",K="close",R="changeTablePaneModel",a="__xf",W="qx.ui.table.pane.Model",y="changeVerticalScrollBarVisible";qx.Class.define(V,{extend:qx.ui.core.Widget,include:qx.ui.core.scroll.MScrollBarFactory,construct:function(bn){qx.ui.core.Widget.call(this);this.__xb=bn;var bo=new qx.ui.layout.Grid();bo.setColumnFlex(0,1);bo.setRowFlex(1,1);this._setLayout(bo);this.__xc=this._showChildControl(bf);this.__xd=this._showChildControl(b);this.__xe=this._showChildControl(bj);this.__xf=this._showChildControl(bd);this.__xg=new qx.ui.container.Composite(new qx.ui.layout.HBox()).set({minWidth:0});this._add(this.__xg,{row:0,column:0,colSpan:2});this.__xh=new qx.ui.table.pane.Clipper();this.__xh.add(this.__xe);this.__xh.addListener(v,this._onChangeCaptureHeader,this);this.__xh.addListener(bk,this._onMousemoveHeader,this);this.__xh.addListener(k,this._onMousedownHeader,this);this.__xh.addListener(i,this._onMouseupHeader,this);this.__xh.addListener(bh,this._onClickHeader,this);this.__xg.add(this.__xh,{flex:1});this.__xi=new qx.ui.table.pane.Clipper();this.__xi.add(this.__xf);this.__xi.addListener(L,this._onMousewheel,this);this.__xi.addListener(bk,this._onMousemovePane,this);this.__xi.addListener(k,this._onMousedownPane,this);this.__xi.addListener(i,this._onMouseupPane,this);this.__xi.addListener(bh,this._onClickPane,this);this.__xi.addListener(w,this._onContextMenu,this);this.__xi.addListener(G,this._onDblclickPane,this);this.__xi.addListener(ba,this._onResizePane,this);this._add(this.__xi,{row:1,column:0});this.__xj=this.getChildControl(d);this.initShowCellFocusIndicator();this.getChildControl(l).hide();this.addListener(r,this._onMouseout,this);this.addListener(F,this._onAppear,this);this.addListener(P,this._onDisappear,this);this.__xk=new qx.event.Timer();this.__xk.addListener(Y,this._oninterval,this);this.initScrollTimeout();},statics:{MIN_COLUMN_WIDTH:10,RESIZE_REGION_RADIUS:5,CLICK_TOLERANCE:5,HORIZONTAL_SCROLLBAR:1,VERTICAL_SCROLLBAR:2},events:{"changeScrollY":j,"changeScrollX":j,"cellClick":h,"cellDblclick":h,"cellContextmenu":h,"beforeSort":j},properties:{horizontalScrollBarVisible:{check:m,init:true,apply:N,event:p},verticalScrollBarVisible:{check:m,init:true,apply:O,event:y},tablePaneModel:{check:W,apply:z,event:R},liveResize:{check:m,init:false},focusCellOnMouseMove:{check:m,init:false},selectBeforeFocus:{check:m,init:false},showCellFocusIndicator:{check:m,init:true,apply:bc},resetSelectionOnHeaderClick:{check:m,init:true},scrollTimeout:{check:A,init:100,apply:n},appearance:{refine:true,init:H}},members:{__xl:null,__xb:null,__xm:null,__xn:null,__xo:null,__xp:null,__xq:null,__xr:null,__xs:null,__xt:null,__xu:null,__xv:null,__xw:null,__xx:null,__xy:false,__xz:null,__xA:null,__xB:null,__xC:null,__xD:null,__xE:null,__xF:null,__xG:null,__xc:null,__xd:null,__xe:null,__xh:null,__xf:null,__xi:null,__xj:null,__xg:null,__xk:null,getPaneInsetRight:function(){var bq=this.getTopRightWidget();var br=bq&&bq.isVisible()&&bq.getBounds()?bq.getBounds().width:0;var bp=this.getVerticalScrollBarVisible()?this.getVerticalScrollBarWidth():0;return Math.max(br,bp);},setPaneWidth:function(bs){if(this.isVerticalScrollBarVisible()){bs+=this.getPaneInsetRight();}this.setWidth(bs);},_createChildControlImpl:function(bt,bu){var bv;switch(bt){case bj:bv=(this.getTable().getNewTablePaneHeader())(this);break;case bd:bv=(this.getTable().getNewTablePane())(this);break;case d:bv=new qx.ui.table.pane.FocusIndicator(this);bv.setUserBounds(0,0,0,0);bv.setZIndex(1000);bv.addListener(i,this._onMouseupFocusIndicator,this);this.__xi.add(bv);bv.show();bv.setDecorator(null);break;case l:bv=new qx.ui.core.Widget();bv.setUserBounds(0,0,0,0);bv.setZIndex(1000);this.__xi.add(bv);break;case bf:bv=this._createScrollBar(X).set({minWidth:0,alignY:q});bv.addListener(g,this._onScrollX,this);this._add(bv,{row:2,column:0});break;case b:bv=this._createScrollBar(B);bv.addListener(g,this._onScrollY,this);this._add(bv,{row:1,column:1});break;}return bv||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,bt);},_applyHorizontalScrollBarVisible:function(bw,bx){this.__xc.setVisibility(bw?bl:c);},_applyVerticalScrollBarVisible:function(by,bz){this.__xd.setVisibility(by?bl:c);},_applyTablePaneModel:function(bA,bB){if(bB!=null){bB.removeListener(bg,this._onPaneModelChanged,this);}bA.addListener(bg,this._onPaneModelChanged,this);},_applyShowCellFocusIndicator:function(bC,bD){if(bC){this.__xj.setDecorator(bm);this._updateFocusIndicator();}else{if(this.__xj){this.__xj.setDecorator(null);}}},getScrollY:function(){return this.__xd.getPosition();},setScrollY:function(scrollY,bE){this.__xd.scrollTo(scrollY);if(bE){this._updateContent();}},getScrollX:function(){return this.__xc.getPosition();},setScrollX:function(scrollX){this.__xc.scrollTo(scrollX);},getTable:function(){return this.__xb;},onColVisibilityChanged:function(){this.updateHorScrollBarMaximum();this._updateFocusIndicator();},setColumnWidth:function(bF,bG){this.__xe.setColumnWidth(bF,bG);this.__xf.setColumnWidth(bF,bG);var bH=this.getTablePaneModel();var x=bH.getX(bF);if(x!=-1){this.updateHorScrollBarMaximum();this._updateFocusIndicator();}},onColOrderChanged:function(){this.__xe.onColOrderChanged();this.__xf.onColOrderChanged();this.updateHorScrollBarMaximum();},onTableModelDataChanged:function(bI,bJ,bK,bL){this.__xf.onTableModelDataChanged(bI,bJ,bK,bL);var bM=this.getTable().getTableModel().getRowCount();if(bM!=this.__xl){this.updateVerScrollBarMaximum();if(this.getFocusedRow()>=bM){if(bM==0){this.setFocusedCell(null,null);}else{this.setFocusedCell(this.getFocusedColumn(),bM-1);}}this.__xl=bM;}},onSelectionChanged:function(){this.__xf.onSelectionChanged();},onFocusChanged:function(){this.__xf.onFocusChanged();},onTableModelMetaDataChanged:function(){this.__xe.onTableModelMetaDataChanged();this.__xf.onTableModelMetaDataChanged();},_onPaneModelChanged:function(){this.__xe.onPaneModelChanged();this.__xf.onPaneModelChanged();},_onResizePane:function(){this.updateHorScrollBarMaximum();this.updateVerScrollBarMaximum();this._updateContent();this.__xe._updateContent();this.__xb._updateScrollBarVisibility();},updateHorScrollBarMaximum:function(){var bQ=this.__xi.getInnerSize();if(!bQ){return ;}var bO=this.getTablePaneModel().getTotalWidth();var bP=this.__xc;if(bQ.width<bO){var bN=Math.max(0,bO-bQ.width);bP.setMaximum(bN);bP.setKnobFactor(bQ.width/bO);var bR=bP.getPosition();bP.setPosition(Math.min(bR,bN));}else{bP.setMaximum(0);bP.setKnobFactor(1);bP.setPosition(0);}},updateVerScrollBarMaximum:function(){var ca=this.__xi.getInnerSize();if(!ca){return ;}var bX=this.getTable().getTableModel();var bT=bX.getRowCount();if(this.getTable().getKeepFirstVisibleRowComplete()){bT+=1;}var bS=this.getTable().getRowHeight();var bV=bT*bS;var bY=this.__xd;if(ca.height<bV){var bU=Math.max(0,bV-ca.height);bY.setMaximum(bU);bY.setKnobFactor(ca.height/bV);var bW=bY.getPosition();bY.setPosition(Math.min(bW,bU));}else{bY.setMaximum(0);bY.setKnobFactor(1);bY.setPosition(0);}},onKeepFirstVisibleRowCompleteChanged:function(){this.updateVerScrollBarMaximum();this._updateContent();},_onAppear:function(){this._startInterval(this.getScrollTimeout());},_onDisappear:function(){this._stopInterval();},_onScrollX:function(e){var cb=e.getData();this.fireDataEvent(o,cb,e.getOldData());this.__xh.scrollToX(cb);this.__xi.scrollToX(cb);},_onScrollY:function(e){this.fireDataEvent(E,e.getData(),e.getOldData());this._postponedUpdateContent();},_onMousewheel:function(e){var cc=this.getTable();if(!cc.getEnabled()){return;}var ce=qx.bom.client.Engine.GECKO?1:3;var cd=this.__xd.getPosition()+((e.getWheelDelta()*ce)*cc.getRowHeight());this.__xd.scrollTo(cd);if(this.__xA&&this.getFocusCellOnMouseMove()){this._focusCellAtPagePos(this.__xA,this.__xB);}e.stop();},__xH:function(cf){var ck=this.getTable();var cl=this.__xe.getHeaderWidgetAtColumn(this.__xu);var cg=cl.getSizeHint().minWidth;var ci=Math.max(cg,this.__xw+cf-this.__xv);if(this.getLiveResize()){var ch=ck.getTableColumnModel();ch.setColumnWidth(this.__xu,ci,true);}else{this.__xe.setColumnWidth(this.__xu,ci,true);var cj=this.getTablePaneModel();this._showResizeLine(cj.getColumnLeft(this.__xu)+ci);}this.__xv+=ci-this.__xw;this.__xw=ci;},__xI:function(cm){var cn=qx.ui.table.pane.Scroller.CLICK_TOLERANCE;if(this.__xe.isShowingColumnMoveFeedback()||cm>this.__xt+cn||cm<this.__xt-cn){this.__xq+=cm-this.__xt;this.__xe.showColumnMoveFeedback(this.__xp,this.__xq);var co=this.__xb.getTablePaneScrollerAtPageX(cm);if(this.__xs&&this.__xs!=co){this.__xs.hideColumnMoveFeedback();}if(co!=null){this.__xr=co.showColumnMoveFeedback(cm);}else{this.__xr=null;}this.__xs=co;this.__xt=cm;}},_onMousemoveHeader:function(e){var cv=this.getTable();if(!cv.getEnabled()){return;}var cw=false;var cp=null;var ct=e.getDocumentLeft();var cu=e.getDocumentTop();this.__xA=ct;this.__xB=cu;if(this.__xu!=null){this.__xH(ct);cw=true;e.stopPropagation();}else if(this.__xp!=null){this.__xI(ct);e.stopPropagation();}else{var cq=this._getResizeColumnForPageX(ct);if(cq!=-1){cw=true;}else{var cs=cv.getTableModel();var cx=this._getColumnForPageX(ct);if(cx!=null&&cs.isColumnSortable(cx)){cp=cx;}}}var cr=cw?D:null;this.getApplicationRoot().setGlobalCursor(cr);this.setCursor(cr);this.__xe.setMouseOverColumn(cp);},_onMousemovePane:function(e){var cy=this.getTable();if(!cy.getEnabled()){return;}var cA=e.getDocumentLeft();var cB=e.getDocumentTop();this.__xA=cA;this.__xB=cB;var cz=this._getRowForPagePos(cA,cB);if(cz!=null&&this._getColumnForPageX(cA)!=null){if(this.getFocusCellOnMouseMove()){this._focusCellAtPagePos(cA,cB);}}this.__xe.setMouseOverColumn(null);},_onMousedownHeader:function(e){if(!this.getTable().getEnabled()){return;}var cD=e.getDocumentLeft();var cE=this._getResizeColumnForPageX(cD);if(cE!=-1){this._startResizeHeader(cE,cD);e.stop();}else{var cC=this._getColumnForPageX(cD);if(cC!=null){this._startMoveHeader(cC,cD);e.stop();}}},_startResizeHeader:function(cF,cG){var cH=this.getTable().getTableColumnModel();this.__xu=cF;this.__xv=cG;this.__xw=cH.getColumnWidth(this.__xu);this.__xh.capture();},_startMoveHeader:function(cI,cJ){this.__xp=cI;this.__xt=cJ;this.__xq=this.getTablePaneModel().getColumnLeft(cI);this.__xh.capture();},_onMousedownPane:function(e){var cN=this.getTable();if(!cN.getEnabled()){return;}if(cN.isEditing()){cN.stopEditing();}var cK=e.getDocumentLeft();var cM=e.getDocumentTop();var cP=this._getRowForPagePos(cK,cM);var cO=this._getColumnForPageX(cK);if(cP!==null){this.__xx={row:cP,col:cO};this.__xy=false;var cL=this.getSelectBeforeFocus();if(cL){cN.getSelectionManager().handleMouseDown(cP,e);}if(!this.getFocusCellOnMouseMove()){this._focusCellAtPagePos(cK,cM);}if(!cL){cN.getSelectionManager().handleMouseDown(cP,e);}}},_onMouseupFocusIndicator:function(e){if(this.__xx&&!this.__xy&&!this.isEditing()&&this.__xj.getRow()==this.__xx.row&&this.__xj.getColumn()==this.__xx.col){this.fireEvent(be,qx.ui.table.pane.CellEvent,[this,e,this.__xx.row,this.__xx.col],true);this.__xy=true;}else if(!this.isEditing()){this._onMousedownPane(e);}},_onChangeCaptureHeader:function(e){if(this.__xu!=null){this._stopResizeHeader();}if(this.__xp!=null){this._stopMoveHeader();}},_stopResizeHeader:function(){var cQ=this.getTable().getTableColumnModel();if(!this.getLiveResize()){this._hideResizeLine();cQ.setColumnWidth(this.__xu,this.__xw,true);}this.__xu=null;this.__xh.releaseCapture();this.getApplicationRoot().setGlobalCursor(null);this.setCursor(null);if(this.isEditing()){var cR=this.__xE.getBounds().height;this.__xE.setUserBounds(0,0,this.__xw,cR);}},_stopMoveHeader:function(){var cW=this.getTable().getTableColumnModel();var cX=this.getTablePaneModel();this.__xe.hideColumnMoveFeedback();if(this.__xs){this.__xs.hideColumnMoveFeedback();}if(this.__xr!=null){var da=cX.getFirstColumnX()+cX.getX(this.__xp);var cV=this.__xr;if(cV!=da&&cV!=da+1){var cY=cW.getVisibleColumnAtX(da);var cU=cW.getVisibleColumnAtX(cV);var cT=cW.getOverallX(cY);var cS=(cU!=null)?cW.getOverallX(cU):cW.getOverallColumnCount();if(cS>cT){cS--;}cW.moveColumn(cT,cS);this._updateFocusIndicator();}}this.__xp=null;this.__xr=null;this.__xh.releaseCapture();},_onMouseupPane:function(e){var db=this.getTable();if(!db.getEnabled()){return;}var dc=this._getRowForPagePos(e.getDocumentLeft(),e.getDocumentTop());if(dc!=-1&&dc!=null&&this._getColumnForPageX(e.getDocumentLeft())!=null){db.getSelectionManager().handleMouseUp(dc,e);}},_onMouseupHeader:function(e){var dd=this.getTable();if(!dd.getEnabled()){return;}if(this.__xu!=null){this._stopResizeHeader();this.__xz=true;e.stop();}else if(this.__xp!=null){this._stopMoveHeader();e.stop();}},_onClickHeader:function(e){if(this.__xz){this.__xz=false;return;}var di=this.getTable();if(!di.getEnabled()){return;}var dg=di.getTableModel();var dh=e.getDocumentLeft();var df=this._getResizeColumnForPageX(dh);if(df==-1){var dl=this._getColumnForPageX(dh);if(dl!=null&&dg.isColumnSortable(dl)){var de=dg.getSortColumnIndex();var dj=(dl!=de)?true:!dg.isSortAscending();var dk={column:dl,ascending:dj,clickEvent:e};if(this.fireDataEvent(J,dk,null,true)){dg.sortByColumn(dl,dj);if(this.getResetSelectionOnHeaderClick()){di.getSelectionModel().resetSelection();}}}}e.stop();},_onClickPane:function(e){var dm=this.getTable();if(!dm.getEnabled()){return;}var dq=e.getDocumentLeft();var dr=e.getDocumentTop();var dn=this._getRowForPagePos(dq,dr);var dp=this._getColumnForPageX(dq);if(dn!=null&&dp!=null){dm.getSelectionManager().handleClick(dn,e);if(this.__xj.isHidden()||(this.__xx&&!this.__xy&&!this.isEditing()&&dn==this.__xx.row&&dp==this.__xx.col)){this.fireEvent(be,qx.ui.table.pane.CellEvent,[this,e,dn,dp],true);this.__xy=true;}}},_onContextMenu:function(e){var dv=e.getDocumentLeft();var dw=e.getDocumentTop();var dt=this._getRowForPagePos(dv,dw);var du=this._getColumnForPageX(dv);if(this.__xj.isHidden()||(this.__xx&&dt==this.__xx.row&&du==this.__xx.col)){this.fireEvent(U,qx.ui.table.pane.CellEvent,[this,e,dt,du],true);var ds=this.getTable().getContextMenu();if(ds){if(ds.getChildren().length>0){ds.openAtMouse(e);}else{ds.exclude();}e.preventDefault();}}},_onContextMenuOpen:function(e){},_onDblclickPane:function(e){var dy=e.getDocumentLeft();var dz=e.getDocumentTop();this._focusCellAtPagePos(dy,dz);this.startEditing();var dx=this._getRowForPagePos(dy,dz);if(dx!=-1&&dx!=null){this.fireEvent(S,qx.ui.table.pane.CellEvent,[this,e,dx],true);}},_onMouseout:function(e){var dA=this.getTable();if(!dA.getEnabled()){return;}if(this.__xu==null){this.setCursor(null);this.getApplicationRoot().setGlobalCursor(null);}this.__xe.setMouseOverColumn(null);},_showResizeLine:function(x){var dC=this._showChildControl(l);var dB=dC.getWidth();var dD=this.__xi.getBounds();dC.setUserBounds(x-Math.round(dB/2),0,dB,dD.height);},_hideResizeLine:function(){this._excludeChildControl(l);},showColumnMoveFeedback:function(dE){var dN=this.getTablePaneModel();var dM=this.getTable().getTableColumnModel();var dH=this.__xf.getContainerLocation().left;var dL=dN.getColumnCount();var dI=0;var dG=0;var dQ=dH;for(var dF=0;dF<dL;dF++){var dJ=dN.getColumnAtX(dF);var dO=dM.getColumnWidth(dJ);if(dE<dQ+dO/2){break;}dQ+=dO;dI=dF+1;dG=dQ-dH;}var dK=this.__xi.getContainerLocation().left;var dP=this.__xi.getBounds().width;var scrollX=dK-dH;dG=qx.lang.Number.limit(dG,scrollX+2,scrollX+dP-1);this._showResizeLine(dG);return dN.getFirstColumnX()+dI;},hideColumnMoveFeedback:function(){this._hideResizeLine();},_focusCellAtPagePos:function(dR,dS){var dU=this._getRowForPagePos(dR,dS);if(dU!=-1&&dU!=null){var dT=this._getColumnForPageX(dR);this.__xb.setFocusedCell(dT,dU);}},setFocusedCell:function(dV,dW){if(!this.isEditing()){this.__xf.setFocusedCell(dV,dW,this.__xn);this.__xC=dV;this.__xD=dW;this._updateFocusIndicator();}},getFocusedColumn:function(){return this.__xC;},getFocusedRow:function(){return this.__xD;},scrollCellVisible:function(dX,dY){var ej=this.getTablePaneModel();var ea=ej.getX(dX);if(ea!=-1){var eg=this.__xi.getInnerSize();if(!eg){return;}var eh=this.getTable().getTableColumnModel();var ed=ej.getColumnLeft(dX);var ek=eh.getColumnWidth(dX);var eb=this.getTable().getRowHeight();var el=dY*eb;var scrollX=this.getScrollX();var scrollY=this.getScrollY();var ei=Math.min(ed,ed+ek-eg.width);var ef=ed;this.setScrollX(Math.max(ei,Math.min(ef,scrollX)));var ec=el+eb-eg.height;if(this.getTable().getKeepFirstVisibleRowComplete()){ec+=eb;}var ee=el;this.setScrollY(Math.max(ec,Math.min(ee,scrollY)),true);}},isEditing:function(){return this.__xE!=null;},startEditing:function(){var eq=this.getTable();var eo=eq.getTableModel();var es=this.__xC;if(!this.isEditing()&&(es!=null)&&eo.isColumnEditable(es)){var et=this.__xD;var em=this.getTablePaneModel().getX(es);var en=eo.getValue(es,et);this.__xF=eq.getTableColumnModel().getCellEditorFactory(es);var ep={col:es,row:et,xPos:em,value:en,table:eq};this.__xE=this.__xF.createCellEditor(ep);if(this.__xE===null){return false;}else if(this.__xE instanceof qx.ui.window.Window){this.__xE.setModal(true);this.__xE.setShowClose(false);this.__xE.addListener(K,this._onCellEditorModalWindowClose,this);var f=eq.getModalCellEditorPreOpenFunction();if(f!=null){f(this.__xE,ep);}this.__xE.open();}else{var er=this.__xj.getInnerSize();this.__xE.setUserBounds(0,0,er.width,er.height);this.__xj.addListener(k,function(e){this.__xx={row:this.__xD,col:this.__xC};e.stopPropagation();},this);this.__xj.add(this.__xE);this.__xj.addState(bi);this.__xj.setKeepActive(false);this.__xj.setDecorator(bm);this.__xE.focus();this.__xE.activate();}return true;}return false;},stopEditing:function(){if(!this.getShowCellFocusIndicator()){this.__xj.setDecorator(null);}this.flushEditor();this.cancelEditing();},flushEditor:function(){if(this.isEditing()){var ev=this.__xF.getCellEditorValue(this.__xE);var eu=this.getTable().getTableModel().getValue(this.__xC,this.__xD);this.getTable().getTableModel().setValue(this.__xC,this.__xD,ev);this.__xb.focus();this.__xb.fireDataEvent(Q,{row:this.__xD,col:this.__xC,oldValue:eu,value:ev});}},cancelEditing:function(){if(this.isEditing()&&!this.__xE.pendingDispose){if(this._cellEditorIsModalWindow){this.__xE.destroy();this.__xE=null;this.__xF=null;this.__xE.pendingDispose=true;}else{this.__xj.removeState(bi);this.__xj.setKeepActive(true);this.__xE.destroy();this.__xE=null;this.__xF=null;}}},_onCellEditorModalWindowClose:function(e){this.stopEditing();},_getColumnForPageX:function(ew){var ez=this.getTable().getTableColumnModel();var eA=this.getTablePaneModel();var ey=eA.getColumnCount();var eC=this.__xe.getContainerLocation().left;for(var x=0;x<ey;x++){var ex=eA.getColumnAtX(x);var eB=ez.getColumnWidth(ex);eC+=eB;if(ew<eC){return ex;}}return null;},_getResizeColumnForPageX:function(eD){var eH=this.getTable().getTableColumnModel();var eI=this.getTablePaneModel();var eG=eI.getColumnCount();var eK=this.__xe.getContainerLocation().left;var eE=qx.ui.table.pane.Scroller.RESIZE_REGION_RADIUS;for(var x=0;x<eG;x++){var eF=eI.getColumnAtX(x);var eJ=eH.getColumnWidth(eF);eK+=eJ;if(eD>=(eK-eE)&&eD<=(eK+eE)){return eF;}}return -1;},_getRowForPagePos:function(eL,eM){var eN=this.__xf.getContentLocation();if(eL<eN.left||eL>eN.right){return null;}if(eM>=eN.top&&eM<=eN.bottom){var eO=this.getTable().getRowHeight();var scrollY=this.__xd.getPosition();if(this.getTable().getKeepFirstVisibleRowComplete()){scrollY=Math.floor(scrollY/eO)*eO;}var eR=scrollY+eM-eN.top;var eT=Math.floor(eR/eO);var eS=this.getTable().getTableModel();var eP=eS.getRowCount();return (eT<eP)?eT:null;}var eQ=this.__xe.getContainerLocation();if(eM>=eQ.top&&eM<=eQ.bottom&&eL<=eQ.right){return -1;}return null;},setTopRightWidget:function(eU){var eV=this.__xG;if(eV!=null){this.__xg.remove(eV);}if(eU!=null){this.__xg.add(eU);}this.__xG=eU;},getTopRightWidget:function(){return this.__xG;},getHeader:function(){return this.__xe;},getTablePane:function(){return this.__xf;},getVerticalScrollBarWidth:function(){var eW=this.__xd;return eW.isVisible()?(eW.getSizeHint().width||0):0;},getNeededScrollBars:function(eX,eY){var ff=this.__xd.getSizeHint().width;var fg=this.__xi.getInnerSize();var fa=fg?fg.width:0;if(this.getVerticalScrollBarVisible()){fa+=ff;}var fj=fg?fg.height:0;if(this.getHorizontalScrollBarVisible()){fj+=ff;}var fd=this.getTable().getTableModel();var fh=fd.getRowCount();var fk=this.getTablePaneModel().getTotalWidth();var fi=this.getTable().getRowHeight()*fh;var fc=false;var fl=false;if(fk>fa){fc=true;if(fi>fj-ff){fl=true;}}else if(fi>fj){fl=true;if(!eY&&(fk>fa-ff)){fc=true;}}var fe=qx.ui.table.pane.Scroller.HORIZONTAL_SCROLLBAR;var fb=qx.ui.table.pane.Scroller.VERTICAL_SCROLLBAR;return ((eX||fc)?fe:0)|((eY||!fl)?0:fb);},getPaneClipper:function(){return this.__xi;},_applyScrollTimeout:function(fm,fn){this._startInterval(fm);},_startInterval:function(fo){this.__xk.setInterval(fo);this.__xk.start();},_stopInterval:function(){this.__xk.stop();},_postponedUpdateContent:function(){this._updateContent();},_oninterval:qx.event.GlobalError.observeMethod(function(){if(this.__xn&&!this.__xf._layoutPending){this.__xn=false;this._updateContent();}}),_updateContent:function(){var ft=this.__xi.getInnerSize();if(!ft){return;}var fw=ft.height;var scrollX=this.__xc.getPosition();var scrollY=this.__xd.getPosition();var fq=this.getTable().getRowHeight();var fr=Math.floor(scrollY/fq);var fv=this.__xf.getFirstVisibleRow();this.__xf.setFirstVisibleRow(fr);var fs=Math.ceil(fw/fq);var fp=0;var fu=this.getTable().getKeepFirstVisibleRowComplete();if(!fu){fs++;fp=scrollY%fq;}this.__xf.setVisibleRowCount(fs);if(fr!=fv){this._updateFocusIndicator();}this.__xi.scrollToX(scrollX);if(!fu){this.__xi.scrollToY(fp);}},_updateFocusIndicator:function(){var fx=this.getTable();if(!fx.getEnabled()){return;}this.__xj.moveToCell(this.__xC,this.__xD);}},destruct:function(){this._stopInterval();var fy=this.getTablePaneModel();if(fy){fy.dispose();}this.__xx=this.__xG=this.__xb=null;this._disposeObjects(u,M,s,t,T,bb,a,I,C);}});})();(function(){var a="qx.ui.table.pane.Clipper";qx.Class.define(a,{extend:qx.ui.container.Composite,construct:function(){qx.ui.container.Composite.call(this,new qx.ui.layout.Grow());this.setMinWidth(0);},members:{scrollToX:function(b){this.getContentElement().scrollToX(b,false);},scrollToY:function(c){this.getContentElement().scrollToY(c,true);}}});})();(function(){var g="Integer",f="Escape",d="keypress",c="Enter",b="excluded",a="qx.ui.table.pane.FocusIndicator";qx.Class.define(a,{extend:qx.ui.container.Composite,construct:function(h){qx.ui.container.Composite.call(this);this.__xJ=h;this.setKeepActive(true);this.addListener(d,this._onKeyPress,this);},properties:{visibility:{refine:true,init:b},row:{check:g,nullable:true},column:{check:g,nullable:true}},members:{__xJ:null,_onKeyPress:function(e){var i=e.getKeyIdentifier();if(i!==f&&i!==c){e.stopPropagation();}},moveToCell:function(j,k){if(!this.__xJ.getShowCellFocusIndicator()&&!this.__xJ.getTable().getTableModel().isColumnEditable(j)){this.exclude();return;}else{this.show();}if(j==null){this.hide();this.setRow(null);this.setColumn(null);}else{var l=this.__xJ.getTablePaneModel().getX(j);if(l==-1){this.hide();this.setRow(null);this.setColumn(null);}else{var q=this.__xJ.getTable();var o=q.getTableColumnModel();var p=this.__xJ.getTablePaneModel();var n=this.__xJ.getTablePane().getFirstVisibleRow();var m=q.getRowHeight();this.setUserBounds(p.getColumnLeft(j)-2,(k-n)*m-2,o.getColumnWidth(j)+3,m+3);this.show();this.setRow(k);this.setColumn(j);}}}},destruct:function(){this.__xJ=null;}});})();(function(){var b="Integer",a="qx.ui.table.pane.CellEvent";qx.Class.define(a,{extend:qx.event.type.Mouse,properties:{row:{check:b,nullable:true},column:{check:b,nullable:true}},members:{init:function(c,d,e,f){d.clone(this);this.setBubbles(false);if(e!=null){this.setRow(e);}else{this.setRow(c._getRowForPagePos(this.getDocumentLeft(),this.getDocumentTop()));}if(f!=null){this.setColumn(f);}else{this.setColumn(c._getColumnForPageX(this.getDocumentLeft()));}},clone:function(g){var h=qx.event.type.Mouse.prototype.clone.call(this,g);h.set({row:this.getRow(),column:this.getColumn()});return h;}}});})();(function(){var a="qx.lang.Number";qx.Class.define(a,{statics:{isInRange:function(b,c,d){return b>=c&&b<=d;},isBetweenRange:function(e,f,g){return e>f&&e<g;},limit:function(h,i,j){if(j!=null&&h>j){return j;}else if(i!=null&&h<i){return i;}else{return h;}}}});})();(function(){var l="move",k="Boolean",j="mouseup",i="mousedown",h="losecapture",g="qx.ui.core.MMovable",f="__Y",d="__ba",c="mousemove",b="maximized",a="move-frame";qx.Mixin.define(g,{properties:{movable:{check:k,init:true},useMoveFrame:{check:k,init:false}},members:{__Y:null,__ba:null,__bb:null,__bc:null,__bd:null,__be:null,__bf:null,__bg:false,__bh:null,__bi:0,_activateMoveHandle:function(m){if(this.__Y){throw new Error("The move handle could not be redefined!");}this.__Y=m;m.addListener(i,this._onMoveMouseDown,this);m.addListener(j,this._onMoveMouseUp,this);m.addListener(c,this._onMoveMouseMove,this);m.addListener(h,this.__bm,this);},__bj:function(){var n=this.__ba;if(!n){n=this.__ba=new qx.ui.core.Widget();n.setAppearance(a);n.exclude();qx.core.Init.getApplication().getRoot().add(n);}return n;},__bk:function(){var location=this.getContainerLocation();var p=this.getBounds();var o=this.__bj();o.setUserBounds(location.left,location.top,p.width,p.height);o.show();o.setZIndex(this.getZIndex()+1);},__bl:function(e){var r=this.__bb;var u=Math.max(r.left,Math.min(r.right,e.getDocumentLeft()));var t=Math.max(r.top,Math.min(r.bottom,e.getDocumentTop()));var q=this.__bc+u;var s=this.__bd+t;return {viewportLeft:q,viewportTop:s,parentLeft:q-this.__be,parentTop:s-this.__bf};},_onMoveMouseDown:function(e){if(!this.getMovable()||this.hasState(b)){return;}var parent=this.getLayoutParent();var w=parent.getContentLocation();var x=parent.getBounds();if(qx.Class.implementsInterface(parent,qx.ui.window.IDesktop)){if(!parent.isContentBlocked()){this.__bh=parent.getBlockerColor();this.__bi=parent.getBlockerOpacity();parent.setBlockerColor(null);parent.setBlockerOpacity(1);parent.blockContent(this.getZIndex()-1);this.__bg=true;}}this.__bb={left:w.left,top:w.top,right:w.left+x.width,bottom:w.top+x.height};var v=this.getContainerLocation();this.__be=w.left;this.__bf=w.top;this.__bc=v.left-e.getDocumentLeft();this.__bd=v.top-e.getDocumentTop();this.addState(l);this.__Y.capture();if(this.getUseMoveFrame()){this.__bk();}e.stop();},_onMoveMouseMove:function(e){if(!this.hasState(l)){return;}var y=this.__bl(e);if(this.getUseMoveFrame()){this.__bj().setDomPosition(y.viewportLeft,y.viewportTop);}else{this.setDomPosition(y.parentLeft,y.parentTop);}e.stopPropagation();},_onMoveMouseUp:function(e){if(!this.hasState(l)){return;}this.removeState(l);var parent=this.getLayoutParent();if(qx.Class.implementsInterface(parent,qx.ui.window.IDesktop)){if(this.__bg){parent.unblockContent();parent.setBlockerColor(this.__bh);parent.setBlockerOpacity(this.__bi);this.__bh=null;this.__bi=0;this.__bg=false;}}this.__Y.releaseCapture();var z=this.__bl(e);this.setLayoutProperties({left:z.parentLeft,top:z.parentTop});if(this.getUseMoveFrame()){this.__bj().exclude();}e.stopPropagation();},__bm:function(e){if(!this.hasState(l)){return;}this.removeState(l);if(this.getUseMoveFrame()){this.__bj().exclude();}}},destruct:function(){this._disposeObjects(d,f);this.__bb=null;}});})();(function(){var k="Boolean",j="resize",i="mousedown",h="w-resize",g="sw-resize",f="n-resize",d="resizableRight",c="ne-resize",b="se-resize",a="Integer",z="e-resize",y="resizableLeft",x="mousemove",w="move",v="shorthand",u="maximized",t="nw-resize",s="mouseout",r="qx.ui.core.MResizable",q="mouseup",o="losecapture",p="resize-frame",m="resizableBottom",n="s-resize",l="resizableTop";qx.Mixin.define(r,{construct:function(){this.addListener(i,this.__bz,this,true);this.addListener(q,this.__bA,this);this.addListener(x,this.__bC,this);this.addListener(s,this.__bD,this);this.addListener(o,this.__bB,this);var A=this.getContainerElement().getDomElement();if(A==null){A=window;}this.__bn=qx.event.Registration.getManager(A).getHandler(qx.event.handler.DragDrop);},properties:{resizableTop:{check:k,init:true},resizableRight:{check:k,init:true},resizableBottom:{check:k,init:true},resizableLeft:{check:k,init:true},resizable:{group:[l,d,m,y],mode:v},resizeSensitivity:{check:a,init:5},useResizeFrame:{check:k,init:true}},members:{__bn:null,__bo:null,__bp:null,__bq:null,__br:null,__bs:null,__bt:null,RESIZE_TOP:1,RESIZE_BOTTOM:2,RESIZE_LEFT:4,RESIZE_RIGHT:8,__bu:function(){var B=this.__bo;if(!B){B=this.__bo=new qx.ui.core.Widget();B.setAppearance(p);B.exclude();qx.core.Init.getApplication().getRoot().add(B);}return B;},__bv:function(){var D=this.__bs;var C=this.__bu();C.setUserBounds(D.left,D.top,D.width,D.height);C.show();C.setZIndex(this.getZIndex()+1);},__bw:function(e){var F=this.__bp;var G=this.getSizeHint();var J=this.__bt;var I=this.__bs;var E=I.width;var H=I.height;var L=I.left;var top=I.top;var K;if((F&this.RESIZE_TOP)||(F&this.RESIZE_BOTTOM)){K=Math.max(J.top,Math.min(J.bottom,e.getDocumentTop()))-this.__br;if(F&this.RESIZE_TOP){H-=K;}else{H+=K;}if(H<G.minHeight){H=G.minHeight;}else if(H>G.maxHeight){H=G.maxHeight;}if(F&this.RESIZE_TOP){top+=I.height-H;}}if((F&this.RESIZE_LEFT)||(F&this.RESIZE_RIGHT)){K=Math.max(J.left,Math.min(J.right,e.getDocumentLeft()))-this.__bq;if(F&this.RESIZE_LEFT){E-=K;}else{E+=K;}if(E<G.minWidth){E=G.minWidth;}else if(E>G.maxWidth){E=G.maxWidth;}if(F&this.RESIZE_LEFT){L+=I.width-E;}}return {viewportLeft:L,viewportTop:top,parentLeft:I.bounds.left+L-I.left,parentTop:I.bounds.top+top-I.top,width:E,height:H};},__bx:{1:f,2:n,4:h,8:z,5:t,6:g,9:c,10:b},__by:function(e){var O=this.getContentLocation();var M=this.getResizeSensitivity();var Q=e.getDocumentLeft();var P=e.getDocumentTop();var N=0;if(this.getResizableTop()&&Math.abs(O.top-P)<M){N+=this.RESIZE_TOP;}else if(this.getResizableBottom()&&Math.abs(O.bottom-P)<M){N+=this.RESIZE_BOTTOM;}if(this.getResizableLeft()&&Math.abs(O.left-Q)<M){N+=this.RESIZE_LEFT;}else if(this.getResizableRight()&&Math.abs(O.right-Q)<M){N+=this.RESIZE_RIGHT;}this.__bp=N;},__bz:function(e){if(!this.__bp){return;}this.addState(j);this.__bq=e.getDocumentLeft();this.__br=e.getDocumentTop();var location=this.getContainerLocation();var T=this.getBounds();this.__bs={top:location.top,left:location.left,width:T.width,height:T.height,bounds:qx.lang.Object.clone(T)};var parent=this.getLayoutParent();var R=parent.getContentLocation();var S=parent.getBounds();this.__bt={left:R.left,top:R.top,right:R.left+S.width,bottom:R.top+S.height};if(this.getUseResizeFrame()){this.__bv();}this.capture();e.stop();},__bA:function(e){if(!this.hasState(j)){return;}if(this.getUseResizeFrame()){this.__bu().exclude();}var U=this.__bw(e);this.setWidth(U.width);this.setHeight(U.height);if(this.getResizableLeft()||this.getResizableTop()){this.setLayoutProperties({left:U.parentLeft,top:U.parentTop});}this.__bp=0;this.removeState(j);this.resetCursor();this.getApplicationRoot().resetGlobalCursor();this.releaseCapture();e.stopPropagation();},__bB:function(e){if(!this.__bp){return;}this.resetCursor();this.getApplicationRoot().resetGlobalCursor();this.removeState(w);if(this.getUseResizeFrame()){this.__bu().exclude();}},__bC:function(e){if(this.hasState(j)){var Y=this.__bw(e);if(this.getUseResizeFrame()){var W=this.__bu();W.setUserBounds(Y.viewportLeft,Y.viewportTop,Y.width,Y.height);}else{this.setWidth(Y.width);this.setHeight(Y.height);if(this.getResizableLeft()||this.getResizableTop()){this.setLayoutProperties({left:Y.parentLeft,top:Y.parentTop});}}e.stopPropagation();}else if(!this.hasState(u)&&!this.__bn.isSessionActive()){this.__by(e);var ba=this.__bp;var X=this.getApplicationRoot();if(ba){var V=this.__bx[ba];this.setCursor(V);X.setGlobalCursor(V);}else if(this.getCursor()){this.resetCursor();X.resetGlobalCursor();}}},__bD:function(e){if(this.getCursor()&&!this.hasState(j)){this.resetCursor();this.getApplicationRoot().resetGlobalCursor();}}},destruct:function(){if(this.__bo!=null&&!qx.core.ObjectRegistry.inShutDown){this.__bo.destroy();this.__bo=null;}this.__bn=null;}});})();(function(){var a="qx.ui.window.IWindowManager";qx.Interface.define(a,{members:{setDesktop:function(b){this.assertInterface(b,qx.ui.window.IDesktop);},changeActiveWindow:function(c,d){},updateStack:function(){},bringToFront:function(e){this.assertInstance(e,qx.ui.window.Window);},sendToBack:function(f){this.assertInstance(f,qx.ui.window.Window);}}});})();(function(){var b="__X",a="qx.ui.window.Manager";qx.Class.define(a,{extend:qx.core.Object,implement:qx.ui.window.IWindowManager,members:{__X:null,setDesktop:function(c){this.__X=c;this.updateStack();},getDesktop:function(){return this.__X;},changeActiveWindow:function(d,e){if(d){this.bringToFront(d);d.setActive(true);}if(e){e.resetActive();}},_minZIndex:1e5,updateStack:function(){qx.ui.core.queue.Widget.add(this);},syncWidget:function(){this.__X.forceUnblockContent();var f=this.__X.getWindows();var h=this._minZIndex;var m=h+f.length*2;var j=h+f.length*4;var k=null;for(var i=0,l=f.length;i<l;i++){var g=f[i];if(!g.isVisible()){continue;}k=k||g;if(g.isModal()){g.setZIndex(j);this.__X.blockContent(j-1);j+=2;k=g;}else if(g.isAlwaysOnTop()){g.setZIndex(m);m+=2;}else{g.setZIndex(h);h+=2;}if(!k.isModal()&&g.isActive()||g.getZIndex()>k.getZIndex()){k=g;}}this.__X.setActiveWindow(k);},bringToFront:function(n){var o=this.__X.getWindows();var p=qx.lang.Array.remove(o,n);if(p){o.push(n);this.updateStack();}},sendToBack:function(q){var r=this.__X.getWindows();var s=qx.lang.Array.remove(r,q);if(s){r.unshift(q);this.updateStack();}}},destruct:function(){this._disposeObjects(b);}});})();(function(){var k="Boolean",j="qx.event.type.Event",i="captionbar",h="_applyCaptionBarChange",g="maximize-button",f="restore-button",d="minimize-button",c="close-button",b="maximized",a="execute",Q="pane",P="title",O="icon",N="statusbar-text",M="statusbar",L="String",K="normal",J="active",I="beforeClose",H="beforeMinimize",r="mousedown",s="changeStatus",p="changeIcon",q="excluded",n="dblclick",o="_applyActive",l="beforeRestore",m="minimize",t="changeModal",u="changeAlwaysOnTop",z="_applyShowStatusbar",y="_applyStatus",B="qx.ui.window.Window",A="changeCaption",D="focusout",C="beforeMaximize",w="maximize",G="restore",F="window",E="close",v="changeActive",x="minimized";qx.Class.define(B,{extend:qx.ui.core.Widget,include:[qx.ui.core.MRemoteChildrenHandling,qx.ui.core.MRemoteLayoutHandling,qx.ui.core.MResizable,qx.ui.core.MMovable,qx.ui.core.MContentPadding],construct:function(R,S){qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.layout.VBox());this._createChildControl(i);this._createChildControl(Q);if(S!=null){this.setIcon(S);}if(R!=null){this.setCaption(R);}this._updateCaptionBar();this.addListener(r,this._onWindowMouseDown,this,true);this.addListener(D,this._onWindowFocusOut,this);qx.core.Init.getApplication().getRoot().add(this);this.initVisibility();qx.ui.core.FocusHandler.getInstance().addRoot(this);},statics:{DEFAULT_MANAGER_CLASS:qx.ui.window.Manager},events:{"beforeClose":j,"close":j,"beforeMinimize":j,"minimize":j,"beforeMaximize":j,"maximize":j,"beforeRestore":j,"restore":j},properties:{appearance:{refine:true,init:F},visibility:{refine:true,init:q},focusable:{refine:true,init:true},active:{check:k,init:false,apply:o,event:v},alwaysOnTop:{check:k,init:false,event:u},modal:{check:k,init:false,event:t},caption:{apply:h,event:A,nullable:true},icon:{check:L,nullable:true,apply:h,event:p,themeable:true},status:{check:L,nullable:true,apply:y,event:s},showClose:{check:k,init:true,apply:h,themeable:true},showMaximize:{check:k,init:true,apply:h,themeable:true},showMinimize:{check:k,init:true,apply:h,themeable:true},allowClose:{check:k,init:true,apply:h},allowMaximize:{check:k,init:true,apply:h},allowMinimize:{check:k,init:true,apply:h},showStatusbar:{check:k,init:false,apply:z}},members:{__V:null,__W:null,getChildrenContainer:function(){return this.getChildControl(Q);},_forwardStates:{active:true,maximized:true},setLayoutParent:function(parent){{};qx.ui.core.Widget.prototype.setLayoutParent.call(this,parent);},_createChildControlImpl:function(T,U){var V;switch(T){case M:V=new qx.ui.container.Composite(new qx.ui.layout.HBox());this._add(V);V.add(this.getChildControl(N));break;case N:V=new qx.ui.basic.Label();V.setValue(this.getStatus());break;case Q:V=new qx.ui.container.Composite();this._add(V,{flex:1});break;case i:var X=new qx.ui.layout.Grid();X.setRowFlex(0,1);X.setColumnFlex(1,1);V=new qx.ui.container.Composite(X);this._add(V);V.addListener(n,this._onCaptionMouseDblClick,this);this._activateMoveHandle(V);break;case O:V=new qx.ui.basic.Image(this.getIcon());this.getChildControl(i).add(V,{row:0,column:0});break;case P:V=new qx.ui.basic.Label(this.getCaption());V.setWidth(0);V.setAllowGrowX(true);var W=this.getChildControl(i);W.add(V,{row:0,column:1});break;case d:V=new qx.ui.form.Button();V.setFocusable(false);V.addListener(a,this._onMinimizeButtonClick,this);this.getChildControl(i).add(V,{row:0,column:2});break;case f:V=new qx.ui.form.Button();V.setFocusable(false);V.addListener(a,this._onRestoreButtonClick,this);this.getChildControl(i).add(V,{row:0,column:3});break;case g:V=new qx.ui.form.Button();V.setFocusable(false);V.addListener(a,this._onMaximizeButtonClick,this);this.getChildControl(i).add(V,{row:0,column:4});break;case c:V=new qx.ui.form.Button();V.setFocusable(false);V.addListener(a,this._onCloseButtonClick,this);this.getChildControl(i).add(V,{row:0,column:6});break;}return V||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,T);},_updateCaptionBar:function(){var ba;var bb=this.getIcon();if(bb){this.getChildControl(O).setSource(bb);this._showChildControl(O);}else{this._excludeChildControl(O);}var Y=this.getCaption();if(Y){this.getChildControl(P).setValue(Y);this._showChildControl(P);}else{this._excludeChildControl(P);}if(this.getShowMinimize()){this._showChildControl(d);ba=this.getChildControl(d);this.getAllowMinimize()?ba.resetEnabled():ba.setEnabled(false);}else{this._excludeChildControl(d);}if(this.getShowMaximize()){if(this.isMaximized()){this._showChildControl(f);this._excludeChildControl(g);}else{this._showChildControl(g);this._excludeChildControl(f);}ba=this.getChildControl(g);this.getAllowMaximize()?ba.resetEnabled():ba.setEnabled(false);}else{this._excludeChildControl(g);this._excludeChildControl(f);}if(this.getShowClose()){this._showChildControl(c);ba=this.getChildControl(c);this.getAllowClose()?ba.resetEnabled():ba.setEnabled(false);}else{this._excludeChildControl(c);}},close:function(){if(!this.isVisible()){return;}if(this.fireNonBubblingEvent(I,qx.event.type.Event,[false,true])){this.hide();this.fireEvent(E);}},open:function(){this.show();this.setActive(true);this.focus();},center:function(){var parent=this.getLayoutParent();if(parent){var bd=parent.getBounds();if(bd){var be=this.getSizeHint();var bc=Math.round((bd.width-be.width)/2);var top=Math.round((bd.height-be.height)/2);if(top<0){top=0;}this.moveTo(bc,top);return;}}{};},maximize:function(){if(this.isMaximized()){return;}var parent=this.getLayoutParent();if(parent!=null&&parent.supportsMaximize()){if(this.fireNonBubblingEvent(C,qx.event.type.Event,[false,true])){if(!this.isVisible()){this.open();}var bf=this.getLayoutProperties();this.__W=bf.left===undefined?0:bf.left;this.__V=bf.top===undefined?0:bf.top;this.setLayoutProperties({left:null,top:null,edge:0});this.addState(b);this._updateCaptionBar();this.fireEvent(w);}}},minimize:function(){if(!this.isVisible()){return;}if(this.fireNonBubblingEvent(H,qx.event.type.Event,[false,true])){var bg=this.getLayoutProperties();this.__W=bg.left===undefined?0:bg.left;this.__V=bg.top===undefined?0:bg.top;this.removeState(b);this.hide();this.fireEvent(m);}},restore:function(){if(this.getMode()===K){return;}if(this.fireNonBubblingEvent(l,qx.event.type.Event,[false,true])){if(!this.isVisible()){this.open();}var bh=this.__W;var top=this.__V;this.setLayoutProperties({edge:null,left:bh,top:top});this.removeState(b);this._updateCaptionBar();this.fireEvent(G);}},moveTo:function(bi,top){if(this.isMaximized()){return;}this.setLayoutProperties({left:bi,top:top});},isMaximized:function(){return this.hasState(b);},getMode:function(){if(!this.isVisible()){return x;}else{if(this.isMaximized()){return b;}else{return K;}}},_applyActive:function(bj,bk){if(bk){this.removeState(J);}else{this.addState(J);}},_getContentPaddingTarget:function(){return this.getChildControl(Q);},_applyShowStatusbar:function(bl,bm){if(bl){this._showChildControl(M);}else{this._excludeChildControl(M);}},_applyCaptionBarChange:function(bn,bo){this._updateCaptionBar();},_applyStatus:function(bp,bq){var br=this.getChildControl(N,true);if(br){br.setValue(bp);}},_onWindowEventStop:function(e){e.stopPropagation();},_onWindowMouseDown:function(e){this.setActive(true);},_onWindowFocusOut:function(e){if(this.getModal()){return;}var bs=e.getRelatedTarget();if(bs!=null&&!qx.ui.core.Widget.contains(this,bs)){this.setActive(false);}},_onCaptionMouseDblClick:function(e){if(this.getAllowMaximize()){this.isMaximized()?this.restore():this.maximize();}},_onMinimizeButtonClick:function(e){this.minimize();this.getChildControl(d).reset();},_onRestoreButtonClick:function(e){this.restore();this.getChildControl(f).reset();},_onMaximizeButtonClick:function(e){this.maximize();this.getChildControl(g).reset();},_onCloseButtonClick:function(e){this.close();this.getChildControl(c).reset();}}});})();(function(){var a="qx.ui.window.IDesktop";qx.Interface.define(a,{members:{setWindowManager:function(b){this.assertInterface(b,qx.ui.window.IWindowManager);},getWindows:function(){},supportsMaximize:function(){},blockContent:function(c){this.assertInteger(c);},unblockContent:function(){},isContentBlocked:function(){}}});})();(function(){var h="headerCellRendererChanged",g="visibilityChangedPre",f="Number",e="qx.event.type.Event",d="_applyFirstColumnX",c="Integer",b="qx.ui.table.pane.Model",a="_applyMaxColumnCount";qx.Class.define(b,{extend:qx.core.Object,construct:function(i){qx.core.Object.call(this);this.setTableColumnModel(i);},events:{"modelChanged":e},statics:{EVENT_TYPE_MODEL_CHANGED:"modelChanged"},properties:{firstColumnX:{check:c,init:0,apply:d},maxColumnCount:{check:f,init:-1,apply:a}},members:{__xK:null,__xL:null,_applyFirstColumnX:function(j,k){this.__xK=null;this.fireEvent(qx.ui.table.pane.Model.EVENT_TYPE_MODEL_CHANGED);},_applyMaxColumnCount:function(l,m){this.__xK=null;this.fireEvent(qx.ui.table.pane.Model.EVENT_TYPE_MODEL_CHANGED);},setTableColumnModel:function(n){if(this.__xL){this.__xL.removeListener(g,this._onColVisibilityChanged,this);this.__xL.removeListener(h,this._onColVisibilityChanged,this);}this.__xL=n;this.__xL.addListener(g,this._onColVisibilityChanged,this);this.__xL.addListener(h,this._onHeaderCellRendererChanged,this);this.__xK=null;},_onColVisibilityChanged:function(o){this.__xK=null;this.fireEvent(qx.ui.table.pane.Model.EVENT_TYPE_MODEL_CHANGED);},_onHeaderCellRendererChanged:function(p){this.fireEvent(qx.ui.table.pane.Model.EVENT_TYPE_MODEL_CHANGED);},getColumnCount:function(){if(this.__xK==null){var q=this.getFirstColumnX();var s=this.getMaxColumnCount();var r=this.__xL.getVisibleColumnCount();if(s==-1||(q+s)>r){this.__xK=r-q;}else{this.__xK=s;}}return this.__xK;},getColumnAtX:function(t){var u=this.getFirstColumnX();return this.__xL.getVisibleColumnAtX(u+t);},getX:function(v){var w=this.getFirstColumnX();var y=this.getMaxColumnCount();var x=this.__xL.getVisibleX(v)-w;if(x>=0&&(y==-1||x<y)){return x;}else{return -1;}},getColumnLeft:function(z){var C=0;var B=this.getColumnCount();for(var x=0;x<B;x++){var A=this.getColumnAtX(x);if(A==z){return C;}C+=this.__xL.getColumnWidth(A);}return -1;},getTotalWidth:function(){var D=0;var E=this.getColumnCount();for(var x=0;x<E;x++){var F=this.getColumnAtX(x);D+=this.__xL.getColumnWidth(F);}return D;}},destruct:function(){if(this.__xL){this.__xL.removeListener(g,this._onColVisibilityChanged,this);this.__xL.removeListener(h,this._onColVisibilityChanged,this);}this.__xL=null;}});})();(function(){var r="px",q=".qooxdoo-table-cell-icon {",p="abstract",o="",n="qx.ui.table.cellrenderer.AbstractImage",m=" qooxdoo-table-cell-icon",l="<div></div>",k="'",j="no-repeat",i="}",c=" text-align:center;",h="inline-block",f="static",b="top",a=" padding-top:1px;",e="title='",d="string",g="-moz-inline-box";qx.Class.define(n,{extend:qx.ui.table.cellrenderer.Abstract,type:p,construct:function(){qx.ui.table.cellrenderer.Abstract.call(this);var s=this.self(arguments);if(!s.stylesheet){s.stylesheet=qx.bom.Stylesheet.createElement(q+c+a+i);}},members:{__Hw:16,__Hx:16,__Hy:null,_insetY:2,_identifyImage:function(t){throw new Error("_identifyImage is abstract");},_getImageInfos:function(u){var v=this._identifyImage(u);if(v==null||typeof v==d){v={url:v,tooltip:null};}if(!v.imageWidth||!v.imageHeight){var w=this.__Hz(v.url);v.imageWidth=w.width;v.imageHeight=w.height;}v.width=v.imageWidth;v.height=v.imageHeight;return v;},__Hz:function(x){var A=qx.util.ResourceManager.getInstance();var z=qx.io.ImageLoader;var y,B;if(A.has(x)){y=A.getImageWidth(x);B=A.getImageHeight(x);}else if(z.isLoaded(x)){y=z.getWidth(x);B=z.getHeight(x);}else{y=this.__Hw;B=this.__Hx;}return {width:y,height:B};},createDataCellHtml:function(C,D){this.__Hy=this._getImageInfos(C);return qx.ui.table.cellrenderer.Abstract.prototype.createDataCellHtml.call(this,C,D);},_getCellClass:function(E){return qx.ui.table.cellrenderer.Abstract.prototype._getCellClass.call(this)+m;},_getContentHtml:function(F){var content=l;if(this.__Hy.url){content=qx.bom.element.Decoration.create(this.__Hy.url,j,{width:this.__Hy.width+r,height:this.__Hy.height+r,display:qx.bom.client.Engine.GECKO&&qx.bom.client.Engine.VERSION<1.9?g:h,verticalAlign:b,position:f});}return content;},_getCellAttributes:function(G){var H=this.__Hy.tooltip;if(H){return e+H+k;}else{return o;}}},destruct:function(){this.__Hy=null;}});})();(function(){var b="qx.ui.table.cellrenderer.Image",a="";qx.Class.define(b,{extend:qx.ui.table.cellrenderer.AbstractImage,construct:function(c,d){qx.ui.table.cellrenderer.AbstractImage.call(this);if(c){this.__HA=c;}if(d){this.__HB=d;}this.__HC=qx.util.AliasManager.getInstance();},members:{__HC:null,__HB:16,__HA:16,_identifyImage:function(e){var f={imageWidth:this.__HA,imageHeight:this.__HB};if(e.value==a){f.url=null;}else{f.url=this.__HC.resolve(e.value);}f.tooltip=e.tooltip;return f;}},destruct:function(){this.__HC=null;}});})();(function(){var k="Boolean",j="qx.event.type.Event",i="queued",h="String",g="sending",f="receiving",d="aborted",c="failed",b="nocache",a="completed",P="qx.io.remote.Response",O="POST",N="configured",M="timeout",L="GET",K="Pragma",J="no-url-params-on-post",I="PUT",H="no-cache",G="Cache-Control",r="Content-Type",s="text/plain",p="application/xml",q="application/json",n="text/html",o="application/x-www-form-urlencoded",l="qx.io.remote.Exchange",m="Integer",t="X-Qooxdoo-Response-Type",u="HEAD",y="qx.io.remote.Request",x="_applyResponseType",A="_applyState",z="text/javascript",C="changeState",B="_applyProhibitCaching",w="",F="_applyMethod",E="DELETE",D="boolean";qx.Class.define(y,{extend:qx.core.Object,construct:function(Q,R,S){qx.core.Object.call(this);this.__sp={};this.__sq={};this.__sr={};this.__ss={};if(Q!==undefined){this.setUrl(Q);}if(R!==undefined){this.setMethod(R);}if(S!==undefined){this.setResponseType(S);}this.setProhibitCaching(true);this.__st=++qx.io.remote.Request.__st;},events:{"created":j,"configured":j,"sending":j,"receiving":j,"completed":P,"aborted":j,"failed":P,"timeout":P},statics:{__st:0,methodAllowsRequestBody:function(T){return (T==O)||(T==I);}},properties:{url:{check:h,init:w},method:{check:[L,O,I,u,E],apply:F,init:L},asynchronous:{check:k,init:true},data:{check:h,nullable:true},username:{check:h,nullable:true},password:{check:h,nullable:true},state:{check:[N,i,g,f,a,d,M,c],init:N,apply:A,event:C},responseType:{check:[s,z,q,p,n],init:s,apply:x},timeout:{check:m,nullable:true},prohibitCaching:{check:function(v){return typeof v==D||v===J;},init:true,apply:B},crossDomain:{check:k,init:false},fileUpload:{check:k,init:false},transport:{check:l,nullable:true},useBasicHttpAuth:{check:k,init:false},parseJson:{check:k,init:true}},members:{__sp:null,__sq:null,__sr:null,__ss:null,__st:null,send:function(){qx.io.remote.RequestQueue.getInstance().add(this);},abort:function(){qx.io.remote.RequestQueue.getInstance().abort(this);},reset:function(){switch(this.getState()){case g:case f:this.error("Aborting already sent request!");case i:this.abort();break;}},isConfigured:function(){return this.getState()===N;},isQueued:function(){return this.getState()===i;},isSending:function(){return this.getState()===g;},isReceiving:function(){return this.getState()===f;},isCompleted:function(){return this.getState()===a;},isAborted:function(){return this.getState()===d;},isTimeout:function(){return this.getState()===M;},isFailed:function(){return this.getState()===c;},__su:qx.event.GlobalError.observeMethod(function(e){var U=e.clone();U.setTarget(this);this.dispatchEvent(U);}),_onqueued:function(e){this.setState(i);this.__su(e);},_onsending:function(e){this.setState(g);this.__su(e);},_onreceiving:function(e){this.setState(f);this.__su(e);},_oncompleted:function(e){this.setState(a);this.__su(e);this.dispose();},_onaborted:function(e){this.setState(d);this.__su(e);this.dispose();},_ontimeout:function(e){this.setState(M);this.__su(e);this.dispose();},_onfailed:function(e){this.setState(c);this.__su(e);this.dispose();},_applyState:function(V,W){{};},_applyProhibitCaching:function(X,Y){if(!X){this.removeParameter(b);this.removeRequestHeader(K);this.removeRequestHeader(G);return;}if(X!==J||this.getMethod()!=O){this.setParameter(b,new Date().valueOf());}else{this.removeParameter(b);}this.setRequestHeader(K,H);this.setRequestHeader(G,H);},_applyMethod:function(ba,bb){if(qx.io.remote.Request.methodAllowsRequestBody(ba)){this.setRequestHeader(r,o);}else{this.removeRequestHeader(r);}var bc=this.getProhibitCaching();this._applyProhibitCaching(bc,bc);},_applyResponseType:function(bd,be){this.setRequestHeader(t,bd);},setRequestHeader:function(bf,bg){this.__sp[bf]=bg;},removeRequestHeader:function(bh){delete this.__sp[bh];},getRequestHeader:function(bi){return this.__sp[bi]||null;},getRequestHeaders:function(){return this.__sp;},setParameter:function(bj,bk,bl){if(bl){this.__sr[bj]=bk;}else{this.__sq[bj]=bk;}},removeParameter:function(bm,bn){if(bn){delete this.__sr[bm];}else{delete this.__sq[bm];}},getParameter:function(bo,bp){if(bp){return this.__sr[bo]||null;}else{return this.__sq[bo]||null;}},getParameters:function(bq){return (bq?this.__sr:this.__sq);},setFormField:function(br,bs){this.__ss[br]=bs;},removeFormField:function(bt){delete this.__ss[bt];},getFormField:function(bu){return this.__ss[bu]||null;},getFormFields:function(){return this.__ss;},getSequenceNumber:function(){return this.__st;}},destruct:function(){this.setTransport(null);this.__sp=this.__sq=this.__sr=this.__ss=null;}});})();(function(){var b=".",a="qx.bom.client.Transport";qx.Class.define(a,{statics:{getMaxConcurrentRequestCount:function(){var h;var c=qx.bom.client.Engine;var g=c.FULLVERSION.split(b);var e=0;var d=0;var f=0;if(g[0]){e=g[0];}if(g[1]){d=g[1];}if(g[2]){f=g[2];}if(window.maxConnectionsPerServer){h=window.maxConnectionsPerServer;}else if(c.OPERA){h=8;}else if(c.WEBKIT){h=4;}else if(c.GECKO&&((e>1)||((e==1)&&(d>9))||((e==1)&&(d==9)&&(f>=1)))){h=6;}else{h=2;}return h;}}});})();(function(){var s="Integer",r="aborted",q="_onaborted",p="_on",o="_applyEnabled",n="Boolean",m="sending",l="__pc",k="interval",j="__pe",c="failed",h="qx.io.remote.RequestQueue",g="timeout",b="completed",a="queued",f="receiving",d="singleton";qx.Class.define(h,{type:d,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.__pb=[];this.__pc=[];this.__pd=0;this.__pe=new qx.event.Timer(500);this.__pe.addListener(k,this._oninterval,this);},properties:{enabled:{init:true,check:n,apply:o},maxTotalRequests:{check:s,nullable:true},maxConcurrentRequests:{check:s,init:qx.bom.client.Transport.getMaxConcurrentRequestCount()},defaultTimeout:{check:s,init:5000}},members:{__pb:null,__pc:null,__pd:null,__pe:null,getRequestQueue:function(){return this.__pb;},getActiveQueue:function(){return this.__pc;},_debug:function(){var t;{};},_check:function(){this._debug();if(this.__pc.length==0&&this.__pb.length==0){this.__pe.stop();}if(!this.getEnabled()){return;}if(this.__pb.length==0||(this.__pb[0].isAsynchronous()&&this.__pc.length>=this.getMaxConcurrentRequests())){return;}if(this.getMaxTotalRequests()!=null&&this.__pd>=this.getMaxTotalRequests()){return;}var u=this.__pb.shift();var v=new qx.io.remote.Exchange(u);this.__pd++;this.__pc.push(v);this._debug();v.addListener(m,this._onsending,this);v.addListener(f,this._onreceiving,this);v.addListener(b,this._oncompleted,this);v.addListener(r,this._oncompleted,this);v.addListener(g,this._oncompleted,this);v.addListener(c,this._oncompleted,this);v._start=(new Date).valueOf();v.send();if(this.__pb.length>0){this._check();}},_remove:function(w){qx.lang.Array.remove(this.__pc,w);w.dispose();this._check();},__pf:0,_onsending:function(e){{};e.getTarget().getRequest()._onsending(e);},_onreceiving:function(e){e.getTarget().getRequest()._onreceiving(e);},_oncompleted:function(e){{};var y=e.getTarget().getRequest();var x=p+e.getType();try{if(y[x]){y[x](e);}}catch(z){this.error("Request "+y+" handler "+x+" threw an error: ",z);try{if(y[q]){var event=qx.event.Registration.createEvent(r,qx.event.type.Event);y[q](event);}}catch(A){}}finally{this._remove(e.getTarget());}},_oninterval:function(e){var H=this.__pc;if(H.length==0){this.__pe.stop();return;}var C=(new Date).valueOf();var F;var D;var G=this.getDefaultTimeout();var E;var B;for(var i=H.length-1;i>=0;i--){F=H[i];D=F.getRequest();if(D.isAsynchronous()){E=D.getTimeout();if(E==0){continue;}if(E==null){E=G;}B=C-F._start;if(B>E){this.warn("Timeout: transport "+F.toHashCode());this.warn(B+"ms > "+E+"ms");F.timeout();}}}},_applyEnabled:function(I,J){if(I){this._check();}this.__pe.setEnabled(I);},add:function(K){K.setState(a);if(K.isAsynchronous()){this.__pb.push(K);}else{this.__pb.unshift(K);}this._check();if(this.getEnabled()){this.__pe.start();}},abort:function(L){var M=L.getTransport();if(M){M.abort();}else if(qx.lang.Array.contains(this.__pb,L)){qx.lang.Array.remove(this.__pb,L);}}},destruct:function(){this._disposeArray(l);this._disposeObjects(j);this.__pb=null;}});})();(function(){var o="failed",n="sending",m="completed",k="receiving",j="aborted",h="timeout",g="qx.event.type.Event",f="Connection dropped",d="qx.io.remote.Response",c="=",bp="configured",bo="&",bn="Unknown status code. ",bm="qx.io.remote.transport.XmlHttp",bl="qx.io.remote.transport.Abstract",bk="Request-URL too large",bj="MSHTML-specific HTTP status code",bi="Not available",bh="Precondition failed",bg="Server error",v="Moved temporarily",w="qx.io.remote.Exchange",t="Possibly due to a cross-domain request?",u="Bad gateway",r="Gone",s="See other",p="Partial content",q="Server timeout",B="qx.io.remote.transport.Script",C="HTTP version not supported",L="Unauthorized",I="Possibly due to application URL using 'file:' protocol?",T="Multiple choices",O="Payment required",bc="Not implemented",Y="Proxy authentication required",E="Length required",bf="_applyState",be="changeState",bd="Not modified",D="qx.io.remote.Request",G="Connection closed by server",H="Moved permanently",K="_applyImplementation",M="",P="Method not allowed",V="Forbidden",bb="Use proxy",x="Ok",y="Conflict",F="Not found",S="Not acceptable",R="Request time-out",Q="Bad request",X="No content",W="file:",N="qx.io.remote.transport.Iframe",U="Request entity too large",a="Unknown status code",ba="Unsupported media type",z="Gateway time-out",A="created",J="Out of resources",b="undefined";qx.Class.define(w,{extend:qx.core.Object,construct:function(bq){qx.core.Object.call(this);this.setRequest(bq);bq.setTransport(this);},events:{"sending":g,"receiving":g,"completed":d,"aborted":g,"failed":d,"timeout":d},statics:{typesOrder:[bm,N,B],typesReady:false,typesAvailable:{},typesSupported:{},registerType:function(br,bs){qx.io.remote.Exchange.typesAvailable[bs]=br;},initTypes:function(){if(qx.io.remote.Exchange.typesReady){return;}for(var bu in qx.io.remote.Exchange.typesAvailable){var bt=qx.io.remote.Exchange.typesAvailable[bu];if(bt.isSupported()){qx.io.remote.Exchange.typesSupported[bu]=bt;}}qx.io.remote.Exchange.typesReady=true;if(qx.lang.Object.isEmpty(qx.io.remote.Exchange.typesSupported)){throw new Error("No supported transport types were found!");}},canHandle:function(bv,bw,bx){if(!qx.lang.Array.contains(bv.handles.responseTypes,bx)){return false;}for(var by in bw){if(!bv.handles[by]){return false;}}return true;},_nativeMap:{0:A,1:bp,2:n,3:k,4:m},wasSuccessful:function(bz,bA,bB){if(bB){switch(bz){case null:case 0:return true;case -1:return bA<4;default:return typeof bz===b;}}else{switch(bz){case -1:{};return bA<4;case 200:case 304:return true;case 201:case 202:case 203:case 204:case 205:return true;case 206:{};return bA!==4;case 300:case 301:case 302:case 303:case 305:case 400:case 401:case 402:case 403:case 404:case 405:case 406:case 407:case 408:case 409:case 410:case 411:case 412:case 413:case 414:case 415:case 500:case 501:case 502:case 503:case 504:case 505:{};return false;case 12002:case 12007:case 12029:case 12030:case 12031:case 12152:case 13030:{};return false;default:if(bz>206&&bz<300){return true;}qx.log.Logger.debug(this,"Unknown status code: "+bz+" ("+bA+")");return false;}}},statusCodeToString:function(bC){switch(bC){case -1:return bi;case 0:var bD=window.location.href;if(qx.lang.String.startsWith(bD.toLowerCase(),W)){return (bn+I);}else{return (bn+t);}break;case 200:return x;case 304:return bd;case 206:return p;case 204:return X;case 300:return T;case 301:return H;case 302:return v;case 303:return s;case 305:return bb;case 400:return Q;case 401:return L;case 402:return O;case 403:return V;case 404:return F;case 405:return P;case 406:return S;case 407:return Y;case 408:return R;case 409:return y;case 410:return r;case 411:return E;case 412:return bh;case 413:return U;case 414:return bk;case 415:return ba;case 500:return bg;case 501:return bc;case 502:return u;case 503:return J;case 504:return z;case 505:return C;case 12002:return q;case 12029:return f;case 12030:return f;case 12031:return f;case 12152:return G;case 13030:return bj;default:return a;}}},properties:{request:{check:D,nullable:true},implementation:{check:bl,nullable:true,apply:K},state:{check:[bp,n,k,m,j,h,o],init:bp,event:be,apply:bf}},members:{send:function(){var bH=this.getRequest();if(!bH){return this.error("Please attach a request object first");}qx.io.remote.Exchange.initTypes();var bF=qx.io.remote.Exchange.typesOrder;var bE=qx.io.remote.Exchange.typesSupported;var bJ=bH.getResponseType();var bK={};if(bH.getAsynchronous()){bK.asynchronous=true;}else{bK.synchronous=true;}if(bH.getCrossDomain()){bK.crossDomain=true;}if(bH.getFileUpload()){bK.fileUpload=true;}for(var bI in bH.getFormFields()){bK.programaticFormFields=true;break;}var bL,bG;for(var i=0,l=bF.length;i<l;i++){bL=bE[bF[i]];if(bL){if(!qx.io.remote.Exchange.canHandle(bL,bK,bJ)){continue;}try{{};bG=new bL;this.setImplementation(bG);bG.setUseBasicHttpAuth(bH.getUseBasicHttpAuth());bG.send();return true;}catch(bM){this.error("Request handler throws error");this.error(bM);return;}}}this.error("There is no transport implementation available to handle this request: "+bH);},abort:function(){var bN=this.getImplementation();if(bN){{};bN.abort();}else{{};this.setState(j);}},timeout:function(){var bQ=this.getImplementation();if(bQ){var bP=M;for(var bO in bQ.getParameters()){bP+=bo+bO+c+bQ.getParameters()[bO];}this.warn("Timeout: implementation "+bQ.toHashCode()+", "+bQ.getUrl()+" ["+bQ.getMethod()+"], "+bP);bQ.timeout();}else{this.warn("Timeout: forcing state to timeout");this.setState(h);}this.__rx();},__rx:function(){var bR=this.getRequest();if(bR){bR.setTimeout(0);}},_onsending:function(e){this.setState(n);},_onreceiving:function(e){this.setState(k);},_oncompleted:function(e){this.setState(m);},_onabort:function(e){this.setState(j);},_onfailed:function(e){this.setState(o);},_ontimeout:function(e){this.setState(h);},_applyImplementation:function(bS,bT){if(bT){bT.removeListener(n,this._onsending,this);bT.removeListener(k,this._onreceiving,this);bT.removeListener(m,this._oncompleted,this);bT.removeListener(j,this._onabort,this);bT.removeListener(h,this._ontimeout,this);bT.removeListener(o,this._onfailed,this);}if(bS){var bV=this.getRequest();bS.setUrl(bV.getUrl());bS.setMethod(bV.getMethod());bS.setAsynchronous(bV.getAsynchronous());bS.setUsername(bV.getUsername());bS.setPassword(bV.getPassword());bS.setParameters(bV.getParameters(false));bS.setFormFields(bV.getFormFields());bS.setRequestHeaders(bV.getRequestHeaders());if(bS instanceof qx.io.remote.transport.XmlHttp){bS.setParseJson(bV.getParseJson());}var bY=bV.getData();if(bY===null){var ca=bV.getParameters(true);var bX=[];for(var bU in ca){var bW=ca[bU];if(bW instanceof Array){for(var i=0;i<bW.length;i++){bX.push(encodeURIComponent(bU)+c+encodeURIComponent(bW[i]));}}else{bX.push(encodeURIComponent(bU)+c+encodeURIComponent(bW));}}if(bX.length>0){bS.setData(bX.join(bo));}}else{bS.setData(bY);}bS.setResponseType(bV.getResponseType());bS.addListener(n,this._onsending,this);bS.addListener(k,this._onreceiving,this);bS.addListener(m,this._oncompleted,this);bS.addListener(j,this._onabort,this);bS.addListener(h,this._ontimeout,this);bS.addListener(o,this._onfailed,this);}},_applyState:function(cb,cc){{};switch(cb){case n:this.fireEvent(n);break;case k:this.fireEvent(k);break;case m:case j:case h:case o:var ce=this.getImplementation();if(!ce){break;}this.__rx();if(this.hasListener(cb)){var cf=qx.event.Registration.createEvent(cb,qx.io.remote.Response);if(cb==m){var cd=ce.getResponseContent();cf.setContent(cd);if(cd===null){{};cb=o;}}else if(cb==o){cf.setContent(ce.getResponseContent());}cf.setStatusCode(ce.getStatusCode());cf.setResponseHeaders(ce.getResponseHeaders());this.dispatchEvent(cf);}this.setImplementation(null);ce.dispose();break;}}},settings:{"qx.ioRemoteDebug":false,"qx.ioRemoteDebugData":false},destruct:function(){var cg=this.getImplementation();if(cg){this.setImplementation(null);cg.dispose();}this.setRequest(null);}});})();(function(){var q="qx.event.type.Event",p="String",o="failed",n="timeout",m="created",l="aborted",k="sending",j="configured",i="receiving",h="completed",c="Object",g="Boolean",f="abstract",b="_applyState",a="GET",e="changeState",d="qx.io.remote.transport.Abstract";qx.Class.define(d,{type:f,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);this.setRequestHeaders({});this.setParameters({});this.setFormFields({});},events:{"created":q,"configured":q,"sending":q,"receiving":q,"completed":q,"aborted":q,"failed":q,"timeout":q},properties:{url:{check:p,nullable:true},method:{check:p,nullable:true,init:a},asynchronous:{check:g,nullable:true,init:true},data:{check:p,nullable:true},username:{check:p,nullable:true},password:{check:p,nullable:true},state:{check:[m,j,k,i,h,l,n,o],init:m,event:e,apply:b},requestHeaders:{check:c,nullable:true},parameters:{check:c,nullable:true},formFields:{check:c,nullable:true},responseType:{check:p,nullable:true},useBasicHttpAuth:{check:g,nullable:true}},members:{send:function(){throw new Error("send is abstract");},abort:function(){{};this.setState(l);},timeout:function(){{};this.setState(n);},failed:function(){{};this.setState(o);},setRequestHeader:function(r,s){throw new Error("setRequestHeader is abstract");},getResponseHeader:function(t){throw new Error("getResponseHeader is abstract");},getResponseHeaders:function(){throw new Error("getResponseHeaders is abstract");},getStatusCode:function(){throw new Error("getStatusCode is abstract");},getStatusText:function(){throw new Error("getStatusText is abstract");},getResponseText:function(){throw new Error("getResponseText is abstract");},getResponseXml:function(){throw new Error("getResponseXml is abstract");},getFetchedLength:function(){throw new Error("getFetchedLength is abstract");},_applyState:function(u,v){{};switch(u){case m:this.fireEvent(m);break;case j:this.fireEvent(j);break;case k:this.fireEvent(k);break;case i:this.fireEvent(i);break;case h:this.fireEvent(h);break;case l:this.fireEvent(l);break;case o:this.fireEvent(o);break;case n:this.fireEvent(n);break;}return true;}},destruct:function(){this.setRequestHeaders(null);this.setParameters(null);this.setFormFields(null);}});})();(function(){var l="=",k="",j="&",h="application/xml",g="application/json",f="text/html",d="qx.client",c="textarea",b="_data_",a="load",G="text/plain",F="text/javascript",E="completed",D="readystatechange",C="?",B="qx.io.remote.transport.Iframe",A="none",z="display",y="gecko",x="frame_",s="aborted",t="pre",q="javascript:void(0)",r="sending",o="form",p="failed",m="mshtml",n="form_",u="opera",v="timeout",w="qx/static/blank.gif";qx.Class.define(B,{extend:qx.io.remote.transport.Abstract,construct:function(){qx.io.remote.transport.Abstract.call(this);var H=(new Date).valueOf();var I=x+H;var J=n+H;var K;if(qx.core.Variant.isSet(d,m)){K=q;}this.__oh=qx.bom.Iframe.create({id:I,name:I,src:K});qx.bom.element.Style.set(this.__oh,z,A);this.__oi=qx.bom.Element.create(o,{id:J,name:J,target:I});qx.bom.element.Style.set(this.__oi,z,A);qx.dom.Element.insertEnd(this.__oi,qx.dom.Node.getBodyElement(document));this.__oj=qx.bom.Element.create(c,{id:b,name:b});qx.dom.Element.insertEnd(this.__oj,this.__oi);qx.dom.Element.insertEnd(this.__oh,qx.dom.Node.getBodyElement(document));qx.event.Registration.addListener(this.__oh,a,this._onload,this);this.__ok=qx.lang.Function.listener(this._onreadystatechange,this);qx.bom.Event.addNativeListener(this.__oh,D,this.__ok);},statics:{handles:{synchronous:false,asynchronous:true,crossDomain:false,fileUpload:true,programaticFormFields:true,responseTypes:[G,F,g,h,f]},isSupported:function(){return true;},_numericMap:{"uninitialized":1,"loading":2,"loaded":2,"interactive":3,"complete":4}},members:{__oj:null,__ol:0,__oi:null,__oh:null,__ok:null,send:function(){var M=this.getMethod();var O=this.getUrl();var S=this.getParameters(false);var R=[];for(var N in S){var P=S[N];if(P instanceof Array){for(var i=0;i<P.length;i++){R.push(encodeURIComponent(N)+l+encodeURIComponent(P[i]));}}else{R.push(encodeURIComponent(N)+l+encodeURIComponent(P));}}if(R.length>0){O+=(O.indexOf(C)>=0?j:C)+R.join(j);}if(this.getData()===null){var S=this.getParameters(true);var R=[];for(var N in S){var P=S[N];if(P instanceof Array){for(var i=0;i<P.length;i++){R.push(encodeURIComponent(N)+l+encodeURIComponent(P[i]));}}else{R.push(encodeURIComponent(N)+l+encodeURIComponent(P));}}if(R.length>0){this.setData(R.join(j));}}var L=this.getFormFields();for(var N in L){var Q=document.createElement(c);Q.name=N;Q.appendChild(document.createTextNode(L[N]));this.__oi.appendChild(Q);}this.__oi.action=O;this.__oi.method=M;this.__oj.appendChild(document.createTextNode(this.getData()));this.__oi.submit();this.setState(r);},_onload:qx.event.GlobalError.observeMethod(function(e){if(qx.bom.client.Engine.NAME==u&&this.getIframeHtmlContent()==k){return;}if(this.__oi.src){return;}this._switchReadyState(qx.io.remote.transport.Iframe._numericMap.complete);}),_onreadystatechange:qx.event.GlobalError.observeMethod(function(e){this._switchReadyState(qx.io.remote.transport.Iframe._numericMap[this.__oh.readyState]);}),_switchReadyState:function(T){switch(this.getState()){case E:case s:case p:case v:this.warn("Ignore Ready State Change");return;}while(this.__ol<T){this.setState(qx.io.remote.Exchange._nativeMap[++this.__ol]);}},setRequestHeader:function(U,V){},getResponseHeader:function(W){return null;},getResponseHeaders:function(){return {};},getStatusCode:function(){return 200;},getStatusText:function(){return k;},getIframeWindow:function(){return qx.bom.Iframe.getWindow(this.__oh);},getIframeDocument:function(){return qx.bom.Iframe.getDocument(this.__oh);},getIframeBody:function(){return qx.bom.Iframe.getBody(this.__oh);},getIframeTextContent:function(){var X=this.getIframeBody();if(!X){return null;}if(!X.firstChild){return k;}if(X.firstChild.tagName&&X.firstChild.tagName.toLowerCase()==t){return X.firstChild.innerHTML;}else{return X.innerHTML;}},getIframeHtmlContent:function(){var Y=this.getIframeBody();return Y?Y.innerHTML:null;},getFetchedLength:function(){return 0;},getResponseContent:function(){if(this.getState()!==E){{};return null;}{};var ba=this.getIframeTextContent();switch(this.getResponseType()){case G:{};return ba;break;case f:ba=this.getIframeHtmlContent();{};return ba;break;case g:ba=this.getIframeHtmlContent();{};try{return ba&&ba.length>0?qx.util.Json.parse(ba,false):null;}catch(bb){return this.error("Could not execute json: ("+ba+")",bb);}case F:ba=this.getIframeHtmlContent();{};try{return ba&&ba.length>0?window.eval(ba):null;}catch(bc){return this.error("Could not execute javascript: ("+ba+")",bc);}case h:ba=this.getIframeDocument();{};return ba;default:this.warn("No valid responseType specified ("+this.getResponseType()+")!");return null;}}},defer:function(){qx.io.remote.Exchange.registerType(qx.io.remote.transport.Iframe,B);},destruct:function(){if(this.__oh){qx.event.Registration.removeListener(this.__oh,a,this._onload,this);qx.bom.Event.removeNativeListener(this.__oh,D,this.__ok);if(qx.core.Variant.isSet(d,y)){this.__oh.src=qx.util.ResourceManager.getInstance().toUri(w);}qx.dom.Element.remove(this.__oh);}if(this.__oi){qx.dom.Element.remove(this.__oi);}this.__oh=this.__oi=this.__oj=null;}});})();(function(){var c="qx.event.handler.Iframe",b="load",a="iframe";qx.Class.define(c,{extend:qx.core.Object,implement:qx.event.IEventHandler,statics:{PRIORITY:qx.event.Registration.PRIORITY_NORMAL,SUPPORTED_TYPES:{load:1},TARGET_CHECK:qx.event.IEventHandler.TARGET_DOMNODE,IGNORE_CAN_HANDLE:false,onevent:qx.event.GlobalError.observeMethod(function(d){qx.event.Registration.fireEvent(d,b);})},members:{canHandleEvent:function(e,f){return e.tagName.toLowerCase()===a;},registerEvent:function(g,h,i){},unregisterEvent:function(j,k,l){}},defer:function(m){qx.event.Registration.addHandler(m);}});})();(function(){var e="qx.client",d="webkit",c="body",b="iframe",a="qx.bom.Iframe";qx.Class.define(a,{statics:{DEFAULT_ATTRIBUTES:{onload:"qx.event.handler.Iframe.onevent(this)",frameBorder:0,frameSpacing:0,marginWidth:0,marginHeight:0,hspace:0,vspace:0,border:0,allowTransparency:true},create:function(f,g){var f=f?qx.lang.Object.clone(f):{};var h=qx.bom.Iframe.DEFAULT_ATTRIBUTES;for(var i in h){if(f[i]==null){f[i]=h[i];}}return qx.bom.Element.create(b,f,g);},getWindow:qx.core.Variant.select(e,{"mshtml|gecko":function(j){try{return j.contentWindow;}catch(k){return null;}},"default":function(l){try{var m=this.getDocument(l);return m?m.defaultView:null;}catch(n){return null;}}}),getDocument:qx.core.Variant.select(e,{"mshtml":function(o){try{var p=this.getWindow(o);return p?p.document:null;}catch(q){return null;}},"default":function(r){try{return r.contentDocument;}catch(s){return null;}}}),getBody:function(t){try{var u=this.getDocument(t);return u?u.getElementsByTagName(c)[0]:null;}catch(v){return null;}},setSource:function(w,x){try{if(this.getWindow(w)&&qx.dom.Hierarchy.isRendered(w)){try{if(qx.core.Variant.isSet(e,d)&&qx.bom.client.Platform.MAC){var y=this.getContentWindow();if(y){y.stop();}}this.getWindow(w).location.replace(x);}catch(z){w.src=x;}}else{w.src=x;}}catch(A){qx.log.Logger.warn("Iframe source could not be set!");}},queryCurrentUrl:function(B){var C=this.getDocument(B);try{if(C&&C.location){return C.location.href;}}catch(D){}return null;}}});})();(function(){var a="qx.dom.Element";qx.Class.define(a,{statics:{hasChild:function(parent,b){return b.parentNode===parent;},hasChildren:function(c){return !!c.firstChild;},hasChildElements:function(d){d=d.firstChild;while(d){if(d.nodeType===1){return true;}d=d.nextSibling;}return false;},getParentElement:function(e){return e.parentNode;},isInDom:function(f,g){if(!g){g=window;}var h=g.document.getElementsByTagName(f.nodeName);for(var i=0,l=h.length;i<l;i++){if(h[i]===f){return true;}}return false;},insertAt:function(j,parent,k){var m=parent.childNodes[k];if(m){parent.insertBefore(j,m);}else{parent.appendChild(j);}return true;},insertBegin:function(n,parent){if(parent.firstChild){this.insertBefore(n,parent.firstChild);}else{parent.appendChild(n);}},insertEnd:function(o,parent){parent.appendChild(o);},insertBefore:function(p,q){q.parentNode.insertBefore(p,q);return true;},insertAfter:function(r,s){var parent=s.parentNode;if(s==parent.lastChild){parent.appendChild(r);}else{return this.insertBefore(r,s.nextSibling);}return true;},remove:function(t){if(!t.parentNode){return false;}t.parentNode.removeChild(t);return true;},removeChild:function(u,parent){if(u.parentNode!==parent){return false;}parent.removeChild(u);return true;},removeChildAt:function(v,parent){var w=parent.childNodes[v];if(!w){return false;}parent.removeChild(w);return true;},replaceChild:function(x,y){if(!y.parentNode){return false;}y.parentNode.replaceChild(x,y);return true;},replaceAt:function(z,A,parent){var B=parent.childNodes[A];if(!B){return false;}parent.replaceChild(z,B);return true;}}});})();(function(){var r="&",q="=",p="?",o="application/json",n="completed",m="text/plain",l="text/javascript",k="qx.io.remote.transport.Script",j="",h="_ScriptTransport_data",c="script",g="timeout",f="_ScriptTransport_",b="_ScriptTransport_id",a="aborted",e="utf-8",d="failed";qx.Class.define(k,{extend:qx.io.remote.transport.Abstract,construct:function(){qx.io.remote.transport.Abstract.call(this);var s=++qx.io.remote.transport.Script.__pg;if(s>=2000000000){qx.io.remote.transport.Script.__pg=s=1;}this.__ph=null;this.__pg=s;},statics:{__pg:0,_instanceRegistry:{},ScriptTransport_PREFIX:f,ScriptTransport_ID_PARAM:b,ScriptTransport_DATA_PARAM:h,handles:{synchronous:false,asynchronous:true,crossDomain:true,fileUpload:false,programaticFormFields:false,responseTypes:[m,l,o]},isSupported:function(){return true;},_numericMap:{"uninitialized":1,"loading":2,"loaded":2,"interactive":3,"complete":4},_requestFinished:qx.event.GlobalError.observeMethod(function(t,content){var u=qx.io.remote.transport.Script._instanceRegistry[t];if(u==null){{};}else{u._responseContent=content;u._switchReadyState(qx.io.remote.transport.Script._numericMap.complete);}})},members:{__pi:0,__ph:null,__pg:null,send:function(){var x=this.getUrl();x+=(x.indexOf(p)>=0?r:p)+qx.io.remote.transport.Script.ScriptTransport_ID_PARAM+q+this.__pg;var A=this.getParameters();var z=[];for(var w in A){if(w.indexOf(qx.io.remote.transport.Script.ScriptTransport_PREFIX)==0){this.error("Illegal parameter name. The following prefix is used internally by qooxdoo): "+qx.io.remote.transport.Script.ScriptTransport_PREFIX);}var y=A[w];if(y instanceof Array){for(var i=0;i<y.length;i++){z.push(encodeURIComponent(w)+q+encodeURIComponent(y[i]));}}else{z.push(encodeURIComponent(w)+q+encodeURIComponent(y));}}if(z.length>0){x+=r+z.join(r);}var v=this.getData();if(v!=null){x+=r+qx.io.remote.transport.Script.ScriptTransport_DATA_PARAM+q+encodeURIComponent(v);}qx.io.remote.transport.Script._instanceRegistry[this.__pg]=this;this.__ph=document.createElement(c);this.__ph.charset=e;this.__ph.src=x;{};document.body.appendChild(this.__ph);},_switchReadyState:function(B){switch(this.getState()){case n:case a:case d:case g:this.warn("Ignore Ready State Change");return;}while(this.__pi<B){this.setState(qx.io.remote.Exchange._nativeMap[++this.__pi]);}},setRequestHeader:function(C,D){},getResponseHeader:function(E){return null;},getResponseHeaders:function(){return {};},getStatusCode:function(){return 200;},getStatusText:function(){return j;},getFetchedLength:function(){return 0;},getResponseContent:function(){if(this.getState()!==n){{};return null;}{};switch(this.getResponseType()){case m:case o:case l:{};var F=this._responseContent;return (F===0?0:(F||null));default:this.warn("No valid responseType specified ("+this.getResponseType()+")!");return null;}}},defer:function(){qx.io.remote.Exchange.registerType(qx.io.remote.transport.Script,k);},destruct:function(){if(this.__ph){delete qx.io.remote.transport.Script._instanceRegistry[this.__pg];document.body.removeChild(this.__ph);}this.__ph=this._responseContent=null;}});})();(function(){var m="failed",k="completed",j="=",h="aborted",g="",f="sending",d="&",c="configured",b="timeout",a="application/xml",J="qx.io.remote.transport.XmlHttp",I="application/json",H="text/html",G="qx.client",F="receiving",E="text/plain",D="text/javascript",C="?",B="created",A="Boolean",u='Referer',v='Basic ',r="\n</pre>",t="string",p='Authorization',q="<pre>Could not execute json: \n",n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",o=':',w="parseerror",x="file:",z="webkit",y="object";qx.Class.define(J,{extend:qx.io.remote.transport.Abstract,statics:{handles:{synchronous:true,asynchronous:true,crossDomain:false,fileUpload:false,programaticFormFields:false,responseTypes:[E,D,I,a,H]},requestObjects:[],requestObjectCount:0,createRequestObject:qx.core.Variant.select(G,{"default":function(){return new XMLHttpRequest;},"mshtml":function(){if(window.ActiveXObject&&qx.xml.Document.XMLHTTP){return new ActiveXObject(qx.xml.Document.XMLHTTP);}if(window.XMLHttpRequest){return new XMLHttpRequest;}}}),isSupported:function(){return !!this.createRequestObject();}},properties:{parseJson:{check:A,init:true}},members:{__nh:false,__ni:0,__nj:null,getRequest:function(){if(this.__nj===null){this.__nj=qx.io.remote.transport.XmlHttp.createRequestObject();this.__nj.onreadystatechange=qx.lang.Function.bind(this._onreadystatechange,this);}return this.__nj;},send:function(){this.__ni=0;var O=this.getRequest();var K=this.getMethod();var R=this.getAsynchronous();var Q=this.getUrl();var M=(window.location.protocol===x&&!(/^http(s){0,1}\:/.test(Q)));this.__nh=M;var U=this.getParameters(false);var S=[];for(var L in U){var P=U[L];if(P instanceof Array){for(var i=0;i<P.length;i++){S.push(encodeURIComponent(L)+j+encodeURIComponent(P[i]));}}else{S.push(encodeURIComponent(L)+j+encodeURIComponent(P));}}if(S.length>0){Q+=(Q.indexOf(C)>=0?d:C)+S.join(d);}if(this.getData()===null){var U=this.getParameters(true);var S=[];for(var L in U){var P=U[L];if(P instanceof Array){for(var i=0;i<P.length;i++){S.push(encodeURIComponent(L)+j+encodeURIComponent(P[i]));}}else{S.push(encodeURIComponent(L)+j+encodeURIComponent(P));}}if(S.length>0){this.setData(S.join(d));}}var T=function(V){var bb=n;var bf=g;var Y,X,W;var bc,bd,be,ba;var i=0;do{Y=V.charCodeAt(i++);X=V.charCodeAt(i++);W=V.charCodeAt(i++);bc=Y>>2;bd=((Y&3)<<4)|(X>>4);be=((X&15)<<2)|(W>>6);ba=W&63;if(isNaN(X)){be=ba=64;}else if(isNaN(W)){ba=64;}bf+=bb.charAt(bc)+bb.charAt(bd)+bb.charAt(be)+bb.charAt(ba);}while(i<V.length);return bf;};try{if(this.getUsername()){if(this.getUseBasicHttpAuth()){O.open(K,Q,R);O.setRequestHeader(p,v+T(this.getUsername()+o+this.getPassword()));}else{O.open(K,Q,R,this.getUsername(),this.getPassword());}}else{O.open(K,Q,R);}}catch(bg){this.error("Failed with exception: "+bg);this.failed();return;}if(!qx.core.Variant.isSet(G,z)){O.setRequestHeader(u,window.location.href);}var N=this.getRequestHeaders();for(var L in N){O.setRequestHeader(L,N[L]);}try{{};O.send(this.getData());}catch(bh){if(M){this.failedLocally();}else{this.error("Failed to send data: "+bh,"send");this.failed();}return;}if(!R){this._onreadystatechange();}},failedLocally:function(){if(this.getState()===m){return;}this.warn("Could not load from file: "+this.getUrl());this.failed();},_onreadystatechange:qx.event.GlobalError.observeMethod(function(e){switch(this.getState()){case k:case h:case m:case b:{};return;}var bi=this.getReadyState();if(bi==4){if(!qx.io.remote.Exchange.wasSuccessful(this.getStatusCode(),bi,this.__nh)){if(this.getState()===c){this.setState(f);}this.failed();return;}}while(this.__ni<bi){this.setState(qx.io.remote.Exchange._nativeMap[++this.__ni]);}}),getReadyState:function(){var bj=null;try{bj=this.getRequest().readyState;}catch(bk){}return bj;},setRequestHeader:function(bl,bm){this.getRequestHeaders()[bl]=bm;},getResponseHeader:function(bn){var bo=null;try{bo=this.getRequest().getResponseHeader(bn)||null;}catch(bp){}return bo;},getStringResponseHeaders:function(){var br=null;try{var bq=this.getRequest().getAllResponseHeaders();if(bq){br=bq;}}catch(bs){}return br;},getResponseHeaders:function(){var bv=this.getStringResponseHeaders();var bw={};if(bv){var bt=bv.split(/[\r\n]+/g);for(var i=0,l=bt.length;i<l;i++){var bu=bt[i].match(/^([^:]+)\s*:\s*(.+)$/i);if(bu){bw[bu[1]]=bu[2];}}}return bw;},getStatusCode:function(){var bx=-1;try{bx=this.getRequest().status;}catch(by){}return bx;},getStatusText:function(){var bz=g;try{bz=this.getRequest().statusText;}catch(bA){}return bz;},getResponseText:function(){var bB=null;try{bB=this.getRequest().responseText;}catch(bC){bB=null;}return bB;},getResponseXml:function(){var bF=null;var bD=this.getStatusCode();var bE=this.getReadyState();if(qx.io.remote.Exchange.wasSuccessful(bD,bE,this.__nh)){try{bF=this.getRequest().responseXML;}catch(bG){}}if(typeof bF==y&&bF!=null){if(!bF.documentElement){var s=String(this.getRequest().responseText).replace(/<\?xml[^\?]*\?>/,g);bF.loadXML(s);}if(!bF.documentElement){throw new Error("Missing Document Element!");}if(bF.documentElement.tagName==w){throw new Error("XML-File is not well-formed!");}}else{throw new Error("Response was not a valid xml document ["+this.getRequest().responseText+"]");}return bF;},getFetchedLength:function(){var bH=this.getResponseText();return typeof bH==t?bH.length:0;},getResponseContent:function(){var bI=this.getState();if(bI!==k&&bI!=m){{};return null;}{};var bK=this.getResponseText();if(bI==m){{};return bK;}switch(this.getResponseType()){case E:case H:{};return bK;case I:{};try{if(bK&&bK.length>0){var bJ;if(this.getParseJson()){bJ=qx.util.Json.parse(bK,false);bJ=(bJ===0?0:(bJ||null));}else{bJ=bK;}return bJ;}else{return null;}}catch(bL){this.error("Could not execute json: ["+bK+"]",bL);return q+bK+r;}case D:{};try{if(bK&&bK.length>0){var bJ=window.eval(bK);return (bJ===0?0:(bJ||null));}else{return null;}}catch(bM){this.error("Could not execute javascript: ["+bK+"]",bM);return null;}case a:bK=this.getResponseXml();{};return (bK===0?0:(bK||null));default:this.warn("No valid responseType specified ("+this.getResponseType()+")!");return null;}},_applyState:function(bN,bO){{};switch(bN){case B:this.fireEvent(B);break;case c:this.fireEvent(c);break;case f:this.fireEvent(f);break;case F:this.fireEvent(F);break;case k:this.fireEvent(k);break;case m:this.fireEvent(m);break;case h:this.getRequest().abort();this.fireEvent(h);break;case b:this.getRequest().abort();this.fireEvent(b);break;}}},defer:function(){qx.io.remote.Exchange.registerType(qx.io.remote.transport.XmlHttp,J);},destruct:function(){var bP=this.getRequest();if(bP){bP.onreadystatechange=qx.lang.Function.empty;switch(bP.readyState){case 1:case 2:case 3:bP.abort();}}this.__nj=null;}});})();(function(){var c="Integer",b="Object",a="qx.io.remote.Response";qx.Class.define(a,{extend:qx.event.type.Event,properties:{state:{check:c,nullable:true},statusCode:{check:c,nullable:true},content:{nullable:true},responseHeaders:{check:b,nullable:true}},members:{clone:function(d){var e=qx.event.type.Event.prototype.clone.call(this,d);e.setType(this.getType());e.setState(this.getState());e.setStatusCode(this.getStatusCode());e.setContent(this.getContent());e.setResponseHeaders(this.getResponseHeaders());return e;},getResponseHeader:function(f){var g=this.getResponseHeaders();if(g){return g[f]||null;}return null;}}});})();(function(){var b="pane",a="qx.ui.container.Scroll";qx.Class.define(a,{extend:qx.ui.core.scroll.AbstractScrollArea,include:[qx.ui.core.MContentPadding],construct:function(content){qx.ui.core.scroll.AbstractScrollArea.call(this);if(content){this.add(content);}},members:{add:function(c){this.getChildControl(b).add(c);},remove:function(d){this.getChildControl(b).remove(d);},getChildren:function(){return this.getChildControl(b).getChildren();},_getContentPaddingTarget:function(){return this.getChildControl(b);}}});})();(function(){var k="legendview-label-important",j="Package/Class/Mixin/Interface is not fully documented",h="ICON_PROPERTY_PUB",g="Themeable Property",f="Child Control",e="ICON_CLASS_SINGLETON",d="Public Property",c="Private Method",b="Public Method",a="ICON_CHILDCONTROL",bd="string",bc="ICON_INTERFACE",bb='<span style="text-decoration: line-through;color: #7193b9;">deprecated</span>',ba="center",Y="ICON_EVENT",X="apiviewer.ui.LegendView",W="Singleton Class",V="Private Property",U="OVERLAY_WARN",T="ICON_PACKAGE",r="Method/Property/Event is inherited from one of the super classes",s="legend",p="ICON_PROPERTY_PRIV",q="middle",n="ICON_BLANK",o="__Tb",l="ICON_PROPERTY_PROT",m="ICON_CLASS_ABSTRACT",v="ICON_CLASS",w="ICON_PROPERTY_PUB_THEMEABLE",E="Protected Method",C="Constant",L="Method/Property/Event is not fully documented",G="OVERLAY_OVERRIDDEN",P="Abstract Class",N="OVERLAY_MIXIN",y="Class",S="Interface",R="ICON_METHOD_PUB",Q="Event",x="Mixin",A="Package",B="Protected Property",D="OVERLAY_ERROR",F="ICON_MIXIN",H="legendview-label",M="ICON_CLASS_STATIC",O="Method/Property overrides the Method/Property of the super class",t="ICON_METHOD_PRIV",u="Static Class",z="Method/Property is included from a mixin",K="ICON_METHOD_PROT",J="OVERLAY_INHERITED",I="ICON_CONSTANT";qx.Class.define(X,{extend:qx.ui.container.Scroll,construct:function(){qx.ui.container.Scroll.call(this);this.setAppearance(s);var be=new qx.ui.layout.Grid(10,10);be.setColumnWidth(1,150);be.setColumnFlex(1,1);var content=new qx.ui.container.Composite(be);this.__Tb=[{icon:T,desc:A},{icon:v,desc:y},{icon:M,desc:u},{icon:m,desc:P},{icon:e,desc:W},{icon:bc,desc:S},{icon:F,desc:x},{icon:a,desc:f},{icon:R,desc:b},{icon:K,desc:E},{icon:t,desc:c},{icon:h,desc:d},{icon:l,desc:B},{icon:p,desc:V},{icon:w,desc:g},{icon:Y,desc:Q},{icon:I,desc:C},{icon:n,desc:bb},{icon:U,desc:j},{icon:D,desc:L},{icon:N,desc:z},{icon:J,desc:r},{icon:G,desc:O}];var length=this.__Tb.length;var bg,bf;for(var i=0;i<length;i++){bg=this.__Tb[i];bf=apiviewer.TreeUtil.iconNameToIconPath(bg.icon);if(typeof (bf)!=bd){bf=bf[0];}content.add(new qx.ui.basic.Image(bf).set({alignX:ba,alignY:q}),{row:i,column:0});content.add(new qx.ui.basic.Label(bg.desc).set({rich:true,appearance:(i<17)?k:H}),{row:i,column:1});}this.add(content);},members:{__Tb:null},destruct:function(){this._disposeMap(o);}});})();(function(){var d="_applyDynamic",c="changeSelection",b="Boolean",a="qx.ui.container.Stack";qx.Class.define(a,{extend:qx.ui.core.Widget,implement:qx.ui.core.ISingleSelection,include:qx.ui.core.MSingleSelectionHandling,construct:function(){qx.ui.core.Widget.call(this);this._setLayout(new qx.ui.layout.Grow);this.addListener(c,this.__nu,this);},properties:{dynamic:{check:b,init:false,apply:d}},members:{_applyDynamic:function(f){var h=this._getChildren();var g=this.getSelection()[0];var j;for(var i=0,l=h.length;i<l;i++){j=h[i];if(j!=g){if(f){h[i].exclude();}else{h[i].hide();}}}},_getItems:function(){return this.getChildren();},_isAllowEmptySelection:function(){return true;},_isItemSelectable:function(k){return true;},__nu:function(e){var m=e.getOldData()[0];var n=e.getData()[0];if(m){if(this.isDynamic()){m.exclude();}else{m.hide();}}if(n){n.show();}},add:function(o){this._add(o);var p=this.getSelection()[0];if(!p){this.setSelection([o]);}else if(p!==o){if(this.isDynamic()){o.exclude();}else{o.hide();}}},remove:function(q){this._remove(q);if(this.getSelection()[0]===q){var r=this._getChildren()[0];if(r){this.setSelection([r]);}else{this.resetSelection();}}},indexOf:function(s){return this._indexOf(s);},getChildren:function(){return this._getChildren();},previous:function(){var v=this.getSelection()[0];var t=this._indexOf(v)-1;var w=this._getChildren();if(t<0){t=w.length-1;}var u=w[t];this.setSelection([u]);},next:function(){var y=this.getSelection()[0];var x=this._indexOf(y)+1;var z=this._getChildren();var A=z[x]||z[0];this.setSelection([A]);}}});})();(function(){var k="pressed",j="abandoned",i="hovered",h="Boolean",g="Space",f="undetermined",d="Enter",c="checked",b="mousedown",a="_applyTriState",w="mouseout",v="changeValue",u="keydown",t="_applyGroup",s="button",r="execute",q="qx.ui.form.RadioGroup",p="_applyValue",o="qx.ui.form.ToggleButton",n="mouseover",l="keyup",m="mouseup";qx.Class.define(o,{extend:qx.ui.basic.Atom,include:[qx.ui.core.MExecutable],implement:[qx.ui.form.IBooleanForm,qx.ui.form.IExecutable,qx.ui.form.IRadioItem],construct:function(x,y){qx.ui.basic.Atom.call(this,x,y);this.addListener(n,this._onMouseOver);this.addListener(w,this._onMouseOut);this.addListener(b,this._onMouseDown);this.addListener(m,this._onMouseUp);this.addListener(u,this._onKeyDown);this.addListener(l,this._onKeyUp);this.addListener(r,this._onExecute,this);},properties:{appearance:{refine:true,init:s},focusable:{refine:true,init:true},value:{check:h,nullable:true,event:v,apply:p,init:false},group:{check:q,nullable:true,apply:t},triState:{check:h,apply:a,nullable:true,init:null}},members:{_applyGroup:function(z,A){if(A){A.remove(this);}if(z){z.add(this);}},_applyValue:function(B,C){B?this.addState(c):this.removeState(c);if(this.isTriState()){if(B===null){this.addState(f);}else if(C===null){this.removeState(f);}}},_applyTriState:function(D,E){this._applyValue(this.getValue());},_onExecute:function(e){this.toggleValue();},_onMouseOver:function(e){if(e.getTarget()!==this){return;}this.addState(i);if(this.hasState(j)){this.removeState(j);this.addState(k);}},_onMouseOut:function(e){if(e.getTarget()!==this){return;}this.removeState(i);if(this.hasState(k)){if(!this.getValue()){this.removeState(k);}this.addState(j);}},_onMouseDown:function(e){if(!e.isLeftPressed()){return;}this.capture();this.removeState(j);this.addState(k);e.stopPropagation();},_onMouseUp:function(e){this.releaseCapture();if(this.hasState(j)){this.removeState(j);}else if(this.hasState(k)){this.execute();}this.removeState(k);e.stopPropagation();},_onKeyDown:function(e){switch(e.getKeyIdentifier()){case d:case g:this.removeState(j);this.addState(k);e.stopPropagation();}},_onKeyUp:function(e){if(!this.hasState(k)){return;}switch(e.getKeyIdentifier()){case d:case g:this.removeState(j);this.execute();this.removeState(k);e.stopPropagation();}}}});})();(function(){var e="inherit",d="toolbar-button",c="qx.ui.toolbar.CheckBox",b="keydown",a="keyup";qx.Class.define(c,{extend:qx.ui.form.ToggleButton,construct:function(f,g){qx.ui.form.ToggleButton.call(this,f,g);this.removeListener(b,this._onKeyDown);this.removeListener(a,this._onKeyUp);},properties:{appearance:{refine:true,init:d},show:{refine:true,init:e},focusable:{refine:true,init:false}}});})();(function(){var a="qx.ui.toolbar.RadioButton";qx.Class.define(a,{extend:qx.ui.toolbar.CheckBox,include:[qx.ui.form.MModelProperty],implement:[qx.ui.form.IModel,qx.ui.form.IRadioItem],members:{_applyValue:function(b,c){qx.ui.toolbar.CheckBox.prototype._applyValue.call(this,b,c);if(b){var d=this.getGroup();if(d){d.setSelection([this]);}}},_onExecute:function(e){var f=this.getGroup();if(f&&f.getAllowEmptySelection()||!f){this.toggleValue();}else{this.setValue(true);}}}});})();(function(){var e="arrow",d="qx.ui.toolbar.MenuButton",c="Boolean",b="_applyShowArrow",a="toolbar-menubutton";qx.Class.define(d,{extend:qx.ui.menubar.Button,properties:{appearance:{refine:true,init:a},showArrow:{check:c,init:false,themeable:true,apply:b}},members:{_createChildControlImpl:function(f,g){var h;switch(f){case e:h=new qx.ui.basic.Image();h.setAnonymous(true);this._addAt(h,10);break;}return h||qx.ui.menubar.Button.prototype._createChildControlImpl.call(this,f);},_applyShowArrow:function(i,j){if(i){this._showChildControl(e);}else{this._excludeChildControl(e);}}}});})();(function(){var j="checked",i="qx.ui.form.RadioGroup",h="Boolean",g="menu-radiobutton",f="_applyValue",d="qx.ui.menu.RadioButton",c="changeValue",b="_applyGroup",a="execute";qx.Class.define(d,{extend:qx.ui.menu.AbstractButton,include:[qx.ui.form.MModelProperty],implement:[qx.ui.form.IRadioItem,qx.ui.form.IBooleanForm,qx.ui.form.IModel],construct:function(k,l){qx.ui.menu.AbstractButton.call(this);if(k!=null){this.setLabel(k);}if(l!=null){this.setMenu(l);}this.addListener(a,this._onExecute,this);},properties:{appearance:{refine:true,init:g},value:{check:h,nullable:true,event:c,apply:f,init:false},group:{check:i,nullable:true,apply:b}},members:{_applyValue:function(m,n){m?this.addState(j):this.removeState(j);},_applyGroup:function(o,p){if(p){p.remove(this);}if(o){o.add(this);}},_onExecute:function(e){this.setValue(true);},_onMouseUp:function(e){if(e.isLeftPressed()){this.execute();}qx.ui.menu.Manager.getInstance().hideAll();},_onKeyPress:function(e){this.execute();}}});})();(function(){var x="pane",w="lastTab",v="page",u="bar",t="firstTab",s="right",r="button",q="bottom",p="left",o="close",f="top",n="changeSelection",j="tabview",c="vertical",b="horizontal",h="_applyBarPosition",g="beforeChangeSelection",k="__DQ",a="qx.ui.tabview.TabView",m="close-button",d="qx.event.type.Data";qx.Class.define(a,{extend:qx.ui.core.Widget,implement:qx.ui.core.ISingleSelection,include:[qx.ui.core.MContentPadding],construct:function(y){qx.ui.core.Widget.call(this);this.__DP={top:"barTop",right:"barRight",bottom:"barBottom",left:"barLeft"};this._createChildControl(u);this._createChildControl(x);var z=this.__DQ=new qx.ui.form.RadioGroup;z.setWrap(false);z.addListener(n,this._onChangeSelection,this);if(y!=null){this.setBarPosition(y);}else{this.initBarPosition();}},events:{"changeSelection":d},properties:{appearance:{refine:true,init:j},barPosition:{check:[p,s,f,q],init:f,apply:h}},members:{__DQ:null,_createChildControlImpl:function(A,B){var C;switch(A){case u:C=new qx.ui.container.SlideBar();C.setZIndex(10);this._add(C);break;case x:C=new qx.ui.container.Stack;C.setZIndex(5);this._add(C,{flex:1});break;}return C||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,A);},_getContentPaddingTarget:function(){return this.getChildControl(x);},add:function(D){{};var E=D.getButton();var F=this.getChildControl(u);var H=this.getChildControl(x);D.exclude();F.add(E);H.add(D);this.__DQ.add(E);D.addState(this.__DP[this.getBarPosition()]);D.addState(w);var G=this.getChildren();if(G[0]==D){D.addState(t);}else{G[G.length-2].removeState(w);}D.addListener(o,this._onPageClose,this);},remove:function(I){var N=this.getChildControl(x);var L=this.getChildControl(u);var K=I.getButton();var M=N.getChildren();if(this.getSelection()[0]==I){var J=M.indexOf(I);if(J==0){if(M[1]){this.setSelection([M[1]]);}else{this.resetSelection();}}else{this.setSelection([M[J-1]]);}}L.remove(K);N.remove(I);this.__DQ.remove(K);I.removeState(this.__DP[this.getBarPosition()]);if(I.hasState(t)){I.removeState(t);if(M[0]){M[0].addState(t);}}if(I.hasState(w)){I.removeState(w);if(M.length>0){M[M.length-1].addState(w);}}I.removeListener(o,this._onPageClose,this);},getChildren:function(){return this.getChildControl(x).getChildren();},indexOf:function(O){return this.getChildControl(x).indexOf(O);},__DP:null,_applyBarPosition:function(P,Q){var R=this.getChildControl(u);var W=P==p||P==s;var U=P==s||P==q;var V=W?qx.ui.layout.HBox:qx.ui.layout.VBox;var Y=this._getLayout();if(Y&&Y instanceof V){}else{this._setLayout(Y=new V);}Y.setReversed(U);R.setOrientation(W?c:b);var X=this.getChildren();if(Q){var S=this.__DP[Q];R.removeState(S);for(var i=0,l=X.length;i<l;i++){X[i].removeState(S);}}if(P){var T=this.__DP[P];R.addState(T);for(var i=0,l=X.length;i<l;i++){X[i].addState(T);}}},getSelection:function(){var ba=this.__DQ.getSelection();var bb=[];for(var i=0;i<ba.length;i++){bb.push(ba[i].getUserData(v));}return bb;},setSelection:function(bc){var bd=[];for(var i=0;i<bc.length;i++){bd.push(bc[i].getChildControl(r));}this.__DQ.setSelection(bd);},resetSelection:function(){this.__DQ.resetSelection();},isSelected:function(be){var bf=be.getChildControl(r);return this.__DQ.isSelected(bf);},isSelectionEmpty:function(){return this.__DQ.isSelectionEmpty();},getSelectables:function(bg){var bh=this.__DQ.getSelectables(bg);var bi=[];for(var i=0;i<bh.length;i++){bi.push(bh[i].getUserData(v));}return bi;},_onChangeSelection:function(e){var bn=this.getChildControl(x);var bk=e.getData()[0];var bm=e.getOldData()[0];var bj=[];var bl=[];if(bk){bj=[bk.getUserData(v)];bn.setSelection(bj);bk.focus();this.scrollChildIntoView(bk,null,null,false);}else{bn.resetSelection();}if(bm){bl=[bm.getUserData(v)];}this.fireDataEvent(n,bj,bl);},_onBeforeChangeSelection:function(e){if(!this.fireNonBubblingEvent(g,qx.event.type.Event,[false,true])){e.preventDefault();}},_onRadioChangeSelection:function(e){var bo=e.getData()[0];if(bo){this.setSelection([bo.getUserData(v)]);}else{this.resetSelection();}},_onPageClose:function(e){var bq=e.getTarget();var bp=bq.getButton().getChildControl(m);bp.reset();this.remove(bq);}},destruct:function(){this._disposeObjects(k);this.__DP=null;}});})();(function(){var k="slider",j="splitter",i="horizontal",h="px",g="vertical",f="knob",d="mousedown",c="mouseout",b="Integer",a="height",D="mousemove",C="move",B="maxHeight",A="resize",z="width",w="_applyOrientation",v="_applyOffset",u="splitpane",t="qx.ui.splitpane.Pane",s="top",q="minHeight",r="mouseup",o="minWidth",p="appear",m="losecapture",n="left",l="maxWidth";qx.Class.define(t,{extend:qx.ui.core.Widget,construct:function(E){qx.ui.core.Widget.call(this);this.__mT=[];if(E){this.setOrientation(E);}else{this.initOrientation();}this.__nc.addListener(d,this._onMouseDown,this);this.__nc.addListener(r,this._onMouseUp,this);this.__nc.addListener(D,this._onMouseMove,this);this.__nc.addListener(c,this._onMouseOut,this);this.__nc.addListener(m,this._onMouseUp,this);},properties:{appearance:{refine:true,init:u},offset:{check:b,init:6,apply:v},orientation:{init:i,check:[i,g],apply:w}},members:{__mU:null,__mV:false,__mW:null,__mX:null,__mY:null,__na:null,__nb:null,__mT:null,__nc:null,_createChildControlImpl:function(F,G){var H;switch(F){case k:H=new qx.ui.splitpane.Slider(this);H.exclude();this._add(H,{type:F});break;case j:H=new qx.ui.splitpane.Splitter(this);this._add(H,{type:F});H.addListener(C,this.__nd,this);break;}return H||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,F);},__nd:function(e){this.__nf(e.getData());},__ne:function(I){this.__nc=new qx.ui.splitpane.Blocker(I);this.getContentElement().add(this.__nc);var J=this.getChildControl(j);var K=J.getWidth();if(!K){J.addListenerOnce(p,function(){this.__nf();},this);}J.addListener(A,function(e){var L=e.getData();if(L.height==0||L.width==0){this.__nc.hide();}else{this.__nc.show();}},this);},getBlocker:function(){return this.__nc;},_applyOrientation:function(M,N){var O=this.getChildControl(k);var R=this.getChildControl(j);this.__mY=M===i;if(!this.__nc){this.__ne(M);}this.__nc.setOrientation(M);var Q=this._getLayout();if(Q){Q.dispose();}var P=M===g?new qx.ui.splitpane.VLayout:new qx.ui.splitpane.HLayout;this._setLayout(P);R.removeState(N);R.addState(M);R.getChildControl(f).removeState(N);R.getChildControl(f).addState(M);O.removeState(N);O.addState(M);qx.ui.core.queue.Manager.flush();this.__nf();},_applyOffset:function(S,T){this.__nf();},__nf:function(U){var V=this.getChildControl(j);var ba=this.getOffset();var bb=V.getBounds();var Y=V.getContainerElement().getDomElement();if(!Y){return;}if(this.__mY){var X=null;if(U){X=U.width;}else if(bb){X=bb.width;}var bc=U&&U.left;if(X){if(!bc){bc=qx.bom.element.Location.getPosition(Y).left;}this.__nc.setWidth(ba,X);this.__nc.setLeft(ba,bc);}}else{var W=null;if(U){W=U.height;}else if(bb){W=bb.height;}var top=U&&U.top;if(W){if(!top){top=qx.bom.element.Location.getPosition(Y).top;}this.__nc.setHeight(ba,W);this.__nc.setTop(ba,top);}}},add:function(bd,be){if(be==null){this._add(bd);}else{this._add(bd,{flex:be});}this.__mT.push(bd);},remove:function(bf){this._remove(bf);qx.lang.Array.remove(this.__mT,bf);},getChildren:function(){return this.__mT;},_onMouseDown:function(e){if(!e.isLeftPressed()){return;}var bg=this.getChildControl(j);var bi=bg.getContainerLocation();var bh=this.getContentLocation();this.__mU=this.__mY?e.getDocumentLeft()-bi.left+bh.left:e.getDocumentTop()-bi.top+bh.top;var bk=this.getChildControl(k);var bj=bg.getBounds();bk.setUserBounds(bj.left,bj.top,bj.width,bj.height);bk.setZIndex(bg.getZIndex()+1);bk.show();this.__mV=true;this.__nc.capture();e.stop();},_onMouseMove:function(e){this._setLastMousePosition(e.getDocumentLeft(),e.getDocumentTop());if(this.__mV){this.__ng();var bl=this.getChildControl(k);var bm=this.__na;if(this.__mY){bl.setDomLeft(bm);this.__nc.setStyle(n,(bm-this.getOffset())+h);}else{bl.setDomTop(bm);this.__nc.setStyle(s,(bm-this.getOffset())+h);}e.stop();}},_onMouseOut:function(e){this._setLastMousePosition(e.getDocumentLeft(),e.getDocumentTop());},_onMouseUp:function(e){if(!this.__mV){return;}this._finalizeSizes();var bn=this.getChildControl(k);bn.exclude();this.__mV=false;this.releaseCapture();e.stop();},_finalizeSizes:function(){var br=this.__na;var bo=this.__nb;if(br==null){return;}var bt=this._getChildren();var bs=bt[2];var bp=bt[3];var bq=bs.getLayoutProperties().flex;var bu=bp.getLayoutProperties().flex;if((bq!=0)&&(bu!=0)){bs.setLayoutProperties({flex:br});bp.setLayoutProperties({flex:bo});}else{if(this.__mY){bs.setWidth(br);bp.setWidth(bo);}else{bs.setHeight(br);bp.setHeight(bo);}}},__ng:function(){if(this.__mY){var bx=o,bE=z,by=l,bC=this.__mW;}else{var bx=q,bE=a,by=B,bC=this.__mX;}var bD=this._getChildren();var bv=bD[2].getSizeHint();var bA=bD[3].getSizeHint();var bB=bD[2].getBounds()[bE]+bD[3].getBounds()[bE];var bz=bC-this.__mU;var bw=bB-bz;if(bz<bv[bx]){bw-=bv[bx]-bz;bz=bv[bx];}else if(bw<bA[bx]){bz-=bA[bx]-bw;bw=bA[bx];}if(bz>bv[by]){bw+=bz-bv[by];bz=bv[by];}else if(bw>bA[by]){bz+=bw-bA[by];bw=bA[by];}this.__na=bz;this.__nb=bw;},_isActiveDragSession:function(){return this.__mV;},_setLastMousePosition:function(x,y){this.__mW=x;this.__mX=y;}},destruct:function(){this.__mT=null;}});})();(function(){var a="qx.ui.splitpane.Slider";qx.Class.define(a,{extend:qx.ui.core.Widget,properties:{allowShrinkX:{refine:true,init:false},allowShrinkY:{refine:true,init:false}}});})();(function(){var e="center",d="knob",c="middle",b="qx.ui.splitpane.Splitter",a="vertical";qx.Class.define(b,{extend:qx.ui.core.Widget,construct:function(f){qx.ui.core.Widget.call(this);if(f.getOrientation()==a){this._setLayout(new qx.ui.layout.HBox(0,e));this._getLayout().setAlignY(c);}else{this._setLayout(new qx.ui.layout.VBox(0,c));this._getLayout().setAlignX(e);}this._createChildControl(d);},properties:{allowShrinkX:{refine:true,init:false},allowShrinkY:{refine:true,init:false}},members:{_createChildControlImpl:function(g,h){var i;switch(g){case d:i=new qx.ui.basic.Image;this._add(i);break;}return i||qx.ui.core.Widget.prototype._createChildControlImpl.call(this,g);}}});})();(function(){var o="px",n="horizontal",m="top",l="height",k="width",j="left",i="100%",h="cursor",g="vertical",f="_applyOrientation",c="qx.ui.splitpane.Blocker",e="col-resize",d="row-resize",b="div",a="absolute";qx.Class.define(c,{extend:qx.html.Element,construct:function(p){var q={position:a,zIndex:11};qx.html.Element.call(this,b,q);if(p){this.setOrientation(p);}else{this.initOrientation();}},properties:{orientation:{init:n,check:[n,g],apply:f}},members:{_applyOrientation:function(r,s){if(r==n){this.setStyle(l,i);this.setStyle(h,e);this.setStyle(m,null);}else{this.setStyle(k,i);this.setStyle(j,null);this.setStyle(h,d);}},setWidth:function(t,u){var v=u+2*t;this.setStyle(k,v+o);},setHeight:function(w,x){var y=x+2*w;this.setStyle(l,y+o);},setLeft:function(z,A){var B=A-z;this.setStyle(j,B+o);},setTop:function(C,D){var top=D-C;this.setStyle(m,top+o);}}});})();(function(){var c="slider",b="splitter",a="qx.ui.splitpane.VLayout";qx.Class.define(a,{extend:qx.ui.layout.Abstract,members:{verifyLayoutProperty:null,renderLayout:function(d,e){var v=this._getLayoutChildren();var length=v.length;var r,u;var g,f,p,h;for(var i=0;i<length;i++){r=v[i];u=r.getLayoutProperties().type;if(u===b){f=r;}else if(u===c){p=r;}else if(!g){g=r;}else{h=r;}}if(g&&h){var x=g.getLayoutProperties().flex;var k=h.getLayoutProperties().flex;if(x==null){x=1;}if(k==null){k=1;}var w=g.getSizeHint();var n=f.getSizeHint();var o=h.getSizeHint();var j=w.height;var s=n.height;var t=o.height;if(x>0&&k>0){var l=x+k;var m=e-s;var j=Math.round((m/l)*x);var t=m-j;var q=qx.ui.layout.Util.arrangeIdeals(w.minHeight,j,w.maxHeight,o.minHeight,t,o.maxHeight);j=q.begin;t=q.end;}else if(x>0){j=e-s-t;if(j<w.minHeight){j=w.minHeight;}if(j>w.maxHeight){j=w.maxHeight;}}else if(k>0){t=e-j-s;if(t<o.minHeight){t=o.minHeight;}if(t>o.maxHeight){t=o.maxHeight;}}g.renderLayout(0,0,d,j);f.renderLayout(0,j,d,s);h.renderLayout(0,j+s,d,t);}else{f.renderLayout(0,0,0,0);if(g){g.renderLayout(0,0,d,e);}else if(h){h.renderLayout(0,0,d,e);}}},_computeSizeHint:function(){var H=this._getLayoutChildren();var length=H.length;var A,z,G;var B=0,D=0,C=0;var E=0,F=0,y=0;for(var i=0;i<length;i++){A=H[i];G=A.getLayoutProperties();if(G.type===c){continue;}z=A.getSizeHint();B+=z.minHeight;D+=z.height;C+=z.maxHeight;if(z.minWidth>E){E=z.minWidth;}if(z.width>F){F=z.width;}if(z.maxWidth>y){y=z.maxWidth;}}return {minHeight:B,height:D,maxHeight:C,minWidth:E,width:F,maxWidth:y};}}});})();(function(){var c="slider",b="splitter",a="qx.ui.splitpane.HLayout";qx.Class.define(a,{extend:qx.ui.layout.Abstract,members:{verifyLayoutProperty:null,renderLayout:function(d,e){var v=this._getLayoutChildren();var length=v.length;var s,u;var g,f,p,h;for(var i=0;i<length;i++){s=v[i];u=s.getLayoutProperties().type;if(u===b){f=s;}else if(u===c){p=s;}else if(!g){g=s;}else{h=s;}}if(g&&h){var x=g.getLayoutProperties().flex;var j=h.getLayoutProperties().flex;if(x==null){x=1;}if(j==null){j=1;}var w=g.getSizeHint();var m=f.getSizeHint();var o=h.getSizeHint();var t=w.width;var r=m.width;var q=o.width;if(x>0&&j>0){var k=x+j;var l=d-r;var t=Math.round((l/k)*x);var q=l-t;var n=qx.ui.layout.Util.arrangeIdeals(w.minWidth,t,w.maxWidth,o.minWidth,q,o.maxWidth);t=n.begin;q=n.end;}else if(x>0){t=d-r-q;if(t<w.minWidth){t=w.minWidth;}if(t>w.maxWidth){t=w.maxWidth;}}else if(j>0){q=d-t-r;if(q<o.minWidth){q=o.minWidth;}if(q>o.maxWidth){q=o.maxWidth;}}g.renderLayout(0,0,t,e);f.renderLayout(t,0,r,e);h.renderLayout(t+r,0,q,e);}else{f.renderLayout(0,0,0,0);if(g){g.renderLayout(0,0,d,e);}else if(h){h.renderLayout(0,0,d,e);}}},_computeSizeHint:function(){var H=this._getLayoutChildren();var length=H.length;var A,z,G;var E=0,F=0,y=0;var B=0,D=0,C=0;for(var i=0;i<length;i++){A=H[i];G=A.getLayoutProperties();if(G.type===c){continue;}z=A.getSizeHint();E+=z.minWidth;F+=z.width;y+=z.maxWidth;if(z.minHeight>B){B=z.minHeight;}if(z.height>D){D=z.height;}if(z.maxHeight>C){C=z.maxHeight;}}return {minWidth:E,width:F,maxWidth:y,minHeight:B,height:D,maxHeight:C};}}});})();(function(){var a="apiviewer.test.LayoutItem";qx.Class.define(a,{extend:qx.core.Object,members:{renderSeparator:function(b,c){}}});})();(function(){var p="other",o="widgets",n="fonts",m="appearances",k="qx.Theme",j="]",h="[Theme ",g="colors",f="decorations",e="Theme",b="meta",d="borders",c="icons";qx.Bootstrap.define(k,{statics:{define:function(name,q){if(!q){var q={};}q.include=this.__rg(q.include);q.patch=this.__rg(q.patch);{};var r={$$type:e,name:name,title:q.title,toString:this.genericToString};if(q.extend){r.supertheme=q.extend;}r.basename=qx.Bootstrap.createNamespace(name,r);this.__rj(r,q);this.__rh(r,q);this.$$registry[name]=r;for(var i=0,a=q.include,l=a.length;i<l;i++){this.include(r,a[i]);}for(var i=0,a=q.patch,l=a.length;i<l;i++){this.patch(r,a[i]);}},__rg:function(s){if(!s){return [];}if(qx.Bootstrap.isArray(s)){return s;}else{return [s];}},__rh:function(t,u){var v=u.aliases||{};if(u.extend&&u.extend.aliases){qx.Bootstrap.objectMergeWith(v,u.extend.aliases,false);}t.aliases=v;},getAll:function(){return this.$$registry;},getByName:function(name){return this.$$registry[name];},isDefined:function(name){return this.getByName(name)!==undefined;},getTotalNumber:function(){return qx.Bootstrap.objectGetLength(this.$$registry);},genericToString:function(){return h+this.name+j;},__ri:function(w){for(var i=0,x=this.__rk,l=x.length;i<l;i++){if(w[x[i]]){return x[i];}}},__rj:function(y,z){var C=this.__ri(z);if(z.extend&&!C){C=z.extend.type;}y.type=C||p;if(!C){return;}var E=function(){};if(z.extend){E.prototype=new z.extend.$$clazz;}var D=E.prototype;var B=z[C];for(var A in B){D[A]=B[A];if(D[A].base){{};D[A].base=z.extend;}}y.$$clazz=E;y[C]=new E;},$$registry:{},__rk:[g,d,f,n,c,o,m,b],__rl:null,__rm:null,__rn:function(){},patch:function(F,G){var I=this.__ri(G);if(I!==this.__ri(F)){throw new Error("The mixins '"+F.name+"' are not compatible '"+G.name+"'!");}var H=G[I];var J=F.$$clazz.prototype;for(var K in H){J[K]=H[K];}},include:function(L,M){var O=M.type;if(O!==L.type){throw new Error("The mixins '"+L.name+"' are not compatible '"+M.name+"'!");}var N=M[O];var P=L.$$clazz.prototype;for(var Q in N){if(P[Q]!==undefined){continue;}P[Q]=N[Q];}}}});})();(function(){var dN="button-frame",dM="atom",dL="widget",dK="main",dJ="button",dI="bold",dH="text-selected",dG="image",dF="middle",dE="selected",co="background-light",cn="cell",cm="text-disabled",cl="groupbox",ck="decoration/arrows/down.png",cj="label",ci="border-invalid",ch="input",cg="white",cf="input-disabled",dU="menu-button",dV="input-focused-invalid",dS="toolbar-button",dT="spinner",dQ="input-focused",dR="popup",dO="tooltip",dP="list",dW="tree-item",dX="treevirtual-contract",dk="scrollbar",dj="datechooser/nav-button",dm="text-hovered",dl="center",dp="treevirtual-expand",dn="textfield",dr="decoration/arrows/right.png",dq="background-application",di="radiobutton",dh="invalid",k="combobox",l="right-top",m="checkbox",n="text-title",o="icon/16/places/folder-open.png",p="qx/static/blank.gif",q="scrollbar/button",r="right",s="combobox/button",t="icon/16/places/folder.png",em="text-label",el="decoration/tree/closed.png",ek="scrollbar-slider-horizontal",ej="checkbox-checked",eq="decoration/arrows/left.png",ep="button-focused",eo="text-light",en="menu-slidebar-button",es="checkbox-undetermined",er="text-input",bm="slidebar/button-forward",bn="background-splitpane",bk=".png",bl="decoration/tree/open.png",bq="default",br="decoration/arrows/down-small.png",bo="datechooser",bp="slidebar/button-backward",bi="selectbox",bj="treevirtual-folder",N="shadow-popup",M="icon/16/mimetypes/office-document.png",P="background-medium",O="icon/32/places/folder-open.png",J="icon/22/places/folder-open.png",I="table",L="decoration/arrows/up.png",K="decoration/form/",H="",G="-invalid",bx="button-checked",by="decoration/window/maximize-active-hovered.png",bz="radiobutton-hovered",bA="keyboard-focus",bt="group-item",bu="decoration/cursors/",bv="slidebar",bw="tooltip-error-arrow",bB="table-scroller-focus-indicator",bC="move-frame",bb="nodrop",ba="decoration/table/boolean-true.png",Y="table-header-cell",X="menu",W="app-header",V="row-layer",U="text-inactive",T="move",bf="radiobutton-checked-focused",be="decoration/window/restore-active-hovered.png",bD="shadow-window",bE="table-column-button",bF="right.png",bG="checkbox-undetermined-hovered",bH="tabview-page-button-bottom-inactive",bI="tooltip-error",bJ="window-statusbar",bK="button-hovered",bL="decoration/scrollbar/scrollbar-",bM="background-tip",cw="scrollbar-slider-horizontal-disabled",cv="table-scroller-header",cu="button-pressed",ct="table-pane",cA="decoration/window/close-active.png",cz="native",cy="checkbox-hovered",cx="button-invalid-shadow",cE="decoration/window/minimize-active-hovered.png",cD="menubar",dc="icon/16/actions/dialog-cancel.png",dd="tabview-page-button-top-inactive",da="tabview-page-button-left-inactive",db="menu-slidebar",cX="toolbar-button-checked",cY="decoration/tree/open-selected.png",cV="radiobutton-checked",cW="decoration/window/minimize-inactive.png",de="icon/16/apps/office-calendar.png",df="group",dv="tabview-page-button-right-inactive",du="decoration/window/minimize-active.png",dx="decoration/window/restore-inactive.png",dw="checkbox-checked-focused",dz="splitpane",dy="combobox/textfield",dB="button-preselected-focused",dA="decoration/window/close-active-hovered.png",dt="qx/icon/Tango/16/actions/window-close.png",ds="checkbox-pressed",ef="button-disabled",eg="selected-dragover",eh="border-separator",ei="decoration/window/maximize-inactive.png",eb="dragover",ec="scrollarea",ed="scrollbar-vertical",ee="decoration/menu/checkbox-invert.gif",dY="decoration/toolbar/toolbar-handle-knob.gif",ea="icon/22/mimetypes/office-document.png",j="button-preselected",i="button-checked-focused",h="up.png",g="best-fit",f="decoration/tree/closed-selected.png",e="qx.theme.modern.Appearance",d="text-active",c="toolbar-button-hovered",b="progressive-table-header",a="decoration/table/select-column-order.png",w="decoration/menu/radiobutton.gif",x="decoration/arrows/forward.png",u="decoration/table/descending.png",v="progressbar",A="window-captionbar-active",B="checkbox-checked-hovered",y="scrollbar-slider-vertical",z="toolbar",D="alias",E="decoration/window/restore-active.png",cI="decoration/table/boolean-false.png",cC="icon/32/mimetypes/office-document.png",cP="radiobutton-checked-disabled",cL="tabview-pane",cr="decoration/arrows/rewind.png",cp="checkbox-focused",R="top",cs="icon/16/actions/dialog-ok.png",bd="radiobutton-checked-hovered",bc="table-header-cell-hovered",bW="window",bX="text-gray",bY="decoration/menu/radiobutton-invert.gif",ca="text-placeholder",cb="slider",cc="keep-align",cd="down.png",ce="tabview-page-button-top-active",bT="icon/22/places/folder.png",bU="decoration/window/maximize-active.png",cq="checkbox-checked-pressed",cO="decoration/window/close-inactive.png",cN="tabview-page-button-left-active",cM="toolbar-part",cT="decoration/splitpane/knob-vertical.png",cS=".gif",cR="radiobutton-checked-pressed",cQ="table-statusbar",cK="radiobutton-pressed",cJ="window-captionbar-inactive",C="copy",bh="radiobutton-focused",bg="decoration/arrows/down-invert.png",cB="decoration/menu/checkbox.gif",bs="decoration/splitpane/knob-horizontal.png",cH="icon/32/places/folder.png",cG="toolbar-separator",cF="tabview-page-button-bottom-active",Q="decoration/arrows/up-small.png",cU="decoration/table/ascending.png",F="decoration/arrows/up-invert.png",S="small",bN="tabview-page-button-right-active",bO="-disabled",bP="scrollbar-horizontal",bQ="checkbox-undetermined-focused",bR="progressive-table-header-cell",bS="menu-separator",dg="pane",bV="decoration/arrows/right-invert.png",dD="left.png",dC="icon/16/actions/view-refresh.png";qx.Theme.define(e,{appearances:{"widget":{},"root":{style:function(et){return {backgroundColor:dq,textColor:em,font:bq};}},"label":{style:function(eu){return {textColor:eu.disabled?cm:undefined};}},"move-frame":{style:function(ev){return {decorator:dK};}},"resize-frame":bC,"dragdrop-cursor":{style:function(ew){var ex=bb;if(ew.copy){ex=C;}else if(ew.move){ex=T;}else if(ew.alias){ex=D;}return {source:bu+ex+cS,position:l,offset:[2,16,2,6]};}},"image":{style:function(ey){return {opacity:!ey.replacement&&ey.disabled?0.3:1};}},"atom":{},"atom/label":cj,"atom/icon":dG,"popup":{style:function(ez){return {decorator:dK,backgroundColor:co,shadow:N};}},"button-frame":{alias:dM,style:function(eA){var eC,eB;if(eA.checked&&eA.focused&&!eA.inner){eC=i;eB=undefined;}else if(eA.disabled){eC=ef;eB=undefined;}else if(eA.pressed){eC=cu;eB=dm;}else if(eA.checked){eC=bx;eB=undefined;}else if(eA.hovered){eC=bK;eB=dm;}else if(eA.preselected&&eA.focused&&!eA.inner){eC=dB;eB=dm;}else if(eA.preselected){eC=j;eB=dm;}else if(eA.focused&&!eA.inner){eC=ep;eB=undefined;}else{eC=dJ;eB=undefined;}return {decorator:eC,textColor:eB,shadow:eA.invalid&&!eA.disabled?cx:undefined};}},"button-frame/image":{style:function(eD){return {opacity:!eD.replacement&&eD.disabled?0.5:1};}},"button":{alias:dN,include:dN,style:function(eE){return {padding:[2,8],center:true};}},"hover-button":{alias:dM,include:dM,style:function(eF){return {decorator:eF.hovered?dE:undefined,textColor:eF.hovered?dH:undefined};}},"splitbutton":{},"splitbutton/button":dJ,"splitbutton/arrow":{alias:dJ,include:dJ,style:function(eG){return {icon:ck,padding:2,marginLeft:1};}},"checkbox":{alias:dM,style:function(eH){var eJ;if(eH.checked){if(eH.disabled){eJ=ej;}else if(eH.focused){eJ=dw;}else if(eH.pressed){eJ=cq;}else if(eH.hovered){eJ=B;}else{eJ=ej;}}else if(eH.undetermined){if(eH.disabled){eJ=es;}else if(eH.focused){eJ=bQ;}else if(eH.hovered){eJ=bG;}else{eJ=es;}}else if(!eH.disabled){if(eH.focused){eJ=cp;}else if(eH.pressed){eJ=ds;}else if(eH.hovered){eJ=cy;}}eJ=eJ||m;var eI=eH.invalid&&!eH.disabled?G:H;return {icon:K+eJ+eI+bk,gap:6};}},"radiobutton":{alias:dM,style:function(eK){var eM;if(eK.checked&&eK.focused){eM=bf;}else if(eK.checked&&eK.disabled){eM=cP;}else if(eK.checked&&eK.pressed){eM=cR;}else if(eK.checked&&eK.hovered){eM=bd;}else if(eK.checked){eM=cV;}else if(eK.focused){eM=bh;}else if(eK.pressed){eM=cK;}else if(eK.hovered){eM=bz;}else{eM=di;}var eL=eK.invalid&&!eK.disabled?G:H;return {icon:K+eM+eL+bk,gap:6};}},"textfield":{style:function(eN){var eS;var eQ=!!eN.focused;var eR=!!eN.invalid;var eO=!!eN.disabled;if(eQ&&eR&&!eO){eS=dV;}else if(eQ&&!eR&&!eO){eS=dQ;}else if(eO){eS=cf;}else if(!eQ&&eR&&!eO){eS=ci;}else{eS=ch;}var eP;if(eN.disabled){eP=cm;}else if(eN.showingPlaceholder){eP=ca;}else{eP=er;}return {decorator:eS,padding:[2,4,1],textColor:eP};}},"textarea":{include:dn,style:function(eT){return {padding:4};}},"spinner":{style:function(eU){var eY;var eW=!!eU.focused;var eX=!!eU.invalid;var eV=!!eU.disabled;if(eW&&eX&&!eV){eY=dV;}else if(eW&&!eX&&!eV){eY=dQ;}else if(eV){eY=cf;}else if(!eW&&eX&&!eV){eY=ci;}else{eY=ch;}return {decorator:eY};}},"spinner/textfield":{style:function(fa){return {marginRight:2,padding:[2,4,1],textColor:fa.disabled?cm:er};}},"spinner/upbutton":{alias:dN,include:dN,style:function(fb){return {icon:Q,padding:fb.pressed?[2,2,0,4]:[1,3,1,3],shadow:undefined};}},"spinner/downbutton":{alias:dN,include:dN,style:function(fc){return {icon:br,padding:fc.pressed?[2,2,0,4]:[1,3,1,3],shadow:undefined};}},"datefield":k,"datefield/button":{alias:s,include:s,style:function(fd){return {icon:de,padding:[0,3],decorator:undefined};}},"datefield/textfield":dy,"datefield/list":{alias:bo,include:bo,style:function(fe){return {decorator:undefined};}},"groupbox":{style:function(ff){return {legendPosition:R};}},"groupbox/legend":{alias:dM,style:function(fg){return {padding:[1,0,1,4],textColor:fg.invalid?dh:n,font:dI};}},"groupbox/frame":{style:function(fh){return {padding:12,decorator:df};}},"check-groupbox":cl,"check-groupbox/legend":{alias:m,include:m,style:function(fi){return {padding:[1,0,1,4],textColor:fi.invalid?dh:n,font:dI};}},"radio-groupbox":cl,"radio-groupbox/legend":{alias:di,include:di,style:function(fj){return {padding:[1,0,1,4],textColor:fj.invalid?dh:n,font:dI};}},"scrollarea":{style:function(fk){return {minWidth:50,minHeight:50};}},"scrollarea/corner":{style:function(fl){return {backgroundColor:dq};}},"scrollarea/pane":dL,"scrollarea/scrollbar-x":dk,"scrollarea/scrollbar-y":dk,"scrollbar":{style:function(fm){if(fm[cz]){return {};}return {width:fm.horizontal?undefined:16,height:fm.horizontal?16:undefined,decorator:fm.horizontal?bP:ed,padding:1};}},"scrollbar/slider":{alias:cb,style:function(fn){return {padding:fn.horizontal?[0,1,0,1]:[1,0,1,0]};}},"scrollbar/slider/knob":{include:dN,style:function(fo){var fp=fo.horizontal?ek:y;if(fo.disabled){fp+=bO;}return {decorator:fp,minHeight:fo.horizontal?undefined:9,minWidth:fo.horizontal?9:undefined};}},"scrollbar/button":{alias:dN,include:dN,style:function(fq){var fr=bL;if(fq.left){fr+=dD;}else if(fq.right){fr+=bF;}else if(fq.up){fr+=h;}else{fr+=cd;}if(fq.left||fq.right){return {padding:[0,0,0,fq.left?3:4],icon:fr,width:15,height:14};}else{return {padding:[0,0,0,2],icon:fr,width:14,height:15};}}},"scrollbar/button-begin":q,"scrollbar/button-end":q,"slider":{style:function(fs){var fw;var fu=!!fs.focused;var fv=!!fs.invalid;var ft=!!fs.disabled;if(fu&&fv&&!ft){fw=dV;}else if(fu&&!fv&&!ft){fw=dQ;}else if(ft){fw=cf;}else if(!fu&&fv&&!ft){fw=ci;}else{fw=ch;}return {decorator:fw};}},"slider/knob":{include:dN,style:function(fx){return {decorator:fx.disabled?cw:ek,shadow:undefined,height:14,width:14};}},"list":{alias:ec,style:function(fy){var fC;var fA=!!fy.focused;var fB=!!fy.invalid;var fz=!!fy.disabled;if(fA&&fB&&!fz){fC=dV;}else if(fA&&!fB&&!fz){fC=dQ;}else if(fz){fC=cf;}else if(!fA&&fB&&!fz){fC=ci;}else{fC=ch;}return {backgroundColor:co,decorator:fC};}},"list/pane":dL,"listitem":{alias:dM,style:function(fD){var fE;if(fD.dragover){fE=fD.selected?eg:eb;}else{fE=fD.selected?dE:undefined;}return {padding:fD.dragover?[4,4,2,4]:4,textColor:fD.selected?dH:undefined,decorator:fE};}},"slidebar":{},"slidebar/scrollpane":{},"slidebar/content":{},"slidebar/button-forward":{alias:dN,include:dN,style:function(fF){return {padding:5,center:true,icon:fF.vertical?ck:dr};}},"slidebar/button-backward":{alias:dN,include:dN,style:function(fG){return {padding:5,center:true,icon:fG.vertical?L:eq};}},"tabview":{style:function(fH){return {contentPadding:16};}},"tabview/bar":{alias:bv,style:function(fI){var fJ={marginBottom:fI.barTop?-1:0,marginTop:fI.barBottom?-4:0,marginLeft:fI.barRight?-3:0,marginRight:fI.barLeft?-1:0,paddingTop:0,paddingRight:0,paddingBottom:0,paddingLeft:0};if(fI.barTop||fI.barBottom){fJ.paddingLeft=5;fJ.paddingRight=7;}else{fJ.paddingTop=5;fJ.paddingBottom=7;}return fJ;}},"tabview/bar/button-forward":{include:bm,alias:bm,style:function(fK){if(fK.barTop||fK.barBottom){return {marginTop:2,marginBottom:2};}else{return {marginLeft:2,marginRight:2};}}},"tabview/bar/button-backward":{include:bp,alias:bp,style:function(fL){if(fL.barTop||fL.barBottom){return {marginTop:2,marginBottom:2};}else{return {marginLeft:2,marginRight:2};}}},"tabview/bar/scrollpane":{},"tabview/pane":{style:function(fM){return {decorator:cL,minHeight:100,marginBottom:fM.barBottom?-1:0,marginTop:fM.barTop?-1:0,marginLeft:fM.barLeft?-1:0,marginRight:fM.barRight?-1:0};}},"tabview-page":dL,"tabview-page/button":{alias:dM,style:function(fN){var fT,fP=0;var fS=0,fO=0,fQ=0,fR=0;if(fN.checked){if(fN.barTop){fT=ce;fP=[6,14];fQ=fN.firstTab?0:-5;fR=fN.lastTab?0:-5;}else if(fN.barBottom){fT=cF;fP=[6,14];fQ=fN.firstTab?0:-5;fR=fN.lastTab?0:-5;}else if(fN.barRight){fT=bN;fP=[6,13];fS=fN.firstTab?0:-5;fO=fN.lastTab?0:-5;}else{fT=cN;fP=[6,13];fS=fN.firstTab?0:-5;fO=fN.lastTab?0:-5;}}else{if(fN.barTop){fT=dd;fP=[4,10];fS=4;fQ=fN.firstTab?5:1;fR=1;}else if(fN.barBottom){fT=bH;fP=[4,10];fO=4;fQ=fN.firstTab?5:1;fR=1;}else if(fN.barRight){fT=dv;fP=[4,10];fR=5;fS=fN.firstTab?5:1;fO=1;fQ=1;}else{fT=da;fP=[4,10];fQ=5;fS=fN.firstTab?5:1;fO=1;fR=1;}}return {zIndex:fN.checked?10:5,decorator:fT,padding:fP,marginTop:fS,marginBottom:fO,marginLeft:fQ,marginRight:fR,textColor:fN.checked?d:U};}},"tabview-page/button/label":{alias:cj,style:function(fU){return {padding:[0,1,0,1],margin:fU.focused?0:1,decorator:fU.focused?bA:undefined};}},"tabview-page/button/close-button":{alias:dM,style:function(fV){return {icon:dt};}},"toolbar":{style:function(fW){return {decorator:z,spacing:2};}},"toolbar/part":{style:function(fX){return {decorator:cM,spacing:2};}},"toolbar/part/container":{style:function(fY){return {paddingLeft:2,paddingRight:2};}},"toolbar/part/handle":{style:function(ga){return {source:dY,marginLeft:3,marginRight:3};}},"toolbar-button":{alias:dM,style:function(gb){return {marginTop:2,marginBottom:2,padding:(gb.pressed||gb.checked||gb.hovered)&&!gb.disabled||(gb.disabled&&gb.checked)?3:5,decorator:gb.pressed||(gb.checked&&!gb.hovered)||(gb.checked&&gb.disabled)?cX:gb.hovered&&!gb.disabled?c:undefined};}},"toolbar-menubutton":{alias:dS,include:dS,style:function(gc){return {showArrow:true};}},"toolbar-menubutton/arrow":{alias:dG,include:dG,style:function(gd){return {source:br};}},"toolbar-splitbutton":{style:function(ge){return {marginTop:2,marginBottom:2};}},"toolbar-splitbutton/button":{alias:dS,include:dS,style:function(gf){return {icon:ck,marginTop:undefined,marginBottom:undefined};}},"toolbar-splitbutton/arrow":{alias:dS,include:dS,style:function(gg){if(gg.pressed||gg.checked||(gg.hovered&&!gg.disabled)){var gh=1;}else{var gh=3;}return {padding:gh,icon:ck,marginTop:undefined,marginBottom:undefined};}},"toolbar-separator":{style:function(gi){return {decorator:cG,margin:7};}},"tree":dP,"tree-item":{style:function(gj){return {padding:[2,6],textColor:gj.selected?dH:undefined,decorator:gj.selected?dE:undefined};}},"tree-item/icon":{include:dG,style:function(gk){return {paddingRight:5};}},"tree-item/label":cj,"tree-item/open":{include:dG,style:function(gl){var gm;if(gl.selected&&gl.opened){gm=cY;}else if(gl.selected&&!gl.opened){gm=f;}else if(gl.opened){gm=bl;}else{gm=el;}return {padding:[0,5,0,2],source:gm};}},"tree-folder":{include:dW,alias:dW,style:function(gn){var gp,go;if(gn.small){gp=gn.opened?o:t;go=o;}else if(gn.large){gp=gn.opened?O:cH;go=O;}else{gp=gn.opened?J:bT;go=J;}return {icon:gp,iconOpened:go};}},"tree-file":{include:dW,alias:dW,style:function(gq){return {icon:gq.small?M:gq.large?cC:ea};}},"treevirtual":I,"treevirtual-folder":{style:function(gr){return {icon:gr.opened?o:t};}},"treevirtual-file":{include:bj,alias:bj,style:function(gs){return {icon:M};}},"treevirtual-line":{style:function(gt){return {icon:p};}},"treevirtual-contract":{style:function(gu){return {icon:bl,paddingLeft:5,paddingTop:2};}},"treevirtual-expand":{style:function(gv){return {icon:el,paddingLeft:5,paddingTop:2};}},"treevirtual-only-contract":dX,"treevirtual-only-expand":dp,"treevirtual-start-contract":dX,"treevirtual-start-expand":dp,"treevirtual-end-contract":dX,"treevirtual-end-expand":dp,"treevirtual-cross-contract":dX,"treevirtual-cross-expand":dp,"treevirtual-end":{style:function(gw){return {icon:p};}},"treevirtual-cross":{style:function(gx){return {icon:p};}},"tooltip":{include:dR,style:function(gy){return {backgroundColor:bM,padding:[1,3,2,3],offset:[15,5,5,5]};}},"tooltip/atom":dM,"tooltip-error":{include:dO,style:function(gz){return {textColor:dH,placeMethod:dL,offset:[0,0,0,14],marginTop:-2,position:l,showTimeout:100,hideTimeout:10000,decorator:bI,shadow:bw,font:dI};}},"tooltip-error/atom":dM,"window":{style:function(gA){return {shadow:bD,contentPadding:[10,10,10,10]};}},"window/pane":{style:function(gB){return {decorator:bW};}},"window/captionbar":{style:function(gC){return {decorator:gC.active?A:cJ,textColor:gC.active?cg:bX,minHeight:26,paddingRight:2};}},"window/icon":{style:function(gD){return {margin:[5,0,3,6]};}},"window/title":{style:function(gE){return {alignY:dF,font:dI,marginLeft:6,marginRight:12};}},"window/minimize-button":{alias:dM,style:function(gF){return {icon:gF.active?gF.hovered?cE:du:cW,margin:[4,8,2,0]};}},"window/restore-button":{alias:dM,style:function(gG){return {icon:gG.active?gG.hovered?be:E:dx,margin:[5,8,2,0]};}},"window/maximize-button":{alias:dM,style:function(gH){return {icon:gH.active?gH.hovered?by:bU:ei,margin:[4,8,2,0]};}},"window/close-button":{alias:dM,style:function(gI){return {icon:gI.active?gI.hovered?dA:cA:cO,margin:[4,8,2,0]};}},"window/statusbar":{style:function(gJ){return {padding:[2,6],decorator:bJ,minHeight:18};}},"window/statusbar-text":{style:function(gK){return {font:S};}},"iframe":{style:function(gL){return {decorator:dK};}},"resizer":{style:function(gM){return {decorator:dg};}},"splitpane":{style:function(gN){return {decorator:dz};}},"splitpane/splitter":{style:function(gO){return {width:gO.horizontal?3:undefined,height:gO.vertical?3:undefined,backgroundColor:bn};}},"splitpane/splitter/knob":{style:function(gP){return {source:gP.horizontal?bs:cT};}},"splitpane/slider":{style:function(gQ){return {width:gQ.horizontal?3:undefined,height:gQ.vertical?3:undefined,backgroundColor:bn};}},"selectbox":{alias:dN,include:dN,style:function(gR){return {padding:[2,8]};}},"selectbox/atom":dM,"selectbox/popup":dR,"selectbox/list":{alias:dP},"selectbox/arrow":{include:dG,style:function(gS){return {source:ck,paddingLeft:5};}},"datechooser":{style:function(gT){var gX;var gV=!!gT.focused;var gW=!!gT.invalid;var gU=!!gT.disabled;if(gV&&gW&&!gU){gX=dV;}else if(gV&&!gW&&!gU){gX=dQ;}else if(gU){gX=cf;}else if(!gV&&gW&&!gU){gX=ci;}else{gX=ch;}return {padding:2,decorator:gX,backgroundColor:co};}},"datechooser/navigation-bar":{},"datechooser/nav-button":{include:dN,alias:dN,style:function(gY){var ha={padding:[2,4],shadow:undefined};if(gY.lastYear){ha.icon=cr;ha.marginRight=1;}else if(gY.lastMonth){ha.icon=eq;}else if(gY.nextYear){ha.icon=x;ha.marginLeft=1;}else if(gY.nextMonth){ha.icon=dr;}return ha;}},"datechooser/last-year-button-tooltip":dO,"datechooser/last-month-button-tooltip":dO,"datechooser/next-year-button-tooltip":dO,"datechooser/next-month-button-tooltip":dO,"datechooser/last-year-button":dj,"datechooser/last-month-button":dj,"datechooser/next-month-button":dj,"datechooser/next-year-button":dj,"datechooser/month-year-label":{style:function(hb){return {font:dI,textAlign:dl,textColor:hb.disabled?cm:undefined};}},"datechooser/date-pane":{style:function(hc){return {textColor:hc.disabled?cm:undefined,marginTop:2};}},"datechooser/weekday":{style:function(hd){return {textColor:hd.disabled?cm:hd.weekend?eo:undefined,textAlign:dl,paddingTop:2,backgroundColor:P};}},"datechooser/week":{style:function(he){return {textAlign:dl,padding:[2,4],backgroundColor:P};}},"datechooser/day":{style:function(hf){return {textAlign:dl,decorator:hf.disabled?undefined:hf.selected?dE:undefined,textColor:hf.disabled?cm:hf.selected?dH:hf.otherMonth?eo:undefined,font:hf.today?dI:undefined,padding:[2,4]};}},"combobox":{style:function(hg){var hk;var hi=!!hg.focused;var hj=!!hg.invalid;var hh=!!hg.disabled;if(hi&&hj&&!hh){hk=dV;}else if(hi&&!hj&&!hh){hk=dQ;}else if(hh){hk=cf;}else if(!hi&&hj&&!hh){hk=ci;}else{hk=ch;}return {decorator:hk};}},"combobox/popup":dR,"combobox/list":{alias:dP},"combobox/button":{include:dN,alias:dN,style:function(hl){var hm={icon:ck,padding:2};if(hl.selected){hm.decorator=ep;}return hm;}},"combobox/textfield":{include:dn,style:function(hn){return {decorator:undefined};}},"menu":{style:function(ho){var hp={decorator:X,shadow:N,spacingX:6,spacingY:1,iconColumnWidth:16,arrowColumnWidth:4,placementModeY:ho.submenu||ho.contextmenu?g:cc};if(ho.submenu){hp.position=l;hp.offset=[-2,-3];}return hp;}},"menu/slidebar":db,"menu-slidebar":dL,"menu-slidebar-button":{style:function(hq){return {decorator:hq.hovered?dE:undefined,padding:7,center:true};}},"menu-slidebar/button-backward":{include:en,style:function(hr){return {icon:hr.hovered?F:L};}},"menu-slidebar/button-forward":{include:en,style:function(hs){return {icon:hs.hovered?bg:ck};}},"menu-separator":{style:function(ht){return {height:0,decorator:bS,margin:[4,2]};}},"menu-button":{alias:dM,style:function(hu){return {decorator:hu.selected?dE:undefined,textColor:hu.selected?dH:undefined,padding:[4,6]};}},"menu-button/icon":{include:dG,style:function(hv){return {alignY:dF};}},"menu-button/label":{include:cj,style:function(hw){return {alignY:dF,padding:1};}},"menu-button/shortcut":{include:cj,style:function(hx){return {alignY:dF,marginLeft:14,padding:1};}},"menu-button/arrow":{include:dG,style:function(hy){return {source:hy.selected?bV:dr,alignY:dF};}},"menu-checkbox":{alias:dU,include:dU,style:function(hz){return {icon:!hz.checked?undefined:hz.selected?ee:cB};}},"menu-radiobutton":{alias:dU,include:dU,style:function(hA){return {icon:!hA.checked?undefined:hA.selected?bY:w};}},"menubar":{style:function(hB){return {decorator:cD};}},"menubar-button":{alias:dM,style:function(hC){return {decorator:(hC.pressed||hC.hovered)&&!hC.disabled?dE:undefined,textColor:hC.pressed||hC.hovered?dH:undefined,padding:[3,8]};}},"colorselector":dL,"colorselector/control-bar":dL,"colorselector/control-pane":dL,"colorselector/visual-pane":cl,"colorselector/preset-grid":dL,"colorselector/colorbucket":{style:function(hD){return {decorator:dK,width:16,height:16};}},"colorselector/preset-field-set":cl,"colorselector/input-field-set":cl,"colorselector/preview-field-set":cl,"colorselector/hex-field-composite":dL,"colorselector/hex-field":dn,"colorselector/rgb-spinner-composite":dL,"colorselector/rgb-spinner-red":dT,"colorselector/rgb-spinner-green":dT,"colorselector/rgb-spinner-blue":dT,"colorselector/hsb-spinner-composite":dL,"colorselector/hsb-spinner-hue":dT,"colorselector/hsb-spinner-saturation":dT,"colorselector/hsb-spinner-brightness":dT,"colorselector/preview-content-old":{style:function(hE){return {decorator:dK,width:50,height:10};}},"colorselector/preview-content-new":{style:function(hF){return {decorator:dK,backgroundColor:co,width:50,height:10};}},"colorselector/hue-saturation-field":{style:function(hG){return {decorator:dK,margin:5};}},"colorselector/brightness-field":{style:function(hH){return {decorator:dK,margin:[5,7]};}},"colorselector/hue-saturation-pane":dL,"colorselector/hue-saturation-handle":dL,"colorselector/brightness-pane":dL,"colorselector/brightness-handle":dL,"colorpopup":{alias:dR,include:dR,style:function(hI){return {padding:5,backgroundColor:dq};}},"colorpopup/field":{style:function(hJ){return {decorator:dK,margin:2,width:14,height:14,backgroundColor:co};}},"colorpopup/selector-button":dJ,"colorpopup/auto-button":dJ,"colorpopup/preview-pane":cl,"colorpopup/current-preview":{style:function(hK){return {height:20,padding:4,marginLeft:4,decorator:dK,allowGrowX:true};}},"colorpopup/selected-preview":{style:function(hL){return {height:20,padding:4,marginRight:4,decorator:dK,allowGrowX:true};}},"colorpopup/colorselector-okbutton":{alias:dJ,include:dJ,style:function(hM){return {icon:cs};}},"colorpopup/colorselector-cancelbutton":{alias:dJ,include:dJ,style:function(hN){return {icon:dc};}},"table":{alias:dL,style:function(hO){return {decorator:I};}},"table-header":{},"table/statusbar":{style:function(hP){return {decorator:cQ,padding:[0,2]};}},"table/column-button":{alias:dN,style:function(hQ){return {decorator:bE,padding:3,icon:a};}},"table-column-reset-button":{include:dU,alias:dU,style:function(){return {icon:dC};}},"table-scroller":dL,"table-scroller/scrollbar-x":dk,"table-scroller/scrollbar-y":dk,"table-scroller/header":{style:function(hR){return {decorator:cv};}},"table-scroller/pane":{style:function(hS){return {backgroundColor:ct};}},"table-scroller/focus-indicator":{style:function(hT){return {decorator:bB};}},"table-scroller/resize-line":{style:function(hU){return {backgroundColor:eh,width:2};}},"table-header-cell":{alias:dM,style:function(hV){return {minWidth:13,minHeight:20,padding:hV.hovered?[3,4,2,4]:[3,4],decorator:hV.hovered?bc:Y,sortIcon:hV.sorted?(hV.sortedAscending?cU:u):undefined};}},"table-header-cell/label":{style:function(hW){return {minWidth:0,alignY:dF,paddingRight:5};}},"table-header-cell/sort-icon":{style:function(hX){return {alignY:dF,alignX:r};}},"table-header-cell/icon":{style:function(hY){return {minWidth:0,alignY:dF,paddingRight:5};}},"table-editor-textfield":{include:dn,style:function(ia){return {decorator:undefined,padding:[2,2],backgroundColor:co};}},"table-editor-selectbox":{include:bi,alias:bi,style:function(ib){return {padding:[0,2],backgroundColor:co};}},"table-editor-combobox":{include:k,alias:k,style:function(ic){return {decorator:undefined,backgroundColor:co};}},"progressive-table-header":{alias:dL,style:function(id){return {decorator:b};}},"progressive-table-header-cell":{alias:dM,style:function(ie){return {minWidth:40,minHeight:25,paddingLeft:6,decorator:bR};}},"app-header":{style:function(ig){return {font:dI,textColor:dH,padding:[8,12],decorator:W};}},"virtual-list":dP,"virtual-list/row-layer":V,"row-layer":{style:function(ih){return {colorEven:cg,colorOdd:cg};}},"group-item":{include:cj,alias:cj,style:function(ii){return {padding:4,decorator:bt,textColor:cg,font:dI};}},"column-layer":dL,"cell":{style:function(ij){return {textColor:ij.selected?dH:em,padding:[3,6],font:bq};}},"cell-string":cn,"cell-number":{include:cn,style:function(ik){return {textAlign:r};}},"cell-image":cn,"cell-boolean":{include:cn,style:function(il){return {iconTrue:ba,iconFalse:cI};}},"cell-atom":cn,"cell-date":cn,"cell-html":cn,"htmlarea":{"include":dL,style:function(im){return {backgroundColor:cg};}},"progressbar":{style:function(io){return {decorator:v,padding:[1],backgroundColor:cg};}},"progressbar/progress":{style:function(ip){return {decorator:dE};}}}});})();(function(){var g="#134275",f="scrollarea",e="main",d="Theme for API Viewer",c="apiviewer.Appearance",b="white",a="bold";qx.Theme.define(c,{title:d,extend:qx.theme.modern.Appearance,appearances:{"toggleview":{style:function(h){return {width:240,decorator:e};}},"detailviewer":{style:function(i){return {backgroundColor:b,decorator:e};}},"legend":{include:f,alias:f,style:function(j){return {contentPadding:[10,10,10,10]};}},"legendview-label-important":{style:function(k){return {textColor:g,font:a};}},"legendview-label":{style:function(l){return {textColor:g};}},"tabview":{style:function(m){return {contentPadding:0};}},"tabview/pane":{style:function(n){return {minHeight:100,marginBottom:n.barBottom?-1:0,marginTop:n.barTop?-1:0,marginLeft:n.barLeft?-1:0,marginRight:n.barRight?-1:0};}}}});})();(function(){var a="apiviewer.test.Widget";qx.Class.define(a,{extend:apiviewer.test.LayoutItem,members:{renderSeparator:function(b,c){}}});})();(function(){var a="apiviewer.test.Methods";qx.Class.define(a,{extend:Object,members:{toString:function(){},valueOf:function(){},isPrototypeOf:function(){},hasOwnProperty:function(){},toLocaleString:function(){}}});})();(function(){var h="apiviewer.ClassLoader",g="(",f=")",e=".json",d="completed",c=".",b="/",a="failed";qx.Class.define(h,{extend:qx.core.Object,construct:function(j){qx.core.Object.call(this);this._baseUri=j;},members:{load:function(k,l,m,self){var n=this._baseUri+b+k+e;var o=new qx.io.remote.Request(n);var p=null;o.setAsynchronous(l);o.setTimeout(30000);o.setProhibitCaching(false);o.addListener(d,function(q){var content=eval(g+q.getContent()+f);var r=k.substring(0,k.lastIndexOf(c));var s=apiviewer.dao.Class.getClassByName(r);p=new apiviewer.dao.Class(content,s);s.addClass(p);this.__Tc(p,m,self);},this);o.addListener(a,function(t){alert("Couldn't load file: "+n);},this);o.send();return p;},__Tc:function(u,v,self){if(v){if(self){v.call(self,u);}else{v(u);}}},__Td:function(w,x,self){var z=[];var y=0;var A,i;for(i=0;i<w.length;i++){A=w[i];if(!A.isLoaded()){z.push(A);}}for(i=0;i<z.length;i++){this.load(z[i].getFullName(),true,function(B){y+=1;if(y==z.length){this.__Tc(apiviewer.dao.Class.getClassByName(w[0].getFullName()),x,self);}},this);}if(z.length==0){this.__Tc(w[0],x,self);}},classLoadDependendClasses:function(C,D,self){var E=C.getDependendClasses();this.__Td(E,D,self);},packageLoadDependendClasses:function(F,G,self){var H=F.getClasses();this.__Td(H,G,self);}}});})();(function(){var a="qx.application.IApplication";qx.Interface.define(a,{members:{main:function(){},finalize:function(){},close:function(){},terminate:function(){}}});})();(function(){var b="abstract",a="qx.application.AbstractGui";qx.Class.define(a,{type:b,extend:qx.core.Object,implement:[qx.application.IApplication],include:qx.locale.MTranslation,members:{__nv:null,_createRootWidget:function(){throw new Error("Abstract method call");},getRoot:function(){return this.__nv;},main:function(){qx.theme.manager.Meta.getInstance().initialize();qx.ui.tooltip.Manager.getInstance();this.__nv=this._createRootWidget();},finalize:function(){this.render();},render:function(){qx.ui.core.queue.Manager.flush();},close:function(c){},terminate:function(){}},destruct:function(){this.__nv=null;}});})();(function(){var a="qx.application.Standalone";qx.Class.define(a,{extend:qx.application.AbstractGui,members:{_createRootWidget:function(){return new qx.ui.root.Application(document);}}});})();(function(){var e="controller",d="script/apidata.json",c="apiviewer/css/apiviewer.css",b="apiviewer.Application",a="viewer";qx.Class.define(b,{extend:qx.application.Standalone,construct:function(){qx.application.Standalone.call(this);qx.bom.Stylesheet.includeFile(c);},members:{main:function(){qx.application.Standalone.prototype.main.call(this);{};qx.Class.include(qx.ui.core.Widget,apiviewer.MWidgetRegistry);this.viewer=new apiviewer.Viewer();this.controller=new apiviewer.Controller();this.getRoot().add(this.viewer,{edge:0});},finalize:function(){qx.application.Standalone.prototype.finalize.call(this);this.controller.load(d);}},destruct:function(){this._disposeObjects(a,e);}});})();(function(){var f="_applyTheme",e="qx.theme",d="qx.theme.manager.Meta",c="qx.theme.Modern",b="Theme",a="singleton";qx.Class.define(d,{type:a,extend:qx.core.Object,properties:{theme:{check:b,nullable:true,apply:f}},members:{_applyTheme:function(g,h){var k=null;var n=null;var q=null;var r=null;var m=null;if(g){k=g.meta.color||null;n=g.meta.decoration||null;q=g.meta.font||null;r=g.meta.icon||null;m=g.meta.appearance||null;}var o=qx.theme.manager.Color.getInstance();var p=qx.theme.manager.Decoration.getInstance();var i=qx.theme.manager.Font.getInstance();var l=qx.theme.manager.Icon.getInstance();var j=qx.theme.manager.Appearance.getInstance();o.setTheme(k);p.setTheme(n);i.setTheme(q);l.setTheme(r);j.setTheme(m);},initialize:function(){var t=qx.core.Setting;var s,u;s=t.get(e);if(s){u=qx.Theme.getByName(s);if(!u){throw new Error("The theme to use is not available: "+s);}this.setTheme(u);}}},settings:{"qx.theme":c}});})();(function(){var e="qx.theme.manager.Icon",d="Theme",c="changeTheme",b="_applyTheme",a="singleton";qx.Class.define(e,{type:a,extend:qx.core.Object,properties:{theme:{check:d,nullable:true,apply:b,event:c}},members:{_applyTheme:function(f,g){var i=qx.util.AliasManager.getInstance();if(g){for(var h in g.aliases){i.remove(h);}}if(f){for(var h in f.aliases){i.add(h,f.aliases[h]);}}}}});})();(function(){var p="Boolean",o="focusout",n="interval",m="mouseover",l="mouseout",k="mousemove",j="widget",i="qx.ui.tooltip.ToolTip",h="_applyCurrent",g="qx.ui.tooltip.Manager",c="__qV",f="__qS",d="tooltip-error",b="__qT",a="singleton";qx.Class.define(g,{type:a,extend:qx.core.Object,construct:function(){qx.core.Object.call(this);qx.event.Registration.addListener(document.body,m,this.__rd,this,true);this.__qS=new qx.event.Timer();this.__qS.addListener(n,this.__ra,this);this.__qT=new qx.event.Timer();this.__qT.addListener(n,this.__rb,this);this.__qU={left:0,top:0};},properties:{current:{check:i,nullable:true,apply:h},showInvalidToolTips:{check:p,init:true},showToolTips:{check:p,init:true}},members:{__qU:null,__qT:null,__qS:null,__qV:null,__qW:null,__qX:function(){if(!this.__qV){this.__qV=new qx.ui.tooltip.ToolTip().set({rich:true});}return this.__qV;},__qY:function(){if(!this.__qW){this.__qW=new qx.ui.tooltip.ToolTip().set({appearance:d});this.__qW.syncAppearance();}return this.__qW;},_applyCurrent:function(q,r){if(r&&qx.ui.core.Widget.contains(r,q)){return;}if(r){if(!r.isDisposed()){r.exclude();}this.__qS.stop();this.__qT.stop();}var t=qx.event.Registration;var s=document.body;if(q){this.__qS.startWith(q.getShowTimeout());t.addListener(s,l,this.__re,this,true);t.addListener(s,o,this.__rf,this,true);t.addListener(s,k,this.__rc,this,true);}else{t.removeListener(s,l,this.__re,this,true);t.removeListener(s,o,this.__rf,this,true);t.removeListener(s,k,this.__rc,this,true);}},__ra:function(e){var u=this.getCurrent();if(u&&!u.isDisposed()){this.__qT.startWith(u.getHideTimeout());if(u.getPlaceMethod()==j){u.placeToWidget(u.getOpener());}else{u.placeToPoint(this.__qU);}u.show();}this.__qS.stop();},__rb:function(e){var v=this.getCurrent();if(v&&!v.isDisposed()){v.exclude();}this.__qT.stop();this.resetCurrent();},__rc:function(e){var w=this.__qU;w.left=e.getDocumentLeft();w.top=e.getDocumentTop();},__rd:function(e){var z=qx.ui.core.Widget.getWidgetByElement(e.getTarget());if(!z){return;}var A,B,y,x;while(z!=null){A=z.getToolTip();B=z.getToolTipText()||null;y=z.getToolTipIcon()||null;if(qx.Class.hasInterface(z.constructor,qx.ui.form.IForm)&&!z.isValid()){x=z.getInvalidMessage();}if(A||B||y||x){break;}z=z.getLayoutParent();}if(!z||!z.getEnabled()||z.isBlockToolTip()||(!x&&!this.getShowToolTips())||(x&&!this.getShowInvalidToolTips())){return;}if(x){A=this.__qY().set({label:x});}if(!A){A=this.__qX().set({label:B,icon:y});}this.setCurrent(A);A.setOpener(z);},__re:function(e){var C=qx.ui.core.Widget.getWidgetByElement(e.getTarget());if(!C){return;}var D=qx.ui.core.Widget.getWidgetByElement(e.getRelatedTarget());if(!D){return;}var E=this.getCurrent();if(E&&(D==E||qx.ui.core.Widget.contains(E,D))){return;}if(D&&C&&qx.ui.core.Widget.contains(C,D)){return;}if(E&&!D){this.setCurrent(null);}else{this.resetCurrent();}},__rf:function(e){var F=qx.ui.core.Widget.getWidgetByElement(e.getTarget());if(!F){return;}var G=this.getCurrent();if(G&&G==F.getToolTip()){this.setCurrent(null);}}},destruct:function(){qx.event.Registration.removeListener(document.body,m,this.__rd,this,true);this._disposeObjects(f,b,c);this.__qU=null;}});})();(function(){var c="_applyId",b="String",a="apiviewer.MWidgetRegistry";qx.Mixin.define(a,{properties:{id:{check:b,apply:c,nullable:true,init:null}},members:{_applyId:function(d,e){var f=apiviewer.MWidgetRegistry;if(e){f.unregister(this,e);}if(d){f.register(this,d);}},getWidgetById:function(g){return apiviewer.MWidgetRegistry.getWidgetById(g);}},statics:{__Te:{},getWidgetById:function(h){return this.__Te[h];},register:function(i,j){if(this.__Te[j]){throw new Error("An object with the id '"+j+"' already exists.");}this.__Te[j]=i;},unregister:function(k,l){if(this.__Te[l]!==k){throw new Error("The object is not registered with the id '"+l+"'.");}delete (this.__Te[l]);}}});})();(function(){var k="value",j="nodeName",i="showPrivate",h="#",g="expandProperties",f="changeSelection",d="(",c="showInherited",b="showProtected",a="request",L="mousedown",K="btn_inherited",J=")",I="application",H="_detailLoader",G="aborted",F="_classLoader",E="btn_protected",D="detail_loader",C=" - ",r="btn_expand",s="$1#$2",p="package",q="tree",n="./script",o="btn_private",l="apiviewer.Controller",m="_tabViewController",t="completed",u="failed",x="$1~$2",w="API Documentation",z="file:",y="_history",B="_tree",A="itemName",v="classLinkClicked";qx.Class.define(l,{extend:qx.core.Object,construct:function(M){qx.core.Object.call(this);this._widgetRegistry=apiviewer.MWidgetRegistry;this._titlePrefix=w;document.title=this._titlePrefix;this._classLoader=new apiviewer.ClassLoader(n);this._detailLoader=this._widgetRegistry.getWidgetById(D);this._tabViewController=new apiviewer.TabViewController(this._widgetRegistry);this.__Tg();this._tree=this._widgetRegistry.getWidgetById(q);this.__Th();this.__Ti();this._history=qx.bom.History.getInstance();this.__Tj();qx.core.Init.getApplication().getRoot().addListener(L,function(e){this.__Tf=e.isShiftPressed()||e.isCtrlOrCommandPressed();},this,true);},members:{__Tf:false,$$logCategory:I,load:function(N){var P=new qx.io.remote.Request(N);P.setTimeout(180000);P.setProhibitCaching(false);P.addListener(t,function(R){var V=new Date();{};var content=R.getContent();var S=new Date();var T=eval(d+content+J);var U=new Date();{};qx.event.Timer.once(function(){this.__Tk(T);qx.event.Timer.once(function(){var W=this._history.getState();if(W){this.__Tl(this.__Tn(W));}else{var Y=this.__To(T);var X=Y.attributes.fullName;this.__Tl(X);}},this,0);},this,0);},this);var O=function(ba){this.error("Couldn't load file: "+N);if(window.location.protocol==z){alert("Failed to load API data from the file system.\n\n"+"The security settings of your browser may prohibit AJAX "+"when using the file protocol. Please try the http protocol "+"instead.");}};P.addListener(u,O,this);P.addListener(G,O,this);var Q=new Date();P.send();},__Tg:function(){this._tabViewController.addListener(v,function(bb){this._updateHistory(bb.getData());},this);this._tabViewController.addListener(f,function(bc){var be=bc.getData()[0];if(this._ignoreTabViewSelection==true){return;}if(be&&be.getUserData(j)){var bf=be.getUserData(j);var bd=be.getUserData(A);if(bd!=null){this._updateHistory(bf+h+bd);}else{this._updateHistory(bf);}}else{this._tree.resetSelection();}},this);},__Th:function(){this._tree.addListener(f,function(bg){var bh=bg.getData()[0];if(bh&&bh.getUserData(j)&&!this._ignoreTreeSelection){var bi=bh.getUserData(j);this._updateHistory(bi);}},this);},__Ti:function(){var bk=apiviewer.UiModel.getInstance();var bm=this._widgetRegistry.getWidgetById(K);bm.bind(k,bk,c);bk.bind(c,bm,k);var bj=this._widgetRegistry.getWidgetById(r);bj.bind(k,bk,g);bk.bind(g,bj,k);var bl=this._widgetRegistry.getWidgetById(E);bl.bind(k,bk,b);bk.bind(b,bl,k);var bn=this._widgetRegistry.getWidgetById(o);bn.bind(k,bk,i);bk.bind(i,bn,k);},__Tj:function(){this._history.addListener(a,function(bo){var bp=this.__Tn(bo.getData());if(bp){this.__Tl(bp);}},this);},__Tk:function(bq){var br=new Date();var bs=new apiviewer.dao.Package(bq);var bt=new Date();{};var br=new Date();this._tree.setTreeData(bs);var bt=new Date();{};return true;},_updateHistory:function(bu){var bv=bu+C+this._titlePrefix;qx.bom.History.getInstance().addToHistory(this.__Tm(bu),bv);},_selectClass:function(bw,bx,self){this._detailLoader.exclude();this._tabViewController.showTabView();var by=bx?qx.lang.Function.bind(bx,self):function(){};if(bw instanceof apiviewer.dao.Class){this._classLoader.classLoadDependendClasses(bw,function(bz){this._tabViewController.openClass(bz,this.__Tf);by();},this);}else{this._classLoader.packageLoadDependendClasses(bw,function(){this._tabViewController.openPackage(bw,this.__Tf);by();},this);}},__Tl:function(bA){var bD=bA;var bG=null;var bC=bA.indexOf(h);if(bC!=-1){bD=bA.substring(0,bC);bG=bA.substring(bC+1);var bE=bG.indexOf(d);if(bE!=-1){bG=qx.lang.String.trim(bG.substring(0,bE));}}this._ignoreTreeSelection=true;var bF=this._tree.selectTreeNodeByClassName(bD);this._ignoreTreeSelection=false;if(!bF){this.error("Unknown class: "+bD);alert("Unknown class: "+bD);return;}var bB=this._tree.getSelection()[0].getUserData(j)||bD;this._ignoreTabViewSelection=true;this._selectClass(apiviewer.dao.Class.getClassByName(bB),function(){if(bG){if(!this._tabViewController.showItem(bG)){this.error("Unknown item of class '"+bD+"': "+bG);alert("Unknown item of class '"+bD+"': "+bG);this._updateHistory(bD);this._ignoreTabViewSelection=false;return;}}this._updateHistory(bA);this._ignoreTabViewSelection=false;},this);},__Tm:function(bH){return bH.replace(/(.*)#(.*)/g,x);},__Tn:function(bI){return bI.replace(/(.*)~(.*)/g,s);},__To:function(bJ){if(bJ.type&&bJ.type==p){return bJ;}else{return this.__To(bJ.children[0]);}}},destruct:function(){this._widgetRegistry=null;this._disposeObjects(H,F,B,y,m);}});})();(function(){var m="",l='#',k="String",j="request",i="mshtml",h="changeTitle",g="abstract",f="_applyState",e="qx.client",d="changeState",a="qx.bom.History",c="_applyTitle",b="qx.event.type.Data";qx.Class.define(a,{extend:qx.core.Object,type:g,construct:function(){qx.core.Object.call(this);this._baseUrl=window.location.href.split(l)[0]+l;this.__vx={};this._setInitialState();},events:{"request":b},statics:{SUPPORTS_HASH_CHANGE_EVENT:(qx.bom.client.Engine.MSHTML&&document.documentMode>=8)||(!qx.bom.client.Engine.MSHTML&&document.documentMode&&"onhashchange" in window),getInstance:function(){if(!this.$$instance){if(this.SUPPORTS_HASH_CHANGE_EVENT){this.$$instance=new qx.bom.NativeHistory();}else if(qx.core.Variant.isSet(e,i)){this.$$instance=new qx.bom.IframeHistory();}else{this.$$instance=new qx.bom.NativeHistory();}}return this.$$instance;}},properties:{title:{check:k,event:h,nullable:true,apply:c},state:{check:k,event:d,nullable:true,apply:f}},members:{__vx:null,_applyState:function(n,o){this._writeState(n);},_setInitialState:function(){this.setState(this._readState());},_encode:function(p){if(qx.lang.Type.isString(p)){return encodeURIComponent(p);}return m;},_decode:function(q){if(qx.lang.Type.isString(q)){return decodeURIComponent(q);}return m;},_applyTitle:function(r){if(r!=null){document.title=r||m;}},addToHistory:function(s,t){if(!qx.lang.Type.isString(s)){s=s+m;}if(qx.lang.Type.isString(t)){this.setTitle(t);this.__vx[s]=t;}if(this.getState()!==s){this._writeState(s);}},navigateBack:function(){qx.event.Timer.once(function(){history.back();},0);},navigateForward:function(){qx.event.Timer.once(function(){history.forward();},0);},_onHistoryLoad:function(u){this.setState(u);this.fireDataEvent(j,u);if(this.__vx[u]!=null){this.setTitle(this.__vx[u]);}},_readState:function(){throw new Error("Abstract method call");},_writeState:function(){throw new Error("Abstract method call");},_setHash:function(v){var w=this._baseUrl+(v||m);var x=window.location;if(w!=x.href){x.href=w;}},_getHash:function(){var y=/#(.*)$/.exec(window.location.href);return y&&y[1]?y[1]:m;}},destruct:function(){this.__vx=null;}});})();(function(){var d="hashchange",c="interval",b="qx.bom.NativeHistory",a="qx.client";qx.Class.define(b,{extend:qx.bom.History,construct:function(){qx.bom.History.call(this);this.__vz();},members:{__vy:null,__vz:function(){if(qx.bom.History.SUPPORTS_HASH_CHANGE_EVENT){this.__vy=qx.lang.Function.bind(this.__vB,this);qx.bom.Event.addNativeListener(window,d,this.__vy);}else{qx.event.Idle.getInstance().addListener(c,this.__vB,this);}},__vA:function(){if(qx.bom.History.SUPPORTS_HASH_CHANGE_EVENT){qx.bom.Event.removeNativeListener(window,d,this.__vy);}else{qx.event.Idle.getInstance().removeListener(c,this.__vB,this);}},__vB:function(){var e=this._readState();if(qx.lang.Type.isString(e)&&e!=this.getState()){this._onHistoryLoad(e);}},_readState:function(){return this._decode(this._getHash());},_writeState:qx.core.Variant.select(a,{"opera":function(f){qx.event.Timer.once(function(){this._setHash(this._encode(f));},this,0);},"default":function(g){this._setHash(this._encode(g));}})},destruct:function(){this.__vA();}});})();(function(){var n="interval",m="-1000px",l="mshtml",k="",j="qx.bom.IframeHistory",i="qx/static/blank.html",h="state",g='<html><body><div id="state">',f='</div></body></html>',d="hidden",a="qx.client",c="undefined",b="absolute";if(qx.core.Variant.isSet(a,l)){qx.Class.define(j,{extend:qx.bom.History,construct:function(){qx.bom.History.call(this);this.__vF();},members:{__vC:null,__vD:false,__vE:null,_setInitialState:function(){qx.bom.History.prototype._setInitialState.call(this);this.__vE=this._getHash();},_setHash:function(o){qx.bom.History.prototype._setHash.call(this,o);this.__vE=this._encode(o);},_readState:function(){if(!this.__vD){return this._decode(this._getHash());}var p=this.__vC.contentWindow.document;var q=p.getElementById(h);return q?this._decode(q.innerText):k;},_writeState:function(r){var r=this._encode(r);this._setHash(r);this.__vE=r;try{var s=this.__vC.contentWindow.document;s.open();s.write(g+r+f);s.close();}catch(t){}},__vF:function(){this.__vJ(function(){qx.event.Idle.getInstance().addListener(n,this.__vG,this);});},__vG:function(e){var v=null;var u=this._getHash();if(!this.__vI(u)){v=this.__vH(u);}else{v=this._readState();}if(qx.lang.Type.isString(v)&&v!=this.getState()){this._onHistoryLoad(v);}},__vH:function(w){w=this._decode(w);this._writeState(w);return w;},__vI:function(x){return qx.lang.Type.isString(x)&&x==this.__vE;},__vJ:function(y){this.__vC=this.__vK();document.body.appendChild(this.__vC);this.__vL(function(){this._writeState(this.getState());if(y){y.call(this);}},this);},__vK:function(){var z=qx.bom.Iframe.create({src:qx.util.ResourceManager.getInstance().toUri(i)});z.style.visibility=d;z.style.position=b;z.style.left=m;z.style.top=m;return z;},__vL:function(A,B,C){if(typeof C===c){C=0;}if(!this.__vC.contentWindow||!this.__vC.contentWindow.document){if(C>20){throw new Error("can't initialize iframe");}qx.event.Timer.once(function(){this.__vL(A,B,++C);},this,10);return;}this.__vD=true;A.call(B||window);}},destruct:function(){this.__vC=null;qx.event.Idle.getInstance().addListener(n,this.__vG,this);}});}})();(function(){var n="Liberation Sans",m="Arial",l="Lucida Grande",k="sans-serif",j="Tahoma",i="Candara",h="Segoe UI",g="Consolas",f="Courier New",e="Monaco",b="monospace",d="Lucida Console",c="qx.theme.modern.Font",a="DejaVu Sans Mono";qx.Theme.define(c,{fonts:{"default":{size:(qx.bom.client.System.WINVISTA||qx.bom.client.System.WIN7)?12:11,lineHeight:1.4,family:qx.bom.client.Platform.MAC?[l]:(qx.bom.client.System.WINVISTA||qx.bom.client.System.WIN7)?[h,i]:[j,n,m,k]},"bold":{size:(qx.bom.client.System.WINVISTA||qx.bom.client.System.WIN7)?12:11,lineHeight:1.4,family:qx.bom.client.Platform.MAC?[l]:(qx.bom.client.System.WINVISTA||qx.bom.client.System.WIN7)?[h,i]:[j,n,m,k],bold:true},"small":{size:(qx.bom.client.System.WINVISTA||qx.bom.client.System.WIN7)?11:10,lineHeight:1.4,family:qx.bom.client.Platform.MAC?[l]:(qx.bom.client.System.WINVISTA||qx.bom.client.System.WIN7)?[h,i]:[j,n,m,k]},"monospace":{size:11,lineHeight:1.4,family:qx.bom.client.Platform.MAC?[d,e]:(qx.bom.client.System.WINVISTA||qx.bom.client.System.WIN7)?[g]:[g,a,f,b]}}});})();(function(){var c="Tango",b="qx/icon/Tango",a="qx.theme.icon.Tango";qx.Theme.define(a,{title:c,aliases:{"icon":b},icons:{}});})();(function(){var i="Number",h="_applyInsets",g="abstract",f="insetRight",e="insetTop",d="insetBottom",c="qx.ui.decoration.Abstract",b="shorthand",a="insetLeft";qx.Class.define(c,{extend:qx.core.Object,implement:[qx.ui.decoration.IDecorator],type:g,properties:{insetLeft:{check:i,nullable:true,apply:h},insetRight:{check:i,nullable:true,apply:h},insetBottom:{check:i,nullable:true,apply:h},insetTop:{check:i,nullable:true,apply:h},insets:{group:[e,f,d,a],mode:b}},members:{__oa:null,_getDefaultInsets:function(){throw new Error("Abstract method called.");},_isInitialized:function(){throw new Error("Abstract method called.");},_resetInsets:function(){this.__oa=null;},getInsets:function(){if(this.__oa){return this.__oa;}var j=this._getDefaultInsets();return this.__oa={left:this.getInsetLeft()==null?j.left:this.getInsetLeft(),right:this.getInsetRight()==null?j.right:this.getInsetRight(),bottom:this.getInsetBottom()==null?j.bottom:this.getInsetBottom(),top:this.getInsetTop()==null?j.top:this.getInsetTop()};},_applyInsets:function(){{};this.__oa=null;}},destruct:function(){this.__oa=null;}});})();(function(){var q="_applyBackground",p="repeat",o="mshtml",n="backgroundPositionX",m="",l="backgroundPositionY",k="no-repeat",j="scale",i=" ",h="repeat-x",c="qx.client",g="repeat-y",f="hidden",b="qx.ui.decoration.MBackgroundImage",a="String",e='"></div>',d='<div style="';qx.Mixin.define(b,{properties:{backgroundImage:{check:a,nullable:true,apply:q},backgroundRepeat:{check:[p,h,g,k,j],init:p,apply:q},backgroundPositionX:{nullable:true,apply:q},backgroundPositionY:{nullable:true,apply:q},backgroundPosition:{group:[l,n]}},members:{_generateBackgroundMarkup:function(r){var v=m;var u=this.getBackgroundImage();var t=this.getBackgroundRepeat();var top=this.getBackgroundPositionY();if(top==null){top=0;}var w=this.getBackgroundPositionX();if(w==null){w=0;}r.backgroundPosition=w+i+top;if(u){var s=qx.util.AliasManager.getInstance().resolve(u);v=qx.bom.element.Decoration.create(s,t,r);}else{if(r){if(qx.core.Variant.isSet(c,o)){if(qx.bom.client.Engine.VERSION<7||qx.bom.client.Feature.QUIRKS_MODE){r.overflow=f;}}v=d+qx.bom.element.Style.compile(r)+e;}}return v;},_applyBackground:function(){{};}}});})();(function(){var j="_applyStyle",i="solid",h="Color",g="",f="double",e="px",d="px ",c="dotted",b="_applyWidth",a="dashed",E="Number",D=" ",C="shorthand",B="widthTop",A="styleRight",z="styleLeft",y="widthLeft",x="widthBottom",w="styleTop",v="colorBottom",q="styleBottom",r="widthRight",o="colorLeft",p="colorRight",m="colorTop",n="border-top",k="border-left",l="border-right",s="qx.ui.decoration.Single",t="border-bottom",u="absolute";qx.Class.define(s,{extend:qx.ui.decoration.Abstract,include:[qx.ui.decoration.MBackgroundImage],construct:function(F,G,H){qx.ui.decoration.Abstract.call(this);if(F!=null){this.setWidth(F);}if(G!=null){this.setStyle(G);}if(H!=null){this.setColor(H);}},properties:{widthTop:{check:E,init:0,apply:b},widthRight:{check:E,init:0,apply:b},widthBottom:{check:E,init:0,apply:b},widthLeft:{check:E,init:0,apply:b},styleTop:{nullable:true,check:[i,c,a,f],init:i,apply:j},styleRight:{nullable:true,check:[i,c,a,f],init:i,apply:j},styleBottom:{nullable:true,check:[i,c,a,f],init:i,apply:j},styleLeft:{nullable:true,check:[i,c,a,f],init:i,apply:j},colorTop:{nullable:true,check:h,apply:j},colorRight:{nullable:true,check:h,apply:j},colorBottom:{nullable:true,check:h,apply:j},colorLeft:{nullable:true,check:h,apply:j},backgroundColor:{check:h,nullable:true,apply:j},left:{group:[y,z,o]},right:{group:[r,A,p]},top:{group:[B,w,m]},bottom:{group:[x,q,v]},width:{group:[B,r,x,y],mode:C},style:{group:[w,A,q,z],mode:C},color:{group:[m,p,v,o],mode:C}},members:{__pl:null,_getDefaultInsets:function(){return {top:this.getWidthTop(),right:this.getWidthRight(),bottom:this.getWidthBottom(),left:this.getWidthLeft()};},_isInitialized:function(){return !!this.__pl;},getMarkup:function(I){if(this.__pl){return this.__pl;}var J=qx.theme.manager.Color.getInstance();var K={};var M=this.getWidthTop();if(M>0){K[n]=M+d+this.getStyleTop()+D+(J.resolve(this.getColorTop())||g);}var M=this.getWidthRight();if(M>0){K[l]=M+d+this.getStyleRight()+D+(J.resolve(this.getColorRight())||g);}var M=this.getWidthBottom();if(M>0){K[t]=M+d+this.getStyleBottom()+D+(J.resolve(this.getColorBottom())||g);}var M=this.getWidthLeft();if(M>0){K[k]=M+d+this.getStyleLeft()+D+(J.resolve(this.getColorLeft())||g);}{};K.position=u;K.top=0;K.left=0;var L=this._generateBackgroundMarkup(K);return this.__pl=L;},resize:function(N,O,P){var Q=this.getInsets();O-=Q.left+Q.right;P-=Q.top+Q.bottom;if(O<0){O=0;}if(P<0){P=0;}N.style.width=O+e;N.style.height=P+e;N.style.left=(parseInt(N.style.left,10)+Q.left-this.getWidthLeft())+e;N.style.top=(parseInt(N.style.top,10)+Q.top-this.getWidthTop())+e;},tint:function(R,S){var T=qx.theme.manager.Color.getInstance();if(S==null){S=this.getBackgroundColor();}R.style.backgroundColor=T.resolve(S)||g;},_applyWidth:function(){{};this._resetInsets();},_applyStyle:function(){{};}},destruct:function(){this.__pl=null;}});})();(function(){var f="px",e="qx.ui.decoration.Background",d="",c="_applyStyle",b="Color",a="absolute";qx.Class.define(e,{extend:qx.ui.decoration.Abstract,include:[qx.ui.decoration.MBackgroundImage],construct:function(g){qx.ui.decoration.Abstract.call(this);if(g!=null){this.setBackgroundColor(g);}},properties:{backgroundColor:{check:b,nullable:true,apply:c}},members:{__oe:null,_getDefaultInsets:function(){return {top:0,right:0,bottom:0,left:0};},_isInitialized:function(){return !!this.__oe;},getMarkup:function(){if(this.__oe){return this.__oe;}var h={position:a,top:0,left:0};var i=this._generateBackgroundMarkup(h);return this.__oe=i;},resize:function(j,k,l){var m=this.getInsets();j.style.width=(k-m.left-m.right)+f;j.style.height=(l-m.top-m.bottom)+f;j.style.left=-m.left+f;j.style.top=-m.top+f;},tint:function(n,o){var p=qx.theme.manager.Color.getInstance();if(o==null){o=this.getBackgroundColor();}n.style.backgroundColor=p.resolve(o)||d;},_applyStyle:function(){{};}},destruct:function(){this.__oe=null;}});})();(function(){var j="_applyStyle",i='"></div>',h="Color",g="1px",f='<div style="',e='border:',d="1px solid ",c="",b=";",a="px",v='</div>',u="qx.ui.decoration.Beveled",t='<div style="position:absolute;top:1px;left:1px;',s='border-bottom:',r='border-right:',q='border-left:',p='border-top:',o="Number",n='<div style="position:absolute;top:1px;left:0px;',m='position:absolute;top:0px;left:1px;',k='<div style="overflow:hidden;font-size:0;line-height:0;">',l="absolute";qx.Class.define(u,{extend:qx.ui.decoration.Abstract,include:[qx.ui.decoration.MBackgroundImage],construct:function(w,x,y){qx.ui.decoration.Abstract.call(this);if(w!=null){this.setOuterColor(w);}if(x!=null){this.setInnerColor(x);}if(y!=null){this.setInnerOpacity(y);}},properties:{innerColor:{check:h,nullable:true,apply:j},innerOpacity:{check:o,init:1,apply:j},outerColor:{check:h,nullable:true,apply:j},backgroundColor:{check:h,nullable:true,apply:j}},members:{__ry:null,_getDefaultInsets:function(){return {top:2,right:2,bottom:2,left:2};},_isInitialized:function(){return !!this.__ry;},_applyStyle:function(){{};},getMarkup:function(){if(this.__ry){return this.__ry;}var z=qx.theme.manager.Color.getInstance();var A=[];var D=d+z.resolve(this.getOuterColor())+b;var C=d+z.resolve(this.getInnerColor())+b;A.push(k);A.push(f);A.push(e,D);A.push(qx.bom.element.Opacity.compile(0.35));A.push(i);A.push(n);A.push(q,D);A.push(r,D);A.push(qx.bom.element.Opacity.compile(1));A.push(i);A.push(f);A.push(m);A.push(p,D);A.push(s,D);A.push(qx.bom.element.Opacity.compile(1));A.push(i);var B={position:l,top:g,left:g,opacity:1};A.push(this._generateBackgroundMarkup(B));A.push(t);A.push(e,C);A.push(qx.bom.element.Opacity.compile(this.getInnerOpacity()));A.push(i);A.push(v);return this.__ry=A.join(c);},resize:function(E,F,G){if(F<4){F=4;}if(G<4){G=4;}if(qx.bom.client.Feature.CONTENT_BOX){var outerWidth=F-2;var outerHeight=G-2;var M=outerWidth;var L=outerHeight;var innerWidth=F-4;var innerHeight=G-4;}else{var outerWidth=F;var outerHeight=G;var M=F-2;var L=G-2;var innerWidth=M;var innerHeight=L;}var O=a;var K=E.childNodes[0].style;K.width=outerWidth+O;K.height=outerHeight+O;var J=E.childNodes[1].style;J.width=outerWidth+O;J.height=L+O;var I=E.childNodes[2].style;I.width=M+O;I.height=outerHeight+O;var H=E.childNodes[3].style;H.width=M+O;H.height=L+O;var N=E.childNodes[4].style;N.width=innerWidth+O;N.height=innerHeight+O;},tint:function(P,Q){var R=qx.theme.manager.Color.getInstance();if(Q==null){Q=this.getBackgroundColor();}P.childNodes[3].style.backgroundColor=R.resolve(Q)||c;}},destruct:function(){this.__ry=null;}});})();(function(){var o="_applyStyle",n="",m="Color",l="px",k="solid",j="dotted",i="double",h="dashed",g="_applyWidth",f="qx.ui.decoration.Uniform",c="px ",e=" ",d="scale",b="PositiveInteger",a="absolute";qx.Class.define(f,{extend:qx.ui.decoration.Abstract,include:[qx.ui.decoration.MBackgroundImage],construct:function(p,q,r){qx.ui.decoration.Abstract.call(this);if(p!=null){this.setWidth(p);}if(q!=null){this.setStyle(q);}if(r!=null){this.setColor(r);}},properties:{width:{check:b,init:0,apply:g},style:{nullable:true,check:[k,j,h,i],init:k,apply:o},color:{nullable:true,check:m,apply:o},backgroundColor:{check:m,nullable:true,apply:o}},members:{__rP:null,_getDefaultInsets:function(){var s=this.getWidth();return {top:s,right:s,bottom:s,left:s};},_isInitialized:function(){return !!this.__rP;},getMarkup:function(){if(this.__rP){return this.__rP;}var t={position:a,top:0,left:0};var u=this.getWidth();{};var w=qx.theme.manager.Color.getInstance();t.border=u+c+this.getStyle()+e+(w.resolve(this.getColor())||n);var v=this._generateBackgroundMarkup(t);return this.__rP=v;},resize:function(x,y,z){var B=this.getBackgroundImage()&&this.getBackgroundRepeat()==d;if(B||qx.bom.client.Feature.CONTENT_BOX){var A=this.getWidth()*2;y-=A;z-=A;if(y<0){y=0;}if(z<0){z=0;}}x.style.width=y+l;x.style.height=z+l;},tint:function(C,D){var E=qx.theme.manager.Color.getInstance();if(D==null){D=this.getBackgroundColor();}C.style.backgroundColor=E.resolve(D)||n;},_applyWidth:function(){{};this._resetInsets();},_applyStyle:function(){{};}},destruct:function(){this.__rP=null;}});})();(function(){var m="Number",l="_applyInsets",k="-l",j="insetRight",i="insetTop",h="_applyBaseImage",g="insetBottom",f="set",e="shorthand",d="-t",a="insetLeft",c="String",b="qx.ui.decoration.Grid";qx.Class.define(b,{extend:qx.core.Object,implement:[qx.ui.decoration.IDecorator],construct:function(n,o){qx.core.Object.call(this);if(qx.ui.decoration.css3.BorderImage.IS_SUPPORTED){this.__oA=new qx.ui.decoration.css3.BorderImage();if(n){this.__oB(n);}}else{this.__oA=new qx.ui.decoration.GridDiv(n);}if(o!=null){this.__oA.setInsets(o);}},properties:{baseImage:{check:c,nullable:true,apply:h},insetLeft:{check:m,nullable:true,apply:l},insetRight:{check:m,nullable:true,apply:l},insetBottom:{check:m,nullable:true,apply:l},insetTop:{check:m,nullable:true,apply:l},insets:{group:[i,j,g,a],mode:e}},members:{__oA:null,getMarkup:function(){return this.__oA.getMarkup();},resize:function(p,q,r){this.__oA.resize(p,q,r);},tint:function(s,t){},getInsets:function(){return this.__oA.getInsets();},_applyInsets:function(u,v,name){var w=f+qx.lang.String.firstUp(name);this.__oA[w](u);},_applyBaseImage:function(x,y){if(this.__oA instanceof qx.ui.decoration.GridDiv){this.__oA.setBaseImage(x);}else{this.__oB(x);}},__oB:function(z){var B,D;this.__oA.setBorderImage(z);var F=qx.util.AliasManager.getInstance().resolve(z);var G=/(.*)(\.[a-z]+)$/.exec(F);var C=G[1];var E=G[2];var A=qx.util.ResourceManager.getInstance();var H=A.getImageHeight(C+d+E);var I=A.getImageWidth(C+k+E);{};this.__oA.setSlice([H,I]);}},destruct:function(){this.__oA=null;}});})();(function(){var m="solid",l="scale",k="border-main",j="white",i="repeat-x",h="border-separator",g="background-light",f="invalid",e="border-focused-invalid",d="border-input",bt="border-disabled",bs="decoration/table/header-cell.png",br="decoration/form/input.png",bq="#f8f8f8",bp="decoration/scrollbar/scrollbar-button-bg-horizontal.png",bo="#b6b6b6",bn="background-pane",bm="repeat-y",bl="decoration/form/input-focused.png",bk="#33508D",t="decoration/selection.png",u="decoration/scrollbar/scrollbar-button-bg-vertical.png",r="decoration/tabview/tab-button-top-active.png",s="black",p="decoration/group-item.png",q="decoration/form/button-c.png",n="decoration/scrollbar/scrollbar-bg-vertical.png",o="decoration/form/button.png",B="decoration/form/button-checked.png",C="decoration/tabview/tab-button-left-inactive.png",O="decoration/groupbox/groupbox.png",K="#FAFAFA",W="decoration/pane/pane.png",R="dotted",bg="decoration/toolbar/toolbar-part.gif",bc="decoration/tabview/tab-button-top-inactive.png",G="decoration/menu/bar-background.png",bj="center",bi="decoration/tabview/tab-button-bottom-active.png",bh="decoration/form/button-hovered.png",F="decoration/form/tooltip-error-arrow.png",I="decoration/window/captionbar-inactive.png",J="qx/decoration/Modern",M="decoration/menu/background.png",P="decoration/window/statusbar.png",S="border-focused",Y="table-focus-indicator",be="#F2F2F2",v="decoration/form/button-checked-c.png",w="decoration/scrollbar/scrollbar-bg-horizontal.png",H="qx.theme.modern.Decoration",V="#f4f4f4",U="decoration/shadow/shadow-small.png",T="decoration/app-header.png",bb="decoration/tabview/tabview-pane.png",ba="decoration/form/tooltip-error.png",Q="decoration/form/button-focused.png",X="decoration/tabview/tab-button-bottom-inactive.png",a="decoration/form/button-disabled.png",bd="decoration/tabview/tab-button-right-active.png",x="decoration/form/button-pressed.png",y="no-repeat",L="decoration/window/captionbar-active.png",b="decoration/tabview/tab-button-left-active.png",c="background-splitpane",E="decoration/form/button-checked-focused.png",z="#C5C5C5",A="decoration/toolbar/toolbar-gradient.png",D="decoration/tabview/tab-button-right-inactive.png",N="#b8b8b8",bf="decoration/shadow/shadow.png";qx.Theme.define(H,{aliases:{decoration:J},decorations:{"main":{decorator:qx.ui.decoration.Uniform,style:{width:1,color:k}},"selected":{decorator:qx.ui.decoration.Background,style:{backgroundImage:t,backgroundRepeat:l}},"selected-dragover":{decorator:qx.ui.decoration.Single,style:{backgroundImage:t,backgroundRepeat:l,bottom:[2,m,bk]}},"dragover":{decorator:qx.ui.decoration.Single,style:{bottom:[2,m,bk]}},"pane":{decorator:qx.ui.decoration.Grid,style:{baseImage:W,insets:[0,2,3,0]}},"group":{decorator:qx.ui.decoration.Grid,style:{baseImage:O}},"border-invalid":{decorator:qx.ui.decoration.Beveled,style:{outerColor:f,innerColor:j,innerOpacity:0.5,backgroundImage:br,backgroundRepeat:i,backgroundColor:g}},"keyboard-focus":{decorator:qx.ui.decoration.Single,style:{width:1,color:s,style:R}},"separator-horizontal":{decorator:qx.ui.decoration.Single,style:{widthLeft:1,colorLeft:h}},"separator-vertical":{decorator:qx.ui.decoration.Single,style:{widthTop:1,colorTop:h}},"tooltip-error":{decorator:qx.ui.decoration.Grid,style:{baseImage:ba,insets:[2,5,5,2]}},"tooltip-error-arrow":{decorator:qx.ui.decoration.Background,style:{backgroundImage:F,backgroundPositionY:bj,backgroundRepeat:y,insets:[0,0,0,10]}},"shadow-window":{decorator:qx.ui.decoration.Grid,style:{baseImage:bf,insets:[4,8,8,4]}},"shadow-popup":{decorator:qx.ui.decoration.Grid,style:{baseImage:U,insets:[0,3,3,0]}},"scrollbar-horizontal":{decorator:qx.ui.decoration.Background,style:{backgroundImage:w,backgroundRepeat:i}},"scrollbar-vertical":{decorator:qx.ui.decoration.Background,style:{backgroundImage:n,backgroundRepeat:bm}},"scrollbar-slider-horizontal":{decorator:qx.ui.decoration.Beveled,style:{backgroundImage:bp,backgroundRepeat:l,outerColor:k,innerColor:j,innerOpacity:0.5}},"scrollbar-slider-horizontal-disabled":{decorator:qx.ui.decoration.Beveled,style:{backgroundImage:bp,backgroundRepeat:l,outerColor:bt,innerColor:j,innerOpacity:0.3}},"scrollbar-slider-vertical":{decorator:qx.ui.decoration.Beveled,style:{backgroundImage:u,backgroundRepeat:l,outerColor:k,innerColor:j,innerOpacity:0.5}},"scrollbar-slider-vertical-disabled":{decorator:qx.ui.decoration.Beveled,style:{backgroundImage:u,backgroundRepeat:l,outerColor:bt,innerColor:j,innerOpacity:0.3}},"button":{decorator:qx.ui.decoration.Grid,style:{baseImage:o,insets:2}},"button-disabled":{decorator:qx.ui.decoration.Grid,style:{baseImage:a,insets:2}},"button-focused":{decorator:qx.ui.decoration.Grid,style:{baseImage:Q,insets:2}},"button-hovered":{decorator:qx.ui.decoration.Grid,style:{baseImage:bh,insets:2}},"button-pressed":{decorator:qx.ui.decoration.Grid,style:{baseImage:x,insets:2}},"button-checked":{decorator:qx.ui.decoration.Grid,style:{baseImage:B,insets:2}},"button-checked-focused":{decorator:qx.ui.decoration.Grid,style:{baseImage:E,insets:2}},"button-invalid-shadow":{decorator:qx.ui.decoration.Beveled,style:{outerColor:f,innerColor:e,insets:[1]}},"checkbox-invalid-shadow":{decorator:qx.ui.decoration.Beveled,style:{outerColor:f,innerColor:e,insets:[0]}},"input":{decorator:qx.ui.decoration.Beveled,style:{outerColor:d,innerColor:j,innerOpacity:0.5,backgroundImage:br,backgroundRepeat:i,backgroundColor:g}},"input-focused":{decorator:qx.ui.decoration.Beveled,style:{outerColor:d,innerColor:S,backgroundImage:bl,backgroundRepeat:i,backgroundColor:g}},"input-focused-invalid":{decorator:qx.ui.decoration.Beveled,style:{outerColor:f,innerColor:e,backgroundImage:bl,backgroundRepeat:i,backgroundColor:g,insets:[2]}},"input-disabled":{decorator:qx.ui.decoration.Beveled,style:{outerColor:bt,innerColor:j,innerOpacity:0.5,backgroundImage:br,backgroundRepeat:i,backgroundColor:g}},"toolbar":{decorator:qx.ui.decoration.Background,style:{backgroundImage:A,backgroundRepeat:l}},"toolbar-button-hovered":{decorator:qx.ui.decoration.Beveled,style:{outerColor:bo,innerColor:bq,backgroundImage:q,backgroundRepeat:l}},"toolbar-button-checked":{decorator:qx.ui.decoration.Beveled,style:{outerColor:bo,innerColor:bq,backgroundImage:v,backgroundRepeat:l}},"toolbar-separator":{decorator:qx.ui.decoration.Single,style:{widthLeft:1,widthRight:1,colorLeft:N,colorRight:V,styleLeft:m,styleRight:m}},"toolbar-part":{decorator:qx.ui.decoration.Background,style:{backgroundImage:bg,backgroundRepeat:bm}},"tabview-pane":{decorator:qx.ui.decoration.Grid,style:{baseImage:bb,insets:[4,6,7,4]}},"tabview-page-button-top-active":{decorator:qx.ui.decoration.Grid,style:{baseImage:r}},"tabview-page-button-top-inactive":{decorator:qx.ui.decoration.Grid,style:{baseImage:bc}},"tabview-page-button-bottom-active":{decorator:qx.ui.decoration.Grid,style:{baseImage:bi}},"tabview-page-button-bottom-inactive":{decorator:qx.ui.decoration.Grid,style:{baseImage:X}},"tabview-page-button-left-active":{decorator:qx.ui.decoration.Grid,style:{baseImage:b}},"tabview-page-button-left-inactive":{decorator:qx.ui.decoration.Grid,style:{baseImage:C}},"tabview-page-button-right-active":{decorator:qx.ui.decoration.Grid,style:{baseImage:bd}},"tabview-page-button-right-inactive":{decorator:qx.ui.decoration.Grid,style:{baseImage:D}},"splitpane":{decorator:qx.ui.decoration.Uniform,style:{backgroundColor:bn,width:3,color:c,style:m}},"window":{decorator:qx.ui.decoration.Single,style:{backgroundColor:bn,width:1,color:k,widthTop:0}},"window-captionbar-active":{decorator:qx.ui.decoration.Grid,style:{baseImage:L}},"window-captionbar-inactive":{decorator:qx.ui.decoration.Grid,style:{baseImage:I}},"window-statusbar":{decorator:qx.ui.decoration.Grid,style:{baseImage:P}},"table":{decorator:qx.ui.decoration.Single,style:{width:1,color:k,style:m}},"table-statusbar":{decorator:qx.ui.decoration.Single,style:{widthTop:1,colorTop:k,style:m}},"table-scroller-header":{decorator:qx.ui.decoration.Single,style:{backgroundImage:bs,backgroundRepeat:l,widthBottom:1,colorBottom:k,style:m}},"table-header-cell":{decorator:qx.ui.decoration.Single,style:{widthRight:1,colorRight:h,styleRight:m}},"table-header-cell-hovered":{decorator:qx.ui.decoration.Single,style:{widthRight:1,colorRight:h,styleRight:m,widthBottom:1,colorBottom:j,styleBottom:m}},"table-column-button":{decorator:qx.ui.decoration.Single,style:{backgroundImage:bs,backgroundRepeat:l,widthBottom:1,colorBottom:k,style:m}},"table-scroller-focus-indicator":{decorator:qx.ui.decoration.Single,style:{width:2,color:Y,style:m}},"progressive-table-header":{decorator:qx.ui.decoration.Single,style:{width:1,color:k,style:m}},"progressive-table-header-cell":{decorator:qx.ui.decoration.Single,style:{backgroundImage:bs,backgroundRepeat:l,widthRight:1,colorRight:be,style:m}},"menu":{decorator:qx.ui.decoration.Single,style:{backgroundImage:M,backgroundRepeat:l,width:1,color:k,style:m}},"menu-separator":{decorator:qx.ui.decoration.Single,style:{widthTop:1,colorTop:z,widthBottom:1,colorBottom:K}},"menubar":{decorator:qx.ui.decoration.Single,style:{backgroundImage:G,backgroundRepeat:l,width:1,color:h,style:m}},"app-header":{decorator:qx.ui.decoration.Background,style:{backgroundImage:T,backgroundRepeat:l}},"progressbar":{decorator:qx.ui.decoration.Single,style:{width:1,color:d}},"group-item":{decorator:qx.ui.decoration.Background,style:{backgroundImage:p,backgroundRepeat:l}}}});})();(function(){var j="#CCCCCC",i="#F3F3F3",h="#E4E4E4",g="#1a1a1a",f="#084FAB",e="gray",d="#fffefe",c="white",b="#4a4a4a",a="#EEEEEE",K="#80B4EF",J="#C72B2B",I="#ffffdd",H="#334866",G="#00204D",F="#666666",E="#CBC8CD",D="#99C3FE",C="#808080",B="#F4F4F4",q="#001533",r="#909090",o="#FCFCFC",p="#314a6e",m="#B6B6B6",n="#0880EF",k="#4d4d4d",l="#DFDFDF",s="#000000",t="#FF9999",w="#7B7A7E",v="#26364D",y="#990000",x="#AFAFAF",A="#404955",z="#AAAAAA",u="qx.theme.modern.Color";qx.Theme.define(u,{colors:{"background-application":l,"background-pane":i,"background-light":o,"background-medium":a,"background-splitpane":x,"background-tip":I,"background-tip-error":J,"background-odd":h,"text-light":r,"text-gray":b,"text-label":g,"text-title":p,"text-input":s,"text-hovered":q,"text-disabled":w,"text-selected":d,"text-active":v,"text-inactive":A,"text-placeholder":E,"border-main":k,"border-separator":C,"border-input":H,"border-disabled":m,"border-pane":G,"border-button":F,"border-column":j,"border-focused":D,"invalid":y,"border-focused-invalid":t,"table-pane":i,"table-focus-indicator":n,"table-row-background-focused-selected":f,"table-row-background-focused":K,"table-row-background-selected":f,"table-row-background-even":i,"table-row-background-odd":h,"table-row-selected":d,"table-row":g,"table-row-line":j,"table-column-line":j,"progressive-table-header":z,"progressive-table-row-background-even":B,"progressive-table-row-background-odd":h,"progressive-progressbar-background":e,"progressive-progressbar-indicator-done":j,"progressive-progressbar-indicator-undone":c,"progressive-progressbar-percent-background":e,"progressive-progressbar-percent-text":c}});})();(function(){var b="apiviewer.Theme",a="APIViewer theme";qx.Theme.define(b,{title:a,meta:{color:qx.theme.modern.Color,decoration:qx.theme.modern.Decoration,font:qx.theme.modern.Font,appearance:apiviewer.Appearance,icon:qx.theme.icon.Tango}});})();(function(){var j="_applyStyle",i="stretch",h="Integer",g="px",f=" ",e="repeat",d="round",c="shorthand",b="px ",a="sliceBottom",y=";'></div>",x="<div style='",w="sliceLeft",v="sliceRight",u="repeatX",t="String",s="qx.ui.decoration.css3.BorderImage",r="border-box",q="",p='") ',n="sliceTop",o='url("',l="hidden",m="repeatY",k="absolute";qx.Class.define(s,{extend:qx.ui.decoration.Abstract,construct:function(z,A){qx.ui.decoration.Abstract.call(this);if(z!=null){this.setBorderImage(z);}if(A!=null){this.setSlice(A);}},statics:{IS_SUPPORTED:qx.bom.element.Style.isPropertySupported("borderImage")},properties:{borderImage:{check:t,nullable:true,apply:j},sliceTop:{check:h,init:0,apply:j},sliceRight:{check:h,init:0,apply:j},sliceBottom:{check:h,init:0,apply:j},sliceLeft:{check:h,init:0,apply:j},slice:{group:[n,v,a,w],mode:c},repeatX:{check:[i,e,d],init:i,apply:j},repeatY:{check:[i,e,d],init:i,apply:j},repeat:{group:[u,m],mode:c}},members:{__nw:null,_getDefaultInsets:function(){return {top:0,right:0,bottom:0,left:0};},_isInitialized:function(){return !!this.__nw;},getMarkup:function(){if(this.__nw){return this.__nw;}var B=this._resolveImageUrl(this.getBorderImage());var C=[this.getSliceTop(),this.getSliceRight(),this.getSliceBottom(),this.getSliceLeft()];var D=[this.getRepeatX(),this.getRepeatY()].join(f);this.__nw=[x,qx.bom.element.Style.compile({"borderImage":o+B+p+C.join(f)+f+D,position:k,lineHeight:0,fontSize:0,overflow:l,boxSizing:r,borderWidth:C.join(b)+g}),y].join(q);return this.__nw;},resize:function(E,F,G){E.style.width=F+g;E.style.height=G+g;},tint:function(H,I){},_applyStyle:function(){{};},_resolveImageUrl:function(J){return qx.util.ResourceManager.getInstance().toUri(qx.util.AliasManager.getInstance().resolve(J));}},destruct:function(){this.__nw=null;}});})();(function(){var j="px",i="0px",h="-1px",g="no-repeat",f="scale-x",e="scale-y",d="-tr",c="-l",b='</div>',a="scale",x="qx.client",w="-br",v="-t",u="-tl",t="-r",s='<div style="position:absolute;top:0;left:0;overflow:hidden;font-size:0;line-height:0;">',r="_applyBaseImage",q="-b",p="String",o="",m="-bl",n="qx.ui.decoration.GridDiv",k="-c",l="mshtml";qx.Class.define(n,{extend:qx.ui.decoration.Abstract,construct:function(y,z){qx.ui.decoration.Abstract.call(this);if(y!=null){this.setBaseImage(y);}if(z!=null){this.setInsets(z);}},properties:{baseImage:{check:p,nullable:true,apply:r}},members:{__nx:null,__ny:null,__nz:null,_getDefaultInsets:function(){return {top:0,right:0,bottom:0,left:0};},_isInitialized:function(){return !!this.__nx;},getMarkup:function(){if(this.__nx){return this.__nx;}var A=qx.bom.element.Decoration;var B=this.__ny;var C=this.__nz;var D=[];D.push(s);D.push(A.create(B.tl,g,{top:0,left:0}));D.push(A.create(B.t,f,{top:0,left:C.left+j}));D.push(A.create(B.tr,g,{top:0,right:0}));D.push(A.create(B.bl,g,{bottom:0,left:0}));D.push(A.create(B.b,f,{bottom:0,left:C.left+j}));D.push(A.create(B.br,g,{bottom:0,right:0}));D.push(A.create(B.l,e,{top:C.top+j,left:0}));D.push(A.create(B.c,a,{top:C.top+j,left:C.left+j}));D.push(A.create(B.r,e,{top:C.top+j,right:0}));D.push(b);return this.__nx=D.join(o);},resize:function(E,F,G){var H=this.__nz;var innerWidth=F-H.left-H.right;var innerHeight=G-H.top-H.bottom;if(innerWidth<0){innerWidth=0;}if(innerHeight<0){innerHeight=0;}E.style.width=F+j;E.style.height=G+j;E.childNodes[1].style.width=innerWidth+j;E.childNodes[4].style.width=innerWidth+j;E.childNodes[7].style.width=innerWidth+j;E.childNodes[6].style.height=innerHeight+j;E.childNodes[7].style.height=innerHeight+j;E.childNodes[8].style.height=innerHeight+j;if(qx.core.Variant.isSet(x,l)){if(qx.bom.client.Engine.VERSION<7||(qx.bom.client.Feature.QUIRKS_MODE&&qx.bom.client.Engine.VERSION<8)){if(F%2==1){E.childNodes[2].style.marginRight=h;E.childNodes[5].style.marginRight=h;E.childNodes[8].style.marginRight=h;}else{E.childNodes[2].style.marginRight=i;E.childNodes[5].style.marginRight=i;E.childNodes[8].style.marginRight=i;}if(G%2==1){E.childNodes[3].style.marginBottom=h;E.childNodes[4].style.marginBottom=h;E.childNodes[5].style.marginBottom=h;}else{E.childNodes[3].style.marginBottom=i;E.childNodes[4].style.marginBottom=i;E.childNodes[5].style.marginBottom=i;}}}},tint:function(I,J){},_applyBaseImage:function(K,L){{};if(K){var P=this._resolveImageUrl(K);var Q=/(.*)(\.[a-z]+)$/.exec(P);var O=Q[1];var N=Q[2];var M=this.__ny={tl:O+u+N,t:O+v+N,tr:O+d+N,bl:O+m+N,b:O+q+N,br:O+w+N,l:O+c+N,c:O+k+N,r:O+t+N};this.__nz=this._computeEdgeSizes(M);}},_resolveImageUrl:function(R){return qx.util.AliasManager.getInstance().resolve(R);},_computeEdgeSizes:function(S){var T=qx.util.ResourceManager.getInstance();return {top:T.getImageHeight(S.t),bottom:T.getImageHeight(S.b),left:T.getImageWidth(S.l),right:T.getImageWidth(S.r)};}},destruct:function(){this.__nx=this.__ny=this.__nz=null;}});})();(function(){var a="apiviewer.test.StringExtend";qx.Class.define(a,{extend:String,members:{}});})();
+
+qx.$$loader.init();
+
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/bootstrap.js b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/bootstrap.js
new file mode 100644
index 00000000000..c7b9d89d18e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/bootstrap.js
@@ -0,0 +1,1829 @@
+/* Modifications: replaced one ; with \n for testing purposes
+ * Before the second !function -- nd */
+
+/* ===================================================
+ * bootstrap-transition.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ $(function () {
+
+ "use strict"; // jshint ;_;
+
+
+ /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+ * ======================================================= */
+
+ $.support.transition = (function () {
+
+ var transitionEnd = (function () {
+
+ var el = document.createElement('bootstrap')
+ , transEndEventNames = {
+ 'WebkitTransition' : 'webkitTransitionEnd'
+ , 'MozTransition' : 'transitionend'
+ , 'OTransition' : 'oTransitionEnd'
+ , 'msTransition' : 'MSTransitionEnd'
+ , 'transition' : 'transitionend'
+ }
+ , name
+
+ for (name in transEndEventNames){
+ if (el.style[name] !== undefined) {
+ return transEndEventNames[name]
+ }
+ }
+
+ }())
+
+ return transitionEnd && {
+ end: transitionEnd
+ }
+
+ })()
+
+ })
+
+}(window.jQuery)
+/* ==========================================================
+ * bootstrap-alert.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* ALERT CLASS DEFINITION
+ * ====================== */
+
+ var dismiss = '[data-dismiss="alert"]'
+ , Alert = function (el) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.prototype.close = function (e) {
+ var $this = $(this)
+ , selector = $this.attr('data-target')
+ , $parent
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+
+ e && e.preventDefault()
+
+ $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+ $parent.trigger(e = $.Event('close'))
+
+ if (e.isDefaultPrevented()) return
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ $parent
+ .trigger('closed')
+ .remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent.on($.support.transition.end, removeElement) :
+ removeElement()
+ }
+
+
+ /* ALERT PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.alert = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('alert')
+ if (!data) $this.data('alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.alert.Constructor = Alert
+
+
+ /* ALERT DATA-API
+ * ============== */
+
+ $(function () {
+ $('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
+ })
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-button.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+ * ============================== */
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.button.defaults, options)
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ , $el = this.$element
+ , data = $el.data()
+ , val = $el.is('input') ? 'val' : 'html'
+
+ state = state + 'Text'
+ data.resetText || $el.data('resetText', $el[val]())
+
+ $el[val](data[state] || this.options[state])
+
+ // push to event loop to allow forms to submit
+ setTimeout(function () {
+ state == 'loadingText' ?
+ $el.addClass(d).attr(d, d) :
+ $el.removeClass(d).removeAttr(d)
+ }, 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
+
+ $parent && $parent
+ .find('.active')
+ .removeClass('active')
+
+ this.$element.toggleClass('active')
+ }
+
+
+ /* BUTTON PLUGIN DEFINITION
+ * ======================== */
+
+ $.fn.button = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('button')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('button', (data = new Button(this, options)))
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ $.fn.button.defaults = {
+ loadingText: 'loading...'
+ }
+
+ $.fn.button.Constructor = Button
+
+
+ /* BUTTON DATA-API
+ * =============== */
+
+ $(function () {
+ $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ $btn.button('toggle')
+ })
+ })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-carousel.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* CAROUSEL CLASS DEFINITION
+ * ========================= */
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.options = options
+ this.options.slide && this.slide(this.options.slide)
+ this.options.pause == 'hover' && this.$element
+ .on('mouseenter', $.proxy(this.pause, this))
+ .on('mouseleave', $.proxy(this.cycle, this))
+ }
+
+ Carousel.prototype = {
+
+ cycle: function (e) {
+ if (!e) this.paused = false
+ this.options.interval
+ && !this.paused
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+ return this
+ }
+
+ , to: function (pos) {
+ var $active = this.$element.find('.active')
+ , children = $active.parent().children()
+ , activePos = children.index($active)
+ , that = this
+
+ if (pos > (children.length - 1) || pos < 0) return
+
+ if (this.sliding) {
+ return this.$element.one('slid', function () {
+ that.to(pos)
+ })
+ }
+
+ if (activePos == pos) {
+ return this.pause().cycle()
+ }
+
+ return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
+ }
+
+ , pause: function (e) {
+ if (!e) this.paused = true
+ clearInterval(this.interval)
+ this.interval = null
+ return this
+ }
+
+ , next: function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ , prev: function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ , slide: function (type, next) {
+ var $active = this.$element.find('.active')
+ , $next = next || $active[type]()
+ , isCycling = this.interval
+ , direction = type == 'next' ? 'left' : 'right'
+ , fallback = type == 'next' ? 'first' : 'last'
+ , that = this
+ , e = $.Event('slide')
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+ if ($next.hasClass('active')) return
+
+ if ($.support.transition && this.$element.hasClass('slide')) {
+ this.$element.trigger(e)
+ if (e.isDefaultPrevented()) return
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ this.$element.one($.support.transition.end, function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () { that.$element.trigger('slid') }, 0)
+ })
+ } else {
+ this.$element.trigger(e)
+ if (e.isDefaultPrevented()) return
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger('slid')
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+ }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.carousel = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('carousel')
+ , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+ if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (typeof option == 'string' || (option = options.slide)) data[option]()
+ else if (options.interval) data.cycle()
+ })
+ }
+
+ $.fn.carousel.defaults = {
+ interval: 5000
+ , pause: 'hover'
+ }
+
+ $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL DATA-API
+ * ================= */
+
+ $(function () {
+ $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) {
+ var $this = $(this), href
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data())
+ $target.carousel(options)
+ e.preventDefault()
+ })
+ })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-collapse.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* COLLAPSE PUBLIC CLASS DEFINITION
+ * ================================ */
+
+ var Collapse = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+ if (this.options.parent) {
+ this.$parent = $(this.options.parent)
+ }
+
+ this.options.toggle && this.toggle()
+ }
+
+ Collapse.prototype = {
+
+ constructor: Collapse
+
+ , dimension: function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ , show: function () {
+ var dimension
+ , scroll
+ , actives
+ , hasData
+
+ if (this.transitioning) return
+
+ dimension = this.dimension()
+ scroll = $.camelCase(['scroll', dimension].join('-'))
+ actives = this.$parent && this.$parent.find('> .accordion-group > .in')
+
+ if (actives && actives.length) {
+ hasData = actives.data('collapse')
+ if (hasData && hasData.transitioning) return
+ actives.collapse('hide')
+ hasData || actives.data('collapse', null)
+ }
+
+ this.$element[dimension](0)
+ this.transition('addClass', $.Event('show'), 'shown')
+ this.$element[dimension](this.$element[0][scroll])
+ }
+
+ , hide: function () {
+ var dimension
+ if (this.transitioning) return
+ dimension = this.dimension()
+ this.reset(this.$element[dimension]())
+ this.transition('removeClass', $.Event('hide'), 'hidden')
+ this.$element[dimension](0)
+ }
+
+ , reset: function (size) {
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ [dimension](size || 'auto')
+ [0].offsetWidth
+
+ this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
+
+ return this
+ }
+
+ , transition: function (method, startEvent, completeEvent) {
+ var that = this
+ , complete = function () {
+ if (startEvent.type == 'show') that.reset()
+ that.transitioning = 0
+ that.$element.trigger(completeEvent)
+ }
+
+ this.$element.trigger(startEvent)
+
+ if (startEvent.isDefaultPrevented()) return
+
+ this.transitioning = 1
+
+ this.$element[method]('in')
+
+ $.support.transition && this.$element.hasClass('collapse') ?
+ this.$element.one($.support.transition.end, complete) :
+ complete()
+ }
+
+ , toggle: function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+
+ /* COLLAPSIBLE PLUGIN DEFINITION
+ * ============================== */
+
+ $.fn.collapse = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('collapse')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.collapse.defaults = {
+ toggle: true
+ }
+
+ $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSIBLE DATA-API
+ * ==================== */
+
+ $(function () {
+ $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {
+ var $this = $(this), href
+ , target = $this.attr('data-target')
+ || e.preventDefault()
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+ , option = $(target).data('collapse') ? 'toggle' : $this.data()
+ $(target).collapse(option)
+ })
+ })
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-dropdown.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* DROPDOWN CLASS DEFINITION
+ * ========================= */
+
+ var toggle = '[data-toggle="dropdown"]'
+ , Dropdown = function (element) {
+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
+ $('html').on('click.dropdown.data-api', function () {
+ $el.parent().removeClass('open')
+ })
+ }
+
+ Dropdown.prototype = {
+
+ constructor: Dropdown
+
+ , toggle: function (e) {
+ var $this = $(this)
+ , $parent
+ , selector
+ , isActive
+
+ if ($this.is('.disabled, :disabled')) return
+
+ selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+ $parent.length || ($parent = $this.parent())
+
+ isActive = $parent.hasClass('open')
+
+ clearMenus()
+
+ if (!isActive) $parent.toggleClass('open')
+
+ return false
+ }
+
+ }
+
+ function clearMenus() {
+ $(toggle).parent().removeClass('open')
+ }
+
+
+ /* DROPDOWN PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.dropdown = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('dropdown')
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
+ * =================================== */
+
+ $(function () {
+ $('html').on('click.dropdown.data-api', clearMenus)
+ $('body')
+ .on('click.dropdown', '.dropdown form', function (e) { e.stopPropagation() })
+ .on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+ })
+
+}(window.jQuery);/* =========================================================
+ * bootstrap-modal.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* MODAL CLASS DEFINITION
+ * ====================== */
+
+ var Modal = function (content, options) {
+ this.options = options
+ this.$element = $(content)
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+ }
+
+ Modal.prototype = {
+
+ constructor: Modal
+
+ , toggle: function () {
+ return this[!this.isShown ? 'show' : 'hide']()
+ }
+
+ , show: function () {
+ var that = this
+ , e = $.Event('show')
+
+ this.$element.trigger(e)
+
+ if (this.isShown || e.isDefaultPrevented()) return
+
+ $('body').addClass('modal-open')
+
+ this.isShown = true
+
+ escape.call(this)
+ backdrop.call(this, function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ if (!that.$element.parent().length) {
+ that.$element.appendTo(document.body) //don't move modals dom position
+ }
+
+ that.$element
+ .show()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ transition ?
+ that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
+ that.$element.trigger('shown')
+
+ })
+ }
+
+ , hide: function (e) {
+ e && e.preventDefault()
+
+ var that = this
+
+ e = $.Event('hide')
+
+ this.$element.trigger(e)
+
+ if (!this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = false
+
+ $('body').removeClass('modal-open')
+
+ escape.call(this)
+
+ this.$element.removeClass('in')
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ hideWithTransition.call(this) :
+ hideModal.call(this)
+ }
+
+ }
+
+
+ /* MODAL PRIVATE METHODS
+ * ===================== */
+
+ function hideWithTransition() {
+ var that = this
+ , timeout = setTimeout(function () {
+ that.$element.off($.support.transition.end)
+ hideModal.call(that)
+ }, 500)
+
+ this.$element.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ hideModal.call(that)
+ })
+ }
+
+ function hideModal(that) {
+ this.$element
+ .hide()
+ .trigger('hidden')
+
+ backdrop.call(this)
+ }
+
+ function backdrop(callback) {
+ var that = this
+ , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+ .appendTo(document.body)
+
+ if (this.options.backdrop != 'static') {
+ this.$backdrop.click($.proxy(this.hide, this))
+ }
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ doAnimate ?
+ this.$backdrop.one($.support.transition.end, callback) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ $.support.transition && this.$element.hasClass('fade')?
+ this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
+ removeBackdrop.call(this)
+
+ } else if (callback) {
+ callback()
+ }
+ }
+
+ function removeBackdrop() {
+ this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ function escape() {
+ var that = this
+ if (this.isShown && this.options.keyboard) {
+ $(document).on('keyup.dismiss.modal', function ( e ) {
+ e.which == 27 && that.hide()
+ })
+ } else if (!this.isShown) {
+ $(document).off('keyup.dismiss.modal')
+ }
+ }
+
+
+ /* MODAL PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.modal = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('modal')
+ , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option]()
+ else if (options.show) data.show()
+ })
+ }
+
+ $.fn.modal.defaults = {
+ backdrop: true
+ , keyboard: true
+ , show: true
+ }
+
+ $.fn.modal.Constructor = Modal
+
+
+ /* MODAL DATA-API
+ * ============== */
+
+ $(function () {
+ $('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
+ var $this = $(this), href
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ , option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
+
+ e.preventDefault()
+ $target.modal(option)
+ })
+ })
+
+}(window.jQuery);/* ===========================================================
+ * bootstrap-tooltip.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Tooltip = function (element, options) {
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.prototype = {
+
+ constructor: Tooltip
+
+ , init: function (type, element, options) {
+ var eventIn
+ , eventOut
+
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.enabled = true
+
+ if (this.options.trigger != 'manual') {
+ eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
+ eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
+ this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ , getOptions: function (options) {
+ options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay
+ , hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ , enter: function (e) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ clearTimeout(this.timeout)
+ self.hoverState = 'in'
+ this.timeout = setTimeout(function() {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ , leave: function (e) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (this.timeout) clearTimeout(this.timeout)
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.hoverState = 'out'
+ this.timeout = setTimeout(function() {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ , show: function () {
+ var $tip
+ , inside
+ , pos
+ , actualWidth
+ , actualHeight
+ , placement
+ , tp
+
+ if (this.hasContent() && this.enabled) {
+ $tip = this.tip()
+ this.setContent()
+
+ if (this.options.animation) {
+ $tip.addClass('fade')
+ }
+
+ placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ inside = /in/.test(placement)
+
+ $tip
+ .remove()
+ .css({ top: 0, left: 0, display: 'block' })
+ .appendTo(inside ? this.$element : document.body)
+
+ pos = this.getPosition(inside)
+
+ actualWidth = $tip[0].offsetWidth
+ actualHeight = $tip[0].offsetHeight
+
+ switch (inside ? placement.split(' ')[1] : placement) {
+ case 'bottom':
+ tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'top':
+ tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'left':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+ break
+ case 'right':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+ break
+ }
+
+ $tip
+ .css(tp)
+ .addClass(placement)
+ .addClass('in')
+ }
+ }
+
+ , isHTML: function(text) {
+ // html string detection logic adapted from jQuery
+ return typeof text != 'string'
+ || ( text.charAt(0) === "<"
+ && text.charAt( text.length - 1 ) === ">"
+ && text.length >= 3
+ ) || /^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(text)
+ }
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.isHTML(title) ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ , hide: function () {
+ var that = this
+ , $tip = this.tip()
+
+ $tip.removeClass('in')
+
+ function removeWithAnimation() {
+ var timeout = setTimeout(function () {
+ $tip.off($.support.transition.end).remove()
+ }, 500)
+
+ $tip.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ $tip.remove()
+ })
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ removeWithAnimation() :
+ $tip.remove()
+ }
+
+ , fixTitle: function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
+ }
+ }
+
+ , hasContent: function () {
+ return this.getTitle()
+ }
+
+ , getPosition: function (inside) {
+ return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
+ width: this.$element[0].offsetWidth
+ , height: this.$element[0].offsetHeight
+ })
+ }
+
+ , getTitle: function () {
+ var title
+ , $e = this.$element
+ , o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ , tip: function () {
+ return this.$tip = this.$tip || $(this.options.template)
+ }
+
+ , validate: function () {
+ if (!this.$element[0].parentNode) {
+ this.hide()
+ this.$element = null
+ this.options = null
+ }
+ }
+
+ , enable: function () {
+ this.enabled = true
+ }
+
+ , disable: function () {
+ this.enabled = false
+ }
+
+ , toggleEnabled: function () {
+ this.enabled = !this.enabled
+ }
+
+ , toggle: function () {
+ this[this.tip().hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+ * ========================= */
+
+ $.fn.tooltip = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tooltip')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tooltip.Constructor = Tooltip
+
+ $.fn.tooltip.defaults = {
+ animation: true
+ , placement: 'top'
+ , selector: false
+ , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+ , trigger: 'hover'
+ , title: ''
+ , delay: 0
+ }
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-popover.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Popover = function ( element, options ) {
+ this.init('popover', element, options)
+ }
+
+
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+ ========================================== */
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+ constructor: Popover
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+ , content = this.getContent()
+
+ $tip.find('.popover-title')[this.isHTML(title) ? 'html' : 'text'](title)
+ $tip.find('.popover-content > *')[this.isHTML(content) ? 'html' : 'text'](content)
+
+ $tip.removeClass('fade top bottom left right in')
+ }
+
+ , hasContent: function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ , getContent: function () {
+ var content
+ , $e = this.$element
+ , o = this.options
+
+ content = $e.attr('data-content')
+ || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
+
+ return content
+ }
+
+ , tip: function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ }
+ return this.$tip
+ }
+
+ })
+
+
+ /* POPOVER PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.popover = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('popover')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.popover.Constructor = Popover
+
+ $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+ placement: 'right'
+ , content: ''
+ , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
+ })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-scrollspy.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* SCROLLSPY CLASS DEFINITION
+ * ========================== */
+
+ function ScrollSpy( element, options) {
+ var process = $.proxy(this.process, this)
+ , $element = $(element).is('body') ? $(window) : $(element)
+ , href
+ this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+ this.$scrollElement = $element.on('scroll.scroll.data-api', process)
+ this.selector = (this.options.target
+ || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ || '') + ' .nav li > a'
+ this.$body = $('body')
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.prototype = {
+
+ constructor: ScrollSpy
+
+ , refresh: function () {
+ var self = this
+ , $targets
+
+ this.offsets = $([])
+ this.targets = $([])
+
+ $targets = this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ , href = $el.data('target') || $el.attr('href')
+ , $href = /^#\w/.test(href) && $(href)
+ return ( $href
+ && href.length
+ && [[ $href.position().top, href ]] ) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ self.offsets.push(this[0])
+ self.targets.push(this[1])
+ })
+ }
+
+ , process: function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
+ , maxScroll = scrollHeight - this.$scrollElement.height()
+ , offsets = this.offsets
+ , targets = this.targets
+ , activeTarget = this.activeTarget
+ , i
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets.last()[0])
+ && this.activate ( i )
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+ && this.activate( targets[i] )
+ }
+ }
+
+ , activate: function (target) {
+ var active
+ , selector
+
+ this.activeTarget = target
+
+ $(this.selector)
+ .parent('.active')
+ .removeClass('active')
+
+ selector = this.selector
+ + '[data-target="' + target + '"],'
+ + this.selector + '[href="' + target + '"]'
+
+ active = $(selector)
+ .parent('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu')) {
+ active = active.closest('li.dropdown').addClass('active')
+ }
+
+ active.trigger('activate')
+ }
+
+ }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.scrollspy = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('scrollspy')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+ $.fn.scrollspy.defaults = {
+ offset: 10
+ }
+
+
+ /* SCROLLSPY DATA-API
+ * ================== */
+
+ $(function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ $spy.scrollspy($spy.data())
+ })
+ })
+
+}(window.jQuery);/* ========================================================
+ * bootstrap-tab.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* TAB CLASS DEFINITION
+ * ==================== */
+
+ var Tab = function ( element ) {
+ this.element = $(element)
+ }
+
+ Tab.prototype = {
+
+ constructor: Tab
+
+ , show: function () {
+ var $this = this.element
+ , $ul = $this.closest('ul:not(.dropdown-menu)')
+ , selector = $this.attr('data-target')
+ , previous
+ , $target
+ , e
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ if ( $this.parent('li').hasClass('active') ) return
+
+ previous = $ul.find('.active a').last()[0]
+
+ e = $.Event('show', {
+ relatedTarget: previous
+ })
+
+ $this.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ $target = $(selector)
+
+ this.activate($this.parent('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $this.trigger({
+ type: 'shown'
+ , relatedTarget: previous
+ })
+ })
+ }
+
+ , activate: function ( element, container, callback) {
+ var $active = container.find('> .active')
+ , transition = callback
+ && $.support.transition
+ && $active.hasClass('fade')
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+
+ element.addClass('active')
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if ( element.parent('.dropdown-menu') ) {
+ element.closest('li.dropdown').addClass('active')
+ }
+
+ callback && callback()
+ }
+
+ transition ?
+ $active.one($.support.transition.end, next) :
+ next()
+
+ $active.removeClass('in')
+ }
+ }
+
+
+ /* TAB PLUGIN DEFINITION
+ * ===================== */
+
+ $.fn.tab = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tab')
+ if (!data) $this.data('tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tab.Constructor = Tab
+
+
+ /* TAB DATA-API
+ * ============ */
+
+ $(function () {
+ $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+ e.preventDefault()
+ $(this).tab('show')
+ })
+ })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-typeahead.js v2.0.4
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function($){
+
+ "use strict"; // jshint ;_;
+
+
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
+ * ================================= */
+
+ var Typeahead = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.typeahead.defaults, options)
+ this.matcher = this.options.matcher || this.matcher
+ this.sorter = this.options.sorter || this.sorter
+ this.highlighter = this.options.highlighter || this.highlighter
+ this.updater = this.options.updater || this.updater
+ this.$menu = $(this.options.menu).appendTo('body')
+ this.source = this.options.source
+ this.shown = false
+ this.listen()
+ }
+
+ Typeahead.prototype = {
+
+ constructor: Typeahead
+
+ , select: function () {
+ var val = this.$menu.find('.active').attr('data-value')
+ this.$element
+ .val(this.updater(val))
+ .change()
+ return this.hide()
+ }
+
+ , updater: function (item) {
+ return item
+ }
+
+ , show: function () {
+ var pos = $.extend({}, this.$element.offset(), {
+ height: this.$element[0].offsetHeight
+ })
+
+ this.$menu.css({
+ top: pos.top + pos.height
+ , left: pos.left
+ })
+
+ this.$menu.show()
+ this.shown = true
+ return this
+ }
+
+ , hide: function () {
+ this.$menu.hide()
+ this.shown = false
+ return this
+ }
+
+ , lookup: function (event) {
+ var that = this
+ , items
+ , q
+
+ this.query = this.$element.val()
+
+ if (!this.query) {
+ return this.shown ? this.hide() : this
+ }
+
+ items = $.grep(this.source, function (item) {
+ return that.matcher(item)
+ })
+
+ items = this.sorter(items)
+
+ if (!items.length) {
+ return this.shown ? this.hide() : this
+ }
+
+ return this.render(items.slice(0, this.options.items)).show()
+ }
+
+ , matcher: function (item) {
+ return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+ }
+
+ , sorter: function (items) {
+ var beginswith = []
+ , caseSensitive = []
+ , caseInsensitive = []
+ , item
+
+ while (item = items.shift()) {
+ if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+ else if (~item.indexOf(this.query)) caseSensitive.push(item)
+ else caseInsensitive.push(item)
+ }
+
+ return beginswith.concat(caseSensitive, caseInsensitive)
+ }
+
+ , highlighter: function (item) {
+ var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
+ return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
+ return '<strong>' + match + '</strong>'
+ })
+ }
+
+ , render: function (items) {
+ var that = this
+
+ items = $(items).map(function (i, item) {
+ i = $(that.options.item).attr('data-value', item)
+ i.find('a').html(that.highlighter(item))
+ return i[0]
+ })
+
+ items.first().addClass('active')
+ this.$menu.html(items)
+ return this
+ }
+
+ , next: function (event) {
+ var active = this.$menu.find('.active').removeClass('active')
+ , next = active.next()
+
+ if (!next.length) {
+ next = $(this.$menu.find('li')[0])
+ }
+
+ next.addClass('active')
+ }
+
+ , prev: function (event) {
+ var active = this.$menu.find('.active').removeClass('active')
+ , prev = active.prev()
+
+ if (!prev.length) {
+ prev = this.$menu.find('li').last()
+ }
+
+ prev.addClass('active')
+ }
+
+ , listen: function () {
+ this.$element
+ .on('blur', $.proxy(this.blur, this))
+ .on('keypress', $.proxy(this.keypress, this))
+ .on('keyup', $.proxy(this.keyup, this))
+
+ if ($.browser.webkit || $.browser.msie) {
+ this.$element.on('keydown', $.proxy(this.keypress, this))
+ }
+
+ this.$menu
+ .on('click', $.proxy(this.click, this))
+ .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+ }
+
+ , keyup: function (e) {
+ switch(e.keyCode) {
+ case 40: // down arrow
+ case 38: // up arrow
+ break
+
+ case 9: // tab
+ case 13: // enter
+ if (!this.shown) return
+ this.select()
+ break
+
+ case 27: // escape
+ if (!this.shown) return
+ this.hide()
+ break
+
+ default:
+ this.lookup()
+ }
+
+ e.stopPropagation()
+ e.preventDefault()
+ }
+
+ , keypress: function (e) {
+ if (!this.shown) return
+
+ switch(e.keyCode) {
+ case 9: // tab
+ case 13: // enter
+ case 27: // escape
+ e.preventDefault()
+ break
+
+ case 38: // up arrow
+ if (e.type != 'keydown') break
+ e.preventDefault()
+ this.prev()
+ break
+
+ case 40: // down arrow
+ if (e.type != 'keydown') break
+ e.preventDefault()
+ this.next()
+ break
+ }
+
+ e.stopPropagation()
+ }
+
+ , blur: function (e) {
+ var that = this
+ setTimeout(function () { that.hide() }, 150)
+ }
+
+ , click: function (e) {
+ e.stopPropagation()
+ e.preventDefault()
+ this.select()
+ }
+
+ , mouseenter: function (e) {
+ this.$menu.find('.active').removeClass('active')
+ $(e.currentTarget).addClass('active')
+ }
+
+ }
+
+
+ /* TYPEAHEAD PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.typeahead = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('typeahead')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.typeahead.defaults = {
+ source: []
+ , items: 8
+ , menu: '<ul class="typeahead dropdown-menu"></ul>'
+ , item: '<li><a href="#"></a></li>'
+ }
+
+ $.fn.typeahead.Constructor = Typeahead
+
+
+ /* TYPEAHEAD DATA-API
+ * ================== */
+
+ $(function () {
+ $('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+ var $this = $(this)
+ if ($this.data('typeahead')) return
+ e.preventDefault()
+ $this.typeahead($this.data())
+ })
+ })
+
+}(window.jQuery);
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jquery-1.7.1.js b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jquery-1.7.1.js
new file mode 100644
index 00000000000..8ccd0ea786e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jquery-1.7.1.js
@@ -0,0 +1,9266 @@
+/*!
+ * jQuery JavaScript Library v1.7.1
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Mon Nov 21 21:11:03 2011 -0500
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document,
+ navigator = window.navigator,
+ location = window.location;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // A simple way to check for HTML strings or ID strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+ // Check if a string has a non-whitespace character in it
+ rnotwhite = /\S/,
+
+ // Used for trimming whitespace
+ trimLeft = /^\s+/,
+ trimRight = /\s+$/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+ // Useragent RegExp
+ rwebkit = /(webkit)[ \/]([\w.]+)/,
+ ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+ rmsie = /(msie) ([\w.]+)/,
+ rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+ // Matches dashed string for camelizing
+ rdashAlpha = /-([a-z]|[0-9])/ig,
+ rmsPrefix = /^-ms-/,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return ( letter + "" ).toUpperCase();
+ },
+
+ // Keep a UserAgent string for use with jQuery.browser
+ userAgent = navigator.userAgent,
+
+ // For matching the engine and version of the browser
+ browserMatch,
+
+ // The deferred used on DOM ready
+ readyList,
+
+ // The ready event handler
+ DOMContentLoaded,
+
+ // Save a reference to some core methods
+ toString = Object.prototype.toString,
+ hasOwn = Object.prototype.hasOwnProperty,
+ push = Array.prototype.push,
+ slice = Array.prototype.slice,
+ trim = String.prototype.trim,
+ indexOf = Array.prototype.indexOf,
+
+ // [[Class]] -> type pairs
+ class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), or $(undefined)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // The body element only exists once, optimize finding it
+ if ( selector === "body" && !context && document.body ) {
+ this.context = document;
+ this[0] = document.body;
+ this.selector = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = quickExpr.exec( selector );
+ }
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+ doc = ( context ? context.ownerDocument || context : document );
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ ret = rsingleTag.exec( selector );
+
+ if ( ret ) {
+ if ( jQuery.isPlainObject( context ) ) {
+ selector = [ document.createElement( ret[1] ) ];
+ jQuery.fn.attr.call( selector, context, true );
+
+ } else {
+ selector = [ doc.createElement( ret[1] ) ];
+ }
+
+ } else {
+ ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+ selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
+ }
+
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $("#id")
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.7.1",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return slice.call( this, 0 );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = this.constructor();
+
+ if ( jQuery.isArray( elems ) ) {
+ push.apply( ret, elems );
+
+ } else {
+ jQuery.merge( ret, elems );
+ }
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" ) {
+ ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+ } else if ( name ) {
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+ }
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Attach the listeners
+ jQuery.bindReady();
+
+ // Add the callback
+ readyList.add( fn );
+
+ return this;
+ },
+
+ eq: function( i ) {
+ i = +i;
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, i + 1 );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ),
+ "slice", slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+ // Either a released hold or an DOMready/load event and not yet ready
+ if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.fireWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger( "ready" ).off( "ready" );
+ }
+ }
+ },
+
+ bindReady: function() {
+ if ( readyList ) {
+ return;
+ }
+
+ readyList = jQuery.Callbacks( "once memory" );
+
+ // Catch cases where $(document).ready() is called after the
+ // browser event has already occurred.
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var toplevel = false;
+
+ try {
+ toplevel = window.frameElement == null;
+ } catch(e) {}
+
+ if ( document.documentElement.doScroll && toplevel ) {
+ doScrollCheck();
+ }
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ // A crude way of determining if an object is a window
+ isWindow: function( obj ) {
+ return obj && typeof obj === "object" && "setInterval" in obj;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ return obj == null ?
+ String( obj ) :
+ class2type[ toString.call(obj) ] || "object";
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ for ( var name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ parseJSON: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+
+ }
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && rnotwhite.test( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0,
+ length = object.length,
+ isObj = length === undefined || jQuery.isFunction( object );
+
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.apply( object[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( object[ i++ ], args ) === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return object;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: trim ?
+ function( text ) {
+ return text == null ?
+ "" :
+ trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( array, results ) {
+ var ret = results || [];
+
+ if ( array != null ) {
+ // The window, strings (and functions) also have 'length'
+ // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+ var type = jQuery.type( array );
+
+ if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+ push.call( ret, array );
+ } else {
+ jQuery.merge( ret, array );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array, i ) {
+ var len;
+
+ if ( array ) {
+ if ( indexOf ) {
+ return indexOf.call( array, elem, i );
+ }
+
+ len = array.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in array && array[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var i = first.length,
+ j = 0;
+
+ if ( typeof second.length === "number" ) {
+ for ( var l = second.length; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [], retVal;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value, key, ret = [],
+ i = 0,
+ length = elems.length,
+ // jquery objects are treated as arrays
+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( key in elems ) {
+ value = callback( elems[ key ], key, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return ret.concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ if ( typeof context === "string" ) {
+ var tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ var args = slice.call( arguments, 2 ),
+ proxy = function() {
+ return fn.apply( context, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Mutifunctional method to get and set values to a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, key, value, exec, fn, pass ) {
+ var length = elems.length;
+
+ // Setting many attributes
+ if ( typeof key === "object" ) {
+ for ( var k in key ) {
+ jQuery.access( elems, k, key[k], exec, fn, value );
+ }
+ return elems;
+ }
+
+ // Setting one attribute
+ if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = !pass && exec && jQuery.isFunction(value);
+
+ for ( var i = 0; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+ }
+
+ return elems;
+ }
+
+ // Getting an attribute
+ return length ? fn( elems[0], key ) : undefined;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ },
+
+ // Use of jQuery.browser is frowned upon.
+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
+ uaMatch: function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = rwebkit.exec( ua ) ||
+ ropera.exec( ua ) ||
+ rmsie.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+ [];
+
+ return { browser: match[1] || "", version: match[2] || "0" };
+ },
+
+ sub: function() {
+ function jQuerySub( selector, context ) {
+ return new jQuerySub.fn.init( selector, context );
+ }
+ jQuery.extend( true, jQuerySub, this );
+ jQuerySub.superclass = this;
+ jQuerySub.fn = jQuerySub.prototype = this();
+ jQuerySub.fn.constructor = jQuerySub;
+ jQuerySub.sub = this.sub;
+ jQuerySub.fn.init = function init( selector, context ) {
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+ context = jQuerySub( context );
+ }
+
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+ };
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
+ var rootjQuerySub = jQuerySub(document);
+ return jQuerySub;
+ },
+
+ browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+ jQuery.browser[ browserMatch.browser ] = true;
+ jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+ jQuery.browser.safari = true;
+}
+
+// IE doesn't match non-breaking spaces with \s
+if ( rnotwhite.test( "\xA0" ) ) {
+ trimLeft = /^[\s\xA0]+/;
+ trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+ DOMContentLoaded = function() {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ };
+
+} else if ( document.attachEvent ) {
+ DOMContentLoaded = function() {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
+ }
+ };
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+ if ( jQuery.isReady ) {
+ return;
+ }
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch(e) {
+ setTimeout( doScrollCheck, 1 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+}
+
+return jQuery;
+
+})();
+
+
+// String to Object flags format cache
+var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+function createFlags( flags ) {
+ var object = flagsCache[ flags ] = {},
+ i, length;
+ flags = flags.split( /\s+/ );
+ for ( i = 0, length = flags.length; i < length; i++ ) {
+ object[ flags[i] ] = true;
+ }
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * flags: an optional list of space-separated flags that will change how
+ * the callback list behaves
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( flags ) {
+
+ // Convert flags from String-formatted to Object-formatted
+ // (we check in cache first)
+ flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+ var // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = [],
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Add one or several callbacks to the list
+ add = function( args ) {
+ var i,
+ length,
+ elem,
+ type,
+ actual;
+ for ( i = 0, length = args.length; i < length; i++ ) {
+ elem = args[ i ];
+ type = jQuery.type( elem );
+ if ( type === "array" ) {
+ // Inspect recursively
+ add( elem );
+ } else if ( type === "function" ) {
+ // Add if not in unique mode and callback is not in
+ if ( !flags.unique || !self.has( elem ) ) {
+ list.push( elem );
+ }
+ }
+ }
+ },
+ // Fire callbacks
+ fire = function( context, args ) {
+ args = args || [];
+ memory = !flags.memory || [ context, args ];
+ firing = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
+ memory = true; // Mark as halted
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( !flags.once ) {
+ if ( stack && stack.length ) {
+ memory = stack.shift();
+ self.fireWith( memory[ 0 ], memory[ 1 ] );
+ }
+ } else if ( memory === true ) {
+ self.disable();
+ } else {
+ list = [];
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ var length = list.length;
+ add( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away, unless previous
+ // firing was halted (stopOnFalse)
+ } else if ( memory && memory !== true ) {
+ firingStart = length;
+ fire( memory[ 0 ], memory[ 1 ] );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ var args = arguments,
+ argIndex = 0,
+ argLength = args.length;
+ for ( ; argIndex < argLength ; argIndex++ ) {
+ for ( var i = 0; i < list.length; i++ ) {
+ if ( args[ argIndex ] === list[ i ] ) {
+ // Handle firingIndex and firingLength
+ if ( firing ) {
+ if ( i <= firingLength ) {
+ firingLength--;
+ if ( i <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ // Remove the element
+ list.splice( i--, 1 );
+ // If we have some unicity property then
+ // we only need to do this once
+ if ( flags.unique ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return this;
+ },
+ // Control if a given callback is in the list
+ has: function( fn ) {
+ if ( list ) {
+ var i = 0,
+ length = list.length;
+ for ( ; i < length; i++ ) {
+ if ( fn === list[ i ] ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory || memory === true ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( stack ) {
+ if ( firing ) {
+ if ( !flags.once ) {
+ stack.push( [ context, args ] );
+ }
+ } else if ( !( flags.once && memory ) ) {
+ fire( context, args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!memory;
+ }
+ };
+
+ return self;
+};
+
+
+
+
+var // Static reference to slice
+ sliceDeferred = [].slice;
+
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var doneList = jQuery.Callbacks( "once memory" ),
+ failList = jQuery.Callbacks( "once memory" ),
+ progressList = jQuery.Callbacks( "memory" ),
+ state = "pending",
+ lists = {
+ resolve: doneList,
+ reject: failList,
+ notify: progressList
+ },
+ promise = {
+ done: doneList.add,
+ fail: failList.add,
+ progress: progressList.add,
+
+ state: function() {
+ return state;
+ },
+
+ // Deprecated
+ isResolved: doneList.fired,
+ isRejected: failList.fired,
+
+ then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+ deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
+ return this;
+ },
+ always: function() {
+ deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
+ return this;
+ },
+ pipe: function( fnDone, fnFail, fnProgress ) {
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( {
+ done: [ fnDone, "resolve" ],
+ fail: [ fnFail, "reject" ],
+ progress: [ fnProgress, "notify" ]
+ }, function( handler, data ) {
+ var fn = data[ 0 ],
+ action = data[ 1 ],
+ returned;
+ if ( jQuery.isFunction( fn ) ) {
+ deferred[ handler ](function() {
+ returned = fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+ }
+ });
+ } else {
+ deferred[ handler ]( newDefer[ action ] );
+ }
+ });
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ if ( obj == null ) {
+ obj = promise;
+ } else {
+ for ( var key in promise ) {
+ obj[ key ] = promise[ key ];
+ }
+ }
+ return obj;
+ }
+ },
+ deferred = promise.promise({}),
+ key;
+
+ for ( key in lists ) {
+ deferred[ key ] = lists[ key ].fire;
+ deferred[ key + "With" ] = lists[ key ].fireWith;
+ }
+
+ // Handle state
+ deferred.done( function() {
+ state = "resolved";
+ }, failList.disable, progressList.lock ).fail( function() {
+ state = "rejected";
+ }, doneList.disable, progressList.lock );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( firstParam ) {
+ var args = sliceDeferred.call( arguments, 0 ),
+ i = 0,
+ length = args.length,
+ pValues = new Array( length ),
+ count = length,
+ pCount = length,
+ deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+ firstParam :
+ jQuery.Deferred(),
+ promise = deferred.promise();
+ function resolveFunc( i ) {
+ return function( value ) {
+ args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ if ( !( --count ) ) {
+ deferred.resolveWith( deferred, args );
+ }
+ };
+ }
+ function progressFunc( i ) {
+ return function( value ) {
+ pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ deferred.notifyWith( promise, pValues );
+ };
+ }
+ if ( length > 1 ) {
+ for ( ; i < length; i++ ) {
+ if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+ args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
+ } else {
+ --count;
+ }
+ }
+ if ( !count ) {
+ deferred.resolveWith( deferred, args );
+ }
+ } else if ( deferred !== firstParam ) {
+ deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+ }
+ return promise;
+ }
+});
+
+
+
+
+jQuery.support = (function() {
+
+ var support,
+ all,
+ a,
+ select,
+ opt,
+ input,
+ marginDiv,
+ fragment,
+ tds,
+ events,
+ eventName,
+ i,
+ isSupported,
+ div = document.createElement( "div" ),
+ documentElement = document.documentElement;
+
+ // Preliminary tests
+ div.setAttribute("className", "t");
+ div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+ all = div.getElementsByTagName( "*" );
+ a = div.getElementsByTagName( "a" )[ 0 ];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return {};
+ }
+
+ // First batch of supports tests
+ select = document.createElement( "select" );
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName( "input" )[ 0 ];
+
+ support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.55/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: ( input.value === "on" ),
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // Tests for enctype support on a form(#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+ // Will be defined later
+ submitBubbles: true,
+ changeBubbles: true,
+ focusinBubbles: false,
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true
+ };
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+ div.attachEvent( "onclick", function() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ support.noCloneEvent = false;
+ });
+ div.cloneNode( true ).fireEvent( "onclick" );
+ }
+
+ // Check if a radio maintains its value
+ // after being appended to the DOM
+ input = document.createElement("input");
+ input.value = "t";
+ input.setAttribute("type", "radio");
+ support.radioValue = input.value === "t";
+
+ input.setAttribute("checked", "checked");
+ div.appendChild( input );
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( div.lastChild );
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ fragment.removeChild( input );
+ fragment.appendChild( div );
+
+ div.innerHTML = "";
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. For more
+ // info see bug #3333
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ if ( window.getComputedStyle ) {
+ marginDiv = document.createElement( "div" );
+ marginDiv.style.width = "0";
+ marginDiv.style.marginRight = "0";
+ div.style.width = "2px";
+ div.appendChild( marginDiv );
+ support.reliableMarginRight =
+ ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+ }
+
+ // Technique from Juriy Zaytsev
+ // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+ // We only care about the case where non-standard event systems
+ // are used, namely in IE. Short-circuiting here helps us to
+ // avoid an eval call (in setAttribute) which can cause CSP
+ // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+ if ( div.attachEvent ) {
+ for( i in {
+ submit: 1,
+ change: 1,
+ focusin: 1
+ }) {
+ eventName = "on" + i;
+ isSupported = ( eventName in div );
+ if ( !isSupported ) {
+ div.setAttribute( eventName, "return;" );
+ isSupported = ( typeof div[ eventName ] === "function" );
+ }
+ support[ i + "Bubbles" ] = isSupported;
+ }
+ }
+
+ fragment.removeChild( div );
+
+ // Null elements to avoid leaks in IE
+ fragment = select = opt = marginDiv = div = input = null;
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, outer, inner, table, td, offsetSupport,
+ conMarginTop, ptlm, vb, style, html,
+ body = document.getElementsByTagName("body")[0];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ conMarginTop = 1;
+ ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
+ vb = "visibility:hidden;border:0;";
+ style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
+ html = "<div " + style + "><div></div></div>" +
+ "<table " + style + " cellpadding='0' cellspacing='0'>" +
+ "<tr><td></td></tr></table>";
+
+ container = document.createElement("div");
+ container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
+ body.insertBefore( container, body.firstChild );
+
+ // Construct the test element
+ div = document.createElement("div");
+ container.appendChild( div );
+
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ // (only IE 8 fails this test)
+ div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
+ tds = div.getElementsByTagName( "td" );
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Check if empty table cells still have offsetWidth/Height
+ // (IE <= 8 fail this test)
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+ // Figure out if the W3C box model works as expected
+ div.innerHTML = "";
+ div.style.width = div.style.paddingLeft = "1px";
+ jQuery.boxModel = support.boxModel = div.offsetWidth === 2;
+
+ if ( typeof div.style.zoom !== "undefined" ) {
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ // (IE < 8 does this)
+ div.style.display = "inline";
+ div.style.zoom = 1;
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
+
+ // Check if elements with layout shrink-wrap their children
+ // (IE 6 does this)
+ div.style.display = "";
+ div.innerHTML = "<div style='width:4px;'></div>";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
+ }
+
+ div.style.cssText = ptlm + vb;
+ div.innerHTML = html;
+
+ outer = div.firstChild;
+ inner = outer.firstChild;
+ td = outer.nextSibling.firstChild.firstChild;
+
+ offsetSupport = {
+ doesNotAddBorder: ( inner.offsetTop !== 5 ),
+ doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
+ };
+
+ inner.style.position = "fixed";
+ inner.style.top = "20px";
+
+ // safari subtracts parent border width here which is 5px
+ offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
+ inner.style.position = inner.style.top = "";
+
+ outer.style.overflow = "hidden";
+ outer.style.position = "relative";
+
+ offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
+ offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
+
+ body.removeChild( container );
+ div = container = null;
+
+ jQuery.extend( support, offsetSupport );
+ });
+
+ return support;
+})();
+
+
+
+
+var rbrace = /^(?:\{.*\}|\[.*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+ cache: {},
+
+ // Please use with caution
+ uuid: 0,
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var privateCache, thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
+ isEvents = name === "events";
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ internalKey ] = id = ++jQuery.uuid;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ privateCache = thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Users should not attempt to inspect the internal events object using jQuery.data,
+ // it is undocumented and subject to change. But does anyone listen? No.
+ if ( isEvents && !thisCache[ name ] ) {
+ return privateCache.events;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+ },
+
+ removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i, l,
+
+ // Reference to internal data cache key
+ internalKey = jQuery.expando,
+
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+
+ // See jQuery.data for more information
+ id = isNode ? elem[ internalKey ] : internalKey;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split( " " );
+ }
+ }
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject(cache[ id ]) ) {
+ return;
+ }
+ }
+
+ // Browsers that fail expando deletion also refuse to delete expandos on
+ // the window, but it will allow it on all other JS objects; other browsers
+ // don't care
+ // Ensure that `cache` is not a window object #10080
+ if ( jQuery.support.deleteExpando || !cache.setInterval ) {
+ delete cache[ id ];
+ } else {
+ cache[ id ] = null;
+ }
+
+ // We destroyed the cache and need to eliminate the expando on the node to avoid
+ // false lookups in the cache for entries that no longer exist
+ if ( isNode ) {
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( jQuery.support.deleteExpando ) {
+ delete elem[ internalKey ];
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( internalKey );
+ } else {
+ elem[ internalKey ] = null;
+ }
+ }
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return jQuery.data( elem, name, data, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ if ( elem.nodeName ) {
+ var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ if ( match ) {
+ return !(match === true || elem.getAttribute("classid") !== match);
+ }
+ }
+
+ return true;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var parts, attr, name,
+ data = null;
+
+ if ( typeof key === "undefined" ) {
+ if ( this.length ) {
+ data = jQuery.data( this[0] );
+
+ if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
+ attr = this[0].attributes;
+ for ( var i = 0, l = attr.length; i < l; i++ ) {
+ name = attr[i].name;
+
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.substring(5) );
+
+ dataAttr( this[0], name, data[ name ] );
+ }
+ }
+ jQuery._data( this[0], "parsedAttrs", true );
+ }
+ }
+
+ return data;
+
+ } else if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ // Try to fetch any internally stored data first
+ if ( data === undefined && this.length ) {
+ data = jQuery.data( this[0], key );
+ data = dataAttr( this[0], key, data );
+ }
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+
+ } else {
+ return this.each(function() {
+ var self = jQuery( this ),
+ args = [ parts[0], value ];
+
+ self.triggerHandler( "setData" + parts[1] + "!", args );
+ jQuery.data( this, key, value );
+ self.triggerHandler( "changeData" + parts[1] + "!", args );
+ });
+ }
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ jQuery.isNumeric( data ) ? parseFloat( data ) :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ for ( var name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+
+function handleQueueMarkDefer( elem, type, src ) {
+ var deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ defer = jQuery._data( elem, deferDataKey );
+ if ( defer &&
+ ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
+ ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
+ // Give room for hard-coded callbacks to fire first
+ // and eventually mark/queue something else on the element
+ setTimeout( function() {
+ if ( !jQuery._data( elem, queueDataKey ) &&
+ !jQuery._data( elem, markDataKey ) ) {
+ jQuery.removeData( elem, deferDataKey, true );
+ defer.fire();
+ }
+ }, 0 );
+ }
+}
+
+jQuery.extend({
+
+ _mark: function( elem, type ) {
+ if ( elem ) {
+ type = ( type || "fx" ) + "mark";
+ jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
+ }
+ },
+
+ _unmark: function( force, elem, type ) {
+ if ( force !== true ) {
+ type = elem;
+ elem = force;
+ force = false;
+ }
+ if ( elem ) {
+ type = type || "fx";
+ var key = type + "mark",
+ count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
+ if ( count ) {
+ jQuery._data( elem, key, count );
+ } else {
+ jQuery.removeData( elem, key, true );
+ handleQueueMarkDefer( elem, type, "mark" );
+ }
+ }
+ },
+
+ queue: function( elem, type, data ) {
+ var q;
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ q = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !q || jQuery.isArray(data) ) {
+ q = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ q.push( data );
+ }
+ }
+ return q || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift(),
+ hooks = {};
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ }
+
+ if ( fn ) {
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ jQuery._data( elem, type + ".run", hooks );
+ fn.call( elem, function() {
+ jQuery.dequeue( elem, type );
+ }, hooks );
+ }
+
+ if ( !queue.length ) {
+ jQuery.removeData( elem, type + "queue " + type + ".run", true );
+ handleQueueMarkDefer( elem, type, "queue" );
+ }
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ }
+
+ if ( data === undefined ) {
+ return jQuery.queue( this[0], type );
+ }
+ return this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, object ) {
+ if ( typeof type !== "string" ) {
+ object = type;
+ type = undefined;
+ }
+ type = type || "fx";
+ var defer = jQuery.Deferred(),
+ elements = this,
+ i = elements.length,
+ count = 1,
+ deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ tmp;
+ function resolve() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ }
+ while( i-- ) {
+ if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+ ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+ jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+ jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
+ count++;
+ tmp.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise();
+ }
+});
+
+
+
+
+var rclass = /[\n\t\r]/g,
+ rspace = /\s+/,
+ rreturn = /\r/g,
+ rtype = /^(?:button|input)$/i,
+ rfocusable = /^(?:button|input|object|select|textarea)$/i,
+ rclickable = /^a(?:rea)?$/i,
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ nodeHook, boolHook, fixSpecified;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, name, value, true, jQuery.attr );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, name, value, true, jQuery.prop );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classNames, i, l, elem,
+ setClass, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( value && typeof value === "string" ) {
+ classNames = value.split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className && classNames.length === 1 ) {
+ elem.className = value;
+
+ } else {
+ setClass = " " + elem.className + " ";
+
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+ setClass += classNames[ c ] + " ";
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classNames, i, l, elem, className, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( (value && typeof value === "string") || value === undefined ) {
+ classNames = ( value || "" ).split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 && elem.className ) {
+ if ( value ) {
+ className = (" " + elem.className + " ").replace( rclass, " " );
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ className = className.replace(" " + classNames[ c ] + " ", " ");
+ }
+ elem.className = jQuery.trim( className );
+
+ } else {
+ elem.className = "";
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.split( rspace );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space seperated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var self = jQuery(this), val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, i, max, option,
+ index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
+
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
+
+ // Loop through all the selected options
+ i = one ? index : 0;
+ max = one ? index + 1 : options.length;
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Don't return options that are disabled or in a disabled optgroup
+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+ if ( one && !values.length && options.length ) {
+ return jQuery( options[ index ] ).val();
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attrFn: {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true
+ },
+
+ attr: function( elem, name, value, pass ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( pass && name in jQuery.attrFn ) {
+ return jQuery( elem )[ name ]( value );
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+
+ } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, "" + value );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ ret = elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret === null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var propName, attrNames, name, l,
+ i = 0;
+
+ if ( value && elem.nodeType === 1 ) {
+ attrNames = value.toLowerCase().split( rspace );
+ l = attrNames.length;
+
+ for ( ; i < l; i++ ) {
+ name = attrNames[ i ];
+
+ if ( name ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ jQuery.attr( elem, name, "" );
+ elem.removeAttribute( getSetAttribute ? name : propName );
+
+ // Set corresponding property to false for boolean attributes
+ if ( rboolean.test( name ) && propName in elem ) {
+ elem[ propName ] = false;
+ }
+ }
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to it's default in case type is set after value
+ // This is for element creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ },
+ // Use the value property for back compat
+ // Use the nodeHook for button elements in IE6/7 (#1954)
+ value: {
+ get: function( elem, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.get( elem, name );
+ }
+ return name in elem ?
+ elem.value :
+ null;
+ },
+ set: function( elem, value, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.set( elem, value, name );
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+});
+
+// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
+jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
+
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ // Fall back to attribute presence where some booleans are not supported
+ var attrNode,
+ property = jQuery.prop( elem, name );
+ return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = true;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ fixSpecified = {
+ name: true,
+ id: true
+ };
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret;
+ ret = elem.getAttributeNode( name );
+ return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
+ ret.nodeValue :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ ret = document.createAttribute( name );
+ elem.setAttributeNode( ret );
+ }
+ return ( ret.nodeValue = value + "" );
+ }
+ };
+
+ // Apply the nodeHook to tabindex
+ jQuery.attrHooks.tabindex.set = nodeHook.set;
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ if ( value === "" ) {
+ value = "false";
+ }
+ nodeHook.set( elem, value, name );
+ }
+ };
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret === null ? undefined : ret;
+ }
+ });
+ });
+}
+
+if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Normalize to lowercase since IE uppercases css property names
+ return elem.style.cssText.toLowerCase() || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = "" + value );
+ }
+ };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+});
+
+
+
+
+var rformElems = /^(?:textarea|input|select)$/i,
+ rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
+ rhoverHack = /\bhover(\.\S+)?\b/,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
+ quickParse = function( selector ) {
+ var quick = rquickIs.exec( selector );
+ if ( quick ) {
+ // 0 1 2 3
+ // [ _, tag, id, class ]
+ quick[1] = ( quick[1] || "" ).toLowerCase();
+ quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
+ }
+ return quick;
+ },
+ quickIs = function( elem, m ) {
+ var attrs = elem.attributes || {};
+ return (
+ (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
+ (!m[2] || (attrs.id || {}).value === m[2]) &&
+ (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
+ );
+ },
+ hoverHack = function( events ) {
+ return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+ };
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var elemData, eventHandle, events,
+ t, tns, type, namespaces, handleObj,
+ handleObjIn, quick, handlers, special;
+
+ // Don't attach events to noData or text/comment nodes (allow plain objects tho)
+ if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ events = elemData.events;
+ if ( !events ) {
+ elemData.events = events = {};
+ }
+ eventHandle = elemData.handle;
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = jQuery.trim( hoverHack(types) ).split( " " );
+ for ( t = 0; t < types.length; t++ ) {
+
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = tns[1];
+ namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: tns[1],
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ quick: quickParse( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ handlers = events[ type ];
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+ t, tns, type, origType, namespaces, origCount,
+ j, events, special, handle, eventType, handleObj;
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+ for ( t = 0; t < types.length; t++ ) {
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tns[1];
+ namespaces = tns[2];
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector? special.delegateType : special.bindType ) || type;
+ eventType = events[ type ] || [];
+ origCount = eventType.length;
+ namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+
+ // Remove matching events
+ for ( j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ eventType.splice( j--, 1 );
+
+ if ( handleObj.selector ) {
+ eventType.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( eventType.length === 0 && origCount !== eventType.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ handle = elemData.handle;
+ if ( handle ) {
+ handle.elem = null;
+ }
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery.removeData( elem, [ "events", "handle" ], true );
+ }
+ },
+
+ // Events that are safe to short-circuit if no handlers are attached.
+ // Native DOM events should not be added, they may have inline handlers.
+ customEvent: {
+ "getData": true,
+ "setData": true,
+ "changeData": true
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ // Don't do events on text and comment nodes
+ if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+ return;
+ }
+
+ // Event object or event type
+ var type = event.type || event,
+ namespaces = [],
+ cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "!" ) >= 0 ) {
+ // Exclusive events trigger only for the exact event (no namespaces)
+ type = type.slice(0, -1);
+ exclusive = true;
+ }
+
+ if ( type.indexOf( "." ) >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+
+ if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+ // No jQuery handlers for this event type, and it can't have inline handlers
+ return;
+ }
+
+ // Caller can pass in an Event, Object, or just an event type string
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[ jQuery.expando ] ? event :
+ // Object literal
+ new jQuery.Event( type, event ) :
+ // Just the event type (string)
+ new jQuery.Event( type );
+
+ event.type = type;
+ event.isTrigger = true;
+ event.exclusive = exclusive;
+ event.namespace = namespaces.join( "." );
+ event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+ ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+ // Handle a global trigger
+ if ( !elem ) {
+
+ // TODO: Stop taunting the data cache; remove global events and always attach to document
+ cache = jQuery.cache;
+ for ( i in cache ) {
+ if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+ jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+ }
+ }
+ return;
+ }
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data != null ? jQuery.makeArray( data ) : [];
+ data.unshift( event );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ eventPath = [[ elem, special.bindType || type ]];
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
+ old = null;
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push([ cur, bubbleType ]);
+ old = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( old && old === elem.ownerDocument ) {
+ eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+ }
+ }
+
+ // Fire handlers on the event path
+ for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
+
+ cur = eventPath[i][0];
+ event.type = eventPath[i][1];
+
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+ // Note that this is a bare JS function and not a jQuery handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ // IE<9 dies on focus/blur to hidden element (#1486)
+ if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ old = elem[ ontype ];
+
+ if ( old ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( old ) {
+ elem[ ontype ] = old;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event || window.event );
+
+ var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+ delegateCount = handlers.delegateCount,
+ args = [].slice.call( arguments, 0 ),
+ run_all = !event.exclusive && !event.namespace,
+ handlerQueue = [],
+ i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Determine handlers that should run if there are delegated events
+ // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {
+
+ // Pregenerate a single jQuery object for reuse with .is()
+ jqcur = jQuery(this);
+ jqcur.context = this.ownerDocument || this;
+
+ for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+ selMatch = {};
+ matches = [];
+ jqcur[0] = cur;
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+ sel = handleObj.selector;
+
+ if ( selMatch[ sel ] === undefined ) {
+ selMatch[ sel ] = (
+ handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
+ );
+ }
+ if ( selMatch[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, matches: matches });
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( handlers.length > delegateCount ) {
+ handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+ }
+
+ // Run delegates first; they may want to stop propagation beneath us
+ for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+ matched = handlerQueue[ i ];
+ event.currentTarget = matched.elem;
+
+ for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+ handleObj = matched.matches[ j ];
+
+ // Triggered event must either 1) be non-exclusive and have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+ props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var eventDoc, doc, body,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop,
+ originalEvent = event,
+ fixHook = jQuery.event.fixHooks[ event.type ] || {},
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = jQuery.Event( originalEvent );
+
+ for ( i = copy.length; i; ) {
+ prop = copy[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Target should not be a text node (#504, Safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
+ if ( event.metaKey === undefined ) {
+ event.metaKey = event.ctrlKey;
+ }
+
+ return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: jQuery.bindReady
+ },
+
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+
+ focus: {
+ delegateType: "focusin"
+ },
+ blur: {
+ delegateType: "focusout"
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( jQuery.isWindow( this ) ) {
+ this.onbeforeunload = eventHandle;
+ }
+ },
+
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+jQuery.event.handle = jQuery.event.dispatch;
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ if ( elem.detachEvent ) {
+ elem.detachEvent( "on" + type, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+ return false;
+}
+function returnTrue() {
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // otherwise set the returnValue property of the original event to false (IE)
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj,
+ selector = handleObj.selector,
+ ret;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !form._submit_attached ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ });
+ form._submit_attached = true;
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ jQuery.event.simulate( "change", this, event, true );
+ }
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ elem._change_attached = true;
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on.call( this, types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ var handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( var type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ live: function( types, data, fn ) {
+ jQuery( this.context ).on( types, this.selector, data, fn );
+ return this;
+ },
+ die: function( types, fn ) {
+ jQuery( this.context ).off( types, this.selector || "**", fn );
+ return this;
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ return jQuery.event.trigger( type, data, this[0], true );
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ guid = fn.guid || jQuery.guid++,
+ i = 0,
+ toggler = function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ };
+
+ // link all the functions, so any of them can unbind this click handler
+ toggler.guid = guid;
+ while ( i < args.length ) {
+ args[ i++ ].guid = guid;
+ }
+
+ return this.click( toggler );
+ },
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+});
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ if ( fn == null ) {
+ fn = data;
+ data = null;
+ }
+
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
+ }
+
+ if ( rkeyEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+ }
+
+ if ( rmouseEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+ }
+});
+
+
+
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+ expando = "sizcache" + (Math.random() + '').replace('.', ''),
+ done = 0,
+ toString = Object.prototype.toString,
+ hasDuplicate = false,
+ baseHasDuplicate = true,
+ rBackslash = /\\/g,
+ rReturn = /\r\n/g,
+ rNonWord = /\W/;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+// Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+ baseHasDuplicate = false;
+ return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+ results = results || [];
+ context = context || document;
+
+ var origContext = context;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var m, set, checkSet, extra, ret, cur, pop, i,
+ prune = true,
+ contextXML = Sizzle.isXML( context ),
+ parts = [],
+ soFar = selector;
+
+ // Reset the position of the chunker regexp (start from head)
+ do {
+ chunker.exec( "" );
+ m = chunker.exec( soFar );
+
+ if ( m ) {
+ soFar = m[3];
+
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = m[3];
+ break;
+ }
+ }
+ } while ( m );
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context, seed );
+
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] ) {
+ selector += parts.shift();
+ }
+
+ set = posProcess( selector, set, seed );
+ }
+ }
+
+ } else {
+ // Take a shortcut and set the context if the root selector is an ID
+ // (but not if it'll be faster if the inner selector is an ID)
+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+ ret = Sizzle.find( parts.shift(), context, contextXML );
+ context = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set )[0] :
+ ret.set[0];
+ }
+
+ if ( context ) {
+ ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+ set = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set ) :
+ ret.set;
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray( set );
+
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ cur = parts.pop();
+ pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, contextXML );
+ }
+
+ } else {
+ checkSet = parts = [];
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ Sizzle.error( cur || selector );
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+
+ } else if ( context && context.nodeType === 1 ) {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+
+ } else {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, origContext, results, seed );
+ Sizzle.uniqueSort( results );
+ }
+
+ return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+ if ( sortOrder ) {
+ hasDuplicate = baseHasDuplicate;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[ i - 1 ] ) {
+ results.splice( i--, 1 );
+ }
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+ return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+ return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+ var set, i, len, match, type, left;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( i = 0, len = Expr.order.length; i < len; i++ ) {
+ type = Expr.order[i];
+
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+ left = match[1];
+ match.splice( 1, 1 );
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace( rBackslash, "" );
+ set = Expr.find[ type ]( match, context, isXML );
+
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( "*" ) :
+ [];
+ }
+
+ return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+ var match, anyFound,
+ type, found, item, filter, left,
+ i, pass,
+ old = expr,
+ result = [],
+ curLoop = set,
+ isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+ while ( expr && set.length ) {
+ for ( type in Expr.filter ) {
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+ filter = Expr.filter[ type ];
+ left = match[1];
+
+ anyFound = false;
+
+ match.splice(1,1);
+
+ if ( left.substr( left.length - 1 ) === "\\" ) {
+ continue;
+ }
+
+ if ( curLoop === result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+ if ( !match ) {
+ anyFound = found = true;
+
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ pass = not ^ found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+
+ } else {
+ curLoop[i] = false;
+ }
+
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Improper expression
+ if ( expr === old ) {
+ if ( anyFound == null ) {
+ Sizzle.error( expr );
+
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Utility function for retreiving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+var getText = Sizzle.getText = function( elem ) {
+ var i, node,
+ nodeType = elem.nodeType,
+ ret = "";
+
+ if ( nodeType ) {
+ if ( nodeType === 1 || nodeType === 9 ) {
+ // Use textContent || innerText for elements
+ if ( typeof elem.textContent === 'string' ) {
+ return elem.textContent;
+ } else if ( typeof elem.innerText === 'string' ) {
+ // Replace IE's carriage returns
+ return elem.innerText.replace( rReturn, '' );
+ } else {
+ // Traverse it's children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ } else {
+
+ // If no nodeType, this is expected to be an array
+ for ( i = 0; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ if ( node.nodeType !== 8 ) {
+ ret += getText( node );
+ }
+ }
+ }
+ return ret;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+ },
+
+ leftMatch: {},
+
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
+
+ attrHandle: {
+ href: function( elem ) {
+ return elem.getAttribute( "href" );
+ },
+ type: function( elem ) {
+ return elem.getAttribute( "type" );
+ }
+ },
+
+ relative: {
+ "+": function(checkSet, part){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !rNonWord.test( part ),
+ isPartStrNotTag = isPartStr && !isTag;
+
+ if ( isTag ) {
+ part = part.toLowerCase();
+ }
+
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+ elem || false :
+ elem === part;
+ }
+ }
+
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+
+ ">": function( checkSet, part ) {
+ var elem,
+ isPartStr = typeof part === "string",
+ i = 0,
+ l = checkSet.length;
+
+ if ( isPartStr && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+ }
+ }
+
+ } else {
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+
+ "": function(checkSet, part, isXML){
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+ },
+
+ "~": function( checkSet, part, isXML ) {
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+ }
+ },
+
+ find: {
+ ID: function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ },
+
+ NAME: function( match, context ) {
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [],
+ results = context.getElementsByName( match[1] );
+
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
+
+ return ret.length === 0 ? null : ret;
+ }
+ },
+
+ TAG: function( match, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( match[1] );
+ }
+ }
+ },
+ preFilter: {
+ CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+ match = " " + match[1].replace( rBackslash, "" ) + " ";
+
+ if ( isXML ) {
+ return match;
+ }
+
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
+ if ( !inplace ) {
+ result.push( elem );
+ }
+
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+
+ ID: function( match ) {
+ return match[1].replace( rBackslash, "" );
+ },
+
+ TAG: function( match, curLoop ) {
+ return match[1].replace( rBackslash, "" ).toLowerCase();
+ },
+
+ CHILD: function( match ) {
+ if ( match[1] === "nth" ) {
+ if ( !match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ match[2] = match[2].replace(/^\+|\s*/g, '');
+
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+ else if ( match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
+
+ ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+ var name = match[1] = match[1].replace( rBackslash, "" );
+
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ // Handle if an un-quoted value was used
+ match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+
+ PSEUDO: function( match, curLoop, inplace, result, not ) {
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+
+ return false;
+ }
+
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+
+ POS: function( match ) {
+ match.unshift( true );
+
+ return match;
+ }
+ },
+
+ filters: {
+ enabled: function( elem ) {
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+
+ disabled: function( elem ) {
+ return elem.disabled === true;
+ },
+
+ checked: function( elem ) {
+ return elem.checked === true;
+ },
+
+ selected: function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ parent: function( elem ) {
+ return !!elem.firstChild;
+ },
+
+ empty: function( elem ) {
+ return !elem.firstChild;
+ },
+
+ has: function( elem, i, match ) {
+ return !!Sizzle( match[3], elem ).length;
+ },
+
+ header: function( elem ) {
+ return (/h\d/i).test( elem.nodeName );
+ },
+
+ text: function( elem ) {
+ var attr = elem.getAttribute( "type" ), type = elem.type;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
+ },
+
+ radio: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
+ },
+
+ checkbox: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
+ },
+
+ file: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
+ },
+
+ password: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
+ },
+
+ submit: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "submit" === elem.type;
+ },
+
+ image: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
+ },
+
+ reset: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "reset" === elem.type;
+ },
+
+ button: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && "button" === elem.type || name === "button";
+ },
+
+ input: function( elem ) {
+ return (/input|select|textarea|button/i).test( elem.nodeName );
+ },
+
+ focus: function( elem ) {
+ return elem === elem.ownerDocument.activeElement;
+ }
+ },
+ setFilters: {
+ first: function( elem, i ) {
+ return i === 0;
+ },
+
+ last: function( elem, i, match, array ) {
+ return i === array.length - 1;
+ },
+
+ even: function( elem, i ) {
+ return i % 2 === 0;
+ },
+
+ odd: function( elem, i ) {
+ return i % 2 === 1;
+ },
+
+ lt: function( elem, i, match ) {
+ return i < match[3] - 0;
+ },
+
+ gt: function( elem, i, match ) {
+ return i > match[3] - 0;
+ },
+
+ nth: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ },
+
+ eq: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ }
+ },
+ filter: {
+ PSEUDO: function( elem, match, i, array ) {
+ var name = match[1],
+ filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var j = 0, l = not.length; j < l; j++ ) {
+ if ( not[j] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ } else {
+ Sizzle.error( name );
+ }
+ },
+
+ CHILD: function( elem, match ) {
+ var first, last,
+ doneName, parent, cache,
+ count, diff,
+ type = match[1],
+ node = elem;
+
+ switch ( type ) {
+ case "only":
+ case "first":
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ if ( type === "first" ) {
+ return true;
+ }
+
+ node = elem;
+
+ case "last":
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ case "nth":
+ first = match[2];
+ last = match[3];
+
+ if ( first === 1 && last === 0 ) {
+ return true;
+ }
+
+ doneName = match[0];
+ parent = elem.parentNode;
+
+ if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
+ count = 0;
+
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
+
+ parent[ expando ] = doneName;
+ }
+
+ diff = elem.nodeIndex - last;
+
+ if ( first === 0 ) {
+ return diff === 0;
+
+ } else {
+ return ( diff % first === 0 && diff / first >= 0 );
+ }
+ }
+ },
+
+ ID: function( elem, match ) {
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+
+ TAG: function( elem, match ) {
+ return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
+ },
+
+ CLASS: function( elem, match ) {
+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
+ .indexOf( match ) > -1;
+ },
+
+ ATTR: function( elem, match ) {
+ var name = match[1],
+ result = Sizzle.attr ?
+ Sizzle.attr( elem, name ) :
+ Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ !type && Sizzle.attr ?
+ result != null :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value !== check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+
+ POS: function( elem, match, i, array ) {
+ var name = match[2],
+ filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS,
+ fescape = function(all, num){
+ return "\\" + (num - 0 + 1);
+ };
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+ array = Array.prototype.slice.call( array, 0 );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+ makeArray = function( array, results ) {
+ var i = 0,
+ ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+
+ } else {
+ for ( ; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+ return a.compareDocumentPosition ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+ };
+
+} else {
+ sortOrder = function( a, b ) {
+ // The nodes are identical, we can exit early
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
+ } else if ( a.sourceIndex && b.sourceIndex ) {
+ return a.sourceIndex - b.sourceIndex;
+ }
+
+ var al, bl,
+ ap = [],
+ bp = [],
+ aup = a.parentNode,
+ bup = b.parentNode,
+ cur = aup;
+
+ // If the nodes are siblings (or identical) we can do a quick check
+ if ( aup === bup ) {
+ return siblingCheck( a, b );
+
+ // If no parents were found then the nodes are disconnected
+ } else if ( !aup ) {
+ return -1;
+
+ } else if ( !bup ) {
+ return 1;
+ }
+
+ // Otherwise they're somewhere else in the tree so we need
+ // to build up a full list of the parentNodes for comparison
+ while ( cur ) {
+ ap.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ cur = bup;
+
+ while ( cur ) {
+ bp.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ al = ap.length;
+ bl = bp.length;
+
+ // Start walking down the tree looking for a discrepancy
+ for ( var i = 0; i < al && i < bl; i++ ) {
+ if ( ap[i] !== bp[i] ) {
+ return siblingCheck( ap[i], bp[i] );
+ }
+ }
+
+ // We ended someplace up the tree so do a sibling check
+ return i === al ?
+ siblingCheck( a, bp[i], -1 ) :
+ siblingCheck( ap[i], b, 1 );
+ };
+
+ siblingCheck = function( a, b, ret ) {
+ if ( a === b ) {
+ return ret;
+ }
+
+ var cur = a.nextSibling;
+
+ while ( cur ) {
+ if ( cur === b ) {
+ return -1;
+ }
+
+ cur = cur.nextSibling;
+ }
+
+ return 1;
+ };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("div"),
+ id = "script" + (new Date()).getTime(),
+ root = document.documentElement;
+
+ form.innerHTML = "<a name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( document.getElementById( id ) ) {
+ Expr.find.ID = function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+
+ return m ?
+ m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+
+ Expr.filter.ID = function( elem, match ) {
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+
+ // release memory in IE
+ root = form = null;
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function( match, context ) {
+ var results = context.getElementsByTagName( match[1] );
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+
+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
+
+ Expr.attrHandle.href = function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ };
+ }
+
+ // release memory in IE
+ div = null;
+})();
+
+if ( document.querySelectorAll ) {
+ (function(){
+ var oldSizzle = Sizzle,
+ div = document.createElement("div"),
+ id = "__sizzle__";
+
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
+
+ Sizzle = function( query, context, extra, seed ) {
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && !Sizzle.isXML(context) ) {
+ // See if we find a selector to speed up
+ var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
+
+ if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
+ // Speed-up: Sizzle("TAG")
+ if ( match[1] ) {
+ return makeArray( context.getElementsByTagName( query ), extra );
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
+ return makeArray( context.getElementsByClassName( match[2] ), extra );
+ }
+ }
+
+ if ( context.nodeType === 9 ) {
+ // Speed-up: Sizzle("body")
+ // The body element only exists once, optimize finding it
+ if ( query === "body" && context.body ) {
+ return makeArray( [ context.body ], extra );
+
+ // Speed-up: Sizzle("#ID")
+ } else if ( match && match[3] ) {
+ var elem = context.getElementById( match[3] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id === match[3] ) {
+ return makeArray( [ elem ], extra );
+ }
+
+ } else {
+ return makeArray( [], extra );
+ }
+ }
+
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(qsaError) {}
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ var oldContext = context,
+ old = context.getAttribute( "id" ),
+ nid = old || id,
+ hasParent = context.parentNode,
+ relativeHierarchySelector = /^\s*[+~]/.test( query );
+
+ if ( !old ) {
+ context.setAttribute( "id", nid );
+ } else {
+ nid = nid.replace( /'/g, "\\$&" );
+ }
+ if ( relativeHierarchySelector && hasParent ) {
+ context = context.parentNode;
+ }
+
+ try {
+ if ( !relativeHierarchySelector || hasParent ) {
+ return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
+ }
+
+ } catch(pseudoError) {
+ } finally {
+ if ( !old ) {
+ oldContext.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ for ( var prop in oldSizzle ) {
+ Sizzle[ prop ] = oldSizzle[ prop ];
+ }
+
+ // release memory in IE
+ div = null;
+ })();
+}
+
+(function(){
+ var html = document.documentElement,
+ matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
+
+ if ( matches ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9 fails this)
+ var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
+ pseudoWorks = false;
+
+ try {
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( document.documentElement, "[test!='']:sizzle" );
+
+ } catch( pseudoError ) {
+ pseudoWorks = true;
+ }
+
+ Sizzle.matchesSelector = function( node, expr ) {
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+ if ( !Sizzle.isXML( node ) ) {
+ try {
+ if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+ var ret = matches.call( node, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || !disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9, so check for that
+ node.document && node.document.nodeType !== 11 ) {
+ return ret;
+ }
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle(expr, null, null, [node]).length > 0;
+ };
+ }
+})();
+
+(function(){
+ var div = document.createElement("div");
+
+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+ // Opera can't find a second classname (in 9.6)
+ // Also, make sure that getElementsByClassName actually exists
+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+ return;
+ }
+
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
+
+ if ( div.getElementsByClassName("e").length === 1 ) {
+ return;
+ }
+
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function( match, context, isXML ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
+
+ // release memory in IE
+ div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML ){
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
+
+ if ( elem.nodeName.toLowerCase() === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
+
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+if ( document.documentElement.contains ) {
+ Sizzle.contains = function( a, b ) {
+ return a !== b && (a.contains ? a.contains(b) : true);
+ };
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+ Sizzle.contains = function( a, b ) {
+ return !!(a.compareDocumentPosition(b) & 16);
+ };
+
+} else {
+ Sizzle.contains = function() {
+ return false;
+ };
+}
+
+Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context, seed ) {
+ var match,
+ tmpSet = [],
+ later = "",
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet, seed );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+Sizzle.selectors.attrMap = {};
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+ // Note: This RegExp should be improved, or likely pulled from Sizzle
+ rmultiselector = /,/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ slice = Array.prototype.slice,
+ POS = jQuery.expr.match.POS,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var self = this,
+ i, l;
+
+ if ( typeof selector !== "string" ) {
+ return jQuery( selector ).filter(function() {
+ for ( i = 0, l = self.length; i < l; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ });
+ }
+
+ var ret = this.pushStack( "", "find", selector ),
+ length, n, r;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( n = length; n < ret.length; n++ ) {
+ for ( r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ has: function( target ) {
+ var targets = jQuery( target );
+ return this.filter(function() {
+ for ( var i = 0, l = targets.length; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ POS.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var ret = [], i, l, cur = this[0];
+
+ // Array (deprecated as of jQuery 1.7)
+ if ( jQuery.isArray( selectors ) ) {
+ var level = 1;
+
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ for ( i = 0; i < selectors.length; i++ ) {
+
+ if ( jQuery( cur ).is( selectors[ i ] ) ) {
+ ret.push({ selector: selectors[ i ], elem: cur, level: level });
+ }
+ }
+
+ cur = cur.parentNode;
+ level++;
+ }
+
+ return ret;
+ }
+
+ // String
+ var pos = POS.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+
+ } else {
+ cur = cur.parentNode;
+ if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
+ break;
+ }
+ }
+ }
+ }
+
+ ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+ return this.pushStack( ret, "closest", selectors );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ }
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return jQuery.nth( elem, 2, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return jQuery.nth( elem, 2, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( elem.parentNode.firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.makeArray( elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret, name, slice.call( arguments ).join(",") );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ nth: function( cur, result, dir, elem ) {
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] ) {
+ if ( cur.nodeType === 1 && ++num === result ) {
+ break;
+ }
+ }
+
+ return cur;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+}
+
+
+
+
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style)/i,
+ rnocache = /<(?:script|object|embed|option|style)/i,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"),
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /\/(java|ecma)script/i,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ area: [ 1, "<map>", "</map>" ],
+ _default: [ 0, "", "" ]
+ },
+ safeFragment = createSafeFragment( document );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+ text: function( text ) {
+ if ( jQuery.isFunction(text) ) {
+ return this.each(function(i) {
+ var self = jQuery( this );
+
+ self.text( text.call(this, i, self.text()) );
+ });
+ }
+
+ if ( typeof text !== "object" && text !== undefined ) {
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+ }
+
+ return jQuery.text( this );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ } else if ( arguments.length ) {
+ var set = jQuery.clean( arguments );
+ set.push.apply( set, this.toArray() );
+ return this.pushStack( set, "before", arguments );
+ }
+ },
+
+ after: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ } else if ( arguments.length ) {
+ var set = this.pushStack( this, "after", arguments );
+ set.push.apply( set, jQuery.clean(arguments) );
+ return set;
+ }
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ if ( value === undefined ) {
+ return this[0] && this[0].nodeType === 1 ?
+ this[0].innerHTML.replace(rinlinejQuery, "") :
+ null;
+
+ // See if we can take a shortcut and just use innerHTML
+ } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+ value = value.replace(rxhtmlTag, "<$1></$2>");
+
+ try {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( this[i].nodeType === 1 ) {
+ jQuery.cleanData( this[i].getElementsByTagName("*") );
+ this[i].innerHTML = value;
+ }
+ }
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {
+ this.empty().append( value );
+ }
+
+ } else if ( jQuery.isFunction( value ) ) {
+ this.each(function(i){
+ var self = jQuery( this );
+
+ self.html( value.call(this, i, self.html()) );
+ });
+
+ } else {
+ this.empty().append( value );
+ }
+
+ return this;
+ },
+
+ replaceWith: function( value ) {
+ if ( this[0] && this[0].parentNode ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
+
+ if ( typeof value !== "string" ) {
+ value = jQuery( value ).detach();
+ }
+
+ return this.each(function() {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ jQuery( this ).remove();
+
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ } else {
+ return this.length ?
+ this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+ this;
+ }
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+ var results, first, fragment, parent,
+ value = args[0],
+ scripts = [];
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback, true );
+ });
+ }
+
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call(this, i, table ? self.html() : undefined);
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( this[0] ) {
+ parent = value && value.parentNode;
+
+ // If we're in a fragment, just use that instead of building a new one
+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+ results = { fragment: parent };
+
+ } else {
+ results = jQuery.buildFragment( args, this, scripts );
+ }
+
+ fragment = results.fragment;
+
+ if ( fragment.childNodes.length === 1 ) {
+ first = fragment = fragment.firstChild;
+ } else {
+ first = fragment.firstChild;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
+ callback.call(
+ table ?
+ root(this[i], first) :
+ this[i],
+ // Make sure that we do not leak memory by inadvertently discarding
+ // the original fragment (which might have attached data) instead of
+ // using it; in addition, use the original fragment object for the last
+ // item instead of first because it can end up being emptied incorrectly
+ // in certain situations (Bug #8070).
+ // Fragments from the fragment cache must always be cloned and never used
+ // in place.
+ results.cacheable || ( l > 1 && i < lastIndex ) ?
+ jQuery.clone( fragment, true, true ) :
+ fragment
+ );
+ }
+ }
+
+ if ( scripts.length ) {
+ jQuery.each( scripts, evalScript );
+ }
+ }
+
+ return this;
+ }
+});
+
+function root( elem, cur ) {
+ return jQuery.nodeName(elem, "table") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function cloneFixAttributes( src, dest ) {
+ var nodeName;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // clearAttributes removes the attributes, which we don't want,
+ // but also removes the attachEvent events, which we *do* want
+ if ( dest.clearAttributes ) {
+ dest.clearAttributes();
+ }
+
+ // mergeAttributes, in contrast, only merges back on the
+ // original attributes, not the events
+ if ( dest.mergeAttributes ) {
+ dest.mergeAttributes( src );
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 fail to clone children inside object elements that use
+ // the proprietary classid attribute value (rather than the type
+ // attribute) to identify the type of content to display
+ if ( nodeName === "object" ) {
+ dest.outerHTML = src.outerHTML;
+
+ } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+ if ( src.checked ) {
+ dest.defaultChecked = dest.checked = src.checked;
+ }
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+
+ // Event data gets referenced instead of copied if the expando
+ // gets copied too
+ dest.removeAttribute( jQuery.expando );
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+ var fragment, cacheable, cacheresults, doc,
+ first = args[ 0 ];
+
+ // nodes may contain either an explicit document object,
+ // a jQuery collection or context object.
+ // If nodes[0] contains a valid object to assign to doc
+ if ( nodes && nodes[0] ) {
+ doc = nodes[0].ownerDocument || nodes[0];
+ }
+
+ // Ensure that an attr object doesn't incorrectly stand in as a document object
+ // Chrome and Firefox seem to allow this to occur and will throw exception
+ // Fixes #8950
+ if ( !doc.createDocumentFragment ) {
+ doc = document;
+ }
+
+ // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+ // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+ if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
+ first.charAt(0) === "<" && !rnocache.test( first ) &&
+ (jQuery.support.checkClone || !rchecked.test( first )) &&
+ (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
+
+ cacheable = true;
+
+ cacheresults = jQuery.fragments[ first ];
+ if ( cacheresults && cacheresults !== 1 ) {
+ fragment = cacheresults;
+ }
+ }
+
+ if ( !fragment ) {
+ fragment = doc.createDocumentFragment();
+ jQuery.clean( args, doc, fragment, scripts );
+ }
+
+ if ( cacheable ) {
+ jQuery.fragments[ first ] = cacheresults ? fragment : 1;
+ }
+
+ return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [],
+ insert = jQuery( selector ),
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
+
+ } else {
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = ( i > 0 ? this.clone(true) : this ).get();
+ jQuery( insert[i] )[ original ]( elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, insert.selector );
+ }
+ };
+});
+
+function getAll( elem ) {
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ return elem.getElementsByTagName( "*" );
+
+ } else if ( typeof elem.querySelectorAll !== "undefined" ) {
+ return elem.querySelectorAll( "*" );
+
+ } else {
+ return [];
+ }
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( elem.type === "checkbox" || elem.type === "radio" ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+// Finds all inputs and passes them to fixDefaultChecked
+function findInputs( elem ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "input" ) {
+ fixDefaultChecked( elem );
+ // Skip scripts, get other children
+ } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
+ jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+ }
+}
+
+// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
+function shimCloneNode( elem ) {
+ var div = document.createElement( "div" );
+ safeFragment.appendChild( div );
+
+ div.innerHTML = elem.outerHTML;
+ return div.firstChild;
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var srcElements,
+ destElements,
+ i,
+ // IE<=8 does not properly clone detached, unknown element nodes
+ clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ?
+ elem.cloneNode( true ) :
+ shimCloneNode( elem );
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+ // IE copies events bound via attachEvent when using cloneNode.
+ // Calling detachEvent on the clone will also remove the events
+ // from the original. In order to get around this, we use some
+ // proprietary methods to clear the events. Thanks to MooTools
+ // guys for this hotness.
+
+ cloneFixAttributes( elem, clone );
+
+ // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ // Weird iteration because IE will replace the length property
+ // with an element if you are cloning the body and one of the
+ // elements on the page has a name or id of "length"
+ for ( i = 0; srcElements[i]; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ cloneFixAttributes( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ cloneCopyEvent( elem, clone );
+
+ if ( deepDataAndEvents ) {
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ for ( i = 0; srcElements[i]; ++i ) {
+ cloneCopyEvent( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ srcElements = destElements = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ clean: function( elems, context, fragment, scripts ) {
+ var checkScriptType;
+
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" ) {
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+ }
+
+ var ret = [], j;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
+
+ if ( !elem ) {
+ continue;
+ }
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ if ( !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
+ } else {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0],
+ div = context.createElement("div");
+
+ // Append wrapper element to unknown element safe doc fragment
+ if ( context === document ) {
+ // Use the fragment we've already created for this document
+ safeFragment.appendChild( div );
+ } else {
+ // Use a fragment created with the owner document
+ createSafeFragment( context ).appendChild( div );
+ }
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = rtbody.test(elem),
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+ }
+
+ elem = div.childNodes;
+ }
+ }
+
+ // Resets defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ var len;
+ if ( !jQuery.support.appendChecked ) {
+ if ( elem[0] && typeof (len = elem.length) === "number" ) {
+ for ( j = 0; j < len; j++ ) {
+ findInputs( elem[j] );
+ }
+ } else {
+ findInputs( elem );
+ }
+ }
+
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ ret = jQuery.merge( ret, elem );
+ }
+ }
+
+ if ( fragment ) {
+ checkScriptType = function( elem ) {
+ return !elem.type || rscriptType.test( elem.type );
+ };
+ for ( i = 0; ret[i]; i++ ) {
+ if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+
+ } else {
+ if ( ret[i].nodeType === 1 ) {
+ var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
+
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+ }
+ fragment.appendChild( ret[i] );
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ cleanData: function( elems ) {
+ var data, id,
+ cache = jQuery.cache,
+ special = jQuery.event.special,
+ deleteExpando = jQuery.support.deleteExpando;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ continue;
+ }
+
+ id = elem[ jQuery.expando ];
+
+ if ( id ) {
+ data = cache[ id ];
+
+ if ( data && data.events ) {
+ for ( var type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+
+ // Null the DOM reference to avoid IE6/7/8 leak (#7054)
+ if ( data.handle ) {
+ data.handle.elem = null;
+ }
+ }
+
+ if ( deleteExpando ) {
+ delete elem[ jQuery.expando ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ delete cache[ id ];
+ }
+ }
+ }
+});
+
+function evalScript( i, elem ) {
+ if ( elem.src ) {
+ jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+ } else {
+ jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+}
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity=([^)]*)/,
+ // fixed for IE9, see #8346
+ rupper = /([A-Z]|^ms)/g,
+ rnumpx = /^-?\d+(?:px)?$/i,
+ rnum = /^-?\d/,
+ rrelNum = /^([\-+])=([\-+.\de]+)/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssWidth = [ "Left", "Right" ],
+ cssHeight = [ "Top", "Bottom" ],
+ curCSS,
+
+ getComputedStyle,
+ currentStyle;
+
+jQuery.fn.css = function( name, value ) {
+ // Setting 'undefined' is a no-op
+ if ( arguments.length === 2 && value === undefined ) {
+ return this;
+ }
+
+ return jQuery.access( this, name, value, true, function( elem, name, value ) {
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ });
+};
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity", "opacity" );
+ return ret === "" ? "1" : ret;
+
+ } else {
+ return elem.style.opacity;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, origName = jQuery.camelCase( name ),
+ style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+ name = jQuery.cssProps[ origName ] || origName;
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra ) {
+ var ret, hooks;
+
+ // Make sure that we're working with the right name
+ name = jQuery.camelCase( name );
+ hooks = jQuery.cssHooks[ name ];
+ name = jQuery.cssProps[ name ] || name;
+
+ // cssFloat needs a special treatment
+ if ( name === "cssFloat" ) {
+ name = "float";
+ }
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+ return ret;
+
+ // Otherwise, if a way to get the computed value exists, use that
+ } else if ( curCSS ) {
+ return curCSS( elem, name );
+ }
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+ }
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ var val;
+
+ if ( computed ) {
+ if ( elem.offsetWidth !== 0 ) {
+ return getWH( elem, name, extra );
+ } else {
+ jQuery.swap( elem, cssShow, function() {
+ val = getWH( elem, name, extra );
+ });
+ }
+
+ return val;
+ }
+ },
+
+ set: function( elem, value ) {
+ if ( rnumpx.test( value ) ) {
+ // ignore negative width and height values #1599
+ value = parseFloat( value );
+
+ if ( value >= 0 ) {
+ return value + "px";
+ }
+
+ } else {
+ return value;
+ }
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( parseFloat( RegExp.$1 ) / 100 ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there there is no filter style applied in a css rule, we are done
+ if ( currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+jQuery(function() {
+ // This hook cannot be added until DOM ready because the support test
+ // for it is not run until after DOM ready
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ var ret;
+ jQuery.swap( elem, { "display": "inline-block" }, function() {
+ if ( computed ) {
+ ret = curCSS( elem, "margin-right", "marginRight" );
+ } else {
+ ret = elem.style.marginRight;
+ }
+ });
+ return ret;
+ }
+ };
+ }
+});
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+ getComputedStyle = function( elem, name ) {
+ var ret, defaultView, computedStyle;
+
+ name = name.replace( rupper, "-$1" ).toLowerCase();
+
+ if ( (defaultView = elem.ownerDocument.defaultView) &&
+ (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+ ret = computedStyle.getPropertyValue( name );
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+ }
+
+ return ret;
+ };
+}
+
+if ( document.documentElement.currentStyle ) {
+ currentStyle = function( elem, name ) {
+ var left, rsLeft, uncomputed,
+ ret = elem.currentStyle && elem.currentStyle[ name ],
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret === null && style && (uncomputed = style[ name ]) ) {
+ ret = uncomputed;
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ( ret || 0 );
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+
+ // Start with offset property
+ var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ which = name === "width" ? cssWidth : cssHeight,
+ i = 0,
+ len = which.length;
+
+ if ( val > 0 ) {
+ if ( extra !== "border" ) {
+ for ( ; i < len; i++ ) {
+ if ( !extra ) {
+ val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
+ } else {
+ val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
+ }
+ }
+ }
+
+ return val + "px";
+ }
+
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, name );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ] || 0;
+ }
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+
+ // Add padding, border, margin
+ if ( extra ) {
+ for ( ; i < len; i++ ) {
+ val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
+ if ( extra !== "padding" ) {
+ val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
+ }
+ }
+ }
+
+ return val + "px";
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ var width = elem.offsetWidth,
+ height = elem.offsetHeight;
+
+ return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+
+
+
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rhash = /#.*$/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rquery = /\?/,
+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ rselectTextarea = /^(?:select|textarea)/i,
+ rspacesAjax = /\s+/,
+ rts = /([?&])_=[^&]*/,
+ rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Document location
+ ajaxLocation,
+
+ // Document location segments
+ ajaxLocParts,
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = ["*/"] + ["*"];
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ if ( jQuery.isFunction( func ) ) {
+ var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
+ i = 0,
+ length = dataTypes.length,
+ dataType,
+ list,
+ placeBefore;
+
+ // For each dataType in the dataTypeExpression
+ for ( ; i < length; i++ ) {
+ dataType = dataTypes[ i ];
+ // We control if we're asked to add before
+ // any existing element
+ placeBefore = /^\+/.test( dataType );
+ if ( placeBefore ) {
+ dataType = dataType.substr( 1 ) || "*";
+ }
+ list = structure[ dataType ] = structure[ dataType ] || [];
+ // then we add to the structure accordingly
+ list[ placeBefore ? "unshift" : "push" ]( func );
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+ dataType /* internal */, inspected /* internal */ ) {
+
+ dataType = dataType || options.dataTypes[ 0 ];
+ inspected = inspected || {};
+
+ inspected[ dataType ] = true;
+
+ var list = structure[ dataType ],
+ i = 0,
+ length = list ? list.length : 0,
+ executeOnly = ( structure === prefilters ),
+ selection;
+
+ for ( ; i < length && ( executeOnly || !selection ); i++ ) {
+ selection = list[ i ]( options, originalOptions, jqXHR );
+ // If we got redirected to another dataType
+ // we try there if executing only and not done already
+ if ( typeof selection === "string" ) {
+ if ( !executeOnly || inspected[ selection ] ) {
+ selection = undefined;
+ } else {
+ options.dataTypes.unshift( selection );
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, selection, inspected );
+ }
+ }
+ }
+ // If we're only executing or nothing was selected
+ // we try the catchall dataType if not done already
+ if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, "*", inspected );
+ }
+ // unnecessary when only executing (prefilters)
+ // but it'll be ignored by the caller in that case
+ return selection;
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+}
+
+jQuery.fn.extend({
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+
+ // Don't do a request if no elements are being requested
+ } else if ( !this.length ) {
+ return this;
+ }
+
+ var off = url.indexOf( " " );
+ if ( off >= 0 ) {
+ var selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params ) {
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( typeof params === "object" ) {
+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+ type = "POST";
+ }
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ // Complete callback (responseText is used internally)
+ complete: function( jqXHR, status, responseText ) {
+ // Store the response as specified by the jqXHR object
+ responseText = jqXHR.responseText;
+ // If successful, inject the HTML into all the matched elements
+ if ( jqXHR.isResolved() ) {
+ // #4825: Get the actual response in case
+ // a dataFilter is present in ajaxSettings
+ jqXHR.done(function( r ) {
+ responseText = r;
+ });
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(responseText.replace(rscript, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ responseText );
+ }
+
+ if ( callback ) {
+ self.each( callback, [ responseText, status, jqXHR ] );
+ }
+ }
+ });
+
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray( this.elements ) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
+ rinput.test( this.type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val, i ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+ jQuery.fn[ o ] = function( f ){
+ return this.on( o, f );
+ };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ type: method,
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ };
+});
+
+jQuery.extend({
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ if ( settings ) {
+ // Building a settings object
+ ajaxExtend( target, jQuery.ajaxSettings );
+ } else {
+ // Extending ajaxSettings
+ settings = target;
+ target = jQuery.ajaxSettings;
+ }
+ ajaxExtend( target, settings );
+ return target;
+ },
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ text: "text/plain",
+ json: "application/json, text/javascript",
+ "*": allTypes
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
+
+ // List of data converters
+ // 1) key format is "source_type destination_type" (a single space in-between)
+ // 2) the catchall symbol "*" can be used for source_type
+ converters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ context: true,
+ url: true
+ }
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events
+ // It's the callbackContext if one was provided in the options
+ // and if it's a DOM node or a jQuery collection
+ globalEventContext = callbackContext !== s &&
+ ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+ jQuery( callbackContext ) : jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // ifModified key
+ ifModifiedKey,
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+ // transport
+ transport,
+ // timeout handle
+ timeoutTimer,
+ // Cross-domain detection vars
+ parts,
+ // The jqXHR state
+ state = 0,
+ // To know if global events are to be dispatched
+ fireGlobals,
+ // Loop variable
+ i,
+ // Fake xhr
+ jqXHR = {
+
+ readyState: 0,
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ if ( !state ) {
+ var lname = name.toLowerCase();
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match === undefined ? null : match;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ statusText = statusText || "abort";
+ if ( transport ) {
+ transport.abort( statusText );
+ }
+ done( 0, statusText );
+ return this;
+ }
+ };
+
+ // Callback for when everything is done
+ // It is defined here because jslint complains if it is declared
+ // at the end of the function (which would be more logical and readable)
+ function done( status, nativeStatusText, responses, headers ) {
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ var isSuccess,
+ success,
+ error,
+ statusText = nativeStatusText,
+ response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
+ lastModified,
+ etag;
+
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+
+ if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
+ jQuery.lastModified[ ifModifiedKey ] = lastModified;
+ }
+ if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
+ jQuery.etag[ ifModifiedKey ] = etag;
+ }
+ }
+
+ // If not modified
+ if ( status === 304 ) {
+
+ statusText = "notmodified";
+ isSuccess = true;
+
+ // If we have data
+ } else {
+
+ try {
+ success = ajaxConvert( s, response );
+ statusText = "success";
+ isSuccess = true;
+ } catch(e) {
+ // We have a parsererror
+ statusText = "parsererror";
+ error = e;
+ }
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( !statusText || status ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = "" + ( nativeStatusText || statusText );
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+ }
+
+ // Attach deferreds
+ deferred.promise( jqXHR );
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+ jqXHR.complete = completeDeferred.add;
+
+ // Status-dependent callbacks
+ jqXHR.statusCode = function( map ) {
+ if ( map ) {
+ var tmp;
+ if ( state < 2 ) {
+ for ( tmp in map ) {
+ statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+ }
+ } else {
+ tmp = map[ jqXHR.status ];
+ jqXHR.then( tmp, tmp );
+ }
+ }
+ return this;
+ };
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
+
+ // Determine if a cross-domain request is in order
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefiler, stop there
+ if ( state === 2 ) {
+ return false;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Get ifModifiedKey before adding the anti-cache parameter
+ ifModifiedKey = s.url;
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+
+ var ts = jQuery.now(),
+ // try replacing _= if it is there
+ ret = s.url.replace( rts, "$1_=" + ts );
+
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ ifModifiedKey = ifModifiedKey || s.url;
+ if ( jQuery.lastModified[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+ }
+ if ( jQuery.etag[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+ }
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already
+ jqXHR.abort();
+ return false;
+
+ }
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout( function(){
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch (e) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a, traditional ) {
+ var s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : value;
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( var prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+ }
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && obj != null && typeof obj === "object" ) {
+ // Serialize object item.
+ for ( var name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {}
+
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields,
+ ct,
+ type,
+ finalDataType,
+ firstDataType;
+
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ var dataTypes = s.dataTypes,
+ converters = {},
+ i,
+ key,
+ length = dataTypes.length,
+ tmp,
+ // Current and previous dataTypes
+ current = dataTypes[ 0 ],
+ prev,
+ // Conversion expression
+ conversion,
+ // Conversion function
+ conv,
+ // Conversion functions (transitive conversion)
+ conv1,
+ conv2;
+
+ // For each dataType in the chain
+ for ( i = 1; i < length; i++ ) {
+
+ // Create converters map
+ // with lowercased keys
+ if ( i === 1 ) {
+ for ( key in s.converters ) {
+ if ( typeof key === "string" ) {
+ converters[ key.toLowerCase() ] = s.converters[ key ];
+ }
+ }
+ }
+
+ // Get the dataTypes
+ prev = current;
+ current = dataTypes[ i ];
+
+ // If current is auto dataType, update it to prev
+ if ( current === "*" ) {
+ current = prev;
+ // If no auto and dataTypes are actually different
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Get the converter
+ conversion = prev + " " + current;
+ conv = converters[ conversion ] || converters[ "* " + current ];
+
+ // If there is no direct converter, search transitively
+ if ( !conv ) {
+ conv2 = undefined;
+ for ( conv1 in converters ) {
+ tmp = conv1.split( " " );
+ if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
+ conv2 = converters[ tmp[1] + " " + current ];
+ if ( conv2 ) {
+ conv1 = converters[ conv1 ];
+ if ( conv1 === true ) {
+ conv = conv2;
+ } else if ( conv2 === true ) {
+ conv = conv1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ // If we found no converter, dispatch an error
+ if ( !( conv || conv2 ) ) {
+ jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+ }
+ // If found converter is not an equivalence
+ if ( conv !== true ) {
+ // Convert with 1 or 2 converters accordingly
+ response = conv ? conv( response ) : conv2( conv1(response) );
+ }
+ }
+ }
+ return response;
+}
+
+
+
+
+var jsc = jQuery.now(),
+ jsre = /(\=)\?(&|$)|\?\?/i;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ return jQuery.expando + "_" + ( jsc++ );
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
+ ( typeof s.data === "string" );
+
+ if ( s.dataTypes[ 0 ] === "jsonp" ||
+ s.jsonp !== false && ( jsre.test( s.url ) ||
+ inspectData && jsre.test( s.data ) ) ) {
+
+ var responseContainer,
+ jsonpCallback = s.jsonpCallback =
+ jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
+ previous = window[ jsonpCallback ],
+ url = s.url,
+ data = s.data,
+ replace = "$1" + jsonpCallback + "$2";
+
+ if ( s.jsonp !== false ) {
+ url = url.replace( jsre, replace );
+ if ( s.url === url ) {
+ if ( inspectData ) {
+ data = data.replace( jsre, replace );
+ }
+ if ( s.data === data ) {
+ // Add callback manually
+ url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
+ }
+ }
+ }
+
+ s.url = url;
+ s.data = data;
+
+ // Install callback
+ window[ jsonpCallback ] = function( response ) {
+ responseContainer = [ response ];
+ };
+
+ // Clean-up function
+ jqXHR.always(function() {
+ // Set callback back to previous value
+ window[ jsonpCallback ] = previous;
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( previous ) ) {
+ window[ jsonpCallback ]( responseContainer[ 0 ] );
+ }
+ });
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( jsonpCallback + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Delegate to script
+ return "script";
+ }
+});
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /javascript|ecmascript/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement( "script" );
+
+ script.async = "async";
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( head && script.parentNode ) {
+ head.removeChild( script );
+ }
+
+ // Dereference the script
+ script = undefined;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709 and #4378).
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( 0, 1 );
+ }
+ }
+ };
+ }
+});
+
+
+
+
+var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject ? function() {
+ // Abort all pending requests
+ for ( var key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( 0, 1 );
+ }
+ } : false,
+ xhrId = 0,
+ xhrCallbacks;
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+ } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+(function( xhr ) {
+ jQuery.extend( jQuery.support, {
+ ajax: !!xhr,
+ cors: !!xhr && ( "withCredentials" in xhr )
+ });
+})( jQuery.ajaxSettings.xhr() );
+
+// Create transport if the browser can provide an xhr
+if ( jQuery.support.ajax ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var xhr = s.xhr(),
+ handle,
+ i;
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( _ ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+
+ var status,
+ statusText,
+ responseHeaders,
+ responses,
+ xml;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occured
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+ responses = {};
+ xml = xhr.responseXML;
+
+ // Construct response list
+ if ( xml && xml.documentElement /* #4958 */ ) {
+ responses.xml = xml;
+ }
+ responses.text = xhr.responseText;
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ // if we're in sync mode or it's in cache
+ // and has been retrieved directly (IE6 & IE7)
+ // we need to manually fire the callback
+ if ( !s.async || xhr.readyState === 4 ) {
+ callback();
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback(0,1);
+ }
+ }
+ };
+ }
+ });
+}
+
+
+
+
+var elemdisplay = {},
+ iframe, iframeDoc,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ],
+ fxNow;
+
+jQuery.fn.extend({
+ show: function( speed, easing, callback ) {
+ var elem, display;
+
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("show", 3), speed, easing, callback );
+
+ } else {
+ for ( var i = 0, j = this.length; i < j; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.style ) {
+ display = elem.style.display;
+
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
+ display = elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( display === "" && jQuery.css(elem, "display") === "none" ) {
+ jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.style ) {
+ display = elem.style.display;
+
+ if ( display === "" || display === "none" ) {
+ elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
+ }
+ }
+ }
+
+ return this;
+ }
+ },
+
+ hide: function( speed, easing, callback ) {
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("hide", 3), speed, easing, callback);
+
+ } else {
+ var elem, display,
+ i = 0,
+ j = this.length;
+
+ for ( ; i < j; i++ ) {
+ elem = this[i];
+ if ( elem.style ) {
+ display = jQuery.css( elem, "display" );
+
+ if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
+ jQuery._data( elem, "olddisplay", display );
+ }
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ if ( this[i].style ) {
+ this[i].style.display = "none";
+ }
+ }
+
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2, callback ) {
+ var bool = typeof fn === "boolean";
+
+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+ this._toggle.apply( this, arguments );
+
+ } else if ( fn == null || bool ) {
+ this.each(function() {
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ });
+
+ } else {
+ this.animate(genFx("toggle", 3), fn, fn2, callback);
+ }
+
+ return this;
+ },
+
+ fadeTo: function( speed, to, easing, callback ) {
+ return this.filter(":hidden").css("opacity", 0).show().end()
+ .animate({opacity: to}, speed, easing, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed( speed, easing, callback );
+
+ if ( jQuery.isEmptyObject( prop ) ) {
+ return this.each( optall.complete, [ false ] );
+ }
+
+ // Do not change referenced properties as per-property easing will be lost
+ prop = jQuery.extend( {}, prop );
+
+ function doAnimation() {
+ // XXX 'this' does not always have a nodeName when running the
+ // test suite
+
+ if ( optall.queue === false ) {
+ jQuery._mark( this );
+ }
+
+ var opt = jQuery.extend( {}, optall ),
+ isElement = this.nodeType === 1,
+ hidden = isElement && jQuery(this).is(":hidden"),
+ name, val, p, e,
+ parts, start, end, unit,
+ method;
+
+ // will store per property easing and be used to determine when an animation is complete
+ opt.animatedProperties = {};
+
+ for ( p in prop ) {
+
+ // property name normalization
+ name = jQuery.camelCase( p );
+ if ( p !== name ) {
+ prop[ name ] = prop[ p ];
+ delete prop[ p ];
+ }
+
+ val = prop[ name ];
+
+ // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
+ if ( jQuery.isArray( val ) ) {
+ opt.animatedProperties[ name ] = val[ 1 ];
+ val = prop[ name ] = val[ 0 ];
+ } else {
+ opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
+ }
+
+ if ( val === "hide" && hidden || val === "show" && !hidden ) {
+ return opt.complete.call( this );
+ }
+
+ if ( isElement && ( name === "height" || name === "width" ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( this, "display" ) === "inline" &&
+ jQuery.css( this, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
+ this.style.display = "inline-block";
+
+ } else {
+ this.style.zoom = 1;
+ }
+ }
+ }
+ }
+
+ if ( opt.overflow != null ) {
+ this.style.overflow = "hidden";
+ }
+
+ for ( p in prop ) {
+ e = new jQuery.fx( this, opt, p );
+ val = prop[ p ];
+
+ if ( rfxtypes.test( val ) ) {
+
+ // Tracks whether to show or hide based on private
+ // data attached to the element
+ method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
+ if ( method ) {
+ jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
+ e[ method ]();
+ } else {
+ e[ val ]();
+ }
+
+ } else {
+ parts = rfxnum.exec( val );
+ start = e.cur();
+
+ if ( parts ) {
+ end = parseFloat( parts[2] );
+ unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" ) {
+ jQuery.style( this, p, (end || 1) + unit);
+ start = ( (end || 1) / e.cur() ) * start;
+ jQuery.style( this, p, start + unit);
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] ) {
+ end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
+ }
+
+ e.custom( start, end, unit );
+
+ } else {
+ e.custom( start, val, "" );
+ }
+ }
+ }
+
+ // For JS strict compliance
+ return true;
+ }
+
+ return optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+
+ stop: function( type, clearQueue, gotoEnd ) {
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var index,
+ hadTimers = false,
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ // clear marker counters if we know they won't be
+ if ( !gotoEnd ) {
+ jQuery._unmark( true, this );
+ }
+
+ function stopQueue( elem, data, index ) {
+ var hooks = data[ index ];
+ jQuery.removeData( elem, index, true );
+ hooks.stop( gotoEnd );
+ }
+
+ if ( type == null ) {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
+ stopQueue( this, data, index );
+ }
+ }
+ } else if ( data[ index = type + ".run" ] && data[ index ].stop ){
+ stopQueue( this, data, index );
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ if ( gotoEnd ) {
+
+ // force the next step to be the last
+ timers[ index ]( true );
+ } else {
+ timers[ index ].saveState();
+ }
+ hadTimers = true;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( !( gotoEnd && hadTimers ) ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ }
+
+});
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout( clearFxNow, 0 );
+ return ( fxNow = jQuery.now() );
+}
+
+function clearFxNow() {
+ fxNow = undefined;
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, num ) {
+ var obj = {};
+
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
+ obj[ this ] = type;
+ });
+
+ return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx( "show", 1 ),
+ slideUp: genFx( "hide", 1 ),
+ slideToggle: genFx( "toggle", 1 ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.extend({
+ speed: function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function( noUnmark ) {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ } else if ( noUnmark !== false ) {
+ jQuery._unmark( this );
+ }
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ) {
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ options.orig = options.orig || {};
+ }
+
+});
+
+jQuery.fx.prototype = {
+ // Simple function for setting a style value
+ update: function() {
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
+ },
+
+ // Get the current size
+ cur: function() {
+ if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
+ return this.elem[ this.prop ];
+ }
+
+ var parsed,
+ r = jQuery.css( this.elem, this.prop );
+ // Empty strings, null, undefined and "auto" are converted to 0,
+ // complex values such as "rotate(1rad)" are returned as is,
+ // simple values such as "10px" are parsed to Float.
+ return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
+ },
+
+ // Start an animation from one number to another
+ custom: function( from, to, unit ) {
+ var self = this,
+ fx = jQuery.fx;
+
+ this.startTime = fxNow || createFxNow();
+ this.end = to;
+ this.now = this.start = from;
+ this.pos = this.state = 0;
+ this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
+
+ function t( gotoEnd ) {
+ return self.step( gotoEnd );
+ }
+
+ t.queue = this.options.queue;
+ t.elem = this.elem;
+ t.saveState = function() {
+ if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
+ jQuery._data( self.elem, "fxshow" + self.prop, self.start );
+ }
+ };
+
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval( fx.tick, fx.interval );
+ }
+ },
+
+ // Simple 'show' function
+ show: function() {
+ var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
+
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any flash of content
+ if ( dataShow !== undefined ) {
+ // This show is picking up where a previous hide or show left off
+ this.custom( this.cur(), dataShow );
+ } else {
+ this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
+ }
+
+ // Start by showing the element
+ jQuery( this.elem ).show();
+ },
+
+ // Simple 'hide' function
+ hide: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom( this.cur(), 0 );
+ },
+
+ // Each step of an animation
+ step: function( gotoEnd ) {
+ var p, n, complete,
+ t = fxNow || createFxNow(),
+ done = true,
+ elem = this.elem,
+ options = this.options;
+
+ if ( gotoEnd || t >= options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ options.animatedProperties[ this.prop ] = true;
+
+ for ( p in options.animatedProperties ) {
+ if ( options.animatedProperties[ p ] !== true ) {
+ done = false;
+ }
+ }
+
+ if ( done ) {
+ // Reset the overflow
+ if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+
+ jQuery.each( [ "", "X", "Y" ], function( index, value ) {
+ elem.style[ "overflow" + value ] = options.overflow[ index ];
+ });
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( options.hide ) {
+ jQuery( elem ).hide();
+ }
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( options.hide || options.show ) {
+ for ( p in options.animatedProperties ) {
+ jQuery.style( elem, p, options.orig[ p ] );
+ jQuery.removeData( elem, "fxshow" + p, true );
+ // Toggle data is no longer needed
+ jQuery.removeData( elem, "toggle" + p, true );
+ }
+ }
+
+ // Execute the complete function
+ // in the event that the complete function throws an exception
+ // we must ensure it won't be called twice. #5684
+
+ complete = options.complete;
+ if ( complete ) {
+
+ options.complete = false;
+ complete.call( elem );
+ }
+ }
+
+ return false;
+
+ } else {
+ // classical easing cannot be used with an Infinity duration
+ if ( options.duration == Infinity ) {
+ this.now = t;
+ } else {
+ n = t - this.startTime;
+ this.state = n / options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
+ this.now = this.start + ( (this.end - this.start) * this.pos );
+ }
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+};
+
+jQuery.extend( jQuery.fx, {
+ tick: function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ },
+
+ interval: 13,
+
+ stop: function() {
+ clearInterval( timerId );
+ timerId = null;
+ },
+
+ speeds: {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+
+ step: {
+ opacity: function( fx ) {
+ jQuery.style( fx.elem, "opacity", fx.now );
+ },
+
+ _default: function( fx ) {
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ } else {
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+ }
+});
+
+// Adds width/height step functions
+// Do not set anything below 0
+jQuery.each([ "width", "height" ], function( i, prop ) {
+ jQuery.fx.step[ prop ] = function( fx ) {
+ jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
+ };
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+
+// Try to restore the default display value of an element
+function defaultDisplay( nodeName ) {
+
+ if ( !elemdisplay[ nodeName ] ) {
+
+ var body = document.body,
+ elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
+ display = elem.css( "display" );
+ elem.remove();
+
+ // If the simple way fails,
+ // get element's real default display by attaching it to a temp iframe
+ if ( display === "none" || display === "" ) {
+ // No iframe to use yet, so create it
+ if ( !iframe ) {
+ iframe = document.createElement( "iframe" );
+ iframe.frameBorder = iframe.width = iframe.height = 0;
+ }
+
+ body.appendChild( iframe );
+
+ // Create a cacheable copy of the iframe document on first call.
+ // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+ // document to it; WebKit & Firefox won't allow reusing the iframe document.
+ if ( !iframeDoc || !iframe.createElement ) {
+ iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+ iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
+ iframeDoc.close();
+ }
+
+ elem = iframeDoc.createElement( nodeName );
+
+ iframeDoc.body.appendChild( elem );
+
+ display = jQuery.css( elem, "display" );
+ body.removeChild( iframe );
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+ rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0], box;
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ try {
+ box = elem.getBoundingClientRect();
+ } catch(e) {}
+
+ var doc = elem.ownerDocument,
+ docElem = doc.documentElement;
+
+ // Make sure we're not dealing with a disconnected DOM node
+ if ( !box || !jQuery.contains( docElem, elem ) ) {
+ return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
+ }
+
+ var body = doc.body,
+ win = getWindow(doc),
+ clientTop = docElem.clientTop || body.clientTop || 0,
+ clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
+ scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
+ top = box.top + scrollTop - clientTop,
+ left = box.left + scrollLeft - clientLeft;
+
+ return { top: top, left: left };
+ };
+
+} else {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0];
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ var computedStyle,
+ offsetParent = elem.offsetParent,
+ prevOffsetParent = elem,
+ doc = elem.ownerDocument,
+ docElem = doc.documentElement,
+ body = doc.body,
+ defaultView = doc.defaultView,
+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+ top = elem.offsetTop,
+ left = elem.offsetLeft;
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ break;
+ }
+
+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+ top -= elem.scrollTop;
+ left -= elem.scrollLeft;
+
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop;
+ left += elem.offsetLeft;
+
+ if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevOffsetParent = offsetParent;
+ offsetParent = elem.offsetParent;
+ }
+
+ if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+ top += body.offsetTop;
+ left += body.offsetLeft;
+ }
+
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ top += Math.max( docElem.scrollTop, body.scrollTop );
+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
+ }
+
+ return { top: top, left: left };
+ };
+}
+
+jQuery.offset = {
+
+ bodyOffset: function( body ) {
+ var top = body.offsetTop,
+ left = body.offsetLeft;
+
+ if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
+ top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+ left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+ }
+
+ return { top: top, left: left };
+ },
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[0] ) {
+ return null;
+ }
+
+ var elem = this[0],
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+ offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+ parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.body;
+ while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+ var method = "scroll" + name;
+
+ jQuery.fn[ method ] = function( val ) {
+ var elem, win;
+
+ if ( val === undefined ) {
+ elem = this[ 0 ];
+
+ if ( !elem ) {
+ return null;
+ }
+
+ win = getWindow( elem );
+
+ // Return the scroll offset
+ return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
+ win.document.body[ method ] :
+ elem[ method ];
+ }
+
+ // Set the scroll offset
+ return this.each(function() {
+ win = getWindow( this );
+
+ if ( win ) {
+ win.scrollTo(
+ !i ? val : jQuery( win ).scrollLeft(),
+ i ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ this[ method ] = val;
+ }
+ });
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+
+
+
+// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+ var type = name.toLowerCase();
+
+ // innerHeight and innerWidth
+ jQuery.fn[ "inner" + name ] = function() {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, "padding" ) ) :
+ this[ type ]() :
+ null;
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn[ "outer" + name ] = function( margin ) {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
+ this[ type ]() :
+ null;
+ };
+
+ jQuery.fn[ type ] = function( size ) {
+ // Get window width or height
+ var elem = this[0];
+ if ( !elem ) {
+ return size == null ? null : this;
+ }
+
+ if ( jQuery.isFunction( size ) ) {
+ return this.each(function( i ) {
+ var self = jQuery( this );
+ self[ type ]( size.call( this, i, self[ type ]() ) );
+ });
+ }
+
+ if ( jQuery.isWindow( elem ) ) {
+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+ // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
+ var docElemProp = elem.document.documentElement[ "client" + name ],
+ body = elem.document.body;
+ return elem.document.compatMode === "CSS1Compat" && docElemProp ||
+ body && body[ "client" + name ] || docElemProp;
+
+ // Get document width or height
+ } else if ( elem.nodeType === 9 ) {
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ return Math.max(
+ elem.documentElement["client" + name],
+ elem.body["scroll" + name], elem.documentElement["scroll" + name],
+ elem.body["offset" + name], elem.documentElement["offset" + name]
+ );
+
+ // Get or set width or height on the element
+ } else if ( size === undefined ) {
+ var orig = jQuery.css( elem, type ),
+ ret = parseFloat( orig );
+
+ return jQuery.isNumeric( ret ) ? ret : orig;
+
+ // Set the width or height on the element (default to pixels if value is unitless)
+ } else {
+ return this.css( type, typeof size === "string" ? size : size + "px" );
+ }
+ };
+
+});
+
+
+
+
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+}
+
+
+
+})( window );
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin.c b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin.c
new file mode 100644
index 00000000000..03158289674
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin.c
@@ -0,0 +1,291 @@
+/* jsmin.c
+ 2011-01-22
+
+Copyright (c) 2002 Douglas Crockford (www.crockford.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+static int theA;
+static int theB;
+static int theLookahead = EOF;
+
+
+/* isAlphanum -- return true if the character is a letter, digit, underscore,
+ dollar sign, or non-ASCII character.
+*/
+
+static int
+isAlphanum(int c)
+{
+ return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z') || c == '_' || c == '$' || c == '\\' ||
+ c > 126);
+}
+
+
+/* get -- return the next character from stdin. Watch out for lookahead. If
+ the character is a control character, translate it to a space or
+ linefeed.
+*/
+
+static int
+get()
+{
+ int c = theLookahead;
+ theLookahead = EOF;
+ if (c == EOF) {
+ c = getc(stdin);
+ }
+ if (c >= ' ' || c == '\n' || c == EOF) {
+ return c;
+ }
+ if (c == '\r') {
+ return '\n';
+ }
+ return ' ';
+}
+
+
+/* peek -- get the next character without getting it.
+*/
+
+static int
+peek()
+{
+ theLookahead = get();
+ return theLookahead;
+}
+
+
+/* next -- get the next character, excluding comments. peek() is used to see
+ if a '/' is followed by a '/' or '*'.
+*/
+
+static int
+next()
+{
+ int c = get();
+ if (c == '/') {
+ switch (peek()) {
+ case '/':
+ for (;;) {
+ c = get();
+ if (c <= '\n') {
+ return c;
+ }
+ }
+ case '*':
+ get();
+ for (;;) {
+ switch (get()) {
+ case '*':
+ if (peek() == '/') {
+ get();
+ return ' ';
+ }
+ break;
+ case EOF:
+ fprintf(stderr, "Error: JSMIN Unterminated comment.\n");
+ exit(1);
+ }
+ }
+ default:
+ return c;
+ }
+ }
+ return c;
+}
+
+
+/* action -- do something! What you do is determined by the argument:
+ 1 Output A. Copy B to A. Get the next B.
+ 2 Copy B to A. Get the next B. (Delete A).
+ 3 Get the next B. (Delete B).
+ action treats a string as a single character. Wow!
+ action recognizes a regular expression if it is preceded by ( or , or =.
+*/
+
+static void
+action(int d)
+{
+ switch (d) {
+ case 1:
+ putc(theA, stdout);
+ case 2:
+ theA = theB;
+ if (theA == '\'' || theA == '"') {
+ for (;;) {
+ putc(theA, stdout);
+ theA = get();
+ if (theA == theB) {
+ break;
+ }
+ if (theA == '\\') {
+ putc(theA, stdout);
+ theA = get();
+ }
+ if (theA == EOF) {
+ fprintf(stderr, "Error: JSMIN unterminated string literal.");
+ exit(1);
+ }
+ }
+ }
+ case 3:
+ theB = next();
+ if (theB == '/' && (theA == '(' || theA == ',' || theA == '=' ||
+ theA == ':' || theA == '[' || theA == '!' ||
+ theA == '&' || theA == '|' || theA == '?' ||
+ theA == '{' || theA == '}' || theA == ';' ||
+ theA == '\n')) {
+ putc(theA, stdout);
+ putc(theB, stdout);
+ for (;;) {
+ theA = get();
+ if (theA == '[') {
+ for (;;) {
+ putc(theA, stdout);
+ theA = get();
+ if (theA == ']') {
+ break;
+ }
+ if (theA == '\\') {
+ putc(theA, stdout);
+ theA = get();
+ }
+ if (theA == EOF) {
+ fprintf(stderr,
+ "Error: JSMIN unterminated set in Regular Expression literal.\n");
+ exit(1);
+ }
+ }
+ } else if (theA == '/') {
+ break;
+ } else if (theA =='\\') {
+ putc(theA, stdout);
+ theA = get();
+ }
+ if (theA == EOF) {
+ fprintf(stderr,
+ "Error: JSMIN unterminated Regular Expression literal.\n");
+ exit(1);
+ }
+ putc(theA, stdout);
+ }
+ theB = next();
+ }
+ }
+}
+
+
+/* jsmin -- Copy the input to the output, deleting the characters which are
+ insignificant to JavaScript. Comments will be removed. Tabs will be
+ replaced with spaces. Carriage returns will be replaced with linefeeds.
+ Most spaces and linefeeds will be removed.
+*/
+
+static void
+jsmin()
+{
+ theA = '\n';
+ action(3);
+ while (theA != EOF) {
+ switch (theA) {
+ case ' ':
+ if (isAlphanum(theB)) {
+ action(1);
+ } else {
+ action(2);
+ }
+ break;
+ case '\n':
+ switch (theB) {
+ case '{':
+ case '[':
+ case '(':
+ case '+':
+ case '-':
+ action(1);
+ break;
+ case ' ':
+ action(3);
+ break;
+ default:
+ if (isAlphanum(theB)) {
+ action(1);
+ } else {
+ action(2);
+ }
+ }
+ break;
+ default:
+ switch (theB) {
+ case ' ':
+ if (isAlphanum(theA)) {
+ action(1);
+ break;
+ }
+ action(3);
+ break;
+ case '\n':
+ switch (theA) {
+ case '}':
+ case ']':
+ case ')':
+ case '+':
+ case '-':
+ case '"':
+ case '\'':
+ action(1);
+ break;
+ default:
+ if (isAlphanum(theA)) {
+ action(1);
+ } else {
+ action(3);
+ }
+ }
+ break;
+ default:
+ action(1);
+ break;
+ }
+ }
+ }
+}
+
+
+/* main -- Output any command line arguments as comments
+ and then minify the input.
+*/
+extern int
+main(int argc, char* argv[])
+{
+ int i;
+ for (i = 1; i < argc; i += 1) {
+ fprintf(stdout, "// %s\n", argv[i]);
+ }
+ jsmin();
+ return 0;
+}
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin.py
new file mode 100644
index 00000000000..b1f7dd7e62e
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+
+# This code is original from jsmin by Douglas Crockford, it was translated to
+# Python by Baruch Even. The original code had the following copyright and
+# license.
+#
+# /* jsmin.c
+# 2007-05-22
+#
+# Copyright (c) 2002 Douglas Crockford (www.crockford.com)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# The Software shall be used for Good, not Evil.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# */
+
+# imports adjusted for speed (cStringIO) and python 3 (io) -- nd
+try:
+ from cStringIO import StringIO
+except ImportError:
+ try:
+ from StringIO import StringIO
+ except ImportError:
+ from io import StringIO
+
+
+def jsmin(js):
+ ins = StringIO(js)
+ outs = StringIO()
+ JavascriptMinify().minify(ins, outs)
+ str = outs.getvalue()
+ if len(str) > 0 and str[0] == '\n':
+ str = str[1:]
+ return str
+
+def isAlphanum(c):
+ """return true if the character is a letter, digit, underscore,
+ dollar sign, or non-ASCII character.
+ """
+ return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or
+ (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126));
+
+class UnterminatedComment(Exception):
+ pass
+
+class UnterminatedStringLiteral(Exception):
+ pass
+
+class UnterminatedRegularExpression(Exception):
+ pass
+
+class JavascriptMinify(object):
+
+ def _outA(self):
+ self.outstream.write(self.theA)
+ def _outB(self):
+ self.outstream.write(self.theB)
+
+ def _get(self):
+ """return the next character from stdin. Watch out for lookahead. If
+ the character is a control character, translate it to a space or
+ linefeed.
+ """
+ c = self.theLookahead
+ self.theLookahead = None
+ if c == None:
+ c = self.instream.read(1)
+ if c >= ' ' or c == '\n':
+ return c
+ if c == '': # EOF
+ return '\000'
+ if c == '\r':
+ return '\n'
+ return ' '
+
+ def _peek(self):
+ self.theLookahead = self._get()
+ return self.theLookahead
+
+ def _next(self):
+ """get the next character, excluding comments. peek() is used to see
+ if an unescaped '/' is followed by a '/' or '*'.
+ """
+ c = self._get()
+ if c == '/' and self.theA != '\\':
+ p = self._peek()
+ if p == '/':
+ c = self._get()
+ while c > '\n':
+ c = self._get()
+ return c
+ if p == '*':
+ c = self._get()
+ while 1:
+ c = self._get()
+ if c == '*':
+ if self._peek() == '/':
+ self._get()
+ return ' '
+ if c == '\000':
+ raise UnterminatedComment()
+
+ return c
+
+ def _action(self, action):
+ """do something! What you do is determined by the argument:
+ 1 Output A. Copy B to A. Get the next B.
+ 2 Copy B to A. Get the next B. (Delete A).
+ 3 Get the next B. (Delete B).
+ action treats a string as a single character. Wow!
+ action recognizes a regular expression if it is preceded by ( or , or =.
+ """
+ if action <= 1:
+ self._outA()
+
+ if action <= 2:
+ self.theA = self.theB
+ if self.theA == "'" or self.theA == '"':
+ while 1:
+ self._outA()
+ self.theA = self._get()
+ if self.theA == self.theB:
+ break
+ if self.theA <= '\n':
+ raise UnterminatedStringLiteral()
+ if self.theA == '\\':
+ self._outA()
+ self.theA = self._get()
+
+
+ if action <= 3:
+ self.theB = self._next()
+ if self.theB == '/' and (self.theA == '(' or self.theA == ',' or
+ self.theA == '=' or self.theA == ':' or
+ self.theA == '[' or self.theA == '?' or
+ self.theA == '!' or self.theA == '&' or
+ self.theA == '|' or self.theA == ';' or
+ self.theA == '{' or self.theA == '}' or
+ self.theA == '\n'):
+ self._outA()
+ self._outB()
+ while 1:
+ self.theA = self._get()
+ if self.theA == '/':
+ break
+ elif self.theA == '\\':
+ self._outA()
+ self.theA = self._get()
+ elif self.theA <= '\n':
+ raise UnterminatedRegularExpression()
+ self._outA()
+ self.theB = self._next()
+
+
+ def _jsmin(self):
+ """Copy the input to the output, deleting the characters which are
+ insignificant to JavaScript. Comments will be removed. Tabs will be
+ replaced with spaces. Carriage returns will be replaced with linefeeds.
+ Most spaces and linefeeds will be removed.
+ """
+ self.theA = '\n'
+ self._action(3)
+
+ while self.theA != '\000':
+ if self.theA == ' ':
+ if isAlphanum(self.theB):
+ self._action(1)
+ else:
+ self._action(2)
+ elif self.theA == '\n':
+ if self.theB in ['{', '[', '(', '+', '-']:
+ self._action(1)
+ elif self.theB == ' ':
+ self._action(3)
+ else:
+ if isAlphanum(self.theB):
+ self._action(1)
+ else:
+ self._action(2)
+ else:
+ if self.theB == ' ':
+ if isAlphanum(self.theA):
+ self._action(1)
+ else:
+ self._action(3)
+ elif self.theB == '\n':
+ if self.theA in ['}', ']', ')', '+', '-', '"', '\'']:
+ self._action(1)
+ else:
+ if isAlphanum(self.theA):
+ self._action(1)
+ else:
+ self._action(3)
+ else:
+ self._action(1)
+
+ def minify(self, instream, outstream):
+ self.instream = instream
+ self.outstream = outstream
+ self.theA = '\n'
+ self.theB = None
+ self.theLookahead = None
+
+ self._jsmin()
+ self.instream.close()
+
+if __name__ == '__main__':
+ import sys
+ jsm = JavascriptMinify()
+ jsm.minify(sys.stdin, sys.stdout)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin_2_0_9.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin_2_0_9.py
new file mode 100644
index 00000000000..23bed6082b8
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/jsmin_2_0_9.py
@@ -0,0 +1,233 @@
+# This code is original from jsmin by Douglas Crockford, it was translated to
+# Python by Baruch Even. It was rewritten by Dave St.Germain for speed.
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2013 Dave St.Germain
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+import sys
+is_3 = sys.version_info >= (3, 0)
+if is_3:
+ import io
+else:
+ import StringIO
+ try:
+ import cStringIO
+ except ImportError:
+ cStringIO = None
+
+
+__all__ = ['jsmin', 'JavascriptMinify']
+__version__ = '2.0.9'
+
+
+def jsmin(js):
+ """
+ returns a minified version of the javascript string
+ """
+ if not is_3:
+ if cStringIO and not isinstance(js, unicode):
+ # strings can use cStringIO for a 3x performance
+ # improvement, but unicode (in python2) cannot
+ klass = cStringIO.StringIO
+ else:
+ klass = StringIO.StringIO
+ else:
+ klass = io.StringIO
+ ins = klass(js)
+ outs = klass()
+ JavascriptMinify(ins, outs).minify()
+ return outs.getvalue()
+
+
+class JavascriptMinify(object):
+ """
+ Minify an input stream of javascript, writing
+ to an output stream
+ """
+
+ def __init__(self, instream=None, outstream=None):
+ self.ins = instream
+ self.outs = outstream
+
+ def minify(self, instream=None, outstream=None):
+ if instream and outstream:
+ self.ins, self.outs = instream, outstream
+
+ self.is_return = False
+ self.return_buf = ''
+
+ def write(char):
+ # all of this is to support literal regular expressions.
+ # sigh
+ if char in 'return':
+ self.return_buf += char
+ self.is_return = self.return_buf == 'return'
+ self.outs.write(char)
+ if self.is_return:
+ self.return_buf = ''
+
+ read = self.ins.read
+
+ space_strings = "abcdefghijklmnopqrstuvwxyz"\
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$\\"
+ starters, enders = '{[(+-', '}])+-"\''
+ newlinestart_strings = starters + space_strings
+ newlineend_strings = enders + space_strings
+ do_newline = False
+ do_space = False
+ escape_slash_count = 0
+ doing_single_comment = False
+ previous_before_comment = ''
+ doing_multi_comment = False
+ in_re = False
+ in_quote = ''
+ quote_buf = []
+
+ previous = read(1)
+ if previous == '\\':
+ escape_slash_count += 1
+ next1 = read(1)
+ if previous == '/':
+ if next1 == '/':
+ doing_single_comment = True
+ elif next1 == '*':
+ doing_multi_comment = True
+ previous = next1
+ next1 = read(1)
+ else:
+ write(previous)
+ elif not previous:
+ return
+ elif previous >= '!':
+ if previous in "'\"":
+ in_quote = previous
+ write(previous)
+ previous_non_space = previous
+ else:
+ previous_non_space = ' '
+ if not next1:
+ return
+
+ while 1:
+ next2 = read(1)
+ if not next2:
+ last = next1.strip()
+ if not (doing_single_comment or doing_multi_comment)\
+ and last not in ('', '/'):
+ if in_quote:
+ write(''.join(quote_buf))
+ write(last)
+ break
+ if doing_multi_comment:
+ if next1 == '*' and next2 == '/':
+ doing_multi_comment = False
+ next2 = read(1)
+ elif doing_single_comment:
+ if next1 in '\r\n':
+ doing_single_comment = False
+ while next2 in '\r\n':
+ next2 = read(1)
+ if not next2:
+ break
+ if previous_before_comment in ')}]':
+ do_newline = True
+ elif previous_before_comment in space_strings:
+ write('\n')
+ elif in_quote:
+ quote_buf.append(next1)
+
+ if next1 == in_quote:
+ numslashes = 0
+ for c in reversed(quote_buf[:-1]):
+ if c != '\\':
+ break
+ else:
+ numslashes += 1
+ if numslashes % 2 == 0:
+ in_quote = ''
+ write(''.join(quote_buf))
+ elif next1 in '\r\n':
+ if previous_non_space in newlineend_strings \
+ or previous_non_space > '~':
+ while 1:
+ if next2 < '!':
+ next2 = read(1)
+ if not next2:
+ break
+ else:
+ if next2 in newlinestart_strings \
+ or next2 > '~' or next2 == '/':
+ do_newline = True
+ break
+ elif next1 < '!' and not in_re:
+ if (previous_non_space in space_strings \
+ or previous_non_space > '~') \
+ and (next2 in space_strings or next2 > '~'):
+ do_space = True
+ elif previous_non_space in '-+' and next2 == previous_non_space:
+ # protect against + ++ or - -- sequences
+ do_space = True
+ elif self.is_return and next2 == '/':
+ # returning a regex...
+ write(' ')
+ elif next1 == '/':
+ if do_space:
+ write(' ')
+ if in_re:
+ if previous != '\\' or (not escape_slash_count % 2) or next2 in 'gimy':
+ in_re = False
+ write('/')
+ elif next2 == '/':
+ doing_single_comment = True
+ previous_before_comment = previous_non_space
+ elif next2 == '*':
+ doing_multi_comment = True
+ previous = next1
+ next1 = next2
+ next2 = read(1)
+ else:
+ in_re = previous_non_space in '(,=:[?!&|' or self.is_return # literal regular expression
+ write('/')
+ else:
+ if do_space:
+ do_space = False
+ write(' ')
+ if do_newline:
+ write('\n')
+ do_newline = False
+
+ write(next1)
+ if not in_re and next1 in "'\"":
+ in_quote = next1
+ quote_buf = []
+
+ previous = next1
+ next1 = next2
+
+ if previous >= '!':
+ previous_non_space = previous
+
+ if previous == '\\':
+ escape_slash_count += 1
+ else:
+ escape_slash_count = 0
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/knockout-2.0.0.js b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/knockout-2.0.0.js
new file mode 100644
index 00000000000..e5577ebdf0d
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/knockout-2.0.0.js
@@ -0,0 +1,97 @@
+// Knockout JavaScript library v2.0.0
+// (c) Steven Sanderson - http://knockoutjs.com/
+// License: MIT (http://www.opensource.org/licenses/mit-license.php)
+
+(function(window,undefined){
+function c(a){throw a;}var l=void 0,m=!0,o=null,p=!1,r=window.ko={};r.b=function(a,b){for(var d=a.split("."),e=window,f=0;f<d.length-1;f++)e=e[d[f]];e[d[d.length-1]]=b};r.l=function(a,b,d){a[b]=d};
+r.a=new function(){function a(a,e){if("INPUT"!=a.tagName||!a.type)return p;if("click"!=e.toLowerCase())return p;var b=a.type.toLowerCase();return"checkbox"==b||"radio"==b}var b=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,d={},e={};d[/Firefox\/2/i.test(navigator.userAgent)?"KeyboardEvent":"UIEvents"]=["keyup","keydown","keypress"];d.MouseEvents="click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave".split(",");for(var f in d){var h=d[f];if(h.length)for(var g=0,i=h.length;g<i;g++)e[h[g]]=
+f}var j=function(){for(var a=3,e=document.createElement("div"),b=e.getElementsByTagName("i");e.innerHTML="<\!--[if gt IE "+ ++a+"]><i></i><![endif]--\>",b[0];);return 4<a?a:l}();return{Ba:["authenticity_token",/^__RequestVerificationToken(_.*)?$/],n:function(a,e){for(var b=0,f=a.length;b<f;b++)e(a[b])},k:function(a,e){if("function"==typeof Array.prototype.indexOf)return Array.prototype.indexOf.call(a,e);for(var b=0,f=a.length;b<f;b++)if(a[b]===e)return b;return-1},Wa:function(a,e,b){for(var f=0,d=
+a.length;f<d;f++)if(e.call(b,a[f]))return a[f];return o},ca:function(a,e){var b=r.a.k(a,e);0<=b&&a.splice(b,1)},ya:function(a){for(var a=a||[],e=[],b=0,f=a.length;b<f;b++)0>r.a.k(e,a[b])&&e.push(a[b]);return e},ba:function(a,e){for(var a=a||[],b=[],f=0,d=a.length;f<d;f++)b.push(e(a[f]));return b},aa:function(a,e){for(var a=a||[],b=[],f=0,d=a.length;f<d;f++)e(a[f])&&b.push(a[f]);return b},J:function(a,e){for(var b=0,f=e.length;b<f;b++)a.push(e[b]);return a},extend:function(a,e){for(var b in e)e.hasOwnProperty(b)&&
+(a[b]=e[b]);return a},U:function(a){for(;a.firstChild;)r.removeNode(a.firstChild)},oa:function(a,e){r.a.U(a);e&&r.a.n(e,function(e){a.appendChild(e)})},Ja:function(a,e){var b=a.nodeType?[a]:a;if(0<b.length){for(var f=b[0],d=f.parentNode,h=0,g=e.length;h<g;h++)d.insertBefore(e[h],f);h=0;for(g=b.length;h<g;h++)r.removeNode(b[h])}},La:function(a,e){0<=navigator.userAgent.indexOf("MSIE 6")?a.setAttribute("selected",e):a.selected=e},z:function(a){return(a||"").replace(b,"")},Db:function(a,e){for(var b=
+[],f=(a||"").split(e),d=0,h=f.length;d<h;d++){var g=r.a.z(f[d]);""!==g&&b.push(g)}return b},Cb:function(a,e){a=a||"";return e.length>a.length?p:a.substring(0,e.length)===e},hb:function(a){for(var e=Array.prototype.slice.call(arguments,1),b="return ("+a+")",f=0;f<e.length;f++)e[f]&&"object"==typeof e[f]&&(b="with(sc["+f+"]) { "+b+" } ");return(new Function("sc",b))(e)},fb:function(a,e){if(e.compareDocumentPosition)return 16==(e.compareDocumentPosition(a)&16);for(;a!=o;){if(a==e)return m;a=a.parentNode}return p},
+ga:function(a){return r.a.fb(a,document)},s:function(e,b,f){if("undefined"!=typeof jQuery){if(a(e,b))var d=f,f=function(a,e){var b=this.checked;if(e)this.checked=e.Ya!==m;d.call(this,a);this.checked=b};jQuery(e).bind(b,f)}else"function"==typeof e.addEventListener?e.addEventListener(b,f,p):"undefined"!=typeof e.attachEvent?e.attachEvent("on"+b,function(a){f.call(e,a)}):c(Error("Browser doesn't support addEventListener or attachEvent"))},sa:function(b,f){(!b||!b.nodeType)&&c(Error("element must be a DOM node when calling triggerEvent"));
+if("undefined"!=typeof jQuery){var d=[];a(b,f)&&d.push({Ya:b.checked});jQuery(b).trigger(f,d)}else if("function"==typeof document.createEvent)"function"==typeof b.dispatchEvent?(d=document.createEvent(e[f]||"HTMLEvents"),d.initEvent(f,m,m,window,0,0,0,0,0,p,p,p,p,0,b),b.dispatchEvent(d)):c(Error("The supplied element doesn't support dispatchEvent"));else if("undefined"!=typeof b.fireEvent){if("click"==f&&"INPUT"==b.tagName&&("checkbox"==b.type.toLowerCase()||"radio"==b.type.toLowerCase()))b.checked=
+b.checked!==m;b.fireEvent("on"+f)}else c(Error("Browser doesn't support triggering events"))},d:function(a){return r.V(a)?a():a},eb:function(a,e){return 0<=r.a.k((a.className||"").split(/\s+/),e)},Qa:function(a,e,b){var f=r.a.eb(a,e);if(b&&!f)a.className=(a.className||"")+" "+e;else if(f&&!b){for(var b=(a.className||"").split(/\s+/),f="",d=0;d<b.length;d++)b[d]!=e&&(f+=b[d]+" ");a.className=r.a.z(f)}},outerHTML:function(a){if(j===l){var e=a.outerHTML;if("string"==typeof e)return e}e=window.document.createElement("div");
+e.appendChild(a.cloneNode(m));return e.innerHTML},Ma:function(a,e){var b=r.a.d(e);if(b===o||b===l)b="";"innerText"in a?a.innerText=b:a.textContent=b;if(9<=j)a.innerHTML=a.innerHTML},yb:function(a,e){for(var a=r.a.d(a),e=r.a.d(e),b=[],f=a;f<=e;f++)b.push(f);return b},X:function(a){for(var e=[],b=0,f=a.length;b<f;b++)e.push(a[b]);return e},ob:6===j,pb:7===j,Ca:function(a,e){for(var b=r.a.X(a.getElementsByTagName("INPUT")).concat(r.a.X(a.getElementsByTagName("TEXTAREA"))),f="string"==typeof e?function(a){return a.name===
+e}:function(a){return e.test(a.name)},d=[],h=b.length-1;0<=h;h--)f(b[h])&&d.push(b[h]);return d},vb:function(a){return"string"==typeof a&&(a=r.a.z(a))?window.JSON&&window.JSON.parse?window.JSON.parse(a):(new Function("return "+a))():o},qa:function(a){("undefined"==typeof JSON||"undefined"==typeof JSON.stringify)&&c(Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js"));
+return JSON.stringify(r.a.d(a))},wb:function(a,e,b){var b=b||{},f=b.params||{},d=b.includeFields||this.Ba,h=a;if("object"==typeof a&&"FORM"==a.tagName)for(var h=a.action,g=d.length-1;0<=g;g--)for(var j=r.a.Ca(a,d[g]),i=j.length-1;0<=i;i--)f[j[i].name]=j[i].value;var e=r.a.d(e),u=document.createElement("FORM");u.style.display="none";u.action=h;u.method="post";for(var y in e)a=document.createElement("INPUT"),a.name=y,a.value=r.a.qa(r.a.d(e[y])),u.appendChild(a);for(y in f)a=document.createElement("INPUT"),
+a.name=y,a.value=f[y],u.appendChild(a);document.body.appendChild(u);b.submitter?b.submitter(u):u.submit();setTimeout(function(){u.parentNode.removeChild(u)},0)}}};r.b("ko.utils",r.a);
+r.a.n([["arrayForEach",r.a.n],["arrayFirst",r.a.Wa],["arrayFilter",r.a.aa],["arrayGetDistinctValues",r.a.ya],["arrayIndexOf",r.a.k],["arrayMap",r.a.ba],["arrayPushAll",r.a.J],["arrayRemoveItem",r.a.ca],["extend",r.a.extend],["fieldsIncludedWithJsonPost",r.a.Ba],["getFormFields",r.a.Ca],["postJson",r.a.wb],["parseJson",r.a.vb],["registerEventHandler",r.a.s],["stringifyJson",r.a.qa],["range",r.a.yb],["toggleDomNodeCssClass",r.a.Qa],["triggerEvent",r.a.sa],["unwrapObservable",r.a.d]],function(a){r.b("ko.utils."+
+a[0],a[1])});Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,d=Array.prototype.slice.call(arguments),a=d.shift();return function(){return b.apply(a,d.concat(Array.prototype.slice.call(arguments)))}});
+r.a.e=new function(){var a=0,b="__ko__"+(new Date).getTime(),d={};return{get:function(a,b){var d=r.a.e.getAll(a,p);return d===l?l:d[b]},set:function(a,b,d){d===l&&r.a.e.getAll(a,p)===l||(r.a.e.getAll(a,m)[b]=d)},getAll:function(e,f){var h=e[b];if(!(h&&"null"!==h)){if(!f)return;h=e[b]="ko"+a++;d[h]={}}return d[h]},clear:function(a){var f=a[b];f&&(delete d[f],a[b]=o)}}};r.b("ko.utils.domData",r.a.e);r.b("ko.utils.domData.clear",r.a.e.clear);
+r.a.A=new function(){function a(a,b){var h=r.a.e.get(a,d);h===l&&b&&(h=[],r.a.e.set(a,d,h));return h}function b(e){var b=a(e,p);if(b)for(var b=b.slice(0),d=0;d<b.length;d++)b[d](e);r.a.e.clear(e);"function"==typeof jQuery&&"function"==typeof jQuery.cleanData&&jQuery.cleanData([e])}var d="__ko_domNodeDisposal__"+(new Date).getTime();return{va:function(e,b){"function"!=typeof b&&c(Error("Callback must be a function"));a(e,m).push(b)},Ia:function(e,b){var h=a(e,p);h&&(r.a.ca(h,b),0==h.length&&r.a.e.set(e,
+d,l))},F:function(a){if(!(1!=a.nodeType&&9!=a.nodeType)){b(a);var f=[];r.a.J(f,a.getElementsByTagName("*"));for(var a=0,d=f.length;a<d;a++)b(f[a])}},removeNode:function(a){r.F(a);a.parentNode&&a.parentNode.removeChild(a)}}};r.F=r.a.A.F;r.removeNode=r.a.A.removeNode;r.b("ko.cleanNode",r.F);r.b("ko.removeNode",r.removeNode);r.b("ko.utils.domNodeDisposal",r.a.A);r.b("ko.utils.domNodeDisposal.addDisposeCallback",r.a.A.va);r.b("ko.utils.domNodeDisposal.removeDisposeCallback",r.a.A.Ia);
+r.a.ma=function(a){var b;if("undefined"!=typeof jQuery){if((b=jQuery.clean([a]))&&b[0]){for(a=b[0];a.parentNode&&11!==a.parentNode.nodeType;)a=a.parentNode;a.parentNode&&a.parentNode.removeChild(a)}}else{var d=r.a.z(a).toLowerCase();b=document.createElement("div");d=d.match(/^<(thead|tbody|tfoot)/)&&[1,"<table>","</table>"]||!d.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!d.indexOf("<td")||!d.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||[0,"",""];a="ignored<div>"+
+d[1]+a+d[2]+"</div>";for("function"==typeof window.innerShiv?b.appendChild(window.innerShiv(a)):b.innerHTML=a;d[0]--;)b=b.lastChild;b=r.a.X(b.lastChild.childNodes)}return b};r.a.Z=function(a,b){r.a.U(a);if(b!==o&&b!==l)if("string"!=typeof b&&(b=b.toString()),"undefined"!=typeof jQuery)jQuery(a).html(b);else for(var d=r.a.ma(b),e=0;e<d.length;e++)a.appendChild(d[e])};r.b("ko.utils.parseHtmlFragment",r.a.ma);r.b("ko.utils.setHtml",r.a.Z);
+r.r=function(){function a(){return(4294967296*(1+Math.random())|0).toString(16).substring(1)}function b(a,f){if(a)if(8==a.nodeType){var d=r.r.Ga(a.nodeValue);d!=o&&f.push({cb:a,tb:d})}else if(1==a.nodeType)for(var d=0,g=a.childNodes,i=g.length;d<i;d++)b(g[d],f)}var d={};return{ka:function(b){"function"!=typeof b&&c(Error("You can only pass a function to ko.memoization.memoize()"));var f=a()+a();d[f]=b;return"<\!--[ko_memo:"+f+"]--\>"},Ra:function(a,b){var h=d[a];h===l&&c(Error("Couldn't find any memo with ID "+
+a+". Perhaps it's already been unmemoized."));try{return h.apply(o,b||[]),m}finally{delete d[a]}},Sa:function(a,f){var d=[];b(a,d);for(var g=0,i=d.length;g<i;g++){var j=d[g].cb,k=[j];f&&r.a.J(k,f);r.r.Ra(d[g].tb,k);j.nodeValue="";j.parentNode&&j.parentNode.removeChild(j)}},Ga:function(a){return(a=a.match(/^\[ko_memo\:(.*?)\]$/))?a[1]:o}}}();r.b("ko.memoization",r.r);r.b("ko.memoization.memoize",r.r.ka);r.b("ko.memoization.unmemoize",r.r.Ra);r.b("ko.memoization.parseMemoText",r.r.Ga);
+r.b("ko.memoization.unmemoizeDomNodeAndDescendants",r.r.Sa);r.Aa={throttle:function(a,b){a.throttleEvaluation=b;var d=o;return r.i({read:a,write:function(e){clearTimeout(d);d=setTimeout(function(){a(e)},b)}})},notify:function(a,b){a.equalityComparer="always"==b?function(){return p}:r.w.fn.equalityComparer;return a}};r.b("ko.extenders",r.Aa);r.Oa=function(a,b){this.da=a;this.bb=b;r.l(this,"dispose",this.v)};r.Oa.prototype.v=function(){this.nb=m;this.bb()};
+r.R=function(){this.u={};r.a.extend(this,r.R.fn);r.l(this,"subscribe",this.ra);r.l(this,"extend",this.extend);r.l(this,"getSubscriptionsCount",this.kb)};
+r.R.fn={ra:function(a,b,d){var d=d||"change",a=b?a.bind(b):a,e=new r.Oa(a,function(){r.a.ca(this.u[d],e)}.bind(this));this.u[d]||(this.u[d]=[]);this.u[d].push(e);return e},notifySubscribers:function(a,b){b=b||"change";this.u[b]&&r.a.n(this.u[b].slice(0),function(b){b&&b.nb!==m&&b.da(a)})},kb:function(){var a=0,b;for(b in this.u)this.u.hasOwnProperty(b)&&(a+=this.u[b].length);return a},extend:function(a){var b=this;if(a)for(var d in a){var e=r.Aa[d];"function"==typeof e&&(b=e(b,a[d]))}return b}};
+r.Ea=function(a){return"function"==typeof a.ra&&"function"==typeof a.notifySubscribers};r.b("ko.subscribable",r.R);r.b("ko.isSubscribable",r.Ea);r.T=function(){var a=[];return{Xa:function(b){a.push({da:b,za:[]})},end:function(){a.pop()},Ha:function(b){r.Ea(b)||c("Only subscribable things can act as dependencies");if(0<a.length){var d=a[a.length-1];0<=r.a.k(d.za,b)||(d.za.push(b),d.da(b))}}}}();var B={undefined:m,"boolean":m,number:m,string:m};
+r.w=function(a){function b(){if(0<arguments.length){if(!b.equalityComparer||!b.equalityComparer(d,arguments[0]))b.H(),d=arguments[0],b.G();return this}r.T.Ha(b);return d}var d=a;r.R.call(b);b.G=function(){b.notifySubscribers(d)};b.H=function(){b.notifySubscribers(d,"beforeChange")};r.a.extend(b,r.w.fn);r.l(b,"valueHasMutated",b.G);r.l(b,"valueWillMutate",b.H);return b};r.w.fn={B:r.w,equalityComparer:function(a,b){return a===o||typeof a in B?a===b:p}};
+r.V=function(a){return a===o||a===l||a.B===l?p:a.B===r.w?m:r.V(a.B)};r.P=function(a){return"function"==typeof a&&a.B===r.w?m:"function"==typeof a&&a.B===r.i&&a.lb?m:p};r.b("ko.observable",r.w);r.b("ko.isObservable",r.V);r.b("ko.isWriteableObservable",r.P);
+r.Q=function(a){0==arguments.length&&(a=[]);a!==o&&a!==l&&!("length"in a)&&c(Error("The argument passed when initializing an observable array must be an array, or null, or undefined."));var b=new r.w(a);r.a.extend(b,r.Q.fn);r.l(b,"remove",b.remove);r.l(b,"removeAll",b.zb);r.l(b,"destroy",b.fa);r.l(b,"destroyAll",b.ab);r.l(b,"indexOf",b.indexOf);r.l(b,"replace",b.replace);return b};
+r.Q.fn={remove:function(a){for(var b=this(),d=[],e="function"==typeof a?a:function(b){return b===a},f=0;f<b.length;f++){var h=b[f];e(h)&&(0===d.length&&this.H(),d.push(h),b.splice(f,1),f--)}d.length&&this.G();return d},zb:function(a){if(a===l){var b=this(),d=b.slice(0);this.H();b.splice(0,b.length);this.G();return d}return!a?[]:this.remove(function(b){return 0<=r.a.k(a,b)})},fa:function(a){var b=this(),d="function"==typeof a?a:function(b){return b===a};this.H();for(var e=b.length-1;0<=e;e--)d(b[e])&&
+(b[e]._destroy=m);this.G()},ab:function(a){return a===l?this.fa(function(){return m}):!a?[]:this.fa(function(b){return 0<=r.a.k(a,b)})},indexOf:function(a){var b=this();return r.a.k(b,a)},replace:function(a,b){var d=this.indexOf(a);0<=d&&(this.H(),this()[d]=b,this.G())}};r.a.n("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){r.Q.fn[a]=function(){var b=this();this.H();b=b[a].apply(b,arguments);this.G();return b}});
+r.a.n(["slice"],function(a){r.Q.fn[a]=function(){var b=this();return b[a].apply(b,arguments)}});r.b("ko.observableArray",r.Q);function C(a,b){a&&"object"==typeof a?b=a:(b=b||{},b.read=a||b.read);"function"!=typeof b.read&&c("Pass a function that returns the value of the dependentObservable");return b}
+r.i=function(a,b,d){function e(){r.a.n(q,function(a){a.v()});q=[]}function f(){var a=g.throttleEvaluation;a&&0<=a?(clearTimeout(v),v=setTimeout(h,a)):h()}function h(){if(j&&"function"==typeof d.disposeWhen&&d.disposeWhen())g.v();else{try{e();r.T.Xa(function(a){q.push(a.ra(f))});var a=d.read.call(d.owner||b);g.notifySubscribers(i,"beforeChange");i=a}finally{r.T.end()}g.notifySubscribers(i);j=m}}function g(){if(0<arguments.length)"function"===typeof d.write?d.write.apply(d.owner||b,arguments):c("Cannot write a value to a dependentObservable unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
+else return j||h(),r.T.Ha(g),i}var i,j=p,d=C(a,d),k="object"==typeof d.disposeWhenNodeIsRemoved?d.disposeWhenNodeIsRemoved:o,n=o;if(k){n=function(){g.v()};r.a.A.va(k,n);var t=d.disposeWhen;d.disposeWhen=function(){return!r.a.ga(k)||"function"==typeof t&&t()}}var q=[],v=o;g.jb=function(){return q.length};g.lb="function"===typeof d.write;g.v=function(){k&&r.a.A.Ia(k,n);e()};r.R.call(g);r.a.extend(g,r.i.fn);d.deferEvaluation!==m&&h();r.l(g,"dispose",g.v);r.l(g,"getDependenciesCount",g.jb);return g};
+r.i.fn={B:r.i};r.i.B=r.w;r.b("ko.dependentObservable",r.i);r.b("ko.computed",r.i);
+(function(){function a(e,f,h){h=h||new d;e=f(e);if(!("object"==typeof e&&e!==o&&e!==l&&!(e instanceof Date)))return e;var g=e instanceof Array?[]:{};h.save(e,g);b(e,function(b){var d=f(e[b]);switch(typeof d){case "boolean":case "number":case "string":case "function":g[b]=d;break;case "object":case "undefined":var k=h.get(d);g[b]=k!==l?k:a(d,f,h)}});return g}function b(a,b){if(a instanceof Array)for(var d=0;d<a.length;d++)b(d);else for(d in a)b(d)}function d(){var a=[],b=[];this.save=function(d,g){var i=
+r.a.k(a,d);0<=i?b[i]=g:(a.push(d),b.push(g))};this.get=function(d){d=r.a.k(a,d);return 0<=d?b[d]:l}}r.Pa=function(b){0==arguments.length&&c(Error("When calling ko.toJS, pass the object you want to convert."));return a(b,function(a){for(var b=0;r.V(a)&&10>b;b++)a=a();return a})};r.toJSON=function(a){a=r.Pa(a);return r.a.qa(a)}})();r.b("ko.toJS",r.Pa);r.b("ko.toJSON",r.toJSON);
+r.h={q:function(a){return"OPTION"==a.tagName?a.__ko__hasDomDataOptionValue__===m?r.a.e.get(a,r.c.options.la):a.getAttribute("value"):"SELECT"==a.tagName?0<=a.selectedIndex?r.h.q(a.options[a.selectedIndex]):l:a.value},S:function(a,b){if("OPTION"==a.tagName)switch(typeof b){case "string":r.a.e.set(a,r.c.options.la,l);"__ko__hasDomDataOptionValue__"in a&&delete a.__ko__hasDomDataOptionValue__;a.value=b;break;default:r.a.e.set(a,r.c.options.la,b),a.__ko__hasDomDataOptionValue__=m,a.value="number"===typeof b?
+b:""}else if("SELECT"==a.tagName)for(var d=a.options.length-1;0<=d;d--){if(r.h.q(a.options[d])==b){a.selectedIndex=d;break}}else{if(b===o||b===l)b="";a.value=b}}};r.b("ko.selectExtensions",r.h);r.b("ko.selectExtensions.readValue",r.h.q);r.b("ko.selectExtensions.writeValue",r.h.S);
+r.j=function(){function a(a,e){for(var d=o;a!=d;)d=a,a=a.replace(b,function(a,b){return e[b]});return a}var b=/\@ko_token_(\d+)\@/g,d=/^[\_$a-z][\_$a-z0-9]*(\[.*?\])*(\.[\_$a-z][\_$a-z0-9]*(\[.*?\])*)*$/i,e=["true","false"];return{D:[],Y:function(b){var e=r.a.z(b);if(3>e.length)return[];"{"===e.charAt(0)&&(e=e.substring(1,e.length-1));for(var b=[],d=o,i,j=0;j<e.length;j++){var k=e.charAt(j);if(d===o)switch(k){case '"':case "'":case "/":d=j,i=k}else if(k==i&&"\\"!==e.charAt(j-1)){k=e.substring(d,j+
+1);b.push(k);var n="@ko_token_"+(b.length-1)+"@",e=e.substring(0,d)+n+e.substring(j+1),j=j-(k.length-n.length),d=o}}i=d=o;for(var t=0,q=o,j=0;j<e.length;j++){k=e.charAt(j);if(d===o)switch(k){case "{":d=j;q=k;i="}";break;case "(":d=j;q=k;i=")";break;case "[":d=j,q=k,i="]"}k===q?t++:k===i&&(t--,0===t&&(k=e.substring(d,j+1),b.push(k),n="@ko_token_"+(b.length-1)+"@",e=e.substring(0,d)+n+e.substring(j+1),j-=k.length-n.length,d=o))}i=[];e=e.split(",");d=0;for(j=e.length;d<j;d++)t=e[d],q=t.indexOf(":"),
+0<q&&q<t.length-1?(k=t.substring(q+1),i.push({key:a(t.substring(0,q),b),value:a(k,b)})):i.push({unknown:a(t,b)});return i},ia:function(a){for(var b="string"===typeof a?r.j.Y(a):a,g=[],a=[],i,j=0;i=b[j];j++)if(0<g.length&&g.push(","),i.key){var k;a:{k=i.key;var n=r.a.z(k);switch(n.length&&n.charAt(0)){case "'":case '"':break a;default:k="'"+n+"'"}}i=i.value;g.push(k);g.push(":");g.push(i);n=r.a.z(i);if(0<=r.a.k(e,r.a.z(n).toLowerCase())?0:n.match(d)!==o)0<a.length&&a.push(", "),a.push(k+" : function(__ko_value) { "+
+i+" = __ko_value; }")}else i.unknown&&g.push(i.unknown);b=g.join("");0<a.length&&(b=b+", '_ko_property_writers' : { "+a.join("")+" } ");return b},rb:function(a,b){for(var e=0;e<a.length;e++)if(r.a.z(a[e].key)==b)return m;return p}}}();r.b("ko.jsonExpressionRewriting",r.j);r.b("ko.jsonExpressionRewriting.bindingRewriteValidators",r.j.D);r.b("ko.jsonExpressionRewriting.parseObjectLiteral",r.j.Y);r.b("ko.jsonExpressionRewriting.insertPropertyAccessorsIntoJson",r.j.ia);
+(function(){function a(a){return 8==a.nodeType&&(f?a.text:a.nodeValue).match(h)}function b(a){return 8==a.nodeType&&(f?a.text:a.nodeValue).match(g)}function d(e,d){for(var f=e,g=1,h=[];f=f.nextSibling;){if(b(f)&&(g--,0===g))return h;h.push(f);a(f)&&g++}d||c(Error("Cannot find closing comment tag to match: "+e.nodeValue));return o}function e(a,b){var e=d(a,b);return e?0<e.length?e[e.length-1].nextSibling:a.nextSibling:o}var f="<\!--test--\>"===document.createComment("test").text,h=f?/^<\!--\s*ko\s+(.*\:.*)\s*--\>$/:
+/^\s*ko\s+(.*\:.*)\s*$/,g=f?/^<\!--\s*\/ko\s*--\>$/:/^\s*\/ko\s*$/,i={ul:m,ol:m};r.f={C:{},childNodes:function(b){return a(b)?d(b):b.childNodes},ha:function(b){if(a(b))for(var b=r.f.childNodes(b),e=0,d=b.length;e<d;e++)r.removeNode(b[e]);else r.a.U(b)},oa:function(b,e){if(a(b)){r.f.ha(b);for(var d=b.nextSibling,f=0,g=e.length;f<g;f++)d.parentNode.insertBefore(e[f],d)}else r.a.oa(b,e)},xb:function(b,e){a(b)?b.parentNode.insertBefore(e,b.nextSibling):b.firstChild?b.insertBefore(e,b.firstChild):b.appendChild(e)},
+mb:function(b,e,d){a(b)?b.parentNode.insertBefore(e,d.nextSibling):d.nextSibling?b.insertBefore(e,d.nextSibling):b.appendChild(e)},nextSibling:function(d){return a(d)?e(d).nextSibling:d.nextSibling&&b(d.nextSibling)?l:d.nextSibling},ta:function(b){return(b=a(b))?b[1]:o},ib:function(a){if(r.f.ta(a)){var b;b=r.f.childNodes(a);for(var e=[],d=0,f=b.length;d<f;d++)r.a.A.F(b[d]),e.push(r.a.outerHTML(b[d]));b=String.prototype.concat.apply("",e);r.f.ha(a);(new r.m.I(a)).text(b)}},Fa:function(d){if(i[d.tagName.toLowerCase()]){var f=
+d.firstChild;if(f){do if(1===f.nodeType){var g;g=f.firstChild;var h=o;if(g){do if(h)h.push(g);else if(a(g)){var q=e(g,m);q?g=q:h=[g]}else b(g)&&(h=[g]);while(g=g.nextSibling)}if(g=h){h=f.nextSibling;for(q=0;q<g.length;q++)h?d.insertBefore(g[q],h):d.appendChild(g[q])}}while(f=f.nextSibling)}}}}})();r.L=function(){};
+r.a.extend(r.L.prototype,{nodeHasBindings:function(a){switch(a.nodeType){case 1:return a.getAttribute("data-bind")!=o;case 8:return r.f.ta(a)!=o;default:return p}},getBindings:function(a,b){var d=this.getBindingsString(a,b);return d?this.parseBindingsString(d,b):o},getBindingsString:function(a){switch(a.nodeType){case 1:return a.getAttribute("data-bind");case 8:return r.f.ta(a);default:return o}},parseBindingsString:function(a,b){try{var d=b.$data,e=" { "+r.j.ia(a)+" } ";return r.a.hb(e,d===o?window:
+d,b)}catch(f){c(Error("Unable to parse bindings.\nMessage: "+f+";\nBindings value: "+a))}}});r.L.instance=new r.L;r.b("ko.bindingProvider",r.L);
+(function(){function a(a,d){for(var h,g=d.childNodes[0];h=g;)g=r.f.nextSibling(h),b(a,h,p)}function b(b,f,h){var g=m,i=1==f.nodeType;i&&r.f.Fa(f);if(i&&h||r.L.instance.nodeHasBindings(f))g=d(f,o,b,h).Bb;i&&g&&a(b,f)}function d(a,b,d,g){function i(a){return function(){return n[a]}}function j(){return n}var k=0;r.f.ib(a);var n,t;new r.i(function(){var q=d&&d instanceof r.K?d:new r.K(r.a.d(d)),v=q.$data;g&&r.Na(a,q);if(n=("function"==typeof b?b():b)||r.L.instance.getBindings(a,q)){if(0===k){k=1;for(var s in n){var w=
+r.c[s];w&&8===a.nodeType&&!r.f.C[s]&&c(Error("The binding '"+s+"' cannot be used with virtual elements"));if(w&&"function"==typeof w.init&&(w=(0,w.init)(a,i(s),j,v,q))&&w.controlsDescendantBindings)t!==l&&c(Error("Multiple bindings ("+t+" and "+s+") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.")),t=s}k=2}if(2===k)for(s in n)(w=r.c[s])&&"function"==typeof w.update&&(0,w.update)(a,i(s),j,v,q)}},o,{disposeWhenNodeIsRemoved:a});
+return{Bb:t===l}}r.c={};r.K=function(a,b){this.$data=a;b?(this.$parent=b.$data,this.$parents=(b.$parents||[]).slice(0),this.$parents.unshift(this.$parent),this.$root=b.$root):(this.$parents=[],this.$root=a)};r.K.prototype.createChildContext=function(a){return new r.K(a,this)};r.Na=function(a,b){if(2==arguments.length)r.a.e.set(a,"__ko_bindingContext__",b);else return r.a.e.get(a,"__ko_bindingContext__")};r.xa=function(a,b,h){1===a.nodeType&&r.f.Fa(a);return d(a,b,h,m)};r.Ta=function(b,d){1===d.nodeType&&
+a(b,d)};r.wa=function(a,d){d&&1!==d.nodeType&&8!==d.nodeType&&c(Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node"));d=d||window.document.body;b(a,d,m)};r.ea=function(a){switch(a.nodeType){case 1:case 8:var b=r.Na(a);if(b)return b;if(a.parentNode)return r.ea(a.parentNode)}};r.$a=function(a){return(a=r.ea(a))?a.$data:l};r.b("ko.bindingHandlers",r.c);r.b("ko.applyBindings",r.wa);r.b("ko.applyBindingsToDescendants",r.Ta);r.b("ko.applyBindingsToNode",
+r.xa);r.b("ko.contextFor",r.ea);r.b("ko.dataFor",r.$a)})();r.a.n(["click"],function(a){r.c[a]={init:function(b,d,e,f){return r.c.event.init.call(this,b,function(){var b={};b[a]=d();return b},e,f)}}});
+r.c.event={init:function(a,b,d,e){var f=b()||{},h;for(h in f)(function(){var f=h;"string"==typeof f&&r.a.s(a,f,function(a){var h,k=b()[f];if(k){var n=d();try{var t=r.a.X(arguments);t.unshift(e);h=k.apply(e,t)}finally{if(h!==m)a.preventDefault?a.preventDefault():a.returnValue=p}if(n[f+"Bubble"]===p)a.cancelBubble=m,a.stopPropagation&&a.stopPropagation()}})})()}};
+r.c.submit={init:function(a,b,d,e){"function"!=typeof b()&&c(Error("The value for a submit binding must be a function"));r.a.s(a,"submit",function(d){var h,g=b();try{h=g.call(e,a)}finally{if(h!==m)d.preventDefault?d.preventDefault():d.returnValue=p}})}};r.c.visible={update:function(a,b){var d=r.a.d(b()),e="none"!=a.style.display;if(d&&!e)a.style.display="";else if(!d&&e)a.style.display="none"}};
+r.c.enable={update:function(a,b){var d=r.a.d(b());if(d&&a.disabled)a.removeAttribute("disabled");else if(!d&&!a.disabled)a.disabled=m}};r.c.disable={update:function(a,b){r.c.enable.update(a,function(){return!r.a.d(b())})}};function D(a,b,d){d&&b!==r.h.q(a)&&r.h.S(a,b);b!==r.h.q(a)&&r.a.sa(a,"change")}
+r.c.value={init:function(a,b,d){var e=["change"],f=d().valueUpdate;f&&("string"==typeof f&&(f=[f]),r.a.J(e,f),e=r.a.ya(e));r.a.n(e,function(e){var f=p;r.a.Cb(e,"after")&&(f=m,e=e.substring(5));var i=f?function(a){setTimeout(a,0)}:function(a){a()};r.a.s(a,e,function(){i(function(){var e=b(),f=r.h.q(a);r.P(e)?e(f):(e=d(),e._ko_property_writers&&e._ko_property_writers.value&&e._ko_property_writers.value(f))})})})},update:function(a,b){var d=r.a.d(b()),e=r.h.q(a),f=d!=e;0===d&&0!==e&&"0"!==e&&(f=m);f&&
+(e=function(){r.h.S(a,d)},e(),"SELECT"==a.tagName&&setTimeout(e,0));"SELECT"==a.tagName&&0<a.length&&D(a,d,p)}};
+r.c.options={update:function(a,b,d){"SELECT"!=a.tagName&&c(Error("options binding applies only to SELECT elements"));var e=0==a.length,f=r.a.ba(r.a.aa(a.childNodes,function(a){return a.tagName&&"OPTION"==a.tagName&&a.selected}),function(a){return r.h.q(a)||a.innerText||a.textContent}),h=a.scrollTop;a.scrollTop=0;for(var g=r.a.d(b());0<a.length;)r.F(a.options[0]),a.remove(0);if(g){d=d();"number"!=typeof g.length&&(g=[g]);if(d.optionsCaption){var i=document.createElement("OPTION");r.a.Z(i,d.optionsCaption);
+r.h.S(i,l);a.appendChild(i)}for(var b=0,j=g.length;b<j;b++){var i=document.createElement("OPTION"),k="string"==typeof d.optionsValue?g[b][d.optionsValue]:g[b],k=r.a.d(k);r.h.S(i,k);var n=d.optionsText,k="function"==typeof n?n(g[b]):"string"==typeof n?g[b][n]:k;if(k===o||k===l)k="";r.a.Ma(i,k);a.appendChild(i)}g=a.getElementsByTagName("OPTION");b=i=0;for(j=g.length;b<j;b++)0<=r.a.k(f,r.h.q(g[b]))&&(r.a.La(g[b],m),i++);if(h)a.scrollTop=h;e&&"value"in d&&D(a,r.a.d(d.value),m)}}};r.c.options.la="__ko.optionValueDomData__";
+r.c.selectedOptions={Da:function(a){for(var b=[],a=a.childNodes,d=0,e=a.length;d<e;d++){var f=a[d];"OPTION"==f.tagName&&f.selected&&b.push(r.h.q(f))}return b},init:function(a,b,d){r.a.s(a,"change",function(){var a=b();r.P(a)?a(r.c.selectedOptions.Da(this)):(a=d(),a._ko_property_writers&&a._ko_property_writers.value&&a._ko_property_writers.value(r.c.selectedOptions.Da(this)))})},update:function(a,b){"SELECT"!=a.tagName&&c(Error("values binding applies only to SELECT elements"));var d=r.a.d(b());if(d&&
+"number"==typeof d.length)for(var e=a.childNodes,f=0,h=e.length;f<h;f++){var g=e[f];"OPTION"==g.tagName&&r.a.La(g,0<=r.a.k(d,r.h.q(g)))}}};r.c.text={update:function(a,b){r.a.Ma(a,b())}};r.c.html={init:function(){return{controlsDescendantBindings:m}},update:function(a,b){var d=r.a.d(b());r.a.Z(a,d)}};r.c.css={update:function(a,b){var d=r.a.d(b()||{}),e;for(e in d)if("string"==typeof e){var f=r.a.d(d[e]);r.a.Qa(a,e,f)}}};
+r.c.style={update:function(a,b){var d=r.a.d(b()||{}),e;for(e in d)if("string"==typeof e){var f=r.a.d(d[e]);a.style[e]=f||""}}};r.c.uniqueName={init:function(a,b){if(b())a.name="ko_unique_"+ ++r.c.uniqueName.Za,(r.a.ob||r.a.pb)&&a.mergeAttributes(document.createElement("<input name='"+a.name+"'/>"),p)}};r.c.uniqueName.Za=0;
+r.c.checked={init:function(a,b,d){r.a.s(a,"click",function(){var e;if("checkbox"==a.type)e=a.checked;else if("radio"==a.type&&a.checked)e=a.value;else return;var f=b();"checkbox"==a.type&&r.a.d(f)instanceof Array?(e=r.a.k(r.a.d(f),a.value),a.checked&&0>e?f.push(a.value):!a.checked&&0<=e&&f.splice(e,1)):r.P(f)?f()!==e&&f(e):(f=d(),f._ko_property_writers&&f._ko_property_writers.checked&&f._ko_property_writers.checked(e))});"radio"==a.type&&!a.name&&r.c.uniqueName.init(a,function(){return m})},update:function(a,
+b){var d=r.a.d(b());if("checkbox"==a.type)a.checked=d instanceof Array?0<=r.a.k(d,a.value):d;else if("radio"==a.type)a.checked=a.value==d}};r.c.attr={update:function(a,b){var d=r.a.d(b())||{},e;for(e in d)if("string"==typeof e){var f=r.a.d(d[e]);f===p||f===o||f===l?a.removeAttribute(e):a.setAttribute(e,f.toString())}}};
+r.c.hasfocus={init:function(a,b,d){function e(a){var e=b();a!=r.a.d(e)&&(r.P(e)?e(a):(e=d(),e._ko_property_writers&&e._ko_property_writers.hasfocus&&e._ko_property_writers.hasfocus(a)))}r.a.s(a,"focus",function(){e(m)});r.a.s(a,"focusin",function(){e(m)});r.a.s(a,"blur",function(){e(p)});r.a.s(a,"focusout",function(){e(p)})},update:function(a,b){var d=r.a.d(b());d?a.focus():a.blur();r.a.sa(a,d?"focusin":"focusout")}};
+r.c["with"]={o:function(a){return function(){var b=a();return{"if":b,data:b,templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c["with"].o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c["with"].o(b),d,e,f)}};r.j.D["with"]=p;r.f.C["with"]=m;r.c["if"]={o:function(a){return function(){return{"if":a(),templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c["if"].o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c["if"].o(b),d,e,f)}};
+r.j.D["if"]=p;r.f.C["if"]=m;r.c.ifnot={o:function(a){return function(){return{ifnot:a(),templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c.ifnot.o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c.ifnot.o(b),d,e,f)}};r.j.D.ifnot=p;r.f.C.ifnot=m;
+r.c.foreach={o:function(a){return function(){var b=r.a.d(a());return!b||"number"==typeof b.length?{foreach:b,templateEngine:r.p.M}:{foreach:b.data,includeDestroyed:b.includeDestroyed,afterAdd:b.afterAdd,beforeRemove:b.beforeRemove,afterRender:b.afterRender,templateEngine:r.p.M}}},init:function(a,b){return r.c.template.init(a,r.c.foreach.o(b))},update:function(a,b,d,e,f){return r.c.template.update(a,r.c.foreach.o(b),d,e,f)}};r.j.D.foreach=p;r.f.C.foreach=m;r.b("ko.allowedVirtualElementBindings",r.f.C);
+r.t=function(){};r.t.prototype.renderTemplateSource=function(){c("Override renderTemplateSource")};r.t.prototype.createJavaScriptEvaluatorBlock=function(){c("Override createJavaScriptEvaluatorBlock")};r.t.prototype.makeTemplateSource=function(a){if("string"==typeof a){var b=document.getElementById(a);b||c(Error("Cannot find template with ID "+a));return new r.m.g(b)}if(1==a.nodeType||8==a.nodeType)return new r.m.I(a);c(Error("Unknown template type: "+a))};
+r.t.prototype.renderTemplate=function(a,b,d){return this.renderTemplateSource(this.makeTemplateSource(a),b,d)};r.t.prototype.isTemplateRewritten=function(a){return this.allowTemplateRewriting===p?m:this.W&&this.W[a]?m:this.makeTemplateSource(a).data("isRewritten")};r.t.prototype.rewriteTemplate=function(a,b){var d=this.makeTemplateSource(a),e=b(d.text());d.text(e);d.data("isRewritten",m);if("string"==typeof a)this.W=this.W||{},this.W[a]=m};r.b("ko.templateEngine",r.t);
+r.$=function(){function a(a,b,d){for(var a=r.j.Y(a),g=r.j.D,i=0;i<a.length;i++){var j=a[i].key;if(g.hasOwnProperty(j)){var k=g[j];"function"===typeof k?(j=k(a[i].value))&&c(Error(j)):k||c(Error("This template engine does not support the '"+j+"' binding within its templates"))}}a="ko.templateRewriting.applyMemoizedBindingsToNextSibling(function() { return (function() { return { "+r.j.ia(a)+" } })() })";return d.createJavaScriptEvaluatorBlock(a)+b}var b=/(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi,
+d=/<\!--\s*ko\b\s*([\s\S]*?)\s*--\>/g;return{gb:function(a,b){b.isTemplateRewritten(a)||b.rewriteTemplate(a,function(a){return r.$.ub(a,b)})},ub:function(e,f){return e.replace(b,function(b,e,d,j,k,n,t){return a(t,e,f)}).replace(d,function(b,e){return a(e,"<\!-- ko --\>",f)})},Ua:function(a){return r.r.ka(function(b,d){b.nextSibling&&r.xa(b.nextSibling,a,d)})}}}();r.b("ko.templateRewriting",r.$);r.b("ko.templateRewriting.applyMemoizedBindingsToNextSibling",r.$.Ua);r.m={};r.m.g=function(a){this.g=a};
+r.m.g.prototype.text=function(){if(0==arguments.length)return"script"==this.g.tagName.toLowerCase()?this.g.text:this.g.innerHTML;var a=arguments[0];"script"==this.g.tagName.toLowerCase()?this.g.text=a:r.a.Z(this.g,a)};r.m.g.prototype.data=function(a){if(1===arguments.length)return r.a.e.get(this.g,"templateSourceData_"+a);r.a.e.set(this.g,"templateSourceData_"+a,arguments[1])};r.m.I=function(a){this.g=a};r.m.I.prototype=new r.m.g;
+r.m.I.prototype.text=function(){if(0==arguments.length)return r.a.e.get(this.g,"__ko_anon_template__");r.a.e.set(this.g,"__ko_anon_template__",arguments[0])};r.b("ko.templateSources",r.m);r.b("ko.templateSources.domElement",r.m.g);r.b("ko.templateSources.anonymousTemplate",r.m.I);
+(function(){function a(a,b,d){for(var g=0;node=a[g];g++)node.parentNode===b&&(1===node.nodeType||8===node.nodeType)&&d(node)}function b(a,b,h,g,i){var i=i||{},j=i.templateEngine||d;r.$.gb(h,j);h=j.renderTemplate(h,g,i);("number"!=typeof h.length||0<h.length&&"number"!=typeof h[0].nodeType)&&c("Template engine must return an array of DOM nodes");j=p;switch(b){case "replaceChildren":r.f.oa(a,h);j=m;break;case "replaceNode":r.a.Ja(a,h);j=m;break;case "ignoreTargetNode":break;default:c(Error("Unknown renderMode: "+
+b))}j&&(r.ua(h,g),i.afterRender&&i.afterRender(h,g.$data));return h}var d;r.pa=function(a){a!=l&&!(a instanceof r.t)&&c("templateEngine must inherit from ko.templateEngine");d=a};r.ua=function(b,d){var h=r.a.J([],b),g=0<b.length?b[0].parentNode:o;a(h,g,function(a){r.wa(d,a)});a(h,g,function(a){r.r.Sa(a,[d])})};r.na=function(a,f,h,g,i){h=h||{};(h.templateEngine||d)==l&&c("Set a template engine before calling renderTemplate");i=i||"replaceChildren";if(g){var j=g.nodeType?g:0<g.length?g[0]:o;return new r.i(function(){var d=
+f&&f instanceof r.K?f:new r.K(r.a.d(f)),n="function"==typeof a?a(d.$data):a,d=b(g,i,n,d,h);"replaceNode"==i&&(g=d,j=g.nodeType?g:0<g.length?g[0]:o)},o,{disposeWhen:function(){return!j||!r.a.ga(j)},disposeWhenNodeIsRemoved:j&&"replaceNode"==i?j.parentNode:j})}return r.r.ka(function(b){r.na(a,f,h,b,"replaceNode")})};r.Ab=function(a,d,h,g,i){function j(a,b){var d=k(a);r.ua(b,d);h.afterRender&&h.afterRender(b,d.$data)}function k(a){return i.createChildContext(r.a.d(a))}return new r.i(function(){var i=
+r.a.d(d)||[];"undefined"==typeof i.length&&(i=[i]);i=r.a.aa(i,function(a){return h.includeDestroyed||a===l||a===o||!r.a.d(a._destroy)});r.a.Ka(g,i,function(d){var f="function"==typeof a?a(d):a;return b(o,"ignoreTargetNode",f,k(d),h)},h,j)},o,{disposeWhenNodeIsRemoved:g})};r.c.template={init:function(a,b){var d=r.a.d(b());"string"!=typeof d&&!d.name&&1==a.nodeType&&((new r.m.I(a)).text(a.innerHTML),r.a.U(a));return{controlsDescendantBindings:m}},update:function(a,b,d,g,i){b=r.a.d(b());g=m;"string"==
+typeof b?d=b:(d=b.name,"if"in b&&(g=g&&r.a.d(b["if"])),"ifnot"in b&&(g=g&&!r.a.d(b.ifnot)));var j=o;"object"===typeof b&&"foreach"in b?j=r.Ab(d||a,g&&b.foreach||[],b,a,i):g?(i="object"==typeof b&&"data"in b?i.createChildContext(r.a.d(b.data)):i,j=r.na(d||a,i,b,a)):r.f.ha(a);i=j;(b=r.a.e.get(a,"__ko__templateSubscriptionDomDataKey__"))&&"function"==typeof b.v&&b.v();r.a.e.set(a,"__ko__templateSubscriptionDomDataKey__",i)}};r.j.D.template=function(a){a=r.j.Y(a);return 1==a.length&&a[0].unknown?o:r.j.rb(a,
+"name")?o:"This template engine does not support anonymous templates nested within its templates"};r.f.C.template=m})();r.b("ko.setTemplateEngine",r.pa);r.b("ko.renderTemplate",r.na);
+r.a.N=function(a,b,d){if(d===l)return r.a.N(a,b,1)||r.a.N(a,b,10)||r.a.N(a,b,Number.MAX_VALUE);for(var a=a||[],b=b||[],e=a,f=b,h=[],g=0;g<=f.length;g++)h[g]=[];for(var g=0,i=Math.min(e.length,d);g<=i;g++)h[0][g]=g;g=1;for(i=Math.min(f.length,d);g<=i;g++)h[g][0]=g;for(var i=e.length,j,k=f.length,g=1;g<=i;g++){j=Math.max(1,g-d);for(var n=Math.min(k,g+d);j<=n;j++)h[j][g]=e[g-1]===f[j-1]?h[j-1][g-1]:Math.min(h[j-1][g]===l?Number.MAX_VALUE:h[j-1][g]+1,h[j][g-1]===l?Number.MAX_VALUE:h[j][g-1]+1)}d=a.length;
+e=b.length;f=[];g=h[e][d];if(g===l)h=o;else{for(;0<d||0<e;){i=h[e][d];k=0<e?h[e-1][d]:g+1;n=0<d?h[e][d-1]:g+1;j=0<e&&0<d?h[e-1][d-1]:g+1;if(k===l||k<i-1)k=g+1;if(n===l||n<i-1)n=g+1;j<i-1&&(j=g+1);k<=n&&k<j?(f.push({status:"added",value:b[e-1]}),e--):(n<k&&n<j?f.push({status:"deleted",value:a[d-1]}):(f.push({status:"retained",value:a[d-1]}),e--),d--)}h=f.reverse()}return h};r.b("ko.utils.compareArrays",r.a.N);
+(function(){function a(a){if(2<a.length){for(var b=a[0],f=a[a.length-1],h=[b];b!==f;){b=b.nextSibling;if(!b)return;h.push(b)}Array.prototype.splice.apply(a,[0,a.length].concat(h))}}function b(b,e,f,h){var g=[],b=r.i(function(){var b=e(f)||[];0<g.length&&(a(g),r.a.Ja(g,b),h&&h(f,b));g.splice(0,g.length);r.a.J(g,b)},o,{disposeWhenNodeIsRemoved:b,disposeWhen:function(){return 0==g.length||!r.a.ga(g[0])}});return{sb:g,i:b}}r.a.Ka=function(d,e,f,h,g){for(var e=e||[],h=h||{},i=r.a.e.get(d,"setDomNodeChildrenFromArrayMapping_lastMappingResult")===
+l,j=r.a.e.get(d,"setDomNodeChildrenFromArrayMapping_lastMappingResult")||[],k=r.a.ba(j,function(a){return a.Va}),n=r.a.N(k,e),e=[],t=0,q=[],k=[],v=o,s=0,w=n.length;s<w;s++)switch(n[s].status){case "retained":var x=j[t];e.push(x);0<x.O.length&&(v=x.O[x.O.length-1]);t++;break;case "deleted":j[t].i.v();a(j[t].O);r.a.n(j[t].O,function(a){q.push({element:a,index:s,value:n[s].value});v=a});t++;break;case "added":var x=n[s].value,z=b(d,f,x,g),u=z.sb;e.push({Va:n[s].value,O:u,i:z.i});for(var z=0,y=u.length;z<
+y;z++){var A=u[z];k.push({element:A,index:s,value:n[s].value});v==o?r.f.xb(d,A):r.f.mb(d,A,v);v=A}g&&g(x,u)}r.a.n(q,function(a){r.F(a.element)});f=p;if(!i){if(h.afterAdd)for(s=0;s<k.length;s++)h.afterAdd(k[s].element,k[s].index,k[s].value);if(h.beforeRemove){for(s=0;s<q.length;s++)h.beforeRemove(q[s].element,q[s].index,q[s].value);f=m}}f||r.a.n(q,function(a){r.removeNode(a.element)});r.a.e.set(d,"setDomNodeChildrenFromArrayMapping_lastMappingResult",e)}})();
+r.b("ko.utils.setDomNodeChildrenFromArrayMapping",r.a.Ka);r.p=function(){this.allowTemplateRewriting=p};r.p.prototype=new r.t;r.p.prototype.renderTemplateSource=function(a){a=a.text();return r.a.ma(a)};r.p.M=new r.p;r.pa(r.p.M);r.b("ko.nativeTemplateEngine",r.p);
+(function(){r.ja=function(){var a=this.qb=function(){if("undefined"==typeof jQuery||!jQuery.tmpl)return 0;try{if(0<=jQuery.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(d,e,f){f=f||{};2>a&&c(Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later."));var h=d.data("precompiled");h||(h=d.text()||"",h=jQuery.template(o,"{{ko_with $item.koBindingContext}}"+h+"{{/ko_with}}"),d.data("precompiled",h));
+d=[e.$data];e=jQuery.extend({koBindingContext:e},f.templateOptions);e=jQuery.tmpl(h,d,e);e.appendTo(document.createElement("div"));jQuery.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){document.write("<script type='text/html' id='"+a+"'>"+b+"<\/script>")};if(0<a)jQuery.tmpl.tag.ko_code={open:"__.push($1 || '');"},jQuery.tmpl.tag.ko_with={open:"with($1) {",close:"} "}};r.ja.prototype=new r.t;
+var a=new r.ja;0<a.qb&&r.pa(a);r.b("ko.jqueryTmplTemplateEngine",r.ja)})();
+})(window);
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/main.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/main.py
new file mode 100644
index 00000000000..c43810594fa
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/main.py
@@ -0,0 +1,234 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+r"""
+=================================
+ Benchmark jsmin implementations
+=================================
+
+Benchmark jsmin implementations.
+
+:Copyright:
+
+ Copyright 2011 - 2015
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+Usage::
+
+ python -mbench.main [-c COUNT] [-p file] jsfile ...
+
+ -c COUNT number of runs per jsfile and minifier. Defaults to 10.
+ -p file File to write the benchmark results in (pickled)
+
+"""
+if __doc__:
+ __doc__ = __doc__.encode('ascii').decode('unicode_escape')
+__author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
+__docformat__ = "restructuredtext en"
+__license__ = "Apache License, Version 2.0"
+__version__ = "1.0.0"
+
+import sys as _sys
+import time as _time
+
+import_notes = []
+class jsmins(object):
+ from bench import jsmin as p_01_simple_port
+ if _sys.version_info >= (2, 4):
+ from bench import jsmin_2_0_9 as p_02_jsmin_2_0_9
+ else:
+ import_notes.append(
+ "jsmin_2_0_9 available for python 2.4 and later..."
+ )
+ print(import_notes[-1])
+
+ import rjsmin as p_05_rjsmin
+ try:
+ import _rjsmin as p_06__rjsmin
+ except ImportError:
+ import_notes.append("_rjsmin (C-Port) not available")
+ print(import_notes[-1])
+jsmins.p_05_rjsmin.jsmin = jsmins.p_05_rjsmin._make_jsmin(
+ python_only=True
+)
+print("Python Release: %s" % ".".join(map(str, _sys.version_info[:3])))
+print("")
+
+
+def slurp(filename):
+ """ Load a file """
+ fp = open(filename)
+ try:
+ return fp.read()
+ finally:
+ fp.close()
+
+
+def print_(*value, **kwargs):
+ """ Print stuff """
+ (kwargs.get('file') or _sys.stdout).write(
+ ''.join(value) + kwargs.get('end', '\n')
+ )
+
+
+def bench(filenames, count):
+ """
+ Benchmark the minifiers with given javascript samples
+
+ :Parameters:
+ `filenames` : sequence
+ List of filenames
+
+ `count` : ``int``
+ Number of runs per js file and minifier
+
+ :Exceptions:
+ - `RuntimeError` : empty filenames sequence
+ """
+ if not filenames:
+ raise RuntimeError("Missing files to benchmark")
+ try:
+ xrange
+ except NameError:
+ xrange = range
+ try:
+ cmp
+ except NameError:
+ cmp = lambda a, b: (a > b) - (a < b)
+
+ ports = [item for item in dir(jsmins) if item.startswith('p_')]
+ ports.sort()
+ space = max(map(len, ports)) - 4
+ ports = [(item[5:], getattr(jsmins, item).jsmin) for item in ports]
+ flush = _sys.stdout.flush
+
+ struct = []
+ inputs = [(filename, slurp(filename)) for filename in filenames]
+ for filename, script in inputs:
+ print_("Benchmarking %r..." % filename, end=" ")
+ flush()
+ outputs = []
+ for _, jsmin in ports:
+ try:
+ outputs.append(jsmin(script))
+ except (SystemExit, KeyboardInterrupt):
+ raise
+ except:
+ outputs.append(None)
+ struct.append(dict(
+ filename=filename,
+ sizes=[
+ (item is not None and len(item) or None) for item in outputs
+ ],
+ size=len(script),
+ messages=[],
+ times=[],
+ ))
+ print_("(%.1f KiB)" % (struct[-1]['size'] / 1024.0,))
+ flush()
+ times = []
+ for idx, (name, jsmin) in enumerate(ports):
+ if outputs[idx] is None:
+ print_(" FAILED %s" % (name,))
+ struct[-1]['times'].append((name, None))
+ else:
+ print_(" Timing %s%s... (%5.1f KiB %s)" % (
+ name,
+ " " * (space - len(name)),
+ len(outputs[idx]) / 1024.0,
+ idx == 0 and '*' or ['=', '>', '<'][
+ cmp(len(outputs[idx]), len(outputs[0]))
+ ],
+ ), end=" ")
+ flush()
+
+ xcount = count
+ while True:
+ counted = [None for _ in xrange(xcount)]
+ start = _time.time()
+ for _ in counted:
+ jsmin(script)
+ end = _time.time()
+ result = (end - start) * 1000
+ if result < 10: # avoid measuring within the error range
+ xcount *= 10
+ continue
+ times.append(result / xcount)
+ break
+
+ print_("%8.2f ms" % times[-1], end=" ")
+ flush()
+ if len(times) <= 1:
+ print_()
+ else:
+ print_("(factor: %s)" % (', '.join([
+ '%.2f' % (timed / times[-1]) for timed in times[:-1]
+ ])))
+ struct[-1]['times'].append((name, times[-1]))
+
+ flush()
+ print_()
+
+ return struct
+
+
+def main(argv=None):
+ """ Main """
+ import getopt as _getopt
+ import os as _os
+ import pickle as _pickle
+
+ if argv is None:
+ argv = _sys.argv[1:]
+ try:
+ opts, args = _getopt.getopt(argv, "hc:p:", ["help"])
+ except getopt.GetoptError:
+ e = _sys.exc_info()[0](_sys.exc_info()[1])
+ print >> _sys.stderr, "%s\nTry %s -mbench.main --help" % (
+ e,
+ _os.path.basename(_sys.executable),
+ )
+ _sys.exit(2)
+
+ count, pickle = 10, None
+ for key, value in opts:
+ if key in ("-h", "--help"):
+ print >> _sys.stderr, (
+ "%s -mbench.main [-c count] [-p file] cssfile ..." % (
+ _os.path.basename(_sys.executable),
+ )
+ )
+ _sys.exit(0)
+ elif key == '-c':
+ count = int(value)
+ elif key == '-p':
+ pickle = str(value)
+
+ struct = bench(args, count)
+ if pickle:
+ fp = open(pickle, 'wb')
+ try:
+ fp.write(_pickle.dumps((
+ ".".join(map(str, _sys.version_info[:3])),
+ import_notes,
+ struct,
+ ), 0))
+ finally:
+ fp.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/markermanager.js b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/markermanager.js
new file mode 100644
index 00000000000..10066507512
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/markermanager.js
@@ -0,0 +1,976 @@
+/**
+ * @name MarkerManager v3
+ * @version 1.0
+ * @copyright (c) 2007 Google Inc.
+ * @author Doug Ricket, Bjorn Brala (port to v3), others,
+ *
+ * @fileoverview Marker manager is an interface between the map and the user,
+ * designed to manage adding and removing many points when the viewport changes.
+ * <br /><br />
+ * <b>How it Works</b>:<br/>
+ * The MarkerManager places its markers onto a grid, similar to the map tiles.
+ * When the user moves the viewport, it computes which grid cells have
+ * entered or left the viewport, and shows or hides all the markers in those
+ * cells.
+ * (If the users scrolls the viewport beyond the markers that are loaded,
+ * no markers will be visible until the <code>EVENT_moveend</code>
+ * triggers an update.)
+ * In practical consequences, this allows 10,000 markers to be distributed over
+ * a large area, and as long as only 100-200 are visible in any given viewport,
+ * the user will see good performance corresponding to the 100 visible markers,
+ * rather than poor performance corresponding to the total 10,000 markers.
+ * Note that some code is optimized for speed over space,
+ * with the goal of accommodating thousands of markers.
+ */
+
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @name MarkerManagerOptions
+ * @class This class represents optional arguments to the {@link MarkerManager}
+ * constructor.
+ * @property {Number} maxZoom Sets the maximum zoom level monitored by a
+ * marker manager. If not given, the manager assumes the maximum map zoom
+ * level. This value is also used when markers are added to the manager
+ * without the optional {@link maxZoom} parameter.
+ * @property {Number} borderPadding Specifies, in pixels, the extra padding
+ * outside the map's current viewport monitored by a manager. Markers that
+ * fall within this padding are added to the map, even if they are not fully
+ * visible.
+ * @property {Boolean} trackMarkers=false Indicates whether or not a marker
+ * manager should track markers' movements. If you wish to move managed
+ * markers using the {@link setPoint}/{@link setLatLng} methods,
+ * this option should be set to {@link true}.
+ */
+
+/**
+ * Creates a new MarkerManager that will show/hide markers on a map.
+ *
+ * Events:
+ * @event changed (Parameters: shown bounds, shown markers) Notify listeners when the state of what is displayed changes.
+ * @event loaded MarkerManager has succesfully been initialized.
+ *
+ * @constructor
+ * @param {Map} map The map to manage.
+ * @param {Object} opt_opts A container for optional arguments:
+ * {Number} maxZoom The maximum zoom level for which to create tiles.
+ * {Number} borderPadding The width in pixels beyond the map border,
+ * where markers should be display.
+ * {Boolean} trackMarkers Whether or not this manager should track marker
+ * movements.
+ */
+function MarkerManager(map, opt_opts) {
+ var me = this;
+ me.map_ = map;
+ me.mapZoom_ = map.getZoom();
+
+ me.projectionHelper_ = new ProjectionHelperOverlay(map);
+ google.maps.event.addListener(me.projectionHelper_, 'ready', function () {
+ me.projection_ = this.getProjection();
+ me.initialize(map, opt_opts);
+ });
+}
+
+
+MarkerManager.prototype.initialize = function (map, opt_opts) {
+ var me = this;
+
+ opt_opts = opt_opts || {};
+ me.tileSize_ = MarkerManager.DEFAULT_TILE_SIZE_;
+
+ var mapTypes = map.mapTypes;
+
+ // Find max zoom level
+ var mapMaxZoom = 1;
+ for (var sType in mapTypes ) {
+ if (typeof map.mapTypes.get(sType) === 'object' && typeof map.mapTypes.get(sType).maxZoom === 'number') {
+ var mapTypeMaxZoom = map.mapTypes.get(sType).maxZoom;
+ if (mapTypeMaxZoom > mapMaxZoom) {
+ mapMaxZoom = mapTypeMaxZoom;
+ }
+ }
+ }
+
+ me.maxZoom_ = opt_opts.maxZoom || 19;
+
+ me.trackMarkers_ = opt_opts.trackMarkers;
+ me.show_ = opt_opts.show || true;
+
+ var padding;
+ if (typeof opt_opts.borderPadding === 'number') {
+ padding = opt_opts.borderPadding;
+ } else {
+ padding = MarkerManager.DEFAULT_BORDER_PADDING_;
+ }
+ // The padding in pixels beyond the viewport, where we will pre-load markers.
+ me.swPadding_ = new google.maps.Size(-padding, padding);
+ me.nePadding_ = new google.maps.Size(padding, -padding);
+ me.borderPadding_ = padding;
+
+ me.gridWidth_ = {};
+
+ me.grid_ = {};
+ me.grid_[me.maxZoom_] = {};
+ me.numMarkers_ = {};
+ me.numMarkers_[me.maxZoom_] = 0;
+
+
+ google.maps.event.addListener(map, 'dragend', function () {
+ me.onMapMoveEnd_();
+ });
+ google.maps.event.addListener(map, 'zoom_changed', function () {
+ me.onMapMoveEnd_();
+ });
+
+
+
+ /**
+ * This closure provide easy access to the map.
+ * They are used as callbacks, not as methods.
+ * @param GMarker marker Marker to be removed from the map
+ * @private
+ */
+ me.removeOverlay_ = function (marker) {
+ marker.setMap(null);
+ me.shownMarkers_--;
+ };
+
+ /**
+ * This closure provide easy access to the map.
+ * They are used as callbacks, not as methods.
+ * @param GMarker marker Marker to be added to the map
+ * @private
+ */
+ me.addOverlay_ = function (marker) {
+ if (me.show_) {
+ marker.setMap(me.map_);
+ me.shownMarkers_++;
+ }
+ };
+
+ me.resetManager_();
+ me.shownMarkers_ = 0;
+
+ me.shownBounds_ = me.getMapGridBounds_();
+
+ google.maps.event.trigger(me, 'loaded');
+
+};
+
+/**
+ * Default tile size used for deviding the map into a grid.
+ */
+MarkerManager.DEFAULT_TILE_SIZE_ = 1024;
+
+/*
+ * How much extra space to show around the map border so
+ * dragging doesn't result in an empty place.
+ */
+MarkerManager.DEFAULT_BORDER_PADDING_ = 100;
+
+/**
+ * Default tilesize of single tile world.
+ */
+MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE = 256;
+
+
+/**
+ * Initializes MarkerManager arrays for all zoom levels
+ * Called by constructor and by clearAllMarkers
+ */
+MarkerManager.prototype.resetManager_ = function () {
+ var mapWidth = MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE;
+ for (var zoom = 0; zoom <= this.maxZoom_; ++zoom) {
+ this.grid_[zoom] = {};
+ this.numMarkers_[zoom] = 0;
+ this.gridWidth_[zoom] = Math.ceil(mapWidth / this.tileSize_);
+ mapWidth <<= 1;
+ }
+
+};
+
+/**
+ * Removes all markers in the manager, and
+ * removes any visible markers from the map.
+ */
+MarkerManager.prototype.clearMarkers = function () {
+ this.processAll_(this.shownBounds_, this.removeOverlay_);
+ this.resetManager_();
+};
+
+
+/**
+ * Gets the tile coordinate for a given latlng point.
+ *
+ * @param {LatLng} latlng The geographical point.
+ * @param {Number} zoom The zoom level.
+ * @param {google.maps.Size} padding The padding used to shift the pixel coordinate.
+ * Used for expanding a bounds to include an extra padding
+ * of pixels surrounding the bounds.
+ * @return {GPoint} The point in tile coordinates.
+ *
+ */
+MarkerManager.prototype.getTilePoint_ = function (latlng, zoom, padding) {
+
+ var pixelPoint = this.projectionHelper_.LatLngToPixel(latlng, zoom);
+
+ var point = new google.maps.Point(
+ Math.floor((pixelPoint.x + padding.width) / this.tileSize_),
+ Math.floor((pixelPoint.y + padding.height) / this.tileSize_)
+ );
+
+ return point;
+};
+
+
+/**
+ * Finds the appropriate place to add the marker to the grid.
+ * Optimized for speed; does not actually add the marker to the map.
+ * Designed for batch-processing thousands of markers.
+ *
+ * @param {Marker} marker The marker to add.
+ * @param {Number} minZoom The minimum zoom for displaying the marker.
+ * @param {Number} maxZoom The maximum zoom for displaying the marker.
+ */
+MarkerManager.prototype.addMarkerBatch_ = function (marker, minZoom, maxZoom) {
+ var me = this;
+
+ var mPoint = marker.getPosition();
+ marker.MarkerManager_minZoom = minZoom;
+
+
+ // Tracking markers is expensive, so we do this only if the
+ // user explicitly requested it when creating marker manager.
+ if (this.trackMarkers_) {
+ google.maps.event.addListener(marker, 'changed', function (a, b, c) {
+ me.onMarkerMoved_(a, b, c);
+ });
+ }
+
+ var gridPoint = this.getTilePoint_(mPoint, maxZoom, new google.maps.Size(0, 0, 0, 0));
+
+ for (var zoom = maxZoom; zoom >= minZoom; zoom--) {
+ var cell = this.getGridCellCreate_(gridPoint.x, gridPoint.y, zoom);
+ cell.push(marker);
+
+ gridPoint.x = gridPoint.x >> 1;
+ gridPoint.y = gridPoint.y >> 1;
+ }
+};
+
+
+/**
+ * Returns whether or not the given point is visible in the shown bounds. This
+ * is a helper method that takes care of the corner case, when shownBounds have
+ * negative minX value.
+ *
+ * @param {Point} point a point on a grid.
+ * @return {Boolean} Whether or not the given point is visible in the currently
+ * shown bounds.
+ */
+MarkerManager.prototype.isGridPointVisible_ = function (point) {
+ var vertical = this.shownBounds_.minY <= point.y &&
+ point.y <= this.shownBounds_.maxY;
+ var minX = this.shownBounds_.minX;
+ var horizontal = minX <= point.x && point.x <= this.shownBounds_.maxX;
+ if (!horizontal && minX < 0) {
+ // Shifts the negative part of the rectangle. As point.x is always less
+ // than grid width, only test shifted minX .. 0 part of the shown bounds.
+ var width = this.gridWidth_[this.shownBounds_.z];
+ horizontal = minX + width <= point.x && point.x <= width - 1;
+ }
+ return vertical && horizontal;
+};
+
+
+/**
+ * Reacts to a notification from a marker that it has moved to a new location.
+ * It scans the grid all all zoom levels and moves the marker from the old grid
+ * location to a new grid location.
+ *
+ * @param {Marker} marker The marker that moved.
+ * @param {LatLng} oldPoint The old position of the marker.
+ * @param {LatLng} newPoint The new position of the marker.
+ */
+MarkerManager.prototype.onMarkerMoved_ = function (marker, oldPoint, newPoint) {
+ // NOTE: We do not know the minimum or maximum zoom the marker was
+ // added at, so we start at the absolute maximum. Whenever we successfully
+ // remove a marker at a given zoom, we add it at the new grid coordinates.
+ var zoom = this.maxZoom_;
+ var changed = false;
+ var oldGrid = this.getTilePoint_(oldPoint, zoom, new google.maps.Size(0, 0, 0, 0));
+ var newGrid = this.getTilePoint_(newPoint, zoom, new google.maps.Size(0, 0, 0, 0));
+ while (zoom >= 0 && (oldGrid.x !== newGrid.x || oldGrid.y !== newGrid.y)) {
+ var cell = this.getGridCellNoCreate_(oldGrid.x, oldGrid.y, zoom);
+ if (cell) {
+ if (this.removeFromArray_(cell, marker)) {
+ this.getGridCellCreate_(newGrid.x, newGrid.y, zoom).push(marker);
+ }
+ }
+ // For the current zoom we also need to update the map. Markers that no
+ // longer are visible are removed from the map. Markers that moved into
+ // the shown bounds are added to the map. This also lets us keep the count
+ // of visible markers up to date.
+ if (zoom === this.mapZoom_) {
+ if (this.isGridPointVisible_(oldGrid)) {
+ if (!this.isGridPointVisible_(newGrid)) {
+ this.removeOverlay_(marker);
+ changed = true;
+ }
+ } else {
+ if (this.isGridPointVisible_(newGrid)) {
+ this.addOverlay_(marker);
+ changed = true;
+ }
+ }
+ }
+ oldGrid.x = oldGrid.x >> 1;
+ oldGrid.y = oldGrid.y >> 1;
+ newGrid.x = newGrid.x >> 1;
+ newGrid.y = newGrid.y >> 1;
+ --zoom;
+ }
+ if (changed) {
+ this.notifyListeners_();
+ }
+};
+
+
+/**
+ * Removes marker from the manager and from the map
+ * (if it's currently visible).
+ * @param {GMarker} marker The marker to delete.
+ */
+MarkerManager.prototype.removeMarker = function (marker) {
+ var zoom = this.maxZoom_;
+ var changed = false;
+ var point = marker.getPosition();
+ var grid = this.getTilePoint_(point, zoom, new google.maps.Size(0, 0, 0, 0));
+ while (zoom >= 0) {
+ var cell = this.getGridCellNoCreate_(grid.x, grid.y, zoom);
+
+ if (cell) {
+ this.removeFromArray_(cell, marker);
+ }
+ // For the current zoom we also need to update the map. Markers that no
+ // longer are visible are removed from the map. This also lets us keep the count
+ // of visible markers up to date.
+ if (zoom === this.mapZoom_) {
+ if (this.isGridPointVisible_(grid)) {
+ this.removeOverlay_(marker);
+ changed = true;
+ }
+ }
+ grid.x = grid.x >> 1;
+ grid.y = grid.y >> 1;
+ --zoom;
+ }
+ if (changed) {
+ this.notifyListeners_();
+ }
+ this.numMarkers_[marker.MarkerManager_minZoom]--;
+};
+
+
+/**
+ * Add many markers at once.
+ * Does not actually update the map, just the internal grid.
+ *
+ * @param {Array of Marker} markers The markers to add.
+ * @param {Number} minZoom The minimum zoom level to display the markers.
+ * @param {Number} opt_maxZoom The maximum zoom level to display the markers.
+ */
+MarkerManager.prototype.addMarkers = function (markers, minZoom, opt_maxZoom) {
+ var maxZoom = this.getOptMaxZoom_(opt_maxZoom);
+ for (var i = markers.length - 1; i >= 0; i--) {
+ this.addMarkerBatch_(markers[i], minZoom, maxZoom);
+ }
+
+ this.numMarkers_[minZoom] += markers.length;
+};
+
+
+/**
+ * Returns the value of the optional maximum zoom. This method is defined so
+ * that we have just one place where optional maximum zoom is calculated.
+ *
+ * @param {Number} opt_maxZoom The optinal maximum zoom.
+ * @return The maximum zoom.
+ */
+MarkerManager.prototype.getOptMaxZoom_ = function (opt_maxZoom) {
+ return opt_maxZoom || this.maxZoom_;
+};
+
+
+/**
+ * Calculates the total number of markers potentially visible at a given
+ * zoom level.
+ *
+ * @param {Number} zoom The zoom level to check.
+ */
+MarkerManager.prototype.getMarkerCount = function (zoom) {
+ var total = 0;
+ for (var z = 0; z <= zoom; z++) {
+ total += this.numMarkers_[z];
+ }
+ return total;
+};
+
+/**
+ * Returns a marker given latitude, longitude and zoom. If the marker does not
+ * exist, the method will return a new marker. If a new marker is created,
+ * it will NOT be added to the manager.
+ *
+ * @param {Number} lat - the latitude of a marker.
+ * @param {Number} lng - the longitude of a marker.
+ * @param {Number} zoom - the zoom level
+ * @return {GMarker} marker - the marker found at lat and lng
+ */
+MarkerManager.prototype.getMarker = function (lat, lng, zoom) {
+ var mPoint = new google.maps.LatLng(lat, lng);
+ var gridPoint = this.getTilePoint_(mPoint, zoom, new google.maps.Size(0, 0, 0, 0));
+
+ var marker = new google.maps.Marker({position: mPoint});
+
+ var cellArray = this.getGridCellNoCreate_(gridPoint.x, gridPoint.y, zoom);
+ if (cellArray !== undefined) {
+ for (var i = 0; i < cellArray.length; i++)
+ {
+ if (lat === cellArray[i].getLatLng().lat() && lng === cellArray[i].getLatLng().lng()) {
+ marker = cellArray[i];
+ }
+ }
+ }
+ return marker;
+};
+
+/**
+ * Add a single marker to the map.
+ *
+ * @param {Marker} marker The marker to add.
+ * @param {Number} minZoom The minimum zoom level to display the marker.
+ * @param {Number} opt_maxZoom The maximum zoom level to display the marker.
+ */
+MarkerManager.prototype.addMarker = function (marker, minZoom, opt_maxZoom) {
+ var maxZoom = this.getOptMaxZoom_(opt_maxZoom);
+ this.addMarkerBatch_(marker, minZoom, maxZoom);
+ var gridPoint = this.getTilePoint_(marker.getPosition(), this.mapZoom_, new google.maps.Size(0, 0, 0, 0));
+ if (this.isGridPointVisible_(gridPoint) &&
+ minZoom <= this.shownBounds_.z &&
+ this.shownBounds_.z <= maxZoom) {
+ this.addOverlay_(marker);
+ this.notifyListeners_();
+ }
+ this.numMarkers_[minZoom]++;
+};
+
+
+/**
+ * Helper class to create a bounds of INT ranges.
+ * @param bounds Array.<Object.<string, number>> Bounds object.
+ * @constructor
+ */
+function GridBounds(bounds) {
+ // [sw, ne]
+
+ this.minX = Math.min(bounds[0].x, bounds[1].x);
+ this.maxX = Math.max(bounds[0].x, bounds[1].x);
+ this.minY = Math.min(bounds[0].y, bounds[1].y);
+ this.maxY = Math.max(bounds[0].y, bounds[1].y);
+
+}
+
+/**
+ * Returns true if this bounds equal the given bounds.
+ * @param {GridBounds} gridBounds GridBounds The bounds to test.
+ * @return {Boolean} This Bounds equals the given GridBounds.
+ */
+GridBounds.prototype.equals = function (gridBounds) {
+ if (this.maxX === gridBounds.maxX && this.maxY === gridBounds.maxY && this.minX === gridBounds.minX && this.minY === gridBounds.minY) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+/**
+ * Returns true if this bounds (inclusively) contains the given point.
+ * @param {Point} point The point to test.
+ * @return {Boolean} This Bounds contains the given Point.
+ */
+GridBounds.prototype.containsPoint = function (point) {
+ var outer = this;
+ return (outer.minX <= point.x && outer.maxX >= point.x && outer.minY <= point.y && outer.maxY >= point.y);
+};
+
+/**
+ * Get a cell in the grid, creating it first if necessary.
+ *
+ * Optimization candidate
+ *
+ * @param {Number} x The x coordinate of the cell.
+ * @param {Number} y The y coordinate of the cell.
+ * @param {Number} z The z coordinate of the cell.
+ * @return {Array} The cell in the array.
+ */
+MarkerManager.prototype.getGridCellCreate_ = function (x, y, z) {
+ var grid = this.grid_[z];
+ if (x < 0) {
+ x += this.gridWidth_[z];
+ }
+ var gridCol = grid[x];
+ if (!gridCol) {
+ gridCol = grid[x] = [];
+ return (gridCol[y] = []);
+ }
+ var gridCell = gridCol[y];
+ if (!gridCell) {
+ return (gridCol[y] = []);
+ }
+ return gridCell;
+};
+
+
+/**
+ * Get a cell in the grid, returning undefined if it does not exist.
+ *
+ * NOTE: Optimized for speed -- otherwise could combine with getGridCellCreate_.
+ *
+ * @param {Number} x The x coordinate of the cell.
+ * @param {Number} y The y coordinate of the cell.
+ * @param {Number} z The z coordinate of the cell.
+ * @return {Array} The cell in the array.
+ */
+MarkerManager.prototype.getGridCellNoCreate_ = function (x, y, z) {
+ var grid = this.grid_[z];
+
+ if (x < 0) {
+ x += this.gridWidth_[z];
+ }
+ var gridCol = grid[x];
+ return gridCol ? gridCol[y] : undefined;
+};
+
+
+/**
+ * Turns at geographical bounds into a grid-space bounds.
+ *
+ * @param {LatLngBounds} bounds The geographical bounds.
+ * @param {Number} zoom The zoom level of the bounds.
+ * @param {google.maps.Size} swPadding The padding in pixels to extend beyond the
+ * given bounds.
+ * @param {google.maps.Size} nePadding The padding in pixels to extend beyond the
+ * given bounds.
+ * @return {GridBounds} The bounds in grid space.
+ */
+MarkerManager.prototype.getGridBounds_ = function (bounds, zoom, swPadding, nePadding) {
+ zoom = Math.min(zoom, this.maxZoom_);
+
+ var bl = bounds.getSouthWest();
+ var tr = bounds.getNorthEast();
+ var sw = this.getTilePoint_(bl, zoom, swPadding);
+
+ var ne = this.getTilePoint_(tr, zoom, nePadding);
+ var gw = this.gridWidth_[zoom];
+
+ // Crossing the prime meridian requires correction of bounds.
+ if (tr.lng() < bl.lng() || ne.x < sw.x) {
+ sw.x -= gw;
+ }
+ if (ne.x - sw.x + 1 >= gw) {
+ // Computed grid bounds are larger than the world; truncate.
+ sw.x = 0;
+ ne.x = gw - 1;
+ }
+
+ var gridBounds = new GridBounds([sw, ne]);
+ gridBounds.z = zoom;
+
+ return gridBounds;
+};
+
+
+/**
+ * Gets the grid-space bounds for the current map viewport.
+ *
+ * @return {Bounds} The bounds in grid space.
+ */
+MarkerManager.prototype.getMapGridBounds_ = function () {
+ return this.getGridBounds_(this.map_.getBounds(), this.mapZoom_, this.swPadding_, this.nePadding_);
+};
+
+
+/**
+ * Event listener for map:movend.
+ * NOTE: Use a timeout so that the user is not blocked
+ * from moving the map.
+ *
+ * Removed this because a a lack of a scopy override/callback function on events.
+ */
+MarkerManager.prototype.onMapMoveEnd_ = function () {
+ this.objectSetTimeout_(this, this.updateMarkers_, 0);
+};
+
+
+/**
+ * Call a function or evaluate an expression after a specified number of
+ * milliseconds.
+ *
+ * Equivalent to the standard window.setTimeout function, but the given
+ * function executes as a method of this instance. So the function passed to
+ * objectSetTimeout can contain references to this.
+ * objectSetTimeout(this, function () { alert(this.x) }, 1000);
+ *
+ * @param {Object} object The target object.
+ * @param {Function} command The command to run.
+ * @param {Number} milliseconds The delay.
+ * @return {Boolean} Success.
+ */
+MarkerManager.prototype.objectSetTimeout_ = function (object, command, milliseconds) {
+ return window.setTimeout(function () {
+ command.call(object);
+ }, milliseconds);
+};
+
+
+/**
+ * Is this layer visible?
+ *
+ * Returns visibility setting
+ *
+ * @return {Boolean} Visible
+ */
+MarkerManager.prototype.visible = function () {
+ return this.show_ ? true : false;
+};
+
+
+/**
+ * Returns true if the manager is hidden.
+ * Otherwise returns false.
+ * @return {Boolean} Hidden
+ */
+MarkerManager.prototype.isHidden = function () {
+ return !this.show_;
+};
+
+
+/**
+ * Shows the manager if it's currently hidden.
+ */
+MarkerManager.prototype.show = function () {
+ this.show_ = true;
+ this.refresh();
+};
+
+
+/**
+ * Hides the manager if it's currently visible
+ */
+MarkerManager.prototype.hide = function () {
+ this.show_ = false;
+ this.refresh();
+};
+
+
+/**
+ * Toggles the visibility of the manager.
+ */
+MarkerManager.prototype.toggle = function () {
+ this.show_ = !this.show_;
+ this.refresh();
+};
+
+
+/**
+ * Refresh forces the marker-manager into a good state.
+ * <ol>
+ * <li>If never before initialized, shows all the markers.</li>
+ * <li>If previously initialized, removes and re-adds all markers.</li>
+ * </ol>
+ */
+MarkerManager.prototype.refresh = function () {
+ if (this.shownMarkers_ > 0) {
+ this.processAll_(this.shownBounds_, this.removeOverlay_);
+ }
+ // An extra check on this.show_ to increase performance (no need to processAll_)
+ if (this.show_) {
+ this.processAll_(this.shownBounds_, this.addOverlay_);
+ }
+ this.notifyListeners_();
+};
+
+
+/**
+ * After the viewport may have changed, add or remove markers as needed.
+ */
+MarkerManager.prototype.updateMarkers_ = function () {
+ this.mapZoom_ = this.map_.getZoom();
+ var newBounds = this.getMapGridBounds_();
+
+ // If the move does not include new grid sections,
+ // we have no work to do:
+ if (newBounds.equals(this.shownBounds_) && newBounds.z === this.shownBounds_.z) {
+ return;
+ }
+
+ if (newBounds.z !== this.shownBounds_.z) {
+ this.processAll_(this.shownBounds_, this.removeOverlay_);
+ if (this.show_) { // performance
+ this.processAll_(newBounds, this.addOverlay_);
+ }
+ } else {
+ // Remove markers:
+ this.rectangleDiff_(this.shownBounds_, newBounds, this.removeCellMarkers_);
+
+ // Add markers:
+ if (this.show_) { // performance
+ this.rectangleDiff_(newBounds, this.shownBounds_, this.addCellMarkers_);
+ }
+ }
+ this.shownBounds_ = newBounds;
+
+ this.notifyListeners_();
+};
+
+
+/**
+ * Notify listeners when the state of what is displayed changes.
+ */
+MarkerManager.prototype.notifyListeners_ = function () {
+ google.maps.event.trigger(this, 'changed', this.shownBounds_, this.shownMarkers_);
+};
+
+
+/**
+ * Process all markers in the bounds provided, using a callback.
+ *
+ * @param {Bounds} bounds The bounds in grid space.
+ * @param {Function} callback The function to call for each marker.
+ */
+MarkerManager.prototype.processAll_ = function (bounds, callback) {
+ for (var x = bounds.minX; x <= bounds.maxX; x++) {
+ for (var y = bounds.minY; y <= bounds.maxY; y++) {
+ this.processCellMarkers_(x, y, bounds.z, callback);
+ }
+ }
+};
+
+
+/**
+ * Process all markers in the grid cell, using a callback.
+ *
+ * @param {Number} x The x coordinate of the cell.
+ * @param {Number} y The y coordinate of the cell.
+ * @param {Number} z The z coordinate of the cell.
+ * @param {Function} callback The function to call for each marker.
+ */
+MarkerManager.prototype.processCellMarkers_ = function (x, y, z, callback) {
+ var cell = this.getGridCellNoCreate_(x, y, z);
+ if (cell) {
+ for (var i = cell.length - 1; i >= 0; i--) {
+ callback(cell[i]);
+ }
+ }
+};
+
+
+/**
+ * Remove all markers in a grid cell.
+ *
+ * @param {Number} x The x coordinate of the cell.
+ * @param {Number} y The y coordinate of the cell.
+ * @param {Number} z The z coordinate of the cell.
+ */
+MarkerManager.prototype.removeCellMarkers_ = function (x, y, z) {
+ this.processCellMarkers_(x, y, z, this.removeOverlay_);
+};
+
+
+/**
+ * Add all markers in a grid cell.
+ *
+ * @param {Number} x The x coordinate of the cell.
+ * @param {Number} y The y coordinate of the cell.
+ * @param {Number} z The z coordinate of the cell.
+ */
+MarkerManager.prototype.addCellMarkers_ = function (x, y, z) {
+ this.processCellMarkers_(x, y, z, this.addOverlay_);
+};
+
+
+/**
+ * Use the rectangleDiffCoords_ function to process all grid cells
+ * that are in bounds1 but not bounds2, using a callback, and using
+ * the current MarkerManager object as the instance.
+ *
+ * Pass the z parameter to the callback in addition to x and y.
+ *
+ * @param {Bounds} bounds1 The bounds of all points we may process.
+ * @param {Bounds} bounds2 The bounds of points to exclude.
+ * @param {Function} callback The callback function to call
+ * for each grid coordinate (x, y, z).
+ */
+MarkerManager.prototype.rectangleDiff_ = function (bounds1, bounds2, callback) {
+ var me = this;
+ me.rectangleDiffCoords_(bounds1, bounds2, function (x, y) {
+ callback.apply(me, [x, y, bounds1.z]);
+ });
+};
+
+
+/**
+ * Calls the function for all points in bounds1, not in bounds2
+ *
+ * @param {Bounds} bounds1 The bounds of all points we may process.
+ * @param {Bounds} bounds2 The bounds of points to exclude.
+ * @param {Function} callback The callback function to call
+ * for each grid coordinate.
+ */
+MarkerManager.prototype.rectangleDiffCoords_ = function (bounds1, bounds2, callback) {
+ var minX1 = bounds1.minX;
+ var minY1 = bounds1.minY;
+ var maxX1 = bounds1.maxX;
+ var maxY1 = bounds1.maxY;
+ var minX2 = bounds2.minX;
+ var minY2 = bounds2.minY;
+ var maxX2 = bounds2.maxX;
+ var maxY2 = bounds2.maxY;
+
+ var x, y;
+ for (x = minX1; x <= maxX1; x++) { // All x in R1
+ // All above:
+ for (y = minY1; y <= maxY1 && y < minY2; y++) { // y in R1 above R2
+ callback(x, y);
+ }
+ // All below:
+ for (y = Math.max(maxY2 + 1, minY1); // y in R1 below R2
+ y <= maxY1; y++) {
+ callback(x, y);
+ }
+ }
+
+ for (y = Math.max(minY1, minY2);
+ y <= Math.min(maxY1, maxY2); y++) { // All y in R2 and in R1
+ // Strictly left:
+ for (x = Math.min(maxX1 + 1, minX2) - 1;
+ x >= minX1; x--) { // x in R1 left of R2
+ callback(x, y);
+ }
+ // Strictly right:
+ for (x = Math.max(minX1, maxX2 + 1); // x in R1 right of R2
+ x <= maxX1; x++) {
+ callback(x, y);
+ }
+ }
+};
+
+
+/**
+ * Removes value from array. O(N).
+ *
+ * @param {Array} array The array to modify.
+ * @param {any} value The value to remove.
+ * @param {Boolean} opt_notype Flag to disable type checking in equality.
+ * @return {Number} The number of instances of value that were removed.
+ */
+MarkerManager.prototype.removeFromArray_ = function (array, value, opt_notype) {
+ var shift = 0;
+ for (var i = 0; i < array.length; ++i) {
+ if (array[i] === value || (opt_notype && array[i] === value)) {
+ array.splice(i--, 1);
+ shift++;
+ }
+ }
+ return shift;
+};
+
+
+
+
+
+
+
+/**
+* Projection overlay helper. Helps in calculating
+* that markers get into the right grid.
+* @constructor
+* @param {Map} map The map to manage.
+**/
+function ProjectionHelperOverlay(map) {
+
+ this.setMap(map);
+
+ var TILEFACTOR = 8;
+ var TILESIDE = 1 << TILEFACTOR;
+ var RADIUS = 7;
+
+ this._map = map;
+ this._zoom = -1;
+ this._X0 =
+ this._Y0 =
+ this._X1 =
+ this._Y1 = -1;
+
+
+}
+if (typeof(google) != 'undefined' && google.maps) { // make sure it exists -- amalo
+ProjectionHelperOverlay.prototype = new google.maps.OverlayView();
+}
+
+/**
+ * Helper function to convert Lng to X
+ * @private
+ * @param {float} lng
+ **/
+ProjectionHelperOverlay.prototype.LngToX_ = function (lng) {
+ return (1 + lng / 180);
+};
+
+/**
+ * Helper function to convert Lat to Y
+ * @private
+ * @param {float} lat
+ **/
+ProjectionHelperOverlay.prototype.LatToY_ = function (lat) {
+ var sinofphi = Math.sin(lat * Math.PI / 180);
+ return (1 - 0.5 / Math.PI * Math.log((1 + sinofphi) / (1 - sinofphi)));
+};
+
+/**
+* Old school LatLngToPixel
+* @param {LatLng} latlng google.maps.LatLng object
+* @param {Number} zoom Zoom level
+* @return {position} {x: pixelPositionX, y: pixelPositionY}
+**/
+ProjectionHelperOverlay.prototype.LatLngToPixel = function (latlng, zoom) {
+ var map = this._map;
+ var div = this.getProjection().fromLatLngToDivPixel(latlng);
+ var abs = {x: ~~(0.5 + this.LngToX_(latlng.lng()) * (2 << (zoom + 6))), y: ~~(0.5 + this.LatToY_(latlng.lat()) * (2 << (zoom + 6)))};
+ return abs;
+};
+
+
+/**
+ * Draw function only triggers a ready event for
+ * MarkerManager to know projection can proceed to
+ * initialize.
+ */
+ProjectionHelperOverlay.prototype.draw = function () {
+ if (!this.ready) {
+ this.ready = true;
+ google.maps.event.trigger(this, 'ready');
+ }
+};
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/write.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/write.py
new file mode 100644
index 00000000000..e91c3d073b1
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/bench/write.py
@@ -0,0 +1,345 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+r"""
+=========================
+ Write benchmark results
+=========================
+
+Write benchmark results.
+
+:Copyright:
+
+ Copyright 2014 - 2015
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+Usage::
+
+ python -mbench.write [-p plain] [-t table] <pickled
+
+ -p plain Plain file to write to (like docs/BENCHMARKS).
+ -t table Table file to write to (like docs/_userdoc/benchmark.txt).
+
+"""
+if __doc__:
+ __doc__ = __doc__.encode('ascii').decode('unicode_escape')
+__author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
+__docformat__ = "restructuredtext en"
+__license__ = "Apache License, Version 2.0"
+__version__ = "1.0.0"
+
+import os as _os
+import re as _re
+import sys as _sys
+
+
+try:
+ unicode
+except NameError:
+ def uni(v):
+ if hasattr(v, 'decode'):
+ return v.decode('latin-1')
+ return str(v)
+else:
+ def uni(v):
+ if isinstance(v, unicode):
+ return v.encode('utf-8')
+ return str(v)
+
+
+def write_table(filename, results):
+ """
+ Output tabled benchmark results
+
+ :Parameters:
+ `filename` : ``str``
+ Filename to write to
+
+ `results` : ``list``
+ Results
+ """
+ try:
+ next
+ except NameError:
+ next = lambda i: (getattr(i, 'next', None) or i.__next__)()
+ try:
+ cmp
+ except NameError:
+ cmp = lambda a, b: (a > b) - (a < b)
+
+ names = [
+ ('simple_port', 'Simple Port'),
+ ('jsmin_2_0_9', 'jsmin 2.0.9'),
+ ('rjsmin', '|rjsmin|'),
+ ('_rjsmin', r'_\ |rjsmin|'),
+ ]
+ benched_per_table = 2
+
+ results = sorted(results, reverse=True)
+
+ # First we transform our data into a table (list of lists)
+ pythons, widths = [], [0] * (benched_per_table + 1)
+ last_version = None
+ for version, _, result in results:
+ version = uni(version)
+ if not(last_version is None or version.startswith('2.')):
+ continue
+ last_version = version
+
+ namesub = _re.compile(r'(?:-\d+(?:\.\d+)*)?\.js$').sub
+ result = iter(result)
+ tables = []
+
+ # given our data it's easier to create the table transposed...
+ for benched in result:
+ rows = [['Name'] + [desc for _, desc in names]]
+ for _ in range(benched_per_table):
+ if _:
+ try:
+ benched = next(result)
+ except StopIteration:
+ rows.append([''] + ['' for _ in names])
+ continue
+
+ times = dict((
+ uni(port), (time, benched['sizes'][idx])
+ ) for idx, (port, time) in enumerate(benched['times']))
+ columns = ['%s (%.1f)' % (
+ namesub('', _os.path.basename(uni(benched['filename']))),
+ benched['size'] / 1024.0,
+ )]
+ for idx, (port, _) in enumerate(names):
+ if port not in times:
+ columns.append('n/a')
+ continue
+ time, size = times[port]
+ if time is None:
+ columns.append('(failed)')
+ continue
+ columns.append('%s%.2f ms (%.1f %s)' % (
+ idx == 0 and ' ' or '',
+ time,
+ size / 1024.0,
+ idx == 0 and '\\*' or ['=', '>', '<'][
+ cmp(size, benched['sizes'][0])
+ ],
+ ))
+ rows.append(columns)
+
+ # calculate column widths (global for all tables)
+ for idx, row in enumerate(rows):
+ widths[idx] = max(widths[idx], max(map(len, row)))
+
+ # ... and transpose it back.
+ tables.append(zip(*rows))
+ pythons.append((version, tables))
+
+ if last_version.startswith('2.'):
+ break
+
+ # Second we create a rest table from it
+ lines = []
+ separator = lambda c='-': '+'.join([''] + [
+ c * (width + 2) for width in widths
+ ] + [''])
+
+ for idx, (version, tables) in enumerate(pythons):
+ if idx:
+ lines.append('')
+ lines.append('')
+
+ line = 'Python %s' % (version,)
+ lines.append(line)
+ lines.append('~' * len(line))
+
+ for table in tables:
+ lines.append('')
+ lines.append('.. rst-class:: benchmark')
+ lines.append('')
+
+ for idx, row in enumerate(table):
+ if idx == 0:
+ # header
+ lines.append(separator())
+ lines.append('|'.join([''] + [
+ ' %s%*s ' % (col, len(col) - width, '')
+ for width, col in zip(widths, row)
+ ] + ['']))
+ lines.append(separator('='))
+ else: # data
+ lines.append('|'.join([''] + [
+ j == 0 and (
+ ' %s%*s ' % (col, len(col) - widths[j], '')
+ ) or (
+ ['%*s ', ' %*s '][idx == 1] % (widths[j], col)
+ )
+ for j, col in enumerate(row)
+ ] + ['']))
+ lines.append(separator())
+
+ fplines = []
+ fp = open(filename)
+ try:
+ fpiter = iter(fp)
+ for line in fpiter:
+ line = line.rstrip()
+ if line == '.. begin tables':
+ buf = []
+ for line in fpiter:
+ line = line.rstrip()
+ if line == '.. end tables':
+ fplines.append('.. begin tables')
+ fplines.append('')
+ fplines.extend(lines)
+ fplines.append('')
+ fplines.append('.. end tables')
+ buf = []
+ break
+ else:
+ buf.append(line)
+ else:
+ fplines.extend(buf)
+ _sys.stderr.write("Placeholder container not found!\n")
+ else:
+ fplines.append(line)
+ finally:
+ fp.close()
+
+ fp = open(filename, 'w')
+ try:
+ fp.write('\n'.join(fplines) + '\n')
+ finally:
+ fp.close()
+
+
+def write_plain(filename, results):
+ """
+ Output plain benchmark results
+
+ :Parameters:
+ `filename` : ``str``
+ Filename to write to
+
+ `results` : ``list``
+ Results
+ """
+ lines = []
+ results = sorted(results, reverse=True)
+ for idx, (version, import_notes, result) in enumerate(results):
+ if idx:
+ lines.append('')
+ lines.append('')
+
+ lines.append('$ python%s -OO bench/main.py bench/*.js' % (
+ '.'.join(version.split('.')[:2])
+ ))
+ lines.append('~' * 72)
+ for note in import_notes:
+ lines.append(uni(note))
+ lines.append('Python Release: %s' % (version,))
+
+ for single in result:
+ lines.append('')
+ lines.append('Benchmarking %r... (%.1f KiB)' % (
+ uni(single['filename']), single['size'] / 1024.0
+ ))
+ for msg in single['messages']:
+ lines.append(msg)
+ times = []
+ space = max([len(uni(port)) for port, _ in single['times']])
+ for idx, (port, time) in enumerate(single['times']):
+ port = uni(port)
+ if time is None:
+ lines.append(" FAILED %s" % (port,))
+ else:
+ times.append(time)
+ lines.append(
+ " Timing %s%s ... (%5.1f KiB %s) %8.2f ms" % (
+ port,
+ " " * (space - len(port)),
+ single['sizes'][idx] / 1024.0,
+ idx == 0 and '*' or ['=', '>', '<'][
+ cmp(single['sizes'][idx], single['sizes'][0])
+ ],
+ time
+ )
+ )
+ if len(times) > 1:
+ lines[-1] += " (factor: %s)" % (', '.join([
+ '%.2f' % (timed / time) for timed in times[:-1]
+ ]))
+
+ lines.append('')
+ lines.append('')
+ lines.append('# vim: nowrap')
+ fp = open(filename, 'w')
+ try:
+ fp.write('\n'.join(lines) + '\n')
+ finally:
+ fp.close()
+
+
+def main(argv=None):
+ """ Main """
+ import getopt as _getopt
+ import pickle as _pickle
+
+ if argv is None:
+ argv = _sys.argv[1:]
+ try:
+ opts, args = _getopt.getopt(argv, "hp:t:", ["help"])
+ except getopt.GetoptError:
+ e = _sys.exc_info()[0](_sys.exc_info()[1])
+ print >> _sys.stderr, "%s\nTry %s -mbench.write --help" % (
+ e,
+ _os.path.basename(_sys.executable),
+ )
+ _sys.exit(2)
+
+ plain, table = None, None
+ for key, value in opts:
+ if key in ("-h", "--help"):
+ print >> _sys.stderr, (
+ "%s -mbench.write [-p plain] [-t table] <pickled" % (
+ _os.path.basename(_sys.executable),
+ )
+ )
+ _sys.exit(0)
+ elif key == '-p':
+ plain = str(value)
+ elif key == '-t':
+ table = str(value)
+
+ struct = []
+ _sys.stdin = getattr(_sys.stdin, 'detach', lambda: _sys.stdin)()
+ try:
+ while True:
+ version, import_notes, result = _pickle.load(_sys.stdin)
+ if hasattr(version, 'decode'):
+ version = version.decode('latin-1')
+ struct.append((version, import_notes, result))
+ except EOFError:
+ pass
+
+ if plain:
+ write_plain(plain, struct)
+
+ if table:
+ write_table(table, struct)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/BENCHMARKS b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/BENCHMARKS
new file mode 100644
index 00000000000..00fbc90f301
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/BENCHMARKS
@@ -0,0 +1,165 @@
+$ python3.5 -OO bench/main.py bench/*.js
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python Release: 3.5.0
+
+Benchmarking 'bench/apiviewer.js'... (953.2 KiB)
+ Timing simple_port ... (951.5 KiB *) 1417.14 ms
+ Timing jsmin_2_0_9 ... (951.5 KiB >) 1682.43 ms (factor: 0.84)
+ Timing rjsmin ... (951.5 KiB =) 36.38 ms (factor: 38.95, 46.25)
+ Timing _rjsmin ... (951.5 KiB =) 1.81 ms (factor: 783.54, 930.22, 20.11)
+
+Benchmarking 'bench/bootstrap.js'... (49.0 KiB)
+ Timing simple_port ... ( 26.4 KiB *) 58.49 ms
+ Timing jsmin_2_0_9 ... ( 26.4 KiB >) 23.18 ms (factor: 2.52)
+ Timing rjsmin ... ( 26.4 KiB >) 8.93 ms (factor: 6.55, 2.60)
+ Timing _rjsmin ... ( 26.4 KiB >) 0.13 ms (factor: 444.62, 176.25, 67.89)
+
+Benchmarking 'bench/DateTimeShortcuts.js'... (18.3 KiB)
+ Timing simple_port ... ( 10.2 KiB *) 21.83 ms
+ Timing jsmin_2_0_9 ... ( 10.3 KiB >) 8.87 ms (factor: 2.46)
+ Timing rjsmin ... ( 10.2 KiB >) 2.42 ms (factor: 9.03, 3.67)
+ Timing _rjsmin ... ( 10.2 KiB >) 0.05 ms (factor: 479.81, 194.97, 53.16)
+
+Benchmarking 'bench/jquery-1.7.1.js'... (242.4 KiB)
+ Timing simple_port ... (135.9 KiB *) 306.41 ms
+ Timing jsmin_2_0_9 ... (136.8 KiB >) 156.45 ms (factor: 1.96)
+ Timing rjsmin ... (135.9 KiB =) 61.57 ms (factor: 4.98, 2.54)
+ Timing _rjsmin ... (135.9 KiB =) 0.83 ms (factor: 368.52, 188.17, 74.05)
+
+Benchmarking 'bench/knockout-2.0.0.js'... (38.9 KiB)
+ Timing simple_port ... ( 38.6 KiB *) 56.58 ms
+ Timing jsmin_2_0_9 ... ( 38.6 KiB >) 25.53 ms (factor: 2.22)
+ Timing rjsmin ... ( 38.6 KiB >) 1.88 ms (factor: 30.11, 13.58)
+ Timing _rjsmin ... ( 38.6 KiB >) 0.08 ms (factor: 736.51, 332.27, 24.46)
+
+Benchmarking 'bench/markermanager.js'... (28.6 KiB)
+ Timing simple_port ... ( 11.6 KiB *) 28.61 ms
+ Timing jsmin_2_0_9 ... ( 11.6 KiB >) 11.74 ms (factor: 2.44)
+ Timing rjsmin ... ( 11.6 KiB =) 3.81 ms (factor: 7.51, 3.08)
+ Timing _rjsmin ... ( 11.6 KiB =) 0.06 ms (factor: 497.49, 204.19, 66.25)
+
+
+$ python3.4 -OO bench/main.py bench/*.js
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python Release: 3.4.3
+
+Benchmarking 'bench/apiviewer.js'... (953.2 KiB)
+ Timing simple_port ... (951.5 KiB *) 1486.02 ms
+ Timing jsmin_2_0_9 ... (951.5 KiB >) 1798.61 ms (factor: 0.83)
+ Timing rjsmin ... (951.5 KiB =) 37.49 ms (factor: 39.64, 47.98)
+ Timing _rjsmin ... (951.5 KiB =) 1.90 ms (factor: 780.39, 944.55, 19.69)
+
+Benchmarking 'bench/bootstrap.js'... (49.0 KiB)
+ Timing simple_port ... ( 26.4 KiB *) 63.29 ms
+ Timing jsmin_2_0_9 ... ( 26.4 KiB >) 27.47 ms (factor: 2.30)
+ Timing rjsmin ... ( 26.4 KiB >) 9.30 ms (factor: 6.80, 2.95)
+ Timing _rjsmin ... ( 26.4 KiB >) 0.14 ms (factor: 459.12, 199.29, 67.47)
+
+Benchmarking 'bench/DateTimeShortcuts.js'... (18.3 KiB)
+ Timing simple_port ... ( 10.2 KiB *) 23.70 ms
+ Timing jsmin_2_0_9 ... ( 10.3 KiB >) 9.66 ms (factor: 2.45)
+ Timing rjsmin ... ( 10.2 KiB >) 2.51 ms (factor: 9.44, 3.85)
+ Timing _rjsmin ... ( 10.2 KiB >) 0.05 ms (factor: 485.22, 197.80, 51.38)
+
+Benchmarking 'bench/jquery-1.7.1.js'... (242.4 KiB)
+ Timing simple_port ... (135.9 KiB *) 332.05 ms
+ Timing jsmin_2_0_9 ... (136.8 KiB >) 170.77 ms (factor: 1.94)
+ Timing rjsmin ... (135.9 KiB =) 64.29 ms (factor: 5.17, 2.66)
+ Timing _rjsmin ... (135.9 KiB =) 0.86 ms (factor: 385.59, 198.30, 74.65)
+
+Benchmarking 'bench/knockout-2.0.0.js'... (38.9 KiB)
+ Timing simple_port ... ( 38.6 KiB *) 60.90 ms
+ Timing jsmin_2_0_9 ... ( 38.6 KiB >) 27.06 ms (factor: 2.25)
+ Timing rjsmin ... ( 38.6 KiB >) 1.99 ms (factor: 30.55, 13.57)
+ Timing _rjsmin ... ( 38.6 KiB >) 0.08 ms (factor: 731.84, 325.16, 23.96)
+
+Benchmarking 'bench/markermanager.js'... (28.6 KiB)
+ Timing simple_port ... ( 11.6 KiB *) 31.08 ms
+ Timing jsmin_2_0_9 ... ( 11.6 KiB >) 12.89 ms (factor: 2.41)
+ Timing rjsmin ... ( 11.6 KiB =) 3.99 ms (factor: 7.78, 3.23)
+ Timing _rjsmin ... ( 11.6 KiB =) 0.06 ms (factor: 512.70, 212.64, 65.88)
+
+
+$ python3.3 -OO bench/main.py bench/*.js
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python Release: 3.3.5
+
+Benchmarking 'bench/apiviewer.js'... (953.2 KiB)
+ Timing simple_port ... (951.5 KiB *) 1824.95 ms
+ Timing jsmin_2_0_9 ... (951.5 KiB >) 1874.17 ms (factor: 0.97)
+ Timing rjsmin ... (951.5 KiB =) 45.03 ms (factor: 40.53, 41.63)
+ Timing _rjsmin ... (951.5 KiB =) 1.86 ms (factor: 982.48, 1008.98, 24.24)
+
+Benchmarking 'bench/bootstrap.js'... (49.0 KiB)
+ Timing simple_port ... ( 26.4 KiB *) 72.87 ms
+ Timing jsmin_2_0_9 ... ( 26.4 KiB >) 27.80 ms (factor: 2.62)
+ Timing rjsmin ... ( 26.4 KiB >) 10.58 ms (factor: 6.89, 2.63)
+ Timing _rjsmin ... ( 26.4 KiB >) 0.14 ms (factor: 528.45, 201.57, 76.74)
+
+Benchmarking 'bench/DateTimeShortcuts.js'... (18.3 KiB)
+ Timing simple_port ... ( 10.2 KiB *) 27.12 ms
+ Timing jsmin_2_0_9 ... ( 10.3 KiB >) 10.54 ms (factor: 2.57)
+ Timing rjsmin ... ( 10.2 KiB >) 2.76 ms (factor: 9.82, 3.82)
+ Timing _rjsmin ... ( 10.2 KiB >) 0.05 ms (factor: 560.00, 217.65, 57.00)
+
+Benchmarking 'bench/jquery-1.7.1.js'... (242.4 KiB)
+ Timing simple_port ... (135.9 KiB *) 385.43 ms
+ Timing jsmin_2_0_9 ... (136.8 KiB >) 183.31 ms (factor: 2.10)
+ Timing rjsmin ... (135.9 KiB =) 73.03 ms (factor: 5.28, 2.51)
+ Timing _rjsmin ... (135.9 KiB =) 0.87 ms (factor: 445.30, 211.78, 84.38)
+
+Benchmarking 'bench/knockout-2.0.0.js'... (38.9 KiB)
+ Timing simple_port ... ( 38.6 KiB *) 71.85 ms
+ Timing jsmin_2_0_9 ... ( 38.6 KiB >) 29.80 ms (factor: 2.41)
+ Timing rjsmin ... ( 38.6 KiB >) 2.37 ms (factor: 30.28, 12.56)
+ Timing _rjsmin ... ( 38.6 KiB >) 0.08 ms (factor: 897.57, 372.29, 29.64)
+
+Benchmarking 'bench/markermanager.js'... (28.6 KiB)
+ Timing simple_port ... ( 11.6 KiB *) 35.54 ms
+ Timing jsmin_2_0_9 ... ( 11.6 KiB >) 14.17 ms (factor: 2.51)
+ Timing rjsmin ... ( 11.6 KiB =) 4.80 ms (factor: 7.40, 2.95)
+ Timing _rjsmin ... ( 11.6 KiB =) 0.06 ms (factor: 592.11, 236.04, 80.03)
+
+
+$ python2.7 -OO bench/main.py bench/*.js
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Python Release: 2.7.10
+
+Benchmarking 'bench/apiviewer.js'... (953.2 KiB)
+ Timing simple_port ... (951.5 KiB *) 1838.28 ms
+ Timing jsmin_2_0_9 ... (951.5 KiB >) 2031.25 ms (factor: 0.91)
+ Timing rjsmin ... (951.5 KiB =) 44.39 ms (factor: 41.41, 45.76)
+ Timing _rjsmin ... (951.5 KiB =) 1.65 ms (factor: 1114.11, 1231.06, 26.90)
+
+Benchmarking 'bench/bootstrap.js'... (49.0 KiB)
+ Timing simple_port ... ( 26.4 KiB *) 73.95 ms
+ Timing jsmin_2_0_9 ... ( 26.4 KiB >) 31.02 ms (factor: 2.38)
+ Timing rjsmin ... ( 26.4 KiB >) 9.36 ms (factor: 7.90, 3.32)
+ Timing _rjsmin ... ( 26.4 KiB >) 0.13 ms (factor: 582.62, 244.42, 73.71)
+
+Benchmarking 'bench/DateTimeShortcuts.js'... (18.3 KiB)
+ Timing simple_port ... ( 10.2 KiB *) 27.22 ms
+ Timing jsmin_2_0_9 ... ( 10.3 KiB >) 11.76 ms (factor: 2.32)
+ Timing rjsmin ... ( 10.2 KiB >) 2.57 ms (factor: 10.59, 4.57)
+ Timing _rjsmin ... ( 10.2 KiB >) 0.04 ms (factor: 772.01, 333.43, 72.92)
+
+Benchmarking 'bench/jquery-1.7.1.js'... (242.4 KiB)
+ Timing simple_port ... (135.9 KiB *) 379.62 ms
+ Timing jsmin_2_0_9 ... (136.8 KiB >) 207.60 ms (factor: 1.83)
+ Timing rjsmin ... (135.9 KiB =) 65.50 ms (factor: 5.80, 3.17)
+ Timing _rjsmin ... (135.9 KiB =) 0.80 ms (factor: 475.82, 260.21, 82.10)
+
+Benchmarking 'bench/knockout-2.0.0.js'... (38.9 KiB)
+ Timing simple_port ... ( 38.6 KiB *) 73.44 ms
+ Timing jsmin_2_0_9 ... ( 38.6 KiB >) 34.63 ms (factor: 2.12)
+ Timing rjsmin ... ( 38.6 KiB >) 2.05 ms (factor: 35.80, 16.89)
+ Timing _rjsmin ... ( 38.6 KiB >) 0.07 ms (factor: 1000.09, 471.65, 27.93)
+
+Benchmarking 'bench/markermanager.js'... (28.6 KiB)
+ Timing simple_port ... ( 11.6 KiB *) 36.26 ms
+ Timing jsmin_2_0_9 ... ( 11.6 KiB >) 15.54 ms (factor: 2.33)
+ Timing rjsmin ... ( 11.6 KiB =) 4.06 ms (factor: 8.94, 3.83)
+ Timing _rjsmin ... ( 11.6 KiB =) 0.05 ms (factor: 663.56, 284.44, 74.24)
+
+
+# vim: nowrap
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/CHANGES b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/CHANGES
new file mode 100644
index 00000000000..ce74c4c7d4d
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/CHANGES
@@ -0,0 +1,111 @@
+Changes with version 1.0.12
+
+ *) Benchmark updates, dropped slimit benchmarks, because of installation
+ trouble
+
+ *) Reworked handling of comments starting with exclamation marks. The matcher
+ should no longer get out of sync, even if they appear in the middle of other
+ matches.
+
+ *) Handle line terminators before and after regex literals more sensible
+
+
+Changes with version 1.0.11
+
+ *) Benchmark updates
+
+ *) Lifted max restrictions for CPython and Jython as well.
+
+ *) Lifted max restrictions for pypy versions. Added pypy3 support.
+ Submitted by https://github.com/tony
+
+
+Changes with version 1.0.10
+
+ *) Added support for pypy 2.2
+
+ *) Relint with newer pylint
+
+ *) Fix locale problem with the setup script on python3.
+ Submitted by https://github.com/svenstaro
+
+
+Changes with version 1.0.9
+
+ *) Documentation and benchmark updates
+
+
+Changes with version 1.0.8
+
+ *) Updated benchmarks
+
+ *) Added command line option for keeping comments starting with an exclamation
+ mark (-b)
+
+ *) Added command line option for disabling the C implemention (-p)
+
+ *) Added support for python 3.4
+
+ *) Added support for keeping comments starting with an exclamation mark. This
+ feature can be enabled by passing keep_bang_comments=True to the jsmin
+ function.
+
+
+Changes with version 1.0.7
+
+ *) Fix inconsistency between Python and C (Python implementation was buggy).
+ Spotted by: Dave Smith <dave thesmithfam.org>
+
+ *) Added support for jython 2.7
+
+
+Changes with version 1.0.6
+
+ *) Added compat option to setup.py supporting the pip installer
+
+ *) Added support for pypy (1.9, 2.0)
+
+ *) Added support for jython (2.5)
+
+
+Changes with version 1.0.5
+
+ *) Newline removal before ! operator was made more sensible.
+
+
+Changes with version 1.0.4
+
+ *) Added support for Python 3.3
+
+ *) Collapsion protection was reduced to "+ +" and "- -" sequences (which
+ still includes longer sequences like "+ ++")
+
+
+Changes with version 1.0.3
+
+ *) "+ ++" and "- --" sequences are no longer collapsed. They were before,
+ because the original jsmin collapsed them, too.
+
+ *) Updated benchmarks, added slimit and removed jsmin v8 (because it produced
+ invalid results).
+
+ *) Removed "classic" regex variant.
+
+
+Changes with version 1.0.2
+
+ *) Although it should work, python 2.3 is no longer supported.
+ (No suitable test environment)
+
+ *) "return /regex/" is now recognized as regex expression. It wasn't before,
+ because the original jsmin ignored that, too.
+
+
+Changes with version 1.0.1
+
+ *) Add C extension reimplementing the regex from rjsmin.py
+
+
+Changes with version 1.0.0
+
+ *) First stable release.
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/CLASSIFIERS b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/CLASSIFIERS
new file mode 100644
index 00000000000..10d59650380
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/CLASSIFIERS
@@ -0,0 +1,19 @@
+Development Status :: 5 - Production/Stable
+Environment :: Web Environment
+Intended Audience :: Developers
+License :: OSI Approved
+License :: OSI Approved :: Apache License, Version 2.0
+Operating System :: OS Independent
+Programming Language :: C
+Programming Language :: Python
+Programming Language :: Python :: 2
+Programming Language :: Python :: 3
+Programming Language :: Python :: Implementation :: CPython
+Programming Language :: Python :: Implementation :: Jython
+Programming Language :: Python :: Implementation :: PyPy
+Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Topic :: Software Development :: Libraries
+Topic :: Software Development :: Libraries :: Python Modules
+Topic :: Text Processing
+Topic :: Text Processing :: Filters
+Topic :: Utilities
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/DESCRIPTION b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/DESCRIPTION
new file mode 100644
index 00000000000..26a5fb30eaf
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/DESCRIPTION
@@ -0,0 +1,73 @@
+=====================
+ Javascript Minifier
+=====================
+
+rJSmin is a javascript minifier written in python.
+
+The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\.
+
+The module is a re-implementation aiming for speed, so it can be used at
+runtime (rather than during a preprocessing step). Usually it produces the
+same results as the original ``jsmin.c``. It differs in the following ways:
+
+- there is no error detection: unterminated string, regex and comment
+ literals are treated as regular javascript code and minified as such.
+- Control characters inside string and regex literals are left untouched; they
+ are not converted to spaces (nor to \n)
+- Newline characters are not allowed inside string and regex literals, except
+ for line continuations in string literals (ECMA-5).
+- "return /regex/" is recognized correctly.
+- Line terminators after regex literals are handled more sensibly
+- "+ +" and "- -" sequences are not collapsed to '++' or '--'
+- Newlines before ! operators are removed more sensibly
+- Comments starting with an exclamation mark (``!``) can be kept optionally
+- rJSmin does not handle streams, but only complete strings. (However, the
+ module provides a "streamy" interface).
+
+Since most parts of the logic are handled by the regex engine it's way faster
+than the original python port of ``jsmin.c`` by Baruch Even. The speed factor
+varies between about 6 and 55 depending on input and python version (it gets
+faster the more compressed the input already is). Compared to the
+speed-refactored python port by Dave St.Germain the performance gain is less
+dramatic but still between 3 and 50 (for huge inputs)). See the
+docs/BENCHMARKS file for details.
+
+rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
+
+Both python 2 (>=2.4) and python 3 are supported.
+
+.. _jsmin.c by Douglas Crockford: http://www.crockford.com/javascript/jsmin.c
+
+
+Copyright and License
+~~~~~~~~~~~~~~~~~~~~~
+
+Copyright 2011 - 2015
+André Malo or his licensors, as applicable.
+
+The whole package (except for the files in the bench/ directory) is
+distributed under the Apache License Version 2.0. You'll find a copy in the
+root directory of the distribution or online at:
+<http://www.apache.org/licenses/LICENSE-2.0>.
+
+
+Bugs
+~~~~
+
+No bugs, of course. ;-)
+But if you've found one or have an idea how to improve rjsmin, feel free
+to send a pull request on `github <https://github.com/ndparker/rjsmin>`_
+or send a mail to <rjsmin-bugs@perlig.de>.
+
+
+Author Information
+~~~~~~~~~~~~~~~~~~
+
+André "nd" Malo <nd perlig.de>
+GPG: 0x8103A37E
+
+
+ If God intended people to be naked, they would be born that way.
+ -- Oscar Wilde
+
+.. vim:tw=72 syntax=rest
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/PROVIDES b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/PROVIDES
new file mode 100644
index 00000000000..8e9e6633191
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/PROVIDES
@@ -0,0 +1 @@
+rjsmin (1.0)
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/SUMMARY b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/SUMMARY
new file mode 100644
index 00000000000..52064ce19c4
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/SUMMARY
@@ -0,0 +1 @@
+Javascript Minifier
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/api-objects.txt b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/api-objects.txt
new file mode 100644
index 00000000000..e5f2e820866
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/api-objects.txt
@@ -0,0 +1,7 @@
+rjsmin rjsmin-module.html
+rjsmin.__license__ rjsmin-module.html#__license__
+rjsmin.jsmin rjsmin-module.html#jsmin
+rjsmin.__package__ rjsmin-module.html#__package__
+rjsmin._make_jsmin rjsmin-module.html#_make_jsmin
+rjsmin.jsmin_for_posers rjsmin-module.html#jsmin_for_posers
+rjsmin.__doc__ rjsmin-module.html#__doc__
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/crarr.png b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/crarr.png
new file mode 100644
index 00000000000..26b43c52433
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/crarr.png
Binary files differ
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/epydoc.css b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/epydoc.css
new file mode 100644
index 00000000000..86d41706824
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/epydoc.css
@@ -0,0 +1,322 @@
+
+
+/* Epydoc CSS Stylesheet
+ *
+ * This stylesheet can be used to customize the appearance of epydoc's
+ * HTML output.
+ *
+ */
+
+/* Default Colors & Styles
+ * - Set the default foreground & background color with 'body'; and
+ * link colors with 'a:link' and 'a:visited'.
+ * - Use bold for decision list terms.
+ * - The heading styles defined here are used for headings *within*
+ * docstring descriptions. All headings used by epydoc itself use
+ * either class='epydoc' or class='toc' (CSS styles for both
+ * defined below).
+ */
+body { background: #ffffff; color: #000000; }
+p { margin-top: 0.5em; margin-bottom: 0.5em; }
+a:link { color: #0000ff; }
+a:visited { color: #204080; }
+dt { font-weight: bold; }
+h1 { font-size: +140%; font-style: italic;
+ font-weight: bold; }
+h2 { font-size: +125%; font-style: italic;
+ font-weight: bold; }
+h3 { font-size: +110%; font-style: italic;
+ font-weight: normal; }
+code { font-size: 100%; }
+/* N.B.: class, not pseudoclass */
+a.link { font-family: monospace; }
+
+/* Page Header & Footer
+ * - The standard page header consists of a navigation bar (with
+ * pointers to standard pages such as 'home' and 'trees'); a
+ * breadcrumbs list, which can be used to navigate to containing
+ * classes or modules; options links, to show/hide private
+ * variables and to show/hide frames; and a page title (using
+ * <h1>). The page title may be followed by a link to the
+ * corresponding source code (using 'span.codelink').
+ * - The footer consists of a navigation bar, a timestamp, and a
+ * pointer to epydoc's homepage.
+ */
+h1.epydoc { margin: 0; font-size: +140%; font-weight: bold; }
+h2.epydoc { font-size: +130%; font-weight: bold; }
+h3.epydoc { font-size: +115%; font-weight: bold;
+ margin-top: 0.2em; }
+td h3.epydoc { font-size: +115%; font-weight: bold;
+ margin-bottom: 0; }
+table.navbar { background: #a0c0ff; color: #000000;
+ border: 2px groove #c0d0d0; }
+table.navbar table { color: #000000; }
+th.navbar-select { background: #70b0ff;
+ color: #000000; }
+table.navbar a { text-decoration: none; }
+table.navbar a:link { color: #0000ff; }
+table.navbar a:visited { color: #204080; }
+span.breadcrumbs { font-size: 85%; font-weight: bold; }
+span.options { font-size: 70%; }
+span.codelink { font-size: 85%; }
+td.footer { font-size: 85%; }
+
+/* Table Headers
+ * - Each summary table and details section begins with a 'header'
+ * row. This row contains a section title (marked by
+ * 'span.table-header') as well as a show/hide private link
+ * (marked by 'span.options', defined above).
+ * - Summary tables that contain user-defined groups mark those
+ * groups using 'group header' rows.
+ */
+td.table-header { background: #70b0ff; color: #000000;
+ border: 1px solid #608090; }
+td.table-header table { color: #000000; }
+td.table-header table a:link { color: #0000ff; }
+td.table-header table a:visited { color: #204080; }
+span.table-header { font-size: 120%; font-weight: bold; }
+th.group-header { background: #c0e0f8; color: #000000;
+ text-align: left; font-style: italic;
+ font-size: 115%;
+ border: 1px solid #608090; }
+
+/* Summary Tables (functions, variables, etc)
+ * - Each object is described by a single row of the table with
+ * two cells. The left cell gives the object's type, and is
+ * marked with 'code.summary-type'. The right cell gives the
+ * object's name and a summary description.
+ * - CSS styles for the table's header and group headers are
+ * defined above, under 'Table Headers'
+ */
+table.summary { border-collapse: collapse;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #608090;
+ margin-bottom: 0.5em; }
+td.summary { border: 1px solid #608090; }
+code.summary-type { font-size: 85%; }
+table.summary a:link { color: #0000ff; }
+table.summary a:visited { color: #204080; }
+
+
+/* Details Tables (functions, variables, etc)
+ * - Each object is described in its own div.
+ * - A single-row summary table w/ table-header is used as
+ * a header for each details section (CSS style for table-header
+ * is defined above, under 'Table Headers').
+ */
+table.details { border-collapse: collapse;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #608090;
+ margin: .2em 0 0 0; }
+table.details table { color: #000000; }
+table.details a:link { color: #0000ff; }
+table.details a:visited { color: #204080; }
+
+/* Fields */
+dl.fields { margin-left: 2em; margin-top: 1em;
+ margin-bottom: 1em; }
+dl.fields dd ul { margin-left: 0em; padding-left: 0em; }
+dl.fields dd ul li ul { margin-left: 2em; padding-left: 0em; }
+div.fields { margin-left: 2em; }
+div.fields p { margin-bottom: 0.5em; }
+
+/* Index tables (identifier index, term index, etc)
+ * - link-index is used for indices containing lists of links
+ * (namely, the identifier index & term index).
+ * - index-where is used in link indices for the text indicating
+ * the container/source for each link.
+ * - metadata-index is used for indices containing metadata
+ * extracted from fields (namely, the bug index & todo index).
+ */
+table.link-index { border-collapse: collapse;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #608090; }
+td.link-index { border-width: 0px; }
+table.link-index a:link { color: #0000ff; }
+table.link-index a:visited { color: #204080; }
+span.index-where { font-size: 70%; }
+table.metadata-index { border-collapse: collapse;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #608090;
+ margin: .2em 0 0 0; }
+td.metadata-index { border-width: 1px; border-style: solid; }
+table.metadata-index a:link { color: #0000ff; }
+table.metadata-index a:visited { color: #204080; }
+
+/* Function signatures
+ * - sig* is used for the signature in the details section.
+ * - .summary-sig* is used for the signature in the summary
+ * table, and when listing property accessor functions.
+ * */
+.sig-name { color: #006080; }
+.sig-arg { color: #008060; }
+.sig-default { color: #602000; }
+.summary-sig { font-family: monospace; }
+.summary-sig-name { color: #006080; font-weight: bold; }
+table.summary a.summary-sig-name:link
+ { color: #006080; font-weight: bold; }
+table.summary a.summary-sig-name:visited
+ { color: #006080; font-weight: bold; }
+.summary-sig-arg { color: #006040; }
+.summary-sig-default { color: #501800; }
+
+/* Subclass list
+ */
+ul.subclass-list { display: inline; }
+ul.subclass-list li { display: inline; }
+
+/* To render variables, classes etc. like functions */
+table.summary .summary-name { color: #006080; font-weight: bold;
+ font-family: monospace; }
+table.summary
+ a.summary-name:link { color: #006080; font-weight: bold;
+ font-family: monospace; }
+table.summary
+ a.summary-name:visited { color: #006080; font-weight: bold;
+ font-family: monospace; }
+
+/* Variable values
+ * - In the 'variable details' sections, each varaible's value is
+ * listed in a 'pre.variable' box. The width of this box is
+ * restricted to 80 chars; if the value's repr is longer than
+ * this it will be wrapped, using a backslash marked with
+ * class 'variable-linewrap'. If the value's repr is longer
+ * than 3 lines, the rest will be ellided; and an ellipsis
+ * marker ('...' marked with 'variable-ellipsis') will be used.
+ * - If the value is a string, its quote marks will be marked
+ * with 'variable-quote'.
+ * - If the variable is a regexp, it is syntax-highlighted using
+ * the re* CSS classes.
+ */
+pre.variable { padding: .5em; margin: 0;
+ background: #dce4ec; color: #000000;
+ border: 1px solid #708890; }
+.variable-linewrap { color: #604000; font-weight: bold; }
+.variable-ellipsis { color: #604000; font-weight: bold; }
+.variable-quote { color: #604000; font-weight: bold; }
+.variable-group { color: #008000; font-weight: bold; }
+.variable-op { color: #604000; font-weight: bold; }
+.variable-string { color: #006030; }
+.variable-unknown { color: #a00000; font-weight: bold; }
+.re { color: #000000; }
+.re-char { color: #006030; }
+.re-op { color: #600000; }
+.re-group { color: #003060; }
+.re-ref { color: #404040; }
+
+/* Base tree
+ * - Used by class pages to display the base class hierarchy.
+ */
+pre.base-tree { font-size: 80%; margin: 0; }
+
+/* Frames-based table of contents headers
+ * - Consists of two frames: one for selecting modules; and
+ * the other listing the contents of the selected module.
+ * - h1.toc is used for each frame's heading
+ * - h2.toc is used for subheadings within each frame.
+ */
+h1.toc { text-align: center; font-size: 105%;
+ margin: 0; font-weight: bold;
+ padding: 0; }
+h2.toc { font-size: 100%; font-weight: bold;
+ margin: 0.5em 0 0 -0.3em; }
+
+/* Syntax Highlighting for Source Code
+ * - doctest examples are displayed in a 'pre.py-doctest' block.
+ * If the example is in a details table entry, then it will use
+ * the colors specified by the 'table pre.py-doctest' line.
+ * - Source code listings are displayed in a 'pre.py-src' block.
+ * Each line is marked with 'span.py-line' (used to draw a line
+ * down the left margin, separating the code from the line
+ * numbers). Line numbers are displayed with 'span.py-lineno'.
+ * The expand/collapse block toggle button is displayed with
+ * 'a.py-toggle' (Note: the CSS style for 'a.py-toggle' should not
+ * modify the font size of the text.)
+ * - If a source code page is opened with an anchor, then the
+ * corresponding code block will be highlighted. The code
+ * block's header is highlighted with 'py-highlight-hdr'; and
+ * the code block's body is highlighted with 'py-highlight'.
+ * - The remaining py-* classes are used to perform syntax
+ * highlighting (py-string for string literals, py-name for names,
+ * etc.)
+ */
+pre.py-doctest { padding: .5em; margin: 1em;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #708890; }
+table pre.py-doctest { background: #dce4ec;
+ color: #000000; }
+pre.py-src { border: 2px solid #000000;
+ background: #f0f0f0; color: #000000; }
+.py-line { border-left: 2px solid #000000;
+ margin-left: .2em; padding-left: .4em; }
+.py-lineno { font-style: italic; font-size: 90%;
+ padding-left: .5em; }
+a.py-toggle { text-decoration: none; }
+div.py-highlight-hdr { border-top: 2px solid #000000;
+ border-bottom: 2px solid #000000;
+ background: #d8e8e8; }
+div.py-highlight { border-bottom: 2px solid #000000;
+ background: #d0e0e0; }
+.py-prompt { color: #005050; font-weight: bold;}
+.py-more { color: #005050; font-weight: bold;}
+.py-string { color: #006030; }
+.py-comment { color: #003060; }
+.py-keyword { color: #600000; }
+.py-output { color: #404040; }
+.py-name { color: #000050; }
+.py-name:link { color: #000050 !important; }
+.py-name:visited { color: #000050 !important; }
+.py-number { color: #005000; }
+.py-defname { color: #000060; font-weight: bold; }
+.py-def-name { color: #000060; font-weight: bold; }
+.py-base-class { color: #000060; }
+.py-param { color: #000060; }
+.py-docstring { color: #006030; }
+.py-decorator { color: #804020; }
+/* Use this if you don't want links to names underlined: */
+/*a.py-name { text-decoration: none; }*/
+
+/* Graphs & Diagrams
+ * - These CSS styles are used for graphs & diagrams generated using
+ * Graphviz dot. 'img.graph-without-title' is used for bare
+ * diagrams (to remove the border created by making the image
+ * clickable).
+ */
+img.graph-without-title { border: none; }
+img.graph-with-title { border: 1px solid #000000; }
+span.graph-title { font-weight: bold; }
+span.graph-caption { }
+
+/* General-purpose classes
+ * - 'p.indent-wrapped-lines' defines a paragraph whose first line
+ * is not indented, but whose subsequent lines are.
+ * - The 'nomargin-top' class is used to remove the top margin (e.g.
+ * from lists). The 'nomargin' class is used to remove both the
+ * top and bottom margin (but not the left or right margin --
+ * for lists, that would cause the bullets to disappear.)
+ */
+p.indent-wrapped-lines { padding: 0 0 0 7em; text-indent: -7em;
+ margin: 0; }
+.nomargin-top { margin-top: 0; }
+.nomargin { margin-top: 0; margin-bottom: 0; }
+
+/* HTML Log */
+div.log-block { padding: 0; margin: .5em 0 .5em 0;
+ background: #e8f0f8; color: #000000;
+ border: 1px solid #000000; }
+div.log-error { padding: .1em .3em .1em .3em; margin: 4px;
+ background: #ffb0b0; color: #000000;
+ border: 1px solid #000000; }
+div.log-warning { padding: .1em .3em .1em .3em; margin: 4px;
+ background: #ffffb0; color: #000000;
+ border: 1px solid #000000; }
+div.log-info { padding: .1em .3em .1em .3em; margin: 4px;
+ background: #b0ffb0; color: #000000;
+ border: 1px solid #000000; }
+h2.log-hdr { background: #70b0ff; color: #000000;
+ margin: 0; padding: 0em 0.5em 0em 0.5em;
+ border-bottom: 1px solid #000000; font-size: 110%; }
+p.log { font-weight: bold; margin: .5em 0 .5em 0; }
+tr.opt-changed { color: #000000; font-weight: bold; }
+tr.opt-default { color: #606060; }
+pre.log { margin: 0; padding: 0; padding-left: 1em; }
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/epydoc.js b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/epydoc.js
new file mode 100644
index 00000000000..e787dbcf471
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/epydoc.js
@@ -0,0 +1,293 @@
+function toggle_private() {
+ // Search for any private/public links on this page. Store
+ // their old text in "cmd," so we will know what action to
+ // take; and change their text to the opposite action.
+ var cmd = "?";
+ var elts = document.getElementsByTagName("a");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "privatelink") {
+ cmd = elts[i].innerHTML;
+ elts[i].innerHTML = ((cmd && cmd.substr(0,4)=="show")?
+ "hide&nbsp;private":"show&nbsp;private");
+ }
+ }
+ // Update all DIVs containing private objects.
+ var elts = document.getElementsByTagName("div");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "private") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"block");
+ }
+ else if (elts[i].className == "public") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"block":"none");
+ }
+ }
+ // Update all table rows containing private objects. Note, we
+ // use "" instead of "block" becaue IE & firefox disagree on what
+ // this should be (block vs table-row), and "" just gives the
+ // default for both browsers.
+ var elts = document.getElementsByTagName("tr");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "private") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"");
+ }
+ }
+ // Update all list items containing private objects.
+ var elts = document.getElementsByTagName("li");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "private") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?
+ "none":"");
+ }
+ }
+ // Update all list items containing private objects.
+ var elts = document.getElementsByTagName("ul");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "private") {
+ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"block");
+ }
+ }
+ // Set a cookie to remember the current option.
+ document.cookie = "EpydocPrivate="+cmd;
+ }
+function show_private() {
+ var elts = document.getElementsByTagName("a");
+ for(var i=0; i<elts.length; i++) {
+ if (elts[i].className == "privatelink") {
+ cmd = elts[i].innerHTML;
+ if (cmd && cmd.substr(0,4)=="show")
+ toggle_private();
+ }
+ }
+ }
+function getCookie(name) {
+ var dc = document.cookie;
+ var prefix = name + "=";
+ var begin = dc.indexOf("; " + prefix);
+ if (begin == -1) {
+ begin = dc.indexOf(prefix);
+ if (begin != 0) return null;
+ } else
+ { begin += 2; }
+ var end = document.cookie.indexOf(";", begin);
+ if (end == -1)
+ { end = dc.length; }
+ return unescape(dc.substring(begin + prefix.length, end));
+ }
+function setFrame(url1, url2) {
+ parent.frames[1].location.href = url1;
+ parent.frames[2].location.href = url2;
+ }
+function checkCookie() {
+ var cmd=getCookie("EpydocPrivate");
+ if (cmd && cmd.substr(0,4)!="show" && location.href.indexOf("#_") < 0)
+ toggle_private();
+ }
+function toggleCallGraph(id) {
+ var elt = document.getElementById(id);
+ if (elt.style.display == "none")
+ elt.style.display = "block";
+ else
+ elt.style.display = "none";
+ }
+function expand(id) {
+ var elt = document.getElementById(id+"-expanded");
+ if (elt) elt.style.display = "block";
+ var elt = document.getElementById(id+"-expanded-linenums");
+ if (elt) elt.style.display = "block";
+ var elt = document.getElementById(id+"-collapsed");
+ if (elt) { elt.innerHTML = ""; elt.style.display = "none"; }
+ var elt = document.getElementById(id+"-collapsed-linenums");
+ if (elt) { elt.innerHTML = ""; elt.style.display = "none"; }
+ var elt = document.getElementById(id+"-toggle");
+ if (elt) { elt.innerHTML = "-"; }
+}
+
+function collapse(id) {
+ var elt = document.getElementById(id+"-expanded");
+ if (elt) elt.style.display = "none";
+ var elt = document.getElementById(id+"-expanded-linenums");
+ if (elt) elt.style.display = "none";
+ var elt = document.getElementById(id+"-collapsed-linenums");
+ if (elt) { elt.innerHTML = "<br />"; elt.style.display="block"; }
+ var elt = document.getElementById(id+"-toggle");
+ if (elt) { elt.innerHTML = "+"; }
+ var elt = document.getElementById(id+"-collapsed");
+ if (elt) {
+ elt.style.display = "block";
+
+ var indent = elt.getAttribute("indent");
+ var pad = elt.getAttribute("pad");
+ var s = "<tt class='py-lineno'>";
+ for (var i=0; i<pad.length; i++) { s += "&nbsp;" }
+ s += "</tt>";
+ s += "&nbsp;&nbsp;<tt class='py-line'>";
+ for (var i=0; i<indent.length; i++) { s += "&nbsp;" }
+ s += "<a href='#' onclick='expand(\"" + id;
+ s += "\");return false'>...</a></tt><br />";
+ elt.innerHTML = s;
+ }
+}
+
+function toggle(id) {
+ elt = document.getElementById(id+"-toggle");
+ if (elt.innerHTML == "-")
+ collapse(id);
+ else
+ expand(id);
+ return false;
+}
+
+function highlight(id) {
+ var elt = document.getElementById(id+"-def");
+ if (elt) elt.className = "py-highlight-hdr";
+ var elt = document.getElementById(id+"-expanded");
+ if (elt) elt.className = "py-highlight";
+ var elt = document.getElementById(id+"-collapsed");
+ if (elt) elt.className = "py-highlight";
+}
+
+function num_lines(s) {
+ var n = 1;
+ var pos = s.indexOf("\n");
+ while ( pos > 0) {
+ n += 1;
+ pos = s.indexOf("\n", pos+1);
+ }
+ return n;
+}
+
+// Collapse all blocks that mave more than `min_lines` lines.
+function collapse_all(min_lines) {
+ var elts = document.getElementsByTagName("div");
+ for (var i=0; i<elts.length; i++) {
+ var elt = elts[i];
+ var split = elt.id.indexOf("-");
+ if (split > 0)
+ if (elt.id.substring(split, elt.id.length) == "-expanded")
+ if (num_lines(elt.innerHTML) > min_lines)
+ collapse(elt.id.substring(0, split));
+ }
+}
+
+function expandto(href) {
+ var start = href.indexOf("#")+1;
+ if (start != 0 && start != href.length) {
+ if (href.substring(start, href.length) != "-") {
+ collapse_all(4);
+ pos = href.indexOf(".", start);
+ while (pos != -1) {
+ var id = href.substring(start, pos);
+ expand(id);
+ pos = href.indexOf(".", pos+1);
+ }
+ var id = href.substring(start, href.length);
+ expand(id);
+ highlight(id);
+ }
+ }
+}
+
+function kill_doclink(id) {
+ var parent = document.getElementById(id);
+ parent.removeChild(parent.childNodes.item(0));
+}
+function auto_kill_doclink(ev) {
+ if (!ev) var ev = window.event;
+ if (!this.contains(ev.toElement)) {
+ var parent = document.getElementById(this.parentID);
+ parent.removeChild(parent.childNodes.item(0));
+ }
+}
+
+function doclink(id, name, targets_id) {
+ var elt = document.getElementById(id);
+
+ // If we already opened the box, then destroy it.
+ // (This case should never occur, but leave it in just in case.)
+ if (elt.childNodes.length > 1) {
+ elt.removeChild(elt.childNodes.item(0));
+ }
+ else {
+ // The outer box: relative + inline positioning.
+ var box1 = document.createElement("div");
+ box1.style.position = "relative";
+ box1.style.display = "inline";
+ box1.style.top = 0;
+ box1.style.left = 0;
+
+ // A shadow for fun
+ var shadow = document.createElement("div");
+ shadow.style.position = "absolute";
+ shadow.style.left = "-1.3em";
+ shadow.style.top = "-1.3em";
+ shadow.style.background = "#404040";
+
+ // The inner box: absolute positioning.
+ var box2 = document.createElement("div");
+ box2.style.position = "relative";
+ box2.style.border = "1px solid #a0a0a0";
+ box2.style.left = "-.2em";
+ box2.style.top = "-.2em";
+ box2.style.background = "white";
+ box2.style.padding = ".3em .4em .3em .4em";
+ box2.style.fontStyle = "normal";
+ box2.onmouseout=auto_kill_doclink;
+ box2.parentID = id;
+
+ // Get the targets
+ var targets_elt = document.getElementById(targets_id);
+ var targets = targets_elt.getAttribute("targets");
+ var links = "";
+ target_list = targets.split(",");
+ for (var i=0; i<target_list.length; i++) {
+ var target = target_list[i].split("=");
+ links += "<li><a href='" + target[1] +
+ "' style='text-decoration:none'>" +
+ target[0] + "</a></li>";
+ }
+
+ // Put it all together.
+ elt.insertBefore(box1, elt.childNodes.item(0));
+ //box1.appendChild(box2);
+ box1.appendChild(shadow);
+ shadow.appendChild(box2);
+ box2.innerHTML =
+ "Which <b>"+name+"</b> do you want to see documentation for?" +
+ "<ul style='margin-bottom: 0;'>" +
+ links +
+ "<li><a href='#' style='text-decoration:none' " +
+ "onclick='kill_doclink(\""+id+"\");return false;'>"+
+ "<i>None of the above</i></a></li></ul>";
+ }
+ return false;
+}
+
+function get_anchor() {
+ var href = location.href;
+ var start = href.indexOf("#")+1;
+ if ((start != 0) && (start != href.length))
+ return href.substring(start, href.length);
+ }
+function redirect_url(dottedName) {
+ // Scan through each element of the "pages" list, and check
+ // if "name" matches with any of them.
+ for (var i=0; i<pages.length; i++) {
+
+ // Each page has the form "<pagename>-m" or "<pagename>-c";
+ // extract the <pagename> portion & compare it to dottedName.
+ var pagename = pages[i].substring(0, pages[i].length-2);
+ if (pagename == dottedName.substring(0,pagename.length)) {
+
+ // We've found a page that matches `dottedName`;
+ // construct its URL, using leftover `dottedName`
+ // content to form an anchor.
+ var pagetype = pages[i].charAt(pages[i].length-1);
+ var url = pagename + ((pagetype=="m")?"-module.html":
+ "-class.html");
+ if (dottedName.length > pagename.length)
+ url += "#" + dottedName.substring(pagename.length+1,
+ dottedName.length);
+ return url;
+ }
+ }
+ }
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/help.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/help.html
new file mode 100644
index 00000000000..729bb89a415
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/help.html
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Help</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rjsmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Help&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">&nbsp;</td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+
+<h1 class="epydoc"> API Documentation </h1>
+
+<p> This document contains the API (Application Programming Interface)
+documentation for this project. Documentation for the Python
+objects defined by the project is divided into separate pages for each
+package, module, and class. The API documentation also includes two
+pages containing information about the project as a whole: a trees
+page, and an index page. </p>
+
+<h2> Object Documentation </h2>
+
+ <p>Each <strong>Package Documentation</strong> page contains: </p>
+ <ul>
+ <li> A description of the package. </li>
+ <li> A list of the modules and sub-packages contained by the
+ package. </li>
+ <li> A summary of the classes defined by the package. </li>
+ <li> A summary of the functions defined by the package. </li>
+ <li> A summary of the variables defined by the package. </li>
+ <li> A detailed description of each function defined by the
+ package. </li>
+ <li> A detailed description of each variable defined by the
+ package. </li>
+ </ul>
+
+ <p>Each <strong>Module Documentation</strong> page contains:</p>
+ <ul>
+ <li> A description of the module. </li>
+ <li> A summary of the classes defined by the module. </li>
+ <li> A summary of the functions defined by the module. </li>
+ <li> A summary of the variables defined by the module. </li>
+ <li> A detailed description of each function defined by the
+ module. </li>
+ <li> A detailed description of each variable defined by the
+ module. </li>
+ </ul>
+
+ <p>Each <strong>Class Documentation</strong> page contains: </p>
+ <ul>
+ <li> A class inheritance diagram. </li>
+ <li> A list of known subclasses. </li>
+ <li> A description of the class. </li>
+ <li> A summary of the methods defined by the class. </li>
+ <li> A summary of the instance variables defined by the class. </li>
+ <li> A summary of the class (static) variables defined by the
+ class. </li>
+ <li> A detailed description of each method defined by the
+ class. </li>
+ <li> A detailed description of each instance variable defined by the
+ class. </li>
+ <li> A detailed description of each class (static) variable defined
+ by the class. </li>
+ </ul>
+
+<h2> Project Documentation </h2>
+
+ <p> The <strong>Trees</strong> page contains the module and class hierarchies: </p>
+ <ul>
+ <li> The <em>module hierarchy</em> lists every package and module, with
+ modules grouped into packages. At the top level, and within each
+ package, modules and sub-packages are listed alphabetically. </li>
+ <li> The <em>class hierarchy</em> lists every class, grouped by base
+ class. If a class has more than one base class, then it will be
+ listed under each base class. At the top level, and under each base
+ class, classes are listed alphabetically. </li>
+ </ul>
+
+ <p> The <strong>Index</strong> page contains indices of terms and
+ identifiers: </p>
+ <ul>
+ <li> The <em>term index</em> lists every term indexed by any object's
+ documentation. For each term, the index provides links to each
+ place where the term is indexed. </li>
+ <li> The <em>identifier index</em> lists the (short) name of every package,
+ module, class, method, function, variable, and parameter. For each
+ identifier, the index provides a short description, and a link to
+ its documentation. </li>
+ </ul>
+
+<h2> The Table of Contents </h2>
+
+<p> The table of contents occupies the two frames on the left side of
+the window. The upper-left frame displays the <em>project
+contents</em>, and the lower-left frame displays the <em>module
+contents</em>: </p>
+
+<table class="help summary" border="1" cellspacing="0" cellpadding="3">
+ <tr style="height: 30%">
+ <td align="center" style="font-size: small">
+ Project<br />Contents<hr />...</td>
+ <td align="center" style="font-size: small" rowspan="2" width="70%">
+ API<br />Documentation<br />Frame<br /><br /><br />
+ </td>
+ </tr>
+ <tr>
+ <td align="center" style="font-size: small">
+ Module<br />Contents<hr />&nbsp;<br />...<br />&nbsp;
+ </td>
+ </tr>
+</table><br />
+
+<p> The <strong>project contents frame</strong> contains a list of all packages
+and modules that are defined by the project. Clicking on an entry
+will display its contents in the module contents frame. Clicking on a
+special entry, labeled "Everything," will display the contents of
+the entire project. </p>
+
+<p> The <strong>module contents frame</strong> contains a list of every
+submodule, class, type, exception, function, and variable defined by a
+module or package. Clicking on an entry will display its
+documentation in the API documentation frame. Clicking on the name of
+the module, at the top of the frame, will display the documentation
+for the module itself. </p>
+
+<p> The "<strong>frames</strong>" and "<strong>no frames</strong>" buttons below the top
+navigation bar can be used to control whether the table of contents is
+displayed or not. </p>
+
+<h2> The Navigation Bar </h2>
+
+<p> A navigation bar is located at the top and bottom of every page.
+It indicates what type of page you are currently viewing, and allows
+you to go to related pages. The following table describes the labels
+on the navigation bar. Note that not some labels (such as
+[Parent]) are not displayed on all pages. </p>
+
+<table class="summary" border="1" cellspacing="0" cellpadding="3" width="100%">
+<tr class="summary">
+ <th>Label</th>
+ <th>Highlighted when...</th>
+ <th>Links to...</th>
+</tr>
+ <tr><td valign="top"><strong>[Parent]</strong></td>
+ <td valign="top"><em>(never highlighted)</em></td>
+ <td valign="top"> the parent of the current package </td></tr>
+ <tr><td valign="top"><strong>[Package]</strong></td>
+ <td valign="top">viewing a package</td>
+ <td valign="top">the package containing the current object
+ </td></tr>
+ <tr><td valign="top"><strong>[Module]</strong></td>
+ <td valign="top">viewing a module</td>
+ <td valign="top">the module containing the current object
+ </td></tr>
+ <tr><td valign="top"><strong>[Class]</strong></td>
+ <td valign="top">viewing a class </td>
+ <td valign="top">the class containing the current object</td></tr>
+ <tr><td valign="top"><strong>[Trees]</strong></td>
+ <td valign="top">viewing the trees page</td>
+ <td valign="top"> the trees page </td></tr>
+ <tr><td valign="top"><strong>[Index]</strong></td>
+ <td valign="top">viewing the index page</td>
+ <td valign="top"> the index page </td></tr>
+ <tr><td valign="top"><strong>[Help]</strong></td>
+ <td valign="top">viewing the help page</td>
+ <td valign="top"> the help page </td></tr>
+</table>
+
+<p> The "<strong>show private</strong>" and "<strong>hide private</strong>" buttons below
+the top navigation bar can be used to control whether documentation
+for private objects is displayed. Private objects are usually defined
+as objects whose (short) names begin with a single underscore, but do
+not end with an underscore. For example, "<code>_x</code>",
+"<code>__pprint</code>", and "<code>epydoc.epytext._tokenize</code>"
+are private objects; but "<code>re.sub</code>",
+"<code>__init__</code>", and "<code>type_</code>" are not. However,
+if a module defines the "<code>__all__</code>" variable, then its
+contents are used to decide which objects are private. </p>
+
+<p> A timestamp below the bottom navigation bar indicates when each
+page was last updated. </p>
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rjsmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Help&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/identifier-index.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/identifier-index.html
new file mode 100644
index 00000000000..37b4b984d89
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/identifier-index.html
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Identifier Index</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rjsmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Indices&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">&nbsp;</td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<table border="0" width="100%">
+<tr valign="bottom"><td>
+<h1 class="epydoc">Identifier Index</h1>
+</td><td>
+[
+ A
+ B
+ C
+ D
+ E
+ F
+ G
+ H
+ I
+ <a href="#J">J</a>
+ K
+ L
+ M
+ N
+ O
+ P
+ Q
+ <a href="#R">R</a>
+ S
+ T
+ U
+ V
+ W
+ X
+ Y
+ Z
+ <a href="#_">_</a>
+]
+</td></table>
+<table border="0" width="100%">
+<tr valign="top"><td valign="top" width="1%"><h2 class="epydoc"><a name="J">J</a></h2></td>
+<td valign="top">
+<table class="link-index" width="100%" border="1">
+<tr>
+<td width="33%" class="link-index"><a href="rjsmin-module.html#jsmin">jsmin()</a><br />
+<span class="index-where">(in&nbsp;<a href="rjsmin-module.html">rjsmin</a>)</span></td>
+<td width="33%" class="link-index">&nbsp;</td>
+<td width="33%" class="link-index">&nbsp;</td>
+</tr>
+<tr><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td></tr>
+</table>
+</td></tr>
+<tr valign="top"><td valign="top" width="1%"><h2 class="epydoc"><a name="R">R</a></h2></td>
+<td valign="top">
+<table class="link-index" width="100%" border="1">
+<tr>
+<td width="33%" class="link-index"><a href="rjsmin-module.html">rjsmin</a></td>
+<td width="33%" class="link-index">&nbsp;</td>
+<td width="33%" class="link-index">&nbsp;</td>
+</tr>
+<tr><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td></tr>
+</table>
+</td></tr>
+<tr valign="top"><td valign="top" width="1%"><h2 class="epydoc"><a name="_">_</a></h2></td>
+<td valign="top">
+<table class="link-index" width="100%" border="1">
+<tr>
+<td width="33%" class="link-index"><a href="rjsmin-module.html#__doc__">__doc__</a><br />
+<span class="index-where">(in&nbsp;<a href="rjsmin-module.html">rjsmin</a>)</span></td>
+<td width="33%" class="link-index"><a href="rjsmin-module.html#__license__">__license__</a><br />
+<span class="index-where">(in&nbsp;<a href="rjsmin-module.html">rjsmin</a>)</span></td>
+<td width="33%" class="link-index"><a href="rjsmin-module.html#__package__">__package__</a><br />
+<span class="index-where">(in&nbsp;<a href="rjsmin-module.html">rjsmin</a>)</span></td>
+</tr>
+<tr><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td><td class="link-index">&nbsp;</td></tr>
+</table>
+</td></tr>
+</table>
+<br /><br /><!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rjsmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Indices&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/index.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/index.html
new file mode 100644
index 00000000000..e51b6dad453
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/index.html
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>rjsmin</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">
+ <span class="breadcrumbs">
+ Module&nbsp;rjsmin
+ </span>
+ </td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<!-- ==================== MODULE DESCRIPTION ==================== -->
+<h1 class="epydoc">Module rjsmin</h1><p class="nomargin-top"><span class="codelink"><a href="rjsmin-pysrc.html">source&nbsp;code</a></span></p>
+<p>rJSmin is a javascript minifier written in python.</p>
+<p>The minifier is based on the semantics of <a class="rst-reference external" href="http://www.crockford.com/javascript/jsmin.c" target="_top">jsmin.c by Douglas Crockford</a>.</p>
+<p>The module is a re-implementation aiming for speed, so it can be used at
+runtime (rather than during a preprocessing step). Usually it produces the
+same results as the original <tt class="rst-docutils literal">jsmin.c</tt>. It differs in the following ways:</p>
+<ul class="rst-simple">
+<li>there is no error detection: unterminated string, regex and comment
+literals are treated as regular javascript code and minified as such.</li>
+<li>Control characters inside string and regex literals are left untouched; they
+are not converted to spaces (nor to n)</li>
+<li>Newline characters are not allowed inside string and regex literals, except
+for line continuations in string literals (ECMA-5).</li>
+<li>&quot;return /regex/&quot; is recognized correctly.</li>
+<li>Line terminators after regex literals are handled more sensibly</li>
+<li>&quot;+ +&quot; and &quot;- -&quot; sequences are not collapsed to '++' or '--'</li>
+<li>Newlines before ! operators are removed more sensibly</li>
+<li>Comments starting with an exclamation mark (<tt class="rst-docutils literal">!</tt>) can be kept optionally</li>
+<li>rJSmin does not handle streams, but only complete strings. (However, the
+module provides a &quot;streamy&quot; interface).</li>
+</ul>
+<p>Since most parts of the logic are handled by the regex engine it's way faster
+than the original python port of <tt class="rst-docutils literal">jsmin.c</tt> by Baruch Even. The speed factor
+varies between about 6 and 55 depending on input and python version (it gets
+faster the more compressed the input already is). Compared to the
+speed-refactored python port by Dave St.Germain the performance gain is less
+dramatic but still between 3 and 50 (for huge inputs). See the docs/BENCHMARKS
+file for details.</p>
+<p>rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.</p>
+<p>Both python 2 and python 3 are supported.</p>
+
+<hr />
+<div class="fields"> <p><strong>Copyright:</strong>
+ Copyright 2011 - 2015
+Andr&#233; Malo or his licensors, as applicable
+ </p>
+ <p><strong>License:</strong>
+ <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at</p>
+<blockquote>
+<a class="rst-reference external" href="http://www.apache.org/licenses/LICENSE-2.0" target="_top">http://www.apache.org/licenses/LICENSE-2.0</a></blockquote>
+<p>Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.</p>
+ </p>
+ <p><strong>Version:</strong>
+ 1.0.12
+ </p>
+ <p><strong>Author:</strong>
+ Andr&#233; Malo
+ </p>
+</div><!-- ==================== FUNCTIONS ==================== -->
+<a name="section-Functions"></a>
+<table class="summary" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr bgcolor="#70b0f0" class="table-header">
+ <td align="left" colspan="2" class="table-header">
+ <span class="table-header">Functions</span></td>
+</tr>
+<tr>
+ <td width="15%" align="right" valign="top" class="summary">
+ <span class="summary-type"><tt class="rst-docutils literal">str</tt></span>
+ </td><td class="summary">
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td><span class="summary-sig"><a href="rjsmin-module.html#jsmin" class="summary-sig-name">jsmin</a>(<span class="summary-sig-arg">script</span>,
+ <span class="summary-sig-arg">keep_bang_comments</span>=<span class="summary-sig-default">False</span>)</span><br />
+ Minify javascript based on <a class="rst-reference external" href="http://www.crockford.com/javascript/jsmin.c" target="_top">jsmin.c by Douglas Crockford</a>.</td>
+ <td align="right" valign="top">
+ <span class="codelink"><a href="rjsmin-pysrc.html#jsmin">source&nbsp;code</a></span>
+
+ </td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+</table>
+<!-- ==================== FUNCTION DETAILS ==================== -->
+<a name="section-FunctionDetails"></a>
+<table class="details" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr bgcolor="#70b0f0" class="table-header">
+ <td align="left" colspan="2" class="table-header">
+ <span class="table-header">Function Details</span></td>
+</tr>
+</table>
+<a name="jsmin"></a>
+<div>
+<table class="details" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr><td>
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr valign="top"><td>
+ <h3 class="epydoc"><span class="sig"><span class="sig-name">jsmin</span>(<span class="sig-arg">script</span>,
+ <span class="sig-arg">keep_bang_comments</span>=<span class="sig-default">False</span>)</span>
+ </h3>
+ </td><td align="right" valign="top"
+ ><span class="codelink"><a href="rjsmin-pysrc.html#jsmin">source&nbsp;code</a></span>&nbsp;
+ </td>
+ </tr></table>
+
+ <p>Minify javascript based on <a class="rst-reference external" href="http://www.crockford.com/javascript/jsmin.c" target="_top">jsmin.c by Douglas Crockford</a>.</p>
+<p>Instead of parsing the stream char by char, it uses a regular
+expression approach which minifies the whole script with one big
+substitution regex.</p>
+ <dl class="fields">
+ <dt>Parameters:</dt>
+ <dd><ul class="nomargin-top">
+ <li><strong class="pname"><code>script</code></strong> (<tt class="rst-docutils literal">str</tt>) - Script to minify</li>
+ <li><strong class="pname"><code>keep_bang_comments</code></strong> (<tt class="rst-docutils literal">bool</tt>) - Keep comments starting with an exclamation mark? (<tt class="rst-docutils literal"><span class="pre">/*!...*/</span></tt>)</li>
+ </ul></dd>
+ <dt>Returns: <tt class="rst-docutils literal">str</tt></dt>
+ <dd>Minified script</dd>
+ </dl>
+</td></tr></table>
+</div>
+<br />
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/module-tree.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/module-tree.html
new file mode 100644
index 00000000000..d89305d211c
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/module-tree.html
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Module Hierarchy</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rjsmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Trees&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">&nbsp;</td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<h1 class="epydoc">Module Hierarchy</h1>
+<ul class="nomargin-top">
+ <li> <strong class="uidlink"><a href="rjsmin-module.html">rjsmin</a></strong>: <em class="summary">rJSmin is a javascript minifier written in python.</em> </li>
+</ul>
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="rjsmin-module.html">Home</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Trees&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/redirect.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/redirect.html
new file mode 100644
index 00000000000..50aee0e9f95
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/redirect.html
@@ -0,0 +1,38 @@
+<html><head><title>Epydoc Redirect Page</title>
+<meta http-equiv="cache-control" content="no-cache" />
+<meta http-equiv="expires" content="0" />
+<meta http-equiv="pragma" content="no-cache" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+<body>
+<script type="text/javascript">
+<!--
+var pages = ["rjsmin-m"];
+var dottedName = get_anchor();
+if (dottedName) {
+ var target = redirect_url(dottedName);
+ if (target) window.location.replace(target);
+}
+// -->
+</script>
+
+<h3>Epydoc Auto-redirect page</h3>
+
+<p>When javascript is enabled, this page will redirect URLs of
+the form <tt>redirect.html#<i>dotted.name</i></tt> to the
+documentation for the object with the given fully-qualified
+dotted name.</p>
+<p><a id="message"> &nbsp; </a></p>
+
+<script type="text/javascript">
+<!--
+if (dottedName) {
+ var msg = document.getElementById("message");
+ msg.innerHTML = "No documentation found for <tt>"+
+ dottedName+"</tt>";
+}
+// -->
+</script>
+
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/rjsmin-module.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/rjsmin-module.html
new file mode 100644
index 00000000000..e51b6dad453
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/rjsmin-module.html
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>rjsmin</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">
+ <span class="breadcrumbs">
+ Module&nbsp;rjsmin
+ </span>
+ </td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<!-- ==================== MODULE DESCRIPTION ==================== -->
+<h1 class="epydoc">Module rjsmin</h1><p class="nomargin-top"><span class="codelink"><a href="rjsmin-pysrc.html">source&nbsp;code</a></span></p>
+<p>rJSmin is a javascript minifier written in python.</p>
+<p>The minifier is based on the semantics of <a class="rst-reference external" href="http://www.crockford.com/javascript/jsmin.c" target="_top">jsmin.c by Douglas Crockford</a>.</p>
+<p>The module is a re-implementation aiming for speed, so it can be used at
+runtime (rather than during a preprocessing step). Usually it produces the
+same results as the original <tt class="rst-docutils literal">jsmin.c</tt>. It differs in the following ways:</p>
+<ul class="rst-simple">
+<li>there is no error detection: unterminated string, regex and comment
+literals are treated as regular javascript code and minified as such.</li>
+<li>Control characters inside string and regex literals are left untouched; they
+are not converted to spaces (nor to n)</li>
+<li>Newline characters are not allowed inside string and regex literals, except
+for line continuations in string literals (ECMA-5).</li>
+<li>&quot;return /regex/&quot; is recognized correctly.</li>
+<li>Line terminators after regex literals are handled more sensibly</li>
+<li>&quot;+ +&quot; and &quot;- -&quot; sequences are not collapsed to '++' or '--'</li>
+<li>Newlines before ! operators are removed more sensibly</li>
+<li>Comments starting with an exclamation mark (<tt class="rst-docutils literal">!</tt>) can be kept optionally</li>
+<li>rJSmin does not handle streams, but only complete strings. (However, the
+module provides a &quot;streamy&quot; interface).</li>
+</ul>
+<p>Since most parts of the logic are handled by the regex engine it's way faster
+than the original python port of <tt class="rst-docutils literal">jsmin.c</tt> by Baruch Even. The speed factor
+varies between about 6 and 55 depending on input and python version (it gets
+faster the more compressed the input already is). Compared to the
+speed-refactored python port by Dave St.Germain the performance gain is less
+dramatic but still between 3 and 50 (for huge inputs). See the docs/BENCHMARKS
+file for details.</p>
+<p>rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.</p>
+<p>Both python 2 and python 3 are supported.</p>
+
+<hr />
+<div class="fields"> <p><strong>Copyright:</strong>
+ Copyright 2011 - 2015
+Andr&#233; Malo or his licensors, as applicable
+ </p>
+ <p><strong>License:</strong>
+ <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at</p>
+<blockquote>
+<a class="rst-reference external" href="http://www.apache.org/licenses/LICENSE-2.0" target="_top">http://www.apache.org/licenses/LICENSE-2.0</a></blockquote>
+<p>Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.</p>
+ </p>
+ <p><strong>Version:</strong>
+ 1.0.12
+ </p>
+ <p><strong>Author:</strong>
+ Andr&#233; Malo
+ </p>
+</div><!-- ==================== FUNCTIONS ==================== -->
+<a name="section-Functions"></a>
+<table class="summary" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr bgcolor="#70b0f0" class="table-header">
+ <td align="left" colspan="2" class="table-header">
+ <span class="table-header">Functions</span></td>
+</tr>
+<tr>
+ <td width="15%" align="right" valign="top" class="summary">
+ <span class="summary-type"><tt class="rst-docutils literal">str</tt></span>
+ </td><td class="summary">
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr>
+ <td><span class="summary-sig"><a href="rjsmin-module.html#jsmin" class="summary-sig-name">jsmin</a>(<span class="summary-sig-arg">script</span>,
+ <span class="summary-sig-arg">keep_bang_comments</span>=<span class="summary-sig-default">False</span>)</span><br />
+ Minify javascript based on <a class="rst-reference external" href="http://www.crockford.com/javascript/jsmin.c" target="_top">jsmin.c by Douglas Crockford</a>.</td>
+ <td align="right" valign="top">
+ <span class="codelink"><a href="rjsmin-pysrc.html#jsmin">source&nbsp;code</a></span>
+
+ </td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+</table>
+<!-- ==================== FUNCTION DETAILS ==================== -->
+<a name="section-FunctionDetails"></a>
+<table class="details" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr bgcolor="#70b0f0" class="table-header">
+ <td align="left" colspan="2" class="table-header">
+ <span class="table-header">Function Details</span></td>
+</tr>
+</table>
+<a name="jsmin"></a>
+<div>
+<table class="details" border="1" cellpadding="3"
+ cellspacing="0" width="100%" bgcolor="white">
+<tr><td>
+ <table width="100%" cellpadding="0" cellspacing="0" border="0">
+ <tr valign="top"><td>
+ <h3 class="epydoc"><span class="sig"><span class="sig-name">jsmin</span>(<span class="sig-arg">script</span>,
+ <span class="sig-arg">keep_bang_comments</span>=<span class="sig-default">False</span>)</span>
+ </h3>
+ </td><td align="right" valign="top"
+ ><span class="codelink"><a href="rjsmin-pysrc.html#jsmin">source&nbsp;code</a></span>&nbsp;
+ </td>
+ </tr></table>
+
+ <p>Minify javascript based on <a class="rst-reference external" href="http://www.crockford.com/javascript/jsmin.c" target="_top">jsmin.c by Douglas Crockford</a>.</p>
+<p>Instead of parsing the stream char by char, it uses a regular
+expression approach which minifies the whole script with one big
+substitution regex.</p>
+ <dl class="fields">
+ <dt>Parameters:</dt>
+ <dd><ul class="nomargin-top">
+ <li><strong class="pname"><code>script</code></strong> (<tt class="rst-docutils literal">str</tt>) - Script to minify</li>
+ <li><strong class="pname"><code>keep_bang_comments</code></strong> (<tt class="rst-docutils literal">bool</tt>) - Keep comments starting with an exclamation mark? (<tt class="rst-docutils literal"><span class="pre">/*!...*/</span></tt>)</li>
+ </ul></dd>
+ <dt>Returns: <tt class="rst-docutils literal">str</tt></dt>
+ <dd>Minified script</dd>
+ </dl>
+</td></tr></table>
+</div>
+<br />
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/rjsmin-pysrc.html b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/rjsmin-pysrc.html
new file mode 100644
index 00000000000..acf0aaab3f1
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/docs/apidoc/rjsmin-pysrc.html
@@ -0,0 +1,617 @@
+<?xml version="1.0" encoding="ascii"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>rjsmin</title>
+ <link rel="stylesheet" href="epydoc.css" type="text/css" />
+ <script type="text/javascript" src="epydoc.js"></script>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="#204080"
+ alink="#204080">
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+<table width="100%" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="100%">
+ <span class="breadcrumbs">
+ Module&nbsp;rjsmin
+ </span>
+ </td>
+ <td>
+ <table cellpadding="0" cellspacing="0">
+ <!-- hide/show private -->
+ </table>
+ </td>
+ </tr>
+</table>
+<h1 class="epydoc">Source Code for <a href="rjsmin-module.html">Module rjsmin</a></h1>
+<pre class="py-src">
+<a name="L1"></a><tt class="py-lineno"> 1</tt> <tt class="py-line"><tt class="py-comment">#!/usr/bin/env python</tt> </tt>
+<a name="L2"></a><tt class="py-lineno"> 2</tt> <tt class="py-line"><tt class="py-comment"># -*- coding: ascii -*-</tt> </tt>
+<a name="L3"></a><tt class="py-lineno"> 3</tt> <tt class="py-line"><tt class="py-docstring">r"""</tt> </tt>
+<a name="L4"></a><tt class="py-lineno"> 4</tt> <tt class="py-line"><tt class="py-docstring">=====================</tt> </tt>
+<a name="L5"></a><tt class="py-lineno"> 5</tt> <tt class="py-line"><tt class="py-docstring"> Javascript Minifier</tt> </tt>
+<a name="L6"></a><tt class="py-lineno"> 6</tt> <tt class="py-line"><tt class="py-docstring">=====================</tt> </tt>
+<a name="L7"></a><tt class="py-lineno"> 7</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L8"></a><tt class="py-lineno"> 8</tt> <tt class="py-line"><tt class="py-docstring">rJSmin is a javascript minifier written in python.</tt> </tt>
+<a name="L9"></a><tt class="py-lineno"> 9</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L10"></a><tt class="py-lineno"> 10</tt> <tt class="py-line"><tt class="py-docstring">The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\\.</tt> </tt>
+<a name="L11"></a><tt class="py-lineno"> 11</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L12"></a><tt class="py-lineno"> 12</tt> <tt class="py-line"><tt class="py-docstring">:Copyright:</tt> </tt>
+<a name="L13"></a><tt class="py-lineno"> 13</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L14"></a><tt class="py-lineno"> 14</tt> <tt class="py-line"><tt class="py-docstring"> Copyright 2011 - 2015</tt> </tt>
+<a name="L15"></a><tt class="py-lineno"> 15</tt> <tt class="py-line"><tt class="py-docstring"> Andr\xe9 Malo or his licensors, as applicable</tt> </tt>
+<a name="L16"></a><tt class="py-lineno"> 16</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L17"></a><tt class="py-lineno"> 17</tt> <tt class="py-line"><tt class="py-docstring">:License:</tt> </tt>
+<a name="L18"></a><tt class="py-lineno"> 18</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L19"></a><tt class="py-lineno"> 19</tt> <tt class="py-line"><tt class="py-docstring"> Licensed under the Apache License, Version 2.0 (the "License");</tt> </tt>
+<a name="L20"></a><tt class="py-lineno"> 20</tt> <tt class="py-line"><tt class="py-docstring"> you may not use this file except in compliance with the License.</tt> </tt>
+<a name="L21"></a><tt class="py-lineno"> 21</tt> <tt class="py-line"><tt class="py-docstring"> You may obtain a copy of the License at</tt> </tt>
+<a name="L22"></a><tt class="py-lineno"> 22</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L23"></a><tt class="py-lineno"> 23</tt> <tt class="py-line"><tt class="py-docstring"> http://www.apache.org/licenses/LICENSE-2.0</tt> </tt>
+<a name="L24"></a><tt class="py-lineno"> 24</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L25"></a><tt class="py-lineno"> 25</tt> <tt class="py-line"><tt class="py-docstring"> Unless required by applicable law or agreed to in writing, software</tt> </tt>
+<a name="L26"></a><tt class="py-lineno"> 26</tt> <tt class="py-line"><tt class="py-docstring"> distributed under the License is distributed on an "AS IS" BASIS,</tt> </tt>
+<a name="L27"></a><tt class="py-lineno"> 27</tt> <tt class="py-line"><tt class="py-docstring"> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</tt> </tt>
+<a name="L28"></a><tt class="py-lineno"> 28</tt> <tt class="py-line"><tt class="py-docstring"> See the License for the specific language governing permissions and</tt> </tt>
+<a name="L29"></a><tt class="py-lineno"> 29</tt> <tt class="py-line"><tt class="py-docstring"> limitations under the License.</tt> </tt>
+<a name="L30"></a><tt class="py-lineno"> 30</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L31"></a><tt class="py-lineno"> 31</tt> <tt class="py-line"><tt class="py-docstring">The module is a re-implementation aiming for speed, so it can be used at</tt> </tt>
+<a name="L32"></a><tt class="py-lineno"> 32</tt> <tt class="py-line"><tt class="py-docstring">runtime (rather than during a preprocessing step). Usually it produces the</tt> </tt>
+<a name="L33"></a><tt class="py-lineno"> 33</tt> <tt class="py-line"><tt class="py-docstring">same results as the original ``jsmin.c``. It differs in the following ways:</tt> </tt>
+<a name="L34"></a><tt class="py-lineno"> 34</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L35"></a><tt class="py-lineno"> 35</tt> <tt class="py-line"><tt class="py-docstring">- there is no error detection: unterminated string, regex and comment</tt> </tt>
+<a name="L36"></a><tt class="py-lineno"> 36</tt> <tt class="py-line"><tt class="py-docstring"> literals are treated as regular javascript code and minified as such.</tt> </tt>
+<a name="L37"></a><tt class="py-lineno"> 37</tt> <tt class="py-line"><tt class="py-docstring">- Control characters inside string and regex literals are left untouched; they</tt> </tt>
+<a name="L38"></a><tt class="py-lineno"> 38</tt> <tt class="py-line"><tt class="py-docstring"> are not converted to spaces (nor to \\n)</tt> </tt>
+<a name="L39"></a><tt class="py-lineno"> 39</tt> <tt class="py-line"><tt class="py-docstring">- Newline characters are not allowed inside string and regex literals, except</tt> </tt>
+<a name="L40"></a><tt class="py-lineno"> 40</tt> <tt class="py-line"><tt class="py-docstring"> for line continuations in string literals (ECMA-5).</tt> </tt>
+<a name="L41"></a><tt class="py-lineno"> 41</tt> <tt class="py-line"><tt class="py-docstring">- "return /regex/" is recognized correctly.</tt> </tt>
+<a name="L42"></a><tt class="py-lineno"> 42</tt> <tt class="py-line"><tt class="py-docstring">- Line terminators after regex literals are handled more sensibly</tt> </tt>
+<a name="L43"></a><tt class="py-lineno"> 43</tt> <tt class="py-line"><tt class="py-docstring">- "+ +" and "- -" sequences are not collapsed to '++' or '--'</tt> </tt>
+<a name="L44"></a><tt class="py-lineno"> 44</tt> <tt class="py-line"><tt class="py-docstring">- Newlines before ! operators are removed more sensibly</tt> </tt>
+<a name="L45"></a><tt class="py-lineno"> 45</tt> <tt class="py-line"><tt class="py-docstring">- Comments starting with an exclamation mark (``!``) can be kept optionally</tt> </tt>
+<a name="L46"></a><tt class="py-lineno"> 46</tt> <tt class="py-line"><tt class="py-docstring">- rJSmin does not handle streams, but only complete strings. (However, the</tt> </tt>
+<a name="L47"></a><tt class="py-lineno"> 47</tt> <tt class="py-line"><tt class="py-docstring"> module provides a "streamy" interface).</tt> </tt>
+<a name="L48"></a><tt class="py-lineno"> 48</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L49"></a><tt class="py-lineno"> 49</tt> <tt class="py-line"><tt class="py-docstring">Since most parts of the logic are handled by the regex engine it's way faster</tt> </tt>
+<a name="L50"></a><tt class="py-lineno"> 50</tt> <tt class="py-line"><tt class="py-docstring">than the original python port of ``jsmin.c`` by Baruch Even. The speed factor</tt> </tt>
+<a name="L51"></a><tt class="py-lineno"> 51</tt> <tt class="py-line"><tt class="py-docstring">varies between about 6 and 55 depending on input and python version (it gets</tt> </tt>
+<a name="L52"></a><tt class="py-lineno"> 52</tt> <tt class="py-line"><tt class="py-docstring">faster the more compressed the input already is). Compared to the</tt> </tt>
+<a name="L53"></a><tt class="py-lineno"> 53</tt> <tt class="py-line"><tt class="py-docstring">speed-refactored python port by Dave St.Germain the performance gain is less</tt> </tt>
+<a name="L54"></a><tt class="py-lineno"> 54</tt> <tt class="py-line"><tt class="py-docstring">dramatic but still between 3 and 50 (for huge inputs). See the docs/BENCHMARKS</tt> </tt>
+<a name="L55"></a><tt class="py-lineno"> 55</tt> <tt class="py-line"><tt class="py-docstring">file for details.</tt> </tt>
+<a name="L56"></a><tt class="py-lineno"> 56</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L57"></a><tt class="py-lineno"> 57</tt> <tt class="py-line"><tt class="py-docstring">rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.</tt> </tt>
+<a name="L58"></a><tt class="py-lineno"> 58</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L59"></a><tt class="py-lineno"> 59</tt> <tt class="py-line"><tt class="py-docstring">Both python 2 and python 3 are supported.</tt> </tt>
+<a name="L60"></a><tt class="py-lineno"> 60</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L61"></a><tt class="py-lineno"> 61</tt> <tt class="py-line"><tt class="py-docstring">.. _jsmin.c by Douglas Crockford:</tt> </tt>
+<a name="L62"></a><tt class="py-lineno"> 62</tt> <tt class="py-line"><tt class="py-docstring"> http://www.crockford.com/javascript/jsmin.c</tt> </tt>
+<a name="L63"></a><tt class="py-lineno"> 63</tt> <tt class="py-line"><tt class="py-docstring">"""</tt> </tt>
+<a name="L64"></a><tt class="py-lineno"> 64</tt> <tt class="py-line"><tt class="py-keyword">if</tt> <tt id="link-0" class="py-name" targets="Variable rjsmin.__doc__=rjsmin-module.html#__doc__"><a title="rjsmin.__doc__" class="py-name" href="#" onclick="return doclink('link-0', '__doc__', 'link-0');">__doc__</a></tt><tt class="py-op">:</tt> </tt>
+<a name="L65"></a><tt class="py-lineno"> 65</tt> <tt class="py-line"> <tt class="py-comment"># pylint: disable = redefined-builtin</tt> </tt>
+<a name="L66"></a><tt class="py-lineno"> 66</tt> <tt class="py-line"> <tt id="link-1" class="py-name"><a title="rjsmin.__doc__" class="py-name" href="#" onclick="return doclink('link-1', '__doc__', 'link-0');">__doc__</a></tt> <tt class="py-op">=</tt> <tt id="link-2" class="py-name"><a title="rjsmin.__doc__" class="py-name" href="#" onclick="return doclink('link-2', '__doc__', 'link-0');">__doc__</a></tt><tt class="py-op">.</tt><tt class="py-name">encode</tt><tt class="py-op">(</tt><tt class="py-string">'ascii'</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">decode</tt><tt class="py-op">(</tt><tt class="py-string">'unicode_escape'</tt><tt class="py-op">)</tt> </tt>
+<a name="L67"></a><tt class="py-lineno"> 67</tt> <tt class="py-line"><tt class="py-name">__author__</tt> <tt class="py-op">=</tt> <tt class="py-string">r"Andr\xe9 Malo"</tt><tt class="py-op">.</tt><tt class="py-name">encode</tt><tt class="py-op">(</tt><tt class="py-string">'ascii'</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">decode</tt><tt class="py-op">(</tt><tt class="py-string">'unicode_escape'</tt><tt class="py-op">)</tt> </tt>
+<a name="L68"></a><tt class="py-lineno"> 68</tt> <tt class="py-line"><tt class="py-name">__docformat__</tt> <tt class="py-op">=</tt> <tt class="py-string">"restructuredtext en"</tt> </tt>
+<a name="L69"></a><tt class="py-lineno"> 69</tt> <tt class="py-line"><tt id="link-3" class="py-name" targets="Variable rjsmin.__license__=rjsmin-module.html#__license__"><a title="rjsmin.__license__" class="py-name" href="#" onclick="return doclink('link-3', '__license__', 'link-3');">__license__</a></tt> <tt class="py-op">=</tt> <tt class="py-string">"Apache License, Version 2.0"</tt> </tt>
+<a name="L70"></a><tt class="py-lineno"> 70</tt> <tt class="py-line"><tt class="py-name">__version__</tt> <tt class="py-op">=</tt> <tt class="py-string">'1.0.12'</tt> </tt>
+<a name="L71"></a><tt class="py-lineno"> 71</tt> <tt class="py-line"><tt class="py-name">__all__</tt> <tt class="py-op">=</tt> <tt class="py-op">[</tt><tt class="py-string">'jsmin'</tt><tt class="py-op">]</tt> </tt>
+<a name="L72"></a><tt class="py-lineno"> 72</tt> <tt class="py-line"> </tt>
+<a name="L73"></a><tt class="py-lineno"> 73</tt> <tt class="py-line"><tt class="py-keyword">import</tt> <tt class="py-name">re</tt> <tt class="py-keyword">as</tt> <tt class="py-name">_re</tt> </tt>
+<a name="L74"></a><tt class="py-lineno"> 74</tt> <tt class="py-line"> </tt>
+<a name="L75"></a><tt class="py-lineno"> 75</tt> <tt class="py-line"> </tt>
+<a name="_make_jsmin"></a><div id="_make_jsmin-def"><a name="L76"></a><tt class="py-lineno"> 76</tt> <a class="py-toggle" href="#" id="_make_jsmin-toggle" onclick="return toggle('_make_jsmin');">-</a><tt class="py-line"><tt class="py-keyword">def</tt> <a class="py-def-name" href="rjsmin-module.html#_make_jsmin">_make_jsmin</a><tt class="py-op">(</tt><tt class="py-param">python_only</tt><tt class="py-op">=</tt><tt class="py-name">False</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+</div><div id="_make_jsmin-collapsed" style="display:none;" pad="+++" indent="++++"></div><div id="_make_jsmin-expanded"><a name="L77"></a><tt class="py-lineno"> 77</tt> <tt class="py-line"> <tt class="py-docstring">"""</tt> </tt>
+<a name="L78"></a><tt class="py-lineno"> 78</tt> <tt class="py-line"><tt class="py-docstring"> Generate JS minifier based on `jsmin.c by Douglas Crockford`_</tt> </tt>
+<a name="L79"></a><tt class="py-lineno"> 79</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L80"></a><tt class="py-lineno"> 80</tt> <tt class="py-line"><tt class="py-docstring"> .. _jsmin.c by Douglas Crockford:</tt> </tt>
+<a name="L81"></a><tt class="py-lineno"> 81</tt> <tt class="py-line"><tt class="py-docstring"> http://www.crockford.com/javascript/jsmin.c</tt> </tt>
+<a name="L82"></a><tt class="py-lineno"> 82</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L83"></a><tt class="py-lineno"> 83</tt> <tt class="py-line"><tt class="py-docstring"> :Parameters:</tt> </tt>
+<a name="L84"></a><tt class="py-lineno"> 84</tt> <tt class="py-line"><tt class="py-docstring"> `python_only` : ``bool``</tt> </tt>
+<a name="L85"></a><tt class="py-lineno"> 85</tt> <tt class="py-line"><tt class="py-docstring"> Use only the python variant. If true, the c extension is not even</tt> </tt>
+<a name="L86"></a><tt class="py-lineno"> 86</tt> <tt class="py-line"><tt class="py-docstring"> tried to be loaded.</tt> </tt>
+<a name="L87"></a><tt class="py-lineno"> 87</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L88"></a><tt class="py-lineno"> 88</tt> <tt class="py-line"><tt class="py-docstring"> :Return: Minifier</tt> </tt>
+<a name="L89"></a><tt class="py-lineno"> 89</tt> <tt class="py-line"><tt class="py-docstring"> :Rtype: ``callable``</tt> </tt>
+<a name="L90"></a><tt class="py-lineno"> 90</tt> <tt class="py-line"><tt class="py-docstring"> """</tt> </tt>
+<a name="L91"></a><tt class="py-lineno"> 91</tt> <tt class="py-line"> <tt class="py-comment"># pylint: disable = unused-variable</tt> </tt>
+<a name="L92"></a><tt class="py-lineno"> 92</tt> <tt class="py-line"> <tt class="py-comment"># pylint: disable = too-many-locals</tt> </tt>
+<a name="L93"></a><tt class="py-lineno"> 93</tt> <tt class="py-line"> </tt>
+<a name="L94"></a><tt class="py-lineno"> 94</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-keyword">not</tt> <tt class="py-name">python_only</tt><tt class="py-op">:</tt> </tt>
+<a name="L95"></a><tt class="py-lineno"> 95</tt> <tt class="py-line"> <tt class="py-keyword">try</tt><tt class="py-op">:</tt> </tt>
+<a name="L96"></a><tt class="py-lineno"> 96</tt> <tt class="py-line"> <tt class="py-keyword">import</tt> <tt class="py-name">_rjsmin</tt> </tt>
+<a name="L97"></a><tt class="py-lineno"> 97</tt> <tt class="py-line"> <tt class="py-keyword">except</tt> <tt class="py-name">ImportError</tt><tt class="py-op">:</tt> </tt>
+<a name="L98"></a><tt class="py-lineno"> 98</tt> <tt class="py-line"> <tt class="py-keyword">pass</tt> </tt>
+<a name="L99"></a><tt class="py-lineno"> 99</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L100"></a><tt class="py-lineno">100</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">_rjsmin</tt><tt class="py-op">.</tt><tt id="link-4" class="py-name" targets="Function rjsmin.jsmin()=rjsmin-module.html#jsmin"><a title="rjsmin.jsmin" class="py-name" href="#" onclick="return doclink('link-4', 'jsmin', 'link-4');">jsmin</a></tt> </tt>
+<a name="L101"></a><tt class="py-lineno">101</tt> <tt class="py-line"> <tt class="py-keyword">try</tt><tt class="py-op">:</tt> </tt>
+<a name="L102"></a><tt class="py-lineno">102</tt> <tt class="py-line"> <tt class="py-name">xrange</tt> </tt>
+<a name="L103"></a><tt class="py-lineno">103</tt> <tt class="py-line"> <tt class="py-keyword">except</tt> <tt class="py-name">NameError</tt><tt class="py-op">:</tt> </tt>
+<a name="L104"></a><tt class="py-lineno">104</tt> <tt class="py-line"> <tt class="py-name">xrange</tt> <tt class="py-op">=</tt> <tt class="py-name">range</tt> <tt class="py-comment"># pylint: disable = redefined-builtin</tt> </tt>
+<a name="L105"></a><tt class="py-lineno">105</tt> <tt class="py-line"> </tt>
+<a name="L106"></a><tt class="py-lineno">106</tt> <tt class="py-line"> <tt class="py-name">space_chars</tt> <tt class="py-op">=</tt> <tt class="py-string">r'[\000-\011\013\014\016-\040]'</tt> </tt>
+<a name="L107"></a><tt class="py-lineno">107</tt> <tt class="py-line"> </tt>
+<a name="L108"></a><tt class="py-lineno">108</tt> <tt class="py-line"> <tt class="py-name">line_comment</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?://[^\r\n]*)'</tt> </tt>
+<a name="L109"></a><tt class="py-lineno">109</tt> <tt class="py-line"> <tt class="py-name">space_comment</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'</tt> </tt>
+<a name="L110"></a><tt class="py-lineno">110</tt> <tt class="py-line"> <tt class="py-name">space_comment_nobang</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:/\*(?!!)[^*]*\*+(?:[^/*][^*]*\*+)*/)'</tt> </tt>
+<a name="L111"></a><tt class="py-lineno">111</tt> <tt class="py-line"> <tt class="py-name">bang_comment</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:/\*![^*]*\*+(?:[^/*][^*]*\*+)*/)'</tt> </tt>
+<a name="L112"></a><tt class="py-lineno">112</tt> <tt class="py-line"> </tt>
+<a name="L113"></a><tt class="py-lineno">113</tt> <tt class="py-line"> <tt class="py-name">string1</tt> <tt class="py-op">=</tt> \ </tt>
+<a name="L114"></a><tt class="py-lineno">114</tt> <tt class="py-line"> <tt class="py-string">r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)'</tt> </tt>
+<a name="L115"></a><tt class="py-lineno">115</tt> <tt class="py-line"> <tt class="py-name">string2</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")'</tt> </tt>
+<a name="L116"></a><tt class="py-lineno">116</tt> <tt class="py-line"> <tt class="py-name">strings</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:%s|%s)'</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt><tt class="py-name">string1</tt><tt class="py-op">,</tt> <tt class="py-name">string2</tt><tt class="py-op">)</tt> </tt>
+<a name="L117"></a><tt class="py-lineno">117</tt> <tt class="py-line"> </tt>
+<a name="L118"></a><tt class="py-lineno">118</tt> <tt class="py-line"> <tt class="py-name">charclass</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'</tt> </tt>
+<a name="L119"></a><tt class="py-lineno">119</tt> <tt class="py-line"> <tt class="py-name">nospecial</tt> <tt class="py-op">=</tt> <tt class="py-string">r'[^/\\\[\r\n]'</tt> </tt>
+<a name="L120"></a><tt class="py-lineno">120</tt> <tt class="py-line"> <tt class="py-name">regex</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)'</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt> </tt>
+<a name="L121"></a><tt class="py-lineno">121</tt> <tt class="py-line"> <tt class="py-name">nospecial</tt><tt class="py-op">,</tt> <tt class="py-name">charclass</tt><tt class="py-op">,</tt> <tt class="py-name">nospecial</tt> </tt>
+<a name="L122"></a><tt class="py-lineno">122</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L123"></a><tt class="py-lineno">123</tt> <tt class="py-line"> <tt class="py-name">space</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:%s|%s)'</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt><tt class="py-name">space_chars</tt><tt class="py-op">,</tt> <tt class="py-name">space_comment</tt><tt class="py-op">)</tt> </tt>
+<a name="L124"></a><tt class="py-lineno">124</tt> <tt class="py-line"> <tt class="py-name">newline</tt> <tt class="py-op">=</tt> <tt class="py-string">r'(?:%s?[\r\n])'</tt> <tt class="py-op">%</tt> <tt class="py-name">line_comment</tt> </tt>
+<a name="L125"></a><tt class="py-lineno">125</tt> <tt class="py-line"> </tt>
+<a name="L126"></a><tt class="py-lineno">126</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">fix_charclass</tt><tt class="py-op">(</tt><tt class="py-param">result</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L127"></a><tt class="py-lineno">127</tt> <tt class="py-line"> <tt class="py-docstring">""" Fixup string of chars to fit into a regex char class """</tt> </tt>
+<a name="L128"></a><tt class="py-lineno">128</tt> <tt class="py-line"> <tt class="py-name">pos</tt> <tt class="py-op">=</tt> <tt class="py-name">result</tt><tt class="py-op">.</tt><tt class="py-name">find</tt><tt class="py-op">(</tt><tt class="py-string">'-'</tt><tt class="py-op">)</tt> </tt>
+<a name="L129"></a><tt class="py-lineno">129</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">pos</tt> <tt class="py-op">&gt;=</tt> <tt class="py-number">0</tt><tt class="py-op">:</tt> </tt>
+<a name="L130"></a><tt class="py-lineno">130</tt> <tt class="py-line"> <tt class="py-name">result</tt> <tt class="py-op">=</tt> <tt class="py-string">r'%s%s-'</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt><tt class="py-name">result</tt><tt class="py-op">[</tt><tt class="py-op">:</tt><tt class="py-name">pos</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> <tt class="py-name">result</tt><tt class="py-op">[</tt><tt class="py-name">pos</tt> <tt class="py-op">+</tt> <tt class="py-number">1</tt><tt class="py-op">:</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> </tt>
+<a name="L131"></a><tt class="py-lineno">131</tt> <tt class="py-line"> </tt>
+<a name="L132"></a><tt class="py-lineno">132</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">sequentize</tt><tt class="py-op">(</tt><tt class="py-param">string</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L133"></a><tt class="py-lineno">133</tt> <tt class="py-line"> <tt class="py-docstring">"""</tt> </tt>
+<a name="L134"></a><tt class="py-lineno">134</tt> <tt class="py-line"><tt class="py-docstring"> Notate consecutive characters as sequence</tt> </tt>
+<a name="L135"></a><tt class="py-lineno">135</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L136"></a><tt class="py-lineno">136</tt> <tt class="py-line"><tt class="py-docstring"> (1-4 instead of 1234)</tt> </tt>
+<a name="L137"></a><tt class="py-lineno">137</tt> <tt class="py-line"><tt class="py-docstring"> """</tt> </tt>
+<a name="L138"></a><tt class="py-lineno">138</tt> <tt class="py-line"> <tt class="py-name">first</tt><tt class="py-op">,</tt> <tt class="py-name">last</tt><tt class="py-op">,</tt> <tt class="py-name">result</tt> <tt class="py-op">=</tt> <tt class="py-name">None</tt><tt class="py-op">,</tt> <tt class="py-name">None</tt><tt class="py-op">,</tt> <tt class="py-op">[</tt><tt class="py-op">]</tt> </tt>
+<a name="L139"></a><tt class="py-lineno">139</tt> <tt class="py-line"> <tt class="py-keyword">for</tt> <tt class="py-name">char</tt> <tt class="py-keyword">in</tt> <tt class="py-name">map</tt><tt class="py-op">(</tt><tt class="py-name">ord</tt><tt class="py-op">,</tt> <tt class="py-name">string</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L140"></a><tt class="py-lineno">140</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">last</tt> <tt class="py-keyword">is</tt> <tt class="py-name">None</tt><tt class="py-op">:</tt> </tt>
+<a name="L141"></a><tt class="py-lineno">141</tt> <tt class="py-line"> <tt class="py-name">first</tt> <tt class="py-op">=</tt> <tt class="py-name">last</tt> <tt class="py-op">=</tt> <tt class="py-name">char</tt> </tt>
+<a name="L142"></a><tt class="py-lineno">142</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">last</tt> <tt class="py-op">+</tt> <tt class="py-number">1</tt> <tt class="py-op">==</tt> <tt class="py-name">char</tt><tt class="py-op">:</tt> </tt>
+<a name="L143"></a><tt class="py-lineno">143</tt> <tt class="py-line"> <tt class="py-name">last</tt> <tt class="py-op">=</tt> <tt class="py-name">char</tt> </tt>
+<a name="L144"></a><tt class="py-lineno">144</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L145"></a><tt class="py-lineno">145</tt> <tt class="py-line"> <tt class="py-name">result</tt><tt class="py-op">.</tt><tt class="py-name">append</tt><tt class="py-op">(</tt><tt class="py-op">(</tt><tt class="py-name">first</tt><tt class="py-op">,</tt> <tt class="py-name">last</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+<a name="L146"></a><tt class="py-lineno">146</tt> <tt class="py-line"> <tt class="py-name">first</tt> <tt class="py-op">=</tt> <tt class="py-name">last</tt> <tt class="py-op">=</tt> <tt class="py-name">char</tt> </tt>
+<a name="L147"></a><tt class="py-lineno">147</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">last</tt> <tt class="py-keyword">is</tt> <tt class="py-keyword">not</tt> <tt class="py-name">None</tt><tt class="py-op">:</tt> </tt>
+<a name="L148"></a><tt class="py-lineno">148</tt> <tt class="py-line"> <tt class="py-name">result</tt><tt class="py-op">.</tt><tt class="py-name">append</tt><tt class="py-op">(</tt><tt class="py-op">(</tt><tt class="py-name">first</tt><tt class="py-op">,</tt> <tt class="py-name">last</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+<a name="L149"></a><tt class="py-lineno">149</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">''</tt><tt class="py-op">.</tt><tt class="py-name">join</tt><tt class="py-op">(</tt><tt class="py-op">[</tt><tt class="py-string">'%s%s%s'</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt> </tt>
+<a name="L150"></a><tt class="py-lineno">150</tt> <tt class="py-line"> <tt class="py-name">chr</tt><tt class="py-op">(</tt><tt class="py-name">first</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L151"></a><tt class="py-lineno">151</tt> <tt class="py-line"> <tt class="py-name">last</tt> <tt class="py-op">&gt;</tt> <tt class="py-name">first</tt> <tt class="py-op">+</tt> <tt class="py-number">1</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'-'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L152"></a><tt class="py-lineno">152</tt> <tt class="py-line"> <tt class="py-name">last</tt> <tt class="py-op">!=</tt> <tt class="py-name">first</tt> <tt class="py-keyword">and</tt> <tt class="py-name">chr</tt><tt class="py-op">(</tt><tt class="py-name">last</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt> </tt>
+<a name="L153"></a><tt class="py-lineno">153</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-keyword">for</tt> <tt class="py-name">first</tt><tt class="py-op">,</tt> <tt class="py-name">last</tt> <tt class="py-keyword">in</tt> <tt class="py-name">result</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> <tt class="py-comment"># noqa</tt> </tt>
+</div><a name="L154"></a><tt class="py-lineno">154</tt> <tt class="py-line"> </tt>
+<a name="L155"></a><tt class="py-lineno">155</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt><tt class="py-op">(</tt> </tt>
+<a name="L156"></a><tt class="py-lineno">156</tt> <tt class="py-line"> <tt class="py-string">r'([\000-\040\047])'</tt><tt class="py-op">,</tt> <tt class="py-comment"># \047 for better portability</tt> </tt>
+<a name="L157"></a><tt class="py-lineno">157</tt> <tt class="py-line"> <tt class="py-keyword">lambda</tt> <tt class="py-name">m</tt><tt class="py-op">:</tt> <tt class="py-string">'\\%03o'</tt> <tt class="py-op">%</tt> <tt class="py-name">ord</tt><tt class="py-op">(</tt><tt class="py-name">m</tt><tt class="py-op">.</tt><tt class="py-name">group</tt><tt class="py-op">(</tt><tt class="py-number">1</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> <tt class="py-op">(</tt> </tt>
+<a name="L158"></a><tt class="py-lineno">158</tt> <tt class="py-line"> <tt class="py-name">sequentize</tt><tt class="py-op">(</tt><tt class="py-name">result</tt><tt class="py-op">)</tt> </tt>
+<a name="L159"></a><tt class="py-lineno">159</tt> <tt class="py-line"> <tt class="py-op">.</tt><tt class="py-name">replace</tt><tt class="py-op">(</tt><tt class="py-string">'\\'</tt><tt class="py-op">,</tt> <tt class="py-string">'\\\\'</tt><tt class="py-op">)</tt> </tt>
+<a name="L160"></a><tt class="py-lineno">160</tt> <tt class="py-line"> <tt class="py-op">.</tt><tt class="py-name">replace</tt><tt class="py-op">(</tt><tt class="py-string">'['</tt><tt class="py-op">,</tt> <tt class="py-string">'\\['</tt><tt class="py-op">)</tt> </tt>
+<a name="L161"></a><tt class="py-lineno">161</tt> <tt class="py-line"> <tt class="py-op">.</tt><tt class="py-name">replace</tt><tt class="py-op">(</tt><tt class="py-string">']'</tt><tt class="py-op">,</tt> <tt class="py-string">'\\]'</tt><tt class="py-op">)</tt> </tt>
+<a name="L162"></a><tt class="py-lineno">162</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L163"></a><tt class="py-lineno">163</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+</div><a name="L164"></a><tt class="py-lineno">164</tt> <tt class="py-line"> </tt>
+<a name="L165"></a><tt class="py-lineno">165</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">id_literal_</tt><tt class="py-op">(</tt><tt class="py-param">what</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L166"></a><tt class="py-lineno">166</tt> <tt class="py-line"> <tt class="py-docstring">""" Make id_literal like char class """</tt> </tt>
+<a name="L167"></a><tt class="py-lineno">167</tt> <tt class="py-line"> <tt class="py-name">match</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-name">what</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">match</tt> </tt>
+<a name="L168"></a><tt class="py-lineno">168</tt> <tt class="py-line"> <tt class="py-name">result</tt> <tt class="py-op">=</tt> <tt class="py-string">''</tt><tt class="py-op">.</tt><tt class="py-name">join</tt><tt class="py-op">(</tt><tt class="py-op">[</tt> </tt>
+<a name="L169"></a><tt class="py-lineno">169</tt> <tt class="py-line"> <tt class="py-name">chr</tt><tt class="py-op">(</tt><tt class="py-name">c</tt><tt class="py-op">)</tt> <tt class="py-keyword">for</tt> <tt class="py-name">c</tt> <tt class="py-keyword">in</tt> <tt class="py-name">xrange</tt><tt class="py-op">(</tt><tt class="py-number">127</tt><tt class="py-op">)</tt> <tt class="py-keyword">if</tt> <tt class="py-keyword">not</tt> <tt class="py-name">match</tt><tt class="py-op">(</tt><tt class="py-name">chr</tt><tt class="py-op">(</tt><tt class="py-name">c</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+<a name="L170"></a><tt class="py-lineno">170</tt> <tt class="py-line"> <tt class="py-op">]</tt><tt class="py-op">)</tt> </tt>
+<a name="L171"></a><tt class="py-lineno">171</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">'[^%s]'</tt> <tt class="py-op">%</tt> <tt class="py-name">fix_charclass</tt><tt class="py-op">(</tt><tt class="py-name">result</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L172"></a><tt class="py-lineno">172</tt> <tt class="py-line"> </tt>
+<a name="L173"></a><tt class="py-lineno">173</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">not_id_literal_</tt><tt class="py-op">(</tt><tt class="py-param">keep</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L174"></a><tt class="py-lineno">174</tt> <tt class="py-line"> <tt class="py-docstring">""" Make negated id_literal like char class """</tt> </tt>
+<a name="L175"></a><tt class="py-lineno">175</tt> <tt class="py-line"> <tt class="py-name">match</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-name">id_literal_</tt><tt class="py-op">(</tt><tt class="py-name">keep</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">match</tt> </tt>
+<a name="L176"></a><tt class="py-lineno">176</tt> <tt class="py-line"> <tt class="py-name">result</tt> <tt class="py-op">=</tt> <tt class="py-string">''</tt><tt class="py-op">.</tt><tt class="py-name">join</tt><tt class="py-op">(</tt><tt class="py-op">[</tt> </tt>
+<a name="L177"></a><tt class="py-lineno">177</tt> <tt class="py-line"> <tt class="py-name">chr</tt><tt class="py-op">(</tt><tt class="py-name">c</tt><tt class="py-op">)</tt> <tt class="py-keyword">for</tt> <tt class="py-name">c</tt> <tt class="py-keyword">in</tt> <tt class="py-name">xrange</tt><tt class="py-op">(</tt><tt class="py-number">127</tt><tt class="py-op">)</tt> <tt class="py-keyword">if</tt> <tt class="py-keyword">not</tt> <tt class="py-name">match</tt><tt class="py-op">(</tt><tt class="py-name">chr</tt><tt class="py-op">(</tt><tt class="py-name">c</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+<a name="L178"></a><tt class="py-lineno">178</tt> <tt class="py-line"> <tt class="py-op">]</tt><tt class="py-op">)</tt> </tt>
+<a name="L179"></a><tt class="py-lineno">179</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">r'[%s]'</tt> <tt class="py-op">%</tt> <tt class="py-name">fix_charclass</tt><tt class="py-op">(</tt><tt class="py-name">result</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L180"></a><tt class="py-lineno">180</tt> <tt class="py-line"> </tt>
+<a name="L181"></a><tt class="py-lineno">181</tt> <tt class="py-line"> <tt class="py-name">not_id_literal</tt> <tt class="py-op">=</tt> <tt class="py-name">not_id_literal_</tt><tt class="py-op">(</tt><tt class="py-string">r'[a-zA-Z0-9_$]'</tt><tt class="py-op">)</tt> </tt>
+<a name="L182"></a><tt class="py-lineno">182</tt> <tt class="py-line"> <tt class="py-name">preregex1</tt> <tt class="py-op">=</tt> <tt class="py-string">r'[(,=:\[!&amp;|?{};\r\n]'</tt> </tt>
+<a name="L183"></a><tt class="py-lineno">183</tt> <tt class="py-line"> <tt class="py-name">preregex2</tt> <tt class="py-op">=</tt> <tt class="py-string">r'%(not_id_literal)sreturn'</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L184"></a><tt class="py-lineno">184</tt> <tt class="py-line"> </tt>
+<a name="L185"></a><tt class="py-lineno">185</tt> <tt class="py-line"> <tt class="py-name">id_literal</tt> <tt class="py-op">=</tt> <tt class="py-name">id_literal_</tt><tt class="py-op">(</tt><tt class="py-string">r'[a-zA-Z0-9_$]'</tt><tt class="py-op">)</tt> </tt>
+<a name="L186"></a><tt class="py-lineno">186</tt> <tt class="py-line"> <tt class="py-name">id_literal_open</tt> <tt class="py-op">=</tt> <tt class="py-name">id_literal_</tt><tt class="py-op">(</tt><tt class="py-string">r'[a-zA-Z0-9_${\[(!+-]'</tt><tt class="py-op">)</tt> </tt>
+<a name="L187"></a><tt class="py-lineno">187</tt> <tt class="py-line"> <tt class="py-name">id_literal_close</tt> <tt class="py-op">=</tt> <tt class="py-name">id_literal_</tt><tt class="py-op">(</tt><tt class="py-string">r'[a-zA-Z0-9_$}\])"\047+-]'</tt><tt class="py-op">)</tt> </tt>
+<a name="L188"></a><tt class="py-lineno">188</tt> <tt class="py-line"> <tt class="py-name">post_regex_off</tt> <tt class="py-op">=</tt> <tt class="py-name">id_literal_</tt><tt class="py-op">(</tt><tt class="py-string">r'[^\000-\040}\])?:|,;.&amp;=+-]'</tt><tt class="py-op">)</tt> </tt>
+<a name="L189"></a><tt class="py-lineno">189</tt> <tt class="py-line"> </tt>
+<a name="L190"></a><tt class="py-lineno">190</tt> <tt class="py-line"> <tt class="py-name">dull</tt> <tt class="py-op">=</tt> <tt class="py-string">r'[^\047"/\000-\040]'</tt> </tt>
+<a name="L191"></a><tt class="py-lineno">191</tt> <tt class="py-line"> </tt>
+<a name="L192"></a><tt class="py-lineno">192</tt> <tt class="py-line"> <tt class="py-name">space_sub_simple</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-op">(</tt> </tt>
+<a name="L193"></a><tt class="py-lineno">193</tt> <tt class="py-line"> <tt class="py-comment"># noqa pylint: disable = bad-continuation</tt> </tt>
+<a name="L194"></a><tt class="py-lineno">194</tt> <tt class="py-line"> </tt>
+<a name="L195"></a><tt class="py-lineno">195</tt> <tt class="py-line"> <tt class="py-string">r'(%(dull)s+)'</tt> <tt class="py-comment"># 0</tt> </tt>
+<a name="L196"></a><tt class="py-lineno">196</tt> <tt class="py-line"> <tt class="py-string">r'|(%(strings)s%(dull)s*)'</tt> <tt class="py-comment"># 1</tt> </tt>
+<a name="L197"></a><tt class="py-lineno">197</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=%(preregex1)s)'</tt> </tt>
+<a name="L198"></a><tt class="py-lineno">198</tt> <tt class="py-line"> <tt class="py-string">r'%(space)s*(?:%(newline)s%(space)s*)*'</tt> </tt>
+<a name="L199"></a><tt class="py-lineno">199</tt> <tt class="py-line"> <tt class="py-string">r'(%(regex)s)'</tt> <tt class="py-comment"># 2</tt> </tt>
+<a name="L200"></a><tt class="py-lineno">200</tt> <tt class="py-line"> <tt class="py-string">r'(%(space)s*(?:%(newline)s%(space)s*)+'</tt> <tt class="py-comment"># 3</tt> </tt>
+<a name="L201"></a><tt class="py-lineno">201</tt> <tt class="py-line"> <tt class="py-string">r'(?=%(post_regex_off)s))?'</tt> </tt>
+<a name="L202"></a><tt class="py-lineno">202</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=%(preregex2)s)'</tt> </tt>
+<a name="L203"></a><tt class="py-lineno">203</tt> <tt class="py-line"> <tt class="py-string">r'%(space)s*(?:(%(newline)s)%(space)s*)*'</tt> <tt class="py-comment"># 4</tt> </tt>
+<a name="L204"></a><tt class="py-lineno">204</tt> <tt class="py-line"> <tt class="py-string">r'(%(regex)s)'</tt> <tt class="py-comment"># 5</tt> </tt>
+<a name="L205"></a><tt class="py-lineno">205</tt> <tt class="py-line"> <tt class="py-string">r'(%(space)s*(?:%(newline)s%(space)s*)+'</tt> <tt class="py-comment"># 6</tt> </tt>
+<a name="L206"></a><tt class="py-lineno">206</tt> <tt class="py-line"> <tt class="py-string">r'(?=%(post_regex_off)s))?'</tt> </tt>
+<a name="L207"></a><tt class="py-lineno">207</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=%(id_literal_close)s)'</tt> </tt>
+<a name="L208"></a><tt class="py-lineno">208</tt> <tt class="py-line"> <tt class="py-string">r'%(space)s*(?:(%(newline)s)%(space)s*)+'</tt> <tt class="py-comment"># 7</tt> </tt>
+<a name="L209"></a><tt class="py-lineno">209</tt> <tt class="py-line"> <tt class="py-string">r'(?=%(id_literal_open)s)'</tt> </tt>
+<a name="L210"></a><tt class="py-lineno">210</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)'</tt> <tt class="py-comment"># 8</tt> </tt>
+<a name="L211"></a><tt class="py-lineno">211</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=\+)(%(space)s)+(?=\+)'</tt> <tt class="py-comment"># 9</tt> </tt>
+<a name="L212"></a><tt class="py-lineno">212</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=-)(%(space)s)+(?=-)'</tt> <tt class="py-comment"># 10</tt> </tt>
+<a name="L213"></a><tt class="py-lineno">213</tt> <tt class="py-line"> <tt class="py-string">r'|%(space)s+'</tt> </tt>
+<a name="L214"></a><tt class="py-lineno">214</tt> <tt class="py-line"> <tt class="py-string">r'|(?:%(newline)s%(space)s*)+'</tt> </tt>
+<a name="L215"></a><tt class="py-lineno">215</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L216"></a><tt class="py-lineno">216</tt> <tt class="py-line"> </tt>
+<a name="L217"></a><tt class="py-lineno">217</tt> <tt class="py-line"> <tt class="py-comment"># print space_sub_simple.__self__.pattern</tt> </tt>
+<a name="L218"></a><tt class="py-lineno">218</tt> <tt class="py-line"> </tt>
+<a name="L219"></a><tt class="py-lineno">219</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">space_subber_simple</tt><tt class="py-op">(</tt><tt class="py-param">match</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L220"></a><tt class="py-lineno">220</tt> <tt class="py-line"> <tt class="py-docstring">""" Substitution callback """</tt> </tt>
+<a name="L221"></a><tt class="py-lineno">221</tt> <tt class="py-line"> <tt class="py-comment"># pylint: disable = too-many-return-statements</tt> </tt>
+<a name="L222"></a><tt class="py-lineno">222</tt> <tt class="py-line"> </tt>
+<a name="L223"></a><tt class="py-lineno">223</tt> <tt class="py-line"> <tt class="py-name">groups</tt> <tt class="py-op">=</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">groups</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L224"></a><tt class="py-lineno">224</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L225"></a><tt class="py-lineno">225</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> </tt>
+<a name="L226"></a><tt class="py-lineno">226</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L227"></a><tt class="py-lineno">227</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">]</tt> </tt>
+<a name="L228"></a><tt class="py-lineno">228</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">2</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L229"></a><tt class="py-lineno">229</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">3</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L230"></a><tt class="py-lineno">230</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">2</tt><tt class="py-op">]</tt> <tt class="py-op">+</tt> <tt class="py-string">'\n'</tt> </tt>
+<a name="L231"></a><tt class="py-lineno">231</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">2</tt><tt class="py-op">]</tt> </tt>
+<a name="L232"></a><tt class="py-lineno">232</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">5</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L233"></a><tt class="py-lineno">233</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">"%s%s%s"</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt> </tt>
+<a name="L234"></a><tt class="py-lineno">234</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">4</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L235"></a><tt class="py-lineno">235</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">5</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> </tt>
+<a name="L236"></a><tt class="py-lineno">236</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">6</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L237"></a><tt class="py-lineno">237</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L238"></a><tt class="py-lineno">238</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">7</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L239"></a><tt class="py-lineno">239</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">'\n'</tt> </tt>
+<a name="L240"></a><tt class="py-lineno">240</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">8</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">9</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">10</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L241"></a><tt class="py-lineno">241</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">' '</tt> </tt>
+<a name="L242"></a><tt class="py-lineno">242</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L243"></a><tt class="py-lineno">243</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">''</tt> </tt>
+</div><a name="L244"></a><tt class="py-lineno">244</tt> <tt class="py-line"> </tt>
+<a name="L245"></a><tt class="py-lineno">245</tt> <tt class="py-line"> <tt class="py-name">space_sub_banged</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-op">(</tt> </tt>
+<a name="L246"></a><tt class="py-lineno">246</tt> <tt class="py-line"> <tt class="py-comment"># noqa pylint: disable = bad-continuation</tt> </tt>
+<a name="L247"></a><tt class="py-lineno">247</tt> <tt class="py-line"> </tt>
+<a name="L248"></a><tt class="py-lineno">248</tt> <tt class="py-line"> <tt class="py-string">r'(%(dull)s+)'</tt> <tt class="py-comment"># 0</tt> </tt>
+<a name="L249"></a><tt class="py-lineno">249</tt> <tt class="py-line"> <tt class="py-string">r'|(%(strings)s%(dull)s*)'</tt> <tt class="py-comment"># 1</tt> </tt>
+<a name="L250"></a><tt class="py-lineno">250</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=%(preregex1)s)'</tt> </tt>
+<a name="L251"></a><tt class="py-lineno">251</tt> <tt class="py-line"> <tt class="py-string">r'(%(space)s*(?:%(newline)s%(space)s*)*)'</tt> <tt class="py-comment"># 2</tt> </tt>
+<a name="L252"></a><tt class="py-lineno">252</tt> <tt class="py-line"> <tt class="py-string">r'(%(regex)s)'</tt> <tt class="py-comment"># 3</tt> </tt>
+<a name="L253"></a><tt class="py-lineno">253</tt> <tt class="py-line"> <tt class="py-string">r'(%(space)s*(?:%(newline)s%(space)s*)+'</tt> <tt class="py-comment"># 4</tt> </tt>
+<a name="L254"></a><tt class="py-lineno">254</tt> <tt class="py-line"> <tt class="py-string">r'(?=%(post_regex_off)s))?'</tt> </tt>
+<a name="L255"></a><tt class="py-lineno">255</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=%(preregex2)s)'</tt> </tt>
+<a name="L256"></a><tt class="py-lineno">256</tt> <tt class="py-line"> <tt class="py-string">r'(%(space)s*(?:(%(newline)s)%(space)s*)*)'</tt> <tt class="py-comment"># 5, 6</tt> </tt>
+<a name="L257"></a><tt class="py-lineno">257</tt> <tt class="py-line"> <tt class="py-string">r'(%(regex)s)'</tt> <tt class="py-comment"># 7</tt> </tt>
+<a name="L258"></a><tt class="py-lineno">258</tt> <tt class="py-line"> <tt class="py-string">r'(%(space)s*(?:%(newline)s%(space)s*)+'</tt> <tt class="py-comment"># 8</tt> </tt>
+<a name="L259"></a><tt class="py-lineno">259</tt> <tt class="py-line"> <tt class="py-string">r'(?=%(post_regex_off)s))?'</tt> </tt>
+<a name="L260"></a><tt class="py-lineno">260</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=%(id_literal_close)s)'</tt> </tt>
+<a name="L261"></a><tt class="py-lineno">261</tt> <tt class="py-line"> <tt class="py-string">r'(%(space)s*(?:%(newline)s%(space)s*)+)'</tt> <tt class="py-comment"># 9</tt> </tt>
+<a name="L262"></a><tt class="py-lineno">262</tt> <tt class="py-line"> <tt class="py-string">r'(?=%(id_literal_open)s)'</tt> </tt>
+<a name="L263"></a><tt class="py-lineno">263</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=%(id_literal)s)(%(space)s+)(?=%(id_literal)s)'</tt> <tt class="py-comment"># 10</tt> </tt>
+<a name="L264"></a><tt class="py-lineno">264</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=\+)(%(space)s+)(?=\+)'</tt> <tt class="py-comment"># 11</tt> </tt>
+<a name="L265"></a><tt class="py-lineno">265</tt> <tt class="py-line"> <tt class="py-string">r'|(?&lt;=-)(%(space)s+)(?=-)'</tt> <tt class="py-comment"># 12</tt> </tt>
+<a name="L266"></a><tt class="py-lineno">266</tt> <tt class="py-line"> <tt class="py-string">r'|(%(space)s+)'</tt> <tt class="py-comment"># 13</tt> </tt>
+<a name="L267"></a><tt class="py-lineno">267</tt> <tt class="py-line"> <tt class="py-string">r'|((?:%(newline)s%(space)s*)+)'</tt> <tt class="py-comment"># 14</tt> </tt>
+<a name="L268"></a><tt class="py-lineno">268</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L269"></a><tt class="py-lineno">269</tt> <tt class="py-line"> </tt>
+<a name="L270"></a><tt class="py-lineno">270</tt> <tt class="py-line"> <tt class="py-comment"># print space_sub_banged.__self__.pattern</tt> </tt>
+<a name="L271"></a><tt class="py-lineno">271</tt> <tt class="py-line"> </tt>
+<a name="L272"></a><tt class="py-lineno">272</tt> <tt class="py-line"> <tt class="py-name">keep</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-op">(</tt> </tt>
+<a name="L273"></a><tt class="py-lineno">273</tt> <tt class="py-line"> <tt class="py-string">r'%(space_chars)s+|%(space_comment_nobang)s+|%(newline)s+'</tt> </tt>
+<a name="L274"></a><tt class="py-lineno">274</tt> <tt class="py-line"> <tt class="py-string">r'|(%(bang_comment)s+)'</tt> </tt>
+<a name="L275"></a><tt class="py-lineno">275</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L276"></a><tt class="py-lineno">276</tt> <tt class="py-line"> <tt class="py-name">keeper</tt> <tt class="py-op">=</tt> <tt class="py-keyword">lambda</tt> <tt class="py-name">m</tt><tt class="py-op">:</tt> <tt class="py-name">m</tt><tt class="py-op">.</tt><tt class="py-name">groups</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt> </tt>
+<a name="L277"></a><tt class="py-lineno">277</tt> <tt class="py-line"> </tt>
+<a name="L278"></a><tt class="py-lineno">278</tt> <tt class="py-line"> <tt class="py-comment"># print keep.__self__.pattern</tt> </tt>
+<a name="L279"></a><tt class="py-lineno">279</tt> <tt class="py-line"> </tt>
+<a name="L280"></a><tt class="py-lineno">280</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">space_subber_banged</tt><tt class="py-op">(</tt><tt class="py-param">match</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L281"></a><tt class="py-lineno">281</tt> <tt class="py-line"> <tt class="py-docstring">""" Substitution callback """</tt> </tt>
+<a name="L282"></a><tt class="py-lineno">282</tt> <tt class="py-line"> <tt class="py-comment"># pylint: disable = too-many-return-statements</tt> </tt>
+<a name="L283"></a><tt class="py-lineno">283</tt> <tt class="py-line"> </tt>
+<a name="L284"></a><tt class="py-lineno">284</tt> <tt class="py-line"> <tt class="py-name">groups</tt> <tt class="py-op">=</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">groups</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L285"></a><tt class="py-lineno">285</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L286"></a><tt class="py-lineno">286</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> </tt>
+<a name="L287"></a><tt class="py-lineno">287</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L288"></a><tt class="py-lineno">288</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">]</tt> </tt>
+<a name="L289"></a><tt class="py-lineno">289</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">3</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L290"></a><tt class="py-lineno">290</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">"%s%s%s%s"</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt> </tt>
+<a name="L291"></a><tt class="py-lineno">291</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">2</tt><tt class="py-op">]</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L292"></a><tt class="py-lineno">292</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">3</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> </tt>
+<a name="L293"></a><tt class="py-lineno">293</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">4</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L294"></a><tt class="py-lineno">294</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">4</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L295"></a><tt class="py-lineno">295</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L296"></a><tt class="py-lineno">296</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">7</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L297"></a><tt class="py-lineno">297</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-string">"%s%s%s%s%s"</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt> </tt>
+<a name="L298"></a><tt class="py-lineno">298</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">5</tt><tt class="py-op">]</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L299"></a><tt class="py-lineno">299</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">6</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L300"></a><tt class="py-lineno">300</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">7</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> </tt>
+<a name="L301"></a><tt class="py-lineno">301</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">8</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L302"></a><tt class="py-lineno">302</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">8</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L303"></a><tt class="py-lineno">303</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L304"></a><tt class="py-lineno">304</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">9</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L305"></a><tt class="py-lineno">305</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">9</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> <tt class="py-op">+</tt> <tt class="py-string">'\n'</tt> </tt>
+<a name="L306"></a><tt class="py-lineno">306</tt> <tt class="py-line"> <tt class="py-keyword">elif</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">10</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">11</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">12</tt><tt class="py-op">]</tt><tt class="py-op">:</tt> </tt>
+<a name="L307"></a><tt class="py-lineno">307</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">10</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">11</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">12</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> <tt class="py-string">' '</tt> </tt>
+<a name="L308"></a><tt class="py-lineno">308</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L309"></a><tt class="py-lineno">309</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">13</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">14</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L310"></a><tt class="py-lineno">310</tt> <tt class="py-line"> </tt>
+<a name="L311"></a><tt class="py-lineno">311</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">jsmin</tt><tt class="py-op">(</tt><tt class="py-param">script</tt><tt class="py-op">,</tt> <tt class="py-param">keep_bang_comments</tt><tt class="py-op">=</tt><tt class="py-name">False</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L312"></a><tt class="py-lineno">312</tt> <tt class="py-line"> <tt class="py-docstring">r"""</tt> </tt>
+<a name="L313"></a><tt class="py-lineno">313</tt> <tt class="py-line"><tt class="py-docstring"> Minify javascript based on `jsmin.c by Douglas Crockford`_\.</tt> </tt>
+<a name="L314"></a><tt class="py-lineno">314</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L315"></a><tt class="py-lineno">315</tt> <tt class="py-line"><tt class="py-docstring"> Instead of parsing the stream char by char, it uses a regular</tt> </tt>
+<a name="L316"></a><tt class="py-lineno">316</tt> <tt class="py-line"><tt class="py-docstring"> expression approach which minifies the whole script with one big</tt> </tt>
+<a name="L317"></a><tt class="py-lineno">317</tt> <tt class="py-line"><tt class="py-docstring"> substitution regex.</tt> </tt>
+<a name="L318"></a><tt class="py-lineno">318</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L319"></a><tt class="py-lineno">319</tt> <tt class="py-line"><tt class="py-docstring"> .. _jsmin.c by Douglas Crockford:</tt> </tt>
+<a name="L320"></a><tt class="py-lineno">320</tt> <tt class="py-line"><tt class="py-docstring"> http://www.crockford.com/javascript/jsmin.c</tt> </tt>
+<a name="L321"></a><tt class="py-lineno">321</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L322"></a><tt class="py-lineno">322</tt> <tt class="py-line"><tt class="py-docstring"> :Parameters:</tt> </tt>
+<a name="L323"></a><tt class="py-lineno">323</tt> <tt class="py-line"><tt class="py-docstring"> `script` : ``str``</tt> </tt>
+<a name="L324"></a><tt class="py-lineno">324</tt> <tt class="py-line"><tt class="py-docstring"> Script to minify</tt> </tt>
+<a name="L325"></a><tt class="py-lineno">325</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L326"></a><tt class="py-lineno">326</tt> <tt class="py-line"><tt class="py-docstring"> `keep_bang_comments` : ``bool``</tt> </tt>
+<a name="L327"></a><tt class="py-lineno">327</tt> <tt class="py-line"><tt class="py-docstring"> Keep comments starting with an exclamation mark? (``/*!...*/``)</tt> </tt>
+<a name="L328"></a><tt class="py-lineno">328</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L329"></a><tt class="py-lineno">329</tt> <tt class="py-line"><tt class="py-docstring"> :Return: Minified script</tt> </tt>
+<a name="L330"></a><tt class="py-lineno">330</tt> <tt class="py-line"><tt class="py-docstring"> :Rtype: ``str``</tt> </tt>
+<a name="L331"></a><tt class="py-lineno">331</tt> <tt class="py-line"><tt class="py-docstring"> """</tt> </tt>
+<a name="L332"></a><tt class="py-lineno">332</tt> <tt class="py-line"> <tt class="py-comment"># pylint: disable = redefined-outer-name</tt> </tt>
+<a name="L333"></a><tt class="py-lineno">333</tt> <tt class="py-line"> </tt>
+<a name="L334"></a><tt class="py-lineno">334</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-name">keep_bang_comments</tt><tt class="py-op">:</tt> </tt>
+<a name="L335"></a><tt class="py-lineno">335</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">space_sub_banged</tt><tt class="py-op">(</tt> </tt>
+<a name="L336"></a><tt class="py-lineno">336</tt> <tt class="py-line"> <tt class="py-name">space_subber_banged</tt><tt class="py-op">,</tt> <tt class="py-string">'\n%s\n'</tt> <tt class="py-op">%</tt> <tt class="py-name">script</tt> </tt>
+<a name="L337"></a><tt class="py-lineno">337</tt> <tt class="py-line"> <tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">strip</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L338"></a><tt class="py-lineno">338</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L339"></a><tt class="py-lineno">339</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">space_sub_simple</tt><tt class="py-op">(</tt> </tt>
+<a name="L340"></a><tt class="py-lineno">340</tt> <tt class="py-line"> <tt class="py-name">space_subber_simple</tt><tt class="py-op">,</tt> <tt class="py-string">'\n%s\n'</tt> <tt class="py-op">%</tt> <tt class="py-name">script</tt> </tt>
+<a name="L341"></a><tt class="py-lineno">341</tt> <tt class="py-line"> <tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">strip</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L342"></a><tt class="py-lineno">342</tt> <tt class="py-line"> </tt>
+<a name="L343"></a><tt class="py-lineno">343</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt id="link-5" class="py-name"><a title="rjsmin.jsmin" class="py-name" href="#" onclick="return doclink('link-5', 'jsmin', 'link-4');">jsmin</a></tt> </tt>
+</div><a name="L344"></a><tt class="py-lineno">344</tt> <tt class="py-line"> </tt>
+<a name="L345"></a><tt class="py-lineno">345</tt> <tt class="py-line"><tt id="link-6" class="py-name"><a title="rjsmin.jsmin" class="py-name" href="#" onclick="return doclink('link-6', 'jsmin', 'link-4');">jsmin</a></tt> <tt class="py-op">=</tt> <tt class="py-name">_make_jsmin</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L346"></a><tt class="py-lineno">346</tt> <tt class="py-line"> </tt>
+<a name="L347"></a><tt class="py-lineno">347</tt> <tt class="py-line"> </tt>
+<a name="jsmin_for_posers"></a><div id="jsmin_for_posers-def"><a name="L348"></a><tt class="py-lineno">348</tt> <a class="py-toggle" href="#" id="jsmin_for_posers-toggle" onclick="return toggle('jsmin_for_posers');">-</a><tt class="py-line"><tt class="py-keyword">def</tt> <a class="py-def-name" href="rjsmin-module.html#jsmin_for_posers">jsmin_for_posers</a><tt class="py-op">(</tt><tt class="py-param">script</tt><tt class="py-op">,</tt> <tt class="py-param">keep_bang_comments</tt><tt class="py-op">=</tt><tt class="py-name">False</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+</div><div id="jsmin_for_posers-collapsed" style="display:none;" pad="+++" indent="++++"></div><div id="jsmin_for_posers-expanded"><a name="L349"></a><tt class="py-lineno">349</tt> <tt class="py-line"> <tt class="py-docstring">r"""</tt> </tt>
+<a name="L350"></a><tt class="py-lineno">350</tt> <tt class="py-line"><tt class="py-docstring"> Minify javascript based on `jsmin.c by Douglas Crockford`_\.</tt> </tt>
+<a name="L351"></a><tt class="py-lineno">351</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L352"></a><tt class="py-lineno">352</tt> <tt class="py-line"><tt class="py-docstring"> Instead of parsing the stream char by char, it uses a regular</tt> </tt>
+<a name="L353"></a><tt class="py-lineno">353</tt> <tt class="py-line"><tt class="py-docstring"> expression approach which minifies the whole script with one big</tt> </tt>
+<a name="L354"></a><tt class="py-lineno">354</tt> <tt class="py-line"><tt class="py-docstring"> substitution regex.</tt> </tt>
+<a name="L355"></a><tt class="py-lineno">355</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L356"></a><tt class="py-lineno">356</tt> <tt class="py-line"><tt class="py-docstring"> .. _jsmin.c by Douglas Crockford:</tt> </tt>
+<a name="L357"></a><tt class="py-lineno">357</tt> <tt class="py-line"><tt class="py-docstring"> http://www.crockford.com/javascript/jsmin.c</tt> </tt>
+<a name="L358"></a><tt class="py-lineno">358</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L359"></a><tt class="py-lineno">359</tt> <tt class="py-line"><tt class="py-docstring"> :Warning: This function is the digest of a _make_jsmin() call. It just</tt> </tt>
+<a name="L360"></a><tt class="py-lineno">360</tt> <tt class="py-line"><tt class="py-docstring"> utilizes the resulting regexes. It's here for fun and may</tt> </tt>
+<a name="L361"></a><tt class="py-lineno">361</tt> <tt class="py-line"><tt class="py-docstring"> vanish any time. Use the `jsmin` function instead.</tt> </tt>
+<a name="L362"></a><tt class="py-lineno">362</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L363"></a><tt class="py-lineno">363</tt> <tt class="py-line"><tt class="py-docstring"> :Parameters:</tt> </tt>
+<a name="L364"></a><tt class="py-lineno">364</tt> <tt class="py-line"><tt class="py-docstring"> `script` : ``str``</tt> </tt>
+<a name="L365"></a><tt class="py-lineno">365</tt> <tt class="py-line"><tt class="py-docstring"> Script to minify</tt> </tt>
+<a name="L366"></a><tt class="py-lineno">366</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L367"></a><tt class="py-lineno">367</tt> <tt class="py-line"><tt class="py-docstring"> `keep_bang_comments` : ``bool``</tt> </tt>
+<a name="L368"></a><tt class="py-lineno">368</tt> <tt class="py-line"><tt class="py-docstring"> Keep comments starting with an exclamation mark? (``/*!...*/``)</tt> </tt>
+<a name="L369"></a><tt class="py-lineno">369</tt> <tt class="py-line"><tt class="py-docstring"></tt> </tt>
+<a name="L370"></a><tt class="py-lineno">370</tt> <tt class="py-line"><tt class="py-docstring"> :Return: Minified script</tt> </tt>
+<a name="L371"></a><tt class="py-lineno">371</tt> <tt class="py-line"><tt class="py-docstring"> :Rtype: ``str``</tt> </tt>
+<a name="L372"></a><tt class="py-lineno">372</tt> <tt class="py-line"><tt class="py-docstring"> """</tt> </tt>
+<a name="L373"></a><tt class="py-lineno">373</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-keyword">not</tt> <tt class="py-name">keep_bang_comments</tt><tt class="py-op">:</tt> </tt>
+<a name="L374"></a><tt class="py-lineno">374</tt> <tt class="py-line"> <tt class="py-name">rex</tt> <tt class="py-op">=</tt> <tt class="py-op">(</tt> </tt>
+<a name="L375"></a><tt class="py-lineno">375</tt> <tt class="py-line"> <tt class="py-string">r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]'</tt> </tt>
+<a name="L376"></a><tt class="py-lineno">376</tt> <tt class="py-line"> <tt class="py-string">r'|\r?\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]'</tt> </tt>
+<a name="L377"></a><tt class="py-lineno">377</tt> <tt class="py-line"> <tt class="py-string">r'|\r?\n|\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?&lt;=[(,=:\[!&amp;|?'</tt> </tt>
+<a name="L378"></a><tt class="py-lineno">378</tt> <tt class="py-line"> <tt class="py-string">r'{};\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*'</tt> </tt>
+<a name="L379"></a><tt class="py-lineno">379</tt> <tt class="py-line"> <tt class="py-string">r'][^*]*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\0'</tt> </tt>
+<a name="L380"></a><tt class="py-lineno">380</tt> <tt class="py-line"> <tt class="py-string">r'14\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r'</tt> </tt>
+<a name="L381"></a><tt class="py-lineno">381</tt> <tt class="py-line"> <tt class="py-string">r'\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r'</tt> </tt>
+<a name="L382"></a><tt class="py-lineno">382</tt> <tt class="py-line"> <tt class="py-string">r'\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))((?:[\000-\011\013\014'</tt> </tt>
+<a name="L383"></a><tt class="py-lineno">383</tt> <tt class="py-line"> <tt class="py-string">r'\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:(?:(?://[^\r'</tt> </tt>
+<a name="L384"></a><tt class="py-lineno">384</tt> <tt class="py-line"> <tt class="py-string">r'\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:'</tt> </tt>
+<a name="L385"></a><tt class="py-lineno">385</tt> <tt class="py-line"> <tt class="py-string">r'[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&amp;)+,.:;=?\]|}-]))?|(?&lt;=[\00'</tt> </tt>
+<a name="L386"></a><tt class="py-lineno">386</tt> <tt class="py-line"> <tt class="py-string">r'0-#%-,./:-@\[-^`{-~-]return)(?:[\000-\011\013\014\016-\040]|(?'</tt> </tt>
+<a name="L387"></a><tt class="py-lineno">387</tt> <tt class="py-line"> <tt class="py-string">r':/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?[\r\n]'</tt> </tt>
+<a name="L388"></a><tt class="py-lineno">388</tt> <tt class="py-line"> <tt class="py-string">r'))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*'</tt> </tt>
+<a name="L389"></a><tt class="py-lineno">389</tt> <tt class="py-line"> <tt class="py-string">r'\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\['</tt> </tt>
+<a name="L390"></a><tt class="py-lineno">390</tt> <tt class="py-line"> <tt class="py-string">r'[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))(('</tt> </tt>
+<a name="L391"></a><tt class="py-lineno">391</tt> <tt class="py-line"> <tt class="py-string">r'?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)'</tt> </tt>
+<a name="L392"></a><tt class="py-lineno">392</tt> <tt class="py-line"> <tt class="py-string">r'*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\04'</tt> </tt>
+<a name="L393"></a><tt class="py-lineno">393</tt> <tt class="py-line"> <tt class="py-string">r'0]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&amp;)+,.:;'</tt> </tt>
+<a name="L394"></a><tt class="py-lineno">394</tt> <tt class="py-line"> <tt class="py-string">r'=?\]|}-]))?|(?&lt;=[^\000-!#%&amp;(*,./:-@\[\\^`{|~])(?:[\000-\011\01'</tt> </tt>
+<a name="L395"></a><tt class="py-lineno">395</tt> <tt class="py-line"> <tt class="py-string">r'3\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?:'</tt> </tt>
+<a name="L396"></a><tt class="py-lineno">396</tt> <tt class="py-line"> <tt class="py-string">r'//[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]'</tt> </tt>
+<a name="L397"></a><tt class="py-lineno">397</tt> <tt class="py-line"> <tt class="py-string">r'*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./:-@\\-^'</tt> </tt>
+<a name="L398"></a><tt class="py-lineno">398</tt> <tt class="py-line"> <tt class="py-string">r'`|-~])|(?&lt;=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\014\0'</tt> </tt>
+<a name="L399"></a><tt class="py-lineno">399</tt> <tt class="py-line"> <tt class="py-string">r'16-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./'</tt> </tt>
+<a name="L400"></a><tt class="py-lineno">400</tt> <tt class="py-line"> <tt class="py-string">r':-@\[-^`{-~-])|(?&lt;=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*['</tt> </tt>
+<a name="L401"></a><tt class="py-lineno">401</tt> <tt class="py-line"> <tt class="py-string">r'^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?&lt;=-)((?:[\000-\011\013'</tt> </tt>
+<a name="L402"></a><tt class="py-lineno">402</tt> <tt class="py-line"> <tt class="py-string">r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:['</tt> </tt>
+<a name="L403"></a><tt class="py-lineno">403</tt> <tt class="py-line"> <tt class="py-string">r'\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'</tt> </tt>
+<a name="L404"></a><tt class="py-lineno">404</tt> <tt class="py-line"> <tt class="py-string">r')+|(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]'</tt> </tt>
+<a name="L405"></a><tt class="py-lineno">405</tt> <tt class="py-line"> <tt class="py-string">r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+'</tt> </tt>
+<a name="L406"></a><tt class="py-lineno">406</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L407"></a><tt class="py-lineno">407</tt> <tt class="py-line"> </tt>
+<a name="L408"></a><tt class="py-lineno">408</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">subber</tt><tt class="py-op">(</tt><tt class="py-param">match</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L409"></a><tt class="py-lineno">409</tt> <tt class="py-line"> <tt class="py-docstring">""" Substitution callback """</tt> </tt>
+<a name="L410"></a><tt class="py-lineno">410</tt> <tt class="py-line"> <tt class="py-name">groups</tt> <tt class="py-op">=</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">groups</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L411"></a><tt class="py-lineno">411</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-op">(</tt> </tt>
+<a name="L412"></a><tt class="py-lineno">412</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L413"></a><tt class="py-lineno">413</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L414"></a><tt class="py-lineno">414</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">3</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">2</tt><tt class="py-op">]</tt> <tt class="py-op">+</tt> <tt class="py-string">'\n'</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L415"></a><tt class="py-lineno">415</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">2</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L416"></a><tt class="py-lineno">416</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">5</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">"%s%s%s"</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt> </tt>
+<a name="L417"></a><tt class="py-lineno">417</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">4</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L418"></a><tt class="py-lineno">418</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">5</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> </tt>
+<a name="L419"></a><tt class="py-lineno">419</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">6</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L420"></a><tt class="py-lineno">420</tt> <tt class="py-line"> <tt class="py-op">)</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L421"></a><tt class="py-lineno">421</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">7</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L422"></a><tt class="py-lineno">422</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">8</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">' '</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L423"></a><tt class="py-lineno">423</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">9</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">' '</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L424"></a><tt class="py-lineno">424</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">10</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">' '</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L425"></a><tt class="py-lineno">425</tt> <tt class="py-line"> <tt class="py-string">''</tt> </tt>
+<a name="L426"></a><tt class="py-lineno">426</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+</div><a name="L427"></a><tt class="py-lineno">427</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L428"></a><tt class="py-lineno">428</tt> <tt class="py-line"> <tt class="py-name">rex</tt> <tt class="py-op">=</tt> <tt class="py-op">(</tt> </tt>
+<a name="L429"></a><tt class="py-lineno">429</tt> <tt class="py-line"> <tt class="py-string">r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]'</tt> </tt>
+<a name="L430"></a><tt class="py-lineno">430</tt> <tt class="py-line"> <tt class="py-string">r'|\r?\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]'</tt> </tt>
+<a name="L431"></a><tt class="py-lineno">431</tt> <tt class="py-line"> <tt class="py-string">r'|\r?\n|\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?&lt;=[(,=:\[!&amp;|?'</tt> </tt>
+<a name="L432"></a><tt class="py-lineno">432</tt> <tt class="py-line"> <tt class="py-string">r'{};\r\n])((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/'</tt> </tt>
+<a name="L433"></a><tt class="py-lineno">433</tt> <tt class="py-line"> <tt class="py-string">r'*][^*]*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013'</tt> </tt>
+<a name="L434"></a><tt class="py-lineno">434</tt> <tt class="py-line"> <tt class="py-string">r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*)((?:/(?!'</tt> </tt>
+<a name="L435"></a><tt class="py-lineno">435</tt> <tt class="py-line"> <tt class="py-string">r'[\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^'</tt> </tt>
+<a name="L436"></a><tt class="py-lineno">436</tt> <tt class="py-line"> <tt class="py-string">r'\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))((?:[\000-\011\013\01'</tt> </tt>
+<a name="L437"></a><tt class="py-lineno">437</tt> <tt class="py-line"> <tt class="py-string">r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:(?:(?://[^'</tt> </tt>
+<a name="L438"></a><tt class="py-lineno">438</tt> <tt class="py-line"> <tt class="py-string">r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+('</tt> </tt>
+<a name="L439"></a><tt class="py-lineno">439</tt> <tt class="py-line"> <tt class="py-string">r'?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&amp;)+,.:;=?\]|}-]))?|(?&lt;=['</tt> </tt>
+<a name="L440"></a><tt class="py-lineno">440</tt> <tt class="py-line"> <tt class="py-string">r'\000-#%-,./:-@\[-^`{-~-]return)((?:[\000-\011\013\014\016-\040'</tt> </tt>
+<a name="L441"></a><tt class="py-lineno">441</tt> <tt class="py-line"> <tt class="py-string">r']|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?['</tt> </tt>
+<a name="L442"></a><tt class="py-lineno">442</tt> <tt class="py-line"> <tt class="py-string">r'\r\n]))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*]['</tt> </tt>
+<a name="L443"></a><tt class="py-lineno">443</tt> <tt class="py-line"> <tt class="py-string">r'^*]*\*+)*/))*)*)((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|'</tt> </tt>
+<a name="L444"></a><tt class="py-lineno">444</tt> <tt class="py-line"> <tt class="py-string">r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*'</tt> </tt>
+<a name="L445"></a><tt class="py-lineno">445</tt> <tt class="py-line"> <tt class="py-string">r'/))((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]'</tt> </tt>
+<a name="L446"></a><tt class="py-lineno">446</tt> <tt class="py-line"> <tt class="py-string">r'*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\01'</tt> </tt>
+<a name="L447"></a><tt class="py-lineno">447</tt> <tt class="py-line"> <tt class="py-string">r'6-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&amp;)'</tt> </tt>
+<a name="L448"></a><tt class="py-lineno">448</tt> <tt class="py-line"> <tt class="py-string">r'+,.:;=?\]|}-]))?|(?&lt;=[^\000-!#%&amp;(*,./:-@\[\\^`{|~])((?:[\000-'</tt> </tt>
+<a name="L449"></a><tt class="py-lineno">449</tt> <tt class="py-line"> <tt class="py-string">r'\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:'</tt> </tt>
+<a name="L450"></a><tt class="py-lineno">450</tt> <tt class="py-line"> <tt class="py-string">r'(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/'</tt> </tt>
+<a name="L451"></a><tt class="py-lineno">451</tt> <tt class="py-line"> <tt class="py-string">r'\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+)(?=[^\000-\040"#%-\047)*,./'</tt> </tt>
+<a name="L452"></a><tt class="py-lineno">452</tt> <tt class="py-line"> <tt class="py-string">r':-@\\-^`|-~])|(?&lt;=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\01'</tt> </tt>
+<a name="L453"></a><tt class="py-lineno">453</tt> <tt class="py-line"> <tt class="py-string">r'3\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=[^\000'</tt> </tt>
+<a name="L454"></a><tt class="py-lineno">454</tt> <tt class="py-line"> <tt class="py-string">r'-#%-,./:-@\[-^`{-~-])|(?&lt;=\+)((?:[\000-\011\013\014\016-\040]|'</tt> </tt>
+<a name="L455"></a><tt class="py-lineno">455</tt> <tt class="py-line"> <tt class="py-string">r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=\+)|(?&lt;=-)((?:[\000-\0'</tt> </tt>
+<a name="L456"></a><tt class="py-lineno">456</tt> <tt class="py-line"> <tt class="py-string">r'11\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=-'</tt> </tt>
+<a name="L457"></a><tt class="py-lineno">457</tt> <tt class="py-line"> <tt class="py-string">r')|((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*'</tt> </tt>
+<a name="L458"></a><tt class="py-lineno">458</tt> <tt class="py-line"> <tt class="py-string">r'\*+)*/))+)|((?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014'</tt> </tt>
+<a name="L459"></a><tt class="py-lineno">459</tt> <tt class="py-line"> <tt class="py-string">r'\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+)'</tt> </tt>
+<a name="L460"></a><tt class="py-lineno">460</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+<a name="L461"></a><tt class="py-lineno">461</tt> <tt class="py-line"> </tt>
+<a name="L462"></a><tt class="py-lineno">462</tt> <tt class="py-line"> <tt class="py-name">keep</tt> <tt class="py-op">=</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">compile</tt><tt class="py-op">(</tt><tt class="py-op">(</tt> </tt>
+<a name="L463"></a><tt class="py-lineno">463</tt> <tt class="py-line"> <tt class="py-string">r'[\000-\011\013\014\016-\040]+|(?:/\*(?!!)[^*]*\*+(?:[^/*][^*]*'</tt> </tt>
+<a name="L464"></a><tt class="py-lineno">464</tt> <tt class="py-line"> <tt class="py-string">r'\*+)*/)+|(?:(?://[^\r\n]*)?[\r\n])+|((?:/\*![^*]*\*+(?:[^/*][^'</tt> </tt>
+<a name="L465"></a><tt class="py-lineno">465</tt> <tt class="py-line"> <tt class="py-string">r'*]*\*+)*/)+)'</tt> </tt>
+<a name="L466"></a><tt class="py-lineno">466</tt> <tt class="py-line"> <tt class="py-op">)</tt> <tt class="py-op">%</tt> <tt class="py-name">locals</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt> </tt>
+<a name="L467"></a><tt class="py-lineno">467</tt> <tt class="py-line"> <tt class="py-name">keeper</tt> <tt class="py-op">=</tt> <tt class="py-keyword">lambda</tt> <tt class="py-name">m</tt><tt class="py-op">:</tt> <tt class="py-name">m</tt><tt class="py-op">.</tt><tt class="py-name">groups</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt> </tt>
+<a name="L468"></a><tt class="py-lineno">468</tt> <tt class="py-line"> </tt>
+<a name="L469"></a><tt class="py-lineno">469</tt> <tt class="py-line"> <tt class="py-keyword">def</tt> <tt class="py-def-name">subber</tt><tt class="py-op">(</tt><tt class="py-param">match</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+<a name="L470"></a><tt class="py-lineno">470</tt> <tt class="py-line"> <tt class="py-docstring">""" Substitution callback """</tt> </tt>
+<a name="L471"></a><tt class="py-lineno">471</tt> <tt class="py-line"> <tt class="py-name">groups</tt> <tt class="py-op">=</tt> <tt class="py-name">match</tt><tt class="py-op">.</tt><tt class="py-name">groups</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L472"></a><tt class="py-lineno">472</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-op">(</tt> </tt>
+<a name="L473"></a><tt class="py-lineno">473</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">0</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L474"></a><tt class="py-lineno">474</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L475"></a><tt class="py-lineno">475</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">3</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">"%s%s%s%s"</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt> </tt>
+<a name="L476"></a><tt class="py-lineno">476</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">2</tt><tt class="py-op">]</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L477"></a><tt class="py-lineno">477</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">3</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> </tt>
+<a name="L478"></a><tt class="py-lineno">478</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">4</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L479"></a><tt class="py-lineno">479</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">4</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L480"></a><tt class="py-lineno">480</tt> <tt class="py-line"> <tt class="py-op">)</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L481"></a><tt class="py-lineno">481</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">7</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">"%s%s%s%s%s"</tt> <tt class="py-op">%</tt> <tt class="py-op">(</tt> </tt>
+<a name="L482"></a><tt class="py-lineno">482</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">5</tt><tt class="py-op">]</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L483"></a><tt class="py-lineno">483</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">6</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L484"></a><tt class="py-lineno">484</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">7</tt><tt class="py-op">]</tt><tt class="py-op">,</tt> </tt>
+<a name="L485"></a><tt class="py-lineno">485</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">8</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> </tt>
+<a name="L486"></a><tt class="py-lineno">486</tt> <tt class="py-line"> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">8</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-string">'\n'</tt> <tt class="py-keyword">or</tt> <tt class="py-string">''</tt><tt class="py-op">,</tt> </tt>
+<a name="L487"></a><tt class="py-lineno">487</tt> <tt class="py-line"> <tt class="py-op">)</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L488"></a><tt class="py-lineno">488</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">9</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">9</tt><tt class="py-op">]</tt> <tt class="py-op">+</tt> <tt class="py-string">'\n'</tt><tt class="py-op">)</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L489"></a><tt class="py-lineno">489</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">10</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">10</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> <tt class="py-string">' '</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L490"></a><tt class="py-lineno">490</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">11</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">11</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> <tt class="py-string">' '</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L491"></a><tt class="py-lineno">491</tt> <tt class="py-line"> <tt class="py-op">(</tt><tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">12</tt><tt class="py-op">]</tt> <tt class="py-keyword">and</tt> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">12</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> <tt class="py-string">' '</tt><tt class="py-op">)</tt> <tt class="py-keyword">or</tt> </tt>
+<a name="L492"></a><tt class="py-lineno">492</tt> <tt class="py-line"> <tt class="py-name">keep</tt><tt class="py-op">(</tt><tt class="py-name">keeper</tt><tt class="py-op">,</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">13</tt><tt class="py-op">]</tt> <tt class="py-keyword">or</tt> <tt class="py-name">groups</tt><tt class="py-op">[</tt><tt class="py-number">14</tt><tt class="py-op">]</tt><tt class="py-op">)</tt> </tt>
+<a name="L493"></a><tt class="py-lineno">493</tt> <tt class="py-line"> <tt class="py-op">)</tt> </tt>
+</div><a name="L494"></a><tt class="py-lineno">494</tt> <tt class="py-line"> </tt>
+<a name="L495"></a><tt class="py-lineno">495</tt> <tt class="py-line"> <tt class="py-keyword">return</tt> <tt class="py-name">_re</tt><tt class="py-op">.</tt><tt class="py-name">sub</tt><tt class="py-op">(</tt><tt class="py-name">rex</tt><tt class="py-op">,</tt> <tt class="py-name">subber</tt><tt class="py-op">,</tt> <tt class="py-string">'\n%s\n'</tt> <tt class="py-op">%</tt> <tt class="py-name">script</tt><tt class="py-op">)</tt><tt class="py-op">.</tt><tt class="py-name">strip</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L496"></a><tt class="py-lineno">496</tt> <tt class="py-line"> </tt>
+<a name="L497"></a><tt class="py-lineno">497</tt> <tt class="py-line"> </tt>
+<a name="L498"></a><tt class="py-lineno">498</tt> <tt class="py-line"><tt class="py-keyword">if</tt> <tt class="py-name">__name__</tt> <tt class="py-op">==</tt> <tt class="py-string">'__main__'</tt><tt class="py-op">:</tt> </tt>
+<a name="main"></a><div id="main-def"><a name="L499"></a><tt class="py-lineno">499</tt> <a class="py-toggle" href="#" id="main-toggle" onclick="return toggle('main');">-</a><tt class="py-line"> <tt class="py-keyword">def</tt> <a class="py-def-name" href="rjsmin-module.html#main">main</a><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">:</tt> </tt>
+</div><div id="main-collapsed" style="display:none;" pad="+++" indent="++++++++"></div><div id="main-expanded"><a name="L500"></a><tt class="py-lineno">500</tt> <tt class="py-line"> <tt class="py-docstring">""" Main """</tt> </tt>
+<a name="L501"></a><tt class="py-lineno">501</tt> <tt class="py-line"> <tt class="py-keyword">import</tt> <tt class="py-name">sys</tt> <tt class="py-keyword">as</tt> <tt class="py-name">_sys</tt> </tt>
+<a name="L502"></a><tt class="py-lineno">502</tt> <tt class="py-line"> </tt>
+<a name="L503"></a><tt class="py-lineno">503</tt> <tt class="py-line"> <tt class="py-name">argv</tt> <tt class="py-op">=</tt> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">argv</tt><tt class="py-op">[</tt><tt class="py-number">1</tt><tt class="py-op">:</tt><tt class="py-op">]</tt> </tt>
+<a name="L504"></a><tt class="py-lineno">504</tt> <tt class="py-line"> <tt class="py-name">keep_bang_comments</tt> <tt class="py-op">=</tt> <tt class="py-string">'-b'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">argv</tt> <tt class="py-keyword">or</tt> <tt class="py-string">'-bp'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">argv</tt> <tt class="py-keyword">or</tt> <tt class="py-string">'-pb'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">argv</tt> </tt>
+<a name="L505"></a><tt class="py-lineno">505</tt> <tt class="py-line"> <tt class="py-keyword">if</tt> <tt class="py-string">'-p'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">argv</tt> <tt class="py-keyword">or</tt> <tt class="py-string">'-bp'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">argv</tt> <tt class="py-keyword">or</tt> <tt class="py-string">'-pb'</tt> <tt class="py-keyword">in</tt> <tt class="py-name">argv</tt><tt class="py-op">:</tt> </tt>
+<a name="L506"></a><tt class="py-lineno">506</tt> <tt class="py-line"> <tt class="py-name">xjsmin</tt> <tt class="py-op">=</tt> <tt class="py-name">_make_jsmin</tt><tt class="py-op">(</tt><tt class="py-name">python_only</tt><tt class="py-op">=</tt><tt class="py-name">True</tt><tt class="py-op">)</tt> </tt>
+<a name="L507"></a><tt class="py-lineno">507</tt> <tt class="py-line"> <tt class="py-keyword">else</tt><tt class="py-op">:</tt> </tt>
+<a name="L508"></a><tt class="py-lineno">508</tt> <tt class="py-line"> <tt class="py-name">xjsmin</tt> <tt class="py-op">=</tt> <tt id="link-7" class="py-name"><a title="rjsmin.jsmin" class="py-name" href="#" onclick="return doclink('link-7', 'jsmin', 'link-4');">jsmin</a></tt> </tt>
+<a name="L509"></a><tt class="py-lineno">509</tt> <tt class="py-line"> </tt>
+<a name="L510"></a><tt class="py-lineno">510</tt> <tt class="py-line"> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">stdout</tt><tt class="py-op">.</tt><tt class="py-name">write</tt><tt class="py-op">(</tt><tt class="py-name">xjsmin</tt><tt class="py-op">(</tt> </tt>
+<a name="L511"></a><tt class="py-lineno">511</tt> <tt class="py-line"> <tt class="py-name">_sys</tt><tt class="py-op">.</tt><tt class="py-name">stdin</tt><tt class="py-op">.</tt><tt class="py-name">read</tt><tt class="py-op">(</tt><tt class="py-op">)</tt><tt class="py-op">,</tt> <tt class="py-name">keep_bang_comments</tt><tt class="py-op">=</tt><tt class="py-name">keep_bang_comments</tt> </tt>
+<a name="L512"></a><tt class="py-lineno">512</tt> <tt class="py-line"> <tt class="py-op">)</tt><tt class="py-op">)</tt> </tt>
+</div><a name="L513"></a><tt class="py-lineno">513</tt> <tt class="py-line"> </tt>
+<a name="L514"></a><tt class="py-lineno">514</tt> <tt class="py-line"> <tt class="py-name">main</tt><tt class="py-op">(</tt><tt class="py-op">)</tt> </tt>
+<a name="L515"></a><tt class="py-lineno">515</tt> <tt class="py-line"> </tt><script type="text/javascript">
+<!--
+expandto(location.href);
+// -->
+</script>
+</pre>
+<br />
+<!-- ==================== NAVIGATION BAR ==================== -->
+<table class="navbar" border="0" width="100%" cellpadding="0"
+ bgcolor="#a0c0ff" cellspacing="0">
+ <tr valign="middle">
+ <!-- Home link -->
+ <th bgcolor="#70b0f0" class="navbar-select"
+ >&nbsp;&nbsp;&nbsp;Home&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Tree link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="module-tree.html">Trees</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Index link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="identifier-index.html">Indices</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Help link -->
+ <th>&nbsp;&nbsp;&nbsp;<a
+ href="help.html">Help</a>&nbsp;&nbsp;&nbsp;</th>
+
+ <!-- Project homepage -->
+ <th class="navbar" align="right" width="100%">
+ <table border="0" cellpadding="0" cellspacing="0">
+ <tr><th class="navbar" align="center"
+ ><a href="http://opensource.perlig.de/rjsmin/" target="_top">Visit rjsmin Online</a></th>
+ </tr></table></th>
+ </tr>
+</table>
+
+<script type="text/javascript">
+ <!--
+ // Private objects are initially displayed (because if
+ // javascript is turned off then we want them to be
+ // visible); but by default, we want to hide them. So hide
+ // them unless we have a cookie that says to show them.
+ checkCookie();
+ // -->
+</script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/package.cfg b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/package.cfg
new file mode 100644
index 00000000000..6093e821980
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/package.cfg
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2009 - 2015
+# André Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[package]
+name = rjsmin
+
+python.min = 2.4
+pypy.min = 1.9
+pypy3.min = 2.4
+jython.min = 2.5
+
+version.number = 1.0.12
+
+author.name = André Malo
+author.email = nd@perlig.de
+#maintainer.name =
+#maintainer.email =
+url.homepage = http://opensource.perlig.de/rjsmin/
+url.download = http://storage.perlig.de/rjsmin/
+
+
+[docs]
+meta.classifiers = docs/CLASSIFIERS
+meta.description = docs/DESCRIPTION
+meta.summary = docs/SUMMARY
+meta.provides = docs/PROVIDES
+meta.license = LICENSE
+meta.keywords =
+ Javascript
+ Minimization
+
+apidoc.dir = docs/apidoc
+apidoc.strip = 1
+#apidoc.ignore =
+
+#userdoc.dir = docs/userdoc
+#userdoc.strip = 1
+#userdoc.ignore =
+# .buildinfo
+
+#examples.dir = docs/examples
+#examples.strip = 1
+#examples.ignore =
+
+#man =
+
+extra =
+ README.rst
+ docs/CHANGES
+ docs/BENCHMARKS
+
+
+[manifest]
+#packages.lib = .
+#packages.collect =
+modules = rjsmin
+
+#scripts =
+
+dist =
+ bench
+ bench.sh
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/rjsmin.c b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/rjsmin.c
new file mode 100644
index 00000000000..aa77a88ee4b
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/rjsmin.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2011 - 2015
+ * Andr\xe9 Malo or his licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cext.h"
+EXT_INIT_FUNC;
+
+#define RJSMIN_DULL_BIT (1 << 0)
+#define RJSMIN_PRE_REGEX_BIT (1 << 1)
+#define RJSMIN_REGEX_DULL_BIT (1 << 2)
+#define RJSMIN_REGEX_CC_DULL_BIT (1 << 3)
+#define RJSMIN_ID_LIT_BIT (1 << 4)
+#define RJSMIN_ID_LIT_O_BIT (1 << 5)
+#define RJSMIN_ID_LIT_C_BIT (1 << 6)
+#define RJSMIN_STRING_DULL_BIT (1 << 7)
+#define RJSMIN_SPACE_BIT (1 << 8)
+#define RJSMIN_POST_REGEX_OFF_BIT (1 << 9)
+
+#ifdef EXT3
+typedef Py_UNICODE rchar;
+#else
+typedef unsigned char rchar;
+#endif
+#define U(c) ((rchar)(c))
+
+#define RJSMIN_IS_DULL(c) ((U(c) > 127) || \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_DULL_BIT))
+
+#define RJSMIN_IS_REGEX_DULL(c) ((U(c) > 127) || \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_REGEX_DULL_BIT))
+
+#define RJSMIN_IS_REGEX_CC_DULL(c) ((U(c) > 127) || \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_REGEX_CC_DULL_BIT))
+
+#define RJSMIN_IS_STRING_DULL(c) ((U(c) > 127) || \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_STRING_DULL_BIT))
+
+#define RJSMIN_IS_ID_LITERAL(c) ((U(c) > 127) || \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_ID_LIT_BIT))
+
+#define RJSMIN_IS_ID_LITERAL_OPEN(c) ((U(c) > 127) || \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_ID_LIT_O_BIT))
+
+#define RJSMIN_IS_ID_LITERAL_CLOSE(c) ((U(c) > 127) || \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_ID_LIT_C_BIT))
+
+#define RJSMIN_IS_POST_REGEX_OFF(c) ((U(c) > 127) || \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_POST_REGEX_OFF_BIT))
+
+#define RJSMIN_IS_SPACE(c) ((U(c) <= 127) && \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_SPACE_BIT))
+
+#define RJSMIN_IS_PRE_REGEX_1(c) ((U(c) <= 127) && \
+ (rjsmin_charmask[U(c) & 0x7F] & RJSMIN_PRE_REGEX_BIT))
+
+
+static const unsigned short rjsmin_charmask[128] = {
+ 396, 396, 396, 396, 396, 396, 396, 396,
+ 396, 396, 2, 396, 396, 2, 396, 396,
+ 396, 396, 396, 396, 396, 396, 396, 396,
+ 396, 396, 396, 396, 396, 396, 396, 396,
+ 396, 687, 588, 653, 765, 653, 143, 588,
+ 687, 205, 653, 237, 143, 237, 141, 648,
+ 765, 765, 765, 765, 765, 765, 765, 765,
+ 765, 765, 143, 143, 653, 143, 653, 143,
+ 653, 765, 765, 765, 765, 765, 765, 765,
+ 765, 765, 765, 765, 765, 765, 765, 765,
+ 765, 765, 765, 765, 765, 765, 765, 765,
+ 765, 765, 765, 683, 513, 197, 653, 765,
+ 653, 765, 765, 765, 765, 765, 765, 765,
+ 765, 765, 765, 765, 765, 765, 765, 765,
+ 765, 765, 765, 765, 765, 765, 765, 765,
+ 765, 765, 765, 687, 143, 207, 653, 765
+};
+
+static Py_ssize_t
+rjsmin(const rchar *source, rchar *target, Py_ssize_t length,
+ int keep_bang_comments)
+{
+ const rchar *reset, *pcreset = NULL, *pctoken = NULL, *xtarget,
+ *sentinel = source + length;
+ rchar *tstart = target;
+ int post_regex = 0;
+ rchar c, quote, spaced = U(' ');
+
+ while (source < sentinel) {
+ c = *source++;
+ if (RJSMIN_IS_DULL(c)) {
+ if (post_regex) post_regex = 0;
+ if (pctoken) pctoken = NULL;
+ if (spaced == U('\n')) spaced = U(' ');
+
+ *target++ = c;
+ continue;
+ }
+ switch (c) {
+
+ /* String */
+ case U('\''): case U('"'):
+ if (post_regex) post_regex = 0;
+ if (pctoken) pctoken = NULL;
+ if (spaced == U('\n')) spaced = U(' ');
+
+ reset = source;
+ *target++ = quote = c;
+ while (source < sentinel) {
+ c = *source++;
+ *target++ = c;
+ if (RJSMIN_IS_STRING_DULL(c))
+ continue;
+ switch (c) {
+ case U('\''): case U('"'):
+ if (c == quote)
+ goto cont;
+ continue;
+ case U('\\'):
+ if (source < sentinel) {
+ c = *source++;
+ *target++ = c;
+ if (c == U('\r') && source < sentinel
+ && *source == U('\n'))
+ *target++ = *source++;
+ }
+ continue;
+ }
+ break;
+ }
+ target -= source - reset;
+ source = reset;
+ continue;
+
+ /* Comment or Regex or something else entirely */
+ case U('/'):
+ if (!(source < sentinel)) {
+ if (post_regex) post_regex = 0;
+ if (pctoken) pctoken = NULL;
+ if (spaced == U('\n')) spaced = U(' ');
+
+ *target++ = c;
+ }
+ else {
+ switch (*source) {
+ /* Comment */
+ case U('*'): case U('/'):
+ goto skip_or_copy_ws;
+
+ default:
+ xtarget = NULL;
+ if ( target == tstart
+ || RJSMIN_IS_PRE_REGEX_1(*((pctoken ? pctoken : target)
+ - 1))
+ || (
+ (xtarget = pctoken ? pctoken : target)
+ && (xtarget - tstart >= 6)
+ && *(xtarget - 1) == U('n')
+ && *(xtarget - 2) == U('r')
+ && *(xtarget - 3) == U('u')
+ && *(xtarget - 4) == U('t')
+ && *(xtarget - 5) == U('e')
+ && *(xtarget - 6) == U('r')
+ && (
+ xtarget - tstart == 6
+ || !RJSMIN_IS_ID_LITERAL(*(xtarget - 7))
+ )
+ )) {
+
+ /* Regex */
+ if (post_regex) post_regex = 0;
+ if (pctoken) pctoken = NULL;
+
+ reset = source;
+ if (spaced == U('\n')) {
+ spaced = U(' ');
+ if (xtarget)
+ *target++ = U('\n');
+ }
+
+ *target++ = U('/');
+ while (source < sentinel) {
+ c = *source++;
+ *target++ = c;
+ if (RJSMIN_IS_REGEX_DULL(c))
+ continue;
+ switch (c) {
+ case U('/'):
+ post_regex = 1;
+ goto cont;
+ case U('\\'):
+ if (source < sentinel) {
+ c = *source++;
+ *target++ = c;
+ if (c == U('\r') || c == U('\n'))
+ break;
+ }
+ continue;
+ case U('['):
+ while (source < sentinel) {
+ c = *source++;
+ *target++ = c;
+ if (RJSMIN_IS_REGEX_CC_DULL(c))
+ continue;
+ switch (c) {
+ case U('\\'):
+ if (source < sentinel) {
+ c = *source++;
+ *target++ = c;
+ if (c == U('\r') || c == U('\n'))
+ break;
+ }
+ continue;
+ case U(']'):
+ goto cont_regex;
+ }
+ }
+ break;
+ }
+ break;
+ cont_regex:
+ continue;
+ }
+ target -= source - reset;
+ source = reset;
+ }
+ else {
+ /* Just a slash */
+ if (post_regex) post_regex = 0;
+ if (pctoken) pctoken = NULL;
+ if (spaced == U('\n')) spaced = U(' ');
+
+ *target++ = c;
+ }
+ continue;
+ }
+ }
+ continue;
+
+ /* Whitespace */
+ default:
+ skip_or_copy_ws:
+ quote = U(' ');
+ --source;
+ while (source < sentinel) {
+ c = *source++;
+ if (RJSMIN_IS_SPACE(c))
+ continue;
+ switch (c) {
+ case U('\r'): case U('\n'):
+ quote = U('\n');
+ continue;
+ case U('/'):
+ if (source < sentinel) {
+ switch (*source) {
+ case U('*'):
+ reset = source++;
+ /* copy bang comment, if requested */
+ if ( keep_bang_comments && source < sentinel
+ && *source == U('!')) {
+ if (!pctoken) {
+ pctoken = target;
+ pcreset = reset;
+ }
+
+ *target++ = U('/');
+ *target++ = U('*');
+ *target++ = *source++;
+ while (source < sentinel) {
+ c = *source++;
+ *target++ = c;
+ if (c == U('*') && source < sentinel
+ && *source == U('/')) {
+ *target++ = *source++;
+ reset = NULL;
+ break;
+ }
+ }
+ if (!reset)
+ continue;
+
+ target -= source - reset;
+ source = reset;
+ if (pcreset == reset) {
+ pctoken = NULL;
+ pcreset = NULL;
+ }
+
+ }
+ /* strip regular comment */
+ else {
+ while (source < sentinel) {
+ c = *source++;
+ if (c == U('*') && source < sentinel
+ && *source == U('/')) {
+ ++source;
+ reset = NULL;
+ break;
+ }
+ }
+ if (!reset)
+ continue;
+ source = reset;
+ *target++ = U('/');
+ }
+ goto cont;
+ case U('/'):
+ ++source;
+ while (source < sentinel) {
+ c = *source++;
+ switch (c) {
+ case U('\n'):
+ break;
+ case U('\r'):
+ if (source < sentinel
+ && *source == U('\n'))
+ ++source;
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ quote = U('\n');
+ continue;
+ }
+ }
+ }
+ --source;
+ break;
+ }
+
+ if ((tstart < (pctoken ? pctoken : target) && source < sentinel)
+ && ((quote == U('\n')
+ && ((RJSMIN_IS_ID_LITERAL_CLOSE(*((pctoken ?
+ pctoken : target) - 1))
+ && RJSMIN_IS_ID_LITERAL_OPEN(*source))
+ || (post_regex
+ && RJSMIN_IS_POST_REGEX_OFF(*source)
+ && !(post_regex = 0))))
+ ||
+ (quote == U(' ') && !pctoken
+ && ((RJSMIN_IS_ID_LITERAL(*(target - 1))
+ && RJSMIN_IS_ID_LITERAL(*source))
+ || (source < sentinel
+ && ((*(target - 1) == U('+')
+ && *source == U('+'))
+ || (*(target - 1) == U('-')
+ && *source == U('-')))))))) {
+ *target++ = quote;
+ }
+
+ pcreset = NULL;
+ spaced = quote;
+ }
+ cont:
+ continue;
+ }
+ return (Py_ssize_t)(target - tstart);
+}
+
+
+PyDoc_STRVAR(rjsmin_jsmin__doc__,
+"jsmin(script, keep_bang_comments=False)\n\
+\n\
+Minify javascript based on `jsmin.c by Douglas Crockford`_\\.\n\
+\n\
+Instead of parsing the stream char by char, it uses a regular\n\
+expression approach which minifies the whole script with one big\n\
+substitution regex.\n\
+\n\
+.. _jsmin.c by Douglas Crockford:\n\
+ http://www.crockford.com/javascript/jsmin.c\n\
+\n\
+:Note: This is a hand crafted C implementation built on the regex\n\
+ semantics.\n\
+\n\
+:Parameters:\n\
+ `script` : ``str``\n\
+ Script to minify\n\
+\n\
+ `keep_bang_comments` : ``bool``\n\
+ Keep comments starting with an exclamation mark? (``/*!...*/``)\n\
+\n\
+:Return: Minified script\n\
+:Rtype: ``str``");
+
+static PyObject *
+rjsmin_jsmin(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *script, *keep_bang_comments_ = NULL, *result;
+ static char *kwlist[] = {"script", "keep_bang_comments", NULL};
+ Py_ssize_t slength, length;
+ int keep_bang_comments;
+#ifdef EXT2
+ int uni;
+#define UOBJ "O"
+#endif
+#ifdef EXT3
+#define UOBJ "U"
+#endif
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, UOBJ "|O", kwlist,
+ &script, &keep_bang_comments_))
+ return NULL;
+
+ if (!keep_bang_comments_)
+ keep_bang_comments = 0;
+ else {
+ keep_bang_comments = PyObject_IsTrue(keep_bang_comments_);
+ if (keep_bang_comments == -1)
+ return NULL;
+ }
+
+#ifdef EXT2
+ if (PyUnicode_Check(script)) {
+ if (!(script = PyUnicode_AsUTF8String(script)))
+ return NULL;
+ uni = 1;
+ }
+ else {
+ if (!(script = PyObject_Str(script)))
+ return NULL;
+ uni = 0;
+ }
+#endif
+
+#ifdef EXT3
+ Py_INCREF(script);
+#define PyString_GET_SIZE PyUnicode_GET_SIZE
+#define PyString_AS_STRING PyUnicode_AS_UNICODE
+#define _PyString_Resize PyUnicode_Resize
+#define PyString_FromStringAndSize PyUnicode_FromUnicode
+#endif
+
+ slength = PyString_GET_SIZE(script);
+ if (!(result = PyString_FromStringAndSize(NULL, slength))) {
+ Py_DECREF(script);
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ length = rjsmin((rchar *)PyString_AS_STRING(script),
+ (rchar *)PyString_AS_STRING(result),
+ slength, keep_bang_comments);
+ Py_END_ALLOW_THREADS
+
+ Py_DECREF(script);
+ if (length < 0) {
+ Py_DECREF(result);
+ return NULL;
+ }
+ if (length != slength && _PyString_Resize(&result, length) == -1)
+ return NULL;
+
+#ifdef EXT2
+ if (uni) {
+ script = PyUnicode_DecodeUTF8(PyString_AS_STRING(result),
+ PyString_GET_SIZE(result), "strict");
+ Py_DECREF(result);
+ if (!script)
+ return NULL;
+ result = script;
+ }
+#endif
+ return result;
+}
+
+/* ------------------------ BEGIN MODULE DEFINITION ------------------------ */
+
+EXT_METHODS = {
+ {"jsmin",
+ (PyCFunction)rjsmin_jsmin, METH_VARARGS | METH_KEYWORDS,
+ rjsmin_jsmin__doc__},
+
+ {NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(EXT_DOCS_VAR,
+"C implementation of rjsmin\n\
+==========================\n\
+\n\
+C implementation of rjsmin.");
+
+
+EXT_DEFINE(EXT_MODULE_NAME, EXT_METHODS_VAR, EXT_DOCS_VAR);
+
+EXT_INIT_FUNC {
+ PyObject *m;
+
+ /* Create the module and populate stuff */
+ if (!(m = EXT_CREATE(&EXT_DEFINE_VAR)))
+ EXT_INIT_ERROR(NULL);
+
+ EXT_ADD_UNICODE(m, "__author__", "Andr\xe9 Malo", "latin-1");
+ EXT_ADD_STRING(m, "__docformat__", "restructuredtext en");
+
+ EXT_INIT_RETURN(m);
+}
+
+/* ------------------------- END MODULE DEFINITION ------------------------- */
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/rjsmin.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/rjsmin.py
new file mode 100755
index 00000000000..54e20ec1c74
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/rjsmin.py
@@ -0,0 +1,515 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+r"""
+=====================
+ Javascript Minifier
+=====================
+
+rJSmin is a javascript minifier written in python.
+
+The minifier is based on the semantics of `jsmin.c by Douglas Crockford`_\\.
+
+:Copyright:
+
+ Copyright 2011 - 2015
+ Andr\xe9 Malo or his licensors, as applicable
+
+:License:
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+The module is a re-implementation aiming for speed, so it can be used at
+runtime (rather than during a preprocessing step). Usually it produces the
+same results as the original ``jsmin.c``. It differs in the following ways:
+
+- there is no error detection: unterminated string, regex and comment
+ literals are treated as regular javascript code and minified as such.
+- Control characters inside string and regex literals are left untouched; they
+ are not converted to spaces (nor to \\n)
+- Newline characters are not allowed inside string and regex literals, except
+ for line continuations in string literals (ECMA-5).
+- "return /regex/" is recognized correctly.
+- Line terminators after regex literals are handled more sensibly
+- "+ +" and "- -" sequences are not collapsed to '++' or '--'
+- Newlines before ! operators are removed more sensibly
+- Comments starting with an exclamation mark (``!``) can be kept optionally
+- rJSmin does not handle streams, but only complete strings. (However, the
+ module provides a "streamy" interface).
+
+Since most parts of the logic are handled by the regex engine it's way faster
+than the original python port of ``jsmin.c`` by Baruch Even. The speed factor
+varies between about 6 and 55 depending on input and python version (it gets
+faster the more compressed the input already is). Compared to the
+speed-refactored python port by Dave St.Germain the performance gain is less
+dramatic but still between 3 and 50 (for huge inputs). See the docs/BENCHMARKS
+file for details.
+
+rjsmin.c is a reimplementation of rjsmin.py in C and speeds it up even more.
+
+Both python 2 and python 3 are supported.
+
+.. _jsmin.c by Douglas Crockford:
+ http://www.crockford.com/javascript/jsmin.c
+"""
+if __doc__:
+ # pylint: disable = redefined-builtin
+ __doc__ = __doc__.encode('ascii').decode('unicode_escape')
+__author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape')
+__docformat__ = "restructuredtext en"
+__license__ = "Apache License, Version 2.0"
+__version__ = '1.0.12'
+__all__ = ['jsmin']
+
+import re as _re
+
+
+def _make_jsmin(python_only=False):
+ """
+ Generate JS minifier based on `jsmin.c by Douglas Crockford`_
+
+ .. _jsmin.c by Douglas Crockford:
+ http://www.crockford.com/javascript/jsmin.c
+
+ :Parameters:
+ `python_only` : ``bool``
+ Use only the python variant. If true, the c extension is not even
+ tried to be loaded.
+
+ :Return: Minifier
+ :Rtype: ``callable``
+ """
+ # pylint: disable = unused-variable
+ # pylint: disable = too-many-locals
+
+ if not python_only:
+ try:
+ import _rjsmin
+ except ImportError:
+ pass
+ else:
+ return _rjsmin.jsmin
+ try:
+ xrange
+ except NameError:
+ xrange = range # pylint: disable = redefined-builtin
+
+ space_chars = r'[\000-\011\013\014\016-\040]'
+
+ line_comment = r'(?://[^\r\n]*)'
+ space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
+ space_comment_nobang = r'(?:/\*(?!!)[^*]*\*+(?:[^/*][^*]*\*+)*/)'
+ bang_comment = r'(?:/\*![^*]*\*+(?:[^/*][^*]*\*+)*/)'
+
+ string1 = \
+ r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)'
+ string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")'
+ string3 = r'(?:`(?:[^`\\]|\\.)*`)'
+ strings = r'(?:%s|%s|%s)' % (string1, string2, string3)
+
+ charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'
+ nospecial = r'[^/\\\[\r\n]'
+ regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % (
+ nospecial, charclass, nospecial
+ )
+ space = r'(?:%s|%s)' % (space_chars, space_comment)
+ newline = r'(?:%s?[\r\n])' % line_comment
+
+ def fix_charclass(result):
+ """ Fixup string of chars to fit into a regex char class """
+ pos = result.find('-')
+ if pos >= 0:
+ result = r'%s%s-' % (result[:pos], result[pos + 1:])
+
+ def sequentize(string):
+ """
+ Notate consecutive characters as sequence
+
+ (1-4 instead of 1234)
+ """
+ first, last, result = None, None, []
+ for char in map(ord, string):
+ if last is None:
+ first = last = char
+ elif last + 1 == char:
+ last = char
+ else:
+ result.append((first, last))
+ first = last = char
+ if last is not None:
+ result.append((first, last))
+ return ''.join(['%s%s%s' % (
+ chr(first),
+ last > first + 1 and '-' or '',
+ last != first and chr(last) or ''
+ ) for first, last in result]) # noqa
+
+ return _re.sub(
+ r'([\000-\040\047])', # \047 for better portability
+ lambda m: '\\%03o' % ord(m.group(1)), (
+ sequentize(result)
+ .replace('\\', '\\\\')
+ .replace('[', '\\[')
+ .replace(']', '\\]')
+ )
+ )
+
+ def id_literal_(what):
+ """ Make id_literal like char class """
+ match = _re.compile(what).match
+ result = ''.join([
+ chr(c) for c in xrange(127) if not match(chr(c))
+ ])
+ return '[^%s]' % fix_charclass(result)
+
+ def not_id_literal_(keep):
+ """ Make negated id_literal like char class """
+ match = _re.compile(id_literal_(keep)).match
+ result = ''.join([
+ chr(c) for c in xrange(127) if not match(chr(c))
+ ])
+ return r'[%s]' % fix_charclass(result)
+
+ not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]')
+ preregex1 = r'[(,=:\[!&|?{};\r\n]'
+ preregex2 = r'%(not_id_literal)sreturn' % locals()
+
+ id_literal = id_literal_(r'[a-zA-Z0-9_$]')
+ id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]')
+ id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]')
+ post_regex_off = id_literal_(r'[^\000-\040}\])?:|,;.&=+-]')
+
+ dull = r'[^\047"`/\000-\040]'
+
+ space_sub_simple = _re.compile((
+ # noqa pylint: disable = bad-continuation
+
+ r'(%(dull)s+)' # 0
+ r'|(%(strings)s%(dull)s*)' # 1
+ r'|(?<=%(preregex1)s)'
+ r'%(space)s*(?:%(newline)s%(space)s*)*'
+ r'(%(regex)s)' # 2
+ r'(%(space)s*(?:%(newline)s%(space)s*)+' # 3
+ r'(?=%(post_regex_off)s))?'
+ r'|(?<=%(preregex2)s)'
+ r'%(space)s*(?:(%(newline)s)%(space)s*)*' # 4
+ r'(%(regex)s)' # 5
+ r'(%(space)s*(?:%(newline)s%(space)s*)+' # 6
+ r'(?=%(post_regex_off)s))?'
+ r'|(?<=%(id_literal_close)s)'
+ r'%(space)s*(?:(%(newline)s)%(space)s*)+' # 7
+ r'(?=%(id_literal_open)s)'
+ r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)' # 8
+ r'|(?<=\+)(%(space)s)+(?=\+)' # 9
+ r'|(?<=-)(%(space)s)+(?=-)' # 10
+ r'|%(space)s+'
+ r'|(?:%(newline)s%(space)s*)+'
+ ) % locals()).sub
+
+ # print space_sub_simple.__self__.pattern
+
+ def space_subber_simple(match):
+ """ Substitution callback """
+ # pylint: disable = too-many-return-statements
+
+ groups = match.groups()
+ if groups[0]:
+ return groups[0]
+ elif groups[1]:
+ return groups[1]
+ elif groups[2]:
+ if groups[3]:
+ return groups[2] + '\n'
+ return groups[2]
+ elif groups[5]:
+ return "%s%s%s" % (
+ groups[4] and '\n' or '',
+ groups[5],
+ groups[6] and '\n' or '',
+ )
+ elif groups[7]:
+ return '\n'
+ elif groups[8] or groups[9] or groups[10]:
+ return ' '
+ else:
+ return ''
+
+ space_sub_banged = _re.compile((
+ # noqa pylint: disable = bad-continuation
+
+ r'(%(dull)s+)' # 0
+ r'|(%(strings)s%(dull)s*)' # 1
+ r'|(?<=%(preregex1)s)'
+ r'(%(space)s*(?:%(newline)s%(space)s*)*)' # 2
+ r'(%(regex)s)' # 3
+ r'(%(space)s*(?:%(newline)s%(space)s*)+' # 4
+ r'(?=%(post_regex_off)s))?'
+ r'|(?<=%(preregex2)s)'
+ r'(%(space)s*(?:(%(newline)s)%(space)s*)*)' # 5, 6
+ r'(%(regex)s)' # 7
+ r'(%(space)s*(?:%(newline)s%(space)s*)+' # 8
+ r'(?=%(post_regex_off)s))?'
+ r'|(?<=%(id_literal_close)s)'
+ r'(%(space)s*(?:%(newline)s%(space)s*)+)' # 9
+ r'(?=%(id_literal_open)s)'
+ r'|(?<=%(id_literal)s)(%(space)s+)(?=%(id_literal)s)' # 10
+ r'|(?<=\+)(%(space)s+)(?=\+)' # 11
+ r'|(?<=-)(%(space)s+)(?=-)' # 12
+ r'|(%(space)s+)' # 13
+ r'|((?:%(newline)s%(space)s*)+)' # 14
+ ) % locals()).sub
+
+ # print space_sub_banged.__self__.pattern
+
+ keep = _re.compile((
+ r'%(space_chars)s+|%(space_comment_nobang)s+|%(newline)s+'
+ r'|(%(bang_comment)s+)'
+ ) % locals()).sub
+ keeper = lambda m: m.groups()[0] or ''
+
+ # print keep.__self__.pattern
+
+ def space_subber_banged(match):
+ """ Substitution callback """
+ # pylint: disable = too-many-return-statements
+
+ groups = match.groups()
+ if groups[0]:
+ return groups[0]
+ elif groups[1]:
+ return groups[1]
+ elif groups[3]:
+ return "%s%s%s%s" % (
+ keep(keeper, groups[2]),
+ groups[3],
+ keep(keeper, groups[4] or ''),
+ groups[4] and '\n' or '',
+ )
+ elif groups[7]:
+ return "%s%s%s%s%s" % (
+ keep(keeper, groups[5]),
+ groups[6] and '\n' or '',
+ groups[7],
+ keep(keeper, groups[8] or ''),
+ groups[8] and '\n' or '',
+ )
+ elif groups[9]:
+ return keep(keeper, groups[9]) + '\n'
+ elif groups[10] or groups[11] or groups[12]:
+ return keep(keeper, groups[10] or groups[11] or groups[12]) or ' '
+ else:
+ return keep(keeper, groups[13] or groups[14])
+
+ def jsmin(script, keep_bang_comments=False):
+ r"""
+ Minify javascript based on `jsmin.c by Douglas Crockford`_\.
+
+ Instead of parsing the stream char by char, it uses a regular
+ expression approach which minifies the whole script with one big
+ substitution regex.
+
+ .. _jsmin.c by Douglas Crockford:
+ http://www.crockford.com/javascript/jsmin.c
+
+ :Parameters:
+ `script` : ``str``
+ Script to minify
+
+ `keep_bang_comments` : ``bool``
+ Keep comments starting with an exclamation mark? (``/*!...*/``)
+
+ :Return: Minified script
+ :Rtype: ``str``
+ """
+ # pylint: disable = redefined-outer-name
+
+ if keep_bang_comments:
+ return space_sub_banged(
+ space_subber_banged, '\n%s\n' % script
+ ).strip()
+ else:
+ return space_sub_simple(
+ space_subber_simple, '\n%s\n' % script
+ ).strip()
+
+ return jsmin
+
+jsmin = _make_jsmin()
+
+
+def jsmin_for_posers(script, keep_bang_comments=False):
+ r"""
+ Minify javascript based on `jsmin.c by Douglas Crockford`_\.
+
+ Instead of parsing the stream char by char, it uses a regular
+ expression approach which minifies the whole script with one big
+ substitution regex.
+
+ .. _jsmin.c by Douglas Crockford:
+ http://www.crockford.com/javascript/jsmin.c
+
+ :Warning: This function is the digest of a _make_jsmin() call. It just
+ utilizes the resulting regexes. It's here for fun and may
+ vanish any time. Use the `jsmin` function instead.
+
+ :Parameters:
+ `script` : ``str``
+ Script to minify
+
+ `keep_bang_comments` : ``bool``
+ Keep comments starting with an exclamation mark? (``/*!...*/``)
+
+ :Return: Minified script
+ :Rtype: ``str``
+ """
+ if not keep_bang_comments:
+ rex = (
+ r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]'
+ r'|\r?\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]'
+ r'|\r?\n|\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?'
+ r'{};\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*'
+ r'][^*]*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\0'
+ r'14\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*((?:/(?![\r'
+ r'\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^\r'
+ r'\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))((?:[\000-\011\013\014'
+ r'\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:(?:(?://[^\r'
+ r'\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:'
+ r'[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;=?\]|}-]))?|(?<=[\00'
+ r'0-#%-,./:-@\[-^`{-~-]return)(?:[\000-\011\013\014\016-\040]|(?'
+ r':/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?[\r\n]'
+ r'))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*'
+ r'\*+)*/))*)*((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\['
+ r'[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))(('
+ r'?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)'
+ r'*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\04'
+ r'0]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;'
+ r'=?\]|}-]))?|(?<=[^\000-!#%&(*,./:-@\[\\^`{|~])(?:[\000-\011\01'
+ r'3\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?:'
+ r'//[^\r\n]*)?[\r\n]))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]'
+ r'*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040"#%-\047)*,./:-@\\-^'
+ r'`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\013\014\0'
+ r'16-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=[^\000-#%-,./'
+ r':-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|(?:/\*['
+ r'^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=\+)|(?<=-)((?:[\000-\011\013'
+ r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)))+(?=-)|(?:['
+ r'\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
+ r')+|(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]'
+ r'|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+'
+ )
+
+ def subber(match):
+ """ Substitution callback """
+ groups = match.groups()
+ return (
+ groups[0] or
+ groups[1] or
+ (groups[3] and (groups[2] + '\n')) or
+ groups[2] or
+ (groups[5] and "%s%s%s" % (
+ groups[4] and '\n' or '',
+ groups[5],
+ groups[6] and '\n' or '',
+ )) or
+ (groups[7] and '\n') or
+ (groups[8] and ' ') or
+ (groups[9] and ' ') or
+ (groups[10] and ' ') or
+ ''
+ )
+ else:
+ rex = (
+ r'([^\047"/\000-\040]+)|((?:(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]'
+ r'|\r?\n|\r)[^\047\\\r\n]*)*\047)|(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]'
+ r'|\r?\n|\r)[^"\\\r\n]*)*"))[^\047"/\000-\040]*)|(?<=[(,=:\[!&|?'
+ r'{};\r\n])((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/'
+ r'*][^*]*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013'
+ r'\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)*)((?:/(?!'
+ r'[\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|(?:\[[^\\\]\r\n]*(?:\\[^'
+ r'\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*/))((?:[\000-\011\013\01'
+ r'4\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:(?:(?://[^'
+ r'\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+('
+ r'?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)+,.:;=?\]|}-]))?|(?<=['
+ r'\000-#%-,./:-@\[-^`{-~-]return)((?:[\000-\011\013\014\016-\040'
+ r']|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:((?:(?://[^\r\n]*)?['
+ r'\r\n]))(?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*]['
+ r'^*]*\*+)*/))*)*)((?:/(?![\r\n/*])[^/\\\[\r\n]*(?:(?:\\[^\r\n]|'
+ r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\]))[^/\\\[\r\n]*)*'
+ r'/))((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]'
+ r'*\*+)*/))*(?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\01'
+ r'6-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+(?=[^\000-\040&)'
+ r'+,.:;=?\]|}-]))?|(?<=[^\000-!#%&(*,./:-@\[\\^`{|~])((?:[\000-'
+ r'\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*(?:'
+ r'(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014\016-\040]|(?:/'
+ r'\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+)(?=[^\000-\040"#%-\047)*,./'
+ r':-@\\-^`|-~])|(?<=[^\000-#%-,./:-@\[-^`{-~-])((?:[\000-\011\01'
+ r'3\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=[^\000'
+ r'-#%-,./:-@\[-^`{-~-])|(?<=\+)((?:[\000-\011\013\014\016-\040]|'
+ r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=\+)|(?<=-)((?:[\000-\0'
+ r'11\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))+)(?=-'
+ r')|((?:[\000-\011\013\014\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*'
+ r'\*+)*/))+)|((?:(?:(?://[^\r\n]*)?[\r\n])(?:[\000-\011\013\014'
+ r'\016-\040]|(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/))*)+)'
+ )
+
+ keep = _re.compile((
+ r'[\000-\011\013\014\016-\040]+|(?:/\*(?!!)[^*]*\*+(?:[^/*][^*]*'
+ r'\*+)*/)+|(?:(?://[^\r\n]*)?[\r\n])+|((?:/\*![^*]*\*+(?:[^/*][^'
+ r'*]*\*+)*/)+)'
+ ) % locals()).sub
+ keeper = lambda m: m.groups()[0] or ''
+
+ def subber(match):
+ """ Substitution callback """
+ groups = match.groups()
+ return (
+ groups[0] or
+ groups[1] or
+ (groups[3] and "%s%s%s%s" % (
+ keep(keeper, groups[2]),
+ groups[3],
+ keep(keeper, groups[4] or ''),
+ groups[4] and '\n' or '',
+ )) or
+ (groups[7] and "%s%s%s%s%s" % (
+ keep(keeper, groups[5]),
+ groups[6] and '\n' or '',
+ groups[7],
+ keep(keeper, groups[8] or ''),
+ groups[8] and '\n' or '',
+ )) or
+ (groups[9] and keep(keeper, groups[9] + '\n')) or
+ (groups[10] and keep(keeper, groups[10]) or ' ') or
+ (groups[11] and keep(keeper, groups[11]) or ' ') or
+ (groups[12] and keep(keeper, groups[12]) or ' ') or
+ keep(keeper, groups[13] or groups[14])
+ )
+
+ return _re.sub(rex, subber, '\n%s\n' % script).strip()
+
+
+if __name__ == '__main__':
+ def main():
+ """ Main """
+ import sys as _sys
+
+ argv = _sys.argv[1:]
+ keep_bang_comments = '-b' in argv or '-bp' in argv or '-pb' in argv
+ if '-p' in argv or '-bp' in argv or '-pb' in argv:
+ xjsmin = _make_jsmin(python_only=True)
+ else:
+ xjsmin = jsmin
+
+ _sys.stdout.write(xjsmin(
+ _sys.stdin.read(), keep_bang_comments=keep_bang_comments
+ ))
+
+ main()
diff --git a/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/setup.py b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/setup.py
new file mode 100644
index 00000000000..d281913400a
--- /dev/null
+++ b/chromium/third_party/catapult/common/py_vulcanize/third_party/rjsmin/setup.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: ascii -*-
+#
+# Copyright 2006 - 2013
+# Andr\xe9 Malo or his licensors, as applicable
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys as _sys
+from _setup import run
+
+
+def setup(args=None, _manifest=0):
+ """ Main setup function """
+ from _setup.ext import Extension
+
+ if 'java' in _sys.platform.lower():
+ # no c extension for jython
+ ext = None
+ else:
+ ext=[Extension('_rjsmin', sources=['rjsmin.c'])]
+
+ return run(script_args=args, ext=ext, manifest_only=_manifest)
+
+
+def manifest():
+ """ Create List of packaged files """
+ return setup((), _manifest=1)
+
+
+if __name__ == '__main__':
+ setup()
diff --git a/chromium/third_party/catapult/third_party/polymer/components/polymer/.bower.json b/chromium/third_party/catapult/third_party/polymer/components/polymer/.bower.json
new file mode 100644
index 00000000000..df435e6ad08
--- /dev/null
+++ b/chromium/third_party/catapult/third_party/polymer/components/polymer/.bower.json
@@ -0,0 +1,45 @@
+{
+ "name": "polymer",
+ "version": "1.11.3",
+ "main": [
+ "polymer.html",
+ "polymer-mini.html",
+ "polymer-micro.html"
+ ],
+ "license": "http://polymer.github.io/LICENSE.txt",
+ "ignore": [
+ "/.*",
+ "/test/",
+ "/util/",
+ "/explainer/",
+ "gulpfile.js",
+ "PRIMER.md",
+ "CONTRIBUTING.md",
+ "CHANGELOG.md"
+ ],
+ "authors": [
+ "The Polymer Authors (http://polymer.github.io/AUTHORS.txt)"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/Polymer/polymer.git"
+ },
+ "dependencies": {
+ "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.24"
+ },
+ "devDependencies": {
+ "web-component-tester": "*",
+ "iron-component-page": "polymerElements/iron-component-page#^1.1.6"
+ },
+ "private": true,
+ "homepage": "https://github.com/polymer/polymer",
+ "_release": "1.11.3",
+ "_resolution": {
+ "type": "version",
+ "tag": "v1.11.3",
+ "commit": "937021964c80c55ed3a2218d830b2520f8195d43"
+ },
+ "_source": "https://github.com/polymer/polymer.git",
+ "_target": "^1.0.0",
+ "_originalSource": "polymer/polymer"
+} \ No newline at end of file
diff --git a/chromium/third_party/catapult/third_party/polymer/components/polymer/LICENSE.txt b/chromium/third_party/catapult/third_party/polymer/components/polymer/LICENSE.txt
new file mode 100644
index 00000000000..95987bac868
--- /dev/null
+++ b/chromium/third_party/catapult/third_party/polymer/components/polymer/LICENSE.txt
@@ -0,0 +1,27 @@
+// Copyright (c) 2014 The Polymer Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chromium/third_party/catapult/third_party/polymer/components/polymer/bower.json b/chromium/third_party/catapult/third_party/polymer/components/polymer/bower.json
new file mode 100644
index 00000000000..a27884059e0
--- /dev/null
+++ b/chromium/third_party/catapult/third_party/polymer/components/polymer/bower.json
@@ -0,0 +1,35 @@
+{
+ "name": "polymer",
+ "version": "1.11.3",
+ "main": [
+ "polymer.html",
+ "polymer-mini.html",
+ "polymer-micro.html"
+ ],
+ "license": "http://polymer.github.io/LICENSE.txt",
+ "ignore": [
+ "/.*",
+ "/test/",
+ "/util/",
+ "/explainer/",
+ "gulpfile.js",
+ "PRIMER.md",
+ "CONTRIBUTING.md",
+ "CHANGELOG.md"
+ ],
+ "authors": [
+ "The Polymer Authors (http://polymer.github.io/AUTHORS.txt)"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/Polymer/polymer.git"
+ },
+ "dependencies": {
+ "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.24"
+ },
+ "devDependencies": {
+ "web-component-tester": "*",
+ "iron-component-page": "polymerElements/iron-component-page#^1.1.6"
+ },
+ "private": true
+}
diff --git a/chromium/third_party/catapult/third_party/polymer/components/polymer/build.log b/chromium/third_party/catapult/third_party/polymer/components/polymer/build.log
new file mode 100644
index 00000000000..eef1ebad531
--- /dev/null
+++ b/chromium/third_party/catapult/third_party/polymer/components/polymer/build.log
@@ -0,0 +1,576 @@
+BUILD LOG
+---------
+Build Time: 2018-02-12T15:48:46-0800
+
+NODEJS INFORMATION
+==================
+nodejs: v8.9.4
+dom-serializer: 0.1.0
+estraverse: 4.2.0
+expand-tilde: 1.2.2
+is-windows: 0.2.0
+jade: 0.26.3
+mocha: 2.5.3
+path-is-inside: 1.0.2
+@types/clone: 0.1.30
+@types/chalk: 0.4.31
+@types/express: 4.0.37
+@types/express-serve-static-core: 4.0.53
+@types/freeport: 1.0.21
+@types/mime: 2.0.0
+@types/launchpad: 0.6.0
+@types/parse5: 0.0.31
+@types/which: 1.0.28
+@types/node: 4.2.20
+@types/serve-static: 1.7.32
+accessibility-developer-tools: 2.12.0
+accepts: 1.3.4
+abbrev: 1.1.1
+after: 0.8.2
+acorn-jsx: 3.0.1
+ansi-red: 0.1.1
+ansi-cyan: 0.1.1
+ansi-escapes: 1.4.0
+ajv-keywords: 1.5.1
+adm-zip: 0.4.7
+ajv: 4.11.8
+agent-base: 2.1.1
+ansi-regex: 2.1.1
+ansi-wrap: 0.1.0
+ansi-styles: 2.2.1
+align-text: 0.1.4
+append-field: 0.1.0
+archy: 1.0.0
+arr-diff: 2.0.0
+archiver: 0.14.4
+arr-flatten: 1.1.0
+arr-union: 2.1.0
+argparse: 1.0.9
+array-differ: 1.0.0
+array-slice: 1.0.0
+array-flatten: 1.1.1
+array-each: 1.0.1
+array-uniq: 1.0.3
+array-union: 1.0.2
+arrify: 1.0.1
+asap: 2.0.6
+array-unique: 0.2.1
+assert-plus: 0.2.0
+arraybuffer.slice: 0.0.6
+asn1: 0.2.3
+assertion-error: 1.0.2
+async: 0.9.2
+asynckit: 0.4.0
+aws-sign2: 0.6.0
+babel-polyfill: 6.26.0
+balanced-match: 1.0.0
+babel-runtime: 6.26.0
+babel-code-frame: 6.26.0
+aws4: 1.6.0
+backo2: 1.0.2
+beeper: 1.1.1
+base64-arraybuffer: 0.1.5
+base64-js: 1.2.0
+base64id: 1.0.0
+binaryextensions: 1.0.1
+bcrypt-pbkdf: 1.0.1
+better-assert: 1.0.2
+bl: 1.2.1
+blob: 0.0.4
+brace-expansion: 1.1.8
+boxen: 0.3.1
+bluebird: 2.11.0
+boom: 2.10.1
+body-parser: 1.18.2
+bufferstreams: 1.1.1
+braces: 1.8.5
+caller-path: 0.1.0
+browserstack: 1.5.0
+callsites: 0.2.0
+buffer-crc32: 0.2.13
+callsite: 1.0.0
+capture-stack-trace: 1.0.0
+bytes: 3.0.0
+camelcase: 1.2.1
+busboy: 0.2.14
+chalk: 1.1.3
+center-align: 0.1.3
+chai: 3.5.0
+caseless: 0.11.0
+circular-json: 0.3.3
+cli-width: 2.2.0
+clone: 1.0.2
+clone-stats: 0.0.1
+cleankill: 1.0.3
+co: 4.6.0
+cli-cursor: 1.0.2
+cliui: 2.1.0
+commander: 2.3.0
+code-point-at: 1.1.0
+component-bind: 1.0.0
+combined-stream: 1.0.5
+component-emitter: 1.1.2
+concat-map: 0.0.1
+component-inherit: 0.0.3
+compress-commons: 0.2.9
+concat-stream: 1.6.0
+configstore: 2.1.0
+content-disposition: 0.5.2
+cookie: 0.3.1
+content-type: 1.0.4
+cookie-signature: 1.0.6
+core-util-is: 1.0.2
+ctype: 0.5.3
+crc32-stream: 0.3.4
+cryptiles: 2.0.5
+create-error-class: 3.0.2
+crc: 3.2.1
+dateformat: 2.2.0
+debuglog: 1.0.1
+core-js: 2.5.1
+debug: 2.6.9
+dashdash: 1.14.1
+d: 1.0.0
+decamelize: 1.2.0
+defaults: 1.0.3
+del: 2.2.2
+deep-eql: 0.1.3
+delayed-stream: 1.0.0
+deep-extend: 0.4.2
+deep-is: 0.1.3
+dezalgo: 1.0.3
+deprecated: 0.0.1
+depd: 1.1.1
+dicer: 0.2.5
+destroy: 1.0.4
+dom5: 1.3.6
+diff: 1.4.0
+detect-file: 0.1.0
+domelementtype: 1.3.0
+doctrine: 2.0.0
+domhandler: 2.4.1
+domutils: 1.6.2
+duplexer: 0.1.1
+dot-prop: 3.0.0
+duplexer2: 0.0.2
+ee-first: 1.1.1
+end-of-stream: 0.1.5
+ecc-jsbn: 0.1.1
+encodeurl: 1.0.1
+engine.io: 1.8.4
+engine.io-client: 1.8.4
+es6-map: 0.1.5
+entities: 1.1.1
+es6-iterator: 2.0.1
+engine.io-parser: 1.3.2
+error-ex: 1.3.1
+es6-weak-map: 2.0.2
+escape-string-regexp: 1.0.5
+escape-html: 1.0.3
+es6-promise: 2.3.0
+es5-ext: 0.10.35
+es6-symbol: 3.1.1
+escope: 3.6.0
+espree: 3.5.1
+esrecurse: 4.2.0
+esquery: 1.0.0
+es6-set: 0.1.5
+esutils: 2.0.2
+event-emitter: 0.3.5
+etag: 1.8.1
+eslint-plugin-html: 1.7.0
+exit-hook: 1.1.1
+expand-range: 1.8.2
+extend-shallow: 1.1.4
+expand-brackets: 0.1.5
+express: 4.16.2
+extsprintf: 1.3.0
+extend: 3.0.1
+extglob: 0.3.2
+fast-levenshtein: 2.0.6
+file-entry-cache: 2.0.0
+fd-slicer: 1.0.1
+figures: 1.7.0
+fancy-log: 1.3.0
+filename-regex: 2.0.1
+filled-array: 1.1.0
+finalhandler: 1.1.0
+find-index: 0.1.1
+fill-range: 2.2.3
+flat-cache: 1.3.0
+fined: 1.1.0
+findup-sync: 0.4.3
+first-chunk-stream: 1.0.0
+flagged-respawn: 0.3.2
+for-in: 1.0.2
+for-own: 0.1.5
+forwarded: 0.1.2
+form-data: 2.1.4
+freeport: 1.0.5
+forever-agent: 0.6.1
+fs.realpath: 1.0.0
+generate-object-property: 1.2.0
+gaze: 0.5.2
+generate-function: 2.0.0
+formatio: 1.1.1
+github-url-from-username-repo: 1.0.2
+github-url-from-git: 1.5.0
+glob: 7.1.2
+fresh: 0.5.2
+glob-stream: 3.1.18
+glob-watcher: 0.0.6
+glob2base: 0.0.12
+fs-exists-sync: 0.1.0
+getpass: 0.1.7
+globals: 9.18.0
+global-modules: 0.2.3
+globby: 5.0.0
+glob-base: 0.3.0
+glob-parent: 2.0.0
+globule: 0.1.0
+graceful-fs: 3.0.11
+global-prefix: 0.1.5
+gulp-audit: 1.0.0
+got: 5.7.1
+gulp-eslint: 3.0.1
+glogg: 1.0.0
+gulp-rename: 1.2.2
+gulp-replace: 0.5.4
+gulp-vulcanize: 6.1.0
+growl: 1.9.2
+gulp-util: 3.0.8
+gulplog: 1.0.0
+has-ansi: 2.0.0
+has-gulplog: 0.1.0
+has-cors: 1.1.0
+has-binary: 0.1.7
+hoek: 2.16.3
+has-color: 0.1.7
+htmlparser2: 3.9.2
+homedir-polyfill: 1.0.1
+hydrolysis: 1.25.0
+ignore: 3.3.5
+hawk: 3.1.3
+https-proxy-agent: 1.0.0
+http-signature: 1.1.1
+iconv-lite: 0.4.19
+inflight: 1.0.6
+imurmurhash: 0.1.4
+http-errors: 1.6.2
+inherits: 2.0.3
+ini: 1.3.4
+indexof: 0.0.1
+ipaddr.js: 1.5.2
+is-arrayish: 0.2.1
+inquirer: 0.12.0
+interpret: 1.0.4
+is-dotfile: 1.0.3
+is-buffer: 1.1.5
+is-extendable: 0.1.1
+is-equal-shallow: 0.1.3
+is-absolute: 0.2.6
+is-extglob: 1.0.0
+is-my-json-valid: 2.16.1
+is-npm: 1.0.0
+is-fullwidth-code-point: 1.0.0
+is-number: 2.1.0
+is-finite: 1.0.2
+is-obj: 1.0.1
+is-path-cwd: 1.0.0
+is-path-in-cwd: 1.0.0
+is-path-inside: 1.0.0
+is-glob: 2.0.1
+is-plain-object: 2.0.4
+is-property: 1.0.2
+is-redirect: 1.0.0
+is-resolvable: 1.0.0
+is-posix-bracket: 0.1.1
+is-retry-allowed: 1.1.0
+is-stream: 1.1.0
+is-relative: 0.2.1
+is-primitive: 2.0.0
+is-typedarray: 1.0.0
+is-utf8: 0.2.1
+isarray: 1.0.0
+isexe: 2.0.0
+jju: 1.3.0
+is-unc-path: 0.1.2
+isobject: 2.1.0
+istextorbinary: 1.0.2
+jsbn: 0.1.1
+json-parse-helpfulerror: 1.0.3
+json-schema: 0.2.3
+json-stable-stringify: 1.0.1
+isstream: 0.1.2
+js-tokens: 3.0.2
+jsonpointer: 4.0.1
+json-stringify-safe: 5.0.1
+json3: 3.3.2
+jsonify: 0.0.0
+kind-of: 3.2.2
+lazy-cache: 1.0.4
+latest-version: 2.0.0
+lazypipe: 1.0.1
+jsprim: 1.4.1
+lodash: 1.0.2
+lodash._basecopy: 3.0.1
+levn: 0.3.0
+lazystream: 0.1.0
+launchpad: 0.6.0
+lodash._basetostring: 3.0.1
+liftoff: 2.3.0
+lodash._basevalues: 3.0.0
+lodash._getnative: 3.9.1
+lodash._reescape: 3.0.0
+lodash._isiterateecall: 3.0.9
+lodash._reevaluate: 3.0.0
+lodash._reinterpolate: 3.0.0
+lodash.isarguments: 3.1.0
+lodash.escape: 3.2.0
+lodash.isarray: 3.0.4
+lodash.keys: 3.1.2
+lodash._root: 3.0.1
+lodash.restparam: 3.6.1
+lodash.template: 3.6.2
+lodash.templatesettings: 3.1.1
+lodash.isstring: 4.0.1
+lodash.mapvalues: 4.6.0
+lodash.isplainobject: 4.0.6
+lru-cache: 2.7.3
+longest: 1.0.1
+lolex: 1.3.2
+map-cache: 0.2.2
+lowercase-keys: 1.0.0
+media-typer: 0.3.0
+methods: 1.1.2
+mime-db: 1.30.0
+micromatch: 2.3.11
+minimist: 1.2.0
+minimatch: 3.0.4
+multipipe: 0.1.2
+mime-types: 2.1.17
+merge-descriptors: 1.0.1
+ms: 2.0.0
+natives: 1.1.0
+mute-stream: 0.0.5
+natural-compare: 1.4.0
+multer: 1.3.0
+node-int64: 0.3.3
+node-status-codes: 1.0.0
+negotiator: 0.6.1
+normalize-package-data: 1.0.3
+nomnom: 1.8.1
+nodegit-promise: 4.0.0
+oauth-sign: 0.8.2
+number-is-nan: 1.0.1
+object-assign: 4.1.1
+object-component: 0.0.3
+once: 1.4.0
+object.defaults: 1.1.0
+normalize-path: 2.1.1
+onetime: 1.1.0
+orchestrator: 0.3.8
+on-finished: 2.3.0
+os-homedir: 1.0.2
+object.pick: 1.3.0
+ordered-read-streams: 0.1.0
+options: 0.0.6
+package-json: 2.4.0
+object.omit: 2.0.1
+os-tmpdir: 1.0.2
+osenv: 0.1.4
+optionator: 0.8.2
+parse5: 1.5.1
+parse-filepath: 1.0.1
+parse-glob: 3.0.4
+parseqs: 0.0.5
+path-is-absolute: 1.0.1
+parse-json: 2.2.0
+parse-passwd: 1.0.0
+parseurl: 1.3.2
+parseuri: 0.0.5
+parsejson: 0.0.3
+path-root-regex: 0.1.2
+path-posix: 1.0.0
+pify: 2.3.0
+path-parse: 1.0.5
+pinkie-promise: 2.0.1
+path-to-regexp: 0.1.7
+plugin-error: 0.1.2
+path-root: 0.1.1
+polyclean: 1.3.1
+pinkie: 2.0.4
+prelude-ls: 1.1.2
+pluralize: 1.2.1
+plist: 2.1.0
+process-nextick-args: 1.0.7
+pend: 1.2.0
+prepend-http: 1.0.4
+pretty-hrtime: 1.0.3
+promisify-node: 0.4.0
+preserve: 0.2.0
+proxy-addr: 2.0.2
+punycode: 1.4.1
+progress: 1.1.8
+randomatic: 1.1.7
+q: 1.5.0
+qs: 6.5.1
+range-parser: 1.2.0
+readable-stream: 2.3.3
+read-package-json: 1.3.3
+read-installed: 3.1.5
+read-all-stream: 3.1.0
+readdir-scoped-modules: 1.0.2
+readline2: 1.0.1
+raw-body: 2.3.2
+rechoir: 0.6.2
+regenerator-runtime: 0.10.5
+registry-auth-token: 3.3.1
+regex-cache: 0.4.4
+remove-trailing-separator: 1.1.0
+registry-url: 3.1.0
+repeat-element: 1.1.2
+replacestream: 4.0.3
+replace-ext: 0.0.1
+repeat-string: 1.6.1
+resolve-from: 1.0.1
+require-uncached: 1.0.3
+resolve-dir: 0.1.1
+repeating: 2.0.1
+run-sequence: 1.2.2
+request: 2.79.0
+restore-cursor: 1.0.1
+run-async: 0.1.0
+safe-buffer: 5.1.1
+right-align: 0.1.3
+samsam: 1.1.2
+rx-lite: 3.1.2
+sauce-connect-launcher: 1.2.2
+sequencify: 0.0.7
+serve-static: 1.13.1
+send: 0.11.1
+resolve: 1.4.0
+semver-diff: 2.1.0
+sigmund: 1.0.1
+setprototypeof: 1.0.3
+slide: 1.1.6
+server-destroy: 1.0.1
+sinon-chai: 2.14.0
+serve-waterfall: 1.1.1
+sinon: 1.17.7
+sparkles: 1.0.0
+sntp: 1.0.9
+socket.io-client: 1.7.4
+source-map: 0.5.7
+socket.io-adapter: 0.5.0
+slice-ansi: 0.0.4
+sprintf-js: 1.0.3
+socket.io: 1.7.4
+stream-combiner: 0.2.2
+statuses: 1.3.1
+stream-consume: 0.1.0
+strip-ansi: 3.0.1
+stacky: 1.3.1
+socket.io-parser: 2.3.1
+streamsearch: 0.1.2
+string-width: 1.0.2
+strip-json-comments: 2.0.1
+stringstream: 0.0.5
+string_decoder: 1.0.3
+supports-color: 2.0.0
+through: 2.3.8
+table: 3.8.3
+textextensions: 1.0.2
+test-fixture: 3.0.0-rc.1
+temp: 0.8.3
+through2: 2.0.3
+text-table: 0.2.0
+time-stamp: 1.1.0
+tildify: 1.2.0
+to-array: 0.1.4
+timed-out: 3.1.3
+tar-stream: 1.5.2
+to-iso-string: 0.0.2
+tunnel-agent: 0.4.3
+tough-cookie: 2.3.3
+tryit: 1.0.3
+type-check: 0.3.2
+type-detect: 1.0.0
+tweetnacl: 0.14.5
+type-is: 1.6.15
+typedarray: 0.0.6
+unique-stream: 1.0.0
+uglify-to-browserify: 1.0.2
+unc-path-regex: 0.1.2
+ultron: 1.0.2
+unpipe: 1.0.0
+underscore: 1.6.0
+update-notifier: 0.6.3
+underscore.string: 3.0.3
+unzip-response: 1.0.2
+util-deprecate: 1.0.2
+urijs: 1.16.1
+url-parse-lax: 1.0.0
+util: 0.10.3
+util-extend: 1.0.3
+uuid: 2.0.3
+utils-merge: 1.0.1
+v8flags: 2.1.1
+vinyl: 0.5.3
+vinyl-fs: 0.3.14
+vary: 1.1.2
+vargs: 0.1.0
+wct-local: 2.0.15
+wct-sauce: 1.8.6
+verror: 1.10.0
+wrappy: 1.0.2
+wordwrap: 1.0.0
+widest-line: 1.0.0
+write: 0.2.1
+window-size: 0.1.0
+ws: 1.1.4
+write-file-atomic: 1.3.4
+xdg-basedir: 2.0.0
+wtf-8: 1.0.0
+xtend: 4.0.1
+xmlbuilder: 8.2.2
+xmlhttprequest-ssl: 1.5.3
+xmldom: 0.1.27
+yeast: 0.1.2
+acorn: 5.1.2
+zip-stream: 0.5.2
+yargs: 3.10.0
+yauzl: 2.8.0
+escodegen: 1.9.0
+eslint: 3.19.0
+esprima: 4.0.0
+gulp: 3.9.1
+har-validator: 2.0.6
+js-yaml: 3.10.0
+mime: 1.4.1
+mkdirp: 0.5.1
+nopt: 3.0.6
+node-uuid: 1.4.8
+rc: 1.2.2
+rimraf: 2.6.2
+semver: 4.3.6
+selenium-standalone: 5.11.2
+shelljs: 0.7.8
+sshpk: 1.13.1
+strip-bom: 1.0.0
+uglify-js: 2.8.29
+user-home: 1.1.1
+vulcanize: 1.16.0
+wd: 0.3.12
+which: 1.3.0
+web-component-tester: 4.3.6
+
+REPO REVISIONS
+==============
+polymer-1.x: 62bd3503279b8e954467dc3cb4e739330b9dda10
+
+BUILD HASHES
+============
+polymer-mini.html: 41538c3e880a3db75fc80c61a8b9e5a3e831de7d
+polymer-micro.html: e64e86493573e21587fbed115ddc7187b778718e
+polymer.html: 34bc3eda3e3a732823d953a3f8eccc0910e5de61 \ No newline at end of file
diff --git a/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer-micro.html b/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer-micro.html
new file mode 100644
index 00000000000..0944f7f6f33
--- /dev/null
+++ b/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer-micro.html
@@ -0,0 +1,821 @@
+<!--
+@license
+Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+--><script>(function () {
+function resolve() {
+document.body.removeAttribute('unresolved');
+}
+if (window.WebComponents) {
+addEventListener('WebComponentsReady', resolve);
+} else {
+if (document.readyState === 'interactive' || document.readyState === 'complete') {
+resolve();
+} else {
+addEventListener('DOMContentLoaded', resolve);
+}
+}
+}());window.Polymer = {
+Settings: function () {
+var settings = window.Polymer || {};
+if (!settings.noUrlSettings) {
+var parts = location.search.slice(1).split('&');
+for (var i = 0, o; i < parts.length && (o = parts[i]); i++) {
+o = o.split('=');
+o[0] && (settings[o[0]] = o[1] || true);
+}
+}
+settings.wantShadow = settings.dom === 'shadow';
+settings.hasShadow = Boolean(Element.prototype.createShadowRoot);
+settings.nativeShadow = settings.hasShadow && !window.ShadowDOMPolyfill;
+settings.useShadow = settings.wantShadow && settings.hasShadow;
+settings.hasNativeImports = Boolean('import' in document.createElement('link'));
+settings.useNativeImports = settings.hasNativeImports;
+settings.useNativeCustomElements = !window.CustomElements || window.CustomElements.useNative;
+settings.useNativeShadow = settings.useShadow && settings.nativeShadow;
+settings.usePolyfillProto = !settings.useNativeCustomElements && !Object.__proto__;
+settings.hasNativeCSSProperties = !navigator.userAgent.match(/AppleWebKit\/601|Edge\/15/) && window.CSS && CSS.supports && CSS.supports('box-shadow', '0 0 0 var(--foo)');
+settings.useNativeCSSProperties = settings.hasNativeCSSProperties && settings.lazyRegister && settings.useNativeCSSProperties;
+settings.isIE = navigator.userAgent.match('Trident');
+settings.passiveTouchGestures = settings.passiveTouchGestures || false;
+return settings;
+}()
+};(function () {
+var userPolymer = window.Polymer;
+window.Polymer = function (prototype) {
+if (typeof prototype === 'function') {
+prototype = prototype.prototype;
+}
+if (!prototype) {
+prototype = {};
+}
+prototype = desugar(prototype);
+var customCtor = prototype === prototype.constructor.prototype ? prototype.constructor : null;
+var options = { prototype: prototype };
+if (prototype.extends) {
+options.extends = prototype.extends;
+}
+Polymer.telemetry._registrate(prototype);
+var ctor = document.registerElement(prototype.is, options);
+return customCtor || ctor;
+};
+var desugar = function (prototype) {
+var base = Polymer.Base;
+if (prototype.extends) {
+base = Polymer.Base._getExtendedPrototype(prototype.extends);
+}
+prototype = Polymer.Base.chainObject(prototype, base);
+prototype.registerCallback();
+return prototype;
+};
+if (userPolymer) {
+for (var i in userPolymer) {
+Polymer[i] = userPolymer[i];
+}
+}
+Polymer.Class = function (prototype) {
+if (!prototype.factoryImpl) {
+prototype.factoryImpl = function () {
+};
+}
+return desugar(prototype).constructor;
+};
+}());
+Polymer.telemetry = {
+registrations: [],
+_regLog: function (prototype) {
+console.log('[' + prototype.is + ']: registered');
+},
+_registrate: function (prototype) {
+this.registrations.push(prototype);
+Polymer.log && this._regLog(prototype);
+},
+dumpRegistrations: function () {
+this.registrations.forEach(this._regLog);
+}
+};Object.defineProperty(window, 'currentImport', {
+enumerable: true,
+configurable: true,
+get: function () {
+return (document._currentScript || document.currentScript || {}).ownerDocument;
+}
+});Polymer.RenderStatus = {
+_ready: false,
+_callbacks: [],
+whenReady: function (cb) {
+if (this._ready) {
+cb();
+} else {
+this._callbacks.push(cb);
+}
+},
+_makeReady: function () {
+this._ready = true;
+for (var i = 0; i < this._callbacks.length; i++) {
+this._callbacks[i]();
+}
+this._callbacks = [];
+},
+_catchFirstRender: function () {
+requestAnimationFrame(function () {
+Polymer.RenderStatus._makeReady();
+});
+},
+_afterNextRenderQueue: [],
+_waitingNextRender: false,
+afterNextRender: function (element, fn, args) {
+this._watchNextRender();
+this._afterNextRenderQueue.push([
+element,
+fn,
+args
+]);
+},
+hasRendered: function () {
+return this._ready;
+},
+_watchNextRender: function () {
+if (!this._waitingNextRender) {
+this._waitingNextRender = true;
+var fn = function () {
+Polymer.RenderStatus._flushNextRender();
+};
+if (!this._ready) {
+this.whenReady(fn);
+} else {
+requestAnimationFrame(fn);
+}
+}
+},
+_flushNextRender: function () {
+var self = this;
+setTimeout(function () {
+self._flushRenderCallbacks(self._afterNextRenderQueue);
+self._afterNextRenderQueue = [];
+self._waitingNextRender = false;
+});
+},
+_flushRenderCallbacks: function (callbacks) {
+for (var i = 0, h; i < callbacks.length; i++) {
+h = callbacks[i];
+h[1].apply(h[0], h[2] || Polymer.nar);
+}
+}
+};
+if (window.HTMLImports) {
+HTMLImports.whenReady(function () {
+Polymer.RenderStatus._catchFirstRender();
+});
+} else {
+Polymer.RenderStatus._catchFirstRender();
+}
+Polymer.ImportStatus = Polymer.RenderStatus;
+Polymer.ImportStatus.whenLoaded = Polymer.ImportStatus.whenReady;(function () {
+'use strict';
+var settings = Polymer.Settings;
+Polymer.Base = {
+__isPolymerInstance__: true,
+_addFeature: function (feature) {
+this.mixin(this, feature);
+},
+registerCallback: function () {
+if (settings.lazyRegister === 'max') {
+if (this.beforeRegister) {
+this.beforeRegister();
+}
+} else {
+this._desugarBehaviors();
+for (var i = 0, b; i < this.behaviors.length; i++) {
+b = this.behaviors[i];
+if (b.beforeRegister) {
+b.beforeRegister.call(this);
+}
+}
+if (this.beforeRegister) {
+this.beforeRegister();
+}
+}
+this._registerFeatures();
+if (!settings.lazyRegister) {
+this.ensureRegisterFinished();
+}
+},
+createdCallback: function () {
+if (settings.disableUpgradeEnabled) {
+if (this.hasAttribute('disable-upgrade')) {
+this._propertySetter = disableUpgradePropertySetter;
+this._configValue = null;
+this.__data__ = {};
+return;
+} else {
+this.__hasInitialized = true;
+}
+}
+this.__initialize();
+},
+__initialize: function () {
+if (!this.__hasRegisterFinished) {
+this._ensureRegisterFinished(this.__proto__);
+}
+Polymer.telemetry.instanceCount++;
+this.root = this;
+for (var i = 0, b; i < this.behaviors.length; i++) {
+b = this.behaviors[i];
+if (b.created) {
+b.created.call(this);
+}
+}
+if (this.created) {
+this.created();
+}
+this._initFeatures();
+},
+ensureRegisterFinished: function () {
+this._ensureRegisterFinished(this);
+},
+_ensureRegisterFinished: function (proto) {
+if (proto.__hasRegisterFinished !== proto.is || !proto.is) {
+if (settings.lazyRegister === 'max') {
+proto._desugarBehaviors();
+for (var i = 0, b; i < proto.behaviors.length; i++) {
+b = proto.behaviors[i];
+if (b.beforeRegister) {
+b.beforeRegister.call(proto);
+}
+}
+}
+proto.__hasRegisterFinished = proto.is;
+if (proto._finishRegisterFeatures) {
+proto._finishRegisterFeatures();
+}
+for (var j = 0, pb; j < proto.behaviors.length; j++) {
+pb = proto.behaviors[j];
+if (pb.registered) {
+pb.registered.call(proto);
+}
+}
+if (proto.registered) {
+proto.registered();
+}
+if (settings.usePolyfillProto && proto !== this) {
+proto.extend(this, proto);
+}
+}
+},
+attachedCallback: function () {
+var self = this;
+Polymer.RenderStatus.whenReady(function () {
+self.isAttached = true;
+for (var i = 0, b; i < self.behaviors.length; i++) {
+b = self.behaviors[i];
+if (b.attached) {
+b.attached.call(self);
+}
+}
+if (self.attached) {
+self.attached();
+}
+});
+},
+detachedCallback: function () {
+var self = this;
+Polymer.RenderStatus.whenReady(function () {
+self.isAttached = false;
+for (var i = 0, b; i < self.behaviors.length; i++) {
+b = self.behaviors[i];
+if (b.detached) {
+b.detached.call(self);
+}
+}
+if (self.detached) {
+self.detached();
+}
+});
+},
+attributeChangedCallback: function (name, oldValue, newValue) {
+this._attributeChangedImpl(name);
+for (var i = 0, b; i < this.behaviors.length; i++) {
+b = this.behaviors[i];
+if (b.attributeChanged) {
+b.attributeChanged.call(this, name, oldValue, newValue);
+}
+}
+if (this.attributeChanged) {
+this.attributeChanged(name, oldValue, newValue);
+}
+},
+_attributeChangedImpl: function (name) {
+this._setAttributeToProperty(this, name);
+},
+extend: function (target, source) {
+if (target && source) {
+var n$ = Object.getOwnPropertyNames(source);
+for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
+this.copyOwnProperty(n, source, target);
+}
+}
+return target || source;
+},
+mixin: function (target, source) {
+for (var i in source) {
+target[i] = source[i];
+}
+return target;
+},
+copyOwnProperty: function (name, source, target) {
+var pd = Object.getOwnPropertyDescriptor(source, name);
+if (pd) {
+Object.defineProperty(target, name, pd);
+}
+},
+_logger: function (level, args) {
+if (args.length === 1 && Array.isArray(args[0])) {
+args = args[0];
+}
+switch (level) {
+case 'log':
+case 'warn':
+case 'error':
+console[level].apply(console, args);
+break;
+}
+},
+_log: function () {
+var args = Array.prototype.slice.call(arguments, 0);
+this._logger('log', args);
+},
+_warn: function () {
+var args = Array.prototype.slice.call(arguments, 0);
+this._logger('warn', args);
+},
+_error: function () {
+var args = Array.prototype.slice.call(arguments, 0);
+this._logger('error', args);
+},
+_logf: function () {
+return this._logPrefix.concat(this.is).concat(Array.prototype.slice.call(arguments, 0));
+}
+};
+Polymer.Base._logPrefix = function () {
+var color = window.chrome && !/edge/i.test(navigator.userAgent) || /firefox/i.test(navigator.userAgent);
+return color ? [
+'%c[%s::%s]:',
+'font-weight: bold; background-color:#EEEE00;'
+] : ['[%s::%s]:'];
+}();
+Polymer.Base.chainObject = function (object, inherited) {
+if (object && inherited && object !== inherited) {
+if (!Object.__proto__) {
+object = Polymer.Base.extend(Object.create(inherited), object);
+}
+object.__proto__ = inherited;
+}
+return object;
+};
+Polymer.Base = Polymer.Base.chainObject(Polymer.Base, HTMLElement.prototype);
+Polymer.BaseDescriptors = {};
+var disableUpgradePropertySetter;
+if (settings.disableUpgradeEnabled) {
+disableUpgradePropertySetter = function (property, value) {
+this.__data__[property] = value;
+};
+var origAttributeChangedCallback = Polymer.Base.attributeChangedCallback;
+Polymer.Base.attributeChangedCallback = function (name, oldValue, newValue) {
+if (!this.__hasInitialized && name === 'disable-upgrade') {
+this.__hasInitialized = true;
+this._propertySetter = Polymer.Bind._modelApi._propertySetter;
+this._configValue = Polymer.Base._configValue;
+this.__initialize();
+}
+origAttributeChangedCallback.call(this, name, oldValue, newValue);
+};
+}
+if (window.CustomElements) {
+Polymer.instanceof = CustomElements.instanceof;
+} else {
+Polymer.instanceof = function (obj, ctor) {
+return obj instanceof ctor;
+};
+}
+Polymer.isInstance = function (obj) {
+return Boolean(obj && obj.__isPolymerInstance__);
+};
+Polymer.telemetry.instanceCount = 0;
+}());(function () {
+var modules = {};
+var lcModules = {};
+var findModule = function (id) {
+return modules[id] || lcModules[id.toLowerCase()];
+};
+var DomModule = function () {
+return document.createElement('dom-module');
+};
+DomModule.prototype = Object.create(HTMLElement.prototype);
+Polymer.Base.mixin(DomModule.prototype, {
+createdCallback: function () {
+this.register();
+},
+register: function (id) {
+id = id || this.id || this.getAttribute('name') || this.getAttribute('is');
+if (id) {
+this.id = id;
+modules[id] = this;
+lcModules[id.toLowerCase()] = this;
+}
+},
+import: function (id, selector) {
+if (id) {
+var m = findModule(id);
+if (!m) {
+forceDomModulesUpgrade();
+m = findModule(id);
+}
+if (m && selector) {
+m = m.querySelector(selector);
+}
+return m;
+}
+}
+});
+Object.defineProperty(DomModule.prototype, 'constructor', {
+value: DomModule,
+configurable: true,
+writable: true
+});
+var cePolyfill = window.CustomElements && !CustomElements.useNative;
+document.registerElement('dom-module', DomModule);
+function forceDomModulesUpgrade() {
+if (cePolyfill) {
+var script = document._currentScript || document.currentScript;
+var doc = script && script.ownerDocument || document;
+var modules = doc.querySelectorAll('dom-module');
+for (var i = modules.length - 1, m; i >= 0 && (m = modules[i]); i--) {
+if (m.__upgraded__) {
+return;
+} else {
+CustomElements.upgrade(m);
+}
+}
+}
+}
+}());Polymer.Base._addFeature({
+_prepIs: function () {
+if (!this.is) {
+var module = (document._currentScript || document.currentScript).parentNode;
+if (module.localName === 'dom-module') {
+var id = module.id || module.getAttribute('name') || module.getAttribute('is');
+this.is = id;
+}
+}
+if (this.is) {
+this.is = this.is.toLowerCase();
+}
+}
+});Polymer.Base._addFeature({
+behaviors: [],
+_desugarBehaviors: function () {
+if (this.behaviors.length) {
+this.behaviors = this._desugarSomeBehaviors(this.behaviors);
+}
+},
+_desugarSomeBehaviors: function (behaviors) {
+var behaviorSet = [];
+behaviors = this._flattenBehaviorsList(behaviors);
+for (var i = behaviors.length - 1; i >= 0; i--) {
+var b = behaviors[i];
+if (behaviorSet.indexOf(b) === -1) {
+this._mixinBehavior(b);
+behaviorSet.unshift(b);
+}
+}
+return behaviorSet;
+},
+_flattenBehaviorsList: function (behaviors) {
+var flat = [];
+for (var i = 0; i < behaviors.length; i++) {
+var b = behaviors[i];
+if (b instanceof Array) {
+flat = flat.concat(this._flattenBehaviorsList(b));
+} else if (b) {
+flat.push(b);
+} else {
+this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for missing or 404 import'));
+}
+}
+return flat;
+},
+_mixinBehavior: function (b) {
+var n$ = Object.getOwnPropertyNames(b);
+var useAssignment = b._noAccessors;
+for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
+if (!Polymer.Base._behaviorProperties[n] && !this.hasOwnProperty(n)) {
+if (useAssignment) {
+this[n] = b[n];
+} else {
+this.copyOwnProperty(n, b, this);
+}
+}
+}
+},
+_prepBehaviors: function () {
+this._prepFlattenedBehaviors(this.behaviors);
+},
+_prepFlattenedBehaviors: function (behaviors) {
+for (var i = 0, l = behaviors.length; i < l; i++) {
+this._prepBehavior(behaviors[i]);
+}
+this._prepBehavior(this);
+},
+_marshalBehaviors: function () {
+for (var i = 0; i < this.behaviors.length; i++) {
+this._marshalBehavior(this.behaviors[i]);
+}
+this._marshalBehavior(this);
+}
+});
+Polymer.Base._behaviorProperties = {
+hostAttributes: true,
+beforeRegister: true,
+registered: true,
+properties: true,
+observers: true,
+listeners: true,
+created: true,
+attached: true,
+detached: true,
+attributeChanged: true,
+ready: true,
+_noAccessors: true
+};Polymer.Base._addFeature({
+_getExtendedPrototype: function (tag) {
+return this._getExtendedNativePrototype(tag);
+},
+_nativePrototypes: {},
+_getExtendedNativePrototype: function (tag) {
+var p = this._nativePrototypes[tag];
+if (!p) {
+p = Object.create(this.getNativePrototype(tag));
+var p$ = Object.getOwnPropertyNames(Polymer.Base);
+for (var i = 0, n; i < p$.length && (n = p$[i]); i++) {
+if (!Polymer.BaseDescriptors[n]) {
+p[n] = Polymer.Base[n];
+}
+}
+Object.defineProperties(p, Polymer.BaseDescriptors);
+this._nativePrototypes[tag] = p;
+}
+return p;
+},
+getNativePrototype: function (tag) {
+return Object.getPrototypeOf(document.createElement(tag));
+}
+});Polymer.Base._addFeature({
+_prepConstructor: function () {
+this._factoryArgs = this.extends ? [
+this.extends,
+this.is
+] : [this.is];
+var ctor = function () {
+return this._factory(arguments);
+};
+if (this.hasOwnProperty('extends')) {
+ctor.extends = this.extends;
+}
+Object.defineProperty(this, 'constructor', {
+value: ctor,
+writable: true,
+configurable: true
+});
+ctor.prototype = this;
+},
+_factory: function (args) {
+var elt = document.createElement.apply(document, this._factoryArgs);
+if (this.factoryImpl) {
+this.factoryImpl.apply(elt, args);
+}
+return elt;
+}
+});Polymer.nob = Object.create(null);
+Polymer.Base._addFeature({
+getPropertyInfo: function (property) {
+var info = this._getPropertyInfo(property, this.properties);
+if (!info) {
+for (var i = 0; i < this.behaviors.length; i++) {
+info = this._getPropertyInfo(property, this.behaviors[i].properties);
+if (info) {
+return info;
+}
+}
+}
+return info || Polymer.nob;
+},
+_getPropertyInfo: function (property, properties) {
+var p = properties && properties[property];
+if (typeof p === 'function') {
+p = properties[property] = { type: p };
+}
+if (p) {
+p.defined = true;
+}
+return p;
+},
+_prepPropertyInfo: function () {
+this._propertyInfo = {};
+for (var i = 0; i < this.behaviors.length; i++) {
+this._addPropertyInfo(this._propertyInfo, this.behaviors[i].properties);
+}
+this._addPropertyInfo(this._propertyInfo, this.properties);
+this._addPropertyInfo(this._propertyInfo, this._propertyEffects);
+},
+_addPropertyInfo: function (target, source) {
+if (source) {
+var t, s;
+for (var i in source) {
+t = target[i];
+s = source[i];
+if (i[0] === '_' && !s.readOnly) {
+continue;
+}
+if (!target[i]) {
+target[i] = {
+type: typeof s === 'function' ? s : s.type,
+readOnly: s.readOnly,
+attribute: Polymer.CaseMap.camelToDashCase(i)
+};
+} else {
+if (!t.type) {
+t.type = s.type;
+}
+if (!t.readOnly) {
+t.readOnly = s.readOnly;
+}
+}
+}
+}
+}
+});
+(function () {
+var propertiesDesc = {
+configurable: true,
+writable: true,
+enumerable: true,
+value: {}
+};
+Polymer.BaseDescriptors.properties = propertiesDesc;
+Object.defineProperty(Polymer.Base, 'properties', propertiesDesc);
+}());Polymer.CaseMap = {
+_caseMap: {},
+_rx: {
+dashToCamel: /-[a-z]/g,
+camelToDash: /([A-Z])/g
+},
+dashToCamelCase: function (dash) {
+return this._caseMap[dash] || (this._caseMap[dash] = dash.indexOf('-') < 0 ? dash : dash.replace(this._rx.dashToCamel, function (m) {
+return m[1].toUpperCase();
+}));
+},
+camelToDashCase: function (camel) {
+return this._caseMap[camel] || (this._caseMap[camel] = camel.replace(this._rx.camelToDash, '-$1').toLowerCase());
+}
+};Polymer.Base._addFeature({
+_addHostAttributes: function (attributes) {
+if (!this._aggregatedAttributes) {
+this._aggregatedAttributes = {};
+}
+if (attributes) {
+this.mixin(this._aggregatedAttributes, attributes);
+}
+},
+_marshalHostAttributes: function () {
+if (this._aggregatedAttributes) {
+this._applyAttributes(this, this._aggregatedAttributes);
+}
+},
+_applyAttributes: function (node, attr$) {
+for (var n in attr$) {
+if (!this.hasAttribute(n) && n !== 'class') {
+var v = attr$[n];
+this.serializeValueToAttribute(v, n, this);
+}
+}
+},
+_marshalAttributes: function () {
+this._takeAttributesToModel(this);
+},
+_takeAttributesToModel: function (model) {
+if (this.hasAttributes()) {
+for (var i in this._propertyInfo) {
+var info = this._propertyInfo[i];
+if (this.hasAttribute(info.attribute)) {
+this._setAttributeToProperty(model, info.attribute, i, info);
+}
+}
+}
+},
+_setAttributeToProperty: function (model, attribute, property, info) {
+if (!this._serializing) {
+property = property || Polymer.CaseMap.dashToCamelCase(attribute);
+info = info || this._propertyInfo && this._propertyInfo[property];
+if (info && !info.readOnly) {
+var v = this.getAttribute(attribute);
+model[property] = this.deserialize(v, info.type);
+}
+}
+},
+_serializing: false,
+reflectPropertyToAttribute: function (property, attribute, value) {
+this._serializing = true;
+value = value === undefined ? this[property] : value;
+this.serializeValueToAttribute(value, attribute || Polymer.CaseMap.camelToDashCase(property));
+this._serializing = false;
+},
+serializeValueToAttribute: function (value, attribute, node) {
+var str = this.serialize(value);
+node = node || this;
+if (str === undefined) {
+node.removeAttribute(attribute);
+} else {
+node.setAttribute(attribute, str);
+}
+},
+deserialize: function (value, type) {
+switch (type) {
+case Number:
+value = Number(value);
+break;
+case Boolean:
+value = value != null;
+break;
+case Object:
+try {
+value = JSON.parse(value);
+} catch (x) {
+}
+break;
+case Array:
+try {
+value = JSON.parse(value);
+} catch (x) {
+value = null;
+console.warn('Polymer::Attributes: couldn`t decode Array as JSON');
+}
+break;
+case Date:
+value = new Date(value);
+break;
+case String:
+default:
+break;
+}
+return value;
+},
+serialize: function (value) {
+switch (typeof value) {
+case 'boolean':
+return value ? '' : undefined;
+case 'object':
+if (value instanceof Date) {
+return value.toString();
+} else if (value) {
+try {
+return JSON.stringify(value);
+} catch (x) {
+return '';
+}
+}
+default:
+return value != null ? value : undefined;
+}
+}
+});Polymer.version = "1.11.3";Polymer.Base._addFeature({
+_registerFeatures: function () {
+this._prepIs();
+this._prepBehaviors();
+this._prepConstructor();
+this._prepPropertyInfo();
+},
+_prepBehavior: function (b) {
+this._addHostAttributes(b.hostAttributes);
+},
+_marshalBehavior: function (b) {
+},
+_initFeatures: function () {
+this._marshalHostAttributes();
+this._marshalBehaviors();
+}
+});</script>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer-mini.html b/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer-mini.html
new file mode 100644
index 00000000000..ac250d7218a
--- /dev/null
+++ b/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer-mini.html
@@ -0,0 +1,2246 @@
+<!--
+@license
+Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+--><link rel="import" href="polymer-micro.html"><script>(function () {
+function resolveCss(cssText, ownerDocument) {
+return cssText.replace(CSS_URL_RX, function (m, pre, url, post) {
+return pre + '\'' + resolve(url.replace(/["']/g, ''), ownerDocument) + '\'' + post;
+});
+}
+function resolveAttrs(element, ownerDocument) {
+for (var name in URL_ATTRS) {
+var a$ = URL_ATTRS[name];
+for (var i = 0, l = a$.length, a, at, v; i < l && (a = a$[i]); i++) {
+if (name === '*' || element.localName === name) {
+at = element.attributes[a];
+v = at && at.value;
+if (v && v.search(BINDING_RX) < 0) {
+at.value = a === 'style' ? resolveCss(v, ownerDocument) : resolve(v, ownerDocument);
+}
+}
+}
+}
+}
+function resolve(url, ownerDocument) {
+if (url && ABS_URL.test(url)) {
+return url;
+}
+var resolver = getUrlResolver(ownerDocument);
+resolver.href = url;
+return resolver.href || url;
+}
+var tempDoc;
+var tempDocBase;
+function resolveUrl(url, baseUri) {
+if (!tempDoc) {
+tempDoc = document.implementation.createHTMLDocument('temp');
+tempDocBase = tempDoc.createElement('base');
+tempDoc.head.appendChild(tempDocBase);
+}
+tempDocBase.href = baseUri;
+return resolve(url, tempDoc);
+}
+function getUrlResolver(ownerDocument) {
+return ownerDocument.body.__urlResolver || (ownerDocument.body.__urlResolver = ownerDocument.createElement('a'));
+}
+function pathFromUrl(url) {
+return url.substring(0, url.lastIndexOf('/') + 1);
+}
+var CSS_URL_RX = /(url\()([^)]*)(\))/g;
+var URL_ATTRS = {
+'*': [
+'href',
+'src',
+'style',
+'url'
+],
+form: ['action']
+};
+var ABS_URL = /(^\/)|(^#)|(^[\w-\d]*:)/;
+var BINDING_RX = /\{\{|\[\[/;
+Polymer.ResolveUrl = {
+resolveCss: resolveCss,
+resolveAttrs: resolveAttrs,
+resolveUrl: resolveUrl,
+pathFromUrl: pathFromUrl
+};
+Polymer.rootPath = Polymer.Settings.rootPath || pathFromUrl(document.baseURI || window.location.href);
+}());Polymer.Base._addFeature({
+_prepTemplate: function () {
+var module;
+if (this._template === undefined) {
+module = Polymer.DomModule.import(this.is);
+this._template = module && module.querySelector('template');
+}
+if (module) {
+var assetPath = module.getAttribute('assetpath') || '';
+var importURL = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI);
+this._importPath = Polymer.ResolveUrl.pathFromUrl(importURL);
+} else {
+this._importPath = '';
+}
+if (this._template && this._template.hasAttribute('is')) {
+this._warn(this._logf('_prepTemplate', 'top-level Polymer template ' + 'must not be a type-extension, found', this._template, 'Move inside simple <template>.'));
+}
+if (this._template && !this._template.content && window.HTMLTemplateElement && HTMLTemplateElement.decorate) {
+HTMLTemplateElement.decorate(this._template);
+}
+},
+_stampTemplate: function () {
+if (this._template) {
+this.root = this.instanceTemplate(this._template);
+}
+},
+instanceTemplate: function (template) {
+var dom = document.importNode(template._content || template.content, true);
+return dom;
+}
+});(function () {
+var baseAttachedCallback = Polymer.Base.attachedCallback;
+var baseDetachedCallback = Polymer.Base.detachedCallback;
+Polymer.Base._addFeature({
+_hostStack: [],
+ready: function () {
+},
+_registerHost: function (host) {
+this.dataHost = host = host || Polymer.Base._hostStack[Polymer.Base._hostStack.length - 1];
+if (host && host._clients) {
+host._clients.push(this);
+}
+this._clients = null;
+this._clientsReadied = false;
+},
+_beginHosting: function () {
+Polymer.Base._hostStack.push(this);
+if (!this._clients) {
+this._clients = [];
+}
+},
+_endHosting: function () {
+Polymer.Base._hostStack.pop();
+},
+_tryReady: function () {
+this._readied = false;
+if (this._canReady()) {
+this._ready();
+}
+},
+_canReady: function () {
+return !this.dataHost || this.dataHost._clientsReadied;
+},
+_ready: function () {
+this._beforeClientsReady();
+if (this._template) {
+this._setupRoot();
+this._readyClients();
+}
+this._clientsReadied = true;
+this._clients = null;
+this._afterClientsReady();
+this._readySelf();
+},
+_readyClients: function () {
+this._beginDistribute();
+var c$ = this._clients;
+if (c$) {
+for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
+c._ready();
+}
+}
+this._finishDistribute();
+},
+_readySelf: function () {
+for (var i = 0, b; i < this.behaviors.length; i++) {
+b = this.behaviors[i];
+if (b.ready) {
+b.ready.call(this);
+}
+}
+if (this.ready) {
+this.ready();
+}
+this._readied = true;
+if (this._attachedPending) {
+this._attachedPending = false;
+this.attachedCallback();
+}
+},
+_beforeClientsReady: function () {
+},
+_afterClientsReady: function () {
+},
+_beforeAttached: function () {
+},
+attachedCallback: function () {
+if (this._readied) {
+this._beforeAttached();
+baseAttachedCallback.call(this);
+} else {
+this._attachedPending = true;
+}
+},
+detachedCallback: function () {
+if (this._readied) {
+baseDetachedCallback.call(this);
+} else {
+this._attachedPending = false;
+}
+}
+});
+}());Polymer.ArraySplice = function () {
+function newSplice(index, removed, addedCount) {
+return {
+index: index,
+removed: removed,
+addedCount: addedCount
+};
+}
+var EDIT_LEAVE = 0;
+var EDIT_UPDATE = 1;
+var EDIT_ADD = 2;
+var EDIT_DELETE = 3;
+function ArraySplice() {
+}
+ArraySplice.prototype = {
+calcEditDistances: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
+var rowCount = oldEnd - oldStart + 1;
+var columnCount = currentEnd - currentStart + 1;
+var distances = new Array(rowCount);
+for (var i = 0; i < rowCount; i++) {
+distances[i] = new Array(columnCount);
+distances[i][0] = i;
+}
+for (var j = 0; j < columnCount; j++)
+distances[0][j] = j;
+for (i = 1; i < rowCount; i++) {
+for (j = 1; j < columnCount; j++) {
+if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))
+distances[i][j] = distances[i - 1][j - 1];
+else {
+var north = distances[i - 1][j] + 1;
+var west = distances[i][j - 1] + 1;
+distances[i][j] = north < west ? north : west;
+}
+}
+}
+return distances;
+},
+spliceOperationsFromEditDistances: function (distances) {
+var i = distances.length - 1;
+var j = distances[0].length - 1;
+var current = distances[i][j];
+var edits = [];
+while (i > 0 || j > 0) {
+if (i == 0) {
+edits.push(EDIT_ADD);
+j--;
+continue;
+}
+if (j == 0) {
+edits.push(EDIT_DELETE);
+i--;
+continue;
+}
+var northWest = distances[i - 1][j - 1];
+var west = distances[i - 1][j];
+var north = distances[i][j - 1];
+var min;
+if (west < north)
+min = west < northWest ? west : northWest;
+else
+min = north < northWest ? north : northWest;
+if (min == northWest) {
+if (northWest == current) {
+edits.push(EDIT_LEAVE);
+} else {
+edits.push(EDIT_UPDATE);
+current = northWest;
+}
+i--;
+j--;
+} else if (min == west) {
+edits.push(EDIT_DELETE);
+i--;
+current = west;
+} else {
+edits.push(EDIT_ADD);
+j--;
+current = north;
+}
+}
+edits.reverse();
+return edits;
+},
+calcSplices: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
+var prefixCount = 0;
+var suffixCount = 0;
+var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
+if (currentStart == 0 && oldStart == 0)
+prefixCount = this.sharedPrefix(current, old, minLength);
+if (currentEnd == current.length && oldEnd == old.length)
+suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
+currentStart += prefixCount;
+oldStart += prefixCount;
+currentEnd -= suffixCount;
+oldEnd -= suffixCount;
+if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)
+return [];
+if (currentStart == currentEnd) {
+var splice = newSplice(currentStart, [], 0);
+while (oldStart < oldEnd)
+splice.removed.push(old[oldStart++]);
+return [splice];
+} else if (oldStart == oldEnd)
+return [newSplice(currentStart, [], currentEnd - currentStart)];
+var ops = this.spliceOperationsFromEditDistances(this.calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
+splice = undefined;
+var splices = [];
+var index = currentStart;
+var oldIndex = oldStart;
+for (var i = 0; i < ops.length; i++) {
+switch (ops[i]) {
+case EDIT_LEAVE:
+if (splice) {
+splices.push(splice);
+splice = undefined;
+}
+index++;
+oldIndex++;
+break;
+case EDIT_UPDATE:
+if (!splice)
+splice = newSplice(index, [], 0);
+splice.addedCount++;
+index++;
+splice.removed.push(old[oldIndex]);
+oldIndex++;
+break;
+case EDIT_ADD:
+if (!splice)
+splice = newSplice(index, [], 0);
+splice.addedCount++;
+index++;
+break;
+case EDIT_DELETE:
+if (!splice)
+splice = newSplice(index, [], 0);
+splice.removed.push(old[oldIndex]);
+oldIndex++;
+break;
+}
+}
+if (splice) {
+splices.push(splice);
+}
+return splices;
+},
+sharedPrefix: function (current, old, searchLength) {
+for (var i = 0; i < searchLength; i++)
+if (!this.equals(current[i], old[i]))
+return i;
+return searchLength;
+},
+sharedSuffix: function (current, old, searchLength) {
+var index1 = current.length;
+var index2 = old.length;
+var count = 0;
+while (count < searchLength && this.equals(current[--index1], old[--index2]))
+count++;
+return count;
+},
+calculateSplices: function (current, previous) {
+return this.calcSplices(current, 0, current.length, previous, 0, previous.length);
+},
+equals: function (currentValue, previousValue) {
+return currentValue === previousValue;
+}
+};
+return new ArraySplice();
+}();Polymer.domInnerHTML = function () {
+var escapeAttrRegExp = /[&\u00A0"]/g;
+var escapeDataRegExp = /[&\u00A0<>]/g;
+function escapeReplace(c) {
+switch (c) {
+case '&':
+return '&amp;';
+case '<':
+return '&lt;';
+case '>':
+return '&gt;';
+case '"':
+return '&quot;';
+case '\xA0':
+return '&nbsp;';
+}
+}
+function escapeAttr(s) {
+return s.replace(escapeAttrRegExp, escapeReplace);
+}
+function escapeData(s) {
+return s.replace(escapeDataRegExp, escapeReplace);
+}
+function makeSet(arr) {
+var set = {};
+for (var i = 0; i < arr.length; i++) {
+set[arr[i]] = true;
+}
+return set;
+}
+var voidElements = makeSet([
+'area',
+'base',
+'br',
+'col',
+'command',
+'embed',
+'hr',
+'img',
+'input',
+'keygen',
+'link',
+'meta',
+'param',
+'source',
+'track',
+'wbr'
+]);
+var plaintextParents = makeSet([
+'style',
+'script',
+'xmp',
+'iframe',
+'noembed',
+'noframes',
+'plaintext',
+'noscript'
+]);
+function getOuterHTML(node, parentNode, composed) {
+switch (node.nodeType) {
+case Node.ELEMENT_NODE:
+var tagName = node.localName;
+var s = '<' + tagName;
+var attrs = node.attributes;
+for (var i = 0, attr; attr = attrs[i]; i++) {
+s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
+}
+s += '>';
+if (voidElements[tagName]) {
+return s;
+}
+return s + getInnerHTML(node, composed) + '</' + tagName + '>';
+case Node.TEXT_NODE:
+var data = node.data;
+if (parentNode && plaintextParents[parentNode.localName]) {
+return data;
+}
+return escapeData(data);
+case Node.COMMENT_NODE:
+return '<!--' + node.data + '-->';
+default:
+console.error(node);
+throw new Error('not implemented');
+}
+}
+function getInnerHTML(node, composed) {
+if (node instanceof HTMLTemplateElement)
+node = node.content;
+var s = '';
+var c$ = Polymer.dom(node).childNodes;
+for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) {
+s += getOuterHTML(child, node, composed);
+}
+return s;
+}
+return { getInnerHTML: getInnerHTML };
+}();(function () {
+'use strict';
+var nativeInsertBefore = Element.prototype.insertBefore;
+var nativeAppendChild = Element.prototype.appendChild;
+var nativeRemoveChild = Element.prototype.removeChild;
+Polymer.TreeApi = {
+arrayCopyChildNodes: function (parent) {
+var copy = [], i = 0;
+for (var n = parent.firstChild; n; n = n.nextSibling) {
+copy[i++] = n;
+}
+return copy;
+},
+arrayCopyChildren: function (parent) {
+var copy = [], i = 0;
+for (var n = parent.firstElementChild; n; n = n.nextElementSibling) {
+copy[i++] = n;
+}
+return copy;
+},
+arrayCopy: function (a$) {
+var l = a$.length;
+var copy = new Array(l);
+for (var i = 0; i < l; i++) {
+copy[i] = a$[i];
+}
+return copy;
+}
+};
+Polymer.TreeApi.Logical = {
+hasParentNode: function (node) {
+return Boolean(node.__dom && node.__dom.parentNode);
+},
+hasChildNodes: function (node) {
+return Boolean(node.__dom && node.__dom.childNodes !== undefined);
+},
+getChildNodes: function (node) {
+return this.hasChildNodes(node) ? this._getChildNodes(node) : node.childNodes;
+},
+_getChildNodes: function (node) {
+if (!node.__dom.childNodes) {
+node.__dom.childNodes = [];
+for (var n = node.__dom.firstChild; n; n = n.__dom.nextSibling) {
+node.__dom.childNodes.push(n);
+}
+}
+return node.__dom.childNodes;
+},
+getParentNode: function (node) {
+return node.__dom && node.__dom.parentNode !== undefined ? node.__dom.parentNode : node.parentNode;
+},
+getFirstChild: function (node) {
+return node.__dom && node.__dom.firstChild !== undefined ? node.__dom.firstChild : node.firstChild;
+},
+getLastChild: function (node) {
+return node.__dom && node.__dom.lastChild !== undefined ? node.__dom.lastChild : node.lastChild;
+},
+getNextSibling: function (node) {
+return node.__dom && node.__dom.nextSibling !== undefined ? node.__dom.nextSibling : node.nextSibling;
+},
+getPreviousSibling: function (node) {
+return node.__dom && node.__dom.previousSibling !== undefined ? node.__dom.previousSibling : node.previousSibling;
+},
+getFirstElementChild: function (node) {
+return node.__dom && node.__dom.firstChild !== undefined ? this._getFirstElementChild(node) : node.firstElementChild;
+},
+_getFirstElementChild: function (node) {
+var n = node.__dom.firstChild;
+while (n && n.nodeType !== Node.ELEMENT_NODE) {
+n = n.__dom.nextSibling;
+}
+return n;
+},
+getLastElementChild: function (node) {
+return node.__dom && node.__dom.lastChild !== undefined ? this._getLastElementChild(node) : node.lastElementChild;
+},
+_getLastElementChild: function (node) {
+var n = node.__dom.lastChild;
+while (n && n.nodeType !== Node.ELEMENT_NODE) {
+n = n.__dom.previousSibling;
+}
+return n;
+},
+getNextElementSibling: function (node) {
+return node.__dom && node.__dom.nextSibling !== undefined ? this._getNextElementSibling(node) : node.nextElementSibling;
+},
+_getNextElementSibling: function (node) {
+var n = node.__dom.nextSibling;
+while (n && n.nodeType !== Node.ELEMENT_NODE) {
+n = n.__dom.nextSibling;
+}
+return n;
+},
+getPreviousElementSibling: function (node) {
+return node.__dom && node.__dom.previousSibling !== undefined ? this._getPreviousElementSibling(node) : node.previousElementSibling;
+},
+_getPreviousElementSibling: function (node) {
+var n = node.__dom.previousSibling;
+while (n && n.nodeType !== Node.ELEMENT_NODE) {
+n = n.__dom.previousSibling;
+}
+return n;
+},
+saveChildNodes: function (node) {
+if (!this.hasChildNodes(node)) {
+node.__dom = node.__dom || {};
+node.__dom.firstChild = node.firstChild;
+node.__dom.lastChild = node.lastChild;
+node.__dom.childNodes = [];
+for (var n = node.firstChild; n; n = n.nextSibling) {
+n.__dom = n.__dom || {};
+n.__dom.parentNode = node;
+node.__dom.childNodes.push(n);
+n.__dom.nextSibling = n.nextSibling;
+n.__dom.previousSibling = n.previousSibling;
+}
+}
+},
+recordInsertBefore: function (node, container, ref_node) {
+container.__dom.childNodes = null;
+if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
+for (var n = node.firstChild; n; n = n.nextSibling) {
+this._linkNode(n, container, ref_node);
+}
+} else {
+this._linkNode(node, container, ref_node);
+}
+},
+_linkNode: function (node, container, ref_node) {
+node.__dom = node.__dom || {};
+container.__dom = container.__dom || {};
+if (ref_node) {
+ref_node.__dom = ref_node.__dom || {};
+}
+node.__dom.previousSibling = ref_node ? ref_node.__dom.previousSibling : container.__dom.lastChild;
+if (node.__dom.previousSibling) {
+node.__dom.previousSibling.__dom.nextSibling = node;
+}
+node.__dom.nextSibling = ref_node || null;
+if (node.__dom.nextSibling) {
+node.__dom.nextSibling.__dom.previousSibling = node;
+}
+node.__dom.parentNode = container;
+if (ref_node) {
+if (ref_node === container.__dom.firstChild) {
+container.__dom.firstChild = node;
+}
+} else {
+container.__dom.lastChild = node;
+if (!container.__dom.firstChild) {
+container.__dom.firstChild = node;
+}
+}
+container.__dom.childNodes = null;
+},
+recordRemoveChild: function (node, container) {
+node.__dom = node.__dom || {};
+container.__dom = container.__dom || {};
+if (node === container.__dom.firstChild) {
+container.__dom.firstChild = node.__dom.nextSibling;
+}
+if (node === container.__dom.lastChild) {
+container.__dom.lastChild = node.__dom.previousSibling;
+}
+var p = node.__dom.previousSibling;
+var n = node.__dom.nextSibling;
+if (p) {
+p.__dom.nextSibling = n;
+}
+if (n) {
+n.__dom.previousSibling = p;
+}
+node.__dom.parentNode = node.__dom.previousSibling = node.__dom.nextSibling = undefined;
+container.__dom.childNodes = null;
+}
+};
+Polymer.TreeApi.Composed = {
+getChildNodes: function (node) {
+return Polymer.TreeApi.arrayCopyChildNodes(node);
+},
+getParentNode: function (node) {
+return node.parentNode;
+},
+clearChildNodes: function (node) {
+node.textContent = '';
+},
+insertBefore: function (parentNode, newChild, refChild) {
+return nativeInsertBefore.call(parentNode, newChild, refChild || null);
+},
+appendChild: function (parentNode, newChild) {
+return nativeAppendChild.call(parentNode, newChild);
+},
+removeChild: function (parentNode, node) {
+return nativeRemoveChild.call(parentNode, node);
+}
+};
+}());Polymer.DomApi = function () {
+'use strict';
+var Settings = Polymer.Settings;
+var TreeApi = Polymer.TreeApi;
+var DomApi = function (node) {
+this.node = needsToWrap ? DomApi.wrap(node) : node;
+};
+var needsToWrap = Settings.hasShadow && !Settings.nativeShadow;
+DomApi.wrap = window.wrap ? window.wrap : function (node) {
+return node;
+};
+DomApi.prototype = {
+flush: function () {
+Polymer.dom.flush();
+},
+deepContains: function (node) {
+if (this.node.contains(node)) {
+return true;
+}
+var n = node;
+var doc = node.ownerDocument;
+while (n && n !== doc && n !== this.node) {
+n = Polymer.dom(n).parentNode || n.host;
+}
+return n === this.node;
+},
+queryDistributedElements: function (selector) {
+var c$ = this.getEffectiveChildNodes();
+var list = [];
+for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
+if (c.nodeType === Node.ELEMENT_NODE && DomApi.matchesSelector.call(c, selector)) {
+list.push(c);
+}
+}
+return list;
+},
+getEffectiveChildNodes: function () {
+var list = [];
+var c$ = this.childNodes;
+for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
+if (c.localName === CONTENT) {
+var d$ = dom(c).getDistributedNodes();
+for (var j = 0; j < d$.length; j++) {
+list.push(d$[j]);
+}
+} else {
+list.push(c);
+}
+}
+return list;
+},
+observeNodes: function (callback) {
+if (callback) {
+if (!this.observer) {
+this.observer = this.node.localName === CONTENT ? new DomApi.DistributedNodesObserver(this) : new DomApi.EffectiveNodesObserver(this);
+}
+return this.observer.addListener(callback);
+}
+},
+unobserveNodes: function (handle) {
+if (this.observer) {
+this.observer.removeListener(handle);
+}
+},
+notifyObserver: function () {
+if (this.observer) {
+this.observer.notify();
+}
+},
+_query: function (matcher, node, halter) {
+node = node || this.node;
+var list = [];
+this._queryElements(TreeApi.Logical.getChildNodes(node), matcher, halter, list);
+return list;
+},
+_queryElements: function (elements, matcher, halter, list) {
+for (var i = 0, l = elements.length, c; i < l && (c = elements[i]); i++) {
+if (c.nodeType === Node.ELEMENT_NODE) {
+if (this._queryElement(c, matcher, halter, list)) {
+return true;
+}
+}
+}
+},
+_queryElement: function (node, matcher, halter, list) {
+var result = matcher(node);
+if (result) {
+list.push(node);
+}
+if (halter && halter(result)) {
+return result;
+}
+this._queryElements(TreeApi.Logical.getChildNodes(node), matcher, halter, list);
+}
+};
+var CONTENT = DomApi.CONTENT = 'content';
+var dom = DomApi.factory = function (node) {
+node = node || document;
+if (!node.__domApi) {
+node.__domApi = new DomApi.ctor(node);
+}
+return node.__domApi;
+};
+DomApi.hasApi = function (node) {
+return Boolean(node.__domApi);
+};
+DomApi.ctor = DomApi;
+Polymer.dom = function (obj, patch) {
+if (obj instanceof Event) {
+return Polymer.EventApi.factory(obj);
+} else {
+return DomApi.factory(obj, patch);
+}
+};
+var p = Element.prototype;
+DomApi.matchesSelector = p.matches || p.matchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.oMatchesSelector || p.webkitMatchesSelector;
+return DomApi;
+}();(function () {
+'use strict';
+var Settings = Polymer.Settings;
+var DomApi = Polymer.DomApi;
+var dom = DomApi.factory;
+var TreeApi = Polymer.TreeApi;
+var getInnerHTML = Polymer.domInnerHTML.getInnerHTML;
+var CONTENT = DomApi.CONTENT;
+if (Settings.useShadow) {
+return;
+}
+var nativeCloneNode = Element.prototype.cloneNode;
+var nativeImportNode = Document.prototype.importNode;
+Polymer.Base.mixin(DomApi.prototype, {
+_lazyDistribute: function (host) {
+if (host.shadyRoot && host.shadyRoot._distributionClean) {
+host.shadyRoot._distributionClean = false;
+Polymer.dom.addDebouncer(host.debounce('_distribute', host._distributeContent));
+}
+},
+appendChild: function (node) {
+return this.insertBefore(node);
+},
+insertBefore: function (node, ref_node) {
+if (ref_node && TreeApi.Logical.getParentNode(ref_node) !== this.node) {
+throw Error('The ref_node to be inserted before is not a child ' + 'of this node');
+}
+if (node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
+var parent = TreeApi.Logical.getParentNode(node);
+if (parent) {
+if (DomApi.hasApi(parent)) {
+dom(parent).notifyObserver();
+}
+this._removeNode(node);
+} else {
+this._removeOwnerShadyRoot(node);
+}
+}
+if (!this._addNode(node, ref_node)) {
+if (ref_node) {
+ref_node = ref_node.localName === CONTENT ? this._firstComposedNode(ref_node) : ref_node;
+}
+var container = this.node._isShadyRoot ? this.node.host : this.node;
+if (ref_node) {
+TreeApi.Composed.insertBefore(container, node, ref_node);
+} else {
+TreeApi.Composed.appendChild(container, node);
+}
+}
+this.notifyObserver();
+return node;
+},
+_addNode: function (node, ref_node) {
+var root = this.getOwnerRoot();
+if (root) {
+var ipAdded = this._maybeAddInsertionPoint(node, this.node);
+if (!root._invalidInsertionPoints) {
+root._invalidInsertionPoints = ipAdded;
+}
+this._addNodeToHost(root.host, node);
+}
+if (TreeApi.Logical.hasChildNodes(this.node)) {
+TreeApi.Logical.recordInsertBefore(node, this.node, ref_node);
+}
+var handled = this._maybeDistribute(node) || this.node.shadyRoot;
+if (handled) {
+if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
+while (node.firstChild) {
+TreeApi.Composed.removeChild(node, node.firstChild);
+}
+} else {
+var parent = TreeApi.Composed.getParentNode(node);
+if (parent) {
+TreeApi.Composed.removeChild(parent, node);
+}
+}
+}
+return handled;
+},
+removeChild: function (node) {
+if (TreeApi.Logical.getParentNode(node) !== this.node) {
+throw Error('The node to be removed is not a child of this node: ' + node);
+}
+if (!this._removeNode(node)) {
+var container = this.node._isShadyRoot ? this.node.host : this.node;
+var parent = TreeApi.Composed.getParentNode(node);
+if (container === parent) {
+TreeApi.Composed.removeChild(container, node);
+}
+}
+this.notifyObserver();
+return node;
+},
+_removeNode: function (node) {
+var logicalParent = TreeApi.Logical.hasParentNode(node) && TreeApi.Logical.getParentNode(node);
+var distributed;
+var root = this._ownerShadyRootForNode(node);
+if (logicalParent) {
+distributed = dom(node)._maybeDistributeParent();
+TreeApi.Logical.recordRemoveChild(node, logicalParent);
+if (root && this._removeDistributedChildren(root, node)) {
+root._invalidInsertionPoints = true;
+this._lazyDistribute(root.host);
+}
+}
+this._removeOwnerShadyRoot(node);
+if (root) {
+this._removeNodeFromHost(root.host, node);
+}
+return distributed;
+},
+replaceChild: function (node, ref_node) {
+this.insertBefore(node, ref_node);
+this.removeChild(ref_node);
+return node;
+},
+_hasCachedOwnerRoot: function (node) {
+return Boolean(node._ownerShadyRoot !== undefined);
+},
+getOwnerRoot: function () {
+return this._ownerShadyRootForNode(this.node);
+},
+_ownerShadyRootForNode: function (node) {
+if (!node) {
+return;
+}
+var root = node._ownerShadyRoot;
+if (root === undefined) {
+if (node._isShadyRoot) {
+root = node;
+} else {
+var parent = TreeApi.Logical.getParentNode(node);
+if (parent) {
+root = parent._isShadyRoot ? parent : this._ownerShadyRootForNode(parent);
+} else {
+root = null;
+}
+}
+if (root || document.documentElement.contains(node)) {
+node._ownerShadyRoot = root;
+}
+}
+return root;
+},
+_maybeDistribute: function (node) {
+var fragContent = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noContent && dom(node).querySelector(CONTENT);
+var wrappedContent = fragContent && TreeApi.Logical.getParentNode(fragContent).nodeType !== Node.DOCUMENT_FRAGMENT_NODE;
+var hasContent = fragContent || node.localName === CONTENT;
+if (hasContent) {
+var root = this.getOwnerRoot();
+if (root) {
+this._lazyDistribute(root.host);
+}
+}
+var needsDist = this._nodeNeedsDistribution(this.node);
+if (needsDist) {
+this._lazyDistribute(this.node);
+}
+return needsDist || hasContent && !wrappedContent;
+},
+_maybeAddInsertionPoint: function (node, parent) {
+var added;
+if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noContent) {
+var c$ = dom(node).querySelectorAll(CONTENT);
+for (var i = 0, n, np, na; i < c$.length && (n = c$[i]); i++) {
+np = TreeApi.Logical.getParentNode(n);
+if (np === node) {
+np = parent;
+}
+na = this._maybeAddInsertionPoint(n, np);
+added = added || na;
+}
+} else if (node.localName === CONTENT) {
+TreeApi.Logical.saveChildNodes(parent);
+TreeApi.Logical.saveChildNodes(node);
+added = true;
+}
+return added;
+},
+_updateInsertionPoints: function (host) {
+var i$ = host.shadyRoot._insertionPoints = dom(host.shadyRoot).querySelectorAll(CONTENT);
+for (var i = 0, c; i < i$.length; i++) {
+c = i$[i];
+TreeApi.Logical.saveChildNodes(c);
+TreeApi.Logical.saveChildNodes(TreeApi.Logical.getParentNode(c));
+}
+},
+_nodeNeedsDistribution: function (node) {
+return node && node.shadyRoot && DomApi.hasInsertionPoint(node.shadyRoot);
+},
+_addNodeToHost: function (host, node) {
+if (host._elementAdd) {
+host._elementAdd(node);
+}
+},
+_removeNodeFromHost: function (host, node) {
+if (host._elementRemove) {
+host._elementRemove(node);
+}
+},
+_removeDistributedChildren: function (root, container) {
+var hostNeedsDist;
+var ip$ = root._insertionPoints;
+for (var i = 0; i < ip$.length; i++) {
+var content = ip$[i];
+if (this._contains(container, content)) {
+var dc$ = dom(content).getDistributedNodes();
+for (var j = 0; j < dc$.length; j++) {
+hostNeedsDist = true;
+var node = dc$[j];
+var parent = TreeApi.Composed.getParentNode(node);
+if (parent) {
+TreeApi.Composed.removeChild(parent, node);
+}
+}
+}
+}
+return hostNeedsDist;
+},
+_contains: function (container, node) {
+while (node) {
+if (node == container) {
+return true;
+}
+node = TreeApi.Logical.getParentNode(node);
+}
+},
+_removeOwnerShadyRoot: function (node) {
+if (this._hasCachedOwnerRoot(node)) {
+var c$ = TreeApi.Logical.getChildNodes(node);
+for (var i = 0, l = c$.length, n; i < l && (n = c$[i]); i++) {
+this._removeOwnerShadyRoot(n);
+}
+}
+node._ownerShadyRoot = undefined;
+},
+_firstComposedNode: function (content) {
+var n$ = dom(content).getDistributedNodes();
+for (var i = 0, l = n$.length, n, p$; i < l && (n = n$[i]); i++) {
+p$ = dom(n).getDestinationInsertionPoints();
+if (p$[p$.length - 1] === content) {
+return n;
+}
+}
+},
+querySelector: function (selector) {
+var result = this._query(function (n) {
+return DomApi.matchesSelector.call(n, selector);
+}, this.node, function (n) {
+return Boolean(n);
+})[0];
+return result || null;
+},
+querySelectorAll: function (selector) {
+return this._query(function (n) {
+return DomApi.matchesSelector.call(n, selector);
+}, this.node);
+},
+getDestinationInsertionPoints: function () {
+return this.node._destinationInsertionPoints || [];
+},
+getDistributedNodes: function () {
+return this.node._distributedNodes || [];
+},
+_clear: function () {
+while (this.childNodes.length) {
+this.removeChild(this.childNodes[0]);
+}
+},
+setAttribute: function (name, value) {
+this.node.setAttribute(name, value);
+this._maybeDistributeParent();
+},
+removeAttribute: function (name) {
+this.node.removeAttribute(name);
+this._maybeDistributeParent();
+},
+_maybeDistributeParent: function () {
+if (this._nodeNeedsDistribution(this.parentNode)) {
+this._lazyDistribute(this.parentNode);
+return true;
+}
+},
+cloneNode: function (deep) {
+var n = nativeCloneNode.call(this.node, false);
+if (deep) {
+var c$ = this.childNodes;
+var d = dom(n);
+for (var i = 0, nc; i < c$.length; i++) {
+nc = dom(c$[i]).cloneNode(true);
+d.appendChild(nc);
+}
+}
+return n;
+},
+importNode: function (externalNode, deep) {
+var doc = this.node instanceof Document ? this.node : this.node.ownerDocument;
+var n = nativeImportNode.call(doc, externalNode, false);
+if (deep) {
+var c$ = TreeApi.Logical.getChildNodes(externalNode);
+var d = dom(n);
+for (var i = 0, nc; i < c$.length; i++) {
+nc = dom(doc).importNode(c$[i], true);
+d.appendChild(nc);
+}
+}
+return n;
+},
+_getComposedInnerHTML: function () {
+return getInnerHTML(this.node, true);
+}
+});
+Object.defineProperties(DomApi.prototype, {
+activeElement: {
+get: function () {
+var active = document.activeElement;
+if (!active) {
+return null;
+}
+var isShadyRoot = !!this.node._isShadyRoot;
+if (this.node !== document) {
+if (!isShadyRoot) {
+return null;
+}
+if (this.node.host === active || !this.node.host.contains(active)) {
+return null;
+}
+}
+var activeRoot = dom(active).getOwnerRoot();
+while (activeRoot && activeRoot !== this.node) {
+active = activeRoot.host;
+activeRoot = dom(active).getOwnerRoot();
+}
+if (this.node === document) {
+return activeRoot ? null : active;
+} else {
+return activeRoot === this.node ? active : null;
+}
+},
+configurable: true
+},
+childNodes: {
+get: function () {
+var c$ = TreeApi.Logical.getChildNodes(this.node);
+return Array.isArray(c$) ? c$ : TreeApi.arrayCopyChildNodes(this.node);
+},
+configurable: true
+},
+children: {
+get: function () {
+if (TreeApi.Logical.hasChildNodes(this.node)) {
+return Array.prototype.filter.call(this.childNodes, function (n) {
+return n.nodeType === Node.ELEMENT_NODE;
+});
+} else {
+return TreeApi.arrayCopyChildren(this.node);
+}
+},
+configurable: true
+},
+parentNode: {
+get: function () {
+return TreeApi.Logical.getParentNode(this.node);
+},
+configurable: true
+},
+firstChild: {
+get: function () {
+return TreeApi.Logical.getFirstChild(this.node);
+},
+configurable: true
+},
+lastChild: {
+get: function () {
+return TreeApi.Logical.getLastChild(this.node);
+},
+configurable: true
+},
+nextSibling: {
+get: function () {
+return TreeApi.Logical.getNextSibling(this.node);
+},
+configurable: true
+},
+previousSibling: {
+get: function () {
+return TreeApi.Logical.getPreviousSibling(this.node);
+},
+configurable: true
+},
+firstElementChild: {
+get: function () {
+return TreeApi.Logical.getFirstElementChild(this.node);
+},
+configurable: true
+},
+lastElementChild: {
+get: function () {
+return TreeApi.Logical.getLastElementChild(this.node);
+},
+configurable: true
+},
+nextElementSibling: {
+get: function () {
+return TreeApi.Logical.getNextElementSibling(this.node);
+},
+configurable: true
+},
+previousElementSibling: {
+get: function () {
+return TreeApi.Logical.getPreviousElementSibling(this.node);
+},
+configurable: true
+},
+textContent: {
+get: function () {
+var nt = this.node.nodeType;
+if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
+return this.node.textContent;
+} else {
+var tc = [];
+for (var i = 0, cn = this.childNodes, c; c = cn[i]; i++) {
+if (c.nodeType !== Node.COMMENT_NODE) {
+tc.push(c.textContent);
+}
+}
+return tc.join('');
+}
+},
+set: function (text) {
+var nt = this.node.nodeType;
+if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
+this.node.textContent = text;
+} else {
+this._clear();
+if (text) {
+this.appendChild(document.createTextNode(text));
+}
+}
+},
+configurable: true
+},
+innerHTML: {
+get: function () {
+var nt = this.node.nodeType;
+if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
+return null;
+} else {
+return getInnerHTML(this.node);
+}
+},
+set: function (text) {
+var nt = this.node.nodeType;
+if (nt !== Node.TEXT_NODE || nt !== Node.COMMENT_NODE) {
+this._clear();
+var d = document.createElement('div');
+d.innerHTML = text;
+var c$ = TreeApi.arrayCopyChildNodes(d);
+for (var i = 0; i < c$.length; i++) {
+this.appendChild(c$[i]);
+}
+}
+},
+configurable: true
+}
+});
+DomApi.hasInsertionPoint = function (root) {
+return Boolean(root && root._insertionPoints.length);
+};
+}());(function () {
+'use strict';
+var Settings = Polymer.Settings;
+var TreeApi = Polymer.TreeApi;
+var DomApi = Polymer.DomApi;
+if (!Settings.useShadow) {
+return;
+}
+Polymer.Base.mixin(DomApi.prototype, {
+querySelectorAll: function (selector) {
+return TreeApi.arrayCopy(this.node.querySelectorAll(selector));
+},
+getOwnerRoot: function () {
+var n = this.node;
+while (n) {
+if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) {
+return n;
+}
+n = n.parentNode;
+}
+},
+importNode: function (externalNode, deep) {
+var doc = this.node instanceof Document ? this.node : this.node.ownerDocument;
+return doc.importNode(externalNode, deep);
+},
+getDestinationInsertionPoints: function () {
+var n$ = this.node.getDestinationInsertionPoints && this.node.getDestinationInsertionPoints();
+return n$ ? TreeApi.arrayCopy(n$) : [];
+},
+getDistributedNodes: function () {
+var n$ = this.node.getDistributedNodes && this.node.getDistributedNodes();
+return n$ ? TreeApi.arrayCopy(n$) : [];
+}
+});
+Object.defineProperties(DomApi.prototype, {
+activeElement: {
+get: function () {
+var node = DomApi.wrap(this.node);
+var activeElement = node.activeElement;
+return node.contains(activeElement) ? activeElement : null;
+},
+configurable: true
+},
+childNodes: {
+get: function () {
+return TreeApi.arrayCopyChildNodes(this.node);
+},
+configurable: true
+},
+children: {
+get: function () {
+return TreeApi.arrayCopyChildren(this.node);
+},
+configurable: true
+},
+textContent: {
+get: function () {
+return this.node.textContent;
+},
+set: function (value) {
+return this.node.textContent = value;
+},
+configurable: true
+},
+innerHTML: {
+get: function () {
+return this.node.innerHTML;
+},
+set: function (value) {
+return this.node.innerHTML = value;
+},
+configurable: true
+}
+});
+var forwardMethods = function (m$) {
+for (var i = 0; i < m$.length; i++) {
+forwardMethod(m$[i]);
+}
+};
+var forwardMethod = function (method) {
+DomApi.prototype[method] = function () {
+return this.node[method].apply(this.node, arguments);
+};
+};
+forwardMethods([
+'cloneNode',
+'appendChild',
+'insertBefore',
+'removeChild',
+'replaceChild',
+'setAttribute',
+'removeAttribute',
+'querySelector'
+]);
+var forwardProperties = function (f$) {
+for (var i = 0; i < f$.length; i++) {
+forwardProperty(f$[i]);
+}
+};
+var forwardProperty = function (name) {
+Object.defineProperty(DomApi.prototype, name, {
+get: function () {
+return this.node[name];
+},
+configurable: true
+});
+};
+forwardProperties([
+'parentNode',
+'firstChild',
+'lastChild',
+'nextSibling',
+'previousSibling',
+'firstElementChild',
+'lastElementChild',
+'nextElementSibling',
+'previousElementSibling'
+]);
+}());Polymer.Base.mixin(Polymer.dom, {
+_flushGuard: 0,
+_FLUSH_MAX: 100,
+_needsTakeRecords: !Polymer.Settings.useNativeCustomElements,
+_debouncers: [],
+_staticFlushList: [],
+_finishDebouncer: null,
+flush: function () {
+this._flushGuard = 0;
+this._prepareFlush();
+while (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) {
+while (this._debouncers.length) {
+this._debouncers.shift().complete();
+}
+if (this._finishDebouncer) {
+this._finishDebouncer.complete();
+}
+this._prepareFlush();
+this._flushGuard++;
+}
+if (this._flushGuard >= this._FLUSH_MAX) {
+console.warn('Polymer.dom.flush aborted. Flush may not be complete.');
+}
+},
+_prepareFlush: function () {
+if (this._needsTakeRecords) {
+CustomElements.takeRecords();
+}
+for (var i = 0; i < this._staticFlushList.length; i++) {
+this._staticFlushList[i]();
+}
+},
+addStaticFlush: function (fn) {
+this._staticFlushList.push(fn);
+},
+removeStaticFlush: function (fn) {
+var i = this._staticFlushList.indexOf(fn);
+if (i >= 0) {
+this._staticFlushList.splice(i, 1);
+}
+},
+addDebouncer: function (debouncer) {
+this._debouncers.push(debouncer);
+this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlush);
+},
+_finishFlush: function () {
+Polymer.dom._debouncers = [];
+}
+});Polymer.EventApi = function () {
+'use strict';
+var DomApi = Polymer.DomApi.ctor;
+var Settings = Polymer.Settings;
+DomApi.Event = function (event) {
+this.event = event;
+};
+if (Settings.useShadow) {
+DomApi.Event.prototype = {
+get rootTarget() {
+return this.event.path[0];
+},
+get localTarget() {
+return this.event.target;
+},
+get path() {
+var path = this.event.path;
+if (!Array.isArray(path)) {
+path = Array.prototype.slice.call(path);
+}
+return path;
+}
+};
+} else {
+DomApi.Event.prototype = {
+get rootTarget() {
+return this.event.target;
+},
+get localTarget() {
+var current = this.event.currentTarget;
+var currentRoot = current && Polymer.dom(current).getOwnerRoot();
+var p$ = this.path;
+for (var i = 0; i < p$.length; i++) {
+if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) {
+return p$[i];
+}
+}
+},
+get path() {
+if (!this.event._path) {
+var path = [];
+var current = this.rootTarget;
+while (current) {
+path.push(current);
+var insertionPoints = Polymer.dom(current).getDestinationInsertionPoints();
+if (insertionPoints.length) {
+for (var i = 0; i < insertionPoints.length - 1; i++) {
+path.push(insertionPoints[i]);
+}
+current = insertionPoints[insertionPoints.length - 1];
+} else {
+current = Polymer.dom(current).parentNode || current.host;
+}
+}
+path.push(window);
+this.event._path = path;
+}
+return this.event._path;
+}
+};
+}
+var factory = function (event) {
+if (!event.__eventApi) {
+event.__eventApi = new DomApi.Event(event);
+}
+return event.__eventApi;
+};
+return { factory: factory };
+}();(function () {
+'use strict';
+var DomApi = Polymer.DomApi.ctor;
+var useShadow = Polymer.Settings.useShadow;
+Object.defineProperty(DomApi.prototype, 'classList', {
+get: function () {
+if (!this._classList) {
+this._classList = new DomApi.ClassList(this);
+}
+return this._classList;
+},
+configurable: true
+});
+DomApi.ClassList = function (host) {
+this.domApi = host;
+this.node = host.node;
+};
+DomApi.ClassList.prototype = {
+add: function () {
+this.node.classList.add.apply(this.node.classList, arguments);
+this._distributeParent();
+},
+remove: function () {
+this.node.classList.remove.apply(this.node.classList, arguments);
+this._distributeParent();
+},
+toggle: function () {
+this.node.classList.toggle.apply(this.node.classList, arguments);
+this._distributeParent();
+},
+_distributeParent: function () {
+if (!useShadow) {
+this.domApi._maybeDistributeParent();
+}
+},
+contains: function () {
+return this.node.classList.contains.apply(this.node.classList, arguments);
+}
+};
+}());(function () {
+'use strict';
+var DomApi = Polymer.DomApi.ctor;
+var Settings = Polymer.Settings;
+DomApi.EffectiveNodesObserver = function (domApi) {
+this.domApi = domApi;
+this.node = this.domApi.node;
+this._listeners = [];
+};
+DomApi.EffectiveNodesObserver.prototype = {
+addListener: function (callback) {
+if (!this._isSetup) {
+this._setup();
+this._isSetup = true;
+}
+var listener = {
+fn: callback,
+_nodes: []
+};
+this._listeners.push(listener);
+this._scheduleNotify();
+return listener;
+},
+removeListener: function (handle) {
+var i = this._listeners.indexOf(handle);
+if (i >= 0) {
+this._listeners.splice(i, 1);
+handle._nodes = [];
+}
+if (!this._hasListeners()) {
+this._cleanup();
+this._isSetup = false;
+}
+},
+_setup: function () {
+this._observeContentElements(this.domApi.childNodes);
+},
+_cleanup: function () {
+this._unobserveContentElements(this.domApi.childNodes);
+},
+_hasListeners: function () {
+return Boolean(this._listeners.length);
+},
+_scheduleNotify: function () {
+if (this._debouncer) {
+this._debouncer.stop();
+}
+this._debouncer = Polymer.Debounce(this._debouncer, this._notify);
+this._debouncer.context = this;
+Polymer.dom.addDebouncer(this._debouncer);
+},
+notify: function () {
+if (this._hasListeners()) {
+this._scheduleNotify();
+}
+},
+_notify: function () {
+this._beforeCallListeners();
+this._callListeners();
+},
+_beforeCallListeners: function () {
+this._updateContentElements();
+},
+_updateContentElements: function () {
+this._observeContentElements(this.domApi.childNodes);
+},
+_observeContentElements: function (elements) {
+for (var i = 0, n; i < elements.length && (n = elements[i]); i++) {
+if (this._isContent(n)) {
+n.__observeNodesMap = n.__observeNodesMap || new WeakMap();
+if (!n.__observeNodesMap.has(this)) {
+n.__observeNodesMap.set(this, this._observeContent(n));
+}
+}
+}
+},
+_observeContent: function (content) {
+var self = this;
+var h = Polymer.dom(content).observeNodes(function () {
+self._scheduleNotify();
+});
+h._avoidChangeCalculation = true;
+return h;
+},
+_unobserveContentElements: function (elements) {
+for (var i = 0, n, h; i < elements.length && (n = elements[i]); i++) {
+if (this._isContent(n)) {
+h = n.__observeNodesMap.get(this);
+if (h) {
+Polymer.dom(n).unobserveNodes(h);
+n.__observeNodesMap.delete(this);
+}
+}
+}
+},
+_isContent: function (node) {
+return node.localName === 'content';
+},
+_callListeners: function () {
+var o$ = this._listeners;
+var nodes = this._getEffectiveNodes();
+for (var i = 0, o; i < o$.length && (o = o$[i]); i++) {
+var info = this._generateListenerInfo(o, nodes);
+if (info || o._alwaysNotify) {
+this._callListener(o, info);
+}
+}
+},
+_getEffectiveNodes: function () {
+return this.domApi.getEffectiveChildNodes();
+},
+_generateListenerInfo: function (listener, newNodes) {
+if (listener._avoidChangeCalculation) {
+return true;
+}
+var oldNodes = listener._nodes;
+var info = {
+target: this.node,
+addedNodes: [],
+removedNodes: []
+};
+var splices = Polymer.ArraySplice.calculateSplices(newNodes, oldNodes);
+for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
+for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
+info.removedNodes.push(n);
+}
+}
+for (i = 0, s; i < splices.length && (s = splices[i]); i++) {
+for (j = s.index; j < s.index + s.addedCount; j++) {
+info.addedNodes.push(newNodes[j]);
+}
+}
+listener._nodes = newNodes;
+if (info.addedNodes.length || info.removedNodes.length) {
+return info;
+}
+},
+_callListener: function (listener, info) {
+return listener.fn.call(this.node, info);
+},
+enableShadowAttributeTracking: function () {
+}
+};
+if (Settings.useShadow) {
+var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup;
+var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup;
+Polymer.Base.mixin(DomApi.EffectiveNodesObserver.prototype, {
+_setup: function () {
+if (!this._observer) {
+var self = this;
+this._mutationHandler = function (mxns) {
+if (mxns && mxns.length) {
+self._scheduleNotify();
+}
+};
+this._observer = new MutationObserver(this._mutationHandler);
+this._boundFlush = function () {
+self._flush();
+};
+Polymer.dom.addStaticFlush(this._boundFlush);
+this._observer.observe(this.node, { childList: true });
+}
+baseSetup.call(this);
+},
+_cleanup: function () {
+this._observer.disconnect();
+this._observer = null;
+this._mutationHandler = null;
+Polymer.dom.removeStaticFlush(this._boundFlush);
+baseCleanup.call(this);
+},
+_flush: function () {
+if (this._observer) {
+this._mutationHandler(this._observer.takeRecords());
+}
+},
+enableShadowAttributeTracking: function () {
+if (this._observer) {
+this._makeContentListenersAlwaysNotify();
+this._observer.disconnect();
+this._observer.observe(this.node, {
+childList: true,
+attributes: true,
+subtree: true
+});
+var root = this.domApi.getOwnerRoot();
+var host = root && root.host;
+if (host && Polymer.dom(host).observer) {
+Polymer.dom(host).observer.enableShadowAttributeTracking();
+}
+}
+},
+_makeContentListenersAlwaysNotify: function () {
+for (var i = 0, h; i < this._listeners.length; i++) {
+h = this._listeners[i];
+h._alwaysNotify = h._isContentListener;
+}
+}
+});
+}
+}());(function () {
+'use strict';
+var DomApi = Polymer.DomApi.ctor;
+var Settings = Polymer.Settings;
+DomApi.DistributedNodesObserver = function (domApi) {
+DomApi.EffectiveNodesObserver.call(this, domApi);
+};
+DomApi.DistributedNodesObserver.prototype = Object.create(DomApi.EffectiveNodesObserver.prototype);
+Polymer.Base.mixin(DomApi.DistributedNodesObserver.prototype, {
+_setup: function () {
+},
+_cleanup: function () {
+},
+_beforeCallListeners: function () {
+},
+_getEffectiveNodes: function () {
+return this.domApi.getDistributedNodes();
+}
+});
+if (Settings.useShadow) {
+Polymer.Base.mixin(DomApi.DistributedNodesObserver.prototype, {
+_setup: function () {
+if (!this._observer) {
+var root = this.domApi.getOwnerRoot();
+var host = root && root.host;
+if (host) {
+var self = this;
+this._observer = Polymer.dom(host).observeNodes(function () {
+self._scheduleNotify();
+});
+this._observer._isContentListener = true;
+if (this._hasAttrSelect()) {
+Polymer.dom(host).observer.enableShadowAttributeTracking();
+}
+}
+}
+},
+_hasAttrSelect: function () {
+var select = this.node.getAttribute('select');
+return select && select.match(/[[.]+/);
+},
+_cleanup: function () {
+var root = this.domApi.getOwnerRoot();
+var host = root && root.host;
+if (host) {
+Polymer.dom(host).unobserveNodes(this._observer);
+}
+this._observer = null;
+}
+});
+}
+}());(function () {
+var DomApi = Polymer.DomApi;
+var TreeApi = Polymer.TreeApi;
+Polymer.Base._addFeature({
+_prepShady: function () {
+this._useContent = this._useContent || Boolean(this._template);
+},
+_setupShady: function () {
+this.shadyRoot = null;
+if (!this.__domApi) {
+this.__domApi = null;
+}
+if (!this.__dom) {
+this.__dom = null;
+}
+if (!this._ownerShadyRoot) {
+this._ownerShadyRoot = undefined;
+}
+},
+_poolContent: function () {
+if (this._useContent) {
+TreeApi.Logical.saveChildNodes(this);
+}
+},
+_setupRoot: function () {
+if (this._useContent) {
+this._createLocalRoot();
+if (!this.dataHost) {
+upgradeLogicalChildren(TreeApi.Logical.getChildNodes(this));
+}
+}
+},
+_createLocalRoot: function () {
+this.shadyRoot = this.root;
+this.shadyRoot._distributionClean = false;
+this.shadyRoot._hasDistributed = false;
+this.shadyRoot._isShadyRoot = true;
+this.shadyRoot._dirtyRoots = [];
+var i$ = this.shadyRoot._insertionPoints = !this._notes || this._notes._hasContent ? this.shadyRoot.querySelectorAll('content') : [];
+TreeApi.Logical.saveChildNodes(this.shadyRoot);
+for (var i = 0, c; i < i$.length; i++) {
+c = i$[i];
+TreeApi.Logical.saveChildNodes(c);
+TreeApi.Logical.saveChildNodes(c.parentNode);
+}
+this.shadyRoot.host = this;
+},
+distributeContent: function (updateInsertionPoints) {
+if (this.shadyRoot) {
+this.shadyRoot._invalidInsertionPoints = this.shadyRoot._invalidInsertionPoints || updateInsertionPoints;
+var host = getTopDistributingHost(this);
+Polymer.dom(this)._lazyDistribute(host);
+}
+},
+_distributeContent: function () {
+if (this._useContent && !this.shadyRoot._distributionClean) {
+if (this.shadyRoot._invalidInsertionPoints) {
+Polymer.dom(this)._updateInsertionPoints(this);
+this.shadyRoot._invalidInsertionPoints = false;
+}
+this._beginDistribute();
+this._distributeDirtyRoots();
+this._finishDistribute();
+}
+},
+_beginDistribute: function () {
+if (this._useContent && DomApi.hasInsertionPoint(this.shadyRoot)) {
+this._resetDistribution();
+this._distributePool(this.shadyRoot, this._collectPool());
+}
+},
+_distributeDirtyRoots: function () {
+var c$ = this.shadyRoot._dirtyRoots;
+for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
+c._distributeContent();
+}
+this.shadyRoot._dirtyRoots = [];
+},
+_finishDistribute: function () {
+if (this._useContent) {
+this.shadyRoot._distributionClean = true;
+if (DomApi.hasInsertionPoint(this.shadyRoot)) {
+this._composeTree();
+notifyContentObservers(this.shadyRoot);
+} else {
+if (!this.shadyRoot._hasDistributed) {
+TreeApi.Composed.clearChildNodes(this);
+this.appendChild(this.shadyRoot);
+} else {
+var children = this._composeNode(this);
+this._updateChildNodes(this, children);
+}
+}
+if (!this.shadyRoot._hasDistributed) {
+notifyInitialDistribution(this);
+}
+this.shadyRoot._hasDistributed = true;
+}
+},
+elementMatches: function (selector, node) {
+node = node || this;
+return DomApi.matchesSelector.call(node, selector);
+},
+_resetDistribution: function () {
+var children = TreeApi.Logical.getChildNodes(this);
+for (var i = 0; i < children.length; i++) {
+var child = children[i];
+if (child._destinationInsertionPoints) {
+child._destinationInsertionPoints = undefined;
+}
+if (isInsertionPoint(child)) {
+clearDistributedDestinationInsertionPoints(child);
+}
+}
+var root = this.shadyRoot;
+var p$ = root._insertionPoints;
+for (var j = 0; j < p$.length; j++) {
+p$[j]._distributedNodes = [];
+}
+},
+_collectPool: function () {
+var pool = [];
+var children = TreeApi.Logical.getChildNodes(this);
+for (var i = 0; i < children.length; i++) {
+var child = children[i];
+if (isInsertionPoint(child)) {
+pool.push.apply(pool, child._distributedNodes);
+} else {
+pool.push(child);
+}
+}
+return pool;
+},
+_distributePool: function (node, pool) {
+var p$ = node._insertionPoints;
+for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
+this._distributeInsertionPoint(p, pool);
+maybeRedistributeParent(p, this);
+}
+},
+_distributeInsertionPoint: function (content, pool) {
+var anyDistributed = false;
+for (var i = 0, l = pool.length, node; i < l; i++) {
+node = pool[i];
+if (!node) {
+continue;
+}
+if (this._matchesContentSelect(node, content)) {
+distributeNodeInto(node, content);
+pool[i] = undefined;
+anyDistributed = true;
+}
+}
+if (!anyDistributed) {
+var children = TreeApi.Logical.getChildNodes(content);
+for (var j = 0; j < children.length; j++) {
+distributeNodeInto(children[j], content);
+}
+}
+},
+_composeTree: function () {
+this._updateChildNodes(this, this._composeNode(this));
+var p$ = this.shadyRoot._insertionPoints;
+for (var i = 0, l = p$.length, p, parent; i < l && (p = p$[i]); i++) {
+parent = TreeApi.Logical.getParentNode(p);
+if (!parent._useContent && parent !== this && parent !== this.shadyRoot) {
+this._updateChildNodes(parent, this._composeNode(parent));
+}
+}
+},
+_composeNode: function (node) {
+var children = [];
+var c$ = TreeApi.Logical.getChildNodes(node.shadyRoot || node);
+for (var i = 0; i < c$.length; i++) {
+var child = c$[i];
+if (isInsertionPoint(child)) {
+var distributedNodes = child._distributedNodes;
+for (var j = 0; j < distributedNodes.length; j++) {
+var distributedNode = distributedNodes[j];
+if (isFinalDestination(child, distributedNode)) {
+children.push(distributedNode);
+}
+}
+} else {
+children.push(child);
+}
+}
+return children;
+},
+_updateChildNodes: function (container, children) {
+var composed = TreeApi.Composed.getChildNodes(container);
+var splices = Polymer.ArraySplice.calculateSplices(children, composed);
+for (var i = 0, d = 0, s; i < splices.length && (s = splices[i]); i++) {
+for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
+if (TreeApi.Composed.getParentNode(n) === container) {
+TreeApi.Composed.removeChild(container, n);
+}
+composed.splice(s.index + d, 1);
+}
+d -= s.addedCount;
+}
+for (var i = 0, s, next; i < splices.length && (s = splices[i]); i++) {
+next = composed[s.index];
+for (j = s.index, n; j < s.index + s.addedCount; j++) {
+n = children[j];
+TreeApi.Composed.insertBefore(container, n, next);
+composed.splice(j, 0, n);
+}
+}
+},
+_matchesContentSelect: function (node, contentElement) {
+var select = contentElement.getAttribute('select');
+if (!select) {
+return true;
+}
+select = select.trim();
+if (!select) {
+return true;
+}
+if (!(node instanceof Element)) {
+return false;
+}
+var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/;
+if (!validSelectors.test(select)) {
+return false;
+}
+return this.elementMatches(select, node);
+},
+_elementAdd: function () {
+},
+_elementRemove: function () {
+}
+});
+var domHostDesc = {
+get: function () {
+var root = Polymer.dom(this).getOwnerRoot();
+return root && root.host;
+},
+configurable: true
+};
+Object.defineProperty(Polymer.Base, 'domHost', domHostDesc);
+Polymer.BaseDescriptors.domHost = domHostDesc;
+function distributeNodeInto(child, insertionPoint) {
+insertionPoint._distributedNodes.push(child);
+var points = child._destinationInsertionPoints;
+if (!points) {
+child._destinationInsertionPoints = [insertionPoint];
+} else {
+points.push(insertionPoint);
+}
+}
+function clearDistributedDestinationInsertionPoints(content) {
+var e$ = content._distributedNodes;
+if (e$) {
+for (var i = 0; i < e$.length; i++) {
+var d = e$[i]._destinationInsertionPoints;
+if (d) {
+d.splice(d.indexOf(content) + 1, d.length);
+}
+}
+}
+}
+function maybeRedistributeParent(content, host) {
+var parent = TreeApi.Logical.getParentNode(content);
+if (parent && parent.shadyRoot && DomApi.hasInsertionPoint(parent.shadyRoot) && parent.shadyRoot._distributionClean) {
+parent.shadyRoot._distributionClean = false;
+host.shadyRoot._dirtyRoots.push(parent);
+}
+}
+function isFinalDestination(insertionPoint, node) {
+var points = node._destinationInsertionPoints;
+return points && points[points.length - 1] === insertionPoint;
+}
+function isInsertionPoint(node) {
+return node.localName == 'content';
+}
+function getTopDistributingHost(host) {
+while (host && hostNeedsRedistribution(host)) {
+host = host.domHost;
+}
+return host;
+}
+function hostNeedsRedistribution(host) {
+var c$ = TreeApi.Logical.getChildNodes(host);
+for (var i = 0, c; i < c$.length; i++) {
+c = c$[i];
+if (c.localName && c.localName === 'content') {
+return host.domHost;
+}
+}
+}
+function notifyContentObservers(root) {
+for (var i = 0, c; i < root._insertionPoints.length; i++) {
+c = root._insertionPoints[i];
+if (DomApi.hasApi(c)) {
+Polymer.dom(c).notifyObserver();
+}
+}
+}
+function notifyInitialDistribution(host) {
+if (DomApi.hasApi(host)) {
+Polymer.dom(host).notifyObserver();
+}
+}
+var needsUpgrade = window.CustomElements && !CustomElements.useNative;
+function upgradeLogicalChildren(children) {
+if (needsUpgrade && children) {
+for (var i = 0; i < children.length; i++) {
+CustomElements.upgrade(children[i]);
+}
+}
+}
+}());if (Polymer.Settings.useShadow) {
+Polymer.Base._addFeature({
+_poolContent: function () {
+},
+_beginDistribute: function () {
+},
+distributeContent: function () {
+},
+_distributeContent: function () {
+},
+_finishDistribute: function () {
+},
+_createLocalRoot: function () {
+this.createShadowRoot();
+this.shadowRoot.appendChild(this.root);
+this.root = this.shadowRoot;
+}
+});
+}Polymer.Async = {
+_currVal: 0,
+_lastVal: 0,
+_callbacks: [],
+_twiddleContent: 0,
+_twiddle: document.createTextNode(''),
+run: function (callback, waitTime) {
+if (waitTime > 0) {
+return ~setTimeout(callback, waitTime);
+} else {
+this._twiddle.textContent = this._twiddleContent++;
+this._callbacks.push(callback);
+return this._currVal++;
+}
+},
+cancel: function (handle) {
+if (handle < 0) {
+clearTimeout(~handle);
+} else {
+var idx = handle - this._lastVal;
+if (idx >= 0) {
+if (!this._callbacks[idx]) {
+throw 'invalid async handle: ' + handle;
+}
+this._callbacks[idx] = null;
+}
+}
+},
+_atEndOfMicrotask: function () {
+var len = this._callbacks.length;
+for (var i = 0; i < len; i++) {
+var cb = this._callbacks[i];
+if (cb) {
+try {
+cb();
+} catch (e) {
+i++;
+this._callbacks.splice(0, i);
+this._lastVal += i;
+this._twiddle.textContent = this._twiddleContent++;
+throw e;
+}
+}
+}
+this._callbacks.splice(0, len);
+this._lastVal += len;
+}
+};
+new window.MutationObserver(function () {
+Polymer.Async._atEndOfMicrotask();
+}).observe(Polymer.Async._twiddle, { characterData: true });Polymer.Debounce = function () {
+var Async = Polymer.Async;
+var Debouncer = function (context) {
+this.context = context;
+var self = this;
+this.boundComplete = function () {
+self.complete();
+};
+};
+Debouncer.prototype = {
+go: function (callback, wait) {
+var h;
+this.finish = function () {
+Async.cancel(h);
+};
+h = Async.run(this.boundComplete, wait);
+this.callback = callback;
+},
+stop: function () {
+if (this.finish) {
+this.finish();
+this.finish = null;
+this.callback = null;
+}
+},
+complete: function () {
+if (this.finish) {
+var callback = this.callback;
+this.stop();
+callback.call(this.context);
+}
+}
+};
+function debounce(debouncer, callback, wait) {
+if (debouncer) {
+debouncer.stop();
+} else {
+debouncer = new Debouncer(this);
+}
+debouncer.go(callback, wait);
+return debouncer;
+}
+return debounce;
+}();Polymer.Base._addFeature({
+_setupDebouncers: function () {
+this._debouncers = {};
+},
+debounce: function (jobName, callback, wait) {
+return this._debouncers[jobName] = Polymer.Debounce.call(this, this._debouncers[jobName], callback, wait);
+},
+isDebouncerActive: function (jobName) {
+var debouncer = this._debouncers[jobName];
+return !!(debouncer && debouncer.finish);
+},
+flushDebouncer: function (jobName) {
+var debouncer = this._debouncers[jobName];
+if (debouncer) {
+debouncer.complete();
+}
+},
+cancelDebouncer: function (jobName) {
+var debouncer = this._debouncers[jobName];
+if (debouncer) {
+debouncer.stop();
+}
+}
+});Polymer.DomModule = document.createElement('dom-module');
+Polymer.Base._addFeature({
+_registerFeatures: function () {
+this._prepIs();
+this._prepBehaviors();
+this._prepConstructor();
+this._prepTemplate();
+this._prepShady();
+this._prepPropertyInfo();
+},
+_prepBehavior: function (b) {
+this._addHostAttributes(b.hostAttributes);
+},
+_initFeatures: function () {
+this._registerHost();
+if (this._template) {
+this._poolContent();
+this._beginHosting();
+this._stampTemplate();
+this._endHosting();
+}
+this._marshalHostAttributes();
+this._setupDebouncers();
+this._marshalBehaviors();
+this._tryReady();
+},
+_marshalBehavior: function (b) {
+}
+});</script>
+
+
+
+
+
+
diff --git a/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer.html b/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer.html
new file mode 100644
index 00000000000..c7c8170ad0c
--- /dev/null
+++ b/chromium/third_party/catapult/third_party/polymer/components/polymer/polymer.html
@@ -0,0 +1,5555 @@
+<!--
+@license
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+--><!--
+@license
+Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+Code distributed by Google as part of the polymer project is also
+subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+--><link rel="import" href="polymer-mini.html"><script>(function () {
+Polymer.nar = [];
+var disableUpgradeEnabled = Polymer.Settings.disableUpgradeEnabled;
+Polymer.Annotations = {
+parseAnnotations: function (template, stripWhiteSpace) {
+var list = [];
+var content = template._content || template.content;
+this._parseNodeAnnotations(content, list, stripWhiteSpace || template.hasAttribute('strip-whitespace'));
+return list;
+},
+_parseNodeAnnotations: function (node, list, stripWhiteSpace) {
+return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, list) : this._parseElementAnnotations(node, list, stripWhiteSpace);
+},
+_bindingRegex: function () {
+var IDENT = '(?:' + '[a-zA-Z_$][\\w.:$\\-*]*' + ')';
+var NUMBER = '(?:' + '[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?' + ')';
+var SQUOTE_STRING = '(?:' + '\'(?:[^\'\\\\]|\\\\.)*\'' + ')';
+var DQUOTE_STRING = '(?:' + '"(?:[^"\\\\]|\\\\.)*"' + ')';
+var STRING = '(?:' + SQUOTE_STRING + '|' + DQUOTE_STRING + ')';
+var ARGUMENT = '(?:' + IDENT + '|' + NUMBER + '|' + STRING + '\\s*' + ')';
+var ARGUMENTS = '(?:' + ARGUMENT + '(?:,\\s*' + ARGUMENT + ')*' + ')';
+var ARGUMENT_LIST = '(?:' + '\\(\\s*' + '(?:' + ARGUMENTS + '?' + ')' + '\\)\\s*' + ')';
+var BINDING = '(' + IDENT + '\\s*' + ARGUMENT_LIST + '?' + ')';
+var OPEN_BRACKET = '(\\[\\[|{{)' + '\\s*';
+var CLOSE_BRACKET = '(?:]]|}})';
+var NEGATE = '(?:(!)\\s*)?';
+var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET;
+return new RegExp(EXPRESSION, 'g');
+}(),
+_parseBindings: function (text) {
+var re = this._bindingRegex;
+var parts = [];
+var lastIndex = 0;
+var m;
+while ((m = re.exec(text)) !== null) {
+if (m.index > lastIndex) {
+parts.push({ literal: text.slice(lastIndex, m.index) });
+}
+var mode = m[1][0];
+var negate = Boolean(m[2]);
+var value = m[3].trim();
+var customEvent, notifyEvent, colon;
+if (mode == '{' && (colon = value.indexOf('::')) > 0) {
+notifyEvent = value.substring(colon + 2);
+value = value.substring(0, colon);
+customEvent = true;
+}
+parts.push({
+compoundIndex: parts.length,
+value: value,
+mode: mode,
+negate: negate,
+event: notifyEvent,
+customEvent: customEvent
+});
+lastIndex = re.lastIndex;
+}
+if (lastIndex && lastIndex < text.length) {
+var literal = text.substring(lastIndex);
+if (literal) {
+parts.push({ literal: literal });
+}
+}
+if (parts.length) {
+return parts;
+}
+},
+_literalFromParts: function (parts) {
+var s = '';
+for (var i = 0; i < parts.length; i++) {
+var literal = parts[i].literal;
+s += literal || '';
+}
+return s;
+},
+_parseTextNodeAnnotation: function (node, list) {
+var parts = this._parseBindings(node.textContent);
+if (parts) {
+node.textContent = this._literalFromParts(parts) || ' ';
+var annote = {
+bindings: [{
+kind: 'text',
+name: 'textContent',
+parts: parts,
+isCompound: parts.length !== 1
+}]
+};
+list.push(annote);
+return annote;
+}
+},
+_parseElementAnnotations: function (element, list, stripWhiteSpace) {
+var annote = {
+bindings: [],
+events: []
+};
+if (element.localName === 'content') {
+list._hasContent = true;
+}
+this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace);
+if (element.attributes) {
+this._parseNodeAttributeAnnotations(element, annote, list);
+if (this.prepElement) {
+this.prepElement(element);
+}
+}
+if (annote.bindings.length || annote.events.length || annote.id) {
+list.push(annote);
+}
+return annote;
+},
+_parseChildNodesAnnotations: function (root, annote, list, stripWhiteSpace) {
+if (root.firstChild) {
+var node = root.firstChild;
+var i = 0;
+while (node) {
+var next = node.nextSibling;
+if (node.localName === 'template' && !node.hasAttribute('preserve-content')) {
+this._parseTemplate(node, i, list, annote, stripWhiteSpace);
+}
+if (node.localName == 'slot') {
+node = this._replaceSlotWithContent(node);
+}
+if (node.nodeType === Node.TEXT_NODE) {
+var n = next;
+while (n && n.nodeType === Node.TEXT_NODE) {
+node.textContent += n.textContent;
+next = n.nextSibling;
+root.removeChild(n);
+n = next;
+}
+if (stripWhiteSpace && !node.textContent.trim()) {
+root.removeChild(node);
+i--;
+}
+}
+if (node.parentNode) {
+var childAnnotation = this._parseNodeAnnotations(node, list, stripWhiteSpace);
+if (childAnnotation) {
+childAnnotation.parent = annote;
+childAnnotation.index = i;
+}
+}
+node = next;
+i++;
+}
+}
+},
+_replaceSlotWithContent: function (slot) {
+var content = slot.ownerDocument.createElement('content');
+while (slot.firstChild) {
+content.appendChild(slot.firstChild);
+}
+var attrs = slot.attributes;
+for (var i = 0; i < attrs.length; i++) {
+var attr = attrs[i];
+content.setAttribute(attr.name, attr.value);
+}
+var name = slot.getAttribute('name');
+if (name) {
+content.setAttribute('select', '[slot=\'' + name + '\']');
+}
+slot.parentNode.replaceChild(content, slot);
+return content;
+},
+_parseTemplate: function (node, index, list, parent, stripWhiteSpace) {
+var content = document.createDocumentFragment();
+content._notes = this.parseAnnotations(node, stripWhiteSpace);
+content.appendChild(node.content);
+list.push({
+bindings: Polymer.nar,
+events: Polymer.nar,
+templateContent: content,
+parent: parent,
+index: index
+});
+},
+_parseNodeAttributeAnnotations: function (node, annotation) {
+var attrs = Array.prototype.slice.call(node.attributes);
+for (var i = attrs.length - 1, a; a = attrs[i]; i--) {
+var n = a.name;
+var v = a.value;
+var b;
+if (n.slice(0, 3) === 'on-') {
+node.removeAttribute(n);
+annotation.events.push({
+name: n.slice(3),
+value: v
+});
+} else if (b = this._parseNodeAttributeAnnotation(node, n, v)) {
+annotation.bindings.push(b);
+} else if (n === 'id') {
+annotation.id = v;
+}
+}
+},
+_parseNodeAttributeAnnotation: function (node, name, value) {
+var parts = this._parseBindings(value);
+if (parts) {
+var origName = name;
+var kind = 'property';
+if (name[name.length - 1] == '$') {
+name = name.slice(0, -1);
+kind = 'attribute';
+}
+var literal = this._literalFromParts(parts);
+if (literal && kind == 'attribute') {
+node.setAttribute(name, literal);
+}
+if (node.localName === 'input' && origName === 'value') {
+node.setAttribute(origName, '');
+}
+if (disableUpgradeEnabled && origName === 'disable-upgrade$') {
+node.setAttribute(name, '');
+}
+node.removeAttribute(origName);
+var propertyName = Polymer.CaseMap.dashToCamelCase(name);
+if (kind === 'property') {
+name = propertyName;
+}
+return {
+kind: kind,
+name: name,
+propertyName: propertyName,
+parts: parts,
+literal: literal,
+isCompound: parts.length !== 1
+};
+}
+},
+findAnnotatedNode: function (root, annote) {
+var parent = annote.parent && Polymer.Annotations.findAnnotatedNode(root, annote.parent);
+if (parent) {
+for (var n = parent.firstChild, i = 0; n; n = n.nextSibling) {
+if (annote.index === i++) {
+return n;
+}
+}
+} else {
+return root;
+}
+}
+};
+}());Polymer.Path = {
+root: function (path) {
+var dotIndex = path.indexOf('.');
+if (dotIndex === -1) {
+return path;
+}
+return path.slice(0, dotIndex);
+},
+isDeep: function (path) {
+return path.indexOf('.') !== -1;
+},
+isAncestor: function (base, path) {
+return base.indexOf(path + '.') === 0;
+},
+isDescendant: function (base, path) {
+return path.indexOf(base + '.') === 0;
+},
+translate: function (base, newBase, path) {
+return newBase + path.slice(base.length);
+},
+matches: function (base, wildcard, path) {
+return base === path || this.isAncestor(base, path) || Boolean(wildcard) && this.isDescendant(base, path);
+}
+};Polymer.Base._addFeature({
+_prepAnnotations: function () {
+if (!this._template) {
+this._notes = [];
+} else {
+var self = this;
+Polymer.Annotations.prepElement = function (element) {
+self._prepElement(element);
+};
+if (this._template._content && this._template._content._notes) {
+this._notes = this._template._content._notes;
+} else {
+this._notes = Polymer.Annotations.parseAnnotations(this._template);
+this._processAnnotations(this._notes);
+}
+Polymer.Annotations.prepElement = null;
+}
+},
+_processAnnotations: function (notes) {
+for (var i = 0; i < notes.length; i++) {
+var note = notes[i];
+for (var j = 0; j < note.bindings.length; j++) {
+var b = note.bindings[j];
+for (var k = 0; k < b.parts.length; k++) {
+var p = b.parts[k];
+if (!p.literal) {
+var signature = this._parseMethod(p.value);
+if (signature) {
+p.signature = signature;
+} else {
+p.model = Polymer.Path.root(p.value);
+}
+}
+}
+}
+if (note.templateContent) {
+this._processAnnotations(note.templateContent._notes);
+var pp = note.templateContent._parentProps = this._discoverTemplateParentProps(note.templateContent._notes);
+var bindings = [];
+for (var prop in pp) {
+var name = '_parent_' + prop;
+bindings.push({
+index: note.index,
+kind: 'property',
+name: name,
+propertyName: name,
+parts: [{
+mode: '{',
+model: prop,
+value: prop
+}]
+});
+}
+note.bindings = note.bindings.concat(bindings);
+}
+}
+},
+_discoverTemplateParentProps: function (notes) {
+var pp = {};
+for (var i = 0, n; i < notes.length && (n = notes[i]); i++) {
+for (var j = 0, b$ = n.bindings, b; j < b$.length && (b = b$[j]); j++) {
+for (var k = 0, p$ = b.parts, p; k < p$.length && (p = p$[k]); k++) {
+if (p.signature) {
+var args = p.signature.args;
+for (var kk = 0; kk < args.length; kk++) {
+var model = args[kk].model;
+if (model) {
+pp[model] = true;
+}
+}
+if (p.signature.dynamicFn) {
+pp[p.signature.method] = true;
+}
+} else {
+if (p.model) {
+pp[p.model] = true;
+}
+}
+}
+}
+if (n.templateContent) {
+var tpp = n.templateContent._parentProps;
+Polymer.Base.mixin(pp, tpp);
+}
+}
+return pp;
+},
+_prepElement: function (element) {
+Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument);
+},
+_findAnnotatedNode: Polymer.Annotations.findAnnotatedNode,
+_marshalAnnotationReferences: function () {
+if (this._template) {
+this._marshalIdNodes();
+this._marshalAnnotatedNodes();
+this._marshalAnnotatedListeners();
+}
+},
+_configureAnnotationReferences: function () {
+var notes = this._notes;
+var nodes = this._nodes;
+for (var i = 0; i < notes.length; i++) {
+var note = notes[i];
+var node = nodes[i];
+this._configureTemplateContent(note, node);
+this._configureCompoundBindings(note, node);
+}
+},
+_configureTemplateContent: function (note, node) {
+if (note.templateContent) {
+node._content = note.templateContent;
+}
+},
+_configureCompoundBindings: function (note, node) {
+var bindings = note.bindings;
+for (var i = 0; i < bindings.length; i++) {
+var binding = bindings[i];
+if (binding.isCompound) {
+var storage = node.__compoundStorage__ || (node.__compoundStorage__ = {});
+var parts = binding.parts;
+var literals = new Array(parts.length);
+for (var j = 0; j < parts.length; j++) {
+literals[j] = parts[j].literal;
+}
+var name = binding.name;
+storage[name] = literals;
+if (binding.literal && binding.kind == 'property') {
+if (node._configValue) {
+node._configValue(name, binding.literal);
+} else {
+node[name] = binding.literal;
+}
+}
+}
+}
+},
+_marshalIdNodes: function () {
+this.$ = {};
+for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) {
+if (a.id) {
+this.$[a.id] = this._findAnnotatedNode(this.root, a);
+}
+}
+},
+_marshalAnnotatedNodes: function () {
+if (this._notes && this._notes.length) {
+var r = new Array(this._notes.length);
+for (var i = 0; i < this._notes.length; i++) {
+r[i] = this._findAnnotatedNode(this.root, this._notes[i]);
+}
+this._nodes = r;
+}
+},
+_marshalAnnotatedListeners: function () {
+for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) {
+if (a.events && a.events.length) {
+var node = this._findAnnotatedNode(this.root, a);
+for (var j = 0, e$ = a.events, e; j < e$.length && (e = e$[j]); j++) {
+this.listen(node, e.name, e.value);
+}
+}
+}
+}
+});Polymer.Base._addFeature({
+listeners: {},
+_listenListeners: function (listeners) {
+var node, name, eventName;
+for (eventName in listeners) {
+if (eventName.indexOf('.') < 0) {
+node = this;
+name = eventName;
+} else {
+name = eventName.split('.');
+node = this.$[name[0]];
+name = name[1];
+}
+this.listen(node, name, listeners[eventName]);
+}
+},
+listen: function (node, eventName, methodName) {
+var handler = this._recallEventHandler(this, eventName, node, methodName);
+if (!handler) {
+handler = this._createEventHandler(node, eventName, methodName);
+}
+if (handler._listening) {
+return;
+}
+this._listen(node, eventName, handler);
+handler._listening = true;
+},
+_boundListenerKey: function (eventName, methodName) {
+return eventName + ':' + methodName;
+},
+_recordEventHandler: function (host, eventName, target, methodName, handler) {
+var hbl = host.__boundListeners;
+if (!hbl) {
+hbl = host.__boundListeners = new WeakMap();
+}
+var bl = hbl.get(target);
+if (!bl) {
+bl = {};
+if (!Polymer.Settings.isIE || target != window) {
+hbl.set(target, bl);
+}
+}
+var key = this._boundListenerKey(eventName, methodName);
+bl[key] = handler;
+},
+_recallEventHandler: function (host, eventName, target, methodName) {
+var hbl = host.__boundListeners;
+if (!hbl) {
+return;
+}
+var bl = hbl.get(target);
+if (!bl) {
+return;
+}
+var key = this._boundListenerKey(eventName, methodName);
+return bl[key];
+},
+_createEventHandler: function (node, eventName, methodName) {
+var host = this;
+var handler = function (e) {
+if (host[methodName]) {
+host[methodName](e, e.detail);
+} else {
+host._warn(host._logf('_createEventHandler', 'listener method `' + methodName + '` not defined'));
+}
+};
+handler._listening = false;
+this._recordEventHandler(host, eventName, node, methodName, handler);
+return handler;
+},
+unlisten: function (node, eventName, methodName) {
+var handler = this._recallEventHandler(this, eventName, node, methodName);
+if (handler) {
+this._unlisten(node, eventName, handler);
+handler._listening = false;
+}
+},
+_listen: function (node, eventName, handler) {
+node.addEventListener(eventName, handler);
+},
+_unlisten: function (node, eventName, handler) {
+node.removeEventListener(eventName, handler);
+}
+});(function () {
+'use strict';
+var wrap = Polymer.DomApi.wrap;
+var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string';
+var GESTURE_KEY = '__polymerGestures';
+var HANDLED_OBJ = '__polymerGesturesHandled';
+var TOUCH_ACTION = '__polymerGesturesTouchAction';
+var TAP_DISTANCE = 25;
+var TRACK_DISTANCE = 5;
+var TRACK_LENGTH = 2;
+var MOUSE_TIMEOUT = 2500;
+var MOUSE_EVENTS = [
+'mousedown',
+'mousemove',
+'mouseup',
+'click'
+];
+var MOUSE_WHICH_TO_BUTTONS = [
+0,
+1,
+4,
+2
+];
+var MOUSE_HAS_BUTTONS = function () {
+try {
+return new MouseEvent('test', { buttons: 1 }).buttons === 1;
+} catch (e) {
+return false;
+}
+}();
+function isMouseEvent(name) {
+return MOUSE_EVENTS.indexOf(name) > -1;
+}
+var SUPPORTS_PASSIVE = false;
+(function () {
+try {
+var opts = Object.defineProperty({}, 'passive', {
+get: function () {
+SUPPORTS_PASSIVE = true;
+}
+});
+window.addEventListener('test', null, opts);
+window.removeEventListener('test', null, opts);
+} catch (e) {
+}
+}());
+function PASSIVE_TOUCH(eventName) {
+if (isMouseEvent(eventName) || eventName === 'touchend') {
+return;
+}
+if (HAS_NATIVE_TA && SUPPORTS_PASSIVE && Polymer.Settings.passiveTouchGestures) {
+return { passive: true };
+}
+}
+var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);
+var mouseCanceller = function (mouseEvent) {
+var sc = mouseEvent.sourceCapabilities;
+if (sc && !sc.firesTouchEvents) {
+return;
+}
+mouseEvent[HANDLED_OBJ] = { skip: true };
+if (mouseEvent.type === 'click') {
+var path = Polymer.dom(mouseEvent).path;
+if (path) {
+for (var i = 0; i < path.length; i++) {
+if (path[i] === POINTERSTATE.mouse.target) {
+return;
+}
+}
+}
+mouseEvent.preventDefault();
+mouseEvent.stopPropagation();
+}
+};
+function setupTeardownMouseCanceller(setup) {
+var events = IS_TOUCH_ONLY ? ['click'] : MOUSE_EVENTS;
+for (var i = 0, en; i < events.length; i++) {
+en = events[i];
+if (setup) {
+document.addEventListener(en, mouseCanceller, true);
+} else {
+document.removeEventListener(en, mouseCanceller, true);
+}
+}
+}
+function ignoreMouse(ev) {
+if (!POINTERSTATE.mouse.mouseIgnoreJob) {
+setupTeardownMouseCanceller(true);
+}
+var unset = function () {
+setupTeardownMouseCanceller();
+POINTERSTATE.mouse.target = null;
+POINTERSTATE.mouse.mouseIgnoreJob = null;
+};
+POINTERSTATE.mouse.target = Polymer.dom(ev).rootTarget;
+POINTERSTATE.mouse.mouseIgnoreJob = Polymer.Debounce(POINTERSTATE.mouse.mouseIgnoreJob, unset, MOUSE_TIMEOUT);
+}
+function hasLeftMouseButton(ev) {
+var type = ev.type;
+if (!isMouseEvent(type)) {
+return false;
+}
+if (type === 'mousemove') {
+var buttons = ev.buttons === undefined ? 1 : ev.buttons;
+if (ev instanceof window.MouseEvent && !MOUSE_HAS_BUTTONS) {
+buttons = MOUSE_WHICH_TO_BUTTONS[ev.which] || 0;
+}
+return Boolean(buttons & 1);
+} else {
+var button = ev.button === undefined ? 0 : ev.button;
+return button === 0;
+}
+}
+function isSyntheticClick(ev) {
+if (ev.type === 'click') {
+if (ev.detail === 0) {
+return true;
+}
+var t = Gestures.findOriginalTarget(ev);
+var bcr = t.getBoundingClientRect();
+var x = ev.pageX, y = ev.pageY;
+return !(x >= bcr.left && x <= bcr.right && (y >= bcr.top && y <= bcr.bottom));
+}
+return false;
+}
+var POINTERSTATE = {
+mouse: {
+target: null,
+mouseIgnoreJob: null
+},
+touch: {
+x: 0,
+y: 0,
+id: -1,
+scrollDecided: false
+}
+};
+function firstTouchAction(ev) {
+var path = Polymer.dom(ev).path;
+var ta = 'auto';
+for (var i = 0, n; i < path.length; i++) {
+n = path[i];
+if (n[TOUCH_ACTION]) {
+ta = n[TOUCH_ACTION];
+break;
+}
+}
+return ta;
+}
+function trackDocument(stateObj, movefn, upfn) {
+stateObj.movefn = movefn;
+stateObj.upfn = upfn;
+document.addEventListener('mousemove', movefn);
+document.addEventListener('mouseup', upfn);
+}
+function untrackDocument(stateObj) {
+document.removeEventListener('mousemove', stateObj.movefn);
+document.removeEventListener('mouseup', stateObj.upfn);
+stateObj.movefn = null;
+stateObj.upfn = null;
+}
+document.addEventListener('touchend', ignoreMouse, SUPPORTS_PASSIVE ? { passive: true } : false);
+var Gestures = {
+gestures: {},
+recognizers: [],
+deepTargetFind: function (x, y) {
+var node = document.elementFromPoint(x, y);
+var next = node;
+while (next && next.shadowRoot) {
+next = next.shadowRoot.elementFromPoint(x, y);
+if (next) {
+node = next;
+}
+}
+return node;
+},
+findOriginalTarget: function (ev) {
+if (ev.path) {
+return ev.path[0];
+}
+return ev.target;
+},
+handleNative: function (ev) {
+var handled;
+var type = ev.type;
+var node = wrap(ev.currentTarget);
+var gobj = node[GESTURE_KEY];
+if (!gobj) {
+return;
+}
+var gs = gobj[type];
+if (!gs) {
+return;
+}
+if (!ev[HANDLED_OBJ]) {
+ev[HANDLED_OBJ] = {};
+if (type.slice(0, 5) === 'touch') {
+var t = ev.changedTouches[0];
+if (type === 'touchstart') {
+if (ev.touches.length === 1) {
+POINTERSTATE.touch.id = t.identifier;
+}
+}
+if (POINTERSTATE.touch.id !== t.identifier) {
+return;
+}
+if (!HAS_NATIVE_TA) {
+if (type === 'touchstart' || type === 'touchmove') {
+Gestures.handleTouchAction(ev);
+}
+}
+}
+}
+handled = ev[HANDLED_OBJ];
+if (handled.skip) {
+return;
+}
+var recognizers = Gestures.recognizers;
+for (var i = 0, r; i < recognizers.length; i++) {
+r = recognizers[i];
+if (gs[r.name] && !handled[r.name]) {
+if (r.flow && r.flow.start.indexOf(ev.type) > -1 && r.reset) {
+r.reset();
+}
+}
+}
+for (i = 0, r; i < recognizers.length; i++) {
+r = recognizers[i];
+if (gs[r.name] && !handled[r.name]) {
+handled[r.name] = true;
+r[type](ev);
+}
+}
+},
+handleTouchAction: function (ev) {
+var t = ev.changedTouches[0];
+var type = ev.type;
+if (type === 'touchstart') {
+POINTERSTATE.touch.x = t.clientX;
+POINTERSTATE.touch.y = t.clientY;
+POINTERSTATE.touch.scrollDecided = false;
+} else if (type === 'touchmove') {
+if (POINTERSTATE.touch.scrollDecided) {
+return;
+}
+POINTERSTATE.touch.scrollDecided = true;
+var ta = firstTouchAction(ev);
+var prevent = false;
+var dx = Math.abs(POINTERSTATE.touch.x - t.clientX);
+var dy = Math.abs(POINTERSTATE.touch.y - t.clientY);
+if (!ev.cancelable) {
+} else if (ta === 'none') {
+prevent = true;
+} else if (ta === 'pan-x') {
+prevent = dy > dx;
+} else if (ta === 'pan-y') {
+prevent = dx > dy;
+}
+if (prevent) {
+ev.preventDefault();
+} else {
+Gestures.prevent('track');
+}
+}
+},
+add: function (node, evType, handler) {
+node = wrap(node);
+var recognizer = this.gestures[evType];
+var deps = recognizer.deps;
+var name = recognizer.name;
+var gobj = node[GESTURE_KEY];
+if (!gobj) {
+node[GESTURE_KEY] = gobj = {};
+}
+for (var i = 0, dep, gd; i < deps.length; i++) {
+dep = deps[i];
+if (IS_TOUCH_ONLY && isMouseEvent(dep) && dep !== 'click') {
+continue;
+}
+gd = gobj[dep];
+if (!gd) {
+gobj[dep] = gd = { _count: 0 };
+}
+if (gd._count === 0) {
+node.addEventListener(dep, this.handleNative, PASSIVE_TOUCH(dep));
+}
+gd[name] = (gd[name] || 0) + 1;
+gd._count = (gd._count || 0) + 1;
+}
+node.addEventListener(evType, handler);
+if (recognizer.touchAction) {
+this.setTouchAction(node, recognizer.touchAction);
+}
+},
+remove: function (node, evType, handler) {
+node = wrap(node);
+var recognizer = this.gestures[evType];
+var deps = recognizer.deps;
+var name = recognizer.name;
+var gobj = node[GESTURE_KEY];
+if (gobj) {
+for (var i = 0, dep, gd; i < deps.length; i++) {
+dep = deps[i];
+gd = gobj[dep];
+if (gd && gd[name]) {
+gd[name] = (gd[name] || 1) - 1;
+gd._count = (gd._count || 1) - 1;
+if (gd._count === 0) {
+node.removeEventListener(dep, this.handleNative, PASSIVE_TOUCH(dep));
+}
+}
+}
+}
+node.removeEventListener(evType, handler);
+},
+register: function (recog) {
+this.recognizers.push(recog);
+for (var i = 0; i < recog.emits.length; i++) {
+this.gestures[recog.emits[i]] = recog;
+}
+},
+findRecognizerByEvent: function (evName) {
+for (var i = 0, r; i < this.recognizers.length; i++) {
+r = this.recognizers[i];
+for (var j = 0, n; j < r.emits.length; j++) {
+n = r.emits[j];
+if (n === evName) {
+return r;
+}
+}
+}
+return null;
+},
+setTouchAction: function (node, value) {
+if (HAS_NATIVE_TA) {
+node.style.touchAction = value;
+}
+node[TOUCH_ACTION] = value;
+},
+fire: function (target, type, detail) {
+var ev = Polymer.Base.fire(type, detail, {
+node: target,
+bubbles: true,
+cancelable: true
+});
+if (ev.defaultPrevented) {
+var preventer = detail.preventer || detail.sourceEvent;
+if (preventer && preventer.preventDefault) {
+preventer.preventDefault();
+}
+}
+},
+prevent: function (evName) {
+var recognizer = this.findRecognizerByEvent(evName);
+if (recognizer.info) {
+recognizer.info.prevent = true;
+}
+},
+resetMouseCanceller: function () {
+if (POINTERSTATE.mouse.mouseIgnoreJob) {
+POINTERSTATE.mouse.mouseIgnoreJob.complete();
+}
+}
+};
+Gestures.register({
+name: 'downup',
+deps: [
+'mousedown',
+'touchstart',
+'touchend'
+],
+flow: {
+start: [
+'mousedown',
+'touchstart'
+],
+end: [
+'mouseup',
+'touchend'
+]
+},
+emits: [
+'down',
+'up'
+],
+info: {
+movefn: null,
+upfn: null
+},
+reset: function () {
+untrackDocument(this.info);
+},
+mousedown: function (e) {
+if (!hasLeftMouseButton(e)) {
+return;
+}
+var t = Gestures.findOriginalTarget(e);
+var self = this;
+var movefn = function movefn(e) {
+if (!hasLeftMouseButton(e)) {
+self.fire('up', t, e);
+untrackDocument(self.info);
+}
+};
+var upfn = function upfn(e) {
+if (hasLeftMouseButton(e)) {
+self.fire('up', t, e);
+}
+untrackDocument(self.info);
+};
+trackDocument(this.info, movefn, upfn);
+this.fire('down', t, e);
+},
+touchstart: function (e) {
+this.fire('down', Gestures.findOriginalTarget(e), e.changedTouches[0], e);
+},
+touchend: function (e) {
+this.fire('up', Gestures.findOriginalTarget(e), e.changedTouches[0], e);
+},
+fire: function (type, target, event, preventer) {
+Gestures.fire(target, type, {
+x: event.clientX,
+y: event.clientY,
+sourceEvent: event,
+preventer: preventer,
+prevent: function (e) {
+return Gestures.prevent(e);
+}
+});
+}
+});
+Gestures.register({
+name: 'track',
+touchAction: 'none',
+deps: [
+'mousedown',
+'touchstart',
+'touchmove',
+'touchend'
+],
+flow: {
+start: [
+'mousedown',
+'touchstart'
+],
+end: [
+'mouseup',
+'touchend'
+]
+},
+emits: ['track'],
+info: {
+x: 0,
+y: 0,
+state: 'start',
+started: false,
+moves: [],
+addMove: function (move) {
+if (this.moves.length > TRACK_LENGTH) {
+this.moves.shift();
+}
+this.moves.push(move);
+},
+movefn: null,
+upfn: null,
+prevent: false
+},
+reset: function () {
+this.info.state = 'start';
+this.info.started = false;
+this.info.moves = [];
+this.info.x = 0;
+this.info.y = 0;
+this.info.prevent = false;
+untrackDocument(this.info);
+},
+hasMovedEnough: function (x, y) {
+if (this.info.prevent) {
+return false;
+}
+if (this.info.started) {
+return true;
+}
+var dx = Math.abs(this.info.x - x);
+var dy = Math.abs(this.info.y - y);
+return dx >= TRACK_DISTANCE || dy >= TRACK_DISTANCE;
+},
+mousedown: function (e) {
+if (!hasLeftMouseButton(e)) {
+return;
+}
+var t = Gestures.findOriginalTarget(e);
+var self = this;
+var movefn = function movefn(e) {
+var x = e.clientX, y = e.clientY;
+if (self.hasMovedEnough(x, y)) {
+self.info.state = self.info.started ? e.type === 'mouseup' ? 'end' : 'track' : 'start';
+if (self.info.state === 'start') {
+Gestures.prevent('tap');
+}
+self.info.addMove({
+x: x,
+y: y
+});
+if (!hasLeftMouseButton(e)) {
+self.info.state = 'end';
+untrackDocument(self.info);
+}
+self.fire(t, e);
+self.info.started = true;
+}
+};
+var upfn = function upfn(e) {
+if (self.info.started) {
+movefn(e);
+}
+untrackDocument(self.info);
+};
+trackDocument(this.info, movefn, upfn);
+this.info.x = e.clientX;
+this.info.y = e.clientY;
+},
+touchstart: function (e) {
+var ct = e.changedTouches[0];
+this.info.x = ct.clientX;
+this.info.y = ct.clientY;
+},
+touchmove: function (e) {
+var t = Gestures.findOriginalTarget(e);
+var ct = e.changedTouches[0];
+var x = ct.clientX, y = ct.clientY;
+if (this.hasMovedEnough(x, y)) {
+if (this.info.state === 'start') {
+Gestures.prevent('tap');
+}
+this.info.addMove({
+x: x,
+y: y
+});
+this.fire(t, ct);
+this.info.state = 'track';
+this.info.started = true;
+}
+},
+touchend: function (e) {
+var t = Gestures.findOriginalTarget(e);
+var ct = e.changedTouches[0];
+if (this.info.started) {
+this.info.state = 'end';
+this.info.addMove({
+x: ct.clientX,
+y: ct.clientY
+});
+this.fire(t, ct, e);
+}
+},
+fire: function (target, touch, preventer) {
+var secondlast = this.info.moves[this.info.moves.length - 2];
+var lastmove = this.info.moves[this.info.moves.length - 1];
+var dx = lastmove.x - this.info.x;
+var dy = lastmove.y - this.info.y;
+var ddx, ddy = 0;
+if (secondlast) {
+ddx = lastmove.x - secondlast.x;
+ddy = lastmove.y - secondlast.y;
+}
+return Gestures.fire(target, 'track', {
+state: this.info.state,
+x: touch.clientX,
+y: touch.clientY,
+dx: dx,
+dy: dy,
+ddx: ddx,
+ddy: ddy,
+sourceEvent: touch,
+preventer: preventer,
+hover: function () {
+return Gestures.deepTargetFind(touch.clientX, touch.clientY);
+}
+});
+}
+});
+Gestures.register({
+name: 'tap',
+deps: [
+'mousedown',
+'click',
+'touchstart',
+'touchend'
+],
+flow: {
+start: [
+'mousedown',
+'touchstart'
+],
+end: [
+'click',
+'touchend'
+]
+},
+emits: ['tap'],
+info: {
+x: NaN,
+y: NaN,
+prevent: false
+},
+reset: function () {
+this.info.x = NaN;
+this.info.y = NaN;
+this.info.prevent = false;
+},
+save: function (e) {
+this.info.x = e.clientX;
+this.info.y = e.clientY;
+},
+mousedown: function (e) {
+if (hasLeftMouseButton(e)) {
+this.save(e);
+}
+},
+click: function (e) {
+if (hasLeftMouseButton(e)) {
+this.forward(e);
+}
+},
+touchstart: function (e) {
+this.save(e.changedTouches[0], e);
+},
+touchend: function (e) {
+this.forward(e.changedTouches[0], e);
+},
+forward: function (e, preventer) {
+var dx = Math.abs(e.clientX - this.info.x);
+var dy = Math.abs(e.clientY - this.info.y);
+var t = Gestures.findOriginalTarget(e);
+if (isNaN(dx) || isNaN(dy) || dx <= TAP_DISTANCE && dy <= TAP_DISTANCE || isSyntheticClick(e)) {
+if (!this.info.prevent) {
+Gestures.fire(t, 'tap', {
+x: e.clientX,
+y: e.clientY,
+sourceEvent: e,
+preventer: preventer
+});
+}
+}
+}
+});
+var DIRECTION_MAP = {
+x: 'pan-x',
+y: 'pan-y',
+none: 'none',
+all: 'auto'
+};
+Polymer.Base._addFeature({
+_setupGestures: function () {
+this.__polymerGestures = null;
+},
+_listen: function (node, eventName, handler) {
+if (Gestures.gestures[eventName]) {
+Gestures.add(node, eventName, handler);
+} else {
+node.addEventListener(eventName, handler);
+}
+},
+_unlisten: function (node, eventName, handler) {
+if (Gestures.gestures[eventName]) {
+Gestures.remove(node, eventName, handler);
+} else {
+node.removeEventListener(eventName, handler);
+}
+},
+setScrollDirection: function (direction, node) {
+node = node || this;
+Gestures.setTouchAction(node, DIRECTION_MAP[direction] || 'auto');
+}
+});
+Polymer.Gestures = Gestures;
+}());(function () {
+'use strict';
+Polymer.Base._addFeature({
+$$: function (slctr) {
+return Polymer.dom(this.root).querySelector(slctr);
+},
+toggleClass: function (name, bool, node) {
+node = node || this;
+if (arguments.length == 1) {
+bool = !node.classList.contains(name);
+}
+if (bool) {
+Polymer.dom(node).classList.add(name);
+} else {
+Polymer.dom(node).classList.remove(name);
+}
+},
+toggleAttribute: function (name, bool, node) {
+node = node || this;
+if (arguments.length == 1) {
+bool = !node.hasAttribute(name);
+}
+if (bool) {
+Polymer.dom(node).setAttribute(name, '');
+} else {
+Polymer.dom(node).removeAttribute(name);
+}
+},
+classFollows: function (name, toElement, fromElement) {
+if (fromElement) {
+Polymer.dom(fromElement).classList.remove(name);
+}
+if (toElement) {
+Polymer.dom(toElement).classList.add(name);
+}
+},
+attributeFollows: function (name, toElement, fromElement) {
+if (fromElement) {
+Polymer.dom(fromElement).removeAttribute(name);
+}
+if (toElement) {
+Polymer.dom(toElement).setAttribute(name, '');
+}
+},
+getEffectiveChildNodes: function () {
+return Polymer.dom(this).getEffectiveChildNodes();
+},
+getEffectiveChildren: function () {
+var list = Polymer.dom(this).getEffectiveChildNodes();
+return list.filter(function (n) {
+return n.nodeType === Node.ELEMENT_NODE;
+});
+},
+getEffectiveTextContent: function () {
+var cn = this.getEffectiveChildNodes();
+var tc = [];
+for (var i = 0, c; c = cn[i]; i++) {
+if (c.nodeType !== Node.COMMENT_NODE) {
+tc.push(Polymer.dom(c).textContent);
+}
+}
+return tc.join('');
+},
+queryEffectiveChildren: function (slctr) {
+var e$ = Polymer.dom(this).queryDistributedElements(slctr);
+return e$ && e$[0];
+},
+queryAllEffectiveChildren: function (slctr) {
+return Polymer.dom(this).queryDistributedElements(slctr);
+},
+getContentChildNodes: function (slctr) {
+var content = Polymer.dom(this.root).querySelector(slctr || 'content');
+return content ? Polymer.dom(content).getDistributedNodes() : [];
+},
+getContentChildren: function (slctr) {
+return this.getContentChildNodes(slctr).filter(function (n) {
+return n.nodeType === Node.ELEMENT_NODE;
+});
+},
+fire: function (type, detail, options) {
+options = options || Polymer.nob;
+var node = options.node || this;
+detail = detail === null || detail === undefined ? {} : detail;
+var bubbles = options.bubbles === undefined ? true : options.bubbles;
+var cancelable = Boolean(options.cancelable);
+var useCache = options._useCache;
+var event = this._getEvent(type, bubbles, cancelable, useCache);
+event.detail = detail;
+if (useCache) {
+this.__eventCache[type] = null;
+}
+node.dispatchEvent(event);
+if (useCache) {
+this.__eventCache[type] = event;
+}
+return event;
+},
+__eventCache: {},
+_getEvent: function (type, bubbles, cancelable, useCache) {
+var event = useCache && this.__eventCache[type];
+if (!event || (event.bubbles != bubbles || event.cancelable != cancelable)) {
+event = new Event(type, {
+bubbles: Boolean(bubbles),
+cancelable: cancelable
+});
+}
+return event;
+},
+async: function (callback, waitTime) {
+var self = this;
+return Polymer.Async.run(function () {
+callback.call(self);
+}, waitTime);
+},
+cancelAsync: function (handle) {
+Polymer.Async.cancel(handle);
+},
+arrayDelete: function (path, item) {
+var index;
+if (Array.isArray(path)) {
+index = path.indexOf(item);
+if (index >= 0) {
+return path.splice(index, 1);
+}
+} else {
+var arr = this._get(path);
+index = arr.indexOf(item);
+if (index >= 0) {
+return this.splice(path, index, 1);
+}
+}
+},
+transform: function (transform, node) {
+node = node || this;
+node.style.webkitTransform = transform;
+node.style.transform = transform;
+},
+translate3d: function (x, y, z, node) {
+node = node || this;
+this.transform('translate3d(' + x + ',' + y + ',' + z + ')', node);
+},
+importHref: function (href, onload, onerror, optAsync) {
+var link = document.createElement('link');
+link.rel = 'import';
+link.href = href;
+var list = Polymer.Base.importHref.imported = Polymer.Base.importHref.imported || {};
+var cached = list[link.href];
+var imprt = cached || link;
+var self = this;
+var loadListener = function (e) {
+e.target.__firedLoad = true;
+e.target.removeEventListener('load', loadListener);
+e.target.removeEventListener('error', errorListener);
+return onload.call(self, e);
+};
+var errorListener = function (e) {
+e.target.__firedError = true;
+e.target.removeEventListener('load', loadListener);
+e.target.removeEventListener('error', errorListener);
+return onerror.call(self, e);
+};
+if (onload) {
+imprt.addEventListener('load', loadListener);
+}
+if (onerror) {
+imprt.addEventListener('error', errorListener);
+}
+if (cached) {
+if (cached.__firedLoad) {
+cached.dispatchEvent(new Event('load'));
+}
+if (cached.__firedError) {
+cached.dispatchEvent(new Event('error'));
+}
+} else {
+list[link.href] = link;
+optAsync = Boolean(optAsync);
+if (optAsync) {
+link.setAttribute('async', '');
+}
+document.head.appendChild(link);
+}
+return imprt;
+},
+create: function (tag, props) {
+var elt = document.createElement(tag);
+if (props) {
+for (var n in props) {
+elt[n] = props[n];
+}
+}
+return elt;
+},
+isLightDescendant: function (node) {
+return this !== node && this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot();
+},
+isLocalDescendant: function (node) {
+return this.root === Polymer.dom(node).getOwnerRoot();
+}
+});
+if (!Polymer.Settings.useNativeCustomElements) {
+var importHref = Polymer.Base.importHref;
+Polymer.Base.importHref = function (href, onload, onerror, optAsync) {
+CustomElements.ready = false;
+var loadFn = function (e) {
+CustomElements.upgradeDocumentTree(document);
+CustomElements.ready = true;
+if (onload) {
+return onload.call(this, e);
+}
+};
+return importHref.call(this, href, loadFn, onerror, optAsync);
+};
+}
+}());Polymer.Bind = {
+prepareModel: function (model) {
+Polymer.Base.mixin(model, this._modelApi);
+},
+_modelApi: {
+_notifyChange: function (source, event, value) {
+value = value === undefined ? this[source] : value;
+event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed';
+this.fire(event, { value: value }, {
+bubbles: false,
+cancelable: false,
+_useCache: Polymer.Settings.eventDataCache || !Polymer.Settings.isIE
+});
+},
+_propertySetter: function (property, value, effects, fromAbove) {
+var old = this.__data__[property];
+if (old !== value && (old === old || value === value)) {
+this.__data__[property] = value;
+if (typeof value == 'object') {
+this._clearPath(property);
+}
+if (this._propertyChanged) {
+this._propertyChanged(property, value, old);
+}
+if (effects) {
+this._effectEffects(property, value, effects, old, fromAbove);
+}
+}
+return old;
+},
+__setProperty: function (property, value, quiet, node) {
+node = node || this;
+var effects = node._propertyEffects && node._propertyEffects[property];
+if (effects) {
+node._propertySetter(property, value, effects, quiet);
+} else if (node[property] !== value) {
+node[property] = value;
+}
+},
+_effectEffects: function (property, value, effects, old, fromAbove) {
+for (var i = 0, l = effects.length, fx; i < l && (fx = effects[i]); i++) {
+fx.fn.call(this, property, this[property], fx.effect, old, fromAbove);
+}
+},
+_clearPath: function (path) {
+for (var prop in this.__data__) {
+if (Polymer.Path.isDescendant(path, prop)) {
+this.__data__[prop] = undefined;
+}
+}
+}
+},
+ensurePropertyEffects: function (model, property) {
+if (!model._propertyEffects) {
+model._propertyEffects = {};
+}
+var fx = model._propertyEffects[property];
+if (!fx) {
+fx = model._propertyEffects[property] = [];
+}
+return fx;
+},
+addPropertyEffect: function (model, property, kind, effect) {
+var fx = this.ensurePropertyEffects(model, property);
+var propEffect = {
+kind: kind,
+effect: effect,
+fn: Polymer.Bind['_' + kind + 'Effect']
+};
+fx.push(propEffect);
+return propEffect;
+},
+createBindings: function (model) {
+var fx$ = model._propertyEffects;
+if (fx$) {
+for (var n in fx$) {
+var fx = fx$[n];
+fx.sort(this._sortPropertyEffects);
+this._createAccessors(model, n, fx);
+}
+}
+},
+_sortPropertyEffects: function () {
+var EFFECT_ORDER = {
+'compute': 0,
+'annotation': 1,
+'annotatedComputation': 2,
+'reflect': 3,
+'notify': 4,
+'observer': 5,
+'complexObserver': 6,
+'function': 7
+};
+return function (a, b) {
+return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind];
+};
+}(),
+_createAccessors: function (model, property, effects) {
+var defun = {
+get: function () {
+return this.__data__[property];
+}
+};
+var setter = function (value) {
+this._propertySetter(property, value, effects);
+};
+var info = model.getPropertyInfo && model.getPropertyInfo(property);
+if (info && info.readOnly) {
+if (!info.computed) {
+model['_set' + this.upper(property)] = setter;
+}
+} else {
+defun.set = setter;
+}
+Object.defineProperty(model, property, defun);
+},
+upper: function (name) {
+return name[0].toUpperCase() + name.substring(1);
+},
+_addAnnotatedListener: function (model, index, property, path, event, negated) {
+if (!model._bindListeners) {
+model._bindListeners = [];
+}
+var fn = this._notedListenerFactory(property, path, Polymer.Path.isDeep(path), negated);
+var eventName = event || Polymer.CaseMap.camelToDashCase(property) + '-changed';
+model._bindListeners.push({
+index: index,
+property: property,
+path: path,
+changedFn: fn,
+event: eventName
+});
+},
+_isEventBogus: function (e, target) {
+return e.path && e.path[0] !== target;
+},
+_notedListenerFactory: function (property, path, isStructured, negated) {
+return function (target, value, targetPath) {
+if (targetPath) {
+var newPath = Polymer.Path.translate(property, path, targetPath);
+this._notifyPath(newPath, value);
+} else {
+value = target[property];
+if (negated) {
+value = !value;
+}
+if (!isStructured) {
+this[path] = value;
+} else {
+if (this.__data__[path] != value) {
+this.set(path, value);
+}
+}
+}
+};
+},
+prepareInstance: function (inst) {
+inst.__data__ = Object.create(null);
+},
+setupBindListeners: function (inst) {
+var b$ = inst._bindListeners;
+for (var i = 0, l = b$.length, info; i < l && (info = b$[i]); i++) {
+var node = inst._nodes[info.index];
+this._addNotifyListener(node, inst, info.event, info.changedFn);
+}
+},
+_addNotifyListener: function (element, context, event, changedFn) {
+element.addEventListener(event, function (e) {
+return context._notifyListener(changedFn, e);
+});
+}
+};Polymer.Base.mixin(Polymer.Bind, {
+_shouldAddListener: function (effect) {
+return effect.name && effect.kind != 'attribute' && effect.kind != 'text' && !effect.isCompound && effect.parts[0].mode === '{';
+},
+_annotationEffect: function (source, value, effect) {
+if (source != effect.value) {
+value = this._get(effect.value);
+this.__data__[effect.value] = value;
+}
+this._applyEffectValue(effect, value);
+},
+_reflectEffect: function (source, value, effect) {
+this.reflectPropertyToAttribute(source, effect.attribute, value);
+},
+_notifyEffect: function (source, value, effect, old, fromAbove) {
+if (!fromAbove) {
+this._notifyChange(source, effect.event, value);
+}
+},
+_functionEffect: function (source, value, fn, old, fromAbove) {
+fn.call(this, source, value, old, fromAbove);
+},
+_observerEffect: function (source, value, effect, old) {
+var fn = this[effect.method];
+if (fn) {
+fn.call(this, value, old);
+} else {
+this._warn(this._logf('_observerEffect', 'observer method `' + effect.method + '` not defined'));
+}
+},
+_complexObserverEffect: function (source, value, effect) {
+var fn = this[effect.method];
+if (fn) {
+var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
+if (args) {
+fn.apply(this, args);
+}
+} else if (effect.dynamicFn) {
+} else {
+this._warn(this._logf('_complexObserverEffect', 'observer method `' + effect.method + '` not defined'));
+}
+},
+_computeEffect: function (source, value, effect) {
+var fn = this[effect.method];
+if (fn) {
+var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
+if (args) {
+var computedvalue = fn.apply(this, args);
+this.__setProperty(effect.name, computedvalue);
+}
+} else if (effect.dynamicFn) {
+} else {
+this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined'));
+}
+},
+_annotatedComputationEffect: function (source, value, effect) {
+var computedHost = this._rootDataHost || this;
+var fn = computedHost[effect.method];
+if (fn) {
+var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
+if (args) {
+var computedvalue = fn.apply(computedHost, args);
+this._applyEffectValue(effect, computedvalue);
+}
+} else if (effect.dynamicFn) {
+} else {
+computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute method `' + effect.method + '` not defined'));
+}
+},
+_marshalArgs: function (model, effect, path, value) {
+var values = [];
+var args = effect.args;
+var bailoutEarly = args.length > 1 || effect.dynamicFn;
+for (var i = 0, l = args.length; i < l; i++) {
+var arg = args[i];
+var name = arg.name;
+var v;
+if (arg.literal) {
+v = arg.value;
+} else if (path === name) {
+v = value;
+} else {
+v = model[name];
+if (v === undefined && arg.structured) {
+v = Polymer.Base._get(name, model);
+}
+}
+if (bailoutEarly && v === undefined) {
+return;
+}
+if (arg.wildcard) {
+var matches = Polymer.Path.isAncestor(path, name);
+values[i] = {
+path: matches ? path : name,
+value: matches ? value : v,
+base: v
+};
+} else {
+values[i] = v;
+}
+}
+return values;
+}
+});Polymer.Base._addFeature({
+_addPropertyEffect: function (property, kind, effect) {
+var prop = Polymer.Bind.addPropertyEffect(this, property, kind, effect);
+prop.pathFn = this['_' + prop.kind + 'PathEffect'];
+},
+_prepEffects: function () {
+Polymer.Bind.prepareModel(this);
+this._addAnnotationEffects(this._notes);
+},
+_prepBindings: function () {
+Polymer.Bind.createBindings(this);
+},
+_addPropertyEffects: function (properties) {
+if (properties) {
+for (var p in properties) {
+var prop = properties[p];
+if (prop.observer) {
+this._addObserverEffect(p, prop.observer);
+}
+if (prop.computed) {
+prop.readOnly = true;
+this._addComputedEffect(p, prop.computed);
+}
+if (prop.notify) {
+this._addPropertyEffect(p, 'notify', { event: Polymer.CaseMap.camelToDashCase(p) + '-changed' });
+}
+if (prop.reflectToAttribute) {
+var attr = Polymer.CaseMap.camelToDashCase(p);
+if (attr[0] === '-') {
+this._warn(this._logf('_addPropertyEffects', 'Property ' + p + ' cannot be reflected to attribute ' + attr + ' because "-" is not a valid starting attribute name. Use a lowercase first letter for the property instead.'));
+} else {
+this._addPropertyEffect(p, 'reflect', { attribute: attr });
+}
+}
+if (prop.readOnly) {
+Polymer.Bind.ensurePropertyEffects(this, p);
+}
+}
+}
+},
+_addComputedEffect: function (name, expression) {
+var sig = this._parseMethod(expression);
+var dynamicFn = sig.dynamicFn;
+for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
+this._addPropertyEffect(arg.model, 'compute', {
+method: sig.method,
+args: sig.args,
+trigger: arg,
+name: name,
+dynamicFn: dynamicFn
+});
+}
+if (dynamicFn) {
+this._addPropertyEffect(sig.method, 'compute', {
+method: sig.method,
+args: sig.args,
+trigger: null,
+name: name,
+dynamicFn: dynamicFn
+});
+}
+},
+_addObserverEffect: function (property, observer) {
+this._addPropertyEffect(property, 'observer', {
+method: observer,
+property: property
+});
+},
+_addComplexObserverEffects: function (observers) {
+if (observers) {
+for (var i = 0, o; i < observers.length && (o = observers[i]); i++) {
+this._addComplexObserverEffect(o);
+}
+}
+},
+_addComplexObserverEffect: function (observer) {
+var sig = this._parseMethod(observer);
+if (!sig) {
+throw new Error('Malformed observer expression \'' + observer + '\'');
+}
+var dynamicFn = sig.dynamicFn;
+for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
+this._addPropertyEffect(arg.model, 'complexObserver', {
+method: sig.method,
+args: sig.args,
+trigger: arg,
+dynamicFn: dynamicFn
+});
+}
+if (dynamicFn) {
+this._addPropertyEffect(sig.method, 'complexObserver', {
+method: sig.method,
+args: sig.args,
+trigger: null,
+dynamicFn: dynamicFn
+});
+}
+},
+_addAnnotationEffects: function (notes) {
+for (var i = 0, note; i < notes.length && (note = notes[i]); i++) {
+var b$ = note.bindings;
+for (var j = 0, binding; j < b$.length && (binding = b$[j]); j++) {
+this._addAnnotationEffect(binding, i);
+}
+}
+},
+_addAnnotationEffect: function (note, index) {
+if (Polymer.Bind._shouldAddListener(note)) {
+Polymer.Bind._addAnnotatedListener(this, index, note.name, note.parts[0].value, note.parts[0].event, note.parts[0].negate);
+}
+for (var i = 0; i < note.parts.length; i++) {
+var part = note.parts[i];
+if (part.signature) {
+this._addAnnotatedComputationEffect(note, part, index);
+} else if (!part.literal) {
+if (note.kind === 'attribute' && note.name[0] === '-') {
+this._warn(this._logf('_addAnnotationEffect', 'Cannot set attribute ' + note.name + ' because "-" is not a valid attribute starting character'));
+} else {
+this._addPropertyEffect(part.model, 'annotation', {
+kind: note.kind,
+index: index,
+name: note.name,
+propertyName: note.propertyName,
+value: part.value,
+isCompound: note.isCompound,
+compoundIndex: part.compoundIndex,
+event: part.event,
+customEvent: part.customEvent,
+negate: part.negate
+});
+}
+}
+}
+},
+_addAnnotatedComputationEffect: function (note, part, index) {
+var sig = part.signature;
+if (sig.static) {
+this.__addAnnotatedComputationEffect('__static__', index, note, part, null);
+} else {
+for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
+if (!arg.literal) {
+this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg);
+}
+}
+if (sig.dynamicFn) {
+this.__addAnnotatedComputationEffect(sig.method, index, note, part, null);
+}
+}
+},
+__addAnnotatedComputationEffect: function (property, index, note, part, trigger) {
+this._addPropertyEffect(property, 'annotatedComputation', {
+index: index,
+isCompound: note.isCompound,
+compoundIndex: part.compoundIndex,
+kind: note.kind,
+name: note.name,
+negate: part.negate,
+method: part.signature.method,
+args: part.signature.args,
+trigger: trigger,
+dynamicFn: part.signature.dynamicFn
+});
+},
+_parseMethod: function (expression) {
+var m = expression.match(/([^\s]+?)\(([\s\S]*)\)/);
+if (m) {
+var sig = {
+method: m[1],
+static: true
+};
+if (this.getPropertyInfo(sig.method) !== Polymer.nob) {
+sig.static = false;
+sig.dynamicFn = true;
+}
+if (m[2].trim()) {
+var args = m[2].replace(/\\,/g, '&comma;').split(',');
+return this._parseArgs(args, sig);
+} else {
+sig.args = Polymer.nar;
+return sig;
+}
+}
+},
+_parseArgs: function (argList, sig) {
+sig.args = argList.map(function (rawArg) {
+var arg = this._parseArg(rawArg);
+if (!arg.literal) {
+sig.static = false;
+}
+return arg;
+}, this);
+return sig;
+},
+_parseArg: function (rawArg) {
+var arg = rawArg.trim().replace(/&comma;/g, ',').replace(/\\(.)/g, '$1');
+var a = { name: arg };
+var fc = arg[0];
+if (fc === '-') {
+fc = arg[1];
+}
+if (fc >= '0' && fc <= '9') {
+fc = '#';
+}
+switch (fc) {
+case '\'':
+case '"':
+a.value = arg.slice(1, -1);
+a.literal = true;
+break;
+case '#':
+a.value = Number(arg);
+a.literal = true;
+break;
+}
+if (!a.literal) {
+a.model = Polymer.Path.root(arg);
+a.structured = Polymer.Path.isDeep(arg);
+if (a.structured) {
+a.wildcard = arg.slice(-2) == '.*';
+if (a.wildcard) {
+a.name = arg.slice(0, -2);
+}
+}
+}
+return a;
+},
+_marshalInstanceEffects: function () {
+Polymer.Bind.prepareInstance(this);
+if (this._bindListeners) {
+Polymer.Bind.setupBindListeners(this);
+}
+},
+_applyEffectValue: function (info, value) {
+var node = this._nodes[info.index];
+var property = info.name;
+value = this._computeFinalAnnotationValue(node, property, value, info);
+if (info.kind == 'attribute') {
+this.serializeValueToAttribute(value, property, node);
+} else {
+var pinfo = node._propertyInfo && node._propertyInfo[property];
+if (pinfo && pinfo.readOnly) {
+return;
+}
+this.__setProperty(property, value, Polymer.Settings.suppressBindingNotifications, node);
+}
+},
+_computeFinalAnnotationValue: function (node, property, value, info) {
+if (info.negate) {
+value = !value;
+}
+if (info.isCompound) {
+var storage = node.__compoundStorage__[property];
+storage[info.compoundIndex] = value;
+value = storage.join('');
+}
+if (info.kind !== 'attribute') {
+if (property === 'className') {
+value = this._scopeElementClass(node, value);
+}
+if (property === 'textContent' || node.localName == 'input' && property == 'value') {
+value = value == undefined ? '' : value;
+}
+}
+return value;
+},
+_executeStaticEffects: function () {
+if (this._propertyEffects && this._propertyEffects.__static__) {
+this._effectEffects('__static__', null, this._propertyEffects.__static__);
+}
+}
+});(function () {
+var usePolyfillProto = Polymer.Settings.usePolyfillProto;
+var avoidInstanceProperties = Boolean(Object.getOwnPropertyDescriptor(document.documentElement, 'properties'));
+Polymer.Base._addFeature({
+_setupConfigure: function (initialConfig) {
+this._config = {};
+this._handlers = [];
+this._aboveConfig = null;
+if (initialConfig) {
+for (var i in initialConfig) {
+if (initialConfig[i] !== undefined) {
+this._config[i] = initialConfig[i];
+}
+}
+}
+},
+_marshalAttributes: function () {
+this._takeAttributesToModel(this._config);
+},
+_attributeChangedImpl: function (name) {
+var model = this._clientsReadied ? this : this._config;
+this._setAttributeToProperty(model, name);
+},
+_configValue: function (name, value) {
+var info = this._propertyInfo[name];
+if (!info || !info.readOnly) {
+this._config[name] = value;
+}
+},
+_beforeClientsReady: function () {
+this._configure();
+},
+_configure: function () {
+this._configureAnnotationReferences();
+this._configureInstanceProperties();
+this._aboveConfig = this.mixin({}, this._config);
+var config = {};
+for (var i = 0; i < this.behaviors.length; i++) {
+this._configureProperties(this.behaviors[i].properties, config);
+}
+this._configureProperties(avoidInstanceProperties ? this.__proto__.properties : this.properties, config);
+this.mixin(config, this._aboveConfig);
+this._config = config;
+if (this._clients && this._clients.length) {
+this._distributeConfig(this._config);
+}
+},
+_configureInstanceProperties: function () {
+for (var i in this._propertyEffects) {
+if (!usePolyfillProto && this.hasOwnProperty(i)) {
+this._configValue(i, this[i]);
+delete this[i];
+}
+}
+},
+_configureProperties: function (properties, config) {
+for (var i in properties) {
+var c = properties[i];
+if (c.value !== undefined) {
+var value = c.value;
+if (typeof value == 'function') {
+value = value.call(this, this._config);
+}
+config[i] = value;
+}
+}
+},
+_distributeConfig: function (config) {
+var fx$ = this._propertyEffects;
+if (fx$) {
+for (var p in config) {
+var fx = fx$[p];
+if (fx) {
+for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) {
+if (x.kind === 'annotation') {
+var node = this._nodes[x.effect.index];
+var name = x.effect.propertyName;
+var isAttr = x.effect.kind == 'attribute';
+var hasEffect = node._propertyEffects && node._propertyEffects[name];
+if (node._configValue && (hasEffect || !isAttr)) {
+var value = p === x.effect.value ? config[p] : this._get(x.effect.value, config);
+value = this._computeFinalAnnotationValue(node, name, value, x.effect);
+if (isAttr) {
+value = node.deserialize(this.serialize(value), node._propertyInfo[name].type);
+}
+node._configValue(name, value);
+}
+}
+}
+}
+}
+}
+},
+_afterClientsReady: function () {
+this.importPath = this._importPath;
+this.rootPath = Polymer.rootPath;
+this._executeStaticEffects();
+this._applyConfig(this._config, this._aboveConfig);
+this._flushHandlers();
+},
+_applyConfig: function (config, aboveConfig) {
+for (var n in config) {
+if (this[n] === undefined) {
+this.__setProperty(n, config[n], n in aboveConfig);
+}
+}
+},
+_notifyListener: function (fn, e) {
+if (!Polymer.Bind._isEventBogus(e, e.target)) {
+var value, path;
+if (e.detail) {
+value = e.detail.value;
+path = e.detail.path;
+}
+if (!this._clientsReadied) {
+this._queueHandler([
+fn,
+e.target,
+value,
+path
+]);
+} else {
+return fn.call(this, e.target, value, path);
+}
+}
+},
+_queueHandler: function (args) {
+this._handlers.push(args);
+},
+_flushHandlers: function () {
+var h$ = this._handlers;
+for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) {
+h[0].call(this, h[1], h[2], h[3]);
+}
+this._handlers = [];
+}
+});
+}());(function () {
+'use strict';
+var Path = Polymer.Path;
+Polymer.Base._addFeature({
+notifyPath: function (path, value, fromAbove) {
+var info = {};
+var v = this._get(path, this, info);
+if (arguments.length === 1) {
+value = v;
+}
+if (info.path) {
+this._notifyPath(info.path, value, fromAbove);
+}
+},
+_notifyPath: function (path, value, fromAbove) {
+var old = this._propertySetter(path, value);
+if (old !== value && (old === old || value === value)) {
+this._pathEffector(path, value);
+if (!fromAbove) {
+this._notifyPathUp(path, value);
+}
+return true;
+}
+},
+_getPathParts: function (path) {
+if (Array.isArray(path)) {
+var parts = [];
+for (var i = 0; i < path.length; i++) {
+var args = path[i].toString().split('.');
+for (var j = 0; j < args.length; j++) {
+parts.push(args[j]);
+}
+}
+return parts;
+} else {
+return path.toString().split('.');
+}
+},
+set: function (path, value, root) {
+var prop = root || this;
+var parts = this._getPathParts(path);
+var array;
+var last = parts[parts.length - 1];
+if (parts.length > 1) {
+for (var i = 0; i < parts.length - 1; i++) {
+var part = parts[i];
+if (array && part[0] == '#') {
+prop = Polymer.Collection.get(array).getItem(part);
+} else {
+prop = prop[part];
+if (array && parseInt(part, 10) == part) {
+parts[i] = Polymer.Collection.get(array).getKey(prop);
+}
+}
+if (!prop) {
+return;
+}
+array = Array.isArray(prop) ? prop : null;
+}
+if (array) {
+var coll = Polymer.Collection.get(array);
+var old, key;
+if (last[0] == '#') {
+key = last;
+old = coll.getItem(key);
+last = array.indexOf(old);
+coll.setItem(key, value);
+} else if (parseInt(last, 10) == last) {
+old = prop[last];
+key = coll.getKey(old);
+parts[i] = key;
+coll.setItem(key, value);
+}
+}
+prop[last] = value;
+if (!root) {
+this._notifyPath(parts.join('.'), value);
+}
+} else {
+prop[path] = value;
+}
+},
+get: function (path, root) {
+return this._get(path, root);
+},
+_get: function (path, root, info) {
+var prop = root || this;
+var parts = this._getPathParts(path);
+var array;
+for (var i = 0; i < parts.length; i++) {
+if (!prop) {
+return;
+}
+var part = parts[i];
+if (array && part[0] == '#') {
+prop = Polymer.Collection.get(array).getItem(part);
+} else {
+prop = prop[part];
+if (info && array && parseInt(part, 10) == part) {
+parts[i] = Polymer.Collection.get(array).getKey(prop);
+}
+}
+array = Array.isArray(prop) ? prop : null;
+}
+if (info) {
+info.path = parts.join('.');
+}
+return prop;
+},
+_pathEffector: function (path, value) {
+var model = Path.root(path);
+var fx$ = this._propertyEffects && this._propertyEffects[model];
+if (fx$) {
+for (var i = 0, fx; i < fx$.length && (fx = fx$[i]); i++) {
+var fxFn = fx.pathFn;
+if (fxFn) {
+fxFn.call(this, path, value, fx.effect);
+}
+}
+}
+if (this._boundPaths) {
+this._notifyBoundPaths(path, value);
+}
+},
+_annotationPathEffect: function (path, value, effect) {
+if (Path.matches(effect.value, false, path)) {
+Polymer.Bind._annotationEffect.call(this, path, value, effect);
+} else if (!effect.negate && Path.isDescendant(effect.value, path)) {
+var node = this._nodes[effect.index];
+if (node && node._notifyPath) {
+var newPath = Path.translate(effect.value, effect.name, path);
+node._notifyPath(newPath, value, true);
+}
+}
+},
+_complexObserverPathEffect: function (path, value, effect) {
+if (Path.matches(effect.trigger.name, effect.trigger.wildcard, path)) {
+Polymer.Bind._complexObserverEffect.call(this, path, value, effect);
+}
+},
+_computePathEffect: function (path, value, effect) {
+if (Path.matches(effect.trigger.name, effect.trigger.wildcard, path)) {
+Polymer.Bind._computeEffect.call(this, path, value, effect);
+}
+},
+_annotatedComputationPathEffect: function (path, value, effect) {
+if (Path.matches(effect.trigger.name, effect.trigger.wildcard, path)) {
+Polymer.Bind._annotatedComputationEffect.call(this, path, value, effect);
+}
+},
+linkPaths: function (to, from) {
+this._boundPaths = this._boundPaths || {};
+if (from) {
+this._boundPaths[to] = from;
+} else {
+this.unlinkPaths(to);
+}
+},
+unlinkPaths: function (path) {
+if (this._boundPaths) {
+delete this._boundPaths[path];
+}
+},
+_notifyBoundPaths: function (path, value) {
+for (var a in this._boundPaths) {
+var b = this._boundPaths[a];
+if (Path.isDescendant(a, path)) {
+this._notifyPath(Path.translate(a, b, path), value);
+} else if (Path.isDescendant(b, path)) {
+this._notifyPath(Path.translate(b, a, path), value);
+}
+}
+},
+_notifyPathUp: function (path, value) {
+var rootName = Path.root(path);
+var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName);
+var eventName = dashCaseName + this._EVENT_CHANGED;
+this.fire(eventName, {
+path: path,
+value: value
+}, {
+bubbles: false,
+_useCache: Polymer.Settings.eventDataCache || !Polymer.Settings.isIE
+});
+},
+_EVENT_CHANGED: '-changed',
+notifySplices: function (path, splices) {
+var info = {};
+var array = this._get(path, this, info);
+this._notifySplices(array, info.path, splices);
+},
+_notifySplices: function (array, path, splices) {
+var change = {
+keySplices: Polymer.Collection.applySplices(array, splices),
+indexSplices: splices
+};
+var splicesPath = path + '.splices';
+this._notifyPath(splicesPath, change);
+this._notifyPath(path + '.length', array.length);
+this.__data__[splicesPath] = {
+keySplices: null,
+indexSplices: null
+};
+},
+_notifySplice: function (array, path, index, added, removed) {
+this._notifySplices(array, path, [{
+index: index,
+addedCount: added,
+removed: removed,
+object: array,
+type: 'splice'
+}]);
+},
+push: function (path) {
+var info = {};
+var array = this._get(path, this, info);
+var args = Array.prototype.slice.call(arguments, 1);
+var len = array.length;
+var ret = array.push.apply(array, args);
+if (args.length) {
+this._notifySplice(array, info.path, len, args.length, []);
+}
+return ret;
+},
+pop: function (path) {
+var info = {};
+var array = this._get(path, this, info);
+var hadLength = Boolean(array.length);
+var args = Array.prototype.slice.call(arguments, 1);
+var ret = array.pop.apply(array, args);
+if (hadLength) {
+this._notifySplice(array, info.path, array.length, 0, [ret]);
+}
+return ret;
+},
+splice: function (path, start) {
+var info = {};
+var array = this._get(path, this, info);
+if (start < 0) {
+start = array.length - Math.floor(-start);
+} else {
+start = Math.floor(start);
+}
+if (!start) {
+start = 0;
+}
+var args = Array.prototype.slice.call(arguments, 1);
+var ret = array.splice.apply(array, args);
+var addedCount = Math.max(args.length - 2, 0);
+if (addedCount || ret.length) {
+this._notifySplice(array, info.path, start, addedCount, ret);
+}
+return ret;
+},
+shift: function (path) {
+var info = {};
+var array = this._get(path, this, info);
+var hadLength = Boolean(array.length);
+var args = Array.prototype.slice.call(arguments, 1);
+var ret = array.shift.apply(array, args);
+if (hadLength) {
+this._notifySplice(array, info.path, 0, 0, [ret]);
+}
+return ret;
+},
+unshift: function (path) {
+var info = {};
+var array = this._get(path, this, info);
+var args = Array.prototype.slice.call(arguments, 1);
+var ret = array.unshift.apply(array, args);
+if (args.length) {
+this._notifySplice(array, info.path, 0, args.length, []);
+}
+return ret;
+},
+prepareModelNotifyPath: function (model) {
+this.mixin(model, {
+fire: Polymer.Base.fire,
+_getEvent: Polymer.Base._getEvent,
+__eventCache: Polymer.Base.__eventCache,
+notifyPath: Polymer.Base.notifyPath,
+_get: Polymer.Base._get,
+_EVENT_CHANGED: Polymer.Base._EVENT_CHANGED,
+_notifyPath: Polymer.Base._notifyPath,
+_notifyPathUp: Polymer.Base._notifyPathUp,
+_pathEffector: Polymer.Base._pathEffector,
+_annotationPathEffect: Polymer.Base._annotationPathEffect,
+_complexObserverPathEffect: Polymer.Base._complexObserverPathEffect,
+_annotatedComputationPathEffect: Polymer.Base._annotatedComputationPathEffect,
+_computePathEffect: Polymer.Base._computePathEffect,
+_notifyBoundPaths: Polymer.Base._notifyBoundPaths,
+_getPathParts: Polymer.Base._getPathParts
+});
+}
+});
+}());Polymer.Base._addFeature({
+resolveUrl: function (url) {
+return Polymer.ResolveUrl.resolveUrl(url, this._importPath);
+}
+});Polymer.CssParse = function () {
+return {
+parse: function (text) {
+text = this._clean(text);
+return this._parseCss(this._lex(text), text);
+},
+_clean: function (cssText) {
+return cssText.replace(this._rx.comments, '').replace(this._rx.port, '');
+},
+_lex: function (text) {
+var root = {
+start: 0,
+end: text.length
+};
+var n = root;
+for (var i = 0, l = text.length; i < l; i++) {
+switch (text[i]) {
+case this.OPEN_BRACE:
+if (!n.rules) {
+n.rules = [];
+}
+var p = n;
+var previous = p.rules[p.rules.length - 1];
+n = {
+start: i + 1,
+parent: p,
+previous: previous
+};
+p.rules.push(n);
+break;
+case this.CLOSE_BRACE:
+n.end = i + 1;
+n = n.parent || root;
+break;
+}
+}
+return root;
+},
+_parseCss: function (node, text) {
+var t = text.substring(node.start, node.end - 1);
+node.parsedCssText = node.cssText = t.trim();
+if (node.parent) {
+var ss = node.previous ? node.previous.end : node.parent.start;
+t = text.substring(ss, node.start - 1);
+t = this._expandUnicodeEscapes(t);
+t = t.replace(this._rx.multipleSpaces, ' ');
+t = t.substring(t.lastIndexOf(';') + 1);
+var s = node.parsedSelector = node.selector = t.trim();
+node.atRule = s.indexOf(this.AT_START) === 0;
+if (node.atRule) {
+if (s.indexOf(this.MEDIA_START) === 0) {
+node.type = this.types.MEDIA_RULE;
+} else if (s.match(this._rx.keyframesRule)) {
+node.type = this.types.KEYFRAMES_RULE;
+node.keyframesName = node.selector.split(this._rx.multipleSpaces).pop();
+}
+} else {
+if (s.indexOf(this.VAR_START) === 0) {
+node.type = this.types.MIXIN_RULE;
+} else {
+node.type = this.types.STYLE_RULE;
+}
+}
+}
+var r$ = node.rules;
+if (r$) {
+for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
+this._parseCss(r, text);
+}
+}
+return node;
+},
+_expandUnicodeEscapes: function (s) {
+return s.replace(/\\([0-9a-f]{1,6})\s/gi, function () {
+var code = arguments[1], repeat = 6 - code.length;
+while (repeat--) {
+code = '0' + code;
+}
+return '\\' + code;
+});
+},
+stringify: function (node, preserveProperties, text) {
+text = text || '';
+var cssText = '';
+if (node.cssText || node.rules) {
+var r$ = node.rules;
+if (r$ && !this._hasMixinRules(r$)) {
+for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
+cssText = this.stringify(r, preserveProperties, cssText);
+}
+} else {
+cssText = preserveProperties ? node.cssText : this.removeCustomProps(node.cssText);
+cssText = cssText.trim();
+if (cssText) {
+cssText = ' ' + cssText + '\n';
+}
+}
+}
+if (cssText) {
+if (node.selector) {
+text += node.selector + ' ' + this.OPEN_BRACE + '\n';
+}
+text += cssText;
+if (node.selector) {
+text += this.CLOSE_BRACE + '\n\n';
+}
+}
+return text;
+},
+_hasMixinRules: function (rules) {
+return rules[0].selector.indexOf(this.VAR_START) === 0;
+},
+removeCustomProps: function (cssText) {
+cssText = this.removeCustomPropAssignment(cssText);
+return this.removeCustomPropApply(cssText);
+},
+removeCustomPropAssignment: function (cssText) {
+return cssText.replace(this._rx.customProp, '').replace(this._rx.mixinProp, '');
+},
+removeCustomPropApply: function (cssText) {
+return cssText.replace(this._rx.mixinApply, '').replace(this._rx.varApply, '');
+},
+types: {
+STYLE_RULE: 1,
+KEYFRAMES_RULE: 7,
+MEDIA_RULE: 4,
+MIXIN_RULE: 1000
+},
+OPEN_BRACE: '{',
+CLOSE_BRACE: '}',
+_rx: {
+comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,
+port: /@import[^;]*;/gim,
+customProp: /(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,
+mixinProp: /(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,
+mixinApply: /@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,
+varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,
+keyframesRule: /^@[^\s]*keyframes/,
+multipleSpaces: /\s+/g
+},
+VAR_START: '--',
+MEDIA_START: '@media',
+AT_START: '@'
+};
+}();Polymer.StyleUtil = function () {
+var settings = Polymer.Settings;
+return {
+unscopedStyleImports: new WeakMap(),
+SHADY_UNSCOPED_ATTR: 'shady-unscoped',
+NATIVE_VARIABLES: Polymer.Settings.useNativeCSSProperties,
+MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css], template',
+INCLUDE_ATTR: 'include',
+toCssText: function (rules, callback) {
+if (typeof rules === 'string') {
+rules = this.parser.parse(rules);
+}
+if (callback) {
+this.forEachRule(rules, callback);
+}
+return this.parser.stringify(rules, this.NATIVE_VARIABLES);
+},
+forRulesInStyles: function (styles, styleRuleCallback, keyframesRuleCallback) {
+if (styles) {
+for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
+this.forEachRuleInStyle(s, styleRuleCallback, keyframesRuleCallback);
+}
+}
+},
+forActiveRulesInStyles: function (styles, styleRuleCallback, keyframesRuleCallback) {
+if (styles) {
+for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
+this.forEachRuleInStyle(s, styleRuleCallback, keyframesRuleCallback, true);
+}
+}
+},
+rulesForStyle: function (style) {
+if (!style.__cssRules && style.textContent) {
+style.__cssRules = this.parser.parse(style.textContent);
+}
+return style.__cssRules;
+},
+isKeyframesSelector: function (rule) {
+return rule.parent && rule.parent.type === this.ruleTypes.KEYFRAMES_RULE;
+},
+forEachRuleInStyle: function (style, styleRuleCallback, keyframesRuleCallback, onlyActiveRules) {
+var rules = this.rulesForStyle(style);
+var styleCallback, keyframeCallback;
+if (styleRuleCallback) {
+styleCallback = function (rule) {
+styleRuleCallback(rule, style);
+};
+}
+if (keyframesRuleCallback) {
+keyframeCallback = function (rule) {
+keyframesRuleCallback(rule, style);
+};
+}
+this.forEachRule(rules, styleCallback, keyframeCallback, onlyActiveRules);
+},
+forEachRule: function (node, styleRuleCallback, keyframesRuleCallback, onlyActiveRules) {
+if (!node) {
+return;
+}
+var skipRules = false;
+if (onlyActiveRules) {
+if (node.type === this.ruleTypes.MEDIA_RULE) {
+var matchMedia = node.selector.match(this.rx.MEDIA_MATCH);
+if (matchMedia) {
+if (!window.matchMedia(matchMedia[1]).matches) {
+skipRules = true;
+}
+}
+}
+}
+if (node.type === this.ruleTypes.STYLE_RULE) {
+styleRuleCallback(node);
+} else if (keyframesRuleCallback && node.type === this.ruleTypes.KEYFRAMES_RULE) {
+keyframesRuleCallback(node);
+} else if (node.type === this.ruleTypes.MIXIN_RULE) {
+skipRules = true;
+}
+var r$ = node.rules;
+if (r$ && !skipRules) {
+for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
+this.forEachRule(r, styleRuleCallback, keyframesRuleCallback, onlyActiveRules);
+}
+}
+},
+applyCss: function (cssText, moniker, target, contextNode) {
+var style = this.createScopeStyle(cssText, moniker);
+return this.applyStyle(style, target, contextNode);
+},
+applyStyle: function (style, target, contextNode) {
+target = target || document.head;
+var after = contextNode && contextNode.nextSibling || target.firstChild;
+this.__lastHeadApplyNode = style;
+return target.insertBefore(style, after);
+},
+createScopeStyle: function (cssText, moniker) {
+var style = document.createElement('style');
+if (moniker) {
+style.setAttribute('scope', moniker);
+}
+style.textContent = cssText;
+return style;
+},
+__lastHeadApplyNode: null,
+applyStylePlaceHolder: function (moniker) {
+var placeHolder = document.createComment(' Shady DOM styles for ' + moniker + ' ');
+var after = this.__lastHeadApplyNode ? this.__lastHeadApplyNode.nextSibling : null;
+var scope = document.head;
+scope.insertBefore(placeHolder, after || scope.firstChild);
+this.__lastHeadApplyNode = placeHolder;
+return placeHolder;
+},
+cssFromModules: function (moduleIds, warnIfNotFound) {
+var modules = moduleIds.trim().split(/\s+/);
+var cssText = '';
+for (var i = 0; i < modules.length; i++) {
+cssText += this.cssFromModule(modules[i], warnIfNotFound);
+}
+return cssText;
+},
+cssFromModule: function (moduleId, warnIfNotFound) {
+var m = Polymer.DomModule.import(moduleId);
+if (m && !m._cssText) {
+m._cssText = this.cssFromElement(m);
+}
+if (!m && warnIfNotFound) {
+console.warn('Could not find style data in module named', moduleId);
+}
+return m && m._cssText || '';
+},
+cssFromElement: function (element) {
+var cssText = '';
+var content = element.content || element;
+var e$ = Polymer.TreeApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_SELECTOR));
+for (var i = 0, e; i < e$.length; i++) {
+e = e$[i];
+if (e.localName === 'template') {
+if (!e.hasAttribute('preserve-content')) {
+cssText += this.cssFromElement(e);
+}
+} else {
+if (e.localName === 'style') {
+var include = e.getAttribute(this.INCLUDE_ATTR);
+if (include) {
+cssText += this.cssFromModules(include, true);
+}
+e = e.__appliedElement || e;
+e.parentNode.removeChild(e);
+var css = this.resolveCss(e.textContent, element.ownerDocument);
+if (!settings.useNativeShadow && e.hasAttribute(this.SHADY_UNSCOPED_ATTR)) {
+e.textContent = css;
+document.head.insertBefore(e, document.head.firstChild);
+} else {
+cssText += css;
+}
+} else if (e.import && e.import.body) {
+var importCss = this.resolveCss(e.import.body.textContent, e.import);
+if (!settings.useNativeShadow && e.hasAttribute(this.SHADY_UNSCOPED_ATTR)) {
+if (!this.unscopedStyleImports.has(e.import)) {
+this.unscopedStyleImports.set(e.import, true);
+var importStyle = document.createElement('style');
+importStyle.setAttribute(this.SHADY_UNSCOPED_ATTR, '');
+importStyle.textContent = importCss;
+document.head.insertBefore(importStyle, document.head.firstChild);
+}
+} else {
+cssText += importCss;
+}
+}
+}
+}
+return cssText;
+},
+styleIncludesToTemplate: function (targetTemplate) {
+var styles = targetTemplate.content.querySelectorAll('style[include]');
+for (var i = 0, s; i < styles.length; i++) {
+s = styles[i];
+s.parentNode.insertBefore(this._includesToFragment(s.getAttribute('include')), s);
+}
+},
+_includesToFragment: function (styleIncludes) {
+var includeArray = styleIncludes.trim().split(' ');
+var frag = document.createDocumentFragment();
+for (var i = 0; i < includeArray.length; i++) {
+var t = Polymer.DomModule.import(includeArray[i], 'template');
+if (t) {
+this._addStylesToFragment(frag, t.content);
+}
+}
+return frag;
+},
+_addStylesToFragment: function (frag, source) {
+var s$ = source.querySelectorAll('style');
+for (var i = 0, s; i < s$.length; i++) {
+s = s$[i];
+var include = s.getAttribute('include');
+if (include) {
+frag.appendChild(this._includesToFragment(include));
+}
+if (s.textContent) {
+frag.appendChild(s.cloneNode(true));
+}
+}
+},
+isTargetedBuild: function (buildType) {
+return settings.useNativeShadow ? buildType === 'shadow' : buildType === 'shady';
+},
+cssBuildTypeForModule: function (module) {
+var dm = Polymer.DomModule.import(module);
+if (dm) {
+return this.getCssBuildType(dm);
+}
+},
+getCssBuildType: function (element) {
+return element.getAttribute('css-build');
+},
+_findMatchingParen: function (text, start) {
+var level = 0;
+for (var i = start, l = text.length; i < l; i++) {
+switch (text[i]) {
+case '(':
+level++;
+break;
+case ')':
+if (--level === 0) {
+return i;
+}
+break;
+}
+}
+return -1;
+},
+processVariableAndFallback: function (str, callback) {
+var start = str.indexOf('var(');
+if (start === -1) {
+return callback(str, '', '', '');
+}
+var end = this._findMatchingParen(str, start + 3);
+var inner = str.substring(start + 4, end);
+var prefix = str.substring(0, start);
+var suffix = this.processVariableAndFallback(str.substring(end + 1), callback);
+var comma = inner.indexOf(',');
+if (comma === -1) {
+return callback(prefix, inner.trim(), '', suffix);
+}
+var value = inner.substring(0, comma).trim();
+var fallback = inner.substring(comma + 1).trim();
+return callback(prefix, value, fallback, suffix);
+},
+rx: {
+VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi,
+MIXIN_MATCH: /(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi,
+VAR_CONSUMED: /(--[\w-]+)\s*([:,;)]|$)/gi,
+ANIMATION_MATCH: /(animation\s*:)|(animation-name\s*:)/,
+MEDIA_MATCH: /@media[^(]*(\([^)]*\))/,
+IS_VAR: /^--/,
+BRACKETED: /\{[^}]*\}/g,
+HOST_PREFIX: '(?:^|[^.#[:])',
+HOST_SUFFIX: '($|[.:[\\s>+~])'
+},
+resolveCss: Polymer.ResolveUrl.resolveCss,
+parser: Polymer.CssParse,
+ruleTypes: Polymer.CssParse.types
+};
+}();Polymer.StyleTransformer = function () {
+var styleUtil = Polymer.StyleUtil;
+var settings = Polymer.Settings;
+var api = {
+dom: function (node, scope, useAttr, shouldRemoveScope) {
+this._transformDom(node, scope || '', useAttr, shouldRemoveScope);
+},
+_transformDom: function (node, selector, useAttr, shouldRemoveScope) {
+if (node.setAttribute) {
+this.element(node, selector, useAttr, shouldRemoveScope);
+}
+var c$ = Polymer.dom(node).childNodes;
+for (var i = 0; i < c$.length; i++) {
+this._transformDom(c$[i], selector, useAttr, shouldRemoveScope);
+}
+},
+element: function (element, scope, useAttr, shouldRemoveScope) {
+if (useAttr) {
+if (shouldRemoveScope) {
+element.removeAttribute(SCOPE_NAME);
+} else {
+element.setAttribute(SCOPE_NAME, scope);
+}
+} else {
+if (scope) {
+if (element.classList) {
+if (shouldRemoveScope) {
+element.classList.remove(SCOPE_NAME);
+element.classList.remove(scope);
+} else {
+element.classList.add(SCOPE_NAME);
+element.classList.add(scope);
+}
+} else if (element.getAttribute) {
+var c = element.getAttribute(CLASS);
+if (shouldRemoveScope) {
+if (c) {
+element.setAttribute(CLASS, c.replace(SCOPE_NAME, '').replace(scope, ''));
+}
+} else {
+element.setAttribute(CLASS, (c ? c + ' ' : '') + SCOPE_NAME + ' ' + scope);
+}
+}
+}
+}
+},
+elementStyles: function (element, callback) {
+var styles = element._styles;
+var cssText = '';
+var cssBuildType = element.__cssBuild;
+var passthrough = settings.useNativeShadow || cssBuildType === 'shady';
+var cb;
+if (passthrough) {
+var self = this;
+cb = function (rule) {
+rule.selector = self._slottedToContent(rule.selector);
+rule.selector = rule.selector.replace(ROOT, ':host > *');
+rule.selector = self._dirShadowTransform(rule.selector);
+if (callback) {
+callback(rule);
+}
+};
+}
+for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
+var rules = styleUtil.rulesForStyle(s);
+cssText += passthrough ? styleUtil.toCssText(rules, cb) : this.css(rules, element.is, element.extends, callback, element._scopeCssViaAttr) + '\n\n';
+}
+return cssText.trim();
+},
+css: function (rules, scope, ext, callback, useAttr) {
+var hostScope = this._calcHostScope(scope, ext);
+scope = this._calcElementScope(scope, useAttr);
+var self = this;
+return styleUtil.toCssText(rules, function (rule) {
+if (!rule.isScoped) {
+self.rule(rule, scope, hostScope);
+rule.isScoped = true;
+}
+if (callback) {
+callback(rule, scope, hostScope);
+}
+});
+},
+_calcElementScope: function (scope, useAttr) {
+if (scope) {
+return useAttr ? CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : CSS_CLASS_PREFIX + scope;
+} else {
+return '';
+}
+},
+_calcHostScope: function (scope, ext) {
+return ext ? '[is=' + scope + ']' : scope;
+},
+rule: function (rule, scope, hostScope) {
+this._transformRule(rule, this._transformComplexSelector, scope, hostScope);
+},
+_transformRule: function (rule, transformer, scope, hostScope) {
+rule.selector = rule.transformedSelector = this._transformRuleCss(rule, transformer, scope, hostScope);
+},
+_splitSelectorList: function (selector) {
+var parts = [];
+var part = '';
+for (var i = 0; i >= 0 && i < selector.length; i++) {
+if (selector[i] === '(') {
+var end = styleUtil._findMatchingParen(selector, i);
+part += selector.slice(i, end + 1);
+i = end;
+} else if (selector[i] === COMPLEX_SELECTOR_SEP) {
+parts.push(part);
+part = '';
+} else {
+part += selector[i];
+}
+}
+if (part) {
+parts.push(part);
+}
+if (parts.length === 0) {
+parts.push(selector);
+}
+return parts;
+},
+_transformRuleCss: function (rule, transformer, scope, hostScope) {
+var p$ = this._splitSelectorList(rule.selector);
+if (!styleUtil.isKeyframesSelector(rule)) {
+for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
+p$[i] = transformer.call(this, p, scope, hostScope);
+}
+}
+return p$.join(COMPLEX_SELECTOR_SEP);
+},
+_ensureScopedDir: function (s) {
+var m = s.match(DIR_PAREN);
+if (m && m[1] === '' && m[0].length === s.length) {
+s = '*' + s;
+}
+return s;
+},
+_additionalDirSelectors: function (dir, after, prefix) {
+if (!dir || !after) {
+return '';
+}
+prefix = prefix || '';
+return COMPLEX_SELECTOR_SEP + prefix + ' ' + dir + ' ' + after;
+},
+_transformComplexSelector: function (selector, scope, hostScope) {
+var stop = false;
+var hostContext = false;
+var dir = false;
+var self = this;
+selector = selector.trim();
+selector = this._slottedToContent(selector);
+selector = selector.replace(ROOT, ':host > *');
+selector = selector.replace(CONTENT_START, HOST + ' $1');
+selector = this._ensureScopedDir(selector);
+selector = selector.replace(SIMPLE_SELECTOR_SEP, function (m, c, s) {
+if (!stop) {
+var info = self._transformCompoundSelector(s, c, scope, hostScope);
+stop = stop || info.stop;
+hostContext = hostContext || info.hostContext;
+dir = dir || info.dir;
+c = info.combinator;
+s = info.value;
+} else {
+s = s.replace(SCOPE_JUMP, ' ');
+}
+return c + s;
+});
+if (hostContext) {
+selector = selector.replace(HOST_CONTEXT_PAREN, function (m, pre, paren, post) {
+var replacement = pre + paren + ' ' + hostScope + post + COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post;
+if (dir) {
+replacement += self._additionalDirSelectors(paren, post, hostScope);
+}
+return replacement;
+});
+}
+return selector;
+},
+_transformDir: function (s) {
+s = s.replace(HOST_DIR, HOST_DIR_REPLACE);
+s = s.replace(DIR_PAREN, DIR_REPLACE);
+return s;
+},
+_transformCompoundSelector: function (selector, combinator, scope, hostScope) {
+var jumpIndex = selector.search(SCOPE_JUMP);
+var hostContext = false;
+var dir = false;
+if (selector.match(DIR_PAREN)) {
+selector = this._transformDir(selector);
+dir = true;
+}
+if (selector.indexOf(HOST_CONTEXT) >= 0) {
+hostContext = true;
+} else if (selector.indexOf(HOST) >= 0) {
+selector = this._transformHostSelector(selector, hostScope);
+} else if (jumpIndex !== 0) {
+selector = scope ? this._transformSimpleSelector(selector, scope) : selector;
+}
+if (selector.indexOf(CONTENT) >= 0) {
+combinator = '';
+}
+var stop;
+if (jumpIndex >= 0) {
+selector = selector.replace(SCOPE_JUMP, ' ');
+stop = true;
+}
+return {
+value: selector,
+combinator: combinator,
+stop: stop,
+hostContext: hostContext,
+dir: dir
+};
+},
+_transformSimpleSelector: function (selector, scope) {
+var p$ = selector.split(PSEUDO_PREFIX);
+p$[0] += scope;
+return p$.join(PSEUDO_PREFIX);
+},
+_transformHostSelector: function (selector, hostScope) {
+var m = selector.match(HOST_PAREN);
+var paren = m && m[2].trim() || '';
+if (paren) {
+if (!paren[0].match(SIMPLE_SELECTOR_PREFIX)) {
+var typeSelector = paren.split(SIMPLE_SELECTOR_PREFIX)[0];
+if (typeSelector === hostScope) {
+return paren;
+} else {
+return SELECTOR_NO_MATCH;
+}
+} else {
+return selector.replace(HOST_PAREN, function (m, host, paren) {
+return hostScope + paren;
+});
+}
+} else {
+return selector.replace(HOST, hostScope);
+}
+},
+documentRule: function (rule) {
+rule.selector = rule.parsedSelector;
+this.normalizeRootSelector(rule);
+if (!settings.useNativeShadow) {
+this._transformRule(rule, this._transformDocumentSelector);
+}
+},
+normalizeRootSelector: function (rule) {
+rule.selector = rule.selector.replace(ROOT, 'html');
+var parts = this._splitSelectorList(rule.selector);
+parts = parts.filter(function (part) {
+return !part.match(HOST_OR_HOST_GT_STAR);
+});
+rule.selector = parts.join(COMPLEX_SELECTOR_SEP);
+},
+_transformDocumentSelector: function (selector) {
+return this._transformComplexSelector(selector, SCOPE_DOC_SELECTOR);
+},
+_slottedToContent: function (cssText) {
+return cssText.replace(SLOTTED_PAREN, CONTENT + '> $1');
+},
+_dirShadowTransform: function (selector) {
+if (!selector.match(/:dir\(/)) {
+return selector;
+}
+return this._splitSelectorList(selector).map(function (s) {
+s = this._ensureScopedDir(s);
+s = this._transformDir(s);
+var m = HOST_CONTEXT_PAREN.exec(s);
+if (m) {
+s += this._additionalDirSelectors(m[2], m[3], '');
+}
+return s;
+}, this).join(COMPLEX_SELECTOR_SEP);
+},
+SCOPE_NAME: 'style-scope'
+};
+var SCOPE_NAME = api.SCOPE_NAME;
+var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' + ':not(.' + SCOPE_NAME + ')';
+var COMPLEX_SELECTOR_SEP = ',';
+var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g;
+var SIMPLE_SELECTOR_PREFIX = /[[.:#*]/;
+var HOST = ':host';
+var ROOT = ':root';
+var HOST_PAREN = /(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/;
+var HOST_CONTEXT = ':host-context';
+var HOST_CONTEXT_PAREN = /(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;
+var CONTENT = '::content';
+var SCOPE_JUMP = /::content|::shadow|\/deep\//;
+var CSS_CLASS_PREFIX = '.';
+var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~=';
+var CSS_ATTR_SUFFIX = ']';
+var PSEUDO_PREFIX = ':';
+var CLASS = 'class';
+var CONTENT_START = new RegExp('^(' + CONTENT + ')');
+var SELECTOR_NO_MATCH = 'should_not_match';
+var SLOTTED_PAREN = /(?:::slotted)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
+var HOST_OR_HOST_GT_STAR = /:host(?:\s*>\s*\*)?/;
+var DIR_PAREN = /(.*):dir\((ltr|rtl)\)/;
+var DIR_REPLACE = ':host-context([dir="$2"]) $1';
+var HOST_DIR = /:host\(:dir\((rtl|ltr)\)\)/g;
+var HOST_DIR_REPLACE = ':host-context([dir="$1"])';
+return api;
+}();Polymer.StyleExtends = function () {
+var styleUtil = Polymer.StyleUtil;
+return {
+hasExtends: function (cssText) {
+return Boolean(cssText.match(this.rx.EXTEND));
+},
+transform: function (style) {
+var rules = styleUtil.rulesForStyle(style);
+var self = this;
+styleUtil.forEachRule(rules, function (rule) {
+self._mapRuleOntoParent(rule);
+if (rule.parent) {
+var m;
+while (m = self.rx.EXTEND.exec(rule.cssText)) {
+var extend = m[1];
+var extendor = self._findExtendor(extend, rule);
+if (extendor) {
+self._extendRule(rule, extendor);
+}
+}
+}
+rule.cssText = rule.cssText.replace(self.rx.EXTEND, '');
+});
+return styleUtil.toCssText(rules, function (rule) {
+if (rule.selector.match(self.rx.STRIP)) {
+rule.cssText = '';
+}
+}, true);
+},
+_mapRuleOntoParent: function (rule) {
+if (rule.parent) {
+var map = rule.parent.map || (rule.parent.map = {});
+var parts = rule.selector.split(',');
+for (var i = 0, p; i < parts.length; i++) {
+p = parts[i];
+map[p.trim()] = rule;
+}
+return map;
+}
+},
+_findExtendor: function (extend, rule) {
+return rule.parent && rule.parent.map && rule.parent.map[extend] || this._findExtendor(extend, rule.parent);
+},
+_extendRule: function (target, source) {
+if (target.parent !== source.parent) {
+this._cloneAndAddRuleToParent(source, target.parent);
+}
+target.extends = target.extends || [];
+target.extends.push(source);
+source.selector = source.selector.replace(this.rx.STRIP, '');
+source.selector = (source.selector && source.selector + ',\n') + target.selector;
+if (source.extends) {
+source.extends.forEach(function (e) {
+this._extendRule(target, e);
+}, this);
+}
+},
+_cloneAndAddRuleToParent: function (rule, parent) {
+rule = Object.create(rule);
+rule.parent = parent;
+if (rule.extends) {
+rule.extends = rule.extends.slice();
+}
+parent.rules.push(rule);
+},
+rx: {
+EXTEND: /@extends\(([^)]*)\)\s*?;/gim,
+STRIP: /%[^,]*$/
+}
+};
+}();Polymer.ApplyShim = function () {
+'use strict';
+var styleUtil = Polymer.StyleUtil;
+var MIXIN_MATCH = styleUtil.rx.MIXIN_MATCH;
+var VAR_ASSIGN = styleUtil.rx.VAR_ASSIGN;
+var BAD_VAR = /var\(\s*(--[^,]*),\s*(--[^)]*)\)/g;
+var APPLY_NAME_CLEAN = /;\s*/m;
+var INITIAL_INHERIT = /^\s*(initial)|(inherit)\s*$/;
+var MIXIN_VAR_SEP = '_-_';
+var mixinMap = {};
+function mapSet(name, props) {
+name = name.trim();
+mixinMap[name] = {
+properties: props,
+dependants: {}
+};
+}
+function mapGet(name) {
+name = name.trim();
+return mixinMap[name];
+}
+function replaceInitialOrInherit(property, value) {
+var match = INITIAL_INHERIT.exec(value);
+if (match) {
+if (match[1]) {
+value = ApplyShim._getInitialValueForProperty(property);
+} else {
+value = 'apply-shim-inherit';
+}
+}
+return value;
+}
+function cssTextToMap(text) {
+var props = text.split(';');
+var property, value;
+var out = {};
+for (var i = 0, p, sp; i < props.length; i++) {
+p = props[i];
+if (p) {
+sp = p.split(':');
+if (sp.length > 1) {
+property = sp[0].trim();
+value = replaceInitialOrInherit(property, sp.slice(1).join(':'));
+out[property] = value;
+}
+}
+}
+return out;
+}
+function invalidateMixinEntry(mixinEntry) {
+var currentProto = ApplyShim.__currentElementProto;
+var currentElementName = currentProto && currentProto.is;
+for (var elementName in mixinEntry.dependants) {
+if (elementName !== currentElementName) {
+mixinEntry.dependants[elementName].__applyShimInvalid = true;
+}
+}
+}
+function produceCssProperties(matchText, propertyName, valueProperty, valueMixin) {
+if (valueProperty) {
+styleUtil.processVariableAndFallback(valueProperty, function (prefix, value) {
+if (value && mapGet(value)) {
+valueMixin = '@apply ' + value + ';';
+}
+});
+}
+if (!valueMixin) {
+return matchText;
+}
+var mixinAsProperties = consumeCssProperties(valueMixin);
+var prefix = matchText.slice(0, matchText.indexOf('--'));
+var mixinValues = cssTextToMap(mixinAsProperties);
+var combinedProps = mixinValues;
+var mixinEntry = mapGet(propertyName);
+var oldProps = mixinEntry && mixinEntry.properties;
+if (oldProps) {
+combinedProps = Object.create(oldProps);
+combinedProps = Polymer.Base.mixin(combinedProps, mixinValues);
+} else {
+mapSet(propertyName, combinedProps);
+}
+var out = [];
+var p, v;
+var needToInvalidate = false;
+for (p in combinedProps) {
+v = mixinValues[p];
+if (v === undefined) {
+v = 'initial';
+}
+if (oldProps && !(p in oldProps)) {
+needToInvalidate = true;
+}
+out.push(propertyName + MIXIN_VAR_SEP + p + ': ' + v);
+}
+if (needToInvalidate) {
+invalidateMixinEntry(mixinEntry);
+}
+if (mixinEntry) {
+mixinEntry.properties = combinedProps;
+}
+if (valueProperty) {
+prefix = matchText + ';' + prefix;
+}
+return prefix + out.join('; ') + ';';
+}
+function fixVars(matchText, varA, varB) {
+return 'var(' + varA + ',' + 'var(' + varB + '))';
+}
+function atApplyToCssProperties(mixinName, fallbacks) {
+mixinName = mixinName.replace(APPLY_NAME_CLEAN, '');
+var vars = [];
+var mixinEntry = mapGet(mixinName);
+if (!mixinEntry) {
+mapSet(mixinName, {});
+mixinEntry = mapGet(mixinName);
+}
+if (mixinEntry) {
+var currentProto = ApplyShim.__currentElementProto;
+if (currentProto) {
+mixinEntry.dependants[currentProto.is] = currentProto;
+}
+var p, parts, f;
+for (p in mixinEntry.properties) {
+f = fallbacks && fallbacks[p];
+parts = [
+p,
+': var(',
+mixinName,
+MIXIN_VAR_SEP,
+p
+];
+if (f) {
+parts.push(',', f);
+}
+parts.push(')');
+vars.push(parts.join(''));
+}
+}
+return vars.join('; ');
+}
+function consumeCssProperties(text) {
+var m;
+while (m = MIXIN_MATCH.exec(text)) {
+var matchText = m[0];
+var mixinName = m[1];
+var idx = m.index;
+var applyPos = idx + matchText.indexOf('@apply');
+var afterApplyPos = idx + matchText.length;
+var textBeforeApply = text.slice(0, applyPos);
+var textAfterApply = text.slice(afterApplyPos);
+var defaults = cssTextToMap(textBeforeApply);
+var replacement = atApplyToCssProperties(mixinName, defaults);
+text = [
+textBeforeApply,
+replacement,
+textAfterApply
+].join('');
+MIXIN_MATCH.lastIndex = idx + replacement.length;
+}
+return text;
+}
+var ApplyShim = {
+_measureElement: null,
+_map: mixinMap,
+_separator: MIXIN_VAR_SEP,
+transform: function (styles, elementProto) {
+this.__currentElementProto = elementProto;
+styleUtil.forRulesInStyles(styles, this._boundFindDefinitions);
+styleUtil.forRulesInStyles(styles, this._boundFindApplications);
+if (elementProto) {
+elementProto.__applyShimInvalid = false;
+}
+this.__currentElementProto = null;
+},
+_findDefinitions: function (rule) {
+var cssText = rule.parsedCssText;
+cssText = cssText.replace(BAD_VAR, fixVars);
+cssText = cssText.replace(VAR_ASSIGN, produceCssProperties);
+rule.cssText = cssText;
+if (rule.selector === ':root') {
+rule.selector = ':host > *';
+}
+},
+_findApplications: function (rule) {
+rule.cssText = consumeCssProperties(rule.cssText);
+},
+transformRule: function (rule) {
+this._findDefinitions(rule);
+this._findApplications(rule);
+},
+_getInitialValueForProperty: function (property) {
+if (!this._measureElement) {
+this._measureElement = document.createElement('meta');
+this._measureElement.style.all = 'initial';
+document.head.appendChild(this._measureElement);
+}
+return window.getComputedStyle(this._measureElement).getPropertyValue(property);
+}
+};
+ApplyShim._boundTransformRule = ApplyShim.transformRule.bind(ApplyShim);
+ApplyShim._boundFindDefinitions = ApplyShim._findDefinitions.bind(ApplyShim);
+ApplyShim._boundFindApplications = ApplyShim._findApplications.bind(ApplyShim);
+return ApplyShim;
+}();(function () {
+var prepElement = Polymer.Base._prepElement;
+var nativeShadow = Polymer.Settings.useNativeShadow;
+var styleUtil = Polymer.StyleUtil;
+var styleTransformer = Polymer.StyleTransformer;
+var styleExtends = Polymer.StyleExtends;
+var applyShim = Polymer.ApplyShim;
+var settings = Polymer.Settings;
+Polymer.Base._addFeature({
+_prepElement: function (element) {
+if (this._encapsulateStyle && this.__cssBuild !== 'shady') {
+styleTransformer.element(element, this.is, this._scopeCssViaAttr);
+}
+prepElement.call(this, element);
+},
+_prepStyles: function () {
+if (this._encapsulateStyle === undefined) {
+this._encapsulateStyle = !nativeShadow;
+}
+if (!nativeShadow) {
+this._scopeStyle = styleUtil.applyStylePlaceHolder(this.is);
+}
+this.__cssBuild = styleUtil.cssBuildTypeForModule(this.is);
+},
+_prepShimStyles: function () {
+if (this._template) {
+var hasTargetedCssBuild = styleUtil.isTargetedBuild(this.__cssBuild);
+if (settings.useNativeCSSProperties && this.__cssBuild === 'shadow' && hasTargetedCssBuild) {
+if (settings.preserveStyleIncludes) {
+styleUtil.styleIncludesToTemplate(this._template);
+}
+return;
+}
+this._styles = this._styles || this._collectStyles();
+if (settings.useNativeCSSProperties && !this.__cssBuild) {
+applyShim.transform(this._styles, this);
+}
+var cssText = settings.useNativeCSSProperties && hasTargetedCssBuild ? this._styles.length && this._styles[0].textContent.trim() : styleTransformer.elementStyles(this);
+this._prepStyleProperties();
+if (!this._needsStyleProperties() && cssText) {
+styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.content : null, this._scopeStyle);
+}
+} else {
+this._styles = [];
+}
+},
+_collectStyles: function () {
+var styles = [];
+var cssText = '', m$ = this.styleModules;
+if (m$) {
+for (var i = 0, l = m$.length, m; i < l && (m = m$[i]); i++) {
+cssText += styleUtil.cssFromModule(m);
+}
+}
+cssText += styleUtil.cssFromModule(this.is);
+var p = this._template && this._template.parentNode;
+if (this._template && (!p || p.id.toLowerCase() !== this.is)) {
+cssText += styleUtil.cssFromElement(this._template);
+}
+if (cssText) {
+var style = document.createElement('style');
+style.textContent = cssText;
+if (styleExtends.hasExtends(style.textContent)) {
+cssText = styleExtends.transform(style);
+}
+styles.push(style);
+}
+return styles;
+},
+_elementAdd: function (node) {
+if (this._encapsulateStyle) {
+if (node.__styleScoped) {
+node.__styleScoped = false;
+} else {
+styleTransformer.dom(node, this.is, this._scopeCssViaAttr);
+}
+}
+},
+_elementRemove: function (node) {
+if (this._encapsulateStyle) {
+styleTransformer.dom(node, this.is, this._scopeCssViaAttr, true);
+}
+},
+scopeSubtree: function (container, shouldObserve) {
+if (nativeShadow) {
+return;
+}
+var self = this;
+var scopify = function (node) {
+if (node.nodeType === Node.ELEMENT_NODE) {
+var className = node.getAttribute('class');
+node.setAttribute('class', self._scopeElementClass(node, className));
+var n$ = node.querySelectorAll('*');
+for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
+className = n.getAttribute('class');
+n.setAttribute('class', self._scopeElementClass(n, className));
+}
+}
+};
+scopify(container);
+if (shouldObserve) {
+var mo = new MutationObserver(function (mxns) {
+for (var i = 0, m; i < mxns.length && (m = mxns[i]); i++) {
+if (m.addedNodes) {
+for (var j = 0; j < m.addedNodes.length; j++) {
+scopify(m.addedNodes[j]);
+}
+}
+}
+});
+mo.observe(container, {
+childList: true,
+subtree: true
+});
+return mo;
+}
+}
+});
+}());Polymer.StyleProperties = function () {
+'use strict';
+var matchesSelector = Polymer.DomApi.matchesSelector;
+var styleUtil = Polymer.StyleUtil;
+var styleTransformer = Polymer.StyleTransformer;
+var IS_IE = navigator.userAgent.match('Trident');
+var settings = Polymer.Settings;
+return {
+decorateStyles: function (styles, scope) {
+var self = this, props = {}, keyframes = [], ruleIndex = 0;
+var scopeSelector = styleTransformer._calcHostScope(scope.is, scope.extends);
+styleUtil.forRulesInStyles(styles, function (rule, style) {
+self.decorateRule(rule);
+rule.index = ruleIndex++;
+self.whenHostOrRootRule(scope, rule, style, function (info) {
+if (rule.parent.type === styleUtil.ruleTypes.MEDIA_RULE) {
+scope.__notStyleScopeCacheable = true;
+}
+if (info.isHost) {
+var hostContextOrFunction = info.selector.split(' ').some(function (s) {
+return s.indexOf(scopeSelector) === 0 && s.length !== scopeSelector.length;
+});
+scope.__notStyleScopeCacheable = scope.__notStyleScopeCacheable || hostContextOrFunction;
+}
+});
+self.collectPropertiesInCssText(rule.propertyInfo.cssText, props);
+}, function onKeyframesRule(rule) {
+keyframes.push(rule);
+});
+styles._keyframes = keyframes;
+var names = [];
+for (var i in props) {
+names.push(i);
+}
+return names;
+},
+decorateRule: function (rule) {
+if (rule.propertyInfo) {
+return rule.propertyInfo;
+}
+var info = {}, properties = {};
+var hasProperties = this.collectProperties(rule, properties);
+if (hasProperties) {
+info.properties = properties;
+rule.rules = null;
+}
+info.cssText = this.collectCssText(rule);
+rule.propertyInfo = info;
+return info;
+},
+collectProperties: function (rule, properties) {
+var info = rule.propertyInfo;
+if (info) {
+if (info.properties) {
+Polymer.Base.mixin(properties, info.properties);
+return true;
+}
+} else {
+var m, rx = this.rx.VAR_ASSIGN;
+var cssText = rule.parsedCssText;
+var value;
+var any;
+while (m = rx.exec(cssText)) {
+value = (m[2] || m[3]).trim();
+if (value !== 'inherit') {
+properties[m[1].trim()] = value;
+}
+any = true;
+}
+return any;
+}
+},
+collectCssText: function (rule) {
+return this.collectConsumingCssText(rule.parsedCssText);
+},
+collectConsumingCssText: function (cssText) {
+return cssText.replace(this.rx.BRACKETED, '').replace(this.rx.VAR_ASSIGN, '');
+},
+collectPropertiesInCssText: function (cssText, props) {
+var m;
+while (m = this.rx.VAR_CONSUMED.exec(cssText)) {
+var name = m[1];
+if (m[2] !== ':') {
+props[name] = true;
+}
+}
+},
+reify: function (props) {
+var names = Object.getOwnPropertyNames(props);
+for (var i = 0, n; i < names.length; i++) {
+n = names[i];
+props[n] = this.valueForProperty(props[n], props);
+}
+},
+valueForProperty: function (property, props) {
+if (property) {
+if (property.indexOf(';') >= 0) {
+property = this.valueForProperties(property, props);
+} else {
+var self = this;
+var fn = function (prefix, value, fallback, suffix) {
+var propertyValue = self.valueForProperty(props[value], props);
+if (!propertyValue || propertyValue === 'initial') {
+propertyValue = self.valueForProperty(props[fallback] || fallback, props) || fallback;
+} else if (propertyValue === 'apply-shim-inherit') {
+propertyValue = 'inherit';
+}
+return prefix + (propertyValue || '') + suffix;
+};
+property = styleUtil.processVariableAndFallback(property, fn);
+}
+}
+return property && property.trim() || '';
+},
+valueForProperties: function (property, props) {
+var parts = property.split(';');
+for (var i = 0, p, m; i < parts.length; i++) {
+if (p = parts[i]) {
+this.rx.MIXIN_MATCH.lastIndex = 0;
+m = this.rx.MIXIN_MATCH.exec(p);
+if (m) {
+p = this.valueForProperty(props[m[1]], props);
+} else {
+var colon = p.indexOf(':');
+if (colon !== -1) {
+var pp = p.substring(colon);
+pp = pp.trim();
+pp = this.valueForProperty(pp, props) || pp;
+p = p.substring(0, colon) + pp;
+}
+}
+parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || '';
+}
+}
+return parts.join(';');
+},
+applyProperties: function (rule, props) {
+var output = '';
+if (!rule.propertyInfo) {
+this.decorateRule(rule);
+}
+if (rule.propertyInfo.cssText) {
+output = this.valueForProperties(rule.propertyInfo.cssText, props);
+}
+rule.cssText = output;
+},
+applyKeyframeTransforms: function (rule, keyframeTransforms) {
+var input = rule.cssText;
+var output = rule.cssText;
+if (rule.hasAnimations == null) {
+rule.hasAnimations = this.rx.ANIMATION_MATCH.test(input);
+}
+if (rule.hasAnimations) {
+var transform;
+if (rule.keyframeNamesToTransform == null) {
+rule.keyframeNamesToTransform = [];
+for (var keyframe in keyframeTransforms) {
+transform = keyframeTransforms[keyframe];
+output = transform(input);
+if (input !== output) {
+input = output;
+rule.keyframeNamesToTransform.push(keyframe);
+}
+}
+} else {
+for (var i = 0; i < rule.keyframeNamesToTransform.length; ++i) {
+transform = keyframeTransforms[rule.keyframeNamesToTransform[i]];
+input = transform(input);
+}
+output = input;
+}
+}
+rule.cssText = output;
+},
+propertyDataFromStyles: function (styles, element) {
+var props = {}, self = this;
+var o = [];
+styleUtil.forActiveRulesInStyles(styles, function (rule) {
+if (!rule.propertyInfo) {
+self.decorateRule(rule);
+}
+var selectorToMatch = rule.transformedSelector || rule.parsedSelector;
+if (element && rule.propertyInfo.properties && selectorToMatch) {
+if (matchesSelector.call(element, selectorToMatch)) {
+self.collectProperties(rule, props);
+addToBitMask(rule.index, o);
+}
+}
+});
+return {
+properties: props,
+key: o
+};
+},
+_rootSelector: /:root|:host\s*>\s*\*/,
+_checkRoot: function (hostScope, selector) {
+return Boolean(selector.match(this._rootSelector)) || hostScope === 'html' && selector.indexOf('html') > -1;
+},
+whenHostOrRootRule: function (scope, rule, style, callback) {
+if (!rule.propertyInfo) {
+self.decorateRule(rule);
+}
+if (!rule.propertyInfo.properties) {
+return;
+}
+var hostScope = scope.is ? styleTransformer._calcHostScope(scope.is, scope.extends) : 'html';
+var parsedSelector = rule.parsedSelector;
+var isRoot = this._checkRoot(hostScope, parsedSelector);
+var isHost = !isRoot && parsedSelector.indexOf(':host') === 0;
+var cssBuild = scope.__cssBuild || style.__cssBuild;
+if (cssBuild === 'shady') {
+isRoot = parsedSelector === hostScope + ' > *.' + hostScope || parsedSelector.indexOf('html') > -1;
+isHost = !isRoot && parsedSelector.indexOf(hostScope) === 0;
+}
+if (!isRoot && !isHost) {
+return;
+}
+var selectorToMatch = hostScope;
+if (isHost) {
+if (settings.useNativeShadow && !rule.transformedSelector) {
+rule.transformedSelector = styleTransformer._transformRuleCss(rule, styleTransformer._transformComplexSelector, scope.is, hostScope);
+}
+selectorToMatch = rule.transformedSelector || rule.parsedSelector;
+}
+if (isRoot && hostScope === 'html') {
+selectorToMatch = rule.transformedSelector || rule.parsedSelector;
+}
+callback({
+selector: selectorToMatch,
+isHost: isHost,
+isRoot: isRoot
+});
+},
+hostAndRootPropertiesForScope: function (scope) {
+var hostProps = {}, rootProps = {}, self = this;
+styleUtil.forActiveRulesInStyles(scope._styles, function (rule, style) {
+self.whenHostOrRootRule(scope, rule, style, function (info) {
+var element = scope._element || scope;
+if (matchesSelector.call(element, info.selector)) {
+if (info.isHost) {
+self.collectProperties(rule, hostProps);
+} else {
+self.collectProperties(rule, rootProps);
+}
+}
+});
+});
+return {
+rootProps: rootProps,
+hostProps: hostProps
+};
+},
+transformStyles: function (element, properties, scopeSelector) {
+var self = this;
+var hostSelector = styleTransformer._calcHostScope(element.is, element.extends);
+var rxHostSelector = element.extends ? '\\' + hostSelector.slice(0, -1) + '\\]' : hostSelector;
+var hostRx = new RegExp(this.rx.HOST_PREFIX + rxHostSelector + this.rx.HOST_SUFFIX);
+var keyframeTransforms = this._elementKeyframeTransforms(element, scopeSelector);
+return styleTransformer.elementStyles(element, function (rule) {
+self.applyProperties(rule, properties);
+if (!settings.useNativeShadow && !Polymer.StyleUtil.isKeyframesSelector(rule) && rule.cssText) {
+self.applyKeyframeTransforms(rule, keyframeTransforms);
+self._scopeSelector(rule, hostRx, hostSelector, element._scopeCssViaAttr, scopeSelector);
+}
+});
+},
+_elementKeyframeTransforms: function (element, scopeSelector) {
+var keyframesRules = element._styles._keyframes;
+var keyframeTransforms = {};
+if (!settings.useNativeShadow && keyframesRules) {
+for (var i = 0, keyframesRule = keyframesRules[i]; i < keyframesRules.length; keyframesRule = keyframesRules[++i]) {
+this._scopeKeyframes(keyframesRule, scopeSelector);
+keyframeTransforms[keyframesRule.keyframesName] = this._keyframesRuleTransformer(keyframesRule);
+}
+}
+return keyframeTransforms;
+},
+_keyframesRuleTransformer: function (keyframesRule) {
+return function (cssText) {
+return cssText.replace(keyframesRule.keyframesNameRx, keyframesRule.transformedKeyframesName);
+};
+},
+_scopeKeyframes: function (rule, scopeId) {
+rule.keyframesNameRx = new RegExp('\\b' + rule.keyframesName + '(?!\\B|-)', 'g');
+rule.transformedKeyframesName = rule.keyframesName + '-' + scopeId;
+rule.transformedSelector = rule.transformedSelector || rule.selector;
+rule.selector = rule.transformedSelector.replace(rule.keyframesName, rule.transformedKeyframesName);
+},
+_hasDirOrHostContext: function (parsedSelector) {
+return /:host-context|:dir/.test(parsedSelector);
+},
+_scopeSelector: function (rule, hostRx, hostSelector, viaAttr, scopeId) {
+rule.transformedSelector = rule.transformedSelector || rule.selector;
+var selector = rule.transformedSelector;
+var scope = styleTransformer._calcElementScope(scopeId, viaAttr);
+var hostScope = styleTransformer._calcElementScope(hostSelector, viaAttr);
+var parts = selector.split(',');
+var isDirOrHostContextSelector = this._hasDirOrHostContext(rule.parsedSelector);
+for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) {
+parts[i] = p.match(hostRx) ? p.replace(hostSelector, scope) : isDirOrHostContextSelector ? p.replace(hostScope, scope + ' ' + hostScope) : scope + ' ' + p;
+}
+rule.selector = parts.join(',');
+},
+applyElementScopeSelector: function (element, selector, old, viaAttr) {
+var c = viaAttr ? element.getAttribute(styleTransformer.SCOPE_NAME) : element.getAttribute('class') || '';
+var v = old ? c.replace(old, selector) : (c ? c + ' ' : '') + this.XSCOPE_NAME + ' ' + selector;
+if (c !== v) {
+if (viaAttr) {
+element.setAttribute(styleTransformer.SCOPE_NAME, v);
+} else {
+element.setAttribute('class', v);
+}
+}
+},
+applyElementStyle: function (element, properties, selector, style) {
+var cssText = style ? style.textContent || '' : this.transformStyles(element, properties, selector);
+var s = element._customStyle;
+if (s && !settings.useNativeShadow && s !== style) {
+s._useCount--;
+if (s._useCount <= 0 && s.parentNode) {
+s.parentNode.removeChild(s);
+}
+}
+if (settings.useNativeShadow) {
+if (element._customStyle) {
+element._customStyle.textContent = cssText;
+style = element._customStyle;
+} else if (cssText) {
+style = styleUtil.applyCss(cssText, selector, element.root, element._scopeStyle);
+}
+} else {
+if (!style) {
+if (cssText) {
+style = styleUtil.applyCss(cssText, selector, null, element._scopeStyle);
+}
+} else if (!style.parentNode) {
+if (IS_IE && cssText.indexOf('@media') > -1) {
+style.textContent = cssText;
+}
+styleUtil.applyStyle(style, null, element._scopeStyle);
+}
+}
+if (style) {
+style._useCount = style._useCount || 0;
+if (element._customStyle != style) {
+style._useCount++;
+}
+element._customStyle = style;
+}
+return style;
+},
+mixinCustomStyle: function (props, customStyle) {
+var v;
+for (var i in customStyle) {
+v = customStyle[i];
+if (v || v === 0) {
+props[i] = v;
+}
+}
+},
+updateNativeStyleProperties: function (element, properties) {
+var oldPropertyNames = element.__customStyleProperties;
+if (oldPropertyNames) {
+for (var i = 0; i < oldPropertyNames.length; i++) {
+element.style.removeProperty(oldPropertyNames[i]);
+}
+}
+var propertyNames = [];
+for (var p in properties) {
+if (properties[p] !== null) {
+element.style.setProperty(p, properties[p]);
+propertyNames.push(p);
+}
+}
+element.__customStyleProperties = propertyNames;
+},
+rx: styleUtil.rx,
+XSCOPE_NAME: 'x-scope'
+};
+function addToBitMask(n, bits) {
+var o = parseInt(n / 32);
+var v = 1 << n % 32;
+bits[o] = (bits[o] || 0) | v;
+}
+}();(function () {
+Polymer.StyleCache = function () {
+this.cache = {};
+};
+Polymer.StyleCache.prototype = {
+MAX: 100,
+store: function (is, data, keyValues, keyStyles) {
+data.keyValues = keyValues;
+data.styles = keyStyles;
+var s$ = this.cache[is] = this.cache[is] || [];
+s$.push(data);
+if (s$.length > this.MAX) {
+s$.shift();
+}
+},
+retrieve: function (is, keyValues, keyStyles) {
+var cache = this.cache[is];
+if (cache) {
+for (var i = cache.length - 1, data; i >= 0; i--) {
+data = cache[i];
+if (keyStyles === data.styles && this._objectsEqual(keyValues, data.keyValues)) {
+return data;
+}
+}
+}
+},
+clear: function () {
+this.cache = {};
+},
+_objectsEqual: function (target, source) {
+var t, s;
+for (var i in target) {
+t = target[i], s = source[i];
+if (!(typeof t === 'object' && t ? this._objectsStrictlyEqual(t, s) : t === s)) {
+return false;
+}
+}
+if (Array.isArray(target)) {
+return target.length === source.length;
+}
+return true;
+},
+_objectsStrictlyEqual: function (target, source) {
+return this._objectsEqual(target, source) && this._objectsEqual(source, target);
+}
+};
+}());Polymer.StyleDefaults = function () {
+var styleProperties = Polymer.StyleProperties;
+var StyleCache = Polymer.StyleCache;
+var nativeVariables = Polymer.Settings.useNativeCSSProperties;
+var api = {
+_styles: [],
+_properties: null,
+customStyle: {},
+_styleCache: new StyleCache(),
+_element: Polymer.DomApi.wrap(document.documentElement),
+addStyle: function (style) {
+this._styles.push(style);
+this._properties = null;
+},
+get _styleProperties() {
+if (!this._properties) {
+styleProperties.decorateStyles(this._styles, this);
+this._styles._scopeStyleProperties = null;
+this._properties = styleProperties.hostAndRootPropertiesForScope(this).rootProps;
+styleProperties.mixinCustomStyle(this._properties, this.customStyle);
+styleProperties.reify(this._properties);
+}
+return this._properties;
+},
+hasStyleProperties: function () {
+return Boolean(this._properties);
+},
+_needsStyleProperties: function () {
+},
+_computeStyleProperties: function () {
+return this._styleProperties;
+},
+updateStyles: function (properties) {
+this._properties = null;
+if (properties) {
+Polymer.Base.mixin(this.customStyle, properties);
+}
+this._styleCache.clear();
+for (var i = 0, s; i < this._styles.length; i++) {
+s = this._styles[i];
+s = s.__importElement || s;
+s._apply();
+}
+if (nativeVariables) {
+styleProperties.updateNativeStyleProperties(document.documentElement, this.customStyle);
+}
+}
+};
+return api;
+}();(function () {
+'use strict';
+var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute;
+var propertyUtils = Polymer.StyleProperties;
+var styleTransformer = Polymer.StyleTransformer;
+var styleDefaults = Polymer.StyleDefaults;
+var nativeShadow = Polymer.Settings.useNativeShadow;
+var nativeVariables = Polymer.Settings.useNativeCSSProperties;
+Polymer.Base._addFeature({
+_prepStyleProperties: function () {
+if (!nativeVariables) {
+this._ownStylePropertyNames = this._styles && this._styles.length ? propertyUtils.decorateStyles(this._styles, this) : null;
+}
+},
+customStyle: null,
+getComputedStyleValue: function (property) {
+if (!nativeVariables && !this._styleProperties) {
+this._computeStyleProperties();
+}
+return !nativeVariables && this._styleProperties && this._styleProperties[property] || getComputedStyle(this).getPropertyValue(property);
+},
+_setupStyleProperties: function () {
+this.customStyle = {};
+this._styleCache = null;
+this._styleProperties = null;
+this._scopeSelector = null;
+this._ownStyleProperties = null;
+this._customStyle = null;
+},
+_needsStyleProperties: function () {
+return Boolean(!nativeVariables && this._ownStylePropertyNames && this._ownStylePropertyNames.length);
+},
+_validateApplyShim: function () {
+if (this.__applyShimInvalid) {
+Polymer.ApplyShim.transform(this._styles, this.__proto__);
+var cssText = styleTransformer.elementStyles(this);
+if (nativeShadow) {
+var templateStyle = this._template.content.querySelector('style');
+if (templateStyle) {
+templateStyle.textContent = cssText;
+}
+} else {
+var shadyStyle = this._scopeStyle && this._scopeStyle.nextSibling;
+if (shadyStyle) {
+shadyStyle.textContent = cssText;
+}
+}
+}
+},
+_beforeAttached: function () {
+if ((!this._scopeSelector || this.__stylePropertiesInvalid) && this._needsStyleProperties()) {
+this.__stylePropertiesInvalid = false;
+this._updateStyleProperties();
+}
+},
+_findStyleHost: function () {
+var e = this, root;
+while (root = Polymer.dom(e).getOwnerRoot()) {
+if (Polymer.isInstance(root.host)) {
+return root.host;
+}
+e = root.host;
+}
+return styleDefaults;
+},
+_updateStyleProperties: function () {
+var info, scope = this._findStyleHost();
+if (!scope._styleProperties) {
+scope._computeStyleProperties();
+}
+if (!scope._styleCache) {
+scope._styleCache = new Polymer.StyleCache();
+}
+var scopeData = propertyUtils.propertyDataFromStyles(scope._styles, this);
+var scopeCacheable = !this.__notStyleScopeCacheable;
+if (scopeCacheable) {
+scopeData.key.customStyle = this.customStyle;
+info = scope._styleCache.retrieve(this.is, scopeData.key, this._styles);
+}
+var scopeCached = Boolean(info);
+if (scopeCached) {
+this._styleProperties = info._styleProperties;
+} else {
+this._computeStyleProperties(scopeData.properties);
+}
+this._computeOwnStyleProperties();
+if (!scopeCached) {
+info = styleCache.retrieve(this.is, this._ownStyleProperties, this._styles);
+}
+var globalCached = Boolean(info) && !scopeCached;
+var style = this._applyStyleProperties(info);
+if (!scopeCached) {
+style = style && nativeShadow ? style.cloneNode(true) : style;
+info = {
+style: style,
+_scopeSelector: this._scopeSelector,
+_styleProperties: this._styleProperties
+};
+if (scopeCacheable) {
+scopeData.key.customStyle = {};
+this.mixin(scopeData.key.customStyle, this.customStyle);
+scope._styleCache.store(this.is, info, scopeData.key, this._styles);
+}
+if (!globalCached) {
+styleCache.store(this.is, Object.create(info), this._ownStyleProperties, this._styles);
+}
+}
+},
+_computeStyleProperties: function (scopeProps) {
+var scope = this._findStyleHost();
+if (!scope._styleProperties) {
+scope._computeStyleProperties();
+}
+var props = Object.create(scope._styleProperties);
+var hostAndRootProps = propertyUtils.hostAndRootPropertiesForScope(this);
+this.mixin(props, hostAndRootProps.hostProps);
+scopeProps = scopeProps || propertyUtils.propertyDataFromStyles(scope._styles, this).properties;
+this.mixin(props, scopeProps);
+this.mixin(props, hostAndRootProps.rootProps);
+propertyUtils.mixinCustomStyle(props, this.customStyle);
+propertyUtils.reify(props);
+this._styleProperties = props;
+},
+_computeOwnStyleProperties: function () {
+var props = {};
+for (var i = 0, n; i < this._ownStylePropertyNames.length; i++) {
+n = this._ownStylePropertyNames[i];
+props[n] = this._styleProperties[n];
+}
+this._ownStyleProperties = props;
+},
+_scopeCount: 0,
+_applyStyleProperties: function (info) {
+var oldScopeSelector = this._scopeSelector;
+this._scopeSelector = info ? info._scopeSelector : this.is + '-' + this.__proto__._scopeCount++;
+var style = propertyUtils.applyElementStyle(this, this._styleProperties, this._scopeSelector, info && info.style);
+if (!nativeShadow) {
+propertyUtils.applyElementScopeSelector(this, this._scopeSelector, oldScopeSelector, this._scopeCssViaAttr);
+}
+return style;
+},
+serializeValueToAttribute: function (value, attribute, node) {
+node = node || this;
+if (attribute === 'class' && !nativeShadow) {
+var host = node === this ? this.domHost || this.dataHost : this;
+if (host) {
+value = host._scopeElementClass(node, value);
+}
+}
+node = this.shadyRoot && this.shadyRoot._hasDistributed ? Polymer.dom(node) : node;
+serializeValueToAttribute.call(this, value, attribute, node);
+},
+_scopeElementClass: function (element, selector) {
+if (!nativeShadow && !this._scopeCssViaAttr) {
+selector = (selector ? selector + ' ' : '') + SCOPE_NAME + ' ' + this.is + (element._scopeSelector ? ' ' + XSCOPE_NAME + ' ' + element._scopeSelector : '');
+}
+return selector;
+},
+updateStyles: function (properties) {
+if (properties) {
+this.mixin(this.customStyle, properties);
+}
+if (nativeVariables) {
+propertyUtils.updateNativeStyleProperties(this, this.customStyle);
+} else {
+if (this.isAttached) {
+if (this._needsStyleProperties()) {
+this._updateStyleProperties();
+} else {
+this._styleProperties = null;
+}
+} else {
+this.__stylePropertiesInvalid = true;
+}
+if (this._styleCache) {
+this._styleCache.clear();
+}
+this._updateRootStyles();
+}
+},
+_updateRootStyles: function (root) {
+root = root || this.root;
+var c$ = Polymer.dom(root)._query(function (e) {
+return e.shadyRoot || e.shadowRoot;
+});
+for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
+if (c.updateStyles) {
+c.updateStyles();
+}
+}
+}
+});
+Polymer.updateStyles = function (properties) {
+styleDefaults.updateStyles(properties);
+Polymer.Base._updateRootStyles(document);
+};
+var styleCache = new Polymer.StyleCache();
+Polymer.customStyleCache = styleCache;
+var SCOPE_NAME = styleTransformer.SCOPE_NAME;
+var XSCOPE_NAME = propertyUtils.XSCOPE_NAME;
+}());Polymer.Base._addFeature({
+_registerFeatures: function () {
+this._prepIs();
+if (this.factoryImpl) {
+this._prepConstructor();
+}
+this._prepStyles();
+},
+_finishRegisterFeatures: function () {
+this._prepTemplate();
+this._prepShimStyles();
+this._prepAnnotations();
+this._prepEffects();
+this._prepBehaviors();
+this._prepPropertyInfo();
+this._prepBindings();
+this._prepShady();
+},
+_prepBehavior: function (b) {
+this._addPropertyEffects(b.properties);
+this._addComplexObserverEffects(b.observers);
+this._addHostAttributes(b.hostAttributes);
+},
+_initFeatures: function () {
+this._setupGestures();
+this._setupConfigure(this.__data__);
+this._setupStyleProperties();
+this._setupDebouncers();
+this._setupShady();
+this._registerHost();
+if (this._template) {
+this._validateApplyShim();
+this._poolContent();
+this._beginHosting();
+this._stampTemplate();
+this._endHosting();
+this._marshalAnnotationReferences();
+}
+this._marshalInstanceEffects();
+this._marshalBehaviors();
+this._marshalHostAttributes();
+this._marshalAttributes();
+this._tryReady();
+},
+_marshalBehavior: function (b) {
+if (b.listeners) {
+this._listenListeners(b.listeners);
+}
+}
+});(function () {
+var propertyUtils = Polymer.StyleProperties;
+var styleUtil = Polymer.StyleUtil;
+var cssParse = Polymer.CssParse;
+var styleDefaults = Polymer.StyleDefaults;
+var styleTransformer = Polymer.StyleTransformer;
+var applyShim = Polymer.ApplyShim;
+var debounce = Polymer.Debounce;
+var settings = Polymer.Settings;
+var updateDebouncer;
+Polymer({
+is: 'custom-style',
+extends: 'style',
+_template: null,
+properties: { include: String },
+ready: function () {
+this.__appliedElement = this.__appliedElement || this;
+this.__cssBuild = styleUtil.getCssBuildType(this);
+if (this.__appliedElement !== this) {
+this.__appliedElement.__cssBuild = this.__cssBuild;
+}
+if (this.ownerDocument !== window.document && this.__appliedElement === this) {
+document.head.appendChild(this);
+}
+this._tryApply();
+},
+attached: function () {
+this._tryApply();
+},
+_tryApply: function () {
+if (!this._appliesToDocument) {
+if (this.parentNode && this.parentNode.localName !== 'dom-module') {
+this._appliesToDocument = true;
+var e = this.__appliedElement;
+if (!settings.useNativeCSSProperties) {
+this.__needsUpdateStyles = styleDefaults.hasStyleProperties();
+styleDefaults.addStyle(e);
+}
+if (e.textContent || this.include) {
+this._apply(true);
+} else {
+var self = this;
+var observer = new MutationObserver(function () {
+observer.disconnect();
+self._apply(true);
+});
+observer.observe(e, { childList: true });
+}
+}
+}
+},
+_updateStyles: function () {
+Polymer.updateStyles();
+},
+_apply: function (initialApply) {
+var e = this.__appliedElement;
+if (this.include) {
+e.textContent = styleUtil.cssFromModules(this.include, true) + e.textContent;
+}
+if (!e.textContent) {
+return;
+}
+var buildType = this.__cssBuild;
+var targetedBuild = styleUtil.isTargetedBuild(buildType);
+if (settings.useNativeCSSProperties && targetedBuild) {
+return;
+}
+var styleRules = styleUtil.rulesForStyle(e);
+if (!targetedBuild) {
+styleUtil.forEachRule(styleRules, function (rule) {
+styleTransformer.documentRule(rule);
+});
+if (settings.useNativeCSSProperties && !buildType) {
+applyShim.transform([e]);
+}
+}
+if (settings.useNativeCSSProperties) {
+e.textContent = styleUtil.toCssText(styleRules);
+} else {
+var self = this;
+var fn = function fn() {
+self._flushCustomProperties();
+};
+if (initialApply) {
+Polymer.RenderStatus.whenReady(fn);
+} else {
+fn();
+}
+}
+},
+_flushCustomProperties: function () {
+if (this.__needsUpdateStyles) {
+this.__needsUpdateStyles = false;
+updateDebouncer = debounce(updateDebouncer, this._updateStyles);
+} else {
+this._applyCustomProperties();
+}
+},
+_applyCustomProperties: function () {
+var element = this.__appliedElement;
+this._computeStyleProperties();
+var props = this._styleProperties;
+var rules = styleUtil.rulesForStyle(element);
+if (!rules) {
+return;
+}
+element.textContent = styleUtil.toCssText(rules, function (rule) {
+var css = rule.cssText = rule.parsedCssText;
+if (rule.propertyInfo && rule.propertyInfo.cssText) {
+css = cssParse.removeCustomPropAssignment(css);
+rule.cssText = propertyUtils.valueForProperties(css, props);
+}
+});
+}
+});
+}());Polymer.Templatizer = {
+properties: { __hideTemplateChildren__: { observer: '_showHideChildren' } },
+_instanceProps: Polymer.nob,
+_parentPropPrefix: '_parent_',
+templatize: function (template) {
+this._templatized = template;
+if (!template._content) {
+template._content = template.content;
+}
+if (template._content._ctor) {
+this.ctor = template._content._ctor;
+this._prepParentProperties(this.ctor.prototype, template);
+return;
+}
+var archetype = Object.create(Polymer.Base);
+this._customPrepAnnotations(archetype, template);
+this._prepParentProperties(archetype, template);
+archetype._prepEffects();
+this._customPrepEffects(archetype);
+archetype._prepBehaviors();
+archetype._prepPropertyInfo();
+archetype._prepBindings();
+archetype._notifyPathUp = this._notifyPathUpImpl;
+archetype._scopeElementClass = this._scopeElementClassImpl;
+archetype.listen = this._listenImpl;
+archetype._showHideChildren = this._showHideChildrenImpl;
+archetype.__setPropertyOrig = this.__setProperty;
+archetype.__setProperty = this.__setPropertyImpl;
+var _constructor = this._constructorImpl;
+var ctor = function TemplateInstance(model, host) {
+_constructor.call(this, model, host);
+};
+ctor.prototype = archetype;
+archetype.constructor = ctor;
+template._content._ctor = ctor;
+this.ctor = ctor;
+},
+_getRootDataHost: function () {
+return this.dataHost && this.dataHost._rootDataHost || this.dataHost;
+},
+_showHideChildrenImpl: function (hide) {
+var c = this._children;
+for (var i = 0; i < c.length; i++) {
+var n = c[i];
+if (Boolean(hide) != Boolean(n.__hideTemplateChildren__)) {
+if (n.nodeType === Node.TEXT_NODE) {
+if (hide) {
+n.__polymerTextContent__ = n.textContent;
+n.textContent = '';
+} else {
+n.textContent = n.__polymerTextContent__;
+}
+} else if (n.style) {
+if (hide) {
+n.__polymerDisplay__ = n.style.display;
+n.style.display = 'none';
+} else {
+n.style.display = n.__polymerDisplay__;
+}
+}
+}
+n.__hideTemplateChildren__ = hide;
+}
+},
+__setPropertyImpl: function (property, value, fromAbove, node) {
+if (node && node.__hideTemplateChildren__ && property == 'textContent') {
+property = '__polymerTextContent__';
+}
+this.__setPropertyOrig(property, value, fromAbove, node);
+},
+_debounceTemplate: function (fn) {
+Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', fn));
+},
+_flushTemplates: function () {
+Polymer.dom.flush();
+},
+_customPrepEffects: function (archetype) {
+var parentProps = archetype._parentProps;
+for (var prop in parentProps) {
+archetype._addPropertyEffect(prop, 'function', this._createHostPropEffector(prop));
+}
+for (prop in this._instanceProps) {
+archetype._addPropertyEffect(prop, 'function', this._createInstancePropEffector(prop));
+}
+},
+_customPrepAnnotations: function (archetype, template) {
+var t = archetype._template = document.createElement('template');
+var c = t._content = template._content;
+if (!c._notes) {
+var rootDataHost = archetype._rootDataHost;
+if (rootDataHost) {
+Polymer.Annotations.prepElement = function () {
+rootDataHost._prepElement();
+};
+}
+c._notes = Polymer.Annotations.parseAnnotations(template);
+Polymer.Annotations.prepElement = null;
+this._processAnnotations(c._notes);
+}
+archetype._notes = c._notes;
+archetype._parentProps = c._parentProps;
+},
+_prepParentProperties: function (archetype, template) {
+var parentProps = this._parentProps = archetype._parentProps;
+if (this._forwardParentProp && parentProps) {
+var proto = archetype._parentPropProto;
+var prop;
+if (!proto) {
+for (prop in this._instanceProps) {
+delete parentProps[prop];
+}
+proto = archetype._parentPropProto = Object.create(null);
+if (template != this) {
+Polymer.Bind.prepareModel(proto);
+Polymer.Base.prepareModelNotifyPath(proto);
+}
+for (prop in parentProps) {
+var parentProp = this._parentPropPrefix + prop;
+var effects = [
+{
+kind: 'function',
+effect: this._createForwardPropEffector(prop),
+fn: Polymer.Bind._functionEffect
+},
+{
+kind: 'notify',
+fn: Polymer.Bind._notifyEffect,
+effect: { event: Polymer.CaseMap.camelToDashCase(parentProp) + '-changed' }
+}
+];
+proto._propertyEffects = proto._propertyEffects || {};
+proto._propertyEffects[parentProp] = effects;
+Polymer.Bind._createAccessors(proto, parentProp, effects);
+}
+}
+var self = this;
+if (template != this) {
+Polymer.Bind.prepareInstance(template);
+template._forwardParentProp = function (source, value) {
+self._forwardParentProp(source, value);
+};
+}
+this._extendTemplate(template, proto);
+template._pathEffector = function (path, value, fromAbove) {
+return self._pathEffectorImpl(path, value, fromAbove);
+};
+}
+},
+_createForwardPropEffector: function (prop) {
+return function (source, value) {
+this._forwardParentProp(prop, value);
+};
+},
+_createHostPropEffector: function (prop) {
+var prefix = this._parentPropPrefix;
+return function (source, value) {
+this.dataHost._templatized[prefix + prop] = value;
+};
+},
+_createInstancePropEffector: function (prop) {
+return function (source, value, old, fromAbove) {
+if (!fromAbove) {
+this.dataHost._forwardInstanceProp(this, prop, value);
+}
+};
+},
+_extendTemplate: function (template, proto) {
+var n$ = Object.getOwnPropertyNames(proto);
+if (proto._propertySetter) {
+template._propertySetter = proto._propertySetter;
+}
+for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
+var val = template[n];
+if (val && n == '_propertyEffects') {
+var pe = Polymer.Base.mixin({}, val);
+template._propertyEffects = Polymer.Base.mixin(pe, proto._propertyEffects);
+} else {
+var pd = Object.getOwnPropertyDescriptor(proto, n);
+Object.defineProperty(template, n, pd);
+if (val !== undefined) {
+template._propertySetter(n, val);
+}
+}
+}
+},
+_showHideChildren: function (hidden) {
+},
+_forwardInstancePath: function (inst, path, value) {
+},
+_forwardInstanceProp: function (inst, prop, value) {
+},
+_notifyPathUpImpl: function (path, value) {
+var dataHost = this.dataHost;
+var root = Polymer.Path.root(path);
+dataHost._forwardInstancePath.call(dataHost, this, path, value);
+if (root in dataHost._parentProps) {
+dataHost._templatized._notifyPath(dataHost._parentPropPrefix + path, value);
+}
+},
+_pathEffectorImpl: function (path, value, fromAbove) {
+if (this._forwardParentPath) {
+if (path.indexOf(this._parentPropPrefix) === 0) {
+var subPath = path.substring(this._parentPropPrefix.length);
+var model = Polymer.Path.root(subPath);
+if (model in this._parentProps) {
+this._forwardParentPath(subPath, value);
+}
+}
+}
+Polymer.Base._pathEffector.call(this._templatized, path, value, fromAbove);
+},
+_constructorImpl: function (model, host) {
+this._rootDataHost = host._getRootDataHost();
+this._setupConfigure(model);
+this._registerHost(host);
+this._beginHosting();
+this.root = this.instanceTemplate(this._template);
+this.root.__noContent = !this._notes._hasContent;
+this.root.__styleScoped = true;
+this._endHosting();
+this._marshalAnnotatedNodes();
+this._marshalInstanceEffects();
+this._marshalAnnotatedListeners();
+var children = [];
+for (var n = this.root.firstChild; n; n = n.nextSibling) {
+children.push(n);
+n._templateInstance = this;
+}
+this._children = children;
+if (host.__hideTemplateChildren__) {
+this._showHideChildren(true);
+}
+this._tryReady();
+},
+_listenImpl: function (node, eventName, methodName) {
+var model = this;
+var host = this._rootDataHost;
+var handler = host._createEventHandler(node, eventName, methodName);
+var decorated = function (e) {
+e.model = model;
+handler(e);
+};
+host._listen(node, eventName, decorated);
+},
+_scopeElementClassImpl: function (node, value) {
+var host = this._rootDataHost;
+if (host) {
+return host._scopeElementClass(node, value);
+}
+return value;
+},
+stamp: function (model) {
+model = model || {};
+if (this._parentProps) {
+var templatized = this._templatized;
+for (var prop in this._parentProps) {
+if (model[prop] === undefined) {
+model[prop] = templatized[this._parentPropPrefix + prop];
+}
+}
+}
+return new this.ctor(model, this);
+},
+modelForElement: function (el) {
+var model;
+while (el) {
+if (model = el._templateInstance) {
+if (model.dataHost != this) {
+el = model.dataHost;
+} else {
+return model;
+}
+} else {
+el = el.parentNode;
+}
+}
+}
+};Polymer({
+is: 'dom-template',
+extends: 'template',
+_template: null,
+behaviors: [Polymer.Templatizer],
+ready: function () {
+this.templatize(this);
+}
+});Polymer._collections = new WeakMap();
+Polymer.Collection = function (userArray) {
+Polymer._collections.set(userArray, this);
+this.userArray = userArray;
+this.store = userArray.slice();
+this.initMap();
+};
+Polymer.Collection.prototype = {
+constructor: Polymer.Collection,
+initMap: function () {
+var omap = this.omap = new WeakMap();
+var pmap = this.pmap = {};
+var s = this.store;
+for (var i = 0; i < s.length; i++) {
+var item = s[i];
+if (item && typeof item == 'object') {
+omap.set(item, i);
+} else {
+pmap[item] = i;
+}
+}
+},
+add: function (item) {
+var key = this.store.push(item) - 1;
+if (item && typeof item == 'object') {
+this.omap.set(item, key);
+} else {
+this.pmap[item] = key;
+}
+return '#' + key;
+},
+removeKey: function (key) {
+if (key = this._parseKey(key)) {
+this._removeFromMap(this.store[key]);
+delete this.store[key];
+}
+},
+_removeFromMap: function (item) {
+if (item && typeof item == 'object') {
+this.omap.delete(item);
+} else {
+delete this.pmap[item];
+}
+},
+remove: function (item) {
+var key = this.getKey(item);
+this.removeKey(key);
+return key;
+},
+getKey: function (item) {
+var key;
+if (item && typeof item == 'object') {
+key = this.omap.get(item);
+} else {
+key = this.pmap[item];
+}
+if (key != undefined) {
+return '#' + key;
+}
+},
+getKeys: function () {
+return Object.keys(this.store).map(function (key) {
+return '#' + key;
+});
+},
+_parseKey: function (key) {
+if (key && key[0] == '#') {
+return key.slice(1);
+}
+},
+setItem: function (key, item) {
+if (key = this._parseKey(key)) {
+var old = this.store[key];
+if (old) {
+this._removeFromMap(old);
+}
+if (item && typeof item == 'object') {
+this.omap.set(item, key);
+} else {
+this.pmap[item] = key;
+}
+this.store[key] = item;
+}
+},
+getItem: function (key) {
+if (key = this._parseKey(key)) {
+return this.store[key];
+}
+},
+getItems: function () {
+var items = [], store = this.store;
+for (var key in store) {
+items.push(store[key]);
+}
+return items;
+},
+_applySplices: function (splices) {
+var keyMap = {}, key;
+for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
+s.addedKeys = [];
+for (var j = 0; j < s.removed.length; j++) {
+key = this.getKey(s.removed[j]);
+keyMap[key] = keyMap[key] ? null : -1;
+}
+for (j = 0; j < s.addedCount; j++) {
+var item = this.userArray[s.index + j];
+key = this.getKey(item);
+key = key === undefined ? this.add(item) : key;
+keyMap[key] = keyMap[key] ? null : 1;
+s.addedKeys.push(key);
+}
+}
+var removed = [];
+var added = [];
+for (key in keyMap) {
+if (keyMap[key] < 0) {
+this.removeKey(key);
+removed.push(key);
+}
+if (keyMap[key] > 0) {
+added.push(key);
+}
+}
+return [{
+removed: removed,
+added: added
+}];
+}
+};
+Polymer.Collection.get = function (userArray) {
+return Polymer._collections.get(userArray) || new Polymer.Collection(userArray);
+};
+Polymer.Collection.applySplices = function (userArray, splices) {
+var coll = Polymer._collections.get(userArray);
+return coll ? coll._applySplices(splices) : null;
+};Polymer({
+is: 'dom-repeat',
+extends: 'template',
+_template: null,
+properties: {
+items: { type: Array },
+as: {
+type: String,
+value: 'item'
+},
+indexAs: {
+type: String,
+value: 'index'
+},
+sort: {
+type: Function,
+observer: '_sortChanged'
+},
+filter: {
+type: Function,
+observer: '_filterChanged'
+},
+observe: {
+type: String,
+observer: '_observeChanged'
+},
+delay: Number,
+renderedItemCount: {
+type: Number,
+notify: !Polymer.Settings.suppressTemplateNotifications,
+readOnly: true
+},
+initialCount: {
+type: Number,
+observer: '_initializeChunking'
+},
+targetFramerate: {
+type: Number,
+value: 20
+},
+notifyDomChange: { type: Boolean },
+_targetFrameTime: {
+type: Number,
+computed: '_computeFrameTime(targetFramerate)'
+}
+},
+behaviors: [Polymer.Templatizer],
+observers: ['_itemsChanged(items.*)'],
+created: function () {
+this._instances = [];
+this._pool = [];
+this._limit = Infinity;
+var self = this;
+this._boundRenderChunk = function () {
+self._renderChunk();
+};
+},
+detached: function () {
+this.__isDetached = true;
+for (var i = 0; i < this._instances.length; i++) {
+this._detachInstance(i);
+}
+},
+attached: function () {
+if (this.__isDetached) {
+this.__isDetached = false;
+var refNode;
+var parentNode = Polymer.dom(this).parentNode;
+if (parentNode.localName == this.is) {
+refNode = parentNode;
+parentNode = Polymer.dom(parentNode).parentNode;
+} else {
+refNode = this;
+}
+var parent = Polymer.dom(parentNode);
+for (var i = 0; i < this._instances.length; i++) {
+this._attachInstance(i, parent, refNode);
+}
+}
+},
+ready: function () {
+this._instanceProps = { __key__: true };
+this._instanceProps[this.as] = true;
+this._instanceProps[this.indexAs] = true;
+if (!this.ctor) {
+this.templatize(this);
+}
+},
+_sortChanged: function (sort) {
+var dataHost = this._getRootDataHost();
+this._sortFn = sort && (typeof sort == 'function' ? sort : function () {
+return dataHost[sort].apply(dataHost, arguments);
+});
+this._needFullRefresh = true;
+if (this.items) {
+this._debounceTemplate(this._render);
+}
+},
+_filterChanged: function (filter) {
+var dataHost = this._getRootDataHost();
+this._filterFn = filter && (typeof filter == 'function' ? filter : function () {
+return dataHost[filter].apply(dataHost, arguments);
+});
+this._needFullRefresh = true;
+if (this.items) {
+this._debounceTemplate(this._render);
+}
+},
+_computeFrameTime: function (rate) {
+return Math.ceil(1000 / rate);
+},
+_initializeChunking: function () {
+if (this.initialCount) {
+this._limit = this.initialCount;
+this._chunkCount = this.initialCount;
+this._lastChunkTime = performance.now();
+}
+},
+_tryRenderChunk: function () {
+if (this.items && this._limit < this.items.length) {
+this.debounce('renderChunk', this._requestRenderChunk);
+}
+},
+_requestRenderChunk: function () {
+requestAnimationFrame(this._boundRenderChunk);
+},
+_renderChunk: function () {
+var currChunkTime = performance.now();
+var ratio = this._targetFrameTime / (currChunkTime - this._lastChunkTime);
+this._chunkCount = Math.round(this._chunkCount * ratio) || 1;
+this._limit += this._chunkCount;
+this._lastChunkTime = currChunkTime;
+this._debounceTemplate(this._render);
+},
+_observeChanged: function () {
+this._observePaths = this.observe && this.observe.replace('.*', '.').split(' ');
+},
+_itemsChanged: function (change) {
+if (change.path == 'items') {
+if (Array.isArray(this.items)) {
+this.collection = Polymer.Collection.get(this.items);
+} else if (!this.items) {
+this.collection = null;
+} else {
+this._error(this._logf('dom-repeat', 'expected array for `items`,' + ' found', this.items));
+}
+this._keySplices = [];
+this._indexSplices = [];
+this._needFullRefresh = true;
+this._initializeChunking();
+this._debounceTemplate(this._render);
+} else if (change.path == 'items.splices') {
+this._keySplices = this._keySplices.concat(change.value.keySplices);
+this._indexSplices = this._indexSplices.concat(change.value.indexSplices);
+this._debounceTemplate(this._render);
+} else {
+var subpath = change.path.slice(6);
+this._forwardItemPath(subpath, change.value);
+this._checkObservedPaths(subpath);
+}
+},
+_checkObservedPaths: function (path) {
+if (this._observePaths) {
+path = path.substring(path.indexOf('.') + 1);
+var paths = this._observePaths;
+for (var i = 0; i < paths.length; i++) {
+if (path.indexOf(paths[i]) === 0) {
+this._needFullRefresh = true;
+if (this.delay) {
+this.debounce('render', this._render, this.delay);
+} else {
+this._debounceTemplate(this._render);
+}
+return;
+}
+}
+}
+},
+render: function () {
+this._needFullRefresh = true;
+this._debounceTemplate(this._render);
+this._flushTemplates();
+},
+_render: function () {
+if (this._needFullRefresh) {
+this._applyFullRefresh();
+this._needFullRefresh = false;
+} else if (this._keySplices.length) {
+if (this._sortFn) {
+this._applySplicesUserSort(this._keySplices);
+} else {
+if (this._filterFn) {
+this._applyFullRefresh();
+} else {
+this._applySplicesArrayOrder(this._indexSplices);
+}
+}
+} else {
+}
+this._keySplices = [];
+this._indexSplices = [];
+var keyToIdx = this._keyToInstIdx = {};
+for (var i = this._instances.length - 1; i >= 0; i--) {
+var inst = this._instances[i];
+if (inst.isPlaceholder && i < this._limit) {
+inst = this._insertInstance(i, inst.__key__);
+} else if (!inst.isPlaceholder && i >= this._limit) {
+inst = this._downgradeInstance(i, inst.__key__);
+}
+keyToIdx[inst.__key__] = i;
+if (!inst.isPlaceholder) {
+inst.__setProperty(this.indexAs, i, true);
+}
+}
+this._pool.length = 0;
+this._setRenderedItemCount(this._instances.length);
+if (!Polymer.Settings.suppressTemplateNotifications || this.notifyDomChange) {
+this.fire('dom-change');
+}
+this._tryRenderChunk();
+},
+_applyFullRefresh: function () {
+var c = this.collection;
+var keys;
+if (this._sortFn) {
+keys = c ? c.getKeys() : [];
+} else {
+keys = [];
+var items = this.items;
+if (items) {
+for (var i = 0; i < items.length; i++) {
+keys.push(c.getKey(items[i]));
+}
+}
+}
+var self = this;
+if (this._filterFn) {
+keys = keys.filter(function (a) {
+return self._filterFn(c.getItem(a));
+});
+}
+if (this._sortFn) {
+keys.sort(function (a, b) {
+return self._sortFn(c.getItem(a), c.getItem(b));
+});
+}
+for (i = 0; i < keys.length; i++) {
+var key = keys[i];
+var inst = this._instances[i];
+if (inst) {
+inst.__key__ = key;
+if (!inst.isPlaceholder && i < this._limit) {
+inst.__setProperty(this.as, c.getItem(key), true);
+}
+} else if (i < this._limit) {
+this._insertInstance(i, key);
+} else {
+this._insertPlaceholder(i, key);
+}
+}
+for (var j = this._instances.length - 1; j >= i; j--) {
+this._detachAndRemoveInstance(j);
+}
+},
+_numericSort: function (a, b) {
+return a - b;
+},
+_applySplicesUserSort: function (splices) {
+var c = this.collection;
+var keyMap = {};
+var key;
+for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
+for (var j = 0; j < s.removed.length; j++) {
+key = s.removed[j];
+keyMap[key] = keyMap[key] ? null : -1;
+}
+for (j = 0; j < s.added.length; j++) {
+key = s.added[j];
+keyMap[key] = keyMap[key] ? null : 1;
+}
+}
+var removedIdxs = [];
+var addedKeys = [];
+for (key in keyMap) {
+if (keyMap[key] === -1) {
+removedIdxs.push(this._keyToInstIdx[key]);
+}
+if (keyMap[key] === 1) {
+addedKeys.push(key);
+}
+}
+if (removedIdxs.length) {
+removedIdxs.sort(this._numericSort);
+for (i = removedIdxs.length - 1; i >= 0; i--) {
+var idx = removedIdxs[i];
+if (idx !== undefined) {
+this._detachAndRemoveInstance(idx);
+}
+}
+}
+var self = this;
+if (addedKeys.length) {
+if (this._filterFn) {
+addedKeys = addedKeys.filter(function (a) {
+return self._filterFn(c.getItem(a));
+});
+}
+addedKeys.sort(function (a, b) {
+return self._sortFn(c.getItem(a), c.getItem(b));
+});
+var start = 0;
+for (i = 0; i < addedKeys.length; i++) {
+start = this._insertRowUserSort(start, addedKeys[i]);
+}
+}
+},
+_insertRowUserSort: function (start, key) {
+var c = this.collection;
+var item = c.getItem(key);
+var end = this._instances.length - 1;
+var idx = -1;
+while (start <= end) {
+var mid = start + end >> 1;
+var midKey = this._instances[mid].__key__;
+var cmp = this._sortFn(c.getItem(midKey), item);
+if (cmp < 0) {
+start = mid + 1;
+} else if (cmp > 0) {
+end = mid - 1;
+} else {
+idx = mid;
+break;
+}
+}
+if (idx < 0) {
+idx = end + 1;
+}
+this._insertPlaceholder(idx, key);
+return idx;
+},
+_applySplicesArrayOrder: function (splices) {
+for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
+for (var j = 0; j < s.removed.length; j++) {
+this._detachAndRemoveInstance(s.index);
+}
+for (j = 0; j < s.addedKeys.length; j++) {
+this._insertPlaceholder(s.index + j, s.addedKeys[j]);
+}
+}
+},
+_detachInstance: function (idx) {
+var inst = this._instances[idx];
+if (!inst.isPlaceholder) {
+for (var i = 0; i < inst._children.length; i++) {
+var el = inst._children[i];
+Polymer.dom(inst.root).appendChild(el);
+}
+return inst;
+}
+},
+_attachInstance: function (idx, parent, refNode) {
+var inst = this._instances[idx];
+if (!inst.isPlaceholder) {
+parent.insertBefore(inst.root, refNode);
+}
+},
+_detachAndRemoveInstance: function (idx) {
+var inst = this._detachInstance(idx);
+if (inst) {
+this._pool.push(inst);
+}
+this._instances.splice(idx, 1);
+},
+_insertPlaceholder: function (idx, key) {
+this._instances.splice(idx, 0, {
+isPlaceholder: true,
+__key__: key
+});
+},
+_stampInstance: function (idx, key) {
+var model = { __key__: key };
+model[this.as] = this.collection.getItem(key);
+model[this.indexAs] = idx;
+return this.stamp(model);
+},
+_insertInstance: function (idx, key) {
+var inst = this._pool.pop();
+if (inst) {
+inst.__setProperty(this.as, this.collection.getItem(key), true);
+inst.__setProperty('__key__', key, true);
+} else {
+inst = this._stampInstance(idx, key);
+}
+var beforeRow = this._instances[idx + 1];
+var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this;
+var parentNode = Polymer.dom(this).parentNode;
+if (parentNode.localName == this.is) {
+if (beforeNode == this) {
+beforeNode = parentNode;
+}
+parentNode = Polymer.dom(parentNode).parentNode;
+}
+Polymer.dom(parentNode).insertBefore(inst.root, beforeNode);
+this._instances[idx] = inst;
+return inst;
+},
+_downgradeInstance: function (idx, key) {
+var inst = this._detachInstance(idx);
+if (inst) {
+this._pool.push(inst);
+}
+inst = {
+isPlaceholder: true,
+__key__: key
+};
+this._instances[idx] = inst;
+return inst;
+},
+_showHideChildren: function (hidden) {
+for (var i = 0; i < this._instances.length; i++) {
+if (!this._instances[i].isPlaceholder)
+this._instances[i]._showHideChildren(hidden);
+}
+},
+_forwardInstanceProp: function (inst, prop, value) {
+if (prop == this.as) {
+var idx;
+if (this._sortFn || this._filterFn) {
+idx = this.items.indexOf(this.collection.getItem(inst.__key__));
+} else {
+idx = inst[this.indexAs];
+}
+this.set('items.' + idx, value);
+}
+},
+_forwardInstancePath: function (inst, path, value) {
+if (path.indexOf(this.as + '.') === 0) {
+this._notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value);
+}
+},
+_forwardParentProp: function (prop, value) {
+var i$ = this._instances;
+for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) {
+if (!inst.isPlaceholder) {
+inst.__setProperty(prop, value, true);
+}
+}
+},
+_forwardParentPath: function (path, value) {
+var i$ = this._instances;
+for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) {
+if (!inst.isPlaceholder) {
+inst._notifyPath(path, value, true);
+}
+}
+},
+_forwardItemPath: function (path, value) {
+if (this._keyToInstIdx) {
+var dot = path.indexOf('.');
+var key = path.substring(0, dot < 0 ? path.length : dot);
+var idx = this._keyToInstIdx[key];
+var inst = this._instances[idx];
+if (inst && !inst.isPlaceholder) {
+if (dot >= 0) {
+path = this.as + '.' + path.substring(dot + 1);
+inst._notifyPath(path, value, true);
+} else {
+inst.__setProperty(this.as, value, true);
+}
+}
+}
+},
+itemForElement: function (el) {
+var instance = this.modelForElement(el);
+return instance && instance[this.as];
+},
+keyForElement: function (el) {
+var instance = this.modelForElement(el);
+return instance && instance.__key__;
+},
+indexForElement: function (el) {
+var instance = this.modelForElement(el);
+return instance && instance[this.indexAs];
+}
+});Polymer({
+is: 'array-selector',
+_template: null,
+properties: {
+items: {
+type: Array,
+observer: 'clearSelection'
+},
+multi: {
+type: Boolean,
+value: false,
+observer: 'clearSelection'
+},
+selected: {
+type: Object,
+notify: true
+},
+selectedItem: {
+type: Object,
+notify: true
+},
+toggle: {
+type: Boolean,
+value: false
+}
+},
+clearSelection: function () {
+if (Array.isArray(this.selected)) {
+for (var i = 0; i < this.selected.length; i++) {
+this.unlinkPaths('selected.' + i);
+}
+} else {
+this.unlinkPaths('selected');
+this.unlinkPaths('selectedItem');
+}
+if (this.multi) {
+if (!this.selected || this.selected.length) {
+this.selected = [];
+this._selectedColl = Polymer.Collection.get(this.selected);
+}
+} else {
+this.selected = null;
+this._selectedColl = null;
+}
+this.selectedItem = null;
+},
+isSelected: function (item) {
+if (this.multi) {
+return this._selectedColl.getKey(item) !== undefined;
+} else {
+return this.selected == item;
+}
+},
+deselect: function (item) {
+if (this.multi) {
+if (this.isSelected(item)) {
+var skey = this._selectedColl.getKey(item);
+this.arrayDelete('selected', item);
+this.unlinkPaths('selected.' + skey);
+}
+} else {
+this.selected = null;
+this.selectedItem = null;
+this.unlinkPaths('selected');
+this.unlinkPaths('selectedItem');
+}
+},
+select: function (item) {
+var icol = Polymer.Collection.get(this.items);
+var key = icol.getKey(item);
+if (this.multi) {
+if (this.isSelected(item)) {
+if (this.toggle) {
+this.deselect(item);
+}
+} else {
+this.push('selected', item);
+var skey = this._selectedColl.getKey(item);
+this.linkPaths('selected.' + skey, 'items.' + key);
+}
+} else {
+if (this.toggle && item == this.selected) {
+this.deselect();
+} else {
+this.selected = item;
+this.selectedItem = item;
+this.linkPaths('selected', 'items.' + key);
+this.linkPaths('selectedItem', 'items.' + key);
+}
+}
+}
+});Polymer({
+is: 'dom-if',
+extends: 'template',
+_template: null,
+properties: {
+'if': {
+type: Boolean,
+value: false,
+observer: '_queueRender'
+},
+restamp: {
+type: Boolean,
+value: false,
+observer: '_queueRender'
+},
+notifyDomChange: { type: Boolean }
+},
+behaviors: [Polymer.Templatizer],
+_queueRender: function () {
+this._debounceTemplate(this._render);
+},
+detached: function () {
+var parentNode = this.parentNode;
+if (parentNode && parentNode.localName == this.is) {
+parentNode = Polymer.dom(parentNode).parentNode;
+}
+if (!parentNode || parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE && (!Polymer.Settings.hasShadow || !(parentNode instanceof ShadowRoot))) {
+this._teardownInstance();
+}
+},
+attached: function () {
+if (this.if && this.ctor) {
+this.async(this._ensureInstance);
+}
+},
+render: function () {
+this._flushTemplates();
+},
+_render: function () {
+if (this.if) {
+if (!this.ctor) {
+this.templatize(this);
+}
+this._ensureInstance();
+this._showHideChildren();
+} else if (this.restamp) {
+this._teardownInstance();
+}
+if (!this.restamp && this._instance) {
+this._showHideChildren();
+}
+if (this.if != this._lastIf) {
+if (!Polymer.Settings.suppressTemplateNotifications || this.notifyDomChange) {
+this.fire('dom-change');
+}
+this._lastIf = this.if;
+}
+},
+_ensureInstance: function () {
+var refNode;
+var parentNode = Polymer.dom(this).parentNode;
+if (parentNode && parentNode.localName == this.is) {
+refNode = parentNode;
+parentNode = Polymer.dom(parentNode).parentNode;
+} else {
+refNode = this;
+}
+if (parentNode) {
+if (!this._instance) {
+this._instance = this.stamp();
+var root = this._instance.root;
+Polymer.dom(parentNode).insertBefore(root, refNode);
+} else {
+var c$ = this._instance._children;
+if (c$ && c$.length) {
+var lastChild = Polymer.dom(refNode).previousSibling;
+if (lastChild !== c$[c$.length - 1]) {
+for (var i = 0, n; i < c$.length && (n = c$[i]); i++) {
+Polymer.dom(parentNode).insertBefore(n, refNode);
+}
+}
+}
+}
+}
+},
+_teardownInstance: function () {
+if (this._instance) {
+var c$ = this._instance._children;
+if (c$ && c$.length) {
+var parent = Polymer.dom(Polymer.dom(c$[0]).parentNode);
+for (var i = 0, n; i < c$.length && (n = c$[i]); i++) {
+parent.removeChild(n);
+}
+}
+this._instance = null;
+}
+},
+_showHideChildren: function () {
+var hidden = this.__hideTemplateChildren__ || !this.if;
+if (this._instance) {
+this._instance._showHideChildren(hidden);
+}
+},
+_forwardParentProp: function (prop, value) {
+if (this._instance) {
+this._instance.__setProperty(prop, value, true);
+}
+},
+_forwardParentPath: function (path, value) {
+if (this._instance) {
+this._instance._notifyPath(path, value, true);
+}
+}
+});Polymer({
+is: 'dom-bind',
+properties: { notifyDomChange: { type: Boolean } },
+extends: 'template',
+_template: null,
+created: function () {
+var self = this;
+Polymer.RenderStatus.whenReady(function () {
+if (document.readyState == 'loading') {
+document.addEventListener('DOMContentLoaded', function () {
+self._markImportsReady();
+});
+} else {
+self._markImportsReady();
+}
+});
+},
+_ensureReady: function () {
+if (!this._readied) {
+this._readySelf();
+}
+},
+_markImportsReady: function () {
+this._importsReady = true;
+this._ensureReady();
+},
+_registerFeatures: function () {
+this._prepConstructor();
+},
+_insertChildren: function () {
+var refNode;
+var parentNode = Polymer.dom(this).parentNode;
+if (parentNode.localName == this.is) {
+refNode = parentNode;
+parentNode = Polymer.dom(parentNode).parentNode;
+} else {
+refNode = this;
+}
+Polymer.dom(parentNode).insertBefore(this.root, refNode);
+},
+_removeChildren: function () {
+if (this._children) {
+for (var i = 0; i < this._children.length; i++) {
+this.root.appendChild(this._children[i]);
+}
+}
+},
+_initFeatures: function () {
+},
+_scopeElementClass: function (element, selector) {
+if (this.dataHost) {
+return this.dataHost._scopeElementClass(element, selector);
+} else {
+return selector;
+}
+},
+_configureInstanceProperties: function () {
+},
+_prepConfigure: function () {
+var config = {};
+for (var prop in this._propertyEffects) {
+config[prop] = this[prop];
+}
+var setupConfigure = this._setupConfigure;
+this._setupConfigure = function () {
+setupConfigure.call(this, config);
+};
+},
+attached: function () {
+if (this._importsReady) {
+this.render();
+}
+},
+detached: function () {
+this._removeChildren();
+},
+render: function () {
+this._ensureReady();
+if (!this._children) {
+this._template = this;
+this._prepAnnotations();
+this._prepEffects();
+this._prepBehaviors();
+this._prepConfigure();
+this._prepBindings();
+this._prepPropertyInfo();
+Polymer.Base._initFeatures.call(this);
+this._children = Polymer.TreeApi.arrayCopyChildNodes(this.root);
+}
+this._insertChildren();
+if (!Polymer.Settings.suppressTemplateNotifications || this.notifyDomChange) {
+this.fire('dom-change');
+}
+}
+});</script>
+
+
+
+
+
+
+
+
+
diff --git a/chromium/third_party/catapult/tracing/.allow-devtools-save b/chromium/third_party/catapult/tracing/.allow-devtools-save
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/.allow-devtools-save
diff --git a/chromium/third_party/catapult/tracing/.bowerrc b/chromium/third_party/catapult/tracing/.bowerrc
new file mode 100644
index 00000000000..d981a1dd485
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/.bowerrc
@@ -0,0 +1,3 @@
+{
+ "directory": "third_party/components"
+}
diff --git a/chromium/third_party/catapult/tracing/.npmignore b/chromium/third_party/catapult/tracing/.npmignore
new file mode 100644
index 00000000000..70d51d239f1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/.npmignore
@@ -0,0 +1,17 @@
+test_data
+skp_data
+third_party
+
+images
+tracing_build
+build
+
+app.yaml
+*_test.html
+
+*.gyp
+*.gypi
+*.gn
+
+*.py
+*.pyc
diff --git a/chromium/third_party/catapult/tracing/LICENSE b/chromium/third_party/catapult/tracing/LICENSE
new file mode 100644
index 00000000000..e6c0d72a512
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chromium/third_party/catapult/tracing/OWNERS b/chromium/third_party/catapult/tracing/OWNERS
new file mode 100644
index 00000000000..65df8c2ebb3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/OWNERS
@@ -0,0 +1,21 @@
+# Owners: These folks have a very good understanding of the tracing
+# system and how the UI bits fit together. Good for reviews of large
+# architectual changes, or areas of the code where you may need more
+# information.
+fmeawad@chromium.org
+benjhayden@chromium.org
+lpy@chromium.org
+
+# For changes related to system_health/loading_metric.html and its tests.
+kouhei@chromium.org
+
+# TEAM: tracing@chromium.org
+# COMPONENT: Speed>Tracing
+
+# These folks have made huge contributions to the project, but are no longer
+# actively reviewing patches.
+nduca@chromium.org
+# petrcermak@chromium.org
+# dsinclair@chromium.org
+# charliea@chromium.org
+# eakuefner@chromium.org
diff --git a/chromium/third_party/catapult/tracing/PRESUBMIT.py b/chromium/third_party/catapult/tracing/PRESUBMIT.py
new file mode 100644
index 00000000000..9a1ba361921
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/PRESUBMIT.py
@@ -0,0 +1,81 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+def _RunArgs(args, input_api):
+ p = input_api.subprocess.Popen(args, stdout=input_api.subprocess.PIPE,
+ stderr=input_api.subprocess.STDOUT)
+ out, _ = p.communicate()
+ return (out, p.returncode)
+
+
+def _CheckRegisteredMetrics(input_api, output_api):
+ """ Check that all tracing metrics are imported in all_metrics.html """
+ results = []
+ tracing_dir = input_api.PresubmitLocalPath()
+ out, return_code = _RunArgs(
+ [input_api.python_executable,
+ input_api.os_path.join(tracing_dir, 'bin', 'validate_all_metrics')],
+ input_api)
+ if return_code:
+ results.append(output_api.PresubmitError(
+ 'Failed validate_all_metrics: ', long_text=out))
+ return results
+
+
+def _CheckRegisteredDiagnostics(input_api, output_api):
+ """Check that all Diagnostic subclasses are registered."""
+ results = []
+ tracing_dir = input_api.PresubmitLocalPath()
+ out, return_code = _RunArgs(
+ [input_api.python_executable,
+ input_api.os_path.join(tracing_dir, 'bin', 'validate_all_diagnostics')],
+ input_api)
+ if return_code:
+ results.append(output_api.PresubmitError(
+ 'Failed validate_all_diagnostics: ', long_text=out))
+ return results
+
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return _CheckChange(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return _CheckChange(input_api, output_api)
+
+
+def _CheckChange(input_api, output_api):
+ results = []
+
+ original_sys_path = sys.path
+ try:
+ sys.path += [input_api.PresubmitLocalPath()]
+ from tracing_build import check_gni
+ error = check_gni.GniCheck()
+ if error:
+ results.append(output_api.PresubmitError(error))
+ finally:
+ sys.path = original_sys_path
+
+ results += input_api.RunTests(input_api.canned_checks.GetPylint(
+ input_api, output_api, extra_paths_list=_GetPathsToPrepend(input_api),
+ pylintrc='../pylintrc'))
+
+ results += _CheckRegisteredMetrics(input_api, output_api)
+ results += _CheckRegisteredDiagnostics(input_api, output_api)
+
+ return results
+
+
+def _GetPathsToPrepend(input_api):
+ import tracing_project
+ project_dir = input_api.PresubmitLocalPath()
+ catapult_dir = input_api.os_path.join(project_dir, '..')
+ return [
+ project_dir,
+ input_api.os_path.join(catapult_dir, 'third_party', 'mock'),
+ ] + tracing_project.GetDependencyPaths()
diff --git a/chromium/third_party/catapult/tracing/README.md b/chromium/third_party/catapult/tracing/README.md
new file mode 100644
index 00000000000..e4188a170ef
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/README.md
@@ -0,0 +1,52 @@
+
+<!-- Copyright 2015 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+![Trace Viewer Logo](https://raw.githubusercontent.com/catapult-project/catapult/master/tracing/images/trace-viewer-circle-blue.png)
+
+Trace-Viewer is the javascript frontend for Chrome [about:tracing](http://dev.chromium.org/developers/how-tos/trace-event-profiling-tool) and [Android
+systrace](http://developer.android.com/tools/help/systrace.html).
+
+It provides rich analysis and visualization capabilities for many types of trace
+files. Its particularly good at viewing linux kernel traces (aka [ftrace](https://www.kernel.org/doc/Documentation/trace/ftrace.txt)) and Chrome's
+[trace_event format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview). Trace viewer can be [embedded](https://github.com/catapult-project/catapult/blob/master/tracing/docs/embedding-trace-viewer.md) as a component in your own code, or used from a plain checkout to turn trace files into standalone, emailable HTML files from the commandline:
+
+```
+$CATAPULT/tracing/bin/trace2html my_trace.json --output=my_trace.html && open my_trace.html
+```
+
+Its easy to [extend trace viewer](https://github.com/catapult-project/catapult/blob/master/tracing/docs/extending-and-customizing-trace-viewer.md) to support your favorite trace format, or add domain specific visualizations to the UI to simplify drilling down into complex data.
+
+Contributing, quick version
+===
+We welcome contributions! To hack on this code.
+
+There are two type of tests.
+
+### In the browser
+
+Run http server `$CATAPULT/bin/run_dev_server`. In any browser, navigate to `http://localhost:8003/`
+
+**Unit tests**| **Descripton**
+--- | ---
+All tests | http://localhost:8003/tests.html
+All tests with short format | http://localhost:8003/tracing/tests.html?shortFormat
+An individual test suite(such as ui/foo_test.js) | http://localhost:8003/tests.html?testSuiteName=ui.foo
+Tests named foo| http://localhost:8003/tests.html?testFilterString=foo
+
+### On command
+
+**Unit tests**| **Description**
+--- | ---
+All python tests | `$CATAPULT/tracing/bin/run_py_tests`
+All tracing tests in d8 environment | `$CATAPULT/tracing/bin/run_vinn_tests`
+All tracing tests in devserver environment | `$CATAPULT/tracing/bin/run_devserver_tests`
+All tests | `$CATAPULT/tracing/bin/run_tests`
+
+Make sure tests pass before sending us changelist. **We use Gerrit for codereview**. For more details, esp on Gerrit, [read our contributing guide](https://github.com/catapult-project/catapult/blob/master/CONTRIBUTING.md) or check out the [Getting Started guide](https://github.com/catapult-project/catapult/blob/master/tracing/docs/getting-started.md).
+
+Contact Us
+===
+Join our Google Group:
+* [tracing@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/tracing)
diff --git a/chromium/third_party/catapult/tracing/app.yaml b/chromium/third_party/catapult/tracing/app.yaml
new file mode 100644
index 00000000000..a39a87aedce
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/app.yaml
@@ -0,0 +1,58 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+runtime: python27
+threadsafe: true
+api_version: 1
+
+handlers:
+
+- url: /base
+ static_dir: tracing/tracing/base
+ secure: always
+
+- url: /core
+ static_dir: tracing/tracing/core
+ secure: always
+
+- url: /extras
+ static_dir: tracing/tracing/extras
+ secure: always
+
+- url: /ui
+ static_dir: tracing/tracing/ui
+ secure: always
+
+- url: /components
+ static_dir: tracing/third_party/components
+ secure: always
+
+- url: /trace_viewer
+ static_dir: tracing/tracing
+ secure: always
+
+- url: /gl-matrix-min.js
+ static_files: tracing/third_party/gl-matrix/dist/gl-matrix-min.js
+ upload: tracing/third_party/gl-matrix/dist/gl-matrix-min.js
+ secure: always
+
+- url: /mannwhitneyu.js
+ static_files: tracing/third_party/mannwhitneyu/mannwhitneyu.js
+ upload: tracing/third_party/mannwhitneyu/mannwhitneyu.js
+ secure: always
+
+- url: /pako.min.js
+ static_files: tracing/third_party/pako/pako.min.js
+ upload: tracing/third_party/pako/pako.min.js
+ secure: always
+
+- url: /d3.min.js
+ static_files: tracing/third_party/d3/d3.min.js
+ upload: tracing/third_party/d3/d3.min.js
+ secure: always
+
+- url: /.*
+ static_files: tracing/tracing/ui/extras/drive/index.html
+ upload: tracing/tracing/ui/extras/drive/index.html
+ secure: always
diff --git a/chromium/third_party/catapult/tracing/bin/PRESUBMIT.py b/chromium/third_party/catapult/tracing/bin/PRESUBMIT.py
new file mode 100644
index 00000000000..799215d729d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/PRESUBMIT.py
@@ -0,0 +1,19 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+def CheckChange(input_api, output_api):
+ init_py_path = os.path.join(input_api.PresubmitLocalPath(), '__init__.py')
+ res = []
+ if os.path.exists(init_py_path):
+ res += [output_api.PresubmitError(
+ '__init__.py is not allowed to exist in bin/')]
+ return res
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CheckChange(input_api, output_api)
diff --git a/chromium/third_party/catapult/tracing/bin/README.md b/chromium/third_party/catapult/tracing/bin/README.md
new file mode 100644
index 00000000000..fae0051fb37
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/README.md
@@ -0,0 +1,42 @@
+Quick descriptions of the scripts in tracing/bin/:
+
+ * `chartjson2histograms`: Converts a chartjson file to HistogramSet JSON.
+ * `compare_samples`: Compares metric results between two runs. Supports
+ chart-json, HistogramSet JSON, and buildbot formats.
+ * `generate_about_tracing_contents`: Vulcanizes trace viewer.
+ * `histograms2csv`: Converts HistogramSet JSON to CSV.
+ * `histograms2html`: Vulcanizes results.html. Optionally copies HistogramSet
+ JSON from existing results.html and/or histograms.json file.
+ * `html2trace`: Extracts trace JSON from a vulcanized trace HTML file.
+ * `label_histograms`: Add a label to Histograms in an HTML or JSON file.
+ * `map_traces`: Runs a trace map function over multiple traces. See also
+ `run_metric`.
+ * `memory_infra_remote_dump`: Extracts before/after memory dumps from a
+ devtools remote protocol port.
+ * `merge_histograms`: Merges Histograms from HistogramSet JSON according to a
+ sequence of grouping keys, produces a new HistogramSet JSON.
+ * `merge_traces`: Merge traces from either vulcanized HTML or JSON files to
+ either a vulcanized HTML or a JSON file.
+ * `results2json`: Extracts HistogramSet JSON from a results.html file.
+ * `run_dev_server_tests`: Automatically run tracing dev server tests.
+ * `run_metric`: Run a metric over one or more traces, produce vulcanized
+ results.html.
+ * `run_node_tests`: Automatically run headless tracing tests in node.
+ * `run_py_tests`: Automatically run tracing python tests.
+ * `run_tests`: Automatically run all tracing tests.
+ * `run_vinn_tests`: Automatically run headless tracing tests in vinn.
+ * `slim_trace`: Reads trace data from either HTML or JSON, removes some data,
+ writes a new `slimmed_$filename` file.
+ * `strip_memory_infra_trace`: Reads memory trace JSON, removes some data,
+ writes a new `$filename-filtered.json` file.
+ * `symbolize_trace`: Modifies trace JSON to symbolize symbols using a Chromium
+ Debug build output directory.
+ * `trace2html`: Vulcanizes trace data from a JSON file to an HTML file.
+ * `update_gni`: Updates `trace_viewer.gni`.
+ * `validate_all_diagnostics`: Checks that all Diagnostic classes in
+ `tracing/tracing/value/diagnostics/` are registered correctly.
+ * `validate_all_metrics`: Checks that all metric functions in
+ `tracing/tracing/metrics/` are registered correctly.
+ * `vulcanize_trace_viewer`: Vulcanizes trace viewer. (TODO(benjhayden): What is
+ the difference between this and `generate_about_tracing_contents`?)
+ * `why_imported`: Explain why given modules are imported in trace viewer.
diff --git a/chromium/third_party/catapult/tracing/bin/add_reserved_diagnostics b/chromium/third_party/catapult/tracing/bin/add_reserved_diagnostics
new file mode 100755
index 00000000000..57b835b5285
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/add_reserved_diagnostics
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import json
+import sys
+import os
+
+tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+sys.path.append(tracing_path)
+import tracing_project
+tracing_project.UpdateSysPathIfNeeded()
+from py_utils import camel_case
+from tracing.value.diagnostics import add_reserved_diagnostics
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import reserved_infos
+
+
+LOG_URLS_CAMELCASE = camel_case.ToUnderscore(reserved_infos.LOG_URLS.name)
+LOG_URLS_K = LOG_URLS_CAMELCASE + '_k'
+LOG_URLS_V = LOG_URLS_CAMELCASE + '_v'
+
+BUILD_URLS_CAMELCASE = camel_case.ToUnderscore(reserved_infos.BUILD_URLS.name)
+BUILD_URLS_K = BUILD_URLS_CAMELCASE + '_k'
+BUILD_URLS_V = BUILD_URLS_CAMELCASE + '_v'
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Adds reserved diagnostics to a HistogramSet.',
+ add_help=False)
+ parser.add_argument('input_path',
+ help='HistogramSet JSON file path (input).')
+ parser.add_argument(
+ '--stdout',
+ action='store_true',
+ help='If present, will print the new HistogramSet instead of '
+ 'clobbering the file referenced by input_path.')
+ parser.add_argument(
+ '--output_path',
+ help='If present, will write new HistogramSet to this file instead of '
+ 'clobbering the file referenced by input_path.')
+ parser.add_argument('-h', '--help', action='help',
+ help='Show this help message and exit.')
+ arg_names_to_infos = {}
+ for info in reserved_infos.AllInfos():
+ if info.type == 'GenericSet':
+ name = camel_case.ToUnderscore(info.name)
+ arg_names_to_infos[name] = info
+ parser.add_argument('--%s' % name)
+
+ # TODO(#3770): Clean this up.
+ parser.add_argument('--%s' % LOG_URLS_K)
+ parser.add_argument('--%s' % LOG_URLS_V)
+
+ parser.add_argument('--%s' % BUILD_URLS_K)
+ parser.add_argument('--%s' % BUILD_URLS_V)
+
+ args = parser.parse_args()
+
+ names_to_values = {}
+ for name, value in vars(args).iteritems():
+ if name == LOG_URLS_K and value is not None:
+ v_value = vars(args)[LOG_URLS_V]
+ names_to_values[reserved_infos.LOG_URLS.name] = [value, v_value]
+ continue
+ if name == BUILD_URLS_K and value is not None:
+ v_value = vars(args)[BUILD_URLS_V]
+ names_to_values[reserved_infos.BUILD_URLS.name] = [value, v_value]
+ continue
+ if name in arg_names_to_infos and value is not None:
+ diagnostic_name = arg_names_to_infos[name].name
+ ctor = arg_names_to_infos[name].entry_type
+ names_to_values[diagnostic_name] = ctor(value)
+
+ with open(args.input_path, 'r') as f:
+ dicts = json.loads(f.read())
+
+ results_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ dicts, names_to_values)
+
+ if args.stdout:
+ print results_json
+ else:
+ path = args.output_path or args.input_path
+ with open(path, 'w') as f:
+ f.write(results_json)
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/tracing/bin/chartjson2histograms.py b/chromium/third_party/catapult/tracing/bin/chartjson2histograms.py
new file mode 100755
index 00000000000..1d8f36a641f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/chartjson2histograms.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import sys
+import os
+
+TRACING_PATH = os.path.abspath(
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
+sys.path.append(TRACING_PATH)
+import tracing_project # pylint: disable=wrong-import-position
+tracing_project.UpdateSysPathIfNeeded()
+
+from tracing.value import convert_chart_json # pylint: disable=wrong-import-position
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Converts a chartjson file to HistogramSet JSON.',
+ add_help=False)
+ parser.add_argument('chartjson_path',
+ help='chartjson file path (input).')
+ parser.add_argument('histograms_path',
+ help='HistogramSet JSON file path (output).')
+ parser.add_argument('-h', '--help', action='help',
+ help='Show this help message and exit.')
+ args = parser.parse_args()
+ result = convert_chart_json.ConvertChartJson(args.chartjson_path)
+ if result.returncode != 0:
+ sys.stderr.write(result.stdout)
+ else:
+ file(args.histograms_path, 'w').write(result.stdout)
+ return result.returncode
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/tracing/bin/compare_samples b/chromium/third_party/catapult/tracing/bin/compare_samples
new file mode 100755
index 00000000000..0d67a997837
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/compare_samples
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import sys
+
+tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ '..'))
+sys.path.append(tracing_path)
+from tracing.metrics import compare_samples
+
+def Main(argv):
+ parser = argparse.ArgumentParser(
+ description='Compare samples.')
+ parser.add_argument('sample_a', type=str,
+ help='comma-separated list of paths to valuesets from '
+ 'sample a')
+ parser.add_argument('sample_b', type=str,
+ help='comma-separated list of paths to valuesets from '
+ 'sample b')
+ parser.add_argument('metric', type=str,
+ help='name of the metric to compare')
+ parser.add_argument('--chartjson', dest='format', action='store_const',
+ const='chartjson',
+ help='assume chartjson format for the input data')
+ parser.add_argument('--buildbot', dest='format', action='store_const',
+ const='buildbot',
+ help='assume buildbot result line format for the data')
+ args = parser.parse_args(argv[1:])
+
+ if not args.format:
+ filename = os.path.basename(sample_a.split(',')[0])
+ args.format = 'chartjson'
+
+ vinn_result = compare_samples.CompareSamples(
+ args.sample_a,
+ args.sample_b,
+ args.metric,
+ args.format
+ )
+ stdout = vinn_result.stdout
+ if not isinstance(stdout, str):
+ stdout = stdout.decode('utf-8')
+ print(stdout)
+ return vinn_result.returncode
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/generate_about_tracing_contents b/chromium/third_party/catapult/tracing/bin/generate_about_tracing_contents
new file mode 100755
index 00000000000..feee8828976
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/generate_about_tracing_contents
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+ sys.path.append(tracing_path)
+ from tracing_build import generate_about_tracing_contents
+ sys.exit(generate_about_tracing_contents.Main(sys.argv[1:]))
diff --git a/chromium/third_party/catapult/tracing/bin/histograms2csv b/chromium/third_party/catapult/tracing/bin/histograms2csv
new file mode 100755
index 00000000000..c36246ec3d2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/histograms2csv
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import codecs
+import json
+import sys
+import os
+
+tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+sys.path.append(tracing_path)
+import tracing_project
+tracing_project.UpdateSysPathIfNeeded()
+
+from tracing.value import histograms_to_csv
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Convert HistogramSet JSON to CSV.',
+ add_help=False)
+ parser.add_argument('json_path',
+ help='HistogramSet JSON file path (input).')
+ parser.add_argument('csv_path',
+ help='CSV file path (output).')
+ parser.add_argument('-h', '--help', action='help',
+ help='Show this help message and exit.')
+ args = parser.parse_args()
+ result = histograms_to_csv.HistogramsToCsv(args.json_path)
+ if result.returncode != 0:
+ sys.stderr.write(result.stdout)
+ else:
+ file(args.csv_path, 'w').write(result.stdout)
+ return result.returncode
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/tracing/bin/histograms2html b/chromium/third_party/catapult/tracing/bin/histograms2html
new file mode 100755
index 00000000000..454c98d154f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/histograms2html
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import codecs
+import json
+import sys
+import os
+
+tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+sys.path.append(tracing_path)
+from tracing_build import render_histograms_viewer
+from tracing_build import vulcanize_histograms_viewer
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Upgrade a results.html or add a new HistogramSet.',
+ add_help=False)
+ parser.add_argument('html_path', metavar='HTML_PATH',
+ help='HTML file path (output).')
+ parser.add_argument('-h', '--help', action='help',
+ help='Show this help message and exit.')
+ parser.add_argument('--html', nargs='+', default=[],
+ help='Zero or more HTML file paths (input).')
+ parser.add_argument('--json', nargs='+', default=[],
+ help='Zero or more HistogramSet JSON file paths (input).')
+ parser.add_argument('--mapresults', nargs='+', default=[],
+ help='Zero or more map results JSON file paths (input).')
+ args = parser.parse_args()
+
+ histograms = []
+
+ for html_path in args.html:
+ histograms.extend(render_histograms_viewer.ReadExistingResults(
+ open(html_path, 'r').read()))
+
+ for json_path in args.json:
+ histograms.extend(json.load(open(json_path, 'r')))
+
+ for json_path in args.mapresults:
+ for filename, results in json.load(open(json_path, 'r')).iteritems():
+ for histogram in results['pairs']['histograms']:
+ histograms.append(histogram)
+
+ open(args.html_path, 'a').close() # Create file if it doesn't exist.
+ with codecs.open(args.html_path,
+ mode='r+', encoding='utf-8') as output_stream:
+ vulcanize_histograms_viewer.VulcanizeAndRenderHistogramsViewer(
+ histograms, output_stream)
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/tracing/bin/html2trace b/chromium/third_party/catapult/tracing/bin/html2trace
new file mode 100755
index 00000000000..82161fb1cfd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/html2trace
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import codecs
+import sys
+import os
+
+tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+sys.path.append(tracing_path)
+from tracing_build import html2trace
+
+
+def main():
+ parser = argparse.ArgumentParser(description='Extract trace data from an '
+ 'HTML trace.', add_help=False)
+ parser.add_argument('html_path', metavar='HTML_PATH',
+ help='HTML file path (input).')
+ parser.add_argument('trace_path', metavar='TRACE_PATH',
+ help='Trace file path (output). If the HTML file '
+ 'contains more than one trace data block, the first '
+ 'block will be extracted into %(metavar)s and the rest '
+ 'will be extracted into separate files %(metavar)s.1, '
+ '%(metavar)s.2, etc.')
+ parser.add_argument('--gzipped_output', choices=['true', 'false', 'auto'],
+ default='auto', help='Flag whether the output trace '
+ 'file should be gzipped.')
+ parser.add_argument('-q', '--quiet', action='store_true',
+ help='Don\'t print the saved file name(s).')
+ parser.add_argument('-h', '--help', action='help',
+ help='Show this help message and exit.')
+ args = parser.parse_args()
+
+ if args.gzipped_output == 'true':
+ gzipped_output = True
+ elif args.gzipped_output == 'false':
+ gzipped_output = False
+ else:
+ gzipped_output = args.trace_path.endswith('.gz')
+
+ with codecs.open(args.html_path, mode='r', encoding='utf-8') as html_file:
+ saved_paths = html2trace.CopyTraceDataFromHTMLFilePath(
+ html_file, args.trace_path, gzipped_output)
+
+ if not args.quiet:
+ print '\n'.join(saved_paths)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/tracing/bin/index.html b/chromium/third_party/catapult/tracing/bin/index.html
new file mode 100644
index 00000000000..a4f68f0635e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/index.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+<script>
+'use strict';
+
+function onTraceViewerImportFail() {
+ document.addEventListener('DOMContentLoaded', function() {
+ document.body.textContent =
+ 'tracing/bin/trace_viewer_full.html is missing. ' +
+ 'Run vulcanize_trace_viewer from $TRACE_VIEWER and reload.';
+ });
+}
+</script>
+<link rel="import" href="trace_viewer_full.html"
+ onerror="onTraceViewerImportFail(event)">
+
+<style>
+ html, body {
+ box-sizing: border-box;
+ overflow: hidden;
+ margin: 0px;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+ }
+ #trace-viewer {
+ width: 100%;
+ height: 100%;
+ }
+ #trace-viewer:focus {
+ outline: none;
+ }
+</style>
+<script>
+'use strict';
+
+(function() {
+ var viewer;
+ var url;
+ var model;
+
+ function load() {
+ var req = new XMLHttpRequest();
+ var isBinary = /[.]gz$/.test(url) || /[.]zip$/.test(url);
+ req.overrideMimeType('text/plain; charset=x-user-defined');
+ req.open('GET', url, true);
+ if (isBinary)
+ req.responseType = 'arraybuffer';
+
+ req.onreadystatechange = function(event) {
+ if (req.readyState !== 4)
+ return;
+
+ window.setTimeout(function() {
+ if (req.status === 200)
+ onResult(isBinary ? req.response : req.responseText);
+ else
+ onResultFail(req.status);
+ }, 0);
+ };
+ req.send(null);
+ }
+
+ function onResultFail(err) {
+ var overlay = new tr.ui.b.Overlay();
+ overlay.textContent = err + ': ' + url + ' could not be loaded';
+ overlay.title = 'Failed to fetch data';
+ overlay.visible = true;
+ }
+
+ function onResult(result) {
+ model = new tr.Model();
+ var i = new tr.importer.Import(model);
+ var p = i.importTracesWithProgressDialog([result]);
+ p.then(onModelLoaded, onImportFail);
+ }
+
+ function onModelLoaded() {
+ viewer.model = model;
+ viewer.viewTitle = url;
+ }
+
+ function onImportFail() {
+ var overlay = new tr.ui.b.Overlay();
+ overlay.textContent = tr.b.normalizeException(err).message;
+ overlay.title = 'Import error';
+ overlay.visible = true;
+ }
+
+ document.addEventListener('DOMContentLoaded', function() {
+ var container = document.createElement('track-view-container');
+ container.id = 'track_view_container';
+
+ viewer = document.createElement('tr-ui-timeline-view');
+ viewer.track_view_container = container;
+ Polymer.dom(viewer).appendChild(container);
+
+ viewer.id = 'trace-viewer';
+ viewer.globalMode = true;
+ Polymer.dom(document.body).appendChild(viewer);
+
+ url = '../test_data/big_trace.json';
+ load();
+ });
+}());
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/tracing/bin/label_histograms b/chromium/third_party/catapult/tracing/bin/label_histograms
new file mode 100755
index 00000000000..07488964b99
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/label_histograms
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import codecs
+import json
+import sys
+import os
+
+tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+sys.path.append(tracing_path)
+from tracing.value import histogram_set
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import reserved_infos
+from tracing_build import render_histograms_viewer
+from tracing_build import vulcanize_histograms_viewer
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Add a label to Histograms in an HTML or JSON file.',
+ add_help=False)
+ parser.add_argument('path', metavar='PATH',
+ help='HTML file path (output).')
+ parser.add_argument('label', metavar='LABEL',
+ help='The label to add to Histograms.')
+ args = parser.parse_args()
+
+ histograms = []
+
+ if args.path.endswith('.html'):
+ histograms.extend(render_histograms_viewer.ReadExistingResults(
+ open(args.path, 'r').read()))
+ elif args.path.endswith('.json'):
+ histograms.extend(json.load(open(json_path, 'r')))
+ else:
+ raise Error('Use either .html or .json extension.')
+ histograms = histogram_set.HistogramSet(histograms)
+ histograms.AddSharedDiagnosticToAllHistograms(
+ reserved_infos.LABELS.name,
+ generic_set.GenericSet([args.label]))
+
+ with codecs.open(args.path,
+ mode='r+', encoding='utf-8') as output_stream:
+ if args.path.endswith('.html'):
+ vulcanize_histograms_viewer.VulcanizeAndRenderHistogramsViewer(
+ histograms, output_stream)
+ else:
+ json.dump(histograms.AsDicts(), output_stream)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/tracing/bin/map_traces b/chromium/third_party/catapult/tracing/bin/map_traces
new file mode 100755
index 00000000000..af58491504d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/map_traces
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ '..'))
+ sys.path.append(tracing_path)
+ from tracing.mre import map_traces
+ sys.exit(map_traces.Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/memory_infra_remote_dump b/chromium/third_party/catapult/tracing/bin/memory_infra_remote_dump
new file mode 100755
index 00000000000..3125e9fe10d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/memory_infra_remote_dump
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Grabs before/after memory dumps using the devtools remote protocol.
+
+To use it you first start Chrome with remote debugging enabled then run the
+script which will take a memory dump, wait for you to press enter, take
+another memory dump and finally save a trace file. For example:
+
+On OSX:
+$ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
+ --remote-debugging-port=9222 \\
+ --memlog=all --memlog-sampling --memlog-stack-mode=pseudo \\
+$ ./tracing/bin/memory_infra_remote_dump --port=9222
+...
+[Press enter to stop tracing]
+...
+/var/folders/18/gl6q632j20nc_tw5g9l03dhc007g45/T/trace_20s191.json: 835 KB
+
+On Android:
+$ ./build/android/adb_chrome_public_command_line \\
+ --memlog=all --memlog-sampling --memlog-stack-mode=pseudo \\
+ --enable-remote-debugging
+$ ./build/android/adb_run_chrome_public
+$ adb forward tcp:1234 localabstract:chrome_devtools_remote
+$ ./third_party/catapult/tracing/bin/memory_infra_remote_dump --port=1234
+...
+[Press enter to stop tracing]
+...
+/var/folders/18/gl6q632j20nc_tw5g9l03dhc007g45/T/trace_20s191.json: 835 KB
+"""
+
+import argparse
+import json
+import os
+import requests
+import sys
+import tempfile
+import time
+
+try:
+ import websocket
+except ImportError:
+ print 'Please run: pip install --user websocket-client'
+ sys.exit(1)
+
+
+class TracingDevtoolsClient(object):
+ def __init__(self, host, port):
+ r = requests.get('http://%s:%s/json/version' % (host, port))
+ url = r.json()['webSocketDebuggerUrl']
+ print 'Connecting to ' + url
+ self.ws = websocket.create_connection(url)
+ self.cmd = 0
+
+ def send(self, method, params={}):
+ self.cmd += 1
+ self.ws.send(
+ json.dumps({'id': self.cmd, 'method': method, 'params': params}))
+ resp = self.recv()
+ assert resp['id'] == self.cmd
+ return resp.get('result', {})
+
+ def recv(self):
+ return json.loads(self.ws.recv())
+
+ def req_memory_dump(self):
+ print 'Requesting memory dump...',
+ resp = self.send('Tracing.requestMemoryDump')
+ assert resp['success'] == True
+ print ' ...done'
+
+ def dump(self, trace_fd):
+ trace_config = {
+ 'excludedCategories': ['*'],
+ 'includedCategories': ['disabled-by-default-memory-infra'],
+ 'memoryDumpConfig': {'triggers': []}
+ }
+ print 'Starting trace with trace_config', trace_config
+ params = {'traceConfig': trace_config, 'transferMode': 'ReturnAsStream'}
+ self.send('Tracing.start', params)
+ self.req_memory_dump()
+
+ if sys.stdin.isatty():
+ while True:
+ try:
+ print '[Press enter to trigger a new dump, q to finish the trace]'
+ cmd = raw_input()
+ except KeyboardInterrupt:
+ break
+ if cmd == 'q':
+ break
+ self.req_memory_dump()
+
+ self.send('Tracing.end')
+
+ # Wait for trace completion
+ print 'Flushing trace'
+ resp = self.recv()
+ assert resp['method'] == 'Tracing.tracingComplete'
+ stream_handle = resp['params']['stream']
+
+ # Read back the trace stream
+ resp = {'eof': False}
+ while not resp['eof']:
+ resp = self.send('IO.read', {'handle': stream_handle})
+ trace_fd.write(resp['data'].encode('utf-8'))
+
+ self.send('IO.close', {'handle': stream_handle})
+ trace_fd.close()
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(
+ description=__doc__,
+ formatter_class=argparse.RawTextHelpFormatter)
+ parser.add_argument('--host', default='localhost')
+ parser.add_argument('--port', '-p', default=9222)
+ parser.add_argument('--output-trace', '-o', default=None)
+ args = parser.parse_args()
+
+ if args.output_trace is None:
+ trace_fd = tempfile.NamedTemporaryFile(prefix='trace_', suffix='.json',
+ delete=False)
+ else:
+ trace_fd = open(args.output_trace, 'wb')
+
+ cli = TracingDevtoolsClient(args.host, args.port)
+ cli.dump(trace_fd)
+ print '\n%s: %d KB' % (trace_fd.name, os.stat(trace_fd.name).st_size / 1000)
diff --git a/chromium/third_party/catapult/tracing/bin/merge_histograms b/chromium/third_party/catapult/tracing/bin/merge_histograms
new file mode 100755
index 00000000000..1d3f1ccca12
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/merge_histograms
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import json
+import os
+import sys
+
+tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+sys.path.append(tracing_path)
+from tracing.value import merge_histograms
+
+def Main(argv):
+ parser = argparse.ArgumentParser(
+ description='Merge Histograms.')
+ parser.add_argument('input', type=str,
+ help='Path to a HistogramSet JSON file. (input)')
+ parser.add_argument('output', type=str,
+ help='Path to a HistogramSet JSON file. (output)')
+ parser.add_argument('groupby', nargs='+',
+ help='One or more grouping keys (name, benchmark, ' +
+ 'time, storyset_repeat, story_repeat, story, tir, label)')
+ args = parser.parse_args(argv[1:])
+
+ merged = merge_histograms.MergeHistograms(args.input, args.groupby)
+ json.dump(merged, file(args.output, 'w'))
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/merge_traces b/chromium/third_party/catapult/tracing/bin/merge_traces
new file mode 100755
index 00000000000..4b610dd0699
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/merge_traces
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+ sys.path.append(tracing_path)
+ from tracing_build import merge_traces
+ sys.exit(merge_traces.Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/results2json b/chromium/third_party/catapult/tracing/bin/results2json
new file mode 100755
index 00000000000..fe90f196614
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/results2json
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import json
+import sys
+import os
+
+tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+sys.path.append(tracing_path)
+from tracing_build import render_histograms_viewer
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Extract HistogramSet JSON from results.html.',
+ add_help=False)
+ parser.add_argument('html_path', metavar='HTML_PATH',
+ help='HTML file path (input).')
+ parser.add_argument('json_path', metavar='JSON_PATH',
+ help='JSON file path (input/output).')
+ parser.add_argument('-h', '--help', action='help',
+ help='Show this help message and exit.')
+ args = parser.parse_args()
+
+ histograms = render_histograms_viewer.ReadExistingResults(
+ open(args.html_path, 'r').read())
+ if os.path.exists(args.json_path):
+ histograms.extend(json.load(open(args.json_path, 'r')))
+ json.dump(histograms, open(args.json_path, 'w'))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/third_party/catapult/tracing/bin/run_dev_server_tests b/chromium/third_party/catapult/tracing/bin/run_dev_server_tests
new file mode 100755
index 00000000000..bd09476721e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/run_dev_server_tests
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..', '..'))
+ sys.path.append(tracing_path)
+ from catapult_build import run_dev_server_tests
+ sys.exit(run_dev_server_tests.Main(sys.argv + ['--tests=tracing']))
diff --git a/chromium/third_party/catapult/tracing/bin/run_metric b/chromium/third_party/catapult/tracing/bin/run_metric
new file mode 100755
index 00000000000..d10719141c0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/run_metric
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import codecs
+import json
+import os
+import sys
+
+sys.path.insert(1, os.path.join(os.path.dirname(__file__), '..'))
+from tracing_build import vulcanize_histograms_viewer
+from tracing.metrics import metric_runner
+from tracing.metrics import discover
+
+def Main(argv):
+ all_metrics = discover.DiscoverMetrics(
+ ['/tracing/metrics/all_metrics.html'])
+
+ parser = argparse.ArgumentParser(
+ description='Runs metrics on local traces')
+ parser.add_argument('trace_file_or_dir',
+ help='A trace file, or a dir containing trace files')
+ parser.add_argument('metrics', nargs='+',
+ help=('Function names of registered metrics '
+ '(not filenames.) '
+ 'Available metrics are: %s' %
+ ', '.join(all_metrics)),
+ choices=all_metrics, metavar='metricName')
+ parser.add_argument('--filename', default='results', type=str,
+ help='Output file name (no extension)')
+ parser.add_argument('--reset', action='store_true',
+ help=('Whether to ignore existing results in HTML file '
+ '(if it exists'))
+ parser.add_argument('--also-output-json', action='store_true',
+ help=('Also output json file containing values. Note that'
+ 'this only contains the results of current run'))
+
+ args = parser.parse_args(argv[1:])
+ trace_file_or_dir = os.path.abspath(args.trace_file_or_dir)
+
+ if os.path.isdir(trace_file_or_dir):
+ trace_dir = trace_file_or_dir
+ traces = [os.path.join(trace_dir, trace) for trace in os.listdir(trace_dir)]
+ else:
+ traces = [trace_file_or_dir]
+
+ failures = []
+ histograms = []
+ for trace_url, mre_result in metric_runner.RunMetricOnTraces(
+ traces, args.metrics).iteritems():
+ failures.extend(mre_result.failures)
+ histograms.extend(mre_result.pairs.get('histograms', []))
+
+ if failures:
+ print 'Running metric failed:'
+ for failure in failures:
+ print failure.stack
+
+ output_file = args.filename + '.html'
+ open(output_file, 'a').close() # Create file if it doesn't exist.
+ with codecs.open(output_file, mode='r+', encoding='utf-8') as output_stream:
+ vulcanize_histograms_viewer.VulcanizeAndRenderHistogramsViewer(
+ histograms, output_stream, args.reset)
+ print 'HTML result created in file://' + os.path.abspath(output_file)
+
+ if args.also_output_json:
+ output_file = args.filename + '.json'
+ with open(output_file, 'w') as f:
+ json.dump(histograms, f, indent=2, sort_keys=True, separators=(',', ': '))
+ print 'JSON result created in file://' + os.path.abspath(output_file)
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/run_node_tests b/chromium/third_party/catapult/tracing/bin/run_node_tests
new file mode 100755
index 00000000000..d044e0f1c22
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/run_node_tests
@@ -0,0 +1,23 @@
+#!/usr/bin/env node
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var catapultPath = fs.realpathSync(path.join(__dirname, '..', '..'));
+var catapultBuildPath = path.join(catapultPath, 'catapult_build');
+
+var node_bootstrap = require(path.join(catapultBuildPath, 'node_bootstrap.js'));
+
+HTMLImportsLoader.addArrayToSourcePath(
+ node_bootstrap.getSourcePathsForProject('tracing'));
+
+// Go!
+var headless_test_module_filenames =
+ node_bootstrap.getHeadlessTestModuleFilenamesForProject('tracing');
+
+HTMLImportsLoader.loadHTML('/tracing/base/headless_tests.html');
+tr.b.unittest.loadAndRunTests(headless_test_module_filenames); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/bin/run_py_tests b/chromium/third_party/catapult/tracing/bin/run_py_tests
new file mode 100755
index 00000000000..e81cb180b79
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/run_py_tests
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import platform
+import sys
+
+_CATAPULT_PATH = os.path.abspath(
+ os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ os.path.pardir,
+ os.path.pardir))
+_TRACING_PATH = os.path.join(_CATAPULT_PATH, 'tracing')
+
+sys.path.insert(0, _TRACING_PATH)
+from tracing import tracing_project
+
+
+def _RunTestsOrDie(top_level_dir):
+ path = [_TRACING_PATH]
+ path.extend(tracing_project.GetDependencyPaths())
+ exit_code = run_with_typ.Run(top_level_dir, path=path)
+ if exit_code:
+ sys.exit(exit_code)
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+if __name__ == '__main__':
+ _AddToPathIfNeeded(_CATAPULT_PATH)
+
+ from hooks import install
+ if '--no-install-hooks' in sys.argv:
+ sys.argv.remove('--no-install-hooks')
+ else:
+ install.InstallHooks()
+
+ from catapult_build import run_with_typ
+ _RunTestsOrDie(os.path.join(_TRACING_PATH, 'tracing'))
+ _RunTestsOrDie(os.path.join(_TRACING_PATH, 'tracing_build'))
+ sys.exit(0)
diff --git a/chromium/third_party/catapult/tracing/bin/run_symbolizer_tests b/chromium/third_party/catapult/tracing/bin/run_symbolizer_tests
new file mode 100755
index 00000000000..3f311753676
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/run_symbolizer_tests
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+The symbolizer tests take a long time to run [potentially 5+ minutes each], so
+they are invoked directly from separately from run_py_tests.
+"""
+
+import os
+import sys
+
+_CATAPULT_PATH = os.path.abspath(
+ os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ os.path.pardir,
+ os.path.pardir))
+_TRACING_PATH = os.path.join(_CATAPULT_PATH, 'tracing')
+
+
+def _RunTestsOrDie(top_level_dir):
+ exit_code = run_with_typ.Run(top_level_dir, path=[_TRACING_PATH],
+ suffixes=['*_test_slow.py'])
+ if exit_code:
+ sys.exit(exit_code)
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+if __name__ == '__main__':
+ _AddToPathIfNeeded(_CATAPULT_PATH)
+
+ from catapult_build import run_with_typ
+ _RunTestsOrDie(os.path.join(_TRACING_PATH, 'tracing', 'extras', 'symbolizer'))
+ sys.exit(0)
diff --git a/chromium/third_party/catapult/tracing/bin/run_tests b/chromium/third_party/catapult/tracing/bin/run_tests
new file mode 100755
index 00000000000..3f94c67af0b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/run_tests
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+
+_THIS_PATH = os.path.dirname(os.path.realpath(__file__))
+_TESTS = [
+ {'path': os.path.join(_THIS_PATH, 'run_py_tests')},
+ {'path': os.path.join(_THIS_PATH, 'run_vinn_tests'),
+ 'disabled': {'win32'}},
+ {'path': os.path.join(_THIS_PATH, 'run_dev_server_tests'),
+ 'chrome_path_arg': True}
+]
+
+
+if __name__ == '__main__':
+ catapult_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..', '..'))
+ sys.path.append(catapult_path)
+ from catapult_build import test_runner
+ sys.exit(test_runner.Main('tracing', _TESTS, sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/run_vinn_tests b/chromium/third_party/catapult/tracing/bin/run_vinn_tests
new file mode 100755
index 00000000000..42ec180f119
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/run_vinn_tests
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+ sys.path.append(tracing_path)
+ from tracing_build import run_vinn_tests
+ sys.exit(run_vinn_tests.Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/slim_trace b/chromium/third_party/catapult/tracing/bin/slim_trace
new file mode 100755
index 00000000000..2e170777840
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/slim_trace
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import os
+
+tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+sys.path.append(tracing_path)
+from tracing_build import slim_trace
+
+
+if __name__ == '__main__':
+ sys.exit(slim_trace.Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/strip_memory_infra_trace b/chromium/third_party/catapult/tracing/bin/strip_memory_infra_trace
new file mode 100755
index 00000000000..8bdc8375d75
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/strip_memory_infra_trace
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ sys.path.append(tracing_path)
+ from tracing_build import strip_memory_infra_trace
+ sys.exit(strip_memory_infra_trace.Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/symbolize_trace b/chromium/third_party/catapult/tracing/bin/symbolize_trace
new file mode 100755
index 00000000000..c2bee858e43
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/symbolize_trace
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+tracing_path = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..'))
+sys.path.append(tracing_path)
+import tracing_project
+tracing_project.UpdateSysPathIfNeeded()
+
+if __name__ == '__main__':
+ from tracing.extras.symbolizer import symbolize_trace
+ sys.exit(symbolize_trace.main(sys.argv[1:]))
diff --git a/chromium/third_party/catapult/tracing/bin/trace2html b/chromium/third_party/catapult/tracing/bin/trace2html
new file mode 100755
index 00000000000..0457d39a66b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/trace2html
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import os
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+ sys.path.append(tracing_path)
+ from tracing_build import trace2html
+ sys.exit(trace2html.Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/update_gni b/chromium/third_party/catapult/tracing/bin/update_gni
new file mode 100755
index 00000000000..b2bc2291846
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/update_gni
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+ sys.path.append(tracing_path)
+ from tracing_build import update_gni
+ sys.exit(update_gni.Update())
diff --git a/chromium/third_party/catapult/tracing/bin/validate_all_diagnostics b/chromium/third_party/catapult/tracing/bin/validate_all_diagnostics
new file mode 100755
index 00000000000..f8bd5badaf0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/validate_all_diagnostics
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import json
+import os
+import string
+import sys
+
+sys.path.insert(
+ 1,
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
+import tracing_project
+tracing_project.UpdateSysPathIfNeeded()
+
+from py_utils import camel_case
+from py_utils import discover
+
+from tracing.value.diagnostics import diagnostic
+from tracing.value.diagnostics import all_diagnostics
+
+import vinn
+
+
+_DISCOVER_CMDLINE = os.path.join(
+ os.path.dirname(__file__), '..', 'tracing', 'value', 'diagnostics',
+ 'discover_cmdline.html')
+
+
+def DiscoverJSDiagnostics(project, js_args):
+ res = vinn.RunFile(_DISCOVER_CMDLINE, source_paths=list(project.source_paths),
+ js_args=js_args)
+ if res.returncode != 0:
+ raise RuntimeError('Error running diagnostics/discover_cmdline: ' + res.stdout)
+ else:
+ return set([str(m) for m in json.loads(res.stdout)])
+
+
+def DiscoverPythonDiagnostics():
+ return discover.DiscoverClasses(
+ os.path.join(tracing_project.TracingProject.tracing_src_path,
+ 'value'),
+ tracing_project.TracingProject.tracing_root_path,
+ diagnostic.Diagnostic, index_by_class_name=True)
+
+
+def CheckPythonDiagnostics():
+ discovered_diagnostics = DiscoverPythonDiagnostics()
+
+ registered_diagnostic_names = [
+ camel_case.ToUnderscore(name)
+ for name in all_diagnostics.GetDiagnosticTypenames()]
+
+ unregistered_diagnostics = (set(discovered_diagnostics.keys()) -
+ set(registered_diagnostic_names))
+
+ return_code = 0
+ if unregistered_diagnostics:
+ print ('These diagnostics are unregistered: %s. Please add them to '
+ 'tracing/tracing/value/diagnostics/all_diagnostics.py.' %
+ ', '.join(unregistered_diagnostics))
+ return_code = 1
+
+ for name in all_diagnostics.GetDiagnosticTypenames():
+ diagnostic = all_diagnostics.GetDiagnosticClassForName(name)
+ if name != diagnostic.__name__:
+ print 'This diagnostic refers to the wrong class: %s: %s' % (
+ name, diagnostic.__name__)
+ return_code = 1
+
+ return return_code
+
+
+def CheckJSDiagnostics():
+ project = tracing_project.TracingProject()
+ all_registered_diagnostics = DiscoverJSDiagnostics(
+ project, ['registry', '/tracing/value/diagnostics/all_diagnostics.html'])
+ all_modules = list(
+ '/' + rel_path for rel_path in
+ tracing_project.TracingProject().FindAllDiagnosticsModuleRelPaths())
+ all_possible_diagnostics = DiscoverJSDiagnostics(
+ project, ['namespace'] + all_modules)
+
+ unregistered_diagnostics = (all_possible_diagnostics -
+ all_registered_diagnostics)
+ if unregistered_diagnostics:
+ print ('These diagnostics are unregistered: %s. Please import their modules in '
+ 'tracing/tracing/value/diagnostics/all_diagnostics.html and '
+ 'ensure that they call Diagnostic.register().' %
+ ', '.join(unregistered_diagnostics))
+ return 1
+
+ lowercased_diagnostics = []
+ for m in all_possible_diagnostics:
+ if str.islower(m[0]):
+ lowercased_diagnostics.append(m)
+ if lowercased_diagnostics:
+ print ('These diagnostics must be renamed to start with a upper-case: %s' %
+ lowercased_diagnostics)
+ return 1
+
+ return 0
+
+
+def Main():
+ return (CheckJSDiagnostics() or CheckPythonDiagnostics())
+
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/chromium/third_party/catapult/tracing/bin/validate_all_metrics b/chromium/third_party/catapult/tracing/bin/validate_all_metrics
new file mode 100755
index 00000000000..b4b26307bc1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/validate_all_metrics
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import json
+import os
+import string
+import sys
+
+sys.path.insert(
+ 1,
+ os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
+from tracing.metrics import discover
+import tracing_project
+
+
+def Main():
+ all_registered_metrics = set(discover.DiscoverMetrics(
+ ['/tracing/metrics/all_metrics.html']))
+ all_modules = list(
+ '/' + rel_path for rel_path in
+ tracing_project.TracingProject().FindAllMetricsModuleRelPaths())
+ all_possible_metrics = set(discover.DiscoverMetrics(all_modules))
+ unregistered_metrics = all_possible_metrics - all_registered_metrics
+ if unregistered_metrics:
+ print ('These metrics are unregistered: %s. Please import their modules in '
+ 'tracing/tracing/metrics/all_metrics.html' %
+ ', '.join(unregistered_metrics))
+ return 1
+ uppercased_metrics = []
+ for m in all_possible_metrics:
+ if str.isupper(m[0]):
+ uppercased_metrics.append(m)
+ if uppercased_metrics:
+ print ('These metrics must be renamed to start with a lower-case: %s' %
+ uppercased_metrics)
+ return 1
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/chromium/third_party/catapult/tracing/bin/vulcanize_trace_viewer b/chromium/third_party/catapult/tracing/bin/vulcanize_trace_viewer
new file mode 100755
index 00000000000..c3602d40447
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/vulcanize_trace_viewer
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+ sys.path.append(tracing_path)
+ from tracing_build import vulcanize_trace_viewer
+ sys.exit(vulcanize_trace_viewer.Main(sys.argv))
diff --git a/chromium/third_party/catapult/tracing/bin/why_imported b/chromium/third_party/catapult/tracing/bin/why_imported
new file mode 100755
index 00000000000..9b5a59a6f49
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bin/why_imported
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Produces a dot file showing dependency relationships between modules.
+
+The dot file contains a text-based representation of a directed graph that
+explains why given module names were included in a trace_viewer config.
+
+Example usage:
+$ ./why_imported tracing.ui.analysis.analysis_view > ~/analysis_view.dot
+
+This can then be converted to a graphical representation with the dot tool:
+$ dot -Grankdir=LR -Tpng ~/analysis_view.dot -o ~/analysis_view.png
+"""
+
+import os
+import sys
+import argparse
+
+
+def Main():
+ project = tracing_project.TracingProject()
+
+ parser = argparse.ArgumentParser(
+ usage='%(prog)s <options> moduleNames', epilog=__doc__)
+ parser.add_argument('--config', choices=project.GetConfigNames())
+ parser.add_argument('module_names', nargs='+')
+ args = parser.parse_args()
+
+ if args.config:
+ names = [project.GetModuleNameForConfigName(options.config)]
+ vulcanizer = project.CreateVulcanizer()
+ load_sequence = vulcanizer.CalcLoadSequenceForModuleNames(names)
+ else:
+ parser.error('No config specified.')
+ print vulcanizer.GetDominatorGraphForModulesNamed(
+ args.module_names, load_sequence)
+
+
+if __name__ == '__main__':
+ tracing_path = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), '..'))
+ sys.path.append(tracing_path)
+ import tracing_project
+ tracing_project.UpdateSysPathIfNeeded()
+ sys.exit(Main())
diff --git a/chromium/third_party/catapult/tracing/bower.json b/chromium/third_party/catapult/tracing/bower.json
new file mode 100644
index 00000000000..429f8995649
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/bower.json
@@ -0,0 +1,22 @@
+{
+ "name": "trace-viewer",
+ "version": "0.0.0",
+ "homepage": "http://google.github.io/trace-viewer",
+ "authors": [
+ "Nat Duca <nduca@chromium.org>",
+ "dan sinclair <dsinclair@chromium.org>"
+ ],
+ "description": "TraceViewer for chrome://tracing and Android Systrace",
+ "license": "BSD",
+ "private": true,
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "trace-viewer/components",
+ "test",
+ "tests"
+ ],
+ "dependencies": {
+ "polymer": "Polymer/polymer#~0.5.5"
+ }
+}
diff --git a/chromium/third_party/catapult/tracing/docs/coordinate-systems.md b/chromium/third_party/catapult/tracing/docs/coordinate-systems.md
new file mode 100644
index 00000000000..011fed4835e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/docs/coordinate-systems.md
@@ -0,0 +1,46 @@
+# Trace-Viewer Coordinate Systems.
+
+## Coordinate Systems
+
+To represent browser content in trace-viewer we need to draw boxes and
+pictures created in one browser in the DOM of another browser window.
+How does a pixel in the output relate to a pixel in the original browser view?
+
+### Scaling
+
+The snapshot view lives in a quad-stack-viewer DOM element. This is area of
+pixels in trace-viewer, for example 685x342 px.
+
+The quad-stack-viewer contains a view-container with a CSS transform. The
+transform will zoom (CSS scale), pan (CSS translateX, translateY),
+orient (CSS rotateX, rotateY) its contents, a canvas. Common scale factors
+will be 0.1 - 2.0. The transformation is controlled by user inputs.
+
+Internally the canvas has the _world_ coordinates.
+
+The _world_ coordinates completely enclose the boxes we may draw, plus some
+padding so the edges of boxes do not sit against the edge of the world. For
+example, padding space of .75 times the minimum of width and height may be
+added. Since the original browser has a few thousand pixels, the padded world
+may be 5-6000 pixels on a side.
+
+The _world_ coordinates are scaled by several factors:
+ * _quad_stack_scale_ adjusts the size of the canvas (eg 0.5).
+ * _devicePixelRatio_ adjusts for high-res devices (eg 1 or 2),
+ * _ui.RASTER_SCALE_, adjusts the size of the canvas. (eg 0.75)
+
+*Do we still need RASTER_SCALE?*
+
+### Translation (origins)
+
+The quad-stack-viewer DOM element is positioned by CSS at some offset in the
+document. All of our origins are relative to the top left corner of the
+quad-stack-viewer.
+
+The CSS transforms move us from the DOM coordinate system to the world system.
+*What is the origin of the canvas in the DOM coordinate system
+when the final size of the canvas is less than the element?*
+
+The _deviceViewportRect_ is the visible browser window in _world_ coordinates.
+Typically it will be at X,Y = 0,0. Thus the _world_ origin will be eg
+-0.75\*3000px , -0.75\*2500px, due to the world padding.
diff --git a/chromium/third_party/catapult/tracing/docs/embedding-trace-viewer.md b/chromium/third_party/catapult/tracing/docs/embedding-trace-viewer.md
new file mode 100644
index 00000000000..2f3778c0d8e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/docs/embedding-trace-viewer.md
@@ -0,0 +1,54 @@
+# Making standalone HTML files
+
+If you have a trace file that you want to turn into a html file with a viewer then:
+
+```
+sys.path.append(os.path.join(path_to_catapult, 'tracing'))
+from trace_viewer_build import trace2html
+with open('my_trace.html', 'w') as new_file:
+ trace2html.WriteHTMLForTracesToFile(['my_trace.json'], new_file)
+```
+
+This will produce a standalone trace viewer with my_trace packed inside.
+
+# Embedding the Easy Way
+Running `$CATAPULT/tracing/bin/vulcanize_trace_viewer` will create `$CATAPULT/tracing/bin/trace_viewer_full.html`. That file has all the js, css and html-templates that you need for a standalone trace viewer instance.
+
+In your code, `<link rel="import" href="trace_viewer_full.html">`. Then, to get a trace viewer up, you need to do two things: make the timeline viewer, and make a model and give it to the viewer:
+```
+ var container = document.createElement('track-view-container');
+ container.id = 'track_view_container';
+
+ viewer = document.createElement('tr-ui-timeline-view');
+ viewer.track_view_container = container;
+ Polymer.dom(viewer).appendChild(container);
+
+ viewer.id = 'trace-viewer';
+ viewer.globalMode = true;
+ Polymer.dom(document.body).appendChild(viewer);
+```
+
+With the viewer created, you need to then make a TraceModel:
+```
+ var model = new tr.Model();
+ var i = new tr.importer.Import(m);
+ var p = i.importTracesWithProgressDialog([result]);
+ p.then(function() {
+ viewer.model = model;
+ }, onImportFail);
+
+```
+
+Model has a variety of import options, from synchronous import to importWithProgressDialog. And, it
+lets you customize the types of postprocessing to be done on the model before it is displayed by the view.
+
+# Configs
+Trace viewer has a lot of extra pieces, for domain-specific use cases. By default, trace2html and vulcanize take everything and combine them together. We call this the "full" config. Passing --help to
+vulcanize or trace2html will show the current set of configs we support, which maps to
+`trace_viewer/extras/*_config.html`. Some of the other configs are smaller, leading to a more compact redistributable.
+
+# Customizing
+For more information on how to customize and extend trace viewer, see [Extending-and-Customizing-Trace-Viewer](Extending-and-Customizing-Trace-Viewer)
+
+# Example
+See bin/index.html for an example of using the embedding system.
diff --git a/chromium/third_party/catapult/tracing/docs/extending-and-customizing-trace-viewer.md b/chromium/third_party/catapult/tracing/docs/extending-and-customizing-trace-viewer.md
new file mode 100644
index 00000000000..aa493ce17e5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/docs/extending-and-customizing-trace-viewer.md
@@ -0,0 +1,26 @@
+Though there are some concepts hold the same across all trace formats we've encountered, there are an always plenty of domain-specific details to a given expertise area that defy standard treatment.
+
+In trace-viewer, we distinguish between "core" pieces, which are domain-neutral and belong in `trace_viewer/core` and domain-specific pieces, which we are in `trace_viewer/extras`. As such, core/ has a variety of extension points that then extras/ pulls in.
+
+# Importers
+TraceViewer is not tied to one specific trace file format: everyone has their own ideal way for getting performance data, storing it, and eventually getting it into the HTML file for viewing. And, since trace-viewer tries to be able to view traces from multiple systems all together, it may not even be possible to get traces into a single file format. Thats fine, as we see it.
+
+The main unit of extension here is the Importer object, `core/importer/importer.html`. To teach trace viewer about a new file format, subclass that importer, then hook it up to `default_importers.html`. Voila, you have the beginnings
+
+When you call TraceModel.import, you pass array of objects. We then run over this array one at a time, then walk through the registered importers looking for one that `.canHandle` that trace. Once it is found, we assign that trace to the importer.
+
+Because some trace formats are container formats, we support sub-traces, where an importer does a bit of processing, then yields another trace that needs more importing. This is, for instance, how we import gzip files.
+
+# Slice Views
+The display and storage of slices can be overridden based on their model-level name and category. This allows domain specific customization of that particular type of data. Some keywords to search for are SliceView.register and AsyncSlice.register.
+
+One way this is used is to customize the display title of a slice. In the trace files and the model, slices with the "net" category are traced with titles that correspond to their probe point. And, the URL of a request is just one of many events in the trace that is discovered quite late in the overall sequence of events. But, when viewing a network trace, the most interesting thing to see is the URL for which a traces corresponds. This transformation is accomplished by registering a custom net async slice, which overrides the `displayTitle` property: this leaves the model in-tact [e.g. exactly as it was traced] but improves on the display.
+
+# Object Views and Types
+In Chrome, some of our traces have a complex and massive JSON dump from our graphics subsystem that, when
+interpreted exactly the right way, let us reconstruct a view of the page just from the trace.
+
+There are two extension points that make this possible:
+- We allow subtypes to be registered for ObjectSnapshots and ObjectInstances. This way you can build up a domain-specific model of the trace instead of having to parse the trace yourself after the fact. See `extras/cc/layer_tree_host_impl.html` for an example.
+
+- We allow custom viewer objects to be registered for Snapshots and Instances. When a user clicks on one, we look for a viewer and use that object instead. See `extras/cc/layer_tree_host_impl_view.html` as an example.
diff --git a/chromium/third_party/catapult/tracing/docs/getting-started.md b/chromium/third_party/catapult/tracing/docs/getting-started.md
new file mode 100644
index 00000000000..472f2f54df6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/docs/getting-started.md
@@ -0,0 +1,21 @@
+Using Trace Viewer Casually
+==================================
+ * [Embedding-Trace-Viewer](https://github.com/catapult-project/catapult/blob/master/tracing/docs/embedding-trace-viewer.md) the trace-viewer in your own app.
+ * How to [extend and customize](https://github.com/catapult-project/catapult/blob/master/tracing/docs/extending-and-customizing-trace-viewer.md) the trace-viewer to suit your domain
+
+Making Traces
+=============
+ * [Trace Event Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit?usp=sharing) if you want to generate traces yourself
+ * [py-trace-event](https://github.com/natduca/py_trace_event) for generating traces from python
+ * [Chrome's trace_event.h](http://src.chromium.org/chrome/trunk/src/base/debug/trace_event.h) if you're in Chrome's ecosystem
+ * [ftrace](https://www.kernel.org/doc/Documentation/trace/ftrace.txt) for generating traces on Linux
+
+Note: trace-viewer supports custom trace file formats. Just [add an importer](https://github.com/catapult-project/catapult/blob/master/tracing/docs/extending-and-customizing-trace-viewer.md) to trace viewer for your favorite file format.
+
+Contributing New Stuff
+======================
+ * Join our Google Groups: [trace-viewer](https://groups.google.com/forum/#!forum/trace-viewer), [trace-viewer-bugs](https://groups.google.com/forum/#!forum/trace-viewer-bugs)
+ * Learn how to start: [Contributing](https://github.com/catapult-project/catapult/blob/master/CONTRIBUTING.md)
+ * Read the [Trace Viewer style guide](https://docs.google.com/document/d/1MMOfywou2Oaho4jOttUk-ZSJcHVd5G5BTsD48rPrBtQ/edit)
+ * Pick a feature from the [tracing wish list](https://docs.google.com/a/chromium.org/document/d/1T1UJHIgImSEPSugCt2TFrkNsraBFITPHpYFGDJStePc/preview).
+ * Familiarize yourself with the [Trace-Viewer's-Internals](https://github.com/catapult-project/catapult/blob/master/tracing/docs/trace-viewer-internals.md).
diff --git a/chromium/third_party/catapult/tracing/docs/trace-viewer-internals.md b/chromium/third_party/catapult/tracing/docs/trace-viewer-internals.md
new file mode 100644
index 00000000000..fc85929cf79
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/docs/trace-viewer-internals.md
@@ -0,0 +1,129 @@
+# TraceViewer’s Internals
+
+## Module system
+
+ * Tracing currently uses html imports for modules.
+ * We aspire to one-class-per file. Feel free to break up big files as you
+encounter them, they exist purely for legacy reasons.
+
+## Tests
+
+ * See unittest.html -- mostly compatible with closure tests
+ * See [[/docs/dev-server-tests.md]] for more information
+
+## Components
+
+ * New UI elements should be Polymer components.
+ * You will see some old references to tvcm.ui.define('x'). This is our old
+approach for building components. Its like polymer, in that you can subclass
+the element, but it doesn't use shadow dom or have any templating or data
+binding.
+
+## Rough module breakdown
+
+ * *Importers:* load files, produce a model
+ * *Model:* stateless, just the data that came from different trace formats
+ * *TimelineTrackView:* shows the data in gantt-chart form
+ * *Tracks:* visualize a particular part of the model
+ * *Selection:* a vector of things in the tracks that the user has selected (counter samples, slices)
+ * *Analysis:* provides summary of selection
+ * *TimelineView:* glues everything together
+ * *ProfilingView:* chrome-specific UI and glue
+
+## Importer notes
+
+ * The importer to model abstraction is meant to allow us to support multiple trace formats
+
+## Model notes
+
+ * The most important concept in the model is a slice. A slice is a range of time, and some metadata about that range, e.g. title, arguments, etc.
+ * Model has
+ * Processes
+ * Counters
+ * Counter samples (at ts=0.2s, we had 10mb allocated and 3mb free)
+ * Threads
+ * Slices (the FFT::compute function ran from 0.7s to 0.9s)
+ * AsyncSlices (at 0.2s we started a file read in the background and it finished at 0.5s)
+ * CpuSlices (at ts=0.2s we were running on cpu2)
+ * CPUs
+ * Slices (at ts=0.2 to 0.4 we were running "top")
+ * Counters (the clock frequency was 1.2ghz at ts=0.1s)
+
+## Slice
+A slice is something which consumes time synchronously on a CPU or a thread. The
+canonical example of this would be a B/E event pair. An async operation is also
+considered a slice. Things get a bit more murky when looking at instant events.
+A thread scoped instant event is a duration 0 slice. Other instant events,
+process or global scoped, don't correlate to a thread or CPU and aren't
+considered slices.
+
+A flow event, on the other hand, is not a slice. It doesn't consume time and is,
+conceptually, a graph of data flow in the system.
+
+
+## Slice groups
+
+ * When you see the tracing UI, you see lots of things like this:
+
+```
+Thread 7:     [  a     ]   [    c   ]
+                        [ b ]
+```
+
+ * This of visualization starts as a *flat* array of slices:
+
+```
+ [{title: “a”, start: 0, end: 1), {title: “c”, start: 1.5, end: 3.5}, {title: “b”, start: 0.5, end: 0.8}]
+```
+
+ * We call this a slice group. A slice group can be composed into subRows -- a subRow is an array of slices that are all non-overlapping. E.g. in the thread7 example above, there are two subrows:
+
+```
+subrow 1:     [  a     ]   [    c   ]
+subrow 2:     [ b ]
+```
+
+ * The SliceTrack is built around the idea of visualizing a single subrow. So when you see a thread like thread 7, you’re really looking at 2 !SliceTracks, each of which has its own subrow.
+
+ * We have two slice group types:
+ * SliceGroup, for nested data. Used for threads.
+ * e.g.  like ( (0,2), (0.1,0.3) )
+ * We convert the slices into subrows based on containment.
+ * b is considered contained by a if b.start >= a.start && b.end <= a.end
+ * AsyncSliceGroup, for overlapping data. Used for async operations.
+ * e.g. ( (0, 2), (1, 3) )
+ * We convert the slices into subrows by greedily packing them into rows, adding rows as needed when there’s no room on an existing subrow
+
+## Timeline notes
+
+ * Timeline is just an array of tracks. A track is one of the rows in the UI. A single thread of data may turn into 5+ tracks, one track for each row of squares.
+ * The core of the Timeline is Slice
+ * Panning/zooming state is on the TimelineViewport, as is the grid and user defined markers
+
+## Tracks
+### there are three broad types of tracks
+
+ * Building blocks
+ * *Container track*
+ * A track that is itself made up of more tracks. Just a div plus logic to delegate overall track interface calls down to its children.
+ * *CanvasBasedTrack*
+ * A track that renders its content using HTML5 canvas
+ * Visualizations
+ * *SliceTrack:* visualizes an array of non-overlapping monotonically-increasing slices. Has some simple but critical logic to efficiently render even with thousands (or more) slices by merging small slices together when they really close together.
+ * *CounterTrack:* visualizes an array of samples values over time. Has support for stacked area charts. Tries to merge samples together when they are not perceptually significant to reduce canvas drawing overhead.
+ * *Model tracks:* e.g. ThreadTrack
+ * Derives from a container track, takes a timeline model object, e.g. a thread, and creates the appropriate child tracks that visualize that thread
+
+## Selection notes
+
+ * When you drag to select, that creates a selection object by asking every track to append things that intersect the dragged-box to the selection
+ * A selection object is an array of hits.
+ * A hit is the pairing of the track-level entity that was selected with the model-level entity that that visual thing represents.
+ * Eg a thread has a bunch of slices in it. That gets turned into a bunch of subrows that we then turn into !SliceTracks. When you click on a slice in a thread in the UI, the hit is {slice: <the slice you clicked>, thread: <the thread it came from>}.
+ * The hit concept exists partly because slices can’t know their parent (see model section for why). Yet, analysis code want to know parentage in order to do things like group-by-thread.
+
+## Analysis code
+
+ * Takes as input a selection
+ * Does the numeric analysis and dumps the numeric results to a builder
+ * The builder is responsible for creating HTML (or any other textual representation of the results)
diff --git a/chromium/third_party/catapult/tracing/images/third-trace-viewer-circle-blue.png b/chromium/third_party/catapult/tracing/images/third-trace-viewer-circle-blue.png
new file mode 100644
index 00000000000..46ceef1f8f6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/third-trace-viewer-circle-blue.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/images/trace-viewer-circle-blue.png b/chromium/third_party/catapult/tracing/images/trace-viewer-circle-blue.png
new file mode 100644
index 00000000000..0eb12eca4e1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/trace-viewer-circle-blue.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/images/trace-viewer-circle-green.png b/chromium/third_party/catapult/tracing/images/trace-viewer-circle-green.png
new file mode 100644
index 00000000000..e6ba7610903
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/trace-viewer-circle-green.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/images/trace-viewer-circle-red.png b/chromium/third_party/catapult/tracing/images/trace-viewer-circle-red.png
new file mode 100644
index 00000000000..915d70649a1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/trace-viewer-circle-red.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/images/trace-viewer-circle-yellow.png b/chromium/third_party/catapult/tracing/images/trace-viewer-circle-yellow.png
new file mode 100644
index 00000000000..a805cc1b4d9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/trace-viewer-circle-yellow.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/images/trace-viewer-square-blue.png b/chromium/third_party/catapult/tracing/images/trace-viewer-square-blue.png
new file mode 100644
index 00000000000..441f684bb04
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/trace-viewer-square-blue.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/images/trace-viewer-square-green.png b/chromium/third_party/catapult/tracing/images/trace-viewer-square-green.png
new file mode 100644
index 00000000000..a4da2ef051f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/trace-viewer-square-green.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/images/trace-viewer-square-red.png b/chromium/third_party/catapult/tracing/images/trace-viewer-square-red.png
new file mode 100644
index 00000000000..fc8e7fe71f8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/trace-viewer-square-red.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/images/trace-viewer-square-yellow.png b/chromium/third_party/catapult/tracing/images/trace-viewer-square-yellow.png
new file mode 100644
index 00000000000..7216975bef6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/images/trace-viewer-square-yellow.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/package.json b/chromium/third_party/catapult/tracing/package.json
new file mode 100644
index 00000000000..7153679fd2e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "traceviewer",
+ "version": "1.0.5",
+ "description": "Trace-Viewer is the javascript frontend for Chrome about:tracing and Android systrace.",
+ "main": "tracing/index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/catapult-project/catapult/tree/master/tracing"
+ },
+ "keywords": [
+ "tracing",
+ "traceviewer",
+ "trace",
+ "events"
+ ],
+ "author": "The Chromium Authors",
+ "license": "BSD-2-Clause",
+ "gypfile": false
+}
diff --git a/chromium/third_party/catapult/tracing/skp_data/google_homepage.skp b/chromium/third_party/catapult/tracing/skp_data/google_homepage.skp
new file mode 100644
index 00000000000..52d34bf5d63
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/skp_data/google_homepage.skp
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/skp_data/lthi_cats.skp b/chromium/third_party/catapult/tracing/skp_data/lthi_cats.skp
new file mode 100644
index 00000000000..02a2ea50203
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/skp_data/lthi_cats.skp
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/third_party/chai/LICENSE b/chromium/third_party/catapult/tracing/third_party/chai/LICENSE
new file mode 100644
index 00000000000..227b598fc61
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/chai/LICENSE
@@ -0,0 +1,7 @@
+Copyright (c) 2011-2015 Jake Luer jake@alogicalparadox.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/chromium/third_party/catapult/tracing/third_party/chai/README.chromium b/chromium/third_party/catapult/tracing/third_party/chai/README.chromium
new file mode 100644
index 00000000000..4a1fb8e791a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/chai/README.chromium
@@ -0,0 +1,15 @@
+Name: chai
+Short Name: chai
+URL: https://github.com/chaijs/chai
+Version: 2.1.2
+Revision: 1abc3845e3ef96afa003d62478692a1cb9a435b0
+Date: Fri Mar 20 09:46:02 2015 +0000
+License: MIT
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+BDD / TDD assertion framework for node.js and the browser that can be paired with any testing framework.
+
+Local Modifications:
+Copied license text out of README.md. Unminified chai.js and ripped out parts pertaining to Buffer because we're not using node and don't want could-not-require exceptions to be thrown. Reminified to prevent jslint from complaining.
diff --git a/chromium/third_party/catapult/tracing/third_party/chai/chai.js b/chromium/third_party/catapult/tracing/third_party/chai/chai.js
new file mode 100644
index 00000000000..5956853750b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/chai/chai.js
@@ -0,0 +1,2 @@
+!function(){function require(e){var t=require.modules[e];if(t)return"exports"in t||"function"!=typeof t.definition||(t.client=t.component=!0,t.definition.call(this,t.exports={},t),delete t.definition),t.exports}require.loader="component",require.helper={},require.helper.semVerSort=function(e,t){for(var r=e.version.split("."),i=t.version.split("."),n=0;n<r.length;++n){var o=parseInt(r[n],10),s=parseInt(i[n],10);if(o!==s)return o>s?1:-1;var a=r[n].substr((""+o).length),c=i[n].substr((""+s).length);if(""===a&&""!==c)return 1;if(""!==a&&""===c)return-1;if(""!==a&&""!==c)return a>c?1:-1}return 0},require.latest=function(e,t){function r(e){throw new Error('failed to find latest module of "'+e+'"')}var i=/(.*)~(.*)@v?(\d+\.\d+\.\d+[^\/]*)$/,n=/(.*)~(.*)/;n.test(e)||r(e);for(var o=Object.keys(require.modules),s=[],a=[],c=0;c<o.length;c++){var u=o[c];if(new RegExp(e+"@").test(u)){var h=u.substr(e.length+1),l=i.exec(u);null!=l?s.push({version:h,name:u}):a.push({version:h,name:u})}}if(0===s.concat(a).length&&r(e),s.length>0){var f=s.sort(require.helper.semVerSort).pop().name;return t===!0?f:require(f)}var f=a.sort(function(e,t){return e.name>t.name})[0].name;return t===!0?f:require(f)},require.modules={},require.register=function(e,t){require.modules[e]={definition:t}},require.define=function(e,t){require.modules[e]={exports:t}},require.register("chaijs~assertion-error@1.0.0",function(e,t){function r(){function e(e,r){Object.keys(r).forEach(function(i){~t.indexOf(i)||(e[i]=r[i])})}var t=[].slice.call(arguments);return function(){for(var t=[].slice.call(arguments),r=0,i={};r<t.length;r++)e(i,t[r]);return i}}function i(e,t,i){var n=r("name","message","stack","constructor","toJSON"),o=n(t||{});this.message=e||"Unspecified AssertionError",this.showDiff=!1;for(var s in o)this[s]=o[s];i=i||arguments.callee,i&&Error.captureStackTrace&&Error.captureStackTrace(this,i)}t.exports=i,i.prototype=Object.create(Error.prototype),i.prototype.name="AssertionError",i.prototype.constructor=i,i.prototype.toJSON=function(e){var t=r("constructor","toJSON","stack"),i=t({name:this.name},this);return!1!==e&&this.stack&&(i.stack=this.stack),i}}),require.register("chaijs~type-detect@0.1.1",function(e,t){function r(e){var t=Object.prototype.toString.call(e);return n[t]?n[t]:null===e?"null":void 0===e?"undefined":e===Object(e)?"object":typeof e}function i(){this.tests={}}var e=t.exports=r,n={"[object Array]":"array","[object RegExp]":"regexp","[object Function]":"function","[object Arguments]":"arguments","[object Date]":"date"};e.Library=i,i.prototype.of=r,i.prototype.define=function(e,t){return 1===arguments.length?this.tests[e]:(this.tests[e]=t,this)},i.prototype.test=function(e,t){if(t===r(e))return!0;var i=this.tests[t];if(i&&"regexp"===r(i))return i.test(e);if(i&&"function"===r(i))return i(e);throw new ReferenceError('Type test "'+t+'" not defined or invalid.')}}),require.register("chaijs~deep-eql@0.1.3",function(e,t){function r(e,t,r){return i(e,t)?!0:"date"===f(e)?o(e,t):"regexp"===f(e)?s(e,t):"arguments"===f(e)?a(e,t,r):n(e,t)?"object"!==f(e)&&"object"!==f(t)&&"array"!==f(e)&&"array"!==f(t)?i(e,t):l(e,t,r):!1}function i(e,t){return e===t?0!==e||1/e===1/t:e!==e&&t!==t}function n(e,t){return f(e)===f(t)}function o(e,t){return"date"!==f(t)?!1:i(e.getTime(),t.getTime())}function s(e,t){return"regexp"!==f(t)?!1:i(e.toString(),t.toString())}function a(e,t,i){return"arguments"!==f(t)?!1:(e=[].slice.call(e),t=[].slice.call(t),r(e,t,i))}function c(e){var t=[];for(var r in e)t.push(r);return t}function u(e,t){if(e.length!==t.length)return!1;for(var r=0,i=!0;r<e.length;r++)if(e[r]!==t[r]){i=!1;break}return i}function h(e){return null!==e&&void 0!==e}function l(e,t,i){if(!h(e)||!h(t))return!1;if(e.prototype!==t.prototype)return!1;var n;if(i){for(n=0;n<i.length;n++)if(i[n][0]===e&&i[n][1]===t||i[n][0]===t&&i[n][1]===e)return!0}else i=[];try{var o=c(e),s=c(t)}catch(a){return!1}if(o.sort(),s.sort(),!u(o,s))return!1;i.push([e,t]);var l;for(n=o.length-1;n>=0;n--)if(l=o[n],!r(e[l],t[l],i))return!1;return!0}var f=require("chaijs~type-detect@0.1.1");t.exports=r}),require.register("chai",function(e,t){t.exports=require("chai/lib/chai.js")}),require.register("chai/lib/chai.js",function(e,t){var r=[],e=t.exports={};e.version="2.1.0",e.AssertionError=require("chaijs~assertion-error@1.0.0");var i=require("chai/lib/chai/utils/index.js");e.use=function(e){return~r.indexOf(e)||(e(this,i),r.push(e)),this},e.util=i;var n=require("chai/lib/chai/config.js");e.config=n;var o=require("chai/lib/chai/assertion.js");e.use(o);var s=require("chai/lib/chai/core/assertions.js");e.use(s);var a=require("chai/lib/chai/interface/expect.js");e.use(a);var c=require("chai/lib/chai/interface/should.js");e.use(c);var u=require("chai/lib/chai/interface/assert.js");e.use(u)}),require.register("chai/lib/chai/assertion.js",function(e,t){var r=require("chai/lib/chai/config.js");t.exports=function(e,t){function i(e,t,r){o(this,"ssfi",r||arguments.callee),o(this,"object",e),o(this,"message",t)}var n=e.AssertionError,o=t.flag;e.Assertion=i,Object.defineProperty(i,"includeStack",{get:function(){return console.warn("Assertion.includeStack is deprecated, use chai.config.includeStack instead."),r.includeStack},set:function(e){console.warn("Assertion.includeStack is deprecated, use chai.config.includeStack instead."),r.includeStack=e}}),Object.defineProperty(i,"showDiff",{get:function(){return console.warn("Assertion.showDiff is deprecated, use chai.config.showDiff instead."),r.showDiff},set:function(e){console.warn("Assertion.showDiff is deprecated, use chai.config.showDiff instead."),r.showDiff=e}}),i.addProperty=function(e,r){t.addProperty(this.prototype,e,r)},i.addMethod=function(e,r){t.addMethod(this.prototype,e,r)},i.addChainableMethod=function(e,r,i){t.addChainableMethod(this.prototype,e,r,i)},i.overwriteProperty=function(e,r){t.overwriteProperty(this.prototype,e,r)},i.overwriteMethod=function(e,r){t.overwriteMethod(this.prototype,e,r)},i.overwriteChainableMethod=function(e,r,i){t.overwriteChainableMethod(this.prototype,e,r,i)},i.prototype.assert=function(e,i,s,a,c,u){var h=t.test(this,arguments);if(!0!==u&&(u=!1),!0!==r.showDiff&&(u=!1),!h){var i=t.getMessage(this,arguments),l=t.getActual(this,arguments);throw new n(i,{actual:l,expected:a,showDiff:u},r.includeStack?this.assert:o(this,"ssfi"))}},Object.defineProperty(i.prototype,"_obj",{get:function(){return o(this,"object")},set:function(e){o(this,"object",e)}})}}),require.register("chai/lib/chai/config.js",function(e,t){t.exports={includeStack:!1,showDiff:!0,truncateThreshold:40}}),require.register("chai/lib/chai/core/assertions.js",function(e,t){t.exports=function(e,t){function r(e,r){r&&q(this,"message",r),e=e.toLowerCase();var i=q(this,"object"),n=~["a","e","i","o","u"].indexOf(e.charAt(0))?"an ":"a ";this.assert(e===t.type(i),"expected #{this} to be "+n+e,"expected #{this} not to be "+n+e)}function i(){q(this,"contains",!0)}function n(e,r){r&&q(this,"message",r);var i=q(this,"object"),n=!1;if("array"===t.type(i)&&"object"===t.type(e)){for(var o in i)if(t.eql(i[o],e)){n=!0;break}}else if("object"===t.type(e)){if(!q(this,"negate")){for(var s in e)new m(i).property(s,e[s]);return}var a={};for(var s in e)a[s]=i[s];n=t.eql(a,e)}else n=i&&~i.indexOf(e);this.assert(n,"expected #{this} to include "+t.inspect(e),"expected #{this} to not include "+t.inspect(e))}function o(){var e=q(this,"object"),t=Object.prototype.toString.call(e);this.assert("[object Arguments]"===t,"expected #{this} to be arguments but got "+t,"expected #{this} to not be arguments")}function s(e,t){t&&q(this,"message",t);var r=q(this,"object");return q(this,"deep")?this.eql(e):void this.assert(e===r,"expected #{this} to equal #{exp}","expected #{this} to not equal #{exp}",e,this._obj,!0)}function a(e,r){r&&q(this,"message",r),this.assert(t.eql(e,q(this,"object")),"expected #{this} to deeply equal #{exp}","expected #{this} to not deeply equal #{exp}",e,this._obj,!0)}function c(e,t){t&&q(this,"message",t);var r=q(this,"object");if(q(this,"doLength")){new m(r,t).to.have.property("length");var i=r.length;this.assert(i>e,"expected #{this} to have a length above #{exp} but got #{act}","expected #{this} to not have a length above #{exp}",e,i)}else this.assert(r>e,"expected #{this} to be above "+e,"expected #{this} to be at most "+e)}function u(e,t){t&&q(this,"message",t);var r=q(this,"object");if(q(this,"doLength")){new m(r,t).to.have.property("length");var i=r.length;this.assert(i>=e,"expected #{this} to have a length at least #{exp} but got #{act}","expected #{this} to have a length below #{exp}",e,i)}else this.assert(r>=e,"expected #{this} to be at least "+e,"expected #{this} to be below "+e)}function h(e,t){t&&q(this,"message",t);var r=q(this,"object");if(q(this,"doLength")){new m(r,t).to.have.property("length");var i=r.length;this.assert(e>i,"expected #{this} to have a length below #{exp} but got #{act}","expected #{this} to not have a length below #{exp}",e,i)}else this.assert(e>r,"expected #{this} to be below "+e,"expected #{this} to be at least "+e)}function l(e,t){t&&q(this,"message",t);var r=q(this,"object");if(q(this,"doLength")){new m(r,t).to.have.property("length");var i=r.length;this.assert(e>=i,"expected #{this} to have a length at most #{exp} but got #{act}","expected #{this} to have a length above #{exp}",e,i)}else this.assert(e>=r,"expected #{this} to be at most "+e,"expected #{this} to be above "+e)}function f(e,r){r&&q(this,"message",r);var i=t.getName(e);this.assert(q(this,"object")instanceof e,"expected #{this} to be an instance of "+i,"expected #{this} to not be an instance of "+i)}function p(e,r){r&&q(this,"message",r);var i=q(this,"object");this.assert(i.hasOwnProperty(e),"expected #{this} to have own property "+t.inspect(e),"expected #{this} to not have own property "+t.inspect(e))}function d(){q(this,"doLength",!0)}function g(e,t){t&&q(this,"message",t);var r=q(this,"object");new m(r,t).to.have.property("length");var i=r.length;this.assert(i==e,"expected #{this} to have a length of #{exp} but got #{act}","expected #{this} to not have a length of #{act}",e,i)}function b(e){var r,i=q(this,"object"),n=!0,o="keys must be given single argument of Array|Object|String, or multiple String arguments";switch(t.type(e)){case"array":if(arguments.length>1)throw new Error(o);break;case"object":if(arguments.length>1)throw new Error(o);e=Object.keys(e);break;default:e=Array.prototype.slice.call(arguments)}if(!e.length)throw new Error("keys required");var s=Object.keys(i),a=e,c=e.length,u=q(this,"any"),h=q(this,"all");if(u||h||(h=!0),u){var l=a.filter(function(e){return~s.indexOf(e)});n=l.length>0}if(h&&(n=e.every(function(e){return~s.indexOf(e)}),q(this,"negate")||q(this,"contains")||(n=n&&e.length==s.length)),c>1){e=e.map(function(e){return t.inspect(e)});var f=e.pop();h&&(r=e.join(", ")+", and "+f),u&&(r=e.join(", ")+", or "+f)}else r=t.inspect(e[0]);r=(c>1?"keys ":"key ")+r,r=(q(this,"contains")?"contain ":"have ")+r,this.assert(n,"expected #{this} to "+r,"expected #{this} to not "+r,a.slice(0).sort(),s.sort(),!0)}function v(e,r,i){i&&q(this,"message",i);var n=q(this,"object");new m(n,i).is.a("function");var o=!1,s=null,a=null,c=null;0===arguments.length?(r=null,e=null):e&&(e instanceof RegExp||"string"==typeof e)?(r=e,e=null):e&&e instanceof Error?(s=e,e=null,r=null):"function"==typeof e?(a=e.prototype.name||e.name,"Error"===a&&e!==Error&&(a=(new e).name)):e=null;try{n()}catch(u){if(s)return this.assert(u===s,"expected #{this} to throw #{exp} but #{act} was thrown","expected #{this} to not throw #{exp}",s instanceof Error?s.toString():s,u instanceof Error?u.toString():u),q(this,"object",u),this;if(e&&(this.assert(u instanceof e,"expected #{this} to throw #{exp} but #{act} was thrown","expected #{this} to not throw #{exp} but #{act} was thrown",a,u instanceof Error?u.toString():u),!r))return q(this,"object",u),this;var h="object"===t.type(u)&&"message"in u?u.message:""+u;if(null!=h&&r&&r instanceof RegExp)return this.assert(r.exec(h),"expected #{this} to throw error matching #{exp} but got #{act}","expected #{this} to throw error not matching #{exp}",r,h),q(this,"object",u),this;if(null!=h&&r&&"string"==typeof r)return this.assert(~h.indexOf(r),"expected #{this} to throw error including #{exp} but got #{act}","expected #{this} to throw error not including #{act}",r,h),q(this,"object",u),this;o=!0,c=u}var l="",f=null!==a?a:s?"#{exp}":"an error";o&&(l=" but #{act} was thrown"),this.assert(o===!0,"expected #{this} to throw "+f+l,"expected #{this} to not throw "+f+l,s instanceof Error?s.toString():s,c instanceof Error?c.toString():c),q(this,"object",c)}function y(e,t,r){return e.every(function(e){return r?t.some(function(t){return r(e,t)}):-1!==t.indexOf(e)})}function j(e,t,r){r&&q(this,"message",r);var i=q(this,"object");new m(e,r).to.have.property(t),new m(i).is.a("function");var n=e[t];i(),this.assert(n!==e[t],"expected ."+t+" to change","expected ."+t+" to not change")}function w(e,t,r){r&&q(this,"message",r);var i=q(this,"object");new m(e,r).to.have.property(t),new m(i).is.a("function");var n=e[t];i(),this.assert(e[t]-n>0,"expected ."+t+" to increase","expected ."+t+" to not increase")}function x(e,t,r){r&&q(this,"message",r);var i=q(this,"object");new m(e,r).to.have.property(t),new m(i).is.a("function");var n=e[t];i(),this.assert(e[t]-n<0,"expected ."+t+" to decrease","expected ."+t+" to not decrease")}var m=e.Assertion,q=(Object.prototype.toString,t.flag);["to","be","been","is","and","has","have","with","that","which","at","of","same"].forEach(function(e){m.addProperty(e,function(){return this})}),m.addProperty("not",function(){q(this,"negate",!0)}),m.addProperty("deep",function(){q(this,"deep",!0)}),m.addProperty("any",function(){q(this,"any",!0),q(this,"all",!1)}),m.addProperty("all",function(){q(this,"all",!0),q(this,"any",!1)}),m.addChainableMethod("an",r),m.addChainableMethod("a",r),m.addChainableMethod("include",n,i),m.addChainableMethod("contain",n,i),m.addChainableMethod("contains",n,i),m.addChainableMethod("includes",n,i),m.addProperty("ok",function(){this.assert(q(this,"object"),"expected #{this} to be truthy","expected #{this} to be falsy")}),m.addProperty("true",function(){this.assert(!0===q(this,"object"),"expected #{this} to be true","expected #{this} to be false",this.negate?!1:!0)}),m.addProperty("false",function(){this.assert(!1===q(this,"object"),"expected #{this} to be false","expected #{this} to be true",this.negate?!0:!1)}),m.addProperty("null",function(){this.assert(null===q(this,"object"),"expected #{this} to be null","expected #{this} not to be null")}),m.addProperty("undefined",function(){this.assert(void 0===q(this,"object"),"expected #{this} to be undefined","expected #{this} not to be undefined")}),m.addProperty("exist",function(){this.assert(null!=q(this,"object"),"expected #{this} to exist","expected #{this} to not exist")}),m.addProperty("empty",function(){var e=q(this,"object"),t=e;Array.isArray(e)||"string"==typeof object?t=e.length:"object"==typeof e&&(t=Object.keys(e).length),this.assert(!t,"expected #{this} to be empty","expected #{this} not to be empty")}),m.addProperty("arguments",o),m.addProperty("Arguments",o),m.addMethod("equal",s),m.addMethod("equals",s),m.addMethod("eq",s),m.addMethod("eql",a),m.addMethod("eqls",a),m.addMethod("above",c),m.addMethod("gt",c),m.addMethod("greaterThan",c),m.addMethod("least",u),m.addMethod("gte",u),m.addMethod("below",h),m.addMethod("lt",h),m.addMethod("lessThan",h),m.addMethod("most",l),m.addMethod("lte",l),m.addMethod("within",function(e,t,r){r&&q(this,"message",r);var i=q(this,"object"),n=e+".."+t;if(q(this,"doLength")){new m(i,r).to.have.property("length");var o=i.length;this.assert(o>=e&&t>=o,"expected #{this} to have a length within "+n,"expected #{this} to not have a length within "+n)}else this.assert(i>=e&&t>=i,"expected #{this} to be within "+n,"expected #{this} to not be within "+n)}),m.addMethod("instanceof",f),m.addMethod("instanceOf",f),m.addMethod("property",function(e,r,i){i&&q(this,"message",i);var n=!!q(this,"deep"),o=n?"deep property ":"property ",s=q(this,"negate"),a=q(this,"object"),c=n?t.getPathInfo(e,a):null,u=n?c.exists:t.hasProperty(e,a),h=n?c.value:a[e];if(s&&void 0!==r){if(void 0===h)throw i=null!=i?i+": ":"",new Error(i+t.inspect(a)+" has no "+o+t.inspect(e))}else this.assert(u,"expected #{this} to have a "+o+t.inspect(e),"expected #{this} to not have "+o+t.inspect(e));void 0!==r&&this.assert(r===h,"expected #{this} to have a "+o+t.inspect(e)+" of #{exp}, but got #{act}","expected #{this} to not have a "+o+t.inspect(e)+" of #{act}",r,h),q(this,"object",h)}),m.addMethod("ownProperty",p),m.addMethod("haveOwnProperty",p),m.addChainableMethod("length",g,d),m.addMethod("lengthOf",g),m.addMethod("match",function(e,t){t&&q(this,"message",t);var r=q(this,"object");this.assert(e.exec(r),"expected #{this} to match "+e,"expected #{this} not to match "+e)}),m.addMethod("string",function(e,r){r&&q(this,"message",r);var i=q(this,"object");new m(i,r).is.a("string"),this.assert(~i.indexOf(e),"expected #{this} to contain "+t.inspect(e),"expected #{this} to not contain "+t.inspect(e))}),m.addMethod("keys",b),m.addMethod("key",b),m.addMethod("throw",v),m.addMethod("throws",v),m.addMethod("Throw",v),m.addMethod("respondTo",function(e,r){r&&q(this,"message",r);var i=q(this,"object"),n=q(this,"itself"),o="function"!==t.type(i)||n?i[e]:i.prototype[e];this.assert("function"==typeof o,"expected #{this} to respond to "+t.inspect(e),"expected #{this} to not respond to "+t.inspect(e))}),m.addProperty("itself",function(){q(this,"itself",!0)}),m.addMethod("satisfy",function(e,r){r&&q(this,"message",r);var i=q(this,"object"),n=e(i);this.assert(n,"expected #{this} to satisfy "+t.objDisplay(e),"expected #{this} to not satisfy"+t.objDisplay(e),this.negate?!1:!0,n)}),m.addMethod("closeTo",function(e,r,i){i&&q(this,"message",i);var n=q(this,"object");if(new m(n,i).is.a("number"),"number"!==t.type(e)||"number"!==t.type(r))throw new Error("the arguments to closeTo must be numbers");this.assert(Math.abs(n-e)<=r,"expected #{this} to be close to "+e+" +/- "+r,"expected #{this} not to be close to "+e+" +/- "+r)}),m.addMethod("members",function(e,r){r&&q(this,"message",r);var i=q(this,"object");new m(i).to.be.an("array"),new m(e).to.be.an("array");var n=q(this,"deep")?t.eql:void 0;return q(this,"contains")?this.assert(y(e,i,n),"expected #{this} to be a superset of #{act}","expected #{this} to not be a superset of #{act}",i,e):void this.assert(y(i,e,n)&&y(e,i,n),"expected #{this} to have the same members as #{act}","expected #{this} to not have the same members as #{act}",i,e)}),m.addChainableMethod("change",j),m.addChainableMethod("changes",j),m.addChainableMethod("increase",w),m.addChainableMethod("increases",w),m.addChainableMethod("decrease",x),m.addChainableMethod("decreases",x)}}),require.register("chai/lib/chai/interface/assert.js",function(exports,module){module.exports=function(chai,util){var Assertion=chai.Assertion,flag=util.flag,assert=chai.assert=function(e,t){var r=new Assertion(null,null,chai.assert);r.assert(e,t,"[ negation message unavailable ]")};assert.fail=function(e,t,r,i){throw r=r||"assert.fail()",new chai.AssertionError(r,{actual:e,expected:t,operator:i},assert.fail)},assert.ok=function(e,t){new Assertion(e,t).is.ok},assert.notOk=function(e,t){new Assertion(e,t).is.not.ok},assert.equal=function(e,t,r){var i=new Assertion(e,r,assert.equal);i.assert(t==flag(i,"object"),"expected #{this} to equal #{exp}","expected #{this} to not equal #{act}",t,e)},assert.notEqual=function(e,t,r){var i=new Assertion(e,r,assert.notEqual);i.assert(t!=flag(i,"object"),"expected #{this} to not equal #{exp}","expected #{this} to equal #{act}",t,e)},assert.strictEqual=function(e,t,r){new Assertion(e,r).to.equal(t)},assert.notStrictEqual=function(e,t,r){new Assertion(e,r).to.not.equal(t)},assert.deepEqual=function(e,t,r){new Assertion(e,r).to.eql(t)},assert.notDeepEqual=function(e,t,r){new Assertion(e,r).to.not.eql(t)},assert.isAbove=function(e,t,r){new Assertion(e,r).to.be.above(t)},assert.isBelow=function(e,t,r){new Assertion(e,r).to.be.below(t)},assert.isTrue=function(e,t){new Assertion(e,t).is["true"]},assert.isFalse=function(e,t){new Assertion(e,t).is["false"]},assert.isNull=function(e,t){new Assertion(e,t).to.equal(null)},assert.isNotNull=function(e,t){new Assertion(e,t).to.not.equal(null)},assert.isUndefined=function(e,t){new Assertion(e,t).to.equal(void 0)},assert.isDefined=function(e,t){new Assertion(e,t).to.not.equal(void 0)},assert.isFunction=function(e,t){new Assertion(e,t).to.be.a("function")},assert.isNotFunction=function(e,t){new Assertion(e,t).to.not.be.a("function")},assert.isObject=function(e,t){new Assertion(e,t).to.be.a("object")},assert.isNotObject=function(e,t){new Assertion(e,t).to.not.be.a("object")},assert.isArray=function(e,t){new Assertion(e,t).to.be.an("array")},assert.isNotArray=function(e,t){new Assertion(e,t).to.not.be.an("array")},assert.isString=function(e,t){new Assertion(e,t).to.be.a("string")},assert.isNotString=function(e,t){new Assertion(e,t).to.not.be.a("string")},assert.isNumber=function(e,t){new Assertion(e,t).to.be.a("number")},assert.isNotNumber=function(e,t){new Assertion(e,t).to.not.be.a("number")},assert.isBoolean=function(e,t){new Assertion(e,t).to.be.a("boolean")},assert.isNotBoolean=function(e,t){new Assertion(e,t).to.not.be.a("boolean")},assert.typeOf=function(e,t,r){new Assertion(e,r).to.be.a(t)},assert.notTypeOf=function(e,t,r){new Assertion(e,r).to.not.be.a(t)},assert.instanceOf=function(e,t,r){new Assertion(e,r).to.be.instanceOf(t)},assert.notInstanceOf=function(e,t,r){new Assertion(e,r).to.not.be.instanceOf(t)},assert.include=function(e,t,r){new Assertion(e,r,assert.include).include(t)},assert.notInclude=function(e,t,r){new Assertion(e,r,assert.notInclude).not.include(t)},assert.match=function(e,t,r){new Assertion(e,r).to.match(t)},assert.notMatch=function(e,t,r){new Assertion(e,r).to.not.match(t)},assert.property=function(e,t,r){new Assertion(e,r).to.have.property(t)},assert.notProperty=function(e,t,r){new Assertion(e,r).to.not.have.property(t)},assert.deepProperty=function(e,t,r){new Assertion(e,r).to.have.deep.property(t)},assert.notDeepProperty=function(e,t,r){new Assertion(e,r).to.not.have.deep.property(t)},assert.propertyVal=function(e,t,r,i){new Assertion(e,i).to.have.property(t,r)},assert.propertyNotVal=function(e,t,r,i){new Assertion(e,i).to.not.have.property(t,r)},assert.deepPropertyVal=function(e,t,r,i){new Assertion(e,i).to.have.deep.property(t,r)},assert.deepPropertyNotVal=function(e,t,r,i){new Assertion(e,i).to.not.have.deep.property(t,r)},assert.lengthOf=function(e,t,r){new Assertion(e,r).to.have.length(t)},assert.Throw=function(e,t,r,i){("string"==typeof t||t instanceof RegExp)&&(r=t,t=null);var n=new Assertion(e,i).to.Throw(t,r);return flag(n,"object")},assert.doesNotThrow=function(e,t,r){"string"==typeof t&&(r=t,t=null),new Assertion(e,r).to.not.Throw(t)},assert.operator=function(val,operator,val2,msg){if(!~["==","===",">",">=","<","<=","!=","!=="].indexOf(operator))throw new Error('Invalid operator "'+operator+'"');var test=new Assertion(eval(val+operator+val2),msg);test.assert(!0===flag(test,"object"),"expected "+util.inspect(val)+" to be "+operator+" "+util.inspect(val2),"expected "+util.inspect(val)+" to not be "+operator+" "+util.inspect(val2))},assert.closeTo=function(e,t,r,i){new Assertion(e,i).to.be.closeTo(t,r)},assert.sameMembers=function(e,t,r){new Assertion(e,r).to.have.same.members(t)},assert.sameDeepMembers=function(e,t,r){new Assertion(e,r).to.have.same.deep.members(t)},assert.includeMembers=function(e,t,r){new Assertion(e,r).to.include.members(t)},assert.changes=function(e,t,r){new Assertion(e).to.change(t,r)},assert.doesNotChange=function(e,t,r){new Assertion(e).to.not.change(t,r)},assert.increases=function(e,t,r){new Assertion(e).to.increase(t,r)},assert.doesNotIncrease=function(e,t,r){new Assertion(e).to.not.increase(t,r)},assert.decreases=function(e,t,r){new Assertion(e).to.decrease(t,r)},assert.doesNotDecrease=function(e,t,r){new Assertion(e).to.not.decrease(t,r)},assert.ifError=function(e,t){new Assertion(e,t).to.not.be.ok},function e(t,r){return assert[r]=assert[t],e}("Throw","throw")("Throw","throws")}}),require.register("chai/lib/chai/interface/expect.js",function(e,t){t.exports=function(e){e.expect=function(t,r){return new e.Assertion(t,r)},e.expect.fail=function(t,r,i,n){throw i=i||"expect.fail()",new e.AssertionError(i,{actual:t,expected:r,operator:n},e.expect.fail)}}}),require.register("chai/lib/chai/interface/should.js",function(e,t){t.exports=function(e){function t(){function t(){return this instanceof String||this instanceof Number?new r(this.constructor(this),null,t):this instanceof Boolean?new r(1==this,null,t):new r(this,null,t)}function i(e){Object.defineProperty(this,"should",{value:e,enumerable:!0,configurable:!0,writable:!0})}Object.defineProperty(Object.prototype,"should",{set:i,get:t,configurable:!0});var n={};return n.fail=function(t,r,i,o){throw i=i||"should.fail()",new e.AssertionError(i,{actual:t,expected:r,operator:o},n.fail)},n.equal=function(e,t,i){new r(e,i).to.equal(t)},n.Throw=function(e,t,i,n){new r(e,n).to.Throw(t,i)},n.exist=function(e,t){new r(e,t).to.exist},n.not={},n.not.equal=function(e,t,i){new r(e,i).to.not.equal(t)},n.not.Throw=function(e,t,i,n){new r(e,n).to.not.Throw(t,i)},n.not.exist=function(e,t){new r(e,t).to.not.exist},n["throw"]=n.Throw,n.not["throw"]=n.not.Throw,n}var r=e.Assertion;e.should=t,e.Should=t}}),require.register("chai/lib/chai/utils/addChainableMethod.js",function(e,t){var r=require("chai/lib/chai/utils/transferFlags.js"),i=require("chai/lib/chai/utils/flag.js"),n=require("chai/lib/chai/config.js"),o="__proto__"in Object,s=/^(?:length|name|arguments|caller)$/,a=Function.prototype.call,c=Function.prototype.apply;t.exports=function(e,t,u,h){"function"!=typeof h&&(h=function(){});var l={method:u,chainingBehavior:h};e.__methods||(e.__methods={}),e.__methods[t]=l,Object.defineProperty(e,t,{get:function(){l.chainingBehavior.call(this);var t=function f(){var e=i(this,"ssfi");e&&n.includeStack===!1&&i(this,"ssfi",f);var t=l.method.apply(this,arguments);return void 0===t?this:t};if(o){var u=t.__proto__=Object.create(this);u.call=a,u.apply=c}else{var h=Object.getOwnPropertyNames(e);h.forEach(function(r){if(!s.test(r)){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,i)}})}return r(this,t),t},configurable:!0})}}),require.register("chai/lib/chai/utils/addMethod.js",function(e,t){var r=require("chai/lib/chai/config.js"),i=require("chai/lib/chai/utils/flag.js");t.exports=function(e,t,n){e[t]=function(){var o=i(this,"ssfi");o&&r.includeStack===!1&&i(this,"ssfi",e[t]);var s=n.apply(this,arguments);return void 0===s?this:s}}}),require.register("chai/lib/chai/utils/addProperty.js",function(e,t){t.exports=function(e,t,r){Object.defineProperty(e,t,{get:function(){var e=r.call(this);return void 0===e?this:e},configurable:!0})}}),require.register("chai/lib/chai/utils/flag.js",function(e,t){t.exports=function(e,t,r){var i=e.__flags||(e.__flags=Object.create(null));return 3!==arguments.length?i[t]:void(i[t]=r)}}),require.register("chai/lib/chai/utils/getActual.js",function(e,t){t.exports=function(e,t){return t.length>4?t[4]:e._obj}}),require.register("chai/lib/chai/utils/getEnumerableProperties.js",function(e,t){t.exports=function(e){var t=[];for(var r in e)t.push(r);return t}}),require.register("chai/lib/chai/utils/getMessage.js",function(e,t){var r=require("chai/lib/chai/utils/flag.js"),i=require("chai/lib/chai/utils/getActual.js"),n=(require("chai/lib/chai/utils/inspect.js"),require("chai/lib/chai/utils/objDisplay.js"));t.exports=function(e,t){var o=r(e,"negate"),s=r(e,"object"),a=t[3],c=i(e,t),u=o?t[2]:t[1],h=r(e,"message");return"function"==typeof u&&(u=u()),u=u||"",u=u.replace(/#{this}/g,n(s)).replace(/#{act}/g,n(c)).replace(/#{exp}/g,n(a)),h?h+": "+u:u}}),require.register("chai/lib/chai/utils/getName.js",function(e,t){t.exports=function(e){if(e.name)return e.name;var t=/^\s?function ([^(]*)\(/.exec(e);return t&&t[1]?t[1]:""}}),require.register("chai/lib/chai/utils/getPathValue.js",function(e,t){var r=require("chai/lib/chai/utils/getPathInfo.js");t.exports=function(e,t){var i=r(e,t);return i.value}}),require.register("chai/lib/chai/utils/getPathInfo.js",function(e,t){function r(e){var t=e.replace(/\[/g,".["),r=t.match(/(\\\.|[^.]+?)+/g);return r.map(function(e){var t=/\[(\d+)\]$/,r=t.exec(e);return r?{i:parseFloat(r[1])}:{p:e}})}function i(e,t,r){var i,n=t;r=void 0===r?e.length:r;for(var o=0,s=r;s>o;o++){var a=e[o];n?("undefined"!=typeof a.p?n=n[a.p]:"undefined"!=typeof a.i&&(n=n[a.i]),o==s-1&&(i=n)):i=void 0}return i}var n=require("chai/lib/chai/utils/hasProperty.js");t.exports=function(e,t){var o=r(e),s=o[o.length-1],a={parent:i(o,t,o.length-1),name:s.p||s.i,value:i(o,t)};return a.exists=n(a.name,a.parent),a}}),require.register("chai/lib/chai/utils/hasProperty.js",function(e,t){var r=require("chai/lib/chai/utils/type.js"),i={number:Number,string:String};t.exports=function(e,t){var n=r(t);return"null"===n||"undefined"===n?!1:(i[n]&&"object"!=typeof t&&(t=new i[n](t)),e in t)}}),require.register("chai/lib/chai/utils/getProperties.js",function(e,t){t.exports=function(){function e(e){-1===t.indexOf(e)&&t.push(e)}for(var t=Object.getOwnPropertyNames(subject),r=Object.getPrototypeOf(subject);null!==r;)Object.getOwnPropertyNames(r).forEach(e),r=Object.getPrototypeOf(r);return t}}),require.register("chai/lib/chai/utils/index.js",function(e,t){var e=t.exports={};e.test=require("chai/lib/chai/utils/test.js"),e.type=require("chai/lib/chai/utils/type.js"),e.getMessage=require("chai/lib/chai/utils/getMessage.js"),e.getActual=require("chai/lib/chai/utils/getActual.js"),e.inspect=require("chai/lib/chai/utils/inspect.js"),e.objDisplay=require("chai/lib/chai/utils/objDisplay.js"),e.flag=require("chai/lib/chai/utils/flag.js"),e.transferFlags=require("chai/lib/chai/utils/transferFlags.js"),e.eql=require("chaijs~deep-eql@0.1.3"),e.getPathValue=require("chai/lib/chai/utils/getPathValue.js"),e.getPathInfo=require("chai/lib/chai/utils/getPathInfo.js"),e.hasProperty=require("chai/lib/chai/utils/hasProperty.js"),e.getName=require("chai/lib/chai/utils/getName.js"),e.addProperty=require("chai/lib/chai/utils/addProperty.js"),e.addMethod=require("chai/lib/chai/utils/addMethod.js"),e.overwriteProperty=require("chai/lib/chai/utils/overwriteProperty.js"),e.overwriteMethod=require("chai/lib/chai/utils/overwriteMethod.js"),e.addChainableMethod=require("chai/lib/chai/utils/addChainableMethod.js"),e.overwriteChainableMethod=require("chai/lib/chai/utils/overwriteChainableMethod.js")}),require.register("chai/lib/chai/utils/inspect.js",function(e,t){function r(e,t,r){var n={showHidden:t,seen:[],stylize:function(e){return e}};return i(n,e,"undefined"==typeof r?2:r)}function i(t,r,p){if(r&&"function"==typeof r.inspect&&r.inspect!==e.inspect&&(!r.constructor||r.constructor.prototype!==r)){var y=r.inspect(p);return"string"!=typeof y&&(y=i(t,y,p)),y}var j=n(t,r);if(j)return j;if(v(r)){if("outerHTML"in r)return r.outerHTML;try{if(document.xmlVersion){var w=new XMLSerializer;return w.serializeToString(r)}var x="http://www.w3.org/1999/xhtml",m=document.createElementNS(x,"_");return m.appendChild(r.cloneNode(!1)),html=m.innerHTML.replace("><",">"+r.innerHTML+"<"),m.innerHTML="",html}catch(q){}}var A=b(r),O=t.showHidden?g(r):A;if(0===O.length||f(r)&&(1===O.length&&"stack"===O[0]||2===O.length&&"description"===O[0]&&"stack"===O[1])){if("function"==typeof r){var M=d(r),P=M?": "+M:"";return t.stylize("[Function"+P+"]","special")}if(h(r))return t.stylize(RegExp.prototype.toString.call(r),"regexp");if(l(r))return t.stylize(Date.prototype.toUTCString.call(r),"date");if(f(r))return o(r)}var S="",E=!1,_=["{","}"];if(u(r)&&(E=!0,_=["[","]"]),"function"==typeof r){var M=d(r),P=M?": "+M:"";S=" [Function"+P+"]"}if(h(r)&&(S=" "+RegExp.prototype.toString.call(r)),l(r)&&(S=" "+Date.prototype.toUTCString.call(r)),
+f(r))return o(r);if(0===O.length&&(!E||0==r.length))return _[0]+S+_[1];if(0>p)return h(r)?t.stylize(RegExp.prototype.toString.call(r),"regexp"):t.stylize("[Object]","special");t.seen.push(r);var k;return k=E?s(t,r,p,A,O):O.map(function(e){return a(t,r,p,A,e,E)}),t.seen.pop(),c(k,S,_)}function n(e,t){switch(typeof t){case"undefined":return e.stylize("undefined","undefined");case"string":var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string");case"number":return 0===t&&1/t===-(1/0)?e.stylize("-0","number"):e.stylize(""+t,"number");case"boolean":return e.stylize(""+t,"boolean")}return null===t?e.stylize("null","null"):void 0}function o(e){return"["+Error.prototype.toString.call(e)+"]"}function s(e,t,r,i,n){for(var o=[],s=0,c=t.length;c>s;++s)o.push(Object.prototype.hasOwnProperty.call(t,String(s))?a(e,t,r,i,String(s),!0):"");return n.forEach(function(n){n.match(/^\d+$/)||o.push(a(e,t,r,i,n,!0))}),o}function a(e,t,r,n,o,s){var a,c;if(t.__lookupGetter__&&(t.__lookupGetter__(o)?c=t.__lookupSetter__(o)?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):t.__lookupSetter__(o)&&(c=e.stylize("[Setter]","special"))),n.indexOf(o)<0&&(a="["+o+"]"),c||(e.seen.indexOf(t[o])<0?(c=null===r?i(e,t[o],null):i(e,t[o],r-1),c.indexOf("\n")>-1&&(c=s?c.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+c.split("\n").map(function(e){return" "+e}).join("\n"))):c=e.stylize("[Circular]","special")),"undefined"==typeof a){if(s&&o.match(/^\d+$/))return c;a=JSON.stringify(""+o),a.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+c}function c(e,t,r){var i=0,n=e.reduce(function(e,t){return i++,t.indexOf("\n")>=0&&i++,e+t.length+1},0);return n>60?r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1]:r[0]+t+" "+e.join(", ")+" "+r[1]}function u(e){return Array.isArray(e)||"object"==typeof e&&"[object Array]"===p(e)}function h(e){return"object"==typeof e&&"[object RegExp]"===p(e)}function l(e){return"object"==typeof e&&"[object Date]"===p(e)}function f(e){return"object"==typeof e&&"[object Error]"===p(e)}function p(e){return Object.prototype.toString.call(e)}var d=require("chai/lib/chai/utils/getName.js"),g=require("chai/lib/chai/utils/getProperties.js"),b=require("chai/lib/chai/utils/getEnumerableProperties.js");t.exports=r;var v=function(e){return"object"==typeof HTMLElement?e instanceof HTMLElement:e&&"object"==typeof e&&1===e.nodeType&&"string"==typeof e.nodeName}}),require.register("chai/lib/chai/utils/objDisplay.js",function(e,t){var r=require("chai/lib/chai/utils/inspect.js"),i=require("chai/lib/chai/config.js");t.exports=function(e){var t=r(e),n=Object.prototype.toString.call(e);if(i.truncateThreshold&&t.length>=i.truncateThreshold){if("[object Function]"===n)return e.name&&""!==e.name?"[Function: "+e.name+"]":"[Function]";if("[object Array]"===n)return"[ Array("+e.length+") ]";if("[object Object]"===n){var o=Object.keys(e),s=o.length>2?o.splice(0,2).join(", ")+", ...":o.join(", ");return"{ Object ("+s+") }"}return t}return t}}),require.register("chai/lib/chai/utils/overwriteMethod.js",function(e,t){t.exports=function(e,t,r){var i=e[t],n=function(){return this};i&&"function"==typeof i&&(n=i),e[t]=function(){var e=r(n).apply(this,arguments);return void 0===e?this:e}}}),require.register("chai/lib/chai/utils/overwriteProperty.js",function(e,t){t.exports=function(e,t,r){var i=Object.getOwnPropertyDescriptor(e,t),n=function(){};i&&"function"==typeof i.get&&(n=i.get),Object.defineProperty(e,t,{get:function(){var e=r(n).call(this);return void 0===e?this:e},configurable:!0})}}),require.register("chai/lib/chai/utils/overwriteChainableMethod.js",function(e,t){t.exports=function(e,t,r,i){var n=e.__methods[t],o=n.chainingBehavior;n.chainingBehavior=function(){var e=i(o).call(this);return void 0===e?this:e};var s=n.method;n.method=function(){var e=r(s).apply(this,arguments);return void 0===e?this:e}}}),require.register("chai/lib/chai/utils/test.js",function(e,t){var r=require("chai/lib/chai/utils/flag.js");t.exports=function(e,t){var i=r(e,"negate"),n=t[0];return i?!n:n}}),require.register("chai/lib/chai/utils/transferFlags.js",function(e,t){t.exports=function(e,t,r){var i=e.__flags||(e.__flags=Object.create(null));t.__flags||(t.__flags=Object.create(null)),r=3===arguments.length?r:!0;for(var n in i)(r||"object"!==n&&"ssfi"!==n&&"message"!=n)&&(t.__flags[n]=i[n])}}),require.register("chai/lib/chai/utils/type.js",function(e,t){var r={"[object Arguments]":"arguments","[object Array]":"array","[object Date]":"date","[object Function]":"function","[object Number]":"number","[object RegExp]":"regexp","[object String]":"string"};t.exports=function(e){var t=Object.prototype.toString.call(e);return r[t]?r[t]:null===e?"null":void 0===e?"undefined":e===Object(e)?"object":typeof e}}),"object"==typeof exports?module.exports=require("chai"):"function"==typeof define&&define.amd?define("chai",[],function(){return require("chai")}):(this||window).chai=require("chai")}();
diff --git a/chromium/third_party/catapult/tracing/third_party/d3/LICENSE b/chromium/third_party/catapult/tracing/third_party/d3/LICENSE
new file mode 100644
index 00000000000..fb7d95d70ba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/d3/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2014, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chromium/third_party/catapult/tracing/third_party/d3/README.chromium b/chromium/third_party/catapult/tracing/third_party/d3/README.chromium
new file mode 100644
index 00000000000..35362f83284
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/d3/README.chromium
@@ -0,0 +1,15 @@
+Name: d3
+Short Name: d3
+URL: https://github.com/mbostock/d3
+Version: 0
+Revision: 0b2fe8fe9eaa529f70f6ab93bc8580b2a5328f43
+Date: Sat Mar 1 11:31:09 2014 -0800
+License: BSD
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+A JavaScript visualization library for HTML and SVG.
+
+Local Modifications:
+Took only the minified JS file and associated license.
diff --git a/chromium/third_party/catapult/tracing/third_party/d3/d3.min.js b/chromium/third_party/catapult/tracing/third_party/d3/d3.min.js
new file mode 100644
index 00000000000..b0178b69e86
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/d3/d3.min.js
@@ -0,0 +1,5 @@
+!function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(n){return aa+n in this}function o(n){return n=aa+n,n in this&&delete this[n]}function a(){var n=[];return this.forEach(function(t){n.push(t)}),n}function c(){var n=0;for(var t in this)t.charCodeAt(0)===ca&&++n;return n}function s(){for(var n in this)if(n.charCodeAt(0)===ca)return!1;return!0}function l(){}function f(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function h(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=sa.length;r>e;++e){var u=sa[e]+t;if(u in n)return u}}function g(){}function p(){}function v(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new u;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function d(){Xo.event.preventDefault()}function m(){for(var n,t=Xo.event;n=t.sourceEvent;)t=n;return t}function y(n){for(var t=new p,e=0,r=arguments.length;++e<r;)t[arguments[e]]=v(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Xo.event;u.target=n,Xo.event=u,t[u.type].apply(e,r)}finally{Xo.event=i}}},t}function x(n){return fa(n,da),n}function M(n){return"function"==typeof n?n:function(){return ha(n,this)}}function _(n){return"function"==typeof n?n:function(){return ga(n,this)}}function b(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Xo.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function w(n){return n.trim().replace(/\s+/g," ")}function S(n){return new RegExp("(?:^|\\s+)"+Xo.requote(n)+"(?:\\s+|$)","g")}function k(n){return n.trim().split(/^|\s+/)}function E(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=k(n).map(A);var u=n.length;return"function"==typeof t?r:e}function A(n){var t=S(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",w(u+" "+n))):e.setAttribute("class",w(u.replace(t," ")))}}function C(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function N(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function L(n){return"function"==typeof n?n:(n=Xo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function T(n){return{__data__:n}}function q(n){return function(){return va(this,n)}}function z(n){return arguments.length||(n=Xo.ascending),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function R(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function D(n){return fa(n,ya),n}function P(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function U(){var n=this.__transition__;n&&++n.active}function j(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Bo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+Xo.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=H;a>0&&(n=n.substring(0,a));var s=Ma.get(n);return s&&(n=s,c=F),a?t?u:r:t?g:i}function H(n,t){return function(e){var r=Xo.event;Xo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Xo.event=r}}}function F(n,t){var e=H(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function O(){var n=".dragsuppress-"+ ++ba,t="click"+n,e=Xo.select(Go).on("touchmove"+n,d).on("dragstart"+n,d).on("selectstart"+n,d);if(_a){var r=Jo.style,u=r[_a];r[_a]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),_a&&(r[_a]=u),i&&(e.on(t,function(){d(),o()},!0),setTimeout(o,0))}}function Y(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>wa&&(Go.scrollX||Go.scrollY)){e=Xo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();wa=!(u.f||u.e),e.remove()}return wa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function I(n){return n>0?1:0>n?-1:0}function Z(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function V(n){return n>1?0:-1>n?Sa:Math.acos(n)}function X(n){return n>1?Ea:-1>n?-Ea:Math.asin(n)}function $(n){return((n=Math.exp(n))-1/n)/2}function B(n){return((n=Math.exp(n))+1/n)/2}function W(n){return((n=Math.exp(2*n))-1)/(n+1)}function J(n){return(n=Math.sin(n/2))*n}function G(){}function K(n,t,e){return new Q(n,t,e)}function Q(n,t,e){this.h=n,this.s=t,this.l=e}function nt(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,gt(u(n+120),u(n),u(n-120))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.h=n,this.c=t,this.l=e}function rt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),ut(e,Math.cos(n*=Na)*t,Math.sin(n)*t)}function ut(n,t,e){return new it(n,t,e)}function it(n,t,e){this.l=n,this.a=t,this.b=e}function ot(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=ct(u)*Fa,r=ct(r)*Oa,i=ct(i)*Ya,gt(lt(3.2404542*u-1.5371385*r-.4985314*i),lt(-.969266*u+1.8760108*r+.041556*i),lt(.0556434*u-.2040259*r+1.0572252*i))}function at(n,t,e){return n>0?tt(Math.atan2(e,t)*La,Math.sqrt(t*t+e*e),n):tt(0/0,0/0,n)}function ct(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function st(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function lt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ft(n){return gt(n>>16,255&n>>8,255&n)}function ht(n){return ft(n)+""}function gt(n,t,e){return new pt(n,t,e)}function pt(n,t,e){this.r=n,this.g=t,this.b=e}function vt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function dt(n,t,e){var r,u,i,o,a=0,c=0,s=0;if(u=/([a-z]+)\((.*)\)/i.exec(n))switch(i=u[2].split(","),u[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Mt(i[0]),Mt(i[1]),Mt(i[2]))}return(o=Va.get(n))?t(o.r,o.g,o.b):(null!=n&&"#"===n.charAt(0)&&(r=parseInt(n.substring(1),16),isNaN(r)||(4===n.length?(a=(3840&r)>>4,a=a>>4|a,c=240&r,c=c>>4|c,s=15&r,s=s<<4|s):7===n.length&&(a=(16711680&r)>>16,c=(65280&r)>>8,s=255&r))),t(a,c,s))}function mt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),K(r,u,c)}function yt(n,t,e){n=xt(n),t=xt(t),e=xt(e);var r=st((.4124564*n+.3575761*t+.1804375*e)/Fa),u=st((.2126729*n+.7151522*t+.072175*e)/Oa),i=st((.0193339*n+.119192*t+.9503041*e)/Ya);return ut(116*u-16,500*(r-u),200*(u-i))}function xt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Mt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function _t(n){return"function"==typeof n?n:function(){return n}}function bt(n){return n}function wt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),St(t,e,n,r)}}function St(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Xo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Go.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Xo.event;Xo.event=n;try{o.progress.call(i,c)}finally{Xo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Bo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Xo.rebind(i,o,"on"),null==r?i:i.get(kt(r))}function kt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Et(){var n=At(),t=Ct()-n;t>24?(isFinite(t)&&(clearTimeout(Wa),Wa=setTimeout(Et,t)),Ba=0):(Ba=1,Ga(Et))}function At(){var n=Date.now();for(Ja=Xa;Ja;)n>=Ja.t&&(Ja.f=Ja.c(n-Ja.t)),Ja=Ja.n;return n}function Ct(){for(var n,t=Xa,e=1/0;t;)t.f?t=n?n.n=t.n:Xa=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return $a=n,e}function Nt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*oa(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:bt;return function(n){var e=Qa.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=nc.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Xo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function zt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Rt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new ec(e-1)),1),e}function i(n,e){return t(n=new ec(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{ec=zt;var r=new zt;return r._=n,o(r,t,e)}finally{ec=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Dt(n);return c.floor=c,c.round=Dt(r),c.ceil=Dt(u),c.offset=Dt(i),c.range=a,n}function Dt(n){return function(t,e){try{ec=zt;var r=new zt;return r._=t,n(r,e)._}finally{ec=Date}}}function Pt(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=uc[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=C[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&ec!==zt,o=new(i?zt:ec);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c>a;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in uc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{ec=zt;var t=new ec;return t._=n,r(t)}finally{ec=Date}}var r=t(n);return e.parse=function(n){try{ec=zt;var t=r.parse(n);return t&&t._}finally{ec=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ee;var x=Xo.map(),M=jt(v),_=Ht(v),b=jt(d),w=Ht(d),S=jt(m),k=Ht(m),E=jt(y),A=Ht(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Ut(n.getDate(),t,2)},e:function(n,t){return Ut(n.getDate(),t,2)},H:function(n,t){return Ut(n.getHours(),t,2)},I:function(n,t){return Ut(n.getHours()%12||12,t,2)},j:function(n,t){return Ut(1+tc.dayOfYear(n),t,3)},L:function(n,t){return Ut(n.getMilliseconds(),t,3)},m:function(n,t){return Ut(n.getMonth()+1,t,2)},M:function(n,t){return Ut(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Ut(n.getSeconds(),t,2)},U:function(n,t){return Ut(tc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Ut(tc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Ut(n.getFullYear()%100,t,2)},Y:function(n,t){return Ut(n.getFullYear()%1e4,t,4)},Z:ne,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Bt,e:Bt,H:Jt,I:Jt,j:Wt,L:Qt,m:$t,M:Gt,p:l,S:Kt,U:Ot,w:Ft,W:Yt,x:c,X:s,y:Zt,Y:It,Z:Vt,"%":te};return t}function Ut(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function jt(n){return new RegExp("^(?:"+n.map(Xo.requote).join("|")+")","i")}function Ht(n){for(var t=new u,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Ft(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Ot(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function Yt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function It(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Zt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.y=Xt(+r[0]),e+r[0].length):-1}function Vt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=+t,e+5):-1}function Xt(n){return n+(n>68?1900:2e3)}function $t(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Bt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Wt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Jt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Gt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Kt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function Qt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ne(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(oa(t)/60),u=oa(t)%60;return e+Ut(r,"0",2)+Ut(u,"0",2)}function te(n,t,e){oc.lastIndex=0;var r=oc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function ee(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function re(){}function ue(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function ie(n,t){n&&lc.hasOwnProperty(n.type)&&lc[n.type](n,t)}function oe(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ae(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)oe(n[e],t,1);t.polygonEnd()}function ce(){function n(n,t){n*=Na,t=t*Na/2+Sa/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);hc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;gc.point=function(o,a){gc.point=n,r=(t=o)*Na,u=Math.cos(a=(e=a)*Na/2+Sa/4),i=Math.sin(a)},gc.lineEnd=function(){n(t,e)}}function se(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function le(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function fe(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function he(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ge(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function pe(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function ve(n){return[Math.atan2(n[1],n[0]),X(n[2])]}function de(n,t){return oa(n[0]-t[0])<Aa&&oa(n[1]-t[1])<Aa}function me(n,t){n*=Na;var e=Math.cos(t*=Na);ye(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function ye(n,t,e){++pc,dc+=(n-dc)/pc,mc+=(t-mc)/pc,yc+=(e-yc)/pc}function xe(){function n(n,u){n*=Na;var i=Math.cos(u*=Na),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);vc+=s,xc+=s*(t+(t=o)),Mc+=s*(e+(e=a)),_c+=s*(r+(r=c)),ye(t,e,r)}var t,e,r;kc.point=function(u,i){u*=Na;var o=Math.cos(i*=Na);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),kc.point=n,ye(t,e,r)}}function Me(){kc.point=me}function _e(){function n(n,t){n*=Na;var e=Math.cos(t*=Na),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&&-V(g)/h,v=Math.atan2(h,g);bc+=p*s,wc+=p*l,Sc+=p*f,vc+=v,xc+=v*(r+(r=o)),Mc+=v*(u+(u=a)),_c+=v*(i+(i=c)),ye(r,u,i)}var t,e,r,u,i;kc.point=function(o,a){t=o,e=a,kc.point=n,o*=Na;var c=Math.cos(a*=Na);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),ye(r,u,i)},kc.lineEnd=function(){n(t,e),kc.lineEnd=Me,kc.point=me}}function be(){return!0}function we(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(de(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new ke(e,n,null,!0),s=new ke(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new ke(r,n,null,!1),s=new ke(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),Se(i),Se(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function Se(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function ke(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ee(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r){if(1&t){n=e[0];var u,r=n.length-1,o=-1;for(i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);return i.lineEnd(),void 0}r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ae))}}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Xo.merge(g);var n=Le(m,p);g.length?we(g,Ne,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ce(),M=t(x);return y}}function Ae(n){return n.length>1}function Ce(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:g,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ne(n,t){return((n=n.x)[0]<0?n[1]-Ea-Aa:Ea-n[1])-((t=t.x)[0]<0?t[1]-Ea-Aa:Ea-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;hc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+Sa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+Sa/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>Sa,k=p*x;if(hc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*ka:_,S^h>=e^m>=e){var E=fe(se(f),se(n));pe(E);var A=fe(u,E);pe(A);var C=(S^_>=0?-1:1)*X(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-Aa>i||Aa>i&&0>hc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Sa:-Sa,c=oa(i-e);oa(c-Sa)<Aa?(n.point(e,r=(r+o)/2>0?Ea:-Ea),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Sa&&(oa(e-u)<Aa&&(e-=u*Aa),oa(i-a)<Aa&&(i-=a*Aa),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return oa(o)>Aa?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function ze(n,t,e,r){var u;if(null==n)u=e*Ea,r.point(-Sa,u),r.point(0,u),r.point(Sa,u),r.point(Sa,0),r.point(Sa,-u),r.point(0,-u),r.point(-Sa,-u),r.point(-Sa,0),r.point(-Sa,u);else if(oa(n[0]-t[0])>Aa){var i=n[0]<t[0]?Sa:-Sa;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Re(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Sa:-Sa),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(de(e,g)||de(p,g))&&(p[0]+=Aa,p[1]+=Aa,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&de(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=se(n),u=se(t),o=[1,0,0],a=fe(r,u),c=le(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=fe(o,a),p=ge(o,f),v=ge(a,h);he(p,v);var d=g,m=le(p,d),y=le(d,d),x=m*m-y*(le(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=ge(d,(-m-M)/y);if(he(_,p),_=ve(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=oa(A-Sa)<Aa,N=C||Aa>A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(oa(_[0]-w)<Aa?k:E):k<=_[1]&&_[1]<=E:A>Sa^(w<=_[0]&&_[0]<=S)){var L=ge(d,(-m+M)/y);return he(L,p),[_,ve(L)]}}}function u(t,e){var r=o?n:Sa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=oa(i)>Aa,c=cr(n,6*Na);return Ee(t,e,c,o?[0,-n]:[-Sa,n-Sa])}function De(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Pe(n,t,e,r){function u(r,u){return oa(r[0]-n)<Aa?u>0?0:3:oa(r[0]-e)<Aa?u>0?2:1:oa(r[1]-t)<Aa?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&Z(s,i,n)>0&&++t:i[1]<=r&&Z(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Ac,Math.min(Ac,n)),t=Math.max(-Ac,Math.min(Ac,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ce(),C=De(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Xo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&we(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function Ue(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function je(n){var t=0,e=Sa/3,r=nr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Sa/180,e=n[1]*Sa/180):[180*(t/Sa),180*(e/Sa)]},u}function He(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,X((i-(n*n+e*e)*u*u)/(2*u))]},e}function Fe(){function n(n,t){Nc+=u*n-r*t,r=n,u=t}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,t=r=i,e=u=o},Rc.lineEnd=function(){n(t,e)}}function Oe(n,t){Lc>n&&(Lc=n),n>qc&&(qc=n),Tc>t&&(Tc=t),t>zc&&(zc=t)}function Ye(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ie(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ie(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ie(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ze(n,t){dc+=n,mc+=t,++yc}function Ve(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);xc+=o*(t+n)/2,Mc+=o*(e+r)/2,_c+=o,Ze(t=n,e=r)}var t,e;Pc.point=function(r,u){Pc.point=n,Ze(t=r,e=u)}}function Xe(){Pc.point=Ze}function $e(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);xc+=o*(r+n)/2,Mc+=o*(u+t)/2,_c+=o,o=u*n-r*t,bc+=o*(r+n),wc+=o*(u+t),Sc+=3*o,Ze(r=n,u=t)}var t,e,r,u;Pc.point=function(i,o){Pc.point=n,Ze(t=r=i,e=u=o)},Pc.lineEnd=function(){n(t,e)}}function Be(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,ka)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:g};return a}function We(n){function t(n){return(a?r:e)(n)}function e(t){return Ke(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=se([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=oa(oa(w)-1)<Aa||oa(r-h)<Aa?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],L=C-t,T=N-e,q=x*L-y*T;(q*q/M>i||oa((y*L+x*T)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Na),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Je(n){var t=We(function(t,e){return n([t*La,e*La])});return function(n){return tr(t(n))}}function Ge(n){this.stream=n}function Ke(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Qe(n){return nr(function(){return n})()}function nr(n){function t(n){return n=a(n[0]*Na,n[1]*Na),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*La,n[1]*La]}function r(){a=Ue(o=ur(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=We(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Ec,_=bt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=tr(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Ec):Re((b=+n)*Na),u()):b
+},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Pe(n[0][0],n[0][1],n[1][0],n[1][1]):bt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Na,d=n[1]%360*Na,r()):[v*La,d*La]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Na,y=n[1]%360*Na,x=n.length>2?n[2]%360*Na:0,r()):[m*La,y*La,x*La]},Xo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function tr(n){return Ke(n,function(t,e){n.point(t*Na,e*Na)})}function er(n,t){return[n,t]}function rr(n,t){return[n>Sa?n-ka:-Sa>n?n+ka:n,t]}function ur(n,t,e){return n?t||e?Ue(or(n),ar(t,e)):or(n):t||e?ar(t,e):rr}function ir(n){return function(t,e){return t+=n,[t>Sa?t-ka:-Sa>t?t+ka:t,e]}}function or(n){var t=ir(n);return t.invert=ir(-n),t}function ar(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),X(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),X(l*r-a*u)]},e}function cr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=sr(e,u),i=sr(e,i),(o>0?i>u:u>i)&&(u+=o*ka)):(u=n+o*ka,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=ve([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function sr(n,t){var e=se(t);e[0]-=n,pe(e);var r=V(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Aa)%(2*Math.PI)}function lr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function hr(n){return n.source}function gr(n){return n.target}function pr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(J(r-t)+u*o*J(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*La,Math.atan2(o,Math.sqrt(r*r+u*u))*La]}:function(){return[n*La,t*La]};return p.distance=h,p}function vr(){function n(n,u){var i=Math.sin(u*=Na),o=Math.cos(u),a=oa((n*=Na)-t),c=Math.cos(a);Uc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;jc.point=function(u,i){t=u*Na,e=Math.sin(i*=Na),r=Math.cos(i),jc.point=n},jc.lineEnd=function(){jc.point=jc.lineEnd=g}}function dr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function mr(n,t){function e(n,t){var e=oa(oa(t)-Ea)<Aa?0:o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(Sa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=I(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ea]},e):xr}function yr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return oa(u)<Aa?er:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-I(u)*Math.sqrt(n*n+e*e)]},e)}function xr(n,t){return[n,Math.log(Math.tan(Sa/4+t/2))]}function Mr(n){var t,e=Qe(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=Sa*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function _r(n,t){return[Math.log(Math.tan(Sa/4+t/2)),-n]}function br(n){return n[0]}function wr(n){return n[1]}function Sr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Z(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function kr(n,t){return n[0]-t[0]||n[1]-t[1]}function Er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Ar(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Cr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Nr(){Jr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Jc.pop()||new Nr;return t.site=n,t}function Tr(n){Or(n),$c.remove(n),Jc.push(n),Jr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&oa(e-c.circle.x)<Aa&&oa(r-c.circle.cy)<Aa;)i=c.P,a.unshift(c),Tr(c),c=i;a.unshift(c),Or(c);for(var s=o;s.circle&&oa(e-s.circle.x)<Aa&&oa(r-s.circle.cy)<Aa;)o=s.N,a.push(s),Tr(s),s=o;a.push(s),Or(s);var l,f=a.length;for(l=1;f>l;++l)s=a[l],c=a[l-1],$r(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Vr(c.site,s.site,null,u),Fr(c),Fr(s)}function zr(n){for(var t,e,r,u,i=n.x,o=n.y,a=$c._;a;)if(r=Rr(a,o)-i,r>Aa)a=a.L;else{if(u=i-Dr(a,o),!(u>Aa)){r>-Aa?(t=a.P,e=a):u>-Aa?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if($c.insert(t,c),t||e){if(t===e)return Or(t),e=Lr(t.site),$c.insert(c,e),c.edge=e.edge=Vr(t.site,c.site),Fr(t),Fr(e),void 0;if(!e)return c.edge=Vr(t.site,c.site),void 0;Or(t),Or(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};$r(e.edge,s,p,M),c.edge=Vr(s,n,null,M),e.edge=Vr(n,p,null,M),Fr(t),Fr(e)}}function Rr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Dr(n,t){var e=n.N;if(e)return Rr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Pr(n){this.site=n,this.edges=[]}function Ur(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Xc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(oa(r-t)>Aa||oa(u-e)>Aa)&&(a.splice(o,0,new Br(Xr(i.site,l,oa(r-f)<Aa&&p-u>Aa?{x:f,y:oa(t-f)<Aa?e:p}:oa(u-p)<Aa&&h-r>Aa?{x:oa(e-p)<Aa?t:h,y:p}:oa(r-h)<Aa&&u-g>Aa?{x:h,y:oa(t-h)<Aa?e:g}:oa(u-g)<Aa&&r-f>Aa?{x:oa(e-g)<Aa?t:f,y:g}:null),i.site,null)),++c)}function jr(n,t){return t.angle-n.angle}function Hr(){Jr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Fr(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h>=-Ca)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Gc.pop()||new Hr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=Wc._;x;)if(m.y<x.y||m.y===x.y&&m.x<=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}Wc.insert(y,m),y||(Bc=m)}}}}function Or(n){var t=n.circle;t&&(t.P||(Bc=t.N),Wc.remove(t),Gc.push(t),Jr(t),n.circle=null)}function Yr(n){for(var t,e=Vc,r=De(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Ir(t,n)||!r(t)||oa(t.a.x-t.b.x)<Aa&&oa(t.a.y-t.b.y)<Aa)&&(t.a=t.b=null,e.splice(u,1))}function Ir(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y<c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y<c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Zr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Vr(n,t,e,r){var u=new Zr(n,t);return Vc.push(u),e&&$r(u,n,t,e),r&&$r(u,t,n,r),Xc[n.i].edges.push(new Br(u,n,t)),Xc[t.i].edges.push(new Br(u,t,n)),u}function Xr(n,t,e){var r=new Zr(n,null);return r.a=t,r.b=e,Vc.push(r),r}function $r(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Br(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Wr(){this._=null}function Jr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Gr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Kr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Qr(n){for(;n.L;)n=n.L;return n}function nu(n,t){var e,r,u,i=n.sort(tu).pop();for(Vc=[],Xc=new Array(n.length),$c=new Wr,Wc=new Wr;;)if(u=Bc,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Xc[i.i]=new Pr(i),zr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&&(Yr(t),Ur(t));var o={cells:Xc,edges:Vc};return $c=Wc=Vc=Xc=null,o}function tu(n,t){return t.y-n.y||t.x-n.x}function eu(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function ru(n){return n.x}function uu(n){return n.y}function iu(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function ou(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&ou(n,c[0],e,r,o,a),c[1]&&ou(n,c[1],o,r,u,a),c[2]&&ou(n,c[2],e,a,o,i),c[3]&&ou(n,c[3],o,a,u,i)}}function au(n,t){n=Xo.rgb(n),t=Xo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+vt(Math.round(e+i*n))+vt(Math.round(r+o*n))+vt(Math.round(u+a*n))}}function cu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=fu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function su(n,t){return t-=n=+n,function(e){return n+t*e}}function lu(n,t){var e,r,u,i,o,a=0,c=0,s=[],l=[];for(n+="",t+="",Qc.lastIndex=0,r=0;e=Qc.exec(t);++r)e.index&&s.push(t.substring(a,c=e.index)),l.push({i:s.length,x:e[0]}),s.push(null),a=Qc.lastIndex;for(a<t.length&&s.push(t.substring(a)),r=0,i=l.length;(e=Qc.exec(n))&&i>r;++r)if(o=l[r],o.x==e[0]){if(o.i)if(null==s[o.i+1])for(s[o.i-1]+=o.x,s.splice(o.i,1),u=r+1;i>u;++u)l[u].i--;else for(s[o.i-1]+=o.x+s[o.i+1],s.splice(o.i,2),u=r+1;i>u;++u)l[u].i-=2;else if(null==s[o.i+1])s[o.i]=o.x;else for(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1),u=r+1;i>u;++u)l[u].i--;l.splice(r,1),i--,r--}else o.x=su(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=l.pop(),null==s[o.i+1]?s[o.i]=o.x:(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1)),i--;return 1===s.length?null==s[0]?(o=l[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)s[(o=l[r]).i]=o.x(n);return s.join("")}}function fu(n,t){for(var e,r=Xo.interpolators.length;--r>=0&&!(e=Xo.interpolators[r](n,t)););return e}function hu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(fu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function gu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function pu(n){return function(t){return 1-n(1-t)}}function vu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function du(n){return n*n}function mu(n){return n*n*n}function yu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function xu(n){return function(t){return Math.pow(t,n)}}function Mu(n){return 1-Math.cos(n*Ea)}function _u(n){return Math.pow(2,10*(n-1))}function bu(n){return 1-Math.sqrt(1-n*n)}function wu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/ka*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*ka/t)}}function Su(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function ku(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Eu(n,t){n=Xo.hcl(n),t=Xo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return rt(e+i*n,r+o*n,u+a*n)+""}}function Au(n,t){n=Xo.hsl(n),t=Xo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return nt(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Xo.lab(n),t=Xo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(zu(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*La,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*La:0}function Tu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(Tu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function zu(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ru(n,t){var e,r=[],u=[],i=Xo.transform(n),o=Xo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:su(a[0],c[0])},{i:3,x:su(a[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),s!=l?(s-l>180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:su(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:su(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:su(g[0],p[0])},{i:e-2,x:su(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Du(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Uu(n){for(var t=n.source,e=n.target,r=Hu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function ju(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Hu(n,t){if(n===t)return n;for(var e=ju(n),r=ju(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Fu(n){n.fixed|=2}function Ou(n){n.fixed&=-7}function Yu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Iu(n){n.fixed&=-5}function Zu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Zu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Vu(n,t){return Xo.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Wu,n}function Xu(n){return n.children}function $u(n){return n.value}function Bu(n,t){return t.value-n.value}function Wu(n){return Xo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Ju(n){return n.x}function Gu(n){return n.y}function Ku(n,t,e){n.y0=t,n.y=e}function Qu(n){return Xo.range(n.length)}function ni(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ti(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ei(n){return n.reduce(ri,0)}function ri(n,t){return n+t[1]}function ui(n,t){return ii(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ii(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function oi(n){return[Xo.min(n),Xo.max(n)]}function ai(n,t){return n.parent==t.parent?1:2}function ci(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function si(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function li(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i<u;)t(r=li(e[i],t),n)>0&&(n=r);return n}function fi(n,t){return n.x-t.x}function hi(n,t){return t.x-n.x}function gi(n,t){return n.depth-t.depth}function pi(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c<o;)i=u[c],e(i,a),a=i;t(n,r)}e(n,null)}function vi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function di(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function mi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function yi(n,t){return n.value-t.value}function xi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Mi(n,t){n._pack_next=t,t._pack_prev=n}function _i(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function bi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(wi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],Ei(r,u,i),t(i),xi(r,i),r._pack_prev=i,xi(i,u),u=r._pack_next,o=3;s>o;o++){Ei(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(_i(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!_i(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?Mi(r,u=a):Mi(r=c,u),o--):(xi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s>o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(Si)}}function wi(n){n._pack_next=n._pack_prev=n}function Si(n){delete n._pack_next,delete n._pack_prev}function ki(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)ki(u[i],t,e,r)}function Ei(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function Ai(n){return 1+Xo.max(n,function(n){return n.y})}function Ci(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ni(n){var t=n.children;return t&&t.length?Ni(t[0]):n}function Li(n){var t,e=n.children;return e&&(t=e.length)?Li(e[t-1]):n}function Ti(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function qi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function zi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ri(n){return n.rangeExtent?n.rangeExtent():zi(n.range())}function Di(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Pi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Ui(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ls}function ji(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Xo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Hi(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?ji:Di,c=r?Pu:Du;return o=u(n,t,c,e),a=u(t,n,c,fu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Nu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Ii(n,t)},i.tickFormat=function(t,e){return Zi(n,t,e)},i.nice=function(t){return Oi(n,t),u()},i.copy=function(){return Hi(n,t,e,r)},u()}function Fi(n,t){return Xo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Oi(n,t){return Pi(n,Ui(Yi(n,t)[2]))}function Yi(n,t){null==t&&(t=10);var e=zi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Ii(n,t){return Xo.range.apply(Xo,Yi(n,t))}function Zi(n,t,e){var r=Yi(n,t);return Xo.format(e?e.replace(Qa,function(n,t,e,u,i,o,a,c,s,l){return[t,e,u,i,o,a,c,s||"."+Xi(l,r),l].join("")}):",."+Vi(r[2])+"f")}function Vi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Xi(n,t){var e=Vi(t[2]);return n in fs?Math.abs(e-Vi(Math.max(Math.abs(t[0]),Math.abs(t[1]))))+ +("e"!==n):e-2*("%"===n)}function $i(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Pi(r.map(u),e?Math:gs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=zi(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++<l;)for(var h=f-1;h>0;h--)o.push(i(s)*h);for(s=0;o[s]<a;s++);for(l=o.length;o[l-1]>c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return hs;arguments.length<2?t=hs:"function"!=typeof t&&(t=Xo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return $i(n.copy(),t,e,r)},Fi(o,n)}function Bi(n,t,e){function r(t){return n(u(t))}var u=Wi(t),i=Wi(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Ii(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(n){return r.domain(Oi(e,n))},r.exponent=function(o){return arguments.length?(u=Wi(t=o),i=Wi(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Bi(n.copy(),t,e)},Fi(r,n)}function Wi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Ji(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return Xo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++a<c;)i.has(o=r[a])||i.set(o,n.push(o));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(o=n,a=0,t={t:"range",a:arguments},e):o},e.rangePoints=function(u,i){arguments.length<2&&(i=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+i);return o=r(n.length<2?(c+s)/2:c+l*i/2,l),a=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-i+2*c);return o=r(l+h*c,h),s&&o.reverse(),a=h*(1-i),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-i+2*c)),g=f-l-(n.length-i)*h;return o=r(l+Math.round(g/2),h),s&&o.reverse(),a=Math.round(h*(1-i)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return zi(t.a[0])},e.copy=function(){return Ji(n,t)},e.domain(n)}function Gi(n,t){function e(){var e=0,i=t.length;for(u=[];++e<i;)u[e-1]=Xo.quantile(n,e/i);return r}function r(n){return isNaN(n=+n)?void 0:t[Xo.bisect(u,n)]}var u;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(Xo.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return u},r.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?u[e-1]:n[0],e<u.length?u[e]:n[n.length-1]]},r.copy=function(){return Gi(n,t)},e()}function Ki(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ki(n,t,e)},u()}function Qi(n,t){function e(e){return e>=e?t[Xo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Qi(n,t)},e}function no(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Ii(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return no(n)},t}function to(n){return n.innerRadius}function eo(n){return n.outerRadius}function ro(n){return n.startAngle}function uo(n){return n.endAngle}function io(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=_t(e),p=_t(r);++f<h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&&(o(),l=[]);return l.length&&o(),s.length?s.join(""):null}var e=br,r=wr,u=be,i=oo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=Ms.get(n)||oo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function oo(n){return n.join("L")}function ao(n){return oo(n)+"Z"}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function so(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function lo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function fo(n,t){return n.length<4?oo(n):n[1]+po(n.slice(1,n.length-1),vo(n,t))}function ho(n,t){return n.length<3?oo(n):n[0]+po((n.push(n[0]),n),vo([n[n.length-2]].concat(n,[n[1]]),t))}function go(n,t){return n.length<3?oo(n):n[0]+po(n,vo(n,t))}function po(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return oo(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s<t.length;s++,c++)i=n[c],a=t[s],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var l=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+l[0]+","+l[1]}return r}function vo(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function mo(n){if(n.length<3)return oo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",_o(ws,o),",",_o(ws,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),bo(c,o,a);return n.pop(),c.push("L",r),c.join("")}function yo(n){if(n.length<4)return oo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(_o(ws,i)+","+_o(ws,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),bo(e,i,o);return e.join("")}function xo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[_o(ws,o),",",_o(ws,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),bo(t,o,a);return t.join("")}function Mo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s<=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return mo(n)}function _o(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function bo(n,t,e){n.push("C",_o(_s,t),",",_o(_s,e),",",_o(bs,t),",",_o(bs,e),",",_o(ws,t),",",_o(ws,e))}function wo(n,t){return(t[1]-n[1])/(t[0]-n[0])}function So(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=wo(u,i);++t<e;)r[t]=(o+(o=wo(u=i,i=n[t+1])))/2;return r[t]=o,r}function ko(n){for(var t,e,r,u,i=[],o=So(n),a=-1,c=n.length-1;++a<c;)t=wo(n[a],n[a+1]),oa(t)<Aa?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function Eo(n){return n.length<3?oo(n):n[0]+po(n,ko(n))}function Ao(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+ys,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Co(n){function t(t){function c(){v.push("M",a(n(m),f),l,s(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=_t(e),_=_t(u),b=e===r?function(){return g}:_t(r),w=u===i?function(){return p}:_t(i);++y<x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=br,r=br,u=0,i=wr,o=be,a=oo,c=a.key,s=a,l="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=Ms.get(n)||oo).key,s=a.reverse||a,l=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function No(n){return n.radius}function Lo(n){return[n.x,n.y]}function To(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ys;return[e*Math.cos(r),e*Math.sin(r)]}}function qo(){return 64}function zo(){return"circle"}function Ro(n){var t=Math.sqrt(n/Sa);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Do(n,t){return fa(n,Ns),n.id=t,n}function Po(n,t,e,r){var u=n.id;return R(n,"function"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Uo(n){return null==n&&(n=""),function(){this.textContent=n}}function jo(n,t,e,r){var i=n.__transition__||(n.__transition__={active:0,count:0}),o=i[e];if(!o){var a=r.time;o=i[e]={tween:new u,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++i.count,Xo.timer(function(r){function u(r){return i.active>e?s():(i.active=e,o.event&&o.event.start.call(n,l,t),o.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Xo.timer(function(){return p.c=c(r||1)?be:c,1},0,a),void 0)}function c(r){if(i.active!==e)return s();for(var u=r/g,a=f(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,l,t),s()):void 0}function s(){return--i.count?delete i[e]:delete n.__transition__,1}var l=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=Ja,v=[];return p.t=h+a,r>=h?u(r-h):(p.c=u,void 0)},0,a)}}function Ho(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function Fo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Oo(n){return n.toISOString()}function Yo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Xo.bisect(js,u);return i==js.length?[t.year,Yi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/js[i-1]<js[i]/u?i-1:i]:[Os,Yi(n,e)[2]]
+}return r.invert=function(t){return Io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Io(+e+1),t).length}var i=r.domain(),o=zi(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Pi(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=zi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Yo(n.copy(),t,e)},Fi(r,n)}function Io(n){return new Date(n)}function Zo(n){return JSON.parse(n.responseText)}function Vo(n){var t=Wo.createRange();return t.selectNode(Wo.body),t.createContextualFragment(n.responseText)}var Xo={version:"3.4.3"};Date.now||(Date.now=function(){return+new Date});var $o=[].slice,Bo=function(n){return $o.call(n)},Wo=document,Jo=Wo.documentElement,Go=window;try{Bo(Jo.childNodes)[0].nodeType}catch(Ko){Bo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{Wo.createElement("div").style.setProperty("opacity",0,"")}catch(Qo){var na=Go.Element.prototype,ta=na.setAttribute,ea=na.setAttributeNS,ra=Go.CSSStyleDeclaration.prototype,ua=ra.setProperty;na.setAttribute=function(n,t){ta.call(this,n,t+"")},na.setAttributeNS=function(n,t,e){ea.call(this,n,t,e+"")},ra.setProperty=function(n,t,e){ua.call(this,n,t+"",e)}}Xo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},Xo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Xo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},Xo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},Xo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},Xo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Xo.mean=function(t,e){var r,u=t.length,i=0,o=-1,a=0;if(1===arguments.length)for(;++o<u;)n(r=t[o])&&(i+=(r-i)/++a);else for(;++o<u;)n(r=e.call(t,t[o],o))&&(i+=(r-i)/++a);return a?i:void 0},Xo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Xo.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?Xo.quantile(t.sort(Xo.ascending),.5):void 0},Xo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)<e?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;e<n.call(t,t[i],i)?u=i:r=i+1}return r}}};var ia=Xo.bisector(function(n){return n});Xo.bisectLeft=ia.left,Xo.bisect=Xo.bisectRight=ia.right,Xo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Xo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Xo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Xo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=Xo.min(arguments,t),r=new Array(e);++n<e;)for(var u,i=-1,o=r[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return r},Xo.transpose=function(n){return Xo.zip.apply(Xo,n)},Xo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Xo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Xo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Xo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var oa=Math.abs;Xo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error("infinite range");var u,i=[],o=e(oa(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)<t;)i.push(u/o);return i},Xo.map=function(n){var t=new u;if(n instanceof u)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},r(u,{has:i,get:function(n){return this[aa+n]},set:function(n,t){return this[aa+n]=t},remove:o,keys:a,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1),this[t])}});var aa="\x00",ca=aa.charCodeAt(0);Xo.nest=function(){function n(t,a,c){if(c>=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=o[c++],d=new u;++g<p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e>=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(Xo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},Xo.set=function(n){var t=new l;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(l,{has:i,add:function(n){return this[aa+n]=!0,n},remove:function(n){return n=aa+n,n in this&&delete this[n]},values:a,size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1))}}),Xo.behavior={},Xo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=f(n,t,t[e]);return n};var sa=["webkit","ms","moz","Moz","o","O"];Xo.dispatch=function(){for(var n=new p,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=v(n);return n},p.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Xo.event=null,Xo.requote=function(n){return n.replace(la,"\\$&")};var la=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,fa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ha=function(n,t){return t.querySelector(n)},ga=function(n,t){return t.querySelectorAll(n)},pa=Jo[h(Jo,"matchesSelector")],va=function(n,t){return pa.call(n,t)};"function"==typeof Sizzle&&(ha=function(n,t){return Sizzle(n,t)[0]||null},ga=Sizzle,va=Sizzle.matchesSelector),Xo.selection=function(){return xa};var da=Xo.selection.prototype=[];da.select=function(n){var t,e,r,u,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c<s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return x(i)},da.selectAll=function(n){var t,e,r=[];n=_(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Bo(n.call(e,e.__data__,a,u))),t.parentNode=e);return x(r)};var ma={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};Xo.ns={prefix:ma,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),ma.hasOwnProperty(e)?{space:ma[e],local:n}:n}},da.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Xo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(b(t,n[t]));return this}return this.each(b(n,t))},da.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=k(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!S(n[u]).test(t))return!1;return!0}for(t in n)this.each(E(t,n[t]));return this}return this.each(E(n,t))},da.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return Go.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(C(n,t,e))},da.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(N(t,n[t]));return this}return this.each(N(n,t))},da.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},da.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},da.append=function(n){return n=L(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},da.insert=function(n,t){return n=L(n),t=M(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},da.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},da.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new u,y=new u,x=[];for(r=-1;++r<a;)d=t.call(i=n[r],i.__data__,r),m.has(d)?v[r]=i:m.set(d,i),x.push(d);for(r=-1;++r<f;)d=t.call(e,o=e[r],r),(i=m.get(d))?(g[r]=i,i.__data__=o):y.has(d)||(p[r]=T(o)),y.set(d,o),m.remove(d);for(r=-1;++r<a;)m.has(x[r])&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],o=e[r],i?(i.__data__=o,g[r]=i):p[r]=T(o);for(;f>r;++r)p[r]=T(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++o<a;)(i=r[o])&&(n[o]=i.__data__);return n}var c=D([]),s=x([]),l=x([]);if("function"==typeof n)for(;++o<a;)e(r=this[o],n.call(r,r.parentNode.__data__,o));else for(;++o<a;)e(r=this[o],n);return s.enter=function(){return c},s.exit=function(){return l},s},da.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},da.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return x(u)},da.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},da.sort=function(n){n=z.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},da.each=function(n){return R(this,function(t,e,r){n.call(t,t.__data__,e,r)})},da.call=function(n){var t=Bo(arguments);return n.apply(t[0]=this,t),this},da.empty=function(){return!this.node()},da.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},da.size=function(){var n=0;return this.each(function(){++n}),n};var ya=[];Xo.selection.enter=D,Xo.selection.enter.prototype=ya,ya.append=da.append,ya.empty=da.empty,ya.node=da.node,ya.call=da.call,ya.size=da.size,ya.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s<l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return x(o)},ya.insert=function(n,t){return arguments.length<2&&(t=P(this)),da.insert.call(this,n,t)},da.transition=function(){for(var n,t,e=ks||++Ls,r=[],u=Es||{time:Date.now(),ease:yu,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c<s;)(t=a[c])&&jo(t,c,e,u),n.push(t)}return Do(r,e)},da.interrupt=function(){return this.each(U)},Xo.select=function(n){var t=["string"==typeof n?ha(n,Wo):n];return t.parentNode=Jo,x([t])},Xo.selectAll=function(n){var t=Bo("string"==typeof n?ga(n,Wo):n);return t.parentNode=Jo,x([t])};var xa=Xo.select(Jo);da.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(j(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(j(n,t,e))};var Ma=Xo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ma.forEach(function(n){"on"+n in Wo&&Ma.remove(n)});var _a="onselectstart"in Wo?null:h(Jo.style,"userSelect"),ba=0;Xo.mouse=function(n){return Y(n,m())};var wa=/WebKit/.test(Go.navigator.userAgent)?-1:0;Xo.touches=function(n,t){return arguments.length<2&&(t=m().touches),t?Bo(t).map(function(t){var e=Y(n,t);return e.identifier=t.identifier,e}):[]},Xo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return Xo.event.changedTouches[0].identifier}function e(n,t){return Xo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(l,g),e=n[0]-v[0],r=n[1]-v[1];d|=e|r,v=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(d&&Xo.event.target===h),f({type:"dragend"})}var c,s=this,l=s.parentNode,f=u.of(s,arguments),h=Xo.event.target,g=n(),p=null==g?"drag":"drag-"+g,v=t(l,g),d=0,m=Xo.select(Go).on(e+"."+p,o).on(r+"."+p,a),y=O();i?(c=i.apply(s,arguments),c=[c.x-v[0],c.y-v[1]]):c=[0,0],f({type:"dragstart"})}}var u=y(n,"drag","dragstart","dragend"),i=null,o=r(g,Xo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},Xo.rebind(n,u,"on")};var Sa=Math.PI,ka=2*Sa,Ea=Sa/2,Aa=1e-6,Ca=Aa*Aa,Na=Sa/180,La=180/Sa,Ta=Math.SQRT2,qa=2,za=4;Xo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=B(v),o=i/(qa*h)*(e*W(Ta*t+v)-$(v));return[r+o*s,u+o*l,i*e/B(Ta*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Ta*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+za*f)/(2*i*qa*h),p=(c*c-i*i-za*f)/(2*c*qa*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ta;return e.duration=1e3*y,e},Xo.behavior.zoom=function(){function n(n){n.on(A,s).on(Pa+".zoom",f).on(C,h).on("dblclick.zoom",g).on(L,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(M.range().map(function(n){return(n-S.x)/S.k}).map(M.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Xo.mouse(r),g),a(i)}function e(){f.on(C,Go===r?h:null).on(N,null),p(l&&Xo.event.target===s),c(i)}var r=this,i=T.of(r,arguments),s=Xo.event.target,l=0,f=Xo.select(Go).on(C,n).on(N,e),g=t(Xo.mouse(r)),p=O();U.call(r),o(i)}function l(){function n(){var n=Xo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=Xo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-x){var s=o[0],l=v[s.identifier];r(2*S.k),u(s,l),d(),a(p)}x=c}else if(o.length>1){var s=o[0],f=o[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function i(){for(var n,t,e,i,o=Xo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=m&&Math.sqrt(l/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}x=null,u(n,t),a(p)}function f(){if(Xo.event.touches.length){for(var t=Xo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}b.on(M,null).on(_,null),w.on(A,s).on(L,l),k(),c(p)}var h,g=this,p=T.of(g,arguments),v={},m=0,y=Xo.event.changedTouches[0].identifier,M="touchmove.zoom-"+y,_="touchend.zoom-"+y,b=Xo.select(Go).on(M,i).on(_,f),w=Xo.select(g).on(A,null).on(L,e),k=O();U.call(g),e(),o(p)}function f(){var n=T.of(this,arguments);m?clearTimeout(m):(U.call(this),o(n)),m=setTimeout(function(){m=null,c(n)},50),d();var e=v||Xo.mouse(this);p||(p=t(e)),r(Math.pow(2,.002*Ra())*S.k),u(e,p),a(n)}function h(){p=null}function g(){var n=T.of(this,arguments),e=Xo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Xo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var p,v,m,x,M,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=Da,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",L="touchstart.zoom",T=y(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=T.of(this,arguments),t=S;ks?Xo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Xo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?Da:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,M=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Xo.rebind(n,T,"on")};var Ra,Da=[0,1/0],Pa="onwheel"in Wo?(Ra=function(){return-Xo.event.deltaY*(Xo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in Wo?(Ra=function(){return Xo.event.wheelDelta},"mousewheel"):(Ra=function(){return-Xo.event.detail},"MozMousePixelScroll");G.prototype.toString=function(){return this.rgb()+""},Xo.hsl=function(n,t,e){return 1===arguments.length?n instanceof Q?K(n.h,n.s,n.l):dt(""+n,mt,K):K(+n,+t,+e)};var Ua=Q.prototype=new G;Ua.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,this.l/n)},Ua.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,n*this.l)},Ua.rgb=function(){return nt(this.h,this.s,this.l)},Xo.hcl=function(n,t,e){return 1===arguments.length?n instanceof et?tt(n.h,n.c,n.l):n instanceof it?at(n.l,n.a,n.b):at((n=yt((n=Xo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):tt(+n,+t,+e)};var ja=et.prototype=new G;ja.brighter=function(n){return tt(this.h,this.c,Math.min(100,this.l+Ha*(arguments.length?n:1)))},ja.darker=function(n){return tt(this.h,this.c,Math.max(0,this.l-Ha*(arguments.length?n:1)))},ja.rgb=function(){return rt(this.h,this.c,this.l).rgb()},Xo.lab=function(n,t,e){return 1===arguments.length?n instanceof it?ut(n.l,n.a,n.b):n instanceof et?rt(n.l,n.c,n.h):yt((n=Xo.rgb(n)).r,n.g,n.b):ut(+n,+t,+e)};var Ha=18,Fa=.95047,Oa=1,Ya=1.08883,Ia=it.prototype=new G;Ia.brighter=function(n){return ut(Math.min(100,this.l+Ha*(arguments.length?n:1)),this.a,this.b)},Ia.darker=function(n){return ut(Math.max(0,this.l-Ha*(arguments.length?n:1)),this.a,this.b)},Ia.rgb=function(){return ot(this.l,this.a,this.b)},Xo.rgb=function(n,t,e){return 1===arguments.length?n instanceof pt?gt(n.r,n.g,n.b):dt(""+n,gt,nt):gt(~~n,~~t,~~e)};var Za=pt.prototype=new G;Za.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),gt(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):gt(u,u,u)},Za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),gt(~~(n*this.r),~~(n*this.g),~~(n*this.b))},Za.hsl=function(){return mt(this.r,this.g,this.b)},Za.toString=function(){return"#"+vt(this.r)+vt(this.g)+vt(this.b)};var Va=Xo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Va.forEach(function(n,t){Va.set(n,ft(t))}),Xo.functor=_t,Xo.xhr=wt(bt),Xo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=St(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++<s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++l):10===r&&(u=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;s>l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new l,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Xo.csv=Xo.dsv(",","text/csv"),Xo.tsv=Xo.dsv(" ","text/tab-separated-values");var Xa,$a,Ba,Wa,Ja,Ga=Go[h(Go,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Xo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};$a?$a.n=i:Xa=i,$a=i,Ba||(Wa=clearTimeout(Wa),Ba=1,Ga(Et))},Xo.timer.flush=function(){At(),Ct()},Xo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Xo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Xo.round(n,Nt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Ka[8+e/3]};var Qa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,nc=Xo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Xo.round(n,Nt(n,t))).toFixed(Math.max(0,Math.min(20,Nt(n*(1+1e-15),t))))}}),tc=Xo.time={},ec=Date;zt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){rc.setUTCDate.apply(this._,arguments)},setDay:function(){rc.setUTCDay.apply(this._,arguments)},setFullYear:function(){rc.setUTCFullYear.apply(this._,arguments)},setHours:function(){rc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){rc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){rc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){rc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){rc.setUTCSeconds.apply(this._,arguments)},setTime:function(){rc.setTime.apply(this._,arguments)}};var rc=Date.prototype;tc.year=Rt(function(n){return n=tc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),tc.years=tc.year.range,tc.years.utc=tc.year.utc.range,tc.day=Rt(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),tc.days=tc.day.range,tc.days.utc=tc.day.utc.range,tc.dayOfYear=function(n){var t=tc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=tc[n]=Rt(function(n){return(n=tc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});tc[n+"s"]=e.range,tc[n+"s"].utc=e.utc.range,tc[n+"OfYear"]=function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)}}),tc.week=tc.sunday,tc.weeks=tc.sunday.range,tc.weeks.utc=tc.sunday.utc.range,tc.weekOfYear=tc.sundayOfYear;var uc={"-":"",_:" ",0:"0"},ic=/^\s*\d+/,oc=/^%/;Xo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Pt(n)}};var ac=Xo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Xo.format=ac.numberFormat,Xo.geo={},re.prototype={s:0,t:0,add:function(n){ue(n,this.t,cc),ue(cc.s,this.s,this),this.s?this.t+=cc.t:this.s=cc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cc=new re;Xo.geo.stream=function(n,t){n&&sc.hasOwnProperty(n.type)?sc[n.type](n,t):ie(n,t)};var sc={Feature:function(n,t){ie(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)ie(e[r].geometry,t)}},lc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){oe(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)oe(e[r],t,0)},Polygon:function(n,t){ae(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ae(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)ie(e[r],t)}};Xo.geo.area=function(n){return fc=0,Xo.geo.stream(n,gc),fc};var fc,hc=new re,gc={sphere:function(){fc+=4*Sa},point:g,lineStart:g,lineEnd:g,polygonStart:function(){hc.reset(),gc.lineStart=ce},polygonEnd:function(){var n=2*hc;fc+=0>n?4*Sa+n:n,gc.lineStart=gc.lineEnd=gc.point=g}};Xo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=se([t*Na,e*Na]);if(m){var u=fe(m,r),i=[u[1],-u[0],0],o=fe(i,u);pe(o),o=ve(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=oa(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=oa(r)>180?r+(r>0?360:-360):r}else v=n,d=e;gc.point(n,e),t(n,e)}function i(){gc.lineStart()}function o(){u(v,d),gc.lineEnd(),oa(y)>Aa&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,gc.polygonStart()},polygonEnd:function(){gc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0>hc?(l=-(h=180),f=-(g=90)):y>Aa?g=90:-Aa>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Xo.geo.stream(n,_);
+var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Xo.geo.centroid=function(n){pc=vc=dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,kc);var t=bc,e=wc,r=Sc,u=t*t+e*e+r*r;return Ca>u&&(t=xc,e=Mc,r=_c,Aa>vc&&(t=dc,e=mc,r=yc),u=t*t+e*e+r*r,Ca>u)?[0/0,0/0]:[Math.atan2(e,t)*La,X(r/Math.sqrt(u))*La]};var pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc,Sc,kc={sphere:g,point:me,lineStart:xe,lineEnd:Me,polygonStart:function(){kc.lineStart=_e},polygonEnd:function(){kc.lineStart=xe}},Ec=Ee(be,Te,ze,[-Sa,-Sa/2]),Ac=1e9;Xo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Pe(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Xo.geo.conicEqualArea=function(){return je(He)}).raw=He,Xo.geo.albers=function(){return Xo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Xo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Xo.geo.albers(),o=Xo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Xo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+Aa,f+.12*s+Aa],[l-.214*s-Aa,f+.234*s-Aa]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+Aa,f+.166*s+Aa],[l-.115*s-Aa,f+.234*s-Aa]]).stream(c).point,n},n.scale(1070)};var Cc,Nc,Lc,Tc,qc,zc,Rc={point:g,lineStart:g,lineEnd:g,polygonStart:function(){Nc=0,Rc.lineStart=Fe},polygonEnd:function(){Rc.lineStart=Rc.lineEnd=Rc.point=g,Cc+=oa(Nc/2)}},Dc={point:Oe,lineStart:g,lineEnd:g,polygonStart:g,polygonEnd:g},Pc={point:Ze,lineStart:Ve,lineEnd:Xe,polygonStart:function(){Pc.lineStart=$e},polygonEnd:function(){Pc.point=Ze,Pc.lineStart=Ve,Pc.lineEnd=Xe}};Xo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Xo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Cc=0,Xo.geo.stream(n,u(Rc)),Cc},n.centroid=function(n){return dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,u(Pc)),Sc?[bc/Sc,wc/Sc]:_c?[xc/_c,Mc/_c]:yc?[dc/yc,mc/yc]:[0/0,0/0]},n.bounds=function(n){return qc=zc=-(Lc=Tc=1/0),Xo.geo.stream(n,u(Dc)),[[Lc,Tc],[qc,zc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Je(n):bt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ye:new Be(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Xo.geo.albersUsa()).context(null)},Xo.geo.transform=function(n){return{stream:function(t){var e=new Ge(t);for(var r in n)e[r]=n[r];return e}}},Ge.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Xo.geo.projection=Qe,Xo.geo.projectionMutator=nr,(Xo.geo.equirectangular=function(){return Qe(er)}).raw=er.invert=er,Xo.geo.rotation=function(n){function t(t){return t=n(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t}return n=ur(n[0]%360*Na,n[1]*Na,n.length>2?n[2]*Na:0),t.invert=function(t){return t=n.invert(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t},t},rr.invert=er,Xo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ur(-n[0]*Na,-n[1]*Na,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=La,n[1]*=La}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=cr((t=+r)*Na,u*Na),n):t},n.precision=function(r){return arguments.length?(e=cr(t*Na,(u=+r)*Na),n):u},n.angle(90)},Xo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Na,u=n[1]*Na,i=t[1]*Na,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Xo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Xo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Xo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Xo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return oa(n%d)>Aa}).map(l)).concat(Xo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return oa(n%m)>Aa}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=lr(a,o,90),f=fr(r,e,y),h=lr(s,c,90),g=fr(i,u,y),n):y},n.majorExtent([[-180,-90+Aa],[180,90-Aa]]).minorExtent([[-180,-80-Aa],[180,80+Aa]])},Xo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=hr,u=gr;return n.distance=function(){return Xo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Xo.geo.interpolate=function(n,t){return pr(n[0]*Na,n[1]*Na,t[0]*Na,t[1]*Na)},Xo.geo.length=function(n){return Uc=0,Xo.geo.stream(n,jc),Uc};var Uc,jc={sphere:g,point:g,lineStart:vr,lineEnd:g,polygonStart:g,polygonEnd:g},Hc=dr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Xo.geo.azimuthalEqualArea=function(){return Qe(Hc)}).raw=Hc;var Fc=dr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},bt);(Xo.geo.azimuthalEquidistant=function(){return Qe(Fc)}).raw=Fc,(Xo.geo.conicConformal=function(){return je(mr)}).raw=mr,(Xo.geo.conicEquidistant=function(){return je(yr)}).raw=yr;var Oc=dr(function(n){return 1/n},Math.atan);(Xo.geo.gnomonic=function(){return Qe(Oc)}).raw=Oc,xr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ea]},(Xo.geo.mercator=function(){return Mr(xr)}).raw=xr;var Yc=dr(function(){return 1},Math.asin);(Xo.geo.orthographic=function(){return Qe(Yc)}).raw=Yc;var Ic=dr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Xo.geo.stereographic=function(){return Qe(Ic)}).raw=Ic,_r.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ea]},(Xo.geo.transverseMercator=function(){var n=Mr(_r),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[-n[1],n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},n.rotate([0,0])}).raw=_r,Xo.geom={},Xo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=_t(e),i=_t(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(kr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=Sr(a),l=Sr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t<l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=br,r=wr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Xo.geom.polygon=function(n){return fa(n,Zc),n};var Zc=Xo.geom.polygon.prototype=[];Zc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Zc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Zc.clip=function(n){for(var t,e,r,u,i,o,a=Cr(n),c=-1,s=this.length-Cr(this),l=this[s-1];++c<s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Er(o,l,u)?(Er(i,l,u)||n.push(Ar(i,o,l,u)),n.push(o)):Er(i,l,u)&&n.push(Ar(i,o,l,u)),i=o;a&&n.push(n[0]),l=u}return n};var Vc,Xc,$c,Bc,Wc,Jc=[],Gc=[];Pr.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(jr),t.length},Br.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Wr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=Qr(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(Gr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Gr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?Qr(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,Gr(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,Kr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Gr(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,Kr(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,Gr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Kr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},Xo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return nu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x>=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Aa)*Aa,y:Math.round(o(n,t)/Aa)*Aa,i:t}})}var r=br,u=wr,i=r,o=u,a=Kc;return n?t(n):(t.links=function(n){return nu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return nu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(jr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c<s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r<i.i&&r<f.i&&eu(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=_t(r=n),t):r},t.y=function(n){return arguments.length?(o=_t(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Kc:n,t):a===Kc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===Kc?null:a&&a[1]},t)};var Kc=[[-1e6,-1e6],[1e6,1e6]];Xo.geom.delaunay=function(n){return Xo.geom.voronoi().triangles(n)},Xo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(oa(c-e)+oa(l-r)<.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e>=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=iu()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=_t(a),M=_t(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.x<v&&(v=l.x),l.y<d&&(d=l.y),l.x>m&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=iu();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){ou(n,k,v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=br,c=wr;return(o=arguments.length)?(a=ru,c=uu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Xo.interpolateRgb=au,Xo.interpolateObject=cu,Xo.interpolateNumber=su,Xo.interpolateString=lu;var Qc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;Xo.interpolate=fu,Xo.interpolators=[function(n,t){var e=typeof t;return("string"===e?Va.has(t)||/^(#|rgb\(|hsl\()/.test(t)?au:lu:t instanceof G?au:"object"===e?Array.isArray(t)?hu:cu:su)(n,t)}],Xo.interpolateArray=hu;var ns=function(){return bt},ts=Xo.map({linear:ns,poly:xu,quad:function(){return du},cubic:function(){return mu},sin:function(){return Mu},exp:function(){return _u},circle:function(){return bu},elastic:wu,back:Su,bounce:function(){return ku}}),es=Xo.map({"in":bt,out:pu,"in-out":vu,"out-in":function(n){return vu(pu(n))}});Xo.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ts.get(e)||ns,r=es.get(r)||bt,gu(r(e.apply(null,$o.call(arguments,1))))},Xo.interpolateHcl=Eu,Xo.interpolateHsl=Au,Xo.interpolateLab=Cu,Xo.interpolateRound=Nu,Xo.transform=function(n){var t=Wo.createElementNS(Xo.ns.prefix.svg,"g");return(Xo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:rs)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var rs={a:1,b:0,c:0,d:1,e:0,f:0};Xo.interpolateTransform=Ru,Xo.layout={},Xo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Uu(n[e]));return t}},Xo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Xo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(s=0,g=-1;++g<i;)s+=u[h][g];v.push(s),m.push(Xo.range(i)),n+=s}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(ka-l*i)/n,s=0,h=-1;++h<i;){for(f=s,g=-1;++g<i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+"-"+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&&t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Xo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Xo.event.x,n.py=Xo.event.y,a.resume()}var e,r,u,i,o,a={},c=Xo.dispatch("start","tick","end"),s=[1,1],l=.9,f=us,h=is,g=-30,p=os,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Zu(t=Xo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Xo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a<s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Xo.behavior.drag().origin(bt).on("dragstart.force",Fu).on("drag.force",t).on("dragend.force",Ou)),arguments.length?(this.on("mouseover.force",Yu).on("mouseout.force",Iu).call(e),void 0):e},Xo.rebind(a,c,"on")};var us=20,is=1,os=1/0;Xo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(s=c.length)){for(var s,l,f=-1,h=t.children=new Array(s),g=0,p=o+1;++f<s;)l=h[f]=n(c[f],p,a),l.parent=t,g+=l.value;r&&h.sort(r),i&&(t.value=g)}else delete t.children,i&&(t.value=+i.call(e,t,o)||0);return t}function t(n,r){var u=n.children,o=0;if(u&&(a=u.length))for(var a,c=-1,s=r+1;++c<a;)o+=t(u[c],s);else i&&(o=+i.call(e,n,r)||0);return i&&(n.value=o),o}function e(t){var e=[];return n(t,0,e),e}var r=Bu,u=Xu,i=$u;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(u=n,e):u},e.value=function(n){return arguments.length?(i=n,e):i},e.revalue=function(n){return t(n,0),n},e},Xo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s<o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Xo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Vu(e,r)},Xo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-a)/Xo.sum(o),s=Xo.range(i.length);null!=e&&s.sort(e===as?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=as,r=0,u=ka;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var as={};Xo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Xo.permute(s,f),l=Xo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m>g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=bt,e=Qu,r=ni,u=Ku,i=Ju,o=Gu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:cs.get(t)||Qu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:ss.get(t)||ni,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var cs=Xo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ti),i=n.map(ei),o=Xo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Xo.range(n.length).reverse()},"default":Qu}),ss=Xo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ni});Xo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=s[i],a>=l[0]&&a<=l[1]&&(o=c[Xo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=oi,u=ui;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=_t(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ii(n,t)}:_t(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Xo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,s,l=r[0],f=l,h=-1;++h<i;)s=r[h],o(s,a),f=c(s,a,f),a=s;vi(n);var g=.5*(l._tree.prelim+s._tree.prelim);t?(u.prelim=t._tree.prelim+e(n,t),u.mod=u.prelim-g):u.prelim=g}else t&&(u.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,u=-1;for(t+=n._tree.mod;++u<r;)a(e[u],t)}}function c(n,t,r){if(t){for(var u,i=n,o=n,a=t,c=n.parent.children[0],s=i._tree.mod,l=o._tree.mod,f=a._tree.mod,h=c._tree.mod;a=si(a),i=ci(i),a&&i;)c=ci(c),o=si(o),o._tree.ancestor=n,u=a._tree.prelim+f-i._tree.prelim-s+e(a,i),u>0&&(di(mi(a,n,r),n,u),s+=u,l+=u),f+=a._tree.mod,s+=i._tree.mod,h+=c._tree.mod,l+=o._tree.mod;a&&!si(o)&&(o._tree.thread=a,o._tree.mod+=f-l),i&&!ci(c)&&(c._tree.thread=i,c._tree.mod+=s-h,r=n)}return r}var s=t.call(this,n,i),l=s[0];pi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(l),a(l,-l._tree.prelim);var f=li(l,hi),h=li(l,fi),g=li(l,gi),p=f.x-e(f,h)/2,v=h.x+e(h,f)/2,d=g.depth||1;return pi(l,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(v-p)*r[0],n.y=n.depth/d*r[1],delete n._tree}),s}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,pi(a,function(n){n.r=+l(n.value)}),pi(a,bi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;pi(a,function(n){n.r+=f}),pi(a,bi),pi(a,function(n){n.r-=f})}return ki(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Xo.layout.hierarchy().sort(yi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Vu(n,e)},Xo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;pi(c,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ai(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ni(c),f=Li(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return pi(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++i<o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l>e.dx)&&(l=e.dx);++i<o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=Xo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=Ti,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ti(t):qi(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return qi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?Ti:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Vu(i,a)},Xo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Xo.random.normal.apply(Xo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Xo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Xo.scale={};var ls={floor:bt,ceil:bt};Xo.scale.linear=function(){return Hi([0,1],[0,1],fu,!1)};var fs={s:1,g:1,p:1,r:1,e:1};Xo.scale.log=function(){return $i(Xo.scale.linear().domain([0,1]),10,!0,[1,10])};var hs=Xo.format(".0e"),gs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Xo.scale.pow=function(){return Bi(Xo.scale.linear(),1,[0,1])},Xo.scale.sqrt=function(){return Xo.scale.pow().exponent(.5)},Xo.scale.ordinal=function(){return Ji([],{t:"range",a:[[]]})},Xo.scale.category10=function(){return Xo.scale.ordinal().range(ps)},Xo.scale.category20=function(){return Xo.scale.ordinal().range(vs)},Xo.scale.category20b=function(){return Xo.scale.ordinal().range(ds)},Xo.scale.category20c=function(){return Xo.scale.ordinal().range(ms)};var ps=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(ht),vs=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(ht),ds=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(ht),ms=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(ht);Xo.scale.quantile=function(){return Gi([],[])},Xo.scale.quantize=function(){return Ki(0,1,[0,1])},Xo.scale.threshold=function(){return Qi([.5],[0,1])
+},Xo.scale.identity=function(){return no([0,1])},Xo.svg={},Xo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ys,a=u.apply(this,arguments)+ys,c=(o>a&&(c=o,o=a,a=c),a-o),s=Sa>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=xs?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=to,e=eo,r=ro,u=uo;return n.innerRadius=function(e){return arguments.length?(t=_t(e),n):t},n.outerRadius=function(t){return arguments.length?(e=_t(t),n):e},n.startAngle=function(t){return arguments.length?(r=_t(t),n):r},n.endAngle=function(t){return arguments.length?(u=_t(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ys;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ys=-Ea,xs=ka-Aa;Xo.svg.line=function(){return io(bt)};var Ms=Xo.map({linear:oo,"linear-closed":ao,step:co,"step-before":so,"step-after":lo,basis:mo,"basis-open":yo,"basis-closed":xo,bundle:Mo,cardinal:go,"cardinal-open":fo,"cardinal-closed":ho,monotone:Eo});Ms.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var _s=[0,2/3,1/3,0],bs=[0,1/3,2/3,0],ws=[0,1/6,2/3,1/6];Xo.svg.line.radial=function(){var n=io(Ao);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},so.reverse=lo,lo.reverse=so,Xo.svg.area=function(){return Co(bt)},Xo.svg.area.radial=function(){var n=Co(Ao);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Xo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ys,l=s.call(n,u,r)+ys;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Sa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=hr,o=gr,a=No,c=ro,s=uo;return n.radius=function(t){return arguments.length?(a=_t(t),n):a},n.source=function(t){return arguments.length?(i=_t(t),n):i},n.target=function(t){return arguments.length?(o=_t(t),n):o},n.startAngle=function(t){return arguments.length?(c=_t(t),n):c},n.endAngle=function(t){return arguments.length?(s=_t(t),n):s},n},Xo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=hr,e=gr,r=Lo;return n.source=function(e){return arguments.length?(t=_t(e),n):t},n.target=function(t){return arguments.length?(e=_t(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Xo.svg.diagonal.radial=function(){var n=Xo.svg.diagonal(),t=Lo,e=n.projection;return n.projection=function(n){return arguments.length?e(To(t=n)):t},n},Xo.svg.symbol=function(){function n(n,r){return(Ss.get(t.call(this,n,r))||Ro)(e.call(this,n,r))}var t=zo,e=qo;return n.type=function(e){return arguments.length?(t=_t(e),n):t},n.size=function(t){return arguments.length?(e=_t(t),n):e},n};var Ss=Xo.map({circle:Ro,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Cs)),e=t*Cs;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Xo.svg.symbolTypes=Ss.keys();var ks,Es,As=Math.sqrt(3),Cs=Math.tan(30*Na),Ns=[],Ls=0;Ns.call=da.call,Ns.empty=da.empty,Ns.node=da.node,Ns.size=da.size,Xo.transition=function(n){return arguments.length?ks?n.transition():n:xa.transition()},Xo.transition.prototype=Ns,Ns.select=function(n){var t,e,r,u=this.id,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s<l;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),jo(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return Do(i,u)},Ns.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=_(n);for(var c=-1,s=this.length;++c<s;)for(var l=this[c],f=-1,h=l.length;++f<h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&jo(u,g,o,i),t.push(u)}return Do(a,o)},Ns.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Do(u,this.id)},Ns.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):R(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Ns.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Ru:fu,a=Xo.ns.qualify(n);return Po(this,"attr."+n,t,a.local?i:u)},Ns.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Xo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Ns.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Go.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=fu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Po(this,"style."+n,t,u)},Ns.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Go.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Ns.text=function(n){return Po(this,"text",n,Uo)},Ns.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Ns.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Xo.ease.apply(Xo,arguments)),R(this,function(e){e.__transition__[t].ease=n}))},Ns.delay=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Ns.duration=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Ns.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Es,u=ks;ks=e,R(this,function(t,r,u){Es=t.__transition__[e],n.call(t,t.__data__,r,u)}),Es=r,ks=u}else R(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Xo.dispatch("start","end"))).on(n,t)});return this},Ns.transition=function(){for(var n,t,e,r,u=this.id,i=++Ls,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,jo(e,s,i,r)),n.push(e)}return Do(o,i)},Xo.svg.axis=function(){function n(n){n.each(function(){var n,s=Xo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):bt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Aa),d=Xo.transition(p.exit()).style("opacity",Aa).remove(),m=Xo.transition(p).style("opacity",1),y=Ri(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Xo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Ho,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ho,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=Fo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=Fo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Xo.scale.linear(),r=Ts,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in qs?t+"":Ts,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Ts="bottom",qs={top:1,right:1,bottom:1,left:1};Xo.svg.brush=function(){function n(i){i.each(function(){var i=Xo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,bt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return zs[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Xo.transition(i),h=Xo.transition(o);c&&(l=Ri(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ri(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Xo.event.keyCode&&(C||(x=null,L[0]-=l[1],L[1]-=f[1],C=2),d())}function p(){32==Xo.event.keyCode&&2==C&&(L[0]+=l[1],L[1]+=f[1],C=0,d())}function v(){var n=Xo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Xo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),L[0]=l[+(n[0]<x[0])],L[1]=f[+(n[1]<x[1])]):x=null),E&&m(n,c,0)&&(e(S),u=!0),A&&m(n,s,1)&&(r(S),u=!0),u&&(t(S),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,a=Ri(t),c=a[0],s=a[1],p=L[e],v=e?f:l,d=v[1]-v[0];return C&&(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&&(p=Math.max(c,Math.min(s,2*x[e]-r))),r>p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Xo.select("body").style("cursor",null),T.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Xo.select(Xo.event.target),w=a.of(_,arguments),S=Xo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=O(),L=Xo.mouse(_),T=Xo.select(Go).on("keydown.brush",u).on("keyup.brush",p);if(Xo.event.changedTouches?T.on("touchmove.brush",v).on("touchend.brush",y):T.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),C)L[0]=l[0]-L[0],L[1]=f[0]-L[1];else if(k){var q=+/w$/.test(k),z=+/^n/.test(k);M=[l[1-q]-L[0],f[1-z]-L[1]],L[0]=l[q],L[1]=f[z]}else Xo.event.altKey&&(x=L.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Xo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=y(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=Rs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,ks?Xo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=hu(l,t.x),r=hu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Rs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=Rs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Xo.rebind(n,a,"on")};var zs={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Rs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Ds=tc.format=ac.timeFormat,Ps=Ds.utc,Us=Ps("%Y-%m-%dT%H:%M:%S.%LZ");Ds.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Oo:Us,Oo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Oo.toString=Us.toString,tc.second=Rt(function(n){return new ec(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),tc.seconds=tc.second.range,tc.seconds.utc=tc.second.utc.range,tc.minute=Rt(function(n){return new ec(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),tc.minutes=tc.minute.range,tc.minutes.utc=tc.minute.utc.range,tc.hour=Rt(function(n){var t=n.getTimezoneOffset()/60;return new ec(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),tc.hours=tc.hour.range,tc.hours.utc=tc.hour.utc.range,tc.month=Rt(function(n){return n=tc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),tc.months=tc.month.range,tc.months.utc=tc.month.utc.range;var js=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Hs=[[tc.second,1],[tc.second,5],[tc.second,15],[tc.second,30],[tc.minute,1],[tc.minute,5],[tc.minute,15],[tc.minute,30],[tc.hour,1],[tc.hour,3],[tc.hour,6],[tc.hour,12],[tc.day,1],[tc.day,2],[tc.week,1],[tc.month,1],[tc.month,3],[tc.year,1]],Fs=Ds.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",be]]),Os={range:function(n,t,e){return Xo.range(Math.ceil(n/e)*e,+t,e).map(Io)},floor:bt,ceil:bt};Hs.year=tc.year,tc.scale=function(){return Yo(Xo.scale.linear(),Hs,Fs)};var Ys=Hs.map(function(n){return[n[0].utc,n[1]]}),Is=Ps.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",be]]);Ys.year=tc.year.utc,tc.scale.utc=function(){return Yo(Xo.scale.linear(),Ys,Is)},Xo.text=wt(function(n){return n.responseText}),Xo.json=function(n,t){return St(n,"application/json",Zo,t)},Xo.html=function(n,t){return St(n,"text/html",Vo,t)},Xo.xml=wt(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Xo):"object"==typeof module&&module.exports?module.exports=Xo:this.d3=Xo}(); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/devscripts/COPYING b/chromium/third_party/catapult/tracing/third_party/devscripts/COPYING
new file mode 100644
index 00000000000..c74d291485b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/devscripts/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/chromium/third_party/catapult/tracing/third_party/devscripts/README.chromium b/chromium/third_party/catapult/tracing/third_party/devscripts/README.chromium
new file mode 100644
index 00000000000..1016e4cbebb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/devscripts/README.chromium
@@ -0,0 +1,12 @@
+Name: devscripts
+URL: http://anonscm.debian.org/gitweb/?p=devscripts/devscripts.git
+Version: 2.12.4
+Security Critical: no
+License: GPL 2.0
+
+Description:
+This directory contains selected tools from the Debian's devscripts collection.
+
+A .vanilla file is checked in so that our patched version can be easily
+compared with the unpatched script (e.g. when sending the changes upstream).
+Having a .patch file checked in was too inconvenient to keep up to date.
diff --git a/chromium/third_party/catapult/tracing/third_party/devscripts/licensecheck.pl b/chromium/third_party/catapult/tracing/third_party/devscripts/licensecheck.pl
new file mode 100755
index 00000000000..a59bbf96320
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/devscripts/licensecheck.pl
@@ -0,0 +1,671 @@
+#!/usr/bin/perl -w
+# This script was originally based on the script of the same name from
+# the KDE SDK (by dfaure@kde.org)
+#
+# This version is
+# Copyright (C) 2007, 2008 Adam D. Barratt
+# Copyright (C) 2012 Francesco Poli
+#
+# This program 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+=head1 NAME
+
+licensecheck - simple license checker for source files
+
+=head1 SYNOPSIS
+
+B<licensecheck> B<--help>|B<--version>
+
+B<licensecheck> [B<--no-conf>] [B<--verbose>] [B<--copyright>]
+[B<-l>|B<--lines=>I<N>] [B<-i>|B<--ignore=>I<regex>] [B<-c>|B<--check=>I<regex>]
+[B<-m>|B<--machine>] [B<-r>|B<--recursive>]
+I<list of files and directories to check>
+
+=head1 DESCRIPTION
+
+B<licensecheck> attempts to determine the license that applies to each file
+passed to it, by searching the start of the file for text belonging to
+various licenses.
+
+If any of the arguments passed are directories, B<licensecheck> will add
+the files contained within to the list of files to process.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--verbose>, B<--no-verbose>
+
+Specify whether to output the text being processed from each file before
+the corresponding license information.
+
+Default is to be quiet.
+
+=item B<-l=>I<N>, B<--lines=>I<N>
+
+Specify the number of lines of each file's header which should be parsed
+for license information. (Default is 60).
+
+=item B<-i=>I<regex>, B<--ignore=>I<regex>
+
+When processing the list of files and directories, the regular
+expression specified by this option will be used to indicate those which
+should not be considered (e.g. backup files, VCS metadata).
+
+=item B<-r>, B<--recursive>
+
+Specify that the contents of directories should be added
+recursively.
+
+=item B<-c=>I<regex>, B<--check=>I<regex>
+
+Specify a pattern against which filenames will be matched in order to
+decide which files to check the license of.
+
+The default includes common source files.
+
+=item B<--copyright>
+
+Also display copyright text found within the file
+
+=item B<-m>, B<--machine>
+
+Display the information in a machine readable way, i.e. in the form
+<file><tab><license>[<tab><copyright>] so that it can be easily sorted
+and/or filtered, e.g. with the B<awk> and B<sort> commands.
+Note that using the B<--verbose> option will kill the readability.
+
+=item B<--no-conf>, B<--noconf>
+
+Do not read any configuration files. This can only be used as the first
+option given on the command-line.
+
+=back
+
+=head1 CONFIGURATION VARIABLES
+
+The two configuration files F</etc/devscripts.conf> and
+F<~/.devscripts> are sourced by a shell in that order to set
+configuration variables. Command line options can be used to override
+configuration file settings. Environment variable settings are
+ignored for this purpose. The currently recognised variables are:
+
+=over 4
+
+=item B<LICENSECHECK_VERBOSE>
+
+If this is set to I<yes>, then it is the same as the B<--verbose> command
+line parameter being used. The default is I<no>.
+
+=item B<LICENSECHECK_PARSELINES>
+
+If this is set to a positive number then the specified number of lines
+at the start of each file will be read whilst attempting to determine
+the license(s) in use. This is equivalent to the B<--lines> command line
+option.
+
+=back
+
+=head1 LICENSE
+
+This code is copyright by Adam D. Barratt <I<adam@adam-barratt.org.uk>>,
+all rights reserved; based on a script of the same name from the KDE
+SDK, which is copyright by <I<dfaure@kde.org>>.
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the GNU
+General Public License, version 2 or later.
+
+=head1 AUTHOR
+
+Adam D. Barratt <adam@adam-barratt.org.uk>
+
+=cut
+
+use strict;
+use warnings;
+use Getopt::Long qw(:config gnu_getopt);
+use File::Basename;
+use Tie::File;
+use Fcntl 'O_RDONLY';
+
+sub fatal($);
+sub parse_copyright($);
+sub parselicense($);
+sub remove_comments($);
+
+my $progname = basename($0);
+
+# From dpkg-source
+my $default_ignore_regex = '
+# Ignore general backup files
+(?:^|/).*~$|
+# Ignore emacs recovery files
+(?:^|/)\.#.*$|
+# Ignore vi swap files
+(?:^|/)\..*\.swp$|
+# Ignore baz-style junk files or directories
+(?:^|/),,.*(?:$|/.*$)|
+# File-names that should be ignored (never directories)
+(?:^|/)(?:DEADJOE|\.cvsignore|\.arch-inventory|\.bzrignore|\.gitignore)$|
+# File or directory names that should be ignored
+(?:^|/)(?:CVS|RCS|\.deps|\{arch\}|\.arch-ids|\.svn|\.hg|_darcs|\.git|
+\.shelf|_MTN|\.bzr(?:\.backup|tags)?)(?:$|/.*$)
+';
+
+# Take out comments and newlines
+$default_ignore_regex =~ s/^#.*$//mg;
+$default_ignore_regex =~ s/\n//sg;
+
+my $default_check_regex = '\.(c(c|pp|xx)?|h(h|pp|xx)?|f(77|90)?|p(l|m)|xs|sh|php|py(|x)|rb|java|vala|el|sc(i|e)|cs|pas|inc|dtd|xsl|mod|m|tex|mli?)$';
+
+my $modified_conf_msg;
+
+my ($opt_verbose, $opt_lines, $opt_noconf) = ('', '', '');
+my $opt_ignore_regex = $default_ignore_regex;
+my $opt_check_regex = $default_check_regex;
+my $opt_recursive = 0;
+my $opt_copyright = 0;
+my $opt_machine = 0;
+my ($opt_help, $opt_version);
+my $def_lines = 60;
+
+# Read configuration files and then command line
+# This is boilerplate
+
+if (@ARGV and $ARGV[0] =~ /^--no-?conf$/) {
+ $modified_conf_msg = " (no configuration files read)";
+ shift;
+} else {
+ my @config_files = ('/etc/devscripts.conf', '~/.devscripts');
+ my %config_vars = (
+ 'LICENSECHECK_VERBOSE' => 'no',
+ 'LICENSECHECK_PARSELINES' => $def_lines,
+ );
+ my %config_default = %config_vars;
+
+ my $shell_cmd;
+ # Set defaults
+ foreach my $var (keys %config_vars) {
+ $shell_cmd .= qq[$var="$config_vars{$var}";\n];
+ }
+ $shell_cmd .= 'for file in ' . join(" ", @config_files) . "; do\n";
+ $shell_cmd .= '[ -f $file ] && . $file; done;' . "\n";
+ # Read back values
+ foreach my $var (keys %config_vars) { $shell_cmd .= "echo \$$var;\n" }
+ my $shell_out = `/bin/bash -c '$shell_cmd'`;
+ @config_vars{keys %config_vars} = split /\n/, $shell_out, -1;
+
+ # Check validity
+ $config_vars{'LICENSECHECK_VERBOSE'} =~ /^(yes|no)$/
+ or $config_vars{'LICENSECHECK_VERBOSE'} = 'no';
+ $config_vars{'LICENSECHECK_PARSELINES'} =~ /^[1-9][0-9]*$/
+ or $config_vars{'LICENSECHECK_PARSELINES'} = $def_lines;
+
+ foreach my $var (sort keys %config_vars) {
+ if ($config_vars{$var} ne $config_default{$var}) {
+ $modified_conf_msg .= " $var=$config_vars{$var}\n";
+ }
+ }
+ $modified_conf_msg ||= " (none)\n";
+ chomp $modified_conf_msg;
+
+ $opt_verbose = $config_vars{'LICENSECHECK_VERBOSE'} eq 'yes' ? 1 : 0;
+ $opt_lines = $config_vars{'LICENSECHECK_PARSELINES'};
+}
+
+GetOptions("help|h" => \$opt_help,
+ "version|v" => \$opt_version,
+ "verbose!" => \$opt_verbose,
+ "lines|l=i" => \$opt_lines,
+ "ignore|i=s" => \$opt_ignore_regex,
+ "recursive|r" => \$opt_recursive,
+ "check|c=s" => \$opt_check_regex,
+ "copyright" => \$opt_copyright,
+ "machine|m" => \$opt_machine,
+ "noconf" => \$opt_noconf,
+ "no-conf" => \$opt_noconf,
+ )
+ or die "Usage: $progname [options] filelist\nRun $progname --help for more details\n";
+
+$opt_lines = $def_lines if $opt_lines !~ /^[1-9][0-9]*$/;
+
+if ($opt_noconf) {
+ fatal "--no-conf is only acceptable as the first command-line option!";
+}
+if ($opt_help) { help(); exit 0; }
+if ($opt_version) { version(); exit 0; }
+
+die "Usage: $progname [options] filelist\nRun $progname --help for more details\n" unless @ARGV;
+
+$opt_lines = $def_lines if not defined $opt_lines;
+
+my @files = ();
+my @find_args = ();
+my $files_count = @ARGV;
+
+push @find_args, qw(-not ( -path */LayoutTests/* -prune ) );
+push @find_args, qw(-not ( -path */out/Debug/* -prune ) );
+push @find_args, qw(-not ( -path */out/Release/* -prune ) );
+push @find_args, qw(-not ( -path .git* -prune ) );
+push @find_args, qw(-not ( -path .svn* -prune ) );
+
+push @find_args, qw(-maxdepth 1) unless $opt_recursive;
+push @find_args, qw(-follow -type f -print);
+
+while (@ARGV) {
+ my $file = shift @ARGV;
+
+ if (-d $file) {
+ open FIND, '-|', 'find', $file, @find_args
+ or die "$progname: couldn't exec find: $!\n";
+
+ while (<FIND>) {
+ chomp;
+ next unless m%$opt_check_regex%;
+ # Skip empty files
+ next if (-z $_);
+ push @files, $_ unless m%$opt_ignore_regex%;
+ }
+ close FIND;
+ } else {
+ next unless ($files_count == 1) or $file =~ m%$opt_check_regex%;
+ push @files, $file unless $file =~ m%$opt_ignore_regex%;
+ }
+}
+
+while (@files) {
+ my $file = shift @files;
+ my $header = '';
+ my $copyright_match;
+ my $copyright = '';
+ my $license = '';
+ my %copyrights;
+
+ open (F, "<$file") or die "Unable to access $file\n";
+ while (<F>) {
+ last if ($. > $opt_lines);
+ $header .= $_;
+ }
+ close(F);
+
+ $copyright = join(" / ", values %copyrights);
+
+ print qq(----- $file header -----\n$header----- end header -----\n\n)
+ if $opt_verbose;
+
+ remove_comments($header);
+ $license = parselicense($header);
+
+ # If no license in header, check footer (slow, because read file backwards)
+ # Need for instance for Perl files, which often use the footer
+ if ($license eq "UNKNOWN") {
+ my $footer = '';
+ tie(my @file_lines, "Tie::File", $file, autochomp => 0, mode => O_RDONLY) or die("Unable to access $file\n");
+ # Avoid indexing error if header is entire file
+ if ($#file_lines >= $opt_lines) {
+ foreach (@file_lines[-$opt_lines .. -1]) {
+ $footer .= $_;
+ }
+ }
+ print qq(----- $file footer -----\n$header----- end footer -----\n\n)
+ if $opt_verbose;
+ remove_comments($footer);
+ $license = parselicense($footer);
+ }
+
+ if ($opt_machine) {
+ print "$file\t$license";
+ print "\t" . ($copyright or "*No copyright*") if $opt_copyright;
+ print "\n";
+ } else {
+ print "$file: ";
+ print "*No copyright* " unless $copyright;
+ print $license . "\n";
+ print " [Copyright: " . $copyright . "]\n"
+ if $copyright and $opt_copyright;
+ print "\n" if $opt_copyright;
+ }
+}
+
+sub remove_comments($) {
+ $_ = $_[0];
+ # Remove Fortran comments
+ s/^[cC] //gm;
+ # Remove .ASM comments
+ s#^;\*?##gm;
+ # Remove .S comments
+ s#^@ ##gm;
+ # Remove new lines
+ tr/\t\r\n/ /;
+ # Remove C / C++ comments
+ s#(\*/|/[/*])##g;
+ # Remove all characters not matching search
+ tr% A-Za-z.,@;0-9\(\)/-%%cd;
+ # Collapse multiple spaces into single space
+ tr/ //s;
+ $_[0] = $_;
+}
+
+sub parse_copyright($) {
+ my $copyright = '';
+ my $match;
+
+ my $copyright_indicator_regex = '
+ (?:copyright # The full word
+ |copr\. # Legally-valid abbreviation
+ |\x{00a9} # Unicode character COPYRIGHT SIGN
+ |\xc2\xa9 # Unicode copyright sign encoded in iso8859
+ |\(c\) # Legally-null representation of sign
+ )';
+ my $copyright_disindicator_regex = '
+ \b(?:info(?:rmation)? # Discussing copyright information
+ |notice # Discussing the notice
+ |and|or # Part of a sentence
+ )\b';
+
+ if (m%$copyright_indicator_regex(?::\s*|\s+)(\S.*)$%ix) {
+ $match = $1;
+
+ # Ignore lines matching "see foo for copyright information" etc.
+ if ($match !~ m%^\s*$copyright_disindicator_regex%ix) {
+ # De-cruft
+ $match =~ s/([,.])?\s*$//;
+ $match =~ s/$copyright_indicator_regex//igx;
+ $match =~ s/^\s+//;
+ $match =~ s/\s{2,}/ /g;
+ $match =~ s/\\@/@/g;
+ $copyright = $match;
+ }
+ }
+
+ return $copyright;
+}
+
+sub help {
+ print <<"EOF";
+Usage: $progname [options] filename [filename ...]
+Valid options are:
+ --help, -h Display this message
+ --version, -v Display version and copyright info
+ --no-conf, --noconf Don't read devscripts config files; must be
+ the first option given
+ --verbose Display the header of each file before its
+ license information
+ --lines, -l Specify how many lines of the file header
+ should be parsed for license information
+ (Default: $def_lines)
+ --check, -c Specify a pattern indicating which files should
+ be checked
+ (Default: '$default_check_regex')
+ --machine, -m Display in a machine readable way (good for awk)
+ --recursive, -r Add the contents of directories recursively
+ --copyright Also display the file's copyright
+ --ignore, -i Specify that files / directories matching the
+ regular expression should be ignored when
+ checking files
+ (Default: '$default_ignore_regex')
+
+Default settings modified by devscripts configuration files:
+$modified_conf_msg
+EOF
+}
+
+sub version {
+ print <<"EOF";
+This is $progname, from the Debian devscripts package, version ###VERSION###
+Copyright (C) 2007, 2008 by Adam D. Barratt <adam\@adam-barratt.org.uk>; based
+on a script of the same name from the KDE SDK by <dfaure\@kde.org>.
+
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the
+GNU General Public License, version 2, or (at your option) any
+later version.
+EOF
+}
+
+sub parselicense($) {
+ my ($licensetext) = @_;
+
+ my $gplver = "";
+ my $lgplver = "";
+ my $extrainfo = "";
+ my $license = "";
+
+ if ($licensetext =~ /version ([^, ]+?)[.,]? (?:\(?only\)?.? )?(?:of the GNU (Affero )?General Public License )?(as )?published by the Free Software Foundation/i or
+ $licensetext =~ /GNU (?:Affero )?General Public License (?:as )?published by the Free Software Foundation; version ([^, ]+?)[.,]? /i or
+ $licensetext =~ /GNU (?:Affero )?General Public License,? [Vv]ersion (\d+(?:\.\d+)?)[ \.]/) {
+ $gplver = " (v$1)";
+ } elsif ($licensetext =~ /either version ([^ ]+)(?: of the License)?, or \(at your option\) any later version/) {
+ $gplver = " (v$1 or later)";
+ }
+
+ if ($licensetext =~ /version ([^, ]+?)[.,]? (?:or later|or any later version) (?:of the GNU (?:Lesser |Library )General Public License )(as )?published by the Free Software Foundation/i or
+ $licensetext =~ /(?:GNU (?:Lesser |Library )|(?:Lesser|Library) GNU )General Public License (?:(?:as )?published by the Free Software Foundation;)?,? (?:either )?[Vv]ersion ([^, ]+?)(?: of the license)?[.,]? (?:or later|or (?:\(at your option\) )?any later version)/i or
+ $licensetext =~ /GNU (?:Lesser |Library )General Public License(?: \(LGPL\))?,? [Vv]ersion (\d+(?:\.\d+)?)[ \.]/) {
+ $lgplver = " (v$1 or later)";
+ }
+
+ if ($licensetext =~ /permission (?:is (also granted|given))? to link (the code of )?this program with (any edition of )?(Qt|the Qt library)/i) {
+ $extrainfo = " (with Qt exception)$extrainfo"
+ }
+
+ if ($licensetext =~ /(All changes made in this file will be lost|DO NOT (EDIT|delete this file)|Generated (automatically|by|from)|generated.*file)/i) {
+ $license = "GENERATED FILE";
+ }
+
+ if ($licensetext =~ /is (free software.? you can redistribute it and\/or modify it|licensed) under the terms of (version [^ ]+ of )?the (GNU (Library |Lesser )General Public License|LGPL)/i or
+ $licensetext =~ /(is distributed|may be used|can redistribute).*terms.*(LGPL|(Lesser|Library) GNU General Public License)/) {
+ if ($lgplver) {
+ $license = "LGPL$lgplver$extrainfo $license";
+ } else {
+ $license = "LGPL (unversioned/unknown version) $license";
+ }
+ }
+
+ if ($licensetext =~ /is free software.? you (can|may) redistribute it and\/or modify it under the terms of (?:version [^ ]+ (?:\(?only\)? )?of )?the GNU General Public License/i) {
+ $license = "GPL$gplver$extrainfo $license";
+ } elsif ($licensetext =~ /is distributed under the terms of the GNU General Public License,/
+ and $gplver) {
+ $license = "GPL$gplver$extrainfo $license";
+ } elsif ($licensetext =~ /is distributed.*terms.*[^L]GPL/) {
+ if ($gplver) {
+ $license = "GPL$gplver$extrainfo $license";
+ } else {
+ $license = "GPL (unversioned/unknown version) $license";
+ }
+ }
+
+ if ($licensetext =~ /This file is part of the .*Qt GUI Toolkit. This file may be distributed under the terms of the Q Public License as defined/) {
+ $license = "QPL (part of Qt) $license";
+ } elsif ($licensetext =~ /may be distributed under the terms of the Q Public License as defined/) {
+ $license = "QPL $license";
+ }
+
+ if ($licensetext =~ /opensource\.org\/licenses\/mit/) {
+ $license = "MIT/X11 (BSD like) $license";
+ } elsif ($licensetext =~ /Permission is hereby granted, free of charge, to any person obtaining a copy of this software and(\/or)? associated documentation files \(the (Software|Materials)\), to deal in the (Software|Materials)/) {
+ $license = "MIT/X11 (BSD like) $license";
+ } elsif ($licensetext =~ /Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose/) {
+ $license = "MIT/X11 (BSD like) $license";
+ } elsif ($licensetext =~ /Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee/) {
+ $license = "MIT/X11 (BSD like) $license";
+ } elsif ($licensetext =~ /MIT .* License/) {
+ $license = "MIT/X11 (BSD like) $license";
+ }
+
+ if ($licensetext =~ /This file is part of the Independent JPEG Group(')?s software.*For conditions of distribution and use, see the accompanying README file/i) {
+ $license = "Independent JPEG Group License $license";
+ }
+
+ if ($licensetext =~ /the University of Illinois Open Source License/){
+ $license = "University of Illinois/NCSA Open Source License (BSD like) $license";
+ }
+
+ if ($licensetext =~ /Permission to use, copy, modify, and(\/or)? distribute this software (and its documentation )?for any purpose (with or )?without fee is hereby granted, provided.*(copyright|entire) notice.*all copies/i) {
+ $license = "ISC $license";
+ }
+
+ if ($licensetext =~ /THIS SOFTWARE IS PROVIDED .*AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY/ ||
+ $licensetext =~ /THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- ITY/) {
+ if ($licensetext =~ /All advertising materials mentioning features or use of this software must display the following/) {
+ $license = "BSD (4 clause) $license";
+ } elsif ($licensetext =~ /be used to endorse or promote products derived from this software/) {
+ $license = "BSD (3 clause) $license";
+ } elsif ($licensetext =~ /Redistributions of source code must retain the above copyright notice/) {
+ $license = "BSD (2 clause) $license";
+ } else {
+ $license = "BSD $license";
+ }
+ } elsif ($licensetext =~ /Use of this source code is governed by a BSD-style license/) {
+ $license = "BSD-like $license";
+ } elsif ($licensetext =~ /BSD terms apply/) {
+ $license = "BSD-like $license";
+ } elsif ($licensetext =~ /subject to the BSD License/) {
+ # TODO(sbc): remove this case once we fix: http://crbug.com/177268
+ $license = "BSD-like $license";
+ } elsif ($licensetext =~ /license BSD/) {
+ $license = "BSD-like $license";
+ } elsif ($licensetext =~ /GOVERNED BY A BSD-STYLE SOURCE LICENSE/) {
+ $license = "BSD-like $license";
+ } elsif ($licensetext =~ /BSD 3-Clause license/) {
+ $license = "BSD (3 clause) $license";
+ }
+
+ if ($licensetext =~ /Mozilla Public License( Version|, v.) ([^ ]+[^., ]),?/) {
+ $license = "MPL (v$2) $license";
+ }
+
+ if ($licensetext =~ /Released under the terms of the Artistic License ([^ ]+)/) {
+ $license = "Artistic (v$1) $license";
+ }
+
+ if ($licensetext =~ /is free software under the Artistic [Ll]icense/) {
+ $license = "Artistic $license";
+ }
+
+ if ($licensetext =~ /This (program|library) is free software; you can redistribute it and\/or modify it under the same terms as Perl itself/) {
+ $license = "Perl $license";
+ }
+
+ if ($licensetext =~ /under the terms of the Apache ([^ ]+) License OR version 2 of the GNU/) {
+ $license = "Apache (v$1) GPL (v2) $license";
+ } elsif ($licensetext =~ /under the Apache License, Version ([^ ]+)/) {
+ $license = "Apache (v$1) $license";
+ }
+
+ if ($licensetext =~ /(THE BEER-WARE LICENSE)/i) {
+ $license = "Beerware $license";
+ }
+
+ if ($licensetext =~ /This source file is subject to version ([^ ]+) of the PHP license/) {
+ $license = "PHP (v$1) $license";
+ }
+
+ if ($licensetext =~ /under the terms of the CeCILL /) {
+ $license = "CeCILL $license";
+ }
+
+ if ($licensetext =~ /under the terms of the CeCILL-([^ ]+) /) {
+ $license = "CeCILL-$1 $license";
+ }
+
+ if ($licensetext =~ /under the SGI Free Software (B License|License B)/) {
+ $license = "SGI Free Software License B $license";
+ }
+
+ if ($licensetext =~ /(in|into) the public domain/i) {
+ $license = "Public domain $license";
+ }
+
+ if ($licensetext =~ /terms of the Common Development and Distribution License(, Version ([^(]+))? \(the License\)/) {
+ $license = "CDDL " . ($1 ? "(v$2) " : '') . $license;
+ }
+
+ if ($licensetext =~ /Microsoft Permissive License \(Ms-PL\)/) {
+ $license = "Ms-PL $license";
+ }
+
+ if ($licensetext =~ /as defined in and that are subject to the Apple Public Source License([ ,-]+Version ([^ ]+)?(\.))/) {
+ $license = "APSL " . ($1 ? "(v$2) " : '') . $license;
+ } elsif ($licensetext =~ /provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software/) {
+ # https://fedoraproject.org/wiki/Licensing/Apple_MIT_License
+ $license = "Apple MIT $license";
+ }
+
+ if ($licensetext =~ /Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license \([\"]?the Software[\"]?\)/ or
+ $licensetext =~ /Boost Software License([ ,-]+Version ([^ ]+)?(\.))/i) {
+ $license = "BSL " . ($1 ? "(v$2) " : '') . $license;
+ }
+
+ if ($licensetext =~ /PYTHON SOFTWARE FOUNDATION LICENSE (VERSION ([^ ]+))/i) {
+ $license = "PSF " . ($1 ? "(v$2) " : '') . $license;
+ }
+
+ if ($licensetext =~ /The origin of this software must not be misrepresented.*Altered source versions must be plainly marked as such.*This notice may not be removed or altered from any source distribution/ or
+ $licensetext =~ /see copyright notice in zlib\.h/) {
+ $license = "zlib/libpng $license";
+ } elsif ($licensetext =~ /This code is released under the libpng license/) {
+ $license = "libpng $license";
+ }
+
+ if ($licensetext =~ /under MIT license/) {
+ $license = "MIT/X11 (BSD like) $license";
+ }
+
+ if ($licensetext =~ /License MIT(-| )License/) {
+ $license = "MIT/X11 (BSD like) $license";
+ }
+
+ if ($licensetext =~ /As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice/) {
+ $license = $license . "with Bison parser exception";
+ }
+
+ if ($licensetext =~ /As a special exception to the GNU General Public License, if you distribute this file as part of a program or library that is built using GNU Libtool, you may include this file under the same distribution terms that you use for the rest of that program/) {
+ $license = $license . "with libtool exception";
+ }
+
+ if ($licensetext =~ /These materials are protected by copyright laws and contain material proprietary to the Khronos Group, Inc\. You may use these materials for implementing Khronos specifications, without altering or removing any trademark, copyright or other notice from the specification/) {
+ $license = $license . "Khronos Group";
+ }
+
+ if ($licensetext =~ /This file is part of the FreeType project, and may only be used(,)? modified(,)? and distributed under the terms of the FreeType project license, LICENSE\.TXT\. By continuing to use, modify, or distribute this file you indicate that you have read the license and understand and accept it fully/) {
+ $license = "FreeType (BSD like) $license";
+ }
+ if ($licensetext =~ /This software, and all works of authorship, whether in source or object code form as indicated by the copyright notice.*is made available, and may only be used, modified, and distributed under the FreeType Project License, LICENSE\.TXT\. Additionally, subject to the terms and conditions of the FreeType Project License, each contributor to the Work hereby grants to any individual or legal entity exercising permissions granted by the FreeType Project License and this section.*a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable.*patent license to make/) {
+ $license = "FreeType (BSD like) with patent clause $license";
+ }
+
+ if ($licensetext =~ /Anti-Grain Geometry.*Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided as is without express or impl/) {
+ $license = "Anti-Grain Geometry $license";
+ }
+
+ if ($licensetext =~ /Developed at SunSoft, a Sun Microsystems, Inc\. business\. Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved\./) {
+ $license = "SunSoft (BSD like) $license";
+ }
+
+ $license = "UNKNOWN" unless $license;
+
+ # Remove trailing spaces.
+ $license =~ s/\s+$//;
+
+ return $license;
+}
+
+sub fatal($) {
+ my ($pack,$file,$line);
+ ($pack,$file,$line) = caller();
+ (my $msg = "$progname: fatal error at line $line:\n@_\n") =~ tr/\0//d;
+ $msg =~ s/\n\n$/\n/;
+ die $msg;
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/devscripts/licensecheck.pl.vanilla b/chromium/third_party/catapult/tracing/third_party/devscripts/licensecheck.pl.vanilla
new file mode 100644
index 00000000000..d98b974adda
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/devscripts/licensecheck.pl.vanilla
@@ -0,0 +1,577 @@
+#!/usr/bin/perl -w
+# This script was originally based on the script of the same name from
+# the KDE SDK (by dfaure@kde.org)
+#
+# This version is
+# Copyright (C) 2007, 2008 Adam D. Barratt
+# Copyright (C) 2012 Francesco Poli
+#
+# This program 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+=head1 NAME
+
+licensecheck - simple license checker for source files
+
+=head1 SYNOPSIS
+
+B<licensecheck> B<--help>|B<--version>
+
+B<licensecheck> [B<--no-conf>] [B<--verbose>] [B<--copyright>]
+[B<-l>|B<--lines=>I<N>] [B<-i>|B<--ignore=>I<regex>] [B<-c>|B<--check=>I<regex>]
+[B<-m>|B<--machine>] [B<-r>|B<--recursive>]
+I<list of files and directories to check>
+
+=head1 DESCRIPTION
+
+B<licensecheck> attempts to determine the license that applies to each file
+passed to it, by searching the start of the file for text belonging to
+various licenses.
+
+If any of the arguments passed are directories, B<licensecheck> will add
+the files contained within to the list of files to process.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--verbose>, B<--no-verbose>
+
+Specify whether to output the text being processed from each file before
+the corresponding license information.
+
+Default is to be quiet.
+
+=item B<-l=>I<N>, B<--lines=>I<N>
+
+Specify the number of lines of each file's header which should be parsed
+for license information. (Default is 60).
+
+=item B<-i=>I<regex>, B<--ignore=>I<regex>
+
+When processing the list of files and directories, the regular
+expression specified by this option will be used to indicate those which
+should not be considered (e.g. backup files, VCS metadata).
+
+=item B<-r>, B<--recursive>
+
+Specify that the contents of directories should be added
+recursively.
+
+=item B<-c=>I<regex>, B<--check=>I<regex>
+
+Specify a pattern against which filenames will be matched in order to
+decide which files to check the license of.
+
+The default includes common source files.
+
+=item B<--copyright>
+
+Also display copyright text found within the file
+
+=item B<-m>, B<--machine>
+
+Display the information in a machine readable way, i.e. in the form
+<file><tab><license>[<tab><copyright>] so that it can be easily sorted
+and/or filtered, e.g. with the B<awk> and B<sort> commands.
+Note that using the B<--verbose> option will kill the readability.
+
+=item B<--no-conf>, B<--noconf>
+
+Do not read any configuration files. This can only be used as the first
+option given on the command-line.
+
+=back
+
+=head1 CONFIGURATION VARIABLES
+
+The two configuration files F</etc/devscripts.conf> and
+F<~/.devscripts> are sourced by a shell in that order to set
+configuration variables. Command line options can be used to override
+configuration file settings. Environment variable settings are
+ignored for this purpose. The currently recognised variables are:
+
+=over 4
+
+=item B<LICENSECHECK_VERBOSE>
+
+If this is set to I<yes>, then it is the same as the B<--verbose> command
+line parameter being used. The default is I<no>.
+
+=item B<LICENSECHECK_PARSELINES>
+
+If this is set to a positive number then the specified number of lines
+at the start of each file will be read whilst attempting to determine
+the license(s) in use. This is equivalent to the B<--lines> command line
+option.
+
+=back
+
+=head1 LICENSE
+
+This code is copyright by Adam D. Barratt <I<adam@adam-barratt.org.uk>>,
+all rights reserved; based on a script of the same name from the KDE
+SDK, which is copyright by <I<dfaure@kde.org>>.
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the GNU
+General Public License, version 2 or later.
+
+=head1 AUTHOR
+
+Adam D. Barratt <adam@adam-barratt.org.uk>
+
+=cut
+
+use strict;
+use warnings;
+use Getopt::Long qw(:config gnu_getopt);
+use File::Basename;
+
+sub fatal($);
+sub parse_copyright($);
+sub parselicense($);
+
+my $progname = basename($0);
+
+# From dpkg-source
+my $default_ignore_regex = '
+# Ignore general backup files
+(?:^|/).*~$|
+# Ignore emacs recovery files
+(?:^|/)\.#.*$|
+# Ignore vi swap files
+(?:^|/)\..*\.swp$|
+# Ignore baz-style junk files or directories
+(?:^|/),,.*(?:$|/.*$)|
+# File-names that should be ignored (never directories)
+(?:^|/)(?:DEADJOE|\.cvsignore|\.arch-inventory|\.bzrignore|\.gitignore)$|
+# File or directory names that should be ignored
+(?:^|/)(?:CVS|RCS|\.deps|\{arch\}|\.arch-ids|\.svn|\.hg|_darcs|\.git|
+\.shelf|_MTN|\.bzr(?:\.backup|tags)?)(?:$|/.*$)
+';
+
+# Take out comments and newlines
+$default_ignore_regex =~ s/^#.*$//mg;
+$default_ignore_regex =~ s/\n//sg;
+
+my $default_check_regex = '\.(c(c|pp|xx)?|h(h|pp|xx)?|f(77|90)?|p(l|m)|xs|sh|php|py(|x)|rb|java|vala|el|sc(i|e)|cs|pas|inc|dtd|xsl|mod|m|tex|mli?)$';
+
+my $modified_conf_msg;
+
+my ($opt_verbose, $opt_lines, $opt_noconf, $opt_ignore_regex, $opt_check_regex)
+ = ('', '', '', '', '');
+my $opt_recursive = 0;
+my $opt_copyright = 0;
+my $opt_machine = 0;
+my ($opt_help, $opt_version);
+my $def_lines = 60;
+
+# Read configuration files and then command line
+# This is boilerplate
+
+if (@ARGV and $ARGV[0] =~ /^--no-?conf$/) {
+ $modified_conf_msg = " (no configuration files read)";
+ shift;
+} else {
+ my @config_files = ('/etc/devscripts.conf', '~/.devscripts');
+ my %config_vars = (
+ 'LICENSECHECK_VERBOSE' => 'no',
+ 'LICENSECHECK_PARSELINES' => $def_lines,
+ );
+ my %config_default = %config_vars;
+
+ my $shell_cmd;
+ # Set defaults
+ foreach my $var (keys %config_vars) {
+ $shell_cmd .= qq[$var="$config_vars{$var}";\n];
+ }
+ $shell_cmd .= 'for file in ' . join(" ", @config_files) . "; do\n";
+ $shell_cmd .= '[ -f $file ] && . $file; done;' . "\n";
+ # Read back values
+ foreach my $var (keys %config_vars) { $shell_cmd .= "echo \$$var;\n" }
+ my $shell_out = `/bin/bash -c '$shell_cmd'`;
+ @config_vars{keys %config_vars} = split /\n/, $shell_out, -1;
+
+ # Check validity
+ $config_vars{'LICENSECHECK_VERBOSE'} =~ /^(yes|no)$/
+ or $config_vars{'LICENSECHECK_VERBOSE'} = 'no';
+ $config_vars{'LICENSECHECK_PARSELINES'} =~ /^[1-9][0-9]*$/
+ or $config_vars{'LICENSECHECK_PARSELINES'} = $def_lines;
+
+ foreach my $var (sort keys %config_vars) {
+ if ($config_vars{$var} ne $config_default{$var}) {
+ $modified_conf_msg .= " $var=$config_vars{$var}\n";
+ }
+ }
+ $modified_conf_msg ||= " (none)\n";
+ chomp $modified_conf_msg;
+
+ $opt_verbose = $config_vars{'LICENSECHECK_VERBOSE'} eq 'yes' ? 1 : 0;
+ $opt_lines = $config_vars{'LICENSECHECK_PARSELINES'};
+}
+
+GetOptions("help|h" => \$opt_help,
+ "version|v" => \$opt_version,
+ "verbose!" => \$opt_verbose,
+ "lines|l=i" => \$opt_lines,
+ "ignore|i=s" => \$opt_ignore_regex,
+ "recursive|r" => \$opt_recursive,
+ "check|c=s" => \$opt_check_regex,
+ "copyright" => \$opt_copyright,
+ "machine|m" => \$opt_machine,
+ "noconf" => \$opt_noconf,
+ "no-conf" => \$opt_noconf,
+ )
+ or die "Usage: $progname [options] filelist\nRun $progname --help for more details\n";
+
+$opt_lines = $def_lines if $opt_lines !~ /^[1-9][0-9]*$/;
+$opt_ignore_regex = $default_ignore_regex if ! length $opt_ignore_regex;
+$opt_check_regex = $default_check_regex if ! length $opt_check_regex;
+
+if ($opt_noconf) {
+ fatal "--no-conf is only acceptable as the first command-line option!";
+}
+if ($opt_help) { help(); exit 0; }
+if ($opt_version) { version(); exit 0; }
+
+die "Usage: $progname [options] filelist\nRun $progname --help for more details\n" unless @ARGV;
+
+$opt_lines = $def_lines if not defined $opt_lines;
+
+my @files = ();
+my @find_args = ();
+my $files_count = @ARGV;
+
+push @find_args, qw(-maxdepth 1) unless $opt_recursive;
+push @find_args, qw(-follow -type f -print);
+
+while (@ARGV) {
+ my $file = shift @ARGV;
+
+ if (-d $file) {
+ open FIND, '-|', 'find', $file, @find_args
+ or die "$progname: couldn't exec find: $!\n";
+
+ while (<FIND>) {
+ chomp;
+ next unless m%$opt_check_regex%;
+ # Skip empty files
+ next if (-z $_);
+ push @files, $_ unless m%$opt_ignore_regex%;
+ }
+ close FIND;
+ } else {
+ next unless ($files_count == 1) or $file =~ m%$opt_check_regex%;
+ push @files, $file unless $file =~ m%$opt_ignore_regex%;
+ }
+}
+
+while (@files) {
+ my $file = shift @files;
+ my $content = '';
+ my $copyright_match;
+ my $copyright = '';
+ my $license = '';
+ my %copyrights;
+
+ open (F, "<$file") or die "Unable to access $file\n";
+ while (<F>) {
+ last if ($. > $opt_lines);
+ $content .= $_;
+ $copyright_match = parse_copyright($_);
+ if ($copyright_match) {
+ $copyrights{lc("$copyright_match")} = "$copyright_match";
+ }
+ }
+ close(F);
+
+ $copyright = join(" / ", values %copyrights);
+
+ print qq(----- $file header -----\n$content----- end header -----\n\n)
+ if $opt_verbose;
+
+ # Remove Fortran comments
+ $content =~ s/^[cC] //gm;
+ $content =~ tr/\t\r\n/ /;
+ # Remove C / C++ comments
+ $content =~ s#(\*/|/[/*])##g;
+ $content =~ tr% A-Za-z.,@;0-9\(\)/-%%cd;
+ $content =~ tr/ //s;
+
+ $license = parselicense($content);
+ if ($opt_machine) {
+ print "$file\t$license";
+ print "\t" . ($copyright or "*No copyright*") if $opt_copyright;
+ print "\n";
+ } else {
+ print "$file: ";
+ print "*No copyright* " unless $copyright;
+ print $license . "\n";
+ print " [Copyright: " . $copyright . "]\n"
+ if $copyright and $opt_copyright;
+ print "\n" if $opt_copyright;
+ }
+}
+
+sub parse_copyright($) {
+ my $copyright = '';
+ my $match;
+
+ my $copyright_indicator_regex = '
+ (?:copyright # The full word
+ |copr\. # Legally-valid abbreviation
+ |\x{00a9} # Unicode character COPYRIGHT SIGN
+ |\xc2\xa9 # Unicode copyright sign encoded in iso8859
+ |\(c\) # Legally-null representation of sign
+ )';
+ my $copyright_disindicator_regex = '
+ \b(?:info(?:rmation)? # Discussing copyright information
+ |notice # Discussing the notice
+ |and|or # Part of a sentence
+ )\b';
+
+ if (m%$copyright_indicator_regex(?::\s*|\s+)(\S.*)$%ix) {
+ $match = $1;
+
+ # Ignore lines matching "see foo for copyright information" etc.
+ if ($match !~ m%^\s*$copyright_disindicator_regex%ix) {
+ # De-cruft
+ $match =~ s/([,.])?\s*$//;
+ $match =~ s/$copyright_indicator_regex//igx;
+ $match =~ s/^\s+//;
+ $match =~ s/\s{2,}/ /g;
+ $match =~ s/\\@/@/g;
+ $copyright = $match;
+ }
+ }
+
+ return $copyright;
+}
+
+sub help {
+ print <<"EOF";
+Usage: $progname [options] filename [filename ...]
+Valid options are:
+ --help, -h Display this message
+ --version, -v Display version and copyright info
+ --no-conf, --noconf Don't read devscripts config files; must be
+ the first option given
+ --verbose Display the header of each file before its
+ license information
+ --lines, -l Specify how many lines of the file header
+ should be parsed for license information
+ (Default: $def_lines)
+ --check, -c Specify a pattern indicating which files should
+ be checked
+ (Default: '$default_check_regex')
+ --machine, -m Display in a machine readable way (good for awk)
+ --recursive, -r Add the contents of directories recursively
+ --copyright Also display the file's copyright
+ --ignore, -i Specify that files / directories matching the
+ regular expression should be ignored when
+ checking files
+ (Default: '$default_ignore_regex')
+
+Default settings modified by devscripts configuration files:
+$modified_conf_msg
+EOF
+}
+
+sub version {
+ print <<"EOF";
+This is $progname, from the Debian devscripts package, version ###VERSION###
+Copyright (C) 2007, 2008 by Adam D. Barratt <adam\@adam-barratt.org.uk>; based
+on a script of the same name from the KDE SDK by <dfaure\@kde.org>.
+
+This program comes with ABSOLUTELY NO WARRANTY.
+You are free to redistribute this code under the terms of the
+GNU General Public License, version 2, or (at your option) any
+later version.
+EOF
+}
+
+sub parselicense($) {
+ my ($licensetext) = @_;
+
+ my $gplver = "";
+ my $extrainfo = "";
+ my $license = "";
+
+ if ($licensetext =~ /version ([^, ]+?)[.,]? (?:\(?only\)?.? )?(?:of the GNU (Affero )?(Lesser |Library )?General Public License )?(as )?published by the Free Software Foundation/i or
+ $licensetext =~ /GNU (?:Affero )?(?:Lesser |Library )?General Public License (?:as )?published by the Free Software Foundation; version ([^, ]+?)[.,]? /i) {
+
+ $gplver = " (v$1)";
+ } elsif ($licensetext =~ /GNU (?:Affero )?(?:Lesser |Library )?General Public License, version (\d+(?:\.\d+)?)[ \.]/) {
+ $gplver = " (v$1)";
+ } elsif ($licensetext =~ /either version ([^ ]+)(?: of the License)?, or \(at your option\) any later version/) {
+ $gplver = " (v$1 or later)";
+ }
+
+ if ($licensetext =~ /(?:675 Mass Ave|59 Temple Place|51 Franklin Steet|02139|02111-1307)/i) {
+ $extrainfo = " (with incorrect FSF address)$extrainfo";
+ }
+
+ if ($licensetext =~ /permission (?:is (also granted|given))? to link (the code of )?this program with (any edition of )?(Qt|the Qt library)/i) {
+ $extrainfo = " (with Qt exception)$extrainfo"
+ }
+
+ if ($licensetext =~ /(All changes made in this file will be lost|DO NOT (EDIT|delete this file)|Generated (automatically|by|from)|generated.*file)/i) {
+ $license = "GENERATED FILE";
+ }
+
+ if ($licensetext =~ /is (free software.? you can redistribute it and\/or modify it|licensed) under the terms of (version [^ ]+ of )?the (GNU (Library |Lesser )General Public License|LGPL)/i) {
+ $license = "LGPL$gplver$extrainfo $license";
+ }
+
+ if ($licensetext =~ /is free software.? you can redistribute it and\/or modify it under the terms of the (GNU Affero General Public License|AGPL)/i) {
+ $license = "AGPL$gplver$extrainfo $license";
+ }
+
+ if ($licensetext =~ /is free software.? you (can|may) redistribute it and\/or modify it under the terms of (?:version [^ ]+ (?:\(?only\)? )?of )?the GNU General Public License/i) {
+ $license = "GPL$gplver$extrainfo $license";
+ }
+
+ if ($licensetext =~ /is distributed under the terms of the GNU General Public License,/
+ and length $gplver) {
+ $license = "GPL$gplver$extrainfo $license";
+ }
+
+ if ($licensetext =~ /is distributed.*terms.*GPL/) {
+ $license = "GPL (unversioned/unknown version) $license";
+ }
+
+ if ($licensetext =~ /This file is part of the .*Qt GUI Toolkit. This file may be distributed under the terms of the Q Public License as defined/) {
+ $license = "QPL (part of Qt) $license";
+ } elsif ($licensetext =~ /may be distributed under the terms of the Q Public License as defined/) {
+ $license = "QPL $license";
+ }
+
+ if ($licensetext =~ /opensource\.org\/licenses\/mit-license\.php/) {
+ $license = "MIT/X11 (BSD like) $license";
+ } elsif ($licensetext =~ /Permission is hereby granted, free of charge, to any person obtaining a copy of this software and(\/or)? associated documentation files \(the (Software|Materials)\), to deal in the (Software|Materials)/) {
+ $license = "MIT/X11 (BSD like) $license";
+ } elsif ($licensetext =~ /Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose/) {
+ $license = "MIT/X11 (BSD like) $license";
+ }
+
+ if ($licensetext =~ /Permission to use, copy, modify, and(\/or)? distribute this software for any purpose with or without fee is hereby granted, provided.*copyright notice.*permission notice.*all copies/) {
+ $license = "ISC $license";
+ }
+
+ if ($licensetext =~ /THIS SOFTWARE IS PROVIDED .*AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY/) {
+ if ($licensetext =~ /All advertising materials mentioning features or use of this software must display the following acknowledge?ment.*This product includes software developed by/i) {
+ $license = "BSD (4 clause) $license";
+ } elsif ($licensetext =~ /(The name .*? may not|Neither the names? .*? nor the names of (its|their) contributors may) be used to endorse or promote products derived from this software/i) {
+ $license = "BSD (3 clause) $license";
+ } elsif ($licensetext =~ /Redistributions of source code must retain the above copyright notice/i) {
+ $license = "BSD (2 clause) $license";
+ } else {
+ $license = "BSD $license";
+ }
+ }
+
+ if ($licensetext =~ /Mozilla Public License Version ([^ ]+)/) {
+ $license = "MPL (v$1) $license";
+ }
+
+ if ($licensetext =~ /Released under the terms of the Artistic License ([^ ]+)/) {
+ $license = "Artistic (v$1) $license";
+ }
+
+ if ($licensetext =~ /is free software under the Artistic [Ll]icense/) {
+ $license = "Artistic $license";
+ }
+
+ if ($licensetext =~ /This program is free software; you can redistribute it and\/or modify it under the same terms as Perl itself/) {
+ $license = "Perl $license";
+ }
+
+ if ($licensetext =~ /under the Apache License, Version ([^ ]+)/) {
+ $license = "Apache (v$1) $license";
+ }
+
+ if ($licensetext =~ /(THE BEER-WARE LICENSE)/i) {
+ $license = "Beerware $license";
+ }
+
+ if ($licensetext =~ /This source file is subject to version ([^ ]+) of the PHP license/) {
+ $license = "PHP (v$1) $license";
+ }
+
+ if ($licensetext =~ /under the terms of the CeCILL /) {
+ $license = "CeCILL $license";
+ }
+
+ if ($licensetext =~ /under the terms of the CeCILL-([^ ]+) /) {
+ $license = "CeCILL-$1 $license";
+ }
+
+ if ($licensetext =~ /under the SGI Free Software License B/) {
+ $license = "SGI Free Software License B $license";
+ }
+
+ if ($licensetext =~ /is in the public domain/i) {
+ $license = "Public domain $license";
+ }
+
+ if ($licensetext =~ /terms of the Common Development and Distribution License(, Version ([^(]+))? \(the License\)/) {
+ $license = "CDDL " . ($1 ? "(v$2) " : '') . $license;
+ }
+
+ if ($licensetext =~ /Microsoft Permissive License \(Ms-PL\)/) {
+ $license = "Ms-PL $license";
+ }
+
+ if ($licensetext =~ /Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license \(the \"Software\"\)/ or
+ $licensetext =~ /Boost Software License([ ,-]+Version ([^ ]+)?(\.))/i) {
+ $license = "BSL " . ($1 ? "(v$2) " : '') . $license;
+ }
+
+ if ($licensetext =~ /PYTHON SOFTWARE FOUNDATION LICENSE (VERSION ([^ ]+))/i) {
+ $license = "PSF " . ($1 ? "(v$2) " : '') . $license;
+ }
+
+ if ($licensetext =~ /The origin of this software must not be misrepresented.*Altered source versions must be plainly marked as such.*This notice may not be removed or altered from any source distribution/ or
+ $licensetext =~ /see copyright notice in zlib\.h/) {
+ $license = "zlib/libpng $license";
+ } elsif ($licensetext =~ /This code is released under the libpng license/) {
+ $license = "libpng $license";
+ }
+
+ if ($licensetext =~ /Do What The Fuck You Want To Public License, Version ([^, ]+)/i) {
+ $license = "WTFPL (v$1) $license";
+ }
+
+ if ($licensetext =~ /Do what The Fuck You Want To Public License/i) {
+ $license = "WTFPL $license";
+ }
+
+ if ($licensetext =~ /(License WTFPL|Under (the|a) WTFPL)/i) {
+ $license = "WTFPL $license";
+ }
+
+ $license = "UNKNOWN" if (!length($license));
+
+ # Remove trailing spaces.
+ $license =~ s/\s+$//;
+
+ return $license;
+}
+
+sub fatal($) {
+ my ($pack,$file,$line);
+ ($pack,$file,$line) = caller();
+ (my $msg = "$progname: fatal error at line $line:\n@_\n") =~ tr/\0//d;
+ $msg =~ s/\n\n$/\n/;
+ die $msg;
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/BUILDING.md b/chromium/third_party/catapult/tracing/third_party/gl-matrix/BUILDING.md
new file mode 100644
index 00000000000..9170ab3d5b1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/BUILDING.md
@@ -0,0 +1,7 @@
+Building for the browser
+========================
+
+
+To build `gl-matrix.js` and `gl-matrix-min.js` for use in the browser run the following command:
+
+ webpack && webpack --config webpack.config.min.js \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/LICENSE.md b/chromium/third_party/catapult/tracing/third_party/gl-matrix/LICENSE.md
new file mode 100644
index 00000000000..79698edab2c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/LICENSE.md
@@ -0,0 +1,19 @@
+Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/README.chromium b/chromium/third_party/catapult/tracing/third_party/gl-matrix/README.chromium
new file mode 100644
index 00000000000..4e5c3d49ea1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/README.chromium
@@ -0,0 +1,15 @@
+Name: gl-matrix
+Short Name: gl-matrix
+URL: https://github.com/toji/gl-matrix
+Version: 0
+Revision: 8fc4869031e4ab1daf771e5206c2578e044cf495
+Date: Tue Feb 12 14:21:14 2013 -0800
+License: BSD
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+Matrix math in javascript
+
+Local Modifications:
+None.
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/README.md b/chromium/third_party/catapult/tracing/third_party/gl-matrix/README.md
new file mode 100644
index 00000000000..ad66cb07f84
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/README.md
@@ -0,0 +1,22 @@
+glMatrix
+=======================
+
+Javascript has evolved into a language capable of handling realtime 3D graphics,
+via WebGL, and computationally intensive tasks such as physics simulations.
+These types of applications demand high performance vector and matrix math,
+which is something that Javascript doesn't provide by default.
+glMatrix to the rescue!
+
+glMatrix is designed to perform vector and matrix operations stupidly fast! By
+hand-tuning each function for maximum performance and encouraging efficient
+usage patterns through API conventions, glMatrix will help you get the most out
+of your browsers Javascript engine.
+
+Learn More
+----------------------
+For documentation, news, tutorials, and more visit the [glMatrix Homepage](http://glmatrix.net/)
+
+Contributing
+----------------------
+Contributions are welcome! Please make pull requests agains the `dev` branch,
+and please provide unit tests for new functionality. (See TESTING.md for details)
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/TESTING.md b/chromium/third_party/catapult/tracing/third_party/gl-matrix/TESTING.md
new file mode 100644
index 00000000000..affd5b27b41
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/TESTING.md
@@ -0,0 +1,12 @@
+Running the test suite
+=======================
+
+
+The unit tests are built upon the following tools:
+
+* Jasmine -- the underlying test suite which executes the test and reports feedback
+* node.js -- used for testing at the command line, via the `jasmine-node` package
+
+To run the unit tests use `jasmine-node`:
+
+ jasmine-node spec \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/VERSION b/chromium/third_party/catapult/tracing/third_party/gl-matrix/VERSION
new file mode 100644
index 00000000000..cc6612c36e0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/VERSION
@@ -0,0 +1 @@
+2.3.0 \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/bower.json b/chromium/third_party/catapult/tracing/third_party/gl-matrix/bower.json
new file mode 100644
index 00000000000..7e52c486673
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/bower.json
@@ -0,0 +1,27 @@
+{
+ "name": "gl-matrix",
+ "homepage": "http://glmatrix.net",
+ "authors": [
+ "Brandon Jones <tojiro@gmail.com>",
+ "Colin MacKenzie IV <sinisterchipmunk@gmail.com>"
+ ],
+ "description": "Javascript Matrix and Vector library for High Performance WebGL apps",
+ "main": "dist/gl-matrix-min.js",
+ "ignore": [
+ "**/.*",
+ "jsdoc-template",
+ "spec",
+ "src",
+ "tasks",
+ "Gemfile",
+ "Gemfile.lock",
+ "Rakefile",
+ "TESTING.md"
+ ],
+ "keywords": [
+ "webGL",
+ "matrix",
+ "vector"
+ ],
+ "license": "MIT"
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/dist/gl-matrix-min.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/dist/gl-matrix-min.js
new file mode 100644
index 00000000000..62db82edfd9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/dist/gl-matrix-min.js
@@ -0,0 +1,29 @@
+/**
+ * @fileoverview gl-matrix - High performance matrix and vector operations
+ * @author Brandon Jones
+ * @author Colin MacKenzie IV
+ * @version 2.3.1
+ */
+
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+!function(t,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define(n);else{var r=n();for(var a in r)("object"==typeof exports?exports:t)[a]=r[a]}}(this,function(){return function(t){function n(a){if(r[a])return r[a].exports;var e=r[a]={exports:{},id:a,loaded:!1};return t[a].call(e.exports,e,e.exports,n),e.loaded=!0,e.exports}var r={};return n.m=t,n.c=r,n.p="",n(0)}([function(t,n,r){n.glMatrix=r(1),n.mat2=r(2),n.mat2d=r(3),n.mat3=r(4),n.mat4=r(5),n.quat=r(6),n.vec2=r(9),n.vec3=r(7),n.vec4=r(8)},function(t,n,r){var a={};a.EPSILON=1e-6,a.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,a.RANDOM=Math.random,a.setMatrixArrayType=function(t){GLMAT_ARRAY_TYPE=t};var e=Math.PI/180;a.toRadian=function(t){return t*e},t.exports=a},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(4);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},e.clone=function(t){var n=new a.ARRAY_TYPE(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},e.transpose=function(t,n){if(t===n){var r=n[1];t[1]=n[2],t[2]=r}else t[0]=n[0],t[1]=n[2],t[2]=n[1],t[3]=n[3];return t},e.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*u-e*a;return o?(o=1/o,t[0]=u*o,t[1]=-a*o,t[2]=-e*o,t[3]=r*o,t):null},e.adjoint=function(t,n){var r=n[0];return t[0]=n[3],t[1]=-n[1],t[2]=-n[2],t[3]=r,t},e.determinant=function(t){return t[0]*t[3]-t[2]*t[1]},e.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],c=r[1],f=r[2],s=r[3];return t[0]=a*i+u*c,t[1]=e*i+o*c,t[2]=a*f+u*s,t[3]=e*f+o*s,t},e.mul=e.multiply,e.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),c=Math.cos(r);return t[0]=a*c+u*i,t[1]=e*c+o*i,t[2]=a*-i+u*c,t[3]=e*-i+o*c,t},e.scale=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],c=r[1];return t[0]=a*i,t[1]=e*i,t[2]=u*c,t[3]=o*c,t},e.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=-r,t[3]=a,t},e.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t},e.str=function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2))},e.LDU=function(t,n,r,a){return t[2]=a[2]/a[0],r[0]=a[0],r[1]=a[1],r[3]=a[3]-t[2]*r[1],[t,n,r]},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(6);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},e.clone=function(t){var n=new a.ARRAY_TYPE(6);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},e.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=r*u-a*e;return c?(c=1/c,t[0]=u*c,t[1]=-a*c,t[2]=-e*c,t[3]=r*c,t[4]=(e*i-u*o)*c,t[5]=(a*o-r*i)*c,t):null},e.determinant=function(t){return t[0]*t[3]-t[1]*t[2]},e.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=r[0],s=r[1],h=r[2],M=r[3],l=r[4],v=r[5];return t[0]=a*f+u*s,t[1]=e*f+o*s,t[2]=a*h+u*M,t[3]=e*h+o*M,t[4]=a*l+u*v+i,t[5]=e*l+o*v+c,t},e.mul=e.multiply,e.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=Math.sin(r),s=Math.cos(r);return t[0]=a*s+u*f,t[1]=e*s+o*f,t[2]=a*-f+u*s,t[3]=e*-f+o*s,t[4]=i,t[5]=c,t},e.scale=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=r[0],s=r[1];return t[0]=a*f,t[1]=e*f,t[2]=u*s,t[3]=o*s,t[4]=i,t[5]=c,t},e.translate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=r[0],s=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=a*f+u*s+i,t[5]=e*f+o*s+c,t},e.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=-r,t[3]=a,t[4]=0,t[5]=0,t},e.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t[4]=0,t[5]=0,t},e.fromTranslation=function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=n[0],t[5]=n[1],t},e.str=function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+1)},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromMat4=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t},e.clone=function(t){var n=new a.ARRAY_TYPE(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.transpose=function(t,n){if(t===n){var r=n[1],a=n[2],e=n[5];t[1]=n[3],t[2]=n[6],t[3]=r,t[5]=n[7],t[6]=a,t[7]=e}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t},e.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8],h=s*o-i*f,M=-s*u+i*c,l=f*u-o*c,v=r*h+a*M+e*l;return v?(v=1/v,t[0]=h*v,t[1]=(-s*a+e*f)*v,t[2]=(i*a-e*o)*v,t[3]=M*v,t[4]=(s*r-e*c)*v,t[5]=(-i*r+e*u)*v,t[6]=l*v,t[7]=(-f*r+a*c)*v,t[8]=(o*r-a*u)*v,t):null},e.adjoint=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8];return t[0]=o*s-i*f,t[1]=e*f-a*s,t[2]=a*i-e*o,t[3]=i*c-u*s,t[4]=r*s-e*c,t[5]=e*u-r*i,t[6]=u*f-o*c,t[7]=a*c-r*f,t[8]=r*o-a*u,t},e.determinant=function(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],c=t[7],f=t[8];return n*(f*u-o*c)+r*(-f*e+o*i)+a*(c*e-u*i)},e.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=r[0],l=r[1],v=r[2],m=r[3],p=r[4],d=r[5],A=r[6],R=r[7],w=r[8];return t[0]=M*a+l*o+v*f,t[1]=M*e+l*i+v*s,t[2]=M*u+l*c+v*h,t[3]=m*a+p*o+d*f,t[4]=m*e+p*i+d*s,t[5]=m*u+p*c+d*h,t[6]=A*a+R*o+w*f,t[7]=A*e+R*i+w*s,t[8]=A*u+R*c+w*h,t},e.mul=e.multiply,e.translate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=r[0],l=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=i,t[5]=c,t[6]=M*a+l*o+f,t[7]=M*e+l*i+s,t[8]=M*u+l*c+h,t},e.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=Math.sin(r),l=Math.cos(r);return t[0]=l*a+M*o,t[1]=l*e+M*i,t[2]=l*u+M*c,t[3]=l*o-M*a,t[4]=l*i-M*e,t[5]=l*c-M*u,t[6]=f,t[7]=s,t[8]=h,t},e.scale=function(t,n,r){var a=r[0],e=r[1];return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=e*n[3],t[4]=e*n[4],t[5]=e*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},e.fromTranslation=function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t},e.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=0,t[3]=-r,t[4]=a,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromMat2d=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t},e.fromQuat=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,c=e+e,f=r*o,s=a*o,h=a*i,M=e*o,l=e*i,v=e*c,m=u*o,p=u*i,d=u*c;return t[0]=1-h-v,t[3]=s-d,t[6]=M+p,t[1]=s+d,t[4]=1-f-v,t[7]=l-m,t[2]=M-p,t[5]=l+m,t[8]=1-f-h,t},e.normalFromMat4=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8],h=n[9],M=n[10],l=n[11],v=n[12],m=n[13],p=n[14],d=n[15],A=r*i-a*o,R=r*c-e*o,w=r*f-u*o,q=a*c-e*i,Y=a*f-u*i,g=e*f-u*c,y=s*m-h*v,x=s*p-M*v,P=s*d-l*v,E=h*p-M*m,T=h*d-l*m,b=M*d-l*p,D=A*b-R*T+w*E+q*P-Y*x+g*y;return D?(D=1/D,t[0]=(i*b-c*T+f*E)*D,t[1]=(c*P-o*b-f*x)*D,t[2]=(o*T-i*P+f*y)*D,t[3]=(e*T-a*b-u*E)*D,t[4]=(r*b-e*P+u*x)*D,t[5]=(a*P-r*T-u*y)*D,t[6]=(m*g-p*Y+d*q)*D,t[7]=(p*w-v*g-d*R)*D,t[8]=(v*Y-m*w+d*A)*D,t):null},e.str=function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2))},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(16);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.clone=function(t){var n=new a.ARRAY_TYPE(16);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n[9]=t[9],n[10]=t[10],n[11]=t[11],n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15],n},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.transpose=function(t,n){if(t===n){var r=n[1],a=n[2],e=n[3],u=n[6],o=n[7],i=n[11];t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=r,t[6]=n[9],t[7]=n[13],t[8]=a,t[9]=u,t[11]=n[14],t[12]=e,t[13]=o,t[14]=i}else t[0]=n[0],t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=n[1],t[5]=n[5],t[6]=n[9],t[7]=n[13],t[8]=n[2],t[9]=n[6],t[10]=n[10],t[11]=n[14],t[12]=n[3],t[13]=n[7],t[14]=n[11],t[15]=n[15];return t},e.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8],h=n[9],M=n[10],l=n[11],v=n[12],m=n[13],p=n[14],d=n[15],A=r*i-a*o,R=r*c-e*o,w=r*f-u*o,q=a*c-e*i,Y=a*f-u*i,g=e*f-u*c,y=s*m-h*v,x=s*p-M*v,P=s*d-l*v,E=h*p-M*m,T=h*d-l*m,b=M*d-l*p,D=A*b-R*T+w*E+q*P-Y*x+g*y;return D?(D=1/D,t[0]=(i*b-c*T+f*E)*D,t[1]=(e*T-a*b-u*E)*D,t[2]=(m*g-p*Y+d*q)*D,t[3]=(M*Y-h*g-l*q)*D,t[4]=(c*P-o*b-f*x)*D,t[5]=(r*b-e*P+u*x)*D,t[6]=(p*w-v*g-d*R)*D,t[7]=(s*g-M*w+l*R)*D,t[8]=(o*T-i*P+f*y)*D,t[9]=(a*P-r*T-u*y)*D,t[10]=(v*Y-m*w+d*A)*D,t[11]=(h*w-s*Y-l*A)*D,t[12]=(i*x-o*E-c*y)*D,t[13]=(r*E-a*x+e*y)*D,t[14]=(m*R-v*q-p*A)*D,t[15]=(s*q-h*R+M*A)*D,t):null},e.adjoint=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8],h=n[9],M=n[10],l=n[11],v=n[12],m=n[13],p=n[14],d=n[15];return t[0]=i*(M*d-l*p)-h*(c*d-f*p)+m*(c*l-f*M),t[1]=-(a*(M*d-l*p)-h*(e*d-u*p)+m*(e*l-u*M)),t[2]=a*(c*d-f*p)-i*(e*d-u*p)+m*(e*f-u*c),t[3]=-(a*(c*l-f*M)-i*(e*l-u*M)+h*(e*f-u*c)),t[4]=-(o*(M*d-l*p)-s*(c*d-f*p)+v*(c*l-f*M)),t[5]=r*(M*d-l*p)-s*(e*d-u*p)+v*(e*l-u*M),t[6]=-(r*(c*d-f*p)-o*(e*d-u*p)+v*(e*f-u*c)),t[7]=r*(c*l-f*M)-o*(e*l-u*M)+s*(e*f-u*c),t[8]=o*(h*d-l*m)-s*(i*d-f*m)+v*(i*l-f*h),t[9]=-(r*(h*d-l*m)-s*(a*d-u*m)+v*(a*l-u*h)),t[10]=r*(i*d-f*m)-o*(a*d-u*m)+v*(a*f-u*i),t[11]=-(r*(i*l-f*h)-o*(a*l-u*h)+s*(a*f-u*i)),t[12]=-(o*(h*p-M*m)-s*(i*p-c*m)+v*(i*M-c*h)),t[13]=r*(h*p-M*m)-s*(a*p-e*m)+v*(a*M-e*h),t[14]=-(r*(i*p-c*m)-o*(a*p-e*m)+v*(a*c-e*i)),t[15]=r*(i*M-c*h)-o*(a*M-e*h)+s*(a*c-e*i),t},e.determinant=function(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],c=t[7],f=t[8],s=t[9],h=t[10],M=t[11],l=t[12],v=t[13],m=t[14],p=t[15],d=n*o-r*u,A=n*i-a*u,R=n*c-e*u,w=r*i-a*o,q=r*c-e*o,Y=a*c-e*i,g=f*v-s*l,y=f*m-h*l,x=f*p-M*l,P=s*m-h*v,E=s*p-M*v,T=h*p-M*m;return d*T-A*E+R*P+w*x-q*y+Y*g},e.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=n[9],l=n[10],v=n[11],m=n[12],p=n[13],d=n[14],A=n[15],R=r[0],w=r[1],q=r[2],Y=r[3];return t[0]=R*a+w*i+q*h+Y*m,t[1]=R*e+w*c+q*M+Y*p,t[2]=R*u+w*f+q*l+Y*d,t[3]=R*o+w*s+q*v+Y*A,R=r[4],w=r[5],q=r[6],Y=r[7],t[4]=R*a+w*i+q*h+Y*m,t[5]=R*e+w*c+q*M+Y*p,t[6]=R*u+w*f+q*l+Y*d,t[7]=R*o+w*s+q*v+Y*A,R=r[8],w=r[9],q=r[10],Y=r[11],t[8]=R*a+w*i+q*h+Y*m,t[9]=R*e+w*c+q*M+Y*p,t[10]=R*u+w*f+q*l+Y*d,t[11]=R*o+w*s+q*v+Y*A,R=r[12],w=r[13],q=r[14],Y=r[15],t[12]=R*a+w*i+q*h+Y*m,t[13]=R*e+w*c+q*M+Y*p,t[14]=R*u+w*f+q*l+Y*d,t[15]=R*o+w*s+q*v+Y*A,t},e.mul=e.multiply,e.translate=function(t,n,r){var a,e,u,o,i,c,f,s,h,M,l,v,m=r[0],p=r[1],d=r[2];return n===t?(t[12]=n[0]*m+n[4]*p+n[8]*d+n[12],t[13]=n[1]*m+n[5]*p+n[9]*d+n[13],t[14]=n[2]*m+n[6]*p+n[10]*d+n[14],t[15]=n[3]*m+n[7]*p+n[11]*d+n[15]):(a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=n[9],l=n[10],v=n[11],t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=i,t[5]=c,t[6]=f,t[7]=s,t[8]=h,t[9]=M,t[10]=l,t[11]=v,t[12]=a*m+i*p+h*d+n[12],t[13]=e*m+c*p+M*d+n[13],t[14]=u*m+f*p+l*d+n[14],t[15]=o*m+s*p+v*d+n[15]),t},e.scale=function(t,n,r){var a=r[0],e=r[1],u=r[2];return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*e,t[5]=n[5]*e,t[6]=n[6]*e,t[7]=n[7]*e,t[8]=n[8]*u,t[9]=n[9]*u,t[10]=n[10]*u,t[11]=n[11]*u,t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},e.rotate=function(t,n,r,e){var u,o,i,c,f,s,h,M,l,v,m,p,d,A,R,w,q,Y,g,y,x,P,E,T,b=e[0],D=e[1],L=e[2],_=Math.sqrt(b*b+D*D+L*L);return Math.abs(_)<a.EPSILON?null:(_=1/_,b*=_,D*=_,L*=_,u=Math.sin(r),o=Math.cos(r),i=1-o,c=n[0],f=n[1],s=n[2],h=n[3],M=n[4],l=n[5],v=n[6],m=n[7],p=n[8],d=n[9],A=n[10],R=n[11],w=b*b*i+o,q=D*b*i+L*u,Y=L*b*i-D*u,g=b*D*i-L*u,y=D*D*i+o,x=L*D*i+b*u,P=b*L*i+D*u,E=D*L*i-b*u,T=L*L*i+o,t[0]=c*w+M*q+p*Y,t[1]=f*w+l*q+d*Y,t[2]=s*w+v*q+A*Y,t[3]=h*w+m*q+R*Y,t[4]=c*g+M*y+p*x,t[5]=f*g+l*y+d*x,t[6]=s*g+v*y+A*x,t[7]=h*g+m*y+R*x,t[8]=c*P+M*E+p*T,t[9]=f*P+l*E+d*T,t[10]=s*P+v*E+A*T,t[11]=h*P+m*E+R*T,n!==t&&(t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t)},e.rotateX=function(t,n,r){var a=Math.sin(r),e=Math.cos(r),u=n[4],o=n[5],i=n[6],c=n[7],f=n[8],s=n[9],h=n[10],M=n[11];return n!==t&&(t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[4]=u*e+f*a,t[5]=o*e+s*a,t[6]=i*e+h*a,t[7]=c*e+M*a,t[8]=f*e-u*a,t[9]=s*e-o*a,t[10]=h*e-i*a,t[11]=M*e-c*a,t},e.rotateY=function(t,n,r){var a=Math.sin(r),e=Math.cos(r),u=n[0],o=n[1],i=n[2],c=n[3],f=n[8],s=n[9],h=n[10],M=n[11];return n!==t&&(t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[0]=u*e-f*a,t[1]=o*e-s*a,t[2]=i*e-h*a,t[3]=c*e-M*a,t[8]=u*a+f*e,t[9]=o*a+s*e,t[10]=i*a+h*e,t[11]=c*a+M*e,t},e.rotateZ=function(t,n,r){var a=Math.sin(r),e=Math.cos(r),u=n[0],o=n[1],i=n[2],c=n[3],f=n[4],s=n[5],h=n[6],M=n[7];return n!==t&&(t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[0]=u*e+f*a,t[1]=o*e+s*a,t[2]=i*e+h*a,t[3]=c*e+M*a,t[4]=f*e-u*a,t[5]=s*e-o*a,t[6]=h*e-i*a,t[7]=M*e-c*a,t},e.fromTranslation=function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=n[0],t[13]=n[1],t[14]=n[2],t[15]=1,t},e.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=n[1],t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=n[2],t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.fromRotation=function(t,n,r){var e,u,o,i=r[0],c=r[1],f=r[2],s=Math.sqrt(i*i+c*c+f*f);return Math.abs(s)<a.EPSILON?null:(s=1/s,i*=s,c*=s,f*=s,e=Math.sin(n),u=Math.cos(n),o=1-u,t[0]=i*i*o+u,t[1]=c*i*o+f*e,t[2]=f*i*o-c*e,t[3]=0,t[4]=i*c*o-f*e,t[5]=c*c*o+u,t[6]=f*c*o+i*e,t[7]=0,t[8]=i*f*o+c*e,t[9]=c*f*o-i*e,t[10]=f*f*o+u,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t)},e.fromXRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=a,t[6]=r,t[7]=0,t[8]=0,t[9]=-r,t[10]=a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.fromYRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=0,t[2]=-r,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=r,t[9]=0,t[10]=a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.fromZRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=0,t[3]=0,t[4]=-r,t[5]=a,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.fromRotationTranslation=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=a+a,c=e+e,f=u+u,s=a*i,h=a*c,M=a*f,l=e*c,v=e*f,m=u*f,p=o*i,d=o*c,A=o*f;return t[0]=1-(l+m),t[1]=h+A,t[2]=M-d,t[3]=0,t[4]=h-A,t[5]=1-(s+m),t[6]=v+p,t[7]=0,t[8]=M+d,t[9]=v-p,t[10]=1-(s+l),t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t},e.fromRotationTranslationScale=function(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3],c=e+e,f=u+u,s=o+o,h=e*c,M=e*f,l=e*s,v=u*f,m=u*s,p=o*s,d=i*c,A=i*f,R=i*s,w=a[0],q=a[1],Y=a[2];return t[0]=(1-(v+p))*w,t[1]=(M+R)*w,t[2]=(l-A)*w,t[3]=0,t[4]=(M-R)*q,t[5]=(1-(h+p))*q,t[6]=(m+d)*q,t[7]=0,t[8]=(l+A)*Y,t[9]=(m-d)*Y,t[10]=(1-(h+v))*Y,t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t},e.fromRotationTranslationScaleOrigin=function(t,n,r,a,e){var u=n[0],o=n[1],i=n[2],c=n[3],f=u+u,s=o+o,h=i+i,M=u*f,l=u*s,v=u*h,m=o*s,p=o*h,d=i*h,A=c*f,R=c*s,w=c*h,q=a[0],Y=a[1],g=a[2],y=e[0],x=e[1],P=e[2];return t[0]=(1-(m+d))*q,t[1]=(l+w)*q,t[2]=(v-R)*q,t[3]=0,t[4]=(l-w)*Y,t[5]=(1-(M+d))*Y,t[6]=(p+A)*Y,t[7]=0,t[8]=(v+R)*g,t[9]=(p-A)*g,t[10]=(1-(M+m))*g,t[11]=0,t[12]=r[0]+y-(t[0]*y+t[4]*x+t[8]*P),t[13]=r[1]+x-(t[1]*y+t[5]*x+t[9]*P),t[14]=r[2]+P-(t[2]*y+t[6]*x+t[10]*P),t[15]=1,t},e.fromQuat=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,c=e+e,f=r*o,s=a*o,h=a*i,M=e*o,l=e*i,v=e*c,m=u*o,p=u*i,d=u*c;return t[0]=1-h-v,t[1]=s+d,t[2]=M-p,t[3]=0,t[4]=s-d,t[5]=1-f-v,t[6]=l+m,t[7]=0,t[8]=M+p,t[9]=l-m,t[10]=1-f-h,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.frustum=function(t,n,r,a,e,u,o){var i=1/(r-n),c=1/(e-a),f=1/(u-o);return t[0]=2*u*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*u*c,t[6]=0,t[7]=0,t[8]=(r+n)*i,t[9]=(e+a)*c,t[10]=(o+u)*f,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*u*2*f,t[15]=0,t},e.perspective=function(t,n,r,a,e){var u=1/Math.tan(n/2),o=1/(a-e);return t[0]=u/r,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=u,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=(e+a)*o,t[11]=-1,t[12]=0,t[13]=0,t[14]=2*e*a*o,t[15]=0,t},e.perspectiveFromFieldOfView=function(t,n,r,a){var e=Math.tan(n.upDegrees*Math.PI/180),u=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),c=2/(o+i),f=2/(e+u);return t[0]=c,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=f,t[6]=0,t[7]=0,t[8]=-((o-i)*c*.5),t[9]=(e-u)*f*.5,t[10]=a/(r-a),t[11]=-1,t[12]=0,t[13]=0,t[14]=a*r/(r-a),t[15]=0,t},e.ortho=function(t,n,r,a,e,u,o){var i=1/(n-r),c=1/(a-e),f=1/(u-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*c,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*f,t[11]=0,t[12]=(n+r)*i,t[13]=(e+a)*c,t[14]=(o+u)*f,t[15]=1,t},e.lookAt=function(t,n,r,u){var o,i,c,f,s,h,M,l,v,m,p=n[0],d=n[1],A=n[2],R=u[0],w=u[1],q=u[2],Y=r[0],g=r[1],y=r[2];return Math.abs(p-Y)<a.EPSILON&&Math.abs(d-g)<a.EPSILON&&Math.abs(A-y)<a.EPSILON?e.identity(t):(M=p-Y,l=d-g,v=A-y,m=1/Math.sqrt(M*M+l*l+v*v),M*=m,l*=m,v*=m,o=w*v-q*l,i=q*M-R*v,c=R*l-w*M,m=Math.sqrt(o*o+i*i+c*c),m?(m=1/m,o*=m,i*=m,c*=m):(o=0,i=0,c=0),f=l*c-v*i,s=v*o-M*c,h=M*i-l*o,m=Math.sqrt(f*f+s*s+h*h),m?(m=1/m,f*=m,s*=m,h*=m):(f=0,s=0,h=0),t[0]=o,t[1]=f,t[2]=M,t[3]=0,t[4]=i,t[5]=s,t[6]=l,t[7]=0,t[8]=c,t[9]=h,t[10]=v,t[11]=0,t[12]=-(o*p+i*d+c*A),t[13]=-(f*p+s*d+h*A),t[14]=-(M*p+l*d+v*A),t[15]=1,t)},e.str=function(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2)+Math.pow(t[9],2)+Math.pow(t[10],2)+Math.pow(t[11],2)+Math.pow(t[12],2)+Math.pow(t[13],2)+Math.pow(t[14],2)+Math.pow(t[15],2))},t.exports=e},function(t,n,r){var a=r(1),e=r(4),u=r(7),o=r(8),i={};i.create=function(){var t=new a.ARRAY_TYPE(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},i.rotationTo=function(){var t=u.create(),n=u.fromValues(1,0,0),r=u.fromValues(0,1,0);return function(a,e,o){var c=u.dot(e,o);return-.999999>c?(u.cross(t,n,e),u.length(t)<1e-6&&u.cross(t,r,e),u.normalize(t,t),i.setAxisAngle(a,t,Math.PI),a):c>.999999?(a[0]=0,a[1]=0,a[2]=0,a[3]=1,a):(u.cross(t,e,o),a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=1+c,i.normalize(a,a))}}(),i.setAxes=function(){var t=e.create();return function(n,r,a,e){return t[0]=a[0],t[3]=a[1],t[6]=a[2],t[1]=e[0],t[4]=e[1],t[7]=e[2],t[2]=-r[0],t[5]=-r[1],t[8]=-r[2],i.normalize(n,i.fromMat3(n,t))}}(),i.clone=o.clone,i.fromValues=o.fromValues,i.copy=o.copy,i.set=o.set,i.identity=function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},i.setAxisAngle=function(t,n,r){r=.5*r;var a=Math.sin(r);return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=Math.cos(r),t},i.add=o.add,i.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],c=r[1],f=r[2],s=r[3];return t[0]=a*s+o*i+e*f-u*c,t[1]=e*s+o*c+u*i-a*f,t[2]=u*s+o*f+a*c-e*i,t[3]=o*s-a*i-e*c-u*f,t},i.mul=i.multiply,i.scale=o.scale,i.rotateX=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),c=Math.cos(r);return t[0]=a*c+o*i,t[1]=e*c+u*i,t[2]=u*c-e*i,t[3]=o*c-a*i,t},i.rotateY=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),c=Math.cos(r);return t[0]=a*c-u*i,t[1]=e*c+o*i,t[2]=u*c+a*i,t[3]=o*c-e*i,t},i.rotateZ=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),c=Math.cos(r);return t[0]=a*c+e*i,t[1]=e*c-a*i,t[2]=u*c+o*i,t[3]=o*c-u*i,t},i.calculateW=function(t,n){var r=n[0],a=n[1],e=n[2];return t[0]=r,t[1]=a,t[2]=e,t[3]=Math.sqrt(Math.abs(1-r*r-a*a-e*e)),t},i.dot=o.dot,i.lerp=o.lerp,i.slerp=function(t,n,r,a){var e,u,o,i,c,f=n[0],s=n[1],h=n[2],M=n[3],l=r[0],v=r[1],m=r[2],p=r[3];return u=f*l+s*v+h*m+M*p,0>u&&(u=-u,l=-l,v=-v,m=-m,p=-p),1-u>1e-6?(e=Math.acos(u),o=Math.sin(e),i=Math.sin((1-a)*e)/o,c=Math.sin(a*e)/o):(i=1-a,c=a),t[0]=i*f+c*l,t[1]=i*s+c*v,t[2]=i*h+c*m,t[3]=i*M+c*p,t},i.sqlerp=function(){var t=i.create(),n=i.create();return function(r,a,e,u,o,c){return i.slerp(t,a,o,c),i.slerp(n,e,u,c),i.slerp(r,t,n,2*c*(1-c)),r}}(),i.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*r+a*a+e*e+u*u,i=o?1/o:0;return t[0]=-r*i,t[1]=-a*i,t[2]=-e*i,t[3]=u*i,t},i.conjugate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t},i.length=o.length,i.len=i.length,i.squaredLength=o.squaredLength,i.sqrLen=i.squaredLength,i.normalize=o.normalize,i.fromMat3=function(t,n){var r,a=n[0]+n[4]+n[8];if(a>0)r=Math.sqrt(a+1),t[3]=.5*r,r=.5/r,t[0]=(n[5]-n[7])*r,t[1]=(n[6]-n[2])*r,t[2]=(n[1]-n[3])*r;else{var e=0;n[4]>n[0]&&(e=1),n[8]>n[3*e+e]&&(e=2);var u=(e+1)%3,o=(e+2)%3;r=Math.sqrt(n[3*e+e]-n[3*u+u]-n[3*o+o]+1),t[e]=.5*r,r=.5/r,t[3]=(n[3*u+o]-n[3*o+u])*r,t[u]=(n[3*u+e]+n[3*e+u])*r,t[o]=(n[3*o+e]+n[3*e+o])*r}return t},i.str=function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},t.exports=i},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(3);return t[0]=0,t[1]=0,t[2]=0,t},e.clone=function(t){var n=new a.ARRAY_TYPE(3);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n},e.fromValues=function(t,n,r){var e=new a.ARRAY_TYPE(3);return e[0]=t,e[1]=n,e[2]=r,e},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t},e.set=function(t,n,r,a){return t[0]=n,t[1]=r,t[2]=a,t},e.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t},e.subtract=function(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t},e.sub=e.subtract,e.multiply=function(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t[2]=n[2]*r[2],t},e.mul=e.multiply,e.divide=function(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t[2]=n[2]/r[2],t},e.div=e.divide,e.min=function(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t[2]=Math.min(n[2],r[2]),t},e.max=function(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t[2]=Math.max(n[2],r[2]),t},e.scale=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t},e.scaleAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t},e.distance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return Math.sqrt(r*r+a*a+e*e)},e.dist=e.distance,e.squaredDistance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return r*r+a*a+e*e},e.sqrDist=e.squaredDistance,e.length=function(t){var n=t[0],r=t[1],a=t[2];return Math.sqrt(n*n+r*r+a*a)},e.len=e.length,e.squaredLength=function(t){var n=t[0],r=t[1],a=t[2];return n*n+r*r+a*a},e.sqrLen=e.squaredLength,e.negate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t},e.inverse=function(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t},e.normalize=function(t,n){var r=n[0],a=n[1],e=n[2],u=r*r+a*a+e*e;return u>0&&(u=1/Math.sqrt(u),t[0]=n[0]*u,t[1]=n[1]*u,t[2]=n[2]*u),t},e.dot=function(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]},e.cross=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],c=r[2];return t[0]=e*c-u*i,t[1]=u*o-a*c,t[2]=a*i-e*o,t},e.lerp=function(t,n,r,a){var e=n[0],u=n[1],o=n[2];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t},e.hermite=function(t,n,r,a,e,u){var o=u*u,i=o*(2*u-3)+1,c=o*(u-2)+u,f=o*(u-1),s=o*(3-2*u);return t[0]=n[0]*i+r[0]*c+a[0]*f+e[0]*s,t[1]=n[1]*i+r[1]*c+a[1]*f+e[1]*s,t[2]=n[2]*i+r[2]*c+a[2]*f+e[2]*s,t},e.bezier=function(t,n,r,a,e,u){var o=1-u,i=o*o,c=u*u,f=i*o,s=3*u*i,h=3*c*o,M=c*u;return t[0]=n[0]*f+r[0]*s+a[0]*h+e[0]*M,t[1]=n[1]*f+r[1]*s+a[1]*h+e[1]*M,t[2]=n[2]*f+r[2]*s+a[2]*h+e[2]*M,t},e.random=function(t,n){n=n||1;var r=2*a.RANDOM()*Math.PI,e=2*a.RANDOM()-1,u=Math.sqrt(1-e*e)*n;return t[0]=Math.cos(r)*u,t[1]=Math.sin(r)*u,t[2]=e*n,t},e.transformMat4=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[3]*a+r[7]*e+r[11]*u+r[15];return o=o||1,t[0]=(r[0]*a+r[4]*e+r[8]*u+r[12])/o,t[1]=(r[1]*a+r[5]*e+r[9]*u+r[13])/o,t[2]=(r[2]*a+r[6]*e+r[10]*u+r[14])/o,t},e.transformMat3=function(t,n,r){var a=n[0],e=n[1],u=n[2];return t[0]=a*r[0]+e*r[3]+u*r[6],t[1]=a*r[1]+e*r[4]+u*r[7],t[2]=a*r[2]+e*r[5]+u*r[8],t},e.transformQuat=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],c=r[2],f=r[3],s=f*a+i*u-c*e,h=f*e+c*a-o*u,M=f*u+o*e-i*a,l=-o*a-i*e-c*u;return t[0]=s*f+l*-o+h*-c-M*-i,t[1]=h*f+l*-i+M*-o-s*-c,t[2]=M*f+l*-c+s*-i-h*-o,t},e.rotateX=function(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[0],u[1]=e[1]*Math.cos(a)-e[2]*Math.sin(a),u[2]=e[1]*Math.sin(a)+e[2]*Math.cos(a),t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t},e.rotateY=function(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[2]*Math.sin(a)+e[0]*Math.cos(a),u[1]=e[1],u[2]=e[2]*Math.cos(a)-e[0]*Math.sin(a),t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t},e.rotateZ=function(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[0]*Math.cos(a)-e[1]*Math.sin(a),u[1]=e[0]*Math.sin(a)+e[1]*Math.cos(a),u[2]=e[2],t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t},e.forEach=function(){var t=e.create();return function(n,r,a,e,u,o){var i,c;for(r||(r=3),a||(a=0),c=e?Math.min(e*r+a,n.length):n.length,i=a;c>i;i+=r)t[0]=n[i],t[1]=n[i+1],t[2]=n[i+2],u(t,t,o),n[i]=t[0],n[i+1]=t[1],n[i+2]=t[2];return n}}(),e.angle=function(t,n){var r=e.fromValues(t[0],t[1],t[2]),a=e.fromValues(n[0],n[1],n[2]);e.normalize(r,r),e.normalize(a,a);var u=e.dot(r,a);return u>1?0:Math.acos(u)},e.str=function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t},e.clone=function(t){var n=new a.ARRAY_TYPE(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},e.fromValues=function(t,n,r,e){var u=new a.ARRAY_TYPE(4);return u[0]=t,u[1]=n,u[2]=r,u[3]=e,u},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},e.set=function(t,n,r,a,e){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t},e.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t},e.subtract=function(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t},e.sub=e.subtract,e.multiply=function(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t[2]=n[2]*r[2],t[3]=n[3]*r[3],t},e.mul=e.multiply,e.divide=function(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t[2]=n[2]/r[2],t[3]=n[3]/r[3],t},e.div=e.divide,e.min=function(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t[2]=Math.min(n[2],r[2]),t[3]=Math.min(n[3],r[3]),t},e.max=function(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t[2]=Math.max(n[2],r[2]),t[3]=Math.max(n[3],r[3]),t},e.scale=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t},e.scaleAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t},e.distance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2],u=n[3]-t[3];return Math.sqrt(r*r+a*a+e*e+u*u)},e.dist=e.distance,e.squaredDistance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2],u=n[3]-t[3];return r*r+a*a+e*e+u*u},e.sqrDist=e.squaredDistance,e.length=function(t){var n=t[0],r=t[1],a=t[2],e=t[3];return Math.sqrt(n*n+r*r+a*a+e*e)},e.len=e.length,e.squaredLength=function(t){var n=t[0],r=t[1],a=t[2],e=t[3];return n*n+r*r+a*a+e*e},e.sqrLen=e.squaredLength,e.negate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=-n[3],t},e.inverse=function(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t[3]=1/n[3],t},e.normalize=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*r+a*a+e*e+u*u;return o>0&&(o=1/Math.sqrt(o),t[0]=r*o,t[1]=a*o,t[2]=e*o,t[3]=u*o),t},e.dot=function(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]},e.lerp=function(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t[3]=i+a*(r[3]-i),t},e.random=function(t,n){return n=n||1,t[0]=a.RANDOM(),t[1]=a.RANDOM(),t[2]=a.RANDOM(),t[3]=a.RANDOM(),e.normalize(t,t),e.scale(t,t,n),t},e.transformMat4=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3];return t[0]=r[0]*a+r[4]*e+r[8]*u+r[12]*o,t[1]=r[1]*a+r[5]*e+r[9]*u+r[13]*o,t[2]=r[2]*a+r[6]*e+r[10]*u+r[14]*o,t[3]=r[3]*a+r[7]*e+r[11]*u+r[15]*o,t},e.transformQuat=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],c=r[2],f=r[3],s=f*a+i*u-c*e,h=f*e+c*a-o*u,M=f*u+o*e-i*a,l=-o*a-i*e-c*u;return t[0]=s*f+l*-o+h*-c-M*-i,t[1]=h*f+l*-i+M*-o-s*-c,t[2]=M*f+l*-c+s*-i-h*-o,t[3]=n[3],t},e.forEach=function(){var t=e.create();return function(n,r,a,e,u,o){var i,c;for(r||(r=4),a||(a=0),c=e?Math.min(e*r+a,n.length):n.length,i=a;c>i;i+=r)t[0]=n[i],t[1]=n[i+1],t[2]=n[i+2],t[3]=n[i+3],u(t,t,o),n[i]=t[0],n[i+1]=t[1],n[i+2]=t[2],n[i+3]=t[3];return n}}(),e.str=function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(2);return t[0]=0,t[1]=0,t},e.clone=function(t){var n=new a.ARRAY_TYPE(2);return n[0]=t[0],n[1]=t[1],n},e.fromValues=function(t,n){var r=new a.ARRAY_TYPE(2);return r[0]=t,r[1]=n,r},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t},e.set=function(t,n,r){return t[0]=n,t[1]=r,t},e.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t},e.subtract=function(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t},e.sub=e.subtract,e.multiply=function(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t},e.mul=e.multiply,e.divide=function(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t},e.div=e.divide,e.min=function(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t},e.max=function(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t},e.scale=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t},e.scaleAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t},e.distance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1];return Math.sqrt(r*r+a*a)},e.dist=e.distance,e.squaredDistance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1];return r*r+a*a},e.sqrDist=e.squaredDistance,e.length=function(t){var n=t[0],r=t[1];return Math.sqrt(n*n+r*r)},e.len=e.length,e.squaredLength=function(t){var n=t[0],r=t[1];return n*n+r*r},e.sqrLen=e.squaredLength,e.negate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t},e.inverse=function(t,n){return t[0]=1/n[0],t[1]=1/n[1],t},e.normalize=function(t,n){var r=n[0],a=n[1],e=r*r+a*a;return e>0&&(e=1/Math.sqrt(e),t[0]=n[0]*e,t[1]=n[1]*e),t},e.dot=function(t,n){return t[0]*n[0]+t[1]*n[1]},e.cross=function(t,n,r){var a=n[0]*r[1]-n[1]*r[0];return t[0]=t[1]=0,t[2]=a,t},e.lerp=function(t,n,r,a){var e=n[0],u=n[1];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t},e.random=function(t,n){n=n||1;var r=2*a.RANDOM()*Math.PI;return t[0]=Math.cos(r)*n,t[1]=Math.sin(r)*n,t},e.transformMat2=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e,t[1]=r[1]*a+r[3]*e,t},e.transformMat2d=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e+r[4],t[1]=r[1]*a+r[3]*e+r[5],t},e.transformMat3=function(t,n,r){
+var a=n[0],e=n[1];return t[0]=r[0]*a+r[3]*e+r[6],t[1]=r[1]*a+r[4]*e+r[7],t},e.transformMat4=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[4]*e+r[12],t[1]=r[1]*a+r[5]*e+r[13],t},e.forEach=function(){var t=e.create();return function(n,r,a,e,u,o){var i,c;for(r||(r=2),a||(a=0),c=e?Math.min(e*r+a,n.length):n.length,i=a;c>i;i+=r)t[0]=n[i],t[1]=n[i+1],u(t,t,o),n[i]=t[0],n[i+1]=t[1];return n}}(),e.str=function(t){return"vec2("+t[0]+", "+t[1]+")"},t.exports=e}])}); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/dist/gl-matrix.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/dist/gl-matrix.js
new file mode 100644
index 00000000000..ab1e9b0aa58
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/dist/gl-matrix.js
@@ -0,0 +1,5020 @@
+/**
+ * @fileoverview gl-matrix - High performance matrix and vector operations
+ * @author Brandon Jones
+ * @author Colin MacKenzie IV
+ * @version 2.3.1
+ */
+
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define(factory);
+ else {
+ var a = factory();
+ for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
+ }
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ exports: {},
+/******/ id: moduleId,
+/******/ loaded: false
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ // Flag the module as loaded
+/******/ module.loaded = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * @fileoverview gl-matrix - High performance matrix and vector operations
+ * @author Brandon Jones
+ * @author Colin MacKenzie IV
+ * @version 2.3.1
+ */
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+ // END HEADER
+
+ exports.glMatrix = __webpack_require__(1);
+ exports.mat2 = __webpack_require__(2);
+ exports.mat2d = __webpack_require__(3);
+ exports.mat3 = __webpack_require__(4);
+ exports.mat4 = __webpack_require__(5);
+ exports.quat = __webpack_require__(6);
+ exports.vec2 = __webpack_require__(9);
+ exports.vec3 = __webpack_require__(7);
+ exports.vec4 = __webpack_require__(8);
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ /**
+ * @class Common utilities
+ * @name glMatrix
+ */
+ var glMatrix = {};
+
+ // Constants
+ glMatrix.EPSILON = 0.000001;
+ glMatrix.ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
+ glMatrix.RANDOM = Math.random;
+
+ /**
+ * Sets the type of array used when creating new vectors and matrices
+ *
+ * @param {Type} type Array type, such as Float32Array or Array
+ */
+ glMatrix.setMatrixArrayType = function(type) {
+ GLMAT_ARRAY_TYPE = type;
+ }
+
+ var degree = Math.PI / 180;
+
+ /**
+ * Convert Degree To Radian
+ *
+ * @param {Number} Angle in Degrees
+ */
+ glMatrix.toRadian = function(a){
+ return a * degree;
+ }
+
+ module.exports = glMatrix;
+
+
+/***/ },
+/* 2 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ var glMatrix = __webpack_require__(1);
+
+ /**
+ * @class 2x2 Matrix
+ * @name mat2
+ */
+ var mat2 = {};
+
+ /**
+ * Creates a new identity mat2
+ *
+ * @returns {mat2} a new 2x2 matrix
+ */
+ mat2.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ };
+
+ /**
+ * Creates a new mat2 initialized with values from an existing matrix
+ *
+ * @param {mat2} a matrix to clone
+ * @returns {mat2} a new 2x2 matrix
+ */
+ mat2.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ };
+
+ /**
+ * Copy the values from one mat2 to another
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the source matrix
+ * @returns {mat2} out
+ */
+ mat2.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ };
+
+ /**
+ * Set a mat2 to the identity matrix
+ *
+ * @param {mat2} out the receiving matrix
+ * @returns {mat2} out
+ */
+ mat2.identity = function(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ };
+
+ /**
+ * Transpose the values of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the source matrix
+ * @returns {mat2} out
+ */
+ mat2.transpose = function(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a1 = a[1];
+ out[1] = a[2];
+ out[2] = a1;
+ } else {
+ out[0] = a[0];
+ out[1] = a[2];
+ out[2] = a[1];
+ out[3] = a[3];
+ }
+
+ return out;
+ };
+
+ /**
+ * Inverts a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the source matrix
+ * @returns {mat2} out
+ */
+ mat2.invert = function(out, a) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
+
+ // Calculate the determinant
+ det = a0 * a3 - a2 * a1;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = a3 * det;
+ out[1] = -a1 * det;
+ out[2] = -a2 * det;
+ out[3] = a0 * det;
+
+ return out;
+ };
+
+ /**
+ * Calculates the adjugate of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the source matrix
+ * @returns {mat2} out
+ */
+ mat2.adjoint = function(out, a) {
+ // Caching this value is nessecary if out == a
+ var a0 = a[0];
+ out[0] = a[3];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a0;
+
+ return out;
+ };
+
+ /**
+ * Calculates the determinant of a mat2
+ *
+ * @param {mat2} a the source matrix
+ * @returns {Number} determinant of a
+ */
+ mat2.determinant = function (a) {
+ return a[0] * a[3] - a[2] * a[1];
+ };
+
+ /**
+ * Multiplies two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the first operand
+ * @param {mat2} b the second operand
+ * @returns {mat2} out
+ */
+ mat2.multiply = function (out, a, b) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
+ var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ return out;
+ };
+
+ /**
+ * Alias for {@link mat2.multiply}
+ * @function
+ */
+ mat2.mul = mat2.multiply;
+
+ /**
+ * Rotates a mat2 by the given angle
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+ mat2.rotate = function (out, a, rad) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ return out;
+ };
+
+ /**
+ * Scales the mat2 by the dimensions in the given vec2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the matrix to rotate
+ * @param {vec2} v the vec2 to scale the matrix by
+ * @returns {mat2} out
+ **/
+ mat2.scale = function(out, a, v) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
+ v0 = v[0], v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ return out;
+ };
+
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.rotate(dest, dest, rad);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+ mat2.fromRotation = function(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.scale(dest, dest, vec);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {vec2} v Scaling vector
+ * @returns {mat2} out
+ */
+ mat2.fromScaling = function(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ return out;
+ }
+
+ /**
+ * Returns a string representation of a mat2
+ *
+ * @param {mat2} mat matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+ mat2.str = function (a) {
+ return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
+ };
+
+ /**
+ * Returns Frobenius norm of a mat2
+ *
+ * @param {mat2} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+ mat2.frob = function (a) {
+ return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)))
+ };
+
+ /**
+ * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
+ * @param {mat2} L the lower triangular matrix
+ * @param {mat2} D the diagonal matrix
+ * @param {mat2} U the upper triangular matrix
+ * @param {mat2} a the input matrix to factorize
+ */
+
+ mat2.LDU = function (L, D, U, a) {
+ L[2] = a[2]/a[0];
+ U[0] = a[0];
+ U[1] = a[1];
+ U[3] = a[3] - L[2] * U[1];
+ return [L, D, U];
+ };
+
+
+ module.exports = mat2;
+
+
+/***/ },
+/* 3 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ var glMatrix = __webpack_require__(1);
+
+ /**
+ * @class 2x3 Matrix
+ * @name mat2d
+ *
+ * @description
+ * A mat2d contains six elements defined as:
+ * <pre>
+ * [a, c, tx,
+ * b, d, ty]
+ * </pre>
+ * This is a short form for the 3x3 matrix:
+ * <pre>
+ * [a, c, tx,
+ * b, d, ty,
+ * 0, 0, 1]
+ * </pre>
+ * The last row is ignored so the array is shorter and operations are faster.
+ */
+ var mat2d = {};
+
+ /**
+ * Creates a new identity mat2d
+ *
+ * @returns {mat2d} a new 2x3 matrix
+ */
+ mat2d.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(6);
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+ };
+
+ /**
+ * Creates a new mat2d initialized with values from an existing matrix
+ *
+ * @param {mat2d} a matrix to clone
+ * @returns {mat2d} a new 2x3 matrix
+ */
+ mat2d.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(6);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+ };
+
+ /**
+ * Copy the values from one mat2d to another
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+ mat2d.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+ };
+
+ /**
+ * Set a mat2d to the identity matrix
+ *
+ * @param {mat2d} out the receiving matrix
+ * @returns {mat2d} out
+ */
+ mat2d.identity = function(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+ };
+
+ /**
+ * Inverts a mat2d
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+ mat2d.invert = function(out, a) {
+ var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
+ atx = a[4], aty = a[5];
+
+ var det = aa * ad - ab * ac;
+ if(!det){
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = ad * det;
+ out[1] = -ab * det;
+ out[2] = -ac * det;
+ out[3] = aa * det;
+ out[4] = (ac * aty - ad * atx) * det;
+ out[5] = (ab * atx - aa * aty) * det;
+ return out;
+ };
+
+ /**
+ * Calculates the determinant of a mat2d
+ *
+ * @param {mat2d} a the source matrix
+ * @returns {Number} determinant of a
+ */
+ mat2d.determinant = function (a) {
+ return a[0] * a[3] - a[1] * a[2];
+ };
+
+ /**
+ * Multiplies two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the first operand
+ * @param {mat2d} b the second operand
+ * @returns {mat2d} out
+ */
+ mat2d.multiply = function (out, a, b) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
+ b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ out[4] = a0 * b4 + a2 * b5 + a4;
+ out[5] = a1 * b4 + a3 * b5 + a5;
+ return out;
+ };
+
+ /**
+ * Alias for {@link mat2d.multiply}
+ * @function
+ */
+ mat2d.mul = mat2d.multiply;
+
+ /**
+ * Rotates a mat2d by the given angle
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+ mat2d.rotate = function (out, a, rad) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+ };
+
+ /**
+ * Scales the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the matrix to translate
+ * @param {vec2} v the vec2 to scale the matrix by
+ * @returns {mat2d} out
+ **/
+ mat2d.scale = function(out, a, v) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
+ v0 = v[0], v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+ };
+
+ /**
+ * Translates the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the matrix to translate
+ * @param {vec2} v the vec2 to translate the matrix by
+ * @returns {mat2d} out
+ **/
+ mat2d.translate = function(out, a, v) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
+ v0 = v[0], v1 = v[1];
+ out[0] = a0;
+ out[1] = a1;
+ out[2] = a2;
+ out[3] = a3;
+ out[4] = a0 * v0 + a2 * v1 + a4;
+ out[5] = a1 * v0 + a3 * v1 + a5;
+ return out;
+ };
+
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.rotate(dest, dest, rad);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+ mat2d.fromRotation = function(out, rad) {
+ var s = Math.sin(rad), c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.scale(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {vec2} v Scaling vector
+ * @returns {mat2d} out
+ */
+ mat2d.fromScaling = function(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.translate(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {vec2} v Translation vector
+ * @returns {mat2d} out
+ */
+ mat2d.fromTranslation = function(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = v[0];
+ out[5] = v[1];
+ return out;
+ }
+
+ /**
+ * Returns a string representation of a mat2d
+ *
+ * @param {mat2d} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+ mat2d.str = function (a) {
+ return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
+ a[3] + ', ' + a[4] + ', ' + a[5] + ')';
+ };
+
+ /**
+ * Returns Frobenius norm of a mat2d
+ *
+ * @param {mat2d} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+ mat2d.frob = function (a) {
+ return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1))
+ };
+
+ module.exports = mat2d;
+
+
+/***/ },
+/* 4 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ var glMatrix = __webpack_require__(1);
+
+ /**
+ * @class 3x3 Matrix
+ * @name mat3
+ */
+ var mat3 = {};
+
+ /**
+ * Creates a new identity mat3
+ *
+ * @returns {mat3} a new 3x3 matrix
+ */
+ mat3.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(9);
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+ };
+
+ /**
+ * Copies the upper-left 3x3 values into the given mat3.
+ *
+ * @param {mat3} out the receiving 3x3 matrix
+ * @param {mat4} a the source 4x4 matrix
+ * @returns {mat3} out
+ */
+ mat3.fromMat4 = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[4];
+ out[4] = a[5];
+ out[5] = a[6];
+ out[6] = a[8];
+ out[7] = a[9];
+ out[8] = a[10];
+ return out;
+ };
+
+ /**
+ * Creates a new mat3 initialized with values from an existing matrix
+ *
+ * @param {mat3} a matrix to clone
+ * @returns {mat3} a new 3x3 matrix
+ */
+ mat3.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(9);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+ };
+
+ /**
+ * Copy the values from one mat3 to another
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the source matrix
+ * @returns {mat3} out
+ */
+ mat3.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+ };
+
+ /**
+ * Set a mat3 to the identity matrix
+ *
+ * @param {mat3} out the receiving matrix
+ * @returns {mat3} out
+ */
+ mat3.identity = function(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+ };
+
+ /**
+ * Transpose the values of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the source matrix
+ * @returns {mat3} out
+ */
+ mat3.transpose = function(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1], a02 = a[2], a12 = a[5];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a01;
+ out[5] = a[7];
+ out[6] = a02;
+ out[7] = a12;
+ } else {
+ out[0] = a[0];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a[1];
+ out[4] = a[4];
+ out[5] = a[7];
+ out[6] = a[2];
+ out[7] = a[5];
+ out[8] = a[8];
+ }
+
+ return out;
+ };
+
+ /**
+ * Inverts a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the source matrix
+ * @returns {mat3} out
+ */
+ mat3.invert = function(out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8],
+
+ b01 = a22 * a11 - a12 * a21,
+ b11 = -a22 * a10 + a12 * a20,
+ b21 = a21 * a10 - a11 * a20,
+
+ // Calculate the determinant
+ det = a00 * b01 + a01 * b11 + a02 * b21;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = b01 * det;
+ out[1] = (-a22 * a01 + a02 * a21) * det;
+ out[2] = (a12 * a01 - a02 * a11) * det;
+ out[3] = b11 * det;
+ out[4] = (a22 * a00 - a02 * a20) * det;
+ out[5] = (-a12 * a00 + a02 * a10) * det;
+ out[6] = b21 * det;
+ out[7] = (-a21 * a00 + a01 * a20) * det;
+ out[8] = (a11 * a00 - a01 * a10) * det;
+ return out;
+ };
+
+ /**
+ * Calculates the adjugate of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the source matrix
+ * @returns {mat3} out
+ */
+ mat3.adjoint = function(out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8];
+
+ out[0] = (a11 * a22 - a12 * a21);
+ out[1] = (a02 * a21 - a01 * a22);
+ out[2] = (a01 * a12 - a02 * a11);
+ out[3] = (a12 * a20 - a10 * a22);
+ out[4] = (a00 * a22 - a02 * a20);
+ out[5] = (a02 * a10 - a00 * a12);
+ out[6] = (a10 * a21 - a11 * a20);
+ out[7] = (a01 * a20 - a00 * a21);
+ out[8] = (a00 * a11 - a01 * a10);
+ return out;
+ };
+
+ /**
+ * Calculates the determinant of a mat3
+ *
+ * @param {mat3} a the source matrix
+ * @returns {Number} determinant of a
+ */
+ mat3.determinant = function (a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8];
+
+ return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
+ };
+
+ /**
+ * Multiplies two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the first operand
+ * @param {mat3} b the second operand
+ * @returns {mat3} out
+ */
+ mat3.multiply = function (out, a, b) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8],
+
+ b00 = b[0], b01 = b[1], b02 = b[2],
+ b10 = b[3], b11 = b[4], b12 = b[5],
+ b20 = b[6], b21 = b[7], b22 = b[8];
+
+ out[0] = b00 * a00 + b01 * a10 + b02 * a20;
+ out[1] = b00 * a01 + b01 * a11 + b02 * a21;
+ out[2] = b00 * a02 + b01 * a12 + b02 * a22;
+
+ out[3] = b10 * a00 + b11 * a10 + b12 * a20;
+ out[4] = b10 * a01 + b11 * a11 + b12 * a21;
+ out[5] = b10 * a02 + b11 * a12 + b12 * a22;
+
+ out[6] = b20 * a00 + b21 * a10 + b22 * a20;
+ out[7] = b20 * a01 + b21 * a11 + b22 * a21;
+ out[8] = b20 * a02 + b21 * a12 + b22 * a22;
+ return out;
+ };
+
+ /**
+ * Alias for {@link mat3.multiply}
+ * @function
+ */
+ mat3.mul = mat3.multiply;
+
+ /**
+ * Translate a mat3 by the given vector
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the matrix to translate
+ * @param {vec2} v vector to translate by
+ * @returns {mat3} out
+ */
+ mat3.translate = function(out, a, v) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8],
+ x = v[0], y = v[1];
+
+ out[0] = a00;
+ out[1] = a01;
+ out[2] = a02;
+
+ out[3] = a10;
+ out[4] = a11;
+ out[5] = a12;
+
+ out[6] = x * a00 + y * a10 + a20;
+ out[7] = x * a01 + y * a11 + a21;
+ out[8] = x * a02 + y * a12 + a22;
+ return out;
+ };
+
+ /**
+ * Rotates a mat3 by the given angle
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+ mat3.rotate = function (out, a, rad) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8],
+
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+
+ out[0] = c * a00 + s * a10;
+ out[1] = c * a01 + s * a11;
+ out[2] = c * a02 + s * a12;
+
+ out[3] = c * a10 - s * a00;
+ out[4] = c * a11 - s * a01;
+ out[5] = c * a12 - s * a02;
+
+ out[6] = a20;
+ out[7] = a21;
+ out[8] = a22;
+ return out;
+ };
+
+ /**
+ * Scales the mat3 by the dimensions in the given vec2
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the matrix to rotate
+ * @param {vec2} v the vec2 to scale the matrix by
+ * @returns {mat3} out
+ **/
+ mat3.scale = function(out, a, v) {
+ var x = v[0], y = v[1];
+
+ out[0] = x * a[0];
+ out[1] = x * a[1];
+ out[2] = x * a[2];
+
+ out[3] = y * a[3];
+ out[4] = y * a[4];
+ out[5] = y * a[5];
+
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+ };
+
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.translate(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {vec2} v Translation vector
+ * @returns {mat3} out
+ */
+ mat3.fromTranslation = function(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = v[0];
+ out[7] = v[1];
+ out[8] = 1;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.rotate(dest, dest, rad);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+ mat3.fromRotation = function(out, rad) {
+ var s = Math.sin(rad), c = Math.cos(rad);
+
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+
+ out[3] = -s;
+ out[4] = c;
+ out[5] = 0;
+
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.scale(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {vec2} v Scaling vector
+ * @returns {mat3} out
+ */
+ mat3.fromScaling = function(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+
+ out[3] = 0;
+ out[4] = v[1];
+ out[5] = 0;
+
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+ }
+
+ /**
+ * Copies the values from a mat2d into a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat2d} a the matrix to copy
+ * @returns {mat3} out
+ **/
+ mat3.fromMat2d = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = 0;
+
+ out[3] = a[2];
+ out[4] = a[3];
+ out[5] = 0;
+
+ out[6] = a[4];
+ out[7] = a[5];
+ out[8] = 1;
+ return out;
+ };
+
+ /**
+ * Calculates a 3x3 matrix from the given quaternion
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {quat} q Quaternion to create matrix from
+ *
+ * @returns {mat3} out
+ */
+ mat3.fromQuat = function (out, q) {
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ yx = y * x2,
+ yy = y * y2,
+ zx = z * x2,
+ zy = z * y2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ out[0] = 1 - yy - zz;
+ out[3] = yx - wz;
+ out[6] = zx + wy;
+
+ out[1] = yx + wz;
+ out[4] = 1 - xx - zz;
+ out[7] = zy - wx;
+
+ out[2] = zx - wy;
+ out[5] = zy + wx;
+ out[8] = 1 - xx - yy;
+
+ return out;
+ };
+
+ /**
+ * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {mat4} a Mat4 to derive the normal matrix from
+ *
+ * @returns {mat3} out
+ */
+ mat3.normalFromMat4 = function (out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
+
+ b00 = a00 * a11 - a01 * a10,
+ b01 = a00 * a12 - a02 * a10,
+ b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11,
+ b04 = a01 * a13 - a03 * a11,
+ b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30,
+ b07 = a20 * a32 - a22 * a30,
+ b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31,
+ b10 = a21 * a33 - a23 * a31,
+ b11 = a22 * a33 - a23 * a32,
+
+ // Calculate the determinant
+ det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+
+ out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+
+ out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+
+ return out;
+ };
+
+ /**
+ * Returns a string representation of a mat3
+ *
+ * @param {mat3} mat matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+ mat3.str = function (a) {
+ return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
+ a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
+ a[6] + ', ' + a[7] + ', ' + a[8] + ')';
+ };
+
+ /**
+ * Returns Frobenius norm of a mat3
+ *
+ * @param {mat3} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+ mat3.frob = function (a) {
+ return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)))
+ };
+
+
+ module.exports = mat3;
+
+
+/***/ },
+/* 5 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ var glMatrix = __webpack_require__(1);
+
+ /**
+ * @class 4x4 Matrix
+ * @name mat4
+ */
+ var mat4 = {};
+
+ /**
+ * Creates a new identity mat4
+ *
+ * @returns {mat4} a new 4x4 matrix
+ */
+ mat4.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(16);
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ };
+
+ /**
+ * Creates a new mat4 initialized with values from an existing matrix
+ *
+ * @param {mat4} a matrix to clone
+ * @returns {mat4} a new 4x4 matrix
+ */
+ mat4.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(16);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+ };
+
+ /**
+ * Copy the values from one mat4 to another
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the source matrix
+ * @returns {mat4} out
+ */
+ mat4.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+ };
+
+ /**
+ * Set a mat4 to the identity matrix
+ *
+ * @param {mat4} out the receiving matrix
+ * @returns {mat4} out
+ */
+ mat4.identity = function(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ };
+
+ /**
+ * Transpose the values of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the source matrix
+ * @returns {mat4} out
+ */
+ mat4.transpose = function(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1], a02 = a[2], a03 = a[3],
+ a12 = a[6], a13 = a[7],
+ a23 = a[11];
+
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a01;
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a02;
+ out[9] = a12;
+ out[11] = a[14];
+ out[12] = a03;
+ out[13] = a13;
+ out[14] = a23;
+ } else {
+ out[0] = a[0];
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a[1];
+ out[5] = a[5];
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a[2];
+ out[9] = a[6];
+ out[10] = a[10];
+ out[11] = a[14];
+ out[12] = a[3];
+ out[13] = a[7];
+ out[14] = a[11];
+ out[15] = a[15];
+ }
+
+ return out;
+ };
+
+ /**
+ * Inverts a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the source matrix
+ * @returns {mat4} out
+ */
+ mat4.invert = function(out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
+
+ b00 = a00 * a11 - a01 * a10,
+ b01 = a00 * a12 - a02 * a10,
+ b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11,
+ b04 = a01 * a13 - a03 * a11,
+ b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30,
+ b07 = a20 * a32 - a22 * a30,
+ b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31,
+ b10 = a21 * a33 - a23 * a31,
+ b11 = a22 * a33 - a23 * a32,
+
+ // Calculate the determinant
+ det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
+ out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
+ out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
+ out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
+ out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
+ out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
+ out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
+
+ return out;
+ };
+
+ /**
+ * Calculates the adjugate of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the source matrix
+ * @returns {mat4} out
+ */
+ mat4.adjoint = function(out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
+
+ out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
+ out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
+ out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
+ out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
+ out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
+ out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
+ out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
+ out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
+ out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
+ out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
+ out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
+ out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
+ out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
+ out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
+ out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
+ out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
+ return out;
+ };
+
+ /**
+ * Calculates the determinant of a mat4
+ *
+ * @param {mat4} a the source matrix
+ * @returns {Number} determinant of a
+ */
+ mat4.determinant = function (a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
+
+ b00 = a00 * a11 - a01 * a10,
+ b01 = a00 * a12 - a02 * a10,
+ b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11,
+ b04 = a01 * a13 - a03 * a11,
+ b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30,
+ b07 = a20 * a32 - a22 * a30,
+ b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31,
+ b10 = a21 * a33 - a23 * a31,
+ b11 = a22 * a33 - a23 * a32;
+
+ // Calculate the determinant
+ return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+ };
+
+ /**
+ * Multiplies two mat4's
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the first operand
+ * @param {mat4} b the second operand
+ * @returns {mat4} out
+ */
+ mat4.multiply = function (out, a, b) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
+
+ // Cache only the current line of the second matrix
+ var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
+ out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
+ out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
+ out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
+ out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
+
+ b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
+ out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
+ out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
+ out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
+ out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
+
+ b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
+ out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
+ out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
+ out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
+ out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
+
+ b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
+ out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
+ out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
+ out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
+ out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
+ return out;
+ };
+
+ /**
+ * Alias for {@link mat4.multiply}
+ * @function
+ */
+ mat4.mul = mat4.multiply;
+
+ /**
+ * Translate a mat4 by the given vector
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to translate
+ * @param {vec3} v vector to translate by
+ * @returns {mat4} out
+ */
+ mat4.translate = function (out, a, v) {
+ var x = v[0], y = v[1], z = v[2],
+ a00, a01, a02, a03,
+ a10, a11, a12, a13,
+ a20, a21, a22, a23;
+
+ if (a === out) {
+ out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
+ out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
+ out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
+ out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
+ } else {
+ a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
+ a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
+ a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
+
+ out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
+ out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
+ out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
+
+ out[12] = a00 * x + a10 * y + a20 * z + a[12];
+ out[13] = a01 * x + a11 * y + a21 * z + a[13];
+ out[14] = a02 * x + a12 * y + a22 * z + a[14];
+ out[15] = a03 * x + a13 * y + a23 * z + a[15];
+ }
+
+ return out;
+ };
+
+ /**
+ * Scales the mat4 by the dimensions in the given vec3
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to scale
+ * @param {vec3} v the vec3 to scale the matrix by
+ * @returns {mat4} out
+ **/
+ mat4.scale = function(out, a, v) {
+ var x = v[0], y = v[1], z = v[2];
+
+ out[0] = a[0] * x;
+ out[1] = a[1] * x;
+ out[2] = a[2] * x;
+ out[3] = a[3] * x;
+ out[4] = a[4] * y;
+ out[5] = a[5] * y;
+ out[6] = a[6] * y;
+ out[7] = a[7] * y;
+ out[8] = a[8] * z;
+ out[9] = a[9] * z;
+ out[10] = a[10] * z;
+ out[11] = a[11] * z;
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+ };
+
+ /**
+ * Rotates a mat4 by the given angle around the given axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {vec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+ mat4.rotate = function (out, a, rad, axis) {
+ var x = axis[0], y = axis[1], z = axis[2],
+ len = Math.sqrt(x * x + y * y + z * z),
+ s, c, t,
+ a00, a01, a02, a03,
+ a10, a11, a12, a13,
+ a20, a21, a22, a23,
+ b00, b01, b02,
+ b10, b11, b12,
+ b20, b21, b22;
+
+ if (Math.abs(len) < glMatrix.EPSILON) { return null; }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c;
+
+ a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
+ a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
+ a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
+
+ // Construct the elements of the rotation matrix
+ b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
+ b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
+ b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
+
+ // Perform rotation-specific matrix multiplication
+ out[0] = a00 * b00 + a10 * b01 + a20 * b02;
+ out[1] = a01 * b00 + a11 * b01 + a21 * b02;
+ out[2] = a02 * b00 + a12 * b01 + a22 * b02;
+ out[3] = a03 * b00 + a13 * b01 + a23 * b02;
+ out[4] = a00 * b10 + a10 * b11 + a20 * b12;
+ out[5] = a01 * b10 + a11 * b11 + a21 * b12;
+ out[6] = a02 * b10 + a12 * b11 + a22 * b12;
+ out[7] = a03 * b10 + a13 * b11 + a23 * b12;
+ out[8] = a00 * b20 + a10 * b21 + a20 * b22;
+ out[9] = a01 * b20 + a11 * b21 + a21 * b22;
+ out[10] = a02 * b20 + a12 * b21 + a22 * b22;
+ out[11] = a03 * b20 + a13 * b21 + a23 * b22;
+
+ if (a !== out) { // If the source and destination differ, copy the unchanged last row
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+ return out;
+ };
+
+ /**
+ * Rotates a matrix by the given angle around the X axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ mat4.rotateX = function (out, a, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad),
+ a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7],
+ a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+
+ if (a !== out) { // If the source and destination differ, copy the unchanged rows
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ out[4] = a10 * c + a20 * s;
+ out[5] = a11 * c + a21 * s;
+ out[6] = a12 * c + a22 * s;
+ out[7] = a13 * c + a23 * s;
+ out[8] = a20 * c - a10 * s;
+ out[9] = a21 * c - a11 * s;
+ out[10] = a22 * c - a12 * s;
+ out[11] = a23 * c - a13 * s;
+ return out;
+ };
+
+ /**
+ * Rotates a matrix by the given angle around the Y axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ mat4.rotateY = function (out, a, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad),
+ a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3],
+ a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+
+ if (a !== out) { // If the source and destination differ, copy the unchanged rows
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ out[0] = a00 * c - a20 * s;
+ out[1] = a01 * c - a21 * s;
+ out[2] = a02 * c - a22 * s;
+ out[3] = a03 * c - a23 * s;
+ out[8] = a00 * s + a20 * c;
+ out[9] = a01 * s + a21 * c;
+ out[10] = a02 * s + a22 * c;
+ out[11] = a03 * s + a23 * c;
+ return out;
+ };
+
+ /**
+ * Rotates a matrix by the given angle around the Z axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ mat4.rotateZ = function (out, a, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad),
+ a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3],
+ a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+
+ if (a !== out) { // If the source and destination differ, copy the unchanged last row
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ out[0] = a00 * c + a10 * s;
+ out[1] = a01 * c + a11 * s;
+ out[2] = a02 * c + a12 * s;
+ out[3] = a03 * c + a13 * s;
+ out[4] = a10 * c - a00 * s;
+ out[5] = a11 * c - a01 * s;
+ out[6] = a12 * c - a02 * s;
+ out[7] = a13 * c - a03 * s;
+ return out;
+ };
+
+ /**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {vec3} v Translation vector
+ * @returns {mat4} out
+ */
+ mat4.fromTranslation = function(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.scale(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {vec3} v Scaling vector
+ * @returns {mat4} out
+ */
+ mat4.fromScaling = function(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = v[1];
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = v[2];
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from a given angle around a given axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotate(dest, dest, rad, axis);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {vec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+ mat4.fromRotation = function(out, rad, axis) {
+ var x = axis[0], y = axis[1], z = axis[2],
+ len = Math.sqrt(x * x + y * y + z * z),
+ s, c, t;
+
+ if (Math.abs(len) < glMatrix.EPSILON) { return null; }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c;
+
+ // Perform rotation-specific matrix multiplication
+ out[0] = x * x * t + c;
+ out[1] = y * x * t + z * s;
+ out[2] = z * x * t - y * s;
+ out[3] = 0;
+ out[4] = x * y * t - z * s;
+ out[5] = y * y * t + c;
+ out[6] = z * y * t + x * s;
+ out[7] = 0;
+ out[8] = x * z * t + y * s;
+ out[9] = y * z * t - x * s;
+ out[10] = z * z * t + c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from the given angle around the X axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateX(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ mat4.fromXRotation = function(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+
+ // Perform axis-specific matrix multiplication
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = c;
+ out[6] = s;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = -s;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from the given angle around the Y axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateY(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ mat4.fromYRotation = function(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+
+ // Perform axis-specific matrix multiplication
+ out[0] = c;
+ out[1] = 0;
+ out[2] = -s;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = s;
+ out[9] = 0;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from the given angle around the Z axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateZ(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+ mat4.fromZRotation = function(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+
+ // Perform axis-specific matrix multiplication
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = -s;
+ out[5] = c;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+ }
+
+ /**
+ * Creates a matrix from a quaternion rotation and vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * var quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {vec3} v Translation vector
+ * @returns {mat4} out
+ */
+ mat4.fromRotationTranslation = function (out, q, v) {
+ // Quaternion math
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ out[0] = 1 - (yy + zz);
+ out[1] = xy + wz;
+ out[2] = xz - wy;
+ out[3] = 0;
+ out[4] = xy - wz;
+ out[5] = 1 - (xx + zz);
+ out[6] = yz + wx;
+ out[7] = 0;
+ out[8] = xz + wy;
+ out[9] = yz - wx;
+ out[10] = 1 - (xx + yy);
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+
+ return out;
+ };
+
+ /**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * var quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {vec3} v Translation vector
+ * @param {vec3} s Scaling vector
+ * @returns {mat4} out
+ */
+ mat4.fromRotationTranslationScale = function (out, q, v, s) {
+ // Quaternion math
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2,
+ sx = s[0],
+ sy = s[1],
+ sz = s[2];
+
+ out[0] = (1 - (yy + zz)) * sx;
+ out[1] = (xy + wz) * sx;
+ out[2] = (xz - wy) * sx;
+ out[3] = 0;
+ out[4] = (xy - wz) * sy;
+ out[5] = (1 - (xx + zz)) * sy;
+ out[6] = (yz + wx) * sy;
+ out[7] = 0;
+ out[8] = (xz + wy) * sz;
+ out[9] = (yz - wx) * sz;
+ out[10] = (1 - (xx + yy)) * sz;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+
+ return out;
+ };
+
+ /**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * mat4.translate(dest, origin);
+ * var quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ * mat4.translate(dest, negativeOrigin);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {vec3} v Translation vector
+ * @param {vec3} s Scaling vector
+ * @param {vec3} o The origin vector around which to scale and rotate
+ * @returns {mat4} out
+ */
+ mat4.fromRotationTranslationScaleOrigin = function (out, q, v, s, o) {
+ // Quaternion math
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2,
+
+ sx = s[0],
+ sy = s[1],
+ sz = s[2],
+
+ ox = o[0],
+ oy = o[1],
+ oz = o[2];
+
+ out[0] = (1 - (yy + zz)) * sx;
+ out[1] = (xy + wz) * sx;
+ out[2] = (xz - wy) * sx;
+ out[3] = 0;
+ out[4] = (xy - wz) * sy;
+ out[5] = (1 - (xx + zz)) * sy;
+ out[6] = (yz + wx) * sy;
+ out[7] = 0;
+ out[8] = (xz + wy) * sz;
+ out[9] = (yz - wx) * sz;
+ out[10] = (1 - (xx + yy)) * sz;
+ out[11] = 0;
+ out[12] = v[0] + ox - (out[0] * ox + out[4] * oy + out[8] * oz);
+ out[13] = v[1] + oy - (out[1] * ox + out[5] * oy + out[9] * oz);
+ out[14] = v[2] + oz - (out[2] * ox + out[6] * oy + out[10] * oz);
+ out[15] = 1;
+
+ return out;
+ };
+
+ mat4.fromQuat = function (out, q) {
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ yx = y * x2,
+ yy = y * y2,
+ zx = z * x2,
+ zy = z * y2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ out[0] = 1 - yy - zz;
+ out[1] = yx + wz;
+ out[2] = zx - wy;
+ out[3] = 0;
+
+ out[4] = yx - wz;
+ out[5] = 1 - xx - zz;
+ out[6] = zy + wx;
+ out[7] = 0;
+
+ out[8] = zx + wy;
+ out[9] = zy - wx;
+ out[10] = 1 - xx - yy;
+ out[11] = 0;
+
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+
+ return out;
+ };
+
+ /**
+ * Generates a frustum matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Number} left Left bound of the frustum
+ * @param {Number} right Right bound of the frustum
+ * @param {Number} bottom Bottom bound of the frustum
+ * @param {Number} top Top bound of the frustum
+ * @param {Number} near Near bound of the frustum
+ * @param {Number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ mat4.frustum = function (out, left, right, bottom, top, near, far) {
+ var rl = 1 / (right - left),
+ tb = 1 / (top - bottom),
+ nf = 1 / (near - far);
+ out[0] = (near * 2) * rl;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = (near * 2) * tb;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = (right + left) * rl;
+ out[9] = (top + bottom) * tb;
+ out[10] = (far + near) * nf;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = (far * near * 2) * nf;
+ out[15] = 0;
+ return out;
+ };
+
+ /**
+ * Generates a perspective projection matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ mat4.perspective = function (out, fovy, aspect, near, far) {
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf = 1 / (near - far);
+ out[0] = f / aspect;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = f;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = (far + near) * nf;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = (2 * far * near) * nf;
+ out[15] = 0;
+ return out;
+ };
+
+ /**
+ * Generates a perspective projection matrix with the given field of view.
+ * This is primarily useful for generating projection matrices to be used
+ * with the still experiemental WebVR API.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ mat4.perspectiveFromFieldOfView = function (out, fov, near, far) {
+ var upTan = Math.tan(fov.upDegrees * Math.PI/180.0),
+ downTan = Math.tan(fov.downDegrees * Math.PI/180.0),
+ leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0),
+ rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0),
+ xScale = 2.0 / (leftTan + rightTan),
+ yScale = 2.0 / (upTan + downTan);
+
+ out[0] = xScale;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ out[3] = 0.0;
+ out[4] = 0.0;
+ out[5] = yScale;
+ out[6] = 0.0;
+ out[7] = 0.0;
+ out[8] = -((leftTan - rightTan) * xScale * 0.5);
+ out[9] = ((upTan - downTan) * yScale * 0.5);
+ out[10] = far / (near - far);
+ out[11] = -1.0;
+ out[12] = 0.0;
+ out[13] = 0.0;
+ out[14] = (far * near) / (near - far);
+ out[15] = 0.0;
+ return out;
+ }
+
+ /**
+ * Generates a orthogonal projection matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+ mat4.ortho = function (out, left, right, bottom, top, near, far) {
+ var lr = 1 / (left - right),
+ bt = 1 / (bottom - top),
+ nf = 1 / (near - far);
+ out[0] = -2 * lr;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = -2 * bt;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 2 * nf;
+ out[11] = 0;
+ out[12] = (left + right) * lr;
+ out[13] = (top + bottom) * bt;
+ out[14] = (far + near) * nf;
+ out[15] = 1;
+ return out;
+ };
+
+ /**
+ * Generates a look-at matrix with the given eye position, focal point, and up axis
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {vec3} eye Position of the viewer
+ * @param {vec3} center Point the viewer is looking at
+ * @param {vec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+ mat4.lookAt = function (out, eye, center, up) {
+ var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
+ eyex = eye[0],
+ eyey = eye[1],
+ eyez = eye[2],
+ upx = up[0],
+ upy = up[1],
+ upz = up[2],
+ centerx = center[0],
+ centery = center[1],
+ centerz = center[2];
+
+ if (Math.abs(eyex - centerx) < glMatrix.EPSILON &&
+ Math.abs(eyey - centery) < glMatrix.EPSILON &&
+ Math.abs(eyez - centerz) < glMatrix.EPSILON) {
+ return mat4.identity(out);
+ }
+
+ z0 = eyex - centerx;
+ z1 = eyey - centery;
+ z2 = eyez - centerz;
+
+ len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+
+ x0 = upy * z2 - upz * z1;
+ x1 = upz * z0 - upx * z2;
+ x2 = upx * z1 - upy * z0;
+ len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
+ if (!len) {
+ x0 = 0;
+ x1 = 0;
+ x2 = 0;
+ } else {
+ len = 1 / len;
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ y0 = z1 * x2 - z2 * x1;
+ y1 = z2 * x0 - z0 * x2;
+ y2 = z0 * x1 - z1 * x0;
+
+ len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
+ if (!len) {
+ y0 = 0;
+ y1 = 0;
+ y2 = 0;
+ } else {
+ len = 1 / len;
+ y0 *= len;
+ y1 *= len;
+ y2 *= len;
+ }
+
+ out[0] = x0;
+ out[1] = y0;
+ out[2] = z0;
+ out[3] = 0;
+ out[4] = x1;
+ out[5] = y1;
+ out[6] = z1;
+ out[7] = 0;
+ out[8] = x2;
+ out[9] = y2;
+ out[10] = z2;
+ out[11] = 0;
+ out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
+ out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
+ out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
+ out[15] = 1;
+
+ return out;
+ };
+
+ /**
+ * Returns a string representation of a mat4
+ *
+ * @param {mat4} mat matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+ mat4.str = function (a) {
+ return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
+ a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
+ a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
+ a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
+ };
+
+ /**
+ * Returns Frobenius norm of a mat4
+ *
+ * @param {mat4} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+ mat4.frob = function (a) {
+ return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
+ };
+
+
+ module.exports = mat4;
+
+
+/***/ },
+/* 6 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ var glMatrix = __webpack_require__(1);
+ var mat3 = __webpack_require__(4);
+ var vec3 = __webpack_require__(7);
+ var vec4 = __webpack_require__(8);
+
+ /**
+ * @class Quaternion
+ * @name quat
+ */
+ var quat = {};
+
+ /**
+ * Creates a new identity quat
+ *
+ * @returns {quat} a new quaternion
+ */
+ quat.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ };
+
+ /**
+ * Sets a quaternion to represent the shortest rotation from one
+ * vector to another.
+ *
+ * Both vectors are assumed to be unit length.
+ *
+ * @param {quat} out the receiving quaternion.
+ * @param {vec3} a the initial vector
+ * @param {vec3} b the destination vector
+ * @returns {quat} out
+ */
+ quat.rotationTo = (function() {
+ var tmpvec3 = vec3.create();
+ var xUnitVec3 = vec3.fromValues(1,0,0);
+ var yUnitVec3 = vec3.fromValues(0,1,0);
+
+ return function(out, a, b) {
+ var dot = vec3.dot(a, b);
+ if (dot < -0.999999) {
+ vec3.cross(tmpvec3, xUnitVec3, a);
+ if (vec3.length(tmpvec3) < 0.000001)
+ vec3.cross(tmpvec3, yUnitVec3, a);
+ vec3.normalize(tmpvec3, tmpvec3);
+ quat.setAxisAngle(out, tmpvec3, Math.PI);
+ return out;
+ } else if (dot > 0.999999) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ } else {
+ vec3.cross(tmpvec3, a, b);
+ out[0] = tmpvec3[0];
+ out[1] = tmpvec3[1];
+ out[2] = tmpvec3[2];
+ out[3] = 1 + dot;
+ return quat.normalize(out, out);
+ }
+ };
+ })();
+
+ /**
+ * Sets the specified quaternion with values corresponding to the given
+ * axes. Each axis is a vec3 and is expected to be unit length and
+ * perpendicular to all other specified axes.
+ *
+ * @param {vec3} view the vector representing the viewing direction
+ * @param {vec3} right the vector representing the local "right" direction
+ * @param {vec3} up the vector representing the local "up" direction
+ * @returns {quat} out
+ */
+ quat.setAxes = (function() {
+ var matr = mat3.create();
+
+ return function(out, view, right, up) {
+ matr[0] = right[0];
+ matr[3] = right[1];
+ matr[6] = right[2];
+
+ matr[1] = up[0];
+ matr[4] = up[1];
+ matr[7] = up[2];
+
+ matr[2] = -view[0];
+ matr[5] = -view[1];
+ matr[8] = -view[2];
+
+ return quat.normalize(out, quat.fromMat3(out, matr));
+ };
+ })();
+
+ /**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {quat} a quaternion to clone
+ * @returns {quat} a new quaternion
+ * @function
+ */
+ quat.clone = vec4.clone;
+
+ /**
+ * Creates a new quat initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} a new quaternion
+ * @function
+ */
+ quat.fromValues = vec4.fromValues;
+
+ /**
+ * Copy the values from one quat to another
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the source quaternion
+ * @returns {quat} out
+ * @function
+ */
+ quat.copy = vec4.copy;
+
+ /**
+ * Set the components of a quat to the given values
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} out
+ * @function
+ */
+ quat.set = vec4.set;
+
+ /**
+ * Set a quat to the identity quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+ quat.identity = function(out) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ };
+
+ /**
+ * Sets a quat from the given angle and rotation axis,
+ * then returns it.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {vec3} axis the axis around which to rotate
+ * @param {Number} rad the angle in radians
+ * @returns {quat} out
+ **/
+ quat.setAxisAngle = function(out, axis, rad) {
+ rad = rad * 0.5;
+ var s = Math.sin(rad);
+ out[0] = s * axis[0];
+ out[1] = s * axis[1];
+ out[2] = s * axis[2];
+ out[3] = Math.cos(rad);
+ return out;
+ };
+
+ /**
+ * Adds two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @returns {quat} out
+ * @function
+ */
+ quat.add = vec4.add;
+
+ /**
+ * Multiplies two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @returns {quat} out
+ */
+ quat.multiply = function(out, a, b) {
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ bx = b[0], by = b[1], bz = b[2], bw = b[3];
+
+ out[0] = ax * bw + aw * bx + ay * bz - az * by;
+ out[1] = ay * bw + aw * by + az * bx - ax * bz;
+ out[2] = az * bw + aw * bz + ax * by - ay * bx;
+ out[3] = aw * bw - ax * bx - ay * by - az * bz;
+ return out;
+ };
+
+ /**
+ * Alias for {@link quat.multiply}
+ * @function
+ */
+ quat.mul = quat.multiply;
+
+ /**
+ * Scales a quat by a scalar number
+ *
+ * @param {quat} out the receiving vector
+ * @param {quat} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {quat} out
+ * @function
+ */
+ quat.scale = vec4.scale;
+
+ /**
+ * Rotates a quaternion by the given angle about the X axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {quat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+ quat.rotateX = function (out, a, rad) {
+ rad *= 0.5;
+
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ bx = Math.sin(rad), bw = Math.cos(rad);
+
+ out[0] = ax * bw + aw * bx;
+ out[1] = ay * bw + az * bx;
+ out[2] = az * bw - ay * bx;
+ out[3] = aw * bw - ax * bx;
+ return out;
+ };
+
+ /**
+ * Rotates a quaternion by the given angle about the Y axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {quat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+ quat.rotateY = function (out, a, rad) {
+ rad *= 0.5;
+
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ by = Math.sin(rad), bw = Math.cos(rad);
+
+ out[0] = ax * bw - az * by;
+ out[1] = ay * bw + aw * by;
+ out[2] = az * bw + ax * by;
+ out[3] = aw * bw - ay * by;
+ return out;
+ };
+
+ /**
+ * Rotates a quaternion by the given angle about the Z axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {quat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+ quat.rotateZ = function (out, a, rad) {
+ rad *= 0.5;
+
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ bz = Math.sin(rad), bw = Math.cos(rad);
+
+ out[0] = ax * bw + ay * bz;
+ out[1] = ay * bw - ax * bz;
+ out[2] = az * bw + aw * bz;
+ out[3] = aw * bw - az * bz;
+ return out;
+ };
+
+ /**
+ * Calculates the W component of a quat from the X, Y, and Z components.
+ * Assumes that quaternion is 1 unit in length.
+ * Any existing W component will be ignored.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quat to calculate W component of
+ * @returns {quat} out
+ */
+ quat.calculateW = function (out, a) {
+ var x = a[0], y = a[1], z = a[2];
+
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
+ return out;
+ };
+
+ /**
+ * Calculates the dot product of two quat's
+ *
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+ quat.dot = vec4.dot;
+
+ /**
+ * Performs a linear interpolation between two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {quat} out
+ * @function
+ */
+ quat.lerp = vec4.lerp;
+
+ /**
+ * Performs a spherical linear interpolation between two quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {quat} out
+ */
+ quat.slerp = function (out, a, b, t) {
+ // benchmarks:
+ // http://jsperf.com/quaternion-slerp-implementations
+
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ bx = b[0], by = b[1], bz = b[2], bw = b[3];
+
+ var omega, cosom, sinom, scale0, scale1;
+
+ // calc cosine
+ cosom = ax * bx + ay * by + az * bz + aw * bw;
+ // adjust signs (if necessary)
+ if ( cosom < 0.0 ) {
+ cosom = -cosom;
+ bx = - bx;
+ by = - by;
+ bz = - bz;
+ bw = - bw;
+ }
+ // calculate coefficients
+ if ( (1.0 - cosom) > 0.000001 ) {
+ // standard case (slerp)
+ omega = Math.acos(cosom);
+ sinom = Math.sin(omega);
+ scale0 = Math.sin((1.0 - t) * omega) / sinom;
+ scale1 = Math.sin(t * omega) / sinom;
+ } else {
+ // "from" and "to" quaternions are very close
+ // ... so we can do a linear interpolation
+ scale0 = 1.0 - t;
+ scale1 = t;
+ }
+ // calculate final values
+ out[0] = scale0 * ax + scale1 * bx;
+ out[1] = scale0 * ay + scale1 * by;
+ out[2] = scale0 * az + scale1 * bz;
+ out[3] = scale0 * aw + scale1 * bw;
+
+ return out;
+ };
+
+ /**
+ * Performs a spherical linear interpolation with two control points
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @param {quat} c the third operand
+ * @param {quat} d the fourth operand
+ * @param {Number} t interpolation amount
+ * @returns {quat} out
+ */
+ quat.sqlerp = (function () {
+ var temp1 = quat.create();
+ var temp2 = quat.create();
+
+ return function (out, a, b, c, d, t) {
+ quat.slerp(temp1, a, d, t);
+ quat.slerp(temp2, b, c, t);
+ quat.slerp(out, temp1, temp2, 2 * t * (1 - t));
+
+ return out;
+ };
+ }());
+
+ /**
+ * Calculates the inverse of a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quat to calculate inverse of
+ * @returns {quat} out
+ */
+ quat.invert = function(out, a) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
+ dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
+ invDot = dot ? 1.0/dot : 0;
+
+ // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
+
+ out[0] = -a0*invDot;
+ out[1] = -a1*invDot;
+ out[2] = -a2*invDot;
+ out[3] = a3*invDot;
+ return out;
+ };
+
+ /**
+ * Calculates the conjugate of a quat
+ * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quat to calculate conjugate of
+ * @returns {quat} out
+ */
+ quat.conjugate = function (out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a[3];
+ return out;
+ };
+
+ /**
+ * Calculates the length of a quat
+ *
+ * @param {quat} a vector to calculate length of
+ * @returns {Number} length of a
+ * @function
+ */
+ quat.length = vec4.length;
+
+ /**
+ * Alias for {@link quat.length}
+ * @function
+ */
+ quat.len = quat.length;
+
+ /**
+ * Calculates the squared length of a quat
+ *
+ * @param {quat} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+ quat.squaredLength = vec4.squaredLength;
+
+ /**
+ * Alias for {@link quat.squaredLength}
+ * @function
+ */
+ quat.sqrLen = quat.squaredLength;
+
+ /**
+ * Normalize a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quaternion to normalize
+ * @returns {quat} out
+ * @function
+ */
+ quat.normalize = vec4.normalize;
+
+ /**
+ * Creates a quaternion from the given 3x3 rotation matrix.
+ *
+ * NOTE: The resultant quaternion is not normalized, so you should be sure
+ * to renormalize the quaternion yourself where necessary.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {mat3} m rotation matrix
+ * @returns {quat} out
+ * @function
+ */
+ quat.fromMat3 = function(out, m) {
+ // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
+ // article "Quaternion Calculus and Fast Animation".
+ var fTrace = m[0] + m[4] + m[8];
+ var fRoot;
+
+ if ( fTrace > 0.0 ) {
+ // |w| > 1/2, may as well choose w > 1/2
+ fRoot = Math.sqrt(fTrace + 1.0); // 2w
+ out[3] = 0.5 * fRoot;
+ fRoot = 0.5/fRoot; // 1/(4w)
+ out[0] = (m[5]-m[7])*fRoot;
+ out[1] = (m[6]-m[2])*fRoot;
+ out[2] = (m[1]-m[3])*fRoot;
+ } else {
+ // |w| <= 1/2
+ var i = 0;
+ if ( m[4] > m[0] )
+ i = 1;
+ if ( m[8] > m[i*3+i] )
+ i = 2;
+ var j = (i+1)%3;
+ var k = (i+2)%3;
+
+ fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
+ out[i] = 0.5 * fRoot;
+ fRoot = 0.5 / fRoot;
+ out[3] = (m[j*3+k] - m[k*3+j]) * fRoot;
+ out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
+ out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
+ }
+
+ return out;
+ };
+
+ /**
+ * Returns a string representation of a quatenion
+ *
+ * @param {quat} vec vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+ quat.str = function (a) {
+ return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
+ };
+
+ module.exports = quat;
+
+
+/***/ },
+/* 7 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ var glMatrix = __webpack_require__(1);
+
+ /**
+ * @class 3 Dimensional Vector
+ * @name vec3
+ */
+ var vec3 = {};
+
+ /**
+ * Creates a new, empty vec3
+ *
+ * @returns {vec3} a new 3D vector
+ */
+ vec3.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ return out;
+ };
+
+ /**
+ * Creates a new vec3 initialized with values from an existing vector
+ *
+ * @param {vec3} a vector to clone
+ * @returns {vec3} a new 3D vector
+ */
+ vec3.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+ };
+
+ /**
+ * Creates a new vec3 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} a new 3D vector
+ */
+ vec3.fromValues = function(x, y, z) {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+ };
+
+ /**
+ * Copy the values from one vec3 to another
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the source vector
+ * @returns {vec3} out
+ */
+ vec3.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+ };
+
+ /**
+ * Set the components of a vec3 to the given values
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} out
+ */
+ vec3.set = function(out, x, y, z) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+ };
+
+ /**
+ * Adds two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+ vec3.add = function(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ return out;
+ };
+
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+ vec3.subtract = function(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec3.subtract}
+ * @function
+ */
+ vec3.sub = vec3.subtract;
+
+ /**
+ * Multiplies two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+ vec3.multiply = function(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec3.multiply}
+ * @function
+ */
+ vec3.mul = vec3.multiply;
+
+ /**
+ * Divides two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+ vec3.divide = function(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec3.divide}
+ * @function
+ */
+ vec3.div = vec3.divide;
+
+ /**
+ * Returns the minimum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+ vec3.min = function(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ return out;
+ };
+
+ /**
+ * Returns the maximum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+ vec3.max = function(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ return out;
+ };
+
+ /**
+ * Scales a vec3 by a scalar number
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec3} out
+ */
+ vec3.scale = function(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ return out;
+ };
+
+ /**
+ * Adds two vec3's after scaling the second operand by a scalar value
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec3} out
+ */
+ vec3.scaleAndAdd = function(out, a, b, scale) {
+ out[0] = a[0] + (b[0] * scale);
+ out[1] = a[1] + (b[1] * scale);
+ out[2] = a[2] + (b[2] * scale);
+ return out;
+ };
+
+ /**
+ * Calculates the euclidian distance between two vec3's
+ *
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ vec3.distance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1],
+ z = b[2] - a[2];
+ return Math.sqrt(x*x + y*y + z*z);
+ };
+
+ /**
+ * Alias for {@link vec3.distance}
+ * @function
+ */
+ vec3.dist = vec3.distance;
+
+ /**
+ * Calculates the squared euclidian distance between two vec3's
+ *
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ vec3.squaredDistance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1],
+ z = b[2] - a[2];
+ return x*x + y*y + z*z;
+ };
+
+ /**
+ * Alias for {@link vec3.squaredDistance}
+ * @function
+ */
+ vec3.sqrDist = vec3.squaredDistance;
+
+ /**
+ * Calculates the length of a vec3
+ *
+ * @param {vec3} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ vec3.length = function (a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ return Math.sqrt(x*x + y*y + z*z);
+ };
+
+ /**
+ * Alias for {@link vec3.length}
+ * @function
+ */
+ vec3.len = vec3.length;
+
+ /**
+ * Calculates the squared length of a vec3
+ *
+ * @param {vec3} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ vec3.squaredLength = function (a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ return x*x + y*y + z*z;
+ };
+
+ /**
+ * Alias for {@link vec3.squaredLength}
+ * @function
+ */
+ vec3.sqrLen = vec3.squaredLength;
+
+ /**
+ * Negates the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a vector to negate
+ * @returns {vec3} out
+ */
+ vec3.negate = function(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ return out;
+ };
+
+ /**
+ * Returns the inverse of the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a vector to invert
+ * @returns {vec3} out
+ */
+ vec3.inverse = function(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ return out;
+ };
+
+ /**
+ * Normalize a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a vector to normalize
+ * @returns {vec3} out
+ */
+ vec3.normalize = function(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ var len = x*x + y*y + z*z;
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ out[2] = a[2] * len;
+ }
+ return out;
+ };
+
+ /**
+ * Calculates the dot product of two vec3's
+ *
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+ vec3.dot = function (a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ };
+
+ /**
+ * Computes the cross product of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+ vec3.cross = function(out, a, b) {
+ var ax = a[0], ay = a[1], az = a[2],
+ bx = b[0], by = b[1], bz = b[2];
+
+ out[0] = ay * bz - az * by;
+ out[1] = az * bx - ax * bz;
+ out[2] = ax * by - ay * bx;
+ return out;
+ };
+
+ /**
+ * Performs a linear interpolation between two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec3} out
+ */
+ vec3.lerp = function (out, a, b, t) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ return out;
+ };
+
+ /**
+ * Performs a hermite interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @param {vec3} c the third operand
+ * @param {vec3} d the fourth operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec3} out
+ */
+ vec3.hermite = function (out, a, b, c, d, t) {
+ var factorTimes2 = t * t,
+ factor1 = factorTimes2 * (2 * t - 3) + 1,
+ factor2 = factorTimes2 * (t - 2) + t,
+ factor3 = factorTimes2 * (t - 1),
+ factor4 = factorTimes2 * (3 - 2 * t);
+
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+
+ return out;
+ };
+
+ /**
+ * Performs a bezier interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @param {vec3} c the third operand
+ * @param {vec3} d the fourth operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec3} out
+ */
+ vec3.bezier = function (out, a, b, c, d, t) {
+ var inverseFactor = 1 - t,
+ inverseFactorTimesTwo = inverseFactor * inverseFactor,
+ factorTimes2 = t * t,
+ factor1 = inverseFactorTimesTwo * inverseFactor,
+ factor2 = 3 * t * inverseFactorTimesTwo,
+ factor3 = 3 * factorTimes2 * inverseFactor,
+ factor4 = factorTimes2 * t;
+
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+
+ return out;
+ };
+
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec3} out
+ */
+ vec3.random = function (out, scale) {
+ scale = scale || 1.0;
+
+ var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+ var z = (glMatrix.RANDOM() * 2.0) - 1.0;
+ var zScale = Math.sqrt(1.0-z*z) * scale;
+
+ out[0] = Math.cos(r) * zScale;
+ out[1] = Math.sin(r) * zScale;
+ out[2] = z * scale;
+ return out;
+ };
+
+ /**
+ * Transforms the vec3 with a mat4.
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the vector to transform
+ * @param {mat4} m matrix to transform with
+ * @returns {vec3} out
+ */
+ vec3.transformMat4 = function(out, a, m) {
+ var x = a[0], y = a[1], z = a[2],
+ w = m[3] * x + m[7] * y + m[11] * z + m[15];
+ w = w || 1.0;
+ out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
+ out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
+ out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
+ return out;
+ };
+
+ /**
+ * Transforms the vec3 with a mat3.
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the vector to transform
+ * @param {mat4} m the 3x3 matrix to transform with
+ * @returns {vec3} out
+ */
+ vec3.transformMat3 = function(out, a, m) {
+ var x = a[0], y = a[1], z = a[2];
+ out[0] = x * m[0] + y * m[3] + z * m[6];
+ out[1] = x * m[1] + y * m[4] + z * m[7];
+ out[2] = x * m[2] + y * m[5] + z * m[8];
+ return out;
+ };
+
+ /**
+ * Transforms the vec3 with a quat
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the vector to transform
+ * @param {quat} q quaternion to transform with
+ * @returns {vec3} out
+ */
+ vec3.transformQuat = function(out, a, q) {
+ // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
+
+ var x = a[0], y = a[1], z = a[2],
+ qx = q[0], qy = q[1], qz = q[2], qw = q[3],
+
+ // calculate quat * vec
+ ix = qw * x + qy * z - qz * y,
+ iy = qw * y + qz * x - qx * z,
+ iz = qw * z + qx * y - qy * x,
+ iw = -qx * x - qy * y - qz * z;
+
+ // calculate result * inverse quat
+ out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
+ out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
+ out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
+ return out;
+ };
+
+ /**
+ * Rotate a 3D vector around the x-axis
+ * @param {vec3} out The receiving vec3
+ * @param {vec3} a The vec3 point to rotate
+ * @param {vec3} b The origin of the rotation
+ * @param {Number} c The angle of rotation
+ * @returns {vec3} out
+ */
+ vec3.rotateX = function(out, a, b, c){
+ var p = [], r=[];
+ //Translate point to the origin
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2];
+
+ //perform rotation
+ r[0] = p[0];
+ r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c);
+ r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c);
+
+ //translate to correct position
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+
+ return out;
+ };
+
+ /**
+ * Rotate a 3D vector around the y-axis
+ * @param {vec3} out The receiving vec3
+ * @param {vec3} a The vec3 point to rotate
+ * @param {vec3} b The origin of the rotation
+ * @param {Number} c The angle of rotation
+ * @returns {vec3} out
+ */
+ vec3.rotateY = function(out, a, b, c){
+ var p = [], r=[];
+ //Translate point to the origin
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2];
+
+ //perform rotation
+ r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c);
+ r[1] = p[1];
+ r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c);
+
+ //translate to correct position
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+
+ return out;
+ };
+
+ /**
+ * Rotate a 3D vector around the z-axis
+ * @param {vec3} out The receiving vec3
+ * @param {vec3} a The vec3 point to rotate
+ * @param {vec3} b The origin of the rotation
+ * @param {Number} c The angle of rotation
+ * @returns {vec3} out
+ */
+ vec3.rotateZ = function(out, a, b, c){
+ var p = [], r=[];
+ //Translate point to the origin
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2];
+
+ //perform rotation
+ r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c);
+ r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c);
+ r[2] = p[2];
+
+ //translate to correct position
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+
+ return out;
+ };
+
+ /**
+ * Perform some operation over an array of vec3s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+ vec3.forEach = (function() {
+ var vec = vec3.create();
+
+ return function(a, stride, offset, count, fn, arg) {
+ var i, l;
+ if(!stride) {
+ stride = 3;
+ }
+
+ if(!offset) {
+ offset = 0;
+ }
+
+ if(count) {
+ l = Math.min((count * stride) + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for(i = offset; i < l; i += stride) {
+ vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
+ fn(vec, vec, arg);
+ a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
+ }
+
+ return a;
+ };
+ })();
+
+ /**
+ * Get the angle between two 3D vectors
+ * @param {vec3} a The first operand
+ * @param {vec3} b The second operand
+ * @returns {Number} The angle in radians
+ */
+ vec3.angle = function(a, b) {
+
+ var tempA = vec3.fromValues(a[0], a[1], a[2]);
+ var tempB = vec3.fromValues(b[0], b[1], b[2]);
+
+ vec3.normalize(tempA, tempA);
+ vec3.normalize(tempB, tempB);
+
+ var cosine = vec3.dot(tempA, tempB);
+
+ if(cosine > 1.0){
+ return 0;
+ } else {
+ return Math.acos(cosine);
+ }
+ };
+
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {vec3} vec vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+ vec3.str = function (a) {
+ return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
+ };
+
+ module.exports = vec3;
+
+
+/***/ },
+/* 8 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ var glMatrix = __webpack_require__(1);
+
+ /**
+ * @class 4 Dimensional Vector
+ * @name vec4
+ */
+ var vec4 = {};
+
+ /**
+ * Creates a new, empty vec4
+ *
+ * @returns {vec4} a new 4D vector
+ */
+ vec4.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ return out;
+ };
+
+ /**
+ * Creates a new vec4 initialized with values from an existing vector
+ *
+ * @param {vec4} a vector to clone
+ * @returns {vec4} a new 4D vector
+ */
+ vec4.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ };
+
+ /**
+ * Creates a new vec4 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} a new 4D vector
+ */
+ vec4.fromValues = function(x, y, z, w) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+ };
+
+ /**
+ * Copy the values from one vec4 to another
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the source vector
+ * @returns {vec4} out
+ */
+ vec4.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ };
+
+ /**
+ * Set the components of a vec4 to the given values
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} out
+ */
+ vec4.set = function(out, x, y, z, w) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+ };
+
+ /**
+ * Adds two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+ vec4.add = function(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ return out;
+ };
+
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+ vec4.subtract = function(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec4.subtract}
+ * @function
+ */
+ vec4.sub = vec4.subtract;
+
+ /**
+ * Multiplies two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+ vec4.multiply = function(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ out[3] = a[3] * b[3];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec4.multiply}
+ * @function
+ */
+ vec4.mul = vec4.multiply;
+
+ /**
+ * Divides two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+ vec4.divide = function(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ out[3] = a[3] / b[3];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec4.divide}
+ * @function
+ */
+ vec4.div = vec4.divide;
+
+ /**
+ * Returns the minimum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+ vec4.min = function(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ out[3] = Math.min(a[3], b[3]);
+ return out;
+ };
+
+ /**
+ * Returns the maximum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+ vec4.max = function(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ out[3] = Math.max(a[3], b[3]);
+ return out;
+ };
+
+ /**
+ * Scales a vec4 by a scalar number
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec4} out
+ */
+ vec4.scale = function(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ return out;
+ };
+
+ /**
+ * Adds two vec4's after scaling the second operand by a scalar value
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec4} out
+ */
+ vec4.scaleAndAdd = function(out, a, b, scale) {
+ out[0] = a[0] + (b[0] * scale);
+ out[1] = a[1] + (b[1] * scale);
+ out[2] = a[2] + (b[2] * scale);
+ out[3] = a[3] + (b[3] * scale);
+ return out;
+ };
+
+ /**
+ * Calculates the euclidian distance between two vec4's
+ *
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ vec4.distance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1],
+ z = b[2] - a[2],
+ w = b[3] - a[3];
+ return Math.sqrt(x*x + y*y + z*z + w*w);
+ };
+
+ /**
+ * Alias for {@link vec4.distance}
+ * @function
+ */
+ vec4.dist = vec4.distance;
+
+ /**
+ * Calculates the squared euclidian distance between two vec4's
+ *
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ vec4.squaredDistance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1],
+ z = b[2] - a[2],
+ w = b[3] - a[3];
+ return x*x + y*y + z*z + w*w;
+ };
+
+ /**
+ * Alias for {@link vec4.squaredDistance}
+ * @function
+ */
+ vec4.sqrDist = vec4.squaredDistance;
+
+ /**
+ * Calculates the length of a vec4
+ *
+ * @param {vec4} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ vec4.length = function (a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ return Math.sqrt(x*x + y*y + z*z + w*w);
+ };
+
+ /**
+ * Alias for {@link vec4.length}
+ * @function
+ */
+ vec4.len = vec4.length;
+
+ /**
+ * Calculates the squared length of a vec4
+ *
+ * @param {vec4} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ vec4.squaredLength = function (a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ return x*x + y*y + z*z + w*w;
+ };
+
+ /**
+ * Alias for {@link vec4.squaredLength}
+ * @function
+ */
+ vec4.sqrLen = vec4.squaredLength;
+
+ /**
+ * Negates the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a vector to negate
+ * @returns {vec4} out
+ */
+ vec4.negate = function(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = -a[3];
+ return out;
+ };
+
+ /**
+ * Returns the inverse of the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a vector to invert
+ * @returns {vec4} out
+ */
+ vec4.inverse = function(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ out[3] = 1.0 / a[3];
+ return out;
+ };
+
+ /**
+ * Normalize a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a vector to normalize
+ * @returns {vec4} out
+ */
+ vec4.normalize = function(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ var len = x*x + y*y + z*z + w*w;
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ out[0] = x * len;
+ out[1] = y * len;
+ out[2] = z * len;
+ out[3] = w * len;
+ }
+ return out;
+ };
+
+ /**
+ * Calculates the dot product of two vec4's
+ *
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+ vec4.dot = function (a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+ };
+
+ /**
+ * Performs a linear interpolation between two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec4} out
+ */
+ vec4.lerp = function (out, a, b, t) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ out[3] = aw + t * (b[3] - aw);
+ return out;
+ };
+
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec4} out
+ */
+ vec4.random = function (out, scale) {
+ scale = scale || 1.0;
+
+ //TODO: This is a pretty awful way of doing this. Find something better.
+ out[0] = glMatrix.RANDOM();
+ out[1] = glMatrix.RANDOM();
+ out[2] = glMatrix.RANDOM();
+ out[3] = glMatrix.RANDOM();
+ vec4.normalize(out, out);
+ vec4.scale(out, out, scale);
+ return out;
+ };
+
+ /**
+ * Transforms the vec4 with a mat4.
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the vector to transform
+ * @param {mat4} m matrix to transform with
+ * @returns {vec4} out
+ */
+ vec4.transformMat4 = function(out, a, m) {
+ var x = a[0], y = a[1], z = a[2], w = a[3];
+ out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
+ out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
+ out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
+ out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
+ return out;
+ };
+
+ /**
+ * Transforms the vec4 with a quat
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the vector to transform
+ * @param {quat} q quaternion to transform with
+ * @returns {vec4} out
+ */
+ vec4.transformQuat = function(out, a, q) {
+ var x = a[0], y = a[1], z = a[2],
+ qx = q[0], qy = q[1], qz = q[2], qw = q[3],
+
+ // calculate quat * vec
+ ix = qw * x + qy * z - qz * y,
+ iy = qw * y + qz * x - qx * z,
+ iz = qw * z + qx * y - qy * x,
+ iw = -qx * x - qy * y - qz * z;
+
+ // calculate result * inverse quat
+ out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
+ out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
+ out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
+ out[3] = a[3];
+ return out;
+ };
+
+ /**
+ * Perform some operation over an array of vec4s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+ vec4.forEach = (function() {
+ var vec = vec4.create();
+
+ return function(a, stride, offset, count, fn, arg) {
+ var i, l;
+ if(!stride) {
+ stride = 4;
+ }
+
+ if(!offset) {
+ offset = 0;
+ }
+
+ if(count) {
+ l = Math.min((count * stride) + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for(i = offset; i < l; i += stride) {
+ vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3];
+ fn(vec, vec, arg);
+ a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3];
+ }
+
+ return a;
+ };
+ })();
+
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {vec4} vec vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+ vec4.str = function (a) {
+ return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
+ };
+
+ module.exports = vec4;
+
+
+/***/ },
+/* 9 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. */
+
+ var glMatrix = __webpack_require__(1);
+
+ /**
+ * @class 2 Dimensional Vector
+ * @name vec2
+ */
+ var vec2 = {};
+
+ /**
+ * Creates a new, empty vec2
+ *
+ * @returns {vec2} a new 2D vector
+ */
+ vec2.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = 0;
+ out[1] = 0;
+ return out;
+ };
+
+ /**
+ * Creates a new vec2 initialized with values from an existing vector
+ *
+ * @param {vec2} a vector to clone
+ * @returns {vec2} a new 2D vector
+ */
+ vec2.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+ };
+
+ /**
+ * Creates a new vec2 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} a new 2D vector
+ */
+ vec2.fromValues = function(x, y) {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = x;
+ out[1] = y;
+ return out;
+ };
+
+ /**
+ * Copy the values from one vec2 to another
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the source vector
+ * @returns {vec2} out
+ */
+ vec2.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+ };
+
+ /**
+ * Set the components of a vec2 to the given values
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} out
+ */
+ vec2.set = function(out, x, y) {
+ out[0] = x;
+ out[1] = y;
+ return out;
+ };
+
+ /**
+ * Adds two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+ vec2.add = function(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ return out;
+ };
+
+ /**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+ vec2.subtract = function(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec2.subtract}
+ * @function
+ */
+ vec2.sub = vec2.subtract;
+
+ /**
+ * Multiplies two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+ vec2.multiply = function(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec2.multiply}
+ * @function
+ */
+ vec2.mul = vec2.multiply;
+
+ /**
+ * Divides two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+ vec2.divide = function(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ return out;
+ };
+
+ /**
+ * Alias for {@link vec2.divide}
+ * @function
+ */
+ vec2.div = vec2.divide;
+
+ /**
+ * Returns the minimum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+ vec2.min = function(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ return out;
+ };
+
+ /**
+ * Returns the maximum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+ vec2.max = function(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ return out;
+ };
+
+ /**
+ * Scales a vec2 by a scalar number
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec2} out
+ */
+ vec2.scale = function(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ return out;
+ };
+
+ /**
+ * Adds two vec2's after scaling the second operand by a scalar value
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec2} out
+ */
+ vec2.scaleAndAdd = function(out, a, b, scale) {
+ out[0] = a[0] + (b[0] * scale);
+ out[1] = a[1] + (b[1] * scale);
+ return out;
+ };
+
+ /**
+ * Calculates the euclidian distance between two vec2's
+ *
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {Number} distance between a and b
+ */
+ vec2.distance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return Math.sqrt(x*x + y*y);
+ };
+
+ /**
+ * Alias for {@link vec2.distance}
+ * @function
+ */
+ vec2.dist = vec2.distance;
+
+ /**
+ * Calculates the squared euclidian distance between two vec2's
+ *
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+ vec2.squaredDistance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return x*x + y*y;
+ };
+
+ /**
+ * Alias for {@link vec2.squaredDistance}
+ * @function
+ */
+ vec2.sqrDist = vec2.squaredDistance;
+
+ /**
+ * Calculates the length of a vec2
+ *
+ * @param {vec2} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+ vec2.length = function (a) {
+ var x = a[0],
+ y = a[1];
+ return Math.sqrt(x*x + y*y);
+ };
+
+ /**
+ * Alias for {@link vec2.length}
+ * @function
+ */
+ vec2.len = vec2.length;
+
+ /**
+ * Calculates the squared length of a vec2
+ *
+ * @param {vec2} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+ vec2.squaredLength = function (a) {
+ var x = a[0],
+ y = a[1];
+ return x*x + y*y;
+ };
+
+ /**
+ * Alias for {@link vec2.squaredLength}
+ * @function
+ */
+ vec2.sqrLen = vec2.squaredLength;
+
+ /**
+ * Negates the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to negate
+ * @returns {vec2} out
+ */
+ vec2.negate = function(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ return out;
+ };
+
+ /**
+ * Returns the inverse of the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to invert
+ * @returns {vec2} out
+ */
+ vec2.inverse = function(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ return out;
+ };
+
+ /**
+ * Normalize a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to normalize
+ * @returns {vec2} out
+ */
+ vec2.normalize = function(out, a) {
+ var x = a[0],
+ y = a[1];
+ var len = x*x + y*y;
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ }
+ return out;
+ };
+
+ /**
+ * Calculates the dot product of two vec2's
+ *
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+ vec2.dot = function (a, b) {
+ return a[0] * b[0] + a[1] * b[1];
+ };
+
+ /**
+ * Computes the cross product of two vec2's
+ * Note that the cross product must by definition produce a 3D vector
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec3} out
+ */
+ vec2.cross = function(out, a, b) {
+ var z = a[0] * b[1] - a[1] * b[0];
+ out[0] = out[1] = 0;
+ out[2] = z;
+ return out;
+ };
+
+ /**
+ * Performs a linear interpolation between two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec2} out
+ */
+ vec2.lerp = function (out, a, b, t) {
+ var ax = a[0],
+ ay = a[1];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ return out;
+ };
+
+ /**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec2} out
+ */
+ vec2.random = function (out, scale) {
+ scale = scale || 1.0;
+ var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+ out[0] = Math.cos(r) * scale;
+ out[1] = Math.sin(r) * scale;
+ return out;
+ };
+
+ /**
+ * Transforms the vec2 with a mat2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat2} m matrix to transform with
+ * @returns {vec2} out
+ */
+ vec2.transformMat2 = function(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y;
+ out[1] = m[1] * x + m[3] * y;
+ return out;
+ };
+
+ /**
+ * Transforms the vec2 with a mat2d
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat2d} m matrix to transform with
+ * @returns {vec2} out
+ */
+ vec2.transformMat2d = function(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y + m[4];
+ out[1] = m[1] * x + m[3] * y + m[5];
+ return out;
+ };
+
+ /**
+ * Transforms the vec2 with a mat3
+ * 3rd vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat3} m matrix to transform with
+ * @returns {vec2} out
+ */
+ vec2.transformMat3 = function(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[3] * y + m[6];
+ out[1] = m[1] * x + m[4] * y + m[7];
+ return out;
+ };
+
+ /**
+ * Transforms the vec2 with a mat4
+ * 3rd vector component is implicitly '0'
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat4} m matrix to transform with
+ * @returns {vec2} out
+ */
+ vec2.transformMat4 = function(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[4] * y + m[12];
+ out[1] = m[1] * x + m[5] * y + m[13];
+ return out;
+ };
+
+ /**
+ * Perform some operation over an array of vec2s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+ vec2.forEach = (function() {
+ var vec = vec2.create();
+
+ return function(a, stride, offset, count, fn, arg) {
+ var i, l;
+ if(!stride) {
+ stride = 2;
+ }
+
+ if(!offset) {
+ offset = 0;
+ }
+
+ if(count) {
+ l = Math.min((count * stride) + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for(i = offset; i < l; i += stride) {
+ vec[0] = a[i]; vec[1] = a[i+1];
+ fn(vec, vec, arg);
+ a[i] = vec[0]; a[i+1] = vec[1];
+ }
+
+ return a;
+ };
+ })();
+
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {vec2} vec vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+ vec2.str = function (a) {
+ return 'vec2(' + a[0] + ', ' + a[1] + ')';
+ };
+
+ module.exports = vec2;
+
+
+/***/ }
+/******/ ])
+});
+; \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/allclasses.tmpl b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/allclasses.tmpl
new file mode 100644
index 00000000000..e89da024d82
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/allclasses.tmpl
@@ -0,0 +1,14 @@
+<div align="center">{+new Link().toFile("index.html").withText("Class Index")+}
+| {+new Link().toFile("files.html").withText("File Index")+}</div>
+<hr />
+<h2>Classes</h2>
+<ul class="classList">
+ <for each="thisClass" in="data">
+ <li>{!
+ if (thisClass.alias != "_global_") {
+ output += new Link().toClass(thisClass.alias);
+ }
+ !}</li>
+ </for>
+</ul>
+<hr /> \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/allfiles.tmpl b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/allfiles.tmpl
new file mode 100644
index 00000000000..c6e40c9a4fe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/allfiles.tmpl
@@ -0,0 +1,65 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}" />
+ {! Link.base = ""; /* all generated links will be relative to this */ !}
+ <title>glMatrix - File Index</title>
+ <meta name="generator" content="JsDoc Toolkit" />
+
+ <style type="text/css">
+ {+include("static/default.css")+}
+ </style>
+ </head>
+
+ <body>
+ {+include("static/header.html")+}
+
+ <div class="wrapper">
+
+ <header id="index">
+ {+publish.classesIndex+}
+ </header>
+
+ <section id="content">
+ <h1 class="classTitle">File Index</h1>
+
+ <for each="item" in="data">
+ <div>
+ <h2>{+new Link().toSrc(item.alias).withText(item.name)+}</h2>
+ <if test="item.desc">{+resolveLinks(item.desc)+}</if>
+ <dl>
+ <if test="item.author">
+ <dt class="heading">Author:</dt>
+ <dd>{+item.author+}</dd>
+ </if>
+ <if test="item.version">
+ <dt class="heading">Version:</dt>
+ <dd>{+item.version+}</dd>
+ </if>
+ {! var locations = item.comment.getTag('location').map(function($){return $.toString().replace(/(^\$ ?| ?\$$)/g, '').replace(/^HeadURL: https:/g, 'http:');}) !}
+ <if test="locations.length">
+ <dt class="heading">Location:</dt>
+ <for each="location" in="locations">
+ <dd><a href="{+location+}">{+location+}</a></dd>
+ </for>
+ </if>
+ </dl>
+ </div>
+ <hr />
+ </for>
+
+ </section>
+
+ <footer>
+ <small>
+ <if test="JSDOC.opt.D.copyright">&copy;{+JSDOC.opt.D.copyright+}<br /></if>
+ Documentation generated by <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> {+JSDOC.VERSION+} on {+new Date()+}
+ <br/><br/>
+ Theme based on Github Pages template by <a href="https://github.com/orderedlist">orderedlist</a>
+ </small>
+ </footer>
+
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/class.tmpl b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/class.tmpl
new file mode 100644
index 00000000000..cb1d2b0f3d6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/class.tmpl
@@ -0,0 +1,340 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}" />
+ <meta name="generator" content="JsDoc Toolkit" />
+ {! Link.base = "../"; /* all generated links will be relative to this */ !}
+ <title>glMatrix - {+data.alias+}</title>
+
+ <style type="text/css">
+ {+include("static/default.css")+}
+ </style>
+ </head>
+
+ <body>
+<!-- ============================== header ================================= -->
+ <!-- begin static/header.html -->
+ {+include("static/header.html")+}
+ <!-- end static/header.html -->
+
+ <div class="wrapper">
+<!-- ============================== classes index ============================ -->
+ <header id="index">
+ <!-- begin publish.classesIndex -->
+ {+publish.classesIndex+}
+ <!-- end publish.classesIndex -->
+ </header>
+
+ <section id="content">
+<!-- ============================== class title ============================ -->
+ <h1 class="classTitle">
+ {!
+ var classType = "";
+
+ if (data.isBuiltin()) {
+ classType += "Built-In ";
+ }
+
+ if (data.isNamespace) {
+ if (data.is('FUNCTION')) {
+ classType += "Function ";
+ }
+ classType += "Namespace ";
+ }
+ else {
+ classType += "Class ";
+ }
+ !}
+ {+classType+}{+data.alias+}
+ </h1>
+
+<!-- ============================== class summary ========================== -->
+ <p class="description">
+ <if test="data.version"><br />Version
+ {+ data.version +}.<br />
+ </if>
+ <if test="data.augments.length"><br />Extends
+ {+
+ data.augments
+ .sort()
+ .map(
+ function($) { return new Link().toSymbol($); }
+ )
+ .join(", ")
+ +}.<br />
+ </if>
+
+ {+resolveLinks(data.classDesc)+}
+
+ <if test="data.desc">
+ <div class="description">{+resolveLinks(summarize(data.desc))+}</div>
+ </if>
+
+ <if test="!data.isBuiltin()">{# isn't defined in any file #}
+ <br /><i>Defined in: </i> {+new Link().toSrc(data.srcFile)+}.
+ </if>
+ </p>
+
+<!-- ============================== properties summary ===================== -->
+ <if test="data.properties.length">
+ {! var ownProperties = data.properties.filter(function($){return $.memberOf == data.alias && !$.isNamespace}).sort(makeSortby("name")); !}
+ <if test="ownProperties.length">
+ <table class="summaryTable" cellspacing="0" summary="A summary of the fields documented in the class {+data.alias+}.">
+ <caption>Field Summary</caption>
+ <thead>
+ <tr>
+ <th scope="col">Field Attributes</th>
+ <th scope="col">Field Name and Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <for each="member" in="ownProperties">
+ <tr>
+ <td class="attributes">{!
+ if (member.isPrivate) output += "&lt;private&gt; ";
+ if (member.isInner) output += "&lt;inner&gt; ";
+ if (member.isStatic) output += "&lt;static&gt; ";
+ if (member.isConstant) output += "&lt;constant&gt; ";
+ !}&nbsp;</td>
+ <td class="nameDescription">
+ <div class="fixedFont">
+ <if test="member.isStatic && member.memberOf != '_global_'">{+member.memberOf+}.</if><b>{+new Link().toSymbol(member.alias).withText(member.name)+}</b>
+ </div>
+ <div class="description">{+resolveLinks(summarize(member.desc))+}</div>
+ </td>
+ </tr>
+ </for>
+ </tbody>
+ </table>
+ </if>
+
+ <if test="data.inheritsFrom.length">
+ <dl class="inheritsList">
+ {!
+ var borrowedMembers = data.properties.filter(function($) {return $.memberOf != data.alias});
+
+ var contributers = [];
+ borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
+ for (var i = 0, l = contributers.length; i < l; i++) {
+ output +=
+ "<dt>Fields borrowed from class "+new Link().toSymbol(contributers[i])+": </dt>"
+ +
+ "<dd>" +
+ borrowedMembers
+ .filter(
+ function($) { return $.memberOf == contributers[i] }
+ )
+ .sort(makeSortby("name"))
+ .map(
+ function($) { return new Link().toSymbol($.alias).withText($.name) }
+ )
+ .join(", ")
+ +
+ "</dd>";
+ }
+ !}
+ </dl>
+ </if>
+ </if>
+
+<!-- ============================== methods summary ======================== -->
+ <if test="data.methods.length">
+ {! var ownMethods = data.methods.filter(function($){return $.memberOf == data.alias && !$.isNamespace}).sort(makeSortby("name")); !}
+ <if test="ownMethods.length">
+ <h2>Methods</h2>
+ <table class="summaryTable" cellspacing="0" summary="A summary of the methods documented in the class {+data.alias+}.">
+ <tbody>
+ <for each="member" in="ownMethods">
+ <tr>
+ <td class="nameDescription">
+ <code class="fixedFont"><if test="member.isStatic && member.memberOf != '_global_'">{+member.memberOf+}.</if><b>{+new Link().toSymbol(member.alias).withText(member.name.replace(/\^\d+$/, ''))+}</b>{+makeSignature(member.params)+}
+ </code>
+ <div class="description">{+resolveLinks(summarize(member.desc))+}</div>
+ </td>
+ </tr>
+ </for>
+ </tbody>
+ </table>
+ </if>
+ </if>
+
+<!-- ============================== field details ========================== -->
+ <if test="defined(ownProperties) && ownProperties.length">
+ <div class="sectionTitle">
+ Field Detail
+ </div>
+ <for each="member" in="ownProperties">
+ <a name="{+Link.symbolNameToLinkName(member)+}"> </a>
+ <div class="fixedFont">{!
+ if (member.isPrivate) output += "&lt;private&gt; ";
+ if (member.isInner) output += "&lt;inner&gt; ";
+ if (member.isStatic) output += "&lt;static&gt; ";
+ if (member.isConstant) output += "&lt;constant&gt; ";
+ !}
+
+ <if test="member.type"><span class="light">{{+new Link().toSymbol(member.type)+}}</span></if>
+ <if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name+}</b>
+
+ </div>
+ <div class="description">
+ {+resolveLinks(member.desc)+}
+ <if test="member.srcFile != data.srcFile">
+ <br />
+ <i>Defined in: </i> {+new Link().toSrc(member.srcFile)+}.
+ </if>
+ <if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
+ </div>
+
+ <if test="member.example.length">
+ <for each="example" in="member.example">
+ <pre class="code">{+example+}</pre>
+ </for>
+ </if>
+
+ <if test="member.deprecated">
+ <dl class="detailList">
+ <dt class="heading">Deprecated:</dt>
+ <dt>
+ {+ resolveLinks(member.deprecated) +}
+ </dt>
+ </dl>
+ </if>
+ <if test="member.since">
+ <dl class="detailList">
+ <dt class="heading">Since:</dt>
+ <dd>{+ member.since +}</dd>
+ </dl>
+ </if>
+ <if test="member.see.length">
+ <dl class="detailList">
+ <dt class="heading">See:</dt>
+ <for each="item" in="member.see">
+ <dd>{+ new Link().toSymbol(item) +}</dd>
+ </for>
+ </dl>
+ </if>
+ <if test="member.defaultValue">
+ <dl class="detailList">
+ <dt class="heading">Default Value:</dt>
+ <dd>
+ {+resolveLinks(member.defaultValue)+}
+ </dd>
+ </dl>
+ </if>
+
+ <if test="!$member_last"><hr /></if>
+ </for>
+ </if>
+
+<!-- ============================== method details ========================= -->
+ <if test="defined(ownMethods) && ownMethods.length">
+ <h2>Method Detail</h2>
+ <for each="member" in="ownMethods">
+ <a name="{+Link.symbolNameToLinkName(member)+}"> </a>
+ <h3 class="fixedFont">
+ <if test="member.type"><span class="light">{{+new Link().toSymbol(member.type)+}}</span></if>
+ <if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name.replace(/\^\d+$/, '')+}</b>{+makeSignature(member.params)+}
+ </h3>
+
+ <div style="margin-left: 1em;">
+ <p class="description">
+ {+resolveLinks(member.desc)+}
+ <if test="member.srcFile != data.srcFile">
+ <br />
+ <i>Defined in: </i> {+new Link().toSrc(member.srcFile)+}.
+ </if>
+ <if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
+ </p>
+
+ <if test="member.example.length">
+ <for each="example" in="member.example">
+ <pre class="code">{+example+}</pre>
+ </for>
+ </if>
+
+ <if test="member.params.length">
+ <dl class="detailList">
+ <dt class="heading">Parameters:</dt>
+ <for each="item" in="member.params">
+ <dt>
+ {+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}<b>{+item.name+}</b>
+ <if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
+ </dt>
+ <dd>{+resolveLinks(item.desc)+}</dd>
+ </for>
+ </dl>
+ </if>
+ <if test="member.deprecated">
+ <dl class="detailList">
+ <dt class="heading">Deprecated:</dt>
+ <dt>
+ {+ resolveLinks(member.deprecated) +}
+ </dt>
+ </dl>
+ </if>
+ <if test="member.since">
+ <dl class="detailList">
+ <dt class="heading">Since:</dt>
+ <dd>{+ member.since +}</dd>
+ </dl>
+ </dl>
+ </if>
+ <if test="member.exceptions.length">
+ <dl class="detailList">
+ <dt class="heading">Throws:</dt>
+ <for each="item" in="member.exceptions">
+ <dt>
+ {+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+} <b>{+item.name+}</b>
+ </dt>
+ <dd>{+resolveLinks(item.desc)+}</dd>
+ </for>
+ </dl>
+ </if>
+ <if test="member.returns.length">
+ <dl class="detailList">
+ <dt class="heading">Returns:</dt>
+ <for each="item" in="member.returns">
+ <dd>{+((item.type)?"<span class=\"light fixedFont\">{"+(new Link().toSymbol(item.type))+"}</span> " : "")+}{+resolveLinks(item.desc)+}</dd>
+ </for>
+ </dl>
+ </if>
+ <if test="member.requires.length">
+ <dl class="detailList">
+ <dt class="heading">Requires:</dt>
+ <for each="item" in="member.requires">
+ <dd>{+ resolveLinks(item) +}</dd>
+ </for>
+ </dl>
+ </if>
+ <if test="member.see.length">
+ <dl class="detailList">
+ <dt class="heading">See:</dt>
+ <for each="item" in="member.see">
+ <dd>{+ new Link().toSymbol(item) +}</dd>
+ </for>
+ </dl>
+ </if>
+
+ <if test="!$member_last"><hr /></if>
+ </div>
+ </for>
+ </if>
+
+ <hr />
+ </section>
+
+
+<!-- ============================== footer ================================= -->
+ <footer>
+ <small>
+ <if test="JSDOC.opt.D.copyright">&copy;{+JSDOC.opt.D.copyright+}<br /></if>
+ Documentation generated by <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> {+JSDOC.VERSION+} on {+new Date()+}
+ <br/><br/>
+ Theme based on Github Pages template by <a href="https://github.com/orderedlist">orderedlist</a>
+ </small>
+ </footer>
+
+ </div>
+ </body>
+</html>
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/index.tmpl b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/index.tmpl
new file mode 100644
index 00000000000..7c92dd40ccd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/index.tmpl
@@ -0,0 +1,52 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}" />
+
+ <title>glMatrix - Index</title>
+ <meta name="generator" content="JsDoc Toolkit" />
+
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+
+ <style type="text/css">
+ {+include("static/default.css")+}
+ </style>
+ </head>
+
+ <body>
+ {+include("static/header.html")+}
+
+ <div class="wrapper">
+
+ <header id="index">
+ {+publish.classesIndex+}
+ </header>
+
+ <section id="content">
+ <h1 class="classTitle">Class Index</h1>
+
+ <for each="thisClass" in="data">
+ <if test="thisClass.alias != '_global_'">
+ <div>
+ <h2>{+(new Link().toSymbol(thisClass.alias))+}</h2>
+ {+resolveLinks(summarize(thisClass.classDesc))+}
+ </div>
+ <hr />
+ </if>
+ </for>
+
+ </section>
+
+ <footer>
+ <small>
+ <if test="JSDOC.opt.D.copyright">&copy;{+JSDOC.opt.D.copyright+}<br /></if>
+ Documentation generated by <a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank">JsDoc Toolkit</a> {+JSDOC.VERSION+} on {+new Date()+}
+ <br/><br/>
+ Theme based on Github Pages template by <a href="https://github.com/orderedlist">orderedlist</a>
+ </small>
+ </footer>
+
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/publish.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/publish.js
new file mode 100644
index 00000000000..82c20045e94
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/publish.js
@@ -0,0 +1,201 @@
+/** Called automatically by JsDoc Toolkit. */
+function publish(symbolSet) {
+ publish.conf = { // trailing slash expected for dirs
+ ext: ".html",
+ outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/",
+ templatesDir: JSDOC.opt.t || SYS.pwd+"../jsdoc-template/",
+ symbolsDir: "symbols/",
+ srcDir: "symbols/src/"
+ };
+
+ // is source output is suppressed, just display the links to the source file
+ if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) {
+ Link.prototype._makeSrcLink = function(srcFilePath) {
+ return "&lt;"+srcFilePath+"&gt;";
+ }
+ }
+
+ // create the folders and subfolders to hold the output
+ IO.mkPath((publish.conf.outDir+"symbols/src").split("/"));
+
+ // used to allow Link to check the details of things being linked to
+ Link.symbolSet = symbolSet;
+
+ // create the required templates
+ try {
+ var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl");
+ var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl");
+ }
+ catch(e) {
+ print("Couldn't create the required templates: "+e);
+ quit();
+ }
+
+ // some ustility filters
+ function hasNoParent($) {return ($.memberOf == "")}
+ function isaFile($) {return ($.is("FILE"))}
+ function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)}
+
+ // get an array version of the symbolset, useful for filtering
+ var symbols = symbolSet.toArray();
+
+ // create the hilited source code files
+ var files = JSDOC.opt.srcFiles;
+ for (var i = 0, l = files.length; i < l; i++) {
+ var file = files[i];
+ var srcDir = publish.conf.outDir + "symbols/src/";
+ makeSrcFile(file, srcDir);
+ }
+
+ // get a list of all the classes in the symbolset
+ var classes = symbols.filter(isaClass).sort(makeSortby("alias"));
+
+ // create a filemap in which outfiles must be to be named uniquely, ignoring case
+ if (JSDOC.opt.u) {
+ var filemapCounts = {};
+ Link.filemap = {};
+ for (var i = 0, l = classes.length; i < l; i++) {
+ var lcAlias = classes[i].alias.toLowerCase();
+
+ if (!filemapCounts[lcAlias]) filemapCounts[lcAlias] = 1;
+ else filemapCounts[lcAlias]++;
+
+ Link.filemap[classes[i].alias] =
+ (filemapCounts[lcAlias] > 1)?
+ lcAlias+"_"+filemapCounts[lcAlias] : lcAlias;
+ }
+ }
+
+ // create a class index, displayed in the left-hand column of every class page
+ Link.base = "../";
+ publish.classesIndex = classesTemplate.process(classes); // kept in memory
+
+ // create each of the class pages
+ for (var i = 0, l = classes.length; i < l; i++) {
+ var symbol = classes[i];
+
+ symbol.events = symbol.getEvents(); // 1 order matters
+ symbol.methods = symbol.getMethods(); // 2
+
+ Link.currentSymbol= symbol;
+ var output = "";
+ output = classTemplate.process(symbol);
+
+ IO.saveFile(publish.conf.outDir+"symbols/", ((JSDOC.opt.u)? Link.filemap[symbol.alias] : symbol.alias) + publish.conf.ext, output);
+ }
+
+ // regenerate the index with different relative links, used in the index pages
+ Link.base = "";
+ publish.classesIndex = classesTemplate.process(classes);
+
+ // create the class index page
+ try {
+ var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl");
+ }
+ catch(e) { print(e.message); quit(); }
+
+ var classesIndex = classesindexTemplate.process(classes);
+ IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex);
+ classesindexTemplate = classesIndex = classes = null;
+
+ // create the file index page
+ try {
+ var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl");
+ }
+ catch(e) { print(e.message); quit(); }
+
+ var documentedFiles = symbols.filter(isaFile); // files that have file-level docs
+ var allFiles = []; // not all files have file-level docs, but we need to list every one
+
+ for (var i = 0; i < files.length; i++) {
+ allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */")));
+ }
+
+ for (var i = 0; i < documentedFiles.length; i++) {
+ var offset = files.indexOf(documentedFiles[i].alias);
+ allFiles[offset] = documentedFiles[i];
+ }
+
+ allFiles = allFiles.sort(makeSortby("name"));
+
+ // output the file index page
+ var filesIndex = fileindexTemplate.process(allFiles);
+ IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex);
+ fileindexTemplate = filesIndex = files = null;
+}
+
+
+/** Just the first sentence (up to a full stop). Should not break on dotted variable names. */
+function summarize(desc) {
+ if (typeof desc != "undefined")
+ return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc;
+}
+
+/** Make a symbol sorter by some attribute. */
+function makeSortby(attribute) {
+ return function(a, b) {
+ if (a[attribute] != undefined && b[attribute] != undefined) {
+ a = a[attribute].toLowerCase();
+ b = b[attribute].toLowerCase();
+ if (a < b) return -1;
+ if (a > b) return 1;
+ return 0;
+ }
+ }
+}
+
+/** Pull in the contents of an external file at the given path. */
+function include(path) {
+ var path = publish.conf.templatesDir+path;
+ return IO.readFile(path);
+}
+
+/** Turn a raw source file into a code-hilited page in the docs. */
+function makeSrcFile(path, srcDir, name) {
+ if (JSDOC.opt.s) return;
+
+ if (!name) {
+ name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_");
+ name = name.replace(/\:/g, "_");
+ }
+
+ var src = {path: path, name:name, charset: IO.encoding, hilited: ""};
+
+ if (defined(JSDOC.PluginManager)) {
+ JSDOC.PluginManager.run("onPublishSrc", src);
+ }
+
+ if (src.hilited) {
+ IO.saveFile(srcDir, name+publish.conf.ext, src.hilited);
+ }
+}
+
+/** Build output for displaying function parameters. */
+function makeSignature(params) {
+ if (!params) return "()";
+ var signature = "("
+ +
+ params.filter(
+ function($) {
+ return $.name.indexOf(".") == -1; // don't show config params in signature
+ }
+ ).map(
+ function($) {
+ return $.name;
+ }
+ ).join(", ")
+ +
+ ")";
+ return signature;
+}
+
+/** Find symbol {@link ...} strings in text and turn into html links */
+function resolveLinks(str, from) {
+ str = str.replace(/\{@link ([^} ]+) ?\}/gi,
+ function(match, symbolName) {
+ return new Link().toSymbol(symbolName);
+ }
+ );
+
+ return str;
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/default.css b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/default.css
new file mode 100644
index 00000000000..efcf7827133
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/default.css
@@ -0,0 +1,428 @@
+/* default.css */
+
+/*
+
+body
+{
+ font: 12px "Lucida Grande", Tahoma, Arial, Helvetica, sans-serif;
+ width: 800px;
+}
+
+.header
+{
+ clear: both;
+ background-color: #ccc;
+ padding: 8px;
+}
+
+h1
+{
+ font-size: 150%;
+ font-weight: bold;
+ padding: 0;
+ margin: 1em 0 0 .3em;
+}
+
+hr
+{
+ border: none 0;
+ border-top: 1px solid #7F8FB1;
+ height: 1px;
+}
+
+pre.code
+{
+ display: block;
+ padding: 8px;
+ border: 1px dashed #ccc;
+}
+
+#index
+{
+ margin-top: 24px;
+ float: left;
+ width: 160px;
+ position: absolute;
+ left: 8px;
+ background-color: #F3F3F3;
+ padding: 8px;
+}
+
+#content
+{
+ margin-left: 190px;
+ width: 600px;
+}
+
+.classList
+{
+ list-style-type: none;
+ padding: 0;
+ margin: 0 0 0 8px;
+ font-family: arial, sans-serif;
+ font-size: 1em;
+ overflow: auto;
+}
+
+.classList li
+{
+ padding: 0;
+ margin: 0 0 8px 0;
+}
+
+.summaryTable { width: 100%; }
+
+h1.classTitle
+{
+ font-size:170%;
+ line-height:130%;
+}
+
+h2 { font-size: 110%; }
+caption, div.sectionTitle
+{
+ background-color: #7F8FB1;
+ color: #fff;
+ font-size:130%;
+ text-align: left;
+ padding: 2px 6px 2px 6px;
+ border: 1px #7F8FB1 solid;
+}
+
+div.sectionTitle { margin-bottom: 8px; }
+.summaryTable thead { display: none; }
+
+.summaryTable td
+{
+ vertical-align: top;
+ padding: 4px;
+ border-bottom: 1px #7F8FB1 solid;
+ border-right: 1px #7F8FB1 solid;
+ border-left: 1px #7F8FB1 solid;
+}
+
+.summaryTable td.attributes
+{
+ border-left: 1px #7F8FB1 solid;
+ width: 140px;
+ text-align: right;
+}
+
+td.attributes, .fixedFont
+{
+ line-height: 15px;
+ color: #002EBE;
+ font-family: "Courier New",Courier,monospace;
+ font-size: 13px;
+}
+
+.summaryTable td.nameDescription
+{
+ text-align: left;
+ font-size: 13px;
+ line-height: 15px;
+}
+
+.summaryTable td.nameDescription, .description
+{
+ line-height: 15px;
+ padding: 4px;
+ padding-left: 4px;
+}
+
+.summaryTable { margin-bottom: 8px; }
+
+ul.inheritsList
+{
+ list-style: square;
+ margin-left: 20px;
+ padding-left: 0;
+}
+
+.detailList {
+ margin-left: 20px;
+ line-height: 15px;
+}
+.detailList dt { margin-left: 20px; }
+
+.detailList .heading
+{
+ font-weight: bold;
+ padding-bottom: 6px;
+ margin-left: 0;
+}
+
+.light, td.attributes, .light a:link, .light a:visited
+{
+ color: #777;
+ font-style: italic;
+}
+
+.fineprint
+{
+ text-align: right;
+ font-size: 10px;
+}
+
+*/
+
+/* Copied from styles.css generated by Github Pages */
+
+@import url(https://fonts.googleapis.com/css?family=Lato:300italic,700italic,300,700);
+
+body {
+ padding:50px;
+ font:14px/1.5 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color:#777;
+ font-weight:300;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color:#222;
+ margin:0 0 20px;
+}
+
+p, ul, ol, table, pre, dl {
+ margin:0 0 20px;
+}
+
+h1, h2, h3 {
+ line-height:1.1;
+}
+
+h1 {
+ font-size:28px;
+}
+
+h2 {
+ color:#393939;
+}
+
+h3, h4, h5, h6 {
+ color:#494949;
+}
+
+a {
+ color:#39c;
+ font-weight:400;
+ text-decoration:none;
+}
+
+a small {
+ font-size:11px;
+ color:#777;
+ margin-top:-0.6em;
+ display:block;
+}
+
+.wrapper {
+ width:860px;
+ margin:0 auto;
+}
+
+blockquote {
+ border-left:1px solid #e5e5e5;
+ margin:0;
+ padding:0 0 0 20px;
+ font-style:italic;
+}
+
+code, pre {
+ font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal;
+ color:#333;
+ font-size:12px;
+}
+
+pre {
+ padding:8px 15px;
+ background: #f8f8f8;
+ border-radius:5px;
+ border:1px solid #e5e5e5;
+ overflow-x: auto;
+}
+
+table {
+ width:100%;
+ border-collapse:collapse;
+}
+
+th, td {
+ text-align:left;
+ padding:5px 10px;
+ border-bottom:1px solid #e5e5e5;
+}
+
+dt {
+ color:#444;
+ font-weight:700;
+}
+
+th {
+ color:#444;
+}
+
+img {
+ max-width:100%;
+}
+
+header {
+ width:270px;
+ float:left;
+ position:fixed;
+}
+
+header ul {
+ list-style:none;
+ padding:0;
+
+ /*background: #eee;
+ background: -moz-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd));
+ background: -webkit-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
+ background: -o-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
+ background: -ms-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
+ background: linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
+
+ border-radius:5px;
+ border:1px solid #d2d2d2;
+ box-shadow:inset #fff 0 1px 0, inset rgba(0,0,0,0.03) 0 -1px 0;*/
+ width:270px;
+}
+
+header li {
+ width:89px;
+ /*float:left;
+ border-right:1px solid #d2d2d2;
+ height:40px;*/
+}
+
+header ul a {
+ line-height:1;
+ font-size:11px;
+ color:#999;
+ display:block;
+ text-align:center;
+ padding-top:6px;
+ /*height:40px;*/
+}
+
+strong {
+ color:#222;
+ font-weight:700;
+}
+
+/*header ul li + li {
+ width:88px;
+ border-left:1px solid #fff;
+}
+
+header ul li + li + li {
+ border-right:none;
+ width:89px;
+}*/
+
+header ul a strong {
+ font-size:14px;
+ display:block;
+ color:#222;
+}
+
+section {
+ width:500px;
+ float:right;
+ padding-bottom:50px;
+}
+
+small {
+ font-size:11px;
+}
+
+hr {
+ border:0;
+ background:#e5e5e5;
+ height:1px;
+ margin:0 0 20px;
+}
+
+footer {
+ width:270px;
+ float:left;
+ position:fixed;
+ bottom:50px;
+}
+
+@media print, screen and (max-width: 960px) {
+
+ div.wrapper {
+ width:auto;
+ margin:0;
+ }
+
+ header, section, footer {
+ float:none;
+ position:static;
+ width:auto;
+ }
+
+ header {
+ /*padding-right:320px;*/
+ padding: 0;
+ }
+
+ section {
+ border:1px solid #e5e5e5;
+ border-width:1px 0;
+ padding:20px 0;
+ margin:0 0 20px;
+ }
+
+ header a small {
+ display:inline;
+ }
+
+ header ul {
+ position:static;
+ height:40px;
+ width: auto;
+ }
+
+ header ul li {
+ float: left;
+ }
+}
+
+@media print, screen and (max-width: 720px) {
+ body {
+ word-wrap:break-word;
+ }
+
+ header {
+ padding:0;
+ }
+
+ header ul, header p.view {
+ position:static;
+ }
+
+ pre, code {
+ word-wrap:normal;
+ }
+}
+
+@media print, screen and (max-width: 480px) {
+ body {
+ padding:15px;
+ }
+
+ /*header ul {
+ display:none;
+ }*/
+}
+
+@media print {
+ body {
+ padding:0.4in;
+ font-size:12pt;
+ color:#444;
+ }
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/header.html b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/header.html
new file mode 100644
index 00000000000..353b735a4ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/header.html
@@ -0,0 +1,2 @@
+<div id="header">
+</div> \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/index.html b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/index.html
new file mode 100644
index 00000000000..d51d4efaa15
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/static/index.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <title>glMatrix Documentation</title>
+</head>
+<frameset cols="20%,80%">
+ <frame src="allclasses-frame.html" name="packageFrame" />
+ <frame src="splash.html" name="classFrame" />
+ <noframes>
+ <body>
+ <p>
+ This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+ </p>
+ </body>
+ </noframes>
+</frameset>
+</html> \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/symbol.tmpl b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/symbol.tmpl
new file mode 100644
index 00000000000..f8f4bd1f6f2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/jsdoc-template/symbol.tmpl
@@ -0,0 +1,35 @@
+<symbol alias="{+data.alias+}">
+ <name>{+data.name+}</name>
+ <memberOf>{+data.memberOf+}</memberOf>
+ <isStatic>{+data.isStatic+}</isStatic>
+ <isa>{+data.isa+}</isa>
+ <desc>{+data.desc+}</desc>
+ <classDesc>{+data.classDesc+}</classDesc>
+
+ <methods><for each="method" in="data.methods">
+ <method>
+ <name>{+method.name+}</name>
+ <memberOf>{+method.memberOf+}</memberOf>
+ <isStatic>{+method.isStatic+}</isStatic>
+ <desc>{+method.desc+}</desc>
+ <params><for each="param" in="method.params">
+ <param>
+ <type>{+param.type+}</type>
+ <name>{+param.name+}</name>
+ <desc>{+param.desc+}</desc>
+ <defaultValue>{+param.defaultValue+}</defaultValue>
+ </param></for>
+ </params>
+ </method></for>
+ </methods>
+
+ <properties><for each="property" in="data.properties">
+ <property>
+ <name>{+property.name+}</name>
+ <memberOf>{+property.memberOf+}</memberOf>
+ <isStatic>{+property.isStatic+}</isStatic>
+ <desc>{+property.desc+}</desc>
+ <type>{+property.type+}</type>
+ </property></for>
+ </properties>
+</symbol>
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/package.json b/chromium/third_party/catapult/tracing/third_party/gl-matrix/package.json
new file mode 100644
index 00000000000..f92ab7d2083
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "gl-matrix",
+ "description": "Javascript Matrix and Vector library for High Performance WebGL apps",
+ "version": "2.3.1",
+ "main": "src/gl-matrix.js",
+ "homepage": "http://glmatrix.net",
+ "bugs": {
+ "url": "https://github.com/toji/gl-matrix/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/toji/gl-matrix.git"
+ },
+ "contributors": [
+ {
+ "name": "Brandon Jones",
+ "email": "tojiro@gmail.com"
+ },
+ {
+ "name": "Colin MacKenzie IV",
+ "email": "sinisterchipmunk@gmail.com"
+ }
+ ],
+ "devDependencies": {
+ "jasmine-node": "1.2.2",
+ "node-libs-browser": "^0.5.2",
+ "webpack": "^1.9.10"
+ },
+ "license": "MIT"
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/common-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/common-spec.js
new file mode 100644
index 00000000000..b6649d09587
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/common-spec.js
@@ -0,0 +1,14 @@
+/*
+* common.js unit test
+*/
+
+describe("glMatrix", function(){
+ var result;
+
+ var glMatrix = require("../../src/gl-matrix/common.js");
+
+ describe("toRadian", function(){
+ beforeEach(function(){ result = glMatrix.toRadian(180); });
+ it("should return a value of 3.141592654(Math.PI)", function(){ expect(result).toBeEqualish(Math.PI); });
+ });
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat2-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat2-spec.js
new file mode 100644
index 00000000000..e901d332a6c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat2-spec.js
@@ -0,0 +1,210 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+describe("mat2", function() {
+ var mat2 = require("../../src/gl-matrix/mat2.js");
+
+ var out, matA, matB, identity, result;
+
+ beforeEach(function() {
+ matA = [1, 2,
+ 3, 4];
+
+ matB = [5, 6,
+ 7, 8];
+
+ out = [0, 0,
+ 0, 0];
+
+ identity = [1, 0,
+ 0, 1];
+ });
+
+ describe("create", function() {
+ beforeEach(function() { result = mat2.create(); });
+ it("should return a 4 element array initialized to a 2x2 identity matrix", function() { expect(result).toBeEqualish(identity); });
+ });
+
+ describe("clone", function() {
+ beforeEach(function() { result = mat2.clone(matA); });
+ it("should return a 4 element array initialized to the values in matA", function() { expect(result).toBeEqualish(matA); });
+ });
+
+ describe("copy", function() {
+ beforeEach(function() { result = mat2.copy(out, matA); });
+ it("should place values into out", function() { expect(out).toBeEqualish(matA); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("identity", function() {
+ beforeEach(function() { result = mat2.identity(out); });
+ it("should place values into out", function() { expect(result).toBeEqualish(identity); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("transpose", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2.transpose(out, matA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 3, 2, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2.transpose(matA, matA); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([1, 3, 2, 4]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("invert", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2.invert(out, matA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-2, 1, 1.5, -0.5]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2.invert(matA, matA); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([-2, 1, 1.5, -0.5]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("adjoint", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2.adjoint(out, matA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([4, -2, -3, 1]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2.adjoint(matA, matA); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([4, -2, -3, 1]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("determinant", function() {
+ beforeEach(function() { result = mat2.determinant(matA); });
+
+ it("should return the determinant", function() { expect(result).toEqual(-2); });
+ });
+
+ describe("multiply", function() {
+ it("should have an alias called 'mul'", function() { expect(mat2.mul).toEqual(mat2.multiply); });
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2.multiply(out, matA, matB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([23, 34, 31, 46]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify matB", function() { expect(matB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2.multiply(matA, matA, matB); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([23, 34, 31, 46]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ it("should not modify matB", function() { expect(matB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when matB is the output matrix", function() {
+ beforeEach(function() { result = mat2.multiply(matB, matA, matB); });
+
+ it("should place values into matB", function() { expect(matB).toBeEqualish([23, 34, 31, 46]); });
+ it("should return matB", function() { expect(result).toBe(matB); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("rotate", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2.rotate(out, matA, Math.PI * 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 4, -1, -2]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2.rotate(matA, matA, Math.PI * 0.5); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([3, 4, -1, -2]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("scale", function() {
+ var vecA;
+ beforeEach(function() { vecA = [2, 3]; });
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2.scale(out, matA, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 9, 12]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2.scale(matA, matA, vecA); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([2, 4, 9, 12]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("str", function() {
+ beforeEach(function() { result = mat2.str(matA); });
+
+ it("should return a string representation of the matrix", function() { expect(result).toEqual("mat2(1, 2, 3, 4)"); });
+ });
+
+ describe("frob", function() {
+ beforeEach(function() { result = mat2.frob(matA); });
+ it("should return the Frobenius Norm of the matrix", function() { expect(result).toEqual( Math.sqrt(Math.pow(1, 2) + Math.pow(2, 2) + Math.pow(3, 2) + Math.pow(4, 2))); });
+ });
+
+ describe("LDU", function() {
+ beforeEach(function() {L = mat2.create(); D = mat2.create(); U = mat2.create(); result = mat2.LDU(L, D, U, [4,3,6,3]);
+ L_result = mat2.create(); L_result[2] = 1.5;
+ D_result = mat2.create();
+ U_result = mat2.create();
+ U_result[0] = 4; U_result[1] = 3; U_result[3] = -1.5;
+ });
+ it("should return a lower triangular, a diagonal and an upper triangular matrix", function() {
+ expect(result[0]).toBeEqualish(L_result);
+ expect(result[1]).toBeEqualish(D_result);
+ expect(result[2]).toBeEqualish(U_result);
+ });
+ });
+
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat2d-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat2d-spec.js
new file mode 100644
index 00000000000..dda0ddd6bc2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat2d-spec.js
@@ -0,0 +1,194 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+describe("mat2d", function() {
+ var mat2d = require("../../src/gl-matrix/mat2d.js");
+
+ var out, matA, matB, identity, result;
+
+ beforeEach(function() {
+ matA = [1, 2,
+ 3, 4,
+ 5, 6];
+
+ oldA = [1, 2,
+ 3, 4,
+ 5, 6];
+
+ matB = [7, 8,
+ 9, 10,
+ 11, 12];
+
+ oldB = [7, 8,
+ 9, 10,
+ 11, 12];
+
+ out = [0, 0,
+ 0, 0,
+ 0, 0];
+
+ identity = [1, 0,
+ 0, 1,
+ 0, 0];
+ });
+
+ describe("create", function() {
+ beforeEach(function() { result = mat2d.create(); });
+ it("should return a 6 element array initialized to a 2x3 identity matrix", function() { expect(result).toBeEqualish(identity); });
+ });
+
+ describe("clone", function() {
+ beforeEach(function() { result = mat2d.clone(matA); });
+ it("should return a 6 element array initialized to the values in matA", function() { expect(result).toBeEqualish(matA); });
+ });
+
+ describe("copy", function() {
+ beforeEach(function() { result = mat2d.copy(out, matA); });
+ it("should place values into out", function() { expect(out).toBeEqualish(matA); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("identity", function() {
+ beforeEach(function() { result = mat2d.identity(out); });
+ it("should place values into out", function() { expect(result).toBeEqualish(identity); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("invert", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2d.invert(out, matA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([ -2, 1, 1.5, -0.5, 1, -2 ]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish(oldA); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2d.invert(matA, matA); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([ -2, 1, 1.5, -0.5, 1, -2 ]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("determinant", function() {
+ beforeEach(function() { result = mat2d.determinant(matA); });
+
+ it("should return the determinant", function() { expect(result).toEqual(-2); });
+ });
+
+ describe("multiply", function() {
+ it("should have an alias called 'mul'", function() { expect(mat2d.mul).toEqual(mat2d.multiply); });
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2d.multiply(out, matA, matB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([31, 46, 39, 58, 52, 76]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish(oldA); });
+ it("should not modify matB", function() { expect(matB).toBeEqualish(oldB); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2d.multiply(matA, matA, matB); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([31, 46, 39, 58, 52, 76]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ it("should not modify matB", function() { expect(matB).toBeEqualish(oldB); });
+ });
+
+ describe("when matB is the output matrix", function() {
+ beforeEach(function() { result = mat2d.multiply(matB, matA, matB); });
+
+ it("should place values into matB", function() { expect(matB).toBeEqualish([31, 46, 39, 58, 52, 76]); });
+ it("should return matB", function() { expect(result).toBe(matB); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish(oldA); });
+ });
+ });
+
+ describe("rotate", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2d.rotate(out, matA, Math.PI * 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 4, -1, -2, 5, 6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish(oldA); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2d.rotate(matA, matA, Math.PI * 0.5); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([3, 4, -1, -2, 5, 6]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("scale", function() {
+ var vecA;
+ beforeEach(function() { vecA = [2, 3]; });
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2d.scale(out, matA, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 9, 12, 5, 6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish(oldA); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2d.scale(matA, matA, vecA); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([2, 4, 9, 12, 5, 6]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("translate", function() {
+ var vecA;
+ beforeEach(function() { vecA = [2, 3]; });
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat2d.translate(out, matA, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4, 16, 22]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish(oldA); });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat2d.translate(matA, matA, vecA); });
+
+ it("should place values into matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4, 16, 22]); });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("str", function() {
+ beforeEach(function() { result = mat2d.str(matA); });
+
+ it("should return a string representation of the matrix", function() { expect(result).toEqual("mat2d(1, 2, 3, 4, 5, 6)"); });
+ });
+
+ describe("frob", function() {
+ beforeEach(function() { result = mat2d.frob(matA); });
+ it("should return the Frobenius Norm of the matrix", function() { expect(result).toEqual( Math.sqrt(Math.pow(1, 2) + Math.pow(2, 2) + Math.pow(3, 2) + Math.pow(4, 2) + Math.pow(5, 2) + Math.pow(6, 2) + 1)); });
+ });
+
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat3-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat3-spec.js
new file mode 100644
index 00000000000..9a9d55a71de
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat3-spec.js
@@ -0,0 +1,347 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+describe("mat3", function() {
+ var mat3 = require("../../src/gl-matrix/mat3.js");
+ var mat4 = require("../../src/gl-matrix/mat4.js");
+ var vec3 = require("../../src/gl-matrix/vec3.js");
+
+ var out, matA, matB, identity, result;
+
+ beforeEach(function() {
+ matA = [1, 0, 0,
+ 0, 1, 0,
+ 1, 2, 1];
+
+ matB = [1, 0, 0,
+ 0, 1, 0,
+ 3, 4, 1];
+
+ out = [0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0];
+
+ identity = [1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1];
+ });
+
+ describe("normalFromMat4", function() {
+ beforeEach(function() {
+ matA = [1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1];
+ result = mat3.normalFromMat4(out, matA);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ describe("with translation and rotation", function() {
+ beforeEach(function() {
+ mat4.translate(matA, matA, [2, 4, 6]);
+ mat4.rotateX(matA, matA, Math.PI / 2);
+
+ result = mat3.normalFromMat4(out, matA);
+ });
+
+ it("should give rotated matrix", function() {
+ expect(result).toBeEqualish([1, 0, 0,
+ 0, 0, 1,
+ 0,-1, 0]);
+ });
+
+ describe("and scale", function() {
+ beforeEach(function() {
+ mat4.scale(matA, matA, [2, 3, 4]);
+
+ result = mat3.normalFromMat4(out, matA);
+ });
+
+ it("should give rotated matrix", function() {
+ expect(result).toBeEqualish([0.5, 0, 0,
+ 0, 0, 0.333333,
+ 0, -0.25, 0]);
+ });
+ });
+ });
+ });
+
+ describe("fromQuat", function() {
+ var q;
+
+ beforeEach(function() {
+ q = [ 0, -0.7071067811865475, 0, 0.7071067811865475 ];
+ result = mat3.fromQuat(out, q);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("should rotate a vector the same as the original quat", function() {
+ expect(vec3.transformMat3([], [0,0,-1], out)).toBeEqualish(vec3.transformQuat([], [0,0,-1], q));
+ });
+
+ it("should rotate a vector by PI/2 radians", function() {
+ expect(vec3.transformMat3([], [0,0,-1], out)).toBeEqualish([1,0,0]);
+ });
+ });
+
+ describe("fromMat4", function() {
+ beforeEach(function() {
+ result = mat3.fromMat4(out, [ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9,10,11,12,
+ 13,14,15,16]); });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("should calculate proper mat3", function() {
+ expect(out).toBeEqualish([ 1, 2, 3,
+ 5, 6, 7,
+ 9,10,11]);
+ });
+ });
+
+ describe("scale", function() {
+ beforeEach(function() { result = mat3.scale(out, matA, [2,2]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it('should place proper values in out', function() {
+ expect(out).toBeEqualish([ 2, 0, 0,
+ 0, 2, 0,
+ 1, 2, 1 ]);
+ });
+ });
+
+ describe("create", function() {
+ beforeEach(function() { result = mat3.create(); });
+ it("should return a 9 element array initialized to a 3x3 identity matrix", function() { expect(result).toBeEqualish(identity); });
+ });
+
+ describe("clone", function() {
+ beforeEach(function() { result = mat3.clone(matA); });
+ it("should return a 9 element array initialized to the values in matA", function() { expect(result).toBeEqualish(matA); });
+ });
+
+ describe("copy", function() {
+ beforeEach(function() { result = mat3.copy(out, matA); });
+ it("should place values into out", function() { expect(out).toBeEqualish(matA); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("identity", function() {
+ beforeEach(function() { result = mat3.identity(out); });
+ it("should place values into out", function() { expect(result).toBeEqualish(identity); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("transpose", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat3.transpose(out, matA); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 1,
+ 0, 1, 2,
+ 0, 0, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 1, 2, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat3.transpose(matA, matA); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 1,
+ 0, 1, 2,
+ 0, 0, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("invert", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat3.invert(out, matA); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ -1, -2, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 1, 2, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat3.invert(matA, matA); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ -1, -2, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("adjoint", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat3.adjoint(out, matA); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ -1, -2, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 1, 2, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat3.adjoint(matA, matA); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ -1, -2, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("determinant", function() {
+ beforeEach(function() { result = mat3.determinant(matA); });
+
+ it("should return the determinant", function() { expect(result).toEqual(1); });
+ });
+
+ describe("multiply", function() {
+ it("should have an alias called 'mul'", function() { expect(mat3.mul).toEqual(mat3.multiply); });
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat3.multiply(out, matA, matB); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 4, 6, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 1, 2, 1
+ ]);
+ });
+ it("should not modify matB", function() {
+ expect(matB).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 3, 4, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat3.multiply(matA, matA, matB); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 4, 6, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ it("should not modify matB", function() {
+ expect(matB).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 3, 4, 1
+ ]);
+ });
+ });
+
+ describe("when matB is the output matrix", function() {
+ beforeEach(function() { result = mat3.multiply(matB, matA, matB); });
+
+ it("should place values into matB", function() {
+ expect(matB).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 4, 6, 1
+ ]);
+ });
+ it("should return matB", function() { expect(result).toBe(matB); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0,
+ 0, 1, 0,
+ 1, 2, 1
+ ]);
+ });
+ });
+ });
+
+ describe("str", function() {
+ beforeEach(function() { result = mat3.str(matA); });
+
+ it("should return a string representation of the matrix", function() { expect(result).toEqual("mat3(1, 0, 0, 0, 1, 0, 1, 2, 1)"); });
+ });
+
+ describe("frob", function() {
+ beforeEach(function() { result = mat3.frob(matA); });
+ it("should return the Frobenius Norm of the matrix", function() { expect(result).toEqual( Math.sqrt(Math.pow(1, 2) + Math.pow(0, 2) + Math.pow(0, 2) + Math.pow(0, 2) + Math.pow(1, 2) + Math.pow(0, 2) + Math.pow(1, 2) + Math.pow(2, 2) + Math.pow(1, 2))); });
+ });
+
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat4-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat4-spec.js
new file mode 100644
index 00000000000..9b7a67f4ee6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/mat4-spec.js
@@ -0,0 +1,637 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+describe("mat4", function() {
+ var mat4 = require("../../src/gl-matrix/mat4.js");
+ var vec3 = require("../../src/gl-matrix/vec3.js");
+
+ var out, matA, matB, identity, result;
+
+ beforeEach(function() {
+ // Attempting to portray a semi-realistic transform matrix
+ matA = [1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1];
+
+ matB = [1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 4, 5, 6, 1];
+
+ out = [0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0];
+
+ identity = [1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1];
+ });
+
+ describe("create", function() {
+ beforeEach(function() { result = mat4.create(); });
+ it("should return a 16 element array initialized to a 4x4 identity matrix", function() { expect(result).toBeEqualish(identity); });
+ });
+
+ describe("clone", function() {
+ beforeEach(function() { result = mat4.clone(matA); });
+ it("should return a 16 element array initialized to the values in matA", function() { expect(result).toBeEqualish(matA); });
+ });
+
+ describe("copy", function() {
+ beforeEach(function() { result = mat4.copy(out, matA); });
+ it("should place values into out", function() { expect(out).toBeEqualish(matA); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("identity", function() {
+ beforeEach(function() { result = mat4.identity(out); });
+ it("should place values into out", function() { expect(result).toBeEqualish(identity); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("transpose", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.transpose(out, matA); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0, 1,
+ 0, 1, 0, 2,
+ 0, 0, 1, 3,
+ 0, 0, 0, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.transpose(matA, matA); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 1,
+ 0, 1, 0, 2,
+ 0, 0, 1, 3,
+ 0, 0, 0, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("invert", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.invert(out, matA); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ -1, -2, -3, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.invert(matA, matA); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ -1, -2, -3, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("adjoint", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.adjoint(out, matA); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ -1, -2, -3, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.adjoint(matA, matA); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ -1, -2, -3, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("determinant", function() {
+ beforeEach(function() { result = mat4.determinant(matA); });
+
+ it("should return the determinant", function() { expect(result).toEqual(1); });
+ });
+
+ describe("multiply", function() {
+ it("should have an alias called 'mul'", function() { expect(mat4.mul).toEqual(mat4.multiply); });
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.multiply(out, matA, matB); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 5, 7, 9, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should not modify matB", function() {
+ expect(matB).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 4, 5, 6, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.multiply(matA, matA, matB); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 5, 7, 9, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ it("should not modify matB", function() {
+ expect(matB).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 4, 5, 6, 1
+ ]);
+ });
+ });
+
+ describe("when matB is the output matrix", function() {
+ beforeEach(function() { result = mat4.multiply(matB, matA, matB); });
+
+ it("should place values into matB", function() {
+ expect(matB).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 5, 7, 9, 1
+ ]);
+ });
+ it("should return matB", function() { expect(result).toBe(matB); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+ });
+
+ describe("translate", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.translate(out, matA, [4, 5, 6]); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 5, 7, 9, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.translate(matA, matA, [4, 5, 6]); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 5, 7, 9, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("scale", function() {
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.scale(out, matA, [4, 5, 6]); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 4, 0, 0, 0,
+ 0, 5, 0, 0,
+ 0, 0, 6, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.scale(matA, matA, [4, 5, 6]); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 4, 0, 0, 0,
+ 0, 5, 0, 0,
+ 0, 0, 6, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("rotate", function() {
+ var rad = Math.PI * 0.5;
+ var axis = [1, 0, 0];
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.rotate(out, matA, rad, axis); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, Math.cos(rad), Math.sin(rad), 0,
+ 0, -Math.sin(rad), Math.cos(rad), 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.rotate(matA, matA, rad, axis); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, Math.cos(rad), Math.sin(rad), 0,
+ 0, -Math.sin(rad), Math.cos(rad), 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("rotateX", function() {
+ var rad = Math.PI * 0.5;
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.rotateX(out, matA, rad); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, Math.cos(rad), Math.sin(rad), 0,
+ 0, -Math.sin(rad), Math.cos(rad), 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.rotateX(matA, matA, rad); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, Math.cos(rad), Math.sin(rad), 0,
+ 0, -Math.sin(rad), Math.cos(rad), 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("rotateY", function() {
+ var rad = Math.PI * 0.5;
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.rotateY(out, matA, rad); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ Math.cos(rad), 0, -Math.sin(rad), 0,
+ 0, 1, 0, 0,
+ Math.sin(rad), 0, Math.cos(rad), 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.rotateY(matA, matA, rad); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ Math.cos(rad), 0, -Math.sin(rad), 0,
+ 0, 1, 0, 0,
+ Math.sin(rad), 0, Math.cos(rad), 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ describe("rotateZ", function() {
+ var rad = Math.PI * 0.5;
+
+ describe("with a separate output matrix", function() {
+ beforeEach(function() { result = mat4.rotateZ(out, matA, rad); });
+
+ it("should place values into out", function() {
+ expect(out).toBeEqualish([
+ Math.cos(rad), Math.sin(rad), 0, 0,
+ -Math.sin(rad), Math.cos(rad), 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify matA", function() {
+ expect(matA).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ });
+
+ describe("when matA is the output matrix", function() {
+ beforeEach(function() { result = mat4.rotateZ(matA, matA, rad); });
+
+ it("should place values into matA", function() {
+ expect(matA).toBeEqualish([
+ Math.cos(rad), Math.sin(rad), 0, 0,
+ -Math.sin(rad), Math.cos(rad), 0, 0,
+ 0, 0, 1, 0,
+ 1, 2, 3, 1
+ ]);
+ });
+ it("should return matA", function() { expect(result).toBe(matA); });
+ });
+ });
+
+ // TODO: fromRotationTranslation
+
+ describe("frustum", function() {
+ beforeEach(function() { result = mat4.frustum(out, -1, 1, -1, 1, -1, 1); });
+ it("should place values into out", function() { expect(result).toBeEqualish([
+ -1, 0, 0, 0,
+ 0, -1, 0, 0,
+ 0, 0, 0, -1,
+ 0, 0, 1, 0
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("perspective", function() {
+ var fovy = Math.PI * 0.5;
+ beforeEach(function() { result = mat4.perspective(out, fovy, 1, 0, 1); });
+ it("should place values into out", function() { expect(result).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, -1, -1,
+ 0, 0, 0, 0
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+
+ describe("with nonzero near, 45deg fovy, and realistic aspect ratio", function() {
+ beforeEach(function() { result = mat4.perspective(out, 45 * Math.PI / 180.0, 640/480, 0.1, 200); });
+ it("should calculate correct matrix", function() { expect(result).toBeEqualish([
+ 1.81066, 0, 0, 0,
+ 0, 2.414213, 0, 0,
+ 0, 0, -1.001, -1,
+ 0, 0, -0.2001, 0
+ ]); });
+ });
+ });
+
+ describe("ortho", function() {
+ beforeEach(function() { result = mat4.ortho(out, -1, 1, -1, 1, -1, 1); });
+ it("should place values into out", function() { expect(result).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, -1, 0,
+ 0, 0, 0, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("lookAt", function() {
+ var eye = [0, 0, 1];
+ var center = [0, 0, -1];
+ var up = [0, 1, 0];
+ var view, up, right;
+
+ describe("looking down", function() {
+ beforeEach(function() {
+ view = [0, -1, 0];
+ up = [0, 0, -1];
+ right= [1, 0, 0];
+ result = mat4.lookAt(out, [0, 0, 0], view, up);
+ });
+
+ it("should transform view into local -Z", function() {
+ result = vec3.transformMat4([], view, out);
+ expect(result).toBeEqualish([0, 0, -1]);
+ });
+
+ it("should transform up into local +Y", function() {
+ result = vec3.transformMat4([], up, out);
+ expect(result).toBeEqualish([0, 1, 0]);
+ });
+
+ it("should transform right into local +X", function() {
+ result = vec3.transformMat4([], right, out);
+ expect(result).toBeEqualish([1, 0, 0]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("#74", function() {
+ beforeEach(function() {
+ mat4.lookAt(out, [0,2,0], [0,0.6,0], [0,0,-1]);
+ });
+
+ it("should transform a point 'above' into local +Y", function() {
+ result = vec3.transformMat4([], [0, 2, -1], out);
+ expect(result).toBeEqualish([0, 1, 0]);
+ });
+
+ it("should transform a point 'right of' into local +X", function() {
+ result = vec3.transformMat4([], [1, 2, 0], out);
+ expect(result).toBeEqualish([1, 0, 0]);
+ });
+
+ it("should transform a point 'in front of' into local -Z", function() {
+ result = vec3.transformMat4([], [0, 1, 0], out);
+ expect(result).toBeEqualish([0, 0, -1]);
+ });
+ });
+
+ beforeEach(function() {
+ eye = [0, 0, 1];
+ center = [0, 0, -1];
+ up = [0, 1, 0];
+ result = mat4.lookAt(out, eye, center, up);
+ });
+ it("should place values into out", function() { expect(result).toBeEqualish([
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, -1, 1
+ ]);
+ });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("str", function() {
+ beforeEach(function() { result = mat4.str(matA); });
+
+ it("should return a string representation of the matrix", function() { expect(result).toEqual("mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1)"); });
+ });
+
+ describe("frob", function() {
+ beforeEach(function() { result = mat4.frob(matA); });
+ it("should return the Frobenius Norm of the matrix", function() { expect(result).toEqual( Math.sqrt(Math.pow(1, 2) + Math.pow(1, 2) + Math.pow(1, 2) + Math.pow(1, 2) + Math.pow(1, 2) + Math.pow(2, 2) + Math.pow(3, 2) )); });
+ });
+
+
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/quat-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/quat-spec.js
new file mode 100644
index 00000000000..4f5150014d0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/quat-spec.js
@@ -0,0 +1,559 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+describe("quat", function() {
+ var mat3 = require("../../src/gl-matrix/mat3.js");
+ var mat4 = require("../../src/gl-matrix/mat4.js");
+ var quat = require("../../src/gl-matrix/quat.js");
+ var vec3 = require("../../src/gl-matrix/vec3.js");
+
+ var out, quatA, quatB, result;
+ var vec, id, deg90;
+
+ beforeEach(function() {
+ quatA = [1, 2, 3, 4];
+ quatB = [5, 6, 7, 8];
+ out = [0, 0, 0, 0];
+ vec = [1, 1, -1];
+ id = [0, 0, 0, 1];
+ deg90 = Math.PI / 2;
+ });
+
+ describe("slerp", function() {
+ describe("the normal case", function() {
+ beforeEach(function() {
+ result = quat.slerp(out, [0, 0, 0, 1], [0, 1, 0, 0], 0.5);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should calculate proper quat", function() {
+ expect(result).toBeEqualish([0, 0.707106, 0, 0.707106]);
+ });
+ });
+
+ describe("where a == b", function() {
+ beforeEach(function() {
+ result = quat.slerp(out, [0, 0, 0, 1], [0, 0, 0, 1], 0.5);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should calculate proper quat", function() {
+ expect(result).toBeEqualish([0, 0, 0, 1]);
+ });
+ });
+
+ describe("where theta == 180deg", function() {
+ beforeEach(function() {
+ quat.rotateX(quatA, [1,0,0,0], Math.PI); // 180 deg
+ result = quat.slerp(out, [1,0,0,0], quatA, 1);
+ });
+
+ it("should calculate proper quat", function() {
+ expect(result).toBeEqualish([0,0,0,-1]);
+ });
+ });
+
+ describe("where a == -b", function() {
+ beforeEach(function() {
+ result = quat.slerp(out, [1, 0, 0, 0], [-1, 0, 0, 0], 0.5);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should calculate proper quat", function() {
+ expect(result).toBeEqualish([1, 0, 0, 0]);
+ });
+ });
+ });
+
+ describe("rotateX", function() {
+ beforeEach(function() {
+ result = quat.rotateX(out, id, deg90);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should transform vec accordingly", function() {
+ vec3.transformQuat(vec, [0,0,-1], out);
+ expect(vec).toBeEqualish([0, 1, 0]);
+ });
+ });
+
+ describe("rotateY", function() {
+ beforeEach(function() {
+ result = quat.rotateY(out, id, deg90);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should transform vec accordingly", function() {
+ vec3.transformQuat(vec, [0,0,-1], out);
+ expect(vec).toBeEqualish([-1, 0, 0]);
+ });
+ });
+
+ describe("rotateZ", function() {
+ beforeEach(function() {
+ result = quat.rotateZ(out, id, deg90);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should transform vec accordingly", function() {
+ vec3.transformQuat(vec, [0,1,0], out);
+ expect(vec).toBeEqualish([-1, 0, 0]);
+ });
+ });
+
+ describe("fromMat3", function() {
+ var matr;
+
+ describe("legacy", function() {
+ beforeEach(function() {
+ matr = [ 1, 0, 0,
+ 0, 0, -1,
+ 0, 1, 0 ];
+ result = quat.fromMat3(out, matr);
+ });
+
+ it("should set dest to the correct value", function() {
+ expect(result).toBeEqualish([-0.707106, 0, 0, 0.707106]);
+ });
+ });
+
+ describe("where trace > 0", function() {
+ beforeEach(function() {
+ matr = [ 1, 0, 0,
+ 0, 0, -1,
+ 0, 1, 0 ];
+ result = quat.fromMat3(out, matr);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("should produce the correct transformation", function() {
+ expect(vec3.transformQuat([], [0,1,0], out)).toBeEqualish([0,0,-1]);
+ });
+ });
+
+ describe("from a normal matrix looking 'backward'", function() {
+ beforeEach(function() {
+ matr = mat3.create();
+ mat3.transpose(matr, mat3.invert(matr, mat3.fromMat4(matr, mat4.lookAt(mat4.create(), [0, 0, 0], [0, 0, 1], [0, 1, 0]))));
+ result = quat.fromMat3(out, matr);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("should produce the same transformation as the given matrix", function() {
+ expect(vec3.transformQuat([], [3,2,-1], quat.normalize(out, out))).toBeEqualish(vec3.transformMat3([], [3,2,-1], matr));
+ });
+ });
+
+ describe("from a normal matrix looking 'left' and 'upside down'", function() {
+ beforeEach(function() {
+ matr = mat3.create();
+ mat3.transpose(matr, mat3.invert(matr, mat3.fromMat4(matr, mat4.lookAt(mat4.create(), [0, 0, 0], [-1, 0, 0], [0, -1, 0]))));
+ result = quat.fromMat3(out, matr);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("should produce the same transformation as the given matrix", function() {
+ expect(vec3.transformQuat([], [3,2,-1], quat.normalize(out, out))).toBeEqualish(vec3.transformMat3([], [3,2,-1], matr));
+ });
+ });
+
+ describe("from a normal matrix looking 'upside down'", function() {
+ beforeEach(function() {
+ matr = mat3.create();
+ mat3.transpose(matr, mat3.invert(matr, mat3.fromMat4(matr, mat4.lookAt(mat4.create(), [0, 0, 0], [0, 0, -1], [0, -1, 0]))));
+ result = quat.fromMat3(out, matr);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("should produce the same transformation as the given matrix", function() {
+ expect(vec3.transformQuat([], [3,2,-1], quat.normalize(out, out))).toBeEqualish(vec3.transformMat3([], [3,2,-1], matr));
+ });
+ });
+ });
+
+ describe("setAxes", function() {
+ var r;
+ beforeEach(function() { r = vec3.create(); });
+
+ describe("looking left", function() {
+ var view, up, right;
+ beforeEach(function() {
+ view = [-1, 0, 0];
+ up = [ 0, 1, 0];
+ right= [ 0, 0,-1];
+ result = quat.setAxes([], view, right, up);
+ });
+
+ it("should transform local view into world left", function() {
+ r = vec3.transformQuat([], [0,0,-1], result);
+ expect(r).toBeEqualish([1, 0, 0]);
+ });
+
+ it("should transform local right into world front", function() {
+ r = vec3.transformQuat([], [1,0,0], result);
+ expect(r).toBeEqualish([0, 0, 1]);
+ });
+ });
+
+ describe("given opengl defaults", function() {
+ var view, up, right;
+ beforeEach(function() {
+ view = [0, 0, -1];
+ up = [0, 1, 0];
+ right= [1, 0, 0];
+ result = quat.setAxes(out, view, right, up);
+ });
+
+ it("should return out", function() {
+ expect(result).toBe(out);
+ });
+
+ it("should produce identity", function() {
+ expect(out).toBeEqualish([0, 0, 0, 1]);
+ });
+ });
+
+ describe("legacy example", function() {
+ var view, up, right;
+ beforeEach(function() {
+ right= [1, 0, 0];
+ up = [0, 0, 1];
+ view = [0, -1, 0];
+ result = quat.setAxes(out, view, right, up);
+ });
+
+ xit("should set correct quat4 values", function() {
+ expect(result).toBeEqualish([0.707106, 0, 0, 0.707106]);
+ });
+ });
+ });
+
+ describe("rotationTo", function() {
+ var r;
+ beforeEach(function() { r = vec3.create(); });
+
+ describe("at right angle", function() {
+ beforeEach(function() {
+ result = quat.rotationTo(out, [0, 1, 0], [1, 0, 0]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("should calculate proper quaternion", function() {
+ expect(out).toBeEqualish([0, 0, -0.707106, 0.707106]);
+ });
+ });
+
+ describe("when vectors are parallel", function() {
+ beforeEach(function() {
+ result = quat.rotationTo(out, [0, 1, 0], [0, 1, 0]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("multiplying A should produce B", function() {
+ expect(vec3.transformQuat(r, [0, 1, 0], out)).toBeEqualish([0, 1, 0]);
+ });
+ });
+
+ describe("when vectors are opposed X", function() {
+ beforeEach(function() {
+ result = quat.rotationTo(out, [1, 0, 0], [-1, 0, 0]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("multiplying A should produce B", function() {
+ expect(vec3.transformQuat(r, [1, 0, 0], out)).toBeEqualish([-1, 0, 0]);
+ });
+ });
+
+ describe("when vectors are opposed Y", function() {
+ beforeEach(function() {
+ result = quat.rotationTo(out, [0, 1, 0], [0, -1, 0]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("multiplying A should produce B", function() {
+ expect(vec3.transformQuat(r, [0, 1, 0], out)).toBeEqualish([0, -1, 0]);
+ });
+ });
+
+ describe("when vectors are opposed Z", function() {
+ beforeEach(function() {
+ result = quat.rotationTo(out, [0, 0, 1], [0, 0, -1]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+
+ it("multiplying A should produce B", function() {
+ expect(vec3.transformQuat(r, [0, 0, 1], out)).toBeEqualish([0, 0, -1]);
+ });
+ });
+ });
+
+ describe("create", function() {
+ beforeEach(function() { result = quat.create(); });
+ it("should return a 4 element array initialized to an identity quaternion", function() { expect(result).toBeEqualish([0, 0, 0, 1]); });
+ });
+
+ describe("clone", function() {
+ beforeEach(function() { result = quat.clone(quatA); });
+ it("should return a 4 element array initialized to the values in quatA", function() { expect(result).toBeEqualish(quatA); });
+ });
+
+ describe("fromValues", function() {
+ beforeEach(function() { result = quat.fromValues(1, 2, 3, 4); });
+ it("should return a 4 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("copy", function() {
+ beforeEach(function() { result = quat.copy(out, quatA); });
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("set", function() {
+ beforeEach(function() { result = quat.set(out, 1, 2, 3, 4); });
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("identity", function() {
+ beforeEach(function() { result = quat.identity(out); });
+ it("should place values into out", function() { expect(result).toBeEqualish([0, 0, 0, 1]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("setAxisAngle", function() {
+ beforeEach(function() { result = quat.setAxisAngle(out, [1, 0, 0], Math.PI * 0.5); });
+ it("should place values into out", function() { expect(result).toBeEqualish([0.707106, 0, 0, 0.707106]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("add", function() {
+ describe("with a separate output quaternion", function() {
+ beforeEach(function() { result = quat.add(out, quatA, quatB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([6, 8, 10, 12]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when quatA is the output quaternion", function() {
+ beforeEach(function() { result = quat.add(quatA, quatA, quatB); });
+
+ it("should place values into quatA", function() { expect(quatA).toBeEqualish([6, 8, 10, 12]); });
+ it("should return quatA", function() { expect(result).toBe(quatA); });
+ it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when quatB is the output quaternion", function() {
+ beforeEach(function() { result = quat.add(quatB, quatA, quatB); });
+
+ it("should place values into quatB", function() { expect(quatB).toBeEqualish([6, 8, 10, 12]); });
+ it("should return quatB", function() { expect(result).toBe(quatB); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("multiply", function() {
+ it("should have an alias called 'mul'", function() { expect(quat.mul).toEqual(quat.multiply); });
+
+ describe("with a separate output quaternion", function() {
+ beforeEach(function() { result = quat.multiply(out, quatA, quatB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([24, 48, 48, -6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when quatA is the output quaternion", function() {
+ beforeEach(function() { result = quat.multiply(quatA, quatA, quatB); });
+
+ it("should place values into quatA", function() { expect(quatA).toBeEqualish([24, 48, 48, -6]); });
+ it("should return quatA", function() { expect(result).toBe(quatA); });
+ it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when quatB is the output quaternion", function() {
+ beforeEach(function() { result = quat.multiply(quatB, quatA, quatB); });
+
+ it("should place values into quatB", function() { expect(quatB).toBeEqualish([24, 48, 48, -6]); });
+ it("should return quatB", function() { expect(result).toBe(quatB); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("scale", function() {
+ describe("with a separate output quaternion", function() {
+ beforeEach(function() { result = quat.scale(out, quatA, 2); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 6, 8]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when quatA is the output quaternion", function() {
+ beforeEach(function() { result = quat.scale(quatA, quatA, 2); });
+
+ it("should place values into quatA", function() { expect(quatA).toBeEqualish([2, 4, 6, 8]); });
+ it("should return quatA", function() { expect(result).toBe(quatA); });
+ });
+ });
+
+ describe("length", function() {
+ it("should have an alias called 'len'", function() { expect(quat.len).toEqual(quat.length); });
+
+ beforeEach(function() { result = quat.length(quatA); });
+
+ it("should return the length", function() { expect(result).toBeCloseTo(5.477225); });
+ });
+
+ describe("squaredLength", function() {
+ it("should have an alias called 'sqrLen'", function() { expect(quat.sqrLen).toEqual(quat.squaredLength); });
+
+ beforeEach(function() { result = quat.squaredLength(quatA); });
+
+ it("should return the squared length", function() { expect(result).toEqual(30); });
+ });
+
+ describe("normalize", function() {
+ beforeEach(function() { quatA = [5, 0, 0, 0]; });
+
+ describe("with a separate output quaternion", function() {
+ beforeEach(function() { result = quat.normalize(out, quatA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 0, 0, 0]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([5, 0, 0, 0]); });
+ });
+
+ describe("when quatA is the output quaternion", function() {
+ beforeEach(function() { result = quat.normalize(quatA, quatA); });
+
+ it("should place values into quatA", function() { expect(quatA).toBeEqualish([1, 0, 0, 0]); });
+ it("should return quatA", function() { expect(result).toBe(quatA); });
+ });
+ });
+
+ describe("lerp", function() {
+ describe("with a separate output quaternion", function() {
+ beforeEach(function() { result = quat.lerp(out, quatA, quatB, 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 4, 5, 6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when quatA is the output quaternion", function() {
+ beforeEach(function() { result = quat.lerp(quatA, quatA, quatB, 0.5); });
+
+ it("should place values into quatA", function() { expect(quatA).toBeEqualish([3, 4, 5, 6]); });
+ it("should return quatA", function() { expect(result).toBe(quatA); });
+ it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when quatB is the output quaternion", function() {
+ beforeEach(function() { result = quat.lerp(quatB, quatA, quatB, 0.5); });
+
+ it("should place values into quatB", function() { expect(quatB).toBeEqualish([3, 4, 5, 6]); });
+ it("should return quatB", function() { expect(result).toBe(quatB); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ /*describe("slerp", function() {
+ describe("with a separate output quaternion", function() {
+ beforeEach(function() { result = quat.slerp(out, quatA, quatB, 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 4, 5, 6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when quatA is the output quaternion", function() {
+ beforeEach(function() { result = quat.slerp(quatA, quatA, quatB, 0.5); });
+
+ it("should place values into quatA", function() { expect(quatA).toBeEqualish([3, 4, 5, 6]); });
+ it("should return quatA", function() { expect(result).toBe(quatA); });
+ it("should not modify quatB", function() { expect(quatB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when quatB is the output quaternion", function() {
+ beforeEach(function() { result = quat.slerp(quatB, quatA, quatB, 0.5); });
+
+ it("should place values into quatB", function() { expect(quatB).toBeEqualish([3, 4, 5, 6]); });
+ it("should return quatB", function() { expect(result).toBe(quatB); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });*/
+
+ // TODO: slerp, calcuateW, rotateX, rotateY, rotateZ
+
+ describe("invert", function() {
+ describe("with a separate output quaternion", function() {
+ beforeEach(function() { result = quat.invert(out, quatA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-0.033333, -0.066666, -0.1, 0.133333]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when quatA is the output quaternion", function() {
+ beforeEach(function() { result = quat.invert(quatA, quatA); });
+
+ it("should place values into quatA", function() { expect(quatA).toBeEqualish([-0.033333, -0.066666, -0.1, 0.133333]); });
+ it("should return quatA", function() { expect(result).toBe(quatA); });
+ });
+ });
+
+ describe("conjugate", function() {
+ describe("with a separate output quaternion", function() {
+ beforeEach(function() { result = quat.conjugate(out, quatA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-1, -2, -3, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify quatA", function() { expect(quatA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when quatA is the output quaternion", function() {
+ beforeEach(function() { result = quat.conjugate(quatA, quatA); });
+
+ it("should place values into quatA", function() { expect(quatA).toBeEqualish([-1, -2, -3, 4]); });
+ it("should return quatA", function() { expect(result).toBe(quatA); });
+ });
+ });
+
+ describe("str", function() {
+ beforeEach(function() { result = quat.str(quatA); });
+
+ it("should return a string representation of the quaternion", function() { expect(result).toEqual("quat(1, 2, 3, 4)"); });
+ });
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec2-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec2-spec.js
new file mode 100644
index 00000000000..254c52739c3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec2-spec.js
@@ -0,0 +1,549 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+describe("vec2", function() {
+ var vec2 = require("../../src/gl-matrix/vec2.js");
+
+ var out, vecA, vecB, result;
+
+ beforeEach(function() { vecA = [1, 2]; vecB = [3, 4]; out = [0, 0]; });
+
+ describe("create", function() {
+ beforeEach(function() { result = vec2.create(); });
+ it("should return a 2 element array initialized to 0s", function() { expect(result).toBeEqualish([0, 0]); });
+ });
+
+ describe("clone", function() {
+ beforeEach(function() { result = vec2.clone(vecA); });
+ it("should return a 2 element array initialized to the values in vecA", function() { expect(result).toBeEqualish(vecA); });
+ });
+
+ describe("fromValues", function() {
+ beforeEach(function() { result = vec2.fromValues(1, 2); });
+ it("should return a 2 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2]); });
+ });
+
+ describe("copy", function() {
+ beforeEach(function() { result = vec2.copy(out, vecA); });
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("set", function() {
+ beforeEach(function() { result = vec2.set(out, 1, 2); });
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("add", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.add(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([4, 6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.add(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([4, 6]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec2.add(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([4, 6]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("subtract", function() {
+ it("should have an alias called 'sub'", function() { expect(vec2.sub).toEqual(vec2.subtract); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.subtract(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-2, -2]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.subtract(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([-2, -2]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec2.subtract(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([-2, -2]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("multiply", function() {
+ it("should have an alias called 'mul'", function() { expect(vec2.mul).toEqual(vec2.multiply); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.multiply(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 8]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.multiply(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 8]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec2.multiply(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 8]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("divide", function() {
+ it("should have an alias called 'div'", function() { expect(vec2.div).toEqual(vec2.divide); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.divide(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([0.3333333, 0.5]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.divide(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([0.3333333, 0.5]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec2.divide(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([0.3333333, 0.5]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("min", function() {
+ beforeEach(function() { vecA = [1, 4]; vecB = [3, 2]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.min(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 2]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.min(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 2]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec2.min(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([1, 2]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 4]); });
+ });
+ });
+
+ describe("max", function() {
+ beforeEach(function() { vecA = [1, 4]; vecB = [3, 2]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.max(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 2]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.max(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 4]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 2]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec2.max(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 4]); });
+ });
+ });
+
+ describe("scale", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.scale(out, vecA, 2); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.scale(vecA, vecA, 2); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([2, 4]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("scaleAndAdd", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.scaleAndAdd(out, vecA, vecB, 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2.5, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.scaleAndAdd(vecA, vecA, vecB, 0.5); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([2.5, 4]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec2.scaleAndAdd(vecB, vecA, vecB, 0.5); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([2.5, 4]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("distance", function() {
+ it("should have an alias called 'dist'", function() { expect(vec2.dist).toEqual(vec2.distance); });
+
+ beforeEach(function() { result = vec2.distance(vecA, vecB); });
+
+ it("should return the distance", function() { expect(result).toBeCloseTo(2.828427); });
+ });
+
+ describe("squaredDistance", function() {
+ it("should have an alias called 'sqrDist'", function() { expect(vec2.sqrDist).toEqual(vec2.squaredDistance); });
+
+ beforeEach(function() { result = vec2.squaredDistance(vecA, vecB); });
+
+ it("should return the squared distance", function() { expect(result).toEqual(8); });
+ });
+
+ describe("length", function() {
+ it("should have an alias called 'len'", function() { expect(vec2.len).toEqual(vec2.length); });
+
+ beforeEach(function() { result = vec2.length(vecA); });
+
+ it("should return the length", function() { expect(result).toBeCloseTo(2.236067); });
+ });
+
+ describe("squaredLength", function() {
+ it("should have an alias called 'sqrLen'", function() { expect(vec2.sqrLen).toEqual(vec2.squaredLength); });
+
+ beforeEach(function() { result = vec2.squaredLength(vecA); });
+
+ it("should return the squared length", function() { expect(result).toEqual(5); });
+ });
+
+ describe("negate", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.negate(out, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-1, -2]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.negate(vecA, vecA); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([-1, -2]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("normalize", function() {
+ beforeEach(function() { vecA = [5, 0]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.normalize(out, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 0]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([5, 0]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.normalize(vecA, vecA); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 0]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("dot", function() {
+ beforeEach(function() { result = vec2.dot(vecA, vecB); });
+
+ it("should return the dot product", function() { expect(result).toEqual(11); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("cross", function() {
+ var out3;
+
+ beforeEach(function() {
+ out3 = [0, 0, 0];
+ result = vec2.cross(out3, vecA, vecB);
+ });
+
+ it("should place values into out", function() { expect(out3).toBeEqualish([0, 0, -2]); });
+ it("should return out", function() { expect(result).toBe(out3); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("lerp", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.lerp(out, vecA, vecB, 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2, 3]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.lerp(vecA, vecA, vecB, 0.5); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([2, 3]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec2.lerp(vecB, vecA, vecB, 0.5); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([2, 3]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("random", function() {
+ describe("with no scale", function() {
+ beforeEach(function() { result = vec2.random(out); });
+
+ it("should result in a unit length vector", function() { expect(vec2.length(out)).toBeCloseTo(1.0); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("with a scale", function() {
+ beforeEach(function() { result = vec2.random(out, 5.0); });
+
+ it("should result in a unit length vector", function() { expect(vec2.length(out)).toBeCloseTo(5.0); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+ });
+
+ describe("transformMat2", function() {
+ var matA;
+ beforeEach(function() { matA = [1, 2, 3, 4]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.transformMat2(out, vecA, matA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([7, 10]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.transformMat2(vecA, vecA, matA); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([7, 10]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("transformMat2d", function() {
+ var matA;
+ beforeEach(function() { matA = [1, 2, 3, 4, 5, 6]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec2.transformMat2d(out, vecA, matA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([12, 16]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4, 5, 6]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec2.transformMat2d(vecA, vecA, matA); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([12, 16]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4, 5, 6]); });
+ });
+ });
+
+ describe("forEach", function() {
+ var vecArray;
+
+ beforeEach(function() {
+ vecArray = [
+ 1, 2,
+ 3, 4,
+ 0, 0
+ ];
+ });
+
+ describe("when performing operations that take no extra arguments", function() {
+ beforeEach(function() { result = vec2.forEach(vecArray, 0, 0, 0, vec2.normalize); });
+
+ it("should update all values", function() {
+ expect(vecArray).toBeEqualish([
+ 0.447214, 0.894427,
+ 0.6, 0.8,
+ 0, 0
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ });
+
+ describe("when performing operations that takes one extra arguments", function() {
+ beforeEach(function() { result = vec2.forEach(vecArray, 0, 0, 0, vec2.add, vecA); });
+
+ it("should update all values", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4,
+ 4, 6,
+ 1, 2
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("when specifying an offset", function() {
+ beforeEach(function() { result = vec2.forEach(vecArray, 0, 2, 0, vec2.add, vecA); });
+
+ it("should update all values except the first vector", function() {
+ expect(vecArray).toBeEqualish([
+ 1, 2,
+ 4, 6,
+ 1, 2
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("when specifying a count", function() {
+ beforeEach(function() { result = vec2.forEach(vecArray, 0, 0, 2, vec2.add, vecA); });
+
+ it("should update all values except the last vector", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4,
+ 4, 6,
+ 0, 0
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("when specifying a stride", function() {
+ beforeEach(function() { result = vec2.forEach(vecArray, 4, 0, 0, vec2.add, vecA); });
+
+ it("should update all values except the second vector", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4,
+ 3, 4,
+ 1, 2
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("when calling a function that does not modify the out variable", function() {
+ beforeEach(function() {
+ result = vec2.forEach(vecArray, 0, 0, 0, function(out, vec) {});
+ });
+
+ it("values should remain unchanged", function() {
+ expect(vecArray).toBeEqualish([
+ 1, 2,
+ 3, 4,
+ 0, 0,
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ });
+ });
+
+ describe("str", function() {
+ beforeEach(function() { result = vec2.str(vecA); });
+
+ it("should return a string representation of the vector", function() { expect(result).toEqual("vec2(1, 2)"); });
+ });
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec3-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec3-spec.js
new file mode 100644
index 00000000000..8ef944f1a24
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec3-spec.js
@@ -0,0 +1,661 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+describe("vec3", function() {
+ var mat3 = require("../../src/gl-matrix/mat3.js");
+ var mat4 = require("../../src/gl-matrix/mat4.js");
+ var vec3 = require("../../src/gl-matrix/vec3.js");
+
+ var out, vecA, vecB, result;
+
+ beforeEach(function() { vecA = [1, 2, 3]; vecB = [4, 5, 6]; out = [0, 0, 0]; });
+
+ describe('rotateX', function(){
+ describe('rotation around world origin [0, 0, 0]', function(){
+ beforeEach(function(){ vecA = [0, 1, 0]; vecB = [0, 0, 0]; result = vec3.rotateX(out, vecA, vecB, Math.PI); });
+ it("should return the rotated vector", function(){ expect(result).toBeEqualish([0, -1, 0]); });
+ });
+ describe('rotation around an arbitrary origin', function(){
+ beforeEach(function(){ vecA = [2, 7, 0]; vecB = [2, 5, 0]; result = vec3.rotateX(out, vecA, vecB, Math.PI); });
+ it("should return the rotated vector", function(){ expect(result).toBeEqualish([2, 3, 0]); });
+ });
+ });
+
+ describe('rotateY', function(){
+ describe('rotation around world origin [0, 0, 0]', function(){
+ beforeEach(function(){ vecA = [1, 0, 0]; vecB = [0, 0, 0]; result = vec3.rotateY(out, vecA, vecB, Math.PI); });
+ it("should return the rotated vector", function(){ expect(result).toBeEqualish([-1, 0, 0]); });
+ });
+ describe('rotation around an arbitrary origin', function(){
+ beforeEach(function(){ vecA = [-2, 3, 10]; vecB = [-4, 3, 10]; result = vec3.rotateY(out, vecA, vecB, Math.PI); });
+ it("should return the rotated vector", function(){ expect(result).toBeEqualish([-6, 3, 10]); });
+ });
+ });
+
+ describe('rotateZ', function(){
+ describe('rotation around world origin [0, 0, 0]', function(){
+ beforeEach(function(){ vecA = [0, 1, 0]; vecB = [0, 0, 0]; result = vec3.rotateZ(out, vecA, vecB, Math.PI); });
+ it("should return the rotated vector", function(){ expect(result).toBeEqualish([0, -1, 0]); });
+ });
+ describe('rotation around an arbitrary origin', function(){
+ beforeEach(function(){ vecA = [0, 6, -5]; vecB = [0, 0, -5]; result = vec3.rotateZ(out, vecA, vecB, Math.PI); });
+ it("should return the rotated vector", function(){ expect(result).toBeEqualish([0, -6, -5]); });
+ });
+ });
+
+ describe('transformMat4', function() {
+ var matr;
+ describe("with an identity", function() {
+ beforeEach(function() { matr = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] });
+
+ beforeEach(function() { result = vec3.transformMat4(out, vecA, matr); });
+
+ it("should produce the input", function() {
+ expect(out).toBeEqualish([1, 2, 3]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("with a lookAt", function() {
+ beforeEach(function() { matr = mat4.lookAt(mat4.create(), [5, 6, 7], [2, 6, 7], [0, 1, 0]); });
+
+ beforeEach(function() { result = vec3.transformMat4(out, vecA, matr); });
+
+ it("should rotate and translate the input", function() {
+ expect(out).toBeEqualish([ 4, -4, -4 ]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("with a perspective matrix (#92)", function() {
+ it("should transform a point from perspective(pi/2, 4/3, 1, 100)", function() {
+ matr = [0.750, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, -1.02, -1,
+ 0, 0, -2.02, 0];
+ result = vec3.transformMat4([], [10, 20, 30], matr);
+ expect(result).toBeEqualish([-0.25, -0.666666, 1.087333]);
+ });
+ });
+
+ });
+
+ describe('transformMat3', function() {
+ var matr;
+ describe("with an identity", function() {
+ beforeEach(function() { matr = [1, 0, 0, 0, 1, 0, 0, 0, 1 ] });
+
+ beforeEach(function() { result = vec3.transformMat3(out, vecA, matr); });
+
+ it("should produce the input", function() {
+ expect(out).toBeEqualish([1, 2, 3]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("with 90deg about X", function() {
+ beforeEach(function() {
+ result = vec3.transformMat3(out, [0,1,0], [1,0,0,0,0,1,0,-1,0]);
+ });
+
+ it("should produce correct output", function() {
+ expect(out).toBeEqualish([0,0,1]);
+ });
+ });
+
+ describe("with 90deg about Y", function() {
+ beforeEach(function() {
+ result = vec3.transformMat3(out, [1,0,0], [0,0,-1,0,1,0,1,0,0]);
+ });
+
+ it("should produce correct output", function() {
+ expect(out).toBeEqualish([0,0,-1]);
+ });
+ });
+
+ describe("with 90deg about Z", function() {
+ beforeEach(function() {
+ result = vec3.transformMat3(out, [1,0,0], [0,1,0,-1,0,0,0,0,1]);
+ });
+
+ it("should produce correct output", function() {
+ expect(out).toBeEqualish([0,1,0]);
+ });
+ });
+
+ describe("with a lookAt normal matrix", function() {
+ beforeEach(function() {
+ matr = mat4.lookAt(mat4.create(), [5, 6, 7], [2, 6, 7], [0, 1, 0]);
+ var n = mat3.create();
+ matr = mat3.transpose(n, mat3.invert(n, mat3.fromMat4(n, matr)));
+ });
+
+ beforeEach(function() { result = vec3.transformMat3(out, [1,0,0], matr); });
+
+ it("should rotate the input", function() {
+ expect(out).toBeEqualish([ 0,0,1 ]);
+ });
+
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+ });
+
+ describe("create", function() {
+ beforeEach(function() { result = vec3.create(); });
+ it("should return a 3 element array initialized to 0s", function() { expect(result).toBeEqualish([0, 0, 0]); });
+ });
+
+ describe("clone", function() {
+ beforeEach(function() { result = vec3.clone(vecA); });
+ it("should return a 3 element array initialized to the values in vecA", function() { expect(result).toBeEqualish(vecA); });
+ });
+
+ describe("fromValues", function() {
+ beforeEach(function() { result = vec3.fromValues(1, 2, 3); });
+ it("should return a 3 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2, 3]); });
+ });
+
+ describe("copy", function() {
+ beforeEach(function() { result = vec3.copy(out, vecA); });
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("set", function() {
+ beforeEach(function() { result = vec3.set(out, 1, 2, 3); });
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("add", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.add(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([5, 7, 9]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.add(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([5, 7, 9]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.add(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([5, 7, 9]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+ });
+
+ describe("subtract", function() {
+ it("should have an alias called 'sub'", function() { expect(vec3.sub).toEqual(vec3.subtract); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.subtract(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-3, -3, -3]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.subtract(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([-3, -3, -3]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.subtract(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([-3, -3, -3]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+ });
+
+ describe("multiply", function() {
+ it("should have an alias called 'mul'", function() { expect(vec3.mul).toEqual(vec3.multiply); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.multiply(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([4, 10, 18]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.multiply(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([4, 10, 18]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.multiply(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([4, 10, 18]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+ });
+
+ describe("divide", function() {
+ it("should have an alias called 'div'", function() { expect(vec3.div).toEqual(vec3.divide); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.divide(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([0.25, 0.4, 0.5]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.divide(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([0.25, 0.4, 0.5]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.divide(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([0.25, 0.4, 0.5]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+ });
+
+ describe("min", function() {
+ beforeEach(function() { vecA = [1, 3, 1]; vecB = [3, 1, 3]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.min(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 1, 1]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.min(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 1, 1]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.min(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([1, 1, 1]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1]); });
+ });
+ });
+
+ describe("max", function() {
+ beforeEach(function() { vecA = [1, 3, 1]; vecB = [3, 1, 3]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.max(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 3, 3]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.max(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 3, 3]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.max(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 3, 3]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1]); });
+ });
+ });
+
+ describe("scale", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.scale(out, vecA, 2); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.scale(vecA, vecA, 2); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([2, 4, 6]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("scaleAndAdd", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.scaleAndAdd(out, vecA, vecB, 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 4.5, 6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.scaleAndAdd(vecA, vecA, vecB, 0.5); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 4.5, 6]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.scaleAndAdd(vecB, vecA, vecB, 0.5); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 4.5, 6]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+ });
+
+ describe("distance", function() {
+ it("should have an alias called 'dist'", function() { expect(vec3.dist).toEqual(vec3.distance); });
+
+ beforeEach(function() { result = vec3.distance(vecA, vecB); });
+
+ it("should return the distance", function() { expect(result).toBeCloseTo(5.196152); });
+ });
+
+ describe("squaredDistance", function() {
+ it("should have an alias called 'sqrDist'", function() { expect(vec3.sqrDist).toEqual(vec3.squaredDistance); });
+
+ beforeEach(function() { result = vec3.squaredDistance(vecA, vecB); });
+
+ it("should return the squared distance", function() { expect(result).toEqual(27); });
+ });
+
+ describe("length", function() {
+ it("should have an alias called 'len'", function() { expect(vec3.len).toEqual(vec3.length); });
+
+ beforeEach(function() { result = vec3.length(vecA); });
+
+ it("should return the length", function() { expect(result).toBeCloseTo(3.741657); });
+ });
+
+ describe("squaredLength", function() {
+ it("should have an alias called 'sqrLen'", function() { expect(vec3.sqrLen).toEqual(vec3.squaredLength); });
+
+ beforeEach(function() { result = vec3.squaredLength(vecA); });
+
+ it("should return the squared length", function() { expect(result).toEqual(14); });
+ });
+
+ describe("negate", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.negate(out, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-1, -2, -3]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.negate(vecA, vecA); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([-1, -2, -3]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("normalize", function() {
+ beforeEach(function() { vecA = [5, 0, 0]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.normalize(out, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 0, 0]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([5, 0, 0]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.normalize(vecA, vecA); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 0, 0]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("dot", function() {
+ beforeEach(function() { result = vec3.dot(vecA, vecB); });
+
+ it("should return the dot product", function() { expect(result).toEqual(32); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("cross", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.cross(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-3, 6, -3]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.cross(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([-3, 6, -3]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.cross(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([-3, 6, -3]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+ });
+
+ describe("lerp", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec3.lerp(out, vecA, vecB, 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2.5, 3.5, 4.5]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec3.lerp(vecA, vecA, vecB, 0.5); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([2.5, 3.5, 4.5]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec3.lerp(vecB, vecA, vecB, 0.5); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([2.5, 3.5, 4.5]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+ });
+
+ describe("random", function() {
+ describe("with no scale", function() {
+ beforeEach(function() { result = vec3.random(out); });
+
+ it("should result in a unit length vector", function() { expect(vec3.length(out)).toBeCloseTo(1.0); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("with a scale", function() {
+ beforeEach(function() { result = vec3.random(out, 5.0); });
+
+ it("should result in a unit length vector", function() { expect(vec3.length(out)).toBeCloseTo(5.0); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+ });
+
+ describe("forEach", function() {
+ var vecArray;
+
+ beforeEach(function() {
+ vecArray = [
+ 1, 2, 3,
+ 4, 5, 6,
+ 0, 0, 0
+ ];
+ });
+
+ describe("when performing operations that take no extra arguments", function() {
+ beforeEach(function() { result = vec3.forEach(vecArray, 0, 0, 0, vec3.normalize); });
+
+ it("should update all values", function() {
+ expect(vecArray).toBeEqualish([
+ 0.267261, 0.534522, 0.801783,
+ 0.455842, 0.569802, 0.683763,
+ 0, 0, 0
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ });
+
+ describe("when performing operations that takes one extra arguments", function() {
+ beforeEach(function() { result = vec3.forEach(vecArray, 0, 0, 0, vec3.add, vecA); });
+
+ it("should update all values", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4, 6,
+ 5, 7, 9,
+ 1, 2, 3
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+
+ describe("when specifying an offset", function() {
+ beforeEach(function() { result = vec3.forEach(vecArray, 0, 3, 0, vec3.add, vecA); });
+
+ it("should update all values except the first vector", function() {
+ expect(vecArray).toBeEqualish([
+ 1, 2, 3,
+ 5, 7, 9,
+ 1, 2, 3
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+
+ describe("when specifying a count", function() {
+ beforeEach(function() { result = vec3.forEach(vecArray, 0, 0, 2, vec3.add, vecA); });
+
+ it("should update all values except the last vector", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4, 6,
+ 5, 7, 9,
+ 0, 0, 0
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+
+ describe("when specifying a stride", function() {
+ beforeEach(function() { result = vec3.forEach(vecArray, 6, 0, 0, vec3.add, vecA); });
+
+ it("should update all values except the second vector", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4, 6,
+ 4, 5, 6,
+ 1, 2, 3
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ });
+
+ describe("when calling a function that does not modify the out variable", function() {
+ beforeEach(function() {
+ result = vec3.forEach(vecArray, 0, 0, 0, function(out, vec) {});
+ });
+
+ it("values should remain unchanged", function() {
+ expect(vecArray).toBeEqualish([
+ 1, 2, 3,
+ 4, 5, 6,
+ 0, 0, 0
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ });
+ });
+
+ describe("angle", function() {
+ beforeEach(function() { result = vec3.angle(vecA, vecB); });
+
+ it("should return the angle", function() { expect(result).toBeEqualish(0.225726); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); });
+ });
+
+ describe("str", function() {
+ beforeEach(function() { result = vec3.str(vecA); });
+
+ it("should return a string representation of the vector", function() { expect(result).toEqual("vec3(1, 2, 3)"); });
+ });
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec4-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec4-spec.js
new file mode 100644
index 00000000000..0c65908cb4a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/vec4-spec.js
@@ -0,0 +1,492 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+describe("vec4", function() {
+ var vec3 = require("../../src/gl-matrix/vec3.js");
+ var vec4 = require("../../src/gl-matrix/vec4.js");
+
+ var out, vecA, vecB, result;
+
+ beforeEach(function() { vecA = [1, 2, 3, 4]; vecB = [5, 6, 7, 8]; out = [0, 0, 0, 0]; });
+
+ describe("create", function() {
+ beforeEach(function() { result = vec4.create(); });
+ it("should return a 4 element array initialized to 0s", function() { expect(result).toBeEqualish([0, 0, 0, 0]); });
+ });
+
+ describe("clone", function() {
+ beforeEach(function() { result = vec4.clone(vecA); });
+ it("should return a 4 element array initialized to the values in vecA", function() { expect(result).toBeEqualish(vecA); });
+ });
+
+ describe("fromValues", function() {
+ beforeEach(function() { result = vec4.fromValues(1, 2, 3, 4); });
+ it("should return a 4 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("copy", function() {
+ beforeEach(function() { result = vec4.copy(out, vecA); });
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("set", function() {
+ beforeEach(function() { result = vec4.set(out, 1, 2, 3, 4); });
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("add", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.add(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([6, 8, 10, 12]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.add(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([6, 8, 10, 12]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec4.add(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([6, 8, 10, 12]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("subtract", function() {
+ it("should have an alias called 'sub'", function() { expect(vec4.sub).toEqual(vec4.subtract); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.subtract(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-4, -4, -4, -4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.subtract(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([-4, -4, -4, -4]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec4.subtract(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([-4, -4, -4, -4]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("multiply", function() {
+ it("should have an alias called 'mul'", function() { expect(vec4.mul).toEqual(vec4.multiply); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.multiply(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([5, 12, 21, 32]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.multiply(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([5, 12, 21, 32]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec4.multiply(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([5, 12, 21, 32]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("divide", function() {
+ it("should have an alias called 'div'", function() { expect(vec4.div).toEqual(vec4.divide); });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.divide(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([0.2, 0.333333, 0.428571, 0.5]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.divide(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([0.2, 0.333333, 0.428571, 0.5]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec4.divide(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([0.2, 0.333333, 0.428571, 0.5]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("min", function() {
+ beforeEach(function() { vecA = [1, 3, 1, 3]; vecB = [3, 1, 3, 1]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.min(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 1, 1, 1]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3, 1]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.min(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 1, 1, 1]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3, 1]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec4.min(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([1, 1, 1, 1]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1, 3]); });
+ });
+ });
+
+ describe("max", function() {
+ beforeEach(function() { vecA = [1, 3, 1, 3]; vecB = [3, 1, 3, 1]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.max(out, vecA, vecB); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 3, 3, 3]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3, 1]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.max(vecA, vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 3, 3, 3]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3, 1]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec4.max(vecB, vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 3, 3, 3]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1, 3]); });
+ });
+ });
+
+ describe("scale", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.scale(out, vecA, 2); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 6, 8]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.scale(vecA, vecA, 2); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([2, 4, 6, 8]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("scaleAndAdd", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.scaleAndAdd(out, vecA, vecB, 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3.5, 5, 6.5, 8]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.scaleAndAdd(vecA, vecA, vecB, 0.5); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([3.5, 5, 6.5, 8]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec4.scaleAndAdd(vecB, vecA, vecB, 0.5); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([3.5, 5, 6.5, 8]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("distance", function() {
+ it("should have an alias called 'dist'", function() { expect(vec4.dist).toEqual(vec4.distance); });
+
+ beforeEach(function() { result = vec4.distance(vecA, vecB); });
+
+ it("should return the distance", function() { expect(result).toBeCloseTo(8); });
+ });
+
+ describe("squaredDistance", function() {
+ it("should have an alias called 'sqrDist'", function() { expect(vec4.sqrDist).toEqual(vec4.squaredDistance); });
+
+ beforeEach(function() { result = vec4.squaredDistance(vecA, vecB); });
+
+ it("should return the squared distance", function() { expect(result).toEqual(64); });
+ });
+
+ describe("length", function() {
+ it("should have an alias called 'len'", function() { expect(vec4.len).toEqual(vec4.length); });
+
+ beforeEach(function() { result = vec4.length(vecA); });
+
+ it("should return the length", function() { expect(result).toBeCloseTo(5.477225); });
+ });
+
+ describe("squaredLength", function() {
+ it("should have an alias called 'sqrLen'", function() { expect(vec4.sqrLen).toEqual(vec4.squaredLength); });
+
+ beforeEach(function() { result = vec4.squaredLength(vecA); });
+
+ it("should return the squared length", function() { expect(result).toEqual(30); });
+ });
+
+ describe("negate", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.negate(out, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([-1, -2, -3, -4]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.negate(vecA, vecA); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([-1, -2, -3, -4]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("normalize", function() {
+ beforeEach(function() { vecA = [5, 0, 0, 0]; });
+
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.normalize(out, vecA); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([1, 0, 0, 0]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([5, 0, 0, 0]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.normalize(vecA, vecA); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 0, 0, 0]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("dot", function() {
+ beforeEach(function() { result = vec4.dot(vecA, vecB); });
+
+ it("should return the dot product", function() { expect(result).toEqual(70); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("lerp", function() {
+ describe("with a separate output vector", function() {
+ beforeEach(function() { result = vec4.lerp(out, vecA, vecB, 0.5); });
+
+ it("should place values into out", function() { expect(out).toBeEqualish([3, 4, 5, 6]); });
+ it("should return out", function() { expect(result).toBe(out); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecA is the output vector", function() {
+ beforeEach(function() { result = vec4.lerp(vecA, vecA, vecB, 0.5); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 4, 5, 6]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("when vecB is the output vector", function() {
+ beforeEach(function() { result = vec4.lerp(vecB, vecA, vecB, 0.5); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 4, 5, 6]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+ });
+
+ describe("random", function() {
+ describe("with no scale", function() {
+ beforeEach(function() { result = vec4.random(out); });
+
+ it("should result in a unit length vector", function() { expect(vec4.length(out)).toBeCloseTo(1.0); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+
+ describe("with a scale", function() {
+ beforeEach(function() { result = vec4.random(out, 5.0); });
+
+ it("should result in a unit length vector", function() { expect(vec4.length(out)).toBeCloseTo(5.0); });
+ it("should return out", function() { expect(result).toBe(out); });
+ });
+ });
+
+ describe("forEach", function() {
+ var vecArray;
+
+ beforeEach(function() {
+ vecArray = [
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 0, 0, 0, 0
+ ];
+ });
+
+ describe("when performing operations that take no extra arguments", function() {
+ beforeEach(function() { result = vec4.forEach(vecArray, 0, 0, 0, vec4.normalize); });
+
+ it("should update all values", function() {
+ expect(vecArray).toBeEqualish([
+ 0.182574, 0.365148, 0.547722, 0.730296,
+ 0.379049, 0.454858, 0.530668, 0.606478,
+ 0, 0, 0, 0
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ });
+
+ describe("when performing operations that takes one extra arguments", function() {
+ beforeEach(function() { result = vec4.forEach(vecArray, 0, 0, 0, vec4.add, vecA); });
+
+ it("should update all values", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4, 6, 8,
+ 6, 8, 10, 12,
+ 1, 2, 3, 4
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when specifying an offset", function() {
+ beforeEach(function() { result = vec4.forEach(vecArray, 0, 4, 0, vec4.add, vecA); });
+
+ it("should update all values except the first vector", function() {
+ expect(vecArray).toBeEqualish([
+ 1, 2, 3, 4,
+ 6, 8, 10, 12,
+ 1, 2, 3, 4
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when specifying a count", function() {
+ beforeEach(function() { result = vec4.forEach(vecArray, 0, 0, 2, vec4.add, vecA); });
+
+ it("should update all values except the last vector", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4, 6, 8,
+ 6, 8, 10, 12,
+ 0, 0, 0, 0
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when specifying a stride", function() {
+ beforeEach(function() { result = vec4.forEach(vecArray, 8, 0, 0, vec4.add, vecA); });
+
+ it("should update all values except the second vector", function() {
+ expect(vecArray).toBeEqualish([
+ 2, 4, 6, 8,
+ 5, 6, 7, 8,
+ 1, 2, 3, 4
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("when calling a function that does not modify the out variable", function() {
+ beforeEach(function() {
+ result = vec3.forEach(vecArray, 0, 0, 0, function(out, vec) {});
+ });
+
+ it("values should remain unchanged", function() {
+ expect(vecArray).toBeEqualish([
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 0, 0, 0, 0
+ ]);
+ });
+ it("should return vecArray", function() { expect(result).toBe(vecArray); });
+ });
+ });
+
+ describe("str", function() {
+ beforeEach(function() { result = vec4.str(vecA); });
+
+ it("should return a string representation of the vector", function() { expect(result).toEqual("vec4(1, 2, 3, 4)"); });
+ });
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/worker-spec.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/worker-spec.js
new file mode 100644
index 00000000000..8b1754f4db1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/gl-matrix/worker-spec.js
@@ -0,0 +1,44 @@
+/* spec tests gl-matrix when embedded into a Web Worker */
+
+// only test with workers if workers are available
+if (typeof(Worker) !== 'undefined') {
+ describe("Embedded within Web Workers", function() {
+ it("should initialize successfully", function() {
+ var xhr = new XMLHttpRequest();
+ var source = null;
+ xhr.onreadystatechange = function() {
+ if (this.readyState == this.DONE) {
+ if (this.status == 200) {
+ source = this.responseText;
+ }
+ }
+ };
+ xhr.open("GET", "/dist/gl-matrix-min.js");
+ xhr.send();
+
+ var result = null;
+
+ waitsFor(function() {
+ if (!source) return false;
+ var blob = new Blob([
+ source,
+ "self.postMessage(vec3.create());"
+ ],
+ {type: "application/javascript"}
+ );
+
+ var worker = new Worker(URL.createObjectURL(blob));
+ worker.onmessage = function(e) {
+ result = e.data;
+ };
+ return true;
+ });
+
+ waitsFor(function() {
+ if (!result) return false;
+ expect(result).toBeEqualish([0, 0, 0]);
+ return true;
+ });
+ });
+ });
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/helpers/spec-helper.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/helpers/spec-helper.js
new file mode 100644
index 00000000000..58e36714505
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/helpers/spec-helper.js
@@ -0,0 +1,32 @@
+var HELPER_MATCHERS = (function() {
+ var EPSILON = 0.00001;
+
+ return {
+ /*
+ Returns true if `actual` has the same length as `expected`, and
+ if each element of both arrays is within 0.000001 of each other.
+ This is a way to check for "equal enough" conditions, as a way
+ of working around floating point imprecision.
+ */
+ toBeEqualish: function(expected) {
+ if (typeof(this.actual) == 'number')
+ return Math.abs(this.actual - expected) < EPSILON;
+
+ if (this.actual.length != expected.length) return false;
+ for (var i = 0; i < this.actual.length; i++) {
+ if (isNaN(this.actual[i]) !== isNaN(expected[i]))
+ return false;
+ if (Math.abs(this.actual[i] - expected[i]) >= EPSILON)
+ return false;
+ }
+ return true;
+ }
+ };
+})();
+
+beforeEach(function() {
+ this.addMatchers(HELPER_MATCHERS);
+});
+
+if (typeof(global) != 'undefined')
+ global.HELPER_MATCHERS = HELPER_MATCHERS;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/jasmine.yml b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/jasmine.yml
new file mode 100644
index 00000000000..afb56ec62c9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/spec/jasmine.yml
@@ -0,0 +1,74 @@
+# src_files
+#
+# Return an array of filepaths relative to src_dir to include before jasmine specs.
+# Default: []
+#
+# EXAMPLE:
+#
+# src_files:
+# - lib/source1.js
+# - lib/source2.js
+# - dist/**/*.js
+#
+src_files:
+ - src/gl-matrix.js
+ - src/gl-matrix/common.js
+
+# stylesheets
+#
+# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
+# Default: []
+#
+# EXAMPLE:
+#
+# stylesheets:
+# - css/style.css
+# - stylesheets/*.css
+#
+stylesheets:
+
+# helpers
+#
+# Return an array of filepaths relative to spec_dir to include before jasmine specs.
+# Default: ["helpers/**/*.js"]
+#
+# EXAMPLE:
+#
+# helpers:
+# - helpers/**/*.js
+#
+helpers:
+
+# spec_files
+#
+# Return an array of filepaths relative to spec_dir to include.
+# Default: ["**/*[sS]pec.js"]
+#
+# EXAMPLE:
+#
+# spec_files:
+# - **/*[sS]pec.js
+#
+spec_files:
+
+# src_dir
+#
+# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
+# Default: project root
+#
+# EXAMPLE:
+#
+# src_dir: public
+#
+src_dir:
+
+# spec_dir
+#
+# Spec directory path. Your spec_files must be returned relative to this path.
+# Default: spec/javascripts
+#
+# EXAMPLE:
+#
+# spec_dir: spec/javascripts
+#
+spec_dir: spec
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix.js
new file mode 100644
index 00000000000..da4fe60dfd2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix.js
@@ -0,0 +1,37 @@
+/**
+ * @fileoverview gl-matrix - High performance matrix and vector operations
+ * @author Brandon Jones
+ * @author Colin MacKenzie IV
+ * @version 2.3.1
+ */
+
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+// END HEADER
+
+exports.glMatrix = require("./gl-matrix/common.js");
+exports.mat2 = require("./gl-matrix/mat2.js");
+exports.mat2d = require("./gl-matrix/mat2d.js");
+exports.mat3 = require("./gl-matrix/mat3.js");
+exports.mat4 = require("./gl-matrix/mat4.js");
+exports.quat = require("./gl-matrix/quat.js");
+exports.vec2 = require("./gl-matrix/vec2.js");
+exports.vec3 = require("./gl-matrix/vec3.js");
+exports.vec4 = require("./gl-matrix/vec4.js"); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/common.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/common.js
new file mode 100644
index 00000000000..5253421532e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/common.js
@@ -0,0 +1,52 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+/**
+ * @class Common utilities
+ * @name glMatrix
+ */
+var glMatrix = {};
+
+// Constants
+glMatrix.EPSILON = 0.000001;
+glMatrix.ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
+glMatrix.RANDOM = Math.random;
+
+/**
+ * Sets the type of array used when creating new vectors and matrices
+ *
+ * @param {Type} type Array type, such as Float32Array or Array
+ */
+glMatrix.setMatrixArrayType = function(type) {
+ GLMAT_ARRAY_TYPE = type;
+}
+
+var degree = Math.PI / 180;
+
+/**
+* Convert Degree To Radian
+*
+* @param {Number} Angle in Degrees
+*/
+glMatrix.toRadian = function(a){
+ return a * degree;
+}
+
+module.exports = glMatrix;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat2.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat2.js
new file mode 100644
index 00000000000..012a5c1af6b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat2.js
@@ -0,0 +1,302 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var glMatrix = require("./common.js");
+
+/**
+ * @class 2x2 Matrix
+ * @name mat2
+ */
+var mat2 = {};
+
+/**
+ * Creates a new identity mat2
+ *
+ * @returns {mat2} a new 2x2 matrix
+ */
+mat2.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+};
+
+/**
+ * Creates a new mat2 initialized with values from an existing matrix
+ *
+ * @param {mat2} a matrix to clone
+ * @returns {mat2} a new 2x2 matrix
+ */
+mat2.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+};
+
+/**
+ * Copy the values from one mat2 to another
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the source matrix
+ * @returns {mat2} out
+ */
+mat2.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+};
+
+/**
+ * Set a mat2 to the identity matrix
+ *
+ * @param {mat2} out the receiving matrix
+ * @returns {mat2} out
+ */
+mat2.identity = function(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+};
+
+/**
+ * Transpose the values of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the source matrix
+ * @returns {mat2} out
+ */
+mat2.transpose = function(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a1 = a[1];
+ out[1] = a[2];
+ out[2] = a1;
+ } else {
+ out[0] = a[0];
+ out[1] = a[2];
+ out[2] = a[1];
+ out[3] = a[3];
+ }
+
+ return out;
+};
+
+/**
+ * Inverts a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the source matrix
+ * @returns {mat2} out
+ */
+mat2.invert = function(out, a) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
+
+ // Calculate the determinant
+ det = a0 * a3 - a2 * a1;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = a3 * det;
+ out[1] = -a1 * det;
+ out[2] = -a2 * det;
+ out[3] = a0 * det;
+
+ return out;
+};
+
+/**
+ * Calculates the adjugate of a mat2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the source matrix
+ * @returns {mat2} out
+ */
+mat2.adjoint = function(out, a) {
+ // Caching this value is nessecary if out == a
+ var a0 = a[0];
+ out[0] = a[3];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a0;
+
+ return out;
+};
+
+/**
+ * Calculates the determinant of a mat2
+ *
+ * @param {mat2} a the source matrix
+ * @returns {Number} determinant of a
+ */
+mat2.determinant = function (a) {
+ return a[0] * a[3] - a[2] * a[1];
+};
+
+/**
+ * Multiplies two mat2's
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the first operand
+ * @param {mat2} b the second operand
+ * @returns {mat2} out
+ */
+mat2.multiply = function (out, a, b) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
+ var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ return out;
+};
+
+/**
+ * Alias for {@link mat2.multiply}
+ * @function
+ */
+mat2.mul = mat2.multiply;
+
+/**
+ * Rotates a mat2 by the given angle
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+mat2.rotate = function (out, a, rad) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ return out;
+};
+
+/**
+ * Scales the mat2 by the dimensions in the given vec2
+ *
+ * @param {mat2} out the receiving matrix
+ * @param {mat2} a the matrix to rotate
+ * @param {vec2} v the vec2 to scale the matrix by
+ * @returns {mat2} out
+ **/
+mat2.scale = function(out, a, v) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
+ v0 = v[0], v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ return out;
+};
+
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.rotate(dest, dest, rad);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2} out
+ */
+mat2.fromRotation = function(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ return out;
+}
+
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2.identity(dest);
+ * mat2.scale(dest, dest, vec);
+ *
+ * @param {mat2} out mat2 receiving operation result
+ * @param {vec2} v Scaling vector
+ * @returns {mat2} out
+ */
+mat2.fromScaling = function(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ return out;
+}
+
+/**
+ * Returns a string representation of a mat2
+ *
+ * @param {mat2} mat matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+mat2.str = function (a) {
+ return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
+};
+
+/**
+ * Returns Frobenius norm of a mat2
+ *
+ * @param {mat2} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+mat2.frob = function (a) {
+ return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)))
+};
+
+/**
+ * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
+ * @param {mat2} L the lower triangular matrix
+ * @param {mat2} D the diagonal matrix
+ * @param {mat2} U the upper triangular matrix
+ * @param {mat2} a the input matrix to factorize
+ */
+
+mat2.LDU = function (L, D, U, a) {
+ L[2] = a[2]/a[0];
+ U[0] = a[0];
+ U[1] = a[1];
+ U[3] = a[3] - L[2] * U[1];
+ return [L, D, U];
+};
+
+
+module.exports = mat2;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat2d.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat2d.js
new file mode 100644
index 00000000000..df3a0e6a0b3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat2d.js
@@ -0,0 +1,317 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var glMatrix = require("./common.js");
+
+/**
+ * @class 2x3 Matrix
+ * @name mat2d
+ *
+ * @description
+ * A mat2d contains six elements defined as:
+ * <pre>
+ * [a, c, tx,
+ * b, d, ty]
+ * </pre>
+ * This is a short form for the 3x3 matrix:
+ * <pre>
+ * [a, c, tx,
+ * b, d, ty,
+ * 0, 0, 1]
+ * </pre>
+ * The last row is ignored so the array is shorter and operations are faster.
+ */
+var mat2d = {};
+
+/**
+ * Creates a new identity mat2d
+ *
+ * @returns {mat2d} a new 2x3 matrix
+ */
+mat2d.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(6);
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+};
+
+/**
+ * Creates a new mat2d initialized with values from an existing matrix
+ *
+ * @param {mat2d} a matrix to clone
+ * @returns {mat2d} a new 2x3 matrix
+ */
+mat2d.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(6);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+};
+
+/**
+ * Copy the values from one mat2d to another
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+mat2d.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ return out;
+};
+
+/**
+ * Set a mat2d to the identity matrix
+ *
+ * @param {mat2d} out the receiving matrix
+ * @returns {mat2d} out
+ */
+mat2d.identity = function(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+};
+
+/**
+ * Inverts a mat2d
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the source matrix
+ * @returns {mat2d} out
+ */
+mat2d.invert = function(out, a) {
+ var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
+ atx = a[4], aty = a[5];
+
+ var det = aa * ad - ab * ac;
+ if(!det){
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = ad * det;
+ out[1] = -ab * det;
+ out[2] = -ac * det;
+ out[3] = aa * det;
+ out[4] = (ac * aty - ad * atx) * det;
+ out[5] = (ab * atx - aa * aty) * det;
+ return out;
+};
+
+/**
+ * Calculates the determinant of a mat2d
+ *
+ * @param {mat2d} a the source matrix
+ * @returns {Number} determinant of a
+ */
+mat2d.determinant = function (a) {
+ return a[0] * a[3] - a[1] * a[2];
+};
+
+/**
+ * Multiplies two mat2d's
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the first operand
+ * @param {mat2d} b the second operand
+ * @returns {mat2d} out
+ */
+mat2d.multiply = function (out, a, b) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
+ b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
+ out[0] = a0 * b0 + a2 * b1;
+ out[1] = a1 * b0 + a3 * b1;
+ out[2] = a0 * b2 + a2 * b3;
+ out[3] = a1 * b2 + a3 * b3;
+ out[4] = a0 * b4 + a2 * b5 + a4;
+ out[5] = a1 * b4 + a3 * b5 + a5;
+ return out;
+};
+
+/**
+ * Alias for {@link mat2d.multiply}
+ * @function
+ */
+mat2d.mul = mat2d.multiply;
+
+/**
+ * Rotates a mat2d by the given angle
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+mat2d.rotate = function (out, a, rad) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+ out[0] = a0 * c + a2 * s;
+ out[1] = a1 * c + a3 * s;
+ out[2] = a0 * -s + a2 * c;
+ out[3] = a1 * -s + a3 * c;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+};
+
+/**
+ * Scales the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the matrix to translate
+ * @param {vec2} v the vec2 to scale the matrix by
+ * @returns {mat2d} out
+ **/
+mat2d.scale = function(out, a, v) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
+ v0 = v[0], v1 = v[1];
+ out[0] = a0 * v0;
+ out[1] = a1 * v0;
+ out[2] = a2 * v1;
+ out[3] = a3 * v1;
+ out[4] = a4;
+ out[5] = a5;
+ return out;
+};
+
+/**
+ * Translates the mat2d by the dimensions in the given vec2
+ *
+ * @param {mat2d} out the receiving matrix
+ * @param {mat2d} a the matrix to translate
+ * @param {vec2} v the vec2 to translate the matrix by
+ * @returns {mat2d} out
+ **/
+mat2d.translate = function(out, a, v) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
+ v0 = v[0], v1 = v[1];
+ out[0] = a0;
+ out[1] = a1;
+ out[2] = a2;
+ out[3] = a3;
+ out[4] = a0 * v0 + a2 * v1 + a4;
+ out[5] = a1 * v0 + a3 * v1 + a5;
+ return out;
+};
+
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.rotate(dest, dest, rad);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat2d} out
+ */
+mat2d.fromRotation = function(out, rad) {
+ var s = Math.sin(rad), c = Math.cos(rad);
+ out[0] = c;
+ out[1] = s;
+ out[2] = -s;
+ out[3] = c;
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+}
+
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.scale(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {vec2} v Scaling vector
+ * @returns {mat2d} out
+ */
+mat2d.fromScaling = function(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = v[1];
+ out[4] = 0;
+ out[5] = 0;
+ return out;
+}
+
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat2d.identity(dest);
+ * mat2d.translate(dest, dest, vec);
+ *
+ * @param {mat2d} out mat2d receiving operation result
+ * @param {vec2} v Translation vector
+ * @returns {mat2d} out
+ */
+mat2d.fromTranslation = function(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ out[4] = v[0];
+ out[5] = v[1];
+ return out;
+}
+
+/**
+ * Returns a string representation of a mat2d
+ *
+ * @param {mat2d} a matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+mat2d.str = function (a) {
+ return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
+ a[3] + ', ' + a[4] + ', ' + a[5] + ')';
+};
+
+/**
+ * Returns Frobenius norm of a mat2d
+ *
+ * @param {mat2d} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+mat2d.frob = function (a) {
+ return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1))
+};
+
+module.exports = mat2d;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat3.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat3.js
new file mode 100644
index 00000000000..bdda05ef020
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat3.js
@@ -0,0 +1,565 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var glMatrix = require("./common.js");
+
+/**
+ * @class 3x3 Matrix
+ * @name mat3
+ */
+var mat3 = {};
+
+/**
+ * Creates a new identity mat3
+ *
+ * @returns {mat3} a new 3x3 matrix
+ */
+mat3.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(9);
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+};
+
+/**
+ * Copies the upper-left 3x3 values into the given mat3.
+ *
+ * @param {mat3} out the receiving 3x3 matrix
+ * @param {mat4} a the source 4x4 matrix
+ * @returns {mat3} out
+ */
+mat3.fromMat4 = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[4];
+ out[4] = a[5];
+ out[5] = a[6];
+ out[6] = a[8];
+ out[7] = a[9];
+ out[8] = a[10];
+ return out;
+};
+
+/**
+ * Creates a new mat3 initialized with values from an existing matrix
+ *
+ * @param {mat3} a matrix to clone
+ * @returns {mat3} a new 3x3 matrix
+ */
+mat3.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(9);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+};
+
+/**
+ * Copy the values from one mat3 to another
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the source matrix
+ * @returns {mat3} out
+ */
+mat3.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+};
+
+/**
+ * Set a mat3 to the identity matrix
+ *
+ * @param {mat3} out the receiving matrix
+ * @returns {mat3} out
+ */
+mat3.identity = function(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+};
+
+/**
+ * Transpose the values of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the source matrix
+ * @returns {mat3} out
+ */
+mat3.transpose = function(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1], a02 = a[2], a12 = a[5];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a01;
+ out[5] = a[7];
+ out[6] = a02;
+ out[7] = a12;
+ } else {
+ out[0] = a[0];
+ out[1] = a[3];
+ out[2] = a[6];
+ out[3] = a[1];
+ out[4] = a[4];
+ out[5] = a[7];
+ out[6] = a[2];
+ out[7] = a[5];
+ out[8] = a[8];
+ }
+
+ return out;
+};
+
+/**
+ * Inverts a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the source matrix
+ * @returns {mat3} out
+ */
+mat3.invert = function(out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8],
+
+ b01 = a22 * a11 - a12 * a21,
+ b11 = -a22 * a10 + a12 * a20,
+ b21 = a21 * a10 - a11 * a20,
+
+ // Calculate the determinant
+ det = a00 * b01 + a01 * b11 + a02 * b21;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = b01 * det;
+ out[1] = (-a22 * a01 + a02 * a21) * det;
+ out[2] = (a12 * a01 - a02 * a11) * det;
+ out[3] = b11 * det;
+ out[4] = (a22 * a00 - a02 * a20) * det;
+ out[5] = (-a12 * a00 + a02 * a10) * det;
+ out[6] = b21 * det;
+ out[7] = (-a21 * a00 + a01 * a20) * det;
+ out[8] = (a11 * a00 - a01 * a10) * det;
+ return out;
+};
+
+/**
+ * Calculates the adjugate of a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the source matrix
+ * @returns {mat3} out
+ */
+mat3.adjoint = function(out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8];
+
+ out[0] = (a11 * a22 - a12 * a21);
+ out[1] = (a02 * a21 - a01 * a22);
+ out[2] = (a01 * a12 - a02 * a11);
+ out[3] = (a12 * a20 - a10 * a22);
+ out[4] = (a00 * a22 - a02 * a20);
+ out[5] = (a02 * a10 - a00 * a12);
+ out[6] = (a10 * a21 - a11 * a20);
+ out[7] = (a01 * a20 - a00 * a21);
+ out[8] = (a00 * a11 - a01 * a10);
+ return out;
+};
+
+/**
+ * Calculates the determinant of a mat3
+ *
+ * @param {mat3} a the source matrix
+ * @returns {Number} determinant of a
+ */
+mat3.determinant = function (a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8];
+
+ return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
+};
+
+/**
+ * Multiplies two mat3's
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the first operand
+ * @param {mat3} b the second operand
+ * @returns {mat3} out
+ */
+mat3.multiply = function (out, a, b) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8],
+
+ b00 = b[0], b01 = b[1], b02 = b[2],
+ b10 = b[3], b11 = b[4], b12 = b[5],
+ b20 = b[6], b21 = b[7], b22 = b[8];
+
+ out[0] = b00 * a00 + b01 * a10 + b02 * a20;
+ out[1] = b00 * a01 + b01 * a11 + b02 * a21;
+ out[2] = b00 * a02 + b01 * a12 + b02 * a22;
+
+ out[3] = b10 * a00 + b11 * a10 + b12 * a20;
+ out[4] = b10 * a01 + b11 * a11 + b12 * a21;
+ out[5] = b10 * a02 + b11 * a12 + b12 * a22;
+
+ out[6] = b20 * a00 + b21 * a10 + b22 * a20;
+ out[7] = b20 * a01 + b21 * a11 + b22 * a21;
+ out[8] = b20 * a02 + b21 * a12 + b22 * a22;
+ return out;
+};
+
+/**
+ * Alias for {@link mat3.multiply}
+ * @function
+ */
+mat3.mul = mat3.multiply;
+
+/**
+ * Translate a mat3 by the given vector
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the matrix to translate
+ * @param {vec2} v vector to translate by
+ * @returns {mat3} out
+ */
+mat3.translate = function(out, a, v) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8],
+ x = v[0], y = v[1];
+
+ out[0] = a00;
+ out[1] = a01;
+ out[2] = a02;
+
+ out[3] = a10;
+ out[4] = a11;
+ out[5] = a12;
+
+ out[6] = x * a00 + y * a10 + a20;
+ out[7] = x * a01 + y * a11 + a21;
+ out[8] = x * a02 + y * a12 + a22;
+ return out;
+};
+
+/**
+ * Rotates a mat3 by the given angle
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+mat3.rotate = function (out, a, rad) {
+ var a00 = a[0], a01 = a[1], a02 = a[2],
+ a10 = a[3], a11 = a[4], a12 = a[5],
+ a20 = a[6], a21 = a[7], a22 = a[8],
+
+ s = Math.sin(rad),
+ c = Math.cos(rad);
+
+ out[0] = c * a00 + s * a10;
+ out[1] = c * a01 + s * a11;
+ out[2] = c * a02 + s * a12;
+
+ out[3] = c * a10 - s * a00;
+ out[4] = c * a11 - s * a01;
+ out[5] = c * a12 - s * a02;
+
+ out[6] = a20;
+ out[7] = a21;
+ out[8] = a22;
+ return out;
+};
+
+/**
+ * Scales the mat3 by the dimensions in the given vec2
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat3} a the matrix to rotate
+ * @param {vec2} v the vec2 to scale the matrix by
+ * @returns {mat3} out
+ **/
+mat3.scale = function(out, a, v) {
+ var x = v[0], y = v[1];
+
+ out[0] = x * a[0];
+ out[1] = x * a[1];
+ out[2] = x * a[2];
+
+ out[3] = y * a[3];
+ out[4] = y * a[4];
+ out[5] = y * a[5];
+
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ return out;
+};
+
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.translate(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {vec2} v Translation vector
+ * @returns {mat3} out
+ */
+mat3.fromTranslation = function(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 1;
+ out[5] = 0;
+ out[6] = v[0];
+ out[7] = v[1];
+ out[8] = 1;
+ return out;
+}
+
+/**
+ * Creates a matrix from a given angle
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.rotate(dest, dest, rad);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat3} out
+ */
+mat3.fromRotation = function(out, rad) {
+ var s = Math.sin(rad), c = Math.cos(rad);
+
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+
+ out[3] = -s;
+ out[4] = c;
+ out[5] = 0;
+
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+}
+
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat3.identity(dest);
+ * mat3.scale(dest, dest, vec);
+ *
+ * @param {mat3} out mat3 receiving operation result
+ * @param {vec2} v Scaling vector
+ * @returns {mat3} out
+ */
+mat3.fromScaling = function(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+
+ out[3] = 0;
+ out[4] = v[1];
+ out[5] = 0;
+
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 1;
+ return out;
+}
+
+/**
+ * Copies the values from a mat2d into a mat3
+ *
+ * @param {mat3} out the receiving matrix
+ * @param {mat2d} a the matrix to copy
+ * @returns {mat3} out
+ **/
+mat3.fromMat2d = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = 0;
+
+ out[3] = a[2];
+ out[4] = a[3];
+ out[5] = 0;
+
+ out[6] = a[4];
+ out[7] = a[5];
+ out[8] = 1;
+ return out;
+};
+
+/**
+* Calculates a 3x3 matrix from the given quaternion
+*
+* @param {mat3} out mat3 receiving operation result
+* @param {quat} q Quaternion to create matrix from
+*
+* @returns {mat3} out
+*/
+mat3.fromQuat = function (out, q) {
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ yx = y * x2,
+ yy = y * y2,
+ zx = z * x2,
+ zy = z * y2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ out[0] = 1 - yy - zz;
+ out[3] = yx - wz;
+ out[6] = zx + wy;
+
+ out[1] = yx + wz;
+ out[4] = 1 - xx - zz;
+ out[7] = zy - wx;
+
+ out[2] = zx - wy;
+ out[5] = zy + wx;
+ out[8] = 1 - xx - yy;
+
+ return out;
+};
+
+/**
+* Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
+*
+* @param {mat3} out mat3 receiving operation result
+* @param {mat4} a Mat4 to derive the normal matrix from
+*
+* @returns {mat3} out
+*/
+mat3.normalFromMat4 = function (out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
+
+ b00 = a00 * a11 - a01 * a10,
+ b01 = a00 * a12 - a02 * a10,
+ b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11,
+ b04 = a01 * a13 - a03 * a11,
+ b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30,
+ b07 = a20 * a32 - a22 * a30,
+ b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31,
+ b10 = a21 * a33 - a23 * a31,
+ b11 = a22 * a33 - a23 * a32,
+
+ // Calculate the determinant
+ det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+
+ out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+
+ out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+
+ return out;
+};
+
+/**
+ * Returns a string representation of a mat3
+ *
+ * @param {mat3} mat matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+mat3.str = function (a) {
+ return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' +
+ a[3] + ', ' + a[4] + ', ' + a[5] + ', ' +
+ a[6] + ', ' + a[7] + ', ' + a[8] + ')';
+};
+
+/**
+ * Returns Frobenius norm of a mat3
+ *
+ * @param {mat3} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+mat3.frob = function (a) {
+ return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)))
+};
+
+
+module.exports = mat3;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat4.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat4.js
new file mode 100644
index 00000000000..b82526d1365
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/mat4.js
@@ -0,0 +1,1283 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var glMatrix = require("./common.js");
+
+/**
+ * @class 4x4 Matrix
+ * @name mat4
+ */
+var mat4 = {};
+
+/**
+ * Creates a new identity mat4
+ *
+ * @returns {mat4} a new 4x4 matrix
+ */
+mat4.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(16);
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+};
+
+/**
+ * Creates a new mat4 initialized with values from an existing matrix
+ *
+ * @param {mat4} a matrix to clone
+ * @returns {mat4} a new 4x4 matrix
+ */
+mat4.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(16);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+};
+
+/**
+ * Copy the values from one mat4 to another
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the source matrix
+ * @returns {mat4} out
+ */
+mat4.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+};
+
+/**
+ * Set a mat4 to the identity matrix
+ *
+ * @param {mat4} out the receiving matrix
+ * @returns {mat4} out
+ */
+mat4.identity = function(out) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+};
+
+/**
+ * Transpose the values of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the source matrix
+ * @returns {mat4} out
+ */
+mat4.transpose = function(out, a) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (out === a) {
+ var a01 = a[1], a02 = a[2], a03 = a[3],
+ a12 = a[6], a13 = a[7],
+ a23 = a[11];
+
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a01;
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a02;
+ out[9] = a12;
+ out[11] = a[14];
+ out[12] = a03;
+ out[13] = a13;
+ out[14] = a23;
+ } else {
+ out[0] = a[0];
+ out[1] = a[4];
+ out[2] = a[8];
+ out[3] = a[12];
+ out[4] = a[1];
+ out[5] = a[5];
+ out[6] = a[9];
+ out[7] = a[13];
+ out[8] = a[2];
+ out[9] = a[6];
+ out[10] = a[10];
+ out[11] = a[14];
+ out[12] = a[3];
+ out[13] = a[7];
+ out[14] = a[11];
+ out[15] = a[15];
+ }
+
+ return out;
+};
+
+/**
+ * Inverts a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the source matrix
+ * @returns {mat4} out
+ */
+mat4.invert = function(out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
+
+ b00 = a00 * a11 - a01 * a10,
+ b01 = a00 * a12 - a02 * a10,
+ b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11,
+ b04 = a01 * a13 - a03 * a11,
+ b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30,
+ b07 = a20 * a32 - a22 * a30,
+ b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31,
+ b10 = a21 * a33 - a23 * a31,
+ b11 = a22 * a33 - a23 * a32,
+
+ // Calculate the determinant
+ det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+
+ if (!det) {
+ return null;
+ }
+ det = 1.0 / det;
+
+ out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
+ out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
+ out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
+ out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
+ out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
+ out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
+ out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
+ out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
+ out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
+ out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
+ out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
+ out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
+ out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
+ out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
+ out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
+ out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
+
+ return out;
+};
+
+/**
+ * Calculates the adjugate of a mat4
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the source matrix
+ * @returns {mat4} out
+ */
+mat4.adjoint = function(out, a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
+
+ out[0] = (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
+ out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
+ out[2] = (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
+ out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
+ out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
+ out[5] = (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
+ out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
+ out[7] = (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
+ out[8] = (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
+ out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
+ out[10] = (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
+ out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
+ out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
+ out[13] = (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
+ out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
+ out[15] = (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
+ return out;
+};
+
+/**
+ * Calculates the determinant of a mat4
+ *
+ * @param {mat4} a the source matrix
+ * @returns {Number} determinant of a
+ */
+mat4.determinant = function (a) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
+
+ b00 = a00 * a11 - a01 * a10,
+ b01 = a00 * a12 - a02 * a10,
+ b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11,
+ b04 = a01 * a13 - a03 * a11,
+ b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30,
+ b07 = a20 * a32 - a22 * a30,
+ b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31,
+ b10 = a21 * a33 - a23 * a31,
+ b11 = a22 * a33 - a23 * a32;
+
+ // Calculate the determinant
+ return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
+};
+
+/**
+ * Multiplies two mat4's
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the first operand
+ * @param {mat4} b the second operand
+ * @returns {mat4} out
+ */
+mat4.multiply = function (out, a, b) {
+ var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
+ a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
+ a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
+ a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
+
+ // Cache only the current line of the second matrix
+ var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
+ out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
+ out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
+ out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
+ out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
+
+ b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
+ out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
+ out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
+ out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
+ out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
+
+ b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
+ out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
+ out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
+ out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
+ out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
+
+ b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
+ out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
+ out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
+ out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
+ out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
+ return out;
+};
+
+/**
+ * Alias for {@link mat4.multiply}
+ * @function
+ */
+mat4.mul = mat4.multiply;
+
+/**
+ * Translate a mat4 by the given vector
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to translate
+ * @param {vec3} v vector to translate by
+ * @returns {mat4} out
+ */
+mat4.translate = function (out, a, v) {
+ var x = v[0], y = v[1], z = v[2],
+ a00, a01, a02, a03,
+ a10, a11, a12, a13,
+ a20, a21, a22, a23;
+
+ if (a === out) {
+ out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
+ out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
+ out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
+ out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
+ } else {
+ a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
+ a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
+ a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
+
+ out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
+ out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
+ out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
+
+ out[12] = a00 * x + a10 * y + a20 * z + a[12];
+ out[13] = a01 * x + a11 * y + a21 * z + a[13];
+ out[14] = a02 * x + a12 * y + a22 * z + a[14];
+ out[15] = a03 * x + a13 * y + a23 * z + a[15];
+ }
+
+ return out;
+};
+
+/**
+ * Scales the mat4 by the dimensions in the given vec3
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to scale
+ * @param {vec3} v the vec3 to scale the matrix by
+ * @returns {mat4} out
+ **/
+mat4.scale = function(out, a, v) {
+ var x = v[0], y = v[1], z = v[2];
+
+ out[0] = a[0] * x;
+ out[1] = a[1] * x;
+ out[2] = a[2] * x;
+ out[3] = a[3] * x;
+ out[4] = a[4] * y;
+ out[5] = a[5] * y;
+ out[6] = a[6] * y;
+ out[7] = a[7] * y;
+ out[8] = a[8] * z;
+ out[9] = a[9] * z;
+ out[10] = a[10] * z;
+ out[11] = a[11] * z;
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ return out;
+};
+
+/**
+ * Rotates a mat4 by the given angle around the given axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {vec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+mat4.rotate = function (out, a, rad, axis) {
+ var x = axis[0], y = axis[1], z = axis[2],
+ len = Math.sqrt(x * x + y * y + z * z),
+ s, c, t,
+ a00, a01, a02, a03,
+ a10, a11, a12, a13,
+ a20, a21, a22, a23,
+ b00, b01, b02,
+ b10, b11, b12,
+ b20, b21, b22;
+
+ if (Math.abs(len) < glMatrix.EPSILON) { return null; }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c;
+
+ a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
+ a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
+ a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
+
+ // Construct the elements of the rotation matrix
+ b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
+ b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
+ b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
+
+ // Perform rotation-specific matrix multiplication
+ out[0] = a00 * b00 + a10 * b01 + a20 * b02;
+ out[1] = a01 * b00 + a11 * b01 + a21 * b02;
+ out[2] = a02 * b00 + a12 * b01 + a22 * b02;
+ out[3] = a03 * b00 + a13 * b01 + a23 * b02;
+ out[4] = a00 * b10 + a10 * b11 + a20 * b12;
+ out[5] = a01 * b10 + a11 * b11 + a21 * b12;
+ out[6] = a02 * b10 + a12 * b11 + a22 * b12;
+ out[7] = a03 * b10 + a13 * b11 + a23 * b12;
+ out[8] = a00 * b20 + a10 * b21 + a20 * b22;
+ out[9] = a01 * b20 + a11 * b21 + a21 * b22;
+ out[10] = a02 * b20 + a12 * b21 + a22 * b22;
+ out[11] = a03 * b20 + a13 * b21 + a23 * b22;
+
+ if (a !== out) { // If the source and destination differ, copy the unchanged last row
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+ return out;
+};
+
+/**
+ * Rotates a matrix by the given angle around the X axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+mat4.rotateX = function (out, a, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad),
+ a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7],
+ a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+
+ if (a !== out) { // If the source and destination differ, copy the unchanged rows
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ out[4] = a10 * c + a20 * s;
+ out[5] = a11 * c + a21 * s;
+ out[6] = a12 * c + a22 * s;
+ out[7] = a13 * c + a23 * s;
+ out[8] = a20 * c - a10 * s;
+ out[9] = a21 * c - a11 * s;
+ out[10] = a22 * c - a12 * s;
+ out[11] = a23 * c - a13 * s;
+ return out;
+};
+
+/**
+ * Rotates a matrix by the given angle around the Y axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+mat4.rotateY = function (out, a, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad),
+ a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3],
+ a20 = a[8],
+ a21 = a[9],
+ a22 = a[10],
+ a23 = a[11];
+
+ if (a !== out) { // If the source and destination differ, copy the unchanged rows
+ out[4] = a[4];
+ out[5] = a[5];
+ out[6] = a[6];
+ out[7] = a[7];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ out[0] = a00 * c - a20 * s;
+ out[1] = a01 * c - a21 * s;
+ out[2] = a02 * c - a22 * s;
+ out[3] = a03 * c - a23 * s;
+ out[8] = a00 * s + a20 * c;
+ out[9] = a01 * s + a21 * c;
+ out[10] = a02 * s + a22 * c;
+ out[11] = a03 * s + a23 * c;
+ return out;
+};
+
+/**
+ * Rotates a matrix by the given angle around the Z axis
+ *
+ * @param {mat4} out the receiving matrix
+ * @param {mat4} a the matrix to rotate
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+mat4.rotateZ = function (out, a, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad),
+ a00 = a[0],
+ a01 = a[1],
+ a02 = a[2],
+ a03 = a[3],
+ a10 = a[4],
+ a11 = a[5],
+ a12 = a[6],
+ a13 = a[7];
+
+ if (a !== out) { // If the source and destination differ, copy the unchanged last row
+ out[8] = a[8];
+ out[9] = a[9];
+ out[10] = a[10];
+ out[11] = a[11];
+ out[12] = a[12];
+ out[13] = a[13];
+ out[14] = a[14];
+ out[15] = a[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ out[0] = a00 * c + a10 * s;
+ out[1] = a01 * c + a11 * s;
+ out[2] = a02 * c + a12 * s;
+ out[3] = a03 * c + a13 * s;
+ out[4] = a10 * c - a00 * s;
+ out[5] = a11 * c - a01 * s;
+ out[6] = a12 * c - a02 * s;
+ out[7] = a13 * c - a03 * s;
+ return out;
+};
+
+/**
+ * Creates a matrix from a vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {vec3} v Translation vector
+ * @returns {mat4} out
+ */
+mat4.fromTranslation = function(out, v) {
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+ return out;
+}
+
+/**
+ * Creates a matrix from a vector scaling
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.scale(dest, dest, vec);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {vec3} v Scaling vector
+ * @returns {mat4} out
+ */
+mat4.fromScaling = function(out, v) {
+ out[0] = v[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = v[1];
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = v[2];
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+
+/**
+ * Creates a matrix from a given angle around a given axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotate(dest, dest, rad, axis);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @param {vec3} axis the axis to rotate around
+ * @returns {mat4} out
+ */
+mat4.fromRotation = function(out, rad, axis) {
+ var x = axis[0], y = axis[1], z = axis[2],
+ len = Math.sqrt(x * x + y * y + z * z),
+ s, c, t;
+
+ if (Math.abs(len) < glMatrix.EPSILON) { return null; }
+
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+
+ s = Math.sin(rad);
+ c = Math.cos(rad);
+ t = 1 - c;
+
+ // Perform rotation-specific matrix multiplication
+ out[0] = x * x * t + c;
+ out[1] = y * x * t + z * s;
+ out[2] = z * x * t - y * s;
+ out[3] = 0;
+ out[4] = x * y * t - z * s;
+ out[5] = y * y * t + c;
+ out[6] = z * y * t + x * s;
+ out[7] = 0;
+ out[8] = x * z * t + y * s;
+ out[9] = y * z * t - x * s;
+ out[10] = z * z * t + c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+
+/**
+ * Creates a matrix from the given angle around the X axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateX(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+mat4.fromXRotation = function(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+
+ // Perform axis-specific matrix multiplication
+ out[0] = 1;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = c;
+ out[6] = s;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = -s;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+
+/**
+ * Creates a matrix from the given angle around the Y axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateY(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+mat4.fromYRotation = function(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+
+ // Perform axis-specific matrix multiplication
+ out[0] = c;
+ out[1] = 0;
+ out[2] = -s;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = 1;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = s;
+ out[9] = 0;
+ out[10] = c;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+
+/**
+ * Creates a matrix from the given angle around the Z axis
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.rotateZ(dest, dest, rad);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {Number} rad the angle to rotate the matrix by
+ * @returns {mat4} out
+ */
+mat4.fromZRotation = function(out, rad) {
+ var s = Math.sin(rad),
+ c = Math.cos(rad);
+
+ // Perform axis-specific matrix multiplication
+ out[0] = c;
+ out[1] = s;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = -s;
+ out[5] = c;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 1;
+ out[11] = 0;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+ return out;
+}
+
+/**
+ * Creates a matrix from a quaternion rotation and vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * var quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {vec3} v Translation vector
+ * @returns {mat4} out
+ */
+mat4.fromRotationTranslation = function (out, q, v) {
+ // Quaternion math
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ out[0] = 1 - (yy + zz);
+ out[1] = xy + wz;
+ out[2] = xz - wy;
+ out[3] = 0;
+ out[4] = xy - wz;
+ out[5] = 1 - (xx + zz);
+ out[6] = yz + wx;
+ out[7] = 0;
+ out[8] = xz + wy;
+ out[9] = yz - wx;
+ out[10] = 1 - (xx + yy);
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+
+ return out;
+};
+
+/**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * var quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {vec3} v Translation vector
+ * @param {vec3} s Scaling vector
+ * @returns {mat4} out
+ */
+mat4.fromRotationTranslationScale = function (out, q, v, s) {
+ // Quaternion math
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2,
+ sx = s[0],
+ sy = s[1],
+ sz = s[2];
+
+ out[0] = (1 - (yy + zz)) * sx;
+ out[1] = (xy + wz) * sx;
+ out[2] = (xz - wy) * sx;
+ out[3] = 0;
+ out[4] = (xy - wz) * sy;
+ out[5] = (1 - (xx + zz)) * sy;
+ out[6] = (yz + wx) * sy;
+ out[7] = 0;
+ out[8] = (xz + wy) * sz;
+ out[9] = (yz - wx) * sz;
+ out[10] = (1 - (xx + yy)) * sz;
+ out[11] = 0;
+ out[12] = v[0];
+ out[13] = v[1];
+ out[14] = v[2];
+ out[15] = 1;
+
+ return out;
+};
+
+/**
+ * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * mat4.translate(dest, origin);
+ * var quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ * mat4.scale(dest, scale)
+ * mat4.translate(dest, negativeOrigin);
+ *
+ * @param {mat4} out mat4 receiving operation result
+ * @param {quat4} q Rotation quaternion
+ * @param {vec3} v Translation vector
+ * @param {vec3} s Scaling vector
+ * @param {vec3} o The origin vector around which to scale and rotate
+ * @returns {mat4} out
+ */
+mat4.fromRotationTranslationScaleOrigin = function (out, q, v, s, o) {
+ // Quaternion math
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2,
+
+ sx = s[0],
+ sy = s[1],
+ sz = s[2],
+
+ ox = o[0],
+ oy = o[1],
+ oz = o[2];
+
+ out[0] = (1 - (yy + zz)) * sx;
+ out[1] = (xy + wz) * sx;
+ out[2] = (xz - wy) * sx;
+ out[3] = 0;
+ out[4] = (xy - wz) * sy;
+ out[5] = (1 - (xx + zz)) * sy;
+ out[6] = (yz + wx) * sy;
+ out[7] = 0;
+ out[8] = (xz + wy) * sz;
+ out[9] = (yz - wx) * sz;
+ out[10] = (1 - (xx + yy)) * sz;
+ out[11] = 0;
+ out[12] = v[0] + ox - (out[0] * ox + out[4] * oy + out[8] * oz);
+ out[13] = v[1] + oy - (out[1] * ox + out[5] * oy + out[9] * oz);
+ out[14] = v[2] + oz - (out[2] * ox + out[6] * oy + out[10] * oz);
+ out[15] = 1;
+
+ return out;
+};
+
+mat4.fromQuat = function (out, q) {
+ var x = q[0], y = q[1], z = q[2], w = q[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ yx = y * x2,
+ yy = y * y2,
+ zx = z * x2,
+ zy = z * y2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ out[0] = 1 - yy - zz;
+ out[1] = yx + wz;
+ out[2] = zx - wy;
+ out[3] = 0;
+
+ out[4] = yx - wz;
+ out[5] = 1 - xx - zz;
+ out[6] = zy + wx;
+ out[7] = 0;
+
+ out[8] = zx + wy;
+ out[9] = zy - wx;
+ out[10] = 1 - xx - yy;
+ out[11] = 0;
+
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = 0;
+ out[15] = 1;
+
+ return out;
+};
+
+/**
+ * Generates a frustum matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {Number} left Left bound of the frustum
+ * @param {Number} right Right bound of the frustum
+ * @param {Number} bottom Bottom bound of the frustum
+ * @param {Number} top Top bound of the frustum
+ * @param {Number} near Near bound of the frustum
+ * @param {Number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+mat4.frustum = function (out, left, right, bottom, top, near, far) {
+ var rl = 1 / (right - left),
+ tb = 1 / (top - bottom),
+ nf = 1 / (near - far);
+ out[0] = (near * 2) * rl;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = (near * 2) * tb;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = (right + left) * rl;
+ out[9] = (top + bottom) * tb;
+ out[10] = (far + near) * nf;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = (far * near * 2) * nf;
+ out[15] = 0;
+ return out;
+};
+
+/**
+ * Generates a perspective projection matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fovy Vertical field of view in radians
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+mat4.perspective = function (out, fovy, aspect, near, far) {
+ var f = 1.0 / Math.tan(fovy / 2),
+ nf = 1 / (near - far);
+ out[0] = f / aspect;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = f;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = (far + near) * nf;
+ out[11] = -1;
+ out[12] = 0;
+ out[13] = 0;
+ out[14] = (2 * far * near) * nf;
+ out[15] = 0;
+ return out;
+};
+
+/**
+ * Generates a perspective projection matrix with the given field of view.
+ * This is primarily useful for generating projection matrices to be used
+ * with the still experiemental WebVR API.
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+mat4.perspectiveFromFieldOfView = function (out, fov, near, far) {
+ var upTan = Math.tan(fov.upDegrees * Math.PI/180.0),
+ downTan = Math.tan(fov.downDegrees * Math.PI/180.0),
+ leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0),
+ rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0),
+ xScale = 2.0 / (leftTan + rightTan),
+ yScale = 2.0 / (upTan + downTan);
+
+ out[0] = xScale;
+ out[1] = 0.0;
+ out[2] = 0.0;
+ out[3] = 0.0;
+ out[4] = 0.0;
+ out[5] = yScale;
+ out[6] = 0.0;
+ out[7] = 0.0;
+ out[8] = -((leftTan - rightTan) * xScale * 0.5);
+ out[9] = ((upTan - downTan) * yScale * 0.5);
+ out[10] = far / (near - far);
+ out[11] = -1.0;
+ out[12] = 0.0;
+ out[13] = 0.0;
+ out[14] = (far * near) / (near - far);
+ out[15] = 0.0;
+ return out;
+}
+
+/**
+ * Generates a orthogonal projection matrix with the given bounds
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @returns {mat4} out
+ */
+mat4.ortho = function (out, left, right, bottom, top, near, far) {
+ var lr = 1 / (left - right),
+ bt = 1 / (bottom - top),
+ nf = 1 / (near - far);
+ out[0] = -2 * lr;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ out[4] = 0;
+ out[5] = -2 * bt;
+ out[6] = 0;
+ out[7] = 0;
+ out[8] = 0;
+ out[9] = 0;
+ out[10] = 2 * nf;
+ out[11] = 0;
+ out[12] = (left + right) * lr;
+ out[13] = (top + bottom) * bt;
+ out[14] = (far + near) * nf;
+ out[15] = 1;
+ return out;
+};
+
+/**
+ * Generates a look-at matrix with the given eye position, focal point, and up axis
+ *
+ * @param {mat4} out mat4 frustum matrix will be written into
+ * @param {vec3} eye Position of the viewer
+ * @param {vec3} center Point the viewer is looking at
+ * @param {vec3} up vec3 pointing up
+ * @returns {mat4} out
+ */
+mat4.lookAt = function (out, eye, center, up) {
+ var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
+ eyex = eye[0],
+ eyey = eye[1],
+ eyez = eye[2],
+ upx = up[0],
+ upy = up[1],
+ upz = up[2],
+ centerx = center[0],
+ centery = center[1],
+ centerz = center[2];
+
+ if (Math.abs(eyex - centerx) < glMatrix.EPSILON &&
+ Math.abs(eyey - centery) < glMatrix.EPSILON &&
+ Math.abs(eyez - centerz) < glMatrix.EPSILON) {
+ return mat4.identity(out);
+ }
+
+ z0 = eyex - centerx;
+ z1 = eyey - centery;
+ z2 = eyez - centerz;
+
+ len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+
+ x0 = upy * z2 - upz * z1;
+ x1 = upz * z0 - upx * z2;
+ x2 = upx * z1 - upy * z0;
+ len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
+ if (!len) {
+ x0 = 0;
+ x1 = 0;
+ x2 = 0;
+ } else {
+ len = 1 / len;
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ y0 = z1 * x2 - z2 * x1;
+ y1 = z2 * x0 - z0 * x2;
+ y2 = z0 * x1 - z1 * x0;
+
+ len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
+ if (!len) {
+ y0 = 0;
+ y1 = 0;
+ y2 = 0;
+ } else {
+ len = 1 / len;
+ y0 *= len;
+ y1 *= len;
+ y2 *= len;
+ }
+
+ out[0] = x0;
+ out[1] = y0;
+ out[2] = z0;
+ out[3] = 0;
+ out[4] = x1;
+ out[5] = y1;
+ out[6] = z1;
+ out[7] = 0;
+ out[8] = x2;
+ out[9] = y2;
+ out[10] = z2;
+ out[11] = 0;
+ out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
+ out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
+ out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
+ out[15] = 1;
+
+ return out;
+};
+
+/**
+ * Returns a string representation of a mat4
+ *
+ * @param {mat4} mat matrix to represent as a string
+ * @returns {String} string representation of the matrix
+ */
+mat4.str = function (a) {
+ return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
+ a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
+ a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' +
+ a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
+};
+
+/**
+ * Returns Frobenius norm of a mat4
+ *
+ * @param {mat4} a the matrix to calculate Frobenius norm of
+ * @returns {Number} Frobenius norm
+ */
+mat4.frob = function (a) {
+ return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
+};
+
+
+module.exports = mat4;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/quat.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/quat.js
new file mode 100644
index 00000000000..2990f7ba52f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/quat.js
@@ -0,0 +1,553 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var glMatrix = require("./common.js");
+var mat3 = require("./mat3.js");
+var vec3 = require("./vec3.js");
+var vec4 = require("./vec4.js");
+
+/**
+ * @class Quaternion
+ * @name quat
+ */
+var quat = {};
+
+/**
+ * Creates a new identity quat
+ *
+ * @returns {quat} a new quaternion
+ */
+quat.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+};
+
+/**
+ * Sets a quaternion to represent the shortest rotation from one
+ * vector to another.
+ *
+ * Both vectors are assumed to be unit length.
+ *
+ * @param {quat} out the receiving quaternion.
+ * @param {vec3} a the initial vector
+ * @param {vec3} b the destination vector
+ * @returns {quat} out
+ */
+quat.rotationTo = (function() {
+ var tmpvec3 = vec3.create();
+ var xUnitVec3 = vec3.fromValues(1,0,0);
+ var yUnitVec3 = vec3.fromValues(0,1,0);
+
+ return function(out, a, b) {
+ var dot = vec3.dot(a, b);
+ if (dot < -0.999999) {
+ vec3.cross(tmpvec3, xUnitVec3, a);
+ if (vec3.length(tmpvec3) < 0.000001)
+ vec3.cross(tmpvec3, yUnitVec3, a);
+ vec3.normalize(tmpvec3, tmpvec3);
+ quat.setAxisAngle(out, tmpvec3, Math.PI);
+ return out;
+ } else if (dot > 0.999999) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+ } else {
+ vec3.cross(tmpvec3, a, b);
+ out[0] = tmpvec3[0];
+ out[1] = tmpvec3[1];
+ out[2] = tmpvec3[2];
+ out[3] = 1 + dot;
+ return quat.normalize(out, out);
+ }
+ };
+})();
+
+/**
+ * Sets the specified quaternion with values corresponding to the given
+ * axes. Each axis is a vec3 and is expected to be unit length and
+ * perpendicular to all other specified axes.
+ *
+ * @param {vec3} view the vector representing the viewing direction
+ * @param {vec3} right the vector representing the local "right" direction
+ * @param {vec3} up the vector representing the local "up" direction
+ * @returns {quat} out
+ */
+quat.setAxes = (function() {
+ var matr = mat3.create();
+
+ return function(out, view, right, up) {
+ matr[0] = right[0];
+ matr[3] = right[1];
+ matr[6] = right[2];
+
+ matr[1] = up[0];
+ matr[4] = up[1];
+ matr[7] = up[2];
+
+ matr[2] = -view[0];
+ matr[5] = -view[1];
+ matr[8] = -view[2];
+
+ return quat.normalize(out, quat.fromMat3(out, matr));
+ };
+})();
+
+/**
+ * Creates a new quat initialized with values from an existing quaternion
+ *
+ * @param {quat} a quaternion to clone
+ * @returns {quat} a new quaternion
+ * @function
+ */
+quat.clone = vec4.clone;
+
+/**
+ * Creates a new quat initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} a new quaternion
+ * @function
+ */
+quat.fromValues = vec4.fromValues;
+
+/**
+ * Copy the values from one quat to another
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the source quaternion
+ * @returns {quat} out
+ * @function
+ */
+quat.copy = vec4.copy;
+
+/**
+ * Set the components of a quat to the given values
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {quat} out
+ * @function
+ */
+quat.set = vec4.set;
+
+/**
+ * Set a quat to the identity quaternion
+ *
+ * @param {quat} out the receiving quaternion
+ * @returns {quat} out
+ */
+quat.identity = function(out) {
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+ return out;
+};
+
+/**
+ * Sets a quat from the given angle and rotation axis,
+ * then returns it.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {vec3} axis the axis around which to rotate
+ * @param {Number} rad the angle in radians
+ * @returns {quat} out
+ **/
+quat.setAxisAngle = function(out, axis, rad) {
+ rad = rad * 0.5;
+ var s = Math.sin(rad);
+ out[0] = s * axis[0];
+ out[1] = s * axis[1];
+ out[2] = s * axis[2];
+ out[3] = Math.cos(rad);
+ return out;
+};
+
+/**
+ * Adds two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @returns {quat} out
+ * @function
+ */
+quat.add = vec4.add;
+
+/**
+ * Multiplies two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @returns {quat} out
+ */
+quat.multiply = function(out, a, b) {
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ bx = b[0], by = b[1], bz = b[2], bw = b[3];
+
+ out[0] = ax * bw + aw * bx + ay * bz - az * by;
+ out[1] = ay * bw + aw * by + az * bx - ax * bz;
+ out[2] = az * bw + aw * bz + ax * by - ay * bx;
+ out[3] = aw * bw - ax * bx - ay * by - az * bz;
+ return out;
+};
+
+/**
+ * Alias for {@link quat.multiply}
+ * @function
+ */
+quat.mul = quat.multiply;
+
+/**
+ * Scales a quat by a scalar number
+ *
+ * @param {quat} out the receiving vector
+ * @param {quat} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {quat} out
+ * @function
+ */
+quat.scale = vec4.scale;
+
+/**
+ * Rotates a quaternion by the given angle about the X axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {quat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+quat.rotateX = function (out, a, rad) {
+ rad *= 0.5;
+
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ bx = Math.sin(rad), bw = Math.cos(rad);
+
+ out[0] = ax * bw + aw * bx;
+ out[1] = ay * bw + az * bx;
+ out[2] = az * bw - ay * bx;
+ out[3] = aw * bw - ax * bx;
+ return out;
+};
+
+/**
+ * Rotates a quaternion by the given angle about the Y axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {quat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+quat.rotateY = function (out, a, rad) {
+ rad *= 0.5;
+
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ by = Math.sin(rad), bw = Math.cos(rad);
+
+ out[0] = ax * bw - az * by;
+ out[1] = ay * bw + aw * by;
+ out[2] = az * bw + ax * by;
+ out[3] = aw * bw - ay * by;
+ return out;
+};
+
+/**
+ * Rotates a quaternion by the given angle about the Z axis
+ *
+ * @param {quat} out quat receiving operation result
+ * @param {quat} a quat to rotate
+ * @param {number} rad angle (in radians) to rotate
+ * @returns {quat} out
+ */
+quat.rotateZ = function (out, a, rad) {
+ rad *= 0.5;
+
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ bz = Math.sin(rad), bw = Math.cos(rad);
+
+ out[0] = ax * bw + ay * bz;
+ out[1] = ay * bw - ax * bz;
+ out[2] = az * bw + aw * bz;
+ out[3] = aw * bw - az * bz;
+ return out;
+};
+
+/**
+ * Calculates the W component of a quat from the X, Y, and Z components.
+ * Assumes that quaternion is 1 unit in length.
+ * Any existing W component will be ignored.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quat to calculate W component of
+ * @returns {quat} out
+ */
+quat.calculateW = function (out, a) {
+ var x = a[0], y = a[1], z = a[2];
+
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
+ return out;
+};
+
+/**
+ * Calculates the dot product of two quat's
+ *
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @returns {Number} dot product of a and b
+ * @function
+ */
+quat.dot = vec4.dot;
+
+/**
+ * Performs a linear interpolation between two quat's
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {quat} out
+ * @function
+ */
+quat.lerp = vec4.lerp;
+
+/**
+ * Performs a spherical linear interpolation between two quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {quat} out
+ */
+quat.slerp = function (out, a, b, t) {
+ // benchmarks:
+ // http://jsperf.com/quaternion-slerp-implementations
+
+ var ax = a[0], ay = a[1], az = a[2], aw = a[3],
+ bx = b[0], by = b[1], bz = b[2], bw = b[3];
+
+ var omega, cosom, sinom, scale0, scale1;
+
+ // calc cosine
+ cosom = ax * bx + ay * by + az * bz + aw * bw;
+ // adjust signs (if necessary)
+ if ( cosom < 0.0 ) {
+ cosom = -cosom;
+ bx = - bx;
+ by = - by;
+ bz = - bz;
+ bw = - bw;
+ }
+ // calculate coefficients
+ if ( (1.0 - cosom) > 0.000001 ) {
+ // standard case (slerp)
+ omega = Math.acos(cosom);
+ sinom = Math.sin(omega);
+ scale0 = Math.sin((1.0 - t) * omega) / sinom;
+ scale1 = Math.sin(t * omega) / sinom;
+ } else {
+ // "from" and "to" quaternions are very close
+ // ... so we can do a linear interpolation
+ scale0 = 1.0 - t;
+ scale1 = t;
+ }
+ // calculate final values
+ out[0] = scale0 * ax + scale1 * bx;
+ out[1] = scale0 * ay + scale1 * by;
+ out[2] = scale0 * az + scale1 * bz;
+ out[3] = scale0 * aw + scale1 * bw;
+
+ return out;
+};
+
+/**
+ * Performs a spherical linear interpolation with two control points
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a the first operand
+ * @param {quat} b the second operand
+ * @param {quat} c the third operand
+ * @param {quat} d the fourth operand
+ * @param {Number} t interpolation amount
+ * @returns {quat} out
+ */
+quat.sqlerp = (function () {
+ var temp1 = quat.create();
+ var temp2 = quat.create();
+
+ return function (out, a, b, c, d, t) {
+ quat.slerp(temp1, a, d, t);
+ quat.slerp(temp2, b, c, t);
+ quat.slerp(out, temp1, temp2, 2 * t * (1 - t));
+
+ return out;
+ };
+}());
+
+/**
+ * Calculates the inverse of a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quat to calculate inverse of
+ * @returns {quat} out
+ */
+quat.invert = function(out, a) {
+ var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
+ dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
+ invDot = dot ? 1.0/dot : 0;
+
+ // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
+
+ out[0] = -a0*invDot;
+ out[1] = -a1*invDot;
+ out[2] = -a2*invDot;
+ out[3] = a3*invDot;
+ return out;
+};
+
+/**
+ * Calculates the conjugate of a quat
+ * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quat to calculate conjugate of
+ * @returns {quat} out
+ */
+quat.conjugate = function (out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = a[3];
+ return out;
+};
+
+/**
+ * Calculates the length of a quat
+ *
+ * @param {quat} a vector to calculate length of
+ * @returns {Number} length of a
+ * @function
+ */
+quat.length = vec4.length;
+
+/**
+ * Alias for {@link quat.length}
+ * @function
+ */
+quat.len = quat.length;
+
+/**
+ * Calculates the squared length of a quat
+ *
+ * @param {quat} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ * @function
+ */
+quat.squaredLength = vec4.squaredLength;
+
+/**
+ * Alias for {@link quat.squaredLength}
+ * @function
+ */
+quat.sqrLen = quat.squaredLength;
+
+/**
+ * Normalize a quat
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {quat} a quaternion to normalize
+ * @returns {quat} out
+ * @function
+ */
+quat.normalize = vec4.normalize;
+
+/**
+ * Creates a quaternion from the given 3x3 rotation matrix.
+ *
+ * NOTE: The resultant quaternion is not normalized, so you should be sure
+ * to renormalize the quaternion yourself where necessary.
+ *
+ * @param {quat} out the receiving quaternion
+ * @param {mat3} m rotation matrix
+ * @returns {quat} out
+ * @function
+ */
+quat.fromMat3 = function(out, m) {
+ // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
+ // article "Quaternion Calculus and Fast Animation".
+ var fTrace = m[0] + m[4] + m[8];
+ var fRoot;
+
+ if ( fTrace > 0.0 ) {
+ // |w| > 1/2, may as well choose w > 1/2
+ fRoot = Math.sqrt(fTrace + 1.0); // 2w
+ out[3] = 0.5 * fRoot;
+ fRoot = 0.5/fRoot; // 1/(4w)
+ out[0] = (m[5]-m[7])*fRoot;
+ out[1] = (m[6]-m[2])*fRoot;
+ out[2] = (m[1]-m[3])*fRoot;
+ } else {
+ // |w| <= 1/2
+ var i = 0;
+ if ( m[4] > m[0] )
+ i = 1;
+ if ( m[8] > m[i*3+i] )
+ i = 2;
+ var j = (i+1)%3;
+ var k = (i+2)%3;
+
+ fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
+ out[i] = 0.5 * fRoot;
+ fRoot = 0.5 / fRoot;
+ out[3] = (m[j*3+k] - m[k*3+j]) * fRoot;
+ out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
+ out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
+ }
+
+ return out;
+};
+
+/**
+ * Returns a string representation of a quatenion
+ *
+ * @param {quat} vec vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+quat.str = function (a) {
+ return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
+};
+
+module.exports = quat;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec2.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec2.js
new file mode 100644
index 00000000000..9e790563af5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec2.js
@@ -0,0 +1,523 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var glMatrix = require("./common.js");
+
+/**
+ * @class 2 Dimensional Vector
+ * @name vec2
+ */
+var vec2 = {};
+
+/**
+ * Creates a new, empty vec2
+ *
+ * @returns {vec2} a new 2D vector
+ */
+vec2.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = 0;
+ out[1] = 0;
+ return out;
+};
+
+/**
+ * Creates a new vec2 initialized with values from an existing vector
+ *
+ * @param {vec2} a vector to clone
+ * @returns {vec2} a new 2D vector
+ */
+vec2.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+};
+
+/**
+ * Creates a new vec2 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} a new 2D vector
+ */
+vec2.fromValues = function(x, y) {
+ var out = new glMatrix.ARRAY_TYPE(2);
+ out[0] = x;
+ out[1] = y;
+ return out;
+};
+
+/**
+ * Copy the values from one vec2 to another
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the source vector
+ * @returns {vec2} out
+ */
+vec2.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ return out;
+};
+
+/**
+ * Set the components of a vec2 to the given values
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @returns {vec2} out
+ */
+vec2.set = function(out, x, y) {
+ out[0] = x;
+ out[1] = y;
+ return out;
+};
+
+/**
+ * Adds two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+vec2.add = function(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ return out;
+};
+
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+vec2.subtract = function(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ return out;
+};
+
+/**
+ * Alias for {@link vec2.subtract}
+ * @function
+ */
+vec2.sub = vec2.subtract;
+
+/**
+ * Multiplies two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+vec2.multiply = function(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ return out;
+};
+
+/**
+ * Alias for {@link vec2.multiply}
+ * @function
+ */
+vec2.mul = vec2.multiply;
+
+/**
+ * Divides two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+vec2.divide = function(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ return out;
+};
+
+/**
+ * Alias for {@link vec2.divide}
+ * @function
+ */
+vec2.div = vec2.divide;
+
+/**
+ * Returns the minimum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+vec2.min = function(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ return out;
+};
+
+/**
+ * Returns the maximum of two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec2} out
+ */
+vec2.max = function(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ return out;
+};
+
+/**
+ * Scales a vec2 by a scalar number
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec2} out
+ */
+vec2.scale = function(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ return out;
+};
+
+/**
+ * Adds two vec2's after scaling the second operand by a scalar value
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec2} out
+ */
+vec2.scaleAndAdd = function(out, a, b, scale) {
+ out[0] = a[0] + (b[0] * scale);
+ out[1] = a[1] + (b[1] * scale);
+ return out;
+};
+
+/**
+ * Calculates the euclidian distance between two vec2's
+ *
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {Number} distance between a and b
+ */
+vec2.distance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return Math.sqrt(x*x + y*y);
+};
+
+/**
+ * Alias for {@link vec2.distance}
+ * @function
+ */
+vec2.dist = vec2.distance;
+
+/**
+ * Calculates the squared euclidian distance between two vec2's
+ *
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+vec2.squaredDistance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1];
+ return x*x + y*y;
+};
+
+/**
+ * Alias for {@link vec2.squaredDistance}
+ * @function
+ */
+vec2.sqrDist = vec2.squaredDistance;
+
+/**
+ * Calculates the length of a vec2
+ *
+ * @param {vec2} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+vec2.length = function (a) {
+ var x = a[0],
+ y = a[1];
+ return Math.sqrt(x*x + y*y);
+};
+
+/**
+ * Alias for {@link vec2.length}
+ * @function
+ */
+vec2.len = vec2.length;
+
+/**
+ * Calculates the squared length of a vec2
+ *
+ * @param {vec2} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+vec2.squaredLength = function (a) {
+ var x = a[0],
+ y = a[1];
+ return x*x + y*y;
+};
+
+/**
+ * Alias for {@link vec2.squaredLength}
+ * @function
+ */
+vec2.sqrLen = vec2.squaredLength;
+
+/**
+ * Negates the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to negate
+ * @returns {vec2} out
+ */
+vec2.negate = function(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ return out;
+};
+
+/**
+ * Returns the inverse of the components of a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to invert
+ * @returns {vec2} out
+ */
+vec2.inverse = function(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ return out;
+};
+
+/**
+ * Normalize a vec2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a vector to normalize
+ * @returns {vec2} out
+ */
+vec2.normalize = function(out, a) {
+ var x = a[0],
+ y = a[1];
+ var len = x*x + y*y;
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ }
+ return out;
+};
+
+/**
+ * Calculates the dot product of two vec2's
+ *
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+vec2.dot = function (a, b) {
+ return a[0] * b[0] + a[1] * b[1];
+};
+
+/**
+ * Computes the cross product of two vec2's
+ * Note that the cross product must by definition produce a 3D vector
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @returns {vec3} out
+ */
+vec2.cross = function(out, a, b) {
+ var z = a[0] * b[1] - a[1] * b[0];
+ out[0] = out[1] = 0;
+ out[2] = z;
+ return out;
+};
+
+/**
+ * Performs a linear interpolation between two vec2's
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the first operand
+ * @param {vec2} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec2} out
+ */
+vec2.lerp = function (out, a, b, t) {
+ var ax = a[0],
+ ay = a[1];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ return out;
+};
+
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec2} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec2} out
+ */
+vec2.random = function (out, scale) {
+ scale = scale || 1.0;
+ var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+ out[0] = Math.cos(r) * scale;
+ out[1] = Math.sin(r) * scale;
+ return out;
+};
+
+/**
+ * Transforms the vec2 with a mat2
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat2} m matrix to transform with
+ * @returns {vec2} out
+ */
+vec2.transformMat2 = function(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y;
+ out[1] = m[1] * x + m[3] * y;
+ return out;
+};
+
+/**
+ * Transforms the vec2 with a mat2d
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat2d} m matrix to transform with
+ * @returns {vec2} out
+ */
+vec2.transformMat2d = function(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[2] * y + m[4];
+ out[1] = m[1] * x + m[3] * y + m[5];
+ return out;
+};
+
+/**
+ * Transforms the vec2 with a mat3
+ * 3rd vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat3} m matrix to transform with
+ * @returns {vec2} out
+ */
+vec2.transformMat3 = function(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[3] * y + m[6];
+ out[1] = m[1] * x + m[4] * y + m[7];
+ return out;
+};
+
+/**
+ * Transforms the vec2 with a mat4
+ * 3rd vector component is implicitly '0'
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec2} out the receiving vector
+ * @param {vec2} a the vector to transform
+ * @param {mat4} m matrix to transform with
+ * @returns {vec2} out
+ */
+vec2.transformMat4 = function(out, a, m) {
+ var x = a[0],
+ y = a[1];
+ out[0] = m[0] * x + m[4] * y + m[12];
+ out[1] = m[1] * x + m[5] * y + m[13];
+ return out;
+};
+
+/**
+ * Perform some operation over an array of vec2s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+vec2.forEach = (function() {
+ var vec = vec2.create();
+
+ return function(a, stride, offset, count, fn, arg) {
+ var i, l;
+ if(!stride) {
+ stride = 2;
+ }
+
+ if(!offset) {
+ offset = 0;
+ }
+
+ if(count) {
+ l = Math.min((count * stride) + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for(i = offset; i < l; i += stride) {
+ vec[0] = a[i]; vec[1] = a[i+1];
+ fn(vec, vec, arg);
+ a[i] = vec[0]; a[i+1] = vec[1];
+ }
+
+ return a;
+ };
+})();
+
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {vec2} vec vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+vec2.str = function (a) {
+ return 'vec2(' + a[0] + ', ' + a[1] + ')';
+};
+
+module.exports = vec2;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec3.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec3.js
new file mode 100644
index 00000000000..c0676feefcd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec3.js
@@ -0,0 +1,709 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var glMatrix = require("./common.js");
+
+/**
+ * @class 3 Dimensional Vector
+ * @name vec3
+ */
+var vec3 = {};
+
+/**
+ * Creates a new, empty vec3
+ *
+ * @returns {vec3} a new 3D vector
+ */
+vec3.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ return out;
+};
+
+/**
+ * Creates a new vec3 initialized with values from an existing vector
+ *
+ * @param {vec3} a vector to clone
+ * @returns {vec3} a new 3D vector
+ */
+vec3.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+};
+
+/**
+ * Creates a new vec3 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} a new 3D vector
+ */
+vec3.fromValues = function(x, y, z) {
+ var out = new glMatrix.ARRAY_TYPE(3);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+};
+
+/**
+ * Copy the values from one vec3 to another
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the source vector
+ * @returns {vec3} out
+ */
+vec3.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ return out;
+};
+
+/**
+ * Set the components of a vec3 to the given values
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @returns {vec3} out
+ */
+vec3.set = function(out, x, y, z) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ return out;
+};
+
+/**
+ * Adds two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+vec3.add = function(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ return out;
+};
+
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+vec3.subtract = function(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ return out;
+};
+
+/**
+ * Alias for {@link vec3.subtract}
+ * @function
+ */
+vec3.sub = vec3.subtract;
+
+/**
+ * Multiplies two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+vec3.multiply = function(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ return out;
+};
+
+/**
+ * Alias for {@link vec3.multiply}
+ * @function
+ */
+vec3.mul = vec3.multiply;
+
+/**
+ * Divides two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+vec3.divide = function(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ return out;
+};
+
+/**
+ * Alias for {@link vec3.divide}
+ * @function
+ */
+vec3.div = vec3.divide;
+
+/**
+ * Returns the minimum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+vec3.min = function(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ return out;
+};
+
+/**
+ * Returns the maximum of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+vec3.max = function(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ return out;
+};
+
+/**
+ * Scales a vec3 by a scalar number
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec3} out
+ */
+vec3.scale = function(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ return out;
+};
+
+/**
+ * Adds two vec3's after scaling the second operand by a scalar value
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec3} out
+ */
+vec3.scaleAndAdd = function(out, a, b, scale) {
+ out[0] = a[0] + (b[0] * scale);
+ out[1] = a[1] + (b[1] * scale);
+ out[2] = a[2] + (b[2] * scale);
+ return out;
+};
+
+/**
+ * Calculates the euclidian distance between two vec3's
+ *
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {Number} distance between a and b
+ */
+vec3.distance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1],
+ z = b[2] - a[2];
+ return Math.sqrt(x*x + y*y + z*z);
+};
+
+/**
+ * Alias for {@link vec3.distance}
+ * @function
+ */
+vec3.dist = vec3.distance;
+
+/**
+ * Calculates the squared euclidian distance between two vec3's
+ *
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+vec3.squaredDistance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1],
+ z = b[2] - a[2];
+ return x*x + y*y + z*z;
+};
+
+/**
+ * Alias for {@link vec3.squaredDistance}
+ * @function
+ */
+vec3.sqrDist = vec3.squaredDistance;
+
+/**
+ * Calculates the length of a vec3
+ *
+ * @param {vec3} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+vec3.length = function (a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ return Math.sqrt(x*x + y*y + z*z);
+};
+
+/**
+ * Alias for {@link vec3.length}
+ * @function
+ */
+vec3.len = vec3.length;
+
+/**
+ * Calculates the squared length of a vec3
+ *
+ * @param {vec3} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+vec3.squaredLength = function (a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ return x*x + y*y + z*z;
+};
+
+/**
+ * Alias for {@link vec3.squaredLength}
+ * @function
+ */
+vec3.sqrLen = vec3.squaredLength;
+
+/**
+ * Negates the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a vector to negate
+ * @returns {vec3} out
+ */
+vec3.negate = function(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ return out;
+};
+
+/**
+ * Returns the inverse of the components of a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a vector to invert
+ * @returns {vec3} out
+ */
+vec3.inverse = function(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ return out;
+};
+
+/**
+ * Normalize a vec3
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a vector to normalize
+ * @returns {vec3} out
+ */
+vec3.normalize = function(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2];
+ var len = x*x + y*y + z*z;
+ if (len > 0) {
+ //TODO: evaluate use of glm_invsqrt here?
+ len = 1 / Math.sqrt(len);
+ out[0] = a[0] * len;
+ out[1] = a[1] * len;
+ out[2] = a[2] * len;
+ }
+ return out;
+};
+
+/**
+ * Calculates the dot product of two vec3's
+ *
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+vec3.dot = function (a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+};
+
+/**
+ * Computes the cross product of two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @returns {vec3} out
+ */
+vec3.cross = function(out, a, b) {
+ var ax = a[0], ay = a[1], az = a[2],
+ bx = b[0], by = b[1], bz = b[2];
+
+ out[0] = ay * bz - az * by;
+ out[1] = az * bx - ax * bz;
+ out[2] = ax * by - ay * bx;
+ return out;
+};
+
+/**
+ * Performs a linear interpolation between two vec3's
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec3} out
+ */
+vec3.lerp = function (out, a, b, t) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ return out;
+};
+
+/**
+ * Performs a hermite interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @param {vec3} c the third operand
+ * @param {vec3} d the fourth operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec3} out
+ */
+vec3.hermite = function (out, a, b, c, d, t) {
+ var factorTimes2 = t * t,
+ factor1 = factorTimes2 * (2 * t - 3) + 1,
+ factor2 = factorTimes2 * (t - 2) + t,
+ factor3 = factorTimes2 * (t - 1),
+ factor4 = factorTimes2 * (3 - 2 * t);
+
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+
+ return out;
+};
+
+/**
+ * Performs a bezier interpolation with two control points
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the first operand
+ * @param {vec3} b the second operand
+ * @param {vec3} c the third operand
+ * @param {vec3} d the fourth operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec3} out
+ */
+vec3.bezier = function (out, a, b, c, d, t) {
+ var inverseFactor = 1 - t,
+ inverseFactorTimesTwo = inverseFactor * inverseFactor,
+ factorTimes2 = t * t,
+ factor1 = inverseFactorTimesTwo * inverseFactor,
+ factor2 = 3 * t * inverseFactorTimesTwo,
+ factor3 = 3 * factorTimes2 * inverseFactor,
+ factor4 = factorTimes2 * t;
+
+ out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
+ out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
+ out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
+
+ return out;
+};
+
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec3} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec3} out
+ */
+vec3.random = function (out, scale) {
+ scale = scale || 1.0;
+
+ var r = glMatrix.RANDOM() * 2.0 * Math.PI;
+ var z = (glMatrix.RANDOM() * 2.0) - 1.0;
+ var zScale = Math.sqrt(1.0-z*z) * scale;
+
+ out[0] = Math.cos(r) * zScale;
+ out[1] = Math.sin(r) * zScale;
+ out[2] = z * scale;
+ return out;
+};
+
+/**
+ * Transforms the vec3 with a mat4.
+ * 4th vector component is implicitly '1'
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the vector to transform
+ * @param {mat4} m matrix to transform with
+ * @returns {vec3} out
+ */
+vec3.transformMat4 = function(out, a, m) {
+ var x = a[0], y = a[1], z = a[2],
+ w = m[3] * x + m[7] * y + m[11] * z + m[15];
+ w = w || 1.0;
+ out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
+ out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
+ out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
+ return out;
+};
+
+/**
+ * Transforms the vec3 with a mat3.
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the vector to transform
+ * @param {mat4} m the 3x3 matrix to transform with
+ * @returns {vec3} out
+ */
+vec3.transformMat3 = function(out, a, m) {
+ var x = a[0], y = a[1], z = a[2];
+ out[0] = x * m[0] + y * m[3] + z * m[6];
+ out[1] = x * m[1] + y * m[4] + z * m[7];
+ out[2] = x * m[2] + y * m[5] + z * m[8];
+ return out;
+};
+
+/**
+ * Transforms the vec3 with a quat
+ *
+ * @param {vec3} out the receiving vector
+ * @param {vec3} a the vector to transform
+ * @param {quat} q quaternion to transform with
+ * @returns {vec3} out
+ */
+vec3.transformQuat = function(out, a, q) {
+ // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
+
+ var x = a[0], y = a[1], z = a[2],
+ qx = q[0], qy = q[1], qz = q[2], qw = q[3],
+
+ // calculate quat * vec
+ ix = qw * x + qy * z - qz * y,
+ iy = qw * y + qz * x - qx * z,
+ iz = qw * z + qx * y - qy * x,
+ iw = -qx * x - qy * y - qz * z;
+
+ // calculate result * inverse quat
+ out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
+ out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
+ out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
+ return out;
+};
+
+/**
+ * Rotate a 3D vector around the x-axis
+ * @param {vec3} out The receiving vec3
+ * @param {vec3} a The vec3 point to rotate
+ * @param {vec3} b The origin of the rotation
+ * @param {Number} c The angle of rotation
+ * @returns {vec3} out
+ */
+vec3.rotateX = function(out, a, b, c){
+ var p = [], r=[];
+ //Translate point to the origin
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2];
+
+ //perform rotation
+ r[0] = p[0];
+ r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c);
+ r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c);
+
+ //translate to correct position
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+
+ return out;
+};
+
+/**
+ * Rotate a 3D vector around the y-axis
+ * @param {vec3} out The receiving vec3
+ * @param {vec3} a The vec3 point to rotate
+ * @param {vec3} b The origin of the rotation
+ * @param {Number} c The angle of rotation
+ * @returns {vec3} out
+ */
+vec3.rotateY = function(out, a, b, c){
+ var p = [], r=[];
+ //Translate point to the origin
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2];
+
+ //perform rotation
+ r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c);
+ r[1] = p[1];
+ r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c);
+
+ //translate to correct position
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+
+ return out;
+};
+
+/**
+ * Rotate a 3D vector around the z-axis
+ * @param {vec3} out The receiving vec3
+ * @param {vec3} a The vec3 point to rotate
+ * @param {vec3} b The origin of the rotation
+ * @param {Number} c The angle of rotation
+ * @returns {vec3} out
+ */
+vec3.rotateZ = function(out, a, b, c){
+ var p = [], r=[];
+ //Translate point to the origin
+ p[0] = a[0] - b[0];
+ p[1] = a[1] - b[1];
+ p[2] = a[2] - b[2];
+
+ //perform rotation
+ r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c);
+ r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c);
+ r[2] = p[2];
+
+ //translate to correct position
+ out[0] = r[0] + b[0];
+ out[1] = r[1] + b[1];
+ out[2] = r[2] + b[2];
+
+ return out;
+};
+
+/**
+ * Perform some operation over an array of vec3s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+vec3.forEach = (function() {
+ var vec = vec3.create();
+
+ return function(a, stride, offset, count, fn, arg) {
+ var i, l;
+ if(!stride) {
+ stride = 3;
+ }
+
+ if(!offset) {
+ offset = 0;
+ }
+
+ if(count) {
+ l = Math.min((count * stride) + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for(i = offset; i < l; i += stride) {
+ vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
+ fn(vec, vec, arg);
+ a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
+ }
+
+ return a;
+ };
+})();
+
+/**
+ * Get the angle between two 3D vectors
+ * @param {vec3} a The first operand
+ * @param {vec3} b The second operand
+ * @returns {Number} The angle in radians
+ */
+vec3.angle = function(a, b) {
+
+ var tempA = vec3.fromValues(a[0], a[1], a[2]);
+ var tempB = vec3.fromValues(b[0], b[1], b[2]);
+
+ vec3.normalize(tempA, tempA);
+ vec3.normalize(tempB, tempB);
+
+ var cosine = vec3.dot(tempA, tempB);
+
+ if(cosine > 1.0){
+ return 0;
+ } else {
+ return Math.acos(cosine);
+ }
+};
+
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {vec3} vec vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+vec3.str = function (a) {
+ return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
+};
+
+module.exports = vec3;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec4.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec4.js
new file mode 100644
index 00000000000..f18d17440ae
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/src/gl-matrix/vec4.js
@@ -0,0 +1,537 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var glMatrix = require("./common.js");
+
+/**
+ * @class 4 Dimensional Vector
+ * @name vec4
+ */
+var vec4 = {};
+
+/**
+ * Creates a new, empty vec4
+ *
+ * @returns {vec4} a new 4D vector
+ */
+vec4.create = function() {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = 0;
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 0;
+ return out;
+};
+
+/**
+ * Creates a new vec4 initialized with values from an existing vector
+ *
+ * @param {vec4} a vector to clone
+ * @returns {vec4} a new 4D vector
+ */
+vec4.clone = function(a) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+};
+
+/**
+ * Creates a new vec4 initialized with the given values
+ *
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} a new 4D vector
+ */
+vec4.fromValues = function(x, y, z, w) {
+ var out = new glMatrix.ARRAY_TYPE(4);
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+};
+
+/**
+ * Copy the values from one vec4 to another
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the source vector
+ * @returns {vec4} out
+ */
+vec4.copy = function(out, a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+};
+
+/**
+ * Set the components of a vec4 to the given values
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} x X component
+ * @param {Number} y Y component
+ * @param {Number} z Z component
+ * @param {Number} w W component
+ * @returns {vec4} out
+ */
+vec4.set = function(out, x, y, z, w) {
+ out[0] = x;
+ out[1] = y;
+ out[2] = z;
+ out[3] = w;
+ return out;
+};
+
+/**
+ * Adds two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+vec4.add = function(out, a, b) {
+ out[0] = a[0] + b[0];
+ out[1] = a[1] + b[1];
+ out[2] = a[2] + b[2];
+ out[3] = a[3] + b[3];
+ return out;
+};
+
+/**
+ * Subtracts vector b from vector a
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+vec4.subtract = function(out, a, b) {
+ out[0] = a[0] - b[0];
+ out[1] = a[1] - b[1];
+ out[2] = a[2] - b[2];
+ out[3] = a[3] - b[3];
+ return out;
+};
+
+/**
+ * Alias for {@link vec4.subtract}
+ * @function
+ */
+vec4.sub = vec4.subtract;
+
+/**
+ * Multiplies two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+vec4.multiply = function(out, a, b) {
+ out[0] = a[0] * b[0];
+ out[1] = a[1] * b[1];
+ out[2] = a[2] * b[2];
+ out[3] = a[3] * b[3];
+ return out;
+};
+
+/**
+ * Alias for {@link vec4.multiply}
+ * @function
+ */
+vec4.mul = vec4.multiply;
+
+/**
+ * Divides two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+vec4.divide = function(out, a, b) {
+ out[0] = a[0] / b[0];
+ out[1] = a[1] / b[1];
+ out[2] = a[2] / b[2];
+ out[3] = a[3] / b[3];
+ return out;
+};
+
+/**
+ * Alias for {@link vec4.divide}
+ * @function
+ */
+vec4.div = vec4.divide;
+
+/**
+ * Returns the minimum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+vec4.min = function(out, a, b) {
+ out[0] = Math.min(a[0], b[0]);
+ out[1] = Math.min(a[1], b[1]);
+ out[2] = Math.min(a[2], b[2]);
+ out[3] = Math.min(a[3], b[3]);
+ return out;
+};
+
+/**
+ * Returns the maximum of two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {vec4} out
+ */
+vec4.max = function(out, a, b) {
+ out[0] = Math.max(a[0], b[0]);
+ out[1] = Math.max(a[1], b[1]);
+ out[2] = Math.max(a[2], b[2]);
+ out[3] = Math.max(a[3], b[3]);
+ return out;
+};
+
+/**
+ * Scales a vec4 by a scalar number
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the vector to scale
+ * @param {Number} b amount to scale the vector by
+ * @returns {vec4} out
+ */
+vec4.scale = function(out, a, b) {
+ out[0] = a[0] * b;
+ out[1] = a[1] * b;
+ out[2] = a[2] * b;
+ out[3] = a[3] * b;
+ return out;
+};
+
+/**
+ * Adds two vec4's after scaling the second operand by a scalar value
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @param {Number} scale the amount to scale b by before adding
+ * @returns {vec4} out
+ */
+vec4.scaleAndAdd = function(out, a, b, scale) {
+ out[0] = a[0] + (b[0] * scale);
+ out[1] = a[1] + (b[1] * scale);
+ out[2] = a[2] + (b[2] * scale);
+ out[3] = a[3] + (b[3] * scale);
+ return out;
+};
+
+/**
+ * Calculates the euclidian distance between two vec4's
+ *
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {Number} distance between a and b
+ */
+vec4.distance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1],
+ z = b[2] - a[2],
+ w = b[3] - a[3];
+ return Math.sqrt(x*x + y*y + z*z + w*w);
+};
+
+/**
+ * Alias for {@link vec4.distance}
+ * @function
+ */
+vec4.dist = vec4.distance;
+
+/**
+ * Calculates the squared euclidian distance between two vec4's
+ *
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {Number} squared distance between a and b
+ */
+vec4.squaredDistance = function(a, b) {
+ var x = b[0] - a[0],
+ y = b[1] - a[1],
+ z = b[2] - a[2],
+ w = b[3] - a[3];
+ return x*x + y*y + z*z + w*w;
+};
+
+/**
+ * Alias for {@link vec4.squaredDistance}
+ * @function
+ */
+vec4.sqrDist = vec4.squaredDistance;
+
+/**
+ * Calculates the length of a vec4
+ *
+ * @param {vec4} a vector to calculate length of
+ * @returns {Number} length of a
+ */
+vec4.length = function (a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ return Math.sqrt(x*x + y*y + z*z + w*w);
+};
+
+/**
+ * Alias for {@link vec4.length}
+ * @function
+ */
+vec4.len = vec4.length;
+
+/**
+ * Calculates the squared length of a vec4
+ *
+ * @param {vec4} a vector to calculate squared length of
+ * @returns {Number} squared length of a
+ */
+vec4.squaredLength = function (a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ return x*x + y*y + z*z + w*w;
+};
+
+/**
+ * Alias for {@link vec4.squaredLength}
+ * @function
+ */
+vec4.sqrLen = vec4.squaredLength;
+
+/**
+ * Negates the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a vector to negate
+ * @returns {vec4} out
+ */
+vec4.negate = function(out, a) {
+ out[0] = -a[0];
+ out[1] = -a[1];
+ out[2] = -a[2];
+ out[3] = -a[3];
+ return out;
+};
+
+/**
+ * Returns the inverse of the components of a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a vector to invert
+ * @returns {vec4} out
+ */
+vec4.inverse = function(out, a) {
+ out[0] = 1.0 / a[0];
+ out[1] = 1.0 / a[1];
+ out[2] = 1.0 / a[2];
+ out[3] = 1.0 / a[3];
+ return out;
+};
+
+/**
+ * Normalize a vec4
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a vector to normalize
+ * @returns {vec4} out
+ */
+vec4.normalize = function(out, a) {
+ var x = a[0],
+ y = a[1],
+ z = a[2],
+ w = a[3];
+ var len = x*x + y*y + z*z + w*w;
+ if (len > 0) {
+ len = 1 / Math.sqrt(len);
+ out[0] = x * len;
+ out[1] = y * len;
+ out[2] = z * len;
+ out[3] = w * len;
+ }
+ return out;
+};
+
+/**
+ * Calculates the dot product of two vec4's
+ *
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @returns {Number} dot product of a and b
+ */
+vec4.dot = function (a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+};
+
+/**
+ * Performs a linear interpolation between two vec4's
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the first operand
+ * @param {vec4} b the second operand
+ * @param {Number} t interpolation amount between the two inputs
+ * @returns {vec4} out
+ */
+vec4.lerp = function (out, a, b, t) {
+ var ax = a[0],
+ ay = a[1],
+ az = a[2],
+ aw = a[3];
+ out[0] = ax + t * (b[0] - ax);
+ out[1] = ay + t * (b[1] - ay);
+ out[2] = az + t * (b[2] - az);
+ out[3] = aw + t * (b[3] - aw);
+ return out;
+};
+
+/**
+ * Generates a random vector with the given scale
+ *
+ * @param {vec4} out the receiving vector
+ * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
+ * @returns {vec4} out
+ */
+vec4.random = function (out, scale) {
+ scale = scale || 1.0;
+
+ //TODO: This is a pretty awful way of doing this. Find something better.
+ out[0] = glMatrix.RANDOM();
+ out[1] = glMatrix.RANDOM();
+ out[2] = glMatrix.RANDOM();
+ out[3] = glMatrix.RANDOM();
+ vec4.normalize(out, out);
+ vec4.scale(out, out, scale);
+ return out;
+};
+
+/**
+ * Transforms the vec4 with a mat4.
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the vector to transform
+ * @param {mat4} m matrix to transform with
+ * @returns {vec4} out
+ */
+vec4.transformMat4 = function(out, a, m) {
+ var x = a[0], y = a[1], z = a[2], w = a[3];
+ out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
+ out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
+ out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
+ out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
+ return out;
+};
+
+/**
+ * Transforms the vec4 with a quat
+ *
+ * @param {vec4} out the receiving vector
+ * @param {vec4} a the vector to transform
+ * @param {quat} q quaternion to transform with
+ * @returns {vec4} out
+ */
+vec4.transformQuat = function(out, a, q) {
+ var x = a[0], y = a[1], z = a[2],
+ qx = q[0], qy = q[1], qz = q[2], qw = q[3],
+
+ // calculate quat * vec
+ ix = qw * x + qy * z - qz * y,
+ iy = qw * y + qz * x - qx * z,
+ iz = qw * z + qx * y - qy * x,
+ iw = -qx * x - qy * y - qz * z;
+
+ // calculate result * inverse quat
+ out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
+ out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
+ out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
+ out[3] = a[3];
+ return out;
+};
+
+/**
+ * Perform some operation over an array of vec4s.
+ *
+ * @param {Array} a the array of vectors to iterate over
+ * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
+ * @param {Number} offset Number of elements to skip at the beginning of the array
+ * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
+ * @param {Function} fn Function to call for each vector in the array
+ * @param {Object} [arg] additional argument to pass to fn
+ * @returns {Array} a
+ * @function
+ */
+vec4.forEach = (function() {
+ var vec = vec4.create();
+
+ return function(a, stride, offset, count, fn, arg) {
+ var i, l;
+ if(!stride) {
+ stride = 4;
+ }
+
+ if(!offset) {
+ offset = 0;
+ }
+
+ if(count) {
+ l = Math.min((count * stride) + offset, a.length);
+ } else {
+ l = a.length;
+ }
+
+ for(i = offset; i < l; i += stride) {
+ vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3];
+ fn(vec, vec, arg);
+ a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3];
+ }
+
+ return a;
+ };
+})();
+
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {vec4} vec vector to represent as a string
+ * @returns {String} string representation of the vector
+ */
+vec4.str = function (a) {
+ return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
+};
+
+module.exports = vec4;
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build.rake b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build.rake
new file mode 100644
index 00000000000..a1783aabc7c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build.rake
@@ -0,0 +1,2 @@
+desc "compile & minify sources into a single file"
+task :build => ['build:compile', 'build:minify']
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build/compile.rake b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build/compile.rake
new file mode 100644
index 00000000000..905e393d889
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build/compile.rake
@@ -0,0 +1,5 @@
+namespace :build do
+ task :compile do
+ compile
+ end
+end
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build/minify.rake b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build/minify.rake
new file mode 100644
index 00000000000..ea5fec42af5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/build/minify.rake
@@ -0,0 +1,5 @@
+namespace :build do
+ task :minify do
+ minify
+ end
+end
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/default.rake b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/default.rake
new file mode 100644
index 00000000000..c057922037d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/default.rake
@@ -0,0 +1 @@
+task :default => ['test:node', 'test:ci']
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/release.rake b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/release.rake
new file mode 100644
index 00000000000..c70f70cfc13
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/release.rake
@@ -0,0 +1,21 @@
+desc "tag and release gl-matrix v#{GLMatrix::VERSION}"
+task :release do
+ require 'thor'
+ Bundler.ui = Bundler::UI::Shell.new(Thor::Shell::Basic.new)
+ Bundler.ui.debug! if ENV['DEBUG']
+
+ # Sanity check: rebuild files just in case dev forgot to.
+ # If so, files will change and release will abort since changes
+ # were not checked in.
+ Rake::Task['build'].invoke
+
+ release do
+ # Put other release-related stuff here, such as publishing docs;
+ # if anything fails, gl-matrix will be untagged and not pushed.
+ #
+ # Example:
+ #
+ # Rake::Task['doc:publish'].invoke
+ #
+ end
+end
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix.rb b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix.rb
new file mode 100644
index 00000000000..cecdc615a97
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix.rb
@@ -0,0 +1,84 @@
+# Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV
+#
+# This software is provided 'as-is', without any express or implied
+# warranty. In no event will the authors be held liable for any damages
+# arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not
+# claim that you wrote the original software. If you use this software
+# in a product, an acknowledgment in the product documentation would be
+# appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not
+# be misrepresented as being the original software.
+#
+# 3. This notice may not be removed or altered from any source distribution.
+#
+$:.unshift File.expand_path('.', File.dirname(__FILE__))
+require 'sprockets'
+require 'jasmine'
+
+class Jasmine::Config
+ def simple_config_file
+ File.expand_path GLMatrix.base_path.join('spec/jasmine.yml')
+ end
+end
+
+class Rack::Jasmine::Runner
+ alias_method :jasmine_call, :call
+ def call(env)
+ GLMatrix.compile
+ jasmine_call env
+ end
+end
+
+module GLMatrix
+ autoload :ReleaseHelper, 'gl-matrix/release_helper'
+ autoload :Version, 'gl-matrix/version'
+ autoload :VERSION, 'gl-matrix/version'
+
+ module_function
+
+ def release(&block)
+ GLMatrix::ReleaseHelper.release &block
+ end
+
+ def sprockets
+ env = Sprockets::Environment.new base_path
+ env.append_path base_path.join('src')
+ env
+ end
+
+ def base_path
+ Pathname.new File.expand_path('../..', File.dirname(__FILE__))
+ end
+
+ # Compiles the source file to the dest file. If a block
+ # is given, the source file is yielded and replaced with
+ # the result. Returns the destination as a Pathname.
+ def compile(source = 'gl-matrix.js', dest = 'dist/gl-matrix.js')
+ dest = base_path.join dest
+ js = sprockets[source]
+ js = yield js if block_given?
+
+ File.open dest, "w" do |f|
+ f.puts js
+ end
+
+ puts "compiled #{source} to #{dest.relative_path_from base_path}"
+ dest
+ end
+
+ def minify(source = 'gl-matrix.js', dest = 'dist/gl-matrix-min.js')
+ dest = compile source, dest do |js|
+ Uglifier.compile js
+ end
+
+ puts "minified #{source} to #{dest.relative_path_from base_path}"
+ end
+
+end
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix/release_helper.rb b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix/release_helper.rb
new file mode 100644
index 00000000000..4aca02baf88
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix/release_helper.rb
@@ -0,0 +1,104 @@
+# Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV
+#
+# This software is provided 'as-is', without any express or implied
+# warranty. In no event will the authors be held liable for any damages
+# arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not
+# claim that you wrote the original software. If you use this software
+# in a product, an acknowledgment in the product documentation would be
+# appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not
+# be misrepresented as being the original software.
+#
+# 3. This notice may not be removed or altered from any source distribution.
+
+# Pretty much everything here was ripped from Bundler.
+# https://github.com/carlhuda/bundler/blob/master/lib/bundler/gem_helper.rb
+module GLMatrix::ReleaseHelper
+ module_function
+
+ def release
+ guard_clean
+ guard_already_tagged
+ tag_version {
+ yield if block_given?
+ git_push
+ }
+ end
+
+ def base
+ GLMatrix.base_path.to_s
+ end
+
+ def git_push
+ perform_git_push
+ perform_git_push ' --tags'
+ Bundler.ui.confirm "Pushed git commits and tags"
+ end
+
+ def perform_git_push(options = '')
+ cmd = "git push #{options}"
+ out, code = sh_with_code(cmd)
+ raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n" unless code == 0
+ end
+
+ def guard_already_tagged
+ if sh('git tag').split(/\n/).include?(version_tag)
+ raise("This tag has already been committed to the repo.")
+ end
+ end
+
+ def guard_clean
+ clean? or raise("There are files that need to be committed first.")
+ end
+
+ def clean?
+ sh_with_code("git diff --exit-code")[1] == 0
+ end
+
+ def tag_version
+ sh "git tag -a -m \"Version #{version}\" #{version_tag}"
+ Bundler.ui.confirm "Tagged #{version_tag}"
+ yield if block_given?
+ rescue
+ Bundler.ui.error "Untagged #{version_tag} due to error"
+ sh_with_code "git tag -d #{version_tag}"
+ raise
+ end
+
+ def version
+ GLMatrix::VERSION
+ end
+
+ def version_tag
+ "v#{version}"
+ end
+
+ def name
+ "gl-matrix"
+ end
+
+ def sh(cmd, &block)
+ out, code = sh_with_code(cmd, &block)
+ code == 0 ? out : raise(out.empty? ? "Running `#{cmd}' failed. Run this command directly for more detailed output." : out)
+ end
+
+ def sh_with_code(cmd, &block)
+ cmd << " 2>&1"
+ outbuf = ''
+ Bundler.ui.debug(cmd)
+ Dir.chdir(base) {
+ outbuf = `#{cmd}`
+ if $? == 0
+ block.call(outbuf) if block
+ end
+ }
+ [outbuf, $?]
+ end
+end
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix/version.rb b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix/version.rb
new file mode 100644
index 00000000000..73bb9d2889d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/tasks/support/gl-matrix/version.rb
@@ -0,0 +1,28 @@
+# Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV
+#
+# This software is provided 'as-is', without any express or implied
+# warranty. In no event will the authors be held liable for any damages
+# arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not
+# claim that you wrote the original software. If you use this software
+# in a product, an acknowledgment in the product documentation would be
+# appreciated but is not required.
+#
+# 2. Altered source versions must be plainly marked as such, and must not
+# be misrepresented as being the original software.
+#
+# 3. This notice may not be removed or altered from any source distribution.
+
+module GLMatrix
+ module Version
+ MAJOR, MINOR, PATCH, REL = *File.read(base_path.join 'VERSION').split(".")
+ STRING = [MAJOR, MINOR, PATCH, REL].compact.join '.'
+ end
+
+ VERSION = Version::STRING
+end
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/webpack.config.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/webpack.config.js
new file mode 100644
index 00000000000..b9eace3a5ad
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/webpack.config.js
@@ -0,0 +1,47 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var fs = require('fs');
+var webpack = require('webpack');
+
+var entryFile = './src/gl-matrix.js';
+
+// Read the comments from the top of the main gl-matrix file and append them to
+// the minified version.
+var header = '';
+var mainFile = fs.readFileSync(entryFile, { encoding: 'utf8' });
+if (mainFile) {
+ var headerIndex = mainFile.indexOf('\/\/ END HEADER');
+ if (headerIndex >= 0) {
+ header = mainFile.substr(0, headerIndex);
+ }
+}
+
+module.exports = {
+ entry: entryFile,
+ output: {
+ path: __dirname + '/dist',
+ filename: 'gl-matrix.js',
+ libraryTarget: 'umd'
+ },
+ plugins: [
+ new webpack.BannerPlugin(header, { raw: true }),
+ ]
+}; \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/gl-matrix/webpack.config.min.js b/chromium/third_party/catapult/tracing/third_party/gl-matrix/webpack.config.min.js
new file mode 100644
index 00000000000..c7f91092d1b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/gl-matrix/webpack.config.min.js
@@ -0,0 +1,28 @@
+/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. */
+
+var webpack = require('webpack');
+module.exports = require('./webpack.config.js');
+
+module.exports.plugins.unshift(
+ new webpack.optimize.UglifyJsPlugin()
+);
+
+module.exports.output.filename = 'gl-matrix-min.js'; \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/jszip/LICENSE.markdown b/chromium/third_party/catapult/tracing/third_party/jszip/LICENSE.markdown
new file mode 100644
index 00000000000..77b40ad819e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/jszip/LICENSE.markdown
@@ -0,0 +1,651 @@
+JSZip is dual licensed. You may use it under the MIT license *or* the GPLv3
+license.
+
+The MIT License
+===============
+
+Copyright (c) 2009-2012 Stuart Knightley, David Duponchel, Franz Buchinger, António Afonso
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+GPL version 3
+=============
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
diff --git a/chromium/third_party/catapult/tracing/third_party/jszip/README.chromium b/chromium/third_party/catapult/tracing/third_party/jszip/README.chromium
new file mode 100644
index 00000000000..ab23a109aae
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/jszip/README.chromium
@@ -0,0 +1,16 @@
+Name: JSZip
+Short Name: JSZip
+URL: https://github.com/Stuk/jszip
+Date: Wed Aug 28 23:10:31 EST 2013
+Revision: 1b5ef3c66bd676c24dd7337ca02ecc99e119e205
+License: LICENSE.markdown
+License File: MIT
+Security Critical: no
+
+Description:
+Create, read and edit .zip files with Javascript
+
+Local Modifications:
+I deleted the below comment from jszip-inflate.js in order to make things load
+correctly.
+ //@ sourceMappingURL=rawinflate.min.js.map
diff --git a/chromium/third_party/catapult/tracing/third_party/jszip/README.markdown b/chromium/third_party/catapult/tracing/third_party/jszip/README.markdown
new file mode 100644
index 00000000000..537c7adff7e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/jszip/README.markdown
@@ -0,0 +1,32 @@
+JSZip
+=====
+
+A library for creating, reading and editing .zip files with Javascript, with a
+lovely and simple API.
+
+See http://stuartk.com/jszip for all the documentation
+
+```javascript
+var zip = new JSZip();
+
+zip.file("Hello.txt", "Hello World\n");
+
+var img = zip.folder("images");
+img.file("smile.gif", imgData, {base64: true});
+
+var content = zip.generate();
+
+location.href = "data:application/zip;base64," + content;
+/*
+Results in a zip containing
+Hello.txt
+images/
+ smile.gif
+*/
+```
+
+License
+=======
+
+JSZip is dual-licensed. You may use it under the MIT license *or* the GPLv3
+license. See LICENSE.markdown.
diff --git a/chromium/third_party/catapult/tracing/third_party/jszip/jszip.min.js b/chromium/third_party/catapult/tracing/third_party/jszip/jszip.min.js
new file mode 100644
index 00000000000..767d8c11d27
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/jszip/jszip.min.js
@@ -0,0 +1,14 @@
+/*!
+
+JSZip - A Javascript class for generating and reading zip files
+<http://stuartk.com/jszip>
+
+(c) 2009-2014 Stuart Knightley <stuart [at] stuartk.com>
+Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
+
+JSZip uses the library pako released under the MIT license :
+https://github.com/nodeca/pako/blob/master/LICENSE
+*/
+!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";var d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";c.encode=function(a){for(var b,c,e,f,g,h,i,j="",k=0;k<a.length;)b=a.charCodeAt(k++),c=a.charCodeAt(k++),e=a.charCodeAt(k++),f=b>>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k<a.length;)f=d.indexOf(a.charAt(k++)),g=d.indexOf(a.charAt(k++)),h=d.indexOf(a.charAt(k++)),i=d.indexOf(a.charAt(k++)),b=f<<2|g>>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.length<a||0>a)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;g<e.length;g++)h=e[g],this.file(h.fileName,h.decompressed,{binary:!0,optimizedBinaryString:!0,date:h.date,dir:h.dir,comment:h.fileComment.length?h.fileComment:null,createFolders:b.createFolders});return f.zipComment.length&&(this.comment=f.zipComment),this}},{"./base64":1,"./zipEntries":22}],11:[function(a,b){(function(a){"use strict";b.exports=function(b,c){return new a(b,c)},b.exports.test=function(b){return a.isBuffer(b)}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],12:[function(a,b){"use strict";function c(a){this.data=a,this.length=this.data.length,this.index=0}var d=a("./uint8ArrayReader");c.prototype=new d,c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./uint8ArrayReader":18}],13:[function(a,b){"use strict";var c=a("./support"),d=a("./utils"),e=a("./crc32"),f=a("./signature"),g=a("./defaults"),h=a("./base64"),i=a("./compressions"),j=a("./compressedObject"),k=a("./nodeBuffer"),l=a("./utf8"),m=a("./stringWriter"),n=a("./uint8ArrayWriter"),o=function(a){if(a._data instanceof j&&(a._data=a._data.getContent(),a.options.binary=!0,a.options.base64=!1,"uint8array"===d.getTypeOf(a._data))){var b=a._data;a._data=new Uint8Array(b.length),0!==b.length&&a._data.set(b,0)}return a._data},p=function(a){var b=o(a),e=d.getTypeOf(b);return"string"===e?!a.options.binary&&c.nodebuffer?k(b,"utf-8"):a.asBinary():b},q=function(a){var b=o(this);return null===b||"undefined"==typeof b?"":(this.options.base64&&(b=h.decode(b)),b=a&&this.options.binary?A.utf8decode(b):d.transformTo("string",b),a||this.options.binary||(b=d.transformTo("string",A.utf8encode(b))),b)},r=function(a,b,c){this.name=a,this.dir=c.dir,this.date=c.date,this.comment=c.comment,this._data=b,this.options=c,this._initialMetadata={dir:c.dir,date:c.date}};r.prototype={asText:function(){return q.call(this,!0)},asBinary:function(){return q.call(this,!1)},asNodeBuffer:function(){var a=p(this);return d.transformTo("nodebuffer",a)},asUint8Array:function(){var a=p(this);return d.transformTo("uint8array",a)},asArrayBuffer:function(){return this.asUint8Array().buffer}};var s=function(a,b){var c,d="";for(c=0;b>c;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a<arguments.length;a++)for(b in arguments[a])arguments[a].hasOwnProperty(b)&&"undefined"==typeof c[b]&&(c[b]=arguments[a][b]);return c},u=function(a){return a=a||{},a.base64!==!0||null!==a.binary&&void 0!==a.binary||(a.binary=!0),a=t(a,g),a.date=a.date||new Date,null!==a.compression&&(a.compression=a.compression.toUpperCase()),a},v=function(a,b,c){var e,f=d.getTypeOf(b);if(c=u(c),c.createFolders&&(e=w(a))&&x.call(this,e,!0),c.dir||null===b||"undefined"==typeof b)c.base64=!1,c.binary=!1,b=null;else if("string"===f)c.binary&&!c.base64&&c.optimizedBinaryString!==!0&&(b=d.string2binary(b));else{if(c.base64=!1,c.binary=!0,!(f||b instanceof j))throw new Error("The data of '"+a+"' is in an unsupported format !");"arraybuffer"===f&&(b=d.transformTo("uint8array",b))}var g=new r(a,b,c);return this.files[a]=g,g},w=function(a){"/"==a.slice(-1)&&(a=a.substring(0,a.length-1));var b=a.lastIndexOf("/");return b>0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b="undefined"!=typeof b?b:!1,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";w+="\n\x00",w+=p||q?"\x00\b":"\x00\x00",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2);var x=f.LOCAL_FILE_HEADER+w+m+t,y=f.CENTRAL_FILE_HEADER+"\x00"+w+s(o.length,2)+"\x00\x00\x00\x00"+(j===!0?"\x00\x00\x00":"\x00\x00\x00\x00")+s(g,4)+m+t+o;return{fileRecord:x,dirRecord:y,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d<c.length;d++)delete this.files[c[d].name];return this},generate:function(a){a=t(a||{},{base64:!0,compression:"STORE",type:"base64",comment:null}),d.checkSupport(a.type);var b,c,e=[],g=0,j=0,k=d.transformTo("string",this.utf8encode(a.comment||this.comment||""));for(var l in this.files)if(this.files.hasOwnProperty(l)){var o=this.files[l],p=o.options.compression||a.compression.toUpperCase(),q=i[p];if(!q)throw new Error(p+" is not a valid compression method !");var r=y.call(this,o,q),u=z.call(this,l,o,r,g);g+=u.fileRecord.length+r.compressedSize,j+=u.dirRecord.length,e.push(u)}var v="";v=f.CENTRAL_DIRECTORY_END+"\x00\x00\x00\x00"+s(e.length,2)+s(e.length,2)+s(j,4)+s(g,4)+s(k.length,2)+k;var w=a.type.toLowerCase();for(b="uint8array"===w||"arraybuffer"===w||"blob"===w||"nodebuffer"===w?new n(g+j+v.length):new m(g+j+v.length),c=0;c<e.length;c++)b.append(e[c].fileRecord),b.append(e[c].compressedObject.compressedContent);for(c=0;c<e.length;c++)b.append(e[c].dirRecord);b.append(v);var x=b.finalize();switch(a.type.toLowerCase()){case"uint8array":case"arraybuffer":case"nodebuffer":return d.transformTo(a.type.toLowerCase(),x);case"blob":return d.arrayBuffer2Blob(d.transformTo("arraybuffer",x));case"base64":return a.base64?h.encode(x):x;default:return x}},crc32:function(a,b){return e(a,b)},utf8encode:function(a){return d.transformTo("string",l.utf8encode(a))},utf8decode:function(a){return l.utf8decode(a)}};b.exports=A},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(a,b,c){"use strict";c.LOCAL_FILE_HEADER="PK",c.CENTRAL_FILE_HEADER="PK",c.CENTRAL_DIRECTORY_END="PK",c.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",c.ZIP64_CENTRAL_DIRECTORY_END="PK",c.DATA_DESCRIPTOR="PK\b"},{}],15:[function(a,b){"use strict";function c(a,b){this.data=a,b||(this.data=e.string2binary(this.data)),this.length=this.data.length,this.index=0}var d=a("./dataReader"),e=a("./utils");c.prototype=new d,c.prototype.byteAt=function(a){return this.data.charCodeAt(a)},c.prototype.lastIndexOfSignature=function(a){return this.data.lastIndexOf(a)},c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5,"./utils":21}],16:[function(a,b){"use strict";var c=a("./utils"),d=function(){this.data=[]};d.prototype={append:function(a){a=c.transformTo("string",a),this.data.push(a)},finalize:function(){return this.data.join("")}},b.exports=d},{"./utils":21}],17:[function(a,b,c){(function(a){"use strict";if(c.base64=!0,c.array=!0,c.string=!0,c.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,c.nodebuffer="undefined"!=typeof a,c.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)c.blob=!1;else{var b=new ArrayBuffer(0);try{c.blob=0===new Blob([b],{type:"application/zip"}).size}catch(d){try{var e=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,f=new e;f.append(b),c.blob=0===f.getBlob("application/zip").size}catch(d){c.blob=!1}}}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],18:[function(a,b){"use strict";function c(a){a&&(this.data=a,this.length=this.data.length,this.index=0)}var d=a("./dataReader");c.prototype=new d,c.prototype.byteAt=function(a){return this.data[a]},c.prototype.lastIndexOfSignature=function(a){for(var b=a.charCodeAt(0),c=a.charCodeAt(1),d=a.charCodeAt(2),e=a.charCodeAt(3),f=this.length-4;f>=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(e.uint8array?k(a.subarray(c,h)):k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;c<a.length;++c)b[c]=255&a.charCodeAt(c);return b}function f(a){var b=65536,d=[],e=a.length,f=c.getTypeOf(a),g=0,h=!0;try{switch(f){case"uint8array":String.fromCharCode.apply(null,new Uint8Array(0));break;case"nodebuffer":String.fromCharCode.apply(null,j(0))}}catch(i){h=!1}if(!h){for(var k="",l=0;l<a.length;l++)k+=String.fromCharCode(a[l]);return k}for(;e>g&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;c<a.length;c++)b[c]=a[c];return b}var h=a("./support"),i=a("./compressions"),j=a("./nodeBuffer");c.string2binary=function(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(255&a.charCodeAt(c));return b},c.arrayBuffer2Blob=function(a){c.checkSupport("blob");try{return new Blob([a],{type:"application/zip"})}catch(b){try{var d=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,e=new d;return e.append(a),e.getBlob("application/zip")}catch(b){throw new Error("Bug : can't construct the Blob.")}}},c.applyFromCharCode=f;var k={};k.string={string:d,array:function(a){return e(a,new Array(a.length))},arraybuffer:function(a){return k.string.uint8array(a).buffer},uint8array:function(a){return e(a,new Uint8Array(a.length))},nodebuffer:function(a){return e(a,j(a.length))}},k.array={string:f,array:d,arraybuffer:function(a){return new Uint8Array(a).buffer},uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(a)}},k.arraybuffer={string:function(a){return f(new Uint8Array(a))},array:function(a){return g(new Uint8Array(a),new Array(a.byteLength))},arraybuffer:d,uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(new Uint8Array(a))}},k.uint8array={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return a.buffer},uint8array:d,nodebuffer:function(a){return j(a)}},k.nodebuffer={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return k.nodebuffer.uint8array(a).buffer},uint8array:function(a){return g(a,new Uint8Array(a.length))},nodebuffer:d},c.transformTo=function(a,b){if(b||(b=""),!a)return b;c.checkSupport(a);var d=c.getTypeOf(b),e=k[d][a](b);return e},c.getTypeOf=function(a){return"string"==typeof a?"string":"[object Array]"===Object.prototype.toString.call(a)?"array":h.nodebuffer&&j.test(a)?"nodebuffer":h.uint8array&&a instanceof Uint8Array?"uint8array":h.arraybuffer&&a instanceof ArrayBuffer?"arraybuffer":void 0},c.checkSupport=function(a){var b=h[a.toLowerCase()];if(!b)throw new Error(a+" is not supported by this browser")},c.MAX_VALUE_16BITS=65535,c.MAX_VALUE_32BITS=-1,c.pretty=function(a){var b,c,d="";for(c=0;c<(a||"").length;c++)b=a.charCodeAt(c),d+="\\x"+(16>b?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a<this.files.length;a++)b=this.files[a],this.reader.setIndex(b.localHeaderOffset),this.checkSignature(h.LOCAL_FILE_HEADER),b.readLocalPart(this.reader),b.handleUTF8()},readCentralDir:function(){var a;for(this.reader.setIndex(this.centralDirOffset);this.reader.readString(4)===h.CENTRAL_FILE_HEADER;)a=new i({zip64:this.zip64},this.loadOptions),a.readCentralPart(this.reader),this.files.push(a)},readEndOfCentral:function(){var a=this.reader.lastIndexOfSignature(h.CENTRAL_DIRECTORY_END);if(-1===a)throw new Error("Corrupted zip : can't find end of central directory");if(this.reader.setIndex(a),this.checkSignature(h.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===g.MAX_VALUE_16BITS||this.diskWithCentralDirStart===g.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===g.MAX_VALUE_16BITS||this.centralDirRecords===g.MAX_VALUE_16BITS||this.centralDirSize===g.MAX_VALUE_32BITS||this.centralDirOffset===g.MAX_VALUE_32BITS){if(this.zip64=!0,a=this.reader.lastIndexOfSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),-1===a)throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");this.reader.setIndex(a),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}},prepareReader:function(a){var b=g.getTypeOf(a);this.reader="string"!==b||j.uint8array?"nodebuffer"===b?new e(a):new f(g.transformTo("uint8array",a)):new d(a,this.loadOptions.optimizedBinaryString)},load:function(a){this.prepareReader(a),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},b.exports=c},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(a,b){"use strict";function c(a,b){this.options=a,this.loadOptions=b}var d=a("./stringReader"),e=a("./utils"),f=a("./compressedObject"),g=a("./object");c.prototype={isEncrypted:function(){return 1===(1&this.bitFlag)},useUTF8:function(){return 2048===(2048&this.bitFlag)},prepareCompressedContent:function(a,b,c){return function(){var d=a.index;a.setIndex(b);var e=a.readData(c);return a.setIndex(d),e}},prepareContent:function(a,b,c,d,f){return function(){var a=e.transformTo(d.uncompressInputType,this.getCompressedContent()),b=d.uncompress(a);if(b.length!==f)throw new Error("Bug : uncompressed data size mismatch");return b}},readLocalPart:function(a){var b,c;if(a.skip(22),this.fileNameLength=a.readInt(2),c=a.readInt(2),this.fileName=a.readString(this.fileNameLength),a.skip(c),-1==this.compressedSize||-1==this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory (compressedSize == -1 || uncompressedSize == -1)");if(b=e.findCompression(this.compressionMethod),null===b)throw new Error("Corrupted zip : compression "+e.pretty(this.compressionMethod)+" unknown (inner file : "+this.fileName+")");if(this.decompressed=new f,this.decompressed.compressedSize=this.compressedSize,this.decompressed.uncompressedSize=this.uncompressedSize,this.decompressed.crc32=this.crc32,this.decompressed.compressionMethod=this.compressionMethod,this.decompressed.getCompressedContent=this.prepareCompressedContent(a,a.index,this.compressedSize,b),this.decompressed.getContent=this.prepareContent(a,a.index,this.compressedSize,b,this.uncompressedSize),this.loadOptions.checkCRC32&&(this.decompressed=e.transformTo("string",this.decompressed.getContent()),g.crc32(this.decompressed)!==this.crc32))throw new Error("Corrupted zip : CRC32 mismatch")},readCentralPart:function(a){if(this.versionMadeBy=a.readString(2),this.versionNeeded=a.readInt(2),this.bitFlag=a.readInt(2),this.compressionMethod=a.readString(2),this.date=a.readDate(),this.crc32=a.readInt(4),this.compressedSize=a.readInt(4),this.uncompressedSize=a.readInt(4),this.fileNameLength=a.readInt(2),this.extraFieldsLength=a.readInt(2),this.fileCommentLength=a.readInt(2),this.diskNumberStart=a.readInt(2),this.internalFileAttributes=a.readInt(2),this.externalFileAttributes=a.readInt(4),this.localHeaderOffset=a.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");this.fileName=a.readString(this.fileNameLength),this.readExtraFields(a),this.parseZIP64ExtraField(a),this.fileComment=a.readString(this.fileCommentLength),this.dir=16&this.externalFileAttributes?!0:!1},parseZIP64ExtraField:function(){if(this.extraFields[1]){var a=new d(this.extraFields[1].value);this.uncompressedSize===e.MAX_VALUE_32BITS&&(this.uncompressedSize=a.readInt(8)),this.compressedSize===e.MAX_VALUE_32BITS&&(this.compressedSize=a.readInt(8)),this.localHeaderOffset===e.MAX_VALUE_32BITS&&(this.localHeaderOffset=a.readInt(8)),this.diskNumberStart===e.MAX_VALUE_32BITS&&(this.diskNumberStart=a.readInt(4))}},readExtraFields:function(a){var b,c,d,e=a.index;for(this.extraFields=this.extraFields||{};a.index<e+this.extraFieldsLength;)b=a.readInt(2),c=a.readInt(2),d=a.readString(c),this.extraFields[b]={id:b,length:c,value:d}},handleUTF8:function(){if(this.useUTF8())this.fileName=g.utf8decode(this.fileName),this.fileComment=g.utf8decode(this.fileComment);else{var a=this.findExtraFieldUnicodePath();null!==a&&(this.fileName=a);var b=this.findExtraFieldUnicodeComment();null!==b&&(this.fileComment=b)}},findExtraFieldUnicodePath:function(){var a=this.extraFields[28789];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileName)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null},findExtraFieldUnicodeComment:function(){var a=this.extraFields[25461];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileComment)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null}},b.exports=c},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(a,b){"use strict";var c=a("./lib/utils/common").assign,d=a("./lib/deflate"),e=a("./lib/inflate"),f=a("./lib/zlib/constants"),g={};c(g,d,e,f),b.exports=g},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(a,b,c){"use strict";function d(a,b){var c=new s(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}function f(a,b){return b=b||{},b.gzip=!0,d(a,b)}var g=a("./zlib/deflate.js"),h=a("./utils/common"),i=a("./utils/strings"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=0,m=4,n=0,o=1,p=-1,q=0,r=8,s=function(a){this.options=h.assign({level:p,method:r,chunkSize:16384,windowBits:15,memLevel:8,strategy:q,to:""},a||{});var b=this.options;b.raw&&b.windowBits>0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)
+};s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d===m?(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n):!0},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d===i.Z_FINISH?(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK):!0},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a=-1^a;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-jb?a.strstart-(a.w_size-jb):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ib,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ib-(m-f),f=m-ib,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-jb)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=hb)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+1])&a.hash_mask;a.insert&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+hb-1])&a.hash_mask,a.prev[f&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=f,f++,a.insert--,!(a.lookahead+a.insert<hb)););}while(a.lookahead<jb&&0!==a.strm.avail_in)}function n(a,b){var c=65535;for(c>a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sb;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sb;if(a.strstart-a.block_start>=a.w_size-jb&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sb:sb}function o(a,b){for(var c,d;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),0!==c&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c)),a.match_length>=hb)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-hb),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=hb){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart;while(0!==--a.match_length);a.strstart++}else a.strstart+=a.match_length,a.match_length=0,a.ins_h=a.window[a.strstart],a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+1])&a.hash_mask;else d=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++;if(d&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function p(a,b){for(var c,d,e;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),a.prev_length=a.match_length,a.prev_match=a.match_start,a.match_length=hb-1,0!==c&&a.prev_length<a.max_lazy_match&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c),a.match_length<=5&&(a.strategy===S||a.match_length===hb&&a.strstart-a.match_start>4096)&&(a.match_length=hb-1)),a.prev_length>=hb&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-hb,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-hb),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart);while(0!==--a.prev_length);if(a.match_available=0,a.match_length=hb-1,a.strstart++,d&&(h(a,!1),0===a.strm.avail_out))return sb}else if(a.match_available){if(d=D._tr_tally(a,0,a.window[a.strstart-1]),d&&h(a,!1),a.strstart++,a.lookahead--,0===a.strm.avail_out)return sb}else a.match_available=1,a.strstart++,a.lookahead--}return a.match_available&&(d=D._tr_tally(a,0,a.window[a.strstart-1]),a.match_available=0),a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function q(a,b){for(var c,d,e,f,g=a.window;;){if(a.lookahead<=ib){if(m(a),a.lookahead<=ib&&b===H)return sb;if(0===a.lookahead)break}if(a.match_length=0,a.lookahead>=hb&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ib;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ib-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=hb?(c=D._tr_tally(a,1,a.match_length-hb),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sb;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=hb-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fb),this.dyn_dtree=new C.Buf16(2*(2*db+1)),this.bl_tree=new C.Buf16(2*(2*eb+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(gb+1),this.heap=new C.Buf16(2*cb+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*cb+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?lb:qb,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<<i.w_bits,i.w_mask=i.w_size-1,i.hash_bits=f+7,i.hash_size=1<<i.hash_bits,i.hash_mask=i.hash_size-1,i.hash_shift=~~((i.hash_bits+hb-1)/hb),i.window=new C.Buf8(2*i.w_size),i.head=new C.Buf16(i.hash_size),i.prev=new C.Buf16(i.w_size),i.lit_bufsize=1<<f+6,i.pending_buf_size=4*i.lit_bufsize,i.pending_buf=new C.Buf8(i.pending_buf_size),i.d_buf=i.lit_bufsize>>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===rb&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===lb)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=mb):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wb),h.status=qb);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=kb),m+=31-m%31,h.status=qb,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===mb)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=nb)}else h.status=nb;if(h.status===nb)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.name.length?255&h.gzhead.name.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ob)}else h.status=ob;if(h.status===ob)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.comment.length?255&h.gzhead.comment.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pb)}else h.status=pb;if(h.status===pb&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qb)):h.status=qb),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===rb&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==rb){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ub||o===vb)&&(h.status=rb),o===sb||o===ub)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===tb&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==lb&&b!==mb&&b!==nb&&b!==ob&&b!==pb&&b!==qb&&b!==rb?d(a,O):(a.state=null,b===qb?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,ab=29,bb=256,cb=bb+1+ab,db=30,eb=19,fb=2*cb+1,gb=15,hb=3,ib=258,jb=ib+hb+1,kb=32,lb=42,mb=69,nb=73,ob=91,pb=103,qb=113,rb=666,sb=1,tb=2,ub=3,vb=4,wb=3,xb=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xb(0,0,0,0,n),new xb(4,4,8,4,o),new xb(4,5,16,8,o),new xb(4,6,32,32,o),new xb(4,4,16,16,p),new xb(8,16,32,32,p),new xb(8,16,128,128,p),new xb(8,32,128,256,p),new xb(32,128,258,1024,p),new xb(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<<e.lenbits)-1,u=(1<<e.distbits)-1;a:do{15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=r[p&t];b:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<<w)-1)];continue b}if(32&w){e.mode=d;break a}a.msg="invalid literal/length code",e.mode=c;break a}x=65535&v,w&=15,w&&(w>q&&(p+=B[f++]<<q,q+=8),x+=p&(1<<w)-1,p>>>=w,q-=w),15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=s[p&u];c:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<<w)-1)];continue c}a.msg="invalid distance code",e.mode=c;break a}if(y=65535&v,w&=15,w>q&&(p+=B[f++]<<q,q+=8,w>q&&(p+=B[f++]<<q,q+=8)),y+=p&(1<<w)-1,y>k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<<q)-1,a.next_in=f,a.next_out=h,a.avail_in=g>f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(ob),b.distcode=b.distdyn=new r.Buf32(pb),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,rb)}function k(a){if(sb){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sb=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<<f.wbits,f.wnext=0,f.whave=0,f.window=new r.Buf8(f.wsize)),d>=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whave<f.wsize&&(f.whave+=e))),0}function m(a,b){var c,e,f,g,h,i,j,m,n,o,p,q,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,Ab=0,Bb=new r.Buf8(4),Cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!a||!a.state||!a.output||!a.input&&0!==a.avail_in)return F;c=a.state,c.mode===V&&(c.mode=W),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,o=i,p=j,xb=C;a:for(;;)switch(c.mode){case K:if(0===c.wrap){c.mode=W;break}for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(2&c.wrap&&35615===m){c.check=0,Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=lb;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=lb;break}if(m>>>=4,n-=4,wb=(15&m)+8,0===c.wbits)c.wbits=wb;else if(wb>c.wbits){a.msg="invalid window size",c.mode=lb;break}c.dmax=1<<wb,a.adler=c.check=1,c.mode=512&m?T:V,m=0,n=0;break;case L:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.flags=m,(255&c.flags)!==J){a.msg="unknown compression method",c.mode=lb;break}if(57344&c.flags){a.msg="unknown header flags set",c.mode=lb;break}c.head&&(c.head.text=m>>8&1),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.time=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,Bb[2]=m>>>16&255,Bb[3]=m>>>24&255,c.check=t(c.check,Bb,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.xflags=255&m,c.head.os=m>>8),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length=m,c.head&&(c.head.extra_len=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wb=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wb)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.name+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.comment+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(65535&c.check)){a.msg="header crc mismatch",c.mode=lb;break}m=0,n=0}c.head&&(c.head.hcrc=c.flags>>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}a.adler=c.check=d(m),m=0,n=0,c.mode=U;case U:if(0===c.havedict)return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,E;a.adler=c.check=1,c.mode=V;case V:if(b===A||b===B)break a;case W:if(c.last){m>>>=7&n,n-=7&n,c.mode=ib;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}switch(c.last=1&m,m>>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=bb,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=lb}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if((65535&m)!==(m>>>16^65535)){a.msg="invalid stored block lengths",c.mode=lb;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.nlen=(31&m)+257,m>>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=lb;break}c.have=0,c.mode=_;case _:for(;c.have<c.ncode;){for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.lens[Cb[c.have++]]=7&m,m>>>=3,n-=3}for(;c.have<19;)c.lens[Cb[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,yb={bits:c.lenbits},xb=v(w,c.lens,0,19,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid code lengths set",c.mode=lb;break}c.have=0,c.mode=ab;case ab:for(;c.have<c.nlen+c.ndist;){for(;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(16>sb)m>>>=qb,n-=qb,c.lens[c.have++]=sb;else{if(16===sb){for(zb=qb+2;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m>>>=qb,n-=qb,0===c.have){a.msg="invalid bit length repeat",c.mode=lb;break}wb=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sb){for(zb=qb+3;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=3+(7&m),m>>>=3,n-=3}else{for(zb=qb+7;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=lb;break}for(;q--;)c.lens[c.have++]=wb}}if(c.mode===lb)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=lb;break}if(c.lenbits=9,yb={bits:c.lenbits},xb=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid literal/lengths set",c.mode=lb;break}if(c.distbits=6,c.distcode=c.distdyn,yb={bits:c.distbits},xb=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,yb),c.distbits=yb.bits,xb){a.msg="invalid distances set",c.mode=lb;break}if(c.mode=bb,b===B)break a;case bb:c.mode=cb;case cb:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(rb&&0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.lencode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,c.length=sb,0===rb){c.mode=hb;break}if(32&rb){c.back=-1,c.mode=V;break}if(64&rb){a.msg="invalid literal/length code",c.mode=lb;break}c.extra=15&rb,c.mode=db;case db:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=eb;case eb:for(;Ab=c.distcode[m&(1<<c.distbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.distcode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,64&rb){a.msg="invalid distance code",c.mode=lb;break}c.offset=sb,c.extra=15&rb,c.mode=fb;case fb:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.offset+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=lb;break}c.mode=gb;case gb:if(0===j)break a;
+if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=lb;break}q>c.wnext?(q-=c.wnext,ob=c.wsize-q):ob=c.wnext-q,q>c.length&&(q=c.length),pb=c.window}else pb=f,ob=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pb[ob++];while(--q);0===c.length&&(c.mode=cb);break;case hb:if(0===j)break a;f[h++]=c.length,j--,c.mode=cb;break;case ib:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<<n,n+=8}if(p-=j,a.total_out+=p,c.total+=p,p&&(a.adler=c.check=c.flags?t(c.check,f,p,h-p):s(c.check,f,p,h-p)),p=j,(c.flags?m:d(m))!==c.check){a.msg="incorrect data check",c.mode=lb;break}m=0,n=0}c.mode=jb;case jb:if(c.wrap&&c.flags){for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(4294967295&c.total)){a.msg="incorrect length check",c.mode=lb;break}m=0,n=0}c.mode=kb;case kb:xb=D;break a;case lb:xb=G;break a;case mb:return H;case nb:default:return F}return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,(c.wsize||p!==a.avail_out&&c.mode<lb&&(c.mode<ib||b!==z))&&l(a,a.output,a.next_out,p-a.avail_out)?(c.mode=mb,H):(o-=a.avail_in,p-=a.avail_out,a.total_in+=o,a.total_out+=p,c.total+=p,c.wrap&&p&&(a.adler=c.check=c.flags?t(c.check,f,p,a.next_out-p):s(c.check,f,p,a.next_out-p)),a.data_type=c.bits+(c.last?64:0)+(c.mode===V?128:0)+(c.mode===bb||c.mode===Y?256:0),(0===o&&0===p||b===z)&&xb===C&&(xb=I),xb)}function n(a){if(!a||!a.state)return F;var b=a.state;return b.window&&(b.window=null),a.state=null,C}function o(a,b){var c;return a&&a.state?(c=a.state,0===(2&c.wrap)?F:(c.head=b,b.done=!1,C)):F}var p,q,r=a("../utils/common"),s=a("./adler32"),t=a("./crc32"),u=a("./inffast"),v=a("./inftrees"),w=0,x=1,y=2,z=4,A=5,B=6,C=0,D=1,E=2,F=-2,G=-3,H=-4,I=-5,J=8,K=1,L=2,M=3,N=4,O=5,P=6,Q=7,R=8,S=9,T=10,U=11,V=12,W=13,X=14,Y=15,Z=16,$=17,_=18,ab=19,bb=20,cb=21,db=22,eb=23,fb=24,gb=25,hb=26,ib=27,jb=28,kb=29,lb=30,mb=31,nb=32,ob=852,pb=592,qb=15,rb=qb,sb=!0;c.inflateReset=g,c.inflateReset2=h,c.inflateResetKeep=f,c.inflateInit=j,c.inflateInit2=i,c.inflate=m,c.inflateEnd=n,c.inflateGetHeader=o,c.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(a,b){"use strict";var c=a("../utils/common"),d=15,e=852,f=592,g=0,h=1,i=2,j=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],k=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],l=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],m=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];b.exports=function(a,b,n,o,p,q,r,s){var t,u,v,w,x,y,z,A,B,C=s.bits,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=null,O=0,P=new c.Buf16(d+1),Q=new c.Buf16(d+1),R=null,S=0;for(D=0;d>=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<<H,w=L-1,a===h&&L>e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]<y?(A=0,B=r[E]):r[E]>y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<<D-J,u=1<<I,F=u;do u-=t,p[x+(M>>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<<D-1;M&t;)t>>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<<I;G>I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<<I,a===h&&L>e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?gb[a]:gb[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<<a.bi_valid&65535,f(a,a.bi_buf),a.bi_buf=b>>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<<a.bi_valid&65535,a.bi_valid+=c)}function h(a,b,c){g(a,c[2*b],c[2*b+1])}function i(a,b){var c=0;do c|=1&a,a>>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ib[d]=c,a=0;a<1<<_[d];a++)hb[c++]=d;for(hb[c-1]=d,e=0,d=0;16>d;d++)for(jb[d]=e,a=0;a<1<<ab[d];a++)gb[e++]=d;for(e>>=7;R>d;d++)for(jb[d]=e<<7,a=0;a<1<<ab[d]-7;a++)gb[256+e++]=d;for(b=0;U>=b;b++)f[b]=0;for(a=0;143>=a;)eb[2*a+1]=8,a++,f[8]++;for(;255>=a;)eb[2*a+1]=9,a++,f[9]++;for(;279>=a;)eb[2*a+1]=7,a++,f[7]++;for(;287>=a;)eb[2*a+1]=8,a++,f[8]++;for(l(eb,Q+1,f),a=0;R>a;a++)fb[2*a+1]=5,fb[2*a]=i(a,5);kb=new nb(eb,_,P+1,Q,U),lb=new nb(fb,ab,0,R,U),mb=new nb(new Array(0),bb,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]<a[f]||a[e]===a[f]&&d[b]<=d[c]}function r(a,b,c){for(var d=a.heap[c],e=c<<1;e<=a.heap_len&&(e<a.heap_len&&q(b,a.heap[e+1],a.heap[e],a.depth)&&e++,!q(b,d,a.heap[e],a.depth));)a.heap[c]=a.heap[e],c=e,e<<=1;a.heap[c]=d}function s(a,b,c){var d,f,i,j,k=0;if(0!==a.last_lit)do d=a.pending_buf[a.d_buf+2*k]<<8|a.pending_buf[a.d_buf+2*k+1],f=a.pending_buf[a.l_buf+k],k++,0===d?h(a,f,b):(i=hb[f],h(a,i+P+1,b),j=_[i],0!==j&&(f-=ib[i],g(a,f,j)),d--,i=e(d),h(a,i,c),j=ab[i],0!==j&&(d-=jb[i],g(a,d,j)));while(k<a.last_lit);h(a,X,b)}function t(a,b){var c,d,e,f=b.dyn_tree,g=b.stat_desc.static_tree,h=b.stat_desc.has_stree,i=b.stat_desc.elems,j=-1;for(a.heap_len=0,a.heap_max=T,c=0;i>c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++h<i&&e===g||(j>h?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++j<k&&e===i)){if(l>j){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*cb[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*cb[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pb||(m(),pb=!0),a.l_desc=new ob(a.dyn_ltree,kb),a.d_desc=new ob(a.dyn_dtree,lb),a.bl_desc=new ob(a.bl_tree,mb),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,eb),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,eb,fb)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(hb[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],bb=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],db=512,eb=new Array(2*(Q+2));d(eb);var fb=new Array(2*R);d(fb);var gb=new Array(db);d(gb);var hb=new Array(N-M+1);d(hb);var ib=new Array(O);d(ib);var jb=new Array(R);d(jb);var kb,lb,mb,nb=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},ob=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pb=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)}); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/mannwhitneyu/README.chromium b/chromium/third_party/catapult/tracing/third_party/mannwhitneyu/README.chromium
new file mode 100644
index 00000000000..78439f32f52
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/mannwhitneyu/README.chromium
@@ -0,0 +1,15 @@
+Name: Mann-Whitney U Test
+Short Name: mannwhitneyu
+URL: https://gist.github.com/gungorbudak/1c3989cc26b9567c6e50
+Version: 0
+Revision: f8f2918a366798793f5fb7e92de0df9142feb737
+Date: Jan 16 2016
+License: MIT
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+Mann Whitney U Test implemented in javascript
+
+Local Modifications:
+None.
diff --git a/chromium/third_party/catapult/tracing/third_party/mannwhitneyu/mannwhitneyu.js b/chromium/third_party/catapult/tracing/third_party/mannwhitneyu/mannwhitneyu.js
new file mode 100644
index 00000000000..2e2bda544b9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/mannwhitneyu/mannwhitneyu.js
@@ -0,0 +1,197 @@
+'use strict';
+
+(function(exports) {
+
+ var rank = {
+ /*
+ * Standart ranking
+ *
+ * The MIT License, Copyright (c) 2014 Ben Magyar
+ */
+ standard: function(array, key) {
+ // sort the array
+ array = array.sort(function(a, b) {
+ var x = a[key];
+ var y = b[key];
+ return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ });
+ // assign a naive ranking
+ for (var i = 1; i < array.length + 1; i++) {
+ array[i - 1]['rank'] = i;
+ }
+ return array;
+ },
+ /*
+ * Fractional ranking
+ *
+ * The MIT License, Copyright (c) 2014 Ben Magyar
+ */
+ fractional: function(array, key) {
+ array = this.standard(array, key);
+ // now apply fractional
+ var pos = 0;
+ while (pos < array.length) {
+ var sum = 0;
+ var i = 0;
+ for (i = 0; array[pos + i + 1] && (array[pos + i][key] === array[pos + i + 1][key]); i++) {
+ sum += array[pos + i]['rank'];
+ }
+ sum += array[pos + i]['rank'];
+ var endPos = pos + i + 1;
+ for (pos; pos < endPos; pos++) {
+ array[pos]['rank'] = sum / (i + 1);
+ }
+ pos = endPos;
+ }
+ return array;
+ },
+ rank: function(x, y) {
+ var nx = x.length,
+ ny = y.length,
+ combined = [],
+ ranked;
+ while (nx--) {
+ combined.push({
+ set: 'x',
+ val: x[nx]
+ });
+ }
+ while (ny--) {
+ combined.push({
+ set: 'y',
+ val: y[ny]
+ });
+ }
+ ranked = this.fractional(combined, 'val');
+ return ranked
+ }
+ };
+
+ /*
+ * Error function
+ *
+ * The MIT License, Copyright (c) 2013 jStat
+ */
+ var erf = function erf(x) {
+ var cof = [-1.3026537197817094, 6.4196979235649026e-1, 1.9476473204185836e-2, -9.561514786808631e-3, -9.46595344482036e-4, 3.66839497852761e-4,
+ 4.2523324806907e-5, -2.0278578112534e-5, -1.624290004647e-6,
+ 1.303655835580e-6, 1.5626441722e-8, -8.5238095915e-8,
+ 6.529054439e-9, 5.059343495e-9, -9.91364156e-10, -2.27365122e-10, 9.6467911e-11, 2.394038e-12, -6.886027e-12, 8.94487e-13, 3.13092e-13, -1.12708e-13, 3.81e-16, 7.106e-15, -1.523e-15, -9.4e-17, 1.21e-16, -2.8e-17
+ ];
+ var j = cof.length - 1;
+ var isneg = false;
+ var d = 0;
+ var dd = 0;
+ var t, ty, tmp, res;
+
+ if (x < 0) {
+ x = -x;
+ isneg = true;
+ }
+
+ t = 2 / (2 + x);
+ ty = 4 * t - 2;
+
+ for (; j > 0; j--) {
+ tmp = d;
+ d = ty * d - dd + cof[j];
+ dd = tmp;
+ }
+
+ res = t * Math.exp(-x * x + 0.5 * (cof[0] + ty * d) - dd);
+ return isneg ? res - 1 : 1 - res;
+ };
+
+ /*
+ * Normal distribution CDF
+ *
+ * The MIT License, Copyright (c) 2013 jStat
+ */
+ var dnorm = function(x, mean, std) {
+ return 0.5 * (1 + erf((x - mean) / Math.sqrt(2 * std * std)));
+ }
+
+ var statistic = function(x, y) {
+ var ranked = rank.rank(x, y),
+ nr = ranked.length,
+ nx = x.length,
+ ny = y.length,
+ ranksums = {
+ x: 0,
+ y: 0
+ },
+ i = 0, t = 0, nt = 1, tcf, ux, uy;
+
+ while (i < nr) {
+ if (i > 0) {
+ if (ranked[i].val == ranked[i-1].val) {
+ nt++;
+ } else {
+ if (nt > 1) {
+ t += Math.pow(nt, 3) - nt
+ nt = 1;
+ }
+ }
+ }
+ ranksums[ranked[i].set] += ranked[i].rank
+ i++;
+ }
+ tcf = 1 - (t / (Math.pow(nr, 3) - nr))
+ ux = nx*ny + (nx*(nx+1)/2) - ranksums.x;
+ uy = nx*ny - ux;
+
+ return {
+ tcf: tcf,
+ ux: ux,
+ uy: uy,
+ big: Math.max(ux, uy),
+ small: Math.min(ux, uy)
+ }
+ }
+
+ exports.test = function(x, y, alt, corr) {
+ // set default value for alternative
+ alt = typeof alt !== 'undefined' ? alt : 'two-sided';
+ // set default value for continuity
+ corr = typeof corr !== 'undefined' ? corr : true;
+ var nx = x.length, // x's size
+ ny = y.length, // y's size
+ f = 1,
+ u, mu, std, z, p;
+
+ // test statistic
+ u = statistic(x, y);
+
+ // mean compute and correct if given
+ if (corr) {
+ mu = (nx * ny / 2) + 0.5;
+ } else {
+ mu = nx * ny / 2;
+ }
+
+ // compute standard deviation using tie correction factor
+ std = Math.sqrt(u.tcf * nx * ny * (nx + ny + 1) / 12);
+
+ // compute z according to given alternative
+ if (alt == 'less') {
+ z = (u.ux - mu) / std;
+ } else if (alt == 'greater') {
+ z = (u.uy - mu) / std;
+ } else if (alt == 'two-sided') {
+ z = Math.abs((u.big - mu) / std);
+ } else {
+ console.log('Unknown alternative argument');
+ }
+
+ // factor to correct two sided p-value
+ if (alt == 'two-sided') {
+ f = 2;
+ }
+
+ // compute p-value using CDF of standard normal
+ p = dnorm(-z, 0, 1) * f;
+
+ return {U: u.small, p: p};
+ }
+
+})(typeof exports === 'undefined' ? this['mannwhitneyu'] = {} : exports); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/mocha/LICENSE b/chromium/third_party/catapult/tracing/third_party/mocha/LICENSE
new file mode 100644
index 00000000000..ca47f261b3f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/mocha/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2011-2015 TJ Holowaychuk <tj@vision-media.ca>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/chromium/third_party/catapult/tracing/third_party/mocha/README.chromium b/chromium/third_party/catapult/tracing/third_party/mocha/README.chromium
new file mode 100644
index 00000000000..e492702c6ba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/mocha/README.chromium
@@ -0,0 +1,9 @@
+Name: Mocha, simple, flexible, fun javascript test framework for node.js & the browser
+Short Name: Mocha
+URL: https://github.com/mochajs/mocha
+Version: 2c2ed43ae7f047f333468e2043001bfb8c9d13d5
+License: MIT
+License File: NOT_SHIPPED
+Security Critical: no
+Description: Used for testing
+Local Modifications: None
diff --git a/chromium/third_party/catapult/tracing/third_party/mocha/mocha.css b/chromium/third_party/catapult/tracing/third_party/mocha/mocha.css
new file mode 100644
index 00000000000..42b9798fa4e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/mocha/mocha.css
@@ -0,0 +1,270 @@
+@charset "utf-8";
+
+body {
+ margin:0;
+}
+
+#mocha {
+ font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ margin: 60px 50px;
+}
+
+#mocha ul,
+#mocha li {
+ margin: 0;
+ padding: 0;
+}
+
+#mocha ul {
+ list-style: none;
+}
+
+#mocha h1,
+#mocha h2 {
+ margin: 0;
+}
+
+#mocha h1 {
+ margin-top: 15px;
+ font-size: 1em;
+ font-weight: 200;
+}
+
+#mocha h1 a {
+ text-decoration: none;
+ color: inherit;
+}
+
+#mocha h1 a:hover {
+ text-decoration: underline;
+}
+
+#mocha .suite .suite h1 {
+ margin-top: 0;
+ font-size: .8em;
+}
+
+#mocha .hidden {
+ display: none;
+}
+
+#mocha h2 {
+ font-size: 12px;
+ font-weight: normal;
+ cursor: pointer;
+}
+
+#mocha .suite {
+ margin-left: 15px;
+}
+
+#mocha .test {
+ margin-left: 15px;
+ overflow: hidden;
+}
+
+#mocha .test.pending:hover h2::after {
+ content: '(pending)';
+ font-family: arial, sans-serif;
+}
+
+#mocha .test.pass.medium .duration {
+ background: #c09853;
+}
+
+#mocha .test.pass.slow .duration {
+ background: #b94a48;
+}
+
+#mocha .test.pass::before {
+ content: '✓';
+ font-size: 12px;
+ display: block;
+ float: left;
+ margin-right: 5px;
+ color: #00d6b2;
+}
+
+#mocha .test.pass .duration {
+ font-size: 9px;
+ margin-left: 5px;
+ padding: 2px 5px;
+ color: #fff;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+ -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -o-border-radius: 5px;
+ border-radius: 5px;
+}
+
+#mocha .test.pass.fast .duration {
+ display: none;
+}
+
+#mocha .test.pending {
+ color: #0b97c4;
+}
+
+#mocha .test.pending::before {
+ content: '◦';
+ color: #0b97c4;
+}
+
+#mocha .test.fail {
+ color: #c00;
+}
+
+#mocha .test.fail pre {
+ color: black;
+}
+
+#mocha .test.fail::before {
+ content: '✖';
+ font-size: 12px;
+ display: block;
+ float: left;
+ margin-right: 5px;
+ color: #c00;
+}
+
+#mocha .test pre.error {
+ color: #c00;
+ max-height: 300px;
+ overflow: auto;
+}
+
+/**
+ * (1): approximate for browsers not supporting calc
+ * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
+ * ^^ seriously
+ */
+#mocha .test pre {
+ display: block;
+ float: left;
+ clear: left;
+ font: 12px/1.5 monaco, monospace;
+ margin: 5px;
+ padding: 15px;
+ border: 1px solid #eee;
+ max-width: 85%; /*(1)*/
+ max-width: calc(100% - 42px); /*(2)*/
+ word-wrap: break-word;
+ border-bottom-color: #ddd;
+ -webkit-border-radius: 3px;
+ -webkit-box-shadow: 0 1px 3px #eee;
+ -moz-border-radius: 3px;
+ -moz-box-shadow: 0 1px 3px #eee;
+ border-radius: 3px;
+}
+
+#mocha .test h2 {
+ position: relative;
+}
+
+#mocha .test a.replay {
+ position: absolute;
+ top: 3px;
+ right: 0;
+ text-decoration: none;
+ vertical-align: middle;
+ display: block;
+ width: 15px;
+ height: 15px;
+ line-height: 15px;
+ text-align: center;
+ background: #eee;
+ font-size: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+ -webkit-transition: opacity 200ms;
+ -moz-transition: opacity 200ms;
+ transition: opacity 200ms;
+ opacity: 0.3;
+ color: #888;
+}
+
+#mocha .test:hover a.replay {
+ opacity: 1;
+}
+
+#mocha-report.pass .test.fail {
+ display: none;
+}
+
+#mocha-report.fail .test.pass {
+ display: none;
+}
+
+#mocha-report.pending .test.pass,
+#mocha-report.pending .test.fail {
+ display: none;
+}
+#mocha-report.pending .test.pass.pending {
+ display: block;
+}
+
+#mocha-error {
+ color: #c00;
+ font-size: 1.5em;
+ font-weight: 100;
+ letter-spacing: 1px;
+}
+
+#mocha-stats {
+ position: fixed;
+ top: 15px;
+ right: 10px;
+ font-size: 12px;
+ margin: 0;
+ color: #888;
+ z-index: 1;
+}
+
+#mocha-stats .progress {
+ float: right;
+ padding-top: 0;
+}
+
+#mocha-stats em {
+ color: black;
+}
+
+#mocha-stats a {
+ text-decoration: none;
+ color: inherit;
+}
+
+#mocha-stats a:hover {
+ border-bottom: 1px solid #eee;
+}
+
+#mocha-stats li {
+ display: inline-block;
+ margin: 0 5px;
+ list-style: none;
+ padding-top: 11px;
+}
+
+#mocha-stats canvas {
+ width: 40px;
+ height: 40px;
+}
+
+#mocha code .comment { color: #ddd; }
+#mocha code .init { color: #2f6fad; }
+#mocha code .string { color: #5890ad; }
+#mocha code .keyword { color: #8a6343; }
+#mocha code .number { color: #2f6fad; }
+
+@media screen and (max-device-width: 480px) {
+ #mocha {
+ margin: 60px 0px;
+ }
+
+ #mocha #stats {
+ position: absolute;
+ }
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/mocha/mocha.js b/chromium/third_party/catapult/tracing/third_party/mocha/mocha.js
new file mode 100755
index 00000000000..cffddcbc130
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/mocha/mocha.js
@@ -0,0 +1,6557 @@
+;(function(){
+
+// CommonJS require()
+
+function require(p){
+ var path = require.resolve(p)
+ , mod = require.modules[path];
+ if (!mod) throw new Error('failed to require "' + p + '"');
+ if (!mod.exports) {
+ mod.exports = {};
+ mod.call(mod.exports, mod, mod.exports, require.relative(path));
+ }
+ return mod.exports;
+ }
+
+require.modules = {};
+
+require.resolve = function (path){
+ var orig = path
+ , reg = path + '.js'
+ , index = path + '/index.js';
+ return require.modules[reg] && reg
+ || require.modules[index] && index
+ || orig;
+ };
+
+require.register = function (path, fn){
+ require.modules[path] = fn;
+ };
+
+require.relative = function (parent) {
+ return function(p){
+ if ('.' != p.charAt(0)) return require(p);
+
+ var path = parent.split('/')
+ , segs = p.split('/');
+ path.pop();
+
+ for (var i = 0; i < segs.length; i++) {
+ var seg = segs[i];
+ if ('..' == seg) path.pop();
+ else if ('.' != seg) path.push(seg);
+ }
+
+ return require(path.join('/'));
+ };
+ };
+
+
+require.register("browser/debug.js", function(module, exports, require){
+module.exports = function(type){
+ return function(){
+ }
+};
+
+}); // module: browser/debug.js
+
+require.register("browser/diff.js", function(module, exports, require){
+/* See LICENSE file for terms of use */
+
+/*
+ * Text diff implementation.
+ *
+ * This library supports the following APIS:
+ * JsDiff.diffChars: Character by character diff
+ * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
+ * JsDiff.diffLines: Line based diff
+ *
+ * JsDiff.diffCss: Diff targeted at CSS content
+ *
+ * These methods are based on the implementation proposed in
+ * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
+ * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
+ */
+var JsDiff = (function() {
+ /*jshint maxparams: 5*/
+ function clonePath(path) {
+ return { newPos: path.newPos, components: path.components.slice(0) };
+ }
+ function removeEmpty(array) {
+ var ret = [];
+ for (var i = 0; i < array.length; i++) {
+ if (array[i]) {
+ ret.push(array[i]);
+ }
+ }
+ return ret;
+ }
+ function escapeHTML(s) {
+ var n = s;
+ n = n.replace(/&/g, '&amp;');
+ n = n.replace(/</g, '&lt;');
+ n = n.replace(/>/g, '&gt;');
+ n = n.replace(/"/g, '&quot;');
+
+ return n;
+ }
+
+ var Diff = function(ignoreWhitespace) {
+ this.ignoreWhitespace = ignoreWhitespace;
+ };
+ Diff.prototype = {
+ diff: function(oldString, newString) {
+ // Handle the identity case (this is due to unrolling editLength == 0
+ if (newString === oldString) {
+ return [{ value: newString }];
+ }
+ if (!newString) {
+ return [{ value: oldString, removed: true }];
+ }
+ if (!oldString) {
+ return [{ value: newString, added: true }];
+ }
+
+ newString = this.tokenize(newString);
+ oldString = this.tokenize(oldString);
+
+ var newLen = newString.length, oldLen = oldString.length;
+ var maxEditLength = newLen + oldLen;
+ var bestPath = [{ newPos: -1, components: [] }];
+
+ // Seed editLength = 0
+ var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
+ if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {
+ return bestPath[0].components;
+ }
+
+ for (var editLength = 1; editLength <= maxEditLength; editLength++) {
+ for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {
+ var basePath;
+ var addPath = bestPath[diagonalPath-1],
+ removePath = bestPath[diagonalPath+1];
+ oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
+ if (addPath) {
+ // No one else is going to attempt to use this value, clear it
+ bestPath[diagonalPath-1] = undefined;
+ }
+
+ var canAdd = addPath && addPath.newPos+1 < newLen;
+ var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
+ if (!canAdd && !canRemove) {
+ bestPath[diagonalPath] = undefined;
+ continue;
+ }
+
+ // Select the diagonal that we want to branch from. We select the prior
+ // path whose position in the new string is the farthest from the origin
+ // and does not pass the bounds of the diff graph
+ if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
+ basePath = clonePath(removePath);
+ this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
+ } else {
+ basePath = clonePath(addPath);
+ basePath.newPos++;
+ this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
+ }
+
+ var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
+
+ if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {
+ return basePath.components;
+ } else {
+ bestPath[diagonalPath] = basePath;
+ }
+ }
+ }
+ },
+
+ pushComponent: function(components, value, added, removed) {
+ var last = components[components.length-1];
+ if (last && last.added === added && last.removed === removed) {
+ // We need to clone here as the component clone operation is just
+ // as shallow array clone
+ components[components.length-1] =
+ {value: this.join(last.value, value), added: added, removed: removed };
+ } else {
+ components.push({value: value, added: added, removed: removed });
+ }
+ },
+ extractCommon: function(basePath, newString, oldString, diagonalPath) {
+ var newLen = newString.length,
+ oldLen = oldString.length,
+ newPos = basePath.newPos,
+ oldPos = newPos - diagonalPath;
+ while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
+ newPos++;
+ oldPos++;
+
+ this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
+ }
+ basePath.newPos = newPos;
+ return oldPos;
+ },
+
+ equals: function(left, right) {
+ var reWhitespace = /\S/;
+ if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
+ return true;
+ } else {
+ return left === right;
+ }
+ },
+ join: function(left, right) {
+ return left + right;
+ },
+ tokenize: function(value) {
+ return value;
+ }
+ };
+
+ var CharDiff = new Diff();
+
+ var WordDiff = new Diff(true);
+ var WordWithSpaceDiff = new Diff();
+ WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
+ return removeEmpty(value.split(/(\s+|\b)/));
+ };
+
+ var CssDiff = new Diff(true);
+ CssDiff.tokenize = function(value) {
+ return removeEmpty(value.split(/([{}:;,]|\s+)/));
+ };
+
+ var LineDiff = new Diff();
+ LineDiff.tokenize = function(value) {
+ var retLines = [],
+ lines = value.split(/^/m);
+
+ for(var i = 0; i < lines.length; i++) {
+ var line = lines[i],
+ lastLine = lines[i - 1];
+
+ // Merge lines that may contain windows new lines
+ if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') {
+ retLines[retLines.length - 1] += '\n';
+ } else if (line) {
+ retLines.push(line);
+ }
+ }
+
+ return retLines;
+ };
+
+ return {
+ Diff: Diff,
+
+ diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
+ diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
+ diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },
+ diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },
+
+ diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },
+
+ createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
+ var ret = [];
+
+ ret.push('Index: ' + fileName);
+ ret.push('===================================================================');
+ ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
+ ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
+
+ var diff = LineDiff.diff(oldStr, newStr);
+ if (!diff[diff.length-1].value) {
+ diff.pop(); // Remove trailing newline add
+ }
+ diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier
+
+ function contextLines(lines) {
+ return lines.map(function(entry) { return ' ' + entry; });
+ }
+ function eofNL(curRange, i, current) {
+ var last = diff[diff.length-2],
+ isLast = i === diff.length-2,
+ isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
+
+ // Figure out if this is the last line for the given file and missing NL
+ if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
+ curRange.push('\\ No newline at end of file');
+ }
+ }
+
+ var oldRangeStart = 0, newRangeStart = 0, curRange = [],
+ oldLine = 1, newLine = 1;
+ for (var i = 0; i < diff.length; i++) {
+ var current = diff[i],
+ lines = current.lines || current.value.replace(/\n$/, '').split('\n');
+ current.lines = lines;
+
+ if (current.added || current.removed) {
+ if (!oldRangeStart) {
+ var prev = diff[i-1];
+ oldRangeStart = oldLine;
+ newRangeStart = newLine;
+
+ if (prev) {
+ curRange = contextLines(prev.lines.slice(-4));
+ oldRangeStart -= curRange.length;
+ newRangeStart -= curRange.length;
+ }
+ }
+ curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));
+ eofNL(curRange, i, current);
+
+ if (current.added) {
+ newLine += lines.length;
+ } else {
+ oldLine += lines.length;
+ }
+ } else {
+ if (oldRangeStart) {
+ // Close out any changes that have been output (or join overlapping)
+ if (lines.length <= 8 && i < diff.length-2) {
+ // Overlapping
+ curRange.push.apply(curRange, contextLines(lines));
+ } else {
+ // end the range and output
+ var contextSize = Math.min(lines.length, 4);
+ ret.push(
+ '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
+ + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
+ + ' @@');
+ ret.push.apply(ret, curRange);
+ ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
+ if (lines.length <= 4) {
+ eofNL(ret, i, current);
+ }
+
+ oldRangeStart = 0; newRangeStart = 0; curRange = [];
+ }
+ }
+ oldLine += lines.length;
+ newLine += lines.length;
+ }
+ }
+
+ return ret.join('\n') + '\n';
+ },
+
+ applyPatch: function(oldStr, uniDiff) {
+ var diffstr = uniDiff.split('\n');
+ var diff = [];
+ var remEOFNL = false,
+ addEOFNL = false;
+
+ for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
+ if(diffstr[i][0] === '@') {
+ var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
+ diff.unshift({
+ start:meh[3],
+ oldlength:meh[2],
+ oldlines:[],
+ newlength:meh[4],
+ newlines:[]
+ });
+ } else if(diffstr[i][0] === '+') {
+ diff[0].newlines.push(diffstr[i].substr(1));
+ } else if(diffstr[i][0] === '-') {
+ diff[0].oldlines.push(diffstr[i].substr(1));
+ } else if(diffstr[i][0] === ' ') {
+ diff[0].newlines.push(diffstr[i].substr(1));
+ diff[0].oldlines.push(diffstr[i].substr(1));
+ } else if(diffstr[i][0] === '\\') {
+ if (diffstr[i-1][0] === '+') {
+ remEOFNL = true;
+ } else if(diffstr[i-1][0] === '-') {
+ addEOFNL = true;
+ }
+ }
+ }
+
+ var str = oldStr.split('\n');
+ for (var i = diff.length - 1; i >= 0; i--) {
+ var d = diff[i];
+ for (var j = 0; j < d.oldlength; j++) {
+ if(str[d.start-1+j] !== d.oldlines[j]) {
+ return false;
+ }
+ }
+ Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
+ }
+
+ if (remEOFNL) {
+ while (!str[str.length-1]) {
+ str.pop();
+ }
+ } else if (addEOFNL) {
+ str.push('');
+ }
+ return str.join('\n');
+ },
+
+ convertChangesToXML: function(changes){
+ var ret = [];
+ for ( var i = 0; i < changes.length; i++) {
+ var change = changes[i];
+ if (change.added) {
+ ret.push('<ins>');
+ } else if (change.removed) {
+ ret.push('<del>');
+ }
+
+ ret.push(escapeHTML(change.value));
+
+ if (change.added) {
+ ret.push('</ins>');
+ } else if (change.removed) {
+ ret.push('</del>');
+ }
+ }
+ return ret.join('');
+ },
+
+ // See: http://code.google.com/p/google-diff-match-patch/wiki/API
+ convertChangesToDMP: function(changes){
+ var ret = [], change;
+ for ( var i = 0; i < changes.length; i++) {
+ change = changes[i];
+ ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
+ }
+ return ret;
+ }
+ };
+})();
+
+if (typeof module !== 'undefined') {
+ module.exports = JsDiff;
+}
+
+}); // module: browser/diff.js
+
+require.register("browser/escape-string-regexp.js", function(module, exports, require){
+'use strict';
+
+var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
+
+module.exports = function (str) {
+ if (typeof str !== 'string') {
+ throw new TypeError('Expected a string');
+ }
+
+ return str.replace(matchOperatorsRe, '\\$&');
+};
+
+}); // module: browser/escape-string-regexp.js
+
+require.register("browser/events.js", function(module, exports, require){
+/**
+ * Module exports.
+ */
+
+exports.EventEmitter = EventEmitter;
+
+/**
+ * Check if `obj` is an array.
+ */
+
+function isArray(obj) {
+ return '[object Array]' == {}.toString.call(obj);
+}
+
+/**
+ * Event emitter constructor.
+ *
+ * @api public
+ */
+
+function EventEmitter(){};
+
+/**
+ * Adds a listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.on = function (name, fn) {
+ if (!this.$events) {
+ this.$events = {};
+ }
+
+ if (!this.$events[name]) {
+ this.$events[name] = fn;
+ } else if (isArray(this.$events[name])) {
+ this.$events[name].push(fn);
+ } else {
+ this.$events[name] = [this.$events[name], fn];
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.addListener = EventEmitter.prototype.on;
+
+/**
+ * Adds a volatile listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.once = function (name, fn) {
+ var self = this;
+
+ function on () {
+ self.removeListener(name, on);
+ fn.apply(this, arguments);
+ };
+
+ on.listener = fn;
+ this.on(name, on);
+
+ return this;
+};
+
+/**
+ * Removes a listener.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.removeListener = function (name, fn) {
+ if (this.$events && this.$events[name]) {
+ var list = this.$events[name];
+
+ if (isArray(list)) {
+ var pos = -1;
+
+ for (var i = 0, l = list.length; i < l; i++) {
+ if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
+ pos = i;
+ break;
+ }
+ }
+
+ if (pos < 0) {
+ return this;
+ }
+
+ list.splice(pos, 1);
+
+ if (!list.length) {
+ delete this.$events[name];
+ }
+ } else if (list === fn || (list.listener && list.listener === fn)) {
+ delete this.$events[name];
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Removes all listeners for an event.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.removeAllListeners = function (name) {
+ if (name === undefined) {
+ this.$events = {};
+ return this;
+ }
+
+ if (this.$events && this.$events[name]) {
+ this.$events[name] = null;
+ }
+
+ return this;
+};
+
+/**
+ * Gets all listeners for a certain event.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.listeners = function (name) {
+ if (!this.$events) {
+ this.$events = {};
+ }
+
+ if (!this.$events[name]) {
+ this.$events[name] = [];
+ }
+
+ if (!isArray(this.$events[name])) {
+ this.$events[name] = [this.$events[name]];
+ }
+
+ return this.$events[name];
+};
+
+/**
+ * Emits an event.
+ *
+ * @api public
+ */
+
+EventEmitter.prototype.emit = function (name) {
+ if (!this.$events) {
+ return false;
+ }
+
+ var handler = this.$events[name];
+
+ if (!handler) {
+ return false;
+ }
+
+ var args = [].slice.call(arguments, 1);
+
+ if ('function' == typeof handler) {
+ handler.apply(this, args);
+ } else if (isArray(handler)) {
+ var listeners = handler.slice();
+
+ for (var i = 0, l = listeners.length; i < l; i++) {
+ listeners[i].apply(this, args);
+ }
+ } else {
+ return false;
+ }
+
+ return true;
+};
+
+}); // module: browser/events.js
+
+require.register("browser/fs.js", function(module, exports, require){
+
+}); // module: browser/fs.js
+
+require.register("browser/glob.js", function(module, exports, require){
+
+}); // module: browser/glob.js
+
+require.register("browser/path.js", function(module, exports, require){
+
+}); // module: browser/path.js
+
+require.register("browser/progress.js", function(module, exports, require){
+/**
+ * Expose `Progress`.
+ */
+
+module.exports = Progress;
+
+/**
+ * Initialize a new `Progress` indicator.
+ */
+
+function Progress() {
+ this.percent = 0;
+ this.size(0);
+ this.fontSize(11);
+ this.font('helvetica, arial, sans-serif');
+}
+
+/**
+ * Set progress size to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.size = function(n){
+ this._size = n;
+ return this;
+};
+
+/**
+ * Set text to `str`.
+ *
+ * @param {String} str
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.text = function(str){
+ this._text = str;
+ return this;
+};
+
+/**
+ * Set font size to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ * @api public
+ */
+
+Progress.prototype.fontSize = function(n){
+ this._fontSize = n;
+ return this;
+};
+
+/**
+ * Set font `family`.
+ *
+ * @param {String} family
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.font = function(family){
+ this._font = family;
+ return this;
+};
+
+/**
+ * Update percentage to `n`.
+ *
+ * @param {Number} n
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.update = function(n){
+ this.percent = n;
+ return this;
+};
+
+/**
+ * Draw on `ctx`.
+ *
+ * @param {CanvasRenderingContext2d} ctx
+ * @return {Progress} for chaining
+ */
+
+Progress.prototype.draw = function(ctx){
+ try {
+ var percent = Math.min(this.percent, 100)
+ , size = this._size
+ , half = size / 2
+ , x = half
+ , y = half
+ , rad = half - 1
+ , fontSize = this._fontSize;
+
+ ctx.font = fontSize + 'px ' + this._font;
+
+ var angle = Math.PI * 2 * (percent / 100);
+ ctx.clearRect(0, 0, size, size);
+
+ // outer circle
+ ctx.strokeStyle = '#9f9f9f';
+ ctx.beginPath();
+ ctx.arc(x, y, rad, 0, angle, false);
+ ctx.stroke();
+
+ // inner circle
+ ctx.strokeStyle = '#eee';
+ ctx.beginPath();
+ ctx.arc(x, y, rad - 1, 0, angle, true);
+ ctx.stroke();
+
+ // text
+ var text = this._text || (percent | 0) + '%'
+ , w = ctx.measureText(text).width;
+
+ ctx.fillText(
+ text
+ , x - w / 2 + 1
+ , y + fontSize / 2 - 1);
+ } catch (ex) {} //don't fail if we can't render progress
+ return this;
+};
+
+}); // module: browser/progress.js
+
+require.register("browser/tty.js", function(module, exports, require){
+exports.isatty = function(){
+ return true;
+};
+
+exports.getWindowSize = function(){
+ if ('innerHeight' in global) {
+ return [global.innerHeight, global.innerWidth];
+ } else {
+ // In a Web Worker, the DOM Window is not available.
+ return [640, 480];
+ }
+};
+
+}); // module: browser/tty.js
+
+require.register("context.js", function(module, exports, require){
+/**
+ * Expose `Context`.
+ */
+
+module.exports = Context;
+
+/**
+ * Initialize a new `Context`.
+ *
+ * @api private
+ */
+
+function Context(){}
+
+/**
+ * Set or get the context `Runnable` to `runnable`.
+ *
+ * @param {Runnable} runnable
+ * @return {Context}
+ * @api private
+ */
+
+Context.prototype.runnable = function(runnable){
+ if (0 == arguments.length) return this._runnable;
+ this.test = this._runnable = runnable;
+ return this;
+};
+
+/**
+ * Set test timeout `ms`.
+ *
+ * @param {Number} ms
+ * @return {Context} self
+ * @api private
+ */
+
+Context.prototype.timeout = function(ms){
+ if (arguments.length === 0) return this.runnable().timeout();
+ this.runnable().timeout(ms);
+ return this;
+};
+
+/**
+ * Set test timeout `enabled`.
+ *
+ * @param {Boolean} enabled
+ * @return {Context} self
+ * @api private
+ */
+
+Context.prototype.enableTimeouts = function (enabled) {
+ this.runnable().enableTimeouts(enabled);
+ return this;
+};
+
+
+/**
+ * Set test slowness threshold `ms`.
+ *
+ * @param {Number} ms
+ * @return {Context} self
+ * @api private
+ */
+
+Context.prototype.slow = function(ms){
+ this.runnable().slow(ms);
+ return this;
+};
+
+/**
+ * Mark a test as skipped.
+ *
+ * @return {Context} self
+ * @api private
+ */
+
+Context.prototype.skip = function(){
+ this.runnable().skip();
+ return this;
+};
+
+/**
+ * Inspect the context void of `._runnable`.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Context.prototype.inspect = function(){
+ return JSON.stringify(this, function(key, val){
+ if ('_runnable' == key) return;
+ if ('test' == key) return;
+ return val;
+ }, 2);
+};
+
+}); // module: context.js
+
+require.register("hook.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Runnable = require('./runnable');
+
+/**
+ * Expose `Hook`.
+ */
+
+module.exports = Hook;
+
+/**
+ * Initialize a new `Hook` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Hook(title, fn) {
+ Runnable.call(this, title, fn);
+ this.type = 'hook';
+}
+
+/**
+ * Inherit from `Runnable.prototype`.
+ */
+
+function F(){};
+F.prototype = Runnable.prototype;
+Hook.prototype = new F;
+Hook.prototype.constructor = Hook;
+
+
+/**
+ * Get or set the test `err`.
+ *
+ * @param {Error} err
+ * @return {Error}
+ * @api public
+ */
+
+Hook.prototype.error = function(err){
+ if (0 == arguments.length) {
+ var err = this._error;
+ this._error = null;
+ return err;
+ }
+
+ this._error = err;
+};
+
+}); // module: hook.js
+
+require.register("interfaces/bdd.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+ , Test = require('../test')
+ , utils = require('../utils')
+ , escapeRe = require('browser/escape-string-regexp');
+
+/**
+ * BDD-style interface:
+ *
+ * describe('Array', function(){
+ * describe('#indexOf()', function(){
+ * it('should return -1 when not present', function(){
+ *
+ * });
+ *
+ * it('should return the index when present', function(){
+ *
+ * });
+ * });
+ * });
+ *
+ */
+
+module.exports = function(suite){
+ var suites = [suite];
+
+ suite.on('pre-require', function(context, file, mocha){
+
+ var common = require('./common')(suites, context);
+
+ context.before = common.before;
+ context.after = common.after;
+ context.beforeEach = common.beforeEach;
+ context.afterEach = common.afterEach;
+ context.run = mocha.options.delay && common.runWithSuite(suite);
+ /**
+ * Describe a "suite" with the given `title`
+ * and callback `fn` containing nested suites
+ * and/or tests.
+ */
+
+ context.describe = context.context = function(title, fn){
+ var suite = Suite.create(suites[0], title);
+ suite.file = file;
+ suites.unshift(suite);
+ fn.call(suite);
+ suites.shift();
+ return suite;
+ };
+
+ /**
+ * Pending describe.
+ */
+
+ context.xdescribe =
+ context.xcontext =
+ context.describe.skip = function(title, fn){
+ var suite = Suite.create(suites[0], title);
+ suite.pending = true;
+ suites.unshift(suite);
+ fn.call(suite);
+ suites.shift();
+ };
+
+ /**
+ * Exclusive suite.
+ */
+
+ context.describe.only = function(title, fn){
+ var suite = context.describe(title, fn);
+ mocha.grep(suite.fullTitle());
+ return suite;
+ };
+
+ /**
+ * Describe a specification or test-case
+ * with the given `title` and callback `fn`
+ * acting as a thunk.
+ */
+
+ context.it = context.specify = function(title, fn){
+ var suite = suites[0];
+ if (suite.pending) fn = null;
+ var test = new Test(title, fn);
+ test.file = file;
+ suite.addTest(test);
+ return test;
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.it.only = function(title, fn){
+ var test = context.it(title, fn);
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
+ mocha.grep(new RegExp(reString));
+ return test;
+ };
+
+ /**
+ * Pending test case.
+ */
+
+ context.xit =
+ context.xspecify =
+ context.it.skip = function(title){
+ context.it(title);
+ };
+
+ });
+};
+
+}); // module: interfaces/bdd.js
+
+require.register("interfaces/common.js", function(module, exports, require){
+/**
+ * Functions common to more than one interface
+ * @module lib/interfaces/common
+ */
+
+'use strict';
+
+module.exports = function (suites, context) {
+
+ return {
+ /**
+ * This is only present if flag --delay is passed into Mocha. It triggers
+ * root suite execution. Returns a function which runs the root suite.
+ */
+ runWithSuite: function runWithSuite(suite) {
+ return function run() {
+ suite.run();
+ };
+ },
+
+ /**
+ * Execute before running tests.
+ */
+ before: function (name, fn) {
+ suites[0].beforeAll(name, fn);
+ },
+
+ /**
+ * Execute after running tests.
+ */
+ after: function (name, fn) {
+ suites[0].afterAll(name, fn);
+ },
+
+ /**
+ * Execute before each test case.
+ */
+ beforeEach: function (name, fn) {
+ suites[0].beforeEach(name, fn);
+ },
+
+ /**
+ * Execute after each test case.
+ */
+ afterEach: function (name, fn) {
+ suites[0].afterEach(name, fn);
+ },
+
+ test: {
+ /**
+ * Pending test case.
+ */
+ skip: function (title) {
+ context.test(title);
+ }
+ }
+ }
+};
+
+}); // module: interfaces/common.js
+
+require.register("interfaces/exports.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+ , Test = require('../test');
+
+/**
+ * TDD-style interface:
+ *
+ * exports.Array = {
+ * '#indexOf()': {
+ * 'should return -1 when the value is not present': function(){
+ *
+ * },
+ *
+ * 'should return the correct index when the value is present': function(){
+ *
+ * }
+ * }
+ * };
+ *
+ */
+
+module.exports = function(suite){
+ var suites = [suite];
+
+ suite.on('require', visit);
+
+ function visit(obj, file) {
+ var suite;
+ for (var key in obj) {
+ if ('function' == typeof obj[key]) {
+ var fn = obj[key];
+ switch (key) {
+ case 'before':
+ suites[0].beforeAll(fn);
+ break;
+ case 'after':
+ suites[0].afterAll(fn);
+ break;
+ case 'beforeEach':
+ suites[0].beforeEach(fn);
+ break;
+ case 'afterEach':
+ suites[0].afterEach(fn);
+ break;
+ default:
+ var test = new Test(key, fn);
+ test.file = file;
+ suites[0].addTest(test);
+ }
+ } else {
+ suite = Suite.create(suites[0], key);
+ suites.unshift(suite);
+ visit(obj[key]);
+ suites.shift();
+ }
+ }
+ }
+};
+
+}); // module: interfaces/exports.js
+
+require.register("interfaces/index.js", function(module, exports, require){
+exports.bdd = require('./bdd');
+exports.tdd = require('./tdd');
+exports.qunit = require('./qunit');
+exports.exports = require('./exports');
+
+}); // module: interfaces/index.js
+
+require.register("interfaces/qunit.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+ , Test = require('../test')
+ , escapeRe = require('browser/escape-string-regexp')
+ , utils = require('../utils');
+
+/**
+ * QUnit-style interface:
+ *
+ * suite('Array');
+ *
+ * test('#length', function(){
+ * var arr = [1,2,3];
+ * ok(arr.length == 3);
+ * });
+ *
+ * test('#indexOf()', function(){
+ * var arr = [1,2,3];
+ * ok(arr.indexOf(1) == 0);
+ * ok(arr.indexOf(2) == 1);
+ * ok(arr.indexOf(3) == 2);
+ * });
+ *
+ * suite('String');
+ *
+ * test('#length', function(){
+ * ok('foo'.length == 3);
+ * });
+ *
+ */
+
+module.exports = function(suite){
+ var suites = [suite];
+
+ suite.on('pre-require', function(context, file, mocha){
+
+ var common = require('./common')(suites, context);
+
+ context.before = common.before;
+ context.after = common.after;
+ context.beforeEach = common.beforeEach;
+ context.afterEach = common.afterEach;
+ context.run = mocha.options.delay && common.runWithSuite(suite);
+ /**
+ * Describe a "suite" with the given `title`.
+ */
+
+ context.suite = function(title){
+ if (suites.length > 1) suites.shift();
+ var suite = Suite.create(suites[0], title);
+ suite.file = file;
+ suites.unshift(suite);
+ return suite;
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.suite.only = function(title, fn){
+ var suite = context.suite(title, fn);
+ mocha.grep(suite.fullTitle());
+ };
+
+ /**
+ * Describe a specification or test-case
+ * with the given `title` and callback `fn`
+ * acting as a thunk.
+ */
+
+ context.test = function(title, fn){
+ var test = new Test(title, fn);
+ test.file = file;
+ suites[0].addTest(test);
+ return test;
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.test.only = function(title, fn){
+ var test = context.test(title, fn);
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
+ mocha.grep(new RegExp(reString));
+ };
+
+ context.test.skip = common.test.skip;
+
+ });
+};
+
+}); // module: interfaces/qunit.js
+
+require.register("interfaces/tdd.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Suite = require('../suite')
+ , Test = require('../test')
+ , escapeRe = require('browser/escape-string-regexp')
+ , utils = require('../utils');
+
+/**
+ * TDD-style interface:
+ *
+ * suite('Array', function(){
+ * suite('#indexOf()', function(){
+ * suiteSetup(function(){
+ *
+ * });
+ *
+ * test('should return -1 when not present', function(){
+ *
+ * });
+ *
+ * test('should return the index when present', function(){
+ *
+ * });
+ *
+ * suiteTeardown(function(){
+ *
+ * });
+ * });
+ * });
+ *
+ */
+
+module.exports = function(suite){
+ var suites = [suite];
+
+ suite.on('pre-require', function(context, file, mocha){
+
+ var common = require('./common')(suites, context);
+
+ context.setup = common.beforeEach;
+ context.teardown = common.afterEach;
+ context.suiteSetup = common.before;
+ context.suiteTeardown = common.after;
+ context.run = mocha.options.delay && common.runWithSuite(suite);
+ /**
+ * Describe a "suite" with the given `title`
+ * and callback `fn` containing nested suites
+ * and/or tests.
+ */
+
+ context.suite = function(title, fn){
+ var suite = Suite.create(suites[0], title);
+ suite.file = file;
+ suites.unshift(suite);
+ fn.call(suite);
+ suites.shift();
+ return suite;
+ };
+
+ /**
+ * Pending suite.
+ */
+ context.suite.skip = function(title, fn) {
+ var suite = Suite.create(suites[0], title);
+ suite.pending = true;
+ suites.unshift(suite);
+ fn.call(suite);
+ suites.shift();
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.suite.only = function(title, fn){
+ var suite = context.suite(title, fn);
+ mocha.grep(suite.fullTitle());
+ };
+
+ /**
+ * Describe a specification or test-case
+ * with the given `title` and callback `fn`
+ * acting as a thunk.
+ */
+
+ context.test = function(title, fn){
+ var suite = suites[0];
+ if (suite.pending) fn = null;
+ var test = new Test(title, fn);
+ test.file = file;
+ suite.addTest(test);
+ return test;
+ };
+
+ /**
+ * Exclusive test-case.
+ */
+
+ context.test.only = function(title, fn){
+ var test = context.test(title, fn);
+ var reString = '^' + escapeRe(test.fullTitle()) + '$';
+ mocha.grep(new RegExp(reString));
+ };
+
+ context.test.skip = common.test.skip;
+ });
+};
+
+}); // module: interfaces/tdd.js
+
+require.register("mocha.js", function(module, exports, require){
+/*!
+ * mocha
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('browser/path')
+ , escapeRe = require('browser/escape-string-regexp')
+ , utils = require('./utils');
+
+/**
+ * Expose `Mocha`.
+ */
+
+exports = module.exports = Mocha;
+
+/**
+ * To require local UIs and reporters when running in node.
+ */
+
+if (typeof process !== 'undefined' && typeof process.cwd === 'function') {
+ var join = path.join
+ , cwd = process.cwd();
+ module.paths.push(cwd, join(cwd, 'node_modules'));
+}
+
+/**
+ * Expose internals.
+ */
+
+exports.utils = utils;
+exports.interfaces = require('./interfaces');
+exports.reporters = require('./reporters');
+exports.Runnable = require('./runnable');
+exports.Context = require('./context');
+exports.Runner = require('./runner');
+exports.Suite = require('./suite');
+exports.Hook = require('./hook');
+exports.Test = require('./test');
+
+/**
+ * Return image `name` path.
+ *
+ * @param {String} name
+ * @return {String}
+ * @api private
+ */
+
+function image(name) {
+ return __dirname + '/../images/' + name + '.png';
+}
+
+/**
+ * Setup mocha with `options`.
+ *
+ * Options:
+ *
+ * - `ui` name "bdd", "tdd", "exports" etc
+ * - `reporter` reporter instance, defaults to `mocha.reporters.spec`
+ * - `globals` array of accepted globals
+ * - `timeout` timeout in milliseconds
+ * - `bail` bail on the first test failure
+ * - `slow` milliseconds to wait before considering a test slow
+ * - `ignoreLeaks` ignore global leaks
+ * - `fullTrace` display the full stack-trace on failing
+ * - `grep` string or regexp to filter tests with
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+function Mocha(options) {
+ options = options || {};
+ this.files = [];
+ this.options = options;
+ if (options.grep) this.grep(new RegExp(options.grep));
+ if (options.fgrep) this.grep(options.fgrep);
+ this.suite = new exports.Suite('', new exports.Context);
+ this.ui(options.ui);
+ this.bail(options.bail);
+ this.reporter(options.reporter, options.reporterOptions);
+ if (null != options.timeout) this.timeout(options.timeout);
+ this.useColors(options.useColors);
+ if (options.enableTimeouts !== null) this.enableTimeouts(options.enableTimeouts);
+ if (options.slow) this.slow(options.slow);
+
+ this.suite.on('pre-require', function (context) {
+ exports.afterEach = context.afterEach || context.teardown;
+ exports.after = context.after || context.suiteTeardown;
+ exports.beforeEach = context.beforeEach || context.setup;
+ exports.before = context.before || context.suiteSetup;
+ exports.describe = context.describe || context.suite;
+ exports.it = context.it || context.test;
+ exports.setup = context.setup || context.beforeEach;
+ exports.suiteSetup = context.suiteSetup || context.before;
+ exports.suiteTeardown = context.suiteTeardown || context.after;
+ exports.suite = context.suite || context.describe;
+ exports.teardown = context.teardown || context.afterEach;
+ exports.test = context.test || context.it;
+ exports.run = context.run;
+ });
+}
+
+/**
+ * Enable or disable bailing on the first failure.
+ *
+ * @param {Boolean} [bail]
+ * @api public
+ */
+
+Mocha.prototype.bail = function(bail){
+ if (0 == arguments.length) bail = true;
+ this.suite.bail(bail);
+ return this;
+};
+
+/**
+ * Add test `file`.
+ *
+ * @param {String} file
+ * @api public
+ */
+
+Mocha.prototype.addFile = function(file){
+ this.files.push(file);
+ return this;
+};
+
+/**
+ * Set reporter to `reporter`, defaults to "spec".
+ *
+ * @param {String|Function} reporter name or constructor
+ * @param {Object} reporterOptions optional options
+ * @api public
+ */
+Mocha.prototype.reporter = function(reporter, reporterOptions){
+ if ('function' == typeof reporter) {
+ this._reporter = reporter;
+ } else {
+ reporter = reporter || 'spec';
+ var _reporter;
+ try { _reporter = require('./reporters/' + reporter); } catch (err) {}
+ if (!_reporter) try { _reporter = require(reporter); } catch (err) {}
+ if (!_reporter && reporter === 'teamcity')
+ console.warn('The Teamcity reporter was moved to a package named ' +
+ 'mocha-teamcity-reporter ' +
+ '(https://npmjs.org/package/mocha-teamcity-reporter).');
+ if (!_reporter) throw new Error('invalid reporter "' + reporter + '"');
+ this._reporter = _reporter;
+ }
+ this.options.reporterOptions = reporterOptions;
+ return this;
+};
+
+/**
+ * Set test UI `name`, defaults to "bdd".
+ *
+ * @param {String} bdd
+ * @api public
+ */
+
+Mocha.prototype.ui = function(name){
+ name = name || 'bdd';
+ this._ui = exports.interfaces[name];
+ if (!this._ui) try { this._ui = require(name); } catch (err) {}
+ if (!this._ui) throw new Error('invalid interface "' + name + '"');
+ this._ui = this._ui(this.suite);
+ return this;
+};
+
+/**
+ * Load registered files.
+ *
+ * @api private
+ */
+
+Mocha.prototype.loadFiles = function(fn){
+ var self = this;
+ var suite = this.suite;
+ var pending = this.files.length;
+ this.files.forEach(function(file){
+ file = path.resolve(file);
+ suite.emit('pre-require', global, file, self);
+ suite.emit('require', require(file), file, self);
+ suite.emit('post-require', global, file, self);
+ --pending || (fn && fn());
+ });
+};
+
+/**
+ * Enable growl support.
+ *
+ * @api private
+ */
+
+Mocha.prototype._growl = function(runner, reporter) {
+ var notify = require('growl');
+
+ runner.on('end', function(){
+ var stats = reporter.stats;
+ if (stats.failures) {
+ var msg = stats.failures + ' of ' + runner.total + ' tests failed';
+ notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });
+ } else {
+ notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
+ name: 'mocha'
+ , title: 'Passed'
+ , image: image('ok')
+ });
+ }
+ });
+};
+
+/**
+ * Add regexp to grep, if `re` is a string it is escaped.
+ *
+ * @param {RegExp|String} re
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.grep = function(re){
+ this.options.grep = 'string' == typeof re
+ ? new RegExp(escapeRe(re))
+ : re;
+ return this;
+};
+
+/**
+ * Invert `.grep()` matches.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.invert = function(){
+ this.options.invert = true;
+ return this;
+};
+
+/**
+ * Ignore global leaks.
+ *
+ * @param {Boolean} ignore
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.ignoreLeaks = function(ignore){
+ this.options.ignoreLeaks = !!ignore;
+ return this;
+};
+
+/**
+ * Enable global leak checking.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.checkLeaks = function(){
+ this.options.ignoreLeaks = false;
+ return this;
+};
+
+/**
+ * Display long stack-trace on failing
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.fullTrace = function() {
+ this.options.fullStackTrace = true;
+ return this;
+};
+
+/**
+ * Enable growl support.
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.growl = function(){
+ this.options.growl = true;
+ return this;
+};
+
+/**
+ * Ignore `globals` array or string.
+ *
+ * @param {Array|String} globals
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.globals = function(globals){
+ this.options.globals = (this.options.globals || []).concat(globals);
+ return this;
+};
+
+/**
+ * Emit color output.
+ *
+ * @param {Boolean} colors
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.useColors = function(colors){
+ if (colors !== undefined) {
+ this.options.useColors = colors;
+ }
+ return this;
+};
+
+/**
+ * Use inline diffs rather than +/-.
+ *
+ * @param {Boolean} inlineDiffs
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.useInlineDiffs = function(inlineDiffs) {
+ this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined
+ ? inlineDiffs
+ : false;
+ return this;
+};
+
+/**
+ * Set the timeout in milliseconds.
+ *
+ * @param {Number} timeout
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.timeout = function(timeout){
+ this.suite.timeout(timeout);
+ return this;
+};
+
+/**
+ * Set slowness threshold in milliseconds.
+ *
+ * @param {Number} slow
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.slow = function(slow){
+ this.suite.slow(slow);
+ return this;
+};
+
+/**
+ * Enable timeouts.
+ *
+ * @param {Boolean} enabled
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.enableTimeouts = function(enabled) {
+ this.suite.enableTimeouts(arguments.length && enabled !== undefined
+ ? enabled
+ : true);
+ return this
+};
+
+/**
+ * Makes all tests async (accepting a callback)
+ *
+ * @return {Mocha}
+ * @api public
+ */
+
+Mocha.prototype.asyncOnly = function(){
+ this.options.asyncOnly = true;
+ return this;
+};
+
+/**
+ * Disable syntax highlighting (in browser).
+ * @returns {Mocha}
+ * @api public
+ */
+Mocha.prototype.noHighlighting = function() {
+ this.options.noHighlighting = true;
+ return this;
+};
+
+/**
+ * Delay root suite execution.
+ * @returns {Mocha}
+ * @api public
+ */
+Mocha.prototype.delay = function delay() {
+ this.options.delay = true;
+ return this;
+};
+
+/**
+ * Run tests and invoke `fn()` when complete.
+ *
+ * @param {Function} fn
+ * @return {Runner}
+ * @api public
+ */
+Mocha.prototype.run = function(fn){
+ if (this.files.length) this.loadFiles();
+ var suite = this.suite;
+ var options = this.options;
+ options.files = this.files;
+ var runner = new exports.Runner(suite, options.delay);
+ var reporter = new this._reporter(runner, options);
+ runner.ignoreLeaks = false !== options.ignoreLeaks;
+ runner.fullStackTrace = options.fullStackTrace;
+ runner.asyncOnly = options.asyncOnly;
+ if (options.grep) runner.grep(options.grep, options.invert);
+ if (options.globals) runner.globals(options.globals);
+ if (options.growl) this._growl(runner, reporter);
+ if (options.useColors !== undefined) {
+ exports.reporters.Base.useColors = options.useColors;
+ }
+ exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
+
+ function done(failures) {
+ if (reporter.done) {
+ reporter.done(failures, fn);
+ } else fn && fn(failures);
+ }
+
+ return runner.run(done);
+};
+
+}); // module: mocha.js
+
+require.register("ms.js", function(module, exports, require){
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ * - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} options
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options){
+ options = options || {};
+ if ('string' == typeof val) return parse(val);
+ return options['long'] ? longFormat(val) : shortFormat(val);
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
+ if (!match) return;
+ var n = parseFloat(match[1]);
+ var type = (match[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'y':
+ return n * y;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+ case 'hours':
+ case 'hour':
+ case 'h':
+ return n * h;
+ case 'minutes':
+ case 'minute':
+ case 'm':
+ return n * m;
+ case 'seconds':
+ case 'second':
+ case 's':
+ return n * s;
+ case 'ms':
+ return n;
+ }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function shortFormat(ms) {
+ if (ms >= d) return Math.round(ms / d) + 'd';
+ if (ms >= h) return Math.round(ms / h) + 'h';
+ if (ms >= m) return Math.round(ms / m) + 'm';
+ if (ms >= s) return Math.round(ms / s) + 's';
+ return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function longFormat(ms) {
+ return plural(ms, d, 'day')
+ || plural(ms, h, 'hour')
+ || plural(ms, m, 'minute')
+ || plural(ms, s, 'second')
+ || ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+ if (ms < n) return;
+ if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
+ return Math.ceil(ms / n) + ' ' + name + 's';
+}
+
+}); // module: ms.js
+
+require.register("pending.js", function(module, exports, require){
+
+/**
+ * Expose `Pending`.
+ */
+
+module.exports = Pending;
+
+/**
+ * Initialize a new `Pending` error with the given message.
+ *
+ * @param {String} message
+ */
+
+function Pending(message) {
+ this.message = message;
+}
+
+}); // module: pending.js
+
+require.register("reporters/base.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var tty = require('browser/tty')
+ , diff = require('browser/diff')
+ , ms = require('../ms')
+ , utils = require('../utils')
+ , supportsColor = process.env ? require('supports-color') : null;
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+ , setTimeout = global.setTimeout
+ , setInterval = global.setInterval
+ , clearTimeout = global.clearTimeout
+ , clearInterval = global.clearInterval;
+
+/**
+ * Check if both stdio streams are associated with a tty.
+ */
+
+var isatty = tty.isatty(1) && tty.isatty(2);
+
+/**
+ * Expose `Base`.
+ */
+
+exports = module.exports = Base;
+
+/**
+ * Enable coloring by default, except in the browser interface.
+ */
+
+exports.useColors = process.env
+ ? (supportsColor || (process.env.MOCHA_COLORS !== undefined))
+ : false;
+
+/**
+ * Inline diffs instead of +/-
+ */
+
+exports.inlineDiffs = false;
+
+/**
+ * Default color map.
+ */
+
+exports.colors = {
+ 'pass': 90
+ , 'fail': 31
+ , 'bright pass': 92
+ , 'bright fail': 91
+ , 'bright yellow': 93
+ , 'pending': 36
+ , 'suite': 0
+ , 'error title': 0
+ , 'error message': 31
+ , 'error stack': 90
+ , 'checkmark': 32
+ , 'fast': 90
+ , 'medium': 33
+ , 'slow': 31
+ , 'green': 32
+ , 'light': 90
+ , 'diff gutter': 90
+ , 'diff added': 42
+ , 'diff removed': 41
+};
+
+/**
+ * Default symbol map.
+ */
+
+exports.symbols = {
+ ok: '✓',
+ err: '✖',
+ dot: '․'
+};
+
+// With node.js on Windows: use symbols available in terminal default fonts
+if ('win32' == process.platform) {
+ exports.symbols.ok = '\u221A';
+ exports.symbols.err = '\u00D7';
+ exports.symbols.dot = '.';
+}
+
+/**
+ * Color `str` with the given `type`,
+ * allowing colors to be disabled,
+ * as well as user-defined color
+ * schemes.
+ *
+ * @param {String} type
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+var color = exports.color = function(type, str) {
+ if (!exports.useColors) return String(str);
+ return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
+};
+
+/**
+ * Expose term window size, with some
+ * defaults for when stderr is not a tty.
+ */
+
+exports.window = {
+ width: isatty
+ ? process.stdout.getWindowSize
+ ? process.stdout.getWindowSize(1)[0]
+ : tty.getWindowSize()[1]
+ : 75
+};
+
+/**
+ * Expose some basic cursor interactions
+ * that are common among reporters.
+ */
+
+exports.cursor = {
+ hide: function(){
+ isatty && process.stdout.write('\u001b[?25l');
+ },
+
+ show: function(){
+ isatty && process.stdout.write('\u001b[?25h');
+ },
+
+ deleteLine: function(){
+ isatty && process.stdout.write('\u001b[2K');
+ },
+
+ beginningOfLine: function(){
+ isatty && process.stdout.write('\u001b[0G');
+ },
+
+ CR: function(){
+ if (isatty) {
+ exports.cursor.deleteLine();
+ exports.cursor.beginningOfLine();
+ } else {
+ process.stdout.write('\r');
+ }
+ }
+};
+
+/**
+ * Outut the given `failures` as a list.
+ *
+ * @param {Array} failures
+ * @api public
+ */
+
+exports.list = function(failures){
+ console.log();
+ failures.forEach(function(test, i){
+ // format
+ var fmt = color('error title', ' %s) %s:\n')
+ + color('error message', ' %s')
+ + color('error stack', '\n%s\n');
+
+ // msg
+ var err = test.err
+ , message = err.message || ''
+ , stack = err.stack || message
+ , index = stack.indexOf(message) + message.length
+ , msg = stack.slice(0, index)
+ , actual = err.actual
+ , expected = err.expected
+ , escape = true;
+
+ // uncaught
+ if (err.uncaught) {
+ msg = 'Uncaught ' + msg;
+ }
+ // explicitly show diff
+ if (err.showDiff && sameType(actual, expected)) {
+
+ if ('string' !== typeof actual) {
+ escape = false;
+ err.actual = actual = utils.stringify(actual);
+ err.expected = expected = utils.stringify(expected);
+ }
+
+ fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
+ var match = message.match(/^([^:]+): expected/);
+ msg = '\n ' + color('error message', match ? match[1] : msg);
+
+ if (exports.inlineDiffs) {
+ msg += inlineDiff(err, escape);
+ } else {
+ msg += unifiedDiff(err, escape);
+ }
+ }
+
+ // indent stack trace without msg
+ stack = stack.slice(index ? index + 1 : index)
+ .replace(/^/gm, ' ');
+
+ console.log(fmt, (i + 1), test.fullTitle(), msg, stack);
+ });
+};
+
+/**
+ * Initialize a new `Base` reporter.
+ *
+ * All other reporters generally
+ * inherit from this reporter, providing
+ * stats such as test duration, number
+ * of tests passed / failed etc.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Base(runner) {
+ var self = this
+ , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
+ , failures = this.failures = [];
+
+ if (!runner) return;
+ this.runner = runner;
+
+ runner.stats = stats;
+
+ runner.on('start', function(){
+ stats.start = new Date;
+ });
+
+ runner.on('suite', function(suite){
+ stats.suites = stats.suites || 0;
+ suite.root || stats.suites++;
+ });
+
+ runner.on('test end', function(test){
+ stats.tests = stats.tests || 0;
+ stats.tests++;
+ });
+
+ runner.on('pass', function(test){
+ stats.passes = stats.passes || 0;
+
+ var medium = test.slow() / 2;
+ test.speed = test.duration > test.slow()
+ ? 'slow'
+ : test.duration > medium
+ ? 'medium'
+ : 'fast';
+
+ stats.passes++;
+ });
+
+ runner.on('fail', function(test, err){
+ stats.failures = stats.failures || 0;
+ stats.failures++;
+ test.err = err;
+ failures.push(test);
+ });
+
+ runner.on('end', function(){
+ stats.end = new Date;
+ stats.duration = new Date - stats.start;
+ });
+
+ runner.on('pending', function(){
+ stats.pending++;
+ });
+}
+
+/**
+ * Output common epilogue used by many of
+ * the bundled reporters.
+ *
+ * @api public
+ */
+
+Base.prototype.epilogue = function(){
+ var stats = this.stats;
+ var tests;
+ var fmt;
+
+ console.log();
+
+ // passes
+ fmt = color('bright pass', ' ')
+ + color('green', ' %d passing')
+ + color('light', ' (%s)');
+
+ console.log(fmt,
+ stats.passes || 0,
+ ms(stats.duration));
+
+ // pending
+ if (stats.pending) {
+ fmt = color('pending', ' ')
+ + color('pending', ' %d pending');
+
+ console.log(fmt, stats.pending);
+ }
+
+ // failures
+ if (stats.failures) {
+ fmt = color('fail', ' %d failing');
+
+ console.log(fmt, stats.failures);
+
+ Base.list(this.failures);
+ console.log();
+ }
+
+ console.log();
+};
+
+/**
+ * Pad the given `str` to `len`.
+ *
+ * @param {String} str
+ * @param {String} len
+ * @return {String}
+ * @api private
+ */
+
+function pad(str, len) {
+ str = String(str);
+ return Array(len - str.length + 1).join(' ') + str;
+}
+
+
+/**
+ * Returns an inline diff between 2 strings with coloured ANSI output
+ *
+ * @param {Error} Error with actual/expected
+ * @return {String} Diff
+ * @api private
+ */
+
+function inlineDiff(err, escape) {
+ var msg = errorDiff(err, 'WordsWithSpace', escape);
+
+ // linenos
+ var lines = msg.split('\n');
+ if (lines.length > 4) {
+ var width = String(lines.length).length;
+ msg = lines.map(function(str, i){
+ return pad(++i, width) + ' |' + ' ' + str;
+ }).join('\n');
+ }
+
+ // legend
+ msg = '\n'
+ + color('diff removed', 'actual')
+ + ' '
+ + color('diff added', 'expected')
+ + '\n\n'
+ + msg
+ + '\n';
+
+ // indent
+ msg = msg.replace(/^/gm, ' ');
+ return msg;
+}
+
+/**
+ * Returns a unified diff between 2 strings
+ *
+ * @param {Error} Error with actual/expected
+ * @return {String} Diff
+ * @api private
+ */
+
+function unifiedDiff(err, escape) {
+ var indent = ' ';
+ function cleanUp(line) {
+ if (escape) {
+ line = escapeInvisibles(line);
+ }
+ if (line[0] === '+') return indent + colorLines('diff added', line);
+ if (line[0] === '-') return indent + colorLines('diff removed', line);
+ if (line.match(/\@\@/)) return null;
+ if (line.match(/\\ No newline/)) return null;
+ else return indent + line;
+ }
+ function notBlank(line) {
+ return line != null;
+ }
+ var msg = diff.createPatch('string', err.actual, err.expected);
+ var lines = msg.split('\n').splice(4);
+ return '\n '
+ + colorLines('diff added', '+ expected') + ' '
+ + colorLines('diff removed', '- actual')
+ + '\n\n'
+ + lines.map(cleanUp).filter(notBlank).join('\n');
+}
+
+/**
+ * Return a character diff for `err`.
+ *
+ * @param {Error} err
+ * @return {String}
+ * @api private
+ */
+
+function errorDiff(err, type, escape) {
+ var actual = escape ? escapeInvisibles(err.actual) : err.actual;
+ var expected = escape ? escapeInvisibles(err.expected) : err.expected;
+ return diff['diff' + type](actual, expected).map(function(str){
+ if (str.added) return colorLines('diff added', str.value);
+ if (str.removed) return colorLines('diff removed', str.value);
+ return str.value;
+ }).join('');
+}
+
+/**
+ * Returns a string with all invisible characters in plain text
+ *
+ * @param {String} line
+ * @return {String}
+ * @api private
+ */
+function escapeInvisibles(line) {
+ return line.replace(/\t/g, '<tab>')
+ .replace(/\r/g, '<CR>')
+ .replace(/\n/g, '<LF>\n');
+}
+
+/**
+ * Color lines for `str`, using the color `name`.
+ *
+ * @param {String} name
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+function colorLines(name, str) {
+ return str.split('\n').map(function(str){
+ return color(name, str);
+ }).join('\n');
+}
+
+/**
+ * Check that a / b have the same type.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Boolean}
+ * @api private
+ */
+
+function sameType(a, b) {
+ a = Object.prototype.toString.call(a);
+ b = Object.prototype.toString.call(b);
+ return a == b;
+}
+
+}); // module: reporters/base.js
+
+require.register("reporters/doc.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , utils = require('../utils');
+
+/**
+ * Expose `Doc`.
+ */
+
+exports = module.exports = Doc;
+
+/**
+ * Initialize a new `Doc` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Doc(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , total = runner.total
+ , indents = 2;
+
+ function indent() {
+ return Array(indents).join(' ');
+ }
+
+ runner.on('suite', function(suite){
+ if (suite.root) return;
+ ++indents;
+ console.log('%s<section class="suite">', indent());
+ ++indents;
+ console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));
+ console.log('%s<dl>', indent());
+ });
+
+ runner.on('suite end', function(suite){
+ if (suite.root) return;
+ console.log('%s</dl>', indent());
+ --indents;
+ console.log('%s</section>', indent());
+ --indents;
+ });
+
+ runner.on('pass', function(test){
+ console.log('%s <dt>%s</dt>', indent(), utils.escape(test.title));
+ var code = utils.escape(utils.clean(test.fn.toString()));
+ console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
+ });
+
+ runner.on('fail', function(test, err){
+ console.log('%s <dt class="error">%s</dt>', indent(), utils.escape(test.title));
+ var code = utils.escape(utils.clean(test.fn.toString()));
+ console.log('%s <dd class="error"><pre><code>%s</code></pre></dd>', indent(), code);
+ console.log('%s <dd class="error">%s</dd>', indent(), utils.escape(err));
+ });
+}
+
+}); // module: reporters/doc.js
+
+require.register("reporters/dot.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , color = Base.color;
+
+/**
+ * Expose `Dot`.
+ */
+
+exports = module.exports = Dot;
+
+/**
+ * Initialize a new `Dot` matrix test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Dot(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , width = Base.window.width * .75 | 0
+ , n = -1;
+
+ runner.on('start', function(){
+ process.stdout.write('\n ');
+ });
+
+ runner.on('pending', function(test){
+ if (++n % width == 0) process.stdout.write('\n ');
+ process.stdout.write(color('pending', Base.symbols.dot));
+ });
+
+ runner.on('pass', function(test){
+ if (++n % width == 0) process.stdout.write('\n ');
+ if ('slow' == test.speed) {
+ process.stdout.write(color('bright yellow', Base.symbols.dot));
+ } else {
+ process.stdout.write(color(test.speed, Base.symbols.dot));
+ }
+ });
+
+ runner.on('fail', function(test, err){
+ if (++n % width == 0) process.stdout.write('\n ');
+ process.stdout.write(color('fail', Base.symbols.dot));
+ });
+
+ runner.on('end', function(){
+ console.log();
+ self.epilogue();
+ });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Dot.prototype = new F;
+Dot.prototype.constructor = Dot;
+
+
+}); // module: reporters/dot.js
+
+require.register("reporters/html-cov.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var JSONCov = require('./json-cov')
+ , fs = require('browser/fs');
+
+/**
+ * Expose `HTMLCov`.
+ */
+
+exports = module.exports = HTMLCov;
+
+/**
+ * Initialize a new `JsCoverage` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTMLCov(runner) {
+ var jade = require('jade')
+ , file = __dirname + '/templates/coverage.jade'
+ , str = fs.readFileSync(file, 'utf8')
+ , fn = jade.compile(str, { filename: file })
+ , self = this;
+
+ JSONCov.call(this, runner, false);
+
+ runner.on('end', function(){
+ process.stdout.write(fn({
+ cov: self.cov
+ , coverageClass: coverageClass
+ }));
+ });
+}
+
+/**
+ * Return coverage class for `n`.
+ *
+ * @return {String}
+ * @api private
+ */
+
+function coverageClass(n) {
+ if (n >= 75) return 'high';
+ if (n >= 50) return 'medium';
+ if (n >= 25) return 'low';
+ return 'terrible';
+}
+
+}); // module: reporters/html-cov.js
+
+require.register("reporters/html.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , utils = require('../utils')
+ , Progress = require('../browser/progress')
+ , escape = utils.escape;
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+ , setTimeout = global.setTimeout
+ , setInterval = global.setInterval
+ , clearTimeout = global.clearTimeout
+ , clearInterval = global.clearInterval;
+
+/**
+ * Expose `HTML`.
+ */
+
+exports = module.exports = HTML;
+
+/**
+ * Stats template.
+ */
+
+var statsTemplate = '<ul id="mocha-stats">'
+ + '<li class="progress"><canvas width="40" height="40"></canvas></li>'
+ + '<li class="passes"><a href="#">passes:</a> <em>0</em></li>'
+ + '<li class="failures"><a href="#">failures:</a> <em>0</em></li>'
+ + '<li class="duration">duration: <em>0</em>s</li>'
+ + '</ul>';
+
+/**
+ * Initialize a new `HTML` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function HTML(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , total = runner.total
+ , stat = fragment(statsTemplate)
+ , items = stat.getElementsByTagName('li')
+ , passes = items[1].getElementsByTagName('em')[0]
+ , passesLink = items[1].getElementsByTagName('a')[0]
+ , failures = items[2].getElementsByTagName('em')[0]
+ , failuresLink = items[2].getElementsByTagName('a')[0]
+ , duration = items[3].getElementsByTagName('em')[0]
+ , canvas = stat.getElementsByTagName('canvas')[0]
+ , report = fragment('<ul id="mocha-report"></ul>')
+ , stack = [report]
+ , progress
+ , ctx
+ , root = document.getElementById('mocha');
+
+ if (canvas.getContext) {
+ var ratio = window.devicePixelRatio || 1;
+ canvas.style.width = canvas.width;
+ canvas.style.height = canvas.height;
+ canvas.width *= ratio;
+ canvas.height *= ratio;
+ ctx = canvas.getContext('2d');
+ ctx.scale(ratio, ratio);
+ progress = new Progress;
+ }
+
+ if (!root) return error('#mocha div missing, add it to your document');
+
+ // pass toggle
+ on(passesLink, 'click', function(){
+ unhide();
+ var name = /pass/.test(report.className) ? '' : ' pass';
+ report.className = report.className.replace(/fail|pass/g, '') + name;
+ if (report.className.trim()) hideSuitesWithout('test pass');
+ });
+
+ // failure toggle
+ on(failuresLink, 'click', function(){
+ unhide();
+ var name = /fail/.test(report.className) ? '' : ' fail';
+ report.className = report.className.replace(/fail|pass/g, '') + name;
+ if (report.className.trim()) hideSuitesWithout('test fail');
+ });
+
+ root.appendChild(stat);
+ root.appendChild(report);
+
+ if (progress) progress.size(40);
+
+ runner.on('suite', function(suite){
+ if (suite.root) return;
+
+ // suite
+ var url = self.suiteURL(suite);
+ var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title));
+
+ // container
+ stack[0].appendChild(el);
+ stack.unshift(document.createElement('ul'));
+ el.appendChild(stack[0]);
+ });
+
+ runner.on('suite end', function(suite){
+ if (suite.root) return;
+ stack.shift();
+ });
+
+ runner.on('fail', function(test, err){
+ if ('hook' == test.type) runner.emit('test end', test);
+ });
+
+ runner.on('test end', function(test){
+ // TODO: add to stats
+ var percent = stats.tests / this.total * 100 | 0;
+ if (progress) progress.update(percent).draw(ctx);
+
+ // update stats
+ var ms = new Date - stats.start;
+ text(passes, stats.passes);
+ text(failures, stats.failures);
+ text(duration, (ms / 1000).toFixed(2));
+
+ // test
+ if ('passed' == test.state) {
+ var url = self.testURL(test);
+ var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="%s" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, url);
+ } else if (test.pending) {
+ var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title);
+ } else {
+ var el = fragment('<li class="test fail"><h2>%e <a href="%e" class="replay">‣</a></h2></li>', test.title, self.testURL(test));
+ var str = test.err.stack || test.err.toString();
+
+ // FF / Opera do not add the message
+ if (!~str.indexOf(test.err.message)) {
+ str = test.err.message + '\n' + str;
+ }
+
+ // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
+ // check for the result of the stringifying.
+ if ('[object Error]' == str) str = test.err.message;
+
+ // Safari doesn't give you a stack. Let's at least provide a source line.
+ if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
+ str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
+ }
+
+ el.appendChild(fragment('<pre class="error">%e</pre>', str));
+ }
+
+ // toggle code
+ // TODO: defer
+ if (!test.pending) {
+ var h2 = el.getElementsByTagName('h2')[0];
+
+ on(h2, 'click', function(){
+ pre.style.display = 'none' == pre.style.display
+ ? 'block'
+ : 'none';
+ });
+
+ var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));
+ el.appendChild(pre);
+ pre.style.display = 'none';
+ }
+
+ // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
+ if (stack[0]) stack[0].appendChild(el);
+ });
+}
+
+/**
+ * Makes a URL, preserving querystring ("search") parameters.
+ * @param {string} s
+ * @returns {string} your new URL
+ */
+var makeUrl = function makeUrl(s) {
+ var search = window.location.search;
+
+ // Remove previous grep query parameter if present
+ if (search) {
+ search = search.replace(/[?&]grep=[^&\s]*/g, '').replace(/^&/, '?');
+ }
+
+ return window.location.pathname + (search ? search + '&' : '?' ) + 'grep=' + encodeURIComponent(s);
+};
+
+/**
+ * Provide suite URL
+ *
+ * @param {Object} [suite]
+ */
+HTML.prototype.suiteURL = function(suite){
+ return makeUrl(suite.fullTitle());
+};
+
+/**
+ * Provide test URL
+ *
+ * @param {Object} [test]
+ */
+
+HTML.prototype.testURL = function(test){
+ return makeUrl(test.fullTitle());
+};
+
+/**
+ * Display error `msg`.
+ */
+
+function error(msg) {
+ document.body.appendChild(fragment('<div id="mocha-error">%s</div>', msg));
+}
+
+/**
+ * Return a DOM fragment from `html`.
+ */
+
+function fragment(html) {
+ var args = arguments
+ , div = document.createElement('div')
+ , i = 1;
+
+ div.innerHTML = html.replace(/%([se])/g, function(_, type){
+ switch (type) {
+ case 's': return String(args[i++]);
+ case 'e': return escape(args[i++]);
+ }
+ });
+
+ return div.firstChild;
+}
+
+/**
+ * Check for suites that do not have elements
+ * with `classname`, and hide them.
+ */
+
+function hideSuitesWithout(classname) {
+ var suites = document.getElementsByClassName('suite');
+ for (var i = 0; i < suites.length; i++) {
+ var els = suites[i].getElementsByClassName(classname);
+ if (0 == els.length) suites[i].className += ' hidden';
+ }
+}
+
+/**
+ * Unhide .hidden suites.
+ */
+
+function unhide() {
+ var els = document.getElementsByClassName('suite hidden');
+ for (var i = 0; i < els.length; ++i) {
+ els[i].className = els[i].className.replace('suite hidden', 'suite');
+ }
+}
+
+/**
+ * Set `el` text to `str`.
+ */
+
+function text(el, str) {
+ if (el.textContent) {
+ el.textContent = str;
+ } else {
+ el.innerText = str;
+ }
+}
+
+/**
+ * Listen on `event` with callback `fn`.
+ */
+
+function on(el, event, fn) {
+ if (el.addEventListener) {
+ el.addEventListener(event, fn, false);
+ } else {
+ el.attachEvent('on' + event, fn);
+ }
+}
+
+}); // module: reporters/html.js
+
+require.register("reporters/index.js", function(module, exports, require){
+exports.Base = require('./base');
+exports.Dot = require('./dot');
+exports.Doc = require('./doc');
+exports.TAP = require('./tap');
+exports.JSON = require('./json');
+exports.HTML = require('./html');
+exports.List = require('./list');
+exports.Min = require('./min');
+exports.Spec = require('./spec');
+exports.Nyan = require('./nyan');
+exports.XUnit = require('./xunit');
+exports.Markdown = require('./markdown');
+exports.Progress = require('./progress');
+exports.Landing = require('./landing');
+exports.JSONCov = require('./json-cov');
+exports.HTMLCov = require('./html-cov');
+exports.JSONStream = require('./json-stream');
+
+}); // module: reporters/index.js
+
+require.register("reporters/json-cov.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `JSONCov`.
+ */
+
+exports = module.exports = JSONCov;
+
+/**
+ * Initialize a new `JsCoverage` reporter.
+ *
+ * @param {Runner} runner
+ * @param {Boolean} output
+ * @api public
+ */
+
+function JSONCov(runner, output) {
+ var self = this
+ , output = 1 == arguments.length ? true : output;
+
+ Base.call(this, runner);
+
+ var tests = []
+ , failures = []
+ , passes = [];
+
+ runner.on('test end', function(test){
+ tests.push(test);
+ });
+
+ runner.on('pass', function(test){
+ passes.push(test);
+ });
+
+ runner.on('fail', function(test){
+ failures.push(test);
+ });
+
+ runner.on('end', function(){
+ var cov = global._$jscoverage || {};
+ var result = self.cov = map(cov);
+ result.stats = self.stats;
+ result.tests = tests.map(clean);
+ result.failures = failures.map(clean);
+ result.passes = passes.map(clean);
+ if (!output) return;
+ process.stdout.write(JSON.stringify(result, null, 2 ));
+ });
+}
+
+/**
+ * Map jscoverage data to a JSON structure
+ * suitable for reporting.
+ *
+ * @param {Object} cov
+ * @return {Object}
+ * @api private
+ */
+
+function map(cov) {
+ var ret = {
+ instrumentation: 'node-jscoverage'
+ , sloc: 0
+ , hits: 0
+ , misses: 0
+ , coverage: 0
+ , files: []
+ };
+
+ for (var filename in cov) {
+ var data = coverage(filename, cov[filename]);
+ ret.files.push(data);
+ ret.hits += data.hits;
+ ret.misses += data.misses;
+ ret.sloc += data.sloc;
+ }
+
+ ret.files.sort(function(a, b) {
+ return a.filename.localeCompare(b.filename);
+ });
+
+ if (ret.sloc > 0) {
+ ret.coverage = (ret.hits / ret.sloc) * 100;
+ }
+
+ return ret;
+}
+
+/**
+ * Map jscoverage data for a single source file
+ * to a JSON structure suitable for reporting.
+ *
+ * @param {String} filename name of the source file
+ * @param {Object} data jscoverage coverage data
+ * @return {Object}
+ * @api private
+ */
+
+function coverage(filename, data) {
+ var ret = {
+ filename: filename,
+ coverage: 0,
+ hits: 0,
+ misses: 0,
+ sloc: 0,
+ source: {}
+ };
+
+ data.source.forEach(function(line, num){
+ num++;
+
+ if (data[num] === 0) {
+ ret.misses++;
+ ret.sloc++;
+ } else if (data[num] !== undefined) {
+ ret.hits++;
+ ret.sloc++;
+ }
+
+ ret.source[num] = {
+ source: line
+ , coverage: data[num] === undefined
+ ? ''
+ : data[num]
+ };
+ });
+
+ ret.coverage = ret.hits / ret.sloc * 100;
+
+ return ret;
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+ return {
+ title: test.title
+ , fullTitle: test.fullTitle()
+ , duration: test.duration
+ }
+}
+
+}); // module: reporters/json-cov.js
+
+require.register("reporters/json-stream.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , color = Base.color;
+
+/**
+ * Expose `List`.
+ */
+
+exports = module.exports = List;
+
+/**
+ * Initialize a new `List` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function List(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , total = runner.total;
+
+ runner.on('start', function(){
+ console.log(JSON.stringify(['start', { total: total }]));
+ });
+
+ runner.on('pass', function(test){
+ console.log(JSON.stringify(['pass', clean(test)]));
+ });
+
+ runner.on('fail', function(test, err){
+ test = clean(test);
+ test.err = err.message;
+ console.log(JSON.stringify(['fail', test]));
+ });
+
+ runner.on('end', function(){
+ process.stdout.write(JSON.stringify(['end', self.stats]));
+ });
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+ return {
+ title: test.title
+ , fullTitle: test.fullTitle()
+ , duration: test.duration
+ }
+}
+
+}); // module: reporters/json-stream.js
+
+require.register("reporters/json.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , cursor = Base.cursor
+ , color = Base.color;
+
+/**
+ * Expose `JSON`.
+ */
+
+exports = module.exports = JSONReporter;
+
+/**
+ * Initialize a new `JSON` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function JSONReporter(runner) {
+ var self = this;
+ Base.call(this, runner);
+
+ var tests = []
+ , pending = []
+ , failures = []
+ , passes = [];
+
+ runner.on('test end', function(test){
+ tests.push(test);
+ });
+
+ runner.on('pass', function(test){
+ passes.push(test);
+ });
+
+ runner.on('fail', function(test){
+ failures.push(test);
+ });
+
+ runner.on('pending', function(test){
+ pending.push(test);
+ });
+
+ runner.on('end', function(){
+ var obj = {
+ stats: self.stats,
+ tests: tests.map(clean),
+ pending: pending.map(clean),
+ failures: failures.map(clean),
+ passes: passes.map(clean)
+ };
+
+ runner.testResults = obj;
+
+ process.stdout.write(JSON.stringify(obj, null, 2));
+ });
+}
+
+/**
+ * Return a plain-object representation of `test`
+ * free of cyclic properties etc.
+ *
+ * @param {Object} test
+ * @return {Object}
+ * @api private
+ */
+
+function clean(test) {
+ return {
+ title: test.title,
+ fullTitle: test.fullTitle(),
+ duration: test.duration,
+ err: errorJSON(test.err || {})
+ }
+}
+
+/**
+ * Transform `error` into a JSON object.
+ * @param {Error} err
+ * @return {Object}
+ */
+
+function errorJSON(err) {
+ var res = {};
+ Object.getOwnPropertyNames(err).forEach(function(key) {
+ res[key] = err[key];
+ }, err);
+ return res;
+}
+
+}); // module: reporters/json.js
+
+require.register("reporters/landing.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , cursor = Base.cursor
+ , color = Base.color;
+
+/**
+ * Expose `Landing`.
+ */
+
+exports = module.exports = Landing;
+
+/**
+ * Airplane color.
+ */
+
+Base.colors.plane = 0;
+
+/**
+ * Airplane crash color.
+ */
+
+Base.colors['plane crash'] = 31;
+
+/**
+ * Runway color.
+ */
+
+Base.colors.runway = 90;
+
+/**
+ * Initialize a new `Landing` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Landing(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , width = Base.window.width * .75 | 0
+ , total = runner.total
+ , stream = process.stdout
+ , plane = color('plane', '✈')
+ , crashed = -1
+ , n = 0;
+
+ function runway() {
+ var buf = Array(width).join('-');
+ return ' ' + color('runway', buf);
+ }
+
+ runner.on('start', function(){
+ stream.write('\n\n\n ');
+ cursor.hide();
+ });
+
+ runner.on('test end', function(test){
+ // check if the plane crashed
+ var col = -1 == crashed
+ ? width * ++n / total | 0
+ : crashed;
+
+ // show the crash
+ if ('failed' == test.state) {
+ plane = color('plane crash', '✈');
+ crashed = col;
+ }
+
+ // render landing strip
+ stream.write('\u001b['+(width+1)+'D\u001b[2A');
+ stream.write(runway());
+ stream.write('\n ');
+ stream.write(color('runway', Array(col).join('⋅')));
+ stream.write(plane)
+ stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
+ stream.write(runway());
+ stream.write('\u001b[0m');
+ });
+
+ runner.on('end', function(){
+ cursor.show();
+ console.log();
+ self.epilogue();
+ });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Landing.prototype = new F;
+Landing.prototype.constructor = Landing;
+
+
+}); // module: reporters/landing.js
+
+require.register("reporters/list.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , cursor = Base.cursor
+ , color = Base.color;
+
+/**
+ * Expose `List`.
+ */
+
+exports = module.exports = List;
+
+/**
+ * Initialize a new `List` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function List(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , n = 0;
+
+ runner.on('start', function(){
+ console.log();
+ });
+
+ runner.on('test', function(test){
+ process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
+ });
+
+ runner.on('pending', function(test){
+ var fmt = color('checkmark', ' -')
+ + color('pending', ' %s');
+ console.log(fmt, test.fullTitle());
+ });
+
+ runner.on('pass', function(test){
+ var fmt = color('checkmark', ' '+Base.symbols.dot)
+ + color('pass', ' %s: ')
+ + color(test.speed, '%dms');
+ cursor.CR();
+ console.log(fmt, test.fullTitle(), test.duration);
+ });
+
+ runner.on('fail', function(test, err){
+ cursor.CR();
+ console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
+ });
+
+ runner.on('end', self.epilogue.bind(self));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+List.prototype = new F;
+List.prototype.constructor = List;
+
+
+}); // module: reporters/list.js
+
+require.register("reporters/markdown.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , utils = require('../utils');
+
+/**
+ * Constants
+ */
+
+var SUITE_PREFIX = '$';
+
+/**
+ * Expose `Markdown`.
+ */
+
+exports = module.exports = Markdown;
+
+/**
+ * Initialize a new `Markdown` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Markdown(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , level = 0
+ , buf = '';
+
+ function title(str) {
+ return Array(level).join('#') + ' ' + str;
+ }
+
+ function indent() {
+ return Array(level).join(' ');
+ }
+
+ function mapTOC(suite, obj) {
+ var ret = obj,
+ key = SUITE_PREFIX + suite.title;
+ obj = obj[key] = obj[key] || { suite: suite };
+ suite.suites.forEach(function(suite){
+ mapTOC(suite, obj);
+ });
+ return ret;
+ }
+
+ function stringifyTOC(obj, level) {
+ ++level;
+ var buf = '';
+ var link;
+ for (var key in obj) {
+ if ('suite' == key) continue;
+ if (key !== SUITE_PREFIX) {
+ link = ' - [' + key.substring(1) + ']';
+ link += '(#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
+ buf += Array(level).join(' ') + link;
+ }
+ buf += stringifyTOC(obj[key], level);
+ }
+ return buf;
+ }
+
+ function generateTOC(suite) {
+ var obj = mapTOC(suite, {});
+ return stringifyTOC(obj, 0);
+ }
+
+ generateTOC(runner.suite);
+
+ runner.on('suite', function(suite){
+ ++level;
+ var slug = utils.slug(suite.fullTitle());
+ buf += '<a name="' + slug + '"></a>' + '\n';
+ buf += title(suite.title) + '\n';
+ });
+
+ runner.on('suite end', function(suite){
+ --level;
+ });
+
+ runner.on('pass', function(test){
+ var code = utils.clean(test.fn.toString());
+ buf += test.title + '.\n';
+ buf += '\n```js\n';
+ buf += code + '\n';
+ buf += '```\n\n';
+ });
+
+ runner.on('end', function(){
+ process.stdout.write('# TOC\n');
+ process.stdout.write(generateTOC(runner.suite));
+ process.stdout.write(buf);
+ });
+}
+
+}); // module: reporters/markdown.js
+
+require.register("reporters/min.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Min`.
+ */
+
+exports = module.exports = Min;
+
+/**
+ * Initialize a new `Min` minimal test reporter (best used with --watch).
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Min(runner) {
+ Base.call(this, runner);
+
+ runner.on('start', function(){
+ // clear screen
+ process.stdout.write('\u001b[2J');
+ // set cursor position
+ process.stdout.write('\u001b[1;3H');
+ });
+
+ runner.on('end', this.epilogue.bind(this));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Min.prototype = new F;
+Min.prototype.constructor = Min;
+
+
+}); // module: reporters/min.js
+
+require.register("reporters/nyan.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base');
+
+/**
+ * Expose `Dot`.
+ */
+
+exports = module.exports = NyanCat;
+
+/**
+ * Initialize a new `Dot` matrix test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function NyanCat(runner) {
+ Base.call(this, runner);
+ var self = this
+ , stats = this.stats
+ , width = Base.window.width * .75 | 0
+ , rainbowColors = this.rainbowColors = self.generateColors()
+ , colorIndex = this.colorIndex = 0
+ , numerOfLines = this.numberOfLines = 4
+ , trajectories = this.trajectories = [[], [], [], []]
+ , nyanCatWidth = this.nyanCatWidth = 11
+ , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)
+ , scoreboardWidth = this.scoreboardWidth = 5
+ , tick = this.tick = 0
+ , n = 0;
+
+ runner.on('start', function(){
+ Base.cursor.hide();
+ self.draw();
+ });
+
+ runner.on('pending', function(test){
+ self.draw();
+ });
+
+ runner.on('pass', function(test){
+ self.draw();
+ });
+
+ runner.on('fail', function(test, err){
+ self.draw();
+ });
+
+ runner.on('end', function(){
+ Base.cursor.show();
+ for (var i = 0; i < self.numberOfLines; i++) write('\n');
+ self.epilogue();
+ });
+}
+
+/**
+ * Draw the nyan cat
+ *
+ * @api private
+ */
+
+NyanCat.prototype.draw = function(){
+ this.appendRainbow();
+ this.drawScoreboard();
+ this.drawRainbow();
+ this.drawNyanCat();
+ this.tick = !this.tick;
+};
+
+/**
+ * Draw the "scoreboard" showing the number
+ * of passes, failures and pending tests.
+ *
+ * @api private
+ */
+
+NyanCat.prototype.drawScoreboard = function(){
+ var stats = this.stats;
+
+ function draw(type, n) {
+ write(' ');
+ write(Base.color(type, n));
+ write('\n');
+ }
+
+ draw('green', stats.passes);
+ draw('fail', stats.failures);
+ draw('pending', stats.pending);
+ write('\n');
+
+ this.cursorUp(this.numberOfLines);
+};
+
+/**
+ * Append the rainbow.
+ *
+ * @api private
+ */
+
+NyanCat.prototype.appendRainbow = function(){
+ var segment = this.tick ? '_' : '-';
+ var rainbowified = this.rainbowify(segment);
+
+ for (var index = 0; index < this.numberOfLines; index++) {
+ var trajectory = this.trajectories[index];
+ if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();
+ trajectory.push(rainbowified);
+ }
+};
+
+/**
+ * Draw the rainbow.
+ *
+ * @api private
+ */
+
+NyanCat.prototype.drawRainbow = function(){
+ var self = this;
+
+ this.trajectories.forEach(function(line, index) {
+ write('\u001b[' + self.scoreboardWidth + 'C');
+ write(line.join(''));
+ write('\n');
+ });
+
+ this.cursorUp(this.numberOfLines);
+};
+
+/**
+ * Draw the nyan cat
+ *
+ * @api private
+ */
+
+NyanCat.prototype.drawNyanCat = function() {
+ var self = this;
+ var startWidth = this.scoreboardWidth + this.trajectories[0].length;
+ var dist = '\u001b[' + startWidth + 'C';
+ var padding = '';
+
+ write(dist);
+ write('_,------,');
+ write('\n');
+
+ write(dist);
+ padding = self.tick ? ' ' : ' ';
+ write('_|' + padding + '/\\_/\\ ');
+ write('\n');
+
+ write(dist);
+ padding = self.tick ? '_' : '__';
+ var tail = self.tick ? '~' : '^';
+ var face;
+ write(tail + '|' + padding + this.face() + ' ');
+ write('\n');
+
+ write(dist);
+ padding = self.tick ? ' ' : ' ';
+ write(padding + '"" "" ');
+ write('\n');
+
+ this.cursorUp(this.numberOfLines);
+};
+
+/**
+ * Draw nyan cat face.
+ *
+ * @return {String}
+ * @api private
+ */
+
+NyanCat.prototype.face = function() {
+ var stats = this.stats;
+ if (stats.failures) {
+ return '( x .x)';
+ } else if (stats.pending) {
+ return '( o .o)';
+ } else if(stats.passes) {
+ return '( ^ .^)';
+ } else {
+ return '( - .-)';
+ }
+};
+
+/**
+ * Move cursor up `n`.
+ *
+ * @param {Number} n
+ * @api private
+ */
+
+NyanCat.prototype.cursorUp = function(n) {
+ write('\u001b[' + n + 'A');
+};
+
+/**
+ * Move cursor down `n`.
+ *
+ * @param {Number} n
+ * @api private
+ */
+
+NyanCat.prototype.cursorDown = function(n) {
+ write('\u001b[' + n + 'B');
+};
+
+/**
+ * Generate rainbow colors.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+NyanCat.prototype.generateColors = function(){
+ var colors = [];
+
+ for (var i = 0; i < (6 * 7); i++) {
+ var pi3 = Math.floor(Math.PI / 3);
+ var n = (i * (1.0 / 6));
+ var r = Math.floor(3 * Math.sin(n) + 3);
+ var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
+ var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
+ colors.push(36 * r + 6 * g + b + 16);
+ }
+
+ return colors;
+};
+
+/**
+ * Apply rainbow to the given `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+NyanCat.prototype.rainbowify = function(str){
+ if (!Base.useColors)
+ return str;
+ var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
+ this.colorIndex += 1;
+ return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
+};
+
+/**
+ * Stdout helper.
+ */
+
+function write(string) {
+ process.stdout.write(string);
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+NyanCat.prototype = new F;
+NyanCat.prototype.constructor = NyanCat;
+
+
+}); // module: reporters/nyan.js
+
+require.register("reporters/progress.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , cursor = Base.cursor
+ , color = Base.color;
+
+/**
+ * Expose `Progress`.
+ */
+
+exports = module.exports = Progress;
+
+/**
+ * General progress bar color.
+ */
+
+Base.colors.progress = 90;
+
+/**
+ * Initialize a new `Progress` bar test reporter.
+ *
+ * @param {Runner} runner
+ * @param {Object} options
+ * @api public
+ */
+
+function Progress(runner, options) {
+ Base.call(this, runner);
+
+ var self = this
+ , options = options || {}
+ , stats = this.stats
+ , width = Base.window.width * .50 | 0
+ , total = runner.total
+ , complete = 0
+ , max = Math.max
+ , lastN = -1;
+
+ // default chars
+ options.open = options.open || '[';
+ options.complete = options.complete || '▬';
+ options.incomplete = options.incomplete || Base.symbols.dot;
+ options.close = options.close || ']';
+ options.verbose = false;
+
+ // tests started
+ runner.on('start', function(){
+ console.log();
+ cursor.hide();
+ });
+
+ // tests complete
+ runner.on('test end', function(){
+ complete++;
+ var incomplete = total - complete
+ , percent = complete / total
+ , n = width * percent | 0
+ , i = width - n;
+
+ if (lastN === n && !options.verbose) {
+ // Don't re-render the line if it hasn't changed
+ return;
+ }
+ lastN = n;
+
+ cursor.CR();
+ process.stdout.write('\u001b[J');
+ process.stdout.write(color('progress', ' ' + options.open));
+ process.stdout.write(Array(n).join(options.complete));
+ process.stdout.write(Array(i).join(options.incomplete));
+ process.stdout.write(color('progress', options.close));
+ if (options.verbose) {
+ process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
+ }
+ });
+
+ // tests are complete, output some stats
+ // and the failures if any
+ runner.on('end', function(){
+ cursor.show();
+ console.log();
+ self.epilogue();
+ });
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Progress.prototype = new F;
+Progress.prototype.constructor = Progress;
+
+
+}); // module: reporters/progress.js
+
+require.register("reporters/spec.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , cursor = Base.cursor
+ , color = Base.color;
+
+/**
+ * Expose `Spec`.
+ */
+
+exports = module.exports = Spec;
+
+/**
+ * Initialize a new `Spec` test reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function Spec(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , indents = 0
+ , n = 0;
+
+ function indent() {
+ return Array(indents).join(' ')
+ }
+
+ runner.on('start', function(){
+ console.log();
+ });
+
+ runner.on('suite', function(suite){
+ ++indents;
+ console.log(color('suite', '%s%s'), indent(), suite.title);
+ });
+
+ runner.on('suite end', function(suite){
+ --indents;
+ if (1 == indents) console.log();
+ });
+
+ runner.on('pending', function(test){
+ var fmt = indent() + color('pending', ' - %s');
+ console.log(fmt, test.title);
+ });
+
+ runner.on('pass', function(test){
+ if ('fast' == test.speed) {
+ var fmt = indent()
+ + color('checkmark', ' ' + Base.symbols.ok)
+ + color('pass', ' %s ');
+ cursor.CR();
+ console.log(fmt, test.title);
+ } else {
+ var fmt = indent()
+ + color('checkmark', ' ' + Base.symbols.ok)
+ + color('pass', ' %s ')
+ + color(test.speed, '(%dms)');
+ cursor.CR();
+ console.log(fmt, test.title, test.duration);
+ }
+ });
+
+ runner.on('fail', function(test, err){
+ cursor.CR();
+ console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
+ });
+
+ runner.on('end', self.epilogue.bind(self));
+}
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+Spec.prototype = new F;
+Spec.prototype.constructor = Spec;
+
+
+}); // module: reporters/spec.js
+
+require.register("reporters/tap.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , cursor = Base.cursor
+ , color = Base.color;
+
+/**
+ * Expose `TAP`.
+ */
+
+exports = module.exports = TAP;
+
+/**
+ * Initialize a new `TAP` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function TAP(runner) {
+ Base.call(this, runner);
+
+ var self = this
+ , stats = this.stats
+ , n = 1
+ , passes = 0
+ , failures = 0;
+
+ runner.on('start', function(){
+ var total = runner.grepTotal(runner.suite);
+ console.log('%d..%d', 1, total);
+ });
+
+ runner.on('test end', function(){
+ ++n;
+ });
+
+ runner.on('pending', function(test){
+ console.log('ok %d %s # SKIP -', n, title(test));
+ });
+
+ runner.on('pass', function(test){
+ passes++;
+ console.log('ok %d %s', n, title(test));
+ });
+
+ runner.on('fail', function(test, err){
+ failures++;
+ console.log('not ok %d %s', n, title(test));
+ if (err.stack) console.log(err.stack.replace(/^/gm, ' '));
+ });
+
+ runner.on('end', function(){
+ console.log('# tests ' + (passes + failures));
+ console.log('# pass ' + passes);
+ console.log('# fail ' + failures);
+ });
+}
+
+/**
+ * Return a TAP-safe title of `test`
+ *
+ * @param {Object} test
+ * @return {String}
+ * @api private
+ */
+
+function title(test) {
+ return test.fullTitle().replace(/#/g, '');
+}
+
+}); // module: reporters/tap.js
+
+require.register("reporters/xunit.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Base = require('./base')
+ , utils = require('../utils')
+ , fs = require('browser/fs')
+ , escape = utils.escape;
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+ , setTimeout = global.setTimeout
+ , setInterval = global.setInterval
+ , clearTimeout = global.clearTimeout
+ , clearInterval = global.clearInterval;
+
+/**
+ * Expose `XUnit`.
+ */
+
+exports = module.exports = XUnit;
+
+/**
+ * Initialize a new `XUnit` reporter.
+ *
+ * @param {Runner} runner
+ * @api public
+ */
+
+function XUnit(runner, options) {
+ Base.call(this, runner);
+ var stats = this.stats
+ , tests = []
+ , self = this;
+
+ if (options.reporterOptions && options.reporterOptions.output) {
+ if (! fs.createWriteStream) {
+ throw new Error('file output not supported in browser');
+ }
+ self.fileStream = fs.createWriteStream(options.reporterOptions.output);
+ }
+
+ runner.on('pending', function(test){
+ tests.push(test);
+ });
+
+ runner.on('pass', function(test){
+ tests.push(test);
+ });
+
+ runner.on('fail', function(test){
+ tests.push(test);
+ });
+
+ runner.on('end', function(){
+ self.write(tag('testsuite', {
+ name: 'Mocha Tests'
+ , tests: stats.tests
+ , failures: stats.failures
+ , errors: stats.failures
+ , skipped: stats.tests - stats.failures - stats.passes
+ , timestamp: (new Date).toUTCString()
+ , time: (stats.duration / 1000) || 0
+ }, false));
+
+ tests.forEach(function(t) { self.test(t); });
+ self.write('</testsuite>');
+ });
+}
+
+/**
+ * Override done to close the stream (if it's a file).
+ */
+XUnit.prototype.done = function(failures, fn) {
+ if (this.fileStream) {
+ this.fileStream.end(function() {
+ fn(failures);
+ });
+ } else {
+ fn(failures);
+ }
+};
+
+/**
+ * Inherit from `Base.prototype`.
+ */
+
+function F(){};
+F.prototype = Base.prototype;
+XUnit.prototype = new F;
+XUnit.prototype.constructor = XUnit;
+
+
+/**
+ * Write out the given line
+ */
+XUnit.prototype.write = function(line) {
+ if (this.fileStream) {
+ this.fileStream.write(line + '\n');
+ } else {
+ console.log(line);
+ }
+};
+
+/**
+ * Output tag for the given `test.`
+ */
+
+XUnit.prototype.test = function(test, ostream) {
+ var attrs = {
+ classname: test.parent.fullTitle()
+ , name: test.title
+ , time: (test.duration / 1000) || 0
+ };
+
+ if ('failed' == test.state) {
+ var err = test.err;
+ this.write(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + "\n" + err.stack))));
+ } else if (test.pending) {
+ this.write(tag('testcase', attrs, false, tag('skipped', {}, true)));
+ } else {
+ this.write(tag('testcase', attrs, true) );
+ }
+};
+
+/**
+ * HTML tag helper.
+ */
+
+function tag(name, attrs, close, content) {
+ var end = close ? '/>' : '>'
+ , pairs = []
+ , tag;
+
+ for (var key in attrs) {
+ pairs.push(key + '="' + escape(attrs[key]) + '"');
+ }
+
+ tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
+ if (content) tag += content + '</' + name + end;
+ return tag;
+}
+
+/**
+ * Return cdata escaped CDATA `str`.
+ */
+
+function cdata(str) {
+ return '<![CDATA[' + escape(str) + ']]>';
+}
+
+}); // module: reporters/xunit.js
+
+require.register("runnable.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+ , debug = require('browser/debug')('mocha:runnable')
+ , Pending = require('./pending')
+ , milliseconds = require('./ms')
+ , utils = require('./utils');
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date
+ , setTimeout = global.setTimeout
+ , setInterval = global.setInterval
+ , clearTimeout = global.clearTimeout
+ , clearInterval = global.clearInterval;
+
+/**
+ * Object#toString().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Expose `Runnable`.
+ */
+
+module.exports = Runnable;
+
+/**
+ * Initialize a new `Runnable` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Runnable(title, fn) {
+ this.title = title;
+ this.fn = fn;
+ this.async = fn && fn.length;
+ this.sync = ! this.async;
+ this._timeout = 2000;
+ this._slow = 75;
+ this._enableTimeouts = true;
+ this.timedOut = false;
+ this._trace = new Error('done() called multiple times')
+}
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+function F(){};
+F.prototype = EventEmitter.prototype;
+Runnable.prototype = new F;
+Runnable.prototype.constructor = Runnable;
+
+
+/**
+ * Set & get timeout `ms`.
+ *
+ * @param {Number|String} ms
+ * @return {Runnable|Number} ms or self
+ * @api private
+ */
+
+Runnable.prototype.timeout = function(ms){
+ if (0 == arguments.length) return this._timeout;
+ if (ms === 0) this._enableTimeouts = false;
+ if ('string' == typeof ms) ms = milliseconds(ms);
+ debug('timeout %d', ms);
+ this._timeout = ms;
+ if (this.timer) this.resetTimeout();
+ return this;
+};
+
+/**
+ * Set & get slow `ms`.
+ *
+ * @param {Number|String} ms
+ * @return {Runnable|Number} ms or self
+ * @api private
+ */
+
+Runnable.prototype.slow = function(ms){
+ if (0 === arguments.length) return this._slow;
+ if ('string' == typeof ms) ms = milliseconds(ms);
+ debug('timeout %d', ms);
+ this._slow = ms;
+ return this;
+};
+
+/**
+ * Set and & get timeout `enabled`.
+ *
+ * @param {Boolean} enabled
+ * @return {Runnable|Boolean} enabled or self
+ * @api private
+ */
+
+Runnable.prototype.enableTimeouts = function(enabled){
+ if (arguments.length === 0) return this._enableTimeouts;
+ debug('enableTimeouts %s', enabled);
+ this._enableTimeouts = enabled;
+ return this;
+};
+
+/**
+ * Halt and mark as pending.
+ *
+ * @api private
+ */
+
+Runnable.prototype.skip = function(){
+ throw new Pending();
+};
+
+/**
+ * Return the full title generated by recursively
+ * concatenating the parent's full title.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Runnable.prototype.fullTitle = function(){
+ return this.parent.fullTitle() + ' ' + this.title;
+};
+
+/**
+ * Clear the timeout.
+ *
+ * @api private
+ */
+
+Runnable.prototype.clearTimeout = function(){
+ clearTimeout(this.timer);
+};
+
+/**
+ * Inspect the runnable void of private properties.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Runnable.prototype.inspect = function(){
+ return JSON.stringify(this, function(key, val){
+ if ('_' == key[0]) return;
+ if ('parent' == key) return '#<Suite>';
+ if ('ctx' == key) return '#<Context>';
+ return val;
+ }, 2);
+};
+
+/**
+ * Reset the timeout.
+ *
+ * @api private
+ */
+
+Runnable.prototype.resetTimeout = function(){
+ var self = this;
+ var ms = this.timeout() || 1e9;
+
+ if (!this._enableTimeouts) return;
+ this.clearTimeout();
+ this.timer = setTimeout(function(){
+ if (!self._enableTimeouts) return;
+ self.callback(new Error('timeout of ' + ms + 'ms exceeded. Ensure the done() callback is being called in this test.'));
+ self.timedOut = true;
+ }, ms);
+};
+
+/**
+ * Whitelist these globals for this test run
+ *
+ * @api private
+ */
+Runnable.prototype.globals = function(arr){
+ var self = this;
+ this._allowedGlobals = arr;
+};
+
+/**
+ * Run the test and invoke `fn(err)`.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runnable.prototype.run = function(fn){
+ var self = this
+ , start = new Date
+ , ctx = this.ctx
+ , finished
+ , emitted;
+
+ // Some times the ctx exists but it is not runnable
+ if (ctx && ctx.runnable) ctx.runnable(this);
+
+ // called multiple times
+ function multiple(err) {
+ if (emitted) return;
+ emitted = true;
+ self.emit('error', err || new Error('done() called multiple times; stacktrace may be inaccurate'));
+ }
+
+ // finished
+ function done(err) {
+ var ms = self.timeout();
+ if (self.timedOut) return;
+ if (finished) return multiple(err || self._trace);
+
+ // Discard the resolution if this test has already failed asynchronously
+ if (self.state) return;
+
+ self.clearTimeout();
+ self.duration = new Date - start;
+ finished = true;
+ if (!err && self.duration > ms && self._enableTimeouts) err = new Error('timeout of ' + ms + 'ms exceeded. Ensure the done() callback is being called in this test.');
+ fn(err);
+ }
+
+ // for .resetTimeout()
+ this.callback = done;
+
+ // explicit async with `done` argument
+ if (this.async) {
+ this.resetTimeout();
+
+ try {
+ this.fn.call(ctx, function(err){
+ if (err instanceof Error || toString.call(err) === "[object Error]") return done(err);
+ if (null != err) {
+ if (Object.prototype.toString.call(err) === '[object Object]') {
+ return done(new Error('done() invoked with non-Error: ' + JSON.stringify(err)));
+ } else {
+ return done(new Error('done() invoked with non-Error: ' + err));
+ }
+ }
+ done();
+ });
+ } catch (err) {
+ done(utils.getError(err));
+ }
+ return;
+ }
+
+ if (this.asyncOnly) {
+ return done(new Error('--async-only option in use without declaring `done()`'));
+ }
+
+ // sync or promise-returning
+ try {
+ if (this.pending) {
+ done();
+ } else {
+ callFn(this.fn);
+ }
+ } catch (err) {
+ done(utils.getError(err));
+ }
+
+ function callFn(fn) {
+ var result = fn.call(ctx);
+ if (result && typeof result.then === 'function') {
+ self.resetTimeout();
+ result
+ .then(function() {
+ done()
+ },
+ function(reason) {
+ done(reason || new Error('Promise rejected with no or falsy reason'))
+ });
+ } else {
+ done();
+ }
+ }
+};
+
+}); // module: runnable.js
+
+require.register("runner.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+ , debug = require('browser/debug')('mocha:runner')
+ , Pending = require('./pending')
+ , Test = require('./test')
+ , utils = require('./utils')
+ , filter = utils.filter
+ , keys = utils.keys
+ , type = utils.type
+ , stringify = utils.stringify
+ , stackFilter = utils.stackTraceFilter();
+
+/**
+ * Non-enumerable globals.
+ */
+
+var globals = [
+ 'setTimeout',
+ 'clearTimeout',
+ 'setInterval',
+ 'clearInterval',
+ 'XMLHttpRequest',
+ 'Date',
+ 'setImmediate',
+ 'clearImmediate'
+];
+
+/**
+ * Expose `Runner`.
+ */
+
+module.exports = Runner;
+
+/**
+ * Initialize a `Runner` for the given `suite`.
+ *
+ * Events:
+ *
+ * - `start` execution started
+ * - `end` execution complete
+ * - `suite` (suite) test suite execution started
+ * - `suite end` (suite) all tests (and sub-suites) have finished
+ * - `test` (test) test execution started
+ * - `test end` (test) test completed
+ * - `hook` (hook) hook execution started
+ * - `hook end` (hook) hook complete
+ * - `pass` (test) test passed
+ * - `fail` (test, err) test failed
+ * - `pending` (test) test pending
+ *
+ * @param {Suite} suite Root suite
+ * @param {boolean} [delay] Whether or not to delay execution of root suite
+ * until ready.
+ * @api public
+ */
+
+function Runner(suite, delay) {
+ var self = this;
+ this._globals = [];
+ this._abort = false;
+ this._delay = delay;
+ this.suite = suite;
+ this.total = suite.total();
+ this.failures = 0;
+ this.on('test end', function(test){ self.checkGlobals(test); });
+ this.on('hook end', function(hook){ self.checkGlobals(hook); });
+ this.grep(/.*/);
+ this.globals(this.globalProps().concat(extraGlobals()));
+}
+
+/**
+ * Wrapper for setImmediate, process.nextTick, or browser polyfill.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.immediately = global.setImmediate || process.nextTick;
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+function F(){};
+F.prototype = EventEmitter.prototype;
+Runner.prototype = new F;
+Runner.prototype.constructor = Runner;
+
+
+/**
+ * Run tests with full titles matching `re`. Updates runner.total
+ * with number of tests matched.
+ *
+ * @param {RegExp} re
+ * @param {Boolean} invert
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.grep = function(re, invert){
+ debug('grep %s', re);
+ this._grep = re;
+ this._invert = invert;
+ this.total = this.grepTotal(this.suite);
+ return this;
+};
+
+/**
+ * Returns the number of tests matching the grep search for the
+ * given suite.
+ *
+ * @param {Suite} suite
+ * @return {Number}
+ * @api public
+ */
+
+Runner.prototype.grepTotal = function(suite) {
+ var self = this;
+ var total = 0;
+
+ suite.eachTest(function(test){
+ var match = self._grep.test(test.fullTitle());
+ if (self._invert) match = !match;
+ if (match) total++;
+ });
+
+ return total;
+};
+
+/**
+ * Return a list of global properties.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+Runner.prototype.globalProps = function() {
+ var props = utils.keys(global);
+
+ // non-enumerables
+ for (var i = 0; i < globals.length; ++i) {
+ if (~utils.indexOf(props, globals[i])) continue;
+ props.push(globals[i]);
+ }
+
+ return props;
+};
+
+/**
+ * Allow the given `arr` of globals.
+ *
+ * @param {Array} arr
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.globals = function(arr){
+ if (0 == arguments.length) return this._globals;
+ debug('globals %j', arr);
+ this._globals = this._globals.concat(arr);
+ return this;
+};
+
+/**
+ * Check for global variable leaks.
+ *
+ * @api private
+ */
+
+Runner.prototype.checkGlobals = function(test){
+ if (this.ignoreLeaks) return;
+ var ok = this._globals;
+
+ var globals = this.globalProps();
+ var leaks;
+
+ if (test) {
+ ok = ok.concat(test._allowedGlobals || []);
+ }
+
+ if(this.prevGlobalsLength == globals.length) return;
+ this.prevGlobalsLength = globals.length;
+
+ leaks = filterLeaks(ok, globals);
+ this._globals = this._globals.concat(leaks);
+
+ if (leaks.length > 1) {
+ this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
+ } else if (leaks.length) {
+ this.fail(test, new Error('global leak detected: ' + leaks[0]));
+ }
+};
+
+/**
+ * Fail the given `test`.
+ *
+ * @param {Test} test
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.fail = function(test, err) {
+ ++this.failures;
+ test.state = 'failed';
+
+ if (!(err instanceof Error)) {
+ err = new Error('the ' + type(err) + ' ' + stringify(err) + ' was thrown, throw an Error :)');
+ }
+
+ err.stack = this.fullStackTrace
+ ? err.stack
+ : stackFilter(err.stack);
+
+ this.emit('fail', test, err);
+};
+
+/**
+ * Fail the given `hook` with `err`.
+ *
+ * Hook failures work in the following pattern:
+ * - If bail, then exit
+ * - Failed `before` hook skips all tests in a suite and subsuites,
+ * but jumps to corresponding `after` hook
+ * - Failed `before each` hook skips remaining tests in a
+ * suite and jumps to corresponding `after each` hook,
+ * which is run only once
+ * - Failed `after` hook does not alter
+ * execution order
+ * - Failed `after each` hook skips remaining tests in a
+ * suite and subsuites, but executes other `after each`
+ * hooks
+ *
+ * @param {Hook} hook
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.failHook = function(hook, err){
+ this.fail(hook, err);
+ if (this.suite.bail()) {
+ this.emit('end');
+ }
+};
+
+/**
+ * Run hook `name` callbacks and then invoke `fn()`.
+ *
+ * @param {String} name
+ * @param {Function} function
+ * @api private
+ */
+
+Runner.prototype.hook = function(name, fn){
+ var suite = this.suite
+ , hooks = suite['_' + name]
+ , self = this
+ , timer;
+
+ function next(i) {
+ var hook = hooks[i];
+ if (!hook) return fn();
+ self.currentRunnable = hook;
+
+ hook.ctx.currentTest = self.test;
+
+ self.emit('hook', hook);
+
+ hook.on('error', function(err){
+ self.failHook(hook, err);
+ });
+
+ hook.run(function(err){
+ hook.removeAllListeners('error');
+ var testError = hook.error();
+ if (testError) self.fail(self.test, testError);
+ if (err) {
+ if (err instanceof Pending) {
+ suite.pending = true;
+ } else {
+ self.failHook(hook, err);
+
+ // stop executing hooks, notify callee of hook err
+ return fn(err);
+ }
+ }
+ self.emit('hook end', hook);
+ delete hook.ctx.currentTest;
+ next(++i);
+ });
+ }
+
+ Runner.immediately(function(){
+ next(0);
+ });
+};
+
+/**
+ * Run hook `name` for the given array of `suites`
+ * in order, and callback `fn(err, errSuite)`.
+ *
+ * @param {String} name
+ * @param {Array} suites
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hooks = function(name, suites, fn){
+ var self = this
+ , orig = this.suite;
+
+ function next(suite) {
+ self.suite = suite;
+
+ if (!suite) {
+ self.suite = orig;
+ return fn();
+ }
+
+ self.hook(name, function(err){
+ if (err) {
+ var errSuite = self.suite;
+ self.suite = orig;
+ return fn(err, errSuite);
+ }
+
+ next(suites.pop());
+ });
+ }
+
+ next(suites.pop());
+};
+
+/**
+ * Run hooks from the top level down.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hookUp = function(name, fn){
+ var suites = [this.suite].concat(this.parents()).reverse();
+ this.hooks(name, suites, fn);
+};
+
+/**
+ * Run hooks from the bottom up.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.hookDown = function(name, fn){
+ var suites = [this.suite].concat(this.parents());
+ this.hooks(name, suites, fn);
+};
+
+/**
+ * Return an array of parent Suites from
+ * closest to furthest.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+Runner.prototype.parents = function(){
+ var suite = this.suite
+ , suites = [];
+ while (suite = suite.parent) suites.push(suite);
+ return suites;
+};
+
+/**
+ * Run the current test and callback `fn(err)`.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runTest = function(fn){
+ var test = this.test
+ , self = this;
+
+ if (this.asyncOnly) test.asyncOnly = true;
+
+ try {
+ test.on('error', function(err){
+ self.fail(test, err);
+ });
+ test.run(fn);
+ } catch (err) {
+ fn(err);
+ }
+};
+
+/**
+ * Run tests in the given `suite` and invoke
+ * the callback `fn()` when complete.
+ *
+ * @param {Suite} suite
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runTests = function(suite, fn){
+ var self = this
+ , tests = suite.tests.slice()
+ , test;
+
+
+ function hookErr(err, errSuite, after) {
+ // before/after Each hook for errSuite failed:
+ var orig = self.suite;
+
+ // for failed 'after each' hook start from errSuite parent,
+ // otherwise start from errSuite itself
+ self.suite = after ? errSuite.parent : errSuite;
+
+ if (self.suite) {
+ // call hookUp afterEach
+ self.hookUp('afterEach', function(err2, errSuite2) {
+ self.suite = orig;
+ // some hooks may fail even now
+ if (err2) return hookErr(err2, errSuite2, true);
+ // report error suite
+ fn(errSuite);
+ });
+ } else {
+ // there is no need calling other 'after each' hooks
+ self.suite = orig;
+ fn(errSuite);
+ }
+ }
+
+ function next(err, errSuite) {
+ // if we bail after first err
+ if (self.failures && suite._bail) return fn();
+
+ if (self._abort) return fn();
+
+ if (err) return hookErr(err, errSuite, true);
+
+ // next test
+ test = tests.shift();
+
+ // all done
+ if (!test) return fn();
+
+ // grep
+ var match = self._grep.test(test.fullTitle());
+ if (self._invert) match = !match;
+ if (!match) return next();
+
+ // pending
+ if (test.pending) {
+ self.emit('pending', test);
+ self.emit('test end', test);
+ return next();
+ }
+
+ // execute test and hook(s)
+ self.emit('test', self.test = test);
+ self.hookDown('beforeEach', function(err, errSuite){
+
+ if (suite.pending) {
+ self.emit('pending', test);
+ self.emit('test end', test);
+ return next();
+ }
+ if (err) return hookErr(err, errSuite, false);
+
+ self.currentRunnable = self.test;
+ self.runTest(function(err){
+ test = self.test;
+
+ if (err) {
+ if (err instanceof Pending) {
+ self.emit('pending', test);
+ } else {
+ self.fail(test, err);
+ }
+ self.emit('test end', test);
+
+ if (err instanceof Pending) {
+ return next();
+ }
+
+ return self.hookUp('afterEach', next);
+ }
+
+ test.state = 'passed';
+ self.emit('pass', test);
+ self.emit('test end', test);
+ self.hookUp('afterEach', next);
+ });
+ });
+ }
+
+ this.next = next;
+ next();
+};
+
+/**
+ * Run the given `suite` and invoke the
+ * callback `fn()` when complete.
+ *
+ * @param {Suite} suite
+ * @param {Function} fn
+ * @api private
+ */
+
+Runner.prototype.runSuite = function(suite, fn){
+ var total = this.grepTotal(suite)
+ , self = this
+ , i = 0;
+
+ debug('run suite %s', suite.fullTitle());
+
+ if (!total) return fn();
+
+ this.emit('suite', this.suite = suite);
+
+ function next(errSuite) {
+ if (errSuite) {
+ // current suite failed on a hook from errSuite
+ if (errSuite == suite) {
+ // if errSuite is current suite
+ // continue to the next sibling suite
+ return done();
+ } else {
+ // errSuite is among the parents of current suite
+ // stop execution of errSuite and all sub-suites
+ return done(errSuite);
+ }
+ }
+
+ if (self._abort) return done();
+
+ var curr = suite.suites[i++];
+ if (!curr) return done();
+ self.runSuite(curr, next);
+ }
+
+ function done(errSuite) {
+ self.suite = suite;
+ self.hook('afterAll', function(){
+ self.emit('suite end', suite);
+ fn(errSuite);
+ });
+ }
+
+ this.hook('beforeAll', function(err){
+ if (err) return done();
+ self.runTests(suite, next);
+ });
+};
+
+/**
+ * Handle uncaught exceptions.
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+Runner.prototype.uncaught = function(err){
+ if (err) {
+ debug('uncaught exception %s', err !== function () {
+ return this;
+ }.call(err) ? err : ( err.message || err ));
+ } else {
+ debug('uncaught undefined exception');
+ err = utils.undefinedError();
+ }
+ err.uncaught = true;
+
+ var runnable = this.currentRunnable;
+ if (!runnable) return;
+
+ runnable.clearTimeout();
+
+ // Ignore errors if complete
+ if (runnable.state) return;
+ this.fail(runnable, err);
+
+ // recover from test
+ if ('test' == runnable.type) {
+ this.emit('test end', runnable);
+ this.hookUp('afterEach', this.next);
+ return;
+ }
+
+ // bail on hooks
+ this.emit('end');
+};
+
+/**
+ * Run the root suite and invoke `fn(failures)`
+ * on completion.
+ *
+ * @param {Function} fn
+ * @return {Runner} for chaining
+ * @api public
+ */
+
+Runner.prototype.run = function(fn){
+ var self = this,
+ rootSuite = this.suite;
+
+ fn = fn || function(){};
+
+ function uncaught(err){
+ self.uncaught(err);
+ }
+
+ function start() {
+ self.emit('start');
+ self.runSuite(rootSuite, function(){
+ debug('finished running');
+ self.emit('end');
+ });
+ }
+
+ debug('start');
+
+ // callback
+ this.on('end', function(){
+ debug('end');
+ process.removeListener('uncaughtException', uncaught);
+ fn(self.failures);
+ });
+
+ // uncaught exception
+ process.on('uncaughtException', uncaught);
+
+ if (this._delay) {
+ // for reporters, I guess.
+ // might be nice to debounce some dots while we wait.
+ this.emit('waiting', rootSuite);
+ rootSuite.once('run', start);
+ }
+ else {
+ start();
+ }
+
+ return this;
+};
+
+/**
+ * Cleanly abort execution
+ *
+ * @return {Runner} for chaining
+ * @api public
+ */
+Runner.prototype.abort = function(){
+ debug('aborting');
+ this._abort = true;
+};
+
+/**
+ * Filter leaks with the given globals flagged as `ok`.
+ *
+ * @param {Array} ok
+ * @param {Array} globals
+ * @return {Array}
+ * @api private
+ */
+
+function filterLeaks(ok, globals) {
+ return filter(globals, function(key){
+ // Firefox and Chrome exposes iframes as index inside the window object
+ if (/^d+/.test(key)) return false;
+
+ // in firefox
+ // if runner runs in an iframe, this iframe's window.getInterface method not init at first
+ // it is assigned in some seconds
+ if (global.navigator && /^getInterface/.test(key)) return false;
+
+ // an iframe could be approached by window[iframeIndex]
+ // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak
+ if (global.navigator && /^\d+/.test(key)) return false;
+
+ // Opera and IE expose global variables for HTML element IDs (issue #243)
+ if (/^mocha-/.test(key)) return false;
+
+ var matched = filter(ok, function(ok){
+ if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
+ return key == ok;
+ });
+ return matched.length == 0 && (!global.navigator || 'onerror' !== key);
+ });
+}
+
+/**
+ * Array of globals dependent on the environment.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+function extraGlobals() {
+ if (typeof(process) === 'object' &&
+ typeof(process.version) === 'string') {
+
+ var nodeVersion = process.version.split('.').reduce(function(a, v) {
+ return a << 8 | v;
+ });
+
+ // 'errno' was renamed to process._errno in v0.9.11.
+
+ if (nodeVersion < 0x00090B) {
+ return ['errno'];
+ }
+ }
+
+ return [];
+}
+
+}); // module: runner.js
+
+require.register("suite.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('browser/events').EventEmitter
+ , debug = require('browser/debug')('mocha:suite')
+ , milliseconds = require('./ms')
+ , utils = require('./utils')
+ , Hook = require('./hook');
+
+/**
+ * Expose `Suite`.
+ */
+
+exports = module.exports = Suite;
+
+/**
+ * Create a new `Suite` with the given `title`
+ * and parent `Suite`. When a suite with the
+ * same title is already present, that suite
+ * is returned to provide nicer reporter
+ * and more flexible meta-testing.
+ *
+ * @param {Suite} parent
+ * @param {String} title
+ * @return {Suite}
+ * @api public
+ */
+
+exports.create = function(parent, title){
+ var suite = new Suite(title, parent.ctx);
+ suite.parent = parent;
+ if (parent.pending) suite.pending = true;
+ title = suite.fullTitle();
+ parent.addSuite(suite);
+ return suite;
+};
+
+/**
+ * Initialize a new `Suite` with the given
+ * `title` and `ctx`.
+ *
+ * @param {String} title
+ * @param {Context} ctx
+ * @api private
+ */
+
+function Suite(title, parentContext) {
+ this.title = title;
+ var context = function() {};
+ context.prototype = parentContext;
+ this.ctx = new context();
+ this.suites = [];
+ this.tests = [];
+ this.pending = false;
+ this._beforeEach = [];
+ this._beforeAll = [];
+ this._afterEach = [];
+ this._afterAll = [];
+ this.root = !title;
+ this._timeout = 2000;
+ this._enableTimeouts = true;
+ this._slow = 75;
+ this._bail = false;
+ this.delayed = false;
+}
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+function F(){};
+F.prototype = EventEmitter.prototype;
+Suite.prototype = new F;
+Suite.prototype.constructor = Suite;
+
+
+/**
+ * Return a clone of this `Suite`.
+ *
+ * @return {Suite}
+ * @api private
+ */
+
+Suite.prototype.clone = function(){
+ var suite = new Suite(this.title);
+ debug('clone');
+ suite.ctx = this.ctx;
+ suite.timeout(this.timeout());
+ suite.enableTimeouts(this.enableTimeouts());
+ suite.slow(this.slow());
+ suite.bail(this.bail());
+ return suite;
+};
+
+/**
+ * Set timeout `ms` or short-hand such as "2s".
+ *
+ * @param {Number|String} ms
+ * @return {Suite|Number} for chaining
+ * @api private
+ */
+
+Suite.prototype.timeout = function(ms){
+ if (0 == arguments.length) return this._timeout;
+ if (ms.toString() === '0') this._enableTimeouts = false;
+ if ('string' == typeof ms) ms = milliseconds(ms);
+ debug('timeout %d', ms);
+ this._timeout = parseInt(ms, 10);
+ return this;
+};
+
+/**
+ * Set timeout `enabled`.
+ *
+ * @param {Boolean} enabled
+ * @return {Suite|Boolean} self or enabled
+ * @api private
+ */
+
+Suite.prototype.enableTimeouts = function(enabled){
+ if (arguments.length === 0) return this._enableTimeouts;
+ debug('enableTimeouts %s', enabled);
+ this._enableTimeouts = enabled;
+ return this;
+};
+
+/**
+ * Set slow `ms` or short-hand such as "2s".
+ *
+ * @param {Number|String} ms
+ * @return {Suite|Number} for chaining
+ * @api private
+ */
+
+Suite.prototype.slow = function(ms){
+ if (0 === arguments.length) return this._slow;
+ if ('string' == typeof ms) ms = milliseconds(ms);
+ debug('slow %d', ms);
+ this._slow = ms;
+ return this;
+};
+
+/**
+ * Sets whether to bail after first error.
+ *
+ * @param {Boolean} bail
+ * @return {Suite|Number} for chaining
+ * @api private
+ */
+
+Suite.prototype.bail = function(bail){
+ if (0 == arguments.length) return this._bail;
+ debug('bail %s', bail);
+ this._bail = bail;
+ return this;
+};
+
+/**
+ * Run `fn(test[, done])` before running tests.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.beforeAll = function(title, fn){
+ if (this.pending) return this;
+ if ('function' === typeof title) {
+ fn = title;
+ title = fn.name;
+ }
+ title = '"before all" hook' + (title ? ': ' + title : '');
+
+ var hook = new Hook(title, fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ hook.enableTimeouts(this.enableTimeouts());
+ hook.slow(this.slow());
+ hook.ctx = this.ctx;
+ this._beforeAll.push(hook);
+ this.emit('beforeAll', hook);
+ return this;
+};
+
+/**
+ * Run `fn(test[, done])` after running tests.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.afterAll = function(title, fn){
+ if (this.pending) return this;
+ if ('function' === typeof title) {
+ fn = title;
+ title = fn.name;
+ }
+ title = '"after all" hook' + (title ? ': ' + title : '');
+
+ var hook = new Hook(title, fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ hook.enableTimeouts(this.enableTimeouts());
+ hook.slow(this.slow());
+ hook.ctx = this.ctx;
+ this._afterAll.push(hook);
+ this.emit('afterAll', hook);
+ return this;
+};
+
+/**
+ * Run `fn(test[, done])` before each test case.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.beforeEach = function(title, fn){
+ if (this.pending) return this;
+ if ('function' === typeof title) {
+ fn = title;
+ title = fn.name;
+ }
+ title = '"before each" hook' + (title ? ': ' + title : '');
+
+ var hook = new Hook(title, fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ hook.enableTimeouts(this.enableTimeouts());
+ hook.slow(this.slow());
+ hook.ctx = this.ctx;
+ this._beforeEach.push(hook);
+ this.emit('beforeEach', hook);
+ return this;
+};
+
+/**
+ * Run `fn(test[, done])` after each test case.
+ *
+ * @param {Function} fn
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.afterEach = function(title, fn){
+ if (this.pending) return this;
+ if ('function' === typeof title) {
+ fn = title;
+ title = fn.name;
+ }
+ title = '"after each" hook' + (title ? ': ' + title : '');
+
+ var hook = new Hook(title, fn);
+ hook.parent = this;
+ hook.timeout(this.timeout());
+ hook.enableTimeouts(this.enableTimeouts());
+ hook.slow(this.slow());
+ hook.ctx = this.ctx;
+ this._afterEach.push(hook);
+ this.emit('afterEach', hook);
+ return this;
+};
+
+/**
+ * Add a test `suite`.
+ *
+ * @param {Suite} suite
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.addSuite = function(suite){
+ suite.parent = this;
+ suite.timeout(this.timeout());
+ suite.enableTimeouts(this.enableTimeouts());
+ suite.slow(this.slow());
+ suite.bail(this.bail());
+ this.suites.push(suite);
+ this.emit('suite', suite);
+ return this;
+};
+
+/**
+ * Add a `test` to this suite.
+ *
+ * @param {Test} test
+ * @return {Suite} for chaining
+ * @api private
+ */
+
+Suite.prototype.addTest = function(test){
+ test.parent = this;
+ test.timeout(this.timeout());
+ test.enableTimeouts(this.enableTimeouts());
+ test.slow(this.slow());
+ test.ctx = this.ctx;
+ this.tests.push(test);
+ this.emit('test', test);
+ return this;
+};
+
+/**
+ * Return the full title generated by recursively
+ * concatenating the parent's full title.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Suite.prototype.fullTitle = function(){
+ if (this.parent) {
+ var full = this.parent.fullTitle();
+ if (full) return full + ' ' + this.title;
+ }
+ return this.title;
+};
+
+/**
+ * Return the total number of tests.
+ *
+ * @return {Number}
+ * @api public
+ */
+
+Suite.prototype.total = function(){
+ return utils.reduce(this.suites, function(sum, suite){
+ return sum + suite.total();
+ }, 0) + this.tests.length;
+};
+
+/**
+ * Iterates through each suite recursively to find
+ * all tests. Applies a function in the format
+ * `fn(test)`.
+ *
+ * @param {Function} fn
+ * @return {Suite}
+ * @api private
+ */
+
+Suite.prototype.eachTest = function(fn){
+ utils.forEach(this.tests, fn);
+ utils.forEach(this.suites, function(suite){
+ suite.eachTest(fn);
+ });
+ return this;
+};
+
+/**
+ * This will run the root suite if we happen to be running in delayed mode.
+ */
+Suite.prototype.run = function run() {
+ if (this.root) {
+ this.emit('run');
+ }
+};
+
+}); // module: suite.js
+
+require.register("test.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var Runnable = require('./runnable');
+
+/**
+ * Expose `Test`.
+ */
+
+module.exports = Test;
+
+/**
+ * Initialize a new `Test` with the given `title` and callback `fn`.
+ *
+ * @param {String} title
+ * @param {Function} fn
+ * @api private
+ */
+
+function Test(title, fn) {
+ Runnable.call(this, title, fn);
+ this.pending = !fn;
+ this.type = 'test';
+}
+
+/**
+ * Inherit from `Runnable.prototype`.
+ */
+
+function F(){};
+F.prototype = Runnable.prototype;
+Test.prototype = new F;
+Test.prototype.constructor = Test;
+
+
+}); // module: test.js
+
+require.register("utils.js", function(module, exports, require){
+/**
+ * Module dependencies.
+ */
+
+var fs = require('browser/fs')
+ , path = require('browser/path')
+ , basename = path.basename
+ , exists = fs.existsSync || path.existsSync
+ , glob = require('browser/glob')
+ , join = path.join
+ , debug = require('browser/debug')('mocha:watch');
+
+/**
+ * Ignored directories.
+ */
+
+var ignore = ['node_modules', '.git'];
+
+/**
+ * Escape special characters in the given string of html.
+ *
+ * @param {String} html
+ * @return {String}
+ * @api private
+ */
+
+exports.escape = function(html){
+ return String(html)
+ .replace(/&/g, '&amp;')
+ .replace(/"/g, '&quot;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;');
+};
+
+/**
+ * Array#forEach (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} scope
+ * @api private
+ */
+
+exports.forEach = function(arr, fn, scope){
+ for (var i = 0, l = arr.length; i < l; i++)
+ fn.call(scope, arr[i], i);
+};
+
+/**
+ * Array#map (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} scope
+ * @api private
+ */
+
+exports.map = function(arr, fn, scope){
+ var result = [];
+ for (var i = 0, l = arr.length; i < l; i++)
+ result.push(fn.call(scope, arr[i], i, arr));
+ return result;
+};
+
+/**
+ * Array#indexOf (<=IE8)
+ *
+ * @parma {Array} arr
+ * @param {Object} obj to find index of
+ * @param {Number} start
+ * @api private
+ */
+
+exports.indexOf = function(arr, obj, start){
+ for (var i = start || 0, l = arr.length; i < l; i++) {
+ if (arr[i] === obj)
+ return i;
+ }
+ return -1;
+};
+
+/**
+ * Array#reduce (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @param {Object} initial value
+ * @api private
+ */
+
+exports.reduce = function(arr, fn, val){
+ var rval = val;
+
+ for (var i = 0, l = arr.length; i < l; i++) {
+ rval = fn(rval, arr[i], i, arr);
+ }
+
+ return rval;
+};
+
+/**
+ * Array#filter (<=IE8)
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ * @api private
+ */
+
+exports.filter = function(arr, fn){
+ var ret = [];
+
+ for (var i = 0, l = arr.length; i < l; i++) {
+ var val = arr[i];
+ if (fn(val, i, arr)) ret.push(val);
+ }
+
+ return ret;
+};
+
+/**
+ * Object.keys (<=IE8)
+ *
+ * @param {Object} obj
+ * @return {Array} keys
+ * @api private
+ */
+
+exports.keys = Object.keys || function(obj) {
+ var keys = []
+ , has = Object.prototype.hasOwnProperty; // for `window` on <=IE8
+
+ for (var key in obj) {
+ if (has.call(obj, key)) {
+ keys.push(key);
+ }
+ }
+
+ return keys;
+};
+
+/**
+ * Watch the given `files` for changes
+ * and invoke `fn(file)` on modification.
+ *
+ * @param {Array} files
+ * @param {Function} fn
+ * @api private
+ */
+
+exports.watch = function(files, fn){
+ var options = { interval: 100 };
+ files.forEach(function(file){
+ debug('file %s', file);
+ fs.watchFile(file, options, function(curr, prev){
+ if (prev.mtime < curr.mtime) fn(file);
+ });
+ });
+};
+
+/**
+ * Array.isArray (<=IE8)
+ *
+ * @param {Object} obj
+ * @return {Boolean}
+ * @api private
+ */
+var isArray = Array.isArray || function (obj) {
+ return '[object Array]' == {}.toString.call(obj);
+};
+
+/**
+ * @description
+ * Buffer.prototype.toJSON polyfill
+ * @type {Function}
+ */
+if(typeof Buffer !== 'undefined' && Buffer.prototype) {
+ Buffer.prototype.toJSON = Buffer.prototype.toJSON || function () {
+ return Array.prototype.slice.call(this, 0);
+ };
+}
+
+/**
+ * Ignored files.
+ */
+
+function ignored(path){
+ return !~ignore.indexOf(path);
+}
+
+/**
+ * Lookup files in the given `dir`.
+ *
+ * @return {Array}
+ * @api private
+ */
+
+exports.files = function(dir, ext, ret){
+ ret = ret || [];
+ ext = ext || ['js'];
+
+ var re = new RegExp('\\.(' + ext.join('|') + ')$');
+
+ fs.readdirSync(dir)
+ .filter(ignored)
+ .forEach(function(path){
+ path = join(dir, path);
+ if (fs.statSync(path).isDirectory()) {
+ exports.files(path, ext, ret);
+ } else if (path.match(re)) {
+ ret.push(path);
+ }
+ });
+
+ return ret;
+};
+
+/**
+ * Compute a slug from the given `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.slug = function(str){
+ return str
+ .toLowerCase()
+ .replace(/ +/g, '-')
+ .replace(/[^-\w]/g, '');
+};
+
+/**
+ * Strip the function definition from `str`,
+ * and re-indent for pre whitespace.
+ */
+
+exports.clean = function(str) {
+ str = str
+ .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '')
+ .replace(/^function *\(.*\) *{|\(.*\) *=> *{?/, '')
+ .replace(/\s+\}$/, '');
+
+ var spaces = str.match(/^\n?( *)/)[1].length
+ , tabs = str.match(/^\n?(\t*)/)[1].length
+ , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm');
+
+ str = str.replace(re, '');
+
+ return exports.trim(str);
+};
+
+/**
+ * Trim the given `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.trim = function(str){
+ return str.replace(/^\s+|\s+$/g, '');
+};
+
+/**
+ * Parse the given `qs`.
+ *
+ * @param {String} qs
+ * @return {Object}
+ * @api private
+ */
+
+exports.parseQuery = function(qs){
+ return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){
+ var i = pair.indexOf('=')
+ , key = pair.slice(0, i)
+ , val = pair.slice(++i);
+
+ obj[key] = decodeURIComponent(val);
+ return obj;
+ }, {});
+};
+
+/**
+ * Highlight the given string of `js`.
+ *
+ * @param {String} js
+ * @return {String}
+ * @api private
+ */
+
+function highlight(js) {
+ return js
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;')
+ .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
+ .replace(/('.*?')/gm, '<span class="string">$1</span>')
+ .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
+ .replace(/(\d+)/gm, '<span class="number">$1</span>')
+ .replace(/\bnew[ \t]+(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
+ .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
+}
+
+/**
+ * Highlight the contents of tag `name`.
+ *
+ * @param {String} name
+ * @api private
+ */
+
+exports.highlightTags = function(name) {
+ var code = document.getElementById('mocha').getElementsByTagName(name);
+ for (var i = 0, len = code.length; i < len; ++i) {
+ code[i].innerHTML = highlight(code[i].innerHTML);
+ }
+};
+
+/**
+ * If a value could have properties, and has none, this function is called, which returns
+ * a string representation of the empty value.
+ *
+ * Functions w/ no properties return `'[Function]'`
+ * Arrays w/ length === 0 return `'[]'`
+ * Objects w/ no properties return `'{}'`
+ * All else: return result of `value.toString()`
+ *
+ * @param {*} value Value to inspect
+ * @param {string} [type] The type of the value, if known.
+ * @returns {string}
+ */
+var emptyRepresentation = function emptyRepresentation(value, type) {
+ type = type || exports.type(value);
+
+ switch(type) {
+ case 'function':
+ return '[Function]';
+ case 'object':
+ return '{}';
+ case 'array':
+ return '[]';
+ default:
+ return value.toString();
+ }
+};
+
+/**
+ * Takes some variable and asks `{}.toString()` what it thinks it is.
+ * @param {*} value Anything
+ * @example
+ * type({}) // 'object'
+ * type([]) // 'array'
+ * type(1) // 'number'
+ * type(false) // 'boolean'
+ * type(Infinity) // 'number'
+ * type(null) // 'null'
+ * type(new Date()) // 'date'
+ * type(/foo/) // 'regexp'
+ * type('type') // 'string'
+ * type(global) // 'global'
+ * @api private
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
+ * @returns {string}
+ */
+exports.type = function type(value) {
+ if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
+ return 'buffer';
+ }
+ return Object.prototype.toString.call(value)
+ .replace(/^\[.+\s(.+?)\]$/, '$1')
+ .toLowerCase();
+};
+
+/**
+ * @summary Stringify `value`.
+ * @description Different behavior depending on type of value.
+ * - If `value` is undefined or null, return `'[undefined]'` or `'[null]'`, respectively.
+ * - If `value` is not an object, function or array, return result of `value.toString()` wrapped in double-quotes.
+ * - If `value` is an *empty* object, function, or array, return result of function
+ * {@link emptyRepresentation}.
+ * - If `value` has properties, call {@link exports.canonicalize} on it, then return result of
+ * JSON.stringify().
+ *
+ * @see exports.type
+ * @param {*} value
+ * @return {string}
+ * @api private
+ */
+
+exports.stringify = function(value) {
+ var type = exports.type(value);
+
+ if (!~exports.indexOf(['object', 'array', 'function'], type)) {
+ if(type != 'buffer') {
+ return jsonStringify(value);
+ }
+ var json = value.toJSON();
+ // Based on the toJSON result
+ return jsonStringify(json.data && json.type ? json.data : json, 2)
+ .replace(/,(\n|$)/g, '$1');
+ }
+
+ for (var prop in value) {
+ if (Object.prototype.hasOwnProperty.call(value, prop)) {
+ return jsonStringify(exports.canonicalize(value), 2).replace(/,(\n|$)/g, '$1');
+ }
+ }
+
+ return emptyRepresentation(value, type);
+};
+
+/**
+ * @description
+ * like JSON.stringify but more sense.
+ * @param {Object} object
+ * @param {Number=} spaces
+ * @param {number=} depth
+ * @returns {*}
+ * @private
+ */
+function jsonStringify(object, spaces, depth) {
+ if(typeof spaces == 'undefined') return _stringify(object); // primitive types
+
+ depth = depth || 1;
+ var space = spaces * depth
+ , str = isArray(object) ? '[' : '{'
+ , end = isArray(object) ? ']' : '}'
+ , length = object.length || exports.keys(object).length
+ , repeat = function(s, n) { return new Array(n).join(s); }; // `.repeat()` polyfill
+
+ function _stringify(val) {
+ switch (exports.type(val)) {
+ case 'null':
+ case 'undefined':
+ val = '[' + val + ']';
+ break;
+ case 'array':
+ case 'object':
+ val = jsonStringify(val, spaces, depth + 1);
+ break;
+ case 'boolean':
+ case 'regexp':
+ case 'number':
+ val = val === 0 && (1/val) === -Infinity // `-0`
+ ? '-0'
+ : val.toString();
+ break;
+ case 'date':
+ val = '[Date: ' + val.toISOString() + ']';
+ break;
+ case 'buffer':
+ var json = val.toJSON();
+ // Based on the toJSON result
+ json = json.data && json.type ? json.data : json;
+ val = '[Buffer: ' + jsonStringify(json, 2, depth + 1) + ']';
+ break;
+ default:
+ val = (val == '[Function]' || val == '[Circular]')
+ ? val
+ : '"' + val + '"'; //string
+ }
+ return val;
+ }
+
+ for(var i in object) {
+ if(!object.hasOwnProperty(i)) continue; // not my business
+ --length;
+ str += '\n ' + repeat(' ', space)
+ + (isArray(object) ? '' : '"' + i + '": ') // key
+ + _stringify(object[i]) // value
+ + (length ? ',' : ''); // comma
+ }
+
+ return str + (str.length != 1 // [], {}
+ ? '\n' + repeat(' ', --space) + end
+ : end);
+}
+
+/**
+ * Return if obj is a Buffer
+ * @param {Object} arg
+ * @return {Boolean}
+ * @api private
+ */
+exports.isBuffer = function (arg) {
+ return typeof Buffer !== 'undefined' && Buffer.isBuffer(arg);
+};
+
+/**
+ * @summary Return a new Thing that has the keys in sorted order. Recursive.
+ * @description If the Thing...
+ * - has already been seen, return string `'[Circular]'`
+ * - is `undefined`, return string `'[undefined]'`
+ * - is `null`, return value `null`
+ * - is some other primitive, return the value
+ * - is not a primitive or an `Array`, `Object`, or `Function`, return the value of the Thing's `toString()` method
+ * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again.
+ * - is an empty `Array`, `Object`, or `Function`, return the result of calling `emptyRepresentation()`
+ *
+ * @param {*} value Thing to inspect. May or may not have properties.
+ * @param {Array} [stack=[]] Stack of seen values
+ * @return {(Object|Array|Function|string|undefined)}
+ * @see {@link exports.stringify}
+ * @api private
+ */
+
+exports.canonicalize = function(value, stack) {
+ var canonicalizedObj,
+ type = exports.type(value),
+ prop,
+ withStack = function withStack(value, fn) {
+ stack.push(value);
+ fn();
+ stack.pop();
+ };
+
+ stack = stack || [];
+
+ if (exports.indexOf(stack, value) !== -1) {
+ return '[Circular]';
+ }
+
+ switch(type) {
+ case 'undefined':
+ case 'buffer':
+ case 'null':
+ canonicalizedObj = value;
+ break;
+ case 'array':
+ withStack(value, function () {
+ canonicalizedObj = exports.map(value, function (item) {
+ return exports.canonicalize(item, stack);
+ });
+ });
+ break;
+ case 'function':
+ for (prop in value) {
+ canonicalizedObj = {};
+ break;
+ }
+ if (!canonicalizedObj) {
+ canonicalizedObj = emptyRepresentation(value, type);
+ break;
+ }
+ /* falls through */
+ case 'object':
+ canonicalizedObj = canonicalizedObj || {};
+ withStack(value, function () {
+ exports.forEach(exports.keys(value).sort(), function (key) {
+ canonicalizedObj[key] = exports.canonicalize(value[key], stack);
+ });
+ });
+ break;
+ case 'date':
+ case 'number':
+ case 'regexp':
+ case 'boolean':
+ canonicalizedObj = value;
+ break;
+ default:
+ canonicalizedObj = value.toString();
+ }
+
+ return canonicalizedObj;
+};
+
+/**
+ * Lookup file names at the given `path`.
+ */
+exports.lookupFiles = function lookupFiles(path, extensions, recursive) {
+ var files = [];
+ var re = new RegExp('\\.(' + extensions.join('|') + ')$');
+
+ if (!exists(path)) {
+ if (exists(path + '.js')) {
+ path += '.js';
+ } else {
+ files = glob.sync(path);
+ if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'");
+ return files;
+ }
+ }
+
+ try {
+ var stat = fs.statSync(path);
+ if (stat.isFile()) return path;
+ }
+ catch (ignored) {
+ return;
+ }
+
+ fs.readdirSync(path).forEach(function(file) {
+ file = join(path, file);
+ try {
+ var stat = fs.statSync(file);
+ if (stat.isDirectory()) {
+ if (recursive) {
+ files = files.concat(lookupFiles(file, extensions, recursive));
+ }
+ return;
+ }
+ }
+ catch (ignored) {
+ return;
+ }
+ if (!stat.isFile() || !re.test(file) || basename(file)[0] === '.') return;
+ files.push(file);
+ });
+
+ return files;
+};
+
+/**
+ * Generate an undefined error with a message warning the user.
+ *
+ * @return {Error}
+ */
+
+exports.undefinedError = function() {
+ return new Error('Caught undefined error, did you throw without specifying what?');
+};
+
+/**
+ * Generate an undefined error if `err` is not defined.
+ *
+ * @param {Error} err
+ * @return {Error}
+ */
+
+exports.getError = function(err) {
+ return err || exports.undefinedError();
+};
+
+
+/**
+ * @summary
+ * This Filter based on `mocha-clean` module.(see: `github.com/rstacruz/mocha-clean`)
+ * @description
+ * When invoking this function you get a filter function that get the Error.stack as an input,
+ * and return a prettify output.
+ * (i.e: strip Mocha, node_modules, bower and componentJS from stack trace).
+ * @returns {Function}
+ */
+
+exports.stackTraceFilter = function() {
+ var slash = '/'
+ , is = typeof document === 'undefined'
+ ? { node: true }
+ : { browser: true }
+ , cwd = is.node
+ ? process.cwd() + slash
+ : location.href.replace(/\/[^\/]*$/, '/');
+
+ function isNodeModule (line) {
+ return (~line.indexOf('node_modules'));
+ }
+
+ function isMochaInternal (line) {
+ return (~line.indexOf('node_modules' + slash + 'mocha')) ||
+ (~line.indexOf('components' + slash + 'mochajs')) ||
+ (~line.indexOf('components' + slash + 'mocha'));
+ }
+
+ // node_modules, bower, componentJS
+ function isBrowserModule(line) {
+ return (~line.indexOf('node_modules')) ||
+ (~line.indexOf('components'));
+ }
+
+ function isNodeInternal (line) {
+ return (~line.indexOf('(timers.js:')) ||
+ (~line.indexOf('(events.js:')) ||
+ (~line.indexOf('(node.js:')) ||
+ (~line.indexOf('(module.js:')) ||
+ (~line.indexOf('GeneratorFunctionPrototype.next (native)')) ||
+ false
+ }
+
+ return function(stack) {
+ stack = stack.split('\n');
+
+ stack = stack.reduce(function (list, line) {
+ if (is.node && (isNodeModule(line) ||
+ isMochaInternal(line) ||
+ isNodeInternal(line)))
+ return list;
+
+ if (is.browser && (isBrowserModule(line)))
+ return list;
+
+ // Clean up cwd(absolute)
+ list.push(line.replace(cwd, ''));
+ return list;
+ }, []);
+
+ return stack.join('\n');
+ }
+};
+}); // module: utils.js
+// The global object is "self" in Web Workers.
+var global = (function() { return this; })();
+
+/**
+ * Save timer references to avoid Sinon interfering (see GH-237).
+ */
+
+var Date = global.Date;
+var setTimeout = global.setTimeout;
+var setInterval = global.setInterval;
+var clearTimeout = global.clearTimeout;
+var clearInterval = global.clearInterval;
+
+/**
+ * Node shims.
+ *
+ * These are meant only to allow
+ * mocha.js to run untouched, not
+ * to allow running node code in
+ * the browser.
+ */
+
+var process = {};
+process.exit = function(status){};
+process.stdout = {};
+
+var uncaughtExceptionHandlers = [];
+
+var originalOnerrorHandler = global.onerror;
+
+/**
+ * Remove uncaughtException listener.
+ * Revert to original onerror handler if previously defined.
+ */
+
+process.removeListener = function(e, fn){
+ if ('uncaughtException' == e) {
+ if (originalOnerrorHandler) {
+ global.onerror = originalOnerrorHandler;
+ } else {
+ global.onerror = function() {};
+ }
+ var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn);
+ if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); }
+ }
+};
+
+/**
+ * Implements uncaughtException listener.
+ */
+
+process.on = function(e, fn){
+ if ('uncaughtException' == e) {
+ global.onerror = function(err, url, line){
+ fn(new Error(err + ' (' + url + ':' + line + ')'));
+ return true;
+ };
+ uncaughtExceptionHandlers.push(fn);
+ }
+};
+
+/**
+ * Expose mocha.
+ */
+
+var Mocha = global.Mocha = require('mocha'),
+ mocha = global.mocha = new Mocha({ reporter: 'html' });
+
+// The BDD UI is registered by default, but no UI will be functional in the
+// browser without an explicit call to the overridden `mocha.ui` (see below).
+// Ensure that this default UI does not expose its methods to the global scope.
+mocha.suite.removeAllListeners('pre-require');
+
+var immediateQueue = []
+ , immediateTimeout;
+
+function timeslice() {
+ var immediateStart = new Date().getTime();
+ while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {
+ immediateQueue.shift()();
+ }
+ if (immediateQueue.length) {
+ immediateTimeout = setTimeout(timeslice, 0);
+ } else {
+ immediateTimeout = null;
+ }
+}
+
+/**
+ * High-performance override of Runner.immediately.
+ */
+
+Mocha.Runner.immediately = function(callback) {
+ immediateQueue.push(callback);
+ if (!immediateTimeout) {
+ immediateTimeout = setTimeout(timeslice, 0);
+ }
+};
+
+/**
+ * Function to allow assertion libraries to throw errors directly into mocha.
+ * This is useful when running tests in a browser because window.onerror will
+ * only receive the 'message' attribute of the Error.
+ */
+mocha.throwError = function(err) {
+ Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) {
+ fn(err);
+ });
+ throw err;
+};
+
+/**
+ * Override ui to ensure that the ui functions are initialized.
+ * Normally this would happen in Mocha.prototype.loadFiles.
+ */
+
+mocha.ui = function(ui){
+ Mocha.prototype.ui.call(this, ui);
+ this.suite.emit('pre-require', global, null, this);
+ return this;
+};
+
+/**
+ * Setup mocha with the given setting options.
+ */
+
+mocha.setup = function(opts){
+ if ('string' == typeof opts) opts = { ui: opts };
+ for (var opt in opts) {
+ if (opts.hasOwnProperty(opt)) {
+ this[opt](opts[opt]);
+ }
+ }
+ return this;
+};
+
+/**
+ * Run mocha, returning the Runner.
+ */
+
+mocha.run = function(fn){
+ var options = mocha.options;
+ mocha.globals('location');
+
+ var query = Mocha.utils.parseQuery(global.location.search || '');
+ if (query.grep) mocha.grep(new RegExp(query.grep));
+ if (query.fgrep) mocha.grep(query.fgrep);
+ if (query.invert) mocha.invert();
+
+ return Mocha.prototype.run.call(mocha, function(err){
+ // The DOM Document is not available in Web Workers.
+ var document = global.document;
+ if (document && document.getElementById('mocha') && options.noHighlighting !== true) {
+ Mocha.utils.highlightTags('code');
+ }
+ if (fn) fn(err);
+ });
+};
+
+/**
+ * Expose the process shim.
+ */
+
+Mocha.process = process;
+})();
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/.npmignore b/chromium/third_party/catapult/tracing/third_party/oboe/.npmignore
new file mode 100644
index 00000000000..7751ce36714
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/.npmignore
@@ -0,0 +1,12 @@
+libpeerconnection.log
+*.idea
+*.iml
+*.tidy
+*.backup
+.DS_Store
+writing
+dissertation
+src
+examples
+build
+benchmarking \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/.travis.yml b/chromium/third_party/catapult/tracing/third_party/oboe/.travis.yml
new file mode 100644
index 00000000000..6e5919de39a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/.travis.yml
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+ - "0.10"
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/CONTRIBUTING.md b/chromium/third_party/catapult/tracing/third_party/oboe/CONTRIBUTING.md
new file mode 100644
index 00000000000..2dae8c9c4db
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/CONTRIBUTING.md
@@ -0,0 +1,71 @@
+# Contributing to Oboe.js
+
+:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
+
+The following is a set of guidelines for contributing to Oboe.js. These are
+just guidelines, not rules, use your best judgment and feel free to propose
+changes to this document in a pull request.
+
+## Read the docs :)
+
+Oboe.js has some [awesome documentation](http://oboejs.com/)
+explaining how and why to use the library.
+
+## Questions/Help
+
+Sometimes your question can be addressed by reading the
+[API](http://oboejs.com/api) closely. It's short and nicely organized!
+
+Please post questions to [StackOverflow](http://stackoverflow.com/)
+using the `oboe.js` and`javascript` tags.
+
+If you file an issue with an implementation question, it will be closed.
+We're not trying to be mean, it just helps keep the issues tab cleaner so we can
+ keep improving the library.
+
+## Reporting Bugs / Requesting Features
+
+If you've found an issue, please submit it in
+[the issues](https://github.com/jimhigson/oboe.js/issues).
+
+To increase our ability to help, please:
+- If it's a server-side bug, fork our
+[bug-template](https://github.com/JuanCaicedo/oboe-bug-template), recreate your
+bug, and then provide a link to that repo.
+- If it's a client-side template, provide a link to a
+[jsbin](https://jsbin.com/)/[codepen](http://codepen.io/)/[plunkr](https://plnkr.co/)
+that demonstrates the issue (if it's on the client), or a github repo
+(if it's on the server), greatly increases our ability to help.
+
+## Pull Requests
+
+If you would like to add functionality, please submit
+[an issue](https://github.com/jimhigson/oboe.js/issues) first to make sure it's
+a direction we want to take.
+
+Please do the following:
+* Follow the existing styles
+* Create an example for that demonstrates your changes so people can see how
+your changes work
+
+In your PR description include any information that will help a maintainer
+understand and test your changes. The easier it is to read and run your PR,
+the faster it can get merged!
+
+### What does Oboe need help with?
+
+#### Helping others!
+
+There is a [Google Group](https://groups.google.com/forum/#!forum/oboejs) for
+general project discussion. If you have a moment to help other people using the
+library, please stop in.
+
+#### Contributing to community
+
+- Write examples! The website has a [section](http://oboejs.com/examples)
+showing common use-cases, and it could always use some more. Feel free to submit
+a PR to [the website](https://github.com/jimhigson/oboe.js-website).
+- We would also like to showcase applications using Oboe, so if you've published
+one and want to share it, file it
+[in the website issues](https://github.com/jimhigson/oboe.js-website/issues)
+and we'll showcase it!
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/Gruntfile.js b/chromium/third_party/catapult/tracing/third_party/oboe/Gruntfile.js
new file mode 100644
index 00000000000..8503f59954f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/Gruntfile.js
@@ -0,0 +1,398 @@
+module.exports = function (grunt) {
+
+ function runNpmScript(command, cb) {
+ var opts = {
+ cmd: 'npm',
+ args: ['run', command],
+ opts: {
+ stdio: 'inherit'
+ }
+ };
+
+ grunt.util.spawn(opts, function(error, result, code) {
+ if(error) {
+ grunt.fail.warn(command + " failed.");
+ }
+ cb();
+ });
+ }
+
+ var autoStartBrowsers = ['Chrome', 'Firefox', 'Safari'];
+
+ var STREAM_SOURCE_PORT_HTTP = 4567;
+
+ // NB: source files are order sensitive
+ var OBOE_BROWSER_SOURCE_FILES = [
+ 'build/version.js'
+ , 'src/LICENCE.js'
+ , 'src/functional.js'
+ , 'src/util.js'
+ , 'src/lists.js'
+ , 'src/libs/clarinet.js'
+ , 'src/ascentManager.js'
+ , 'src/parseResponseHeaders.browser.js'
+ , 'src/detectCrossOrigin.browser.js'
+ , 'src/streamingHttp.browser.js'
+ , 'src/jsonPathSyntax.js'
+ , 'src/ascent.js'
+ , 'src/incrementalContentBuilder.js'
+ , 'src/jsonPath.js'
+ , 'src/singleEventPubSub.js'
+ , 'src/pubSub.js'
+ , 'src/events.js'
+ , 'src/patternAdapter.js'
+ , 'src/instanceApi.js'
+ , 'src/wire.js'
+ , 'src/defaults.js'
+ , 'src/publicApi.js'
+ ];
+
+ var OBOE_NODE_SOURCE_FILES = [
+ 'build/version.js'
+ , 'src/LICENCE.js'
+ , 'src/functional.js'
+ , 'src/util.js'
+ , 'src/lists.js'
+ , 'src/libs/clarinet.js'
+ , 'src/ascentManager.js'
+ , 'src/streamingHttp.node.js'
+ , 'src/jsonPathSyntax.js'
+ , 'src/ascent.js'
+ , 'src/incrementalContentBuilder.js'
+ , 'src/jsonPath.js'
+ , 'src/singleEventPubSub.js'
+ , 'src/pubSub.js'
+ , 'src/events.js'
+ , 'src/patternAdapter.js'
+ , 'src/instanceApi.js'
+ , 'src/wire.js'
+ , 'src/defaults.js'
+ , 'src/publicApi.js'
+ ];
+
+ var FILES_TRIGGERING_KARMA = [
+ 'src/**/*.js',
+ 'test/specs/*.spec.js',
+ 'test/libs/*.js'
+ ];
+
+ // load the wrapper file for packaging source targeted at either
+ // browser or node
+ function wrapper(target){
+ return require('fs')
+ .readFileSync('src/wrapper.' + target + '.js', 'utf8')
+ .split('// ---contents--- //');
+ }
+
+ grunt.initConfig({
+
+ pkg:grunt.file.readJSON("package.json")
+
+ , clean: ['dist/*.js', 'build/*.js']
+
+ , concat: {
+ browser:{
+ src: OBOE_BROWSER_SOURCE_FILES,
+ dest: 'build/oboe-browser.concat.js'
+ },
+ node:{
+ src: OBOE_NODE_SOURCE_FILES,
+ dest: 'build/oboe-node.concat.js'
+ }
+ }
+
+ , wrap: {
+ browserPackage: {
+ src: 'build/oboe-browser.concat.js',
+ dest: '.',
+ wrapper: wrapper('browser')
+ },
+
+ nodePackage: {
+ src: 'build/oboe-node.concat.js',
+ dest: '.',
+ wrapper: wrapper('node')
+ }
+ }
+
+
+ , uglify: {
+ build:{
+ files:{
+ 'build/oboe-browser.min.js': 'build/oboe-browser.concat.js'
+ }
+ }
+ }
+
+ , karma: {
+ options:{
+ singleRun: true,
+ proxies: {
+ '/testServer' : 'http://localhost:' + STREAM_SOURCE_PORT_HTTP
+ },
+ // test results reporter to use
+ // possible values: 'dots', 'progress', 'junit'
+ reporters : ['progress'],
+
+ // enable / disable colors in the output (reporters and logs)
+ colors : true
+ }
+ ,
+ 'coverage':{
+ reporters : ['coverage'],
+ preprocessors: {
+ // source files to generate coverage for
+ // (these files will be instrumented by Istanbul)
+ 'src/**/*.js': ['coverage']
+ },
+ 'browsers': ['PhantomJS'],
+ configFile: 'test/unit.conf.js'
+ }
+
+ ,
+ 'precaptured-dev': {
+ // for doing a single test run with already captured browsers during development.
+ // this is good for running tests in browsers karma can't easily start such as
+ // IE running inside a Windows VM on a unix dev environment
+ browsers: [],
+ configFile: 'test/unit.conf.js',
+ singleRun: 'true'
+ }
+ ,
+ 'single-dev': {
+ browsers: autoStartBrowsers,
+ configFile: 'test/unit.conf.js'
+ }
+ ,
+ 'single-concat': {
+ browsers: autoStartBrowsers,
+ configFile: 'test/concat.conf.js'
+ }
+ ,
+ 'single-minified': {
+ browsers: autoStartBrowsers,
+ configFile: 'test/min.conf.js'
+ }
+
+ ,
+ 'single-amd': {
+ browsers: autoStartBrowsers,
+ configFile: 'test/amd.conf.js'
+ }
+
+ ,
+ 'single-browser-http': {
+ browsers: autoStartBrowsers,
+ configFile: 'test/http.conf.js'
+ }
+
+ ,
+ 'persist': {
+ // for setting up a persistent karma server.
+ // To start the server, the task is:
+ // karma:persist
+ // To run these, the task is:
+ // karma:persist:run
+ configFile: 'test/unit.conf.js',
+ browsers: [],
+ singleRun:false,
+ background:true
+ }
+ }
+
+ , copy: {
+ browserDist: {
+ files: [
+ {src: ['build/oboe-browser.min.js'], dest: 'dist/oboe-browser.min.js'}
+ , {src: ['build/oboe-browser.concat.js'], dest: 'dist/oboe-browser.js' }
+ ]
+ },
+ nodeDist: {
+ files: [
+ {src: ['build/oboe-node.concat.js'], dest: 'dist/oboe-node.js'}
+ ]
+ }
+ }
+
+ , exec:{
+ // these might not go too well on Windows :-) - get Cygwin.
+ reportMinifiedSize:{
+ command: "echo minified size is `wc -c < dist/oboe-browser.min.js` bytes"
+ },
+ reportMinifiedAndGzippedSize:{
+ command: "echo Size after gzip is `gzip --best --stdout dist/oboe-browser.min.js | wc -c` bytes - max 5120"
+ },
+ createGitVersionJs:{
+ command: "echo \"// `git describe`\" > build/version.js"
+ }
+ }
+
+ , watch:{
+ karma:{
+ files:FILES_TRIGGERING_KARMA,
+ tasks:['karma:persist:run']
+ },
+
+ // like above but reports the file size. This is good for
+ // watching while developing to make sure it doesn't get
+ // too big. Doesn't run tests against minified.
+ karmaAndSize:{
+ files: FILES_TRIGGERING_KARMA,
+ tasks:[
+ 'karma:persist:run',
+ 'browser-build',
+ 'dist-sizes']
+ },
+
+ // like above but reports the file size. This is good for
+ // watching while developing to make sure it doesn't get
+ // too big. Doesn't run tests against minified.
+ testNode:{
+ files: FILES_TRIGGERING_KARMA,
+ tasks:[
+ 'node-build']
+ },
+
+ restartStreamSourceAndRunTests:{
+ // this fails at the moment because start-stream-source
+ // fails if run more than once - the port is taken.
+ files: ['test/streamsource.js'],
+ tasks: ['start-stream-source', 'karma:persist:run']
+ }
+ }
+
+ , concurrent:{
+ watchDev: {
+ tasks:[ 'watch:karmaAndSize', 'watch:restartStreamSourceAndRunTests' ],
+ options:{
+ logConcurrentOutput: true
+ }
+ }
+ }
+
+ });
+
+ require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
+
+ var streamSource;
+
+ grunt.registerTask('start-stream-source', function () {
+ grunt.log.ok('do we have a streaming source already?', !!streamSource);
+
+ // if we previously loaded the streamsource, stop it to let the new one in:
+ if( streamSource ) {
+ grunt.log.ok('there seems to be a streaming server already, let\'s stop it');
+ streamSource.stop();
+ }
+
+ streamSource = require('./test/streamsource.js');
+ streamSource.start(STREAM_SOURCE_PORT_HTTP, grunt);
+ });
+
+ grunt.registerTask("jasmine_node_oboe", "Runs jasmine-node.", function() {
+ runNpmScript('test-node', this.async());
+ });
+
+ // change the auto-starting browsers so that future tests will use
+ // phantomjs instead of actual browsers. Can do:
+ // grunt headless-mode default
+ // to run without any actual browsers
+ grunt.registerTask('headless-mode', function(){
+ autoStartBrowsers.length = 0;
+ autoStartBrowsers.push('PhantomJS');
+ });
+
+ grunt.registerTask('test-start-server', [
+ 'karma:persist'
+ ]);
+
+ grunt.registerTask('test-run', [
+ 'karma:persist:run'
+ ]);
+
+ grunt.registerTask('dist-sizes', [
+ 'exec:reportMinifiedAndGzippedSize'
+ ]);
+
+ grunt.registerTask('node-build', [
+ 'exec:createGitVersionJs',
+ 'concat:node',
+ 'wrap:nodePackage',
+ 'copy:nodeDist'
+ ]);
+
+ grunt.registerTask('node-build-test', [
+ 'node-build',
+ 'jasmine_node_oboe'
+ ]);
+
+ grunt.registerTask('node', [
+ 'start-stream-source',
+ 'node-build-test'
+ ]);
+
+ grunt.registerTask('browser-build', [
+ 'exec:createGitVersionJs',
+ 'concat:browser',
+ 'concat:node',
+ 'wrap:browserPackage',
+ 'uglify',
+ 'copy:browserDist'
+ ]);
+
+ grunt.registerTask('browser-build-test', [
+ 'karma:single-dev',
+ 'karma:single-browser-http',
+ 'browser-build',
+ 'karma:single-concat',
+ 'karma:single-minified',
+ 'karma:single-amd'
+ ]);
+
+ grunt.registerTask('build', [
+ 'browser-build',
+ 'node-build'
+ ]);
+
+ // build and run just the integration tests.
+ grunt.registerTask('build-integration-test', [
+ 'build',
+ 'start-stream-source',
+ 'karma:single-concat',
+ 'jasmine_node_oboe',
+ 'dist-sizes'
+ ]);
+
+ grunt.registerTask('default', [
+
+ 'clear',
+ 'clean',
+ 'start-stream-source',
+
+ 'browser-build-test',
+
+ 'node-build-test',
+
+ 'dist-sizes'
+ ]);
+
+
+
+ // browser-test-auto-run or node-test-auto-run
+ //
+ // The most useful for developing. Start this task, capture some browsers
+ // (unless node) then edit the code. Tests will be run as the code is
+ // saved.
+ grunt.registerTask('browser-test-auto-run', [
+ 'start-stream-source',
+ 'karma:persist',
+ 'concurrent:watchDev'
+ ]);
+ grunt.registerTask('node-test-auto-run', [
+ 'start-stream-source',
+ 'watch:testNode'
+ ]);
+ grunt.registerTask('coverage', [
+ 'karma:coverage'
+ ]);
+};
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/LICENCE b/chromium/third_party/catapult/tracing/third_party/oboe/LICENCE
new file mode 100755
index 00000000000..261adc505fc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/LICENCE
@@ -0,0 +1,26 @@
+Copyright (c) 2013, Jim Higson
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies,
+either expressed or implied, of the FreeBSD Project. \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/README.chromium b/chromium/third_party/catapult/tracing/third_party/oboe/README.chromium
new file mode 100644
index 00000000000..0f31e09f70e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/README.chromium
@@ -0,0 +1,19 @@
+Name: Oboe.js
+Short Name: oboe
+URL: https://github.com/jimhigson/oboe.js
+Version: 2.1.3
+Revision: 4b43d2f5e50733a6c6eac3725142ac1c1a69b0e3
+Date: Tue Jan 31 15:08:00 EST 2017
+License: BSD-2-Clause
+License File: LICENCSE
+Security Critical: no
+
+Description:
+Oboe.js is an open source Javascript library for loading JSON using streaming, combining the convenience of DOM with the speed and fluidity of SAX.
+
+Local Modifications:
+Although the whole repository is pulled, we only use dist/oboe-browser.js and dist/oboe-node.js. There are some local modifications, explained below:
+
+* dist/oboe-node.js:1092: the internal 'http' module is used to remove dependency on external the 'http-https' module.
+* dist/oboe-node.js:2439-2442: two methods (write, finish) are exposed in the public API for manually sending data to the parser.
+* dist/oboe-browser.js:2545-2548: two methods (write, finish) are exposed in the public API for manually sending data to the parser.
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/README.md b/chromium/third_party/catapult/tracing/third_party/oboe/README.md
new file mode 100644
index 00000000000..094b88f1fba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/README.md
@@ -0,0 +1,24 @@
+Oboe.js is an [open source](LICENCE) Javascript library
+for loading JSON using streaming, combining the convenience of DOM with
+the speed and fluidity of SAX.
+
+It can parse any JSON as a stream, is small enough to be a [micro-library](http://microjs.com/#),
+doesn't have dependencies, and doesn't care which other libraries you need it to speak to.
+
+We can load trees [larger than the available memory](http://oboejs.com/examples#loading-json-trees-larger-than-the-available-ram).
+Or we can [instantiate classical OOP models from JSON](http://oboejs.com/examples#demarshalling-json-to-an-oop-model),
+or [completely transform your JSON](http://oboejs.com/examples#transforming-json-while-it-is-streaming) while it is being read.
+
+Oboe makes it really easy to start using json from a response before the ajax request completes.
+Or even if it never completes.
+
+Where next?
+-----------
+
+- [The website](http://oboejs.com)
+- Visualise [faster web applications through streaming](http://oboejs.com/why)
+- Visit the [project homepage](http://oboejs.com)
+- Browse [code examples](http://oboejs.com/examples)
+- Learn the Oboe.js [API](http://oboejs.com/api)
+- [Download](http://oboejs.com/download) the library
+- [Discuss](http://oboejs.com/discuss) Oboe.js
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/.gitIgnore b/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/.gitIgnore
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/.gitIgnore
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/benchmarkClient.js b/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/benchmarkClient.js
new file mode 100644
index 00000000000..31546d08554
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/benchmarkClient.js
@@ -0,0 +1,127 @@
+
+/* call this script from the command line with first argument either
+ oboe, jsonParse, or clarinet.
+
+ This script won't time the events, I'm using `time` on the command line
+ to keep things simple.
+ */
+
+require('color');
+
+var DB_URL = 'http://localhost:4444/db';
+
+
+function aggregateWithOboe() {
+
+ var oboe = require('../dist/oboe-node.js');
+
+ oboe(DB_URL).node('{id url}.url', function(url){
+
+ oboe(url).node('name', function(name){
+
+ console.log(name);
+ this.abort();
+ console.log( process.memoryUsage().heapUsed );
+ });
+ });
+}
+
+function aggregateWithJsonParse() {
+
+ var getJson = require('get-json');
+
+ getJson(DB_URL, function(err, records) {
+
+ records.data.forEach( function( record ){
+
+ var url = record.url;
+
+ getJson(url, function(err, record) {
+ console.log(record.name);
+ console.log( process.memoryUsage().heapUsed );
+ });
+ });
+
+ });
+
+}
+
+
+function aggregateWithClarinet() {
+
+ var clarinet = require('clarinet');
+ var http = require('http');
+ var outerClarinetStream = clarinet.createStream();
+ var outerKey;
+
+ var outerRequest = http.request(DB_URL, function(res) {
+
+ res.pipe(outerClarinetStream);
+ });
+
+ outerClarinetStream = clarinet.createStream();
+
+ outerRequest.end();
+
+ outerClarinetStream.on('openobject', function( keyName ){
+ if( keyName ) {
+ outerKey = keyName;
+ }
+ });
+
+ outerClarinetStream.on('key', function(keyName){
+ outerKey = keyName;
+ });
+
+ outerClarinetStream.on('value', function(value){
+ if( outerKey == 'url' ) {
+ innerRequest(value)
+ }
+ });
+
+
+ function innerRequest(url) {
+
+ var innerRequest = http.request(url, function(res) {
+
+ res.pipe(innerClarinetStream);
+ });
+
+ var innerClarinetStream = clarinet.createStream();
+
+ innerRequest.end();
+
+ var innerKey;
+
+ innerClarinetStream.on('openobject', function( keyName ){
+ if( keyName ) {
+ innerKey = keyName;
+ }
+ });
+
+ innerClarinetStream.on('key', function(keyName){
+ innerKey = keyName;
+ });
+
+ innerClarinetStream.on('value', function(value){
+ if( innerKey == 'name' ) {
+ console.log( value )
+ console.log( process.memoryUsage().heapUsed );
+ }
+ });
+ }
+}
+
+var strategies = {
+ oboe: aggregateWithOboe,
+ jsonParse: aggregateWithJsonParse,
+ clarinet: aggregateWithClarinet
+}
+
+var strategyName = process.argv[2];
+
+// use any of the above three strategies depending on a command line argument:
+console.log('benchmarking strategy', strategyName);
+
+strategies[strategyName]();
+
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/benchmarkServer.js b/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/benchmarkServer.js
new file mode 100644
index 00000000000..c9f4fc84e55
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/benchmarking/benchmarkServer.js
@@ -0,0 +1,94 @@
+/**
+ */
+
+"use strict";
+
+var PORT = 4444;
+
+var TIME_BETWEEN_RECORDS = 15;
+// 80 records but only every other one has a URL:
+var NUMBER_OF_RECORDS = 80;
+
+function sendJsonHeaders(res) {
+ var JSON_MIME_TYPE = "application/octet-stream";
+ res.setHeader("Content-Type", JSON_MIME_TYPE);
+ res.writeHead(200);
+}
+
+function serveItemList(_req, res) {
+
+ console.log('slow fake db server: send simulated database data');
+
+ res.write('{"data": [');
+
+ var i = 0;
+
+ var inervalId = setInterval(function () {
+
+ if( i % 2 == 0 ) {
+
+ res.write(JSON.stringify({
+ "id": i,
+ "url": "http://localhost:4444/item/" + i
+ }));
+ } else {
+ res.write(JSON.stringify({
+ "id": i
+ }));
+ }
+
+ if (i == NUMBER_OF_RECORDS) {
+
+ res.end(']}');
+
+ clearInterval(inervalId);
+
+ console.log('db server: finished writing to stream');
+ } else {
+ res.write(',');
+ }
+
+ i++;
+
+ }, TIME_BETWEEN_RECORDS);
+}
+
+function serveItem(req, res){
+
+ var id = req.params.id;
+
+ console.log('will output fake record with id', id);
+
+ setTimeout(function(){
+ // the items served are all the same except for the id field.
+ // this is realistic looking but randomly generated object fro
+ // <project>/test/json/oneHundredrecords.json
+ res.end(JSON.stringify({
+ "id" : id,
+ "url": "http://localhost:4444/item/" + id,
+ "guid": "046447ee-da78-478c-b518-b612111942a5",
+ "picture": "http://placehold.it/32x32",
+ "age": 37,
+ "name": "Humanoid robot number " + id,
+ "company": "Robotomic",
+ "phone": "806-587-2379",
+ "email": "payton@robotomic.com"
+ }));
+
+ }, TIME_BETWEEN_RECORDS);
+
+}
+
+function routing() {
+ var Router = require('node-simple-router'),
+ router = Router();
+
+ router.get( '/db', serveItemList);
+ router.get( '/item/:id', serveItem);
+
+ return router;
+}
+
+var server = require('http').createServer(routing()).listen(PORT);
+
+console.log('Benchmark server started on port', String(PORT));
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/build/README.md b/chromium/third_party/catapult/tracing/third_party/oboe/build/README.md
new file mode 100644
index 00000000000..85484c6378f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/build/README.md
@@ -0,0 +1 @@
+Directory used for the building. Nothing to see here. \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/component.json b/chromium/third_party/catapult/tracing/third_party/oboe/component.json
new file mode 100644
index 00000000000..c124a8b55eb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/component.json
@@ -0,0 +1,18 @@
+{
+ "name": "oboe",
+ "version": "2.1.2",
+ "main": "dist/oboe-browser.js",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "components",
+ "writing",
+ "src",
+ "examples",
+ "build",
+ "benchmarking",
+ "package.json",
+ "Gruntfile.js",
+ "test"
+ ]
+} \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-browser.js b/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-browser.js
new file mode 100644
index 00000000000..619e1d45ac4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-browser.js
@@ -0,0 +1,2707 @@
+// This file is the concatenation of many js files.
+// See http://github.com/jimhigson/oboe.js for the raw source
+
+// having a local undefined, window, Object etc allows slightly better minification:
+(function (window, Object, Array, Error, JSON, undefined ) {
+
+ // v2.1.3-2-gc85b5c4
+
+/*
+
+Copyright (c) 2013, Jim Higson
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+/**
+ * Partially complete a function.
+ *
+ * var add3 = partialComplete( function add(a,b){return a+b}, 3 );
+ *
+ * add3(4) // gives 7
+ *
+ * function wrap(left, right, cen){return left + " " + cen + " " + right;}
+ *
+ * var pirateGreeting = partialComplete( wrap , "I'm", ", a mighty pirate!" );
+ *
+ * pirateGreeting("Guybrush Threepwood");
+ * // gives "I'm Guybrush Threepwood, a mighty pirate!"
+ */
+var partialComplete = varArgs(function( fn, args ) {
+
+ // this isn't the shortest way to write this but it does
+ // avoid creating a new array each time to pass to fn.apply,
+ // otherwise could just call boundArgs.concat(callArgs)
+
+ var numBoundArgs = args.length;
+
+ return varArgs(function( callArgs ) {
+
+ for (var i = 0; i < callArgs.length; i++) {
+ args[numBoundArgs + i] = callArgs[i];
+ }
+
+ args.length = numBoundArgs + callArgs.length;
+
+ return fn.apply(this, args);
+ });
+ }),
+
+/**
+ * Compose zero or more functions:
+ *
+ * compose(f1, f2, f3)(x) = f1(f2(f3(x))))
+ *
+ * The last (inner-most) function may take more than one parameter:
+ *
+ * compose(f1, f2, f3)(x,y) = f1(f2(f3(x,y))))
+ */
+ compose = varArgs(function(fns) {
+
+ var fnsList = arrayAsList(fns);
+
+ function next(params, curFn) {
+ return [apply(params, curFn)];
+ }
+
+ return varArgs(function(startParams){
+
+ return foldR(next, startParams, fnsList)[0];
+ });
+ });
+
+/**
+ * A more optimised version of compose that takes exactly two functions
+ * @param f1
+ * @param f2
+ */
+function compose2(f1, f2){
+ return function(){
+ return f1.call(this,f2.apply(this,arguments));
+ }
+}
+
+/**
+ * Generic form for a function to get a property from an object
+ *
+ * var o = {
+ * foo:'bar'
+ * }
+ *
+ * var getFoo = attr('foo')
+ *
+ * fetFoo(o) // returns 'bar'
+ *
+ * @param {String} key the property name
+ */
+function attr(key) {
+ return function(o) { return o[key]; };
+}
+
+/**
+ * Call a list of functions with the same args until one returns a
+ * truthy result. Similar to the || operator.
+ *
+ * So:
+ * lazyUnion([f1,f2,f3 ... fn])( p1, p2 ... pn )
+ *
+ * Is equivalent to:
+ * apply([p1, p2 ... pn], f1) ||
+ * apply([p1, p2 ... pn], f2) ||
+ * apply([p1, p2 ... pn], f3) ... apply(fn, [p1, p2 ... pn])
+ *
+ * @returns the first return value that is given that is truthy.
+ */
+ var lazyUnion = varArgs(function(fns) {
+
+ return varArgs(function(params){
+
+ var maybeValue;
+
+ for (var i = 0; i < len(fns); i++) {
+
+ maybeValue = apply(params, fns[i]);
+
+ if( maybeValue ) {
+ return maybeValue;
+ }
+ }
+ });
+ });
+
+/**
+ * This file declares various pieces of functional programming.
+ *
+ * This isn't a general purpose functional library, to keep things small it
+ * has just the parts useful for Oboe.js.
+ */
+
+
+/**
+ * Call a single function with the given arguments array.
+ * Basically, a functional-style version of the OO-style Function#apply for
+ * when we don't care about the context ('this') of the call.
+ *
+ * The order of arguments allows partial completion of the arguments array
+ */
+function apply(args, fn) {
+ return fn.apply(undefined, args);
+}
+
+/**
+ * Define variable argument functions but cut out all that tedious messing about
+ * with the arguments object. Delivers the variable-length part of the arguments
+ * list as an array.
+ *
+ * Eg:
+ *
+ * var myFunction = varArgs(
+ * function( fixedArgument, otherFixedArgument, variableNumberOfArguments ){
+ * console.log( variableNumberOfArguments );
+ * }
+ * )
+ *
+ * myFunction('a', 'b', 1, 2, 3); // logs [1,2,3]
+ *
+ * var myOtherFunction = varArgs(function( variableNumberOfArguments ){
+ * console.log( variableNumberOfArguments );
+ * })
+ *
+ * myFunction(1, 2, 3); // logs [1,2,3]
+ *
+ */
+function varArgs(fn){
+
+ var numberOfFixedArguments = fn.length -1,
+ slice = Array.prototype.slice;
+
+
+ if( numberOfFixedArguments == 0 ) {
+ // an optimised case for when there are no fixed args:
+
+ return function(){
+ return fn.call(this, slice.call(arguments));
+ }
+
+ } else if( numberOfFixedArguments == 1 ) {
+ // an optimised case for when there are is one fixed args:
+
+ return function(){
+ return fn.call(this, arguments[0], slice.call(arguments, 1));
+ }
+ }
+
+ // general case
+
+ // we know how many arguments fn will always take. Create a
+ // fixed-size array to hold that many, to be re-used on
+ // every call to the returned function
+ var argsHolder = Array(fn.length);
+
+ return function(){
+
+ for (var i = 0; i < numberOfFixedArguments; i++) {
+ argsHolder[i] = arguments[i];
+ }
+
+ argsHolder[numberOfFixedArguments] =
+ slice.call(arguments, numberOfFixedArguments);
+
+ return fn.apply( this, argsHolder);
+ }
+}
+
+
+/**
+ * Swap the order of parameters to a binary function
+ *
+ * A bit like this flip: http://zvon.org/other/haskell/Outputprelude/flip_f.html
+ */
+function flip(fn){
+ return function(a, b){
+ return fn(b,a);
+ }
+}
+
+
+/**
+ * Create a function which is the intersection of two other functions.
+ *
+ * Like the && operator, if the first is truthy, the second is never called,
+ * otherwise the return value from the second is returned.
+ */
+function lazyIntersection(fn1, fn2) {
+
+ return function (param) {
+
+ return fn1(param) && fn2(param);
+ };
+}
+
+/**
+ * A function which does nothing
+ */
+function noop(){}
+
+/**
+ * A function which is always happy
+ */
+function always(){return true}
+
+/**
+ * Create a function which always returns the same
+ * value
+ *
+ * var return3 = functor(3);
+ *
+ * return3() // gives 3
+ * return3() // still gives 3
+ * return3() // will always give 3
+ */
+function functor(val){
+ return function(){
+ return val;
+ }
+}
+
+/**
+ * This file defines some loosely associated syntactic sugar for
+ * Javascript programming
+ */
+
+
+/**
+ * Returns true if the given candidate is of type T
+ */
+function isOfType(T, maybeSomething){
+ return maybeSomething && maybeSomething.constructor === T;
+}
+
+var len = attr('length'),
+ isString = partialComplete(isOfType, String);
+
+/**
+ * I don't like saying this:
+ *
+ * foo !=== undefined
+ *
+ * because of the double-negative. I find this:
+ *
+ * defined(foo)
+ *
+ * easier to read.
+ */
+function defined( value ) {
+ return value !== undefined;
+}
+
+/**
+ * Returns true if object o has a key named like every property in
+ * the properties array. Will give false if any are missing, or if o
+ * is not an object.
+ */
+function hasAllProperties(fieldList, o) {
+
+ return (o instanceof Object)
+ &&
+ all(function (field) {
+ return (field in o);
+ }, fieldList);
+}
+/**
+ * Like cons in Lisp
+ */
+function cons(x, xs) {
+
+ /* Internally lists are linked 2-element Javascript arrays.
+
+ Ideally the return here would be Object.freeze([x,xs])
+ so that bugs related to mutation are found fast.
+ However, cons is right on the critical path for
+ performance and this slows oboe-mark down by
+ ~25%. Under theoretical future JS engines that freeze more
+ efficiently (possibly even use immutability to
+ run faster) this should be considered for
+ restoration.
+ */
+
+ return [x,xs];
+}
+
+/**
+ * The empty list
+ */
+var emptyList = null,
+
+/**
+ * Get the head of a list.
+ *
+ * Ie, head(cons(a,b)) = a
+ */
+ head = attr(0),
+
+/**
+ * Get the tail of a list.
+ *
+ * Ie, tail(cons(a,b)) = b
+ */
+ tail = attr(1);
+
+
+/**
+ * Converts an array to a list
+ *
+ * asList([a,b,c])
+ *
+ * is equivalent to:
+ *
+ * cons(a, cons(b, cons(c, emptyList)))
+ **/
+function arrayAsList(inputArray){
+
+ return reverseList(
+ inputArray.reduce(
+ flip(cons),
+ emptyList
+ )
+ );
+}
+
+/**
+ * A varargs version of arrayAsList. Works a bit like list
+ * in LISP.
+ *
+ * list(a,b,c)
+ *
+ * is equivalent to:
+ *
+ * cons(a, cons(b, cons(c, emptyList)))
+ */
+var list = varArgs(arrayAsList);
+
+/**
+ * Convert a list back to a js native array
+ */
+function listAsArray(list){
+
+ return foldR( function(arraySoFar, listItem){
+
+ arraySoFar.unshift(listItem);
+ return arraySoFar;
+
+ }, [], list );
+
+}
+
+/**
+ * Map a function over a list
+ */
+function map(fn, list) {
+
+ return list
+ ? cons(fn(head(list)), map(fn,tail(list)))
+ : emptyList
+ ;
+}
+
+/**
+ * foldR implementation. Reduce a list down to a single value.
+ *
+ * @pram {Function} fn (rightEval, curVal) -> result
+ */
+function foldR(fn, startValue, list) {
+
+ return list
+ ? fn(foldR(fn, startValue, tail(list)), head(list))
+ : startValue
+ ;
+}
+
+/**
+ * foldR implementation. Reduce a list down to a single value.
+ *
+ * @pram {Function} fn (rightEval, curVal) -> result
+ */
+function foldR1(fn, list) {
+
+ return tail(list)
+ ? fn(foldR1(fn, tail(list)), head(list))
+ : head(list)
+ ;
+}
+
+
+/**
+ * Return a list like the one given but with the first instance equal
+ * to item removed
+ */
+function without(list, test, removedFn) {
+
+ return withoutInner(list, removedFn || noop);
+
+ function withoutInner(subList, removedFn) {
+ return subList
+ ? ( test(head(subList))
+ ? (removedFn(head(subList)), tail(subList))
+ : cons(head(subList), withoutInner(tail(subList), removedFn))
+ )
+ : emptyList
+ ;
+ }
+}
+
+/**
+ * Returns true if the given function holds for every item in
+ * the list, false otherwise
+ */
+function all(fn, list) {
+
+ return !list ||
+ ( fn(head(list)) && all(fn, tail(list)) );
+}
+
+/**
+ * Call every function in a list of functions with the same arguments
+ *
+ * This doesn't make any sense if we're doing pure functional because
+ * it doesn't return anything. Hence, this is only really useful if the
+ * functions being called have side-effects.
+ */
+function applyEach(fnList, args) {
+
+ if( fnList ) {
+ head(fnList).apply(null, args);
+
+ applyEach(tail(fnList), args);
+ }
+}
+
+/**
+ * Reverse the order of a list
+ */
+function reverseList(list){
+
+ // js re-implementation of 3rd solution from:
+ // http://www.haskell.org/haskellwiki/99_questions/Solutions/5
+ function reverseInner( list, reversedAlready ) {
+ if( !list ) {
+ return reversedAlready;
+ }
+
+ return reverseInner(tail(list), cons(head(list), reversedAlready))
+ }
+
+ return reverseInner(list, emptyList);
+}
+
+function first(test, list) {
+ return list &&
+ (test(head(list))
+ ? head(list)
+ : first(test,tail(list)));
+}
+
+/*
+ This is a slightly hacked-up browser only version of clarinet
+
+ * some features removed to help keep browser Oboe under
+ the 5k micro-library limit
+ * plug directly into event bus
+
+ For the original go here:
+ https://github.com/dscape/clarinet
+
+ We receive the events:
+ STREAM_DATA
+ STREAM_END
+
+ We emit the events:
+ SAX_KEY
+ SAX_VALUE_OPEN
+ SAX_VALUE_CLOSE
+ FAIL_EVENT
+ */
+
+function clarinet(eventBus) {
+ "use strict";
+
+ var
+ // shortcut some events on the bus
+ emitSaxKey = eventBus(SAX_KEY).emit,
+ emitValueOpen = eventBus(SAX_VALUE_OPEN).emit,
+ emitValueClose = eventBus(SAX_VALUE_CLOSE).emit,
+ emitFail = eventBus(FAIL_EVENT).emit,
+
+ MAX_BUFFER_LENGTH = 64 * 1024
+ , stringTokenPattern = /[\\"\n]/g
+ , _n = 0
+
+ // states
+ , BEGIN = _n++
+ , VALUE = _n++ // general stuff
+ , OPEN_OBJECT = _n++ // {
+ , CLOSE_OBJECT = _n++ // }
+ , OPEN_ARRAY = _n++ // [
+ , CLOSE_ARRAY = _n++ // ]
+ , STRING = _n++ // ""
+ , OPEN_KEY = _n++ // , "a"
+ , CLOSE_KEY = _n++ // :
+ , TRUE = _n++ // r
+ , TRUE2 = _n++ // u
+ , TRUE3 = _n++ // e
+ , FALSE = _n++ // a
+ , FALSE2 = _n++ // l
+ , FALSE3 = _n++ // s
+ , FALSE4 = _n++ // e
+ , NULL = _n++ // u
+ , NULL2 = _n++ // l
+ , NULL3 = _n++ // l
+ , NUMBER_DECIMAL_POINT = _n++ // .
+ , NUMBER_DIGIT = _n // [0-9]
+
+ // setup initial parser values
+ , bufferCheckPosition = MAX_BUFFER_LENGTH
+ , latestError
+ , c
+ , p
+ , textNode = undefined
+ , numberNode = ""
+ , slashed = false
+ , closed = false
+ , state = BEGIN
+ , stack = []
+ , unicodeS = null
+ , unicodeI = 0
+ , depth = 0
+ , position = 0
+ , column = 0 //mostly for error reporting
+ , line = 1
+ ;
+
+ function checkBufferLength () {
+
+ var maxActual = 0;
+
+ if (textNode !== undefined && textNode.length > MAX_BUFFER_LENGTH) {
+ emitError("Max buffer length exceeded: textNode");
+ maxActual = Math.max(maxActual, textNode.length);
+ }
+ if (numberNode.length > MAX_BUFFER_LENGTH) {
+ emitError("Max buffer length exceeded: numberNode");
+ maxActual = Math.max(maxActual, numberNode.length);
+ }
+
+ bufferCheckPosition = (MAX_BUFFER_LENGTH - maxActual)
+ + position;
+ }
+
+ eventBus(STREAM_DATA).on(handleData);
+
+ /* At the end of the http content close the clarinet
+ This will provide an error if the total content provided was not
+ valid json, ie if not all arrays, objects and Strings closed properly */
+ eventBus(STREAM_END).on(handleStreamEnd);
+
+ function emitError (errorString) {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+
+ latestError = Error(errorString + "\nLn: "+line+
+ "\nCol: "+column+
+ "\nChr: "+c);
+
+ emitFail(errorReport(undefined, undefined, latestError));
+ }
+
+ function handleStreamEnd() {
+ if( state == BEGIN ) {
+ // Handle the case where the stream closes without ever receiving
+ // any input. This isn't an error - response bodies can be blank,
+ // particularly for 204 http responses
+
+ // Because of how Oboe is currently implemented, we parse a
+ // completely empty stream as containing an empty object.
+ // This is because Oboe's done event is only fired when the
+ // root object of the JSON stream closes.
+
+ // This should be decoupled and attached instead to the input stream
+ // from the http (or whatever) resource ending.
+ // If this decoupling could happen the SAX parser could simply emit
+ // zero events on a completely empty input.
+ emitValueOpen({});
+ emitValueClose();
+
+ closed = true;
+ return;
+ }
+
+ if (state !== VALUE || depth !== 0)
+ emitError("Unexpected end");
+
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+
+ closed = true;
+ }
+
+ function whitespace(c){
+ return c == '\r' || c == '\n' || c == ' ' || c == '\t';
+ }
+
+ function handleData (chunk) {
+
+ // this used to throw the error but inside Oboe we will have already
+ // gotten the error when it was emitted. The important thing is to
+ // not continue with the parse.
+ if (latestError)
+ return;
+
+ if (closed) {
+ return emitError("Cannot write after close");
+ }
+
+ var i = 0;
+ c = chunk[0];
+
+ while (c) {
+ p = c;
+ c = chunk[i++];
+ if(!c) break;
+
+ position ++;
+ if (c == "\n") {
+ line ++;
+ column = 0;
+ } else column ++;
+ switch (state) {
+
+ case BEGIN:
+ if (c === "{") state = OPEN_OBJECT;
+ else if (c === "[") state = OPEN_ARRAY;
+ else if (!whitespace(c))
+ return emitError("Non-whitespace before {[.");
+ continue;
+
+ case OPEN_KEY:
+ case OPEN_OBJECT:
+ if (whitespace(c)) continue;
+ if(state === OPEN_KEY) stack.push(CLOSE_KEY);
+ else {
+ if(c === '}') {
+ emitValueOpen({});
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ continue;
+ } else stack.push(CLOSE_OBJECT);
+ }
+ if(c === '"')
+ state = STRING;
+ else
+ return emitError("Malformed object key should start with \" ");
+ continue;
+
+ case CLOSE_KEY:
+ case CLOSE_OBJECT:
+ if (whitespace(c)) continue;
+
+ if(c===':') {
+ if(state === CLOSE_OBJECT) {
+ stack.push(CLOSE_OBJECT);
+
+ if (textNode !== undefined) {
+ // was previously (in upstream Clarinet) one event
+ // - object open came with the text of the first
+ emitValueOpen({});
+ emitSaxKey(textNode);
+ textNode = undefined;
+ }
+ depth++;
+ } else {
+ if (textNode !== undefined) {
+ emitSaxKey(textNode);
+ textNode = undefined;
+ }
+ }
+ state = VALUE;
+ } else if (c==='}') {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ } else if(c===',') {
+ if(state === CLOSE_OBJECT)
+ stack.push(CLOSE_OBJECT);
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ state = OPEN_KEY;
+ } else
+ return emitError('Bad object');
+ continue;
+
+ case OPEN_ARRAY: // after an array there always a value
+ case VALUE:
+ if (whitespace(c)) continue;
+ if(state===OPEN_ARRAY) {
+ emitValueOpen([]);
+ depth++;
+ state = VALUE;
+ if(c === ']') {
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ continue;
+ } else {
+ stack.push(CLOSE_ARRAY);
+ }
+ }
+ if(c === '"') state = STRING;
+ else if(c === '{') state = OPEN_OBJECT;
+ else if(c === '[') state = OPEN_ARRAY;
+ else if(c === 't') state = TRUE;
+ else if(c === 'f') state = FALSE;
+ else if(c === 'n') state = NULL;
+ else if(c === '-') { // keep and continue
+ numberNode += c;
+ } else if(c==='0') {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else if('123456789'.indexOf(c) !== -1) {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else
+ return emitError("Bad value");
+ continue;
+
+ case CLOSE_ARRAY:
+ if(c===',') {
+ stack.push(CLOSE_ARRAY);
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ state = VALUE;
+ } else if (c===']') {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ } else if (whitespace(c))
+ continue;
+ else
+ return emitError('Bad array');
+ continue;
+
+ case STRING:
+ if (textNode === undefined) {
+ textNode = "";
+ }
+
+ // thanks thejh, this is an about 50% performance improvement.
+ var starti = i-1;
+
+ STRING_BIGLOOP: while (true) {
+
+ // zero means "no unicode active". 1-4 mean "parse some more". end after 4.
+ while (unicodeI > 0) {
+ unicodeS += c;
+ c = chunk.charAt(i++);
+ if (unicodeI === 4) {
+ // TODO this might be slow? well, probably not used too often anyway
+ textNode += String.fromCharCode(parseInt(unicodeS, 16));
+ unicodeI = 0;
+ starti = i-1;
+ } else {
+ unicodeI++;
+ }
+ // we can just break here: no stuff we skipped that still has to be sliced out or so
+ if (!c) break STRING_BIGLOOP;
+ }
+ if (c === '"' && !slashed) {
+ state = stack.pop() || VALUE;
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ if (c === '\\' && !slashed) {
+ slashed = true;
+ textNode += chunk.substring(starti, i-1);
+ c = chunk.charAt(i++);
+ if (!c) break;
+ }
+ if (slashed) {
+ slashed = false;
+ if (c === 'n') { textNode += '\n'; }
+ else if (c === 'r') { textNode += '\r'; }
+ else if (c === 't') { textNode += '\t'; }
+ else if (c === 'f') { textNode += '\f'; }
+ else if (c === 'b') { textNode += '\b'; }
+ else if (c === 'u') {
+ // \uxxxx. meh!
+ unicodeI = 1;
+ unicodeS = '';
+ } else {
+ textNode += c;
+ }
+ c = chunk.charAt(i++);
+ starti = i-1;
+ if (!c) break;
+ else continue;
+ }
+
+ stringTokenPattern.lastIndex = i;
+ var reResult = stringTokenPattern.exec(chunk);
+ if (!reResult) {
+ i = chunk.length+1;
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ i = reResult.index+1;
+ c = chunk.charAt(reResult.index);
+ if (!c) {
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ }
+ continue;
+
+ case TRUE:
+ if (!c) continue; // strange buffers
+ if (c==='r') state = TRUE2;
+ else
+ return emitError( 'Invalid true started with t'+ c);
+ continue;
+
+ case TRUE2:
+ if (!c) continue;
+ if (c==='u') state = TRUE3;
+ else
+ return emitError('Invalid true started with tr'+ c);
+ continue;
+
+ case TRUE3:
+ if (!c) continue;
+ if(c==='e') {
+ emitValueOpen(true);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid true started with tru'+ c);
+ continue;
+
+ case FALSE:
+ if (!c) continue;
+ if (c==='a') state = FALSE2;
+ else
+ return emitError('Invalid false started with f'+ c);
+ continue;
+
+ case FALSE2:
+ if (!c) continue;
+ if (c==='l') state = FALSE3;
+ else
+ return emitError('Invalid false started with fa'+ c);
+ continue;
+
+ case FALSE3:
+ if (!c) continue;
+ if (c==='s') state = FALSE4;
+ else
+ return emitError('Invalid false started with fal'+ c);
+ continue;
+
+ case FALSE4:
+ if (!c) continue;
+ if (c==='e') {
+ emitValueOpen(false);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid false started with fals'+ c);
+ continue;
+
+ case NULL:
+ if (!c) continue;
+ if (c==='u') state = NULL2;
+ else
+ return emitError('Invalid null started with n'+ c);
+ continue;
+
+ case NULL2:
+ if (!c) continue;
+ if (c==='l') state = NULL3;
+ else
+ return emitError('Invalid null started with nu'+ c);
+ continue;
+
+ case NULL3:
+ if (!c) continue;
+ if(c==='l') {
+ emitValueOpen(null);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid null started with nul'+ c);
+ continue;
+
+ case NUMBER_DECIMAL_POINT:
+ if(c==='.') {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else
+ return emitError('Leading zero not followed by .');
+ continue;
+
+ case NUMBER_DIGIT:
+ if('0123456789'.indexOf(c) !== -1) numberNode += c;
+ else if (c==='.') {
+ if(numberNode.indexOf('.')!==-1)
+ return emitError('Invalid number has two dots');
+ numberNode += c;
+ } else if (c==='e' || c==='E') {
+ if(numberNode.indexOf('e')!==-1 ||
+ numberNode.indexOf('E')!==-1 )
+ return emitError('Invalid number has two exponential');
+ numberNode += c;
+ } else if (c==="+" || c==="-") {
+ if(!(p==='e' || p==='E'))
+ return emitError('Invalid symbol in number');
+ numberNode += c;
+ } else {
+ if (numberNode) {
+ emitValueOpen(parseFloat(numberNode));
+ emitValueClose();
+ numberNode = "";
+ }
+ i--; // go back one
+ state = stack.pop() || VALUE;
+ }
+ continue;
+
+ default:
+ return emitError("Unknown state: " + state);
+ }
+ }
+ if (position >= bufferCheckPosition)
+ checkBufferLength();
+ }
+}
+
+
+/**
+ * A bridge used to assign stateless functions to listen to clarinet.
+ *
+ * As well as the parameter from clarinet, each callback will also be passed
+ * the result of the last callback.
+ *
+ * This may also be used to clear all listeners by assigning zero handlers:
+ *
+ * ascentManager( clarinet, {} )
+ */
+function ascentManager(oboeBus, handlers){
+ "use strict";
+
+ var listenerId = {},
+ ascent;
+
+ function stateAfter(handler) {
+ return function(param){
+ ascent = handler( ascent, param);
+ }
+ }
+
+ for( var eventName in handlers ) {
+
+ oboeBus(eventName).on(stateAfter(handlers[eventName]), listenerId);
+ }
+
+ oboeBus(NODE_SWAP).on(function(newNode) {
+
+ var oldHead = head(ascent),
+ key = keyOf(oldHead),
+ ancestors = tail(ascent),
+ parentNode;
+
+ if( ancestors ) {
+ parentNode = nodeOf(head(ancestors));
+ parentNode[key] = newNode;
+ }
+ });
+
+ oboeBus(NODE_DROP).on(function() {
+
+ var oldHead = head(ascent),
+ key = keyOf(oldHead),
+ ancestors = tail(ascent),
+ parentNode;
+
+ if( ancestors ) {
+ parentNode = nodeOf(head(ancestors));
+
+ delete parentNode[key];
+ }
+ });
+
+ oboeBus(ABORTING).on(function(){
+
+ for( var eventName in handlers ) {
+ oboeBus(eventName).un(listenerId);
+ }
+ });
+}
+
+// based on gist https://gist.github.com/monsur/706839
+
+/**
+ * XmlHttpRequest's getAllResponseHeaders() method returns a string of response
+ * headers according to the format described here:
+ * http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method
+ * This method parses that string into a user-friendly key/value pair object.
+ */
+function parseResponseHeaders(headerStr) {
+ var headers = {};
+
+ headerStr && headerStr.split('\u000d\u000a')
+ .forEach(function(headerPair){
+
+ // Can't use split() here because it does the wrong thing
+ // if the header value has the string ": " in it.
+ var index = headerPair.indexOf('\u003a\u0020');
+
+ headers[headerPair.substring(0, index)]
+ = headerPair.substring(index + 2);
+ });
+
+ return headers;
+}
+
+/**
+ * Detect if a given URL is cross-origin in the scope of the
+ * current page.
+ *
+ * Browser only (since cross-origin has no meaning in Node.js)
+ *
+ * @param {Object} pageLocation - as in window.location
+ * @param {Object} ajaxHost - an object like window.location describing the
+ * origin of the url that we want to ajax in
+ */
+function isCrossOrigin(pageLocation, ajaxHost) {
+
+ /*
+ * NB: defaultPort only knows http and https.
+ * Returns undefined otherwise.
+ */
+ function defaultPort(protocol) {
+ return {'http:':80, 'https:':443}[protocol];
+ }
+
+ function portOf(location) {
+ // pageLocation should always have a protocol. ajaxHost if no port or
+ // protocol is specified, should use the port of the containing page
+
+ return location.port || defaultPort(location.protocol||pageLocation.protocol);
+ }
+
+ // if ajaxHost doesn't give a domain, port is the same as pageLocation
+ // it can't give a protocol but not a domain
+ // it can't give a port but not a domain
+
+ return !!( (ajaxHost.protocol && (ajaxHost.protocol != pageLocation.protocol)) ||
+ (ajaxHost.host && (ajaxHost.host != pageLocation.host)) ||
+ (ajaxHost.host && (portOf(ajaxHost) != portOf(pageLocation)))
+ );
+}
+
+/* turn any url into an object like window.location */
+function parseUrlOrigin(url) {
+ // url could be domain-relative
+ // url could give a domain
+
+ // cross origin means:
+ // same domain
+ // same port
+ // some protocol
+ // so, same everything up to the first (single) slash
+ // if such is given
+ //
+ // can ignore everything after that
+
+ var URL_HOST_PATTERN = /(\w+:)?(?:\/\/)([\w.-]+)?(?::(\d+))?\/?/,
+
+ // if no match, use an empty array so that
+ // subexpressions 1,2,3 are all undefined
+ // and will ultimately return all empty
+ // strings as the parse result:
+ urlHostMatch = URL_HOST_PATTERN.exec(url) || [];
+
+ return {
+ protocol: urlHostMatch[1] || '',
+ host: urlHostMatch[2] || '',
+ port: urlHostMatch[3] || ''
+ };
+}
+
+function httpTransport(){
+ return new XMLHttpRequest();
+}
+
+/**
+ * A wrapper around the browser XmlHttpRequest object that raises an
+ * event whenever a new part of the response is available.
+ *
+ * In older browsers progressive reading is impossible so all the
+ * content is given in a single call. For newer ones several events
+ * should be raised, allowing progressive interpretation of the response.
+ *
+ * @param {Function} oboeBus an event bus local to this Oboe instance
+ * @param {XMLHttpRequest} xhr the xhr to use as the transport. Under normal
+ * operation, will have been created using httpTransport() above
+ * but for tests a stub can be provided instead.
+ * @param {String} method one of 'GET' 'POST' 'PUT' 'PATCH' 'DELETE'
+ * @param {String} url the url to make a request to
+ * @param {String|Null} data some content to be sent with the request.
+ * Only valid if method is POST or PUT.
+ * @param {Object} [headers] the http request headers to send
+ * @param {boolean} withCredentials the XHR withCredentials property will be
+ * set to this value
+ */
+function streamingHttp(oboeBus, xhr, method, url, data, headers, withCredentials) {
+
+ "use strict";
+
+ var emitStreamData = oboeBus(STREAM_DATA).emit,
+ emitFail = oboeBus(FAIL_EVENT).emit,
+ numberOfCharsAlreadyGivenToCallback = 0,
+ stillToSendStartEvent = true;
+
+ // When an ABORTING message is put on the event bus abort
+ // the ajax request
+ oboeBus( ABORTING ).on( function(){
+
+ // if we keep the onreadystatechange while aborting the XHR gives
+ // a callback like a successful call so first remove this listener
+ // by assigning null:
+ xhr.onreadystatechange = null;
+
+ xhr.abort();
+ });
+
+ /**
+ * Handle input from the underlying xhr: either a state change,
+ * the progress event or the request being complete.
+ */
+ function handleProgress() {
+
+ var textSoFar = xhr.responseText,
+ newText = textSoFar.substr(numberOfCharsAlreadyGivenToCallback);
+
+
+ /* Raise the event for new text.
+
+ On older browsers, the new text is the whole response.
+ On newer/better ones, the fragment part that we got since
+ last progress. */
+
+ if( newText ) {
+ emitStreamData( newText );
+ }
+
+ numberOfCharsAlreadyGivenToCallback = len(textSoFar);
+ }
+
+
+ if('onprogress' in xhr){ // detect browser support for progressive delivery
+ xhr.onprogress = handleProgress;
+ }
+
+ xhr.onreadystatechange = function() {
+
+ function sendStartIfNotAlready() {
+ // Internet Explorer is very unreliable as to when xhr.status etc can
+ // be read so has to be protected with try/catch and tried again on
+ // the next readyState if it fails
+ try{
+ stillToSendStartEvent && oboeBus( HTTP_START ).emit(
+ xhr.status,
+ parseResponseHeaders(xhr.getAllResponseHeaders()) );
+ stillToSendStartEvent = false;
+ } catch(e){/* do nothing, will try again on next readyState*/}
+ }
+
+ switch( xhr.readyState ) {
+
+ case 2: // HEADERS_RECEIVED
+ case 3: // LOADING
+ return sendStartIfNotAlready();
+
+ case 4: // DONE
+ sendStartIfNotAlready(); // if xhr.status hasn't been available yet, it must be NOW, huh IE?
+
+ // is this a 2xx http code?
+ var successful = String(xhr.status)[0] == 2;
+
+ if( successful ) {
+ // In Chrome 29 (not 28) no onprogress is emitted when a response
+ // is complete before the onload. We need to always do handleInput
+ // in case we get the load but have not had a final progress event.
+ // This looks like a bug and may change in future but let's take
+ // the safest approach and assume we might not have received a
+ // progress event for each part of the response
+ handleProgress();
+
+ oboeBus(STREAM_END).emit();
+ } else {
+
+ emitFail( errorReport(
+ xhr.status,
+ xhr.responseText
+ ));
+ }
+ }
+ };
+
+ try{
+
+ xhr.open(method, url, true);
+
+ for( var headerName in headers ){
+ xhr.setRequestHeader(headerName, headers[headerName]);
+ }
+
+ if( !isCrossOrigin(window.location, parseUrlOrigin(url)) ) {
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ }
+
+ xhr.withCredentials = withCredentials;
+
+ xhr.send(data);
+
+ } catch( e ) {
+
+ // To keep a consistent interface with Node, we can't emit an event here.
+ // Node's streaming http adaptor receives the error as an asynchronous
+ // event rather than as an exception. If we emitted now, the Oboe user
+ // has had no chance to add a .fail listener so there is no way
+ // the event could be useful. For both these reasons defer the
+ // firing to the next JS frame.
+ window.setTimeout(
+ partialComplete(emitFail, errorReport(undefined, undefined, e))
+ , 0
+ );
+ }
+}
+
+var jsonPathSyntax = (function() {
+
+ var
+
+ /**
+ * Export a regular expression as a simple function by exposing just
+ * the Regex#exec. This allows regex tests to be used under the same
+ * interface as differently implemented tests, or for a user of the
+ * tests to not concern themselves with their implementation as regular
+ * expressions.
+ *
+ * This could also be expressed point-free as:
+ * Function.prototype.bind.bind(RegExp.prototype.exec),
+ *
+ * But that's far too confusing! (and not even smaller once minified
+ * and gzipped)
+ */
+ regexDescriptor = function regexDescriptor(regex) {
+ return regex.exec.bind(regex);
+ }
+
+ /**
+ * Join several regular expressions and express as a function.
+ * This allows the token patterns to reuse component regular expressions
+ * instead of being expressed in full using huge and confusing regular
+ * expressions.
+ */
+ , jsonPathClause = varArgs(function( componentRegexes ) {
+
+ // The regular expressions all start with ^ because we
+ // only want to find matches at the start of the
+ // JSONPath fragment we are inspecting
+ componentRegexes.unshift(/^/);
+
+ return regexDescriptor(
+ RegExp(
+ componentRegexes.map(attr('source')).join('')
+ )
+ );
+ })
+
+ , possiblyCapturing = /(\$?)/
+ , namedNode = /([\w-_]+|\*)/
+ , namePlaceholder = /()/
+ , nodeInArrayNotation = /\["([^"]+)"\]/
+ , numberedNodeInArrayNotation = /\[(\d+|\*)\]/
+ , fieldList = /{([\w ]*?)}/
+ , optionalFieldList = /(?:{([\w ]*?)})?/
+
+
+ // foo or *
+ , jsonPathNamedNodeInObjectNotation = jsonPathClause(
+ possiblyCapturing,
+ namedNode,
+ optionalFieldList
+ )
+
+ // ["foo"]
+ , jsonPathNamedNodeInArrayNotation = jsonPathClause(
+ possiblyCapturing,
+ nodeInArrayNotation,
+ optionalFieldList
+ )
+
+ // [2] or [*]
+ , jsonPathNumberedNodeInArrayNotation = jsonPathClause(
+ possiblyCapturing,
+ numberedNodeInArrayNotation,
+ optionalFieldList
+ )
+
+ // {a b c}
+ , jsonPathPureDuckTyping = jsonPathClause(
+ possiblyCapturing,
+ namePlaceholder,
+ fieldList
+ )
+
+ // ..
+ , jsonPathDoubleDot = jsonPathClause(/\.\./)
+
+ // .
+ , jsonPathDot = jsonPathClause(/\./)
+
+ // !
+ , jsonPathBang = jsonPathClause(
+ possiblyCapturing,
+ /!/
+ )
+
+ // nada!
+ , emptyString = jsonPathClause(/$/)
+
+ ;
+
+
+ /* We export only a single function. When called, this function injects
+ into another function the descriptors from above.
+ */
+ return function (fn){
+ return fn(
+ lazyUnion(
+ jsonPathNamedNodeInObjectNotation
+ , jsonPathNamedNodeInArrayNotation
+ , jsonPathNumberedNodeInArrayNotation
+ , jsonPathPureDuckTyping
+ )
+ , jsonPathDoubleDot
+ , jsonPathDot
+ , jsonPathBang
+ , emptyString
+ );
+ };
+
+}());
+/**
+ * Get a new key->node mapping
+ *
+ * @param {String|Number} key
+ * @param {Object|Array|String|Number|null} node a value found in the json
+ */
+function namedNode(key, node) {
+ return {key:key, node:node};
+}
+
+/** get the key of a namedNode */
+var keyOf = attr('key');
+
+/** get the node from a namedNode */
+var nodeOf = attr('node');
+/**
+ * This file provides various listeners which can be used to build up
+ * a changing ascent based on the callbacks provided by Clarinet. It listens
+ * to the low-level events from Clarinet and emits higher-level ones.
+ *
+ * The building up is stateless so to track a JSON file
+ * ascentManager.js is required to store the ascent state
+ * between calls.
+ */
+
+
+
+/**
+ * A special value to use in the path list to represent the path 'to' a root
+ * object (which doesn't really have any path). This prevents the need for
+ * special-casing detection of the root object and allows it to be treated
+ * like any other object. We might think of this as being similar to the
+ * 'unnamed root' domain ".", eg if I go to
+ * http://en.wikipedia.org./wiki/En/Main_page the dot after 'org' deliminates
+ * the unnamed root of the DNS.
+ *
+ * This is kept as an object to take advantage that in Javascript's OO objects
+ * are guaranteed to be distinct, therefore no other object can possibly clash
+ * with this one. Strings, numbers etc provide no such guarantee.
+ **/
+var ROOT_PATH = {};
+
+
+/**
+ * Create a new set of handlers for clarinet's events, bound to the emit
+ * function given.
+ */
+function incrementalContentBuilder( oboeBus ) {
+
+ var emitNodeOpened = oboeBus(NODE_OPENED).emit,
+ emitNodeClosed = oboeBus(NODE_CLOSED).emit,
+ emitRootOpened = oboeBus(ROOT_PATH_FOUND).emit,
+ emitRootClosed = oboeBus(ROOT_NODE_FOUND).emit;
+
+ function arrayIndicesAreKeys( possiblyInconsistentAscent, newDeepestNode) {
+
+ /* for values in arrays we aren't pre-warned of the coming paths
+ (Clarinet gives no call to onkey like it does for values in objects)
+ so if we are in an array we need to create this path ourselves. The
+ key will be len(parentNode) because array keys are always sequential
+ numbers. */
+
+ var parentNode = nodeOf( head( possiblyInconsistentAscent));
+
+ return isOfType( Array, parentNode)
+ ?
+ keyFound( possiblyInconsistentAscent,
+ len(parentNode),
+ newDeepestNode
+ )
+ :
+ // nothing needed, return unchanged
+ possiblyInconsistentAscent
+ ;
+ }
+
+ function nodeOpened( ascent, newDeepestNode ) {
+
+ if( !ascent ) {
+ // we discovered the root node,
+ emitRootOpened( newDeepestNode);
+
+ return keyFound( ascent, ROOT_PATH, newDeepestNode);
+ }
+
+ // we discovered a non-root node
+
+ var arrayConsistentAscent = arrayIndicesAreKeys( ascent, newDeepestNode),
+ ancestorBranches = tail( arrayConsistentAscent),
+ previouslyUnmappedName = keyOf( head( arrayConsistentAscent));
+
+ appendBuiltContent(
+ ancestorBranches,
+ previouslyUnmappedName,
+ newDeepestNode
+ );
+
+ return cons(
+ namedNode( previouslyUnmappedName, newDeepestNode ),
+ ancestorBranches
+ );
+ }
+
+
+ /**
+ * Add a new value to the object we are building up to represent the
+ * parsed JSON
+ */
+ function appendBuiltContent( ancestorBranches, key, node ){
+
+ nodeOf( head( ancestorBranches))[key] = node;
+ }
+
+
+ /**
+ * For when we find a new key in the json.
+ *
+ * @param {String|Number|Object} newDeepestName the key. If we are in an
+ * array will be a number, otherwise a string. May take the special
+ * value ROOT_PATH if the root node has just been found
+ *
+ * @param {String|Number|Object|Array|Null|undefined} [maybeNewDeepestNode]
+ * usually this won't be known so can be undefined. Can't use null
+ * to represent unknown because null is a valid value in JSON
+ **/
+ function keyFound(ascent, newDeepestName, maybeNewDeepestNode) {
+
+ if( ascent ) { // if not root
+
+ // If we have the key but (unless adding to an array) no known value
+ // yet. Put that key in the output but against no defined value:
+ appendBuiltContent( ascent, newDeepestName, maybeNewDeepestNode );
+ }
+
+ var ascentWithNewPath = cons(
+ namedNode( newDeepestName,
+ maybeNewDeepestNode),
+ ascent
+ );
+
+ emitNodeOpened( ascentWithNewPath);
+
+ return ascentWithNewPath;
+ }
+
+
+ /**
+ * For when the current node ends.
+ */
+ function nodeClosed( ascent ) {
+
+ emitNodeClosed( ascent);
+
+ return tail( ascent) ||
+ // If there are no nodes left in the ascent the root node
+ // just closed. Emit a special event for this:
+ emitRootClosed(nodeOf(head(ascent)));
+ }
+
+ var contentBuilderHandlers = {};
+ contentBuilderHandlers[SAX_VALUE_OPEN] = nodeOpened;
+ contentBuilderHandlers[SAX_VALUE_CLOSE] = nodeClosed;
+ contentBuilderHandlers[SAX_KEY] = keyFound;
+ return contentBuilderHandlers;
+}
+
+/**
+ * The jsonPath evaluator compiler used for Oboe.js.
+ *
+ * One function is exposed. This function takes a String JSONPath spec and
+ * returns a function to test candidate ascents for matches.
+ *
+ * String jsonPath -> (List ascent) -> Boolean|Object
+ *
+ * This file is coded in a pure functional style. That is, no function has
+ * side effects, every function evaluates to the same value for the same
+ * arguments and no variables are reassigned.
+ */
+// the call to jsonPathSyntax injects the token syntaxes that are needed
+// inside the compiler
+var jsonPathCompiler = jsonPathSyntax(function (pathNodeSyntax,
+ doubleDotSyntax,
+ dotSyntax,
+ bangSyntax,
+ emptySyntax ) {
+
+ var CAPTURING_INDEX = 1;
+ var NAME_INDEX = 2;
+ var FIELD_LIST_INDEX = 3;
+
+ var headKey = compose2(keyOf, head),
+ headNode = compose2(nodeOf, head);
+
+ /**
+ * Create an evaluator function for a named path node, expressed in the
+ * JSONPath like:
+ * foo
+ * ["bar"]
+ * [2]
+ */
+ function nameClause(previousExpr, detection ) {
+
+ var name = detection[NAME_INDEX],
+
+ matchesName = ( !name || name == '*' )
+ ? always
+ : function(ascent){return headKey(ascent) == name};
+
+
+ return lazyIntersection(matchesName, previousExpr);
+ }
+
+ /**
+ * Create an evaluator function for a a duck-typed node, expressed like:
+ *
+ * {spin, taste, colour}
+ * .particle{spin, taste, colour}
+ * *{spin, taste, colour}
+ */
+ function duckTypeClause(previousExpr, detection) {
+
+ var fieldListStr = detection[FIELD_LIST_INDEX];
+
+ if (!fieldListStr)
+ return previousExpr; // don't wrap at all, return given expr as-is
+
+ var hasAllrequiredFields = partialComplete(
+ hasAllProperties,
+ arrayAsList(fieldListStr.split(/\W+/))
+ ),
+
+ isMatch = compose2(
+ hasAllrequiredFields,
+ headNode
+ );
+
+ return lazyIntersection(isMatch, previousExpr);
+ }
+
+ /**
+ * Expression for $, returns the evaluator function
+ */
+ function capture( previousExpr, detection ) {
+
+ // extract meaning from the detection
+ var capturing = !!detection[CAPTURING_INDEX];
+
+ if (!capturing)
+ return previousExpr; // don't wrap at all, return given expr as-is
+
+ return lazyIntersection(previousExpr, head);
+
+ }
+
+ /**
+ * Create an evaluator function that moves onto the next item on the
+ * lists. This function is the place where the logic to move up a
+ * level in the ascent exists.
+ *
+ * Eg, for JSONPath ".foo" we need skip1(nameClause(always, [,'foo']))
+ */
+ function skip1(previousExpr) {
+
+
+ if( previousExpr == always ) {
+ /* If there is no previous expression this consume command
+ is at the start of the jsonPath.
+ Since JSONPath specifies what we'd like to find but not
+ necessarily everything leading down to it, when running
+ out of JSONPath to check against we default to true */
+ return always;
+ }
+
+ /** return true if the ascent we have contains only the JSON root,
+ * false otherwise
+ */
+ function notAtRoot(ascent){
+ return headKey(ascent) != ROOT_PATH;
+ }
+
+ return lazyIntersection(
+ /* If we're already at the root but there are more
+ expressions to satisfy, can't consume any more. No match.
+
+ This check is why none of the other exprs have to be able
+ to handle empty lists; skip1 is the only evaluator that
+ moves onto the next token and it refuses to do so once it
+ reaches the last item in the list. */
+ notAtRoot,
+
+ /* We are not at the root of the ascent yet.
+ Move to the next level of the ascent by handing only
+ the tail to the previous expression */
+ compose2(previousExpr, tail)
+ );
+
+ }
+
+ /**
+ * Create an evaluator function for the .. (double dot) token. Consumes
+ * zero or more levels of the ascent, the fewest that are required to find
+ * a match when given to previousExpr.
+ */
+ function skipMany(previousExpr) {
+
+ if( previousExpr == always ) {
+ /* If there is no previous expression this consume command
+ is at the start of the jsonPath.
+ Since JSONPath specifies what we'd like to find but not
+ necessarily everything leading down to it, when running
+ out of JSONPath to check against we default to true */
+ return always;
+ }
+
+ var
+ // In JSONPath .. is equivalent to !.. so if .. reaches the root
+ // the match has succeeded. Ie, we might write ..foo or !..foo
+ // and both should match identically.
+ terminalCaseWhenArrivingAtRoot = rootExpr(),
+ terminalCaseWhenPreviousExpressionIsSatisfied = previousExpr,
+ recursiveCase = skip1(function(ascent) {
+ return cases(ascent);
+ }),
+
+ cases = lazyUnion(
+ terminalCaseWhenArrivingAtRoot
+ , terminalCaseWhenPreviousExpressionIsSatisfied
+ , recursiveCase
+ );
+
+ return cases;
+ }
+
+ /**
+ * Generate an evaluator for ! - matches only the root element of the json
+ * and ignores any previous expressions since nothing may precede !.
+ */
+ function rootExpr() {
+
+ return function(ascent){
+ return headKey(ascent) == ROOT_PATH;
+ };
+ }
+
+ /**
+ * Generate a statement wrapper to sit around the outermost
+ * clause evaluator.
+ *
+ * Handles the case where the capturing is implicit because the JSONPath
+ * did not contain a '$' by returning the last node.
+ */
+ function statementExpr(lastClause) {
+
+ return function(ascent) {
+
+ // kick off the evaluation by passing through to the last clause
+ var exprMatch = lastClause(ascent);
+
+ return exprMatch === true ? head(ascent) : exprMatch;
+ };
+ }
+
+ /**
+ * For when a token has been found in the JSONPath input.
+ * Compiles the parser for that token and returns in combination with the
+ * parser already generated.
+ *
+ * @param {Function} exprs a list of the clause evaluator generators for
+ * the token that was found
+ * @param {Function} parserGeneratedSoFar the parser already found
+ * @param {Array} detection the match given by the regex engine when
+ * the feature was found
+ */
+ function expressionsReader( exprs, parserGeneratedSoFar, detection ) {
+
+ // if exprs is zero-length foldR will pass back the
+ // parserGeneratedSoFar as-is so we don't need to treat
+ // this as a special case
+
+ return foldR(
+ function( parserGeneratedSoFar, expr ){
+
+ return expr(parserGeneratedSoFar, detection);
+ },
+ parserGeneratedSoFar,
+ exprs
+ );
+
+ }
+
+ /**
+ * If jsonPath matches the given detector function, creates a function which
+ * evaluates against every clause in the clauseEvaluatorGenerators. The
+ * created function is propagated to the onSuccess function, along with
+ * the remaining unparsed JSONPath substring.
+ *
+ * The intended use is to create a clauseMatcher by filling in
+ * the first two arguments, thus providing a function that knows
+ * some syntax to match and what kind of generator to create if it
+ * finds it. The parameter list once completed is:
+ *
+ * (jsonPath, parserGeneratedSoFar, onSuccess)
+ *
+ * onSuccess may be compileJsonPathToFunction, to recursively continue
+ * parsing after finding a match or returnFoundParser to stop here.
+ */
+ function generateClauseReaderIfTokenFound (
+
+ tokenDetector, clauseEvaluatorGenerators,
+
+ jsonPath, parserGeneratedSoFar, onSuccess) {
+
+ var detected = tokenDetector(jsonPath);
+
+ if(detected) {
+ var compiledParser = expressionsReader(
+ clauseEvaluatorGenerators,
+ parserGeneratedSoFar,
+ detected
+ ),
+
+ remainingUnparsedJsonPath = jsonPath.substr(len(detected[0]));
+
+ return onSuccess(remainingUnparsedJsonPath, compiledParser);
+ }
+ }
+
+ /**
+ * Partially completes generateClauseReaderIfTokenFound above.
+ */
+ function clauseMatcher(tokenDetector, exprs) {
+
+ return partialComplete(
+ generateClauseReaderIfTokenFound,
+ tokenDetector,
+ exprs
+ );
+ }
+
+ /**
+ * clauseForJsonPath is a function which attempts to match against
+ * several clause matchers in order until one matches. If non match the
+ * jsonPath expression is invalid and an error is thrown.
+ *
+ * The parameter list is the same as a single clauseMatcher:
+ *
+ * (jsonPath, parserGeneratedSoFar, onSuccess)
+ */
+ var clauseForJsonPath = lazyUnion(
+
+ clauseMatcher(pathNodeSyntax , list( capture,
+ duckTypeClause,
+ nameClause,
+ skip1 ))
+
+ , clauseMatcher(doubleDotSyntax , list( skipMany))
+
+ // dot is a separator only (like whitespace in other languages) but
+ // rather than make it a special case, use an empty list of
+ // expressions when this token is found
+ , clauseMatcher(dotSyntax , list() )
+
+ , clauseMatcher(bangSyntax , list( capture,
+ rootExpr))
+
+ , clauseMatcher(emptySyntax , list( statementExpr))
+
+ , function (jsonPath) {
+ throw Error('"' + jsonPath + '" could not be tokenised')
+ }
+ );
+
+
+ /**
+ * One of two possible values for the onSuccess argument of
+ * generateClauseReaderIfTokenFound.
+ *
+ * When this function is used, generateClauseReaderIfTokenFound simply
+ * returns the compiledParser that it made, regardless of if there is
+ * any remaining jsonPath to be compiled.
+ */
+ function returnFoundParser(_remainingJsonPath, compiledParser){
+ return compiledParser
+ }
+
+ /**
+ * Recursively compile a JSONPath expression.
+ *
+ * This function serves as one of two possible values for the onSuccess
+ * argument of generateClauseReaderIfTokenFound, meaning continue to
+ * recursively compile. Otherwise, returnFoundParser is given and
+ * compilation terminates.
+ */
+ function compileJsonPathToFunction( uncompiledJsonPath,
+ parserGeneratedSoFar ) {
+
+ /**
+ * On finding a match, if there is remaining text to be compiled
+ * we want to either continue parsing using a recursive call to
+ * compileJsonPathToFunction. Otherwise, we want to stop and return
+ * the parser that we have found so far.
+ */
+ var onFind = uncompiledJsonPath
+ ? compileJsonPathToFunction
+ : returnFoundParser;
+
+ return clauseForJsonPath(
+ uncompiledJsonPath,
+ parserGeneratedSoFar,
+ onFind
+ );
+ }
+
+ /**
+ * This is the function that we expose to the rest of the library.
+ */
+ return function(jsonPath){
+
+ try {
+ // Kick off the recursive parsing of the jsonPath
+ return compileJsonPathToFunction(jsonPath, always);
+
+ } catch( e ) {
+ throw Error( 'Could not compile "' + jsonPath +
+ '" because ' + e.message
+ );
+ }
+ }
+
+});
+
+/**
+ * A pub/sub which is responsible for a single event type. A
+ * multi-event type event bus is created by pubSub by collecting
+ * several of these.
+ *
+ * @param {String} eventType
+ * the name of the events managed by this singleEventPubSub
+ * @param {singleEventPubSub} [newListener]
+ * place to notify of new listeners
+ * @param {singleEventPubSub} [removeListener]
+ * place to notify of when listeners are removed
+ */
+function singleEventPubSub(eventType, newListener, removeListener){
+
+ /** we are optimised for emitting events over firing them.
+ * As well as the tuple list which stores event ids and
+ * listeners there is a list with just the listeners which
+ * can be iterated more quickly when we are emitting
+ */
+ var listenerTupleList,
+ listenerList;
+
+ function hasId(id){
+ return function(tuple) {
+ return tuple.id == id;
+ };
+ }
+
+ return {
+
+ /**
+ * @param {Function} listener
+ * @param {*} listenerId
+ * an id that this listener can later by removed by.
+ * Can be of any type, to be compared to other ids using ==
+ */
+ on:function( listener, listenerId ) {
+
+ var tuple = {
+ listener: listener
+ , id: listenerId || listener // when no id is given use the
+ // listener function as the id
+ };
+
+ if( newListener ) {
+ newListener.emit(eventType, listener, tuple.id);
+ }
+
+ listenerTupleList = cons( tuple, listenerTupleList );
+ listenerList = cons( listener, listenerList );
+
+ return this; // chaining
+ },
+
+ emit:function () {
+ applyEach( listenerList, arguments );
+ },
+
+ un: function( listenerId ) {
+
+ var removed;
+
+ listenerTupleList = without(
+ listenerTupleList,
+ hasId(listenerId),
+ function(tuple){
+ removed = tuple;
+ }
+ );
+
+ if( removed ) {
+ listenerList = without( listenerList, function(listener){
+ return listener == removed.listener;
+ });
+
+ if( removeListener ) {
+ removeListener.emit(eventType, removed.listener, removed.id);
+ }
+ }
+ },
+
+ listeners: function(){
+ // differs from Node EventEmitter: returns list, not array
+ return listenerList;
+ },
+
+ hasListener: function(listenerId){
+ var test = listenerId? hasId(listenerId) : always;
+
+ return defined(first( test, listenerTupleList));
+ }
+ };
+}
+
+/**
+ * pubSub is a curried interface for listening to and emitting
+ * events.
+ *
+ * If we get a bus:
+ *
+ * var bus = pubSub();
+ *
+ * We can listen to event 'foo' like:
+ *
+ * bus('foo').on(myCallback)
+ *
+ * And emit event foo like:
+ *
+ * bus('foo').emit()
+ *
+ * or, with a parameter:
+ *
+ * bus('foo').emit('bar')
+ *
+ * All functions can be cached and don't need to be
+ * bound. Ie:
+ *
+ * var fooEmitter = bus('foo').emit
+ * fooEmitter('bar'); // emit an event
+ * fooEmitter('baz'); // emit another
+ *
+ * There's also an uncurried[1] shortcut for .emit and .on:
+ *
+ * bus.on('foo', callback)
+ * bus.emit('foo', 'bar')
+ *
+ * [1]: http://zvon.org/other/haskell/Outputprelude/uncurry_f.html
+ */
+function pubSub(){
+
+ var singles = {},
+ newListener = newSingle('newListener'),
+ removeListener = newSingle('removeListener');
+
+ function newSingle(eventName) {
+ return singles[eventName] = singleEventPubSub(
+ eventName,
+ newListener,
+ removeListener
+ );
+ }
+
+ /** pubSub instances are functions */
+ function pubSubInstance( eventName ){
+
+ return singles[eventName] || newSingle( eventName );
+ }
+
+ // add convenience EventEmitter-style uncurried form of 'emit' and 'on'
+ ['emit', 'on', 'un'].forEach(function(methodName){
+
+ pubSubInstance[methodName] = varArgs(function(eventName, parameters){
+ apply( parameters, pubSubInstance( eventName )[methodName]);
+ });
+ });
+
+ return pubSubInstance;
+}
+
+/**
+ * This file declares some constants to use as names for event types.
+ */
+
+var // the events which are never exported are kept as
+ // the smallest possible representation, in numbers:
+ _S = 1,
+
+ // fired whenever a new node starts in the JSON stream:
+ NODE_OPENED = _S++,
+
+ // fired whenever a node closes in the JSON stream:
+ NODE_CLOSED = _S++,
+
+ // called if a .node callback returns a value -
+ NODE_SWAP = _S++,
+ NODE_DROP = _S++,
+
+ FAIL_EVENT = 'fail',
+
+ ROOT_NODE_FOUND = _S++,
+ ROOT_PATH_FOUND = _S++,
+
+ HTTP_START = 'start',
+ STREAM_DATA = 'data',
+ STREAM_END = 'end',
+ ABORTING = _S++,
+
+ // SAX events butchered from Clarinet
+ SAX_KEY = _S++,
+ SAX_VALUE_OPEN = _S++,
+ SAX_VALUE_CLOSE = _S++;
+
+function errorReport(statusCode, body, error) {
+ try{
+ var jsonBody = JSON.parse(body);
+ }catch(e){}
+
+ return {
+ statusCode:statusCode,
+ body:body,
+ jsonBody:jsonBody,
+ thrown:error
+ };
+}
+
+/**
+ * The pattern adaptor listens for newListener and removeListener
+ * events. When patterns are added or removed it compiles the JSONPath
+ * and wires them up.
+ *
+ * When nodes and paths are found it emits the fully-qualified match
+ * events with parameters ready to ship to the outside world
+ */
+
+function patternAdapter(oboeBus, jsonPathCompiler) {
+
+ var predicateEventMap = {
+ node:oboeBus(NODE_CLOSED)
+ , path:oboeBus(NODE_OPENED)
+ };
+
+ function emitMatchingNode(emitMatch, node, ascent) {
+
+ /*
+ We're now calling to the outside world where Lisp-style
+ lists will not be familiar. Convert to standard arrays.
+
+ Also, reverse the order because it is more common to
+ list paths "root to leaf" than "leaf to root" */
+ var descent = reverseList(ascent);
+
+ emitMatch(
+ node,
+
+ // To make a path, strip off the last item which is the special
+ // ROOT_PATH token for the 'path' to the root node
+ listAsArray(tail(map(keyOf,descent))), // path
+ listAsArray(map(nodeOf, descent)) // ancestors
+ );
+ }
+
+ /*
+ * Set up the catching of events such as NODE_CLOSED and NODE_OPENED and, if
+ * matching the specified pattern, propagate to pattern-match events such as
+ * oboeBus('node:!')
+ *
+ *
+ *
+ * @param {Function} predicateEvent
+ * either oboeBus(NODE_CLOSED) or oboeBus(NODE_OPENED).
+ * @param {Function} compiledJsonPath
+ */
+ function addUnderlyingListener( fullEventName, predicateEvent, compiledJsonPath ){
+
+ var emitMatch = oboeBus(fullEventName).emit;
+
+ predicateEvent.on( function (ascent) {
+
+ var maybeMatchingMapping = compiledJsonPath(ascent);
+
+ /* Possible values for maybeMatchingMapping are now:
+
+ false:
+ we did not match
+
+ an object/array/string/number/null:
+ we matched and have the node that matched.
+ Because nulls are valid json values this can be null.
+
+ undefined:
+ we matched but don't have the matching node yet.
+ ie, we know there is an upcoming node that matches but we
+ can't say anything else about it.
+ */
+ if (maybeMatchingMapping !== false) {
+
+ emitMatchingNode(
+ emitMatch,
+ nodeOf(maybeMatchingMapping),
+ ascent
+ );
+ }
+ }, fullEventName);
+
+ oboeBus('removeListener').on( function(removedEventName){
+
+ // if the fully qualified match event listener is later removed, clean up
+ // by removing the underlying listener if it was the last using that pattern:
+
+ if( removedEventName == fullEventName ) {
+
+ if( !oboeBus(removedEventName).listeners( )) {
+ predicateEvent.un( fullEventName );
+ }
+ }
+ });
+ }
+
+ oboeBus('newListener').on( function(fullEventName){
+
+ var match = /(node|path):(.*)/.exec(fullEventName);
+
+ if( match ) {
+ var predicateEvent = predicateEventMap[match[1]];
+
+ if( !predicateEvent.hasListener( fullEventName) ) {
+
+ addUnderlyingListener(
+ fullEventName,
+ predicateEvent,
+ jsonPathCompiler( match[2] )
+ );
+ }
+ }
+ })
+
+}
+
+/**
+ * The instance API is the thing that is returned when oboe() is called.
+ * it allows:
+ *
+ * - listeners for various events to be added and removed
+ * - the http response header/headers to be read
+ */
+function instanceApi(oboeBus, contentSource){
+
+ var oboeApi,
+ fullyQualifiedNamePattern = /^(node|path):./,
+ rootNodeFinishedEvent = oboeBus(ROOT_NODE_FOUND),
+ emitNodeDrop = oboeBus(NODE_DROP).emit,
+ emitNodeSwap = oboeBus(NODE_SWAP).emit,
+
+ /**
+ * Add any kind of listener that the instance api exposes
+ */
+ addListener = varArgs(function( eventId, parameters ){
+
+ if( oboeApi[eventId] ) {
+
+ // for events added as .on(event, callback), if there is a
+ // .event() equivalent with special behaviour , pass through
+ // to that:
+ apply(parameters, oboeApi[eventId]);
+ } else {
+
+ // we have a standard Node.js EventEmitter 2-argument call.
+ // The first parameter is the listener.
+ var event = oboeBus(eventId),
+ listener = parameters[0];
+
+ if( fullyQualifiedNamePattern.test(eventId) ) {
+
+ // allow fully-qualified node/path listeners
+ // to be added
+ addForgettableCallback(event, listener);
+ } else {
+
+ // the event has no special handling, pass through
+ // directly onto the event bus:
+ event.on( listener);
+ }
+ }
+
+ return oboeApi; // chaining
+ }),
+
+ /**
+ * Remove any kind of listener that the instance api exposes
+ */
+ removeListener = function( eventId, p2, p3 ){
+
+ if( eventId == 'done' ) {
+
+ rootNodeFinishedEvent.un(p2);
+
+ } else if( eventId == 'node' || eventId == 'path' ) {
+
+ // allow removal of node and path
+ oboeBus.un(eventId + ':' + p2, p3);
+ } else {
+
+ // we have a standard Node.js EventEmitter 2-argument call.
+ // The second parameter is the listener. This may be a call
+ // to remove a fully-qualified node/path listener but requires
+ // no special handling
+ var listener = p2;
+
+ oboeBus(eventId).un(listener);
+ }
+
+ return oboeApi; // chaining
+ };
+
+ /**
+ * Add a callback, wrapped in a try/catch so as to not break the
+ * execution of Oboe if an exception is thrown (fail events are
+ * fired instead)
+ *
+ * The callback is used as the listener id so that it can later be
+ * removed using .un(callback)
+ */
+ function addProtectedCallback(eventName, callback) {
+ oboeBus(eventName).on(protectedCallback(callback), callback);
+ return oboeApi; // chaining
+ }
+
+ /**
+ * Add a callback where, if .forget() is called during the callback's
+ * execution, the callback will be de-registered
+ */
+ function addForgettableCallback(event, callback, listenerId) {
+
+ // listenerId is optional and if not given, the original
+ // callback will be used
+ listenerId = listenerId || callback;
+
+ var safeCallback = protectedCallback(callback);
+
+ event.on( function() {
+
+ var discard = false;
+
+ oboeApi.forget = function(){
+ discard = true;
+ };
+
+ apply( arguments, safeCallback );
+
+ delete oboeApi.forget;
+
+ if( discard ) {
+ event.un(listenerId);
+ }
+ }, listenerId);
+
+ return oboeApi; // chaining
+ }
+
+ /**
+ * wrap a callback so that if it throws, Oboe.js doesn't crash but instead
+ * throw the error in another event loop
+ */
+ function protectedCallback( callback ) {
+ return function() {
+ try{
+ return callback.apply(oboeApi, arguments);
+ }catch(e) {
+ setTimeout(function() {
+ throw new Error(e.message);
+ });
+ }
+ }
+ }
+
+ /**
+ * Return the fully qualified event for when a pattern matches
+ * either a node or a path
+ *
+ * @param type {String} either 'node' or 'path'
+ */
+ function fullyQualifiedPatternMatchEvent(type, pattern) {
+ return oboeBus(type + ':' + pattern);
+ }
+
+ function wrapCallbackToSwapNodeIfSomethingReturned( callback ) {
+ return function() {
+ var returnValueFromCallback = callback.apply(this, arguments);
+
+ if( defined(returnValueFromCallback) ) {
+
+ if( returnValueFromCallback == oboe.drop ) {
+ emitNodeDrop();
+ } else {
+ emitNodeSwap(returnValueFromCallback);
+ }
+ }
+ }
+ }
+
+ function addSingleNodeOrPathListener(eventId, pattern, callback) {
+
+ var effectiveCallback;
+
+ if( eventId == 'node' ) {
+ effectiveCallback = wrapCallbackToSwapNodeIfSomethingReturned(callback);
+ } else {
+ effectiveCallback = callback;
+ }
+
+ addForgettableCallback(
+ fullyQualifiedPatternMatchEvent(eventId, pattern),
+ effectiveCallback,
+ callback
+ );
+ }
+
+ /**
+ * Add several listeners at a time, from a map
+ */
+ function addMultipleNodeOrPathListeners(eventId, listenerMap) {
+
+ for( var pattern in listenerMap ) {
+ addSingleNodeOrPathListener(eventId, pattern, listenerMap[pattern]);
+ }
+ }
+
+ /**
+ * implementation behind .onPath() and .onNode()
+ */
+ function addNodeOrPathListenerApi( eventId, jsonPathOrListenerMap, callback ){
+
+ if( isString(jsonPathOrListenerMap) ) {
+ addSingleNodeOrPathListener(eventId, jsonPathOrListenerMap, callback);
+
+ } else {
+ addMultipleNodeOrPathListeners(eventId, jsonPathOrListenerMap);
+ }
+
+ return oboeApi; // chaining
+ }
+
+
+ // some interface methods are only filled in after we receive
+ // values and are noops before that:
+ oboeBus(ROOT_PATH_FOUND).on( function(rootNode) {
+ oboeApi.root = functor(rootNode);
+ });
+
+ /**
+ * When content starts make the headers readable through the
+ * instance API
+ */
+ oboeBus(HTTP_START).on( function(_statusCode, headers) {
+
+ oboeApi.header = function(name) {
+ return name ? headers[name]
+ : headers
+ ;
+ }
+ });
+
+ /**
+ * Construct and return the public API of the Oboe instance to be
+ * returned to the calling application
+ */
+ return oboeApi = {
+ on : addListener,
+ addListener : addListener,
+ removeListener : removeListener,
+ emit : oboeBus.emit,
+
+ node : partialComplete(addNodeOrPathListenerApi, 'node'),
+ path : partialComplete(addNodeOrPathListenerApi, 'path'),
+
+ done : partialComplete(addForgettableCallback, rootNodeFinishedEvent),
+ start : partialComplete(addProtectedCallback, HTTP_START ),
+
+ // fail doesn't use protectedCallback because
+ // could lead to non-terminating loops
+ fail : oboeBus(FAIL_EVENT).on,
+
+ // public api calling abort fires the ABORTING event
+ abort : oboeBus(ABORTING).emit,
+
+ // for manually feeding data
+ write : oboeBus(STREAM_DATA).emit,
+ finish : oboeBus(STREAM_END).emit,
+
+ // initially return nothing for header and root
+ header : noop,
+ root : noop,
+
+ source : contentSource
+ };
+}
+
+/**
+ * This file sits just behind the API which is used to attain a new
+ * Oboe instance. It creates the new components that are required
+ * and introduces them to each other.
+ */
+
+function wire (httpMethodName, contentSource, body, headers, withCredentials){
+
+ var oboeBus = pubSub();
+
+ // Wire the input stream in if we are given a content source.
+ // This will usually be the case. If not, the instance created
+ // will have to be passed content from an external source.
+
+ if( contentSource ) {
+
+ streamingHttp( oboeBus,
+ httpTransport(),
+ httpMethodName,
+ contentSource,
+ body,
+ headers,
+ withCredentials
+ );
+ }
+
+ clarinet(oboeBus);
+
+ ascentManager(oboeBus, incrementalContentBuilder(oboeBus));
+
+ patternAdapter(oboeBus, jsonPathCompiler);
+
+ return instanceApi(oboeBus, contentSource);
+}
+
+function applyDefaults( passthrough, url, httpMethodName, body, headers, withCredentials, cached ){
+
+ headers = headers ?
+ // Shallow-clone the headers array. This allows it to be
+ // modified without side effects to the caller. We don't
+ // want to change objects that the user passes in.
+ JSON.parse(JSON.stringify(headers))
+ : {};
+
+ if( body ) {
+ if( !isString(body) ) {
+
+ // If the body is not a string, stringify it. This allows objects to
+ // be given which will be sent as JSON.
+ body = JSON.stringify(body);
+
+ // Default Content-Type to JSON unless given otherwise.
+ headers['Content-Type'] = headers['Content-Type'] || 'application/json';
+ }
+ } else {
+ body = null;
+ }
+
+ // support cache busting like jQuery.ajax({cache:false})
+ function modifiedUrl(baseUrl, cached) {
+
+ if( cached === false ) {
+
+ if( baseUrl.indexOf('?') == -1 ) {
+ baseUrl += '?';
+ } else {
+ baseUrl += '&';
+ }
+
+ baseUrl += '_=' + new Date().getTime();
+ }
+ return baseUrl;
+ }
+
+ return passthrough( httpMethodName || 'GET', modifiedUrl(url, cached), body, headers, withCredentials || false );
+}
+
+// export public API
+function oboe(arg1) {
+
+ // We use duck-typing to detect if the parameter given is a stream, with the
+ // below list of parameters.
+ // Unpipe and unshift would normally be present on a stream but this breaks
+ // compatibility with Request streams.
+ // See https://github.com/jimhigson/oboe.js/issues/65
+
+ var nodeStreamMethodNames = list('resume', 'pause', 'pipe'),
+ isStream = partialComplete(
+ hasAllProperties
+ , nodeStreamMethodNames
+ );
+
+ if( arg1 ) {
+ if (isStream(arg1) || isString(arg1)) {
+
+ // simple version for GETs. Signature is:
+ // oboe( url )
+ // or, under node:
+ // oboe( readableStream )
+ return applyDefaults(
+ wire,
+ arg1 // url
+ );
+
+ } else {
+
+ // method signature is:
+ // oboe({method:m, url:u, body:b, headers:{...}})
+
+ return applyDefaults(
+ wire,
+ arg1.url,
+ arg1.method,
+ arg1.body,
+ arg1.headers,
+ arg1.withCredentials,
+ arg1.cached
+ );
+
+ }
+ } else {
+ // wire up a no-AJAX, no-stream Oboe. Will have to have content
+ // fed in externally and using .emit.
+ return wire();
+ }
+}
+
+/* oboe.drop is a special value. If a node callback returns this value the
+ parsed node is deleted from the JSON
+ */
+oboe.drop = function() {
+ return oboe.drop;
+};
+
+
+ if ( typeof define === "function" && define.amd ) {
+ define( "oboe", [], function () { return oboe; } );
+ } else if (typeof exports === 'object') {
+ module.exports = oboe;
+ } else {
+ window.oboe = oboe;
+ }
+})((function(){
+ // Access to the window object throws an exception in HTML5 web workers so
+ // point it to "self" if it runs in a web worker
+ try {
+ return window;
+ } catch (e) {
+ return self;
+ }
+ }()), Object, Array, Error, JSON);
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-browser.min.js b/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-browser.min.js
new file mode 100644
index 00000000000..89d5b88a9e0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-browser.min.js
@@ -0,0 +1 @@
+!function(a,b,c,d,e,f){function g(a,b){return function(){return a.call(this,b.apply(this,arguments))}}function h(a){return function(b){return b[a]}}function i(a,b){return b.apply(f,a)}function j(a){var b=a.length-1,d=c.prototype.slice;if(0==b)return function(){return a.call(this,d.call(arguments))};if(1==b)return function(){return a.call(this,arguments[0],d.call(arguments,1))};var e=c(a.length);return function(){for(var c=0;b>c;c++)e[c]=arguments[c];return e[b]=d.call(arguments,b),a.apply(this,e)}}function k(a){return function(b,c){return a(c,b)}}function l(a,b){return function(c){return a(c)&&b(c)}}function m(){}function n(){return!0}function o(a){return function(){return a}}function p(a,b){return b&&b.constructor===a}function q(a){return a!==f}function r(a,c){return c instanceof b&&y(function(a){return a in c},a)}function s(a,b){return[a,b]}function t(a){return A(a.reduce(k(s),X))}function u(a){return w(function(a,b){return a.unshift(b),a},[],a)}function v(a,b){return b?s(a(Y(b)),v(a,Z(b))):X}function w(a,b,c){return c?a(w(a,b,Z(c)),Y(c)):b}function x(a,b,c){function d(a,c){return a?b(Y(a))?(c(Y(a)),Z(a)):s(Y(a),d(Z(a),c)):X}return d(a,c||m)}function y(a,b){return!b||a(Y(b))&&y(a,Z(b))}function z(a,b){a&&(Y(a).apply(null,b),z(Z(a),b))}function A(a){function b(a,c){return a?b(Z(a),s(Y(a),c)):c}return b(a,X)}function B(a,b){return b&&(a(Y(b))?Y(b):B(a,Z(b)))}function C(a){"use strict";function b(){var a=0;P!==f&&P.length>p&&(c("Max buffer length exceeded: textNode"),a=Math.max(a,P.length)),Q.length>p&&(c("Max buffer length exceeded: numberNode"),a=Math.max(a,Q.length)),O=p-a+Y}function c(a){P!==f&&(m(P),n(),P=f),i=d(a+"\nLn: "+$+"\nCol: "+Z+"\nChr: "+j),o(N(f,f,i))}function e(){return T==s?(m({}),n(),void(S=!0)):((T!==t||0!==X)&&c("Unexpected end"),P!==f&&(m(P),n(),P=f),void(S=!0))}function g(a){return"\r"==a||"\n"==a||" "==a||" "==a}function h(a){if(!i){if(S)return c("Cannot write after close");var d=0;for(j=a[0];j&&(k=j,j=a[d++]);)switch(Y++,"\n"==j?($++,Z=0):Z++,T){case s:if("{"===j)T=u;else if("["===j)T=w;else if(!g(j))return c("Non-whitespace before {[.");continue;case z:case u:if(g(j))continue;if(T===z)U.push(A);else{if("}"===j){m({}),n(),T=U.pop()||t;continue}U.push(v)}if('"'!==j)return c('Malformed object key should start with " ');T=y;continue;case A:case v:if(g(j))continue;if(":"===j)T===v?(U.push(v),P!==f&&(m({}),l(P),P=f),X++):P!==f&&(l(P),P=f),T=t;else if("}"===j)P!==f&&(m(P),n(),P=f),n(),X--,T=U.pop()||t;else{if(","!==j)return c("Bad object");T===v&&U.push(v),P!==f&&(m(P),n(),P=f),T=z}continue;case w:case t:if(g(j))continue;if(T===w){if(m([]),X++,T=t,"]"===j){n(),X--,T=U.pop()||t;continue}U.push(x)}if('"'===j)T=y;else if("{"===j)T=u;else if("["===j)T=w;else if("t"===j)T=B;else if("f"===j)T=E;else if("n"===j)T=I;else if("-"===j)Q+=j;else if("0"===j)Q+=j,T=M;else{if(-1==="123456789".indexOf(j))return c("Bad value");Q+=j,T=M}continue;case x:if(","===j)U.push(x),P!==f&&(m(P),n(),P=f),T=t;else{if("]"!==j){if(g(j))continue;return c("Bad array")}P!==f&&(m(P),n(),P=f),n(),X--,T=U.pop()||t}continue;case y:P===f&&(P="");var e=d-1;a:for(;;){for(;W>0;)if(V+=j,j=a.charAt(d++),4===W?(P+=String.fromCharCode(parseInt(V,16)),W=0,e=d-1):W++,!j)break a;if('"'===j&&!R){T=U.pop()||t,P+=a.substring(e,d-1);break}if("\\"===j&&!R&&(R=!0,P+=a.substring(e,d-1),j=a.charAt(d++),!j))break;if(R){if(R=!1,"n"===j?P+="\n":"r"===j?P+="\r":"t"===j?P+=" ":"f"===j?P+="\f":"b"===j?P+="\b":"u"===j?(W=1,V=""):P+=j,j=a.charAt(d++),e=d-1,j)continue;break}q.lastIndex=d;var h=q.exec(a);if(!h){d=a.length+1,P+=a.substring(e,d-1);break}if(d=h.index+1,j=a.charAt(h.index),!j){P+=a.substring(e,d-1);break}}continue;case B:if(!j)continue;if("r"!==j)return c("Invalid true started with t"+j);T=C;continue;case C:if(!j)continue;if("u"!==j)return c("Invalid true started with tr"+j);T=D;continue;case D:if(!j)continue;if("e"!==j)return c("Invalid true started with tru"+j);m(!0),n(),T=U.pop()||t;continue;case E:if(!j)continue;if("a"!==j)return c("Invalid false started with f"+j);T=F;continue;case F:if(!j)continue;if("l"!==j)return c("Invalid false started with fa"+j);T=G;continue;case G:if(!j)continue;if("s"!==j)return c("Invalid false started with fal"+j);T=H;continue;case H:if(!j)continue;if("e"!==j)return c("Invalid false started with fals"+j);m(!1),n(),T=U.pop()||t;continue;case I:if(!j)continue;if("u"!==j)return c("Invalid null started with n"+j);T=J;continue;case J:if(!j)continue;if("l"!==j)return c("Invalid null started with nu"+j);T=K;continue;case K:if(!j)continue;if("l"!==j)return c("Invalid null started with nul"+j);m(null),n(),T=U.pop()||t;continue;case L:if("."!==j)return c("Leading zero not followed by .");Q+=j,T=M;continue;case M:if(-1!=="0123456789".indexOf(j))Q+=j;else if("."===j){if(-1!==Q.indexOf("."))return c("Invalid number has two dots");Q+=j}else if("e"===j||"E"===j){if(-1!==Q.indexOf("e")||-1!==Q.indexOf("E"))return c("Invalid number has two exponential");Q+=j}else if("+"===j||"-"===j){if("e"!==k&&"E"!==k)return c("Invalid symbol in number");Q+=j}else Q&&(m(parseFloat(Q)),n(),Q=""),d--,T=U.pop()||t;continue;default:return c("Unknown state: "+T)}Y>=O&&b()}}var i,j,k,l=a(qa).emit,m=a(ra).emit,n=a(sa).emit,o=a(ja).emit,p=65536,q=/[\\"\n]/g,r=0,s=r++,t=r++,u=r++,v=r++,w=r++,x=r++,y=r++,z=r++,A=r++,B=r++,C=r++,D=r++,E=r++,F=r++,G=r++,H=r++,I=r++,J=r++,K=r++,L=r++,M=r,O=p,P=f,Q="",R=!1,S=!1,T=s,U=[],V=null,W=0,X=0,Y=0,Z=0,$=1;a(na).on(h),a(oa).on(e)}function D(a,b){"use strict";function c(a){return function(b){d=a(d,b)}}var d,e={};for(var f in b)a(f).on(c(b[f]),e);a(ha).on(function(a){var b,c=Y(d),e=aa(c),f=Z(d);f&&(b=ba(Y(f)),b[e]=a)}),a(ia).on(function(){var a,b=Y(d),c=aa(b),e=Z(d);e&&(a=ba(Y(e)),delete a[c])}),a(pa).on(function(){for(var c in b)a(c).un(e)})}function E(a){var b={};return a&&a.split("\r\n").forEach(function(a){var c=a.indexOf(": ");b[a.substring(0,c)]=a.substring(c+2)}),b}function F(a,b){function c(a){return{"http:":80,"https:":443}[a]}function d(b){return b.port||c(b.protocol||a.protocol)}return!!(b.protocol&&b.protocol!=a.protocol||b.host&&b.host!=a.host||b.host&&d(b)!=d(a))}function G(a){var b=/(\w+:)?(?:\/\/)([\w.-]+)?(?::(\d+))?\/?/,c=b.exec(a)||[];return{protocol:c[1]||"",host:c[2]||"",port:c[3]||""}}function H(){return new XMLHttpRequest}function I(b,c,d,e,g,h,i){"use strict";function j(){var a=c.responseText,b=a.substr(m);b&&k(b),m=V(a)}var k=b(na).emit,l=b(ja).emit,m=0,n=!0;b(pa).on(function(){c.onreadystatechange=null,c.abort()}),"onprogress"in c&&(c.onprogress=j),c.onreadystatechange=function(){function a(){try{n&&b(ma).emit(c.status,E(c.getAllResponseHeaders())),n=!1}catch(a){}}switch(c.readyState){case 2:case 3:return a();case 4:a();var d=2==String(c.status)[0];d?(j(),b(oa).emit()):l(N(c.status,c.responseText))}};try{c.open(d,e,!0);for(var o in h)c.setRequestHeader(o,h[o]);F(a.location,G(e))||c.setRequestHeader("X-Requested-With","XMLHttpRequest"),c.withCredentials=i,c.send(g)}catch(p){a.setTimeout(T(l,N(f,f,p)),0)}}function J(a,b){return{key:a,node:b}}function K(a){function b(a,b){var d=ba(Y(a));return p(c,d)?f(a,V(d),b):a}function d(a,c){if(!a)return j(c),f(a,ca,c);var d=b(a,c),g=Z(d),h=aa(Y(d));return e(g,h,c),s(J(h,c),g)}function e(a,b,c){ba(Y(a))[b]=c}function f(a,b,c){a&&e(a,b,c);var d=s(J(b,c),a);return h(d),d}function g(a){return i(a),Z(a)||k(ba(Y(a)))}var h=a(fa).emit,i=a(ga).emit,j=a(la).emit,k=a(ka).emit,l={};return l[ra]=d,l[sa]=g,l[qa]=f,l}function L(a,b,c){function d(a){return function(b){return b.id==a}}var e,f;return{on:function(c,d){var g={listener:c,id:d||c};return b&&b.emit(a,c,g.id),e=s(g,e),f=s(c,f),this},emit:function(){z(f,arguments)},un:function(b){var g;e=x(e,d(b),function(a){g=a}),g&&(f=x(f,function(a){return a==g.listener}),c&&c.emit(a,g.listener,g.id))},listeners:function(){return f},hasListener:function(a){var b=a?d(a):n;return q(B(b,e))}}}function M(){function a(a){return c[a]=L(a,d,e)}function b(b){return c[b]||a(b)}var c={},d=a("newListener"),e=a("removeListener");return["emit","on","un"].forEach(function(a){b[a]=j(function(c,d){i(d,b(c)[a])})}),b}function N(a,b,c){try{var d=e.parse(b)}catch(f){}return{statusCode:a,body:b,jsonBody:d,thrown:c}}function O(a,b){function c(a,b,c){var d=A(c);a(b,u(Z(v(aa,d))),u(v(ba,d)))}function d(b,d,e){var f=a(b).emit;d.on(function(a){var b=e(a);b!==!1&&c(f,ba(b),a)},b),a("removeListener").on(function(c){c==b&&(a(c).listeners()||d.un(b))})}var e={node:a(ga),path:a(fa)};a("newListener").on(function(a){var c=/(node|path):(.*)/.exec(a);if(c){var f=e[c[1]];f.hasListener(a)||d(a,f,b(c[2]))}})}function P(a,b){function c(b,c){return a(b).on(f(c),c),p}function e(a,b,c){c=c||b;var d=f(b);return a.on(function(){var b=!1;p.forget=function(){b=!0},i(arguments,d),delete p.forget,b&&a.un(c)},c),p}function f(a){return function(){try{return a.apply(p,arguments)}catch(b){setTimeout(function(){throw new d(b.message)})}}}function g(b,c){return a(b+":"+c)}function h(a){return function(){var b=a.apply(this,arguments);q(b)&&(b==S.drop?t():u(b))}}function k(a,b,c){var d;d="node"==a?h(c):c,e(g(a,b),d,c)}function l(a,b){for(var c in b)k(a,c,b[c])}function n(a,b,c){return W(b)?k(a,b,c):l(a,b),p}var p,r=/^(node|path):./,s=a(ka),t=a(ia).emit,u=a(ha).emit,v=j(function(b,c){if(p[b])i(c,p[b]);else{var d=a(b),f=c[0];r.test(b)?e(d,f):d.on(f)}return p}),w=function(b,c,d){if("done"==b)s.un(c);else if("node"==b||"path"==b)a.un(b+":"+c,d);else{var e=c;a(b).un(e)}return p};return a(la).on(function(a){p.root=o(a)}),a(ma).on(function(a,b){p.header=function(a){return a?b[a]:b}}),p={on:v,addListener:v,removeListener:w,emit:a.emit,node:T(n,"node"),path:T(n,"path"),done:T(e,s),start:T(c,ma),fail:a(ja).on,abort:a(pa).emit,header:m,root:m,source:b}}function Q(a,b,c,d,e){var f=M();return b&&I(f,H(),a,b,c,d,e),C(f),D(f,K(f)),O(f,da),P(f,b)}function R(a,b,c,d,f,g,h){function i(a,b){return b===!1&&(a+=-1==a.indexOf("?")?"?":"&",a+="_="+(new Date).getTime()),a}return f=f?e.parse(e.stringify(f)):{},d?W(d)||(d=e.stringify(d),f["Content-Type"]=f["Content-Type"]||"application/json"):d=null,a(c||"GET",i(b,h),d,f,g||!1)}function S(a){var b=$("resume","pause","pipe"),c=T(r,b);return a?c(a)||W(a)?R(Q,a):R(Q,a.url,a.method,a.body,a.headers,a.withCredentials,a.cached):Q()}var T=j(function(a,b){var c=b.length;return j(function(d){for(var e=0;e<d.length;e++)b[c+e]=d[e];return b.length=c+d.length,a.apply(this,b)})}),U=(j(function(a){function b(a,b){return[i(a,b)]}var c=t(a);return j(function(a){return w(b,a,c)[0]})}),j(function(a){return j(function(b){for(var c,d=0;d<V(a);d++)if(c=i(b,a[d]))return c})})),V=h("length"),W=T(p,String),X=null,Y=h(0),Z=h(1),$=j(t),_=function(){var a=function(a){return a.exec.bind(a)},b=j(function(b){return b.unshift(/^/),a(RegExp(b.map(h("source")).join("")))}),c=/(\$?)/,d=/([\w-_]+|\*)/,e=/()/,f=/\["([^"]+)"\]/,g=/\[(\d+|\*)\]/,i=/{([\w ]*?)}/,k=/(?:{([\w ]*?)})?/,l=b(c,d,k),m=b(c,f,k),n=b(c,g,k),o=b(c,e,i),p=b(/\.\./),q=b(/\./),r=b(c,/!/),s=b(/$/);return function(a){return a(U(l,m,n,o),p,q,r,s)}}(),aa=h("key"),ba=h("node"),ca={},da=_(function(a,b,c,e,f){function h(a,b){var c=b[z],d=c&&"*"!=c?function(a){return B(a)==c}:n;return l(d,a)}function i(a,b){var c=b[A];if(!c)return a;var d=T(r,t(c.split(/\W+/))),e=g(d,C);return l(e,a)}function j(a,b){var c=!!b[y];return c?l(a,Y):a}function k(a){function b(a){return B(a)!=ca}return a==n?n:l(b,g(a,Z))}function m(a){if(a==n)return n;var b=o(),c=a,d=k(function(a){return e(a)}),e=U(b,c,d);return e}function o(){return function(a){return B(a)==ca}}function p(a){return function(b){var c=a(b);return c===!0?Y(b):c}}function q(a,b,c){return w(function(a,b){return b(a,c)},b,a)}function s(a,b,c,d,e){var f=a(c);if(f){var g=q(b,d,f),h=c.substr(V(f[0]));return e(h,g)}}function u(a,b){return T(s,a,b)}function v(a,b){return b}function x(a,b){var c=a?x:v;return D(a,b,c)}var y=1,z=2,A=3,B=g(aa,Y),C=g(ba,Y),D=U(u(a,$(j,i,h,k)),u(b,$(m)),u(c,$()),u(e,$(j,o)),u(f,$(p)),function(a){throw d('"'+a+'" could not be tokenised')});return function(a){try{return x(a,n)}catch(b){throw d('Could not compile "'+a+'" because '+b.message)}}}),ea=1,fa=ea++,ga=ea++,ha=ea++,ia=ea++,ja="fail",ka=ea++,la=ea++,ma="start",na="data",oa="end",pa=ea++,qa=ea++,ra=ea++,sa=ea++;S.drop=function(){return S.drop},"function"==typeof define&&define.amd?define("oboe",[],function(){return S}):"object"==typeof exports?module.exports=S:a.oboe=S}(function(){try{return window}catch(a){return self}}(),Object,Array,Error,JSON); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-node.js b/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-node.js
new file mode 100644
index 00000000000..f8fbb15895b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/dist/oboe-node.js
@@ -0,0 +1,2587 @@
+// this file is the concatenation of several js files. See http://github.com/jimhigson/oboe.js
+// for the unconcatenated source
+
+module.exports = (function () {
+
+ // v2.1.3-2-gc85b5c4
+
+/*
+
+Copyright (c) 2013, Jim Higson
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+/**
+ * Partially complete a function.
+ *
+ * var add3 = partialComplete( function add(a,b){return a+b}, 3 );
+ *
+ * add3(4) // gives 7
+ *
+ * function wrap(left, right, cen){return left + " " + cen + " " + right;}
+ *
+ * var pirateGreeting = partialComplete( wrap , "I'm", ", a mighty pirate!" );
+ *
+ * pirateGreeting("Guybrush Threepwood");
+ * // gives "I'm Guybrush Threepwood, a mighty pirate!"
+ */
+var partialComplete = varArgs(function( fn, args ) {
+
+ // this isn't the shortest way to write this but it does
+ // avoid creating a new array each time to pass to fn.apply,
+ // otherwise could just call boundArgs.concat(callArgs)
+
+ var numBoundArgs = args.length;
+
+ return varArgs(function( callArgs ) {
+
+ for (var i = 0; i < callArgs.length; i++) {
+ args[numBoundArgs + i] = callArgs[i];
+ }
+
+ args.length = numBoundArgs + callArgs.length;
+
+ return fn.apply(this, args);
+ });
+ }),
+
+/**
+ * Compose zero or more functions:
+ *
+ * compose(f1, f2, f3)(x) = f1(f2(f3(x))))
+ *
+ * The last (inner-most) function may take more than one parameter:
+ *
+ * compose(f1, f2, f3)(x,y) = f1(f2(f3(x,y))))
+ */
+ compose = varArgs(function(fns) {
+
+ var fnsList = arrayAsList(fns);
+
+ function next(params, curFn) {
+ return [apply(params, curFn)];
+ }
+
+ return varArgs(function(startParams){
+
+ return foldR(next, startParams, fnsList)[0];
+ });
+ });
+
+/**
+ * A more optimised version of compose that takes exactly two functions
+ * @param f1
+ * @param f2
+ */
+function compose2(f1, f2){
+ return function(){
+ return f1.call(this,f2.apply(this,arguments));
+ }
+}
+
+/**
+ * Generic form for a function to get a property from an object
+ *
+ * var o = {
+ * foo:'bar'
+ * }
+ *
+ * var getFoo = attr('foo')
+ *
+ * fetFoo(o) // returns 'bar'
+ *
+ * @param {String} key the property name
+ */
+function attr(key) {
+ return function(o) { return o[key]; };
+}
+
+/**
+ * Call a list of functions with the same args until one returns a
+ * truthy result. Similar to the || operator.
+ *
+ * So:
+ * lazyUnion([f1,f2,f3 ... fn])( p1, p2 ... pn )
+ *
+ * Is equivalent to:
+ * apply([p1, p2 ... pn], f1) ||
+ * apply([p1, p2 ... pn], f2) ||
+ * apply([p1, p2 ... pn], f3) ... apply(fn, [p1, p2 ... pn])
+ *
+ * @returns the first return value that is given that is truthy.
+ */
+ var lazyUnion = varArgs(function(fns) {
+
+ return varArgs(function(params){
+
+ var maybeValue;
+
+ for (var i = 0; i < len(fns); i++) {
+
+ maybeValue = apply(params, fns[i]);
+
+ if( maybeValue ) {
+ return maybeValue;
+ }
+ }
+ });
+ });
+
+/**
+ * This file declares various pieces of functional programming.
+ *
+ * This isn't a general purpose functional library, to keep things small it
+ * has just the parts useful for Oboe.js.
+ */
+
+
+/**
+ * Call a single function with the given arguments array.
+ * Basically, a functional-style version of the OO-style Function#apply for
+ * when we don't care about the context ('this') of the call.
+ *
+ * The order of arguments allows partial completion of the arguments array
+ */
+function apply(args, fn) {
+ return fn.apply(undefined, args);
+}
+
+/**
+ * Define variable argument functions but cut out all that tedious messing about
+ * with the arguments object. Delivers the variable-length part of the arguments
+ * list as an array.
+ *
+ * Eg:
+ *
+ * var myFunction = varArgs(
+ * function( fixedArgument, otherFixedArgument, variableNumberOfArguments ){
+ * console.log( variableNumberOfArguments );
+ * }
+ * )
+ *
+ * myFunction('a', 'b', 1, 2, 3); // logs [1,2,3]
+ *
+ * var myOtherFunction = varArgs(function( variableNumberOfArguments ){
+ * console.log( variableNumberOfArguments );
+ * })
+ *
+ * myFunction(1, 2, 3); // logs [1,2,3]
+ *
+ */
+function varArgs(fn){
+
+ var numberOfFixedArguments = fn.length -1,
+ slice = Array.prototype.slice;
+
+
+ if( numberOfFixedArguments == 0 ) {
+ // an optimised case for when there are no fixed args:
+
+ return function(){
+ return fn.call(this, slice.call(arguments));
+ }
+
+ } else if( numberOfFixedArguments == 1 ) {
+ // an optimised case for when there are is one fixed args:
+
+ return function(){
+ return fn.call(this, arguments[0], slice.call(arguments, 1));
+ }
+ }
+
+ // general case
+
+ // we know how many arguments fn will always take. Create a
+ // fixed-size array to hold that many, to be re-used on
+ // every call to the returned function
+ var argsHolder = Array(fn.length);
+
+ return function(){
+
+ for (var i = 0; i < numberOfFixedArguments; i++) {
+ argsHolder[i] = arguments[i];
+ }
+
+ argsHolder[numberOfFixedArguments] =
+ slice.call(arguments, numberOfFixedArguments);
+
+ return fn.apply( this, argsHolder);
+ }
+}
+
+
+/**
+ * Swap the order of parameters to a binary function
+ *
+ * A bit like this flip: http://zvon.org/other/haskell/Outputprelude/flip_f.html
+ */
+function flip(fn){
+ return function(a, b){
+ return fn(b,a);
+ }
+}
+
+
+/**
+ * Create a function which is the intersection of two other functions.
+ *
+ * Like the && operator, if the first is truthy, the second is never called,
+ * otherwise the return value from the second is returned.
+ */
+function lazyIntersection(fn1, fn2) {
+
+ return function (param) {
+
+ return fn1(param) && fn2(param);
+ };
+}
+
+/**
+ * A function which does nothing
+ */
+function noop(){}
+
+/**
+ * A function which is always happy
+ */
+function always(){return true}
+
+/**
+ * Create a function which always returns the same
+ * value
+ *
+ * var return3 = functor(3);
+ *
+ * return3() // gives 3
+ * return3() // still gives 3
+ * return3() // will always give 3
+ */
+function functor(val){
+ return function(){
+ return val;
+ }
+}
+
+/**
+ * This file defines some loosely associated syntactic sugar for
+ * Javascript programming
+ */
+
+
+/**
+ * Returns true if the given candidate is of type T
+ */
+function isOfType(T, maybeSomething){
+ return maybeSomething && maybeSomething.constructor === T;
+}
+
+var len = attr('length'),
+ isString = partialComplete(isOfType, String);
+
+/**
+ * I don't like saying this:
+ *
+ * foo !=== undefined
+ *
+ * because of the double-negative. I find this:
+ *
+ * defined(foo)
+ *
+ * easier to read.
+ */
+function defined( value ) {
+ return value !== undefined;
+}
+
+/**
+ * Returns true if object o has a key named like every property in
+ * the properties array. Will give false if any are missing, or if o
+ * is not an object.
+ */
+function hasAllProperties(fieldList, o) {
+
+ return (o instanceof Object)
+ &&
+ all(function (field) {
+ return (field in o);
+ }, fieldList);
+}
+/**
+ * Like cons in Lisp
+ */
+function cons(x, xs) {
+
+ /* Internally lists are linked 2-element Javascript arrays.
+
+ Ideally the return here would be Object.freeze([x,xs])
+ so that bugs related to mutation are found fast.
+ However, cons is right on the critical path for
+ performance and this slows oboe-mark down by
+ ~25%. Under theoretical future JS engines that freeze more
+ efficiently (possibly even use immutability to
+ run faster) this should be considered for
+ restoration.
+ */
+
+ return [x,xs];
+}
+
+/**
+ * The empty list
+ */
+var emptyList = null,
+
+/**
+ * Get the head of a list.
+ *
+ * Ie, head(cons(a,b)) = a
+ */
+ head = attr(0),
+
+/**
+ * Get the tail of a list.
+ *
+ * Ie, tail(cons(a,b)) = b
+ */
+ tail = attr(1);
+
+
+/**
+ * Converts an array to a list
+ *
+ * asList([a,b,c])
+ *
+ * is equivalent to:
+ *
+ * cons(a, cons(b, cons(c, emptyList)))
+ **/
+function arrayAsList(inputArray){
+
+ return reverseList(
+ inputArray.reduce(
+ flip(cons),
+ emptyList
+ )
+ );
+}
+
+/**
+ * A varargs version of arrayAsList. Works a bit like list
+ * in LISP.
+ *
+ * list(a,b,c)
+ *
+ * is equivalent to:
+ *
+ * cons(a, cons(b, cons(c, emptyList)))
+ */
+var list = varArgs(arrayAsList);
+
+/**
+ * Convert a list back to a js native array
+ */
+function listAsArray(list){
+
+ return foldR( function(arraySoFar, listItem){
+
+ arraySoFar.unshift(listItem);
+ return arraySoFar;
+
+ }, [], list );
+
+}
+
+/**
+ * Map a function over a list
+ */
+function map(fn, list) {
+
+ return list
+ ? cons(fn(head(list)), map(fn,tail(list)))
+ : emptyList
+ ;
+}
+
+/**
+ * foldR implementation. Reduce a list down to a single value.
+ *
+ * @pram {Function} fn (rightEval, curVal) -> result
+ */
+function foldR(fn, startValue, list) {
+
+ return list
+ ? fn(foldR(fn, startValue, tail(list)), head(list))
+ : startValue
+ ;
+}
+
+/**
+ * foldR implementation. Reduce a list down to a single value.
+ *
+ * @pram {Function} fn (rightEval, curVal) -> result
+ */
+function foldR1(fn, list) {
+
+ return tail(list)
+ ? fn(foldR1(fn, tail(list)), head(list))
+ : head(list)
+ ;
+}
+
+
+/**
+ * Return a list like the one given but with the first instance equal
+ * to item removed
+ */
+function without(list, test, removedFn) {
+
+ return withoutInner(list, removedFn || noop);
+
+ function withoutInner(subList, removedFn) {
+ return subList
+ ? ( test(head(subList))
+ ? (removedFn(head(subList)), tail(subList))
+ : cons(head(subList), withoutInner(tail(subList), removedFn))
+ )
+ : emptyList
+ ;
+ }
+}
+
+/**
+ * Returns true if the given function holds for every item in
+ * the list, false otherwise
+ */
+function all(fn, list) {
+
+ return !list ||
+ ( fn(head(list)) && all(fn, tail(list)) );
+}
+
+/**
+ * Call every function in a list of functions with the same arguments
+ *
+ * This doesn't make any sense if we're doing pure functional because
+ * it doesn't return anything. Hence, this is only really useful if the
+ * functions being called have side-effects.
+ */
+function applyEach(fnList, args) {
+
+ if( fnList ) {
+ head(fnList).apply(null, args);
+
+ applyEach(tail(fnList), args);
+ }
+}
+
+/**
+ * Reverse the order of a list
+ */
+function reverseList(list){
+
+ // js re-implementation of 3rd solution from:
+ // http://www.haskell.org/haskellwiki/99_questions/Solutions/5
+ function reverseInner( list, reversedAlready ) {
+ if( !list ) {
+ return reversedAlready;
+ }
+
+ return reverseInner(tail(list), cons(head(list), reversedAlready))
+ }
+
+ return reverseInner(list, emptyList);
+}
+
+function first(test, list) {
+ return list &&
+ (test(head(list))
+ ? head(list)
+ : first(test,tail(list)));
+}
+
+/*
+ This is a slightly hacked-up browser only version of clarinet
+
+ * some features removed to help keep browser Oboe under
+ the 5k micro-library limit
+ * plug directly into event bus
+
+ For the original go here:
+ https://github.com/dscape/clarinet
+
+ We receive the events:
+ STREAM_DATA
+ STREAM_END
+
+ We emit the events:
+ SAX_KEY
+ SAX_VALUE_OPEN
+ SAX_VALUE_CLOSE
+ FAIL_EVENT
+ */
+
+function clarinet(eventBus) {
+ "use strict";
+
+ var
+ // shortcut some events on the bus
+ emitSaxKey = eventBus(SAX_KEY).emit,
+ emitValueOpen = eventBus(SAX_VALUE_OPEN).emit,
+ emitValueClose = eventBus(SAX_VALUE_CLOSE).emit,
+ emitFail = eventBus(FAIL_EVENT).emit,
+
+ MAX_BUFFER_LENGTH = 64 * 1024
+ , stringTokenPattern = /[\\"\n]/g
+ , _n = 0
+
+ // states
+ , BEGIN = _n++
+ , VALUE = _n++ // general stuff
+ , OPEN_OBJECT = _n++ // {
+ , CLOSE_OBJECT = _n++ // }
+ , OPEN_ARRAY = _n++ // [
+ , CLOSE_ARRAY = _n++ // ]
+ , STRING = _n++ // ""
+ , OPEN_KEY = _n++ // , "a"
+ , CLOSE_KEY = _n++ // :
+ , TRUE = _n++ // r
+ , TRUE2 = _n++ // u
+ , TRUE3 = _n++ // e
+ , FALSE = _n++ // a
+ , FALSE2 = _n++ // l
+ , FALSE3 = _n++ // s
+ , FALSE4 = _n++ // e
+ , NULL = _n++ // u
+ , NULL2 = _n++ // l
+ , NULL3 = _n++ // l
+ , NUMBER_DECIMAL_POINT = _n++ // .
+ , NUMBER_DIGIT = _n // [0-9]
+
+ // setup initial parser values
+ , bufferCheckPosition = MAX_BUFFER_LENGTH
+ , latestError
+ , c
+ , p
+ , textNode = undefined
+ , numberNode = ""
+ , slashed = false
+ , closed = false
+ , state = BEGIN
+ , stack = []
+ , unicodeS = null
+ , unicodeI = 0
+ , depth = 0
+ , position = 0
+ , column = 0 //mostly for error reporting
+ , line = 1
+ ;
+
+ function checkBufferLength () {
+
+ var maxActual = 0;
+
+ if (textNode !== undefined && textNode.length > MAX_BUFFER_LENGTH) {
+ emitError("Max buffer length exceeded: textNode");
+ maxActual = Math.max(maxActual, textNode.length);
+ }
+ if (numberNode.length > MAX_BUFFER_LENGTH) {
+ emitError("Max buffer length exceeded: numberNode");
+ maxActual = Math.max(maxActual, numberNode.length);
+ }
+
+ bufferCheckPosition = (MAX_BUFFER_LENGTH - maxActual)
+ + position;
+ }
+
+ eventBus(STREAM_DATA).on(handleData);
+
+ /* At the end of the http content close the clarinet
+ This will provide an error if the total content provided was not
+ valid json, ie if not all arrays, objects and Strings closed properly */
+ eventBus(STREAM_END).on(handleStreamEnd);
+
+ function emitError (errorString) {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+
+ latestError = Error(errorString + "\nLn: "+line+
+ "\nCol: "+column+
+ "\nChr: "+c);
+
+ emitFail(errorReport(undefined, undefined, latestError));
+ }
+
+ function handleStreamEnd() {
+ if( state == BEGIN ) {
+ // Handle the case where the stream closes without ever receiving
+ // any input. This isn't an error - response bodies can be blank,
+ // particularly for 204 http responses
+
+ // Because of how Oboe is currently implemented, we parse a
+ // completely empty stream as containing an empty object.
+ // This is because Oboe's done event is only fired when the
+ // root object of the JSON stream closes.
+
+ // This should be decoupled and attached instead to the input stream
+ // from the http (or whatever) resource ending.
+ // If this decoupling could happen the SAX parser could simply emit
+ // zero events on a completely empty input.
+ emitValueOpen({});
+ emitValueClose();
+
+ closed = true;
+ return;
+ }
+
+ if (state !== VALUE || depth !== 0)
+ emitError("Unexpected end");
+
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+
+ closed = true;
+ }
+
+ function whitespace(c){
+ return c == '\r' || c == '\n' || c == ' ' || c == '\t';
+ }
+
+ function handleData (chunk) {
+
+ // this used to throw the error but inside Oboe we will have already
+ // gotten the error when it was emitted. The important thing is to
+ // not continue with the parse.
+ if (latestError)
+ return;
+
+ if (closed) {
+ return emitError("Cannot write after close");
+ }
+
+ var i = 0;
+ c = chunk[0];
+
+ while (c) {
+ p = c;
+ c = chunk[i++];
+ if(!c) break;
+
+ position ++;
+ if (c == "\n") {
+ line ++;
+ column = 0;
+ } else column ++;
+ switch (state) {
+
+ case BEGIN:
+ if (c === "{") state = OPEN_OBJECT;
+ else if (c === "[") state = OPEN_ARRAY;
+ else if (!whitespace(c))
+ return emitError("Non-whitespace before {[.");
+ continue;
+
+ case OPEN_KEY:
+ case OPEN_OBJECT:
+ if (whitespace(c)) continue;
+ if(state === OPEN_KEY) stack.push(CLOSE_KEY);
+ else {
+ if(c === '}') {
+ emitValueOpen({});
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ continue;
+ } else stack.push(CLOSE_OBJECT);
+ }
+ if(c === '"')
+ state = STRING;
+ else
+ return emitError("Malformed object key should start with \" ");
+ continue;
+
+ case CLOSE_KEY:
+ case CLOSE_OBJECT:
+ if (whitespace(c)) continue;
+
+ if(c===':') {
+ if(state === CLOSE_OBJECT) {
+ stack.push(CLOSE_OBJECT);
+
+ if (textNode !== undefined) {
+ // was previously (in upstream Clarinet) one event
+ // - object open came with the text of the first
+ emitValueOpen({});
+ emitSaxKey(textNode);
+ textNode = undefined;
+ }
+ depth++;
+ } else {
+ if (textNode !== undefined) {
+ emitSaxKey(textNode);
+ textNode = undefined;
+ }
+ }
+ state = VALUE;
+ } else if (c==='}') {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ } else if(c===',') {
+ if(state === CLOSE_OBJECT)
+ stack.push(CLOSE_OBJECT);
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ state = OPEN_KEY;
+ } else
+ return emitError('Bad object');
+ continue;
+
+ case OPEN_ARRAY: // after an array there always a value
+ case VALUE:
+ if (whitespace(c)) continue;
+ if(state===OPEN_ARRAY) {
+ emitValueOpen([]);
+ depth++;
+ state = VALUE;
+ if(c === ']') {
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ continue;
+ } else {
+ stack.push(CLOSE_ARRAY);
+ }
+ }
+ if(c === '"') state = STRING;
+ else if(c === '{') state = OPEN_OBJECT;
+ else if(c === '[') state = OPEN_ARRAY;
+ else if(c === 't') state = TRUE;
+ else if(c === 'f') state = FALSE;
+ else if(c === 'n') state = NULL;
+ else if(c === '-') { // keep and continue
+ numberNode += c;
+ } else if(c==='0') {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else if('123456789'.indexOf(c) !== -1) {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else
+ return emitError("Bad value");
+ continue;
+
+ case CLOSE_ARRAY:
+ if(c===',') {
+ stack.push(CLOSE_ARRAY);
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ state = VALUE;
+ } else if (c===']') {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ } else if (whitespace(c))
+ continue;
+ else
+ return emitError('Bad array');
+ continue;
+
+ case STRING:
+ if (textNode === undefined) {
+ textNode = "";
+ }
+
+ // thanks thejh, this is an about 50% performance improvement.
+ var starti = i-1;
+
+ STRING_BIGLOOP: while (true) {
+
+ // zero means "no unicode active". 1-4 mean "parse some more". end after 4.
+ while (unicodeI > 0) {
+ unicodeS += c;
+ c = chunk.charAt(i++);
+ if (unicodeI === 4) {
+ // TODO this might be slow? well, probably not used too often anyway
+ textNode += String.fromCharCode(parseInt(unicodeS, 16));
+ unicodeI = 0;
+ starti = i-1;
+ } else {
+ unicodeI++;
+ }
+ // we can just break here: no stuff we skipped that still has to be sliced out or so
+ if (!c) break STRING_BIGLOOP;
+ }
+ if (c === '"' && !slashed) {
+ state = stack.pop() || VALUE;
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ if (c === '\\' && !slashed) {
+ slashed = true;
+ textNode += chunk.substring(starti, i-1);
+ c = chunk.charAt(i++);
+ if (!c) break;
+ }
+ if (slashed) {
+ slashed = false;
+ if (c === 'n') { textNode += '\n'; }
+ else if (c === 'r') { textNode += '\r'; }
+ else if (c === 't') { textNode += '\t'; }
+ else if (c === 'f') { textNode += '\f'; }
+ else if (c === 'b') { textNode += '\b'; }
+ else if (c === 'u') {
+ // \uxxxx. meh!
+ unicodeI = 1;
+ unicodeS = '';
+ } else {
+ textNode += c;
+ }
+ c = chunk.charAt(i++);
+ starti = i-1;
+ if (!c) break;
+ else continue;
+ }
+
+ stringTokenPattern.lastIndex = i;
+ var reResult = stringTokenPattern.exec(chunk);
+ if (!reResult) {
+ i = chunk.length+1;
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ i = reResult.index+1;
+ c = chunk.charAt(reResult.index);
+ if (!c) {
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ }
+ continue;
+
+ case TRUE:
+ if (!c) continue; // strange buffers
+ if (c==='r') state = TRUE2;
+ else
+ return emitError( 'Invalid true started with t'+ c);
+ continue;
+
+ case TRUE2:
+ if (!c) continue;
+ if (c==='u') state = TRUE3;
+ else
+ return emitError('Invalid true started with tr'+ c);
+ continue;
+
+ case TRUE3:
+ if (!c) continue;
+ if(c==='e') {
+ emitValueOpen(true);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid true started with tru'+ c);
+ continue;
+
+ case FALSE:
+ if (!c) continue;
+ if (c==='a') state = FALSE2;
+ else
+ return emitError('Invalid false started with f'+ c);
+ continue;
+
+ case FALSE2:
+ if (!c) continue;
+ if (c==='l') state = FALSE3;
+ else
+ return emitError('Invalid false started with fa'+ c);
+ continue;
+
+ case FALSE3:
+ if (!c) continue;
+ if (c==='s') state = FALSE4;
+ else
+ return emitError('Invalid false started with fal'+ c);
+ continue;
+
+ case FALSE4:
+ if (!c) continue;
+ if (c==='e') {
+ emitValueOpen(false);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid false started with fals'+ c);
+ continue;
+
+ case NULL:
+ if (!c) continue;
+ if (c==='u') state = NULL2;
+ else
+ return emitError('Invalid null started with n'+ c);
+ continue;
+
+ case NULL2:
+ if (!c) continue;
+ if (c==='l') state = NULL3;
+ else
+ return emitError('Invalid null started with nu'+ c);
+ continue;
+
+ case NULL3:
+ if (!c) continue;
+ if(c==='l') {
+ emitValueOpen(null);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid null started with nul'+ c);
+ continue;
+
+ case NUMBER_DECIMAL_POINT:
+ if(c==='.') {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else
+ return emitError('Leading zero not followed by .');
+ continue;
+
+ case NUMBER_DIGIT:
+ if('0123456789'.indexOf(c) !== -1) numberNode += c;
+ else if (c==='.') {
+ if(numberNode.indexOf('.')!==-1)
+ return emitError('Invalid number has two dots');
+ numberNode += c;
+ } else if (c==='e' || c==='E') {
+ if(numberNode.indexOf('e')!==-1 ||
+ numberNode.indexOf('E')!==-1 )
+ return emitError('Invalid number has two exponential');
+ numberNode += c;
+ } else if (c==="+" || c==="-") {
+ if(!(p==='e' || p==='E'))
+ return emitError('Invalid symbol in number');
+ numberNode += c;
+ } else {
+ if (numberNode) {
+ emitValueOpen(parseFloat(numberNode));
+ emitValueClose();
+ numberNode = "";
+ }
+ i--; // go back one
+ state = stack.pop() || VALUE;
+ }
+ continue;
+
+ default:
+ return emitError("Unknown state: " + state);
+ }
+ }
+ if (position >= bufferCheckPosition)
+ checkBufferLength();
+ }
+}
+
+
+/**
+ * A bridge used to assign stateless functions to listen to clarinet.
+ *
+ * As well as the parameter from clarinet, each callback will also be passed
+ * the result of the last callback.
+ *
+ * This may also be used to clear all listeners by assigning zero handlers:
+ *
+ * ascentManager( clarinet, {} )
+ */
+function ascentManager(oboeBus, handlers){
+ "use strict";
+
+ var listenerId = {},
+ ascent;
+
+ function stateAfter(handler) {
+ return function(param){
+ ascent = handler( ascent, param);
+ }
+ }
+
+ for( var eventName in handlers ) {
+
+ oboeBus(eventName).on(stateAfter(handlers[eventName]), listenerId);
+ }
+
+ oboeBus(NODE_SWAP).on(function(newNode) {
+
+ var oldHead = head(ascent),
+ key = keyOf(oldHead),
+ ancestors = tail(ascent),
+ parentNode;
+
+ if( ancestors ) {
+ parentNode = nodeOf(head(ancestors));
+ parentNode[key] = newNode;
+ }
+ });
+
+ oboeBus(NODE_DROP).on(function() {
+
+ var oldHead = head(ascent),
+ key = keyOf(oldHead),
+ ancestors = tail(ascent),
+ parentNode;
+
+ if( ancestors ) {
+ parentNode = nodeOf(head(ancestors));
+
+ delete parentNode[key];
+ }
+ });
+
+ oboeBus(ABORTING).on(function(){
+
+ for( var eventName in handlers ) {
+ oboeBus(eventName).un(listenerId);
+ }
+ });
+}
+
+var httpTransport = functor(require('http'));
+
+/**
+ * A wrapper around the browser XmlHttpRequest object that raises an
+ * event whenever a new part of the response is available.
+ *
+ * In older browsers progressive reading is impossible so all the
+ * content is given in a single call. For newer ones several events
+ * should be raised, allowing progressive interpretation of the response.
+ *
+ * @param {Function} oboeBus an event bus local to this Oboe instance
+ * @param {XMLHttpRequest} transport the http implementation to use as the transport. Under normal
+ * operation, will have been created using httpTransport() above
+ * and therefore be Node's http
+ * but for tests a stub may be provided instead.
+ * @param {String} method one of 'GET' 'POST' 'PUT' 'PATCH' 'DELETE'
+ * @param {String} contentSource the url to make a request to, or a stream to read from
+ * @param {String|Null} data some content to be sent with the request.
+ * Only valid if method is POST or PUT.
+ * @param {Object} [headers] the http request headers to send
+ */
+function streamingHttp(oboeBus, transport, method, contentSource, data, headers) {
+ "use strict";
+
+ /* receiving data after calling .abort on Node's http has been observed in the
+ wild. Keep aborted as state so that if the request has been aborted we
+ can ignore new data from that point on */
+ var aborted = false;
+
+ function readStreamToEventBus(readableStream) {
+
+ // use stream in flowing mode
+ readableStream.on('data', function (chunk) {
+
+ // avoid reading the stream after aborting the request
+ if( !aborted ) {
+ oboeBus(STREAM_DATA).emit(chunk.toString());
+ }
+ });
+
+ readableStream.on('end', function() {
+
+ // avoid reading the stream after aborting the request
+ if( !aborted ) {
+ oboeBus(STREAM_END).emit();
+ }
+ });
+ }
+
+ function readStreamToEnd(readableStream, callback){
+ var content = '';
+
+ readableStream.on('data', function (chunk) {
+
+ content += chunk.toString();
+ });
+
+ readableStream.on('end', function() {
+
+ callback( content );
+ });
+ }
+
+ function openUrlAsStream( url ) {
+
+ var parsedUrl = require('url').parse(url);
+
+ return transport.request({
+ hostname: parsedUrl.hostname,
+ port: parsedUrl.port,
+ path: parsedUrl.path,
+ method: method,
+ headers: headers,
+ protocol: parsedUrl.protocol
+ });
+ }
+
+ function fetchUrl() {
+ if( !contentSource.match(/https?:\/\//) ) {
+ throw new Error(
+ 'Supported protocols when passing a URL into Oboe are http and https. ' +
+ 'If you wish to use another protocol, please pass a ReadableStream ' +
+ '(http://nodejs.org/api/stream.html#stream_class_stream_readable) like ' +
+ 'oboe(fs.createReadStream("my_file")). I was given the URL: ' +
+ contentSource
+ );
+ }
+
+ var req = openUrlAsStream(contentSource);
+
+ req.on('response', function(res){
+ var statusCode = res.statusCode,
+ successful = String(statusCode)[0] == 2;
+
+ oboeBus(HTTP_START).emit( res.statusCode, res.headers);
+
+ if( successful ) {
+
+ readStreamToEventBus(res)
+
+ } else {
+ readStreamToEnd(res, function(errorBody){
+ oboeBus(FAIL_EVENT).emit(
+ errorReport( statusCode, errorBody )
+ );
+ });
+ }
+ });
+
+ req.on('error', function(e) {
+ oboeBus(FAIL_EVENT).emit(
+ errorReport(undefined, undefined, e )
+ );
+ });
+
+ oboeBus(ABORTING).on( function(){
+ aborted = true;
+ req.abort();
+ });
+
+ if( data ) {
+ req.write(data);
+ }
+
+ req.end();
+ }
+
+ if( isString(contentSource) ) {
+ fetchUrl(contentSource);
+ } else {
+ // contentsource is a stream
+ readStreamToEventBus(contentSource);
+ }
+
+}
+
+var jsonPathSyntax = (function() {
+
+ var
+
+ /**
+ * Export a regular expression as a simple function by exposing just
+ * the Regex#exec. This allows regex tests to be used under the same
+ * interface as differently implemented tests, or for a user of the
+ * tests to not concern themselves with their implementation as regular
+ * expressions.
+ *
+ * This could also be expressed point-free as:
+ * Function.prototype.bind.bind(RegExp.prototype.exec),
+ *
+ * But that's far too confusing! (and not even smaller once minified
+ * and gzipped)
+ */
+ regexDescriptor = function regexDescriptor(regex) {
+ return regex.exec.bind(regex);
+ }
+
+ /**
+ * Join several regular expressions and express as a function.
+ * This allows the token patterns to reuse component regular expressions
+ * instead of being expressed in full using huge and confusing regular
+ * expressions.
+ */
+ , jsonPathClause = varArgs(function( componentRegexes ) {
+
+ // The regular expressions all start with ^ because we
+ // only want to find matches at the start of the
+ // JSONPath fragment we are inspecting
+ componentRegexes.unshift(/^/);
+
+ return regexDescriptor(
+ RegExp(
+ componentRegexes.map(attr('source')).join('')
+ )
+ );
+ })
+
+ , possiblyCapturing = /(\$?)/
+ , namedNode = /([\w-_]+|\*)/
+ , namePlaceholder = /()/
+ , nodeInArrayNotation = /\["([^"]+)"\]/
+ , numberedNodeInArrayNotation = /\[(\d+|\*)\]/
+ , fieldList = /{([\w ]*?)}/
+ , optionalFieldList = /(?:{([\w ]*?)})?/
+
+
+ // foo or *
+ , jsonPathNamedNodeInObjectNotation = jsonPathClause(
+ possiblyCapturing,
+ namedNode,
+ optionalFieldList
+ )
+
+ // ["foo"]
+ , jsonPathNamedNodeInArrayNotation = jsonPathClause(
+ possiblyCapturing,
+ nodeInArrayNotation,
+ optionalFieldList
+ )
+
+ // [2] or [*]
+ , jsonPathNumberedNodeInArrayNotation = jsonPathClause(
+ possiblyCapturing,
+ numberedNodeInArrayNotation,
+ optionalFieldList
+ )
+
+ // {a b c}
+ , jsonPathPureDuckTyping = jsonPathClause(
+ possiblyCapturing,
+ namePlaceholder,
+ fieldList
+ )
+
+ // ..
+ , jsonPathDoubleDot = jsonPathClause(/\.\./)
+
+ // .
+ , jsonPathDot = jsonPathClause(/\./)
+
+ // !
+ , jsonPathBang = jsonPathClause(
+ possiblyCapturing,
+ /!/
+ )
+
+ // nada!
+ , emptyString = jsonPathClause(/$/)
+
+ ;
+
+
+ /* We export only a single function. When called, this function injects
+ into another function the descriptors from above.
+ */
+ return function (fn){
+ return fn(
+ lazyUnion(
+ jsonPathNamedNodeInObjectNotation
+ , jsonPathNamedNodeInArrayNotation
+ , jsonPathNumberedNodeInArrayNotation
+ , jsonPathPureDuckTyping
+ )
+ , jsonPathDoubleDot
+ , jsonPathDot
+ , jsonPathBang
+ , emptyString
+ );
+ };
+
+}());
+/**
+ * Get a new key->node mapping
+ *
+ * @param {String|Number} key
+ * @param {Object|Array|String|Number|null} node a value found in the json
+ */
+function namedNode(key, node) {
+ return {key:key, node:node};
+}
+
+/** get the key of a namedNode */
+var keyOf = attr('key');
+
+/** get the node from a namedNode */
+var nodeOf = attr('node');
+/**
+ * This file provides various listeners which can be used to build up
+ * a changing ascent based on the callbacks provided by Clarinet. It listens
+ * to the low-level events from Clarinet and emits higher-level ones.
+ *
+ * The building up is stateless so to track a JSON file
+ * ascentManager.js is required to store the ascent state
+ * between calls.
+ */
+
+
+
+/**
+ * A special value to use in the path list to represent the path 'to' a root
+ * object (which doesn't really have any path). This prevents the need for
+ * special-casing detection of the root object and allows it to be treated
+ * like any other object. We might think of this as being similar to the
+ * 'unnamed root' domain ".", eg if I go to
+ * http://en.wikipedia.org./wiki/En/Main_page the dot after 'org' deliminates
+ * the unnamed root of the DNS.
+ *
+ * This is kept as an object to take advantage that in Javascript's OO objects
+ * are guaranteed to be distinct, therefore no other object can possibly clash
+ * with this one. Strings, numbers etc provide no such guarantee.
+ **/
+var ROOT_PATH = {};
+
+
+/**
+ * Create a new set of handlers for clarinet's events, bound to the emit
+ * function given.
+ */
+function incrementalContentBuilder( oboeBus ) {
+
+ var emitNodeOpened = oboeBus(NODE_OPENED).emit,
+ emitNodeClosed = oboeBus(NODE_CLOSED).emit,
+ emitRootOpened = oboeBus(ROOT_PATH_FOUND).emit,
+ emitRootClosed = oboeBus(ROOT_NODE_FOUND).emit;
+
+ function arrayIndicesAreKeys( possiblyInconsistentAscent, newDeepestNode) {
+
+ /* for values in arrays we aren't pre-warned of the coming paths
+ (Clarinet gives no call to onkey like it does for values in objects)
+ so if we are in an array we need to create this path ourselves. The
+ key will be len(parentNode) because array keys are always sequential
+ numbers. */
+
+ var parentNode = nodeOf( head( possiblyInconsistentAscent));
+
+ return isOfType( Array, parentNode)
+ ?
+ keyFound( possiblyInconsistentAscent,
+ len(parentNode),
+ newDeepestNode
+ )
+ :
+ // nothing needed, return unchanged
+ possiblyInconsistentAscent
+ ;
+ }
+
+ function nodeOpened( ascent, newDeepestNode ) {
+
+ if( !ascent ) {
+ // we discovered the root node,
+ emitRootOpened( newDeepestNode);
+
+ return keyFound( ascent, ROOT_PATH, newDeepestNode);
+ }
+
+ // we discovered a non-root node
+
+ var arrayConsistentAscent = arrayIndicesAreKeys( ascent, newDeepestNode),
+ ancestorBranches = tail( arrayConsistentAscent),
+ previouslyUnmappedName = keyOf( head( arrayConsistentAscent));
+
+ appendBuiltContent(
+ ancestorBranches,
+ previouslyUnmappedName,
+ newDeepestNode
+ );
+
+ return cons(
+ namedNode( previouslyUnmappedName, newDeepestNode ),
+ ancestorBranches
+ );
+ }
+
+
+ /**
+ * Add a new value to the object we are building up to represent the
+ * parsed JSON
+ */
+ function appendBuiltContent( ancestorBranches, key, node ){
+
+ nodeOf( head( ancestorBranches))[key] = node;
+ }
+
+
+ /**
+ * For when we find a new key in the json.
+ *
+ * @param {String|Number|Object} newDeepestName the key. If we are in an
+ * array will be a number, otherwise a string. May take the special
+ * value ROOT_PATH if the root node has just been found
+ *
+ * @param {String|Number|Object|Array|Null|undefined} [maybeNewDeepestNode]
+ * usually this won't be known so can be undefined. Can't use null
+ * to represent unknown because null is a valid value in JSON
+ **/
+ function keyFound(ascent, newDeepestName, maybeNewDeepestNode) {
+
+ if( ascent ) { // if not root
+
+ // If we have the key but (unless adding to an array) no known value
+ // yet. Put that key in the output but against no defined value:
+ appendBuiltContent( ascent, newDeepestName, maybeNewDeepestNode );
+ }
+
+ var ascentWithNewPath = cons(
+ namedNode( newDeepestName,
+ maybeNewDeepestNode),
+ ascent
+ );
+
+ emitNodeOpened( ascentWithNewPath);
+
+ return ascentWithNewPath;
+ }
+
+
+ /**
+ * For when the current node ends.
+ */
+ function nodeClosed( ascent ) {
+
+ emitNodeClosed( ascent);
+
+ return tail( ascent) ||
+ // If there are no nodes left in the ascent the root node
+ // just closed. Emit a special event for this:
+ emitRootClosed(nodeOf(head(ascent)));
+ }
+
+ var contentBuilderHandlers = {};
+ contentBuilderHandlers[SAX_VALUE_OPEN] = nodeOpened;
+ contentBuilderHandlers[SAX_VALUE_CLOSE] = nodeClosed;
+ contentBuilderHandlers[SAX_KEY] = keyFound;
+ return contentBuilderHandlers;
+}
+
+/**
+ * The jsonPath evaluator compiler used for Oboe.js.
+ *
+ * One function is exposed. This function takes a String JSONPath spec and
+ * returns a function to test candidate ascents for matches.
+ *
+ * String jsonPath -> (List ascent) -> Boolean|Object
+ *
+ * This file is coded in a pure functional style. That is, no function has
+ * side effects, every function evaluates to the same value for the same
+ * arguments and no variables are reassigned.
+ */
+// the call to jsonPathSyntax injects the token syntaxes that are needed
+// inside the compiler
+var jsonPathCompiler = jsonPathSyntax(function (pathNodeSyntax,
+ doubleDotSyntax,
+ dotSyntax,
+ bangSyntax,
+ emptySyntax ) {
+
+ var CAPTURING_INDEX = 1;
+ var NAME_INDEX = 2;
+ var FIELD_LIST_INDEX = 3;
+
+ var headKey = compose2(keyOf, head),
+ headNode = compose2(nodeOf, head);
+
+ /**
+ * Create an evaluator function for a named path node, expressed in the
+ * JSONPath like:
+ * foo
+ * ["bar"]
+ * [2]
+ */
+ function nameClause(previousExpr, detection ) {
+
+ var name = detection[NAME_INDEX],
+
+ matchesName = ( !name || name == '*' )
+ ? always
+ : function(ascent){return headKey(ascent) == name};
+
+
+ return lazyIntersection(matchesName, previousExpr);
+ }
+
+ /**
+ * Create an evaluator function for a a duck-typed node, expressed like:
+ *
+ * {spin, taste, colour}
+ * .particle{spin, taste, colour}
+ * *{spin, taste, colour}
+ */
+ function duckTypeClause(previousExpr, detection) {
+
+ var fieldListStr = detection[FIELD_LIST_INDEX];
+
+ if (!fieldListStr)
+ return previousExpr; // don't wrap at all, return given expr as-is
+
+ var hasAllrequiredFields = partialComplete(
+ hasAllProperties,
+ arrayAsList(fieldListStr.split(/\W+/))
+ ),
+
+ isMatch = compose2(
+ hasAllrequiredFields,
+ headNode
+ );
+
+ return lazyIntersection(isMatch, previousExpr);
+ }
+
+ /**
+ * Expression for $, returns the evaluator function
+ */
+ function capture( previousExpr, detection ) {
+
+ // extract meaning from the detection
+ var capturing = !!detection[CAPTURING_INDEX];
+
+ if (!capturing)
+ return previousExpr; // don't wrap at all, return given expr as-is
+
+ return lazyIntersection(previousExpr, head);
+
+ }
+
+ /**
+ * Create an evaluator function that moves onto the next item on the
+ * lists. This function is the place where the logic to move up a
+ * level in the ascent exists.
+ *
+ * Eg, for JSONPath ".foo" we need skip1(nameClause(always, [,'foo']))
+ */
+ function skip1(previousExpr) {
+
+
+ if( previousExpr == always ) {
+ /* If there is no previous expression this consume command
+ is at the start of the jsonPath.
+ Since JSONPath specifies what we'd like to find but not
+ necessarily everything leading down to it, when running
+ out of JSONPath to check against we default to true */
+ return always;
+ }
+
+ /** return true if the ascent we have contains only the JSON root,
+ * false otherwise
+ */
+ function notAtRoot(ascent){
+ return headKey(ascent) != ROOT_PATH;
+ }
+
+ return lazyIntersection(
+ /* If we're already at the root but there are more
+ expressions to satisfy, can't consume any more. No match.
+
+ This check is why none of the other exprs have to be able
+ to handle empty lists; skip1 is the only evaluator that
+ moves onto the next token and it refuses to do so once it
+ reaches the last item in the list. */
+ notAtRoot,
+
+ /* We are not at the root of the ascent yet.
+ Move to the next level of the ascent by handing only
+ the tail to the previous expression */
+ compose2(previousExpr, tail)
+ );
+
+ }
+
+ /**
+ * Create an evaluator function for the .. (double dot) token. Consumes
+ * zero or more levels of the ascent, the fewest that are required to find
+ * a match when given to previousExpr.
+ */
+ function skipMany(previousExpr) {
+
+ if( previousExpr == always ) {
+ /* If there is no previous expression this consume command
+ is at the start of the jsonPath.
+ Since JSONPath specifies what we'd like to find but not
+ necessarily everything leading down to it, when running
+ out of JSONPath to check against we default to true */
+ return always;
+ }
+
+ var
+ // In JSONPath .. is equivalent to !.. so if .. reaches the root
+ // the match has succeeded. Ie, we might write ..foo or !..foo
+ // and both should match identically.
+ terminalCaseWhenArrivingAtRoot = rootExpr(),
+ terminalCaseWhenPreviousExpressionIsSatisfied = previousExpr,
+ recursiveCase = skip1(function(ascent) {
+ return cases(ascent);
+ }),
+
+ cases = lazyUnion(
+ terminalCaseWhenArrivingAtRoot
+ , terminalCaseWhenPreviousExpressionIsSatisfied
+ , recursiveCase
+ );
+
+ return cases;
+ }
+
+ /**
+ * Generate an evaluator for ! - matches only the root element of the json
+ * and ignores any previous expressions since nothing may precede !.
+ */
+ function rootExpr() {
+
+ return function(ascent){
+ return headKey(ascent) == ROOT_PATH;
+ };
+ }
+
+ /**
+ * Generate a statement wrapper to sit around the outermost
+ * clause evaluator.
+ *
+ * Handles the case where the capturing is implicit because the JSONPath
+ * did not contain a '$' by returning the last node.
+ */
+ function statementExpr(lastClause) {
+
+ return function(ascent) {
+
+ // kick off the evaluation by passing through to the last clause
+ var exprMatch = lastClause(ascent);
+
+ return exprMatch === true ? head(ascent) : exprMatch;
+ };
+ }
+
+ /**
+ * For when a token has been found in the JSONPath input.
+ * Compiles the parser for that token and returns in combination with the
+ * parser already generated.
+ *
+ * @param {Function} exprs a list of the clause evaluator generators for
+ * the token that was found
+ * @param {Function} parserGeneratedSoFar the parser already found
+ * @param {Array} detection the match given by the regex engine when
+ * the feature was found
+ */
+ function expressionsReader( exprs, parserGeneratedSoFar, detection ) {
+
+ // if exprs is zero-length foldR will pass back the
+ // parserGeneratedSoFar as-is so we don't need to treat
+ // this as a special case
+
+ return foldR(
+ function( parserGeneratedSoFar, expr ){
+
+ return expr(parserGeneratedSoFar, detection);
+ },
+ parserGeneratedSoFar,
+ exprs
+ );
+
+ }
+
+ /**
+ * If jsonPath matches the given detector function, creates a function which
+ * evaluates against every clause in the clauseEvaluatorGenerators. The
+ * created function is propagated to the onSuccess function, along with
+ * the remaining unparsed JSONPath substring.
+ *
+ * The intended use is to create a clauseMatcher by filling in
+ * the first two arguments, thus providing a function that knows
+ * some syntax to match and what kind of generator to create if it
+ * finds it. The parameter list once completed is:
+ *
+ * (jsonPath, parserGeneratedSoFar, onSuccess)
+ *
+ * onSuccess may be compileJsonPathToFunction, to recursively continue
+ * parsing after finding a match or returnFoundParser to stop here.
+ */
+ function generateClauseReaderIfTokenFound (
+
+ tokenDetector, clauseEvaluatorGenerators,
+
+ jsonPath, parserGeneratedSoFar, onSuccess) {
+
+ var detected = tokenDetector(jsonPath);
+
+ if(detected) {
+ var compiledParser = expressionsReader(
+ clauseEvaluatorGenerators,
+ parserGeneratedSoFar,
+ detected
+ ),
+
+ remainingUnparsedJsonPath = jsonPath.substr(len(detected[0]));
+
+ return onSuccess(remainingUnparsedJsonPath, compiledParser);
+ }
+ }
+
+ /**
+ * Partially completes generateClauseReaderIfTokenFound above.
+ */
+ function clauseMatcher(tokenDetector, exprs) {
+
+ return partialComplete(
+ generateClauseReaderIfTokenFound,
+ tokenDetector,
+ exprs
+ );
+ }
+
+ /**
+ * clauseForJsonPath is a function which attempts to match against
+ * several clause matchers in order until one matches. If non match the
+ * jsonPath expression is invalid and an error is thrown.
+ *
+ * The parameter list is the same as a single clauseMatcher:
+ *
+ * (jsonPath, parserGeneratedSoFar, onSuccess)
+ */
+ var clauseForJsonPath = lazyUnion(
+
+ clauseMatcher(pathNodeSyntax , list( capture,
+ duckTypeClause,
+ nameClause,
+ skip1 ))
+
+ , clauseMatcher(doubleDotSyntax , list( skipMany))
+
+ // dot is a separator only (like whitespace in other languages) but
+ // rather than make it a special case, use an empty list of
+ // expressions when this token is found
+ , clauseMatcher(dotSyntax , list() )
+
+ , clauseMatcher(bangSyntax , list( capture,
+ rootExpr))
+
+ , clauseMatcher(emptySyntax , list( statementExpr))
+
+ , function (jsonPath) {
+ throw Error('"' + jsonPath + '" could not be tokenised')
+ }
+ );
+
+
+ /**
+ * One of two possible values for the onSuccess argument of
+ * generateClauseReaderIfTokenFound.
+ *
+ * When this function is used, generateClauseReaderIfTokenFound simply
+ * returns the compiledParser that it made, regardless of if there is
+ * any remaining jsonPath to be compiled.
+ */
+ function returnFoundParser(_remainingJsonPath, compiledParser){
+ return compiledParser
+ }
+
+ /**
+ * Recursively compile a JSONPath expression.
+ *
+ * This function serves as one of two possible values for the onSuccess
+ * argument of generateClauseReaderIfTokenFound, meaning continue to
+ * recursively compile. Otherwise, returnFoundParser is given and
+ * compilation terminates.
+ */
+ function compileJsonPathToFunction( uncompiledJsonPath,
+ parserGeneratedSoFar ) {
+
+ /**
+ * On finding a match, if there is remaining text to be compiled
+ * we want to either continue parsing using a recursive call to
+ * compileJsonPathToFunction. Otherwise, we want to stop and return
+ * the parser that we have found so far.
+ */
+ var onFind = uncompiledJsonPath
+ ? compileJsonPathToFunction
+ : returnFoundParser;
+
+ return clauseForJsonPath(
+ uncompiledJsonPath,
+ parserGeneratedSoFar,
+ onFind
+ );
+ }
+
+ /**
+ * This is the function that we expose to the rest of the library.
+ */
+ return function(jsonPath){
+
+ try {
+ // Kick off the recursive parsing of the jsonPath
+ return compileJsonPathToFunction(jsonPath, always);
+
+ } catch( e ) {
+ throw Error( 'Could not compile "' + jsonPath +
+ '" because ' + e.message
+ );
+ }
+ }
+
+});
+
+/**
+ * A pub/sub which is responsible for a single event type. A
+ * multi-event type event bus is created by pubSub by collecting
+ * several of these.
+ *
+ * @param {String} eventType
+ * the name of the events managed by this singleEventPubSub
+ * @param {singleEventPubSub} [newListener]
+ * place to notify of new listeners
+ * @param {singleEventPubSub} [removeListener]
+ * place to notify of when listeners are removed
+ */
+function singleEventPubSub(eventType, newListener, removeListener){
+
+ /** we are optimised for emitting events over firing them.
+ * As well as the tuple list which stores event ids and
+ * listeners there is a list with just the listeners which
+ * can be iterated more quickly when we are emitting
+ */
+ var listenerTupleList,
+ listenerList;
+
+ function hasId(id){
+ return function(tuple) {
+ return tuple.id == id;
+ };
+ }
+
+ return {
+
+ /**
+ * @param {Function} listener
+ * @param {*} listenerId
+ * an id that this listener can later by removed by.
+ * Can be of any type, to be compared to other ids using ==
+ */
+ on:function( listener, listenerId ) {
+
+ var tuple = {
+ listener: listener
+ , id: listenerId || listener // when no id is given use the
+ // listener function as the id
+ };
+
+ if( newListener ) {
+ newListener.emit(eventType, listener, tuple.id);
+ }
+
+ listenerTupleList = cons( tuple, listenerTupleList );
+ listenerList = cons( listener, listenerList );
+
+ return this; // chaining
+ },
+
+ emit:function () {
+ applyEach( listenerList, arguments );
+ },
+
+ un: function( listenerId ) {
+
+ var removed;
+
+ listenerTupleList = without(
+ listenerTupleList,
+ hasId(listenerId),
+ function(tuple){
+ removed = tuple;
+ }
+ );
+
+ if( removed ) {
+ listenerList = without( listenerList, function(listener){
+ return listener == removed.listener;
+ });
+
+ if( removeListener ) {
+ removeListener.emit(eventType, removed.listener, removed.id);
+ }
+ }
+ },
+
+ listeners: function(){
+ // differs from Node EventEmitter: returns list, not array
+ return listenerList;
+ },
+
+ hasListener: function(listenerId){
+ var test = listenerId? hasId(listenerId) : always;
+
+ return defined(first( test, listenerTupleList));
+ }
+ };
+}
+
+/**
+ * pubSub is a curried interface for listening to and emitting
+ * events.
+ *
+ * If we get a bus:
+ *
+ * var bus = pubSub();
+ *
+ * We can listen to event 'foo' like:
+ *
+ * bus('foo').on(myCallback)
+ *
+ * And emit event foo like:
+ *
+ * bus('foo').emit()
+ *
+ * or, with a parameter:
+ *
+ * bus('foo').emit('bar')
+ *
+ * All functions can be cached and don't need to be
+ * bound. Ie:
+ *
+ * var fooEmitter = bus('foo').emit
+ * fooEmitter('bar'); // emit an event
+ * fooEmitter('baz'); // emit another
+ *
+ * There's also an uncurried[1] shortcut for .emit and .on:
+ *
+ * bus.on('foo', callback)
+ * bus.emit('foo', 'bar')
+ *
+ * [1]: http://zvon.org/other/haskell/Outputprelude/uncurry_f.html
+ */
+function pubSub(){
+
+ var singles = {},
+ newListener = newSingle('newListener'),
+ removeListener = newSingle('removeListener');
+
+ function newSingle(eventName) {
+ return singles[eventName] = singleEventPubSub(
+ eventName,
+ newListener,
+ removeListener
+ );
+ }
+
+ /** pubSub instances are functions */
+ function pubSubInstance( eventName ){
+
+ return singles[eventName] || newSingle( eventName );
+ }
+
+ // add convenience EventEmitter-style uncurried form of 'emit' and 'on'
+ ['emit', 'on', 'un'].forEach(function(methodName){
+
+ pubSubInstance[methodName] = varArgs(function(eventName, parameters){
+ apply( parameters, pubSubInstance( eventName )[methodName]);
+ });
+ });
+
+ return pubSubInstance;
+}
+
+/**
+ * This file declares some constants to use as names for event types.
+ */
+
+var // the events which are never exported are kept as
+ // the smallest possible representation, in numbers:
+ _S = 1,
+
+ // fired whenever a new node starts in the JSON stream:
+ NODE_OPENED = _S++,
+
+ // fired whenever a node closes in the JSON stream:
+ NODE_CLOSED = _S++,
+
+ // called if a .node callback returns a value -
+ NODE_SWAP = _S++,
+ NODE_DROP = _S++,
+
+ FAIL_EVENT = 'fail',
+
+ ROOT_NODE_FOUND = _S++,
+ ROOT_PATH_FOUND = _S++,
+
+ HTTP_START = 'start',
+ STREAM_DATA = 'data',
+ STREAM_END = 'end',
+ ABORTING = _S++,
+
+ // SAX events butchered from Clarinet
+ SAX_KEY = _S++,
+ SAX_VALUE_OPEN = _S++,
+ SAX_VALUE_CLOSE = _S++;
+
+function errorReport(statusCode, body, error) {
+ try{
+ var jsonBody = JSON.parse(body);
+ }catch(e){}
+
+ return {
+ statusCode:statusCode,
+ body:body,
+ jsonBody:jsonBody,
+ thrown:error
+ };
+}
+
+/**
+ * The pattern adaptor listens for newListener and removeListener
+ * events. When patterns are added or removed it compiles the JSONPath
+ * and wires them up.
+ *
+ * When nodes and paths are found it emits the fully-qualified match
+ * events with parameters ready to ship to the outside world
+ */
+
+function patternAdapter(oboeBus, jsonPathCompiler) {
+
+ var predicateEventMap = {
+ node:oboeBus(NODE_CLOSED)
+ , path:oboeBus(NODE_OPENED)
+ };
+
+ function emitMatchingNode(emitMatch, node, ascent) {
+
+ /*
+ We're now calling to the outside world where Lisp-style
+ lists will not be familiar. Convert to standard arrays.
+
+ Also, reverse the order because it is more common to
+ list paths "root to leaf" than "leaf to root" */
+ var descent = reverseList(ascent);
+
+ emitMatch(
+ node,
+
+ // To make a path, strip off the last item which is the special
+ // ROOT_PATH token for the 'path' to the root node
+ listAsArray(tail(map(keyOf,descent))), // path
+ listAsArray(map(nodeOf, descent)) // ancestors
+ );
+ }
+
+ /*
+ * Set up the catching of events such as NODE_CLOSED and NODE_OPENED and, if
+ * matching the specified pattern, propagate to pattern-match events such as
+ * oboeBus('node:!')
+ *
+ *
+ *
+ * @param {Function} predicateEvent
+ * either oboeBus(NODE_CLOSED) or oboeBus(NODE_OPENED).
+ * @param {Function} compiledJsonPath
+ */
+ function addUnderlyingListener( fullEventName, predicateEvent, compiledJsonPath ){
+
+ var emitMatch = oboeBus(fullEventName).emit;
+
+ predicateEvent.on( function (ascent) {
+
+ var maybeMatchingMapping = compiledJsonPath(ascent);
+
+ /* Possible values for maybeMatchingMapping are now:
+
+ false:
+ we did not match
+
+ an object/array/string/number/null:
+ we matched and have the node that matched.
+ Because nulls are valid json values this can be null.
+
+ undefined:
+ we matched but don't have the matching node yet.
+ ie, we know there is an upcoming node that matches but we
+ can't say anything else about it.
+ */
+ if (maybeMatchingMapping !== false) {
+
+ emitMatchingNode(
+ emitMatch,
+ nodeOf(maybeMatchingMapping),
+ ascent
+ );
+ }
+ }, fullEventName);
+
+ oboeBus('removeListener').on( function(removedEventName){
+
+ // if the fully qualified match event listener is later removed, clean up
+ // by removing the underlying listener if it was the last using that pattern:
+
+ if( removedEventName == fullEventName ) {
+
+ if( !oboeBus(removedEventName).listeners( )) {
+ predicateEvent.un( fullEventName );
+ }
+ }
+ });
+ }
+
+ oboeBus('newListener').on( function(fullEventName){
+
+ var match = /(node|path):(.*)/.exec(fullEventName);
+
+ if( match ) {
+ var predicateEvent = predicateEventMap[match[1]];
+
+ if( !predicateEvent.hasListener( fullEventName) ) {
+
+ addUnderlyingListener(
+ fullEventName,
+ predicateEvent,
+ jsonPathCompiler( match[2] )
+ );
+ }
+ }
+ })
+
+}
+
+/**
+ * The instance API is the thing that is returned when oboe() is called.
+ * it allows:
+ *
+ * - listeners for various events to be added and removed
+ * - the http response header/headers to be read
+ */
+function instanceApi(oboeBus, contentSource){
+
+ var oboeApi,
+ fullyQualifiedNamePattern = /^(node|path):./,
+ rootNodeFinishedEvent = oboeBus(ROOT_NODE_FOUND),
+ emitNodeDrop = oboeBus(NODE_DROP).emit,
+ emitNodeSwap = oboeBus(NODE_SWAP).emit,
+
+ /**
+ * Add any kind of listener that the instance api exposes
+ */
+ addListener = varArgs(function( eventId, parameters ){
+
+ if( oboeApi[eventId] ) {
+
+ // for events added as .on(event, callback), if there is a
+ // .event() equivalent with special behaviour , pass through
+ // to that:
+ apply(parameters, oboeApi[eventId]);
+ } else {
+
+ // we have a standard Node.js EventEmitter 2-argument call.
+ // The first parameter is the listener.
+ var event = oboeBus(eventId),
+ listener = parameters[0];
+
+ if( fullyQualifiedNamePattern.test(eventId) ) {
+
+ // allow fully-qualified node/path listeners
+ // to be added
+ addForgettableCallback(event, listener);
+ } else {
+
+ // the event has no special handling, pass through
+ // directly onto the event bus:
+ event.on( listener);
+ }
+ }
+
+ return oboeApi; // chaining
+ }),
+
+ /**
+ * Remove any kind of listener that the instance api exposes
+ */
+ removeListener = function( eventId, p2, p3 ){
+
+ if( eventId == 'done' ) {
+
+ rootNodeFinishedEvent.un(p2);
+
+ } else if( eventId == 'node' || eventId == 'path' ) {
+
+ // allow removal of node and path
+ oboeBus.un(eventId + ':' + p2, p3);
+ } else {
+
+ // we have a standard Node.js EventEmitter 2-argument call.
+ // The second parameter is the listener. This may be a call
+ // to remove a fully-qualified node/path listener but requires
+ // no special handling
+ var listener = p2;
+
+ oboeBus(eventId).un(listener);
+ }
+
+ return oboeApi; // chaining
+ };
+
+ /**
+ * Add a callback, wrapped in a try/catch so as to not break the
+ * execution of Oboe if an exception is thrown (fail events are
+ * fired instead)
+ *
+ * The callback is used as the listener id so that it can later be
+ * removed using .un(callback)
+ */
+ function addProtectedCallback(eventName, callback) {
+ oboeBus(eventName).on(protectedCallback(callback), callback);
+ return oboeApi; // chaining
+ }
+
+ /**
+ * Add a callback where, if .forget() is called during the callback's
+ * execution, the callback will be de-registered
+ */
+ function addForgettableCallback(event, callback, listenerId) {
+
+ // listenerId is optional and if not given, the original
+ // callback will be used
+ listenerId = listenerId || callback;
+
+ var safeCallback = protectedCallback(callback);
+
+ event.on( function() {
+
+ var discard = false;
+
+ oboeApi.forget = function(){
+ discard = true;
+ };
+
+ apply( arguments, safeCallback );
+
+ delete oboeApi.forget;
+
+ if( discard ) {
+ event.un(listenerId);
+ }
+ }, listenerId);
+
+ return oboeApi; // chaining
+ }
+
+ /**
+ * wrap a callback so that if it throws, Oboe.js doesn't crash but instead
+ * throw the error in another event loop
+ */
+ function protectedCallback( callback ) {
+ return function() {
+ try{
+ return callback.apply(oboeApi, arguments);
+ }catch(e) {
+ setTimeout(function() {
+ throw new Error(e.message);
+ });
+ }
+ }
+ }
+
+ /**
+ * Return the fully qualified event for when a pattern matches
+ * either a node or a path
+ *
+ * @param type {String} either 'node' or 'path'
+ */
+ function fullyQualifiedPatternMatchEvent(type, pattern) {
+ return oboeBus(type + ':' + pattern);
+ }
+
+ function wrapCallbackToSwapNodeIfSomethingReturned( callback ) {
+ return function() {
+ var returnValueFromCallback = callback.apply(this, arguments);
+
+ if( defined(returnValueFromCallback) ) {
+
+ if( returnValueFromCallback == oboe.drop ) {
+ emitNodeDrop();
+ } else {
+ emitNodeSwap(returnValueFromCallback);
+ }
+ }
+ }
+ }
+
+ function addSingleNodeOrPathListener(eventId, pattern, callback) {
+
+ var effectiveCallback;
+
+ if( eventId == 'node' ) {
+ effectiveCallback = wrapCallbackToSwapNodeIfSomethingReturned(callback);
+ } else {
+ effectiveCallback = callback;
+ }
+
+ addForgettableCallback(
+ fullyQualifiedPatternMatchEvent(eventId, pattern),
+ effectiveCallback,
+ callback
+ );
+ }
+
+ /**
+ * Add several listeners at a time, from a map
+ */
+ function addMultipleNodeOrPathListeners(eventId, listenerMap) {
+
+ for( var pattern in listenerMap ) {
+ addSingleNodeOrPathListener(eventId, pattern, listenerMap[pattern]);
+ }
+ }
+
+ /**
+ * implementation behind .onPath() and .onNode()
+ */
+ function addNodeOrPathListenerApi( eventId, jsonPathOrListenerMap, callback ){
+
+ if( isString(jsonPathOrListenerMap) ) {
+ addSingleNodeOrPathListener(eventId, jsonPathOrListenerMap, callback);
+
+ } else {
+ addMultipleNodeOrPathListeners(eventId, jsonPathOrListenerMap);
+ }
+
+ return oboeApi; // chaining
+ }
+
+
+ // some interface methods are only filled in after we receive
+ // values and are noops before that:
+ oboeBus(ROOT_PATH_FOUND).on( function(rootNode) {
+ oboeApi.root = functor(rootNode);
+ });
+
+ /**
+ * When content starts make the headers readable through the
+ * instance API
+ */
+ oboeBus(HTTP_START).on( function(_statusCode, headers) {
+
+ oboeApi.header = function(name) {
+ return name ? headers[name]
+ : headers
+ ;
+ }
+ });
+
+ /**
+ * Construct and return the public API of the Oboe instance to be
+ * returned to the calling application
+ */
+ return oboeApi = {
+ on : addListener,
+ addListener : addListener,
+ removeListener : removeListener,
+ emit : oboeBus.emit,
+
+ node : partialComplete(addNodeOrPathListenerApi, 'node'),
+ path : partialComplete(addNodeOrPathListenerApi, 'path'),
+
+ done : partialComplete(addForgettableCallback, rootNodeFinishedEvent),
+ start : partialComplete(addProtectedCallback, HTTP_START ),
+
+ // fail doesn't use protectedCallback because
+ // could lead to non-terminating loops
+ fail : oboeBus(FAIL_EVENT).on,
+
+ // public api calling abort fires the ABORTING event
+ abort : oboeBus(ABORTING).emit,
+
+ // for manually feeding data
+ write : oboeBus(STREAM_DATA).emit,
+ finish : oboeBus(STREAM_END).emit,
+
+ // initially return nothing for header and root
+ header : noop,
+ root : noop,
+
+ source : contentSource
+ };
+}
+
+/**
+ * This file sits just behind the API which is used to attain a new
+ * Oboe instance. It creates the new components that are required
+ * and introduces them to each other.
+ */
+
+function wire (httpMethodName, contentSource, body, headers, withCredentials){
+
+ var oboeBus = pubSub();
+
+ // Wire the input stream in if we are given a content source.
+ // This will usually be the case. If not, the instance created
+ // will have to be passed content from an external source.
+
+ if( contentSource ) {
+
+ streamingHttp( oboeBus,
+ httpTransport(),
+ httpMethodName,
+ contentSource,
+ body,
+ headers,
+ withCredentials
+ );
+ }
+
+ clarinet(oboeBus);
+
+ ascentManager(oboeBus, incrementalContentBuilder(oboeBus));
+
+ patternAdapter(oboeBus, jsonPathCompiler);
+
+ return instanceApi(oboeBus, contentSource);
+}
+
+function applyDefaults( passthrough, url, httpMethodName, body, headers, withCredentials, cached ){
+
+ headers = headers ?
+ // Shallow-clone the headers array. This allows it to be
+ // modified without side effects to the caller. We don't
+ // want to change objects that the user passes in.
+ JSON.parse(JSON.stringify(headers))
+ : {};
+
+ if( body ) {
+ if( !isString(body) ) {
+
+ // If the body is not a string, stringify it. This allows objects to
+ // be given which will be sent as JSON.
+ body = JSON.stringify(body);
+
+ // Default Content-Type to JSON unless given otherwise.
+ headers['Content-Type'] = headers['Content-Type'] || 'application/json';
+ }
+ } else {
+ body = null;
+ }
+
+ // support cache busting like jQuery.ajax({cache:false})
+ function modifiedUrl(baseUrl, cached) {
+
+ if( cached === false ) {
+
+ if( baseUrl.indexOf('?') == -1 ) {
+ baseUrl += '?';
+ } else {
+ baseUrl += '&';
+ }
+
+ baseUrl += '_=' + new Date().getTime();
+ }
+ return baseUrl;
+ }
+
+ return passthrough( httpMethodName || 'GET', modifiedUrl(url, cached), body, headers, withCredentials || false );
+}
+
+// export public API
+function oboe(arg1) {
+
+ // We use duck-typing to detect if the parameter given is a stream, with the
+ // below list of parameters.
+ // Unpipe and unshift would normally be present on a stream but this breaks
+ // compatibility with Request streams.
+ // See https://github.com/jimhigson/oboe.js/issues/65
+
+ var nodeStreamMethodNames = list('resume', 'pause', 'pipe'),
+ isStream = partialComplete(
+ hasAllProperties
+ , nodeStreamMethodNames
+ );
+
+ if( arg1 ) {
+ if (isStream(arg1) || isString(arg1)) {
+
+ // simple version for GETs. Signature is:
+ // oboe( url )
+ // or, under node:
+ // oboe( readableStream )
+ return applyDefaults(
+ wire,
+ arg1 // url
+ );
+
+ } else {
+
+ // method signature is:
+ // oboe({method:m, url:u, body:b, headers:{...}})
+
+ return applyDefaults(
+ wire,
+ arg1.url,
+ arg1.method,
+ arg1.body,
+ arg1.headers,
+ arg1.withCredentials,
+ arg1.cached
+ );
+
+ }
+ } else {
+ // wire up a no-AJAX, no-stream Oboe. Will have to have content
+ // fed in externally and using .emit.
+ return wire();
+ }
+}
+
+/* oboe.drop is a special value. If a node callback returns this value the
+ parsed node is deleted from the JSON
+ */
+oboe.drop = function() {
+ return oboe.drop;
+};
+
+
+ return oboe;
+})();
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/index.js b/chromium/third_party/catapult/tracing/third_party/oboe/index.js
new file mode 100644
index 00000000000..d1cc947676f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/index.js
@@ -0,0 +1,3 @@
+var oboe = require('./dist/oboe-node');
+
+module.exports = oboe;
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/jasmine.json b/chromium/third_party/catapult/tracing/third_party/oboe/jasmine.json
new file mode 100644
index 00000000000..de5e5a91d00
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/jasmine.json
@@ -0,0 +1,8 @@
+{
+ "spec_dir": "test",
+ "spec_files": [
+ "specs/oboe.*.spec.js"
+ ],
+ "stopSpecOnExpectationFailure": false,
+ "random": false
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/logo.png b/chromium/third_party/catapult/tracing/third_party/oboe/logo.png
new file mode 100644
index 00000000000..ecc5e5396f7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/logo.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/package.json b/chromium/third_party/catapult/tracing/third_party/oboe/package.json
new file mode 100644
index 00000000000..310fa98effb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/package.json
@@ -0,0 +1,86 @@
+{
+ "name": "oboe",
+ "title": "Oboe.js",
+ "version": "2.1.3",
+ "description": "Oboe.js reads json, giving you the objects as they are found without waiting for the stream to finish",
+ "main": "./dist/oboe-node.js",
+ "browser": "./dist/oboe-browser.js",
+ "scripts": {
+ "test": "node ./node_modules/grunt-cli/bin/grunt headless-mode default",
+ "test-start-server": "node ./node_modules/grunt-cli/bin/grunt test-start-server",
+ "test-run": "node ./node_modules/grunt-cli/bin/grunt test-run",
+ "test-node": "jasmine JASMINE_CONFIG_PATH=jasmine.json",
+ "browser-test-auto-run": "node ./node_modules/grunt-cli/bin/grunt test-auto-run",
+ "node-test-auto-run": "node ./node_modules/grunt-cli/bin/grunt node-test-auto-run",
+ "dist-sizes": "node ./node_modules/grunt-cli/bin/grunt dist-sizes"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/jimhigson/oboe.js.git"
+ },
+ "keywords": [
+ "json",
+ "parser",
+ "stream",
+ "progressive",
+ "http",
+ "sax",
+ "event",
+ "emitter",
+ "async",
+ "browser"
+ ],
+ "homepage": "http://oboejs.com",
+ "author": "Jim Higson",
+ "license": "BSD",
+ "readmeFilename": "README.md",
+ "devDependencies": {
+ "color": "~0.4.4",
+ "cors": "~2.1.1",
+ "doctoc": "~0.4.3",
+ "express": "~3.4.3",
+ "get-json": "0.0.1",
+ "grunt": "~0.4.1",
+ "grunt-clear": "~0.2.1",
+ "grunt-cli": "~0.1.9",
+ "grunt-concurrent": "~0.3.1",
+ "grunt-contrib-clean": "~0.5.0",
+ "grunt-contrib-concat": "~0.1.3",
+ "grunt-contrib-copy": "~0.4.1",
+ "grunt-contrib-uglify": "~0.2.0",
+ "grunt-contrib-watch": "~0.5.1",
+ "grunt-exec": "~0.4.2",
+ "grunt-karma": "2.0.0",
+ "grunt-micro": "~0.1.0",
+ "grunt-wrap": "~0.2.0",
+ "jasmine": "2.5.2",
+ "jasmine-core": "2.5.2",
+ "jasmine-node": "~1.11.0",
+ "karma": "1.3.0",
+ "karma-coverage": "1.1.1",
+ "karma-firefox-launcher": "1.0.0",
+ "karma-jasmine": "1.0.2",
+ "karma-phantomjs-launcher": "1.0.2",
+ "karma-safari-launcher": "1.0.0",
+ "matchdep": "~0.1.2",
+ "request": "^2.55.0",
+ "sinon": "=1.17.3"
+ },
+ "dependencies": {
+ "http-https": "^1.0.0"
+ },
+ "jam": {
+ "main": "dist/oboe-browser.js",
+ "include": [
+ "dist/oboe-browser.js",
+ "LICENCE",
+ "package.json",
+ "README.md"
+ ],
+ "dependencies": {},
+ "categories": [
+ "AJAX & Websockets",
+ "Parsers & Compilers"
+ ]
+ }
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/LICENCE.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/LICENCE.js
new file mode 100644
index 00000000000..b2a60bf9fb2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/LICENCE.js
@@ -0,0 +1,30 @@
+/*
+
+Copyright (c) 2013, Jim Higson
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/ascent.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/ascent.js
new file mode 100644
index 00000000000..c5cec4e44bd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/ascent.js
@@ -0,0 +1,15 @@
+/**
+ * Get a new key->node mapping
+ *
+ * @param {String|Number} key
+ * @param {Object|Array|String|Number|null} node a value found in the json
+ */
+function namedNode(key, node) {
+ return {key:key, node:node};
+}
+
+/** get the key of a namedNode */
+var keyOf = attr('key');
+
+/** get the node from a namedNode */
+var nodeOf = attr('node'); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/ascentManager.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/ascentManager.js
new file mode 100644
index 00000000000..672fb251ea2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/ascentManager.js
@@ -0,0 +1,62 @@
+
+/**
+ * A bridge used to assign stateless functions to listen to clarinet.
+ *
+ * As well as the parameter from clarinet, each callback will also be passed
+ * the result of the last callback.
+ *
+ * This may also be used to clear all listeners by assigning zero handlers:
+ *
+ * ascentManager( clarinet, {} )
+ */
+function ascentManager(oboeBus, handlers){
+ "use strict";
+
+ var listenerId = {},
+ ascent;
+
+ function stateAfter(handler) {
+ return function(param){
+ ascent = handler( ascent, param);
+ }
+ }
+
+ for( var eventName in handlers ) {
+
+ oboeBus(eventName).on(stateAfter(handlers[eventName]), listenerId);
+ }
+
+ oboeBus(NODE_SWAP).on(function(newNode) {
+
+ var oldHead = head(ascent),
+ key = keyOf(oldHead),
+ ancestors = tail(ascent),
+ parentNode;
+
+ if( ancestors ) {
+ parentNode = nodeOf(head(ancestors));
+ parentNode[key] = newNode;
+ }
+ });
+
+ oboeBus(NODE_DROP).on(function() {
+
+ var oldHead = head(ascent),
+ key = keyOf(oldHead),
+ ancestors = tail(ascent),
+ parentNode;
+
+ if( ancestors ) {
+ parentNode = nodeOf(head(ancestors));
+
+ delete parentNode[key];
+ }
+ });
+
+ oboeBus(ABORTING).on(function(){
+
+ for( var eventName in handlers ) {
+ oboeBus(eventName).un(listenerId);
+ }
+ });
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/defaults.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/defaults.js
new file mode 100644
index 00000000000..95131daf354
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/defaults.js
@@ -0,0 +1,41 @@
+function applyDefaults( passthrough, url, httpMethodName, body, headers, withCredentials, cached ){
+
+ headers = headers ?
+ // Shallow-clone the headers array. This allows it to be
+ // modified without side effects to the caller. We don't
+ // want to change objects that the user passes in.
+ JSON.parse(JSON.stringify(headers))
+ : {};
+
+ if( body ) {
+ if( !isString(body) ) {
+
+ // If the body is not a string, stringify it. This allows objects to
+ // be given which will be sent as JSON.
+ body = JSON.stringify(body);
+
+ // Default Content-Type to JSON unless given otherwise.
+ headers['Content-Type'] = headers['Content-Type'] || 'application/json';
+ }
+ } else {
+ body = null;
+ }
+
+ // support cache busting like jQuery.ajax({cache:false})
+ function modifiedUrl(baseUrl, cached) {
+
+ if( cached === false ) {
+
+ if( baseUrl.indexOf('?') == -1 ) {
+ baseUrl += '?';
+ } else {
+ baseUrl += '&';
+ }
+
+ baseUrl += '_=' + new Date().getTime();
+ }
+ return baseUrl;
+ }
+
+ return passthrough( httpMethodName || 'GET', modifiedUrl(url, cached), body, headers, withCredentials || false );
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/detectCrossOrigin.browser.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/detectCrossOrigin.browser.js
new file mode 100644
index 00000000000..af3ffca7906
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/detectCrossOrigin.browser.js
@@ -0,0 +1,65 @@
+/**
+ * Detect if a given URL is cross-origin in the scope of the
+ * current page.
+ *
+ * Browser only (since cross-origin has no meaning in Node.js)
+ *
+ * @param {Object} pageLocation - as in window.location
+ * @param {Object} ajaxHost - an object like window.location describing the
+ * origin of the url that we want to ajax in
+ */
+function isCrossOrigin(pageLocation, ajaxHost) {
+
+ /*
+ * NB: defaultPort only knows http and https.
+ * Returns undefined otherwise.
+ */
+ function defaultPort(protocol) {
+ return {'http:':80, 'https:':443}[protocol];
+ }
+
+ function portOf(location) {
+ // pageLocation should always have a protocol. ajaxHost if no port or
+ // protocol is specified, should use the port of the containing page
+
+ return location.port || defaultPort(location.protocol||pageLocation.protocol);
+ }
+
+ // if ajaxHost doesn't give a domain, port is the same as pageLocation
+ // it can't give a protocol but not a domain
+ // it can't give a port but not a domain
+
+ return !!( (ajaxHost.protocol && (ajaxHost.protocol != pageLocation.protocol)) ||
+ (ajaxHost.host && (ajaxHost.host != pageLocation.host)) ||
+ (ajaxHost.host && (portOf(ajaxHost) != portOf(pageLocation)))
+ );
+}
+
+/* turn any url into an object like window.location */
+function parseUrlOrigin(url) {
+ // url could be domain-relative
+ // url could give a domain
+
+ // cross origin means:
+ // same domain
+ // same port
+ // some protocol
+ // so, same everything up to the first (single) slash
+ // if such is given
+ //
+ // can ignore everything after that
+
+ var URL_HOST_PATTERN = /(\w+:)?(?:\/\/)([\w.-]+)?(?::(\d+))?\/?/,
+
+ // if no match, use an empty array so that
+ // subexpressions 1,2,3 are all undefined
+ // and will ultimately return all empty
+ // strings as the parse result:
+ urlHostMatch = URL_HOST_PATTERN.exec(url) || [];
+
+ return {
+ protocol: urlHostMatch[1] || '',
+ host: urlHostMatch[2] || '',
+ port: urlHostMatch[3] || ''
+ };
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/events.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/events.js
new file mode 100644
index 00000000000..ac8e5d29427
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/events.js
@@ -0,0 +1,45 @@
+/**
+ * This file declares some constants to use as names for event types.
+ */
+
+var // the events which are never exported are kept as
+ // the smallest possible representation, in numbers:
+ _S = 1,
+
+ // fired whenever a new node starts in the JSON stream:
+ NODE_OPENED = _S++,
+
+ // fired whenever a node closes in the JSON stream:
+ NODE_CLOSED = _S++,
+
+ // called if a .node callback returns a value -
+ NODE_SWAP = _S++,
+ NODE_DROP = _S++,
+
+ FAIL_EVENT = 'fail',
+
+ ROOT_NODE_FOUND = _S++,
+ ROOT_PATH_FOUND = _S++,
+
+ HTTP_START = 'start',
+ STREAM_DATA = 'data',
+ STREAM_END = 'end',
+ ABORTING = _S++,
+
+ // SAX events butchered from Clarinet
+ SAX_KEY = _S++,
+ SAX_VALUE_OPEN = _S++,
+ SAX_VALUE_CLOSE = _S++;
+
+function errorReport(statusCode, body, error) {
+ try{
+ var jsonBody = JSON.parse(body);
+ }catch(e){}
+
+ return {
+ statusCode:statusCode,
+ body:body,
+ jsonBody:jsonBody,
+ thrown:error
+ };
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/functional.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/functional.js
new file mode 100644
index 00000000000..f4277454120
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/functional.js
@@ -0,0 +1,250 @@
+/**
+ * Partially complete a function.
+ *
+ * var add3 = partialComplete( function add(a,b){return a+b}, 3 );
+ *
+ * add3(4) // gives 7
+ *
+ * function wrap(left, right, cen){return left + " " + cen + " " + right;}
+ *
+ * var pirateGreeting = partialComplete( wrap , "I'm", ", a mighty pirate!" );
+ *
+ * pirateGreeting("Guybrush Threepwood");
+ * // gives "I'm Guybrush Threepwood, a mighty pirate!"
+ */
+var partialComplete = varArgs(function( fn, args ) {
+
+ // this isn't the shortest way to write this but it does
+ // avoid creating a new array each time to pass to fn.apply,
+ // otherwise could just call boundArgs.concat(callArgs)
+
+ var numBoundArgs = args.length;
+
+ return varArgs(function( callArgs ) {
+
+ for (var i = 0; i < callArgs.length; i++) {
+ args[numBoundArgs + i] = callArgs[i];
+ }
+
+ args.length = numBoundArgs + callArgs.length;
+
+ return fn.apply(this, args);
+ });
+ }),
+
+/**
+ * Compose zero or more functions:
+ *
+ * compose(f1, f2, f3)(x) = f1(f2(f3(x))))
+ *
+ * The last (inner-most) function may take more than one parameter:
+ *
+ * compose(f1, f2, f3)(x,y) = f1(f2(f3(x,y))))
+ */
+ compose = varArgs(function(fns) {
+
+ var fnsList = arrayAsList(fns);
+
+ function next(params, curFn) {
+ return [apply(params, curFn)];
+ }
+
+ return varArgs(function(startParams){
+
+ return foldR(next, startParams, fnsList)[0];
+ });
+ });
+
+/**
+ * A more optimised version of compose that takes exactly two functions
+ * @param f1
+ * @param f2
+ */
+function compose2(f1, f2){
+ return function(){
+ return f1.call(this,f2.apply(this,arguments));
+ }
+}
+
+/**
+ * Generic form for a function to get a property from an object
+ *
+ * var o = {
+ * foo:'bar'
+ * }
+ *
+ * var getFoo = attr('foo')
+ *
+ * fetFoo(o) // returns 'bar'
+ *
+ * @param {String} key the property name
+ */
+function attr(key) {
+ return function(o) { return o[key]; };
+}
+
+/**
+ * Call a list of functions with the same args until one returns a
+ * truthy result. Similar to the || operator.
+ *
+ * So:
+ * lazyUnion([f1,f2,f3 ... fn])( p1, p2 ... pn )
+ *
+ * Is equivalent to:
+ * apply([p1, p2 ... pn], f1) ||
+ * apply([p1, p2 ... pn], f2) ||
+ * apply([p1, p2 ... pn], f3) ... apply(fn, [p1, p2 ... pn])
+ *
+ * @returns the first return value that is given that is truthy.
+ */
+ var lazyUnion = varArgs(function(fns) {
+
+ return varArgs(function(params){
+
+ var maybeValue;
+
+ for (var i = 0; i < len(fns); i++) {
+
+ maybeValue = apply(params, fns[i]);
+
+ if( maybeValue ) {
+ return maybeValue;
+ }
+ }
+ });
+ });
+
+/**
+ * This file declares various pieces of functional programming.
+ *
+ * This isn't a general purpose functional library, to keep things small it
+ * has just the parts useful for Oboe.js.
+ */
+
+
+/**
+ * Call a single function with the given arguments array.
+ * Basically, a functional-style version of the OO-style Function#apply for
+ * when we don't care about the context ('this') of the call.
+ *
+ * The order of arguments allows partial completion of the arguments array
+ */
+function apply(args, fn) {
+ return fn.apply(undefined, args);
+}
+
+/**
+ * Define variable argument functions but cut out all that tedious messing about
+ * with the arguments object. Delivers the variable-length part of the arguments
+ * list as an array.
+ *
+ * Eg:
+ *
+ * var myFunction = varArgs(
+ * function( fixedArgument, otherFixedArgument, variableNumberOfArguments ){
+ * console.log( variableNumberOfArguments );
+ * }
+ * )
+ *
+ * myFunction('a', 'b', 1, 2, 3); // logs [1,2,3]
+ *
+ * var myOtherFunction = varArgs(function( variableNumberOfArguments ){
+ * console.log( variableNumberOfArguments );
+ * })
+ *
+ * myFunction(1, 2, 3); // logs [1,2,3]
+ *
+ */
+function varArgs(fn){
+
+ var numberOfFixedArguments = fn.length -1,
+ slice = Array.prototype.slice;
+
+
+ if( numberOfFixedArguments == 0 ) {
+ // an optimised case for when there are no fixed args:
+
+ return function(){
+ return fn.call(this, slice.call(arguments));
+ }
+
+ } else if( numberOfFixedArguments == 1 ) {
+ // an optimised case for when there are is one fixed args:
+
+ return function(){
+ return fn.call(this, arguments[0], slice.call(arguments, 1));
+ }
+ }
+
+ // general case
+
+ // we know how many arguments fn will always take. Create a
+ // fixed-size array to hold that many, to be re-used on
+ // every call to the returned function
+ var argsHolder = Array(fn.length);
+
+ return function(){
+
+ for (var i = 0; i < numberOfFixedArguments; i++) {
+ argsHolder[i] = arguments[i];
+ }
+
+ argsHolder[numberOfFixedArguments] =
+ slice.call(arguments, numberOfFixedArguments);
+
+ return fn.apply( this, argsHolder);
+ }
+}
+
+
+/**
+ * Swap the order of parameters to a binary function
+ *
+ * A bit like this flip: http://zvon.org/other/haskell/Outputprelude/flip_f.html
+ */
+function flip(fn){
+ return function(a, b){
+ return fn(b,a);
+ }
+}
+
+
+/**
+ * Create a function which is the intersection of two other functions.
+ *
+ * Like the && operator, if the first is truthy, the second is never called,
+ * otherwise the return value from the second is returned.
+ */
+function lazyIntersection(fn1, fn2) {
+
+ return function (param) {
+
+ return fn1(param) && fn2(param);
+ };
+}
+
+/**
+ * A function which does nothing
+ */
+function noop(){}
+
+/**
+ * A function which is always happy
+ */
+function always(){return true}
+
+/**
+ * Create a function which always returns the same
+ * value
+ *
+ * var return3 = functor(3);
+ *
+ * return3() // gives 3
+ * return3() // still gives 3
+ * return3() // will always give 3
+ */
+function functor(val){
+ return function(){
+ return val;
+ }
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/incrementalContentBuilder.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/incrementalContentBuilder.js
new file mode 100644
index 00000000000..381a73dd451
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/incrementalContentBuilder.js
@@ -0,0 +1,150 @@
+/**
+ * This file provides various listeners which can be used to build up
+ * a changing ascent based on the callbacks provided by Clarinet. It listens
+ * to the low-level events from Clarinet and emits higher-level ones.
+ *
+ * The building up is stateless so to track a JSON file
+ * ascentManager.js is required to store the ascent state
+ * between calls.
+ */
+
+
+
+/**
+ * A special value to use in the path list to represent the path 'to' a root
+ * object (which doesn't really have any path). This prevents the need for
+ * special-casing detection of the root object and allows it to be treated
+ * like any other object. We might think of this as being similar to the
+ * 'unnamed root' domain ".", eg if I go to
+ * http://en.wikipedia.org./wiki/En/Main_page the dot after 'org' deliminates
+ * the unnamed root of the DNS.
+ *
+ * This is kept as an object to take advantage that in Javascript's OO objects
+ * are guaranteed to be distinct, therefore no other object can possibly clash
+ * with this one. Strings, numbers etc provide no such guarantee.
+ **/
+var ROOT_PATH = {};
+
+
+/**
+ * Create a new set of handlers for clarinet's events, bound to the emit
+ * function given.
+ */
+function incrementalContentBuilder( oboeBus ) {
+
+ var emitNodeOpened = oboeBus(NODE_OPENED).emit,
+ emitNodeClosed = oboeBus(NODE_CLOSED).emit,
+ emitRootOpened = oboeBus(ROOT_PATH_FOUND).emit,
+ emitRootClosed = oboeBus(ROOT_NODE_FOUND).emit;
+
+ function arrayIndicesAreKeys( possiblyInconsistentAscent, newDeepestNode) {
+
+ /* for values in arrays we aren't pre-warned of the coming paths
+ (Clarinet gives no call to onkey like it does for values in objects)
+ so if we are in an array we need to create this path ourselves. The
+ key will be len(parentNode) because array keys are always sequential
+ numbers. */
+
+ var parentNode = nodeOf( head( possiblyInconsistentAscent));
+
+ return isOfType( Array, parentNode)
+ ?
+ keyFound( possiblyInconsistentAscent,
+ len(parentNode),
+ newDeepestNode
+ )
+ :
+ // nothing needed, return unchanged
+ possiblyInconsistentAscent
+ ;
+ }
+
+ function nodeOpened( ascent, newDeepestNode ) {
+
+ if( !ascent ) {
+ // we discovered the root node,
+ emitRootOpened( newDeepestNode);
+
+ return keyFound( ascent, ROOT_PATH, newDeepestNode);
+ }
+
+ // we discovered a non-root node
+
+ var arrayConsistentAscent = arrayIndicesAreKeys( ascent, newDeepestNode),
+ ancestorBranches = tail( arrayConsistentAscent),
+ previouslyUnmappedName = keyOf( head( arrayConsistentAscent));
+
+ appendBuiltContent(
+ ancestorBranches,
+ previouslyUnmappedName,
+ newDeepestNode
+ );
+
+ return cons(
+ namedNode( previouslyUnmappedName, newDeepestNode ),
+ ancestorBranches
+ );
+ }
+
+
+ /**
+ * Add a new value to the object we are building up to represent the
+ * parsed JSON
+ */
+ function appendBuiltContent( ancestorBranches, key, node ){
+
+ nodeOf( head( ancestorBranches))[key] = node;
+ }
+
+
+ /**
+ * For when we find a new key in the json.
+ *
+ * @param {String|Number|Object} newDeepestName the key. If we are in an
+ * array will be a number, otherwise a string. May take the special
+ * value ROOT_PATH if the root node has just been found
+ *
+ * @param {String|Number|Object|Array|Null|undefined} [maybeNewDeepestNode]
+ * usually this won't be known so can be undefined. Can't use null
+ * to represent unknown because null is a valid value in JSON
+ **/
+ function keyFound(ascent, newDeepestName, maybeNewDeepestNode) {
+
+ if( ascent ) { // if not root
+
+ // If we have the key but (unless adding to an array) no known value
+ // yet. Put that key in the output but against no defined value:
+ appendBuiltContent( ascent, newDeepestName, maybeNewDeepestNode );
+ }
+
+ var ascentWithNewPath = cons(
+ namedNode( newDeepestName,
+ maybeNewDeepestNode),
+ ascent
+ );
+
+ emitNodeOpened( ascentWithNewPath);
+
+ return ascentWithNewPath;
+ }
+
+
+ /**
+ * For when the current node ends.
+ */
+ function nodeClosed( ascent ) {
+
+ emitNodeClosed( ascent);
+
+ return tail( ascent) ||
+ // If there are no nodes left in the ascent the root node
+ // just closed. Emit a special event for this:
+ emitRootClosed(nodeOf(head(ascent)));
+ }
+
+ var contentBuilderHandlers = {};
+ contentBuilderHandlers[SAX_VALUE_OPEN] = nodeOpened;
+ contentBuilderHandlers[SAX_VALUE_CLOSE] = nodeClosed;
+ contentBuilderHandlers[SAX_KEY] = keyFound;
+ return contentBuilderHandlers;
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/instanceApi.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/instanceApi.js
new file mode 100644
index 00000000000..2c14ebab3ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/instanceApi.js
@@ -0,0 +1,254 @@
+/**
+ * The instance API is the thing that is returned when oboe() is called.
+ * it allows:
+ *
+ * - listeners for various events to be added and removed
+ * - the http response header/headers to be read
+ */
+function instanceApi(oboeBus, contentSource){
+
+ var oboeApi,
+ fullyQualifiedNamePattern = /^(node|path):./,
+ rootNodeFinishedEvent = oboeBus(ROOT_NODE_FOUND),
+ emitNodeDrop = oboeBus(NODE_DROP).emit,
+ emitNodeSwap = oboeBus(NODE_SWAP).emit,
+
+ /**
+ * Add any kind of listener that the instance api exposes
+ */
+ addListener = varArgs(function( eventId, parameters ){
+
+ if( oboeApi[eventId] ) {
+
+ // for events added as .on(event, callback), if there is a
+ // .event() equivalent with special behaviour , pass through
+ // to that:
+ apply(parameters, oboeApi[eventId]);
+ } else {
+
+ // we have a standard Node.js EventEmitter 2-argument call.
+ // The first parameter is the listener.
+ var event = oboeBus(eventId),
+ listener = parameters[0];
+
+ if( fullyQualifiedNamePattern.test(eventId) ) {
+
+ // allow fully-qualified node/path listeners
+ // to be added
+ addForgettableCallback(event, listener);
+ } else {
+
+ // the event has no special handling, pass through
+ // directly onto the event bus:
+ event.on( listener);
+ }
+ }
+
+ return oboeApi; // chaining
+ }),
+
+ /**
+ * Remove any kind of listener that the instance api exposes
+ */
+ removeListener = function( eventId, p2, p3 ){
+
+ if( eventId == 'done' ) {
+
+ rootNodeFinishedEvent.un(p2);
+
+ } else if( eventId == 'node' || eventId == 'path' ) {
+
+ // allow removal of node and path
+ oboeBus.un(eventId + ':' + p2, p3);
+ } else {
+
+ // we have a standard Node.js EventEmitter 2-argument call.
+ // The second parameter is the listener. This may be a call
+ // to remove a fully-qualified node/path listener but requires
+ // no special handling
+ var listener = p2;
+
+ oboeBus(eventId).un(listener);
+ }
+
+ return oboeApi; // chaining
+ };
+
+ /**
+ * Add a callback, wrapped in a try/catch so as to not break the
+ * execution of Oboe if an exception is thrown (fail events are
+ * fired instead)
+ *
+ * The callback is used as the listener id so that it can later be
+ * removed using .un(callback)
+ */
+ function addProtectedCallback(eventName, callback) {
+ oboeBus(eventName).on(protectedCallback(callback), callback);
+ return oboeApi; // chaining
+ }
+
+ /**
+ * Add a callback where, if .forget() is called during the callback's
+ * execution, the callback will be de-registered
+ */
+ function addForgettableCallback(event, callback, listenerId) {
+
+ // listenerId is optional and if not given, the original
+ // callback will be used
+ listenerId = listenerId || callback;
+
+ var safeCallback = protectedCallback(callback);
+
+ event.on( function() {
+
+ var discard = false;
+
+ oboeApi.forget = function(){
+ discard = true;
+ };
+
+ apply( arguments, safeCallback );
+
+ delete oboeApi.forget;
+
+ if( discard ) {
+ event.un(listenerId);
+ }
+ }, listenerId);
+
+ return oboeApi; // chaining
+ }
+
+ /**
+ * wrap a callback so that if it throws, Oboe.js doesn't crash but instead
+ * throw the error in another event loop
+ */
+ function protectedCallback( callback ) {
+ return function() {
+ try{
+ return callback.apply(oboeApi, arguments);
+ }catch(e) {
+ setTimeout(function() {
+ throw new Error(e.message);
+ });
+ }
+ }
+ }
+
+ /**
+ * Return the fully qualified event for when a pattern matches
+ * either a node or a path
+ *
+ * @param type {String} either 'node' or 'path'
+ */
+ function fullyQualifiedPatternMatchEvent(type, pattern) {
+ return oboeBus(type + ':' + pattern);
+ }
+
+ function wrapCallbackToSwapNodeIfSomethingReturned( callback ) {
+ return function() {
+ var returnValueFromCallback = callback.apply(this, arguments);
+
+ if( defined(returnValueFromCallback) ) {
+
+ if( returnValueFromCallback == oboe.drop ) {
+ emitNodeDrop();
+ } else {
+ emitNodeSwap(returnValueFromCallback);
+ }
+ }
+ }
+ }
+
+ function addSingleNodeOrPathListener(eventId, pattern, callback) {
+
+ var effectiveCallback;
+
+ if( eventId == 'node' ) {
+ effectiveCallback = wrapCallbackToSwapNodeIfSomethingReturned(callback);
+ } else {
+ effectiveCallback = callback;
+ }
+
+ addForgettableCallback(
+ fullyQualifiedPatternMatchEvent(eventId, pattern),
+ effectiveCallback,
+ callback
+ );
+ }
+
+ /**
+ * Add several listeners at a time, from a map
+ */
+ function addMultipleNodeOrPathListeners(eventId, listenerMap) {
+
+ for( var pattern in listenerMap ) {
+ addSingleNodeOrPathListener(eventId, pattern, listenerMap[pattern]);
+ }
+ }
+
+ /**
+ * implementation behind .onPath() and .onNode()
+ */
+ function addNodeOrPathListenerApi( eventId, jsonPathOrListenerMap, callback ){
+
+ if( isString(jsonPathOrListenerMap) ) {
+ addSingleNodeOrPathListener(eventId, jsonPathOrListenerMap, callback);
+
+ } else {
+ addMultipleNodeOrPathListeners(eventId, jsonPathOrListenerMap);
+ }
+
+ return oboeApi; // chaining
+ }
+
+
+ // some interface methods are only filled in after we receive
+ // values and are noops before that:
+ oboeBus(ROOT_PATH_FOUND).on( function(rootNode) {
+ oboeApi.root = functor(rootNode);
+ });
+
+ /**
+ * When content starts make the headers readable through the
+ * instance API
+ */
+ oboeBus(HTTP_START).on( function(_statusCode, headers) {
+
+ oboeApi.header = function(name) {
+ return name ? headers[name]
+ : headers
+ ;
+ }
+ });
+
+ /**
+ * Construct and return the public API of the Oboe instance to be
+ * returned to the calling application
+ */
+ return oboeApi = {
+ on : addListener,
+ addListener : addListener,
+ removeListener : removeListener,
+ emit : oboeBus.emit,
+
+ node : partialComplete(addNodeOrPathListenerApi, 'node'),
+ path : partialComplete(addNodeOrPathListenerApi, 'path'),
+
+ done : partialComplete(addForgettableCallback, rootNodeFinishedEvent),
+ start : partialComplete(addProtectedCallback, HTTP_START ),
+
+ // fail doesn't use protectedCallback because
+ // could lead to non-terminating loops
+ fail : oboeBus(FAIL_EVENT).on,
+
+ // public api calling abort fires the ABORTING event
+ abort : oboeBus(ABORTING).emit,
+
+ // initially return nothing for header and root
+ header : noop,
+ root : noop,
+
+ source : contentSource
+ };
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/jsonPath.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/jsonPath.js
new file mode 100644
index 00000000000..59b1434b422
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/jsonPath.js
@@ -0,0 +1,364 @@
+/**
+ * The jsonPath evaluator compiler used for Oboe.js.
+ *
+ * One function is exposed. This function takes a String JSONPath spec and
+ * returns a function to test candidate ascents for matches.
+ *
+ * String jsonPath -> (List ascent) -> Boolean|Object
+ *
+ * This file is coded in a pure functional style. That is, no function has
+ * side effects, every function evaluates to the same value for the same
+ * arguments and no variables are reassigned.
+ */
+// the call to jsonPathSyntax injects the token syntaxes that are needed
+// inside the compiler
+var jsonPathCompiler = jsonPathSyntax(function (pathNodeSyntax,
+ doubleDotSyntax,
+ dotSyntax,
+ bangSyntax,
+ emptySyntax ) {
+
+ var CAPTURING_INDEX = 1;
+ var NAME_INDEX = 2;
+ var FIELD_LIST_INDEX = 3;
+
+ var headKey = compose2(keyOf, head),
+ headNode = compose2(nodeOf, head);
+
+ /**
+ * Create an evaluator function for a named path node, expressed in the
+ * JSONPath like:
+ * foo
+ * ["bar"]
+ * [2]
+ */
+ function nameClause(previousExpr, detection ) {
+
+ var name = detection[NAME_INDEX],
+
+ matchesName = ( !name || name == '*' )
+ ? always
+ : function(ascent){return headKey(ascent) == name};
+
+
+ return lazyIntersection(matchesName, previousExpr);
+ }
+
+ /**
+ * Create an evaluator function for a a duck-typed node, expressed like:
+ *
+ * {spin, taste, colour}
+ * .particle{spin, taste, colour}
+ * *{spin, taste, colour}
+ */
+ function duckTypeClause(previousExpr, detection) {
+
+ var fieldListStr = detection[FIELD_LIST_INDEX];
+
+ if (!fieldListStr)
+ return previousExpr; // don't wrap at all, return given expr as-is
+
+ var hasAllrequiredFields = partialComplete(
+ hasAllProperties,
+ arrayAsList(fieldListStr.split(/\W+/))
+ ),
+
+ isMatch = compose2(
+ hasAllrequiredFields,
+ headNode
+ );
+
+ return lazyIntersection(isMatch, previousExpr);
+ }
+
+ /**
+ * Expression for $, returns the evaluator function
+ */
+ function capture( previousExpr, detection ) {
+
+ // extract meaning from the detection
+ var capturing = !!detection[CAPTURING_INDEX];
+
+ if (!capturing)
+ return previousExpr; // don't wrap at all, return given expr as-is
+
+ return lazyIntersection(previousExpr, head);
+
+ }
+
+ /**
+ * Create an evaluator function that moves onto the next item on the
+ * lists. This function is the place where the logic to move up a
+ * level in the ascent exists.
+ *
+ * Eg, for JSONPath ".foo" we need skip1(nameClause(always, [,'foo']))
+ */
+ function skip1(previousExpr) {
+
+
+ if( previousExpr == always ) {
+ /* If there is no previous expression this consume command
+ is at the start of the jsonPath.
+ Since JSONPath specifies what we'd like to find but not
+ necessarily everything leading down to it, when running
+ out of JSONPath to check against we default to true */
+ return always;
+ }
+
+ /** return true if the ascent we have contains only the JSON root,
+ * false otherwise
+ */
+ function notAtRoot(ascent){
+ return headKey(ascent) != ROOT_PATH;
+ }
+
+ return lazyIntersection(
+ /* If we're already at the root but there are more
+ expressions to satisfy, can't consume any more. No match.
+
+ This check is why none of the other exprs have to be able
+ to handle empty lists; skip1 is the only evaluator that
+ moves onto the next token and it refuses to do so once it
+ reaches the last item in the list. */
+ notAtRoot,
+
+ /* We are not at the root of the ascent yet.
+ Move to the next level of the ascent by handing only
+ the tail to the previous expression */
+ compose2(previousExpr, tail)
+ );
+
+ }
+
+ /**
+ * Create an evaluator function for the .. (double dot) token. Consumes
+ * zero or more levels of the ascent, the fewest that are required to find
+ * a match when given to previousExpr.
+ */
+ function skipMany(previousExpr) {
+
+ if( previousExpr == always ) {
+ /* If there is no previous expression this consume command
+ is at the start of the jsonPath.
+ Since JSONPath specifies what we'd like to find but not
+ necessarily everything leading down to it, when running
+ out of JSONPath to check against we default to true */
+ return always;
+ }
+
+ var
+ // In JSONPath .. is equivalent to !.. so if .. reaches the root
+ // the match has succeeded. Ie, we might write ..foo or !..foo
+ // and both should match identically.
+ terminalCaseWhenArrivingAtRoot = rootExpr(),
+ terminalCaseWhenPreviousExpressionIsSatisfied = previousExpr,
+ recursiveCase = skip1(function(ascent) {
+ return cases(ascent);
+ }),
+
+ cases = lazyUnion(
+ terminalCaseWhenArrivingAtRoot
+ , terminalCaseWhenPreviousExpressionIsSatisfied
+ , recursiveCase
+ );
+
+ return cases;
+ }
+
+ /**
+ * Generate an evaluator for ! - matches only the root element of the json
+ * and ignores any previous expressions since nothing may precede !.
+ */
+ function rootExpr() {
+
+ return function(ascent){
+ return headKey(ascent) == ROOT_PATH;
+ };
+ }
+
+ /**
+ * Generate a statement wrapper to sit around the outermost
+ * clause evaluator.
+ *
+ * Handles the case where the capturing is implicit because the JSONPath
+ * did not contain a '$' by returning the last node.
+ */
+ function statementExpr(lastClause) {
+
+ return function(ascent) {
+
+ // kick off the evaluation by passing through to the last clause
+ var exprMatch = lastClause(ascent);
+
+ return exprMatch === true ? head(ascent) : exprMatch;
+ };
+ }
+
+ /**
+ * For when a token has been found in the JSONPath input.
+ * Compiles the parser for that token and returns in combination with the
+ * parser already generated.
+ *
+ * @param {Function} exprs a list of the clause evaluator generators for
+ * the token that was found
+ * @param {Function} parserGeneratedSoFar the parser already found
+ * @param {Array} detection the match given by the regex engine when
+ * the feature was found
+ */
+ function expressionsReader( exprs, parserGeneratedSoFar, detection ) {
+
+ // if exprs is zero-length foldR will pass back the
+ // parserGeneratedSoFar as-is so we don't need to treat
+ // this as a special case
+
+ return foldR(
+ function( parserGeneratedSoFar, expr ){
+
+ return expr(parserGeneratedSoFar, detection);
+ },
+ parserGeneratedSoFar,
+ exprs
+ );
+
+ }
+
+ /**
+ * If jsonPath matches the given detector function, creates a function which
+ * evaluates against every clause in the clauseEvaluatorGenerators. The
+ * created function is propagated to the onSuccess function, along with
+ * the remaining unparsed JSONPath substring.
+ *
+ * The intended use is to create a clauseMatcher by filling in
+ * the first two arguments, thus providing a function that knows
+ * some syntax to match and what kind of generator to create if it
+ * finds it. The parameter list once completed is:
+ *
+ * (jsonPath, parserGeneratedSoFar, onSuccess)
+ *
+ * onSuccess may be compileJsonPathToFunction, to recursively continue
+ * parsing after finding a match or returnFoundParser to stop here.
+ */
+ function generateClauseReaderIfTokenFound (
+
+ tokenDetector, clauseEvaluatorGenerators,
+
+ jsonPath, parserGeneratedSoFar, onSuccess) {
+
+ var detected = tokenDetector(jsonPath);
+
+ if(detected) {
+ var compiledParser = expressionsReader(
+ clauseEvaluatorGenerators,
+ parserGeneratedSoFar,
+ detected
+ ),
+
+ remainingUnparsedJsonPath = jsonPath.substr(len(detected[0]));
+
+ return onSuccess(remainingUnparsedJsonPath, compiledParser);
+ }
+ }
+
+ /**
+ * Partially completes generateClauseReaderIfTokenFound above.
+ */
+ function clauseMatcher(tokenDetector, exprs) {
+
+ return partialComplete(
+ generateClauseReaderIfTokenFound,
+ tokenDetector,
+ exprs
+ );
+ }
+
+ /**
+ * clauseForJsonPath is a function which attempts to match against
+ * several clause matchers in order until one matches. If non match the
+ * jsonPath expression is invalid and an error is thrown.
+ *
+ * The parameter list is the same as a single clauseMatcher:
+ *
+ * (jsonPath, parserGeneratedSoFar, onSuccess)
+ */
+ var clauseForJsonPath = lazyUnion(
+
+ clauseMatcher(pathNodeSyntax , list( capture,
+ duckTypeClause,
+ nameClause,
+ skip1 ))
+
+ , clauseMatcher(doubleDotSyntax , list( skipMany))
+
+ // dot is a separator only (like whitespace in other languages) but
+ // rather than make it a special case, use an empty list of
+ // expressions when this token is found
+ , clauseMatcher(dotSyntax , list() )
+
+ , clauseMatcher(bangSyntax , list( capture,
+ rootExpr))
+
+ , clauseMatcher(emptySyntax , list( statementExpr))
+
+ , function (jsonPath) {
+ throw Error('"' + jsonPath + '" could not be tokenised')
+ }
+ );
+
+
+ /**
+ * One of two possible values for the onSuccess argument of
+ * generateClauseReaderIfTokenFound.
+ *
+ * When this function is used, generateClauseReaderIfTokenFound simply
+ * returns the compiledParser that it made, regardless of if there is
+ * any remaining jsonPath to be compiled.
+ */
+ function returnFoundParser(_remainingJsonPath, compiledParser){
+ return compiledParser
+ }
+
+ /**
+ * Recursively compile a JSONPath expression.
+ *
+ * This function serves as one of two possible values for the onSuccess
+ * argument of generateClauseReaderIfTokenFound, meaning continue to
+ * recursively compile. Otherwise, returnFoundParser is given and
+ * compilation terminates.
+ */
+ function compileJsonPathToFunction( uncompiledJsonPath,
+ parserGeneratedSoFar ) {
+
+ /**
+ * On finding a match, if there is remaining text to be compiled
+ * we want to either continue parsing using a recursive call to
+ * compileJsonPathToFunction. Otherwise, we want to stop and return
+ * the parser that we have found so far.
+ */
+ var onFind = uncompiledJsonPath
+ ? compileJsonPathToFunction
+ : returnFoundParser;
+
+ return clauseForJsonPath(
+ uncompiledJsonPath,
+ parserGeneratedSoFar,
+ onFind
+ );
+ }
+
+ /**
+ * This is the function that we expose to the rest of the library.
+ */
+ return function(jsonPath){
+
+ try {
+ // Kick off the recursive parsing of the jsonPath
+ return compileJsonPathToFunction(jsonPath, always);
+
+ } catch( e ) {
+ throw Error( 'Could not compile "' + jsonPath +
+ '" because ' + e.message
+ );
+ }
+ }
+
+});
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/jsonPathSyntax.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/jsonPathSyntax.js
new file mode 100644
index 00000000000..8c54ed334e1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/jsonPathSyntax.js
@@ -0,0 +1,115 @@
+var jsonPathSyntax = (function() {
+
+ var
+
+ /**
+ * Export a regular expression as a simple function by exposing just
+ * the Regex#exec. This allows regex tests to be used under the same
+ * interface as differently implemented tests, or for a user of the
+ * tests to not concern themselves with their implementation as regular
+ * expressions.
+ *
+ * This could also be expressed point-free as:
+ * Function.prototype.bind.bind(RegExp.prototype.exec),
+ *
+ * But that's far too confusing! (and not even smaller once minified
+ * and gzipped)
+ */
+ regexDescriptor = function regexDescriptor(regex) {
+ return regex.exec.bind(regex);
+ }
+
+ /**
+ * Join several regular expressions and express as a function.
+ * This allows the token patterns to reuse component regular expressions
+ * instead of being expressed in full using huge and confusing regular
+ * expressions.
+ */
+ , jsonPathClause = varArgs(function( componentRegexes ) {
+
+ // The regular expressions all start with ^ because we
+ // only want to find matches at the start of the
+ // JSONPath fragment we are inspecting
+ componentRegexes.unshift(/^/);
+
+ return regexDescriptor(
+ RegExp(
+ componentRegexes.map(attr('source')).join('')
+ )
+ );
+ })
+
+ , possiblyCapturing = /(\$?)/
+ , namedNode = /([\w-_]+|\*)/
+ , namePlaceholder = /()/
+ , nodeInArrayNotation = /\["([^"]+)"\]/
+ , numberedNodeInArrayNotation = /\[(\d+|\*)\]/
+ , fieldList = /{([\w ]*?)}/
+ , optionalFieldList = /(?:{([\w ]*?)})?/
+
+
+ // foo or *
+ , jsonPathNamedNodeInObjectNotation = jsonPathClause(
+ possiblyCapturing,
+ namedNode,
+ optionalFieldList
+ )
+
+ // ["foo"]
+ , jsonPathNamedNodeInArrayNotation = jsonPathClause(
+ possiblyCapturing,
+ nodeInArrayNotation,
+ optionalFieldList
+ )
+
+ // [2] or [*]
+ , jsonPathNumberedNodeInArrayNotation = jsonPathClause(
+ possiblyCapturing,
+ numberedNodeInArrayNotation,
+ optionalFieldList
+ )
+
+ // {a b c}
+ , jsonPathPureDuckTyping = jsonPathClause(
+ possiblyCapturing,
+ namePlaceholder,
+ fieldList
+ )
+
+ // ..
+ , jsonPathDoubleDot = jsonPathClause(/\.\./)
+
+ // .
+ , jsonPathDot = jsonPathClause(/\./)
+
+ // !
+ , jsonPathBang = jsonPathClause(
+ possiblyCapturing,
+ /!/
+ )
+
+ // nada!
+ , emptyString = jsonPathClause(/$/)
+
+ ;
+
+
+ /* We export only a single function. When called, this function injects
+ into another function the descriptors from above.
+ */
+ return function (fn){
+ return fn(
+ lazyUnion(
+ jsonPathNamedNodeInObjectNotation
+ , jsonPathNamedNodeInArrayNotation
+ , jsonPathNumberedNodeInArrayNotation
+ , jsonPathPureDuckTyping
+ )
+ , jsonPathDoubleDot
+ , jsonPathDot
+ , jsonPathBang
+ , emptyString
+ );
+ };
+
+}()); \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/libs/clarinet.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/libs/clarinet.js
new file mode 100644
index 00000000000..c67bc83034d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/libs/clarinet.js
@@ -0,0 +1,501 @@
+/*
+ This is a slightly hacked-up browser only version of clarinet
+
+ * some features removed to help keep browser Oboe under
+ the 5k micro-library limit
+ * plug directly into event bus
+
+ For the original go here:
+ https://github.com/dscape/clarinet
+
+ We receive the events:
+ STREAM_DATA
+ STREAM_END
+
+ We emit the events:
+ SAX_KEY
+ SAX_VALUE_OPEN
+ SAX_VALUE_CLOSE
+ FAIL_EVENT
+ */
+
+function clarinet(eventBus) {
+ "use strict";
+
+ var
+ // shortcut some events on the bus
+ emitSaxKey = eventBus(SAX_KEY).emit,
+ emitValueOpen = eventBus(SAX_VALUE_OPEN).emit,
+ emitValueClose = eventBus(SAX_VALUE_CLOSE).emit,
+ emitFail = eventBus(FAIL_EVENT).emit,
+
+ MAX_BUFFER_LENGTH = 64 * 1024
+ , stringTokenPattern = /[\\"\n]/g
+ , _n = 0
+
+ // states
+ , BEGIN = _n++
+ , VALUE = _n++ // general stuff
+ , OPEN_OBJECT = _n++ // {
+ , CLOSE_OBJECT = _n++ // }
+ , OPEN_ARRAY = _n++ // [
+ , CLOSE_ARRAY = _n++ // ]
+ , STRING = _n++ // ""
+ , OPEN_KEY = _n++ // , "a"
+ , CLOSE_KEY = _n++ // :
+ , TRUE = _n++ // r
+ , TRUE2 = _n++ // u
+ , TRUE3 = _n++ // e
+ , FALSE = _n++ // a
+ , FALSE2 = _n++ // l
+ , FALSE3 = _n++ // s
+ , FALSE4 = _n++ // e
+ , NULL = _n++ // u
+ , NULL2 = _n++ // l
+ , NULL3 = _n++ // l
+ , NUMBER_DECIMAL_POINT = _n++ // .
+ , NUMBER_DIGIT = _n // [0-9]
+
+ // setup initial parser values
+ , bufferCheckPosition = MAX_BUFFER_LENGTH
+ , latestError
+ , c
+ , p
+ , textNode = undefined
+ , numberNode = ""
+ , slashed = false
+ , closed = false
+ , state = BEGIN
+ , stack = []
+ , unicodeS = null
+ , unicodeI = 0
+ , depth = 0
+ , position = 0
+ , column = 0 //mostly for error reporting
+ , line = 1
+ ;
+
+ function checkBufferLength () {
+
+ var maxActual = 0;
+
+ if (textNode !== undefined && textNode.length > MAX_BUFFER_LENGTH) {
+ emitError("Max buffer length exceeded: textNode");
+ maxActual = Math.max(maxActual, textNode.length);
+ }
+ if (numberNode.length > MAX_BUFFER_LENGTH) {
+ emitError("Max buffer length exceeded: numberNode");
+ maxActual = Math.max(maxActual, numberNode.length);
+ }
+
+ bufferCheckPosition = (MAX_BUFFER_LENGTH - maxActual)
+ + position;
+ }
+
+ eventBus(STREAM_DATA).on(handleData);
+
+ /* At the end of the http content close the clarinet
+ This will provide an error if the total content provided was not
+ valid json, ie if not all arrays, objects and Strings closed properly */
+ eventBus(STREAM_END).on(handleStreamEnd);
+
+ function emitError (errorString) {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+
+ latestError = Error(errorString + "\nLn: "+line+
+ "\nCol: "+column+
+ "\nChr: "+c);
+
+ emitFail(errorReport(undefined, undefined, latestError));
+ }
+
+ function handleStreamEnd() {
+ if( state == BEGIN ) {
+ // Handle the case where the stream closes without ever receiving
+ // any input. This isn't an error - response bodies can be blank,
+ // particularly for 204 http responses
+
+ // Because of how Oboe is currently implemented, we parse a
+ // completely empty stream as containing an empty object.
+ // This is because Oboe's done event is only fired when the
+ // root object of the JSON stream closes.
+
+ // This should be decoupled and attached instead to the input stream
+ // from the http (or whatever) resource ending.
+ // If this decoupling could happen the SAX parser could simply emit
+ // zero events on a completely empty input.
+ emitValueOpen({});
+ emitValueClose();
+
+ closed = true;
+ return;
+ }
+
+ if (state !== VALUE || depth !== 0)
+ emitError("Unexpected end");
+
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+
+ closed = true;
+ }
+
+ function whitespace(c){
+ return c == '\r' || c == '\n' || c == ' ' || c == '\t';
+ }
+
+ function handleData (chunk) {
+
+ // this used to throw the error but inside Oboe we will have already
+ // gotten the error when it was emitted. The important thing is to
+ // not continue with the parse.
+ if (latestError)
+ return;
+
+ if (closed) {
+ return emitError("Cannot write after close");
+ }
+
+ var i = 0;
+ c = chunk[0];
+
+ while (c) {
+ p = c;
+ c = chunk[i++];
+ if(!c) break;
+
+ position ++;
+ if (c == "\n") {
+ line ++;
+ column = 0;
+ } else column ++;
+ switch (state) {
+
+ case BEGIN:
+ if (c === "{") state = OPEN_OBJECT;
+ else if (c === "[") state = OPEN_ARRAY;
+ else if (!whitespace(c))
+ return emitError("Non-whitespace before {[.");
+ continue;
+
+ case OPEN_KEY:
+ case OPEN_OBJECT:
+ if (whitespace(c)) continue;
+ if(state === OPEN_KEY) stack.push(CLOSE_KEY);
+ else {
+ if(c === '}') {
+ emitValueOpen({});
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ continue;
+ } else stack.push(CLOSE_OBJECT);
+ }
+ if(c === '"')
+ state = STRING;
+ else
+ return emitError("Malformed object key should start with \" ");
+ continue;
+
+ case CLOSE_KEY:
+ case CLOSE_OBJECT:
+ if (whitespace(c)) continue;
+
+ if(c===':') {
+ if(state === CLOSE_OBJECT) {
+ stack.push(CLOSE_OBJECT);
+
+ if (textNode !== undefined) {
+ // was previously (in upstream Clarinet) one event
+ // - object open came with the text of the first
+ emitValueOpen({});
+ emitSaxKey(textNode);
+ textNode = undefined;
+ }
+ depth++;
+ } else {
+ if (textNode !== undefined) {
+ emitSaxKey(textNode);
+ textNode = undefined;
+ }
+ }
+ state = VALUE;
+ } else if (c==='}') {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ } else if(c===',') {
+ if(state === CLOSE_OBJECT)
+ stack.push(CLOSE_OBJECT);
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ state = OPEN_KEY;
+ } else
+ return emitError('Bad object');
+ continue;
+
+ case OPEN_ARRAY: // after an array there always a value
+ case VALUE:
+ if (whitespace(c)) continue;
+ if(state===OPEN_ARRAY) {
+ emitValueOpen([]);
+ depth++;
+ state = VALUE;
+ if(c === ']') {
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ continue;
+ } else {
+ stack.push(CLOSE_ARRAY);
+ }
+ }
+ if(c === '"') state = STRING;
+ else if(c === '{') state = OPEN_OBJECT;
+ else if(c === '[') state = OPEN_ARRAY;
+ else if(c === 't') state = TRUE;
+ else if(c === 'f') state = FALSE;
+ else if(c === 'n') state = NULL;
+ else if(c === '-') { // keep and continue
+ numberNode += c;
+ } else if(c==='0') {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else if('123456789'.indexOf(c) !== -1) {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else
+ return emitError("Bad value");
+ continue;
+
+ case CLOSE_ARRAY:
+ if(c===',') {
+ stack.push(CLOSE_ARRAY);
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ state = VALUE;
+ } else if (c===']') {
+ if (textNode !== undefined) {
+ emitValueOpen(textNode);
+ emitValueClose();
+ textNode = undefined;
+ }
+ emitValueClose();
+ depth--;
+ state = stack.pop() || VALUE;
+ } else if (whitespace(c))
+ continue;
+ else
+ return emitError('Bad array');
+ continue;
+
+ case STRING:
+ if (textNode === undefined) {
+ textNode = "";
+ }
+
+ // thanks thejh, this is an about 50% performance improvement.
+ var starti = i-1;
+
+ STRING_BIGLOOP: while (true) {
+
+ // zero means "no unicode active". 1-4 mean "parse some more". end after 4.
+ while (unicodeI > 0) {
+ unicodeS += c;
+ c = chunk.charAt(i++);
+ if (unicodeI === 4) {
+ // TODO this might be slow? well, probably not used too often anyway
+ textNode += String.fromCharCode(parseInt(unicodeS, 16));
+ unicodeI = 0;
+ starti = i-1;
+ } else {
+ unicodeI++;
+ }
+ // we can just break here: no stuff we skipped that still has to be sliced out or so
+ if (!c) break STRING_BIGLOOP;
+ }
+ if (c === '"' && !slashed) {
+ state = stack.pop() || VALUE;
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ if (c === '\\' && !slashed) {
+ slashed = true;
+ textNode += chunk.substring(starti, i-1);
+ c = chunk.charAt(i++);
+ if (!c) break;
+ }
+ if (slashed) {
+ slashed = false;
+ if (c === 'n') { textNode += '\n'; }
+ else if (c === 'r') { textNode += '\r'; }
+ else if (c === 't') { textNode += '\t'; }
+ else if (c === 'f') { textNode += '\f'; }
+ else if (c === 'b') { textNode += '\b'; }
+ else if (c === 'u') {
+ // \uxxxx. meh!
+ unicodeI = 1;
+ unicodeS = '';
+ } else {
+ textNode += c;
+ }
+ c = chunk.charAt(i++);
+ starti = i-1;
+ if (!c) break;
+ else continue;
+ }
+
+ stringTokenPattern.lastIndex = i;
+ var reResult = stringTokenPattern.exec(chunk);
+ if (!reResult) {
+ i = chunk.length+1;
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ i = reResult.index+1;
+ c = chunk.charAt(reResult.index);
+ if (!c) {
+ textNode += chunk.substring(starti, i-1);
+ break;
+ }
+ }
+ continue;
+
+ case TRUE:
+ if (!c) continue; // strange buffers
+ if (c==='r') state = TRUE2;
+ else
+ return emitError( 'Invalid true started with t'+ c);
+ continue;
+
+ case TRUE2:
+ if (!c) continue;
+ if (c==='u') state = TRUE3;
+ else
+ return emitError('Invalid true started with tr'+ c);
+ continue;
+
+ case TRUE3:
+ if (!c) continue;
+ if(c==='e') {
+ emitValueOpen(true);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid true started with tru'+ c);
+ continue;
+
+ case FALSE:
+ if (!c) continue;
+ if (c==='a') state = FALSE2;
+ else
+ return emitError('Invalid false started with f'+ c);
+ continue;
+
+ case FALSE2:
+ if (!c) continue;
+ if (c==='l') state = FALSE3;
+ else
+ return emitError('Invalid false started with fa'+ c);
+ continue;
+
+ case FALSE3:
+ if (!c) continue;
+ if (c==='s') state = FALSE4;
+ else
+ return emitError('Invalid false started with fal'+ c);
+ continue;
+
+ case FALSE4:
+ if (!c) continue;
+ if (c==='e') {
+ emitValueOpen(false);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid false started with fals'+ c);
+ continue;
+
+ case NULL:
+ if (!c) continue;
+ if (c==='u') state = NULL2;
+ else
+ return emitError('Invalid null started with n'+ c);
+ continue;
+
+ case NULL2:
+ if (!c) continue;
+ if (c==='l') state = NULL3;
+ else
+ return emitError('Invalid null started with nu'+ c);
+ continue;
+
+ case NULL3:
+ if (!c) continue;
+ if(c==='l') {
+ emitValueOpen(null);
+ emitValueClose();
+ state = stack.pop() || VALUE;
+ } else
+ return emitError('Invalid null started with nul'+ c);
+ continue;
+
+ case NUMBER_DECIMAL_POINT:
+ if(c==='.') {
+ numberNode += c;
+ state = NUMBER_DIGIT;
+ } else
+ return emitError('Leading zero not followed by .');
+ continue;
+
+ case NUMBER_DIGIT:
+ if('0123456789'.indexOf(c) !== -1) numberNode += c;
+ else if (c==='.') {
+ if(numberNode.indexOf('.')!==-1)
+ return emitError('Invalid number has two dots');
+ numberNode += c;
+ } else if (c==='e' || c==='E') {
+ if(numberNode.indexOf('e')!==-1 ||
+ numberNode.indexOf('E')!==-1 )
+ return emitError('Invalid number has two exponential');
+ numberNode += c;
+ } else if (c==="+" || c==="-") {
+ if(!(p==='e' || p==='E'))
+ return emitError('Invalid symbol in number');
+ numberNode += c;
+ } else {
+ if (numberNode) {
+ emitValueOpen(parseFloat(numberNode));
+ emitValueClose();
+ numberNode = "";
+ }
+ i--; // go back one
+ state = stack.pop() || VALUE;
+ }
+ continue;
+
+ default:
+ return emitError("Unknown state: " + state);
+ }
+ }
+ if (position >= bufferCheckPosition)
+ checkBufferLength();
+ }
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/lists.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/lists.js
new file mode 100644
index 00000000000..17b3a4f7efe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/lists.js
@@ -0,0 +1,192 @@
+/**
+ * Like cons in Lisp
+ */
+function cons(x, xs) {
+
+ /* Internally lists are linked 2-element Javascript arrays.
+
+ Ideally the return here would be Object.freeze([x,xs])
+ so that bugs related to mutation are found fast.
+ However, cons is right on the critical path for
+ performance and this slows oboe-mark down by
+ ~25%. Under theoretical future JS engines that freeze more
+ efficiently (possibly even use immutability to
+ run faster) this should be considered for
+ restoration.
+ */
+
+ return [x,xs];
+}
+
+/**
+ * The empty list
+ */
+var emptyList = null,
+
+/**
+ * Get the head of a list.
+ *
+ * Ie, head(cons(a,b)) = a
+ */
+ head = attr(0),
+
+/**
+ * Get the tail of a list.
+ *
+ * Ie, tail(cons(a,b)) = b
+ */
+ tail = attr(1);
+
+
+/**
+ * Converts an array to a list
+ *
+ * asList([a,b,c])
+ *
+ * is equivalent to:
+ *
+ * cons(a, cons(b, cons(c, emptyList)))
+ **/
+function arrayAsList(inputArray){
+
+ return reverseList(
+ inputArray.reduce(
+ flip(cons),
+ emptyList
+ )
+ );
+}
+
+/**
+ * A varargs version of arrayAsList. Works a bit like list
+ * in LISP.
+ *
+ * list(a,b,c)
+ *
+ * is equivalent to:
+ *
+ * cons(a, cons(b, cons(c, emptyList)))
+ */
+var list = varArgs(arrayAsList);
+
+/**
+ * Convert a list back to a js native array
+ */
+function listAsArray(list){
+
+ return foldR( function(arraySoFar, listItem){
+
+ arraySoFar.unshift(listItem);
+ return arraySoFar;
+
+ }, [], list );
+
+}
+
+/**
+ * Map a function over a list
+ */
+function map(fn, list) {
+
+ return list
+ ? cons(fn(head(list)), map(fn,tail(list)))
+ : emptyList
+ ;
+}
+
+/**
+ * foldR implementation. Reduce a list down to a single value.
+ *
+ * @pram {Function} fn (rightEval, curVal) -> result
+ */
+function foldR(fn, startValue, list) {
+
+ return list
+ ? fn(foldR(fn, startValue, tail(list)), head(list))
+ : startValue
+ ;
+}
+
+/**
+ * foldR implementation. Reduce a list down to a single value.
+ *
+ * @pram {Function} fn (rightEval, curVal) -> result
+ */
+function foldR1(fn, list) {
+
+ return tail(list)
+ ? fn(foldR1(fn, tail(list)), head(list))
+ : head(list)
+ ;
+}
+
+
+/**
+ * Return a list like the one given but with the first instance equal
+ * to item removed
+ */
+function without(list, test, removedFn) {
+
+ return withoutInner(list, removedFn || noop);
+
+ function withoutInner(subList, removedFn) {
+ return subList
+ ? ( test(head(subList))
+ ? (removedFn(head(subList)), tail(subList))
+ : cons(head(subList), withoutInner(tail(subList), removedFn))
+ )
+ : emptyList
+ ;
+ }
+}
+
+/**
+ * Returns true if the given function holds for every item in
+ * the list, false otherwise
+ */
+function all(fn, list) {
+
+ return !list ||
+ ( fn(head(list)) && all(fn, tail(list)) );
+}
+
+/**
+ * Call every function in a list of functions with the same arguments
+ *
+ * This doesn't make any sense if we're doing pure functional because
+ * it doesn't return anything. Hence, this is only really useful if the
+ * functions being called have side-effects.
+ */
+function applyEach(fnList, args) {
+
+ if( fnList ) {
+ head(fnList).apply(null, args);
+
+ applyEach(tail(fnList), args);
+ }
+}
+
+/**
+ * Reverse the order of a list
+ */
+function reverseList(list){
+
+ // js re-implementation of 3rd solution from:
+ // http://www.haskell.org/haskellwiki/99_questions/Solutions/5
+ function reverseInner( list, reversedAlready ) {
+ if( !list ) {
+ return reversedAlready;
+ }
+
+ return reverseInner(tail(list), cons(head(list), reversedAlready))
+ }
+
+ return reverseInner(list, emptyList);
+}
+
+function first(test, list) {
+ return list &&
+ (test(head(list))
+ ? head(list)
+ : first(test,tail(list)));
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/parseResponseHeaders.browser.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/parseResponseHeaders.browser.js
new file mode 100644
index 00000000000..8a2d27b6a50
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/parseResponseHeaders.browser.js
@@ -0,0 +1,24 @@
+// based on gist https://gist.github.com/monsur/706839
+
+/**
+ * XmlHttpRequest's getAllResponseHeaders() method returns a string of response
+ * headers according to the format described here:
+ * http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method
+ * This method parses that string into a user-friendly key/value pair object.
+ */
+function parseResponseHeaders(headerStr) {
+ var headers = {};
+
+ headerStr && headerStr.split('\u000d\u000a')
+ .forEach(function(headerPair){
+
+ // Can't use split() here because it does the wrong thing
+ // if the header value has the string ": " in it.
+ var index = headerPair.indexOf('\u003a\u0020');
+
+ headers[headerPair.substring(0, index)]
+ = headerPair.substring(index + 2);
+ });
+
+ return headers;
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/patternAdapter.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/patternAdapter.js
new file mode 100644
index 00000000000..f51670e68ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/patternAdapter.js
@@ -0,0 +1,112 @@
+/**
+ * The pattern adaptor listens for newListener and removeListener
+ * events. When patterns are added or removed it compiles the JSONPath
+ * and wires them up.
+ *
+ * When nodes and paths are found it emits the fully-qualified match
+ * events with parameters ready to ship to the outside world
+ */
+
+function patternAdapter(oboeBus, jsonPathCompiler) {
+
+ var predicateEventMap = {
+ node:oboeBus(NODE_CLOSED)
+ , path:oboeBus(NODE_OPENED)
+ };
+
+ function emitMatchingNode(emitMatch, node, ascent) {
+
+ /*
+ We're now calling to the outside world where Lisp-style
+ lists will not be familiar. Convert to standard arrays.
+
+ Also, reverse the order because it is more common to
+ list paths "root to leaf" than "leaf to root" */
+ var descent = reverseList(ascent);
+
+ emitMatch(
+ node,
+
+ // To make a path, strip off the last item which is the special
+ // ROOT_PATH token for the 'path' to the root node
+ listAsArray(tail(map(keyOf,descent))), // path
+ listAsArray(map(nodeOf, descent)) // ancestors
+ );
+ }
+
+ /*
+ * Set up the catching of events such as NODE_CLOSED and NODE_OPENED and, if
+ * matching the specified pattern, propagate to pattern-match events such as
+ * oboeBus('node:!')
+ *
+ *
+ *
+ * @param {Function} predicateEvent
+ * either oboeBus(NODE_CLOSED) or oboeBus(NODE_OPENED).
+ * @param {Function} compiledJsonPath
+ */
+ function addUnderlyingListener( fullEventName, predicateEvent, compiledJsonPath ){
+
+ var emitMatch = oboeBus(fullEventName).emit;
+
+ predicateEvent.on( function (ascent) {
+
+ var maybeMatchingMapping = compiledJsonPath(ascent);
+
+ /* Possible values for maybeMatchingMapping are now:
+
+ false:
+ we did not match
+
+ an object/array/string/number/null:
+ we matched and have the node that matched.
+ Because nulls are valid json values this can be null.
+
+ undefined:
+ we matched but don't have the matching node yet.
+ ie, we know there is an upcoming node that matches but we
+ can't say anything else about it.
+ */
+ if (maybeMatchingMapping !== false) {
+
+ emitMatchingNode(
+ emitMatch,
+ nodeOf(maybeMatchingMapping),
+ ascent
+ );
+ }
+ }, fullEventName);
+
+ oboeBus('removeListener').on( function(removedEventName){
+
+ // if the fully qualified match event listener is later removed, clean up
+ // by removing the underlying listener if it was the last using that pattern:
+
+ if( removedEventName == fullEventName ) {
+
+ if( !oboeBus(removedEventName).listeners( )) {
+ predicateEvent.un( fullEventName );
+ }
+ }
+ });
+ }
+
+ oboeBus('newListener').on( function(fullEventName){
+
+ var match = /(node|path):(.*)/.exec(fullEventName);
+
+ if( match ) {
+ var predicateEvent = predicateEventMap[match[1]];
+
+ if( !predicateEvent.hasListener( fullEventName) ) {
+
+ addUnderlyingListener(
+ fullEventName,
+ predicateEvent,
+ jsonPathCompiler( match[2] )
+ );
+ }
+ }
+ })
+
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/pubSub.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/pubSub.js
new file mode 100644
index 00000000000..7d9d3f3c510
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/pubSub.js
@@ -0,0 +1,64 @@
+/**
+ * pubSub is a curried interface for listening to and emitting
+ * events.
+ *
+ * If we get a bus:
+ *
+ * var bus = pubSub();
+ *
+ * We can listen to event 'foo' like:
+ *
+ * bus('foo').on(myCallback)
+ *
+ * And emit event foo like:
+ *
+ * bus('foo').emit()
+ *
+ * or, with a parameter:
+ *
+ * bus('foo').emit('bar')
+ *
+ * All functions can be cached and don't need to be
+ * bound. Ie:
+ *
+ * var fooEmitter = bus('foo').emit
+ * fooEmitter('bar'); // emit an event
+ * fooEmitter('baz'); // emit another
+ *
+ * There's also an uncurried[1] shortcut for .emit and .on:
+ *
+ * bus.on('foo', callback)
+ * bus.emit('foo', 'bar')
+ *
+ * [1]: http://zvon.org/other/haskell/Outputprelude/uncurry_f.html
+ */
+function pubSub(){
+
+ var singles = {},
+ newListener = newSingle('newListener'),
+ removeListener = newSingle('removeListener');
+
+ function newSingle(eventName) {
+ return singles[eventName] = singleEventPubSub(
+ eventName,
+ newListener,
+ removeListener
+ );
+ }
+
+ /** pubSub instances are functions */
+ function pubSubInstance( eventName ){
+
+ return singles[eventName] || newSingle( eventName );
+ }
+
+ // add convenience EventEmitter-style uncurried form of 'emit' and 'on'
+ ['emit', 'on', 'un'].forEach(function(methodName){
+
+ pubSubInstance[methodName] = varArgs(function(eventName, parameters){
+ apply( parameters, pubSubInstance( eventName )[methodName]);
+ });
+ });
+
+ return pubSubInstance;
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/publicApi.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/publicApi.js
new file mode 100644
index 00000000000..2b375729832
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/publicApi.js
@@ -0,0 +1,56 @@
+// export public API
+function oboe(arg1) {
+
+ // We use duck-typing to detect if the parameter given is a stream, with the
+ // below list of parameters.
+ // Unpipe and unshift would normally be present on a stream but this breaks
+ // compatibility with Request streams.
+ // See https://github.com/jimhigson/oboe.js/issues/65
+
+ var nodeStreamMethodNames = list('resume', 'pause', 'pipe'),
+ isStream = partialComplete(
+ hasAllProperties
+ , nodeStreamMethodNames
+ );
+
+ if( arg1 ) {
+ if (isStream(arg1) || isString(arg1)) {
+
+ // simple version for GETs. Signature is:
+ // oboe( url )
+ // or, under node:
+ // oboe( readableStream )
+ return applyDefaults(
+ wire,
+ arg1 // url
+ );
+
+ } else {
+
+ // method signature is:
+ // oboe({method:m, url:u, body:b, headers:{...}})
+
+ return applyDefaults(
+ wire,
+ arg1.url,
+ arg1.method,
+ arg1.body,
+ arg1.headers,
+ arg1.withCredentials,
+ arg1.cached
+ );
+
+ }
+ } else {
+ // wire up a no-AJAX, no-stream Oboe. Will have to have content
+ // fed in externally and using .emit.
+ return wire();
+ }
+}
+
+/* oboe.drop is a special value. If a node callback returns this value the
+ parsed node is deleted from the JSON
+ */
+oboe.drop = function() {
+ return oboe.drop;
+};
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/singleEventPubSub.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/singleEventPubSub.js
new file mode 100644
index 00000000000..62b2ec43e99
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/singleEventPubSub.js
@@ -0,0 +1,93 @@
+/**
+ * A pub/sub which is responsible for a single event type. A
+ * multi-event type event bus is created by pubSub by collecting
+ * several of these.
+ *
+ * @param {String} eventType
+ * the name of the events managed by this singleEventPubSub
+ * @param {singleEventPubSub} [newListener]
+ * place to notify of new listeners
+ * @param {singleEventPubSub} [removeListener]
+ * place to notify of when listeners are removed
+ */
+function singleEventPubSub(eventType, newListener, removeListener){
+
+ /** we are optimised for emitting events over firing them.
+ * As well as the tuple list which stores event ids and
+ * listeners there is a list with just the listeners which
+ * can be iterated more quickly when we are emitting
+ */
+ var listenerTupleList,
+ listenerList;
+
+ function hasId(id){
+ return function(tuple) {
+ return tuple.id == id;
+ };
+ }
+
+ return {
+
+ /**
+ * @param {Function} listener
+ * @param {*} listenerId
+ * an id that this listener can later by removed by.
+ * Can be of any type, to be compared to other ids using ==
+ */
+ on:function( listener, listenerId ) {
+
+ var tuple = {
+ listener: listener
+ , id: listenerId || listener // when no id is given use the
+ // listener function as the id
+ };
+
+ if( newListener ) {
+ newListener.emit(eventType, listener, tuple.id);
+ }
+
+ listenerTupleList = cons( tuple, listenerTupleList );
+ listenerList = cons( listener, listenerList );
+
+ return this; // chaining
+ },
+
+ emit:function () {
+ applyEach( listenerList, arguments );
+ },
+
+ un: function( listenerId ) {
+
+ var removed;
+
+ listenerTupleList = without(
+ listenerTupleList,
+ hasId(listenerId),
+ function(tuple){
+ removed = tuple;
+ }
+ );
+
+ if( removed ) {
+ listenerList = without( listenerList, function(listener){
+ return listener == removed.listener;
+ });
+
+ if( removeListener ) {
+ removeListener.emit(eventType, removed.listener, removed.id);
+ }
+ }
+ },
+
+ listeners: function(){
+ // differs from Node EventEmitter: returns list, not array
+ return listenerList;
+ },
+
+ hasListener: function(listenerId){
+ var test = listenerId? hasId(listenerId) : always;
+
+ return defined(first( test, listenerTupleList));
+ }
+ };
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/streamingHttp.browser.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/streamingHttp.browser.js
new file mode 100644
index 00000000000..0f6a5229f05
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/streamingHttp.browser.js
@@ -0,0 +1,149 @@
+function httpTransport(){
+ return new XMLHttpRequest();
+}
+
+/**
+ * A wrapper around the browser XmlHttpRequest object that raises an
+ * event whenever a new part of the response is available.
+ *
+ * In older browsers progressive reading is impossible so all the
+ * content is given in a single call. For newer ones several events
+ * should be raised, allowing progressive interpretation of the response.
+ *
+ * @param {Function} oboeBus an event bus local to this Oboe instance
+ * @param {XMLHttpRequest} xhr the xhr to use as the transport. Under normal
+ * operation, will have been created using httpTransport() above
+ * but for tests a stub can be provided instead.
+ * @param {String} method one of 'GET' 'POST' 'PUT' 'PATCH' 'DELETE'
+ * @param {String} url the url to make a request to
+ * @param {String|Null} data some content to be sent with the request.
+ * Only valid if method is POST or PUT.
+ * @param {Object} [headers] the http request headers to send
+ * @param {boolean} withCredentials the XHR withCredentials property will be
+ * set to this value
+ */
+function streamingHttp(oboeBus, xhr, method, url, data, headers, withCredentials) {
+
+ "use strict";
+
+ var emitStreamData = oboeBus(STREAM_DATA).emit,
+ emitFail = oboeBus(FAIL_EVENT).emit,
+ numberOfCharsAlreadyGivenToCallback = 0,
+ stillToSendStartEvent = true;
+
+ // When an ABORTING message is put on the event bus abort
+ // the ajax request
+ oboeBus( ABORTING ).on( function(){
+
+ // if we keep the onreadystatechange while aborting the XHR gives
+ // a callback like a successful call so first remove this listener
+ // by assigning null:
+ xhr.onreadystatechange = null;
+
+ xhr.abort();
+ });
+
+ /**
+ * Handle input from the underlying xhr: either a state change,
+ * the progress event or the request being complete.
+ */
+ function handleProgress() {
+
+ var textSoFar = xhr.responseText,
+ newText = textSoFar.substr(numberOfCharsAlreadyGivenToCallback);
+
+
+ /* Raise the event for new text.
+
+ On older browsers, the new text is the whole response.
+ On newer/better ones, the fragment part that we got since
+ last progress. */
+
+ if( newText ) {
+ emitStreamData( newText );
+ }
+
+ numberOfCharsAlreadyGivenToCallback = len(textSoFar);
+ }
+
+
+ if('onprogress' in xhr){ // detect browser support for progressive delivery
+ xhr.onprogress = handleProgress;
+ }
+
+ xhr.onreadystatechange = function() {
+
+ function sendStartIfNotAlready() {
+ // Internet Explorer is very unreliable as to when xhr.status etc can
+ // be read so has to be protected with try/catch and tried again on
+ // the next readyState if it fails
+ try{
+ stillToSendStartEvent && oboeBus( HTTP_START ).emit(
+ xhr.status,
+ parseResponseHeaders(xhr.getAllResponseHeaders()) );
+ stillToSendStartEvent = false;
+ } catch(e){/* do nothing, will try again on next readyState*/}
+ }
+
+ switch( xhr.readyState ) {
+
+ case 2: // HEADERS_RECEIVED
+ case 3: // LOADING
+ return sendStartIfNotAlready();
+
+ case 4: // DONE
+ sendStartIfNotAlready(); // if xhr.status hasn't been available yet, it must be NOW, huh IE?
+
+ // is this a 2xx http code?
+ var successful = String(xhr.status)[0] == 2;
+
+ if( successful ) {
+ // In Chrome 29 (not 28) no onprogress is emitted when a response
+ // is complete before the onload. We need to always do handleInput
+ // in case we get the load but have not had a final progress event.
+ // This looks like a bug and may change in future but let's take
+ // the safest approach and assume we might not have received a
+ // progress event for each part of the response
+ handleProgress();
+
+ oboeBus(STREAM_END).emit();
+ } else {
+
+ emitFail( errorReport(
+ xhr.status,
+ xhr.responseText
+ ));
+ }
+ }
+ };
+
+ try{
+
+ xhr.open(method, url, true);
+
+ for( var headerName in headers ){
+ xhr.setRequestHeader(headerName, headers[headerName]);
+ }
+
+ if( !isCrossOrigin(window.location, parseUrlOrigin(url)) ) {
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ }
+
+ xhr.withCredentials = withCredentials;
+
+ xhr.send(data);
+
+ } catch( e ) {
+
+ // To keep a consistent interface with Node, we can't emit an event here.
+ // Node's streaming http adaptor receives the error as an asynchronous
+ // event rather than as an exception. If we emitted now, the Oboe user
+ // has had no chance to add a .fail listener so there is no way
+ // the event could be useful. For both these reasons defer the
+ // firing to the next JS frame.
+ window.setTimeout(
+ partialComplete(emitFail, errorReport(undefined, undefined, e))
+ , 0
+ );
+ }
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/streamingHttp.node.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/streamingHttp.node.js
new file mode 100644
index 00000000000..cc2f4212c04
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/streamingHttp.node.js
@@ -0,0 +1,135 @@
+var httpTransport = functor(require('http-https'));
+
+/**
+ * A wrapper around the browser XmlHttpRequest object that raises an
+ * event whenever a new part of the response is available.
+ *
+ * In older browsers progressive reading is impossible so all the
+ * content is given in a single call. For newer ones several events
+ * should be raised, allowing progressive interpretation of the response.
+ *
+ * @param {Function} oboeBus an event bus local to this Oboe instance
+ * @param {XMLHttpRequest} transport the http implementation to use as the transport. Under normal
+ * operation, will have been created using httpTransport() above
+ * and therefore be Node's http
+ * but for tests a stub may be provided instead.
+ * @param {String} method one of 'GET' 'POST' 'PUT' 'PATCH' 'DELETE'
+ * @param {String} contentSource the url to make a request to, or a stream to read from
+ * @param {String|Null} data some content to be sent with the request.
+ * Only valid if method is POST or PUT.
+ * @param {Object} [headers] the http request headers to send
+ */
+function streamingHttp(oboeBus, transport, method, contentSource, data, headers) {
+ "use strict";
+
+ /* receiving data after calling .abort on Node's http has been observed in the
+ wild. Keep aborted as state so that if the request has been aborted we
+ can ignore new data from that point on */
+ var aborted = false;
+
+ function readStreamToEventBus(readableStream) {
+
+ // use stream in flowing mode
+ readableStream.on('data', function (chunk) {
+
+ // avoid reading the stream after aborting the request
+ if( !aborted ) {
+ oboeBus(STREAM_DATA).emit(chunk.toString());
+ }
+ });
+
+ readableStream.on('end', function() {
+
+ // avoid reading the stream after aborting the request
+ if( !aborted ) {
+ oboeBus(STREAM_END).emit();
+ }
+ });
+ }
+
+ function readStreamToEnd(readableStream, callback){
+ var content = '';
+
+ readableStream.on('data', function (chunk) {
+
+ content += chunk.toString();
+ });
+
+ readableStream.on('end', function() {
+
+ callback( content );
+ });
+ }
+
+ function openUrlAsStream( url ) {
+
+ var parsedUrl = require('url').parse(url);
+
+ return transport.request({
+ hostname: parsedUrl.hostname,
+ port: parsedUrl.port,
+ path: parsedUrl.path,
+ method: method,
+ headers: headers,
+ protocol: parsedUrl.protocol
+ });
+ }
+
+ function fetchUrl() {
+ if( !contentSource.match(/https?:\/\//) ) {
+ throw new Error(
+ 'Supported protocols when passing a URL into Oboe are http and https. ' +
+ 'If you wish to use another protocol, please pass a ReadableStream ' +
+ '(http://nodejs.org/api/stream.html#stream_class_stream_readable) like ' +
+ 'oboe(fs.createReadStream("my_file")). I was given the URL: ' +
+ contentSource
+ );
+ }
+
+ var req = openUrlAsStream(contentSource);
+
+ req.on('response', function(res){
+ var statusCode = res.statusCode,
+ successful = String(statusCode)[0] == 2;
+
+ oboeBus(HTTP_START).emit( res.statusCode, res.headers);
+
+ if( successful ) {
+
+ readStreamToEventBus(res)
+
+ } else {
+ readStreamToEnd(res, function(errorBody){
+ oboeBus(FAIL_EVENT).emit(
+ errorReport( statusCode, errorBody )
+ );
+ });
+ }
+ });
+
+ req.on('error', function(e) {
+ oboeBus(FAIL_EVENT).emit(
+ errorReport(undefined, undefined, e )
+ );
+ });
+
+ oboeBus(ABORTING).on( function(){
+ aborted = true;
+ req.abort();
+ });
+
+ if( data ) {
+ req.write(data);
+ }
+
+ req.end();
+ }
+
+ if( isString(contentSource) ) {
+ fetchUrl(contentSource);
+ } else {
+ // contentsource is a stream
+ readStreamToEventBus(contentSource);
+ }
+
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/util.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/util.js
new file mode 100644
index 00000000000..cf6d2cfd800
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/util.js
@@ -0,0 +1,44 @@
+/**
+ * This file defines some loosely associated syntactic sugar for
+ * Javascript programming
+ */
+
+
+/**
+ * Returns true if the given candidate is of type T
+ */
+function isOfType(T, maybeSomething){
+ return maybeSomething && maybeSomething.constructor === T;
+}
+
+var len = attr('length'),
+ isString = partialComplete(isOfType, String);
+
+/**
+ * I don't like saying this:
+ *
+ * foo !=== undefined
+ *
+ * because of the double-negative. I find this:
+ *
+ * defined(foo)
+ *
+ * easier to read.
+ */
+function defined( value ) {
+ return value !== undefined;
+}
+
+/**
+ * Returns true if object o has a key named like every property in
+ * the properties array. Will give false if any are missing, or if o
+ * is not an object.
+ */
+function hasAllProperties(fieldList, o) {
+
+ return (o instanceof Object)
+ &&
+ all(function (field) {
+ return (field in o);
+ }, fieldList);
+} \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/wire.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/wire.js
new file mode 100644
index 00000000000..712f5516586
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/wire.js
@@ -0,0 +1,34 @@
+/**
+ * This file sits just behind the API which is used to attain a new
+ * Oboe instance. It creates the new components that are required
+ * and introduces them to each other.
+ */
+
+function wire (httpMethodName, contentSource, body, headers, withCredentials){
+
+ var oboeBus = pubSub();
+
+ // Wire the input stream in if we are given a content source.
+ // This will usually be the case. If not, the instance created
+ // will have to be passed content from an external source.
+
+ if( contentSource ) {
+
+ streamingHttp( oboeBus,
+ httpTransport(),
+ httpMethodName,
+ contentSource,
+ body,
+ headers,
+ withCredentials
+ );
+ }
+
+ clarinet(oboeBus);
+
+ ascentManager(oboeBus, incrementalContentBuilder(oboeBus));
+
+ patternAdapter(oboeBus, jsonPathCompiler);
+
+ return instanceApi(oboeBus, contentSource);
+}
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/wrapper.browser.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/wrapper.browser.js
new file mode 100644
index 00000000000..2a7dd9d12f7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/wrapper.browser.js
@@ -0,0 +1,24 @@
+// This file is the concatenation of many js files.
+// See http://github.com/jimhigson/oboe.js for the raw source
+
+// having a local undefined, window, Object etc allows slightly better minification:
+(function (window, Object, Array, Error, JSON, undefined ) {
+
+ // ---contents--- //
+
+ if ( typeof define === "function" && define.amd ) {
+ define( "oboe", [], function () { return oboe; } );
+ } else if (typeof exports === 'object') {
+ module.exports = oboe;
+ } else {
+ window.oboe = oboe;
+ }
+})((function(){
+ // Access to the window object throws an exception in HTML5 web workers so
+ // point it to "self" if it runs in a web worker
+ try {
+ return window;
+ } catch (e) {
+ return self;
+ }
+ }()), Object, Array, Error, JSON);
diff --git a/chromium/third_party/catapult/tracing/third_party/oboe/src/wrapper.node.js b/chromium/third_party/catapult/tracing/third_party/oboe/src/wrapper.node.js
new file mode 100644
index 00000000000..38c93a52e6c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/oboe/src/wrapper.node.js
@@ -0,0 +1,9 @@
+// this file is the concatenation of several js files. See http://github.com/jimhigson/oboe.js
+// for the unconcatenated source
+
+module.exports = (function () {
+
+ // ---contents--- //
+
+ return oboe;
+})();
diff --git a/chromium/third_party/catapult/tracing/third_party/pako/LICENSE b/chromium/third_party/catapult/tracing/third_party/pako/LICENSE
new file mode 100644
index 00000000000..a934ef8db47
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/pako/LICENSE
@@ -0,0 +1,21 @@
+(The MIT License)
+
+Copyright (C) 2014-2017 by Vitaly Puzrin and Andrei Tuputcyn
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/chromium/third_party/catapult/tracing/third_party/pako/README.chromium b/chromium/third_party/catapult/tracing/third_party/pako/README.chromium
new file mode 100644
index 00000000000..b335916b62e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/pako/README.chromium
@@ -0,0 +1,15 @@
+Name: pako
+Short Name: pako
+URL: https://github.com/nodeca/pako
+Version: 1.0.6
+Revision: 893381abcafa10fa2081ce60dae7d4d8e873a658
+Date: Thu Sep 14 14:38:19 2017 +0300
+License: MIT
+License File: LICENSE
+Security Critical: no
+
+Description:
+high speed zlib port to javascript, works in browser & node.js http://nodeca.github.io/pako/
+
+Local Modifications:
+Took only the minified JS file and associated license.
diff --git a/chromium/third_party/catapult/tracing/third_party/pako/pako.min.js b/chromium/third_party/catapult/tracing/third_party/pako/pako.min.js
new file mode 100644
index 00000000000..73024f7a68c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/pako/pako.min.js
@@ -0,0 +1 @@
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).pako=t()}}(function(){return function t(e,a,i){function n(s,o){if(!a[s]){if(!e[s]){var l="function"==typeof require&&require;if(!o&&l)return l(s,!0);if(r)return r(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var d=a[s]={exports:{}};e[s][0].call(d.exports,function(t){var a=e[s][1][t];return n(a||t)},d,d.exports,t,e,a,i)}return a[s].exports}for(var r="function"==typeof require&&require,s=0;s<i.length;s++)n(i[s]);return n}({1:[function(t,e,a){"use strict";function i(t){if(!(this instanceof i))return new i(t);this.options=s.assign({level:_,method:c,chunkSize:16384,windowBits:15,memLevel:8,strategy:u,to:""},t||{});var e=this.options;e.raw&&e.windowBits>0?e.windowBits=-e.windowBits:e.gzip&&e.windowBits>0&&e.windowBits<16&&(e.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new h,this.strm.avail_out=0;var a=r.deflateInit2(this.strm,e.level,e.method,e.windowBits,e.memLevel,e.strategy);if(a!==f)throw new Error(l[a]);if(e.header&&r.deflateSetHeader(this.strm,e.header),e.dictionary){var n;if(n="string"==typeof e.dictionary?o.string2buf(e.dictionary):"[object ArrayBuffer]"===d.call(e.dictionary)?new Uint8Array(e.dictionary):e.dictionary,(a=r.deflateSetDictionary(this.strm,n))!==f)throw new Error(l[a]);this._dict_set=!0}}function n(t,e){var a=new i(e);if(a.push(t,!0),a.err)throw a.msg||l[a.err];return a.result}var r=t("./zlib/deflate"),s=t("./utils/common"),o=t("./utils/strings"),l=t("./zlib/messages"),h=t("./zlib/zstream"),d=Object.prototype.toString,f=0,_=-1,u=0,c=8;i.prototype.push=function(t,e){var a,i,n=this.strm,l=this.options.chunkSize;if(this.ended)return!1;i=e===~~e?e:!0===e?4:0,"string"==typeof t?n.input=o.string2buf(t):"[object ArrayBuffer]"===d.call(t)?n.input=new Uint8Array(t):n.input=t,n.next_in=0,n.avail_in=n.input.length;do{if(0===n.avail_out&&(n.output=new s.Buf8(l),n.next_out=0,n.avail_out=l),1!==(a=r.deflate(n,i))&&a!==f)return this.onEnd(a),this.ended=!0,!1;0!==n.avail_out&&(0!==n.avail_in||4!==i&&2!==i)||("string"===this.options.to?this.onData(o.buf2binstring(s.shrinkBuf(n.output,n.next_out))):this.onData(s.shrinkBuf(n.output,n.next_out)))}while((n.avail_in>0||0===n.avail_out)&&1!==a);return 4===i?(a=r.deflateEnd(this.strm),this.onEnd(a),this.ended=!0,a===f):2!==i||(this.onEnd(f),n.avail_out=0,!0)},i.prototype.onData=function(t){this.chunks.push(t)},i.prototype.onEnd=function(t){t===f&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=s.flattenChunks(this.chunks)),this.chunks=[],this.err=t,this.msg=this.strm.msg},a.Deflate=i,a.deflate=n,a.deflateRaw=function(t,e){return e=e||{},e.raw=!0,n(t,e)},a.gzip=function(t,e){return e=e||{},e.gzip=!0,n(t,e)}},{"./utils/common":3,"./utils/strings":4,"./zlib/deflate":8,"./zlib/messages":13,"./zlib/zstream":15}],2:[function(t,e,a){"use strict";function i(t){if(!(this instanceof i))return new i(t);this.options=s.assign({chunkSize:16384,windowBits:0,to:""},t||{});var e=this.options;e.raw&&e.windowBits>=0&&e.windowBits<16&&(e.windowBits=-e.windowBits,0===e.windowBits&&(e.windowBits=-15)),!(e.windowBits>=0&&e.windowBits<16)||t&&t.windowBits||(e.windowBits+=32),e.windowBits>15&&e.windowBits<48&&0==(15&e.windowBits)&&(e.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new d,this.strm.avail_out=0;var a=r.inflateInit2(this.strm,e.windowBits);if(a!==l.Z_OK)throw new Error(h[a]);this.header=new f,r.inflateGetHeader(this.strm,this.header)}function n(t,e){var a=new i(e);if(a.push(t,!0),a.err)throw a.msg||h[a.err];return a.result}var r=t("./zlib/inflate"),s=t("./utils/common"),o=t("./utils/strings"),l=t("./zlib/constants"),h=t("./zlib/messages"),d=t("./zlib/zstream"),f=t("./zlib/gzheader"),_=Object.prototype.toString;i.prototype.push=function(t,e){var a,i,n,h,d,f,u=this.strm,c=this.options.chunkSize,b=this.options.dictionary,g=!1;if(this.ended)return!1;i=e===~~e?e:!0===e?l.Z_FINISH:l.Z_NO_FLUSH,"string"==typeof t?u.input=o.binstring2buf(t):"[object ArrayBuffer]"===_.call(t)?u.input=new Uint8Array(t):u.input=t,u.next_in=0,u.avail_in=u.input.length;do{if(0===u.avail_out&&(u.output=new s.Buf8(c),u.next_out=0,u.avail_out=c),(a=r.inflate(u,l.Z_NO_FLUSH))===l.Z_NEED_DICT&&b&&(f="string"==typeof b?o.string2buf(b):"[object ArrayBuffer]"===_.call(b)?new Uint8Array(b):b,a=r.inflateSetDictionary(this.strm,f)),a===l.Z_BUF_ERROR&&!0===g&&(a=l.Z_OK,g=!1),a!==l.Z_STREAM_END&&a!==l.Z_OK)return this.onEnd(a),this.ended=!0,!1;u.next_out&&(0!==u.avail_out&&a!==l.Z_STREAM_END&&(0!==u.avail_in||i!==l.Z_FINISH&&i!==l.Z_SYNC_FLUSH)||("string"===this.options.to?(n=o.utf8border(u.output,u.next_out),h=u.next_out-n,d=o.buf2string(u.output,n),u.next_out=h,u.avail_out=c-h,h&&s.arraySet(u.output,u.output,n,h,0),this.onData(d)):this.onData(s.shrinkBuf(u.output,u.next_out)))),0===u.avail_in&&0===u.avail_out&&(g=!0)}while((u.avail_in>0||0===u.avail_out)&&a!==l.Z_STREAM_END);return a===l.Z_STREAM_END&&(i=l.Z_FINISH),i===l.Z_FINISH?(a=r.inflateEnd(this.strm),this.onEnd(a),this.ended=!0,a===l.Z_OK):i!==l.Z_SYNC_FLUSH||(this.onEnd(l.Z_OK),u.avail_out=0,!0)},i.prototype.onData=function(t){this.chunks.push(t)},i.prototype.onEnd=function(t){t===l.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=s.flattenChunks(this.chunks)),this.chunks=[],this.err=t,this.msg=this.strm.msg},a.Inflate=i,a.inflate=n,a.inflateRaw=function(t,e){return e=e||{},e.raw=!0,n(t,e)},a.ungzip=n},{"./utils/common":3,"./utils/strings":4,"./zlib/constants":6,"./zlib/gzheader":9,"./zlib/inflate":11,"./zlib/messages":13,"./zlib/zstream":15}],3:[function(t,e,a){"use strict";function i(t,e){return Object.prototype.hasOwnProperty.call(t,e)}var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;a.assign=function(t){for(var e=Array.prototype.slice.call(arguments,1);e.length;){var a=e.shift();if(a){if("object"!=typeof a)throw new TypeError(a+"must be non-object");for(var n in a)i(a,n)&&(t[n]=a[n])}}return t},a.shrinkBuf=function(t,e){return t.length===e?t:t.subarray?t.subarray(0,e):(t.length=e,t)};var r={arraySet:function(t,e,a,i,n){if(e.subarray&&t.subarray)t.set(e.subarray(a,a+i),n);else for(var r=0;r<i;r++)t[n+r]=e[a+r]},flattenChunks:function(t){var e,a,i,n,r,s;for(i=0,e=0,a=t.length;e<a;e++)i+=t[e].length;for(s=new Uint8Array(i),n=0,e=0,a=t.length;e<a;e++)r=t[e],s.set(r,n),n+=r.length;return s}},s={arraySet:function(t,e,a,i,n){for(var r=0;r<i;r++)t[n+r]=e[a+r]},flattenChunks:function(t){return[].concat.apply([],t)}};a.setTyped=function(t){t?(a.Buf8=Uint8Array,a.Buf16=Uint16Array,a.Buf32=Int32Array,a.assign(a,r)):(a.Buf8=Array,a.Buf16=Array,a.Buf32=Array,a.assign(a,s))},a.setTyped(n)},{}],4:[function(t,e,a){"use strict";function i(t,e){if(e<65537&&(t.subarray&&s||!t.subarray&&r))return String.fromCharCode.apply(null,n.shrinkBuf(t,e));for(var a="",i=0;i<e;i++)a+=String.fromCharCode(t[i]);return a}var n=t("./common"),r=!0,s=!0;try{String.fromCharCode.apply(null,[0])}catch(t){r=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(t){s=!1}for(var o=new n.Buf8(256),l=0;l<256;l++)o[l]=l>=252?6:l>=248?5:l>=240?4:l>=224?3:l>=192?2:1;o[254]=o[254]=1,a.string2buf=function(t){var e,a,i,r,s,o=t.length,l=0;for(r=0;r<o;r++)55296==(64512&(a=t.charCodeAt(r)))&&r+1<o&&56320==(64512&(i=t.charCodeAt(r+1)))&&(a=65536+(a-55296<<10)+(i-56320),r++),l+=a<128?1:a<2048?2:a<65536?3:4;for(e=new n.Buf8(l),s=0,r=0;s<l;r++)55296==(64512&(a=t.charCodeAt(r)))&&r+1<o&&56320==(64512&(i=t.charCodeAt(r+1)))&&(a=65536+(a-55296<<10)+(i-56320),r++),a<128?e[s++]=a:a<2048?(e[s++]=192|a>>>6,e[s++]=128|63&a):a<65536?(e[s++]=224|a>>>12,e[s++]=128|a>>>6&63,e[s++]=128|63&a):(e[s++]=240|a>>>18,e[s++]=128|a>>>12&63,e[s++]=128|a>>>6&63,e[s++]=128|63&a);return e},a.buf2binstring=function(t){return i(t,t.length)},a.binstring2buf=function(t){for(var e=new n.Buf8(t.length),a=0,i=e.length;a<i;a++)e[a]=t.charCodeAt(a);return e},a.buf2string=function(t,e){var a,n,r,s,l=e||t.length,h=new Array(2*l);for(n=0,a=0;a<l;)if((r=t[a++])<128)h[n++]=r;else if((s=o[r])>4)h[n++]=65533,a+=s-1;else{for(r&=2===s?31:3===s?15:7;s>1&&a<l;)r=r<<6|63&t[a++],s--;s>1?h[n++]=65533:r<65536?h[n++]=r:(r-=65536,h[n++]=55296|r>>10&1023,h[n++]=56320|1023&r)}return i(h,n)},a.utf8border=function(t,e){var a;for((e=e||t.length)>t.length&&(e=t.length),a=e-1;a>=0&&128==(192&t[a]);)a--;return a<0?e:0===a?e:a+o[t[a]]>e?a:e}},{"./common":3}],5:[function(t,e,a){"use strict";e.exports=function(t,e,a,i){for(var n=65535&t|0,r=t>>>16&65535|0,s=0;0!==a;){a-=s=a>2e3?2e3:a;do{r=r+(n=n+e[i++]|0)|0}while(--s);n%=65521,r%=65521}return n|r<<16|0}},{}],6:[function(t,e,a){"use strict";e.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],7:[function(t,e,a){"use strict";var i=function(){for(var t,e=[],a=0;a<256;a++){t=a;for(var i=0;i<8;i++)t=1&t?3988292384^t>>>1:t>>>1;e[a]=t}return e}();e.exports=function(t,e,a,n){var r=i,s=n+a;t^=-1;for(var o=n;o<s;o++)t=t>>>8^r[255&(t^e[o])];return-1^t}},{}],8:[function(t,e,a){"use strict";function i(t,e){return t.msg=A[e],e}function n(t){return(t<<1)-(t>4?9:0)}function r(t){for(var e=t.length;--e>=0;)t[e]=0}function s(t){var e=t.state,a=e.pending;a>t.avail_out&&(a=t.avail_out),0!==a&&(z.arraySet(t.output,e.pending_buf,e.pending_out,a,t.next_out),t.next_out+=a,e.pending_out+=a,t.total_out+=a,t.avail_out-=a,e.pending-=a,0===e.pending&&(e.pending_out=0))}function o(t,e){B._tr_flush_block(t,t.block_start>=0?t.block_start:-1,t.strstart-t.block_start,e),t.block_start=t.strstart,s(t.strm)}function l(t,e){t.pending_buf[t.pending++]=e}function h(t,e){t.pending_buf[t.pending++]=e>>>8&255,t.pending_buf[t.pending++]=255&e}function d(t,e,a,i){var n=t.avail_in;return n>i&&(n=i),0===n?0:(t.avail_in-=n,z.arraySet(e,t.input,t.next_in,n,a),1===t.state.wrap?t.adler=S(t.adler,e,n,a):2===t.state.wrap&&(t.adler=E(t.adler,e,n,a)),t.next_in+=n,t.total_in+=n,n)}function f(t,e){var a,i,n=t.max_chain_length,r=t.strstart,s=t.prev_length,o=t.nice_match,l=t.strstart>t.w_size-it?t.strstart-(t.w_size-it):0,h=t.window,d=t.w_mask,f=t.prev,_=t.strstart+at,u=h[r+s-1],c=h[r+s];t.prev_length>=t.good_match&&(n>>=2),o>t.lookahead&&(o=t.lookahead);do{if(a=e,h[a+s]===c&&h[a+s-1]===u&&h[a]===h[r]&&h[++a]===h[r+1]){r+=2,a++;do{}while(h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&r<_);if(i=at-(_-r),r=_-at,i>s){if(t.match_start=e,s=i,i>=o)break;u=h[r+s-1],c=h[r+s]}}}while((e=f[e&d])>l&&0!=--n);return s<=t.lookahead?s:t.lookahead}function _(t){var e,a,i,n,r,s=t.w_size;do{if(n=t.window_size-t.lookahead-t.strstart,t.strstart>=s+(s-it)){z.arraySet(t.window,t.window,s,s,0),t.match_start-=s,t.strstart-=s,t.block_start-=s,e=a=t.hash_size;do{i=t.head[--e],t.head[e]=i>=s?i-s:0}while(--a);e=a=s;do{i=t.prev[--e],t.prev[e]=i>=s?i-s:0}while(--a);n+=s}if(0===t.strm.avail_in)break;if(a=d(t.strm,t.window,t.strstart+t.lookahead,n),t.lookahead+=a,t.lookahead+t.insert>=et)for(r=t.strstart-t.insert,t.ins_h=t.window[r],t.ins_h=(t.ins_h<<t.hash_shift^t.window[r+1])&t.hash_mask;t.insert&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[r+et-1])&t.hash_mask,t.prev[r&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=r,r++,t.insert--,!(t.lookahead+t.insert<et)););}while(t.lookahead<it&&0!==t.strm.avail_in)}function u(t,e){for(var a,i;;){if(t.lookahead<it){if(_(t),t.lookahead<it&&e===Z)return _t;if(0===t.lookahead)break}if(a=0,t.lookahead>=et&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),0!==a&&t.strstart-a<=t.w_size-it&&(t.match_length=f(t,a)),t.match_length>=et)if(i=B._tr_tally(t,t.strstart-t.match_start,t.match_length-et),t.lookahead-=t.match_length,t.match_length<=t.max_lazy_match&&t.lookahead>=et){t.match_length--;do{t.strstart++,t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart}while(0!=--t.match_length);t.strstart++}else t.strstart+=t.match_length,t.match_length=0,t.ins_h=t.window[t.strstart],t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+1])&t.hash_mask;else i=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++;if(i&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=t.strstart<et-1?t.strstart:et-1,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function c(t,e){for(var a,i,n;;){if(t.lookahead<it){if(_(t),t.lookahead<it&&e===Z)return _t;if(0===t.lookahead)break}if(a=0,t.lookahead>=et&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),t.prev_length=t.match_length,t.prev_match=t.match_start,t.match_length=et-1,0!==a&&t.prev_length<t.max_lazy_match&&t.strstart-a<=t.w_size-it&&(t.match_length=f(t,a),t.match_length<=5&&(t.strategy===H||t.match_length===et&&t.strstart-t.match_start>4096)&&(t.match_length=et-1)),t.prev_length>=et&&t.match_length<=t.prev_length){n=t.strstart+t.lookahead-et,i=B._tr_tally(t,t.strstart-1-t.prev_match,t.prev_length-et),t.lookahead-=t.prev_length-1,t.prev_length-=2;do{++t.strstart<=n&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart)}while(0!=--t.prev_length);if(t.match_available=0,t.match_length=et-1,t.strstart++,i&&(o(t,!1),0===t.strm.avail_out))return _t}else if(t.match_available){if((i=B._tr_tally(t,0,t.window[t.strstart-1]))&&o(t,!1),t.strstart++,t.lookahead--,0===t.strm.avail_out)return _t}else t.match_available=1,t.strstart++,t.lookahead--}return t.match_available&&(i=B._tr_tally(t,0,t.window[t.strstart-1]),t.match_available=0),t.insert=t.strstart<et-1?t.strstart:et-1,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function b(t,e){for(var a,i,n,r,s=t.window;;){if(t.lookahead<=at){if(_(t),t.lookahead<=at&&e===Z)return _t;if(0===t.lookahead)break}if(t.match_length=0,t.lookahead>=et&&t.strstart>0&&(n=t.strstart-1,(i=s[n])===s[++n]&&i===s[++n]&&i===s[++n])){r=t.strstart+at;do{}while(i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&n<r);t.match_length=at-(r-n),t.match_length>t.lookahead&&(t.match_length=t.lookahead)}if(t.match_length>=et?(a=B._tr_tally(t,1,t.match_length-et),t.lookahead-=t.match_length,t.strstart+=t.match_length,t.match_length=0):(a=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++),a&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function g(t,e){for(var a;;){if(0===t.lookahead&&(_(t),0===t.lookahead)){if(e===Z)return _t;break}if(t.match_length=0,a=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++,a&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function m(t,e,a,i,n){this.good_length=t,this.max_lazy=e,this.nice_length=a,this.max_chain=i,this.func=n}function w(t){t.window_size=2*t.w_size,r(t.head),t.max_lazy_match=x[t.level].max_lazy,t.good_match=x[t.level].good_length,t.nice_match=x[t.level].nice_length,t.max_chain_length=x[t.level].max_chain,t.strstart=0,t.block_start=0,t.lookahead=0,t.insert=0,t.match_length=t.prev_length=et-1,t.match_available=0,t.ins_h=0}function p(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=q,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new z.Buf16(2*$),this.dyn_dtree=new z.Buf16(2*(2*Q+1)),this.bl_tree=new z.Buf16(2*(2*V+1)),r(this.dyn_ltree),r(this.dyn_dtree),r(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new z.Buf16(tt+1),this.heap=new z.Buf16(2*J+1),r(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new z.Buf16(2*J+1),r(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function v(t){var e;return t&&t.state?(t.total_in=t.total_out=0,t.data_type=Y,e=t.state,e.pending=0,e.pending_out=0,e.wrap<0&&(e.wrap=-e.wrap),e.status=e.wrap?rt:dt,t.adler=2===e.wrap?0:1,e.last_flush=Z,B._tr_init(e),D):i(t,U)}function k(t){var e=v(t);return e===D&&w(t.state),e}function y(t,e,a,n,r,s){if(!t)return U;var o=1;if(e===L&&(e=6),n<0?(o=0,n=-n):n>15&&(o=2,n-=16),r<1||r>G||a!==q||n<8||n>15||e<0||e>9||s<0||s>M)return i(t,U);8===n&&(n=9);var l=new p;return t.state=l,l.strm=t,l.wrap=o,l.gzhead=null,l.w_bits=n,l.w_size=1<<l.w_bits,l.w_mask=l.w_size-1,l.hash_bits=r+7,l.hash_size=1<<l.hash_bits,l.hash_mask=l.hash_size-1,l.hash_shift=~~((l.hash_bits+et-1)/et),l.window=new z.Buf8(2*l.w_size),l.head=new z.Buf16(l.hash_size),l.prev=new z.Buf16(l.w_size),l.lit_bufsize=1<<r+6,l.pending_buf_size=4*l.lit_bufsize,l.pending_buf=new z.Buf8(l.pending_buf_size),l.d_buf=1*l.lit_bufsize,l.l_buf=3*l.lit_bufsize,l.level=e,l.strategy=s,l.method=a,k(t)}var x,z=t("../utils/common"),B=t("./trees"),S=t("./adler32"),E=t("./crc32"),A=t("./messages"),Z=0,R=1,C=3,N=4,O=5,D=0,I=1,U=-2,T=-3,F=-5,L=-1,H=1,j=2,K=3,M=4,P=0,Y=2,q=8,G=9,X=15,W=8,J=286,Q=30,V=19,$=2*J+1,tt=15,et=3,at=258,it=at+et+1,nt=32,rt=42,st=69,ot=73,lt=91,ht=103,dt=113,ft=666,_t=1,ut=2,ct=3,bt=4,gt=3;x=[new m(0,0,0,0,function(t,e){var a=65535;for(a>t.pending_buf_size-5&&(a=t.pending_buf_size-5);;){if(t.lookahead<=1){if(_(t),0===t.lookahead&&e===Z)return _t;if(0===t.lookahead)break}t.strstart+=t.lookahead,t.lookahead=0;var i=t.block_start+a;if((0===t.strstart||t.strstart>=i)&&(t.lookahead=t.strstart-i,t.strstart=i,o(t,!1),0===t.strm.avail_out))return _t;if(t.strstart-t.block_start>=t.w_size-it&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):(t.strstart>t.block_start&&(o(t,!1),t.strm.avail_out),_t)}),new m(4,4,8,4,u),new m(4,5,16,8,u),new m(4,6,32,32,u),new m(4,4,16,16,c),new m(8,16,32,32,c),new m(8,16,128,128,c),new m(8,32,128,256,c),new m(32,128,258,1024,c),new m(32,258,258,4096,c)],a.deflateInit=function(t,e){return y(t,e,q,X,W,P)},a.deflateInit2=y,a.deflateReset=k,a.deflateResetKeep=v,a.deflateSetHeader=function(t,e){return t&&t.state?2!==t.state.wrap?U:(t.state.gzhead=e,D):U},a.deflate=function(t,e){var a,o,d,f;if(!t||!t.state||e>O||e<0)return t?i(t,U):U;if(o=t.state,!t.output||!t.input&&0!==t.avail_in||o.status===ft&&e!==N)return i(t,0===t.avail_out?F:U);if(o.strm=t,a=o.last_flush,o.last_flush=e,o.status===rt)if(2===o.wrap)t.adler=0,l(o,31),l(o,139),l(o,8),o.gzhead?(l(o,(o.gzhead.text?1:0)+(o.gzhead.hcrc?2:0)+(o.gzhead.extra?4:0)+(o.gzhead.name?8:0)+(o.gzhead.comment?16:0)),l(o,255&o.gzhead.time),l(o,o.gzhead.time>>8&255),l(o,o.gzhead.time>>16&255),l(o,o.gzhead.time>>24&255),l(o,9===o.level?2:o.strategy>=j||o.level<2?4:0),l(o,255&o.gzhead.os),o.gzhead.extra&&o.gzhead.extra.length&&(l(o,255&o.gzhead.extra.length),l(o,o.gzhead.extra.length>>8&255)),o.gzhead.hcrc&&(t.adler=E(t.adler,o.pending_buf,o.pending,0)),o.gzindex=0,o.status=st):(l(o,0),l(o,0),l(o,0),l(o,0),l(o,0),l(o,9===o.level?2:o.strategy>=j||o.level<2?4:0),l(o,gt),o.status=dt);else{var _=q+(o.w_bits-8<<4)<<8;_|=(o.strategy>=j||o.level<2?0:o.level<6?1:6===o.level?2:3)<<6,0!==o.strstart&&(_|=nt),_+=31-_%31,o.status=dt,h(o,_),0!==o.strstart&&(h(o,t.adler>>>16),h(o,65535&t.adler)),t.adler=1}if(o.status===st)if(o.gzhead.extra){for(d=o.pending;o.gzindex<(65535&o.gzhead.extra.length)&&(o.pending!==o.pending_buf_size||(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending!==o.pending_buf_size));)l(o,255&o.gzhead.extra[o.gzindex]),o.gzindex++;o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),o.gzindex===o.gzhead.extra.length&&(o.gzindex=0,o.status=ot)}else o.status=ot;if(o.status===ot)if(o.gzhead.name){d=o.pending;do{if(o.pending===o.pending_buf_size&&(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending===o.pending_buf_size)){f=1;break}f=o.gzindex<o.gzhead.name.length?255&o.gzhead.name.charCodeAt(o.gzindex++):0,l(o,f)}while(0!==f);o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),0===f&&(o.gzindex=0,o.status=lt)}else o.status=lt;if(o.status===lt)if(o.gzhead.comment){d=o.pending;do{if(o.pending===o.pending_buf_size&&(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending===o.pending_buf_size)){f=1;break}f=o.gzindex<o.gzhead.comment.length?255&o.gzhead.comment.charCodeAt(o.gzindex++):0,l(o,f)}while(0!==f);o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),0===f&&(o.status=ht)}else o.status=ht;if(o.status===ht&&(o.gzhead.hcrc?(o.pending+2>o.pending_buf_size&&s(t),o.pending+2<=o.pending_buf_size&&(l(o,255&t.adler),l(o,t.adler>>8&255),t.adler=0,o.status=dt)):o.status=dt),0!==o.pending){if(s(t),0===t.avail_out)return o.last_flush=-1,D}else if(0===t.avail_in&&n(e)<=n(a)&&e!==N)return i(t,F);if(o.status===ft&&0!==t.avail_in)return i(t,F);if(0!==t.avail_in||0!==o.lookahead||e!==Z&&o.status!==ft){var u=o.strategy===j?g(o,e):o.strategy===K?b(o,e):x[o.level].func(o,e);if(u!==ct&&u!==bt||(o.status=ft),u===_t||u===ct)return 0===t.avail_out&&(o.last_flush=-1),D;if(u===ut&&(e===R?B._tr_align(o):e!==O&&(B._tr_stored_block(o,0,0,!1),e===C&&(r(o.head),0===o.lookahead&&(o.strstart=0,o.block_start=0,o.insert=0))),s(t),0===t.avail_out))return o.last_flush=-1,D}return e!==N?D:o.wrap<=0?I:(2===o.wrap?(l(o,255&t.adler),l(o,t.adler>>8&255),l(o,t.adler>>16&255),l(o,t.adler>>24&255),l(o,255&t.total_in),l(o,t.total_in>>8&255),l(o,t.total_in>>16&255),l(o,t.total_in>>24&255)):(h(o,t.adler>>>16),h(o,65535&t.adler)),s(t),o.wrap>0&&(o.wrap=-o.wrap),0!==o.pending?D:I)},a.deflateEnd=function(t){var e;return t&&t.state?(e=t.state.status)!==rt&&e!==st&&e!==ot&&e!==lt&&e!==ht&&e!==dt&&e!==ft?i(t,U):(t.state=null,e===dt?i(t,T):D):U},a.deflateSetDictionary=function(t,e){var a,i,n,s,o,l,h,d,f=e.length;if(!t||!t.state)return U;if(a=t.state,2===(s=a.wrap)||1===s&&a.status!==rt||a.lookahead)return U;for(1===s&&(t.adler=S(t.adler,e,f,0)),a.wrap=0,f>=a.w_size&&(0===s&&(r(a.head),a.strstart=0,a.block_start=0,a.insert=0),d=new z.Buf8(a.w_size),z.arraySet(d,e,f-a.w_size,a.w_size,0),e=d,f=a.w_size),o=t.avail_in,l=t.next_in,h=t.input,t.avail_in=f,t.next_in=0,t.input=e,_(a);a.lookahead>=et;){i=a.strstart,n=a.lookahead-(et-1);do{a.ins_h=(a.ins_h<<a.hash_shift^a.window[i+et-1])&a.hash_mask,a.prev[i&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=i,i++}while(--n);a.strstart=i,a.lookahead=et-1,_(a)}return a.strstart+=a.lookahead,a.block_start=a.strstart,a.insert=a.lookahead,a.lookahead=0,a.match_length=a.prev_length=et-1,a.match_available=0,t.next_in=l,t.input=h,t.avail_in=o,a.wrap=s,D},a.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":3,"./adler32":5,"./crc32":7,"./messages":13,"./trees":14}],9:[function(t,e,a){"use strict";e.exports=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}},{}],10:[function(t,e,a){"use strict";e.exports=function(t,e){var a,i,n,r,s,o,l,h,d,f,_,u,c,b,g,m,w,p,v,k,y,x,z,B,S;a=t.state,i=t.next_in,B=t.input,n=i+(t.avail_in-5),r=t.next_out,S=t.output,s=r-(e-t.avail_out),o=r+(t.avail_out-257),l=a.dmax,h=a.wsize,d=a.whave,f=a.wnext,_=a.window,u=a.hold,c=a.bits,b=a.lencode,g=a.distcode,m=(1<<a.lenbits)-1,w=(1<<a.distbits)-1;t:do{c<15&&(u+=B[i++]<<c,c+=8,u+=B[i++]<<c,c+=8),p=b[u&m];e:for(;;){if(v=p>>>24,u>>>=v,c-=v,0===(v=p>>>16&255))S[r++]=65535&p;else{if(!(16&v)){if(0==(64&v)){p=b[(65535&p)+(u&(1<<v)-1)];continue e}if(32&v){a.mode=12;break t}t.msg="invalid literal/length code",a.mode=30;break t}k=65535&p,(v&=15)&&(c<v&&(u+=B[i++]<<c,c+=8),k+=u&(1<<v)-1,u>>>=v,c-=v),c<15&&(u+=B[i++]<<c,c+=8,u+=B[i++]<<c,c+=8),p=g[u&w];a:for(;;){if(v=p>>>24,u>>>=v,c-=v,!(16&(v=p>>>16&255))){if(0==(64&v)){p=g[(65535&p)+(u&(1<<v)-1)];continue a}t.msg="invalid distance code",a.mode=30;break t}if(y=65535&p,v&=15,c<v&&(u+=B[i++]<<c,(c+=8)<v&&(u+=B[i++]<<c,c+=8)),(y+=u&(1<<v)-1)>l){t.msg="invalid distance too far back",a.mode=30;break t}if(u>>>=v,c-=v,v=r-s,y>v){if((v=y-v)>d&&a.sane){t.msg="invalid distance too far back",a.mode=30;break t}if(x=0,z=_,0===f){if(x+=h-v,v<k){k-=v;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}}else if(f<v){if(x+=h+f-v,(v-=f)<k){k-=v;do{S[r++]=_[x++]}while(--v);if(x=0,f<k){k-=v=f;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}}}else if(x+=f-v,v<k){k-=v;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}for(;k>2;)S[r++]=z[x++],S[r++]=z[x++],S[r++]=z[x++],k-=3;k&&(S[r++]=z[x++],k>1&&(S[r++]=z[x++]))}else{x=r-y;do{S[r++]=S[x++],S[r++]=S[x++],S[r++]=S[x++],k-=3}while(k>2);k&&(S[r++]=S[x++],k>1&&(S[r++]=S[x++]))}break}}break}}while(i<n&&r<o);i-=k=c>>3,u&=(1<<(c-=k<<3))-1,t.next_in=i,t.next_out=r,t.avail_in=i<n?n-i+5:5-(i-n),t.avail_out=r<o?o-r+257:257-(r-o),a.hold=u,a.bits=c}},{}],11:[function(t,e,a){"use strict";function i(t){return(t>>>24&255)+(t>>>8&65280)+((65280&t)<<8)+((255&t)<<24)}function n(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new u.Buf16(320),this.work=new u.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function r(t){var e;return t&&t.state?(e=t.state,t.total_in=t.total_out=e.total=0,t.msg="",e.wrap&&(t.adler=1&e.wrap),e.mode=N,e.last=0,e.havedict=0,e.dmax=32768,e.head=null,e.hold=0,e.bits=0,e.lencode=e.lendyn=new u.Buf32(dt),e.distcode=e.distdyn=new u.Buf32(ft),e.sane=1,e.back=-1,z):E}function s(t){var e;return t&&t.state?(e=t.state,e.wsize=0,e.whave=0,e.wnext=0,r(t)):E}function o(t,e){var a,i;return t&&t.state?(i=t.state,e<0?(a=0,e=-e):(a=1+(e>>4),e<48&&(e&=15)),e&&(e<8||e>15)?E:(null!==i.window&&i.wbits!==e&&(i.window=null),i.wrap=a,i.wbits=e,s(t))):E}function l(t,e){var a,i;return t?(i=new n,t.state=i,i.window=null,(a=o(t,e))!==z&&(t.state=null),a):E}function h(t){if(ut){var e;for(f=new u.Buf32(512),_=new u.Buf32(32),e=0;e<144;)t.lens[e++]=8;for(;e<256;)t.lens[e++]=9;for(;e<280;)t.lens[e++]=7;for(;e<288;)t.lens[e++]=8;for(m(p,t.lens,0,288,f,0,t.work,{bits:9}),e=0;e<32;)t.lens[e++]=5;m(v,t.lens,0,32,_,0,t.work,{bits:5}),ut=!1}t.lencode=f,t.lenbits=9,t.distcode=_,t.distbits=5}function d(t,e,a,i){var n,r=t.state;return null===r.window&&(r.wsize=1<<r.wbits,r.wnext=0,r.whave=0,r.window=new u.Buf8(r.wsize)),i>=r.wsize?(u.arraySet(r.window,e,a-r.wsize,r.wsize,0),r.wnext=0,r.whave=r.wsize):((n=r.wsize-r.wnext)>i&&(n=i),u.arraySet(r.window,e,a-i,n,r.wnext),(i-=n)?(u.arraySet(r.window,e,a-i,i,0),r.wnext=i,r.whave=r.wsize):(r.wnext+=n,r.wnext===r.wsize&&(r.wnext=0),r.whave<r.wsize&&(r.whave+=n))),0}var f,_,u=t("../utils/common"),c=t("./adler32"),b=t("./crc32"),g=t("./inffast"),m=t("./inftrees"),w=0,p=1,v=2,k=4,y=5,x=6,z=0,B=1,S=2,E=-2,A=-3,Z=-4,R=-5,C=8,N=1,O=2,D=3,I=4,U=5,T=6,F=7,L=8,H=9,j=10,K=11,M=12,P=13,Y=14,q=15,G=16,X=17,W=18,J=19,Q=20,V=21,$=22,tt=23,et=24,at=25,it=26,nt=27,rt=28,st=29,ot=30,lt=31,ht=32,dt=852,ft=592,_t=15,ut=!0;a.inflateReset=s,a.inflateReset2=o,a.inflateResetKeep=r,a.inflateInit=function(t){return l(t,_t)},a.inflateInit2=l,a.inflate=function(t,e){var a,n,r,s,o,l,f,_,dt,ft,_t,ut,ct,bt,gt,mt,wt,pt,vt,kt,yt,xt,zt,Bt,St=0,Et=new u.Buf8(4),At=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!t||!t.state||!t.output||!t.input&&0!==t.avail_in)return E;(a=t.state).mode===M&&(a.mode=P),o=t.next_out,r=t.output,f=t.avail_out,s=t.next_in,n=t.input,l=t.avail_in,_=a.hold,dt=a.bits,ft=l,_t=f,xt=z;t:for(;;)switch(a.mode){case N:if(0===a.wrap){a.mode=P;break}for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(2&a.wrap&&35615===_){a.check=0,Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0),_=0,dt=0,a.mode=O;break}if(a.flags=0,a.head&&(a.head.done=!1),!(1&a.wrap)||(((255&_)<<8)+(_>>8))%31){t.msg="incorrect header check",a.mode=ot;break}if((15&_)!==C){t.msg="unknown compression method",a.mode=ot;break}if(_>>>=4,dt-=4,yt=8+(15&_),0===a.wbits)a.wbits=yt;else if(yt>a.wbits){t.msg="invalid window size",a.mode=ot;break}a.dmax=1<<yt,t.adler=a.check=1,a.mode=512&_?j:M,_=0,dt=0;break;case O:for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(a.flags=_,(255&a.flags)!==C){t.msg="unknown compression method",a.mode=ot;break}if(57344&a.flags){t.msg="unknown header flags set",a.mode=ot;break}a.head&&(a.head.text=_>>8&1),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0,a.mode=D;case D:for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.head&&(a.head.time=_),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,Et[2]=_>>>16&255,Et[3]=_>>>24&255,a.check=b(a.check,Et,4,0)),_=0,dt=0,a.mode=I;case I:for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.head&&(a.head.xflags=255&_,a.head.os=_>>8),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0,a.mode=U;case U:if(1024&a.flags){for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.length=_,a.head&&(a.head.extra_len=_),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0}else a.head&&(a.head.extra=null);a.mode=T;case T:if(1024&a.flags&&((ut=a.length)>l&&(ut=l),ut&&(a.head&&(yt=a.head.extra_len-a.length,a.head.extra||(a.head.extra=new Array(a.head.extra_len)),u.arraySet(a.head.extra,n,s,ut,yt)),512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,a.length-=ut),a.length))break t;a.length=0,a.mode=F;case F:if(2048&a.flags){if(0===l)break t;ut=0;do{yt=n[s+ut++],a.head&&yt&&a.length<65536&&(a.head.name+=String.fromCharCode(yt))}while(yt&&ut<l);if(512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,yt)break t}else a.head&&(a.head.name=null);a.length=0,a.mode=L;case L:if(4096&a.flags){if(0===l)break t;ut=0;do{yt=n[s+ut++],a.head&&yt&&a.length<65536&&(a.head.comment+=String.fromCharCode(yt))}while(yt&&ut<l);if(512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,yt)break t}else a.head&&(a.head.comment=null);a.mode=H;case H:if(512&a.flags){for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_!==(65535&a.check)){t.msg="header crc mismatch",a.mode=ot;break}_=0,dt=0}a.head&&(a.head.hcrc=a.flags>>9&1,a.head.done=!0),t.adler=a.check=0,a.mode=M;break;case j:for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}t.adler=a.check=i(_),_=0,dt=0,a.mode=K;case K:if(0===a.havedict)return t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,S;t.adler=a.check=1,a.mode=M;case M:if(e===y||e===x)break t;case P:if(a.last){_>>>=7&dt,dt-=7&dt,a.mode=nt;break}for(;dt<3;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}switch(a.last=1&_,_>>>=1,dt-=1,3&_){case 0:a.mode=Y;break;case 1:if(h(a),a.mode=Q,e===x){_>>>=2,dt-=2;break t}break;case 2:a.mode=X;break;case 3:t.msg="invalid block type",a.mode=ot}_>>>=2,dt-=2;break;case Y:for(_>>>=7&dt,dt-=7&dt;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if((65535&_)!=(_>>>16^65535)){t.msg="invalid stored block lengths",a.mode=ot;break}if(a.length=65535&_,_=0,dt=0,a.mode=q,e===x)break t;case q:a.mode=G;case G:if(ut=a.length){if(ut>l&&(ut=l),ut>f&&(ut=f),0===ut)break t;u.arraySet(r,n,s,ut,o),l-=ut,s+=ut,f-=ut,o+=ut,a.length-=ut;break}a.mode=M;break;case X:for(;dt<14;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(a.nlen=257+(31&_),_>>>=5,dt-=5,a.ndist=1+(31&_),_>>>=5,dt-=5,a.ncode=4+(15&_),_>>>=4,dt-=4,a.nlen>286||a.ndist>30){t.msg="too many length or distance symbols",a.mode=ot;break}a.have=0,a.mode=W;case W:for(;a.have<a.ncode;){for(;dt<3;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.lens[At[a.have++]]=7&_,_>>>=3,dt-=3}for(;a.have<19;)a.lens[At[a.have++]]=0;if(a.lencode=a.lendyn,a.lenbits=7,zt={bits:a.lenbits},xt=m(w,a.lens,0,19,a.lencode,0,a.work,zt),a.lenbits=zt.bits,xt){t.msg="invalid code lengths set",a.mode=ot;break}a.have=0,a.mode=J;case J:for(;a.have<a.nlen+a.ndist;){for(;St=a.lencode[_&(1<<a.lenbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(wt<16)_>>>=gt,dt-=gt,a.lens[a.have++]=wt;else{if(16===wt){for(Bt=gt+2;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_>>>=gt,dt-=gt,0===a.have){t.msg="invalid bit length repeat",a.mode=ot;break}yt=a.lens[a.have-1],ut=3+(3&_),_>>>=2,dt-=2}else if(17===wt){for(Bt=gt+3;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}dt-=gt,yt=0,ut=3+(7&(_>>>=gt)),_>>>=3,dt-=3}else{for(Bt=gt+7;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}dt-=gt,yt=0,ut=11+(127&(_>>>=gt)),_>>>=7,dt-=7}if(a.have+ut>a.nlen+a.ndist){t.msg="invalid bit length repeat",a.mode=ot;break}for(;ut--;)a.lens[a.have++]=yt}}if(a.mode===ot)break;if(0===a.lens[256]){t.msg="invalid code -- missing end-of-block",a.mode=ot;break}if(a.lenbits=9,zt={bits:a.lenbits},xt=m(p,a.lens,0,a.nlen,a.lencode,0,a.work,zt),a.lenbits=zt.bits,xt){t.msg="invalid literal/lengths set",a.mode=ot;break}if(a.distbits=6,a.distcode=a.distdyn,zt={bits:a.distbits},xt=m(v,a.lens,a.nlen,a.ndist,a.distcode,0,a.work,zt),a.distbits=zt.bits,xt){t.msg="invalid distances set",a.mode=ot;break}if(a.mode=Q,e===x)break t;case Q:a.mode=V;case V:if(l>=6&&f>=258){t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,g(t,_t),o=t.next_out,r=t.output,f=t.avail_out,s=t.next_in,n=t.input,l=t.avail_in,_=a.hold,dt=a.bits,a.mode===M&&(a.back=-1);break}for(a.back=0;St=a.lencode[_&(1<<a.lenbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(mt&&0==(240&mt)){for(pt=gt,vt=mt,kt=wt;St=a.lencode[kt+((_&(1<<pt+vt)-1)>>pt)],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(pt+gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}_>>>=pt,dt-=pt,a.back+=pt}if(_>>>=gt,dt-=gt,a.back+=gt,a.length=wt,0===mt){a.mode=it;break}if(32&mt){a.back=-1,a.mode=M;break}if(64&mt){t.msg="invalid literal/length code",a.mode=ot;break}a.extra=15&mt,a.mode=$;case $:if(a.extra){for(Bt=a.extra;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.length+=_&(1<<a.extra)-1,_>>>=a.extra,dt-=a.extra,a.back+=a.extra}a.was=a.length,a.mode=tt;case tt:for(;St=a.distcode[_&(1<<a.distbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(0==(240&mt)){for(pt=gt,vt=mt,kt=wt;St=a.distcode[kt+((_&(1<<pt+vt)-1)>>pt)],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(pt+gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}_>>>=pt,dt-=pt,a.back+=pt}if(_>>>=gt,dt-=gt,a.back+=gt,64&mt){t.msg="invalid distance code",a.mode=ot;break}a.offset=wt,a.extra=15&mt,a.mode=et;case et:if(a.extra){for(Bt=a.extra;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.offset+=_&(1<<a.extra)-1,_>>>=a.extra,dt-=a.extra,a.back+=a.extra}if(a.offset>a.dmax){t.msg="invalid distance too far back",a.mode=ot;break}a.mode=at;case at:if(0===f)break t;if(ut=_t-f,a.offset>ut){if((ut=a.offset-ut)>a.whave&&a.sane){t.msg="invalid distance too far back",a.mode=ot;break}ut>a.wnext?(ut-=a.wnext,ct=a.wsize-ut):ct=a.wnext-ut,ut>a.length&&(ut=a.length),bt=a.window}else bt=r,ct=o-a.offset,ut=a.length;ut>f&&(ut=f),f-=ut,a.length-=ut;do{r[o++]=bt[ct++]}while(--ut);0===a.length&&(a.mode=V);break;case it:if(0===f)break t;r[o++]=a.length,f--,a.mode=V;break;case nt:if(a.wrap){for(;dt<32;){if(0===l)break t;l--,_|=n[s++]<<dt,dt+=8}if(_t-=f,t.total_out+=_t,a.total+=_t,_t&&(t.adler=a.check=a.flags?b(a.check,r,_t,o-_t):c(a.check,r,_t,o-_t)),_t=f,(a.flags?_:i(_))!==a.check){t.msg="incorrect data check",a.mode=ot;break}_=0,dt=0}a.mode=rt;case rt:if(a.wrap&&a.flags){for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_!==(4294967295&a.total)){t.msg="incorrect length check",a.mode=ot;break}_=0,dt=0}a.mode=st;case st:xt=B;break t;case ot:xt=A;break t;case lt:return Z;case ht:default:return E}return t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,(a.wsize||_t!==t.avail_out&&a.mode<ot&&(a.mode<nt||e!==k))&&d(t,t.output,t.next_out,_t-t.avail_out)?(a.mode=lt,Z):(ft-=t.avail_in,_t-=t.avail_out,t.total_in+=ft,t.total_out+=_t,a.total+=_t,a.wrap&&_t&&(t.adler=a.check=a.flags?b(a.check,r,_t,t.next_out-_t):c(a.check,r,_t,t.next_out-_t)),t.data_type=a.bits+(a.last?64:0)+(a.mode===M?128:0)+(a.mode===Q||a.mode===q?256:0),(0===ft&&0===_t||e===k)&&xt===z&&(xt=R),xt)},a.inflateEnd=function(t){if(!t||!t.state)return E;var e=t.state;return e.window&&(e.window=null),t.state=null,z},a.inflateGetHeader=function(t,e){var a;return t&&t.state?0==(2&(a=t.state).wrap)?E:(a.head=e,e.done=!1,z):E},a.inflateSetDictionary=function(t,e){var a,i,n=e.length;return t&&t.state?0!==(a=t.state).wrap&&a.mode!==K?E:a.mode===K&&(i=1,(i=c(i,e,n,0))!==a.check)?A:d(t,e,n,n)?(a.mode=lt,Z):(a.havedict=1,z):E},a.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":3,"./adler32":5,"./crc32":7,"./inffast":10,"./inftrees":12}],12:[function(t,e,a){"use strict";var i=t("../utils/common"),n=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],r=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],s=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],o=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];e.exports=function(t,e,a,l,h,d,f,_){var u,c,b,g,m,w,p,v,k,y=_.bits,x=0,z=0,B=0,S=0,E=0,A=0,Z=0,R=0,C=0,N=0,O=null,D=0,I=new i.Buf16(16),U=new i.Buf16(16),T=null,F=0;for(x=0;x<=15;x++)I[x]=0;for(z=0;z<l;z++)I[e[a+z]]++;for(E=y,S=15;S>=1&&0===I[S];S--);if(E>S&&(E=S),0===S)return h[d++]=20971520,h[d++]=20971520,_.bits=1,0;for(B=1;B<S&&0===I[B];B++);for(E<B&&(E=B),R=1,x=1;x<=15;x++)if(R<<=1,(R-=I[x])<0)return-1;if(R>0&&(0===t||1!==S))return-1;for(U[1]=0,x=1;x<15;x++)U[x+1]=U[x]+I[x];for(z=0;z<l;z++)0!==e[a+z]&&(f[U[e[a+z]]++]=z);if(0===t?(O=T=f,w=19):1===t?(O=n,D-=257,T=r,F-=257,w=256):(O=s,T=o,w=-1),N=0,z=0,x=B,m=d,A=E,Z=0,b=-1,C=1<<E,g=C-1,1===t&&C>852||2===t&&C>592)return 1;for(;;){p=x-Z,f[z]<w?(v=0,k=f[z]):f[z]>w?(v=T[F+f[z]],k=O[D+f[z]]):(v=96,k=0),u=1<<x-Z,B=c=1<<A;do{h[m+(N>>Z)+(c-=u)]=p<<24|v<<16|k|0}while(0!==c);for(u=1<<x-1;N&u;)u>>=1;if(0!==u?(N&=u-1,N+=u):N=0,z++,0==--I[x]){if(x===S)break;x=e[a+f[z]]}if(x>E&&(N&g)!==b){for(0===Z&&(Z=E),m+=B,R=1<<(A=x-Z);A+Z<S&&!((R-=I[A+Z])<=0);)A++,R<<=1;if(C+=1<<A,1===t&&C>852||2===t&&C>592)return 1;h[b=N&g]=E<<24|A<<16|m-d|0}}return 0!==N&&(h[m+N]=x-Z<<24|64<<16|0),_.bits=E,0}},{"../utils/common":3}],13:[function(t,e,a){"use strict";e.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],14:[function(t,e,a){"use strict";function i(t){for(var e=t.length;--e>=0;)t[e]=0}function n(t,e,a,i,n){this.static_tree=t,this.extra_bits=e,this.extra_base=a,this.elems=i,this.max_length=n,this.has_stree=t&&t.length}function r(t,e){this.dyn_tree=t,this.max_code=0,this.stat_desc=e}function s(t){return t<256?et[t]:et[256+(t>>>7)]}function o(t,e){t.pending_buf[t.pending++]=255&e,t.pending_buf[t.pending++]=e>>>8&255}function l(t,e,a){t.bi_valid>M-a?(t.bi_buf|=e<<t.bi_valid&65535,o(t,t.bi_buf),t.bi_buf=e>>M-t.bi_valid,t.bi_valid+=a-M):(t.bi_buf|=e<<t.bi_valid&65535,t.bi_valid+=a)}function h(t,e,a){l(t,a[2*e],a[2*e+1])}function d(t,e){var a=0;do{a|=1&t,t>>>=1,a<<=1}while(--e>0);return a>>>1}function f(t){16===t.bi_valid?(o(t,t.bi_buf),t.bi_buf=0,t.bi_valid=0):t.bi_valid>=8&&(t.pending_buf[t.pending++]=255&t.bi_buf,t.bi_buf>>=8,t.bi_valid-=8)}function _(t,e){var a,i,n,r,s,o,l=e.dyn_tree,h=e.max_code,d=e.stat_desc.static_tree,f=e.stat_desc.has_stree,_=e.stat_desc.extra_bits,u=e.stat_desc.extra_base,c=e.stat_desc.max_length,b=0;for(r=0;r<=K;r++)t.bl_count[r]=0;for(l[2*t.heap[t.heap_max]+1]=0,a=t.heap_max+1;a<j;a++)(r=l[2*l[2*(i=t.heap[a])+1]+1]+1)>c&&(r=c,b++),l[2*i+1]=r,i>h||(t.bl_count[r]++,s=0,i>=u&&(s=_[i-u]),o=l[2*i],t.opt_len+=o*(r+s),f&&(t.static_len+=o*(d[2*i+1]+s)));if(0!==b){do{for(r=c-1;0===t.bl_count[r];)r--;t.bl_count[r]--,t.bl_count[r+1]+=2,t.bl_count[c]--,b-=2}while(b>0);for(r=c;0!==r;r--)for(i=t.bl_count[r];0!==i;)(n=t.heap[--a])>h||(l[2*n+1]!==r&&(t.opt_len+=(r-l[2*n+1])*l[2*n],l[2*n+1]=r),i--)}}function u(t,e,a){var i,n,r=new Array(K+1),s=0;for(i=1;i<=K;i++)r[i]=s=s+a[i-1]<<1;for(n=0;n<=e;n++){var o=t[2*n+1];0!==o&&(t[2*n]=d(r[o]++,o))}}function c(){var t,e,a,i,r,s=new Array(K+1);for(a=0,i=0;i<U-1;i++)for(it[i]=a,t=0;t<1<<W[i];t++)at[a++]=i;for(at[a-1]=i,r=0,i=0;i<16;i++)for(nt[i]=r,t=0;t<1<<J[i];t++)et[r++]=i;for(r>>=7;i<L;i++)for(nt[i]=r<<7,t=0;t<1<<J[i]-7;t++)et[256+r++]=i;for(e=0;e<=K;e++)s[e]=0;for(t=0;t<=143;)$[2*t+1]=8,t++,s[8]++;for(;t<=255;)$[2*t+1]=9,t++,s[9]++;for(;t<=279;)$[2*t+1]=7,t++,s[7]++;for(;t<=287;)$[2*t+1]=8,t++,s[8]++;for(u($,F+1,s),t=0;t<L;t++)tt[2*t+1]=5,tt[2*t]=d(t,5);rt=new n($,W,T+1,F,K),st=new n(tt,J,0,L,K),ot=new n(new Array(0),Q,0,H,P)}function b(t){var e;for(e=0;e<F;e++)t.dyn_ltree[2*e]=0;for(e=0;e<L;e++)t.dyn_dtree[2*e]=0;for(e=0;e<H;e++)t.bl_tree[2*e]=0;t.dyn_ltree[2*Y]=1,t.opt_len=t.static_len=0,t.last_lit=t.matches=0}function g(t){t.bi_valid>8?o(t,t.bi_buf):t.bi_valid>0&&(t.pending_buf[t.pending++]=t.bi_buf),t.bi_buf=0,t.bi_valid=0}function m(t,e,a,i){g(t),i&&(o(t,a),o(t,~a)),A.arraySet(t.pending_buf,t.window,e,a,t.pending),t.pending+=a}function w(t,e,a,i){var n=2*e,r=2*a;return t[n]<t[r]||t[n]===t[r]&&i[e]<=i[a]}function p(t,e,a){for(var i=t.heap[a],n=a<<1;n<=t.heap_len&&(n<t.heap_len&&w(e,t.heap[n+1],t.heap[n],t.depth)&&n++,!w(e,i,t.heap[n],t.depth));)t.heap[a]=t.heap[n],a=n,n<<=1;t.heap[a]=i}function v(t,e,a){var i,n,r,o,d=0;if(0!==t.last_lit)do{i=t.pending_buf[t.d_buf+2*d]<<8|t.pending_buf[t.d_buf+2*d+1],n=t.pending_buf[t.l_buf+d],d++,0===i?h(t,n,e):(h(t,(r=at[n])+T+1,e),0!==(o=W[r])&&l(t,n-=it[r],o),h(t,r=s(--i),a),0!==(o=J[r])&&l(t,i-=nt[r],o))}while(d<t.last_lit);h(t,Y,e)}function k(t,e){var a,i,n,r=e.dyn_tree,s=e.stat_desc.static_tree,o=e.stat_desc.has_stree,l=e.stat_desc.elems,h=-1;for(t.heap_len=0,t.heap_max=j,a=0;a<l;a++)0!==r[2*a]?(t.heap[++t.heap_len]=h=a,t.depth[a]=0):r[2*a+1]=0;for(;t.heap_len<2;)r[2*(n=t.heap[++t.heap_len]=h<2?++h:0)]=1,t.depth[n]=0,t.opt_len--,o&&(t.static_len-=s[2*n+1]);for(e.max_code=h,a=t.heap_len>>1;a>=1;a--)p(t,r,a);n=l;do{a=t.heap[1],t.heap[1]=t.heap[t.heap_len--],p(t,r,1),i=t.heap[1],t.heap[--t.heap_max]=a,t.heap[--t.heap_max]=i,r[2*n]=r[2*a]+r[2*i],t.depth[n]=(t.depth[a]>=t.depth[i]?t.depth[a]:t.depth[i])+1,r[2*a+1]=r[2*i+1]=n,t.heap[1]=n++,p(t,r,1)}while(t.heap_len>=2);t.heap[--t.heap_max]=t.heap[1],_(t,e),u(r,h,t.bl_count)}function y(t,e,a){var i,n,r=-1,s=e[1],o=0,l=7,h=4;for(0===s&&(l=138,h=3),e[2*(a+1)+1]=65535,i=0;i<=a;i++)n=s,s=e[2*(i+1)+1],++o<l&&n===s||(o<h?t.bl_tree[2*n]+=o:0!==n?(n!==r&&t.bl_tree[2*n]++,t.bl_tree[2*q]++):o<=10?t.bl_tree[2*G]++:t.bl_tree[2*X]++,o=0,r=n,0===s?(l=138,h=3):n===s?(l=6,h=3):(l=7,h=4))}function x(t,e,a){var i,n,r=-1,s=e[1],o=0,d=7,f=4;for(0===s&&(d=138,f=3),i=0;i<=a;i++)if(n=s,s=e[2*(i+1)+1],!(++o<d&&n===s)){if(o<f)do{h(t,n,t.bl_tree)}while(0!=--o);else 0!==n?(n!==r&&(h(t,n,t.bl_tree),o--),h(t,q,t.bl_tree),l(t,o-3,2)):o<=10?(h(t,G,t.bl_tree),l(t,o-3,3)):(h(t,X,t.bl_tree),l(t,o-11,7));o=0,r=n,0===s?(d=138,f=3):n===s?(d=6,f=3):(d=7,f=4)}}function z(t){var e;for(y(t,t.dyn_ltree,t.l_desc.max_code),y(t,t.dyn_dtree,t.d_desc.max_code),k(t,t.bl_desc),e=H-1;e>=3&&0===t.bl_tree[2*V[e]+1];e--);return t.opt_len+=3*(e+1)+5+5+4,e}function B(t,e,a,i){var n;for(l(t,e-257,5),l(t,a-1,5),l(t,i-4,4),n=0;n<i;n++)l(t,t.bl_tree[2*V[n]+1],3);x(t,t.dyn_ltree,e-1),x(t,t.dyn_dtree,a-1)}function S(t){var e,a=4093624447;for(e=0;e<=31;e++,a>>>=1)if(1&a&&0!==t.dyn_ltree[2*e])return R;if(0!==t.dyn_ltree[18]||0!==t.dyn_ltree[20]||0!==t.dyn_ltree[26])return C;for(e=32;e<T;e++)if(0!==t.dyn_ltree[2*e])return C;return R}function E(t,e,a,i){l(t,(O<<1)+(i?1:0),3),m(t,e,a,!0)}var A=t("../utils/common"),Z=4,R=0,C=1,N=2,O=0,D=1,I=2,U=29,T=256,F=T+1+U,L=30,H=19,j=2*F+1,K=15,M=16,P=7,Y=256,q=16,G=17,X=18,W=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],J=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],Q=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],V=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],$=new Array(2*(F+2));i($);var tt=new Array(2*L);i(tt);var et=new Array(512);i(et);var at=new Array(256);i(at);var it=new Array(U);i(it);var nt=new Array(L);i(nt);var rt,st,ot,lt=!1;a._tr_init=function(t){lt||(c(),lt=!0),t.l_desc=new r(t.dyn_ltree,rt),t.d_desc=new r(t.dyn_dtree,st),t.bl_desc=new r(t.bl_tree,ot),t.bi_buf=0,t.bi_valid=0,b(t)},a._tr_stored_block=E,a._tr_flush_block=function(t,e,a,i){var n,r,s=0;t.level>0?(t.strm.data_type===N&&(t.strm.data_type=S(t)),k(t,t.l_desc),k(t,t.d_desc),s=z(t),n=t.opt_len+3+7>>>3,(r=t.static_len+3+7>>>3)<=n&&(n=r)):n=r=a+5,a+4<=n&&-1!==e?E(t,e,a,i):t.strategy===Z||r===n?(l(t,(D<<1)+(i?1:0),3),v(t,$,tt)):(l(t,(I<<1)+(i?1:0),3),B(t,t.l_desc.max_code+1,t.d_desc.max_code+1,s+1),v(t,t.dyn_ltree,t.dyn_dtree)),b(t),i&&g(t)},a._tr_tally=function(t,e,a){return t.pending_buf[t.d_buf+2*t.last_lit]=e>>>8&255,t.pending_buf[t.d_buf+2*t.last_lit+1]=255&e,t.pending_buf[t.l_buf+t.last_lit]=255&a,t.last_lit++,0===e?t.dyn_ltree[2*a]++:(t.matches++,e--,t.dyn_ltree[2*(at[a]+T+1)]++,t.dyn_dtree[2*s(e)]++),t.last_lit===t.lit_bufsize-1},a._tr_align=function(t){l(t,D<<1,3),h(t,Y,$),f(t)}},{"../utils/common":3}],15:[function(t,e,a){"use strict";e.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],"/":[function(t,e,a){"use strict";var i={};(0,t("./lib/utils/common").assign)(i,t("./lib/deflate"),t("./lib/inflate"),t("./lib/zlib/constants")),e.exports=i},{"./lib/deflate":1,"./lib/inflate":2,"./lib/utils/common":3,"./lib/zlib/constants":6}]},{},[])("/")});
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/README.chromium b/chromium/third_party/catapult/tracing/third_party/symbols/README.chromium
new file mode 100644
index 00000000000..b50ed33a8e4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/README.chromium
@@ -0,0 +1,21 @@
+Name: symbols module from Chromium
+URL: https://chromium.googlesource.com/chromium/src.git
+License: BSD
+
+Description:
+
+Originally added to src/build/android/pylib/symbols by Primiano Tucci:
+
+commit eb3ad0de43537c5bff297326b11b121c77cc18e6
+Author: primiano@chromium.org
+Date: Mon Feb 24 19:23:59 2014 +0000
+
+ Add fast ELF Symbolizer to memory_inspector.
+
+ This CL introduces a multiprocess, pipelined and asynchronous ELF
+ symbolizer (based on addr2line) which gives honor to a bulkly workstation
+ when symbolizing large batches of symbols.
+
+ BUG=340294,339059
+
+ Review URL: https://codereview.chromium.org/167893009
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py
new file mode 100644
index 00000000000..b4d94ae225b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/PRESUBMIT.py
@@ -0,0 +1,21 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+def CommonChecks(input_api, output_api):
+ output = []
+ output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+ output.extend(input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api,
+ output_api,
+ input_api.PresubmitLocalPath(),
+ whitelist=[r'^.+_unittest\.py$']))
+ return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api) \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/__init__.py b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/__init__.py
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py
new file mode 100644
index 00000000000..9deec868368
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer.py
@@ -0,0 +1,470 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import datetime
+import logging
+import multiprocessing
+import os
+import posixpath
+import re
+import subprocess
+import sys
+import threading
+import time
+try:
+ import Queue
+except ImportError:
+ import queue as Queue
+
+
+# addr2line builds a possibly infinite memory cache that can exhaust
+# the computer's memory if allowed to grow for too long. This constant
+# controls how many lookups we do before restarting the process. 4000
+# gives near peak performance without extreme memory usage.
+ADDR2LINE_RECYCLE_LIMIT = 4000
+
+
+class ELFSymbolizer(object):
+ """An uber-fast (multiprocessing, pipelined and asynchronous) ELF symbolizer.
+
+ This class is a frontend for addr2line (part of GNU binutils), designed to
+ symbolize batches of large numbers of symbols for a given ELF file. It
+ supports sharding symbolization against many addr2line instances and
+ pipelining of multiple requests per each instance (in order to hide addr2line
+ internals and OS pipe latencies).
+
+ The interface exhibited by this class is a very simple asynchronous interface,
+ which is based on the following three methods:
+ - SymbolizeAsync(): used to request (enqueue) resolution of a given address.
+ - The |callback| method: used to communicated back the symbol information.
+ - Join(): called to conclude the batch to gather the last outstanding results.
+ In essence, before the Join method returns, this class will have issued as
+ many callbacks as the number of SymbolizeAsync() calls. In this regard, note
+ that due to multiprocess sharding, callbacks can be delivered out of order.
+
+ Some background about addr2line:
+ - it is invoked passing the elf path in the cmdline, piping the addresses in
+ its stdin and getting results on its stdout.
+ - it has pretty large response times for the first requests, but it
+ works very well in streaming mode once it has been warmed up.
+ - it doesn't scale by itself (on more cores). However, spawning multiple
+ instances at the same time on the same file is pretty efficient as they
+ keep hitting the pagecache and become mostly CPU bound.
+ - it might hang or crash, mostly for OOM. This class deals with both of these
+ problems.
+
+ Despite the "scary" imports and the multi* words above, (almost) no multi-
+ threading/processing is involved from the python viewpoint. Concurrency
+ here is achieved by spawning several addr2line subprocesses and handling their
+ output pipes asynchronously. Therefore, all the code here (with the exception
+ of the Queue instance in Addr2Line) should be free from mind-blowing
+ thread-safety concerns.
+
+ The multiprocess sharding works as follows:
+ The symbolizer tries to use the lowest number of addr2line instances as
+ possible (with respect of |max_concurrent_jobs|) and enqueue all the requests
+ in a single addr2line instance. For few symbols (i.e. dozens) sharding isn't
+ worth the startup cost.
+ The multiprocess logic kicks in as soon as the queues for the existing
+ instances grow. Specifically, once all the existing instances reach the
+ |max_queue_size| bound, a new addr2line instance is kicked in.
+ In the case of a very eager producer (i.e. all |max_concurrent_jobs| instances
+ have a backlog of |max_queue_size|), back-pressure is applied on the caller by
+ blocking the SymbolizeAsync method.
+
+ This module has been deliberately designed to be dependency free (w.r.t. of
+ other modules in this project), to allow easy reuse in external projects.
+ """
+
+ def __init__(self, elf_file_path, addr2line_path, callback, inlines=False,
+ max_concurrent_jobs=None, addr2line_timeout=30, max_queue_size=50,
+ source_root_path=None, strip_base_path=None):
+ """Args:
+ elf_file_path: path of the elf file to be symbolized.
+ addr2line_path: path of the toolchain's addr2line binary.
+ callback: a callback which will be invoked for each resolved symbol with
+ the two args (sym_info, callback_arg). The former is an instance of
+ |ELFSymbolInfo| and contains the symbol information. The latter is an
+ embedder-provided argument which is passed to SymbolizeAsync().
+ inlines: when True, the ELFSymbolInfo will contain also the details about
+ the outer inlining functions. When False, only the innermost function
+ will be provided.
+ max_concurrent_jobs: Max number of addr2line instances spawned.
+ Parallelize responsibly, addr2line is a memory and I/O monster.
+ max_queue_size: Max number of outstanding requests per addr2line instance.
+ addr2line_timeout: Max time (in seconds) to wait for a addr2line response.
+ After the timeout, the instance will be considered hung and respawned.
+ source_root_path: In some toolchains only the name of the source file is
+ is output, without any path information; disambiguation searches
+ through the source directory specified by |source_root_path| argument
+ for files whose name matches, adding the full path information to the
+ output. For example, if the toolchain outputs "unicode.cc" and there
+ is a file called "unicode.cc" located under |source_root_path|/foo,
+ the tool will replace "unicode.cc" with
+ "|source_root_path|/foo/unicode.cc". If there are multiple files with
+ the same name, disambiguation will fail because the tool cannot
+ determine which of the files was the source of the symbol.
+ strip_base_path: Rebases the symbols source paths onto |source_root_path|
+ (i.e replace |strip_base_path| with |source_root_path).
+ """
+ assert(os.path.isfile(addr2line_path)), 'Cannot find ' + addr2line_path
+ self.elf_file_path = elf_file_path
+ self.addr2line_path = addr2line_path
+ self.callback = callback
+ self.inlines = inlines
+ self.max_concurrent_jobs = (max_concurrent_jobs or
+ min(multiprocessing.cpu_count(), 4))
+ self.max_queue_size = max_queue_size
+ self.addr2line_timeout = addr2line_timeout
+ self.requests_counter = 0 # For generating monotonic request IDs.
+ self._a2l_instances = [] # Up to |max_concurrent_jobs| _Addr2Line inst.
+
+ # If necessary, create disambiguation lookup table
+ self.disambiguate = source_root_path is not None
+ self.disambiguation_table = {}
+ self.strip_base_path = strip_base_path
+ if(self.disambiguate):
+ self.source_root_path = os.path.abspath(source_root_path)
+ self._CreateDisambiguationTable()
+
+ # Create one addr2line instance. More instances will be created on demand
+ # (up to |max_concurrent_jobs|) depending on the rate of the requests.
+ self._CreateNewA2LInstance()
+
+ def SymbolizeAsync(self, addr, callback_arg=None):
+ """Requests symbolization of a given address.
+
+ This method is not guaranteed to return immediately. It generally does, but
+ in some scenarios (e.g. all addr2line instances have full queues) it can
+ block to create back-pressure.
+
+ Args:
+ addr: address to symbolize.
+ callback_arg: optional argument which will be passed to the |callback|."""
+ assert(isinstance(addr, int))
+
+ # Process all the symbols that have been resolved in the meanwhile.
+ # Essentially, this drains all the addr2line(s) out queues.
+ for a2l_to_purge in self._a2l_instances:
+ a2l_to_purge.ProcessAllResolvedSymbolsInQueue()
+ a2l_to_purge.RecycleIfNecessary()
+
+ # Find the best instance according to this logic:
+ # 1. Find an existing instance with the shortest queue.
+ # 2. If all of instances' queues are full, but there is room in the pool,
+ # (i.e. < |max_concurrent_jobs|) create a new instance.
+ # 3. If there were already |max_concurrent_jobs| instances and all of them
+ # had full queues, make back-pressure.
+
+ # 1.
+ def _SortByQueueSizeAndReqID(a2l):
+ return (a2l.queue_size, a2l.first_request_id)
+ a2l = min(self._a2l_instances, key=_SortByQueueSizeAndReqID)
+
+ # 2.
+ if (a2l.queue_size >= self.max_queue_size and
+ len(self._a2l_instances) < self.max_concurrent_jobs):
+ a2l = self._CreateNewA2LInstance()
+
+ # 3.
+ if a2l.queue_size >= self.max_queue_size:
+ a2l.WaitForNextSymbolInQueue()
+
+ a2l.EnqueueRequest(addr, callback_arg)
+
+ def Join(self):
+ """Waits for all the outstanding requests to complete and terminates."""
+ for a2l in self._a2l_instances:
+ a2l.WaitForIdle()
+ a2l.Terminate()
+
+ def _CreateNewA2LInstance(self):
+ assert(len(self._a2l_instances) < self.max_concurrent_jobs)
+ a2l = ELFSymbolizer.Addr2Line(self)
+ self._a2l_instances.append(a2l)
+ return a2l
+
+ def _CreateDisambiguationTable(self):
+ """ Non-unique file names will result in None entries"""
+ start_time = time.time()
+ logging.info('Collecting information about available source files...')
+ self.disambiguation_table = {}
+
+ for root, _, filenames in os.walk(self.source_root_path):
+ for f in filenames:
+ self.disambiguation_table[f] = os.path.join(root, f) if (f not in
+ self.disambiguation_table) else None
+ logging.info('Finished collecting information about '
+ 'possible files (took %.1f s).',
+ (time.time() - start_time))
+
+
+ class Addr2Line(object):
+ """A python wrapper around an addr2line instance.
+
+ The communication with the addr2line process looks as follows:
+ [STDIN] [STDOUT] (from addr2line's viewpoint)
+ > f001111
+ > f002222
+ < Symbol::Name(foo, bar) for f001111
+ < /path/to/source/file.c:line_number
+ > f003333
+ < Symbol::Name2() for f002222
+ < /path/to/source/file.c:line_number
+ < Symbol::Name3() for f003333
+ < /path/to/source/file.c:line_number
+ """
+
+ SYM_ADDR_RE = re.compile(r'([^:]+):(\?|\d+).*')
+
+ def __init__(self, symbolizer):
+ self._symbolizer = symbolizer
+ self._lib_file_name = posixpath.basename(symbolizer.elf_file_path)
+
+ # The request queue (i.e. addresses pushed to addr2line's stdin and not
+ # yet retrieved on stdout)
+ self._request_queue = collections.deque()
+
+ # This is essentially len(self._request_queue). It has been optimized to a
+ # separate field because turned out to be a perf hot-spot.
+ self.queue_size = 0
+
+ # Keep track of the number of symbols a process has processed to
+ # avoid a single process growing too big and using all the memory.
+ self._processed_symbols_count = 0
+
+ # Objects required to handle the addr2line subprocess.
+ self._proc = None # Subprocess.Popen(...) instance.
+ self._thread = None # Threading.thread instance.
+ self._out_queue = None # Queue.Queue instance (for buffering a2l stdout).
+ self._RestartAddr2LineProcess()
+
+ def EnqueueRequest(self, addr, callback_arg):
+ """Pushes an address to addr2line's stdin (and keeps track of it)."""
+ self._symbolizer.requests_counter += 1 # For global "age" of requests.
+ req_idx = self._symbolizer.requests_counter
+ self._request_queue.append((addr, callback_arg, req_idx))
+ self.queue_size += 1
+ self._WriteToA2lStdin(addr)
+
+ def WaitForIdle(self):
+ """Waits until all the pending requests have been symbolized."""
+ while self.queue_size > 0:
+ self.WaitForNextSymbolInQueue()
+
+ def WaitForNextSymbolInQueue(self):
+ """Waits for the next pending request to be symbolized."""
+ if not self.queue_size:
+ return
+
+ # This outer loop guards against a2l hanging (detecting stdout timeout).
+ while True:
+ start_time = datetime.datetime.now()
+ timeout = datetime.timedelta(seconds=self._symbolizer.addr2line_timeout)
+
+ # The inner loop guards against a2l crashing (checking if it exited).
+ while (datetime.datetime.now() - start_time < timeout):
+ # poll() returns !None if the process exited. a2l should never exit.
+ if self._proc.poll():
+ logging.warning('addr2line crashed, respawning (lib: %s).' %
+ self._lib_file_name)
+ self._RestartAddr2LineProcess()
+ # TODO(primiano): the best thing to do in this case would be
+ # shrinking the pool size as, very likely, addr2line is crashed
+ # due to low memory (and the respawned one will die again soon).
+
+ try:
+ lines = self._out_queue.get(block=True, timeout=0.25)
+ except Queue.Empty:
+ # On timeout (1/4 s.) repeat the inner loop and check if either the
+ # addr2line process did crash or we waited its output for too long.
+ continue
+
+ # In nominal conditions, we get straight to this point.
+ self._ProcessSymbolOutput(lines)
+ return
+
+ # If this point is reached, we waited more than |addr2line_timeout|.
+ logging.warning('Hung addr2line process, respawning (lib: %s).' %
+ self._lib_file_name)
+ self._RestartAddr2LineProcess()
+
+ def ProcessAllResolvedSymbolsInQueue(self):
+ """Consumes all the addr2line output lines produced (without blocking)."""
+ if not self.queue_size:
+ return
+ while True:
+ try:
+ lines = self._out_queue.get_nowait()
+ except Queue.Empty:
+ break
+ self._ProcessSymbolOutput(lines)
+
+ def RecycleIfNecessary(self):
+ """Restarts the process if it has been used for too long.
+
+ A long running addr2line process will consume excessive amounts
+ of memory without any gain in performance."""
+ if self._processed_symbols_count >= ADDR2LINE_RECYCLE_LIMIT:
+ self._RestartAddr2LineProcess()
+
+
+ def Terminate(self):
+ """Kills the underlying addr2line process.
+
+ The poller |_thread| will terminate as well due to the broken pipe."""
+ try:
+ self._proc.kill()
+ self._proc.communicate() # Essentially wait() without risking deadlock.
+ except Exception: # An exception while terminating? How interesting.
+ pass
+ self._proc = None
+
+ def _WriteToA2lStdin(self, addr):
+ self._proc.stdin.write('%s\n' % hex(addr))
+ if self._symbolizer.inlines:
+ # In the case of inlines we output an extra blank line, which causes
+ # addr2line to emit a (??,??:0) tuple that we use as a boundary marker.
+ self._proc.stdin.write('\n')
+ self._proc.stdin.flush()
+
+ def _ProcessSymbolOutput(self, lines):
+ """Parses an addr2line symbol output and triggers the client callback."""
+ (_, callback_arg, _) = self._request_queue.popleft()
+ self.queue_size -= 1
+
+ innermost_sym_info = None
+ sym_info = None
+ for (line1, line2) in lines:
+ prev_sym_info = sym_info
+ name = line1 if not line1.startswith('?') else None
+ source_path = None
+ source_line = None
+ m = ELFSymbolizer.Addr2Line.SYM_ADDR_RE.match(line2)
+ if m:
+ if not m.group(1).startswith('?'):
+ source_path = m.group(1)
+ if not m.group(2).startswith('?'):
+ source_line = int(m.group(2))
+ else:
+ logging.warning('Got invalid symbol path from addr2line: %s' % line2)
+
+ # In case disambiguation is on, and needed
+ was_ambiguous = False
+ disambiguated = False
+ if self._symbolizer.disambiguate:
+ if source_path and not posixpath.isabs(source_path):
+ path = self._symbolizer.disambiguation_table.get(source_path)
+ was_ambiguous = True
+ disambiguated = path is not None
+ source_path = path if disambiguated else source_path
+
+ # Use absolute paths (so that paths are consistent, as disambiguation
+ # uses absolute paths)
+ if source_path and not was_ambiguous:
+ source_path = os.path.abspath(source_path)
+
+ if source_path and self._symbolizer.strip_base_path:
+ # Strip the base path
+ source_path = re.sub('^' + self._symbolizer.strip_base_path,
+ self._symbolizer.source_root_path or '', source_path)
+
+ sym_info = ELFSymbolInfo(name, source_path, source_line, was_ambiguous,
+ disambiguated)
+ if prev_sym_info:
+ prev_sym_info.inlined_by = sym_info
+ if not innermost_sym_info:
+ innermost_sym_info = sym_info
+
+ self._processed_symbols_count += 1
+ self._symbolizer.callback(innermost_sym_info, callback_arg)
+
+ def _RestartAddr2LineProcess(self):
+ if self._proc:
+ self.Terminate()
+
+ # The only reason of existence of this Queue (and the corresponding
+ # Thread below) is the lack of a subprocess.stdout.poll_avail_lines().
+ # Essentially this is a pipe able to extract a couple of lines atomically.
+ self._out_queue = Queue.Queue()
+
+ # Start the underlying addr2line process in line buffered mode.
+
+ cmd = [self._symbolizer.addr2line_path, '--functions', '--demangle',
+ '--exe=' + self._symbolizer.elf_file_path]
+ if self._symbolizer.inlines:
+ cmd += ['--inlines']
+ self._proc = subprocess.Popen(cmd, bufsize=1, stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE, stderr=sys.stderr, close_fds=True)
+
+ # Start the poller thread, which simply moves atomically the lines read
+ # from the addr2line's stdout to the |_out_queue|.
+ self._thread = threading.Thread(
+ target=ELFSymbolizer.Addr2Line.StdoutReaderThread,
+ args=(self._proc.stdout, self._out_queue, self._symbolizer.inlines))
+ self._thread.daemon = True # Don't prevent early process exit.
+ self._thread.start()
+
+ self._processed_symbols_count = 0
+
+ # Replay the pending requests on the new process (only for the case
+ # of a hung addr2line timing out during the game).
+ for (addr, _, _) in self._request_queue:
+ self._WriteToA2lStdin(addr)
+
+ @staticmethod
+ def StdoutReaderThread(process_pipe, queue, inlines):
+ """The poller thread fn, which moves the addr2line stdout to the |queue|.
+
+ This is the only piece of code not running on the main thread. It merely
+ writes to a Queue, which is thread-safe. In the case of inlines, it
+ detects the ??,??:0 marker and sends the lines atomically, such that the
+ main thread always receives all the lines corresponding to one symbol in
+ one shot."""
+ try:
+ lines_for_one_symbol = []
+ while True:
+ line1 = process_pipe.readline().rstrip('\r\n')
+ line2 = process_pipe.readline().rstrip('\r\n')
+ if not line1 or not line2:
+ break
+ inline_has_more_lines = inlines and (len(lines_for_one_symbol) == 0 or
+ (line1 != '??' and line2 != '??:0'))
+ if not inlines or inline_has_more_lines:
+ lines_for_one_symbol += [(line1, line2)]
+ if inline_has_more_lines:
+ continue
+ queue.put(lines_for_one_symbol)
+ lines_for_one_symbol = []
+ process_pipe.close()
+
+ # Every addr2line processes will die at some point, please die silently.
+ except (IOError, OSError):
+ pass
+
+ @property
+ def first_request_id(self):
+ """Returns the request_id of the oldest pending request in the queue."""
+ return self._request_queue[0][2] if self._request_queue else 0
+
+
+class ELFSymbolInfo(object):
+ """The result of the symbolization passed as first arg. of each callback."""
+
+ def __init__(self, name, source_path, source_line, was_ambiguous=False,
+ disambiguated=False):
+ """All the fields here can be None (if addr2line replies with '??')."""
+ self.name = name
+ self.source_path = source_path
+ self.source_line = source_line
+ # In the case of |inlines|=True, the |inlined_by| points to the outer
+ # function inlining the current one (and so on, to form a chain).
+ self.inlined_by = None
+ self.disambiguated = disambiguated
+ self.was_ambiguous = was_ambiguous
+
+ def __str__(self):
+ return '%s [%s:%d]' % (
+ self.name or '??', self.source_path or '??', self.source_line or 0)
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py
new file mode 100755
index 00000000000..d7978aba0f8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/elf_symbolizer_unittest.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import functools
+import logging
+import os
+import sys
+import unittest
+
+sys.path.insert(0, os.path.dirname(__file__))
+# pylint: disable=relative-import
+import elf_symbolizer
+import mock_addr2line
+
+
+_MOCK_A2L_PATH = os.path.join(os.path.dirname(mock_addr2line.__file__),
+ 'mock_addr2line')
+_INCOMPLETE_MOCK_ADDR = 1024 * 1024
+_UNKNOWN_MOCK_ADDR = 2 * 1024 * 1024
+_INLINE_MOCK_ADDR = 3 * 1024 * 1024
+
+
+class ELFSymbolizerTest(unittest.TestCase):
+ def setUp(self):
+ self._callback = functools.partial(
+ ELFSymbolizerTest._SymbolizeCallback, self)
+ self._resolved_addresses = set()
+ # Mute warnings, we expect them due to the crash/hang tests.
+ logging.getLogger().setLevel(logging.ERROR)
+
+ def testParallelism1(self):
+ self._RunTest(max_concurrent_jobs=1, num_symbols=100)
+
+ def testParallelism4(self):
+ self._RunTest(max_concurrent_jobs=4, num_symbols=100)
+
+ def testParallelism8(self):
+ self._RunTest(max_concurrent_jobs=8, num_symbols=100)
+
+ def testCrash(self):
+ os.environ['MOCK_A2L_CRASH_EVERY'] = '99'
+ self._RunTest(max_concurrent_jobs=1, num_symbols=100)
+ os.environ['MOCK_A2L_CRASH_EVERY'] = '0'
+
+ def testHang(self):
+ os.environ['MOCK_A2L_HANG_EVERY'] = '99'
+ self._RunTest(max_concurrent_jobs=1, num_symbols=100)
+ os.environ['MOCK_A2L_HANG_EVERY'] = '0'
+
+ def testInlines(self):
+ """Stimulate the inline processing logic."""
+ symbolizer = elf_symbolizer.ELFSymbolizer(
+ elf_file_path='/path/doesnt/matter/mock_lib1.so',
+ addr2line_path=_MOCK_A2L_PATH,
+ callback=self._callback,
+ inlines=True,
+ max_concurrent_jobs=4)
+
+ for addr in xrange(1000):
+ exp_inline = False
+ exp_unknown = False
+
+ # First 100 addresses with inlines.
+ if addr < 100:
+ addr += _INLINE_MOCK_ADDR
+ exp_inline = True
+
+ # Followed by 100 without inlines.
+ elif addr < 200:
+ pass
+
+ # Followed by 100 interleaved inlines and not inlines.
+ elif addr < 300:
+ if addr & 1:
+ addr += _INLINE_MOCK_ADDR
+ exp_inline = True
+
+ # Followed by 100 interleaved inlines and unknonwn.
+ elif addr < 400:
+ if addr & 1:
+ addr += _INLINE_MOCK_ADDR
+ exp_inline = True
+ else:
+ addr += _UNKNOWN_MOCK_ADDR
+ exp_unknown = True
+
+ exp_name = 'mock_sym_for_addr_%d' % addr if not exp_unknown else None
+ exp_source_path = 'mock_src/mock_lib1.so.c' if not exp_unknown else None
+ exp_source_line = addr if not exp_unknown else None
+ cb_arg = (addr, exp_name, exp_source_path, exp_source_line, exp_inline)
+ symbolizer.SymbolizeAsync(addr, cb_arg)
+
+ symbolizer.Join()
+
+ def testIncompleteSyminfo(self):
+ """Stimulate the symbol-not-resolved logic."""
+ symbolizer = elf_symbolizer.ELFSymbolizer(
+ elf_file_path='/path/doesnt/matter/mock_lib1.so',
+ addr2line_path=_MOCK_A2L_PATH,
+ callback=self._callback,
+ max_concurrent_jobs=1)
+
+ # Test symbols with valid name but incomplete path.
+ addr = _INCOMPLETE_MOCK_ADDR
+ exp_name = 'mock_sym_for_addr_%d' % addr
+ exp_source_path = None
+ exp_source_line = None
+ cb_arg = (addr, exp_name, exp_source_path, exp_source_line, False)
+ symbolizer.SymbolizeAsync(addr, cb_arg)
+
+ # Test symbols with no name or sym info.
+ addr = _UNKNOWN_MOCK_ADDR
+ exp_name = None
+ exp_source_path = None
+ exp_source_line = None
+ cb_arg = (addr, exp_name, exp_source_path, exp_source_line, False)
+ symbolizer.SymbolizeAsync(addr, cb_arg)
+
+ symbolizer.Join()
+
+ def _RunTest(self, max_concurrent_jobs, num_symbols):
+ symbolizer = elf_symbolizer.ELFSymbolizer(
+ elf_file_path='/path/doesnt/matter/mock_lib1.so',
+ addr2line_path=_MOCK_A2L_PATH,
+ callback=self._callback,
+ max_concurrent_jobs=max_concurrent_jobs,
+ addr2line_timeout=0.5)
+
+ for addr in xrange(num_symbols):
+ exp_name = 'mock_sym_for_addr_%d' % addr
+ exp_source_path = 'mock_src/mock_lib1.so.c'
+ exp_source_line = addr
+ cb_arg = (addr, exp_name, exp_source_path, exp_source_line, False)
+ symbolizer.SymbolizeAsync(addr, cb_arg)
+
+ symbolizer.Join()
+
+ # Check that all the expected callbacks have been received.
+ for addr in xrange(num_symbols):
+ self.assertIn(addr, self._resolved_addresses)
+ self._resolved_addresses.remove(addr)
+
+ # Check for unexpected callbacks.
+ self.assertEqual(len(self._resolved_addresses), 0)
+
+ def _SymbolizeCallback(self, sym_info, cb_arg):
+ self.assertTrue(isinstance(sym_info, elf_symbolizer.ELFSymbolInfo))
+ self.assertTrue(isinstance(cb_arg, tuple))
+ self.assertEqual(len(cb_arg), 5)
+
+ # Unpack expectations from the callback extra argument.
+ (addr, exp_name, exp_source_path, exp_source_line, exp_inlines) = cb_arg
+ if exp_name is None:
+ self.assertIsNone(sym_info.name)
+ else:
+ self.assertTrue(sym_info.name.startswith(exp_name))
+ self.assertEqual(sym_info.source_path, exp_source_path)
+ self.assertEqual(sym_info.source_line, exp_source_line)
+
+ if exp_inlines:
+ self.assertEqual(sym_info.name, exp_name + '_inner')
+ self.assertEqual(sym_info.inlined_by.name, exp_name + '_middle')
+ self.assertEqual(sym_info.inlined_by.inlined_by.name,
+ exp_name + '_outer')
+
+ # Check against duplicate callbacks.
+ self.assertNotIn(addr, self._resolved_addresses)
+ self._resolved_addresses.add(addr)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/__init__.py b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/__init__.py
diff --git a/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line
new file mode 100755
index 00000000000..5544359ad60
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/third_party/symbols/symbols/mock_addr2line/mock_addr2line
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Simple mock for addr2line.
+
+Outputs mock symbol information, with each symbol being a function of the
+original address (so it is easy to double-check consistency in unittests).
+"""
+
+import optparse
+import os
+import posixpath
+import sys
+import time
+
+
+def main(argv):
+ parser = optparse.OptionParser()
+ parser.add_option('-e', '--exe', dest='exe') # Path of the debug-library.so.
+ # Silently swallow the other unnecessary arguments.
+ parser.add_option('-C', '--demangle', action='store_true')
+ parser.add_option('-f', '--functions', action='store_true')
+ parser.add_option('-i', '--inlines', action='store_true')
+ options, _ = parser.parse_args(argv[1:])
+ lib_file_name = posixpath.basename(options.exe)
+ processed_sym_count = 0
+ crash_every = int(os.environ.get('MOCK_A2L_CRASH_EVERY', 0))
+ hang_every = int(os.environ.get('MOCK_A2L_HANG_EVERY', 0))
+
+ while(True):
+ line = sys.stdin.readline().rstrip('\r')
+ if not line:
+ break
+
+ # An empty line should generate '??,??:0' (is used as marker for inlines).
+ if line == '\n':
+ print '??'
+ print '??:0'
+ sys.stdout.flush()
+ continue
+
+ addr = int(line, 16)
+ processed_sym_count += 1
+ if crash_every and processed_sym_count % crash_every == 0:
+ sys.exit(1)
+ if hang_every and processed_sym_count % hang_every == 0:
+ time.sleep(1)
+
+ # Addresses < 1M will return good mock symbol information.
+ if addr < 1024 * 1024:
+ print 'mock_sym_for_addr_%d' % addr
+ print 'mock_src/%s.c:%d' % (lib_file_name, addr)
+
+ # Addresses 1M <= x < 2M will return symbols with a name but a missing path.
+ elif addr < 2 * 1024 * 1024:
+ print 'mock_sym_for_addr_%d' % addr
+ print '??:0'
+
+ # Addresses 2M <= x < 3M will return unknown symbol information.
+ elif addr < 3 * 1024 * 1024:
+ print '??'
+ print '??'
+
+ # Addresses 3M <= x < 4M will return inlines.
+ elif addr < 4 * 1024 * 1024:
+ print 'mock_sym_for_addr_%d_inner' % addr
+ print 'mock_src/%s.c:%d' % (lib_file_name, addr)
+ print 'mock_sym_for_addr_%d_middle' % addr
+ print 'mock_src/%s.c:%d' % (lib_file_name, addr)
+ print 'mock_sym_for_addr_%d_outer' % addr
+ print 'mock_src/%s.c:%d' % (lib_file_name, addr)
+
+ else:
+ print 'mock_sym_for_addr_%d' % addr
+ print 'mock_src/%s.c:%d' % (lib_file_name, addr)
+
+ sys.stdout.flush()
+
+
+if __name__ == '__main__':
+ main(sys.argv) \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/tracing/__init__.py b/chromium/third_party/catapult/tracing/tracing/__init__.py
new file mode 100644
index 00000000000..76063aae790
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/__init__.py
@@ -0,0 +1,6 @@
+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import tracing_project
+tracing_project.UpdateSysPathIfNeeded()
diff --git a/chromium/third_party/catapult/tracing/tracing/base/assert_utils.html b/chromium/third_party/catapult/tracing/tracing/base/assert_utils.html
new file mode 100644
index 00000000000..1f0a9972d07
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/assert_utils.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<script>
+'use strict';
+
+// TODO(charliea): Investigate whether we could make this a Chai plugin.
+/**
+ * @fileoverview Provides assert functions that are not available on the Chai
+ * assert module.
+ */
+tr.exportTo('tr.b', function() {
+ /**
+ * Throws if the range |actual| is not equal to the range |expected| (using
+ * tr.b.math.Range.equals).
+ */
+ function assertRangeEquals(actual, expected) {
+ assert(actual.equals(expected),
+ 'Expected Range(' + actual.min + ', ' + actual.max + ') to be ' +
+ 'Range(' + expected.min + ', ' + expected.max + ')');
+ }
+
+ return {
+ assertRangeEquals,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/base.html b/chromium/third_party/catapult/tracing/tracing/base/base.html
new file mode 100644
index 00000000000..c313389b4d0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/base.html
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<script>
+'use strict';
+
+/**
+ * The global object.
+ * @type {!Object}
+ * @const
+ */
+const global = this.window || this.global;
+
+/** Platform, package, object property, and Event support. */
+this.tr = (function() {
+ if (global.tr) return global.tr;
+
+ /**
+ * Builds an object structure for the provided namespace path,
+ * ensuring that names that already exist are not overwritten. For
+ * example:
+ * 'a.b.c' -> a = {};a.b={};a.b.c={};
+ * @param {string} name Name of the object that this file defines.
+ * @private
+ */
+ function exportPath(name) {
+ const parts = name.split('.');
+ let cur = global;
+
+ for (let part; parts.length && (part = parts.shift());) {
+ if (part in cur) {
+ cur = cur[part];
+ } else {
+ cur = cur[part] = {};
+ }
+ }
+ return cur;
+ }
+
+ function isExported(name) {
+ const parts = name.split('.');
+ let cur = global;
+
+ for (let part; parts.length && (part = parts.shift());) {
+ if (part in cur) {
+ cur = cur[part];
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function isDefined(name) {
+ const parts = name.split('.');
+
+ let curObject = global;
+
+ for (let i = 0; i < parts.length; i++) {
+ const partName = parts[i];
+ const nextObject = curObject[partName];
+ if (nextObject === undefined) return false;
+ curObject = nextObject;
+ }
+ return true;
+ }
+
+ let panicElement = undefined;
+ const rawPanicMessages = [];
+ function showPanicElementIfNeeded() {
+ if (panicElement) return;
+
+ const panicOverlay = document.createElement('div');
+ panicOverlay.style.backgroundColor = 'white';
+ panicOverlay.style.border = '3px solid red';
+ panicOverlay.style.boxSizing = 'border-box';
+ panicOverlay.style.color = 'black';
+ panicOverlay.style.display = 'flex';
+ panicOverlay.style.height = '100%';
+ panicOverlay.style.left = 0;
+ panicOverlay.style.padding = '8px';
+ panicOverlay.style.position = 'fixed';
+ panicOverlay.style.top = 0;
+ panicOverlay.style.webkitFlexDirection = 'column';
+ panicOverlay.style.width = '100%';
+
+ panicElement = document.createElement('div');
+ panicElement.style.webkitFlex = '1 1 auto';
+ panicElement.style.overflow = 'auto';
+ panicOverlay.appendChild(panicElement);
+
+ if (!document.body) {
+ setTimeout(function() {
+ document.body.appendChild(panicOverlay);
+ }, 150);
+ } else {
+ document.body.appendChild(panicOverlay);
+ }
+ }
+
+ function showPanic(panicTitle, panicDetails) {
+ if (tr.isHeadless) {
+ if (panicDetails instanceof Error) throw panicDetails;
+ throw new Error('Panic: ' + panicTitle + ':\n' + panicDetails);
+ }
+
+ if (panicDetails instanceof Error) {
+ panicDetails = panicDetails.stack;
+ }
+
+ showPanicElementIfNeeded();
+ const panicMessageEl = document.createElement('div');
+ panicMessageEl.innerHTML =
+ '<h2 id="message"></h2>' +
+ '<pre id="details"></pre>';
+ panicMessageEl.querySelector('#message').textContent = panicTitle;
+ panicMessageEl.querySelector('#details').textContent = panicDetails;
+ panicElement.appendChild(panicMessageEl);
+
+ rawPanicMessages.push({
+ title: panicTitle,
+ details: panicDetails
+ });
+ }
+
+ function hasPanic() {
+ return rawPanicMessages.length !== 0;
+ }
+ function getPanicText() {
+ return rawPanicMessages.map(function(msg) {
+ return msg.title;
+ }).join(', ');
+ }
+
+ function exportTo(namespace, fn) {
+ const obj = exportPath(namespace);
+ const exports = fn();
+
+ for (const propertyName in exports) {
+ // Maybe we should check the prototype chain here? The current usage
+ // pattern is always using an object literal so we only care about own
+ // properties.
+ const propertyDescriptor = Object.getOwnPropertyDescriptor(exports,
+ propertyName);
+ if (propertyDescriptor) {
+ Object.defineProperty(obj, propertyName, propertyDescriptor);
+ }
+ }
+ }
+
+ /**
+ * Initialization which must be deferred until run-time.
+ */
+ function initialize() {
+ if (global.isVinn) {
+ tr.isVinn = true;
+ } else if (global.process && global.process.versions.node) {
+ tr.isNode = true;
+ } else {
+ tr.isVinn = false;
+ tr.isNode = false;
+ tr.doc = document;
+
+ tr.isMac = /Mac/.test(navigator.platform);
+ tr.isWindows = /Win/.test(navigator.platform);
+ tr.isChromeOS = /CrOS/.test(navigator.userAgent);
+ tr.isLinux = /Linux/.test(navigator.userAgent);
+ }
+ tr.isHeadless = tr.isVinn || tr.isNode;
+ }
+
+ return {
+ initialize,
+
+ exportTo,
+ isExported,
+ isDefined,
+
+ showPanic,
+ hasPanic,
+ getPanicText,
+ };
+})();
+
+tr.initialize();
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/base64.html b/chromium/third_party/catapult/tracing/tracing/base/base64.html
new file mode 100644
index 00000000000..4e78cd9e5e6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/base64.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ function Base64() {
+ }
+
+ function b64ToUint6(nChr) {
+ if (nChr > 64 && nChr < 91) return nChr - 65;
+ if (nChr > 96 && nChr < 123) return nChr - 71;
+ if (nChr > 47 && nChr < 58) return nChr + 4;
+ if (nChr === 43) return 62;
+ if (nChr === 47) return 63;
+ return 0;
+ }
+
+ Base64.getDecodedBufferLength = function(input) {
+ let pad = 0;
+ if (input.substr(-2) === '==') {
+ pad = 2;
+ } else if (input.substr(-1) === '=') {
+ pad = 1;
+ }
+ return ((input.length * 3 + 1) >> 2) - pad;
+ };
+
+ Base64.EncodeArrayBufferToString = function(input) {
+ // http://stackoverflow.com/questions/9267899/
+ let binary = '';
+ const bytes = new Uint8Array(input);
+ const len = bytes.byteLength;
+ for (let i = 0; i < len; i++) {
+ binary += String.fromCharCode(bytes[i]);
+ }
+ return btoa(binary);
+ };
+
+ Base64.DecodeToTypedArray = function(input, output) {
+ const nInLen = input.length;
+ const nOutLen = Base64.getDecodedBufferLength(input);
+ let nMod3 = 0;
+ let nMod4 = 0;
+ let nUint24 = 0;
+ let nOutIdx = 0;
+
+ if (nOutLen > output.byteLength) {
+ throw new Error('Output buffer too small to decode.');
+ }
+
+ for (let nInIdx = 0; nInIdx < nInLen; nInIdx++) {
+ nMod4 = nInIdx & 3;
+ nUint24 |= b64ToUint6(input.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
+ if (nMod4 === 3 || nInLen - nInIdx === 1) {
+ for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
+ output.setUint8(nOutIdx, nUint24 >>> (16 >>> nMod3 & 24) & 255);
+ }
+ nUint24 = 0;
+ }
+ }
+ return nOutLen;
+ };
+
+ /*
+ * Wrapper of btoa
+ * The reason is that window object has a builtin btoa,
+ * but we also want to use btoa when it is headless.
+ * For example we want to use it in a mapper
+ */
+ Base64.btoa = function(input) {
+ return btoa(input);
+ };
+
+ /*
+ * Wrapper of atob
+ * The reason is that window object has a builtin atob,
+ * but we also want to use atob when it is headless.
+ * For example we want to use it in a mapper
+ */
+ Base64.atob = function(input) {
+ return atob(input);
+ };
+
+ return {
+ Base64,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/base64_test.html b/chromium/third_party/catapult/tracing/tracing/base/base64_test.html
new file mode 100644
index 00000000000..44970675a8b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/base64_test.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base64.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('getDecodedLength', function() {
+ assert.strictEqual(tr.b.Base64.getDecodedBufferLength('YQ=='), 1);
+ assert.strictEqual(tr.b.Base64.getDecodedBufferLength('YWI='), 2);
+ assert.strictEqual(tr.b.Base64.getDecodedBufferLength('YWJj='), 3);
+ assert.strictEqual(tr.b.Base64.getDecodedBufferLength('YWJjZA=='), 4);
+ assert.strictEqual(tr.b.Base64.getDecodedBufferLength('YWJjZGU='), 5);
+ assert.strictEqual(tr.b.Base64.getDecodedBufferLength('YWJjZGVm'), 6);
+ });
+
+ test('DecodeToTypedArray', function() {
+ const buffer = new DataView(new ArrayBuffer(256));
+ tr.b.Base64.DecodeToTypedArray('YQ==', buffer);
+ assert.strictEqual(buffer.getInt8(0), 97);
+
+ tr.b.Base64.DecodeToTypedArray('YWJjZA==', buffer);
+ for (let i = 0; i < 4; i++) {
+ assert.strictEqual(buffer.getInt8(i), 97 + i);
+ }
+
+ tr.b.Base64.DecodeToTypedArray('YWJjZGVm', buffer);
+ for (let i = 0; i < 4; i++) {
+ assert.strictEqual(buffer.getInt8(i), 97 + i);
+ }
+ });
+
+ test('DecodeLengthReturn', function() {
+ const buffer = new DataView(new ArrayBuffer(256));
+ let len = tr.b.Base64.DecodeToTypedArray(btoa('h'), buffer);
+ assert.strictEqual(len, 1);
+ len = tr.b.Base64.DecodeToTypedArray(btoa('he'), buffer);
+ assert.strictEqual(len, 2);
+ len = tr.b.Base64.DecodeToTypedArray(btoa('hel'), buffer);
+ assert.strictEqual(len, 3);
+ len = tr.b.Base64.DecodeToTypedArray(btoa('hell'), buffer);
+ assert.strictEqual(len, 4);
+ len = tr.b.Base64.DecodeToTypedArray(btoa('hello'), buffer);
+ assert.strictEqual(len, 5);
+ len = tr.b.Base64.DecodeToTypedArray(btoa('hello!'), buffer);
+ assert.strictEqual(len, 6);
+ });
+
+ test('Base64.atob', function() {
+ const output = tr.b.Base64.atob('aGVsbG8gd29ybGQ=');
+ assert.strictEqual(output, 'hello world');
+ });
+
+ test('Base64.btoa', function() {
+ const output = tr.b.Base64.btoa('hello world');
+ assert.strictEqual(output, 'aGVsbG8gd29ybGQ=');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/category_util.html b/chromium/third_party/catapult/tracing/tracing/base/category_util.html
new file mode 100644
index 00000000000..e10ea4f4b8d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/category_util.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Helper code for working with tracing categories.
+ *
+ */
+tr.exportTo('tr.b', function() {
+ // Cached values for getCategoryParts.
+ const categoryPartsFor = {};
+
+ /**
+ * Categories are stored in comma-separated form, e.g: 'a,b' meaning
+ * that the event is part of the a and b category.
+ *
+ * This function returns the category split by string, caching the
+ * array for performance.
+ *
+ * Do not mutate the returned array!!!!
+ */
+ function getCategoryParts(category) {
+ let parts = categoryPartsFor[category];
+ if (parts !== undefined) return parts;
+ parts = category.split(',');
+ categoryPartsFor[category] = parts;
+ return parts;
+ }
+
+ return {
+ getCategoryParts,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/color.html b/chromium/third_party/catapult/tracing/tracing/base/color.html
new file mode 100644
index 00000000000..0c2fd52f1b5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/color.html
@@ -0,0 +1,260 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ function clamp01(value) {
+ return Math.max(0, Math.min(1, value));
+ }
+
+ function Color(opt_r, opt_g, opt_b, opt_a) {
+ this.r = Math.floor(opt_r) || 0;
+ this.g = Math.floor(opt_g) || 0;
+ this.b = Math.floor(opt_b) || 0;
+ this.a = opt_a;
+ }
+
+ Color.fromString = function(str) {
+ let tmp;
+ let values;
+ if (str.substr(0, 4) === 'rgb(') {
+ tmp = str.substr(4, str.length - 5);
+ values = tmp.split(',').map(function(v) {
+ return v.replace(/^\s+/, '', 'g');
+ });
+ if (values.length !== 3) {
+ throw new Error('Malformatted rgb-expression');
+ }
+ return new Color(
+ parseInt(values[0]),
+ parseInt(values[1]),
+ parseInt(values[2]));
+ }
+ if (str.substr(0, 5) === 'rgba(') {
+ tmp = str.substr(5, str.length - 6);
+ values = tmp.split(',').map(function(v) {
+ return v.replace(/^\s+/, '', 'g');
+ });
+ if (values.length !== 4) {
+ throw new Error('Malformatted rgb-expression');
+ }
+ return new Color(
+ parseInt(values[0]),
+ parseInt(values[1]),
+ parseInt(values[2]),
+ parseFloat(values[3]));
+ }
+ if (str[0] === '#' && str.length === 7) {
+ return new Color(
+ parseInt(str.substr(1, 2), 16),
+ parseInt(str.substr(3, 2), 16),
+ parseInt(str.substr(5, 2), 16));
+ }
+ throw new Error('Unrecognized string format.');
+ };
+
+ Color.lerp = function(a, b, percent) {
+ if (a.a !== undefined && b.a !== undefined) {
+ return Color.lerpRGBA(a, b, percent);
+ }
+ return Color.lerpRGB(a, b, percent);
+ };
+
+ Color.lerpRGB = function(a, b, percent) {
+ return new Color(
+ ((b.r - a.r) * percent) + a.r,
+ ((b.g - a.g) * percent) + a.g,
+ ((b.b - a.b) * percent) + a.b);
+ };
+
+ Color.lerpRGBA = function(a, b, percent) {
+ return new Color(
+ ((b.r - a.r) * percent) + a.r,
+ ((b.g - a.g) * percent) + a.g,
+ ((b.b - a.b) * percent) + a.b,
+ ((b.a - a.a) * percent) + a.a);
+ };
+
+ Color.fromDict = function(dict) {
+ return new Color(dict.r, dict.g, dict.b, dict.a);
+ };
+
+ /**
+ * Converts an HSL triplet with alpha to an RGB color.
+ * |h| Hue value in [0, 1].
+ * |s| Saturation value in [0, 1].
+ * |l| Lightness in [0, 1].
+ * |a| Alpha in [0, 1]
+ */
+ Color.fromHSLExplicit = function(h, s, l, a) {
+ let r;
+ let g;
+ let b;
+ function hue2rgb(p, q, t) {
+ if (t < 0) t += 1;
+ if (t > 1) t -= 1;
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
+ if (t < 1 / 2) return q;
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
+ return p;
+ }
+
+ if (s === 0) {
+ r = g = b = l;
+ } else {
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ const p = 2 * l - q;
+ r = hue2rgb(p, q, h + 1 / 3);
+ g = hue2rgb(p, q, h);
+ b = hue2rgb(p, q, h - 1 / 3);
+ }
+
+ return new Color(Math.floor(r * 255),
+ Math.floor(g * 255),
+ Math.floor(b * 255), a);
+ };
+
+ Color.fromHSL = function(hsl) {
+ return Color.fromHSLExplicit(hsl.h, hsl.s, hsl.l, hsl.a);
+ };
+
+ Color.prototype = {
+ clone() {
+ const c = new Color();
+ c.r = this.r;
+ c.g = this.g;
+ c.b = this.b;
+ c.a = this.a;
+ return c;
+ },
+
+ blendOver(bgColor) {
+ const oneMinusThisAlpha = 1 - this.a;
+ const outA = this.a + bgColor.a * oneMinusThisAlpha;
+ const bgBlend = (bgColor.a * oneMinusThisAlpha) / bgColor.a;
+ return new Color(
+ this.r * this.a + bgColor.r * bgBlend,
+ this.g * this.a + bgColor.g * bgBlend,
+ this.b * this.a + bgColor.b * bgBlend,
+ outA);
+ },
+
+ brighten(opt_k) {
+ const k = opt_k || 0.45;
+
+ return new Color(
+ Math.min(255, this.r + Math.floor(this.r * k)),
+ Math.min(255, this.g + Math.floor(this.g * k)),
+ Math.min(255, this.b + Math.floor(this.b * k)),
+ this.a);
+ },
+
+ lighten(k, opt_maxL) {
+ const maxL = opt_maxL !== undefined ? opt_maxL : 1.0;
+ const hsl = this.toHSL();
+ hsl.l = Math.min(hsl.l + k, maxL);
+ return Color.fromHSL(hsl);
+ },
+
+ darken(opt_k) {
+ let k;
+ if (opt_k !== undefined) {
+ k = opt_k;
+ } else {
+ k = 0.45;
+ }
+
+ return new Color(
+ Math.min(255, this.r - Math.floor(this.r * k)),
+ Math.min(255, this.g - Math.floor(this.g * k)),
+ Math.min(255, this.b - Math.floor(this.b * k)),
+ this.a);
+ },
+
+ desaturate(opt_desaturateFactor) {
+ let desaturateFactor;
+ if (opt_desaturateFactor !== undefined) {
+ desaturateFactor = opt_desaturateFactor;
+ } else {
+ desaturateFactor = 1;
+ }
+
+ const hsl = this.toHSL();
+ hsl.s = clamp01(hsl.s * (1 - desaturateFactor));
+ return Color.fromHSL(hsl);
+ },
+
+ withAlpha(a) {
+ return new Color(this.r, this.g, this.b, a);
+ },
+
+ toString() {
+ if (this.a !== undefined) {
+ return 'rgba(' +
+ this.r + ',' + this.g + ',' +
+ this.b + ',' + this.a + ')';
+ }
+ return 'rgb(' + this.r + ',' + this.g + ',' + this.b + ')';
+ },
+
+ /**
+ * Returns a dict {h, s, l, a} with:
+ * |h| Hue value in [0, 1].
+ * |s| Saturation value in [0, 1].
+ * |l| Lightness in [0, 1].
+ * |a| Alpha in [0, 1]
+ */
+ toHSL() {
+ const r = this.r / 255;
+ const g = this.g / 255;
+ const b = this.b / 255;
+
+ const max = Math.max(r, g, b);
+ const min = Math.min(r, g, b);
+
+ let h;
+ let s;
+ const l = (max + min) / 2;
+ if (min === max) {
+ h = 0;
+ s = 0;
+ } else {
+ const delta = max - min;
+ if (l > 0.5) {
+ s = delta / (2 - max - min);
+ } else {
+ s = delta / (max + min);
+ }
+
+ if (r === max) {
+ h = (g - b) / delta;
+ if (g < b) h += 6;
+ } else if (g === max) {
+ h = 2 + ((b - r) / delta);
+ } else {
+ h = 4 + ((r - g) / delta);
+ }
+ h /= 6;
+ }
+
+ return {h, s, l, a: this.a};
+ },
+
+ toStringWithAlphaOverride(alpha) {
+ return 'rgba(' +
+ this.r + ',' + this.g + ',' +
+ this.b + ',' + alpha + ')';
+ }
+ };
+
+ return {
+ Color,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/color_scheme.html b/chromium/third_party/catapult/tracing/tracing/base/color_scheme.html
new file mode 100644
index 00000000000..fbd22506647
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/color_scheme.html
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/color.html">
+<link rel="import" href="/tracing/base/sinebow_color_generator.html">
+<link rel="import" href="/tracing/base/utils.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides color scheme related functions.
+ */
+tr.exportTo('tr.b', function() {
+ // Basic constants...
+ const numGeneralPurposeColorIds = 23;
+ const generalPurposeColors = new Array(numGeneralPurposeColorIds);
+ const sinebowAlpha = 1.0;
+ const sinebowBrightness = 1.5;
+ const sinebowColorGenerator =
+ new tr.b.SinebowColorGenerator(sinebowAlpha, sinebowBrightness);
+ for (let i = 0; i < numGeneralPurposeColorIds; i++) {
+ generalPurposeColors[i] = sinebowColorGenerator.nextColor();
+ }
+
+ const reservedColorsByName = {
+ thread_state_uninterruptible: new tr.b.Color(182, 125, 143),
+ thread_state_iowait: new tr.b.Color(255, 140, 0),
+ thread_state_running: new tr.b.Color(126, 200, 148),
+ thread_state_runnable: new tr.b.Color(133, 160, 210),
+ thread_state_sleeping: new tr.b.Color(240, 240, 240),
+ thread_state_unknown: new tr.b.Color(199, 155, 125),
+
+ background_memory_dump: new tr.b.Color(0, 180, 180),
+ light_memory_dump: new tr.b.Color(0, 0, 180),
+ detailed_memory_dump: new tr.b.Color(180, 0, 180),
+
+ vsync_highlight_color: new tr.b.Color(0, 0, 255),
+ generic_work: new tr.b.Color(125, 125, 125),
+
+ good: new tr.b.Color(0, 125, 0),
+ bad: new tr.b.Color(180, 125, 0),
+ terrible: new tr.b.Color(180, 0, 0),
+
+ black: new tr.b.Color(0, 0, 0),
+ grey: new tr.b.Color(221, 221, 221),
+ white: new tr.b.Color(255, 255, 255),
+ yellow: new tr.b.Color(255, 255, 0),
+ olive: new tr.b.Color(100, 100, 0),
+
+ rail_response: new tr.b.Color(67, 135, 253),
+ rail_animation: new tr.b.Color(244, 74, 63),
+ rail_idle: new tr.b.Color(238, 142, 0),
+ rail_load: new tr.b.Color(13, 168, 97),
+ startup: new tr.b.Color(230, 230, 0),
+
+ heap_dump_stack_frame: new tr.b.Color(128, 128, 128),
+ heap_dump_object_type: new tr.b.Color(0, 0, 255),
+ heap_dump_child_node_arrow: new tr.b.Color(204, 102, 0),
+
+ cq_build_running: new tr.b.Color(255, 255, 119),
+ cq_build_passed: new tr.b.Color(153, 238, 102),
+ cq_build_failed: new tr.b.Color(238, 136, 136),
+ cq_build_abandoned: new tr.b.Color(187, 187, 187),
+
+ cq_build_attempt_runnig: new tr.b.Color(222, 222, 75),
+ cq_build_attempt_passed: new tr.b.Color(103, 218, 35),
+ cq_build_attempt_failed: new tr.b.Color(197, 81, 81)
+ };
+
+ // Some constants we'll need for later lookups.
+ const numReservedColorIds = Object.keys(reservedColorsByName).length;
+ const numColorsPerVariant = numGeneralPurposeColorIds + numReservedColorIds;
+
+ function ColorScheme() {
+ }
+
+ /*
+ * A flat array of tr.b.Color values of the palette, and their variants.
+ *
+ * This array is made up of a set of base colors, repeated N times to form
+ * a set of variants on that base color.
+ *
+ * Within the base colors, there are "general purpose" colors,
+ * which can be used for random color selection, and
+ * reserved colors, which are used when specific colors
+ * need to be used, e.g. where red is desired.
+ *
+ * The variants are automatically generated from the base colors. The 0th
+ * variant is the default apeparance of the color, and the varaiants are
+ * mutations of that color, e.g. several brightening levels and desaturations.
+ *
+ * For example, a very simple version of this array looks like the following:
+ * 0: Generic Color 0
+ * 1: Generic Color 1
+ * 2: Named Color 'foo'
+ * 3: Brightened Generic Color 0
+ * 4: Brightened Generic Color 1
+ * 5: Brightened Named Color 'foo'
+ */
+ const paletteBase = [];
+ paletteBase.push.apply(paletteBase, generalPurposeColors);
+ paletteBase.push.apply(paletteBase, Object.values(reservedColorsByName));
+ ColorScheme.colors = [];
+ ColorScheme.properties = {};
+ ColorScheme.properties = {
+ numColorsPerVariant,
+ };
+
+ function pushVariant(func) {
+ const variantColors = paletteBase.map(func);
+ ColorScheme.colors.push.apply(ColorScheme.colors, variantColors);
+ }
+
+ // Basic colors.
+ pushVariant(function(c) { return c; });
+
+ // Brightened variants.
+ ColorScheme.properties.brightenedOffsets = [];
+ ColorScheme.properties.brightenedOffsets.push(ColorScheme.colors.length);
+ pushVariant(function(c) {
+ return c.lighten(0.3, 0.8);
+ });
+
+ ColorScheme.properties.brightenedOffsets.push(ColorScheme.colors.length);
+ pushVariant(function(c) {
+ return c.lighten(0.48, 0.85);
+ });
+
+ ColorScheme.properties.brightenedOffsets.push(ColorScheme.colors.length);
+ pushVariant(function(c) {
+ return c.lighten(0.65, 0.9);
+ });
+
+
+ // Desaturated variants.
+ ColorScheme.properties.dimmedOffsets = [];
+ ColorScheme.properties.dimmedOffsets.push(ColorScheme.colors.length);
+ pushVariant(function(c) {
+ return c.desaturate();
+ });
+ ColorScheme.properties.dimmedOffsets.push(ColorScheme.colors.length);
+ pushVariant(function(c) {
+ return c.desaturate(0.5);
+ });
+ ColorScheme.properties.dimmedOffsets.push(ColorScheme.colors.length);
+ pushVariant(function(c) {
+ return c.desaturate(0.3);
+ });
+
+ /**
+ * A toString'd representation of ColorScheme.colors.
+ */
+ ColorScheme.colorsAsStrings = ColorScheme.colors.map(function(c) {
+ return c.toString();
+ });
+
+ // Build reservedColorNameToIdMap.
+ const reservedColorNameToIdMap = (function() {
+ const m = new Map();
+ let i = generalPurposeColors.length;
+ for (const key of Object.keys(reservedColorsByName)) {
+ m.set(key, i++);
+ }
+ return m;
+ })();
+
+ /**
+ * @param {String} name The color name.
+ * @return {Number} The color ID for the given color name.
+ */
+ ColorScheme.getColorIdForReservedName = function(name) {
+ const id = reservedColorNameToIdMap.get(name);
+ if (id === undefined) {
+ throw new Error('Unrecognized color ' + name);
+ }
+ return id;
+ };
+
+ ColorScheme.getColorForReservedNameAsString = function(reservedName) {
+ const id = ColorScheme.getColorIdForReservedName(reservedName);
+ return ColorScheme.colorsAsStrings[id];
+ };
+
+ /**
+ * Computes a simplistic hashcode of the provide name. Used to chose colors
+ * for slices.
+ * @param {string} name The string to hash.
+ */
+ ColorScheme.getStringHash = function(name) {
+ let hash = 0;
+ for (let i = 0; i < name.length; ++i) {
+ hash = (hash + 37 * hash + 11 * name.charCodeAt(i)) % 0xFFFFFFFF;
+ }
+ return hash;
+ };
+
+ // Previously computed string color IDs. They are based on a stable hash, so
+ // it is safe to save them throughout the program time.
+ const stringColorIdCache = new Map();
+
+ /**
+ * @return {Number} A color ID that is stably associated to the provided via
+ * the getStringHash method. The color ID will be chosen from the general
+ * purpose ID space only, e.g. no reserved ID will be used.
+ */
+ ColorScheme.getColorIdForGeneralPurposeString = function(string) {
+ if (stringColorIdCache.get(string) === undefined) {
+ const hash = ColorScheme.getStringHash(string);
+ stringColorIdCache.set(string, hash % numGeneralPurposeColorIds);
+ }
+ return stringColorIdCache.get(string);
+ };
+
+ /**
+ * @return {Number} A color id generated consistently from a |colorId| and
+ * number |n|.
+ */
+ ColorScheme.getAnotherColorId = function(colorId, n) {
+ return (colorId + n) % numColorsPerVariant;
+ };
+
+ /**
+ * @return {Number} A color ID that the |offset| variant of |colorId|.
+ */
+ ColorScheme.getVariantColorId = function(colorId, offset) {
+ return colorId + offset;
+ };
+
+ return {
+ ColorScheme,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/color_scheme_test.html b/chromium/third_party/catapult/tracing/tracing/base/color_scheme_test.html
new file mode 100644
index 00000000000..7c418671e3c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/color_scheme_test.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ function isValidColorId(colorId) {
+ return typeof(colorId) === 'number' &&
+ colorId >= 0 &&
+ colorId <= 200;
+ }
+
+ test('getColorIdForReservedName', function() {
+ assert.isTrue(isValidColorId(
+ ColorScheme.getColorIdForReservedName('black')));
+ assert.throws(ColorScheme.getColorIdForReservedName.bind(
+ undefined, 'NOT_A_RESERVED_NAME'));
+ assert.throws(ColorScheme.getColorIdForReservedName.bind(
+ undefined, 'constructor'));
+ });
+
+ test('getColorForReservedNameAsString', function() {
+ assert.strictEqual('rgb(0,0,0)',
+ ColorScheme.getColorForReservedNameAsString('black'));
+ assert.throws(ColorScheme.getColorForReservedNameAsString.bind(
+ undefined, 'NOT_A_RESERVED_NAME'));
+ assert.throws(ColorScheme.getColorForReservedNameAsString.bind(
+ undefined, 'constructor'));
+ });
+
+ test('getColorIdForGeneralPurposeString', function() {
+ assert.isTrue(isValidColorId(
+ ColorScheme.getColorIdForGeneralPurposeString('black')));
+ assert.isTrue(isValidColorId(
+ ColorScheme.getColorIdForGeneralPurposeString('NOT_A_RESERVED_NAME')));
+ assert.isTrue(isValidColorId(
+ ColorScheme.getColorIdForGeneralPurposeString('constructor')));
+ });
+
+ test('getAnotherColorId', function() {
+ const colorId = ColorScheme.getColorIdForGeneralPurposeString('black');
+ assert.isTrue(isValidColorId(
+ ColorScheme.getAnotherColorId(colorId, 300)));
+ });
+
+ test('getVariantColorId', function() {
+ const colorId = ColorScheme.getColorIdForGeneralPurposeString('black');
+ const offset = ColorScheme.properties.brightenedOffsets[0];
+ assert.isTrue(isValidColorId(
+ ColorScheme.getVariantColorId(colorId, offset)));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/color_test.html b/chromium/third_party/catapult/tracing/tracing/base/color_test.html
new file mode 100644
index 00000000000..f92ed6977a3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/color_test.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/color.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('fromRGB', function() {
+ const c = tr.b.Color.fromString('rgb(1, 2, 3)');
+ assert.strictEqual(c.r, 1);
+ assert.strictEqual(c.g, 2);
+ assert.strictEqual(c.b, 3);
+ assert.isUndefined(c.a);
+ });
+
+ test('fromRGBA', function() {
+ const c = tr.b.Color.fromString('rgba(1, 2, 3, 0.5)');
+ assert.strictEqual(c.r, 1);
+ assert.strictEqual(c.g, 2);
+ assert.strictEqual(c.b, 3);
+ assert.strictEqual(c.a, 0.5);
+ });
+
+ test('fromHex', function() {
+ const c = tr.b.Color.fromString('#010203');
+ assert.strictEqual(c.r, 1);
+ assert.strictEqual(c.g, 2);
+ assert.strictEqual(c.b, 3);
+ assert.isUndefined(c.a);
+ });
+
+ test('toStringRGB', function() {
+ const c = new tr.b.Color(1, 2, 3);
+ assert.strictEqual(c.toString(), 'rgb(1,2,3)');
+ });
+
+ test('toStringRGBA', function() {
+ const c = new tr.b.Color(1, 2, 3, 0.5);
+ assert.strictEqual(c.toString(), 'rgba(1,2,3,0.5)');
+ });
+
+ test('lerpRGB', function() {
+ const a = new tr.b.Color(0, 127, 191);
+ const b = new tr.b.Color(255, 255, 255);
+ const x = tr.b.Color.lerpRGB(a, b, 0.25);
+ assert.strictEqual(x.r, 63);
+ assert.strictEqual(x.g, 159);
+ assert.strictEqual(x.b, 207);
+ });
+
+ test('lerpRGBA', function() {
+ const a = new tr.b.Color(0, 127, 191, 0.5);
+ const b = new tr.b.Color(255, 255, 255, 1);
+ const x = tr.b.Color.lerpRGBA(a, b, 0.25);
+ assert.strictEqual(x.r, 63);
+ assert.strictEqual(x.g, 159);
+ assert.strictEqual(x.b, 207);
+ assert.strictEqual(x.a, 0.625);
+ });
+
+ test('blendRGBA', function() {
+ const red = new tr.b.Color(255, 0, 0, 0.5);
+ const white = new tr.b.Color(255, 255, 255, 1);
+ const x = red.blendOver(white);
+ assert.strictEqual(x.r, 255);
+ assert.strictEqual(x.g, 127);
+ assert.strictEqual(x.b, 127);
+ assert.strictEqual(x.a, 1);
+ });
+
+ test('fromHSL', function() {
+ const reddish = tr.b.Color.fromHSLExplicit(.994, 0.644, .484, 0.8);
+ assert.strictEqual(reddish.r, 202);
+ assert.strictEqual(reddish.g, 43);
+ assert.strictEqual(reddish.b, 49);
+ assert.strictEqual(reddish.a, 0.8);
+
+ const gray = tr.b.Color.fromHSLExplicit(0, 0, .50, 1.0);
+ assert.strictEqual(gray.r, 127);
+ assert.strictEqual(gray.g, 127);
+ assert.strictEqual(gray.b, 127);
+ assert.strictEqual(gray.a, 1.0);
+ });
+
+ test('toHSL', function() {
+ const reddish = new tr.b.Color(203, 44, 49, 0.8).toHSL();
+ assert.closeTo(reddish.h, .994, 0.01);
+ assert.closeTo(reddish.s, 0.644, 0.01);
+ assert.closeTo(reddish.l, 0.484, 0.01);
+ assert.strictEqual(reddish.a, 0.8);
+
+ const gray = new tr.b.Color(128, 128, 128, 1.0).toHSL();
+ assert.strictEqual(gray.h, 0);
+ assert.strictEqual(gray.s, 0);
+ assert.closeTo(gray.l, .50, 0.01);
+ assert.strictEqual(gray.a, 1.0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/event.html b/chromium/third_party/catapult/tracing/tracing/base/event.html
new file mode 100644
index 00000000000..00e543a21fb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/event.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event_target.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ let Event;
+ if (tr.isHeadless) {
+ /**
+ * Creates a new event to be used with tr.b.EventTarget or DOM EventTarget
+ * objects.
+ * @param {string} type The name of the event.
+ * @param {boolean=} opt_bubbles Whether the event bubbles.
+ * Default is false.
+ * @param {boolean=} opt_preventable Whether the default action of the event
+ * can be prevented.
+ * @constructor
+ * @extends {Event}
+ */
+ function HeadlessEvent(type, opt_bubbles, opt_preventable) {
+ this.type = type;
+ this.bubbles = (opt_bubbles !== undefined ?
+ !!opt_bubbles : false);
+ this.cancelable = (opt_preventable !== undefined ?
+ !!opt_preventable : false);
+
+ this.defaultPrevented = false;
+ this.cancelBubble = false;
+ }
+
+ HeadlessEvent.prototype = {
+ preventDefault() {
+ this.defaultPrevented = true;
+ },
+
+ stopPropagation() {
+ this.cancelBubble = true;
+ }
+ };
+ Event = HeadlessEvent;
+ } else {
+ /**
+ * Creates a new event to be used with tr.b.EventTarget or DOM EventTarget
+ * objects.
+ * @param {string} type The name of the event.
+ * @param {boolean=} opt_bubbles Whether the event bubbles.
+ * Default is false.
+ * @param {boolean=} opt_preventable Whether the default action of the event
+ * can be prevented.
+ * @constructor
+ * @extends {Event}
+ */
+ function TrEvent(type, opt_bubbles, opt_preventable) {
+ const e = tr.doc.createEvent('Event');
+ e.initEvent(type, !!opt_bubbles, !!opt_preventable);
+ e.__proto__ = global.Event.prototype;
+ return e;
+ }
+
+ TrEvent.prototype = {
+ __proto__: global.Event.prototype
+ };
+ Event = TrEvent;
+ }
+
+ /**
+ * Dispatches a simple event on an event target.
+ * @param {!EventTarget} target The event target to dispatch the event on.
+ * @param {string} type The type of the event.
+ * @param {boolean=} opt_bubbles Whether the event bubbles or not.
+ * @param {boolean=} opt_cancelable Whether the default action of the event
+ * can be prevented.
+ * @param {!Object=} opt_fields
+ *
+ * @return {boolean} If any of the listeners called {@code preventDefault}
+ * during the dispatch this will return false.
+ */
+ function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable,
+ opt_fields) {
+ const e = new tr.b.Event(type, opt_bubbles, opt_cancelable);
+ Object.assign(e, opt_fields);
+ return target.dispatchEvent(e);
+ }
+
+ async function dispatchSimpleEventAsync(target, type, opt_fields) {
+ const e = new tr.b.Event(type, false, false);
+ Object.assign(e, opt_fields);
+ return await target.dispatchAsync(e);
+ }
+
+ return {
+ Event,
+ dispatchSimpleEvent,
+ dispatchSimpleEventAsync,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/event_target.html b/chromium/third_party/catapult/tracing/tracing/base/event_target.html
new file mode 100644
index 00000000000..c3a3025d0fc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/event_target.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This contains an implementation of the EventTarget interface
+ * as defined by DOM Level 2 Events.
+ */
+tr.exportTo('tr.b', function() {
+ /**
+ * Creates a new EventTarget. This class implements the DOM level 2
+ * EventTarget interface and can be used wherever those are used.
+ * @constructor
+ */
+ function EventTarget() {
+ }
+ EventTarget.decorate = function(target) {
+ for (const k in EventTarget.prototype) {
+ if (k === 'decorate') continue;
+ const v = EventTarget.prototype[k];
+ if (typeof v !== 'function') continue;
+ target[k] = v;
+ }
+ };
+
+ EventTarget.prototype = {
+
+ /**
+ * Adds an event listener to the target.
+ * @param {string} type The name of the event.
+ * @param {!Function|{handleEvent:Function}} handler The handler for the
+ * event. This is called when the event is dispatched.
+ */
+ addEventListener(type, handler) {
+ if (!this.listeners_) {
+ this.listeners_ = Object.create(null);
+ }
+ if (!(type in this.listeners_)) {
+ this.listeners_[type] = [handler];
+ } else {
+ const handlers = this.listeners_[type];
+ if (handlers.indexOf(handler) < 0) {
+ handlers.push(handler);
+ }
+ }
+ },
+
+ /**
+ * Removes an event listener from the target.
+ * @param {string} type The name of the event.
+ * @param {!Function|{handleEvent:Function}} handler The handler for the
+ * event.
+ */
+ removeEventListener(type, handler) {
+ if (!this.listeners_) return;
+ if (type in this.listeners_) {
+ const handlers = this.listeners_[type];
+ const index = handlers.indexOf(handler);
+ if (index >= 0) {
+ // Clean up if this was the last listener.
+ if (handlers.length === 1) {
+ delete this.listeners_[type];
+ } else {
+ handlers.splice(index, 1);
+ }
+ }
+ }
+ },
+
+ /**
+ * Dispatches an event and calls all the listeners that are listening to
+ * the type of the event.
+ * @param {!cr.event.Event} event The event to dispatch.
+ * @return {boolean} Whether the default action was prevented. If someone
+ * calls preventDefault on the event object then this returns false.
+ */
+ dispatchEvent(event) {
+ if (!this.listeners_) return true;
+
+ // Since we are using DOM Event objects we need to override some of the
+ // properties and methods so that we can emulate this correctly.
+ event.__defineGetter__('target', () => this);
+ const realPreventDefault = event.preventDefault;
+ event.preventDefault = function() {
+ realPreventDefault.call(this);
+ this.rawReturnValue = false;
+ };
+
+ const type = event.type;
+ let prevented = 0;
+ if (type in this.listeners_) {
+ // Clone to prevent removal during dispatch
+ const handlers = this.listeners_[type].concat();
+ for (let i = 0, handler; handler = handlers[i]; i++) {
+ if (handler.handleEvent) {
+ prevented |= handler.handleEvent.call(handler, event) === false;
+ } else {
+ prevented |= handler.call(this, event) === false;
+ }
+ }
+ }
+
+ return !prevented && event.rawReturnValue;
+ },
+
+ async dispatchAsync(event) {
+ if (!this.listeners_) return true;
+
+ const listeners = this.listeners_[event.type];
+ if (listeners === undefined) return;
+
+ // Clone to prevent removal during dispatch
+ await Promise.all(listeners.slice().map(listener => {
+ if (listener.handleEvent) {
+ return listener.handleEvent.call(listener, event);
+ }
+ return listener.call(this, event);
+ }));
+ },
+
+ hasEventListener(type) {
+ return (this.listeners_ !== undefined &&
+ this.listeners_[type] !== undefined);
+ }
+ };
+
+ return {
+ EventTarget,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/event_target_test.html b/chromium/third_party/catapult/tracing/tracing/base/event_target_test.html
new file mode 100644
index 00000000000..149f8d35495
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/event_target_test.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/event_target.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('sync', function() {
+ let listenerCallCount = 0;
+ function listener() { listenerCallCount++; }
+
+ const div = new tr.b.EventTarget();
+ tr.b.EventTarget.decorate(div);
+
+ assert.isFalse(div.hasEventListener('foo'));
+
+ div.addEventListener('foo', listener);
+ assert.isTrue(div.hasEventListener('foo'));
+
+ tr.b.dispatchSimpleEvent(div, 'foo');
+ assert.strictEqual(listenerCallCount, 1);
+
+ div.removeEventListener('foo', listener);
+
+ tr.b.dispatchSimpleEvent(div, 'foo');
+ assert.strictEqual(listenerCallCount, 1);
+
+ assert.isFalse(div.hasEventListener('foo'));
+ });
+
+ test('async', function() {
+ let listenerCallCount = 0;
+ async function listener() {
+ listenerCallCount++;
+ await Promise.resolve();
+ }
+
+ const div = new tr.b.EventTarget();
+ tr.b.EventTarget.decorate(div);
+
+ assert.isFalse(div.hasEventListener('foo'));
+
+ div.addEventListener('foo', listener);
+ assert.isTrue(div.hasEventListener('foo'));
+
+ tr.b.dispatchSimpleEventAsync(div, 'foo');
+ assert.strictEqual(listenerCallCount, 1);
+
+ div.removeEventListener('foo', listener);
+
+ tr.b.dispatchSimpleEventAsync(div, 'foo');
+ assert.strictEqual(listenerCallCount, 1);
+
+ assert.isFalse(div.hasEventListener('foo'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/extension_registry.html b/chromium/third_party/catapult/tracing/tracing/base/extension_registry.html
new file mode 100644
index 00000000000..754af87c715
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/extension_registry.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/extension_registry_base.html">
+<link rel="import" href="/tracing/base/extension_registry_basic.html">
+<link rel="import" href="/tracing/base/extension_registry_type_based.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Helper code for defining extension registries, which can be
+ * used to make a part of trace-viewer extensible.
+ *
+ * This file provides two basic types of extension registries:
+ * - Generic: register a type with metadata, query for those types based on
+ * a predicate
+ *
+ * - TypeName-based: register a type that handles some combination
+ * of tracing categories or typeNames, then query
+ * for it based on a category, typeName or both.
+ *
+ * When you register subtypes, you pass the constructor for the
+ * subtype, and any metadata you want associated with the subtype. Use metadata
+ * instead of stuffing fields onto the constructor. E.g.:
+ * registry.register(MySubclass, {titleWhenShownInTabStrip: 'MySub'})
+ *
+ * Some registries want a default object that is returned when a more precise
+ * subtype has not been registered. To provide one, set the defaultConstructor
+ * option on the registry options.
+ *
+ * TODO: Extension registry used to make reference to mandatoryBaseType but it
+ * was never enforced. We may want to add it back in the future in order to
+ * enforce the types that can be put into a given registry.
+ */
+tr.exportTo('tr.b', function() {
+ function decorateExtensionRegistry(registry, registryOptions) {
+ if (registry.register) {
+ throw new Error('Already has registry');
+ }
+
+ registryOptions.freeze();
+ if (registryOptions.mode === tr.b.BASIC_REGISTRY_MODE) {
+ tr.b._decorateBasicExtensionRegistry(registry, registryOptions);
+ } else if (registryOptions.mode === tr.b.TYPE_BASED_REGISTRY_MODE) {
+ tr.b._decorateTypeBasedExtensionRegistry(registry, registryOptions);
+ } else {
+ throw new Error('Unrecognized mode');
+ }
+
+ // Make it an event target.
+ if (registry.addEventListener === undefined) {
+ tr.b.EventTarget.decorate(registry);
+ }
+ }
+
+ return {
+ decorateExtensionRegistry,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/extension_registry_base.html b/chromium/third_party/catapult/tracing/tracing/base/extension_registry_base.html
new file mode 100644
index 00000000000..99f12f30f1e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/extension_registry_base.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ function RegisteredTypeInfo(constructor, metadata) {
+ this.constructor = constructor;
+ this.metadata = metadata;
+ }
+
+ const BASIC_REGISTRY_MODE = 'BASIC_REGISTRY_MODE';
+ const TYPE_BASED_REGISTRY_MODE = 'TYPE_BASED_REGISTRY_MODE';
+ const ALL_MODES = {BASIC_REGISTRY_MODE: true, TYPE_BASED_REGISTRY_MODE: true};
+
+ function ExtensionRegistryOptions(mode) {
+ if (mode === undefined) {
+ throw new Error('Mode is required');
+ }
+ if (!ALL_MODES[mode]) {
+ throw new Error('Not a mode.');
+ }
+
+ this.mode_ = mode;
+ this.defaultMetadata_ = {};
+ this.defaultConstructor_ = undefined;
+ this.defaultTypeInfo_ = undefined;
+ this.frozen_ = false;
+ }
+ ExtensionRegistryOptions.prototype = {
+ freeze() {
+ if (this.frozen_) {
+ throw new Error('Frozen');
+ }
+ this.frozen_ = true;
+ },
+
+ get mode() {
+ return this.mode_;
+ },
+
+ get defaultMetadata() {
+ return this.defaultMetadata_;
+ },
+
+ set defaultMetadata(defaultMetadata) {
+ if (this.frozen_) {
+ throw new Error('Frozen');
+ }
+ this.defaultMetadata_ = defaultMetadata;
+ this.defaultTypeInfo_ = undefined;
+ },
+
+ get defaultConstructor() {
+ return this.defaultConstructor_;
+ },
+
+ set defaultConstructor(defaultConstructor) {
+ if (this.frozen_) {
+ throw new Error('Frozen');
+ }
+ this.defaultConstructor_ = defaultConstructor;
+ this.defaultTypeInfo_ = undefined;
+ },
+
+ get defaultTypeInfo() {
+ if (this.defaultTypeInfo_ === undefined && this.defaultConstructor_) {
+ this.defaultTypeInfo_ = new RegisteredTypeInfo(
+ this.defaultConstructor,
+ this.defaultMetadata);
+ }
+ return this.defaultTypeInfo_;
+ },
+
+ validateConstructor(constructor) {
+ if (!this.mandatoryBaseClass) return;
+ let curProto = constructor.prototype.__proto__;
+ let ok = false;
+ while (curProto) {
+ if (curProto === this.mandatoryBaseClass.prototype) {
+ ok = true;
+ break;
+ }
+ curProto = curProto.__proto__;
+ }
+ if (!ok) {
+ throw new Error(constructor + 'must be subclass of ' + registry);
+ }
+ }
+ };
+
+ return {
+ BASIC_REGISTRY_MODE,
+ TYPE_BASED_REGISTRY_MODE,
+
+ ExtensionRegistryOptions,
+ RegisteredTypeInfo,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/extension_registry_basic.html b/chromium/third_party/catapult/tracing/tracing/base/extension_registry_basic.html
new file mode 100644
index 00000000000..f0351be38f8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/extension_registry_basic.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/extension_registry_base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ const RegisteredTypeInfo = tr.b.RegisteredTypeInfo;
+ const ExtensionRegistryOptions = tr.b.ExtensionRegistryOptions;
+
+ function decorateBasicExtensionRegistry(registry, extensionRegistryOptions) {
+ const savedStateStack = [];
+ registry.registeredTypeInfos_ = [];
+
+ registry.register = function(constructor,
+ opt_metadata) {
+ if (registry.findIndexOfRegisteredConstructor(
+ constructor) !== undefined) {
+ throw new Error('Handler already registered for ' + constructor);
+ }
+
+ extensionRegistryOptions.validateConstructor(constructor);
+
+ const metadata = {};
+ for (const k in extensionRegistryOptions.defaultMetadata) {
+ metadata[k] = extensionRegistryOptions.defaultMetadata[k];
+ }
+ if (opt_metadata) {
+ for (const k in opt_metadata) {
+ metadata[k] = opt_metadata[k];
+ }
+ }
+
+ const typeInfo = new RegisteredTypeInfo(
+ constructor,
+ metadata);
+
+ let e = new tr.b.Event('will-register');
+ e.typeInfo = typeInfo;
+ registry.dispatchEvent(e);
+
+ registry.registeredTypeInfos_.push(typeInfo);
+
+ e = new tr.b.Event('registry-changed');
+ registry.dispatchEvent(e);
+ };
+
+ registry.pushCleanStateBeforeTest = function() {
+ savedStateStack.push(registry.registeredTypeInfos_);
+ registry.registeredTypeInfos_ = [];
+
+ const e = new tr.b.Event('registry-changed');
+ registry.dispatchEvent(e);
+ };
+ registry.popCleanStateAfterTest = function() {
+ registry.registeredTypeInfos_ = savedStateStack[0];
+ savedStateStack.splice(0, 1);
+
+ const e = new tr.b.Event('registry-changed');
+ registry.dispatchEvent(e);
+ };
+
+ registry.findIndexOfRegisteredConstructor = function(constructor) {
+ for (let i = 0; i < registry.registeredTypeInfos_.length; i++) {
+ if (registry.registeredTypeInfos_[i].constructor === constructor) {
+ return i;
+ }
+ }
+ return undefined;
+ };
+
+ registry.unregister = function(constructor) {
+ const foundIndex = registry.findIndexOfRegisteredConstructor(constructor);
+ if (foundIndex === undefined) {
+ throw new Error(constructor + ' not registered');
+ }
+ registry.registeredTypeInfos_.splice(foundIndex, 1);
+
+ const e = new tr.b.Event('registry-changed');
+ registry.dispatchEvent(e);
+ };
+
+ registry.getAllRegisteredTypeInfos = function() {
+ return registry.registeredTypeInfos_;
+ };
+
+ registry.findTypeInfo = function(constructor) {
+ const foundIndex = this.findIndexOfRegisteredConstructor(constructor);
+ if (foundIndex !== undefined) {
+ return this.registeredTypeInfos_[foundIndex];
+ }
+ return undefined;
+ };
+
+ registry.findTypeInfoMatching = function(predicate, opt_this) {
+ opt_this = opt_this ? opt_this : undefined;
+ for (let i = 0; i < registry.registeredTypeInfos_.length; ++i) {
+ const typeInfo = registry.registeredTypeInfos_[i];
+ if (predicate.call(opt_this, typeInfo)) {
+ return typeInfo;
+ }
+ }
+ return extensionRegistryOptions.defaultTypeInfo;
+ };
+
+ registry.findTypeInfoWithName = function(name) {
+ if (typeof(name) !== 'string') {
+ throw new Error('Name is not a string.');
+ }
+ const typeInfo = registry.findTypeInfoMatching(function(ti) {
+ return ti.constructor.name === name;
+ });
+ if (typeInfo) return typeInfo;
+ return undefined;
+ };
+ }
+
+ return {
+ _decorateBasicExtensionRegistry: decorateBasicExtensionRegistry
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/extension_registry_test.html b/chromium/third_party/catapult/tracing/tracing/base/extension_registry_test.html
new file mode 100644
index 00000000000..27c64f300df
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/extension_registry_test.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('tberSimpleNamedRegistration', function() {
+ function DummyEvent() {
+ }
+ DummyEvent.prototype = {
+ };
+
+ function DummyEventSubclass() {
+ }
+ DummyEventSubclass.prototype = {
+ __proto__: DummyEvent.prototype
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(
+ tr.b.TYPE_BASED_REGISTRY_MODE);
+ options.mandatoryBaseClass = DummyEvent;
+ options.defaultConstructor = DummyEvent;
+ tr.b.decorateExtensionRegistry(
+ DummyEvent, options);
+
+ DummyEvent.register(DummyEventSubclass, {typeName: 'dummy-name'});
+ assert.strictEqual(DummyEvent, DummyEvent.getConstructor('cat', 'name'));
+ assert.strictEqual(
+ DummyEvent.getConstructor('dummy', 'dummy-name'), DummyEventSubclass);
+ DummyEvent.unregister(DummyEventSubclass);
+ assert.strictEqual(
+ DummyEvent, DummyEvent.getConstructor('dummy', 'dummy-name'));
+ });
+
+ test('tberSimpleCategoryRegistration', function() {
+ function DummyEvent() {
+ }
+ DummyEvent.prototype = {
+ };
+
+ function DummyEventSubclass() {
+ }
+ DummyEventSubclass.prototype = {
+ __proto__: DummyEvent.prototype
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(
+ tr.b.TYPE_BASED_REGISTRY_MODE);
+ options.mandatoryBaseClass = DummyEvent;
+ options.defaultConstructor = DummyEvent;
+ tr.b.decorateExtensionRegistry(
+ DummyEvent, options);
+
+ DummyEvent.register(
+ DummyEventSubclass,
+ {categoryParts: ['dummy']
+ });
+ assert.strictEqual(DummyEvent, DummyEvent.getConstructor('cat', 'name'));
+ assert.strictEqual(DummyEvent.getConstructor('dummy', 'dummy-name'),
+ DummyEventSubclass);
+ DummyEvent.unregister(DummyEventSubclass);
+ assert.strictEqual(
+ DummyEvent, DummyEvent.getConstructor('dummy', 'dummy-name'));
+ });
+
+ test('tberSimpleCompoundCategory', function() {
+ function DummyEvent() {
+ }
+ DummyEvent.prototype = {
+ };
+
+ function DummyEventSubclass() {
+ }
+ DummyEventSubclass.prototype = {
+ __proto__: DummyEvent.prototype
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(
+ tr.b.TYPE_BASED_REGISTRY_MODE);
+ options.mandatoryBaseClass = DummyEvent;
+ options.defaultConstructor = DummyEvent;
+ tr.b.decorateExtensionRegistry(
+ DummyEvent, options);
+
+ DummyEvent.register(
+ DummyEventSubclass,
+ {
+ categoryParts: ['dummy']
+ });
+ assert.strictEqual(DummyEvent, DummyEvent.getConstructor('cat', 'name'));
+ assert.strictEqual(DummyEventSubclass,
+ DummyEvent.getConstructor('dummy,something-else',
+ 'dummy-name'));
+ });
+
+ test('tberDefaultType', function() {
+ function DummyEvent() {
+ }
+ DummyEvent.prototype = {
+ };
+
+ function DummyEventSubclass() {
+ }
+ DummyEventSubclass.prototype = {
+ __proto__: DummyEvent.prototype
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(
+ tr.b.TYPE_BASED_REGISTRY_MODE);
+ options.mandatoryBaseClass = DummyEvent;
+ options.defaultConstructor = DummyEvent;
+ tr.b.decorateExtensionRegistry(
+ DummyEvent, options);
+
+ DummyEvent.register(
+ DummyEventSubclass,
+ {
+ categoryParts: ['dummy']
+ });
+ assert.strictEqual(DummyEvent, DummyEvent.getConstructor('cat', 'name'));
+ assert.strictEqual(DummyEventSubclass,
+ DummyEvent.getConstructor('dummy,something-else',
+ 'dummy-name'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/extension_registry_type_based.html b/chromium/third_party/catapult/tracing/tracing/base/extension_registry_type_based.html
new file mode 100644
index 00000000000..b9b30d2aa81
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/extension_registry_type_based.html
@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/category_util.html">
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/extension_registry_base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ const getCategoryParts = tr.b.getCategoryParts;
+
+ const RegisteredTypeInfo = tr.b.RegisteredTypeInfo;
+ const ExtensionRegistryOptions = tr.b.ExtensionRegistryOptions;
+
+
+ function decorateTypeBasedExtensionRegistry(registry,
+ extensionRegistryOptions) {
+ const savedStateStack = [];
+
+ registry.registeredTypeInfos_ = [];
+
+ registry.categoryPartToTypeInfoMap_ = new Map();
+ registry.typeNameToTypeInfoMap_ = new Map();
+
+ registry.register = function(constructor,
+ metadata) {
+ extensionRegistryOptions.validateConstructor(constructor);
+
+ const typeInfo = new RegisteredTypeInfo(
+ constructor,
+ metadata || extensionRegistryOptions.defaultMetadata);
+
+ typeInfo.typeNames = [];
+ typeInfo.categoryParts = [];
+ if (metadata && metadata.typeName) {
+ typeInfo.typeNames.push(metadata.typeName);
+ }
+ if (metadata && metadata.typeNames) {
+ typeInfo.typeNames.push.apply(
+ typeInfo.typeNames, metadata.typeNames);
+ }
+ if (metadata && metadata.categoryParts) {
+ typeInfo.categoryParts.push.apply(
+ typeInfo.categoryParts, metadata.categoryParts);
+ }
+
+ if (typeInfo.typeNames.length === 0 &&
+ typeInfo.categoryParts.length === 0) {
+ throw new Error('typeName or typeNames must be provided');
+ }
+
+ // Sanity checks...
+ typeInfo.typeNames.forEach(function(typeName) {
+ if (registry.typeNameToTypeInfoMap_.has(typeName)) {
+ throw new Error('typeName ' + typeName + ' already registered');
+ }
+ });
+ typeInfo.categoryParts.forEach(function(categoryPart) {
+ if (registry.categoryPartToTypeInfoMap_.has(categoryPart)) {
+ throw new Error('categoryPart ' + categoryPart +
+ ' already registered');
+ }
+ });
+
+ let e = new tr.b.Event('will-register');
+ e.typeInfo = typeInfo;
+ registry.dispatchEvent(e);
+
+ // Actual registration.
+ typeInfo.typeNames.forEach(function(typeName) {
+ registry.typeNameToTypeInfoMap_.set(typeName, typeInfo);
+ });
+ typeInfo.categoryParts.forEach(function(categoryPart) {
+ registry.categoryPartToTypeInfoMap_.set(categoryPart, typeInfo);
+ });
+ registry.registeredTypeInfos_.push(typeInfo);
+
+ e = new tr.b.Event('registry-changed');
+ registry.dispatchEvent(e);
+ };
+
+ registry.pushCleanStateBeforeTest = function() {
+ savedStateStack.push({
+ registeredTypeInfos: registry.registeredTypeInfos_,
+ typeNameToTypeInfoMap: registry.typeNameToTypeInfoMap_,
+ categoryPartToTypeInfoMap: registry.categoryPartToTypeInfoMap_
+ });
+ registry.registeredTypeInfos_ = [];
+ registry.typeNameToTypeInfoMap_ = new Map();
+ registry.categoryPartToTypeInfoMap_ = new Map();
+ const e = new tr.b.Event('registry-changed');
+ registry.dispatchEvent(e);
+ };
+
+ registry.popCleanStateAfterTest = function() {
+ const state = savedStateStack[0];
+ savedStateStack.splice(0, 1);
+
+ registry.registeredTypeInfos_ = state.registeredTypeInfos;
+ registry.typeNameToTypeInfoMap_ = state.typeNameToTypeInfoMap;
+ registry.categoryPartToTypeInfoMap_ = state.categoryPartToTypeInfoMap;
+ const e = new tr.b.Event('registry-changed');
+ registry.dispatchEvent(e);
+ };
+
+ registry.unregister = function(constructor) {
+ let typeInfoIndex = -1;
+ for (let i = 0; i < registry.registeredTypeInfos_.length; i++) {
+ if (registry.registeredTypeInfos_[i].constructor === constructor) {
+ typeInfoIndex = i;
+ break;
+ }
+ }
+ if (typeInfoIndex === -1) {
+ throw new Error(constructor + ' not registered');
+ }
+
+ const typeInfo = registry.registeredTypeInfos_[typeInfoIndex];
+ registry.registeredTypeInfos_.splice(typeInfoIndex, 1);
+ typeInfo.typeNames.forEach(function(typeName) {
+ registry.typeNameToTypeInfoMap_.delete(typeName);
+ });
+ typeInfo.categoryParts.forEach(function(categoryPart) {
+ registry.categoryPartToTypeInfoMap_.delete(categoryPart);
+ });
+ const e = new tr.b.Event('registry-changed');
+ registry.dispatchEvent(e);
+ };
+
+ registry.getTypeInfo = function(category, typeName) {
+ if (category) {
+ const categoryParts = getCategoryParts(category);
+ for (let i = 0; i < categoryParts.length; i++) {
+ const categoryPart = categoryParts[i];
+ const typeInfo = registry.categoryPartToTypeInfoMap_.get(
+ categoryPart);
+ if (typeInfo !== undefined) return typeInfo;
+ }
+ }
+ const typeInfo = registry.typeNameToTypeInfoMap_.get(typeName);
+ if (typeInfo !== undefined) return typeInfo;
+
+ return extensionRegistryOptions.defaultTypeInfo;
+ };
+
+ // TODO(nduca): Remove or rename.
+ registry.getConstructor = function(category, typeName) {
+ const typeInfo = registry.getTypeInfo(category, typeName);
+ if (typeInfo) return typeInfo.constructor;
+ return undefined;
+ };
+ }
+
+ return {
+ _decorateTypeBasedExtensionRegistry: decorateTypeBasedExtensionRegistry
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/fixed_color_scheme.html b/chromium/third_party/catapult/tracing/tracing/base/fixed_color_scheme.html
new file mode 100644
index 00000000000..a540db8fbb4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/fixed_color_scheme.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+<link rel="import" href="/tracing/base/sinebow_color_generator.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ class FixedColorScheme {
+ /**
+ * @param {!Map} namesToColors
+ * @constructor
+ */
+ constructor(namesToColors) {
+ this.namesToColors_ = namesToColors;
+ }
+
+ /**
+ * Create a color scheme where each name in names gets assigned a fixed
+ * color. This color is arbitrary but unique within the color scheme.
+ * @param {!Array<string>} names
+ * @return {tr.b.FixedColorScheme}
+ */
+ static fromNames(names) {
+ const namesToColors = new Map();
+ const generator = new tr.b.SinebowColorGenerator();
+ for (const name of names) {
+ namesToColors.set(name, generator.colorForKey(name));
+ }
+ return new FixedColorScheme(namesToColors);
+ }
+
+ /**
+ * Return color associated with |name|.
+ * @param {!string} name
+ * @return {tr.b.Color}
+ */
+ getColor(name) {
+ const color = this.namesToColors_.get(name);
+ if (color === undefined) throw new Error('Unknown color: ' + name);
+ return color;
+ }
+ }
+
+ const MemoryColumnColorScheme = new FixedColorScheme(new Map([
+ ['used_memory_column', new tr.b.Color(0, 0, 255)],
+ ['older_used_memory_column', new tr.b.Color(153, 204, 255)],
+ ['tracing_memory_column', new tr.b.Color(153, 153, 153)]
+ ]));
+
+ function FixedColorSchemeRegistry() {}
+ FixedColorSchemeRegistry.lookUp = function(name) {
+ const info = this.findTypeInfoMatching(info => info.metadata.name === name);
+ if (!info) return undefined;
+ return info.constructor();
+ };
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ tr.b.decorateExtensionRegistry(FixedColorSchemeRegistry, options);
+
+ return {
+ MemoryColumnColorScheme,
+ FixedColorScheme,
+ FixedColorSchemeRegistry,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/fixed_color_scheme_test.html b/chromium/third_party/catapult/tracing/tracing/base/fixed_color_scheme_test.html
new file mode 100644
index 00000000000..283de53d2d1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/fixed_color_scheme_test.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color.html">
+<link rel="import" href="/tracing/base/fixed_color_scheme.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function isColor(color) {
+ return color.toString().startsWith('rgb');
+ }
+
+ test('canSpecifyColors', function() {
+ const scheme = new tr.b.FixedColorScheme(new Map([
+ ['red', new tr.b.Color(255, 0, 0)],
+ ['green', new tr.b.Color(0, 255, 0)],
+ ['blue', new tr.b.Color(0, 0, 255)],
+ ]));
+ assert.strictEqual(scheme.getColor('red').toString(),
+ (new tr.b.Color(255, 0, 0)).toString());
+ assert.strictEqual(scheme.getColor('green').toString(),
+ (new tr.b.Color(0, 255, 0)).toString());
+ assert.strictEqual(scheme.getColor('blue').toString(),
+ (new tr.b.Color(0, 0, 255)).toString());
+ });
+
+ test('namesGetColors', function() {
+ const scheme = tr.b.FixedColorScheme.fromNames(['foo', 'bar', 'baz']);
+ assert.isTrue(isColor(scheme.getColor('foo')));
+ assert.isTrue(isColor(scheme.getColor('bar')));
+ assert.isTrue(isColor(scheme.getColor('baz')));
+ });
+
+ test('namesGetDifferentColors', function() {
+ const scheme = tr.b.FixedColorScheme.fromNames(['foo', 'bar', 'baz']);
+ assert.notEqual(scheme.getColor('foo'), scheme.getColor('bar'));
+ assert.notEqual(scheme.getColor('bar'), scheme.getColor('baz'));
+ assert.notEqual(scheme.getColor('baz'), scheme.getColor('foo'));
+ });
+
+ test('sameNamesGetSameColors', function() {
+ const scheme = tr.b.FixedColorScheme.fromNames(['foo', 'bar', 'baz']);
+ assert.strictEqual(scheme.getColor('foo'), scheme.getColor('foo'));
+ assert.strictEqual(scheme.getColor('bar'), scheme.getColor('bar'));
+ assert.strictEqual(scheme.getColor('baz'), scheme.getColor('baz'));
+ });
+
+ test('differentSchemesGiveTheSameColorsForTheSameNames', function() {
+ const a = tr.b.FixedColorScheme.fromNames(['foo', 'bar', 'baz']);
+ const b = tr.b.FixedColorScheme.fromNames(['foo', 'bar', 'baz']);
+ assert.strictEqual(
+ a.getColor('foo').toString(), b.getColor('foo').toString());
+ assert.strictEqual(
+ a.getColor('bar').toString(), b.getColor('bar').toString());
+ assert.strictEqual(
+ a.getColor('baz').toString(), b.getColor('baz').toString());
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/guid.html b/chromium/third_party/catapult/tracing/tracing/base/guid.html
new file mode 100644
index 00000000000..eb73e695aee
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/guid.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ let nextGUID = 1;
+
+ const UUID4_PATTERN = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
+
+ const GUID = {
+ /* Allocate an integer GUID.
+ *
+ * These GUIDs are not unique between loads, but are fast to generate, and
+ * consume very little memory.
+ *
+ * @return {number} globally unique id.
+ */
+ allocateSimple() {
+ return nextGUID++;
+ },
+
+ /* Return the last GUID allocated without allocating a new one.
+ *
+ * @return {number} last guid.
+ */
+ getLastSimpleGuid() {
+ return nextGUID - 1;
+ },
+
+ /* Generate a random string UUID.
+ *
+ * Version 4 random UUIDs are practically guaranteed to be unique between
+ * loads, so they can be serialized and compared with results from other
+ * loads. These are slower to generate and consume more memory than simple
+ * GUIDs.
+ *
+ * Background on using Math.random() for allocating identifiers:
+ * https://medium.com/@betable/tifu-by-using-math-random-f1c308c4fd9d#.n5b6vgrsh
+ * https://v8project.blogspot.com/2015/12/theres-mathrandom-and-then-theres.html
+ *
+ * @return {string} universally unique id.
+ */
+ allocateUUID4() {
+ return UUID4_PATTERN.replace(/[xy]/g, function(c) {
+ let r = parseInt(Math.random() * 16);
+ if (c === 'y') r = (r & 3) + 8;
+ return r.toString(16);
+ });
+ }
+ };
+
+ return {
+ GUID,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/headless_tests.html b/chromium/third_party/catapult/tracing/tracing/base/headless_tests.html
new file mode 100644
index 00000000000..5731e4ff155
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/headless_tests.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/unittest.html">
+<link rel="import" href="/tracing/base/unittest/test_runner.html">
+<link rel="import" href="/tracing/base/unittest/text_test_results.html">
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+tr.exportTo('tr.b.unittest', function() {
+ if (!tr.isHeadless) {
+ throw new Error('headless_tests.html only works in headless mode');
+ }
+ function quit(errCode) {
+ if (tr.isVinn) {
+ global.quit(errCode);
+ } else {
+ process.exit(errCode);
+ }
+ }
+
+ function printSpacer() {
+ console.log('\n\n------------------------------------------------------' +
+ '----------------');
+ }
+ function loadAndRunTests(suiteRelpathsToLoad) {
+ const results = new tr.b.unittest.TextTestResults();
+
+ const loader = new tr.b.unittest.SuiteLoader(suiteRelpathsToLoad);
+
+ let p = loader.allSuitesLoadedPromise;
+
+ p = p.then(
+ function didAllSuitesLoad() {
+ const tests = loader.getAllTests().filter(function(testCase) {
+ if (testCase instanceof tr.b.unittest.PerfTestCase) {
+ return false;
+ }
+ return true;
+ });
+ if (tests.length === 0) {
+ printSpacer();
+ console.log('FAILED: No tests to run.');
+ console.log(err.stack);
+ quit(1);
+ }
+ const runner = new tr.b.unittest.TestRunner(results, tests);
+ return runner.beginRunning();
+ },
+ function suiteLoadingFailure(err) {
+ printSpacer();
+ console.log('FAILED: A test suite failed to load.');
+ console.log(err.stack);
+ quit(1);
+ });
+
+ p = p.then(
+ function didAllTestRun() {
+ if (results.numTestsThatFailed > 0) {
+ quit(1);
+ } else {
+ quit(0);
+ }
+ },
+ function testHarnessError(e) {
+ console.log('FAILED: A test harness error has ocurred.');
+ console.log(e.stack);
+ quit(1);
+ });
+ return p;
+ }
+
+ return {
+ loadAndRunTests,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/in_memory_trace_stream.html b/chromium/third_party/catapult/tracing/tracing/base/in_memory_trace_stream.html
new file mode 100644
index 00000000000..69b02015c44
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/in_memory_trace_stream.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/trace_stream.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ const MAX_FUNCTION_ARGS_COUNT = Math.pow(2, 15) - 1;
+
+ class InMemoryTraceStream extends tr.b.TraceStream {
+ constructor(buffer, isBinary, opt_headerSize) {
+ super();
+ if (!buffer instanceof Uint8Array) {
+ throw new Error('buffer should be a Uint8Array');
+ }
+ const headerSize = opt_headerSize || tr.b.TraceStream.HEADER_SIZE;
+
+ this.data_ = buffer;
+ this.isBinary_ = isBinary;
+ this.header_ = InMemoryTraceStream.uint8ArrayToString_(
+ this.data_.subarray(0, headerSize));
+ this.cursor_ = 0;
+ }
+
+ get isBinary() {
+ return this.isBinary_;
+ }
+
+ get hasData() {
+ return this.cursor_ < this.data_.length;
+ }
+
+ get header() {
+ return this.header_;
+ }
+
+ get data() {
+ return this.data_;
+ }
+
+ toString() {
+ this.rewind();
+ return this.readNumBytes(Number.MAX_VALUE);
+ }
+
+ readUntilDelimiter(delim) {
+ if (delim.length !== 1) {
+ throw new Error('delim must be exactly one character');
+ }
+ const offset = this.data_.indexOf(delim.charCodeAt(0), this.cursor_) + 1;
+ return this.readToOffset_(
+ offset > 0 ? Math.min(offset, this.data_.length) : this.data_.length);
+ }
+
+ readNumBytes(opt_size) {
+ if (opt_size !== undefined && opt_size <= 0) {
+ throw new Error(
+ `readNumBytes expects a positive size (${opt_size} given)`);
+ }
+
+ const size = opt_size || tr.b.TraceStream.CHUNK_SIZE;
+ const offset = Math.min(this.cursor_ + size, this.data_.length);
+ return this.readToOffset_(offset);
+ }
+
+ rewind() {
+ this.cursor_ = 0;
+ }
+
+ // The underlying buffer is not copied.
+ substream(startOffset, opt_endOffset, opt_headerSize) {
+ return new InMemoryTraceStream(
+ this.data_.subarray(startOffset, opt_endOffset), this.isBinary_,
+ opt_headerSize);
+ }
+
+ /**
+ * @returns {string} The contents of the stream between the current cursor
+ * location (inclusive) and |offset| (exclusive). The cursor location is
+ * moved forward to |offset|.
+ */
+ readToOffset_(offset) {
+ const out = InMemoryTraceStream.uint8ArrayToString_(
+ this.data_.subarray(this.cursor_, offset));
+ this.cursor_ = offset;
+ return out;
+ }
+
+ static uint8ArrayToString_(arr) {
+ if (typeof TextDecoder !== 'undefined') {
+ const decoder = new TextDecoder('utf-8');
+ return decoder.decode(arr);
+ }
+ const c = [];
+ for (let i = 0; i < arr.length; i += MAX_FUNCTION_ARGS_COUNT) {
+ c.push(String.fromCharCode(...arr.subarray(
+ i, i + MAX_FUNCTION_ARGS_COUNT)));
+ }
+ return c.join('');
+ }
+ }
+
+ return {
+ InMemoryTraceStream,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/in_memory_trace_stream_test.html b/chromium/third_party/catapult/tracing/tracing/base/in_memory_trace_stream_test.html
new file mode 100644
index 00000000000..fbc838f4877
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/in_memory_trace_stream_test.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/in_memory_trace_stream.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function stringToUint8Array(str) {
+ const buffer = new ArrayBuffer(str.length);
+ const bufferView = new Uint8Array(buffer);
+ for (let i = 0; i < bufferView.length; i++) {
+ bufferView[i] = str.charCodeAt(i);
+ }
+ return bufferView;
+ }
+
+ test('readUntilDelimiter', function() {
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array('line 1\nline 2\n'), false);
+ assert.strictEqual(stream.readUntilDelimiter('\n'), 'line 1\n');
+ assert.strictEqual(stream.readUntilDelimiter('\n'), 'line 2\n');
+ assert.isFalse(stream.hasData);
+ });
+
+ test('readUntilDelimiter_noDelimiter', function() {
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array('line 1'), false);
+ assert.isTrue(stream.hasData);
+ assert.strictEqual(stream.readUntilDelimiter('\n'), 'line 1');
+ assert.isFalse(stream.hasData);
+ });
+
+ test('readUntilDelimiter_noData', function() {
+ const stream = new tr.b.InMemoryTraceStream(new Uint8Array(0), false);
+ assert.isFalse(stream.hasData);
+ assert.strictEqual(stream.readUntilDelimiter('\n'), '');
+ assert.isFalse(stream.hasData);
+ });
+
+ test('readUntilDelimiter_multiCharacterDelimiterThrows', function() {
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array('Line 1'), false);
+ assert.throws(stream.readUntilDelimiter.bind(stream, 'xy'));
+ });
+
+ test('readNumBytes', function() {
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array('first block second large block and the rest'),
+ false);
+ assert.isTrue(stream.hasData);
+ assert.strictEqual(stream.readNumBytes(12), 'first block ');
+ assert.strictEqual(stream.readNumBytes(19), 'second large block ');
+ // Read a chunk of default length.
+ assert.strictEqual(stream.readNumBytes(), 'and the rest');
+ assert.isFalse(stream.hasData);
+ });
+
+ test('readNumBytes_noData', function() {
+ const stream = new tr.b.InMemoryTraceStream(new Uint8Array(0), false);
+ assert.isFalse(stream.hasData);
+ assert.strictEqual(stream.readNumBytes(10), '');
+ assert.isFalse(stream.hasData);
+ });
+
+ test('readNumBytes_notEnoughData', function() {
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array('bla'), false);
+ assert.isTrue(stream.hasData);
+ assert.strictEqual(stream.readNumBytes(10), 'bla');
+ assert.isFalse(stream.hasData);
+ });
+
+ test('readNumBytes_negativeSize', function() {
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array('bla'), false);
+ assert.throws(stream.readNumBytes.bind(stream, -10));
+ });
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/interval_tree.html b/chromium/third_party/catapult/tracing/tracing/base/interval_tree.html
new file mode 100644
index 00000000000..b0874802fe7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/interval_tree.html
@@ -0,0 +1,350 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ function max(a, b) {
+ if (a === undefined) return b;
+ if (b === undefined) return a;
+ return Math.max(a, b);
+ }
+
+ /**
+ * This class implements an interval tree.
+ * See: http://wikipedia.org/wiki/Interval_tree
+ *
+ * Internally the tree is a Red-Black tree. The insertion/colour is done using
+ * the Left-leaning Red-Black Trees algorithm as described in:
+ * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf
+ *
+ * @param {function} beginPositionCb Callback to retrieve the begin position.
+ * @param {function} endPositionCb Callback to retrieve the end position.
+ *
+ * @constructor
+ */
+ function IntervalTree(beginPositionCb, endPositionCb) {
+ this.beginPositionCb_ = beginPositionCb;
+ this.endPositionCb_ = endPositionCb;
+
+ this.root_ = undefined;
+ this.size_ = 0;
+ }
+
+ IntervalTree.prototype = {
+ /**
+ * Insert events into the interval tree.
+ *
+ * @param {Object} datum The object to insert.
+ */
+ insert(datum) {
+ const startPosition = this.beginPositionCb_(datum);
+ const endPosition = this.endPositionCb_(datum);
+
+ const node = new IntervalTreeNode(datum,
+ startPosition, endPosition);
+ this.size_++;
+
+ this.root_ = this.insertNode_(this.root_, node);
+ this.root_.colour = Colour.BLACK;
+ return datum;
+ },
+
+ insertNode_(root, node) {
+ if (root === undefined) return node;
+
+ if (root.leftNode && root.leftNode.isRed &&
+ root.rightNode && root.rightNode.isRed) {
+ this.flipNodeColour_(root);
+ }
+
+ if (node.key < root.key) {
+ root.leftNode = this.insertNode_(root.leftNode, node);
+ } else if (node.key === root.key) {
+ root.merge(node);
+ } else {
+ root.rightNode = this.insertNode_(root.rightNode, node);
+ }
+
+ if (root.rightNode && root.rightNode.isRed &&
+ (root.leftNode === undefined || !root.leftNode.isRed)) {
+ root = this.rotateLeft_(root);
+ }
+
+ if (root.leftNode && root.leftNode.isRed &&
+ root.leftNode.leftNode && root.leftNode.leftNode.isRed) {
+ root = this.rotateRight_(root);
+ }
+
+ return root;
+ },
+
+ rotateRight_(node) {
+ const sibling = node.leftNode;
+ node.leftNode = sibling.rightNode;
+ sibling.rightNode = node;
+ sibling.colour = node.colour;
+ node.colour = Colour.RED;
+ return sibling;
+ },
+
+ rotateLeft_(node) {
+ const sibling = node.rightNode;
+ node.rightNode = sibling.leftNode;
+ sibling.leftNode = node;
+ sibling.colour = node.colour;
+ node.colour = Colour.RED;
+ return sibling;
+ },
+
+ flipNodeColour_(node) {
+ node.colour = this.flipColour_(node.colour);
+ node.leftNode.colour = this.flipColour_(node.leftNode.colour);
+ node.rightNode.colour = this.flipColour_(node.rightNode.colour);
+ },
+
+ flipColour_(colour) {
+ return colour === Colour.RED ? Colour.BLACK : Colour.RED;
+ },
+
+ /* The high values are used to find intersection. It should be called after
+ * all of the nodes are inserted. Doing it each insert is _slow_. */
+ updateHighValues() {
+ this.updateHighValues_(this.root_);
+ },
+
+ /* There is probably a smarter way to do this by starting from the inserted
+ * node, but need to handle the rotations correctly. Went the easy route
+ * for now. */
+ updateHighValues_(node) {
+ if (node === undefined) return undefined;
+
+ node.maxHighLeft = this.updateHighValues_(node.leftNode);
+ node.maxHighRight = this.updateHighValues_(node.rightNode);
+
+ return max(max(node.maxHighLeft, node.highValue), node.maxHighRight);
+ },
+
+ validateFindArguments_(queryLow, queryHigh) {
+ if (queryLow === undefined || queryHigh === undefined) {
+ throw new Error('queryLow and queryHigh must be defined');
+ }
+ if ((typeof queryLow !== 'number') || (typeof queryHigh !== 'number')) {
+ throw new Error('queryLow and queryHigh must be numbers');
+ }
+ },
+
+ /**
+ * Retrieve all overlapping intervals.
+ *
+ * @param {number} queryLow The low value for the intersection interval.
+ * @param {number} queryHigh The high value for the intersection interval.
+ * @return {Array} All [begin, end] pairs inside intersecting intervals.
+ */
+ findIntersection(queryLow, queryHigh) {
+ this.validateFindArguments_(queryLow, queryHigh);
+ if (this.root_ === undefined) return [];
+
+ const ret = [];
+ this.root_.appendIntersectionsInto_(ret, queryLow, queryHigh);
+ return ret;
+ },
+
+ /**
+ * Returns the number of nodes in the tree.
+ */
+ get size() {
+ return this.size_;
+ },
+
+ /**
+ * Returns the root node in the tree.
+ */
+ get root() {
+ return this.root_;
+ },
+
+ /**
+ * Dumps out the [lowValue, highValue] pairs for each node in depth-first
+ * order.
+ */
+ dump_() {
+ if (this.root_ === undefined) return [];
+ return this.root_.dump();
+ }
+ };
+
+ const Colour = {
+ RED: 'red',
+ BLACK: 'black'
+ };
+
+ function IntervalTreeNode(datum, lowValue, highValue) {
+ this.lowValue_ = lowValue;
+
+ this.data_ = [{
+ datum,
+ high: highValue,
+ low: lowValue
+ }];
+
+ this.colour_ = Colour.RED;
+
+ this.parentNode_ = undefined;
+ this.leftNode_ = undefined;
+ this.rightNode_ = undefined;
+
+ this.maxHighLeft_ = undefined;
+ this.maxHighRight_ = undefined;
+ }
+
+ IntervalTreeNode.prototype = {
+ appendIntersectionsInto_(ret, queryLow, queryHigh) {
+ /* This node starts has a start point at or further right then queryHigh
+ * so we know this node is out and all right children are out. Just need
+ * to check left */
+ if (this.lowValue_ >= queryHigh) {
+ if (!this.leftNode_) return;
+ return this.leftNode_.appendIntersectionsInto_(
+ ret, queryLow, queryHigh);
+ }
+
+ /* If we have a maximum left high value that is bigger then queryLow we
+ * need to check left for matches */
+ if (this.maxHighLeft_ > queryLow) {
+ this.leftNode_.appendIntersectionsInto_(ret, queryLow, queryHigh);
+ }
+
+ /* We know that this node starts before queryHigh, if any of it's data
+ * ends after queryLow we need to add those nodes */
+ if (this.highValue > queryLow) {
+ for (let i = (this.data.length - 1); i >= 0; --i) {
+ /* data nodes are sorted by high value, so as soon as we see one
+ * before low value we're done. */
+ if (this.data[i].high < queryLow) break;
+
+ ret.push(this.data[i].datum);
+ }
+ }
+
+ /* check for matches in the right tree */
+ if (this.rightNode_) {
+ this.rightNode_.appendIntersectionsInto_(ret, queryLow, queryHigh);
+ }
+ },
+
+ get colour() {
+ return this.colour_;
+ },
+
+ set colour(colour) {
+ this.colour_ = colour;
+ },
+
+ get key() {
+ return this.lowValue_;
+ },
+
+ get lowValue() {
+ return this.lowValue_;
+ },
+
+ get highValue() {
+ return this.data_[this.data_.length - 1].high;
+ },
+
+ set leftNode(left) {
+ this.leftNode_ = left;
+ },
+
+ get leftNode() {
+ return this.leftNode_;
+ },
+
+ get hasLeftNode() {
+ return this.leftNode_ !== undefined;
+ },
+
+ set rightNode(right) {
+ this.rightNode_ = right;
+ },
+
+ get rightNode() {
+ return this.rightNode_;
+ },
+
+ get hasRightNode() {
+ return this.rightNode_ !== undefined;
+ },
+
+ set parentNode(parent) {
+ this.parentNode_ = parent;
+ },
+
+ get parentNode() {
+ return this.parentNode_;
+ },
+
+ get isRootNode() {
+ return this.parentNode_ === undefined;
+ },
+
+ set maxHighLeft(high) {
+ this.maxHighLeft_ = high;
+ },
+
+ get maxHighLeft() {
+ return this.maxHighLeft_;
+ },
+
+ set maxHighRight(high) {
+ this.maxHighRight_ = high;
+ },
+
+ get maxHighRight() {
+ return this.maxHighRight_;
+ },
+
+ get data() {
+ return this.data_;
+ },
+
+ get isRed() {
+ return this.colour_ === Colour.RED;
+ },
+
+ merge(node) {
+ for (let i = 0; i < node.data.length; i++) {
+ this.data_.push(node.data[i]);
+ }
+ this.data_.sort(function(a, b) {
+ return a.high - b.high;
+ });
+ },
+
+ dump() {
+ const ret = {};
+ if (this.leftNode_) {
+ ret.left = this.leftNode_.dump();
+ }
+
+ ret.data = this.data_.map(function(d) { return [d.low, d.high]; });
+
+ if (this.rightNode_) {
+ ret.right = this.rightNode_.dump();
+ }
+
+ return ret;
+ }
+ };
+
+ return {
+ IntervalTree,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/interval_tree_test.html b/chromium/third_party/catapult/tracing/tracing/base/interval_tree_test.html
new file mode 100644
index 00000000000..01c9e930f26
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/interval_tree_test.html
@@ -0,0 +1,235 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/interval_tree.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function SimpleIntervalTree() {
+ tr.b.IntervalTree.call(this,
+ function(s) { return s.start; },
+ function(s) { return s.end; });
+ return this;
+ }
+ SimpleIntervalTree.prototype = {
+ __proto__: tr.b.IntervalTree.prototype
+ };
+
+ function buildSimpleTree() {
+ const tree = new SimpleIntervalTree();
+ tree.v0 = tree.insert({start: 2, end: 6});
+ tree.v1 = tree.insert({start: 1, end: 3});
+ tree.v2 = tree.insert({start: 5, end: 7});
+ tree.v3 = tree.insert({start: 1, end: 5});
+ tree.v4 = tree.insert({start: 3, end: 5});
+ tree.v5 = tree.insert({start: 3, end: 5});
+ tree.v6 = tree.insert({start: 3, end: 6});
+ tree.v7 = tree.insert({start: 1, end: 1});
+ tree.v8 = tree.insert({start: 4, end: 8});
+ tree.v9 = tree.insert({start: 0, end: 2});
+
+ tree.updateHighValues();
+
+ return tree;
+ }
+
+ function sortSimpleResults(intersection) {
+ intersection.sort(function(a, b) {
+ if (a.start === b.start) return a.end - b.end;
+ return a.start - b.start;
+ });
+ }
+
+ test('findIntersection', function() {
+ const tree = buildSimpleTree();
+ const intersection = tree.findIntersection(2, 4);
+ sortSimpleResults(intersection);
+
+ const expected = [tree.v1, tree.v3, tree.v0, tree.v4, tree.v5, tree.v6];
+ assert.strictEqual(intersection.length, 6);
+ assert.deepEqual(intersection, expected);
+ });
+
+ test('findIntersection_zeroDuration', function() {
+ const tree = buildSimpleTree();
+ const intersection = tree.findIntersection(2, 2);
+ sortSimpleResults(intersection);
+
+ const expected = [tree.v1, tree.v3];
+ assert.strictEqual(intersection.length, 2);
+ assert.deepEqual(intersection, expected);
+ });
+
+ test('findIntersection_noMatching', function() {
+ const tree = buildSimpleTree();
+ const intersection = tree.findIntersection(9, 10);
+ assert.deepEqual(intersection, []);
+ });
+
+ test('findIntersection_emptyTree', function() {
+ const tree = new tr.b.IntervalTree();
+ tree.updateHighValues();
+
+ const intersection = tree.findIntersection(2, 4);
+ assert.deepEqual(intersection, []);
+ });
+
+ test('findIntersection_emptyInterval', function() {
+ const tree = new tr.b.IntervalTree();
+ tree.updateHighValues();
+
+ assert.throws(function() {
+ tree.findIntersection();
+ });
+ assert.throws(function() {
+ tree.findIntersection(1);
+ });
+ assert.throws(function() {
+ tree.findIntersection('a', 'b');
+ });
+ });
+
+ test('insert', function() {
+ const tree = new tr.b.IntervalTree(
+ function(s) { return s.start; },
+ function(s) { return s.end; });
+
+ assert.strictEqual(tree.size, 0);
+
+ tree.insert({start: 1, end: 4});
+ tree.insert({start: 3, end: 5});
+ tree.updateHighValues();
+
+ const outTree = {
+ 'left': {
+ 'data': [[1, 4]]
+ },
+ 'data': [[3, 5]]
+ };
+
+ assert.strictEqual(tree.size, 2);
+ assert.deepEqual(tree.dump_(), outTree);
+ });
+
+ test('insert_withoutEnd', function() {
+ const tree = new tr.b.IntervalTree(
+ function(s) { return s.start; },
+ function(s) { return s.end; });
+
+ assert.strictEqual(tree.size, 0);
+
+ tree.insert({start: 3, end: 5});
+ tree.insert({start: 1, end: 4});
+ tree.updateHighValues();
+
+ const outTree = {
+ 'left': {
+ 'data': [[1, 4]]
+ },
+ 'data': [[3, 5]]
+ };
+
+ assert.strictEqual(tree.size, 2);
+ assert.deepEqual(tree.dump_(), outTree);
+ });
+
+ test('insert_balancesTree', function() {
+ const tree = new tr.b.IntervalTree(
+ function(s) { return s.start; },
+ function(s) { return s.end; });
+
+ assert.strictEqual(tree.size, 0);
+
+ for (let i = 0; i < 10; ++i) {
+ tree.insert({start: i, end: 5});
+ }
+ tree.updateHighValues();
+
+ const outTree = {
+ 'left': {
+ 'left': {
+ 'data': [[0, 5]]
+ },
+ 'data': [[1, 5]],
+ 'right': {
+ 'data': [[2, 5]]
+ }
+ },
+ 'data': [[3, 5]],
+ 'right': {
+ 'left': {
+ 'left': {
+ 'data': [[4, 5]]
+ },
+ 'data': [[5, 5]],
+ 'right': {
+ 'data': [[6, 5]]
+ }
+ },
+ 'data': [[7, 5]],
+ 'right': {
+ 'left': {
+ 'data': [[8, 5]]
+ },
+ 'data': [[9, 5]]
+ }
+ }
+ };
+
+ assert.deepEqual(tree.dump_(), outTree);
+ });
+
+ test('insert_withDuplicateIntervals', function() {
+ const tree = new tr.b.IntervalTree(
+ function(s) { return s.start; },
+ function(s) { return s.end; });
+
+ assert.strictEqual(tree.size, 0);
+
+ tree.insert({start: 1, end: 4});
+ tree.insert({start: 3, end: 5});
+ tree.insert({start: 3, end: 5});
+ tree.insert({start: 3, end: 6});
+ tree.updateHighValues();
+
+ const outTree = {
+ 'left': {
+ 'data': [[1, 4]]
+ },
+ 'data': [[3, 5], [3, 5], [3, 6]]
+ };
+
+ assert.strictEqual(tree.size, 4);
+ assert.deepEqual(tree.dump_(), outTree);
+ });
+
+ test('insert_updatesHighValues', function() {
+ const tree = buildSimpleTree();
+
+ const expected = [
+ [undefined, undefined],
+ [2, undefined],
+ [5, 8],
+ [undefined, undefined],
+ [6, 7],
+ [undefined, undefined]
+ ];
+
+ const result = [];
+ function walk(node) {
+ if (node === undefined) return;
+
+ walk(node.leftNode);
+ result.push([node.maxHighLeft, node.maxHighRight]);
+ walk(node.rightNode);
+ }
+ walk(tree.root);
+
+ assert.deepEqual(result, expected);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/bbox2.html b/chromium/third_party/catapult/tracing/tracing/base/math/bbox2.html
new file mode 100644
index 00000000000..bca11eb0ce9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/bbox2.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview 2D bounding box computations.
+ */
+tr.exportTo('tr.b.math', function() {
+ /**
+ * Tracks a 2D bounding box.
+ * @constructor
+ */
+ function BBox2() {
+ this.isEmpty_ = true;
+ this.min_ = undefined;
+ this.max_ = undefined;
+ }
+
+ BBox2.prototype = {
+ __proto__: Object.prototype,
+
+ reset() {
+ this.isEmpty_ = true;
+ this.min_ = undefined;
+ this.max_ = undefined;
+ },
+
+ get isEmpty() {
+ return this.isEmpty_;
+ },
+
+ addBBox2(bbox2) {
+ if (bbox2.isEmpty) return;
+ this.addVec2(bbox2.min_);
+ this.addVec2(bbox2.max_);
+ },
+
+ clone() {
+ const bbox = new BBox2();
+ bbox.addBBox2(this);
+ return bbox;
+ },
+
+ /**
+ * Adds x, y to the range.
+ */
+ addXY(x, y) {
+ if (this.isEmpty_) {
+ this.max_ = vec2.create();
+ this.min_ = vec2.create();
+ vec2.set(this.max_, x, y);
+ vec2.set(this.min_, x, y);
+ this.isEmpty_ = false;
+ return;
+ }
+ this.max_[0] = Math.max(this.max_[0], x);
+ this.max_[1] = Math.max(this.max_[1], y);
+ this.min_[0] = Math.min(this.min_[0], x);
+ this.min_[1] = Math.min(this.min_[1], y);
+ },
+
+ /**
+ * Adds value_x, value_y in the form [value_x,value_y] to the range.
+ */
+ addVec2(value) {
+ if (this.isEmpty_) {
+ this.max_ = vec2.create();
+ this.min_ = vec2.create();
+ vec2.set(this.max_, value[0], value[1]);
+ vec2.set(this.min_, value[0], value[1]);
+ this.isEmpty_ = false;
+ return;
+ }
+ this.max_[0] = Math.max(this.max_[0], value[0]);
+ this.max_[1] = Math.max(this.max_[1], value[1]);
+ this.min_[0] = Math.min(this.min_[0], value[0]);
+ this.min_[1] = Math.min(this.min_[1], value[1]);
+ },
+
+ addQuad(quad) {
+ this.addVec2(quad.p1);
+ this.addVec2(quad.p2);
+ this.addVec2(quad.p3);
+ this.addVec2(quad.p4);
+ },
+
+ get minVec2() {
+ if (this.isEmpty_) return undefined;
+ return this.min_;
+ },
+
+ get maxVec2() {
+ if (this.isEmpty_) return undefined;
+ return this.max_;
+ },
+
+ get sizeAsVec2() {
+ if (this.isEmpty_) {
+ throw new Error('Empty BBox2 has no size');
+ }
+ const size = vec2.create();
+ vec2.subtract(size, this.max_, this.min_);
+ return size;
+ },
+
+ get size() {
+ if (this.isEmpty_) {
+ throw new Error('Empty BBox2 has no size');
+ }
+ return {width: this.max_[0] - this.min_[0],
+ height: this.max_[1] - this.min_[1]};
+ },
+
+ get width() {
+ if (this.isEmpty_) {
+ throw new Error('Empty BBox2 has no width');
+ }
+ return this.max_[0] - this.min_[0];
+ },
+
+ get height() {
+ if (this.isEmpty_) {
+ throw new Error('Empty BBox2 has no width');
+ }
+ return this.max_[1] - this.min_[1];
+ },
+
+ toString() {
+ if (this.isEmpty_) return 'empty';
+ return 'min=(' + this.min_[0] + ',' + this.min_[1] + ') ' +
+ 'max=(' + this.max_[0] + ',' + this.max_[1] + ')';
+ },
+
+ asRect() {
+ return tr.b.math.Rect.fromXYWH(
+ this.min_[0],
+ this.min_[1],
+ this.max_[0] - this.min_[0],
+ this.max_[1] - this.min_[1]);
+ }
+ };
+
+ return {
+ BBox2,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/bbox2_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/bbox2_test.html
new file mode 100644
index 00000000000..90b4be3ccb3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/bbox2_test.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/bbox2.html">
+<script>
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('addVec2', function() {
+ const bbox = new tr.b.math.BBox2();
+ const x = vec2.create();
+ vec2.set(x, 10, 10);
+ bbox.addVec2(x);
+ assert.strictEqual(bbox.minVec2[0], 10);
+ assert.strictEqual(bbox.minVec2[1], 10);
+ assert.strictEqual(bbox.maxVec2[0], 10);
+ assert.strictEqual(bbox.maxVec2[1], 10);
+
+ // Mutate x.
+ vec2.set(x, 11, 11);
+
+ // Bbox shouldn't have changed.
+ assert.strictEqual(bbox.minVec2[0], 10);
+ assert.strictEqual(bbox.minVec2[1], 10);
+ assert.strictEqual(bbox.maxVec2[0], 10);
+ assert.strictEqual(bbox.maxVec2[1], 10);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/math.html b/chromium/third_party/catapult/tracing/tracing/base/math/math.html
new file mode 100644
index 00000000000..260cc4ac7bd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/math.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script src="/gl-matrix-min.js"></script>
+
+<script>
+'use strict';
+
+// In node, the script-src for gl-matrix-min above brings in glmatrix into
+// a module, instead of into the global scope. Whereas, Tracing code
+// assumes that glMatrix is in the global scope. So, in Node only, we
+// require() it in, and then take all its exports and shove them into the
+// global scope by hand.
+(function(global) {
+ if (tr.isNode) {
+ const glMatrixAbsPath = HTMLImportsLoader.hrefToAbsolutePath(
+ '/gl-matrix-min.js');
+ const glMatrixModule = require(glMatrixAbsPath);
+ for (const exportName in glMatrixModule) {
+ global[exportName] = glMatrixModule[exportName];
+ }
+ }
+})(this);
+</script>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b.math', function() {
+ const PREFERRED_NUMBER_SERIES_MULTIPLIERS = [1, 2, 5, 10];
+
+ /* Returns true when x and y are within delta of each other. */
+ function approximately(x, y, delta) {
+ if (delta === undefined) delta = 1e-9;
+ return Math.abs(x - y) < delta;
+ }
+
+ function clamp(x, lo, hi) {
+ return Math.min(Math.max(x, lo), hi);
+ }
+
+ function lerp(percentage, lo, hi) {
+ const range = hi - lo;
+ return lo + percentage * range;
+ }
+
+ function normalize(value, lo, hi) {
+ return (value - lo) / (hi - lo);
+ }
+
+ function deg2rad(deg) {
+ return (Math.PI * deg) / 180.0;
+ }
+
+ /* The Gauss error function gives the probability that a measurement (which is
+ * under the influence of normally distributed errors with standard deviation
+ * sigma = 1) is less than x from the mean value of the standard normal
+ * distribution.
+ * https://www.desmos.com/calculator/t1v4bdpske
+ *
+ * @param {number} x A tolerance for error.
+ * @return {number} The probability that a measurement is less than |x| from
+ * the mean value of the standard normal distribution.
+ */
+ function erf(x) {
+ // save the sign of x
+ // erf(-x) = -erf(x);
+ const sign = (x >= 0) ? 1 : -1;
+ x = Math.abs(x);
+
+ // constants
+ const a1 = 0.254829592;
+ const a2 = -0.284496736;
+ const a3 = 1.421413741;
+ const a4 = -1.453152027;
+ const a5 = 1.061405429;
+ const p = 0.3275911;
+
+ // Abramowitz and Stegun formula 7.1.26
+ // maximum error: 1.5e-7
+ const t = 1.0 / (1.0 + p * x);
+ const y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t *
+ Math.exp(-x * x);
+ return sign * y;
+ }
+
+ const tmpVec2 = vec2.create();
+ const tmpVec2b = vec2.create();
+ const tmpVec4 = vec4.create();
+ const tmpMat2d = mat2d.create();
+
+ vec2.createFromArray = function(arr) {
+ if (arr.length !== 2) throw new Error('Should be length 2');
+ const v = vec2.create();
+ vec2.set(v, arr[0], arr[1]);
+ return v;
+ };
+
+ vec2.createXY = function(x, y) {
+ const v = vec2.create();
+ vec2.set(v, x, y);
+ return v;
+ };
+
+ vec2.toString = function(a) {
+ return '[' + a[0] + ', ' + a[1] + ']';
+ };
+
+ vec2.addTwoScaledUnitVectors = function(out, u1, scale1, u2, scale2) {
+ // out = u1 * scale1 + u2 * scale2
+ vec2.scale(tmpVec2, u1, scale1);
+ vec2.scale(tmpVec2b, u2, scale2);
+ vec2.add(out, tmpVec2, tmpVec2b);
+ };
+
+ vec2.interpolatePiecewiseFunction = function(points, x) {
+ if (x < points[0][0]) return points[0][1];
+ for (let i = 1; i < points.length; ++i) {
+ if (x < points[i][0]) {
+ const percent = normalize(x, points[i - 1][0], points[i][0]);
+ return lerp(percent, points[i - 1][1], points[i][1]);
+ }
+ }
+ return points[points.length - 1][1];
+ };
+
+ vec3.createXYZ = function(x, y, z) {
+ const v = vec3.create();
+ vec3.set(v, x, y, z);
+ return v;
+ };
+
+ vec3.toString = function(a) {
+ return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
+ };
+
+ mat2d.translateXY = function(out, x, y) {
+ vec2.set(tmpVec2, x, y);
+ mat2d.translate(out, out, tmpVec2);
+ };
+
+ mat2d.scaleXY = function(out, x, y) {
+ vec2.set(tmpVec2, x, y);
+ mat2d.scale(out, out, tmpVec2);
+ };
+
+ vec4.unitize = function(out, a) {
+ out[0] = a[0] / a[3];
+ out[1] = a[1] / a[3];
+ out[2] = a[2] / a[3];
+ out[3] = 1;
+ return out;
+ };
+
+ vec2.copyFromVec4 = function(out, a) {
+ vec4.unitize(tmpVec4, a);
+ vec2.copy(out, tmpVec4);
+ };
+
+ /**
+ * @param {number} x
+ * @param {number=} opt_base Defaults to 10
+ * @return {number}
+ */
+ function logOrLog10(x, base) {
+ if (base === 10) return Math.log10(x);
+ return Math.log(x) / Math.log(base);
+ }
+
+ /**
+ * @param {number} x
+ * @param {number=} opt_base Defaults to 10
+ * @return {number}
+ */
+ function lesserPower(x, opt_base) {
+ const base = opt_base || 10;
+ return Math.pow(base, Math.floor(logOrLog10(x, base)));
+ }
+
+ /**
+ * @param {number} x
+ * @param {number=} opt_base Defaults to 10
+ * @return {number}
+ */
+ function greaterPower(x, opt_base) {
+ const base = opt_base || 10;
+ return Math.pow(base, Math.ceil(logOrLog10(x, base)));
+ }
+
+ function lesserWholeNumber(x) {
+ if (x === 0) return 0;
+ const pow10 = (x < 0) ? -lesserPower(-x) : lesserPower(x);
+ return pow10 * Math.floor(x / pow10);
+ }
+
+ function greaterWholeNumber(x) {
+ if (x === 0) return 0;
+ const pow10 = (x < 0) ? -lesserPower(-x) : lesserPower(x);
+ return pow10 * Math.ceil(x / pow10);
+ }
+
+ function truncate(value, digits) {
+ const pow10 = Math.pow(10, digits);
+ return Math.round(value * pow10) / pow10;
+ }
+
+ /**
+ * Uses the 1-2-5 series to find the closest prefered number to min
+ * whose absolute value is at least the absolute value of |min|.
+ * https://en.wikipedia.org/wiki/Preferred_number
+ */
+ function preferredNumberLargerThanMin(min) {
+ const absMin = Math.abs(min);
+ // The conservative guess is the largest power of 10 less than
+ // or equal to |absMin|.
+ const conservativeGuess = tr.b.math.lesserPower(absMin);
+ let minPreferedNumber = undefined;
+ for (const multiplier of PREFERRED_NUMBER_SERIES_MULTIPLIERS) {
+ const tightenedGuess = conservativeGuess * multiplier;
+ if (tightenedGuess >= absMin) {
+ minPreferedNumber = tightenedGuess;
+ break;
+ }
+ }
+ if (minPreferedNumber === undefined) {
+ throw new Error('Could not compute preferred number for ' + min);
+ }
+ if (min < 0) minPreferedNumber *= -1;
+ return minPreferedNumber;
+ }
+
+ return {
+ approximately,
+ clamp,
+ lerp,
+ normalize,
+ deg2rad,
+ erf,
+ lesserPower,
+ greaterPower,
+ lesserWholeNumber,
+ greaterWholeNumber,
+ preferredNumberLargerThanMin,
+ truncate,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/math_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/math_test.html
new file mode 100644
index 00000000000..70e5405cd22
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/math_test.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/math.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('truncate', function() {
+ assert.strictEqual(3, tr.b.math.truncate(10 / 3, 0));
+ assert.strictEqual(3.3, tr.b.math.truncate(10 / 3, 1));
+ assert.strictEqual(3.33, tr.b.math.truncate(10 / 3, 2));
+ assert.strictEqual(3.333, tr.b.math.truncate(10 / 3, 3));
+ assert.strictEqual(3.3333, tr.b.math.truncate(10 / 3, 4));
+ });
+
+ test('erf', function() {
+ assert.closeTo(-1, tr.b.math.erf(-1e10), 1e-6);
+ assert.closeTo(-0.8427, tr.b.math.erf(-1), 1e-6);
+ assert.closeTo(-0.5205, tr.b.math.erf(-0.5), 1e-6);
+ assert.closeTo(0, tr.b.math.erf(0), 1e-6);
+ assert.closeTo(0.5205, tr.b.math.erf(0.5), 1e-6);
+ assert.closeTo(0.8427, tr.b.math.erf(1), 1e-6);
+ assert.closeTo(1, tr.b.math.erf(1e10), 1e-6);
+ });
+
+ test('clamping', function() {
+ assert.strictEqual(tr.b.math.clamp(2, 1, 3), 2);
+ assert.strictEqual(tr.b.math.clamp(1, 1, 3), 1);
+ assert.strictEqual(tr.b.math.clamp(0, 1, 3), 1);
+ assert.strictEqual(tr.b.math.clamp(3, 1, 3), 3);
+ assert.strictEqual(tr.b.math.clamp(4, 1, 3), 3);
+ });
+
+ test('interpolatePiecewiseFunction', function() {
+ const points = [[0, 0], [0.1, 0.5], [1, 1]];
+ assert.strictEqual(0, vec2.interpolatePiecewiseFunction(points, -1));
+ assert.strictEqual(0, vec2.interpolatePiecewiseFunction(points, 0));
+ assert.strictEqual(0.25, vec2.interpolatePiecewiseFunction(points, 0.05));
+ assert.strictEqual(0.5, vec2.interpolatePiecewiseFunction(points, 0.1));
+ assert.strictEqual(0.75, vec2.interpolatePiecewiseFunction(points, 0.55));
+ assert.strictEqual(1, vec2.interpolatePiecewiseFunction(points, 1));
+ assert.strictEqual(1, vec2.interpolatePiecewiseFunction(points, 2));
+ });
+
+ test('powers', function() {
+ assert.strictEqual(0.01, tr.b.math.lesserPower(0.05));
+ assert.strictEqual(0.1, tr.b.math.greaterPower(0.05));
+ assert.strictEqual(0.1, tr.b.math.lesserPower(0.5));
+ assert.strictEqual(1, tr.b.math.greaterPower(0.5));
+ assert.strictEqual(1, tr.b.math.lesserPower(5));
+ assert.strictEqual(10, tr.b.math.greaterPower(5));
+ assert.strictEqual(10, tr.b.math.lesserPower(50));
+ assert.strictEqual(100, tr.b.math.greaterPower(50));
+
+ assert.strictEqual(0, tr.b.math.lesserPower(0));
+ assert.strictEqual(0, tr.b.math.greaterPower(0));
+ assert.isTrue(isNaN(tr.b.math.lesserPower(-1)));
+ assert.isTrue(isNaN(tr.b.math.greaterPower(-1)));
+
+ assert.strictEqual(0.25, tr.b.math.lesserPower(0.3, 2));
+ assert.strictEqual(0.5, tr.b.math.greaterPower(0.3, 2));
+ assert.strictEqual(0.5, tr.b.math.lesserPower(0.8, 2));
+ assert.strictEqual(1, tr.b.math.greaterPower(0.8, 2));
+ assert.strictEqual(1, tr.b.math.lesserPower(1.5, 2));
+ assert.strictEqual(2, tr.b.math.greaterPower(1.5, 2));
+ assert.strictEqual(2, tr.b.math.lesserPower(3, 2));
+ assert.strictEqual(4, tr.b.math.greaterPower(3, 2));
+ assert.strictEqual(4, tr.b.math.lesserPower(5, 2));
+ assert.strictEqual(8, tr.b.math.greaterPower(5, 2));
+
+ assert.strictEqual(0, tr.b.math.lesserPower(0, 2));
+ assert.strictEqual(0, tr.b.math.greaterPower(0, 2));
+ assert.isTrue(isNaN(tr.b.math.lesserPower(-1, 2)));
+ assert.isTrue(isNaN(tr.b.math.greaterPower(-1, 2)));
+ });
+
+ test('lesserWholeNumber', function() {
+ // Use powers of 2 less than 10 to prevent float rounding errors from
+ // breaking Math.floor().
+ for (const i of [1, 2, 4, 8]) {
+ assert.strictEqual(-i, tr.b.math.lesserWholeNumber(-i));
+ assert.strictEqual(-i * 10, tr.b.math.lesserWholeNumber(-i * 10));
+ assert.strictEqual(-i / 10, tr.b.math.lesserWholeNumber(-i / 10));
+ assert.strictEqual(-i * 100, tr.b.math.lesserWholeNumber(-i * 100));
+ assert.strictEqual(-i / 100, tr.b.math.lesserWholeNumber(-i / 100));
+
+ assert.strictEqual(i, tr.b.math.lesserWholeNumber(i));
+ assert.strictEqual(i * 10, tr.b.math.lesserWholeNumber(i * 10));
+ assert.strictEqual(i / 10, tr.b.math.lesserWholeNumber(i / 10));
+ assert.strictEqual(i * 100, tr.b.math.lesserWholeNumber(i * 100));
+ assert.strictEqual(i / 100, tr.b.math.lesserWholeNumber(i / 100));
+
+ const x = i * 1.01;
+ assert.strictEqual(-i, tr.b.math.lesserWholeNumber(-x));
+ assert.strictEqual(-i * 10, tr.b.math.lesserWholeNumber(-x * 10));
+ assert.strictEqual(-i / 10, tr.b.math.lesserWholeNumber(-x / 10));
+ assert.strictEqual(-i * 100, tr.b.math.lesserWholeNumber(-x * 100));
+ assert.strictEqual(-i / 100, tr.b.math.lesserWholeNumber(-x / 100));
+
+ assert.strictEqual(i, tr.b.math.lesserWholeNumber(x));
+ assert.strictEqual(i * 10, tr.b.math.lesserWholeNumber(x * 10));
+ assert.strictEqual(i / 10, tr.b.math.lesserWholeNumber(x / 10));
+ assert.strictEqual(i * 100, tr.b.math.lesserWholeNumber(x * 100));
+ assert.strictEqual(i / 100, tr.b.math.lesserWholeNumber(x / 100));
+ }
+ });
+
+ test('greaterWholeNumber', function() {
+ // Use powers of 2 great than 10 to prevent float rounding errors from
+ // breaking Math.floor().
+ for (const i of [1, 2, 4, 8]) {
+ assert.strictEqual(-i, tr.b.math.greaterWholeNumber(-i));
+ assert.strictEqual(-i * 10, tr.b.math.greaterWholeNumber(-i * 10));
+ assert.strictEqual(-i / 10, tr.b.math.greaterWholeNumber(-i / 10));
+ assert.strictEqual(-i * 100, tr.b.math.greaterWholeNumber(-i * 100));
+ assert.strictEqual(-i / 100, tr.b.math.greaterWholeNumber(-i / 100));
+
+ assert.strictEqual(i, tr.b.math.greaterWholeNumber(i));
+ assert.strictEqual(i * 10, tr.b.math.greaterWholeNumber(i * 10));
+ assert.strictEqual(i / 10, tr.b.math.greaterWholeNumber(i / 10));
+ assert.strictEqual(i * 100, tr.b.math.greaterWholeNumber(i * 100));
+ assert.strictEqual(i / 100, tr.b.math.greaterWholeNumber(i / 100));
+
+ const x = i * 0.99;
+ assert.strictEqual(-i, tr.b.math.greaterWholeNumber(-x));
+ assert.strictEqual(-i * 10, tr.b.math.greaterWholeNumber(-x * 10));
+ assert.strictEqual(-i / 10, tr.b.math.greaterWholeNumber(-x / 10));
+ assert.strictEqual(-i * 100, tr.b.math.greaterWholeNumber(-x * 100));
+ assert.strictEqual(-i / 100, tr.b.math.greaterWholeNumber(-x / 100));
+
+ assert.strictEqual(i, tr.b.math.greaterWholeNumber(x));
+ assert.strictEqual(i * 10, tr.b.math.greaterWholeNumber(x * 10));
+ assert.strictEqual(i / 10, tr.b.math.greaterWholeNumber(x / 10));
+ assert.strictEqual(i * 100, tr.b.math.greaterWholeNumber(x * 100));
+ assert.strictEqual(i / 100, tr.b.math.greaterWholeNumber(x / 100));
+ }
+ });
+
+ test('preferedNumberLargerThanMin', function() {
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(0), 0);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(1), 1);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(2), 2);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(3), 5);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(7), 10);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(0.03), 0.05);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(-1), -1);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(237538), 500000);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(46.13246), 50);
+ assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(-823.34561),
+ -1000);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/piecewise_linear_function.html b/chromium/third_party/catapult/tracing/tracing/base/math/piecewise_linear_function.html
new file mode 100644
index 00000000000..0a782adae01
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/piecewise_linear_function.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b.math', function() {
+ const PERCENTILE_PRECISION = 1e-7;
+ /**
+ * A function that consists of linear pieces.
+ * See https://en.wikipedia.org/wiki/Piecewise_linear_function.
+ * @constructor
+ */
+ function PiecewiseLinearFunction() {
+ this.pieces = [];
+ }
+
+ PiecewiseLinearFunction.prototype = {
+ /**
+ * Push a linear piece defined by linear interpolation between.
+ * (x1, y1) and (x2, y2).
+ * Pieces must be pushed in the order of increasing x coordinate.
+ */
+ push(x1, y1, x2, y2) {
+ if (x1 >= x2) {
+ throw new Error('Invalid segment');
+ }
+ if (this.pieces.length > 0 &&
+ this.pieces[this.pieces.length - 1].x2 > x1) {
+ throw new Error('Potentially overlapping segments');
+ }
+ if (x1 < x2) {
+ this.pieces.push(new Piece(x1, y1, x2, y2));
+ }
+ },
+
+ /**
+ * Returns the size of the set A such that for all x in A: f(x) < y.
+ */
+ partBelow(y) {
+ return this.pieces.reduce((acc, p) => (acc + p.partBelow(y)), 0);
+ },
+
+ get min() {
+ return this.pieces.reduce((acc, p) => Math.min(acc, p.min), Infinity);
+ },
+
+ get max() {
+ return this.pieces.reduce((acc, p) => Math.max(acc, p.max), -Infinity);
+ },
+
+ get average() {
+ let weightedSum = 0;
+ let totalWeight = 0;
+ this.pieces.forEach(function(piece) {
+ weightedSum += piece.width * piece.average;
+ totalWeight += piece.width;
+ });
+ if (totalWeight === 0) return 0;
+ return weightedSum / totalWeight;
+ },
+
+ /**
+ * Returns the minimum possible value y such that the percentage of x points
+ * that have f(x) <= y is approximately equal to the given |percent|.
+ */
+ percentile(percent) {
+ if (!(percent >= 0 && percent <= 1)) {
+ throw new Error('percent must be [0,1]');
+ }
+ let lower = this.min;
+ let upper = this.max;
+ const total = this.partBelow(upper);
+ if (total === 0) return 0;
+ while (upper - lower > PERCENTILE_PRECISION) {
+ const middle = (lower + upper) / 2;
+ const below = this.partBelow(middle);
+ if (below / total < percent) {
+ lower = middle;
+ } else {
+ upper = middle;
+ }
+ }
+ return (lower + upper) / 2;
+ }
+ };
+
+ /**
+ * A linear segment from (x1, y1) to (x2, y2).
+ * @constructor
+ */
+ function Piece(x1, y1, x2, y2) {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ }
+
+ Piece.prototype = {
+ /**
+ * The total length of all x points such that f(x) < y.
+ * More formally:
+ * max(x2 - x1) such that for all x in [x1 .. x2]: f(x) < y.
+ */
+ partBelow(y) {
+ const width = this.width;
+ if (width === 0) return 0;
+ const minY = this.min;
+ const maxY = this.max;
+ if (y >= maxY) return width;
+ if (y < minY) return 0;
+ return (y - minY) / (maxY - minY) * width;
+ },
+
+ get min() {
+ return Math.min(this.y1, this.y2);
+ },
+
+ get max() {
+ return Math.max(this.y1, this.y2);
+ },
+
+ get average() {
+ return (this.y1 + this.y2) / 2;
+ },
+
+ get width() {
+ return this.x2 - this.x1;
+ }
+ };
+
+ return {
+ PiecewiseLinearFunction,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/piecewise_linear_function_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/piecewise_linear_function_test.html
new file mode 100644
index 00000000000..fb33bb44a3d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/piecewise_linear_function_test.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/piecewise_linear_function.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('PiecewiseLinearFunctionEmpty', function() {
+ const f = new tr.b.math.PiecewiseLinearFunction();
+ assert.strictEqual(f.max, -Infinity);
+ assert.strictEqual(f.min, Infinity);
+ assert.strictEqual(f.average, 0);
+ assert.strictEqual(f.percentile(0.5), 0);
+ });
+
+ test('PiecewiseLinearFunction', function() {
+ const f = new tr.b.math.PiecewiseLinearFunction();
+ f.push(0, 0.0, 10, 1.0);
+ f.push(10, 1.0, 20, 0.0);
+ f.push(20, 0.0, 30, 0.0);
+ assert.strictEqual(f.max, 1.0);
+ assert.strictEqual(f.min, 0.0);
+ assert.closeTo(f.average, 20 * 1 / 2.0 / 30, 1e-6);
+ assert.closeTo(f.percentile(1.0 / 3.0), 0.0, 1e-6);
+ assert.closeTo(f.percentile(2.0 / 3.0), 0.5, 1e-6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/quad.html b/chromium/third_party/catapult/tracing/tracing/base/math/quad.html
new file mode 100644
index 00000000000..b87f76a4f87
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/quad.html
@@ -0,0 +1,233 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b.math', function() {
+ const tmpVec2s = [];
+ for (let i = 0; i < 8; i++) {
+ tmpVec2s[i] = vec2.create();
+ }
+
+ const tmpVec2a = vec4.create();
+ const tmpVec4a = vec4.create();
+ const tmpVec4b = vec4.create();
+ const tmpMat4 = mat4.create();
+ const tmpMat4b = mat4.create();
+
+ const p00 = vec2.createXY(0, 0);
+ const p10 = vec2.createXY(1, 0);
+ const p01 = vec2.createXY(0, 1);
+ const p11 = vec2.createXY(1, 1);
+
+ const lerpingVecA = vec2.create();
+ const lerpingVecB = vec2.create();
+ function lerpVec2(out, a, b, amt) {
+ vec2.scale(lerpingVecA, a, amt);
+ vec2.scale(lerpingVecB, b, 1 - amt);
+ vec2.add(out, lerpingVecA, lerpingVecB);
+ vec2.normalize(out, out);
+ return out;
+ }
+
+ /**
+ * @constructor
+ */
+ function Quad() {
+ this.p1 = vec2.create();
+ this.p2 = vec2.create();
+ this.p3 = vec2.create();
+ this.p4 = vec2.create();
+ }
+
+ Quad.fromXYWH = function(x, y, w, h) {
+ const q = new Quad();
+ vec2.set(q.p1, x, y);
+ vec2.set(q.p2, x + w, y);
+ vec2.set(q.p3, x + w, y + h);
+ vec2.set(q.p4, x, y + h);
+ return q;
+ };
+
+ Quad.fromRect = function(r) {
+ return new Quad.fromXYWH(
+ r.x, r.y,
+ r.width, r.height);
+ };
+
+ Quad.from4Vecs = function(p1, p2, p3, p4) {
+ const q = new Quad();
+ vec2.set(q.p1, p1[0], p1[1]);
+ vec2.set(q.p2, p2[0], p2[1]);
+ vec2.set(q.p3, p3[0], p3[1]);
+ vec2.set(q.p4, p4[0], p4[1]);
+ return q;
+ };
+
+ Quad.from8Array = function(arr) {
+ if (arr.length !== 8) {
+ throw new Error('Array must be 8 long');
+ }
+ const q = new Quad();
+ q.p1[0] = arr[0];
+ q.p1[1] = arr[1];
+ q.p2[0] = arr[2];
+ q.p2[1] = arr[3];
+ q.p3[0] = arr[4];
+ q.p3[1] = arr[5];
+ q.p4[0] = arr[6];
+ q.p4[1] = arr[7];
+ return q;
+ };
+
+ Quad.prototype = {
+ pointInside(point) {
+ return pointInImplicitQuad(point,
+ this.p1, this.p2, this.p3, this.p4);
+ },
+
+ boundingRect() {
+ const x0 = Math.min(this.p1[0], this.p2[0], this.p3[0], this.p4[0]);
+ const y0 = Math.min(this.p1[1], this.p2[1], this.p3[1], this.p4[1]);
+
+ const x1 = Math.max(this.p1[0], this.p2[0], this.p3[0], this.p4[0]);
+ const y1 = Math.max(this.p1[1], this.p2[1], this.p3[1], this.p4[1]);
+
+ return new tr.b.math.Rect.fromXYWH(x0, y0, x1 - x0, y1 - y0);
+ },
+
+ clone() {
+ const q = new Quad();
+ vec2.copy(q.p1, this.p1);
+ vec2.copy(q.p2, this.p2);
+ vec2.copy(q.p3, this.p3);
+ vec2.copy(q.p4, this.p4);
+ return q;
+ },
+
+ scale(s) {
+ const q = new Quad();
+ this.scaleFast(q, s);
+ return q;
+ },
+
+ scaleFast(dstQuad, s) {
+ vec2.copy(dstQuad.p1, this.p1, s);
+ vec2.copy(dstQuad.p2, this.p2, s);
+ vec2.copy(dstQuad.p3, this.p3, s);
+ vec2.copy(dstQuad.p3, this.p3, s);
+ },
+
+ isRectangle() {
+ // Simple rectangle check. Note: will not handle out-of-order components.
+ const bounds = this.boundingRect();
+ return (
+ bounds.x === this.p1[0] &&
+ bounds.y === this.p1[1] &&
+ bounds.width === this.p2[0] - this.p1[0] &&
+ bounds.y === this.p2[1] &&
+ bounds.width === this.p3[0] - this.p1[0] &&
+ bounds.height === this.p3[1] - this.p2[1] &&
+ bounds.x === this.p4[0] &&
+ bounds.height === this.p4[1] - this.p2[1]
+ );
+ },
+
+ projectUnitRect(rect) {
+ const q = new Quad();
+ this.projectUnitRectFast(q, rect);
+ return q;
+ },
+
+ projectUnitRectFast(dstQuad, rect) {
+ const v12 = tmpVec2s[0];
+ const v14 = tmpVec2s[1];
+ const v23 = tmpVec2s[2];
+ const v43 = tmpVec2s[3];
+
+ vec2.sub(v12, this.p2, this.p1);
+ const l12 = vec2.length(v12);
+ vec2.scale(v12, v12, 1 / l12);
+
+ vec2.sub(v14, this.p4, this.p1);
+ const l14 = vec2.length(v14);
+ vec2.scale(v14, v14, 1 / l14);
+
+ vec2.sub(v23, this.p3, this.p2);
+ const l23 = vec2.length(v23);
+ vec2.scale(v23, v23, 1 / l23);
+
+ vec2.sub(v43, this.p3, this.p4);
+ const l43 = vec2.length(v43);
+ vec2.scale(v43, v43, 1 / l43);
+
+ const b12 = tmpVec2s[0];
+ const b14 = tmpVec2s[1];
+ const b23 = tmpVec2s[2];
+ const b43 = tmpVec2s[3];
+ lerpVec2(b12, v12, v43, rect.y);
+ lerpVec2(b43, v12, v43, 1 - rect.bottom);
+ lerpVec2(b14, v14, v23, rect.x);
+ lerpVec2(b23, v14, v23, 1 - rect.right);
+
+ vec2.addTwoScaledUnitVectors(tmpVec2a,
+ b12, l12 * rect.x,
+ b14, l14 * rect.y);
+ vec2.add(dstQuad.p1, this.p1, tmpVec2a);
+
+ vec2.addTwoScaledUnitVectors(tmpVec2a,
+ b12, l12 * -(1.0 - rect.right),
+ b23, l23 * rect.y);
+ vec2.add(dstQuad.p2, this.p2, tmpVec2a);
+
+
+ vec2.addTwoScaledUnitVectors(tmpVec2a,
+ b43, l43 * -(1.0 - rect.right),
+ b23, l23 * -(1.0 - rect.bottom));
+ vec2.add(dstQuad.p3, this.p3, tmpVec2a);
+
+ vec2.addTwoScaledUnitVectors(tmpVec2a,
+ b43, l43 * rect.left,
+ b14, l14 * -(1.0 - rect.bottom));
+ vec2.add(dstQuad.p4, this.p4, tmpVec2a);
+ },
+
+ toString() {
+ return 'Quad(' +
+ vec2.toString(this.p1) + ', ' +
+ vec2.toString(this.p2) + ', ' +
+ vec2.toString(this.p3) + ', ' +
+ vec2.toString(this.p4) + ')';
+ }
+ };
+
+ function sign(p1, p2, p3) {
+ return (p1[0] - p3[0]) * (p2[1] - p3[1]) -
+ (p2[0] - p3[0]) * (p1[1] - p3[1]);
+ }
+
+ function pointInTriangle2(pt, p1, p2, p3) {
+ const b1 = sign(pt, p1, p2) < 0.0;
+ const b2 = sign(pt, p2, p3) < 0.0;
+ const b3 = sign(pt, p3, p1) < 0.0;
+ return ((b1 === b2) && (b2 === b3));
+ }
+
+ function pointInImplicitQuad(point, p1, p2, p3, p4) {
+ return pointInTriangle2(point, p1, p2, p3) ||
+ pointInTriangle2(point, p1, p3, p4);
+ }
+
+ return {
+ pointInTriangle2,
+ pointInImplicitQuad,
+ Quad,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/quad_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/quad_test.html
new file mode 100644
index 00000000000..9f31d46bf15
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/quad_test.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+<script>
+'use strict';
+
+function assertQuadEquals(a, b, opt_message) {
+ let ok = true;
+ ok &= a.p1[0] === b.p1[0] && a.p1[1] === b.p1[1];
+ ok &= a.p2[0] === b.p2[0] && a.p2[1] === b.p2[1];
+ ok &= a.p3[0] === b.p3[0] && a.p3[1] === b.p3[1];
+ ok &= a.p4[0] === b.p4[0] && a.p4[1] === b.p4[1];
+ if (ok) return;
+ const message = opt_message || 'Expected "' + a.toString() +
+ '", got "' + b.toString() + '"';
+ assert.fail(a, b, message);
+}
+
+tr.b.unittest.testSuite(function() {
+ test('pointInTri', function() {
+ const res = tr.b.math.pointInTriangle2(
+ [0.25, 0.25],
+ [0, 0],
+ [1, 0],
+ [0, 1]);
+ assert.isTrue(res);
+ });
+
+ test('pointNotInTri', function() {
+ const res = tr.b.math.pointInTriangle2(
+ [0.75, 0.75],
+ [0, 0],
+ [1, 0],
+ [0, 1]);
+ assert.isFalse(res);
+ });
+
+ test('pointInside', function() {
+ const q = tr.b.math.Quad.from4Vecs([0, 0],
+ [1, 0],
+ [1, 1],
+ [0, 1]);
+ const res = q.pointInside([0.5, 0.5]);
+ assert.isTrue(res);
+ });
+
+ test('pointNotInQuad', function() {
+ const q = tr.b.math.Quad.from4Vecs([0, 0],
+ [1, 0],
+ [1, 1],
+ [0, 1]);
+ const res = q.pointInside([1.5, 0.5]);
+ assert.isFalse(res);
+ });
+
+ test('isRectangle', function() {
+ assert.isTrue(tr.b.math.Quad.fromXYWH(0, 0, 10, 10).isRectangle());
+ assert.isTrue(tr.b.math.Quad.fromXYWH(-10, -10, 5, 5).isRectangle());
+ assert.isTrue(tr.b.math.Quad.fromXYWH(-10, -10, 20, 20).isRectangle());
+ assert.isTrue(tr.b.math.Quad.fromXYWH(-10, 10, 5, 5).isRectangle());
+
+ assert.isFalse(tr.b.math.Quad.fromXYWH(0, 0, -10, -10).isRectangle());
+ assert.isFalse(
+ tr.b.math.Quad.from8Array([0, 1, 2, 3, 4, 5, 6, 7]).isRectangle());
+ assert.isFalse(
+ tr.b.math.Quad.from8Array([0, 0, 0, 5, 5, 5, 0, 0]).isRectangle());
+ });
+
+ test('projectUnitRect', function() {
+ const container = tr.b.math.Quad.fromXYWH(0, 0, 10, 10);
+ const srcRect = tr.b.math.Rect.fromXYWH(0.1, 0.8, 0.8, 0.1);
+ const expectedRect = srcRect.scale(10);
+
+ const q = new tr.b.math.Quad();
+ container.projectUnitRectFast(q, srcRect);
+
+ assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+ });
+
+ test('projectUnitRectOntoUnitQuad', function() {
+ const container = tr.b.math.Quad.fromXYWH(0, 0, 1, 1);
+ const srcRect = tr.b.math.Rect.fromXYWH(0.0, 0, 1, 1);
+ const expectedRect = srcRect;
+
+ const q = new tr.b.math.Quad();
+ container.projectUnitRectFast(q, srcRect);
+
+ assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+ });
+
+ test('projectUnitRectOntoSizeTwoQuad', function() {
+ const container = tr.b.math.Quad.fromXYWH(0, 0, 2, 2);
+ const srcRect = tr.b.math.Rect.fromXYWH(0.0, 0, 1, 1);
+ const expectedRect = srcRect.scale(2);
+
+ const q = new tr.b.math.Quad();
+ container.projectUnitRectFast(q, srcRect);
+
+ assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+ });
+
+ test('projectUnitRectOntoTranslatedQuad', function() {
+ const container = tr.b.math.Quad.fromXYWH(1, 1, 1, 1);
+ const srcRect = tr.b.math.Rect.fromXYWH(0.0, 0, 1, 1);
+ const expectedRect = srcRect.translate([1, 1]);
+
+ const q = new tr.b.math.Quad();
+ container.projectUnitRectFast(q, srcRect);
+
+ assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+ });
+
+ test('projectShrunkUnitRectOntoUnitQuad', function() {
+ const container = tr.b.math.Quad.fromXYWH(0, 0, 1, 1);
+ const srcRect = tr.b.math.Rect.fromXYWH(0.1, 0.1, 0.8, 0.8);
+ const expectedRect = srcRect;
+
+ const q = new tr.b.math.Quad();
+ container.projectUnitRectFast(q, srcRect);
+
+ assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/range.html b/chromium/third_party/catapult/tracing/tracing/base/math/range.html
new file mode 100644
index 00000000000..a225eed4d28
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/range.html
@@ -0,0 +1,308 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Quick range computations.
+ */
+tr.exportTo('tr.b.math', function() {
+ function Range() {
+ this.isEmpty_ = true;
+ this.min_ = undefined;
+ this.max_ = undefined;
+ }
+
+ Range.prototype = {
+ __proto__: Object.prototype,
+
+ clone() {
+ if (this.isEmpty) return new Range();
+ return Range.fromExplicitRange(this.min_, this.max_);
+ },
+
+ reset() {
+ this.isEmpty_ = true;
+ this.min_ = undefined;
+ this.max_ = undefined;
+ },
+
+ get isEmpty() {
+ return this.isEmpty_;
+ },
+
+ addRange(range) {
+ if (range.isEmpty) return;
+ this.addValue(range.min);
+ this.addValue(range.max);
+ },
+
+ addValue(value) {
+ if (this.isEmpty_) {
+ this.max_ = value;
+ this.min_ = value;
+ this.isEmpty_ = false;
+ return;
+ }
+ this.max_ = Math.max(this.max_, value);
+ this.min_ = Math.min(this.min_, value);
+ },
+
+ set min(min) {
+ this.isEmpty_ = false;
+ this.min_ = min;
+ },
+
+ get min() {
+ if (this.isEmpty_) return undefined;
+ return this.min_;
+ },
+
+ get max() {
+ if (this.isEmpty_) return undefined;
+ return this.max_;
+ },
+
+ set max(max) {
+ this.isEmpty_ = false;
+ this.max_ = max;
+ },
+
+ get range() {
+ if (this.isEmpty_) return undefined;
+ return this.max_ - this.min_;
+ },
+
+ get center() {
+ return (this.min_ + this.max_) * 0.5;
+ },
+
+ get duration() {
+ if (this.isEmpty_) return 0;
+ return this.max_ - this.min_;
+ },
+
+ /**
+ * Get a new Range spanning the powers (of opt_base || 10) that enclose
+ * |this| Range.
+ * If |this| is empty, returns a new empty Range.
+ *
+ * @param {number=} opt_base Defaults to 10.
+ * @return {!Range}
+ */
+ enclosingPowers(opt_base) {
+ if (this.isEmpty) return new Range();
+ return Range.fromExplicitRange(
+ tr.b.math.lesserPower(this.min_, opt_base),
+ tr.b.math.greaterPower(this.max_, opt_base));
+ },
+
+ normalize(x) {
+ return tr.b.math.normalize(x, this.min, this.max);
+ },
+
+ lerp(x) {
+ return tr.b.math.lerp(x, this.min, this.max);
+ },
+
+ clamp(x) {
+ return tr.b.math.clamp(x, this.min, this.max);
+ },
+
+ equals(that) {
+ if (this.isEmpty && that.isEmpty) return true;
+ if (this.isEmpty !== that.isEmpty) return false;
+ return (tr.b.math.approximately(this.min, that.min) &&
+ tr.b.math.approximately(this.max, that.max));
+ },
+
+ containsExplicitRangeInclusive(min, max) {
+ if (this.isEmpty) return false;
+ return this.min_ <= min && max <= this.max_;
+ },
+
+ containsExplicitRangeExclusive(min, max) {
+ if (this.isEmpty) return false;
+ return this.min_ < min && max < this.max_;
+ },
+
+ intersectsExplicitRangeInclusive(min, max) {
+ if (this.isEmpty) return false;
+ return this.min_ <= max && min <= this.max_;
+ },
+
+ intersectsExplicitRangeExclusive(min, max) {
+ if (this.isEmpty) return false;
+ return this.min_ < max && min < this.max_;
+ },
+
+ containsRangeInclusive(range) {
+ if (range.isEmpty) return false;
+ return this.containsExplicitRangeInclusive(range.min_, range.max_);
+ },
+
+ containsRangeExclusive(range) {
+ if (range.isEmpty) return false;
+ return this.containsExplicitRangeExclusive(range.min_, range.max_);
+ },
+
+ intersectsRangeInclusive(range) {
+ if (range.isEmpty) return false;
+ return this.intersectsExplicitRangeInclusive(range.min_, range.max_);
+ },
+
+ intersectsRangeExclusive(range) {
+ if (range.isEmpty) return false;
+ return this.intersectsExplicitRangeExclusive(range.min_, range.max_);
+ },
+
+ findExplicitIntersectionDuration(min, max) {
+ min = Math.max(this.min, min);
+ max = Math.min(this.max, max);
+ if (max < min) return 0;
+ return max - min;
+ },
+
+ findIntersection(range) {
+ if (this.isEmpty || range.isEmpty) return new Range();
+
+ const min = Math.max(this.min, range.min);
+ const max = Math.min(this.max, range.max);
+
+ if (max < min) return new Range();
+
+ return Range.fromExplicitRange(min, max);
+ },
+
+ toJSON() {
+ if (this.isEmpty_) return {isEmpty: true};
+ return {
+ isEmpty: false,
+ max: this.max,
+ min: this.min
+ };
+ },
+
+ /**
+ * Returns a slice of |sortedArray| that intersects with this range
+ * inclusively.
+ * If the range does not have a min, it is treated as unbounded from below.
+ * Similarly, if max is undefined, the range is unbounded from above.
+ *
+ * @param {Array} sortedArray The sorted array of elements to be filtered.
+ * @param {Funcation=} opt_keyFunc A function that extracts a numeric value,
+ * to be used in comparisons, from an element of the array. If not
+ * specified, array elements themselves will be used.
+ * @param {Object=} opt_this An optional this argument to be passed to
+ * opt_keyFunc.
+ */
+ filterArray(sortedArray, opt_keyFunc, opt_this) {
+ if (this.isEmpty_) return [];
+
+ const keyFunc = opt_keyFunc || (x => x);
+ function getValue(obj) {
+ return keyFunc.call(opt_this, obj);
+ }
+
+ const first = tr.b.findFirstTrueIndexInSortedArray(sortedArray,
+ obj => this.min_ === undefined || this.min_ <= getValue(obj));
+ const last = tr.b.findFirstTrueIndexInSortedArray(sortedArray,
+ obj => this.max_ !== undefined && this.max_ < getValue(obj));
+ return sortedArray.slice(first, last);
+ }
+ };
+
+ Range.fromDict = function(d) {
+ if (d.isEmpty === true) return new Range();
+ if (d.isEmpty === false) {
+ const range = new Range();
+ range.min = d.min;
+ range.max = d.max;
+ return range;
+ }
+ throw new Error('Not a range');
+ };
+
+ Range.fromExplicitRange = function(min, max) {
+ const range = new Range();
+ range.min = min;
+ range.max = max;
+ return range;
+ };
+
+ Range.compareByMinTimes = function(a, b) {
+ if (!a.isEmpty && !b.isEmpty) return a.min_ - b.min_;
+
+ if (a.isEmpty && !b.isEmpty) return -1;
+
+ if (!a.isEmpty && b.isEmpty) return 1;
+
+ return 0;
+ };
+
+ /**
+ * Subtracts the intersection of |rangeA| and |rangeB| from |rangeA| and
+ * returns the remaining ranges as return. |rangeA| and |rangeB| are
+ * not changed during the subtraction.
+ *
+ * rangeA: |==========|
+ * rangeB: |===|
+ * result: |==| |===|
+ *
+ * @param {tr.b.math.Range} rangeA
+ * @param {tr.b.math.Range} rangeB
+ * @return {Array.<tr.b.math.Range>} An array of ranges which is the result of
+ * the subtraction.
+ */
+ Range.findDifference = function(rangeA, rangeB) {
+ if (!rangeA || rangeA.duration < 0 || !rangeB || rangeB.duration < 0) {
+ throw new Error(`Couldn't subtract ranges`);
+ }
+ const resultRanges = [];
+
+ if (rangeA.isEmpty) return resultRanges;
+ if (rangeB.isEmpty) return [rangeA.clone()];
+
+ const intersection = rangeA.findIntersection(rangeB);
+ if (intersection.isEmpty) {
+ return [rangeA.clone()];
+ }
+ if (rangeA.duration === 0 && rangeB.duration === 0) {
+ if (intersection.empty) return [rangeA.clone()];
+ else if (intersection.duration === 0) return resultRanges;
+ throw new Error(`Two points' intersection can only be a point or empty`);
+ }
+
+ // rangeA: |==========|
+ // rangeB: |===|
+ // result: |==| |===|
+ const leftRange = tr.b.math.Range.fromExplicitRange(
+ rangeA.min, intersection.min);
+ if (leftRange.duration > 0) {
+ resultRanges.push(leftRange);
+ }
+ const rightRange = tr.b.math.Range.fromExplicitRange(
+ intersection.max, rangeA.max);
+ if (rightRange.duration > 0) {
+ resultRanges.push(rightRange);
+ }
+ return resultRanges;
+ };
+
+ Range.PERCENT_RANGE = Range.fromExplicitRange(0, 1);
+ Object.freeze(Range.PERCENT_RANGE);
+
+ return {
+ Range,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/range_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/range_test.html
new file mode 100644
index 00000000000..595e4799a0b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/range_test.html
@@ -0,0 +1,591 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Range = tr.b.math.Range;
+
+ test('addValue', function() {
+ const range = new Range();
+ assert.isTrue(range.isEmpty);
+ range.addValue(1);
+ assert.isFalse(range.isEmpty);
+ assert.strictEqual(1, range.min);
+ assert.strictEqual(1, range.max);
+
+ range.addValue(2);
+ assert.isFalse(range.isEmpty);
+ assert.strictEqual(1, range.min);
+ assert.strictEqual(2, range.max);
+ });
+
+ test('addNonEmptyRange', function() {
+ const r1 = new Range();
+ r1.addValue(1);
+ r1.addValue(2);
+
+ const r = new Range();
+ r.addRange(r1);
+ assert.strictEqual(1, r.min);
+ assert.strictEqual(2, r.max);
+
+ const r2 = Range.fromDict(r.toJSON());
+ assert.strictEqual(r2.isEmpty, r.isEmpty);
+ assert.strictEqual(r2.max, r.max);
+ assert.strictEqual(r2.min, r.min);
+ });
+
+ test('addEmptyRange', function() {
+ const r1 = new Range();
+
+ const r = new Range();
+ r.addRange(r1);
+ assert.isTrue(r.isEmpty);
+ assert.isUndefined(r.min);
+ assert.isUndefined(r.max);
+
+ const r2 = Range.fromDict(r.toJSON());
+ assert.strictEqual(r2.isEmpty, r.isEmpty);
+ assert.isUndefined(r2.max);
+ assert.isUndefined(r2.min);
+ });
+
+ test('addRangeToRange', function() {
+ const r1 = new Range();
+ r1.addValue(1);
+ r1.addValue(2);
+
+ const r = new Range();
+ r.addValue(3);
+ r.addRange(r1);
+
+ assert.isFalse(r.isEmpty);
+ assert.strictEqual(1, r.min);
+ assert.strictEqual(3, r.max);
+ });
+
+ test('containsRange', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = Range.fromExplicitRange(1, 2);
+
+ assert.isTrue(r1.containsRangeInclusive(r2));
+ assert.isFalse(r2.containsRangeInclusive(r1));
+ assert.isTrue(r1.containsRangeExclusive(r2));
+ assert.isFalse(r2.containsRangeExclusive(r1));
+ });
+
+ test('containsRange_emptyRange', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = new Range();
+
+ assert.isFalse(r1.containsRangeInclusive(r2));
+ assert.isFalse(r2.containsRangeInclusive(r1));
+ assert.isFalse(r1.containsRangeExclusive(r2));
+ assert.isFalse(r2.containsRangeExclusive(r1));
+ });
+
+ test('containsRange_overlapping', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = Range.fromExplicitRange(2, 4);
+
+ assert.isFalse(r1.containsRangeInclusive(r2));
+ assert.isFalse(r2.containsRangeInclusive(r1));
+ assert.isFalse(r1.containsRangeExclusive(r2));
+ assert.isFalse(r2.containsRangeExclusive(r1));
+ });
+
+ test('containsRange_disjoint', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(3, 5);
+
+ assert.isFalse(r1.containsRangeInclusive(r2));
+ assert.isFalse(r2.containsRangeInclusive(r1));
+ assert.isFalse(r1.containsRangeExclusive(r2));
+ assert.isFalse(r2.containsRangeExclusive(r1));
+ });
+
+ test('containsRange_singlePointRange', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(1, 1);
+
+ assert.isTrue(r1.containsRangeInclusive(r2));
+ assert.isFalse(r2.containsRangeInclusive(r1));
+ assert.isTrue(r1.containsRangeExclusive(r2));
+ assert.isFalse(r2.containsRangeExclusive(r1));
+ });
+
+ test('containsRange_singlePointRangeAtBorder', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(2, 2);
+
+ assert.isTrue(r1.containsRangeInclusive(r2));
+ assert.isFalse(r2.containsRangeInclusive(r1));
+ assert.isFalse(r1.containsRangeExclusive(r2));
+ assert.isFalse(r2.containsRangeExclusive(r1));
+ });
+
+ test('containsExplicitRange', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = Range.fromExplicitRange(1, 2);
+
+ assert.isTrue(r1.containsExplicitRangeInclusive(1, 2));
+ assert.isFalse(r2.containsExplicitRangeInclusive(0, 3));
+ assert.isTrue(r1.containsExplicitRangeExclusive(1, 2));
+ assert.isFalse(r2.containsExplicitRangeExclusive(0, 3));
+ });
+
+ test('containsExplicitRange_overlapping', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = Range.fromExplicitRange(2, 4);
+
+ assert.isFalse(r1.containsExplicitRangeInclusive(2, 4));
+ assert.isFalse(r2.containsExplicitRangeInclusive(0, 3));
+ assert.isFalse(r1.containsExplicitRangeExclusive(2, 4));
+ assert.isFalse(r2.containsExplicitRangeExclusive(0, 3));
+ });
+
+ test('containsExplicitRange_disjoint', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(3, 5);
+
+ assert.isFalse(r1.containsExplicitRangeInclusive(3, 5));
+ assert.isFalse(r2.containsExplicitRangeInclusive(0, 2));
+ assert.isFalse(r1.containsExplicitRangeExclusive(3, 5));
+ assert.isFalse(r2.containsExplicitRangeExclusive(0, 2));
+ });
+
+ test('containsExplicitRange_singlePointRange', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(1, 1);
+
+ assert.isTrue(r1.containsExplicitRangeInclusive(1, 1));
+ assert.isFalse(r2.containsExplicitRangeInclusive(0, 2));
+ assert.isTrue(r1.containsExplicitRangeExclusive(1, 1));
+ assert.isFalse(r2.containsExplicitRangeExclusive(0, 2));
+ });
+
+ test('containsExplicitRange_singlePointRangeAtBorder', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(2, 2);
+
+ assert.isTrue(r1.containsExplicitRangeInclusive(2, 2));
+ assert.isFalse(r2.containsExplicitRangeInclusive(0, 2));
+ assert.isFalse(r1.containsExplicitRangeExclusive(2, 2));
+ assert.isFalse(r2.containsExplicitRangeExclusive(0, 2));
+ });
+
+ test('intersectsRange', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = Range.fromExplicitRange(1, 2);
+
+ assert.isTrue(r1.intersectsRangeInclusive(r2));
+ assert.isTrue(r2.intersectsRangeInclusive(r1));
+ assert.isTrue(r1.intersectsRangeExclusive(r2));
+ assert.isTrue(r2.intersectsRangeExclusive(r1));
+ });
+
+ test('intersectsRange_emptyRange', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = new Range();
+
+ assert.isFalse(r1.intersectsRangeInclusive(r2));
+ assert.isFalse(r2.intersectsRangeInclusive(r1));
+ assert.isFalse(r1.intersectsRangeExclusive(r2));
+ assert.isFalse(r2.intersectsRangeExclusive(r1));
+ });
+
+ test('intersectsRange_overlapping', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = Range.fromExplicitRange(2, 4);
+
+ assert.isTrue(r1.intersectsRangeInclusive(r2));
+ assert.isTrue(r2.intersectsRangeInclusive(r1));
+ assert.isTrue(r1.intersectsRangeExclusive(r2));
+ assert.isTrue(r2.intersectsRangeExclusive(r1));
+ });
+
+ test('intersectsRange_disjoint', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(3, 5);
+
+ assert.isFalse(r1.intersectsRangeInclusive(r2));
+ assert.isFalse(r2.intersectsRangeInclusive(r1));
+ assert.isFalse(r1.intersectsRangeExclusive(r2));
+ assert.isFalse(r2.intersectsRangeExclusive(r1));
+ });
+
+ test('intersectsRange_singlePointRange', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(1, 1);
+
+ assert.isTrue(r1.intersectsRangeInclusive(r2));
+ assert.isTrue(r2.intersectsRangeInclusive(r1));
+ assert.isTrue(r1.intersectsRangeExclusive(r2));
+ assert.isTrue(r2.intersectsRangeExclusive(r1));
+ });
+
+ test('intersectsRange_singlePointRangeAtBorder', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(2, 2);
+
+ assert.isTrue(r1.intersectsRangeInclusive(r2));
+ assert.isTrue(r2.intersectsRangeInclusive(r1));
+ assert.isFalse(r1.intersectsRangeExclusive(r2));
+ assert.isFalse(r2.intersectsRangeExclusive(r1));
+ });
+
+ test('intersectsExplicitRange', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = Range.fromExplicitRange(1, 2);
+
+ assert.isTrue(r1.intersectsExplicitRangeInclusive(1, 2));
+ assert.isTrue(r2.intersectsExplicitRangeInclusive(0, 3));
+ assert.isTrue(r1.intersectsExplicitRangeExclusive(1, 2));
+ assert.isTrue(r2.intersectsExplicitRangeExclusive(0, 3));
+ });
+
+ test('intersectsExplicitRange_overlapping', function() {
+ const r1 = Range.fromExplicitRange(0, 3);
+ const r2 = Range.fromExplicitRange(2, 4);
+
+ assert.isTrue(r1.intersectsExplicitRangeInclusive(2, 4));
+ assert.isTrue(r2.intersectsExplicitRangeInclusive(0, 3));
+ assert.isTrue(r1.intersectsExplicitRangeExclusive(2, 4));
+ assert.isTrue(r2.intersectsExplicitRangeExclusive(0, 3));
+ });
+
+ test('intersectsExplicitRange_disjoint', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(3, 5);
+
+ assert.isFalse(r1.intersectsExplicitRangeInclusive(3, 5));
+ assert.isFalse(r2.intersectsExplicitRangeInclusive(0, 2));
+ assert.isFalse(r1.intersectsExplicitRangeExclusive(3, 5));
+ assert.isFalse(r2.intersectsExplicitRangeExclusive(0, 2));
+ });
+
+ test('intersectsExplicitRange_singlePointRange', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(1, 1);
+
+ assert.isTrue(r1.intersectsExplicitRangeInclusive(1, 1));
+ assert.isTrue(r2.intersectsExplicitRangeInclusive(0, 2));
+ assert.isTrue(r1.intersectsExplicitRangeExclusive(1, 1));
+ assert.isTrue(r2.intersectsExplicitRangeExclusive(0, 2));
+ });
+
+ test('intersectsExplicitRange_singlePointRangeAtBorder', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(2, 2);
+
+ assert.isTrue(r1.intersectsExplicitRangeInclusive(2, 2));
+ assert.isTrue(r2.intersectsExplicitRangeInclusive(0, 2));
+ assert.isFalse(r1.intersectsExplicitRangeExclusive(2, 2));
+ assert.isFalse(r2.intersectsExplicitRangeExclusive(0, 2));
+ });
+
+ test('duration', function() {
+ assert.strictEqual(Range.fromExplicitRange(2, 4).duration, 2);
+ });
+
+ test('duration_singlePointRange', function() {
+ assert.strictEqual(Range.fromExplicitRange(2, 2).duration, 0);
+ });
+
+ test('duration_emptyRange', function() {
+ assert.strictEqual(new Range().duration, 0);
+ });
+
+ test('findIntersection_overlapping', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(1, 3);
+
+ const result = Range.fromExplicitRange(1, 2);
+ assert.deepEqual(r1.findIntersection(r2), result);
+ assert.deepEqual(r2.findIntersection(r1), result);
+ });
+
+ test('findIntersection_bordering', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(2, 4);
+
+ const result = Range.fromExplicitRange(2, 2);
+ assert.deepEqual(r1.findIntersection(r2), result);
+ assert.deepEqual(r2.findIntersection(r1), result);
+ });
+
+ test('findIntersection_singlePointRange', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(2, 2);
+
+ const result = Range.fromExplicitRange(2, 2);
+ assert.deepEqual(r1.findIntersection(r2), result);
+ assert.deepEqual(r2.findIntersection(r1), result);
+ });
+
+ test('findIntersection_disjoint', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = Range.fromExplicitRange(3, 5);
+
+ assert.isTrue(r1.findIntersection(r2).isEmpty);
+ assert.isTrue(r2.findIntersection(r1).isEmpty);
+ });
+
+ test('findIntersection_emptyRange', function() {
+ const r1 = Range.fromExplicitRange(0, 2);
+ const r2 = new Range();
+
+ assert.isTrue(r1.findIntersection(r2).isEmpty);
+ assert.isTrue(r2.findIntersection(r1).isEmpty);
+ });
+
+ test('findExplicitIntersectionDuration_overlapping', function() {
+ const r = Range.fromExplicitRange(2, 4);
+ assert.strictEqual(1, r.findExplicitIntersectionDuration(1, 3));
+ assert.strictEqual(1, r.findExplicitIntersectionDuration(3, 5));
+ assert.strictEqual(2, r.findExplicitIntersectionDuration(0, 5));
+ });
+
+ test('findExplicitIntersectionDuration_invalidOtherRange', function() {
+ const r = Range.fromExplicitRange(2, 4);
+ assert.strictEqual(0, r.findExplicitIntersectionDuration(3, 1));
+ assert.strictEqual(0, r.findExplicitIntersectionDuration(5, 3));
+ });
+
+ test('findExplicitIntersectionDuration_disjoint', function() {
+ const r = Range.fromExplicitRange(2, 4);
+ assert.strictEqual(0, r.findExplicitIntersectionDuration(0, 1));
+ assert.strictEqual(0, r.findExplicitIntersectionDuration(4.5, 5));
+ });
+
+ test('filter_numericField', function() {
+ const r = Range.fromExplicitRange(2, 3);
+ const array = [{start: 1},
+ {start: 2},
+ {start: 3},
+ {start: 4}];
+ assert.deepEqual([{start: 2}, {start: 3}], r.filterArray(
+ array, function(value) {return value.start;}));
+ });
+
+ test('filter_noNumericField', function() {
+ const r = Range.fromExplicitRange(2, 3);
+ assert.deepEqual([2, 3], r.filterArray([1, 2, 3, 4]));
+ });
+
+ test('filter_empty', function() {
+ const r = new Range();
+ assert.deepEqual([], r.filterArray([1, 2, 3, 4]));
+ });
+
+ test('filter_oneSided', function() {
+ const r = new Range();
+ r.min = 2;
+ assert.deepEqual([2, 3, 4], r.filterArray([1, 2, 3, 4]));
+ });
+
+ test('left_boundary_corner_case1', function() {
+ const r = Range.fromExplicitRange(1, 2);
+ const array = [{start: 1},
+ {start: 2},
+ {start: 3},
+ {start: 4}];
+ assert.deepEqual([{start: 1}, {start: 2}], r.filterArray(
+ array, function(value) {return value.start;}));
+ });
+
+ test('left_boundary_corner_case2', function() {
+ const r = Range.fromExplicitRange(0, 2);
+ const array = [{start: 1},
+ {start: 2},
+ {start: 3},
+ {start: 4}];
+ assert.deepEqual([{start: 1}, {start: 2}], r.filterArray(
+ array, function(value) {return value.start;}));
+ });
+
+ test('left_boundary_corner_case3', function() {
+ const r = Range.fromExplicitRange(1, 1);
+ const array = [{start: 1},
+ {start: 2},
+ {start: 3},
+ {start: 4}];
+ assert.deepEqual([{start: 1}], r.filterArray(
+ array, function(value) {return value.start;}));
+ });
+
+ test('left_boundary_corner_case4', function() {
+ const r = Range.fromExplicitRange(0, 0);
+ const array = [{start: 1},
+ {start: 2},
+ {start: 3},
+ {start: 4}];
+ assert.deepEqual([], r.filterArray(
+ array, function(value) {return value.start;}));
+ });
+
+ test('right_boundary_corner_case1', function() {
+ const r = Range.fromExplicitRange(4, 5);
+ const array = [{start: 1},
+ {start: 2},
+ {start: 3},
+ {start: 4}];
+ assert.deepEqual([{start: 4}], r.filterArray(
+ array, function(value) {return value.start;}));
+ });
+
+ test('right_boundary_corner_case2', function() {
+ const r = Range.fromExplicitRange(4, 4);
+ const array = [{start: 1},
+ {start: 2},
+ {start: 3},
+ {start: 4}];
+ assert.deepEqual([{start: 4}], r.filterArray(
+ array, function(value) {return value.start;}));
+ });
+
+ test('right_boundary_corner_case3', function() {
+ const r = Range.fromExplicitRange(5, 5);
+ const array = [{start: 1},
+ {start: 2},
+ {start: 3},
+ {start: 4}];
+ assert.deepEqual([], r.filterArray(
+ array, function(value) {return value.start;}));
+ });
+
+
+ test('clone_empty', function() {
+ const range = new Range();
+ const cloned = range.clone();
+ assert.deepEqual(cloned, range);
+ });
+
+ test('clone_normal', function() {
+ const range = Range.fromExplicitRange(1, 2);
+ const cloned = range.clone();
+ assert.deepEqual(range, cloned);
+ range.min = 0;
+ assert.strictEqual(1, cloned.min);
+ });
+
+ test('findDifference_normal', function() {
+ // [{a,min, a.max}, {b.min, b.max}, [{c1.min, c1.max}, ...]]
+ const truthTable = [
+ [[50, 100], [-Infinity, 0], [[50, 100]]],
+ [[50, 100], [-Infinity, 75], [[75, 100]]],
+ [[50, 100], [-Infinity, Infinity], []],
+
+ [[50, 100], [0, 0], [[50, 100]]],
+ [[50, 100], [0, 25], [[50, 100]]],
+ [[50, 100], [0, 50], [[50, 100]]],
+ [[50, 100], [0, 75], [[75, 100]]],
+ [[50, 100], [0, 100], []],
+ [[50, 100], [0, 150], []],
+ [[50, 100], [50, 50], [[50, 100]]],
+ [[50, 100], [50, 75], [[75, 100]]],
+ [[50, 100], [50, 100], []],
+ [[50, 100], [50, 150], []],
+ [[50, 100], [75, 75], [[50, 75], [75, 100]]],
+ [[50, 100], [75, 100], [[50, 75]]],
+ [[50, 100], [75, 150], [[50, 75]]],
+
+ [[50, 50], [0, 0], [[50, 50]]],
+ [[50, 50], [0, 25], [[50, 50]]],
+ [[50, 50], [0, 50], []],
+ [[50, 50], [50, 50], []],
+ [[50, 50], [0, 75], []],
+
+ [[50, Infinity], [0, 0], [[50, Infinity]]],
+ [[50, Infinity], [0, 25], [[50, Infinity]]],
+ [[50, Infinity], [0, 50], [[50, Infinity]]],
+ [[50, Infinity], [0, 75], [[75, Infinity]]],
+ [[50, Infinity], [0, 100], [[100, Infinity]]],
+ [[50, Infinity], [50, 50], [[50, Infinity]]],
+ [[50, Infinity], [50, 75], [[75, Infinity]]],
+ [[50, Infinity], [50, 100], [[100, Infinity]]],
+ [[50, Infinity], [75, 75], [[50, 75], [75, Infinity]]],
+ [[50, Infinity], [75, 100], [[50, 75], [100, Infinity]]],
+ ];
+
+ for (const row of truthTable) {
+ const ranges = Range.findDifference(
+ Range.fromExplicitRange(row[0][0], row[0][1]),
+ Range.fromExplicitRange(row[1][0], row[1][1]));
+ const simpleRanges = [];
+ for (const range of ranges) {
+ simpleRanges.push([range.min, range.max]);
+ }
+ assert.deepEqual(simpleRanges, row[2], 'range(' + row[0] +
+ ') subtracted by ' + 'range(' + row[1] + ') should be range(' +
+ row[2] + ').');
+ }
+ });
+
+ test('findDifference_AUndefined', function() {
+ const rangeA = undefined;
+ const rangeB = Range.fromExplicitRange(1, 2);
+ assert.throws(function() {Range.findDifference(rangeA, rangeB);});
+ });
+
+ test('findDifference_BUndefined', function() {
+ const rangeA = Range.fromExplicitRange(1, 2);
+ const rangeB = undefined;
+ assert.throws(function() {Range.findDifference(rangeA, rangeB);});
+ });
+
+ test('findDifference_EmptyMinusNormal', function() {
+ const rangeA = new Range();
+ const rangeB = Range.fromExplicitRange(1, 2);
+ const result = Range.findDifference(rangeA, rangeB);
+ assert.deepEqual(result, []);
+ });
+
+ test('findDifference_0MinusNormal', function() {
+ const rangeA = Range.fromExplicitRange(0, 0);
+ const rangeB = Range.fromExplicitRange(1, 2);
+ const result = Range.findDifference(rangeA, rangeB);
+ assert.deepEqual(result, [rangeA]);
+ });
+
+ test('findDifference_NormalMinus0', function() {
+ const rangeA = Range.fromExplicitRange(1, 2);
+ const rangeB = Range.fromExplicitRange(0, 0);
+ const result = Range.findDifference(rangeA, rangeB);
+ assert.deepEqual([rangeA], result);
+ result.min = 5;
+ assert.strictEqual(rangeA.min, 1);
+ });
+
+ test('findDifference_NormalMinusEmpty', function() {
+ const rangeA = Range.fromExplicitRange(1, 2);
+ const rangeB = new Range();
+ const result = Range.findDifference(rangeA, rangeB);
+ assert.deepEqual([rangeA], result);
+ result.min = 5;
+ assert.strictEqual(rangeA.min, 1);
+ });
+
+ test('findDifference_pointMinusEmpty', function() {
+ const rangeA = Range.fromExplicitRange(1, 1);
+ const rangeB = new Range();
+ const result = Range.findDifference(rangeA, rangeB);
+ assert.deepEqual(result, [rangeA]);
+ });
+
+ test('findDifference_emptyMinusPoint', function() {
+ const rangeA = new Range();
+ const rangeB = Range.fromExplicitRange(1, 1);
+ const result = Range.findDifference(rangeA, rangeB);
+ assert.deepEqual(result, []);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/range_utils.html b/chromium/third_party/catapult/tracing/tracing/base/math/range_utils.html
new file mode 100644
index 00000000000..60c5fdd2954
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/range_utils.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides event merging functionality for grouping/analysis.
+ */
+tr.exportTo('tr.b.math', function() {
+ function convertEventsToRanges(events) {
+ return events.map(function(event) {
+ return tr.b.math.Range.fromExplicitRange(event.start, event.end);
+ });
+ }
+
+ function mergeRanges(inRanges, mergeThreshold, mergeFunction) {
+ const remainingEvents = inRanges.slice();
+ remainingEvents.sort(function(x, y) {
+ return x.min - y.min;
+ });
+
+ if (remainingEvents.length <= 1) {
+ const merged = [];
+ if (remainingEvents.length === 1) {
+ merged.push(mergeFunction(remainingEvents));
+ }
+ return merged;
+ }
+
+ const mergedEvents = [];
+
+ let currentMergeBuffer = [];
+ let rightEdge;
+ function beginMerging() {
+ currentMergeBuffer.push(remainingEvents[0]);
+ remainingEvents.splice(0, 1);
+ rightEdge = currentMergeBuffer[0].max;
+ }
+
+ function flushCurrentMergeBuffer() {
+ if (currentMergeBuffer.length === 0) return;
+
+ mergedEvents.push(mergeFunction(currentMergeBuffer));
+ currentMergeBuffer = [];
+
+ // Refill merge buffer if needed.
+ if (remainingEvents.length !== 0) beginMerging();
+ }
+
+ beginMerging();
+
+ while (remainingEvents.length) {
+ const currentEvent = remainingEvents[0];
+
+ const distanceFromRightEdge = currentEvent.min - rightEdge;
+ if (distanceFromRightEdge < mergeThreshold) {
+ rightEdge = Math.max(rightEdge, currentEvent.max);
+ remainingEvents.splice(0, 1);
+ currentMergeBuffer.push(currentEvent);
+ continue;
+ }
+
+ // Too big a gap.
+ flushCurrentMergeBuffer();
+ }
+ flushCurrentMergeBuffer();
+
+ return mergedEvents;
+ }
+
+ // Pass in |opt_totalRange| in order to find empty ranges before the first of
+ // |inRanges| and after the last of |inRanges|.
+ function findEmptyRangesBetweenRanges(inRanges, opt_totalRange) {
+ if (opt_totalRange && opt_totalRange.isEmpty) opt_totalRange = undefined;
+
+ const emptyRanges = [];
+ if (!inRanges.length) {
+ if (opt_totalRange) emptyRanges.push(opt_totalRange);
+ return emptyRanges;
+ }
+
+ inRanges = inRanges.slice();
+ inRanges.sort(function(x, y) {
+ return x.min - y.min;
+ });
+ if (opt_totalRange &&
+ (opt_totalRange.min < inRanges[0].min)) {
+ emptyRanges.push(tr.b.math.Range.fromExplicitRange(
+ opt_totalRange.min, inRanges[0].min));
+ }
+
+ inRanges.forEach(function(range, index) {
+ for (let otherIndex = 0; otherIndex < inRanges.length; ++otherIndex) {
+ if (index === otherIndex) continue;
+ const other = inRanges[otherIndex];
+
+ if (other.min > range.max) {
+ // |inRanges| is sorted, so |other| is the first range after |range|,
+ // and there is an empty range between them.
+ emptyRanges.push(tr.b.math.Range.fromExplicitRange(
+ range.max, other.min));
+ return;
+ }
+ // Otherwise, |other| starts before |range| ends, so |other| might
+ // possibly contain the end of |range|.
+
+ if (other.max > range.max) {
+ // |other| does contain the end of |range|, so no empty range starts
+ // at the end of this |range|.
+ return;
+ }
+ }
+ if (opt_totalRange && (range.max < opt_totalRange.max)) {
+ emptyRanges.push(tr.b.math.Range.fromExplicitRange(
+ range.max, opt_totalRange.max));
+ }
+ });
+ return emptyRanges;
+ }
+
+ return {
+ convertEventsToRanges,
+ findEmptyRangesBetweenRanges,
+ mergeRanges,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/range_utils_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/range_utils_test.html
new file mode 100644
index 00000000000..183a90df6f0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/range_utils_test.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function simpleMerger(events) {
+ return {
+ min: events[0].min,
+ max: events[events.length - 1].max
+ };
+ }
+ test('simple', function() {
+ const inEvents = [
+ {min: 0, max: 100},
+ {min: 100, max: 120},
+ {min: 200, max: 220}
+ ];
+
+ const merged = tr.b.math.mergeRanges(inEvents, 50, simpleMerger);
+
+ assert.strictEqual(merged.length, 2);
+ assert.deepEqual(merged[0], {min: 0, max: 120});
+ assert.deepEqual(merged[1], {min: 200, max: 220});
+ });
+
+ test('overlapping', function() {
+ const inEvents = [
+ {min: 0, max: 100},
+ {min: 80, max: 120},
+ {min: 200, max: 220}
+ ];
+
+ const merged = tr.b.math.mergeRanges(inEvents, 50, simpleMerger);
+
+ assert.strictEqual(merged.length, 2);
+ assert.deepEqual(merged[0], {min: 0, max: 120});
+ assert.deepEqual(merged[1], {min: 200, max: 220});
+ });
+
+ test('middleOneIsSmall', function() {
+ const inEvents = [
+ {min: 0, max: 100},
+ {min: 40, max: 50},
+ {min: 100, max: 120}
+ ];
+
+ const merged = tr.b.math.mergeRanges(inEvents, 50, simpleMerger);
+
+ assert.strictEqual(merged.length, 1);
+ assert.deepEqual(merged[0], {min: 0, max: 120});
+ });
+
+ test('firstEventIsSplitPoint', function() {
+ const inEvents = [
+ {min: 0, max: 100},
+ {min: 150, max: 200}
+ ];
+
+ const merged = tr.b.math.mergeRanges(inEvents, 25, simpleMerger);
+
+ assert.strictEqual(merged.length, 2);
+ assert.deepEqual(merged[0], {min: 0, max: 100});
+ assert.deepEqual(merged[1], {min: 150, max: 200});
+ });
+
+ test('mergeSingleEvent', function() {
+ const inEvents = [
+ {min: 0, max: 100}
+ ];
+
+ let mergeCount = 0;
+ tr.b.math.mergeRanges(inEvents, 25, function(events) {
+ assert.deepEqual(events, inEvents);
+ mergeCount++;
+ });
+ assert.strictEqual(mergeCount, 1);
+ });
+
+ test('zeroDurationSplit', function() {
+ let inEvents = [0, 10, 20, 50, 60];
+ inEvents = inEvents.map(function(event) {
+ return tr.b.math.Range.fromExplicitRange(event, event);
+ });
+ const timestampMerger = function(timestamps) {
+ return {
+ min: timestamps[0].min,
+ max: timestamps[timestamps.length - 1].max
+ };
+ };
+ const merged = tr.b.math.mergeRanges(inEvents, 15, timestampMerger);
+ assert.strictEqual(merged.length, 2);
+ assert.deepEqual(merged[0], {min: 0, max: 20});
+ assert.deepEqual(merged[1], {min: 50, max: 60});
+ });
+
+ test('findEmptyRangesBetweenRanges', function() {
+ const events = [
+ {min: 2, max: 4},
+ {min: 1, max: 3},
+ {min: 6, max: 8}
+ ];
+ const ranges = tr.b.math.findEmptyRangesBetweenRanges(
+ events, {min: 0, max: 10});
+ assert.strictEqual(3, ranges.length);
+ assert.strictEqual(0, ranges[0].min);
+ assert.strictEqual(1, ranges[0].max);
+ assert.strictEqual(4, ranges[1].min);
+ assert.strictEqual(6, ranges[1].max);
+ assert.strictEqual(8, ranges[2].min);
+ assert.strictEqual(10, ranges[2].max);
+ });
+
+ test('findEmptyRangesWithEmptyInput', function() {
+ let ranges = tr.b.math.findEmptyRangesBetweenRanges(
+ [], {min: 0, max: 10});
+ assert.strictEqual(1, ranges.length);
+ assert.strictEqual(0, ranges[0].min);
+ assert.strictEqual(10, ranges[0].max);
+
+ ranges = tr.b.math.findEmptyRangesBetweenRanges([]);
+ assert.strictEqual(0, ranges.length);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/rect.html b/chromium/third_party/catapult/tracing/tracing/base/math/rect.html
new file mode 100644
index 00000000000..194b975a27b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/rect.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b.math', function() {
+ /**
+ * Tracks a 2D bounding box.
+ * @constructor
+ */
+ function Rect() {
+ this.x = 0;
+ this.y = 0;
+ this.width = 0;
+ this.height = 0;
+ }
+
+ Rect.fromXYWH = function(x, y, w, h) {
+ const rect = new Rect();
+ rect.x = x;
+ rect.y = y;
+ rect.width = w;
+ rect.height = h;
+ return rect;
+ };
+
+ Rect.fromArray = function(ary) {
+ if (ary.length !== 4) {
+ throw new Error('ary.length must be 4');
+ }
+ const rect = new Rect();
+ rect.x = ary[0];
+ rect.y = ary[1];
+ rect.width = ary[2];
+ rect.height = ary[3];
+ return rect;
+ };
+
+ Rect.prototype = {
+ __proto__: Object.prototype,
+
+ get left() {
+ return this.x;
+ },
+
+ get top() {
+ return this.y;
+ },
+
+ get right() {
+ return this.x + this.width;
+ },
+
+ get bottom() {
+ return this.y + this.height;
+ },
+
+ toString() {
+ return 'Rect(' + this.x + ', ' + this.y + ', ' +
+ this.width + ', ' + this.height + ')';
+ },
+
+ toArray() {
+ return [this.x, this.y, this.width, this.height];
+ },
+
+ clone() {
+ const rect = new Rect();
+ rect.x = this.x;
+ rect.y = this.y;
+ rect.width = this.width;
+ rect.height = this.height;
+ return rect;
+ },
+
+ enlarge(pad) {
+ const rect = new Rect();
+ this.enlargeFast(rect, pad);
+ return rect;
+ },
+
+ enlargeFast(out, pad) {
+ out.x = this.x - pad;
+ out.y = this.y - pad;
+ out.width = this.width + 2 * pad;
+ out.height = this.height + 2 * pad;
+ return out;
+ },
+
+ size() {
+ return {width: this.width, height: this.height};
+ },
+
+ scale(s) {
+ const rect = new Rect();
+ this.scaleFast(rect, s);
+ return rect;
+ },
+
+ scaleSize(s) {
+ return Rect.fromXYWH(this.x, this.y, this.width * s, this.height * s);
+ },
+
+ scaleFast(out, s) {
+ out.x = this.x * s;
+ out.y = this.y * s;
+ out.width = this.width * s;
+ out.height = this.height * s;
+ return out;
+ },
+
+ translate(v) {
+ const rect = new Rect();
+ this.translateFast(rect, v);
+ return rect;
+ },
+
+ translateFast(out, v) {
+ out.x = this.x + v[0];
+ out.y = this.x + v[1];
+ out.width = this.width;
+ out.height = this.height;
+ return out;
+ },
+
+ asUVRectInside(containingRect) {
+ const rect = new Rect();
+ rect.x = (this.x - containingRect.x) / containingRect.width;
+ rect.y = (this.y - containingRect.y) / containingRect.height;
+ rect.width = this.width / containingRect.width;
+ rect.height = this.height / containingRect.height;
+ return rect;
+ },
+
+ intersects(that) {
+ let ok = true;
+ ok &= this.x < that.right;
+ ok &= this.right > that.x;
+ ok &= this.y < that.bottom;
+ ok &= this.bottom > that.y;
+ return ok;
+ },
+
+ equalTo(rect) {
+ return rect &&
+ (this.x === rect.x) &&
+ (this.y === rect.y) &&
+ (this.width === rect.width) &&
+ (this.height === rect.height);
+ }
+ };
+
+ return {
+ Rect,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/rect_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/rect_test.html
new file mode 100644
index 00000000000..640a7d9221f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/rect_test.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/rect.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('UVRectBasic', function() {
+ function assertRectEquals(a, b, opt_message) {
+ const ok = true;
+ if (a.x === b.x && a.y === b.y &&
+ a.width === b.width && a.height === b.height) {
+ return;
+ }
+ const message = opt_message || 'Expected "' + a.toString() +
+ '", got "' + b.toString() + '"';
+ assert.fail(a, b, message);
+ }
+ const container = tr.b.math.Rect.fromXYWH(0, 0, 10, 10);
+ const inner = tr.b.math.Rect.fromXYWH(1, 1, 8, 8);
+ const uv = inner.asUVRectInside(container);
+ assertRectEquals(uv, tr.b.math.Rect.fromXYWH(0.1, 0.1, .8, .8));
+ assert.strictEqual(10, container.size().width);
+ assert.strictEqual(10, container.size().height);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/running_statistics.html b/chromium/third_party/catapult/tracing/tracing/base/math/running_statistics.html
new file mode 100644
index 00000000000..d2dc5e5f6c5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/running_statistics.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b.math', function() {
+ /**
+ * An object of this class computes basic statistics online in O(1).
+ * Usage:
+ * 1. Create an instance.
+ * 2. Add numbers using the |add| method.
+ * 3. Query statistics.
+ * 4. Repeat from step 2.
+ */
+ class RunningStatistics {
+ constructor() {
+ this.mean_ = 0;
+ this.count_ = 0;
+ this.max_ = -Infinity;
+ this.min_ = Infinity;
+ this.sum_ = 0;
+ this.variance_ = 0;
+
+ // Mean of logarithms of absolute values of samples, or undefined if any
+ // samples were <= 0.
+ this.meanlogs_ = 0;
+ }
+
+ get count() {
+ return this.count_;
+ }
+
+ get geometricMean() {
+ if (this.meanlogs_ === undefined) return 0;
+ return Math.exp(this.meanlogs_);
+ }
+
+ get mean() {
+ if (this.count_ === 0) return undefined;
+ return this.mean_;
+ }
+
+ get max() {
+ return this.max_;
+ }
+
+ get min() {
+ return this.min_;
+ }
+
+ get sum() {
+ return this.sum_;
+ }
+
+ get variance() {
+ if (this.count_ === 0) return undefined;
+ if (this.count_ === 1) return 0;
+ return this.variance_ / (this.count_ - 1);
+ }
+
+ get stddev() {
+ if (this.count_ === 0) return undefined;
+ return Math.sqrt(this.variance);
+ }
+
+ add(x) {
+ this.count_++;
+ this.max_ = Math.max(this.max_, x);
+ this.min_ = Math.min(this.min_, x);
+ this.sum_ += x;
+
+ // The geometric mean is computed using the arithmetic mean of logarithms.
+ if (x <= 0) {
+ this.meanlogs_ = undefined;
+ } else if (this.meanlogs_ !== undefined) {
+ this.meanlogs_ += (Math.log(Math.abs(x)) - this.meanlogs_) / this.count;
+ }
+
+ // The following uses Welford's algorithm for computing running mean
+ // and variance. See http://www.johndcook.com/blog/standard_deviation.
+ if (this.count_ === 1) {
+ this.mean_ = x;
+ this.variance_ = 0;
+ } else {
+ const oldMean = this.mean_;
+ const oldVariance = this.variance_;
+ // Using the 2nd formula for updating the mean yields better precision
+ // but it doesn't work for the case oldMean is Infinity. Hence we handle
+ // that case separately.
+ if (oldMean === Infinity || oldMean === -Infinity) {
+ this.mean_ = this.sum_ / this.count_;
+ } else {
+ this.mean_ = oldMean + (x - oldMean) / this.count_;
+ }
+ this.variance_ = oldVariance + (x - oldMean) * (x - this.mean_);
+ }
+ }
+
+ merge(other) {
+ const result = new RunningStatistics();
+ result.count_ = this.count_ + other.count_;
+ result.sum_ = this.sum_ + other.sum_;
+ result.min_ = Math.min(this.min_, other.min_);
+ result.max_ = Math.max(this.max_, other.max_);
+ if (result.count === 0) {
+ result.mean_ = 0;
+ result.variance_ = 0;
+ result.meanlogs_ = 0;
+ } else {
+ // Combine the mean and the variance using the formulas from
+ // https://goo.gl/ddcAep.
+ result.mean_ = result.sum / result.count;
+ const deltaMean = (this.mean || 0) - (other.mean || 0);
+ result.variance_ = this.variance_ + other.variance_ +
+ (this.count * other.count * deltaMean * deltaMean / result.count);
+
+ // Merge the arithmetic means of logarithms of absolute values of
+ // samples, weighted by counts.
+ if (this.meanlogs_ === undefined || other.meanlogs_ === undefined) {
+ result.meanlogs_ = undefined;
+ } else {
+ result.meanlogs_ = (this.count * this.meanlogs_ +
+ other.count * other.meanlogs_) / result.count;
+ }
+ }
+ return result;
+ }
+
+ truncate(unit) {
+ this.max_ = unit.truncate(this.max_);
+ if (this.meanlogs_ !== undefined) {
+ // geomean = exp(meanlogs)
+ // meanlogs is serialized, but geomean is displayed.
+ // truncate meanlogs such that geomean is unaffected.
+ const formatted = unit.format(this.geometricMean);
+ let lo = 1;
+ let hi = 16;
+ while (lo < hi - 1) {
+ const digits = parseInt((lo + hi) / 2);
+ const test = tr.b.math.truncate(this.meanlogs_, digits);
+ if (formatted === unit.format(Math.exp(test))) {
+ hi = digits;
+ } else {
+ lo = digits;
+ }
+ }
+ const test = tr.b.math.truncate(this.meanlogs_, lo);
+ if (formatted === unit.format(Math.exp(test))) {
+ this.meanlogs_ = test;
+ } else {
+ this.meanlogs_ = tr.b.math.truncate(this.meanlogs_, hi);
+ }
+ }
+ this.mean_ = unit.truncate(this.mean_);
+ this.min_ = unit.truncate(this.min_);
+ this.sum_ = unit.truncate(this.sum_);
+ this.variance_ = unit.truncate(this.variance_);
+ }
+
+ asDict() {
+ if (!this.count) {
+ return [];
+ }
+ // It's more efficient to serialize these fields in an array. If you
+ // add any other fields, you should re-evaluate whether it would be more
+ // efficient to serialize as a dict.
+ return [
+ this.count_,
+ this.max_,
+ this.meanlogs_,
+ this.mean_,
+ this.min_,
+ this.sum_,
+ this.variance_,
+ ];
+ }
+
+ static fromDict(dict) {
+ const result = new RunningStatistics();
+ if (dict.length !== 7) {
+ return result;
+ }
+ [
+ result.count_,
+ result.max_,
+ result.meanlogs_,
+ result.mean_,
+ result.min_,
+ result.sum_,
+ result.variance_,
+ ] = dict;
+ return result;
+ }
+ }
+
+ return {
+ RunningStatistics,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/running_statistics_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/running_statistics_test.html
new file mode 100644
index 00000000000..5a06ebe5cb8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/running_statistics_test.html
@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/running_statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unit.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const RunningStatistics = tr.b.math.RunningStatistics;
+ const Statistics = tr.b.math.Statistics;
+
+ function run(data) {
+ const running = new RunningStatistics();
+ data.forEach(x => running.add(x));
+ return running;
+ }
+
+ test('truncate', function() {
+ const running = run([50, 60, 70 + (1 / 3)]);
+ assert.closeTo(59.533, running.geometricMean, 1e-3);
+ assert.strictEqual(
+ '[3,70.33333333333333,4.0865378041527345,60.11111111111111,50,' +
+ '180.33333333333331,206.74074074074068]',
+ JSON.stringify(running.asDict()));
+
+ running.truncate(tr.b.Unit.byName.unitlessNumber);
+ assert.closeTo(59.533, running.geometricMean, 1e-3);
+ assert.strictEqual(70.3333, running.max);
+ assert.strictEqual(4.086538, running.meanlogs_);
+ assert.strictEqual(60.1111, running.mean);
+ assert.strictEqual(180.3333, running.sum);
+ assert.strictEqual(206.7407, running.variance_);
+ });
+
+ test('sum', function() {
+ let data;
+ data = [];
+ assert.closeTo(Statistics.sum(data), run(data).sum, 1e-6);
+ data = [1];
+ assert.closeTo(Statistics.sum(data), run(data).sum, 1e-6);
+ data = [1, 2, 3];
+ assert.closeTo(Statistics.sum(data), run(data).sum, 1e-6);
+ data = [2, 4, 4, 2];
+ assert.closeTo(Statistics.sum(data), run(data).sum, 1e-6);
+ data = [Infinity, Infinity, Infinity, 4, 4, Infinity, 1];
+ assert.strictEqual(Statistics.sum(data), run(data).sum, Infinity);
+ data = [-Infinity, -Infinity, 2, -Infinity, 5, -Infinity];
+ assert.strictEqual(Statistics.sum(data), run(data).sum, -Infinity);
+ });
+
+ test('min', function() {
+ let data;
+ data = [];
+ assert.strictEqual(Statistics.min(data), run(data).min);
+ data = [1];
+ assert.strictEqual(Statistics.min(data), run(data).min);
+ data = [1, 2, 3];
+ assert.strictEqual(Statistics.min(data), run(data).min);
+ data = [2, 4, 4, 2];
+ assert.strictEqual(Statistics.min(data), run(data).min);
+ });
+
+ test('max', function() {
+ let data;
+ data = [];
+ assert.strictEqual(Statistics.max(data), run(data).max);
+ data = [1];
+ assert.strictEqual(Statistics.max(data), run(data).max);
+ data = [1, 2, 3];
+ assert.strictEqual(Statistics.max(data), run(data).max);
+ data = [2, 4, 4, 2];
+ assert.strictEqual(Statistics.max(data), run(data).max);
+ });
+
+ test('mean', function() {
+ let data;
+ data = [];
+ assert.strictEqual(Statistics.mean(data), run(data).mean);
+ data = [1];
+ assert.strictEqual(Statistics.mean(data), run(data).mean);
+ data = [1, 2, 3];
+ assert.closeTo(Statistics.mean(data), run(data).mean, 1e-6);
+ data = [2, 4, 4, 2];
+ assert.closeTo(Statistics.mean(data), run(data).mean, 1e-6);
+ data = [Infinity, Infinity, Infinity, 4, 4, Infinity, 1];
+ assert.strictEqual(Statistics.mean(data), run(data).mean, Infinity);
+ data = [-Infinity, -Infinity, 2, -Infinity, 5, -Infinity];
+ assert.strictEqual(Statistics.mean(data), run(data).mean, -Infinity);
+ });
+
+ test('geometricMean', function() {
+ let data;
+ data = [];
+ assert.strictEqual(Statistics.geometricMean(data), run(data).geometricMean);
+ data = [-1];
+ assert.strictEqual(Statistics.geometricMean(data), run(data).geometricMean);
+ data = [1];
+ assert.strictEqual(Statistics.geometricMean(data), run(data).geometricMean);
+ data = [1, 2, 3];
+ assert.closeTo(Statistics.geometricMean(data),
+ run(data).geometricMean, 1e-6);
+ data = [2, 4, 4, 2];
+ assert.closeTo(Statistics.geometricMean(data),
+ run(data).geometricMean, 1e-6);
+ });
+
+ test('variance', function() {
+ let data;
+ data = [];
+ assert.strictEqual(Statistics.variance(data), run(data).variance);
+ data = [1];
+ assert.strictEqual(Statistics.variance(data), run(data).variance);
+ data = [1, 2, 3];
+ assert.closeTo(Statistics.variance(data), run(data).variance, 1e-6);
+ data = [2, 4, 4, 2];
+ assert.closeTo(Statistics.variance(data), run(data).variance, 1e-6);
+ });
+
+ test('stddev', function() {
+ let data;
+ data = [];
+ assert.strictEqual(Statistics.stddev(data), run(data).stddev);
+ data = [1];
+ assert.strictEqual(Statistics.stddev(data), run(data).stddev);
+ data = [1, 2, 3];
+ assert.closeTo(Statistics.stddev(data), run(data).stddev, 1e-6);
+ data = [2, 4, 4, 2];
+ assert.closeTo(Statistics.stddev(data), run(data).stddev, 1e-6);
+ });
+
+ test('merge', function() {
+ let data1 = [];
+ let data2 = [];
+ let data = data1.concat(data2);
+ let stats = run(data1).merge(run(data2));
+ assert.strictEqual(Statistics.sum(data), stats.sum);
+ assert.strictEqual(Statistics.min(data), stats.min);
+ assert.strictEqual(Statistics.max(data), stats.max);
+ assert.strictEqual(Statistics.mean(data), stats.mean);
+ assert.strictEqual(Statistics.variance(data), stats.variance);
+ assert.strictEqual(Statistics.stddev(data), stats.stddev);
+ assert.strictEqual(Statistics.geometricMean(data), stats.geometricMean);
+
+ data1 = [];
+ data2 = [1, 2, 3];
+ data = data1.concat(data2);
+ stats = run(data1).merge(run(data2));
+ assert.strictEqual(Statistics.sum(data), stats.sum);
+ assert.strictEqual(Statistics.min(data), stats.min);
+ assert.strictEqual(Statistics.max(data), stats.max);
+ assert.strictEqual(Statistics.mean(data), stats.mean);
+ assert.closeTo(Statistics.variance(data), stats.variance, 1e-6);
+ assert.closeTo(Statistics.stddev(data), stats.stddev, 1e-6);
+ assert.closeTo(Statistics.geometricMean(data), stats.geometricMean, 1e-6);
+
+ data1 = [1, 2, 3];
+ data2 = [];
+ data = data1.concat(data2);
+ stats = run(data1).merge(run(data2));
+ assert.strictEqual(Statistics.sum(data), stats.sum);
+ assert.strictEqual(Statistics.min(data), stats.min);
+ assert.strictEqual(Statistics.max(data), stats.max);
+ assert.strictEqual(Statistics.mean(data), stats.mean);
+ assert.closeTo(Statistics.variance(data), stats.variance, 1e-6);
+ assert.closeTo(Statistics.stddev(data), stats.stddev, 1e-6);
+ assert.closeTo(Statistics.geometricMean(data), stats.geometricMean, 1e-6);
+
+ data1 = [1, 2, 3];
+ data2 = [10, 20, 100];
+ data = data1.concat(data2);
+ stats = run(data1).merge(run(data2));
+ assert.strictEqual(Statistics.sum(data), stats.sum);
+ assert.strictEqual(Statistics.min(data), stats.min);
+ assert.strictEqual(Statistics.max(data), stats.max);
+ assert.strictEqual(Statistics.mean(data), stats.mean);
+ assert.closeTo(Statistics.variance(data), stats.variance, 1e-6);
+ assert.closeTo(Statistics.stddev(data), stats.stddev, 1e-6);
+ assert.closeTo(Statistics.geometricMean(data), stats.geometricMean, 1e-6);
+
+ data1 = [1, 1, 1, 1, 1];
+ data2 = [10, 20, 10, 40];
+ data = data1.concat(data2);
+ stats = run(data1).merge(run(data2));
+ assert.strictEqual(Statistics.sum(data), stats.sum);
+ assert.strictEqual(Statistics.min(data), stats.min);
+ assert.strictEqual(Statistics.max(data), stats.max);
+ assert.strictEqual(Statistics.mean(data), stats.mean);
+ assert.closeTo(Statistics.variance(data), stats.variance, 1e-6);
+ assert.closeTo(Statistics.stddev(data), stats.stddev, 1e-6);
+ assert.closeTo(Statistics.geometricMean(data), stats.geometricMean, 1e-6);
+ });
+
+ test('serialization', function() {
+ const data = [1, 2, 3];
+ const dict = run(data).asDict();
+ const cloneDict = RunningStatistics.fromDict(dict).asDict();
+ for (let field = 0; field < dict.length; ++field) {
+ assert.closeTo(dict[field], cloneDict[field], 1e-6);
+ }
+
+ // You can change this number, but when you do, please explain in your CL
+ // description why it changed.
+ assert.strictEqual(32, JSON.stringify(dict).length);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/statistics.html b/chromium/third_party/catapult/tracing/tracing/base/math/statistics.html
new file mode 100644
index 00000000000..daa49e522f3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/statistics.html
@@ -0,0 +1,857 @@
+<!DOCTYPE html>
+<!--
+Copyright 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<script src="/mannwhitneyu/mannwhitneyu.js"></script>
+
+<script>
+'use strict';
+
+// In node, the script-src for mannwhitneyu above brings in mannwhitneyui
+// into a module, instead of into the global scope. Whereas this file
+// assumes that mannwhitneyu is in the global scope. So, in Node only, we
+// require() it in, and then take all its exports and shove them into the
+// global scope by hand.
+(function(global) {
+ if (tr.isNode) {
+ const mwuAbsPath = HTMLImportsLoader.hrefToAbsolutePath(
+ '/mannwhitneyu.js');
+ const mwuModule = require(mwuAbsPath);
+ for (const exportName in mwuModule) {
+ global[exportName] = mwuModule[exportName];
+ }
+ }
+})(this);
+</script>
+
+<script>
+'use strict';
+
+// TODO(charliea): Remove:
+/* eslint-disable catapult-camelcase */
+
+tr.exportTo('tr.b.math', function() {
+ const Statistics = {};
+
+ /* Returns the quotient, or zero if the denominator is zero.*/
+ Statistics.divideIfPossibleOrZero = function(numerator, denominator) {
+ if (denominator === 0) return 0;
+ return numerator / denominator;
+ };
+
+ Statistics.sum = function(ary, opt_func, opt_this) {
+ const func = opt_func || (x => x);
+ let ret = 0;
+ let i = 0;
+ for (const elt of ary) {
+ ret += func.call(opt_this, elt, i++);
+ }
+ return ret;
+ };
+
+ Statistics.mean = function(ary, opt_func, opt_this) {
+ const func = opt_func || (x => x);
+ let sum = 0;
+ let i = 0;
+
+ for (const elt of ary) {
+ sum += func.call(opt_this, elt, i++);
+ }
+
+ if (i === 0) return undefined;
+
+ return sum / i;
+ };
+
+ Statistics.geometricMean = function(ary, opt_func, opt_this) {
+ const func = opt_func || (x => x);
+ let i = 0;
+ let logsum = 0;
+
+ // The geometric mean is expressed as the arithmetic mean of logarithms
+ // in order to prevent overflow.
+ for (const elt of ary) {
+ const x = func.call(opt_this, elt, i++);
+ if (x <= 0) return 0;
+ logsum += Math.log(Math.abs(x));
+ }
+
+ if (i === 0) return 1;
+
+ return Math.exp(logsum / i);
+ };
+
+ // Returns undefined if the sum of the weights is zero.
+ Statistics.weightedMean = function(
+ ary, weightCallback, opt_valueCallback, opt_this) {
+ const valueCallback = opt_valueCallback || (x => x);
+ let numerator = 0;
+ let denominator = 0;
+ let i = -1;
+
+ for (const elt of ary) {
+ i++;
+ const value = valueCallback.call(opt_this, elt, i);
+ if (value === undefined) continue;
+ const weight = weightCallback.call(opt_this, elt, i, value);
+ numerator += weight * value;
+ denominator += weight;
+ }
+
+ if (denominator === 0) return undefined;
+
+ return numerator / denominator;
+ };
+
+ Statistics.variance = function(ary, opt_func, opt_this) {
+ if (ary.length === 0) return undefined;
+ if (ary.length === 1) return 0;
+ const func = opt_func || (x => x);
+ const mean = Statistics.mean(ary, func, opt_this);
+ const sumOfSquaredDistances = Statistics.sum(
+ ary,
+ function(d, i) {
+ const v = func.call(this, d, i) - mean;
+ return v * v;
+ },
+ opt_this);
+ return sumOfSquaredDistances / (ary.length - 1);
+ };
+
+ Statistics.stddev = function(ary, opt_func, opt_this) {
+ if (ary.length === 0) return undefined;
+ return Math.sqrt(
+ Statistics.variance(ary, opt_func, opt_this));
+ };
+
+ Statistics.max = function(ary, opt_func, opt_this) {
+ const func = opt_func || (x => x);
+ let ret = -Infinity;
+ let i = 0;
+ for (const elt of ary) {
+ ret = Math.max(ret, func.call(opt_this, elt, i++));
+ }
+ return ret;
+ };
+
+ Statistics.min = function(ary, opt_func, opt_this) {
+ const func = opt_func || (x => x);
+ let ret = Infinity;
+ let i = 0;
+ for (const elt of ary) {
+ ret = Math.min(ret, func.call(opt_this, elt, i++));
+ }
+ return ret;
+ };
+
+ Statistics.range = function(ary, opt_func, opt_this) {
+ const func = opt_func || (x => x);
+ const ret = new tr.b.math.Range();
+ let i = 0;
+ for (const elt of ary) {
+ ret.addValue(func.call(opt_this, elt, i++));
+ }
+ return ret;
+ };
+
+ Statistics.percentile = function(ary, percent, opt_func, opt_this) {
+ if (!(percent >= 0 && percent <= 1)) {
+ throw new Error('percent must be [0,1]');
+ }
+
+ const func = opt_func || (x => x);
+ const tmp = new Array(ary.length);
+ let i = 0;
+ for (const elt of ary) {
+ tmp[i] = func.call(opt_this, elt, i++);
+ }
+ tmp.sort((a, b) => a - b);
+ const idx = Math.floor((ary.length - 1) * percent);
+ return tmp[idx];
+ };
+
+ /**
+ * Sorts the samples, and map them linearly to the range [0,1].
+ *
+ * They're mapped such that for the N samples, the first sample is 0.5/N and
+ * the last sample is (N-0.5)/N.
+ *
+ * Background: The discrepancy of the sample set i/(N-1); i=0, ..., N-1 is
+ * 2/N, twice the discrepancy of the sample set (i+1/2)/N; i=0, ..., N-1. In
+ * our case we don't want to distinguish between these two cases, as our
+ * original domain is not bounded (it is for Monte Carlo integration, where
+ * discrepancy was first used).
+ **/
+ Statistics.normalizeSamples = function(samples) {
+ if (samples.length === 0) {
+ return {
+ normalized_samples: samples,
+ scale: 1.0
+ };
+ }
+ // Create a copy to make sure that we don't mutate original |samples| input.
+ samples = samples.slice().sort(
+ function(a, b) {
+ return a - b;
+ }
+ );
+ const low = Math.min.apply(null, samples);
+ const high = Math.max.apply(null, samples);
+ const newLow = 0.5 / samples.length;
+ const newHigh = (samples.length - 0.5) / samples.length;
+ if (high - low === 0.0) {
+ // Samples is an array of 0.5 in this case.
+ samples = Array.apply(null, new Array(samples.length)).map(
+ function() { return 0.5;});
+ return {
+ normalized_samples: samples,
+ scale: 1.0
+ };
+ }
+ const scale = (newHigh - newLow) / (high - low);
+ for (let i = 0; i < samples.length; i++) {
+ samples[i] = (samples[i] - low) * scale + newLow;
+ }
+ return {
+ normalized_samples: samples,
+ scale
+ };
+ };
+
+ /**
+ * Computes the discrepancy of a set of 1D samples from the interval [0,1].
+ *
+ * The samples must be sorted. We define the discrepancy of an empty set
+ * of samples to be zero.
+ *
+ * http://en.wikipedia.org/wiki/Low-discrepancy_sequence
+ * http://mathworld.wolfram.com/Discrepancy.html
+ */
+ Statistics.discrepancy = function(samples, opt_locationCount) {
+ if (samples.length === 0) return 0.0;
+
+ let maxLocalDiscrepancy = 0;
+ const invSampleCount = 1.0 / samples.length;
+ const locations = [];
+ // For each location, stores the number of samples less than that location.
+ const countLess = [];
+ // For each location, stores the number of samples less than or equal to
+ // that location.
+ const countLessEqual = [];
+
+ if (opt_locationCount !== undefined) {
+ // Generate list of equally spaced locations.
+ let sampleIndex = 0;
+ for (let i = 0; i < opt_locationCount; i++) {
+ const location = i / (opt_locationCount - 1);
+ locations.push(location);
+ while (sampleIndex < samples.length &&
+ samples[sampleIndex] < location) {
+ sampleIndex += 1;
+ }
+ countLess.push(sampleIndex);
+ while (sampleIndex < samples.length &&
+ samples[sampleIndex] <= location) {
+ sampleIndex += 1;
+ }
+ countLessEqual.push(sampleIndex);
+ }
+ } else {
+ // Populate locations with sample positions. Append 0 and 1 if necessary.
+ if (samples[0] > 0.0) {
+ locations.push(0.0);
+ countLess.push(0);
+ countLessEqual.push(0);
+ }
+ for (let i = 0; i < samples.length; i++) {
+ locations.push(samples[i]);
+ countLess.push(i);
+ countLessEqual.push(i + 1);
+ }
+ if (samples[-1] < 1.0) {
+ locations.push(1.0);
+ countLess.push(samples.length);
+ countLessEqual.push(samples.length);
+ }
+ }
+
+ // Compute discrepancy as max(overshoot, -undershoot), where
+ // overshoot = max(countClosed(i, j)/N - length(i, j)) for all i < j,
+ // undershoot = min(countOpen(i, j)/N - length(i, j)) for all i < j,
+ // N = len(samples),
+ // countClosed(i, j) is the number of points between i and j
+ // including ends,
+ // countOpen(i, j) is the number of points between i and j excluding ends,
+ // length(i, j) is locations[i] - locations[j].
+
+ // The following algorithm is modification of Kadane's algorithm,
+ // see https://en.wikipedia.org/wiki/Maximum_subarray_problem.
+
+ // The maximum of (countClosed(k, i-1)/N - length(k, i-1)) for any k < i-1.
+ let maxDiff = 0;
+ // The minimum of (countOpen(k, i-1)/N - length(k, i-1)) for any k < i-1.
+ let minDiff = 0;
+ for (let i = 1; i < locations.length; i++) {
+ const length = locations[i] - locations[i - 1];
+ const countClosed = countLessEqual[i] - countLess[i - 1];
+ const countOpen = countLess[i] - countLessEqual[i - 1];
+ // Number of points that are added if we extend a closed range that
+ // ends at location (i-1).
+ const countClosedIncrement =
+ countLessEqual[i] - countLessEqual[i - 1];
+ // Number of points that are added if we extend an open range that
+ // ends at location (i-1).
+ const countOpenIncrement = countLess[i] - countLess[i - 1];
+
+ // Either extend the previous optimal range or start a new one.
+ maxDiff = Math.max(
+ countClosedIncrement * invSampleCount - length + maxDiff,
+ countClosed * invSampleCount - length);
+ minDiff = Math.min(
+ countOpenIncrement * invSampleCount - length + minDiff,
+ countOpen * invSampleCount - length);
+
+ maxLocalDiscrepancy = Math.max(
+ maxDiff, -minDiff, maxLocalDiscrepancy);
+ }
+ return maxLocalDiscrepancy;
+ };
+
+ /**
+ * A discrepancy based metric for measuring timestamp jank.
+ *
+ * timestampsDiscrepancy quantifies the largest area of jank observed in a
+ * series of timestamps. Note that this is different from metrics based on
+ * the max_time_interval. For example, the time stamp series A = [0,1,2,3,5,6]
+ * and B = [0,1,2,3,5,7] have the same max_time_interval = 2, but
+ * Discrepancy(B) > Discrepancy(A).
+ *
+ * Two variants of discrepancy can be computed:
+ *
+ * Relative discrepancy is following the original definition of
+ * discrepancy. It characterized the largest area of jank, relative to the
+ * duration of the entire time stamp series. We normalize the raw results,
+ * because the best case discrepancy for a set of N samples is 1/N (for
+ * equally spaced samples), and we want our metric to report 0.0 in that
+ * case.
+ *
+ * Absolute discrepancy also characterizes the largest area of jank, but its
+ * value wouldn't change (except for imprecisions due to a low
+ * |interval_multiplier|) if additional 'good' intervals were added to an
+ * exisiting list of time stamps. Its range is [0,inf] and the unit is
+ * milliseconds.
+ *
+ * The time stamp series C = [0,2,3,4] and D = [0,2,3,4,5] have the same
+ * absolute discrepancy, but D has lower relative discrepancy than C.
+ *
+ * |timestamps| may be a list of lists S = [S_1, S_2, ..., S_N], where each
+ * S_i is a time stamp series. In that case, the discrepancy D(S) is:
+ * D(S) = max(D(S_1), D(S_2), ..., D(S_N))
+ **/
+ Statistics.timestampsDiscrepancy = function(timestamps, opt_absolute,
+ opt_locationCount) {
+ if (timestamps.length === 0) return 0.0;
+
+ if (opt_absolute === undefined) opt_absolute = true;
+
+ if (Array.isArray(timestamps[0])) {
+ const rangeDiscrepancies = timestamps.map(function(r) {
+ return Statistics.timestampsDiscrepancy(r);
+ });
+ return Math.max.apply(null, rangeDiscrepancies);
+ }
+
+ const s = Statistics.normalizeSamples(timestamps);
+ const samples = s.normalized_samples;
+ const sampleScale = s.scale;
+ let discrepancy = Statistics.discrepancy(samples, opt_locationCount);
+ const invSampleCount = 1.0 / samples.length;
+ if (opt_absolute === true) {
+ // Compute absolute discrepancy
+ discrepancy /= sampleScale;
+ } else {
+ // Compute relative discrepancy
+ discrepancy = tr.b.math.clamp(
+ (discrepancy - invSampleCount) / (1.0 - invSampleCount), 0.0, 1.0);
+ }
+ return discrepancy;
+ };
+
+ /**
+ * Modifies |samples| in-place to reduce its length down to |count|.
+ *
+ * @param {!Array} samples
+ * @param {number} count
+ * @return {!Array}
+ */
+ Statistics.uniformlySampleArray = function(samples, count) {
+ if (samples.length <= count) {
+ return samples;
+ }
+ while (samples.length > count) {
+ const i = parseInt(Math.random() * samples.length);
+ samples.splice(i, 1);
+ }
+ return samples;
+ };
+
+ /**
+ * A mechanism to uniformly sample elements from an arbitrary long stream.
+ *
+ * Call this method every time a new element is obtained from the stream,
+ * passing always the same |samples| array and the |numSamples| you desire.
+ * Also pass in the current |streamLength|, which is the same as the index of
+ * |newElement| within that stream.
+ *
+ * The |samples| array will possibly be updated, replacing one of its element
+ * with |newElements|. The length of |samples| will not be more than
+ * |numSamples|.
+ *
+ * This method guarantees that after |streamLength| elements have been
+ * processed each one has equal probability of being in |samples|. The order
+ * of samples is not preserved though.
+ *
+ * Args:
+ * samples: Array of elements that have already been selected. Start with [].
+ * streamLength: The current length of the stream, up to |newElement|.
+ * newElement: The element that was just extracted from the stream.
+ * numSamples: The total number of samples desired.
+ **/
+ Statistics.uniformlySampleStream = function(samples, streamLength, newElement,
+ numSamples) {
+ if (streamLength <= numSamples) {
+ if (samples.length >= streamLength) {
+ samples[streamLength - 1] = newElement;
+ } else {
+ samples.push(newElement);
+ }
+ return;
+ }
+
+ const probToKeep = numSamples / streamLength;
+ if (Math.random() > probToKeep) return; // New sample was rejected.
+
+ // Keeping it, replace an alement randomly.
+ const index = Math.floor(Math.random() * numSamples);
+ samples[index] = newElement;
+ };
+
+ /**
+ * A mechanism to merge two arrays of uniformly sampled elements in a way that
+ * ensures elements in the final array are still sampled uniformly.
+ *
+ * This works similarly to sampleStreamUniform. The |samplesA| array will be
+ * updated, some of its elements replaced by elements from |samplesB| in a
+ * way that ensure that elements will be sampled uniformly.
+ *
+ * Args:
+ * samplesA: Array of uniformly sampled elements, will be updated.
+ * streamLengthA: The length of the stream from which |samplesA| was sampled.
+ * samplesB: Other array of uniformly sampled elements, will NOT be updated.
+ * streamLengthB: The length of the stream from which |samplesB| was sampled.
+ * numSamples: The total number of samples desired, both in |samplesA| and
+ * |samplesB|.
+ **/
+ Statistics.mergeSampledStreams = function(
+ samplesA, streamLengthA,
+ samplesB, streamLengthB, numSamples) {
+ if (streamLengthB < numSamples) {
+ // samplesB has not reached max capacity so every sample of stream B were
+ // chosen with certainty. Add them one by one into samplesA.
+ const nbElements = Math.min(streamLengthB, samplesB.length);
+ for (let i = 0; i < nbElements; ++i) {
+ Statistics.uniformlySampleStream(samplesA, streamLengthA + i + 1,
+ samplesB[i], numSamples);
+ }
+ return;
+ }
+ if (streamLengthA < numSamples) {
+ // samplesA has not reached max capacity so every sample of stream A were
+ // chosen with certainty. Add them one by one into samplesB.
+ const nbElements = Math.min(streamLengthA, samplesA.length);
+ const tempSamples = samplesB.slice();
+ for (let i = 0; i < nbElements; ++i) {
+ Statistics.uniformlySampleStream(tempSamples, streamLengthB + i + 1,
+ samplesA[i], numSamples);
+ }
+ // Copy that back into the first vector.
+ for (let i = 0; i < tempSamples.length; ++i) {
+ samplesA[i] = tempSamples[i];
+ }
+ return;
+ }
+
+ // Both sample arrays are at max capacity, use the power of maths!
+ // Elements in samplesA have been selected with probability
+ // numSamples / streamLengthA. Same for samplesB. For each index of the
+ // array we keep samplesA[i] with probability
+ // P = streamLengthA / (streamLengthA + streamLengthB)
+ // and replace it with samplesB[i] with probability 1-P.
+ // The total probability of keeping it is therefore
+ // numSamples / streamLengthA *
+ // streamLengthA / (streamLengthA + streamLengthB)
+ // = numSamples / (streamLengthA + streamLengthB)
+ // A similar computation shows we have the same probability of keeping any
+ // element in samplesB. Magic!
+ const nbElements = Math.min(numSamples, samplesB.length);
+ const probOfSwapping = streamLengthB / (streamLengthA + streamLengthB);
+ for (let i = 0; i < nbElements; ++i) {
+ if (Math.random() < probOfSwapping) {
+ samplesA[i] = samplesB[i];
+ }
+ }
+ };
+
+ /* Continuous distributions are defined by probability density functions.
+ *
+ * Random variables are referred to by capital letters: X, Y, Z.
+ * Particular values from these distributions are referred to by lowercase
+ * letters like |x|.
+ * The probability that |X| ever exactly equals |x| is P(X==x) = 0.
+ *
+ * For a discrete probability distribution, see tr.v.Histogram.
+ */
+ function Distribution() {
+ }
+
+ Distribution.prototype = {
+ /* The probability density of the random variable at value |x| is the
+ * relative likelihood for this random variable to take on the given value
+ * |x|.
+ *
+ * @param {number} x A value from the random distribution.
+ * @return {number} probability density at x.
+ */
+ computeDensity(x) {
+ throw Error('Not implemented');
+ },
+
+ /* A percentile is the probability that a sample from the distribution is
+ * less than the given value |x|. This function is monotonically increasing.
+ *
+ * @param {number} x A value from the random distribution.
+ * @return {number} P(X<x).
+ */
+ computePercentile(x) {
+ throw Error('Not implemented');
+ },
+
+ /* A complementary percentile is the probability that a sample from the
+ * distribution is greater than the given value |x|. This function is
+ * monotonically decreasing.
+ *
+ * @param {number} x A value from the random distribution.
+ * @return {number} P(X>x).
+ */
+ computeComplementaryPercentile(x) {
+ return 1 - this.computePercentile(x);
+ },
+
+ /* Compute the mean of the probability distribution.
+ *
+ * @return {number} mean.
+ */
+ get mean() {
+ throw Error('Not implemented');
+ },
+
+ /* The mode of a distribution is the most likely value.
+ * The maximum of the computeDensity() function is at this mode.
+ * @return {number} mode.
+ */
+ get mode() {
+ throw Error('Not implemented');
+ },
+
+ /* The median is the center value of the distribution.
+ * computePercentile(median) = computeComplementaryPercentile(median) = 0.5
+ *
+ * @return {number} median.
+ */
+ get median() {
+ throw Error('Not implemented');
+ },
+
+ /* The standard deviation is a measure of how dispersed or spread out the
+ * distribution is (this statistic has the same units as the values).
+ *
+ * @return {number} standard deviation.
+ */
+ get standardDeviation() {
+ throw Error('Not implemented');
+ },
+
+ /* An alternative measure of how spread out the distribution is,
+ * the variance is the square of the standard deviation.
+ * @return {number} variance.
+ */
+ get variance() {
+ throw Error('Not implemented');
+ }
+ };
+
+ Statistics.UniformDistribution = function(opt_range) {
+ if (!opt_range) opt_range = tr.b.math.Range.fromExplicitRange(0, 1);
+ this.range = opt_range;
+ };
+
+ Statistics.UniformDistribution.prototype = {
+ __proto__: Distribution.prototype,
+
+ computeDensity(x) {
+ return 1 / this.range.range;
+ },
+
+ computePercentile(x) {
+ return tr.b.math.normalize(x, this.range.min, this.range.max);
+ },
+
+ get mean() {
+ return this.range.center;
+ },
+
+ get mode() {
+ return undefined;
+ },
+
+ get median() {
+ return this.mean;
+ },
+
+ get standardDeviation() {
+ return Math.sqrt(this.variance);
+ },
+
+ get variance() {
+ return Math.pow(this.range.range, 2) / 12;
+ }
+ };
+
+ /* The Normal or Gaussian distribution, or bell curve, is common in complex
+ * processes such as are found in many of the natural sciences. If Z is the
+ * standard normal distribution with mean = 0 and variance = 1, then the
+ * general normal distribution is Y = mean + Z*sqrt(variance).
+ * https://www.desmos.com/calculator/tqtbjm4s3z
+ */
+ Statistics.NormalDistribution = function(opt_mean, opt_variance) {
+ this.mean_ = opt_mean || 0;
+ this.variance_ = opt_variance || 1;
+ this.standardDeviation_ = Math.sqrt(this.variance_);
+ };
+
+ Statistics.NormalDistribution.prototype = {
+ __proto__: Distribution.prototype,
+
+ computeDensity(x) {
+ const scale = (1.0 / (this.standardDeviation * Math.sqrt(2.0 * Math.PI)));
+ const exponent = -Math.pow(x - this.mean, 2) / (2.0 * this.variance);
+ return scale * Math.exp(exponent);
+ },
+
+ computePercentile(x) {
+ const standardizedX = ((x - this.mean) /
+ Math.sqrt(2.0 * this.variance));
+ return (1.0 + tr.b.math.erf(standardizedX)) / 2.0;
+ },
+
+ get mean() {
+ return this.mean_;
+ },
+
+ get median() {
+ return this.mean;
+ },
+
+ get mode() {
+ return this.mean;
+ },
+
+ get standardDeviation() {
+ return this.standardDeviation_;
+ },
+
+ get variance() {
+ return this.variance_;
+ }
+ };
+
+ /* The log-normal distribution is a continuous probability distribution of a
+ * random variable whose logarithm is normally distributed.
+ * If Y is the general normal distribution, then X = exp(Y) is the general
+ * log-normal distribution.
+ * X will have different parameters from Y,
+ * so the mean of Y is called the "location" of X,
+ * and the standard deviation of Y is called the "shape" of X.
+ * The standard lognormal distribution exp(Z) has location = 0 and shape = 1.
+ * https://www.desmos.com/calculator/tqtbjm4s3z
+ */
+ Statistics.LogNormalDistribution = function(opt_location, opt_shape) {
+ this.normalDistribution_ = new Statistics.NormalDistribution(
+ opt_location, Math.pow(opt_shape || 1, 2));
+ };
+
+ Statistics.LogNormalDistribution.prototype = {
+ __proto__: Statistics.NormalDistribution.prototype,
+
+ computeDensity(x) {
+ return this.normalDistribution_.computeDensity(Math.log(x)) / x;
+ },
+
+ computePercentile(x) {
+ return this.normalDistribution_.computePercentile(Math.log(x));
+ },
+
+ get mean() {
+ return Math.exp(this.normalDistribution_.mean +
+ (this.normalDistribution_.variance / 2));
+ },
+
+ get variance() {
+ const nm = this.normalDistribution_.mean;
+ const nv = this.normalDistribution_.variance;
+ return (Math.exp(2 * (nm + nv)) -
+ Math.exp(2 * nm + nv));
+ },
+
+ get standardDeviation() {
+ return Math.sqrt(this.variance);
+ },
+
+ get median() {
+ return Math.exp(this.normalDistribution_.mean);
+ },
+
+ get mode() {
+ return Math.exp(this.normalDistribution_.mean -
+ this.normalDistribution_.variance);
+ }
+ };
+
+ /**
+ * Instead of describing a LogNormalDistribution in terms of its "location"
+ * and "shape", it can also be described in terms of its median
+ * and the point at which its complementary cumulative distribution
+ * function bends between the linear-ish region in the middle and the
+ * exponential-ish region. When the distribution is used to compute
+ * percentiles for log-normal random processes such as latency, as the latency
+ * improves, it hits a point of diminishing returns, when it becomes
+ * relatively difficult to improve the score further. This point of
+ * diminishing returns is the first x-intercept of the third derivative of the
+ * CDF, which is the second derivative of the PDF.
+ *
+ * https://www.desmos.com/calculator/cg5rnftabn
+ *
+ * @param {number} median The median of the distribution.
+ * @param {number} diminishingReturns The point of diminishing returns.
+ * @return {LogNormalDistribution}
+ */
+ Statistics.LogNormalDistribution.fromMedianAndDiminishingReturns =
+ function(median, diminishingReturns) {
+ diminishingReturns = Math.log(diminishingReturns / median);
+ const shape = Math.sqrt(1 - 3 * diminishingReturns -
+ Math.sqrt(Math.pow(diminishingReturns - 3, 2) - 8)) / 2;
+ const location = Math.log(median);
+ return new Statistics.LogNormalDistribution(location, shape);
+ };
+
+ // p-values less than this indicate statistical significance.
+ Statistics.DEFAULT_ALPHA = 0.01;
+
+ // If a statistical significant difference has not been established with
+ // this many observations per sample, we'll assume none exists.
+ Statistics.MAX_SUGGESTED_SAMPLE_SIZE = 20;
+
+ /** @enum */
+ Statistics.Significance = {
+ SIGNIFICANT: 'REJECT',
+ INSIGNIFICANT: 'FAIL_TO_REJECT',
+ NEED_MORE_DATA: 'NEED_MORE_DATA',
+ DONT_CARE: 'DONT_CARE',
+ };
+
+
+ class HypothesisTestResult {
+ constructor(p, u, needMoreData, opt_alpha) {
+ this.p_ = p;
+ this.u_ = u;
+ this.needMoreData_ = needMoreData;
+ this.compare(opt_alpha);
+ }
+
+ /**
+ * The probability under the null hypothesis (i.e. the two samples are
+ * indistinguishable) of obtaining a result more extreme than observed.
+ * @return number in (0,1)
+ */
+ get p() {
+ return this.p_;
+ }
+
+ /**
+ * The U statistic from MWU.
+ * @return number
+ */
+ get U() {
+ return this.u_;
+ }
+
+ /**
+ * @return {!tr.b.math.Statistics.Significance}
+ */
+ get significance() {
+ return this.significance_;
+ }
+
+ /**
+ * Recompute |significance| with the same p-value but a new alpha threshold.
+ * Faster than recomputing MWU.
+ *
+ * @param {number=}
+ * @return {!tr.b.math.Statistics.Significance}
+ */
+ compare(opt_alpha) {
+ const alpha = opt_alpha || Statistics.DEFAULT_ALPHA;
+ if (this.p < alpha) {
+ this.significance_ = Statistics.Significance.SIGNIFICANT;
+ } else if (this.needMoreData_) {
+ this.significance_ = Statistics.Significance.NEED_MORE_DATA;
+ } else {
+ this.significance_ = Statistics.Significance.INSIGNIFICANT;
+ }
+ return this.significance_;
+ }
+
+ asDict() {
+ return {
+ p: this.p,
+ U: this.U,
+ significance: this.significance,
+ };
+ }
+ }
+
+ /**
+ * @param {!Array.<number>} a
+ * @param {!Array.<number>} b
+ * @param {number=} opt_alpha
+ * @param {number=} opt_reqSampleSize
+ * @return {!HypothesisTestResult}
+ */
+ Statistics.mwu = function(a, b, opt_alpha, opt_reqSampleSize) {
+ const result = mannwhitneyu.test(a, b);
+ const needMoreData = opt_reqSampleSize &&
+ Math.min(a.length, b.length) < opt_reqSampleSize;
+ return new HypothesisTestResult(
+ result.p, result.U, needMoreData, opt_alpha);
+ };
+
+ return {
+ Statistics,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/math/statistics_test.html b/chromium/third_party/catapult/tracing/tracing/base/math/statistics_test.html
new file mode 100644
index 00000000000..e0b081a3af1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/math/statistics_test.html
@@ -0,0 +1,579 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/statistics.html">
+<script>
+'use strict';
+
+// TODO(charliea): Remove:
+/* eslint-disable catapult-camelcase */
+
+tr.b.unittest.testSuite(function() {
+ const Statistics = tr.b.math.Statistics;
+
+ /**
+ * Lloyd relaxation in 1D.
+ *
+ * Keeps the position of the first and last sample.
+ **/
+ function relax(samples, opt_iterations) {
+ opt_iterations = opt_iterations || 10;
+ for (let i = 0; i < opt_iterations; i++) {
+ const voronoiBoundaries = [];
+ for (let j = 1; j < samples.length; j++) {
+ voronoiBoundaries.push((samples[j] + samples[j - 1]) * 0.5);
+ }
+
+ const relaxedSamples = [];
+ relaxedSamples.push(samples[0]);
+ for (let j = 1; j < samples.length - 1; j++) {
+ relaxedSamples.push(
+ (voronoiBoundaries[j - 1] + voronoiBoundaries[j]) * 0.5);
+ }
+ relaxedSamples.push(samples[samples.length - 1]);
+ samples = relaxedSamples;
+ }
+ return samples;
+ }
+
+ function createRandomSamples(numSamples) {
+ const samples = [];
+ let position = 0.0;
+ samples.push(position);
+ for (let i = 1; i < numSamples; i++) {
+ position += Math.random();
+ samples.push(position);
+ }
+ return samples;
+ }
+
+ test('normalDistribution', function() {
+ for (let mean = -100; mean <= 100; mean += 25) {
+ for (let stddev = 0.1; stddev < 2; stddev += 0.2) {
+ const dist = new Statistics.NormalDistribution(mean, stddev * stddev);
+ assert.closeTo(mean, dist.mean, 1e-6);
+ assert.closeTo(stddev, dist.standardDeviation, 1e-6);
+ assert.closeTo(0, dist.standardDeviation * dist.computeDensity(
+ -1e10), 1e-5);
+ assert.closeTo(0.05399, dist.standardDeviation * dist.computeDensity(
+ dist.mean - 2 * dist.standardDeviation), 1e-5);
+ assert.closeTo(0.24197, dist.standardDeviation * dist.computeDensity(
+ dist.mean - dist.standardDeviation), 1e-5);
+ assert.closeTo(0.39894, dist.standardDeviation * dist.computeDensity(
+ dist.mean), 1e-5);
+ assert.closeTo(0.24197, dist.standardDeviation * dist.computeDensity(
+ dist.mean + dist.standardDeviation), 1e-5);
+ assert.closeTo(0.054, dist.standardDeviation * dist.computeDensity(
+ dist.mean + 2 * dist.standardDeviation), 1e-5);
+ assert.closeTo(0, dist.standardDeviation * dist.computeDensity(
+ 1e10), 1e-5);
+
+ assert.closeTo(0, dist.computePercentile(-1e10), 1e-5);
+ assert.closeTo(0.02275, dist.computePercentile(
+ dist.mean - 2 * dist.standardDeviation), 1e-5);
+ assert.closeTo(0.15866, dist.computePercentile(
+ dist.mean - dist.standardDeviation), 1e-5);
+ assert.closeTo(0.5, dist.computePercentile(dist.mean), 1e-5);
+ assert.closeTo(0.841344, dist.computePercentile(
+ dist.mean + dist.standardDeviation), 1e-5);
+ assert.closeTo(0.97725, dist.computePercentile(
+ dist.mean + 2 * dist.standardDeviation), 1e-5);
+ assert.closeTo(1, dist.computePercentile(1e10), 1e-5);
+ }
+ }
+ });
+
+ test('logNormalDistribution', function() {
+ // Unlike the Normal distribution, the LogNormal distribution can look very
+ // different depending on its parameters, and it's defined in terms of the
+ // Normal distribution anyway, so only test the standard LogNormal
+ // distribution.
+ const dist = new Statistics.LogNormalDistribution(0, 1);
+ assert.closeTo(0.3678, dist.mode, 1e-4);
+ assert.closeTo(1, dist.median, 1e-6);
+ assert.closeTo(1.6487, dist.mean, 1e-4);
+ assert.closeTo(0.65774, dist.computeDensity(dist.mode), 1e-5);
+ assert.closeTo(0.39894, dist.computeDensity(dist.median), 1e-5);
+ assert.closeTo(0.21354, dist.computeDensity(dist.mean), 1e-5);
+ assert.closeTo(0, dist.computePercentile(1e-10), 1e-6);
+ assert.closeTo(0.15865, dist.computePercentile(dist.mode), 1e-5);
+ assert.closeTo(0.5, dist.computePercentile(dist.median), 1e-6);
+ assert.closeTo(0.69146, dist.computePercentile(dist.mean), 1e-5);
+ assert.closeTo(1, dist.computePercentile(1e100), 1e-5);
+ });
+
+ test('divideIfPossibleOrZero', function() {
+ assert.strictEqual(Statistics.divideIfPossibleOrZero(1, 2), 0.5);
+ assert.strictEqual(Statistics.divideIfPossibleOrZero(0, 2), 0);
+ assert.strictEqual(Statistics.divideIfPossibleOrZero(1, 0), 0);
+ assert.strictEqual(Statistics.divideIfPossibleOrZero(0, 0), 0);
+ });
+
+ test('sumBasic', function() {
+ assert.strictEqual(Statistics.sum([1, 2, 3]), 6);
+ });
+
+ test('sumWithFunctor', function() {
+ const ctx = {};
+ const ary = [1, 2, 3];
+ assert.strictEqual(12, Statistics.sum(ary, function(x, i) {
+ assert.strictEqual(this, ctx);
+ assert.strictEqual(ary[i], x);
+ return x * 2;
+ }, ctx));
+ });
+
+ test('minMaxWithFunctor', function() {
+ const ctx = {};
+ const ary = [1, 2, 3];
+ function func(x, i) {
+ assert.strictEqual(this, ctx);
+ assert.strictEqual(ary[i], x);
+ return x;
+ }
+ assert.strictEqual(Statistics.max(ary, func, ctx), 3);
+ assert.strictEqual(Statistics.min(ary, func, ctx), 1);
+
+ const range = Statistics.range(ary, func, ctx);
+ assert.isFalse(range.isEmpty);
+ assert.strictEqual(range.min, 1);
+ assert.strictEqual(range.max, 3);
+ });
+
+ test('maxExtrema', function() {
+ assert.strictEqual(Statistics.max([]), -Infinity);
+ assert.strictEqual(Statistics.min([]), Infinity);
+ });
+
+ test('meanBasic', function() {
+ assert.closeTo(Statistics.mean([1, 2, 3]), 2, 1e-6);
+ assert.closeTo(Statistics.mean(new Set([1, 2, 3])), 2, 1e-6);
+ });
+
+ test('geometricMean', function() {
+ assert.strictEqual(1, Statistics.geometricMean([]));
+ assert.strictEqual(1, Statistics.geometricMean([1]));
+ assert.strictEqual(0, Statistics.geometricMean([-1]));
+ assert.strictEqual(0, Statistics.geometricMean([0]));
+ assert.strictEqual(0, Statistics.geometricMean([1, 2, 3, 0]));
+ assert.strictEqual(0, Statistics.geometricMean([1, 2, 3, -1]));
+ assert.strictEqual(1, Statistics.geometricMean([1, 1, 1]));
+ assert.strictEqual(2, Statistics.geometricMean([2]));
+ assert.closeTo(Math.sqrt(6), Statistics.geometricMean([2, 3]), 1e-6);
+ assert.closeTo(6, Statistics.geometricMean(new Set([4, 9])), 1e-6);
+
+ let samples = [];
+ for (let i = 0; i < 1e3; ++i) {
+ samples.push(Number.MAX_SAFE_INTEGER);
+ }
+ assert.closeTo(Number.MAX_SAFE_INTEGER, Statistics.geometricMean(samples),
+ Number.MAX_SAFE_INTEGER * 1e-13);
+
+ samples = [];
+ for (let i = 0; i < 1e3; ++i) {
+ samples.push(Number.MAX_VALUE / 1e3);
+ }
+ assert.closeTo(Number.MAX_VALUE / 1e3, Statistics.geometricMean(samples),
+ Number.MAX_VALUE * 1e-13);
+ });
+
+ test('weightedMean', function() {
+ function getWeight(element) {
+ return element.weight;
+ }
+ function getValue(element) {
+ return element.value;
+ }
+
+ let data = [
+ {value: 10, weight: 3},
+ {value: 20, weight: 1},
+ {value: 30, weight: 6}
+ ];
+ assert.strictEqual(23, Statistics.weightedMean(data, getWeight, getValue));
+
+ data = [
+ {value: 10, weight: 0},
+ {value: 20, weight: 0},
+ {value: 30, weight: 0}
+ ];
+ assert.strictEqual(
+ undefined, Statistics.weightedMean(data, getWeight, getValue));
+
+ data = [
+ {value: 10, weight: -10},
+ {value: 20, weight: 5},
+ {value: 30, weight: 5}
+ ];
+ assert.strictEqual(
+ undefined, Statistics.weightedMean(data, getWeight, getValue));
+ });
+
+ test('weightedMean_positionDependent', function() {
+ function getWeight(element, idx) {
+ return idx;
+ }
+ // 3 has weight of 0, 6 has weight of 1, 9 has weight of 2
+ assert.strictEqual(8, Statistics.weightedMean([3, 6, 9], getWeight));
+ });
+
+ test('max_positionDependent', function() {
+ function getValue(element, idx) {
+ return element * idx;
+ }
+ assert.strictEqual(6, Statistics.max([1, 2, 3], getValue));
+ });
+
+ test('min_positionDependent', function() {
+ function getValue(element, idx) {
+ return element * idx;
+ }
+ assert.strictEqual(-6, Statistics.min([1, 2, -3], getValue));
+ });
+
+ test('varianceBasic', function() {
+ // In [2, 4, 4, 2], all items have a deviation of 1.0 from the mean so the
+ // population variance is 4.0 / 4 = 1.0, but the sample variance is 4.0 / 3.
+ assert.strictEqual(Statistics.variance([2, 4, 4, 2]), 4.0 / 3);
+
+ // In [1, 2, 3], the squared deviations are 1.0, 0.0 and 1.0 respectively;
+ // population variance 2.0 / 3 but sample variance is 2.0 / 2 = 1.0.
+ assert.strictEqual(Statistics.variance([1, 2, 3]), 1.0);
+ });
+
+ test('varianceWithFunctor', function() {
+ const ctx = {};
+ const ary = [{x: 2},
+ {x: 4},
+ {x: 4},
+ {x: 2}];
+ assert.strictEqual(4.0 / 3, Statistics.variance(ary, function(d) {
+ assert.strictEqual(ctx, this);
+ return d.x;
+ }, ctx));
+ });
+
+ test('stddevBasic', function() {
+ assert.strictEqual(Statistics.stddev([2, 4, 4, 2]), Math.sqrt(4.0 / 3));
+ });
+
+ test('stddevWithFunctor', function() {
+ const ctx = {};
+ const ary = [{x: 2},
+ {x: 4},
+ {x: 4},
+ {x: 2}];
+ assert.strictEqual(Math.sqrt(4.0 / 3), Statistics.stddev(ary, function(d) {
+ assert.strictEqual(ctx, this);
+ return d.x;
+ }, ctx));
+ });
+
+ test('percentile', function() {
+ const ctx = {};
+ const ary = [{x: 0},
+ {x: 1},
+ {x: 2},
+ {x: 3},
+ {x: 4},
+ {x: 5},
+ {x: 6},
+ {x: 7},
+ {x: 8},
+ {x: 9}];
+ function func(d, i) {
+ assert.strictEqual(ctx, this);
+ return d.x;
+ }
+ assert.strictEqual(Statistics.percentile(ary, 0, func, ctx), 0);
+ assert.strictEqual(Statistics.percentile(ary, .5, func, ctx), 4);
+ assert.strictEqual(Statistics.percentile(ary, .75, func, ctx), 6);
+ assert.strictEqual(Statistics.percentile(ary, 1, func, ctx), 9);
+ });
+
+ test('percentile_positionDependent', function() {
+ const ctx = {};
+ const ary = [{x: 0},
+ {x: 1},
+ {x: 2},
+ {x: 3},
+ {x: 4},
+ {x: 5},
+ {x: 6},
+ {x: 7},
+ {x: 8},
+ {x: 9}];
+ function func(d, i) {
+ assert.strictEqual(ctx, this);
+ assert.strictEqual(d.x, i);
+ return d.x * i;
+ }
+ assert.strictEqual(Statistics.percentile(ary, 0, func, ctx), 0);
+ assert.strictEqual(Statistics.percentile(ary, .5, func, ctx), 16);
+ assert.strictEqual(Statistics.percentile(ary, .75, func, ctx), 36);
+ assert.strictEqual(Statistics.percentile(ary, 1, func, ctx), 81);
+ });
+
+ test('normalizeSamples', function() {
+ let samples = [];
+ let results = Statistics.normalizeSamples(samples);
+ assert.deepEqual(results.normalized_samples, []);
+ assert.deepEqual(results.scale, 1.0);
+
+ samples = [0.0, 0.0];
+ results = Statistics.normalizeSamples(samples);
+ assert.deepEqual(results.normalized_samples, [0.5, 0.5]);
+ assert.deepEqual(results.scale, 1.0);
+
+ samples = [0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0];
+ results = Statistics.normalizeSamples(samples);
+ assert.deepEqual(results.normalized_samples,
+ [1.0 / 8.0, 3.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0]);
+ assert.deepEqual(results.scale, 0.75);
+
+ samples = [1.0 / 8.0, 3.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0];
+ results = Statistics.normalizeSamples(samples);
+ assert.deepEqual(results.normalized_samples, samples);
+ assert.deepEqual(results.scale, 1.0);
+ });
+
+ /**
+ *Tests NormalizeSamples and Discrepancy with random samples.
+ *
+ * Generates 10 sets of 10 random samples, computes the discrepancy,
+ * relaxes the samples using Llloyd's algorithm in 1D, and computes the
+ * discrepancy of the relaxed samples. Discrepancy of the relaxed samples
+ * must be less than or equal to the discrepancy of the original samples.
+ **/
+ test('discrepancy_Random', function() {
+ for (let i = 0; i < 10; i++) {
+ const samples = Statistics.normalizeSamples(
+ createRandomSamples(10)).normalized_samples;
+ const d = Statistics.discrepancy(samples);
+ const relaxedSamples = relax(samples);
+ const dRelaxed = Statistics.discrepancy(relaxedSamples);
+ assert.isBelow(dRelaxed, d);
+ }
+ });
+
+
+ /* Computes discrepancy for sample sets with known statistics. */
+ test('discrepancy_Analytic', function() {
+ let samples = [];
+ let d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 0.0);
+
+ samples = [0.5];
+ d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 0.5);
+
+ samples = [0.0, 1.0];
+ d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 1.0);
+
+ samples = [0.5, 0.5, 0.5];
+ d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 1.0);
+
+ samples = [1.0 / 8.0, 3.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0];
+ d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 0.25);
+
+ samples = [1.0 / 8.0, 5.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0];
+ d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 0.5);
+
+ samples = [1.0 / 8.0, 3.0 / 8.0, 5.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0];
+ d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 0.4);
+
+ samples = [0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0];
+ d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 0.5);
+
+ samples = Statistics.normalizeSamples(samples).normalized_samples;
+ d = Statistics.discrepancy(samples);
+ assert.strictEqual(d, 0.25);
+ });
+
+ test('timestampsDiscrepancy', function() {
+ let timestamps = [];
+ let dAbs = Statistics.timestampsDiscrepancy(timestamps, true);
+ assert.strictEqual(dAbs, 0.0);
+
+ timestamps = [4];
+ dAbs = Statistics.timestampsDiscrepancy(timestamps, true);
+ assert.strictEqual(dAbs, 0.5);
+
+ const timestampsA = [0, 1, 2, 3, 5, 6];
+ const timestampsB = [0, 1, 2, 3, 5, 7];
+ const timestampsC = [0, 2, 3, 4];
+ const timestampsD = [0, 2, 3, 4, 5];
+
+
+ const dAbsA = Statistics.timestampsDiscrepancy(timestampsA, true);
+ const dAbsB = Statistics.timestampsDiscrepancy(timestampsB, true);
+ const dAbsC = Statistics.timestampsDiscrepancy(timestampsC, true);
+ const dAbsD = Statistics.timestampsDiscrepancy(timestampsD, true);
+ const dRelA = Statistics.timestampsDiscrepancy(timestampsA, false);
+ const dRelB = Statistics.timestampsDiscrepancy(timestampsB, false);
+ const dRelC = Statistics.timestampsDiscrepancy(timestampsC, false);
+ const dRelD = Statistics.timestampsDiscrepancy(timestampsD, false);
+
+
+ assert.isBelow(dAbsA, dAbsB);
+ assert.isBelow(dRelA, dRelB);
+ assert.isBelow(dRelD, dRelC);
+ assert.closeTo(dAbsD, dAbsC, 0.0001);
+ });
+
+ test('discrepancyMultipleRanges', function() {
+ const samples = [[0.0, 1.2, 2.3, 3.3], [6.3, 7.5, 8.4], [4.2, 5.4, 5.9]];
+ const d0 = Statistics.timestampsDiscrepancy(samples[0]);
+ const d1 = Statistics.timestampsDiscrepancy(samples[1]);
+ const d2 = Statistics.timestampsDiscrepancy(samples[2]);
+ const d = Statistics.timestampsDiscrepancy(samples);
+ assert.strictEqual(d, Math.max(d0, d1, d2));
+ });
+
+ /**
+ * Tests approimate discrepancy implementation by comparing to exact
+ * solution.
+ **/
+ test('approximateDiscrepancy', function() {
+ for (let i = 0; i < 5; i++) {
+ let samples = createRandomSamples(10);
+ samples = Statistics.normalizeSamples(samples).normalized_samples;
+ const d = Statistics.discrepancy(samples);
+ const dApprox = Statistics.discrepancy(samples, 500);
+ assert.closeTo(d, dApprox, 0.01);
+ }
+ });
+
+ test('uniformlySampleArray', function() {
+ const samples = ['A', 'B', 'C', 'D', 'E'];
+ for (let i = samples.length; i >= 0; --i) {
+ Statistics.uniformlySampleArray(samples, i);
+ assert.lengthOf(samples, i);
+ }
+ });
+
+ test('uniformlySampleStream', function() {
+ let samples = [];
+ Statistics.uniformlySampleStream(samples, 1, 'A', 5);
+ assert.deepEqual(['A'], samples);
+ Statistics.uniformlySampleStream(samples, 2, 'B', 5);
+ Statistics.uniformlySampleStream(samples, 3, 'C', 5);
+ Statistics.uniformlySampleStream(samples, 4, 'D', 5);
+ Statistics.uniformlySampleStream(samples, 5, 'E', 5);
+ assert.deepEqual(['A', 'B', 'C', 'D', 'E'], samples);
+
+ Statistics.uniformlySampleStream(samples, 6, 'F', 5);
+ // Can't really assert anything more than the length since the elements are
+ // drawn at random.
+ assert.strictEqual(samples.length, 5);
+
+ // Try starting with a non-empty array.
+ samples = [0, 0, 0];
+ Statistics.uniformlySampleStream(samples, 1, 'G', 5);
+ assert.deepEqual(['G', 0, 0], samples);
+ });
+
+ test('mergeSampledStreams', function() {
+ let samples = [];
+ Statistics.mergeSampledStreams(samples, 0, ['A'], 1, 5);
+ assert.deepEqual(['A'], samples);
+ Statistics.mergeSampledStreams(samples, 1, ['B', 'C', 'D', 'E'], 4, 5);
+ assert.deepEqual(['A', 'B', 'C', 'D', 'E'], samples);
+
+ Statistics.mergeSampledStreams(samples, 9, ['F', 'G', 'H', 'I', 'J'], 7, 5);
+ // Can't really assert anything more than the length since the elements are
+ // drawn at random.
+ assert.strictEqual(samples.length, 5);
+
+ samples = ['A', 'B'];
+ Statistics.mergeSampledStreams(samples, 2, ['F', 'G', 'H', 'I', 'J'], 7, 5);
+ assert.strictEqual(samples.length, 5);
+ });
+
+ test('mannWhitneyUTestSmokeTest', function() {
+ // x < 0.01
+ let sampleA = [1, 2, 2.1, 2.2, 2, 1];
+ let sampleB = [12, 13, 13.1, 13.2, 13, 12];
+ let results = Statistics.mwu(sampleA, sampleB);
+ assert.isBelow(results.p, Statistics.DEFAULT_ALPHA);
+
+ assert.strictEqual(results.significance,
+ Statistics.Significance.SIGNIFICANT);
+ assert.strictEqual(results.compare(Statistics.DEFAULT_ALPHA / 10),
+ Statistics.Significance.INSIGNIFICANT);
+ assert.strictEqual(results.significance,
+ Statistics.Significance.INSIGNIFICANT);
+
+ // 0.01 < x < 0.1
+ sampleA = [1, 2, 2.1, 2.2, 2, 1];
+ sampleB = [2, 3, 3.1, 3.2, 3, 2];
+ results = Statistics.mwu(sampleA, sampleB);
+ assert.isBelow(results.p, 0.1);
+ assert.isAbove(results.p, 0.01);
+
+ // 0.1 < x
+ sampleA = [1, 2, 2.1, 2.2, 2, 1];
+ sampleB = [1, 2, 2.1, 2.2, 2, 1];
+ results = Statistics.mwu(sampleA, sampleB);
+ assert.isAbove(results.p, 0.1);
+ });
+
+ test('mannWhitneyUEdgeCases', function() {
+ const longRepeatingSample = [
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ ];
+ const emptySample = [];
+ const singleLargeValue = [1000000];
+ // mean 10, std 2
+ const normallyDistributedSample = [
+ 8.341540e+0, 7.216640e+0, 8.844310e+0, 9.801980e+0, 1.048760e+1,
+ 6.915150e+0, 7.881740e+0, 1.131160e+1, 9.959400e+0, 9.030880e+0
+ ];
+ // Identical samples should not cause the null to be rejected.
+ let results = Statistics.mwu(longRepeatingSample, longRepeatingSample);
+ assert.isAbove(results.p, 0.05);
+ results = Statistics.mwu(normallyDistributedSample,
+ normallyDistributedSample);
+ assert.isAbove(results.p, 0.05);
+ results = Statistics.mwu(singleLargeValue, singleLargeValue);
+
+ // A single value is generally not sufficient to reject the null, no matter
+ // how far off it is.
+ results = Statistics.mwu(normallyDistributedSample, singleLargeValue);
+ assert.isAbove(results.p, 0.05);
+
+ // A single value way outside the first sample may be enough to reject,
+ // if the first sample is large enough.
+ results = Statistics.mwu(longRepeatingSample, singleLargeValue);
+ assert.isBelow(results.p, 0.005);
+
+ // Empty samples should not be comparable.
+ results = Statistics.mwu(emptySample, emptySample);
+ assert(isNaN(results.p));
+
+ results = Statistics.mwu(
+ emptySample, emptySample, Statistics.DEFAULT_ALPHA, 1);
+ assert.strictEqual(results.significance,
+ Statistics.Significance.NEED_MORE_DATA);
+ assert.strictEqual(results.compare(0.9),
+ Statistics.Significance.NEED_MORE_DATA);
+ assert.strictEqual(results.significance,
+ Statistics.Significance.NEED_MORE_DATA);
+
+ // The result of comparing a sample against an empty sample should not be a
+ // valid p value. NOTE: The current implementation returns 0, it is up to
+ // the caller to interpret this.
+ results = Statistics.mwu(normallyDistributedSample, emptySample);
+ assert(!results.p);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/multi_dimensional_view.html b/chromium/third_party/catapult/tracing/tracing/base/multi_dimensional_view.html
new file mode 100644
index 00000000000..03468c6c2aa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/multi_dimensional_view.html
@@ -0,0 +1,1217 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Multi-dimensional view data structure.
+ *
+ * A multi-dimensional view provides a hierarchical representation of a
+ * collection of multi-dimensional paths with associated scalar values. Unlike
+ * separate single-dimensional views (e.g. one tree for each dimension),
+ * multi-dimensional views facilitate aggregation over combinations of
+ * substrings of the path dimensions (rather than just substrings of a single
+ * path dimension).
+ *
+ * Every view consists of multi-dimensional nodes (see MultiDimensionalViewNode
+ * for more details). This file also provides a builder class for constructing
+ * top-down and bottom-up representations of arbitrary collections of
+ * multi-dimensional paths (see MultiDimensionalViewBuilder for more details).
+ *
+ * Example: Given the following collection of two dimensional paths:
+ *
+ * <===================== Path =====================> <== Total values ===>
+ * <------- dimension 0 -------> <- dimension 1 -> <- v 0 -> <- v 1 ->
+ * [['Run()', 'Exec()', 'Call()'], ['Obj', 'View'] ]: [1 , 3
+ * [['Run()', 'Exec()', 'Call()'], ['Obj', 'Widget']]: [2 , 5
+ * [['Run()', 'Exec()', 'Load()'], ['Obj'] ]: [4 , 11
+ * [['Run()', 'Exec()'] , ['int'] ]: [8 , 7
+ * [['Run()'] , ['Obj', 'Window']]: [16 , 0
+ * [['Stop()'] , ['Obj'] ]: [32 , 13
+ *
+ * a multi-dimensional view provides a recursive breakdown of the aggregated
+ * values, e.g. (total values shown in square brackets):
+ *
+ * (root): [63, 39]
+ * |
+ * | break down by 0th dimension
+ * v
+ * Run(): [31, 26]
+ * |
+ * | break down by 0th dimension
+ * v
+ * Exec(): [15, 26]
+ * |
+ * | break down by 1st dimension
+ * v
+ * Obj: [7, 19]
+ * |
+ * | break down by 0th dimension again
+ * v
+ * Call(): [3, 8]
+ * |
+ * | break down by 1st dimension again
+ * v
+ * View: [1, 3]
+ *
+ * Observe that the recursive breakdown above is over both dimensions.
+ * Furthermore, the underlying single-dimension paths (Run() -> Exec() -> Call()
+ * and Obj -> View) can be arbitrarily interleaved in the breakdown.
+ */
+tr.exportTo('tr.b', function() {
+ /**
+ * Node of a multi-dimensional view.
+ *
+ * The structure of a view is encoded in the nodes using links to their
+ * children wrt each dimension. The diagram below shows how the nodes
+ * corresponding to the following four two-dimensional view paths:
+ *
+ * 1. [['A', 'B'], ['1', '2']]
+ * 2. [['A', 'C'], ['1', '2']]
+ * 3. [['A', 'B'], ['1', '3']]
+ * 4. [['A', 'C'], ['1', '3']]
+ *
+ * can be reached from the root of a two-dimensional view using these links
+ * ('*' stands for undefined):
+ *
+ * +---------------------+
+ * | title: [*,*] (root) |
+ * +---------------------+
+ * children wrt children wrt
+ * 0th dimension 1st dimension
+ * | :
+ * _______A________| :........1.........
+ * | :
+ * v v
+ * +--------------+ +--------------+
+ * | title: [A,*] | | title: [*,1] |
+ * +--------------+ +--------------+
+ * children wrt children wrt children wrt children wrt
+ * 0th dimension 1st dimension 0th dimension 1st dimension
+ * | | :.....1...... _____A_____| : :
+ * _B_| |__C__ : | ...2..: :.3..
+ * | | : | : :
+ * v v v v v v
+ * +-------+ +-------+ +-------+ +-------+ +-------+
+ * | [B,*] | | [C,*] | | [A,1] | | [*,2] | | [*,3] |
+ * +-------+ +-------+ +-------+ +-------+ +-------+
+ * : ___:_____B______| | : :......3.....|.... |
+ * :.1.. | :.1.. __C___| :...2... _A_| : _A_|
+ * : | : | : | : |
+ * v v v v v v v v
+ * +-------+ +-------+ +-------+ +-------+
+ * | [B,1] | | [C,1] | | [A,2] | | [A,3] |
+ * +-------+ +-------+ +-------+ +-------+
+ * : : : :.......3.......||.......... ||
+ * : :..3....:................ BC : BC
+ * : ______:_______________:___|| : ||
+ * 2 | 2 _______:____| ______:___||
+ * : | : | : | : |
+ * v v v v v v v v
+ * +----------+ +----------+ +----------+ +----------+
+ * | [B,2] | | [C,2] | | [B,3] | | [C,3] |
+ * | (node 1) | | (node 2) | | (node 3) | | (node 4) |
+ * +----------+ +----------+ +----------+ +----------+
+ *
+ * The self/total values of a node represents the aggregated values of all
+ * paths (in the collection from which the view was built) matching the node
+ * excluding/including the node's descendants.
+ *
+ * Terminology examples:
+ *
+ * - Children of [A,*] wrt 0th dimension: [B,*], [C,*]
+ * - Children of [A,*] (wrt all dimensions): [B,*], [C,*], [A,1]
+ * - Descendants of [A,*] wrt 1st dimension: [A,1], [A,2], [A,3]
+ * - Single-dimensional descendants of [A,*]: [A,1], [A,2], [A,3], [B,*],
+ * [C,*]
+ * - Descendants of [A,*] (wrt all dimensions): [A,1], [A,2], [A,3], [B,*],
+ * [C,*], [B,1], [C,1], [B,2], [C,2], [B,3], [C,3]
+ *
+ * @{constructor}
+ */
+ function MultiDimensionalViewNode(title, valueCount) {
+ // List of titles of this node wrt each dimension.
+ this.title = title;
+
+ // Map from child name to child node for each dimension.
+ const dimensions = title.length;
+ this.children = new Array(dimensions);
+ for (let i = 0; i < dimensions; i++) {
+ this.children[i] = new Map();
+ }
+
+ // For each value index (from 0 to |valueCount| - 1), we store the self and
+ // total values together with a Boolean flag whether the value is only a
+ // lower bound (i.e. aggregated from children rather than provided
+ // directly).
+ this.values = new Array(valueCount);
+ for (let v = 0; v < valueCount; v++) {
+ this.values[v] = { self: 0, total: 0, totalState: NOT_PROVIDED };
+ }
+ }
+
+ /**
+ * States of total values stored in multi-dimensional view nodes.
+ *
+ * @enum
+ */
+ MultiDimensionalViewNode.TotalState = {
+ // Neither total nor self value was provided for either the node or any of
+ // its descendants.
+ NOT_PROVIDED: 0,
+
+ // The total value was NOT provided for the node, but the self value was
+ // provided for the node or the total or self value was provided for at
+ // least one of its descendants.
+ LOWER_BOUND: 1,
+
+ // The total value was provided for the node.
+ EXACT: 2
+ };
+ // Cache the total value states to avoid repeated object field lookups.
+ const NOT_PROVIDED = MultiDimensionalViewNode.TotalState.NOT_PROVIDED;
+ const LOWER_BOUND = MultiDimensionalViewNode.TotalState.LOWER_BOUND;
+ const EXACT = MultiDimensionalViewNode.TotalState.EXACT;
+
+ MultiDimensionalViewNode.prototype = {
+ /** Duck type <tr-ui-b-table> rows. */
+ get subRows() {
+ return Array.from(this.children[0].values());
+ }
+ };
+
+ /**
+ * Builder for multi-dimensional views.
+ *
+ * Given a collection of multi-dimensional paths, a builder can be used to
+ * construct the following three representations of the paths:
+ *
+ * 1. Top-down tree view
+ * A multi-dimensional path in the view corresponds to all paths in the
+ * collection that have it as their prefix.
+ *
+ * 2. Top-down heavy view
+ * A multi-dimensional path in the view corresponds to all paths in the
+ * collection that have it as their substring
+ *
+ * 3. Bottom-up heavy view
+ * A multi-dimensional path in the view corresponds to all paths in the
+ * collection that have it as their substring reversed.
+ *
+ * For example, the following collection of 2-dimensional paths (with single
+ * values):
+ *
+ * 2-dimensional path | self
+ * Time (0th dimension) | Activity (1st dimension) | value
+ * ========================+========================+=======
+ * Saturday | Cooking | 1 h
+ * Saturday | Sports -> Football | 2 h
+ * Sunday | Sports -> Basketball | 3 h
+ *
+ * gives rise to the following top-down tree view, which aggregates the
+ * scalar values over prefixes of the given paths:
+ *
+ * +---------+
+ * | * |
+ * | * |
+ * | self=0 |
+ * | total=6 |
+ * +---------+
+ * | : | :
+ * _________Cooking_______| : | :............Sunday............
+ * | : | :
+ * | ...Saturday..: |_Sports_ :
+ * | : | :
+ * v v v v
+ * +---------+ +---------+ +---------+ +---------+
+ * | * | | Sat | | * | | Sun |
+ * | Cooking | | * | | Sports | | * |
+ * | self=0 | | self=0 | | self=0 | | self=0 |
+ * | total=1 | | total=3 | | total=5 | | total=3 |
+ * +---------+ +---------+ +---------+ +---------+
+ * : | | : | | : |
+ * Saturday | Sports : | | : Sports
+ * : | | .....Saturday....: | | :.....Sunday....... |
+ * : _Cook_| | : _Foot_| |_Bask_ : |
+ * : | | : | | : |
+ * v v v v v v v v
+ * +---------+ +---------+ +------------+ +--------------+ +---------+
+ * | Sat | | Sat | | * | | * | | Sun |
+ * | Cooking | | Sports | | S/Football | | S/Basketball | | Sports |
+ * | self=1 | | self=0 | | self=0 | | self=0 | | self=0 |
+ * | total=1 | | total=2 | | total=2 | | total=3 | | total=3 |
+ * +---------+ +---------+ +------------+ +--------------+ +---------+
+ * | : : |
+ * |_Foot_ ..Sat.: :.Sun.. _Bask_|
+ * | : : |
+ * v v v v
+ * +------------+ +--------------+
+ * | Sat | | Sun |
+ * | S/Football | | S/Basketball |
+ * | self=2 | | self=3 |
+ * | total=2 | | total=3 |
+ * +------------+ +--------------+
+ *
+ * To build a multi-dimensional view of a collection of multi-dimensional
+ * paths, you create a builder, add the paths to it and then use it to
+ * construct the view. For example, the following code generates the
+ * 2-dimensional top-down tree view shown above:
+ *
+ * const builder = new MultiDimensionalViewBuilder(2);
+ * builder.addPath([['Saturday'], ['Cooking']], [1], SELF);
+ * builder.addPath([['Saturday'], ['Sports', 'Football']], [2], SELF);
+ * builder.addPath([['Sunday'], ['Sports', 'Basketball']], [3], SELF);
+ * const treeViewRoot = builder.buildTopDownTreeView();
+ *
+ * The heavy views can be constructed analogously (by calling
+ * buildTopDownHeavyView() or buildBottomUpHeavyView() at the end instead).
+ *
+ * Note that the same builder can be used to construct both the tree and
+ * heavy views (for the same collection of paths). However, no more paths can
+ * be added once either view has been built.
+ *
+ * @{constructor}
+ */
+ function MultiDimensionalViewBuilder(dimensions, valueCount) {
+ if (typeof(dimensions) !== 'number' || dimensions < 0) {
+ throw new Error('Dimensions must be a non-negative number');
+ }
+ this.dimensions_ = dimensions;
+
+ if (typeof(valueCount) !== 'number' || valueCount < 0) {
+ throw new Error('Number of values must be a non-negative number');
+ }
+ this.valueCount_ = valueCount;
+
+ this.buildRoot_ = this.createRootNode_();
+ this.topDownTreeViewRoot_ = undefined;
+ this.topDownHeavyViewRoot_ = undefined;
+ this.bottomUpHeavyViewNode_ = undefined;
+ this.complete_ = false;
+
+ this.maxDimensionDepths_ = new Array(dimensions);
+ for (let d = 0; d < dimensions; d++) {
+ this.maxDimensionDepths_[d] = 0;
+ }
+ }
+
+ /** @{enum} */
+ MultiDimensionalViewBuilder.ValueKind = {
+ SELF: 0,
+ TOTAL: 1
+ };
+
+ /**
+ * Types of multi-dimensional views provided by MultiDimensionalViewBuilder.
+ *
+ * @enum
+ */
+ MultiDimensionalViewBuilder.ViewType = {
+ TOP_DOWN_TREE_VIEW: 0,
+ TOP_DOWN_HEAVY_VIEW: 1,
+ BOTTOM_UP_HEAVY_VIEW: 2
+ };
+
+ MultiDimensionalViewBuilder.prototype = {
+ /**
+ * Add values associated with a multi-dimensional path to the tree.
+ *
+ * The path must have the same number of dimensions as the builder. Its
+ * elements must be single-dimension paths (lists of strings) of arbitrary
+ * length (empty for the root of the given dimension). Starting from the
+ * root of the tree, each single-dimension path is traversed from left to
+ * right to reach the node corresponding to the whole path.
+ *
+ * The length of the provided list of values must be equal to the builder's
+ * value count. The builder supports adding both kinds of values
+ * (self/total) wrt all value indices for an arbitrary multi-dimensional
+ * path. The rationale for adding total values (in addition to/instead of
+ * self values) is to cater for missing sub-paths. Example: Consider the
+ * following collection of single-dimensional paths (with single values):
+ *
+ * [['Loop::Run()', 'Execute()', 'FunctionBig']]: self=99000
+ * [['Loop::Run()', 'Execute()', 'FunctionSmall1']]: self=1
+ * [['Loop::Run()', 'Execute()', 'FunctionSmall2']]: self=1
+ * ...
+ * [['Loop::Run()', 'Execute()', 'FunctionSmall1000']]: self=1
+ *
+ * If we required that only self values could be added to the builder, then
+ * all of the 1001 paths would need to be provided (most likely in a trace)
+ * to obtain the correct total of [['Loop::Run()', 'Execute()']]. However,
+ * since we allow adding total values as well, only the following 2 paths
+ * need to be provided to get the correct numbers explaining 99% of the
+ * aggregated total value:
+ *
+ * [['Loop::Run()', 'Execute()']]: total=100000
+ * [['Loop::Run()', 'Execute()', 'FunctionBig']]: self=99000
+ *
+ * In other words, the long tail containing 1000 small paths need not be
+ * dumped (greatly reducing the size of a trace where applicable).
+ *
+ * Important: No paths can be added to a builder once either view has been
+ * built!
+ */
+ addPath(path, values, valueKind) {
+ if (this.buildRoot_ === undefined) {
+ throw new Error(
+ 'Paths cannot be added after either view has been built');
+ }
+ if (path.length !== this.dimensions_) {
+ throw new Error('Path must be ' + this.dimensions_ + '-dimensional');
+ }
+ if (values.length !== this.valueCount_) {
+ throw new Error('Must provide ' + this.valueCount_ + ' values');
+ }
+
+ let isTotal;
+ switch (valueKind) {
+ case MultiDimensionalViewBuilder.ValueKind.SELF:
+ isTotal = false;
+ break;
+ case MultiDimensionalViewBuilder.ValueKind.TOTAL:
+ isTotal = true;
+ break;
+ default:
+ throw new Error('Invalid value kind: ' + valueKind);
+ }
+
+ let node = this.buildRoot_;
+ for (let d = 0; d < path.length; d++) {
+ const singleDimensionPath = path[d];
+ const singleDimensionPathLength = singleDimensionPath.length;
+ this.maxDimensionDepths_[d] =
+ Math.max(this.maxDimensionDepths_[d], singleDimensionPathLength);
+ for (let i = 0; i < singleDimensionPathLength; i++) {
+ node = this.getOrCreateChildNode_(node, d, singleDimensionPath[i]);
+ }
+ }
+
+ for (let v = 0; v < this.valueCount_; v++) {
+ const addedValue = values[v];
+ if (addedValue === undefined) continue;
+ const nodeValue = node.values[v];
+ if (isTotal) {
+ nodeValue.total += addedValue;
+ nodeValue.totalState = EXACT;
+ } else {
+ nodeValue.self += addedValue;
+ nodeValue.totalState = Math.max(nodeValue.totalState, LOWER_BOUND);
+ }
+ }
+ },
+
+
+ get complete() {
+ return this.complete_;
+ },
+
+ /**
+ * Force all MultiDimensionalViewNode's to have totalState EXACT.
+ * Set to true only if all SELF paths for the tree have been provided.
+ * Setting unnecessary if providing TOTAL values.
+ *
+ * MultiDimensionalViewBuilder allows both 'self' and 'total' values to be
+ * entered for paths then later when the veiws are constructed it
+ * determines the total and whether that total is exact or a lower bound
+ * for each node. When total values are provided we know that that total
+ * is exact however when self values are provided the computed totals
+ * *could* be complete ...if the user has provided the all the self
+ * values for the whole tree. We can't know this within the
+ * MultiDimensionalViewBuilder so this flag allows the user to specify
+ * that this is the case.
+ *
+ * Important: Can't be set once any view has been built.
+ */
+ set complete(isComplete) {
+ if (this.buildRoot_ === undefined) {
+ throw new Error('Can\'t set complete after any view has been built.');
+ }
+ this.complete_ = isComplete;
+ },
+
+ buildView(viewType) {
+ switch (viewType) {
+ case MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW:
+ return this.buildTopDownTreeView();
+ case MultiDimensionalViewBuilder.ViewType.TOP_DOWN_HEAVY_VIEW:
+ return this.buildTopDownHeavyView();
+ case MultiDimensionalViewBuilder.ViewType.BOTTOM_UP_HEAVY_VIEW:
+ return this.buildBottomUpHeavyView();
+ default:
+ throw new Error('Unknown multi-dimensional view type: ' + viewType);
+ }
+ },
+
+ /**
+ * Build the top-down tree view of the multi-dimensional view.
+ *
+ * Note that no more paths can be added to the builder once either view has
+ * been built.
+ */
+ buildTopDownTreeView() {
+ if (this.topDownTreeViewRoot_ === undefined) {
+ const treeViewRoot = this.buildRoot_;
+ this.buildRoot_ = undefined;
+
+ this.setUpMissingChildRelationships_(treeViewRoot,
+ 0 /* firstDimensionToSetUp */);
+ this.finalizeTotalValues_(treeViewRoot,
+ 0 /* firstDimensionToFinalize */,
+ new WeakMap() /* dimensionalSelfSumsMap */);
+
+ this.topDownTreeViewRoot_ = treeViewRoot;
+ }
+
+ return this.topDownTreeViewRoot_;
+ },
+
+ /**
+ * Build the top-down heavy view of the multi-dimensional view.
+ *
+ * Note that no more paths can be added to the builder once either view has
+ * been built.
+ */
+ buildTopDownHeavyView() {
+ if (this.topDownHeavyViewRoot_ === undefined) {
+ this.topDownHeavyViewRoot_ = this.buildGenericHeavyView_(
+ this.addDimensionToTopDownHeavyViewNode_.bind(this));
+ }
+ return this.topDownHeavyViewRoot_;
+ },
+
+ /**
+ * Build the bottom-up heavy view of the multi-dimensional view.
+ *
+ * Note that no more paths can be added to the builder once either view has
+ * been built.
+ */
+ buildBottomUpHeavyView() {
+ if (this.bottomUpHeavyViewNode_ === undefined) {
+ this.bottomUpHeavyViewNode_ = this.buildGenericHeavyView_(
+ this.addDimensionToBottomUpHeavyViewNode_.bind(this));
+ }
+ return this.bottomUpHeavyViewNode_;
+ },
+
+ createRootNode_() {
+ return new MultiDimensionalViewNode(
+ new Array(this.dimensions_) /* title */, this.valueCount_);
+ },
+
+ getOrCreateChildNode_(
+ parentNode, dimension, childDimensionTitle) {
+ if (dimension < 0 || dimension >= this.dimensions_) {
+ throw new Error('Invalid dimension');
+ }
+
+ const dimensionChildren = parentNode.children[dimension];
+
+ let childNode = dimensionChildren.get(childDimensionTitle);
+ if (childNode !== undefined) {
+ return childNode;
+ }
+
+ const childTitle = parentNode.title.slice();
+ childTitle[dimension] = childDimensionTitle;
+ childNode = new MultiDimensionalViewNode(childTitle, this.valueCount_);
+ dimensionChildren.set(childDimensionTitle, childNode);
+
+ return childNode;
+ },
+
+ /**
+ * Set up missing child relationships.
+ *
+ * When an arbitrary multi-dimensional path [path1, path2, ..., pathN] is
+ * added to the build tree (see addPath), only the nodes on the path1 ->
+ * path2 -> ... -> pathN chain are created (i.e. no interleavings of the
+ * single-dimensional paths are added to the tree). This method recursively
+ * adds all the missing paths.
+ *
+ * Two-dimensional example:
+ *
+ * Initial build tree . After path . After missing child
+ * (root only) . [[A, B], [1, 2]] . relationships were
+ * . was added . set up
+ * . .
+ * +---+ . +---+ . +---+
+ * |*,*| . |*,*| . |*,*|
+ * +---+ . +---+ . +---+
+ * . A . A 1
+ * . | . | :
+ * . v . v V
+ * . +---+ . +---+ +---+
+ * . |A,*| . |A,*| |*,1|
+ * . +---+ . +---+ +---+
+ * . B . B 1 A 2
+ * . | . | : | :
+ * . v . v v v v
+ * . +---+ . +---+ +---+ +---+
+ * . |B,*| . |B,*| |A,1| |*,2|
+ * . +---+ . +---+ +---+ +---+
+ * . 1 . 1 B 2 A
+ * . : . : | : |
+ * . v . v v v v
+ * . +---+ . +---+ +---+
+ * . |B,1| . |B,1| |A,2|
+ * . +---+ . +---+ +---+
+ * . 2 . 2 B
+ * . : . : |
+ * . v . v V
+ * . +---+ . +---+
+ * . |B,2| . |B,2|
+ * . +---+ . +---+
+ */
+ setUpMissingChildRelationships_(node, firstDimensionToSetUp) {
+ // Missing child relationships of this node wrt dimensions 0, ...,
+ // (firstDimensionToSetUp - 1) and all descendants of the associated
+ // children have already been set up. Now we do the same for dimensions
+ // firstDimensionToSetUp, ..., (this.dimensions_ - 1).
+ for (let d = firstDimensionToSetUp; d < this.dimensions_; d++) {
+ // Step 1. Gather the names of all children wrt the current dimension.
+ const currentDimensionChildTitles = new Set(node.children[d].keys());
+ for (let i = 0; i < d; i++) {
+ for (const previousDimensionChildNode of node.children[i].values()) {
+ for (const previousDimensionGrandChildTitle of
+ previousDimensionChildNode.children[d].keys()) {
+ currentDimensionChildTitles.add(previousDimensionGrandChildTitle);
+ }
+ }
+ }
+
+ // Step 2. Add missing children wrt the current dimension and
+ // recursively set up its missing child relationships.
+ for (const currentDimensionChildTitle of currentDimensionChildTitles) {
+ // Add a missing child (if it doesn't exist).
+ const currentDimensionChildNode =
+ this.getOrCreateChildNode_(node, d, currentDimensionChildTitle);
+
+ // Set-up child relationships (of the child node) wrt dimensions 0,
+ // ..., d - 1.
+ for (let i = 0; i < d; i++) {
+ for (const previousDimensionChildNode of
+ node.children[i].values()) {
+ const previousDimensionGrandChildNode =
+ previousDimensionChildNode.children[d].get(
+ currentDimensionChildTitle);
+ if (previousDimensionGrandChildNode !== undefined) {
+ currentDimensionChildNode.children[i].set(
+ previousDimensionChildNode.title[i],
+ previousDimensionGrandChildNode);
+ }
+ }
+ }
+
+ // Set-up child relationships (of the child node) wrt dimensions d,
+ // ..., (this.dimensions_ - 1).
+ this.setUpMissingChildRelationships_(currentDimensionChildNode, d);
+ }
+ }
+ },
+
+ /**
+ * Finalize the total values of a multi-dimensional tree.
+ *
+ * The intermediate builder tree, a node of which we want to finalize
+ * recursively, already has the right shape. The only thing that needs to
+ * be done is to propagate self and total values from subsumed child nodes
+ * in each dimension and update total value states appropriately.
+ *
+ * To derive the expression for the lower bound on the total value wrt
+ * value index V (from 1 to |this.valueCount_| - 1), we rely on the
+ * following assumptions:
+ *
+ * 1. Self/total values associated with different value indices are
+ * independent. From this point onwards, "self/total value" refers to
+ * self/total value wrt the fixed value index V.
+ *
+ * 2. Each node's self value does NOT overlap with the self or total value
+ * of any other node.
+ *
+ * 3. The total values of a node's children wrt a single dimension (e.g.
+ * [path1/A, path2] and [path1/B, path2]) do NOT overlap.
+ *
+ * 4. The total values of a node's children wrt different dimensions
+ * (e.g. [path1/A, path2] and [path1, path2/1]) MIGHT overlap.
+ *
+ * As a consequence of assumptions 1 and 3, the total value of a node can
+ * be split into the part that cannot overlap (so-called "self-sum") and
+ * the part that can overlap (so-called "residual"):
+ *
+ * total(N, V) = selfSum(N, V) + residual(N, V) (A)
+ *
+ * where the self-sum is calculated as the sum of the node's self value
+ * plus the sum of its descendants' self values (summed over all
+ * dimensions):
+ *
+ * selfSum(N, V) = self(N, V) + sum over all descendants C of N {
+ * self(C, V) (B)
+ * }
+ *
+ * Observe that the residual of a node does not include any self value (of
+ * any node in the view). Furthermore, by assumption 2, we derive that the
+ * residuals of a node's children wrt a single dimension don't overlap. On
+ * the other hand, the residuals of a node's children wrt different
+ * dimensions might overlap. This gives us the following lower bound on the
+ * residual of a node:
+ *
+ * residual(N, V) >= minResidual(N, V) = max over dimensions D {
+ * sum over children C of N at dimension D {
+ * residual(C, V) (C)
+ * }
+ * })
+ *
+ * By combining equation (A) and inequality (C), we get a lower bound on
+ * the total value of a node:
+ *
+ * total(N, V) >= selfSum(N, V) + minResidual(N, V)
+ *
+ * For example, given a two-dimensional node [path1, path2] with self value
+ * 10 and four children (2 wrt each dimension):
+ *
+ * Child | Self value | Total value
+ * ==================+============+=============
+ * [path1/A, path2] | 21 | 30
+ * [path1/B, path2] | 25 | 32
+ * [path1, path2/1] | 3 | 15
+ * [path1, path2/2] | 40 | 41
+ *
+ * and assuming that the children have no further descendants (i.e. their
+ * residual values are equal to the differences between their total and
+ * self values), the lower bound on the total value of [path1, path2] is:
+ *
+ * total([path1, path2], 0)
+ * >= selfSum([path1, path2], 0) +
+ * minResidual([path1, path2], 0)
+ * = self([path1, path2], 0) +
+ * sum over all descendants C of [path1, path2] {
+ * self (C, 0)
+ * } +
+ * max over dimensions D {
+ * sum over children C of [path1, path2] at dimension D {
+ * residual(C, 0)
+ * }
+ * }
+ * = self([path1, path2], 0) +
+ * ((self([path1/A, path2], 0) + self([path1/B, path2], 0)) +
+ * (self([path1, path2/1], 0) + self([path1, path2/2], 0))) +
+ * max(residual([path1/A, path2], 0) +
+ * residual([path1/B, path2], 0),
+ * residual([path1, path2/1], 0) +
+ * residual([path1, path2/2], 0))
+ * = 10 +
+ * ((21 + 25) + (3 + 40)) +
+ * max((30 - 21) + (32 - 25), (15 - 3) + (41 - 40))
+ * = 115
+ *
+ * To reduce the complexity of the calculation, we keep a temporary list of
+ * dimensional self-sums for each node that we have already visited. For a
+ * given node, the Kth element in the list is equal to the self size of the
+ * node plus the sum of self sizes of all its descendants wrt dimensions 0
+ * to K (inclusive). The list has two important properties:
+ *
+ * 1. The last element in the list is equal to the self-sum of the
+ * associated node (equation (B)).
+ *
+ * 2. The calculation of the list can be performed recursively using the
+ * lists of the associated node's children (avoids square complexity
+ * in the size of the graph):
+ *
+ * dimensionalSelfSum(N, V)[D] =
+ * self(N, V) +
+ * sum I = 0 to D {
+ * sum over children C of N at dimension I {
+ * dimensionalSelfSum(C, V)[I]
+ * }
+ * }
+ *
+ * This method also (recursively) ensures that, for each value index V, if
+ * at least one of the descendants C of node N has at least a LOWER_BOUND
+ * on total(C, V), then the N will also be marked as having a LOWER_BOUND
+ * on total(N, V) (unless N contains the EXACT value of total(N, V), in
+ * which case its relevant totalState won't be modified).
+ */
+ finalizeTotalValues_(
+ node, firstDimensionToFinalize, dimensionalSelfSumsMap) {
+ // Dimension D -> Value index V -> dimensionalSelfSum(|node|, V)[D].
+ const dimensionalSelfSums = new Array(this.dimensions_);
+
+ // Value index V -> minResidual(|node|, V).
+ const minResidual = new Array(this.valueCount_);
+ for (let v = 0; v < this.valueCount_; v++) minResidual[v] = 0;
+
+ // Value index V -> |node| value V.
+ const nodeValues = node.values;
+
+ // Value index V -> dimensionalSelfSum(|node|, V)[|d|].
+ const nodeSelfSums = new Array(this.valueCount_);
+ for (let v = 0; v < this.valueCount_; v++) {
+ nodeSelfSums[v] = nodeValues[v].self;
+ }
+
+ for (let d = 0; d < this.dimensions_; d++) {
+ // Value index V -> sum over children C of |node| at dimension |d| {
+ // residual(C, V) }.
+ const childResidualSums = new Array(this.valueCount_);
+ for (let v = 0; v < this.valueCount_; v++) {
+ childResidualSums[v] = 0;
+ }
+
+ for (const childNode of node.children[d].values()) {
+ if (d >= firstDimensionToFinalize) {
+ this.finalizeTotalValues_(childNode, d, dimensionalSelfSumsMap);
+ }
+ // Dimension D -> Value index V ->
+ // dimensionalSelfSum(|childNode|, V)[D].
+ const childNodeSelfSums = dimensionalSelfSumsMap.get(childNode);
+ const childNodeValues = childNode.values;
+ for (let v = 0; v < this.valueCount_; v++) {
+ nodeSelfSums[v] += childNodeSelfSums[d][v];
+ const residual = childNodeValues[v].total -
+ childNodeSelfSums[this.dimensions_ - 1][v];
+ childResidualSums[v] += residual;
+ if (this.complete) {
+ nodeValues[v].totalState = EXACT;
+ } else if (childNodeValues[v].totalState > NOT_PROVIDED) {
+ nodeValues[v].totalState = Math.max(
+ nodeValues[v].totalState, LOWER_BOUND);
+ }
+ }
+ }
+
+ dimensionalSelfSums[d] = nodeSelfSums.slice();
+ for (let v = 0; v < this.valueCount_; v++) {
+ minResidual[v] = Math.max(minResidual[v], childResidualSums[v]);
+ }
+ }
+
+ for (let v = 0; v < this.valueCount_; v++) {
+ nodeValues[v].total = Math.max(
+ nodeValues[v].total, nodeSelfSums[v] + minResidual[v]);
+ }
+
+ if (dimensionalSelfSumsMap.has(node)) {
+ throw new Error('Internal error: Node finalized more than once');
+ }
+ dimensionalSelfSumsMap.set(node, dimensionalSelfSums);
+ },
+
+ /**
+ * Build a generic heavy view of the multi-dimensional view.
+ */
+ buildGenericHeavyView_(treeViewNodeHandler) {
+ // 1. Clone the root node of the top-down tree view node (except
+ // children).
+ const treeViewRoot = this.buildTopDownTreeView();
+ const heavyViewRoot = this.createRootNode_();
+ heavyViewRoot.values = treeViewRoot.values;
+
+ // 2. Create recursion depth trackers (to avoid total value
+ // double-counting).
+ const recursionDepthTrackers = new Array(this.dimensions_);
+ for (let d = 0; d < this.dimensions_; d++) {
+ recursionDepthTrackers[d] =
+ new RecursionDepthTracker(this.maxDimensionDepths_[d], d);
+ }
+
+ // 3. Add all paths associated with the single-dimensional descendants of
+ // the top-down tree view root node to the heavy view root node
+ // (depending on the type of the target heavy view).
+ this.addDimensionsToGenericHeavyViewNode_(treeViewRoot, heavyViewRoot,
+ 0 /* startDimension */, recursionDepthTrackers,
+ false /* previousDimensionsRecursive */, treeViewNodeHandler);
+
+ // 4. Set up missing child relationships.
+ this.setUpMissingChildRelationships_(heavyViewRoot,
+ 0 /* firstDimensionToSetUp */);
+
+ return heavyViewRoot;
+ },
+
+ /**
+ * Add all paths associated with the single-dimensional descendants of a
+ * top-down tree-view node wrt multiple dimensions to a generic heavy-view
+ * node (depending on the type of the target heavy view).
+ */
+ addDimensionsToGenericHeavyViewNode_(treeViewParentNode,
+ heavyViewParentNode, startDimension, recursionDepthTrackers,
+ previousDimensionsRecursive, treeViewNodeHandler) {
+ for (let d = startDimension; d < this.dimensions_; d++) {
+ this.addDimensionDescendantsToGenericHeavyViewNode_(treeViewParentNode,
+ heavyViewParentNode, d, recursionDepthTrackers,
+ previousDimensionsRecursive, treeViewNodeHandler);
+ }
+ },
+
+ /**
+ * Add all paths associated with the descendants of a top-down tree-view
+ * node wrt a single dimension to a generic heavy-view node (depending on
+ * the type of the target heavy view).
+ */
+ addDimensionDescendantsToGenericHeavyViewNode_(treeViewParentNode,
+ heavyViewParentNode, currentDimension, recursionDepthTrackers,
+ previousDimensionsRecursive, treeViewNodeHandler) {
+ const treeViewChildren = treeViewParentNode.children[currentDimension];
+ const recursionDepthTracker = recursionDepthTrackers[currentDimension];
+ for (const treeViewChildNode of treeViewChildren.values()) {
+ recursionDepthTracker.push(treeViewChildNode);
+
+ // Add all paths associated with the child node to the heavy view-node
+ // parent node.
+ treeViewNodeHandler(
+ treeViewChildNode, heavyViewParentNode, currentDimension,
+ recursionDepthTrackers, previousDimensionsRecursive);
+
+ // Recursively add all paths associated with the descendants of the
+ // tree view child node wrt the current dimension to the heavy-view
+ // parent node.
+ this.addDimensionDescendantsToGenericHeavyViewNode_(treeViewChildNode,
+ heavyViewParentNode, currentDimension, recursionDepthTrackers,
+ previousDimensionsRecursive, treeViewNodeHandler);
+
+ recursionDepthTracker.pop();
+ }
+ },
+
+ /**
+ * Add a top-down tree-view child node together with its single-dimensional
+ * subtree to a top-down heavy-view parent node (tree-view node handler for
+ * top-down heavy view).
+ *
+ * Sample resulting top-down heavy view:
+ *
+ * +----------------+ +-----------------+
+ * | source | | destination |
+ * | tree-view root | ===============> | heavy-view root |
+ * | self=0 | | self=0 |
+ * | total=48 | | total=48 |
+ * +----------------+ +-----------------+
+ * | | ______| | |______
+ * v v v v v
+ * +----------+ +----------+ +----------+ +----------+ +----------+
+ * | A* | | B | | A*** | | B | | C |
+ * | self=10 | | self=12 | | self=13 | | self=13 | | self=2 |
+ * | total=30 | | total=18 | | total=30 | | total=34 | | total=7 |
+ * +----------+ +----------+ +----------+ +----------+ +----------+
+ * | : : :.........
+ * v v v v
+ * +----------+ ............ ............ ............
+ * | B | : B : : A : : C :
+ * | self=1 | : self=1 : : self=3 : : self=2 :
+ * | total=16 | : total=16 : : total=8 : : total=7 :
+ * +----------+ ............ ............ ............
+ * | |________ : :.........
+ * v v v v
+ * +----------+ +----------+ ............ ............
+ * | A** | | C | : A : : C :
+ * | self=3 | | self=2 | : self=3 : : self=2 :
+ * | total=8 | | total=7 | : total=8 : : total=7 :
+ * +----------+ +----------+ ............ ............
+ *
+ * Observe that care needs to be taken when dealing with recursion to avoid
+ * double-counting, e.g. the total value of A** (8) was not added to the
+ * total value of A*** (30) because it is already included in the total
+ * value of A* (30) (which was also added to A***). That is why we need to
+ * keep track of the path we traversed along the current dimension (to
+ * determine whether total value should be added or not).
+ */
+ addDimensionToTopDownHeavyViewNode_(
+ treeViewChildNode, heavyViewParentNode, currentDimension,
+ recursionDepthTrackers, previousDimensionsRecursive) {
+ this.addDimensionToTopDownHeavyViewNodeRecursively_(treeViewChildNode,
+ heavyViewParentNode, currentDimension, recursionDepthTrackers,
+ previousDimensionsRecursive, 1 /* subTreeDepth */);
+ },
+
+ addDimensionToTopDownHeavyViewNodeRecursively_(
+ treeViewChildNode, heavyViewParentNode, currentDimension,
+ recursionDepthTrackers, previousDimensionsRecursive, subTreeDepth) {
+ const recursionDepthTracker = recursionDepthTrackers[currentDimension];
+ const currentDimensionRecursive =
+ subTreeDepth <= recursionDepthTracker.recursionDepth;
+ const currentOrPreviousDimensionsRecursive =
+ currentDimensionRecursive || previousDimensionsRecursive;
+
+ const dimensionTitle = treeViewChildNode.title[currentDimension];
+ const heavyViewChildNode = this.getOrCreateChildNode_(
+ heavyViewParentNode, currentDimension, dimensionTitle);
+
+ this.addNodeValues_(treeViewChildNode, heavyViewChildNode,
+ !currentOrPreviousDimensionsRecursive /* addTotal */);
+
+ // Add the descendants of the tree-view child node wrt the next
+ // dimensions as children of the heavy-view child node.
+ this.addDimensionsToGenericHeavyViewNode_(treeViewChildNode,
+ heavyViewChildNode, currentDimension + 1, recursionDepthTrackers,
+ currentOrPreviousDimensionsRecursive,
+ this.addDimensionToTopDownHeavyViewNode_.bind(this));
+
+ for (const treeViewGrandChildNode of
+ treeViewChildNode.children[currentDimension].values()) {
+ recursionDepthTracker.push(treeViewGrandChildNode);
+
+ // Recursively add the tree-view grandchild node to the heavy-view
+ // child node.
+ this.addDimensionToTopDownHeavyViewNodeRecursively_(
+ treeViewGrandChildNode, heavyViewChildNode, currentDimension,
+ recursionDepthTrackers, previousDimensionsRecursive,
+ subTreeDepth + 1);
+
+ recursionDepthTracker.pop();
+ }
+ },
+
+ /**
+ * Add a top-down tree-view child node together with all its ancestors wrt
+ * the given dimension as descendants of a bottom-up heavy-view parent node
+ * in the reverse order (tree-view node handler for bottom-up heavy view).
+ *
+ * Sample resulting bottom-up heavy view:
+ *
+ * +----------------+ +-----------------+
+ * | source | | destination |
+ * | tree-view root | ===============> | heavy-view root |
+ * | self=0 | | self=0 |
+ * | total=48 | | total=48 |
+ * +----------------+ +-----------------+
+ * | | ______| | |______
+ * v v v v v
+ * +----------+ +----------+ +----------+ +----------+ +----------+
+ * | A* | | B | | A*** | | B | | C |
+ * | self=10 | | self=12 | | self=13 | | self=13 | | self=2 |
+ * | total=30 | | total=18 | | total=30 | | total=34 | | total=7 |
+ * +----------+ +----------+ +----------+ +----------+ +----------+
+ * | : : :
+ * v v v v
+ * +----------+ ............ ............ ............
+ * | B# | : B : : A : : B## :
+ * | self=1 | : self=3 : : self=1 : : self=2 :
+ * | total=16 | : total=8 : : total=16 : : total=7 :
+ * +----------+ ............ ............ ............
+ * | |________ : :
+ * v v v v
+ * +----------+ +----------+ ............ ............
+ * | A** | | C | : A : : A :
+ * | self=3 | | self=2 | : self=3 : : self=2 :
+ * | total=8 | | total=7 | : total=8 : : total=7 :
+ * +----------+ +----------+ ............ ............
+ *
+ * Similarly to the construction of the top-down heavy view, care needs to
+ * be taken when dealing with recursion to avoid double-counting, e.g. the
+ * total value of A** (8) was not added to the total value of A*** (30)
+ * because it is already included in the total value of A* (30) (which was
+ * also added to A***). That is why we need to keep track of the path we
+ * traversed along the current dimension (to determine whether total value
+ * should be added or not).
+ *
+ * Note that when we add an ancestor (B#) of a top-down tree-view node (C)
+ * to the bottom-up heavy view, the values of the original tree-view node
+ * (C) (rather than the ancestor's values) are added to the corresponding
+ * heavy-view node (B##).
+ */
+ addDimensionToBottomUpHeavyViewNode_(
+ treeViewChildNode, heavyViewParentNode, currentDimension,
+ recursionDepthTrackers, previousDimensionsRecursive) {
+ const recursionDepthTracker = recursionDepthTrackers[currentDimension];
+ const bottomIndex = recursionDepthTracker.bottomIndex;
+ const topIndex = recursionDepthTracker.topIndex;
+ const firstNonRecursiveIndex =
+ bottomIndex + recursionDepthTracker.recursionDepth;
+ const viewNodePath = recursionDepthTracker.viewNodePath;
+
+ const trackerAncestorNode = recursionDepthTracker.trackerAncestorNode;
+ let heavyViewDescendantNode = heavyViewParentNode;
+ for (let i = bottomIndex; i < topIndex; i++) {
+ const treeViewAncestorNode = viewNodePath[i];
+ const dimensionTitle = treeViewAncestorNode.title[currentDimension];
+ heavyViewDescendantNode = this.getOrCreateChildNode_(
+ heavyViewDescendantNode, currentDimension, dimensionTitle);
+
+ const currentDimensionRecursive = i < firstNonRecursiveIndex;
+ const currentOrPreviousDimensionsRecursive =
+ currentDimensionRecursive || previousDimensionsRecursive;
+
+ // The self and total values are taken from the original top-down tree
+ // view child node (rather than the ancestor node).
+ this.addNodeValues_(treeViewChildNode, heavyViewDescendantNode,
+ !currentOrPreviousDimensionsRecursive);
+
+ // Add the descendants of the tree-view child node wrt the next
+ // dimensions as children of the heavy-view child node.
+ this.addDimensionsToGenericHeavyViewNode_(treeViewChildNode,
+ heavyViewDescendantNode, currentDimension + 1,
+ recursionDepthTrackers, currentOrPreviousDimensionsRecursive,
+ this.addDimensionToBottomUpHeavyViewNode_.bind(this));
+ }
+ },
+
+ addNodeValues_(sourceNode, targetNode, addTotal) {
+ const targetNodeValues = targetNode.values;
+ const sourceNodeValues = sourceNode.values;
+ for (let v = 0; v < this.valueCount_; v++) {
+ const targetNodeValue = targetNodeValues[v];
+ const sourceNodeValue = sourceNodeValues[v];
+ targetNodeValue.self += sourceNodeValue.self;
+ if (addTotal) {
+ targetNodeValue.total += sourceNodeValue.total;
+ if (this.complete) {
+ targetNodeValue.totalState = EXACT;
+ } else if (sourceNodeValue.totalState > NOT_PROVIDED) {
+ targetNodeValue.totalState = Math.max(
+ targetNodeValue.totalState, LOWER_BOUND);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Recursion depth tracker.
+ *
+ * This class tracks the recursion depth of the current stack (updated via
+ * the push and pop methods). The recursion depth of a stack is the lengh of
+ * its longest leaf suffix that is repeated within the stack itself.
+ *
+ * For example, the recursion depth of the stack A -> B -> C -> A -> B -> B
+ * -> C (where C is the leaf node) is 2 because the suffix B -> C is repeated
+ * within it.
+ *
+ * @{constructor}
+ */
+ function RecursionDepthTracker(maxDepth, dimension) {
+ this.titlePath = new Array(maxDepth);
+ this.viewNodePath = new Array(maxDepth);
+ this.bottomIndex = this.topIndex = maxDepth;
+
+ this.dimension_ = dimension;
+ this.currentTrackerNode_ =
+ this.createNode_(0 /* recursionDepth */, undefined /* parent */);
+ }
+
+ RecursionDepthTracker.prototype = {
+ push(viewNode) {
+ if (this.bottomIndex === 0) {
+ throw new Error('Cannot push to a full tracker');
+ }
+ const title = viewNode.title[this.dimension_];
+ this.bottomIndex--;
+ this.titlePath[this.bottomIndex] = title;
+ this.viewNodePath[this.bottomIndex] = viewNode;
+
+ let childTrackerNode = this.currentTrackerNode_.children.get(title);
+ if (childTrackerNode !== undefined) {
+ // Child node already exists, so we don't need to calculate anything.
+ this.currentTrackerNode_ = childTrackerNode;
+ return;
+ }
+
+ // Child node doesn't exist yet, so we need to calculate its recursion
+ // depth.
+ const maxLengths = zFunction(this.titlePath, this.bottomIndex);
+ let recursionDepth = 0;
+ for (let i = 0; i < maxLengths.length; i++) {
+ recursionDepth = Math.max(recursionDepth, maxLengths[i]);
+ }
+
+ childTrackerNode =
+ this.createNode_(recursionDepth, this.currentTrackerNode_);
+ this.currentTrackerNode_.children.set(title, childTrackerNode);
+ this.currentTrackerNode_ = childTrackerNode;
+ },
+
+ pop() {
+ if (this.bottomIndex === this.topIndex) {
+ throw new Error('Cannot pop from an empty tracker');
+ }
+
+ this.titlePath[this.bottomIndex] = undefined;
+ this.viewNodePath[this.bottomIndex] = undefined;
+ this.bottomIndex++;
+
+ this.currentTrackerNode_ = this.currentTrackerNode_.parent;
+ },
+
+ get recursionDepth() {
+ return this.currentTrackerNode_.recursionDepth;
+ },
+
+ createNode_(recursionDepth, parent) {
+ return {
+ recursionDepth,
+ parent,
+ children: new Map()
+ };
+ }
+ };
+
+ /**
+ * Calculate the Z-function of (a suffix of) a list.
+ *
+ * Z-function: Given a list (or a string) of length n, for each index i from
+ * 1 to n - 1, find the length z[i] of the longest substring starting at
+ * position i which is also a prefix of the list. This function returns the
+ * list of maximum lengths z.
+ *
+ * Mathematically, for each i from 1 to n - 1, z[i] is the maximum value such
+ * that [list[0], ..., list[i - 1]] = [list[i], ..., list[i + z[i] - 1]].
+ * z[0] is defined to be zero for convenience.
+ *
+ * Example:
+ *
+ * Input (list): ['A', 'B', 'A', 'C', 'A', 'B', 'A']
+ * Output (z): [ 0 , 0 , 1 , 0 , 3 , 0 , 1 ]
+ *
+ * Unlike the brute-force approach (which is O(n^2) in the worst case), the
+ * complexity of this implementation is linear in the size of the list, i.e.
+ * O(n).
+ *
+ * Source: http://e-maxx-eng.github.io/string/z-function.html
+ */
+ function zFunction(list, startIndex) {
+ const n = list.length - startIndex;
+ if (n === 0) return [];
+
+ const z = new Array(n);
+ z[0] = 0;
+
+ for (let i = 1, left = 0, right = 0; i < n; ++i) {
+ let maxLength;
+ if (i <= right) {
+ maxLength = Math.min(right - i + 1, z[i - left]);
+ } else {
+ maxLength = 0;
+ }
+
+ while (i + maxLength < n && list[startIndex + maxLength] ===
+ list[startIndex + i + maxLength]) {
+ ++maxLength;
+ }
+
+ if (i + maxLength - 1 > right) {
+ left = i;
+ right = i + maxLength - 1;
+ }
+
+ z[i] = maxLength;
+ }
+
+ return z;
+ }
+
+ return {
+ MultiDimensionalViewBuilder,
+ MultiDimensionalViewNode,
+
+ // Exports below are for testing only.
+ RecursionDepthTracker,
+ zFunction,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/multi_dimensional_view_test.html b/chromium/third_party/catapult/tracing/tracing/base/multi_dimensional_view_test.html
new file mode 100644
index 00000000000..b51d738617e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/multi_dimensional_view_test.html
@@ -0,0 +1,13382 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/multi_dimensional_view.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const MultiDimensionalViewBuilder = tr.b.MultiDimensionalViewBuilder;
+ const MultiDimensionalViewNode = tr.b.MultiDimensionalViewNode;
+ const ViewType = MultiDimensionalViewBuilder.ViewType;
+ const SELF = MultiDimensionalViewBuilder.ValueKind.SELF;
+ const TOTAL = MultiDimensionalViewBuilder.ValueKind.TOTAL;
+ const NOT_PROVIDED = MultiDimensionalViewNode.TotalState.NOT_PROVIDED;
+ const LOWER_BOUND = MultiDimensionalViewNode.TotalState.LOWER_BOUND;
+ const EXACT = MultiDimensionalViewNode.TotalState.EXACT;
+ const RecursionDepthTracker = tr.b.RecursionDepthTracker;
+ const zFunction = tr.b.zFunction;
+
+ function assertListStrictEqual(a, b) {
+ assert.lengthOf(a, b.length);
+ for (let i = 0; i < a.length; i++) {
+ assert.strictEqual(a[i], b[i]);
+ }
+ }
+
+ function checkTree(actualTreeRootNode, expectedStructureRootNode) {
+ // Build map from expected structure node IDs to expected structure nodes.
+ const expectedStructureNodesById = new Map();
+ addExpectedStructureToMap(
+ expectedStructureRootNode, expectedStructureNodesById);
+
+ // Recursively check the structure of the actual tree.
+ const actualTreeNodesById = new Map();
+ checkTreeStructure(actualTreeRootNode, expectedStructureRootNode,
+ actualTreeNodesById, expectedStructureNodesById);
+
+ // Test sanity check.
+ assert.strictEqual(
+ actualTreeNodesById.size, expectedStructureNodesById.size);
+ }
+
+ function addExpectedStructureToMap(expectedStructureNode, map) {
+ if (typeof expectedStructureNode === 'string') {
+ return; // Reference to another expected structure node.
+ }
+
+ const expectedStructureNodeId = expectedStructureNode.id;
+ if (expectedStructureNodeId !== undefined) {
+ assert.isFalse(map.has(expectedStructureNodeId));
+ map.set(expectedStructureNodeId, expectedStructureNode);
+ }
+
+ const expectedStructureChildren = expectedStructureNode.children;
+ for (let d = 0; d < expectedStructureChildren.length; d++) {
+ const expectedStructureDimensionChildren = expectedStructureChildren[d];
+ for (let i = 0; i < expectedStructureDimensionChildren.length; i++) {
+ addExpectedStructureToMap(expectedStructureDimensionChildren[i], map);
+ }
+ }
+ }
+
+ function checkTreeStructure(actualTreeNode, expectedStructureNode,
+ actualTreeNodesById, expectedStructureNodesById) {
+ // Check the multi-dimensional title.
+ assert.deepEqual(
+ Array.from(actualTreeNode.title), expectedStructureNode.title);
+
+ // Check the values.
+ assert.deepEqual(actualTreeNode.values, expectedStructureNode.values);
+
+ // Check the children.
+ const expectedStructureChildNodes = expectedStructureNode.children;
+ const actualTreeChildNodes = actualTreeNode.children;
+ assert.lengthOf(actualTreeChildNodes, expectedStructureChildNodes.length);
+
+ for (let d = 0; d < expectedStructureChildNodes.length; d++) {
+ const expectedStructureDimensionChildNodes =
+ expectedStructureChildNodes[d];
+ const actualTreeDimensionChildNodes = actualTreeChildNodes[d];
+ assert.strictEqual(actualTreeDimensionChildNodes.size,
+ expectedStructureDimensionChildNodes.length);
+
+ const expectedStructureDimensionChildNodeTitles = new Set();
+
+ for (let i = 0; i < expectedStructureDimensionChildNodes.length; i++) {
+ let expectedStructureDimensionChildNode =
+ expectedStructureDimensionChildNodes[i];
+ let isReference = false;
+
+ // If the expected structure child node is a reference to another
+ // expected structure node, resolve it.
+ if (typeof expectedStructureDimensionChildNode === 'string') {
+ expectedStructureDimensionChildNode = expectedStructureNodesById.get(
+ expectedStructureDimensionChildNode);
+ assert.isDefined(expectedStructureDimensionChildNode);
+ isReference = true;
+ }
+
+ // Check that the expected structure doesn't contain two children with
+ // the same title.
+ const childTitle = expectedStructureDimensionChildNode.title[d];
+ assert.isFalse(
+ expectedStructureDimensionChildNodeTitles.has(childTitle));
+ expectedStructureDimensionChildNodeTitles.add(childTitle);
+
+ // Get the associated child node of the actual tree.
+ const actualTreeDimensionChildNode =
+ actualTreeDimensionChildNodes.get(childTitle);
+ assert.isDefined(actualTreeDimensionChildNode);
+
+ // Check that all expected structure nodes with the same ID correspond
+ // to the same actual tree node.
+ const childId = expectedStructureDimensionChildNode.id;
+ if (childId !== undefined) {
+ if (actualTreeNodesById.has(childId)) {
+ assert.strictEqual(actualTreeDimensionChildNode,
+ actualTreeNodesById.get(childId));
+ } else {
+ actualTreeNodesById.set(childId, actualTreeDimensionChildNode);
+ }
+ }
+
+ // Recursively check the structure of the actual tree child node
+ // (unless the expected structure child node was a reference).
+ if (!isReference) {
+ checkTreeStructure(actualTreeDimensionChildNode,
+ expectedStructureDimensionChildNode, actualTreeNodesById,
+ expectedStructureNodesById);
+ }
+ }
+
+ // Test sanity check (all child titles should be unique).
+ assert.strictEqual(expectedStructureDimensionChildNodeTitles.size,
+ expectedStructureDimensionChildNodes.length);
+ }
+ }
+
+ function createBuilderWithEntries(dimensions, valueCount, pathEntries) {
+ const builder = new MultiDimensionalViewBuilder(dimensions, valueCount);
+ pathEntries.forEach(function(pathEntry) {
+ builder.addPath(pathEntry.path, pathEntry.values, pathEntry.kind);
+ });
+ return builder;
+ }
+
+ function builderTest(testName, dimensions, valueCount, setComplete,
+ pathEntries, expectedTopDownTreeViewStructure,
+ expectedTopDownHeavyViewStructure, expectedBottomUpHeavyViewStructure) {
+ test('builder_' + testName, function() {
+ // Create a multi-dimensional tree builder and add all paths to it.
+ const builder =
+ createBuilderWithEntries(dimensions, valueCount, pathEntries);
+ builder.complete = setComplete;
+
+ // Build and check the views.
+ checkTree(
+ builder.buildView(ViewType.TOP_DOWN_TREE_VIEW),
+ expectedTopDownTreeViewStructure);
+ checkTree(
+ builder.buildView(ViewType.TOP_DOWN_HEAVY_VIEW),
+ expectedTopDownHeavyViewStructure);
+ checkTree(
+ builder.buildView(ViewType.BOTTOM_UP_HEAVY_VIEW),
+ expectedBottomUpHeavyViewStructure);
+ });
+ }
+
+ /**
+ * Calculate the sum of binary powers.
+ *
+ * Each exponent can either be (1) a single number corresponding to a single
+ * power of two (2**exponent), or (2) a two-element list for a sum over a
+ * range of exponents (2**exponent[0] + 2**(exponent[0] + 1) + ... +
+ * 2**exponent[1]).
+ */
+ function b(/* exponent1, ..., exponentN */) {
+ let sum = 0;
+ for (let i = 0; i < arguments.length; i++) {
+ const exponent = arguments[i];
+ if (typeof exponent === 'number') {
+ sum += 1 << arguments[i];
+ } else {
+ assert.lengthOf(exponent, 2); // Test sanity check.
+ // We use the fact that 2**A + 2**(A + 1) ... + 2**B =
+ // (2**0 + 2**1 + ... 2**B) - (2**0 + 2**1 + ... + 2**(A - 1)) =
+ // (2**(B + 1) - 1) - (2**A - 1) = 2**(B + 1) - 2**A.
+ sum += (1 << (exponent[1] + 1)) - (1 << exponent[0]);
+ }
+ }
+ return sum;
+ }
+
+ function checkZFunction(list, expectedResult) {
+ if (typeof list === 'string') {
+ assert.deepEqual(zFunction(list, 0), expectedResult);
+ assert.deepEqual(zFunction(list[0] + list, 1), expectedResult);
+ assert.deepEqual(zFunction(list + list, list.length), expectedResult);
+ } else {
+ assert.deepEqual(zFunction([].concat(list), 0), expectedResult);
+ assert.deepEqual(zFunction([list[0]].concat(list), 1), expectedResult);
+ assert.deepEqual(
+ zFunction(list.concat(list), list.length), expectedResult);
+ }
+ }
+
+ /**
+ * Helper function for generating builder tests. Given a number of dimensions
+ * and a list of path entries, this function generates the source code of
+ * the corresponding builder test with expected top-down tree view, top-down
+ * heavy view and bottom-up heavy view structures.
+ *
+ * This avoids the need to write such tests manually, which is very tedious.
+ * However, the correctness of the generated structures needs to be verified
+ * by the developer! Maximum line length must also be enforced manually.
+ */
+ function generateBuilderTest(
+ targetTestName, dimensions, valueCount, pathEntries) {
+ test('builderTestGenerator_' + targetTestName, function() {
+ // Create the builder.
+ const builder =
+ createBuilderWithEntries(dimensions, valueCount, pathEntries);
+
+ // Generate the test case source code.
+ const generator = new tr.c.TestUtils.SourceGenerator();
+ generator.indentBlock(2, false /* don't break line */, function() {
+ // Test name and number of dimensions (first line).
+ generator.push('builderTest(\'', targetTestName, '\', ',
+ String(dimensions), ' /* dimensions */, ',
+ String(valueCount), ' /* valueCount */,');
+
+ generator.indentBlock(4, true /* break line */, function() {
+ // Path entries.
+ generator.formatMultiLineList(pathEntries, function(pathEntry) {
+ generator.push('{ path: ');
+ generator.formatSingleLineList(
+ pathEntry.path,
+ function(singleDimensionPath) {
+ generator.formatSingleLineList(
+ singleDimensionPath, generator.formatString, generator);
+ });
+ generator.push(', values: ');
+ generator.formatSingleLineList(
+ pathEntry.values,
+ function(value) {
+ generator.push(String(value));
+ });
+ const kind = pathEntry.kind === SELF ? 'SELF' : 'TOTAL';
+ generator.push(', kind: ', kind, ' }');
+ });
+ generator.push(',');
+ generator.breakLine();
+
+ function formatExpectedTreeStructure(root, label) {
+ let nextNodeId = 0;
+ const nodeInfos = new WeakMap();
+
+ function assignNodeIdsToRepeatedNodes(node) {
+ if (nodeInfos.has(node)) {
+ // We have already visited the node (one or more times), so
+ // there is no need to visit its children.
+ if (nodeInfos.get(node) === undefined) {
+ // This is the second time we visited the node: Change the
+ // undefined entry to a defined node info entry.
+ nodeInfos.set(node, { id: undefined });
+ }
+ return;
+ }
+
+ // This is the first time we visited the node: Add an undefined
+ // entry to the node info map and recursively visit all its
+ // children.
+ nodeInfos.set(node, undefined);
+ node.children.forEach(function(singleDimensionChildren) {
+ for (const child of singleDimensionChildren.values()) {
+ assignNodeIdsToRepeatedNodes(child);
+ }
+ });
+ }
+ assignNodeIdsToRepeatedNodes(root);
+
+ // Track the multi-dimensional path to the current node to generate
+ // comments.
+ const paths = new Array(dimensions);
+ for (let i = 0; i < paths.length; i++) {
+ paths[i] = [];
+ }
+ function withChild(childNode, dimension, callback) {
+ paths[dimension].push(childNode.title[dimension]);
+ callback();
+ paths[dimension].pop();
+ }
+ function appendPathComment(opt_label) {
+ if (opt_label) {
+ generator.pushComment(opt_label);
+ return;
+ }
+
+ paths.forEach(function(dimensionPath, dimensionIndex) {
+ if (dimensionIndex > 0) {
+ generator.pushComment(', ');
+ }
+ if (dimensionPath.length === 0) {
+ generator.pushComment('*');
+ return;
+ }
+ dimensionPath.forEach(function(ancestorTitle, ancestorIndex) {
+ if (ancestorIndex > 0) {
+ generator.pushComment(' -> ');
+ }
+ generator.pushComment(ancestorTitle);
+ });
+ });
+ }
+
+ function formatExpectedTreeStructureRecursively(node, opt_label) {
+ let nodeId = undefined;
+ const nodeInfo = nodeInfos.get(node);
+ if (nodeInfo !== undefined) {
+ // This node is referenced multiple times in the expected tree
+ // structure.
+ nodeId = nodeInfo.id;
+ if (nodeId === undefined) {
+ // This is the first time we visited the node: Assign it a
+ // unique node id and then format it and its descendants
+ // recursively.
+ nodeId = '#' + (nextNodeId++);
+ nodeInfo.id = nodeId;
+ } else {
+ // We have already visited this node: Just insert the node's
+ // id (instead of formatting it and its descendants
+ // recursively again).
+ generator.push('\'', nodeId, '\'');
+ appendPathComment();
+ return;
+ }
+ }
+
+ generator.push('{');
+ appendPathComment(opt_label);
+
+ generator.indentBlock(2, true /* break line */, function() {
+ // Node id (if defined).
+ if (nodeId !== undefined) {
+ generator.push('id: \'', nodeId, '\',');
+ generator.breakLine();
+ }
+
+ // Node title.
+ generator.push('title: ');
+ generator.formatSingleLineList(
+ node.title, generator.formatString, generator);
+ generator.push(',');
+ generator.breakLine();
+
+ // Node values.
+ generator.push('values: ');
+ generator.formatMultiLineList(
+ node.values,
+ function(value) {
+ generator.push('{');
+ generator.indentBlock(2, true /* break line */,
+ function() {
+ generator.push('total: ', String(value.total), ',');
+ generator.breakLine();
+ generator.push('self: ', String(value.self), ',');
+ generator.breakLine();
+ generator.push('totalState: ');
+
+ let totalStateName;
+ for (const [name, state] of Object.entries(
+ MultiDimensionalViewNode.TotalState)) {
+ if (state === value.totalState) {
+ totalStateName = name;
+ break;
+ }
+ }
+ if (totalStateName === undefined) {
+ throw new Error(
+ 'Unknown total state: ' + value.totalState);
+ }
+ generator.push(totalStateName);
+ generator.breakLine();
+ });
+ generator.push('}');
+ });
+ generator.push(',');
+ generator.breakLine();
+
+ // Node children.
+ const children = node.children;
+ generator.push('children: ');
+ generator.formatMultiLineList(
+ children,
+ function(singleDimensionChildren, dimension) {
+ generator.formatMultiLineList(
+ Array.from(singleDimensionChildren.values()),
+ function(child, childIndex) {
+ withChild(child, dimension, function() {
+ formatExpectedTreeStructureRecursively(child);
+ });
+ });
+ });
+ });
+ generator.breakLine();
+ generator.push('}');
+ }
+
+ formatExpectedTreeStructureRecursively(root, label);
+ }
+
+ // Build and format the three multi-dimensional views.
+ formatExpectedTreeStructure(
+ builder.buildTopDownTreeView(), 'Top-down tree view');
+ generator.push(',');
+ generator.breakLine();
+ formatExpectedTreeStructure(
+ builder.buildTopDownHeavyView(), 'Top-down heavy view');
+ generator.push(',');
+ generator.breakLine();
+ formatExpectedTreeStructure(
+ builder.buildBottomUpHeavyView(), 'Bottom-up heavy view');
+ generator.push(');');
+ });
+ });
+
+ tr.c.TestUtils.addSourceListing(this, generator.build());
+
+ throw new Error('This error is thrown to prevent accidentally ' +
+ 'checking in a test generator instead of an actual test.');
+ });
+ }
+
+ builderTest('zeroDimensions_noPaths', 0 /* dimensions */, 1 /* valueCount */,
+ false /* setComplete */,
+ [],
+ { // Top-down tree view.
+ title: [],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: []
+ },
+ { // Top-down heavy view.
+ title: [],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: []
+ },
+ { // Bottom-up heavy view.
+ title: [],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: []
+ });
+
+ builderTest('zeroDimensions_withPaths', 0 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [], values: [2], kind: SELF },
+ { path: [], values: [3], kind: TOTAL },
+ { path: [], values: [4], kind: SELF },
+ { path: [], values: [5], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [],
+ values: [
+ {
+ total: 8,
+ self: 6,
+ totalState: EXACT
+ }
+ ],
+ children: []
+ },
+ { // Top-down heavy view.
+ title: [],
+ values: [
+ {
+ total: 8,
+ self: 6,
+ totalState: EXACT
+ }
+ ],
+ children: []
+ },
+ { // Bottom-up heavy view.
+ title: [],
+ values: [
+ {
+ total: 8,
+ self: 6,
+ totalState: EXACT
+ }
+ ],
+ children: []
+ });
+
+ builderTest('oneDimension_noPaths', 1 /* dimensions */, 1 /* valueCount */,
+ false /* setComplete */,
+ [],
+ { // Top-down tree view.
+ title: [undefined],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ []
+ ]
+ });
+
+ builderTest('oneDimension_zeroLengthPath', 1 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [[]], values: [42], kind: SELF }
+ ],
+ { // Top-down tree view.
+ title: [undefined],
+ values: [
+ {
+ total: 42,
+ self: 42,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 42,
+ self: 42,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 42,
+ self: 42,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ });
+
+ builderTest('oneDimension_noRecursion', 1 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['A', 'B', 'C']], values: [10], kind: SELF },
+ { path: [['A', 'B']], values: [20], kind: SELF },
+ { path: [['B', 'D']], values: [30], kind: SELF },
+ { path: [['A', 'B', 'D']], values: [40], kind: SELF },
+ { path: [['A', 'C']], values: [50], kind: SELF },
+ { path: [[]], values: [60], kind: SELF }
+ ],
+ { // Top-down tree view.
+ title: [undefined],
+ values: [
+ {
+ total: 210,
+ self: 60,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 120,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 70,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 50,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 30,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 210,
+ self: 60,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 120,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 70,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 50,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 100,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 70,
+ self: 70,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 60,
+ self: 60,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // D.
+ title: ['D'],
+ values: [
+ {
+ total: 70,
+ self: 70,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 210,
+ self: 60,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 120,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 100,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 70,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 60,
+ self: 60,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 50,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // D.
+ title: ['D'],
+ values: [
+ {
+ total: 70,
+ self: 70,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 70,
+ self: 70,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('oneDimension_simpleRecursion', 1 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['A']], values: [10], kind: SELF },
+ { path: [['A', 'A', 'A']], values: [20], kind: SELF },
+ { path: [['A', 'A']], values: [30], kind: SELF },
+ { path: [['A', 'A', 'A', 'A']], values: [40], kind: SELF }
+ ],
+ { // Top-down tree view.
+ title: [undefined],
+ values: [
+ {
+ total: 100,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 100,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 90,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 60,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A -> A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 100,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 100,
+ self: 100,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 90,
+ self: 90,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 60,
+ self: 60,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A -> A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 100,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 100,
+ self: 100,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 90,
+ self: 90,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 60,
+ self: 60,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A -> A -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('oneDimension_complexRecursion', 1 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['A', 'B', 'C']], values: [10], kind: SELF },
+ { path: [['A', 'D', 'B', 'C', 'A', 'B', 'C']], values: [20],
+ kind: SELF },
+ { path: [['A', 'D', 'B', 'C', 'A', 'B', 'D']], values: [30],
+ kind: SELF },
+ { path: [['C', 'B', 'C']], values: [40], kind: SELF },
+ { path: [['C', 'B', 'C', 'B', 'C']], values: [50], kind: SELF }
+ ],
+ { // Top-down tree view.
+ title: [undefined],
+ values: [
+ {
+ total: 150,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B -> C -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B -> C -> A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B -> C -> A ->
+ // B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A -> D -> B -> C -> A ->
+ // B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 90,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 90,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 90,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> C -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 50,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 150,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B -> C -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B -> C -> A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> D -> B -> C -> A ->
+ // B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A -> D -> B -> C -> A ->
+ // B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 150,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 150,
+ self: 120,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C -> A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C -> A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // B -> C -> A -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 50,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 150,
+ self: 120,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // C -> A -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 90,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 90,
+ self: 90,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> C -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 50,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // D.
+ title: ['D'],
+ values: [
+ {
+ total: 50,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> C -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> C -> A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> C -> A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // D -> B -> C -> A -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 150,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> C -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> C -> B -> D -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 150,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A -> C -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A -> C -> B -> D -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> D -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 90,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 150,
+ self: 120,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 150,
+ self: 120,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> A -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> A -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> A -> C -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> A -> C -> B ->
+ // D -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 20,
+ self: 20,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // C -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> D -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 90,
+ self: 90,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 50,
+ self: 50,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> C -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 50,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // D.
+ title: ['D'],
+ values: [
+ {
+ total: 50,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // D -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> A -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> A -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> A -> C -> B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> B -> A -> C -> B ->
+ // D -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 30,
+ self: 30,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('oneDimension_withTotalSizes', 1 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['B', 'C']], values: [10], kind: TOTAL },
+ { path: [['B', 'C', 'D']], values: [5], kind: TOTAL },
+ { path: [['B']], values: [15], kind: SELF },
+ { path: [['B']], values: [20], kind: TOTAL },
+ { path: [['B', 'D']], values: [40], kind: SELF },
+ { path: [['C']], values: [50], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [undefined],
+ values: [
+ {
+ total: 115,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 65,
+ self: 15,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // B -> C -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 5,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 50,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 115,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 65,
+ self: 15,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> C -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 5,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> D.
+ title: ['D'],
+ values: [
+ {
+ total: 5,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // D.
+ title: ['D'],
+ values: [
+ {
+ total: 45,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 115,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 65,
+ self: 15,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // D.
+ title: ['D'],
+ values: [
+ {
+ total: 45,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 5,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // D -> C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 5,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // D -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 40,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('oneDimension_protoTitle', 1 /* dimensions */, 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['__proto__']], values: [45], kind: SELF },
+ { path: [['A']], values: [18], kind: SELF },
+ { path: [['A', '__proto__']], values: [89], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [undefined],
+ values: [
+ {
+ total: 152,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // __proto__.
+ title: ['__proto__'],
+ values: [
+ {
+ total: 45,
+ self: 45,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 107,
+ self: 18,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> __proto__.
+ title: ['__proto__'],
+ values: [
+ {
+ total: 89,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 152,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // __proto__.
+ title: ['__proto__'],
+ values: [
+ {
+ total: 134,
+ self: 45,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 107,
+ self: 18,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> __proto__.
+ title: ['__proto__'],
+ values: [
+ {
+ total: 89,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 152,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // __proto__.
+ title: ['__proto__'],
+ values: [
+ {
+ total: 134,
+ self: 45,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // __proto__ -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 89,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 107,
+ self: 18,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ });
+
+ // See tracing/tracing/base/multi_dimensional_view.html
+ // (MultiDimensionalViewBuilder.addDimensionToTopDownHeavyViewNode_ and
+ // MultiDimensionalViewBuilder.addDimensionToBottomUpHeavyViewNode_
+ // documentation).
+ builderTest('oneDimension_documentationExample', 1 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['A']], values: [10], kind: SELF },
+ { path: [['A']], values: [30], kind: TOTAL },
+ { path: [['A', 'B']], values: [1], kind: SELF },
+ { path: [['A', 'B', 'A']], values: [3], kind: SELF },
+ { path: [['A', 'B', 'A']], values: [8], kind: TOTAL },
+ { path: [['A', 'B', 'C']], values: [2], kind: SELF },
+ { path: [['A', 'B', 'C']], values: [7], kind: TOTAL },
+ { path: [['B']], values: [12], kind: SELF },
+ { path: [['B']], values: [18], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [undefined],
+ values: [
+ {
+ total: 48,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 30,
+ self: 10,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 16,
+ self: 1,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 8,
+ self: 3,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 7,
+ self: 2,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 18,
+ self: 12,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 48,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 30,
+ self: 13,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 16,
+ self: 1,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 8,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // A -> B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 7,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 34,
+ self: 13,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 8,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ },
+ { // B -> C.
+ title: ['C'],
+ values: [
+ {
+ total: 7,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 7,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined],
+ values: [
+ {
+ total: 48,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A.
+ title: ['A'],
+ values: [
+ {
+ total: 30,
+ self: 13,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 8,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 8,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B.
+ title: ['B'],
+ values: [
+ {
+ total: 34,
+ self: 13,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 16,
+ self: 1,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C.
+ title: ['C'],
+ values: [
+ {
+ total: 7,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B.
+ title: ['B'],
+ values: [
+ {
+ total: 7,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> A.
+ title: ['A'],
+ values: [
+ {
+ total: 7,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('twoDimensions_noPaths', 2 /* dimensions */, 1 /* valueCount */,
+ false /* setComplete */,
+ [],
+ { // Top-down tree view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ });
+
+ // See tracing/tracing/base/multi_dimensional_view.html
+ // (MultiDimensionalViewNode.finalizeTotalValues_ documentation).
+ builderTest('twoDimensions_totalCalculation', 2 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [[], []], values: [10], kind: SELF },
+ { path: [['A'], []], values: [21], kind: SELF },
+ { path: [['A'], []], values: [30], kind: TOTAL },
+ { path: [['B'], []], values: [25], kind: SELF },
+ { path: [['B'], []], values: [32], kind: TOTAL },
+ { path: [[], ['1']], values: [3], kind: SELF },
+ { path: [[], ['1']], values: [15], kind: TOTAL },
+ { path: [[], ['2']], values: [40], kind: SELF },
+ { path: [[], ['2']], values: [41], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 115,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 30,
+ self: 21,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 32,
+ self: 25,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 15,
+ self: 3,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // *, 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 41,
+ self: 40,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 115,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 30,
+ self: 21,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 32,
+ self: 25,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 15,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // *, 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 41,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 115,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 30,
+ self: 21,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 32,
+ self: 25,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 15,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // *, 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 41,
+ self: 40,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ });
+
+ // See tracing/tracing/base/multi_dimensional_view.html
+ // (MultiDimensionalViewNode documentation).
+ builderTest('twoDimensions_documentationExample1', 2 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['A', 'B'], ['T1', 'T2']], values: [1], kind: TOTAL },
+ { path: [['A', 'B'], ['T1']], values: [2], kind: TOTAL },
+ { path: [['A', 'B'], []], values: [4], kind: TOTAL },
+ { path: [['A'], ['T1', 'T2']], values: [10], kind: TOTAL },
+ { path: [['A'], ['T1']], values: [20], kind: TOTAL },
+ { path: [['A'], []], values: [40], kind: TOTAL },
+ { path: [[], ['T1', 'T2']], values: [100], kind: TOTAL },
+ { path: [[], ['T1']], values: [200], kind: TOTAL },
+ { path: [[], []], values: [400], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 400,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 4,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B, T1.
+ id: '#0',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B, T1 -> T2.
+ id: '#1',
+ title: ['B', 'T2'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, T1.
+ id: '#2',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#0' // A -> B, T1.
+ ],
+ [
+ { // A, T1 -> T2.
+ id: '#3',
+ title: ['A', 'T2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#1' // A -> B, T1 -> T2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T1.
+ title: [undefined, 'T1'],
+ values: [
+ {
+ total: 200,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#2' // A, T1.
+ ],
+ [
+ { // *, T1 -> T2.
+ title: [undefined, 'T2'],
+ values: [
+ {
+ total: 100,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#3' // A, T1 -> T2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 400,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 4,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B, T1.
+ id: '#0',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B, T1 -> T2.
+ id: '#1',
+ title: ['B', 'T2'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, T2.
+ id: '#2',
+ title: ['B', 'T2'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, T1.
+ id: '#3',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // A -> B, T1.
+ ],
+ [
+ { // A, T1 -> T2.
+ id: '#4',
+ title: ['A', 'T2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1' // A -> B, T1 -> T2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, T2.
+ id: '#5',
+ title: ['A', 'T2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // A -> B, T2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 4,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B, T1.
+ id: '#6',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B, T1 -> T2.
+ id: '#7',
+ title: ['B', 'T2'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, T2.
+ id: '#8',
+ title: ['B', 'T2'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T1.
+ title: [undefined, 'T1'],
+ values: [
+ {
+ total: 200,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3', // A, T1.
+ '#6' // B, T1.
+ ],
+ [
+ { // *, T1 -> T2.
+ title: [undefined, 'T2'],
+ values: [
+ {
+ total: 100,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4', // A, T1 -> T2.
+ '#7' // B, T1 -> T2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, T2.
+ title: [undefined, 'T2'],
+ values: [
+ {
+ total: 100,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5', // A, T2.
+ '#8' // B, T2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 400,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A, T1.
+ id: '#0',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // A, T2.
+ id: '#1',
+ title: ['A', 'T2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A, T2 -> T1.
+ id: '#2',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 4,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 4,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A, T1.
+ id: '#3',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B -> A, T2.
+ id: '#4',
+ title: ['A', 'T2'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A, T2 -> T1.
+ id: '#5',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, T1.
+ id: '#6',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // B -> A, T1.
+ ],
+ []
+ ]
+ },
+ { // B, T2.
+ id: '#7',
+ title: ['B', 'T2'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // B -> A, T2.
+ ],
+ [
+ { // B, T2 -> T1.
+ id: '#8',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5' // B -> A, T2 -> T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T1.
+ title: [undefined, 'T1'],
+ values: [
+ {
+ total: 200,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0', // A, T1.
+ '#6' // B, T1.
+ ],
+ []
+ ]
+ },
+ { // *, T2.
+ title: [undefined, 'T2'],
+ values: [
+ {
+ total: 100,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1', // A, T2.
+ '#7' // B, T2.
+ ],
+ [
+ { // *, T2 -> T1.
+ title: [undefined, 'T1'],
+ values: [
+ {
+ total: 100,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2', // A, T2 -> T1.
+ '#8' // B, T2 -> T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ // See tracing/tracing/base/multi_dimensional_view.html
+ // (MultiDimensionalViewBuilder documentation).
+ builderTest('twoDimensions_documentationExample2', 2 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['Saturday'], ['Cooking']], values: [1], kind: SELF },
+ { path: [['Saturday'], ['Sports', 'Football']], values: [2],
+ kind: SELF },
+ { path: [['Sunday'], ['Sports', 'Basketball']], values: [3],
+ kind: SELF }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 6,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // Saturday, *.
+ title: ['Saturday', undefined],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Saturday, Cooking.
+ id: '#0',
+ title: ['Saturday', 'Cooking'],
+ values: [
+ {
+ total: 1,
+ self: 1,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Saturday, Sports.
+ id: '#1',
+ title: ['Saturday', 'Sports'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Saturday, Sports -> Football.
+ id: '#2',
+ title: ['Saturday', 'Football'],
+ values: [
+ {
+ total: 2,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Sunday, *.
+ title: ['Sunday', undefined],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Sunday, Sports.
+ id: '#3',
+ title: ['Sunday', 'Sports'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Sunday, Sports -> Basketball.
+ id: '#4',
+ title: ['Sunday', 'Basketball'],
+ values: [
+ {
+ total: 3,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, Cooking.
+ title: [undefined, 'Cooking'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // Saturday, Cooking.
+ ],
+ []
+ ]
+ },
+ { // *, Sports.
+ title: [undefined, 'Sports'],
+ values: [
+ {
+ total: 5,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1', // Saturday, Sports.
+ '#3' // Sunday, Sports.
+ ],
+ [
+ { // *, Sports -> Football.
+ title: [undefined, 'Football'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // Saturday, Sports -> Football.
+ ],
+ []
+ ]
+ },
+ { // *, Sports -> Basketball.
+ title: [undefined, 'Basketball'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // Sunday, Sports -> Basketball.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 6,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // Saturday, *.
+ title: ['Saturday', undefined],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Saturday, Cooking.
+ id: '#0',
+ title: ['Saturday', 'Cooking'],
+ values: [
+ {
+ total: 1,
+ self: 1,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Saturday, Sports.
+ id: '#1',
+ title: ['Saturday', 'Sports'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Saturday, Sports -> Football.
+ id: '#2',
+ title: ['Saturday', 'Football'],
+ values: [
+ {
+ total: 2,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Saturday, Football.
+ id: '#3',
+ title: ['Saturday', 'Football'],
+ values: [
+ {
+ total: 2,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Sunday, *.
+ title: ['Sunday', undefined],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Sunday, Sports.
+ id: '#4',
+ title: ['Sunday', 'Sports'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Sunday, Sports -> Basketball.
+ id: '#5',
+ title: ['Sunday', 'Basketball'],
+ values: [
+ {
+ total: 3,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Sunday, Basketball.
+ id: '#6',
+ title: ['Sunday', 'Basketball'],
+ values: [
+ {
+ total: 3,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, Cooking.
+ title: [undefined, 'Cooking'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // Saturday, Cooking.
+ ],
+ []
+ ]
+ },
+ { // *, Sports.
+ title: [undefined, 'Sports'],
+ values: [
+ {
+ total: 5,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1', // Saturday, Sports.
+ '#4' // Sunday, Sports.
+ ],
+ [
+ { // *, Sports -> Football.
+ title: [undefined, 'Football'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // Saturday, Sports -> Football.
+ ],
+ []
+ ]
+ },
+ { // *, Sports -> Basketball.
+ title: [undefined, 'Basketball'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5' // Sunday, Sports -> Basketball.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, Football.
+ title: [undefined, 'Football'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // Saturday, Football.
+ ],
+ []
+ ]
+ },
+ { // *, Basketball.
+ title: [undefined, 'Basketball'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6' // Sunday, Basketball.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 6,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // Saturday, *.
+ title: ['Saturday', undefined],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Saturday, Cooking.
+ id: '#0',
+ title: ['Saturday', 'Cooking'],
+ values: [
+ {
+ total: 1,
+ self: 1,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Saturday, Sports.
+ id: '#1',
+ title: ['Saturday', 'Sports'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Saturday, Football.
+ id: '#2',
+ title: ['Saturday', 'Football'],
+ values: [
+ {
+ total: 2,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Saturday, Football -> Sports.
+ id: '#3',
+ title: ['Saturday', 'Sports'],
+ values: [
+ {
+ total: 2,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Sunday, *.
+ title: ['Sunday', undefined],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Sunday, Sports.
+ id: '#4',
+ title: ['Sunday', 'Sports'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Sunday, Basketball.
+ id: '#5',
+ title: ['Sunday', 'Basketball'],
+ values: [
+ {
+ total: 3,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Sunday, Basketball -> Sports.
+ id: '#6',
+ title: ['Sunday', 'Sports'],
+ values: [
+ {
+ total: 3,
+ self: 3,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, Cooking.
+ title: [undefined, 'Cooking'],
+ values: [
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // Saturday, Cooking.
+ ],
+ []
+ ]
+ },
+ { // *, Sports.
+ title: [undefined, 'Sports'],
+ values: [
+ {
+ total: 5,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1', // Saturday, Sports.
+ '#4' // Sunday, Sports.
+ ],
+ []
+ ]
+ },
+ { // *, Football.
+ title: [undefined, 'Football'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // Saturday, Football.
+ ],
+ [
+ { // *, Football -> Sports.
+ title: [undefined, 'Sports'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // Saturday, Football -> Sports.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, Basketball.
+ title: [undefined, 'Basketball'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5' // Sunday, Basketball.
+ ],
+ [
+ { // *, Basketball -> Sports.
+ title: [undefined, 'Sports'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6' // Sunday, Basketball -> Sports.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ // See https://goo.gl/KY7zVE.
+ builderTest('twoDimensions_heapDumpExample', 2 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['BrMain', 'Init'], ['T']], values: [151], kind: TOTAL },
+ { path: [['BrMain', 'Init'], ['W']], values: [83], kind: TOTAL },
+ { path: [['BrMain', 'Init'], []], values: [242], kind: TOTAL },
+ { path: [['BrMain', 'MsgLp'], ['T']], values: [307], kind: TOTAL },
+ { path: [['BrMain', 'MsgLp'], ['V']], values: [281], kind: TOTAL },
+ { path: [['BrMain', 'MsgLp'], []], values: [601], kind: TOTAL },
+ { path: [['RdMain', 'RTask'], ['T']], values: [211], kind: TOTAL },
+ { path: [['RdMain', 'RTask'], ['W']], values: [337], kind: TOTAL },
+ { path: [['RdMain', 'RTask'], []], values: [556], kind: TOTAL },
+ { path: [[], ['T']], values: [698], kind: TOTAL },
+ { path: [[], ['V']], values: [340], kind: TOTAL },
+ { path: [[], ['W']], values: [461], kind: TOTAL },
+ { path: [[], []], values: [1538], kind: TOTAL },
+ { path: [['BrMain'], ['T']], values: [465], kind: TOTAL },
+ { path: [['BrMain'], ['V']], values: [297], kind: TOTAL },
+ { path: [['BrMain'], ['W']], values: [96], kind: TOTAL },
+ { path: [['BrMain'], []], values: [876], kind: TOTAL },
+ { path: [['RdMain'], ['T']], values: [229], kind: TOTAL },
+ { path: [['RdMain'], ['W']], values: [355], kind: TOTAL },
+ { path: [['RdMain'], []], values: [628], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 1538,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // BrMain, *.
+ title: ['BrMain', undefined],
+ values: [
+ {
+ total: 876,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // BrMain -> Init, *.
+ title: ['Init', undefined],
+ values: [
+ {
+ total: 242,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // BrMain -> Init, T.
+ id: '#0',
+ title: ['Init', 'T'],
+ values: [
+ {
+ total: 151,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // BrMain -> Init, W.
+ id: '#1',
+ title: ['Init', 'W'],
+ values: [
+ {
+ total: 83,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // BrMain -> MsgLp, *.
+ title: ['MsgLp', undefined],
+ values: [
+ {
+ total: 601,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // BrMain -> MsgLp, T.
+ id: '#2',
+ title: ['MsgLp', 'T'],
+ values: [
+ {
+ total: 307,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // BrMain -> MsgLp, V.
+ id: '#3',
+ title: ['MsgLp', 'V'],
+ values: [
+ {
+ total: 281,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // BrMain, T.
+ id: '#4',
+ title: ['BrMain', 'T'],
+ values: [
+ {
+ total: 465,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#0', // BrMain -> Init, T.
+ '#2' // BrMain -> MsgLp, T.
+ ],
+ []
+ ]
+ },
+ { // BrMain, V.
+ id: '#5',
+ title: ['BrMain', 'V'],
+ values: [
+ {
+ total: 297,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#3' // BrMain -> MsgLp, V.
+ ],
+ []
+ ]
+ },
+ { // BrMain, W.
+ id: '#6',
+ title: ['BrMain', 'W'],
+ values: [
+ {
+ total: 96,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#1' // BrMain -> Init, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // RdMain, *.
+ title: ['RdMain', undefined],
+ values: [
+ {
+ total: 628,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // RdMain -> RTask, *.
+ title: ['RTask', undefined],
+ values: [
+ {
+ total: 556,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // RdMain -> RTask, T.
+ id: '#7',
+ title: ['RTask', 'T'],
+ values: [
+ {
+ total: 211,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // RdMain -> RTask, W.
+ id: '#8',
+ title: ['RTask', 'W'],
+ values: [
+ {
+ total: 337,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // RdMain, T.
+ id: '#9',
+ title: ['RdMain', 'T'],
+ values: [
+ {
+ total: 229,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#7' // RdMain -> RTask, T.
+ ],
+ []
+ ]
+ },
+ { // RdMain, W.
+ id: '#10',
+ title: ['RdMain', 'W'],
+ values: [
+ {
+ total: 355,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#8' // RdMain -> RTask, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T.
+ title: [undefined, 'T'],
+ values: [
+ {
+ total: 698,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#4', // BrMain, T.
+ '#9' // RdMain, T.
+ ],
+ []
+ ]
+ },
+ { // *, V.
+ title: [undefined, 'V'],
+ values: [
+ {
+ total: 340,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#5' // BrMain, V.
+ ],
+ []
+ ]
+ },
+ { // *, W.
+ title: [undefined, 'W'],
+ values: [
+ {
+ total: 461,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#6', // BrMain, W.
+ '#10' // RdMain, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 1538,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // BrMain, *.
+ title: ['BrMain', undefined],
+ values: [
+ {
+ total: 876,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // BrMain -> Init, *.
+ title: ['Init', undefined],
+ values: [
+ {
+ total: 242,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // BrMain -> Init, T.
+ id: '#0',
+ title: ['Init', 'T'],
+ values: [
+ {
+ total: 151,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // BrMain -> Init, W.
+ id: '#1',
+ title: ['Init', 'W'],
+ values: [
+ {
+ total: 83,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // BrMain -> MsgLp, *.
+ title: ['MsgLp', undefined],
+ values: [
+ {
+ total: 601,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // BrMain -> MsgLp, T.
+ id: '#2',
+ title: ['MsgLp', 'T'],
+ values: [
+ {
+ total: 307,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // BrMain -> MsgLp, V.
+ id: '#3',
+ title: ['MsgLp', 'V'],
+ values: [
+ {
+ total: 281,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // BrMain, T.
+ id: '#4',
+ title: ['BrMain', 'T'],
+ values: [
+ {
+ total: 465,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0', // BrMain -> Init, T.
+ '#2' // BrMain -> MsgLp, T.
+ ],
+ []
+ ]
+ },
+ { // BrMain, V.
+ id: '#5',
+ title: ['BrMain', 'V'],
+ values: [
+ {
+ total: 297,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // BrMain -> MsgLp, V.
+ ],
+ []
+ ]
+ },
+ { // BrMain, W.
+ id: '#6',
+ title: ['BrMain', 'W'],
+ values: [
+ {
+ total: 96,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1' // BrMain -> Init, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Init, *.
+ title: ['Init', undefined],
+ values: [
+ {
+ total: 242,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Init, T.
+ id: '#7',
+ title: ['Init', 'T'],
+ values: [
+ {
+ total: 151,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Init, W.
+ id: '#8',
+ title: ['Init', 'W'],
+ values: [
+ {
+ total: 83,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // MsgLp, *.
+ title: ['MsgLp', undefined],
+ values: [
+ {
+ total: 601,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // MsgLp, T.
+ id: '#9',
+ title: ['MsgLp', 'T'],
+ values: [
+ {
+ total: 307,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // MsgLp, V.
+ id: '#10',
+ title: ['MsgLp', 'V'],
+ values: [
+ {
+ total: 281,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // RdMain, *.
+ title: ['RdMain', undefined],
+ values: [
+ {
+ total: 628,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // RdMain -> RTask, *.
+ title: ['RTask', undefined],
+ values: [
+ {
+ total: 556,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // RdMain -> RTask, T.
+ id: '#11',
+ title: ['RTask', 'T'],
+ values: [
+ {
+ total: 211,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // RdMain -> RTask, W.
+ id: '#12',
+ title: ['RTask', 'W'],
+ values: [
+ {
+ total: 337,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // RdMain, T.
+ id: '#13',
+ title: ['RdMain', 'T'],
+ values: [
+ {
+ total: 229,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#11' // RdMain -> RTask, T.
+ ],
+ []
+ ]
+ },
+ { // RdMain, W.
+ id: '#14',
+ title: ['RdMain', 'W'],
+ values: [
+ {
+ total: 355,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#12' // RdMain -> RTask, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // RTask, *.
+ title: ['RTask', undefined],
+ values: [
+ {
+ total: 556,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // RTask, T.
+ id: '#15',
+ title: ['RTask', 'T'],
+ values: [
+ {
+ total: 211,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // RTask, W.
+ id: '#16',
+ title: ['RTask', 'W'],
+ values: [
+ {
+ total: 337,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T.
+ title: [undefined, 'T'],
+ values: [
+ {
+ total: 698,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4', // BrMain, T.
+ '#7', // Init, T.
+ '#9', // MsgLp, T.
+ '#13', // RdMain, T.
+ '#15' // RTask, T.
+ ],
+ []
+ ]
+ },
+ { // *, V.
+ title: [undefined, 'V'],
+ values: [
+ {
+ total: 340,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5', // BrMain, V.
+ '#10' // MsgLp, V.
+ ],
+ []
+ ]
+ },
+ { // *, W.
+ title: [undefined, 'W'],
+ values: [
+ {
+ total: 461,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6', // BrMain, W.
+ '#8', // Init, W.
+ '#14', // RdMain, W.
+ '#16' // RTask, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 1538,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // BrMain, *.
+ title: ['BrMain', undefined],
+ values: [
+ {
+ total: 876,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // BrMain, T.
+ id: '#0',
+ title: ['BrMain', 'T'],
+ values: [
+ {
+ total: 465,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // BrMain, V.
+ id: '#1',
+ title: ['BrMain', 'V'],
+ values: [
+ {
+ total: 297,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // BrMain, W.
+ id: '#2',
+ title: ['BrMain', 'W'],
+ values: [
+ {
+ total: 96,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Init, *.
+ title: ['Init', undefined],
+ values: [
+ {
+ total: 242,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // Init -> BrMain, *.
+ title: ['BrMain', undefined],
+ values: [
+ {
+ total: 242,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // Init -> BrMain, T.
+ id: '#3',
+ title: ['BrMain', 'T'],
+ values: [
+ {
+ total: 151,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // Init -> BrMain, W.
+ id: '#4',
+ title: ['BrMain', 'W'],
+ values: [
+ {
+ total: 83,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // Init, T.
+ id: '#5',
+ title: ['Init', 'T'],
+ values: [
+ {
+ total: 151,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // Init -> BrMain, T.
+ ],
+ []
+ ]
+ },
+ { // Init, W.
+ id: '#6',
+ title: ['Init', 'W'],
+ values: [
+ {
+ total: 83,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // Init -> BrMain, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // MsgLp, *.
+ title: ['MsgLp', undefined],
+ values: [
+ {
+ total: 601,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // MsgLp -> BrMain, *.
+ title: ['BrMain', undefined],
+ values: [
+ {
+ total: 601,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // MsgLp -> BrMain, T.
+ id: '#7',
+ title: ['BrMain', 'T'],
+ values: [
+ {
+ total: 307,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // MsgLp -> BrMain, V.
+ id: '#8',
+ title: ['BrMain', 'V'],
+ values: [
+ {
+ total: 281,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // MsgLp, T.
+ id: '#9',
+ title: ['MsgLp', 'T'],
+ values: [
+ {
+ total: 307,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#7' // MsgLp -> BrMain, T.
+ ],
+ []
+ ]
+ },
+ { // MsgLp, V.
+ id: '#10',
+ title: ['MsgLp', 'V'],
+ values: [
+ {
+ total: 281,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#8' // MsgLp -> BrMain, V.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // RdMain, *.
+ title: ['RdMain', undefined],
+ values: [
+ {
+ total: 628,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // RdMain, T.
+ id: '#11',
+ title: ['RdMain', 'T'],
+ values: [
+ {
+ total: 229,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // RdMain, W.
+ id: '#12',
+ title: ['RdMain', 'W'],
+ values: [
+ {
+ total: 355,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // RTask, *.
+ title: ['RTask', undefined],
+ values: [
+ {
+ total: 556,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // RTask -> RdMain, *.
+ title: ['RdMain', undefined],
+ values: [
+ {
+ total: 556,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // RTask -> RdMain, T.
+ id: '#13',
+ title: ['RdMain', 'T'],
+ values: [
+ {
+ total: 211,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // RTask -> RdMain, W.
+ id: '#14',
+ title: ['RdMain', 'W'],
+ values: [
+ {
+ total: 337,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // RTask, T.
+ id: '#15',
+ title: ['RTask', 'T'],
+ values: [
+ {
+ total: 211,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#13' // RTask -> RdMain, T.
+ ],
+ []
+ ]
+ },
+ { // RTask, W.
+ id: '#16',
+ title: ['RTask', 'W'],
+ values: [
+ {
+ total: 337,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#14' // RTask -> RdMain, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T.
+ title: [undefined, 'T'],
+ values: [
+ {
+ total: 698,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0', // BrMain, T.
+ '#5', // Init, T.
+ '#9', // MsgLp, T.
+ '#11', // RdMain, T.
+ '#15' // RTask, T.
+ ],
+ []
+ ]
+ },
+ { // *, V.
+ title: [undefined, 'V'],
+ values: [
+ {
+ total: 340,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1', // BrMain, V.
+ '#10' // MsgLp, V.
+ ],
+ []
+ ]
+ },
+ { // *, W.
+ title: [undefined, 'W'],
+ values: [
+ {
+ total: 461,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2', // BrMain, W.
+ '#6', // Init, W.
+ '#12', // RdMain, W.
+ '#16' // RTask, W.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('twoDimensions_oneRecursiveDimension', 2 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['A', 'B'], []], values: [1500], kind: TOTAL },
+ { path: [['A', 'B', 'A'], []], values: [200], kind: TOTAL },
+ { path: [['A', 'B', 'B'], []], values: [300], kind: TOTAL },
+ { path: [['A', 'B', 'C'], []], values: [700], kind: TOTAL },
+ { path: [['A', 'B'], ['T1']], values: [15], kind: TOTAL },
+ { path: [['A', 'B', 'A'], ['T1']], values: [2], kind: TOTAL },
+ { path: [['A', 'B', 'B'], ['T1']], values: [3], kind: TOTAL },
+ { path: [['A', 'B', 'C'], ['T1']], values: [7], kind: TOTAL },
+ { path: [['B', 'A'], ['T1']], values: [30000], kind: TOTAL },
+ { path: [['B', 'A'], []], values: [40000], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 41500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 1500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 1500,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 200,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> A, T1.
+ id: '#0',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 300,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> B, T1.
+ id: '#1',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B -> C, *.
+ title: ['C', undefined],
+ values: [
+ {
+ total: 700,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> C, T1.
+ id: '#2',
+ title: ['C', 'T1'],
+ values: [
+ {
+ total: 7,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, T1.
+ id: '#3',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 15,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#0', // A -> B -> A, T1.
+ '#1', // A -> B -> B, T1.
+ '#2' // A -> B -> C, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, T1.
+ id: '#4',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 15,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // A -> B, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 40000,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 40000,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A, T1.
+ id: '#5',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 30000,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, T1.
+ id: '#6',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 30000,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5' // B -> A, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T1.
+ title: [undefined, 'T1'],
+ values: [
+ {
+ total: 30015,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4', // A, T1.
+ '#6' // B, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 41500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 41500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 1500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 200,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> A, T1.
+ id: '#0',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 300,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> B, T1.
+ id: '#1',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B -> C, *.
+ title: ['C', undefined],
+ values: [
+ {
+ total: 700,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> C, T1.
+ id: '#2',
+ title: ['C', 'T1'],
+ values: [
+ {
+ total: 7,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, T1.
+ id: '#3',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 15,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0', // A -> B -> A, T1.
+ '#1', // A -> B -> B, T1.
+ '#2' // A -> B -> C, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, T1.
+ id: '#4',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 30015,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // A -> B, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 41500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 40200,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A, T1.
+ id: '#5',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 30002,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 300,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B, T1.
+ id: '#6',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> C, *.
+ title: ['C', undefined],
+ values: [
+ {
+ total: 700,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> C, T1.
+ id: '#7',
+ title: ['C', 'T1'],
+ values: [
+ {
+ total: 7,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, T1.
+ id: '#8',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 30015,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5', // B -> A, T1.
+ '#6', // B -> B, T1.
+ '#7' // B -> C, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C, *.
+ title: ['C', undefined],
+ values: [
+ {
+ total: 700,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // C, T1.
+ id: '#9',
+ title: ['C', 'T1'],
+ values: [
+ {
+ total: 7,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T1.
+ title: [undefined, 'T1'],
+ values: [
+ {
+ total: 30015,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4', // A, T1.
+ '#8', // B, T1.
+ '#9' // C, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 41500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 41500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 40200,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 200,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> A, T1.
+ id: '#0',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 2,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, T1.
+ id: '#1',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 30002,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // A -> B -> A, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, T1.
+ id: '#2',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 30015,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1' // A -> B, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 41500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 1500,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A, T1.
+ id: '#3',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 15,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 300,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 300,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B -> A, T1.
+ id: '#4',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B -> B, T1.
+ id: '#5',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 3,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // B -> B -> A, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, T1.
+ id: '#6',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 30015,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3', // B -> A, T1.
+ '#5' // B -> B, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // C, *.
+ title: ['C', undefined],
+ values: [
+ {
+ total: 700,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 700,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // C -> B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 700,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // C -> B -> A, T1.
+ id: '#7',
+ title: ['A', 'T1'],
+ values: [
+ {
+ total: 7,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // C -> B, T1.
+ id: '#8',
+ title: ['B', 'T1'],
+ values: [
+ {
+ total: 7,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#7' // C -> B -> A, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // C, T1.
+ id: '#9',
+ title: ['C', 'T1'],
+ values: [
+ {
+ total: 7,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#8' // C -> B, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, T1.
+ title: [undefined, 'T1'],
+ values: [
+ {
+ total: 30015,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2', // A, T1.
+ '#6', // B, T1.
+ '#9' // C, T1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('twoDimensions_twoRecursiveDimensions', 2 /* dimensions */,
+ 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['A', 'A', 'B'], ['1', '2', '2']], values: [10], kind: SELF },
+ { path: [['A', 'A'], ['1', '2']], values: [40], kind: TOTAL },
+ { path: [['A', 'B', 'B'], ['1', '1', '2']], values: [20], kind: TOTAL },
+ { path: [['A', 'B'], ['1', '1']], values: [5], kind: SELF }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A -> B, 1.
+ id: '#0',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A -> B, 1 -> 2.
+ id: '#1',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A -> B, 1 -> 2 -> 2.
+ id: '#2',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> A, 1.
+ id: '#3',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // A -> A -> B, 1.
+ ],
+ [
+ { // A -> A, 1 -> 2.
+ id: '#4',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ '#1' // A -> A -> B, 1 -> 2.
+ ],
+ [
+ { // A -> A, 1 -> 2 -> 2.
+ id: '#5',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // A -> A -> B, 1 -> 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 25,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> B, 1.
+ id: '#6',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> B, 1 -> 1.
+ id: '#7',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> B, 1 -> 1 -> 2.
+ id: '#8',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, 1.
+ id: '#9',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 25,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6' // A -> B -> B, 1.
+ ],
+ [
+ { // A -> B, 1 -> 1.
+ id: '#10',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 25,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#7' // A -> B -> B, 1 -> 1.
+ ],
+ [
+ { // A -> B, 1 -> 1 -> 2.
+ id: '#11',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#8' // A -> B -> B, 1 -> 1 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, 1.
+ id: '#12',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3', // A -> A, 1.
+ '#9' // A -> B, 1.
+ ],
+ [
+ { // A, 1 -> 2.
+ id: '#13',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // A -> A, 1 -> 2.
+ ],
+ [
+ { // A, 1 -> 2 -> 2.
+ id: '#14',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5' // A -> A, 1 -> 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, 1 -> 1.
+ id: '#15',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 25,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#10' // A -> B, 1 -> 1.
+ ],
+ [
+ { // A, 1 -> 1 -> 2.
+ id: '#16',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#11' // A -> B, 1 -> 1 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#12' // A, 1.
+ ],
+ [
+ { // *, 1 -> 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#13' // A, 1 -> 2.
+ ],
+ [
+ { // *, 1 -> 2 -> 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#14' // A, 1 -> 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, 1 -> 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 25,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#15' // A, 1 -> 1.
+ ],
+ [
+ { // *, 1 -> 1 -> 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#16' // A, 1 -> 1 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A -> B, 1.
+ id: '#0',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A -> B, 1 -> 2.
+ id: '#1',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A -> B, 1 -> 2 -> 2.
+ id: '#2',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> A -> B, 2.
+ id: '#3',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A -> B, 2 -> 2.
+ id: '#4',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> A, 1.
+ id: '#5',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // A -> A -> B, 1.
+ ],
+ [
+ { // A -> A, 1 -> 2.
+ id: '#6',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1' // A -> A -> B, 1 -> 2.
+ ],
+ [
+ { // A -> A, 1 -> 2 -> 2.
+ id: '#7',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // A -> A -> B, 1 -> 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> A, 2.
+ id: '#8',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // A -> A -> B, 2.
+ ],
+ [
+ { // A -> A, 2 -> 2.
+ id: '#9',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // A -> A -> B, 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 35,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> B, 1.
+ id: '#10',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> B, 1 -> 1.
+ id: '#11',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B -> B, 1 -> 1 -> 2.
+ id: '#12',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B -> B, 1 -> 2.
+ id: '#13',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B -> B, 2.
+ id: '#14',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, 1.
+ id: '#15',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 35,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#10' // A -> B -> B, 1.
+ ],
+ [
+ { // A -> B, 1 -> 1.
+ id: '#16',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 25,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#11' // A -> B -> B, 1 -> 1.
+ ],
+ [
+ { // A -> B, 1 -> 1 -> 2.
+ id: '#17',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#12' // A -> B -> B, 1 -> 1 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, 1 -> 2.
+ id: '#18',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 30,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#13' // A -> B -> B, 1 -> 2.
+ ],
+ [
+ { // A -> B, 1 -> 2 -> 2.
+ id: '#19',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, 2.
+ id: '#20',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 30,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#14' // A -> B -> B, 2.
+ ],
+ [
+ { // A -> B, 2 -> 2.
+ id: '#21',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, 1.
+ id: '#22',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5', // A -> A, 1.
+ '#15' // A -> B, 1.
+ ],
+ [
+ { // A, 1 -> 2.
+ id: '#23',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6', // A -> A, 1 -> 2.
+ '#18' // A -> B, 1 -> 2.
+ ],
+ [
+ { // A, 1 -> 2 -> 2.
+ id: '#24',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#7', // A -> A, 1 -> 2 -> 2.
+ '#19' // A -> B, 1 -> 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, 1 -> 1.
+ id: '#25',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 25,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#16' // A -> B, 1 -> 1.
+ ],
+ [
+ { // A, 1 -> 1 -> 2.
+ id: '#26',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#17' // A -> B, 1 -> 1 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, 2.
+ id: '#27',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#8', // A -> A, 2.
+ '#20' // A -> B, 2.
+ ],
+ [
+ { // A, 2 -> 2.
+ id: '#28',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#9', // A -> A, 2 -> 2.
+ '#21' // A -> B, 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 35,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B, 1.
+ id: '#29',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B, 1 -> 1.
+ id: '#30',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B, 1 -> 1 -> 2.
+ id: '#31',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> B, 1 -> 2.
+ id: '#32',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> B, 2.
+ id: '#33',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, 1.
+ id: '#34',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 35,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#29' // B -> B, 1.
+ ],
+ [
+ { // B, 1 -> 2.
+ id: '#35',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 30,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#32' // B -> B, 1 -> 2.
+ ],
+ [
+ { // B, 1 -> 2 -> 2.
+ id: '#36',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, 1 -> 1.
+ id: '#37',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 25,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#30' // B -> B, 1 -> 1.
+ ],
+ [
+ { // B, 1 -> 1 -> 2.
+ id: '#38',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#31' // B -> B, 1 -> 1 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, 2.
+ id: '#39',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 30,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#33' // B -> B, 2.
+ ],
+ [
+ { // B, 2 -> 2.
+ id: '#40',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#22', // A, 1.
+ '#34' // B, 1.
+ ],
+ [
+ { // *, 1 -> 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#23', // A, 1 -> 2.
+ '#35' // B, 1 -> 2.
+ ],
+ [
+ { // *, 1 -> 2 -> 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#24', // A, 1 -> 2 -> 2.
+ '#36' // B, 1 -> 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, 1 -> 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 25,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#25', // A, 1 -> 1.
+ '#37' // B, 1 -> 1.
+ ],
+ [
+ { // *, 1 -> 1 -> 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#26', // A, 1 -> 1 -> 2.
+ '#38' // B, 1 -> 1 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#27', // A, 2.
+ '#39' // B, 2.
+ ],
+ [
+ { // *, 2 -> 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#28', // A, 2 -> 2.
+ '#40' // B, 2 -> 2.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A, 1.
+ id: '#0',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // A -> A, 2.
+ id: '#1',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A, 2 -> 1.
+ id: '#2',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 40,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // A -> A, 2 -> 2.
+ id: '#3',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> A, 2 -> 2 -> 1.
+ id: '#4',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, 1.
+ id: '#5',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // A -> A, 1.
+ ],
+ [
+ { // A, 1 -> 1.
+ id: '#6',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 25,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, 2.
+ id: '#7',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1' // A -> A, 2.
+ ],
+ [
+ { // A, 2 -> 1.
+ id: '#8',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // A -> A, 2 -> 1.
+ ],
+ [
+ { // A, 2 -> 1 -> 1.
+ id: '#9',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, 2 -> 2.
+ id: '#10',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // A -> A, 2 -> 2.
+ ],
+ [
+ { // A, 2 -> 2 -> 1.
+ id: '#11',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // A -> A, 2 -> 2 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 35,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 35,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A -> A, 1.
+ id: '#12',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B -> A -> A, 2.
+ id: '#13',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A -> A, 2 -> 1.
+ id: '#14',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B -> A -> A, 2 -> 2.
+ id: '#15',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A -> A, 2 -> 2 -> 1.
+ id: '#16',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B -> A, 1.
+ id: '#17',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 35,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#12' // B -> A -> A, 1.
+ ],
+ [
+ { // B -> A, 1 -> 1.
+ id: '#18',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 25,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> A, 2.
+ id: '#19',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 30,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#13' // B -> A -> A, 2.
+ ],
+ [
+ { // B -> A, 2 -> 1.
+ id: '#20',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 30,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#14' // B -> A -> A, 2 -> 1.
+ ],
+ [
+ { // B -> A, 2 -> 1 -> 1.
+ id: '#21',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> A, 2 -> 2.
+ id: '#22',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#15' // B -> A -> A, 2 -> 2.
+ ],
+ [
+ { // B -> A, 2 -> 2 -> 1.
+ id: '#23',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#16' // B -> A -> A, 2 -> 2 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> B -> A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B -> A, 1.
+ id: '#24',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B -> A, 1 -> 1.
+ id: '#25',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> B -> A, 2.
+ id: '#26',
+ title: ['A', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B -> A, 2 -> 1.
+ id: '#27',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> B -> A, 2 -> 1 -> 1.
+ id: '#28',
+ title: ['A', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B -> B, 1.
+ id: '#29',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#24' // B -> B -> A, 1.
+ ],
+ [
+ { // B -> B, 1 -> 1.
+ id: '#30',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#25' // B -> B -> A, 1 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> B, 2.
+ id: '#31',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#26' // B -> B -> A, 2.
+ ],
+ [
+ { // B -> B, 2 -> 1.
+ id: '#32',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#27' // B -> B -> A, 2 -> 1.
+ ],
+ [
+ { // B -> B, 2 -> 1 -> 1.
+ id: '#33',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#28' // B -> B -> A, 2 -> 1 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, 1.
+ id: '#34',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 35,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#17', // B -> A, 1.
+ '#29' // B -> B, 1.
+ ],
+ [
+ { // B, 1 -> 1.
+ id: '#35',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 25,
+ self: 5,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#18', // B -> A, 1 -> 1.
+ '#30' // B -> B, 1 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, 2.
+ id: '#36',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 30,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#19', // B -> A, 2.
+ '#31' // B -> B, 2.
+ ],
+ [
+ { // B, 2 -> 1.
+ id: '#37',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 30,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#20', // B -> A, 2 -> 1.
+ '#32' // B -> B, 2 -> 1.
+ ],
+ [
+ { // B, 2 -> 1 -> 1.
+ id: '#38',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#21', // B -> A, 2 -> 1 -> 1.
+ '#33' // B -> B, 2 -> 1 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, 2 -> 2.
+ id: '#39',
+ title: ['B', '2'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#22' // B -> A, 2 -> 2.
+ ],
+ [
+ { // B, 2 -> 2 -> 1.
+ id: '#40',
+ title: ['B', '1'],
+ values: [
+ {
+ total: 10,
+ self: 10,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#23' // B -> A, 2 -> 2 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 65,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5', // A, 1.
+ '#34' // B, 1.
+ ],
+ [
+ { // *, 1 -> 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 25,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6', // A, 1 -> 1.
+ '#35' // B, 1 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#7', // A, 2.
+ '#36' // B, 2.
+ ],
+ [
+ { // *, 2 -> 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 60,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#8', // A, 2 -> 1.
+ '#37' // B, 2 -> 1.
+ ],
+ [
+ { // *, 2 -> 1 -> 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 20,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#9', // A, 2 -> 1 -> 1.
+ '#38' // B, 2 -> 1 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, 2 -> 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#10', // A, 2 -> 2.
+ '#39' // B, 2 -> 2.
+ ],
+ [
+ { // *, 2 -> 2 -> 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 10,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#11', // A, 2 -> 2 -> 1.
+ '#40' // B, 2 -> 2 -> 1.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('threeDimensions', 3 /* dimensions */, 1 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [['A', 'B'], ['C', 'D'], ['E', 'F']], values: [b(0)],
+ kind: SELF },
+ { path: [['A', 'B'], ['C', 'D'], ['E']], values: [b(1)], kind: SELF },
+ { path: [['A', 'B'], ['C', 'D'], []], values: [b(2)], kind: SELF },
+ { path: [['A', 'B'], ['C'], ['E', 'F']], values: [b(3)], kind: SELF },
+ { path: [['A', 'B'], ['C'], ['E']], values: [b(4)], kind: SELF },
+ { path: [['A', 'B'], ['C'], []], values: [b(5)], kind: SELF },
+ { path: [['A', 'B'], [], ['E', 'F']], values: [b(6)], kind: SELF },
+ { path: [['A', 'B'], [], ['E']], values: [b(7)], kind: SELF },
+ { path: [['A', 'B'], [], []], values: [b(8)], kind: SELF },
+
+ { path: [['A'], ['C', 'D'], ['E', 'F']], values: [b(9)], kind: SELF },
+ { path: [['A'], ['C', 'D'], ['E']], values: [b(10)], kind: SELF },
+ { path: [['A'], ['C', 'D'], []], values: [b(11)], kind: SELF },
+ { path: [['A'], ['C'], ['E', 'F']], values: [b(12)], kind: SELF },
+ { path: [['A'], ['C'], ['E']], values: [b(13)], kind: SELF },
+ { path: [['A'], ['C'], []], values: [b(14)], kind: SELF },
+ { path: [['A'], [], ['E', 'F']], values: [b(15)], kind: SELF },
+ { path: [['A'], [], ['E']], values: [b(16)], kind: SELF },
+ { path: [['A'], [], []], values: [b(17)], kind: SELF },
+
+ { path: [[], ['C', 'D'], ['E', 'F']], values: [b(18)], kind: SELF },
+ { path: [[], ['C', 'D'], ['E']], values: [b(19)], kind: SELF },
+ { path: [[], ['C', 'D'], []], values: [b(20)], kind: SELF },
+ { path: [[], ['C'], ['E', 'F']], values: [b(21)], kind: SELF },
+ { path: [[], ['C'], ['E']], values: [b(22)], kind: SELF },
+ { path: [[], ['C'], []], values: [b(23)], kind: SELF },
+ { path: [[], [], ['E', 'F']], values: [b(24)], kind: SELF },
+ { path: [[], [], ['E']], values: [b(25)], kind: SELF },
+ { path: [[], [], []], values: [b(26)], kind: SELF }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined, undefined],
+ values: [
+ {
+ total: b([0, 26]),
+ self: b(26),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *, *.
+ title: ['A', undefined, undefined],
+ values: [
+ {
+ total: b([0, 17]),
+ self: b(17),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B, *, *.
+ title: ['B', undefined, undefined],
+ values: [
+ {
+ total: b([0, 8]),
+ self: b(8),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B, C, *.
+ id: '#0',
+ title: ['B', 'C', undefined],
+ values: [
+ {
+ total: b([0, 5]),
+ self: b(5),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B, C -> D, *.
+ id: '#1',
+ title: ['B', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A -> B, C -> D, E.
+ id: '#2',
+ title: ['B', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A -> B, C -> D, E -> F.
+ id: '#3',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, C, E.
+ id: '#4',
+ title: ['B', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4),
+ self: b(4),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#2' // A -> B, C -> D, E.
+ ],
+ [
+ { // A -> B, C, E -> F.
+ id: '#5',
+ title: ['B', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#3' // A -> B, C -> D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, *, E.
+ id: '#6',
+ title: ['B', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7),
+ self: b(7),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#4' // A -> B, C, E.
+ ],
+ [
+ { // A -> B, *, E -> F.
+ id: '#7',
+ title: ['B', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#5' // A -> B, C, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, C, *.
+ id: '#8',
+ title: ['A', 'C', undefined],
+ values: [
+ {
+ total: b([0, 5], [9, 14]),
+ self: b(14),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // A -> B, C, *.
+ ],
+ [
+ { // A, C -> D, *.
+ id: '#9',
+ title: ['A', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11]),
+ self: b(11),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1' // A -> B, C -> D, *.
+ ],
+ [],
+ [
+ { // A, C -> D, E.
+ id: '#10',
+ title: ['A', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10),
+ self: b(10),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // A -> B, C -> D, E.
+ ],
+ [],
+ [
+ { // A, C -> D, E -> F.
+ id: '#11',
+ title: ['A', 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // A -> B, C -> D, E -> F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, C, E.
+ id: '#12',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 9, 10, 12, 13),
+ self: b(13),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // A -> B, C, E.
+ ],
+ [
+ '#10' // A, C -> D, E.
+ ],
+ [
+ { // A, C, E -> F.
+ id: '#13',
+ title: ['A', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3, 9, 12),
+ self: b(12),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5' // A -> B, C, E -> F.
+ ],
+ [
+ '#11' // A, C -> D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, *, E.
+ id: '#14',
+ title: ['A', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16),
+ self: b(16),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6' // A -> B, *, E.
+ ],
+ [
+ '#12' // A, C, E.
+ ],
+ [
+ { // A, *, E -> F.
+ id: '#15',
+ title: ['A', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15),
+ self: b(15),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#7' // A -> B, *, E -> F.
+ ],
+ [
+ '#13' // A, C, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, C, *.
+ title: [undefined, 'C', undefined],
+ values: [
+ {
+ total: b([0, 5], [9, 14], [18, 23]),
+ self: b(23),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#8' // A, C, *.
+ ],
+ [
+ { // *, C -> D, *.
+ title: [undefined, 'D', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11], [18, 20]),
+ self: b(20),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#9' // A, C -> D, *.
+ ],
+ [],
+ [
+ { // *, C -> D, E.
+ id: '#16',
+ title: [undefined, 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10, 18, 19),
+ self: b(19),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#10' // A, C -> D, E.
+ ],
+ [],
+ [
+ { // *, C -> D, E -> F.
+ id: '#17',
+ title: [undefined, 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#11' // A, C -> D, E -> F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, C, E.
+ id: '#18',
+ title: [undefined, 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 9, 10, 12, 13, 18, 19, 21, 22),
+ self: b(22),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#12' // A, C, E.
+ ],
+ [
+ '#16' // *, C -> D, E.
+ ],
+ [
+ { // *, C, E -> F.
+ id: '#19',
+ title: [undefined, 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3, 9, 12, 18, 21),
+ self: b(21),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#13' // A, C, E -> F.
+ ],
+ [
+ '#17' // *, C -> D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, *, E.
+ title: [undefined, undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21,
+ 22, 24, 25),
+ self: b(25),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#14' // A, *, E.
+ ],
+ [
+ '#18' // *, C, E.
+ ],
+ [
+ { // *, *, E -> F.
+ title: [undefined, undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15, 18, 21, 24),
+ self: b(24),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#15' // A, *, E -> F.
+ ],
+ [
+ '#19' // *, C, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined, undefined],
+ values: [
+ {
+ total: b([0, 26]),
+ self: b(26),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *, *.
+ title: ['A', undefined, undefined],
+ values: [
+ {
+ total: b([0, 17]),
+ self: b(17),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A -> B, *, *.
+ title: ['B', undefined, undefined],
+ values: [
+ {
+ total: b([0, 8]),
+ self: b(8),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B, C, *.
+ id: '#0',
+ title: ['B', 'C', undefined],
+ values: [
+ {
+ total: b([0, 5]),
+ self: b(5),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A -> B, C -> D, *.
+ id: '#1',
+ title: ['B', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A -> B, C -> D, E.
+ id: '#2',
+ title: ['B', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A -> B, C -> D, E -> F.
+ id: '#3',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, C -> D, F.
+ id: '#4',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, C, E.
+ id: '#5',
+ title: ['B', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4),
+ self: b(4),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#2' // A -> B, C -> D, E.
+ ],
+ [
+ { // A -> B, C, E -> F.
+ id: '#6',
+ title: ['B', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#3' // A -> B, C -> D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, C, F.
+ id: '#7',
+ title: ['B', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#4' // A -> B, C -> D, F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, D, *.
+ id: '#8',
+ title: ['B', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A -> B, D, E.
+ id: '#9',
+ title: ['B', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A -> B, D, E -> F.
+ id: '#10',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, D, F.
+ id: '#11',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A -> B, *, E.
+ id: '#12',
+ title: ['B', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7),
+ self: b(7),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#5', // A -> B, C, E.
+ '#9' // A -> B, D, E.
+ ],
+ [
+ { // A -> B, *, E -> F.
+ id: '#13',
+ title: ['B', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#6', // A -> B, C, E -> F.
+ '#10' // A -> B, D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A -> B, *, F.
+ id: '#14',
+ title: ['B', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#7', // A -> B, C, F.
+ '#11' // A -> B, D, F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, C, *.
+ id: '#15',
+ title: ['A', 'C', undefined],
+ values: [
+ {
+ total: b([0, 5], [9, 14]),
+ self: b(14),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0' // A -> B, C, *.
+ ],
+ [
+ { // A, C -> D, *.
+ id: '#16',
+ title: ['A', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11]),
+ self: b(11),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1' // A -> B, C -> D, *.
+ ],
+ [],
+ [
+ { // A, C -> D, E.
+ id: '#17',
+ title: ['A', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10),
+ self: b(10),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2' // A -> B, C -> D, E.
+ ],
+ [],
+ [
+ { // A, C -> D, E -> F.
+ id: '#18',
+ title: ['A', 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3' // A -> B, C -> D, E -> F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, C -> D, F.
+ id: '#19',
+ title: ['A', 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4' // A -> B, C -> D, F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, C, E.
+ id: '#20',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 9, 10, 12, 13),
+ self: b(13),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5' // A -> B, C, E.
+ ],
+ [
+ '#17' // A, C -> D, E.
+ ],
+ [
+ { // A, C, E -> F.
+ id: '#21',
+ title: ['A', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3, 9, 12),
+ self: b(12),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6' // A -> B, C, E -> F.
+ ],
+ [
+ '#18' // A, C -> D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, C, F.
+ id: '#22',
+ title: ['A', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3, 9, 12),
+ self: b(12),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#7' // A -> B, C, F.
+ ],
+ [
+ '#19' // A, C -> D, F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, D, *.
+ id: '#23',
+ title: ['A', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11]),
+ self: b(11),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#8' // A -> B, D, *.
+ ],
+ [],
+ [
+ { // A, D, E.
+ id: '#24',
+ title: ['A', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10),
+ self: b(10),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#9' // A -> B, D, E.
+ ],
+ [],
+ [
+ { // A, D, E -> F.
+ id: '#25',
+ title: ['A', 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#10' // A -> B, D, E -> F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, D, F.
+ id: '#26',
+ title: ['A', 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#11' // A -> B, D, F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, *, E.
+ id: '#27',
+ title: ['A', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16),
+ self: b(16),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#12' // A -> B, *, E.
+ ],
+ [
+ '#20', // A, C, E.
+ '#24' // A, D, E.
+ ],
+ [
+ { // A, *, E -> F.
+ id: '#28',
+ title: ['A', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15),
+ self: b(15),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#13' // A -> B, *, E -> F.
+ ],
+ [
+ '#21', // A, C, E -> F.
+ '#25' // A, D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, *, F.
+ id: '#29',
+ title: ['A', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15),
+ self: b(15),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#14' // A -> B, *, F.
+ ],
+ [
+ '#22', // A, C, F.
+ '#26' // A, D, F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *, *.
+ title: ['B', undefined, undefined],
+ values: [
+ {
+ total: b([0, 8]),
+ self: b(8),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B, C, *.
+ id: '#30',
+ title: ['B', 'C', undefined],
+ values: [
+ {
+ total: b([0, 5]),
+ self: b(5),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B, C -> D, *.
+ id: '#31',
+ title: ['B', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // B, C -> D, E.
+ id: '#32',
+ title: ['B', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // B, C -> D, E -> F.
+ id: '#33',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, C -> D, F.
+ id: '#34',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, C, E.
+ id: '#35',
+ title: ['B', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4),
+ self: b(4),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#32' // B, C -> D, E.
+ ],
+ [
+ { // B, C, E -> F.
+ id: '#36',
+ title: ['B', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#33' // B, C -> D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, C, F.
+ id: '#37',
+ title: ['B', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#34' // B, C -> D, F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, D, *.
+ id: '#38',
+ title: ['B', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // B, D, E.
+ id: '#39',
+ title: ['B', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // B, D, E -> F.
+ id: '#40',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, D, F.
+ id: '#41',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, *, E.
+ id: '#42',
+ title: ['B', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7),
+ self: b(7),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#35', // B, C, E.
+ '#39' // B, D, E.
+ ],
+ [
+ { // B, *, E -> F.
+ id: '#43',
+ title: ['B', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#36', // B, C, E -> F.
+ '#40' // B, D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *, F.
+ id: '#44',
+ title: ['B', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#37', // B, C, F.
+ '#41' // B, D, F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, C, *.
+ title: [undefined, 'C', undefined],
+ values: [
+ {
+ total: b([0, 5], [9, 14], [18, 23]),
+ self: b(23),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#15', // A, C, *.
+ '#30' // B, C, *.
+ ],
+ [
+ { // *, C -> D, *.
+ title: [undefined, 'D', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11], [18, 20]),
+ self: b(20),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#16', // A, C -> D, *.
+ '#31' // B, C -> D, *.
+ ],
+ [],
+ [
+ { // *, C -> D, E.
+ id: '#45',
+ title: [undefined, 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10, 18, 19),
+ self: b(19),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#17', // A, C -> D, E.
+ '#32' // B, C -> D, E.
+ ],
+ [],
+ [
+ { // *, C -> D, E -> F.
+ id: '#46',
+ title: [undefined, 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#18', // A, C -> D, E -> F.
+ '#33' // B, C -> D, E -> F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, C -> D, F.
+ id: '#47',
+ title: [undefined, 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#19', // A, C -> D, F.
+ '#34' // B, C -> D, F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, C, E.
+ id: '#48',
+ title: [undefined, 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 9, 10, 12, 13, 18, 19, 21, 22),
+ self: b(22),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#20', // A, C, E.
+ '#35' // B, C, E.
+ ],
+ [
+ '#45' // *, C -> D, E.
+ ],
+ [
+ { // *, C, E -> F.
+ id: '#49',
+ title: [undefined, 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3, 9, 12, 18, 21),
+ self: b(21),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#21', // A, C, E -> F.
+ '#36' // B, C, E -> F.
+ ],
+ [
+ '#46' // *, C -> D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, C, F.
+ id: '#50',
+ title: [undefined, 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3, 9, 12, 18, 21),
+ self: b(21),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#22', // A, C, F.
+ '#37' // B, C, F.
+ ],
+ [
+ '#47' // *, C -> D, F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, D, *.
+ title: [undefined, 'D', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11], [18, 20]),
+ self: b(20),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#23', // A, D, *.
+ '#38' // B, D, *.
+ ],
+ [],
+ [
+ { // *, D, E.
+ id: '#51',
+ title: [undefined, 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10, 18, 19),
+ self: b(19),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#24', // A, D, E.
+ '#39' // B, D, E.
+ ],
+ [],
+ [
+ { // *, D, E -> F.
+ id: '#52',
+ title: [undefined, 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#25', // A, D, E -> F.
+ '#40' // B, D, E -> F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, D, F.
+ id: '#53',
+ title: [undefined, 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#26', // A, D, F.
+ '#41' // B, D, F.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, *, E.
+ title: [undefined, undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21,
+ 22, 24, 25),
+ self: b(25),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#27', // A, *, E.
+ '#42' // B, *, E.
+ ],
+ [
+ '#48', // *, C, E.
+ '#51' // *, D, E.
+ ],
+ [
+ { // *, *, E -> F.
+ title: [undefined, undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15, 18, 21, 24),
+ self: b(24),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#28', // A, *, E -> F.
+ '#43' // B, *, E -> F.
+ ],
+ [
+ '#49', // *, C, E -> F.
+ '#52' // *, D, E -> F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, *, F.
+ title: [undefined, undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15, 18, 21, 24),
+ self: b(24),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#29', // A, *, F.
+ '#44' // B, *, F.
+ ],
+ [
+ '#50', // *, C, F.
+ '#53' // *, D, F.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined, undefined],
+ values: [
+ {
+ total: b([0, 26]),
+ self: b(26),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *, *.
+ title: ['A', undefined, undefined],
+ values: [
+ {
+ total: b([0, 17]),
+ self: b(17),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A, C, *.
+ id: '#0',
+ title: ['A', 'C', undefined],
+ values: [
+ {
+ total: b([0, 5], [9, 14]),
+ self: b(14),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A, C, E.
+ id: '#1',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 9, 10, 12, 13),
+ self: b(13),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // A, C, F.
+ id: '#2',
+ title: ['A', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3, 9, 12),
+ self: b(12),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A, C, F -> E.
+ id: '#3',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 3, 9, 12),
+ self: b(12),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // A, D, *.
+ id: '#4',
+ title: ['A', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11]),
+ self: b(11),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // A, D -> C, *.
+ id: '#5',
+ title: ['A', 'C', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11]),
+ self: b(11),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A, D -> C, E.
+ id: '#6',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10),
+ self: b(10),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // A, D -> C, F.
+ id: '#7',
+ title: ['A', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // A, D -> C, F -> E.
+ id: '#8',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, D, E.
+ id: '#9',
+ title: ['A', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10),
+ self: b(10),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#6' // A, D -> C, E.
+ ],
+ []
+ ]
+ },
+ { // A, D, F.
+ id: '#10',
+ title: ['A', 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#7' // A, D -> C, F.
+ ],
+ [
+ { // A, D, F -> E.
+ id: '#11',
+ title: ['A', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 9),
+ self: b(9),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#8' // A, D -> C, F -> E.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // A, *, E.
+ id: '#12',
+ title: ['A', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16),
+ self: b(16),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#1', // A, C, E.
+ '#9' // A, D, E.
+ ],
+ []
+ ]
+ },
+ { // A, *, F.
+ id: '#13',
+ title: ['A', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15),
+ self: b(15),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#2', // A, C, F.
+ '#10' // A, D, F.
+ ],
+ [
+ { // A, *, F -> E.
+ id: '#14',
+ title: ['A', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15),
+ self: b(15),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#3', // A, C, F -> E.
+ '#11' // A, D, F -> E.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, *, *.
+ title: ['B', undefined, undefined],
+ values: [
+ {
+ total: b([0, 8]),
+ self: b(8),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // B -> A, *, *.
+ title: ['A', undefined, undefined],
+ values: [
+ {
+ total: b([0, 8]),
+ self: b(8),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A, C, *.
+ id: '#15',
+ title: ['A', 'C', undefined],
+ values: [
+ {
+ total: b([0, 5]),
+ self: b(5),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // B -> A, C, E.
+ id: '#16',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4),
+ self: b(4),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // B -> A, C, F.
+ id: '#17',
+ title: ['A', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // B -> A, C, F -> E.
+ id: '#18',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B -> A, D, *.
+ id: '#19',
+ title: ['A', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ { // B -> A, D -> C, *.
+ id: '#20',
+ title: ['A', 'C', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // B -> A, D -> C, E.
+ id: '#21',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // B -> A, D -> C, F.
+ id: '#22',
+ title: ['A', 'C', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ [
+ { // B -> A, D -> C, F -> E.
+ id: '#23',
+ title: ['A', 'C', 'E'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B -> A, D, E.
+ id: '#24',
+ title: ['A', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#21' // B -> A, D -> C, E.
+ ],
+ []
+ ]
+ },
+ { // B -> A, D, F.
+ id: '#25',
+ title: ['A', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#22' // B -> A, D -> C, F.
+ ],
+ [
+ { // B -> A, D, F -> E.
+ id: '#26',
+ title: ['A', 'D', 'E'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#23' // B -> A, D -> C, F -> E.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B -> A, *, E.
+ id: '#27',
+ title: ['A', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7),
+ self: b(7),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#16', // B -> A, C, E.
+ '#24' // B -> A, D, E.
+ ],
+ []
+ ]
+ },
+ { // B -> A, *, F.
+ id: '#28',
+ title: ['A', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#17', // B -> A, C, F.
+ '#25' // B -> A, D, F.
+ ],
+ [
+ { // B -> A, *, F -> E.
+ id: '#29',
+ title: ['A', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [
+ '#18', // B -> A, C, F -> E.
+ '#26' // B -> A, D, F -> E.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, C, *.
+ id: '#30',
+ title: ['B', 'C', undefined],
+ values: [
+ {
+ total: b([0, 5]),
+ self: b(5),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#15' // B -> A, C, *.
+ ],
+ [],
+ [
+ { // B, C, E.
+ id: '#31',
+ title: ['B', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4),
+ self: b(4),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#16' // B -> A, C, E.
+ ],
+ [],
+ []
+ ]
+ },
+ { // B, C, F.
+ id: '#32',
+ title: ['B', 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#17' // B -> A, C, F.
+ ],
+ [],
+ [
+ { // B, C, F -> E.
+ id: '#33',
+ title: ['B', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 3),
+ self: b(3),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#18' // B -> A, C, F -> E.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // B, D, *.
+ id: '#34',
+ title: ['B', 'D', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#19' // B -> A, D, *.
+ ],
+ [
+ { // B, D -> C, *.
+ id: '#35',
+ title: ['B', 'C', undefined],
+ values: [
+ {
+ total: b([0, 2]),
+ self: b(2),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#20' // B -> A, D -> C, *.
+ ],
+ [],
+ [
+ { // B, D -> C, E.
+ id: '#36',
+ title: ['B', 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#21' // B -> A, D -> C, E.
+ ],
+ [],
+ []
+ ]
+ },
+ { // B, D -> C, F.
+ id: '#37',
+ title: ['B', 'C', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#22' // B -> A, D -> C, F.
+ ],
+ [],
+ [
+ { // B, D -> C, F -> E.
+ id: '#38',
+ title: ['B', 'C', 'E'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#23' // B -> A, D -> C, F -> E.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, D, E.
+ id: '#39',
+ title: ['B', 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1),
+ self: b(1),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#24' // B -> A, D, E.
+ ],
+ [
+ '#36' // B, D -> C, E.
+ ],
+ []
+ ]
+ },
+ { // B, D, F.
+ id: '#40',
+ title: ['B', 'D', 'F'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#25' // B -> A, D, F.
+ ],
+ [
+ '#37' // B, D -> C, F.
+ ],
+ [
+ { // B, D, F -> E.
+ id: '#41',
+ title: ['B', 'D', 'E'],
+ values: [
+ {
+ total: b(0),
+ self: b(0),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#26' // B -> A, D, F -> E.
+ ],
+ [
+ '#38' // B, D -> C, F -> E.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // B, *, E.
+ id: '#42',
+ title: ['B', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7),
+ self: b(7),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#27' // B -> A, *, E.
+ ],
+ [
+ '#31', // B, C, E.
+ '#39' // B, D, E.
+ ],
+ []
+ ]
+ },
+ { // B, *, F.
+ id: '#43',
+ title: ['B', undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#28' // B -> A, *, F.
+ ],
+ [
+ '#32', // B, C, F.
+ '#40' // B, D, F.
+ ],
+ [
+ { // B, *, F -> E.
+ id: '#44',
+ title: ['B', undefined, 'E'],
+ values: [
+ {
+ total: b(0, 3, 6),
+ self: b(6),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#29' // B -> A, *, F -> E.
+ ],
+ [
+ '#33', // B, C, F -> E.
+ '#41' // B, D, F -> E.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, C, *.
+ title: [undefined, 'C', undefined],
+ values: [
+ {
+ total: b([0, 5], [9, 14], [18, 23]),
+ self: b(23),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#0', // A, C, *.
+ '#30' // B, C, *.
+ ],
+ [],
+ [
+ { // *, C, E.
+ id: '#45',
+ title: [undefined, 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 9, 10, 12, 13, 18, 19, 21, 22),
+ self: b(22),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#1', // A, C, E.
+ '#31' // B, C, E.
+ ],
+ [],
+ []
+ ]
+ },
+ { // *, C, F.
+ id: '#46',
+ title: [undefined, 'C', 'F'],
+ values: [
+ {
+ total: b(0, 3, 9, 12, 18, 21),
+ self: b(21),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#2', // A, C, F.
+ '#32' // B, C, F.
+ ],
+ [],
+ [
+ { // *, C, F -> E.
+ id: '#47',
+ title: [undefined, 'C', 'E'],
+ values: [
+ {
+ total: b(0, 3, 9, 12, 18, 21),
+ self: b(21),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#3', // A, C, F -> E.
+ '#33' // B, C, F -> E.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ },
+ { // *, D, *.
+ title: [undefined, 'D', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11], [18, 20]),
+ self: b(20),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#4', // A, D, *.
+ '#34' // B, D, *.
+ ],
+ [
+ { // *, D -> C, *.
+ title: [undefined, 'C', undefined],
+ values: [
+ {
+ total: b([0, 2], [9, 11], [18, 20]),
+ self: b(20),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#5', // A, D -> C, *.
+ '#35' // B, D -> C, *.
+ ],
+ [],
+ [
+ { // *, D -> C, E.
+ id: '#48',
+ title: [undefined, 'C', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10, 18, 19),
+ self: b(19),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#6', // A, D -> C, E.
+ '#36' // B, D -> C, E.
+ ],
+ [],
+ []
+ ]
+ },
+ { // *, D -> C, F.
+ id: '#49',
+ title: [undefined, 'C', 'F'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#7', // A, D -> C, F.
+ '#37' // B, D -> C, F.
+ ],
+ [],
+ [
+ { // *, D -> C, F -> E.
+ id: '#50',
+ title: [undefined, 'C', 'E'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#8', // A, D -> C, F -> E.
+ '#38' // B, D -> C, F -> E.
+ ],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, D, E.
+ id: '#51',
+ title: [undefined, 'D', 'E'],
+ values: [
+ {
+ total: b(0, 1, 9, 10, 18, 19),
+ self: b(19),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#9', // A, D, E.
+ '#39' // B, D, E.
+ ],
+ [
+ '#48' // *, D -> C, E.
+ ],
+ []
+ ]
+ },
+ { // *, D, F.
+ id: '#52',
+ title: [undefined, 'D', 'F'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#10', // A, D, F.
+ '#40' // B, D, F.
+ ],
+ [
+ '#49' // *, D -> C, F.
+ ],
+ [
+ { // *, D, F -> E.
+ id: '#53',
+ title: [undefined, 'D', 'E'],
+ values: [
+ {
+ total: b(0, 9, 18),
+ self: b(18),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#11', // A, D, F -> E.
+ '#41' // B, D, F -> E.
+ ],
+ [
+ '#50' // *, D -> C, F -> E.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ }
+ ],
+ [
+ { // *, *, E.
+ title: [undefined, undefined, 'E'],
+ values: [
+ {
+ total: b(0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21,
+ 22, 24, 25),
+ self: b(25),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#12', // A, *, E.
+ '#42' // B, *, E.
+ ],
+ [
+ '#45', // *, C, E.
+ '#51' // *, D, E.
+ ],
+ []
+ ]
+ },
+ { // *, *, F.
+ title: [undefined, undefined, 'F'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15, 18, 21, 24),
+ self: b(24),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#13', // A, *, F.
+ '#43' // B, *, F.
+ ],
+ [
+ '#46', // *, C, F.
+ '#52' // *, D, F.
+ ],
+ [
+ { // *, *, F -> E.
+ title: [undefined, undefined, 'E'],
+ values: [
+ {
+ total: b(0, 3, 6, 9, 12, 15, 18, 21, 24),
+ self: b(24),
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ '#14', // A, *, F -> E.
+ '#44' // B, *, F -> E.
+ ],
+ [
+ '#47', // *, C, F -> E.
+ '#53' // *, D, F -> E.
+ ],
+ []
+ ]
+ }
+ ]
+ ]
+ }
+ ]
+ ]
+ });
+
+ builderTest('twoDimensionsComplete_totalCalculation', 2 /* dimensions */,
+ 1 /* valueCount */,
+ true /* setComplete */,
+ [
+ { path: [[], []], values: [10], kind: SELF },
+ { path: [['A'], []], values: [21], kind: SELF },
+ { path: [['A'], []], values: [30], kind: TOTAL },
+ { path: [['B'], []], values: [25], kind: SELF },
+ { path: [['B'], []], values: [32], kind: TOTAL },
+ { path: [[], ['1']], values: [3], kind: SELF },
+ { path: [[], ['1']], values: [15], kind: TOTAL },
+ { path: [[], ['2']], values: [40], kind: SELF },
+ { path: [[], ['2']], values: [41], kind: TOTAL }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 115,
+ self: 10,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 30,
+ self: 21,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 32,
+ self: 25,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 15,
+ self: 3,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // *, 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 41,
+ self: 40,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 115,
+ self: 10,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 30,
+ self: 21,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 32,
+ self: 25,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 15,
+ self: 3,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // *, 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 41,
+ self: 40,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined],
+ values: [
+ {
+ total: 115,
+ self: 10,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [
+ { // A, *.
+ title: ['A', undefined],
+ values: [
+ {
+ total: 30,
+ self: 21,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // B, *.
+ title: ['B', undefined],
+ values: [
+ {
+ total: 32,
+ self: 25,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1.
+ title: [undefined, '1'],
+ values: [
+ {
+ total: 15,
+ self: 3,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ },
+ { // *, 2.
+ title: [undefined, '2'],
+ values: [
+ {
+ total: 41,
+ self: 40,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ });
+
+
+ builderTest('threeDimensions_twoValues', 3 /* dimensions */,
+ 2 /* valueCount */,
+ false /* setComplete */,
+ [
+ { path: [[], [], []], values: [1, 89], kind: SELF },
+ { path: [['A'], [], []], values: [2, 34], kind: SELF },
+ { path: [['A'], [], []], values: [4, 55], kind: TOTAL },
+ { path: [['B'], [], []], values: [undefined, 13], kind: SELF },
+ { path: [['B'], [], []], values: [16, 21], kind: TOTAL },
+ { path: [[], ['1'], []], values: [32, undefined], kind: SELF },
+ { path: [[], ['1'], []], values: [64, 8], kind: TOTAL },
+ { path: [[], ['2'], []], values: [128, 2], kind: SELF },
+ { path: [[], ['2'], []], values: [undefined, undefined], kind: TOTAL },
+ { path: [[], [], ['%']], values: [undefined, 1], kind: TOTAL },
+ { path: [[], [], ['$']], values: [1024, undefined], kind: TOTAL },
+ { path: [[], [], ['@']], values: [undefined, undefined], kind: SELF }
+ ],
+ { // Top-down tree view.
+ title: [undefined, undefined, undefined],
+ values: [
+ {
+ total: (1 + 2 + 32 + 128) /* selfSum([[], [], []], 0) */ +
+ 1024 /* minResidual([[], [], []], 0) */,
+ self: 1,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: (89 + 34 + 13 + 2) /* selfSum([[], [], []], 1) */ +
+ ((55 - 34) + (21 - 13)) /* maxResidual([[], [], []], 1) */,
+ self: 89,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *, *.
+ title: ['A', undefined, undefined],
+ values: [
+ {
+ total: 4,
+ self: 2,
+ totalState: EXACT
+ },
+ {
+ total: 55,
+ self: 34,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // B, *, *.
+ title: ['B', undefined, undefined],
+ values: [
+ {
+ total: 16,
+ self: 0,
+ totalState: EXACT
+ },
+ {
+ total: 21,
+ self: 13,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1, *.
+ title: [undefined, '1', undefined],
+ values: [
+ {
+ total: 64,
+ self: 32,
+ totalState: EXACT
+ },
+ {
+ total: 8,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, 2, *.
+ title: [undefined, '2', undefined],
+ values: [
+ {
+ total: 128,
+ self: 128,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 2,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, *, %.
+ title: [undefined, undefined, '%'],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ },
+ {
+ total: 1,
+ self: 0,
+ totalState: EXACT
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, *, $.
+ title: [undefined, undefined, '$'],
+ values: [
+ {
+ total: 1024,
+ self: 0,
+ totalState: EXACT
+ },
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, *, @.
+ title: [undefined, undefined, '@'],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ },
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Top-down heavy view.
+ title: [undefined, undefined, undefined],
+ values: [
+ {
+ total: 1187,
+ self: 1,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 167,
+ self: 89,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *, *.
+ title: ['A', undefined, undefined],
+ values: [
+ {
+ total: 4,
+ self: 2,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 55,
+ self: 34,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // B, *, *.
+ title: ['B', undefined, undefined],
+ values: [
+ {
+ total: 16,
+ self: 0,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 21,
+ self: 13,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1, *.
+ title: [undefined, '1', undefined],
+ values: [
+ {
+ total: 64,
+ self: 32,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 8,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, 2, *.
+ title: [undefined, '2', undefined],
+ values: [
+ {
+ total: 128,
+ self: 128,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 2,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, *, %.
+ title: [undefined, undefined, '%'],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ },
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, *, $.
+ title: [undefined, undefined, '$'],
+ values: [
+ {
+ total: 1024,
+ self: 0,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, *, @.
+ title: [undefined, undefined, '@'],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ },
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ },
+ { // Bottom-up heavy view.
+ title: [undefined, undefined, undefined],
+ values: [
+ {
+ total: 1187,
+ self: 1,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 167,
+ self: 89,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [
+ { // A, *, *.
+ title: ['A', undefined, undefined],
+ values: [
+ {
+ total: 4,
+ self: 2,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 55,
+ self: 34,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // B, *, *.
+ title: ['B', undefined, undefined],
+ values: [
+ {
+ total: 16,
+ self: 0,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 21,
+ self: 13,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, 1, *.
+ title: [undefined, '1', undefined],
+ values: [
+ {
+ total: 64,
+ self: 32,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 8,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, 2, *.
+ title: [undefined, '2', undefined],
+ values: [
+ {
+ total: 128,
+ self: 128,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 2,
+ self: 2,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ],
+ [
+ { // *, *, %.
+ title: [undefined, undefined, '%'],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ },
+ {
+ total: 1,
+ self: 0,
+ totalState: LOWER_BOUND
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, *, $.
+ title: [undefined, undefined, '$'],
+ values: [
+ {
+ total: 1024,
+ self: 0,
+ totalState: LOWER_BOUND
+ },
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ },
+ { // *, *, @.
+ title: [undefined, undefined, '@'],
+ values: [
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ },
+ {
+ total: 0,
+ self: 0,
+ totalState: NOT_PROVIDED
+ }
+ ],
+ children: [
+ [],
+ [],
+ []
+ ]
+ }
+ ]
+ ]
+ });
+
+ test('recursionDepthTracker', function() {
+ const MAX_DEPTH = 5;
+ const tracker = new RecursionDepthTracker(MAX_DEPTH, 2 /* dimension */);
+
+ function pushNewNode(title) {
+ const node = new MultiDimensionalViewNode(
+ [undefined, 'ignored dimension', title, 'also ignored'],
+ 1 /* valueCount (not relevant for this test) */);
+ tracker.push(node);
+ return node;
+ }
+
+ function checkTracker(expectedDefinedViewNodePath, expectedRecursionDepth) {
+ const expectedBottomIndex = MAX_DEPTH -
+ expectedDefinedViewNodePath.length;
+ assert.strictEqual(tracker.bottomIndex, expectedBottomIndex);
+ assert.strictEqual(tracker.topIndex, MAX_DEPTH);
+
+ const undefinedPadding = new Array(expectedBottomIndex);
+ const expectedViewNodePath =
+ undefinedPadding.concat(expectedDefinedViewNodePath);
+ const expectedTitlePath =
+ undefinedPadding.concat(expectedDefinedViewNodePath.map(
+ function(node) { return node.title[2]; }));
+ assertListStrictEqual(tracker.viewNodePath, expectedViewNodePath);
+ assertListStrictEqual(tracker.titlePath, expectedTitlePath);
+
+ assert.strictEqual(tracker.recursionDepth, expectedRecursionDepth);
+ }
+
+ checkTracker([] /* empty stack */, 0);
+ const a1 = pushNewNode('A');
+ checkTracker([a1], 0);
+ const b1 = pushNewNode('B');
+ checkTracker([b1, a1], 0);
+ const c1 = pushNewNode('C');
+ checkTracker([c1, b1, a1], 0);
+ const d1 = pushNewNode('D');
+ checkTracker([d1, c1, b1, a1], 0);
+ tracker.pop();
+ checkTracker([c1, b1, a1], 0);
+ const a2 = pushNewNode('A');
+ checkTracker([a2, c1, b1, a1], 1);
+ const b2 = pushNewNode('B');
+ checkTracker([b2, a2, c1, b1, a1], 2);
+ tracker.pop();
+ checkTracker([a2, c1, b1, a1], 1);
+ tracker.pop();
+ checkTracker([c1, b1, a1], 0);
+ tracker.push(b2);
+ checkTracker([b2, c1, b1, a1], 1);
+ tracker.pop();
+ checkTracker([c1, b1, a1], 0);
+ tracker.pop();
+ checkTracker([b1, a1], 0);
+ tracker.pop();
+ checkTracker([a1], 0);
+ const a3 = pushNewNode('A');
+ checkTracker([a3, a1], 1);
+ tracker.push(a2);
+ checkTracker([a2, a3, a1], 2);
+ const a4 = pushNewNode('A');
+ checkTracker([a4, a2, a3, a1], 3);
+ tracker.pop();
+ checkTracker([a2, a3, a1], 2);
+ const b3 = pushNewNode('B');
+ checkTracker([b3, a2, a3, a1], 0);
+ tracker.push(a4);
+ checkTracker([a4, b3, a2, a3, a1], 1);
+ tracker.pop();
+ checkTracker([b3, a2, a3, a1], 0);
+ tracker.pop();
+ checkTracker([a2, a3, a1], 2);
+ tracker.pop();
+ checkTracker([a3, a1], 1);
+ tracker.pop();
+ checkTracker([a1], 0);
+ tracker.pop();
+ checkTracker([], 0);
+ tracker.push(a4);
+ checkTracker([a4], 0);
+ tracker.push(b1);
+ checkTracker([b1, a4], 0);
+ tracker.push(a1);
+ checkTracker([a1, b1, a4], 1);
+ tracker.pop();
+ checkTracker([b1, a4], 0);
+ const c2 = pushNewNode('C');
+ checkTracker([c2, b1, a4], 0);
+ tracker.push(a3);
+ checkTracker([a3, c2, b1, a4], 1);
+ tracker.pop();
+ checkTracker([c2, b1, a4], 0);
+ tracker.pop();
+ checkTracker([b1, a4], 0);
+ tracker.pop();
+ checkTracker([a4], 0);
+ tracker.pop();
+ checkTracker([], 0);
+
+ assert.throws(function() {
+ // Try popping from an empty tracker.
+ tracker.pop();
+ });
+
+ pushNewNode('F');
+ pushNewNode('U');
+ pushNewNode('L');
+ pushNewNode('L');
+ pushNewNode('!');
+ assert.throws(function() {
+ // Try pushing to a full tracker.
+ pushNewNode(':-(');
+ });
+ });
+
+ test('zFunction', function() {
+ // Empty list/string (suffix).
+ assert.deepEqual(zFunction([], 0), []);
+ assert.deepEqual(zFunction(['A'], 1), []);
+ assert.deepEqual(zFunction(['A', 'B', 'C'], 3), []);
+ assert.deepEqual(zFunction('', 0), []);
+ assert.deepEqual(zFunction('A', 1), []);
+ assert.deepEqual(zFunction('ABC', 3), []);
+
+ // Singleton list/string.
+ checkZFunction([1], [0]);
+ checkZFunction('T', [0]);
+
+ // No duplicate elements.
+ checkZFunction([1, 2, 3, 4, 5], [0, 0, 0, 0, 0]);
+ checkZFunction('ABCDEF', [0, 0, 0, 0, 0, 0]);
+
+ // No substring is a suffix.
+ checkZFunction([1, 2, 3, 2], [0, 0, 0, 0]);
+ checkZFunction('ABBB', [0, 0, 0, 0]);
+
+ // Pure repetition.
+ checkZFunction([1, 1, 1, 1, 1], [0, 4, 3, 2, 1]);
+ checkZFunction('AAAAA', [0, 4, 3, 2, 1]);
+
+ // Interleaved repetition.
+ checkZFunction([1, 2, 1, 3, 1, 2, 1], [0, 0, 1, 0, 3, 0, 1]);
+ checkZFunction('AAABAAB', [0, 2, 1, 0, 2, 1, 0]);
+
+ // Complex patterns.
+ checkZFunction([7, 9, 7, 9, 7, 9, 7, 9], [0, 0, 6, 0, 4, 0, 2, 0]);
+ checkZFunction('CCGTCCCGTACC', [0, 1, 0, 0, 2, 4, 1, 0, 0, 0, 2, 1]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/raf.html b/chromium/third_party/catapult/tracing/tracing/base/raf.html
new file mode 100644
index 00000000000..726a211be1f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/raf.html
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/utils.html">
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+tr.exportTo('tr.b', function() {
+ const ESTIMATED_IDLE_PERIOD_LENGTH_MILLISECONDS = 10;
+ // The maximum amount of time that we allow for a task to get scheduled
+ // in idle time before forcing the task to run.
+ const REQUEST_IDLE_CALLBACK_TIMEOUT_MILLISECONDS = 100;
+
+ // Setting this to true will cause stack traces to get dumped into the
+ // tasks. When an exception happens the original stack will be printed.
+ //
+ // NOTE: This should never be set committed as true.
+ const recordRAFStacks = false;
+
+ let pendingPreAFs = [];
+ let pendingRAFs = [];
+ const pendingIdleCallbacks = [];
+ let currentRAFDispatchList = undefined;
+
+ let rafScheduled = false;
+ let idleWorkScheduled = false;
+
+ function scheduleRAF() {
+ if (rafScheduled) return;
+ rafScheduled = true;
+ if (tr.isHeadless) {
+ Promise.resolve().then(function() {
+ processRequests(false, 0);
+ }, function(e) {
+ throw e;
+ });
+ } else {
+ if (window.requestAnimationFrame) {
+ window.requestAnimationFrame(processRequests.bind(this, false));
+ } else {
+ const delta = Date.now() - window.performance.now();
+ window.webkitRequestAnimationFrame(function(domTimeStamp) {
+ processRequests(false, domTimeStamp - delta);
+ });
+ }
+ }
+ }
+
+ function nativeRequestIdleCallbackSupported() {
+ return !tr.isHeadless && window.requestIdleCallback;
+ }
+
+ function scheduleIdleWork() {
+ if (idleWorkScheduled) return;
+ if (!nativeRequestIdleCallbackSupported()) {
+ scheduleRAF();
+ return;
+ }
+ idleWorkScheduled = true;
+ window.requestIdleCallback(function(deadline, didTimeout) {
+ processIdleWork(false /* forceAllTasksToRun */, deadline);
+ }, { timeout: REQUEST_IDLE_CALLBACK_TIMEOUT_MILLISECONDS });
+ }
+
+ function onAnimationFrameError(e, opt_stack) {
+ console.log(e.stack);
+ if (tr.isHeadless) throw e;
+
+ if (opt_stack) console.log(opt_stack);
+
+ if (e.message) {
+ console.error(e.message, e.stack);
+ } else {
+ console.error(e);
+ }
+ }
+
+ function runTask(task, frameBeginTime) {
+ try {
+ task.callback.call(task.context, frameBeginTime);
+ } catch (e) {
+ tr.b.onAnimationFrameError(e, task.stack);
+ }
+ }
+
+ function processRequests(forceAllTasksToRun, frameBeginTime) {
+ rafScheduled = false;
+
+ const currentPreAFs = pendingPreAFs;
+ currentRAFDispatchList = pendingRAFs;
+ pendingPreAFs = [];
+ pendingRAFs = [];
+ const hasRAFTasks = currentPreAFs.length || currentRAFDispatchList.length;
+
+ for (let i = 0; i < currentPreAFs.length; i++) {
+ runTask(currentPreAFs[i], frameBeginTime);
+ }
+
+ while (currentRAFDispatchList.length > 0) {
+ runTask(currentRAFDispatchList.shift(), frameBeginTime);
+ }
+ currentRAFDispatchList = undefined;
+
+ if ((!hasRAFTasks && !nativeRequestIdleCallbackSupported()) ||
+ forceAllTasksToRun) {
+ // We assume that we want to do a fixed maximum amount of optional work
+ // per frame. Hopefully rAF will eventually pass this in for us.
+ const rafCompletionDeadline =
+ frameBeginTime + ESTIMATED_IDLE_PERIOD_LENGTH_MILLISECONDS;
+ processIdleWork(
+ forceAllTasksToRun, {
+ timeRemaining() {
+ return rafCompletionDeadline - window.performance.now();
+ }
+ }
+ );
+ }
+
+ if (pendingIdleCallbacks.length > 0) scheduleIdleWork();
+ }
+
+ function processIdleWork(forceAllTasksToRun, deadline) {
+ idleWorkScheduled = false;
+ while (pendingIdleCallbacks.length > 0) {
+ runTask(pendingIdleCallbacks.shift());
+ // Check timer after running at least one idle task to avoid buggy
+ // window.performance.now() on some platforms from blocking the idle
+ // task queue.
+ if (!forceAllTasksToRun &&
+ (tr.isHeadless || deadline.timeRemaining() <= 0)) {
+ break;
+ }
+ }
+
+ if (pendingIdleCallbacks.length > 0) scheduleIdleWork();
+ }
+
+ function getStack_() {
+ if (!recordRAFStacks) return '';
+
+ const stackLines = tr.b.stackTrace();
+ // Strip off getStack_.
+ stackLines.shift();
+ return stackLines.join('\n');
+ }
+
+ function requestPreAnimationFrame(callback, opt_this) {
+ pendingPreAFs.push({
+ callback,
+ context: opt_this || global,
+ stack: getStack_()});
+ scheduleRAF();
+ }
+
+ function requestAnimationFrameInThisFrameIfPossible(callback, opt_this) {
+ if (!currentRAFDispatchList) {
+ requestAnimationFrame(callback, opt_this);
+ return;
+ }
+ currentRAFDispatchList.push({
+ callback,
+ context: opt_this || global,
+ stack: getStack_()});
+ return;
+ }
+
+ function requestAnimationFrame(callback, opt_this) {
+ pendingRAFs.push({
+ callback,
+ context: opt_this || global,
+ stack: getStack_()});
+ scheduleRAF();
+ }
+
+ function animationFrame() {
+ return new Promise(resolve => requestAnimationFrame(resolve));
+ }
+
+ function requestIdleCallback(callback, opt_this) {
+ pendingIdleCallbacks.push({
+ callback,
+ context: opt_this || global,
+ stack: getStack_()});
+ scheduleIdleWork();
+ }
+
+ function forcePendingRAFTasksToRun(frameBeginTime) {
+ if (!rafScheduled) return;
+ processRequests(false, frameBeginTime);
+ }
+
+ function forceAllPendingTasksToRunForTest() {
+ if (!rafScheduled && !idleWorkScheduled) return;
+ processRequests(true, 0);
+ }
+
+ function timeout(ms) {
+ return new Promise(resolve => window.setTimeout(resolve, ms));
+ }
+
+ function idle() {
+ return new Promise(resolve => requestIdleCallback(resolve));
+ }
+
+ return {
+ animationFrame,
+ forceAllPendingTasksToRunForTest,
+ forcePendingRAFTasksToRun,
+ idle,
+ onAnimationFrameError,
+ requestAnimationFrame,
+ requestAnimationFrameInThisFrameIfPossible,
+ requestIdleCallback,
+ requestPreAnimationFrame,
+ timeout,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/raf_test.html b/chromium/third_party/catapult/tracing/tracing/base/raf_test.html
new file mode 100644
index 00000000000..d3f2b0fc5ee
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/raf_test.html
@@ -0,0 +1,245 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/raf.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ if (tr.isHeadless) return;
+
+ test('idleCallbackWorks', function() {
+ return new Promise(function(resolve, reject) {
+ tr.b.requestIdleCallback(resolve);
+ });
+ });
+
+ test('forceAllPendingTasksToRunForTest', function() {
+ let rafRan = false;
+ tr.b.requestAnimationFrame(function() {
+ rafRan = true;
+ });
+ let idleRan = false;
+ tr.b.requestIdleCallback(function() {
+ idleRan = true;
+ });
+ assert.isFalse(rafRan);
+ assert.isFalse(idleRan);
+ tr.b.forceAllPendingTasksToRunForTest();
+ assert.isTrue(rafRan);
+ assert.isTrue(idleRan);
+ });
+
+ test('forcePendingRAFTasksToRun', function() {
+ let rafRan = false;
+ tr.b.requestAnimationFrame(function() {
+ rafRan = true;
+ });
+ let idleRan = false;
+ tr.b.requestIdleCallback(function() {
+ idleRan = true;
+ });
+ tr.b.forcePendingRAFTasksToRun();
+ assert.isTrue(rafRan);
+ assert.isFalse(idleRan);
+ });
+
+ let fakeNow = undefined;
+ function withFakeWindowPerformanceNow(func) {
+ const oldNow = window.performance.now;
+ try {
+ window.performance.now = function() { return fakeNow; };
+ func();
+ } finally {
+ window.performance.now = oldNow;
+ }
+ }
+
+ // None of the following tests are relevant if the browser supports idle
+ // callbacks natively. Nevertheless, run them without native idle support to
+ // make sure the fallback keeps working.
+ function withoutNativeIdleCallbacks(func) {
+ const oldRIC = window.requestIdleCallback;
+ try {
+ window.requestIdleCallback = undefined;
+ func();
+ } finally {
+ window.requestIdleCallback = oldRIC;
+ }
+ }
+
+ function withMockedScheduling(func) {
+ withFakeWindowPerformanceNow(function() {
+ withoutNativeIdleCallbacks(func);
+ });
+ }
+
+ test('runIdleTaskWhileIdle', function() {
+ withMockedScheduling(function() {
+ tr.b.forceAllPendingTasksToRunForTest();
+
+ let rafRan = false;
+ tr.b.requestAnimationFrame(function() {
+ rafRan = true;
+ });
+ let idleRan = false;
+ tr.b.requestIdleCallback(function() {
+ idleRan = true;
+ });
+ fakeNow = 0;
+ tr.b.forcePendingRAFTasksToRun(fakeNow);
+ assert.isFalse(idleRan);
+ assert.isTrue(rafRan);
+ tr.b.forcePendingRAFTasksToRun(fakeNow);
+ assert.isTrue(idleRan);
+ });
+ });
+
+ test('twoShortIdleCallbacks', function() {
+ withMockedScheduling(function() {
+ tr.b.forceAllPendingTasksToRunForTest();
+
+ let idle1Ran = false;
+ let idle2Ran = false;
+ tr.b.requestIdleCallback(function() {
+ fakeNow += 1;
+ idle1Ran = true;
+ });
+ tr.b.requestIdleCallback(function() {
+ fakeNow += 1;
+ idle2Ran = true;
+ });
+ fakeNow = 0;
+ tr.b.forcePendingRAFTasksToRun(fakeNow);
+ assert.isTrue(idle1Ran);
+ assert.isTrue(idle2Ran);
+ });
+ });
+
+
+ test('oneLongOneShortIdleCallback', function() {
+ withMockedScheduling(function() {
+ tr.b.forceAllPendingTasksToRunForTest();
+
+ let idle1Ran = false;
+ let idle2Ran = false;
+ tr.b.requestIdleCallback(function() {
+ fakeNow += 100;
+ idle1Ran = true;
+ });
+ tr.b.requestIdleCallback(function() {
+ fakeNow += 1;
+ idle2Ran = true;
+ });
+ fakeNow = 0;
+ tr.b.forcePendingRAFTasksToRun(fakeNow);
+ assert.isTrue(idle1Ran);
+ assert.isFalse(idle2Ran);
+
+ // Reset idle1Ran to verify that it dosn't run again.
+ idle1Ran = false;
+
+ // Now run. idle2 should now run.
+ tr.b.forcePendingRAFTasksToRun(fakeNow);
+ assert.isFalse(idle1Ran);
+ assert.isTrue(idle2Ran);
+ });
+ });
+
+ test('buggyPerformanceNowDoesNotBlockIdleTasks', function() {
+ withMockedScheduling(function() {
+ tr.b.forcePendingRAFTasksToRun(); // Clear current RAF task queue.
+
+ let idle1Ran = false;
+ let idle2Ran = false;
+ tr.b.requestIdleCallback(function() {
+ fakeNow += 100;
+ idle1Ran = true;
+ });
+ tr.b.requestIdleCallback(function() {
+ fakeNow += 1;
+ idle2Ran = true;
+ });
+ fakeNow = 10000;
+ tr.b.forcePendingRAFTasksToRun(0);
+ assert.isTrue(idle1Ran);
+ assert.isFalse(idle2Ran);
+
+ // Reset idle1Ran to verify that it dosn't run again.
+ idle1Ran = false;
+
+ // Now run. idle2 should now run.
+ tr.b.forcePendingRAFTasksToRun(0);
+ assert.isFalse(idle1Ran);
+ assert.isTrue(idle2Ran);
+ });
+ });
+
+ function withFixedIdleTimeRemaining(idleTime, func) {
+ const oldRIC = window.requestIdleCallback;
+ try {
+ const pendingIdleCallbacks = [];
+ window.requestIdleCallback = function(callback) {
+ const deadline = {
+ timeRemaining() {
+ return idleTime;
+ }
+ };
+ pendingIdleCallbacks.push(function() {
+ callback(deadline, false /* didTimeout */);
+ });
+ };
+ func(pendingIdleCallbacks);
+ } finally {
+ window.requestIdleCallback = oldRIC;
+ }
+ }
+
+ test('idleCallbackWithIdletime', function() {
+ withFixedIdleTimeRemaining(1000, function(pendingIdleCallbacks) {
+ let idle1Ran = false;
+ let idle2Ran = false;
+ tr.b.requestIdleCallback(function() {
+ idle1Ran = true;
+ });
+ tr.b.requestIdleCallback(function() {
+ idle2Ran = true;
+ });
+ assert.lengthOf(pendingIdleCallbacks, 1);
+ pendingIdleCallbacks.shift()();
+
+ // Both callbacks should have run since there was idle time.
+ assert.isTrue(idle1Ran);
+ assert.isTrue(idle2Ran);
+ });
+ });
+
+ test('idleCallbackWithoutIdletime', function() {
+ withFixedIdleTimeRemaining(0, function(pendingIdleCallbacks) {
+ let idle1Ran = false;
+ let idle2Ran = false;
+ tr.b.requestIdleCallback(function() {
+ idle1Ran = true;
+ });
+ tr.b.requestIdleCallback(function() {
+ idle2Ran = true;
+ });
+ assert.lengthOf(pendingIdleCallbacks, 1);
+ pendingIdleCallbacks.shift()();
+
+ // Only the first idle callback should have run since there was no idle
+ // time left.
+ assert.isTrue(idle1Ran);
+ assert.isFalse(idle2Ran);
+
+ // Run the remaining idle task.
+ assert.lengthOf(pendingIdleCallbacks, 1);
+ pendingIdleCallbacks.shift()();
+ assert.isTrue(idle2Ran);
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/scalar.html b/chromium/third_party/catapult/tracing/tracing/base/scalar.html
new file mode 100644
index 00000000000..4c91eb69dc2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/scalar.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ class Scalar {
+ constructor(unit, value) {
+ if (!(unit instanceof tr.b.Unit)) {
+ throw new Error('Expected Unit');
+ }
+
+ if (!(typeof(value) === 'number')) {
+ throw new Error('Expected value to be number');
+ }
+
+ this.unit = unit;
+ this.value = value;
+ }
+
+ asDict() {
+ return {
+ unit: this.unit.asJSON(),
+ value: tr.b.numberToJson(this.value),
+ };
+ }
+
+ toString() {
+ return this.unit.format(this.value);
+ }
+
+ static fromDict(d) {
+ return new Scalar(tr.b.Unit.fromJSON(d.unit),
+ tr.b.numberFromJson(d.value));
+ }
+ }
+
+ return {
+ Scalar,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/scalar_test.html b/chromium/third_party/catapult/tracing/tracing/base/scalar_test.html
new file mode 100644
index 00000000000..3bfd772732d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/scalar_test.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('nonUnitThrows', function() {
+ assert.throws(function() { new tr.b.Scalar('foo', -273.15); });
+ });
+
+ test('nonNumberScalarThrows', function() {
+ const unit = tr.b.Unit.byName.sizeInBytes;
+ assert.throws(function() { new tr.b.Scalar(unit, 'foo'); });
+ });
+
+ test('scalarBasic', function() {
+ const unit = tr.b.Unit.byName.sizeInBytes;
+
+ const d = {
+ unit: unit.asJSON(),
+ value: 42
+ };
+
+ assert.deepEqual(d, tr.b.Scalar.fromDict(d).asDict());
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/serializable.html b/chromium/third_party/catapult/tracing/tracing/base/serializable.html
new file mode 100644
index 00000000000..de8efe78c48
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/serializable.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.b', function() {
+ class Serializable {
+ constructor() {
+ Object.defineProperty(this, 'properties_', {
+ configurable: false,
+ enumerable: false,
+ value: new Map(),
+ });
+ }
+
+ /**
+ * @param {string} name
+ * @param {!Object} initialValue
+ */
+ define(name, initialValue) {
+ if (this[name] !== undefined) {
+ throw new Error(`"${name}" is already defined.`);
+ }
+ if (name[name.length - 1] === '_') {
+ throw new Error(`"${name}" cannot end with an underscore.`);
+ }
+
+ this.properties_.set(name, initialValue);
+
+ Object.defineProperty(this, name, {
+ configurable: false,
+ enumerable: true,
+ get: () => this.properties_.get(name),
+ set: value => this.setProperty_(name, value),
+ });
+ }
+
+ setProperty_(name, value) {
+ this.properties_.set(name, value);
+ }
+
+ clone() {
+ return Serializable.fromDict(this.asDict());
+ }
+
+ asDict() {
+ function visit(obj) {
+ if (obj instanceof Serializable) return obj.asDict();
+ if (obj instanceof Set) return Array.from(obj);
+ if (obj instanceof Array) return obj.map(visit);
+ if (!(obj instanceof Map)) return obj;
+
+ const result = {};
+ for (const [name, value] of obj) {
+ result[name] = visit(value);
+ }
+ return result;
+ }
+
+ const dict = {type: this.constructor.name};
+ for (const [name, value] of this.properties_) {
+ dict[name.replace(/_$/, '')] = visit(value);
+ }
+ return dict;
+ }
+
+ static fromDict(dict) {
+ function visit(d) {
+ if (d instanceof Array) return d.map(visit);
+ if (!(d instanceof Object)) return d;
+ if (typeof d.type === 'string') return Serializable.fromDict(d);
+
+ const result = new Map();
+ for (const [name, value] of Object.entries(d)) {
+ result.set(name, visit(value));
+ }
+ return result;
+ }
+
+ const typeInfo = Serializable.findTypeInfoWithName(dict.type);
+ const result = new typeInfo.constructor();
+ for (const [name, value] of Object.entries(dict)) {
+ result[name] = visit(value);
+ }
+ return result;
+ }
+ }
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ options.defaultMetadata = {};
+ options.mandatoryBaseClass = Serializable;
+ tr.b.decorateExtensionRegistry(Serializable, options);
+
+ return {
+ Serializable,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/serializable_test.html b/chromium/third_party/catapult/tracing/tracing/base/serializable_test.html
new file mode 100644
index 00000000000..502c1afcc11
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/serializable_test.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/serializable.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ class Stuff extends tr.b.Serializable {
+ constructor() {
+ super();
+ this.define('boole', false);
+ this.define('answer', 0);
+ this.define('hipparchus', new Map());
+ this.define('ary', []);
+ this.define('cantor', new Set());
+ }
+ }
+
+ tr.b.Serializable.register(Stuff);
+
+ test('serializable', function() {
+ const stuff = new Stuff();
+ stuff.boole = true;
+ stuff.answer = 42;
+ stuff.hipparchus.set('thing', new Stuff());
+ stuff.hipparchus.get('thing').answer = -1;
+ stuff.ary.push('holy');
+ stuff.cantor.add('handgrenade');
+
+ const clone = stuff.clone();
+ assert.isTrue(clone.boole);
+ assert.strictEqual(42, clone.answer);
+ assert.strictEqual(-1, clone.hipparchus.get('thing').answer);
+ assert.strictEqual('holy', tr.b.getOnlyElement(clone.ary));
+ assert.strictEqual('handgrenade', tr.b.getOnlyElement(clone.cantor));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/settings.html b/chromium/third_party/catapult/tracing/tracing/base/settings.html
new file mode 100644
index 00000000000..4a5d786edd2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/settings.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Settings object.
+ */
+tr.exportTo('tr.b', function() {
+ /**
+ * Settings is a simple wrapper around local storage, to make it easier
+ * to test classes that have settings.
+ *
+ * May be called as new tr.b.Settings() or simply tr.b.Settings()
+ * @constructor
+ */
+ function Settings() {
+ return Settings;
+ }
+
+ if (tr.b.unittest && tr.b.unittest.TestRunner) {
+ tr.b.unittest.TestRunner.addEventListener(
+ 'tr-unittest-will-run',
+ function() {
+ if (tr.isHeadless) {
+ Settings.setAlternativeStorageInstance(new HeadlessStorage());
+ } else {
+ Settings.setAlternativeStorageInstance(global.sessionStorage);
+ global.sessionStorage.clear();
+ }
+ });
+ }
+
+ function SessionSettings() {
+ return SessionSettings;
+ }
+
+ function AddStaticStorageFunctionsToClass_(inputClass, storage) {
+ inputClass.storage_ = storage;
+
+ /**
+ * Get the setting with the given name.
+ *
+ * @param {string} key The name of the setting.
+ * @param {string=} opt_default The default value to return if not set.
+ * @param {string=} opt_namespace If set, the setting name will be prefixed
+ * with this namespace, e.g. "categories.settingName". This is useful for
+ * a set of related settings.
+ */
+ inputClass.get = function(key, opt_default, opt_namespace) {
+ key = inputClass.namespace_(key, opt_namespace);
+ const rawVal = inputClass.storage_.getItem(key);
+ if (rawVal === null || rawVal === undefined) {
+ return opt_default;
+ }
+
+ // Old settings versions used to stringify objects instead of putting them
+ // into JSON. If those are encountered, parse will fail. In that case,
+ // "upgrade" the setting to the default value.
+ try {
+ return JSON.parse(rawVal).value;
+ } catch (e) {
+ inputClass.storage_.removeItem(key);
+ return opt_default;
+ }
+ };
+
+ /**
+ * Set the setting with the given name to the given value.
+ *
+ * @param {string} key The name of the setting.
+ * @param {string} value The value of the setting.
+ * @param {string=} opt_namespace If set, the setting name will be prefixed
+ * with this namespace, e.g. "categories.settingName". This is useful for
+ * a set of related settings.
+ */
+ inputClass.set = function(key, value, opt_namespace) {
+ if (value === undefined) {
+ throw new Error('Settings.set: value must not be undefined');
+ }
+ const v = JSON.stringify({value});
+ inputClass.storage_.setItem(
+ inputClass.namespace_(key, opt_namespace), v);
+ };
+
+ /**
+ * Return a list of all the keys, or all the keys in the given namespace
+ * if one is provided.
+ *
+ * @param {string=} opt_namespace If set, only return settings which
+ * begin with this prefix.
+ */
+ inputClass.keys = function(opt_namespace) {
+ const result = [];
+ opt_namespace = opt_namespace || '';
+ for (let i = 0; i < inputClass.storage_.length; i++) {
+ const key = inputClass.storage_.key(i);
+ if (inputClass.isnamespaced_(key, opt_namespace)) {
+ result.push(inputClass.unnamespace_(key, opt_namespace));
+ }
+ }
+ return result;
+ };
+
+ inputClass.isnamespaced_ = function(key, opt_namespace) {
+ return key.indexOf(inputClass.normalize_(opt_namespace)) === 0;
+ };
+
+ inputClass.namespace_ = function(key, opt_namespace) {
+ return inputClass.normalize_(opt_namespace) + key;
+ };
+
+ inputClass.unnamespace_ = function(key, opt_namespace) {
+ return key.replace(inputClass.normalize_(opt_namespace), '');
+ };
+
+ /**
+ * All settings are prefixed with a global namespace to avoid collisions.
+ * inputClass may also be namespaced with an additional prefix passed into
+ * the get, set, and keys methods in order to group related settings.
+ * This method makes sure the two namespaces are always set properly.
+ */
+ inputClass.normalize_ = function(opt_namespace) {
+ return inputClass.NAMESPACE + (opt_namespace ? opt_namespace + '.' : '');
+ };
+
+ inputClass.setAlternativeStorageInstance = function(instance) {
+ inputClass.storage_ = instance;
+ };
+
+ inputClass.getAlternativeStorageInstance = function() {
+ if (!tr.isHeadless && inputClass.storage_ === localStorage) {
+ return undefined;
+ }
+ return inputClass.storage_;
+ };
+
+ inputClass.NAMESPACE = 'trace-viewer';
+ }
+
+ function HeadlessStorage() {
+ this.length = 0;
+ this.hasItem_ = {};
+ this.items_ = {};
+ this.itemsAsArray_ = undefined;
+ }
+ HeadlessStorage.prototype = {
+ key(index) {
+ return this.itemsAsArray[index];
+ },
+
+ get itemsAsArray() {
+ if (this.itemsAsArray_ !== undefined) {
+ return this.itemsAsArray_;
+ }
+ const itemsAsArray = [];
+ for (const k in this.items_) {
+ itemsAsArray.push(k);
+ }
+ this.itemsAsArray_ = itemsAsArray;
+ return this.itemsAsArray_;
+ },
+
+ getItem(key) {
+ if (!this.hasItem_[key]) {
+ return null;
+ }
+ return this.items_[key];
+ },
+
+ removeItem(key) {
+ if (!this.hasItem_[key]) {
+ return;
+ }
+ const value = this.items_[key];
+ delete this.hasItem_[key];
+ delete this.items_[key];
+ this.length--;
+ this.itemsAsArray_ = undefined;
+ return value;
+ },
+
+ setItem(key, value) {
+ if (this.hasItem_[key]) {
+ this.items_[key] = value;
+ return;
+ }
+ this.items_[key] = value;
+ this.hasItem_[key] = true;
+ this.length++;
+ this.itemsAsArray_ = undefined;
+ return value;
+ }
+ };
+
+ if (tr.isHeadless) {
+ AddStaticStorageFunctionsToClass_(Settings, new HeadlessStorage());
+ AddStaticStorageFunctionsToClass_(SessionSettings, new HeadlessStorage());
+ } else {
+ AddStaticStorageFunctionsToClass_(Settings, localStorage);
+ AddStaticStorageFunctionsToClass_(SessionSettings, sessionStorage);
+ }
+
+ return {
+ Settings,
+ SessionSettings,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/settings_test.html b/chromium/third_party/catapult/tracing/tracing/base/settings_test.html
new file mode 100644
index 00000000000..5fb452f1816
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/settings_test.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/settings.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function assertSettingIs(expectedValue, key) {
+ assert.strictEqual(tr.b.Settings.get(key), expectedValue);
+ }
+
+ // Old settings versions used to stringify objects instead of putting them
+ // into JSON. This test makes sure that these old settings yield the default
+ // value instead of strings.
+ test('oldStyleSettingYieldsDefaultValue', function() {
+ const storage = tr.b.Settings.getAlternativeStorageInstance();
+ storage.setItem(tr.b.Settings.namespace_('key'), 'hello world');
+
+ assert.strictEqual(tr.b.Settings.get('key', 'value'), 'value');
+ });
+
+ test('setGetString', function() {
+ const settings = new tr.b.Settings();
+ settings.set('my_key', 'my_val');
+ assert.strictEqual(settings.get('my_key'), 'my_val');
+ // tr.b.Settings() is a singleton
+ assert.strictEqual(tr.b.Settings().get('my_key'), 'my_val');
+ });
+
+ test('setGetNumber', function() {
+ const settings = new tr.b.Settings();
+ settings.set('my_key', 5);
+ assertSettingIs(5, 'my_key');
+ });
+
+ test('setGetBool', function() {
+ const settings = new tr.b.Settings();
+ settings.set('my_key', false);
+ assertSettingIs(false, 'my_key');
+ });
+
+ test('setGetObject', function() {
+ const settings = new tr.b.Settings();
+ settings.set('my_key', {'hello': 5});
+ assert.deepEqual(settings.get('my_key'), {'hello': 5});
+ });
+
+ test('setInvalidObject', function() {
+ const settings = new tr.b.Settings();
+ const obj = {'hello': undefined};
+ obj.hello = obj;
+ assert.throws(function() {
+ settings.set('my_key', obj);
+ });
+ });
+
+ test('setUndefined', function() {
+ const settings = new tr.b.Settings();
+ assert.throws(function() {
+ settings.set('my_key', undefined);
+ });
+ });
+
+ test('getUnset', function() {
+ const settings = new tr.b.Settings();
+ // Undefined should be returned if value isn't set.
+ assertSettingIs(undefined, 'my_key');
+ });
+
+ test('getDefault', function() {
+ const settings = new tr.b.Settings();
+ // default_val should be returned if value isn't set.
+ assert.strictEqual(settings.get('my_key', 'default_val'), 'default_val');
+ });
+
+ test('setGetPrefix', function() {
+ const settings = new tr.b.Settings();
+ settings.set('key_a', 'foo', 'my_prefix');
+ assert.strictEqual(settings.get('key_a', undefined, 'my_prefix'), 'foo');
+ assert.strictEqual(settings.get('key_a', 'bar', 'my_prefix'), 'foo');
+ assert.isUndefined(settings.get('key_a'));
+ assert.strictEqual(settings.get('key_a', 'bar'), 'bar');
+ });
+
+ test('keys', function() {
+ const settings = new tr.b.Settings();
+ settings.set('key_a', 'foo');
+ settings.set('key_b', 'bar');
+ settings.set('key_c', 'baz');
+ assert.sameMembers(settings.keys(), ['key_a', 'key_b', 'key_c']);
+ });
+
+ test('keysPrefix', function() {
+ const settings = new tr.b.Settings();
+ settings.set('key_a', 'foo', 'prefix1');
+ settings.set('key_b', 'bar', 'prefix1');
+ settings.set('key_c', 'baz', 'prefix1');
+ settings.set('key_a', 'foo', 'prefix2');
+ settings.set('key_b', 'bar', 'prefix2');
+ settings.set('key_C', 'baz', 'prefix2');
+ assert.sameMembers(settings.keys('prefix1'), ['key_a', 'key_b', 'key_c']);
+ assert.sameMembers(settings.keys('prefix2'), ['key_C', 'key_a', 'key_b']);
+ assert.sameMembers(
+ settings.keys(),
+ ['prefix1.key_a', 'prefix1.key_b', 'prefix1.key_c',
+ 'prefix2.key_C', 'prefix2.key_a', 'prefix2.key_b']);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/sinebow_color_generator.html b/chromium/third_party/catapult/tracing/tracing/base/sinebow_color_generator.html
new file mode 100644
index 00000000000..dac1471f205
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/sinebow_color_generator.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.b', function() {
+ /**
+ * Generate pretty colors!
+ * http://basecase.org/env/on-rainbows
+ * https://mycarta.wordpress.com/2012/10/06/the-rainbow-is-deadlong-live-the-rainbow-part-3/
+ *
+ * Set brightness = 0 to always generate black.
+ * Set brightness = 2 to always generate white.
+ * Set brightness = 1 to generate saturated colors.
+ *
+ * @constructor
+ * @param {number=} opt_a alpha opacity in [0,1]
+ * @param {number=} opt_brightness in [0,2]
+ */
+ function SinebowColorGenerator(opt_a, opt_brightness) {
+ this.a_ = (opt_a === undefined) ? 1 : opt_a;
+ this.brightness_ = (opt_brightness === undefined) ? 1 : opt_brightness;
+ this.colorIndex_ = 0;
+ this.keyToColor = {};
+ }
+
+ SinebowColorGenerator.prototype = {
+ colorForKey(key) {
+ if (!this.keyToColor[key]) {
+ this.keyToColor[key] = this.nextColor();
+ }
+ return this.keyToColor[key];
+ },
+
+ nextColor() {
+ const components = SinebowColorGenerator.nthColor(this.colorIndex_++);
+ return tr.b.Color.fromString(SinebowColorGenerator.calculateColor(
+ components[0], components[1], components[2],
+ this.a_, this.brightness_));
+ }
+ };
+
+ SinebowColorGenerator.PHI = (1 + Math.sqrt(5)) / 2;
+
+ SinebowColorGenerator.sinebow_ = function(h) {
+ h += 0.5;
+ h = -h;
+ let r = Math.sin(Math.PI * h);
+ let g = Math.sin(Math.PI * (h + 1 / 3));
+ let b = Math.sin(Math.PI * (h + 2 / 3));
+ r *= r; g *= g; b *= b;
+ // Roughly correct for human perception.
+ // https://en.wikipedia.org/wiki/Luma_%28video%29
+ // Multiply by 2 to normalize all values to 0.5.
+ // (Halfway between black and white.)
+ const y = 2 * (0.2989 * r + 0.5870 * g + 0.1140 * b);
+ r /= y; g /= y; b /= y;
+ return [256 * r, 256 * g, 256 * b];
+ };
+
+ SinebowColorGenerator.nthColor = function(n) {
+ return SinebowColorGenerator.sinebow_(n * this.PHI);
+ };
+
+ SinebowColorGenerator.calculateColor = function(r, g, b, a, brightness) {
+ if (brightness <= 1) {
+ r *= brightness;
+ g *= brightness;
+ b *= brightness;
+ } else {
+ r = tr.b.math.lerp(tr.b.math.normalize(brightness, 1, 2), r, 255);
+ g = tr.b.math.lerp(tr.b.math.normalize(brightness, 1, 2), g, 255);
+ b = tr.b.math.lerp(tr.b.math.normalize(brightness, 1, 2), b, 255);
+ }
+ r = Math.round(r);
+ g = Math.round(g);
+ b = Math.round(b);
+ return 'rgba(' + r + ',' + g + ',' + b + ', ' + a + ')';
+ };
+
+ return {
+ SinebowColorGenerator,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/sinebow_color_generator_test.html b/chromium/third_party/catapult/tracing/tracing/base/sinebow_color_generator_test.html
new file mode 100644
index 00000000000..db3ed984994
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/sinebow_color_generator_test.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color.html">
+<link rel="import" href="/tracing/base/sinebow_color_generator.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ test('SinebowColorGenerator', function() {
+ let generator = new tr.b.SinebowColorGenerator();
+ assert.strictEqual(
+ 'rgba(270,67,67,1)', generator.colorForKey('z').toString());
+ assert.strictEqual(
+ 'rgba(44,132,329,1)', generator.colorForKey('y').toString());
+ assert.strictEqual(
+ 'rgba(99,166,9,1)', generator.colorForKey('x').toString());
+ assert.strictEqual(
+ 'rgba(270,67,67,1)', generator.colorForKey('z').toString());
+
+ generator = new tr.b.SinebowColorGenerator(0.5);
+ assert.strictEqual(
+ 'rgba(270,67,67,0.5)', generator.colorForKey('z').toString());
+ assert.strictEqual(
+ 'rgba(44,132,329,0.5)', generator.colorForKey('y').toString());
+ assert.strictEqual(
+ 'rgba(99,166,9,0.5)', generator.colorForKey('x').toString());
+ assert.strictEqual(
+ 'rgba(270,67,67,0.5)', generator.colorForKey('z').toString());
+
+ generator = new tr.b.SinebowColorGenerator(1, 0);
+ assert.strictEqual(
+ 'rgba(0,0,0,1)', generator.colorForKey('z').toString());
+ assert.strictEqual(
+ 'rgba(0,0,0,1)', generator.colorForKey('y').toString());
+ assert.strictEqual(
+ 'rgba(0,0,0,1)', generator.colorForKey('x').toString());
+ assert.strictEqual(
+ 'rgba(0,0,0,1)', generator.colorForKey('z').toString());
+
+ generator = new tr.b.SinebowColorGenerator(1, 2);
+ assert.strictEqual(
+ 'rgba(255,255,255,1)', generator.colorForKey('z').toString());
+ assert.strictEqual(
+ 'rgba(255,255,255,1)', generator.colorForKey('y').toString());
+ assert.strictEqual(
+ 'rgba(255,255,255,1)', generator.colorForKey('x').toString());
+ assert.strictEqual(
+ 'rgba(255,255,255,1)', generator.colorForKey('z').toString());
+ });
+
+ test('SinebowColorGeneratorVisual', function() {
+ if (tr.isHeadless) return;
+
+ const generator = new tr.b.SinebowColorGenerator();
+ const parentDiv = document.createElement('div');
+ this.addHTMLOutput(parentDiv);
+
+ for (let i = 0; i < 350; i++) {
+ const spanElem = document.createElement('span');
+ spanElem.style.width = '50px';
+ spanElem.style.display = 'inline-block';
+ spanElem.style.backgroundColor = generator.colorForKey(i).toString();
+ const rgb = generator.colorForKey(i).toString().split('(')[1].split(',');
+ const r = rgb[0];
+ const g = rgb[1];
+ const b = rgb[2].split(')')[0];
+ const hsl = new tr.b.Color(r, g, b, 1).toHSL();
+ spanElem.appendChild(document.createTextNode(hsl.h.toFixed(3)));
+
+ parentDiv.appendChild(spanElem);
+ if (i % 21 === 20) {
+ parentDiv.appendChild(document.createElement('br'));
+ }
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/task.html b/chromium/third_party/catapult/tracing/tracing/base/task.html
new file mode 100644
index 00000000000..60ff686e898
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/task.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/timing.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ const Timing = tr.b.Timing;
+ /**
+ * A task is a combination of a run callback, a set of subtasks, and an after
+ * task.
+ *
+ * When executed, a task does the following things:
+ * 1. Runs its callback
+ * 2. Runs its subtasks
+ * 3. Runs its after callback.
+ *
+ * The list of subtasks and after task can be mutated inside step #1 but as
+ * soon as the task's callback returns, the subtask list and after task is
+ * fixed and cannot be changed again.
+ *
+ * Use task.after().after().after() to describe the toplevel passes that make
+ * up your computation. Then, use subTasks to add detail to each subtask as it
+ * runs. For example:
+ * var pieces = [];
+ * taskA = new Task(function() { pieces = getPieces(); });
+ * taskA.after(function(taskA) {
+ * pieces.forEach(function(piece) {
+ * taskA.subTask(function(taskB) { piece.process(); }, this);
+ * });
+ * });
+ *
+ * @constructor
+ */
+ function Task(runCb, thisArg) {
+ if (runCb !== undefined && thisArg === undefined &&
+ runCb.prototype !== undefined) {
+ throw new Error('Almost certainly you meant to pass a bound callback ' +
+ 'or thisArg.');
+ }
+ this.runCb_ = runCb;
+ this.thisArg_ = thisArg;
+ this.afterTask_ = undefined;
+ this.subTasks_ = [];
+ this.updatesUi_ = false;
+ }
+
+ Task.prototype = {
+ get name() {
+ return this.runCb_.name;
+ },
+
+ /** Sets a hint for whether or not this task updates the UI. */
+ set updatesUi(value) {
+ this.updatesUi_ = value;
+ },
+
+ /*
+ * See constructor documentation on semantics of subtasks.
+ */
+ subTask(cb, thisArg) {
+ if (cb instanceof Task) {
+ this.subTasks_.push(cb);
+ } else {
+ this.subTasks_.push(new Task(cb, thisArg));
+ }
+ return this.subTasks_[this.subTasks_.length - 1];
+ },
+
+ /**
+ * Runs the current task and returns the task that should be executed next.
+ */
+ run() {
+ if (this.runCb_ !== undefined) this.runCb_.call(this.thisArg_, this);
+ const subTasks = this.subTasks_;
+ this.subTasks_ = undefined; // Prevent more subTasks from being posted.
+
+ if (!subTasks.length) return this.afterTask_;
+
+ // If there are subtasks, then we want to execute all the subtasks and
+ // then this task's afterTask. To make this happen, we update the
+ // afterTask of all the subtasks so the point upward to each other, e.g.
+ // subTask[0].afterTask to subTask[1] and so on. Then, the last subTask's
+ // afterTask points at this task's afterTask.
+ for (let i = 1; i < subTasks.length; i++) {
+ subTasks[i - 1].afterTask_ = subTasks[i];
+ }
+ subTasks[subTasks.length - 1].afterTask_ = this.afterTask_;
+ return subTasks[0];
+ },
+
+ /*
+ * See constructor documentation on semantics of after tasks.
+ */
+ after(cb, thisArg) {
+ if (this.afterTask_) {
+ throw new Error('Has an after task already');
+ }
+ if (cb instanceof Task) {
+ this.afterTask_ = cb;
+ } else {
+ this.afterTask_ = new Task(cb, thisArg);
+ }
+ return this.afterTask_;
+ },
+
+ /*
+ * Adds a task after the chain of tasks.
+ */
+ enqueue(cb, thisArg) {
+ if (!this.afterTask_) return this.after(cb, thisArg);
+ return this.afterTask_.enqueue(cb, thisArg);
+ }
+ };
+
+ Task.RunSynchronously = function(task) {
+ let curTask = task;
+ while (curTask) {
+ curTask = curTask.run();
+ }
+ };
+
+ /**
+ * Runs a task using raf.requestIdleCallback, returning
+ * a promise for its completion.
+ */
+ Task.RunWhenIdle = function(task) {
+ return new Promise(function(resolve, reject) {
+ let curTask = task;
+ function runAnother() {
+ try {
+ curTask = curTask.run();
+ } catch (e) {
+ reject(e);
+ return;
+ }
+
+ if (curTask) {
+ if (curTask.updatesUi_) {
+ tr.b.requestAnimationFrameInThisFrameIfPossible(runAnother);
+ } else {
+ tr.b.requestIdleCallback(runAnother);
+ }
+ return;
+ }
+
+ resolve();
+ }
+ tr.b.requestIdleCallback(runAnother);
+ });
+ };
+
+ return {
+ Task,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/task_test.html b/chromium/third_party/catapult/tracing/tracing/base/task_test.html
new file mode 100644
index 00000000000..7f32ccf30dc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/task_test.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/task.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Task = tr.b.Task;
+
+ test('basicAllStepsPass', function() {
+ const results = [];
+
+ const startingTask = new Task(function(task) {
+ results.push('a');
+ task.subTask(function() {
+ results.push('a/1');
+ }, this);
+ task.subTask(function() {
+ results.push('a/2');
+ }, this);
+ }, this);
+ startingTask.after(function() {
+ results.push('b');
+ }, this).after(function() {
+ results.push('c');
+ }, this);
+
+ Task.RunSynchronously(startingTask);
+ assert.deepEqual(results, ['a', 'a/1', 'a/2', 'b', 'c']);
+ });
+
+ test('basicAllStepsPassAsync', function() {
+ const results = [];
+
+ const startingTask = new Task(function(task) {
+ results.push('a');
+ task.subTask(function() {
+ results.push('a/1');
+ }, this);
+ task.subTask(function() {
+ results.push('a/2');
+ }, this);
+ }, this);
+ startingTask.after(function() {
+ results.push('b');
+ }, this).after(function() {
+ results.push('c');
+ }, this);
+
+ const promise = Task.RunWhenIdle(startingTask);
+ promise.then(function() {
+ assert.deepEqual(results, ['a', 'a/1', 'a/2', 'b', 'c']);
+ });
+ return promise;
+ });
+
+ test('taskThatThrowsShouldRejectItsPromise', function() {
+ const startingTask = new Task(function(task) {
+ throw new Error(
+ 'IGNORE. This is an expected error to test error handling.');
+ }, this);
+
+ const taskPromise = Task.RunWhenIdle(startingTask);
+
+ return new Promise(function(resolve, reject) {
+ taskPromise.then(function() {
+ reject(new Error('Should have thrown'));
+ }, function(err) {
+ resolve();
+ });
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/time_display_modes.html b/chromium/third_party/catapult/tracing/tracing/base/time_display_modes.html
new file mode 100644
index 00000000000..09b34030745
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/time_display_modes.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit_scale.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Time currentDisplayUnit
+ */
+tr.exportTo('tr.b', function() {
+ const msDisplayMode = {
+ scale: 1e-3,
+ suffix: 'ms',
+ // Compares a < b with adjustments to precision errors.
+ roundedLess(a, b) {
+ return Math.round(a * 1000) < Math.round(b * 1000);
+ },
+ formatSpec: {
+ unitScale: [tr.b.UnitScale.TIME.MILLI_SEC],
+ minimumFractionDigits: 3,
+ }
+ };
+
+ const nsDisplayMode = {
+ scale: 1e-9,
+ suffix: 'ns',
+ // Compares a < b with adjustments to precision errors.
+ roundedLess(a, b) {
+ return Math.round(a * 1000000) < Math.round(b * 1000000);
+ },
+ formatSpec: {
+ unitScale: [tr.b.UnitScale.TIME.NANO_SEC],
+ maximumFractionDigits: 0
+ }
+ };
+
+ const TimeDisplayModes = {
+ ns: nsDisplayMode,
+ ms: msDisplayMode
+ };
+
+ return {
+ TimeDisplayModes,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/timing.html b/chromium/third_party/catapult/tracing/tracing/base/timing.html
new file mode 100644
index 00000000000..501abf96856
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/timing.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.b', function() {
+ class Mark {
+ constructor(groupName, functionName, opt_timestamp) {
+ if (tr.isHeadless) return;
+
+ this.groupName_ = groupName;
+ this.functionName_ = functionName;
+ const guid = tr.b.GUID.allocateSimple();
+ this.measureName_ = `${groupName} ${functionName}`;
+ if (opt_timestamp) {
+ this.startMark_ = {startTime: opt_timestamp};
+ } else {
+ this.startMarkName_ = `${this.measureName} ${guid} start`;
+ }
+ this.endMark_ = undefined;
+ this.endMarkName_ = `${this.measureName} ${guid} end`;
+
+ window.performance.mark(this.startMarkName_);
+ }
+
+ get groupName() {
+ return this.groupName_;
+ }
+
+ get functionName() {
+ return this.functionName_;
+ }
+
+ get measureName() {
+ return this.measureName_;
+ }
+
+ get startMark() {
+ return this.startMark_ || tr.b.getOnlyElement(
+ window.performance.getEntriesByName(this.startMarkName_));
+ }
+
+ get endMark() {
+ return this.endMark_ || tr.b.getOnlyElement(
+ window.performance.getEntriesByName(this.endMarkName_));
+ }
+
+ get durationMs() {
+ // There may be many measures named `this.measureName`, but the start and
+ // end mark names contain a GUID so they are unique.
+ return this.endMark.startTime - this.startMark.startTime;
+ }
+
+ end(opt_timestamp) {
+ if (tr.isHeadless) return;
+
+ if (opt_timestamp) {
+ this.endMark_ = {startTime: opt_timestamp};
+ } else {
+ window.performance.mark(this.endMarkName_);
+ }
+
+ if (!this.startMark_ && !this.endMark_) {
+ window.performance.measure(
+ this.measureName_, this.startMarkName_, this.endMarkName_);
+ } else if (Timing.logVoidMarks && !(window.ga instanceof Function)) {
+ // eslint-disable-next-line no-console
+ console.log('void mark',
+ this.groupName, this.functionName, this.durationMs);
+ }
+
+ if (!(window.ga instanceof Function)) return;
+ // Google Analytics
+ ga('send', {
+ hitType: 'event',
+ eventCategory: this.groupName,
+ eventAction: this.functionName,
+ eventValue: this.durationMs,
+ });
+ }
+ }
+
+ class Timing {
+ static mark(groupName, functionName, opt_timestamp) {
+ return new Mark(groupName, functionName, opt_timestamp);
+ }
+
+ static instant(groupName, functionName, opt_value) {
+ const valueString = opt_value === undefined ? '' : ' ' + opt_value;
+
+ /* eslint-disable no-console */
+ if (console && console.timeStamp) {
+ console.timeStamp(`${groupName} ${functionName}${valueString}`);
+ }
+ /* eslint-enable no-console */
+
+ // Google Analytics
+ if (window && window.ga instanceof Function) {
+ ga('send', {
+ hitType: 'event',
+ eventCategory: groupName,
+ eventAction: functionName,
+ eventValue: opt_value,
+ });
+ }
+ }
+
+ static getCurrentTimeMs() {
+ try {
+ return performance.now();
+ } catch (error) {}
+ return 0;
+ }
+ }
+
+ Timing.logVoidMarks = false;
+
+ return {
+ Timing,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/timing_test.html b/chromium/third_party/catapult/tracing/tracing/base/timing_test.html
new file mode 100644
index 00000000000..82cb798af66
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/timing_test.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/timing.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ test('mark', function() {
+ if (tr.isHeadless) return;
+
+ const markedTime = tr.b.Timing.mark('timing_test', 'mark');
+ markedTime.end();
+ const result = window.performance.getEntriesByName('timing_test mark');
+ const duration = parseFloat(result[0].duration);
+ assert.isTrue(duration >= 0.0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/trace_stream.html b/chromium/third_party/catapult/tracing/tracing/base/trace_stream.html
new file mode 100644
index 00000000000..3d4452f1b10
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/trace_stream.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ /**
+ * A TraceStream is a data structure holding trace data that supports
+ * sequentially reading data, efficiently. It also supports rewinding to the
+ * beginning of the trace data and building a sub-stream; but, the latter two
+ * operations do not have to be very efficient. For example, it is OK that an
+ * implementation sends a new XHR to get the trace data again when rewinding
+ * or creating a sub-stream from a large stream that does not fit in memory.
+ */
+ class TraceStream {
+ static get HEADER_SIZE() {
+ return Math.pow(2, 10);
+ }
+
+ static get CHUNK_SIZE() {
+ return Math.pow(2, 20);
+ }
+
+ get isBinary() {
+ throw new Error('Not implemented');
+ }
+
+ /**
+ * @returns {boolean} true if there is data remaining in the stream to read,
+ * without rewinding.
+ */
+ get hasData() {
+ throw new Error('Not implemented');
+ }
+
+ /**
+ * @returns {string} The first chunk of the stream. The header size is
+ * either given in the constructor or the default 1KB is used.
+ */
+ get header() {
+ throw new Error('Not implemented');
+ }
+
+ /**
+ * Reads until a given character, including the given character.
+ *
+ * @param {!string} delim A string of size exactly one.
+ *
+ * @returns {!string} The data until the delimiter as a string. If the
+ * delimiter is not found, all of the remaining data is returned.
+ */
+ readUntilDelimiter(delim) {
+ throw new Error('Not implemented');
+ }
+
+ /**
+ * Reads a specific number of bytes from the stream.
+ *
+ * @param {number=} opt_size The maximum number of bytes to be read from the
+ * stream. If unspecified, at most 1MB will be read.
+ *
+ * @returns {!string} A string of size opt_size, unless there is not enough
+ * data in the stream in which the string will be smaller.
+ */
+ readNumBytes(opt_size) {
+ throw new Error('Not implemented');
+ }
+
+ rewind() {
+ throw new Error('Not implemented');
+ }
+
+ /**
+ * Returns a new stream, created from a subset of this stream. This is
+ * needed to support importing subtraces. For example, when the importer
+ * encounters a trace event stream that has a BattOr subtrace in it, it will
+ * create a new stream for the BattOr subtrace and use the proper importer.
+ *
+ * @param {!number} startOffset The start offset of the new stream.
+ * @param {number=} opt_endOffset The end offset of the new stream
+ * (exclusive). If unspecified, the end offset of the current stream is
+ * used.
+ * @param {number=} opt_headerSize The header size of the new stream. If
+ * unspecified, the header size is assumed to be 1KB.
+ *
+ * @returns {!TraceStream} The new stream. The cursor of the new stream will
+ * be at the beginning.
+ */
+ substream(offset, opt_length, opt_headerSize) {
+ throw new Error('Not implemented');
+ }
+ }
+
+ return {
+ TraceStream,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unit.html b/chromium/third_party/catapult/tracing/tracing/base/unit.html
new file mode 100644
index 00000000000..90a5eba869b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unit.html
@@ -0,0 +1,531 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/time_display_modes.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ const TimeDisplayModes = tr.b.TimeDisplayModes;
+
+ const PLUS_MINUS_SIGN = String.fromCharCode(177);
+
+ const CACHED_FORMATTERS = {};
+ function getNumberFormatter(minSpec, maxSpec, minCtx, maxCtx) {
+ const key = minSpec + '-' + maxSpec + '-' + minCtx + '-' + maxCtx;
+ let formatter = CACHED_FORMATTERS[key];
+ if (formatter === undefined) {
+ let minimumFractionDigits = minCtx !== undefined ? minCtx : minSpec;
+ let maximumFractionDigits = maxCtx !== undefined ? maxCtx : maxSpec;
+
+ // If the context overrides only one of the two |*FractionDigits|
+ // properties and the other one is provided by the unit, we might need to
+ // shift the other property so that
+ // |minimumFractionDigits| <= |maximumFractionDigits|.
+ if (minimumFractionDigits > maximumFractionDigits) {
+ if (minCtx !== undefined && maxCtx === undefined) {
+ // Only minimumFractionDigits was overriden by context.
+ maximumFractionDigits = minimumFractionDigits;
+ } else if (minCtx === undefined && maxCtx !== undefined) {
+ // Only maximumFractionDigits was overriden by context.
+ minimumFractionDigits = maximumFractionDigits;
+ }
+ }
+
+ formatter = new Intl.NumberFormat(undefined, {
+ minimumFractionDigits,
+ maximumFractionDigits,
+ });
+
+ CACHED_FORMATTERS[key] = formatter;
+ }
+ return formatter;
+ }
+
+ function max(a, b) {
+ if (a === undefined) return b;
+ if (b === undefined) return a;
+ return a.scale > b.scale ? a : b;
+ }
+
+ /** @enum */
+ const ImprovementDirection = {
+ DONT_CARE: 0,
+ BIGGER_IS_BETTER: 1,
+ SMALLER_IS_BETTER: 2
+ };
+
+ /** @constructor */
+ function Unit(unitName, jsonName, scaleBaseUnit, isDelta,
+ improvementDirection, formatSpec) {
+ this.unitName = unitName;
+ this.jsonName = jsonName;
+ this.scaleBaseUnit = scaleBaseUnit;
+ this.isDelta = isDelta;
+ this.improvementDirection = improvementDirection;
+ this.formatSpec_ = formatSpec;
+
+ // Example: powerInWattsDelta_biggerIsBetter -> powerInWatts.
+ this.baseUnit = undefined;
+
+ // Example: energyInJoules_smallerIsBetter ->
+ // energyInJoulesDelta_smallerIsBetter.
+ this.correspondingDeltaUnit = undefined;
+ }
+
+ Unit.prototype = {
+ asJSON() {
+ return this.jsonName;
+ },
+
+ /**
+ * Remove insignificant digits from a number so that it consumes less disk
+ * space when serialized.
+ *
+ * @param {number} value
+ * @return {number}
+ */
+ truncate(value) {
+ if (typeof value !== 'number') return value;
+ if (0 === (value % 1)) return value;
+
+ if (typeof this.formatSpec_ !== 'function' &&
+ (!this.formatSpec_.unitScale ||
+ ((this.formatSpec_.unitScale.length === 1) &&
+ (this.formatSpec_.unitScale[0].value === 1)))) {
+ const digits = this.formatSpec_.maximumFractionDigits ||
+ this.formatSpec_.minimumFractionDigits;
+ return tr.b.math.truncate(value, digits + 1);
+ }
+
+ // If formatSpec is a function or uses a unitScale, then its formatting is
+ // unpredictable.
+ // Binary search to find the smallest number of decimal digits that
+ // preserves the correct formatted value.
+
+ const formatted = this.format(value);
+ let test = Math.round(value);
+ if (formatted === this.format(test)) return test;
+
+ let lo = 1;
+ let hi = 16;
+ while (lo < hi - 1) {
+ const digits = parseInt((lo + hi) / 2);
+ test = tr.b.math.truncate(value, digits);
+ if (formatted === this.format(test)) {
+ hi = digits;
+ } else {
+ lo = digits;
+ }
+ }
+
+ test = tr.b.math.truncate(value, lo);
+ if (formatted === this.format(test)) return test;
+
+ return tr.b.math.truncate(value, hi);
+ },
+
+ getUnitScale_(opt_context) {
+ let formatSpec = this.formatSpec_;
+ let formatSpecWasFunction = false;
+ if (typeof formatSpec === 'function') {
+ formatSpecWasFunction = true;
+ formatSpec = formatSpec();
+ }
+ const context = opt_context || {};
+
+ let scale = undefined;
+ if (context.unitScale) {
+ scale = context.unitScale;
+ } else if (context.unitPrefix) {
+ // TODO(aiolos): Switch all calls to format to use UnitScales instead
+ // of UnitPrefixScales. UnitPrefixeScales use in Unit is deprecated.
+ const symbol = formatSpec.baseSymbol ?
+ formatSpec.baseSymbol : this.scaleBaseUnit.baseSymbol;
+ scale = tr.b.UnitScale.defineUnitScaleFromPrefixScale(
+ symbol, symbol, [context.unitPrefix]).AUTO;
+ } else {
+ scale = formatSpec.unitScale;
+ if (!scale) {
+ // Unit has no conversion value(s). Ex: Watts, count.
+ scale = [{
+ value: 1,
+ symbol: formatSpec.baseSymbol || '',
+ baseSymbol: formatSpec.baseSymbol || ''
+ }];
+ if (!formatSpecWasFunction) formatSpec.unitScale = scale;
+ }
+ }
+ if (!(scale instanceof Array)) {
+ throw new Error('Unit has a malformed unit scale.');
+ }
+ return scale;
+ },
+
+ get unitString() {
+ const scale = this.getUnitScale_();
+ if (!scale) {
+ throw new Error(
+ 'A UnitScale could not be found for Unit ' + this.unitName);
+ }
+ return scale[0].symbol;
+ },
+
+ /**
+ * Returns a human readable string representation of the value passed.
+ *
+ * Example: .00023 formatted using the timeInMsAutoFormat Unit would return
+ * '230 ns' since the base unit scale is ms.
+ *
+ * @param {number} value - The value to be formatted.
+ * @param {Object} [opt_context] - Optional formatting parameters.
+ * @param {!tr.b.UnitScale=} [opt_context.unitScale] - A UnitScale to use
+ * while formatting the value instead of this Unit's UnitScale.
+ * @param {!tr.b.UnitPrefix=} [opt_context.unitPrefix] - A UnitPrefix that
+ * the value should be formatted into.
+ * @param {number} [opt_context.deltaValue] - Format the value based on
+ * this delta between it and another number instead of the actual value.
+ */
+ format(value, opt_context) {
+ let signString = '';
+ if (value < 0) {
+ signString = '-';
+ value = -value; // Treat positive and negative values symmetrically.
+ } else if (this.isDelta) {
+ signString = value === 0 ? PLUS_MINUS_SIGN : '+';
+ }
+
+ const context = opt_context || {};
+ const scale = this.getUnitScale_(context);
+ let deltaValue = context.deltaValue === undefined ? value :
+ context.deltaValue;
+ deltaValue = Math.abs(deltaValue) * this.scaleBaseUnit.value;
+ if (deltaValue === 0) {
+ // In this special case we need to format to unit the same, if the value
+ // was 1. It is required for example to prevent 0 nJ instead of 0 J.
+ deltaValue = 1;
+ }
+ let i = 0;
+ while (i < scale.length - 1 &&
+ deltaValue / scale[i + 1].value >= 1) {
+ i++;
+ }
+ const selectedSubUnit = scale[i];
+
+ let formatSpec = this.formatSpec_;
+ if (typeof formatSpec === 'function') formatSpec = formatSpec();
+ let unitString = '';
+ if (selectedSubUnit.symbol) {
+ if (!formatSpec.avoidSpacePrecedingUnit) unitString = ' ';
+ unitString += selectedSubUnit.symbol;
+ }
+
+ value = tr.b.convertUnit(value, this.scaleBaseUnit, selectedSubUnit);
+ const numberString = getNumberFormatter(
+ formatSpec.minimumFractionDigits,
+ formatSpec.maximumFractionDigits,
+ context.minimumFractionDigits,
+ context.maximumFractionDigits).format(value);
+
+ return signString + numberString + unitString;
+ }
+ };
+
+ Unit.reset = function() {
+ Unit.currentTimeDisplayMode = TimeDisplayModes.ms;
+ };
+
+ Unit.timestampFromUs = function(us) {
+ return tr.b.convertUnit(us, tr.b.UnitPrefixScale.METRIC.MICRO,
+ tr.b.UnitPrefixScale.METRIC.MILLI);
+ };
+
+ Object.defineProperty(Unit, 'currentTimeDisplayMode', {
+ get() {
+ return Unit.currentTimeDisplayMode_;
+ },
+ // Use tr-v-ui-preferred-display-unit element instead of directly setting.
+ set(value) {
+ if (Unit.currentTimeDisplayMode_ === value) return;
+
+ Unit.currentTimeDisplayMode_ = value;
+ Unit.dispatchEvent(new tr.b.Event('display-mode-changed'));
+ }
+ });
+
+ Unit.didPreferredTimeDisplayUnitChange = function() {
+ let largest = undefined;
+ // TODO(aiolos): base should not depend on ui. Move the functionality of
+ // searching for preferred-display-unit out of Unit.
+ // https://github.com/catapult-project/catapult/issues/3092
+ const els = tr.ui.b.findDeepElementsMatching(document.body,
+ 'tr-v-ui-preferred-display-unit');
+ els.forEach(function(el) {
+ largest = max(largest, el.preferredTimeDisplayMode);
+ });
+
+ Unit.currentTimeDisplayMode = largest === undefined ?
+ TimeDisplayModes.ms : largest;
+ };
+
+ Unit.byName = {};
+ Unit.byJSONName = {};
+
+ Unit.fromJSON = function(object) {
+ const u = Unit.byJSONName[object];
+ if (u) {
+ return u;
+ }
+ throw new Error(`Unrecognized unit "${object}"`);
+ };
+
+ /**
+ * Define all combinations of a unit with isDelta and improvementDirection
+ * flags. For example, the following code:
+ *
+ * Unit.define({
+ * baseUnitName: 'powerInWatts'
+ * baseJsonName: 'W'
+ * formatSpec: {
+ * // Specification of how the unit should be formatted (unit symbol,
+ * // unit prefix, fraction digits, etc), or a function returning such
+ * // a specification.
+ * }
+ * });
+ *
+ * generates the following six units (JSON names shown in parentheses):
+ *
+ * Unit.byName.powerInWatts (W)
+ * Unit.byName.powerInWatts_smallerIsBetter (W_smallerIsBetter)
+ * Unit.byName.powerInWatts_biggerIsBetter (W_biggerIsBetter)
+ * Unit.byName.powerInWattsDelta (WDelta)
+ * Unit.byName.powerInWattsDelta_smallerIsBetter (WDelta_smallerIsBetter)
+ * Unit.byName.powerInWattsDelta_biggerIsBetter (WDelta_biggerIsBetter)
+ *
+ * with the appropriate flags and formatting code (including +/- prefixes
+ * for deltas).
+ */
+ Unit.define = function(params) {
+ const definedUnits = [];
+
+ for (const improvementDirection of Object.values(ImprovementDirection)) {
+ const regularUnit =
+ Unit.defineUnitVariant_(params, false, improvementDirection);
+ const deltaUnit =
+ Unit.defineUnitVariant_(params, true, improvementDirection);
+
+ regularUnit.correspondingDeltaUnit = deltaUnit;
+ deltaUnit.correspondingDeltaUnit = deltaUnit;
+ definedUnits.push(regularUnit, deltaUnit);
+ }
+
+ const baseUnit = Unit.byName[params.baseUnitName];
+ definedUnits.forEach(u => u.baseUnit = baseUnit);
+ };
+
+ Unit.nameSuffixForImprovementDirection = function(improvementDirection) {
+ switch (improvementDirection) {
+ case ImprovementDirection.DONT_CARE:
+ return '';
+ case ImprovementDirection.BIGGER_IS_BETTER:
+ return '_biggerIsBetter';
+ case ImprovementDirection.SMALLER_IS_BETTER:
+ return '_smallerIsBetter';
+ default:
+ throw new Error(
+ 'Unknown improvement direction: ' + improvementDirection);
+ }
+ };
+
+ Unit.defineUnitVariant_ = function(params, isDelta, improvementDirection) {
+ let nameSuffix = isDelta ? 'Delta' : '';
+ nameSuffix += Unit.nameSuffixForImprovementDirection(improvementDirection);
+
+ const unitName = params.baseUnitName + nameSuffix;
+ const jsonName = params.baseJsonName + nameSuffix;
+ if (Unit.byName[unitName] !== undefined) {
+ throw new Error('Unit \'' + unitName + '\' already exists');
+ }
+ if (Unit.byJSONName[jsonName] !== undefined) {
+ throw new Error('JSON unit \'' + jsonName + '\' alread exists');
+ }
+
+ let scaleBaseUnit = params.scaleBaseUnit;
+ if (!scaleBaseUnit) {
+ let formatSpec = params.formatSpec;
+ if (typeof formatSpec === 'function') formatSpec = formatSpec();
+ const baseSymbol = formatSpec.unitScale ?
+ formatSpec.unitScale[0].baseSymbol : (formatSpec.baseSymbol || '');
+ scaleBaseUnit = { value: 1, symbol: baseSymbol, baseSymbol };
+ }
+ const unit = new Unit(unitName, jsonName, scaleBaseUnit,
+ isDelta, improvementDirection, params.formatSpec);
+ Unit.byName[unitName] = unit;
+ Unit.byJSONName[jsonName] = unit;
+
+ return unit;
+ };
+
+ tr.b.EventTarget.decorate(Unit);
+ Unit.reset();
+
+ // Known display units follow.
+ //////////////////////////////////////////////////////////////////////////////
+
+ Unit.define({
+ baseUnitName: 'timeInMsAutoFormat',
+ baseJsonName: 'msBestFitFormat',
+ scaleBaseUnit: tr.b.UnitScale.TIME.MILLI_SEC,
+ formatSpec: {
+ unitScale: tr.b.UnitScale.TIME.AUTO,
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 3
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'timeDurationInMs',
+ baseJsonName: 'ms',
+ scaleBaseUnit: tr.b.UnitScale.TIME.MILLI_SEC,
+ formatSpec() {
+ return Unit.currentTimeDisplayMode_.formatSpec;
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'timeStampInMs',
+ baseJsonName: 'tsMs',
+ scaleBaseUnit: tr.b.UnitScale.TIME.MILLI_SEC,
+ formatSpec() {
+ return Unit.currentTimeDisplayMode_.formatSpec;
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'normalizedPercentage',
+ baseJsonName: 'n%',
+ formatSpec: {
+ unitScale: [{value: 0.01, symbol: '%'}],
+ avoidSpacePrecedingUnit: true,
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'sizeInBytes',
+ baseJsonName: 'sizeInBytes',
+ formatSpec: {
+ unitScale: tr.b.UnitScale.MEMORY.AUTO,
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'bandwidthInBytesPerSecond',
+ baseJsonName: 'bytesPerSecond',
+ formatSpec: {
+ unitScale: tr.b.UnitScale.BANDWIDTH_BYTES.AUTO,
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'energyInJoules',
+ baseJsonName: 'J',
+ formatSpec: {
+ unitScale: tr.b.UnitScale.defineUnitScaleFromPrefixScale(
+ 'J', 'JOULE', tr.b.UnitPrefixScale.METRIC, 'JOULE').AUTO,
+ minimumFractionDigits: 3
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'powerInWatts',
+ baseJsonName: 'W',
+ formatSpec: {
+ unitScale: tr.b.UnitScale.defineUnitScaleFromPrefixScale(
+ 'W', 'WATT', tr.b.UnitPrefixScale.METRIC, 'WATT').AUTO,
+ minimumFractionDigits: 3
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'electricCurrentInAmperes',
+ baseJsonName: 'A',
+ formatSpec: {
+ baseSymbol: 'A',
+ unitScale: tr.b.UnitScale.defineUnitScaleFromPrefixScale(
+ 'A', 'AMPERE', tr.b.UnitPrefixScale.METRIC, 'AMPERE').AUTO,
+ minimumFractionDigits: 3
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'electricPotentialInVolts',
+ baseJsonName: 'V',
+ formatSpec: {
+ baseSymbol: 'V',
+ unitScale: tr.b.UnitScale.defineUnitScaleFromPrefixScale(
+ 'V', 'VOLT', tr.b.UnitPrefixScale.METRIC, 'VOLT').AUTO,
+ minimumFractionDigits: 3
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'frequencyInHertz',
+ baseJsonName: 'Hz',
+ formatSpec: {
+ baseSymbol: 'Hz',
+ unitScale: tr.b.UnitScale.defineUnitScaleFromPrefixScale(
+ 'Hz', 'HERTZ', tr.b.UnitPrefixScale.METRIC, 'HERTZ').AUTO,
+ minimumFractionDigits: 3
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'unitlessNumber',
+ baseJsonName: 'unitless',
+ formatSpec: {
+ minimumFractionDigits: 3,
+ maximumFractionDigits: 3
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'count',
+ baseJsonName: 'count',
+ formatSpec: {
+ minimumFractionDigits: 0,
+ maximumFractionDigits: 0
+ }
+ });
+
+ Unit.define({
+ baseUnitName: 'sigma',
+ baseJsonName: 'sigma',
+ formatSpec: {
+ baseSymbol: String.fromCharCode(963),
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1
+ }
+ });
+
+ return {
+ ImprovementDirection,
+ Unit,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unit_scale.html b/chromium/third_party/catapult/tracing/tracing/base/unit_scale.html
new file mode 100644
index 00000000000..4350a5575bf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unit_scale.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ const GREEK_SMALL_LETTER_MU = String.fromCharCode(956);
+
+ const SECONDS_IN_A_MINUTE = 60;
+ const SECONDS_IN_AN_HOUR = SECONDS_IN_A_MINUTE * 60;
+ const SECONDS_IN_A_DAY = SECONDS_IN_AN_HOUR * 24;
+ const SECONDS_IN_A_WEEK = SECONDS_IN_A_DAY * 7;
+ const SECONDS_IN_A_YEAR = SECONDS_IN_A_DAY * 365.2422;
+ const SECONDS_IN_A_MONTH = SECONDS_IN_A_YEAR / 12;
+
+ const UnitPrefixScale = {};
+ const UnitScale = {};
+
+ function defineUnitPrefixScale(name, prefixes) {
+ if (UnitPrefixScale[name] !== undefined) {
+ throw new Error('Unit prefix scale \'' + name + '\' already exists');
+ }
+ if (prefixes.AUTO !== undefined) {
+ throw new Error('The \'AUTO\' unit prefix is not supported for unit' +
+ 'prefix scales and cannot be added to scale \'' + name + '\'');
+ }
+
+ UnitPrefixScale[name] = prefixes;
+ }
+
+ UnitScale.defineUnitScale = function(name, unitScale) {
+ if (UnitScale[name] !== undefined) {
+ throw new Error('Unit scale \'' + name + '\' already exists');
+ }
+ if (unitScale.AUTO !== undefined) {
+ throw new Error('\'AUTO\' unit scale will be added automatically ' +
+ 'for unit scale \'' + name + '\'');
+ }
+
+ // The 'AUTO' unit scale is used in auto formatting Units. In units using
+ // the 'BINARY' UnitScale the absolute formatted value closest to the
+ // [1, 1024) interval as possible is used. So 1023 and 1024 bytes are
+ // displayed as "1,023.0 B" and "1.0 KiB", respectively.
+ unitScale.AUTO = Object.values(unitScale);
+ unitScale.AUTO.sort((a, b) => a.value - b.value);
+
+ if (name) UnitScale[name] = unitScale;
+ return unitScale;
+ };
+
+ function definePrefixScaleFromUnitScale(prefixName, unitScale) {
+ if (!unitScale) {
+ throw new Error('Cannot create PrefixScale without a unit scale.');
+ }
+ const prefixScale = {};
+ for (const [curPrefix, curScale] of Object.entries(unitScale)) {
+ if (curPrefix === 'AUTO') {
+ continue;
+ }
+ if (curScale.symbol === undefined || !curScale.value) {
+ throw new Error(
+ `Cannot create PrefixScale from malformed unit ${curScale}.`);
+ }
+ prefixScale[curPrefix] = {
+ value: curScale.value,
+ symbol: curScale.symbol
+ };
+ }
+ return defineUnitPrefixScale(prefixName, prefixScale);
+ }
+
+ UnitScale.defineUnitScaleFromPrefixScale = function(
+ baseSymbol, baseName, prefixScale, opt_scaleName) {
+ if (baseSymbol === undefined) {
+ throw new Error('Cannot create UnitScale with undefined baseSymbol.');
+ }
+ if (!baseName) {
+ throw new Error('Cannot create UnitScale without a baseName.');
+ }
+ if (!prefixScale) {
+ throw new Error('Cannot create UnitScale without a prefix scale.');
+ }
+ const unitScale = {};
+ for (const curPrefix of Object.keys(prefixScale)) {
+ const curScale = prefixScale[curPrefix];
+ if (curScale.symbol === undefined || !curScale.value) {
+ throw new Error(
+ `Cannot convert PrefixScale with malformed prefix ${curScale}.`);
+ }
+ const name = curPrefix === 'NONE' ? baseName : `${curPrefix}_${baseName}`;
+ unitScale[name] = {
+ value: curScale.value,
+ symbol: curScale.symbol + baseSymbol,
+ baseSymbol
+ };
+ }
+ return UnitScale.defineUnitScale(opt_scaleName, unitScale);
+ };
+
+ /**
+ * Converts |value| from |fromScale| (e.g. kilo) to |toScale| (e.g. mega).
+ *
+ * Returns undefined if |value| is undefined.
+ * |fromScale| and |toScale| need not come from the same UnitScale or
+ * UnitPrefixScale. But if they are both UnitScales they must have matching
+ * or undefined baseSymbol's.
+ *
+ * @param {(undefined|number)} value
+ * @param {!object} fromScale
+ * @param {!object} toScale
+ * @return {(undefined|number)}
+ */
+ function convertUnit(value, fromScale, toScale) {
+ if (value === undefined) return undefined;
+ const fromScaleBase = fromScale.baseSymbol;
+ const toScaleBase = toScale.baseSymbol;
+ if (fromScaleBase !== undefined && toScaleBase !== undefined &&
+ fromScaleBase !== toScaleBase) {
+ throw new Error(
+ 'Cannot convert between units with different base symbols.');
+ }
+ return value * (fromScale.value / toScale.value);
+ }
+
+ // See https://en.wikipedia.org/wiki/Binary_prefix.
+ defineUnitPrefixScale('BINARY', {
+ NONE: { value: Math.pow(1024, 0), symbol: '' },
+ KIBI: { value: Math.pow(1024, 1), symbol: 'Ki' },
+ MEBI: { value: Math.pow(1024, 2), symbol: 'Mi' },
+ GIBI: { value: Math.pow(1024, 3), symbol: 'Gi' },
+ TEBI: { value: Math.pow(1024, 4), symbol: 'Ti' }
+ });
+
+ // See https://en.wikipedia.org/wiki/Metric_prefix.
+ defineUnitPrefixScale('METRIC', {
+ NANO: { value: 1e-9, symbol: 'n' },
+ MICRO: { value: 1e-6, symbol: GREEK_SMALL_LETTER_MU },
+ MILLI: { value: 1e-3, symbol: 'm' },
+ NONE: { value: 1, symbol: ''},
+ KILO: { value: 1e3, symbol: 'k'},
+ MEGA: { value: 1e6, symbol: 'M'},
+ GIGA: { value: 1e9, symbol: 'G'}
+ });
+
+ UnitScale.defineUnitScale('TIME', {
+ NANO_SEC: { value: 1e-9, symbol: 'ns', baseSymbol: 's'},
+ MICRO_SEC: { value: 1e-6, symbol: GREEK_SMALL_LETTER_MU + 's',
+ baseSymbol: 's'},
+ MILLI_SEC: { value: 1e-3, symbol: 'ms', baseSymbol: 's'},
+ SEC: { value: 1, symbol: 's', baseSymbol: 's'},
+ MINUTE: { value: SECONDS_IN_A_MINUTE, symbol: 'min', baseSymbol: 's'},
+ HOUR: { value: SECONDS_IN_AN_HOUR, symbol: 'hr', baseSymbol: 's'},
+ DAY: { value: SECONDS_IN_A_DAY, symbol: 'days', baseSymbol: 's'},
+ WEEK: { value: SECONDS_IN_A_WEEK, symbol: 'weeks', baseSymbol: 's'},
+ MONTH: { value: SECONDS_IN_A_MONTH, symbol: 'months', baseSymbol: 's'},
+ YEAR: { value: SECONDS_IN_A_YEAR, symbol: 'years', baseSymbol: 's'}
+ });
+
+ UnitScale.defineUnitScaleFromPrefixScale(
+ 'B', 'BYTE', UnitPrefixScale.BINARY, 'MEMORY');
+
+ definePrefixScaleFromUnitScale('DATA_SIZE', UnitScale.MEMORY);
+
+ UnitScale.defineUnitScaleFromPrefixScale(
+ '/s', 'SECONDS', UnitPrefixScale.DATA_SIZE, 'BANDWIDTH_BYTES');
+
+ return {
+ UnitPrefixScale,
+ UnitScale,
+ convertUnit,
+ GREEK_SMALL_LETTER_MU,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unit_scale_test.html b/chromium/third_party/catapult/tracing/tracing/base/unit_scale_test.html
new file mode 100644
index 00000000000..cfd20f52811
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unit_scale_test.html
@@ -0,0 +1,170 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const UnitPrefixScale = tr.b.UnitPrefixScale;
+ const UnitScale = tr.b.UnitScale;
+
+ test('convertUnit', function() {
+ // UnitPrefixScale to UnitScale
+ assert.strictEqual(tr.b.convertUnit(
+ 43.53, UnitPrefixScale.BINARY.MEBI, UnitScale.MEMORY.MEBI_BYTE),
+ 43.53);
+ assert.strictEqual(tr.b.convertUnit(
+ 43, UnitPrefixScale.BINARY.MEBI, UnitScale.MEMORY.BYTE), 45088768);
+ assert.strictEqual(tr.b.convertUnit(
+ -400, UnitPrefixScale.BINARY.NONE, UnitScale.MEMORY.KIBI_BYTE),
+ -0.390625);
+ assert.strictEqual(tr.b.convertUnit(
+ 43.53, UnitPrefixScale.METRIC.MILLI, UnitScale.TIME.MILLI_SEC),
+ 43.53);
+ assert.strictEqual(tr.b.convertUnit(
+ 50, UnitPrefixScale.METRIC.MILLI, UnitScale.TIME.SEC), 0.05);
+ assert.strictEqual(tr.b.convertUnit(
+ -400, UnitPrefixScale.METRIC.NONE, UnitScale.TIME.MICRO_SEC),
+ -400000000);
+
+ // UnitScale to UnitPrefixScale
+ assert.strictEqual(tr.b.convertUnit(
+ 43.53, UnitScale.MEMORY.MEBI_BYTE, UnitPrefixScale.BINARY.MEBI),
+ 43.53);
+ assert.strictEqual(tr.b.convertUnit(
+ 43, UnitScale.MEMORY.MEBI_BYTE, UnitPrefixScale.BINARY.NONE),
+ 45088768);
+ assert.strictEqual(tr.b.convertUnit(
+ -400, UnitScale.MEMORY.BYTE, UnitPrefixScale.BINARY.KIBI),
+ -0.390625);
+ assert.strictEqual(tr.b.convertUnit(
+ 43.53, UnitScale.TIME.MILLI_SEC, UnitPrefixScale.METRIC.MILLI),
+ 43.53);
+ assert.strictEqual(tr.b.convertUnit(
+ 50, UnitPrefixScale.METRIC.MILLI, UnitScale.TIME.SEC), 0.05);
+ assert.strictEqual(tr.b.convertUnit(
+ -400, UnitPrefixScale.METRIC.NONE, UnitScale.TIME.MICRO_SEC),
+ -400000000);
+
+ // UnitScale to UnitScale
+ assert.strictEqual(tr.b.convertUnit(
+ 43.53, UnitScale.MEMORY.MEBI_BYTE, UnitScale.MEMORY.MEBI_BYTE),
+ 43.53);
+ assert.strictEqual(tr.b.convertUnit(
+ 43, UnitScale.MEMORY.MEBI_BYTE, UnitScale.MEMORY.BYTE), 45088768);
+ assert.strictEqual(tr.b.convertUnit(
+ -400, UnitScale.MEMORY.BYTE, UnitScale.MEMORY.KIBI_BYTE),
+ -0.390625);
+ assert.strictEqual(tr.b.convertUnit(
+ 43.53, UnitScale.TIME.MILLI_SEC, UnitScale.TIME.MILLI_SEC), 43.53);
+ assert.strictEqual(tr.b.convertUnit(
+ 50, UnitScale.TIME.MILLI_SEC, UnitScale.TIME.SEC), 0.05);
+ assert.strictEqual(tr.b.convertUnit(
+ -400, UnitScale.TIME.SEC, UnitScale.TIME.MICRO_SEC), -400000000);
+ assert.closeTo(tr.b.convertUnit(
+ 12, UnitScale.TIME.YEAR, UnitScale.TIME.MONTH), 144, 1.e-8);
+
+ // UnitPrefixScale to UnitPrefixScale
+ assert.strictEqual(tr.b.convertUnit(
+ 43.53, UnitPrefixScale.BINARY.MEBI, UnitPrefixScale.BINARY.MEBI),
+ 43.53);
+ assert.strictEqual(tr.b.convertUnit(
+ 43, UnitPrefixScale.BINARY.MEBI, UnitPrefixScale.BINARY.NONE),
+ 45088768);
+ assert.strictEqual(tr.b.convertUnit(
+ -400, UnitPrefixScale.BINARY.NONE, UnitPrefixScale.BINARY.KIBI),
+ -0.390625);
+ assert.strictEqual(tr.b.convertUnit(
+ 43.53, UnitPrefixScale.METRIC.MILLI, UnitPrefixScale.METRIC.MILLI),
+ 43.53);
+ assert.strictEqual(tr.b.convertUnit(
+ 50, UnitPrefixScale.METRIC.MILLI, UnitPrefixScale.METRIC.NONE),
+ 0.05);
+ assert.strictEqual(tr.b.convertUnit(
+ -400, UnitPrefixScale.METRIC.NONE, UnitPrefixScale.METRIC.MICRO),
+ -400000000);
+ });
+
+ test('defineUnitScale', function() {
+ assert.strictEqual(UnitPrefixScale.PONY, undefined);
+ const ponyScale = {
+ SHORT_JUMPS: { value: 1e-3, symbol: 'SJ', baseSymbol: 'J'},
+ REGULAR_JUMPS: { value: 1, symbol: 'J', baseSymbol: 'J'},
+ LONG_JUMPS: {value: 1e3, symbol: 'LJ', baseSymbol: 'J'},
+ EPIC_JUMPS: {value: 1e6, symbol: 'EJ', baseSymbol: 'J'}
+ };
+ UnitScale.defineUnitScale('PONY', ponyScale);
+ assert.strictEqual(tr.b.convertUnit(
+ 32.1, UnitScale.PONY.REGULAR_JUMPS, UnitScale.PONY.SHORT_JUMPS),
+ 32100);
+ assert.strictEqual(tr.b.convertUnit(
+ -32, UnitScale.PONY.SHORT_JUMPS, UnitScale.PONY.REGULAR_JUMPS),
+ -0.032);
+ assert.strictEqual(tr.b.convertUnit(
+ 32.1, UnitScale.PONY.EPIC_JUMPS, UnitScale.PONY.LONG_JUMPS),
+ 32100);
+ assert.strictEqual(tr.b.convertUnit(
+ -34600000, UnitScale.PONY.SHORT_JUMPS, UnitScale.PONY.EPIC_JUMPS),
+ -0.0346);
+ });
+
+ test('defineUnitScaleFromPrefixScale', function() {
+ assert.strictEqual(UnitPrefixScale.BUNNY, undefined);
+ UnitScale.defineUnitScaleFromPrefixScale(
+ 'H', 'HOPS', UnitPrefixScale.METRIC, 'BUNNY');
+ assert.strictEqual(tr.b.convertUnit(
+ 32.1, UnitScale.BUNNY.HOPS, UnitScale.BUNNY.MILLI_HOPS),
+ 32100);
+ assert.strictEqual(tr.b.convertUnit(
+ -32, UnitScale.BUNNY.MILLI_HOPS, UnitScale.BUNNY.HOPS),
+ -0.032);
+ assert.strictEqual(tr.b.convertUnit(
+ 32.1, UnitScale.BUNNY.GIGA_HOPS, UnitScale.BUNNY.KILO_HOPS),
+ 32100000);
+ assert.strictEqual(tr.b.convertUnit(
+ -32, UnitScale.BUNNY.KILO_HOPS, UnitScale.BUNNY.MEGA_HOPS),
+ -0.032);
+ });
+
+ test('timeScale', function() {
+ assert.strictEqual(tr.b.convertUnit(
+ 123.45, UnitScale.TIME.NANO_SEC, UnitScale.TIME.MICRO_SEC), 0.12345);
+ assert.strictEqual(tr.b.convertUnit(
+ 123.45, UnitScale.TIME.MICRO_SEC, UnitScale.TIME.MILLI_SEC), 0.12345);
+ assert.strictEqual(tr.b.convertUnit(
+ 123.45, UnitScale.TIME.MILLI_SEC, UnitScale.TIME.SEC), 0.12345);
+ assert.strictEqual(tr.b.convertUnit(
+ 123.45, UnitScale.TIME.SEC, UnitScale.TIME.MINUTE), 2.0575);
+ assert.strictEqual(tr.b.convertUnit(
+ 123.45, UnitScale.TIME.MINUTE, UnitScale.TIME.HOUR), 2.0575);
+ assert.strictEqual(tr.b.convertUnit(
+ 123.48, UnitScale.TIME.HOUR, UnitScale.TIME.DAY), 5.145);
+ assert.strictEqual(tr.b.convertUnit(
+ 123.48, UnitScale.TIME.DAY, UnitScale.TIME.WEEK), 17.64);
+ assert.strictEqual(tr.b.convertUnit(
+ 123.48, UnitScale.TIME.WEEK, UnitScale.TIME.MONTH),
+ 28.3984709324388);
+ assert.closeTo(tr.b.convertUnit(
+ 123.48, UnitScale.TIME.MONTH, UnitScale.TIME.YEAR), 10.29,
+ 0.000001);
+ });
+
+ test('memoryScale', function() {
+ assert.strictEqual(tr.b.convertUnit(
+ 4608, UnitScale.MEMORY.BYTE, UnitScale.MEMORY.KIBI_BYTE), 4.5);
+ assert.strictEqual(tr.b.convertUnit(
+ 4608, UnitScale.MEMORY.KIBI_BYTE, UnitScale.MEMORY.MEBI_BYTE), 4.5);
+ assert.strictEqual(tr.b.convertUnit(
+ 4608, UnitScale.MEMORY.MEBI_BYTE, UnitScale.MEMORY.GIBI_BYTE), 4.5);
+ assert.strictEqual(tr.b.convertUnit(
+ 4608, UnitScale.MEMORY.GIBI_BYTE, UnitScale.MEMORY.TEBI_BYTE), 4.5);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unit_test.html b/chromium/third_party/catapult/tracing/tracing/base/unit_test.html
new file mode 100644
index 00000000000..6639e1ae208
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unit_test.html
@@ -0,0 +1,444 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/time_display_modes.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ImprovementDirection = tr.b.ImprovementDirection;
+ const Unit = tr.b.Unit;
+ const UnitPrefixScale = tr.b.UnitPrefixScale;
+
+ test('truncate', function() {
+ assert.isTrue(isNaN(Unit.byName.count.truncate(NaN)));
+ assert.isUndefined(Unit.byName.count.truncate(undefined));
+ assert.isNull(Unit.byName.count.truncate(null));
+
+ assert.strictEqual(0, Unit.byName.unitlessNumber.truncate(0));
+ assert.strictEqual(1, Unit.byName.unitlessNumber.truncate(1));
+ assert.strictEqual(10, Unit.byName.unitlessNumber.truncate(10));
+
+ assert.strictEqual(0.3, Unit.byName.count.truncate(1 / 3));
+ assert.strictEqual(0.33, Unit.byName.sigma.truncate(1 / 3));
+ assert.strictEqual(0.3333, Unit.byName.unitlessNumber.truncate(1 / 3));
+ assert.strictEqual(0.333333, Unit.byName.frequencyInHertz.truncate(1 / 3));
+ assert.strictEqual(0.333333, Unit.byName.electricPotentialInVolts.truncate(
+ 1 / 3));
+ assert.strictEqual(0.333333, Unit.byName.electricCurrentInAmperes.truncate(
+ 1 / 3));
+ assert.strictEqual(0.333333, Unit.byName.powerInWatts.truncate(1 / 3));
+ assert.strictEqual(0.333333, Unit.byName.energyInJoules.truncate(1 / 3));
+ assert.strictEqual(0.3, Unit.byName.bandwidthInBytesPerSecond.truncate(
+ 1 / 3));
+ assert.strictEqual(0.3, Unit.byName.sizeInBytes.truncate(1 / 3));
+ assert.strictEqual(0.333, Unit.byName.normalizedPercentage.truncate(1 / 3));
+ assert.strictEqual(0.333, Unit.byName.timeStampInMs.truncate(1 / 3));
+ assert.strictEqual(0.333, Unit.byName.timeDurationInMs.truncate(1 / 3));
+ assert.strictEqual(0.333333, Unit.byName.timeInMsAutoFormat.truncate(
+ 1 / 3));
+
+ assert.strictEqual(333.333, Unit.byName.energyInJoules.truncate(1e3 / 3));
+ assert.strictEqual(3333, Unit.byName.energyInJoules.truncate(1e4 / 3));
+
+ assert.strictEqual(0.7, Unit.byName.count.truncate(2 / 3));
+ assert.strictEqual(0.67, Unit.byName.sigma.truncate(2 / 3));
+ assert.strictEqual(0.6667, Unit.byName.unitlessNumber.truncate(2 / 3));
+ assert.strictEqual(0.666667, Unit.byName.frequencyInHertz.truncate(2 / 3));
+ assert.strictEqual(0.666667, Unit.byName.electricPotentialInVolts.truncate(
+ 2 / 3));
+ assert.strictEqual(0.666667, Unit.byName.electricCurrentInAmperes.truncate(
+ 2 / 3));
+ assert.strictEqual(0.666667, Unit.byName.powerInWatts.truncate(2 / 3));
+ assert.strictEqual(0.666667, Unit.byName.energyInJoules.truncate(2 / 3));
+ assert.strictEqual(0.7, Unit.byName.bandwidthInBytesPerSecond.truncate(
+ 2 / 3));
+ assert.strictEqual(0.7, Unit.byName.sizeInBytes.truncate(2 / 3));
+ assert.strictEqual(0.667, Unit.byName.normalizedPercentage.truncate(2 / 3));
+ assert.strictEqual(0.667, Unit.byName.timeStampInMs.truncate(2 / 3));
+ assert.strictEqual(0.667, Unit.byName.timeDurationInMs.truncate(2 / 3));
+ assert.strictEqual(0.666667, Unit.byName.timeInMsAutoFormat.truncate(
+ 2 / 3));
+
+ assert.strictEqual(666.667, Unit.byName.energyInJoules.truncate(2e3 / 3));
+ assert.strictEqual(6667, Unit.byName.energyInJoules.truncate(2e4 / 3));
+ });
+
+ test('Unit.display-mode-changed', function() {
+ const TimeDisplayModes = tr.b.TimeDisplayModes;
+
+ let listenerWasCalled = false;
+ function listener(e) {
+ listenerWasCalled = true;
+ }
+
+ try {
+ Unit.currentTimeDisplayMode = TimeDisplayModes.ms;
+ Unit.addEventListener('display-mode-changed', listener);
+
+ listenerWasCalled = false;
+ Unit.currentTimeDisplayMode = TimeDisplayModes.ns;
+ assert.isTrue(listenerWasCalled);
+ assert.strictEqual(Unit.currentTimeDisplayMode, TimeDisplayModes.ns);
+ } finally {
+ Unit.removeEventListener('display-mode-changed', listener);
+ Unit.reset();
+ }
+ });
+
+ test('Unit.didPreferredTimeDisplayUnitChange', function() {
+ if (tr.isHeadless) return;
+ const Unit = tr.b.Unit;
+ const TimeDisplayModes = tr.b.TimeDisplayModes;
+ assert.strictEqual(Unit.currentTimeDisplayMode, TimeDisplayModes.ms);
+
+ const displayUnit = document.createElement(
+ 'tr-v-ui-preferred-display-unit');
+ displayUnit.preferredTimeDisplayMode = TimeDisplayModes.ns;
+ this.addHTMLOutput(displayUnit);
+ tr.b.Unit.didPreferredTimeDisplayUnitChange();
+ assert.strictEqual(Unit.currentTimeDisplayMode, TimeDisplayModes.ns);
+ });
+
+ function checkTimeUnit(unit) {
+ try {
+ // Use milliseconds to display time (default behavior).
+ Unit.currentTimeDisplayMode = tr.b.TimeDisplayModes.ms;
+
+ assert.strictEqual(unit.format(0), '0.000 ms');
+ assert.strictEqual(unit.format(0.02), '0.020 ms');
+ assert.strictEqual(unit.format(0.001), '0.001 ms');
+ assert.strictEqual(unit.format(0.0005), '0.001 ms');
+ assert.strictEqual(unit.format(0.00049), '0.000 ms');
+ assert.strictEqual(unit.format(999.999), '999.999 ms');
+ assert.strictEqual(unit.format(1000.001), '1,000.001 ms');
+ assert.strictEqual(unit.format(123456789), '123,456,789.000 ms');
+ assert.strictEqual(unit.format(-0.00051), '-0.001 ms');
+ assert.strictEqual(unit.format(-123456789), '-123,456,789.000 ms');
+
+ // Change the unit to nanoseconds.
+ Unit.currentTimeDisplayMode = tr.b.TimeDisplayModes.ns;
+
+ assert.strictEqual(unit.format(0), '0 ns');
+ assert.strictEqual(unit.format(1), '1,000,000 ns');
+ assert.strictEqual(unit.format(0.000042), '42 ns');
+ assert.strictEqual(unit.format(0.000001), '1 ns');
+ assert.strictEqual(unit.format(0.0000005), '1 ns');
+ assert.strictEqual(unit.format(0.00000049), '0 ns');
+ assert.strictEqual(unit.format(123.456), '123,456,000 ns');
+ assert.strictEqual(unit.format(-0.07), '-70,000 ns');
+ } finally {
+ Unit.reset();
+ }
+ }
+
+ test('timeStampInMs', function() {
+ assert.strictEqual(Unit.byName.timeStampInMs.unitName, 'timeStampInMs');
+ assert.strictEqual(Unit.byName.timeStampInMs.asJSON(), 'tsMs');
+ checkTimeUnit(Unit.byName.timeStampInMs);
+ });
+
+ test('timeDurationInMs', function() {
+ assert.strictEqual(Unit.byName.timeDurationInMs.unitName,
+ 'timeDurationInMs');
+ assert.strictEqual(Unit.byName.timeDurationInMs.asJSON(), 'ms');
+ checkTimeUnit(Unit.byName.timeDurationInMs);
+ });
+
+ test('sizeInBytes', function() {
+ const SOURCE_VALUES = [0, 1, 1536, 424.5 * 1024 * 1024,
+ 1025 * 1024 * 1024 * 1024 * 1024, -2.5 * 1024 * 1024];
+ const EXPECTED_REGULAR_FORMATTED_VALUES = ['0.0 B', '1.0 B', '1.5 KiB',
+ '424.5 MiB', '1,025.0 TiB', '-2.5 MiB'];
+ const EXPECTED_DELTA_FORMATTED_VALUES = [
+ '\u00B10.0 B', '+1.0 B', '+1.5 KiB',
+ '+424.5 MiB', '+1,025.0 TiB', '-2.5 MiB',
+ ];
+
+ function checkSizeUnit(unit, expectation) {
+ assert.strictEqual(unit.unitName, expectation.unitName);
+ assert.strictEqual(unit.asJSON(), expectation.asJSON);
+ assert.strictEqual(unit.isDelta, expectation.isDelta);
+ assert.strictEqual(unit.baseUnit, expectation.baseUnit);
+ assert.strictEqual(unit.correspondingDeltaUnit,
+ expectation.correspondingDeltaUnit);
+ assert.strictEqual(unit.improvementDirection,
+ expectation.improvementDirection);
+ assert.deepEqual(SOURCE_VALUES.map(v => unit.format(v)),
+ expectation.formattedValues);
+ }
+
+ // Regular (non-delta).
+ checkSizeUnit(Unit.byName.sizeInBytes, {
+ unitName: 'sizeInBytes',
+ asJSON: 'sizeInBytes',
+ isDelta: false,
+ baseUnit: Unit.byName.sizeInBytes,
+ correspondingDeltaUnit: Unit.byName.sizeInBytesDelta,
+ improvementDirection: ImprovementDirection.DONT_CARE,
+ formattedValues: EXPECTED_REGULAR_FORMATTED_VALUES
+ });
+ checkSizeUnit(Unit.byName.sizeInBytes_smallerIsBetter, {
+ unitName: 'sizeInBytes_smallerIsBetter',
+ asJSON: 'sizeInBytes_smallerIsBetter',
+ isDelta: false,
+ baseUnit: Unit.byName.sizeInBytes,
+ correspondingDeltaUnit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ improvementDirection: ImprovementDirection.SMALLER_IS_BETTER,
+ formattedValues: EXPECTED_REGULAR_FORMATTED_VALUES
+ });
+ checkSizeUnit(Unit.byName.sizeInBytes_biggerIsBetter, {
+ unitName: 'sizeInBytes_biggerIsBetter',
+ asJSON: 'sizeInBytes_biggerIsBetter',
+ isDelta: false,
+ baseUnit: Unit.byName.sizeInBytes,
+ correspondingDeltaUnit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ improvementDirection: ImprovementDirection.BIGGER_IS_BETTER,
+ formattedValues: EXPECTED_REGULAR_FORMATTED_VALUES
+ });
+
+ // Delta.
+ checkSizeUnit(Unit.byName.sizeInBytesDelta, {
+ unitName: 'sizeInBytesDelta',
+ asJSON: 'sizeInBytesDelta',
+ isDelta: true,
+ baseUnit: Unit.byName.sizeInBytes,
+ correspondingDeltaUnit: Unit.byName.sizeInBytesDelta,
+ improvementDirection: ImprovementDirection.DONT_CARE,
+ formattedValues: EXPECTED_DELTA_FORMATTED_VALUES
+ });
+ checkSizeUnit(Unit.byName.sizeInBytesDelta_smallerIsBetter, {
+ unitName: 'sizeInBytesDelta_smallerIsBetter',
+ asJSON: 'sizeInBytesDelta_smallerIsBetter',
+ isDelta: true,
+ baseUnit: Unit.byName.sizeInBytes,
+ correspondingDeltaUnit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ improvementDirection: ImprovementDirection.SMALLER_IS_BETTER,
+ formattedValues: EXPECTED_DELTA_FORMATTED_VALUES
+ });
+ checkSizeUnit(Unit.byName.sizeInBytesDelta_biggerIsBetter, {
+ unitName: 'sizeInBytesDelta_biggerIsBetter',
+ asJSON: 'sizeInBytesDelta_biggerIsBetter',
+ isDelta: true,
+ baseUnit: Unit.byName.sizeInBytes,
+ correspondingDeltaUnit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ improvementDirection: ImprovementDirection.BIGGER_IS_BETTER,
+ formattedValues: EXPECTED_DELTA_FORMATTED_VALUES
+ });
+ });
+
+ test('bytesPerSecond', function() {
+ const SOURCE_VALUES = [0, 1, 1536, 424.5 * 1024 * 1024,
+ 1025 * 1024 * 1024 * 1024 * 1024, -2.5 * 1024 * 1024];
+ const EXPECTED_REGULAR_FORMATTED_VALUES = ['0.0 B/s', '1.0 B/s',
+ '1.5 KiB/s', '424.5 MiB/s', '1,025.0 TiB/s', '-2.5 MiB/s'];
+ const EXPECTED_DELTA_FORMATTED_VALUES = [
+ '\u00B10.0 B/s', '+1.0 B/s', '+1.5 KiB/s',
+ '+424.5 MiB/s', '+1,025.0 TiB/s', '-2.5 MiB/s',
+ ];
+
+ function checkSizeUnit(unit, expectation) {
+ assert.strictEqual(unit.unitName, expectation.unitName);
+ assert.strictEqual(unit.asJSON(), expectation.asJSON);
+ assert.strictEqual(unit.isDelta, expectation.isDelta);
+ assert.strictEqual(unit.baseUnit, expectation.baseUnit);
+ assert.strictEqual(unit.correspondingDeltaUnit,
+ expectation.correspondingDeltaUnit);
+ assert.strictEqual(unit.improvementDirection,
+ expectation.improvementDirection);
+ assert.deepEqual(SOURCE_VALUES.map(v => unit.format(v)),
+ expectation.formattedValues);
+ }
+
+ // Regular (non-delta).
+ checkSizeUnit(Unit.byName.bandwidthInBytesPerSecond, {
+ unitName: 'bandwidthInBytesPerSecond',
+ asJSON: 'bytesPerSecond',
+ isDelta: false,
+ baseUnit: Unit.byName.bandwidthInBytesPerSecond,
+ correspondingDeltaUnit: Unit.byName.bandwidthInBytesPerSecondDelta,
+ improvementDirection: ImprovementDirection.DONT_CARE,
+ formattedValues: EXPECTED_REGULAR_FORMATTED_VALUES
+ });
+ checkSizeUnit(Unit.byName.bandwidthInBytesPerSecond_smallerIsBetter, {
+ unitName: 'bandwidthInBytesPerSecond_smallerIsBetter',
+ asJSON: 'bytesPerSecond_smallerIsBetter',
+ isDelta: false,
+ baseUnit: Unit.byName.bandwidthInBytesPerSecond,
+ correspondingDeltaUnit:
+ Unit.byName.bandwidthInBytesPerSecondDelta_smallerIsBetter,
+ improvementDirection: ImprovementDirection.SMALLER_IS_BETTER,
+ formattedValues: EXPECTED_REGULAR_FORMATTED_VALUES
+ });
+ checkSizeUnit(Unit.byName.bandwidthInBytesPerSecond_biggerIsBetter, {
+ unitName: 'bandwidthInBytesPerSecond_biggerIsBetter',
+ asJSON: 'bytesPerSecond_biggerIsBetter',
+ isDelta: false,
+ baseUnit: Unit.byName.bandwidthInBytesPerSecond,
+ correspondingDeltaUnit:
+ Unit.byName.bandwidthInBytesPerSecondDelta_biggerIsBetter,
+ improvementDirection: ImprovementDirection.BIGGER_IS_BETTER,
+ formattedValues: EXPECTED_REGULAR_FORMATTED_VALUES
+ });
+
+ // Delta.
+ checkSizeUnit(Unit.byName.bandwidthInBytesPerSecondDelta, {
+ unitName: 'bandwidthInBytesPerSecondDelta',
+ asJSON: 'bytesPerSecondDelta',
+ isDelta: true,
+ baseUnit: Unit.byName.bandwidthInBytesPerSecond,
+ correspondingDeltaUnit: Unit.byName.bandwidthInBytesPerSecondDelta,
+ improvementDirection: ImprovementDirection.DONT_CARE,
+ formattedValues: EXPECTED_DELTA_FORMATTED_VALUES
+ });
+ checkSizeUnit(Unit.byName.bandwidthInBytesPerSecondDelta_smallerIsBetter, {
+ unitName: 'bandwidthInBytesPerSecondDelta_smallerIsBetter',
+ asJSON: 'bytesPerSecondDelta_smallerIsBetter',
+ isDelta: true,
+ baseUnit: Unit.byName.bandwidthInBytesPerSecond,
+ correspondingDeltaUnit:
+ Unit.byName.bandwidthInBytesPerSecondDelta_smallerIsBetter,
+ improvementDirection: ImprovementDirection.SMALLER_IS_BETTER,
+ formattedValues: EXPECTED_DELTA_FORMATTED_VALUES
+ });
+ checkSizeUnit(Unit.byName.bandwidthInBytesPerSecondDelta_biggerIsBetter, {
+ unitName: 'bandwidthInBytesPerSecondDelta_biggerIsBetter',
+ asJSON: 'bytesPerSecondDelta_biggerIsBetter',
+ isDelta: true,
+ baseUnit: Unit.byName.bandwidthInBytesPerSecond,
+ correspondingDeltaUnit:
+ Unit.byName.bandwidthInBytesPerSecondDelta_biggerIsBetter,
+ improvementDirection: ImprovementDirection.BIGGER_IS_BETTER,
+ formattedValues: EXPECTED_DELTA_FORMATTED_VALUES
+ });
+ });
+
+ test('context', function() {
+ assert.strictEqual(Unit.byName.timeStampInMs.format(0, {}), '0.000 ms');
+ assert.strictEqual(Unit.byName.normalizedPercentageDelta.format(1.23456,
+ { maximumFractionDigits: 2 }), '+123.46%');
+ assert.strictEqual(Unit.byName.powerInWatts.format(999.999,
+ { minimumFractionDigits: 5 }), '999.99900 W');
+ assert.strictEqual(Unit.byName.powerInWatts_biggerIsBetter.format(8.88,
+ { minimumFractionDigits: 1 }), '8.88 W');
+ assert.strictEqual(Unit.byName.unitlessNumber.format(0.00789,
+ { maximumFractionDigits: 6 }), '0.00789');
+ assert.strictEqual(Unit.byName.unitlessNumber.format(41.9,
+ { maximumFractionDigits: 0 }), '42');
+ assert.strictEqual(
+ Unit.byName.energyInJoules.format(0.4444,
+ { minimumFractionDigits: 2, maximumFractionDigits: 3 }),
+ '444.40 mJ');
+ assert.strictEqual(
+ Unit.byName.energyInJoules.format(0.6,
+ { minimumFractionDigits: 2, maximumFractionDigits: 3 }),
+ '600.00 mJ');
+ assert.strictEqual(
+ Unit.byName.sizeInBytesDelta_smallerIsBetter.format(0,
+ { minimumFractionDigits: 1, maximumFractionDigits: 1 }),
+ '\u00B10.0 B');
+ assert.strictEqual(
+ Unit.byName.sizeInBytes.format(25600000000,
+ { unitPrefix: UnitPrefixScale.BINARY.KIBI }),
+ '25,000,000.0 KiB');
+ assert.strictEqual(
+ Unit.byName.sizeInBytes.format(5243,
+ { unitPrefix: UnitPrefixScale.BINARY.MEBI,
+ minimumFractionDigits: 2 }),
+ '0.01 MiB');
+ assert.strictEqual(
+ Unit.byName.bandwidthInBytesPerSecondDelta_smallerIsBetter.format(0,
+ { minimumFractionDigits: 1, maximumFractionDigits: 1 }),
+ '\u00B10.0 B/s');
+ assert.strictEqual(
+ Unit.byName.bandwidthInBytesPerSecond.format(25600000000,
+ { unitPrefix: UnitPrefixScale.DATA_SIZE.KIBI_BYTE }),
+ '25,000,000.0 KiB/s');
+ assert.strictEqual(
+ Unit.byName.bandwidthInBytesPerSecond.format(5243,
+ { unitPrefix: UnitPrefixScale.DATA_SIZE.MEBI_BYTE,
+ minimumFractionDigits: 2 }),
+ '0.01 MiB/s');
+ });
+
+ test('energyInJoules', function() {
+ assert.strictEqual(Unit.byName.energyInJoules.format(1000), '1.000 kJ');
+ assert.strictEqual(Unit.byName.energyInJoules.format(1), '1.000 J');
+ assert.strictEqual(Unit.byName.energyInJoules.format(0), '0.000 J');
+ assert.strictEqual(Unit.byName.energyInJoules.format(.005), '5.000 mJ');
+ assert.strictEqual(
+ Unit.byName.energyInJoules.format(.0005),
+ '500.000 ' + tr.b.GREEK_SMALL_LETTER_MU + 'J');
+ assert.strictEqual(
+ Unit.byName.energyInJoules.format(.0004),
+ '400.000 ' + tr.b.GREEK_SMALL_LETTER_MU + 'J');
+ });
+
+ test('powerInWatts', function() {
+ assert.strictEqual(Unit.byName.powerInWatts.format(1000), '1.000 kW');
+ assert.strictEqual(Unit.byName.powerInWatts.format(1), '1.000 W');
+ assert.strictEqual(Unit.byName.powerInWatts.format(0), '0.000 W');
+ assert.strictEqual(Unit.byName.powerInWatts.format(.001), '1.000 mW');
+ assert.strictEqual(Unit.byName.powerInWatts.format(.001005), '1.005 mW');
+ });
+
+ test('electricCurrentInAmperes', function() {
+ assert.strictEqual(
+ Unit.byName.electricCurrentInAmperes.format(1000), '1.000 kA');
+ assert.strictEqual(
+ Unit.byName.electricCurrentInAmperes.format(1), '1.000 A');
+ assert.strictEqual(
+ Unit.byName.electricCurrentInAmperes.format(0), '0.000 A');
+ assert.strictEqual(
+ Unit.byName.electricCurrentInAmperes.format(.001), '1.000 mA');
+ assert.strictEqual(
+ Unit.byName.electricCurrentInAmperes.format(.001005), '1.005 mA');
+ });
+
+ test('electricPotentialInVolts', function() {
+ assert.strictEqual(
+ Unit.byName.electricPotentialInVolts.format(1000), '1.000 kV');
+ assert.strictEqual(
+ Unit.byName.electricPotentialInVolts.format(1), '1.000 V');
+ assert.strictEqual(
+ Unit.byName.electricPotentialInVolts.format(0), '0.000 V');
+ assert.strictEqual(
+ Unit.byName.electricPotentialInVolts.format(.001), '1.000 mV');
+ assert.strictEqual(
+ Unit.byName.electricPotentialInVolts.format(.001005), '1.005 mV');
+ });
+
+ test('frequencyInHertz', function() {
+ assert.strictEqual(
+ Unit.byName.frequencyInHertz.format(1000), '1.000 kHz');
+ assert.strictEqual(Unit.byName.frequencyInHertz.format(1), '1.000 Hz');
+ assert.strictEqual(Unit.byName.frequencyInHertz.format(0), '0.000 Hz');
+ assert.strictEqual(Unit.byName.frequencyInHertz.format(.001), '1.000 mHz');
+ assert.strictEqual(
+ Unit.byName.frequencyInHertz.format(.001005), '1.005 mHz');
+ });
+
+ test('unitlessNumber', function() {
+ assert.strictEqual(Unit.byName.unitlessNumber.format(1), '1.000');
+ assert.strictEqual(Unit.byName.unitlessNumber.format(0), '0.000');
+ assert.strictEqual(Unit.byName.unitlessNumber.format(1.23), '1.230');
+ assert.strictEqual(Unit.byName.unitlessNumber.format(-1.23), '-1.230');
+ assert.strictEqual(Unit.byName.unitlessNumber.format(0), '0.000');
+ });
+
+ test('count', function() {
+ assert.strictEqual(Unit.byName.count.format(0), '0');
+ assert.strictEqual(Unit.byName.count.format(1), '1');
+ assert.strictEqual(Unit.byName.count.format(1.4), '1');
+ assert.strictEqual(Unit.byName.count.format(100), '100');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest.html b/chromium/third_party/catapult/tracing/tracing/base/unittest.html
new file mode 100644
index 00000000000..e8d214b2300
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+
+<script src="/chai/chai.js"></script>
+<script>
+ 'use strict';
+ /**
+ * Alias chai assert to the global assert.
+ */
+ if (tr.isNode) {
+ // In node, chai.js knows to act as a node module, whereas our HTML
+ // imports code expects chai to end up in the global scope. So, in Node,
+ // copy the chai exports into global.
+ const chaiAbsPath = HTMLImportsLoader.hrefToAbsolutePath(
+ '/chai/chai.js');
+ const chaiModule = require(chaiAbsPath);
+ for (const exportName in chaiModule) {
+ global[exportName] = chaiModule[exportName];
+ }
+ } else {
+ // https://github.com/catapult-project/catapult/issues/3097
+ chai.config.includeStack = true;
+
+ /**
+ * Catapult presubmit wanted me to put a jsdoc here. So nduca did.
+ */
+ global.assert = chai.assert;
+ }
+ global.assert.equal = () => {
+ // See https://github.com/catapult-project/catapult/issues/3235
+ throw new Error('Use assert.strictEqual instead of assert.equal since ' +
+ 'assert.equal will coerce its arguments.');
+ };
+</script>
+
+<link rel="import" href="/tracing/base/unittest/suite_loader.html">
+<link rel="import" href="/tracing/base/unittest/test_case.html">
+<link rel="import" href="/tracing/base/unittest/test_runner.html">
+<link rel="import" href="/tracing/base/unittest/test_suite.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/constants.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/constants.html
new file mode 100644
index 00000000000..f00bba28e1d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/constants.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b.unittest', function() {
+ const TestStatus = {
+ PENDING: 'pending-status',
+ RUNNING: 'running-status',
+ DONE_RUNNING: 'done-running-status'
+ };
+
+ const TestTypes = {
+ UNITTEST: 'unittest-type',
+ PERFTEST: 'perftest-type'
+ };
+
+ return {
+ TestStatus,
+ TestTypes,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html
new file mode 100644
index 00000000000..66cf9e95109
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/html_test_results.html
@@ -0,0 +1,540 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/unittest/constants.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<style>
+ x-tr-b-unittest-test-results {
+ display: flex;
+ flex-direction: column;
+ flex: 0 0 auto;
+ }
+
+ x-tr-b-unittest-test-results > x-html-test-case-result.dark > #summary {
+ background-color: #eee;
+ }
+
+ x-html-test-case-result {
+ display: block;
+ }
+ x-html-test-case-result > #summary > #title,
+ x-html-test-case-result > #summary > #status,
+ x-html-test-case-result > #details > x-html-test-case-error > #message,
+ x-html-test-case-result > #details > x-html-test-case-error > #stack,
+ x-html-test-case-result > #details > x-html-test-case-error > #return-value,
+ x-html-test-case-result > #details > x-html-test-case-flaky > #message {
+ -webkit-user-select: auto;
+ }
+
+ x-html-test-case-result > #details > x-html-test-case-error,
+ x-html-test-case-result > #details > x-html-test-case-flaky {
+ display: block;
+ border: 1px solid grey;
+ border-radius: 5px;
+ font-family: monospace;
+ margin-bottom: 14px;
+ }
+
+ x-html-test-case-result > #details > x-html-test-case-error > #message,
+ x-html-test-case-result > #details > x-html-test-case-error > #stack,
+ x-html-test-case-result > #details > x-html-test-case-flaky > #message {
+ white-space: pre;
+ }
+
+ x-html-test-case-result > #details > x-html-test-case-html-result {
+ display: block;
+ }
+
+ .unittest-pending {
+ color: orange;
+ }
+ .unittest-running {
+ color: orange;
+ font-weight: bold;
+ }
+
+ .unittest-passed {
+ color: darkgreen;
+ }
+
+ .unittest-failed {
+ color: darkred;
+ font-weight: bold;
+ }
+
+ .unittest-flaky {
+ color: darkorange;
+ }
+
+ .unittest-skipped {
+ color: blue;
+ }
+
+ .unittest-exception {
+ color: red;
+ font-weight: bold;
+ }
+
+ .unittest-failure {
+ border: 1px solid grey;
+ border-radius: 5px;
+ padding: 5px;
+ }
+</style>
+<template id="x-html-test-case-result-template">
+ <div id="summary">
+ <span id="title"></span>&nbsp;
+ <span id="status"></span>&nbsp;
+ <span id="return-value"></span>
+ </div>
+ <div id="details"></div>
+</template>
+
+<template id="x-html-test-case-error-template">
+ <div id="stack"></div>
+</template>
+
+<template id="x-html-test-case-flaky-template">
+ <div id="message"></div>
+</template>
+
+<template id="x-html-test-case-skipped-template">
+ <div id="message"></div>
+</template>
+
+<script>
+'use strict';
+tr.exportTo('tr.b.unittest', function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ const TestStatus = tr.b.unittest.TestStatus;
+ const TestTypes = tr.b.unittest.TestTypes;
+
+ /**
+ * @constructor
+ */
+ const HTMLTestCaseResult = tr.ui.b.define('x-html-test-case-result');
+
+ HTMLTestCaseResult.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ Polymer.dom(this).appendChild(tr.ui.b.instantiateTemplate(
+ '#x-html-test-case-result-template', THIS_DOC));
+ this.testCase_ = undefined;
+ this.testCaseHRef_ = undefined;
+ this.duration_ = undefined;
+ this.testStatus_ = TestStatus.PENDING;
+ this.testReturnValue_ = undefined;
+ this.showHTMLOutput_ = false;
+ this.updateColorAndStatus_();
+ },
+
+ get showHTMLOutput() {
+ return this.showHTMLOutput_;
+ },
+
+ set showHTMLOutput(showHTMLOutput) {
+ this.showHTMLOutput_ = showHTMLOutput;
+ this.updateHTMLOutputDisplayState_();
+ },
+
+ get testCase() {
+ return this.testCase_;
+ },
+
+ set testCase(testCase) {
+ this.testCase_ = testCase;
+ this.updateTitle_();
+ },
+
+ get testCaseHRef() {
+ return this.testCaseHRef_;
+ },
+
+ set testCaseHRef(href) {
+ this.testCaseHRef_ = href;
+ this.updateTitle_();
+ },
+ updateTitle_() {
+ const titleEl = Polymer.dom(this).querySelector('#title');
+ if (this.testCase_ === undefined) {
+ Polymer.dom(titleEl).textContent = '';
+ return;
+ }
+
+ if (this.testCaseHRef_) {
+ Polymer.dom(titleEl).innerHTML =
+ '<a href="' + this.testCaseHRef_ + '">' +
+ this.testCase_.fullyQualifiedName + '</a>';
+ } else {
+ Polymer.dom(titleEl).textContent = this.testCase_.fullyQualifiedName;
+ }
+ },
+
+ addError(normalizedException) {
+ const errorEl = document.createElement('x-html-test-case-error');
+ Polymer.dom(errorEl).appendChild(tr.ui.b.instantiateTemplate(
+ '#x-html-test-case-error-template', THIS_DOC));
+ Polymer.dom(Polymer.dom(errorEl).querySelector('#stack')).
+ textContent = normalizedException.stack;
+ Polymer.dom(Polymer.dom(this).querySelector('#details')).appendChild(
+ errorEl);
+ this.updateColorAndStatus_();
+ },
+
+ addFlaky() {
+ const flakyEl = document.createElement('x-html-test-case-flaky');
+ Polymer.dom(flakyEl).appendChild(tr.ui.b.instantiateTemplate(
+ '#x-html-test-case-flaky-template', THIS_DOC));
+ Polymer.dom(Polymer.dom(flakyEl).querySelector('#message'))
+ .textContent = 'FLAKY';
+ Polymer.dom(Polymer.dom(this).querySelector('#details')).appendChild(
+ flakyEl);
+ this.updateColorAndStatus_();
+ },
+
+ addSkipped() {
+ const skippedEl = document.createElement('x-html-test-case-skipped');
+ Polymer.dom(skippedEl).appendChild(tr.ui.b.instantiateTemplate(
+ '#x-html-test-case-skipped-template', THIS_DOC));
+ Polymer.dom(Polymer.dom(skippedEl).querySelector('#message'))
+ .textContent = 'SKIPPED';
+ Polymer.dom(Polymer.dom(this).querySelector('#details')).appendChild(
+ skippedEl);
+ this.updateColorAndStatus_();
+ },
+
+ addHTMLOutput(element) {
+ const htmlResultEl = document.createElement(
+ 'x-html-test-case-html-result');
+ Polymer.dom(htmlResultEl).appendChild(element);
+ Polymer.dom(Polymer.dom(this).querySelector('#details'))
+ .appendChild(htmlResultEl);
+ },
+
+ updateHTMLOutputDisplayState_() {
+ const htmlResults =
+ Polymer.dom(this).querySelectorAll('x-html-test-case-html-result');
+ let display;
+ if (this.showHTMLOutput) {
+ display = '';
+ } else {
+ display = (this.testStatus_ === TestStatus.RUNNING) ? '' : 'none';
+ }
+ for (let i = 0; i < htmlResults.length; i++) {
+ htmlResults[i].style.display = display;
+ }
+ },
+
+ get hadErrors() {
+ return !!Polymer.dom(this).querySelector('x-html-test-case-error');
+ },
+
+ get isFlaky() {
+ return !!Polymer.dom(this).querySelector('x-html-test-case-flaky');
+ },
+
+ get isSkipped() {
+ return !!Polymer.dom(this).querySelector('x-html-test-case-skipped');
+ },
+
+ get duration() {
+ return this.duration_;
+ },
+
+ set duration(duration) {
+ this.duration_ = duration;
+ this.updateColorAndStatus_();
+ },
+
+ get testStatus() {
+ return this.testStatus_;
+ },
+
+ set testStatus(testStatus) {
+ this.testStatus_ = testStatus;
+ this.updateColorAndStatus_();
+ this.updateHTMLOutputDisplayState_();
+ },
+
+ updateColorAndStatus_() {
+ let colorCls;
+ let status;
+ if (this.hadErrors) {
+ colorCls = 'unittest-failed';
+ status = 'failed';
+ } else if (this.isFlaky) {
+ colorCls = 'unittest-flaky';
+ status = 'flaky';
+ } else if (this.isSkipped) {
+ colorCls = 'unittest-skipped';
+ status = 'skipped';
+ } else if (this.testStatus_ === TestStatus.PENDING) {
+ colorCls = 'unittest-pending';
+ status = 'pending';
+ } else if (this.testStatus_ === TestStatus.RUNNING) {
+ colorCls = 'unittest-running';
+ status = 'running';
+ } else { // DONE_RUNNING and no errors
+ colorCls = 'unittest-passed';
+ status = 'passed';
+ }
+
+ const statusEl = Polymer.dom(this).querySelector('#status');
+ if (this.duration_) {
+ Polymer.dom(statusEl).textContent = status + ' (' +
+ this.duration_.toFixed(2) + 'ms)';
+ } else {
+ Polymer.dom(statusEl).textContent = status;
+ }
+ statusEl.className = colorCls;
+ },
+
+ get testReturnValue() {
+ return this.testReturnValue_;
+ },
+
+ set testReturnValue(testReturnValue) {
+ this.testReturnValue_ = testReturnValue;
+ Polymer.dom(Polymer.dom(this).querySelector('#return-value'))
+ .textContent = testReturnValue;
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ const HTMLTestResults = tr.ui.b.define('x-tr-b-unittest-test-results');
+
+ HTMLTestResults.prototype = {
+ __proto__: HTMLUnknownElement.prototype,
+
+ decorate() {
+ this.testCaseResultsByCaseGUID_ = {};
+ this.currentTestCaseStartTime_ = undefined;
+ this.totalRunTime_ = 0;
+ this.numTestsThatPassed_ = 0;
+ this.numTestsThatFailed_ = 0;
+ this.numFlakyTests_ = 0;
+ this.numSkippedTests_ = 0;
+ this.showHTMLOutput_ = false;
+ this.showPendingAndPassedTests_ = false;
+ this.linkifyCallback_ = undefined;
+ this.headless_ = false;
+ },
+
+ get headless() {
+ return this.headless_;
+ },
+
+ set headless(headless) {
+ this.headless_ = headless;
+ },
+
+ getHRefForTestCase(testCase) {
+ /* Override this to create custom links */
+ return undefined;
+ },
+
+ get showHTMLOutput() {
+ return this.showHTMLOutput_;
+ },
+
+ set showHTMLOutput(showHTMLOutput) {
+ this.showHTMLOutput_ = showHTMLOutput;
+ const testCaseResults =
+ Polymer.dom(this).querySelectorAll('x-html-test-case-result');
+ for (let i = 0; i < testCaseResults.length; i++) {
+ testCaseResults[i].showHTMLOutput = showHTMLOutput;
+ }
+ },
+
+ get showPendingAndPassedTests() {
+ return this.showPendingAndPassedTests_;
+ },
+
+ set showPendingAndPassedTests(showPendingAndPassedTests) {
+ this.showPendingAndPassedTests_ = showPendingAndPassedTests;
+
+ const testCaseResults =
+ Polymer.dom(this).querySelectorAll('x-html-test-case-result');
+ for (let i = testCaseResults.length - 1; i >= 0; i--) {
+ this.updateDisplayStateForResult_(testCaseResults[i]);
+ }
+ },
+
+ updateDisplayStateForResult_(res) {
+ let display;
+ if (this.showPendingAndPassedTests_) {
+ if (res.testStatus === TestStatus.RUNNING ||
+ res.hadErrors) {
+ display = '';
+ } else {
+ display = 'none';
+ }
+ } else {
+ display = '';
+ }
+ res.style.display = display;
+ },
+
+ willRunTests(testCases) {
+ this.timeAtBeginningOfTest_ = window.performance.now();
+ testCases.forEach(function(testCase, i) {
+ const testCaseResult = new HTMLTestCaseResult();
+ testCaseResult.showHTMLOutput = this.showHTMLOutput_;
+ testCaseResult.testCase = testCase;
+ if ((i % 2) === 0) {
+ Polymer.dom(testCaseResult).classList.add('dark');
+ }
+
+ const href = this.getHRefForTestCase(testCase);
+ if (href) {
+ testCaseResult.testCaseHRef = href;
+ }
+ testCaseResult.testStatus = TestStatus.PENDING;
+ this.testCaseResultsByCaseGUID_[testCase.guid] = testCaseResult;
+ Polymer.dom(this).appendChild(testCaseResult);
+ this.updateDisplayStateForResult_(testCaseResult);
+ }, this);
+ },
+
+ willRunTest(testCase) {
+ this.currentTestCaseResult_ = this.testCaseResultsByCaseGUID_[
+ testCase.guid];
+ this.currentTestCaseStartTime_ = window.performance.now();
+ this.currentTestCaseResult_.testStatus = TestStatus.RUNNING;
+ this.updateDisplayStateForResult_(this.currentTestCaseResult_);
+ this.log_(testCase.fullyQualifiedName + ': ');
+ },
+
+ addErrorForCurrentTest(error) {
+ this.log_('\n');
+
+ const normalizedException = tr.b.normalizeException(error);
+ this.log_('Exception: ' + normalizedException.message + '\n' +
+ normalizedException.stack);
+
+ this.currentTestCaseResult_.addError(normalizedException);
+ this.updateDisplayStateForResult_(this.currentTestCaseResult_);
+ if (this.headless_) {
+ this.notifyTestResultToDevServer_('EXCEPT', normalizedException.stack);
+ }
+ },
+
+ addHTMLOutputForCurrentTest(element) {
+ this.currentTestCaseResult_.addHTMLOutput(element);
+ this.updateDisplayStateForResult_(this.currentTestCaseResult_);
+ },
+
+ setCurrentTestFlaky() {
+ this.currentTestCaseResult_.addFlaky();
+ this.updateDisplayStateForResult_(this.currentTestCaseResult_);
+ },
+
+ setCurrentTestSkipped() {
+ this.currentTestCaseResult_.addSkipped();
+ this.updateDisplayStateForResult_(this.currentTestCaseResult_);
+ },
+
+ setReturnValueFromCurrentTest(returnValue) {
+ this.currentTestCaseResult_.testReturnValue = returnValue;
+ },
+
+ didCurrentTestEnd() {
+ const now = window.performance.now();
+ const testCaseResult = this.currentTestCaseResult_;
+ const testCaseDuration = now - this.currentTestCaseStartTime_;
+ this.currentTestCaseResult_.testStatus = TestStatus.DONE_RUNNING;
+ testCaseResult.duration = testCaseDuration;
+ this.totalRunTime_ = now - this.timeAtBeginningOfTest_;
+ let resultString;
+ if (testCaseResult.hadErrors) {
+ resultString = 'FAILED';
+ this.numTestsThatFailed_ += 1;
+ tr.b.dispatchSimpleEvent(this, 'testfailed');
+ } else if (testCaseResult.isFlaky) {
+ resultString = 'FLAKY';
+ this.numFlakyTests_ += 1;
+ tr.b.dispatchSimpleEvent(this, 'testflaky');
+ } else if (testCaseResult.isSkipped) {
+ resultString = 'SKIPPED';
+ this.numSkippedTests_ += 1;
+ tr.b.dispatchSimpleEvent(this, 'testskipped');
+ } else {
+ resultString = 'PASSED';
+ this.numTestsThatPassed_ += 1;
+ tr.b.dispatchSimpleEvent(this, 'testpassed');
+ }
+ this.log_('[' + resultString + ']\n');
+
+ if (this.headless_) {
+ this.notifyTestResultToDevServer_(resultString);
+ }
+
+ this.updateDisplayStateForResult_(this.currentTestCaseResult_);
+ this.currentTestCaseResult_ = undefined;
+ },
+
+ didRunTests() {
+ this.log_('[DONE]\n');
+ if (this.headless_) {
+ this.notifyTestCompletionToDevServer_();
+ }
+ },
+
+ getStats() {
+ return {
+ numTestsThatPassed: this.numTestsThatPassed_,
+ numTestsThatFailed: this.numTestsThatFailed_,
+ numFlakyTests: this.numFlakyTests_,
+ numSkippedTests: this.numSkippedTests_,
+ totalRunTime: this.totalRunTime_
+ };
+ },
+
+ didAllTestsPass() {
+ // A test counts as failing if it failed or it was skipped.
+ return this.numTestsThatFailed_ + this.numSkippedTests_ === 0;
+ },
+
+ notifyTestResultToDevServer_(result, extraMsg) {
+ const req = new XMLHttpRequest();
+ const testName = this.currentTestCaseResult_.testCase.fullyQualifiedName;
+ const data = result + ' ' + testName + ' ' + (extraMsg || '');
+ tr.b.postAsync('/tracing/notify_test_result', data);
+ },
+
+ notifyTestCompletionToDevServer_() {
+ if (this.numTestsThatPassed_ + this.numTestsThatFailed_ +
+ this.numFlakyTests_ + this.numSkippedTests_ === 0) {
+ return;
+ }
+ let data = this.didAllTestsPass() ? 'ALL_PASSED' : 'HAD_FAILURES';
+ data += '\nPassed tests: ' + this.numTestsThatPassed_ +
+ ' Failed tests: ' + this.numTestsThatFailed_ +
+ ' Skipped tests: ' + this.numSkippedTests_ +
+ ' Flaky tests: ' + this.numFlakyTests_;
+
+ tr.b.postAsync('/tracing/notify_tests_completed', data);
+ },
+
+ log_(msg) {
+ tr.b.dispatchSimpleEvent(this, 'statschange');
+ }
+ };
+
+ return {
+ HTMLTestResults,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/interactive_test_runner.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/interactive_test_runner.html
new file mode 100644
index 00000000000..d83012033b3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/interactive_test_runner.html
@@ -0,0 +1,735 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/unittest.html">
+<link rel="import" href="/tracing/base/unittest/html_test_results.html">
+<link rel="import" href="/tracing/base/unittest/suite_loader.html">
+<link rel="import" href="/tracing/base/unittest/test_runner.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<style>
+ x-base-interactive-test-runner {
+ display: flex;
+ flex-direction: column;
+ flex: 0 0 auto;
+ }
+
+ x-base-interactive-test-runner > * {
+ flex: 0 0 auto;
+ }
+ x-base-interactive-test-runner > #title {
+ font-size: 16pt;
+ }
+
+ x-base-interactive-test-runner {
+ font-family: sans-serif;
+ }
+
+ x-base-interactive-test-runner > h1 {
+ margin: 5px 0px 10px 0px;
+ }
+
+ x-base-interactive-test-runner > #stats {
+ }
+
+ x-base-interactive-test-runner > #controls {
+ display: block;
+ margin-bottom: 5px;
+ }
+
+ x-base-interactive-test-runner > #controls > ul {
+ list-style-type: none;
+ padding: 0;
+ margin: 0;
+ }
+
+ x-base-interactive-test-runner > #controls > ul > li {
+ float: left;
+ margin-right: 10px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ }
+
+ x-base-interactive-test-runner > #shortform-results {
+ color: green;
+ height; 40px;
+ word-wrap: break-word;
+ }
+
+ x-base-interactive-test-runner > #shortform-results > .fail {
+ color: darkred;
+ font-weight: bold;
+ }
+
+ x-base-interactive-test-runner > #shortform-results > .flaky {
+ color: darkorange;
+ }
+
+ x-base-interactive-test-runner > #shortform-results > .skipped {
+ color: blue;
+ }
+
+ x-base-interactive-test-runner > #results-container {
+ flex: 1 1 auto;
+ min-height: 0;
+ overflow: auto;
+ padding: 0 4px 0 4px;
+ }
+
+ .unittest-pending {
+ color: orange;
+ }
+ .unittest-running {
+ color: orange;
+ font-weight: bold;
+ }
+
+ .unittest-passed {
+ color: darkgreen;
+ }
+
+ .unittest-failed {
+ color: darkred;
+ font-weight: bold;
+ }
+
+ .unittest-flaky {
+ color: darkorange;
+ }
+
+ .unittest-exception {
+ color: red;
+ font-weight: bold;
+ }
+
+ .unittest-failure {
+ border: 1px solid grey;
+ border-radius: 5px;
+ padding: 5px;
+ }
+</style>
+
+<template id="x-base-interactive-test-runner-template">
+ <h1 id="title">Tests</h1>
+ <div id="stats"></div>
+ <div id="controls">
+ <ul id="links">
+ </ul>
+ <div style="clear: both;"></div>
+
+ <div>
+ <span>
+ <label>
+ <input type="radio" name="test-type-to-run" value="unit" />
+ Run unit tests
+ </label>
+ </span>
+ <span>
+ <label>
+ <input type="radio" name="test-type-to-run" value="perf" />
+ Run perf tests
+ </label>
+ </span>
+ <span>
+ <label>
+ <input type="radio" name="test-type-to-run" value="all" />
+ Run all tests
+ </label>
+ </span>
+ </div>
+ <span>
+ <label>
+ <input type="checkbox" id="short-format" /> Short format</label>
+ </span>
+ </div>
+ <div id="shortform-results">
+ </div>
+ <div id="results-container">
+ </div>
+</template>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b.unittest', function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+ const ALL_TEST_TYPES = 'all';
+
+ /**
+ * @constructor
+ */
+ const InteractiveTestRunner = tr.ui.b.define(
+ 'x-base-interactive-test-runner');
+
+ InteractiveTestRunner.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.allTests_ = undefined;
+
+ this.suppressStateChange_ = false;
+
+ this.testFilterString_ = '';
+ this.testTypeToRun_ = tr.b.unittest.TestTypes.UNITTEST;
+ this.shortFormat_ = false;
+ this.testSuiteName_ = '';
+
+ this.rerunPending_ = false;
+ this.runner_ = undefined;
+ this.results_ = undefined;
+ this.headless_ = false;
+
+ this.onResultsStatsChanged_ = this.onResultsStatsChanged_.bind(this);
+ this.onTestFailed_ = this.onTestFailed_.bind(this);
+ this.onTestFlaky_ = this.onTestFlaky_.bind(this);
+ this.onTestSkipped_ = this.onTestSkipped_.bind(this);
+ this.onTestPassed_ = this.onTestPassed_.bind(this);
+
+ Polymer.dom(this).appendChild(tr.ui.b.instantiateTemplate(
+ '#x-base-interactive-test-runner-template', THIS_DOC));
+
+ Polymer.dom(this).querySelector(
+ 'input[name=test-type-to-run][value=unit]').checked = true;
+ const testTypeToRunEls = Array.from(Polymer.dom(this).querySelectorAll(
+ 'input[name=test-type-to-run]'));
+
+ testTypeToRunEls.forEach(
+ function(inputEl) {
+ inputEl.addEventListener(
+ 'click', this.onTestTypeToRunClick_.bind(this));
+ }, this);
+
+ const shortFormatEl = Polymer.dom(this).querySelector('#short-format');
+ shortFormatEl.checked = this.shortFormat_;
+ shortFormatEl.addEventListener(
+ 'click', this.onShortFormatClick_.bind(this));
+ this.updateShortFormResultsDisplay_();
+
+ // Oh, DOM, how I love you. Title is such a convenient property name and I
+ // refuse to change my worldview because of tooltips.
+ this.__defineSetter__(
+ 'title',
+ function(title) {
+ Polymer.dom(Polymer.dom(this).querySelector('#title')).textContent =
+ title;
+ });
+ },
+
+ get allTests() {
+ return this.allTests_;
+ },
+
+ set allTests(allTests) {
+ this.allTests_ = allTests;
+ this.scheduleRerun_();
+ },
+
+ get testLinks() {
+ return this.testLinks_;
+ },
+ set testLinks(testLinks) {
+ this.testLinks_ = testLinks;
+ const linksEl = Polymer.dom(this).querySelector('#links');
+ Polymer.dom(linksEl).textContent = '';
+ this.testLinks_.forEach(function(l) {
+ const link = document.createElement('a');
+ link.href = l.linkPath;
+ Polymer.dom(link).textContent = l.title;
+
+ const li = document.createElement('li');
+ Polymer.dom(li).appendChild(link);
+
+ Polymer.dom(linksEl).appendChild(li);
+ }, this);
+ },
+
+ get testFilterString() {
+ return this.testFilterString_;
+ },
+
+ set testFilterString(testFilterString) {
+ this.testFilterString_ = testFilterString;
+ this.scheduleRerun_();
+ if (!this.suppressStateChange_) {
+ tr.b.dispatchSimpleEvent(this, 'statechange');
+ }
+ },
+
+ get shortFormat() {
+ return this.shortFormat_;
+ },
+
+ set shortFormat(shortFormat) {
+ this.shortFormat_ = shortFormat;
+ Polymer.dom(this).querySelector('#short-format').checked = shortFormat;
+ if (this.results_) {
+ this.results_.shortFormat = shortFormat;
+ }
+ if (!this.suppressStateChange_) {
+ tr.b.dispatchSimpleEvent(this, 'statechange');
+ }
+ },
+
+ onShortFormatClick_(e) {
+ this.shortFormat_ =
+ Polymer.dom(this).querySelector('#short-format').checked;
+ this.updateShortFormResultsDisplay_();
+ this.updateResultsGivenShortFormat_();
+ if (!this.suppressStateChange_) {
+ tr.b.dispatchSimpleEvent(this, 'statechange');
+ }
+ },
+
+ updateShortFormResultsDisplay_() {
+ const display = this.shortFormat_ ? '' : 'none';
+ Polymer.dom(this).querySelector('#shortform-results').style.display =
+ display;
+ },
+
+ updateResultsGivenShortFormat_() {
+ if (!this.results_) return;
+
+ if (this.testFilterString_.length || this.testSuiteName_.length) {
+ this.results_.showHTMLOutput = true;
+ } else {
+ this.results_.showHTMLOutput = false;
+ }
+ this.results_.showPendingAndPassedTests = this.shortFormat_;
+ },
+
+ get testTypeToRun() {
+ return this.testTypeToRun_;
+ },
+
+ set testTypeToRun(testTypeToRun) {
+ this.testTypeToRun_ = testTypeToRun;
+ let sel;
+ switch (testTypeToRun) {
+ case tr.b.unittest.TestTypes.UNITTEST:
+ sel = 'input[name=test-type-to-run][value=unit]';
+ break;
+ case tr.b.unittest.TestTypes.PERFTEST:
+ sel = 'input[name=test-type-to-run][value=perf]';
+ break;
+ case ALL_TEST_TYPES:
+ sel = 'input[name=test-type-to-run][value=all]';
+ break;
+ default:
+ throw new Error('Invalid test type to run: ' + testTypeToRun);
+ }
+ Polymer.dom(this).querySelector(sel).checked = true;
+ this.scheduleRerun_();
+ if (!this.suppressStateChange_) {
+ tr.b.dispatchSimpleEvent(this, 'statechange');
+ }
+ },
+
+ onTestTypeToRunClick_(e) {
+ switch (e.target.value) {
+ case 'unit':
+ this.testTypeToRun_ = tr.b.unittest.TestTypes.UNITTEST;
+ break;
+ case 'perf':
+ this.testTypeToRun_ = tr.b.unittest.TestTypes.PERFTEST;
+ break;
+ case 'all':
+ this.testTypeToRun_ = ALL_TEST_TYPES;
+ break;
+ default:
+ throw new Error('Inalid test type: ' + e.target.value);
+ }
+
+ this.scheduleRerun_();
+ if (!this.suppressStateChange_) {
+ tr.b.dispatchSimpleEvent(this, 'statechange');
+ }
+ },
+
+ onTestPassed_() {
+ Polymer.dom(Polymer.dom(this).querySelector('#shortform-results')).
+ appendChild(document.createTextNode('.'));
+ },
+
+ onTestFailed_() {
+ const span = document.createElement('span');
+ Polymer.dom(span).classList.add('fail');
+ Polymer.dom(span).appendChild(document.createTextNode('F'));
+ Polymer.dom(Polymer.dom(this).querySelector('#shortform-results'))
+ .appendChild(span);
+ },
+
+ onTestFlaky_() {
+ const span = document.createElement('span');
+ Polymer.dom(span).classList.add('flaky');
+ Polymer.dom(span).appendChild(document.createTextNode('~'));
+ Polymer.dom(Polymer.dom(this).querySelector('#shortform-results'))
+ .appendChild(span);
+ },
+
+ onTestSkipped_() {
+ const span = document.createElement('span');
+ Polymer.dom(span).classList.add('skipped');
+ Polymer.dom(span).appendChild(document.createTextNode('s'));
+ Polymer.dom(Polymer.dom(this).querySelector('#shortform-results'))
+ .appendChild(span);
+ },
+
+ onResultsStatsChanged_() {
+ const statsEl = Polymer.dom(this).querySelector('#stats');
+ const stats = this.results_.getStats();
+ const numTestsOverall = this.runner_.testCases.length;
+ const numTestsThatRan = stats.numTestsThatPassed +
+ stats.numTestsThatFailed +
+ stats.numFlakyTests +
+ stats.numSkippedTests;
+ Polymer.dom(statsEl).innerHTML =
+ '<span>' + numTestsThatRan + '/' + numTestsOverall +
+ '</span> tests run, ' +
+ '<span class="unittest-failed">' + stats.numTestsThatFailed +
+ '</span> failures, ' +
+ '<span class="unittest-flaky">' + stats.numFlakyTests +
+ '</span> flaky, ' +
+ '<span class="unittest-skipped">' + stats.numSkippedTests +
+ '</span> skipped, ' +
+ ' in ' + stats.totalRunTime.toFixed(2) + 'ms.';
+ },
+
+ scheduleRerun_() {
+ if (this.rerunPending_) return;
+ if (this.runner_) {
+ this.rerunPending_ = true;
+ this.runner_.beginToStopRunning();
+ const doRerun = function() {
+ this.rerunPending_ = false;
+ this.scheduleRerun_();
+ }.bind(this);
+ this.runner_.runCompletedPromise.then(
+ doRerun, doRerun);
+ return;
+ }
+ this.beginRunning_();
+ },
+
+ beginRunning_() {
+ const resultsContainer =
+ Polymer.dom(this).querySelector('#results-container');
+ if (this.results_) {
+ this.results_.removeEventListener('testpassed', this.onTestPassed_);
+ this.results_.removeEventListener('testfailed', this.onTestFailed_);
+ this.results_.removeEventListener('testflaky', this.onTestFlaky_);
+ this.results_.removeEventListener('testskipped', this.onTestSkipped_);
+ this.results_.removeEventListener('statschange',
+ this.onResultsStatsChanged_);
+ delete this.results_.getHRefForTestCase;
+ Polymer.dom(resultsContainer).removeChild(this.results_);
+ }
+
+ this.results_ = new tr.b.unittest.HTMLTestResults();
+ this.results_.headless = this.headless_;
+ this.results_.getHRefForTestCase = this.getHRefForTestCase.bind(this);
+ this.updateResultsGivenShortFormat_();
+
+ this.results_.shortFormat = this.shortFormat_;
+ this.results_.addEventListener('testpassed', this.onTestPassed_);
+ this.results_.addEventListener('testfailed', this.onTestFailed_);
+ this.results_.addEventListener('testflaky', this.onTestFlaky_);
+ this.results_.addEventListener('testskipped', this.onTestSkipped_);
+ this.results_.addEventListener('statschange',
+ this.onResultsStatsChanged_);
+ Polymer.dom(resultsContainer).appendChild(this.results_);
+
+ const tests = this.allTests_.filter(function(test) {
+ const i = test.fullyQualifiedName.indexOf(this.testFilterString_);
+ if (i === -1) return false;
+ if (this.testTypeToRun_ !== ALL_TEST_TYPES &&
+ test.testType !== this.testTypeToRun_) {
+ return false;
+ }
+ return true;
+ }, this);
+
+ this.runner_ = new tr.b.unittest.TestRunner(this.results_, tests);
+ this.runner_.beginRunning();
+
+ this.runner_.runCompletedPromise.then(
+ this.runCompleted_.bind(this),
+ this.runCompleted_.bind(this));
+ },
+
+ setState(state, opt_suppressStateChange) {
+ this.suppressStateChange_ = true;
+ if (state.testFilterString !== undefined) {
+ this.testFilterString = state.testFilterString;
+ } else {
+ this.testFilterString = '';
+ }
+
+ if (state.shortFormat === undefined) {
+ this.shortFormat = false;
+ } else {
+ this.shortFormat = state.shortFormat;
+ }
+
+ if (state.testTypeToRun === undefined) {
+ this.testTypeToRun = tr.b.unittest.TestTypes.UNITTEST;
+ } else {
+ this.testTypeToRun = state.testTypeToRun;
+ }
+
+ this.testSuiteName_ = state.testSuiteName || '';
+ this.headless_ = state.headless || false;
+
+ if (!opt_suppressStateChange) {
+ this.suppressStateChange_ = false;
+ }
+
+ this.onShortFormatClick_();
+ this.scheduleRerun_();
+ this.suppressStateChange_ = false;
+ },
+
+ getDefaultState() {
+ return {
+ testFilterString: '',
+ testSuiteName: '',
+ shortFormat: false,
+ testTypeToRun: tr.b.unittest.TestTypes.UNITTEST
+ };
+ },
+
+ getState() {
+ return {
+ testFilterString: this.testFilterString_,
+ testSuiteName: this.testSuiteName_,
+ shortFormat: this.shortFormat_,
+ testTypeToRun: this.testTypeToRun_
+ };
+ },
+
+ getHRefForTestCase(testCases) {
+ return undefined;
+ },
+
+ runCompleted_() {
+ this.runner_ = undefined;
+ }
+ };
+
+ function loadAndRunTests(runnerConfig) {
+ // The test runner no-ops pushState so keep it around.
+ const realWindowHistoryPushState = window.history.pushState.bind(
+ window.history);
+
+ function stateToSearchString(defaultState, state) {
+ const parts = [];
+ for (const k in state) {
+ if (state[k] === defaultState[k]) continue;
+ const v = state[k];
+ let kv;
+ if (v === true) {
+ kv = k;
+ } else if (v === false) {
+ kv = k + '=false';
+ } else if (v === '') {
+ continue;
+ } else {
+ kv = k + '=' + v;
+ }
+ parts.push(kv);
+ }
+ return parts.join('&');
+ }
+
+ function stateFromSearchString(string) {
+ const state = {};
+ string.split('&').forEach(function(part) {
+ if (part === '') return;
+ const kv = part.split('=');
+ let k;
+ let v;
+ if (kv.length === 1) {
+ k = kv[0];
+ v = true;
+ } else {
+ k = kv[0];
+ if (kv[1] === 'false') {
+ v = false;
+ } else {
+ v = kv[1];
+ }
+ }
+ state[k] = v;
+ });
+ return state;
+ }
+
+ function getSuiteRelpathsToLoad(state) {
+ if (state.testSuiteName) {
+ return new Promise(function(resolve) {
+ const parts = state.testSuiteName.split('.');
+ const testSuiteRelPath = '/' + parts.join('/') + '.html';
+
+ const suiteRelpathsToLoad = [testSuiteRelPath];
+ resolve(suiteRelpathsToLoad);
+ });
+ }
+ return runnerConfig.getAllSuiteRelPathsAsync();
+ }
+
+
+ function loadAndRunTestsImpl() {
+ const state = stateFromSearchString(
+ window.location.search.substring(1));
+ updateTitle(state);
+
+
+ showLoadingOverlay();
+
+ let loader;
+ let p = getSuiteRelpathsToLoad(state);
+ p = p.then(
+ function(suiteRelpathsToLoad) {
+ loader = new tr.b.unittest.SuiteLoader(suiteRelpathsToLoad);
+ return loader.allSuitesLoadedPromise;
+ },
+ function(e) {
+ hideLoadingOverlay();
+ throw e;
+ });
+ p = p.then(
+ function() {
+ hideLoadingOverlay();
+ // FIXME
+ window.addEventListener('WebComponentsReady', function() {
+ runTests(loader, state);
+ });
+ runTests(loader, state);
+ // Polymer.whenReady(function() {
+ // runTests(loader, state);
+ // });
+ },
+ function(err) {
+ hideLoadingOverlay();
+ tr.showPanic('Module loading failure', err);
+ throw err;
+ });
+ return p;
+ }
+
+ function showLoadingOverlay() {
+ const overlay = document.createElement('div');
+ overlay.id = 'tests-loading-overlay';
+ overlay.style.backgroundColor = 'white';
+ overlay.style.boxSizing = 'border-box';
+ overlay.style.color = 'black';
+ overlay.style.display = 'flex';
+ overlay.style.height = '100%';
+ overlay.style.left = 0;
+ overlay.style.padding = '8px';
+ overlay.style.position = 'fixed';
+ overlay.style.top = 0;
+ overlay.style.flexDirection = 'column';
+ overlay.style.width = '100%';
+
+ const element = document.createElement('div');
+ element.style.flex = '1 1 auto';
+ element.style.overflow = 'auto';
+ Polymer.dom(overlay).appendChild(element);
+
+ Polymer.dom(element).textContent = 'Loading tests...';
+ Polymer.dom(document.body).appendChild(overlay);
+ }
+ function hideLoadingOverlay() {
+ const overlay = Polymer.dom(document.body).querySelector(
+ '#tests-loading-overlay');
+ Polymer.dom(document.body).removeChild(overlay);
+ }
+
+ function updateTitle(state) {
+ const testFilterString = state.testFilterString || '';
+ const testSuiteName = state.testSuiteName || '';
+
+ let title;
+ if (testSuiteName && testFilterString.length) {
+ title = testFilterString + ' in ' + testSuiteName;
+ } else if (testSuiteName) {
+ title = testSuiteName;
+ } else if (testFilterString) {
+ title = testFilterString + ' in all tests';
+ } else {
+ title = runnerConfig.title;
+ }
+
+ if (state.shortFormat) title += '(s)';
+ document.title = title;
+ const runner = Polymer.dom(document).querySelector(
+ 'x-base-interactive-test-runner');
+ if (runner) runner.title = title;
+ }
+
+ function runTests(loader, state) {
+ const runner = new tr.b.unittest.InteractiveTestRunner();
+ runner.style.width = '100%';
+ runner.style.height = '100%';
+ runner.testLinks = runnerConfig.testLinks;
+ runner.allTests = loader.getAllTests();
+ Polymer.dom(document.body).appendChild(runner);
+
+ runner.setState(state);
+ updateTitle(state);
+
+ runner.addEventListener('statechange', function() {
+ const state = runner.getState();
+ const stateString = stateToSearchString(
+ runner.getDefaultState(), state);
+ if (window.location.search.substring(1) === stateString) return;
+
+ updateTitle(state);
+ let stateURL;
+ if (stateString.length > 0) {
+ stateURL = window.location.pathname + '?' + stateString;
+ } else {
+ stateURL = window.location.pathname;
+ }
+ realWindowHistoryPushState(state, document.title, stateURL);
+ });
+
+ window.addEventListener('popstate', function(state) {
+ runner.setState(state, true);
+ });
+
+ runner.getHRefForTestCase = function(testCase) {
+ const state = runner.getState();
+ if (state.testFilterString === '' &&
+ state.testSuiteName === '') {
+ state.testSuiteName = testCase.suite.name;
+ state.testFilterString = '';
+ state.shortFormat = false;
+ } else {
+ state.testSuiteName = testCase.suite.name;
+ state.testFilterString = testCase.name;
+ state.shortFormat = false;
+ }
+ const stateString = stateToSearchString(
+ runner.getDefaultState(), state);
+ if (stateString.length > 0) {
+ return window.location.pathname + '?' + stateString;
+ }
+ return window.location.pathname;
+ };
+ }
+
+ loadAndRunTestsImpl();
+ }
+
+ return {
+ InteractiveTestRunner,
+ loadAndRunTests,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html
new file mode 100644
index 00000000000..6c14bd5afbf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/suite_loader.html
@@ -0,0 +1,253 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/unittest/test_suite.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/base/xhr.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b.unittest', function() {
+ function HTMLImportsModuleLoader() {
+ }
+ HTMLImportsModuleLoader.prototype = {
+ loadModule(testRelpath, moduleName) {
+ return new Promise(function(resolve, reject) {
+ const importEl = document.createElement('link');
+ importEl.moduleName = moduleName;
+ Polymer.dom(importEl).setAttribute('rel', 'import');
+ Polymer.dom(importEl).setAttribute('href', testRelpath);
+
+ importEl.addEventListener('load', function() {
+ resolve({testRelpath,
+ moduleName});
+ });
+ importEl.addEventListener('error', function(e) {
+ reject('Error loading &#60;link rel="import" href="' +
+ testRelpath + '"');
+ });
+
+ Polymer.dom(tr.doc.head).appendChild(importEl);
+ });
+ },
+
+ getCurrentlyExecutingModuleName() {
+ if (!document.currentScript) {
+ throw new Error('Cannot call testSuite except during load.');
+ }
+ try {
+ throw new Error('');
+ } catch (e) {
+ const stack = e.stack.split('\n');
+ let url = stack[stack.length - 1].slice(7);
+ url = url.slice(0, url.lastIndexOf(':'));
+ url = url.slice(0, url.lastIndexOf(':')); // Yes, again.
+ return this.guessModuleNameFromURL_(url);
+ }
+ },
+
+ guessModuleNameFromURL_(url) {
+ const m = /.+?:\/\/.+?(\/.+)/.exec(url);
+ if (!m) {
+ throw new Error('Guessing module name failed');
+ }
+ const path = m[1];
+ if (path[0] !== '/') {
+ throw new Error('malformed path');
+ }
+ const i = path.indexOf('.html');
+ if (i < 0) {
+ throw new Error('Cannot define testSuites outside html imports');
+ }
+ return path.substring(1, i).split('/').join('.');
+ }
+ };
+
+ function HeadlessModuleLoader() {
+ this.currentlyExecutingModuleInfo_ = undefined;
+ }
+ HeadlessModuleLoader.prototype = {
+ loadModule(testRelpath, moduleName) {
+ return Promise.resolve().then(function() {
+ const moduleInfo = {
+ testRelpath,
+ moduleName
+ };
+ if (this.currentlyExecutingModuleInfo_ !== undefined) {
+ throw new Error('WAT');
+ }
+ this.currentlyExecutingModuleInfo_ = moduleInfo;
+
+ try {
+ loadHTML(testRelpath);
+ } catch (e) {
+ e.message = 'While loading ' + moduleName + ', ' + e.message;
+ e.stack = 'While loading ' + moduleName + ', ' + e.stack;
+ throw e;
+ } finally {
+ this.currentlyExecutingModuleInfo_ = undefined;
+ }
+
+ return moduleInfo;
+ }.bind(this));
+ },
+
+ getCurrentlyExecutingModuleName() {
+ if (this.currentlyExecutingModuleInfo_ === undefined) {
+ throw new Error('No currently loading module');
+ }
+ return this.currentlyExecutingModuleInfo_.moduleName;
+ }
+ };
+
+
+ function SuiteLoader(suiteRelpathsToLoad) {
+ tr.b.EventTarget.call(this);
+
+ this.currentModuleLoader_ = undefined;
+ this.testSuites = [];
+
+ if (tr.isHeadless) {
+ this.currentModuleLoader_ = new HeadlessModuleLoader();
+ } else {
+ this.currentModuleLoader_ = new HTMLImportsModuleLoader();
+ }
+
+ this.allSuitesLoadedPromise = this.beginLoadingModules_(
+ suiteRelpathsToLoad);
+ }
+
+ SuiteLoader.prototype = {
+ __proto__: tr.b.EventTarget.prototype,
+
+ beginLoadingModules_(testRelpaths) {
+ // Hooks!
+ this.bindGlobalHooks_();
+
+ // Load the modules.
+ const modulePromises = [];
+ for (let i = 0; i < testRelpaths.length; i++) {
+ const testRelpath = testRelpaths[i];
+ const moduleName = testRelpath.split('/').slice(-1)[0];
+
+ const p = this.currentModuleLoader_.loadModule(testRelpath, moduleName);
+ modulePromises.push(p);
+ }
+
+ const allModulesLoadedPromise = new Promise(function(resolve, reject) {
+ let remaining = modulePromises.length;
+ let resolved = false;
+ function oneMoreLoaded() {
+ if (resolved) return;
+ remaining--;
+ if (remaining > 0) return;
+ resolved = true;
+ resolve();
+ }
+
+ function oneRejected(e) {
+ if (resolved) return;
+ resolved = true;
+ reject(e);
+ }
+
+ modulePromises.forEach(function(modulePromise) {
+ modulePromise.then(oneMoreLoaded, oneRejected);
+ });
+ });
+
+ // Script errors errors abort load;
+ const scriptErrorPromise = new Promise(function(xresolve, xreject) {
+ this.scriptErrorPromiseResolver_ = {
+ resolve: xresolve,
+ reject: xreject
+ };
+ }.bind(this));
+ const donePromise = Promise.race([
+ allModulesLoadedPromise,
+ scriptErrorPromise
+ ]);
+
+ // Cleanup.
+ return donePromise.then(
+ function() {
+ this.scriptErrorPromiseResolver_ = undefined;
+ this.unbindGlobalHooks_();
+ }.bind(this),
+ function(e) {
+ this.scriptErrorPromiseResolver_ = undefined;
+ this.unbindGlobalHooks_();
+ throw e;
+ }.bind(this));
+ },
+
+ bindGlobalHooks_() {
+ if (global._currentSuiteLoader !== undefined) {
+ throw new Error('A suite loader exists already');
+ }
+ global._currentSuiteLoader = this;
+
+ this.oldGlobalOnError_ = global.onerror;
+ global.onerror = function(errorMsg, url, lineNumber) {
+ this.scriptErrorPromiseResolver_.reject(
+ new Error(errorMsg + '\n' + url + ':' + lineNumber));
+ if (this.oldGlobalOnError_) {
+ return this.oldGlobalOnError_(errorMsg, url, lineNumber);
+ }
+ return false;
+ }.bind(this);
+ },
+
+ unbindGlobalHooks_() {
+ global._currentSuiteLoader = undefined;
+
+ global.onerror = this.oldGlobalOnError_;
+ this.oldGlobalOnError_ = undefined;
+ },
+
+ constructAndRegisterTestSuite(suiteConstructor) {
+ const name = this.currentModuleLoader_.getCurrentlyExecutingModuleName();
+
+ const testSuite = new tr.b.unittest.TestSuite(
+ name, suiteConstructor);
+
+ this.testSuites.push(testSuite);
+
+ const e = new tr.b.Event('suite-loaded');
+ e.testSuite = testSuite;
+ this.dispatchEvent(e);
+ },
+
+ getAllTests() {
+ const tests = [];
+ this.testSuites.forEach(function(suite) {
+ tests.push.apply(tests, suite.tests);
+ });
+ return tests;
+ },
+
+ findTestWithFullyQualifiedName(fullyQualifiedName) {
+ for (let i = 0; i < this.testSuites.length; i++) {
+ const suite = this.testSuites[i];
+ for (let j = 0; j < suite.tests.length; j++) {
+ const test = suite.tests[j];
+ if (test.fullyQualifiedName === fullyQualifiedName) return test;
+ }
+ }
+ throw new Error('Test ' + fullyQualifiedName +
+ 'not found amongst ' + this.testSuites.length);
+ }
+ };
+
+ return {
+ SuiteLoader,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/test_case.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_case.html
new file mode 100644
index 00000000000..1a626608ce4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_case.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/unittest/constants.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b.unittest', function() {
+ const TestTypes = tr.b.unittest.TestTypes;
+
+ function TestCase(name, opt_testFn, opt_options) {
+ if (!name) {
+ throw new Error('Name must be provided');
+ }
+ this.guid_ = tr.b.GUID.allocateSimple();
+ this.suite_ = undefined; // Set by TestSuite.addTest.
+ this.name_ = name;
+
+ if (opt_options) {
+ this.options_ = opt_options;
+ } else {
+ this.options_ = {};
+ }
+
+ this.testFn_ = opt_testFn;
+ }
+
+ TestCase.parseFullyQualifiedName = function(fqn) {
+ const i = fqn.lastIndexOf('.');
+ if (i === -1) {
+ throw new Error('FullyQualifiedNames must have a period in them');
+ }
+ return {
+ suiteName: fqn.substr(0, i),
+ testCaseName: fqn.substr(i + 1)
+ };
+ };
+
+ TestCase.prototype = {
+ __proto__: Object.prototype,
+
+ get guid() {
+ return this.guid_;
+ },
+
+ get suite() {
+ return this.suite_;
+ },
+
+ set suite(suite) {
+ if (this.suite_ !== undefined) {
+ throw new Error('Suite can only be assigned once.');
+ }
+ this.suite_ = suite;
+ },
+
+ get testType() {
+ return TestTypes.UNITTEST;
+ },
+
+ get name() {
+ return this.name_;
+ },
+
+ get fullyQualifiedName() {
+ return this.suite_.name + '.' + this.name_;
+ },
+
+ get options() {
+ return this.options_;
+ },
+
+ setUp() {
+ if (this.options_.setUp) {
+ this.options_.setUp.call(this);
+ }
+ },
+
+ run(htmlHook) {
+ return this.testFn_();
+ },
+
+ tearDown() {
+ if (this.options_.tearDown) {
+ this.options_.tearDown.call(this);
+ }
+ },
+
+ // TODO(nduca): The routing of this is a bit awkward. Probably better
+ // to install a global function.
+ addHTMLOutput(element) {
+ tr.b.unittest.addHTMLOutputForCurrentTest(element);
+ }
+ };
+
+ function PerfTestCase(name, testFn, opt_options) {
+ TestCase.call(this, name, testFn, opt_options);
+ this.iterations = this.options.iterations || 10;
+ }
+
+ PerfTestCase.prototype = {
+ __proto__: TestCase.prototype,
+
+ get testType() {
+ return TestTypes.PERFTEST;
+ },
+
+ run() {
+ const durations = [];
+ const iterations = this.iterations;
+ for (let i = 0; i < iterations; ++i) {
+ const start = window.performance.now();
+ this.runOneIteration();
+ const duration = window.performance.now() - start;
+ durations.push(duration);
+ }
+
+ const durationStrings = durations.map(function(d) {
+ return d.toFixed(2) + 'ms';
+ });
+ const average = tr.b.math.Statistics.mean(durations);
+ const min = tr.b.math.Statistics.min(durations);
+
+ let summaryString = ' [';
+ summaryString += 'min ' + min.toFixed(2) + 'ms, ';
+ summaryString += 'avg ' + average.toFixed(2) + 'ms';
+ summaryString += ']';
+
+ return durationStrings.join(', ') + summaryString;
+ },
+
+ runOneIteration() {
+ this.testFn_();
+ }
+ };
+
+ return {
+ TestCase,
+ PerfTestCase,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/test_case_test.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_case_test.html
new file mode 100644
index 00000000000..c738b66bbbc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_case_test.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/unittest/test_case.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('parseFullyQualifiedName', function() {
+ const p = tr.b.unittest.TestCase.parseFullyQualifiedName('foo.bar');
+ assert.strictEqual(p.suiteName, 'foo');
+ assert.strictEqual(p.testCaseName, 'bar');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/test_runner.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_runner.html
new file mode 100644
index 00000000000..adcbdcca80e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_runner.html
@@ -0,0 +1,285 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/timing.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.b.unittest', function() {
+ let realTvOnAnimationFrameError;
+ let realGlobalOnError;
+ let realGlobalHistoryPushState;
+
+ const NUM_TESTS_PER_RIC = 16;
+
+ function installGlobalTestHooks(runner) {
+ realTvOnAnimationFrameError = tr.b.onAnimationFrameError;
+ tr.b.onAnimationFrameError = function(error) {
+ runner.results.addErrorForCurrentTest(error);
+ };
+
+ if (tr.isExported('global.onerror')) {
+ realGlobalOnError = global.onerror;
+ global.onerror = function(errorMsg, url, lineNumber) {
+ runner.results.addErrorForCurrentTest(
+ errorMsg + ' at ' + url + ':' + lineNumber);
+ if (realGlobalOnError) {
+ return realGlobalOnError(errorMsg, url, lineNumber);
+ }
+ return false;
+ };
+ }
+
+ if (tr.isExported('global.history')) {
+ realGlobalHistoryPushState = global.history.pushState;
+ global.history.pushState = function() {
+ };
+ }
+
+ tr.b.unittest.addHTMLOutputForCurrentTest = function(element) {
+ runner.results.addHTMLOutputForCurrentTest(element);
+ };
+
+ if (tr.isExported('global.sessionStorage')) {
+ global.sessionStorage.clear();
+ }
+
+ const e = new tr.b.Event('tr-unittest-will-run');
+ TestRunner.dispatchEvent(e);
+ }
+
+ function uninstallGlobalTestHooks() {
+ if (tr.isExported('global.onerror')) {
+ global.onerror = realGlobalOnError;
+ realGlobalOnError = undefined;
+ }
+
+ tr.b.onAnimationFrameError = realTvOnAnimationFrameError;
+ realTvOnAnimationFrameError = undefined;
+
+ if (tr.isExported('global.history')) {
+ global.history.pushState = realGlobalHistoryPushState;
+ realGlobalHistoryPushState = undefined;
+ }
+
+ tr.b.unittest.addHTMLOutputForCurrentTest = undefined;
+ }
+
+
+ function TestRunner(results, testCases) {
+ this.results_ = results;
+ this.testCases_ = testCases;
+ this.pendingTestCases_ = [];
+
+ this.runOneTestCaseScheduled_ = false;
+ this.numRunsSinceLastRIC_ = 0;
+
+ this.runCompletedPromise = undefined;
+ this.runCompletedResolver_ = undefined;
+
+ this.currentTestCase_ = undefined;
+ }
+
+ TestRunner.prototype = {
+ __proto__: Object.prototype,
+
+ beginRunning() {
+ if (this.pendingTestCases_.length) {
+ throw new Error('Tests still running!');
+ }
+
+ this.runCompletedPromise = new Promise(function(resolve, reject) {
+ this.runCompletedResolver_ = {
+ resolve,
+ reject
+ };
+ }.bind(this));
+
+ this.pendingTestCases_ = this.testCases_.slice(0);
+
+ this.results_.willRunTests(this.pendingTestCases_);
+
+ this.scheduleRunOneTestCase_();
+
+ return this.runCompletedPromise;
+ },
+
+ beginToStopRunning() {
+ if (!this.runCompletedResolver_) {
+ throw new Error('Still running');
+ }
+ this.pendingTestCases_ = [];
+ return this.runCompletedPromise;
+ },
+
+ get testCases() {
+ return this.testCases_;
+ },
+
+ get results() {
+ return this.results_;
+ },
+
+ scheduleRunOneTestCase_() {
+ if (this.runOneTestCaseScheduled_) return;
+ this.runOneTestCaseScheduled_ = true;
+
+ this.numRunsSinceLastRIC_++;
+ if (this.numRunsSinceLastRIC_ === NUM_TESTS_PER_RIC) {
+ this.numRunsSinceLastRIC_ = 0;
+ tr.b.idle().then(() => this.runOneTestCase_());
+ } else {
+ Promise.resolve().then(() => this.runOneTestCase_());
+ }
+ },
+
+ runOneTestCase_() {
+ this.runOneTestCaseScheduled_ = false;
+
+ if (this.pendingTestCases_.length === 0) {
+ this.didFinishRunningAllTests_();
+ return;
+ }
+
+ this.currentTestCase_ = this.pendingTestCases_.splice(0, 1)[0];
+ this.currentMark_ = tr.b.Timing.mark(
+ 'TestRunner', this.currentTestCase_.name);
+ this.results_.willRunTest(this.currentTestCase_);
+
+ if (this.isCurrentTestSkipped_()) {
+ this.results_.setCurrentTestSkipped();
+ this.results_.didCurrentTestEnd();
+ this.currentMark_.end();
+ this.currentTestCase_ = undefined;
+ this.scheduleRunOneTestCase_();
+ return;
+ }
+
+ if (this.isCurrentTestFlaky_()) {
+ this.results_.setCurrentTestFlaky();
+ this.results_.didCurrentTestEnd();
+ this.currentMark_.end();
+ this.currentTestCase_ = undefined;
+ this.scheduleRunOneTestCase_();
+ return;
+ }
+
+ if (!this.setUpCurrentTestCase_()) {
+ this.results_.didCurrentTestEnd();
+ this.currentMark_.end();
+ this.currentTestCase_ = undefined;
+ this.scheduleRunOneTestCase_();
+ return;
+ }
+
+ this.runCurrentTestCase_().then(
+ function pass(result) {
+ try {
+ this.tearDownCurrentTestCase_(true);
+ if (result) {
+ this.results_.setReturnValueFromCurrentTest(result);
+ }
+ this.results_.didCurrentTestEnd();
+ this.currentMark_.end();
+ this.currentTestCase_ = undefined;
+ this.scheduleRunOneTestCase_();
+ } catch (e) {
+ this.hadInternalError_(e);
+ throw e;
+ }
+ }.bind(this),
+ function fail(error) {
+ try {
+ this.results_.addErrorForCurrentTest(error);
+ this.tearDownCurrentTestCase_(false);
+ this.results_.didCurrentTestEnd();
+ this.currentMark_.end();
+ this.currentTestCase_ = undefined;
+ this.scheduleRunOneTestCase_();
+ } catch (e) {
+ this.hadInternalError_(e);
+ throw e;
+ }
+ }.bind(this));
+ },
+
+ isCurrentTestFlaky_() {
+ return !!this.currentTestCase_.options.flaky;
+ },
+
+ isCurrentTestSkipped_() {
+ return !!this.currentTestCase_.options.skipped;
+ },
+
+ setUpCurrentTestCase_() {
+ // Try setting it up. Return true if succeeded.
+ installGlobalTestHooks(this);
+ try {
+ this.currentTestCase_.setUp();
+ } catch (error) {
+ this.results_.addErrorForCurrentTest(error);
+ return false;
+ }
+ return true;
+ },
+
+ runCurrentTestCase_() {
+ return new Promise(function(resolve, reject) {
+ let maybePromise;
+ try {
+ maybePromise = this.currentTestCase_.run();
+ } catch (error) {
+ reject(error);
+ return;
+ }
+
+ if (maybePromise !== undefined && maybePromise.then) {
+ maybePromise.then(
+ function(result) {
+ resolve(result);
+ },
+ function(error) {
+ reject(error);
+ });
+ } else {
+ resolve(maybePromise);
+ }
+ }.bind(this));
+ },
+
+ hadInternalError_(outerE) {
+ this.results.didRunTests();
+
+ this.runCompletedResolver_.reject(outerE);
+ this.runCompletedResolver_ = undefined;
+ },
+
+ tearDownCurrentTestCase_() {
+ try {
+ this.currentTestCase_.tearDown();
+ } catch (error) {
+ this.results_.addErrorForCurrentTest(error);
+ }
+
+ uninstallGlobalTestHooks();
+ },
+
+ didFinishRunningAllTests_() {
+ this.results.didRunTests();
+ this.runCompletedResolver_.resolve();
+ this.runCompletedResolver_ = undefined;
+ }
+ };
+
+ tr.b.EventTarget.decorate(TestRunner);
+
+ return {
+ TestRunner,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html
new file mode 100644
index 00000000000..237403fbf05
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/test_suite.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unittest/constants.html">
+<link rel="import" href="/tracing/base/unittest/test_case.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b.unittest', function() {
+ const TestCase = tr.b.unittest.TestCase;
+ const PerfTestCase = tr.b.unittest.PerfTestCase;
+
+ const TestTypes = tr.b.unittest.TestTypes;
+
+ function TestSuite(name, suiteConstructor) {
+ this.guid = tr.b.GUID.allocateSimple();
+ this.name_ = name;
+ this.tests_ = [];
+ this.testNames_ = {}; // For dupe checking.
+
+ global.flakyTest = function(testCaseOrName, opt_testFn, opt_options) {
+ if (testCaseOrName instanceof TestCase) {
+ testCaseOrName.options.flaky = true;
+ test(testCaseOrName);
+ } else {
+ const options = Object.assign({}, opt_options || {});
+ options.flaky = true;
+ test(testCaseOrName, opt_testFn, options);
+ }
+ }.bind(this);
+
+ global.test = function(testCaseOrName, opt_testFn, opt_options) {
+ if (testCaseOrName instanceof TestCase) {
+ if (opt_testFn !== undefined) {
+ throw new Error('opt_testFn cannot be given when giving a TestCase');
+ }
+ if (opt_options !== undefined) {
+ throw new Error('opt_options cannot be given when giving a TestCase');
+ }
+ this.addTest(testCaseOrName);
+ return;
+ }
+
+ let testName = testCaseOrName;
+ const testFn = opt_testFn;
+ const options = opt_options || {};
+ if (testFn === undefined) {
+ throw new Error('Must provide opt_testFn');
+ }
+
+ // If the test cares about DPI settings then we first push a test
+ // that fakes the DPI as the low or hi Dpi version, depending on what
+ // we're current using.
+ if (options.dpiAware) {
+ const defaultDevicePixelRatio = window.devicePixelRatio;
+ const dpi = defaultDevicePixelRatio > 1 ? 1 : 2;
+
+ const testWrapper = function() {
+ window.devicePixelRatio = dpi;
+ try {
+ testFn.bind(this).call();
+ } finally {
+ window.devicePixelRatio = defaultDevicePixelRatio;
+ }
+ };
+
+ let newName = name;
+ if (dpi === 1) {
+ newName += '_loDPI';
+ testName += '_hiDPI';
+ } else {
+ newName += '_hiDPI';
+ testName += '_loDPI';
+ }
+
+ this.addTest(new TestCase(newName,
+ testWrapper, options || {}));
+ }
+
+ this.addTest(new TestCase(testName,
+ testFn, options || {}));
+ }.bind(this);
+
+ global.timedPerfTest = function(name, testFn, options) {
+ if (options === undefined || options.iterations === undefined) {
+ throw new Error('timedPerfTest must have iteration option provided.');
+ }
+ this.addTest(new PerfTestCase(name, testFn, options));
+ }.bind(this);
+
+ try {
+ suiteConstructor.call();
+ } finally {
+ global.test = undefined;
+ global.timedPerfTest = undefined;
+ }
+ }
+
+ TestSuite.prototype = {
+ __proto__: Object.prototype,
+
+ get tests() {
+ return this.tests_;
+ },
+
+ addTest(test) {
+ if (test.suite !== undefined) {
+ throw new Error('Test suite is already assigned');
+ }
+ if (this.testNames_[test.name] !== undefined) {
+ throw new Error('Test name already used');
+ }
+ test.suite = this;
+ this.testNames_[test.name] = true;
+ this.tests_.push(test);
+ },
+
+ get name() {
+ return this.name_;
+ }
+ };
+
+ function testSuite(suiteConstructor) {
+ if (!global._currentSuiteLoader) {
+ throw new Error('testSuites can only be defined during suite loading');
+ }
+ global._currentSuiteLoader.constructAndRegisterTestSuite(suiteConstructor);
+ }
+
+ return {
+ TestSuite,
+ testSuite,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest/text_test_results.html b/chromium/third_party/catapult/tracing/tracing/base/unittest/text_test_results.html
new file mode 100644
index 00000000000..0bececfcd60
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest/text_test_results.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/unittest/constants.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+tr.exportTo('tr.b.unittest', function() {
+ /**
+ * @constructor
+ */
+ function TextTestResults() {
+ this.numTestsThatPassed_ = 0;
+ this.numTestsThatFailed_ = 0;
+ this.numFlakyTests_ = 0;
+ this.numSkippedTests_ = 0;
+ this.currentTestCaseHadErrors_ = false;
+ this.currentTestIsFlaky_ = false;
+ this.currentTestIsSkipped_ = false;
+ }
+
+ TextTestResults.prototype = {
+ get numTestsThatRan() {
+ return this.numTestsThatPassed_ + this.numTestsThatFailed_ +
+ this.numFlakyTests_ + this.numSkippedTests_;
+ },
+
+ get numTestsThatFailed() {
+ return this.numTestsThatFailed_;
+ },
+
+ get numTestsThatPassed() {
+ return this.numTestsThatPassed_;
+ },
+
+ get numFlakyTests() {
+ return this.numFlakyTests_;
+ },
+
+ get numSkippedTests() {
+ return this.numSkippedTests_;
+ },
+
+ willRunTests(testCases) {
+ },
+
+ willRunTest(testCase) {
+ this.write_(testCase.name + ' (' + testCase.suite.name + ') ... ');
+ this.currentTestCaseHadErrors_ = false;
+ this.currentTestIsFlaky_ = false;
+ this.currentTestIsSkipped_ = false;
+ },
+
+ addErrorForCurrentTest(error) {
+ if (!this.currentTestCaseHadErrors_) this.write_('FAIL\n');
+ const normalizedException = tr.b.normalizeException(error);
+ this.write_(normalizedException.stack + '\n');
+ this.currentTestCaseHadErrors_ = true;
+ },
+
+ addHTMLOutputForCurrentTest(element) {
+ this.curHTMLOutput_.push(element);
+ },
+
+ setCurrentTestFlaky() {
+ if (!this.currentTestIsFlaky_) this.write_('FLAKY\n');
+ this.currentTestIsFlaky_ = true;
+ },
+
+ setCurrentTestSkipped() {
+ if (!this.currentTestIsSkipped_) this.write_('SKIPPED\n');
+ this.currentTestIsSkipped_ = true;
+ },
+
+ setReturnValueFromCurrentTest(returnValue) {
+ this.write_('[RESULT] ' + JSON.stringify(returnValue) + '\n');
+ },
+
+ didCurrentTestEnd() {
+ if (this.currentTestCaseHadErrors_) {
+ this.numTestsThatFailed_ += 1;
+ } else if (this.currentTestIsFlaky_) {
+ this.numFlakyTests_ += 1;
+ } else if (this.currentTestIsSkipped_) {
+ this.numSkippedTests_ += 1;
+ } else {
+ this.numTestsThatPassed_ += 1;
+ this.write_('ok\n');
+ }
+ },
+
+ didRunTests() {
+ this.write_('\n------------------------------------------------------' +
+ '----------------\n');
+ if (this.numTestsThatRan === 1) {
+ this.write_('Ran 1 test\n');
+ } else {
+ this.write_('Ran ' + this.numTestsThatRan + ' tests\n');
+ }
+
+ const errorString = 'errors=' + this.numTestsThatFailed;
+ const flakyString = 'flaky=' + this.numFlakyTests;
+ const skippedString = 'skipped=' + this.numSkippedTests;
+ const messages = [];
+ if (this.numTestsThatFailed > 0) messages.push(errorString);
+ if (this.numFlakyTests > 0) messages.push(flakyString);
+ if (this.numSkippedTests > 0) messages.push(skippedString);
+ let details = '';
+ if (messages.length > 0) {
+ details += ' (' + messages.join(' ') + ')';
+ }
+
+ if (this.numTestsThatFailed > 0) {
+ this.write_('\nFAILED' + details);
+ } else {
+ this.write_('\nOK' + details);
+ }
+ },
+
+ write_(msg) {
+ if (tr.isVinn) {
+ global.write(msg);
+ } else {
+ console.log(msg);
+ }
+ }
+ };
+
+ return {
+ TextTestResults,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/unittest_test.html b/chromium/third_party/catapult/tracing/tracing/base/unittest_test.html
new file mode 100644
index 00000000000..553a804b4a6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/unittest_test.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/unittest.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('promise', function() {
+ return new Promise(function(resolve, reject) {
+ resolve();
+ });
+ });
+
+ test('async', function() {
+ return new Promise(function(resolve) {
+ tr.b.requestAnimationFrame(function() {
+ resolve();
+ });
+ });
+ });
+
+ test('assert_equal_is_forbidden', function() {
+ assert.throws(() => assert.equal(0, '0'));
+ });
+
+ /* To test failures remove comments
+ test('fail', function() {
+ assert.strictEqual(true, false);
+ });
+
+ test('rejected-promise', function() {
+ return new Promise(function(resolve, reject){
+ reject("Failure by rejection");
+ });
+ });
+
+ test('promise-that-throws-after-resolver', function() {
+ return new Promise(function(resolve, rejet){
+ throw new Error('blah');
+ });
+ });
+
+ */
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/url_json.html b/chromium/third_party/catapult/tracing/tracing/base/url_json.html
new file mode 100644
index 00000000000..c1b014e3d1c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/url_json.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.b', function() {
+ function encodeString(s) {
+ return encodeURIComponent(s).replace(/[(-.)]/, c =>
+ '%' + c.charCodeAt(0).toString(16));
+ }
+
+ function encodeStrings(dict) {
+ if (dict instanceof Array || !(dict instanceof Object)) {
+ throw new Error(
+ 'UrlJson only supports dictionaries of strings.');
+ }
+
+ const result = {};
+ for (const [key, value] of Object.entries(dict)) {
+ if ((value instanceof Array || !(value instanceof Object)) &&
+ typeof(value) !== 'string') {
+ throw new Error(
+ 'UrlJson only supports strings and dictionaries of strings.');
+ }
+
+ if (value instanceof Object) {
+ result[encodeString(key)] = encodeStrings(value);
+ } else {
+ result[encodeString(key)] = encodeString(value);
+ }
+ }
+ return result;
+ }
+
+ function decodeStrings(dict) {
+ const result = {};
+ for (const [key, value] of Object.entries(dict)) {
+ if (value instanceof Object) {
+ result[decodeURIComponent(key)] = decodeStrings(value);
+ } else if (typeof(value) === 'string') {
+ result[decodeURIComponent(key)] = decodeURIComponent(value);
+ } else {
+ throw new Error(
+ 'UrlJson only supports strings and dictionaries of strings.');
+ }
+ }
+ return result;
+ }
+
+ /*
+ * This implements a subset of JSON in a compact URL-safe format.
+ * Only strings and dictionaries of strings are supported.
+ * Numbers, arrays, booleans, and null are not supported.
+ * Instead of using url-unsafe characters {":,}
+ * This format uses url-safe characters (-.)
+ * If strings contain those characters, they will be URI-encoded like other
+ * url-unsafe characters.
+ * For example, the following object would be encoded as the following
+ * UrlJson:
+ * {"abc": {"def": "ghi", "jkl": "mno"}, "pqr": "stu"}
+ * abc-(def-ghi.jkl-mno).pqr-stu
+ */
+ class UrlJson {
+ static stringify(dict) {
+ dict = encodeStrings(dict);
+ const str = JSON.stringify(dict);
+ return str.slice(1, str.length - 1)
+ .replace(/{/g, '(')
+ .replace(/}/g, ')')
+ .replace(/ /g, '')
+ .replace(/"/g, '')
+ .replace(/,/g, '.')
+ .replace(/:/g, '-');
+ }
+
+ static parse(str) {
+ if (str === '') return {};
+ str = ('{"' + str + '"}')
+ .replace(/-\(/g, '": {"')
+ .replace(/-/g, '": "')
+ .replace(/\(/g, '{"')
+ .replace(/\)/g, '"}')
+ .replace(/}"/g, '}')
+ .replace(/\./g, '", "');
+ return decodeStrings(JSON.parse(str));
+ }
+ }
+
+ return {
+ UrlJson,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/url_json_test.html b/chromium/third_party/catapult/tracing/tracing/base/url_json_test.html
new file mode 100644
index 00000000000..8dccd0613e4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/url_json_test.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/url_json.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ function urlJson2Json(s) {
+ return JSON.stringify(tr.b.UrlJson.parse(s));
+ }
+
+ test('stringifyInvalid', function() {
+ assert.throws(() => tr.b.UrlJson.stringify([]));
+ assert.throws(() => tr.b.UrlJson.stringify(0));
+ assert.throws(() => tr.b.UrlJson.stringify(null));
+ assert.throws(() => tr.b.UrlJson.stringify(true));
+ assert.throws(() => tr.b.UrlJson.stringify(false));
+ assert.throws(() => tr.b.UrlJson.stringify({a: []}));
+ assert.throws(() => tr.b.UrlJson.stringify({a: 0}));
+ assert.throws(() => tr.b.UrlJson.stringify({a: null}));
+ assert.throws(() => tr.b.UrlJson.stringify({a: true}));
+ assert.throws(() => tr.b.UrlJson.stringify({a: false}));
+ });
+
+ test('stringify', function() {
+ assert.strictEqual('', tr.b.UrlJson.stringify({}));
+ assert.strictEqual('a-', tr.b.UrlJson.stringify({a: ''}));
+ assert.strictEqual('a-0', tr.b.UrlJson.stringify({a: '0'}));
+ assert.strictEqual('a-%25', tr.b.UrlJson.stringify({a: '%'}));
+ assert.strictEqual('a-(b-)', tr.b.UrlJson.stringify({a: {b: ''}}));
+ assert.strictEqual('a-.b-', tr.b.UrlJson.stringify({a: '', b: ''}));
+ });
+
+ test('parse', function() {
+ assert.strictEqual('{}', urlJson2Json(''));
+ assert.strictEqual('{"a":""}', urlJson2Json('a-'));
+ assert.strictEqual('{"a":"0"}', urlJson2Json('a-0'));
+ assert.strictEqual('{"a":"%"}', urlJson2Json('a-%25'));
+ assert.strictEqual('{"a":{"b":""}}', urlJson2Json('a-(b-)'));
+ assert.strictEqual('{"a":"","b":""}', urlJson2Json('a-.b-'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/utils.html b/chromium/third_party/catapult/tracing/tracing/base/utils.html
new file mode 100644
index 00000000000..0bbce55a277
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/utils.html
@@ -0,0 +1,652 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ const URL_REGEX = /^(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b|file:\/\/)([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/; // eslint-disable-line max-len
+
+ function deepCopy(value) {
+ if (!(value instanceof Object)) {
+ if (value === undefined || value === null) return value;
+ if (typeof value === 'string') return value.substring();
+ if (typeof value === 'boolean') return value;
+ if (typeof value === 'number') return value;
+ throw new Error('Unrecognized: ' + typeof value);
+ }
+
+ const object = value;
+ if (object instanceof Array) {
+ const res = new Array(object.length);
+ for (let i = 0; i < object.length; i++) {
+ res[i] = deepCopy(object[i]);
+ }
+ return res;
+ }
+
+ if (object.__proto__ !== Object.prototype) {
+ throw new Error('Can only clone simple types');
+ }
+ const res = {};
+ for (const key in object) {
+ res[key] = deepCopy(object[key]);
+ }
+ return res;
+ }
+
+ function normalizeException(e) {
+ if (e === undefined || e === null) {
+ return {
+ typeName: 'UndefinedError',
+ message: 'Unknown: null or undefined exception',
+ stack: 'Unknown'
+ };
+ }
+
+ if (typeof(e) === 'string') {
+ return {
+ typeName: 'StringError',
+ message: e,
+ stack: [e]
+ };
+ }
+
+ let typeName;
+ if (e.name) {
+ typeName = e.name;
+ } else if (e.constructor) {
+ if (e.constructor.name) {
+ typeName = e.constructor.name;
+ } else {
+ typeName = 'AnonymousError';
+ }
+ } else {
+ typeName = 'ErrorWithNoConstructor';
+ }
+
+ const msg = e.message ? e.message : 'Unknown';
+ return {
+ typeName,
+ message: msg,
+ stack: e.stack ? e.stack : [msg]
+ };
+ }
+
+ function stackTraceAsString() {
+ return new Error().stack + '';
+ }
+ function stackTrace() {
+ let stack = stackTraceAsString();
+ stack = stack.split('\n');
+ return stack.slice(2);
+ }
+
+ function getUsingPath(path, fromDict) {
+ const parts = path.split('.');
+ let cur = fromDict;
+
+ for (let part; parts.length && (part = parts.shift());) {
+ if (!parts.length) {
+ return cur[part];
+ } else if (part in cur) {
+ cur = cur[part];
+ } else {
+ return undefined;
+ }
+ }
+ return undefined;
+ }
+
+ /**
+ * Format date as a string "YYYY-MM-DD HH:mm:ss". The timezone is implicitly
+ * UTC. This format is based on the ISO format, but without milliseconds and
+ * the 'T' is replaced with a space for legibility.
+ *
+ * @param {!Date} date
+ * @return {string}
+ */
+ function formatDate(date) {
+ return date.toISOString().replace('T', ' ').slice(0, 19);
+ }
+
+ /**
+ * Infinity and NaN are left out of JSON for security reasons that do not
+ * apply to our use cases. This helper function allows serializing them
+ * independently of null.
+ *
+ * @param {!number} n
+ * @return {!(number|string)}
+ */
+ function numberToJson(n) {
+ if (isNaN(n)) return 'NaN';
+ if (n === Infinity) return 'Infinity';
+ if (n === -Infinity) return '-Infinity';
+ return n;
+ }
+
+ /**
+ * Infinity and NaN are left out of JSON for security reasons that do not
+ * apply to our use cases. This helper function allows deserializing them
+ * independently of null.
+ *
+ * @param {!(number|string)} n
+ * @return {!number}
+ */
+ function numberFromJson(n) {
+ if (n === 'NaN' || n === null) return NaN;
+ if (n === 'Infinity') return Infinity;
+ if (n === '-Infinity') return -Infinity;
+ return n;
+ }
+
+ /**
+ * @param {Array.<T>} ary
+ * @returns {Array.<Object.<T, number>>} The run length encoding of the array
+ * as an array of {value, count} objects.
+ * @template T
+ */
+ function runLengthEncoding(ary) {
+ const encodedArray = [];
+ for (const element of ary) {
+ if (encodedArray.length === 0 ||
+ encodedArray[encodedArray.length - 1].value !== element) {
+ encodedArray.push({
+ value: element,
+ count: 1,
+ });
+ } else {
+ encodedArray[encodedArray.length - 1].count += 1;
+ }
+ }
+ return encodedArray;
+ }
+
+ /**
+ * @param {string} s
+ * @return {boolean}
+ */
+ function isUrl(s) {
+ return typeof(s) === 'string' && s.match(URL_REGEX) !== null;
+ }
+
+ /**
+ * Returns the only element in the iterable. If the iterable is empty or has
+ * more than one element, an error is thrown.
+ */
+ function getOnlyElement(iterable) {
+ const iterator = iterable[Symbol.iterator]();
+
+ const firstIteration = iterator.next();
+ if (firstIteration.done) {
+ throw new Error('getOnlyElement was passed an empty iterable.');
+ }
+
+ const secondIteration = iterator.next();
+ if (!secondIteration.done) {
+ throw new Error(
+ 'getOnlyElement was passed an iterable with multiple elements.');
+ }
+
+ return firstIteration.value;
+ }
+
+ /**
+ * Returns the first element in the iterable. If the iterable is empty, an
+ * error is thrown.
+ */
+ function getFirstElement(iterable) {
+ const iterator = iterable[Symbol.iterator]();
+ const result = iterator.next();
+ if (result.done) {
+ throw new Error('getFirstElement was passed an empty iterable.');
+ }
+
+ return result.value;
+ }
+
+ function compareArrays(x, y, elementCmp) {
+ const minLength = Math.min(x.length, y.length);
+ let i;
+ for (i = 0; i < minLength; i++) {
+ const tmp = elementCmp(x[i], y[i]);
+ if (tmp) return tmp;
+ }
+ if (x.length === y.length) return 0;
+
+ if (x[i] === undefined) return -1;
+
+ return 1;
+ }
+
+ /**
+ * Returns a new Map with items grouped by the return value of the
+ * specified function being called on each item.
+ * @param {!Array.<!*>} ary The array being iterated through
+ * @param {!function(!*):!*} callback The mapping function between the array
+ * value and the map key.
+ * @param {*=} opt_this
+ */
+ function groupIntoMap(ary, callback, opt_this, opt_arrayConstructor) {
+ const arrayConstructor = opt_arrayConstructor || Array;
+ const results = new Map();
+ for (const element of ary) {
+ const key = callback.call(opt_this, element);
+ let items = results.get(key);
+ if (items === undefined) {
+ items = new arrayConstructor();
+ results.set(key, items);
+ }
+ items.push(element);
+ }
+ return results;
+ }
+
+ function inPlaceFilter(array, predicate, opt_this) {
+ opt_this = opt_this || this;
+ let nextPosition = 0;
+ for (let i = 0; i < array.length; i++) {
+ if (!predicate.call(opt_this, array[i], i)) continue;
+ if (nextPosition < i) {
+ array[nextPosition] = array[i]; // Move elements only if necessary.
+ }
+ nextPosition++;
+ }
+
+ if (nextPosition < array.length) {
+ array.length = nextPosition; // Truncate the array only if necessary.
+ }
+ }
+
+ /**
+ * Convert an array of dictionaries to a dictionary of arrays.
+ *
+ * The keys of the resulting dictionary are a union of the keys of all
+ * dictionaries in the provided array. Each array in the resulting dictionary
+ * has the same length as the provided array and contains the values of its
+ * key in the dictionaries in the provided array. Example:
+ *
+ * INPUT:
+ *
+ * [
+ * {a: 6, b: 5 },
+ * undefined,
+ * {a: 4, b: 3, c: 2},
+ * { b: 1, c: 0}
+ * ]
+ *
+ * OUTPUT:
+ *
+ * {
+ * a: [6, undefined, 4, undefined],
+ * b: [5, undefined, 3, 1 ],
+ * c: [undefined, undefined, 2, 0 ]
+ * }
+ *
+ * @param {!Array} array Array of items to be inverted. If opt_dictGetter
+ * is not provided, all elements of the array must be either undefined,
+ * or dictionaries.
+ * @param {?(function(*): (!Object|undefined))=} opt_dictGetter Optional
+ * function mapping defined elements of array to dictionaries.
+ * @param {*=} opt_this Optional 'this' context for opt_dictGetter.
+ */
+ function invertArrayOfDicts(array, opt_dictGetter, opt_this) {
+ opt_this = opt_this || this;
+ const result = {};
+ for (let i = 0; i < array.length; i++) {
+ const item = array[i];
+ if (item === undefined) continue;
+ const dict = opt_dictGetter ? opt_dictGetter.call(opt_this, item) : item;
+ if (dict === undefined) continue;
+ for (const key in dict) {
+ let valueList = result[key];
+ if (valueList === undefined) {
+ result[key] = valueList = new Array(array.length);
+ }
+ valueList[i] = dict[key];
+ }
+ }
+ return result;
+ }
+
+ function setsEqual(a, b) {
+ if (!(a instanceof Set) || !(b instanceof Set)) return false;
+ if (a.size !== b.size) return false;
+ // Avoid Array.from() here -- it creates garbage.
+ for (const x of a) {
+ if (!b.has(x)) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Finds the first index in the array whose value is >= loVal.
+ *
+ * The key for the search is defined by the mapFn. This array must
+ * be prearranged such that ary.map(mapFn) would also be sorted in
+ * ascending order.
+ *
+ * @param {Array} ary An array of arbitrary objects.
+ * @param {function():*} mapFn Callback that produces a key value
+ * from an element in ary.
+ * @param {number} loVal Value for which to search.
+ * @return {Number} Offset o into ary where all ary[i] for i <= o
+ * are < loVal, or ary.length if loVal is greater than all elements in
+ * the array.
+ */
+ function findLowIndexInSortedArray(ary, mapFn, loVal) {
+ if (ary.length === 0) return 1;
+
+ let low = 0;
+ let high = ary.length - 1;
+ let i;
+ let comparison;
+ let hitPos = -1;
+ while (low <= high) {
+ i = Math.floor((low + high) / 2);
+ comparison = mapFn(ary[i]) - loVal;
+ if (comparison < 0) {
+ low = i + 1; continue;
+ } else if (comparison > 0) {
+ high = i - 1; continue;
+ } else {
+ hitPos = i;
+ high = i - 1;
+ }
+ }
+ // return where we hit, or failing that the low pos
+ return hitPos !== -1 ? hitPos : low;
+ }
+
+ /**
+ * Finds an index in an array of intervals that either intersects
+ * the provided loVal, or if no intersection is found, -1 or ary.length.
+ *
+ * The array of intervals is defined implicitly via two mapping functions
+ * over the provided ary. mapLoFn determines the lower value of the interval,
+ * mapWidthFn the width. Intersection is lower-inclusive, e.g. [lo,lo+w).
+ *
+ * The array of intervals formed by this mapping must be non-overlapping and
+ * sorted in ascending order by loVal.
+ *
+ * @param {Array} ary An array of objects that can be converted into sorted
+ * nonoverlapping ranges [x,y) using the mapLoFn and mapWidth.
+ * @param {function():*} mapLoFn Callback that produces the low value for the
+ * interval represented by an element in the array.
+ * @param {function():*} mapWidthFn Callback that produces the width for the
+ * interval represented by an element in the array.
+ * @param {number} loVal The low value for the search.
+ * @return {Number} An index in the array that intersects or is first-above
+ * loVal, -1 if none found and loVal is below than all the intervals,
+ * ary.length if loVal is greater than all the intervals.
+ */
+ function findIndexInSortedIntervals(ary, mapLoFn, mapWidthFn, loVal) {
+ const first = findLowIndexInSortedArray(ary, mapLoFn, loVal);
+ if (first === 0) {
+ if (loVal >= mapLoFn(ary[0]) &&
+ loVal < mapLoFn(ary[0]) + mapWidthFn(ary[0], 0)) {
+ return 0;
+ }
+ return -1;
+ }
+
+ if (first < ary.length) {
+ if (loVal >= mapLoFn(ary[first]) &&
+ loVal < mapLoFn(ary[first]) + mapWidthFn(ary[first], first)) {
+ return first;
+ }
+ if (loVal >= mapLoFn(ary[first - 1]) &&
+ loVal < mapLoFn(ary[first - 1]) +
+ mapWidthFn(ary[first - 1], first - 1)) {
+ return first - 1;
+ }
+ return ary.length;
+ }
+
+ if (first === ary.length) {
+ if (loVal >= mapLoFn(ary[first - 1]) &&
+ loVal < mapLoFn(ary[first - 1]) +
+ mapWidthFn(ary[first - 1], first - 1)) {
+ return first - 1;
+ }
+ return ary.length;
+ }
+
+ return ary.length;
+ }
+
+ /**
+ * Finds an index in an array of sorted closed intervals that either
+ * intersects the provided val, or if no intersection is found, -1 or
+ * ary.length.
+ *
+ * The array of intervals is defined implicitly via two mapping functions
+ * over the provided ary. mapLoFn determines the lower value of the interval,
+ * mapHiFn the high. Intersection is closed, e.g. [lo,hi], unlike with
+ * findIndexInSortedIntervals, which is right-open.
+ *
+ * The array of intervals formed by this mapping must be non-overlapping, and
+ * sorted in ascending order by val.
+ *
+ * @param {Array} ary An array of objects that can be converted into sorted
+ * nonoverlapping ranges [x,y) using the mapLoFn and mapWidth.
+ * @param {function():*} mapLoFn Callback that produces the low value for the
+ * interval represented by an element in the array.
+ * @param {function():*} mapHiFn Callback that produces the high for the
+ * interval represented by an element in the array.
+ * @param {number} val The value for the search.
+ * @return {Number} An index in the array that intersects or is first-above
+ * val, -1 if none found and val is below than all the intervals,
+ * ary.length if val is greater than all the intervals.
+ */
+ function findIndexInSortedClosedIntervals(ary, mapLoFn, mapHiFn, val) {
+ const i = findLowIndexInSortedArray(ary, mapLoFn, val);
+ if (i === 0) {
+ if (val >= mapLoFn(ary[0], 0) &&
+ val <= mapHiFn(ary[0], 0)) {
+ return 0;
+ }
+ return -1;
+ }
+
+ if (i < ary.length) {
+ if (val >= mapLoFn(ary[i - 1], i - 1) &&
+ val <= mapHiFn(ary[i - 1], i - 1)) {
+ return i - 1;
+ }
+ if (val >= mapLoFn(ary[i], i) &&
+ val <= mapHiFn(ary[i], i)) {
+ return i;
+ }
+ return ary.length;
+ }
+
+ if (i === ary.length) {
+ if (val >= mapLoFn(ary[i - 1], i - 1) &&
+ val <= mapHiFn(ary[i - 1], i - 1)) {
+ return i - 1;
+ }
+ return ary.length;
+ }
+
+ return ary.length;
+ }
+
+ /**
+ * Calls cb for all intervals in the implicit array of intervals
+ * defnied by ary, mapLoFn and mapHiFn that intersect the range
+ * [loVal,hiVal)
+ *
+ * This function uses the same scheme as findLowIndexInSortedArray
+ * to define the intervals. The same restrictions on sortedness and
+ * non-overlappingness apply.
+ *
+ * @param {Array} ary An array of objects that can be converted into sorted
+ * nonoverlapping ranges [x,y) using the mapLoFn and mapWidth.
+ * @param {function():*} mapLoFn Callback that produces the low value for the
+ * interval represented by an element in the array.
+ * @param {function():*} mapWidthFn Callback that produces the width for the
+ * interval represented by an element in the array.
+ * @param {number} loVal The low value for the search, inclusive.
+ * @param {number} hiVal The high value for the search, non inclusive.
+ * @param {function():*} cb The function to run for intersecting intervals.
+ */
+ function iterateOverIntersectingIntervals(ary, mapLoFn, mapWidthFn, loVal,
+ hiVal, cb) {
+ if (ary.length === 0) return;
+
+ if (loVal > hiVal) return;
+
+ let i = findLowIndexInSortedArray(ary, mapLoFn, loVal);
+ if (i === -1) {
+ return;
+ }
+ if (i > 0) {
+ const hi = mapLoFn(ary[i - 1]) + mapWidthFn(ary[i - 1], i - 1);
+ if (hi >= loVal) {
+ cb(ary[i - 1], i - 1);
+ }
+ }
+ if (i === ary.length) {
+ return;
+ }
+
+ for (let n = ary.length; i < n; i++) {
+ const lo = mapLoFn(ary[i]);
+ if (lo >= hiVal) break;
+ cb(ary[i], i);
+ }
+ }
+
+ /**
+ * Finds the element in the array whose value is closest to |val|.
+ *
+ * The same restrictions on sortedness as for findLowIndexInSortedArray apply.
+ *
+ * @param {Array} ary An array of arbitrary objects.
+ * @param {function():*} mapFn Callback that produces a key value
+ * from an element in ary.
+ * @param {number} val Value for which to search.
+ * @param {number} maxDiff Maximum allowed difference in value between |val|
+ * and an element's value.
+ * @return {object} Object in the array whose value is closest to |val|, or
+ * null if no object is within range.
+ */
+ function findClosestElementInSortedArray(ary, mapFn, val, maxDiff) {
+ if (ary.length === 0) return null;
+
+ let aftIdx = findLowIndexInSortedArray(ary, mapFn, val);
+ const befIdx = aftIdx > 0 ? aftIdx - 1 : 0;
+
+ if (aftIdx === ary.length) aftIdx -= 1;
+
+ const befDiff = Math.abs(val - mapFn(ary[befIdx]));
+ const aftDiff = Math.abs(val - mapFn(ary[aftIdx]));
+
+ if (befDiff > maxDiff && aftDiff > maxDiff) return null;
+
+ const idx = befDiff < aftDiff ? befIdx : aftIdx;
+ return ary[idx];
+ }
+
+ /**
+ * Finds the closest interval in the implicit array of intervals
+ * defined by ary, mapLoFn and mapHiFn.
+ *
+ * This function uses the same scheme as findLowIndexInSortedArray
+ * to define the intervals. The same restrictions on sortedness and
+ * non-overlappingness apply.
+ *
+ * @param {Array} ary An array of objects that can be converted into sorted
+ * nonoverlapping ranges [x,y) using the mapLoFn and mapHiFn.
+ * @param {function():*} mapLoFn Callback that produces the low value for the
+ * interval represented by an element in the array.
+ * @param {function():*} mapHiFn Callback that produces the high for the
+ * interval represented by an element in the array.
+ * @param {number} val The value for the search.
+ * @param {number} maxDiff Maximum allowed difference in value between |val|
+ * and an interval's low or high value.
+ * @return {interval} Interval in the array whose high or low value is closest
+ * to |val|, or null if no interval is within range.
+ */
+ function findClosestIntervalInSortedIntervals(ary, mapLoFn, mapHiFn, val,
+ maxDiff) {
+ if (ary.length === 0) return null;
+
+ let idx = findLowIndexInSortedArray(ary, mapLoFn, val);
+ if (idx > 0) idx -= 1;
+
+ const hiInt = ary[idx];
+ let loInt = hiInt;
+
+ if (val > mapHiFn(hiInt) && idx + 1 < ary.length) {
+ loInt = ary[idx + 1];
+ }
+
+ const loDiff = Math.abs(val - mapLoFn(loInt));
+ const hiDiff = Math.abs(val - mapHiFn(hiInt));
+
+ if (loDiff > maxDiff && hiDiff > maxDiff) return null;
+
+ if (loDiff < hiDiff) return loInt;
+
+ return hiInt;
+ }
+
+ /**
+ * Returns first index i in |array| such that |test| is true for array[i].
+ * Returns array.length if no such i is found. Assumes |test| is monotonic
+ * boolean on |array|, i.e. if test(array[i]) is true, then test(array[i + 1])
+ * is also true.
+ *
+ * @param {Array} array Array of elements to perform binary search on.
+ * @param {function(*):boolean} test Monotonic boolean test function.
+ */
+ function findFirstTrueIndexInSortedArray(array, test) {
+ let i0 = 0;
+ let i1 = array.length;
+ while (i0 < i1) {
+ const i = Math.trunc((i0 + i1) / 2);
+ if (test(array[i])) {
+ i1 = i; // Explore the left branch.
+ } else {
+ i0 = i + 1; // Explore the right branch.
+ }
+ }
+ return i1;
+ }
+
+ return {
+ compareArrays,
+ deepCopy,
+ findClosestElementInSortedArray,
+ findClosestIntervalInSortedIntervals,
+ findFirstTrueIndexInSortedArray,
+ findIndexInSortedClosedIntervals,
+ findIndexInSortedIntervals,
+ findLowIndexInSortedArray,
+ formatDate,
+ getFirstElement,
+ getOnlyElement,
+ getUsingPath,
+ groupIntoMap,
+ inPlaceFilter,
+ invertArrayOfDicts,
+ isUrl,
+ iterateOverIntersectingIntervals,
+ normalizeException,
+ numberFromJson,
+ numberToJson,
+ runLengthEncoding,
+ setsEqual,
+ stackTrace,
+ stackTraceAsString,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/utils_test.html b/chromium/third_party/catapult/tracing/tracing/base/utils_test.html
new file mode 100644
index 00000000000..a9b00f0c5c1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/utils_test.html
@@ -0,0 +1,433 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('getUsingPath', function() {
+ const z = tr.b.getUsingPath('x.y.z', {'x': {'y': {'z': 3}}});
+ assert.strictEqual(z, 3);
+
+ const w = tr.b.getUsingPath('x.w', {'x': {'y': {'z': 3}}});
+ assert.isUndefined(w);
+ });
+
+ test('testExceptionNaming', function() {
+ const err = new Error('asdf');
+ err.name = 'MyError';
+
+ const ex = tr.b.normalizeException(err);
+ assert.strictEqual(ex.typeName, 'MyError');
+ });
+
+ test('formatDate', function() {
+ assert.strictEqual(tr.b.formatDate(new Date(0)), '1970-01-01 00:00:00');
+ });
+
+ test('runLengthEncoding', function() {
+ assert.deepEqual(tr.b.runLengthEncoding([]), []);
+
+ let encoded = tr.b.runLengthEncoding([1, 1]);
+ assert.deepEqual(encoded.map(x => x.value), [1]);
+ assert.deepEqual(encoded.map(x => x.count), [2]);
+
+ encoded = tr.b.runLengthEncoding([1, 2]);
+ assert.deepEqual(encoded.map(x => x.value), [1, 2]);
+ assert.deepEqual(encoded.map(x => x.count), [1, 1]);
+
+ encoded = tr.b.runLengthEncoding([1, 1, 2, 2, 2, 3, 1, 1]);
+ assert.deepEqual(encoded.map(x => x.value), [1, 2, 3, 1]);
+ assert.deepEqual(encoded.map(x => x.count), [2, 3, 1, 2]);
+ });
+
+ test('isUrl', function() {
+ assert.isFalse(tr.b.isUrl());
+ assert.isFalse(tr.b.isUrl(null));
+ assert.isFalse(tr.b.isUrl(42));
+ assert.isFalse(tr.b.isUrl([]));
+ assert.isFalse(tr.b.isUrl({}));
+ assert.isFalse(tr.b.isUrl(''));
+ assert.isFalse(tr.b.isUrl('data:,'));
+ assert.isFalse(tr.b.isUrl('ftp://user:password@host:port/path'));
+ assert.isTrue(tr.b.isUrl('http://google.com/'));
+ assert.isTrue(tr.b.isUrl('https://www.google.com/'));
+ });
+
+ test('setsEqual', function() {
+ assert.isTrue(tr.b.setsEqual(new Set(), new Set()));
+ assert.isTrue(tr.b.setsEqual(new Set(['a']), new Set(['a'])));
+ assert.isFalse(tr.b.setsEqual(new Set(), undefined));
+ assert.isFalse(tr.b.setsEqual(new Set(), new Set(['a'])));
+ assert.isFalse(tr.b.setsEqual(new Set(['a']), new Set(['b'])));
+ });
+
+ test('compareArrays', function() {
+ function cmp(x, y) {
+ assert.isDefined(x);
+ assert.isDefined(y);
+ return x - y;
+ }
+
+ assert.isBelow(tr.b.compareArrays([1], [2], cmp), 0);
+ assert.isAbove(tr.b.compareArrays([2], [1], cmp), 0);
+
+ assert.isBelow(tr.b.compareArrays([1], [1, 2], cmp), 0);
+ assert.isAbove(tr.b.compareArrays([1, 2], [1], cmp), 0);
+
+ assert.isBelow(tr.b.compareArrays([], [1], cmp), 0);
+ assert.isAbove(tr.b.compareArrays([1], [], cmp), 0);
+
+ assert.isAbove(tr.b.compareArrays([2], [1], cmp), 0);
+
+ assert.strictEqual(tr.b.compareArrays([], [], cmp), 0);
+ assert.strictEqual(tr.b.compareArrays([1], [1], cmp), 0);
+ });
+
+ test('getOnlyElement_throwsIfEmpty', function() {
+ assert.throws(() => tr.b.getOnlyElement([]),
+ 'getOnlyElement was passed an empty iterable.');
+ });
+
+ test('getOnlyElement_oneItem', function() {
+ assert.strictEqual(tr.b.getOnlyElement([1]), 1);
+ });
+
+ test('getOnlyElement_twoItems', function() {
+ assert.throws(() => tr.b.getOnlyElement([1, 2]),
+ 'getOnlyElement was passed an iterable with multiple elements.');
+ });
+
+ test('getFirstElement_throwsIfEmpty', function() {
+ assert.throws(() => tr.b.getFirstElement([]),
+ 'getFirstElement was passed an empty iterable.');
+ });
+
+ test('getFirstElement_oneItem', function() {
+ assert.strictEqual(tr.b.getFirstElement([1]), 1);
+ });
+
+ test('getFirstElement_twoItems', function() {
+ assert.strictEqual(tr.b.getFirstElement([1, 2]), 1);
+ });
+
+ test('groupIntoMap', function() {
+ // Empty array
+ let srcArray = [];
+ const fn = function(curr) { return (curr % 2); };
+ const dstDict = {};
+
+ assert.deepEqual(tr.b.groupIntoMap(srcArray, fn), dstDict);
+
+ // Non-empty array
+ srcArray = [0, 1, 2, 3, 4, 5, 6];
+ const dstMap = new Map([
+ [0, [0, 2, 4, 6]],
+ [1, [1, 3, 5]]
+ ]);
+
+ assert.deepEqual(tr.b.groupIntoMap(srcArray, fn), dstMap);
+ });
+
+ test('inPlaceFilter_simple', function() {
+ const someThisArg = {};
+ const list = [1, 2, 3, 4];
+ tr.b.inPlaceFilter(list, function(item) {
+ assert.strictEqual(this, someThisArg);
+ return item % 2 === 0;
+ }, someThisArg);
+ assert.deepEqual(list, [2, 4]);
+ });
+
+ test('invertArrayOfDicts_defaultGetter', function() {
+ const array = [
+ {a: 6, b: 5},
+ undefined,
+ {a: 4, b: 3, c: 2},
+ {b: 1, c: 0}
+ ];
+ const dict = tr.b.invertArrayOfDicts(array);
+ assert.sameMembers(Object.keys(dict), ['a', 'b', 'c']);
+ assert.deepEqual(Array.from(dict.a), [6, undefined, 4, undefined]);
+ assert.deepEqual(Array.from(dict.b), [5, undefined, 3, 1]);
+ assert.deepEqual(Array.from(dict.c), [undefined, undefined, 2, 0]);
+ });
+
+ test('invertArrayOfDicts_customGetter', function() {
+ const fakeThis = { itemToDict: JSON.parse };
+ const array = [
+ '{"a": "test", "b": true}',
+ '{}',
+ '{invalid-json}',
+ '{"a": 42, "c": false}'
+ ];
+ const dict = tr.b.invertArrayOfDicts(array, function(item) {
+ try {
+ return this.itemToDict(item);
+ } catch (e) {
+ return undefined;
+ }
+ }, fakeThis);
+ assert.sameMembers(Object.keys(dict), ['a', 'b', 'c']);
+ assert.deepEqual(
+ Array.from(dict.a), ['test', undefined, undefined, 42]);
+ assert.deepEqual(
+ Array.from(dict.b), [true, undefined, undefined, undefined]);
+ assert.deepEqual(
+ Array.from(dict.c), [undefined, undefined, undefined, false]);
+ });
+
+ const ArrayOfIntervals = function(array) {
+ this.array = array;
+ };
+
+ ArrayOfIntervals.prototype = {
+ get(index) {
+ return this.array[index];
+ },
+
+ findLowElementIndex(ts) {
+ return tr.b.findLowIndexInSortedArray(
+ this.array,
+ function(x) { return x.lo; },
+ ts);
+ },
+
+ findIntervalIndex(ts) {
+ return tr.b.findIndexInSortedIntervals(
+ this.array,
+ function(x) { return x.lo; },
+ function(x) { return x.hi - x.lo; },
+ ts);
+ },
+
+ findIndexInClosedIntervals(ts) {
+ return tr.b.findIndexInSortedClosedIntervals(
+ this.array,
+ function(x) { return x.lo; },
+ function(x) { return x.hi; },
+ ts);
+ },
+
+ findIntersectingIntervals(tsA, tsB) {
+ const array = this.array;
+ const result = [];
+ tr.b.iterateOverIntersectingIntervals(
+ this.array,
+ function(x) { return x.lo; },
+ function(x) { return x.hi - x.lo; },
+ tsA,
+ tsB,
+ function(x) { result.push(array.indexOf(x)); });
+ return result;
+ },
+
+ findClosestElement(ts, tsDiff) {
+ return tr.b.findClosestElementInSortedArray(
+ this.array,
+ function(x) { return x.lo; },
+ ts,
+ tsDiff);
+ },
+
+ findClosestInterval(ts, tsDiff) {
+ return tr.b.findClosestIntervalInSortedIntervals(
+ this.array,
+ function(x) { return x.lo; },
+ function(x) { return x.hi; },
+ ts,
+ tsDiff);
+ }
+ };
+
+ test('findLowElementIndex', function() {
+ const array = new ArrayOfIntervals([
+ {lo: 10, hi: 15},
+ {lo: 20, hi: 30}
+ ]);
+
+ assert.strictEqual(array.findLowElementIndex(-100), 0);
+ assert.strictEqual(array.findLowElementIndex(0), 0);
+ assert.strictEqual(array.findLowElementIndex(10), 0);
+
+ assert.strictEqual(array.findLowElementIndex(10.1), 1);
+ assert.strictEqual(array.findLowElementIndex(15), 1);
+ assert.strictEqual(array.findLowElementIndex(20), 1);
+
+ assert.strictEqual(array.findLowElementIndex(20.1), 2);
+ assert.strictEqual(array.findLowElementIndex(21), 2);
+ assert.strictEqual(array.findLowElementIndex(100), 2);
+ });
+
+ test('findIntervalIndex', function() {
+ const array = new ArrayOfIntervals([
+ {lo: 10, hi: 15},
+ {lo: 20, hi: 30}
+ ]);
+
+ assert.strictEqual(array.findIntervalIndex(0), -1);
+ assert.strictEqual(array.findIntervalIndex(9.9), -1);
+
+ assert.strictEqual(array.findIntervalIndex(10), 0);
+ assert.strictEqual(array.findIntervalIndex(12), 0);
+ assert.strictEqual(array.findIntervalIndex(14.9), 0);
+
+ assert.strictEqual(array.findIntervalIndex(20), 1);
+ assert.strictEqual(array.findIntervalIndex(21), 1);
+ assert.strictEqual(array.findIntervalIndex(29.99), 1);
+
+ assert.strictEqual(array.findIntervalIndex(30), 2);
+ assert.strictEqual(array.findIntervalIndex(40), 2);
+
+
+ // misses, in between the intervals, return array length
+ assert.strictEqual(array.findIntervalIndex(15), 2);
+ assert.strictEqual(array.findIntervalIndex(19.9), 2);
+ });
+
+ test('findClosedIntervalIndex', function() {
+ const array = new ArrayOfIntervals([
+ {lo: 10, hi: 15},
+ {lo: 15, hi: 20},
+ {lo: 21, hi: 25}
+ ]);
+
+ assert.strictEqual(array.findIndexInClosedIntervals(0), -1);
+ assert.strictEqual(array.findIndexInClosedIntervals(9.999), -1);
+ assert.strictEqual(array.findIndexInClosedIntervals(10), 0);
+ assert.strictEqual(array.findIndexInClosedIntervals(14), 0);
+ assert.strictEqual(array.findIndexInClosedIntervals(15), 0);
+ assert.strictEqual(array.findIndexInClosedIntervals(15.00001), 1);
+ assert.strictEqual(array.findIndexInClosedIntervals(20.5), 3);
+ assert.strictEqual(array.findIndexInClosedIntervals(22), 2);
+ assert.strictEqual(array.findIndexInClosedIntervals(25), 2);
+ assert.strictEqual(array.findIndexInClosedIntervals(25.00001), 3);
+ });
+
+ test('findClosedInEmptyArray', function() {
+ const array = new ArrayOfIntervals([]);
+ assert.strictEqual(array.findIndexInClosedIntervals(0), 0);
+ });
+
+ test('findIntersectingIntervals', function() {
+ const array = new ArrayOfIntervals([
+ {lo: 10, hi: 15},
+ {lo: 20, hi: 30}
+ ]);
+
+ assert.deepEqual(array.findIntersectingIntervals(0, 0), []);
+ assert.deepEqual(array.findIntersectingIntervals(100, 0), []);
+ assert.deepEqual(array.findIntersectingIntervals(0, 10), []);
+
+ assert.deepEqual(array.findIntersectingIntervals(0, 10.1), [0]);
+ assert.deepEqual(array.findIntersectingIntervals(5, 15), [0]);
+ assert.deepEqual(array.findIntersectingIntervals(15, 20), [0]);
+
+ assert.deepEqual(array.findIntersectingIntervals(15.1, 20), []);
+
+ assert.deepEqual(array.findIntersectingIntervals(15.1, 20.1), [1]);
+ assert.deepEqual(array.findIntersectingIntervals(20, 30), [1]);
+ assert.deepEqual(array.findIntersectingIntervals(30, 100), [1]);
+
+ assert.deepEqual(array.findIntersectingIntervals(0, 100), [0, 1]);
+ assert.deepEqual(array.findIntersectingIntervals(15, 20.1), [0, 1]);
+ });
+
+ test('findClosestElement', function() {
+ const array = new ArrayOfIntervals([
+ {lo: 10, hi: 15},
+ {lo: 20, hi: 30}
+ ]);
+
+ // Test the helper method first.
+ assert.isUndefined(array.get(-1));
+ assert.strictEqual(array.get(0), array.array[0]);
+ assert.strictEqual(array.get(1), array.array[1]);
+ assert.isUndefined(array.get(2));
+
+ assert.isNull(array.findClosestElement(0, 0));
+ assert.isNull(array.findClosestElement(0, 9.9));
+ assert.isNull(array.findClosestElement(10, -10));
+
+ assert.strictEqual(array.get(0), array.findClosestElement(0, 10));
+ assert.strictEqual(array.get(0), array.findClosestElement(8, 5));
+ assert.strictEqual(array.get(0), array.findClosestElement(10, 0));
+ assert.strictEqual(array.get(0), array.findClosestElement(12, 2));
+
+ assert.isNull(array.findClosestElement(15, 3));
+ assert.isNotNull(array.findClosestElement(15, 5));
+
+ assert.strictEqual(array.get(1), array.findClosestElement(19, 1));
+ assert.strictEqual(array.get(1), array.findClosestElement(20, 0));
+ assert.strictEqual(array.get(1), array.findClosestElement(30, 15));
+
+ assert.isNull(array.findClosestElement(30, 9.9));
+ assert.isNull(array.findClosestElement(100, 50));
+ });
+
+ test('findClosestInterval', function() {
+ const array = new ArrayOfIntervals([
+ {lo: 10, hi: 15},
+ {lo: 20, hi: 30}
+ ]);
+
+ assert.isNull(array.findClosestInterval(0, 0));
+ assert.isNull(array.findClosestInterval(0, 9.9));
+ assert.isNull(array.findClosestInterval(0, -100));
+
+ assert.strictEqual(array.get(0), array.findClosestInterval(0, 10));
+ assert.strictEqual(array.get(0), array.findClosestInterval(10, 0));
+ assert.strictEqual(array.get(0), array.findClosestInterval(12, 3));
+ assert.strictEqual(array.get(0), array.findClosestInterval(12, 100));
+
+ assert.strictEqual(array.get(0), array.findClosestInterval(13, 3));
+ assert.strictEqual(array.get(0), array.findClosestInterval(13, 20));
+ assert.strictEqual(array.get(0), array.findClosestInterval(15, 0));
+
+ assert.isNull(array.findClosestInterval(17.5, 0));
+ assert.isNull(array.findClosestInterval(17.5, 2.4));
+ assert.isNotNull(array.findClosestInterval(17.5, 2.5));
+ assert.isNotNull(array.findClosestInterval(17.5, 10));
+
+ assert.strictEqual(array.get(1), array.findClosestInterval(19, 2));
+ assert.strictEqual(array.get(1), array.findClosestInterval(20, 0));
+ assert.strictEqual(array.get(1), array.findClosestInterval(24, 100));
+ assert.strictEqual(array.get(1), array.findClosestInterval(26, 100));
+
+ assert.strictEqual(array.get(1), array.findClosestInterval(30, 0));
+ assert.strictEqual(array.get(1), array.findClosestInterval(35, 10));
+ assert.strictEqual(array.get(1), array.findClosestInterval(50, 100));
+
+ assert.isNull(array.findClosestInterval(50, 19));
+ assert.isNull(array.findClosestInterval(100, 50));
+ assert.isNull(array.findClosestInterval(50, -100));
+ });
+
+ test('findFirstTrueIndexInSortedArray', function() {
+ const array = [1, 3, 7, 15, 30, 50, 80];
+ const objectArray = array.map(v => {return {value: v};});
+
+ assert.strictEqual(
+ tr.b.findFirstTrueIndexInSortedArray(objectArray, x => (x.value > 90)),
+ objectArray.length);
+ assert.strictEqual(
+ tr.b.findFirstTrueIndexInSortedArray(objectArray, x => (x.value > 15)),
+ 4);
+ assert.strictEqual(
+ tr.b.findFirstTrueIndexInSortedArray(objectArray, x => (x.value >= 15)),
+ 3);
+ assert.strictEqual(
+ tr.b.findFirstTrueIndexInSortedArray(objectArray, x => (x.value > 0)),
+ 0);
+ assert.strictEqual(
+ tr.b.findFirstTrueIndexInSortedArray(objectArray,
+ x => (x.value % 5 === 0)),
+ 3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/view_state.html b/chromium/third_party/catapult/tracing/tracing/base/view_state.html
new file mode 100644
index 00000000000..a64bbc591fb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/view_state.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/serializable.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.b', function() {
+ /*
+ * This is a base class for MVC Model classes.
+ * Subclasses must call super() and define() in their constructors to define
+ * managed properties.
+ * Call addUpdateListener(listener) to listen for update events.
+ *
+ * When clients set fields on an instance of a subclass of ViewState,
+ * an update event will be dispatched containing the delta.
+ *
+ * Defined properties can optionally contain instances of any ViewState
+ * subclass in Arrays, Maps, or Sets, recursively. Update events do not bubble
+ * up through parent ViewStateModels. This allows clients to choose whether to
+ * listen to every sub-ViewState or select instances. This also allows
+ * ViewState subclasses to define circular references if necessary, though
+ * that is not supported for serialization.
+ */
+ class ViewState extends tr.b.Serializable {
+ constructor() {
+ super();
+ tr.b.EventTarget.decorate(this);
+ }
+
+ setProperty_(name, value) {
+ this.update(new Map([[name, value]]));
+ }
+
+ async updateFromViewState(other) {
+ await this.update(other.properties_);
+ }
+
+ /**
+ * Updates properties, and, if any of them actually changed, dispatches
+ * an event with delta = {propertyName: {previous, current}}.
+ *
+ * @param {!(Object|Map)} delta
+ */
+ async update(delta) {
+ // This method only wants to iterate over delta, so convert it to a map.
+ if (!(delta instanceof Map)) delta = new Map(Object.entries(delta));
+
+ // Clients presumably want to test for changes to specific fields by name,
+ // which is easier with dictionaries, so the actualDelta is a dictionary.
+ const actualDelta = {};
+ for (const [name, current] of delta) {
+ const previous = this[name];
+ if (previous === current) continue;
+
+ actualDelta[name] = {previous, current};
+ tr.b.Serializable.prototype.setProperty_.call(this, name, current);
+ }
+
+ if (Object.keys(actualDelta).length === 0) return;
+
+ await tr.b.dispatchSimpleEventAsync(
+ this, this.updateEventName_, {delta: actualDelta});
+ }
+
+ get updateEventName_() {
+ return this.constructor.name + '.update';
+ }
+
+ /**
+ * @param {!function(!tr.b.Event)} listener
+ */
+ addUpdateListener(listener) {
+ this.addEventListener(this.updateEventName_, listener);
+ }
+
+ /**
+ * @param {!function(!tr.b.Event)} listener
+ */
+ removeUpdateListener(listener) {
+ this.removeEventListener(this.updateEventName_, listener);
+ }
+ }
+
+ return {
+ ViewState,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/view_state_test.html b/chromium/third_party/catapult/tracing/tracing/base/view_state_test.html
new file mode 100644
index 00000000000..ec6e2769285
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/view_state_test.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/view_state.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ class Stuff extends tr.b.ViewState {
+ constructor() {
+ super();
+ this.define('boole', false);
+ this.define('sub', []);
+ }
+ }
+
+ tr.b.ViewState.register(Stuff);
+
+ test('sync', function() {
+ const state = new Stuff();
+ let updateCount = 0;
+ let delta;
+ function listener(event) {
+ ++updateCount;
+ delta = event.delta;
+ }
+ state.addUpdateListener(listener);
+ assert.strictEqual(0, updateCount);
+
+ state.boole = true;
+ assert.strictEqual(1, updateCount);
+ assert.isFalse(delta.boole.previous);
+ assert.isTrue(delta.boole.current);
+ assert.isTrue(state.boole);
+
+ state.boole = true;
+ assert.strictEqual(1, updateCount);
+
+ state.sub = [new Stuff()];
+ assert.strictEqual(2, updateCount);
+ assert.lengthOf(delta.sub.previous, 0);
+ assert.lengthOf(delta.sub.current, 1);
+
+ state.sub.push(new Stuff());
+ assert.strictEqual(2, updateCount);
+
+ state.sub[0].addUpdateListener(listener);
+ assert.strictEqual(2, updateCount);
+
+ state.sub[0].boole = true;
+ assert.strictEqual(3, updateCount);
+ assert.isFalse(delta.boole.previous);
+ assert.isTrue(delta.boole.current);
+ assert.isTrue(state.sub[0].boole);
+ });
+
+ test('async', async function() {
+ const state = new Stuff();
+ let updateCount = 0;
+ let delta;
+ async function listener(event) {
+ ++updateCount;
+ delta = event.delta;
+ await Promise.resolve();
+ }
+ state.addUpdateListener(listener);
+ assert.strictEqual(0, updateCount);
+
+ await state.update({boole: true});
+ assert.strictEqual(1, updateCount);
+ assert.isFalse(delta.boole.previous);
+ assert.isTrue(delta.boole.current);
+ assert.isTrue(state.boole);
+
+ await state.update({boole: true});
+ assert.strictEqual(1, updateCount);
+
+ await state.update({sub: [new Stuff()]});
+ assert.strictEqual(2, updateCount);
+ assert.lengthOf(delta.sub.previous, 0);
+ assert.lengthOf(delta.sub.current, 1);
+
+ state.sub.push(new Stuff());
+ assert.strictEqual(2, updateCount);
+
+ state.sub[0].addUpdateListener(listener);
+ assert.strictEqual(2, updateCount);
+
+ await state.sub[0].update({boole: true});
+ assert.strictEqual(3, updateCount);
+ assert.isFalse(delta.boole.previous);
+ assert.isTrue(delta.boole.current);
+ assert.isTrue(state.sub[0].boole);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/base/xhr.html b/chromium/third_party/catapult/tracing/tracing/base/xhr.html
new file mode 100644
index 00000000000..f168ee43b09
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/base/xhr.html
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/in_memory_trace_stream.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.b', function() {
+ let fs;
+ if (tr.isNode) fs = require('fs');
+
+ function guessBinary(url) {
+ return /[.]gz$/.test(url) || /[.]zip$/.test(url);
+ }
+ function xhr(method, url, async, opt_data, forceBinary) {
+ const req = new XMLHttpRequest();
+ req.overrideMimeType('text/plain; charset=x-user-defined');
+ req.open(method, url, async);
+
+ const isBinary = forceBinary;
+
+ if (isBinary === undefined) {
+ guessBinary(url);
+ if (isBinary && async) req.responseType = 'arraybuffer';
+ }
+
+ const data = opt_data !== undefined ? opt_data : null;
+
+ if (!async) {
+ req.send(data);
+ if (req.status === 200) return req.responseText;
+ throw new Error('XHR failed with status ' + req.status +
+ ' for url ' + url);
+ }
+
+ const p = new Promise(function(resolve, reject) {
+ req.onreadystatechange = function(aEvt) {
+ if (req.readyState !== 4) return;
+ tr.b.timeout(0).then(() => {
+ if (req.status !== 200) {
+ reject(new Error('XHR failed with status ' + req.status +
+ ' for url ' + url));
+ return;
+ }
+ if (req.responseType === 'arraybuffer') {
+ resolve(req.response);
+ return;
+ }
+ resolve(req.responseText);
+ });
+ };
+ });
+ req.send(data);
+ return p;
+ }
+
+ function getAsync(url) {
+ // Browser.
+ if (!tr.isHeadless) return xhr('GET', url, true);
+
+ // Node or vinn prep.
+ let filename;
+ if (url.startsWith('file:///')) {
+ filename = url.substring(7);
+ } else {
+ filename = global.HTMLImportsLoader.hrefToAbsolutePath(url);
+ }
+ const isBinary = guessBinary(url);
+
+ // Node.
+ if (tr.isNode) {
+ const encoding = isBinary ? undefined : 'utf8';
+ return new Promise(function(resolve, reject) {
+ fs.readFile(filename, encoding, function(err, data) {
+ if (err) {
+ reject(err);
+ return;
+ }
+ resolve(data);
+ });
+ });
+ }
+
+ // Vinn.
+ return Promise.resolve().then(function() {
+ if (isBinary) return readbuffer(filename);
+ return read(filename);
+ });
+ }
+
+ function getSync(url, asTraceStream) {
+ // Browser.
+ if (!tr.isHeadless) return xhr('GET', url, false);
+
+ // Node or vinn prep.
+ let filename;
+ if (url.startsWith('file:///')) { // posix
+ filename = url.substring(7);
+ } else if (url.startsWith('file://') && url[8] === ':') { // win
+ filename = url.substring(7);
+ } else {
+ filename = global.HTMLImportsLoader.hrefToAbsolutePath(url);
+ }
+ const isBinary = guessBinary(url);
+
+ // Node.
+ if (tr.isNode) {
+ const encoding = isBinary ? undefined : 'utf8';
+ return fs.readFileSync(filename, encoding);
+ }
+
+ // Vinn.
+ try {
+ if (asTraceStream) {
+ return new tr.b.InMemoryTraceStream(
+ new Uint8Array(readbuffer(filename)), isBinary);
+ } else if (isBinary) {
+ return readbuffer(filename);
+ }
+ return read(filename);
+ } catch (ex) {
+ if (ex.message) {
+ ex.message += ' when reading ' + filename;
+ throw ex;
+ }
+ throw new Error(ex + ' when reading' + filename);
+ }
+ }
+
+ function postAsync(url, data) {
+ if (tr.isHeadless) {
+ throw new Error('Only supported inside a browser');
+ }
+ return xhr('POST', url, true, data);
+ }
+
+ function postTextAsync(url, data) {
+ if (tr.isHeadless) {
+ throw new Error('Only supported inside a browser');
+ }
+ return xhr('POST', url, true, data, false);
+ }
+
+ return {
+ getAsync,
+ getSync,
+ postAsync,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/core/auditor.html b/chromium/third_party/catapult/tracing/tracing/core/auditor.html
new file mode 100644
index 00000000000..dd3dd224a36
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/core/auditor.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/extension_registry.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Base class for auditors.
+ */
+tr.exportTo('tr.c', function() {
+ function Auditor(model) {
+ this.model_ = model;
+ }
+
+ Auditor.prototype = {
+ __proto__: Object.prototype,
+
+ get model() {
+ return this.model_;
+ },
+
+ /**
+ * Called by the Model after baking slices. May modify model.
+ */
+ runAnnotate() {
+ },
+
+ /**
+ * Called by import to install userFriendlyCategoryDriver.
+ */
+ installUserFriendlyCategoryDriverIfNeeded() {
+ },
+
+ /**
+ * Called by the Model after importing. Should not modify model, except
+ * for adding interaction ranges and audits.
+ */
+ runAudit() {
+ }
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ options.defaultMetadata = {};
+ options.mandatoryBaseClass = Auditor;
+ tr.b.decorateExtensionRegistry(Auditor, options);
+
+ return {
+ Auditor,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/core/filter.html b/chromium/third_party/catapult/tracing/tracing/core/filter.html
new file mode 100644
index 00000000000..acbbb06e96f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/core/filter.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.c', function() {
+ function makeCaseInsensitiveRegex(pattern) {
+ // See https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/
+ // Regular_Expressions.
+ pattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ return new RegExp(pattern, 'i');
+ }
+
+ /**
+ * @constructor The generic base class for filtering a Model based on
+ * various rules. The base class returns true for everything.
+ */
+ function Filter() { }
+
+ Filter.prototype = {
+ __proto__: Object.prototype,
+
+ matchCounter(counter) {
+ return true;
+ },
+
+ matchCpu(cpu) {
+ return true;
+ },
+
+ matchProcess(process) {
+ return true;
+ },
+
+ matchSlice(slice) {
+ return true;
+ },
+
+ matchThread(thread) {
+ return true;
+ }
+ };
+
+ /**
+ * @constructor A filter that matches objects by their name or category
+ * case insensitive.
+ * .findAllObjectsMatchingFilter
+ */
+ function TitleOrCategoryFilter(text) {
+ Filter.call(this);
+ this.regex_ = makeCaseInsensitiveRegex(text);
+
+ if (!text.length) {
+ throw new Error('Filter text is empty.');
+ }
+ }
+ TitleOrCategoryFilter.prototype = {
+ __proto__: Filter.prototype,
+
+ matchSlice(slice) {
+ if (slice.title === undefined && slice.category === undefined) {
+ return false;
+ }
+
+ return this.regex_.test(slice.title) ||
+ (!!slice.category && this.regex_.test(slice.category));
+ }
+ };
+
+ /**
+ * @constructor A filter that matches objects with the exact given title.
+ */
+ function ExactTitleFilter(text) {
+ Filter.call(this);
+ this.text_ = text;
+
+ if (!text.length) {
+ throw new Error('Filter text is empty.');
+ }
+ }
+ ExactTitleFilter.prototype = {
+ __proto__: Filter.prototype,
+
+ matchSlice(slice) {
+ return slice.title === this.text_;
+ }
+ };
+
+ /**
+ * @constructor A filter that matches objects by their full text contents
+ * (title, category, args). Note that for performance this filter applies a
+ * regex against all the keys of the slice arguments instead of recursing
+ * through any embedded sub-objects.
+ */
+ function FullTextFilter(text) {
+ Filter.call(this);
+ this.regex_ = makeCaseInsensitiveRegex(text);
+ this.titleOrCategoryFilter_ = new TitleOrCategoryFilter(text);
+ }
+ FullTextFilter.prototype = {
+ __proto__: Filter.prototype,
+
+ matchObject_(obj) {
+ for (const key in obj) {
+ if (!obj.hasOwnProperty(key)) continue;
+ if (this.regex_.test(key)) return true;
+ if (this.regex_.test(obj[key])) return true;
+ }
+ return false;
+ },
+
+ matchSlice(slice) {
+ if (this.titleOrCategoryFilter_.matchSlice(slice)) return true;
+ return this.matchObject_(slice.args);
+ }
+ };
+
+ return {
+ Filter,
+ TitleOrCategoryFilter,
+ ExactTitleFilter,
+ FullTextFilter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/core/filter_test.html b/chromium/third_party/catapult/tracing/tracing/core/filter_test.html
new file mode 100644
index 00000000000..b69aa378497
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/core/filter_test.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unittest.html">
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TitleOrCategoryFilter = tr.c.TitleOrCategoryFilter;
+ const ExactTitleFilter = tr.c.ExactTitleFilter;
+ const FullTextFilter = tr.c.FullTextFilter;
+
+ test('titleOrCategoryFilter', function() {
+ assert.throw(function() {
+ new TitleOrCategoryFilter();
+ });
+ assert.throw(function() {
+ new TitleOrCategoryFilter('');
+ });
+
+ const s0 = tr.c.TestUtils.newSliceEx(
+ {cat: 'cat', title: 'a', start: 1, duration: 3});
+ assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s0));
+ assert.isTrue(new TitleOrCategoryFilter('cat').matchSlice(s0));
+ assert.isTrue(new TitleOrCategoryFilter('at').matchSlice(s0));
+ assert.isFalse(new TitleOrCategoryFilter('b').matchSlice(s0));
+ assert.isFalse(new TitleOrCategoryFilter('X').matchSlice(s0));
+
+ const s1 = tr.c.TestUtils.newSliceEx(
+ {cat: 'cat', title: 'abc', start: 1, duration: 3});
+ assert.isTrue(new TitleOrCategoryFilter('abc').matchSlice(s1));
+ assert.isTrue(new TitleOrCategoryFilter('Abc').matchSlice(s1));
+ assert.isTrue(new TitleOrCategoryFilter('cat').matchSlice(s1));
+ assert.isTrue(new TitleOrCategoryFilter('Cat').matchSlice(s1));
+ assert.isFalse(new TitleOrCategoryFilter('cat1').matchSlice(s1));
+ assert.isFalse(new TitleOrCategoryFilter('X').matchSlice(s1));
+ });
+
+ test('exactTitleFilter', function() {
+ assert.throw(function() {
+ new ExactTitleFilter();
+ });
+ assert.throw(function() {
+ new ExactTitleFilter('');
+ });
+
+ const s0 = tr.c.TestUtils.newSliceEx({title: 'a', start: 1, duration: 3});
+ assert.isTrue(new ExactTitleFilter('a').matchSlice(s0));
+ assert.isFalse(new ExactTitleFilter('b').matchSlice(s0));
+ assert.isFalse(new ExactTitleFilter('A').matchSlice(s0));
+
+ const s1 = tr.c.TestUtils.newSliceEx({title: 'abc', start: 1, duration: 3});
+ assert.isTrue(new ExactTitleFilter('abc').matchSlice(s1));
+ assert.isFalse(new ExactTitleFilter('Abc').matchSlice(s1));
+ assert.isFalse(new ExactTitleFilter('bc').matchSlice(s1));
+ assert.isFalse(new ExactTitleFilter('a').matchSlice(s1));
+ });
+
+ test('fullTextFilter', function() {
+ assert.throw(function() {
+ new FullTextFilter();
+ });
+ assert.throw(function() {
+ new FullTextFilter('');
+ });
+
+ const s0 = tr.c.TestUtils.newSliceEx(
+ {cat: 'cat', title: 'a', start: 1, duration: 3});
+ s0.args.key = 'value';
+ s0.args.anotherKey = 'anotherValue';
+ assert.isTrue(new FullTextFilter('cat').matchSlice(s0));
+ assert.isTrue(new FullTextFilter('a').matchSlice(s0));
+ assert.isTrue(new FullTextFilter('key').matchSlice(s0));
+ assert.isTrue(new FullTextFilter('value').matchSlice(s0));
+ assert.isTrue(new FullTextFilter('anotherValue').matchSlice(s0));
+ assert.isFalse(new FullTextFilter('not there').matchSlice(s0));
+
+ const s1 = tr.c.TestUtils.newSliceEx(
+ {cat: 'cat', title: 'a', start: 1, duration: 3});
+ s1.args.key = 123;
+ assert.isTrue(new FullTextFilter('123').matchSlice(s1));
+
+ const s2 = tr.c.TestUtils.newSliceEx(
+ {cat: 'cat', title: 'a', start: 1, duration: 3});
+ s2.args.key = ['innerValue1', 'innerValue2'];
+ assert.isTrue(new FullTextFilter('innerValue1').matchSlice(s2));
+ assert.isTrue(new FullTextFilter('innerValue2').matchSlice(s2));
+
+ const s3 = tr.c.TestUtils.newSliceEx(
+ {cat: 'cat', title: 'a', start: 1, duration: 3});
+ s3.args.key = ['one', 'two', 'three'];
+ assert.isTrue(new FullTextFilter('two').matchSlice(s3));
+
+ const s4 = tr.c.TestUtils.newSliceEx(
+ {cat: 'cat', title: 'a', start: 1, duration: 3});
+ s4.args.key = undefined;
+ assert.isFalse(new FullTextFilter('not there').matchSlice(s4));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/core/scripting_controller.html b/chromium/third_party/catapult/tracing/tracing/core/scripting_controller.html
new file mode 100644
index 00000000000..ec4a6570a36
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/core/scripting_controller.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+<link rel="import" href="/tracing/core/scripting_object.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.c', function() {
+ function ScriptingController(brushingStateController) {
+ this.brushingStateController_ = brushingStateController;
+ this.scriptObjectNames_ = [];
+ this.scriptObjectValues_ = [];
+ this.brushingStateController.addEventListener(
+ 'model-changed', this.onModelChanged_.bind(this));
+
+ // Register all scripting objects.
+ const typeInfos = ScriptingObjectRegistry.getAllRegisteredTypeInfos();
+ typeInfos.forEach(function(typeInfo) {
+ this.addScriptObject(typeInfo.metadata.name, typeInfo.constructor);
+ // Also make the object available to the DevTools inspector.
+ global[typeInfo.metadata.name] = typeInfo.constructor;
+ }, this);
+ }
+
+ function ScriptingObjectRegistry() {
+ }
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ tr.b.decorateExtensionRegistry(ScriptingObjectRegistry, options);
+
+ ScriptingController.prototype = {
+ get brushingStateController() {
+ return this.brushingStateController_;
+ },
+
+ onModelChanged_() {
+ this.scriptObjectValues_.forEach(function(v) {
+ if (v.onModelChanged) {
+ v.onModelChanged(this.brushingStateController.model);
+ }
+ }, this);
+ },
+
+ addScriptObject(name, value) {
+ this.scriptObjectNames_.push(name);
+ this.scriptObjectValues_.push(value);
+ },
+
+ executeCommand(command) {
+ const f = new Function(
+ this.scriptObjectNames_, 'return eval(' + command + ')');
+ return f.apply(null, this.scriptObjectValues_);
+ }
+ };
+
+ return {
+ ScriptingController,
+ ScriptingObjectRegistry,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/core/scripting_controller_test.html b/chromium/third_party/catapult/tracing/tracing/core/scripting_controller_test.html
new file mode 100644
index 00000000000..ab2737e0024
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/core/scripting_controller_test.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function FakeBrushingStateController() {
+ tr.b.EventTarget.call(this);
+
+ this.addAllEventsMatchingFilterToSelectionReturnValue = [];
+
+ this.viewport = undefined;
+ this.model = undefined;
+ this.selection = new tr.model.EventSet();
+ this.highlight = new tr.model.EventSet();
+ }
+ FakeBrushingStateController.prototype = {
+ __proto__: tr.b.EventTarget.prototype
+ };
+
+ test('scriptingControllerBasicArithmetic', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.c.ScriptingController(brushingStateController);
+ const result = controller.executeCommand('1 + 1');
+ assert.strictEqual(result, 2);
+ });
+
+ test('scriptingControllerNonLocalContext', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.c.ScriptingController(brushingStateController);
+ const x = 1;
+ controller.executeCommand('x = 2');
+ assert.strictEqual(x, 1);
+ });
+
+ test('scriptingControllerModifyGlobalContext', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.c.ScriptingController(brushingStateController);
+ global._x = 1;
+ controller.executeCommand('_x = 2');
+ assert.strictEqual(global._x, 2);
+ delete global._x;
+ });
+
+ test('scriptingControllerPersistentContext', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.c.ScriptingController(brushingStateController);
+ controller.executeCommand('a = 42');
+ const result = controller.executeCommand('a');
+ assert.strictEqual(result, 42);
+ });
+
+ test('scriptingControllerAddScriptObject', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.c.ScriptingController(brushingStateController);
+ controller.addScriptObject('z', 123);
+ const result = controller.executeCommand('z');
+ assert.strictEqual(result, 123);
+ });
+
+ test('scriptingControllerObjectRegistry', function() {
+ const brushingStateController = new FakeBrushingStateController();
+
+ tr.c.ScriptingObjectRegistry.register(
+ function() { return 123; },
+ {
+ name: 'testFunctionName'
+ }
+ );
+ const controller = new tr.c.ScriptingController(brushingStateController);
+ const result = controller.executeCommand('testFunctionName()');
+ assert.strictEqual(result, 123);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/core/scripting_object.html b/chromium/third_party/catapult/tracing/tracing/core/scripting_object.html
new file mode 100644
index 00000000000..e3dfade5ecb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/core/scripting_object.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.c', function() {
+ function ScriptingObject() {
+ }
+
+ ScriptingObject.prototype = {
+ onModelChanged(model) {
+ }
+ };
+
+ return {
+ ScriptingObject,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/core/test_utils.html b/chromium/third_party/catapult/tracing/tracing/core/test_utils.html
new file mode 100644
index 00000000000..ceaa4702765
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/core/test_utils.html
@@ -0,0 +1,498 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/model/counter.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/profile_node.html">
+<link rel="import" href="/tracing/model/scoped_id.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/model/stack_frame.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+<link rel="import" href="/tracing/model/thread_time_slice.html">
+<link rel="import" href="/tracing/model/user_model/stub_expectation.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Helper functions for use in tracing tests.
+ */
+tr.exportTo('tr.c', function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ function _getStartAndCpuDurationFromDict(
+ options, required, startFieldName, durationFieldName, endFieldName) {
+ if (options[startFieldName] === undefined) {
+ if (required) {
+ throw new Error('Too little information.');
+ } else {
+ return {start: undefined, duration: undefined};
+ }
+ }
+ if (options[durationFieldName] !== undefined &&
+ options[endFieldName] !== undefined) {
+ throw new Error('Too much information.');
+ }
+ if (options[durationFieldName] === undefined &&
+ options[endFieldName] === undefined) {
+ if (required) {
+ throw new Error('Too little information.');
+ } else {
+ return {start: undefined, duration: undefined};
+ }
+ }
+
+ let duration;
+ if (options[durationFieldName] !== undefined) {
+ duration = options[durationFieldName];
+ } else {
+ duration = options[endFieldName] - options[startFieldName];
+ }
+
+ return {
+ start: options[startFieldName],
+ duration
+ };
+ }
+
+ function _maybeGetCpuStartAndCpuDurationFromDict(options) {
+ return _getStartAndCpuDurationFromDict(
+ options, false, 'cpuStart', 'cpuDuration', 'cpuEnd');
+ }
+
+ function TestUtils() {
+ }
+
+ TestUtils.getStartAndDurationFromDict = function(options) {
+ return _getStartAndCpuDurationFromDict(
+ options, true, 'start', 'duration', 'end');
+ };
+
+ TestUtils.newAsyncSlice = function(start, duration, startThread, endThread) {
+ return TestUtils.newAsyncSliceNamed(
+ 'a', start, duration, startThread, endThread);
+ };
+
+ TestUtils.newAsyncSliceNamed = function(
+ name, start, duration, startThread, endThread) {
+ const asyncSliceConstructor =
+ tr.model.AsyncSlice.subTypes.getConstructor('', name);
+
+ const s = new asyncSliceConstructor('', name, 0, start);
+ s.duration = duration;
+ s.startThread = startThread;
+ s.endThread = endThread;
+ return s;
+ };
+
+ TestUtils.newAsyncSliceEx = function(options) {
+ const sd = TestUtils.getStartAndDurationFromDict(options);
+
+ const cat = options.cat ? options.cat : 'cat';
+ const title = options.title ? options.title : 'a';
+ const colorId = options.colorId || 0;
+
+ let isTopLevel;
+ if (options.isTopLevel !== undefined) {
+ isTopLevel = options.isTopLevel;
+ } else {
+ isTopLevel = false;
+ }
+
+ const asyncSliceConstructor =
+ tr.model.AsyncSlice.subTypes.getConstructor(cat, title);
+
+ const slice = new asyncSliceConstructor(
+ cat,
+ title,
+ colorId,
+ sd.start,
+ options.args ? options.args : {},
+ sd.duration, isTopLevel);
+
+ if (options.id) {
+ slice.id = options.id;
+ } else {
+ slice.id = tr.b.GUID.allocateSimple();
+ }
+
+ if (options.startStackFrame) {
+ slice.startStackFrame = options.startStackFrame;
+ }
+ if (options.endStackFrame) {
+ slice.endStackFrame = options.endStackFrame;
+ }
+ if (options.important) {
+ slice.important = options.important;
+ }
+ if (options.startThread) {
+ slice.startThread = options.startThread;
+ }
+ if (options.endThread) {
+ slice.endThread = options.endThread;
+ }
+ return slice;
+ };
+
+ TestUtils.newCounter = function(parent) {
+ return TestUtils.newCounterNamed(parent, 'a');
+ };
+
+ TestUtils.newCounterNamed = function(parent, name) {
+ const s = new tr.model.Counter(parent, name, null, name);
+ return s;
+ };
+
+ TestUtils.newCounterCategory = function(parent, category, name) {
+ const s = new tr.model.Counter(parent, name, category, name);
+ return s;
+ };
+
+ TestUtils.newCounterSeries = function() {
+ const s = new tr.model.CounterSeries('a', 0);
+ return s;
+ };
+
+ TestUtils.newFlowEventEx = function(options) {
+ if (options.start === undefined) throw new Error('Too little info');
+
+ const title = options.title ? options.title : 'a';
+
+ const colorId = options.colorId ? options.colorId : 0;
+
+ const sd = TestUtils.getStartAndDurationFromDict(options);
+
+ let id;
+ if (options.id !== undefined) {
+ id = options.id;
+ } else {
+ id = tr.b.GUID.allocateSimple();
+ }
+
+ const event = new tr.model.FlowEvent(
+ options.cat ? options.cat : 'cat',
+ id,
+ title,
+ colorId,
+ sd.start,
+ options.args ? options.args : {},
+ sd.duration);
+
+ if (options.startStackFrame) {
+ event.startStackFrame = options.startStackFrame;
+ }
+ if (options.endStackFrame) {
+ event.endStackFrame = options.endStackFrame;
+ }
+ if (options.important) {
+ event.important = options.important;
+ }
+ if (options.startSlice) {
+ event.startSlice = options.startSlice;
+ event.startSlice.outFlowEvents.push(event);
+ }
+ if (options.endSlice) {
+ event.endSlice = options.endSlice;
+ event.endSlice.inFlowEvents.push(event);
+ }
+ return event;
+ };
+
+ TestUtils.newThreadSlice = function(thread, state, start, duration, opt_cpu) {
+ const s = new tr.model.ThreadTimeSlice(
+ thread, state, 'cat', start, {}, duration);
+ if (opt_cpu) {
+ s.cpuOnWhichThreadWasRunning = opt_cpu;
+ }
+ return s;
+ };
+
+ TestUtils.newSampleNamed = function(
+ thread, sampleName, category, frameNames, start) {
+ let model;
+ if (thread.parent) {
+ model = thread.parent.model;
+ } else {
+ model = undefined;
+ }
+ const node = TestUtils.newProfileNodes(model, frameNames);
+ const s = new tr.model.Sample(
+ start, sampleName, node, thread, undefined, 1);
+ return s;
+ };
+
+ TestUtils.newSliceEx = function(options) {
+ const sd = TestUtils.getStartAndDurationFromDict(options);
+
+ const title = options.title ? options.title : 'a';
+
+ const colorId = options.colorId ? options.colorId : 0;
+
+ const cpuSD = _maybeGetCpuStartAndCpuDurationFromDict(options);
+
+ const cat = options.cat ? options.cat : 'cat';
+
+ const bindId = options.bindId ? options.bindId : 0;
+
+ let type;
+ if (options.type) {
+ type = options.type;
+ } else {
+ type = tr.model.ThreadSlice.subTypes.getConstructor(cat, title);
+ }
+
+ const slice = new type(
+ cat,
+ title,
+ colorId,
+ sd.start,
+ options.args ? options.args : {},
+ sd.duration,
+ cpuSD.start, cpuSD.duration,
+ undefined, bindId);
+
+ if (options.isTopLevel) slice.isTopLevel = true;
+
+ return slice;
+ };
+
+ TestUtils.newStackTrace = function(model, titles) {
+ let frame = undefined;
+ titles.forEach(function(title) {
+ frame = new tr.model.StackFrame(
+ frame, tr.b.GUID.allocateSimple(), title, 7);
+ if (model) model.addStackFrame(frame);
+ });
+ return frame;
+ };
+
+ TestUtils.newProfileNode = function(model, title, parentNode) {
+ return new tr.model.ProfileNode(
+ tr.b.GUID.allocateSimple(), title, parentNode);
+ };
+
+ TestUtils.newProfileNodes = function(model, titles) {
+ let node = undefined;
+ for (const title of titles) {
+ node = TestUtils.newProfileNode(model, title, node);
+ }
+ return node;
+ };
+
+ TestUtils.newSnapshot = function(model, options) {
+ return model.getOrCreateProcess(options.pid || 1).objects.addSnapshot(
+ new tr.model.ScopedId(options.scope || tr.model.OBJECT_DEFAULT_SCOPE,
+ options.id || '0x1'),
+ options.category || 'cat',
+ options.name || 'A',
+ options.ts || 0,
+ options.args || {},
+ options.baseTypeName);
+ };
+
+ TestUtils.findSliceNamed = function(slices, name) {
+ if (slices instanceof tr.model.SliceGroup) {
+ slices = slices.slices;
+ }
+ for (let i = 0; i < slices.length; i++) {
+ if (slices[i].title === name) return slices[i];
+ }
+ return undefined;
+ };
+
+ TestUtils.newInteractionRecord = function(parentModel, start, duration) {
+ return new tr.model.um.StubExpectation({
+ parentModel, start, duration});
+ };
+
+ TestUtils.newModel = function(customizeModelCallback) {
+ return TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneEmptyContainers: false,
+ customizeModelCallback
+ });
+ };
+
+ TestUtils.newModelWithEvents = function(events, opts) {
+ if (!(events instanceof Array)) events = [events];
+
+ opts = opts || {};
+
+ const io = new tr.importer.ImportOptions();
+ io.showImportWarnings = false;
+ io.customizeModelCallback = opts.customizeModelCallback;
+ io.trackDetailedModelStats = opts.trackDetailedModelStats === undefined ?
+ false : opts.trackDetailedModelStats;
+ io.shiftWorldToZero = opts.shiftWorldToZero === undefined ?
+ true : opts.shiftWorldToZero;
+ io.pruneEmptyContainers = opts.pruneEmptyContainers === undefined ?
+ true : opts.pruneEmptyContainers;
+ io.auditorConstructors = opts.auditorConstructors === undefined ?
+ [] : opts.auditorConstructors;
+
+ const m = new tr.Model();
+ const i = new tr.importer.Import(m, io);
+ i.importTraces(events);
+ return m;
+ };
+
+ TestUtils.newModelWithAuditor = function(customizeModelCallback, auditor) {
+ return TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneEmptyContainers: false,
+ customizeModelCallback,
+ auditorConstructors: [auditor]
+ });
+ };
+
+ TestUtils.newFakeThread = function() {
+ const process = {model: {}};
+ return new tr.model.Thread(process);
+ };
+
+ /** @constructor */
+ TestUtils.SourceGenerator = function() {
+ this.sourceList_ = [];
+ this.currentLineCommentList_ = [];
+ this.currentIndent_ = 0;
+ this.currentLineEmpty_ = true;
+ };
+
+ TestUtils.SourceGenerator.prototype = {
+ push(/* arguments */) {
+ if (this.currentLineEmpty_) {
+ this.sourceList_.push(' '.repeat(this.currentIndent_));
+ this.currentLineEmpty_ = false;
+ }
+ this.sourceList_.push.apply(
+ this.sourceList_, Array.prototype.slice.call(arguments));
+ },
+
+ pushComment(/* arguments */) {
+ this.currentLineCommentList_.push.apply(
+ this.currentLineCommentList_, Array.prototype.slice.call(arguments));
+ },
+
+ build() {
+ this.finishLine_();
+ return this.sourceList_.join('');
+ },
+
+ breakLine() {
+ this.finishLine_();
+ this.push('\n');
+ this.currentLineEmpty_ = true;
+ },
+
+ finishLine_() {
+ if (this.currentLineCommentList_.length === 0) return;
+ this.push(' // ');
+ this.push.apply(this, this.currentLineCommentList_);
+ this.push('.');
+ this.currentLineCommentList_ = [];
+ },
+
+ indentBlock(spaces, breakLine, blockCallback, opt_this) {
+ opt_this = opt_this || this;
+ this.currentIndent_ += spaces;
+ if (breakLine) this.breakLine();
+ blockCallback.call(opt_this);
+ this.currentIndent_ -= spaces;
+ },
+
+ formatSingleLineList(list, itemCallback, opt_this) {
+ opt_this = opt_this || this;
+ this.push('[');
+ Array.from(list).forEach(function(item, index) {
+ if (index > 0) this.push(', ');
+ itemCallback.call(opt_this, item, index);
+ }, this);
+ this.push(']');
+ },
+
+ formatMultiLineList(list, itemCallback, opt_this) {
+ opt_this = opt_this || this;
+ this.push('[');
+ this.indentBlock(2, false /* don't break line */, function() {
+ Array.from(list).forEach(function(item, index) {
+ if (index > 0) this.push(',');
+ this.breakLine();
+ itemCallback.call(opt_this, item, index);
+ }, this);
+ }, this);
+ if (list.length > 0) this.breakLine();
+ this.push(']');
+ },
+
+ formatString(string) {
+ if (string === undefined) {
+ this.push('undefined');
+ } else {
+ this.push('\'', string, '\'');
+ }
+ }
+ };
+
+ TestUtils.addSourceListing = function(test, source) {
+ const testSourceEl = document.createElement('pre');
+ testSourceEl.style.fontFamily = 'monospace';
+ Polymer.dom(testSourceEl).textContent = source;
+
+ const copyButtonEl = document.createElement('button');
+ Polymer.dom(copyButtonEl).textContent = 'Copy into to clipboard';
+ copyButtonEl.addEventListener('click', function() {
+ const selection = window.getSelection();
+
+ // Store the original selection.
+ const originalRanges = new Array(selection.rangeCount);
+ for (let i = 0; i < originalRanges.length; i++) {
+ originalRanges[i] = selection.getRangeAt(i);
+ }
+
+ // Copy the generated test source code into clipboard.
+ selection.removeAllRanges();
+ const range = document.createRange();
+ range.selectNode(testSourceEl);
+ selection.addRange(range);
+ document.execCommand('copy');
+
+ // Restore the original selection.
+ selection.removeAllRanges();
+ for (let i = 0; i < originalRanges.length; i++) {
+ selection.addRange(originalRanges[i]);
+ }
+ });
+
+ const outputEl = document.createElement('div');
+ Polymer.dom(outputEl).appendChild(copyButtonEl);
+ Polymer.dom(outputEl).appendChild(testSourceEl);
+ test.addHTMLOutput(outputEl);
+ };
+
+ TestUtils.newInstantEvent = function(options) {
+ const title = options.title;
+ const start = options.start;
+ if ((title === undefined) ||
+ (title === '') ||
+ (start === undefined)) {
+ throw new Error('too little information');
+ }
+
+ const category = options.category || 'category';
+ const colorId = options.colorId || 0;
+ const args = options.args || {};
+ return new tr.model.InstantEvent(
+ category, title, colorId, start, args);
+ };
+
+ return {
+ TestUtils,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/__init__.py b/chromium/third_party/catapult/tracing/tracing/extras/__init__.py
new file mode 100644
index 00000000000..a22a6ee39a9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/ads/domain_category.html b/chromium/third_party/catapult/tracing/tracing/extras/ads/domain_category.html
new file mode 100644
index 00000000000..bb153e81a05
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/ads/domain_category.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.ads', function() {
+ function Rule(expr, category) {
+ this.expr = expr;
+ this.category = category;
+ }
+
+ const CATEGORY_ADS = 'Ads';
+ const CATEGORY_ANALYTICS = 'Analytics';
+ const CATEGORY_CONTENT_RECOMMENDATION = 'Content Recommendation';
+ const CATEGORY_EXTENSIONS = 'Extensions';
+ const CATEGORY_OTHER = 'Other';
+ const CATEGORY_SOCIAL = 'Social';
+ const CATEGORY_TRACING = 'Tracing';
+
+ // Each rule is a tuple of (RegEx, Category). The first match will be used.
+ // For now we only assign 1 category to a domain; it may make sense to
+ // generalize this later to labeling domains with several categories.
+ const CATEGORY_DOMAIN_RULES = [
+ new Rule(/\.googleadservices\.com$/, CATEGORY_ADS),
+ new Rule(/\.moatads\.com$/, CATEGORY_ANALYTICS),
+ // Yahoo-Bing Contextual Ads
+ new Rule(/contextual\.media\.net$/, CATEGORY_ADS),
+ new Rule(/\.postrelease\.com$/, CATEGORY_CONTENT_RECOMMENDATION),
+ new Rule(/\.burt\.io$/, CATEGORY_ANALYTICS),
+ // Google DoubleClick, GPT
+ new Rule(/\.googletagservices\.com$/, CATEGORY_ADS),
+ new Rule(/\.ensighten\.com$/, CATEGORY_ANALYTICS),
+ // Amazon CloudFront
+ new Rule(/\.cloudfront\.net$/, CATEGORY_ADS),
+ new Rule(/\.viafoura\.net$/, CATEGORY_ANALYTICS),
+ // Google Content Ads/DoubleClick
+ new Rule(/\.googlesyndication\.com$/, CATEGORY_ADS),
+ // Google DoubleClick
+ new Rule(/\.doubleclick\.net$/, CATEGORY_ADS),
+ // Adobe Analytics/TagManager
+ new Rule(/\.adobetag\.com$/, CATEGORY_ANALYTICS),
+ new Rule(/\.rubiconproject\.com$/, CATEGORY_ADS),
+ new Rule(/\.sharethrough\.com$/, CATEGORY_ADS),
+ new Rule(/\.facebook\.net$/, CATEGORY_SOCIAL),
+ new Rule(/\.facebook\.com$/, CATEGORY_SOCIAL),
+ new Rule(/\.outbrain\.com$/, CATEGORY_CONTENT_RECOMMENDATION),
+ // Google Content Ads/Others
+ new Rule(/\.gstatic\.com$/, CATEGORY_ADS),
+ new Rule(/\.newrelic\.com$/, CATEGORY_ANALYTICS),
+ new Rule(/\.newsinc\.com$/, CATEGORY_ADS),
+ new Rule(/\.spingo\.com$/, CATEGORY_CONTENT_RECOMMENDATION),
+ new Rule(/\.visualrevenue\.com$/, CATEGORY_ANALYTICS),
+ new Rule(/cdn\.livefyre\.com$/, CATEGORY_SOCIAL),
+ new Rule(/\.dynamicyield\.com$/, CATEGORY_ANALYTICS),
+ new Rule(/cdn\.krxd\.net$/, CATEGORY_ANALYTICS),
+ new Rule(/\.chartbeat\.com$/, CATEGORY_ANALYTICS),
+ new Rule(/\.clicktale\.net$/, CATEGORY_ANALYTICS),
+ new Rule(/\.gravity\.com$/, CATEGORY_ANALYTICS),
+ new Rule(/\.brightcove\.com$/, CATEGORY_ANALYTICS),
+ new Rule(/^chrome:\/\//, CATEGORY_TRACING),
+ new Rule(/^chrome-extension:\/\//, CATEGORY_EXTENSIONS)
+ ];
+
+ function DomainCategory() {
+ }
+
+ DomainCategory.fromDomain = function(domain) {
+ for (let i = 0; i < CATEGORY_DOMAIN_RULES.length; i++) {
+ if (CATEGORY_DOMAIN_RULES[i].expr.test(domain)) {
+ return CATEGORY_DOMAIN_RULES[i].category;
+ }
+ }
+ return CATEGORY_OTHER;
+ };
+
+ return {
+ DomainCategory
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/ads/domain_category_test.html b/chromium/third_party/catapult/tracing/tracing/extras/ads/domain_category_test.html
new file mode 100644
index 00000000000..531726071dd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/ads/domain_category_test.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/ads/domain_category.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const DomainCategory = tr.e.ads.DomainCategory;
+ test('domainCategory', function() {
+ assert.strictEqual(
+ 'Ads',
+ DomainCategory.fromDomain('https://parnter.googleadservices.com'));
+ assert.strictEqual(
+ 'Analytics',
+ DomainCategory.fromDomain('https://x.adobetag.com'));
+ assert.strictEqual(
+ 'Social',
+ DomainCategory.fromDomain('http://x.facebook.net'));
+ assert.strictEqual(
+ 'Content Recommendation',
+ DomainCategory.fromDomain('http://xyz.outbrain.com'));
+ assert.strictEqual(
+ 'Tracing', DomainCategory.fromDomain('chrome://tracing'));
+ assert.strictEqual(
+ 'Extensions',
+ DomainCategory.fromDomain('chrome-extension://oiuy325oiu'));
+ assert.strictEqual(
+ 'Other',
+ DomainCategory.fromDomain('http://xyz.outbrain.com.au'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/android/android_auditor.html b/chromium/third_party/catapult/tracing/tracing/extras/android/android_auditor.html
new file mode 100644
index 00000000000..a1638d24baa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/android/android_auditor.html
@@ -0,0 +1,767 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/auditor.html">
+<link rel="import" href="/tracing/model/alert.html">
+<link rel="import" href="/tracing/model/frame.html">
+<link rel="import" href="/tracing/model/helpers/android_model_helper.html">
+<link rel="import" href="/tracing/model/thread_time_slice.html">
+<link rel="import" href="/tracing/model/user_model/response_expectation.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Class for Android-specific Auditing.
+ */
+tr.exportTo('tr.e.audits', function() {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const Auditor = tr.c.Auditor;
+ const AndroidModelHelper = tr.model.helpers.AndroidModelHelper;
+ const ColorScheme = tr.b.ColorScheme;
+ const Statistics = tr.b.math.Statistics;
+ const FRAME_PERF_CLASS = tr.model.FRAME_PERF_CLASS;
+ const Alert = tr.model.Alert;
+ const EventInfo = tr.model.EventInfo;
+ const Scalar = tr.b.Scalar;
+ const timeDurationInMs = tr.b.Unit.byName.timeDurationInMs;
+
+ // TODO: extract from VSYNC, since not all devices have vsync near 60fps
+ const EXPECTED_FRAME_TIME_MS = 16.67;
+
+ function getStart(e) { return e.start; }
+ function getDuration(e) { return e.duration; }
+ // used for general UI thread responsiveness alerts, falls back to duration
+ function getCpuDuration(e) {
+ return (e.cpuDuration !== undefined) ? e.cpuDuration : e.duration;
+ }
+
+ function frameIsActivityStart(frame) {
+ return frame.associatedEvents.any(x => x.title === 'activityStart');
+ }
+
+ function frameMissedDeadline(frame) {
+ return frame.args.deadline && frame.args.deadline < frame.end;
+ }
+
+ /** Builder object for EventInfo docLink structures */
+ function DocLinkBuilder() {
+ this.docLinks = [];
+ }
+ DocLinkBuilder.prototype = {
+ addAppVideo(name, videoId) {
+ this.docLinks.push({
+ label: 'Video Link',
+ textContent: ('Android Performance Patterns: ' + name),
+ href: 'https://www.youtube.com/watch?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE&v=' + videoId // @suppress longLineCheck
+ });
+ return this;
+ },
+ addDacRef(name, link) {
+ this.docLinks.push({
+ label: 'Doc Link',
+ textContent: (name + ' documentation'),
+ href: 'https://developer.android.com/reference/' + link
+ });
+ return this;
+ },
+ build() {
+ return this.docLinks;
+ }
+ };
+
+ /**
+ * Auditor for Android-specific traces.
+ * @constructor
+ */
+ function AndroidAuditor(model) {
+ Auditor.call(this, model);
+
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+ if (helper.apps.length || helper.surfaceFlinger) {
+ this.helper = helper;
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Rendering / RenderThread alerts - only available on SDK 22+
+ //////////////////////////////////////////////////////////////////////////////
+
+ AndroidAuditor.viewAlphaAlertInfo_ = new EventInfo(
+ 'Inefficient View alpha usage',
+ 'Setting an alpha between 0 and 1 has significant performance costs, if one of the fast alpha paths is not used.', // @suppress longLineCheck
+ new DocLinkBuilder()
+ .addAppVideo('Hidden Cost of Transparency', 'wIy8g8yNhNk')
+ .addDacRef('View#setAlpha()', 'android/view/View.html#setAlpha(float)') // @suppress longLineCheck
+ .build());
+ AndroidAuditor.saveLayerAlertInfo_ = new EventInfo(
+ 'Expensive rendering with Canvas#saveLayer()',
+ 'Canvas#saveLayer() incurs extremely high rendering cost. They disrupt the rendering pipeline when drawn, forcing a flush of drawing content. Instead use View hardware layers, or static Bitmaps. This enables the offscreen buffers to be reused in between frames, and avoids the disruptive render target switch.', // @suppress longLineCheck
+ new DocLinkBuilder()
+ .addAppVideo('Hidden Cost of Transparency', 'wIy8g8yNhNk')
+ .addDacRef('Canvas#saveLayerAlpha()', 'android/graphics/Canvas.html#saveLayerAlpha(android.graphics.RectF, int, int)') // @suppress longLineCheck
+ .build());
+ AndroidAuditor.getSaveLayerAlerts_ = function(frame) {
+ const badAlphaRegEx =
+ /^(.+) alpha caused (unclipped )?saveLayer (\d+)x(\d+)$/;
+ const saveLayerRegEx = /^(unclipped )?saveLayer (\d+)x(\d+)$/;
+
+ const ret = [];
+ const events = [];
+
+ frame.associatedEvents.forEach(function(slice) {
+ const match = badAlphaRegEx.exec(slice.title);
+ if (match) {
+ // due to bug in tracing code on SDK 22, ignore
+ // presence of 'unclipped' string in View alpha slices
+ const args = { 'view name': match[1],
+ 'width': parseInt(match[3]),
+ 'height': parseInt(match[4]) };
+ ret.push(new Alert(AndroidAuditor.viewAlphaAlertInfo_,
+ slice.start, [slice], args));
+ } else if (saveLayerRegEx.test(slice.title)) {
+ events.push(slice);
+ }
+ }, this);
+
+ if (events.length > ret.length) {
+ // more saveLayers than bad alpha can account for - add another alert
+
+ const unclippedSeen = Statistics.sum(events, function(slice) {
+ return saveLayerRegEx.exec(slice.title)[1] ? 1 : 0;
+ });
+ const clippedSeen = events.length - unclippedSeen;
+ const earliestStart = Statistics.min(events, function(slice) {
+ return slice.start;
+ });
+
+ const args = {
+ 'Unclipped saveLayer count (especially bad!)': unclippedSeen,
+ 'Clipped saveLayer count': clippedSeen
+ };
+
+ events.push(frame);
+ ret.push(new Alert(AndroidAuditor.saveLayerAlertInfo_,
+ earliestStart, events, args));
+ }
+
+ return ret;
+ };
+
+
+ AndroidAuditor.pathAlertInfo_ = new EventInfo(
+ 'Path texture churn',
+ 'Paths are drawn with a mask texture, so when a path is modified / newly drawn, that texture must be generated and uploaded to the GPU. Ensure that you cache paths between frames and do not unnecessarily call Path#reset(). You can cut down on this cost by sharing Path object instances between drawables/views.'); // @suppress longLineCheck
+ AndroidAuditor.getPathAlert_ = function(frame) {
+ const uploadRegEx = /^Generate Path Texture$/;
+
+ const events = frame.associatedEvents.filter(function(event) {
+ return event.title === 'Generate Path Texture';
+ });
+ const start = Statistics.min(events, getStart);
+ const duration = Statistics.sum(events, getDuration);
+
+ if (duration < 3) return undefined;
+
+ events.push(frame);
+ return new Alert(AndroidAuditor.pathAlertInfo_, start, events,
+ { 'Time spent': new Scalar(timeDurationInMs, duration) });
+ };
+
+
+ AndroidAuditor.uploadAlertInfo_ = new EventInfo(
+ 'Expensive Bitmap uploads',
+ 'Bitmaps that have been modified / newly drawn must be uploaded to the GPU. Since this is expensive if the total number of pixels uploaded is large, reduce the amount of Bitmap churn in this animation/context, per frame.'); // @suppress longLineCheck
+ AndroidAuditor.getUploadAlert_ = function(frame) {
+ const uploadRegEx = /^Upload (\d+)x(\d+) Texture$/;
+
+ const events = [];
+ let start = Number.POSITIVE_INFINITY;
+ let duration = 0;
+ let pixelsUploaded = 0;
+ frame.associatedEvents.forEach(function(event) {
+ const match = uploadRegEx.exec(event.title);
+ if (match) {
+ events.push(event);
+ start = Math.min(start, event.start);
+ duration += event.duration;
+ pixelsUploaded += parseInt(match[1]) * parseInt(match[2]);
+ }
+ });
+ if (events.length === 0 || duration < 3) return undefined;
+
+ const mPixels = (pixelsUploaded / 1000000).toFixed(2) + ' million';
+ const args = { 'Pixels uploaded': mPixels,
+ 'Time spent': new Scalar(timeDurationInMs, duration) };
+ events.push(frame);
+ return new Alert(AndroidAuditor.uploadAlertInfo_, start, events, args);
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+ // UI responsiveness alerts
+ //////////////////////////////////////////////////////////////////////////////
+
+ AndroidAuditor.ListViewInflateAlertInfo_ = new EventInfo(
+ 'Inflation during ListView recycling',
+ 'ListView item recycling involved inflating views. Ensure your Adapter#getView() recycles the incoming View, instead of constructing a new one.'); // @suppress longLineCheck
+ AndroidAuditor.ListViewBindAlertInfo_ = new EventInfo(
+ 'Inefficient ListView recycling/rebinding',
+ 'ListView recycling taking too much time per frame. Ensure your Adapter#getView() binds data efficiently.'); // @suppress longLineCheck
+ AndroidAuditor.getListViewAlert_ = function(frame) {
+ const events = frame.associatedEvents.filter(function(event) {
+ return event.title === 'obtainView' || event.title === 'setupListItem';
+ });
+ const duration = Statistics.sum(events, getCpuDuration);
+
+ if (events.length === 0 || duration < 3) return undefined;
+
+ // simplifying assumption - check for *any* inflation.
+ // TODO(ccraik): make 'inflate' slices associated events.
+ let hasInflation = false;
+ for (const event of events) {
+ if (event.findDescendentSlice('inflate')) {
+ hasInflation = true;
+ }
+ }
+
+ const start = Statistics.min(events, getStart);
+ const args = { 'Time spent': new Scalar(timeDurationInMs, duration) };
+ args['ListView items ' + (hasInflation ? 'inflated' : 'rebound')] =
+ events.length / 2;
+ const eventInfo = hasInflation ? AndroidAuditor.ListViewInflateAlertInfo_ :
+ AndroidAuditor.ListViewBindAlertInfo_;
+ events.push(frame);
+ return new Alert(eventInfo, start, events, args);
+ };
+
+
+ AndroidAuditor.measureLayoutAlertInfo_ = new EventInfo(
+ 'Expensive measure/layout pass',
+ 'Measure/Layout took a significant time, contributing to jank. Avoid triggering layout during animations.', // @suppress longLineCheck
+ new DocLinkBuilder()
+ .addAppVideo('Invalidations, Layouts, and Performance', 'we6poP0kw6E')
+ .build());
+ AndroidAuditor.getMeasureLayoutAlert_ = function(frame) {
+ const events = frame.associatedEvents.filter(function(event) {
+ return event.title === 'measure' || event.title === 'layout';
+ });
+ const duration = Statistics.sum(events, getCpuDuration);
+
+ if (events.length === 0 || duration < 3) return undefined;
+
+ const start = Statistics.min(events, getStart);
+ events.push(frame);
+ return new Alert(AndroidAuditor.measureLayoutAlertInfo_, start, events,
+ { 'Time spent': new Scalar(timeDurationInMs, duration) });
+ };
+
+
+ AndroidAuditor.viewDrawAlertInfo_ = new EventInfo(
+ 'Long View#draw()',
+ 'Recording the drawing commands of invalidated Views took a long time. Avoid significant work in View or Drawable custom drawing, especially allocations or drawing to Bitmaps.', // @suppress longLineCheck
+ new DocLinkBuilder()
+ .addAppVideo('Invalidations, Layouts, and Performance', 'we6poP0kw6E')
+ .addAppVideo('Avoiding Allocations in onDraw()', 'HAK5acHQ53E')
+ .build());
+ AndroidAuditor.getViewDrawAlert_ = function(frame) {
+ let slice = undefined;
+ for (const event of frame.associatedEvents) {
+ if (event.title === 'getDisplayList' ||
+ event.title === 'Record View#draw()') {
+ slice = event;
+ break;
+ }
+ }
+
+ if (!slice || getCpuDuration(slice) < 3) return undefined;
+ return new Alert(AndroidAuditor.viewDrawAlertInfo_, slice.start,
+ [slice, frame],
+ { 'Time spent': new Scalar(
+ timeDurationInMs, getCpuDuration(slice)) });
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Runtime alerts
+ //////////////////////////////////////////////////////////////////////////////
+
+ AndroidAuditor.blockingGcAlertInfo_ = new EventInfo(
+ 'Blocking Garbage Collection',
+ 'Blocking GCs are caused by object churn, and made worse by having large numbers of objects in the heap. Avoid allocating objects during animations/scrolling, and recycle Bitmaps to avoid triggering garbage collection.', // @suppress longLineCheck
+ new DocLinkBuilder()
+ .addAppVideo('Garbage Collection in Android', 'pzfzz50W5Uo')
+ .addAppVideo('Avoiding Allocations in onDraw()', 'HAK5acHQ53E')
+ .build());
+ AndroidAuditor.getBlockingGcAlert_ = function(frame) {
+ const events = frame.associatedEvents.filter(function(event) {
+ return event.title === 'DVM Suspend' ||
+ event.title === 'GC: Wait For Concurrent';
+ });
+ const blockedDuration = Statistics.sum(events, getDuration);
+ if (blockedDuration < 3) return undefined;
+
+ const start = Statistics.min(events, getStart);
+ events.push(frame);
+ return new Alert(AndroidAuditor.blockingGcAlertInfo_, start, events,
+ { 'Blocked duration': new Scalar(
+ timeDurationInMs, blockedDuration) });
+ };
+
+
+ AndroidAuditor.lockContentionAlertInfo_ = new EventInfo(
+ 'Lock contention',
+ 'UI thread lock contention is caused when another thread holds a lock that the UI thread is trying to use. UI thread progress is blocked until the lock is released. Inspect locking done within the UI thread, and ensure critical sections are short.'); // @suppress longLineCheck
+ AndroidAuditor.getLockContentionAlert_ = function(frame) {
+ const events = frame.associatedEvents.filter(function(event) {
+ return /^Lock Contention on /.test(event.title);
+ });
+
+ const blockedDuration = Statistics.sum(events, getDuration);
+ if (blockedDuration < 1) return undefined;
+
+ const start = Statistics.min(events, getStart);
+ events.push(frame);
+ return new Alert(AndroidAuditor.lockContentionAlertInfo_, start, events,
+ { 'Blocked duration': new Scalar(
+ timeDurationInMs, blockedDuration) });
+ };
+
+ AndroidAuditor.schedulingAlertInfo_ = new EventInfo(
+ 'Scheduling delay',
+ 'Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.'); // @suppress longLineCheck
+ AndroidAuditor.getSchedulingAlert_ = function(frame) {
+ let totalDuration = 0;
+ const totalStats = {};
+ for (const ttr of frame.threadTimeRanges) {
+ const stats = ttr.thread.getSchedulingStatsForRange(ttr.start, ttr.end);
+ for (const [key, value] of Object.entries(stats)) {
+ if (!(key in totalStats)) {
+ totalStats[key] = 0;
+ }
+ totalStats[key] += value;
+ totalDuration += value;
+ }
+ }
+
+ // only alert if frame not running for > 3ms. Note that we expect a frame
+ // to never describe intentionally idle time.
+ if (!(SCHEDULING_STATE.RUNNING in totalStats) ||
+ totalDuration === 0 ||
+ totalDuration - totalStats[SCHEDULING_STATE.RUNNING] < 3) {
+ return;
+ }
+
+ const args = {};
+ for (const [key, value] of Object.entries(totalStats)) {
+ let newKey = key;
+ if (key === SCHEDULING_STATE.RUNNABLE) {
+ newKey = 'Not scheduled, but runnable';
+ } else if (key === SCHEDULING_STATE.UNINTR_SLEEP) {
+ newKey = 'Blocking I/O delay';
+ }
+ args[newKey] = new Scalar(timeDurationInMs, value);
+ }
+
+ return new Alert(AndroidAuditor.schedulingAlertInfo_, frame.start, [frame],
+ args);
+ };
+
+ AndroidAuditor.prototype = {
+ __proto__: Auditor.prototype,
+
+ renameAndSort_() {
+ this.model.kernel.important = false;// auto collapse
+ // SurfaceFlinger first, other processes sorted by slice count
+ this.model.getAllProcesses().forEach(function(process) {
+ if (this.helper.surfaceFlinger &&
+ process === this.helper.surfaceFlinger.process) {
+ if (!process.name) {
+ process.name = 'SurfaceFlinger';
+ }
+ process.sortIndex = Number.NEGATIVE_INFINITY;
+ process.important = false; // auto collapse
+ return;
+ }
+
+ const uiThread = process.getThread(process.pid);
+ if (!process.name && uiThread && uiThread.name) {
+ if (/^ndroid\./.test(uiThread.name)) {
+ uiThread.name = 'a' + uiThread.name;
+ }
+ process.name = uiThread.name;
+
+ uiThread.name = 'UI Thread';
+ }
+
+ process.sortIndex = 0;
+ for (const tid in process.threads) {
+ process.sortIndex -= process.threads[tid].sliceGroup.slices.length;
+ }
+ }, this);
+
+ // ensure sequential, relative order for UI/Render/Worker threads
+ this.model.getAllThreads().forEach(function(thread) {
+ if (thread.tid === thread.parent.pid) {
+ thread.sortIndex = -3;
+ }
+ if (thread.name === 'RenderThread') {
+ thread.sortIndex = -2;
+ }
+ if (/^hwuiTask/.test(thread.name)) {
+ thread.sortIndex = -1;
+ }
+ });
+ },
+
+ pushFramesAndJudgeJank_() {
+ let badFramesObserved = 0;
+ let framesObserved = 0;
+ const surfaceFlinger = this.helper.surfaceFlinger;
+
+ this.helper.apps.forEach(function(app) {
+ // override frame list
+ app.process.frames = app.getFrames();
+
+ app.process.frames.forEach(function(frame) {
+ if (frame.totalDuration > EXPECTED_FRAME_TIME_MS * 2) {
+ badFramesObserved += 2;
+ frame.perfClass = FRAME_PERF_CLASS.TERRIBLE;
+ } else if (frame.totalDuration > EXPECTED_FRAME_TIME_MS ||
+ frameMissedDeadline(frame)) {
+ badFramesObserved++;
+ frame.perfClass = FRAME_PERF_CLASS.BAD;
+ } else {
+ frame.perfClass = FRAME_PERF_CLASS.GOOD;
+ }
+ });
+ framesObserved += app.process.frames.length;
+ });
+
+ if (framesObserved) {
+ const portionBad = badFramesObserved / framesObserved;
+ if (portionBad > 0.3) {
+ this.model.faviconHue = 'red';
+ } else if (portionBad > 0.05) {
+ this.model.faviconHue = 'yellow';
+ } else {
+ this.model.faviconHue = 'green';
+ }
+ }
+ },
+
+ pushEventInfo_() {
+ const appAnnotator = new AppAnnotator();
+ this.helper.apps.forEach(function(app) {
+ if (app.uiThread) {
+ appAnnotator.applyEventInfos(app.uiThread.sliceGroup);
+ }
+ if (app.renderThread) {
+ appAnnotator.applyEventInfos(app.renderThread.sliceGroup);
+ }
+ });
+ },
+
+ runAnnotate() {
+ if (!this.helper) return;
+
+ this.renameAndSort_();
+ this.pushFramesAndJudgeJank_();
+ this.pushEventInfo_();
+
+ this.helper.iterateImportantSlices(function(slice) {
+ slice.important = true;
+ });
+ },
+
+ runAudit() {
+ if (!this.helper) return;
+
+ const alerts = this.model.alerts;
+ this.helper.apps.forEach(function(app) {
+ app.getFrames().forEach(function(frame) {
+ alerts.push.apply(alerts, AndroidAuditor.getSaveLayerAlerts_(frame));
+
+ // skip most alerts for neutral or good frames
+ if (frame.perfClass === FRAME_PERF_CLASS.NEUTRAL ||
+ frame.perfClass === FRAME_PERF_CLASS.GOOD) {
+ return;
+ }
+
+ let alert = AndroidAuditor.getPathAlert_(frame);
+ if (alert) alerts.push(alert);
+
+ alert = AndroidAuditor.getUploadAlert_(frame);
+ if (alert) alerts.push(alert);
+
+ alert = AndroidAuditor.getListViewAlert_(frame);
+ if (alert) alerts.push(alert);
+
+ alert = AndroidAuditor.getMeasureLayoutAlert_(frame);
+ if (alert) alerts.push(alert);
+
+ alert = AndroidAuditor.getViewDrawAlert_(frame);
+ if (alert) alerts.push(alert);
+
+ alert = AndroidAuditor.getBlockingGcAlert_(frame);
+ if (alert) alerts.push(alert);
+
+ alert = AndroidAuditor.getLockContentionAlert_(frame);
+ if (alert) alerts.push(alert);
+
+ alert = AndroidAuditor.getSchedulingAlert_(frame);
+ if (alert) alerts.push(alert);
+ });
+ }, this);
+
+ this.addRenderingInteractionRecords();
+ this.addInputInteractionRecords();
+ },
+
+ addRenderingInteractionRecords() {
+ const events = [];
+ this.helper.apps.forEach(function(app) {
+ events.push.apply(events, app.getAnimationAsyncSlices());
+ events.push.apply(events, app.getFrames());
+ });
+
+ const mergerFunction = function(events) {
+ const ir = new tr.model.um.ResponseExpectation(
+ this.model, 'Rendering',
+ events[0].min,
+ events[events.length - 1].max - events[0].min);
+ this.model.userModel.expectations.push(ir);
+ }.bind(this);
+ tr.b.math.mergeRanges(
+ tr.b.math.convertEventsToRanges(events), 30, mergerFunction);
+ },
+
+ addInputInteractionRecords() {
+ const inputSamples = [];
+ this.helper.apps.forEach(function(app) {
+ inputSamples.push.apply(inputSamples, app.getInputSamples());
+ });
+
+ const mergerFunction = function(events) {
+ const ir = new tr.model.um.ResponseExpectation(
+ this.model, 'Input',
+ events[0].min,
+ events[events.length - 1].max - events[0].min);
+ this.model.userModel.expectations.push(ir);
+ }.bind(this);
+ const inputRanges = inputSamples.map(function(sample) {
+ return tr.b.math.Range.fromExplicitRange(
+ sample.timestamp, sample.timestamp);
+ });
+ tr.b.math.mergeRanges(inputRanges, 30, mergerFunction);
+ }
+ };
+
+ Auditor.register(AndroidAuditor);
+
+ function AppAnnotator() {
+ this.titleInfoLookup = new Map();
+ this.titleParentLookup = new Map();
+ this.build_();
+ }
+
+ AppAnnotator.prototype = {
+ build_() {
+ const registerEventInfo = function(dict) {
+ this.titleInfoLookup.set(dict.title, new EventInfo(
+ dict.title, dict.description, dict.docLinks));
+ if (dict.parents) {
+ this.titleParentLookup.set(dict.title, dict.parents);
+ }
+ }.bind(this);
+
+ registerEventInfo({
+ title: 'inflate',
+ description: 'Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes.'}); // @suppress longLineCheck
+
+ //////////////////////////////////////////////////////////////////////////
+ // Adapter view
+ //////////////////////////////////////////////////////////////////////////
+ registerEventInfo({
+ title: 'obtainView',
+ description: 'Adapter#getView() called to bind content to a recycled View that is being presented.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'setupListItem',
+ description: 'Attached a newly-bound, recycled View to its parent ListView.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'setupGridItem',
+ description: 'Attached a newly-bound, recycled View to its parent GridView.'}); // @suppress longLineCheck
+
+ //////////////////////////////////////////////////////////////////////////
+ // Choreographer (tracing enabled on M+)
+ //////////////////////////////////////////////////////////////////////////
+ const choreographerLinks = new DocLinkBuilder()
+ .addDacRef('Choreographer', 'android/view/Choreographer.html') // @suppress longLineCheck
+ .build();
+ registerEventInfo({
+ title: 'Choreographer#doFrame',
+ docLinks: choreographerLinks,
+ description: 'Choreographer executes frame callbacks for inputs, animations, and rendering traversals. When this work is done, a frame will be presented to the user.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'input',
+ parents: ['Choreographer#doFrame'],
+ docLinks: choreographerLinks,
+ description: 'Input callbacks are processed. This generally encompasses dispatching input to Views, as well as any work the Views do to process this input/gesture.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'animation',
+ parents: ['Choreographer#doFrame'],
+ docLinks: choreographerLinks,
+ description: 'Animation callbacks are processed. This is generally minimal work, as animations determine progress for the frame, and push new state to animated objects (such as setting View properties).'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'traversals',
+ parents: ['Choreographer#doFrame'],
+ docLinks: choreographerLinks,
+ description: 'Primary draw traversals. This is the primary traversal of the View hierarchy, including layout and draw passes.'}); // @suppress longLineCheck
+
+ //////////////////////////////////////////////////////////////////////////
+ // performTraversals + sub methods
+ //////////////////////////////////////////////////////////////////////////
+ const traversalParents = ['Choreographer#doFrame', 'performTraversals'];
+ const layoutLinks = new DocLinkBuilder()
+ .addDacRef('View#Layout', 'android/view/View.html#Layout')
+ .build();
+ registerEventInfo({
+ title: 'performTraversals',
+ description: 'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'measure',
+ parents: traversalParents,
+ docLinks: layoutLinks,
+ description: 'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'layout',
+ parents: traversalParents,
+ docLinks: layoutLinks,
+ description: 'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'}); // @suppress longLineCheck
+ const drawString = 'Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.'; // @suppress longLineCheck
+ registerEventInfo({
+ title: 'draw',
+ parents: traversalParents,
+ description: drawString});
+
+ const recordString = 'Every invalidated View\'s drawing commands are recorded. Each will have View#draw() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.'; // @suppress longLineCheck
+ registerEventInfo({
+ title: 'getDisplayList', // Legacy name for compatibility.
+ parents: ['draw'],
+ description: recordString});
+ registerEventInfo({
+ title: 'Record View#draw()',
+ parents: ['draw'],
+ description: recordString});
+
+ registerEventInfo({
+ title: 'drawDisplayList',
+ parents: ['draw'],
+ description: 'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU. On Android L and higher devices, this work is done on a dedicated RenderThread, instead of on the UI Thread.'}); // @suppress longLineCheck
+
+ //////////////////////////////////////////////////////////////////////////
+ // RenderThread
+ //////////////////////////////////////////////////////////////////////////
+ registerEventInfo({
+ title: 'DrawFrame',
+ description: 'RenderThread portion of the standard UI/RenderThread split frame. This represents the actual formation and issuing of drawing commands to the GPU.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'doFrame',
+ description: 'RenderThread animation frame. Represents drawing work done by the RenderThread on a frame where the UI thread did not produce new drawing content.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'syncFrameState',
+ description: 'Sync stage between the UI thread and the RenderThread, where the UI thread hands off a frame (including information about modified Views). Time in this method primarily consists of uploading modified Bitmaps to the GPU. After this sync is completed, the UI thread is unblocked, and the RenderThread starts to render the frame.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'flush drawing commands',
+ description: 'Issuing the now complete drawing commands to the GPU.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'eglSwapBuffers',
+ description: 'Complete GPU rendering of the frame.'}); // @suppress longLineCheck
+
+ //////////////////////////////////////////////////////////////////////////
+ // RecyclerView
+ //////////////////////////////////////////////////////////////////////////
+ registerEventInfo({
+ title: 'RV Scroll',
+ description: 'RecyclerView is calculating a scroll. If there are too many of these in Systrace, some Views inside RecyclerView might be causing it. Try to avoid using EditText, focusable views or handle them with care.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'RV OnLayout',
+ description: 'OnLayout has been called by the View system. If this shows up too many times in Systrace, make sure the children of RecyclerView do not update themselves directly. This will cause a full re-layout but when it happens via the Adapter notifyItemChanged, RecyclerView can avoid full layout calculation.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'RV FullInvalidate',
+ description: 'NotifyDataSetChanged or equal has been called. If this is taking a long time, try sending granular notify adapter changes instead of just calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter might help.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'RV PartialInvalidate',
+ description: 'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'RV OnBindView',
+ description: 'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'}); // @suppress longLineCheck
+ registerEventInfo({
+ title: 'RV CreateView',
+ description: 'RecyclerView is creating a new View. If too many of these are present: 1) There might be a problem in Recycling (e.g. custom Animations that set transient state and prevent recycling or ItemAnimator not implementing the contract properly. See Adapter#onFailedToRecycleView(ViewHolder). 2) There may be too many item view types. Try merging them. 3) There might be too many itemChange animations and not enough space in RecyclerPool. Try increasing your pool size and item cache size.'}); // @suppress longLineCheck
+
+ //////////////////////////////////////////////////////////////////////////
+ // Graphics + Composition
+ //////////////////////////////////////////////////////////////////////////
+ // TODO(ccraik): SurfaceFlinger work
+ registerEventInfo({
+ title: 'eglSwapBuffers',
+ description: 'The CPU has finished producing drawing commands, and is flushing drawing work to the GPU, and posting that buffer to the consumer (which is often SurfaceFlinger window composition). Once this is completed, the GPU can produce the frame content without any involvement from the CPU.'}); // @suppress longLineCheck
+ },
+
+ applyEventInfosRecursive_(parentNames, slice) {
+ const checkExpectedParentNames = function(expectedParentNames) {
+ if (!expectedParentNames) return true;
+ return expectedParentNames.some(function(name) {
+ return parentNames.has(name);
+ });
+ };
+
+ // Set EventInfo on the slice if it matches title, and parent.
+ if (this.titleInfoLookup.has(slice.title)) {
+ if (checkExpectedParentNames(this.titleParentLookup.get(slice.title))) {
+ slice.info = this.titleInfoLookup.get(slice.title);
+ }
+ }
+
+ // Push slice into parentNames, and recurse over subSlices.
+ if (slice.subSlices.length > 0) {
+ // Increment title in parentName dict.
+ if (!parentNames.has(slice.title)) {
+ parentNames.set(slice.title, 0);
+ }
+ parentNames.set(slice.title, parentNames.get(slice.title) + 1);
+
+ // Recurse over subSlices.
+ slice.subSlices.forEach(function(subSlice) {
+ this.applyEventInfosRecursive_(parentNames, subSlice);
+ }, this);
+
+ // Decrement title in parentName dict.
+ parentNames.set(slice.title, parentNames.get(slice.title) - 1);
+ if (parentNames.get(slice.title) === 0) {
+ delete parentNames[slice.title];
+ }
+ }
+ },
+
+ applyEventInfos(sliceGroup) {
+ sliceGroup.topLevelSlices.forEach(function(slice) {
+ this.applyEventInfosRecursive_(new Map(), slice);
+ }, this);
+ }
+ };
+
+ return {
+ AndroidAuditor,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/android/android_auditor_test.html b/chromium/third_party/catapult/tracing/tracing/extras/android/android_auditor_test.html
new file mode 100644
index 00000000000..bb042eac514
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/android/android_auditor_test.html
@@ -0,0 +1,424 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/android/android_auditor.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/model/frame.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const FRAME_PERF_CLASS = tr.model.FRAME_PERF_CLASS;
+ const newThreadSlice = tr.c.TestUtils.newThreadSlice;
+ const Scalar = tr.b.Scalar;
+ const timeDurationInMs = tr.b.Unit.byName.timeDurationInMs;
+
+ test('constructorSliceName', function() {
+ // verify 'constructor' slice name doesn't break the auditor
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ renderThread.name = 'RenderThread';
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'constructor', start: 200, duration: 5}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 0);
+ });
+
+ test('saveLayerAlert_badAlpha', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ renderThread.name = 'RenderThread';
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'doFrame', start: 200, duration: 5}));
+ renderThread.sliceGroup.pushSlice(newSliceEx({
+ title: 'BadAlphaView alpha caused saveLayer 480x320',
+ start: 203,
+ duration: 1
+ }));
+
+ // doesn't create alert, since bad alpha accounts for this savelayer
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'unclipped saveLayer 480x320', start: 204, duration: 1}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 1);
+
+ const alert = model.alerts[0];
+ assert.strictEqual(alert.args['view name'], 'BadAlphaView');
+ assert.strictEqual(alert.args.width, 480);
+ assert.strictEqual(alert.args.height, 320);
+ });
+
+ test('saveLayerAlert_canvas', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ renderThread.name = 'RenderThread';
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'doFrame', start: 200, duration: 5}));
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'saveLayer 480x320', start: 204, duration: 1}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 1);
+
+ const alert = model.alerts[0];
+ assert.strictEqual(alert.args['Clipped saveLayer count'], 1);
+ assert.strictEqual(alert.associatedEvents.length, 2);
+ });
+
+ test('generatePathAlert', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ renderThread.name = 'RenderThread';
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'doFrame', start: 0, duration: 20}));
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'Generate Path Texture', start: 0, duration: 3}));
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'Generate Path Texture', start: 3, duration: 6}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 1);
+
+ const alert = model.alerts[0];
+ assert.deepEqual(alert.args['Time spent'],
+ new Scalar(timeDurationInMs, 9));
+ assert.strictEqual(alert.associatedEvents.length, 3);
+ });
+
+ test('uploadAlert', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ renderThread.name = 'RenderThread';
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'doFrame', start: 0, duration: 20}));
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'Upload 1000x1000 Texture', start: 0, duration: 15}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 1);
+
+ const alert = model.alerts[0];
+ assert.strictEqual(alert.args['Pixels uploaded'], '1.00 million');
+ assert.deepEqual(alert.args['Time spent'],
+ new Scalar(timeDurationInMs, 15));
+ assert.strictEqual(alert.associatedEvents.length, 2);
+ });
+
+ test('listViewAlert', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'obtainView', start: 0, duration: 5}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'setupListItem', start: 5, duration: 5}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'obtainView', start: 10, duration: 5}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'setupListItem', start: 15, duration: 5}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 20, duration: 5}));
+
+ // short frame, so no alert should be generated
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'obtainView', start: 50, duration: 5}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'setupListItem', start: 55, duration: 5}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 60, duration: 1}));
+
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'obtainView', start: 100, duration: 10}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'inflate', start: 101, duration: 8}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'setupListItem', start: 110, duration: 10}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 120, duration: 5}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 2);
+ let alert = model.alerts[0];
+ assert.strictEqual(alert.args['ListView items rebound'], 2);
+ assert.deepEqual(alert.args['Time spent'],
+ new Scalar(timeDurationInMs, 20));
+ assert.strictEqual(alert.associatedEvents.length, 5);
+
+ alert = model.alerts[1];
+ assert.strictEqual(alert.args['ListView items inflated'], 1);
+ assert.deepEqual(alert.args['Time spent'],
+ new Scalar(timeDurationInMs, 20));
+ // note: inflate not assoc.
+ assert.strictEqual(alert.associatedEvents.length, 3);
+ });
+
+ test('measureLayoutAlert', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 20}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'measure', start: 0, duration: 5}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'layout', start: 10, duration: 5}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 1);
+
+ const alert = model.alerts[0];
+ assert.deepEqual(alert.args['Time spent'],
+ new Scalar(timeDurationInMs, 10));
+ assert.strictEqual(alert.associatedEvents.length, 3);
+ });
+
+ test('viewDrawAlert', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ // modern naming
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 20}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'Record View#draw()', start: 0, duration: 10}));
+
+ // legacy naming
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 40, duration: 20}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'getDisplayList', start: 40, duration: 10}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 2);
+ assert.deepEqual(model.alerts[0].args['Time spent'],
+ new Scalar(timeDurationInMs, 10));
+ assert.deepEqual(model.alerts[1].args['Time spent'],
+ new Scalar(timeDurationInMs, 10));
+ });
+
+ test('blockingGcAlert', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ const sliceGroup = uiThread.sliceGroup;
+ sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 20}));
+ sliceGroup.pushSlice(newSliceEx(
+ {title: 'DVM Suspend', start: 0, duration: 15}));
+
+ sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 50, duration: 20}));
+ sliceGroup.pushSlice(newSliceEx(
+ {title: 'GC: Wait For Concurrent', start: 50, duration: 15}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 2);
+ assert.deepEqual(model.alerts[0].args['Blocked duration'],
+ new Scalar(timeDurationInMs, 15));
+ assert.deepEqual(model.alerts[1].args['Blocked duration'],
+ new Scalar(timeDurationInMs, 15));
+ });
+
+ test('lockContentionAlert', function() {
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ const sliceGroup = uiThread.sliceGroup;
+ sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 20}));
+ sliceGroup.pushSlice(newSliceEx(
+ {title: 'Lock Contention on a lock', start: 0, duration: 15}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(model.alerts.length, 1);
+ assert.deepEqual(model.alerts[0].args['Blocked duration'],
+ new Scalar(timeDurationInMs, 15));
+ });
+
+ test('schedulingAlerts', function() {
+ let model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 20}));
+ uiThread.timeSlices = [
+ newThreadSlice(uiThread, SCHEDULING_STATE.RUNNING, 0, 6),
+ newThreadSlice(uiThread, SCHEDULING_STATE.RUNNABLE, 6, 10),
+ newThreadSlice(uiThread, SCHEDULING_STATE.RUNNING, 16, 4)];
+ }, tr.e.audits.AndroidAuditor);
+ assert.strictEqual(model.alerts.length, 1);
+ let alert = model.alerts[0];
+ assert.strictEqual(alert.info.title, 'Scheduling delay');
+ assert.deepEqual(alert.args['Not scheduled, but runnable'],
+ new Scalar(timeDurationInMs, 10));
+
+ model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 20}));
+ uiThread.timeSlices = [
+ newThreadSlice(uiThread, SCHEDULING_STATE.RUNNING, 0, 5),
+ newThreadSlice(uiThread, SCHEDULING_STATE.UNINTR_SLEEP, 5, 10),
+ newThreadSlice(uiThread, SCHEDULING_STATE.RUNNING, 15, 5)];
+ }, tr.e.audits.AndroidAuditor);
+ assert.strictEqual(model.alerts.length, 1);
+ alert = model.alerts[0];
+ assert.strictEqual(alert.info.title, 'Scheduling delay');
+ assert.deepEqual(alert.args['Blocking I/O delay'],
+ new Scalar(timeDurationInMs, 10));
+ });
+
+ test('addFramesToModel', function() {
+ let process;
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ process = model.getOrCreateProcess(1);
+ const uiThread = process.getOrCreateThread(1);
+
+ // High level choreographer frame signal
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'Choreographer#doFrame', start: 0, duration: 8}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'Choreographer#doFrame', start: 16, duration: 20}));
+
+ // Old devices only have 'performTraversals'
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 40, duration: 90}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.strictEqual(process.frames.length, 3);
+ assert.closeTo(process.frames[0].totalDuration, 8, 1e-5);
+ assert.closeTo(process.frames[1].totalDuration, 20, 1e-5);
+ assert.closeTo(process.frames[2].totalDuration, 90, 1e-5);
+
+ assert.strictEqual(process.frames[0].perfClass,
+ FRAME_PERF_CLASS.GOOD);
+ assert.strictEqual(process.frames[1].perfClass,
+ FRAME_PERF_CLASS.BAD);
+ assert.strictEqual(process.frames[2].perfClass,
+ FRAME_PERF_CLASS.TERRIBLE);
+ });
+
+ test('processRenameAndSort', function() {
+ let appProcess;
+ let sfProcess;
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ appProcess = model.getOrCreateProcess(1);
+ const uiThread = appProcess.getOrCreateThread(1);
+ uiThread.name = 'ndroid.systemui';
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 8}));
+
+ sfProcess = model.getOrCreateProcess(2);
+ const sfThread = sfProcess.getOrCreateThread(2);
+ sfThread.name = '/system/bin/surfaceflinger';
+ sfThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'doComposition', start: 8, duration: 2}));
+ }, tr.e.audits.AndroidAuditor);
+
+ // both processes should be renamed
+ assert.strictEqual(appProcess.name, 'android.systemui');
+ assert.strictEqual(sfProcess.name, 'SurfaceFlinger');
+
+ assert.isTrue(sfProcess.sortIndex < appProcess.sortIndex);
+ assert.isTrue(appProcess.important);
+ assert.isFalse(sfProcess.important);
+ });
+
+ test('eventInfo', function() {
+ const eventsExpectingInfo = [];
+ const eventsNotExpectingInfo = [];
+
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const appProcess = model.getOrCreateProcess(1);
+ const uiThread = appProcess.getOrCreateThread(1);
+ uiThread.name = 'ndroid.systemui';
+
+ const pushInfoSlice = function(slice) {
+ eventsExpectingInfo.push(slice);
+ uiThread.sliceGroup.pushSlice(slice);
+ };
+ const pushNonInfoSlice = function(slice) {
+ eventsNotExpectingInfo.push(slice);
+ uiThread.sliceGroup.pushSlice(slice);
+ };
+
+ pushInfoSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 10}));
+ pushInfoSlice(newSliceEx({title: 'measure', start: 0, duration: 2}));
+ pushInfoSlice(newSliceEx({title: 'layout', start: 2, duration: 1}));
+ pushInfoSlice(newSliceEx({title: 'draw', start: 3, duration: 7}));
+
+ // Out of place slices should not be tagged.
+ pushNonInfoSlice(newSliceEx({title: 'measure', start: 11, duration: 1}));
+ pushNonInfoSlice(newSliceEx({title: 'draw', start: 12, duration: 1}));
+ }, tr.e.audits.AndroidAuditor);
+
+ eventsExpectingInfo.forEach(function(event) {
+ assert.notEqual(event.info, undefined);
+ });
+
+ eventsNotExpectingInfo.forEach(function(event) {
+ assert.strictEqual(event.info, undefined);
+ });
+ });
+
+ test('drawingThreadPriorities', function() {
+ let uiThread;
+ let renderThread;
+ let workerThread;
+ let otherThread;
+ const model = tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const appProcess = model.getOrCreateProcess(1);
+
+ uiThread = appProcess.getOrCreateThread(1);
+ uiThread.name = 'ndroid.systemui';
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 0, duration: 4}));
+
+ renderThread = appProcess.getOrCreateThread(2);
+ renderThread.name = 'RenderThread';
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'DrawFrame', start: 3, duration: 4}));
+
+ workerThread = appProcess.getOrCreateThread(3);
+ workerThread.name = 'hwuiTask1';
+ workerThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'work', start: 4, duration: 1}));
+
+ otherThread = appProcess.getOrCreateThread(4);
+ otherThread.name = 'other';
+ otherThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'otherWork', start: 0, duration: 2}));
+ }, tr.e.audits.AndroidAuditor);
+
+ assert.isTrue(uiThread.sortIndex < renderThread.sortIndex);
+ assert.isTrue(renderThread.sortIndex < workerThread.sortIndex);
+ assert.isTrue(workerThread.sortIndex < otherThread.sortIndex);
+ });
+
+ test('favicon', function() {
+ const createModelWithJank = function(percentageJank) {
+ return tr.c.TestUtils.newModelWithAuditor(function(model) {
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ for (let i = 0; i < 100; i++) {
+ const slice = newSliceEx({
+ title: 'performTraversals',
+ start: 30 * i,
+ duration: i <= percentageJank ? 24 : 8
+ });
+ uiThread.sliceGroup.pushSlice(slice);
+ }
+ }, tr.e.audits.AndroidAuditor);
+ };
+ assert.strictEqual(createModelWithJank(3).faviconHue, 'green');
+ assert.strictEqual(createModelWithJank(10).faviconHue, 'yellow');
+ assert.strictEqual(createModelWithJank(50).faviconHue, 'red');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/blame_context.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/blame_context.html
new file mode 100644
index 00000000000..08a8842b1f9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/blame_context.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview BlameContext is the Trace Viewer side correspondence of
+ * Chrome's class base::trace_event::BlameContext. More specifically,
+ *
+ * BlameContextSnapshot, which inherits from ObjectSnapshot, is the base class
+ * of all snapshots of blame contexts traced in Chrome.
+ *
+ * BlameContextInstance, which inherits from ObjectInstance, gathers snapshots
+ * of the same blame context traced in Chrome.
+ *
+ * BlameContextSnapshot and BlameContextInstance should never be instantiated
+ * directly. Subclasses corresponding to different BlameContexts in Chrome
+ * should define their own BlameContextSnapshot and BlameContextInstance
+ * specializations for instantiation.
+ *
+ */
+tr.exportTo('tr.e.chrome', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+ const ObjectInstance = tr.model.ObjectInstance;
+
+ function BlameContextSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ }
+
+ BlameContextSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ /**
+ * Returns the parent in the context tree.
+ */
+ get parentContext() {
+ if (this.args.parent instanceof BlameContextSnapshot) {
+ return this.args.parent;
+ }
+ return undefined;
+ },
+
+ get userFriendlyName() {
+ return 'BlameContext';
+ }
+ };
+
+ function BlameContextInstance() {
+ ObjectInstance.apply(this, arguments);
+ }
+
+ BlameContextInstance.prototype = {
+ __proto__: ObjectInstance.prototype,
+
+ /**
+ * Returns the type of the blame context, to be overriden by subclasses.
+ */
+ get blameContextType() {
+ throw new Error('Not implemented');
+ }
+ };
+
+ return {
+ BlameContextSnapshot,
+ BlameContextInstance,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/blame_context_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/blame_context_test.html
new file mode 100644
index 00000000000..8d6f4b5be5c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/blame_context_test.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/blame_context.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const BlameContextSnapshot = tr.e.chrome.BlameContextSnapshot;
+ const BlameContextInstance = tr.e.chrome.BlameContextInstance;
+
+ function TestBlameContextSnapshot() {
+ BlameContextSnapshot.apply(this, arguments);
+ }
+
+ TestBlameContextSnapshot.prototype = {
+ __proto__: BlameContextSnapshot.prototype,
+
+ get userFriendlyName() {
+ return 'Test';
+ }
+ };
+
+ tr.model.ObjectSnapshot.subTypes.register(
+ TestBlameContextSnapshot,
+ {typeName: 'Test'});
+
+ function TestBlameContextInstance() {
+ BlameContextInstance.apply(this, arguments);
+ }
+
+ TestBlameContextInstance.prototype = {
+ __proto__: BlameContextInstance.prototype,
+
+ get blameContextType() {
+ return 'Test';
+ }
+ };
+
+ tr.model.ObjectInstance.subTypes.register(
+ TestBlameContextInstance,
+ {typeName: 'Test'});
+
+ const TestUtils = tr.c.TestUtils;
+
+ test('parentContext', function() {
+ let parent;
+ let child;
+ TestUtils.newModel(function(model) {
+ parent = TestUtils.newSnapshot(model, {id: '0x1', name: 'Test'});
+ child = TestUtils.newSnapshot(model, {id: '0x2', name: 'Test',
+ args: {parent: {id_ref: '0x1'}}});
+ });
+
+ assert.isTrue(child.parentContext === parent);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/frame_blame_context_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/frame_blame_context_test.html
new file mode 100644
index 00000000000..43b15ae43be
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/frame_blame_context_test.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/frame_tree_node.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/render_frame.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/top_level.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TestUtils = tr.c.TestUtils;
+
+ test('crossProcessCounterpart', function() {
+ let frameTreeNode;
+ let renderFrame;
+ TestUtils.newModel(function(model) {
+ // Add a toplevel to make the context tree consistent with the spec,
+ // though its functionality is not tested here.
+ TestUtils.newSnapshot(model, {
+ pid: 1, name: 'TopLevel', id: '0x1',
+ scope: 'PlatformThread', category: 'blink'});
+ renderFrame = TestUtils.newSnapshot(
+ model, {
+ pid: 1, name: 'RenderFrame', id: '0x2', scope: 'RenderFrame',
+ category: 'blink', args: {
+ parent: {scope: 'PlatformThread', id_ref: '0x1'}}});
+ frameTreeNode = TestUtils.newSnapshot(
+ model, {
+ pid: 2, name: 'FrameTreeNode', id: '0x3', scope: 'FrameTreeNode',
+ category: 'navigation', args: {
+ renderFrame: {scope: 'RenderFrame', id_ref: '0x2', pid_ref: 1}}});
+ });
+
+ assert.isTrue(frameTreeNode.renderFrame === renderFrame);
+ assert.isTrue(renderFrame.frameTreeNode === frameTreeNode);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/frame_tree_node.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/frame_tree_node.html
new file mode 100644
index 00000000000..bfd21093de5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/frame_tree_node.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/blame_context/blame_context.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Trace Viewer side's correspondence of Chrome's
+ * content::FrameTreeNode class.
+ *
+ */
+tr.exportTo('tr.e.chrome', function() {
+ const BlameContextSnapshot = tr.e.chrome.BlameContextSnapshot;
+ const BlameContextInstance = tr.e.chrome.BlameContextInstance;
+
+ function FrameTreeNodeSnapshot() {
+ BlameContextSnapshot.apply(this, arguments);
+ }
+
+ FrameTreeNodeSnapshot.prototype = {
+ __proto__: BlameContextSnapshot.prototype,
+
+ get renderFrame() {
+ if (this.args.renderFrame instanceof tr.e.chrome.RenderFrameSnapshot) {
+ return this.args.renderFrame;
+ }
+ return undefined;
+ },
+
+ get url() {
+ return this.args.url;
+ },
+
+ get userFriendlyName() {
+ return 'FrameTreeNode';
+ }
+ };
+
+ tr.model.ObjectSnapshot.subTypes.register(
+ FrameTreeNodeSnapshot,
+ {typeName: 'FrameTreeNode'});
+
+ function FrameTreeNodeInstance() {
+ BlameContextInstance.apply(this, arguments);
+ }
+
+ FrameTreeNodeInstance.prototype = {
+ __proto__: BlameContextInstance.prototype,
+
+ get blameContextType() {
+ return 'Frame';
+ }
+ };
+
+ tr.model.ObjectInstance.subTypes.register(
+ FrameTreeNodeInstance,
+ {typeName: 'FrameTreeNode'});
+
+ return {
+ FrameTreeNodeSnapshot,
+ FrameTreeNodeInstance,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/render_frame.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/render_frame.html
new file mode 100644
index 00000000000..1543403dae8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/render_frame.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/blame_context/blame_context.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Trace Viewer side's correspondence of Chrome's
+ * content::FrameBlameContext class.
+ *
+ */
+tr.exportTo('tr.e.chrome', function() {
+ const BlameContextSnapshot = tr.e.chrome.BlameContextSnapshot;
+ const BlameContextInstance = tr.e.chrome.BlameContextInstance;
+
+ function RenderFrameSnapshot() {
+ BlameContextSnapshot.apply(this, arguments);
+ }
+
+ RenderFrameSnapshot.prototype = {
+ __proto__: BlameContextSnapshot.prototype,
+
+ referencedAt(item, object, field) {
+ if (item instanceof tr.e.chrome.FrameTreeNodeSnapshot &&
+ object === item.args &&
+ field === 'renderFrame') {
+ this.args.frameTreeNode = item;
+ }
+ },
+
+ get frameTreeNode() {
+ if (this.args.frameTreeNode instanceof
+ tr.e.chrome.FrameTreeNodeSnapshot) {
+ return this.args.frameTreeNode;
+ }
+ return undefined;
+ },
+
+ get url() {
+ if (this.frameTreeNode) {
+ return this.frameTreeNode.url;
+ }
+ return undefined;
+ },
+
+ get userFriendlyName() {
+ return 'RenderFrame';
+ }
+ };
+
+ tr.model.ObjectSnapshot.subTypes.register(
+ RenderFrameSnapshot,
+ {typeName: 'RenderFrame'});
+
+ function RenderFrameInstance() {
+ BlameContextInstance.apply(this, arguments);
+ }
+
+ RenderFrameInstance.prototype = {
+ __proto__: BlameContextInstance.prototype,
+
+ get blameContextType() {
+ return 'Frame';
+ }
+ };
+
+ tr.model.ObjectInstance.subTypes.register(
+ RenderFrameInstance,
+ {typeName: 'RenderFrame'});
+
+ return {
+ RenderFrameSnapshot,
+ RenderFrameInstance,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/top_level.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/top_level.html
new file mode 100644
index 00000000000..b69bdb83b0d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blame_context/top_level.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/blame_context/blame_context.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Trace Viewer side's correspondence of Chrome's
+ * content::TopLevelBlameContext class.
+ *
+ */
+tr.exportTo('tr.e.chrome', function() {
+ const BlameContextSnapshot = tr.e.chrome.BlameContextSnapshot;
+ const BlameContextInstance = tr.e.chrome.BlameContextInstance;
+
+ function TopLevelSnapshot() {
+ BlameContextSnapshot.apply(this, arguments);
+ }
+
+ TopLevelSnapshot.prototype = {
+ __proto__: BlameContextSnapshot.prototype,
+
+ get userFriendlyName() {
+ return 'TopLevel';
+ }
+ };
+
+ tr.model.ObjectSnapshot.subTypes.register(
+ TopLevelSnapshot,
+ {typeName: 'TopLevel'});
+
+ function TopLevelInstance() {
+ BlameContextInstance.apply(this, arguments);
+ }
+
+ TopLevelInstance.prototype = {
+ __proto__: BlameContextInstance.prototype,
+
+ get blameContextType() {
+ return 'TopLevel';
+ }
+ };
+
+ tr.model.ObjectInstance.subTypes.register(
+ TopLevelInstance,
+ {typeName: 'TopLevel'});
+
+ return {
+ TopLevelSnapshot,
+ TopLevelInstance,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/blink/blink_scheduler_async_slice.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blink/blink_scheduler_async_slice.html
new file mode 100644
index 00000000000..1916a699f7a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blink/blink_scheduler_async_slice.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/model/async_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.blink', function() {
+ class BlinkSchedulerAsyncSlice extends tr.model.AsyncSlice {
+ get viewSubGroupGroupingKey() {
+ if (this.title.startsWith('FrameScheduler.')) {
+ return 'Frame' + this.id;
+ }
+ if (this.title.startsWith('Scheduler.')) {
+ return 'Renderer Scheduler';
+ }
+ return undefined;
+ }
+
+ get viewSubGroupTitle() {
+ // NOTE: Be careful with hardcoded (for performance) string length.
+ if (this.title.startsWith('FrameScheduler.')) {
+ return this.title.substring(15);
+ }
+ if (this.title.startsWith('Scheduler.')) {
+ return this.title.substring(10);
+ }
+ return this.title;
+ }
+ }
+
+ tr.model.AsyncSlice.subTypes.register(BlinkSchedulerAsyncSlice, {
+ categoryParts: [
+ 'renderer.scheduler',
+ 'disabled-by-default-renderer.scheduler',
+ 'disabled-by-default-renderer.scheduler.debug',
+ ]
+ });
+
+ return {
+ BlinkSchedulerAsyncSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/blink/blink_scheduler_async_slice_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blink/blink_scheduler_async_slice_test.html
new file mode 100644
index 00000000000..be078c3d1ed
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/blink/blink_scheduler_async_slice_test.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/blink/blink_scheduler_async_slice.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+ const BlinkSchedulerAsyncSlice = tr.e.blink.BlinkSchedulerAsyncSlice;
+
+ test('construct', function() {
+ assert.strictEqual(
+ AsyncSlice.subTypes.getConstructor(
+ 'renderer.scheduler', 'Scheduler.Foo'),
+ BlinkSchedulerAsyncSlice);
+ assert.strictEqual(
+ AsyncSlice.subTypes.getConstructor(
+ 'disabled-by-default-renderer.scheduler', 'Scheduler.Bar'),
+ BlinkSchedulerAsyncSlice);
+ assert.strictEqual(
+ AsyncSlice.subTypes.getConstructor(
+ 'disabled-by-default-renderer.scheduler.debug', 'Scheduler.Baz'),
+ BlinkSchedulerAsyncSlice);
+ });
+
+ test('subgroups', function() {
+ const rendererSlice = new BlinkSchedulerAsyncSlice(
+ 'renderer.scheduler', 'Scheduler.Foo', 7, 0, {}, 3);
+ assert.strictEqual(rendererSlice.viewSubGroupGroupingKey,
+ 'Renderer Scheduler');
+ assert.strictEqual(rendererSlice.viewSubGroupTitle, 'Foo');
+
+
+ const frameSlice = new BlinkSchedulerAsyncSlice(
+ 'renderer.scheduler', 'FrameScheduler.Bar', 7, 0, {}, 3);
+ frameSlice.id = ':ptr:0x1';
+ assert.strictEqual(frameSlice.viewSubGroupGroupingKey, 'Frame:ptr:0x1');
+ assert.strictEqual(frameSlice.viewSubGroupTitle, 'Bar');
+
+ const otherSlice = new BlinkSchedulerAsyncSlice(
+ 'renderer.scheduler', 'Something.Baz', 7, 0, {}, 3);
+ assert.isUndefined(otherSlice.viewSubGroupGroupingKey);
+ assert.strictEqual(otherSlice.viewSubGroupTitle, 'Something.Baz');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/cc.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/cc.html
new file mode 100644
index 00000000000..64b825f6a9f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/cc.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/display_item_list.html">
+<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import" href="/tracing/extras/chrome/cc/layer_tree_host_impl.html">
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/extras/chrome/cc/tile.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/constants.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/constants.html
new file mode 100644
index 00000000000..1f4aa35b7a2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/constants.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const constants = {};
+ constants.ACTIVE_TREE = 0;
+ constants.PENDING_TREE = 1;
+
+ constants.HIGH_PRIORITY_BIN = 0;
+ constants.LOW_PRIORITY_BIN = 1;
+
+ constants.SEND_BEGIN_FRAME_EVENT =
+ 'ThreadProxy::ScheduledActionSendBeginMainFrame';
+ constants.BEGIN_MAIN_FRAME_EVENT = 'ThreadProxy::BeginMainFrame';
+
+ return {
+ constants
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/debug_colors.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/debug_colors.html
new file mode 100644
index 00000000000..07486dcd03c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/debug_colors.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Mapping of different tile configuration
+ * to border colors and widths.
+ */
+tr.exportTo('tr.e.cc', function() {
+ const tileTypes = {
+ highRes: 'highRes',
+ lowRes: 'lowRes',
+ extraHighRes: 'extraHighRes',
+ extraLowRes: 'extraLowRes',
+ missing: 'missing',
+ culled: 'culled',
+ solidColor: 'solidColor',
+ picture: 'picture',
+ directPicture: 'directPicture',
+ unknown: 'unknown'
+ };
+
+ const tileBorder = {
+ highRes: {
+ color: 'rgba(80, 200, 200, 0.7)',
+ width: 1
+ },
+ lowRes: {
+ color: 'rgba(212, 83, 192, 0.7)',
+ width: 2
+ },
+ extraHighRes: {
+ color: 'rgba(239, 231, 20, 0.7)',
+ width: 2
+ },
+ extraLowRes: {
+ color: 'rgba(93, 186, 18, 0.7)',
+ width: 2
+ },
+ missing: {
+ color: 'rgba(255, 0, 0, 0.7)',
+ width: 1
+ },
+ culled: {
+ color: 'rgba(160, 100, 0, 0.8)',
+ width: 1
+ },
+ solidColor: {
+ color: 'rgba(128, 128, 128, 0.7)',
+ width: 1
+ },
+ picture: {
+ color: 'rgba(64, 64, 64, 0.7)',
+ width: 1
+ },
+ directPicture: {
+ color: 'rgba(127, 255, 0, 1.0)',
+ width: 1
+ },
+ unknown: {
+ color: 'rgba(0, 0, 0, 1.0)',
+ width: 2
+ }
+ };
+
+ return {
+ tileTypes,
+ tileBorder
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/display_item_list.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/display_item_list.html
new file mode 100644
index 00000000000..bb23acf149f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/display_item_list.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ function DisplayItemList(skp64, layerRect) {
+ tr.e.cc.Picture.apply(this, arguments);
+ }
+
+ DisplayItemList.prototype = {
+ __proto__: tr.e.cc.Picture.prototype
+ };
+
+ /**
+ * @constructor
+ */
+ function DisplayItemListSnapshot() {
+ tr.e.cc.PictureSnapshot.apply(this, arguments);
+ }
+
+ DisplayItemListSnapshot.prototype = {
+ __proto__: tr.e.cc.PictureSnapshot.prototype,
+
+ initialize() {
+ tr.e.cc.PictureSnapshot.prototype.initialize.call(this);
+ this.displayItems_ = this.args.params.items;
+ },
+
+ get items() {
+ return this.displayItems_;
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(
+ DisplayItemListSnapshot,
+ {typeNames: ['cc::DisplayItemList']});
+
+ return {
+ DisplayItemListSnapshot,
+ DisplayItemList,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/display_item_list_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/display_item_list_test.html
new file mode 100644
index 00000000000..78d5d21a57d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/display_item_list_test.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/cc.html">
+<link rel="import" href="/tracing/extras/chrome/cc/display_item_list.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('cc::DisplayItemList')[0];
+ const snapshot = instance.snapshots[0];
+
+ assert.instanceOf(snapshot, tr.e.cc.DisplayItemListSnapshot);
+ instance.wasDeleted(150);
+ });
+
+ test('getItems', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('cc::DisplayItemList')[0];
+ const snapshot = instance.snapshots[0];
+
+ const items = snapshot.items;
+ assert.strictEqual(items.length, 2);
+
+ assert.strictEqual(items[0], 'BeginClipDisplayItem');
+ assert.strictEqual(items[1], 'EndClipDisplayItem');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice.html
new file mode 100644
index 00000000000..e3bd9bf2010
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice.html
@@ -0,0 +1,645 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/async_slice.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+ const EventSet = tr.model.EventSet;
+
+ const UI_COMP_NAME = 'INPUT_EVENT_LATENCY_UI_COMPONENT';
+ const ORIGINAL_COMP_NAME = 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT';
+ const BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT';
+ const END_COMP_NAME = 'INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT';
+ const LEGACY_END_COMP_NAME =
+ 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT';
+
+ const MAIN_RENDERER_THREAD_NAME = 'CrRendererMain';
+ const COMPOSITOR_THREAD_NAME = 'Compositor';
+
+ const POSTTASK_FLOW_EVENT = 'disabled-by-default-toplevel.flow';
+ const IPC_FLOW_EVENT = 'disabled-by-default-ipc.flow';
+
+ const INPUT_EVENT_TYPE_NAMES = {
+ CHAR: 'Char',
+ CLICK: 'GestureClick',
+ CONTEXT_MENU: 'ContextMenu',
+ FLING_CANCEL: 'GestureFlingCancel',
+ FLING_START: 'GestureFlingStart',
+ KEY_DOWN: 'KeyDown',
+ KEY_DOWN_RAW: 'RawKeyDown',
+ KEY_UP: 'KeyUp',
+ LATENCY_SCROLL_UPDATE: 'ScrollUpdate',
+ MOUSE_DOWN: 'MouseDown',
+ MOUSE_ENTER: 'MouseEnter',
+ MOUSE_LEAVE: 'MouseLeave',
+ MOUSE_MOVE: 'MouseMove',
+ MOUSE_UP: 'MouseUp',
+ MOUSE_WHEEL: 'MouseWheel',
+ PINCH_BEGIN: 'GesturePinchBegin',
+ PINCH_END: 'GesturePinchEnd',
+ PINCH_UPDATE: 'GesturePinchUpdate',
+ SCROLL_BEGIN: 'GestureScrollBegin',
+ SCROLL_END: 'GestureScrollEnd',
+ SCROLL_UPDATE: 'GestureScrollUpdate',
+ SCROLL_UPDATE_RENDERER: 'ScrollUpdate',
+ SHOW_PRESS: 'GestureShowPress',
+ TAP: 'GestureTap',
+ TAP_CANCEL: 'GestureTapCancel',
+ TAP_DOWN: 'GestureTapDown',
+ TOUCH_CANCEL: 'TouchCancel',
+ TOUCH_END: 'TouchEnd',
+ TOUCH_MOVE: 'TouchMove',
+ TOUCH_START: 'TouchStart',
+ UNKNOWN: 'UNKNOWN'
+ };
+
+ function InputLatencyAsyncSlice() {
+ AsyncSlice.apply(this, arguments);
+ this.associatedEvents_ = new EventSet();
+ this.typeName_ = undefined;
+ if (!this.isLegacyEvent) {
+ this.determineModernTypeName_();
+ }
+ }
+
+ InputLatencyAsyncSlice.prototype = {
+ __proto__: AsyncSlice.prototype,
+
+ // Legacy InputLatencyAsyncSlices involve a top-level slice titled
+ // "InputLatency" containing a subSlice whose title starts with
+ // "InputLatency:". Modern InputLatencyAsyncSlices involve a single
+ // top-level slice whose title starts with "InputLatency::".
+ // Legacy subSlices are not available at construction time, so
+ // determineLegacyTypeName_() must be called at get time.
+ // So this returns false for the legacy subSlice events titled like
+ // "InputLatency:Foo" even though they are technically legacy events.
+ get isLegacyEvent() {
+ return this.title === 'InputLatency';
+ },
+
+ get typeName() {
+ if (!this.typeName_) {
+ this.determineLegacyTypeName_();
+ }
+ return this.typeName_;
+ },
+
+ checkTypeName_() {
+ if (!this.typeName_) {
+ throw new Error('Unable to determine typeName');
+ }
+ let found = false;
+ for (const typeName in INPUT_EVENT_TYPE_NAMES) {
+ if (this.typeName === INPUT_EVENT_TYPE_NAMES[typeName]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ this.typeName_ = INPUT_EVENT_TYPE_NAMES.UNKNOWN;
+ }
+ },
+
+ determineModernTypeName_() {
+ // This method works both on modern events titled like
+ // "InputLatency::Foo" and also on the legacy subSlices titled like
+ // "InputLatency:Foo". Modern events' titles contain 2 colons, whereas the
+ // legacy subSlices events contain 1 colon.
+
+ const lastColonIndex = this.title.lastIndexOf(':');
+ if (lastColonIndex < 0) return;
+
+ const characterAfterLastColonIndex = lastColonIndex + 1;
+ this.typeName_ = this.title.slice(characterAfterLastColonIndex);
+
+ // Check that the determined typeName is known.
+ this.checkTypeName_();
+ },
+
+ determineLegacyTypeName_() {
+ // Iterate over all descendent subSlices.
+ for (const subSlice of this.enumerateAllDescendents()) {
+ // If |subSlice| is not an InputLatencyAsyncSlice, then ignore it.
+ const subSliceIsAInputLatencyAsyncSlice = (
+ subSlice instanceof InputLatencyAsyncSlice);
+ if (!subSliceIsAInputLatencyAsyncSlice) continue;
+
+ // If |subSlice| does not have a typeName, then ignore it.
+ if (!subSlice.typeName) continue;
+
+ // If |this| already has a typeName and |subSlice| has a different
+ // typeName, then explode!
+ if (this.typeName_ && subSlice.typeName_) {
+ const subSliceHasDifferentTypeName = (
+ this.typeName_ !== subSlice.typeName_);
+ if (subSliceHasDifferentTypeName) {
+ throw new Error(
+ 'InputLatencyAsyncSlice.determineLegacyTypeName_() ' +
+ ' found multiple typeNames');
+ }
+ }
+
+ // The typeName of |this| top-level event is whatever the typeName of
+ // |subSlice| is. Set |this.typeName_| to the subSlice's typeName.
+ this.typeName_ = subSlice.typeName_;
+ }
+
+ // If typeName could not be determined, then explode!
+ if (!this.typeName_) {
+ throw new Error(
+ 'InputLatencyAsyncSlice.determineLegacyTypeName_() failed');
+ }
+
+ // Check that the determined typeName is known.
+ this.checkTypeName_();
+ },
+
+ getRendererHelper(sourceSlices) {
+ const traceModel = this.startThread.parent.model;
+ const modelHelper = traceModel.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!modelHelper) return undefined;
+
+ let mainThread = undefined;
+ let compositorThread = undefined;
+
+ for (const i in sourceSlices) {
+ if (sourceSlices[i].parentContainer.name ===
+ MAIN_RENDERER_THREAD_NAME) {
+ mainThread = sourceSlices[i].parentContainer;
+ } else if (sourceSlices[i].parentContainer.name ===
+ COMPOSITOR_THREAD_NAME) {
+ compositorThread = sourceSlices[i].parentContainer;
+ }
+
+ if (mainThread && compositorThread) break;
+ }
+
+ const rendererHelpers = modelHelper.rendererHelpers;
+
+ const pids = Object.keys(rendererHelpers);
+ for (let i = 0; i < pids.length; i++) {
+ const pid = pids[i];
+ const rendererHelper = rendererHelpers[pid];
+ if (rendererHelper.mainThread === mainThread ||
+ rendererHelper.compositorThread === compositorThread) {
+ return rendererHelper;
+ }
+ }
+
+ return undefined;
+ },
+
+ addEntireSliceHierarchy(slice) {
+ this.associatedEvents_.push(slice);
+ slice.iterateAllSubsequentSlices(function(subsequentSlice) {
+ this.associatedEvents_.push(subsequentSlice);
+ }, this);
+ },
+
+ addDirectlyAssociatedEvents(flowEvents) {
+ const slices = [];
+
+ flowEvents.forEach(function(flowEvent) {
+ this.associatedEvents_.push(flowEvent);
+ const newSource = flowEvent.startSlice.mostTopLevelSlice;
+ if (slices.indexOf(newSource) === -1) {
+ slices.push(newSource);
+ }
+ }, this);
+
+ const lastFlowEvent = flowEvents[flowEvents.length - 1];
+ const lastSource = lastFlowEvent.endSlice.mostTopLevelSlice;
+ if (slices.indexOf(lastSource) === -1) {
+ slices.push(lastSource);
+ }
+
+ return slices;
+ },
+
+ // Find the Latency::ScrollUpdate slice that corresponds to the
+ // InputLatency::GestureScrollUpdate slice.
+ // The C++ CL that makes this connection is at:
+ // https://codereview.chromium.org/1178963003
+ addScrollUpdateEvents(rendererHelper) {
+ if (!rendererHelper || !rendererHelper.compositorThread) {
+ return;
+ }
+
+ const compositorThread = rendererHelper.compositorThread;
+ const gestureScrollUpdateStart = this.start;
+ const gestureScrollUpdateEnd = this.end;
+
+ const allCompositorAsyncSlices =
+ compositorThread.asyncSliceGroup.slices;
+
+ for (const i in allCompositorAsyncSlices) {
+ const slice = allCompositorAsyncSlices[i];
+
+ if (slice.title !== 'Latency::ScrollUpdate') continue;
+
+ const parentId = slice.args.data.
+ INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT.
+ sequence_number;
+
+ if (parentId === undefined) {
+ // Old trace, we can only rely on the timestamp to find the slice
+ if (slice.start < gestureScrollUpdateStart ||
+ slice.start >= gestureScrollUpdateEnd) {
+ continue;
+ }
+ } else {
+ // New trace, we can definitively find the latency slice by comparing
+ // its sequence number with gesture id
+ if (parseInt(parentId) !== parseInt(this.id)) {
+ continue;
+ }
+ }
+
+ slice.associatedEvents.forEach(function(event) {
+ this.associatedEvents_.push(event);
+ }, this);
+ break;
+ }
+ },
+
+ // Return true if the slice hierarchy is tracked by LatencyInfo of other
+ // input latency events. If the slice hierarchy is tracked by both, this
+ // function still returns true.
+ belongToOtherInputs(slice, flowEvents) {
+ let fromOtherInputs = false;
+
+ slice.iterateEntireHierarchy(function(subsequentSlice) {
+ if (fromOtherInputs) return;
+
+ subsequentSlice.inFlowEvents.forEach(function(inflow) {
+ if (fromOtherInputs) return;
+
+ if (inflow.category.indexOf('input') > -1) {
+ if (flowEvents.indexOf(inflow) === -1) {
+ fromOtherInputs = true;
+ }
+ }
+ }, this);
+ }, this);
+
+ return fromOtherInputs;
+ },
+
+ // Return true if |event| triggers slices of other inputs.
+ triggerOtherInputs(event, flowEvents) {
+ if (event.outFlowEvents === undefined ||
+ event.outFlowEvents.length === 0) {
+ return false;
+ }
+
+ // Once we fix the bug of flow event binding, there should exist one and
+ // only one outgoing flow (PostTask) from ScheduleBeginImplFrameDeadline
+ // and PostComposite.
+ const flow = event.outFlowEvents[0];
+
+ if (flow.category !== POSTTASK_FLOW_EVENT ||
+ !flow.endSlice) {
+ return false;
+ }
+
+ const endSlice = flow.endSlice;
+ if (this.belongToOtherInputs(endSlice.mostTopLevelSlice, flowEvents)) {
+ return true;
+ }
+
+ return false;
+ },
+
+ // Follow outgoing flow of subsequentSlices in the current hierarchy.
+ // We also handle cases where different inputs interfere with each other.
+ followSubsequentSlices(event, queue, visited, flowEvents) {
+ let stopFollowing = false;
+ let inputAck = false;
+
+ event.iterateAllSubsequentSlices(function(slice) {
+ if (stopFollowing) return;
+
+ // Do not follow TaskQueueManager::RunTask because it causes
+ // many false events to be included.
+ if (slice.title === 'TaskQueueManager::RunTask') return;
+
+ // Do not follow ScheduledActionSendBeginMainFrame because the real
+ // main thread BeginMainFrame is already traced by LatencyInfo flow.
+ if (slice.title === 'ThreadProxy::ScheduledActionSendBeginMainFrame') {
+ return;
+ }
+
+ // Do not follow ScheduleBeginImplFrameDeadline that triggers an
+ // OnBeginImplFrameDeadline that is tracked by another LatencyInfo.
+ if (slice.title === 'Scheduler::ScheduleBeginImplFrameDeadline') {
+ if (this.triggerOtherInputs(slice, flowEvents)) return;
+ }
+
+ // Do not follow PostComposite that triggers CompositeImmediately
+ // that is tracked by another LatencyInfo.
+ if (slice.title === 'CompositorImpl::PostComposite') {
+ if (this.triggerOtherInputs(slice, flowEvents)) return;
+ }
+
+ // Stop following the rest of the current slice hierarchy if
+ // FilterAndSendWebInputEvent occurs after ProcessInputEventAck.
+ if (slice.title === 'InputRouterImpl::ProcessInputEventAck') {
+ inputAck = true;
+ }
+ if (inputAck &&
+ slice.title === 'InputRouterImpl::FilterAndSendWebInputEvent') {
+ stopFollowing = true;
+ }
+
+ this.followCurrentSlice(slice, queue, visited);
+ }, this);
+ },
+
+ // Follow outgoing flow events of the current slice.
+ followCurrentSlice(event, queue, visited) {
+ event.outFlowEvents.forEach(function(outflow) {
+ if ((outflow.category === POSTTASK_FLOW_EVENT ||
+ outflow.category === IPC_FLOW_EVENT) &&
+ outflow.endSlice) {
+ this.associatedEvents_.push(outflow);
+
+ const nextEvent = outflow.endSlice.mostTopLevelSlice;
+ if (!visited.contains(nextEvent)) {
+ visited.push(nextEvent);
+ queue.push(nextEvent);
+ }
+ }
+ }, this);
+ },
+
+ backtraceFromDraw(beginImplFrame, visited) {
+ const pendingEventQueue = [];
+ pendingEventQueue.push(beginImplFrame.mostTopLevelSlice);
+
+ while (pendingEventQueue.length !== 0) {
+ const event = pendingEventQueue.pop();
+
+ this.addEntireSliceHierarchy(event);
+
+ // TODO(yuhao): For now, we backtrace all the way to the source input.
+ // But is this really needed? I will have an entry in the design
+ // doc to discuss this.
+ event.inFlowEvents.forEach(function(inflow) {
+ if (inflow.category === POSTTASK_FLOW_EVENT && inflow.startSlice) {
+ const nextEvent = inflow.startSlice.mostTopLevelSlice;
+ if (!visited.contains(nextEvent)) {
+ visited.push(nextEvent);
+ pendingEventQueue.push(nextEvent);
+ }
+ }
+ }, this);
+ }
+ },
+
+ sortRasterizerSlices(rasterWorkerThreads,
+ sortedRasterizerSlices) {
+ rasterWorkerThreads.forEach(function(rasterizer) {
+ Array.prototype.push.apply(sortedRasterizerSlices,
+ rasterizer.sliceGroup.slices);
+ }, this);
+
+ sortedRasterizerSlices.sort(function(a, b) {
+ if (a.start !== b.start) {
+ return a.start - b.start;
+ }
+ return a.guid - b.guid;
+ });
+ },
+
+ // Find rasterization slices that have the source_prepare_tiles_id
+ // same as the prepare_tiles_id of TileManager::PrepareTiles
+ // The C++ CL that makes this connection is at:
+ // https://codereview.chromium.org/1208683002/
+ addRasterizationEvents(prepareTiles, rendererHelper,
+ visited, flowEvents, sortedRasterizerSlices) {
+ if (!prepareTiles.args.prepare_tiles_id) return;
+
+ if (!rendererHelper || !rendererHelper.rasterWorkerThreads) {
+ return;
+ }
+
+ const rasterWorkerThreads = rendererHelper.rasterWorkerThreads;
+ const prepareTileId = prepareTiles.args.prepare_tiles_id;
+ const pendingEventQueue = [];
+
+ // Collect all the rasterizer tasks. Return the cached copy if possible.
+ if (sortedRasterizerSlices.length === 0) {
+ this.sortRasterizerSlices(rasterWorkerThreads, sortedRasterizerSlices);
+ }
+
+ // TODO(yuhao): Once TaskSetFinishedTaskImpl also get the prepareTileId
+ // we can simply track by checking id rather than counting.
+ let numFinishedTasks = 0;
+ const RASTER_TASK_TITLE = 'RasterizerTaskImpl::RunOnWorkerThread';
+ const IMAGEDECODE_TASK_TITLE = 'ImageDecodeTaskImpl::RunOnWorkerThread';
+ const FINISHED_TASK_TITLE = 'TaskSetFinishedTaskImpl::RunOnWorkerThread';
+
+ for (let i = 0; i < sortedRasterizerSlices.length; i++) {
+ const task = sortedRasterizerSlices[i];
+
+ if (task.title === RASTER_TASK_TITLE ||
+ task.title === IMAGEDECODE_TASK_TITLE) {
+ if (task.args.source_prepare_tiles_id === prepareTileId) {
+ this.addEntireSliceHierarchy(task.mostTopLevelSlice);
+ }
+ } else if (task.title === FINISHED_TASK_TITLE) {
+ if (task.start > prepareTiles.start) {
+ pendingEventQueue.push(task.mostTopLevelSlice);
+ if (++numFinishedTasks === 3) break;
+ }
+ }
+ }
+
+ // Trace PostTask from rasterizer tasks.
+ while (pendingEventQueue.length !== 0) {
+ const event = pendingEventQueue.pop();
+
+ this.addEntireSliceHierarchy(event);
+ this.followSubsequentSlices(event, pendingEventQueue, visited,
+ flowEvents);
+ }
+ },
+
+ addOtherCausallyRelatedEvents(rendererHelper, sourceSlices,
+ flowEvents, sortedRasterizerSlices) {
+ const pendingEventQueue = [];
+ // Keep track of visited nodes when traversing a DAG
+ const visitedEvents = new EventSet();
+ let beginImplFrame = undefined;
+ let prepareTiles = undefined;
+ sortedRasterizerSlices = [];
+
+ sourceSlices.forEach(function(sourceSlice) {
+ if (!visitedEvents.contains(sourceSlice)) {
+ visitedEvents.push(sourceSlice);
+ pendingEventQueue.push(sourceSlice);
+ }
+ }, this);
+
+ while (pendingEventQueue.length !== 0) {
+ const event = pendingEventQueue.pop();
+
+ // Push the current event chunk into associatedEvents.
+ this.addEntireSliceHierarchy(event);
+
+ this.followCurrentSlice(event, pendingEventQueue, visitedEvents);
+
+ this.followSubsequentSlices(event, pendingEventQueue, visitedEvents,
+ flowEvents);
+
+ // The rasterization work (CompositorTileWorker thread) and the
+ // Compositor tile manager are connect by the prepare_tiles_id
+ // instead of flow events.
+ const COMPOSITOR_PREPARE_TILES = 'TileManager::PrepareTiles';
+ prepareTiles = event.findDescendentSlice(COMPOSITOR_PREPARE_TILES);
+ if (prepareTiles) {
+ this.addRasterizationEvents(prepareTiles, rendererHelper,
+ visitedEvents, flowEvents, sortedRasterizerSlices);
+ }
+
+ // OnBeginImplFrameDeadline could be triggered by other inputs.
+ // For now, we backtrace from it.
+ // TODO(yuhao): There are more such slices that we need to backtrace
+ const COMPOSITOR_ON_BIFD = 'Scheduler::OnBeginImplFrameDeadline';
+ beginImplFrame = event.findDescendentSlice(COMPOSITOR_ON_BIFD);
+ if (beginImplFrame) {
+ this.backtraceFromDraw(beginImplFrame, visitedEvents);
+ }
+ }
+
+ // A separate pass on GestureScrollUpdate.
+ // Scroll update doesn't go through the main thread, but the compositor
+ // may go back to the main thread if there is an onscroll event handler.
+ // This is captured by a different flow event, which does not have the
+ // same ID as the Input Latency Event, but it is technically causally
+ // related to the GestureScrollUpdate input. Add them manually for now.
+ const INPUT_GSU = 'InputLatency::GestureScrollUpdate';
+ if (this.title === INPUT_GSU) {
+ this.addScrollUpdateEvents(rendererHelper);
+ }
+ },
+
+ get associatedEvents() {
+ if (this.associatedEvents_.length !== 0) {
+ return this.associatedEvents_;
+ }
+
+ const modelIndices = this.startThread.parent.model.modelIndices;
+ const flowEvents = modelIndices.getFlowEventsWithId(this.id);
+
+ if (flowEvents.length === 0) {
+ return this.associatedEvents_;
+ }
+
+ // Step 1: Get events that are directly connected by the LatencyInfo
+ // flow events. This gives us a small set of events that are guaranteed
+ // to be associated with the input, but are almost certain incomplete.
+ // We call this set "source" event set.
+ // This step returns the "source" event set (sourceSlices), which is then
+ // used in the second step.
+ const sourceSlices = this.addDirectlyAssociatedEvents(flowEvents);
+
+ // Step 2: Start from the previously constructed "source" event set, we
+ // follow the toplevel (i.e., PostTask) and IPC flow events. Any slices
+ // that are reachable from the "source" event set via PostTasks or IPCs
+ // are conservatively considered associated with the input event.
+ // We then deal with specific cases where flow events either over include
+ // or miss capturing slices.
+ const rendererHelper = this.getRendererHelper(sourceSlices);
+ this.addOtherCausallyRelatedEvents(rendererHelper, sourceSlices,
+ flowEvents);
+
+ return this.associatedEvents_;
+ },
+
+ get inputLatency() {
+ if (!('data' in this.args)) return undefined;
+
+ const data = this.args.data;
+ const endTimeComp = data[END_COMP_NAME] || data[LEGACY_END_COMP_NAME];
+ if (endTimeComp === undefined) return undefined;
+
+ let latency = 0;
+ const endTime = endTimeComp.time;
+ if (ORIGINAL_COMP_NAME in data) {
+ latency = endTime - data[ORIGINAL_COMP_NAME].time;
+ } else if (UI_COMP_NAME in data) {
+ latency = endTime - data[UI_COMP_NAME].time;
+ } else if (BEGIN_COMP_NAME in data) {
+ latency = endTime - data[BEGIN_COMP_NAME].time;
+ } else {
+ throw new Error('No valid begin latency component');
+ }
+ return latency;
+ }
+ };
+
+ const eventTypeNames = [
+ 'Char',
+ 'ContextMenu',
+ 'GestureClick',
+ 'GestureFlingCancel',
+ 'GestureFlingStart',
+ 'GestureScrollBegin',
+ 'GestureScrollEnd',
+ 'GestureScrollUpdate',
+ 'GestureShowPress',
+ 'GestureTap',
+ 'GestureTapCancel',
+ 'GestureTapDown',
+ 'GesturePinchBegin',
+ 'GesturePinchEnd',
+ 'GesturePinchUpdate',
+ 'KeyDown',
+ 'KeyUp',
+ 'MouseDown',
+ 'MouseEnter',
+ 'MouseLeave',
+ 'MouseMove',
+ 'MouseUp',
+ 'MouseWheel',
+ 'RawKeyDown',
+ 'ScrollUpdate',
+ 'TouchCancel',
+ 'TouchEnd',
+ 'TouchMove',
+ 'TouchStart'
+ ];
+ const allTypeNames = ['InputLatency'];
+ eventTypeNames.forEach(function(eventTypeName) {
+ // Old style.
+ allTypeNames.push('InputLatency:' + eventTypeName);
+
+ // New style.
+ allTypeNames.push('InputLatency::' + eventTypeName);
+ });
+
+ AsyncSlice.subTypes.register(
+ InputLatencyAsyncSlice,
+ {
+ typeNames: allTypeNames,
+ categoryParts: ['latencyInfo']
+ });
+
+ return {
+ InputLatencyAsyncSlice,
+ INPUT_EVENT_TYPE_NAMES,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice_test.html
new file mode 100644
index 00000000000..e65613ea647
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/input_latency_async_slice_test.html
@@ -0,0 +1,702 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/model_indices.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newFlowEventEx = tr.c.TestUtils.newFlowEventEx;
+ const newModel = tr.c.TestUtils.newModel;
+ const EventSet = tr.model.EventSet;
+
+ test('matchByType_oldStyle', function() {
+ const sOuter = newAsyncSliceEx({
+ title: 'InputLatency',
+ cat: 'benchmark',
+ start: 0,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ args: {
+ data: {
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT: {'time': 0},
+ INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT: {time: 10}
+ }
+ }
+ });
+ assert.throws(function() {
+ sOuter.typeName;
+ });
+
+ const sInner = newAsyncSliceEx({
+ title: 'InputLatency:GestureScrollUpdate',
+ cat: 'benchmark',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ args: {
+ 'step': 'GestureScrollUpdate'
+ }
+ });
+ sOuter.subSlices.push(sInner);
+ assert.isTrue(sOuter instanceof tr.e.cc.InputLatencyAsyncSlice);
+ assert.isTrue(sInner instanceof tr.e.cc.InputLatencyAsyncSlice);
+ assert.strictEqual(sOuter.inputLatency, 10);
+ assert.strictEqual(
+ tr.e.cc.INPUT_EVENT_TYPE_NAMES.SCROLL_UPDATE, sInner.typeName);
+ assert.strictEqual(
+ tr.e.cc.INPUT_EVENT_TYPE_NAMES.SCROLL_UPDATE, sOuter.typeName);
+ });
+
+ test('matchByType_newStyle', function() {
+ const sInfo = newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ cat: 'benchmark',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ args: {
+ data: {
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT: {'time': 0},
+ INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT: {time: 10}
+ }
+ }
+ });
+
+ assert.isTrue(sInfo instanceof tr.e.cc.InputLatencyAsyncSlice);
+ assert.strictEqual(sInfo.inputLatency, 10);
+ assert.strictEqual(
+ tr.e.cc.INPUT_EVENT_TYPE_NAMES.SCROLL_UPDATE, sInfo.typeName);
+ });
+
+ test('unknownType', function() {
+ const sInfo = newAsyncSliceEx({
+ title: 'InputLatency::BadTypeName',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ args: {
+ data: {
+ INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT: {'time': 0},
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT: {'time': 0},
+ INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT: {time: 10}
+ }
+ }
+ });
+ assert.strictEqual(tr.e.cc.INPUT_EVENT_TYPE_NAMES.UNKNOWN, sInfo.typeName);
+ });
+
+ test('getAssociatedEventsBypassRendererMain', function() {
+ const m = newModel(function(m) {
+ const pb = m.getOrCreateProcess(1);
+ const pr = m.getOrCreateProcess(2);
+ const mainBrowserThread = pb.getOrCreateThread(10);
+ const mainRendererThread = pr.getOrCreateThread(20);
+ const compositorThread = pr.getOrCreateThread(21);
+
+ mainBrowserThread.name = 'CrBrowserMain';
+ mainRendererThread.name = 'CrRendererMain';
+ compositorThread.name = 'Compositor';
+
+ // Expectation: None of s2 and s3 should be included
+ // CrBrowserMain: [s0] [s1]
+ // | /|\
+ // CrRendererMain: | [s2] [s3] |
+ // \|/ |
+ // Compositor: [s4]-------------|
+
+ m.s0 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's0', start: 0.0, duration: 1.0 }));
+ m.s1 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's1', start: 6.0, duration: 1.0 }));
+ m.s2 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's2', start: 2.0, duration: 1.0 }));
+ m.s3 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's3', start: 4.0, duration: 1.0 }));
+ m.s4 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's4', start: 0.5, duration: 1.0 }));
+
+ m.f1 = newFlowEventEx({
+ title: 'test1',
+ start: 0,
+ end: 10,
+ startSlice: m.s0,
+ endSlice: m.s4,
+ id: '0x100'
+ });
+
+ m.f2 = newFlowEventEx({
+ title: 'test2',
+ start: 20,
+ end: 30,
+ startSlice: m.s4,
+ endSlice: m.s1,
+ id: '0x100'
+ });
+
+ m.flowEvents.push(m.f1);
+ m.flowEvents.push(m.f2);
+
+ m.as0 = newAsyncSliceEx({
+ title: 'test1',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x101',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ });
+
+ m.as1 = newAsyncSliceEx({
+ title: 'test2',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ startThread: compositorThread
+ });
+ });
+
+ assert.isTrue(m.as0.associatedEvents.length === 0);
+ assert.isTrue(m.as1.associatedEvents.equals(
+ new EventSet([m.f1, m.s0, m.f2, m.s4, m.s1])));
+ });
+
+ test('getAssociatedEventsBypassRendererMainWithOnScroll', function() {
+ const m = newModel(function(m) {
+ const pb = m.getOrCreateProcess(1);
+ const pr = m.getOrCreateProcess(2);
+ const mainBrowserThread = pb.getOrCreateThread(10);
+ const mainRendererThread = pr.getOrCreateThread(20);
+ const compositorThread = pr.getOrCreateThread(21);
+
+ mainBrowserThread.name = 'CrBrowserMain';
+ mainRendererThread.name = 'CrRendererMain';
+ compositorThread.name = 'Compositor';
+
+ // Expectation: s2 should be included but not s3
+ // GestureScrollUpdate: [ as1 ]
+ // CrBrowserMain: [s0] [s1]
+ // | /|\
+ // CrRendererMain: | [s2] [s3] |
+ // \|/ /|\ |
+ // Compositor: [s4]___|__________|
+ // ScrollUpdate: [ as2 ]
+
+ m.s0 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's0', start: 0.0, duration: 1.0 }));
+ m.s1 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's1', start: 6.0, duration: 1.0 }));
+ m.s2 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's2', start: 2.0, duration: 1.0 }));
+ m.s3 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's3', start: 4.0, duration: 1.0 }));
+ m.s4 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's4', start: 0.5, duration: 1.0 }));
+
+ m.f1 = newFlowEventEx({
+ title: 'f1',
+ start: 0,
+ end: 10,
+ startSlice: m.s0,
+ endSlice: m.s4,
+ id: '0x100'
+ });
+
+ m.f2 = newFlowEventEx({
+ title: 'f2',
+ start: 20,
+ end: 30,
+ startSlice: m.s4,
+ endSlice: m.s1,
+ id: '0x100'
+ });
+
+ m.f3 = newFlowEventEx({
+ title: 'f3',
+ start: 20,
+ end: 30,
+ startSlice: m.s4,
+ endSlice: m.s2,
+ id: '0x800'
+ });
+
+ m.flowEvents.push(m.f1);
+ m.flowEvents.push(m.f2);
+ m.flowEvents.push(m.f3);
+
+ m.as0 = mainBrowserThread.asyncSliceGroup.push(newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ cat: 'benchmark,latencyInfo',
+ args: {
+ data: {
+ INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT: 100
+ }
+ },
+ start: 2,
+ end: 10,
+ id: '0x101',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ }));
+ assert.strictEqual(tr.e.cc.INPUT_EVENT_TYPE_NAMES.SCROLL_UPDATE,
+ m.as0.typeName);
+
+ m.as1 = mainBrowserThread.asyncSliceGroup.push(newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ cat: 'benchmark,latencyInfo',
+ args: {
+ data: {}
+ },
+ start: 0,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ }));
+ assert.strictEqual(tr.e.cc.INPUT_EVENT_TYPE_NAMES.SCROLL_UPDATE,
+ m.as1.typeName);
+
+ m.as2 = compositorThread.asyncSliceGroup.push(newAsyncSliceEx({
+ title: 'Latency::ScrollUpdate',
+ cat: 'benchmark,latencyInfo',
+ args: {
+ data: {
+ INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT: 100
+ }
+ },
+ start: 1.5,
+ end: 8,
+ id: '0x800',
+ isTopLevel: true,
+ startThread: compositorThread
+ }));
+ assert.strictEqual(tr.e.cc.INPUT_EVENT_TYPE_NAMES.LATENCY_SCROLL_UPDATE,
+ m.as2.typeName);
+ });
+
+ assert.isTrue(m.as0.associatedEvents.length === 0);
+ assert.isTrue(m.as1.associatedEvents.equals(
+ new EventSet([m.f1, m.s0, m.f2, m.s4, m.s1, m.f3, m.s2])));
+ });
+
+ test('getAssociatedEventsWithoutCommit', function() {
+ const m = newModel(function(m) {
+ const pb = m.getOrCreateProcess(1);
+ const pr = m.getOrCreateProcess(2);
+ const mainBrowserThread = pb.getOrCreateThread(10);
+ const mainRendererThread = pr.getOrCreateThread(20);
+ const compositorThread = pr.getOrCreateThread(21);
+
+ mainBrowserThread.name = 'CrBrowserMain';
+ mainRendererThread.name = 'CrRendererMain';
+ compositorThread.name = 'Compositor';
+
+ // Expectation: none of s3 and s5 should be included
+ // CrBrowserMain: [s0] [s1]
+ // | /|\
+ // | __________|
+ // | |
+ // CrRendererMain: | [s2] [s3] [s5]
+ // \|/ /|\
+ // Compositor: [s4]___|
+
+ m.s0 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's0', start: 0.0, duration: 1.0 }));
+ m.s1 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's1', start: 6.0, duration: 1.0 }));
+ m.s2 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's2', start: 2.0, duration: 1.0 }));
+ m.s3 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's3', start: 4.0, duration: 1.0 }));
+ m.s4 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's4', start: 0.5, duration: 1.0 }));
+ m.s5 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's5', start: 100.0, duration: 1.0 }));
+
+ m.f1 = newFlowEventEx({
+ title: 'f1',
+ start: 0,
+ end: 10,
+ startSlice: m.s0,
+ endSlice: m.s4,
+ id: '0x100'
+ });
+
+ m.f2 = newFlowEventEx({
+ title: 'f2',
+ start: 20,
+ end: 30,
+ startSlice: m.s4,
+ endSlice: m.s2,
+ id: '0x100'
+ });
+
+ m.f3 = newFlowEventEx({
+ title: 'f3',
+ start: 20,
+ end: 30,
+ startSlice: m.s2,
+ endSlice: m.s1,
+ id: '0x100'
+ });
+
+ m.flowEvents.push(m.f1);
+ m.flowEvents.push(m.f2);
+ m.flowEvents.push(m.f3);
+
+ m.as0 = newAsyncSliceEx({
+ title: 'test1',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x101',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ });
+
+ m.as1 = newAsyncSliceEx({
+ title: 'test2',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ });
+ });
+
+ assert.isTrue(m.as0.associatedEvents.length === 0);
+ assert.isTrue(m.as1.associatedEvents.equals(
+ new EventSet([m.f1, m.s0, m.f2, m.s4, m.f3, m.s2, m.s1])));
+ });
+
+ test('getAssociatedEventsWillCommit', function() {
+ const m = newModel(function(m) {
+ const pb = m.getOrCreateProcess(1);
+ const pr = m.getOrCreateProcess(2);
+ const mainBrowserThread = pb.getOrCreateThread(10);
+ const mainRendererThread = pr.getOrCreateThread(20);
+ const compositorThread = pr.getOrCreateThread(21);
+
+ mainBrowserThread.name = 'CrBrowserMain';
+ mainRendererThread.name = 'CrRendererMain';
+ compositorThread.name = 'Compositor';
+
+ // Expectation: s3 should be included by getOtherCasuallyRelatedEvents,
+ // because there is a PostTask s7 -> s3, but s6 shouldn't be included.
+ // CrBrowserMain: [s0] [ s1 ]
+ // | /|\
+ // | |
+ // | [ s2 ]____ |
+ // CrRendererMain: | /|\ [s7] | | [s6]
+ // | | | | |
+ // | | | | |
+ // \|/ | \|/ \|/ |
+ // Compositor: [s4]__| [s3] [s5]__|
+
+ m.s0 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's0', start: 0.0, duration: 1.0 }));
+ m.s1 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's1', start: 6.0, duration: 1.0 }));
+ m.s2 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's2', start: 2.0, duration: 1.0 }));
+ m.s3 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's3', start: 4.0, duration: 1.0 }));
+ m.s4 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's4', start: 0.5, duration: 1.0 }));
+ m.s5 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's5', start: 5.5, duration: 1.0 }));
+ m.s6 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's6', start: 1000.0, duration: 1.0 }));
+ m.s7 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's7', start: 2.5, duration: 0.2 }));
+
+ mainBrowserThread.sliceGroup.createSubSlices();
+ mainRendererThread.sliceGroup.createSubSlices();
+ compositorThread.sliceGroup.createSubSlices();
+
+ m.f1 = newFlowEventEx({
+ title: 'f1',
+ start: 0,
+ end: 10,
+ startSlice: m.s0,
+ endSlice: m.s4,
+ id: '0x100'
+ });
+
+ m.f2 = newFlowEventEx({
+ title: 'f2',
+ start: 20,
+ end: 30,
+ startSlice: m.s4,
+ endSlice: m.s2,
+ id: '0x100'
+ });
+
+ m.f3 = newFlowEventEx({
+ title: 'f3',
+ start: 20,
+ end: 30,
+ startSlice: m.s2,
+ endSlice: m.s5,
+ id: '0x100'
+ });
+
+ m.f4 = newFlowEventEx({
+ title: 'f4',
+ start: 20,
+ end: 30,
+ startSlice: m.s5,
+ endSlice: m.s1,
+ id: '0x100'
+ });
+
+ m.f5 = newFlowEventEx({
+ title: 'f5',
+ cat: 'disabled-by-default-toplevel.flow',
+ start: 20,
+ end: 30,
+ startSlice: m.s7,
+ endSlice: m.s3,
+ id: '0xAAA'
+ });
+
+ m.flowEvents.push(m.f1);
+ m.flowEvents.push(m.f2);
+ m.flowEvents.push(m.f3);
+ m.flowEvents.push(m.f4);
+ m.flowEvents.push(m.f5);
+
+ m.as0 = newAsyncSliceEx({
+ title: 'test1',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x101',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ });
+
+ m.as1 = newAsyncSliceEx({
+ title: 'test2',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ });
+ });
+
+ assert.isTrue(m.as0.associatedEvents.length === 0);
+ assert.isTrue(m.as1.associatedEvents.equals(new EventSet(
+ [m.f1, m.f2, m.f3, m.f4, m.f5,
+ m.s0, m.s1, m.s2, m.s3, m.s4, m.s5, m.s7])));
+ });
+
+ test('getAssociatedEventsExcludeOtherInputs', function() {
+ const m = newModel(function(m) {
+ const pb = m.getOrCreateProcess(1);
+ const pr = m.getOrCreateProcess(2);
+ const mainBrowserThread = pb.getOrCreateThread(10);
+ const mainRendererThread = pr.getOrCreateThread(20);
+ const compositorThread = pr.getOrCreateThread(21);
+
+ mainBrowserThread.name = 'CrBrowserMain';
+ mainRendererThread.name = 'CrRendererMain';
+ compositorThread.name = 'Compositor';
+
+ // Expectation: s3 should be included by getOtherCasuallyRelatedEvents,
+ // because there is a PostTask s7 -> s3. Even though there is also a
+ // PostTask from s9 to s6, s6 shouldn't be included because it's tracked
+ // by LatencyInfo of another input.
+ // CrBrowserMain: [s0] [ s1 ] [s8]
+ // | /|\ |
+ // | | |
+ // | [ s2 ]____ | \|/
+ // CrRendererMain: | /|\ [s7] | | [s6]
+ // | | | | | /|\
+ // | | | | | |
+ // \|/ | \|/ \|/ | |
+ // Compositor: [s4]__| [s3] [ s5 ]_| |
+ // [s9]_________|
+
+ m.s0 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's0', start: 0.0, duration: 1.0 }));
+ m.s1 = mainBrowserThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's1', start: 6.0, duration: 1.0 }));
+ m.s2 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's2', start: 2.0, duration: 1.0 }));
+ m.s3 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's3', start: 4.0, duration: 1.0 }));
+ m.s4 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's4', start: 0.5, duration: 1.0 }));
+ m.s5 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's5', start: 5.5, duration: 1.0 }));
+ m.s6 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's6', start: 10.0, duration: 1.0 }));
+ m.s7 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's7', start: 2.5, duration: 0.2 }));
+ m.s8 = mainRendererThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 's8', start: 9.5, duration: 1.0 }));
+ m.s9 = compositorThread.sliceGroup.pushSlice(newSliceEx(
+ { title: 'Scheduler::ScheduleBeginImplFrameDeadline',
+ start: 5.7, duration: 0.2 }));
+
+ mainBrowserThread.sliceGroup.createSubSlices();
+ mainRendererThread.sliceGroup.createSubSlices();
+ compositorThread.sliceGroup.createSubSlices();
+
+ m.f1 = newFlowEventEx({
+ title: 'f1',
+ cat: 'input',
+ start: 0,
+ end: 10,
+ startSlice: m.s0,
+ endSlice: m.s4,
+ id: '0x100'
+ });
+
+ m.f2 = newFlowEventEx({
+ title: 'f2',
+ cat: 'input',
+ start: 20,
+ end: 30,
+ startSlice: m.s4,
+ endSlice: m.s2,
+ id: '0x100'
+ });
+
+ m.f3 = newFlowEventEx({
+ title: 'f3',
+ cat: 'input',
+ start: 20,
+ end: 30,
+ startSlice: m.s2,
+ endSlice: m.s5,
+ id: '0x100'
+ });
+
+ m.f4 = newFlowEventEx({
+ title: 'f4',
+ cat: 'input',
+ start: 20,
+ end: 30,
+ startSlice: m.s5,
+ endSlice: m.s1,
+ id: '0x100'
+ });
+
+ m.f5 = newFlowEventEx({
+ title: 'f5',
+ cat: 'disabled-by-default-toplevel.flow',
+ start: 20,
+ end: 30,
+ startSlice: m.s7,
+ endSlice: m.s3,
+ id: '0xAAA'
+ });
+
+ m.f6 = newFlowEventEx({
+ title: 'f6',
+ cat: 'disabled-by-default-toplevel.flow',
+ start: 20,
+ end: 30,
+ startSlice: m.s9,
+ endSlice: m.s6,
+ id: '0xAAB'
+ });
+
+ m.f7 = newFlowEventEx({
+ title: 'f7',
+ cat: 'input',
+ start: 20,
+ end: 30,
+ startSlice: m.s8,
+ endSlice: m.s6,
+ id: '0x102'
+ });
+
+ m.flowEvents.push(m.f1);
+ m.flowEvents.push(m.f2);
+ m.flowEvents.push(m.f3);
+ m.flowEvents.push(m.f4);
+ m.flowEvents.push(m.f5);
+ m.flowEvents.push(m.f6);
+ m.flowEvents.push(m.f7);
+
+ m.as0 = newAsyncSliceEx({
+ title: 'test1',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x101',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ });
+
+ m.as1 = newAsyncSliceEx({
+ title: 'test2',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ });
+
+ m.as2 = newAsyncSliceEx({
+ title: 'test2',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x102',
+ isTopLevel: true,
+ startThread: mainBrowserThread
+ });
+ });
+
+ assert.isTrue(m.as0.associatedEvents.length === 0);
+ assert.isTrue(m.as1.associatedEvents.equals(new EventSet(
+ [m.f1, m.f2, m.f3, m.f4, m.f5,
+ m.s0, m.s1, m.s2, m.s3, m.s4, m.s5, m.s7, m.s9])));
+ });
+
+ test('legacyEndComponent', function() {
+ const sInfo = newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ cat: 'benchmark',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ args: {
+ data: {
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT: {'time': 0},
+ INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT: {time: 10}
+ }
+ }
+ });
+
+ assert.isTrue(sInfo instanceof tr.e.cc.InputLatencyAsyncSlice);
+ assert.strictEqual(sInfo.inputLatency, 10);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_impl.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_impl.html
new file mode 100644
index 00000000000..caf63707186
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_impl.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/extras/chrome/cc/constants.html">
+<link rel="import" href="/tracing/extras/chrome/cc/region.html">
+<link rel="import" href="/tracing/extras/chrome/cc/tile_coverage_rect.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const constants = tr.e.cc.constants;
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ /**
+ * @constructor
+ */
+ function LayerImplSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ }
+
+ LayerImplSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ preInitialize() {
+ tr.e.cc.preInitializeObject(this);
+
+ this.layerTreeImpl_ = undefined;
+ this.parentLayer = undefined;
+ },
+
+ initialize() {
+ // Defaults.
+ this.invalidation = new tr.e.cc.Region();
+ this.unrecordedRegion = new tr.e.cc.Region();
+ this.pictures = [];
+
+ // Import & validate this.args
+ tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
+ this, ['layerId', 'layerQuad']);
+ tr.e.cc.moveOptionalFieldsFromArgsToToplevel(
+ this, ['children', 'maskLayer', 'replicaLayer',
+ 'idealContentsScale', 'geometryContentsScale',
+ 'layoutRects', 'usingGpuRasterization']);
+
+ // Leave gpu memory usage in both places.
+ this.gpuMemoryUsageInBytes = this.args.gpuMemoryUsage;
+
+ // Leave bounds in both places.
+ this.bounds = tr.b.math.Rect.fromXYWH(
+ 0, 0,
+ this.args.bounds.width, this.args.bounds.height);
+
+ if (this.args.animationBounds) {
+ // AnimationBounds[2] and [5] are the Z-component of the box.
+ this.animationBoundsRect = tr.b.math.Rect.fromXYWH(
+ this.args.animationBounds[0], this.args.animationBounds[1],
+ this.args.animationBounds[3], this.args.animationBounds[4]);
+ }
+
+ // After Slimming Paint v2, compositor no longer knows hierarchy
+ // information. If the children value is undefined, the tracing
+ // data comes from the new version of cc, otherwise we set the
+ // parentLayer as we did before SPv2.
+ if (this.children) {
+ for (let i = 0; i < this.children.length; i++) {
+ this.children[i].parentLayer = this;
+ }
+ }
+ if (this.maskLayer) {
+ this.maskLayer.parentLayer = this;
+ }
+ if (this.replicaLayer) {
+ this.replicaLayer.parentLayer = this;
+ }
+ if (!this.geometryContentsScale) {
+ this.geometryContentsScale = 1.0;
+ }
+ if (!this.idealContentsScale) {
+ this.idealContentsScale = 1.0;
+ }
+
+ this.touchEventHandlerRegion = tr.e.cc.Region.fromArrayOrUndefined(
+ this.args.touchEventHandlerRegion);
+ this.wheelEventHandlerRegion = tr.e.cc.Region.fromArrayOrUndefined(
+ this.args.wheelEventHandlerRegion);
+ this.nonFastScrollableRegion = tr.e.cc.Region.fromArrayOrUndefined(
+ this.args.nonFastScrollableRegion);
+ },
+
+ get layerTreeImpl() {
+ if (this.layerTreeImpl_) {
+ return this.layerTreeImpl_;
+ }
+ if (this.parentLayer) {
+ return this.parentLayer.layerTreeImpl;
+ }
+ return undefined;
+ },
+ set layerTreeImpl(layerTreeImpl) {
+ this.layerTreeImpl_ = layerTreeImpl;
+ },
+
+ get activeLayer() {
+ if (this.layerTreeImpl.whichTree === constants.ACTIVE_TREE) {
+ return this;
+ }
+ const activeTree = this.layerTreeImpl.layerTreeHostImpl.activeTree;
+ return activeTree.findLayerWithId(this.layerId);
+ },
+
+ get pendingLayer() {
+ if (this.layerTreeImpl.whichTree === constants.PENDING_TREE) {
+ return this;
+ }
+ const pendingTree = this.layerTreeImpl.layerTreeHostImpl.pendingTree;
+ return pendingTree.findLayerWithId(this.layerId);
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function PictureLayerImplSnapshot() {
+ LayerImplSnapshot.apply(this, arguments);
+ }
+
+ PictureLayerImplSnapshot.prototype = {
+ __proto__: LayerImplSnapshot.prototype,
+
+ initialize() {
+ LayerImplSnapshot.prototype.initialize.call(this);
+
+ // Backward compatibility: the new format puts debug info fields under
+ // 'debugInfo', while the old format puts them directly under args.
+ if (this.args.debugInfo) {
+ for (const i in this.args.debugInfo) {
+ this.args[i] = this.args.debugInfo[i];
+ }
+ delete this.args.debugInfo;
+ }
+
+ if (this.args.annotatedInvalidationRects) {
+ this.invalidation = new tr.e.cc.Region();
+ for (const annotatedRect of this.args.annotatedInvalidationRects) {
+ const rect = annotatedRect.geometryRect;
+ rect.reason = annotatedRect.reason;
+ rect.client = annotatedRect.client;
+ this.invalidation.addRect(rect);
+ }
+ delete this.args.annotatedInvalidationRects;
+ } else if (this.args.invalidation) {
+ // Use unannotated invalidation rect if no annotated rects are
+ // available.
+ this.invalidation = tr.e.cc.Region.fromArray(this.args.invalidation);
+ }
+ delete this.args.invalidation;
+
+ if (this.args.unrecordedRegion) {
+ this.unrecordedRegion = tr.e.cc.Region.fromArray(
+ this.args.unrecordedRegion);
+ delete this.args.unrecordedRegion;
+ }
+
+ if (this.args.pictures) {
+ this.pictures = this.args.pictures;
+
+ // The picture list comes in with an unknown ordering. We resort based
+ // on timestamp order so we will draw the base picture first and the
+ // various fixes on top of that.
+ this.pictures.sort(function(a, b) { return a.ts - b.ts; });
+ }
+
+ this.tileCoverageRects = [];
+ if (this.args.coverageTiles) {
+ for (let i = 0; i < this.args.coverageTiles.length; ++i) {
+ const rect = this.args.coverageTiles[i].geometryRect.scale(
+ this.idealContentsScale);
+ const tile = this.args.coverageTiles[i].tile;
+ this.tileCoverageRects.push(new tr.e.cc.TileCoverageRect(rect, tile));
+ }
+ delete this.args.coverageTiles;
+ }
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(
+ PictureLayerImplSnapshot,
+ {
+ typeName: 'cc::PictureLayerImpl'
+ });
+
+ ObjectSnapshot.subTypes.register(
+ LayerImplSnapshot,
+ {
+ typeNames: [
+ 'cc::LayerImpl',
+ 'cc::DelegatedRendererLayerImpl',
+ 'cc::HeadsUpDisplayLayerImpl',
+ 'cc::IOSurfaceLayerImpl',
+ 'cc::NinePatchLayerImpl',
+ 'cc::PictureImageLayerImpl',
+ 'cc::ScrollbarLayerImpl',
+ 'cc::SolidColorLayerImpl',
+ 'cc::SolidColorScrollbarLayerImpl',
+ 'cc::SurfaceLayerImpl',
+ 'cc::TextureLayerImpl',
+ 'cc::TiledLayerImpl',
+ 'cc::VideoLayerImpl',
+ 'cc::PaintedScrollbarLayerImpl',
+ 'ClankPatchLayer',
+ 'TabBorderLayer',
+ 'CounterLayer'
+ ]
+ });
+
+ return {
+ LayerImplSnapshot,
+ PictureLayerImplSnapshot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl.html
new file mode 100644
index 00000000000..d857a3b5bbd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl.html
@@ -0,0 +1,198 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/bbox2.html">
+<link rel="import" href="/tracing/extras/chrome/cc/constants.html">
+<link rel="import" href="/tracing/extras/chrome/cc/layer_tree_impl.html">
+<link rel="import" href="/tracing/extras/chrome/cc/util.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the LayerTreeHostImpl model-level objects.
+ */
+tr.exportTo('tr.e.cc', function() {
+ const constants = tr.e.cc.constants;
+
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+ const ObjectInstance = tr.model.ObjectInstance;
+
+ /**
+ * @constructor
+ */
+ function LayerTreeHostImplSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ }
+
+ LayerTreeHostImplSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ preInitialize() {
+ tr.e.cc.preInitializeObject(this);
+ },
+
+ initialize() {
+ tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
+ this, ['deviceViewportSize',
+ 'activeTree']);
+ tr.e.cc.moveOptionalFieldsFromArgsToToplevel(
+ this, ['pendingTree']);
+
+ // Move active_tiles into this.tiles. If that doesn't exist then, then as
+ // a backward compatability move tiles into this.tiles.
+ if (this.args.activeTiles !== undefined) {
+ this.activeTiles = this.args.activeTiles;
+ delete this.args.activeTiles;
+ } else if (this.args.tiles !== undefined) {
+ this.activeTiles = this.args.tiles;
+ delete this.args.tiles;
+ }
+
+ if (!this.activeTiles) {
+ this.activeTiles = [];
+ }
+
+ this.activeTree.layerTreeHostImpl = this;
+ this.activeTree.whichTree = constants.ACTIVE_TREE;
+ if (this.pendingTree) {
+ this.pendingTree.layerTreeHostImpl = this;
+ this.pendingTree.whichTree = constants.PENDING_TREE;
+ }
+ },
+
+ /**
+ * Get all of tile scales and their associated names.
+ */
+ getContentsScaleNames() {
+ const scales = {};
+ for (let i = 0; i < this.activeTiles.length; ++i) {
+ const tile = this.activeTiles[i];
+ // Return scale -> scale name mappings.
+ // Example:
+ // 0.25 -> LOW_RESOLUTION
+ // 1.0 -> HIGH_RESOLUTION
+ // 0.75 -> NON_IDEAL_RESOLUTION
+ scales[tile.contentsScale] = tile.resolution;
+ }
+ return scales;
+ },
+
+ getTree(whichTree) {
+ if (whichTree === constants.ACTIVE_TREE) {
+ return this.activeTree;
+ }
+ if (whichTree === constants.PENDING_TREE) {
+ return this.pendingTree;
+ }
+ throw new Exception('Unknown tree type + ' + whichTree);
+ },
+
+ get tilesHaveGpuMemoryUsageInfo() {
+ if (this.tilesHaveGpuMemoryUsageInfo_ !== undefined) {
+ return this.tilesHaveGpuMemoryUsageInfo_;
+ }
+
+ for (let i = 0; i < this.activeTiles.length; i++) {
+ if (this.activeTiles[i].gpuMemoryUsageInBytes === undefined) {
+ continue;
+ }
+ this.tilesHaveGpuMemoryUsageInfo_ = true;
+ return true;
+ }
+ this.tilesHaveGpuMemoryUsageInfo_ = false;
+ return false;
+ },
+
+ get gpuMemoryUsageInBytes() {
+ if (!this.tilesHaveGpuMemoryUsageInfo) return;
+
+ let usage = 0;
+ for (let i = 0; i < this.activeTiles.length; i++) {
+ const u = this.activeTiles[i].gpuMemoryUsageInBytes;
+ if (u !== undefined) usage += u;
+ }
+ return usage;
+ },
+
+ get userFriendlyName() {
+ let frameNumber;
+ if (!this.activeTree) {
+ frameNumber = this.objectInstance.snapshots.indexOf(this);
+ } else {
+ if (this.activeTree.sourceFrameNumber === undefined) {
+ frameNumber = this.objectInstance.snapshots.indexOf(this);
+ } else {
+ frameNumber = this.activeTree.sourceFrameNumber;
+ }
+ }
+ return 'cc::LayerTreeHostImpl frame ' + frameNumber;
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(
+ LayerTreeHostImplSnapshot,
+ {typeName: 'cc::LayerTreeHostImpl'});
+
+ /**
+ * @constructor
+ */
+ function LayerTreeHostImplInstance() {
+ ObjectInstance.apply(this, arguments);
+
+ this.allLayersBBox_ = undefined;
+ }
+
+ LayerTreeHostImplInstance.prototype = {
+ __proto__: ObjectInstance.prototype,
+
+ get allContentsScales() {
+ if (this.allContentsScales_) {
+ return this.allContentsScales_;
+ }
+
+ const scales = {};
+ for (const tileID in this.allTileHistories_) {
+ const tileHistory = this.allTileHistories_[tileID];
+ scales[tileHistory.contentsScale] = true;
+ }
+ this.allContentsScales_ = Object.keys(scales);
+ return this.allContentsScales_;
+ },
+
+ get allLayersBBox() {
+ if (this.allLayersBBox_) {
+ return this.allLayersBBox_;
+ }
+ const bbox = new tr.b.math.BBox2();
+ function handleTree(tree) {
+ tree.renderSurfaceLayerList.forEach(function(layer) {
+ bbox.addQuad(layer.layerQuad);
+ });
+ }
+ this.snapshots.forEach(function(lthi) {
+ handleTree(lthi.activeTree);
+ if (lthi.pendingTree) {
+ handleTree(lthi.pendingTree);
+ }
+ });
+ this.allLayersBBox_ = bbox;
+ return this.allLayersBBox_;
+ }
+ };
+
+ ObjectInstance.subTypes.register(
+ LayerTreeHostImplInstance,
+ {typeName: 'cc::LayerTreeHostImpl'});
+
+ return {
+ LayerTreeHostImplSnapshot,
+ LayerTreeHostImplInstance,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test.html
new file mode 100644
index 00000000000..207ae0a4b11
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/layer_tree_host_impl.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
+ const snapshot = instance.snapshots[0];
+
+ assert.instanceOf(snapshot, tr.e.cc.LayerTreeHostImplSnapshot);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js
new file mode 100644
index 00000000000..b8e443aa0a1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js
@@ -0,0 +1,345 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+// A single LTHI sort of manually created from a Google search for cats.
+// This cannot be const because this file may be loaded more than once.
+global.g_catLTHIEvents = [
+ {
+ 'name': 'cc::Picture',
+ 'args': {
+ 'snapshot': {
+ 'params': {
+ 'opaque_rect': [
+ -15,
+ -15,
+ 0,
+ 0
+ ],
+ 'layer_rect': [
+ -15,
+ -15,
+ 1260,
+ 1697
+ ]
+ },
+ 'skp64': 'c2tpYXBpY3QWAAAAOAQAABQDAAADAAAAAWRhZXKoCQAACAAAHgMAAAAIAAAeAwAAAAwAACMAAHBBAABwQRwAAAMAAHDBAABwwQAghUQAQEFEAQAAAKAJAAAYAAAVAQAAAAAAAAAAAAAAAECDRACAPUQIAAAeAwAAABwAAAMAAAAAAAAAAABAg0QAAMhBAQAAAIwAAAAYAAAVAgAAAAAAAAAAAAAAAECDRAAAyEEEAAAcCAAAHgMAAAAcAAADAAAAAAAAyEEAQINEAADQQQEAAADYAAAADAAAIwAAAAAAAMhBGAAAFQIAAAAAAAAAAAAAAABAg0QAAMhBBAAAHBgAABUDAAAAAAAAAAAAyEEAQINEAADQQQgAAB4DAAAACAAAHgMAAAAMAAAjAABwwQAAcMEUAAAGAAAAAAAAAAAAAIhBAACIQQQAABwEAAAcCAAAHgMAAAAcAAADAACAQAAAAEAAAHxCAADAQQEAAABQAQAABAAAHAgAAB4DAAAAHAAAAwAAgEAAAABAAAB8QgAAwEEBAAAAeAEAAAQAABwIAAAeAwAAABwAAAMAAIBAAAAAQAAAfEIAAMBBAQAAAOABAABAAAAUBAAAAAwAAAA1AEgARgBSAFUARwAGAAAAAKDcPwCG4kEAAJBBAAAgQQDSlkEAONVBAEsHQgCxKUIAm0BCBAAAHAgAAB4DAAAAHAAAAwAAgEAAAABAAAB8QgAAwEEBAAAACAIAAAQAABwkAAAUBQAAAAIAAAADAAAAAQAAAAAAYD0AkM1BAACQQQDwhUIIAAAeAwAAAAgAAB4DAAAADAAAIwAAcMEAAHDBFAAABgAAAAABAAAAAACyQgAAsEEEAAAcBAAAHCQAABQFAAAAAgAAAAMAAAABAAAAAABgPQCQzUEAAJBBAJCxQlgAABQGAAAAFAAAADAAUgBRAEwAVwBSAFUATABRAEoACgAAAAAQE0AA3sVBAACQQQCQvUIAkNVCAJDlQgCQ9UIAkPtCAMgBQwDICUMAyA5DAMgRQwDIGUMkAAAUBQAAAAIAAAADAAAAAQAAAAAAYD0AkM1BAACQQQDII0MIAAAeAwAAAAgAAB4DAAAADAAAIwAAcMEAAHDBFAAABgAAAAACAAAAAAA5QwAAiEEEAAAcBAAAHAgAAB4DAAAAHAAAAwAALEMAAABAAIC/QwAAwEEBAAAAZAMAAAQAABwIAAAeAwAAABwAAAMAACxDAAAAQACAv0MAAMBBAQAAAIwDAAAEAAAcCAAAHgMAAAAcAAADAAAsQwAAAEAAgL9DAADAQQEAAAB0BAAAwAAAFAcAAAA2AAAAJgBEAFMAVwBYAFUASAADADAAUgBRAEwAVwBSAFUATABRAEoAAwA2AFEARABTAFYASwBSAFcAAAAbAAAAAKDcPwCG4kEAAJBBAAAyQ8CvO0MAa0NDwDpMQ0B3UUOAJ1pDAOJfQ8CuZ0PAHGxDwCt4Q6BigEPAuoRDwMCGQwBfiUPAq41DAImQQwCPkkMg55ZDgESbQ4B7nUOgQKFDwJilQ2B2qUNA3q1DwG+xQ+DHtUOgFLpDBAAAHAgAAB4DAAAAHAAAAwAALEMAAABAAIC/QwAAwEEBAAAAnAQAAAQAABwkAAAUBQAAAAIAAAADAAAAAQAAAAAAYD0AkM1BAACQQQCYwUMIAAAeAwAAAAgAAB4DAAAADAAAIwAAcMEAAHDBFAAABgAAAAADAAAAAADrQwAAiEEEAAAcBAAAHAgAAB4DAAAAHAAAAwCA5EMAAABAAAD6QwAAwEEBAAAAIAUAAAQAABwIAAAeAwAAABwAAAMAgORDAAAAQAAA+kMAAMBBAQAAAEgFAAAEAAAcCAAAHgMAAAAcAAADAIDkQwAAAEAAAPpDAADAQQEAAACkBQAANAAAFAcAAAAIAAAANgBEAFkASAAEAAAAAKDcPwCG4kEAAJBBAIDnQyBF60PAIu9DQMLyQwQAABwIAAAeAwAAABwAAAMAgORDAAAAQAAA+kMAAMBBAQAAAMwFAAAEAAAcJAAAFAUAAAACAAAAAwAAAAEAAAAAAGA9AJDNQQAAkEEAwvtDCAAAHgMAAAAIAAAeAwAAAAwAACMAAHDBAABwwRQAAAYAAAAABAAAAABAA0QAAIhBBAAAHAQAABwIAAAeAwAAABwAAAMAAABEAAAAQAAAC0QAAMBBAQAAAFAGAAAEAAAcCAAAHgMAAAAcAAADAAAARAAAAEAAAAtEAADAQQEAAAB4BgAABAAAHAgAAB4DAAAAHAAAAwAAAEQAAABAAAALRAAAwEEBAAAA1AYAADQAABQEAAAACAAAAC8AUgBEAEcABAAAAACg3D8AhuJBAACQQQCAAUTAXQNEIIQFRPByB0QEAAAcCAAAHgMAAAAcAAADAAAARAAAAEAAAAtEAADAQQEAAAD8BgAABAAAHDAAABQGAAAABgAAAEEAQgBBAAAAAwAAAACAmD4A3rVBAACAQQCADEQAQA5EAEAQRBgAABUIAAAAAECARAAAAEAAIINEAADAQQwAAA4JAAAAAQAAACQAABQKAAAAAgAAACIAAAABAAAAAICYPgDetUEAAIBBADCBRBgAABUDAAAAAAAAAAAA+kMAQINEAID6QxgAABULAAAAAICARAAA0EEAQINEAAD6QxgAABUMAAAAAICARAAA0EEAoIBEAAD6QxgAABUNAAAAAAAAAAAA/kMAQINEAIA9RBgAABUIAAAAAMBNRAAAAEAAQHhEAACoQQwAAA4JAAAAAgAAACQAABQOAAAAAgAAAJ0DAAABAAAAAIAmwABQ3kEAAIBBAEB4RCQAABQOAAAAAgAAAJ8DAAABAAAAAIAmwABQ3kEAAIBBAEB8RAgAAB4DAAAAHAAAAwDATUQAAEBAAEB4RAAAsEEBAAAAfAgAABAAAB8AAAAADwAAAB8AAAAEAAAcBAAAHAgAAB4DAAAAHAAAAwAAAAAAgPpDAECDRAAA+0MBAAAA1AgAAAwAACMAAAAAAID6QwwAACMAAACAAACAwBgAABUQAAAAAAAAAAAAAAAAQINEAACgQAQAABwIAAAeAwAAABwAAAMAAAAAAAD7QwBAg0QAgP1DAQAAACAJAAAMAAAjAAAAAAAA+0MYAAAVEAAAAAAAAAAAAAAAAECDRAAAoEAEAAAcCAAAHgMAAAAcAAADAAAAAACA/UMAQINEAAD+QwEAAABsCQAADAAAIwAAAAAAgP1DGAAAFRAAAAAAAAAAAAAAAABAg0QAAKBABAAAHBgAABURAAAAAAAAAACA+kMAQINEAAD7QxgAABUSAAAAAAAAAACA/UMAQINEAAD+QwQAABwEAAAcdGNhZiMAAAACAAAADVNrU3JjWGZlcm1vZGUQU2tMaW5lYXJHcmFkaWVudGNmcHQCAAAAAAENTHVjaWRhIEdyYW5kZQQNTHVjaWRhIEdyYW5kZQYMTHVjaWRhR3JhbmRl/v8AAAABCUhlbHZldGljYQQJSGVsdmV0aWNhBglIZWx2ZXRpY2H+/wAAeWFyYcQIAABwbXRiBQAAAD8AAAAWAAAAAAAAAKkAAACJUE5HDQoaCgAAAA1JSERSAAAAPwAAABYIBgAAAHf8RCEAAABwSURBVFiF7ZSxAcQgDMRk8KQMRQdD0lElxf8MueKsCSSMHXPOB1MSYIyh9vicvfcv/t6rdpGQAOcctYeEphZQkgCteb5Bxffe1R4SEiAi1B4SKt7123teuj/Wk6+dd42vnXedfMVXvCEVv9ZSe0h4ASOjDeti06sSAAAAAElFTkSuQmCCAAAAAAAAAAAAAAAMAAAADQAAAAAAAAAPAQAAiVBORw0KGgoAAAANSUhEUgAAAAwAAAANCAYAAACdKY9CAAAA1klEQVQokZWSMWrDQBBF38hrxW5SGJdSkyqtyRXSB3QRnUUXEWzvK+QKwSCxxbIE5CpaZMmFsuBCK/DAr+a9zxQjwBY4AK/AjuX5A67ArwIOVVV9FEXxlmXZcYlu29bVdf1TluW3AO9N03zG4Ecpz/OzAKdpmr7W4DAiohUgwzAwjuMqnCQJgCiAJwQUgPce7/2qkKbpLAY7NMTawz5OxWSgN8a40BKLMcYBfQJ0WuuLtdYppViKtdZprS9AJ8AeODK/xkvkkp75NZwAAmz+IxFhAm7A7Q619kxK1JGuJQAAAABJRU5ErkJgggAAAAAAAAAAANcAAAAWAAAAAAAAAMcAAACJUE5HDQoaCgAAAA1JSERSAAAA1wAAABYIBgAAAFPJCaQAAACOSURBVHic7duxDYQwEETRObSVupJrgpQiiRwS0AIrS9Z7FUzytU78O8/zH+BzlSRjjNU7YCvXdb1xzTlXb4HtVJLc9716B2znWD0AdlVJchwag69VklTV6h2wHZcLmqgKmrhc0ERc0ERc0ERc0ERV0ERc0MSzEJqoCpq4XNBEVdDE5YImqoImlbz//YFvPbqBDWEab+OuAAAAAElFTkSuQmCCAAAAAAAAAAAALwAAABYAAAAAAAAApgAAAIlQTkcNChoKAAAADUlIRFIAAAAvAAAAFggGAAAAUFLFyQAAAG1JREFUWIXt17ENwCAUA9EL8qRMkiVoGZKKMgVZIKSwLPEmOKzfcLXWbkIJoNbq7vis977i55zuli0CGGO4O7YUd8AfAigl8w0CkOTu2BK9fGb1K3r5E+8SHZ9Z/YqOP2fjcpZ3Ocu7CNZ/MNEDHg4NYflXb+0AAAAASUVORK5CYIIAAAAAAAAAAAAAMAAAABYAAAAAAAAArgAAAIlQTkcNChoKAAAADUlIRFIAAAAwAAAAFggGAAAAhvcfrAAAAHVJREFUWIXtk7ERwCAMxGTwpAxFB0PSUSVFMoFT/JmLJpDOfuu9XyTGAVprao8Qc84nYO+tdgnjAGsttUeYohb4igOUkrfjjIBaq9ojjAOYmdojzBkBmV8o73pf0l/gjA1kDjhjA5kv8Aeo+QPUOMAYQ+0R5gZf3A3r3/HMCQAAAABJRU5ErkJgggAAAAAAAAAAAAAgdG5wEgAAAAAAQEEAAIA/AAAAAAAAAAAAAIBA/////wIwAwAAAAAAAAAAAAAAAAABAAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBAACAPwAAAAAAAAAAAACAQAAAAP8CMAMAAAAAAAAAAAACAAAATAAAAAAAAAAAAAAAAgAAAOXl5f/R0dH/EAAAAAAAAAAK1yM9AAAAAArXI70AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAyEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQQAAgD8AAAAAAAAAAAAAgECOjo7/ADADAAAAAAAAAGBBAACAPwAAAAAAAAAAAACAQAAAAP8BMIMCAwAAAAEAAAAAAIBBAACAPwAAAAAAAAAAAACAQAAAAP8BMIMCAwAAAAIAAAAAAGBBAACAPwAAAAAAAAAAAACAQAAAAP8BMIMCAwAAAAIAAAAAAGBBAACAPwAAAAAAAAAAAACAQH9/f/8BMIMCAwAAAAEAAAAAAEBBAACAPwAAAAAAAAAAAACAQPj4+P8AMAMAAAAAAAAAQEEAAIA/AAAAAAAAAAAAAIBAAAAAfwAwAwAAAAAAAABgQQAAgD8AAAAAAAAAAAAAgEAAAADMATCDAgMAAAACAAAAAABAQQAAgD8AAAAAAAAAAAAAgEDs7Oz/ADADAAAAAAAAAEBBAACAPwAAAAAAAAAAAACAQAAAAP8AMAMAAAAAAAAAQEEAAIA/AAAAAAAAAAAAAIBA/////wAwAwAAAAAAAACAQQAAgD8AAAAAAAAAAAAAgEAAAAD/ATCDAgMAAAABAAAAAABAQQAAgD8AAAAAAAAAAAAAgEAAAAA/ADAAAAAAAAAAAEBBAACAPwAAAAAAAAAAAACAQAAAAP8CMAMAAAAAAAAAAAACAAAATAAAAAAAAAAAAAAAAgAAAOXl5f/R0dH/EAAAAAAAAADNzEw+AAAAAM3MTL4AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQQAAgD8AAAAAAAAAAAAAgED/////ADACAAAAAAAAAEBBAACAPwAAAAAAAAAAAACAQI6Ojv8AMAIAAAAAACBodHACAAAAAgAAAAABAAABAAACAAAAAAoAAAAIAAAAAAAAAAUBAQEABQEBAQAAQIBEAAAAQAAgg0QAAABAACCDRAAAwEEAQIBEAADAQQBggEQAAEBAAACDRAAAQEAAAINEAAC4QQBggEQAALhBAECARAAAAEAAIINEAADAQQAAAAEAAAEAAAIAAAAACgAAAAgAAAAAAAAABQEBAQAFAQEBAADATUQAAABAAEB4RAAAAEAAQHhEAACoQQDATUQAAKhBAABORAAAQEAAAHhEAABAQAAAeEQAAKBBAABORAAAoEEAwE1EAAAAQABAeEQAAKhBAAAgZm9l' // @suppress longLineCheck
+ }
+ },
+ 'pid': 1,
+ 'ts': 100,
+ 'cat': 'disabled-by-default-cc.debug',
+ 'tid': 1,
+ 'ph': 'O',
+ 'id': 'PICTURE_1'
+ },
+ {
+ 'name': 'AnalyzeTask',
+ 'args': {
+ 'data': {
+ 'source_frame_number': 107,
+ 'tile_id': {
+ 'id_ref': 'TILE_1'
+ },
+ 'resolution': 'HIGH_RESOLUTION',
+ 'is_tile_in_pending_tree_now_bin': true
+ }
+ },
+ 'pid': 1,
+ 'ts': 101,
+ 'cat': 'cc',
+ 'tid': 1,
+ 'ph': 'B'
+ },
+ {
+ 'name': 'AnalyzeTask',
+ 'args': {},
+ 'pid': 1,
+ 'ts': 105,
+ 'cat': 'cc',
+ 'tid': 1,
+ 'ph': 'E'
+ },
+ {
+ 'name': 'RasterTask',
+ 'args': {
+ 'data': {
+ 'source_frame_number': 107,
+ 'tile_id': {
+ 'id_ref': 'TILE_1'
+ },
+ 'resolution': 'HIGH_RESOLUTION',
+ 'is_tile_in_pending_tree_now_bin': true
+ }
+ },
+ 'pid': 1,
+ 'ts': 110,
+ 'cat': 'cc',
+ 'tid': 1,
+ 'ph': 'B'
+ },
+ {
+ 'name': 'RasterTask',
+ 'args': {},
+ 'pid': 1,
+ 'ts': 150,
+ 'cat': 'cc',
+ 'tid': 1,
+ 'ph': 'E'
+ },
+ {
+ 'name': 'RasterTask',
+ 'args': {
+ 'data': {
+ 'source_frame_number': 107,
+ 'tile_id': {
+ 'id_ref': 'TILE_2'
+ },
+ 'resolution': 'HIGH_RESOLUTION',
+ 'is_tile_in_pending_tree_now_bin': true
+ }
+ },
+ 'pid': 1,
+ 'ts': 170,
+ 'cat': 'cc',
+ 'tid': 1,
+ 'ph': 'B'
+ },
+ {
+ 'name': 'RasterTask',
+ 'args': {},
+ 'pid': 1,
+ 'ts': 180,
+ 'cat': 'cc',
+ 'tid': 1,
+ 'ph': 'E'
+ },
+ {
+ 'name': 'cc::LayerTreeHostImpl',
+ 'args': {
+ 'snapshot': {
+ 'device_viewport_size': {
+ 'width': 2460,
+ 'height': 1606
+ },
+ 'active_tree': {
+ 'source_frame_number': 7,
+ 'root_layer': {
+ 'tilings': [
+ {
+ 'content_scale': 2,
+ 'content_bounds': {
+ 'width': 2460,
+ 'height': 3334
+ },
+ 'num_tiles': 1
+ },
+ {
+ 'content_scale': 0.25,
+ 'content_bounds': {
+ 'width': 308,
+ 'height': 417
+ },
+ 'num_tiles': 1
+ }
+ ],
+ 'coverage_tiles': [
+ {
+ 'geometry_rect': [0, 0, 256, 256],
+ 'tile': {
+ 'id_ref': 'TILE_1'
+ }
+ },
+ {
+ 'geometry_rect': [256, 0, 256, 256]
+ },
+ {
+ 'geometry_rect': [512, 0, 256, 256]
+ },
+ {
+ 'geometry_rect': [0, 256, 256, 512]
+ },
+ {
+ 'geometry_rect': [256, 256, 512, 512]
+ }
+ ],
+ 'gpu_memory_usage': 22069248,
+ 'draws_content': 1,
+ 'layer_id': 6,
+ 'invalidation': [10, 20, 30, 40],
+ 'bounds': {
+ 'width': 1230,
+ 'height': 1667
+ },
+ 'children': [
+ {
+ 'tilings': [
+ {
+ 'content_scale': 2,
+ 'content_bounds': {
+ 'width': 200,
+ 'height': 100
+ },
+ 'num_tiles': 1
+ }
+ ],
+ 'gpu_memory_usage': 128000,
+ 'draws_content': 1,
+ 'layer_id': 7,
+ 'invalidation': [],
+ 'bounds': {
+ 'width': 100,
+ 'height': 50
+ },
+ 'children': [
+ ],
+ 'ideal_contents_scale': 2,
+ 'layer_quad': [
+ 0,
+ 0,
+ 200,
+ 0,
+ 200,
+ 100,
+ 0,
+ 100
+ ],
+ 'pictures': [
+ ],
+ 'debug_info': {
+ 'annotated_invalidation_rects': [
+ {
+ 'geometry_rect': [11, 22, 33, 44],
+ 'reason': 'appeared',
+ 'client': 'client1'
+ },
+ {
+ 'geometry_rect': [22, 33, 44, 55],
+ 'reason': 'disappeared',
+ 'client': 'client2'
+ },
+ ]
+ },
+ 'id': 'cc::PictureLayerImpl/LAYER_2'
+ }
+ ],
+ 'ideal_contents_scale': 2,
+ 'layer_quad': [
+ 0,
+ -1022,
+ 2460,
+ -1022,
+ 2460,
+ 2312,
+ 0,
+ 2312
+ ],
+ 'pictures': [
+ {
+ 'id_ref': 'PICTURE_1'
+ }
+ ],
+ 'id': 'cc::PictureLayerImpl/LAYER_1'
+ },
+ 'render_surface_layer_list': [
+ {'id_ref': 'LAYER_1'},
+ {'id_ref': 'LAYER_2'}
+ ],
+ 'id': 'cc::LayerTreeImpl/0x7d246ee0'
+ },
+ 'tiles': [
+ {
+ 'active_priority': {
+ 'time_to_visible_in_seconds': 0,
+ 'resolution': 'HIGH_RESOLUTION',
+ 'distance_to_visible_in_pixels': 0
+ },
+ 'pending_priority': {
+ 'time_to_visible_in_seconds': 3.4028234663852886e+38,
+ 'resolution': 'NON_IDEAL_RESOLUTION',
+ 'distance_to_visible_in_pixels': 3.4028234663852886e+38
+ },
+ 'managed_state': {
+ 'resolution': 'HIGH_RESOLUTION',
+ 'is_solid_color': false,
+ 'is_using_gpu_memory': true,
+ 'has_resource': true,
+ 'scheduled_priority': 10,
+ 'distance_to_visible': 0,
+ 'gpu_memory_usage': 1024000
+ },
+ 'layer_id': '6',
+ 'picture_pile': {
+ 'id_ref': 'PICTURE_1'
+ },
+ 'contents_scale': 2,
+ 'content_rect': [0, 0, 1024, 1024],
+ 'id': 'cc::Tile/TILE_1'
+ },
+ {
+ 'active_priority': {
+ 'time_to_visible_in_seconds': 0,
+ 'resolution': 'HIGH_RESOLUTION',
+ 'distance_to_visible_in_pixels': 0
+ },
+ 'pending_priority': {
+ 'time_to_visible_in_seconds': 3.4028234663852886e+38,
+ 'resolution': 'NON_IDEAL_RESOLUTION',
+ 'distance_to_visible_in_pixels': 3.4028234663852886e+38
+ },
+ 'managed_state': {
+ 'resolution': 'HIGH_RESOLUTION',
+ 'is_solid_color': false,
+ 'is_using_gpu_memory': true,
+ 'has_resource': true,
+ 'scheduled_priority': 12,
+ 'distance_to_visible': 0,
+ 'gpu_memory_usage': 1024000
+ },
+ 'layer_id': '6',
+ 'picture_pile': {
+ 'id_ref': 'PICTURE_1'
+ },
+ 'contents_scale': 2,
+ 'content_rect': [0, 1024, 1024, 1024],
+ 'id': 'cc::Tile/TILE_2'
+ }
+ ]
+ }
+ },
+ 'pid': 1,
+ 'ts': 500,
+ 'cat': 'disabled-by-default-cc.debug',
+ 'tid': 28163,
+ 'ph': 'O',
+ 'id': 'LTHI_1'
+ },
+ {
+ 'name': 'cc::DisplayItemList',
+ 'args': {
+ 'snapshot': {
+ 'params': {
+ 'layer_rect': [
+ -15,
+ -15,
+ 1260,
+ 1697
+ ],
+ 'items': [
+ 'BeginClipDisplayItem',
+ 'EndClipDisplayItem'
+ ]
+ },
+ 'skp64': '[base 64 encoded skia picture]'
+ }
+ },
+ 'pid': 1,
+ 'ts': 300,
+ 'cat': 'disabled-by-default-cc.debug',
+ 'tid': 1,
+ 'ph': 'O',
+ 'id': 'PICTURE_3'
+ }
+];
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_impl.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_impl.html
new file mode 100644
index 00000000000..8b2d4120737
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/layer_tree_impl.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/constants.html">
+<link rel="import" href="/tracing/extras/chrome/cc/layer_impl.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const constants = tr.e.cc.constants;
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ /**
+ * @constructor
+ */
+ function LayerTreeImplSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ }
+
+ LayerTreeImplSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ preInitialize() {
+ tr.e.cc.preInitializeObject(this);
+ this.layerTreeHostImpl = undefined;
+ this.whichTree = undefined;
+ this.sourceFrameNumber = undefined;
+ },
+
+ initialize() {
+ tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
+ this, ['renderSurfaceLayerList']);
+ tr.e.cc.moveOptionalFieldsFromArgsToToplevel(
+ this, ['rootLayer', 'layers']);
+ if (this.args.sourceFrameNumber) {
+ this.sourceFrameNumber = this.args.sourceFrameNumber;
+ }
+
+ // Slimming Paint v2 removes the tree hierarchy and replace
+ // it with a layer list. The tracing data should have either
+ // rootLayer or layers available.
+ if (this.rootLayer) {
+ // The version before SPv2
+ this.rootLayer.layerTreeImpl = this;
+ } else {
+ // The SPv2 version, where the layer list contains all
+ // non-mask, non-replica layers.
+ for (let i = 0; i < this.layers.length; i++) {
+ this.layers[i].layerTreeImpl = this;
+ }
+ }
+
+ if (this.args.swapPromiseTraceIds &&
+ this.args.swapPromiseTraceIds.length) {
+ this.tracedInputLatencies = [];
+
+ const ownProcess = this.objectInstance.parent;
+ const modelHelper = ownProcess.model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (modelHelper) {
+ this._initializeTracedInputLatencies(modelHelper);
+ }
+ }
+ },
+
+ _initializeTracedInputLatencies(modelHelper) {
+ const latencyEvents = modelHelper.browserHelper.getLatencyEventsInRange(
+ modelHelper.model.bounds);
+
+ // Convert all ids to InputLatency Async objects.
+ latencyEvents.forEach(function(event) {
+ for (let i = 0; i < this.args.swapPromiseTraceIds.length; i++) {
+ if (!event.args.data || !event.args.data.trace_id) {
+ continue;
+ }
+ if (parseInt(event.args.data.trace_id) ===
+ this.args.swapPromiseTraceIds[i]) {
+ this.tracedInputLatencies.push(event);
+ }
+ }
+ }, this);
+ },
+
+ get hasSourceFrameBeenDrawnBefore() {
+ if (this.whichTree === tr.e.cc.constants.PENDING_TREE) {
+ return false;
+ }
+
+ // Old chrome's don't produce sourceFrameNumber.
+ if (this.sourceFrameNumber === undefined) return;
+
+ const thisLTHI = this.layerTreeHostImpl;
+ const thisLTHIIndex = thisLTHI.objectInstance.snapshots.indexOf(
+ thisLTHI);
+ const prevLTHIIndex = thisLTHIIndex - 1;
+ if (prevLTHIIndex < 0 ||
+ prevLTHIIndex >= thisLTHI.objectInstance.snapshots.length) {
+ return false;
+ }
+ const prevLTHI = thisLTHI.objectInstance.snapshots[prevLTHIIndex];
+ if (!prevLTHI.activeTree) return false;
+
+ // Old chrome's don't produce sourceFrameNumber.
+ if (prevLTHI.activeTree.sourceFrameNumber === undefined) return;
+ return prevLTHI.activeTree.sourceFrameNumber === this.sourceFrameNumber;
+ },
+
+ get otherTree() {
+ const other = this.whichTree === constants.ACTIVE_TREE ?
+ constants.PENDING_TREE : constants.ACTIVE_TREE;
+ return this.layerTreeHostImpl.getTree(other);
+ },
+
+ get gpuMemoryUsageInBytes() {
+ let totalBytes = 0;
+ this.iterLayers(function(layer) {
+ if (layer.gpuMemoryUsageInBytes !== undefined) {
+ totalBytes += layer.gpuMemoryUsageInBytes;
+ }
+ });
+ return totalBytes;
+ },
+
+ iterLayers(func, thisArg) {
+ const visitedLayers = {};
+ function visitLayer(layer, depth, isMask, isReplica) {
+ if (visitedLayers[layer.layerId]) return;
+
+ visitedLayers[layer.layerId] = true;
+ func.call(thisArg, layer, depth, isMask, isReplica);
+ if (layer.children) {
+ for (let i = 0; i < layer.children.length; i++) {
+ visitLayer(layer.children[i], depth + 1);
+ }
+ }
+ if (layer.maskLayer) {
+ visitLayer(layer.maskLayer, depth + 1, true, false);
+ }
+ if (layer.replicaLayer) {
+ visitLayer(layer.replicaLayer, depth + 1, false, true);
+ }
+ }
+ if (this.rootLayer) {
+ visitLayer(this.rootLayer, 0, false, false);
+ } else {
+ for (let i = 0; i < this.layers.length; i++) {
+ visitLayer(this.layers[i], 0, false, false);
+ }
+ }
+ },
+ findLayerWithId(id) {
+ let foundLayer = undefined;
+ function visitLayer(layer) {
+ if (layer.layerId === id) {
+ foundLayer = layer;
+ }
+ }
+ this.iterLayers(visitLayer);
+ return foundLayer;
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(
+ LayerTreeImplSnapshot,
+ {typeName: 'cc::LayerTreeImpl'});
+
+ return {
+ LayerTreeImplSnapshot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture.html
new file mode 100644
index 00000000000..b1a6f2ef288
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture.html
@@ -0,0 +1,451 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/extras/chrome/cc/picture_as_image_data.html">
+<link rel="import" href="/tracing/extras/chrome/cc/util.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+tr.exportTo('tr.e.cc', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ // Number of pictures created. Used as an uniqueId because we are immutable.
+ const PictureCount = 0;
+ const OPS_TIMING_ITERATIONS = 3;
+
+ function Picture(skp64, layerRect) {
+ this.skp64_ = skp64;
+ this.layerRect_ = layerRect;
+
+ this.guid_ = tr.b.GUID.allocateSimple();
+ }
+
+ Picture.prototype = {
+ get canSave() {
+ return true;
+ },
+
+ get layerRect() {
+ return this.layerRect_;
+ },
+
+ get guid() {
+ return this.guid_;
+ },
+
+ getBase64SkpData() {
+ return this.skp64_;
+ },
+
+ getOps() {
+ if (!PictureSnapshot.CanGetOps()) {
+ console.error(PictureSnapshot.HowToEnablePictureDebugging());
+ return undefined;
+ }
+
+ const ops = window.chrome.skiaBenchmarking.getOps({
+ skp64: this.skp64_,
+ params: {
+ layer_rect: this.layerRect_.toArray()
+ }
+ });
+
+ if (!ops) {
+ console.error('Failed to get picture ops.');
+ }
+
+ return ops;
+ },
+
+ getOpTimings() {
+ if (!PictureSnapshot.CanGetOpTimings()) {
+ console.error(PictureSnapshot.HowToEnablePictureDebugging());
+ return undefined;
+ }
+
+ const opTimings = window.chrome.skiaBenchmarking.getOpTimings({
+ skp64: this.skp64_,
+ params: {
+ layer_rect: this.layerRect_.toArray()
+ }
+ });
+
+ if (!opTimings) {
+ console.error('Failed to get picture op timings.');
+ }
+
+ return opTimings;
+ },
+
+ /**
+ * Tag each op with the time it takes to rasterize.
+ *
+ * FIXME: We should use real statistics to get better numbers here, see
+ * https://code.google.com/p/trace-viewer/issues/detail?id=357
+ *
+ * @param {Array} ops Array of Skia operations.
+ * @return {Array} Skia ops where op.cmd_time contains the associated time
+ * for a given op.
+ */
+ tagOpsWithTimings(ops) {
+ const opTimings = [];
+ for (let iteration = 0; iteration < OPS_TIMING_ITERATIONS; iteration++) {
+ opTimings[iteration] = this.getOpTimings();
+ if (!opTimings[iteration] || !opTimings[iteration].cmd_times) {
+ return ops;
+ }
+ if (opTimings[iteration].cmd_times.length !== ops.length) {
+ return ops;
+ }
+ }
+
+ for (let opIndex = 0; opIndex < ops.length; opIndex++) {
+ let min = Number.MAX_VALUE;
+ for (let i = 0; i < OPS_TIMING_ITERATIONS; i++) {
+ min = Math.min(min, opTimings[i].cmd_times[opIndex]);
+ }
+ ops[opIndex].cmd_time = min;
+ }
+
+ return ops;
+ },
+
+ /**
+ * Rasterize the picture.
+ *
+ * @param {{opt_stopIndex: number, params}} The SkPicture operation to
+ * rasterize up to. If not defined, the entire SkPicture is rasterized.
+ * @param {{opt_showOverdraw: bool, params}} Defines whether pixel overdraw
+ should be visualized in the image.
+ * @param {function(tr.e.cc.PictureAsImageData)} The callback function that
+ * is called after rasterization is complete or fails.
+ */
+ rasterize(params, rasterCompleteCallback) {
+ if (!PictureSnapshot.CanRasterize() || !PictureSnapshot.CanGetOps()) {
+ rasterCompleteCallback(new tr.e.cc.PictureAsImageData(
+ this, tr.e.cc.PictureSnapshot.HowToEnablePictureDebugging()));
+ return;
+ }
+
+ if (!this.layerRect_.width || !this.layerRect_.height) {
+ rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this, null));
+ return;
+ }
+
+ const raster = window.chrome.skiaBenchmarking.rasterize(
+ {
+ skp64: this.skp64_,
+ params: {
+ layer_rect: this.layerRect_.toArray()
+ }
+ },
+ {
+ stop: params.stopIndex === undefined ? -1 : params.stopIndex,
+ overdraw: !!params.showOverdraw,
+ params: { }
+ });
+
+ if (raster) {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+ canvas.width = raster.width;
+ canvas.height = raster.height;
+ const imageData = ctx.createImageData(raster.width, raster.height);
+ imageData.data.set(new Uint8ClampedArray(raster.data));
+ rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this, imageData));
+ } else {
+ const error = 'Failed to rasterize picture. ' +
+ 'Your recording may be from an old Chrome version. ' +
+ 'The SkPicture format is not backward compatible.';
+ rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this, error));
+ }
+ }
+ };
+
+ function LayeredPicture(pictures) {
+ this.guid_ = tr.b.GUID.allocateSimple();
+ this.pictures_ = pictures;
+ this.layerRect_ = undefined;
+ }
+
+ LayeredPicture.prototype = {
+ __proto__: Picture.prototype,
+
+ get canSave() {
+ return false;
+ },
+
+ get typeName() {
+ return 'cc::LayeredPicture';
+ },
+
+ get layerRect() {
+ if (this.layerRect_ !== undefined) {
+ return this.layerRect_;
+ }
+
+ this.layerRect_ = {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0
+ };
+
+ for (let i = 0; i < this.pictures_.length; ++i) {
+ const rect = this.pictures_[i].layerRect;
+ this.layerRect_.x = Math.min(this.layerRect_.x, rect.x);
+ this.layerRect_.y = Math.min(this.layerRect_.y, rect.y);
+ this.layerRect_.width =
+ Math.max(this.layerRect_.width, rect.x + rect.width);
+ this.layerRect_.height =
+ Math.max(this.layerRect_.height, rect.y + rect.height);
+ }
+ return this.layerRect_;
+ },
+
+ get guid() {
+ return this.guid_;
+ },
+
+ getBase64SkpData() {
+ throw new Error('Not available with a LayeredPicture.');
+ },
+
+ getOps() {
+ let ops = [];
+ for (let i = 0; i < this.pictures_.length; ++i) {
+ ops = ops.concat(this.pictures_[i].getOps());
+ }
+ return ops;
+ },
+
+ getOpTimings() {
+ const opTimings = this.pictures_[0].getOpTimings();
+ for (let i = 1; i < this.pictures_.length; ++i) {
+ const timings = this.pictures_[i].getOpTimings();
+ opTimings.cmd_times = opTimings.cmd_times.concat(timings.cmd_times);
+ opTimings.total_time += timings.total_time;
+ }
+ return opTimings;
+ },
+
+ tagOpsWithTimings(ops) {
+ const opTimings = [];
+ for (let iteration = 0; iteration < OPS_TIMING_ITERATIONS; iteration++) {
+ opTimings[iteration] = this.getOpTimings();
+ if (!opTimings[iteration] || !opTimings[iteration].cmd_times) {
+ return ops;
+ }
+ }
+
+ for (let opIndex = 0; opIndex < ops.length; opIndex++) {
+ let min = Number.MAX_VALUE;
+ for (let i = 0; i < OPS_TIMING_ITERATIONS; i++) {
+ min = Math.min(min, opTimings[i].cmd_times[opIndex]);
+ }
+ ops[opIndex].cmd_time = min;
+ }
+ return ops;
+ },
+
+ rasterize(params, rasterCompleteCallback) {
+ this.picturesAsImageData_ = [];
+ const rasterCallback = function(pictureAsImageData) {
+ this.picturesAsImageData_.push(pictureAsImageData);
+ if (this.picturesAsImageData_.length !== this.pictures_.length) {
+ return;
+ }
+
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+ canvas.width = this.layerRect.width;
+ canvas.height = this.layerRect.height;
+
+ // TODO(dsinclair): Verify these finish in the order started.
+ // Do the rasterize calls run sync or asyn? As the imageData
+ // going to be in the same order as the pictures_ list?
+ for (let i = 0; i < this.picturesAsImageData_.length; ++i) {
+ ctx.putImageData(this.picturesAsImageData_[i].imageData,
+ this.pictures_[i].layerRect.x,
+ this.pictures_[i].layerRect.y);
+ }
+ this.picturesAsImageData_ = [];
+
+ rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this,
+ ctx.getImageData(this.layerRect.x, this.layerRect.y,
+ this.layerRect.width, this.layerRect.height)));
+ }.bind(this);
+
+ for (let i = 0; i < this.pictures_.length; ++i) {
+ this.pictures_[i].rasterize(params, rasterCallback);
+ }
+ }
+ };
+
+
+ /**
+ * @constructor
+ */
+ function PictureSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ }
+
+ PictureSnapshot.HasSkiaBenchmarking = function() {
+ return tr.isExported('chrome.skiaBenchmarking');
+ };
+
+ PictureSnapshot.CanRasterize = function() {
+ if (!PictureSnapshot.HasSkiaBenchmarking()) {
+ return false;
+ }
+ if (!window.chrome.skiaBenchmarking.rasterize) {
+ return false;
+ }
+ return true;
+ };
+
+ PictureSnapshot.CanGetOps = function() {
+ if (!PictureSnapshot.HasSkiaBenchmarking()) {
+ return false;
+ }
+ if (!window.chrome.skiaBenchmarking.getOps) {
+ return false;
+ }
+ return true;
+ };
+
+ PictureSnapshot.CanGetOpTimings = function() {
+ if (!PictureSnapshot.HasSkiaBenchmarking()) {
+ return false;
+ }
+ if (!window.chrome.skiaBenchmarking.getOpTimings) {
+ return false;
+ }
+ return true;
+ };
+
+ PictureSnapshot.CanGetInfo = function() {
+ if (!PictureSnapshot.HasSkiaBenchmarking()) {
+ return false;
+ }
+ if (!window.chrome.skiaBenchmarking.getInfo) {
+ return false;
+ }
+ return true;
+ };
+
+ PictureSnapshot.HowToEnablePictureDebugging = function() {
+ if (tr.isHeadless) {
+ return 'Pictures only work in chrome';
+ }
+
+ const usualReason = [
+ 'For pictures to show up, you need to have Chrome running with ',
+ '--enable-skia-benchmarking. Please restart chrome with this flag ',
+ 'and try again.'
+ ].join('');
+
+ if (!PictureSnapshot.HasSkiaBenchmarking()) {
+ return usualReason;
+ }
+ if (!PictureSnapshot.CanRasterize()) {
+ return 'Your chrome is old: chrome.skipBenchmarking.rasterize not found';
+ }
+ if (!PictureSnapshot.CanGetOps()) {
+ return 'Your chrome is old: chrome.skiaBenchmarking.getOps not found';
+ }
+ if (!PictureSnapshot.CanGetOpTimings()) {
+ return 'Your chrome is old: ' +
+ 'chrome.skiaBenchmarking.getOpTimings not found';
+ }
+ if (!PictureSnapshot.CanGetInfo()) {
+ return 'Your chrome is old: chrome.skiaBenchmarking.getInfo not found';
+ }
+ return undefined;
+ };
+
+ PictureSnapshot.CanDebugPicture = function() {
+ return PictureSnapshot.HowToEnablePictureDebugging() === undefined;
+ };
+
+ PictureSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ preInitialize() {
+ tr.e.cc.preInitializeObject(this);
+ this.rasterResult_ = undefined;
+ },
+
+ initialize() {
+ // If we have an alias args, that means this picture was represented
+ // by an alias, and the real args is in alias.args.
+ if (this.args.alias) {
+ this.args = this.args.alias.args;
+ }
+
+ if (!this.args.params.layerRect) {
+ throw new Error('Missing layer rect');
+ }
+
+ this.layerRect_ = this.args.params.layerRect;
+ this.picture_ = new Picture(this.args.skp64, this.args.params.layerRect);
+ },
+
+ set picture(picture) {
+ this.picture_ = picture;
+ },
+
+ get canSave() {
+ return this.picture_.canSave;
+ },
+
+ get layerRect() {
+ return this.layerRect_ ? this.layerRect_ : this.picture_.layerRect;
+ },
+
+ get guid() {
+ return this.picture_.guid;
+ },
+
+ getBase64SkpData() {
+ return this.picture_.getBase64SkpData();
+ },
+
+ getOps() {
+ return this.picture_.getOps();
+ },
+
+ getOpTimings() {
+ return this.picture_.getOpTimings();
+ },
+
+ tagOpsWithTimings(ops) {
+ return this.picture_.tagOpsWithTimings(ops);
+ },
+
+ rasterize(params, rasterCompleteCallback) {
+ this.picture_.rasterize(params, rasterCompleteCallback);
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(
+ PictureSnapshot,
+ {typeNames: ['cc::Picture']});
+
+ return {
+ PictureSnapshot,
+ Picture,
+ LayeredPicture,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture_as_image_data.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture_as_image_data.html
new file mode 100644
index 00000000000..0d33fc2f70c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture_as_image_data.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ /**
+ * @constructor
+ */
+ function PictureAsImageData(picture, errorOrImageData) {
+ this.picture_ = picture;
+ if (errorOrImageData instanceof ImageData) {
+ this.error_ = undefined;
+ this.imageData_ = errorOrImageData;
+ } else {
+ this.error_ = errorOrImageData;
+ this.imageData_ = undefined;
+ }
+ }
+
+ /**
+ * Creates a new pending PictureAsImageData (no image data and no error).
+ *
+ * @return {PictureAsImageData} a new pending PictureAsImageData.
+ */
+ PictureAsImageData.Pending = function(picture) {
+ return new PictureAsImageData(picture, undefined);
+ };
+
+ PictureAsImageData.prototype = {
+ get picture() {
+ return this.picture_;
+ },
+
+ get error() {
+ return this.error_;
+ },
+
+ get imageData() {
+ return this.imageData_;
+ },
+
+ isPending() {
+ return this.error_ === undefined && this.imageData_ === undefined;
+ },
+
+ asCanvas() {
+ if (!this.imageData_) return;
+
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ canvas.width = this.imageData_.width;
+ canvas.height = this.imageData_.height;
+ ctx.putImageData(this.imageData_, 0, 0);
+ return canvas;
+ }
+ };
+
+ return {
+ PictureAsImageData,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture_test.html
new file mode 100644
index 00000000000..71b17b78389
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/picture_test.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/cc.html">
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('cc::Picture')[0];
+ const snapshot = instance.snapshots[0];
+
+ assert.instanceOf(snapshot, tr.e.cc.PictureSnapshot);
+ instance.wasDeleted(150);
+ });
+
+ test('getOps', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('cc::Picture')[0];
+ const snapshot = instance.snapshots[0];
+
+ const ops = snapshot.getOps();
+ if (!ops) return;
+ assert.strictEqual(ops.length, 142);
+
+ const op0 = ops[0];
+ assert.strictEqual(op0.cmd_string, 'Save');
+ assert.instanceOf(op0.info, Array);
+ });
+
+ function setUpFakeSkiaBenchmarking() {
+ if (tr.e.cc.PictureSnapshot.CanRasterize() &&
+ tr.e.cc.PictureSnapshot.CanGetOps()) {
+ return window.chrome;
+ }
+
+ const oldChrome = window.chrome;
+ window.chrome = {
+ skiaBenchmarking: {
+ rasterize() {},
+ getOps() {},
+ }
+ };
+ return oldChrome;
+ }
+
+ test('rasterizeZeroSize', function() {
+ if (!window) return;
+
+ const oldChrome = setUpFakeSkiaBenchmarking();
+ try {
+ const picture = new tr.e.cc.Picture(
+ '', {x: 0, y: 0, width: 0, height: 50});
+ let result;
+ picture.rasterize({}, function(data) { result = data; });
+ assert.strictEqual(result.picture, picture);
+ assert.isUndefined(result.imageData);
+ assert.isNull(result.error);
+ } finally {
+ window.chrome = oldChrome;
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/raster_task.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/raster_task.html
new file mode 100644
index 00000000000..cc506aac902
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/raster_task.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/extras/chrome/cc/tile.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const knownRasterTaskNames = [
+ 'TileManager::RunRasterTask',
+ 'RasterWorkerPoolTaskImpl::RunRasterOnThread',
+ 'RasterWorkerPoolTaskImpl::Raster',
+ 'RasterTaskImpl::Raster',
+ 'cc::RasterTask',
+ 'RasterTask'
+ ];
+
+ const knownAnalysisTaskNames = [
+ 'TileManager::RunAnalyzeTask',
+ 'RasterWorkerPoolTaskImpl::RunAnalysisOnThread',
+ 'RasterWorkerPoolTaskImpl::Analyze',
+ 'RasterTaskImpl::Analyze',
+ 'cc::AnalyzeTask',
+ 'AnalyzeTask'
+ ];
+
+ function getTileFromRasterTaskSlice(slice) {
+ if (!(isSliceDoingRasterization(slice) || isSliceDoingAnalysis(slice))) {
+ return undefined;
+ }
+
+ let tileData;
+ if (slice.args.data) {
+ tileData = slice.args.data;
+ } else {
+ tileData = slice.args.tileData;
+ }
+ if (tileData === undefined) return undefined;
+ if (tileData.tile_id) return tileData.tile_id;
+
+ const tile = tileData.tileId;
+ if (!(tile instanceof tr.e.cc.TileSnapshot)) {
+ return undefined;
+ }
+ return tileData.tileId;
+ }
+
+ function isSliceDoingRasterization(slice) {
+ return knownRasterTaskNames.includes(slice.title);
+ }
+
+ function isSliceDoingAnalysis(slice) {
+ return knownAnalysisTaskNames.includes(slice.title);
+ }
+
+ return {
+ getTileFromRasterTaskSlice,
+ isSliceDoingRasterization,
+ isSliceDoingAnalysis
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/region.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/region.html
new file mode 100644
index 00000000000..e2601dd2641
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/region.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/rect.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ /**
+ * @constructor
+ */
+ function Region() {
+ this.rects = [];
+ }
+
+ Region.fromArray = function(array) {
+ if (array.length % 4 !== 0) {
+ throw new Error('Array must consist be a multiple of 4 in length');
+ }
+
+ const r = new Region();
+ for (let i = 0; i < array.length; i += 4) {
+ r.rects.push(tr.b.math.Rect.fromXYWH(array[i], array[i + 1],
+ array[i + 2], array[i + 3]));
+ }
+ return r;
+ };
+
+ /**
+ * @return {Region} If array is undefined, returns an empty region. Otherwise
+ * returns Region.fromArray(array).
+ */
+ Region.fromArrayOrUndefined = function(array) {
+ if (array === undefined) return new Region();
+ return Region.fromArray(array);
+ };
+
+ Region.prototype = {
+ __proto__: Region.prototype,
+
+ rectIntersects(r) {
+ for (let i = 0; i < this.rects.length; i++) {
+ if (this.rects[i].intersects(r)) return true;
+ }
+ return false;
+ },
+
+ addRect(r) {
+ this.rects.push(r);
+ }
+ };
+
+ return {
+ Region,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/render_pass.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/render_pass.html
new file mode 100644
index 00000000000..ec78354ae6b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/render_pass.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/extras/chrome/cc/util.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ /**
+ * @constructor
+ */
+ function RenderPassSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ }
+
+ RenderPassSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ preInitialize() {
+ tr.e.cc.preInitializeObject(this);
+ },
+
+ initialize() {
+ tr.e.cc.moveRequiredFieldsFromArgsToToplevel(
+ this, ['quadList']);
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(
+ RenderPassSnapshot,
+ {typeName: 'cc::RenderPass'});
+
+ return {
+ RenderPassSnapshot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile.html
new file mode 100644
index 00000000000..f9c232ab974
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/extras/chrome/cc/debug_colors.html">
+<link rel="import" href="/tracing/extras/chrome/cc/util.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ /**
+ * @constructor
+ */
+ function TileSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ }
+
+ TileSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ preInitialize() {
+ tr.e.cc.preInitializeObject(this);
+ },
+
+ initialize() {
+ tr.e.cc.moveOptionalFieldsFromArgsToToplevel(
+ this, ['layerId', 'contentsScale', 'contentRect']);
+ if (this.args.managedState) {
+ this.resolution = this.args.managedState.resolution;
+ this.isSolidColor = this.args.managedState.isSolidColor;
+ this.isUsingGpuMemory = this.args.managedState.isUsingGpuMemory;
+ this.hasResource = this.args.managedState.hasResource;
+ this.scheduledPriority = this.args.scheduledPriority;
+ this.gpuMemoryUsageInBytes = this.args.gpuMemoryUsage;
+ } else {
+ this.resolution = this.args.resolution;
+ this.isSolidColor = this.args.drawInfo.isSolidColor;
+ this.isUsingGpuMemory = this.args.isUsingGpuMemory;
+ this.hasResource = this.args.hasResource;
+ this.scheduledPriority = this.args.scheduledPriority;
+ this.gpuMemoryUsageInBytes = this.args.gpuMemoryUsage;
+ }
+
+ // This check is for backward compatability. It can probably
+ // be removed once we're confident that most traces contain
+ // content_rect.
+ if (this.contentRect) {
+ this.layerRect = this.contentRect.scale(1.0 / this.contentsScale);
+ }
+
+ if (this.isSolidColor) {
+ this.type_ = tr.e.cc.tileTypes.solidColor;
+ } else if (!this.hasResource) {
+ this.type_ = tr.e.cc.tileTypes.missing;
+ } else if (this.resolution === 'HIGH_RESOLUTION') {
+ this.type_ = tr.e.cc.tileTypes.highRes;
+ } else if (this.resolution === 'LOW_RESOLUTION') {
+ this.type_ = tr.e.cc.tileTypes.lowRes;
+ } else {
+ this.type_ = tr.e.cc.tileTypes.unknown;
+ }
+ },
+
+ getTypeForLayer(layer) {
+ let type = this.type_;
+ if (type === tr.e.cc.tileTypes.unknown) {
+ if (this.contentsScale < layer.idealContentsScale) {
+ type = tr.e.cc.tileTypes.extraLowRes;
+ } else if (this.contentsScale > layer.idealContentsScale) {
+ type = tr.e.cc.tileTypes.extraHighRes;
+ }
+ }
+ return type;
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(TileSnapshot, {typeName: 'cc::Tile'});
+
+ return {
+ TileSnapshot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile_coverage_rect.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile_coverage_rect.html
new file mode 100644
index 00000000000..d1c65fa608a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile_coverage_rect.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ /**
+ * This class represents a tile (from impl side) and its final rect on the
+ * layer. Note that the rect is determined by what is needed to cover all
+ * of the layer without overlap.
+ * @constructor
+ */
+ function TileCoverageRect(rect, tile) {
+ this.geometryRect = rect;
+ this.tile = tile;
+ }
+
+ return {
+ TileCoverageRect,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile_test.html
new file mode 100644
index 00000000000..218af949862
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/tile_test.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/tile.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = Object.values(m.processes)[0];
+ const instance = p.objects.getAllInstancesNamed('cc::Tile')[0];
+ const snapshot = instance.snapshots[0];
+
+ assert.instanceOf(snapshot, tr.e.cc.TileSnapshot);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/util.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/util.html
new file mode 100644
index 00000000000..e074e68287c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/util.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+<script>
+
+'use strict';
+
+tr.exportTo('tr.e.cc', function() {
+ const convertedNameCache = {};
+ function convertNameToJSConvention(name) {
+ if (name in convertedNameCache) {
+ return convertedNameCache[name];
+ }
+
+ if (name[0] === '_' ||
+ name[name.length - 1] === '_') {
+ convertedNameCache[name] = name;
+ return name;
+ }
+
+ const words = name.split('_');
+ if (words.length === 1) {
+ convertedNameCache[name] = words[0];
+ return words[0];
+ }
+
+ for (let i = 1; i < words.length; i++) {
+ words[i] = words[i][0].toUpperCase() + words[i].substring(1);
+ }
+
+ convertedNameCache[name] = words.join('');
+ return convertedNameCache[name];
+ }
+
+ function moveRequiredFieldsFromArgsToToplevel(object, fields) {
+ for (let i = 0; i < fields.length; i++) {
+ const key = fields[i];
+ if (object.args[key] === undefined) {
+ throw Error('Expected field ' + key + ' not found in args');
+ }
+ if (object[key] !== undefined) {
+ throw Error('Field ' + key + ' already in object');
+ }
+ object[key] = object.args[key];
+ delete object.args[key];
+ }
+ }
+
+ function moveOptionalFieldsFromArgsToToplevel(object, fields) {
+ for (let i = 0; i < fields.length; i++) {
+ const key = fields[i];
+ if (object.args[key] === undefined) continue;
+ if (object[key] !== undefined) {
+ throw Error('Field ' + key + ' already in object');
+ }
+ object[key] = object.args[key];
+ delete object.args[key];
+ }
+ }
+
+ function preInitializeObject(object) {
+ preInitializeObjectInner(object.args, false);
+ }
+
+ function preInitializeObjectInner(object, hasRecursed) {
+ if (!(object instanceof Object)) return;
+
+ if (object instanceof Array) {
+ for (let i = 0; i < object.length; i++) {
+ preInitializeObjectInner(object[i], true);
+ }
+ return;
+ }
+
+ if (hasRecursed &&
+ (object instanceof tr.model.ObjectSnapshot ||
+ object instanceof tr.model.ObjectInstance)) {
+ return;
+ }
+
+ for (let key in object) {
+ const newKey = convertNameToJSConvention(key);
+ if (newKey !== key) {
+ const value = object[key];
+ delete object[key];
+ object[newKey] = value;
+ key = newKey;
+ }
+
+ // Convert objects with keys ending with Quad to tr.b.math.Quad type.
+ if (/Quad$/.test(key) && !(object[key] instanceof tr.b.math.Quad)) {
+ let q;
+ try {
+ q = tr.b.math.Quad.from8Array(object[key]);
+ } catch (e) {
+ }
+ object[key] = q;
+ continue;
+ }
+
+ // Convert objects with keys ending with Rect to tr.b.math.Rect type.
+ if (/Rect$/.test(key) && !(object[key] instanceof tr.b.math.Rect)) {
+ let r;
+ try {
+ r = tr.b.math.Rect.fromArray(object[key]);
+ } catch (e) {
+ }
+ object[key] = r;
+ }
+
+ preInitializeObjectInner(object[key], true);
+ }
+ }
+
+ return {
+ preInitializeObject,
+ convertNameToJSConvention,
+ moveRequiredFieldsFromArgsToToplevel,
+ moveOptionalFieldsFromArgsToToplevel,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/util_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/util_test.html
new file mode 100644
index 00000000000..9c0adeb0f76
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cc/util_test.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/extras/chrome/cc/util.html">
+
+<script>
+
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('nameConvert', function() {
+ assert.strictEqual(tr.e.cc.convertNameToJSConvention('_foo'), '_foo');
+ assert.strictEqual(tr.e.cc.convertNameToJSConvention('foo_'), 'foo_');
+ assert.strictEqual(tr.e.cc.convertNameToJSConvention('foo'), 'foo');
+ assert.strictEqual(tr.e.cc.convertNameToJSConvention('foo_bar'), 'fooBar');
+ assert.strictEqual(tr.e.cc.convertNameToJSConvention('foo_bar_baz'),
+ 'fooBarBaz');
+ });
+
+ test('objectConvertNested', function() {
+ const object = {
+ un_disturbed: true,
+ args: {
+ foo_bar: {
+ a_field: 7
+ }
+ }
+ };
+ const expected = {
+ un_disturbed: true,
+ args: {
+ fooBar: {
+ aField: 7
+ }
+ }
+ };
+ tr.e.cc.preInitializeObject(object);
+ assert.deepEqual(object, expected);
+ });
+
+ test('arrayConvert', function() {
+ const object = {
+ un_disturbed: true,
+ args: [
+ {foo_bar: 7},
+ {foo_bar: 8}
+ ]
+ };
+ const expected = {
+ un_disturbed: true,
+ args: [
+ {fooBar: 7},
+ {fooBar: 8}
+ ]
+ };
+ tr.e.cc.preInitializeObject(object);
+ assert.deepEqual(object, expected);
+ });
+
+ test('quadCoversion', function() {
+ const object = {
+ args: {
+ some_quad: [1, 2, 3, 4, 5, 6, 7, 8]
+ }
+ };
+ tr.e.cc.preInitializeObject(object);
+ assert.instanceOf(object.args.someQuad, tr.b.math.Quad);
+ });
+
+ test('quadConversionNested', function() {
+ const object = {
+ args: {
+ nested_field: {
+ a_quad: [1, 2, 3, 4, 5, 6, 7, 8]
+ },
+ non_nested_quad: [1, 2, 3, 4, 5, 6, 7, 8]
+ }
+ };
+ tr.e.cc.preInitializeObject(object);
+ assert.instanceOf(object.args.nestedField.aQuad, tr.b.math.Quad);
+ assert.instanceOf(object.args.nonNestedQuad, tr.b.math.Quad);
+ });
+
+ test('rectCoversion', function() {
+ const object = {
+ args: {
+ some_rect: [1, 2, 3, 4]
+ }
+ };
+ tr.e.cc.preInitializeObject(object);
+ assert.instanceOf(object.args.someRect, tr.b.math.Rect);
+ });
+
+ test('rectCoversionNested', function() {
+ const object = {
+ args: {
+ nested_field: {
+ a_rect: [1, 2, 3, 4]
+ },
+ non_nested_rect: [1, 2, 3, 4]
+ }
+ };
+ tr.e.cc.preInitializeObject(object);
+ assert.instanceOf(object.args.nestedField.aRect, tr.b.math.Rect);
+ assert.instanceOf(object.args.nonNestedRect, tr.b.math.Rect);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html
new file mode 100644
index 00000000000..a786c061bf9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/core/auditor.html">
+<link rel="import"
+ href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import"
+ href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/model/constants.html">
+<link rel="import" href="/tracing/model/event_info.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Base class for trace data Auditors.
+ */
+tr.exportTo('tr.e.audits', function() {
+ const Auditor = tr.c.Auditor;
+
+ /**
+ * Auditor for Chrome-specific traces.
+ * @constructor
+ */
+ function ChromeAuditor(model) {
+ Auditor.call(this, model);
+
+ const modelHelper = this.model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (modelHelper && modelHelper.browserHelper) {
+ // Must be a browserHelper in order to do audits.
+ this.modelHelper = modelHelper;
+ } else {
+ this.modelHelper = undefined;
+ }
+ }
+
+ ChromeAuditor.prototype = {
+ __proto__: Auditor.prototype,
+
+ runAnnotate() {
+ if (!this.modelHelper) return;
+
+ for (const pid in this.modelHelper.rendererHelpers) {
+ const rendererHelper = this.modelHelper.rendererHelpers[pid];
+
+ if (rendererHelper.isChromeTracingUI) {
+ rendererHelper.process.important = false;
+ }
+ }
+ },
+
+ /**
+ * Called by import to install userFriendlyCategoryDriver.
+ */
+ installUserFriendlyCategoryDriverIfNeeded() {
+ this.model.addUserFriendlyCategoryDriver(
+ tr.e.chrome.ChromeUserFriendlyCategoryDriver);
+ },
+
+ runAudit() {
+ if (!this.modelHelper) return;
+
+ this.model.replacePIDRefsInPatchups(
+ tr.model.BROWSER_PROCESS_PID_REF,
+ this.modelHelper.browserProcess.pid);
+ this.model.applyObjectRefPatchups();
+ }
+ };
+
+ Auditor.register(ChromeAuditor);
+
+ return {
+ ChromeAuditor,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html
new file mode 100644
index 00000000000..5947cfb35b9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_auditor_test.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_auditor.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/scoped_id.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ function createMainProcesses(m) {
+ m.browserProcess = m.getOrCreateProcess(1);
+ m.browserMain = m.browserProcess.getOrCreateThread(2);
+ m.browserMain.name = 'CrBrowserMain';
+
+ m.renderer1 = m.getOrCreateProcess(3);
+ m.renderer1Main = m.renderer1.getOrCreateThread(4);
+ m.renderer1Main.name = 'CrRendererMain';
+
+ m.renderer1Compositor = m.renderer1.getOrCreateThread(4);
+ m.renderer1Compositor.name = 'Compositor';
+ }
+
+ function newInputLatencyEvent(tsStart, tsEnd, opt_args) {
+ const e = new tr.model.AsyncSlice(
+ 'benchmark', 'InputLatency',
+ ColorScheme.getColorIdForGeneralPurposeString('InputLatency'),
+ tsStart, opt_args);
+ e.duration = tsEnd - tsStart;
+ return e;
+ }
+
+ function newImplRenderingStatsEvent(ts, opt_args) {
+ const e = new tr.model.ThreadSlice(
+ 'benchmark', 'BenchmarkInstrumentation::ImplThreadRenderingStats',
+ ColorScheme.getColorIdForGeneralPurposeString('x'),
+ ts, opt_args, 0);
+ return e;
+ }
+
+ test('simple', function() {
+ tr.c.TestUtils.newModelWithAuditor(function(m) {
+ createMainProcesses(m);
+ const bAsyncSlices = m.browserMain.asyncSliceGroup;
+ bAsyncSlices.push(newInputLatencyEvent(100, 130));
+ bAsyncSlices.push(newInputLatencyEvent(116, 150));
+ bAsyncSlices.push(newInputLatencyEvent(133, 166));
+ bAsyncSlices.push(newInputLatencyEvent(150, 183));
+ bAsyncSlices.push(newInputLatencyEvent(166, 200));
+ bAsyncSlices.push(newInputLatencyEvent(183, 216));
+
+ const rm1Slices = m.renderer1Compositor.sliceGroup;
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(113));
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(130));
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(147));
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(163));
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(180));
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(197));
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(213));
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(230));
+ rm1Slices.pushSlice(newImplRenderingStatsEvent(247));
+ }, tr.e.audits.ChromeAuditor);
+ });
+
+ test('refsToBrowser', function() {
+ const events = [
+ // An object created and snapshotted in the browser process.
+ {ts: 1000, pid: 1, tid: 2, ph: 'N', cat: 'c', id: '0x1000', name: 'a',
+ args: {}},
+ {ts: 1100, pid: 1, tid: 2, ph: 'O', cat: 'c', id: '0x1000', name: 'a',
+ args: {snapshot: {foo: 12345}}},
+ {ts: 1300, pid: 1, tid: 2, ph: 'D', cat: 'c', id: '0x1000', name: 'a',
+ args: {}},
+
+ // A reference to the object in the browser from the renderer process.
+ {ts: 1200, pid: 3, tid: 4, ph: 'X', cat: 'c', name: 'b', dur: 100,
+ args: {bar: {pid_ref: -1, id_ref: '0x1000'}}}
+ ];
+
+ const m = tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false,
+ pruneEmptyContainers: false,
+ customizeModelCallback: createMainProcesses,
+ auditorConstructors: [tr.e.audits.ChromeAuditor]
+ });
+
+ const browserObject = m.browserProcess.objects.getObjectInstanceAt(
+ new tr.model.ScopedId('ptr', '0x1000'), 1.2);
+ assert.isDefined(browserObject);
+ const foo = browserObject.getSnapshotAt(1.2);
+ assert.isDefined(foo);
+
+ assert.strictEqual(m.renderer1Main.sliceGroup.slices.length, 1);
+ const slice = m.renderer1Main.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.args.bar, foo);
+ });
+
+ test('filterTracingUI', function() {
+ const m = tr.c.TestUtils.newModelWithAuditor(function(m) {
+ m.browserProcess = m.getOrCreateProcess(1);
+ m.browserMain = m.browserProcess.getOrCreateThread(2);
+ m.browserMain.name = 'CrBrowserMain';
+
+ m.renderer1 = m.getOrCreateProcess(3);
+ m.renderer1.labels = ['https://google.com'];
+ m.renderer1Main = m.renderer1.getOrCreateThread(4);
+ m.renderer1Main.name = 'CrRendererMain';
+
+ m.renderer2 = m.getOrCreateProcess(5);
+ m.renderer2.labels = ['chrome://tracing'];
+ m.renderer2Main = m.renderer2.getOrCreateThread(6);
+ m.renderer2Main.name = 'CrRendererMain';
+ }, tr.e.audits.ChromeAuditor);
+
+ assert.isTrue(m.renderer1.important);
+ assert.isFalse(m.renderer2.important);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_processes.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_processes.html
new file mode 100644
index 00000000000..0456b29126e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_processes.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/fixed_color_scheme.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.chrome.chrome_processes', function() {
+ const CHROME_PROCESS_NAMES = {
+ BROWSER: 'browser_process',
+ RENDERER: 'renderer_processes', // Intentionally plural.
+ ALL: 'all_processes',
+ GPU: 'gpu_process',
+ PPAPI: 'ppapi_process',
+ UNKNOWN: 'unknown_processes',
+ };
+
+ const PROCESS_COLOR_SCHEME_NAME = 'ChromeProcessNames';
+ const PROCESS_COLOR_SCHEME =
+ tr.b.FixedColorScheme.fromNames(Object.values(CHROME_PROCESS_NAMES));
+
+ tr.b.FixedColorSchemeRegistry.register(() => PROCESS_COLOR_SCHEME, {
+ name: PROCESS_COLOR_SCHEME_NAME,
+ });
+
+ /**
+ * Converts name to lower case and replaces spaces with underscores.
+ */
+ function canonicalizeName(name) {
+ return name.toLowerCase().replace(' ', '_');
+ }
+
+ /**
+ * Convert raw process name to canonical process names used in catapult.
+ *
+ * Examples:
+ * browser -> CHROME_PROCESS_NAME.BROWSER
+ * renderer -> CHROME_PROCESS_NAME.RENDERER
+ */
+ function canonicalizeProcessName(rawProcessName) {
+ if (!rawProcessName) return CHROME_PROCESS_NAMES.UNKNOWN;
+
+ const baseCanonicalName = canonicalizeName(rawProcessName);
+ switch (baseCanonicalName) {
+ case 'renderer': return CHROME_PROCESS_NAMES.RENDERER;
+ case 'browser': return CHROME_PROCESS_NAMES.BROWSER;
+ }
+
+ if (Object.values(CHROME_PROCESS_NAMES).includes(baseCanonicalName)) {
+ return baseCanonicalName;
+ }
+
+ return CHROME_PROCESS_NAMES.UNKNOWN;
+ }
+
+ return {
+ CHROME_PROCESS_NAMES,
+ PROCESS_COLOR_SCHEME,
+ PROCESS_COLOR_SCHEME_NAME,
+ canonicalizeName,
+ canonicalizeProcessName,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html
new file mode 100644
index 00000000000..69128010fa9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_test_utils.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Base class for trace data Auditors.
+ */
+tr.exportTo('tr.e.chrome', function() {
+ function ChromeTestUtils() {
+ }
+
+ ChromeTestUtils.newChromeModel = function(customizeModelCallback) {
+ return tr.c.TestUtils.newModel(function(model) {
+ model.browserProcess = model.getOrCreateProcess(1);
+ model.browserMain = model.browserProcess.getOrCreateThread(2);
+ model.browserMain.name = 'CrBrowserMain';
+
+ model.rendererProcess = model.getOrCreateProcess(2);
+ model.rendererMain = model.rendererProcess.getOrCreateThread(3);
+ model.rendererMain.name = 'CrRendererMain';
+
+ model.rendererCompositor = model.rendererProcess.getOrCreateThread(4);
+ model.rendererCompositor.name = 'Compositor';
+
+ model.rasterWorker1 = model.rendererProcess.getOrCreateThread(5);
+ model.rasterWorker1.name = 'CompositorTileWorker1';
+
+ customizeModelCallback(model);
+ });
+ };
+
+ ChromeTestUtils.addEvent = function(thread, dict) {
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ thread.asyncSliceGroup.push(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addNavigationStartEvent = function(model, dict) {
+ dict.title = 'NavigationTiming navigationStart';
+ const event = tr.c.TestUtils.newInstantEvent(dict);
+ model.instantEvents.push(event);
+ return event;
+ };
+
+ ChromeTestUtils.addFirstContentfulPaintEvent = function(model, dict) {
+ dict.title = 'firstContentfulPaint';
+ const event = tr.c.TestUtils.newInstantEvent(dict);
+ model.instantEvents.push(event);
+ return event;
+ };
+
+ ChromeTestUtils.addInputEvent = function(model, typeName, dict) {
+ dict.title = 'InputLatency::' + typeName;
+ dict.isTopLevel = (dict.isTopLevel === undefined);
+ dict.startThread = model.browserMain;
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ model.browserMain.asyncSliceGroup.push(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addFlingAnimationEvent = function(model, dict) {
+ dict.title = 'InputHandlerProxy::HandleGestureFling::started';
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ model.rendererCompositor.asyncSliceGroup.push(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addRenderingEvent = function(model, dict) {
+ dict.title = dict.title || 'DummyEvent';
+ dict.type = tr.model.ThreadSlice;
+ const slice = tr.c.TestUtils.newSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addFrameEvent = function(model, dict) {
+ dict.title = tr.model.helpers.IMPL_RENDERING_STATS;
+ dict.type = tr.model.ThreadSlice;
+ const slice = tr.c.TestUtils.newSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addLoadingEvent = function(model, dict) {
+ dict.title = 'WebContentsImpl Loading';
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ model.rendererMain.asyncSliceGroup.push(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addNetworkEvent = function(model, dict) {
+ dict.cat = 'netlog';
+ dict.title = 'Generic Network event';
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ model.browserMain.asyncSliceGroup.push(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addCommitLoadEvent = function(model, dict) {
+ dict.title = 'RenderFrameImpl::didCommitProvisionalLoad';
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addCreateChildFrameEvent = function(model, dict) {
+ dict.title = 'RenderFrameImpl::createChildFrame';
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addStartProvisionalLoadEvent = function(model, dict) {
+ dict.title = 'RenderFrameImpl::didStartProvisionalLoad';
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addFailProvisionalLoadEvent = function(model, dict) {
+ dict.title = 'RenderFrameImpl::didFailProvisionalLoad';
+ const slice = tr.c.TestUtils.newAsyncSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addFinishLoadEvent = function(model, dict) {
+ dict.title = 'RenderFrameImpl::didFinishLoad';
+ const slice = tr.c.TestUtils.newSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addLoadFinishedEvent = function(model, dict) {
+ dict.title = 'LoadFinished';
+ const slice = tr.c.TestUtils.newSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ ChromeTestUtils.addCreateThreadsEvent = function(model, dict) {
+ dict.title = 'BrowserMainLoop::CreateThreads';
+ const slice = tr.c.TestUtils.newSliceEx(dict);
+ model.rendererMain.sliceGroup.pushSlice(slice);
+ return slice;
+ };
+
+ return {
+ ChromeTestUtils,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html
new file mode 100644
index 00000000000..d81818658de
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver.html
@@ -0,0 +1,261 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/sinebow_color_generator.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.chrome', function() {
+ const SAME_AS_PARENT = 'same-as-parent';
+
+ const TITLES_FOR_USER_FRIENDLY_CATEGORY = {
+ composite: [
+ 'CompositingInputsUpdater::update',
+ 'ThreadProxy::SetNeedsUpdateLayers',
+ 'LayerTreeHost::DoUpdateLayers',
+ 'LayerTreeHost::UpdateLayers::BuildPropertyTrees',
+ 'LocalFrameView::pushPaintArtifactToCompositor',
+ 'LocalFrameView::updateCompositedSelectionIfNeeded',
+ 'LocalFrameView::RunCompositingLifecyclePhase',
+ 'UpdateLayerTree',
+ ],
+
+ gc: [
+ 'minorGC',
+ 'majorGC',
+ 'MajorGC',
+ 'MinorGC',
+ 'V8.GCScavenger',
+ 'V8.GCIncrementalMarking',
+ 'V8.GCIdleNotification',
+ 'V8.GCContext',
+ 'V8.GCCompactor',
+ 'V8GCController::traceDOMWrappers',
+ ],
+
+ iframe_creation: [
+ 'WebLocalFrameImpl::createChildframe',
+ ],
+
+ imageDecode: [
+ 'Decode Image',
+ 'ImageFrameGenerator::decode',
+ 'ImageFrameGenerator::decodeAndScale',
+ 'ImageResourceContent::updateImage',
+ ],
+
+ input: [
+ 'HitTest',
+ 'ScrollableArea::scrollPositionChanged',
+ 'EventHandler::handleMouseMoveEvent',
+ ],
+
+ layout: [
+ 'IntersectionObserverController::computeTrackedIntersectionObservations',
+ 'LocalFrameView::invalidateTree',
+ 'LocalFrameView::layout',
+ 'LocalFrameView::performLayout',
+ 'LocalFrameView::performPostLayoutTasks',
+ 'LocalFrameView::performPreLayoutTasks',
+ 'LocalFrameView::RunStyleAndLayoutCompositingPhases',
+ 'Layout',
+ 'PaintLayer::updateLayerPositionsAfterLayout',
+ 'ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities',
+ 'WebViewImpl::updateAllLifecyclePhases',
+ 'WebViewImpl::beginFrame',
+ ],
+
+ parseHTML: [
+ 'BackgroundHTMLParser::pumpTokenizer',
+ 'BackgroundHTMLParser::sendTokensToMainThread',
+ 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser',
+ 'HTMLDocumentParser::documentElementAvailable',
+ 'HTMLDocumentParser::notifyPendingTokenizedChunks',
+ 'HTMLDocumentParser::processParsedChunkFromBackgroundParser',
+ 'HTMLDocumentParser::processTokenizedChunkFromBackgroundParser',
+ 'ParseHTML',
+ ],
+
+ raster: [
+ 'DisplayListRasterSource::PerformSolidColorAnalysis',
+ 'Picture::Raster',
+ 'RasterBufferImpl::Playback',
+ 'RasterTask',
+ 'RasterizerTaskImpl::RunOnWorkerThread',
+ 'SkCanvas::drawImageRect()',
+ 'SkCanvas::drawPicture()',
+ 'SkCanvas::drawTextBlob()',
+ 'TileTaskWorkerPool::PlaybackToMemory',
+ ],
+
+ record: [
+ 'Canvas2DLayerBridge::flushRecordingOnly',
+ 'CompositingInputsUpdater::update',
+ 'CompositingRequirementsUpdater::updateRecursive',
+ 'ContentLayerDelegate::paintContents',
+ 'DisplayItemList::Finalize',
+ 'LocalFrameView::RunPaintLifecyclePhase',
+ 'LocalFrameView::RunPrePaintLifecyclePhase',
+ 'Paint',
+ 'PaintController::commitNewDisplayItems',
+ 'PaintLayerCompositor::updateIfNeededRecursive',
+ 'Picture::Record',
+ 'PictureLayer::Update',
+ ],
+
+ style: [
+ 'CSSParserImpl::parseStyleSheet.parse',
+ 'CSSParserImpl::parseStyleSheet.tokenize',
+ 'Document::rebuildLayoutTree',
+ 'Document::recalcStyle',
+ 'Document::updateActiveStyle',
+ 'Document::updateStyle',
+ 'Document::updateStyleInvalidationIfNeeded',
+ 'LocalFrameView::updateStyleAndLayoutIfNeededRecursive',
+ 'ParseAuthorStyleSheet',
+ 'RuleSet::addRulesFromSheet',
+ 'StyleElement::processStyleSheet',
+ 'StyleEngine::createResolver',
+ 'StyleEngine::updateActiveStyleSheets',
+ 'StyleSheetContents::parseAuthorStyleSheet',
+ 'UpdateLayoutTree',
+ ],
+
+ script_parse_and_compile: [
+ 'V8.CompileFullCode',
+ 'V8.NewContext',
+ 'V8.Parse',
+ 'V8.ParseLazy',
+ 'V8.RecompileSynchronous',
+ 'V8.ScriptCompiler',
+ 'v8.compile',
+ 'v8.parseOnBackground',
+ ],
+
+ script_execute: [
+ 'EvaluateScript',
+ 'FunctionCall',
+ 'HTMLParserScriptRunner ExecuteScript',
+ 'V8.Execute',
+ 'V8.RunMicrotasks',
+ 'V8.Task',
+ 'WindowProxy::initialize',
+ 'v8.callFunction',
+ 'v8.run',
+ ],
+
+ resource_loading: [
+ 'RenderFrameImpl::didFinishDocumentLoad',
+ 'RenderFrameImpl::didFinishLoad',
+ 'Resource::appendData',
+ 'ResourceDispatcher::OnReceivedData',
+ 'ResourceDispatcher::OnReceivedResponse',
+ 'ResourceDispatcher::OnRequestComplete',
+ 'ResourceFetcher::requestResource',
+ 'WebURLLoaderImpl::Context::Cancel',
+ 'WebURLLoaderImpl::Context::OnCompletedRequest',
+ 'WebURLLoaderImpl::Context::OnReceivedData',
+ 'WebURLLoaderImpl::Context::OnReceivedRedirect',
+ 'WebURLLoaderImpl::Context::OnReceivedResponse',
+ 'WebURLLoaderImpl::Context::Start',
+ 'WebURLLoaderImpl::loadAsynchronously',
+ 'WebURLLoaderImpl::loadSynchronously',
+ 'content::mojom::URLLoaderClient',
+ ],
+
+ // Where do these go?
+ renderer_misc: [
+ 'DecodeFont',
+ 'ThreadState::completeSweep', // blink_gc
+ ],
+
+ // TODO(fmeawad): https://github.com/catapult-project/catapult/issues/2572
+ v8_runtime: [
+ // Dynamically populated.
+ ],
+
+ [SAME_AS_PARENT]: [
+ 'SyncChannel::Send',
+ ]
+ };
+
+ const COLOR_FOR_USER_FRIENDLY_CATEGORY = new tr.b.SinebowColorGenerator();
+ const USER_FRIENDLY_CATEGORY_FOR_TITLE = new Map();
+
+ for (const category in TITLES_FOR_USER_FRIENDLY_CATEGORY) {
+ TITLES_FOR_USER_FRIENDLY_CATEGORY[category].forEach(function(title) {
+ USER_FRIENDLY_CATEGORY_FOR_TITLE.set(title, category);
+ });
+ }
+
+ // keys: event.category part
+ // values: user friendly category
+ const USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY = {
+ netlog: 'net',
+ overhead: 'overhead',
+ startup: 'startup',
+ gpu: 'gpu',
+ };
+
+ function ChromeUserFriendlyCategoryDriver() {
+ }
+
+ ChromeUserFriendlyCategoryDriver.fromEvent = function(event) {
+ let userFriendlyCategory =
+ USER_FRIENDLY_CATEGORY_FOR_TITLE.get(event.title);
+ if (userFriendlyCategory) {
+ if (userFriendlyCategory === SAME_AS_PARENT) {
+ if (event.parentSlice) {
+ return ChromeUserFriendlyCategoryDriver.fromEvent(event.parentSlice);
+ }
+ } else {
+ return userFriendlyCategory;
+ }
+ }
+
+ const eventCategoryParts = tr.b.getCategoryParts(event.category);
+ for (let i = 0; i < eventCategoryParts.length; ++i) {
+ const eventCategory = eventCategoryParts[i];
+ userFriendlyCategory = USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY[
+ eventCategory];
+ if (userFriendlyCategory) {
+ return userFriendlyCategory;
+ }
+ }
+
+ return 'other';
+ };
+
+ ChromeUserFriendlyCategoryDriver.getColor = function(ufc) {
+ return COLOR_FOR_USER_FRIENDLY_CATEGORY.colorForKey(ufc);
+ };
+
+ ChromeUserFriendlyCategoryDriver.ALL_TITLES = ['other'];
+ for (const category in TITLES_FOR_USER_FRIENDLY_CATEGORY) {
+ if (category === SAME_AS_PARENT) continue;
+ ChromeUserFriendlyCategoryDriver.ALL_TITLES.push(category);
+ }
+ for (const category of Object.values(
+ USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY)) {
+ ChromeUserFriendlyCategoryDriver.ALL_TITLES.push(category);
+ }
+ ChromeUserFriendlyCategoryDriver.ALL_TITLES.sort();
+
+ // Prime the color generator by iterating through all UFCs in alphabetical
+ // order.
+ for (const category of ChromeUserFriendlyCategoryDriver.ALL_TITLES) {
+ ChromeUserFriendlyCategoryDriver.getColor(category);
+ }
+
+ return {
+ ChromeUserFriendlyCategoryDriver,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html
new file mode 100644
index 00000000000..5251a7d2edc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/chrome_user_friendly_category_driver_test.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import"
+ href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/model/event_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ufcFromEvent = tr.e.chrome.ChromeUserFriendlyCategoryDriver.fromEvent;
+
+ test('userFriendlyCategory', function() {
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'LocalFrameView::layout',
+ category: 'cat'
+ }), 'layout');
+
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'V8.Execute',
+ category: 'cat'
+ }), 'script_execute');
+
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'Paint',
+ category: 'cat'
+ }), 'record');
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'Document::updateStyle',
+ category: 'cat'
+ }), 'style');
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser',
+ category: 'cat'
+ }), 'parseHTML');
+
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'constructor',
+ category: 'cat'
+ }), 'other');
+ });
+
+ test('ufcFromTraceCategory', function() {
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'a',
+ category: 'netlog'
+ }), 'net');
+
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'a',
+ category: 'foobar,overhead'
+ }), 'overhead');
+
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'a',
+ category: 'startup'
+ }), 'startup');
+ });
+
+ test('ufcOther', function() {
+ assert.strictEqual(ufcFromEvent({
+ guid: tr.b.GUID.allocateSimple(),
+ title: 'a',
+ category: 'other'
+ }), 'other');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time.html
new file mode 100644
index 00000000000..24468cb10e0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time.html
@@ -0,0 +1,164 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/multi_dimensional_view.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_processes.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_renderer_helper.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.chrome', function() {
+ class CpuTime {
+ /**
+ * Returns two level map of rail stage to initiator type to set of bounds of
+ * associated segments, intersected with |rangeOfInterest|.
+ *
+ * For each rail stage, we additionally have a key 'all_initiators' that
+ * returns all the segment bounds associated with that rail stage across all
+ * initiator types. For completeness, there is an additional rail stage
+ * 'all_stages' that has all the segment bounds across all rail stages.
+ *
+ * If a segment is not contained within |rangeOfInterest| it is not
+ * included.
+ *
+ * There is a unique segment bound for each segment in the map. For example,
+ * assume
+ * - |segmentA| is associated with both Click Response and Scroll Animation
+ * - |bound1| is the interesting bound of |segmentA| in Response -> Click
+ * set.
+ * - |bound2| is the interesting bound of |segmentA| in Animation -> Scroll
+ * set.
+ * Then bound1 === bound2. These segment bounds can therefore be used as
+ * keys in a map to represent the segment.
+ *
+ * Example return value (all bounds are intersected with |rangeOfInterest|):
+ *
+ * {
+ * 'Animation': {
+ * 'CSS': {Segment bounds for CSS Animation},
+ * 'Video': {Segment bounds for Video Animation},
+ * ...
+ * 'all_initiators': {All Animation segment bounds}
+ * },
+ * 'Response': {
+ * 'Click': {Segment bounds for Click Response},
+ * 'Scroll': {Segment bounds for Scroll Response},
+ * ...
+ * 'all_initiators': {All Response segment bounds}
+ * },
+ * ...
+ * 'all_stages': {
+ * 'all_initiators': {All segment bounds}
+ * }
+ * }
+ *
+ * @param {!Array.<!tr.model.um.Segment>} segments
+ * @param {!Array.<!tr.b.math.Range>} rangeOfInterest
+ * @returns {!Map.<string, Map.<string, Set.<!tr.b.math.Range>>}
+ */
+ static getStageToInitiatorToSegmentBounds(segments, rangeOfInterest) {
+ const stageToInitiatorToRanges = new Map();
+ stageToInitiatorToRanges.set('all_stages',
+ new Map([['all_initiators', new Set()]]));
+ const allRanges =
+ stageToInitiatorToRanges.get('all_stages').get('all_initiators');
+
+ for (const segment of segments) {
+ if (!rangeOfInterest.intersectsRangeInclusive(segment.range)) continue;
+ const intersectingRange =
+ rangeOfInterest.findIntersection(segment.range);
+ allRanges.add(intersectingRange);
+
+ for (const expectation of segment.expectations) {
+ const stageTitle = expectation.stageTitle;
+ if (!stageToInitiatorToRanges.has(stageTitle)) {
+ stageToInitiatorToRanges.set(stageTitle,
+ new Map([['all_initiators', new Set()]]));
+ }
+
+ const initiatorToRanges = stageToInitiatorToRanges.get(stageTitle);
+ initiatorToRanges.get('all_initiators').add(intersectingRange);
+
+ const initiatorType = expectation.initiatorType;
+ if (initiatorType) {
+ if (!initiatorToRanges.has(initiatorType)) {
+ initiatorToRanges.set(initiatorType, new Set());
+ }
+ initiatorToRanges.get(initiatorType).add(intersectingRange);
+ }
+ }
+ }
+ return stageToInitiatorToRanges;
+ }
+
+ /**
+ * Returns the root node of a MultiDimensionalView in TopDownTreeView for
+ * cpu time.
+ *
+ * The returned tree view is three dimensional (processType, threadType, and
+ * railStage + initiator). Rail stage and initiator are not separate
+ * dimensions because they are not independent - there is no such thing as
+ * CSS Response or Scroll Load.
+ *
+ * Each node in the tree view contains two values - cpuUsage and cpuTotal.
+ *
+ * See cpu_time_multidimensinoal_view.md for more details about the returned
+ * multidimensional view.
+ *
+ * @param {!tr.Model} model
+ * @param {!tr.b.math.Range} rangeOfInterest
+ * @returns {!tr.b.MultiDimensionalViewNode}
+ */
+ static constructMultiDimensionalView(model, rangeOfInterest) {
+ const mdvBuilder = new tr.b.MultiDimensionalViewBuilder(
+ 3 /* dimensions (process, thread and rail stage / initiator) */,
+ 2 /* valueCount (cpuUsage and cpuTotal) */);
+
+ const stageToInitiatorToRanges =
+ CpuTime.getStageToInitiatorToSegmentBounds(
+ model.userModel.segments, rangeOfInterest);
+
+ const allSegmentBoundsInRange =
+ stageToInitiatorToRanges.get('all_stages').get('all_initiators');
+
+ for (const [pid, process] of Object.entries(model.processes)) {
+ const processType =
+ tr.e.chrome.chrome_processes.canonicalizeProcessName(process.name);
+ for (const [tid, thread] of Object.entries(process.threads)) {
+ // Cache cpuTime for each segment bound.
+ const rangeToCpuTime = new Map();
+ for (const range of allSegmentBoundsInRange) {
+ rangeToCpuTime.set(range, thread.getCpuTimeForRange(range));
+ }
+
+ for (const [stage, initiatorToRanges] of stageToInitiatorToRanges) {
+ for (const [initiator, ranges] of initiatorToRanges) {
+ const cpuTime = tr.b.math.Statistics.sum(ranges,
+ range => rangeToCpuTime.get(range));
+ const duration = tr.b.math.Statistics.sum(ranges,
+ range => range.duration);
+ const cpuTimePerSecond = cpuTime / duration;
+ mdvBuilder.addPath(
+ [[processType], [thread.type], [stage, initiator]],
+ [cpuTimePerSecond, cpuTime],
+ tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL);
+ }
+ }
+ }
+ }
+
+ return mdvBuilder.buildTopDownTreeView();
+ }
+ }
+
+ return {
+ CpuTime,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_multidimensional_view.md b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_multidimensional_view.md
new file mode 100644
index 00000000000..dcc646c3f9a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_multidimensional_view.md
@@ -0,0 +1,79 @@
+<!-- Copyright 2017 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+# CPU Time MultiDimensionalView Explainer
+
+This document explains the MultiDimensionalView returned by `constructMultiDimensionalView` in `cpuTime.html`.
+
+The returned MultiDimensionalView is in TopDownTreeView mode. It is three
+dimensional (processType, threadType, and railStage + initiator). Rail stage and
+initiator are not separate dimensions because they are not independent - there
+is no such thing as CSS Response or Scroll Load.
+
+Each node in the tree view contains two values - cpuUsage and cpuTotal.
+
+When talking about multidimensional tree views, a useful abstration is "path",
+which uniquely determines a node in the tree: A path is a 3 element array, and
+each of these three elements is a possibly empty array of strings. Here is an
+example path:
+```
+[ ['browser_process'], ['CrBrowserMain'], ['Animation', 'CSS'] ]
+ Dimension 1 Dimension 2 Dimension 3
+```
+
+We can arrive at the node denoted by this path in many different ways starting
+from the root node, so this path is not to be confused with the graph theoretic
+notion of path. Here is one of the ways to reach the node (we show the
+intermediate paths during the traversal inline):
+
+```javascript
+const node = treeRoot // [[], [], []]
+ .children[0] // access children along first dimension
+ .get('browser_process') // [['browser_process'], [], []]
+ .children[2] // access children along third dimension
+ .get('Animation') // [['browser_process'], [], ['Animation']]
+ .children[1] // Access children along second dimension
+ .get('CrBrowserMain') // [['browser_process'], ['CrBrowserMain'], ['Animation']]
+ .children[2] // Go further down along third dimension
+ .get('CSS') // [['browser_process'], ['CrBrowserMain'], ['Animation', 'CSS']]
+```
+Now node.values contains the cpu time data for the browser main thread during
+the CSS Animation stage:
+- `node.values[0]` is `cpuUsage` - cpu time over per unit of wall clock time
+- `node.values[1]` is `cpuTotal` - total miliseconds of used cpu time
+
+The path for the node that hold data for all threads of renderer process
+during scroll response expectations is `[['renderer_process'], [], ['Response', 'Scroll']]`.
+
+As we can see, we simply have an empty array for the second dimension. This
+works similarly if we want to get data for all processes for a particular
+thread.
+
+However, if we want to access data for all rail stages and all initiator
+types, we have to use the special rail stage `all_stages`, and initiator
+type `all_initiators`. For example, to get cpu data during all Response
+stages for all processes and threads, we use the node at path
+ `[[], [], ['Response', 'all_initiators']]`
+
+To get cpu data for all rail stages for ChildIOThread, we use the path
+ `[[], ['ChildIOThread'], ['all_stages', 'all_initiators']]`
+
+This is because the tree view automatically aggregates cpu time
+data along each dimension by summing values on the children nodes. For
+aggregating rail stages and initiator types, summing is not the right thing
+to do since
+
+ 1. User Expectations can overlap (for example, one tab can go through a
+ Video Animation while another tab is concurrently going through a CSS
+ Animation - it's worth noting that user expectations are not scoped to a
+ tab.)
+
+ 2. Different rail stages have different durations (for example, if we
+ have 200ms of Video Animation with 50% cpuUsage, and 500ms of CSS
+ Animation with 60% cpuUage, cpuUsage for all Animations is clearly not
+ 110%.)
+
+We therefore more manually do the appropriate aggregations and store the
+data in `all_stages` and `all_initiators` nodes.
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_test.html
new file mode 100644
index 00000000000..606463737ce
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_test.html
@@ -0,0 +1,1503 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cpu_time.html">
+<link rel="import" href="/tracing/extras/chrome/cpu_time_test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const getStageToInitiatorToSegmentBounds =
+ tr.e.chrome.CpuTime.getStageToInitiatorToSegmentBounds;
+
+ const INITIATOR_TYPE = tr.model.um.INITIATOR_TYPE;
+
+ const CHROME_PROCESS_NAMES =
+ tr.e.chrome.chrome_processes.CHROME_PROCESS_NAMES;
+
+ const constructMultiDimensionalView =
+ tr.e.chrome.CpuTime.constructMultiDimensionalView;
+
+ const buildModelFromSpec = tr.e.chrome.cpuTimeTestUtils.buildModelFromSpec;
+
+ test('getStageToInitiatorToSegmentBounds', () => {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ // This is needed for a model to have segments.
+ thread.name = 'CrBrowserMain';
+
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, INITIATOR_TYPE.CSS,
+ 100, // start time.
+ 300 // duration.
+ ));
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, INITIATOR_TYPE.VIDEO, 300, 100));
+ model.userModel.expectations.push(new tr.model.um.ResponseExpectation(
+ model, INITIATOR_TYPE.SCROLL, 400, 200));
+ });
+
+ const segments = model.userModel.segments;
+
+ const map = getStageToInitiatorToSegmentBounds(
+ model.userModel.segments, model.bounds);
+
+ // Ignoring Idle Expectations, we have the following segments:
+ // [100, 300]: CSS Animation
+ // [300, 400]: CSS Animation, Video Animation
+ // [400, 600]: Scroll Response
+ const allSegments = [...map.get('all_stages').get('all_initiators')];
+ assert.sameDeepMembers(
+ allSegments.map(s => [s.min, s.max]),
+ [[100, 300], [300, 400], [400, 600]]
+ );
+
+ const videoAnimationSegments =
+ [...map.get('Animation').get(INITIATOR_TYPE.VIDEO)];
+ assert.sameDeepMembers(
+ videoAnimationSegments.map(s => [s.min, s.max]),
+ [[300, 400]]);
+
+ const cssAnimationSegments =
+ [...map.get('Animation').get(INITIATOR_TYPE.CSS)];
+ assert.sameDeepMembers(
+ cssAnimationSegments.map(s => [s.min, s.max]),
+ [[100, 300], [300, 400]]);
+
+ const allAnimationSegments =
+ [...map.get('Animation').get('all_initiators')];
+ assert.sameDeepMembers(
+ allAnimationSegments.map(s => [s.min, s.max]),
+ [[100, 300], [300, 400]]);
+
+ const scrollResponseSegments =
+ [...map.get('Response').get(INITIATOR_TYPE.SCROLL)];
+ assert.sameDeepMembers(
+ scrollResponseSegments.map(s => [s.min, s.max]),
+ [[400, 600]]);
+
+ const allResponseSegments =
+ [...map.get('Response').get('all_initiators')];
+ assert.sameDeepMembers(
+ allResponseSegments.map(s => [s.min, s.max]),
+ [[400, 600]]);
+ });
+
+ test('getStageToInitiatorToSegmentBounds-rangeOfInterest', () => {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ // This is needed for a model to have segments.
+ thread.name = 'CrBrowserMain';
+
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, INITIATOR_TYPE.CSS,
+ 100, // start time.
+ 300 // duration.
+ ));
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, INITIATOR_TYPE.VIDEO, 300, 100));
+ model.userModel.expectations.push(new tr.model.um.ResponseExpectation(
+ model, INITIATOR_TYPE.SCROLL, 400, 200));
+ });
+
+ const segments = model.userModel.segments;
+
+ const map = getStageToInitiatorToSegmentBounds(model.userModel.segments,
+ tr.b.math.Range.fromExplicitRange(150, 350));
+
+ // Ignoring Idle Expectations, we have the following segments in range:
+ // [150, 300]: CSS Animation
+ // [300, 350]: CSS Animation, Video Animation
+ const allSegments = [...map.get('all_stages').get('all_initiators')];
+ assert.sameDeepMembers(
+ allSegments.map(s => [s.min, s.max]),
+ [[150, 300], [300, 350]]
+ );
+
+ const videoAnimationSegments =
+ [...map.get('Animation').get(INITIATOR_TYPE.VIDEO)];
+ assert.sameDeepMembers(
+ videoAnimationSegments.map(s => [s.min, s.max]),
+ [[300, 350]]);
+
+ const cssAnimationSegments =
+ [...map.get('Animation').get(INITIATOR_TYPE.CSS)];
+ assert.sameDeepMembers(
+ cssAnimationSegments.map(s => [s.min, s.max]),
+ [[150, 300], [300, 350]]);
+
+ const allAnimationSegments =
+ [...map.get('Animation').get('all_initiators')];
+ assert.sameDeepMembers(
+ allAnimationSegments.map(s => [s.min, s.max]),
+ [[150, 300], [300, 350]]);
+
+ // There should be no Response segments
+ assert.isFalse(map.has('Response'));
+ });
+
+ /**
+ * Given the root node of a top down multidimensional tree view, returns
+ * the node at |path|.
+ */
+ function getNodeValues_(root, path) {
+ let node = root;
+ for (let i = 0; i < path.length; i++) {
+ for (const component of path[i]) {
+ node = node.children[i].get(component);
+ }
+ }
+ return node.values;
+ }
+
+ const getCpuUsage_ = nodeValues => nodeValues[0].total;
+ const getCpuTotal_ = nodeValues => nodeValues[1].total;
+
+ /**
+ * Returns a simple model spec with one process (browser process) and one
+ * thread (CrBrowserMain).
+ *
+ * It does not contain any slices or expectations - those should be added
+ * manually.
+ *
+ * This is a function instead of just a variable because the test functions
+ * are meant to modify this modelSpec and insert suitable expectations.
+ */
+ function getSimpleModelSpec_() {
+ return {
+ processes: [
+ {
+ name: 'Browser',
+ pid: 12345,
+ threads: [
+ {
+ name: 'CrBrowserMain',
+ tid: 1,
+ slices: []
+ },
+ ],
+ },
+ ],
+ expectations: [],
+ };
+ }
+
+ test('constructMultiDimensionalView_' +
+ 'slicesDoNotStraddleExpecationBoundaries', () => {
+ const simpleModelSpec = getSimpleModelSpec_();
+ simpleModelSpec.processes[0].threads[0].slices.push(
+ {range: [150, 200], cpu: 30},
+ {range: [205, 255], cpu: 20}
+ );
+ simpleModelSpec.expectations.push({
+ stage: 'Animation',
+ initiatorType: INITIATOR_TYPE.CSS,
+ range: [100, 300],
+ });
+
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Animation', 'CSS']];
+
+ const model = buildModelFromSpec(simpleModelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ // Total CPU Time is 30 + 20 from the two slices, and the total duration of
+ // CSS Animation expectation is 200 (because the range is [100, 300]). CPU
+ // Usage is therefore (30 + 20) / 200.
+ assert.closeTo(getCpuUsage_(values), (30 + 20) / 200, 1e-7);
+ assert.closeTo(getCpuTotal_(values), (30 + 20), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_' +
+ 'slicesStraddleExpectationBoundaries', () => {
+ const simpleModelSpec = getSimpleModelSpec_();
+ simpleModelSpec.processes[0].threads[0].slices.push(
+ {range: [150, 200], cpu: 30},
+ {range: [205, 255], cpu: 20}
+ );
+ simpleModelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [75, 175]}
+ );
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Animation', 'Video']
+ ];
+
+ const model = buildModelFromSpec(simpleModelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ // Only half of the first slice is in the expectation range, so we get a
+ // total CPU contribution of 30 / 2 = 15. The second slice is not in the
+ // expectation at all, so CPU contribution from that slice is 0. So total
+ // CPU Usage during Video Animation expectation is 15.
+ // The total duration of the expectation is 100, so CPU usage is 15 / 100.
+ assert.closeTo(getCpuUsage_(values), 15 / 100, 1e-7);
+ assert.closeTo(getCpuTotal_(values), 15, 1e-7);
+ });
+
+ test('constructMultiDimensionalView_' +
+ 'singleThread-disjointExpectationsOfSameInitiator', () => {
+ const simpleModelSpec = getSimpleModelSpec_();
+ simpleModelSpec.processes[0].threads[0].slices.push(
+ {range: [150, 200], cpu: 30},
+ {range: [205, 255], cpu: 20}
+ );
+ simpleModelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [100, 160]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [205, 225]}
+ );
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Response', 'Scroll']
+ ];
+
+ const model = buildModelFromSpec(simpleModelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ // 1/5 of the first slice and 2/5 of the second slice is in the expectation
+ // ranges, so total CPU is 0.2 * 30 + 0.4 * 20.
+ // Total duration of Scroll Response expectation is 60 + 20, since the two
+ // expectation ranges are disjoint.
+ assert.closeTo(getCpuUsage_(values),
+ (0.2 * 30 + 0.4 * 20) / (60 + 20), 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ 0.2 * 30 + 0.4 * 20, 1e-7);
+ });
+
+ test('constructMultiDimensionalView_' +
+ 'singleThread-overlappingExpectationsOfSameInitiators', () => {
+ const simpleModelSpec = getSimpleModelSpec_();
+ simpleModelSpec.processes[0].threads[0].slices.push(
+ {range: [150, 200], cpu: 30},
+ {range: [205, 255], cpu: 20}
+ );
+ simpleModelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [100, 190]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [160, 230]}
+ );
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Animation', 'CSS']
+ ];
+
+ const model = buildModelFromSpec(simpleModelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ // The whole of the first slice is covered by CSS Animation expectation,
+ // even though the expectations are from two different ranges. The second
+ // slice is only half covered. Total CPU usage: 30 + 0.5 * 20.
+ // The total range covered by the expectation is [100, 230], so total
+ // duration is 130.
+ assert.closeTo(getCpuUsage_(values), (30 + 0.5 * 20) / 130, 1e-7);
+ assert.closeTo(getCpuTotal_(values), 30 + 0.5 * 20, 1e-7);
+ });
+
+ test('constructMultiDimensionalView_' +
+ 'singleThread-overlappingExpectationsOfDifferentInitiators', () => {
+ const simpleModelSpec = getSimpleModelSpec_();
+ simpleModelSpec.processes[0].threads[0].slices.push(
+ {range: [150, 200], cpu: 30},
+ {range: [205, 255], cpu: 20}
+ );
+ simpleModelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [100, 190]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [160, 230]}
+ );
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Animation', 'all_initiators']
+ ];
+
+ const model = buildModelFromSpec(simpleModelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values),
+ (30 + 0.5 * 20) / 130, 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ 30 + 0.5 * 20, 1e-7);
+ });
+
+ test('constructMultiDimensionalView_' +
+ 'singleThread-allStages-customRangeOfInterest', () => {
+ const simpleModelSpec = getSimpleModelSpec_();
+ simpleModelSpec.processes[0].threads[0].slices.push(
+ {range: [150, 200], cpu: 30},
+ {range: [205, 255], cpu: 20}
+ );
+ simpleModelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [100, 190]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [160, 230]}
+ );
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['all_stages', 'all_initiators']
+ ];
+
+ const model = buildModelFromSpec(simpleModelSpec);
+ const rangeOfInterest = new tr.b.math.Range.fromExplicitRange(100, 210);
+ const root = constructMultiDimensionalView(model, rangeOfInterest);
+ const values = getNodeValues_(root, path);
+
+ // Only 1/10 of the second slice is included in the range of interest, so
+ // contribution from that slice is 0.1 * 20.
+ // The total range of expectation within range of interest is [100, 210], so
+ // total duration is 110.
+ assert.closeTo(getCpuUsage_(values), (30 + 0.1 * 20) / 110, 1e-7);
+ assert.closeTo(getCpuTotal_(values), 30 + 0.1 * 20, 1e-7);
+ });
+
+ /**
+ * Returns a model spec where the browser process has two worker threads.
+ *
+ * This is a function instead of just a variable because the test functions
+ * are meant to modify this modelSpec and insert suitable expectations.
+ *
+ * Thread 1 looks like
+ *
+ * |0 |10 |20 |30 |40 |50 |60 |70 .... Time
+ * [ ] [ ] [ ] [ ] .... Slices
+ *
+ * where each slice has a duration of 10ms and CPU time of 5ms.
+ *
+ * Thread 2 looks like
+ *
+ * |0 |50 |100 |150 |200 |250 |300 |350 .... Time
+ * [ ] [ ] [ ] [ ] .... Slices
+ * where each slice has a duration of 80ms and CPU time of 40ms.
+ */
+ function getMultipleThreadsOfSameTypeModelSpec_() {
+ return {
+ processes: [
+ {
+ name: 'Browser',
+ pid: 12345,
+ threads: [
+ {
+ name: 'CrBrowserMain',
+ tid: 1,
+ slices: [],
+ },
+ {
+ name: 'Worker/1',
+ tid: 42,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 20) {
+ slices.push({range: [i, i + 10], cpu: 5});
+ }
+ return slices;
+ })(),
+ },
+ {
+ name: 'Worker/2',
+ tid: 52,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 100) {
+ slices.push({range: [i, i + 80], cpu: 40});
+ }
+ return slices;
+ })(),
+ },
+ ],
+ },
+ ],
+
+ expectations: [],
+ };
+ }
+
+ test('constructMultiDimensionalView_multipleThreadsOfSameType_' +
+ 'singleExpectation', () => {
+ const modelSpec = getMultipleThreadsOfSameTypeModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Worker'], ['Animation', 'Video']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ // There are five thread-1 slices within [0, 90] and one thread-2 slice.
+ assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 90, 1e-7);
+ assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7);
+ });
+
+ test('constructMultiDimensionalView_multipleThreadsOfSameType_' +
+ 'disjointExpectationSameInitiator', () => {
+ const modelSpec = getMultipleThreadsOfSameTypeModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Worker'], ['Animation', 'CSS']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ // Both worker threads are of the same type ('Worker'), so their CPU times
+ // will be added together.
+ // There are 3 thread-1 slices and 6/8 of a thread-2 slice within
+ // [500, 560].
+ // There are 1 thread-1 slices and two thread-2 slices within [690, 890].
+ // Total expectation duration is 60 + 200.
+ assert.closeTo(getCpuUsage_(values),
+ ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)) / (60 + 200), 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ (5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_multipleThreadsOfSameType_' +
+ 'overlappingExpectationsOfSameInitiator', () => {
+ const modelSpec = getMultipleThreadsOfSameTypeModelSpec_();
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Worker'], ['Response', 'Scroll']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values),
+ (5 * 4 + 40 * (70 / 80)) / 90, 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ 5 * 4 + 40 * (70 / 80), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_multipleThreadsOfSameType_' +
+ 'disjointExpectationsAllInitiators', () => {
+ const modelSpec = getMultipleThreadsOfSameTypeModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Worker'], ['Animation', 'all_initiators']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values),
+ ((5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2))) /
+ (90 + 60 + 200), 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ (5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)),
+ 1e-7);
+ });
+
+
+ test('constructMultiDimensionalView_multipleThreadsOfSameType_' +
+ 'overlappingExpectationsAllInitiators', () => {
+ const modelSpec = getMultipleThreadsOfSameTypeModelSpec_();
+ // [Click R]
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Worker'], ['Response', 'all_initiators']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values),
+ (5 * 5 + 40) / 100, 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ 5 * 5 + 40, 1e-7);
+ });
+
+
+ test('constructMultiDimensionalView_multipleThreadsOfSameType_' +
+ 'allStagesAllInitiators', () => {
+ const modelSpec = getMultipleThreadsOfSameTypeModelSpec_();
+ // [Video A] [Click R] [CSS A] [ CSS A ]
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Worker'], ['all_stages', 'all_initiators']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values), (250 + 400) / 990, 1e-7);
+ assert.closeTo(getCpuTotal_(values), 250 + 400, 1e-7);
+ });
+
+ /**
+ * Returns a model spec where there are two renderer processes, each with a
+ * renderer main thread.
+ *
+ * This is a function instead of just a variable because the test functions
+ * are meant to modify this modelSpec and insert suitable expectations.
+ *
+ * The main thread on renderer-1 looks like
+ *
+ * |0 |10 |20 |30 |40 |50 |60 |70 .... Time
+ * [ ] [ ] [ ] [ ] .... Slices
+ *
+ * where each slice has a duration of 10ms and CPU time of 5ms.
+ *
+ * The main thread on renderer-2 looks like
+ *
+ * |0 |50 |100 |150 |200 |250 |300 |350 .... Time
+ * [ ] [ ] [ ] [ ] .... Slices
+ *
+ * where each slice has a duration of 80ms and CPU time of 40ms.
+ */
+ function getMultipleProcessesOfSameTypeModelSpec_() {
+ return {
+ processes: [
+ {
+ name: 'Browser',
+ pid: 12345,
+ threads: [
+ {
+ name: 'CrBrowserMain',
+ tid: 1,
+ slices: [],
+ },
+ ],
+ },
+ {
+ name: 'Renderer',
+ pid: 20001,
+ threads: [
+ {
+ name: 'CrRendererMain',
+ tid: 42,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 20) {
+ slices.push({range: [i, i + 10], cpu: 5});
+ }
+ return slices;
+ })(),
+ },
+ ],
+ },
+ {
+ name: 'Renderer',
+ pid: 30001,
+ threads: [
+ {
+ name: 'CrRendererMain',
+ tid: 52,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 100) {
+ slices.push({range: [i, i + 80], cpu: 40});
+ }
+ return slices;
+ })(),
+ },
+ ]
+ },
+ ],
+
+ expectations: [],
+ };
+ }
+
+ test('constructMultiDimensionalView_multipleProcessesOfSameType_' +
+ 'singleExpectation', () => {
+ const modelSpec = getMultipleProcessesOfSameTypeModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['CrRendererMain'], ['Animation', 'Video']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 90, 1e-7);
+ assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7);
+ });
+
+ test('constructMultiDimensionalView_multipleProcessesOfSameType_' +
+ 'disjointExpectationSameInitiator', () => {
+ const modelSpec = getMultipleProcessesOfSameTypeModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['CrRendererMain'], ['Animation', 'CSS']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values),
+ ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)) / (60 + 200), 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ (5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_multipleProcessesOfSameType_' +
+ 'overlappingExpectationsOfSameInitiator', () => {
+ const modelSpec = getMultipleProcessesOfSameTypeModelSpec_();
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['CrRendererMain'], ['Response', 'Scroll']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values),
+ (5 * 4 + 40 * (70 / 80)) / 90, 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ 5 * 4 + 40 * (70 / 80), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_multipleProcessesOfSameType_' +
+ 'disjointExpectationsAllInitiators', () => {
+ const modelSpec = getMultipleProcessesOfSameTypeModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['CrRendererMain'], ['Animation', 'all_initiators']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values),
+ ((5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2))) /
+ (90 + 60 + 200), 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ (5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)),
+ 1e-7);
+ });
+
+
+ test('constructMultiDimensionalView_multipleProcessesOfSameType_' +
+ 'overlappingExpectationsAllInitiators', () => {
+ const modelSpec = getMultipleProcessesOfSameTypeModelSpec_();
+ // [Click R]
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['CrRendererMain'], ['Response', 'all_initiators']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 100, 1e-7);
+ assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7);
+ });
+
+
+ test('constructMultiDimensionalView_multipleProcessesOfSameType_' +
+ 'allStagesAllInitiators', () => {
+ const modelSpec = getMultipleProcessesOfSameTypeModelSpec_();
+ // [Video A] [Click R] [CSS A] [ CSS A ]
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const path = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['CrRendererMain'], ['all_stages', 'all_initiators']
+ ];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values), (250 + 400) / 990, 1e-7);
+ assert.closeTo(getCpuTotal_(values), 250 + 400, 1e-7);
+ });
+
+ /**
+ * Returns a model spec where the browser process has a main thread and an IO
+ * thread.
+ *
+ * This is a function instead of just a variable because the test functions
+ * are meant to modify this modelSpec and insert suitable expectations.
+ *
+ * The browser main thread looks like
+ *
+ * |0 |10 |20 |30 |40 |50 |60 |70 .... Time
+ * [ ] [ ] [ ] [ ] .... Slices
+ *
+ * where each slice has a duration of 10ms and CPU time of 5ms.
+ *
+ * The IO Thread looks like
+ *
+ * |0 |50 |100 |150 |200 |250 |300 |350 .... Time
+ * [ ] [ ] [ ] [ ] .... Slices
+ *
+ * where each slice has a duration of 80ms and CPU time of 40ms.
+ */
+ function getAllThreadsOfSameProcessModelSpec_() {
+ return {
+ processes: [
+ {
+ name: 'Browser',
+ pid: 12345,
+ threads: [
+ {
+ name: 'CrBrowserMain',
+ tid: 1,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 20) {
+ slices.push({range: [i, i + 10], cpu: 5});
+ }
+ return slices;
+ })(),
+ },
+ {
+ name: 'Chrome_IOThread',
+ tid: 5,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 100) {
+ slices.push({range: [i, i + 80], cpu: 40});
+ }
+ return slices;
+ })(),
+ }
+ ],
+ },
+ ],
+
+ expectations: [],
+ };
+ }
+
+
+ test('constructMultiDimensionalView_AllThreadsOfSameProcess_' +
+ 'singleExpectation', () => {
+ const modelSpec = getAllThreadsOfSameProcessModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]}
+ );
+
+ const pathForAllThreads = [
+ [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'Video']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Animation', 'Video']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Chrome_IOThread'], ['Animation', 'Video']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllThreadsOfSameProcess_' +
+ 'disjointExpectationSameInitiator', () => {
+ const modelSpec = getAllThreadsOfSameProcessModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const pathForAllThreads = [
+ [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'CSS']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Animation', 'CSS']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Chrome_IOThread'], ['Animation', 'CSS']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllThreadsOfSameProcess_' +
+ 'overlappingExpectationsOfSameInitiator', () => {
+ const modelSpec = getAllThreadsOfSameProcessModelSpec_();
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]}
+ );
+
+ const pathForAllThreads = [
+ [CHROME_PROCESS_NAMES.BROWSER], [], ['Response', 'Scroll']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Response', 'Scroll']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Chrome_IOThread'], ['Response', 'Scroll']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllThreadsOfSameProcess_' +
+ 'disjointExpectationsAllInitiators', () => {
+ const modelSpec = getAllThreadsOfSameProcessModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const pathForAllThreads = [
+ [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'all_initiators']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Animation', 'all_initiators']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Chrome_IOThread'], ['Animation', 'all_initiators']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllThreadsOfSameProcess_' +
+ 'overlappingExpectationsAllInitiators', () => {
+ const modelSpec = getAllThreadsOfSameProcessModelSpec_();
+ // [Click R]
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]}
+ );
+
+ const pathForAllThreads = [
+ [CHROME_PROCESS_NAMES.BROWSER], [], ['Response', 'all_initiators']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['Response', 'all_initiators']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Chrome_IOThread'], ['Response', 'all_initiators']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllThreadsOfSameProcess_' +
+ 'allStagesAllInitiators', () => {
+ const modelSpec = getAllThreadsOfSameProcessModelSpec_();
+ // [Video A] [Click R] [CSS A] [ CSS A ]
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const pathForAllThreads = [
+ [CHROME_PROCESS_NAMES.BROWSER], [], ['all_stages', 'all_initiators']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['CrBrowserMain'], ['all_stages', 'all_initiators']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.BROWSER],
+ ['Chrome_IOThread'], ['all_stages', 'all_initiators']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ /**
+ * Returns a model spec where a renderer process and a GPU process both have a
+ * Chrome_ChildIOThread.
+ *
+ * This is a function instead of just a variable because the test functions
+ * are meant to modify this modelSpec and insert suitable expectations.
+ *
+ * The modelSpec includes a basic browser process because it not a valid
+ * chrome model otherwise.
+ *
+ * The renderer ChildIOThread looks like
+ *
+ * |0 |10 |20 |30 |40 |50 |60 |70 .... Time
+ * [ ] [ ] [ ] [ ] .... Slices
+ *
+ * where each slice has a duration of 10ms and CPU time of 5ms.
+ *
+ * The GPU ChildIOThread looks like
+ *
+ * |0 |50 |100 |150 |200 |250 |300 |350 .... Time
+ * [ ] [ ] [ ] [ ] .... Slices
+ *
+ * where each slice has a duration of 80ms and CPU time of 40ms.
+ */
+ function getAllProcessesOfSameThreadModelSpec_() {
+ return {
+ processes: [
+ {
+ name: 'Browser',
+ pid: 12345,
+ threads: [
+ {
+ name: 'CrBrowserMain',
+ tid: 1,
+ slices: [],
+ },
+ ],
+ },
+ {
+ name: 'Renderer',
+ pid: 20001,
+ threads: [
+ {
+ name: 'Chrome_ChildIOThread',
+ tid: 42,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 20) {
+ slices.push({range: [i, i + 10], cpu: 5});
+ }
+ return slices;
+ })(),
+ },
+ ],
+ },
+ {
+ name: 'GPU Process',
+ pid: 30001,
+ threads: [
+ {
+ name: 'Chrome_ChildIOThread',
+ tid: 52,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 100) {
+ slices.push({range: [i, i + 80], cpu: 40});
+ }
+ return slices;
+ })(),
+ },
+ ]
+ },
+ ],
+ expectations: [],
+ };
+ }
+
+ test('constructMultiDimensionalView_AllProcessesOfSameThread_' +
+ 'singleExpectation', () => {
+ const modelSpec = getAllProcessesOfSameThreadModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]}
+ );
+
+ const pathForAllThreads = [
+ [], ['Chrome_ChildIOThread'], ['Animation', 'Video']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['Chrome_ChildIOThread'], ['Animation', 'Video']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.GPU],
+ ['Chrome_ChildIOThread'], ['Animation', 'Video']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllProcessesOfSameThread_' +
+ 'disjointExpectationSameInitiator', () => {
+ const modelSpec = getAllProcessesOfSameThreadModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const pathForAllThreads = [
+ [], ['Chrome_ChildIOThread'], ['Animation', 'CSS']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['Chrome_ChildIOThread'], ['Animation', 'CSS']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.GPU],
+ ['Chrome_ChildIOThread'], ['Animation', 'CSS']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllProcessesOfSameThread_' +
+ 'overlappingExpectationsOfSameInitiator', () => {
+ const modelSpec = getAllProcessesOfSameThreadModelSpec_();
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]}
+ );
+
+ const pathForAllThreads = [
+ [], ['Chrome_ChildIOThread'], ['Response', 'Scroll']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['Chrome_ChildIOThread'], ['Response', 'Scroll']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.GPU],
+ ['Chrome_ChildIOThread'], ['Response', 'Scroll']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllProcessesOfSameThread_' +
+ 'disjointExpectationsAllInitiators', () => {
+ const modelSpec = getAllProcessesOfSameThreadModelSpec_();
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const pathForAllThreads = [
+ [], ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.GPU],
+ ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllProcessesOfSameThread_' +
+ 'overlappingExpectationsAllInitiators', () => {
+ const modelSpec = getAllProcessesOfSameThreadModelSpec_();
+ // [Click R]
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]}
+ );
+
+ const pathForAllThreads = [
+ [], ['Chrome_ChildIOThread'], ['Response', 'all_initiators']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['Chrome_ChildIOThread'], ['Response', 'all_initiators']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.GPU],
+ ['Chrome_ChildIOThread'], ['Response', 'all_initiators']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_AllProcessesOfSameThread_' +
+ 'allStagesAllInitiators', () => {
+ const modelSpec = getAllProcessesOfSameThreadModelSpec_();
+ // [Video A] [Click R] [CSS A] [ CSS A ]
+ // [Scroll R]
+ // [Scroll R]
+ modelSpec.expectations.push(
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ );
+
+ const pathForAllThreads = [
+ [], ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']];
+
+ const pathForThread1 = [
+ [CHROME_PROCESS_NAMES.RENDERER],
+ ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']];
+
+ const pathForThread2 = [
+ [CHROME_PROCESS_NAMES.GPU],
+ ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']];
+
+ const model = buildModelFromSpec(modelSpec);
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const valueForAllThreads = getNodeValues_(root, pathForAllThreads);
+ const valueForThread1 = getNodeValues_(root, pathForThread1);
+ const valueForThread2 = getNodeValues_(root, pathForThread2);
+
+ assert.closeTo(getCpuUsage_(valueForAllThreads),
+ getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7);
+ assert.closeTo(getCpuTotal_(valueForAllThreads),
+ getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7);
+ });
+
+ test('constructMultiDimensionalView_completeAggregation', () => {
+ const modelSpec = {
+ processes: [
+ {
+ name: 'Browser',
+ pid: 12345,
+ threads: [
+ {
+ name: 'CrBrowserMain',
+ tid: 1,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 50) {
+ slices.push({range: [i, i + 50], cpu: 30});
+ }
+ return slices;
+ })(),
+ },
+ ],
+ },
+ {
+ name: 'Renderer',
+ pid: 20001,
+ threads: [
+ {
+ name: 'Chrome_ChildIOThread',
+ tid: 42,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 20) {
+ slices.push({range: [i, i + 10], cpu: 5});
+ }
+ return slices;
+ })(),
+ },
+ ],
+ },
+ {
+ name: 'GPU Process',
+ pid: 30001,
+ threads: [
+ {
+ name: 'Chrome_ChildIOThread',
+ tid: 52,
+ slices: (() => {
+ const slices = [];
+ for (let i = 0; i < 1000; i += 100) {
+ slices.push({range: [i, i + 80], cpu: 40});
+ }
+ return slices;
+ })(),
+ },
+ ]
+ },
+ ],
+
+ // [Video A] [Click R] [CSS A] [ CSS A ]
+ // [Scroll R]
+ // [Scroll R]
+ expectations: [
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO,
+ range: [0, 90]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK,
+ range: [200, 220]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [210, 260]},
+ {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL,
+ range: [250, 300]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [500, 560]},
+ {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS,
+ range: [690, 890]}
+ ],
+ };
+
+ const model = buildModelFromSpec(modelSpec);
+ const path = [[], [], ['all_stages', 'all_initiators']];
+ const root = constructMultiDimensionalView(model, model.bounds);
+ const values = getNodeValues_(root, path);
+
+ assert.closeTo(getCpuUsage_(values),
+ (30 * 20 + 5 * 50 + 40 * 10) / 1000, 1e-7);
+ assert.closeTo(getCpuTotal_(values),
+ (30 * 20 + 5 * 50 + 40 * 10), 1e-7);
+ });
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_test_utils.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_test_utils.html
new file mode 100644
index 00000000000..3066677e6e7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/cpu_time_test_utils.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.chrome.cpuTimeTestUtils', function() {
+ /**
+ * Takes a model spec, and returns a fully constructed model.
+ *
+ * A model spec is a minimal representation of a model containing only the
+ * information needed to set up scenarios for testing cpu time metrics - it
+ * specifies
+ * - All the processes with name, pid, and threads
+ * - All the threads with name, tid, and top level slices
+ * - All the top level slices with range and cpu duration
+ * - All the User Expectations (except Idle Expectations) with range, stage,
+ * and initiator.
+ *
+ * Example model spec:
+ * {
+ * processes: [
+ * {
+ * name: 'Browser',
+ * pid: 12345,
+ * threads: [
+ * {
+ * name: 'CrBrowserMain',
+ * tid: 1,
+ * slices: [
+ * {range: [150, 200], cpu: 30},
+ * {range: [205, 255], cpu: 20}
+ * ]
+ * },
+ * ],
+ * },
+ * ],
+ * expectations: [
+ * {stage: 'Animation', initiatorType: 'Video', range: [0, 90]},
+ * {stage: 'Response', initiatorType: 'Click', range: [200, 220]},
+ * ]
+ * }
+ */
+ function buildModelFromSpec(modelSpec) {
+ return tr.c.TestUtils.newModel(model => {
+ // Create processes, threads, and slices
+ for (const processSpec of modelSpec.processes) {
+ const process = model.getOrCreateProcess(processSpec.pid);
+ process.name = processSpec.name;
+
+ for (const threadSpec of processSpec.threads) {
+ const thread = process.getOrCreateThread(threadSpec.tid);
+ thread.name = threadSpec.name;
+
+ for (const sliceSpec of threadSpec.slices) {
+ // Sanity checks on sliceSpec
+ const sliceStart = sliceSpec.range[0];
+ const sliceEnd = sliceSpec.range[1];
+ const duration = sliceEnd - sliceStart;
+ const cpuDuration = sliceSpec.cpu;
+ assert(sliceEnd >= sliceStart,
+ 'Slice end time is earlier than slice start time: ' +
+ `sliceStart: ${sliceStart}, sliceEnd: ${sliceEnd}`);
+ assert(duration >= cpuDuration,
+ `Cpu duration (${cpuDuration}) is larger than ` +
+ `slice duration (${duration})`);
+
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: sliceSpec.range[0],
+ duration: sliceSpec.range[1] - sliceSpec.range[0],
+ // We currently do not have all the data about exactly when a
+ // thread was scheduled or descheduled - for example, if a slice
+ // got descheduled twice over its duration, the trace will not
+ // contain information to indicate that. Without loss of
+ // generality, we therefore make the assumption that the cpuStart
+ // is at the beginning of the slice, and total cpu time of a slice
+ // is uniformly spread over its duration.
+ cpuStart: sliceSpec.range[0],
+ cpuDuration: sliceSpec.cpu
+ }));
+ }
+ }
+ }
+
+ const expectations = model.userModel.expectations;
+ for (const expSpec of modelSpec.expectations) {
+ // This switch statement is not exhaustive. You may have to add more
+ // cases here when you add new scenarios.
+ switch (expSpec.stage) {
+ case 'Animation':
+ expectations.push(new tr.model.um.AnimationExpectation(
+ model, expSpec.initiatorType,
+ expSpec.range[0], expSpec.range[1] - expSpec.range[0]
+ ));
+ break;
+ case 'Idle':
+ expectations.push(new tr.model.um.IdleExpectation(
+ model, expSpec.range[0], expSpec.range[1] - expSpec.range[0]
+ ));
+ break;
+ case 'Response':
+ expectations.push(new tr.model.um.ResponseExpectation(
+ model, expSpec.initiatorType,
+ expSpec.range[0], expSpec.range[1] - expSpec.range[0]
+ ));
+ break;
+ default:
+ throw new Error('Internal Error: Stage ' + expSpec.stage +
+ 'not handled yet. You should add another case here.');
+ }
+ }
+ });
+ }
+
+ return {
+ buildModelFromSpec,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency.html
new file mode 100644
index 00000000000..81d9803fa71
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency.html
@@ -0,0 +1,367 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.e.chrome', function() {
+ // TODO(dproy): Because title and category are properties of TimedEvent
+ // subclasses and not TimedEvent itself, we have to write our own "has title
+ // and category" function rather than having it provided by TimedEvent.
+ // This should be fixed.
+ // https://github.com/catapult-project/catapult/issues/2784
+ function hasTitleAndCategory(event, title, category) {
+ return event.title === title && event.category &&
+ tr.b.getCategoryParts(event.category).includes(category);
+ }
+
+ function getNavStartTimestamps(rendererHelper) {
+ const navStartTimestamps = [];
+ for (const e of rendererHelper.mainThread.sliceGroup.childEvents()) {
+ if (hasTitleAndCategory(e, 'navigationStart', 'blink.user_timing')) {
+ navStartTimestamps.push(e.start);
+ }
+ }
+ return navStartTimestamps;
+ }
+
+ /**
+ * Returns a map of renderer PIDs to array of timestamps at which the
+ * renderer became interactive.
+ */
+ function getInteractiveTimestamps(model) {
+ const interactiveTimestampsMap = new Map();
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ for (const rendererHelper of Object.values(chromeHelper.rendererHelpers)) {
+ const timestamps = [];
+ interactiveTimestampsMap.set(rendererHelper.pid, timestamps);
+ }
+ for (const expectation of model.userModel.expectations) {
+ if (!(expectation instanceof tr.model.um.LoadExpectation)) continue;
+ if (tr.e.chrome.CHROME_INTERNAL_URLS.includes(
+ expectation.url)) {
+ continue;
+ }
+ if (expectation.timeToInteractive === undefined) continue;
+ if (interactiveTimestampsMap.get(expectation.renderProcess.pid) ===
+ undefined) {
+ interactiveTimestampsMap.set(expectation.renderProcess.pid, []);
+ }
+ interactiveTimestampsMap.get(expectation.renderProcess.pid).push(
+ expectation.timeToInteractive);
+ }
+ return interactiveTimestampsMap;
+ }
+
+ /**
+ * Returns an Array of task windows that start with the supplied interactive
+ * timestamps.
+ *
+ * A task window is defined as the range of time from the time when the page
+ * became interactive until either
+ *
+ * 1. The beginning of the next navigationStart event or
+ * 2. The end of the trace
+ *
+ * This function only works when timestamps are from the same renderer. If
+ * windows for multiple renderers need to be computed, the timestamps should
+ * be separated for each renderer and this function should be called
+ * separately for each.
+ *
+ * @param {!Array.<number>} interactiveTimestamps
+ * @param {!Array.<number>} navStartTimestamps
+ * @param {!number} traceEndTimestamp
+ * @returns {!Array.<tr.b.math.Range>}
+ */
+ function getPostInteractiveTaskWindows(
+ interactiveTimestamps, navStartTimestamps, traceEndTimestamp) {
+ let navStartTsIndex = 0;
+ let lastTaskWindowEndTs = undefined;
+ const taskWindows = [];
+ for (const currTTI of interactiveTimestamps) {
+ // Find the first navigation start event after the interactive
+ // timestamp.
+ while (navStartTsIndex < navStartTimestamps.length &&
+ navStartTimestamps[navStartTsIndex] < currTTI) {
+ navStartTsIndex++;
+ }
+
+ const taskWindowEndTs = navStartTsIndex < navStartTimestamps.length ?
+ navStartTimestamps[navStartTsIndex] : traceEndTimestamp;
+
+ if (taskWindowEndTs === lastTaskWindowEndTs) {
+ // This is the case where we have two different interactive timestamps
+ // with no navigationStart event between them. This is only possible
+ // when two different pages are sharing the same renderer process (and
+ // therefore the same renderer scheduler). We cannot define a proper
+ // task window in this case to calculate Estimated Input Latency.
+ throw Error('Encountered two consecutive interactive timestamps ' +
+ 'with no navigationStart between them. ' +
+ 'PostInteractiveTaskWindow is not well defined in this case.');
+ }
+
+ taskWindows.push(tr.b.math.Range.fromExplicitRange(
+ currTTI, taskWindowEndTs));
+ lastTaskWindowEndTs = taskWindowEndTs;
+ }
+ return taskWindows;
+ }
+
+ /**
+ * Returns the contribution of the given task to expected queueing time
+ * in the given time window.
+ *
+ * The result is probabilityOf(task) * expectedQueueTimeDueTo(task),
+ * where
+ * - probabilityOf(task) = probability of input arriving while the given
+ * task is running.
+ * - expectedQueueingTimeDueTo(task) = expected time until the end of the
+ * given task for input arriving while the task is running.
+ *
+ * We assume that input arrival time is uniformly distributed in the given
+ * time window.
+ *
+ * @param {!tr.b.math.Range} A time window.
+ * @param {!Array.<!{start: number, end: number, weight: number}>} A list of
+ * weighted tasks. The weight of a task must be between 0.0 and 1.0.
+ * @returns {number}
+ */
+ function contributionToEQT(window, task) {
+ const startInWindow = Math.max(window.min, task.start);
+ const endInWindow = Math.min(window.max, task.end);
+ const durationInWindow = endInWindow - startInWindow;
+ if (durationInWindow <= 0) return 0;
+ const probabilityOfTask = durationInWindow / (window.max - window.min);
+ const minQueueingTime = task.end - endInWindow;
+ const maxQueueingTime = task.end - startInWindow;
+ const expectedQueueingTimeDueToTask =
+ (maxQueueingTime + minQueueingTime) / 2;
+ return probabilityOfTask * expectedQueueingTimeDueToTask;
+ }
+
+ /**
+ * Returns weighted expected queueing time (EQT) for the given time window and
+ * the given set of weighted tasks. The tasks must not overlap.
+ *
+ * The weighted EQT is computed as
+ * sum(contributionToEQT(window, task) * task.weight)
+ * for all tasks in weightedTasks, where
+ * - contributionToEQT is the function defined above.
+ * - task.weight is an arbitrary number between 0.0 and 1.0. This is useful
+ * for computing contribution of chrome subcomponents (e.g. GC) to
+ * the expected queueing time for EQT diagnostics.
+ *
+ * We assume that input arrival time is uniformly distributed in the given
+ * time window.
+ *
+ * @param {!tr.b.math.Range} A time window.
+ * @param {!Array.<!{start: number, end: number, weight: number}>} A list of
+ * weighted tasks. The weight of a task must be between 0.0 and 1.0.
+ * @returns {number}
+ */
+ function weightedExpectedQueueingTime(window, weightedTasks) {
+ let result = 0;
+ for (const task of weightedTasks) {
+ result += contributionToEQT(window, task) * task.weight;
+ }
+ return result;
+ }
+
+ /**
+ * Returns expected queueing time for the given time window and
+ * the given set of tasks. The tasks must not overlap.
+ *
+ * @param {!tr.b.math.Range} A time window.
+ * @param {!Array.<!{start: number, end: number}>} A list of tasks.
+ * @returns {number}
+ */
+ function expectedQueueingTime(window, tasks) {
+ return weightedExpectedQueueingTime(window, tasks.map(function(task) {
+ return { start: task.start, end: task.end, weight: 1 };
+ }));
+ }
+
+ /**
+ * Object of this calss represents the sliding window and maintains its
+ * main invariant: windowEQT = firstTaskEQT + innerEQT + lastTaskEQT.
+ * It is intended to be used only in maxExpectedQueueingTimeInSlidingWindow().
+ */
+ class SlidingWindow {
+ /**
+ * @param {number} The starting time of the sliding window.
+ * @param {number} The window size.
+ * @param {!Array.<!{start: number, end: number}>} A list of tasks sorted by
+ * task start time.
+ */
+ constructor(startTime, windowSize, sortedTasks) {
+ /**
+ * @private @const {number} The window size.
+ */
+ this.windowSize_ = windowSize;
+ /**
+ * @private @const {!Array.<!{start: number, end: number}>} The tasks.
+ */
+ this.sortedTasks_ = sortedTasks;
+ /**
+ * @private {!tr.b.math.Range} The endpoints of the sliding window.
+ */
+ this.range_ = tr.b.math.Range.fromExplicitRange(
+ startTime, startTime + windowSize);
+ /**
+ * @private {number} The index of the first task in the sortedTasks that
+ * ends after this window starts:
+ * this.range_.min < this.sortedTasks_[this.firstTaskIndex_].end.
+ */
+ this.firstTaskIndex_ =
+ sortedTasks.findIndex(task => startTime < task.end);
+ if (this.firstTaskIndex_ === -1) {
+ this.firstTaskIndex_ = sortedTasks.length;
+ }
+ /**
+ * @private {number} The index of the last task in the sortedTasks that
+ * starts before this window ends:
+ * this.range.max > this.sortedTasks_[lastTaskIndex_].start.
+ */
+ this.lastTaskIndex_ = -1;
+ while (this.lastTaskIndex_ + 1 < sortedTasks.length &&
+ sortedTasks[this.lastTaskIndex_ + 1].start < startTime + windowSize) {
+ this.lastTaskIndex_++;
+ }
+ /**
+ * @private {number} The sum of EQT contributions for all tasks between
+ * the first task and the last task (excluding the first and the last
+ * tasks). All such tasks are completely inside the window.
+ */
+ this.innerEQT_ = 0;
+ for (let i = this.firstTaskIndex_ + 1; i < this.lastTaskIndex_; i++) {
+ this.innerEQT_ += contributionToEQT(this.range_, sortedTasks[i]);
+ }
+ }
+
+ /**
+ * @returns the EQT for this window.
+ */
+ get getEQT() {
+ let firstTaskEQT = 0;
+ if (this.firstTaskIndex_ < this.sortedTasks_.length) {
+ firstTaskEQT = contributionToEQT(this.range_,
+ this.sortedTasks_[this.firstTaskIndex_]);
+ }
+ let lastTaskEQT = 0;
+ if (this.firstTaskIndex_ < this.lastTaskIndex_) {
+ lastTaskEQT = contributionToEQT(this.range_,
+ this.sortedTasks_[this.lastTaskIndex_]);
+ }
+ return firstTaskEQT + this.innerEQT_ + lastTaskEQT;
+ }
+
+ /**
+ * Moves the window to the given time t.
+ * @param {number} The time.
+ */
+ slide(t) {
+ this.range_ = tr.b.math.Range.fromExplicitRange(t, t + this.windowSize_);
+ if (this.firstTaskIndex_ < this.sortedTasks_.length &&
+ this.sortedTasks_[this.firstTaskIndex_].end <= t) {
+ // The first task moved out of the window.
+ this.firstTaskIndex_++;
+ if (this.firstTaskIndex_ < this.lastTaskIndex_) {
+ // The new first window was accounted in innerEQT. Undo that.
+ this.innerEQT_ -= contributionToEQT(this.range_,
+ this.sortedTasks_[this.firstTaskIndex_]);
+ }
+ }
+ if (this.lastTaskIndex_ + 1 < this.sortedTasks_.length &&
+ this.sortedTasks_[this.lastTaskIndex_ + 1].start <
+ t + this.windowSize_) {
+ // A new task moved in the window.
+ if (this.firstTaskIndex_ < this.lastTaskIndex_) {
+ // The old last task is completely inside the window.
+ // Account it in innerEQT.
+ this.innerEQT_ += contributionToEQT(this.range_,
+ this.sortedTasks_[this.lastTaskIndex_]);
+ }
+ this.lastTaskIndex_++;
+ }
+ }
+ }
+
+ /**
+ * Returns maximum expected queueing time for time window of the given size
+ * that slides from the startTime to the endTime:
+ * max { expectedQueueingTime(window(t, t + windowSize), tasks),
+ * for all startTime <= t && t + w <= endTime }.
+ * See https://goo.gl/jmWpMl for the description of the algorithm.
+ *
+ * @param {number} start time for the sliding window.
+ * @param {number} end time for the sliding window.
+ * @param {number} the size of the sliding window.
+ * @param {!Array.<!{start: number, end: number}>} A list of tasks.
+ * The tasks must not overlap.
+ * @returns {number}
+ */
+ function maxExpectedQueueingTimeInSlidingWindow(startTime, endTime,
+ windowSize, tasks) {
+ if (windowSize <= 0) {
+ throw Error('The window size must be positive number');
+ }
+ if (startTime + windowSize > endTime) {
+ throw Error('The sliding window must fit in the specified time range');
+ }
+
+ const sortedTasks = tasks.slice().sort((a, b) => a.start - b.start);
+
+ for (let i = 1; i < sortedTasks.length; i++) {
+ // Ensure that the previous task finishes not later than the current task.
+ // This can happen with short trace events late in the timeline, when
+ // floating point errors increasingly come into play.
+ if (sortedTasks[i - 1].end > sortedTasks[i].start) {
+ const midpoint = (sortedTasks[i - 1].end + sortedTasks[i].start) / 2;
+ sortedTasks[i - 1].end = midpoint;
+ sortedTasks[i].start = midpoint;
+ }
+ }
+
+ // Collect all time points that the sliding window needs to stop at.
+ // See https://goo.gl/jmWpMl for justification.
+ let endpoints = [];
+ endpoints.push(startTime);
+ endpoints.push(endTime - windowSize);
+ for (const task of tasks) {
+ endpoints.push(task.start - windowSize);
+ endpoints.push(task.start);
+ endpoints.push(task.end - windowSize);
+ endpoints.push(task.end);
+ }
+ endpoints = endpoints.filter(
+ x => (startTime <= x && x + windowSize <= endTime));
+ endpoints.sort((a, b) => a - b);
+
+ // Slide the window and compute maxEQT.
+ const slidingWindow = new SlidingWindow(
+ endpoints[0], windowSize, sortedTasks);
+ let maxEQT = 0;
+ for (const t of endpoints) {
+ slidingWindow.slide(t);
+ maxEQT = Math.max(maxEQT, slidingWindow.getEQT);
+ }
+ return maxEQT;
+ }
+
+ return {
+ getPostInteractiveTaskWindows,
+ getNavStartTimestamps,
+ getInteractiveTimestamps,
+ expectedQueueingTime,
+ maxExpectedQueueingTimeInSlidingWindow,
+ weightedExpectedQueueingTime
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html
new file mode 100644
index 00000000000..3031ec2c4a2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/estimated_input_latency_test.html
@@ -0,0 +1,384 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/assert_utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import"
+ href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/extras/chrome/estimated_input_latency.html">
+<link rel="import" href="/tracing/metrics/system_health/loading_metric.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const getInteractiveTimestamps = tr.e.chrome.getInteractiveTimestamps;
+ const getPostInteractiveTaskWindows =
+ tr.e.chrome.getPostInteractiveTaskWindows;
+ const getNavStartTimestamps = tr.e.chrome.getNavStartTimestamps;
+ const expectedQueueingTime = tr.e.chrome.expectedQueueingTime;
+ const maxExpectedQueueingTimeInSlidingWindow =
+ tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow;
+ const weightedExpectedQueueingTime = tr.e.chrome.weightedExpectedQueueingTime;
+ const assertRangeEquals = tr.b.assertRangeEquals;
+
+ function newSchedulerTask(startTime, duration) {
+ return tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: startTime,
+ duration
+ });
+ }
+
+ /**
+ * Adds a FrameLoader snapshot to rendererProcess that is used by test FMP
+ * candidate slices.
+ */
+ function addTestFrame(rendererProcess) {
+ rendererProcess.objects.addSnapshot(
+ 'ptr', 'loading', 'FrameLoader', 300, {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ }
+
+ function addNavigationStart(mainThread, startNavTime) {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: startNavTime,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ }
+
+ function addNetworkRequest(rendererMain, start, duration) {
+ const networkEvents = [];
+ rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start,
+ duration,
+ }));
+ }
+
+ function addFMPCandidate(mainThread, fmpTime) {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: fmpTime,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ }
+
+ function addDomContentLoadedEnd(mainThread, dclTime) {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: dclTime,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ }
+
+ function addSchedulerTask(mainThread, startTime, duration) {
+ mainThread.sliceGroup.pushSlice(newSchedulerTask(startTime, duration));
+ }
+
+ function addDummyTask(mainThread, startTime) {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'dummy',
+ title: 'dummyTitle',
+ start: startTime,
+ duration: 0.0
+ }));
+ }
+
+ test('getNavStartTimestamps', () => {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(model => {
+ const mainThread = model.rendererMain;
+ addNavigationStart(mainThread, 0);
+ addNavigationStart(mainThread, 10);
+ addNavigationStart(mainThread, 30);
+ });
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelper = chromeHelper.rendererHelpers[
+ model.rendererProcess.pid];
+ const navStartTimestamps = getNavStartTimestamps(rendererHelper);
+
+ // It is ok to assert equality for floating point numbers here because
+ // the timestamps should remain unmodified.
+ assert.deepEqual(navStartTimestamps, [0, 10, 30]);
+ });
+
+ /**
+ * Checks getInteractiveTimestamps works as intended. If the definition of
+ * TTI metric changes, this test may begin to fail and we may need to adjust
+ * our EIL implementation.
+ */
+ test('getInteractiveTimestamps', () => {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(model => {
+ addTestFrame(model.rendererProcess);
+
+ const mainThread = model.rendererMain;
+ addNavigationStart(mainThread, 0);
+ addNetworkRequest(mainThread, 0, 50);
+ addFMPCandidate(mainThread, 5000);
+ addDomContentLoadedEnd(mainThread, 5000);
+
+ addNavigationStart(mainThread, 100000);
+ addNetworkRequest(mainThread, 100000, 50);
+ addFMPCandidate(mainThread, 110000);
+ addDomContentLoadedEnd(mainThread, 110000);
+
+ // To detect when a page has become interactive, we need to find a large
+ // enough window of no long tasks. Adding a dummy task sufficiently far
+ // away extends the bounds of the model so that it can contain this
+ // window. In a non-test scenario, we always record traces for long enough
+ // that this is not an issue.
+ addDummyTask(mainThread, 900000);
+ });
+
+ const interactiveTimestampsMap = getInteractiveTimestamps(model);
+ const interactiveTimestamps =
+ interactiveTimestampsMap.get(model.rendererProcess.pid);
+ assert.deepEqual(
+ interactiveTimestamps.sort((a, b) => a - b), [5000, 110000]);
+ });
+
+ test('getInteractiveTimestampsMultiRenderer', () => {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcesses = [];
+ // ChromeModel creates one renderer. We create rest of them here.
+ for (let i = 1; i <= 5; i++) {
+ const rendererProcess = model.getOrCreateProcess(i + 100);
+ const mainThread = rendererProcess.getOrCreateThread(i + 100 + 10);
+ mainThread.name = 'CrRendererMain';
+
+ addTestFrame(rendererProcess);
+ addNavigationStart(mainThread, i * 1000);
+ addNetworkRequest(mainThread, i * 1000, 50);
+ addFMPCandidate(mainThread, i * 1000 + 50);
+ addDomContentLoadedEnd(mainThread, i * 1000 + 2000);
+ addNavigationStart(mainThread, i * 10000);
+ addNetworkRequest(mainThread, i * 10000, 50);
+ addFMPCandidate(mainThread, i * 10000 + 2000);
+ addDomContentLoadedEnd(mainThread, i * 10000 + 2000);
+ addDummyTask(mainThread, 100000);
+ }
+ });
+
+ const interactiveTimestampsMap = getInteractiveTimestamps(model);
+ assert.deepEqual(interactiveTimestampsMap.get(101), [3000, 12000]);
+ assert.deepEqual(interactiveTimestampsMap.get(102), [4000, 22000]);
+ assert.deepEqual(interactiveTimestampsMap.get(103), [5000, 32000]);
+ assert.deepEqual(interactiveTimestampsMap.get(104), [6000, 42000]);
+ assert.deepEqual(interactiveTimestampsMap.get(105), [7000, 52000]);
+ });
+
+ test('singlePostInteractiveWindow', () => {
+ const interactiveTimestamps = [50];
+ const navStartTimestamps = [0];
+ const traceEndTimestamp = [100];
+ const windows = getPostInteractiveTaskWindows(
+ interactiveTimestamps, navStartTimestamps, traceEndTimestamp);
+ assert.strictEqual(windows.length, 1);
+ assertRangeEquals(windows[0], tr.b.math.Range.fromExplicitRange(50, 100));
+ });
+
+ test('multiplePostInteractiveWindows', () => {
+ const interactiveTimestamps = [50, 80];
+ const navStartTimestamps = [0, 70];
+ const traceEndTimestamp = [100];
+ const windows = getPostInteractiveTaskWindows(
+ interactiveTimestamps, navStartTimestamps, traceEndTimestamp);
+ assert.strictEqual(windows.length, 2);
+ assertRangeEquals(windows[0], tr.b.math.Range.fromExplicitRange(50, 70));
+ assertRangeEquals(windows[1], tr.b.math.Range.fromExplicitRange(80, 100));
+ });
+
+ test('postInteractiveWindowWithOneNavigationNeverReachingInteractive', () => {
+ const interactiveTimestamps = [50, 90];
+ const navStartTimestamps = [0, 60, 70];
+ const traceEndTimestamp = [100];
+ const windows = getPostInteractiveTaskWindows(
+ interactiveTimestamps, navStartTimestamps, traceEndTimestamp);
+ assert.strictEqual(windows.length, 2);
+ assertRangeEquals(windows[0], tr.b.math.Range.fromExplicitRange(50, 60));
+ assertRangeEquals(windows[1], tr.b.math.Range.fromExplicitRange(90, 100));
+ });
+
+ test('twoInteractiveTimeStampsWithNoNavStartInBetween', () => {
+ const interactiveTimestamps = [50, 75];
+ const navStartTimestamps = [0];
+ const traceEndTimestamp = [100];
+ assert.throws(() => getPostInteractiveTaskWindows(
+ interactiveTimestamps, navStartTimestamps, traceEndTimestamp));
+ });
+
+ test('expectedQueueingTime_noTasks', () => {
+ const window = tr.b.math.Range.fromExplicitRange(0, 1000);
+ assert.closeTo(0, expectedQueueingTime(window, []), 1e-6);
+ });
+
+ test('expectedQueueingTime_singleTask', () => {
+ const window = tr.b.math.Range.fromExplicitRange(0, 1000);
+ assert.closeTo(1000 / 2,
+ expectedQueueingTime(window, [{start: 0, end: 1000}]),
+ 1e-6);
+ });
+
+ test('expectedQueueingTime_singleTaskStartingBeforeWindow', () => {
+ const window = tr.b.math.Range.fromExplicitRange(0, 1000);
+ assert.closeTo(1000 / 2,
+ expectedQueueingTime(window, [{start: -1, end: 1000}]),
+ 1e-6);
+ });
+
+ test('expectedQueueingTime_singleTaskEndingAfterWindow', () => {
+ const window = tr.b.math.Range.fromExplicitRange(0, 1000);
+ assert.closeTo(1500,
+ expectedQueueingTime(window, [{start: 0, end: 2000}]),
+ 1e-6);
+ });
+
+ test('expectedQueueingTime_singleTaskInsideWindow', () => {
+ const window = tr.b.math.Range.fromExplicitRange(0, 1000);
+ assert.closeTo(10 / 1000 * 10 / 2,
+ expectedQueueingTime(window, [{start: 500, end: 510}]),
+ 1e-6);
+ });
+
+ test('expectedQueueingTime_twoTasksInsideWindow', () => {
+ const window = tr.b.math.Range.fromExplicitRange(0, 1000);
+ assert.closeTo(10 / 1000 * 10 / 2 + 100 / 1000 * 100 / 2,
+ expectedQueueingTime(window,
+ [{start: 500, end: 510}, {start: 600, end: 700}]),
+ 1e-6);
+ });
+
+ test('expectedQueueingTime_twoTasksPartiallyInsideWindow', () => {
+ const window = tr.b.math.Range.fromExplicitRange(0, 1000);
+ assert.closeTo(10 / 1000 * 10 / 2 + 100 / 1000 * (100 + 200) / 2,
+ expectedQueueingTime(window,
+ [{start: 500, end: 510}, {start: 900, end: 1100}]),
+ 1e-6);
+ });
+
+ test('weightedExpectedQueueingTime', () => {
+ const window = tr.b.math.Range.fromExplicitRange(0, 1000);
+ assert.closeTo(1000 / 2 * 0.7,
+ weightedExpectedQueueingTime(window,
+ [{start: 0, end: 1000, weight: 0.7}]),
+ 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_taskOutsideRange', () => {
+ assert.closeTo(0,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100,
+ [{start: 2000, end: 3000}]),
+ 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_taskInsideRange', () => {
+ assert.closeTo(100 / 100 * 100 / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100,
+ [{start: 200, end: 300}]),
+ 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_longTask', () => {
+ assert.closeTo(100 / 100 * (100 + 200) / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100,
+ [{start: 200, end: 400}]),
+ 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_twoTasks', () => {
+ assert.closeTo(2 * 10 / 100 * 10 / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100,
+ [{start: 200, end: 210}, {start: 290, end: 300}]),
+ 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_taskLargerThanRange', () => {
+ assert.closeTo(100 / 100 * (1200 + 1100) / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100,
+ [{start: -200, end: 1200}]),
+ 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_multipleTasks', () => {
+ assert.closeTo(40 / 100 * 40 / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100, [
+ {start: 500, end: 510},
+ {start: 510, end: 520},
+ {start: 520, end: 530},
+ {start: 615, end: 655},
+ {start: 1000, end: 2000},
+ ]), 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_threeTasks', () => {
+ assert.closeTo(40 / 100 * 40 / 2 + 20 / 100 * (50 + 30) / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100, [
+ {start: 500, end: 510},
+ {start: 520, end: 560},
+ {start: 600, end: 650},
+ ]), 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_taskEndsAfterRange', () => {
+ assert.closeTo(1 / 100 * (200 + 199) / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100, [
+ {start: 500, end: 502},
+ {start: 999, end: 1199},
+ ]), 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_taskStartsBeforeRange', () => {
+ assert.closeTo(3 / 100 * 1 / 2 + 20 / 100 * 20 / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100, [
+ {start: -10, end: 1},
+ {start: 1, end: 2},
+ {start: 2, end: 3},
+ {start: 80, end: 100},
+ {start: 999, end: 1099},
+ ]), 1e-6);
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_nonFittingWindowThrows', () => {
+ assert.throws(() => maxExpectedQueueingTimeInSlidingWindow(0, 10, 100,
+ [{start: 0, end: 100}]),
+ 'The sliding window must fit in the specified time range'
+ );
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_emptyWindowThrows', () => {
+ assert.throws(() => maxExpectedQueueingTimeInSlidingWindow(0, 10, 0,
+ [{start: 0, end: 100}]),
+ 'The window size must be positive number'
+ );
+ });
+
+ test('maxExpectedQueueingTimeInSlidingWindow_smallOverlapIsTolerated', () => {
+ // Allow small floating-point precision error when comparing task
+ // end-points for overlapping.
+ assert.closeTo((100.01 + 0.01) / 2,
+ maxExpectedQueueingTimeInSlidingWindow(0, 1000, 100,
+ [{start: 0, end: 100.02}, {start: 100.0, end: 200}]),
+ 1e-6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/event_finder_utils.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/event_finder_utils.html
new file mode 100644
index 00000000000..01281cc7cf7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/event_finder_utils.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.chrome', function() {
+ // We want to ignore chrome internal URLs when computing metrics.
+ const CHROME_INTERNAL_URLS = [
+ // Blank URLs are usually initial empty document.
+ '',
+ 'about:blank',
+ // Chrome on Android creates main frames with the below URL for plugins.
+ 'data:text/html,pluginplaceholderdata',
+ // Special URL used to start a navigation to an unreachable error page.
+ 'chrome-error://chromewebdata/'
+ ];
+
+
+ // Title for top level tasks in the scheduler. Any input event queued during a
+ // top level scheduler task cannot be handled until the end of that task.
+ const SCHEDULER_TOP_LEVEL_TASK_TITLE = 'ThreadControllerImpl::RunTask';
+
+ const SCHEDULOER_TOP_LEVEL_TASKS = new Set([
+ // Current title for the scheduler top level task.
+ SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ // Previous names scheduler top level tasks, kept for backwards
+ // compatibility.
+ 'ThreadControllerImpl::DoWork',
+ 'TaskQueueManager::ProcessTaskFromWorkQueue'
+ ]);
+
+ /**
+ * Utility class providing methods to efficiently find events.
+ * TODO(4023) This should be merged with thread/process helper.
+ */
+ class EventFinderUtils {
+ /**
+ * Returns true if |category| is one of the categories of |event|, and
+ * |event| has title |title|.
+ *
+ * TODO(dproy): Make this a method on a suitable parent class of the
+ * event/slice classes that are used with this function.
+ */
+ static hasCategoryAndName(event, category, title) {
+ return event.title === title && event.category &&
+ tr.b.getCategoryParts(event.category).includes(category);
+ }
+
+ /**
+ * Returns the list of main thread slices of |rendererHelper|
+ * with title |eventTitle| and category |eventCategory|.
+ * Returned slices do not include telemetry internal events.
+ *
+ * @param {tr.model.helpers.ChromeRendererHelper} rendererHelper
+ * @param {string} eventTitle
+ * @param {string} eventCategory
+ * @returns {Array<!tr.model.ThreadSlice>}
+ */
+ static* getMainThreadEvents(
+ rendererHelper, eventTitle, eventCategory) {
+ if (!rendererHelper.mainThread) return;
+ // Events yielded by childEvents() are sorted by start time.
+ for (const ev of rendererHelper.mainThread.sliceGroup.childEvents()) {
+ if (rendererHelper.isTelemetryInternalEvent(ev)) continue;
+ if (!this.hasCategoryAndName(ev, eventCategory, eventTitle)) {
+ continue;
+ }
+ yield ev;
+ }
+ }
+
+ /**
+ * Returns a map of frame id to main thread slices of |rendererHelper| with
+ * title |eventTitle| and categry |eventCategory|, sorted by start
+ * time. Returned slices do not include telemetry internal events.
+ *
+ * @param {tr.model.helpers.ChromeRendererHelper} rendererHelper
+ * @param {string} eventTitle
+ * @param {string} eventCategory
+ * @returns {Map.<string, Array<!tr.model.ThreadSlice>>}
+ */
+ static getSortedMainThreadEventsByFrame(
+ rendererHelper, eventTitle, eventCategory) {
+ const eventsByFrame = new Map();
+ const events = this.getMainThreadEvents(
+ rendererHelper, eventTitle, eventCategory);
+ for (const ev of events) {
+ const frameIdRef = ev.args.frame;
+ if (frameIdRef === undefined) continue;
+ if (!eventsByFrame.has(frameIdRef)) {
+ eventsByFrame.set(frameIdRef, []);
+ }
+ eventsByFrame.get(frameIdRef).push(ev);
+ }
+
+ return eventsByFrame;
+ }
+
+ /**
+ * Returns a map of navigation id to main thread slices of |rendererHelper|
+ * with title |eventTitle| and categry |eventCategory|.
+ * Returned slices do not include telemetry internal events.
+ *
+ * @param {tr.model.helpers.ChromeRendererHelper} rendererHelper
+ * @param {string} eventTitle
+ * @param {string} eventCategory
+ * @returns {Map.<string, tr.model.ThreadSlice>}
+ */
+ static getSortedMainThreadEventsByNavId(
+ rendererHelper, eventTitle, eventCategory) {
+ const eventsByNavId = new Map();
+ const events = this.getMainThreadEvents(
+ rendererHelper, eventTitle, eventCategory);
+ for (const ev of events) {
+ if (ev.args.data === undefined) continue;
+ const navIdRef = ev.args.data.navigationId;
+ if (navIdRef === undefined) continue;
+ eventsByNavId.set(navIdRef, ev);
+ }
+
+ return eventsByNavId;
+ }
+
+ /**
+ * Returns latest event in |sortedEvents| that starts on or before
+ * |timestamp|, or undefined if no such event exists.
+ *
+ * @param {!Array<!tr.model.TimedEvent>} sortedEvents - events sorted by
+ * start time.
+ * @param {number} timestamp
+ * @returns {tr.model.TimedEvent|undefined}
+ */
+ static findLastEventStartingOnOrBeforeTimestamp(sortedEvents, timestamp) {
+ const firstIndexAfterTimestamp =
+ tr.b.findFirstTrueIndexInSortedArray(
+ sortedEvents, e => e.start > timestamp);
+ // We found the first index after the timestamp, so the index immediately
+ // before it is the index we're looking for. If the first index after
+ // timestamp is 0, then there is no index on or before timestamp.
+ if (firstIndexAfterTimestamp === 0) return undefined;
+ return sortedEvents[firstIndexAfterTimestamp - 1];
+ }
+
+ /**
+ * Returns latest event in |sortedEvents| that starts before
+ * |timestamp|, or undefined if no such event exists.
+ *
+ * @param {!Array<!tr.model.TimedEvent>} sortedEvents - events sorted by
+ * start time.
+ * @param {number} timestamp
+ * @returns {tr.model.TimedEvent|undefined}
+ */
+ static findLastEventStartingBeforeTimestamp(sortedEvents, timestamp) {
+ const firstIndexAfterTimestamp =
+ tr.b.findFirstTrueIndexInSortedArray(
+ sortedEvents, e => e.start >= timestamp);
+ // We found the first index after the timestamp, so the index immediately
+ // before it is the index we're looking for. If the first index after
+ // timestamp is 0, then there is no index on or before timestamp.
+ if (firstIndexAfterTimestamp === 0) return undefined;
+ return sortedEvents[firstIndexAfterTimestamp - 1];
+ }
+
+
+ /**
+ * Returns earliest event in |sortedEvents| that starts on or after
+ * |timestamp|, or undefined if no such event exists.
+ *
+ * @param {!Array<!tr.model.TimedEvent>} sortedEvents - events sorted by
+ * start time.
+ * @param {number} timestamp
+ * @returns {tr.model.Event|undefined}
+ */
+ static findNextEventStartingOnOrAfterTimestamp(sortedEvents, timestamp) {
+ const firstIndexOnOrAfterTimestamp =
+ tr.b.findFirstTrueIndexInSortedArray(
+ sortedEvents, e => e.start >= timestamp);
+
+ if (firstIndexOnOrAfterTimestamp === sortedEvents.length) {
+ return undefined;
+ }
+ return sortedEvents[firstIndexOnOrAfterTimestamp];
+ }
+
+ /**
+ * Returns earliest event in |sortedEvents| that starts after |timestamp|,
+ * or undefined if no such event exists.
+ *
+ * @param {!Array<!tr.model.TimedEvent>} sortedEvents - events sorted by
+ * start time.
+ * @param {number} timestamp
+ * @returns {tr.model.Event|undefined}
+ */
+ static findNextEventStartingAfterTimestamp(sortedEvents, timestamp) {
+ const firstIndexOnOrAfterTimestamp =
+ tr.b.findFirstTrueIndexInSortedArray(
+ sortedEvents, e => e.start > timestamp);
+
+ if (firstIndexOnOrAfterTimestamp === sortedEvents.length) {
+ return undefined;
+ }
+ return sortedEvents[firstIndexOnOrAfterTimestamp];
+ }
+
+ /**
+ * Returns a list of top level scheduler tasks.
+ * It is used by TTI and EQT metrics.
+ * @param {!tr.model.Thread} mainThread - the main thead of the renderer.
+ * @returns {!Array<tr.model.Slice>}
+ */
+ static findToplevelSchedulerTasks(mainThread) {
+ const tasks = [];
+ tasks.push(...mainThread.findTopmostSlices(
+ slice => slice.category === 'toplevel' &&
+ SCHEDULOER_TOP_LEVEL_TASKS.has(slice.title)));
+ return tasks;
+ }
+ }
+
+ return {
+ EventFinderUtils,
+ CHROME_INTERNAL_URLS,
+ SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/event_finder_utils_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/event_finder_utils_test.html
new file mode 100644
index 00000000000..f3d078cceff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/event_finder_utils_test.html
@@ -0,0 +1,256 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+
+<script>
+'use strict';
+
+const EventFinderUtils = tr.e.chrome.EventFinderUtils;
+
+tr.b.unittest.testSuite(function() {
+ test('getSortedMainThreadEventsByFrame', () => {
+ const model = tr.c.TestUtils.newModel(model => {
+ const rendererProcess = model.getOrCreateProcess(1);
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0x0'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 300,
+ duration: 0.0,
+ args: {frame: '0x1'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 400,
+ duration: 0.0,
+ args: {frame: '0x0'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'devtools.timeline',
+ title: 'navigationStart',
+ start: 500,
+ duration: 0.0,
+ args: {frame: '0x0'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'firstPaint',
+ start: 600,
+ duration: 0.0,
+ args: {frame: '0x0'}
+ }));
+ });
+
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelper = chromeHelper.rendererHelpers[1];
+ const frameToSlices = EventFinderUtils.getSortedMainThreadEventsByFrame(
+ rendererHelper, 'navigationStart', 'blink.user_timing');
+
+ assert.strictEqual(frameToSlices.size, 2);
+ assert.strictEqual(frameToSlices.get('0x0').length, 2);
+ assert.strictEqual(frameToSlices.get('0x0')[0].start, 200);
+ assert.strictEqual(frameToSlices.get('0x0')[1].start, 400);
+ assert.strictEqual(frameToSlices.get('0x1').length, 1);
+ assert.strictEqual(frameToSlices.get('0x1')[0].start, 300);
+ });
+
+ test('getSortedMainThreadEventsByNavId', () => {
+ const model = tr.c.TestUtils.newModel(model => {
+ const rendererProcess = model.getOrCreateProcess(1);
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0x0', data: { navigationId: '0xa' }}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 300,
+ duration: 0.0,
+ args: {frame: '0x1', data: { navigationId: '0xb' }}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 400,
+ duration: 0.0,
+ args: {frame: '0x0', data: { navigationId: '0xc' }}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'devtools.timeline',
+ title: 'navigationStart',
+ start: 500,
+ duration: 0.0,
+ args: {frame: '0x0', data: { navigationId: '0xd' }}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'firstPaint',
+ start: 600,
+ duration: 0.0,
+ args: {frame: '0x0'}
+ }));
+ });
+
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelper = chromeHelper.rendererHelpers[1];
+ const navIdToSlices = EventFinderUtils.getSortedMainThreadEventsByNavId(
+ rendererHelper, 'navigationStart', 'blink.user_timing');
+
+ assert.strictEqual(navIdToSlices.size, 3);
+ assert.strictEqual(navIdToSlices.get('0xa').start, 200);
+ assert.strictEqual(navIdToSlices.get('0xb').start, 300);
+ assert.strictEqual(navIdToSlices.get('0xc').start, 400);
+ });
+
+ test('multipleCategoriesOnAnEvent', () => {
+ const model = tr.c.TestUtils.newModel(model => {
+ const rendererProcess = model.getOrCreateProcess(1);
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing,rail',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0x0'}
+ }));
+ });
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelper = chromeHelper.rendererHelpers[1];
+ const frameToSlices = EventFinderUtils.getSortedMainThreadEventsByFrame(
+ rendererHelper, 'navigationStart', 'blink.user_timing');
+
+ assert.strictEqual(frameToSlices.get('0x0')[0].start, 200);
+ });
+
+ test('findLastEventStartingOnOrBeforeTimestamp', () => {
+ const sortedEvents = [50, 100, 150, 200].map(ts =>
+ tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: ts,
+ duration: 40.0}));
+
+ assert.strictEqual(
+ EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(
+ sortedEvents, 100).start,
+ 100);
+ assert.strictEqual(
+ EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(
+ sortedEvents, 99).start,
+ 50);
+ assert.isUndefined(
+ EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(
+ sortedEvents, 49));
+ });
+
+ test('findNextEventStartingAfterTimestamp', () => {
+ const sortedEvents = [50, 50, 50, 200].map(ts =>
+ tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: ts,
+ duration: 40.0}));
+
+ assert.strictEqual(
+ EventFinderUtils.findNextEventStartingAfterTimestamp(
+ sortedEvents, 49).start,
+ 50);
+ assert.strictEqual(
+ EventFinderUtils.findNextEventStartingAfterTimestamp(
+ sortedEvents, 50).start,
+ 200);
+ assert.isUndefined(
+ EventFinderUtils.findNextEventStartingAfterTimestamp(
+ sortedEvents, 201));
+ });
+
+ test('findToplevelSchedulerTasks', () => {
+ const model = tr.c.TestUtils.newModel(model => {
+ const rendererProcess = model.getOrCreateProcess(1);
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: 'ThreadControllerImpl::RunTask',
+ start: 10,
+ duration: 1,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: 'ThreadControllerImpl::DoWork',
+ start: 20,
+ duration: 2,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: 'TaskQueueManager::ProcessTaskFromWorkQueue',
+ start: 30,
+ duration: 3,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: 'MessageLoop::RunTask',
+ start: 40,
+ duration: 4,
+ }));
+ // The category of 'ThreadControllerImpl::DoWork' slice was changed to
+ // 'sequence_manager' because it is not longer a scheduler top level task.
+ // See crbug.com/871204 for context.
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'sequence_manager',
+ title: 'ThreadControllerImpl::DoWork',
+ start: 50,
+ duration: 5,
+ }));
+ });
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelper = chromeHelper.rendererHelpers[1];
+ const tasks = EventFinderUtils.findToplevelSchedulerTasks(
+ rendererHelper.mainThread);
+
+ assert.strictEqual(tasks.length, 3);
+ assert.strictEqual(tasks[0].title,
+ 'ThreadControllerImpl::RunTask');
+ assert.strictEqual(tasks[0].start, 10);
+ assert.strictEqual(tasks[0].duration, 1);
+ assert.strictEqual(tasks[1].title,
+ 'ThreadControllerImpl::DoWork');
+ assert.strictEqual(tasks[1].start, 20);
+ assert.strictEqual(tasks[1].duration, 2);
+ assert.strictEqual(tasks[2].title,
+ 'TaskQueueManager::ProcessTaskFromWorkQueue');
+ assert.strictEqual(tasks[2].start, 30);
+ assert.strictEqual(tasks[2].duration, 3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice.html
new file mode 100644
index 00000000000..bfea13a7166
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/model/async_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.gpu', function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+
+ function GpuAsyncSlice() {
+ AsyncSlice.apply(this, arguments);
+ }
+
+ GpuAsyncSlice.prototype = {
+ __proto__: AsyncSlice.prototype,
+
+ get viewSubGroupTitle() {
+ if (this.args.channel) {
+ if (this.category === 'disabled-by-default-gpu.device') {
+ return 'Device.' + this.args.channel;
+ }
+ return 'Service.' + this.args.channel;
+ }
+ return this.title;
+ }
+ };
+
+ AsyncSlice.subTypes.register(
+ GpuAsyncSlice,
+ {
+ categoryParts: ['disabled-by-default-gpu.device',
+ 'disabled-by-default-gpu.service']
+ });
+
+ return {
+ GpuAsyncSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice_test.html
new file mode 100644
index 00000000000..53edf5ded5f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/gpu_async_slice_test.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/gpu/gpu_async_slice.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+ const GpuAsyncSlice = tr.e.gpu.GpuAsyncSlice;
+
+ test('construct', function() {
+ assert.strictEqual(AsyncSlice.subTypes.getConstructor(
+ 'disabled-by-default-gpu.device', 'gpu1'),
+ GpuAsyncSlice);
+ assert.strictEqual(AsyncSlice.subTypes.getConstructor(
+ 'disabled-by-default-gpu.service', 'gpu2'),
+ GpuAsyncSlice);
+ });
+
+ test('subgroup', function() {
+ const sDevice = new GpuAsyncSlice('disabled-by-default-gpu.device', 'gpu1',
+ 7, 0, {'channel': 'test_channel1'});
+
+ const sService = new GpuAsyncSlice(
+ 'disabled-by-default-gpu.service', 'gpu2', 7, 0,
+ {'channel': 'test_channel2'});
+
+ assert.strictEqual(sDevice.viewSubGroupTitle, 'Device.test_channel1');
+ assert.strictEqual(sService.viewSubGroupTitle, 'Service.test_channel2');
+ });
+
+ test('import', function() {
+ const events = [
+ {name: 'trace1', args: {}, pid: 1, ts: 100,
+ cat: 'disabled-by-default-gpu.service', tid: 2, ph: 'b', id: 71},
+ {name: 'trace1', args: {}, pid: 1, ts: 200,
+ cat: 'disabled-by-default-gpu.service', tid: 2, ph: 'e', id: 71},
+ {name: 'trace2', args: {'channel': 'test_channel'}, pid: 1, ts: 100,
+ cat: 'disabled-by-default-gpu.service', tid: 2, ph: 'b', id: 72},
+ {name: 'trace2', args: {'channel': 'test_channel'}, pid: 1, ts: 200,
+ cat: 'disabled-by-default-gpu.service', tid: 2, ph: 'e', id: 72},
+ {name: 'trace3', args: {'channel': 'test_channel'}, pid: 1, ts: 100,
+ cat: 'disabled-by-default-gpu.device', tid: 2, ph: 'b', id: 73},
+ {name: 'trace3', args: {'channel': 'test_channel'}, pid: 1, ts: 200,
+ cat: 'disabled-by-default-gpu.device', tid: 2, ph: 'e', id: 73}
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([events]);
+ const t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ assert.strictEqual(t2.asyncSliceGroup.length, 3);
+
+ const slice1 = t2.asyncSliceGroup.slices[0];
+ const slice2 = t2.asyncSliceGroup.slices[1];
+ const slice3 = t2.asyncSliceGroup.slices[2];
+
+ assert.instanceOf(slice1, GpuAsyncSlice);
+ assert.instanceOf(slice2, GpuAsyncSlice);
+ assert.instanceOf(slice3, GpuAsyncSlice);
+
+ assert.strictEqual(slice1.viewSubGroupTitle, 'trace1');
+ assert.strictEqual(slice2.viewSubGroupTitle, 'Service.test_channel');
+ assert.strictEqual(slice3.viewSubGroupTitle, 'Device.test_channel');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state.html
new file mode 100644
index 00000000000..b82c85abdf9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.gpu', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ /**
+ * @constructor
+ */
+ function StateSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ }
+
+ StateSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ preInitialize() {
+ this.screenshot_ = undefined;
+ },
+
+ initialize() {
+ if (this.args.screenshot) {
+ this.screenshot_ = this.args.screenshot;
+ }
+ },
+
+ /**
+ * @return {String} a base64 encoded screenshot if available.
+ */
+ get screenshot() {
+ return this.screenshot_;
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(
+ StateSnapshot,
+ {typeName: 'gpu::State'});
+
+ return {
+ StateSnapshot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state_test.html
new file mode 100644
index 00000000000..ac5f34dfe8c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state_test.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/gpu/state.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script src="/tracing/extras/chrome/gpu/state_test_data.js"></script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_gpuStateTrace]);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('gpu::State')[0];
+ const snapshot = instance.snapshots[0];
+
+ assert.instanceOf(snapshot, tr.e.gpu.StateSnapshot);
+ assert.typeOf(snapshot.screenshot, 'string');
+ instance.wasDeleted(150);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state_test_data.js b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state_test_data.js
new file mode 100644
index 00000000000..9327b49e8eb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/gpu/state_test_data.js
@@ -0,0 +1,22 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+const g_gpuStateTrace = [
+ {
+ 'cat': 'disabled-by-default-gpu.debug',
+ 'pid': 23969,
+ 'tid': 1799,
+ 'ts': 1427012847340,
+ 'ph': 'O',
+ 'name': 'gpu::State',
+ 'args': {
+ 'snapshot': {
+ 'screenshot': 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB90JCREbHlyxtxQAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAqUlEQVRIx+2WiwrAIAhF/f9vHmywQTMft8w2CJKIoPDozR50fmy0AcsAiMjs9UDOJgG4jwG8SMuUXoMAZcVYBmgPqDYNwLo3JHqcHufbRETZKireOSbDQAA+zgKE7lyiCQDtcQygS6PKYIp3vZ5MvgB0mhmQu8kcgAXE6bYBoZYFmPnhgg5n4En/h0RmvdmX3eKAMYZ3HtGD0+NU3w2BR795dPe/aANuuwDyW5SiCgNBiQAAAABJRU5ErkJggg==' // @suppress longLineCheck
+ }
+ },
+ 'id': '0x7d229bc0'
+ }
+];
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_object.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_object.html
new file mode 100644
index 00000000000..60911317e14
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_object.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.chrome', function() {
+ const KNOWN_PROPERTIES = {
+ absX: 1,
+ absY: 1,
+ address: 1,
+ anonymous: 1,
+ childNeeds: 1,
+ children: 1,
+ classNames: 1,
+ col: 1,
+ colSpan: 1,
+ float: 1,
+ height: 1,
+ htmlId: 1,
+ name: 1,
+ posChildNeeds: 1,
+ positioned: 1,
+ positionedMovement: 1,
+ relX: 1,
+ relY: 1,
+ relativePositioned: 1,
+ row: 1,
+ rowSpan: 1,
+ selfNeeds: 1,
+ stickyPositioned: 1,
+ tag: 1,
+ width: 1
+ };
+
+ function LayoutObject(snapshot, args) {
+ this.snapshot_ = snapshot;
+ this.id_ = args.address;
+ this.name_ = args.name;
+ this.childLayoutObjects_ = [];
+ this.otherProperties_ = {};
+ this.tag_ = args.tag;
+ this.relativeRect_ = tr.b.math.Rect.fromXYWH(
+ args.relX, args.relY, args.width, args.height);
+ this.absoluteRect_ = tr.b.math.Rect.fromXYWH(
+ args.absX, args.absY, args.width, args.height);
+ this.isFloat_ = args.float;
+ this.isStickyPositioned_ = args.stickyPositioned;
+ this.isPositioned_ = args.positioned;
+ this.isRelativePositioned_ = args.relativePositioned;
+ this.isAnonymous_ = args.anonymous;
+ this.htmlId_ = args.htmlId;
+ this.classNames_ = args.classNames;
+ this.needsLayoutReasons_ = [];
+ if (args.selfNeeds) {
+ this.needsLayoutReasons_.push('self');
+ }
+ if (args.childNeeds) {
+ this.needsLayoutReasons_.push('child');
+ }
+ if (args.posChildNeeds) {
+ this.needsLayoutReasons_.push('positionedChild');
+ }
+ if (args.positionedMovement) {
+ this.needsLayoutReasons_.push('positionedMovement');
+ }
+ this.tableRow_ = args.row;
+ this.tableCol_ = args.col;
+ this.tableRowSpan_ = args.rowSpan;
+ this.tableColSpan_ = args.colSpan;
+
+ if (args.children) {
+ args.children.forEach(function(child) {
+ this.childLayoutObjects_.push(new LayoutObject(snapshot, child));
+ }.bind(this));
+ }
+
+ for (const property in args) {
+ if (!KNOWN_PROPERTIES[property]) {
+ this.otherProperties_[property] = args[property];
+ }
+ }
+ }
+
+ LayoutObject.prototype = {
+ get snapshot() {
+ return this.snapshot_;
+ },
+
+ get id() {
+ return this.id_;
+ },
+
+ get name() {
+ return this.name_;
+ },
+
+ get tag() {
+ return this.tag_;
+ },
+
+ get relativeRect() {
+ return this.relativeRect_;
+ },
+
+ get absoluteRect() {
+ return this.absoluteRect_;
+ },
+
+ get isPositioned() {
+ return this.isPositioned_;
+ },
+
+ get isFloat() {
+ return this.isFloat_;
+ },
+
+ get isStickyPositioned() {
+ return this.isStickyPositioned_;
+ },
+
+ get isRelativePositioned() {
+ return this.isRelativePositioned_;
+ },
+
+ get isAnonymous() {
+ return this.isAnonymous_;
+ },
+
+ get tableRow() {
+ return this.tableRow_;
+ },
+
+ get tableCol() {
+ return this.tableCol_;
+ },
+
+ get tableRowSpan() {
+ return this.tableRowSpan_;
+ },
+
+ get tableColSpan() {
+ return this.tableColSpan_;
+ },
+
+ get htmlId() {
+ return this.htmlId_;
+ },
+
+ get classNames() {
+ return this.classNames_;
+ },
+
+ get needsLayoutReasons() {
+ return this.needsLayoutReasons_;
+ },
+
+ get hasChildLayoutObjects() {
+ return this.childLayoutObjects_.length > 0;
+ },
+
+ get childLayoutObjects() {
+ return this.childLayoutObjects_;
+ },
+
+ traverseTree(cb, opt_this) {
+ cb.call(opt_this, this);
+ if (!this.hasChildLayoutObjects) return;
+ this.childLayoutObjects.forEach(function(child) {
+ child.traverseTree(cb, opt_this);
+ });
+ },
+
+ get otherPropertyNames() {
+ const names = [];
+ for (const name in this.otherProperties_) {
+ names.push(name);
+ }
+ return names;
+ },
+
+ getProperty(name) {
+ return this.otherProperties_[name];
+ },
+
+ get previousSnapshotLayoutObject() {
+ if (!this.snapshot.previousSnapshot) return undefined;
+ return this.snapshot.previousSnapshot.getLayoutObjectById(this.id);
+ },
+
+ get nextSnapshotLayoutObject() {
+ if (!this.snapshot.nextSnapshot) return undefined;
+ return this.snapshot.nextSnapshot.getLayoutObjectById(this.id);
+ }
+ };
+
+ return {
+ LayoutObject,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_object_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_object_test.html
new file mode 100644
index 00000000000..d1c888f17ef
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_object_test.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/layout_object.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function FakeSnapshot() {
+ this.layoutObjectsById = {};
+ }
+ FakeSnapshot.prototype = {
+ getLayoutObjectById(id) {
+ return this.layoutObjectsById[id];
+ }
+ };
+
+ test('instantiate', function() {
+ const snapshot = new FakeSnapshot();
+ const layoutObject = new tr.e.chrome.LayoutObject(snapshot, {
+ address: 'deadbeef',
+ name: 'LayoutView',
+ other: 1,
+ children: [
+ {
+ address: 'beef2',
+ name: 'LayoutBlockFlow',
+ other: 2
+ }
+ ]
+ });
+ snapshot.layoutObjectsById[layoutObject.id] = layoutObject;
+
+ assert.strictEqual(snapshot, layoutObject.snapshot);
+ assert.strictEqual('LayoutView', layoutObject.name);
+ assert.strictEqual('deadbeef', layoutObject.id);
+ assert.strictEqual(1, layoutObject.otherPropertyNames.length);
+ assert.strictEqual(1, layoutObject.getProperty('other'));
+ assert.isTrue(layoutObject.hasChildLayoutObjects);
+ const child = layoutObject.childLayoutObjects[0];
+ assert.strictEqual('LayoutBlockFlow', child.name);
+ assert.strictEqual('beef2', child.id);
+ assert.strictEqual(1, child.otherPropertyNames.length);
+ assert.strictEqual(2, child.getProperty('other'));
+
+ assert.isUndefined(layoutObject.previousSnapshotLayoutObject);
+ assert.isUndefined(layoutObject.nextSnapshotLayoutObject);
+
+ let count = 0;
+ layoutObject.traverseTree(function(node) {
+ count += 1;
+ });
+ assert.strictEqual(2, count);
+
+ const nextSnapshot = new FakeSnapshot();
+ nextSnapshot.previousSnapshot = snapshot;
+ snapshot.nextSnapshot = nextSnapshot;
+
+ const nextLayoutObject = new tr.e.chrome.LayoutObject(nextSnapshot, {
+ address: 'deadbeef',
+ name: 'LayoutView'
+ });
+ nextSnapshot.layoutObjectsById[nextLayoutObject.id] = nextLayoutObject;
+
+ assert.strictEqual(layoutObject,
+ nextLayoutObject.previousSnapshotLayoutObject);
+ assert.strictEqual(nextLayoutObject, layoutObject.nextSnapshotLayoutObject);
+ assert.isUndefined(layoutObject.previousSnapshotLayoutObject);
+ assert.isUndefined(nextLayoutObject.nextSnapshotLayoutObject);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_tree.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_tree.html
new file mode 100644
index 00000000000..94a2f505d3c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/layout_tree.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_registry.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.chrome', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+ const ObjectInstance = tr.model.ObjectInstance;
+
+ function LayoutTreeInstance() {
+ ObjectInstance.apply(this, arguments);
+ }
+
+ LayoutTreeInstance.prototype = {
+ __proto__: ObjectInstance.prototype,
+ };
+
+ ObjectInstance.subTypes.register(
+ LayoutTreeInstance, {typeName: 'LayoutTree'});
+
+ function LayoutTreeSnapshot() {
+ ObjectSnapshot.apply(this, arguments);
+ this.rootLayoutObject = new tr.e.chrome.LayoutObject(this, this.args);
+ }
+
+ LayoutTreeSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+ };
+
+ ObjectSnapshot.subTypes.register(
+ LayoutTreeSnapshot, {typeName: 'LayoutTree'});
+
+ return {
+ LayoutTreeInstance,
+ LayoutTreeSnapshot,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/slice_title_fixer.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/slice_title_fixer.html
new file mode 100644
index 00000000000..5a4bc02f396
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/slice_title_fixer.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Some generic slice titles appear very frequently in traces,
+ * like MessageLoop::RunTask. Some of these slices have arguments that give
+ * useful context. This class combine such arguments with the slice title to
+ * generate a more useful title.
+ */
+tr.exportTo('tr.e.chrome', function() {
+ function SliceTitleFixer() {
+ }
+
+ // AsyncSlice uses virtual functions to accomplish something similar to what
+ // we're doing here. If this function ever becomes too complex we may consider
+ // using a similar pattern.
+ SliceTitleFixer.fromEvent = function(event) {
+ if (event.args && event.args.src_func) {
+ return event.title + ' <- ' + event.args.src_func;
+ }
+ return event.title;
+ };
+
+ return {
+ SliceTitleFixer,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/slice_title_fixer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/slice_title_fixer_test.html
new file mode 100644
index 00000000000..8b8ef3c9554
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/slice_title_fixer_test.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/slice_title_fixer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const stfFromEvent = tr.e.chrome.SliceTitleFixer.fromEvent;
+
+ test('sliceTitleFixer', function() {
+ assert.strictEqual(stfFromEvent({
+ title: 'SomeDummy:event'
+ }), 'SomeDummy:event');
+
+ assert.strictEqual(stfFromEvent({
+ title: 'EventWith:sourceFunction',
+ args: {'src_func': 'theSource'}
+ }), 'EventWith:sourceFunction <- theSource');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/time_to_interactive.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/time_to_interactive.html
new file mode 100644
index 00000000000..ea025e67697
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/time_to_interactive.html
@@ -0,0 +1,397 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.chrome', function() {
+ // Required quiet window size for Time to Interactive.
+ const TIME_TO_INTERACTIVE_WINDOW_SIZE_MS = 5000;
+
+ // Number of requests tolerated before network is considered busy.
+ const ACTIVE_REQUEST_TOLERANCE = 2;
+
+ // Minimum gap between task clusters for determining First CPU Idle.
+ const FCI_MIN_CLUSTER_SEPARATION_MS = 1000;
+
+ // Minimum duration of a task cluster to consider it heavy.
+ const TASK_CLUSTER_HEAVINESS_THRESHOLD_MS = 250;
+
+ /**
+ * Enum for endpoint types.
+ * @enum {string}
+ */
+ const ENDPOINT_TYPES = {
+ LONG_TASK_START: 'LONG_TASK_START',
+ LONG_TASK_END: 'LONG_TASK_END',
+ REQUEST_START: 'REQUEST_START',
+ REQUEST_END: 'REQUEST_END'
+ };
+
+ /**
+ * @typedef {Object} Endpoint
+ * @property {number} time - timestamp of endpoint.
+ * @property {string} type - A type defined in |ENDPOINT_TYPES|.
+ * originates from.
+ */
+
+ /**
+ * Returns an array of endpoints. An endpoint is either the start or end
+ * timestamp of a TimedEvent.
+ *
+ * @param {Array.<!tr.model.TimedEvent>} events - Events to extract endpoints
+ * from.
+ * @param {string} startType - Endpoint type for a start time endpoint.
+ * @param {string} endType - Endpoint type for an end time endpoint.
+ * @returns {Array.<!Endpoint>}
+ */
+ function getEndpoints_(events, startType, endType) {
+ const endpoints = [];
+ for (const event of events) {
+ endpoints.push({
+ time: event.start,
+ type: startType
+ });
+ endpoints.push({
+ time: event.end,
+ type: endType
+ });
+ }
+
+ return endpoints;
+ }
+
+ /**
+ * Returns true if at time |timestamp| we have a long enough quiet window for
+ * determining Time to Interactive.
+ *
+ * @param {number} timestamp - Timestamp of interest.
+ * @param {number} networkQuietWindowStart - Most recent timestamp when the
+ * renderer became network 2-quiet. Undefined if renderer is not network
+ * 2-quiet at |timestamp|.
+ * @param {number} mainThreadQuietWindowStart - End of most recent long task.
+ * Undefined if a long task is in progress at |timestamp|.
+ * @returns {boolean}
+ */
+ function reachedTTIQuiscence_(timestamp,
+ networkQuietWindowStart, mainThreadQuietWindowStart) {
+ if (networkQuietWindowStart === undefined ||
+ mainThreadQuietWindowStart === undefined) {
+ return false;
+ }
+
+ const mainThreadQuietForLongEnough =
+ timestamp - mainThreadQuietWindowStart >=
+ TIME_TO_INTERACTIVE_WINDOW_SIZE_MS;
+
+ const networkQuietForLongEnough =
+ timestamp - networkQuietWindowStart >=
+ TIME_TO_INTERACTIVE_WINDOW_SIZE_MS;
+
+ return mainThreadQuietForLongEnough && networkQuietForLongEnough;
+ }
+
+ /**
+ * Returns the timestamp for when the page first becomes Interactive.
+ *
+ * See https://goo.gl/IN68jL for detailed explanation of definition and
+ * motivations. This metric was previously known as "Consistently
+ * Interactive". To summarize, we look for a 5 second window starting from
+ * between |searchBegin| and |searchEnd| such that there is no long task
+ * overlapping with that window, and the entire window is network 2-quiet. A
+ * long task is defined as a main thread task with wall duration longer than
+ * 50ms, and network 2-quiet means the window never has more than 2 concurrent
+ * in-flight network requests. Interactive 'candidate' is defined as end of
+ * the last long task before this quiet window, or as |searchBegin| if there
+ * is no long task before that window. We define Interactive as max of
+ * Interactive candidate and domContentLoadedEnd.
+ *
+ * Returns undefined if no suitable quiet window is found.
+ *
+ * @param {number} searchBegin - The left boundary for our search for quiet
+ * window. Ideally, this is First Meaningful Paint, but if FMP is not
+ * available, First Contentful Paint or domContentLoadedEnd may be used as an
+ * approximation.
+ * @param {number} searchEnd - The right boundary for our search for quiet
+ * window. This is either the start of next navigationStart request, or end of
+ * traces.
+ * @param {number} domContentLoadedEnd - Timestamp of domContentLoadedEnd
+ * event for the main loading frame.
+ * @param {Array.<!tr.model.TimedEvent>} longTasks - Main thread tasks longer
+ * than 50ms overlapping with the search window.
+ * @param {Array.<!tr.model.TimedEvent>} networkRequests - Resource
+ * requests overlapping with the search window.
+ * @returns {number|undefined}
+ */
+ function findInteractiveTime(searchBegin, searchEnd,
+ domContentLoadedEnd, longTasksInWindow, networkRequests) {
+ // It is sufficient to only look at the end points of long tasks and network
+ // requests. These are the points where any meaningful changes happen.
+ const longTaskEndpoints = getEndpoints_(longTasksInWindow,
+ ENDPOINT_TYPES.LONG_TASK_START, ENDPOINT_TYPES.LONG_TASK_END);
+ const networkRequestEndpoints = getEndpoints_(networkRequests,
+ ENDPOINT_TYPES.REQUEST_START, ENDPOINT_TYPES.REQUEST_END);
+ const endpoints = longTaskEndpoints.concat(networkRequestEndpoints);
+ endpoints.sort((a, b) => a.time - b.time);
+
+ let networkQuietWindowStart = searchBegin;
+ let mainThreadQuietWindowStart = searchBegin;
+ let interactiveCandidate = undefined;
+ let activeRequests = 0;
+
+ for (const endpoint of endpoints) {
+ if (reachedTTIQuiscence_(endpoint.time,
+ networkQuietWindowStart, mainThreadQuietWindowStart)) {
+ interactiveCandidate = mainThreadQuietWindowStart;
+ break;
+ }
+
+ switch (endpoint.type) {
+ case ENDPOINT_TYPES.LONG_TASK_START:
+ mainThreadQuietWindowStart = undefined;
+ break;
+ case ENDPOINT_TYPES.LONG_TASK_END:
+ mainThreadQuietWindowStart = endpoint.time;
+ break;
+ case ENDPOINT_TYPES.REQUEST_START:
+ activeRequests++;
+ if (activeRequests > ACTIVE_REQUEST_TOLERANCE) {
+ networkQuietWindowStart = undefined;
+ }
+ break;
+ case ENDPOINT_TYPES.REQUEST_END:
+ activeRequests--;
+ if (activeRequests === ACTIVE_REQUEST_TOLERANCE) {
+ // Just became network 2-quiet.
+ networkQuietWindowStart = endpoint.time;
+ }
+ break;
+ default:
+ // This should never happen.
+ throw new Error('Internal Error: Unhandled endpoint type.');
+ }
+ }
+
+ if (interactiveCandidate === undefined &&
+ reachedTTIQuiscence_(searchEnd,
+ networkQuietWindowStart, mainThreadQuietWindowStart)) {
+ interactiveCandidate = mainThreadQuietWindowStart;
+ }
+
+ if (interactiveCandidate === undefined) return undefined;
+
+ return Math.max(interactiveCandidate, domContentLoadedEnd);
+ }
+
+ /**
+ * Returns the required quiet window size for First CPU Idle at
+ * |timeSinceSearchBeginMs| after searchBegin.
+ *
+ * Required quiet window size is modeled as an exponential decay. See
+ * https://goo.gl/kQXGLW for development of the exact equation used here.
+ *
+ * @param {number} timeSinceSearchBeginMs - Time since the beginning of search
+ * window for First CPU Idle.
+ */
+ function requiredFCIWindowSizeMs(timeSinceSearchBeginMs) {
+ const timeCoefficient = 1 / 15 * Math.log(2);
+
+ const timeSinceSearchBeginSeconds = tr.b.convertUnit(timeSinceSearchBeginMs,
+ tr.b.UnitPrefixScale.METRIC.MILLI, tr.b.UnitPrefixScale.METRIC.NONE);
+ const windowSizeSeconds =
+ 4 * Math.exp(- timeCoefficient * timeSinceSearchBeginSeconds) + 1;
+ return tr.b.convertUnit(windowSizeSeconds,
+ tr.b.UnitPrefixScale.METRIC.NONE, tr.b.UnitPrefixScale.METRIC.MILLI);
+ }
+
+ /**
+ * TaskCluster represents a group of long tasks such that they are at least 1s
+ * away from any other long task that is not in the group.
+ *
+ * A TaskCluster instance is meant to be immutable once constructed.
+ */
+ class TaskCluster {
+ /**
+ * Create a TaskCluster.
+ * @param {Array.<!tr.model.TimedEvent>} tasksInClusterSorted - Tasks in the
+ * cluster. Assumed sorted by start time.
+ */
+ constructor(tasksInClusterSorted) {
+ if (tasksInClusterSorted.length === 0) {
+ throw new Error('Internal Error: TaskCluster must have non zero tasks');
+ }
+
+ for (let i = 0; i < tasksInClusterSorted.length - 1; i++) {
+ const durationBetweenTasks = tasksInClusterSorted[i + 1].start -
+ tasksInClusterSorted[i].end;
+ if (durationBetweenTasks >= FCI_MIN_CLUSTER_SEPARATION_MS) {
+ throw new Error('Internal Error: Tasks in a TaskCluster cannot be ' +
+ 'more than ' + FCI_MIN_CLUSTER_SEPARATION_MS +
+ ' miliseconds apart');
+ }
+
+ // Ideally the condition below should be durationBetweenTasks < 0, but
+ // sometimes, for rounding errors, the end time of one task may very
+ // slightly extend past the start time of the next.
+ if (durationBetweenTasks < -1e7) {
+ throw new Error('Internal Error: List of tasks used to construct ' +
+ 'TaskCluster must be sorted.');
+ }
+ }
+
+ this._clusterTasks = tasksInClusterSorted;
+ }
+
+ /**
+ * @type{number}
+ */
+ get start() {
+ return this._clusterTasks[0].start;
+ }
+
+ /**
+ * @type{number}
+ */
+ get end() {
+ return this._clusterTasks[this._clusterTasks.length - 1].end;
+ }
+
+ /**
+ * @returns {boolean}
+ */
+ isHeavy() {
+ return this.end - this.start > TASK_CLUSTER_HEAVINESS_THRESHOLD_MS;
+ }
+ }
+
+
+ /**
+ * Returns all the task clusters of |sortedLongTasks|.
+ *
+ * @param {Array.<!tr.model.TimedEvent>} sortedLongTasks - Main thread tasks
+ * longer than 50ms, sorted by task start time.
+ * @returns {Array.<!TaskCluster>}
+ */
+ function findFCITaskClusters(sortedLongTasks) {
+ const clusters = [];
+ if (sortedLongTasks.length === 0) return clusters;
+
+ const firstTask = sortedLongTasks[0];
+ const restOfTasks = sortedLongTasks.slice(1);
+
+ let currentClusterTasks = [firstTask];
+
+ for (const currTask of restOfTasks) {
+ const prevTask = currentClusterTasks[currentClusterTasks.length - 1];
+ if (currTask.start - prevTask.end < FCI_MIN_CLUSTER_SEPARATION_MS) {
+ // Add task to current task cluster.
+ currentClusterTasks.push(currTask);
+ } else {
+ // Wrap up the current cluster and add task to a fresh cluster.
+ clusters.push(new TaskCluster(currentClusterTasks));
+ currentClusterTasks = [currTask];
+ }
+ }
+
+ clusters.push(new TaskCluster(currentClusterTasks));
+
+ return clusters;
+ }
+
+ /**
+ * Returns true if at time |timestamp|, assuming |timestamp| is not in the
+ * middle of a heavy task cluster, we have a long enough quiet window for
+ * determining First CPU Idle.
+ *
+ * @param {number} timestamp - Timestamp of interest. We assume |timestamp| is
+ * not in the middle of a heavy task cluster.
+ * @param {number} mainThreadQuietWindowStart - Most recent timestamp when we
+ * considered the main thread to be quiet. Usually end of most recent
+ * heavy task cluster or |searchBegin| where there are no heavy task
+ * cluster.
+ * @param {number} searchBegin - Left boundary for quiet window search.
+ * @returns {boolean}
+ */
+ function reachedFCIQuiescence_(timestamp, mainThreadQuietWindowStart,
+ searchBegin) {
+ const quietWindowSize = timestamp - mainThreadQuietWindowStart;
+ const timeSinceSearchBegin = mainThreadQuietWindowStart - searchBegin;
+ const requiredWindowSize = requiredFCIWindowSizeMs(timeSinceSearchBegin);
+ return quietWindowSize > requiredWindowSize;
+ }
+
+ /**
+ * Returns the timestamp for First CPU Idle for a page.
+ *
+ * See https://goo.gl/1a1XwZ for definition, and https://goo.gl/IN68jL for an
+ * explanation of how the definition was developed. This metric was previously
+ * known as "First Interactive". To summarize, in order to find First
+ * Interactive we look for a long enough window between |searchBegin| and
+ * |searchEnd| such that it doesn't contain a heavy task cluster. The required
+ * length of the window decreases the further we move away from |searchBegin|.
+ * A "task cluster" is defined as a group of long tasks such that they are at
+ * least 1s away from any other long task that is not in the group. A task
+ * cluster is considered "heavy" if the duration of the task cluster (the time
+ * interval from the beginning of first task to the end of last task) is
+ * longer than 250ms. We call the beginning of the quiet window FCI candidate,
+ * and define First Cpu Idle as max of FCI candidate and
+ * domContentLoadedEnd.
+ *
+ * Returns undefined if no suitable quiet window is found.
+ *
+ * @param {number} searchBegin - The left boundary for our search for quiet
+ * window. Ideally, this is First Meaningful Paint, but if FMP is not
+ * available, First Contentful Paint or domContentLoadedEnd may be used as
+ * an approximation.
+ * @param {number} searchEnd - The right boundary for our search for quiet
+ * window. This is either the start of next navigationStart request, or
+ * end of traces.
+ * @param {number} domContentLoadedEnd - Timestamp of domContentLoadedEnd
+ * event for the main loading frame.
+ * @param {Array.<!tr.model.TimedEvent>} longTasks - Main thread tasks longer
+ * than 50ms overlapping with the search window.
+ * @returns {number|undefined}
+ */
+ function findFirstCpuIdleTime(searchBegin, searchEnd,
+ domContentLoadedEnd, longTasksInWindow) {
+ const sortedLongTasks = longTasksInWindow.sort((a, b) => a.start - b.start);
+ const taskClusters = findFCITaskClusters(sortedLongTasks);
+ const heavyTaskClusters = taskClusters.filter(cluster => cluster.isHeavy());
+
+ let quietWindowBegin = searchBegin;
+ let fiCandidate = undefined;
+ for (const cluster of heavyTaskClusters) {
+ if (reachedFCIQuiescence_(cluster.start, quietWindowBegin, searchBegin)) {
+ fiCandidate = quietWindowBegin;
+ break;
+ }
+ quietWindowBegin = cluster.end;
+ }
+
+ if (fiCandidate === undefined) {
+ // Check if quiescence was reached at the end of the search window.
+ if (reachedFCIQuiescence_(searchEnd, quietWindowBegin, searchBegin)) {
+ fiCandidate = quietWindowBegin;
+ } else {
+ // We never reached quiescence.
+ return undefined;
+ }
+ }
+
+ return Math.max(fiCandidate, domContentLoadedEnd);
+ }
+
+ return {
+ findInteractiveTime,
+ findFirstCpuIdleTime,
+ requiredFCIWindowSizeMs,
+ findFCITaskClusters,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome/time_to_interactive_test.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome/time_to_interactive_test.html
new file mode 100644
index 00000000000..655bd23fc25
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome/time_to_interactive_test.html
@@ -0,0 +1,329 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/time_to_interactive.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const findInteractiveTime = tr.e.chrome.findInteractiveTime;
+ const findFirstCpuIdleTime = tr.e.chrome.findFirstCpuIdleTime;
+ const requiredFCIWindowSizeMs = tr.e.chrome.requiredFCIWindowSizeMs;
+ const findFCITaskClusters = tr.e.chrome.findFCITaskClusters;
+
+ test('findInteractiveTime_' +
+ 'doesNotWaitForTasksFarAwayWithoutNetworkRequests', () => {
+ const longTasks = [
+ {start: 50, end: 200},
+ {start: 300, end: 400},
+ // More than 5000ms gap here.
+ {start: 7000, end: 7200}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.closeTo(
+ findInteractiveTime(0, 10000, 50, longTasks, []),
+ 400, 1e-7);
+ });
+
+ test('findInteractiveTime_' +
+ 'waitsForTasksFarAwayWhenNetworkIsBusy', () => {
+ const longTasks = [
+ {start: 50, end: 200},
+ {start: 300, end: 400},
+ // More than 5000ms gap here.
+ {start: 7000, end: 7200}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ const networkRequests = [
+ {start: 300, end: 3000},
+ {start: 500, end: 2900},
+ {start: 600, end: 3100},
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ // Last network 2-quiet region starts at 2900, while the next long task
+ // starts at 7000. We don't have 5 seconds of quiet window before that long
+ // task.
+ assert.closeTo(findInteractiveTime(
+ 0, 20000, 50, longTasks, networkRequests), 7200, 1e-7);
+ });
+
+ test('findInteractiveTime_' +
+ 'noQuietWindowBecauseOfLongTask', () => {
+ const longTasks = [
+ {start: 50, end: 200},
+ {start: 300, end: 400},
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ // windowEnd is 2400, so we don't get 5 seconds on quiet window after 400.
+ assert.isUndefined(findInteractiveTime(
+ 0, 2400, 50, longTasks, []));
+ });
+
+ test('findInteractiveTime_' +
+ 'noQuietWindowBecauseOfNetwork', () => {
+ const networkRequests = [
+ {start: 50, end: 200},
+ {start: 51, end: 300},
+ {start: 52, end: 400},
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ // windowEnd is 2200, and beginning of last network 2-quiet region is 200.
+ // We don't have a 5 second quiet window.
+ assert.isUndefined(findInteractiveTime(
+ 0, 2200, 50, [], networkRequests));
+ });
+
+ test('findInteractiveTime_' +
+ 'network2QuietHappensAfterLastLongTask', () => {
+ const longTasks = [
+ {start: 50, end: 200},
+ {start: 300, end: 400},
+ // More than 5000ms gap here.
+ {start: 7000, end: 7200}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ const networkRequests = [
+ {start: 300, end: 8000},
+ {start: 500, end: 8100},
+ {start: 600, end: 8300},
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.closeTo(findInteractiveTime(
+ 0, 20000, 50, longTasks, networkRequests), 7200, 1e-7);
+ });
+
+
+ test('findInteractiveTime_' +
+ 'longEnoughNetwork2QuietBeforeLastLongTask', () => {
+ const longTasks = [
+ {start: 50, end: 200},
+ {start: 300, end: 400},
+ // More than 5000ms gap here.
+ {start: 7000, end: 7200}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ const networkRequests = [
+ {start: 300, end: 1000},
+ {start: 500, end: 1100},
+ {start: 600, end: 1200},
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+
+ // 1000ms is the beginning of last network 2-quiet region, and we have a 5s
+ // window between that and the start of next long task.
+ assert.closeTo(findInteractiveTime(
+ 0, 20000, 50, longTasks, networkRequests), 400, 1e-7);
+ });
+
+ test('findInteractiveTime_' +
+ 'isLowerBoundedAtDCL', () => {
+ const longTasks = [
+ {start: 50, end: 200}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ // End of last long task is 200, but FCI is still 5000 because of
+ // DOMContentLoadedEnd being at 5000.
+ assert.closeTo(findInteractiveTime(
+ 0, 20000, 5000, longTasks, []), 5000, 1e-7);
+ });
+
+
+ test('findInteractiveTime_' +
+ 'returnsWindowStartWhenNoLongTasks', () => {
+ // Note that it is possible for DOMContentLoadedEnd to happen before
+ // windowStart, since windowStart is usually First Meaningful Paint. If
+ // there are no long tasks, and DCL is before windowStart, FCI should be
+ // windowStart.
+ assert.closeTo(findInteractiveTime(
+ 1000, 20000, 500, [], []), 1000, 1e-7);
+ });
+
+ test('findInteractiveTime' +
+ 'networkRequestStartsBeforeWindowStart', () => {
+ const longTasks = [
+ {start: 7000, end: 7200}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ const networkRequests = [
+ {start: 0, end: 6000},
+ {start: 10, end: 6100},
+ {start: 20, end: 6200}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ // windowStart is now 1000. All three network requests start before
+ // windowStart, but should still manage to block netowrk 2-quiet.
+ assert.closeTo(findInteractiveTime(
+ 1000, 20000, 1050, longTasks, networkRequests), 7200, 1e-7);
+ });
+
+ test('requiredFCIWindowSizeMs', () => {
+ // The required window size function is an exponential decay, and is
+ // uniquely determined by values at three points.
+ assert.closeTo(requiredFCIWindowSizeMs(0), 5000, 1e-7);
+ assert.closeTo(requiredFCIWindowSizeMs(15000), 3000, 1e-7);
+ assert.closeTo(requiredFCIWindowSizeMs(Infinity), 1000, 1e-7);
+ });
+
+ test('findFCITaskClusters_MultipleLongTasks', () => {
+ const longTasks = [
+ {start: 50, end: 200},
+ {start: 500, end: 700},
+ {start: 1710, end: 1800},
+ {start: 1900, end: 2000},
+ {start: 2200, end: 2300},
+ {start: 5000, end: 5100},
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ const clusters = findFCITaskClusters(longTasks);
+ assert.strictEqual(clusters.length, 3);
+ assert.strictEqual(clusters[0].start, 50);
+ assert.strictEqual(clusters[0].end, 700);
+ assert.strictEqual(clusters[1].start, 1710);
+ assert.strictEqual(clusters[1].end, 2300);
+ assert.strictEqual(clusters[2].start, 5000);
+ assert.strictEqual(clusters[2].end, 5100);
+ });
+
+ test('findFCITaskClusters_NoLongTasks', () => {
+ const clusters = findFCITaskClusters([]);
+ assert.strictEqual(clusters.length, 0);
+ });
+
+ test('findFirstInteractiveTimestamp_noLongTasks', () => {
+ const searchBegin = 0;
+ const searchEnd = 20000;
+ const dclEnd = 0;
+ const longTasks = [];
+
+ assert.closeTo(findFirstCpuIdleTime(searchBegin, searchEnd, dclEnd,
+ longTasks), 0, 1e-7);
+ });
+
+ test('findFirstCpuIdleTime_' +
+ 'firstInteractiveReachedInBetweenTaskClusters', () => {
+ const searchBegin = 0;
+ const searchEnd = 20000;
+ const dclEnd = 0;
+ const longTasks = [
+ // Cluster 1.
+ {start: 50, end: 150},
+ {start: 200, end: 300},
+ {start: 500, end: 700},
+ // Cluster 2.
+ {start: 2000, end: 2100},
+ {start: 2900, end: 3000},
+ // Cluster 3.
+ {start: 8000, end: 8100},
+ {start: 8200, end: 8500},
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.closeTo(findFirstCpuIdleTime(searchBegin, searchEnd, dclEnd,
+ longTasks), 3000, 1e-7);
+ });
+
+ test('findFirstCpuIdleTime_' +
+ 'FirstInteractiveReachedAfterLastHeavyCluster', () => {
+ const searchBegin = 0;
+ const searchEnd = 20000;
+ const dclEnd = 0;
+ const longTasks = [
+ // Cluster 1.
+ {start: 1000, end: 1100},
+ {start: 1150, end: 1350},
+ // Cluster 2.
+ {start: 4000, end: 4400},
+ // Cluster 3.
+ {start: 7000, end: 7400}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.closeTo(findFirstCpuIdleTime(searchBegin, searchEnd, dclEnd,
+ longTasks), 7400, 1e-7);
+ });
+
+
+ test('findFirstInteractiveTimestamp_noFirstInteractiveReached', () => {
+ const searchBegin = 0;
+ const searchEnd = 10000;
+ const dclEnd = 0;
+ const longTasks = [
+ // Four spaced out heavy task clusters.
+ {start: 2000, end: 2300},
+ {start: 4000, end: 4300},
+ {start: 6000, end: 6300},
+ {start: 8000, end: 8300}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.isUndefined(findFirstCpuIdleTime(searchBegin, searchEnd,
+ dclEnd, longTasks));
+ });
+
+ test('findFirstInteractiveTimestamp_lowerBoundedAtDCL', () => {
+ const searchBegin = 0;
+ const searchEnd = 10000;
+ const dclEnd = 8500;
+ const longTasks = [
+ {start: 2000, end: 2100},
+ {start: 4000, end: 4100}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.closeTo(findFirstCpuIdleTime(searchBegin, searchEnd, dclEnd,
+ longTasks), dclEnd, 1e-7);
+ });
+
+ test('findFirstInteractiveTimestamp_doesNotAssumeLongTasksAreSorted', () => {
+ const searchBegin = 0;
+ const searchEnd = 20000;
+ const dclEnd = 0;
+ const longTasks = [
+ {start: 2000, end: 2400},
+ {start: 1000, end: 1400}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.closeTo(findFirstCpuIdleTime(searchBegin, searchEnd, dclEnd,
+ longTasks), 2400, 1e-7);
+ });
+
+ test('findFirstCpuIdleTime_' +
+ 'lightTaskClustersDoesNotBlockFirstInteractive', () => {
+ const searchBegin = 0;
+ const searchEnd = 20000;
+ const dclEnd = 0;
+ const longTasks = [
+ // Cluster 1 - heavy (duration 350ms).
+ {start: 1000, end: 1100},
+ {start: 1150, end: 1350},
+ // Cluster 2 - light (duration 200ms).
+ {start: 4000, end: 4200},
+ // Cluster 3 - heavy (duration 400ms).
+ {start: 7000, end: 7400}
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.closeTo(findFirstCpuIdleTime(searchBegin, searchEnd, dclEnd,
+ longTasks), 1350, 1e-7);
+ });
+
+ test('findFirstCpuIdleTime_' +
+ 'requiredWindowSizeIsAtLeast5sAtTheBeginning', () => {
+ // Search begin intentionally not 0 to catch errors in calculating
+ // timeSinceSearchBegin.
+ const searchBegin = 10000;
+ const searchEnd = 30000;
+ const dclEnd = 5000;
+ const longTasks = [
+ // Heavy Task Cluster (duration 501ms). Starts 4999 ms after
+ // |searchBegin|.
+ {start: 14999, end: 15100},
+ {start: 15200, end: 15500},
+ ].map(options => tr.c.TestUtils.newSliceEx(options));
+
+ assert.closeTo(findFirstCpuIdleTime(searchBegin, searchEnd, dclEnd,
+ longTasks), 15500, 1e-7);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/chrome_config.html b/chromium/third_party/catapult/tracing/tracing/extras/chrome_config.html
new file mode 100644
index 00000000000..f6969a549cc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/chrome_config.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+The chrome config is heavily used:
+ - chrome://tracing,
+ - trace2html, which in turn implies
+ - adb_profile_chrome
+ - telemetry
+-->
+
+<link rel="import" href="/tracing/extras/android/android_auditor.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/blame_context.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/frame_tree_node.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/render_frame.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/top_level.html">
+<link rel="import" href="/tracing/extras/chrome/blink/blink_scheduler_async_slice.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_auditor.html">
+<link rel="import" href="/tracing/extras/chrome/layout_object.html">
+<link rel="import" href="/tracing/extras/chrome/layout_tree.html">
+<link rel="import" href="/tracing/extras/cpu/cpu_usage_auditor.html">
+<link rel="import" href="/tracing/extras/importer/etw/etw_importer.html">
+<link rel="import" href="/tracing/extras/importer/fuchsia_importer.html">
+<link rel="import" href="/tracing/extras/importer/gzip_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace2html_importer.html">
+<link rel="import" href="/tracing/extras/importer/v8/v8_log_importer.html">
+<link rel="import" href="/tracing/extras/importer/zip_importer.html">
+<link rel="import" href="/tracing/extras/lean_config.html">
+<link rel="import" href="/tracing/extras/measure/measure.html">
+<link rel="import" href="/tracing/extras/net/net.html">
+<link rel="import" href="/tracing/extras/systrace_config.html">
+<link rel="import" href="/tracing/extras/v8_config.html">
+<link rel="import" href="/tracing/extras/vsync/vsync_auditor.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/cpu/cpu_usage_auditor.html b/chromium/third_party/catapult/tracing/tracing/extras/cpu/cpu_usage_auditor.html
new file mode 100644
index 00000000000..d32e69cc998
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/cpu/cpu_usage_auditor.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/core/auditor.html">
+<link rel="import" href="/tracing/model/resource_usage_series.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.audits', function() {
+ /**
+ * Auditor that analyzes the model and, if possible, adds data to it
+ * showing CPU usage.
+ */
+ class CpuUsageAuditor extends tr.c.Auditor {
+ constructor(model) {
+ super();
+ this.model_ = model;
+ }
+
+ runAnnotate() {
+ this.model_.device.cpuUsageSeries = this.computeCpuUsageSeries_(
+ this.model_.bounds.min, this.model_.bounds.max,
+ this.computeCpuUsage_());
+ }
+
+ /**
+ * Compute the bin size given the start and end times of the trace.
+ */
+ computeBinSize_(start, end) {
+ const MIN_BIN_SIZE_MS = 1.0;
+ const MAX_NUM_BINS = 100000;
+ const interval = end - start;
+ let binSize = MIN_BIN_SIZE_MS;
+ while (binSize * MAX_NUM_BINS < interval) binSize *= 2;
+ return binSize;
+ }
+
+ /**
+ * Returns a CPU usage series from a given set of CPU usage slices.
+ * Slices are in the format created by getCpuUsage below.
+ */
+ computeCpuUsageSeries_(start, end, usageRecords) {
+ const series = new tr.model.ResourceUsageSeries();
+ if (start === undefined || usageRecords.length === 0) return series;
+ const binSize = this.computeBinSize_(start, end);
+ const numBins = Math.ceil((end - start) / binSize);
+ const arr = new Array(numBins).fill(0);
+ for (const record of usageRecords) {
+ const firstIndex = Math.ceil((record.start - start) / binSize);
+ const lastIndex = Math.floor((record.end - start) / binSize);
+ for (let i = firstIndex; i <= lastIndex; i++) arr[i] += record.usage;
+ }
+ for (let i = 0; i < numBins; i++) {
+ series.addUsageSample(start + (i * binSize), arr[i]);
+ }
+ return series;
+ }
+
+ /**
+ * Returns a list of CPU usage slices based on tracing data. Thus, this
+ * effectively counts only processes that are traced (will not count
+ * e.g. background processes)
+ */
+ computeCpuUsage_() {
+ const model = this.model_;
+ const result = [];
+ for (const pid in model.processes) {
+ for (const e of model.processes[pid].getDescendantEvents()) {
+ if (!(e instanceof tr.model.ThreadSlice) || e.duration === 0 ||
+ e.cpuDuration === undefined) {
+ continue;
+ }
+
+ // This slice contains the most fine-grained CPU usage information
+ // for the area of the trace that it covers but that is not covered
+ // by its subslices.
+ // The math goes this way:
+ // s.selfTime : duration of slice s not spent in its subslices.
+ // s.cpuSelfTime : cpuDuration over slice s but not its subslices.
+ //
+ // We're looking for
+ // s.cpuSelfTimeRatio: average CPU usage over the area covered by
+ // s but not any of its subslices.
+ // = s.cpuSelfTime / s.selfTime
+ if (e.selfTime === 0 || e.selfTime === undefined ||
+ e.cpuSelfTime === undefined) {
+ continue;
+ }
+ const usage = tr.b.math.clamp(e.cpuSelfTime / e.selfTime, 0, 1);
+
+ // Go through the area covered by this slice but not its subslices
+ // and add the cpuSelfTimeRatio contribution over this area.
+ let lastTime = e.start;
+ for (const subslice of e.subSlices) {
+ result.push({usage, start: lastTime, end: subslice.start});
+ lastTime = subslice.end;
+ }
+ result.push({usage, start: lastTime, end: e.end});
+ }
+ }
+ return result;
+ }
+ }
+
+ tr.c.Auditor.register(CpuUsageAuditor);
+
+ return {
+ CpuUsageAuditor
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/full_config.html b/chromium/third_party/catapult/tracing/tracing/extras/full_config.html
new file mode 100644
index 00000000000..2f157189922
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/full_config.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!-- The full config is all the configs slammed together. -->
+<link rel="import" href="/tracing/extras/chrome_config.html">
+<link rel="import" href="/tracing/extras/importer/gcloud_trace/gcloud_trace_importer.html">
+<link rel="import" href="/tracing/extras/lean_config.html">
+<link rel="import" href="/tracing/extras/systrace_config.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/android/atrace_process_dump_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/atrace_process_dump_importer.html
new file mode 100644
index 00000000000..518adfc2f35
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/atrace_process_dump_importer.html
@@ -0,0 +1,216 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.importer.android.atrace_process_dump', function() {
+ const IMPORT_PRIORITY = tr.e.importer.linux_perf.IMPORT_PRIORITY + 1;
+ const HEADER = 'ATRACE_PROCESS_DUMP';
+
+ const PROTECTION_FLAG_LETTERS = {
+ '-': 0,
+ 'r': tr.model.VMRegion.PROTECTION_FLAG_READ,
+ 'w': tr.model.VMRegion.PROTECTION_FLAG_WRITE,
+ 'x': tr.model.VMRegion.PROTECTION_FLAG_EXECUTE,
+ 's': tr.model.VMRegion.PROTECTION_FLAG_MAYSHARE,
+ };
+
+ class AtraceProcessDumpImporter extends tr.importer.Importer {
+ constructor(model, data) {
+ super(model, data);
+ this.importPriority = IMPORT_PRIORITY;
+ this.model_ = model;
+ this.raw_data_ = data;
+ this.clock_sync_markers_ = {};
+ this.snapshots_ = [];
+ this.processes_ = {};
+ }
+
+ static canImport(events) {
+ if (!(typeof(events) === 'string' || events instanceof String)) {
+ return false;
+ }
+ return events.startsWith(HEADER);
+ }
+
+ get importerName() {
+ return 'AtraceProcessDumpImporter';
+ }
+
+ get model() {
+ return this.model_;
+ }
+
+ lazyParseData() {
+ if (this.raw_data_ === undefined) {
+ return;
+ }
+ const dump = JSON.parse(this.raw_data_.slice(HEADER.length + 1));
+ this.clock_sync_markers_ = dump.clock_sync_markers;
+ this.snapshots_ = dump.dump.snapshots;
+ this.processes_ = dump.dump.processes;
+ this.raw_data_ = undefined;
+ }
+
+ importClockSyncMarkers() {
+ this.lazyParseData();
+ for (const syncId in this.clock_sync_markers_) {
+ const ts = parseInt(this.clock_sync_markers_[syncId]);
+ this.model_.clockSyncManager.addClockSyncMarker(
+ tr.model.ClockDomainId.LINUX_CLOCK_MONOTONIC, syncId, ts);
+ }
+ }
+
+ setProcessMemoryDumpTotals_(pmd, processInfo) {
+ pmd.totals = {
+ 'residentBytes': processInfo.rss * 1024,
+ 'platformSpecific': {
+ 'vm': processInfo.vm * 1024
+ }
+ // TODO(kraynov): Add OOM scores and make UI able to show it.
+ };
+ const totals = pmd.totals.platformSpecific;
+
+ function importGpuMetric(name) {
+ if (processInfo[name] !== undefined && processInfo[name] > 0) {
+ totals[name] = processInfo[name] * 1024;
+ totals[name + '_pss'] = processInfo[name + '_pss'] * 1024;
+ }
+ }
+ importGpuMetric('gpu_egl');
+ importGpuMetric('gpu_gl');
+ importGpuMetric('gpu_etc');
+
+ if (processInfo.pss !== undefined) {
+ // Full stats.
+ totals.pss = processInfo.pss * 1024;
+ totals.swp = processInfo.swp * 1024;
+ totals.pc = processInfo.pc * 1024;
+ totals.pd = processInfo.pd * 1024;
+ totals.sc = processInfo.sc * 1024;
+ totals.sd = processInfo.sd * 1024;
+ }
+ }
+
+ setProcessMemoryDumpVmRegions_(pmd, processInfo) {
+ if (processInfo.mmaps === undefined) {
+ return;
+ }
+ const vmRegions = [];
+ for (const memoryMap of processInfo.mmaps) {
+ const addr = memoryMap.vm.split('-').map(x => parseInt(x, 16));
+ let flags = 0;
+ for (const letter of memoryMap.flags) {
+ flags |= PROTECTION_FLAG_LETTERS[letter];
+ }
+ const totals = {
+ 'proportionalResident': memoryMap.pss * 1024,
+ 'privateCleanResident': memoryMap.pc * 1024,
+ 'privateDirtyResident': memoryMap.pd * 1024,
+ 'sharedCleanResident': memoryMap.sc * 1024,
+ 'sharedDirtyResident': memoryMap.sd * 1024,
+ 'swapped': memoryMap.swp * 1024,
+ };
+ vmRegions.push(new tr.model.VMRegion(
+ addr[0], addr[1] - addr[0], flags, memoryMap.file, totals));
+ }
+ pmd.vmRegions =
+ tr.model.VMRegionClassificationNode.fromRegions(vmRegions);
+ }
+
+ importEvents() {
+ this.lazyParseData();
+ // Assign process and thread names.
+ for (const [pid, process] of Object.entries(this.processes_)) {
+ const modelProcess = this.model_.getProcess(pid);
+ if (modelProcess === undefined) {
+ continue;
+ }
+ modelProcess.name = process.name;
+
+ const threads = process.threads;
+ if (threads === undefined) {
+ continue;
+ }
+ for (const [tid, thread] of Object.entries(threads)) {
+ const modelThread = modelProcess.threads[tid];
+ if (modelThread === undefined) {
+ continue;
+ }
+ modelThread.name = thread.name;
+ }
+ }
+
+ // Memory dumps.
+ const memCounter =
+ this.model_.kernel.getOrCreateCounter('global', 'SystemMemory');
+ const memUsedSeries = new tr.model.CounterSeries('Used (KB)', 0);
+ const memSwappedSeries = new tr.model.CounterSeries('Swapped (KB)', 0);
+ memCounter.addSeries(memUsedSeries);
+ memCounter.addSeries(memSwappedSeries);
+
+ for (const snapshot of this.snapshots_) {
+ const ts = parseInt(snapshot.ts);
+ const memoryDump = snapshot.memdump;
+
+ if (memoryDump === undefined) {
+ const memInfo = snapshot.meminfo;
+ if (memInfo === undefined) {
+ continue;
+ }
+
+ // See Android com.android.server.am.ActivityManagerService class
+ // for calculation formula in 'dumpsys meminfo'.
+ //
+ // The formula below excludes Cached PSS because it's too expensive
+ // to calculate and it's not volatile during short systrace run.
+ // Cached PSS is a total PSS of apps being primary targets for
+ // OOM killer and treated by 'dumpsys meminfo' as a free memory.
+ const memCaches = memInfo.Buffers + memInfo.Cached - memInfo.Mapped;
+ const memUsed = memInfo.MemTotal - memInfo.MemFree - memCaches;
+ const memSwapped = memInfo.SwapTotal - memInfo.SwapFree;
+
+ memUsedSeries.addCounterSample(ts, memUsed);
+ memSwappedSeries.addCounterSample(ts, memSwapped);
+ continue;
+ }
+
+ const gmd = new tr.model.GlobalMemoryDump(this.model_, ts);
+ this.model_.globalMemoryDumps.push(gmd);
+
+ for (const [pid, processInfo] of Object.entries(memoryDump)) {
+ if (processInfo.rss === undefined) {
+ // Memory stats aren't available.
+ continue;
+ }
+ const modelProcess = this.model_.getProcess(pid);
+ if (modelProcess === undefined) {
+ continue;
+ }
+ const pmd = new tr.model.ProcessMemoryDump(gmd, modelProcess, ts);
+ gmd.processMemoryDumps[pid] = pmd;
+ modelProcess.memoryDumps.push(pmd);
+ this.setProcessMemoryDumpTotals_(pmd, processInfo);
+ this.setProcessMemoryDumpVmRegions_(pmd, processInfo);
+ }
+ }
+ }
+ }
+
+ tr.importer.Importer.register(AtraceProcessDumpImporter);
+
+ return {
+ AtraceProcessDumpImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/android/atrace_process_dump_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/atrace_process_dump_importer_test.html
new file mode 100644
index 00000000000..ecf3e8a1584
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/atrace_process_dump_importer_test.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/android/atrace_process_dump_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Importer =
+ tr.e.importer.android.atrace_process_dump.AtraceProcessDumpImporter;
+
+ const TEST_DATA =
+ 'ATRACE_PROCESS_DUMP\n' +
+ '{"clock_sync_markers": {"very-unique-id": 1}, "dump":' +
+ '{"start_ts": "21917568", "snapshots": [' +
+ '{"ts": "21917568", "memdump": {' +
+ ' "788": {' +
+ ' "vm": 2629440, "rss": 249348,' +
+ ' "oom_sc": 0, "oom_sc_adj": -900,' +
+ ' "min_flt": 15844983, "maj_flt": 54832,' +
+ ' "utime": 831123, "stime": 1117125,' +
+ ' "mmaps": [{"vm": "a1000-a5000", "file": "foo", "flags": "rw-s",' +
+ ' "pss": 100, "rss": 200, "swp": 10,' +
+ ' "pc": 50, "pd": 60, "sc": 40, "sd": 45}]' +
+ '}}}],' +
+ '"processes": {' +
+ '"37": {"name": "kworker/5:0H"},' +
+ '"788": {"name": "system_server", "exe": "/system/bin/app_process64",' +
+ ' "threads": {' +
+ ' "788": {"name": "system_server"},' +
+ ' "793": {"name": "Signal Catcher"}' +
+ '}}}}}';
+
+ test('canImport', function() {
+ const canImport = Importer.canImport;
+ assert.isTrue(canImport(TEST_DATA));
+ assert.isFalse(canImport('\n'));
+ });
+
+ test('lazyParseData', function() {
+ const importer = new Importer(null, TEST_DATA);
+ importer.lazyParseData();
+ assert.isUndefined(importer.raw_data_);
+ assert.lengthOf(Object.keys(importer.clock_sync_markers_), 1);
+ assert.lengthOf(importer.snapshots_, 1);
+ assert.lengthOf(Object.keys(importer.processes_), 2);
+ assert.lengthOf(Object.keys(importer.processes_['37']), 1);
+ assert.lengthOf(Object.keys(importer.processes_['788']), 3);
+ assert.lengthOf(Object.keys(importer.processes_['788'].threads), 2);
+
+ const snapshot = importer.snapshots_[0];
+ assert.strictEqual(snapshot.ts, '21917568');
+ assert.lengthOf(Object.keys(snapshot.memdump), 1);
+ assert.lengthOf(Object.keys(snapshot.memdump['788']), 9);
+ });
+
+ test('importEvents', function() {
+ const model = new tr.Model();
+ const proc788 = model.getOrCreateProcess(788);
+ const importer = new Importer(model, TEST_DATA);
+ importer.importEvents();
+ assert.strictEqual(proc788.name, 'system_server');
+ assert.lengthOf(model.globalMemoryDumps, 1);
+
+ const gmd = model.globalMemoryDumps[0];
+ assert.lengthOf(Object.keys(gmd.processMemoryDumps), 1);
+ const pmd = gmd.processMemoryDumps['788'];
+ assert.strictEqual(pmd.totals.residentBytes, 249348 * 1024);
+
+ const vmRegions = pmd.vmRegions.allRegionsForTesting;
+ assert.lengthOf(vmRegions, 1);
+ const vmRegion = vmRegions[0];
+ assert.deepEqual(vmRegion.byteStats, pmd.vmRegions.byteStats);
+ assert.strictEqual(vmRegion.byteStats.swapped, 10240);
+ assert.strictEqual(vmRegion.mappedFile, 'foo');
+ assert.strictEqual(vmRegion.protectionFlags, 134);
+ assert.strictEqual(vmRegion.sizeInBytes, 16384);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/android/event_log_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/event_log_importer.html
new file mode 100644
index 00000000000..677ad5f9912
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/event_log_importer.html
@@ -0,0 +1,324 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/importer/simple_line_reader.html">
+<link rel="import" href="/tracing/model/activity.html">
+<link rel="import" href="/tracing/model/model.html">
+
+
+<script>
+/**
+ * @fileoverview Imports android event log data into the trace model.
+ * Android event log data contains information about activities that
+ * are launched/paused, processes that are started, memory usage, etc.
+ *
+ * The current implementation only parses activity events, with the goal of
+ * determining which Activity is running in the foreground for a process.
+ *
+ * This importer assumes the events arrive as a string. The unit tests provide
+ * examples of the trace format.
+ */
+'use strict';
+
+tr.exportTo('tr.e.importer.android', function() {
+ const Importer = tr.importer.Importer;
+
+ const ACTIVITY_STATE = {
+ NONE: 'none',
+ CREATED: 'created',
+ STARTED: 'started',
+ RESUMED: 'resumed',
+ PAUSED: 'paused',
+ STOPPED: 'stopped',
+ DESTROYED: 'destroyed'
+ };
+
+ const activityMap = {};
+
+ /**
+ * Imports android event log data (adb logcat -b events)
+ * @constructor
+ */
+ function EventLogImporter(model, events) {
+ this.model_ = model;
+ this.events_ = events;
+ this.importPriority = 3;
+ }
+
+ // Generic format of event log entries.
+ // Sample event log entry that this matches (split over 2 lines):
+ // 08-11 13:12:31.405 880 2645 I am_focused_activity: [0,com.google.android.googlequicksearchbox/com.google.android.launcher.GEL] // @suppress longLineCheck
+ const eventLogActivityRE = new RegExp(
+ '(\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d+)' +
+ '\\s+(\\d+)\\s+(\\d+)\\s+([A-Z])\\s*' +
+ '(am_\\w+)\\s*:(.*)');
+
+ // 08-28 03:58:21.834 888 3177 I am_create_activity: [0,5972200,30,com.nxp.taginfolite/.activities.MainView,android.intent.action.MAIN,NULL,NULL,270532608] // @suppress longLineCheck
+ // Store the name of the created activity only
+ const amCreateRE = new RegExp('\s*\\[.*,.*,.*,(.*),.*,.*,.*,.*\\]');
+
+ // 07-22 12:22:19.504 920 2504 I am_focused_activity: [0,com.android.systemui/.recents.RecentsActivity] // @suppress longLineCheck
+ // Store the name of the focused activity only
+ const amFocusedRE = new RegExp('\s*\\[\\d+,(.*)\\]');
+
+ // 07-21 19:56:12.315 920 2261 I am_proc_start: [0,19942,10062,com.google.android.talk,broadcast,com.google.android.talk/com.google.android.apps.hangouts.realtimechat.RealTimeChatService$AlarmReceiver] // @suppress longLineCheck
+ // We care about proc starts on behalf of activities, and store the activity
+ const amProcStartRE = new RegExp('\s*\\[\\d+,\\d+,\\d+,.*,activity,(.*)\\]');
+
+ // 07-22 12:21:43.490 2893 2893 I am_on_resume_called: [0,com.google.android.launcher.GEL] // @suppress longLineCheck
+ // Store the activity name only
+ const amOnResumeRE = new RegExp('\s*\\[\\d+,(.*)\\]');
+
+ // 07-22 12:22:19.545 2893 2893 I am_on_paused_called: [0,com.google.android.launcher.GEL] // @suppress longLineCheck
+ // Store the activity name only
+ const amOnPauseRE = new RegExp('\s*\\[\\d+,(.*)\\]');
+
+ // 08-28 03:51:54.456 888 907 I am_activity_launch_time: [0,185307115,com.google.android.googlequicksearchbox/com.google.android.launcher.GEL,1174,1174] // @suppress longLineCheck
+ // Store the activity name and launch times
+ const amLaunchTimeRE = new RegExp('\s*\\[\\d+,\\d+,(.*),(\\d+),(\\d+)');
+
+ // 08-28 03:58:15.854 888 902 I am_destroy_activity: [0,203516597,29,com.android.chrome/com.google.android.apps.chrome.Main,finish-idle] // @suppress longLineCheck
+ // Store the activity name only
+ const amDestroyRE = new RegExp('\s*\\[\\d+,\\d+,\\d+,(.*)\\]');
+
+ /**
+ * @return {boolean} True when events is an android event log array.
+ */
+ EventLogImporter.canImport = function(events) {
+ if (!(typeof(events) === 'string' || events instanceof String)) {
+ return false;
+ }
+
+ // Prevent the importer from matching this file in vulcanized traces.
+ if (/^<!DOCTYPE html>/.test(events)) return false;
+
+ return eventLogActivityRE.test(events);
+ };
+
+ EventLogImporter.prototype = {
+ __proto__: Importer.prototype,
+
+ get importerName() {
+ return 'EventLogImporter';
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ /**
+ * @return {string} the full activity name (including package) from
+ * a component
+ */
+ getFullActivityName(component) {
+ const componentSplit = component.split('/');
+ if (componentSplit[1].startsWith('.')) {
+ return componentSplit[0] + componentSplit[1];
+ }
+
+ return componentSplit[1];
+ },
+
+ /**
+ * @return {string} the process name of a component
+ */
+ getProcName(component) {
+ const componentSplit = component.split('/');
+ return componentSplit[0];
+ },
+
+ findOrCreateActivity(activityName) {
+ if (activityName in activityMap) {
+ return activityMap[activityName];
+ }
+ const activity = {
+ state: ACTIVITY_STATE.NONE,
+ name: activityName
+ };
+ activityMap[activityName] = activity;
+ return activity;
+ },
+
+ deleteActivity(activityName) {
+ delete activityMap[activityName];
+ },
+
+ handleCreateActivity(ts, activityName) {
+ const activity = this.findOrCreateActivity(activityName);
+ activity.state = ACTIVITY_STATE.CREATED;
+ activity.createdTs = ts;
+ },
+
+ handleFocusActivity(ts, procName, activityName) {
+ const activity = this.findOrCreateActivity(activityName);
+ activity.lastFocusedTs = ts;
+ },
+
+ handleProcStartForActivity(ts, activityName) {
+ const activity = this.findOrCreateActivity(activityName);
+ activity.procStartTs = ts;
+ },
+
+ handleOnResumeCalled(ts, pid, activityName) {
+ const activity = this.findOrCreateActivity(activityName);
+ activity.state = ACTIVITY_STATE.RESUMED;
+ activity.lastResumeTs = ts;
+ // on_resume_called shows the actual PID; use this
+ // to link the activity up with a process later
+ activity.pid = pid;
+ },
+
+ handleOnPauseCalled(ts, activityName) {
+ const activity = this.findOrCreateActivity(activityName);
+ activity.state = ACTIVITY_STATE.PAUSED;
+ activity.lastPauseTs = ts;
+ // Create a new AndroidActivity representing the foreground state,
+ // but only if the pause happened within the model bounds
+ if (ts > this.model_.bounds.min && ts < this.model_.bounds.max) {
+ this.addActivityToProcess(activity);
+ }
+ },
+
+ handleLaunchTime(ts, activityName, launchTime) {
+ const activity = this.findOrCreateActivity(activityName);
+ activity.launchTime = launchTime;
+ },
+
+ handleDestroyActivity(ts, activityName) {
+ this.deleteActivity(activityName);
+ },
+
+ addActivityToProcess(activity) {
+ if (activity.pid === undefined) return;
+ const process = this.model_.getOrCreateProcess(activity.pid);
+ // The range of the activity is the time from resume to time
+ // of pause; limit the start time to the beginning of the model
+ const range = tr.b.math.Range.fromExplicitRange(
+ Math.max(this.model_.bounds.min, activity.lastResumeTs),
+ activity.lastPauseTs);
+ const newActivity = new tr.model.Activity(activity.name,
+ 'Android Activity', range,
+ {created: activity.createdTs,
+ procstart: activity.procStartTs,
+ lastfocus: activity.lastFocusedTs});
+ process.activities.push(newActivity);
+ },
+
+ parseAmLine_(line) {
+ let match = eventLogActivityRE.exec(line);
+ if (!match) return;
+
+ // Possible activity life-cycles:
+ // 1) Launch from scratch:
+ // - am_create_activity
+ // - am_focused_activity
+ // - am_proc_start
+ // - am_proc_bound
+ // - am_restart_activity
+ // - am_on_resume_called
+ // 2) Re-open existing activity
+ // - am_focused_activity
+ // - am_on_resume_called
+
+ // HACK: event log date format is "MM-DD" and doesn't contain the year;
+ // to figure out the year, take the min bound of the model, convert
+ // to real-time and use that as the year.
+ // The Android event log will eventually contain the year once this
+ // CL is in a release:
+ // https://android-review.googlesource.com/#/c/168900
+ const firstRealtimeTs = this.model_.bounds.min -
+ this.model_.realtime_to_monotonic_offset_ms;
+ const year = new Date(firstRealtimeTs).getFullYear();
+ const ts = match[1].substring(0, 5) + '-' + year + ' ' +
+ match[1].substring(5, match[1].length);
+
+ const monotonicTs = Date.parse(ts) +
+ this.model_.realtime_to_monotonic_offset_ms;
+
+ const pid = match[2];
+ const action = match[5];
+ const data = match[6];
+
+ if (action === 'am_create_activity') {
+ match = amCreateRE.exec(data);
+ if (match && match.length >= 2) {
+ this.handleCreateActivity(monotonicTs,
+ this.getFullActivityName(match[1]));
+ }
+ } else if (action === 'am_focused_activity') {
+ match = amFocusedRE.exec(data);
+ if (match && match.length >= 2) {
+ this.handleFocusActivity(monotonicTs,
+ this.getProcName(match[1]), this.getFullActivityName(match[1]));
+ }
+ } else if (action === 'am_proc_start') {
+ match = amProcStartRE.exec(data);
+ if (match && match.length >= 2) {
+ this.handleProcStartForActivity(monotonicTs,
+ this.getFullActivityName(match[1]));
+ }
+ } else if (action === 'am_on_resume_called') {
+ match = amOnResumeRE.exec(data);
+ if (match && match.length >= 2) {
+ this.handleOnResumeCalled(monotonicTs, pid, match[1]);
+ }
+ } else if (action === 'am_on_paused_called') {
+ match = amOnPauseRE.exec(data);
+ if (match && match.length >= 2) {
+ this.handleOnPauseCalled(monotonicTs, match[1]);
+ }
+ } else if (action === 'am_activity_launch_time') {
+ match = amLaunchTimeRE.exec(data);
+ this.handleLaunchTime(monotonicTs,
+ this.getFullActivityName(match[1]), match[2]);
+ } else if (action === 'am_destroy_activity') {
+ match = amDestroyRE.exec(data);
+ if (match && match.length === 2) {
+ this.handleDestroyActivity(monotonicTs,
+ this.getFullActivityName(match[1]));
+ }
+ }
+ },
+
+ importEvents() {
+ // Check if we have a mapping from real-time to CLOCK_MONOTONIC
+ if (isNaN(this.model_.realtime_to_monotonic_offset_ms)) {
+ this.model_.importWarning({
+ type: 'eveng_log_clock_sync',
+ message: 'Need a trace_event_clock_sync to map realtime to import.'
+ });
+ return;
+ }
+ // Since the event log typically spans a much larger timeframe
+ // than the ftrace data, we want to calculate the bounds of the existing
+ // model, and dump all event log data outside of those bounds
+ this.model_.updateBounds();
+
+ const lines = this.events_.split('\n');
+ lines.forEach(this.parseAmLine_, this);
+
+ // Iterate over all created activities that are not destroyed yet
+ for (const activityName in activityMap) {
+ const activity = activityMap[activityName];
+ // If we're still in the foreground, store the activity anyway
+ if (activity.state === ACTIVITY_STATE.RESUMED) {
+ // Set the pause timestamp to the end of the model bounds
+ activity.lastPauseTs = this.model_.bounds.max;
+ this.addActivityToProcess(activity);
+ }
+ }
+ }
+ };
+
+ Importer.register(EventLogImporter);
+
+ return {
+ EventLogImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/android/process_data_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/process_data_importer.html
new file mode 100644
index 00000000000..7c9cdf5e89f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/process_data_importer.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/importer/simple_line_reader.html">
+<link rel="import" href="/tracing/model/activity.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+/**
+ * @fileoverview
+ */
+'use strict';
+
+tr.exportTo('tr.e.importer.android.process_data', function() {
+ const Importer = tr.importer.Importer;
+
+ const PROCESS_DUMP_HEADER = 'PROCESS DUMP';
+
+ /**
+ * Imports android process data
+ * @constructor
+ */
+ function ProcessDataImporter(model, processData) {
+ this.model_ = model;
+ this.processDataLines = processData.split('\n');
+ this.importPriority = 3;
+ }
+
+ /**
+ * @return {boolean}
+ */
+ ProcessDataImporter.canImport = function(events) {
+ if (!(typeof(events) === 'string' || events instanceof String)) {
+ return false;
+ }
+
+ if (events.split('\n')[0] === PROCESS_DUMP_HEADER) {
+ return true;
+ }
+
+ return false;
+ };
+
+ ProcessDataImporter.prototype = {
+ __proto__: Importer.prototype,
+
+ get importerName() {
+ return 'ProcessDataImporter';
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ parseEventData(data) {
+ const allDumpedProcesses = {};
+
+ let parseProcesses = false;
+ let parseThreads = false;
+ let legacy = false;
+
+ // Skip header on line 1.
+ for (let i = 1; i < data.length; i++) {
+ const cols = data[i].split(/\s+/);
+ if (cols[0].startsWith('USER')) {
+ if (parseProcesses) {
+ parseProcesses = false;
+ parseThreads = true;
+ } else {
+ parseThreads = false;
+ parseProcesses = true;
+ }
+
+ const colCount = cols.length;
+ if (parseProcesses && colCount === 9) {
+ legacy = false;
+ } else if (parseProcesses && colCount === 8) {
+ legacy = true;
+ }
+ continue;
+ }
+
+ if (parseProcesses) {
+ const pid = Number(cols[1]);
+ if (allDumpedProcesses[pid] === undefined) {
+ allDumpedProcesses[pid] = {};
+ }
+ allDumpedProcesses[pid] = {
+ 'name': cols[8], pid, 'comm': cols[9]
+ };
+ continue;
+ }
+
+ if (parseThreads) {
+ let pid;
+ let tid;
+ let name;
+
+ // In legacy ps dumps, the PID is actually shown in the PPID column
+ // for thread lines, but PID column for the process line
+ if (legacy) {
+ pid = Number(cols[1]);
+ if (allDumpedProcesses[pid] !== undefined) {
+ // this is a process line in the dump.
+ tid = pid;
+ } else {
+ // Thread line, so swap.
+ tid = pid;
+ pid = Number(cols[2]); // i.e. the PPID column.
+ }
+ name = cols.slice(8).join(' ');
+ } else {
+ pid = Number(cols[1]);
+ tid = Number(cols[2]);
+ name = cols.slice(3).join(' ');
+ }
+
+ // Thread data for a process we didn't identify, skip.
+ if (allDumpedProcesses[pid] === undefined) continue;
+
+ if (allDumpedProcesses[pid].threads === undefined) {
+ allDumpedProcesses[pid].threads = {};
+ }
+ allDumpedProcesses[pid].threads[tid] = {tid, name};
+ continue;
+ }
+ }
+ return allDumpedProcesses;
+ },
+
+ importEvents() {
+ // Merge the snapshots into a single object, indexable by PID.
+
+ const allDumpedProcesses = this.parseEventData(this.processDataLines);
+
+ // Update the model with the new process / thread name data.
+ const modelProcesses = this.model_.getAllProcesses();
+ for (let i = 0; i < modelProcesses.length; i++) {
+ const modelProcess = modelProcesses[i];
+ const pid = modelProcess.pid;
+ const dumpedProcess = allDumpedProcesses[pid];
+ if (dumpedProcess === undefined) {
+ // There's a process in the model that the ps dump doesn't know about,
+ // nothing we can do so skip it.
+ continue;
+ }
+
+ modelProcess.name = dumpedProcess.name;
+ const processDumpThreads = dumpedProcess.threads;
+ if (processDumpThreads !== undefined) {
+ for (const tid in modelProcess.threads) {
+ const modelThread = modelProcess.threads[tid];
+ if (Number(pid) === Number(tid)) {
+ modelThread.name = 'UI thread';
+ } else if (modelThread.name === '<...>') {
+ if (processDumpThreads[tid] !== undefined) {
+ // Use the stored thread name that we have.
+ modelThread.name = processDumpThreads[tid].name;
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+
+ Importer.register(ProcessDataImporter);
+
+ return {
+ ProcessDataImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/android/process_data_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/process_data_importer_test.html
new file mode 100644
index 00000000000..f902b06229c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/android/process_data_importer_test.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/android/process_data_importer.html">
+
+<script>
+'use strict';
+
+const TEST_DATA =
+ 'PROCESS DUMP\n' +
+ 'USER PID PPID VSZ RSS WCHAN PC S NAME COMM\n' +
+ 'root 1 0 0 0 SyS_epoll_wait ffffff S test1 init\n' +
+ 'root 2 0 0 0 kthreadd 0 S test2 2\n' +
+ 'root 3 2 0 0 smpboot_thread_fn 0 S test3 3\n' +
+ 'USER PID TID CMD\n' +
+ 'root 1 1 test1\n' +
+ 'root 2 2 test2\n' +
+ 'root 3 3 test3\n' +
+ 'u0_a48 1 4 test1_t1\n' +
+ 'u0_a10 2 5 test2_t1\n' +
+ 'u0_a10 3 6 test3_t1\n' +
+ 'u0_a10 1 7 test1_t2\n' +
+ 'u0_a10 2 8 test2_t2\n' +
+ 'u0_a10 3 9 test3_t2\n' +
+ 'u0_a10 3 10 test3_t3\n';
+
+const LEGACY_TEST_DATA =
+ 'PROCESS DUMP\n' +
+ 'USER PID PPID VSIZE RSS WCHAN PC NAME\n' +
+ 'root 1 0 1324 856 SyS_epoll_ 00070cd8 S test1\n' +
+ 'root 2 0 0 0 kthreadd 00000000 S test2\n' +
+ 'root 3 0 0 0 smpboot_th 00000000 S test3\n' +
+ 'USER PID PPID VSIZE RSS WCHAN PC NAME\n' +
+ 'root 1 0 1324 856 SyS_epoll_ 00070cd8 S test1\n' +
+ 'root 2 0 0 0 kthreadd 00000000 S test2\n' +
+ 'root 3 0 0 0 smpboot_th 00000000 S test3\n' +
+ 'u0_a35 4 1 726452 34352 SyS_epoll_ ffffffff S test1_t1\n' +
+ 'u0_a35 5 2 726452 34352 SyS_epoll_ ffffffff S test2_t1\n' +
+ 'u0_a53 6 3 846540 54996 SyS_epoll_ ffffffff S test3_t1\n' +
+ 'u0_a53 7 1 846540 54996 futex_wait ffffffff S test1_t2\n' +
+ 'u0_a53 8 2 846540 54996 futex_wait ffffffff S test2_t2\n' +
+ 'u0_a53 9 3 846540 54996 futex_wait ffffffff S test3_t2\n' +
+ 'root 10 3 4692 244 poll_sched ffffffff S test3_t3\n';
+
+tr.b.unittest.testSuite(function() {
+ test('canImport', function() {
+ const canImport =
+ tr.e.importer.android.process_data.ProcessDataImporter.canImport;
+ assert.isTrue(canImport(TEST_DATA));
+ assert.isTrue(canImport(LEGACY_TEST_DATA));
+ assert.isFalse(canImport(''));
+ assert.isFalse(canImport('\n'));
+ });
+
+ test('procinfoImport', function() {
+ const importer = new tr.e.importer.android.process_data.ProcessDataImporter(
+ null, TEST_DATA);
+ const result = importer.parseEventData(importer.processDataLines);
+ verifyParsedDump(result);
+ });
+
+ test('procinfoImportLegacy', function() {
+ const importer = new tr.e.importer.android.process_data.ProcessDataImporter(
+ null, LEGACY_TEST_DATA);
+ const result = importer.parseEventData(importer.processDataLines);
+ verifyParsedDump(result);
+ });
+
+ function verifyParsedDump(result) {
+ assert.isDefined(result);
+
+ // indexable by PID, so invalid PIDs should be undefined.
+ assert.isUndefined(result[0]);
+ assert.isUndefined(result[100]);
+
+ let proc = result[1];
+ assert.isDefined(proc);
+ assert.strictEqual(proc.name, 'test1');
+ assert.strictEqual(proc.pid, 1);
+ assert.isDefined(proc.threads);
+ let thread = proc.threads[1];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test1');
+ assert.strictEqual(thread.tid, 1);
+ thread = proc.threads[4];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test1_t1');
+ assert.strictEqual(thread.tid, 4);
+ thread = proc.threads[7];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test1_t2');
+ assert.strictEqual(thread.tid, 7);
+
+ proc = result[2];
+ assert.isDefined(proc);
+ assert.strictEqual(proc.name, 'test2');
+ assert.strictEqual(proc.pid, 2);
+ assert.isDefined(proc.threads);
+ thread = proc.threads[2];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test2');
+ assert.strictEqual(thread.tid, 2);
+ thread = proc.threads[5];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test2_t1');
+ assert.strictEqual(thread.tid, 5);
+ thread = proc.threads[8];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test2_t2');
+ assert.strictEqual(thread.tid, 8);
+
+ proc = result[3];
+ assert.isDefined(proc);
+ assert.strictEqual(proc.name, 'test3');
+ assert.strictEqual(proc.pid, 3);
+ assert.isDefined(proc.threads);
+ thread = proc.threads[3];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test3');
+ assert.strictEqual(thread.tid, 3);
+ thread = proc.threads[6];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test3_t1');
+ assert.strictEqual(thread.tid, 6);
+ thread = proc.threads[9];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test3_t2');
+ assert.strictEqual(thread.tid, 9);
+ thread = proc.threads[10];
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'test3_t3');
+ assert.strictEqual(thread.tid, 10);
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/battor_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/battor_importer.html
new file mode 100644
index 00000000000..1235a4e41d5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/battor_importer.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_series.html">
+
+<script>
+/**
+ * @fileoverview Imports text files in the BattOr format into the
+ * Model. This format is output by the battor_agent executable and library.
+ *
+ * This importer assumes the events arrive as a string. The unit tests provide
+ * examples of the trace format.
+ */
+'use strict';
+
+tr.exportTo('tr.e.importer.battor', function() {
+ /**
+ * Imports a BattOr power trace into a specified model.
+ * @constructor
+ */
+ function BattorImporter(model, events) {
+ this.importPriority = 3; // runs after the linux_perf importer
+ this.model_ = model;
+
+ // The list of power samples contained within the trace.
+ this.samples_ = [];
+ // The clock sync markers contained within the trace.
+ this.syncTimestampsById_ = new Map();
+
+ this.parseTrace_(events);
+ }
+
+ const battorDataLineRE = new RegExp(
+ '^(-?\\d+\\.\\d+)\\s+(-?\\d+\\.\\d+)\\s+(-?\\d+\\.\\d+)' +
+ '(?:\\s+<(\\S+)>)?$'
+ );
+ const battorHeaderLineRE = /^# BattOr/;
+
+ /**
+ * Guesses whether the provided events is a BattOr string.
+ * Looks for the magic string "# BattOr" at the start of the file,
+ *
+ * @return {boolean} True when events is a BattOr array.
+ */
+ BattorImporter.canImport = function(events) {
+ if (!(typeof(events) === 'string' || events instanceof String)) {
+ return false;
+ }
+
+ return battorHeaderLineRE.test(events);
+ };
+
+ BattorImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'BattorImporter';
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ /**
+ * Imports clock sync markers from the trace into into this.model_.
+ */
+ importClockSyncMarkers() {
+ for (const [syncId, ts] of this.syncTimestampsById_) {
+ this.model_.clockSyncManager.addClockSyncMarker(
+ tr.model.ClockDomainId.BATTOR, syncId, ts);
+ }
+ },
+
+ /**
+ * Imports the events from the trace into this.model_.
+ */
+ importEvents() {
+ if (this.model_.device.powerSeries) {
+ this.model_.importWarning({
+ type: 'import_error',
+ message: 'Power counter exists, can not import BattOr power trace.'
+ });
+ return;
+ }
+
+ const modelTimeTransformer =
+ this.model_.clockSyncManager.getModelTimeTransformer(
+ tr.model.ClockDomainId.BATTOR);
+
+ const powerSeries = this.model_.device.powerSeries =
+ new tr.model.PowerSeries(this.model_.device);
+ for (let i = 0; i < this.samples_.length; i++) {
+ const sample = this.samples_[i];
+ powerSeries.addPowerSample(
+ modelTimeTransformer(sample.ts), sample.powerInW);
+ }
+ },
+
+ /**
+ * Given the BattOr trace as a string, parse it and store the results in
+ * this.samples_ and this.syncTimestampsById_.
+ */
+ parseTrace_(trace) {
+ const lines = trace.split('\n');
+
+ for (let line of lines) {
+ line = line.trim();
+
+ if (line.length === 0) continue;
+
+ if (line.startsWith('#')) continue;
+
+ // Parse power sample.
+ const groups = battorDataLineRE.exec(line);
+ if (!groups) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Unrecognized line in BattOr trace: ' + line
+ });
+ continue;
+ }
+
+ const ts = parseFloat(groups[1]);
+ const voltageInV = tr.b.convertUnit(parseFloat(groups[2]),
+ tr.b.UnitPrefixScale.METRIC.MILLI,
+ tr.b.UnitPrefixScale.METRIC.NONE);
+ const currentInA = tr.b.convertUnit(parseFloat(groups[3]),
+ tr.b.UnitPrefixScale.METRIC.MILLI,
+ tr.b.UnitPrefixScale.METRIC.NONE);
+ const syncId = groups[4];
+
+ if (syncId) {
+ this.syncTimestampsById_.set(syncId, ts);
+ }
+
+ if (voltageInV < 0 || currentInA < 0) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'The following line in the BattOr trace has a negative ' +
+ 'voltage or current, neither of which are allowed: ' + line +
+ '. A common cause of this is that the device is charging ' +
+ 'while the trace is being recorded.'
+ });
+ continue;
+ }
+
+ this.samples_.push(new Sample(ts, voltageInV, currentInA));
+ }
+ }
+ };
+
+ /**
+ * A sample recorded by a BattOr.
+ *
+ * @param {number} ts The timestamp (in milliseconds) of the sample.
+ * @param {number} voltage The voltage (in volts) at the specified time.
+ * @param {number} current The current (in amps) at the specified time.
+ *
+ * @constructor
+ */
+ function Sample(ts, voltageInV, currentInA) {
+ this.ts = ts;
+ this.voltageInV = voltageInV;
+ this.currentInA = currentInA;
+ }
+
+ Sample.prototype = {
+ /** Returns the instantaneous power consumption (in Watts). */
+ get powerInW() { return this.voltageInV * this.currentInA; }
+ };
+
+ tr.importer.Importer.register(BattorImporter);
+
+ return {
+ BattorImporter,
+ };
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/battor_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/battor_importer_test.html
new file mode 100644
index 00000000000..ba9e091716d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/battor_importer_test.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/battor_importer.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const CHROMIUM_EVENTS = [
+ {
+ name: 'a', args: {}, pid: 52, ts: 0,
+ cat: 'foo', tid: 53, ph: 'B'
+ },
+ {
+ pid: 94936, tid: 5643, ts: 15000,
+ ph: 'c', cat: '__metadata', name: 'clock_sync',
+ args: {sync_id: 'ABCDEF-01234-5678-0A1B2C3D', issue_ts: 10000},
+ tts: 16496444
+ }
+ ];
+
+ const BATTOR_LINES = [
+ '# BattOr',
+ '# voltage_range [0.0, 6144.0] mV',
+ '# current_range [0.0, 2275.5] mA',
+ '# sample_rate 2000 Hz, gain 5.0x',
+ '0.000000 0.000000 4000.000000',
+ '0.500000 0.000000 4000.000000',
+ '1.000000 0.000000 4000.000000',
+ '1.500000 0.000000 4000.000000',
+ '2.000000 1.000000 4000.000000'
+ ];
+
+ test('canImport', function() {
+ assert.isFalse(tr.e.importer.battor.BattorImporter.canImport('string'));
+ assert.isFalse(tr.e.importer.battor.BattorImporter.canImport([]));
+ assert.isTrue(tr.e.importer.battor.BattorImporter.canImport(
+ BATTOR_LINES.join('\n')));
+ });
+
+ test('importExplicitClockSync', function() {
+ // Add a BattOr sample with an explicit clock sync.
+ const battorLinesWithExplicitSync = BATTOR_LINES.slice();
+ battorLinesWithExplicitSync.push(
+ '2.500000 1.000000 4000.000000 <ABCDEF-01234-5678-0A1B2C3D>');
+
+ const m = tr.c.TestUtils.newModelWithEvents(
+ [CHROMIUM_EVENTS, battorLinesWithExplicitSync.join('\n')]);
+
+ // Check to see if power samples were imported successfully.
+ assert.isDefined(m.device.powerSeries);
+
+ assert.strictEqual(m.device.powerSeries.samples[0].start, 7.5);
+ assert.strictEqual(m.device.powerSeries.samples[5].start, 10.0);
+ });
+
+ test('importExplicitClockSync_syncOnNegativeVoltageLine', function() {
+ // Add a BattOr sample with an explicit clock sync that occurs on a line
+ // with a negative voltage measurement. The sample should be ignored, but
+ // the clock sync should be counted.
+ const battorLinesWithExplicitSync = BATTOR_LINES.slice();
+ battorLinesWithExplicitSync.push(
+ '2.500000 -1.000000 4000.000000 <ABCDEF-01234-5678-0A1B2C3D>');
+
+ const m = tr.c.TestUtils.newModelWithEvents(
+ [CHROMIUM_EVENTS, battorLinesWithExplicitSync.join('\n')]);
+
+ // Check to see if power samples were imported successfully.
+ assert.isDefined(m.device.powerSeries);
+
+ assert.lengthOf(m.device.powerSeries.samples, 5);
+ assert.strictEqual(m.device.powerSeries.samples[0].start, 7.5);
+ });
+
+ test('explicitClockSyncWithoutSyncMarkers', function() {
+ // Create an empty model.
+ let m = new tr.Model();
+ const io = new tr.importer.ImportOptions();
+ io.showImportWarnings = false;
+ m.importOptions = io;
+
+ // Add a BattOr sample with an explicit clock sync.
+ const battorLinesWithExplicitSync = BATTOR_LINES.slice();
+ battorLinesWithExplicitSync.push(
+ '2.500000 1.000000 4000.000000 <ABCDEF-01234-5678-0A1B2C3D>');
+
+ m = tr.c.TestUtils.newModelWithEvents(
+ [battorLinesWithExplicitSync.join('\n')]);
+
+ assert.lengthOf(m.device.powerSeries.samples, 6);
+ assert.strictEqual(m.device.powerSeries.samples[0].start, 0);
+ assert.strictEqual(m.device.powerSeries.samples[5].start, 2.5);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/ddms_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/ddms_importer.html
new file mode 100644
index 00000000000..73ffc41b4c1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/ddms_importer.html
@@ -0,0 +1,223 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+/**
+ * @fileoverview Blah.
+ */
+'use strict';
+
+tr.exportTo('tr.e.importer.ddms', function() {
+ const kPid = 0;
+ const kCategory = 'java';
+ const kMethodLutEndMarker = '\n*end\n';
+ const kThreadsStart = '\n*threads\n';
+ const kMethodsStart = '\n*methods\n';
+
+ const kTraceMethodEnter = 0x00; // method entry
+ const kTraceMethodExit = 0x01; // method exit
+ const kTraceUnroll = 0x02; // method exited by exception unrolling
+ // 0x03 currently unused
+ const kTraceMethodActionMask = 0x03; // two bits
+
+ const kTraceHeaderLength = 32;
+ const kTraceMagicValue = 0x574f4c53;
+ const kTraceVersionSingleClock = 2;
+ const kTraceVersionDualClock = 3;
+ const kTraceRecordSizeSingleClock = 10; // using v2
+ const kTraceRecordSizeDualClock = 14; // using v3 with two timestamps
+
+ function Reader(stringPayload) {
+ this.position_ = 0;
+ this.data_ = new Uint8Array(stringPayload.length);
+ for (let i = 0; i < stringPayload.length; ++i) {
+ this.data_[i] = stringPayload.charCodeAt(i);
+ }
+ }
+
+ Reader.prototype = {
+ __proto__: Object.prototype,
+
+ uint8() {
+ const result = this.data_[this.position_];
+ this.position_ += 1;
+ return result;
+ },
+
+ uint16() {
+ let result = 0;
+ result += this.uint8();
+ result += this.uint8() << 8;
+ return result;
+ },
+
+ uint32() {
+ let result = 0;
+ result += this.uint8();
+ result += this.uint8() << 8;
+ result += this.uint8() << 16;
+ result += this.uint8() << 24;
+ return result;
+ },
+
+ uint64() {
+ // Javascript isn't able to manage 64-bit numeric values.
+ const low = this.uint32();
+ const high = this.uint32();
+ const lowStr = ('0000000' + low.toString(16)).substr(-8);
+ const highStr = ('0000000' + high.toString(16)).substr(-8);
+ const result = highStr + lowStr;
+ return result;
+ },
+
+ seekTo(position) {
+ this.position_ = position;
+ },
+
+ hasMore() {
+ return this.position_ < this.data_.length;
+ }
+ };
+
+ /**
+ * Imports DDMS method tracing events into a specified model.
+ * @constructor
+ */
+ function DdmsImporter(model, data) {
+ this.importPriority = 3;
+ this.model_ = model;
+ this.data_ = data;
+ }
+
+ /**
+ * Guesses whether the provided events is from a DDMS method trace.
+ * @return {boolean} True when events is a DDMS method trace.
+ */
+ DdmsImporter.canImport = function(data) {
+ if (typeof(data) === 'string' || data instanceof String) {
+ const header = data.slice(0, 1000);
+ return header.startsWith('*version\n') &&
+ header.indexOf('\nvm=') >= 0 &&
+ header.indexOf(kThreadsStart) >= 0;
+ }
+ /* key bit */
+ return false;
+ };
+
+ DdmsImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'DdmsImporter';
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ /**
+ * Imports the data in this.data_ into this.model_.
+ */
+ importEvents() {
+ const divider = this.data_.indexOf(kMethodLutEndMarker) +
+ kMethodLutEndMarker.length;
+ this.metadata_ = this.data_.slice(0, divider);
+ this.methods_ = {};
+ this.parseThreads();
+ this.parseMethods();
+
+ const traceReader = new Reader(this.data_.slice(divider));
+ const magic = traceReader.uint32();
+ if (magic !== kTraceMagicValue) {
+ throw Error('Failed to match magic value');
+ }
+ this.version_ = traceReader.uint16();
+ if (this.version_ !== kTraceVersionDualClock) {
+ throw Error('Unknown version');
+ }
+ const dataOffest = traceReader.uint16();
+ const startDateTime = traceReader.uint64();
+ const recordSize = traceReader.uint16();
+
+ traceReader.seekTo(dataOffest);
+
+ while (traceReader.hasMore()) {
+ this.parseTraceEntry(traceReader);
+ }
+ },
+
+ parseTraceEntry(reader) {
+ const tid = reader.uint16();
+ const methodPacked = reader.uint32();
+ const cpuSinceStart = reader.uint32();
+ const wallClockSinceStart = reader.uint32();
+ let method = methodPacked & ~kTraceMethodActionMask;
+ const action = methodPacked & kTraceMethodActionMask;
+ const thread = this.getTid(tid);
+ method = this.getMethodName(method);
+ if (action === kTraceMethodEnter) {
+ thread.sliceGroup.beginSlice(kCategory, method, wallClockSinceStart,
+ undefined, cpuSinceStart);
+ } else if (thread.sliceGroup.openSliceCount) {
+ thread.sliceGroup.endSlice(wallClockSinceStart, cpuSinceStart);
+ }
+ },
+
+ parseThreads() {
+ let threads = this.metadata_.slice(this.metadata_.indexOf(kThreadsStart) +
+ kThreadsStart.length);
+ threads = threads.slice(0, threads.indexOf('\n*'));
+ threads = threads.split('\n');
+ threads.forEach(this.parseThread.bind(this));
+ },
+
+ parseThread(threadLine) {
+ const tid = threadLine.slice(0, threadLine.indexOf('\t'));
+ const thread = this.getTid(parseInt(tid));
+ thread.name = threadLine.slice(threadLine.indexOf('\t') + 1);
+ },
+
+ getTid(tid) {
+ return this.model_.getOrCreateProcess(kPid)
+ .getOrCreateThread(tid);
+ },
+
+ parseMethods() {
+ let methods = this.metadata_.slice(this.metadata_.indexOf(kMethodsStart) +
+ kMethodsStart.length);
+ methods = methods.slice(0, methods.indexOf('\n*'));
+ methods = methods.split('\n');
+ methods.forEach(this.parseMethod.bind(this));
+ },
+
+ parseMethod(methodLine) {
+ const data = methodLine.split('\t');
+ const methodId = parseInt(data[0]);
+ const methodName = data[1] + '.' + data[2] + data[3];
+ this.addMethod(methodId, methodName);
+ },
+
+ addMethod(methodId, methodName) {
+ this.methods_[methodId] = methodName;
+ },
+
+ getMethodName(methodId) {
+ return this.methods_[methodId];
+ }
+ };
+
+ // Register the DdmsImporter to the Importer.
+ tr.importer.Importer.register(DdmsImporter);
+
+ return {
+ DdmsImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/ddms_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/ddms_importer_test.html
new file mode 100644
index 00000000000..a516751e47b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/ddms_importer_test.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/ddms_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Base64 = tr.b.Base64;
+
+ test('canImport', function() {
+ assert.isFalse(tr.e.importer.ddms.DdmsImporter.canImport('string'));
+ assert.isFalse(tr.e.importer.ddms.DdmsImporter.canImport([]));
+ assert.isTrue(tr.e.importer.ddms.DdmsImporter.canImport(TEST_DATA));
+ });
+
+ test('parseThreads', function() {
+ const m = tr.c.TestUtils.newModelWithEvents(TEST_DATA, {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ let threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 2);
+ threads = m.findAllThreadsNamed('main');
+ assert.strictEqual(threads.length, 1);
+ const thread = threads[0];
+ assert.strictEqual(thread.tid, 2703);
+ });
+
+ test('parseMethods', function() {
+ const m = tr.c.TestUtils.newModelWithEvents(TEST_DATA, {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.findAllThreadsNamed('Binder_1');
+ assert.strictEqual(threads.length, 1);
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.length, 22);
+ assert.strictEqual('android.os.Binder.execTransact(IJJI)Z',
+ thread.sliceGroup.slices[0].title);
+ });
+
+ const TEST_DATA = Base64.atob(
+ 'KnZlcnNpb24KMwpkYXRhLWZpbGUtb3ZlcmZsb3c9ZmFsc2UKY2' +
+ 'xvY2s9ZHVhbAplbGFwc2VkLXRpbWUtdXNlYz02MzMwNzc5Cm51' +
+ 'bS1tZXRob2QtY2FsbHM9NzYKY2xvY2stY2FsbC1vdmVyaGVhZC' +
+ '1uc2VjPTMzNDMKdm09YXJ0Cip0aHJlYWRzCjI3MDMJbWFpbgoy' +
+ 'NzEwCUhlYXAgdGhyZWFkIHBvb2wgd29ya2VyIHRocmVhZCAxCj' +
+ 'I3MDkJSGVhcCB0aHJlYWQgcG9vbCB3b3JrZXIgdGhyZWFkIDAK' +
+ 'MjcxMQlIZWFwIHRocmVhZCBwb29sIHdvcmtlciB0aHJlYWQgMg' +
+ 'oyNzEyCVNpZ25hbCBDYXRjaGVyCjI3MTMJSkRXUAoyNzE0CVJl' +
+ 'ZmVyZW5jZVF1ZXVlRGFlbW9uCjI3MTUJRmluYWxpemVyRGFlbW' +
+ '9uCjI3MTYJRmluYWxpemVyV2F0Y2hkb2dEYWVtb24KMjcxNwlI' +
+ 'ZWFwVHJpbW1lckRhZW1vbgoyNzE4CUdDRGFlbW9uCjI3MTkJQm' +
+ 'luZGVyXzEKMjcyMAlCaW5kZXJfMgoyNzI3CVJlbmRlclRocmVh' +
+ 'ZAoyNzI4CUFzeW5jVGFzayAjMQoyNzI5CUFzeW5jVGFzayAjMg' +
+ 'oyNzMwCUJpbmRlcl8zCjExNTk4CWh3dWlUYXNrMQoxMTU5OQlo' +
+ 'd3VpVGFzazIKMTE2MDAJQXN5bmNUYXNrICMzCjExNjAxCUFzeW' +
+ '5jVGFzayAjNAoxMTY3MwlBc3luY1Rhc2sgIzUKKm1ldGhvZHMK' +
+ 'MHg3MGZiNzc1OAlkYWx2aWsuc3lzdGVtLkNsb3NlR3VhcmQJY2' +
+ 'xvc2UJKClWCUNsb3NlR3VhcmQuamF2YQoweDcwZmI4NDE4CWRh' +
+ 'bHZpay5zeXN0ZW0uVk1EZWJ1ZwlzdGFydE1ldGhvZFRyYWNpbm' +
+ 'cJKExqYXZhL2xhbmcvU3RyaW5nO0xqYXZhL2lvL0ZpbGVEZXNj' +
+ 'cmlwdG9yO0lJWkkpVglWTURlYnVnLmphdmEKMHg3MGZlYTcyOA' +
+ 'lqYXZhLnV0aWwuQXJyYXlMaXN0CXNpemUJKClJCUFycmF5TGlz' +
+ 'dC5qYXZhCjB4NzEwMTNmYTgJbGliY29yZS5pby5CbG9ja0d1YX' +
+ 'JkT3MJY2xvc2UJKExqYXZhL2lvL0ZpbGVEZXNjcmlwdG9yOylW' +
+ 'CUJsb2NrR3VhcmRPcy5qYXZhCjB4NzEwNTc3NDgJYW5kcm9pZC' +
+ '5vcy5CaW5kZXIJZXhlY1RyYW5zYWN0CShJSkpJKVoJQmluZGVy' +
+ 'LmphdmEKMHg3MTA3MTdlOAlhbmRyb2lkLmFwcC5BY3Rpdml0eV' +
+ 'RocmVhZCRBcHBsaWNhdGlvblRocmVhZAlwcm9maWxlckNvbnRy' +
+ 'b2wJKFpMYW5kcm9pZC9hcHAvUHJvZmlsZXJJbmZvO0kpVglBY3' +
+ 'Rpdml0eVRocmVhZC5qYXZhCjB4NzEwNzJhNDgJYW5kcm9pZC5h' +
+ 'cHAuQXBwbGljYXRpb25UaHJlYWROYXRpdmUJb25UcmFuc2FjdA' +
+ 'koSUxhbmRyb2lkL29zL1BhcmNlbDtMYW5kcm9pZC9vcy9QYXJj' +
+ 'ZWw7SSlaCUFwcGxpY2F0aW9uVGhyZWFkTmF0aXZlLmphdmEKMH' +
+ 'g3MTA3MmYyOAlhbmRyb2lkLm9zLkhhbmRsZXIJZW5xdWV1ZU1l' +
+ 'c3NhZ2UJKExhbmRyb2lkL29zL01lc3NhZ2VRdWV1ZTtMYW5kcm' +
+ '9pZC9vcy9NZXNzYWdlO0opWglIYW5kbGVyLmphdmEKMHg3MTA3' +
+ 'MmZlOAlhbmRyb2lkLm9zLkhhbmRsZXIJZGlzcGF0Y2hNZXNzYW' +
+ 'dlCShMYW5kcm9pZC9vcy9NZXNzYWdlOylWCUhhbmRsZXIuamF2' +
+ 'YQoweDcxMDczNTI4CWFuZHJvaWQub3MuSGFuZGxlcglzZW5kTW' +
+ 'Vzc2FnZQkoTGFuZHJvaWQvb3MvTWVzc2FnZTspWglIYW5kbGVy' +
+ 'LmphdmEKMHg3MTA3MzU4OAlhbmRyb2lkLm9zLkhhbmRsZXIJc2' +
+ 'VuZE1lc3NhZ2VBdFRpbWUJKExhbmRyb2lkL29zL01lc3NhZ2U7' +
+ 'SilaCUhhbmRsZXIuamF2YQoweDcxMDczNWI4CWFuZHJvaWQub3' +
+ 'MuSGFuZGxlcglzZW5kTWVzc2FnZURlbGF5ZWQJKExhbmRyb2lk' +
+ 'L29zL01lc3NhZ2U7SilaCUhhbmRsZXIuamF2YQoweDcxMDczNj' +
+ 'Q4CWFuZHJvaWQuYXBwLkFjdGl2aXR5VGhyZWFkJEgJaGFuZGxl' +
+ 'TWVzc2FnZQkoTGFuZHJvaWQvb3MvTWVzc2FnZTspVglBY3Rpdm' +
+ 'l0eVRocmVhZC5qYXZhCjB4NzEwNzM3NjgJYW5kcm9pZC5hcHAu' +
+ 'QWN0aXZpdHlUaHJlYWQkUHJvZmlsZXIJc3RhcnRQcm9maWxpbm' +
+ 'cJKClWCUFjdGl2aXR5VGhyZWFkLmphdmEKMHg3MTA3Mzc5OAlh' +
+ 'bmRyb2lkLmFwcC5BY3Rpdml0eVRocmVhZCRQcm9maWxlcglzdG' +
+ '9wUHJvZmlsaW5nCSgpVglBY3Rpdml0eVRocmVhZC5qYXZhCjB4' +
+ 'NzEwYzQ2ZDgJYW5kcm9pZC5vcy5NZXNzYWdlCW9idGFpbgkoKU' +
+ 'xhbmRyb2lkL29zL01lc3NhZ2U7CU1lc3NhZ2UuamF2YQoweDcx' +
+ 'MGM0YTM4CWFuZHJvaWQub3MuTWVzc2FnZQlpc0luVXNlCSgpWg' +
+ 'lNZXNzYWdlLmphdmEKMHg3MTBjNGE2OAlhbmRyb2lkLm9zLk1l' +
+ 'c3NhZ2UJbWFya0luVXNlCSgpVglNZXNzYWdlLmphdmEKMHg3MT' +
+ 'BjNGFmOAlhbmRyb2lkLm9zLk1lc3NhZ2UJcmVjeWNsZVVuY2hl' +
+ 'Y2tlZAkoKVYJTWVzc2FnZS5qYXZhCjB4NzEwYzRmMTgJYW5kcm' +
+ '9pZC5vcy5QYXJjZWwJaW5pdAkoSilWCVBhcmNlbC5qYXZhCjB4' +
+ 'NzEwYzRmYTgJYW5kcm9pZC5vcy5QYXJjZWwJb2J0YWluCShKKU' +
+ 'xhbmRyb2lkL29zL1BhcmNlbDsJUGFyY2VsLmphdmEKMHg3MTBj' +
+ 'NTQyOAlhbmRyb2lkLm9zLlBhcmNlbAllbmZvcmNlSW50ZXJmYW' +
+ 'NlCShMamF2YS9sYW5nL1N0cmluZzspVglQYXJjZWwuamF2YQow' +
+ 'eDcxMGM1OWY4CWFuZHJvaWQub3MuUGFyY2VsCXJlYWRJbnQJKC' +
+ 'lJCVBhcmNlbC5qYXZhCjB4NzEwYzZhNDgJYW5kcm9pZC5vcy5Q' +
+ 'YXJjZWxGaWxlRGVzY3JpcHRvcgljbG9zZVdpdGhTdGF0dXMJKE' +
+ 'lMamF2YS9sYW5nL1N0cmluZzspVglQYXJjZWxGaWxlRGVzY3Jp' +
+ 'cHRvci5qYXZhCjB4NzEwYzZkNzgJYW5kcm9pZC5vcy5QYXJjZW' +
+ 'xGaWxlRGVzY3JpcHRvcgl3cml0ZUNvbW1TdGF0dXNBbmRDbG9z' +
+ 'ZQkoSUxqYXZhL2xhbmcvU3RyaW5nOylWCVBhcmNlbEZpbGVEZX' +
+ 'NjcmlwdG9yLmphdmEKMHg3MTBjNmUwOAlhbmRyb2lkLm9zLlBh' +
+ 'cmNlbEZpbGVEZXNjcmlwdG9yCWNsb3NlCSgpVglQYXJjZWxGaW' +
+ 'xlRGVzY3JpcHRvci5qYXZhCjB4NzEwYzZmZTgJYW5kcm9pZC5v' +
+ 'cy5QYXJjZWxGaWxlRGVzY3JpcHRvcglyZWxlYXNlUmVzb3VyY2' +
+ 'VzCSgpVglQYXJjZWxGaWxlRGVzY3JpcHRvci5qYXZhCjB4NzEx' +
+ 'NWIwZjgJYW5kcm9pZC5vcy5NZXNzYWdlUXVldWUJZW5xdWV1ZU' +
+ '1lc3NhZ2UJKExhbmRyb2lkL29zL01lc3NhZ2U7SilaCU1lc3Nh' +
+ 'Z2VRdWV1ZS5qYXZhCjB4NzExNWIyMTgJYW5kcm9pZC5vcy5NZX' +
+ 'NzYWdlUXVldWUJbmV4dAkoKUxhbmRyb2lkL29zL01lc3NhZ2U7' +
+ 'CU1lc3NhZ2VRdWV1ZS5qYXZhCjB4NzE3ZTM2MzAJZGFsdmlrLn' +
+ 'N5c3RlbS5WTURlYnVnCXN0YXJ0TWV0aG9kVHJhY2luZ0ZkCShM' +
+ 'amF2YS9sYW5nL1N0cmluZztMamF2YS9pby9GaWxlRGVzY3JpcH' +
+ 'RvcjtJSVpJKVYJVk1EZWJ1Zy5qYXZhCjB4NzE4MTBhMjAJamF2' +
+ 'YS5pby5GaWxlRGVzY3JpcHRvcglpc1NvY2tldAkoKVoJRmlsZU' +
+ 'Rlc2NyaXB0b3IuamF2YQoweDcxODEwYWUwCWphdmEuaW8uRmls' +
+ 'ZURlc2NyaXB0b3IJdmFsaWQJKClaCUZpbGVEZXNjcmlwdG9yLm' +
+ 'phdmEKMHg3MTgxYmI4MAlsaWJjb3JlLmlvLklvVXRpbHMJY2xv' +
+ 'c2UJKExqYXZhL2lvL0ZpbGVEZXNjcmlwdG9yOylWCUlvVXRpbH' +
+ 'MuamF2YQoweDcxODFiYmIwCWxpYmNvcmUuaW8uSW9VdGlscwlj' +
+ 'bG9zZVF1aWV0bHkJKExqYXZhL2lvL0ZpbGVEZXNjcmlwdG9yOy' +
+ 'lWCUlvVXRpbHMuamF2YQoweDcxODIxZWUwCWFuZHJvaWQuYXBw' +
+ 'LkFjdGl2aXR5VGhyZWFkCWFjY2VzcyQzMDAJKExhbmRyb2lkL2' +
+ 'FwcC9BY3Rpdml0eVRocmVhZDtJTGphdmEvbGFuZy9PYmplY3Q7' +
+ 'SUkpVglBY3Rpdml0eVRocmVhZC5qYXZhCjB4NzE4MjJhZTAJYW' +
+ '5kcm9pZC5hcHAuQWN0aXZpdHlUaHJlYWQJc2VuZE1lc3NhZ2UJ' +
+ 'KElMamF2YS9sYW5nL09iamVjdDtJSSlWCUFjdGl2aXR5VGhyZW' +
+ 'FkLmphdmEKMHg3MTgyMmIxMAlhbmRyb2lkLmFwcC5BY3Rpdml0' +
+ 'eVRocmVhZAlzZW5kTWVzc2FnZQkoSUxqYXZhL2xhbmcvT2JqZW' +
+ 'N0O0lJWilWCUFjdGl2aXR5VGhyZWFkLmphdmEKMHg3MTgyMzIz' +
+ 'MAlhbmRyb2lkLmFwcC5BY3Rpdml0eVRocmVhZAloYW5kbGVQcm' +
+ '9maWxlckNvbnRyb2wJKFpMYW5kcm9pZC9hcHAvUHJvZmlsZXJJ' +
+ 'bmZvO0kpVglBY3Rpdml0eVRocmVhZC5qYXZhCjB4NzE4MzY3MD' +
+ 'AJYW5kcm9pZC5vcy5EZWJ1ZwlzdG9wTWV0aG9kVHJhY2luZwko' +
+ 'KVYJRGVidWcuamF2YQoqZW5kClNMT1cDACAASxycoWkAAAAOAA' +
+ 'AAAAAAAAAAAAAAAAAAjwoxNn5xxtotAKISAgCPChmE+3CT4y0A' +
+ '/hsCAI8KaTcHcbbkLQAtNQIAjwoIbgxx0eQtAEc1AgCPCkhqDH' +
+ 'Hk5C0AWjUCAI8KWHf7cPLkLQBoNQIAjwpZd/tw/eQtAHM1AgCP' +
+ 'CnhtDHED5S0AeTUCAI8KeW0McQjlLQB+NQIAjwqwu4FxFOUtAI' +
+ 'o1AgCPCoC7gXEa5S0AkDUCAI8K4AqBcSPlLQCaNQIAjwrhCoFx' +
+ 'KuUtAKE1AgCPCqg/AXE65S0AsTUCAI8KIAqBcUDlLQC2NQIAjw' +
+ 'ohCoFxTuUtAMU1AgCPCqk/AXFn5S0A3jUCAI8KgbuBcWzlLQDi' +
+ 'NQIAjwqxu4Fxb+UtAOU1AgCPCuhvDHF15S0A6zUCAI8K6W8McX' +
+ 'nlLQDvNQIAjwpJagxxfOUtAPI1AgCPCgluDHGB5S0A9zUCAI8K' +
+ 'MTKCcYXlLQD6NQIAjwpJNgdxjOUtAAM2AgCPCukvB3GS5S0ACT' +
+ 'YCAI8K+EoMcaTlLQAbNgIAjwr5SgxxwOUtADY2AgCPChiyFXHH' +
+ '5S0APTYCAI8KKKf+cPHlLQBnNgIAjwopp/5w++UtAHE2AgCfCk' +
+ 'h3BXHy2wAAu5RgAJ8KqE8McSvcAADwlGAAnwoYTwxxaNwAACyV' +
+ 'YACfChlPDHGD3AAARpVgAJ8KqU8McZbcAABZlWAAnwqoTwxxrN' +
+ 'wAAG6VYACfChhPDHHL3AAAjpVgAJ8KGU8MceDcAACjlWAAnwqp' +
+ 'Twxx8twAALSVYACfCkgqB3Ea3QAA3ZVgAJ8KKFQMcUHdAAAFlm' +
+ 'AAnwopVAxxjN0AAFGWYACfCvhZDHHD3QAAiJZgAJ8K+VkMcejd' +
+ 'AACslmAAnwr4WQxxAN4AAMOWYACfCvlZDHEa3gAA3ZZgAJ8K+F' +
+ 'kMcS/eAADylmAAnwr5WQxxR94AAAqXYACfCugXB3Fv3gAAM5dg' +
+ 'AJ8K4B6CcYveAABPl2AAnwrgKoJxrN4AAHCXYACfChArgnHQ3g' +
+ 'AAkpdgAJ8K2EYMceTeAACml2AAnwrZRgxxDd8AANCXYACfCig1' +
+ 'B3Er3wAA7pdgAJ8KuDUHcT7fAAAAmGAAnwqINQdxa98AAC+YYA' +
+ 'CfCigvB3GD3wAASJhgAJ8K+LAVcaDfAABjmGAAnwo4Sgxxtt8A' +
+ 'AHiYYACfCjlKDHHL3wAAkJhgAJ8KaEoMce3fAACxmGAAnwppSg' +
+ 'xxAuAAAMWYYACfCvmwFXFz4AAAOJlgAI8KGbIVcU3mLQBAmWAA' +
+ 'jwroLwdxVuYtAEmZYACfCikvB3GG4AAASZlgAI8KSDYHcVzmLQ' +
+ 'BPmWAAjwowMoJxZuYtAFmZYACfCok1B3GW4AAAWJlgAI8KmDcH' +
+ 'cXTmLQBnmWAAnwq5NQdxr+AAAHGZYACPCgBng3GC5i0AdplgAJ' +
+ '8KKTUHcb3gAAB/mWAAnwoRK4JxzOAAAI6ZYAA=');
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/etw_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/etw_importer.html
new file mode 100644
index 00000000000..c0e928ebdc4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/etw_importer.html
@@ -0,0 +1,483 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/extras/importer/etw/eventtrace_parser.html">
+<link rel="import" href="/tracing/extras/importer/etw/process_parser.html">
+<link rel="import" href="/tracing/extras/importer/etw/thread_parser.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+/**
+ * @fileoverview Imports JSON file with the raw payloads from a Windows event
+ * trace into the Model. This format is outputted by Chrome running
+ * on a Windows system.
+ *
+ * This importer assumes the events arrived as a JSON file and the payloads are
+ * undecoded sequence of bytes in hex format string. The unit tests provide
+ * examples of the trace format.
+ *
+ * The format of the system trace is
+ * {
+ * name: 'ETW',
+ * content: [ <events> ]
+ * }
+ *
+ * where the <events> are dictionary values with fields.
+ *
+ * {
+ * guid: "1234-...", // The unique GUID for the event.
+ * op: 12, // The opcode of the event.
+ * ver: 1, // The encoding version of the event.
+ * cpu: 0, // The cpu id on which the event was captured.
+ * ts: 1092, // The thread id on which the event was captured.
+ * payload: "aaaa" // A base64 encoded string of the raw payload.
+ * }
+ *
+ * The payload is an undecoded version of the raw event sent by ETW.
+ * This importer uses specific parsers to decode recognized events.
+ * A parser need to register the recognized event by calling
+ * registerEventHandler(guid, opcode, handler). The parser is responsible to
+ * decode the payload and update the Model.
+ *
+ * The payload formats are described there:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa364085(v=vs.85).aspx
+ *
+ */
+'use strict';
+
+tr.exportTo('tr.e.importer.etw', function() {
+ // GUID and opcode of a Thread DCStart event, as defined at the link above.
+ const kThreadGuid = '3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';
+ const kThreadDCStartOpcode = 3;
+
+ /**
+ * Represents the raw bytes payload decoder.
+ * @constructor
+ */
+ function Decoder() {
+ this.payload_ = new DataView(new ArrayBuffer(256));
+ }
+
+ Decoder.prototype = {
+ __proto__: Object.prototype,
+
+ reset(base64Payload) {
+ const decodedSize = tr.b.Base64.getDecodedBufferLength(base64Payload);
+ if (decodedSize > this.payload_.byteLength) {
+ this.payload_ = new DataView(new ArrayBuffer(decodedSize));
+ }
+
+ tr.b.Base64.DecodeToTypedArray(base64Payload, this.payload_);
+ this.position_ = 0;
+ },
+
+ skip(length) {
+ this.position_ += length;
+ },
+
+ decodeUInt8() {
+ const result = this.payload_.getUint8(this.position_, true);
+ this.position_ += 1;
+ return result;
+ },
+
+ decodeUInt16() {
+ const result = this.payload_.getUint16(this.position_, true);
+ this.position_ += 2;
+ return result;
+ },
+
+ decodeUInt32() {
+ const result = this.payload_.getUint32(this.position_, true);
+ this.position_ += 4;
+ return result;
+ },
+
+ decodeUInt64ToString() {
+ // Javascript isn't able to manage 64-bit numeric values.
+ const low = this.decodeUInt32();
+ const high = this.decodeUInt32();
+ const lowStr = ('0000000' + low.toString(16)).substr(-8);
+ const highStr = ('0000000' + high.toString(16)).substr(-8);
+ const result = highStr + lowStr;
+ return result;
+ },
+
+ decodeInt8() {
+ const result = this.payload_.getInt8(this.position_, true);
+ this.position_ += 1;
+ return result;
+ },
+
+ decodeInt16() {
+ const result = this.payload_.getInt16(this.position_, true);
+ this.position_ += 2;
+ return result;
+ },
+
+ decodeInt32() {
+ const result = this.payload_.getInt32(this.position_, true);
+ this.position_ += 4;
+ return result;
+ },
+
+ decodeInt64ToString() {
+ // Javascript isn't able to manage 64-bit numeric values.
+ // Fallback to unsigned 64-bit hexa value.
+ return this.decodeUInt64ToString();
+ },
+
+ decodeUInteger(is64) {
+ if (is64) {
+ return this.decodeUInt64ToString();
+ }
+ return this.decodeUInt32();
+ },
+
+ decodeString() {
+ let str = '';
+ while (true) {
+ const c = this.decodeUInt8();
+ if (!c) return str;
+ str = str + String.fromCharCode(c);
+ }
+ },
+
+ decodeW16String() {
+ let str = '';
+ while (true) {
+ const c = this.decodeUInt16();
+ if (!c) return str;
+ str = str + String.fromCharCode(c);
+ }
+ },
+
+ decodeFixedW16String(length) {
+ const oldPosition = this.position_;
+ let str = '';
+ for (let i = 0; i < length; i++) {
+ const c = this.decodeUInt16();
+ if (!c) break;
+ str = str + String.fromCharCode(c);
+ }
+
+ // Move the position after the fixed buffer (i.e. wchar[length]).
+ this.position_ = oldPosition + 2 * length;
+ return str;
+ },
+
+ decodeBytes(length) {
+ const bytes = [];
+ for (let i = 0; i < length; ++i) {
+ const c = this.decodeUInt8();
+ bytes.push(c);
+ }
+ return bytes;
+ },
+
+ decodeSID(is64) {
+ // Decode the TOKEN_USER structure.
+ const pSid = this.decodeUInteger(is64);
+ const attributes = this.decodeUInt32();
+
+ // Skip padding.
+ if (is64) {
+ this.decodeUInt32();
+ }
+
+ // Decode the SID structure.
+ const revision = this.decodeUInt8();
+ const subAuthorityCount = this.decodeUInt8();
+ this.decodeUInt16();
+ this.decodeUInt32();
+
+ if (revision !== 1) {
+ throw new Error(
+ 'Invalid SID revision: could not decode the SID structure.');
+ }
+
+ const sid = this.decodeBytes(4 * subAuthorityCount);
+
+ return {
+ pSid,
+ attributes,
+ sid
+ };
+ },
+
+ decodeSystemTime() {
+ // Decode the SystemTime structure.
+ const wYear = this.decodeInt16();
+ const wMonth = this.decodeInt16();
+ const wDayOfWeek = this.decodeInt16();
+ const wDay = this.decodeInt16();
+ const wHour = this.decodeInt16();
+ const wMinute = this.decodeInt16();
+ const wSecond = this.decodeInt16();
+ const wMilliseconds = this.decodeInt16();
+ return {
+ wYear,
+ wMonth,
+ wDayOfWeek,
+ wDay,
+ wHour,
+ wMinute,
+ wSecond,
+ wMilliseconds
+ };
+ },
+
+ decodeTimeZoneInformation() {
+ // Decode the TimeZoneInformation structure.
+ const bias = this.decodeUInt32();
+ const standardName = this.decodeFixedW16String(32);
+ const standardDate = this.decodeSystemTime();
+ const standardBias = this.decodeUInt32();
+ const daylightName = this.decodeFixedW16String(32);
+ const daylightDate = this.decodeSystemTime();
+ const daylightBias = this.decodeUInt32();
+ return {
+ bias,
+ standardName,
+ standardDate,
+ standardBias,
+ daylightName,
+ daylightDate,
+ daylightBias
+ };
+ }
+
+ };
+
+ /**
+ * Imports Windows ETW kernel events into a specified model.
+ * @constructor
+ */
+ function EtwImporter(model, events) {
+ this.importPriority = 3;
+ this.model_ = model;
+ this.events_ = events;
+ this.handlers_ = {};
+ this.decoder_ = new Decoder();
+ this.walltime_ = undefined;
+ this.ticks_ = undefined;
+ this.is64bit_ = undefined;
+
+ // A map of tids to their process pid. On Windows, the tid is global to
+ // the system and doesn't need to belong to a process. As many events
+ // only provide tid, this map allows to retrieve the parent process.
+ this.tidsToPid_ = {};
+
+ // Instantiate the parsers; this will register handlers for known events.
+ const allTypeInfos = tr.e.importer.etw.Parser.getAllRegisteredTypeInfos();
+ this.parsers_ = allTypeInfos.map(
+ function(typeInfo) {
+ return new typeInfo.constructor(this);
+ }, this);
+ }
+
+ /**
+ * Guesses whether the provided events is from a Windows ETW trace.
+ * The object must has a property named 'name' with the value 'ETW' and
+ * a property 'content' with all the undecoded events.
+ *
+ * @return {boolean} True when events is a Windows ETW array.
+ */
+ EtwImporter.canImport = function(events) {
+ if (!events.hasOwnProperty('name') ||
+ !events.hasOwnProperty('content') ||
+ events.name !== 'ETW') {
+ return false;
+ }
+
+ return true;
+ };
+
+ EtwImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'EtwImporter';
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ createThreadIfNeeded(pid, tid) {
+ this.tidsToPid_[tid] = pid;
+ },
+
+ removeThreadIfPresent(tid) {
+ this.tidsToPid_[tid] = undefined;
+ },
+
+ getPidFromWindowsTid(tid) {
+ if (tid === 0) return 0;
+ const pid = this.tidsToPid_[tid];
+ if (pid === undefined) {
+ // Kernel threads are not defined.
+ return 0;
+ }
+ return pid;
+ },
+
+ getThreadFromWindowsTid(tid) {
+ const pid = this.getPidFromWindowsTid(tid);
+ const process = this.model_.getProcess(pid);
+ if (!process) return undefined;
+ return process.getThread(tid);
+ },
+
+ /*
+ * Retrieve the Cpu for a given cpuNumber.
+ * @return {Cpu} A Cpu corresponding to the given cpuNumber.
+ */
+ getOrCreateCpu(cpuNumber) {
+ const cpu = this.model_.kernel.getOrCreateCpu(cpuNumber);
+ return cpu;
+ },
+
+ /**
+ * Imports the data in this.events_ into this.model_.
+ */
+ importEvents() {
+ this.events_.content.forEach(this.parseInfo.bind(this));
+
+ if (this.walltime_ === undefined || this.ticks_ === undefined) {
+ throw Error('Cannot find clock sync information in the system trace.');
+ }
+
+ if (this.is64bit_ === undefined) {
+ throw Error('Cannot determine pointer size of the system trace.');
+ }
+
+ this.events_.content.forEach(this.parseEvent.bind(this));
+ },
+
+ importTimestamp(timestamp) {
+ const ts = parseInt(timestamp, 16);
+ return (ts - this.walltime_ + this.ticks_) / 1000.;
+ },
+
+ parseInfo(event) {
+ // Retrieve clock sync information.
+ if (event.hasOwnProperty('guid') &&
+ event.hasOwnProperty('walltime') &&
+ event.hasOwnProperty('tick') &&
+ event.guid === 'ClockSync') {
+ this.walltime_ = parseInt(event.walltime, 16);
+ this.ticks_ = parseInt(event.tick, 16);
+ }
+
+ // Retrieve pointer size information from a Thread.DCStart event.
+ if (this.is64bit_ === undefined &&
+ event.hasOwnProperty('guid') &&
+ event.hasOwnProperty('op') &&
+ event.hasOwnProperty('ver') &&
+ event.hasOwnProperty('payload') &&
+ event.guid === kThreadGuid &&
+ event.op === kThreadDCStartOpcode) {
+ const decodedSize = tr.b.Base64.getDecodedBufferLength(event.payload);
+
+ if (event.ver === 1) {
+ if (decodedSize >= 52) {
+ this.is64bit_ = true;
+ } else {
+ this.is64bit_ = false;
+ }
+ } else if (event.ver === 2) {
+ if (decodedSize >= 64) {
+ this.is64bit_ = true;
+ } else {
+ this.is64bit_ = false;
+ }
+ } else if (event.ver === 3) {
+ if (decodedSize >= 60) {
+ this.is64bit_ = true;
+ } else {
+ this.is64bit_ = false;
+ }
+ }
+ }
+
+ return true;
+ },
+
+ parseEvent(event) {
+ if (!event.hasOwnProperty('guid') ||
+ !event.hasOwnProperty('op') ||
+ !event.hasOwnProperty('ver') ||
+ !event.hasOwnProperty('cpu') ||
+ !event.hasOwnProperty('ts') ||
+ !event.hasOwnProperty('payload')) {
+ return false;
+ }
+
+ const timestamp = this.importTimestamp(event.ts);
+
+ // Create the event header.
+ const header = {
+ guid: event.guid,
+ opcode: event.op,
+ version: event.ver,
+ cpu: event.cpu,
+ timestamp,
+ is64: this.is64bit_
+ };
+
+ // Set the payload to decode.
+ const decoder = this.decoder_;
+ decoder.reset(event.payload);
+
+ // Retrieve the handler to decode the payload.
+ const handler = this.getEventHandler(header.guid, header.opcode);
+ if (!handler) return false;
+
+ if (!handler(header, decoder)) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Malformed ' + header.guid + ' event (' + event.payload + ')'
+ });
+ return false;
+ }
+
+ return true;
+ },
+
+ /**
+ * Registers a windows ETW event handler used by parseEvent().
+ */
+ registerEventHandler(guid, opcode, handler) {
+ if (this.handlers_[guid] === undefined) {
+ this.handlers_[guid] = [];
+ }
+ this.handlers_[guid][opcode] = handler;
+ },
+
+ /**
+ * Retrieves a registered event handler.
+ */
+ getEventHandler(guid, opcode) {
+ if (this.handlers_[guid] === undefined) {
+ return undefined;
+ }
+ return this.handlers_[guid][opcode];
+ }
+
+ };
+
+ // Register the EtwImporter to the Importer.
+ tr.importer.Importer.register(EtwImporter);
+
+ return {
+ EtwImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/etw_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/etw_importer_test.html
new file mode 100644
index 00000000000..c071b13ff5b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/etw_importer_test.html
@@ -0,0 +1,293 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/etw/etw_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Base64 = tr.b.Base64;
+
+ test('canImport', function() {
+ assert.isFalse(tr.e.importer.etw.EtwImporter.canImport('string'));
+ assert.isFalse(tr.e.importer.etw.EtwImporter.canImport([]));
+
+ // Must not parse an invalid name.
+ const dummy = { name: 'dummy', content: [] };
+ assert.isFalse(tr.e.importer.etw.EtwImporter.canImport(dummy));
+
+ // Must parse an empty valid trace.
+ const valid = { name: 'ETW', content: [] };
+ assert.isTrue(tr.e.importer.etw.EtwImporter.canImport(valid));
+ });
+
+ test('getModel', function() {
+ const model = 'dummy';
+ const events = [];
+ const importer = new tr.e.importer.etw.EtwImporter(model, events);
+ assert.strictEqual(importer.model, model);
+ });
+
+ test('registerEventHandler', function() {
+ // Create a dummy EtwImporter.
+ const model = 'dummy';
+ const events = ['events'];
+ const importer = new tr.e.importer.etw.EtwImporter(model, events);
+ const dummyHandler = function() {};
+
+ // The handler must not exists.
+ assert.isUndefined(importer.getEventHandler('ABCDEF', 2));
+
+ // Register an event handler for guid: ABCDEF and opcode: 2.
+ importer.registerEventHandler('ABCDEF', 2, dummyHandler);
+
+ // The handler exists now, must find it.
+ assert.isDefined(importer.getEventHandler('ABCDEF', 2));
+
+ // Must be able to manage an invalid handler.
+ assert.isUndefined(importer.getEventHandler('zzzzzz', 2));
+ });
+
+ test('parseEvent', function() {
+ const model = 'dummy';
+ const events = [];
+ const importer = new tr.e.importer.etw.EtwImporter(model, events);
+ let handlerCalled = false;
+ const dummyHandler = function() { handlerCalled = true; return true; };
+
+ // Register a valid handler.
+ importer.registerEventHandler('aaaa', 42, dummyHandler);
+
+ // Try to parse an invalid event with missing fields.
+ const incompleteEvent = { 'guid': 'aaaa', 'op': 42, 'ver': 0 };
+ assert.isFalse(importer.parseEvent(incompleteEvent));
+ assert.isFalse(handlerCalled);
+
+ // Try to parse a valid event.
+ const validEvent = {
+ 'guid': 'aaaa', 'op': 42, 'ver': 0, 'cpu': 0, 'ts': 0,
+ 'payload': Base64.btoa('0')
+ };
+ assert.isTrue(importer.parseEvent(validEvent));
+ assert.isTrue(handlerCalled);
+ });
+
+ test('resetTooSmall', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+
+ const oldByteLength = decoder.payload_.byteLength;
+ // Decode a payload too big for the actual buffer.
+ decoder.reset('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==');
+ const newByteLength = decoder.payload_.byteLength;
+
+ // Validate the buffer has been resized.
+ assert.isBelow(oldByteLength, newByteLength);
+ });
+
+ test('decode', function() {
+ const model = 'dummy';
+ const events = [];
+ const importer = new tr.e.importer.etw.EtwImporter(model, events);
+
+ const decoder = importer.decoder_;
+
+ decoder.reset('YQBiYw==');
+ assert.strictEqual(decoder.decodeInt32(), 0x63620061);
+
+ // Decode unsigned numbers.
+ decoder.reset('AQ==');
+ assert.strictEqual(decoder.decodeUInt8(), 0x01);
+
+ decoder.reset('AQI=');
+ assert.strictEqual(decoder.decodeUInt16(), 0x0201);
+
+ decoder.reset('AQIDBA==');
+ assert.strictEqual(decoder.decodeUInt32(), 0x04030201);
+
+ decoder.reset('AQIDBAUGBwg=');
+ assert.strictEqual(decoder.decodeUInt64ToString(), '0807060504030201');
+
+ // Decode signed numbers.
+ decoder.reset('AQ==');
+ assert.strictEqual(decoder.decodeInt8(), 0x01);
+
+ decoder.reset('AQI=');
+ assert.strictEqual(decoder.decodeInt16(), 0x0201);
+
+ decoder.reset('AQIDBA==');
+ assert.strictEqual(decoder.decodeInt32(), 0x04030201);
+
+ decoder.reset('AQIDBAUGBwg=');
+ assert.strictEqual(decoder.decodeInt64ToString(), '0807060504030201');
+
+ // Last value before being a signed number.
+ decoder.reset('fw==');
+ assert.strictEqual(decoder.decodeInt8(), 127);
+
+ // Decode negative numbers.
+ decoder.reset('1g==');
+ assert.strictEqual(decoder.decodeInt8(), -42);
+
+ decoder.reset('gA==');
+ assert.strictEqual(decoder.decodeInt8(), -128);
+
+ decoder.reset('hYI=');
+ assert.strictEqual(decoder.decodeInt16(), -32123);
+
+ decoder.reset('hYL//w==');
+ assert.strictEqual(decoder.decodeInt32(), -32123);
+
+ decoder.reset('Lv1ptv////8=');
+ assert.strictEqual(decoder.decodeInt32(), -1234567890);
+
+ // Decode number with zero (nul) in the middle of the string.
+ decoder.reset('YQBiYw==');
+ assert.strictEqual(decoder.decodeInt32(), 0x63620061);
+ });
+
+ test('decodeUInteger', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+
+ decoder.reset('AQIDBAUGBwg=');
+ assert.strictEqual(decoder.decodeUInteger(false), 0x04030201);
+
+ decoder.reset('AQIDBAUGBwg=');
+ assert.strictEqual(decoder.decodeUInteger(true), '0807060504030201');
+ });
+
+ test('decodeString', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+
+ decoder.reset('dGVzdAA=');
+ assert.strictEqual(decoder.decodeString(), 'test');
+
+ decoder.reset('VGhpcyBpcyBhIHRlc3Qu');
+ assert.strictEqual(decoder.decodeString(), 'This is a test.');
+ });
+
+ test('decodeW16String', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+ decoder.reset('dABlAHMAdAAAAA==');
+ assert.strictEqual(decoder.decodeW16String(), 'test');
+ });
+
+ test('decodeFixedW16String', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+ decoder.reset('dABlAHMAdAAAAA==');
+ assert.strictEqual(decoder.decodeFixedW16String(32), 'test');
+ assert.strictEqual(decoder.position_, 64);
+
+ decoder.reset('dABlAHMAdAAAAA==');
+ assert.strictEqual(decoder.decodeFixedW16String(1), 't');
+ assert.strictEqual(decoder.position_, 2);
+ });
+
+ test('decodeBytes', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+ decoder.reset('AAECAwQFBgc=');
+ const bytes = decoder.decodeBytes(8);
+ for (let i = 0; i < bytes.length; ++i) {
+ assert.strictEqual(bytes[i], i);
+ }
+ });
+
+ test('decodeSID', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+
+ // Decode a SID structure with 64-bit pointer.
+ decoder.reset(
+ 'AQIDBAECAwQFBAMCAAAAAAEFAAAAAAAFFQAAAAECAwQFBgcICQoLDA0DAAA=');
+ const sid = decoder.decodeSID(true);
+
+ assert.strictEqual(sid.pSid, '0403020104030201');
+ assert.strictEqual(sid.attributes, 0x02030405);
+ assert.strictEqual(sid.sid.length, 20);
+ });
+
+ test('decodeSystemTime', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+
+ // Decode a SystemTime structure.
+ decoder.reset('AQACAAMABAAFAAYABwAIAA==');
+ const time = decoder.decodeSystemTime();
+ assert.strictEqual(time.wYear, 1);
+ assert.strictEqual(time.wMonth, 2);
+ assert.strictEqual(time.wDayOfWeek, 3);
+ assert.strictEqual(time.wDay, 4);
+ assert.strictEqual(time.wHour, 5);
+ assert.strictEqual(time.wMinute, 6);
+ assert.strictEqual(time.wSecond, 7);
+ assert.strictEqual(time.wMilliseconds, 8);
+ });
+
+ test('decodeTimeZoneInformation', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+
+ // Decode a TimeZoneInformation structure.
+ decoder.reset('AQIDBGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIAAwAEAAUABgAHAAgABA' +
+ 'MCAWIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIAAwAEAAUABgAHAAgACAgI' +
+ 'CA==');
+ const time = decoder.decodeTimeZoneInformation();
+
+ assert.strictEqual(time.bias, 0x04030201);
+ assert.strictEqual(time.standardBias, 0x01020304);
+ assert.strictEqual(time.daylightBias, 0x08080808);
+ assert.strictEqual(time.standardName, 'a');
+ assert.strictEqual(time.daylightName, 'b');
+ });
+
+ test('manageThreads', function() {
+ const events = [];
+ const model = 'dummy';
+ const importer = new tr.e.importer.etw.EtwImporter(model, events);
+
+ // After initialisation, no threads must exists.
+ assert.strictEqual(
+ Object.getOwnPropertyNames(importer.tidsToPid_).length, 0);
+
+ // Add some threads.
+ const thread10 = importer.createThreadIfNeeded(1, 10);
+ const thread11 = importer.createThreadIfNeeded(1, 11);
+ const thread20 = importer.createThreadIfNeeded(2, 20);
+
+ assert.strictEqual(
+ Object.getOwnPropertyNames(importer.tidsToPid_).length, 3);
+ assert.isTrue(importer.tidsToPid_.hasOwnProperty(10));
+ assert.isTrue(importer.tidsToPid_.hasOwnProperty(11));
+ assert.isTrue(importer.tidsToPid_.hasOwnProperty(20));
+
+ // Retrieve existing threads and processes.
+ const pid10 = importer.getPidFromWindowsTid(10);
+ const pid11 = importer.getPidFromWindowsTid(11);
+ const pid20 = importer.getPidFromWindowsTid(20);
+
+ assert.strictEqual(pid10, 1);
+ assert.strictEqual(pid11, 1);
+ assert.strictEqual(pid20, 2);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/eventtrace_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/eventtrace_parser.html
new file mode 100644
index 00000000000..5dd1bcec174
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/eventtrace_parser.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/etw/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses EventTrace events in the Windows event trace format.
+ */
+
+tr.exportTo('tr.e.importer.etw', function() {
+ const Parser = tr.e.importer.etw.Parser;
+
+ // Constants for EventTrace events.
+ const guid = '68FDD900-4A3E-11D1-84F4-0000F80464E3';
+ const kEventTraceHeaderOpcode = 0;
+
+ /**
+ * Parses Windows EventTrace trace events.
+ * @constructor
+ */
+ function EventTraceParser(importer) {
+ Parser.call(this, importer);
+
+ // Register handlers.
+ importer.registerEventHandler(guid, kEventTraceHeaderOpcode,
+ EventTraceParser.prototype.decodeHeader.bind(this));
+ }
+
+ EventTraceParser.prototype = {
+ __proto__: Parser.prototype,
+
+ decodeFields(header, decoder) {
+ if (header.version !== 2) {
+ throw new Error('Incompatible EventTrace event version.');
+ }
+
+ const bufferSize = decoder.decodeUInt32();
+ const version = decoder.decodeUInt32();
+ const providerVersion = decoder.decodeUInt32();
+ const numberOfProcessors = decoder.decodeUInt32();
+ const endTime = decoder.decodeUInt64ToString();
+ const timerResolution = decoder.decodeUInt32();
+ const maxFileSize = decoder.decodeUInt32();
+ const logFileMode = decoder.decodeUInt32();
+ const buffersWritten = decoder.decodeUInt32();
+ const startBuffers = decoder.decodeUInt32();
+ const pointerSize = decoder.decodeUInt32();
+ const eventsLost = decoder.decodeUInt32();
+ const cpuSpeed = decoder.decodeUInt32();
+ const loggerName = decoder.decodeUInteger(header.is64);
+ const logFileName = decoder.decodeUInteger(header.is64);
+ const timeZoneInformation = decoder.decodeTimeZoneInformation();
+ const padding = decoder.decodeUInt32();
+ const bootTime = decoder.decodeUInt64ToString();
+ const perfFreq = decoder.decodeUInt64ToString();
+ const startTime = decoder.decodeUInt64ToString();
+ const reservedFlags = decoder.decodeUInt32();
+ const buffersLost = decoder.decodeUInt32();
+ const sessionNameString = decoder.decodeW16String();
+ const logFileNameString = decoder.decodeW16String();
+
+ return {
+ bufferSize,
+ version,
+ providerVersion,
+ numberOfProcessors,
+ endTime,
+ timerResolution,
+ maxFileSize,
+ logFileMode,
+ buffersWritten,
+ startBuffers,
+ pointerSize,
+ eventsLost,
+ cpuSpeed,
+ loggerName,
+ logFileName,
+ timeZoneInformation,
+ bootTime,
+ perfFreq,
+ startTime,
+ reservedFlags,
+ buffersLost,
+ sessionNameString,
+ logFileNameString
+ };
+ },
+
+ decodeHeader(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ // TODO(etienneb): Update the Model with |fields|.
+ return true;
+ }
+
+ };
+
+ Parser.register(EventTraceParser);
+
+ return {
+ EventTraceParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/eventtrace_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/eventtrace_parser_test.html
new file mode 100644
index 00000000000..bfa2caed994
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/eventtrace_parser_test.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/etw/etw_importer.html">
+<link rel="import" href="/tracing/extras/importer/etw/eventtrace_parser.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ // Constants for EventTrace events.
+ const guid = '68FDD900-4A3E-11D1-84F4-0000F80464E3';
+ const kEventTraceHeaderOpcode = 0;
+
+ const kEventTraceHeaderPayload32bitV2 =
+ 'AAABAAYBAQWwHQAAEAAAABEs1WHICMwBYWECAGQAAAABAAAAAwAAAAEAAAAEAAAAAAAAA' +
+ 'FoJAAAFAAAABgAAACwBAABAAHQAegByAGUAcwAuAGQAbABsACwALQAxADEAMgAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAAAAAQACAAAAAAAAAAAAAABAAHQ' +
+ 'AegByAGUAcwAuAGQAbABsACwALQAxADEAMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAADAAAAAgACAAAAAAAAAMT///8AAAAAf0Ob368FzAGdrCMAAAAAACw0o' +
+ '2DICMwBAQAAAAAAAABNAGEAawBlACAAVABlAHMAdAAgAEQAYQB0AGEAIABTAGUAcwBzAG' +
+ 'kAbwBuAAAAYwA6AFwAcwByAGMAXABzAGEAdwBiAHUAYwBrAFwAdAByAHUAbgBrAFwAcwB' +
+ 'yAGMAXABzAGEAdwBiAHUAYwBrAFwAbABvAGcAXwBsAGkAYgBcAHQAZQBzAHQAXwBkAGEA' +
+ 'dABhAFwAaQBtAGEAZwBlAF8AZABhAHQAYQBfADMAMgBfAHYAMAAuAGUAdABsAAAA';
+
+ const kEventTraceHeaderPayload64bitV2 =
+ 'AAABAAYBAQWxHQAABAAAADsuzRRYLM8BYWECAAAAAAABAAEAtgEAAAEAAAAIAAAAHwAAA' +
+ 'KAGAAAAAAAAAAAAAAAAAAAAAAAALAEAAEAAdAB6AHIAZQBzAC4AZABsAGwALAAtADEAMQ' +
+ 'AyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAABAAIAAAAAAAA' +
+ 'AAAAAAEAAdAB6AHIAZQBzAC4AZABsAGwALAAtADEAMQAxAAAAAAAAAAAAAAAAAAAAAAAA' +
+ 'AAAAAAAAAAAAAAAAAAAAAAAAAAMAAAACAAIAAAAAAAAAxP///wAAAABZQyWiwCvPAX1GG' +
+ 'QAAAAAALWSZBFgszwEBAAAAAAAAAFIAZQBsAG8AZwBnAGUAcgAAAEMAOgBcAGsAZQByAG' +
+ '4AZQBsAC4AZQB0AGwAAAA=';
+
+ test('DecodeFields', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+ const parser = new tr.e.importer.etw.EventTraceParser(importer);
+ let header;
+ let fields;
+
+ // Validate a version 2 32-bit payload.
+ header = {
+ guid, opcode: kEventTraceHeaderOpcode, version: 2, is64: 0
+ };
+ decoder.reset(kEventTraceHeaderPayload32bitV2);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.bufferSize, 65536);
+ assert.strictEqual(fields.version, 83951878);
+ assert.strictEqual(fields.providerVersion, 7600);
+ assert.strictEqual(fields.numberOfProcessors, 16);
+ assert.strictEqual(fields.endTime, '01cc08c861d52c11');
+ assert.strictEqual(fields.timerResolution, 156001);
+ assert.strictEqual(fields.maxFileSize, 100);
+ assert.strictEqual(fields.logFileMode, 1);
+ assert.strictEqual(fields.buffersWritten, 3);
+ assert.strictEqual(fields.startBuffers, 1);
+ assert.strictEqual(fields.pointerSize, 4);
+ assert.strictEqual(fields.eventsLost, 0);
+ assert.strictEqual(fields.cpuSpeed, 2394);
+ assert.strictEqual(fields.loggerName, 5);
+ assert.strictEqual(fields.logFileName, 6);
+ assert.strictEqual(fields.timeZoneInformation.standardName,
+ '@tzres.dll,-112');
+ assert.strictEqual(fields.timeZoneInformation.daylightName,
+ '@tzres.dll,-111');
+ assert.strictEqual(fields.bootTime, '01cc05afdf9b437f');
+ assert.strictEqual(fields.perfFreq, '000000000023ac9d');
+ assert.strictEqual(fields.startTime, '01cc08c860a3342c');
+ assert.strictEqual(fields.reservedFlags, 1);
+ assert.strictEqual(fields.buffersLost, 0);
+ assert.strictEqual(fields.sessionNameString, 'Make Test Data Session');
+ assert.strictEqual(fields.logFileNameString,
+ 'c:\\src\\sawbuck\\trunk\\src\\sawbuck\\log_lib\\' +
+ 'test_data\\image_data_32_v0.etl');
+
+ // Validate a version 2 64-bit payload.
+ header = {
+ guid, opcode: kEventTraceHeaderOpcode, version: 2, is64: 1
+ };
+ decoder.reset(kEventTraceHeaderPayload64bitV2);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.bufferSize, 65536);
+ assert.strictEqual(fields.version, 83951878);
+ assert.strictEqual(fields.providerVersion, 7601);
+ assert.strictEqual(fields.numberOfProcessors, 4);
+ assert.strictEqual(fields.endTime, '01cf2c5814cd2e3b');
+ assert.strictEqual(fields.timerResolution, 156001);
+ assert.strictEqual(fields.maxFileSize, 0);
+ assert.strictEqual(fields.logFileMode, 0x10001);
+ assert.strictEqual(fields.buffersWritten, 438);
+ assert.strictEqual(fields.startBuffers, 1);
+ assert.strictEqual(fields.pointerSize, 8);
+ assert.strictEqual(fields.eventsLost, 31);
+ assert.strictEqual(fields.cpuSpeed, 1696);
+ assert.strictEqual(fields.loggerName, '0000000000000000');
+ assert.strictEqual(fields.logFileName, '0000000000000000');
+ assert.strictEqual(fields.timeZoneInformation.standardName,
+ '@tzres.dll,-112');
+ assert.strictEqual(fields.timeZoneInformation.daylightName,
+ '@tzres.dll,-111');
+ assert.strictEqual(fields.bootTime, '01cf2bc0a2254359');
+ assert.strictEqual(fields.perfFreq, '000000000019467d');
+ assert.strictEqual(fields.startTime, '01cf2c580499642d');
+ assert.strictEqual(fields.reservedFlags, 1);
+ assert.strictEqual(fields.buffersLost, 0);
+ assert.strictEqual(fields.sessionNameString, 'Relogger');
+ assert.strictEqual(fields.logFileNameString, 'C:\\kernel.etl');
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/parser.html
new file mode 100644
index 00000000000..95f9d079e23
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/parser.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/extension_registry.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Base class for Windows ETW event parsers.
+ *
+ * The ETW trace event importer depends on subclasses of
+ * Parser to parse event data. Each subclass corresponds
+ * to a group of trace events; e.g. Thread and Process implements
+ * decoding of scheduling events. Parser subclasses must
+ * call Parser.register to arrange to be instantiated
+ * and their constructor must register their event handlers with the
+ * importer. For example,
+ *
+ * var Parser = tr.e.importer.etw.Parser;
+ *
+ * function ThreadParser(importer) {
+ * Parser.call(this, importer);
+ *
+ * importer.registerEventHandler(guid, kThreadStartOpcode,
+ * ThreadParser.prototype.decodeStart.bind(this));
+ * importer.registerEventHandler(guid, kThreadEndOpcode,
+ * ThreadParser.prototype.decodeEnd.bind(this));
+ * }
+ *
+ * Parser.register(ThreadParser);
+ *
+ * When a registered event is found, the associated event handler is invoked:
+ *
+ * decodeStart: function(header, decoder) {
+ * [...]
+ * return true;
+ * },
+ *
+ * If the routine returns false the caller will generate an import error
+ * saying there was a problem parsing it. Handlers can also emit import
+ * messages using this.importer.model.importWarning. If this is done in lieu of
+ * the generic import error it may be desirable for the handler to return
+ * true.
+ *
+ */
+tr.exportTo('tr.e.importer.etw', function() {
+ /**
+ * Parses Windows ETW events.
+ * @constructor
+ */
+ function Parser(importer) {
+ this.importer = importer;
+ this.model = importer.model;
+ }
+
+ Parser.prototype = {
+ __proto__: Object.prototype
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ options.mandatoryBaseClass = Parser;
+ tr.b.decorateExtensionRegistry(Parser, options);
+
+
+ return {
+ Parser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/process_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/process_parser.html
new file mode 100644
index 00000000000..bb857a9a33d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/process_parser.html
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/etw/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses processes events in the Windows event trace format.
+ *
+ * The Windows process events are:
+ *
+ * - DCStart: Describes a process that was already running when the trace
+ * started. ETW automatically generates these events for all running
+ * processes at the beginning of the trace.
+ * - Start: Describes a process launched during the tracing session.
+ * - End: Describes a process that ended during the tracing session.
+ * - DCEnd: Describes a process that was still running when the trace ended.
+ *
+ * See http://msdn.microsoft.com/library/windows/desktop/aa364092.aspx
+ */
+tr.exportTo('tr.e.importer.etw', function() {
+ const Parser = tr.e.importer.etw.Parser;
+
+ // Constants for Process events.
+ const guid = '3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C';
+ const kProcessStartOpcode = 1;
+ const kProcessEndOpcode = 2;
+ const kProcessDCStartOpcode = 3;
+ const kProcessDCEndOpcode = 4;
+ const kProcessDefunctOpcode = 39;
+
+ /**
+ * Parses Windows process trace events.
+ * @constructor
+ */
+ function ProcessParser(importer) {
+ Parser.call(this, importer);
+
+ // Register handlers.
+ importer.registerEventHandler(guid, kProcessStartOpcode,
+ ProcessParser.prototype.decodeStart.bind(this));
+ importer.registerEventHandler(guid, kProcessEndOpcode,
+ ProcessParser.prototype.decodeEnd.bind(this));
+ importer.registerEventHandler(guid, kProcessDCStartOpcode,
+ ProcessParser.prototype.decodeDCStart.bind(this));
+ importer.registerEventHandler(guid, kProcessDCEndOpcode,
+ ProcessParser.prototype.decodeDCEnd.bind(this));
+ importer.registerEventHandler(guid, kProcessDefunctOpcode,
+ ProcessParser.prototype.decodeDefunct.bind(this));
+ }
+
+ ProcessParser.prototype = {
+ __proto__: Parser.prototype,
+
+ decodeFields(header, decoder) {
+ if (header.version > 5) {
+ throw new Error('Incompatible Process event version.');
+ }
+
+ let pageDirectoryBase;
+ if (header.version === 1) {
+ pageDirectoryBase = decoder.decodeUInteger(header.is64);
+ }
+
+ let uniqueProcessKey;
+ if (header.version >= 2) {
+ uniqueProcessKey = decoder.decodeUInteger(header.is64);
+ }
+
+ const processId = decoder.decodeUInt32();
+ const parentId = decoder.decodeUInt32();
+
+ let sessionId;
+ let exitStatus;
+ if (header.version >= 1) {
+ sessionId = decoder.decodeUInt32();
+ exitStatus = decoder.decodeInt32();
+ }
+
+ let directoryTableBase;
+ if (header.version >= 3) {
+ directoryTableBase = decoder.decodeUInteger(header.is64);
+ }
+
+ let flags;
+ if (header.version >= 4) {
+ flags = decoder.decodeUInt32();
+ }
+
+ const userSID = decoder.decodeSID(header.is64);
+
+ let imageFileName;
+ if (header.version >= 1) {
+ imageFileName = decoder.decodeString();
+ }
+
+ let commandLine;
+ if (header.version >= 2) {
+ commandLine = decoder.decodeW16String();
+ }
+
+ let packageFullName;
+ let applicationId;
+ if (header.version >= 4) {
+ packageFullName = decoder.decodeW16String();
+ applicationId = decoder.decodeW16String();
+ }
+
+ let exitTime;
+ if (header.version === 5 && header.opcode === kProcessDefunctOpcode) {
+ exitTime = decoder.decodeUInt64ToString();
+ }
+
+ return {
+ pageDirectoryBase,
+ uniqueProcessKey,
+ processId,
+ parentId,
+ sessionId,
+ exitStatus,
+ directoryTableBase,
+ flags,
+ userSID,
+ imageFileName,
+ commandLine,
+ packageFullName,
+ applicationId,
+ exitTime
+ };
+ },
+
+ decodeStart(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ const process = this.model.getOrCreateProcess(fields.processId);
+ if (process.hasOwnProperty('has_ended')) {
+ // On Windows, a process ID used by a process could be reused as soon as
+ // the process ends (there is no pid cycling like on Linux). However, in
+ // a short trace, this is unlikely to happen.
+ throw new Error('Process clash detected.');
+ }
+ process.name = fields.imageFileName;
+ return true;
+ },
+
+ decodeEnd(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ const process = this.model.getOrCreateProcess(fields.processId);
+ process.has_ended = true;
+ return true;
+ },
+
+ decodeDCStart(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ const process = this.model.getOrCreateProcess(fields.processId);
+ if (process.hasOwnProperty('has_ended')) {
+ throw new Error('Process clash detected.');
+ }
+ process.name = fields.imageFileName;
+ return true;
+ },
+
+ decodeDCEnd(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ const process = this.model.getOrCreateProcess(fields.processId);
+ process.has_ended = true;
+ return true;
+ },
+
+ decodeDefunct(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ // TODO(etienneb): Update the Model with |fields|.
+ return true;
+ }
+
+ };
+
+ Parser.register(ProcessParser);
+
+ return {
+ ProcessParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/process_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/process_parser_test.html
new file mode 100644
index 00000000000..aeeafc15dd2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/process_parser_test.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/etw/etw_importer.html">
+<link rel="import" href="/tracing/extras/importer/etw/process_parser.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ // Constants for Process events.
+ const guid = '3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C';
+ const kProcessStartOpcode = 1;
+ const kProcessDefunctOpcode = 39;
+
+ const kProcessStartPayload32bitV1 =
+ 'AAAAAPAGAADcAwAAAQAAAAMBAAAAAAAAAAAAAAEFAAAAAAAFFQAAAJYs7Cxo/TEG8dyk0' +
+ '+gDAABub3RlcGFkLmV4ZQA=';
+
+ const kProcessStartPayload32bitV2 =
+ 'AAAAAPAGAADcAwAAAQAAAAMBAAAAAAAAAAAAAAEFAAAAAAAFFQAAAJYs7Cxo/TEG8dyk0' +
+ '+gDAABub3RlcGFkLmV4ZQAiAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABzAHkAcwB0AGUAbQ' +
+ 'AzADIAXABuAG8AdABlAHAAYQBkAC4AZQB4AGUAIgAgAAAA';
+
+ const kProcessStartPayload32bitV3 =
+ 'AAAAAPAGAADcAwAAAQAAAAMBAAAAAAAAAAAAAAAAAAABBQAAAAAABRUAAACWLOwsaP0xB' +
+ 'vHcpNPoAwAAbm90ZXBhZC5leGUAIgBDADoAXABXAGkAbgBkAG8AdwBzAFwAcwB5AHMAdA' +
+ 'BlAG0AMwAyAFwAbgBvAHQAZQBwAGEAZAAuAGUAeABlACIAIAAAAA==';
+
+ const kProcessStartPayload64bitV3 =
+ 'YIBiD4D6//8AGgAAoBwAAAEAAAADAQAAAPBDHQEAAAAwVlMVoPj//wAAAACg+P//AQUAA' +
+ 'AAAAAUVAAAAAgMBAgMEBQYHCAkKCwwAAHhwZXJmLmV4ZQB4AHAAZQByAGYAIAAgAC0AZA' +
+ 'AgAG8AdQB0AC4AZQB0AGwAAAA=';
+
+ const kProcessStartPayload64bitV4 =
+ 'gED8GgDg//+MCgAACBcAAAUAAAADAQAAALCiowAAAAAAAAAAkPBXBADA//8AAAAAAAAAA' +
+ 'AEFAAAAAAAFFQAAAAECAwQFBgcICQoLBukDAAB4cGVyZi5leGUAeABwAGUAcgBmACAAIA' +
+ 'AtAHMAdABvAHAAAAAAAAAA';
+
+ const kProcessDefunctPayload64bitV5 =
+ 'wMXyBgDg//9IGQAAEAgAAAEAAAAAAAAAAGDLTwAAAAAAAAAA8OU7AwDA//8AAAAAAAAMA' +
+ 'AEFAAAAAAAFFQAAAMDBwsPExcbH0NHS09QDAABjaHJvbWUuZXhlAAAAAAAAAI1Jovns+s' +
+ '4B';
+
+ test('DecodeFields', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+ const parser = new tr.e.importer.etw.ProcessParser(importer);
+ let header;
+ let fields;
+
+ // Validate a version 1 32-bit payload.
+ header = { guid, opcode: kProcessStartOpcode, version: 1, is64: 0 };
+ decoder.reset(kProcessStartPayload32bitV1);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.pageDirectoryBase, 0);
+ assert.strictEqual(fields.processId, 1776);
+ assert.strictEqual(fields.parentId, 988);
+ assert.strictEqual(fields.sessionId, 1);
+ assert.strictEqual(fields.exitStatus, 259);
+ assert.strictEqual(fields.imageFileName, 'notepad.exe');
+
+ // Validate a version 2 32-bit payload.
+ header = { guid, opcode: kProcessStartOpcode, version: 2, is64: 0 };
+ decoder.reset(kProcessStartPayload32bitV2);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.uniqueProcessKey, 0);
+ assert.strictEqual(fields.processId, 1776);
+ assert.strictEqual(fields.parentId, 988);
+ assert.strictEqual(fields.sessionId, 1);
+ assert.strictEqual(fields.exitStatus, 259);
+ assert.strictEqual(fields.imageFileName, 'notepad.exe');
+ assert.strictEqual(fields.commandLine,
+ '\"C:\\Windows\\system32\\notepad.exe\" ');
+
+ // Validate a version 3 32-bit payload.
+ header = { guid, opcode: kProcessStartOpcode, version: 3, is64: 0 };
+ decoder.reset(kProcessStartPayload32bitV3);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.uniqueProcessKey, 0);
+ assert.strictEqual(fields.processId, 1776);
+ assert.strictEqual(fields.parentId, 988);
+ assert.strictEqual(fields.sessionId, 1);
+ assert.strictEqual(fields.exitStatus, 259);
+ assert.strictEqual(fields.directoryTableBase, 0);
+ assert.strictEqual(fields.imageFileName, 'notepad.exe');
+ assert.strictEqual(fields.commandLine,
+ '\"C:\\Windows\\system32\\notepad.exe\" ');
+
+ // Validate a version 3 64-bit payload.
+ header = { guid, opcode: kProcessStartOpcode, version: 3, is64: 1 };
+ decoder.reset(kProcessStartPayload64bitV3);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.uniqueProcessKey, 'fffffa800f628060');
+ assert.strictEqual(fields.processId, 6656);
+ assert.strictEqual(fields.parentId, 7328);
+ assert.strictEqual(fields.sessionId, 1);
+ assert.strictEqual(fields.exitStatus, 259);
+ assert.strictEqual(fields.directoryTableBase, '000000011d43f000');
+ assert.strictEqual(fields.imageFileName, 'xperf.exe');
+ assert.strictEqual(fields.commandLine, 'xperf -d out.etl');
+
+ // Validate a version 4 64-bit payload.
+ header = { guid, opcode: kProcessStartOpcode, version: 4, is64: 1 };
+ decoder.reset(kProcessStartPayload64bitV4);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.uniqueProcessKey, 'ffffe0001afc4080');
+ assert.strictEqual(fields.processId, 2700);
+ assert.strictEqual(fields.parentId, 5896);
+ assert.strictEqual(fields.sessionId, 5);
+ assert.strictEqual(fields.exitStatus, 259);
+ assert.strictEqual(fields.directoryTableBase, '00000000a3a2b000');
+ assert.strictEqual(fields.flags, 0);
+ assert.strictEqual(fields.imageFileName, 'xperf.exe');
+ assert.strictEqual(fields.commandLine, 'xperf -stop');
+ assert.strictEqual(fields.packageFullName, '');
+ assert.strictEqual(fields.applicationId, '');
+
+ // Validate a version 5 64-bit payload.
+ header = { guid, opcode: kProcessDefunctOpcode, version: 5, is64: 1 };
+ decoder.reset(kProcessDefunctPayload64bitV5);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.uniqueProcessKey, 'ffffe00006f2c5c0');
+ assert.strictEqual(fields.processId, 6472);
+ assert.strictEqual(fields.parentId, 2064);
+ assert.strictEqual(fields.sessionId, 1);
+ assert.strictEqual(fields.exitStatus, 0);
+ assert.strictEqual(fields.directoryTableBase, '000000004fcb6000');
+ assert.strictEqual(fields.flags, 0);
+ assert.strictEqual(fields.imageFileName, 'chrome.exe');
+ assert.strictEqual(fields.commandLine, '');
+ assert.strictEqual(fields.packageFullName, '');
+ assert.strictEqual(fields.applicationId, '');
+ assert.strictEqual(fields.exitTime, '01cefaecf9a2498d');
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/thread_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/thread_parser.html
new file mode 100644
index 00000000000..5a28e9f8165
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/thread_parser.html
@@ -0,0 +1,256 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/etw/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses threads events in the Windows event trace format.
+ *
+ * The Windows thread events are:
+ *
+ * - DCStart: Describes a thread that was already running when the trace
+ * started. ETW automatically generates these events for all running
+ * threads at the beginning of the trace.
+ * - Start: Describes a thread that started during the tracing session.
+ * - End: Describes a thread that ended during the tracing session.
+ * - DCEnd: Describes a thread that was still alive when the trace ended.
+ *
+ * See http://msdn.microsoft.com/library/windows/desktop/aa364132.aspx
+ */
+tr.exportTo('tr.e.importer.etw', function() {
+ const Parser = tr.e.importer.etw.Parser;
+
+ // Constants for Thread events.
+ const guid = '3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';
+ const kThreadStartOpcode = 1;
+ const kThreadEndOpcode = 2;
+ const kThreadDCStartOpcode = 3;
+ const kThreadDCEndOpcode = 4;
+ const kThreadCSwitchOpcode = 36;
+
+ /**
+ * Parses Windows threads trace events.
+ * @constructor
+ */
+ function ThreadParser(importer) {
+ Parser.call(this, importer);
+
+ // Register handlers.
+ importer.registerEventHandler(guid, kThreadStartOpcode,
+ ThreadParser.prototype.decodeStart.bind(this));
+ importer.registerEventHandler(guid, kThreadEndOpcode,
+ ThreadParser.prototype.decodeEnd.bind(this));
+ importer.registerEventHandler(guid, kThreadDCStartOpcode,
+ ThreadParser.prototype.decodeDCStart.bind(this));
+ importer.registerEventHandler(guid, kThreadDCEndOpcode,
+ ThreadParser.prototype.decodeDCEnd.bind(this));
+ importer.registerEventHandler(guid, kThreadCSwitchOpcode,
+ ThreadParser.prototype.decodeCSwitch.bind(this));
+ }
+
+ ThreadParser.prototype = {
+ __proto__: Parser.prototype,
+
+ decodeFields(header, decoder) {
+ if (header.version > 3) {
+ throw new Error('Incompatible Thread event version ' +
+ header.version + '.');
+ }
+
+ // Common fields to all Thread events.
+ const processId = decoder.decodeUInt32();
+ const threadId = decoder.decodeUInt32();
+
+ // Extended fields.
+ let stackBase;
+ let stackLimit;
+ let userStackBase;
+ let userStackLimit;
+ let affinity;
+ let startAddr;
+ let win32StartAddr;
+ let tebBase;
+ let subProcessTag;
+ let basePriority;
+ let pagePriority;
+ let ioPriority;
+ let threadFlags;
+ let waitMode;
+
+ if (header.version === 1) {
+ // On version 1, only start events have extended information.
+ if (header.opcode === kThreadStartOpcode ||
+ header.opcode === kThreadDCStartOpcode) {
+ stackBase = decoder.decodeUInteger(header.is64);
+ stackLimit = decoder.decodeUInteger(header.is64);
+ userStackBase = decoder.decodeUInteger(header.is64);
+ userStackLimit = decoder.decodeUInteger(header.is64);
+ startAddr = decoder.decodeUInteger(header.is64);
+ win32StartAddr = decoder.decodeUInteger(header.is64);
+ waitMode = decoder.decodeInt8();
+ decoder.skip(3);
+ }
+ } else {
+ stackBase = decoder.decodeUInteger(header.is64);
+ stackLimit = decoder.decodeUInteger(header.is64);
+ userStackBase = decoder.decodeUInteger(header.is64);
+ userStackLimit = decoder.decodeUInteger(header.is64);
+
+ // Version 2 produces a field named 'startAddr'.
+ if (header.version === 2) {
+ startAddr = decoder.decodeUInteger(header.is64);
+ } else {
+ affinity = decoder.decodeUInteger(header.is64);
+ }
+
+ win32StartAddr = decoder.decodeUInteger(header.is64);
+ tebBase = decoder.decodeUInteger(header.is64);
+ subProcessTag = decoder.decodeUInt32();
+
+ if (header.version === 3) {
+ basePriority = decoder.decodeUInt8();
+ pagePriority = decoder.decodeUInt8();
+ ioPriority = decoder.decodeUInt8();
+ threadFlags = decoder.decodeUInt8();
+ }
+ }
+
+ return {
+ processId,
+ threadId,
+ stackBase,
+ stackLimit,
+ userStackBase,
+ userStackLimit,
+ affinity,
+ startAddr,
+ win32StartAddr,
+ tebBase,
+ subProcessTag,
+ waitMode,
+ basePriority,
+ pagePriority,
+ ioPriority,
+ threadFlags
+ };
+ },
+
+ decodeCSwitchFields(header, decoder) {
+ // The only difference in version 3 is that oldThreadWaitMode is renamed
+ // to ThreadFlags. There is no difference between version 3 and version 4.
+ // Therefore we can safely handle all of these versions with the same code
+ // since we don't interpret oldThreadWaitMode at all.
+ // To see the layout of the CSwitch_V4 class you can run wbemtest
+ // elevated, "Connect...", change root\cimv2 to root\WMI, "Connect",
+ // "Open Class...", "CSwitch_V4", "Show MOF".
+ if (header.version < 2 || header.version > 4) {
+ throw new Error('Incompatible cswitch event version ' +
+ header.version + '.');
+ }
+
+ // Decode CSwitch payload.
+ const newThreadId = decoder.decodeUInt32();
+ const oldThreadId = decoder.decodeUInt32();
+ const newThreadPriority = decoder.decodeInt8();
+ const oldThreadPriority = decoder.decodeInt8();
+ const previousCState = decoder.decodeUInt8();
+ const spareByte = decoder.decodeInt8();
+ const oldThreadWaitReason = decoder.decodeInt8();
+ // oldThreadWaitMode is called ThreadFlags in V3 and V4.
+ const oldThreadWaitMode = decoder.decodeInt8();
+ const oldThreadState = decoder.decodeInt8();
+ const oldThreadWaitIdealProcessor = decoder.decodeInt8();
+ const newThreadWaitTime = decoder.decodeUInt32();
+ const reserved = decoder.decodeUInt32();
+
+ return {
+ newThreadId,
+ oldThreadId,
+ newThreadPriority,
+ oldThreadPriority,
+ previousCState,
+ spareByte,
+ oldThreadWaitReason,
+ oldThreadWaitMode,
+ oldThreadState,
+ oldThreadWaitIdealProcessor,
+ newThreadWaitTime,
+ reserved
+ };
+ },
+
+ decodeStart(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ this.importer.createThreadIfNeeded(fields.processId, fields.threadId);
+ return true;
+ },
+
+ decodeEnd(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ this.importer.removeThreadIfPresent(fields.threadId);
+ return true;
+ },
+
+ decodeDCStart(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ this.importer.createThreadIfNeeded(fields.processId, fields.threadId);
+ return true;
+ },
+
+ decodeDCEnd(header, decoder) {
+ const fields = this.decodeFields(header, decoder);
+ this.importer.removeThreadIfPresent(fields.threadId);
+ return true;
+ },
+
+ decodeCSwitch(header, decoder) {
+ const fields = this.decodeCSwitchFields(header, decoder);
+ const cpu = this.importer.getOrCreateCpu(header.cpu);
+ const newThread =
+ this.importer.getThreadFromWindowsTid(fields.newThreadId);
+
+ // Generate the new thread name. If some events were lost, it's possible
+ // that information about the new thread or process is not available.
+ let newThreadName;
+ if (newThread && newThread.userFriendlyName) {
+ newThreadName = newThread.userFriendlyName;
+ } else {
+ const newProcessId = this.importer.getPidFromWindowsTid(
+ fields.newThreadId);
+ const newProcess = this.model.getProcess(newProcessId);
+ let newProcessName;
+ if (newProcess) {
+ newProcessName = newProcess.name;
+ } else {
+ newProcessName = 'Unknown process';
+ }
+
+ newThreadName =
+ newProcessName + ' (tid ' + fields.newThreadId + ')';
+ }
+
+ cpu.switchActiveThread(
+ header.timestamp,
+ {},
+ fields.newThreadId,
+ newThreadName,
+ fields);
+ return true;
+ }
+
+ };
+
+ Parser.register(ThreadParser);
+
+ return {
+ ThreadParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/thread_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/thread_parser_test.html
new file mode 100644
index 00000000000..a15e3235a25
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/etw/thread_parser_test.html
@@ -0,0 +1,176 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/etw/etw_importer.html">
+<link rel="import" href="/tracing/extras/importer/etw/thread_parser.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ // Constants for Thread events.
+ const guid = '3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';
+ const kThreadStartOpcode = 1;
+ const kThreadEndOpcode = 2;
+ const kThreadDCStartOpcode = 3;
+ const kThreadCSwitchOpcode = 36;
+
+ const kThreadStartPayload32bitV1 =
+ 'BAAAAEwHAAAAYLfzADC38wAAAAAAAAAAhdse9wAAAAD/AAAA';
+
+ const kThreadEndPayload32bitV1 = 'BAAAALQAAAA=';
+
+
+ const kThreadDCStartPayload64bitV2 =
+ 'AAAAAAAAAAAAYPUCAPj//wAA9QIA+P//AAAAAAAAAAAAAAAAAAAAAIAlxwEA+P//gCXHA' +
+ 'QD4//8AAAAAAAAAAAAAAAA=';
+
+ const kThreadStartPayload32bitV3 =
+ 'LAIAACwTAAAAUJixACCYsQAA1QAAwNQAAwAAAOkDq3cA4P1/AAAAAAkFAgA=';
+
+ const kThreadStartPayload64bitV3 =
+ 'eCEAAJQUAAAAMA4nAND//wDQDScA0P//MP0LBgAAAAAAgAsGAAAAAP8AAAAAAAAALP1YX' +
+ 'AAAAAAAwBL/AAAAAAAAAAAIBQIA';
+
+ const kThreadCSwitchPayload32bitV2 = 'AAAAACwRAAAACQAAFwABABIAAAAmSAAA';
+ const kThreadCSwitchPayload64bitV2 = 'zAgAAAAAAAAIAAEAAAACBAEAAACHbYg0';
+
+ test('DecodeFields', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+ const parser = new tr.e.importer.etw.ThreadParser(importer);
+ let header;
+ let fields;
+
+ // Validate a version 1 32-bit payload.
+ header = { guid, opcode: kThreadStartOpcode, version: 1, is64: 0 };
+ decoder.reset(kThreadStartPayload32bitV1);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.processId, 4);
+ assert.strictEqual(fields.threadId, 1868);
+ assert.strictEqual(fields.stackBase, 4088881152);
+ assert.strictEqual(fields.stackLimit, 4088868864);
+ assert.strictEqual(fields.userStackBase, 0);
+ assert.strictEqual(fields.userStackLimit, 0);
+ assert.strictEqual(fields.startAddr, 4145994629);
+ assert.strictEqual(fields.win32StartAddr, 0);
+ assert.strictEqual(fields.waitMode, -1);
+
+ // Validate an End version 1 32-bit payload.
+ header = { guid, opcode: kThreadEndOpcode, version: 1, is64: 0 };
+ decoder.reset(kThreadStartPayload32bitV1);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.processId, 4);
+ assert.strictEqual(fields.threadId, 1868);
+
+ // Validate a version 2 64-bit payload.
+ header = { guid, opcode: kThreadDCStartOpcode, version: 2, is64: 1 };
+ decoder.reset(kThreadDCStartPayload64bitV2);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.processId, 0);
+ assert.strictEqual(fields.threadId, 0);
+ assert.strictEqual(fields.stackBase, 'fffff80002f56000');
+ assert.strictEqual(fields.stackLimit, 'fffff80002f50000');
+ assert.strictEqual(fields.userStackBase, '0000000000000000');
+ assert.strictEqual(fields.userStackLimit, '0000000000000000');
+ assert.strictEqual(fields.startAddr, 'fffff80001c72580');
+ assert.strictEqual(fields.win32StartAddr, 'fffff80001c72580');
+ assert.strictEqual(fields.tebBase, '0000000000000000');
+ assert.strictEqual(fields.subProcessTag, 0);
+
+ // Validate a version 3 32-bit payload.
+ header = { guid, opcode: kThreadStartOpcode, version: 3, is64: 0 };
+ decoder.reset(kThreadStartPayload32bitV3);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.processId, 556);
+ assert.strictEqual(fields.threadId, 4908);
+ assert.strictEqual(fields.stackBase, 2979549184);
+ assert.strictEqual(fields.stackLimit, 2979536896);
+ assert.strictEqual(fields.userStackBase, 13959168);
+ assert.strictEqual(fields.userStackLimit, 13942784);
+ assert.strictEqual(fields.affinity, 3);
+ assert.strictEqual(fields.win32StartAddr, 2007696361);
+ assert.strictEqual(fields.tebBase, 2147344384);
+ assert.strictEqual(fields.subProcessTag, 0);
+ assert.strictEqual(fields.basePriority, 9);
+ assert.strictEqual(fields.pagePriority, 5);
+ assert.strictEqual(fields.ioPriority, 2);
+ assert.strictEqual(fields.threadFlags, 0);
+
+ // Validate a version 3 64-bit payload.
+ header = { guid, opcode: kThreadStartOpcode, version: 3, is64: 1 };
+ decoder.reset(kThreadStartPayload64bitV3);
+ fields = parser.decodeFields(header, decoder);
+
+ assert.strictEqual(fields.processId, 8568);
+ assert.strictEqual(fields.threadId, 5268);
+ assert.strictEqual(fields.stackBase, 'ffffd000270e3000');
+ assert.strictEqual(fields.stackLimit, 'ffffd000270dd000');
+ assert.strictEqual(fields.userStackBase, '00000000060bfd30');
+ assert.strictEqual(fields.userStackLimit, '00000000060b8000');
+ assert.strictEqual(fields.affinity, '00000000000000ff');
+ assert.strictEqual(fields.win32StartAddr, '000000005c58fd2c');
+ assert.strictEqual(fields.tebBase, '00000000ff12c000');
+ assert.strictEqual(fields.subProcessTag, 0);
+ assert.strictEqual(fields.basePriority, 8);
+ assert.strictEqual(fields.pagePriority, 5);
+ assert.strictEqual(fields.ioPriority, 2);
+ assert.strictEqual(fields.threadFlags, 0);
+ });
+
+ test('DecodeCSwitchFields', function() {
+ const importer = new tr.e.importer.etw.EtwImporter('dummy', []);
+ const decoder = importer.decoder_;
+ const parser = new tr.e.importer.etw.ThreadParser(importer);
+ let header;
+ let fields;
+
+
+ // Validate a version 2 CSwitch 32-bit payload.
+ header = { guid, opcode: kThreadCSwitchOpcode, version: 2, is64: 0 };
+ decoder.reset(kThreadCSwitchPayload32bitV2);
+ fields = parser.decodeCSwitchFields(header, decoder);
+
+ assert.strictEqual(fields.newThreadId, 0);
+ assert.strictEqual(fields.oldThreadId, 4396);
+ assert.strictEqual(fields.newThreadPriority, 0);
+ assert.strictEqual(fields.oldThreadPriority, 9);
+ assert.strictEqual(fields.previousCState, 0);
+ assert.strictEqual(fields.spareByte, 0);
+ assert.strictEqual(fields.oldThreadWaitReason, 23);
+ assert.strictEqual(fields.oldThreadWaitMode, 0);
+ assert.strictEqual(fields.oldThreadState, 1);
+ assert.strictEqual(fields.oldThreadWaitIdealProcessor, 0);
+ assert.strictEqual(fields.newThreadWaitTime, 18);
+ assert.strictEqual(fields.reserved, 18470);
+
+ // Validate a version 2 CSwitch 64-bit payload.
+ header = { guid, opcode: kThreadCSwitchOpcode, version: 2, is64: 1 };
+ decoder.reset(kThreadCSwitchPayload64bitV2);
+ fields = parser.decodeCSwitchFields(header, decoder);
+
+ assert.strictEqual(fields.newThreadId, 2252);
+ assert.strictEqual(fields.oldThreadId, 0);
+ assert.strictEqual(fields.newThreadPriority, 8);
+ assert.strictEqual(fields.oldThreadPriority, 0);
+ assert.strictEqual(fields.previousCState, 1);
+ assert.strictEqual(fields.spareByte, 0);
+ assert.strictEqual(fields.oldThreadWaitReason, 0);
+ assert.strictEqual(fields.oldThreadWaitMode, 0);
+ assert.strictEqual(fields.oldThreadState, 2);
+ assert.strictEqual(fields.oldThreadWaitIdealProcessor, 4);
+ assert.strictEqual(fields.newThreadWaitTime, 1);
+ assert.strictEqual(fields.reserved, 881356167);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html
new file mode 100644
index 00000000000..8fd2fcbf870
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/trace_stream.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.importer.fuchsia', function() {
+ const IMPORT_PRIORITY = 0;
+ const IDLE_THREAD_THRESHOLD = 6444000000;
+
+ // Zircon thread state constants from:
+ // https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_get_info.md
+ const ZX_THREAD_STATE_NEW = 0;
+ const ZX_THREAD_STATE_RUNNING = 1;
+ const ZX_THREAD_STATE_SUSPENDED = 2;
+ const ZX_THREAD_STATE_BLOCKED = 3;
+ const ZX_THREAD_STATE_DYING = 4;
+ const ZX_THREAD_STATE_DEAD = 5;
+
+ class FuchsiaImporter extends tr.importer.Importer {
+ constructor(model, eventData) {
+ super(model, eventData);
+ this.importPriority = IMPORT_PRIORITY;
+ this.model_ = model;
+ this.events_ = eventData.events;
+ this.parsers_ = [];
+ this.threadInfo_ = new Map();
+ this.processNames_ = new Map();
+ this.threadStates_ = new Map();
+ }
+
+ static canImport(eventData) {
+ if (eventData instanceof tr.b.TraceStream) {
+ if (eventData.isBinary) return false;
+ eventData = eventData.header;
+ }
+
+ if (eventData instanceof Object && eventData.type === 'fuchsia') {
+ return true;
+ }
+
+ return false;
+ }
+
+ get importerName() {
+ return 'FuchsiaImporter';
+ }
+
+ get model() {
+ return this.model_;
+ }
+
+ importClockSyncMarkers() {
+ }
+
+ finalizeImport() {
+ }
+
+ isIdleThread(prio, tid) {
+ if (prio === undefined) {
+ // If the "prio" field is not available (if we were, for example,
+ // using an old trace), then fall back to the legacy heuristic of
+ // assuming that large numbered threads are idle ones.
+ return tid > IDLE_THREAD_THRESHOLD;
+ }
+ // A thread is idle iff its priority is set to 0.
+ return prio === 0;
+ }
+
+ recordThreadState_(tid, timestamp, state, prio) {
+ if (this.isIdleThread(prio, tid)) {
+ return;
+ }
+ const states =
+ this.threadStates_.has(tid) ? this.threadStates_.get(tid) : [];
+ states.push({'ts': timestamp, state});
+ this.threadStates_.set(tid, states);
+ }
+
+ // Context switch events take the form:
+ // {
+ // "ph": "k",
+ // "ts": 151981130.88743783,
+ // "cpu": 1,
+ // "out": {
+ // "pid": 25977,
+ // "tid": 28909,
+ // "state": 3,
+ // "prio": 20
+ // },
+ // "in": {
+ // "pid": 0,
+ // "tid": 6444931392,
+ // "prio": 0
+ // }
+ // },
+ processContextSwitchEvent_(event) {
+ let tid = event.in.tid;
+ let threadName = tid.toString();
+ let procName = '';
+ const prio = event.in.prio;
+
+ if (this.threadInfo_.has(tid)) {
+ const threadInfo = this.threadInfo_.get(tid);
+ threadName = threadInfo.name;
+ const pid = threadInfo.pid;
+ if (this.processNames_.has(pid)) {
+ procName = this.processNames_.get(pid) + ':';
+ }
+ }
+
+ const name = procName + threadName;
+
+ if (this.isIdleThread(prio, tid)) {
+ tid = undefined; // Fake kernel idle task
+ }
+
+ const cpu = this.model_.kernel.getOrCreateCpu(event.cpu);
+ const timestamp = tr.b.Unit.timestampFromUs(event.ts);
+ cpu.switchActiveThread(timestamp, {}, tid, name, tid);
+
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ this.recordThreadState_(tid, timestamp, SCHEDULING_STATE.RUNNING, prio);
+
+ let outState = SCHEDULING_STATE.UNKNOWN;
+
+ switch (event.out.state) {
+ case ZX_THREAD_STATE_NEW:
+ outState = SCHEDULING_STATE.RUNNABLE;
+ break;
+
+ case ZX_THREAD_STATE_RUNNING:
+ outState = SCHEDULING_STATE.RUNNABLE;
+ break;
+
+ case ZX_THREAD_STATE_BLOCKED:
+ outState = SCHEDULING_STATE.SLEEPING;
+ break;
+
+ case ZX_THREAD_STATE_SUSPENDED:
+ outState = SCHEDULING_STATE.STOPPED;
+ break;
+
+ case ZX_THREAD_STATE_DEAD:
+ outState = SCHEDULING_STATE.TASK_DEAD;
+ break;
+ }
+ this.recordThreadState_(event.out.tid, timestamp, outState,
+ event.out.prio);
+ }
+
+ processProcessInfoEvent_(event) {
+ const process = this.model_.getOrCreateProcess(event.pid);
+ process.name = event.name;
+ this.processNames_.set(event.pid, event.name);
+
+ if ('sort_index' in event) {
+ process.sortIndex = event.sort_index;
+ }
+ }
+
+ processThreadInfoEvent_(event) {
+ const thread = this.model_.getOrCreateProcess(event.pid).
+ getOrCreateThread(event.tid);
+ thread.name = event.name;
+ this.threadInfo_.set(event.tid, {'name': event.name, 'pid': event.pid});
+
+ if ('sort_index' in event) {
+ const thread = this.model_.getOrCreateProcess(event.pid).
+ getOrCreateThread(event.tid);
+ thread.sortIndex = event.sort_index;
+ }
+ }
+
+ processEvent_(event) {
+ switch (event.ph) {
+ case 'k':
+ this.processContextSwitchEvent_(event);
+ break;
+ case 'p':
+ this.processProcessInfoEvent_(event);
+ break;
+ case 't':
+ this.processThreadInfoEvent_(event);
+ break;
+ }
+ }
+
+ postProcessStates_() {
+ for (const [tid, states] of this.threadStates_) {
+ if (!this.threadInfo_.has(tid)) {
+ continue;
+ }
+ const pid = this.threadInfo_.get(tid).pid;
+ const thread = this.model_.getOrCreateProcess(
+ pid).getOrCreateThread(tid);
+ const slices = [];
+ for (let i = 0; i < states.length - 1; i++) {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, states[i].state, '',
+ states[i].ts, {}, states[i + 1].ts - states[i].ts));
+ }
+
+ thread.timeSlices = slices;
+ }
+ }
+
+ /**
+ * Imports the data in this.events_ into model_.
+ */
+ importEvents() {
+ for (const event of this.events_) {
+ this.processEvent_(event);
+ }
+ this.postProcessStates_();
+ }
+ }
+
+ tr.importer.Importer.register(FuchsiaImporter);
+
+ return {
+ FuchsiaImporter,
+ IMPORT_PRIORITY,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer_test.html
new file mode 100644
index 00000000000..e7494f0da82
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/fuchsia_importer_test.html
@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/fuchsia_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ // Test that fuchsia process and thread info events properly annotate
+ // thread and process names.
+ test('processAndThreadInfo', function() {
+ const events = `{
+ "displayTimeUnit": "ns",
+ "traceEvents": [
+ {
+ "cat": "cat0",
+ "name": "name0",
+ "ts": 1.0,
+ "pid": 1,
+ "tid": 2,
+ "ph": "B"
+ },
+ {
+ "cat": "cat0",
+ "name": "name0",
+ "ts": 2.0,
+ "pid": 1,
+ "tid": 2,
+ "ph": "E"
+ }
+ ],
+ "systemTraceEvents": {
+ "type": "fuchsia",
+ "events": [
+ {
+ "ph": "p",
+ "pid": 1,
+ "name": "proc1"
+ },
+ {
+ "ph": "t",
+ "pid": 1,
+ "tid": 2,
+ "name": "thread2"
+ }
+ ]
+ }
+ }`;
+ const m = tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ const process = m.getProcess(1);
+ assert.isDefined(process);
+ assert.strictEqual(process.name, 'proc1');
+
+ const thread = process.getThread(2);
+ assert.isDefined(thread);
+ assert.strictEqual(thread.name, 'thread2');
+ });
+
+ // Test that context switch events create CPU slices.
+ test('cpuSlices', function() {
+ const events = `{
+ "displayTimeUnit": "ns",
+ "traceEvents": [
+ ],
+ "systemTraceEvents": {
+ "type": "fuchsia",
+ "events": [
+ {
+ "ph": "p",
+ "pid": 1,
+ "name": "proc1"
+ },
+ {
+ "ph": "t",
+ "pid": 1,
+ "tid": 2,
+ "name": "thread2"
+ },
+ {
+ "ph": "t",
+ "pid": 1,
+ "tid": 3,
+ "name": "thread3"
+ },
+ {
+ "ph": "k",
+ "ts": 1.0,
+ "cpu": 1,
+ "out": {
+ "pid": 1,
+ "tid": 2,
+ "state": 1
+ },
+ "in": {
+ "pid": 1,
+ "tid": 3
+ }
+ },
+ {
+ "ph": "k",
+ "ts": 2.0,
+ "cpu": 1,
+ "out": {
+ "pid": 1,
+ "tid": 3,
+ "state": 3
+ },
+ "in": {
+ "pid": 1,
+ "tid": 2
+ }
+ },
+ {
+ "ph": "k",
+ "ts": 3.0,
+ "cpu": 1,
+ "out": {
+ "pid": 1,
+ "tid": 2,
+ "state": 1
+ },
+ "in": {
+ "pid": 1,
+ "tid": 3
+ }
+ }
+ ]
+ }
+ }`;
+ const m = tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ const cpu = m.kernel.cpus[1];
+ assert.isDefined(cpu);
+ assert.strictEqual(cpu.slices.length, 2);
+
+ assert.strictEqual(cpu.slices[0].title, 'proc1:thread3');
+ assert.closeTo(cpu.slices[0].duration, 0.001, 1e-5);
+
+ assert.strictEqual(cpu.slices[1].title, 'proc1:thread2');
+ assert.closeTo(cpu.slices[1].duration, 0.001, 1e-5);
+
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+
+ const thread2Slices =
+ m.getOrCreateProcess(1).getOrCreateThread(2).timeSlices;
+ assert.strictEqual(thread2Slices[0].schedulingState,
+ SCHEDULING_STATE.RUNNABLE);
+ assert.closeTo(thread2Slices[0].start, 0.001, 1e-5);
+ assert.closeTo(thread2Slices[0].duration, 0.001, 1e-5);
+ assert.strictEqual(thread2Slices[1].schedulingState,
+ SCHEDULING_STATE.RUNNING);
+ assert.closeTo(thread2Slices[1].start, 0.002, 1e-5);
+ assert.closeTo(thread2Slices[1].duration, 0.001, 1e-5);
+
+ const thread3Slices =
+ m.getOrCreateProcess(1).getOrCreateThread(3).timeSlices;
+ assert.strictEqual(thread3Slices[0].schedulingState,
+ SCHEDULING_STATE.RUNNING);
+ assert.closeTo(thread3Slices[0].start, 0.001, 1e-5);
+ assert.closeTo(thread3Slices[0].duration, 0.001, 1e-5);
+ assert.strictEqual(thread3Slices[1].schedulingState,
+ SCHEDULING_STATE.SLEEPING);
+ assert.closeTo(thread3Slices[1].start, 0.002, 1e-5);
+ assert.closeTo(thread3Slices[1].duration, 0.001, 1e-5);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/gcloud_trace/gcloud_trace_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/gcloud_trace/gcloud_trace_importer.html
new file mode 100644
index 00000000000..bd3ce854503
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/gcloud_trace/gcloud_trace_importer.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/importer/importer.html">
+
+<script>
+
+'use strict';
+
+/**
+ * @fileoverview GcloudTraceImporter imports JSON data from Google Cloud Trace.
+ */
+tr.exportTo('tr.e.importer.gcloud_trace', function() {
+ function GcloudTraceImporter(model, eventData) {
+ this.importPriority = 2;
+ this.eventData_ = eventData;
+ }
+
+ /**
+ * @return {boolean} Whether obj looks like the JSON output from Cloud Trace.
+ */
+ GcloudTraceImporter.canImport = function(eventData) {
+ if (typeof(eventData) !== 'string' && !(eventData instanceof String)) {
+ return false;
+ }
+
+ // Slice the data so we don't potentially do a replace on a gigantic string.
+ const normalizedEventData = eventData.slice(0, 20).replace(/\s/g, '');
+ if (normalizedEventData.length < 14) return false;
+
+ return normalizedEventData.slice(0, 14) === '{"projectId":"';
+ };
+
+ GcloudTraceImporter.prototype = {
+
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'GcloudTraceImporter';
+ },
+
+ /**
+ * Called by the Model to extract subtraces from the event data. The
+ * subtraces are passed on to other importers that can recognize them.
+ */
+ extractSubtraces() {
+ const traceEvents = this.createEventsForTrace();
+ return traceEvents ? [traceEvents] : [];
+ },
+
+ createEventsForTrace() {
+ const events = [];
+ const trace = JSON.parse(this.eventData_);
+ const spanLength = trace.spans.length;
+ for (let i = 0; i < spanLength; i++) {
+ events.push(this.createEventForSpan(trace.traceId, trace.spans[i]));
+ }
+ return {
+ 'traceEvents': events
+ };
+ },
+
+ createEventForSpan(traceId, span) {
+ let newArgs = {};
+ if (span.labels) {
+ newArgs = JSON.parse(JSON.stringify(span.labels));
+ }
+ newArgs['Span ID'] = span.spanId;
+ newArgs['Start Time'] = span.startTime;
+ newArgs['End Time'] = span.endTime;
+ if (span.parentSpanId) {
+ newArgs['Parent Span ID'] = span.parentSpanId;
+ }
+ // The timestamps are ISO-standard strings, which are parsed to millis,
+ // then converted to the micros that the trace viewer expects.
+ return {
+ name: span.name,
+ args: newArgs,
+ pid: traceId,
+ ts: Date.parse(span.startTime) * 1000,
+ dur: (Date.parse(span.endTime) - Date.parse(span.startTime)) * 1000,
+ cat: 'tracespan',
+ tid: traceId,
+ ph: 'X'
+ };
+ }
+ };
+
+ tr.importer.Importer.register(GcloudTraceImporter);
+
+ return {
+ GcloudTraceImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/gcloud_trace/gcloud_trace_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/gcloud_trace/gcloud_trace_importer_test.html
new file mode 100644
index 00000000000..b902ff5fce9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/gcloud_trace/gcloud_trace_importer_test.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/gcloud_trace/gcloud_trace_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const GcloudTraceImporter = tr.e.importer.gcloud_trace.GcloudTraceImporter;
+
+ test('noSpans', function() {
+ const trace = {projectId: 'My Project', traceId: '123', spans: []};
+
+ const model = new tr.Model();
+ const importer = new tr.e.importer.gcloud_trace.GcloudTraceImporter(model,
+ JSON.stringify(trace));
+ const subtraces = importer.extractSubtraces();
+ assert.strictEqual(1, subtraces.length);
+ // Note there are, in fact, use cases for traces with no events (spans).
+ assert.deepEqual([], subtraces[0].traceEvents);
+ });
+
+ test('typicalTrace', function() {
+ const span1 = {
+ 'spanId': '1',
+ 'kind': 'RPC_CLIENT',
+ 'name': '/first',
+ 'startTime': '2015-09-03T16:40:00.841654024Z',
+ 'endTime': '2015-09-03T16:40:00.856599389Z',
+ 'labels': {
+ 'key1': 'value1',
+ 'key2': 'value2'
+ }
+ };
+ const span2 = {
+ 'spanId': '2',
+ 'kind': 'RPC_SERVER',
+ 'name': '/second',
+ 'startTime': '2015-09-03T16:40:00.842880028Z',
+ 'endTime': '2015-09-03T16:40:00.851729538Z',
+ 'parentSpanId': '1',
+ 'labels': {
+ 'key1': 'value3',
+ 'key2': 'value4'
+ }
+ };
+ const trace = {projectId: 'My Project', traceId: '123',
+ spans: [span1, span2]};
+
+ const model = new tr.Model();
+ const importer = new tr.e.importer.gcloud_trace.GcloudTraceImporter(model,
+ JSON.stringify(trace));
+ const subtraces = importer.extractSubtraces();
+ assert.strictEqual(1, subtraces.length);
+ assert.strictEqual(2, subtraces[0].traceEvents.length);
+
+ const span1Event = subtraces[0].traceEvents[0];
+ assert.strictEqual('tracespan', span1Event.cat);
+ assert.strictEqual('/first', span1Event.name);
+ assert.strictEqual(1441298400841000, span1Event.ts);
+ assert.strictEqual(15000, span1Event.dur);
+ assert.strictEqual('123', span1Event.pid);
+ assert.strictEqual('123', span1Event.tid);
+ assert.strictEqual(
+ '2015-09-03T16:40:00.856599389Z', span1Event.args['End Time']);
+ assert.strictEqual('1', span1Event.args['Span ID']);
+ assert.strictEqual('value1', span1Event.args.key1);
+ assert.strictEqual('value2', span1Event.args.key2);
+ assert.strictEqual(
+ '2015-09-03T16:40:00.856599389Z', span1Event.args['End Time']);
+
+ const span2Event = subtraces[0].traceEvents[1];
+ assert.strictEqual('tracespan', span2Event.cat);
+ assert.strictEqual('/second', span2Event.name);
+ assert.strictEqual(1441298400842000, span2Event.ts);
+ assert.strictEqual(9000, span2Event.dur);
+ assert.strictEqual('123', span2Event.pid);
+ assert.strictEqual('123', span2Event.tid);
+ });
+
+ test('canImport', function() {
+ assert.isTrue(GcloudTraceImporter.canImport(
+ JSON.stringify({projectId: 'My Project'})));
+ assert.isTrue(GcloudTraceImporter.canImport(
+ JSON.stringify({projectId: '56', traceId: '34'})));
+ assert.isFalse(GcloudTraceImporter.canImport(
+ JSON.stringify({wrongjson: '33'})));
+ assert.isFalse(GcloudTraceImporter.canImport(''));
+ assert.isFalse(GcloudTraceImporter.canImport([]));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/gzip_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/gzip_importer.html
new file mode 100644
index 00000000000..88b6edba0d6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/gzip_importer.html
@@ -0,0 +1,252 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/in_memory_trace_stream.html">
+<link rel="import" href="/tracing/extras/importer/pako.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview GzipImporter inflates gzip compressed data and passes it along
+ * to an actual importer.
+ */
+tr.exportTo('tr.e.importer', function() {
+ const GZIP_MEMBER_HEADER_ID_SIZE = 3;
+
+ const GZIP_HEADER_ID1 = 0x1f;
+ const GZIP_HEADER_ID2 = 0x8b;
+ const GZIP_DEFLATE_COMPRESSION = 8;
+
+ function _stringToUInt8Array(str) {
+ const array = new Uint8Array(str.length);
+ for (let i = 0; i < str.length; ++i) {
+ array[i] = str.charCodeAt(i);
+ }
+ return array;
+ }
+
+ function GzipImporter(model, eventData) {
+ // Normalize the data into an Uint8Array.
+ this.inflateAsTraceStream = false;
+ if (typeof(eventData) === 'string' || eventData instanceof String) {
+ eventData = _stringToUInt8Array(eventData);
+ } else if (eventData instanceof ArrayBuffer) {
+ eventData = new Uint8Array(eventData);
+ } else if (eventData instanceof tr.b.InMemoryTraceStream) {
+ // This importer does not support processing general TraceStreams, only
+ // InMemoryTraceStreams for now.
+ eventData = eventData.data;
+ this.inflateAsTraceStream_ = true;
+ } else {
+ throw new Error('Unknown gzip data format');
+ }
+ this.model_ = model;
+ this.gzipData_ = eventData;
+ }
+
+ /**
+ * @param {eventData} Possibly gzip compressed data as a string or an
+ * ArrayBuffer.
+ * @return {boolean} Whether obj looks like gzip compressed data.
+ */
+ GzipImporter.canImport = function(eventData) {
+ // This importer does not support processing general TraceStreams, only
+ // InMemoryTraceStreams for now.
+ if (eventData instanceof tr.b.InMemoryTraceStream) {
+ eventData = eventData.header;
+ }
+
+ let header;
+ if (eventData instanceof ArrayBuffer) {
+ header = new Uint8Array(eventData.slice(0, GZIP_MEMBER_HEADER_ID_SIZE));
+ } else if (typeof(eventData) === 'string' || eventData instanceof String) {
+ header = eventData.substring(0, GZIP_MEMBER_HEADER_ID_SIZE);
+ header = _stringToUInt8Array(header);
+ } else {
+ return false;
+ }
+ return header[0] === GZIP_HEADER_ID1 &&
+ header[1] === GZIP_HEADER_ID2 &&
+ header[2] === GZIP_DEFLATE_COMPRESSION;
+ };
+
+ /**
+ * Inflates (decompresses) the data stored in the given gzip bitstream.
+ * @return {string} Inflated data.
+ */
+ GzipImporter.inflateGzipData_ = function(data) {
+ let position = 0;
+
+ function getByte() {
+ if (position >= data.length) {
+ throw new Error('Unexpected end of gzip data');
+ }
+ return data[position++];
+ }
+
+ function getWord() {
+ const low = getByte();
+ const high = getByte();
+ return (high << 8) + low;
+ }
+
+ function skipBytes(amount) {
+ position += amount;
+ }
+
+ function skipZeroTerminatedString() {
+ while (getByte() !== 0) {}
+ }
+
+ const id1 = getByte();
+ const id2 = getByte();
+ if (id1 !== GZIP_HEADER_ID1 || id2 !== GZIP_HEADER_ID2) {
+ throw new Error('Not gzip data');
+ }
+ const compressionMethod = getByte();
+ if (compressionMethod !== GZIP_DEFLATE_COMPRESSION) {
+ throw new Error('Unsupported compression method: ' + compressionMethod);
+ }
+ const flags = getByte();
+ const haveHeaderCrc = flags & (1 << 1);
+ const haveExtraFields = flags & (1 << 2);
+ const haveFileName = flags & (1 << 3);
+ const haveComment = flags & (1 << 4);
+
+ // Skip modification time, extra flags and OS.
+ skipBytes(4 + 1 + 1);
+
+ // Skip remaining fields before compressed data.
+ if (haveExtraFields) {
+ const bytesToSkip = getWord();
+ skipBytes(bytesToSkip);
+ }
+ if (haveFileName) skipZeroTerminatedString();
+ if (haveComment) skipZeroTerminatedString();
+ if (haveHeaderCrc) getWord();
+
+ // Inflate the data using pako.
+ const inflatedData = pako.inflateRaw(data.subarray(position));
+
+ if (this.inflateAsTraceStream_) {
+ return GzipImporter.transformToStream(inflatedData);
+ }
+
+ let string;
+ try {
+ string = GzipImporter.transformToString(inflatedData);
+ } catch (err) {
+ // It may be the case that inflated data does not fit into a V8 string. In
+ // that case, try to transform to a trace stream.
+ return GzipImporter.transformToStream(inflatedData);
+ }
+
+ if (inflatedData.length > 0 && string.length === 0) {
+ // Try transforming to a trace stream.
+ return GzipImporter.transformToStream(inflatedData);
+ }
+
+ return string;
+ };
+
+ GzipImporter.transformToStream = function(data) {
+ if (data instanceof Uint8Array) {
+ return new tr.b.InMemoryTraceStream(data, false);
+ }
+
+ throw new Error(`Cannot transform ${type} to TraceStream.`);
+ };
+
+ /**
+ * Transforms an array-like object to a string.
+ *
+ * Note that the following two expressions yield identical results:
+ *
+ * GzipImporter.transformToString_(data)
+ * JSZip.utils.transformTo('string', data)
+ *
+ * We use a custom static method because it is faster and, more importantly,
+ * avoids OOMing on large traces. See
+ * https://github.com/catapult-project/catapult/issues/2051.
+ */
+ GzipImporter.transformToString = function(data) {
+ if (typeof(data) === 'string') return data; // We already have a string.
+
+ // Fall back to manual conversion if TextDecoder is not available.
+ if (typeof TextDecoder === 'undefined') {
+ if (data instanceof ArrayBuffer) {
+ data = new Uint8Array(data);
+ }
+
+ // Based on JSZip.Utils.stringToArrayLike
+ const result = [];
+ let chunk = 65536;
+ let k = 0;
+ const len = data.length;
+
+ while (k < len && chunk > 1) {
+ try {
+ const chunklen = Math.min(k + chunk, len);
+ let dataslice;
+ if (data instanceof Array) {
+ dataslice = data.slice(k, chunklen);
+ } else {
+ dataslice = data.subarray(k, chunklen);
+ }
+ result.push(String.fromCharCode.apply(null, dataslice));
+ k += chunk;
+ } catch (e) {
+ chunk = Math.floor(chunk / 2);
+ }
+ }
+
+ return result.join('');
+ }
+
+ if (data instanceof Array) {
+ // TextDecoder requires an ArrayBuffer or an ArrayBufferView.
+ data = new Uint8Array(data);
+ }
+
+ return new TextDecoder('utf-8').decode(data);
+ };
+
+ GzipImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'GzipImporter';
+ },
+
+ /**
+ * Called by the Model to check whether the importer just encapsulates
+ * the actual trace data which needs to be imported by another importer.
+ */
+ isTraceDataContainer() {
+ return true;
+ },
+
+ /**
+ * Called by the Model to extract subtraces from the event data. The
+ * subtraces are passed on to other importers that can recognize them.
+ */
+ extractSubtraces() {
+ const eventData = GzipImporter.inflateGzipData_(this.gzipData_);
+ return eventData ? [eventData] : [];
+ }
+ };
+
+ tr.importer.Importer.register(GzipImporter);
+
+ return {
+ GzipImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/gzip_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/gzip_importer_test.html
new file mode 100644
index 00000000000..32fd72be45a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/gzip_importer_test.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/base/trace_stream.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/gzip_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Base64 = tr.b.Base64;
+ const findSliceNamed = tr.c.TestUtils.findSliceNamed;
+ const ORIGINAL_DATA =
+ '[{"name":"a","args":{},"pid":52,"ts":520,"cat":"foo","tid":53,' +
+ '"ph":"B"},{"name":"a","args":{},"pid":52,"ts":520,"cat":"foo",' +
+ '"tid":53,"ph":"E"}]\n';
+ const GZIP_DATA_BASE_64 =
+ 'H4sICHr4HVIAA3RyYWNlAIuuVspLzE1VslJKVNJRSixKL1ayqq7VUSrITFGy' +
+ 'MjXSUSopBtEGOkrJiSVAVWn5+UB1JWBZY6CyDKCYk1KtDhWMcVWqjeUCALak' +
+ 'EH+QAAAA';
+
+ test('failImportEmpty', function() {
+ assert.isFalse(tr.e.importer.GzipImporter.canImport([]));
+ assert.isFalse(tr.e.importer.GzipImporter.canImport(''));
+ });
+
+ test('inflateString', function() {
+ // Test inflating the data from a string.
+ const gzipData = Base64.atob(GZIP_DATA_BASE_64);
+ const importer = new tr.e.importer.GzipImporter(null, gzipData);
+ assert.isTrue(tr.e.importer.GzipImporter.canImport(gzipData));
+ assert.strictEqual(
+ importer.extractSubtraces()[0].toString(), ORIGINAL_DATA);
+ });
+
+ test('inflateArrayBuffer', function() {
+ // Test inflating the data from an ArrayBuffer.
+ const gzipData = Base64.atob(GZIP_DATA_BASE_64);
+ const buffer = new ArrayBuffer(gzipData.length);
+ const view = new Uint8Array(buffer);
+ for (let i = 0; i < gzipData.length; i++) {
+ view[i] = gzipData.charCodeAt(i);
+ }
+ const importer = new tr.e.importer.GzipImporter(null, buffer);
+ assert.isTrue(tr.e.importer.GzipImporter.canImport(buffer));
+ assert.strictEqual(
+ importer.extractSubtraces()[0].toString(), ORIGINAL_DATA);
+ });
+
+ test('import', function() {
+ const gzipData = Base64.atob(GZIP_DATA_BASE_64);
+ assert.isTrue(tr.e.importer.GzipImporter.canImport(gzipData));
+
+ const model = tr.c.TestUtils.newModelWithEvents(gzipData);
+ const threads = model.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const slice = findSliceNamed(threads[0].sliceGroup, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ });
+
+ test('transformToString', function() {
+ function checkTransform(data, expectedString) {
+ assert.strictEqual(tr.e.importer.GzipImporter.transformToString(data),
+ expectedString);
+ }
+
+ function createArrayBuffer(values) {
+ const buffer = new ArrayBuffer(values.length);
+ const view = new Uint8Array(buffer);
+ view.set(values);
+ return buffer;
+ }
+
+ // If the browser supports TextDecoder, this will test our custom
+ // implementation. Otherwise, the jszip fallback will be tested.
+ checkTransform('abc012', 'abc012');
+ checkTransform([100, 101, 102, 51, 52, 53], 'def345');
+ checkTransform(createArrayBuffer([103, 104, 105, 54, 55, 56]), 'ghi678');
+ checkTransform(new Uint8Array([106, 107, 108, 57, 58, 59]), 'jkl9:;');
+
+ if (typeof TextDecoder === 'undefined') {
+ // The browser doesn't support TextDecoder, so we have already checked
+ // the jszip fallback.
+ return;
+ }
+
+ // The browser supports TextDecoder, so we now check the jszip fallback.
+ const oldTextDecoder = TextDecoder;
+ TextDecoder = undefined;
+ try {
+ checkTransform('abc012', 'abc012');
+ checkTransform([100, 101, 102, 51, 52, 53], 'def345');
+ checkTransform(createArrayBuffer([103, 104, 105, 54, 55, 56]), 'ghi678');
+ checkTransform(new Uint8Array([106, 107, 108, 57, 58, 59]), 'jkl9:;');
+ } finally {
+ TextDecoder = oldTextDecoder;
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/heap_dump_trace_event_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/heap_dump_trace_event_importer.html
new file mode 100644
index 00000000000..e22671b6359
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/heap_dump_trace_event_importer.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/heap_dump.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Logic for importing a Heap Dump.
+ */
+tr.exportTo('tr.e.importer', function() {
+ /**
+ * @constructor
+ */
+ function HeapDumpTraceEventImporter(
+ heapProfileExpander,
+ stackFrames,
+ processMemoryDump,
+ idPrefix,
+ model) {
+ this.expander = heapProfileExpander;
+ this.stackFrames = stackFrames;
+ this.processMemoryDump = processMemoryDump;
+ this.idPrefix = idPrefix;
+ this.model = model;
+ }
+
+ HeapDumpTraceEventImporter.prototype = {
+
+ getLeafStackFrame(stackFrameId) {
+ // Root.
+ if (stackFrameId === '') return undefined;
+ const parentId = this.idPrefix + stackFrameId;
+ const id = parentId + ':self';
+
+ // In the new format all values are 'self' values,
+ // we distingiush these from the totals in the UI via
+ // artificial '<self>' stack frames.
+ if (!this.stackFrames[id]) {
+ const parentStackFrame = this.stackFrames[parentId];
+ const stackFrame = new tr.model.StackFrame(
+ parentStackFrame, id, '<self>',
+ undefined /* colorId */);
+ this.model.addStackFrame(stackFrame);
+ }
+ return this.stackFrames[id];
+ },
+
+ parseEntry(entry, heapDump) {
+ const size = entry.size;
+ const count = entry.count;
+ const leafStackFrame = this.getLeafStackFrame(entry.node.id);
+ const objectTypeName = entry.type.name;
+ const valuesAreTotals = false;
+ if (objectTypeName === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Missing object type name (ID ' + typeId + ')',
+ });
+ }
+ heapDump.addEntry(
+ leafStackFrame, objectTypeName, size, count, valuesAreTotals);
+ },
+
+ parse() {
+ const heapDumps = {};
+ const inflated = this.expander.inflated;
+ for (const [allocatorName, entries] of Object.entries(inflated)) {
+ const heapDump =
+ new tr.model.HeapDump(this.processMemoryDump, allocatorName);
+ for (const entry of entries) {
+ this.parseEntry(entry, heapDump);
+ }
+ heapDump.isComplete = true;
+ heapDumps[allocatorName] = heapDump;
+ }
+ return heapDumps;
+ },
+
+ };
+
+ return {
+ HeapDumpTraceEventImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/jszip.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/jszip.html
new file mode 100644
index 00000000000..5db6c4bbfc3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/jszip.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+// Vinn workaround for JSzip requiring window.
+if (tr.isVinn) {
+ /**
+ * Hack.
+ */
+ global.window = {};
+}
+</script>
+<script src="/jszip.min.js"></script>
+<script>
+'use strict';
+// Vinn workaround for JSzip requiring window.
+if (tr.isVinn) {
+ /**
+ * Hack.
+ */
+ global.JSZip = global.window.JSZip;
+ global.window = undefined;
+} else if (tr.isNode) {
+ const jsZipAbsPath = HTMLImportsLoader.hrefToAbsolutePath(
+ '/jszip.min.js');
+ const jsZipModule = require(jsZipAbsPath);
+ global.JSZip = jsZipModule;
+}
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/legacy_heap_dump_trace_event_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/legacy_heap_dump_trace_event_importer.html
new file mode 100644
index 00000000000..ee0097b903c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/legacy_heap_dump_trace_event_importer.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html>
+
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/heap_dump.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Logic for importing a Heap Dump.
+ */
+tr.exportTo('tr.e.importer', function() {
+ /**
+ * @constructor
+ * @param {!tr.model.Model} model The model we are currently building.
+ * @param {!tr.model.ProcessMemoryDump} processMemoryDump
+ * The parent memory dump for this heap dump.
+ * @param {!Map|undefined} processObjectTypeNameMap
+ * A map from raw heap dump 'type' ids to human-readable names.
+ * @param {!string} idPrefix Process-specific prefix to prepend to a stack
+ * trace id before looking it up in the model.
+ * @param {!string} dumpId
+ * Raw heap dump id, used only for nice error messages.
+ * @param {!Object} rawHeapDumps
+ * Raw heap dump.
+ */
+ function LegacyHeapDumpTraceEventImporter(
+ model,
+ processMemoryDump,
+ processObjectTypeNameMap,
+ idPrefix,
+ dumpId,
+ rawHeapDumps) {
+ this.model_ = model;
+ this.processObjectTypeNameMap_ = processObjectTypeNameMap;
+ this.idPrefix_ = idPrefix;
+ this.processMemoryDump_ = processMemoryDump;
+ this.pid_ = this.processMemoryDump_.process.pid;
+ this.dumpId_ = dumpId;
+ this.rawHeapDumps_ = rawHeapDumps;
+ }
+
+ LegacyHeapDumpTraceEventImporter.prototype = {
+ /**
+ * Parse rawHeapDump and add entries to heapDump.
+ *
+ * @param {!{!entries:(!Array<!Object>|undefined)}} rawHeapDump
+ * The data we're going to parse.
+ * @param {!string} allocatorName e.g. malloc.
+ * @return {!tr.model.HeapDump} on success or undefined on an error.
+ */
+ parseRawHeapDump(rawHeapDump, allocatorName) {
+ const model = this.model_;
+ const processMemoryDump = this.processMemoryDump_;
+ const heapDump = new tr.model.HeapDump(processMemoryDump, allocatorName);
+
+ const entries = rawHeapDump.entries;
+ if (entries === undefined || entries.length === 0) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'No heap entries in a ' + allocatorName +
+ ' heap dump for PID=' + this.pid_ +
+ ' and dump ID=' + this.dumpId_ + '.'
+ });
+
+ return undefined;
+ }
+
+ // The old format always starts with a {size: <total>} entry.
+ // See https://goo.gl/WYStil
+ // TODO(petrcermak): Remove support for the old format once the new
+ // format has been around long enough.
+ const isOldFormat = entries[0].bt === undefined;
+ if (!isOldFormat && this.processObjectTypeNameMap_ === undefined) {
+ // Mapping from object type IDs to names must be provided in the new
+ // format.
+ return undefined;
+ }
+
+ for (let i = 0; i < entries.length; i++) {
+ const entry = entries[i];
+ const size = parseInt(entry.size, 16);
+ const leafStackFrameIndex = entry.bt;
+ let leafStackFrame;
+
+ // There are two possible mappings from leaf stack frame indices
+ // (provided in the trace) to the corresponding stack frames
+ // depending on the format.
+ if (isOldFormat) {
+ // Old format:
+ // Undefined index -> / (root)
+ // Defined index for /A/B -> /A/B/<self>
+ if (leafStackFrameIndex === undefined) {
+ leafStackFrame = undefined; /* root */
+ } else {
+ // Get the leaf stack frame corresponding to the provided index.
+ let leafStackFrameId = this.idPrefix_ + leafStackFrameIndex;
+ if (leafStackFrameIndex === '') {
+ leafStackFrame = undefined; /* root */
+ } else {
+ leafStackFrame = model.stackFrames[leafStackFrameId];
+ if (leafStackFrame === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Missing leaf stack frame (ID ' +
+ leafStackFrameId + ') of heap entry ' + i + ' (size ' +
+ size + ') in a ' + allocatorName +
+ ' heap dump for PID=' + this.pid_ + '.'
+ });
+ continue;
+ }
+ }
+
+ // Inject an artificial <self> leaf stack frame.
+ leafStackFrameId += ':self';
+ if (model.stackFrames[leafStackFrameId] !== undefined) {
+ // The frame might already exist if there are multiple process
+ // memory dumps (for the same process) in the trace.
+ leafStackFrame = model.stackFrames[leafStackFrameId];
+ } else {
+ leafStackFrame = new tr.model.StackFrame(
+ leafStackFrame, leafStackFrameId, '<self>',
+ undefined /* colorId */);
+ model.addStackFrame(leafStackFrame);
+ }
+ }
+ } else {
+ // New format:
+ // Undefined index -> (invalid value)
+ // Defined index for /A/B -> /A/B
+ if (leafStackFrameIndex === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Missing stack frame ID of heap entry ' + i +
+ ' (size ' + size + ') in a ' + allocatorName +
+ ' heap dump for PID=' + this.pid_ + '.'
+ });
+ continue;
+ }
+
+ // Get the leaf stack frame corresponding to the provided index.
+ const leafStackFrameId = this.idPrefix_ + leafStackFrameIndex;
+ if (leafStackFrameIndex === '') {
+ leafStackFrame = undefined; /* root */
+ } else {
+ leafStackFrame = model.stackFrames[leafStackFrameId];
+ if (leafStackFrame === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Missing leaf stack frame (ID ' + leafStackFrameId +
+ ') of heap entry ' + i + ' (size ' + size + ') in a ' +
+ allocatorName + ' heap dump for PID=' + this.pid_ + '.'
+ });
+ continue;
+ }
+ }
+ }
+
+ const objectTypeId = entry.type;
+ let objectTypeName;
+ if (objectTypeId === undefined) {
+ objectTypeName = undefined; /* total over all types */
+ } else if (this.processObjectTypeNameMap_ === undefined) {
+ // This can only happen when the old format is used.
+ continue;
+ } else {
+ objectTypeName = this.processObjectTypeNameMap_[objectTypeId];
+ if (objectTypeName === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Missing object type name (ID ' + objectTypeId +
+ ') of heap entry ' + i + ' (size ' + size + ') in a ' +
+ allocatorName + ' heap dump for PID=' + this.pid_ + '.'
+ });
+ continue;
+ }
+ }
+
+ const count = entry.count === undefined ? undefined :
+ parseInt(entry.count, 16);
+ heapDump.addEntry(leafStackFrame, objectTypeName, size, count);
+ }
+
+ return heapDump;
+ },
+
+ parse() {
+ const heapDumps = {};
+ for (const allocatorName in this.rawHeapDumps_) {
+ const rawHeapDump = this.rawHeapDumps_[allocatorName];
+ const heapDump = this.parseRawHeapDump(rawHeapDump, allocatorName);
+
+ // Throw away heap dumps with no entries. This can happen if all raw
+ // entries in the trace are skipped for some reason (e.g. invalid leaf
+ // stack frame ID).
+ if (heapDump !== undefined && heapDump.entries.length > 0) {
+ heapDumps[allocatorName] = heapDump;
+ }
+ }
+ return heapDumps;
+ },
+
+ };
+
+ return {
+ LegacyHeapDumpTraceEventImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/android_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/android_parser.html
new file mode 100644
index 00000000000..bf534205db6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/android_parser.html
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses trace_marker events that were inserted in the trace by
+ * userland.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux trace mark events that were inserted in the trace by userland.
+ * @constructor
+ */
+ function AndroidParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('tracing_mark_write:android',
+ AndroidParser.prototype.traceMarkWriteAndroidEvent.bind(this));
+ importer.registerEventHandler('0:android',
+ AndroidParser.prototype.traceMarkWriteAndroidEvent.bind(this));
+
+ this.model_ = importer.model_;
+ this.ppids_ = {};
+ }
+
+ function parseArgs(argsString) {
+ const args = {};
+ if (argsString) {
+ const argsArray = argsString.split(';');
+ for (let i = 0; i < argsArray.length; ++i) {
+ const parts = argsArray[i].split('=');
+ if (parts[0]) {
+ args[parts.shift()] = parts.join('=');
+ }
+ }
+ }
+ return args;
+ }
+
+ AndroidParser.prototype = {
+ __proto__: Parser.prototype,
+
+ openAsyncSlice(thread, category, name, cookie, ts, args) {
+ const asyncSliceConstructor =
+ tr.model.AsyncSlice.subTypes.getConstructor(
+ category, name);
+ const slice = new asyncSliceConstructor(
+ category, name,
+ ColorScheme.getColorIdForGeneralPurposeString(name), ts, args);
+ const key = category + ':' + name + ':' + cookie;
+ slice.id = cookie;
+ slice.startThread = thread;
+
+ if (!this.openAsyncSlices) {
+ this.openAsyncSlices = { };
+ }
+ this.openAsyncSlices[key] = slice;
+ },
+
+ closeAsyncSlice(thread, category, name, cookie, ts, args) {
+ if (!this.openAsyncSlices) {
+ // No async slices have been started.
+ return;
+ }
+
+ const key = category + ':' + name + ':' + cookie;
+ const slice = this.openAsyncSlices[key];
+ if (!slice) {
+ // No async slices w/ this key have been started.
+ return;
+ }
+
+ for (const arg in args) {
+ if (slice.args[arg] !== undefined) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Both the S and F events of ' + slice.title +
+ ' provided values for argument ' + arg + '.' +
+ ' The value of the F event will be used.'
+ });
+ }
+ slice.args[arg] = args[arg];
+ }
+
+ slice.endThread = thread;
+ slice.duration = ts - slice.start;
+ slice.startThread.asyncSliceGroup.push(slice);
+ delete this.openAsyncSlices[key];
+ },
+
+ traceMarkWriteAndroidEvent(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ const eventData = eventBase.details.split('|');
+ switch (eventData[0]) {
+ case 'B': {
+ const ppid = parseInt(eventData[1]);
+ const title = eventData[2];
+ const args = parseArgs(eventData[3]);
+ let category = eventData[4];
+ if (category === undefined) category = 'android';
+
+ const thread = this.model_.getOrCreateProcess(ppid)
+ .getOrCreateThread(pid);
+ thread.name = eventBase.threadName;
+ if (!thread.sliceGroup.isTimestampValidForBeginOrEnd(ts)) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Timestamps are moving backward.'
+ });
+ return false;
+ }
+
+ this.ppids_[pid] = ppid;
+ thread.sliceGroup.beginSlice(category, title, ts, args);
+
+ break;
+ }
+
+ case 'E': {
+ const ppid = this.ppids_[pid];
+ if (ppid === undefined) {
+ // Silently ignore unmatched E events.
+ break;
+ }
+
+ const thread = this.model_.getOrCreateProcess(ppid)
+ .getOrCreateThread(pid);
+ if (!thread.sliceGroup.openSliceCount) {
+ // Silently ignore unmatched E events.
+ break;
+ }
+
+ const slice = thread.sliceGroup.endSlice(ts);
+
+ const args = parseArgs(eventData[3]);
+ for (const arg in args) {
+ if (slice.args[arg] !== undefined) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Both the B and E events of ' + slice.title +
+ ' provided values for argument ' + arg + '.' +
+ ' The value of the E event will be used.'
+ });
+ }
+ slice.args[arg] = args[arg];
+ }
+
+ break;
+ }
+
+ case 'C': {
+ const ppid = parseInt(eventData[1]);
+ const name = eventData[2];
+ const value = parseInt(eventData[3]);
+ let category = eventData[4];
+ if (category === undefined) category = 'android';
+
+ const ctr = this.model_.getOrCreateProcess(ppid)
+ .getOrCreateCounter(category, name);
+ // Initialize the counter's series fields if needed.
+ if (ctr.numSeries === 0) {
+ ctr.addSeries(new tr.model.CounterSeries(value,
+ ColorScheme.getColorIdForGeneralPurposeString(
+ ctr.name + '.' + 'value')));
+ }
+
+ ctr.series.forEach(function(series) {
+ series.addCounterSample(ts, value);
+ });
+
+ break;
+ }
+
+ case 'S': {
+ const ppid = parseInt(eventData[1]);
+ const name = eventData[2];
+ const cookie = parseInt(eventData[3]);
+ const args = parseArgs(eventData[4]);
+ let category = eventData[5];
+ if (category === undefined) category = 'android';
+
+ const thread = this.model_.getOrCreateProcess(ppid)
+ .getOrCreateThread(pid);
+ thread.name = eventBase.threadName;
+
+ this.ppids_[pid] = ppid;
+ this.openAsyncSlice(thread, category, name, cookie, ts, args);
+
+ break;
+ }
+
+ case 'F': {
+ // Note: An async slice may end on a different thread from the one
+ // that started it so this thread may not have been seen yet.
+ const ppid = parseInt(eventData[1]);
+
+ const name = eventData[2];
+ const cookie = parseInt(eventData[3]);
+ const args = parseArgs(eventData[4]);
+ let category = eventData[5];
+ if (category === undefined) category = 'android';
+
+ const thread = this.model_.getOrCreateProcess(ppid)
+ .getOrCreateThread(pid);
+ thread.name = eventBase.threadName;
+
+ this.ppids_[pid] = ppid;
+ this.closeAsyncSlice(thread, category, name, cookie, ts, args);
+
+ break;
+ }
+
+ default:
+ return false;
+ }
+
+ return true;
+ }
+ };
+
+ Parser.register(AndroidParser);
+
+ return {
+ AndroidParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/android_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/android_parser_test.html
new file mode 100644
index 00000000000..0e53e7e5e65
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/android_parser_test.html
@@ -0,0 +1,233 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('androidUserlandImport', function() {
+ const lines = [
+ 'SurfaceFlinger-4831 [001] ...1 80909.598554: tracing_mark_write: B|4829|onMessageReceived', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598572: tracing_mark_write: B|4829|handleMessageInvalidate', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598590: tracing_mark_write: B|4829|latchBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598604: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598627: tracing_mark_write: B|4829|latchBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598651: tracing_mark_write: B|4829|updateTexImage', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598675: tracing_mark_write: B|4829|acquireBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598695: tracing_mark_write: B|4829|' + // @suppress longLineCheck
+ 'com.android.launcher/com.android.launcher2.Launcher: 0',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598709: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598733: tracing_mark_write: C|4829|' + // @suppress longLineCheck
+ 'com.android.launcher/com.android.launcher2.Launcher|0',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598746: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598844: tracing_mark_write: B|4829|releaseBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598862: tracing_mark_write: B|4829|' + // @suppress longLineCheck
+ 'com.android.launcher/com.android.launcher2.Launcher: 2',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598876: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598892: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598925: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598955: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598988: tracing_mark_write: B|4829|latchBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.599001: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.599021: tracing_mark_write: B|4829|latchBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.599036: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.599068: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.599087: tracing_mark_write: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.599104: tracing_mark_write: E'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.parent.pid, 4829);
+ assert.strictEqual(thread.tid, 4831);
+ assert.strictEqual(thread.name, 'SurfaceFlinger');
+ assert.strictEqual(thread.sliceGroup.length, 11);
+ });
+
+ test('androidUserlandImportWithSpacesInThreadName', function() {
+ const lines = [
+ 'Surface Flinger -4831 [001] ...1 80909.598590: tracing_mark_write: B|4829|latchBuffer', // @suppress longLineCheck
+ 'Surface Flinger -4831 [001] ...1 80909.598604: tracing_mark_write: E' // @suppress longLineCheck
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.parent.pid, 4829);
+ assert.strictEqual(thread.tid, 4831);
+ assert.strictEqual(thread.name, 'Surface Flinger ');
+ assert.strictEqual(thread.sliceGroup.length, 1);
+ });
+
+ test('androidAsyncUserlandImport', function() {
+ const lines = [
+ 'ndroid.launcher-9649 ( 9649) [000] ...1 1990280.663276: ' +
+ 'tracing_mark_write: S|9649|animator:childrenOutlineAlpha|' +
+ '1113053968',
+ 'ndroid.launcher-9649 ( 9649) [000] ...1 1990280.781445: ' +
+ 'tracing_mark_write: F|9649|animator:childrenOutlineAlpha|' +
+ '1113053968'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.parent.pid, 9649);
+ assert.strictEqual(thread.tid, 9649);
+ assert.strictEqual(thread.name, 'ndroid.launcher');
+ assert.strictEqual(thread.sliceGroup.length, 0);
+ assert.strictEqual(thread.asyncSliceGroup.length, 1);
+
+ const slice = thread.asyncSliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'animator:childrenOutlineAlpha');
+ assert.closeTo(118.169, slice.duration, 1e-5);
+
+ // no subslice events created
+ assert.strictEqual(slice.subSlices.length, 0);
+ });
+
+ test('androidUserlandLegacyKernelImport', function() {
+ const lines = [
+ 'SurfaceFlinger-4831 [001] ...1 80909.598554: 0: B|4829|onMessageReceived', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598572: 0: B|4829|handleMessageInvalidate', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598590: 0: B|4829|latchBuffer',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598604: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598627: 0: B|4829|latchBuffer',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598651: 0: B|4829|updateTexImage', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598675: 0: B|4829|acquireBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598695: 0: B|4829|' +
+ 'com.android.launcher/com.android.launcher2.Launcher: 0',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598709: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598733: 0: C|4829|' +
+ 'com.android.launcher/com.android.launcher2.Launcher|0',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598746: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598844: 0: B|4829|releaseBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.598862: 0: B|4829|' +
+ 'com.android.launcher/com.android.launcher2.Launcher: 2',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598876: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598892: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598925: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598955: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.598988: 0: B|4829|latchBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.599001: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.599021: 0: B|4829|latchBuffer', // @suppress longLineCheck
+ 'SurfaceFlinger-4831 [001] ...1 80909.599036: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.599068: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.599087: 0: E',
+ 'SurfaceFlinger-4831 [001] ...1 80909.599104: 0: E'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.parent.pid, 4829);
+ assert.strictEqual(thread.tid, 4831);
+ assert.strictEqual(thread.name, 'SurfaceFlinger');
+ assert.strictEqual(thread.sliceGroup.length, 11);
+ });
+
+ test('androidUserlandChromiumImport', function() {
+ const lines = [
+ 'SandboxedProces-2894 [001] ...1 253.780659: tracing_mark_write: B|2867|DoWorkLoop|arg1=1|cat1', // @suppress longLineCheck
+ 'SandboxedProces-2894 [001] ...1 253.780671: tracing_mark_write: B|2867|DeferOrRunPendingTask|source=test=test;task=xyz|cat2', // @suppress longLineCheck
+ 'SandboxedProces-2894 [001] ...1 253.780671: tracing_mark_write: E|2867|DeferOrRunPendingTask||cat1', // @suppress longLineCheck
+ 'SandboxedProces-2894 [001] ...1 253.780686: tracing_mark_write: B|2867|MessageLoop::RunTask|source=ipc/ipc_sync_message_filter.cc:Send|cat2', // @suppress longLineCheck
+ 'SandboxedProces-2894 [001] ...1 253.780700: tracing_mark_write: E|2867|MessageLoop::RunTask||cat1', // @suppress longLineCheck
+ 'SandboxedProces-2894 [001] ...1 253.780750: tracing_mark_write: C|2867|counter1|10|cat1', // @suppress longLineCheck
+ 'SandboxedProces-2894 [001] ...1 253.780859: tracing_mark_write: E|2867|DoWorkLoop|arg2=2|cat2', // @suppress longLineCheck
+ 'SandboxedProces-2894 [000] ...1 255.663276: tracing_mark_write: S|2867|async|1113053968|arg1=1;arg2=2|cat1', // @suppress longLineCheck
+ 'SandboxedProces-2894 [000] ...1 255.663276: tracing_mark_write: F|2867|async|1113053968|arg3=3|cat1', // @suppress longLineCheck
+ 'SandboxedProces-2894 [000] ...1 255.663276: tracing_mark_write: trace_event_clock_sync: parent_ts=128' // @suppress longLineCheck
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.parent.pid, 2867);
+ assert.strictEqual(thread.tid, 2894);
+ assert.strictEqual(thread.name, 'SandboxedProces');
+ assert.strictEqual(thread.sliceGroup.length, 3);
+
+ assert.strictEqual(thread.sliceGroup.slices[0].args.arg1, '1');
+ assert.strictEqual(thread.sliceGroup.slices[0].args.arg2, '2');
+
+ assert.strictEqual(thread.sliceGroup.slices[1].args.source, 'test=test');
+ assert.strictEqual(thread.sliceGroup.slices[1].category, 'cat2');
+ assert.strictEqual('DeferOrRunPendingTask',
+ thread.sliceGroup.slices[1].title);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.task, 'xyz');
+
+ assert.strictEqual('ipc/ipc_sync_message_filter.cc:Send',
+ thread.sliceGroup.slices[2].args.source);
+
+ assert.strictEqual(thread.asyncSliceGroup.length, 1);
+ assert.strictEqual(thread.asyncSliceGroup.slices[0].args.arg1, '1');
+ assert.strictEqual(thread.asyncSliceGroup.slices[0].args.arg2, '2');
+ assert.strictEqual(thread.asyncSliceGroup.slices[0].args.arg3, '3');
+
+ const counters = m.getAllCounters();
+ assert.strictEqual(counters.length, 1);
+ assert.strictEqual(counters[0].category, 'cat1');
+ assert.strictEqual(counters[0].name, 'counter1');
+
+ assert.strictEqual(counters[0].numSamples, 1);
+ assert.strictEqual(counters[0].getSeries(0).getSample(0).value, 10);
+
+ assert.strictEqual(Math.round((253.780659 - (255.663276 - 128)) * 1000),
+ Math.round(thread.sliceGroup.slices[0].start));
+ });
+
+ test('androidNeedReschedImport', function() {
+ const lines = [
+ 'RenderThread-3894 [001] ...1 253.780659: tracing_mark_write: B|3586|DrawFrame', // @suppress longLineCheck
+ 'RenderThread-3894 [001] ...1 253.780671: tracing_mark_write: B|3586|waitForTask', // @suppress longLineCheck
+ 'RenderThread-3894 [001] .N.1 253.780671: tracing_mark_write: E', // @suppress longLineCheck
+ 'RenderThread-3894 [001] ...1 253.780671: tracing_mark_write: B|3586|waitForTask', // @suppress longLineCheck
+ 'RenderThread-3894 [001] .n.1 253.780671: tracing_mark_write: E', // @suppress longLineCheck
+ 'RenderThread-3894 [001] ...1 253.780671: tracing_mark_write: B|3586|waitForTask', // @suppress longLineCheck
+ 'RenderThread-3894 [001] .p.1 253.780671: tracing_mark_write: E', // @suppress longLineCheck
+ 'RenderThread-3894 [001] ...1 253.780686: tracing_mark_write: E' // @suppress longLineCheck
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings, 'hasImportWarnings');
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.parent.pid, 3586);
+ assert.strictEqual(thread.tid, 3894);
+ assert.strictEqual(thread.name, 'RenderThread');
+ assert.strictEqual(thread.sliceGroup.length, 4);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser.html
new file mode 100644
index 00000000000..690d2dd6786
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser.html
@@ -0,0 +1,732 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses Binder events
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ // Matches binder transactions:
+ // transaction=%d dest_node=%d dest_proc=%d dest_thread=%d reply=%d flags=0x%x
+ // code=0x%x
+ const binderTransRE = new RegExp('transaction=(\\d+) dest_node=(\\d+) ' +
+ 'dest_proc=(\\d+) dest_thread=(\\d+) ' +
+ 'reply=(\\d+) flags=(0x[0-9a-fA-F]+) ' +
+ 'code=(0x[0-9a-fA-F]+)');
+ // binder_transaction_alloc_buf: transaction=%d data_size=%d offsets_size=%d
+ const binderAllocRE = new RegExp('transaction=(\\d+) data_size=(\\d+) ' +
+ 'offsets_size=(\\d+)');
+
+ const binderTransReceivedRE = /transaction=(\d+)/;
+
+ function isBinderThread(name) {
+ return (name.indexOf('Binder') > -1);
+ }
+
+ // Taken from kernel source: include/uapi/linux/android/binder.h.
+ const TF_ONE_WAY = 0x01;
+ const TF_ROOT_OBJECT = 0x04;
+ const TF_STATUS_CODE = 0x08;
+ const TF_ACCEPT_FDS = 0x10;
+ const NO_FLAGS = 0;
+
+ function binderFlagsToHuman(num) {
+ const flag = parseInt(num, 16);
+ let str = '';
+
+ if (flag & TF_ONE_WAY) {
+ str += 'this is a one-way call: async, no return; ';
+ }
+ if (flag & TF_ROOT_OBJECT) {
+ str += 'contents are the components root object; ';
+ }
+ if (flag & TF_STATUS_CODE) {
+ str += 'contents are a 32-bit status code; ';
+ }
+ if (flag & TF_ACCEPT_FDS) {
+ str += 'allow replies with file descriptors; ';
+ }
+ if (flag === NO_FLAGS) {
+ str += 'No Flags Set';
+ }
+
+ return str;
+ }
+
+ function isReplyToOrigin(calling, called) {
+ return (called.dest_proc === calling.calling_pid ||
+ called.dest_thread === calling.calling_pid);
+ }
+
+ function binderCodeToHuman(code) {
+ return 'Java Layer Dependent';
+ }
+
+ function doInternalSlice(trans, slice, ts) {
+ if (slice.subSlices.length !== 0) {
+ /* We want to make sure we keep moving the small slice to the end of
+ the big slice or else the arrows will not point to the end.
+ */
+ slice.subSlices[0].start = ts;
+ return slice.subSlices[0];
+ }
+ const kthread = trans.calling_kthread.thread;
+ const internalSlice = kthread.sliceGroup.pushCompleteSlice('binder',
+ slice.title,
+ ts, .001, 0, 0,
+ slice.args);
+
+ internalSlice.title = slice.title;
+ internalSlice.id = slice.id;
+ internalSlice.colorId = slice.colorId;
+ slice.subSlices.push(internalSlice);
+ return internalSlice;
+ }
+
+ function generateBinderArgsForSlice(trans, cThreadName) {
+ return {
+ 'Transaction Id': trans.transaction_key,
+ 'Destination Node': trans.dest_node,
+ 'Destination Process': trans.dest_proc,
+ 'Destination Thread': trans.dest_thread,
+ 'Destination Name': cThreadName,
+ 'Reply transaction?': trans.is_reply_transaction,
+ 'Flags': trans.flags + ' ' +
+ binderFlagsToHuman(trans.flags),
+
+ 'Code': trans.code + ' ' +
+ binderCodeToHuman(trans.code),
+
+ 'Calling PID': trans.calling_pid,
+ 'Calling tgid': trans.calling_kthread.thread.parent.pid
+ };
+ }
+
+ /** @constructor */
+ function BinderTransaction(events, callingPid, callingTs, callingKthread) {
+ this.transaction_key = parseInt(events[1]);
+ this.dest_node = parseInt(events[2]);
+ this.dest_proc = parseInt(events[3]);
+ this.dest_thread = parseInt(events[4]);
+ this.is_reply_transaction = parseInt(events[5]) === 1 ? true : false;
+ this.expect_reply = ((this.is_reply_transaction === false) &&
+ (parseInt(events[6], 16) & TF_ONE_WAY) === 0);
+
+ this.flags = events[6];
+ this.code = events[7];
+ this.calling_pid = callingPid;
+ this.calling_ts = callingTs;
+ this.calling_kthread = callingKthread;
+ }
+
+
+ /** @constructor */
+ function BinderParser(importer) {
+ Parser.call(this, importer);
+ importer.registerEventHandler('binder_locked',
+ BinderParser.prototype.
+ binderLocked.bind(this));
+ importer.registerEventHandler('binder_unlock',
+ BinderParser.prototype.
+ binderUnlock.bind(this));
+ importer.registerEventHandler('binder_lock',
+ BinderParser.prototype.binderLock.bind(this));
+ importer.registerEventHandler('binder_transaction',
+ BinderParser.prototype.
+ binderTransaction.bind(this));
+ importer.registerEventHandler('binder_transaction_received',
+ BinderParser.prototype.
+ binderTransactionReceived.bind(this));
+ importer.registerEventHandler('binder_transaction_alloc_buf',
+ BinderParser.prototype.
+ binderTransactionAllocBuf.bind(this));
+
+ this.model_ = importer.model;
+ this.kthreadlookup = {};
+ this.importer_ = importer;
+ this.transWaitingRecv = {};
+ this.syncTransWaitingCompletion = {};
+ this.recursiveSyncTransWaitingCompletion_ByPID = {};
+ this.receivedTransWaitingConversion = {};
+ }
+
+ BinderParser.prototype = {
+ __proto__: Parser.prototype,
+
+ binderLock(eventName, cpuNumber, pid, ts, eventBase) {
+ const tgid = parseInt(eventBase.tgid);
+ if (isNaN(tgid)) return false;
+
+ this.doNameMappings(pid, tgid, eventName.threadName);
+
+ const kthread = this.importer_.
+ getOrCreateBinderKernelThread(eventBase.threadName, tgid, pid);
+
+ kthread.binderAttemptLockTS = ts;
+ kthread.binderOpenTsA = ts;
+ return true;
+ },
+
+ binderLocked(eventName, cpuNumber, pid, ts, eventBase) {
+ const tgid = parseInt(eventBase.tgid);
+ if (isNaN(tgid)) return false;
+
+ const binderThread = isBinderThread(eventBase.threadName);
+ const name = eventBase.threadName;
+
+ const kthread = this.importer_.
+ getOrCreateBinderKernelThread(eventBase.threadName, tgid, pid);
+
+ this.doNameMappings(pid, tgid, name);
+
+ const rthread = kthread.thread;
+ kthread.binderLockAquiredTS = ts;
+
+ if (kthread.binderAttemptLockTS === undefined) return false;
+
+ const args = this.generateArgsForSlice(tgid, pid, name, kthread);
+ rthread.sliceGroup.pushCompleteSlice('binder', 'binder lock waiting',
+ kthread.binderAttemptLockTS,
+ ts - kthread.binderAttemptLockTS,
+ 0, 0, args);
+
+ kthread.binderAttemptLockTS = undefined;
+ return true;
+ },
+
+ binderUnlock(eventName, cpuNumber, pid, ts, eventBase) {
+ const tgid = parseInt(eventBase.tgid);
+ if (isNaN(tgid)) return false;
+
+ const kthread = this.importer_.
+ getOrCreateBinderKernelThread(
+ eventBase.threadName, tgid, pid);
+
+ if (kthread.binderLockAquiredTS === undefined) return false;
+
+ const args = this.generateArgsForSlice(tgid, pid, eventBase.threadName,
+ kthread);
+ kthread.thread.sliceGroup.pushCompleteSlice(
+ 'binder',
+ 'binder lock held',
+ kthread.binderLockAquiredTS,
+ ts - kthread.binderLockAquiredTS,
+ 0, 0, args);
+
+ kthread.binderLockAquiredTS = undefined;
+ return true;
+ },
+
+ /** There are a few transaction status changes that signify
+ * progress through a binder transaction:
+ *
+ * Case One: Sync transaction.
+ * Thread A calls a blocking function on Thread B. We receive a
+ * binder_transaction msg From thread A stating that it is going to Call
+ * thread B. We create a slice and a binder object for this transaction and
+ * add it to addTransactionWaitingForRecv(transaction key, binder object)
+ * This notifies thread B and passes the slice, binder object and time
+ * stamp.
+ *
+ * Case Two: Async transaction.
+ * Thread A calls an async function on Thread B. Like above we receive a
+ * binder_transaction message, but the flags differ from above. The
+ * TF_ONEWAY flags are set so we know that when Thread B gets the
+ * binder_transaction_received with the same transaciton key the total
+ * transaction is complete.
+ *
+ * Case Three: 'Prior_receive'
+ * Prior_receive occurs when the thread being called (think A calls B),
+ * receives a binder_transaction_received message, but cannot correlate it
+ * to any current outstanding recursive transactions. That means the
+ * message it just received is the start of some communication, not some
+ * ongoing communication.
+ * Once the execution flow has been passed to thread B, from A:
+ * Thread B enters binder_transaction_received() we see that Thread A
+ * had notified us that it sent us a message by calling
+ * getTransactionWaitingForRecv(transaction key);
+ * What can happen now is either this was a simple Call reply,
+ * or this is a call -> recursion -> reply. We call modelPriorReceive()
+ * which sets up the slices accordingly.
+ * If this is a call -> recursion -> reply
+ * we will go to case 4 by calling addRecursiveSyncTransNeedingCompletion()
+ * The function takes B's PID, the binder object from A and the current
+ * binder object from B. This function adds outstanding non-complete
+ * transactions to a stack on thread B.
+ *
+ * Case Four: 'recursiveTrans'
+ * This case follows Like above:
+ * A sent binder_transaction
+ * B got binder_transaction_received
+ * B instead of replying to A can Call C or call 'into' A, ie recursion
+ * Case four also deals with setting up a large slice to 'contain'
+ * all the recursive transactions that happen until B finally replies to
+ * A.
+ *
+ *
+ * An example: A-> B-> C-> B-> A
+ *
+ * (1) A starts a synchronous transaction to B.
+ * (2) A enters binderTransaction() event handler, hits the else statement
+ * (3) A calls addTransactionWaitingForRecv(trans key, object) to notify
+ * Thread B.
+ * (4) B Enters binderTransactionReceived().
+ * (5) B hits the second if after calling
+ * getTransactionWaitingForRecv(trans key)
+ * This function returns us the object set up in step (3).
+ * (6) This is not an async transaction, B calls
+ * setCurrentReceiveOnPID(B's PID, [ts for (4), object from (3)]).
+ *
+ * (7) B enters binderTransaction() event handler, first if triggers after
+ * calling getPriorReceiveOnPID(B's PID) the tuple from (6) is returned.
+ *
+ * (8) Execution enters modelPriorReceive().
+ * (8a) A slice is setup for this binder transaction in B's timeline.
+ * (9) This is not a reply to thread A, B is going to call Thread C.
+ * (10) else statement is hit.
+ * (11) We set the tile from (8a) to be binder_reply this is the
+ * 'containg slice' for the recursion
+ * (12) We create a new slice 'binder_transaction' this slice is the
+ * recursive slice that will have arrows to Thread C's slice.
+ * (13) addRecursiveSyncTransNeedingCompletion(B's PID,
+ * [obj from (3), obj from 7])
+ * this sets up notification that B's pid has outstanding recursive
+ * transactions that need to be completed.
+ * (14) B notifies C that a transaction is waiting for it by calling
+ * addTransactionWaitingForRecv like in step (3).
+ * (15) C enters binderTransactionReceived() step 5 6 7 8 8a happen, but in
+ * the context of Thread C.
+ * (16) C is in modelPriorReceive(), it hits the first if statement,
+ * this transaction _IS_ a reply, and it is a reply to B.
+ * (17) C calls addSyncTransNeedingCompletion(trans key,
+ * [object from(3), object from 15-5])
+ * (18) B enters binderTransactionReceived() hits the first if after calling
+ * getSyncTransNeedingCompletion(trans key from (17)) the tuple from
+ * (17) gets returned.
+ *
+ * (19) B scales up the slice created in (12) and sets up flows from 15-8a
+ * slice.
+ * (20) B enters BinderTransaction() event handler and the second if is hit
+ * after calling getRecursiveTransactionNeedingCompletion(B's pid).
+ * (21) modelRecursiveTransactions() gets called, first if executes.
+ * (22) slice durations are fixed up.
+ * (23) B notifies A via
+ * addSyncTransNeedingCompletion(trans key, binder obj from 8a).
+ * (24) B deletes the outstanding asynctrans via
+ ( removeRecursiveTransaction(B's pid).
+ * (25) A enters binderTransactionReceived() event handler and finishes up
+ * some flows, and slices.
+ */
+ binderTransaction(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = binderTransRE.exec(eventBase.details);
+ if (event === undefined) return false;
+
+ const tgid = parseInt(eventBase.tgid);
+ if (isNaN(tgid)) return false;
+
+ this.doNameMappings(pid, tgid, eventBase.threadName);
+
+ const kthread = this.importer_.
+ getOrCreateBinderKernelThread(eventBase.threadName, tgid, pid);
+
+ const trans = new BinderTransaction(event, pid, ts, kthread);
+ const args = generateBinderArgsForSlice(trans, eventBase.threadName);
+ /**
+ * This thread previously ack'd the transaction with a
+ * transaction_received. That means someone sent us a message we processed
+ * it and are now sending a transaction.
+ * The transaction could be a response, or it could be recursive.
+ */
+ const priorReceive = this.getPriorReceiveOnPID(pid);
+
+ if (priorReceive !== false) {
+ return this.modelPriorReceive(priorReceive, ts, pid, tgid, kthread,
+ trans, args, event);
+ }
+ /**
+ * This Thread has an already established recursive slice. We will now
+ * either complete the entire transaction, OR do more recursive calls.
+ */
+ const recursiveTrans = this.getRecursiveTransactionNeedingCompletion(pid);
+
+ if (recursiveTrans !== false) {
+ return this.modelRecursiveTransactions(recursiveTrans, ts, pid,
+ kthread, trans, args);
+ }
+
+ /**
+ * Start of a Transaction. This thread is the initiator of either a call
+ * response, an async call -> ack, or a call -> recursion -> response.
+ * Note, we put a fake duration into this slice and patch it up later.
+ */
+ const slice = kthread.thread.sliceGroup.pushCompleteSlice('binder',
+ '', ts, .03, 0, 0, args);
+
+ slice.colorId = ColorScheme.getColorIdForGeneralPurposeString(
+ ts.toString());
+ trans.slice = slice;
+
+ if (trans.expect_reply) {
+ slice.title = 'binder transaction';
+ } else {
+ slice.title = 'binder transaction async';
+ }
+
+ this.addTransactionWaitingForRecv(trans.transaction_key, trans);
+
+ return true;
+ },
+
+ binderTransactionReceived(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ const event = binderTransReceivedRE.exec(eventBase.details);
+ if (event === undefined) return false;
+ const tgid = parseInt(eventBase.tgid);
+ if (isNaN(tgid)) return false;
+
+ const transactionkey = parseInt(event[1]);
+ const kthread = this.importer_.
+ getOrCreateBinderKernelThread(eventBase.threadName, tgid, pid);
+
+ const syncComplete = this.getSyncTransNeedsCompletion(transactionkey);
+
+ if (syncComplete !== false) {
+ /* This recv is the completion of a synchronous transaction.
+ * We need to scale the slice up to the current ts and finish
+ * creating some flows.
+ */
+ const syncTrans = syncComplete[0];
+ const syncSlice = syncTrans.slice;
+ const responseTrans = syncComplete[1];
+ const responseSlice = responseTrans.slice;
+
+ syncSlice.duration = ts - syncSlice.start;
+ /** These calls are a little hack that places a very small slice at
+ * the end of the sync slice and the response slice. This allows us
+ * to hook flow events (arrows) from the start to the end of the
+ * slices.
+ */
+ const syncInternal = doInternalSlice(syncTrans, syncSlice, ts);
+ const responseTs = responseSlice.start + responseSlice.duration;
+ const responseInternal = doInternalSlice(responseTrans,
+ responseSlice, responseTs);
+
+ if (responseSlice.outFlowEvents.length === 0 ||
+ syncSlice.inFlowEvents.length === 0) {
+ const flow = this.generateFlow(responseInternal, syncInternal,
+ responseTrans, syncTrans);
+
+ syncSlice.inFlowEvents.push(flow);
+ responseSlice.outFlowEvents.push(flow);
+ this.model_.flowEvents.push(flow);
+ }
+ // Move flow arrows -- but not the first one.
+ for (let i = 1; i < syncSlice.inFlowEvents.length; i++) {
+ syncSlice.inFlowEvents[i].duration =
+ ts - syncSlice.inFlowEvents[i].start;
+ }
+ return true;
+ }
+
+ const trForRecv = this.getTransactionWaitingForRecv(transactionkey);
+
+ if (trForRecv !== false) {
+ if (!trForRecv.expect_reply) {
+ // This is an async call place an Async slice.
+ const args = generateBinderArgsForSlice(trForRecv,
+ eventBase.threadName);
+ const slice = kthread.thread.sliceGroup.
+ pushCompleteSlice('binder',
+ 'binder Async recv',
+ ts, .03, 0, 0,
+ args);
+
+ const fakeEvent = [0, 0, 0, 0, 0, 0, 0];
+ const fakeTrans = new BinderTransaction(fakeEvent, pid, ts, kthread);
+ const flow = this.generateFlow(trForRecv.slice, slice,
+ trForRecv, fakeTrans);
+
+ this.model_.flowEvents.push(flow);
+ trForRecv.slice.title = 'binder transaction async';
+ trForRecv.slice.duration = .03;
+ return true;
+ }
+ // Setup prior receive.
+ trForRecv.slice.title = 'binder transaction';
+ this.setCurrentReceiveOnPID(pid, [ts, trForRecv]);
+ return true;
+ }
+ /** This case is when we received an ack for a transaction we have
+ * never seen before. This usually happens at the start of a trace.
+ * We will get incomplete transactions that started before started
+ * tracing. Just discard them.
+ */
+ return false;
+ },
+
+ binderTransactionAllocBuf(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ const event = binderAllocRE.exec(eventBase.details);
+ if (event === null) return false;
+ const tgid = parseInt(eventBase.tgid);
+ if (isNaN(tgid)) return false;
+
+ const transactionkey = parseInt(event[1]);
+ const kthread = this.importer_.
+ getOrCreateBinderKernelThread(eventBase.threadName, tgid, pid);
+
+ const trans = this.peekTransactionWaitingForRecv(transactionkey);
+ if (trans && trans.slice) {
+ trans.slice.args['Data Size'] = parseInt(event[2]);
+ trans.slice.args['Offsets Size'] = parseInt(event[3]);
+ return true;
+ }
+ return false;
+ },
+
+
+ // helper functions
+ modelRecursiveTransactions(recursiveTrans, ts, pid, kthread,
+ trans, args) {
+ const recursiveSlice = recursiveTrans[1].slice;
+ const origSlice = recursiveTrans[0].slice;
+ recursiveSlice.duration = ts - recursiveSlice.start;
+ recursiveSlice.args = args;
+ trans.slice = recursiveSlice;
+
+ if (trans.is_reply_transaction) {
+ /* Case one:
+ * This transaction is finally the reply of the recursion.
+ */
+ origSlice.duration = ts - origSlice.start;
+ this.addSyncTransNeedingCompletion(trans.transaction_key,
+ recursiveTrans);
+
+ if (isReplyToOrigin(recursiveTrans[0], trans)) {
+ this.removeRecursiveTransaction(pid);
+ }
+ } else {
+ /**
+ * Case two:
+ * This transaction is more recursive calls.
+ * This is a nested call within an already started transaction,
+ * it can either be a async or a normal sync transaction.
+ */
+ const slice = kthread.thread.sliceGroup.pushCompleteSlice('binder',
+ '', ts, .03, 0,
+ 0, args);
+
+ trans.slice = slice;
+ this.addTransactionWaitingForRecv(trans.transaction_key, trans);
+ }
+ return true;
+ },
+
+ modelPriorReceive(priorReceive, ts, pid, tgid, kthread, trans,
+ args, event) {
+ const calleeSlice = priorReceive[1].slice;
+ const calleeTrans = priorReceive[1];
+ const recvTs = priorReceive[0];
+ let slice = kthread.thread.sliceGroup.pushCompleteSlice('binder',
+ '', recvTs, ts - recvTs, 0, 0);
+
+ const flow = this.generateFlow(calleeSlice, slice, calleeTrans, trans);
+ this.model_.flowEvents.push(flow);
+ trans.slice = slice;
+
+ if (trans.is_reply_transaction) {
+ /* This is a response to a synchronous or a recursive sync
+ * transaction.
+ */
+ slice.title = 'binder reply';
+ slice.args = args;
+ /* Notify this transaction key that when it recv's it is completing
+ * a sync transaction.
+ */
+ this.addSyncTransNeedingCompletion(trans.transaction_key,
+ [calleeTrans, trans]);
+ } else {
+ /**
+ * Recursive calls and or calls around, either way it's not
+ * going to complete a transaction.
+ */
+ slice.title = 'binder reply';
+ /* Since this is a recursive transaction we want to create the main
+ * large slice which will contain all these recursive transactions.
+ * For that we created the main slice above and this is a recursive
+ * transaction that will be placed right below it. Note, that this
+ * is only for the first recursive transaction. If more come they will
+ * be handled below in the getRecursiveTransactionNeedingCompletion
+ */
+ const trans1 = new BinderTransaction(event, pid, ts, kthread);
+
+ slice = kthread.thread.sliceGroup.
+ pushCompleteSlice('binder',
+ 'binder transaction',
+ recvTs,
+ (ts - recvTs), 0,
+ 0, args);
+
+ /* could be a async trans if so set the length to be a small one */
+ if (!trans.expect_reply) {
+ slice.title = 'binder transaction async';
+ slice.duration = .03;
+ } else {
+ /* stupid hack to stop merging of AIDL slices and
+ * this slice. This is currently disabled, if AIDL tracing is on we
+ * will see merging of this slice and the AIDL slice. Once upstream
+ * has a solution for flow events to be placed in the middle of
+ * slices this part can be fixed.
+ *
+ * This is commented out because AIDL tracing doesn't exit yet.
+ */
+ // slice.start += .15;
+ }
+ trans1.slice = slice;
+ this.addRecursiveSyncTransNeedingCompletion(pid,
+ [calleeTrans, trans]);
+ this.addTransactionWaitingForRecv(trans.transaction_key, trans1);
+ }
+ return true;
+ },
+
+ getRecursiveTransactionNeedingCompletion(pid) {
+ if (this.recursiveSyncTransWaitingCompletion_ByPID[pid] === undefined) {
+ return false;
+ }
+
+ const len = this.recursiveSyncTransWaitingCompletion_ByPID[pid].length;
+ if (len === 0) return false;
+
+ return this.recursiveSyncTransWaitingCompletion_ByPID[pid][len - 1];
+ },
+
+ addRecursiveSyncTransNeedingCompletion(pid, tuple) {
+ if (this.recursiveSyncTransWaitingCompletion_ByPID[pid] === undefined) {
+ this.recursiveSyncTransWaitingCompletion_ByPID[pid] = [];
+ }
+
+ this.recursiveSyncTransWaitingCompletion_ByPID[pid].push(tuple);
+ },
+
+ removeRecursiveTransaction(pid) {
+ const len = this.recursiveSyncTransWaitingCompletion_ByPID[pid].length;
+ if (len === 0) {
+ delete this.recursiveSyncTransWaitingCompletion_ByPID[pid];
+ return;
+ }
+
+ this.recursiveSyncTransWaitingCompletion_ByPID[pid].splice(len - 1, 1);
+ },
+
+ setCurrentReceiveOnPID(pid, tuple) {
+ if (this.receivedTransWaitingConversion[pid] === undefined) {
+ this.receivedTransWaitingConversion[pid] = [];
+ }
+ this.receivedTransWaitingConversion[pid].push(tuple);
+ },
+
+ getPriorReceiveOnPID(pid) {
+ if (this.receivedTransWaitingConversion[pid] === undefined) {
+ return false;
+ }
+
+ const len = this.receivedTransWaitingConversion[pid].length;
+ if (len === 0) return false;
+
+ return this.receivedTransWaitingConversion[pid].splice(len - 1, 1)[0];
+ },
+
+ addSyncTransNeedingCompletion(transactionkey, tuple) {
+ const dict = this.syncTransWaitingCompletion;
+ dict[transactionkey] = tuple;
+ },
+
+ getSyncTransNeedsCompletion(transactionkey) {
+ const ret = this.syncTransWaitingCompletion[transactionkey];
+ if (ret === undefined) return false;
+
+ delete this.syncTransWaitingCompletion[transactionkey];
+ return ret;
+ },
+
+ getTransactionWaitingForRecv(transactionkey) {
+ const ret = this.transWaitingRecv[transactionkey];
+ if (ret === undefined) return false;
+
+ delete this.transWaitingRecv[transactionkey];
+ return ret;
+ },
+
+ peekTransactionWaitingForRecv(transactionkey) {
+ const ret = this.transWaitingRecv[transactionkey];
+ if (ret === undefined) return false;
+ return ret;
+ },
+
+ addTransactionWaitingForRecv(transactionkey, transaction) {
+ this.transWaitingRecv[transactionkey] = transaction;
+ },
+
+ generateFlow(from, to, fromTrans, toTrans) {
+ const title = 'Transaction from : ' +
+ this.pid2name(fromTrans.calling_pid) +
+ ' From PID: ' + fromTrans.calling_pid + ' to pid: ' +
+ toTrans.calling_pid +
+ ' Thread Name: ' + this.pid2name(toTrans.calling_pid);
+
+ const ts = from.start;
+ const flow = new tr.model.FlowEvent('binder', 'binder',
+ title, 1, ts, []);
+ flow.startSlice = from;
+ flow.endSlice = to;
+ flow.start = from.start;
+ flow.duration = to.start - ts;
+
+ from.outFlowEvents.push(flow);
+ to.inFlowEvents.push(flow);
+
+ return flow;
+ },
+
+ generateArgsForSlice(tgid, pid, name, kthread) {
+ return {
+ 'Thread Name': name,
+ pid,
+ 'gid': tgid
+ };
+ },
+
+ pid2name(pid) {
+ return this.kthreadlookup[pid];
+ },
+
+ doNameMappings(pid, tgid, name) {
+ this.registerPidName(pid, name);
+ this.registerPidName(tgid, name);
+ },
+
+ registerPidName(pid, name) {
+ if (this.pid2name(pid) === undefined) {
+ this.kthreadlookup[pid] = name;
+ }
+ }
+ };
+
+ Parser.register(BinderParser);
+ return {
+ BinderParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser_test.html
new file mode 100644
index 00000000000..07a619b07cf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/binder_parser_test.html
@@ -0,0 +1,273 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('binderParserImport', function() {
+ const lines = [
+ 'binderLibTest-10619 (10619) [001] ...1 25191.335749: ' +
+ 'binder_transaction: transaction=489053 dest_node=489048 ' +
+ 'dest_proc=10670 dest_thread=0 reply=0 flags=0x10 code=0xd',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.335996:' +
+ ' binder_transaction_received: transaction=489053',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.336167:' +
+ ' binder_transaction: transaction=489056 dest_node=161277 ' +
+ 'dest_proc=3454 dest_thread=0 reply=0 flags=0x10 code=0x2',
+ '/system/bin/servicemanager-3454 ( 3454) [000] ...1 25191.336199:' +
+ ' binder_transaction_received: transaction=489056',
+ '/system/bin/servicemanager-3454 ( 3454) [000] ...1 25191.336302:' +
+ ' binder_transaction: transaction=489057 dest_node=0 dest_proc=10670' +
+ ' dest_thread=10670 reply=1 flags=0x0 code=0x0',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.336334:' +
+ ' binder_transaction_received: transaction=489057',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.336655:' +
+ ' binder_transaction: transaction=489059 dest_node=488755' +
+ ' dest_proc=10622 dest_thread=0 reply=0 flags=0x10 code=0x1',
+ 'Binder_4-10645 (10622) [001] ...1 25191.336693:' +
+ ' binder_transaction_received: transaction=489059',
+ 'Binder_4-10645 (10622) [001] ...1 25191.336754: binder_transaction:' +
+ ' transaction=489060 dest_node=0 dest_proc=10670 dest_thread=10670' +
+ ' reply=1 flags=0x0 code=0x0',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.337003:' +
+ ' binder_transaction_received: transaction=489060',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.337052:' +
+ ' binder_transaction: transaction=489061 dest_node=0 dest_proc=10619' +
+ ' dest_thread=10619 reply=1 flags=0x8 code=0x0',
+ 'binderLibTest-10619 (10619) [001] ...1 25191.337085:' +
+ ' binder_transaction_received: transaction=489061',
+ 'atrace-10618 (10618) [000] ...1 25196.059954: tracing_mark_write:' +
+ ' trace_event_clock_sync: parent_ts=25196.050781'
+ ];
+
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shfitWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 4);
+ });
+
+ test('binderRecursiveTest', function() {
+ const lines = [
+ 'binderLibTest-10619 (10619) [001] ...1 25191.335749: ' +
+ 'binder_transaction: transaction=489053 dest_node=489048 ' +
+ 'dest_proc=10670 dest_thread=0 reply=0 flags=0x10 code=0xd',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.335996:' +
+ ' binder_transaction_received: transaction=489053',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.336167:' +
+ ' binder_transaction: transaction=489056 dest_node=161277 ' +
+ 'dest_proc=3454 dest_thread=0 reply=0 flags=0x10 code=0x2',
+ '/system/bin/servicemanager-3454 ( 3454) [000] ...1 25191.336199:' +
+ ' binder_transaction_received: transaction=489056',
+ '/system/bin/servicemanager-3454 ( 3454) [000] ...1 25191.336302:' +
+ ' binder_transaction: transaction=489057 dest_node=0 dest_proc=10670' +
+ ' dest_thread=10670 reply=1 flags=0x0 code=0x0',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.336334:' +
+ ' binder_transaction_received: transaction=489057',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.336655:' +
+ ' binder_transaction: transaction=489059 dest_node=488755' +
+ ' dest_proc=10622 dest_thread=0 reply=0 flags=0x10 code=0x1',
+ 'Binder_4-10645 (10622) [001] ...1 25191.336693:' +
+ ' binder_transaction_received: transaction=489059',
+ 'Binder_4-10645 (10622) [001] ...1 25191.336754: binder_transaction:' +
+ ' transaction=489060 dest_node=0 dest_proc=10670 dest_thread=10670' +
+ ' reply=1 flags=0x0 code=0x0',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.337003:' +
+ ' binder_transaction_received: transaction=489060',
+ 'binderLibTest-10670 (10670) [000] ...1 25191.337052:' +
+ ' binder_transaction: transaction=489061 dest_node=0 dest_proc=10619' +
+ ' dest_thread=10619 reply=1 flags=0x8 code=0x0',
+ 'binderLibTest-10619 (10619) [001] ...1 25191.337085:' +
+ ' binder_transaction_received: transaction=489061',
+ 'atrace-10618 (10618) [000] ...1 25196.059954: tracing_mark_write:' +
+ ' trace_event_clock_sync: parent_ts=25196.050781'
+ ];
+
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shfitWorldToZero: false
+ });
+ const threads = m.getAllThreads();
+
+ let thread = threads[0];
+ assert.strictEqual(thread.parent.pid, 3454);
+ assert.strictEqual(thread.tid, 3454);
+ assert.strictEqual(thread.name, '/system/bin/servicemanager');
+ /* one main slice and one 'internal slice' for the end flow event' */
+ assert.strictEqual(thread.sliceGroup.length, 2);
+
+ /* check flow events for service manager */
+ let mainSlice = thread.sliceGroup.slices[0];
+ assert.strictEqual(mainSlice.inFlowEvents.length, 1);
+ assert.strictEqual(mainSlice.outFlowEvents.length, 1);
+ let internalSlice = thread.sliceGroup.slices[1];
+ assert.strictEqual(internalSlice.outFlowEvents.length, 1);
+
+ /* check name of slice */
+ assert.strictEqual(mainSlice.title, 'binder reply');
+ assert.strictEqual(mainSlice.args['Destination Process'], 10670);
+ assert.strictEqual(mainSlice.args['Destination Thread'], 10670);
+ assert.strictEqual(mainSlice.args['Reply transaction?'], true);
+ assert.strictEqual(mainSlice.args['Calling PID'], 3454);
+ assert.strictEqual(mainSlice.args['Calling tgid'], 3454);
+
+ /* check binderLibTest */
+ thread = threads[1];
+ assert.strictEqual(thread.parent.pid, 10619);
+ assert.strictEqual(thread.tid, 10619);
+ assert.strictEqual(thread.name, 'binderLibTest');
+
+ assert.strictEqual(2, thread.sliceGroup.length);
+
+ mainSlice = thread.sliceGroup.slices[0];
+ assert.strictEqual(mainSlice.inFlowEvents.length, 1);
+ assert.strictEqual(mainSlice.outFlowEvents.length, 1);
+ internalSlice = thread.sliceGroup.slices[1];
+ assert.strictEqual(internalSlice.inFlowEvents.length, 1);
+
+ assert.strictEqual(mainSlice.title, 'binder transaction');
+ assert.strictEqual(mainSlice.args['Destination Process'], 10670);
+ assert.strictEqual(mainSlice.args['Reply transaction?'], false);
+ assert.strictEqual(mainSlice.args['Calling PID'], 10619);
+ assert.strictEqual(mainSlice.args['Calling tgid'], 10619);
+
+ /* check Binder_4 */
+ thread = threads[2];
+ assert.strictEqual(thread.parent.pid, 10622);
+ assert.strictEqual(thread.tid, 10645);
+ assert.strictEqual(thread.name, 'Binder_4');
+ assert.strictEqual(2, thread.sliceGroup.length);
+
+ mainSlice = thread.sliceGroup.slices[0];
+ assert.strictEqual(mainSlice.inFlowEvents.length, 1);
+ assert.strictEqual(mainSlice.outFlowEvents.length, 1);
+ internalSlice = thread.sliceGroup.slices[1];
+ assert.strictEqual(internalSlice.outFlowEvents.length, 1);
+
+ assert.strictEqual(mainSlice.title, 'binder reply');
+ assert.strictEqual(mainSlice.args['Destination Process'], 10670);
+ assert.strictEqual(mainSlice.args['Destination Thread'], 10670);
+ assert.strictEqual(mainSlice.args['Reply transaction?'], true);
+ assert.strictEqual(mainSlice.args['Calling PID'], 10645);
+ assert.strictEqual(mainSlice.args['Calling tgid'], 10622);
+
+ /* check last binderLibTest with recursive slices */
+ thread = threads[3];
+ assert.strictEqual(thread.parent.pid, 10670);
+ assert.strictEqual(thread.tid, 10670);
+ assert.strictEqual(thread.name, 'binderLibTest');
+ assert.strictEqual(6, thread.sliceGroup.length);
+
+ mainSlice = thread.sliceGroup.slices[0];
+ assert.strictEqual(mainSlice.inFlowEvents.length, 1);
+ assert.strictEqual(mainSlice.outFlowEvents.length, 1);
+ internalSlice = thread.sliceGroup.slices[5];
+ assert.strictEqual(internalSlice.outFlowEvents.length, 1);
+
+ assert.strictEqual(mainSlice.title, 'binder reply');
+ assert.strictEqual(mainSlice.args['Destination Process'], 10619);
+ assert.strictEqual(mainSlice.args['Destination Thread'], 10619);
+ assert.strictEqual(mainSlice.args['Reply transaction?'], true);
+ assert.strictEqual(mainSlice.args['Calling PID'], 10670);
+ assert.strictEqual(mainSlice.args['Calling tgid'], 10670);
+
+ let recursive = thread.sliceGroup.slices[1];
+ let recursiveInternal = thread.sliceGroup.slices[2];
+ assert.strictEqual(recursive.inFlowEvents.length, 1);
+ assert.strictEqual(recursive.outFlowEvents.length, 1);
+ assert.strictEqual(recursiveInternal.inFlowEvents.length, 1);
+
+ assert.strictEqual(recursive.title, 'binder transaction');
+ assert.strictEqual(recursive.args['Destination Process'], 3454);
+ assert.strictEqual(recursive.args['Reply transaction?'], false);
+ assert.strictEqual(recursive.args['Calling PID'], 10670);
+ assert.strictEqual(recursive.args['Calling tgid'], 10670);
+
+ /* check second recursive slice and internal */
+
+ recursive = thread.sliceGroup.slices[3];
+ recursiveInternal = thread.sliceGroup.slices[4];
+ assert.strictEqual(recursive.inFlowEvents.length, 1);
+ assert.strictEqual(recursive.outFlowEvents.length, 1);
+ assert.strictEqual(recursiveInternal.inFlowEvents.length, 1);
+
+ assert.strictEqual(recursive.title, 'binder transaction');
+ assert.strictEqual(recursive.args['Destination Process'], 10622);
+ assert.strictEqual(recursive.args['Reply transaction?'], false);
+ assert.strictEqual(recursive.args['Calling PID'], 10670);
+ assert.strictEqual(recursive.args['Calling tgid'], 10670);
+ });
+
+ test('binderSimpleAsync', function() {
+ const lines = [
+ '/system/bin/surfaceflinger-3462 ( 3462) [000] ...1 108286.109437:' +
+ ' binder_transaction: transaction=923419 dest_node=175950' +
+ ' dest_proc=4044 dest_thread=0 reply=0 flags=0x11 code=0x1',
+ 'Binder_5-12869 ( 4044) [000] ...1 108286.109835:' +
+ ' binder_transaction_received: transaction=923419'
+ ];
+
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shfitWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads(0);
+ assert.strictEqual(threads.length, 2);
+
+ let thread = threads[0];
+ assert.strictEqual(thread.tid, 3462);
+ assert.strictEqual(thread.name, '/system/bin/surfaceflinger');
+ assert.strictEqual(thread.sliceGroup.length, 1);
+
+ let slice = thread.sliceGroup.slices[0];
+ assert.strictEqual(slice.outFlowEvents.length, 1);
+ assert.strictEqual(slice.inFlowEvents.length, 0);
+ assert.strictEqual(slice.title, 'binder transaction async');
+
+ thread = threads[1];
+ assert.strictEqual(thread.tid, 12869);
+ assert.strictEqual(thread.name, 'Binder_5');
+ assert.strictEqual(thread.sliceGroup.length, 1);
+
+ slice = thread.sliceGroup.slices[0];
+ assert.strictEqual(slice.inFlowEvents.length, 1);
+ assert.strictEqual(slice.outFlowEvents.length, 0);
+ assert.strictEqual(slice.title, 'binder Async recv');
+ });
+
+ test('binderAllocBuf', function() {
+ const lines = [
+ 'binderLibTest-10619 (10619) [001] ...1 25191.335749: ' +
+ 'binder_transaction: transaction=489053 dest_node=489048 ' +
+ 'dest_proc=10670 dest_thread=0 reply=0 flags=0x10 code=0xd',
+ 'binderLibTest-10619 (10619) [001] ...1 25191.335750: ' +
+ 'binder_transaction_alloc_buf: transaction=489053 ' +
+ 'data_size=1001 offsets_size=1002',
+ 'binderLibTest-10670 (10620) [000] ...1 25191.335751: ' +
+ 'binder_transaction_received: transaction=489053',
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shfitWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+ const threads = m.getAllThreads(0);
+ assert.strictEqual(threads.length, 1);
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.length, 1);
+ const slice = thread.sliceGroup.slices[0];
+ assert.strictEqual(slice.args['Data Size'], 1001);
+ assert.strictEqual(slice.args['Offsets Size'], 1002);
+ });
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser.html
new file mode 100644
index 00000000000..501fa83aea0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses trace_marker events that were inserted in the trace by
+ * userland.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux trace mark events that were inserted in the trace by userland.
+ * @constructor
+ */
+ function BusParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('memory_bus_usage',
+ BusParser.prototype.traceMarkWriteBusEvent.bind(this));
+
+ this.model_ = importer.model_;
+ this.ppids_ = {};
+ }
+
+ BusParser.prototype = {
+ __proto__: Parser.prototype,
+
+ traceMarkWriteBusEvent(eventName, cpuNumber, pid, ts,
+ eventBase, threadName) {
+ const re = new RegExp('bus=(\\S+) rw_bytes=(\\d+) r_bytes=(\\d+) ' +
+ 'w_bytes=(\\d+) cycles=(\\d+) ns=(\\d+)');
+ const event = re.exec(eventBase.details);
+
+ const name = event[1];
+ const rwBytes = parseInt(event[2]);
+ const rBytes = parseInt(event[3]);
+ const wBytes = parseInt(event[4]);
+ const cycles = parseInt(event[5]);
+ const ns = parseInt(event[6]);
+
+ // BW in MiB/s.
+ const sec = tr.b.convertUnit(ns, tr.b.UnitPrefixScale.METRIC.NANO,
+ tr.b.UnitPrefixScale.METRIC.NONE);
+ const readBandwidthInBps = rBytes / sec;
+ const readBandwidthInMiBps = tr.b.convertUnit(readBandwidthInBps,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI);
+ const writeBandwidthInBps = wBytes / sec;
+ const writeBandwidthInMiBps = tr.b.convertUnit(writeBandwidthInBps,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI);
+
+ let ctr = this.model_.kernel
+ .getOrCreateCounter(null, 'bus ' + name + ' read');
+ if (ctr.numSeries === 0) {
+ ctr.addSeries(new tr.model.CounterSeries('value',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ ctr.name + '.' + 'value')));
+ }
+ ctr.series.forEach(function(series) {
+ series.addCounterSample(ts, readBandwidthInMiBps);
+ });
+
+ ctr = this.model_.kernel
+ .getOrCreateCounter(null, 'bus ' + name + ' write');
+ if (ctr.numSeries === 0) {
+ ctr.addSeries(new tr.model.CounterSeries('value',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ ctr.name + '.' + 'value')));
+ }
+ ctr.series.forEach(function(series) {
+ series.addCounterSample(ts, writeBandwidthInMiBps);
+ });
+
+ return true;
+ }
+ };
+
+ Parser.register(BusParser);
+
+ return {
+ BusParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser_test.html
new file mode 100644
index 00000000000..d2bfa35b1a5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/bus_parser_test.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('exynos5Bus', function() {
+ const lines = [
+ 's3c-fb-vsync-85 [001] d..2 8116.730115: memory_bus_usage: ' +
+ 'bus=RIGHT rw_bytes=0 r_bytes=0 w_bytes=0 cycles=2681746 ns=16760792',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.730118: memory_bus_usage: ' +
+ 'bus=CPU rw_bytes=2756608 r_bytes=2267328 w_bytes=491328 ' +
+ 'cycles=6705198 ns=16763375',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.746788: memory_bus_usage: ' +
+ 'bus=DDR_C rw_bytes=2736128 r_bytes=2260864 w_bytes=479248 ' +
+ 'cycles=6670677 ns=16676375',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.746790: memory_bus_usage: ' +
+ 'bus=DDR_R1 rw_bytes=31457280 r_bytes=31460912 w_bytes=0 ' +
+ 'cycles=6670521 ns=16676500',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.746792: memory_bus_usage: ' +
+ 'bus=DDR_L rw_bytes=16953344 r_bytes=16731088 w_bytes=223664 ' +
+ 'cycles=6669885 ns=16674833',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.746793: memory_bus_usage: ' +
+ 'bus=RIGHT rw_bytes=0 r_bytes=0 w_bytes=0 cycles=2667378 ns=16671250',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.746798: memory_bus_usage: ' +
+ 'bus=CPU rw_bytes=2797568 r_bytes=2309424 w_bytes=491968 ' +
+ 'cycles=6672156 ns=16680458',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.763521: memory_bus_usage: ' +
+ 'bus=DDR_C rw_bytes=2408448 r_bytes=1968448 w_bytes=441456 ' +
+ 'cycles=6689562 ns=16723458',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.763523: memory_bus_usage: ' +
+ 'bus=DDR_R1 rw_bytes=31490048 r_bytes=31493360 w_bytes=0 ' +
+ 'cycles=6690012 ns=16725083',
+
+ 's3c-fb-vsync-85 [001] d..2 8116.763525: memory_bus_usage: ' +
+ 'bus=DDR_L rw_bytes=16941056 r_bytes=16719136 w_bytes=223472 ' +
+ 'cycles=6690156 ns=16725375'
+
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ const counters = m.getAllCounters();
+ assert.strictEqual(counters.length, 10);
+
+ assert.strictEqual(counters[0].series[0].samples.length, 2);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser.html
new file mode 100644
index 00000000000..eb290cccd96
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses trace_marker events that were inserted in the trace by
+ * userland.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux trace mark events that were inserted in the trace by userland.
+ * @constructor
+ */
+ function ClockParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('clock_set_rate',
+ ClockParser.prototype.traceMarkWriteClockEvent.bind(this));
+ importer.registerEventHandler('clk_set_rate',
+ ClockParser.prototype.traceMarkWriteClkEvent.bind(this));
+ importer.registerEventHandler('clock_enable',
+ ClockParser.prototype.traceMarkWriteClockOnOffEvent.bind(this));
+ importer.registerEventHandler('clock_disable',
+ ClockParser.prototype.traceMarkWriteClockOnOffEvent.bind(this));
+ importer.registerEventHandler('clk_enable',
+ ClockParser.prototype.traceMarkWriteClkOnEvent.bind(this));
+ importer.registerEventHandler('clk_disable',
+ ClockParser.prototype.traceMarkWriteClkOffEvent.bind(this));
+ this.model_ = importer.model_;
+ this.ppids_ = {};
+ }
+
+ ClockParser.prototype = {
+ __proto__: Parser.prototype,
+
+ clockMark(name, subName, value, ts) {
+ const ctr = this.model_.kernel
+ .getOrCreateCounter(null, name + ' ' + subName);
+ // Initialize the counter's series fields if needed.
+ if (ctr.numSeries === 0) {
+ ctr.addSeries(new tr.model.CounterSeries('value',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ ctr.name + '.' + 'value')));
+ }
+ ctr.series.forEach(function(series) {
+ series.addCounterSample(ts, value);
+ });
+ },
+
+ traceMarkWriteClockEvent(eventName, cpuNumber, pid, ts,
+ eventBase, threadName) {
+ const event = /(\S+) state=(\d+)/.exec(eventBase.details);
+ const name = event[1];
+ const rate = parseInt(event[2]);
+ this.clockMark(name, 'Frequency', rate, ts);
+ return true;
+ },
+
+ traceMarkWriteClkEvent(eventName, cpuNumber, pid, ts,
+ eventBase, threadName) {
+ const event = /(\S+) (\d+)/.exec(eventBase.details);
+ const name = event[1];
+ const rate = parseInt(event[2]);
+ this.clockMark(name, 'Frequency', rate, ts);
+ return true;
+ },
+
+ traceMarkWriteClockOnOffEvent(eventName, cpuNumber, pid, ts,
+ eventBase, threadName) {
+ const event = /(\S+) state=(\d+)/.exec(eventBase.details);
+ const name = event[1];
+ const state = parseInt(event[2]);
+ this.clockMark(name, 'State', state, ts);
+ return true;
+ },
+
+ traceMarkWriteClkOnEvent(eventName, cpuNumber, pid, ts,
+ eventBase, threadName) {
+ const event = /\S+/.exec(eventBase.details);
+ const name = event[0];
+ this.clockMark(name, 'State', 1, ts);
+ return true;
+ },
+
+ traceMarkWriteClkOffEvent(eventName, cpuNumber, pid, ts,
+ eventBase, threadName) {
+ const event = /\S+/.exec(eventBase.details);
+ const name = event[0];
+ this.clockMark(name, 'State', 0, ts);
+ return true;
+ }
+ };
+
+ Parser.register(ClockParser);
+
+ return {
+ ClockParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser_test.html
new file mode 100644
index 00000000000..3ce688c796b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/clock_parser_test.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('clock', function() {
+ const lines = [
+ 'cfinteractive-23 [000] d..2 8113.233768: clock_set_rate: ' +
+ 'fout_apll state=500000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.249509: clock_set_rate: ' +
+ 'fout_apll state=300000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.289796: clock_set_rate: ' +
+ 'fout_apll state=400000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.294568: clock_set_rate: ' +
+ 'fout_apll state=500000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.309509: clock_set_rate: ' +
+ 'fout_apll state=800000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.388732: clock_set_rate: ' +
+ 'fout_apll state=200000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.410182: clock_set_rate: ' +
+ 'fout_apll state=300000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.414872: clock_set_rate: ' +
+ 'fout_apll state=600000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.494455: clock_set_rate: ' +
+ 'fout_apll state=200000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.515254: clock_set_rate: ' +
+ 'fout_apll state=500000000 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.694455: clk_set_rate: ' +
+ 'fout_apll 200000000',
+
+ 'cfinteractive-23 [000] d..2 8113.715254: clk_set_rate: ' +
+ 'fout_apll 500000000'
+ ];
+
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ const counters = m.getAllCounters();
+ assert.strictEqual(counters.length, 1);
+
+ assert.strictEqual(counters[0].series[0].samples.length, 12);
+ });
+
+ test('clock state', function() {
+ const lines = [
+ 'cfinteractive-23 [000] d..2 8113.233768: clock_enable: ' +
+ 'fout_apll state=1 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.249509: clock_disable: ' +
+ 'fout_apll state=0 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.289796: clock_enable: ' +
+ 'fout_apll state=1 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.294568: clock_disable: ' +
+ 'fout_apll state=0 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.309509: clock_enable: ' +
+ 'fout_apll state=1 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.388732: clock_disable: ' +
+ 'fout_apll state=0 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.410182: clock_enable: ' +
+ 'fout_apll state=1 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.414872: clock_disable: ' +
+ 'fout_apll state=0 cpu_id=0',
+
+ 'cfinteractive-23 [000] d..2 8113.694455: clk_enable: ' +
+ 'fout_apll',
+
+ 'cfinteractive-23 [000] d..2 8113.715254: clk_disable: ' +
+ 'fout_apll'
+ ];
+
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ const counters = m.getAllCounters();
+ assert.strictEqual(counters.length, 1);
+
+ assert.strictEqual(counters[0].series[0].samples.length, 10);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser.html
new file mode 100644
index 00000000000..da112cb0e31
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses cpufreq events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux cpufreq trace events.
+ * @constructor
+ */
+ function CpufreqParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('cpufreq_interactive_up',
+ CpufreqParser.prototype.cpufreqUpDownEvent.bind(this));
+ importer.registerEventHandler('cpufreq_interactive_down',
+ CpufreqParser.prototype.cpufreqUpDownEvent.bind(this));
+ importer.registerEventHandler('cpufreq_interactive_already',
+ CpufreqParser.prototype.cpufreqTargetEvent.bind(this));
+ importer.registerEventHandler('cpufreq_interactive_notyet',
+ CpufreqParser.prototype.cpufreqTargetEvent.bind(this));
+ importer.registerEventHandler('cpufreq_interactive_setspeed',
+ CpufreqParser.prototype.cpufreqTargetEvent.bind(this));
+ importer.registerEventHandler('cpufreq_interactive_target',
+ CpufreqParser.prototype.cpufreqTargetEvent.bind(this));
+ importer.registerEventHandler('cpufreq_interactive_boost',
+ CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this));
+ importer.registerEventHandler('cpufreq_interactive_unboost',
+ CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this));
+ }
+
+ function splitData(input) {
+ // TODO(sleffler) split by cpu
+ const data = {};
+ const args = input.split(/\s+/);
+ const len = args.length;
+ for (let i = 0; i < len; i++) {
+ const item = args[i].split('=');
+ data[item[0]] = parseInt(item[1]);
+ }
+ return data;
+ }
+
+ CpufreqParser.prototype = {
+ __proto__: Parser.prototype,
+
+ cpufreqSlice(ts, eventName, cpu, args) {
+ // TODO(sleffler) should be per-cpu
+ const kthread = this.importer.getOrCreatePseudoThread('cpufreq');
+ kthread.openSlice = eventName;
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ ts, args, 0);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ },
+
+ cpufreqBoostSlice(ts, eventName, args) {
+ const kthread = this.importer.getOrCreatePseudoThread('cpufreq_boost');
+ kthread.openSlice = eventName;
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ ts, args, 0);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ },
+
+ /**
+ * Parses cpufreq events and sets up state in the importer.
+ */
+ cpufreqUpDownEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const data = splitData(eventBase.details);
+ this.cpufreqSlice(ts, eventName, data.cpu, data);
+ return true;
+ },
+
+ cpufreqTargetEvent(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ const data = splitData(eventBase.details);
+ this.cpufreqSlice(ts, eventName, data.cpu, data);
+ return true;
+ },
+
+ cpufreqBoostUnboostEvent(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ this.cpufreqBoostSlice(ts, eventName,
+ {
+ type: eventBase.details
+ });
+ return true;
+ }
+ };
+
+ Parser.register(CpufreqParser);
+
+ return {
+ CpufreqParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser_test.html
new file mode 100644
index 00000000000..9c324a8346d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/cpufreq_parser_test.html
@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('cpuFreqTargetImport', function() {
+ const lines = [
+ '<idle>-0 [000] ..s3 1043.718825: cpufreq_interactive_target: ' +
+ 'cpu=0 load=2 cur=2000000 targ=300000\n',
+ '<idle>-0 [000] ..s3 1043.718825: cpufreq_interactive_target: ' +
+ 'cpu=0 load=12 cur=1000000 actual=1000000 targ=200000\n'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cpu, 0);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.load, 2);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cur, 2000000);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.targ, 300000);
+
+ assert.strictEqual(thread.sliceGroup.slices[1].args.cpu, 0);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.load, 12);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.cur, 1000000);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.actual, 1000000);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.targ, 200000);
+ });
+
+ test('cpuFreqNotYetImport', function() {
+ const lines = [
+ '<idle>-0 [001] ..s3 1043.718832: cpufreq_interactive_notyet: ' +
+ 'cpu=1 load=10 cur=700000 targ=200000\n',
+ '<idle>-0 [001] ..s3 1043.718832: cpufreq_interactive_notyet: ' +
+ 'cpu=1 load=10 cur=700000 actual=1000000 targ=200000\n'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cpu, 1);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.load, 10);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cur, 700000);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.targ, 200000);
+
+ assert.strictEqual(thread.sliceGroup.slices[1].args.cpu, 1);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.load, 10);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.cur, 700000);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.actual, 1000000);
+ assert.strictEqual(thread.sliceGroup.slices[1].args.targ, 200000);
+ });
+
+ test('cpuFreqSetSpeedImport', function() {
+ const lines = [
+ 'cfinteractive-23 [001] ...1 1043.719688: ' +
+ 'cpufreq_interactive_setspeed: cpu=0 targ=200000 actual=700000\n'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cpu, 0);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.targ, 200000);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.actual, 700000);
+ });
+
+ test('cpuFreqAlreadyImport', function() {
+ const lines = [
+ '<idle>-0 [000] ..s3 1043.738822: cpufreq_interactive_already: cpu=0 load=18 cur=200000 actual=700000 targ=200000\n' // @suppress longLineCheck
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cpu, 0);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.load, 18);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cur, 200000);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.actual, 700000);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.targ, 200000);
+ });
+
+ test('cpuFreqBoostImport', function() {
+ const lines = [
+ 'InputDispatcher-465 [001] ...1 1044.213948: ' +
+ 'cpufreq_interactive_boost: pulse\n'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.slices[0].args.type, 'pulse');
+ });
+
+ test('cpuFreqUnBoostImport', function() {
+ const lines = [
+ 'InputDispatcher-465 [001] ...1 1044.213948: ' +
+ 'cpufreq_interactive_unboost: pulse\n'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.slices[0].args.type, 'pulse');
+ });
+
+ test('cpuFreqUpImport', function() {
+ const lines = [
+ 'kinteractive-69 [003] .... 414324.164432: ' +
+ 'cpufreq_interactive_up: cpu=1 targ=1400000 actual=800000'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cpu, 1);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.targ, 1400000);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.actual, 800000);
+ });
+
+ test('cpuFreqDownImport', function() {
+ const lines = [
+ 'kinteractive-69 [003] .... 414365.834193: ' +
+ 'cpufreq_interactive_down: cpu=3 targ=800000 actual=1000000'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+ assert.strictEqual(thread.sliceGroup.slices[0].args.cpu, 3);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.targ, 800000);
+ assert.strictEqual(thread.sliceGroup.slices[0].args.actual, 1000000);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser.html
new file mode 100644
index 00000000000..e44e29eb8cf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser.html
@@ -0,0 +1,302 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses filesystem and block device events in the Linux event
+ * trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux filesystem and block device trace events.
+ * @constructor
+ */
+ function DiskParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('f2fs_write_begin',
+ DiskParser.prototype.f2fsWriteBeginEvent.bind(this));
+ importer.registerEventHandler('f2fs_write_end',
+ DiskParser.prototype.f2fsWriteEndEvent.bind(this));
+ importer.registerEventHandler('f2fs_sync_file_enter',
+ DiskParser.prototype.f2fsSyncFileEnterEvent.bind(this));
+ importer.registerEventHandler('f2fs_sync_file_exit',
+ DiskParser.prototype.f2fsSyncFileExitEvent.bind(this));
+ importer.registerEventHandler('ext4_sync_file_enter',
+ DiskParser.prototype.ext4SyncFileEnterEvent.bind(this));
+ importer.registerEventHandler('ext4_sync_file_exit',
+ DiskParser.prototype.ext4SyncFileExitEvent.bind(this));
+ importer.registerEventHandler('ext4_da_write_begin',
+ DiskParser.prototype.ext4WriteBeginEvent.bind(this));
+ importer.registerEventHandler('ext4_da_write_end',
+ DiskParser.prototype.ext4WriteEndEvent.bind(this));
+ importer.registerEventHandler('block_rq_issue',
+ DiskParser.prototype.blockRqIssueEvent.bind(this));
+ importer.registerEventHandler('block_rq_complete',
+ DiskParser.prototype.blockRqCompleteEvent.bind(this));
+ }
+
+ DiskParser.prototype = {
+ __proto__: Parser.prototype,
+
+ openAsyncSlice(ts, category, threadName, pid, key, name) {
+ const kthread = this.importer.getOrCreateKernelThread(
+ category + ':' + threadName, pid);
+ const asyncSliceConstructor =
+ tr.model.AsyncSlice.subTypes.getConstructor(
+ category, name);
+ const slice = new asyncSliceConstructor(
+ category, name,
+ ColorScheme.getColorIdForGeneralPurposeString(name),
+ ts);
+ slice.startThread = kthread.thread;
+
+ if (!kthread.openAsyncSlices) {
+ kthread.openAsyncSlices = { };
+ }
+ kthread.openAsyncSlices[key] = slice;
+ },
+
+ closeAsyncSlice(ts, category, threadName, pid, key, args) {
+ const kthread = this.importer.getOrCreateKernelThread(
+ category + ':' + threadName, pid);
+ if (kthread.openAsyncSlices) {
+ const slice = kthread.openAsyncSlices[key];
+ if (slice) {
+ slice.duration = ts - slice.start;
+ slice.args = args;
+ slice.endThread = kthread.thread;
+ slice.subSlices = [
+ new tr.model.AsyncSlice(category, slice.title,
+ slice.colorId, slice.start, slice.args, slice.duration)
+ ];
+ kthread.thread.asyncSliceGroup.push(slice);
+ delete kthread.openAsyncSlices[key];
+ }
+ }
+ },
+
+ /**
+ * Parses events and sets up state in the importer.
+ */
+ f2fsWriteBeginEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev = \((\d+,\d+)\), ino = (\d+), pos = (\d+), len = (\d+), flags = (\d+)/. // @suppress longLineCheck
+ exec(eventBase.details);
+ if (!event) return false;
+ const device = event[1];
+ const inode = parseInt(event[2]);
+ const pos = parseInt(event[3]);
+ const len = parseInt(event[4]);
+ const key = device + '-' + inode + '-' + pos + '-' + len;
+ this.openAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
+ key, 'f2fs_write');
+ return true;
+ },
+
+ f2fsWriteEndEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev = \((\d+,\d+)\), ino = (\d+), pos = (\d+), len = (\d+), copied = (\d+)/. // @suppress longLineCheck
+ exec(eventBase.details);
+ if (!event) return false;
+
+ const device = event[1];
+ const inode = parseInt(event[2]);
+ const pos = parseInt(event[3]);
+ const len = parseInt(event[4]);
+ const error = parseInt(event[5]) !== len;
+ const key = device + '-' + inode + '-' + pos + '-' + len;
+ this.closeAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
+ key, {
+ device,
+ inode,
+ error
+ });
+ return true;
+ },
+
+ ext4WriteBeginEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) flags (\d+)/.
+ exec(eventBase.details);
+ if (!event) return false;
+ const device = event[1];
+ const inode = parseInt(event[2]);
+ const pos = parseInt(event[3]);
+ const len = parseInt(event[4]);
+ const key = device + '-' + inode + '-' + pos + '-' + len;
+ this.openAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
+ key, 'ext4_write');
+ return true;
+ },
+
+ ext4WriteEndEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) copied (\d+)/.
+ exec(eventBase.details);
+ if (!event) return false;
+
+ const device = event[1];
+ const inode = parseInt(event[2]);
+ const pos = parseInt(event[3]);
+ const len = parseInt(event[4]);
+ const error = parseInt(event[5]) !== len;
+ const key = device + '-' + inode + '-' + pos + '-' + len;
+ this.closeAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
+ key, {
+ device,
+ inode,
+ error
+ });
+ return true;
+ },
+
+ f2fsSyncFileEnterEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = new RegExp(
+ 'dev = \\((\\d+,\\d+)\\), ino = (\\d+), pino = (\\d+), i_mode = (\\S+), ' + // @suppress longLineCheck
+ 'i_size = (\\d+), i_nlink = (\\d+), i_blocks = (\\d+), i_advise = (\\d+)'). // @suppress longLineCheck
+ exec(eventBase.details);
+ if (!event) return false;
+
+ const device = event[1];
+ const inode = parseInt(event[2]);
+ const key = device + '-' + inode;
+ this.openAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
+ key, 'fsync');
+ return true;
+ },
+
+ f2fsSyncFileExitEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = new RegExp('dev = \\((\\d+,\\d+)\\), ino = (\\d+), checkpoint is (\\S+), ' + // @suppress longLineCheck
+ 'datasync = (\\d+), ret = (\\d+)').
+ exec(eventBase.details.replace('not needed', 'not_needed'));
+ if (!event) return false;
+
+ const device = event[1];
+ const inode = parseInt(event[2]);
+ const error = parseInt(event[5]);
+ const key = device + '-' + inode;
+ this.closeAsyncSlice(ts, 'f2fs', eventBase.threadName, eventBase.pid,
+ key, {
+ device,
+ inode,
+ error
+ });
+ return true;
+ },
+
+ ext4SyncFileEnterEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev (\d+,\d+) ino (\d+) parent (\d+) datasync (\d+)/.
+ exec(eventBase.details);
+ if (!event) return false;
+
+ const device = event[1];
+ const inode = parseInt(event[2]);
+ const datasync = (event[4] === '1') || (event[4] === 1);
+ const key = device + '-' + inode;
+ const action = datasync ? 'fdatasync' : 'fsync';
+ this.openAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
+ key, action);
+ return true;
+ },
+
+ ext4SyncFileExitEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev (\d+,\d+) ino (\d+) ret (\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const device = event[1];
+ const inode = parseInt(event[2]);
+ const error = parseInt(event[3]);
+ const key = device + '-' + inode;
+ this.closeAsyncSlice(ts, 'ext4', eventBase.threadName, eventBase.pid,
+ key, {
+ device,
+ inode,
+ error
+ });
+ return true;
+ },
+
+ blockRqIssueEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
+ '\\d+ \\(.*\\) (\\d+) \\+ (\\d+) \\[.*\\]').exec(eventBase.details);
+ if (!event) return false;
+
+ let action;
+ switch (event[3]) {
+ case 'D':
+ action = 'discard';
+ break;
+ case 'W':
+ action = 'write';
+ break;
+ case 'R':
+ action = 'read';
+ break;
+ case 'N':
+ action = 'none';
+ break;
+ default:
+ action = 'unknown';
+ break;
+ }
+
+ if (event[2]) {
+ action += ' flush';
+ }
+ if (event[4] === 'F') {
+ action += ' fua';
+ }
+ if (event[5] === 'A') {
+ action += ' ahead';
+ }
+ if (event[6] === 'S') {
+ action += ' sync';
+ }
+ if (event[7] === 'M') {
+ action += ' meta';
+ }
+ const device = event[1];
+ const sector = parseInt(event[8]);
+ const numSectors = parseInt(event[9]);
+ const key = device + '-' + sector + '-' + numSectors;
+ this.openAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
+ key, action);
+ return true;
+ },
+
+ blockRqCompleteEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? ' +
+ '\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);
+ if (!event) return false;
+
+ const device = event[1];
+ const sector = parseInt(event[8]);
+ const numSectors = parseInt(event[9]);
+ const error = parseInt(event[10]);
+ const key = device + '-' + sector + '-' + numSectors;
+ this.closeAsyncSlice(ts, 'block', eventBase.threadName, eventBase.pid,
+ key, {
+ device,
+ sector,
+ numSectors,
+ error
+ });
+ return true;
+ }
+ };
+
+ Parser.register(DiskParser);
+
+ return {
+ DiskParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser_test.html
new file mode 100644
index 00000000000..ac1795a7140
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/disk_parser_test.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('diskImport', function() {
+ const lines = [
+ // NB: spliced from different traces; mismatched timestamps don't matter
+ 'AsyncTask #2-18830 [000] ...1 154578.668286: ext4_sync_file_enter: ' +
+ 'dev 259,1 ino 81993 parent 81906 datasync 1',
+ 'Binder_A-3179 [001] ...1 1354.510088: f2fs_sync_file_enter: ' +
+ 'dev = (259,14), ino = 4882, pino = 313, i_mode = 0x81b0, i_size = ' +
+ '25136, i_nlink = 1, i_blocks = 8, i_advise = 0x0',
+ 'Binder_A-3179 [001] ...1 1354.514013: f2fs_sync_file_exit: ' +
+ 'dev = (259,14), ino = 4882, checkpoint is not needed, datasync = 1, ret = 0', // @suppress longLineCheck
+ 'mmcqd/0-81 [000] d..2 154578.668390: block_rq_issue: ' +
+ '179,0 WS 0 () 3427120 + 16 [mmcqd/0]',
+ 'mmcqd/0-81 [000] d..2 154578.669181: block_rq_complete: ' +
+ '179,0 WS () 3427120 + 16 [0]',
+ 'mmcqd/0-81 [001] d..2 154578.670853: block_rq_issue: ' +
+ '179,0 FWS 0 () 18446744073709551615 + 0 [mmcqd/0]',
+ 'mmcqd/0-81 [001] d..2 154578.670869: block_rq_complete: ' +
+ '179,0 FWS () 18446744073709551615 + 0 [0]',
+ 'AsyncTask #2-18830 [001] ...1 154578.670901: ext4_sync_file_exit: ' +
+ 'dev 259,1 ino 81993 ret 0',
+ 'mmcqd/0-81 [001] d..2 154578.877038: block_rq_issue: ' +
+ '179,0 R 0 () 3255256 + 8 [mmcqd/0]',
+ 'mmcqd/0-81 [001] d..2 154578.877110: block_rq_issue: ' +
+ '179,0 R 0 () 3255288 + 8 [mmcqd/0]',
+ 'mmcqd/0-81 [000] d..2 154578.877345: block_rq_complete: ' +
+ '179,0 R () 3255256 + 8 [0]',
+ 'mmcqd/0-81 [000] d..2 154578.877466: block_rq_complete: ' +
+ '179,0 R () 3255288 + 8 [0]',
+ 'ContactsProvide-1184 [000] ...1 66.613719: f2fs_write_begin: ' +
+ 'dev = (253,2), ino = 3342, pos = 0, len = 75, flags = 0',
+ 'ContactsProvide-1184 [000] ...1 66.613733: f2fs_write_end: ' +
+ 'dev = (253,2), ino = 3342, pos = 0, len = 75, copied = 75'
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ let blockThread = undefined;
+ let ext4Thread = undefined;
+ let f2fsSyncThread = undefined;
+ let f2fsWriteThread = undefined;
+
+ m.getAllThreads().forEach(function(t) {
+ switch (t.name) {
+ case 'block:mmcqd/0':
+ blockThread = t;
+ break;
+ case 'ext4:AsyncTask #2':
+ ext4Thread = t;
+ break;
+ case 'f2fs:Binder_A':
+ f2fsSyncThread = t;
+ break;
+ case 'f2fs:ContactsProvide':
+ f2fsWriteThread = t;
+ break;
+ default:
+ assert.fail(t, undefined, 'Unexpected thread named ' + t.name);
+ }
+ });
+ assert.isDefined(blockThread);
+ assert.isDefined(ext4Thread);
+ assert.isDefined(f2fsSyncThread);
+ assert.isDefined(f2fsWriteThread);
+
+ assert.strictEqual(blockThread.asyncSliceGroup.length, 4);
+
+ let slice = blockThread.asyncSliceGroup.slices[0];
+ assert.strictEqual(slice.category, 'block');
+ assert.strictEqual(slice.title, 'write sync');
+ assert.strictEqual(slice.args.device, '179,0');
+ assert.strictEqual(slice.args.error, 0);
+ assert.strictEqual(slice.args.numSectors, 16);
+ assert.strictEqual(slice.args.sector, 3427120);
+
+ assert.strictEqual(ext4Thread.asyncSliceGroup.length, 1);
+
+ slice = ext4Thread.asyncSliceGroup.slices[0];
+ assert.strictEqual(slice.category, 'ext4');
+ assert.strictEqual(slice.title, 'fdatasync');
+ assert.strictEqual(slice.args.device, '259,1');
+ assert.strictEqual(slice.args.error, 0);
+ assert.strictEqual(slice.args.inode, 81993);
+
+ assert.strictEqual(f2fsSyncThread.asyncSliceGroup.length, 1);
+
+ slice = f2fsSyncThread.asyncSliceGroup.slices[0];
+ assert.strictEqual(slice.category, 'f2fs');
+ assert.strictEqual(slice.title, 'fsync');
+ assert.strictEqual(slice.args.device, '259,14');
+ assert.strictEqual(slice.args.error, 0);
+ assert.strictEqual(slice.args.inode, 4882);
+
+ assert.strictEqual(f2fsWriteThread.asyncSliceGroup.length, 1);
+
+ slice = f2fsWriteThread.asyncSliceGroup.slices[0];
+ assert.strictEqual(slice.category, 'f2fs');
+ assert.strictEqual(slice.title, 'f2fs_write');
+ assert.strictEqual(slice.args.device, '253,2');
+ assert.strictEqual(slice.args.inode, 3342);
+ assert.strictEqual(slice.args.error, false);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser.html
new file mode 100644
index 00000000000..a7f02f23e93
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses drm driver events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux drm trace events.
+ * @constructor
+ */
+ function DrmParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('drm_vblank_event',
+ DrmParser.prototype.vblankEvent.bind(this));
+ }
+
+ DrmParser.prototype = {
+ __proto__: Parser.prototype,
+
+ drmVblankSlice(ts, eventName, args) {
+ const kthread = this.importer.getOrCreatePseudoThread('drm_vblank');
+ kthread.openSlice = eventName;
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ ts, args, 0);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ },
+
+ /**
+ * Parses drm driver events and sets up state in the importer.
+ */
+ vblankEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /crtc=(\d+), seq=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const crtc = parseInt(event[1]);
+ const seq = parseInt(event[2]);
+ this.drmVblankSlice(ts, 'vblank:' + crtc,
+ {
+ crtc,
+ seq
+ });
+ return true;
+ }
+ };
+
+ Parser.register(DrmParser);
+
+ return {
+ DrmParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser_test.html
new file mode 100644
index 00000000000..1369fa5ca9a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/drm_parser_test.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('drmImport', function() {
+ const lines = [
+ ' chrome-2465 [000] 71.653157: drm_vblank_event: crtc=0, seq=4233',
+ ' <idle>-0 [000] 71.669851: drm_vblank_event: crtc=0, seq=4234'
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const vblankThread = threads[0];
+ assert.strictEqual(vblankThread.name, 'drm_vblank');
+ assert.strictEqual(vblankThread.sliceGroup.length, 2);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser.html
new file mode 100644
index 00000000000..3f93d3bd6de
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses exynos events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux exynos trace events.
+ * @constructor
+ */
+ function ExynosParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('exynos_busfreq_target_int',
+ ExynosParser.prototype.busfreqTargetIntEvent.bind(this));
+ importer.registerEventHandler('exynos_busfreq_target_mif',
+ ExynosParser.prototype.busfreqTargetMifEvent.bind(this));
+
+ importer.registerEventHandler('exynos_page_flip_state',
+ ExynosParser.prototype.pageFlipStateEvent.bind(this));
+ }
+
+ ExynosParser.prototype = {
+ __proto__: Parser.prototype,
+
+ exynosBusfreqSample(name, ts, frequency) {
+ const targetCpu = this.importer.getOrCreateCpu(0);
+ const counter = targetCpu.getOrCreateCounter('', name);
+ if (counter.numSeries === 0) {
+ counter.addSeries(new tr.model.CounterSeries('frequency',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ counter.name + '.' + 'frequency')));
+ }
+ counter.series.forEach(function(series) {
+ series.addCounterSample(ts, frequency);
+ });
+ },
+
+ /**
+ * Parses exynos_busfreq_target_int events and sets up state.
+ */
+ busfreqTargetIntEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /frequency=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ this.exynosBusfreqSample('INT Frequency', ts, parseInt(event[1]));
+ return true;
+ },
+
+ /**
+ * Parses exynos_busfreq_target_mif events and sets up state.
+ */
+ busfreqTargetMifEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /frequency=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ this.exynosBusfreqSample('MIF Frequency', ts, parseInt(event[1]));
+ return true;
+ },
+
+ exynosPageFlipStateOpenSlice(ts, pipe, fb, state) {
+ const kthread = this.importer.getOrCreatePseudoThread(
+ 'exynos_flip_state (pipe:' + pipe + ', fb:' + fb + ')');
+ kthread.openSliceTS = ts;
+ kthread.openSlice = state;
+ },
+
+ exynosPageFlipStateCloseSlice(ts, pipe, fb, args) {
+ const kthread = this.importer.getOrCreatePseudoThread(
+ 'exynos_flip_state (pipe:' + pipe + ', fb:' + fb + ')');
+ if (kthread.openSlice) {
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ kthread.openSliceTS,
+ args,
+ ts - kthread.openSliceTS);
+ kthread.thread.sliceGroup.pushSlice(slice);
+ }
+ kthread.openSlice = undefined;
+ },
+
+ /**
+ * Parses page_flip_state events and sets up state in the importer.
+ */
+ pageFlipStateEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /pipe=(\d+), fb=(\d+), state=(.*)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const pipe = parseInt(event[1]);
+ const fb = parseInt(event[2]);
+ const state = event[3];
+
+ this.exynosPageFlipStateCloseSlice(ts, pipe, fb,
+ {
+ pipe,
+ fb
+ });
+ if (state !== 'flipped') {
+ this.exynosPageFlipStateOpenSlice(ts, pipe, fb, state);
+ }
+ return true;
+ }
+ };
+
+ Parser.register(ExynosParser);
+
+ return {
+ ExynosParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser_test.html
new file mode 100644
index 00000000000..74cd74a7b4c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/exynos_parser_test.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('exynosBusfreqImport', function() {
+ const lines = [
+ ' kworker/1:0-4177 [001] .... 2803.129806: ' +
+ 'exynos_busfreq_target_int: frequency=200000',
+ ' kworker/1:0-4177 [001] .... 2803.229207: ' +
+ 'exynos_busfreq_target_int: frequency=267000',
+ ' kworker/1:0-4177 [001] .... 2803.329031: ' +
+ 'exynos_busfreq_target_int: frequency=160000',
+ ' kworker/1:0-4177 [001] .... 2805.729039: ' +
+ 'exynos_busfreq_target_mif: frequency=200000'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c0 = m.kernel.cpus[0];
+ assert.strictEqual(c0.slices.length, 0);
+ assert.strictEqual(
+ c0.counters['.INT Frequency'].series[0].samples.length, 3);
+ assert.strictEqual(
+ c0.counters['.MIF Frequency'].series[0].samples.length, 1);
+ });
+
+ test('exynosPageFlipSlowRequestImport', function() {
+ const lines = [
+ ' <idle>-0 [000] d.h. 1000.000000: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=wait_kds',
+ ' Chrome_IOThread-21603 [000] d.h. 1000.000001: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=wait_apply',
+ ' kworker/0:1-25931 [000] .... 1000.000002: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=wait_flip',
+ ' kworker/0:1-25931 [000] .... 1000.000003: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=flipped',
+ ' <idle>-0 [000] d.h. 1000.000004: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=wait_kds',
+ ' Chrome_IOThread-21603 [000] d.h. 1000.000005: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=wait_apply',
+ ' kworker/0:1-25931 [000] .... 1000.000006: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=wait_flip',
+ ' kworker/0:1-25931 [000] .... 1000.000007: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=flipped'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ // there are 2 threads:
+ // (1) "exynos_flip_state (pipe:0, fb:25)"
+ // (2) "exynos_flip_state (pipe:0, fb:26)"
+ assert.strictEqual(threads.length, 2);
+
+ // in the test data, event of fb=26 occurs first, so it's thread[0]
+ const gfxFbId26Thread = threads[0]; // thread where fb === 26
+ const gfxFbId25Thread = threads[1]; // thread where fb === 25
+ assert.strictEqual(
+ gfxFbId25Thread.name, 'exynos_flip_state (pipe:0, fb:25)');
+ assert.strictEqual(
+ gfxFbId26Thread.name, 'exynos_flip_state (pipe:0, fb:26)');
+ // Every state (except for 'flipped') will start a new slice.
+ // The last event will not be closed, so it's not a slice
+ assert.strictEqual(gfxFbId25Thread.sliceGroup.length, 3);
+ assert.strictEqual(gfxFbId26Thread.sliceGroup.length, 3);
+ });
+
+ test('exynosPageFlipFastRequestImport', function() {
+ const lines = [
+ ' <idle>-0 [000] d.h. 1000.000000: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=wait_kds',
+ ' Chrome_IOThread-21603 [000] d.h. 1000.000001: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=wait_kds',
+ ' X-21385 [000] .... 1000.000002: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=wait_apply',
+ ' kworker/0:1-25931 [000] .... 1000.000003: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=wait_flip',
+ ' X-21385 [001] .... 1000.000004: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=wait_apply',
+ ' kworker/0:1-25931 [000] .... 1000.000005: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=flipped',
+ ' <idle>-0 [000] d.h. 1000.000006: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=wait_kds',
+ ' X-21385 [000] .... 1000.000007: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=wait_flip',
+ ' kworker/0:1-25931 [000] .... 1000.000008: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=flipped',
+ ' kworker/0:1-25931 [000] .... 1000.000009: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=wait_kds',
+ ' Chrome_IOThread-21603 [000] d.h. 1000.000010: ' +
+ 'exynos_page_flip_state: pipe=0, fb=25, state=wait_apply',
+ ' <idle>-0 [000] d.h. 1000.000011: ' +
+ 'exynos_page_flip_state: pipe=0, fb=26, state=wait_apply'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ // there are 2 threads:
+ // (1) "exynos_flip_state (pipe:0, fb:25)"
+ // (2) "exynos_flip_state (pipe:0, fb:26)"
+ assert.strictEqual(threads.length, 2);
+
+ // in the test data, event of fb=26 occurs first, so it's thread[0]
+ const gfxFbId26Thread = threads[0]; // thread where fb === 26
+ const gfxFbId25Thread = threads[1]; // thread where fb === 25
+ assert.strictEqual(
+ gfxFbId25Thread.name, 'exynos_flip_state (pipe:0, fb:25)');
+ assert.strictEqual(
+ gfxFbId26Thread.name, 'exynos_flip_state (pipe:0, fb:26)');
+ // Every state (except for 'flipped') will start a new slice.
+ // The last event will not be closed, so it's not a slice
+ assert.strictEqual(gfxFbId25Thread.sliceGroup.length, 4);
+ assert.strictEqual(gfxFbId26Thread.sliceGroup.length, 4);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/fence_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/fence_parser.html
new file mode 100644
index 00000000000..5745ff5e4a2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/fence_parser.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses fence events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux fence trace events.
+ * @constructor
+ */
+ function FenceParser(importer) {
+ Parser.call(this, importer);
+
+ this.model_ = importer.model_;
+ importer.registerEventHandler(
+ 'fence_init',
+ FenceParser.prototype.initEvent.bind(this));
+ importer.registerEventHandler(
+ 'fence_destroy',
+ FenceParser.prototype.fenceDestroyEvent.bind(this));
+ importer.registerEventHandler(
+ 'fence_enable_signal',
+ FenceParser.prototype.fenceEnableSignalEvent.bind(this));
+ importer.registerEventHandler(
+ 'fence_signaled',
+ FenceParser.prototype.fenceSignaledEvent.bind(this));
+ this.model_ = importer.model_;
+ }
+
+ const fenceRE = /driver=(\S+) timeline=(\S+) context=(\d+) seqno=(\d+)/;
+
+ FenceParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses fence events and sets up state in the importer.
+ */
+ initEvent(eventName, cpuNumber, pid,
+ ts, eventBase) {
+ const event = fenceRE.exec(eventBase.details);
+ if (!event) return false;
+
+ if (eventBase.tgid === undefined) {
+ return false;
+ }
+
+ const thread = this.importer.getOrCreatePseudoThread(event[2]);
+ thread.lastActiveTs = ts;
+
+ return true;
+ },
+
+ fenceDestroyEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = fenceRE.exec(eventBase.details);
+ if (!event) return false;
+
+ if (eventBase.tgid === undefined) {
+ return false;
+ }
+ const thread = this.importer.getOrCreatePseudoThread(event[2]);
+ const name = 'fence_destroy(' + event[4] + ')';
+ const colorName = 'fence(' + event[4] + ')';
+
+ if (thread.lastActiveTs !== undefined) {
+ const duration = ts - thread.lastActiveTs;
+ const slice = new tr.model.ThreadSlice(
+ '', name,
+ ColorScheme.getColorIdForGeneralPurposeString(colorName),
+ thread.lastActiveTs, {
+ 'driver': event[1],
+ 'context': event[3]
+ },
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ if (thread.thread.sliceGroup.openSliceCount > 0) {
+ thread.thread.sliceGroup.endSlice(ts);
+ }
+ thread.lastActiveTs = ts;
+ },
+
+ fenceEnableSignalEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = fenceRE.exec(eventBase.details);
+ if (!event) return false;
+
+ if (eventBase.tgid === undefined) {
+ return false;
+ }
+ const thread = this.importer.getOrCreatePseudoThread(event[2]);
+ const name = 'fence_enable(' + event[4] + ')';
+ const colorName = 'fence(' + event[4] + ')';
+
+ if (thread.lastActiveTs !== undefined) {
+ const duration = ts - thread.lastActiveTs;
+ const slice = new tr.model.ThreadSlice(
+ '', name,
+ ColorScheme.getColorIdForGeneralPurposeString(colorName),
+ thread.lastActiveTs, {
+ 'driver': event[1],
+ 'context': event[3]
+ },
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ if (thread.thread.sliceGroup.openSliceCount > 0) {
+ thread.thread.sliceGroup.endSlice(ts);
+ }
+ thread.lastActiveTs = ts;
+ },
+
+ fenceSignaledEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = fenceRE.exec(eventBase.details);
+ if (!event) return false;
+
+ if (eventBase.tgid === undefined) {
+ return false;
+ }
+ const thread = this.importer.getOrCreatePseudoThread(event[2]);
+ const name = 'fence_signal(' + event[4] + ')';
+ const colorName = 'fence(' + event[4] + ')';
+
+ if (thread.lastActiveTs !== undefined) {
+ const duration = ts - thread.lastActiveTs;
+ const slice = new tr.model.ThreadSlice(
+ '', name,
+ ColorScheme.getColorIdForGeneralPurposeString(colorName),
+ thread.lastActiveTs, {
+ 'driver': event[1],
+ 'context': event[3]
+ },
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ if (thread.thread.sliceGroup.openSliceCount > 0) {
+ thread.thread.sliceGroup.endSlice(ts);
+ }
+ thread.lastActiveTs = ts;
+
+ return true;
+ },
+
+ };
+
+ Parser.register(FenceParser);
+
+ return {
+ FenceParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/fence_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/fence_parser_test.html
new file mode 100644
index 00000000000..ae439e2c591
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/fence_parser_test.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('fenceEventImport', function() {
+ const lines = [
+ 'HwBinder:595_2-650 ( 595) [001] .... 584509.195956: ' +
+ 'fence_init: driver=sde_fence:crtc111:25602 timeline=crtc111 ' +
+ 'context=3 seqno=256022',
+ 'crtc_event:111-247 ( 247) [001] d..1 584509.213897: ' +
+ 'fence_signaled: driver=sde_fence:crtc111:25602 timeline=crtc111 ' +
+ 'context=3 seqno=256022'
+ ];
+
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html
new file mode 100644
index 00000000000..cedff930314
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer.html
@@ -0,0 +1,941 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/trace_stream.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/android_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/binder_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/bus_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/clock_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/cpufreq_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/disk_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/drm_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/exynos_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/fence_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/gesture_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/i2c_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/i915_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ion_heap_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/irq_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/kfunc_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/mali_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/memreclaim_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/power_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/regulator_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/rss_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/sched_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/sync_parser.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/workqueue_parser.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/importer/simple_line_reader.html">
+<link rel="import" href="/tracing/model/clock_sync_manager.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+/**
+ * @fileoverview Imports text files in the Linux event trace format into the
+ * Model. This format is output both by sched_trace and by Linux's perf tool.
+ *
+ * This importer assumes the events arrive as a string. The unit tests provide
+ * examples of the trace format.
+ *
+ * Linux scheduler traces use a definition for 'pid' that is different than
+ * tracing uses. Whereas tracing uses pid to identify a specific process, a pid
+ * in a linux trace refers to a specific thread within a process. Within this
+ * file, we the definition used in Linux traces, as it improves the importing
+ * code's readability.
+ */
+'use strict';
+
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID =
+ 'linux_clock_monotonic_to_ftrace_global';
+
+ const IMPORT_PRIORITY = 2;
+
+ /**
+ * Imports linux perf events into a specified model.
+ * @constructor
+ */
+ function FTraceImporter(model, events) {
+ this.importPriority = IMPORT_PRIORITY;
+ this.model_ = model;
+ this.events_ = events;
+ this.wakeups_ = [];
+ this.blockedReasons_ = [];
+ this.kernelThreadStates_ = {};
+ this.buildMapFromLinuxPidsToThreads_();
+ this.lines_ = [];
+ this.pseudoThreadCounter = 1;
+ this.parsers_ = [];
+ this.eventHandlers_ = {};
+ this.haveClockSyncedMonotonicToGlobal_ = false;
+ this.clockDomainId_ = tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL;
+ }
+
+ const TestExports = {};
+
+ // Matches the trace record in 3.2 and later with the print-tgid option:
+ // <idle>-0 0 [001] d... 1.23: sched_switch
+ //
+ // A TGID (Thread Group ID) is basically what the Linux kernel calls what
+ // userland refers to as a process ID (as opposed to a Linux pid, which is
+ // what userland calls a thread ID).
+ const lineREWithTGID = new RegExp(
+ '^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]' +
+ '\\s+[dX.][Nnp.][Hhs.][0-9a-f.]' +
+ '\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');
+ const lineParserWithTGID = function(line) {
+ const groups = lineREWithTGID.exec(line);
+ if (!groups) return groups;
+
+ let tgid = groups[3];
+ if (tgid[0] === '-') tgid = undefined;
+
+ return {
+ threadName: groups[1],
+ pid: groups[2],
+ tgid,
+ cpuNumber: groups[4],
+ timestamp: groups[5],
+ eventName: groups[6],
+ details: groups[7]
+ };
+ };
+ TestExports.lineParserWithTGID = lineParserWithTGID;
+
+ // Matches the default trace record in 3.2 and later (includes irq-info):
+ // <idle>-0 [001] d... 1.23: sched_switch
+ const lineREWithIRQInfo = new RegExp(
+ '^\\s*(.+)-(\\d+)\\s+\\[(\\d+)\\]' +
+ '\\s+[dX.][Nnp.][Hhs.][0-9a-f.]' +
+ '\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');
+ const lineParserWithIRQInfo = function(line) {
+ const groups = lineREWithIRQInfo.exec(line);
+ if (!groups) return groups;
+ return {
+ threadName: groups[1],
+ pid: groups[2],
+ cpuNumber: groups[3],
+ timestamp: groups[4],
+ eventName: groups[5],
+ details: groups[6]
+ };
+ };
+ TestExports.lineParserWithIRQInfo = lineParserWithIRQInfo;
+
+ // Matches the default trace record pre-3.2:
+ // <idle>-0 [001] 1.23: sched_switch
+ const lineREWithLegacyFmt =
+ /^\s*(.+)-(\d+)\s+\[(\d+)\]\s*(\d+\.\d+):\s+(\S+):\s(.*)$/;
+ const lineParserWithLegacyFmt = function(line) {
+ const groups = lineREWithLegacyFmt.exec(line);
+ if (!groups) {
+ return groups;
+ }
+ return {
+ threadName: groups[1],
+ pid: groups[2],
+ cpuNumber: groups[3],
+ timestamp: groups[4],
+ eventName: groups[5],
+ details: groups[6]
+ };
+ };
+ TestExports.lineParserWithLegacyFmt = lineParserWithLegacyFmt;
+
+ // Matches the trace_event_clock_sync marker:
+ // 0: trace_event_clock_sync: parent_ts=19581477508
+ const traceEventClockSyncRE = /trace_event_clock_sync: parent_ts=(\d+\.?\d*)/;
+ TestExports.traceEventClockSyncRE = traceEventClockSyncRE;
+
+ const realTimeClockSyncRE = /trace_event_clock_sync: realtime_ts=(\d+)/;
+ const genericClockSyncRE = /trace_event_clock_sync: name=([\w\-]+)/;
+
+ // Some kernel trace events are manually classified in slices and
+ // hand-assigned a pseudo PID.
+ const pseudoKernelPID = 0;
+
+ /**
+ * Deduce the format of trace data. Linux kernels prior to 3.3 used one
+ * format (by default); 3.4 and later used another. Additionally, newer
+ * kernels can optionally trace the TGID.
+ *
+ * @return {function} the function for parsing data when the format is
+ * recognized; otherwise undefined.
+ */
+ function autoDetectLineParser(line) {
+ if (line[0] === '{') return false;
+ if (lineREWithTGID.test(line)) return lineParserWithTGID;
+ if (lineREWithIRQInfo.test(line)) return lineParserWithIRQInfo;
+ if (lineREWithLegacyFmt.test(line)) return lineParserWithLegacyFmt;
+ return undefined;
+ }
+ TestExports.autoDetectLineParser = autoDetectLineParser;
+
+ /**
+ * Guesses whether the provided events is a Linux perf string.
+ * Looks for the magic string "# tracer" at the start of the file,
+ * or the typical task-pid-cpu-timestamp-function sequence of a typical
+ * trace's body.
+ *
+ * @return {boolean} True when events is a linux perf array.
+ */
+ FTraceImporter.canImport = function(events) {
+ if (events instanceof tr.b.TraceStream) events = events.header;
+
+ if (!(typeof(events) === 'string' || events instanceof String)) {
+ return false;
+ }
+
+ if (FTraceImporter._extractEventsFromSystraceHTML(events, false).ok) {
+ return true;
+ }
+
+ if (FTraceImporter._extractEventsFromSystraceMultiHTML(events, false).ok) {
+ return true;
+ }
+
+ if (/^# tracer:/.test(events)) return true;
+
+ const lineBreakIndex = events.indexOf('\n');
+ if (lineBreakIndex > -1) events = events.substring(0, lineBreakIndex);
+
+ if (autoDetectLineParser(events)) return true;
+
+ return false;
+ };
+
+ FTraceImporter._extractEventsFromSystraceHTML = function(
+ incomingEvents, produceResult) {
+ const failure = {ok: false};
+ if (produceResult === undefined) produceResult = true;
+
+ const header = incomingEvents instanceof tr.b.TraceStream ?
+ incomingEvents.header : incomingEvents;
+ if (!/^<!DOCTYPE html>/.test(header)) return failure;
+ const r = new tr.importer.SimpleLineReader(incomingEvents);
+
+ // Try to find the data...
+ if (!r.advanceToLineMatching(/^ <script>$/)) return failure;
+ if (!r.advanceToLineMatching(/^ var linuxPerfData = "\\$/)) return failure;
+
+ const eventsBeginAtLine = r.curLineNumber + 1;
+ r.beginSavingLines();
+ if (!r.advanceToLineMatching(/^ <\/script>$/)) return failure;
+
+ let rawEvents = r.endSavingLinesAndGetResult();
+
+ // Drop off first and last event as it contains the tag.
+ rawEvents = rawEvents.slice(1, rawEvents.length - 1);
+
+ if (!r.advanceToLineMatching(/^<\/body>$/)) return failure;
+ if (!r.advanceToLineMatching(/^<\/html>$/)) return failure;
+
+ function endsWith(str, suffix) {
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
+ }
+ function stripSuffix(str, suffix) {
+ if (!endsWith(str, suffix)) return str;
+ return str.substring(str, str.length - suffix.length);
+ }
+
+ // Strip off escaping in the file needed to preserve linebreaks.
+ let events = [];
+ if (produceResult) {
+ for (let i = 0; i < rawEvents.length; i++) {
+ let event = rawEvents[i];
+ event = stripSuffix(event, '\\n\\');
+ events.push(event);
+ }
+ } else {
+ events = [rawEvents[rawEvents.length - 1]];
+ }
+
+ // Last event ends differently. Strip that off too,
+ // treating absence of that trailing string as a failure.
+ const oldLastEvent = events[events.length - 1];
+ const newLastEvent = stripSuffix(oldLastEvent, '\\n";');
+ if (newLastEvent === oldLastEvent) return failure;
+ events[events.length - 1] = newLastEvent;
+
+ return {ok: true,
+ lines: produceResult ? events : undefined,
+ eventsBeginAtLine};
+ };
+
+ FTraceImporter._extractEventsFromSystraceMultiHTML = function(
+ incomingEvents, produceResult) {
+ const failure = {ok: false};
+ if (produceResult === undefined) produceResult = true;
+
+ const header = incomingEvents instanceof tr.b.TraceStream ?
+ incomingEvents.header : incomingEvents;
+ if (!(new RegExp('^<!DOCTYPE HTML>', 'i').test(header))) return failure;
+
+ const r = new tr.importer.SimpleLineReader(incomingEvents);
+
+ // Try to find the Linux perf trace in any of the trace-data tags
+ let events = [];
+ let eventsBeginAtLine;
+ while (!/^# tracer:/.test(events)) {
+ if (!r.advanceToLineMatching(
+ /^ <script class="trace-data" type="application\/text">$/)) {
+ return failure;
+ }
+
+ eventsBeginAtLine = r.curLineNumber + 1;
+
+ r.beginSavingLines();
+ if (!r.advanceToLineMatching(/^ <\/script>$/)) return failure;
+
+ events = r.endSavingLinesAndGetResult();
+
+ // Drop off first and last event as it contains the tag.
+ events = events.slice(1, events.length - 1);
+ }
+
+ if (!r.advanceToLineMatching(/^<\/body>$/)) return failure;
+ if (!r.advanceToLineMatching(/^<\/html>$/)) return failure;
+
+ return {
+ ok: true,
+ lines: produceResult ? events : undefined,
+ eventsBeginAtLine,
+ };
+ };
+
+ FTraceImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'FTraceImporter';
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ /**
+ * Imports clock sync markers into model_.
+ */
+ importClockSyncMarkers() {
+ this.lazyInit_();
+ this.forEachLine_(function(text, eventBase, cpuNumber, pid, ts) {
+ const eventName = eventBase.eventName;
+ if (eventName !== 'tracing_mark_write' && eventName !== '0') return;
+
+ if (traceEventClockSyncRE.exec(eventBase.details) ||
+ genericClockSyncRE.exec(eventBase.details)) {
+ this.traceClockSyncEvent_(eventName, cpuNumber, pid, ts, eventBase);
+ } else if (realTimeClockSyncRE.exec(eventBase.details)) {
+ // TODO(charliea): Migrate this sync to ClockSyncManager.
+ // This entry syncs CLOCK_REALTIME with CLOCK_MONOTONIC. Store the
+ // offset between the two in the model so that importers parsing files
+ // with CLOCK_REALTIME timestamps can map back to CLOCK_MONOTONIC.
+ const match = realTimeClockSyncRE.exec(eventBase.details);
+ this.model_.realtime_to_monotonic_offset_ms = ts - match[1];
+ }
+ }.bind(this));
+ },
+
+ /**
+ * Imports the data in this.events_ into model_.
+ */
+ importEvents() {
+ const modelTimeTransformer =
+ this.model_.clockSyncManager.getModelTimeTransformer(
+ this.clockDomainId_);
+
+ this.importCpuData_(modelTimeTransformer);
+ this.buildMapFromLinuxPidsToThreads_();
+ this.buildPerThreadCpuSlicesFromCpuState_();
+ },
+
+ /**
+ * Registers a linux perf event parser used by importCpuData_.
+ */
+ registerEventHandler(eventName, handler) {
+ // TODO(sleffler) how to handle conflicts?
+ this.eventHandlers_[eventName] = handler;
+ },
+
+ /**
+ * @return {Cpu} A Cpu corresponding to the given cpuNumber.
+ */
+ getOrCreateCpu(cpuNumber) {
+ return this.model_.kernel.getOrCreateCpu(cpuNumber);
+ },
+
+ /**
+ * @return {TimelineThread} A thread corresponding to the kernelThreadName.
+ */
+ getOrCreateKernelThread(kernelThreadName, pid, tid) {
+ if (!this.kernelThreadStates_[kernelThreadName]) {
+ const thread = this.model_.getOrCreateProcess(pid).getOrCreateThread(
+ tid);
+ thread.name = kernelThreadName;
+ this.kernelThreadStates_[kernelThreadName] = {
+ pid,
+ thread,
+ openSlice: undefined,
+ openSliceTS: undefined
+ };
+ this.threadsByLinuxPid[tid] = thread;
+ }
+ return this.kernelThreadStates_[kernelThreadName];
+ },
+
+ /**
+ * Processes can have multiple binder threads.
+ * Binder thread names are not unique across processes we therefore need to
+ * keep more information in order to return the correct threads.
+ */
+ getOrCreateBinderKernelThread(kernelThreadName, pid, tid) {
+ const key = kernelThreadName + pid + tid;
+ if (!this.kernelThreadStates_[key]) {
+ const thread = this.model_.getOrCreateProcess(pid).getOrCreateThread(
+ tid);
+ thread.name = kernelThreadName;
+ this.kernelThreadStates_[key] = {
+ pid,
+ thread,
+ openSlice: undefined,
+ openSliceTS: undefined
+ };
+ this.threadsByLinuxPid[tid] = thread;
+ }
+ return this.kernelThreadStates_[key];
+ },
+
+ /**
+ * @return {TimelineThread} A pseudo thread corresponding to the
+ * threadName. Pseudo threads are for events that we want to break
+ * out to a separate timeline but would not otherwise happen.
+ * These threads are assigned to pseudoKernelPID and given a
+ * unique (incrementing) TID.
+ */
+ getOrCreatePseudoThread(threadName) {
+ let thread = this.kernelThreadStates_[threadName];
+ if (!thread) {
+ thread = this.getOrCreateKernelThread(threadName, pseudoKernelPID,
+ this.pseudoThreadCounter);
+ this.pseudoThreadCounter++;
+ }
+ return thread;
+ },
+
+ /**
+ * Records the fact that a pid has become runnable. This data will
+ * eventually get used to derive each thread's timeSlices array.
+ */
+ markPidRunnable(ts, pid, comm, prio, fromPid) {
+ // The the pids that get passed in to this function are Linux kernel
+ // pids, which identify threads. The rest of trace-viewer refers to
+ // these as tids, so the change of nomenclature happens in the following
+ // construction of the wakeup object.
+ this.wakeups_.push({ts, tid: pid, fromTid: fromPid});
+ },
+
+ /**
+ * Records the reason why a pid has gone into uninterruptible sleep.
+ */
+ addPidBlockedReason(ts, pid, iowait, caller) {
+ // The the pids that get passed in to this function are Linux kernel
+ // pids, which identify threads. The rest of trace-viewer refers to
+ // these as tids, so the change of nomenclature happens in the following
+ // construction of the wakeup object.
+ this.blockedReasons_.push({ts, tid: pid, iowait,
+ caller});
+ },
+
+ /**
+ * Precomputes a lookup table from linux pids back to existing
+ * Threads. This is used during importing to add information to each
+ * thread about whether it was running, descheduled, sleeping, et
+ * cetera.
+ */
+ buildMapFromLinuxPidsToThreads_() {
+ this.threadsByLinuxPid = {};
+ this.model_.getAllThreads().forEach(
+ function(thread) {
+ this.threadsByLinuxPid[thread.tid] = thread;
+ }.bind(this));
+ },
+
+ /**
+ * Builds the timeSlices array on each thread based on our knowledge of what
+ * each Cpu is doing. This is done only for Threads that are
+ * already in the model, on the assumption that not having any traced data
+ * on a thread means that it is not of interest to the user.
+ */
+ buildPerThreadCpuSlicesFromCpuState_() {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+
+ // Push the cpu slices to the threads that they run on.
+ for (const cpuNumber in this.model_.kernel.cpus) {
+ const cpu = this.model_.kernel.cpus[cpuNumber];
+
+ for (let i = 0; i < cpu.slices.length; i++) {
+ const cpuSlice = cpu.slices[i];
+
+ const thread = this.threadsByLinuxPid[cpuSlice.args.tid];
+ if (!thread) continue;
+
+ cpuSlice.threadThatWasRunning = thread;
+
+ if (!thread.tempCpuSlices) {
+ thread.tempCpuSlices = [];
+ }
+ thread.tempCpuSlices.push(cpuSlice);
+ }
+ }
+
+ for (const i in this.wakeups_) {
+ const wakeup = this.wakeups_[i];
+ const thread = this.threadsByLinuxPid[wakeup.tid];
+ if (!thread) continue;
+ thread.tempWakeups = thread.tempWakeups || [];
+ thread.tempWakeups.push(wakeup);
+ }
+ for (const i in this.blockedReasons_) {
+ const reason = this.blockedReasons_[i];
+ const thread = this.threadsByLinuxPid[reason.tid];
+ if (!thread) continue;
+ thread.tempBlockedReasons = thread.tempBlockedReasons || [];
+ thread.tempBlockedReasons.push(reason);
+ }
+
+ // Create slices for when the thread is not running.
+ this.model_.getAllThreads().forEach(function(thread) {
+ if (thread.tempCpuSlices === undefined) return;
+ const origSlices = thread.tempCpuSlices;
+ delete thread.tempCpuSlices;
+
+ origSlices.sort(function(x, y) {
+ return x.start - y.start;
+ });
+
+ const wakeups = thread.tempWakeups || [];
+ delete thread.tempWakeups;
+ wakeups.sort(function(x, y) {
+ return x.ts - y.ts;
+ });
+
+ const reasons = thread.tempBlockedReasons || [];
+ delete thread.tempBlockedReasons;
+ reasons.sort(function(x, y) {
+ return x.ts - y.ts;
+ });
+
+ // Walk the slice list and put slices between each original slice to
+ // show when the thread isn't running.
+ const slices = [];
+
+ if (origSlices.length) {
+ const slice = origSlices[0];
+
+ if (wakeups.length && wakeups[0].ts < slice.start) {
+ const wakeup = wakeups.shift();
+ const wakeupDuration = slice.start - wakeup.ts;
+ const args = {'wakeup from tid': wakeup.fromTid};
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.RUNNABLE, '',
+ wakeup.ts, args, wakeupDuration));
+ }
+
+ const runningSlice = new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.RUNNING, '',
+ slice.start, {}, slice.duration);
+ runningSlice.cpuOnWhichThreadWasRunning = slice.cpu;
+ slices.push(runningSlice);
+ }
+
+ for (let i = 1; i < origSlices.length; i++) {
+ let wakeup = undefined;
+ const prevSlice = origSlices[i - 1];
+ const nextSlice = origSlices[i];
+ let midDuration = nextSlice.start - prevSlice.end;
+ while (wakeups.length && wakeups[0].ts < nextSlice.start) {
+ const w = wakeups.shift();
+ if (wakeup === undefined && w.ts > prevSlice.end) {
+ wakeup = w;
+ }
+ }
+ let blockedReason = undefined;
+ while (reasons.length && reasons[0].ts < prevSlice.end) {
+ const r = reasons.shift();
+ }
+ if (wakeup !== undefined &&
+ reasons.length &&
+ reasons[0].ts < wakeup.ts) {
+ blockedReason = reasons.shift();
+ }
+
+ // Push a sleep slice onto the slices list, interrupting it with a
+ // wakeup if appropriate.
+ const pushSleep = function(state) {
+ if (wakeup !== undefined) {
+ midDuration = wakeup.ts - prevSlice.end;
+ }
+
+ if (blockedReason !== undefined) {
+ const args = {
+ 'kernel callsite when blocked:': blockedReason.caller
+ };
+ if (blockedReason.iowait) {
+ switch (state) {
+ case SCHEDULING_STATE.UNINTR_SLEEP:
+ state = SCHEDULING_STATE.UNINTR_SLEEP_IO;
+ break;
+ case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL:
+ state = SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO;
+ break;
+ case SCHEDULING_STATE.UNINTR_SLEEP_WAKING:
+ state = SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO;
+ break;
+ default:
+ }
+ }
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread,
+ state, '', prevSlice.end, args, midDuration));
+ } else {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread,
+ state, '', prevSlice.end, {}, midDuration));
+ }
+ if (wakeup !== undefined) {
+ const wakeupDuration = nextSlice.start - wakeup.ts;
+ const args = {'wakeup from tid': wakeup.fromTid};
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.RUNNABLE, '',
+ wakeup.ts, args, wakeupDuration));
+ wakeup = undefined;
+ }
+ };
+
+ if (prevSlice.args.stateWhenDescheduled === 'S') {
+ pushSleep(SCHEDULING_STATE.SLEEPING);
+ } else if (prevSlice.args.stateWhenDescheduled === 'R' ||
+ prevSlice.args.stateWhenDescheduled === 'R+') {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.RUNNABLE, '',
+ prevSlice.end, {}, midDuration));
+ } else if (prevSlice.args.stateWhenDescheduled === 'D') {
+ pushSleep(SCHEDULING_STATE.UNINTR_SLEEP);
+ } else if (prevSlice.args.stateWhenDescheduled === 'T') {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.STOPPED, '',
+ prevSlice.end, {}, midDuration));
+ } else if (prevSlice.args.stateWhenDescheduled === 't') {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.DEBUG, '',
+ prevSlice.end, {}, midDuration));
+ } else if (prevSlice.args.stateWhenDescheduled === 'Z') {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.ZOMBIE, '',
+ prevSlice.end, {}, midDuration));
+ } else if (prevSlice.args.stateWhenDescheduled === 'X') {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.EXIT_DEAD, '',
+ prevSlice.end, {}, midDuration));
+ } else if (prevSlice.args.stateWhenDescheduled === 'x') {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.TASK_DEAD, '',
+ prevSlice.end, {}, midDuration));
+ } else if (prevSlice.args.stateWhenDescheduled === 'K') {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.WAKE_KILL, '',
+ prevSlice.end, {}, midDuration));
+ } else if (prevSlice.args.stateWhenDescheduled === 'W') {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.WAKING, '',
+ prevSlice.end, {}, midDuration));
+ } else if (prevSlice.args.stateWhenDescheduled === 'D|K') {
+ pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL);
+ } else if (prevSlice.args.stateWhenDescheduled === 'D|W') {
+ pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKING);
+ } else {
+ slices.push(new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.UNKNOWN, '',
+ prevSlice.end, {}, midDuration));
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Unrecognized sleep state: ' +
+ prevSlice.args.stateWhenDescheduled
+ });
+ }
+
+ const runningSlice = new tr.model.ThreadTimeSlice(
+ thread, SCHEDULING_STATE.RUNNING, '',
+ nextSlice.start, {}, nextSlice.duration);
+ runningSlice.cpuOnWhichThreadWasRunning = prevSlice.cpu;
+ slices.push(runningSlice);
+ }
+ thread.timeSlices = slices;
+ }, this);
+ },
+
+ /**
+ * Creates an instance of each registered linux perf event parser.
+ * This allows the parsers to register handlers for the events they
+ * understand. We also register our own special handlers (for the
+ * timestamp synchronization markers).
+ */
+ createParsers_() {
+ // Instantiate the parsers; this will register handlers for known events
+ const allTypeInfos = tr.e.importer.linux_perf.
+ Parser.getAllRegisteredTypeInfos();
+ const parsers = allTypeInfos.map(
+ function(typeInfo) {
+ return new typeInfo.constructor(this);
+ }, this);
+
+ return parsers;
+ },
+
+ registerDefaultHandlers_() {
+ this.registerEventHandler('tracing_mark_write',
+ FTraceImporter.prototype.traceMarkingWriteEvent_.bind(this));
+ // NB: old-style trace markers; deprecated
+ this.registerEventHandler('0',
+ FTraceImporter.prototype.traceMarkingWriteEvent_.bind(this));
+ // Register dummy clock sync handlers to avoid warnings in the log.
+ this.registerEventHandler('tracing_mark_write:trace_event_clock_sync',
+ function() { return true; });
+ this.registerEventHandler('0:trace_event_clock_sync',
+ function() { return true; });
+ },
+
+ /**
+ * Processes a trace_event_clock_sync event.
+ */
+ traceClockSyncEvent_(eventName, cpuNumber, pid, ts, eventBase) {
+ // Check to see if we have a normal clock sync marker that contains a
+ // sync ID and the current time according to the "ftrace global" clock.
+ let event = /name=(\w+?)\s(.+)/.exec(eventBase.details);
+ if (event) {
+ // TODO(alexandermont): This section of code seems to be broken. It
+ // creates an "args" variable, but doesn't seem to do anything with it.
+ const name = event[1];
+ const pieces = event[2].split(' ');
+ const args = {
+ perfTs: ts
+ };
+ for (let i = 0; i < pieces.length; i++) {
+ const parts = pieces[i].split('=');
+ if (parts.length !== 2) {
+ throw new Error('omgbbq');
+ }
+ args[parts[0]] = parts[1];
+ }
+
+ this.model_.clockSyncManager.addClockSyncMarker(
+ this.clockDomainId_, name, ts);
+ return true;
+ }
+
+ // Check to see if we have a "new style" clock sync marker that contains
+ // only a sync ID.
+ event = /name=([\w\-]+)/.exec(eventBase.details);
+ if (event) {
+ this.model_.clockSyncManager.addClockSyncMarker(
+ this.clockDomainId_, event[1], ts);
+ return true;
+ }
+
+ // Check to see if we have a special clock sync marker that contains both
+ // the current "ftrace global" time and the current CLOCK_MONOTONIC time.
+ event = /parent_ts=(\d+\.?\d*)/.exec(eventBase.details);
+ if (!event) return false;
+
+ let monotonicTs = event[1] * 1000;
+ // A monotonic timestamp of zero is used as a sentinel value to indicate
+ // that CLOCK_MONOTONIC and the ftrace global clock are identical.
+ if (monotonicTs === 0) monotonicTs = ts;
+
+ if (this.haveClockSyncedMonotonicToGlobal_) {
+ // ftrace sometimes includes multiple clock syncs between the monotonic
+ // and global clocks within a single trace. We protect against this by
+ // only taking the first one into account.
+ return true;
+ }
+
+ // We have a clock sync event that contains two timestamps: a timestamp
+ // according to the ftrace 'global' clock, and that same timestamp
+ // according to clock_gettime(CLOCK_MONOTONIC).
+ this.model_.clockSyncManager.addClockSyncMarker(
+ this.clockDomainId_,
+ MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID, ts);
+ this.model_.clockSyncManager.addClockSyncMarker(
+ tr.model.ClockDomainId.LINUX_CLOCK_MONOTONIC,
+ MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID, monotonicTs);
+
+ this.haveClockSyncedMonotonicToGlobal_ = true;
+ return true;
+ },
+
+ /**
+ * Processes a trace_marking_write event.
+ */
+ traceMarkingWriteEvent_(eventName, cpuNumber, pid, ts, eventBase,
+ threadName) {
+ // Some profiles end up with a \n\ on the end of each line. Strip it
+ // before we do the comparisons.
+ eventBase.details = eventBase.details.replace(/\\n.*$/, '');
+
+ const event = /^\s*(\w+):\s*(.*)$/.exec(eventBase.details);
+ if (!event) {
+ // Check if the event matches events traced by the Android framework
+ const tag = eventBase.details.substring(0, 2);
+ if (tag === 'B|' || tag === 'E' || tag === 'E|' || tag === 'X|' ||
+ tag === 'C|' || tag === 'S|' || tag === 'F|') {
+ eventBase.subEventName = 'android';
+ } else {
+ return false;
+ }
+ } else {
+ eventBase.subEventName = event[1];
+ eventBase.details = event[2];
+ }
+
+ const writeEventName = eventName + ':' + eventBase.subEventName;
+ const handler = this.eventHandlers_[writeEventName];
+ if (!handler) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Unknown trace_marking_write event ' + writeEventName
+ });
+ return true;
+ }
+ return handler(writeEventName, cpuNumber, pid, ts, eventBase, threadName);
+ },
+
+ /**
+ * Walks the this.events_ structure and creates Cpu objects.
+ */
+ importCpuData_(modelTimeTransformer) {
+ this.forEachLine_(function(text, eventBase, cpuNumber, pid, ts) {
+ const eventName = eventBase.eventName;
+ const handler = this.eventHandlers_[eventName];
+ if (!handler) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Unknown event ' + eventName + ' (' + text + ')'
+ });
+ return;
+ }
+ ts = modelTimeTransformer(ts);
+ if (!handler(eventName, cpuNumber, pid, ts, eventBase)) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Malformed ' + eventName + ' event (' + text + ')'
+ });
+ }
+ }.bind(this));
+ },
+
+ /**
+ * Walks the this.events_ structure and populates this.lines_.
+ */
+ parseLines_() {
+ let extractResult = FTraceImporter._extractEventsFromSystraceHTML(
+ this.events_, true);
+ if (!extractResult.ok) {
+ extractResult = FTraceImporter._extractEventsFromSystraceMultiHTML(
+ this.events_, true);
+ }
+ let lineParser = undefined;
+ if (extractResult.ok) {
+ for (const line of extractResult.lines) {
+ lineParser = this.parseLine_(line, lineParser);
+ }
+ } else {
+ const r = new tr.importer.SimpleLineReader(this.events_);
+ for (const line of r) {
+ lineParser = this.parseLine_(line, lineParser);
+ }
+ }
+ },
+
+ parseLine_(line, lineParser) {
+ line = line.trim();
+ if (line.length === 0) return lineParser;
+ if (/^#/.test(line)) {
+ const clockType = /^# clock_type=([A-Z_]+)$/.exec(line);
+ // This allows the clock domain to be specified through a comment,
+ // Ex. "# clock_type=LINUX_CLOCK_MONOTONIC".
+ // This is used in the WALT trace agent.
+ if (clockType) {
+ this.clockDomainId_ = clockType[1];
+ }
+ return lineParser;
+ }
+
+ if (!lineParser) {
+ lineParser = autoDetectLineParser(line);
+ if (!lineParser) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Cannot parse line: ' + line
+ });
+ return lineParser;
+ }
+ }
+
+ const eventBase = lineParser(line);
+ if (!eventBase) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Unrecognized line: ' + line
+ });
+ return lineParser;
+ }
+
+ this.lines_.push([
+ line,
+ eventBase,
+ parseInt(eventBase.cpuNumber),
+ parseInt(eventBase.pid),
+ parseFloat(eventBase.timestamp) * 1000
+ ]);
+ return lineParser;
+ },
+
+ /**
+ * Calls |handler| for every parsed line.
+ */
+ forEachLine_(handler) {
+ for (let i = 0; i < this.lines_.length; ++i) {
+ const line = this.lines_[i];
+ handler.apply(this, line);
+ }
+ },
+
+ /**
+ * Initializes the ftrace importer. This initialization can't be done in the
+ * constructor because all trace event handlers may not have been registered
+ * by that point.
+ */
+ lazyInit_() {
+ this.parsers_ = this.createParsers_();
+ this.registerDefaultHandlers_();
+ this.parseLines_();
+ }
+ };
+
+ tr.importer.Importer.register(FTraceImporter);
+
+ return {
+ FTraceImporter,
+ _FTraceImporterTestExports: TestExports,
+ IMPORT_PRIORITY,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer_test.html
new file mode 100644
index 00000000000..ee9382ab13f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ftrace_importer_test.html
@@ -0,0 +1,686 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/in_memory_trace_stream.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/model/clock_sync_manager.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ClockDomainId = tr.model.ClockDomainId;
+ const FTraceImporter = tr.e.importer.linux_perf.FTraceImporter;
+ const FTraceImporterTestExports =
+ tr.e.importer.linux_perf._FTraceImporterTestExports;
+
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('lineParserWithLegacyFmt', function() {
+ const p = FTraceImporterTestExports.lineParserWithLegacyFmt;
+ let x = p(' <idle>-0 [001] 4467.843475: sched_switch: ' +
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ==> ' +
+ 'next_comm=SurfaceFlinger next_pid=178 next_prio=112');
+ assert.isNotNull(x);
+ assert.strictEqual(x.threadName, '<idle>');
+ assert.strictEqual(x.pid, '0');
+ assert.strictEqual(x.cpuNumber, '001');
+ assert.strictEqual(x.timestamp, '4467.843475');
+ assert.strictEqual(x.eventName, 'sched_switch');
+ assert.strictEqual(
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R' +
+ ' ==> next_comm=SurfaceFlinger next_pid=178 next_prio=112', x.details);
+
+ x = p('Binder-Thread #-647 [001] 260.464294: sched_switch: ' +
+ 'prev_comm=Binder Thread # prev_pid=647 prev_prio=120 prev_state=D ' +
+ ' ==> next_comm=.android.chrome next_pid=1562 next_prio=120');
+ assert.isNotNull(x);
+ assert.strictEqual(x.threadName, 'Binder-Thread #');
+ assert.strictEqual(x.pid, '647');
+ });
+
+ test('lineParserWithIRQInfo', function() {
+ const p = FTraceImporterTestExports.lineParserWithIRQInfo;
+ const x = p(' systrace.sh-5441 [001] d... 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x.threadName, 'systrace.sh');
+ assert.strictEqual(x.pid, '5441');
+ assert.strictEqual(x.cpuNumber, '001');
+ assert.strictEqual(x.timestamp, '1031.091570');
+ assert.strictEqual(x.eventName, 'sched_wakeup');
+ assert.strictEqual(x.details, 'comm=debugd pid=4978 prio=120 success=1 target_cpu=000'); // @suppress longLineCheck
+ });
+
+ test('lineParserWithIRQInfoNeedResched', function() {
+ const p = FTraceImporterTestExports.lineParserWithIRQInfo;
+ let x = p(' systrace.sh-5441 [001] .N.. 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x.threadName, 'systrace.sh');
+ assert.strictEqual(x.pid, '5441');
+ assert.strictEqual(x.cpuNumber, '001');
+ assert.strictEqual(x.timestamp, '1031.091570');
+ assert.strictEqual(x.eventName, 'sched_wakeup');
+ assert.strictEqual(x.details, 'comm=debugd pid=4978 prio=120 success=1 target_cpu=000'); // @suppress longLineCheck
+
+ x = p(' systrace.sh-5441 [001] .n.. 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x.threadName, 'systrace.sh');
+
+ x = p(' systrace.sh-5441 [001] .p.. 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x.threadName, 'systrace.sh');
+ });
+
+ test('lineParserWithTGID', function() {
+ const p = FTraceImporterTestExports.lineParserWithTGID;
+ let x = p(' systrace.sh-5441 (54321) [001] d... 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x.threadName, 'systrace.sh');
+ assert.strictEqual(x.pid, '5441');
+ assert.strictEqual(x.tgid, '54321');
+ assert.strictEqual(x.cpuNumber, '001');
+ assert.strictEqual(x.timestamp, '1031.091570');
+ assert.strictEqual(x.eventName, 'sched_wakeup');
+ assert.strictEqual(x.details, 'comm=debugd pid=4978 prio=120 success=1 target_cpu=000'); // @suppress longLineCheck
+
+ x = p(' systrace.sh-5441 ( 321) [001] d... 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x.tgid, '321');
+
+ x = p(' systrace.sh-5441 (-----) [001] d... 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.isUndefined(x.tgid);
+ });
+
+ test('lineParserWithTGIDNeedResched', function() {
+ const p = FTraceImporterTestExports.lineParserWithTGID;
+ let x = p(' systrace.sh-5441 (54321) [001] .N.. 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x.threadName, 'systrace.sh');
+ assert.strictEqual(x.pid, '5441');
+ assert.strictEqual(x.tgid, '54321');
+ assert.strictEqual(x.cpuNumber, '001');
+ assert.strictEqual(x.timestamp, '1031.091570');
+ assert.strictEqual(x.eventName, 'sched_wakeup');
+ assert.strictEqual(x.details, 'comm=debugd pid=4978 prio=120 success=1 target_cpu=000'); // @suppress longLineCheck
+
+ x = p(' systrace.sh-5441 ( 321) [001] .n.. 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x.tgid, '321');
+
+ x = p(' systrace.sh-5441 (-----) [001] .p.. 1031.091570: ' +
+ 'sched_wakeup: comm=debugd pid=4978 prio=120 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.isUndefined(x.tgid);
+ });
+
+ test('autodetectLineCornerCases', function() {
+ const detectParser = FTraceImporterTestExports.autoDetectLineParser;
+ const lineParserWithLegacyFmt =
+ FTraceImporterTestExports.lineParserWithLegacyFmt;
+ const lineParserWithIRQInfo =
+ FTraceImporterTestExports.lineParserWithIRQInfo;
+ const lineParserWithTGID = FTraceImporterTestExports.lineParserWithTGID;
+
+ const lineWithLegacyFmt =
+ 'systrace.sh-8170 [001] 15180.978813: sched_switch: ' +
+ 'prev_comm=systrace.sh prev_pid=8170 prev_prio=120 ' +
+ 'prev_state=x ==> next_comm=kworker/1:0 next_pid=7873 ' +
+ 'next_prio=120';
+ let detected = detectParser(lineWithLegacyFmt);
+ assert.strictEqual(lineParserWithLegacyFmt, detected);
+
+ const lineWithIRQInfo =
+ 'systrace.sh-8170 [001] d... 15180.978813: sched_switch: ' +
+ 'prev_comm=systrace.sh prev_pid=8170 prev_prio=120 ' +
+ 'prev_state=x ==> next_comm=kworker/1:0 next_pid=7873 ' +
+ 'next_prio=120';
+ detected = detectParser(lineWithIRQInfo);
+ assert.strictEqual(lineParserWithIRQInfo, detected);
+
+ const lineWithTGID =
+ 'systrace.sh-8170 (54321) [001] d... 15180.978813: sched_switch: ' +
+ 'prev_comm=systrace.sh prev_pid=8170 prev_prio=120 ' +
+ 'prev_state=x ==> next_comm=kworker/1:0 next_pid=7873 ' +
+ 'next_prio=120';
+ detected = detectParser(lineWithTGID);
+ assert.strictEqual(lineParserWithTGID, detected);
+ });
+
+ test('traceEventClockSyncRE', function() {
+ const re = FTraceImporterTestExports.traceEventClockSyncRE;
+ let x = re.exec('trace_event_clock_sync: parent_ts=19581477508');
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], '19581477508');
+
+ x = re.exec('trace_event_clock_sync: parent_ts=123.456');
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], '123.456');
+ });
+
+ test('genericClockSync', function() {
+ const lines = [
+ '# tracer: nop',
+ '#',
+ '# TASK-PID CPU# TIMESTAMP FUNCTION',
+ '# | | | | |',
+ 'sh-26121 [000] ...1 15.050: tracing_mark_write: trace_event_clock_sync: name=battor regulator=8941_smbb_boost' // @suppress longLineCheck
+ ];
+
+ const io = new tr.importer.ImportOptions();
+ const m = new tr.Model();
+ const i = new tr.importer.Import(m, io);
+
+ m.clockSyncManager.addClockSyncMarker(ClockDomainId.BATTOR, 'battor', 50);
+
+ i.importTraces([lines.join('\n')]);
+
+ assert.isFalse(m.hasImportWarnings);
+ // The clock sync happened at 15050 in the ftrace global domain and at 50
+ // in the BattOr domain. This means the ftrace global timestamps need 15000
+ // subtracted from them in order to be on the BattOr timeline.
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(ClockDomainId.BATTOR)(3),
+ 3);
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.LINUX_FTRACE_GLOBAL)(15003),
+ 3);
+ });
+
+ test('clockTypeMarker', function() {
+ const lines = [
+ '# tracer: nop',
+ '#',
+ '# clock_type=LINUX_CLOCK_MONOTONIC',
+ '# TASK-PID CPU# TIMESTAMP FUNCTION',
+ '# | | | | |',
+ '<0>-0 (-----) [001] ...1 15.050: tracing_mark_write: ' +
+ 'trace_event_clock_sync: name=some_sync_id'
+ ];
+
+ const io = new tr.importer.ImportOptions();
+ const m = new tr.Model();
+ const i = new tr.importer.Import(m, io);
+
+ m.clockSyncManager.addClockSyncMarker(
+ ClockDomainId.LINUX_FTRACE_GLOBAL, 'some_sync_id', 50);
+
+ i.importTraces([lines.join('\n')]);
+
+ assert.isFalse(m.hasImportWarnings);
+ // The clock sync happened at 15050 in the linux monotonic domain and at 50
+ // in the ftrace global domain. This means the ftrace global timestamps need
+ // 15000 added to them in order to be on the linux monotonic timeline.
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.LINUX_FTRACE_GLOBAL)(3),
+ 15003);
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.LINUX_CLOCK_MONOTONIC)(3),
+ 3);
+ });
+
+ test('canImport', function() {
+ let lines = [
+ '# tracer: nop',
+ '#',
+ '# TASK-PID CPU# TIMESTAMP FUNCTION',
+ '# | | | | |',
+ ' <idle>-0 [001] 4467.843475: sched_switch: ' +
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ==> ' +
+ 'next_comm=SurfaceFlinger next_pid=178 next_prio=112',
+
+ ' SurfaceFlinger-178 [001] 4467.843536: sched_switch: ' +
+ 'prev_comm=SurfaceFlinger prev_pid=178 prev_prio=112 prev_state=S ' +
+ '==> next_comm=kworker/u:2 next_pid=2844 next_prio=120',
+
+ ' kworker/u:2-2844 [001] 4467.843567: sched_switch: ' +
+ 'prev_comm=kworker/u:2 prev_pid=2844 prev_prio=120 prev_state=S ' +
+ '==> next_comm=swapper next_pid=0 next_prio=120',
+
+ ' <idle>-0 [001] 4467.844208: sched_switch: ' +
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ==> ' +
+ 'next_comm=kworker/u:2 next_pid=2844 next_prio=120'
+ ];
+ assert.isTrue(FTraceImporter.canImport(lines.join('\n')));
+
+ lines = [
+ ' <idle>-0 [001] 4467.843475: sched_switch: ' +
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ==> ' +
+ 'next_comm=SurfaceFlinger next_pid=178 next_prio=112'
+ ];
+ assert.isTrue(FTraceImporter.canImport(lines.join('\n')));
+
+ lines = [
+ ' <idle>-0 [001] 4467.843475: sched_switch: ' +
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ==> ' +
+ 'next_comm=SurfaceFlinger next_pid=178 next_prio=112',
+
+ ' SurfaceFlinger-178 [001] 4467.843536: sched_switch: ' +
+ 'prev_comm=SurfaceFlinger prev_pid=178 prev_prio=112 ' +
+ 'prev_state=S ==> next_comm=kworker/u:2 next_pid=2844 ' +
+ 'next_prio=120'
+ ];
+ assert.isTrue(FTraceImporter.canImport(lines.join('\n')));
+
+ lines = [
+ 'SomeRandomText',
+ 'More random text'
+ ];
+ assert.isFalse(FTraceImporter.canImport(lines.join('\n')));
+ });
+
+ test('canImport34AndLater', function() {
+ let lines = [
+ '# tracer: nop',
+ '#',
+ '# entries-in-buffer/entries-written: 55191/55191 #P:2',
+ '#',
+ '# _-----=> irqs-off',
+ '# / _----=> need-resched',
+ '# | / _---=> hardirq/softirq',
+ '# || / _--=> preempt-depth',
+ '# ||| / delay',
+ '# TASK-PID CPU# |||| TIMESTAMP FUNCTION',
+ '# | | | |||| | |',
+ ' systrace.sh-5441 [001] d... 1031.091570: sched_wakeup: ' +
+ 'comm=debugd pid=4978 prio=120 success=1 target_cpu=000',
+ ' systrace.sh-5441 [001] d... 1031.091584: sched_switch: ' +
+ 'prev_comm=systrace.sh prev_pid=5441 prev_prio=120 prev_state=x ' +
+ '==> next_comm=chrome next_pid=5418 next_prio=120'
+ ];
+ assert.isTrue(FTraceImporter.canImport(lines.join('\n')));
+
+ lines = [
+ ' systrace.sh-5441 [001] d... 1031.091570: sched_wakeup: ' +
+ 'comm=debugd pid=4978 prio=120 success=1 target_cpu=000',
+ ' systrace.sh-5441 [001] d... 1031.091584: sched_switch: ' +
+ 'prev_comm=systrace.sh prev_pid=5441 prev_prio=120 prev_state=x ' +
+ '==> next_comm=chrome next_pid=5418 next_prio=120'
+ ];
+ assert.isTrue(FTraceImporter.canImport(lines.join('\n')));
+ });
+
+ test('importOneSequence', function() {
+ const lines = [
+ ' <idle>-0 [001] 4467.843475: sched_switch: ' +
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ==> ' +
+ 'next_comm=SurfaceFlinger next_pid=178 next_prio=112',
+
+ ' SurfaceFlinger-178 [001] 4467.843536: sched_switch: ' +
+ 'prev_comm=SurfaceFlinger prev_pid=178 prev_prio=112 ' +
+ 'prev_state=S ==> next_comm=kworker/u:2 next_pid=2844 ' +
+ 'next_prio=120',
+
+ ' kworker/u:2-2844 [001] 4467.843567: sched_switch: ' +
+ 'prev_comm=kworker/u:2 prev_pid=2844 prev_prio=120 ' +
+ 'prev_state=S ==> next_comm=swapper next_pid=0 next_prio=120'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c = m.kernel.cpus[1];
+ assert.strictEqual(c.slices.length, 2);
+
+ assert.strictEqual(c.slices[0].title, 'SurfaceFlinger');
+ assert.strictEqual(c.slices[0].start, 4467843.475);
+ assert.closeTo(.536 - .475, c.slices[0].duration, 1e-5);
+ });
+
+ test('importOneSequenceWithSpacyThreadName', function() {
+ const lines = [
+ ' <idle>-0 [001] 4467.843475: sched_switch: ' +
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ==> ' +
+ 'next_comm=Surface Flinger next_pid=178 next_prio=112',
+
+ 'Surface Flinger -178 [001] 4467.843536: sched_switch: ' +
+ 'prev_comm=Surface Flinger prev_pid=178 prev_prio=112 ' +
+ 'prev_state=S ==> next_comm=kworker/u:2 next_pid=2844 ' +
+ 'next_prio=120',
+
+ ' kworker/u:2-2844 [001] 4467.843567: sched_switch: ' +
+ 'prev_comm=kworker/u:2 prev_pid=2844 prev_prio=120 ' +
+ 'prev_state=S ==> next_comm=swapper next_pid=0 next_prio=120'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c = m.kernel.cpus[1];
+ assert.strictEqual(c.slices.length, 2);
+
+ assert.strictEqual(c.slices[0].title, 'Surface Flinger ');
+ assert.strictEqual(c.slices[0].start, 4467843.475);
+ assert.closeTo(.536 - .475, c.slices[0].duration, 1e-5);
+ });
+
+ test('importWithNewline', function() {
+ const lines = [
+ ''
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+ });
+
+ test('importSystraceHtml', function() {
+ const p = tr.b.getAsync(
+ '/test_data/trivial_systrace.html');
+ return p.then(function(data) {
+ const m = newModel(data);
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.isDefined(m.processes[124]);
+ assert.isDefined(m.processes[360]);
+
+ assert.isDefined(m.processes[124].counters['android.StatusBar']);
+ assert.strictEqual(
+ m.processes[124].counters['android.StatusBar'].numSamples, 1);
+ assert.isDefined(m.processes[124].counters['android.VSYNC']);
+ assert.strictEqual(
+ 2, m.processes[124].counters['android.VSYNC'].numSamples);
+ assert.isDefined(m.processes[360].counters['android.iq']);
+ assert.strictEqual(
+ 1, m.processes[360].counters['android.iq'].numSamples);
+ }, function(err) {
+ throw err;
+ });
+ });
+
+ test('importMultiTraceHtml', function() {
+ const lines = [
+ '<!DoCTYPE hTml>', // check must be case insensitive
+ '<body>',
+ ' <div class="view">',
+ ' <\/div>',
+ ' <script class="trace-data" type="application/text">',
+ 'test1',
+ 'test2',
+ ' <\/script>',
+ ' <script class="trace-data" type="application/text">',
+ '# tracer: nop',
+ '#',
+ '# TASK-PID CPU# TIMESTAMP FUNCTION',
+ '# | | | | |',
+ ' hwc_eventmon-336 [000] 50260.929925: 0: C|124|VSYNC|1',
+ ' Binder_1-340 [000] 50260.935656: 0: C|124|StatusBar|1',
+ ' hwc_eventmon-336 [000] 50260.946573: 0: C|124|VSYNC|0',
+ ' InputReader-419 [000] 50262.538578: 0: C|360|iq|1',
+ ' <\/script>',
+ '<\/body>',
+ '<\/html>'
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.isDefined(m.processes[124]);
+ assert.isDefined(m.processes[360]);
+
+ assert.isDefined(m.processes[124].counters['android.StatusBar']);
+ assert.strictEqual(
+ m.processes[124].counters['android.StatusBar'].numSamples, 1);
+ assert.isDefined(m.processes[124].counters['android.VSYNC']);
+ assert.strictEqual(
+ 2, m.processes[124].counters['android.VSYNC'].numSamples);
+ assert.isDefined(m.processes[360].counters['android.iq']);
+ assert.strictEqual(
+ 1, m.processes[360].counters['android.iq'].numSamples);
+ });
+
+ test('importTraceStream', function() {
+ const lines = [
+ '<!DoCTYPE hTml>', // check must be case insensitive
+ '<body>',
+ ' <div class="view">',
+ ' <\/div>',
+ ' <script class="trace-data" type="application/text">',
+ 'test1',
+ 'test2',
+ ' <\/script>',
+ ' <script class="trace-data" type="application/text">',
+ '# tracer: nop',
+ '#',
+ '# TASK-PID CPU# TIMESTAMP FUNCTION',
+ '# | | | | |',
+ ' hwc_eventmon-336 [000] 50260.929925: 0: C|124|VSYNC|1',
+ ' Binder_1-340 [000] 50260.935656: 0: C|124|StatusBar|1',
+ ' hwc_eventmon-336 [000] 50260.946573: 0: C|124|VSYNC|0',
+ ' InputReader-419 [000] 50262.538578: 0: C|360|iq|1',
+ ' <\/script>',
+ '<\/body>',
+ '<\/html>'
+ ];
+ const inputStr = lines.join('\n');
+ const buffer = new ArrayBuffer(inputStr.length);
+ const bufferView = new Uint8Array(buffer);
+ for (let i = 0; i < bufferView.length; i++) {
+ bufferView[i] = inputStr.charCodeAt(i);
+ }
+
+ const m = newModel(new tr.b.InMemoryTraceStream(bufferView));
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.isDefined(m.processes[124]);
+ assert.isDefined(m.processes[360]);
+
+ assert.isDefined(m.processes[124].counters['android.StatusBar']);
+ assert.strictEqual(
+ m.processes[124].counters['android.StatusBar'].numSamples, 1);
+ assert.isDefined(m.processes[124].counters['android.VSYNC']);
+ assert.strictEqual(
+ 2, m.processes[124].counters['android.VSYNC'].numSamples);
+ assert.isDefined(m.processes[360].counters['android.iq']);
+ assert.strictEqual(1, m.processes[360].counters['android.iq'].numSamples);
+ });
+
+ test('clockSync', function() {
+ const lines = [
+ ' <idle>-0 [001] 4467.843475: sched_switch: ' +
+ 'prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ' +
+ '==> next_comm=SurfaceFlinger next_pid=178 next_prio=112',
+ ' SurfaceFlinger-178 [001] 4467.843536: sched_switch: ' +
+ 'prev_comm=SurfaceFlinger prev_pid=178 prev_prio=112 ' +
+ 'prev_state=S ==> next_comm=kworker/u:2 next_pid=2844 ' +
+ 'next_prio=120',
+ ' kworker/u:2-2844 [001] 4467.843567: sched_switch: ' +
+ 'prev_comm=kworker/u:2 prev_pid=2844 prev_prio=120 ' +
+ 'prev_state=S ==> next_comm=swapper next_pid=0 ' +
+ 'next_prio=120',
+ ' kworker/u:2-2844 [001] 4467.843000: 0: ' +
+ 'trace_event_clock_sync: parent_ts=0.1'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c = m.kernel.cpus[1];
+ assert.strictEqual(c.slices.length, 2);
+
+ assert.closeTo(
+ (467.843475 - (467.843 - 0.1)) * 1000,
+ c.slices[0].start,
+ 1e-5);
+ });
+
+ test('clockSyncMarkWrite', function() {
+ const lines = [
+ 'systrace.sh-8170 [001] 15180.978813: sched_switch: ' +
+ 'prev_comm=systrace.sh prev_pid=8170 prev_prio=120 ' +
+ 'prev_state=x ==> next_comm=kworker/1:0 next_pid=7873 ' +
+ 'next_prio=120',
+ ' kworker/1:0-7873 [001] 15180.978836: sched_switch: ' +
+ 'prev_comm=kworker/1:0 prev_pid=7873 prev_prio=120 ' +
+ 'prev_state=S ==> next_comm=debugd next_pid=4404 next_prio=120',
+ ' debugd-4404 [001] 15180.979010: sched_switch: prev_comm=debugd ' +
+ 'prev_pid=4404 prev_prio=120 prev_state=S ==> ' +
+ 'next_comm=dbus-daemon next_pid=510 next_prio=120',
+ 'systrace.sh-8182 [000] 15186.203900: tracing_mark_write: ' +
+ 'trace_event_clock_sync: parent_ts=0'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c = m.kernel.cpus[1];
+ assert.strictEqual(c.slices.length, 2);
+
+ assert.closeTo((15180.978813 - 0) * 1000, c.slices[0].start, 1e-5);
+
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL)(100),
+ 100);
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ tr.model.ClockDomainId.LINUX_CLOCK_MONOTONIC)(100),
+ 100);
+ });
+
+ test('clockSyncMarkWriteSecondIgnored', function() {
+ const lines = [
+ 'systrace.sh-8182 [000] 15186.203900: tracing_mark_write: ' +
+ 'trace_event_clock_sync: parent_ts=0',
+ 'systrace.sh-8182 [000] 15187.203900: tracing_mark_write: ' +
+ 'trace_event_clock_sync: parent_ts=0'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL)(100),
+ 100);
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ tr.model.ClockDomainId.LINUX_CLOCK_MONOTONIC)(100),
+ 100);
+ });
+
+ test('tracingMarkWriteEOLCleanup', function() {
+ const lines = [
+ 'systrace.sh-8182 [001] ...1 2068001.677892: tracing_mark_write: ' +
+ 'B|9304|test\\n\\',
+ 'systrace.sh-8182 [002] ...1 2068991.686415: tracing_mark_write: E\\n\\'
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c = m.processes[9304].threads[8182].sliceGroup;
+ assert.strictEqual(c.slices.length, 1);
+
+ assert.closeTo((2068001.677892 - 0) * 1000, c.slices[0].start, 1e-5);
+ assert.closeTo(
+ (2068991.686415 - 2068001.677892) * 1000,
+ c.slices[0].duration,
+ 1e-5);
+ });
+
+ test('cpuCount', function() {
+ const lines = [
+ 'systrace.sh-8170 [001] 15180.978813: sched_switch: ' +
+ 'prev_comm=systrace.sh prev_pid=8170 prev_prio=120 ' +
+ 'prev_state=x ==> next_comm=kworker/1:0 next_pid=7873 ' +
+ 'next_prio=120',
+ ' kworker/1:0-7873 [001] 15180.978836: sched_switch: ' +
+ 'prev_comm=kworker/1:0 prev_pid=7873 prev_prio=120 ' +
+ 'prev_state=S ==> next_comm=debugd next_pid=4404 next_prio=120',
+ ' debugd-4404 [000] 15180.979010: sched_switch: prev_comm=debugd ' +
+ 'prev_pid=4404 prev_prio=120 prev_state=S ==> ' +
+ 'next_comm=dbus-daemon next_pid=510 next_prio=120'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.lengthOf(Object.keys(m.kernel.cpus), 2);
+ assert.strictEqual(m.kernel.bestGuessAtCpuCount, 2);
+ });
+
+ test('noOverlap', function() {
+ const lines = [
+ '# tracer: nop',
+ '#',
+ '# entries-in-buffer/entries-written: 10/10 #P:1',
+ '#',
+ '# _-----=> irqs-off',
+ '# / _----=> need-resched',
+ '# | / _---=> hardirq/softirq',
+ '# || / _--=> preempt-depth',
+ '# ||| / delay',
+ '# TASK-PID CPU# |||| TIMESTAMP FUNCTION',
+ '# | | | |||| | |',
+ ' <idle>-0 [000] d..3 49.000000: sched_switch: ' +
+ 'prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=S ' +
+ '==> next_comm=Unity next_pid=29677 next_prio=120',
+ ' <...>-29677 [000] d..3 49.001000: sched_switch: ' +
+ 'prev_comm=Unity prev_pid=29677 prev_prio=120 prev_state=R+ ' +
+ '==> next_comm=swapper/3 next_pid=0 next_prio=120',
+ ' <...>-29678 [000] d..4 49.002000: sched_wakeup: ' +
+ 'comm=Unity pid=29677 prio=120 success=1 target_cpu=000',
+ ' <idle>-0 [000] d..3 49.003000: sched_switch: ' +
+ 'prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ' +
+ '==> next_comm=Unity next_pid=29677 next_prio=120',
+ ' <...>-29677 [000] ...1 49.004000: tracing_mark_write: ' +
+ 'B|7244|eglSwapBuffersWithDamageKHR',
+ ' <...>-29677 [000] d..3 49.005000: sched_switch: ' +
+ 'prev_comm=Unity prev_pid=29677 prev_prio=120 prev_state=S ' +
+ '==> next_comm=swapper/3 next_pid=0 next_prio=120',
+ ' <...>-2599 [000] d.h4 49.006000: sched_wakeup: ' +
+ 'comm=Unity pid=29677 prio=120 success=1 target_cpu=000',
+ ' <idle>-0 [000] d..3 49.007000: sched_switch: ' +
+ 'prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ' +
+ '==> next_comm=Unity next_pid=29677 next_prio=120',
+ ' <...>-29677 [000] ...1 49.008000: tracing_mark_write: ' +
+ 'B|7244|queueBuffer',
+ ' <...>-29677 [000] d..3 49.009000: sched_switch: ' +
+ 'prev_comm=Unity prev_pid=29677 prev_prio=120 prev_state=R ' +
+ '==> next_comm=swapper/3 next_pid=0 next_prio=120'
+ ];
+ const m = newModel(lines.join('\n'));
+ const thread = m.getAllThreads()[0];
+ let previousEnd = 0;
+ for (const slice of thread.timeSlices) {
+ assert.isTrue(slice.end >= slice.start);
+ assert.isTrue(slice.start >= previousEnd);
+ previousEnd = slice.end;
+ }
+ });
+
+ test('cpuSliceNaming', function() {
+ // Invoke the binder parser first on a thread(1002) in the process that is
+ // not the main thread(1001) and then use sched events to create a cpu
+ // slice.
+ const lines = [
+ 'bar-1002 (1001) [000] ...1 1.000000: binder_transaction_received: ' +
+ 'transaction=612345 ',
+ 'dont_care-2000 (2000) [001] d..3 2.000000: sched_switch: ' +
+ 'prev_comm=dont_care prev_pid=2000 prev_prio=100 prev_state=D ' +
+ '==> next_comm=foo next_pid=1001 next_prio=100',
+ 'foo-1001 (1001) [001] d..3 3.000000: sched_switch: ' +
+ 'prev_comm=foo prev_pid=1001 prev_prio=100 prev_state=S ' +
+ '==> next_comm=doesnt_matter next_pid=3000 next_prio=100'
+ ];
+ const m = newModel(lines.join('\n'));
+ const slice = m.kernel.getOrCreateCpu(1).slices[0];
+ assert.strictEqual(slice.title, 'foo');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser.html
new file mode 100644
index 00000000000..e06cfbe9ef4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses gesture events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses trace events generated by gesture library for touchpad.
+ * @constructor
+ */
+ function GestureParser(importer) {
+ Parser.call(this, importer);
+ importer.registerEventHandler('tracing_mark_write:log',
+ GestureParser.prototype.logEvent.bind(this));
+ importer.registerEventHandler('tracing_mark_write:SyncInterpret',
+ GestureParser.prototype.syncEvent.bind(this));
+ importer.registerEventHandler('tracing_mark_write:HandleTimer',
+ GestureParser.prototype.timerEvent.bind(this));
+ }
+
+ GestureParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parse events generate by gesture library.
+ * gestureOpenSlice and gestureCloseSlice are two common
+ * functions to store the begin time and end time for all
+ * events in gesture library
+ */
+ gestureOpenSlice(title, ts, opt_args) {
+ const thread = this.importer.getOrCreatePseudoThread('gesture').thread;
+ thread.sliceGroup.beginSlice(
+ 'touchpad_gesture', title, ts, opt_args);
+ },
+
+ gestureCloseSlice(title, ts) {
+ const thread = this.importer.getOrCreatePseudoThread('gesture').thread;
+ if (thread.sliceGroup.openSliceCount) {
+ const slice = thread.sliceGroup.mostRecentlyOpenedPartialSlice;
+ if (slice.title !== title) {
+ this.importer.model.importWarning({
+ type: 'title_match_error',
+ message: 'Titles do not match. Title is ' +
+ slice.title + ' in openSlice, and is ' +
+ title + ' in endSlice'
+ });
+ } else {
+ thread.sliceGroup.endSlice(ts);
+ }
+ }
+ },
+
+ /**
+ * For log events, events will come in pairs with a tag log:
+ * like this:
+ * tracing_mark_write: log: start: TimerLogOutputs
+ * tracing_mark_write: log: end: TimerLogOutputs
+ * which represent the start and the end time of certain log behavior
+ * Take these logs above for example, they are the start and end time
+ * of logging Output for HandleTimer function
+ */
+ logEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const innerEvent =
+ /^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);
+ switch (innerEvent[1]) {
+ case 'start':
+ this.gestureOpenSlice('GestureLog', ts, {name: innerEvent[2]});
+ break;
+ case 'end':
+ this.gestureCloseSlice('GestureLog', ts);
+ }
+ return true;
+ },
+
+ /**
+ * For SyncInterpret events, events will come in pairs with
+ * a tag SyncInterpret:
+ * like this:
+ * tracing_mark_write: SyncInterpret: start: ClickWiggleFilterInterpreter
+ * tracing_mark_write: SyncInterpret: end: ClickWiggleFilterInterpreter
+ * which represent the start and the end time of SyncInterpret function
+ * inside the certain interpreter in the gesture library.
+ * Take the logs above for example, they are the start and end time
+ * of the SyncInterpret function inside ClickWiggleFilterInterpreter
+ */
+ syncEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const innerEvent = /^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);
+ switch (innerEvent[1]) {
+ case 'start':
+ this.gestureOpenSlice('SyncInterpret', ts,
+ {interpreter: innerEvent[2]});
+ break;
+ case 'end':
+ this.gestureCloseSlice('SyncInterpret', ts);
+ }
+ return true;
+ },
+
+ /**
+ * For HandleTimer events, events will come in pairs with
+ * a tag HandleTimer:
+ * like this:
+ * tracing_mark_write: HandleTimer: start: LookaheadFilterInterpreter
+ * tracing_mark_write: HandleTimer: end: LookaheadFilterInterpreter
+ * which represent the start and the end time of HandleTimer function
+ * inside the certain interpreter in the gesture library.
+ * Take the logs above for example, they are the start and end time
+ * of the HandleTimer function inside LookaheadFilterInterpreter
+ */
+ timerEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const innerEvent = /^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);
+ switch (innerEvent[1]) {
+ case 'start':
+ this.gestureOpenSlice('HandleTimer', ts,
+ {interpreter: innerEvent[2]});
+ break;
+ case 'end':
+ this.gestureCloseSlice('HandleTimer', ts);
+ }
+ return true;
+ }
+ };
+
+ Parser.register(GestureParser);
+
+ return {
+ GestureParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser_test.html
new file mode 100644
index 00000000000..95f5cb5a54b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/gesture_parser_test.html
@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('gestureImport', function() {
+ const lines = [
+ '<...>-1837 [000] ...1 875292.741648: tracing_mark_write: ' +
+ 'log: start: TimerLogOutputs', // 0
+ '<...>-1837 [000] ...1 875292.741651: tracing_mark_write: ' +
+ 'log: end: TimerLogOutputs',
+ '<...>-1837 [000] ...1 875292.742796: tracing_mark_write: ' +
+ 'log: start: LogTimerCallback',
+ '<...>-1837 [000] ...1 875292.742802: tracing_mark_write: ' +
+ 'log: end: LogTimerCallback',
+ '<...>-1837 [000] ...1 875292.742805: tracing_mark_write: ' +
+ 'HandleTimer: start: LoggingFilterInterpreter', // 2
+ '<...>-1837 [000] ...1 875292.742809: tracing_mark_write: ' +
+ 'HandleTimer: start: AppleTrackpadFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742814: tracing_mark_write: ' +
+ 'HandleTimer: start: Cr48ProfileSensorFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742818: tracing_mark_write: ' +
+ 'HandleTimer: start: T5R2CorrectingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742822: tracing_mark_write: ' +
+ 'HandleTimer: start: StuckButtonInhibitorFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742825: tracing_mark_write: ' +
+ 'HandleTimer: start: IntegralGestureFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742829: tracing_mark_write: ' +
+ 'HandleTimer: start: ScalingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742833: tracing_mark_write: ' +
+ 'HandleTimer: start: SplitCorrectingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742836: tracing_mark_write: ' +
+ 'HandleTimer: start: AccelFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742840: tracing_mark_write: ' +
+ 'HandleTimer: start: SensorJumpFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742843: tracing_mark_write: ' +
+ 'HandleTimer: start: BoxFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742846: tracing_mark_write: ' +
+ 'HandleTimer: start: LookaheadFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742853: tracing_mark_write: ' +
+ 'SyncInterpret: start: IirFilterInterpreter', // 14
+ '<...>-1837 [000] ...1 875292.742861: tracing_mark_write: ' +
+ 'SyncInterpret: start: PalmClassifyingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742872: tracing_mark_write: ' +
+ 'SyncInterpret: start: ClickWiggleFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742881: tracing_mark_write: ' +
+ 'SyncInterpret: start: FlingStopFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742887: tracing_mark_write: ' +
+ 'SyncInterpret: start: ImmediateInterpreter',
+ '<...>-1837 [000] ...1 875292.742906: tracing_mark_write: ' +
+ 'SyncInterpret: end: ImmediateInterpreter',
+ '<...>-1837 [000] ...1 875292.742910: tracing_mark_write: ' +
+ 'SyncInterpret: end: FlingStopFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742914: tracing_mark_write: ' +
+ 'SyncInterpret: end: ClickWiggleFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742917: tracing_mark_write: ' +
+ 'SyncInterpret: end: PalmClassifyingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742921: tracing_mark_write: ' +
+ 'SyncInterpret: end: IirFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742926: tracing_mark_write: ' +
+ 'HandleTimer: end: LookaheadFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742929: tracing_mark_write: ' +
+ 'HandleTimer: end: BoxFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742932: tracing_mark_write: ' +
+ 'HandleTimer: end: SensorJumpFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742937: tracing_mark_write: ' +
+ 'HandleTimer: end: AccelFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742940: tracing_mark_write: ' +
+ 'HandleTimer: end: SplitCorrectingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742944: tracing_mark_write: ' +
+ 'HandleTimer: end: ScalingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742949: tracing_mark_write: ' +
+ 'HandleTimer: end: IntegralGestureFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742952: tracing_mark_write: ' +
+ 'HandleTimer: end: StuckButtonInhibitorFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742956: tracing_mark_write: ' +
+ 'HandleTimer: end: T5R2CorrectingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742959: tracing_mark_write: ' +
+ 'HandleTimer: end: Cr48ProfileSensorFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742962: tracing_mark_write: ' +
+ 'HandleTimer: end: AppleTrackpadFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742966: tracing_mark_write: ' +
+ 'HandleTimer: end: LoggingFilterInterpreter',
+ '<...>-1837 [000] ...1 875292.742969: tracing_mark_write: ' +
+ 'log: start: TimerLogOutputs',
+ '<...>-1837 [000] ...1 875292.742973: tracing_mark_write: ' +
+ 'log: end: TimerLogOutputs',
+ '<...>-1837 [000] ...1 875292.795219: tracing_mark_write: ' +
+ 'log: start: LogHardwareState',
+ '<...>-1837 [000] ...1 875292.795231: tracing_mark_write: ' +
+ 'log: end: LogHardwareState'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const gestureThread = threads[0];
+ assert.strictEqual(gestureThread.name, 'gesture');
+ assert.strictEqual(gestureThread.sliceGroup.length, 21);
+ assert.strictEqual('touchpad_gesture',
+ gestureThread.sliceGroup.slices[0].category);
+ assert.strictEqual('GestureLog',
+ gestureThread.sliceGroup.slices[0].title);
+ assert.strictEqual('touchpad_gesture',
+ gestureThread.sliceGroup.slices[2].category);
+ assert.strictEqual('HandleTimer',
+ gestureThread.sliceGroup.slices[2].title);
+ assert.strictEqual('touchpad_gesture',
+ gestureThread.sliceGroup.slices[14].category);
+ assert.strictEqual('SyncInterpret',
+ gestureThread.sliceGroup.slices[14].title);
+ });
+
+ test('unusualStart', function() {
+ const lines = [
+ 'X-30368 [000] ...1 1819362.481867: tracing_mark_write: ' +
+ 'SyncInterpret: start: IirFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481881: tracing_mark_write: ' +
+ 'SyncInterpret: start: PalmClassifyingFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481894: tracing_mark_write: ' +
+ 'SyncInterpret: start: ClickWiggleFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481905: tracing_mark_write: ' +
+ 'SyncInterpret: start: FlingStopFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481912: tracing_mark_write: ' +
+ 'SyncInterpret: start: ImmediateInterpreter',
+ 'X-30368 [000] ...1 1819362.481933: tracing_mark_write: ' +
+ 'SyncInterpret: end: ImmediateInterpreter',
+ 'X-30368 [000] ...1 1819362.481938: tracing_mark_write: ' +
+ 'SyncInterpret: end: FlingStopFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481943: tracing_mark_write: ' +
+ 'SyncInterpret: end: ClickWiggleFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481947: tracing_mark_write: ' +
+ 'SyncInterpret: end: PalmClassifyingFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481952: tracing_mark_write: ' +
+ 'SyncInterpret: end: IirFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481958: tracing_mark_write: ' +
+ 'HandleTimer: end: LookaheadFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481962: tracing_mark_write: ' +
+ 'HandleTimer: end: BoxFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481967: tracing_mark_write: ' +
+ 'HandleTimer: end: SensorJumpFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481973: tracing_mark_write: ' +
+ 'HandleTimer: end: AccelFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481977: tracing_mark_write: ' +
+ 'HandleTimer: end: SplitCorrectingFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481982: tracing_mark_write: ' +
+ 'HandleTimer: end: ScalingFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481988: tracing_mark_write: ' +
+ 'HandleTimer: end: IntegralGestureFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481993: tracing_mark_write: ' +
+ 'HandleTimer: end: StuckButtonInhibitorFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481998: tracing_mark_write: ' +
+ 'HandleTimer: end: T5R2CorrectingFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.482033: tracing_mark_write: ' +
+ 'HandleTimer: end: Cr48ProfileSensorFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.482038: tracing_mark_write: ' +
+ 'HandleTimer: end: AppleTrackpadFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.482043: tracing_mark_write: ' +
+ 'HandleTimer: end: LoggingFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.482047: tracing_mark_write: ' +
+ 'log: start: TimerLogOutputs',
+ 'X-30368 [000] ...1 1819362.482053: tracing_mark_write: ' +
+ 'log: end: TimerLogOutputs'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+ });
+
+ test('importError', function() {
+ const lines = [
+ 'X-30368 [000] ...1 1819362.481912: tracing_mark_write: ' +
+ 'SyncInterpret: start: ImmediateInterpreter',
+ 'X-30368 [000] ...1 1819362.481958: tracing_mark_write: ' +
+ 'HandleTimer: end: LookaheadFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481962: tracing_mark_write: ' +
+ 'HandleTimer: end: BoxFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481967: tracing_mark_write: ' +
+ 'HandleTimer: end: SensorJumpFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481973: tracing_mark_write: ' +
+ 'HandleTimer: end: AccelFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481977: tracing_mark_write: ' +
+ 'HandleTimer: end: SplitCorrectingFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481982: tracing_mark_write: ' +
+ 'HandleTimer: end: ScalingFilterInterpreter',
+ 'X-30368 [000] ...1 1819362.481988: tracing_mark_write: ' +
+ 'HandleTimer: end: IntegralGestureFilterInterpreter'
+ ];
+ const m = newModel(lines.join('\n'));
+
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(m.importWarnings.length, 7);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i2c_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i2c_parser.html
new file mode 100644
index 00000000000..60769de3ad2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i2c_parser.html
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses i2c driver events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux i2c trace events.
+ * @constructor
+ */
+ function I2cParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('i2c_write',
+ I2cParser.prototype.i2cWriteEvent.bind(this));
+ importer.registerEventHandler('i2c_read',
+ I2cParser.prototype.i2cReadEvent.bind(this));
+ importer.registerEventHandler('i2c_reply',
+ I2cParser.prototype.i2cReplyEvent.bind(this));
+ importer.registerEventHandler('i2c_result',
+ I2cParser.prototype.i2cResultEvent.bind(this));
+ }
+
+ // Matches the i2c_write and i2c_reply records
+ const i2cWriteReplyRE = new RegExp(
+ 'i2c-(\\d+) #(\\d+) a=([\\da-fA-F]+) f=([\\da-fA-F]+) l=(\\d+) ' +
+ '(\\[[\\da-fA-F\\-]+\\])');
+ // Matches the i2c_read record
+ const i2cReadRE = /i2c-(\d+) #(\d+) a=([\da-fA-F]+) f=([\da-fA-F]+) l=(\d+)/;
+ // Matches the i2c_result record
+ const i2cResultRE = /i2c-(\d+) n=(\d+) ret=(\d+)/;
+
+ I2cParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses i2c events and sets up state in the importer.
+ */
+ i2cWriteEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = i2cWriteReplyRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const adapterNumber = parseInt(event[1]);
+ const messageNumber = event[2];
+ const address = event[3];
+ const flags = event[4];
+ const dataLength = event[5];
+ const data = event[6];
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'i2c adapter ' + adapterNumber);
+
+ pushLastSliceIfNeeded(thread, event[1], ts);
+
+ thread.lastEntryTitle = 'i2c write';
+ thread.lastEntryTs = ts;
+ thread.lastEntryArgs = {
+ 'Message number': messageNumber,
+ 'Address': address,
+ 'Flags': flags,
+ 'Data Length': dataLength,
+ 'Data': data
+ };
+
+ return true;
+ },
+
+ i2cReadEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = i2cReadRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const adapterNumber = parseInt(event[1]);
+ const messageNumber = event[2];
+ const address = event[3];
+ const flags = event[4];
+ const dataLength = event[5];
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'i2c adapter ' + adapterNumber);
+
+ pushLastSliceIfNeeded(thread, event[1], ts);
+
+ thread.lastEntryTitle = 'i2c read';
+ thread.lastEntryTs = ts;
+ thread.lastEntryArgs = {
+ 'Message number': messageNumber,
+ 'Address': address,
+ 'Flags': flags,
+ 'Data Length': dataLength
+ };
+
+ return true;
+ },
+
+ i2cReplyEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = i2cWriteReplyRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const adapterNumber = parseInt(event[1]);
+ const messageNumber = event[2];
+ const address = event[3];
+ const flags = event[4];
+ const dataLength = event[5];
+ const data = event[6];
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'i2c adapter ' + adapterNumber);
+
+ pushLastSliceIfNeeded(thread, event[1], ts);
+
+ thread.lastEntryTitle = 'i2c reply';
+ thread.lastEntryTs = ts;
+ thread.lastEntryArgs = {
+ 'Message number': messageNumber,
+ 'Address': address,
+ 'Flags': flags,
+ 'Data Length': dataLength,
+ 'Data': data
+ };
+
+ return true;
+ },
+
+ i2cResultEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = i2cResultRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const adapterNumber = parseInt(event[1]);
+ const numMessages = event[2];
+ const ret = event[3];
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'i2c adapter ' + adapterNumber);
+
+ const args = thread.lastEntryArgs;
+ if (args !== undefined) {
+ args['Number of messages'] = numMessages;
+ args.Return = ret;
+ }
+
+ pushLastSliceIfNeeded(thread, event[1], ts);
+
+ thread.lastEntryTitle = undefined;
+ thread.lastEntryTs = undefined;
+ thread.lastEntryArgs = undefined;
+
+ return true;
+ },
+ };
+
+ function pushLastSliceIfNeeded(thread, id, currentTs) {
+ if (thread.lastEntryTs !== undefined) {
+ const duration = currentTs - thread.lastEntryTs;
+ const slice = new tr.model.ThreadSlice(
+ '', thread.lastEntryTitle,
+ ColorScheme.getColorIdForGeneralPurposeString(id),
+ thread.lastEntryTs, thread.lastEntryArgs, duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ }
+
+ Parser.register(I2cParser);
+
+ return {
+ I2cParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i2c_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i2c_parser_test.html
new file mode 100644
index 00000000000..da031719eb1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i2c_parser_test.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('i2cImport', function() {
+ const lines = [
+
+ ' /system/bin/surfaceflinger-516 ( 516) [002] ...1 6481.291425: ' +
+ 'i2c_write: i2c-3 #0 a=020 f=0000 l=2 [15-00]',
+ ' /system/bin/surfaceflinger-516 ( 516) [002] ...1 6481.291602: ' +
+ 'i2c_result: i2c-3 n=1 ret=1',
+ ' kworker/u8:5-9309 ( 9309) [001] ...1 6481.365821: ' +
+ 'i2c_write: i2c-7 #0 a=01d f=0000 l=1 [00]',
+ ' kworker/u8:5-9309 ( 9309) [001] ...1 6481.365823: ' +
+ 'i2c_read: i2c-7 #1 a=01d f=0001 l=1',
+ ' kworker/u8:5-9309 ( 9309) [001] ...1 6481.366730: ' +
+ 'i2c_reply: i2c-7 #1 a=01d f=0001 l=1 [01]',
+ ' kworker/u8:5-9309 ( 9309) [001] ...1 6481.366732: ' +
+ 'i2c_result: i2c-7 n=2 ret=2'
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings,
+ `Expected no import warnings but got ${m.importWarnings}`);
+
+ let threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 2);
+
+ threads = m.findAllThreadsNamed('i2c adapter 3');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 1);
+ let slice = threads[0].sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'i2c write');
+ assert.isDefined(slice.args);
+ assert.strictEqual(slice.args['Message number'], '0');
+ assert.strictEqual(slice.args.Address, '020');
+ assert.strictEqual(slice.args.Flags, '0000');
+ assert.strictEqual(slice.args['Data Length'], '2');
+ assert.strictEqual(slice.args.Data, '[15-00]');
+
+ threads = m.findAllThreadsNamed('i2c adapter 7');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 3);
+
+ slice = threads[0].sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'i2c write');
+ assert.strictEqual(slice.args['Message number'], '0');
+ assert.strictEqual(slice.args.Address, '01d');
+ assert.strictEqual(slice.args.Flags, '0000');
+ assert.strictEqual(slice.args['Data Length'], '1');
+ assert.strictEqual(slice.args.Data, '[00]');
+
+ slice = threads[0].sliceGroup.slices[1];
+ assert.strictEqual(slice.title, 'i2c read');
+ assert.strictEqual(slice.args['Message number'], '1');
+ assert.strictEqual(slice.args.Address, '01d');
+ assert.strictEqual(slice.args.Flags, '0001');
+ assert.strictEqual(slice.args['Data Length'], '1');
+
+ slice = threads[0].sliceGroup.slices[2];
+ assert.strictEqual(slice.title, 'i2c reply');
+ assert.strictEqual(slice.args['Message number'], '1');
+ assert.strictEqual(slice.args.Address, '01d');
+ assert.strictEqual(slice.args.Flags, '0001');
+ assert.strictEqual(slice.args['Data Length'], '1');
+ assert.strictEqual(slice.args.Data, '[01]');
+ assert.strictEqual(slice.args['Number of messages'], '2');
+ assert.strictEqual(slice.args.Return, '2');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser.html
new file mode 100644
index 00000000000..3862b351652
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser.html
@@ -0,0 +1,363 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses i915 driver events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux i915 trace events.
+ * @constructor
+ */
+ function I915Parser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('i915_gem_object_create',
+ I915Parser.prototype.gemObjectCreateEvent.bind(this));
+ importer.registerEventHandler('i915_gem_object_bind',
+ I915Parser.prototype.gemObjectBindEvent.bind(this));
+ importer.registerEventHandler('i915_gem_object_unbind',
+ I915Parser.prototype.gemObjectBindEvent.bind(this));
+ importer.registerEventHandler('i915_gem_object_change_domain',
+ I915Parser.prototype.gemObjectChangeDomainEvent.bind(this));
+ importer.registerEventHandler('i915_gem_object_pread',
+ I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));
+ importer.registerEventHandler('i915_gem_object_pwrite',
+ I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));
+ importer.registerEventHandler('i915_gem_object_fault',
+ I915Parser.prototype.gemObjectFaultEvent.bind(this));
+ importer.registerEventHandler('i915_gem_object_clflush',
+ // NB: reuse destroy handler
+ I915Parser.prototype.gemObjectDestroyEvent.bind(this));
+ importer.registerEventHandler('i915_gem_object_destroy',
+ I915Parser.prototype.gemObjectDestroyEvent.bind(this));
+ importer.registerEventHandler('i915_gem_ring_dispatch',
+ I915Parser.prototype.gemRingDispatchEvent.bind(this));
+ importer.registerEventHandler('i915_gem_ring_flush',
+ I915Parser.prototype.gemRingFlushEvent.bind(this));
+ importer.registerEventHandler('i915_gem_request',
+ I915Parser.prototype.gemRequestEvent.bind(this));
+ importer.registerEventHandler('i915_gem_request_add',
+ I915Parser.prototype.gemRequestEvent.bind(this));
+ importer.registerEventHandler('i915_gem_request_complete',
+ I915Parser.prototype.gemRequestEvent.bind(this));
+ importer.registerEventHandler('i915_gem_request_retire',
+ I915Parser.prototype.gemRequestEvent.bind(this));
+ importer.registerEventHandler('i915_gem_request_wait_begin',
+ I915Parser.prototype.gemRequestEvent.bind(this));
+ importer.registerEventHandler('i915_gem_request_wait_end',
+ I915Parser.prototype.gemRequestEvent.bind(this));
+ importer.registerEventHandler('i915_gem_ring_wait_begin',
+ I915Parser.prototype.gemRingWaitEvent.bind(this));
+ importer.registerEventHandler('i915_gem_ring_wait_end',
+ I915Parser.prototype.gemRingWaitEvent.bind(this));
+ importer.registerEventHandler('i915_reg_rw',
+ I915Parser.prototype.regRWEvent.bind(this));
+ importer.registerEventHandler('i915_flip_request',
+ I915Parser.prototype.flipEvent.bind(this));
+ importer.registerEventHandler('i915_flip_complete',
+ I915Parser.prototype.flipEvent.bind(this));
+ importer.registerEventHandler('intel_gpu_freq_change',
+ I915Parser.prototype.gpuFrequency.bind(this));
+ }
+
+ I915Parser.prototype = {
+ __proto__: Parser.prototype,
+
+ i915FlipOpenSlice(ts, obj, plane) {
+ // use i915_flip_obj_plane?
+ const kthread = this.importer.getOrCreatePseudoThread('i915_flip');
+ kthread.openSliceTS = ts;
+ kthread.openSlice = 'flip:' + obj + '/' + plane;
+ },
+
+ i915FlipCloseSlice(ts, args) {
+ const kthread = this.importer.getOrCreatePseudoThread('i915_flip');
+ if (kthread.openSlice) {
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ kthread.openSliceTS,
+ args,
+ ts - kthread.openSliceTS);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ }
+ kthread.openSlice = undefined;
+ },
+
+ i915GemObjectSlice(ts, eventName, obj, args) {
+ const kthread = this.importer.getOrCreatePseudoThread('i915_gem');
+ kthread.openSlice = eventName + ':' + obj;
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ ts, args, 0);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ },
+
+ i915GemRingSlice(ts, eventName, dev, ring, args) {
+ const kthread = this.importer.getOrCreatePseudoThread('i915_gem_ring');
+ kthread.openSlice = eventName + ':' + dev + '.' + ring;
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ ts, args, 0);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ },
+
+ i915RegSlice(ts, eventName, reg, args) {
+ const kthread = this.importer.getOrCreatePseudoThread('i915_reg');
+ kthread.openSlice = eventName + ':' + reg;
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ ts, args, 0);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ },
+
+ i915FreqChangeSlice(ts, eventName, args) {
+ const kthread = this.importer.getOrCreatePseudoThread('i915_gpu_freq');
+ kthread.openSlice = eventName;
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ ts, args, 0);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ },
+
+ /**
+ * Parses i915 driver events and sets up state in the importer.
+ */
+ gemObjectCreateEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /obj=(\w+), size=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const obj = event[1];
+ const size = parseInt(event[2]);
+ this.i915GemObjectSlice(ts, eventName, obj,
+ {
+ obj,
+ size
+ });
+ return true;
+ },
+
+ gemObjectBindEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ // TODO(sleffler) mappable
+ const event = /obj=(\w+), offset=(\w+), size=(\d+)/.exec(
+ eventBase.details);
+ if (!event) return false;
+
+ const obj = event[1];
+ const offset = event[2];
+ const size = parseInt(event[3]);
+ this.i915ObjectGemSlice(ts, eventName + ':' + obj,
+ {
+ obj,
+ offset,
+ size
+ });
+ return true;
+ },
+
+ gemObjectChangeDomainEvent(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ const event = /obj=(\w+), read=(\w+=>\w+), write=(\w+=>\w+)/.exec(
+ eventBase.details);
+ if (!event) return false;
+
+ const obj = event[1];
+ const read = event[2];
+ const write = event[3];
+ this.i915GemObjectSlice(ts, eventName, obj,
+ {
+ obj,
+ read,
+ write
+ });
+ return true;
+ },
+
+ gemObjectPreadWriteEvent(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ const event = /obj=(\w+), offset=(\d+), len=(\d+)/.exec(
+ eventBase.details);
+ if (!event) return false;
+
+ const obj = event[1];
+ const offset = parseInt(event[2]);
+ const len = parseInt(event[3]);
+ this.i915GemObjectSlice(ts, eventName, obj,
+ {
+ obj,
+ offset,
+ len
+ });
+ return true;
+ },
+
+ gemObjectFaultEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ // TODO(sleffler) writable
+ const event = /obj=(\w+), (\w+) index=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const obj = event[1];
+ const type = event[2];
+ const index = parseInt(event[3]);
+ this.i915GemObjectSlice(ts, eventName, obj,
+ {
+ obj,
+ type,
+ index
+ });
+ return true;
+ },
+
+ gemObjectDestroyEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /obj=(\w+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const obj = event[1];
+ this.i915GemObjectSlice(ts, eventName, obj,
+ {
+ obj
+ });
+ return true;
+ },
+
+ gemRingDispatchEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(
+ eventBase.details);
+ if (!event) return false;
+
+ const dev = parseInt(event[1]);
+ const ring = parseInt(event[2]);
+ const seqno = parseInt(event[3]);
+ this.i915GemRingSlice(ts, eventName, dev, ring,
+ {
+ dev,
+ ring,
+ seqno
+ });
+ return true;
+ },
+
+ gemRingFlushEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev=(\d+), ring=(\w+), invalidate=(\w+), flush=(\w+)/
+ .exec(eventBase.details);
+ if (!event) return false;
+
+ const dev = parseInt(event[1]);
+ const ring = parseInt(event[2]);
+ const invalidate = event[3];
+ const flush = event[4];
+ this.i915GemRingSlice(ts, eventName, dev, ring,
+ {
+ dev,
+ ring,
+ invalidate,
+ flush
+ });
+ return true;
+ },
+
+ gemRequestEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(
+ eventBase.details);
+ if (!event) return false;
+
+ const dev = parseInt(event[1]);
+ const ring = parseInt(event[2]);
+ const seqno = parseInt(event[3]);
+ this.i915GemRingSlice(ts, eventName, dev, ring,
+ {
+ dev,
+ ring,
+ seqno
+ });
+ return true;
+ },
+
+ gemRingWaitEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /dev=(\d+), ring=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const dev = parseInt(event[1]);
+ const ring = parseInt(event[2]);
+ this.i915GemRingSlice(ts, eventName, dev, ring,
+ {
+ dev,
+ ring
+ });
+ return true;
+ },
+
+ regRWEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /(\w+) reg=(\w+), len=(\d+), val=(\(\w+, \w+\))/
+ .exec(eventBase.details);
+ if (!event) return false;
+
+ const rw = event[1];
+ const reg = event[2];
+ const len = event[3];
+ const data = event[3];
+ this.i915RegSlice(ts, rw, reg,
+ {
+ rw,
+ reg,
+ len,
+ data
+ });
+ return true;
+ },
+
+ flipEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /plane=(\d+), obj=(\w+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const plane = parseInt(event[1]);
+ const obj = event[2];
+ if (eventName === 'i915_flip_request') {
+ this.i915FlipOpenSlice(ts, obj, plane);
+ } else {
+ this.i915FlipCloseSlice(ts,
+ {
+ obj,
+ plane
+ });
+ }
+ return true;
+ },
+
+ gpuFrequency(eventName, cpuNumver, pid, ts, eventBase) {
+ const event = /new_freq=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+ const freq = parseInt(event[1]);
+
+ this.i915FreqChangeSlice(ts, eventName, {
+ freq
+ });
+ return true;
+ }
+ };
+
+ Parser.register(I915Parser);
+
+ return {
+ I915Parser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser_test.html
new file mode 100644
index 00000000000..e3564493b96
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/i915_parser_test.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('i915Import', function() {
+ const lines = [
+ // NB: spliced from different traces; mismatched timestamps don't matter
+ ' chrome-1223 [000] 2784.773556: i915_gem_object_pwrite: ' +
+ 'obj=ffff88013f13fc00, offset=0, len=2984',
+ ' chrome-1539 [000] 18420.677750: ' +
+ 'i915_gem_object_change_domain: ' +
+ 'obj=ffff8800a88d1400, read=44=>40, write=00=>40',
+ ' chrome-1539 [000] 18420.677759: i915_gem_object_fault: ' +
+ 'obj=ffff8800a88d1400, GTT index=0 , writable',
+ ' X-964 [000] 2784.774864: i915_flip_request: ' +
+ 'plane=0, obj=ffff88013f0b9a00',
+ ' <idle>-0 [000] 2784.788644: i915_flip_complete: ' +
+ 'plane=0, obj=ffff88013f0b9a00',
+ ' chrome-1539 [001] 18420.681687: i915_gem_request_retire: ' +
+ 'dev=0, ring=1, seqno=1178152',
+ ' chrome-1539 [000] 18422.955688: i915_gem_request_add: ' +
+ 'dev=0, ring=1, seqno=1178364',
+ ' cat-21833 [000] 18422.956832: i915_gem_request_complete: ' +
+ 'dev=0, ring=1, seqno=1178364',
+ ' X-1012 [001] 18420.682511: i915_gem_request_wait_begin: ' +
+ 'dev=0, ring=4, seqno=1178156',
+ ' X-1012 [000] 18422.765707: i915_gem_request_wait_end: ' +
+ 'dev=0, ring=4, seqno=1178359',
+ ' chrome-1539 [000] 18422.955655: i915_gem_ring_flush: ' +
+ 'dev=0, ring=1, invalidate=001e, flush=0040',
+ ' chrome-1539 [000] 18422.955660: i915_gem_ring_dispatch: ' +
+ 'dev=0, ring=1, seqno=1178364',
+ ' chrome-1539 [000] 18420.677772: i915_reg_rw: ' +
+ 'write reg=0x100030, len=8, val=(0xfca9001, 0xfce8007)',
+ ' kworker/u16:2-13998 [005] 1577664.436065: ' +
+ 'intel_gpu_freq_change: new_freq=350'
+
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ let i915GemThread = undefined;
+ let i915FlipThread = undefined;
+ let i915GemRingThread = undefined;
+ let i915RegThread = undefined;
+ let i915GpuFreqThread = undefined;
+ m.getAllThreads().forEach(function(t) {
+ switch (t.name) {
+ case 'i915_gem':
+ i915GemThread = t;
+ break;
+ case 'i915_flip':
+ i915FlipThread = t;
+ break;
+ case 'i915_gem_ring':
+ i915GemRingThread = t;
+ break;
+ case 'i915_reg':
+ i915RegThread = t;
+ break;
+ case 'i915_gpu_freq':
+ i915GpuFreqThread = t;
+ break;
+ default:
+ assert.fail(t, undefined, 'Unexpected thread named ' + t.name);
+ }
+ });
+ assert.isDefined(i915GemThread);
+ assert.isDefined(i915FlipThread);
+ assert.isDefined(i915GemRingThread);
+ assert.isDefined(i915RegThread);
+ assert.isDefined(i915GpuFreqThread);
+
+ assert.strictEqual(i915GemThread.sliceGroup.length, 3);
+
+ assert.strictEqual(i915FlipThread.sliceGroup.length, 1);
+
+ assert.closeTo(
+ 2784.774864 * 1000.0,
+ i915FlipThread.sliceGroup.slices[0].start,
+ 1e-5);
+ assert.closeTo(
+ (2784.788644 - 2784.774864) * 1000.0,
+ i915FlipThread.sliceGroup.slices[0].duration,
+ 1e-5);
+
+ assert.strictEqual(i915GemRingThread.sliceGroup.length, 7);
+ assert.strictEqual(i915RegThread.sliceGroup.length, 1);
+ assert.strictEqual(i915GpuFreqThread.sliceGroup.length, 1);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ion_heap_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ion_heap_parser.html
new file mode 100644
index 00000000000..bb08b7b4cc9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ion_heap_parser.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2019 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses ion heap events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses ion heap trace events.
+ * @constructor
+ */
+ function IonHeapParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('ion_heap_shrink',
+ IonHeapParser.prototype.traceIonHeapShrink.bind(this));
+
+ importer.registerEventHandler('ion_heap_grow',
+ IonHeapParser.prototype.traceIonHeapGrow.bind(this));
+
+ this.model_ = importer.model_;
+ }
+
+ const TestExports = {};
+
+ // Matches the ion_heap_shrink and ion_heap_grow records
+ const ionHeapRE = new RegExp(
+ 'heap_name=(\\S+), len=(\\d+), total_allocated=(\\d+)');
+
+ TestExports.ionHeapRE = ionHeapRE;
+
+
+ IonHeapParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses ion_heap_shrink events and sets up state in the importer.
+ */
+ traceIonHeapShrink(eventName, cpuNumber, pid, ts, eventBase, threadName) {
+ const event = ionHeapRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const name = event[1];
+ const len = parseInt(event[2]);
+ const totalAllocated = parseInt(event[3]);
+ const ionHeap = totalAllocated + len;
+
+ const ctr = this.model_.kernel.getOrCreateCounter(
+ null, name + ' ion heap');
+ if (ctr.numSeries === 0) {
+ ctr.addSeries(new tr.model.CounterSeries('value',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ ctr.name + '.' + 'value')));
+ }
+ ctr.series.forEach(function(series) {
+ series.addCounterSample(ts, ionHeap);
+ });
+
+ return true;
+ },
+
+ /**
+ * Parses ion_heap_grow events and sets up state in the importer.
+ */
+ traceIonHeapGrow(eventName, cpuNumber, pid, ts, eventBase, threadName) {
+ const event = ionHeapRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const name = event[1];
+ const len = parseInt(event[2]);
+ const totalAllocated = parseInt(event[3]);
+ const ionHeap = totalAllocated + len;
+
+ const ctr = this.model_.kernel.getOrCreateCounter(
+ null, name + ' ion heap');
+ if (ctr.numSeries === 0) {
+ ctr.addSeries(new tr.model.CounterSeries('value',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ ctr.name + '.' + 'value')));
+ }
+ ctr.series.forEach(function(series) {
+ series.addCounterSample(ts, ionHeap);
+ });
+
+ return true;
+ }
+ };
+
+ Parser.register(IonHeapParser);
+
+ return {
+ IonHeapParser,
+ _IonHeapParserTestExports: TestExports
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ion_heap_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ion_heap_parser_test.html
new file mode 100644
index 00000000000..3979f56870f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/ion_heap_parser_test.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2019 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('ionHeapRE', function() {
+ const re = tr.e.importer.linux_perf._IonHeapParserTestExports.ionHeapRE;
+ let x = re.exec('ion_heap_shrink: heap_name=system, len=20480, ' +
+ 'total_allocated=181116928');
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], 'system');
+ assert.strictEqual(x[2], '20480');
+ assert.strictEqual(x[3], '181116928');
+
+ x = re.exec('ion_heap_grow: heap_name=system, len=17526784, ' +
+ 'total_allocated=181096448');
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], 'system');
+ assert.strictEqual(x[2], '17526784');
+ assert.strictEqual(x[3], '181096448');
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser.html
new file mode 100644
index 00000000000..0654c9d96be
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser.html
@@ -0,0 +1,271 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses drm driver events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux irq trace events.
+ * @constructor
+ */
+ function IrqParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('irq_handler_entry',
+ IrqParser.prototype.irqHandlerEntryEvent.bind(this));
+ importer.registerEventHandler('irq_handler_exit',
+ IrqParser.prototype.irqHandlerExitEvent.bind(this));
+ importer.registerEventHandler('softirq_raise',
+ IrqParser.prototype.softirqRaiseEvent.bind(this));
+ importer.registerEventHandler('softirq_entry',
+ IrqParser.prototype.softirqEntryEvent.bind(this));
+ importer.registerEventHandler('softirq_exit',
+ IrqParser.prototype.softirqExitEvent.bind(this));
+ importer.registerEventHandler('ipi_entry',
+ IrqParser.prototype.ipiEntryEvent.bind(this));
+ importer.registerEventHandler('ipi_exit',
+ IrqParser.prototype.ipiExitEvent.bind(this));
+ importer.registerEventHandler('preempt_disable',
+ IrqParser.prototype.preemptStartEvent.bind(this));
+ importer.registerEventHandler('preempt_enable',
+ IrqParser.prototype.preemptEndEvent.bind(this));
+ importer.registerEventHandler('irq_disable',
+ IrqParser.prototype.irqoffStartEvent.bind(this));
+ importer.registerEventHandler('irq_enable',
+ IrqParser.prototype.irqoffEndEvent.bind(this));
+ }
+
+ // Matches the irq_handler_entry record
+ const irqHandlerEntryRE = /irq=(\d+) name=(.+)/;
+
+ // Matches the irq_handler_exit record
+ const irqHandlerExitRE = /irq=(\d+) ret=(.+)/;
+
+ // Matches the softirq_raise record
+ const softirqRE = /vec=(\d+) \[action=(.+)\]/;
+
+ // Matches the ipi_exit_
+ const ipiHandlerExitRE = /\((.+)\)/;
+
+ // Matches the preempt_disable/enable records
+ const preemptirqRE = /caller=(.+) parent=(.+)/;
+
+ IrqParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses irq events and sets up state in the mporter.
+ */
+ irqHandlerEntryEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = irqHandlerEntryRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const irq = parseInt(event[1]);
+ const name = event[2];
+
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'irqs cpu ' + cpuNumber);
+ thread.lastEntryTs = ts;
+ thread.irqName = name;
+
+ return true;
+ },
+
+ irqHandlerExitEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = irqHandlerExitRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const irq = parseInt(event[1]);
+ const ret = event[2];
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'irqs cpu ' + cpuNumber);
+
+ if (thread.lastEntryTs !== undefined) {
+ const duration = ts - thread.lastEntryTs;
+ const slice = new tr.model.ThreadSlice(
+ '',
+ 'IRQ (' + thread.irqName + ')',
+ ColorScheme.getColorIdForGeneralPurposeString(event[1]),
+ thread.lastEntryTs, { ret },
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ thread.lastEntryTs = undefined;
+ thread.irqName = undefined;
+ return true;
+ },
+
+ softirqRaiseEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ return true;
+ },
+
+ softirqEntryEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = softirqRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const action = event[2];
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'softirq cpu ' + cpuNumber);
+ thread.lastEntryTs = ts;
+
+ return true;
+ },
+
+ softirqExitEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = softirqRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const vec = parseInt(event[1]);
+ const action = event[2];
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'softirq cpu ' + cpuNumber);
+
+ if (thread.lastEntryTs !== undefined) {
+ const duration = ts - thread.lastEntryTs;
+ const slice = new tr.model.ThreadSlice(
+ '', action,
+ ColorScheme.getColorIdForGeneralPurposeString(event[1]),
+ thread.lastEntryTs, { vec },
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ thread.lastEntryTs = undefined;
+ return true;
+ },
+ /**
+ * Parses ipi events and sets up state in the mporter.
+ */
+ ipiEntryEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'irqs cpu ' + cpuNumber);
+ thread.lastEntryTs = ts;
+
+ return true;
+ },
+
+ ipiExitEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = ipiHandlerExitRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const ipiName = event[1];
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'irqs cpu ' + cpuNumber);
+
+ if (thread.lastEntryTs !== undefined) {
+ const duration = ts - thread.lastEntryTs;
+ const slice = new tr.model.ThreadSlice(
+ '',
+ 'IPI (' + ipiName + ')',
+ ColorScheme.getColorIdForGeneralPurposeString(ipiName),
+ thread.lastEntryTs,
+ {},
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ thread.lastEntryTs = undefined;
+ return true;
+ },
+
+ /**
+ * Parses preempt disable/enable events and sets up state in the importer.
+ */
+ preemptStartEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = preemptirqRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'preempt cpu ' + cpuNumber);
+ thread.lastEntryTs = ts;
+
+ thread.preemptStartCaller = event[1];
+ thread.preemptStartParent = event[2];
+ return true;
+ },
+
+ preemptEndEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = preemptirqRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'preempt cpu ' + cpuNumber);
+
+ thread.preemptEndCaller = event[1];
+ thread.preemptEndParent = event[2];
+
+ if (thread.lastEntryTs !== undefined) {
+ const duration = ts - thread.lastEntryTs;
+ const slice = new tr.model.ThreadSlice(
+ '',
+ thread.preemptStartParent + ': ' + thread.preemptStartCaller,
+ ColorScheme.getColorIdForGeneralPurposeString(
+ thread.preemptEndCaller),
+ thread.lastEntryTs, {},
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ thread.lastEntryTs = undefined;
+ return true;
+ },
+
+ /**
+ * Parses irqoff disable/enable events and sets up state in the importer.
+ */
+ irqoffStartEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = preemptirqRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'irqoff cpu ' + cpuNumber);
+ thread.lastEntryTs = ts;
+
+ thread.irqoffStartCaller = event[1];
+ thread.irqoffStartParent = event[2];
+ return true;
+ },
+
+ irqoffEndEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = preemptirqRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const thread = this.importer.getOrCreatePseudoThread(
+ 'irqoff cpu ' + cpuNumber);
+
+ thread.irqoffEndCaller = event[1];
+ thread.irqoffEndParent = event[2];
+
+ if (thread.lastEntryTs !== undefined) {
+ const duration = ts - thread.lastEntryTs;
+ const slice = new tr.model.ThreadSlice(
+ '',
+ thread.irqoffStartParent + ': ' + thread.irqoffStartCaller,
+ ColorScheme.getColorIdForGeneralPurposeString(
+ thread.irqoffEndCaller),
+ thread.lastEntryTs, {},
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ thread.lastEntryTs = undefined;
+ return true;
+ }
+ };
+
+ Parser.register(IrqParser);
+
+ return {
+ IrqParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser_test.html
new file mode 100644
index 00000000000..84080971650
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/irq_parser_test.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('irqImport', function() {
+ const lines = [
+ ' kworker/u4:1-31907 (31907) [001] d.h3 14063.748288: ' +
+ 'irq_handler_entry: irq=27 name=arch_timer',
+ ' kworker/u4:1-31907 (31907) [001] dNh3 14063.748384: ' +
+ 'irq_handler_exit: irq=27 ret=handled',
+ ' kworker/u4:2-31908 (31908) [000] ..s3 14063.477231: ' +
+ 'softirq_entry: vec=9 [action=RCU]',
+ ' kworker/u4:2-31908 (31908) [000] ..s3 14063.477246: ' +
+ 'softirq_exit: vec=9 [action=RCU]',
+ ' RenderThread-2978 ( 2794) [002] dN.1 62828.421805: ' +
+ 'ipi_entry: (Rescheduling interrupts)',
+ ' RenderThread-2978 ( 2794) [002] dN.1 62828.421809: ' +
+ 'ipi_exit: (Rescheduling interrupts)',
+ ' RenderThread-2978 ( 2794) [002] dN.1 62829.421809: ' +
+ 'preempt_disable: caller=avc_lookup parent=avc_has_perm_noaudit',
+ ' RenderThread-2978 ( 2794) [002] dN.1 62830.421809: ' +
+ 'preempt_enable: caller=avc_lookup parent=avc_has_perm_noaudit',
+ ' kworker/u1:2-31908 (31908) [004] ..s3 14163.477231: ' +
+ 'irq_disable: caller=avc_lookup parent=avc_has_perm_noaudit',
+ ' kworker/u1:2-31908 (31908) [004] ..s3 14163.477246: ' +
+ 'irq_enable: caller=avc_lookup parent=avc_has_perm_noaudit'
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ let threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 5);
+
+ threads = m.findAllThreadsNamed('irqs cpu 1');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 1);
+
+ threads = m.findAllThreadsNamed('softirq cpu 0');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 1);
+
+ threads = m.findAllThreadsNamed('irqs cpu 2');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 1);
+
+ threads = m.findAllThreadsNamed('preempt cpu 2');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 1);
+
+ threads = m.findAllThreadsNamed('irqoff cpu 4');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser.html
new file mode 100644
index 00000000000..b8f6f9aa915
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses graph_ent and graph_ret events that were inserted by
+ * the Linux kernel's function graph trace.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const LinuxPerfParser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses graph_ent and graph_ret events that were inserted by the Linux
+ * kernel's function graph trace.
+ * @constructor
+ */
+ function KernelFuncParser(importer) {
+ LinuxPerfParser.call(this, importer);
+
+ importer.registerEventHandler('graph_ent',
+ KernelFuncParser.prototype.traceKernelFuncEnterEvent.
+ bind(this));
+ importer.registerEventHandler('graph_ret',
+ KernelFuncParser.prototype.traceKernelFuncReturnEvent.
+ bind(this));
+
+ this.model_ = importer.model_;
+ this.ppids_ = {};
+ }
+
+ const TestExports = {};
+
+ const funcEnterRE = new RegExp('func=(.+)');
+ TestExports.funcEnterRE = funcEnterRE;
+
+ KernelFuncParser.prototype = {
+ __proto__: LinuxPerfParser.prototype,
+
+ traceKernelFuncEnterEvent(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ const eventData = funcEnterRE.exec(eventBase.details);
+ if (!eventData) return false;
+
+ if (eventBase.tgid === undefined) {
+ return false;
+ }
+
+ const tgid = parseInt(eventBase.tgid);
+ const name = eventData[1];
+ const thread = this.model_.getOrCreateProcess(tgid)
+ .getOrCreateThread(pid);
+ thread.name = eventBase.threadName;
+
+ const slices = thread.kernelSliceGroup;
+ if (!slices.isTimestampValidForBeginOrEnd(ts)) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Timestamps are moving backward.'
+ });
+ return false;
+ }
+
+ const slice = slices.beginSlice(null, name, ts, {});
+
+ return true;
+ },
+
+ traceKernelFuncReturnEvent(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ if (eventBase.tgid === undefined) {
+ return false;
+ }
+
+ const tgid = parseInt(eventBase.tgid);
+ const thread = this.model_.getOrCreateProcess(tgid)
+ .getOrCreateThread(pid);
+ thread.name = eventBase.threadName;
+
+ const slices = thread.kernelSliceGroup;
+ if (!slices.isTimestampValidForBeginOrEnd(ts)) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Timestamps are moving backward.'
+ });
+ return false;
+ }
+
+ if (slices.openSliceCount > 0) {
+ slices.endSlice(ts);
+ }
+
+ return true;
+ }
+ };
+
+ LinuxPerfParser.register(KernelFuncParser);
+
+ return {
+ KernelFuncParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser_test.html
new file mode 100644
index 00000000000..16f2a13c934
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/kfunc_parser_test.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('kernelFunctionParser', function() {
+ const lines = [
+ 'Binder_2-127 ( 127) [001] .... 3431.906759: graph_ent: func=sys_write',
+ 'Binder_2-127 ( 127) [001] .... 3431.906769: graph_ret: func=sys_write',
+ 'Binder_2-127 ( 127) [001] .... 3431.906785: graph_ent: func=sys_write',
+ 'Binder_2-127 ( 127) [001] ...1 3431.906798: tracing_mark_write: B|' +
+ '127|dequeueBuffer',
+ 'Binder_2-127 ( 127) [001] .... 3431.906802: graph_ret: func=sys_write',
+ 'Binder_2-127 ( 127) [001] .... 3431.906842: graph_ent: func=sys_write',
+ 'Binder_2-127 ( 127) [001] ...1 3431.906849: tracing_mark_write: E',
+ 'Binder_2-127 ( 127) [001] .... 3431.906853: graph_ret: func=sys_write',
+ 'Binder_2-127 ( 127) [001] .... 3431.906896: graph_ent: func=sys_write',
+ 'Binder_2-127 ( 127) [001] .... 3431.906906: graph_ret: func=sys_write'
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ const process = m.processes[127];
+ assert.isDefined(process);
+
+ const thread = process.threads[127];
+ assert.isDefined(thread);
+
+ const slices = thread.sliceGroup.slices;
+ assert.strictEqual(thread.sliceGroup.length, 7);
+
+ // Slice 0 is an un-split sys_write
+ assert.strictEqual(slices[0].title, 'sys_write');
+
+ // Slices 1 & 3 are a split sys_write
+ assert.strictEqual(slices[1].title, 'sys_write');
+ assert.strictEqual(slices[2].title, 'dequeueBuffer');
+ assert.strictEqual(slices[3].title, 'sys_write (cont.)');
+
+ // Slices 4 & 5 are a split sys_write with the dequeueBuffer in between
+ assert.strictEqual(slices[4].title, 'sys_write');
+ assert.strictEqual(slices[5].title, 'sys_write (cont.)');
+
+ // Slice 6 is another un-split sys_write
+ assert.strictEqual(slices[6].title, 'sys_write');
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser.html
new file mode 100644
index 00000000000..38c54d176fc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser.html
@@ -0,0 +1,659 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses Mali DDK/kernel events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses Mali DDK/kernel trace events.
+ * @constructor
+ */
+ function MaliParser(importer) {
+ Parser.call(this, importer);
+
+ // kernel DVFS events
+ importer.registerEventHandler('mali_dvfs_event',
+ MaliParser.prototype.dvfsEventEvent.bind(this));
+ importer.registerEventHandler('mali_dvfs_set_clock',
+ MaliParser.prototype.dvfsSetClockEvent.bind(this));
+ importer.registerEventHandler('mali_dvfs_set_voltage',
+ MaliParser.prototype.dvfsSetVoltageEvent.bind(this));
+
+ // kernel Mali hw counter events
+ this.addJMCounter('mali_hwc_MESSAGES_SENT', 'Messages Sent');
+ this.addJMCounter('mali_hwc_MESSAGES_RECEIVED', 'Messages Received');
+ this.addJMCycles('mali_hwc_GPU_ACTIVE', 'GPU Active');
+ this.addJMCycles('mali_hwc_IRQ_ACTIVE', 'IRQ Active');
+
+ for (let i = 0; i < 7; i++) {
+ const jobStr = 'JS' + i;
+ const jobHWCStr = 'mali_hwc_' + jobStr;
+ this.addJMCounter(jobHWCStr + '_JOBS', jobStr + ' Jobs');
+ this.addJMCounter(jobHWCStr + '_TASKS', jobStr + ' Tasks');
+ this.addJMCycles(jobHWCStr + '_ACTIVE', jobStr + ' Active');
+ this.addJMCycles(jobHWCStr + '_WAIT_READ', jobStr + ' Wait Read');
+ this.addJMCycles(jobHWCStr + '_WAIT_ISSUE', jobStr + ' Wait Issue');
+ this.addJMCycles(jobHWCStr + '_WAIT_DEPEND', jobStr + ' Wait Depend');
+ this.addJMCycles(jobHWCStr + '_WAIT_FINISH', jobStr + ' Wait Finish');
+ }
+
+ this.addTilerCounter('mali_hwc_TRIANGLES', 'Triangles');
+ this.addTilerCounter('mali_hwc_QUADS', 'Quads');
+ this.addTilerCounter('mali_hwc_POLYGONS', 'Polygons');
+ this.addTilerCounter('mali_hwc_POINTS', 'Points');
+ this.addTilerCounter('mali_hwc_LINES', 'Lines');
+ this.addTilerCounter('mali_hwc_VCACHE_HIT', 'VCache Hit');
+ this.addTilerCounter('mali_hwc_VCACHE_MISS', 'VCache Miss');
+ this.addTilerCounter('mali_hwc_FRONT_FACING', 'Front Facing');
+ this.addTilerCounter('mali_hwc_BACK_FACING', 'Back Facing');
+ this.addTilerCounter('mali_hwc_PRIM_VISIBLE', 'Prim Visible');
+ this.addTilerCounter('mali_hwc_PRIM_CULLED', 'Prim Culled');
+ this.addTilerCounter('mali_hwc_PRIM_CLIPPED', 'Prim Clipped');
+
+ this.addTilerCounter('mali_hwc_WRBUF_HIT', 'Wrbuf Hit');
+ this.addTilerCounter('mali_hwc_WRBUF_MISS', 'Wrbuf Miss');
+ this.addTilerCounter('mali_hwc_WRBUF_LINE', 'Wrbuf Line');
+ this.addTilerCounter('mali_hwc_WRBUF_PARTIAL', 'Wrbuf Partial');
+ this.addTilerCounter('mali_hwc_WRBUF_STALL', 'Wrbuf Stall');
+
+ this.addTilerCycles('mali_hwc_ACTIVE', 'Tiler Active');
+ this.addTilerCycles('mali_hwc_INDEX_WAIT', 'Index Wait');
+ this.addTilerCycles('mali_hwc_INDEX_RANGE_WAIT', 'Index Range Wait');
+ this.addTilerCycles('mali_hwc_VERTEX_WAIT', 'Vertex Wait');
+ this.addTilerCycles('mali_hwc_PCACHE_WAIT', 'Pcache Wait');
+ this.addTilerCycles('mali_hwc_WRBUF_WAIT', 'Wrbuf Wait');
+ this.addTilerCycles('mali_hwc_BUS_READ', 'Bus Read');
+ this.addTilerCycles('mali_hwc_BUS_WRITE', 'Bus Write');
+
+ this.addTilerCycles('mali_hwc_TILER_UTLB_STALL', 'Tiler UTLB Stall');
+ this.addTilerCycles('mali_hwc_TILER_UTLB_HIT', 'Tiler UTLB Hit');
+
+ this.addFragCycles('mali_hwc_FRAG_ACTIVE', 'Active');
+ /* NB: don't propagate spelling mistakes to labels */
+ this.addFragCounter('mali_hwc_FRAG_PRIMATIVES', 'Primitives');
+ this.addFragCounter('mali_hwc_FRAG_PRIMATIVES_DROPPED',
+ 'Primitives Dropped');
+ this.addFragCycles('mali_hwc_FRAG_CYCLE_DESC', 'Descriptor Processing');
+ this.addFragCycles('mali_hwc_FRAG_CYCLES_PLR', 'PLR Processing??');
+ this.addFragCycles('mali_hwc_FRAG_CYCLES_VERT', 'Vertex Processing');
+ this.addFragCycles('mali_hwc_FRAG_CYCLES_TRISETUP', 'Triangle Setup');
+ this.addFragCycles('mali_hwc_FRAG_CYCLES_RAST', 'Rasterization???');
+ this.addFragCounter('mali_hwc_FRAG_THREADS', 'Threads');
+ this.addFragCounter('mali_hwc_FRAG_DUMMY_THREADS', 'Dummy Threads');
+ this.addFragCounter('mali_hwc_FRAG_QUADS_RAST', 'Quads Rast');
+ this.addFragCounter('mali_hwc_FRAG_QUADS_EZS_TEST', 'Quads EZS Test');
+ this.addFragCounter('mali_hwc_FRAG_QUADS_EZS_KILLED', 'Quads EZS Killed');
+ this.addFragCounter('mali_hwc_FRAG_QUADS_LZS_TEST', 'Quads LZS Test');
+ this.addFragCounter('mali_hwc_FRAG_QUADS_LZS_KILLED', 'Quads LZS Killed');
+ this.addFragCycles('mali_hwc_FRAG_CYCLE_NO_TILE', 'No Tiles');
+ this.addFragCounter('mali_hwc_FRAG_NUM_TILES', 'Tiles');
+ this.addFragCounter('mali_hwc_FRAG_TRANS_ELIM', 'Transactions Eliminated');
+
+ this.addComputeCycles('mali_hwc_COMPUTE_ACTIVE', 'Active');
+ this.addComputeCounter('mali_hwc_COMPUTE_TASKS', 'Tasks');
+ this.addComputeCounter('mali_hwc_COMPUTE_THREADS', 'Threads Started');
+ this.addComputeCycles('mali_hwc_COMPUTE_CYCLES_DESC',
+ 'Waiting for Descriptors');
+
+ this.addTripipeCycles('mali_hwc_TRIPIPE_ACTIVE', 'Active');
+
+ this.addArithCounter('mali_hwc_ARITH_WORDS', 'Instructions (/Pipes)');
+ this.addArithCycles('mali_hwc_ARITH_CYCLES_REG',
+ 'Reg scheduling stalls (/Pipes)');
+ this.addArithCycles('mali_hwc_ARITH_CYCLES_L0',
+ 'L0 cache miss stalls (/Pipes)');
+ this.addArithCounter('mali_hwc_ARITH_FRAG_DEPEND',
+ 'Frag dep check failures (/Pipes)');
+
+ this.addLSCounter('mali_hwc_LS_WORDS', 'Instruction Words Completed');
+ this.addLSCounter('mali_hwc_LS_ISSUES', 'Full Pipeline Issues');
+ this.addLSCounter('mali_hwc_LS_RESTARTS', 'Restarts (unpairable insts)');
+ this.addLSCounter('mali_hwc_LS_REISSUES_MISS',
+ 'Pipeline reissue (cache miss/uTLB)');
+ this.addLSCounter('mali_hwc_LS_REISSUES_VD',
+ 'Pipeline reissue (varying data)');
+ /* TODO(sleffler) fix kernel event typo */
+ this.addLSCounter('mali_hwc_LS_REISSUE_ATTRIB_MISS',
+ 'Pipeline reissue (attribute cache miss)');
+ this.addLSCounter('mali_hwc_LS_REISSUE_NO_WB', 'Writeback not used');
+
+ this.addTexCounter('mali_hwc_TEX_WORDS', 'Words');
+ this.addTexCounter('mali_hwc_TEX_BUBBLES', 'Bubbles');
+ this.addTexCounter('mali_hwc_TEX_WORDS_L0', 'Words L0');
+ this.addTexCounter('mali_hwc_TEX_WORDS_DESC', 'Words Desc');
+ this.addTexCounter('mali_hwc_TEX_THREADS', 'Threads');
+ this.addTexCounter('mali_hwc_TEX_RECIRC_FMISS', 'Recirc due to Full Miss');
+ this.addTexCounter('mali_hwc_TEX_RECIRC_DESC', 'Recirc due to Desc Miss');
+ this.addTexCounter('mali_hwc_TEX_RECIRC_MULTI', 'Recirc due to Multipass');
+ this.addTexCounter('mali_hwc_TEX_RECIRC_PMISS',
+ 'Recirc due to Partial Cache Miss');
+ this.addTexCounter('mali_hwc_TEX_RECIRC_CONF',
+ 'Recirc due to Cache Conflict');
+
+ this.addLSCCounter('mali_hwc_LSC_READ_HITS', 'Read Hits');
+ this.addLSCCounter('mali_hwc_LSC_READ_MISSES', 'Read Misses');
+ this.addLSCCounter('mali_hwc_LSC_WRITE_HITS', 'Write Hits');
+ this.addLSCCounter('mali_hwc_LSC_WRITE_MISSES', 'Write Misses');
+ this.addLSCCounter('mali_hwc_LSC_ATOMIC_HITS', 'Atomic Hits');
+ this.addLSCCounter('mali_hwc_LSC_ATOMIC_MISSES', 'Atomic Misses');
+ this.addLSCCounter('mali_hwc_LSC_LINE_FETCHES', 'Line Fetches');
+ this.addLSCCounter('mali_hwc_LSC_DIRTY_LINE', 'Dirty Lines');
+ this.addLSCCounter('mali_hwc_LSC_SNOOPS', 'Snoops');
+
+ this.addAXICounter('mali_hwc_AXI_TLB_STALL', 'Address channel stall');
+ this.addAXICounter('mali_hwc_AXI_TLB_MISS', 'Cache Miss');
+ this.addAXICounter('mali_hwc_AXI_TLB_TRANSACTION', 'Transactions');
+ this.addAXICounter('mali_hwc_LS_TLB_MISS', 'LS Cache Miss');
+ this.addAXICounter('mali_hwc_LS_TLB_HIT', 'LS Cache Hit');
+ this.addAXICounter('mali_hwc_AXI_BEATS_READ', 'Read Beats');
+ this.addAXICounter('mali_hwc_AXI_BEATS_WRITE', 'Write Beats');
+
+ this.addMMUCounter('mali_hwc_MMU_TABLE_WALK', 'Page Table Walks');
+ this.addMMUCounter('mali_hwc_MMU_REPLAY_MISS',
+ 'Cache Miss from Replay Buffer');
+ this.addMMUCounter('mali_hwc_MMU_REPLAY_FULL', 'Replay Buffer Full');
+ this.addMMUCounter('mali_hwc_MMU_NEW_MISS', 'Cache Miss on New Request');
+ this.addMMUCounter('mali_hwc_MMU_HIT', 'Cache Hit');
+
+ this.addMMUCycles('mali_hwc_UTLB_STALL', 'UTLB Stalled');
+ this.addMMUCycles('mali_hwc_UTLB_REPLAY_MISS', 'UTLB Replay Miss');
+ this.addMMUCycles('mali_hwc_UTLB_REPLAY_FULL', 'UTLB Replay Full');
+ this.addMMUCycles('mali_hwc_UTLB_NEW_MISS', 'UTLB New Miss');
+ this.addMMUCycles('mali_hwc_UTLB_HIT', 'UTLB Hit');
+
+ this.addL2Counter('mali_hwc_L2_READ_BEATS', 'Read Beats');
+ this.addL2Counter('mali_hwc_L2_WRITE_BEATS', 'Write Beats');
+ this.addL2Counter('mali_hwc_L2_ANY_LOOKUP', 'Any Lookup');
+ this.addL2Counter('mali_hwc_L2_READ_LOOKUP', 'Read Lookup');
+ this.addL2Counter('mali_hwc_L2_SREAD_LOOKUP', 'Shareable Read Lookup');
+ this.addL2Counter('mali_hwc_L2_READ_REPLAY', 'Read Replayed');
+ this.addL2Counter('mali_hwc_L2_READ_SNOOP', 'Read Snoop');
+ this.addL2Counter('mali_hwc_L2_READ_HIT', 'Read Cache Hit');
+ this.addL2Counter('mali_hwc_L2_CLEAN_MISS', 'CleanUnique Miss');
+ this.addL2Counter('mali_hwc_L2_WRITE_LOOKUP', 'Write Lookup');
+ this.addL2Counter('mali_hwc_L2_SWRITE_LOOKUP', 'Shareable Write Lookup');
+ this.addL2Counter('mali_hwc_L2_WRITE_REPLAY', 'Write Replayed');
+ this.addL2Counter('mali_hwc_L2_WRITE_SNOOP', 'Write Snoop');
+ this.addL2Counter('mali_hwc_L2_WRITE_HIT', 'Write Cache Hit');
+ this.addL2Counter('mali_hwc_L2_EXT_READ_FULL', 'ExtRD with BIU Full');
+ this.addL2Counter('mali_hwc_L2_EXT_READ_HALF', 'ExtRD with BIU >1/2 Full');
+ this.addL2Counter('mali_hwc_L2_EXT_WRITE_FULL', 'ExtWR with BIU Full');
+ this.addL2Counter('mali_hwc_L2_EXT_WRITE_HALF', 'ExtWR with BIU >1/2 Full');
+
+ this.addL2Counter('mali_hwc_L2_EXT_READ', 'External Read (ExtRD)');
+ this.addL2Counter('mali_hwc_L2_EXT_READ_LINE', 'ExtRD (linefill)');
+ this.addL2Counter('mali_hwc_L2_EXT_WRITE', 'External Write (ExtWR)');
+ this.addL2Counter('mali_hwc_L2_EXT_WRITE_LINE', 'ExtWR (linefill)');
+ this.addL2Counter('mali_hwc_L2_EXT_WRITE_SMALL', 'ExtWR (burst size <64B)');
+ this.addL2Counter('mali_hwc_L2_EXT_BARRIER', 'External Barrier');
+ this.addL2Counter('mali_hwc_L2_EXT_AR_STALL', 'Address Read stalls');
+ this.addL2Counter('mali_hwc_L2_EXT_R_BUF_FULL',
+ 'Response Buffer full stalls');
+ this.addL2Counter('mali_hwc_L2_EXT_RD_BUF_FULL',
+ 'Read Data Buffer full stalls');
+ this.addL2Counter('mali_hwc_L2_EXT_R_RAW', 'RAW hazard stalls');
+ this.addL2Counter('mali_hwc_L2_EXT_W_STALL', 'Write Data stalls');
+ this.addL2Counter('mali_hwc_L2_EXT_W_BUF_FULL', 'Write Data Buffer full');
+ this.addL2Counter('mali_hwc_L2_EXT_R_W_HAZARD', 'WAW or WAR hazard stalls');
+ this.addL2Counter('mali_hwc_L2_TAG_HAZARD', 'Tag hazard replays');
+ this.addL2Cycles('mali_hwc_L2_SNOOP_FULL', 'Snoop buffer full');
+ this.addL2Cycles('mali_hwc_L2_REPLAY_FULL', 'Replay buffer full');
+
+ // DDK events (from X server)
+ importer.registerEventHandler('tracing_mark_write:mali_driver',
+ MaliParser.prototype.maliDDKEvent.bind(this));
+
+ // Mali job scheduler events from Exynos kernels
+ importer.registerEventHandler('mali_job_systrace_event_start',
+ MaliParser.prototype.maliJobEvent.bind(this));
+ importer.registerEventHandler('mali_job_systrace_event_stop',
+ MaliParser.prototype.maliJobEvent.bind(this));
+
+ this.model_ = importer.model_;
+
+ this.deferredJobs_ = {}; // <job type>: [<deferred jobs>]
+ }
+
+ MaliParser.prototype = {
+ __proto__: Parser.prototype,
+
+ maliDDKOpenSlice(pid, tid, ts, func, blockinfo) {
+ const thread = this.importer.model_.getOrCreateProcess(pid)
+ .getOrCreateThread(tid);
+ const funcArgs = /^([\w\d_]*)(?:\(\))?:?\s*(.*)$/.exec(func);
+ thread.sliceGroup.beginSlice('gpu-driver', funcArgs[1], ts,
+ { 'args': funcArgs[2],
+ blockinfo });
+ },
+
+ maliDDKCloseSlice(pid, tid, ts, args, blockinfo) {
+ const thread = this.importer.model_.getOrCreateProcess(pid)
+ .getOrCreateThread(tid);
+ if (!thread.sliceGroup.openSliceCount) {
+ // Discard unmatched ends.
+ return;
+ }
+ thread.sliceGroup.endSlice(ts);
+ },
+
+ /**
+ * Deduce the format of Mali perf events.
+ *
+ * @return {RegExp} the regular expression for parsing data when the format
+ * is recognized; otherwise null.
+ */
+ autoDetectLineRE(line) {
+ // Matches Mali perf events with thread info
+ const lineREWithThread =
+ /^\s*\(([\w\-]*)\)\s*(\w+):\s*([\w\\\/\.\-]*@\d*):?\s*(.*)$/;
+ if (lineREWithThread.test(line)) {
+ return lineREWithThread;
+ }
+
+ // Matches old-style Mali perf events
+ const lineRENoThread = /^s*()(\w+):\s*([\w\\\/.\-]*):?\s*(.*)$/;
+ if (lineRENoThread.test(line)) {
+ return lineRENoThread;
+ }
+ return null;
+ },
+
+ lineRE: null,
+
+ /**
+ * Parses maliDDK events and sets up state in the importer.
+ * events will come in pairs with a cros_trace_print_enter
+ * like this (line broken here for formatting):
+ *
+ * tracing_mark_write: mali_driver: (mali-012345) cros_trace_print_enter: \
+ * gles/src/texture/mali_gles_texture_slave.c@1505: gles2_texturep_upload
+ *
+ * and a cros_trace_print_exit like this:
+ *
+ * tracing_mark_write: mali_driver: (mali-012345) cros_trace_print_exit: \
+ * gles/src/texture/mali_gles_texture_slave.c@1505:
+ */
+ maliDDKEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ if (this.lineRE === null) {
+ this.lineRE = this.autoDetectLineRE(eventBase.details);
+ if (this.lineRE === null) return false;
+ }
+ const maliEvent = this.lineRE.exec(eventBase.details);
+ // Old-style Mali perf events have no thread id, so make one.
+ const tid = (maliEvent[1] === '' ? 'mali' : maliEvent[1]);
+ switch (maliEvent[2]) {
+ case 'cros_trace_print_enter':
+ this.maliDDKOpenSlice(pid, tid, ts, maliEvent[4],
+ maliEvent[3]);
+ break;
+ case 'cros_trace_print_exit':
+ this.maliDDKCloseSlice(pid, tid, ts, [], maliEvent[3]);
+ }
+ return true;
+ },
+
+ /**
+ * Parses Mali Job events and sets up state in the importer.
+ * Events come in pairs like this:
+ *
+ * tracing_mark_write: S|7229|vertex-job|62|0|0|0|0|f46aed08|722962164982...
+ * tracing_mark_write: F|7229|vertex-job|62|0|0|0|0|f46aed08|722962164982...
+ *
+ * The '|' separated fields are (numbers correspond to jobEventRE groups
+ * below):
+ * 1: 'S'tart / 'F'inish
+ * 2: tgid that submitted the job
+ * 3: job type
+ * 4: job id
+ * 5,6: dependency 0: job id, dependency type
+ * 7,8: dependency 1: job id, dependency type
+ * 9: ctx id
+ * 10: unique job submission id
+ */
+ maliJobEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const jobEventRE =
+ // eslint-disable-next-line max-len
+ /^.*tracing_mark_write: (S|F)\|(\d+)\|(\w+)-job\|(\d+)\|(\d+)\|(\d+)\|(\d+)\|(\d+)\|([a-z0-9]+)\|(\d+)$/;
+ const jobEvent = jobEventRE.exec(eventBase.details);
+ if (!jobEvent) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ args: 'unexpected mali_job_systrace_event_* event syntax'
+ });
+ return;
+ }
+ const jobType = jobEvent[3];
+ const jobId = jobEvent[4];
+ const thread = this.importer.model_.getOrCreateProcess(0)
+ .getOrCreateThread('mali:' + jobType);
+ switch (jobEvent[1]) {
+ case 'S': {
+ /* The HW has a two-deep ("head", "next") job FIFO for each job
+ * type. Start events indicate when the job was pushed into the FIFO,
+ * *not* when the hardware actually starts executing the job. It
+ * either starts ~immediately if the FIFO was empty, or when the
+ * previous job finishes otherwise.
+ *
+ * So we can get events in the order S|0, S|1, F|0, F|1, but we want
+ * to turn that into a '0' slice from S|0 to F|0, and another '1'
+ * slice from F|0 to F|1. In other words, when there is already a
+ * slice open, we want to defer creating a slice for this job until we
+ * finish the previous slice, then immediately open the slice for this
+ * event using the same timestamp.
+ */
+ const args = {
+ ctx: jobEvent[9],
+ pid: parseInt(jobEvent[2], 10),
+ dep0: parseInt(jobEvent[5], 10),
+ dep1: parseInt(jobEvent[7], 10)
+ };
+ if (thread.sliceGroup.openSliceCount) {
+ if (!(jobType in this.deferredJobs_)) {
+ this.deferredJobs_[jobType] = [];
+ }
+ this.deferredJobs_[jobType].push({id: jobId, args});
+ } else {
+ thread.sliceGroup.beginSlice(null, jobId, ts, args);
+ }
+ } break;
+ case 'F': {
+ if (!thread.sliceGroup.openSliceCount) {
+ // Discard unmatched ends.
+ return;
+ }
+ if (thread.sliceGroup.mostRecentlyOpenedPartialSlice.title !==
+ jobId) {
+ this.model_.importWarning({
+ type: 'invalid event nesting',
+ message: 'non-sequential jobs in same mali job slot'
+ });
+ }
+ thread.sliceGroup.endSlice(ts);
+ const deferredJobs = this.deferredJobs_[jobType];
+ if (deferredJobs && deferredJobs.length) {
+ const job = deferredJobs.shift();
+ thread.sliceGroup.beginSlice(null, job.id, ts, job.args);
+ }
+ } break;
+ }
+ return true;
+ },
+
+ /*
+ * Kernel event support.
+ */
+
+ dvfsSample(counterName, seriesName, ts, s) {
+ const value = parseInt(s);
+ const counter = this.model_.kernel.
+ getOrCreateCounter('DVFS', counterName);
+ if (counter.numSeries === 0) {
+ counter.addSeries(new tr.model.CounterSeries(seriesName,
+ ColorScheme.getColorIdForGeneralPurposeString(counter.name)));
+ }
+ counter.series.forEach(function(series) {
+ series.addCounterSample(ts, value);
+ });
+ },
+
+ dvfsEventEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /utilization=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ this.dvfsSample('DVFS Utilization', 'utilization', ts, event[1]);
+ return true;
+ },
+
+ dvfsSetClockEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /frequency=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ this.dvfsSample('DVFS Frequency', 'frequency', ts, event[1]);
+ return true;
+ },
+
+ dvfsSetVoltageEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /voltage=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ this.dvfsSample('DVFS Voltage', 'voltage', ts, event[1]);
+ return true;
+ },
+
+ hwcSample(cat, counterName, seriesName, ts, eventBase) {
+ const event = /val=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+ const value = parseInt(event[1]);
+
+ const counter = this.model_.kernel.
+ getOrCreateCounter(cat, counterName);
+ if (counter.numSeries === 0) {
+ counter.addSeries(new tr.model.CounterSeries(seriesName,
+ ColorScheme.getColorIdForGeneralPurposeString(counter.name)));
+ }
+ counter.series.forEach(function(series) {
+ series.addCounterSample(ts, value);
+ });
+ return true;
+ },
+
+ /*
+ * Job Manager block counters.
+ */
+ jmSample(ctrName, seriesName, ts, eventBase) {
+ return this.hwcSample('mali:jm', 'JM: ' + ctrName, seriesName, ts,
+ eventBase);
+ },
+ addJMCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.jmSample(hwcTitle, 'count', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+ addJMCycles(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.jmSample(hwcTitle, 'cycles', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * Tiler block counters.
+ */
+ tilerSample(ctrName, seriesName, ts, eventBase) {
+ return this.hwcSample('mali:tiler', 'Tiler: ' + ctrName, seriesName,
+ ts, eventBase);
+ },
+ addTilerCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.tilerSample(hwcTitle, 'count', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+ addTilerCycles(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.tilerSample(hwcTitle, 'cycles', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * Fragment counters.
+ */
+ fragSample(ctrName, seriesName, ts, eventBase) {
+ return this.hwcSample('mali:fragment', 'Fragment: ' + ctrName,
+ seriesName, ts, eventBase);
+ },
+ addFragCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.fragSample(hwcTitle, 'count', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+ addFragCycles(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.fragSample(hwcTitle, 'cycles', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * Compute counters.
+ */
+ computeSample(ctrName, seriesName, ts, eventBase) {
+ return this.hwcSample('mali:compute', 'Compute: ' + ctrName,
+ seriesName, ts, eventBase);
+ },
+ addComputeCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.computeSample(hwcTitle, 'count', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+ addComputeCycles(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.computeSample(hwcTitle, 'cycles', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * Tripipe counters.
+ */
+ addTripipeCycles(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.hwcSample('mali:shader', 'Tripipe: ' + hwcTitle, 'cycles',
+ ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * Arith counters.
+ */
+ arithSample(ctrName, seriesName, ts, eventBase) {
+ return this.hwcSample('mali:arith', 'Arith: ' + ctrName, seriesName, ts,
+ eventBase);
+ },
+ addArithCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.arithSample(hwcTitle, 'count', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+ addArithCycles(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.arithSample(hwcTitle, 'cycles', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * Load/Store counters.
+ */
+ addLSCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.hwcSample('mali:ls', 'LS: ' + hwcTitle, 'count', ts,
+ eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * Texture counters.
+ */
+ textureSample(ctrName, seriesName, ts, eventBase) {
+ return this.hwcSample('mali:texture', 'Texture: ' + ctrName,
+ seriesName, ts, eventBase);
+ },
+ addTexCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.textureSample(hwcTitle, 'count', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * LSC counters.
+ */
+ addLSCCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.hwcSample('mali:lsc', 'LSC: ' + hwcTitle, 'count', ts,
+ eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * TLB counters.
+ */
+ addAXICounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.hwcSample('mali:axi', 'AXI: ' + hwcTitle, 'count', ts,
+ eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * MMU counters.
+ */
+ mmuSample(ctrName, seriesName, ts, eventBase) {
+ return this.hwcSample('mali:mmu', 'MMU: ' + ctrName, seriesName, ts,
+ eventBase);
+ },
+ addMMUCounter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.mmuSample(hwcTitle, 'count', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+ addMMUCycles(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.mmuSample(hwcTitle, 'cycles', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+
+ /*
+ * L2 counters.
+ */
+ l2Sample(ctrName, seriesName, ts, eventBase) {
+ return this.hwcSample('mali:l2', 'L2: ' + ctrName, seriesName, ts,
+ eventBase);
+ },
+ addL2Counter(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.l2Sample(hwcTitle, 'count', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ },
+ addL2Cycles(hwcEventName, hwcTitle) {
+ function handler(eventName, cpuNumber, pid, ts, eventBase) {
+ return this.l2Sample(hwcTitle, 'cycles', ts, eventBase);
+ }
+ this.importer.registerEventHandler(hwcEventName, handler.bind(this));
+ }
+ };
+
+ Parser.register(MaliParser);
+
+ return {
+ MaliParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser_test.html
new file mode 100644
index 00000000000..76cc2e73b9c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/mali_parser_test.html
@@ -0,0 +1,559 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('maliDDKImport', function() {
+ const linesNoThread = [
+ // Row 1 open
+ ' chrome-1780 [001] ...1 28.562633: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'gles/src/dispatch/mali_gles_dispatch_entrypoints.c992: ' +
+ 'glTexSubImage2D',
+ // Row 2 open
+ ' chrome-1780 [001] ...1 28.562655: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'gles/src/texture/mali_gles_texture_api.c996: ' +
+ 'gles_texture_tex_sub_image_2d',
+ // Row 3 open
+ ' chrome-1780 [001] ...1 28.562671: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c295: ' +
+ 'gles_texturep_slave_map_master',
+ // Row 3 close
+ ' chrome-1780 [001] ...1 28.562684: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c295: ',
+ // Row 3 open
+ ' chrome-1780 [001] ...1 28.562700: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c1505: ' +
+ 'gles2_texturep_upload_2d',
+ // Row 4 open
+ ' chrome-1780 [001] ...1 28.562726: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c1612: ' +
+ 'gles2_texturep_upload_2d: pixel array: wait for dependencies',
+ // Row 5 open
+ ' chrome-1780 [001] ...1 28.562742: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'cobj/src/mali_cobj_surface_operations.c1693: ' +
+ 'cobj_convert_pixels_to_surface',
+ // Row 6 open
+ ' chrome-1780 [001] ...1 28.562776: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'cobj/src/mali_cobj_surface_operations.c1461: ' +
+ 'cobj_convert_pixels',
+ // Row 7 open
+ ' chrome-1780 [001] ...1 28.562791: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'cobj/src/mali_cobj_surface_operations.c1505: ' +
+ 'cobj_convert_pixels: fast-path linear copy',
+ // Row 8 open
+ ' chrome-1780 [001] ...1 28.562808: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_enter: ' +
+ 'cobj/src/mali_cobj_surface_operations.c1511: ' +
+ 'cobj_convert_pixels: reorder-only',
+ // Row 8 close
+ ' chrome-1780 [001] ...1 28.563383: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'cobj/src/mali_cobj_surface_operations.c1511',
+ // Row 7 close
+ ' chrome-1780 [001] ...1 28.563397: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'cobj/src/mali_cobj_surface_operations.c1505',
+ // Row 6 close
+ ' chrome-1780 [001] ...1 28.563409: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'cobj/src/mali_cobj_surface_operations.c1461',
+ // Row 5 close
+ ' chrome-1780 [001] ...1 28.563438: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'cobj/src/mali_cobj_surface_operations.c1693',
+ // Row 4 close
+ ' chrome-1780 [001] ...1 28.563451: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c1612',
+ // Row 3 close
+ ' chrome-1780 [001] ...1 28.563462: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c1505',
+ // Row 2 close
+ ' chrome-1780 [001] ...1 28.563475: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'gles/src/texture/mali_gles_texture_api.c996',
+ // Row 1 close
+ ' chrome-1780 [001] ...1 28.563486: tracing_mark_write: ' +
+ 'mali_driver: cros_trace_print_exit: ' +
+ 'gles/src/dispatch/mali_gles_dispatch_entrypoints.c992'
+ ];
+
+ const linesWithThread = [
+ // Row 1 open
+ ' chrome-1780 [001] ...1 28.562633: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'gles/src/dispatch/mali_gles_dispatch_entrypoints.c@992: ' +
+ 'glTexSubImage2D',
+ // Row 2 open
+ ' chrome-1780 [001] ...1 28.562655: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'gles/src/texture/mali_gles_texture_api.c@996: ' +
+ 'gles_texture_tex_sub_image_2d',
+ // Row 3 open
+ ' chrome-1780 [001] ...1 28.562671: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c@295: ' +
+ 'gles_texturep_slave_map_master',
+ // Row 3 close
+ ' chrome-1780 [001] ...1 28.562684: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c@295: ',
+ // Row 3 open
+ ' chrome-1780 [001] ...1 28.562700: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c@1505: ' +
+ 'gles2_texturep_upload_2d',
+ // Row 4 open
+ ' chrome-1780 [001] ...1 28.562726: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c@1612: ' +
+ 'gles2_texturep_upload_2d: pixel array: wait for dependencies',
+ // Row 5 open
+ ' chrome-1780 [001] ...1 28.562742: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'cobj/src/mali_cobj_surface_operations.c@1693: ' +
+ 'cobj_convert_pixels_to_surface',
+ // Row 6 open
+ ' chrome-1780 [001] ...1 28.562776: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'cobj/src/mali_cobj_surface_operations.c@1461: ' +
+ 'cobj_convert_pixels',
+ // Row 7 open
+ ' chrome-1780 [001] ...1 28.562791: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'cobj/src/mali_cobj_surface_operations.c@1505: ' +
+ 'cobj_convert_pixels: fast-path linear copy',
+ // Row 8 open
+ ' chrome-1780 [001] ...1 28.562808: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_enter: ' +
+ 'cobj/src/mali_cobj_surface_operations.c@1511: ' +
+ 'cobj_convert_pixels: reorder-only',
+ // Row 8 close
+ ' chrome-1780 [001] ...1 28.563383: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'cobj/src/mali_cobj_surface_operations.c@1511',
+ // Row 7 close
+ ' chrome-1780 [001] ...1 28.563397: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'cobj/src/mali_cobj_surface_operations.c@1505',
+ // Row 6 close
+ ' chrome-1780 [001] ...1 28.563409: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'cobj/src/mali_cobj_surface_operations.c@1461',
+ // Row 5 close
+ ' chrome-1780 [001] ...1 28.563438: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'cobj/src/mali_cobj_surface_operations.c@1693',
+ // Row 4 close
+ ' chrome-1780 [001] ...1 28.563451: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c@1612',
+ // Row 3 close
+ ' chrome-1780 [001] ...1 28.563462: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'gles/src/texture/mali_gles_texture_slave.c@1505',
+ // Row 2 close
+ ' chrome-1780 [001] ...1 28.563475: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'gles/src/texture/mali_gles_texture_api.c@996',
+ // Row 1 close
+ ' chrome-1780 [001] ...1 28.563486: tracing_mark_write: ' +
+ 'mali_driver: (mali-1878934320) cros_trace_print_exit: ' +
+ 'gles/src/dispatch/mali_gles_dispatch_entrypoints.c@992'
+ ];
+ const traceNoThread = newModel(linesNoThread.join('\n'));
+ const traceWithThread = newModel(linesWithThread.join('\n'));
+ assert.isFalse(traceNoThread.hasImportWarnings);
+ assert.isFalse(traceWithThread.hasImportWarnings);
+
+ const threadsNoThread = traceNoThread.getAllThreads();
+ const threadsWithThread = traceWithThread.getAllThreads();
+ assert.strictEqual(threadsNoThread.length, 1);
+ assert.strictEqual(threadsWithThread.length, 1);
+
+ const maliThreadNoThread = threadsNoThread[0];
+ const maliThreadWithThread = threadsWithThread[0];
+ assert.strictEqual(maliThreadNoThread.tid, 'mali');
+ assert.strictEqual(maliThreadWithThread.tid, 'mali-1878934320');
+ assert.strictEqual(maliThreadNoThread.sliceGroup.length, 9);
+ assert.strictEqual(maliThreadWithThread.sliceGroup.length, 9);
+ });
+
+ test('DVFSFrequencyImport', function() {
+ const lines = [
+ ' kworker/u:0-5 [001] .... 1174.839552: mali_dvfs_set_clock: ' +
+ 'frequency=266',
+ ' kworker/u:0-5 [000] .... 1183.840486: mali_dvfs_set_clock: ' +
+ 'frequency=400'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const counters = m.getAllCounters();
+ assert.strictEqual(counters.length, 1);
+
+ const c0 = counters[0];
+ assert.strictEqual(c0.name, 'DVFS Frequency');
+ assert.strictEqual(c0.series[0].samples.length, 2);
+ });
+
+ test('DVFSVoltageImport', function() {
+ const lines = [
+ ' kworker/u:0-5 [001] .... 1174.839562: mali_dvfs_set_voltage: ' +
+ 'voltage=937500',
+ ' kworker/u:0-5 [000] .... 1183.840009: mali_dvfs_set_voltage: ' +
+ 'voltage=1100000'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const counters = m.getAllCounters();
+ assert.strictEqual(counters.length, 1);
+
+ const c0 = counters[0];
+ assert.strictEqual(c0.name, 'DVFS Voltage');
+ assert.strictEqual(c0.series[0].samples.length, 2);
+ });
+
+ test('DVFSUtilizationImport', function() {
+ const lines = [
+ ' kworker/u:0-5 [001] .... 1174.839552: mali_dvfs_event: ' +
+ 'utilization=7',
+ ' kworker/u:0-5 [000] .... 1183.840486: mali_dvfs_event: ' +
+ 'utilization=37'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const counters = m.getAllCounters();
+ assert.strictEqual(counters.length, 1);
+
+ const c0 = counters[0];
+ assert.strictEqual(c0.name, 'DVFS Utilization');
+ assert.strictEqual(c0.series[0].samples.length, 2);
+ });
+
+ test('maliHWCImport', function() {
+ const lines = [
+ ' kworker/u:0-5 [000] .... 78.896588: ' +
+ 'mali_hwc_ACTIVE: val=238',
+ ' kworker/u:0-5 [000] .... 79.046889: ' +
+ 'mali_hwc_ARITH_CYCLES_L0: val=1967',
+ ' kworker/u:0-5 [000] .... 79.046888: ' +
+ 'mali_hwc_ARITH_CYCLES_REG: val=136',
+ ' kworker/u:0-5 [000] .... 79.046890: ' +
+ 'mali_hwc_ARITH_FRAG_DEPEND: val=19676',
+ ' kworker/u:0-5 [000] .... 79.046886: ' +
+ 'mali_hwc_ARITH_WORDS: val=255543',
+ ' kworker/u:0-5 [000] .... 79.046920: ' +
+ 'mali_hwc_AXI_BEATS_READ: val=257053',
+ ' kworker/u:0-5 [000] .... 78.896594: ' +
+ 'mali_hwc_AXI_TLB_STALL: val=1',
+ ' kworker/u:0-5 [000] .... 78.946646: ' +
+ 'mali_hwc_AXI_TLB_TRANSACTION: val=4',
+ ' kworker/u:0-5 [000] .... 79.046853: ' +
+ 'mali_hwc_BACK_FACING: val=104',
+ ' kworker/u:0-5 [000] .... 79.046880: ' +
+ 'mali_hwc_COMPUTE_ACTIVE: val=17462',
+ ' kworker/u:0-5 [000] .... 79.046884: ' +
+ 'mali_hwc_COMPUTE_CYCLES_DESC: val=3933',
+ ' kworker/u:0-5 [000] .... 79.046881: ' +
+ 'mali_hwc_COMPUTE_TASKS: val=15',
+ ' kworker/u:0-5 [000] .... 79.046883: ' +
+ 'mali_hwc_COMPUTE_THREADS: val=60',
+ ' kworker/u:0-5 [000] .... 79.046860: ' +
+ 'mali_hwc_FRAG_ACTIVE: val=690986',
+ ' kworker/u:0-5 [000] .... 79.046864: ' +
+ 'mali_hwc_FRAG_CYCLE_DESC: val=13980',
+ ' kworker/u:0-5 [000] .... 79.046876: ' +
+ 'mali_hwc_FRAG_CYCLE_NO_TILE: val=3539',
+ ' kworker/u:0-5 [000] .... 79.046865: ' +
+ 'mali_hwc_FRAG_CYCLES_PLR: val=1499',
+ ' kworker/u:0-5 [000] .... 79.046869: ' +
+ 'mali_hwc_FRAG_CYCLES_RAST: val=1999',
+ ' kworker/u:0-5 [000] .... 79.046868: ' +
+ 'mali_hwc_FRAG_CYCLES_TRISETUP: val=22353',
+ ' kworker/u:0-5 [000] .... 79.046867: ' +
+ 'mali_hwc_FRAG_CYCLES_VERT: val=20763',
+ ' kworker/u:0-5 [000] .... 79.046872: ' +
+ 'mali_hwc_FRAG_DUMMY_THREADS: val=1968',
+ ' kworker/u:0-5 [000] .... 79.046877: ' +
+ 'mali_hwc_FRAG_NUM_TILES: val=1840',
+ ' kworker/u:0-5 [000] .... 79.046862: ' +
+ 'mali_hwc_FRAG_PRIMATIVES: val=3752',
+ ' kworker/u:0-5 [000] .... 79.046863: ' +
+ 'mali_hwc_FRAG_PRIMATIVES_DROPPED: val=18',
+ ' kworker/u:0-5 [000] .... 79.046874: ' +
+ 'mali_hwc_FRAG_QUADS_EZS_TEST: val=117925',
+ ' kworker/u:0-5 [000] .... 79.046873: ' +
+ 'mali_hwc_FRAG_QUADS_RAST: val=117889',
+ ' kworker/u:0-5 [000] .... 79.046870: ' +
+ 'mali_hwc_FRAG_THREADS: val=471507',
+ ' kworker/u:0-5 [000] .... 79.046879: ' +
+ 'mali_hwc_FRAG_TRANS_ELIM: val=687',
+ ' kworker/u:0-5 [000] .... 80.315162: ' +
+ 'mali_hwc_FRONT_FACING: val=56',
+ ' kworker/u:0-5 [000] .... 78.896582: ' +
+ 'mali_hwc_GPU_ACTIVE: val=1316',
+ ' kworker/u:0-5 [000] .... 78.896584: ' +
+ 'mali_hwc_IRQ_ACTIVE: val=17',
+ ' kworker/u:0-5 [000] .... 79.046834: ' +
+ 'mali_hwc_JS0_ACTIVE: val=709444',
+ ' kworker/u:0-5 [000] .... 79.046831: ' +
+ 'mali_hwc_JS0_JOBS: val=2',
+ ' kworker/u:0-5 [000] .... 79.046832: ' +
+ 'mali_hwc_JS0_TASKS: val=7263',
+ ' kworker/u:0-5 [000] .... 79.046836: ' +
+ 'mali_hwc_JS0_WAIT_DEPEND: val=665876',
+ ' kworker/u:0-5 [000] .... 79.046835: ' +
+ 'mali_hwc_JS0_WAIT_ISSUE: val=910',
+ ' kworker/u:0-5 [000] .... 79.046840: ' +
+ 'mali_hwc_JS1_ACTIVE: val=153980',
+ ' kworker/u:0-5 [000] .... 79.046838: ' +
+ 'mali_hwc_JS1_JOBS: val=133',
+ ' kworker/u:0-5 [000] .... 79.046839: ' +
+ 'mali_hwc_JS1_TASKS: val=128',
+ ' kworker/u:0-5 [000] .... 79.046843: ' +
+ 'mali_hwc_JS1_WAIT_FINISH: val=74404',
+ ' kworker/u:0-5 [000] .... 79.046842: ' +
+ 'mali_hwc_JS1_WAIT_ISSUE: val=10146',
+ ' kworker/u:0-5 [000] .... 78.896603: ' +
+ 'mali_hwc_L2_ANY_LOOKUP: val=22',
+ ' kworker/u:0-5 [000] .... 79.046942: ' +
+ 'mali_hwc_L2_CLEAN_MISS: val=116',
+ ' kworker/u:0-5 [000] .... 79.063515: ' +
+ 'mali_hwc_L2_EXT_AR_STALL: val=9',
+ ' kworker/u:0-5 [000] .... 78.963384: ' +
+ 'mali_hwc_L2_EXT_BARRIER: val=1',
+ ' kworker/u:0-5 [000] .... 79.063516: ' +
+ 'mali_hwc_L2_EXT_R_BUF_FULL: val=43',
+ ' kworker/u:0-5 [000] .... 78.896611: ' +
+ 'mali_hwc_L2_EXT_READ: val=4',
+ ' kworker/u:0-5 [000] .... 78.896612: ' +
+ 'mali_hwc_L2_EXT_READ_LINE: val=4',
+ ' kworker/u:0-5 [000] .... 79.046956: ' +
+ 'mali_hwc_L2_EXT_R_RAW: val=1',
+ ' kworker/u:0-5 [000] .... 79.063518: ' +
+ 'mali_hwc_L2_EXT_R_W_HAZARD: val=15',
+ ' kworker/u:0-5 [000] .... 78.963381: ' +
+ 'mali_hwc_L2_EXT_WRITE: val=25',
+ ' kworker/u:0-5 [000] .... 79.046952: ' +
+ 'mali_hwc_L2_EXT_WRITE_LINE: val=63278',
+ ' kworker/u:0-5 [000] .... 78.963382: ' +
+ 'mali_hwc_L2_EXT_WRITE_SMALL: val=1',
+ ' kworker/u:0-5 [000] .... 79.814532: ' +
+ 'mali_hwc_L2_EXT_W_STALL: val=9',
+ ' kworker/u:0-5 [000] .... 78.896602: ' +
+ 'mali_hwc_L2_READ_BEATS: val=16',
+ ' kworker/u:0-5 [000] .... 78.896607: ' +
+ 'mali_hwc_L2_READ_HIT: val=11',
+ ' kworker/u:0-5 [000] .... 78.896604: ' +
+ 'mali_hwc_L2_READ_LOOKUP: val=19',
+ ' kworker/u:0-5 [000] .... 78.896606: ' +
+ 'mali_hwc_L2_READ_REPLAY: val=2',
+ ' kworker/u:0-5 [000] .... 79.046940: ' +
+ 'mali_hwc_L2_READ_SNOOP: val=24',
+ ' kworker/u:0-5 [000] .... 79.046959: ' +
+ 'mali_hwc_L2_REPLAY_FULL: val=6629',
+ ' kworker/u:0-5 [000] .N.. 80.565684: ' +
+ 'mali_hwc_L2_SNOOP_FULL: val=5',
+ ' kworker/u:0-5 [000] .... 79.046937: ' +
+ 'mali_hwc_L2_SREAD_LOOKUP: val=241',
+ ' kworker/u:0-5 [000] .... 79.046944: ' +
+ 'mali_hwc_L2_SWRITE_LOOKUP: val=133',
+ ' kworker/u:0-5 [000] .... 78.896614: ' +
+ 'mali_hwc_L2_TAG_HAZARD: val=4',
+ ' kworker/u:0-5 [000] .... 78.963368: ' +
+ 'mali_hwc_L2_WRITE_BEATS: val=96',
+ ' kworker/u:0-5 [000] .... 79.046947: ' +
+ 'mali_hwc_L2_WRITE_HIT: val=78265',
+ ' kworker/u:0-5 [000] .... 78.896608: ' +
+ 'mali_hwc_L2_WRITE_LOOKUP: val=3',
+ ' kworker/u:0-5 [000] .... 79.046946: ' +
+ 'mali_hwc_L2_WRITE_REPLAY: val=15879',
+ ' kworker/u:0-5 [000] .... 79.046912: ' +
+ 'mali_hwc_LSC_LINE_FETCHES: val=15',
+ ' kworker/u:0-5 [000] .... 79.046909: ' +
+ 'mali_hwc_LSC_READ_HITS: val=2961',
+ ' kworker/u:0-5 [000] .... 79.046911: ' +
+ 'mali_hwc_LSC_READ_MISSES: val=22',
+ ' kworker/u:0-5 [000] .... 79.046914: ' +
+ 'mali_hwc_LSC_SNOOPS: val=10',
+ ' kworker/u:0-5 [000] .... 79.046893: ' +
+ 'mali_hwc_LS_ISSUES: val=524219',
+ ' kworker/u:0-5 [000] .... 79.046894: ' +
+ 'mali_hwc_LS_REISSUES_MISS: val=439',
+ ' kworker/u:0-5 [000] .... 79.046895: ' +
+ 'mali_hwc_LS_REISSUES_VD: val=52007',
+ ' kworker/u:0-5 [000] .... 79.046919: ' +
+ 'mali_hwc_LS_TLB_HIT: val=3043',
+ ' kworker/u:0-5 [000] .... 79.046918: ' +
+ 'mali_hwc_LS_TLB_MISS: val=5',
+ ' kworker/u:0-5 [000] .... 79.046891: ' +
+ 'mali_hwc_LS_WORDS: val=471514',
+ ' kworker/u:0-5 [000] .... 79.046925: ' +
+ 'mali_hwc_MMU_HIT: val=771',
+ ' kworker/u:0-5 [000] .... 79.046924: ' +
+ 'mali_hwc_MMU_NEW_MISS: val=494',
+ ' kworker/u:0-5 [000] .... 79.046922: ' +
+ 'mali_hwc_MMU_REPLAY_MISS: val=841',
+ ' kworker/u:0-5 [000] .... 79.046921: ' +
+ 'mali_hwc_MMU_TABLE_WALK: val=3119',
+ ' kworker/u:0-5 [000] .... 79.046848: ' +
+ 'mali_hwc_POINTS: val=5',
+ ' kworker/u:0-5 [000] .... 79.046856: ' +
+ 'mali_hwc_PRIM_CLIPPED: val=70',
+ ' kworker/u:0-5 [000] .... 79.046855: ' +
+ 'mali_hwc_PRIM_CULLED: val=26',
+ ' kworker/u:0-5 [000] .... 79.046854: ' +
+ 'mali_hwc_PRIM_VISIBLE: val=109',
+ ' kworker/u:0-5 [000] .... 79.046898: ' +
+ 'mali_hwc_TEX_BUBBLES: val=24874',
+ ' kworker/u:0-5 [000] .... 79.046905: ' +
+ 'mali_hwc_TEX_RECIRC_DESC: val=5937',
+ ' kworker/u:0-5 [000] .... 79.046904: ' +
+ 'mali_hwc_TEX_RECIRC_FMISS: val=209450',
+ ' kworker/u:0-5 [000] .... 78.896592: ' +
+ 'mali_hwc_TEX_RECIRC_MULTI: val=238',
+ ' kworker/u:0-5 [000] .... 79.046908: ' +
+ 'mali_hwc_TEX_RECIRC_PMISS: val=9672',
+ ' kworker/u:0-5 [000] .... 79.046903: ' +
+ 'mali_hwc_TEX_THREADS: val=660900',
+ ' kworker/u:0-5 [000] .... 79.046897: ' +
+ 'mali_hwc_TEX_WORDS: val=471193',
+ ' kworker/u:0-5 [000] .... 79.046901: ' +
+ 'mali_hwc_TEX_WORDS_DESC: val=707',
+ ' kworker/u:0-5 [000] .... 79.046900: ' +
+ 'mali_hwc_TEX_WORDS_L0: val=32',
+ ' kworker/u:0-5 [000] .... 79.046846: ' +
+ 'mali_hwc_TRIANGLES: val=130',
+ ' kworker/u:0-5 [000] .... 79.046885: ' +
+ 'mali_hwc_TRIPIPE_ACTIVE: val=691001',
+ ' kworker/u:0-5 [000] .... 78.896600: ' +
+ 'mali_hwc_UTLB_NEW_MISS: val=6',
+ ' kworker/u:0-5 [000] .... 78.896599: ' +
+ 'mali_hwc_UTLB_REPLAY_FULL: val=248',
+ ' kworker/u:0-5 [000] .... 78.896597: ' +
+ 'mali_hwc_UTLB_REPLAY_MISS: val=1',
+ ' kworker/u:0-5 [000] .... 78.896596: ' +
+ 'mali_hwc_UTLB_STALL: val=1',
+ ' kworker/u:0-5 [000] .... 79.046850: ' +
+ 'mali_hwc_VCACHE_HIT: val=311',
+ ' kworker/u:0-5 [000] .... 79.046851: ' +
+ 'mali_hwc_VCACHE_MISS: val=70'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const counters = m.getAllCounters();
+ assert.strictEqual(counters.length, 103);
+
+ // all counters should have 1 sample
+ for (let tI = 0; tI < counters.length; tI++) {
+ const counter = counters[tI];
+ assert.strictEqual(counter.series[0].samples.length, 1);
+ }
+ // TODO(sleffler) verify counter names? (not sure if it's worth the effort)
+ });
+
+ test('maliJobImport', function() {
+ const jobEvents = [
+ // vertex slice 0 open
+ ' surfaceflinger-6962 ( 6962) [000] d.h2 498269.966588: ' +
+ 'mali_job_systrace_event_start: tracing_mark_write: ' +
+ 'S|6962|vertex-job|85|84|1|0|0|920d408|69628513498269966584032',
+ // vertex slice 0 close
+ ' surfaceflinger-6962 ( 6962) [000] d.h2 498269.966702: ' +
+ 'mali_job_systrace_event_stop: tracing_mark_write: ' +
+ 'F|6962|vertex-job|85|84|1|0|0|920d408|69628513498269966584032',
+
+ // vertex slice 1 open
+ ' surfaceflinger-6962 ( 6962) [000] d..1 498269.966966: ' +
+ 'mali_job_systrace_event_start: tracing_mark_write: ' +
+ 'S|7541|vertex-job|225|0|0|0|0|f5e13b48|754122517498269966963802',
+ // vertex slice 1 close
+ ' surfaceflinger-6962 ( 6962) [000] d.h1 498269.967109: ' +
+ 'mali_job_systrace_event_stop: tracing_mark_write: ' +
+ 'F|7541|vertex-job|225|0|0|0|0|f5e13b48|754122517498269966963802',
+
+ // fragment slice 0 open
+ ' kworker/u17:4-6269 ( 6269) [001] d..1 498269.967667: ' +
+ 'mali_job_systrace_event_start: tracing_mark_write: ' +
+ 'S|6962|fragment-job|86|85|1|0|0|920d408|69628613498269967664417',
+ // fragment slice 1 open (deferred)
+ ' mali-cmar-backe-7634 ( 7541) [003] d..1 498269.968473: ' +
+ 'mali_job_systrace_event_start: tracing_mark_write: ' +
+ 'S|7541|fragment-job|223|225|1|0|0|f5e13b48|754122317498269968470186',
+ // fragment slice 0 close (adjusted open of slice 1)
+ ' HwBinder:6936_2-7001 ( 6936) [000] d.h3 498269.970336: ' +
+ 'mali_job_systrace_event_stop: tracing_mark_write: ' +
+ 'F|6962|fragment-job|86|85|1|0|0|920d408|69628613498269967664417',
+ // fragment slice 1 close
+ ' RenderThread-7619 ( 7541) [000] d.h1 498269.971688: ' +
+ 'mali_job_systrace_event_stop: tracing_mark_write: ' +
+ 'F|7541|fragment-job|223|225|1|0|0|f5e13b48|754122317498269970293032',
+ ];
+
+ const expectedThreads = [
+ {
+ tid: 'mali:vertex',
+ slices: [
+ {title: '85', start: '498269.966588', end: '498269.966702'},
+ {title: '225', start: '498269.966966', end: '498269.967109'}]},
+ {
+ tid: 'mali:fragment',
+ slices: [
+ {title: '86', start: '498269.967667', end: '498269.970336'},
+ {title: '223', start: '498269.970336', end: '498269.971688'}]},
+ ];
+
+ const trace = newModel(jobEvents.join('\n'));
+ assert.isFalse(trace.hasImportWarnings);
+
+ const threads = trace.getAllThreads();
+ assert.strictEqual(threads.length, expectedThreads.length);
+ for (let tidx = 0; tidx < threads.length; tidx++) {
+ const actualThread = threads[tidx];
+ const expectedThread = expectedThreads[tidx];
+ assert.strictEqual(actualThread.tid, expectedThreads[tidx].tid);
+ assert.strictEqual(actualThread.sliceGroup.length,
+ expectedThreads[tidx].slices.length);
+ for (let sidx = 0; sidx < actualThread.sliceGroup.length; sidx++) {
+ const actualSlice = actualThread.sliceGroup.slices[sidx];
+ const expectedSlice = expectedThread.slices[sidx];
+ assert.strictEqual(actualSlice.title, expectedSlice.title);
+ assert.strictEqual(actualSlice.start,
+ parseFloat(expectedSlice.start) * 1000);
+ assert.strictEqual(actualSlice.end,
+ parseFloat(expectedSlice.end) * 1000);
+ }
+ }
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser.html
new file mode 100644
index 00000000000..027554eacfd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses drm driver events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux vmscan trace events.
+ * @constructor
+ */
+ function MemReclaimParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('mm_vmscan_kswapd_wake',
+ MemReclaimParser.prototype.kswapdWake.bind(this));
+ importer.registerEventHandler('mm_vmscan_kswapd_sleep',
+ MemReclaimParser.prototype.kswapdSleep.bind(this));
+ importer.registerEventHandler('mm_vmscan_direct_reclaim_begin',
+ MemReclaimParser.prototype.reclaimBegin.bind(this));
+ importer.registerEventHandler('mm_vmscan_direct_reclaim_end',
+ MemReclaimParser.prototype.reclaimEnd.bind(this));
+ importer.registerEventHandler('lowmemory_kill',
+ MemReclaimParser.prototype.lowmemoryKill.bind(this));
+ }
+
+ // Matches the mm_vmscan_kswapd_wake record
+ // mm_vmscan_kswapd_wake: nid=%d order=%d
+ const kswapdWakeRE = /nid=(\d+) order=(\d+)/;
+
+ // Matches the mm_vmscan_kswapd_sleep record
+ // mm_vmscan_kswapd_sleep: order=%d
+ const kswapdSleepRE = /nid=(\d+)/;
+
+ // Matches the mm_vmscan_direct_reclaim_begin record
+ // mm_vmscan_direct_reclaim_begin: order=%d may_writepage=%d gfp_flags=%s
+ const reclaimBeginRE = /order=(\d+) may_writepage=\d+ gfp_flags=(.+)/;
+
+ // Matches the mm_vmscan_direct_reclaim_end record
+ // mm_vmscan_direct_reclaim_end: nr_reclaimed=%lu
+ const reclaimEndRE = /nr_reclaimed=(\d+)/;
+
+ // Matches the lowmemory_kill record
+ const lowmemoryRE =
+ /([^ ]+) \((\d+)\), page cache (\d+)kB \(limit (\d+)kB\), free (-?\d+)Kb/;
+
+ MemReclaimParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses memreclaim events and sets up state in the importer.
+ */
+ kswapdWake(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = kswapdWakeRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const tgid = parseInt(eventBase.tgid);
+
+ const nid = parseInt(event[1]);
+ const order = parseInt(event[2]);
+
+ const kthread = this.importer.getOrCreateKernelThread(
+ eventBase.threadName, tgid, pid);
+
+ if (kthread.openSliceTS) {
+ if (order > kthread.order) {
+ kthread.order = order;
+ }
+ } else {
+ kthread.openSliceTS = ts;
+ kthread.order = order;
+ }
+ return true;
+ },
+
+ kswapdSleep(eventName, cpuNumber, pid, ts, eventBase) {
+ const tgid = parseInt(eventBase.tgid);
+
+ const kthread = this.importer.getOrCreateKernelThread(
+ eventBase.threadName, tgid, pid);
+
+ if (kthread.openSliceTS) {
+ kthread.thread.sliceGroup.pushCompleteSlice(
+ 'memreclaim', eventBase.threadName, kthread.openSliceTS,
+ ts - kthread.openSliceTS, 0, 0,
+ {
+ order: kthread.order
+ });
+ }
+ kthread.openSliceTS = undefined;
+ kthread.order = undefined;
+ return true;
+ },
+
+ reclaimBegin(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = reclaimBeginRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const order = parseInt(event[1]);
+ const gfp = event[2];
+ const tgid = parseInt(eventBase.tgid);
+
+ const kthread = this.importer.getOrCreateKernelThread(
+ eventBase.threadName, tgid, pid);
+
+ kthread.openSliceTS = ts;
+ kthread.order = order;
+ kthread.gfp = gfp;
+ return true;
+ },
+
+ reclaimEnd(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = reclaimEndRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const nrReclaimed = parseInt(event[1]);
+ const tgid = parseInt(eventBase.tgid);
+
+ const kthread = this.importer.getOrCreateKernelThread(
+ eventBase.threadName, tgid, pid);
+
+ if (kthread.openSliceTS !== undefined) {
+ kthread.thread.sliceGroup.pushCompleteSlice('memreclaim',
+ 'direct reclaim', kthread.openSliceTS, ts - kthread.openSliceTS,
+ 0, 0,
+ {
+ order: kthread.order,
+ gfp: kthread.gfp,
+ nr_reclaimed: nrReclaimed
+ });
+ }
+ kthread.openSliceTS = undefined;
+ kthread.order = undefined;
+ kthread.gfp = undefined;
+ return true;
+ },
+
+ lowmemoryKill(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = lowmemoryRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const tgid = parseInt(eventBase.tgid);
+ const killedName = event[1];
+ const killedPid = parseInt(event[2]);
+ const cache = parseInt(event[3]);
+ const free = parseInt(event[5]);
+
+ const kthread = this.importer.getOrCreateKernelThread(
+ eventBase.threadName, tgid, pid);
+
+ kthread.thread.sliceGroup.pushCompleteSlice('lowmemory',
+ 'low memory kill', ts, 0,
+ 0, 0,
+ {
+ killed_name: killedName,
+ killed_pid: killedPid,
+ cache,
+ free
+ });
+ return true;
+ }
+ };
+
+ Parser.register(MemReclaimParser);
+
+ return {
+ MemReclaimParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser_test.html
new file mode 100644
index 00000000000..1396d6713eb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/memreclaim_parser_test.html
@@ -0,0 +1,170 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('memreclaimImport', function() {
+ const lines = [
+ ' surfaceflinger-1155 ( 1155) [001] ...1 12839.528756: mm_vmscan_direct_reclaim_begin: order=0 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|GFP_ZERO|0x2', // @suppress longLineCheck
+ ' surfaceflinger-1155 ( 1155) [001] ...1 12839.531950: mm_vmscan_direct_reclaim_end: nr_reclaimed=66', // @suppress longLineCheck
+ ' kswapd0-33 ( 33) [001] ...1 12838.491407: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ ' kswapd0-33 ( 33) [001] ...1 12838.529770: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ ' kswapd0-33 ( 33) [001] ...1 12840.545737: mm_vmscan_kswapd_sleep: nid=0'// @suppress longLineCheck
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.strictEqual(
+ m.processes['1155'].threads['1155'].sliceGroup.length, 1);
+ assert.strictEqual(m.processes['33'].threads['33'].sliceGroup.length, 1);
+ });
+
+ test('memreclaimDirectReclaim', function() {
+ const lines = [
+ 'RenderThread-9844 ( 9786) [001] ...1 1734.106078: mm_vmscan_direct_reclaim_begin: order=5 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|0x2', // @suppress longLineCheck
+ 'RenderThread-9844 ( 9786) [001] ...1 1734.107619: mm_vmscan_direct_reclaim_end: nr_reclaimed=72', // @suppress longLineCheck
+ 'RenderThread-9844 ( 9786) [001] ...1 1734.107738: mm_vmscan_direct_reclaim_begin: order=4 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|0x2', // @suppress longLineCheck
+ 'RenderThread-9844 ( 9786) [001] ...1 1734.107844: mm_vmscan_direct_reclaim_end: nr_reclaimed=35', // @suppress longLineCheck
+ 'RenderThread-9844 ( 9786) [001] ...1 1734.107891: mm_vmscan_direct_reclaim_begin: order=4 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|0x2', // @suppress longLineCheck
+ 'RenderThread-9844 ( 9786) [001] ...1 1734.107945: mm_vmscan_direct_reclaim_end: nr_reclaimed=35', // @suppress longLineCheck
+ 'RenderThread-9844 ( 9786) [001] ...1 1734.107990: mm_vmscan_direct_reclaim_begin: order=4 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|0x2', // @suppress longLineCheck
+ 'RenderThread-9844 ( 9786) [001] ...1 1734.108062: mm_vmscan_direct_reclaim_end: nr_reclaimed=34', // @suppress longLineCheck
+ 'Binder_8-1735 ( 1022) [001] ...1 1735.472240: mm_vmscan_direct_reclaim_begin: order=3 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|0x2', // @suppress longLineCheck
+ 'Binder_8-1735 ( 1022) [001] ...1 1735.472849: mm_vmscan_direct_reclaim_end: nr_reclaimed=47', // @suppress longLineCheck
+ 'Binder_8-1735 ( 1022) [001] ...1 1735.473002: mm_vmscan_direct_reclaim_begin: order=3 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|0x2', // @suppress longLineCheck
+ 'Binder_8-1735 ( 1022) [001] ...1 1735.474859: mm_vmscan_direct_reclaim_end: nr_reclaimed=48', // @suppress longLineCheck
+ 'touchFusion-88 ( 88) [000] ...1 1736.510656: mm_vmscan_direct_reclaim_begin: order=2 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|GFP_COMP|GFP_NOMEMALLOC|GFP_KMEMCG', // @suppress longLineCheck
+ 'touchFusion-88 ( 88) [000] ...1 1736.517616: mm_vmscan_direct_reclaim_end: nr_reclaimed=34', // @suppress longLineCheck
+ 'touchFusion-88 ( 88) [000] ...1 1736.527061: mm_vmscan_direct_reclaim_begin: order=2 may_writepage=1 gfp_flags=GFP_KERNEL|GFP_NOWARN|GFP_COMP|GFP_NOMEMALLOC|GFP_KMEMCG', // @suppress longLineCheck
+ 'touchFusion-88 ( 88) [000] ...1 1736.530857: mm_vmscan_direct_reclaim_end: nr_reclaimed=39'// @suppress longLineCheck
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+
+ assert.strictEqual(threads.length, 3);
+
+ const Binder8 = threads[0];
+ const touchFusion = threads[1];
+ const RenderThread = threads[2];
+
+ /* make sure there are the expected amount of slices per thread */
+ assert.strictEqual(Binder8.sliceGroup.length, 2);
+ assert.strictEqual(touchFusion.sliceGroup.length, 2);
+ assert.strictEqual(RenderThread.sliceGroup.length, 4);
+
+ /* make sure the slices have information to display to the
+ * user when selected
+ */
+
+ const iterateMe = [Binder8, touchFusion, RenderThread];
+ iterateMe.forEach(function(thread) {
+ for (let i = 0; i < thread.sliceGroup.length; i++) {
+ assert.isDefined(thread.sliceGroup.slices[i].args);
+ }
+ });
+ });
+
+ test('memreclaimKswapd', function() {
+ const lines = [
+ 'kswapd0-48 ( 48) [001] ...1 1734.210437: mm_vmscan_kswapd_wake: nid=0 order=5', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.227291: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.237585: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.258698: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.269642: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.319484: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.344839: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.428425: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.429593: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.599419: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1734.696606: mm_vmscan_kswapd_sleep: nid=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1735.465745: mm_vmscan_kswapd_wake: nid=0 order=3', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1735.563917: mm_vmscan_kswapd_wake: nid=0 order=5', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1735.570555: mm_vmscan_kswapd_wake: nid=0 order=4', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1735.666658: mm_vmscan_kswapd_sleep: nid=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1736.508069: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1736.529293: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1736.696725: mm_vmscan_kswapd_sleep: nid=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1737.945426: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1737.988642: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.057237: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.144630: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.207546: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.221963: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.316889: mm_vmscan_kswapd_sleep: nid=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.712804: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.751103: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.773175: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.785068: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.789545: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1738.873675: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1738.899117: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1738.939214: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1738.990366: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1739.028269: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1739.036765: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1739.077631: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.094731: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.096757: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.160536: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.256638: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.264972: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1739.360137: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.368759: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.387082: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.455657: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.489058: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.507561: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.570247: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [001] ...1 1739.582975: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.678148: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.762025: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.799245: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.821950: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.894130: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1739.919775: lowmemory_kill: d.process.media (10517), page cache 311740kB (limit 322560kB), free -1456Kb', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.026933: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.126608: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.150819: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.156101: mm_vmscan_kswapd_wake: nid=0 order=1', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.246626: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.357055: mm_vmscan_kswapd_sleep: nid=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.762705: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.772367: mm_vmscan_kswapd_wake: nid=0 order=2', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.783509: mm_vmscan_kswapd_wake: nid=0 order=0', // @suppress longLineCheck
+ 'kswapd0-48 ( 48) [000] ...1 1740.876601: mm_vmscan_kswapd_sleep: nid=0'// @suppress longLineCheck
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 1);
+
+ const thread = threads[0];
+
+ assert.strictEqual(thread.sliceGroup.length, 7);
+
+ thread.sliceGroup.slices.forEach(function(slice) {
+ assert.strictEqual(slice.args !== undefined, true);
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/parser.html
new file mode 100644
index 00000000000..42151aea319
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/parser.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/extension_registry.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Base class for linux perf event parsers.
+ *
+ * The linux perf trace event importer depends on subclasses of
+ * Parser to parse event data. Each subclass corresponds
+ * to a group of trace events; e.g. SchedParser implements
+ * parsing of sched:* kernel trace events. Parser subclasses must
+ * call Parser.register to arrange to be instantiated
+ * and their constructor must register their event handlers with the
+ * importer. For example,
+ *
+ * var Parser = tr.e.importer.linux_perf.Parser;
+ *
+ * function WorkqueueParser(importer) {
+ * Parser.call(this, importer);
+ *
+ * importer.registerEventHandler('workqueue_execute_start',
+ * WorkqueueParser.prototype.executeStartEvent.bind(this));
+ * importer.registerEventHandler('workqueue_execute_end',
+ * WorkqueueParser.prototype.executeEndEvent.bind(this));
+ * }
+ *
+ * Parser.register(WorkqueueParser);
+ *
+ * When a registered event name is found in the data stream the associated
+ * event handler is invoked:
+ *
+ * executeStartEvent: function(eventName, cpuNumber, ts, eventBase)
+ *
+ * If the routine returns false the caller will generate an import error
+ * saying there was a problem parsing it. Handlers can also emit import
+ * messages using this.importer.model.importWarning. If this is done in lieu of
+ * the generic import error it may be desirable for the handler to return
+ * true.
+ *
+ * Trace events generated by writing to the trace_marker file are expected
+ * to have a leading text marker followed by a ':'; e.g. the trace clock
+ * synchronization event is:
+ *
+ * tracing_mark_write: trace_event_clock_sync: parent_ts=0
+ *
+ * To register an event handler for these events, prepend the marker with
+ * 'tracing_mark_write:'; e.g.
+ *
+ * this.registerEventHandler('tracing_mark_write:trace_event_clock_sync',
+ *
+ * All subclasses should depend on importer.linux_perf.parser, e.g.
+ *
+ * tr.defineModule('importer.linux_perf.workqueue_parser')
+ * .dependsOn('importer.linux_perf.parser')
+ * .exportsTo('tracing', function()
+ *
+ * and be listed in the dependsOn of FTraceImporter. Beware that after adding a
+ * new subclass you must run build/generate_about_tracing_contents.py to
+ * regenerate tr.ui.e.about_tracing.*.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ /**
+ * Parses linux perf events.
+ * @constructor
+ */
+ function Parser(importer) {
+ this.importer = importer;
+ this.model = importer.model;
+ }
+
+ Parser.prototype = {
+ __proto__: Object.prototype
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ options.mandatoryBaseClass = Parser;
+ tr.b.decorateExtensionRegistry(Parser, options);
+
+ return {
+ Parser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/power_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/power_parser.html
new file mode 100644
index 00000000000..90a668eb3d2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/power_parser.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses power events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux power trace events.
+ * @constructor
+ */
+ function PowerParser(importer) {
+ Parser.call(this, importer);
+
+ // NB: old-style power events, deprecated
+ importer.registerEventHandler('power_start',
+ PowerParser.prototype.powerStartEvent.bind(this));
+ importer.registerEventHandler('power_frequency',
+ PowerParser.prototype.powerFrequencyEvent.bind(this));
+
+ importer.registerEventHandler('cpu_frequency',
+ PowerParser.prototype.cpuFrequencyEvent.bind(this));
+ importer.registerEventHandler('cpu_frequency_limits',
+ PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));
+ importer.registerEventHandler('cpu_idle',
+ PowerParser.prototype.cpuIdleEvent.bind(this));
+ }
+
+ PowerParser.prototype = {
+ __proto__: Parser.prototype,
+
+ cpuStateSlice(ts, targetCpuNumber, eventType, cpuState) {
+ const targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
+ if (eventType !== '1') {
+ this.importer.model.importWarning({
+ type: 'parse_error',
+ message: 'Don\'t understand power_start events of ' +
+ 'type ' + eventType
+ });
+ return;
+ }
+ const powerCounter = targetCpu.getOrCreateCounter('', 'C-State');
+ if (powerCounter.numSeries === 0) {
+ powerCounter.addSeries(new tr.model.CounterSeries('state',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ powerCounter.name + '.' + 'state')));
+ }
+ powerCounter.series.forEach(function(series) {
+ series.addCounterSample(ts, cpuState);
+ });
+ },
+
+ cpuIdleSlice(ts, targetCpuNumber, cpuState) {
+ const targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
+ const powerCounter = targetCpu.getOrCreateCounter('', 'C-State');
+ if (powerCounter.numSeries === 0) {
+ powerCounter.addSeries(new tr.model.CounterSeries('state',
+ ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name)));
+ }
+ // NB: 4294967295/-1 means an exit from the current state
+ const val = (cpuState !== 4294967295 ? cpuState + 1 : 0);
+ powerCounter.series.forEach(function(series) {
+ series.addCounterSample(ts, val);
+ });
+ },
+
+ cpuFrequencySlice(ts, targetCpuNumber, powerState) {
+ const targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
+ const powerCounter =
+ targetCpu.getOrCreateCounter('', 'Clock Frequency');
+ if (powerCounter.numSeries === 0) {
+ powerCounter.addSeries(new tr.model.CounterSeries('state',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ powerCounter.name + '.' + 'state')));
+ }
+ powerCounter.series.forEach(function(series) {
+ series.addCounterSample(ts, powerState);
+ });
+ },
+
+ cpuFrequencyLimitsSlice(ts, targetCpuNumber, minFreq, maxFreq) {
+ const targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
+ const powerCounter =
+ targetCpu.getOrCreateCounter('', 'Clock Frequency Limits');
+ if (powerCounter.numSeries === 0) {
+ powerCounter.addSeries(new tr.model.CounterSeries('Min Frequency',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ powerCounter.name + '.' + 'Min Frequency')));
+ powerCounter.addSeries(new tr.model.CounterSeries('Max Frequency',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ powerCounter.name + '.' + 'Max Frequency')));
+ }
+ powerCounter.series.forEach(function(series) {
+ if (series.name === 'Min Frequency') {
+ series.addCounterSample(ts, minFreq);
+ }
+ if (series.name === 'Max Frequency') {
+ series.addCounterSample(ts, maxFreq);
+ }
+ });
+ },
+
+ /**
+ * Parses power events and sets up state in the importer.
+ */
+ powerStartEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /type=(\d+) state=(\d) cpu_id=(\d+)/.exec(
+ eventBase.details);
+ if (!event) return false;
+
+ const targetCpuNumber = parseInt(event[3]);
+ const cpuState = parseInt(event[2]);
+ this.cpuStateSlice(ts, targetCpuNumber, event[1], cpuState);
+ return true;
+ },
+
+ powerFrequencyEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /type=(\d+) state=(\d+) cpu_id=(\d+)/
+ .exec(eventBase.details);
+ if (!event) return false;
+
+ const targetCpuNumber = parseInt(event[3]);
+ const powerState = parseInt(event[2]);
+ this.cpuFrequencySlice(ts, targetCpuNumber, powerState);
+ return true;
+ },
+
+ cpuFrequencyEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const targetCpuNumber = parseInt(event[2]);
+ const powerState = parseInt(event[1]);
+ this.cpuFrequencySlice(ts, targetCpuNumber, powerState);
+ return true;
+ },
+
+ cpuFrequencyLimitsEvent(eventName, cpu, pid, ts, eventBase) {
+ const event = /min=(\d+) max=(\d+) cpu_id=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const targetCpuNumber = parseInt(event[3]);
+ const minFreq = parseInt(event[1]);
+ const maxFreq = parseInt(event[2]);
+ this.cpuFrequencyLimitsSlice(ts, targetCpuNumber, minFreq, maxFreq);
+ return true;
+ },
+
+ cpuIdleEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ const targetCpuNumber = parseInt(event[2]);
+ const cpuState = parseInt(event[1]);
+ this.cpuIdleSlice(ts, targetCpuNumber, cpuState);
+ return true;
+ }
+ };
+
+ Parser.register(PowerParser);
+
+ return {
+ PowerParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/power_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/power_parser_test.html
new file mode 100644
index 00000000000..99335c464c8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/power_parser_test.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('powerFrequencyImport', function() {
+ const lines = [
+ ' kworker/0:3-6880 [000] 2784.783015: power_frequency: ' +
+ 'type=2 state=1000000 cpu_id=0',
+ ' kworker/1:2-7269 [001] 2784.788993: power_frequency: ' +
+ 'type=2 state=800000 cpu_id=1',
+ ' kworker/1:2-7269 [001] 2784.993120: power_frequency: ' +
+ 'type=2 state=1300000 cpu_id=1'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c0 = m.kernel.cpus[0];
+ assert.strictEqual(c0.slices.length, 0);
+ assert.strictEqual(
+ c0.counters['.Clock Frequency'].series[0].samples.length, 1);
+
+ const c1 = m.kernel.cpus[1];
+ assert.strictEqual(c1.slices.length, 0);
+ assert.strictEqual(
+ c1.counters['.Clock Frequency'].series[0].samples.length, 2);
+ });
+
+ test('cpuFrequencyImport', function() {
+ const lines = [
+ ' kworker/1:0-9665 [001] 15051.007301: cpu_frequency: ' +
+ 'state=800000 cpu_id=1',
+ ' kworker/1:0-9665 [001] 15051.010278: cpu_frequency: ' +
+ 'state=1300000 cpu_id=1',
+ ' kworker/0:2-7972 [000] 15051.010278: cpu_frequency: ' +
+ 'state=1000000 cpu_id=0',
+ ' kworker/0:2-7972 [000] 15051.020304: cpu_frequency: ' +
+ 'state=800000 cpu_id=0'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c0 = m.kernel.cpus[0];
+ assert.strictEqual(c0.slices.length, 0);
+ assert.strictEqual(
+ c0.counters['.Clock Frequency'].series[0].samples.length, 2);
+
+ const c1 = m.kernel.cpus[1];
+ assert.strictEqual(c1.slices.length, 0);
+ assert.strictEqual(
+ c1.counters['.Clock Frequency'].series[0].samples.length, 2);
+ });
+
+ test('cpuIdleImport', function() {
+ const lines = [
+ ' <idle>-0 [000] 15050.992883: cpu_idle: ' +
+ 'state=1 cpu_id=0',
+ ' <idle>-0 [000] 15050.993027: cpu_idle: ' +
+ 'state=4294967295 cpu_id=0',
+ ' <idle>-0 [001] 15050.993132: cpu_idle: ' +
+ 'state=1 cpu_id=1',
+ ' <idle>-0 [001] 15050.993276: cpu_idle: ' +
+ 'state=4294967295 cpu_id=1',
+ ' <idle>-0 [001] 15050.993279: cpu_idle: ' +
+ 'state=3 cpu_id=1',
+ ' <idle>-0 [001] 15050.993457: cpu_idle: ' +
+ 'state=4294967295 cpu_id=1'
+ ];
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const c0 = m.kernel.cpus[0];
+ assert.strictEqual(c0.slices.length, 0);
+ assert.strictEqual(c0.counters['.C-State'].series[0].samples.length, 2);
+
+ const c1 = m.kernel.cpus[1];
+ assert.strictEqual(c1.slices.length, 0);
+ assert.strictEqual(c1.counters['.C-State'].series[0].samples.length, 4);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser.html
new file mode 100644
index 00000000000..c92767eaba2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses regulator events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux regulator trace events.
+ * @constructor
+ */
+ function RegulatorParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('regulator_enable',
+ RegulatorParser.prototype.regulatorEnableEvent.bind(this));
+ importer.registerEventHandler('regulator_enable_delay',
+ RegulatorParser.prototype.regulatorEnableDelayEvent.bind(this));
+ importer.registerEventHandler('regulator_enable_complete',
+ RegulatorParser.prototype.regulatorEnableCompleteEvent.bind(this));
+ importer.registerEventHandler('regulator_disable',
+ RegulatorParser.prototype.regulatorDisableEvent.bind(this));
+ importer.registerEventHandler('regulator_disable_complete',
+ RegulatorParser.prototype.regulatorDisableCompleteEvent.bind(this));
+ importer.registerEventHandler('regulator_set_voltage',
+ RegulatorParser.prototype.regulatorSetVoltageEvent.bind(this));
+ importer.registerEventHandler('regulator_set_voltage_complete',
+ RegulatorParser.prototype.regulatorSetVoltageCompleteEvent.bind(this));
+
+ this.model_ = importer.model_;
+ }
+
+ // Matches the regulator_enable record
+ const regulatorEnableRE = /name=(.+)/;
+
+ // Matches the regulator_disable record
+ const regulatorDisableRE = /name=(.+)/;
+
+ // Matches the regulator_set_voltage_complete record
+ const regulatorSetVoltageCompleteRE = /name=(\S+), val=(\d+)/;
+
+ RegulatorParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Get or create a counter with one series.
+ */
+ getCtr_(ctrName, valueName) {
+ const ctr = this.model_.kernel
+ .getOrCreateCounter(null, 'vreg ' + ctrName + ' ' + valueName);
+ // Initialize the counter's series fields if needed.
+ if (ctr.series[0] === undefined) {
+ ctr.addSeries(new tr.model.CounterSeries(valueName,
+ ColorScheme.getColorIdForGeneralPurposeString(
+ ctrName + '.' + valueName)));
+ }
+ return ctr;
+ },
+
+ /**
+ * Parses regulator events and sets up state in the importer.
+ */
+ regulatorEnableEvent(eventName, cpuNum, pid, ts, eventBase) {
+ const event = regulatorEnableRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const name = event[1];
+
+ const ctr = this.getCtr_(name, 'enabled');
+ ctr.series[0].addCounterSample(ts, 1);
+
+ return true;
+ },
+
+ regulatorEnableDelayEvent(eventName, cpuNum, pid, ts, eventBase) {
+ return true;
+ },
+
+ regulatorEnableCompleteEvent(eventName, cpuNum, pid, ts,
+ eventBase) {
+ return true;
+ },
+
+ regulatorDisableEvent(eventName, cpuNum, pid, ts, eventBase) {
+ const event = regulatorDisableRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const name = event[1];
+
+ const ctr = this.getCtr_(name, 'enabled');
+ ctr.series[0].addCounterSample(ts, 0);
+
+ return true;
+ },
+
+ regulatorDisableCompleteEvent(eventName, cpuNum, pid, ts,
+ eventBase) {
+ return true;
+ },
+
+ regulatorSetVoltageEvent(eventName, cpuNum, pid, ts, eventBase) {
+ return true;
+ },
+
+ regulatorSetVoltageCompleteEvent(eventName, cpuNum, pid, ts,
+ eventBase) {
+ const event = regulatorSetVoltageCompleteRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const name = event[1];
+ const voltage = parseInt(event[2]);
+
+ const ctr = this.getCtr_(name, 'voltage');
+ ctr.series[0].addCounterSample(ts, voltage);
+
+ return true;
+ }
+
+ };
+
+ Parser.register(RegulatorParser);
+
+ return {
+ RegulatorParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser_test.html
new file mode 100644
index 00000000000..55ffc85c4aa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/regulator_parser_test.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('regulatorImport', function() {
+ const lines = [
+ ' kworker/0:2H-14312 [000] ...1 143713.787749: ' +
+ 'regulator_set_voltage: name=krait0 (810000-1100000)',
+ ' kworker/0:2H-14312 [000] ...1 143713.787778: ' +
+ 'regulator_set_voltage_complete: name=krait0, val=810000',
+ ' kworker/0:2H-14312 [000] ...1 143714.037871: ' +
+ 'regulator_set_voltage: name=krait0 (800000-1100000)',
+ ' kworker/0:2H-14312 [000] ...1 143714.037895: ' +
+ 'regulator_set_voltage_complete: name=krait0, val=800000',
+ 'kworker/0:1-30321 [000] ...1 144568.624596: ' +
+ 'regulator_enable: name=8941_smbb_boost',
+ 'kworker/0:1-30321 [000] ...1 144568.624715: ' +
+ 'regulator_enable_delay: name=8941_smbb_boost',
+ 'kworker/0:1-30321 [000] ...1 144568.624723: ' +
+ 'regulator_enable_complete: name=8941_smbb_boost',
+ 'kworker/0:1-30321 [000] ...1 144568.653546: ' +
+ 'regulator_disable: name=8941_smbb_boost',
+ 'kworker/0:1-30321 [000] ...1 144568.654785: ' +
+ 'regulator_disable_complete: name=8941_smbb_boost'
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.property(m.kernel.counters, 'null.vreg krait0 voltage');
+ assert.property(m.kernel.counters, 'null.vreg 8941_smbb_boost enabled');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/rss_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/rss_parser.html
new file mode 100644
index 00000000000..70192df1b5b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/rss_parser.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses rss stat events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses Rss stat trace events.
+ * @constructor
+ */
+ function RssParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('rss_stat',
+ RssParser.prototype.rssStat.bind(this));
+ }
+
+ const TestExports = {};
+
+ // Matches the rss_stat record
+ const rssStatRE = new RegExp('member=(\\d+) size=(\\d+)');
+
+ TestExports.rssStatRE = rssStatRE;
+
+ const unknownThreadName = '<...>';
+
+ RssParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses rss stat events and sets up state in the importer.
+ */
+ rssStat(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = rssStatRE.exec(eventBase.details);
+ if (!event) return false;
+ const member = parseInt(event[1]);
+ const size = parseInt(event[2]);
+
+ if (eventBase.tgid === undefined) {
+ return false;
+ }
+
+ const tgid = parseInt(eventBase.tgid);
+ const process = this.importer.model_.getOrCreateProcess(tgid);
+ let subTitle = '';
+
+ if (member === 0) {
+ subTitle = ' (file pages)';
+ } else if (member === 1) {
+ subTitle = ' (anon)';
+ }
+
+ const rssCounter =
+ process.getOrCreateCounter('RSS', 'RSS ' + member + subTitle);
+ if (rssCounter.numSeries === 0) {
+ rssCounter.addSeries(new tr.model.CounterSeries('RSS',
+ tr.b.ColorScheme.getColorIdForGeneralPurposeString(
+ rssCounter.name)));
+ }
+ rssCounter.series.forEach(function(series) {
+ series.addCounterSample(ts, size);
+ });
+ return true;
+ },
+ };
+
+ Parser.register(RssParser);
+
+ return {
+ RssParser,
+ _RssParserTestExports: TestExports
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/rss_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/rss_parser_test.html
new file mode 100644
index 00000000000..7ac477eed50
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/rss_parser_test.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('rssStatRE', function() {
+ const re = tr.e.importer.linux_perf._RssParserTestExports.rssStatRE;
+ let x = re.exec('rss_stat: member=0 size=536576');
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], '0');
+ assert.strictEqual(x[2], '536576');
+
+ x = re.exec('rss_stat: member=1 size=716800');
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], '1');
+ assert.strictEqual(x[2], '716800');
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser.html
new file mode 100644
index 00000000000..3004f577f1f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+<link rel="import" href="/tracing/model/counter.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses scheduler events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux sched trace events.
+ * @constructor
+ */
+ function SchedParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('sched_switch',
+ SchedParser.prototype.schedSwitchEvent.bind(this));
+ importer.registerEventHandler('sched_wakeup',
+ SchedParser.prototype.schedWakeupEvent.bind(this));
+ importer.registerEventHandler('sched_blocked_reason',
+ SchedParser.prototype.schedBlockedEvent.bind(this));
+ importer.registerEventHandler('sched_cpu_hotplug',
+ SchedParser.prototype.schedCpuHotplugEvent.bind(this));
+ }
+
+ const TestExports = {};
+
+ // Matches the sched_switch record
+ const schedSwitchRE = new RegExp(
+ 'prev_comm=(.+) prev_pid=(\\d+) prev_prio=(\\d+) ' +
+ 'prev_state=(\\S\\+?|\\S\\|\\S) ==> ' +
+ 'next_comm=(.+) next_pid=(\\d+) next_prio=(\\d+)');
+
+ // Matches sched_blocked_reason record
+ const schedBlockedRE = new RegExp('pid=(\\d+) iowait=(\\d) caller=(.+)');
+ TestExports.schedSwitchRE = schedSwitchRE;
+
+ // Matches the sched_wakeup record
+ // success=? is optional not all kernels report it, so don't include
+ // it in the capture groups
+ const schedWakeupRE =
+ /comm=(.+) pid=(\d+) prio=(\d+)(?: success=\d+)? target_cpu=(\d+)/;
+ TestExports.schedWakeupRE = schedWakeupRE;
+
+ const unknownThreadName = '<...>';
+
+ SchedParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses scheduler events and sets up state in the CPUs of the importer.
+ */
+ schedSwitchEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = schedSwitchRE.exec(eventBase.details);
+ if (!event) return false;
+ const prevState = event[4];
+ const nextComm = event[5];
+ const nextPid = parseInt(event[6]);
+ const nextPrio = parseInt(event[7]);
+
+ if (eventBase.tgid !== undefined) {
+ const tgid = parseInt(eventBase.tgid);
+ const process = this.importer.model_.getOrCreateProcess(tgid);
+ const storedThread = process.getThread(pid);
+ if (!storedThread) {
+ const thread = process.getOrCreateThread(pid);
+ thread.name = eventBase.threadName;
+ } else if (storedThread.name === unknownThreadName) {
+ storedThread.name = eventBase.threadName;
+ }
+ }
+
+ const nextThread = this.importer.threadsByLinuxPid[nextPid];
+ let nextName;
+ if (nextThread) {
+ nextName = nextThread.userFriendlyName;
+ } else {
+ nextName = nextComm;
+ }
+
+ const cpu = this.importer.getOrCreateCpu(cpuNumber);
+ cpu.switchActiveThread(
+ ts,
+ {stateWhenDescheduled: prevState},
+ nextPid,
+ nextName,
+ {
+ comm: nextComm,
+ tid: nextPid,
+ prio: nextPrio
+ });
+
+ return true;
+ },
+
+ schedWakeupEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = schedWakeupRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const fromPid = pid;
+ const comm = event[1];
+ pid = parseInt(event[2]);
+ const prio = parseInt(event[3]);
+ this.importer.markPidRunnable(ts, pid, comm, prio, fromPid);
+ return true;
+ },
+
+ schedCpuHotplugEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = /cpu (\d+) (.+) error=(\d+)/.exec(eventBase.details);
+ if (!event) return false;
+
+ cpuNumber = event[1];
+ const state = event[2];
+ const targetCpu = this.importer.getOrCreateCpu(cpuNumber);
+
+ const powerCounter = targetCpu.getOrCreateCounter('', 'Cpu Hotplug');
+ if (powerCounter.numSeries === 0) {
+ powerCounter.addSeries(new tr.model.CounterSeries('State',
+ tr.b.ColorScheme.getColorIdForGeneralPurposeString(
+ powerCounter.name + '.' + 'State')));
+ }
+ powerCounter.series.forEach(function(series) {
+ if (series.name === 'State') {
+ series.addCounterSample(ts, state.localeCompare('offline') ? 0 : 1);
+ }
+ });
+ return true;
+ },
+
+ schedBlockedEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = schedBlockedRE.exec(eventBase.details);
+ if (!event) return false;
+
+ pid = parseInt(event[1]);
+ const iowait = parseInt(event[2]);
+ const caller = event[3];
+
+ this.importer.addPidBlockedReason(ts, pid, iowait, caller);
+ return true;
+ }
+ };
+
+ Parser.register(SchedParser);
+
+ return {
+ SchedParser,
+ _SchedParserTestExports: TestExports
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser_test.html
new file mode 100644
index 00000000000..998d7f4ab21
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sched_parser_test.html
@@ -0,0 +1,262 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('schedSwitchRE', function() {
+ const re = tr.e.importer.linux_perf._SchedParserTestExports.schedSwitchRE;
+ let x = re.exec('prev_comm=swapper prev_pid=0 prev_prio=120 prev_state=R ' +
+ '==> next_comm=SurfaceFlinger next_pid=178 next_prio=112');
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], 'swapper');
+ assert.strictEqual(x[2], '0');
+ assert.strictEqual(x[3], '120');
+ assert.strictEqual(x[4], 'R');
+ assert.strictEqual(x[5], 'SurfaceFlinger');
+ assert.strictEqual(x[6], '178');
+ assert.strictEqual(x[7], '112');
+
+ x = re.exec('prev_comm=.android.chrome prev_pid=1562 prev_prio=120 prev_state=R ==> next_comm=Binder Thread # next_pid=195 next_prio=120'); // @suppress longLineCheck
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], '.android.chrome');
+ assert.strictEqual(x[5], 'Binder Thread #');
+
+ x = re.exec('prev_comm=Binder Thread # prev_pid=1562 prev_prio=120 prev_state=R ==> next_comm=.android.chrome next_pid=195 next_prio=120'); // @suppress longLineCheck
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], 'Binder Thread #');
+ assert.strictEqual(x[5], '.android.chrome');
+
+ // explicit test for prev_state of D|W
+ x = re.exec('prev_comm=.android.chrome prev_pid=1562 prev_prio=120 ' +
+ 'prev_state=D|W ==> next_comm=Binder Thread # next_pid=195 ' +
+ 'next_prio=120');
+ assert.isNotNull(x);
+ assert.strictEqual(x[4], 'D|W');
+ });
+
+ test('schedWakeupRE', function() {
+ const re = tr.e.importer.linux_perf._SchedParserTestExports.schedWakeupRE;
+ const x = re.exec(
+ 'comm=SensorService pid=207 prio=112 success=1 target_cpu=000');
+ assert.isNotNull(x);
+ assert.strictEqual(x[1], 'SensorService');
+ assert.strictEqual(x[2], '207');
+ assert.strictEqual(x[3], '112');
+ assert.strictEqual(x[4], '000');
+ const y = re.exec(
+ 'comm=SensorService pid=207 prio=112 target_cpu=000');
+ assert.isNotNull(y);
+ assert.strictEqual(y[1], 'SensorService');
+ assert.strictEqual(y[2], '207');
+ assert.strictEqual(y[3], '112');
+ assert.strictEqual(y[4], '000');
+ });
+
+ test('importOneSequenceWithSchedWakeUp', function() {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const lines = [
+ 'ndroid.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D ==> next_comm=ndroid.launcher next_pid=584 next_prio=120', // @suppress longLineCheck
+ 'ndroid.launcher-584 [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001', // @suppress longLineCheck
+ 'ndroid.launcher-584 [001] d..3 12622.506950: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: B|128|queueBuffer', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E',
+ ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=ndroid.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const thread = m.findAllThreadsNamed('Binder_1')[0];
+ const timeSlices = thread.timeSlices;
+ assert.strictEqual(timeSlices.length, 4);
+
+ const runningSlice = timeSlices[0];
+ assert.strictEqual(runningSlice.schedulingState, SCHEDULING_STATE.RUNNING);
+ assert.closeTo(12622506.890, runningSlice.start, 1e-5);
+ assert.closeTo(.918 - .890, runningSlice.duration, 1e-5);
+
+ const sleepSlice = timeSlices[1];
+ assert.strictEqual(
+ sleepSlice.schedulingState, SCHEDULING_STATE.UNINTR_SLEEP);
+ assert.closeTo(12622506.918, sleepSlice.start, 1e-5);
+ assert.closeTo(.936 - .918, sleepSlice.duration, 1e-5);
+
+ const wakeupSlice = timeSlices[2];
+ assert.strictEqual(
+ wakeupSlice.schedulingState, SCHEDULING_STATE.RUNNABLE);
+ assert.closeTo(12622506.936, wakeupSlice.start, 1e-5);
+ assert.closeTo(.950 - .936, wakeupSlice.duration, 1e-5);
+ assert.strictEqual(wakeupSlice.args['wakeup from tid'], 584);
+
+ const runningSlice2 = timeSlices[3];
+ assert.strictEqual(
+ runningSlice2.schedulingState, SCHEDULING_STATE.RUNNING);
+ assert.closeTo(12622506.950, runningSlice2.start, 1e-5);
+ assert.closeTo(7.253 - 6.950, runningSlice2.duration, 1e-5);
+ });
+
+ test('importWithUnknownSleepState', function() {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const lines = [
+ 'ndroid.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=F|O ==> next_comm=ndroid.launcher next_pid=584 next_prio=120', // @suppress longLineCheck
+ 'ndroid.launcher-584 [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001', // @suppress longLineCheck
+ 'ndroid.launcher-584 [001] d..3 12622.506950: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: B|128|queueBuffer', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E',
+ ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=F|O ==> next_comm=ndroid.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
+ ];
+
+ let m;
+ assert.doesNotThrow(function() {
+ m = newModel(lines.join('\n'));
+ });
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(
+ m.importWarnings[0].message, 'Unrecognized sleep state: F|O');
+
+ const thread = m.findAllThreadsNamed('Binder_1')[0];
+ const timeSlices = thread.timeSlices;
+
+ assert.strictEqual(timeSlices[1].schedulingState, SCHEDULING_STATE.UNKNOWN);
+ });
+
+ test('importWithUninterruptibleSleep', function() {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const lines = [
+ 'ndroid.launcher-584 [001] d..3 12622.506890: sched_switch: ' +
+ 'prev_comm=ndroid.launcher prev_pid=584 ' +
+ 'prev_prio=120 prev_state=R+ ' +
+ '==> next_comm=Binder_1 next_pid=217 next_prio=120',
+
+ ' Binder_1-217 [001] d..3 12622.506918: sched_switch: ' +
+ 'prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D|K ' +
+ '==> next_comm=ndroid.launcher next_pid=584 next_prio=120',
+
+ 'ndroid.launcher-584 [001] d..4 12622.506936: sched_wakeup: ' +
+ 'comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001',
+
+ 'ndroid.launcher-584 [001] d..3 12622.506950: sched_switch: ' +
+ 'prev_comm=ndroid.launcher prev_pid=584 ' +
+ 'prev_prio=120 prev_state=R+ ' +
+ '==> next_comm=Binder_1 next_pid=217 next_prio=120',
+
+ ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: ' +
+ 'B|128|queueBuffer',
+
+ ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E',
+
+ ' Binder_1-217 [001] d..3 12622.507253: sched_switch: ' +
+ 'prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ' +
+ '==> next_comm=ndroid.launcher next_pid=584 next_prio=120'
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const thread = m.findAllThreadsNamed('Binder_1')[0];
+ const timeSlices = thread.timeSlices;
+ assert.strictEqual(timeSlices.length, 4);
+
+ const wakeKillSlice = timeSlices[1];
+ assert.strictEqual(wakeKillSlice.schedulingState,
+ SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL);
+ assert.closeTo(12622506.918, wakeKillSlice.start, 1e-5);
+ assert.closeTo(.936 - .918, wakeKillSlice.duration, 1e-5);
+ });
+
+ test('importWithUninterruptibleSleepAndBlockedReason', function() {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const lines = [
+ 'ndroid.launcher-584 [001] d..3 12622.506890: sched_switch: ' +
+ 'prev_comm=ndroid.launcher prev_pid=584 ' +
+ 'prev_prio=120 prev_state=R+ ' +
+ '==> next_comm=Binder_1 next_pid=217 next_prio=120',
+
+ ' Binder_1-217 [001] d..3 12622.506918: sched_switch: ' +
+ 'prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D|K ' +
+ '==> next_comm=ndroid.launcher next_pid=584 next_prio=120',
+
+ ' Binder_1-217 [001] d..3 12622.506930: sched_blocked_reason: ' +
+ 'pid=217 iowait=1 caller=sleep_on_page_killable+0x10/0x4c',
+
+ 'ndroid.launcher-584 [001] d..4 12622.506936: sched_wakeup: ' +
+ 'comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001',
+
+ 'ndroid.launcher-584 [001] d..3 12622.506950: sched_switch: ' +
+ 'prev_comm=ndroid.launcher prev_pid=584 ' +
+ 'prev_prio=120 prev_state=R+ ' +
+ '==> next_comm=Binder_1 next_pid=217 next_prio=120',
+
+ ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: ' +
+ 'B|128|queueBuffer',
+
+ ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E',
+
+ ' Binder_1-217 [001] d..3 12622.507253: sched_switch: ' +
+ 'prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ' +
+ '==> next_comm=ndroid.launcher next_pid=584 next_prio=120'
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const thread = m.findAllThreadsNamed('Binder_1')[0];
+ const timeSlices = thread.timeSlices;
+ assert.strictEqual(timeSlices.length, 4);
+
+ const wakeKillSlice = timeSlices[1];
+ assert.strictEqual(wakeKillSlice.schedulingState,
+ SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO);
+ assert.closeTo(12622506.918, wakeKillSlice.start, 1e-5);
+ assert.closeTo(.936 - .918, wakeKillSlice.duration, 1e-5);
+ });
+
+ test('importWithTgids', function() {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const lines = [
+ 'kworker/u12:4-9393 ( 9393) [002] d..3 10386.798979: sched_switch: ' +
+ 'prev_comm=kworker/u12:4 prev_pid=9393 prev_prio=120 ' +
+ 'prev_state=S ==> next_comm=swapper/2 next_pid=0 next_prio=120',
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const p = m.processes[9393];
+ assert.strictEqual(p.pid, 9393);
+ });
+
+ test('importWithMissingNames', function() {
+ const lines = [
+ ' Binder_1-217 ( 438) [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=F|O ==> next_comm=ndroid.launcher next_pid=584 next_prio=120', // @suppress longLineCheck
+ '<...>-584 ( 954) [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001', // @suppress longLineCheck
+ 'ndroid.launcher-584 ( 954) [001] d..3 12622.506950: sched_switch: prev_comm=ndroid.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ];
+
+ const m = newModel(lines.join('\n'));
+ assert.isFalse(m.hasImportWarnings);
+
+ const p = m.processes[954];
+ const t = p.getThread(584);
+ assert.strictEqual(t.name, 'ndroid.launcher');
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser.html
new file mode 100644
index 00000000000..2e96b8714b6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses sync events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux sync trace events.
+ * @constructor
+ */
+ function SyncParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler(
+ 'sync_timeline',
+ SyncParser.prototype.timelineEvent.bind(this));
+ importer.registerEventHandler(
+ 'sync_wait',
+ SyncParser.prototype.syncWaitEvent.bind(this));
+ importer.registerEventHandler(
+ 'sync_pt',
+ SyncParser.prototype.syncPtEvent.bind(this));
+ this.model_ = importer.model_;
+ }
+
+ const syncTimelineRE = /name=(\S+) value=(\S*)/;
+ const syncWaitRE = /(\S+) name=(\S+) state=(\d+)/;
+ const syncPtRE = /name=(\S+) value=(\S*)/;
+
+ SyncParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses sync events and sets up state in the importer.
+ */
+ timelineEvent(eventName, cpuNumber, pid,
+ ts, eventBase) {
+ const event = syncTimelineRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const thread = this.importer.getOrCreatePseudoThread(event[1]);
+
+ if (thread.lastActiveTs !== undefined) {
+ const duration = ts - thread.lastActiveTs;
+ let value = thread.lastActiveValue;
+ if (value === undefined) value = ' ';
+ const slice = new tr.model.ThreadSlice(
+ '', value,
+ ColorScheme.getColorIdForGeneralPurposeString(value),
+ thread.lastActiveTs, {},
+ duration);
+ thread.thread.sliceGroup.pushSlice(slice);
+ }
+ thread.lastActiveTs = ts;
+ thread.lastActiveValue = event[2];
+ return true;
+ },
+
+ syncWaitEvent(eventName, cpuNumber, pid, ts,
+ eventBase) {
+ const event = syncWaitRE.exec(eventBase.details);
+ if (!event) return false;
+
+ if (eventBase.tgid === undefined) {
+ return false;
+ }
+
+ const tgid = parseInt(eventBase.tgid);
+ const thread = this.model_.getOrCreateProcess(tgid)
+ .getOrCreateThread(pid);
+ thread.name = eventBase.threadName;
+ const slices = thread.kernelSliceGroup;
+ if (!slices.isTimestampValidForBeginOrEnd(ts)) {
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Timestamps are moving backward.'
+ });
+ return false;
+ }
+
+ const name = 'fence_wait("' + event[2] + '")';
+ if (event[1] === 'begin') {
+ const slice = slices.beginSlice(null, name, ts, {
+ 'Start state': event[3]
+ });
+ } else if (event[1] === 'end') {
+ if (slices.openSliceCount > 0) {
+ slices.endSlice(ts);
+ }
+ } else {
+ return false;
+ }
+
+ return true;
+ },
+
+ syncPtEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ return !!syncPtRE.exec(eventBase.details);
+ }
+ };
+
+ Parser.register(SyncParser);
+
+ return {
+ SyncParser,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser_test.html
new file mode 100644
index 00000000000..eaf824acad6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/sync_parser_test.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('syncEventImport', function() {
+ const lines = [
+ 's3c-fb-92 ( 0) [000] ...1 7206.550061: sync_timeline: name=s3c-fb value=7094', // @suppress longLineCheck
+ 'TimedEventQueue-2700 ( 0) [001] ...1 7206.569027: sync_wait: begin name=SurfaceView:6 state=1', // @suppress longLineCheck
+ 'TimedEventQueue-2700 ( 0) [001] ...1 7206.569038: sync_pt: name=malitl_124_0x40b6406c value=7289', // @suppress longLineCheck
+ 'TimedEventQueue-2700 ( 0) [001] ...1 7206.569056: sync_pt: name=exynos-gsc.0-src value=25', // @suppress longLineCheck
+ 'TimedEventQueue-2700 ( 0) [001] ...1 7206.569068: sync_wait: end name=SurfaceView:6 state=1', // @suppress longLineCheck
+ 'irq/128-s5p-mfc-62 ( 0) [000] d..3 7206.572402: sync_timeline: name=vb2 value=37', // @suppress longLineCheck
+ 'irq/128-s5p-mfc-62 ( 0) [000] d..3 7206.572475: sync_timeline: name=vb2 value=33', // @suppress longLineCheck
+ 'SurfaceFlinger-225 ( 0) [001] ...1 7206.584769: sync_timeline: name=malitl_124_0x40b6406c value=7290', // @suppress longLineCheck
+ 'kworker/u:5-2269 ( 0) [000] ...1 7206.586745: sync_wait: begin name=display state=1', // @suppress longLineCheck
+ 'kworker/u:5-2269 ( 0) [000] ...1 7206.586750: sync_pt: name=s3c-fb value=7093', // @suppress longLineCheck
+ 'kworker/u:5-2269 ( 0) [000] ...1 7206.586760: sync_wait: end name=display state=1', // @suppress longLineCheck
+ 's3c-fb-92 ( 0) [000] ...1 7206.587193: sync_wait: begin name=vb2 state=0', // @suppress longLineCheck
+ 's3c-fb-92 ( 0) [000] ...1 7206.587198: sync_pt: name=exynos-gsc.0-dst value=27', // @suppress longLineCheck
+ '<idle>-0 ( 0) [000] d.h4 7206.591133: sync_timeline: name=exynos-gsc.0-src value=27', // @suppress longLineCheck
+ '<idle>-0 ( 0) [000] d.h4 7206.591152: sync_timeline: name=exynos-gsc.0-dst value=27', // @suppress longLineCheck
+ 's3c-fb-92 ( 0) [000] ...1 7206.591244: sync_wait: end name=vb2 state=1' // @suppress longLineCheck
+ ];
+
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ let threads = m.getAllThreads();
+ assert.strictEqual(threads.length, 4);
+
+ threads = m.findAllThreadsNamed('s3c-fb');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 1);
+
+ threads = m.findAllThreadsNamed('kworker/u:5');
+ assert.strictEqual(threads.length, 1);
+ assert.strictEqual(threads[0].sliceGroup.length, 1);
+ assert.strictEqual('fence_wait("display")',
+ threads[0].sliceGroup.slices[0].title);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser.html
new file mode 100644
index 00000000000..5e9ab9db1b4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Parses workqueue events in the Linux event trace format.
+ */
+tr.exportTo('tr.e.importer.linux_perf', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Parser = tr.e.importer.linux_perf.Parser;
+
+ /**
+ * Parses linux workqueue trace events.
+ * @constructor
+ */
+ function WorkqueueParser(importer) {
+ Parser.call(this, importer);
+
+ importer.registerEventHandler('workqueue_execute_start',
+ WorkqueueParser.prototype.executeStartEvent.bind(this));
+ importer.registerEventHandler('workqueue_execute_end',
+ WorkqueueParser.prototype.executeEndEvent.bind(this));
+ importer.registerEventHandler('workqueue_queue_work',
+ WorkqueueParser.prototype.executeQueueWork.bind(this));
+ importer.registerEventHandler('workqueue_activate_work',
+ WorkqueueParser.prototype.executeActivateWork.bind(this));
+ }
+
+ // Matches the workqueue_execute_start record
+ // workqueue_execute_start: work struct c7a8a89c: function MISRWrapper
+ const workqueueExecuteStartRE = /work struct (.+): function (\S+)/;
+
+ // Matches the workqueue_execute_start record
+ // workqueue_execute_end: work struct c7a8a89c
+ const workqueueExecuteEndRE = /work struct (.+)/;
+
+ WorkqueueParser.prototype = {
+ __proto__: Parser.prototype,
+
+ /**
+ * Parses workqueue events and sets up state in the importer.
+ */
+ executeStartEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = workqueueExecuteStartRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const kthread = this.importer.getOrCreateKernelThread(
+ eventBase.threadName, pid, pid);
+ kthread.openSliceTS = ts;
+ kthread.openSlice = event[2];
+ return true;
+ },
+
+ executeEndEvent(eventName, cpuNumber, pid, ts, eventBase) {
+ const event = workqueueExecuteEndRE.exec(eventBase.details);
+ if (!event) return false;
+
+ const kthread = this.importer.getOrCreateKernelThread(
+ eventBase.threadName, pid, pid);
+ if (kthread.openSlice) {
+ const slice = new tr.model.ThreadSlice('', kthread.openSlice,
+ ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
+ kthread.openSliceTS,
+ {},
+ ts - kthread.openSliceTS);
+
+ kthread.thread.sliceGroup.pushSlice(slice);
+ }
+ kthread.openSlice = undefined;
+ return true;
+ },
+
+ executeQueueWork(eventName, cpuNumber, pid, ts, eventBase) {
+ // TODO: Do something with this event?
+ return true;
+ },
+
+ executeActivateWork(eventName, cpuNumber, pid, ts, eventBase) {
+ // TODO: Do something with this event?
+ return true;
+ }
+
+ };
+
+ Parser.register(WorkqueueParser);
+
+ return {
+ WorkqueueParser,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser_test.html
new file mode 100644
index 00000000000..dfd6646d27f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/linux_perf/workqueue_parser_test.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('workQueueImport', function() {
+ const lines = [
+ ' kworker/0:3-6880 [000] 2784.771958: workqueue_execute_start: ' +
+ 'work struct ffff8800a5083a20: function intel_unpin_work_fn',
+ ' kworker/0:3-6880 [000] 2784.771966: workqueue_execute_end: ' +
+ 'work struct ffff8800a5083a20',
+ ' kworker/1:2-7269 [001] 2784.805966: workqueue_execute_start: ' +
+ 'work struct ffff88014fb0f158: function do_dbs_timer',
+ ' kworker/1:2-7269 [001] 2784.805975: workqueue_execute_end: ' +
+ 'work struct ffff88014fb0f158'
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.strictEqual(
+ m.processes['6880'].threads['6880'].sliceGroup.length, 1);
+ assert.strictEqual(
+ m.processes['7269'].threads['7269'].sliceGroup.length, 1);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/oboe.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/oboe.html
new file mode 100644
index 00000000000..e9ae74e5e08
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/oboe.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+if (tr.isHeadless) {
+ // oboe requires window; there is no window object in headless mode.
+ // Temporarily make one.
+ global.window = {};
+}
+</script>
+
+<script id="oboe-script" src="/oboe/dist/oboe-browser.js"></script>
+
+<script>
+'use strict';
+if (tr.isVinn) {
+ global.oboe = global.window.oboe;
+ global.window = undefined;
+} else if (tr.isNode) {
+ // Use the node.js version instead.
+ global.window = undefined;
+ const path = HTMLImportsLoader.hrefToAbsolutePath('/oboe/dist/oboe-node.js');
+ global.oboe = require(path);
+}
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/pako.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/pako.html
new file mode 100644
index 00000000000..691a55c0217
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/pako.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+
+<script src="/pako.min.js"></script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/profiling_dictionary_reader.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/profiling_dictionary_reader.html
new file mode 100644
index 00000000000..ae8c51334e8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/profiling_dictionary_reader.html
@@ -0,0 +1,315 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.importer', function() {
+ const STRING_ID_SUFFIX = '_sid';
+ const PLURAL_STRING_ID_SUFFIX = '_sids';
+
+ function isStringReference(s) {
+ return s.endsWith(STRING_ID_SUFFIX) || s.endsWith(PLURAL_STRING_ID_SUFFIX);
+ }
+
+ function getStringReferenceName(name) {
+ if (name.endsWith(PLURAL_STRING_ID_SUFFIX)) {
+ return name.slice(0, -PLURAL_STRING_ID_SUFFIX.length);
+ }
+ return name.slice(0, -STRING_ID_SUFFIX.length);
+ }
+
+ function deferenceStrings(idToString, o) {
+ const clone = Object.assign({}, o);
+ for (const [key, value] of Object.entries(clone)) {
+ if (isStringReference(key)) {
+ const name = getStringReferenceName(key);
+ clone[name] = idToString(value);
+ }
+ }
+ return clone;
+ }
+
+ function singularize(word) {
+ if (word.endsWith('s')) {
+ return word.slice(0, -1);
+ }
+ return word;
+ }
+
+ function getMetadataPairs(dataJson) {
+ const isMetadata = v => typeof v !== 'object' || Array.isArray(v);
+ const pairs = Object.entries(dataJson);
+ const metadataPairs = pairs.filter(([_, v]) => isMetadata(v));
+ return metadataPairs;
+ }
+
+ function getGroupPairs(dataJson) {
+ const pairs = Object.entries(dataJson);
+ const nonMapPairs = pairs.filter(([k, _]) => k !== 'maps');
+ const groupPairs = nonMapPairs.filter(([_, v]) => typeof v === 'object');
+ return groupPairs;
+ }
+
+ function createMap(mapJson) {
+ const map = new Map();
+ for (const entry of mapJson) {
+ if (entry.id === undefined) {
+ throw new Error('Missing required key "id" in streaming event.');
+ }
+ map.set(entry.id, entry);
+ }
+ return map;
+ }
+
+ function createMaps(mapsJson) {
+ const maps = new Map();
+ for (const [name, mapJson] of Object.entries(mapsJson)) {
+ maps.set(name, createMap(mapJson));
+ }
+ return maps;
+ }
+
+ function createGroup(groupJson, opt_startTime) {
+ const entries = [];
+ const n = Object.values(groupJson)[0].length;
+
+ for (let i = 0; i < n; i++) {
+ const entry = {};
+ for (const name in groupJson) {
+ entry[name] = groupJson[name][i];
+ }
+ entries.push(entry);
+ }
+
+ const timeDelta = groupJson.timeDelta;
+ if (opt_startTime === undefined && timeDelta !== undefined) {
+ throw new Error('Missing required key "startTime" in streaming event.');
+ }
+
+ if (opt_startTime) {
+ let delta = 0;
+ for (const entry of entries) {
+ delta += entry.timeDelta ? entry.timeDelta : 0;
+ entry.time = opt_startTime + delta;
+ }
+ }
+
+ return entries;
+ }
+
+ function createGroups(groupsJson, opt_startTime) {
+ const groups = new Map();
+ for (const [name, groupJson] of Object.entries(groupsJson)) {
+ groups.set(name, createGroup(groupJson, opt_startTime));
+ }
+
+ return groups;
+ }
+
+ function createMetadata(metadataPairs) {
+ const metadata = new Map();
+ for (const [name, value] of metadataPairs) {
+ metadata.set(name, value);
+ }
+ if (metadata.get('version') === undefined) {
+ throw new Error('Missing required key "version" in streaming event.');
+ }
+ return metadata;
+ }
+
+ /**
+ * Extracts data from a profiling dictionary. See goo.gl/R0Ae4f.
+ *
+ * A profiling dictionary is a compressed format that is good for recording
+ * sampling data. ProfilingDictionaryReader unpacks that data. To use the
+ * ProfilingDictionaryReader first create an 'empty' reader using .empty()
+ * then call #expandData(data) on your dictionary or the helper:
+ * #expandEvent(event) on a tracing event containing the profiling dictionary.
+ * ProfilingDictionaryReader is an immutable data structure so these methods
+ * don't modify the ProfilingDictionaryReader instead they return new
+ * ProfilingDictionaryReaders which wrap the data you passed. To access the
+ * unpacked data use the #inflated property and the #getMapValue() method.
+ *
+ * Usage example, given input like:
+ * $ let input = {
+ * version: 1,
+ * allocators: {
+ * books: {
+ * authors: [1, 1, 2],
+ * title_sid: [10, 11, 12],
+ * },
+ * },
+ * maps: {
+ * authors: [
+ * { id: 1, name_sid: 1 },
+ * { id: 2, name_sid: 2 },
+ * ],
+ * strings: [
+ * { id: 1, string: 'DFW' },
+ * { id: 2, string: 'C. Stross' },
+ * { id: 10, string: 'Book A' },
+ * { id: 11, string: 'Book B' },
+ * { id: 12, string: 'Book C' },
+ * ],
+ * }
+ * };
+ * We can create an empty reader:
+ * $ let reader = ProfilingDictionaryReader.empty();
+ * Then read in the input:
+ * $ reader = reader.expandData(input);
+ * Then view the expanded data:
+ * $ console.log(reader.inflated);
+ * {
+ * books: [
+ * { author: { id: 1, name: 'DFW' }, title: "Book A", },
+ * { author: { id: 2, name: 'C. Stross' }, title: "Book B", },
+ * { author: { id: 2, name: 'C. Stross' }, title: "Book C", },
+ * ],
+ * }
+ *
+ */
+ class ProfilingDictionaryReader {
+ constructor(opt_metadata, opt_maps, opt_groups, opt_parent) {
+ this.metadata = opt_metadata || new Map();
+ this.maps = opt_maps || new Map();
+ this.groups = opt_groups || new Map();
+ this.parent_ = opt_parent || undefined;
+ this.inflated_ = undefined;
+ this.raw_ = undefined;
+ this.boundGetString_ = this.getString.bind(this);
+ this.deferenceStrings_ = o => deferenceStrings(this.boundGetString_, o);
+ }
+
+ /**
+ * Creates an empty ProfilingDictionaryReader.
+ */
+ static empty() {
+ return new ProfilingDictionaryReader();
+ }
+
+ /**
+ * Returns the parent or null if this is the root ProfilingDictionaryReader.
+ */
+ get parent() {
+ return this.parent_;
+ }
+
+ get raw() {
+ if (this.raw_) return this.raw_;
+ this.raw_ = {};
+ for (const [name, group] of this.groups.entries()) {
+ this.raw_[name] = group;
+ }
+ return this.raw_;
+ }
+
+ get inflated() {
+ if (this.inflated_) return this.inflated_;
+ this.inflated_ = {};
+ for (const [name, group] of this.groups.entries()) {
+ this.inflated_[name] = this.inflateGroup(group);
+ }
+ return this.inflated_;
+ }
+
+ /**
+ * Get a map from the newest event by name.
+ * If no map with that name was present returns an empty Map.
+ */
+ getNewMap(name) {
+ return this.maps.get(name) || new Map();
+ }
+
+ /**
+ * Get a record with the id |id| from the map with name |mapName|.
+ * This method searches through the expanded events in reverse order of
+ * expansion until it finds a matching value. If no value matches returns
+ * undefined.
+ */
+ getMapValue(mapName, id) {
+ let value = this.getNewMap(mapName).get(id);
+ if (value === undefined && this.parent) {
+ value = this.parent.getMapValue(mapName, id);
+ }
+ return value;
+ }
+
+ /**
+ * Get the string with the id |id|.
+ * This method searches through the expanded events in reverse order of
+ * expansion until it finds a string with the matching id. If there is no
+ * matching string with returns undefined.
+ */
+ getString(id) {
+ const value = this.getMapValue('strings', id);
+ if (value === undefined) return undefined;
+ return value.string;
+ }
+
+ /**
+ * True iff this or any parent has a map with name |name|.
+ */
+ hasMap(name) {
+ if (this.maps.has(name)) return true;
+ if (this.parent === undefined) return false;
+ return this.parent.hasMap(name);
+ }
+
+ inflateGroup(group) {
+ return group.map(this.inflateEntry.bind(this));
+ }
+
+ inflateEntry(entry) {
+ const inflatedEntry = {};
+ for (const [name, value] of Object.entries(entry)) {
+ let inflatedValue;
+ if (this.hasMap(name)) {
+ const id = value;
+ inflatedValue = this.deferenceStrings_(this.getMapValue(name, id));
+ } else {
+ inflatedValue = value;
+ }
+ inflatedEntry[singularize(name)] = inflatedValue;
+ }
+ return this.deferenceStrings_(inflatedEntry);
+ }
+
+ /**
+ * Returns a new ProfilingDictionaryReader with this
+ * ProfilingDictionaryReader as its parent and the fields 'maps', 'groups'
+ * and 'metadata' filled in based on |data|.
+ */
+ expandData(data) {
+ const mapsJson = data.maps || {};
+ const groupsJson = data.allocators || {};
+ const metadataPairs = getMetadataPairs(data);
+ const metadata = createMetadata(metadataPairs);
+ const opt_startTime = metadata.get('startTime');
+ const maps = createMaps(mapsJson);
+ const groups = createGroups(groupsJson, opt_startTime);
+ return new ProfilingDictionaryReader(metadata, maps, groups, this);
+ }
+
+ /**
+ * Convenience method for this.expandData(event.args.data).
+ */
+ expandEvent(event) {
+ return this.expandData(event.args.data);
+ }
+ }
+
+ return {
+ ProfilingDictionaryReader,
+ singularize,
+ deferenceStringsForTest: deferenceStrings,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/profiling_dictionary_reader_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/profiling_dictionary_reader_test.html
new file mode 100644
index 00000000000..fb622e1fac9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/profiling_dictionary_reader_test.html
@@ -0,0 +1,275 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/profiling_dictionary_reader.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function makeEvent(json) {
+ return {
+ args: {
+ data: json
+ },
+ };
+ }
+
+ test('deferenceStrings', function() {
+ const stringToId = id => '' + id;
+ const result = tr.e.importer.deferenceStringsForTest(stringToId, {
+ foo: 'foo',
+ one_bar_sid: 1,
+ many_baz_sids: 2,
+ });
+ assert.deepEqual(result, {
+ foo: 'foo',
+ one_bar_sid: 1,
+ many_baz_sids: 2,
+ one_bar: '1',
+ many_baz: '2',
+ });
+ });
+
+ test('singularize', function() {
+ assert.strictEqual('name', tr.e.importer.singularize('names'));
+ assert.strictEqual('aircraft', tr.e.importer.singularize('aircraft'));
+ });
+
+ test('throws_an_error_if_version_key_missing', function() {
+ const data = {};
+ const expander = new tr.e.importer.ProfilingDictionaryReader();
+ assert.throws(() => expander.expandData(data));
+ });
+
+ test('throws_an_error_if_map_entry_is_missing_an_id', function() {
+ const data = {
+ maps: {
+ version: 1,
+ price: [
+ { 'i_dont_have_an_id_key': 100 },
+ ],
+ },
+ };
+ const expander = new tr.e.importer.ProfilingDictionaryReader();
+ assert.throws(() => expander.expandData(data));
+ });
+
+ test('has_an_empty_constructor_to_create_an_empty_reader', function() {
+ const expander = tr.e.importer.ProfilingDictionaryReader.empty();
+ assert.strictEqual(expander.metadata.size, 0);
+ assert.deepEqual(expander.raw, {});
+ assert.deepEqual(expander.inflated, {});
+ });
+
+ test('reads_extra_metadata', function() {
+ const data = {
+ version: 1,
+ myStringMetadata: '1',
+ myNumberMetadata: 2,
+ myArrayMetadata: [3],
+ };
+ const expander1 = new tr.e.importer.ProfilingDictionaryReader();
+ const expander2 = expander1.expandData(data);
+ assert.deepEqual(expander2.metadata.get('myStringMetadata'), '1');
+ assert.deepEqual(expander2.metadata.get('myNumberMetadata'), 2);
+ assert.deepEqual(expander2.metadata.get('myArrayMetadata'), [3]);
+ });
+
+ test('reads_a_single_event_with_single_group_and_single_row', function() {
+ const data = {
+ version: 1,
+ allocators: {
+ books: {
+ page_counts: [10, 20, 30],
+ },
+ },
+ };
+ const expander1 = new tr.e.importer.ProfilingDictionaryReader();
+ const expander2 = expander1.expandData(data);
+ assert.deepEqual(expander2.raw.books, [
+ { page_counts: 10 },
+ { page_counts: 20 },
+ { page_counts: 30 },
+ ]);
+ // Note that the 'inflated' property singularizes key names.
+ assert.deepEqual(expander2.inflated.books, [
+ { page_count: 10 },
+ { page_count: 20 },
+ { page_count: 30 },
+ ]);
+ });
+
+ test('supports_persistant_maps', function() {
+ const expander1 = new tr.e.importer.ProfilingDictionaryReader();
+ const expander2 = expander1.expandData({
+ version: 1,
+ maps: {
+ authors: [{ id: 0, name: 'DE Knuth' }],
+ },
+ });
+ const expander3 = expander2.expandData({
+ version: 1,
+ maps: {
+ authors: [{ id: 1, name: 'JH Morris' }],
+ papers: [{ id: 0, title: 'Literate programming', citations: 1378 }],
+ },
+ });
+ assert.isTrue(expander3.hasMap('authors'));
+ assert.isTrue(expander3.hasMap('papers'));
+ assert.isFalse(expander3.hasMap('books'));
+ assert.strictEqual(expander3.getMapValue('authors', 0).name, 'DE Knuth');
+ assert.strictEqual(expander3.getMapValue('authors', 1).name, 'JH Morris');
+ assert.strictEqual(expander3.getMapValue('papers', 0).citations, 1378);
+ assert.strictEqual(expander3.getMapValue('papers', 1), undefined);
+
+ assert.strictEqual(expander2.getMapValue('authors', 0).name, 'DE Knuth');
+ assert.strictEqual(expander2.getMapValue('authors', 1), undefined);
+ });
+
+ test('has_special_support_for_start_time', function() {
+ const expander1 = new tr.e.importer.ProfilingDictionaryReader();
+ const expander2 = expander1.expandData({
+ version: 1,
+ startTime: 100,
+ allocators: {
+ sales: {
+ price: [1, 2, 3, 4],
+ },
+ },
+ });
+ assert.deepEqual(expander2.inflated.sales, [
+ { time: 100, price: 1 },
+ { time: 100, price: 2 },
+ { time: 100, price: 3 },
+ { time: 100, price: 4 },
+ ]);
+ });
+
+ test('has_special_support_for_time_deltas', function() {
+ const expander1 = new tr.e.importer.ProfilingDictionaryReader();
+ const expander2 = expander1.expandData({
+ version: 1,
+ startTime: 100,
+ allocators: {
+ sales: {
+ timeDelta: [1, 1, 10, 10],
+ price: [1, 2, 3, 4],
+ },
+ },
+ });
+ assert.deepEqual(expander2.inflated.sales, [
+ { time: 101, timeDelta: 1, price: 1 },
+ { time: 102, timeDelta: 1, price: 2 },
+ { time: 112, timeDelta: 10, price: 3 },
+ { time: 122, timeDelta: 10, price: 4 },
+ ]);
+ });
+
+ test('has_special_support_for_strings', function() {
+ const expander1 = new tr.e.importer.ProfilingDictionaryReader();
+ const expander2 = expander1.expandData({
+ version: 1,
+ allocators: {
+ books: {
+ authors: [1, 1, 2, 3],
+ isbn: [100, 101, 102, 103],
+ title_sid: [10, 11, 12, 13],
+ },
+ },
+ maps: {
+ authors: [
+ { id: 1, name_sid: 1 },
+ { id: 2, name_sid: 1 },
+ { id: 3, name_sid: 2 },
+ ],
+ strings: [
+ { id: 1, string: 'DFW' },
+ { id: 2, string: 'C. Stross' },
+ { id: 2, string: 'C. Stross' },
+ { id: 10, string: 'Infinite Jest' },
+ { id: 11, string: 'The Laundry Files' },
+ { id: 12, string: 'Accelerando' },
+ { id: 13, string: 'Halting State' },
+ ],
+ },
+ });
+
+ assert.strictEqual(expander2.inflated.books[0].author.name, 'DFW');
+ assert.strictEqual(expander2.inflated.books[0].isbn, 100);
+ assert.strictEqual(expander2.inflated.books[0].title, 'Infinite Jest');
+ });
+
+ test('can_parse_events_directly', function() {
+ const data = {
+ version: 1,
+ allocators: {
+ books: {
+ pages: [10, 20, 30],
+ },
+ },
+ };
+ const expander1 = new tr.e.importer.ProfilingDictionaryReader();
+ const expander2 = expander1.expandEvent(makeEvent(data));
+ assert.deepEqual(expander2.raw.books, [
+ { pages: 10 },
+ { pages: 20 },
+ { pages: 30 },
+ ]);
+ });
+
+ test('full_example', function() {
+ let reader = new tr.e.importer.ProfilingDictionaryReader();
+ reader = reader.expandData({
+ version: 1,
+ maps: {
+ authors: [
+ { id: 1, name_sid: 1 },
+ ],
+ strings: [
+ { id: 1, string: 'DFW' },
+ { id: 10, string: 'Book A' },
+ { id: 11, string: 'Book B' },
+ ],
+ }
+ });
+ reader = reader.expandData({
+ version: 1,
+ startTime: 1992,
+ allocators: {
+ books: {
+ timeDelta: [1, 0, 2, 3],
+ authors: [1, 1, 2, 2],
+ isbns: [100, 101, 102, 103],
+ title_sid: [10, 11, 12, 13],
+ },
+ papers: {
+ authors: [1, 1, 2, 2],
+ },
+ },
+ maps: {
+ authors: [
+ { id: 2, name_sid: 2 },
+ ],
+ strings: [
+ { id: 2, string: 'C. Stross' },
+ { id: 12, string: 'Book C' },
+ { id: 13, string: 'Book D' },
+ ],
+ }
+ });
+
+ assert.strictEqual(reader.getMapValue('strings', 1).string, 'DFW');
+ assert.strictEqual(reader.getString(2), 'C. Stross');
+ assert.strictEqual(reader.inflated.books[0].author.name, 'DFW');
+ assert.strictEqual(reader.inflated.books[0].isbn, 100);
+ assert.strictEqual(reader.inflated.books[0].title, 'Book A');
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace2html_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace2html_importer.html
new file mode 100644
index 00000000000..270db638f66
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace2html_importer.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/base/trace_stream.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/importer/simple_line_reader.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.importer', function() {
+ function Trace2HTMLImporter(model, events) {
+ this.importPriority = 0;
+ }
+
+ Trace2HTMLImporter.subtraces_ = [];
+
+ function _extractEventsFromHTML(text) {
+ // Clear the array before pushing data to it.
+ Trace2HTMLImporter.subtraces_ = [];
+
+ const r = new tr.importer.SimpleLineReader(text);
+
+ // Try to find viewer-data...
+ while (true) {
+ if (!r.advanceToLineMatching(
+ new RegExp('^<\s*script id="viewer-data" ' +
+ 'type="(application\/json|text\/plain)">\r?$'))) {
+ break;
+ }
+
+ r.beginSavingLines();
+ if (!r.advanceToLineMatching(/^<\/\s*script>\r?$/)) return;
+
+ let rawEvents = r.endSavingLinesAndGetResult();
+
+ // Drop off first and last event as it contains the end script tag.
+ rawEvents = rawEvents.slice(1, rawEvents.length - 1);
+ const data64 = rawEvents.join('\n');
+ const buffer = new ArrayBuffer(
+ tr.b.Base64.getDecodedBufferLength(data64));
+ const len = tr.b.Base64.DecodeToTypedArray(data64, new DataView(buffer));
+ Trace2HTMLImporter.subtraces_.push(buffer.slice(0, len));
+ }
+ }
+
+ function _canImportFromHTML(text) {
+ if (!/^<!DOCTYPE html>/.test(text)) return false;
+
+ // Try to find viewer-data...
+ _extractEventsFromHTML(text);
+ if (Trace2HTMLImporter.subtraces_.length === 0) return false;
+ return true;
+ }
+
+ Trace2HTMLImporter.canImport = function(events) {
+ if (events instanceof tr.b.TraceStream) return false;
+ return _canImportFromHTML(events);
+ };
+
+ Trace2HTMLImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'Trace2HTMLImporter';
+ },
+
+ isTraceDataContainer() {
+ return true;
+ },
+
+ extractSubtraces() {
+ return Trace2HTMLImporter.subtraces_;
+ },
+
+ importEvents() {
+ }
+ };
+
+
+ tr.importer.Importer.register(Trace2HTMLImporter);
+
+
+ return {
+ Trace2HTMLImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace2html_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace2html_importer_test.html
new file mode 100644
index 00000000000..9e268b6e7b1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace2html_importer_test.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="improt" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/extras/importer/trace2html_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Base64 = tr.b.Base64;
+
+ test('simple', function() {
+ const htmlLines = [
+ '<!DOCTYPE html>',
+ '<script id="viewer-data" type="application/json">',
+ Base64.btoa('hello'),
+ '<\/script>',
+ '<script id="viewer-data" type="text/plain">',
+ Base64.btoa('world'),
+ '<\/script>',
+ '</html>'
+ ];
+ const htmlText = htmlLines.join('\n');
+ assert.isTrue(tr.e.importer.Trace2HTMLImporter.canImport(htmlText));
+
+ const m = new tr.Model();
+ const imp = new tr.e.importer.Trace2HTMLImporter(m, htmlText);
+ const subTracesAsBuffers = imp.extractSubtraces();
+ const subTracesAsStrings = subTracesAsBuffers.map(function(buffer) {
+ let str = '';
+ const ary = new Uint8Array(buffer);
+ for (let i = 0; i < ary.length; i++) {
+ str += String.fromCharCode(ary[i]);
+ }
+ return str;
+ });
+ assert.deepEqual(subTracesAsStrings, ['hello', 'world']);
+ });
+
+ test('windowsLineEndings', function() {
+ const htmlLines = [
+ '<!DOCTYPE html>',
+ '<script id="viewer-data" type="application/json">',
+ Base64.btoa('hello'),
+ '<\/script>',
+ '<script id="viewer-data" type="text/plain">',
+ Base64.btoa('world'),
+ '<\/script>',
+ '</html>'
+ ];
+ const htmlText = htmlLines.join('\r\n');
+ assert.isTrue(tr.e.importer.Trace2HTMLImporter.canImport(htmlText));
+
+ const m = new tr.Model();
+ const imp = new tr.e.importer.Trace2HTMLImporter(m, htmlText);
+ const subTracesAsBuffers = imp.extractSubtraces();
+ const subTracesAsStrings = subTracesAsBuffers.map(function(buffer) {
+ let str = '';
+ const ary = new Uint8Array(buffer);
+ for (let i = 0; i < ary.length; i++) {
+ str += String.fromCharCode(ary[i]);
+ }
+ return str;
+ });
+ assert.deepEqual(subTracesAsStrings, ['hello', 'world']);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_entry.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_entry.html
new file mode 100644
index 00000000000..56201a0d2c0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_entry.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/source_info/js_source_info.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview TraceCodeEntry is a wrapper around the V8 CodeEntry that
+ * extracts extra context information for each item. This includes things like
+ * the source file, line and if the function is a native method or not.
+ */
+tr.exportTo('tr.e.importer', function() {
+ function TraceCodeEntry(address, size, name, scriptId) {
+ this.id_ = tr.b.GUID.allocateSimple();
+ this.address_ = address;
+ this.size_ = size;
+
+ // Stolen from DevTools TimelineJSProfileProcessor._buildCallFrame
+ // Code states:
+ // (empty) -> compiled
+ // ~ -> optimizable
+ // * -> optimized
+ const rePrefix = /^(\w*:)?([*~]?)(.*)$/m;
+ const tokens = rePrefix.exec(name);
+ const prefix = tokens[1];
+ let state = tokens[2];
+ const body = tokens[3];
+
+ if (state === '*') {
+ state = tr.model.source_info.JSSourceState.OPTIMIZED;
+ } else if (state === '~') {
+ state = tr.model.source_info.JSSourceState.OPTIMIZABLE;
+ } else if (state === '') {
+ state = tr.model.source_info.JSSourceState.COMPILED;
+ } else {
+ state = tr.model.source_info.JSSourceState.UNKNOWN;
+ }
+
+ let rawName;
+ let rawUrl;
+ if (prefix === 'Script:') {
+ rawName = '';
+ rawUrl = body;
+ } else {
+ const spacePos = body.lastIndexOf(' ');
+ rawName = spacePos !== -1 ? body.substr(0, spacePos) : body;
+ rawUrl = spacePos !== -1 ? body.substr(spacePos + 1) : '';
+ }
+
+ function splitLineAndColumn(url) {
+ const lineColumnRegEx = /(?::(\d+))?(?::(\d+))?$/;
+ const lineColumnMatch = lineColumnRegEx.exec(url);
+ let lineNumber;
+ let columnNumber;
+
+ if (typeof(lineColumnMatch[1]) === 'string') {
+ lineNumber = parseInt(lineColumnMatch[1], 10);
+ // Immediately convert line and column to 0-based numbers.
+ lineNumber = isNaN(lineNumber) ? undefined : lineNumber - 1;
+ }
+ if (typeof(lineColumnMatch[2]) === 'string') {
+ columnNumber = parseInt(lineColumnMatch[2], 10);
+ columnNumber = isNaN(columnNumber) ? undefined : columnNumber - 1;
+ }
+
+ return {
+ url: url.substring(0, url.length - lineColumnMatch[0].length),
+ lineNumber,
+ columnNumber
+ };
+ }
+
+ const nativeSuffix = ' native';
+ const isNative = rawName.endsWith(nativeSuffix);
+ this.name_ =
+ isNative ? rawName.slice(0, -nativeSuffix.length) : rawName;
+
+ const urlData = splitLineAndColumn(rawUrl);
+ const url = urlData.url || '';
+ const line = urlData.lineNumber || 0;
+ const column = urlData.columnNumber || 0;
+
+ this.sourceInfo_ = new tr.model.source_info.JSSourceInfo(
+ url, line, column, isNative, scriptId, state);
+ }
+
+ TraceCodeEntry.prototype = {
+ get id() {
+ return this.id_;
+ },
+
+ get sourceInfo() {
+ return this.sourceInfo_;
+ },
+
+ get name() {
+ return this.name_;
+ },
+
+ set address(address) {
+ this.address_ = address;
+ },
+
+ get address() {
+ return this.address_;
+ },
+
+ set size(size) {
+ this.size_ = size;
+ },
+
+ get size() {
+ return this.size_;
+ }
+ };
+
+ return {
+ TraceCodeEntry,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_entry_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_entry_test.html
new file mode 100644
index 00000000000..422350f04ba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_entry_test.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/trace_code_entry.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('lazy_compile_method', function() {
+ const tce = new tr.e.importer.TraceCodeEntry(
+ '0x123', 10, 'Handler:timeStamp', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, 'timeStamp');
+ assert.strictEqual(tce.sourceInfo.isNative, false);
+ assert.strictEqual(tce.sourceInfo.file, '');
+ assert.strictEqual(tce.sourceInfo.line, -1);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+ });
+
+ test('non_lazy_compile_method', function() {
+ const tce = new tr.e.importer.TraceCodeEntry(
+ '0x123', 10, 'Handler:timeStamp', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, 'timeStamp');
+ assert.strictEqual(tce.sourceInfo.state, 'compiled');
+ assert.strictEqual(tce.sourceInfo.isNative, false);
+ assert.strictEqual(tce.sourceInfo.file, '');
+ assert.strictEqual(tce.sourceInfo.line, -1);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+ });
+
+ test('native_matching', function() {
+ const tce = new tr.e.importer.TraceCodeEntry('0x123', 10,
+ 'LazyCompile:~IsAccessorDescriptor native v8natives.js:183', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, 'IsAccessorDescriptor');
+ assert.strictEqual(tce.sourceInfo.isNative, true);
+ assert.strictEqual(tce.sourceInfo.state, 'optimizable');
+ assert.strictEqual(tce.sourceInfo.file, 'v8natives.js');
+ assert.strictEqual(tce.sourceInfo.line, 182);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+ });
+
+ test('strips_*_from_name', function() {
+ const tce = new tr.e.importer.TraceCodeEntry('0x123', 10,
+ 'LazyCompile:*IsAccessorDescriptor native v8natives.js:183', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, 'IsAccessorDescriptor');
+ assert.strictEqual(tce.sourceInfo.isNative, true);
+ assert.strictEqual(tce.sourceInfo.state, 'optimized');
+ assert.strictEqual(tce.sourceInfo.file, 'v8natives.js');
+ assert.strictEqual(tce.sourceInfo.line, 182);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+ });
+
+ test('non_native_matching', function() {
+ const tce = new tr.e.importer.TraceCodeEntry('0x123', 10,
+ 'LazyCompile:~IsAccessorDescriptor v8natives.js:183', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, 'IsAccessorDescriptor');
+ assert.strictEqual(tce.sourceInfo.isNative, false);
+ assert.strictEqual(tce.sourceInfo.file, 'v8natives.js');
+ assert.strictEqual(tce.sourceInfo.line, 182);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+ });
+
+ test('lazy_compile_without_script', function() {
+ const tce = new tr.e.importer.TraceCodeEntry(
+ '0x123', 10, 'LazyCompile:~Object', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, 'Object');
+ assert.strictEqual(tce.sourceInfo.isNative, false);
+ assert.strictEqual(tce.sourceInfo.file, '');
+ assert.strictEqual(tce.sourceInfo.line, -1);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+ });
+
+ test('line_matching_without_script', function() {
+ const tce = new tr.e.importer.TraceCodeEntry('0x123', 10,
+ 'LazyCompile:~Object :220', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, 'Object');
+ assert.strictEqual(tce.sourceInfo.isNative, false);
+ assert.strictEqual(tce.sourceInfo.file, '');
+ assert.strictEqual(tce.sourceInfo.line, 219);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+ });
+
+ test('unknown_method_name', function() {
+ let tce = new tr.e.importer.TraceCodeEntry('0x123', 10, 'LazyCompile:', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, '');
+ assert.strictEqual(tce.sourceInfo.isNative, false);
+ assert.strictEqual(tce.sourceInfo.file, '');
+ assert.strictEqual(tce.sourceInfo.line, -1);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+
+ tce = new tr.e.importer.TraceCodeEntry(
+ '0x123', 10, 'LazyCompile:~ :37', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, '');
+ assert.strictEqual(tce.sourceInfo.isNative, false);
+ assert.strictEqual(tce.sourceInfo.file, '');
+ assert.strictEqual(tce.sourceInfo.line, 36);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+
+ tce = new tr.e.importer.TraceCodeEntry('0x123', 10,
+ 'LazyCompile:~ native liveedit.js:37:10', 12);
+ assert.strictEqual(tce.size, 10);
+ assert.strictEqual(tce.name, '');
+ assert.strictEqual(tce.sourceInfo.isNative, true);
+ assert.strictEqual(tce.sourceInfo.file, 'liveedit.js');
+ assert.strictEqual(tce.sourceInfo.line, 36);
+ assert.strictEqual(tce.sourceInfo.column, 9);
+ assert.strictEqual(tce.sourceInfo.scriptId, 12);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_map.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_map.html
new file mode 100644
index 00000000000..b66df9155de
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_code_map.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel='import' href='/tracing/extras/importer/trace_code_entry.html'>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.importer', function() {
+ // This code is a tracification of:
+ // devtools/front_end/timeline/TimelineJSProfile.js
+ function TraceCodeMap() {
+ this.banks_ = new Map();
+ }
+
+ TraceCodeMap.prototype = {
+ addEntry(addressHex, size, name, scriptId) {
+ const entry = new tr.e.importer.TraceCodeEntry(
+ this.getAddress_(addressHex), size, name, scriptId);
+
+ this.addEntry_(addressHex, entry);
+ },
+
+ moveEntry(oldAddressHex, newAddressHex, size) {
+ const entry = this.getBank_(oldAddressHex)
+ .removeEntry(this.getAddress_(oldAddressHex));
+ if (!entry) return;
+
+ entry.address = this.getAddress_(newAddressHex);
+ entry.size = size;
+ this.addEntry_(newAddressHex, entry);
+ },
+
+ lookupEntry(addressHex) {
+ return this.getBank_(addressHex)
+ .lookupEntry(this.getAddress_(addressHex));
+ },
+
+ addEntry_(addressHex, entry) {
+ // FIXME: Handle bank spanning addresses ...
+ this.getBank_(addressHex).addEntry(entry);
+ },
+
+ getAddress_(addressHex) {
+ // 13 hex digits === 52 bits, double mantissa fits 53 bits.
+ const bankSizeHexDigits = 13;
+ addressHex = addressHex.slice(2); // cut 0x prefix.
+ return parseInt(addressHex.slice(-bankSizeHexDigits), 16);
+ },
+
+ getBank_(addressHex) {
+ addressHex = addressHex.slice(2); // cut 0x prefix.
+
+ // 13 hex digits === 52 bits, double mantissa fits 53 bits.
+ const bankSizeHexDigits = 13;
+ const maxHexDigits = 16;
+ const bankName = addressHex.slice(-maxHexDigits, -bankSizeHexDigits);
+ let bank = this.banks_.get(bankName);
+ if (!bank) {
+ bank = new TraceCodeBank();
+ this.banks_.set(bankName, bank);
+ }
+ return bank;
+ }
+ };
+
+ function TraceCodeBank() {
+ this.entries_ = [];
+ }
+
+ TraceCodeBank.prototype = {
+ removeEntry(address) {
+ // findLowIndexInSortedArray returns 1 for empty. Just handle the
+ // empty list and bail early.
+ if (this.entries_.length === 0) return undefined;
+
+ const index = tr.b.findLowIndexInSortedArray(
+ this.entries_, function(entry) { return entry.address; }, address);
+ const entry = this.entries_[index];
+ if (!entry || entry.address !== address) return undefined;
+
+ this.entries_.splice(index, 1);
+ return entry;
+ },
+
+ lookupEntry(address) {
+ const index = tr.b.findFirstTrueIndexInSortedArray(
+ this.entries_, e => (address < e.address)) - 1;
+ const entry = this.entries_[index];
+ return entry &&
+ address < entry.address + entry.size ? entry : undefined;
+ },
+
+ addEntry(newEntry) {
+ // findLowIndexInSortedArray returns 1 for empty list. Just push the
+ // new address as it's the only item.
+ if (this.entries_.length === 0) {
+ this.entries_.push(newEntry);
+ }
+
+ const endAddress = newEntry.address + newEntry.size;
+ const lastIndex = tr.b.findLowIndexInSortedArray(
+ this.entries_, function(entry) { return entry.address; }, endAddress);
+ let index;
+ for (index = lastIndex - 1; index >= 0; --index) {
+ const entry = this.entries_[index];
+ const entryEndAddress = entry.address + entry.size;
+ if (entryEndAddress <= newEntry.address) break;
+ }
+ ++index;
+ this.entries_.splice(index, lastIndex - index, newEntry);
+ }
+ };
+
+ return {
+ TraceCodeMap,
+ };
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html
new file mode 100644
index 00000000000..2c9a84edfe4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer.html
@@ -0,0 +1,3394 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/trace_stream.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/extras/importer/heap_dump_trace_event_importer.html">
+<link rel="import" href="/tracing/extras/importer/legacy_heap_dump_trace_event_importer.html">
+<link rel="import" href="/tracing/extras/importer/oboe.html">
+<link rel="import" href="/tracing/extras/importer/profiling_dictionary_reader.html">
+<link rel="import" href="/tracing/extras/importer/trace_code_entry.html">
+<link rel="import" href="/tracing/extras/importer/trace_code_map.html">
+<link rel="import" href="/tracing/extras/importer/v8/codemap.html">
+<link rel="import" href="/tracing/extras/measure/measure_async_slice.html">
+<link rel="import" href="/tracing/importer/context_processor.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/comment_box_annotation.html">
+<link rel="import" href="/tracing/model/constants.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+<link rel="import" href="/tracing/model/flow_event.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/instant_event.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+<link rel="import" href="/tracing/model/profile_node.html">
+<link rel="import" href="/tracing/model/profile_tree.html">
+<link rel="import" href="/tracing/model/rect_annotation.html">
+<link rel="import" href="/tracing/model/scoped_id.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+<link rel="import" href="/tracing/model/x_marker_annotation.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview TraceEventImporter imports TraceEvent-formatted data
+ * into the provided model.
+ */
+tr.exportTo('tr.e.importer', function() {
+ const Base64 = tr.b.Base64;
+ const deepCopy = tr.b.deepCopy;
+ const ColorScheme = tr.b.ColorScheme;
+ const HeapDumpTraceEventImporter = tr.e.importer.HeapDumpTraceEventImporter;
+ const LegacyHeapDumpTraceEventImporter =
+ tr.e.importer.LegacyHeapDumpTraceEventImporter;
+ const StreamingEventExpander = tr.e.importer.StreamingEventExpander;
+ const ProfilingDictionaryReader = tr.e.importer.ProfilingDictionaryReader;
+ const MEASURE_NAME_REGEX = tr.e.measure.MEASURE_NAME_REGEX;
+
+ function getEventColor(event, opt_customName) {
+ if (event.cname) {
+ return ColorScheme.getColorIdForReservedName(event.cname);
+ } else if (opt_customName || event.name) {
+ return ColorScheme.getColorIdForGeneralPurposeString(
+ opt_customName || event.name);
+ }
+ }
+
+ function isLegacyChromeClockSyncEvent(event) {
+ return event.name !== undefined &&
+ event.name.startsWith(LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX) &&
+ ((event.ph === 'S') || (event.ph === 'F'));
+ }
+
+ const PRODUCER = 'producer';
+ const CONSUMER = 'consumer';
+ const STEP = 'step';
+
+ const BACKGROUND = tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;
+ const LIGHT = tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;
+ const DETAILED = tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;
+ const MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER = [undefined, BACKGROUND, LIGHT,
+ DETAILED];
+
+ const GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX = 'global/';
+
+ const LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX = 'ClockSyncEvent.';
+
+ // Map from raw memory dump byte stat names to model byte stat names. See
+ // //base/trace_event/process_memory_maps.cc in Chromium.
+ const BYTE_STAT_NAME_MAP = {
+ 'pc': 'privateCleanResident',
+ 'pd': 'privateDirtyResident',
+ 'sc': 'sharedCleanResident',
+ 'sd': 'sharedDirtyResident',
+ 'pss': 'proportionalResident',
+ 'sw': 'swapped'
+ };
+
+ // See tr.model.MemoryAllocatorDump 'weak' field and
+ // base::trace_event::MemoryAllocatorDump::Flags::WEAK in the Chromium
+ // codebase.
+ const WEAK_MEMORY_ALLOCATOR_DUMP_FLAG = 1 << 0;
+
+ // Object type name patterns for various compilers.
+ const OBJECT_TYPE_NAME_PATTERNS = [
+ {
+ // Clang.
+ prefix: 'const char *WTF::getStringWithTypeName() [T = ',
+ suffix: ']'
+ },
+ {
+ // GCC.
+ prefix: 'const char* WTF::getStringWithTypeName() [with T = ',
+ suffix: ']'
+ },
+ {
+ // Microsoft Visual C++
+ prefix: 'const char *__cdecl WTF::getStringWithTypeName<',
+ suffix: '>(void)'
+ }
+ ];
+
+ // The list of fields on the trace that are known to contain subtraces.
+ const SUBTRACE_FIELDS = new Set([
+ 'powerTraceAsString',
+ 'systemTraceEvents',
+ 'androidProcessDump',
+ ]);
+
+ // The complete list of fields on the trace that should not be treated as
+ // trace metadata.
+ const NON_METADATA_FIELDS = new Set([
+ 'displayTimeUnit',
+ 'samples',
+ 'stackFrames',
+ 'traceAnnotations',
+ 'traceEvents',
+ ...SUBTRACE_FIELDS
+ ]);
+
+ function TraceEventImporter(model, eventData) {
+ this.hasEvents_ = undefined; // Set properly when importEvents is called.
+ this.importPriority = 1;
+ this.model_ = model;
+ this.events_ = undefined;
+ this.sampleEvents_ = undefined;
+ this.stackFrameEvents_ = undefined;
+ this.stackFrameTree_ = new tr.model.ProfileTree();
+ this.subtraces_ = [];
+ this.eventsWereFromString_ = false;
+ this.softwareMeasuredCpuCount_ = undefined;
+
+
+ this.allAsyncEvents_ = [];
+ this.allFlowEvents_ = [];
+ this.allObjectEvents_ = [];
+
+ this.contextProcessorPerThread = {};
+
+ this.traceEventSampleStackFramesByName_ = {};
+
+ this.v8ProcessCodeMaps_ = {};
+ this.v8ProcessRootStackFrame_ = {};
+ this.v8SamplingData_ = [];
+
+ // Profile Tree Map.
+ // Type of Profile Tree -> Map(ID -> Profile Tree)
+ this.profileTrees_ = new Map();
+ // ID -> Info Object
+ this.profileInfo_ = new Map();
+
+ // For tracking async events that is used to create back-compat clock sync
+ // event.
+ this.legacyChromeClockSyncStartEvent_ = undefined;
+ this.legacyChromeClockSyncFinishEvent_ = undefined;
+
+ // Dump ID -> PID -> [process memory dump events].
+ this.allMemoryDumpEvents_ = {};
+
+ // Unpacks size, count, stackId and heapId from 'P' events. Also remembers
+ // stack frame and type information.
+ this.heapProfileExpander = new ProfilingDictionaryReader();
+
+ // PID -> Object type ID -> Object type name.
+ this.objectTypeNameMap_ = {};
+
+ // For old Chrome traces with no clock domain metadata, just use a
+ // placeholder clock domain.
+ this.clockDomainId_ = tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;
+ // A function able to transform timestamps in |clockDomainId| to timestamps
+ // in the model clock domain.
+ this.toModelTime_ = undefined;
+
+ if (typeof(eventData) === 'string' || eventData instanceof String) {
+ eventData = eventData.trim();
+ // If the event data begins with a [, then we know it should end with a ].
+ // The reason we check for this is because some tracing implementations
+ // cannot guarantee that a ']' gets written to the trace file. So, we are
+ // forgiving and if this is obviously the case, we fix it up before
+ // throwing the string at JSON.parse.
+ if (eventData[0] === '[') {
+ eventData = eventData.replace(/\s*,\s*$/, '');
+ if (eventData[eventData.length - 1] !== ']') {
+ eventData = eventData + ']';
+ }
+ }
+
+ this.events_ = JSON.parse(eventData);
+ this.eventsWereFromString_ = true;
+ } else {
+ this.events_ = eventData;
+ }
+
+ // Some trace_event implementations put the actual trace events
+ // inside a container. E.g { ... , traceEvents: [ ] }
+ // If we see that, just pull out the trace events.
+ if (this.events_.traceEvents) {
+ const container = this.events_;
+ this.events_ = this.events_.traceEvents;
+
+ for (const subtraceField of SUBTRACE_FIELDS) {
+ if (container[subtraceField]) {
+ this.storeSubtrace_(container[subtraceField]);
+ }
+ }
+ this.storeSamples_(container.samples);
+ this.storeStackFrames_(container.stackFrames);
+ this.storeDisplayTimeUnit_(container.displayTimeUnit);
+ this.storeTraceAnnotations_(container.traceAnnotations);
+ this.storeMetadata_(container);
+ } else if (this.events_ instanceof tr.b.TraceStream) {
+ const parser = oboe()
+ .node('{cat ph}', function(e) { return oboe.drop; })
+ .node('!.powerTraceAsString', this.storeSubtrace_.bind(this))
+ .node('!.systemTraceEvents', this.storeSubtrace_.bind(this))
+ .node('!.samples', this.storeSamples_.bind(this))
+ .node('!.stackFrames', this.storeStackFrames_.bind(this))
+ .node('!.displayTimeUnit', this.storeDisplayTimeUnit_.bind(this))
+ .node('!.traceAnnotations', this.storeTraceAnnotations_.bind(this))
+ .done(this.storeMetadata_.bind(this));
+ this.events_.rewind();
+ while (this.events_.hasData) {
+ parser.write(this.events_.readNumBytes());
+ }
+ parser.finish();
+ }
+ }
+
+ /**
+ * @return {boolean} Whether obj is a TraceEvent array.
+ */
+ TraceEventImporter.canImport = function(eventData) {
+ // May be encoded JSON. But we dont want to parse it fully yet.
+ // Use a simple heuristic:
+ // - eventData that starts with [ are probably trace_event
+ // - eventData that starts with { are probably trace_event
+ // May be encoded JSON. Treat files that start with { as importable by us.
+ if (eventData instanceof tr.b.TraceStream) {
+ if (eventData.isBinary) return false;
+ eventData = eventData.header;
+ }
+
+ if (typeof(eventData) === 'string' || eventData instanceof String) {
+ eventData = eventData.trim();
+ return eventData[0] === '{' || eventData[0] === '[';
+ }
+
+ // Might just be an array of events
+ if (eventData instanceof Array && eventData.length && eventData[0].ph) {
+ return true;
+ }
+
+ // Might be an object with a traceEvents field in it.
+ if (eventData.traceEvents) {
+ if (eventData.traceEvents instanceof Array) {
+ if (eventData.traceEvents.length && eventData.traceEvents[0].ph) {
+ return true;
+ }
+ if (eventData.samples && eventData.samples.length &&
+ eventData.stackFrames !== undefined) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ /**
+ * Extracts a scoped ID from an event.
+ *
+ * In legacy trace files, the ID of an event is always stored in the 'id'
+ * field and the event phase determines if the ID is process-local or
+ * global. For example, async event IDs are considered global and object
+ * event IDs are considered process-local.
+ *
+ * New trace files can explicitly specify whether an event ID is
+ * process-local or global. These new IDs are stored in the 'id2' field so
+ * that old trace importers that do not implement this logic break when they
+ * try to import a new trace file. The value of id2 can be either of the
+ * form '{global: 0x1000}' or of the form '{local: 0x1000}'.
+ *
+ * @param {!Object} event A trace event.
+ * @return {!tr.model.ScopedId}
+ */
+ TraceEventImporter.scopedIdForEvent_ = function(event) {
+ const scope = event.scope || tr.model.OBJECT_DEFAULT_SCOPE;
+ let pid = undefined;
+ if (event.id !== undefined) {
+ if (event.id2 !== undefined) {
+ throw new Error('Event has both id and id2');
+ }
+ pid = tr.model.LOCAL_ID_PHASES.has(event.ph) ? event.pid : undefined;
+ return new tr.model.ScopedId(scope, event.id, pid);
+ } else if (event.id2 !== undefined) {
+ if (event.id2.global !== undefined) {
+ return new tr.model.ScopedId(scope, event.id2.global);
+ } else if (event.id2.local !== undefined) {
+ return new tr.model.ScopedId(scope, event.id2.local, event.pid);
+ }
+ throw new Error(
+ 'Event that uses id2 must have either a global or local ID');
+ }
+ return undefined;
+ };
+
+ TraceEventImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'TraceEventImporter';
+ },
+
+ extractSubtraces() {
+ // Because subtraces can be quite large, we need to make sure that we
+ // don't hold a reference to the memory.
+ const subtraces = this.subtraces_;
+ this.subtraces_ = [];
+ return subtraces;
+ },
+
+ /**
+ * Deep copying is only needed if the trace was given to us as events.
+ */
+ deepCopyIfNeeded_(obj) {
+ if (obj === undefined) obj = {};
+ if (this.eventsWereFromString_) return obj;
+ return deepCopy(obj);
+ },
+
+ /**
+ * Always perform deep copying.
+ */
+ deepCopyAlways_(obj) {
+ if (obj === undefined) obj = {};
+ return deepCopy(obj);
+ },
+
+ /**
+ * Helper to process an async event.
+ */
+ processAsyncEvent(event) {
+ const thread = this.model_.getOrCreateProcess(event.pid).
+ getOrCreateThread(event.tid);
+ this.allAsyncEvents_.push({
+ sequenceNumber: this.allAsyncEvents_.length,
+ event,
+ thread
+ });
+ },
+
+ /**
+ * Helper to process a flow event.
+ */
+ processFlowEvent(event, opt_slice) {
+ const thread = this.model_.getOrCreateProcess(event.pid).
+ getOrCreateThread(event.tid);
+ this.allFlowEvents_.push({
+ refGuid: tr.b.GUID.getLastSimpleGuid(),
+ sequenceNumber: this.allFlowEvents_.length,
+ event,
+ slice: opt_slice, // slice for events that have flow info
+ thread
+ });
+ },
+
+ /**
+ * Helper that creates and adds samples to a Counter object based on
+ * 'C' phase events.
+ */
+ processCounterEvent(event) {
+ let ctrName;
+ if (event.id !== undefined) {
+ ctrName = event.name + '[' + event.id + ']';
+ } else {
+ ctrName = event.name;
+ }
+
+ const ctr = this.model_.getOrCreateProcess(event.pid)
+ .getOrCreateCounter(event.cat, ctrName);
+ const reservedColorId = event.cname ? getEventColor(event) : undefined;
+
+ // Initialize the counter's series fields if needed.
+ if (ctr.numSeries === 0) {
+ for (const seriesName in event.args) {
+ const colorId = reservedColorId ||
+ getEventColor(event, ctr.name + '.' + seriesName);
+ ctr.addSeries(new tr.model.CounterSeries(seriesName, colorId));
+ }
+
+ if (ctr.numSeries === 0) {
+ this.model_.importWarning({
+ type: 'counter_parse_error',
+ message: 'Expected counter ' + event.name +
+ ' to have at least one argument to use as a value.'
+ });
+
+ // Drop the counter.
+ delete ctr.parent.counters[ctr.name];
+ return;
+ }
+ }
+
+ const ts = this.toModelTimeFromUs_(event.ts);
+ ctr.series.forEach(function(series) {
+ const val = event.args[series.name] ? event.args[series.name] : 0;
+ series.addCounterSample(ts, val);
+ });
+ },
+
+ processObjectEvent(event) {
+ const thread = this.model_.getOrCreateProcess(event.pid).
+ getOrCreateThread(event.tid);
+ this.allObjectEvents_.push({
+ sequenceNumber: this.allObjectEvents_.length,
+ event,
+ thread});
+ if (thread.guid in this.contextProcessorPerThread) {
+ const processor = this.contextProcessorPerThread[thread.guid];
+ const scopedId = TraceEventImporter.scopedIdForEvent_(event);
+ if (event.ph === 'D') {
+ processor.destroyContext(scopedId);
+ }
+ // The context processor maintains a cache of unique context objects and
+ // active context sets to reduce memory usage. If an object is modified,
+ // we should invalidate this cache, because otherwise context sets from
+ // before and after the modification may erroneously point to the same
+ // context snapshot (as both are the same set/object instances).
+ processor.invalidateContextCacheForSnapshot(scopedId);
+ }
+ },
+
+ processContextEvent(event) {
+ const thread = this.model_.getOrCreateProcess(event.pid).
+ getOrCreateThread(event.tid);
+ if (!(thread.guid in this.contextProcessorPerThread)) {
+ this.contextProcessorPerThread[thread.guid] =
+ new tr.importer.ContextProcessor(this.model_);
+ }
+ const scopedId = TraceEventImporter.scopedIdForEvent_(event);
+ const contextType = event.name;
+ const processor = this.contextProcessorPerThread[thread.guid];
+ if (event.ph === '(') {
+ processor.enterContext(contextType, scopedId);
+ } else if (event.ph === ')') {
+ processor.leaveContext(contextType, scopedId);
+ } else {
+ this.model_.importWarning({
+ type: 'unknown_context_phase',
+ message: 'Unknown context event phase: ' + event.ph + '.'
+ });
+ }
+ },
+
+ setContextsFromThread_(thread, slice) {
+ if (thread.guid in this.contextProcessorPerThread) {
+ slice.contexts =
+ this.contextProcessorPerThread[thread.guid].activeContexts;
+ }
+ },
+
+ processDurationEvent(event) {
+ const thread = this.model_.getOrCreateProcess(event.pid)
+ .getOrCreateThread(event.tid);
+ const ts = this.toModelTimeFromUs_(event.ts);
+ if (event.dur === 0 &&
+ !thread.sliceGroup.isTimestampValidForBeginOrEnd(ts)) {
+ this.model_.importWarning({
+ type: 'duration_parse_error',
+ message: 'Timestamps are moving backward.'
+ });
+ return;
+ }
+
+ if (event.ph === 'B') {
+ const slice = thread.sliceGroup.beginSlice(
+ event.cat, event.name, this.toModelTimeFromUs_(event.ts),
+ this.deepCopyIfNeeded_(event.args),
+ this.toModelTimeFromUs_(event.tts), event.argsStripped,
+ getEventColor(event), event.bind_id);
+ slice.startStackFrame = this.getStackFrameForEvent_(event);
+ this.setContextsFromThread_(thread, slice);
+ } else if (event.ph === 'I' || event.ph === 'i' || event.ph === 'R') {
+ if (event.s !== undefined && event.s !== 't') {
+ throw new Error('This should never happen');
+ }
+
+ thread.sliceGroup.beginSlice(event.cat, event.name,
+ this.toModelTimeFromUs_(event.ts),
+ this.deepCopyIfNeeded_(event.args),
+ this.toModelTimeFromUs_(event.tts),
+ event.argsStripped,
+ getEventColor(event), event.bind_id);
+ const slice = thread.sliceGroup.endSlice(
+ this.toModelTimeFromUs_(event.ts),
+ this.toModelTimeFromUs_(event.tts));
+ slice.startStackFrame = this.getStackFrameForEvent_(event);
+ slice.endStackFrame = undefined;
+ } else {
+ if (!thread.sliceGroup.openSliceCount) {
+ this.model_.importWarning({
+ type: 'duration_parse_error',
+ message: 'E phase event without a matching B phase event.'
+ });
+ return;
+ }
+
+ const slice = thread.sliceGroup.endSlice(
+ this.toModelTimeFromUs_(event.ts),
+ this.toModelTimeFromUs_(event.tts),
+ getEventColor(event));
+ if (event.name && slice.title !== event.name) {
+ this.model_.importWarning({
+ type: 'title_match_error',
+ message: 'Titles do not match. Title is ' +
+ slice.title + ' in openSlice, and is ' +
+ event.name + ' in endSlice'
+ });
+ }
+ slice.endStackFrame = this.getStackFrameForEvent_(event);
+
+ this.mergeArgsInto_(slice.args, event.args, slice.title);
+ }
+ },
+
+ mergeArgsInto_(dstArgs, srcArgs, eventName) {
+ for (const arg in srcArgs) {
+ if (dstArgs[arg] !== undefined) {
+ this.model_.importWarning({
+ type: 'arg_merge_error',
+ message: 'Different phases of ' + eventName +
+ ' provided values for argument ' + arg + '.' +
+ ' The last provided value will be used.'
+ });
+ }
+ dstArgs[arg] = this.deepCopyIfNeeded_(srcArgs[arg]);
+ }
+ },
+
+ processCompleteEvent(event) {
+ // Preventing the overhead slices from making it into the model. This
+ // only applies to legacy traces, as the overhead traces have been
+ // removed from the chromium code.
+ if (event.cat !== undefined &&
+ event.cat.indexOf('trace_event_overhead') > -1) {
+ return undefined;
+ }
+
+ const thread = this.model_.getOrCreateProcess(event.pid)
+ .getOrCreateThread(event.tid);
+
+ if (event.flow_out) {
+ if (event.flow_in) {
+ event.flowPhase = STEP;
+ } else {
+ event.flowPhase = PRODUCER;
+ }
+ } else if (event.flow_in) {
+ event.flowPhase = CONSUMER;
+ }
+
+ const slice = thread.sliceGroup.pushCompleteSlice(event.cat, event.name,
+
+ this.toModelTimeFromUs_(event.ts),
+ this.maybeToModelTimeFromUs_(event.dur),
+ this.maybeToModelTimeFromUs_(event.tts),
+ this.maybeToModelTimeFromUs_(event.tdur),
+ this.deepCopyIfNeeded_(event.args),
+ event.argsStripped,
+ getEventColor(event),
+ event.bind_id);
+ slice.startStackFrame = this.getStackFrameForEvent_(event);
+ slice.endStackFrame = this.getStackFrameForEvent_(event, true);
+ this.setContextsFromThread_(thread, slice);
+
+ return slice;
+ },
+
+ processJitCodeEvent(event) {
+ if (this.v8ProcessCodeMaps_[event.pid] === undefined) {
+ this.v8ProcessCodeMaps_[event.pid] = new tr.e.importer.TraceCodeMap();
+ }
+ const map = this.v8ProcessCodeMaps_[event.pid];
+
+ const data = event.args.data;
+ // TODO(dsinclair): There are _a lot_ of JitCode events so I'm skipping
+ // the display for now. Can revisit later if we want to show them.
+ // Handle JitCodeMoved and JitCodeAdded event.
+ if (event.name === 'JitCodeMoved') {
+ map.moveEntry(data.code_start, data.new_code_start, data.code_len);
+ } else { // event.name === 'JitCodeAdded'
+ map.addEntry(data.code_start, data.code_len, data.name, data.script_id);
+ }
+ },
+
+ processMetadataEvent(event) {
+ // V8 JIT events are currently logged as phase 'M' so we need to
+ // separate them out and handle specially.
+ if (event.name === 'JitCodeAdded' || event.name === 'JitCodeMoved') {
+ this.v8SamplingData_.push(event);
+ return;
+ }
+
+ // The metadata events aren't useful without args.
+ if (event.argsStripped) return;
+
+ if (event.name === 'process_name') {
+ const process = this.model_.getOrCreateProcess(event.pid);
+ process.name = event.args.name;
+ } else if (event.name === 'process_labels') {
+ const process = this.model_.getOrCreateProcess(event.pid);
+ const labels = event.args.labels.split(',');
+ for (let i = 0; i < labels.length; i++) {
+ process.addLabelIfNeeded(labels[i]);
+ }
+ } else if (event.name === 'process_uptime_seconds') {
+ const process = this.model_.getOrCreateProcess(event.pid);
+ process.uptime_seconds = event.args.uptime;
+ } else if (event.name === 'process_sort_index') {
+ const process = this.model_.getOrCreateProcess(event.pid);
+ process.sortIndex = event.args.sort_index;
+ } else if (event.name === 'thread_name') {
+ const thread = this.model_.getOrCreateProcess(event.pid).
+ getOrCreateThread(event.tid);
+ thread.name = event.args.name;
+ } else if (event.name === 'thread_sort_index') {
+ const thread = this.model_.getOrCreateProcess(event.pid).
+ getOrCreateThread(event.tid);
+ thread.sortIndex = event.args.sort_index;
+ } else if (event.name === 'num_cpus') {
+ let n = event.args.number;
+ // Not all render processes agree on the cpu count in trace_event. Some
+ // processes will report 1, while others will report the actual cpu
+ // count. To deal with this, take the max of what is reported.
+ if (this.softwareMeasuredCpuCount_ !== undefined) {
+ n = Math.max(n, this.softwareMeasuredCpuCount_);
+ }
+ this.softwareMeasuredCpuCount_ = n;
+ } else if (event.name === 'stackFrames') {
+ const stackFrames = event.args.stackFrames;
+ if (stackFrames === undefined) {
+ this.model_.importWarning({
+ type: 'metadata_parse_error',
+ message: 'No stack frames found in a \'' + event.name +
+ '\' metadata event'
+ });
+ } else {
+ this.importStackFrames_(stackFrames, 'p' + event.pid + ':');
+ }
+ } else if (event.name === 'typeNames') {
+ const objectTypeNameMap = event.args.typeNames;
+ if (objectTypeNameMap === undefined) {
+ this.model_.importWarning({
+ type: 'metadata_parse_error',
+ message: 'No mapping from object type IDs to names found in a \'' +
+ event.name + '\' metadata event'
+ });
+ } else {
+ this.importObjectTypeNameMap_(objectTypeNameMap, event.pid);
+ }
+ } else if (event.name === 'TraceConfig') {
+ this.model_.metadata.push(
+ {name: 'TraceConfig', value: event.args.value});
+ } else {
+ this.model_.importWarning({
+ type: 'metadata_parse_error',
+ message: 'Unrecognized metadata name: ' + event.name
+ });
+ }
+ },
+
+ processInstantEvent(event) {
+ // V8 JIT events were logged as phase 'I' in the old format,
+ // so we need to separate them out and handle specially.
+ if (event.name === 'JitCodeAdded' || event.name === 'JitCodeMoved') {
+ this.v8SamplingData_.push(event);
+ return;
+ }
+
+ // Thread-level instant events are treated as zero-duration slices.
+ if (event.s === 't' || event.s === undefined) {
+ this.processDurationEvent(event);
+ return;
+ }
+
+ let constructor;
+ switch (event.s) {
+ case 'g':
+ constructor = tr.model.GlobalInstantEvent;
+ break;
+ case 'p':
+ constructor = tr.model.ProcessInstantEvent;
+ break;
+ default:
+ this.model_.importWarning({
+ type: 'instant_parse_error',
+ message: 'I phase event with unknown "s" field value.'
+ });
+ return;
+ }
+
+ const instantEvent = new constructor(event.cat, event.name,
+ getEventColor(event), this.toModelTimeFromUs_(event.ts),
+ this.deepCopyIfNeeded_(event.args));
+
+ switch (instantEvent.type) {
+ case tr.model.InstantEventType.GLOBAL:
+ this.model_.instantEvents.push(instantEvent);
+ break;
+
+ case tr.model.InstantEventType.PROCESS: {
+ const process = this.model_.getOrCreateProcess(event.pid);
+ process.instantEvents.push(instantEvent);
+ break;
+ }
+
+ default:
+ throw new Error('Unknown instant event type: ' + event.s);
+ }
+ },
+
+ getOrCreateProfileTree_(sampleType, id) {
+ if (!this.profileTrees_.has(sampleType)) {
+ this.profileTrees_.set(sampleType, new Map());
+ }
+ const profileTreeMap = this.profileTrees_.get(sampleType);
+ if (profileTreeMap.has(id)) {
+ return profileTreeMap.get(id);
+ }
+ const profileTree = new tr.model.ProfileTree();
+ profileTreeMap.set(id, profileTree);
+ const info = this.profileInfo_.get(id);
+ if (info !== undefined) {
+ profileTree.startTime = info.startTime;
+ profileTree.pid = info.pid;
+ profileTree.tid = info.tid;
+ }
+ return profileTree;
+ },
+
+ processSample(event) {
+ if (event.args === undefined || event.args.data === undefined) {
+ return;
+ }
+ if (event.id === undefined) {
+ throw new Error('No event ID in sample');
+ }
+
+ const data = event.args.data;
+ // Sampling usually happens in a separate thread, but start time is issued
+ // in the main thread, in order to get the correct thread object,
+ // we should use pid and tid from main thread.
+ if (data.startTime !== undefined) {
+ this.profileInfo_.set(event.id, {
+ startTime: data.startTime,
+ pid: event.pid,
+ tid: event.tid
+ });
+ }
+ const timeDeltas = data.timeDeltas;
+ for (const sampleType in data) {
+ if (sampleType === 'timeDeltas' || sampleType === 'startTime') {
+ continue;
+ }
+ // The length of samples array and the length of timeDeltas array
+ // should be the same.
+ if (data[sampleType].samples && timeDeltas &&
+ data[sampleType].samples.length !== timeDeltas.length) {
+ // eslint-disable-next-line
+ throw new Error('samples and timeDeltas array should have same length');
+ }
+
+ const profileTree = this.getOrCreateProfileTree_(sampleType, event.id);
+ const nodes = data[sampleType].nodes;
+ const samples = data[sampleType].samples;
+ if (nodes !== undefined) {
+ for (const node of nodes) {
+ // Get the sepcific ProfileNode type based on sampleType.
+ const ProfileNodeType =
+ tr.model.ProfileNode.subTypes.getConstructor(undefined,
+ sampleType);
+ const profileNode = ProfileNodeType.constructFromObject(profileTree,
+ node);
+ if (profileNode === undefined) {
+ continue;
+ }
+ profileTree.add(profileNode);
+ }
+ }
+ // The samples array contains id pointing to the profile node.
+ if (samples !== undefined) {
+ const thread = this.model_.getOrCreateProcess(profileTree.pid)
+ .getOrCreateThread(profileTree.tid);
+ for (let i = 0, len = samples.length; i < len; ++i) {
+ const node = profileTree.getNode(samples[i]);
+ profileTree.endTime += timeDeltas[i];
+ if (node === undefined) continue;
+ const start = this.toModelTimeFromUs_(profileTree.endTime);
+ this.model_.samples.push(
+ new tr.model.Sample(start, node.sampleTitle, node, thread));
+ }
+ }
+ }
+ },
+
+ processLegacyV8Sample(event) {
+ const data = event.args.data;
+ const sampleType = 'legacySample';
+ const ProfileNodeType =
+ tr.model.ProfileNode.subTypes.getConstructor(undefined, sampleType);
+
+ // As-per DevTools, the backend sometimes creates bogus samples. Skip it.
+ if (data.vm_state === 'js' && !data.stack.length) return;
+
+ const profileTree = this.getOrCreateProfileTree_(sampleType, event.pid);
+ if (profileTree.getNode(-1) === undefined) {
+ profileTree.add(
+ new ProfileNodeType(-1, {
+ url: '',
+ scriptId: -1,
+ functionName: 'unknown'
+ }, undefined));
+ }
+ // There are several types of v8 sample events, gc, native, compiler, etc.
+ // Some of these types have stacks and some don't, we handle those two
+ // cases differently. For types that don't have any stack frames attached
+ // we synthesize one based on the type of thing that's happening so when
+ // we view all the samples we'll see something like 'external' or 'gc'
+ // as a fraction of the time spent.
+ let node = undefined;
+ if (data.stack.length > 0 && this.v8ProcessCodeMaps_[event.pid]) {
+ const map = this.v8ProcessCodeMaps_[event.pid];
+ // Stacks have the leaf node first, flip them around so the root
+ // comes first.
+ data.stack.reverse();
+ let parentNode = undefined;
+ for (let i = 0; i < data.stack.length; i++) {
+ const entry = map.lookupEntry(data.stack[i]);
+ if (entry === undefined) {
+ node = profileTree.getNode(-1);
+ } else {
+ node = profileTree.getNode(entry.id);
+ if (node === undefined) {
+ const sourceInfo = entry.sourceInfo;
+ node = new ProfileNodeType(entry.id, {
+ functionName: entry.name,
+ url: entry.sourceInfo.file,
+ lineNumber: sourceInfo.line !== -1 ? sourceInfo.line :
+ undefined,
+ columnNumber: sourceInfo.column !== -1 ? sourceInfo.column :
+ undefined,
+ scriptid: entry.sourceInfo.scriptId
+ }, parentNode);
+ profileTree.add(node);
+ }
+ }
+ parentNode = node;
+ }
+ } else {
+ node = profileTree.getNode(data.vm_state);
+ if (node === undefined) {
+ node = new ProfileNodeType(data.vm_state, {
+ url: '',
+ functionName: data.vm_state
+ }, undefined);
+ profileTree.add(node);
+ }
+ }
+
+ const thread = this.model_.getOrCreateProcess(event.pid)
+ .getOrCreateThread(event.tid);
+
+ this.model_.samples.push(
+ new tr.model.Sample(this.toModelTimeFromUs_(event.ts),
+ node.sampleTitle, node, thread));
+ },
+
+ processTraceSampleEvent(event) {
+ if (event.name === 'V8Sample' || event.name.startsWith('Profile')) {
+ this.v8SamplingData_.push(event);
+ return;
+ }
+
+ let node = this.stackFrameTree_.getNode(event.name);
+ if (node === undefined && event.sf !== undefined) {
+ node = this.stackFrameTree_.getNode('g' + event.sf);
+ }
+
+ if (node === undefined) {
+ let id = event.name;
+ if (event.sf) {
+ id = 'g' + event.sf;
+ }
+ const ProfileNodeType =
+ tr.model.ProfileNode.subTypes.getConstructor(undefined,
+ 'legacySample');
+ node = this.stackFrameTree_.add(new ProfileNodeType(
+ id, {
+ functionName: event.name
+ }, undefined
+ ));
+ }
+ const thread = this.model_.getOrCreateProcess(event.pid)
+ .getOrCreateThread(event.tid);
+
+ const sample = new tr.model.Sample(
+ this.toModelTimeFromUs_(event.ts), 'Trace Event Sample',
+ node, thread, undefined, 1,
+ this.deepCopyIfNeeded_(event.args));
+ this.setContextsFromThread_(thread, sample);
+ this.model_.samples.push(sample);
+ },
+
+ processMemoryDumpEvent(event) {
+ // TODO(chiniforooshan): Make memory dumps either use local or global IDs
+ // instead of the generic IDs with different phases.
+ // https://github.com/catapult-project/catapult/issues/2957
+ if (event.ph !== 'v') {
+ throw new Error('Invalid memory dump event phase "' + event.ph + '".');
+ }
+
+ const dumpId = event.id;
+ if (dumpId === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Memory dump event (phase \'' + event.ph +
+ '\') without a dump ID.'
+ });
+ return;
+ }
+
+ const pid = event.pid;
+ if (pid === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Memory dump event (phase\'' + event.ph + '\', dump ID \'' +
+ dumpId + '\') without a PID.'
+ });
+ return;
+ }
+
+ // Dump ID -> PID -> [process memory dump events].
+ const allEvents = this.allMemoryDumpEvents_;
+
+ // PID -> [process memory dump events].
+ let dumpIdEvents = allEvents[dumpId];
+ if (dumpIdEvents === undefined) {
+ allEvents[dumpId] = dumpIdEvents = {};
+ }
+
+ // [process memory dump events].
+ let processEvents = dumpIdEvents[pid];
+ if (processEvents === undefined) {
+ dumpIdEvents[pid] = processEvents = [];
+ }
+
+ processEvents.push(event);
+ },
+
+ processClockSyncEvent(event) {
+ if (event.ph !== 'c') {
+ throw new Error('Invalid clock sync event phase "' + event.ph + '".');
+ }
+
+ const syncId = event.args.sync_id;
+ if (syncId === undefined) {
+ this.model_.importWarning({
+ type: 'clock_sync_parse_error',
+ message: 'Clock sync at time ' + event.ts + ' without an ID.'
+ });
+ return;
+ }
+
+ if (event.args && event.args.issue_ts !== undefined) {
+ // When Chrome is the tracing controller and is the requester of the
+ // clock sync, the clock sync event looks like:
+ //
+ // {
+ // "args": {
+ // "sync_id": "abc123",
+ // "issue_ts": 12340
+ // }
+ // "ph": "c"
+ // "ts": 12345
+ // ...
+ // }
+ this.model_.clockSyncManager.addClockSyncMarker(
+ this.clockDomainId_, syncId,
+ tr.b.Unit.timestampFromUs(event.args.issue_ts),
+ tr.b.Unit.timestampFromUs(event.ts));
+ } else {
+ // When Chrome is a tracing agent and is the recipient of the clock
+ // sync request, the clock sync event looks like:
+ //
+ // {
+ // "args": { "sync_id": "abc123" }
+ // "ph": "c"
+ // "ts": 12345
+ // ...
+ // }
+ this.model_.clockSyncManager.addClockSyncMarker(
+ this.clockDomainId_, syncId, tr.b.Unit.timestampFromUs(event.ts));
+ }
+ },
+
+ processLegacyChromeClockSyncEvent(event) {
+ // Older versions of Chrome don't support the devtools clock sync API, but
+ // Telemetry can work around this by creating clock sync events via
+ // console.time & console.timeEnd, which issue trace events as long as the
+ // 'blink.console' category is enabled. When we encounter async events
+ // with names starting with the prefix 'ClockSyncEvent.' , treat these as
+ // clock sync markers.
+ if (event.ph === 'S') {
+ this.legacyChromeClockSyncStartEvent_ = event;
+ } else if (event.ph === 'F') {
+ this.legacyChromeClockSyncFinishEvent_ = event;
+ }
+
+ if (this.legacyChromeClockSyncStartEvent_ === undefined ||
+ this.legacyChromeClockSyncFinishEvent_ === undefined) {
+ return;
+ }
+
+ const startSyncId = this.legacyChromeClockSyncStartEvent_.name.substring(
+ LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX.length);
+ const finishSyncId =
+ this.legacyChromeClockSyncFinishEvent_.name.substring(
+ LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX.length);
+
+ if (startSyncId !== finishSyncId) {
+ throw new Error(
+ 'Inconsistent clock sync ID of legacy Chrome clock sync events');
+ }
+
+ this.model_.clockSyncManager.addClockSyncMarker(
+ this.clockDomainId_, startSyncId,
+ tr.b.Unit.timestampFromUs(this.legacyChromeClockSyncStartEvent_.ts),
+ tr.b.Unit.timestampFromUs(this.legacyChromeClockSyncFinishEvent_.ts));
+ },
+
+ // Because the order of Jit code events and V8 samples are not guaranteed,
+ // We store them in an array, sort by timestamp, and then process them.
+ processV8Events() {
+ this.v8SamplingData_.sort(function(a, b) {
+ if (a.ts !== b.ts) return a.ts - b.ts;
+ if (a.ph === 'M' || a.ph === 'I') {
+ return -1;
+ } else if (b.ph === 'M' || b.ph === 'I') {
+ return 1;
+ }
+ return 0;
+ });
+ const length = this.v8SamplingData_.length;
+ for (let i = 0; i < length; ++i) {
+ const event = this.v8SamplingData_[i];
+ if (event.ph === 'M' || event.ph === 'I') {
+ this.processJitCodeEvent(event);
+ } else if (event.ph === 'P') {
+ // The current sampling format and legacy sampling format
+ // have the same ph, but the current sampling format will
+ // start with 'Profile' in its name.
+ if (event.name.startsWith('Profile')) {
+ this.processSample(event);
+ } else {
+ this.processLegacyV8Sample(event);
+ }
+ }
+ }
+ },
+
+ importClockSyncMarkers() {
+ if (this.events_ instanceof tr.b.TraceStream) {
+ const parser = oboe().node(
+ '{cat ph}', this.importClockSyncMarker_.bind(this));
+ this.events_.rewind();
+ while (this.events_.hasData) {
+ parser.write(this.events_.readNumBytes());
+ }
+ parser.finish();
+ } else {
+ for (let i = 0; i < this.events_.length; i++) {
+ this.importClockSyncMarker_(this.events_[i]);
+ }
+ }
+ },
+
+ importClockSyncMarker_(event) {
+ const isLegacyChromeClockSync = isLegacyChromeClockSyncEvent(event);
+ if (event.ph !== 'c' && !isLegacyChromeClockSync) return;
+
+ const eventSizeInBytes =
+ this.model_.importOptions.trackDetailedModelStats ?
+ JSON.stringify(event).length : undefined;
+
+ this.model_.stats.willProcessBasicTraceEvent(
+ 'clock_sync', event.cat, event.name, event.ts, eventSizeInBytes);
+
+ if (isLegacyChromeClockSync) {
+ this.processLegacyChromeClockSyncEvent(event);
+ } else {
+ this.processClockSyncEvent(event);
+ }
+ },
+
+ /**
+ * Walks through the events_ list and outputs the structures discovered to
+ * model_.
+ */
+ importEvents() {
+ this.hasEvents_ = false;
+ if (this.stackFrameEvents_) {
+ this.importStackFrames_(this.stackFrameEvents_, 'g');
+ }
+
+ if (this.traceAnnotations_) this.importAnnotations_();
+
+ if (this.events_ instanceof tr.b.TraceStream) {
+ const parser = oboe().node('{cat ph}', this.processEvent_.bind(this));
+ this.events_.rewind();
+ while (this.events_.hasData) {
+ parser.write(this.events_.readNumBytes());
+ }
+ parser.finish();
+ } else {
+ for (let eI = 0; eI < this.events_.length; eI++) {
+ this.processEvent_(this.events_[eI]);
+ }
+ }
+
+ // Import calls importEvents then autoCloseOpenSlices then finalizeImport.
+ // AsyncSlices must be created in importEvents so they can be auto-closed.
+ this.createAsyncSlices_();
+
+ this.processV8Events();
+
+ // Remove all the root stack frame children as they should
+ // already be added.
+ for (const frame of Object.values(this.v8ProcessRootStackFrame_)) {
+ frame.removeAllChildren();
+ }
+ },
+
+ // Some trace authors store subtraces as specific properties of the trace.
+ storeSubtrace_(subtrace) {
+ this.subtraces_.push(subtrace);
+ return oboe.drop;
+ },
+
+ storeSamples_(samples) {
+ this.sampleEvents_ = samples;
+ return oboe.drop;
+ },
+
+ storeStackFrames_(stackFrames) {
+ this.stackFrameEvents_ = stackFrames;
+ return oboe.drop;
+ },
+
+ // Some implementations specify displayTimeUnit
+ storeDisplayTimeUnit_(unitName) {
+ if (!unitName) return;
+ const unit = tr.b.TimeDisplayModes[unitName];
+ if (unit === undefined) {
+ throw new Error('Unit ' + unitName + ' is not supported.');
+ }
+ this.model_.intrinsicTimeUnit = unit;
+ return oboe.drop;
+ },
+
+ storeTraceAnnotations_(traceAnnotations) {
+ this.traceAnnotations_ = traceAnnotations;
+ return oboe.drop;
+ },
+
+ // Any fields in the container that is not in NON_METADATA_FIELDS should be
+ // treated as metadata.
+ storeMetadata_(container) {
+ for (const fieldName of Object.keys(container)) {
+ if (NON_METADATA_FIELDS.has(fieldName)) continue;
+ this.model_.metadata.push(
+ { name: fieldName, value: container[fieldName] });
+ if (fieldName !== 'metadata') continue;
+ const metadata = container[fieldName];
+ if (metadata['highres-ticks']) {
+ this.model_.isTimeHighResolution = metadata['highres-ticks'];
+ }
+ if (metadata['clock-domain']) {
+ this.clockDomainId_ = metadata['clock-domain'];
+ }
+ }
+ return oboe.drop;
+ },
+
+ processEvent_(event) {
+ this.hasEvents_ = true;
+ const importOptions = this.model_.importOptions;
+ const trackDetailedModelStats = importOptions.trackDetailedModelStats;
+ const modelStats = this.model_.stats;
+
+ if (event.args === '__stripped__') {
+ event.argsStripped = true;
+ event.args = undefined;
+ }
+
+ let eventSizeInBytes = undefined;
+ if (trackDetailedModelStats) {
+ eventSizeInBytes = JSON.stringify(event).length;
+ }
+
+ switch (event.ph) {
+ case 'B':
+ case 'E':
+ modelStats.willProcessBasicTraceEvent(
+ 'begin_end (non-compact)', event.cat, event.name, event.ts,
+ eventSizeInBytes);
+ this.processDurationEvent(event);
+ break;
+
+ case 'X': {
+ modelStats.willProcessBasicTraceEvent(
+ 'begin_end (compact)', event.cat, event.name, event.ts,
+ eventSizeInBytes);
+ const slice = this.processCompleteEvent(event);
+ // TODO(yuhaoz): If Chrome supports creating other events with flow,
+ // we will need to call processFlowEvent for them also.
+ // https://github.com/catapult-project/catapult/issues/1259
+ if (slice !== undefined && event.bind_id !== undefined) {
+ this.processFlowEvent(event, slice);
+ }
+ break;
+ }
+
+ case 'b':
+ case 'e':
+ case 'n':
+ case 'S':
+ case 'F':
+ case 'T':
+ case 'p':
+ modelStats.willProcessBasicTraceEvent(
+ 'async', event.cat, event.name, event.ts, eventSizeInBytes);
+ this.processAsyncEvent(event);
+ break;
+
+ // Note, I is historic. The instant event marker got changed, but we
+ // want to support loading old trace files so we have both I and i.
+ case 'I':
+ case 'i':
+ case 'R':
+ modelStats.willProcessBasicTraceEvent(
+ 'instant', event.cat, event.name, event.ts, eventSizeInBytes);
+ this.processInstantEvent(event);
+ break;
+
+ case 'P':
+ modelStats.willProcessBasicTraceEvent(
+ 'samples', event.cat, event.name, event.ts, eventSizeInBytes);
+ this.processTraceSampleEvent(event);
+ break;
+
+ case 'C':
+ modelStats.willProcessBasicTraceEvent(
+ 'counters', event.cat, event.name, event.ts, eventSizeInBytes);
+ this.processCounterEvent(event);
+ break;
+
+ case 'M':
+ modelStats.willProcessBasicTraceEvent(
+ 'metadata', event.cat, event.name, event.ts, eventSizeInBytes);
+ this.processMetadataEvent(event);
+ break;
+
+ case 'N':
+ case 'D':
+ case 'O':
+ modelStats.willProcessBasicTraceEvent(
+ 'objects', event.cat, event.name, event.ts, eventSizeInBytes);
+ this.processObjectEvent(event);
+ break;
+
+ case 's':
+ case 't':
+ case 'f':
+ modelStats.willProcessBasicTraceEvent(
+ 'flows', event.cat, event.name, event.ts, eventSizeInBytes);
+ this.processFlowEvent(event);
+ break;
+
+ case 'v':
+ modelStats.willProcessBasicTraceEvent(
+ 'memory_dumps', event.cat, event.name, event.ts,
+ eventSizeInBytes);
+ this.processMemoryDumpEvent(event);
+ break;
+
+ case '(':
+ case ')':
+ this.processContextEvent(event);
+ break;
+
+ // No-op. Clock sync events have already been processed in
+ // importClockSyncMarkers().
+ case 'c':
+ break;
+
+ default:
+ modelStats.willProcessBasicTraceEvent(
+ 'unknown', event.cat, event.name, event.ts, eventSizeInBytes);
+ this.model_.importWarning({
+ type: 'parse_error',
+ message: 'Unrecognized event phase: ' +
+ event.ph + ' (' + event.name + ')'
+ });
+ }
+ return oboe.drop;
+ },
+
+ importStackFrames_(rawStackFrames, idPrefix) {
+ const model = this.model_;
+
+ for (const id in rawStackFrames) {
+ const rawStackFrame = rawStackFrames[id];
+ const fullId = idPrefix + id;
+ const textForColor = rawStackFrame.category ?
+ rawStackFrame.category : rawStackFrame.name;
+ const stackFrame = new tr.model.StackFrame(
+ undefined /* parentFrame */, fullId, rawStackFrame.name,
+ ColorScheme.getColorIdForGeneralPurposeString(textForColor));
+ model.addStackFrame(stackFrame);
+ }
+
+ for (const id in rawStackFrames) {
+ const fullId = idPrefix + id;
+ const stackFrame = model.stackFrames[fullId];
+ if (stackFrame === undefined) {
+ throw new Error('Internal error');
+ }
+
+ const rawStackFrame = rawStackFrames[id];
+ const parentId = rawStackFrame.parent;
+ let parentStackFrame;
+ if (parentId === undefined) {
+ parentStackFrame = undefined;
+ } else {
+ const parentFullId = idPrefix + parentId;
+ parentStackFrame = model.stackFrames[parentFullId];
+ if (parentStackFrame === undefined) {
+ this.model_.importWarning({
+ type: 'metadata_parse_error',
+ message: 'Missing parent frame with ID ' + parentFullId +
+ ' for stack frame \'' + stackFrame.name + '\' (ID ' + fullId +
+ ').'
+ });
+ }
+ }
+ stackFrame.parentFrame = parentStackFrame;
+ }
+
+ // This section is a reimplementation of the above behaviour but using
+ // the new ProfileNode type instead of StackFrame.
+ // We keep the StackFrame version for compatibility for now.
+ const ProfileNodeType =
+ tr.model.ProfileNode.subTypes.getConstructor(undefined,
+ 'legacySample');
+ if (idPrefix === 'g') {
+ for (const id in rawStackFrames) {
+ const rawStackFrame = rawStackFrames[id];
+ const textForColor = rawStackFrame.category ?
+ rawStackFrame.category : rawStackFrame.name;
+ const node = this.stackFrameTree_.add(new ProfileNodeType(
+ 'g' + id, {
+ functionName: rawStackFrame.name
+ }, undefined));
+ node.colorId =
+ ColorScheme.getColorIdForGeneralPurposeString(textForColor);
+ node.parentId = rawStackFrame.parent;
+ }
+
+ for (const id in rawStackFrames) {
+ const node = this.stackFrameTree_.getNode('g' + id);
+ const parentId = node.parentId;
+ let parentNode = undefined;
+ if (parentId !== undefined) {
+ parentNode = this.stackFrameTree_.getNode('g' + parentId);
+ if (parentNode === undefined) {
+ this.model_.importWarning({
+ type: 'metadata_parse_error',
+ message: 'Missing parent frame with ID ' + parentId +
+ ' for stack frame \'' + node.name + '\' (ID ' + node.id +
+ ').'
+ });
+ }
+ node.parentNode = parentNode;
+ }
+ }
+ }
+ },
+
+ importObjectTypeNameMap_(rawObjectTypeNameMap, pid) {
+ if (pid in this.objectTypeNameMap_) {
+ this.model_.importWarning({
+ type: 'metadata_parse_error',
+ message: 'Mapping from object type IDs to names provided for pid=' +
+ pid + ' multiple times.'
+ });
+ return;
+ }
+
+ let objectTypeNamePrefix = undefined;
+ let objectTypeNameSuffix = undefined;
+ const objectTypeNameMap = {};
+ for (const objectTypeId in rawObjectTypeNameMap) {
+ const rawObjectTypeName = rawObjectTypeNameMap[objectTypeId];
+
+ // If we haven't figured out yet which compiler the object type names
+ // come from, we try to do it now.
+ if (objectTypeNamePrefix === undefined) {
+ for (let i = 0; i < OBJECT_TYPE_NAME_PATTERNS.length; i++) {
+ const pattern = OBJECT_TYPE_NAME_PATTERNS[i];
+ if (rawObjectTypeName.startsWith(pattern.prefix) &&
+ rawObjectTypeName.endsWith(pattern.suffix)) {
+ objectTypeNamePrefix = pattern.prefix;
+ objectTypeNameSuffix = pattern.suffix;
+ break;
+ }
+ }
+ }
+
+ if (objectTypeNamePrefix !== undefined &&
+ rawObjectTypeName.startsWith(objectTypeNamePrefix) &&
+ rawObjectTypeName.endsWith(objectTypeNameSuffix)) {
+ // With compiler-specific prefix and suffix (automatically annotated
+ // object types).
+ objectTypeNameMap[objectTypeId] = rawObjectTypeName.substring(
+ objectTypeNamePrefix.length,
+ rawObjectTypeName.length - objectTypeNameSuffix.length);
+ } else {
+ // Without compiler-specific prefix and suffix (manually annotated
+ // object types and '[unknown]').
+ objectTypeNameMap[objectTypeId] = rawObjectTypeName;
+ }
+ }
+
+ this.objectTypeNameMap_[pid] = objectTypeNameMap;
+ },
+
+ importAnnotations_() {
+ for (const id in this.traceAnnotations_) {
+ const annotation = tr.model.Annotation.fromDictIfPossible(
+ this.traceAnnotations_[id]);
+ if (!annotation) {
+ this.model_.importWarning({
+ type: 'annotation_warning',
+ message: 'Unrecognized traceAnnotation typeName \"' +
+ this.traceAnnotations_[id].typeName + '\"'
+ });
+ continue;
+ }
+ this.model_.addAnnotation(annotation);
+ }
+ },
+
+ /**
+ * Called by the Model after all other importers have imported their
+ * events.
+ */
+ finalizeImport() {
+ if (this.softwareMeasuredCpuCount_ !== undefined) {
+ this.model_.kernel.softwareMeasuredCpuCount =
+ this.softwareMeasuredCpuCount_;
+ }
+ this.createFlowSlices_();
+ this.createExplicitObjects_();
+ this.createImplicitObjects_();
+ this.createMemoryDumps_();
+ },
+
+ /* Events can have one or more stack frames associated with them, but
+ * that frame might be encoded either as a stack trace of program counters,
+ * or as a direct stack frame reference. This handles either case and
+ * if found, returns the stackframe.
+ */
+ getStackFrameForEvent_(event, opt_lookForEndEvent) {
+ let sf;
+ let stack;
+ if (opt_lookForEndEvent) {
+ sf = event.esf;
+ stack = event.estack;
+ } else {
+ sf = event.sf;
+ stack = event.stack;
+ }
+ if (stack !== undefined && sf !== undefined) {
+ this.model_.importWarning({
+ type: 'stack_frame_and_stack_error',
+ message: 'Event at ' + event.ts +
+ ' cannot have both a stack and a stackframe.'
+ });
+ return undefined;
+ }
+
+ if (stack !== undefined) {
+ return this.model_.resolveStackToStackFrame_(event.pid, stack);
+ }
+ if (sf === undefined) return undefined;
+
+ const stackFrame = this.model_.stackFrames['g' + sf];
+ if (stackFrame === undefined) {
+ this.model_.importWarning({
+ type: 'sample_import_error',
+ message: 'No frame for ' + sf
+ });
+ return;
+ }
+ return stackFrame;
+ },
+
+ resolveStackToStackFrame_(pid, stack) {
+ // TODO(alph,fmeawad): Add codemap resolution code here.
+ return undefined;
+ },
+
+ importSampleData() {
+ if (!this.sampleEvents_) return;
+ const m = this.model_;
+
+ // If this is the only importer, then fake-create the threads.
+ const events = this.sampleEvents_;
+ if (this.hasEvents_ === undefined) {
+ throw new Error('importEvents is not run before importSampleData');
+ } else if (!this.hasEvents_) {
+ for (let i = 0; i < events.length; i++) {
+ const event = events[i];
+ m.getOrCreateProcess(event.tid).getOrCreateThread(event.tid);
+ }
+ }
+
+ const threadsByTid = {};
+ m.getAllThreads().forEach(function(t) {
+ threadsByTid[t.tid] = t;
+ });
+
+ for (let i = 0; i < events.length; i++) {
+ const event = events[i];
+ const thread = threadsByTid[event.tid];
+ if (thread === undefined) {
+ m.importWarning({
+ type: 'sample_import_error',
+ message: 'Thread ' + events.tid + 'not found'
+ });
+ continue;
+ }
+
+ let cpu;
+ if (event.cpu !== undefined) {
+ cpu = m.kernel.getOrCreateCpu(event.cpu);
+ }
+
+ const leafNode = this.stackFrameTree_.getNode('g' + event.sf);
+
+ const sample = new tr.model.Sample(
+ this.toModelTimeFromUs_(event.ts),
+ event.name,
+ leafNode,
+ thread,
+ cpu,
+ event.weight
+ );
+ m.samples.push(sample);
+ }
+ },
+
+ createAsyncSlices_() {
+ if (this.allAsyncEvents_.length === 0) return;
+
+ this.allAsyncEvents_.sort(function(x, y) {
+ const d = x.event.ts - y.event.ts;
+ if (d !== 0) return d;
+ return x.sequenceNumber - y.sequenceNumber;
+ });
+
+ const legacyEvents = [];
+ // Group nestable async events by ID. Events with the same ID should
+ // belong to the same parent async event.
+ const nestableAsyncEventsByKey = {};
+ const nestableMeasureAsyncEventsByKey = {};
+ for (let i = 0; i < this.allAsyncEvents_.length; i++) {
+ const asyncEventState = this.allAsyncEvents_[i];
+ const event = asyncEventState.event;
+ if (event.ph === 'S' || event.ph === 'F' || event.ph === 'T' ||
+ event.ph === 'p') {
+ legacyEvents.push(asyncEventState);
+ continue;
+ }
+ if (event.cat === undefined) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'Nestable async events (ph: b, e, or n) require a ' +
+ 'cat parameter.'
+ });
+ continue;
+ }
+
+ if (event.name === undefined) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'Nestable async events (ph: b, e, or n) require a ' +
+ 'name parameter.'
+ });
+ continue;
+ }
+
+ const id = TraceEventImporter.scopedIdForEvent_(event);
+ if (id === undefined) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'Nestable async events (ph: b, e, or n) require an ' +
+ 'id parameter.'
+ });
+ continue;
+ }
+
+ if (event.cat === 'blink.user_timing') {
+ const matched = MEASURE_NAME_REGEX.exec(event.name);
+ if (matched !== null) {
+ const key = matched[1] + ':' + event.cat;
+ try {
+ event.args = JSON.parse(Base64.atob(matched[3]) || '{}');
+ } catch (e) {
+ // ignored because we assume that we accidentally
+ // matched a performance.measure() where the user was
+ // not aware of this convention.
+ }
+ if (nestableMeasureAsyncEventsByKey[key] === undefined) {
+ nestableMeasureAsyncEventsByKey[key] = [];
+ }
+ nestableMeasureAsyncEventsByKey[key].push(asyncEventState);
+ continue;
+ }
+ }
+
+ const key = event.cat + ':' + id.toStringWithDelimiter(':');
+ if (nestableAsyncEventsByKey[key] === undefined) {
+ nestableAsyncEventsByKey[key] = [];
+ }
+ nestableAsyncEventsByKey[key].push(asyncEventState);
+ }
+ // Handle legacy async events.
+ this.createLegacyAsyncSlices_(legacyEvents);
+
+ // Parse nestable measure async events into AsyncSlices.
+ this.createNestableAsyncSlices_(nestableMeasureAsyncEventsByKey);
+
+ // Parse nestable async events into AsyncSlices.
+ this.createNestableAsyncSlices_(nestableAsyncEventsByKey);
+ },
+
+ createLegacyAsyncSlice_(events) {
+ const asyncEventState = events[events.length - 1];
+ const event = asyncEventState.event;
+ const name = event.name;
+ const id = TraceEventImporter.scopedIdForEvent_(event);
+ const key = id.toStringWithDelimiter(':');
+ const asyncSliceConstructor = tr.model.AsyncSlice.subTypes.getConstructor(
+ events[0].event.cat, name);
+ let duration;
+ if (event.ts !== undefined) {
+ duration = this.toModelTimeFromUs_(event.ts - events[0].event.ts);
+ }
+ const slice = new asyncSliceConstructor(
+ events[0].event.cat,
+ name,
+ getEventColor(events[0].event),
+ this.toModelTimeFromUs_(events[0].event.ts),
+ Object.assign({}, events[0].event.args, event.args),
+ duration || 0,
+ true,
+ undefined,
+ undefined,
+ events[0].event.argsStripped);
+ if (duration === undefined) {
+ slice.didNotFinish = true;
+ slice.error = 'Slice has no matching END. End time has been adjusted.';
+ // End time will be adjusted by AsyncSliceGroup.autoCloseOpenSlices().
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'Legacy async BEGIN event at ' +
+ events[0].event.ts + ' with name="' +
+ name + '" and id=' + key + ' was unmatched.'
+ });
+ }
+ slice.startThread = events[0].thread;
+ slice.endThread = asyncEventState.thread;
+ slice.id = key;
+
+ const stepType = events[1].event.ph;
+ let isValid = true;
+
+ // Create subSlices for each step. Skip the start and finish events,
+ // which are always first and last respectively.
+ for (let j = 1; j < events.length - 1; ++j) {
+ if (events[j].event.ph === 'T' || events[j].event.ph === 'p') {
+ isValid = this.assertStepTypeMatches_(stepType, events[j]);
+ if (!isValid) break;
+ }
+
+ if (events[j].event.ph === 'S') {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'At ' + events[j].event.ts + ', a slice named "' +
+ name + '" with id=' + id +
+ ' had a step before the start event.'
+ });
+ continue;
+ }
+
+ if (events[j].event.ph === 'F') {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'At ' + events[j].event.ts + ', a slice named ' +
+ name + ' with id=' + id +
+ ' had a step after the finish event.'
+ });
+ continue;
+ }
+
+ const startIndex = j + (stepType === 'T' ? 0 : -1);
+ const endIndex = startIndex + 1;
+
+ let subName = name;
+ if (!events[j].event.argsStripped &&
+ (events[j].event.ph === 'T' || events[j].event.ph === 'p')) {
+ subName = events[j].event.args.step;
+ }
+
+ const asyncSliceConstructor =
+ tr.model.AsyncSlice.subTypes.getConstructor(
+ events[0].event.cat,
+ subName);
+ let duration;
+ if (events[endIndex].event.ts !== undefined) {
+ duration = this.toModelTimeFromUs_(
+ events[endIndex].event.ts - events[startIndex].event.ts);
+ }
+ const subSlice = new asyncSliceConstructor(
+ events[0].event.cat,
+ subName,
+ getEventColor(events[0].event, subName + j),
+ this.toModelTimeFromUs_(events[startIndex].event.ts),
+ this.deepCopyIfNeeded_(events[j].event.args),
+ duration || 0,
+ undefined,
+ undefined,
+ events[startIndex].event.argsStripped);
+ if (duration === undefined) {
+ subSlice.didNotFinish = true;
+ subSlice.error =
+ 'Slice has no matching END. End time has been adjusted.';
+ // End time will be adjusted by AsyncSliceGroup.autoCloseOpenSlices().
+ }
+ subSlice.startThread = events[startIndex].thread;
+ subSlice.endThread = events[endIndex].thread;
+ subSlice.id = key;
+
+ slice.subSlices.push(subSlice);
+ }
+
+ if (isValid) {
+ // Add |slice| to the start-thread's asyncSlices.
+ slice.startThread.asyncSliceGroup.push(slice);
+ }
+ },
+
+ createLegacyAsyncSlices_(legacyEvents) {
+ if (legacyEvents.length === 0) return;
+
+ legacyEvents.sort(function(x, y) {
+ const d = x.event.ts - y.event.ts;
+ if (d !== 0) return d;
+ return x.sequenceNumber - y.sequenceNumber;
+ });
+
+ const asyncEventStatesByNameThenID = {};
+
+ for (let i = 0; i < legacyEvents.length; i++) {
+ const asyncEventState = legacyEvents[i];
+
+ const event = asyncEventState.event;
+ const name = event.name;
+ if (name === undefined) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'Async events (ph: S, T, p, or F) require a name ' +
+ ' parameter.'
+ });
+ continue;
+ }
+
+ const id = TraceEventImporter.scopedIdForEvent_(event);
+ if (id === undefined) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'Async events (ph: S, T, p, or F) require an id parameter.'
+ });
+ continue;
+ }
+ const key = id.toStringWithDelimiter(':');
+ // TODO(simonjam): Add a synchronous tick on the appropriate thread.
+
+ if (event.ph === 'S') {
+ if (asyncEventStatesByNameThenID[name] === undefined) {
+ asyncEventStatesByNameThenID[name] = {};
+ }
+ if (asyncEventStatesByNameThenID[name][key]) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'At ' + event.ts + ', a slice of the same id ' + id +
+ ' was alrady open.'
+ });
+ continue;
+ }
+ asyncEventStatesByNameThenID[name][key] = [];
+ asyncEventStatesByNameThenID[name][key].push(asyncEventState);
+ } else {
+ if (asyncEventStatesByNameThenID[name] === undefined) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: `At ${event.ts}, no slice named "${name}" was open.`,
+ });
+ continue;
+ }
+ if (asyncEventStatesByNameThenID[name][key] === undefined) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message:
+ `At ${event.ts}, no slice named "${name}" with id=${id} was ` +
+ 'open.',
+ });
+ continue;
+ }
+ const events = asyncEventStatesByNameThenID[name][key];
+ events.push(asyncEventState);
+
+ if (event.ph === 'F') {
+ this.createLegacyAsyncSlice_(events);
+ delete asyncEventStatesByNameThenID[name][key];
+ }
+ }
+ }
+
+ // Auto-close unmatched S events by creating a fake F event.
+ for (const [name, statesByID] of
+ Object.entries(asyncEventStatesByNameThenID)) {
+ for (const [id, states] of Object.entries(statesByID)) {
+ const startEvent = states[0].event;
+ // Don't set 'ts' in the fake 'F' event. createLegacyAsyncSlice_ will
+ // set duration=undefined and didNotFinish=true.
+ // AsyncSliceGroup.autoCloseOpenSlices() will set duration so that the
+ // AsyncSlice ends when the trace ends.
+ states.push({
+ sequenceNumber: 1 + states[states.length - 1].sequenceNumber,
+ event: {
+ ph: 'F',
+ name,
+ id: startEvent.id,
+ id2: startEvent.id2,
+ scope: startEvent.scope,
+ pid: startEvent.pid,
+ tid: startEvent.tid,
+ cat: startEvent.cat,
+ args: {},
+ },
+ thread: this.model_.getOrCreateProcess(startEvent.pid).
+ getOrCreateThread(startEvent.tid),
+ });
+ this.createLegacyAsyncSlice_(states);
+ }
+ }
+ },
+
+ createNestableAsyncSlices_(nestableEventsByKey) {
+ for (const key in nestableEventsByKey) {
+ const eventStateEntries = nestableEventsByKey[key];
+ // Stack of enclosing BEGIN events.
+ const parentStack = [];
+ for (let i = 0; i < eventStateEntries.length; ++i) {
+ const eventStateEntry = eventStateEntries[i];
+ // If this is the end of an event, match it to the start.
+ if (eventStateEntry.event.ph === 'e') {
+ // Walk up the parent stack to find the corresponding BEGIN for
+ // this END.
+ let parentIndex = -1;
+ for (let k = parentStack.length - 1; k >= 0; --k) {
+ if (parentStack[k].event.name === eventStateEntry.event.name) {
+ parentIndex = k;
+ break;
+ }
+ }
+ if (parentIndex === -1) {
+ // Unmatched end.
+ eventStateEntry.finished = false;
+ } else {
+ parentStack[parentIndex].end = eventStateEntry;
+ // Pop off all enclosing unmatched BEGINs util parentIndex.
+ while (parentIndex < parentStack.length) {
+ parentStack.pop();
+ }
+ }
+ }
+ // Inherit the current parent.
+ if (parentStack.length > 0) {
+ eventStateEntry.parentEntry = parentStack[parentStack.length - 1];
+ }
+ if (eventStateEntry.event.ph === 'b') {
+ parentStack.push(eventStateEntry);
+ }
+ }
+ const topLevelSlices = [];
+ for (let i = 0; i < eventStateEntries.length; ++i) {
+ const eventStateEntry = eventStateEntries[i];
+ // Skip matched END, as its slice will be created when we
+ // encounter its corresponding BEGIN.
+ if (eventStateEntry.event.ph === 'e' &&
+ eventStateEntry.finished === undefined) {
+ continue;
+ }
+ let startState = undefined;
+ let endState = undefined;
+ let sliceArgs = eventStateEntry.event.args || {};
+ let sliceError = undefined;
+ const id = TraceEventImporter.scopedIdForEvent_(
+ eventStateEntry.event);
+ if (eventStateEntry.event.ph === 'n') {
+ startState = eventStateEntry;
+ endState = eventStateEntry;
+ } else if (eventStateEntry.event.ph === 'b') {
+ if (eventStateEntry.end === undefined) {
+ // Unmatched BEGIN. End it when last event with this ID ends.
+ eventStateEntry.end =
+ eventStateEntries[eventStateEntries.length - 1];
+ sliceError =
+ 'Slice has no matching END. End time has been adjusted.';
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'Nestable async BEGIN event at ' +
+ eventStateEntry.event.ts + ' with name="' +
+ eventStateEntry.event.name + '" and id=' + id +
+ ' was unmatched.'
+ });
+ } else {
+ // Include args for both END and BEGIN for a matched pair.
+ function concatenateArguments(args1, args2) {
+ if (args1.params === undefined || args2.params === undefined) {
+ return Object.assign({}, args1, args2);
+ }
+ // Make an argument object to hold the combined params.
+ const args3 = {};
+ args3.params = Object.assign({}, args1.params, args2.params);
+ return Object.assign({}, args1, args2, args3);
+ }
+ const endArgs = eventStateEntry.end.event.args || {};
+ sliceArgs = concatenateArguments(sliceArgs, endArgs);
+ }
+ startState = eventStateEntry;
+ endState = eventStateEntry.end;
+ } else {
+ // Unmatched END. Start it at the first event with this ID starts.
+ sliceError =
+ 'Slice has no matching BEGIN. Start time has been adjusted.';
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'Nestable async END event at ' +
+ eventStateEntry.event.ts + ' with name=' +
+ eventStateEntry.event.name +
+ ' and id=' + id + ' was unmatched.'
+ });
+ startState = eventStateEntries[0];
+ endState = eventStateEntry;
+ }
+
+ const isTopLevel = (eventStateEntry.parentEntry === undefined);
+ const asyncSliceConstructor =
+ tr.model.AsyncSlice.subTypes.getConstructor(
+ eventStateEntry.event.cat,
+ eventStateEntry.event.name);
+
+ let threadStart = undefined;
+ let threadDuration = undefined;
+ if (startState.event.tts && startState.event.use_async_tts) {
+ threadStart = this.toModelTimeFromUs_(startState.event.tts);
+ if (endState.event.tts) {
+ const threadEnd = this.toModelTimeFromUs_(endState.event.tts);
+ threadDuration = threadEnd - threadStart;
+ }
+ }
+
+ const slice = new asyncSliceConstructor(
+ eventStateEntry.event.cat,
+ eventStateEntry.event.name,
+ getEventColor(endState.event),
+ this.toModelTimeFromUs_(startState.event.ts),
+ sliceArgs,
+ this.toModelTimeFromUs_(endState.event.ts - startState.event.ts),
+ isTopLevel,
+ threadStart,
+ threadDuration,
+ startState.event.argsStripped);
+
+ slice.startThread = startState.thread;
+ slice.endThread = endState.thread;
+
+ slice.startStackFrame = this.getStackFrameForEvent_(startState.event);
+ slice.endStackFrame = this.getStackFrameForEvent_(endState.event);
+
+ slice.id = key;
+ if (sliceError !== undefined) {
+ slice.error = sliceError;
+ }
+ eventStateEntry.slice = slice;
+ // Add the slice to the topLevelSlices array if there is no parent.
+ // Otherwise, add the slice to the subSlices of its parent.
+ if (isTopLevel) {
+ topLevelSlices.push(slice);
+ } else if (eventStateEntry.parentEntry.slice !== undefined) {
+ eventStateEntry.parentEntry.slice.subSlices.push(slice);
+ }
+ }
+ for (let si = 0; si < topLevelSlices.length; si++) {
+ topLevelSlices[si].startThread.asyncSliceGroup.push(
+ topLevelSlices[si]);
+ }
+ }
+ },
+
+ assertStepTypeMatches_(stepType, event) {
+ if (stepType !== event.event.ph) {
+ this.model_.importWarning({
+ type: 'async_slice_parse_error',
+ message: 'At ' + event.event.ts + ', a slice named ' +
+ event.event.name + ' with id=' +
+ TraceEventImporter.scopedIdForEvent_(event.event) +
+ ' had both begin and end steps, which is not allowed.'
+ });
+ return false;
+ }
+ return true;
+ },
+
+ validateFlowEvent_(event) {
+ if (event.name === undefined) {
+ this.model_.importWarning({
+ type: 'flow_slice_parse_error',
+ message: 'Flow events (ph: s, t or f) require a name parameter.'
+ });
+ return false;
+ }
+
+ // Support Flow API v1.
+ if (event.ph === 's' || event.ph === 'f' || event.ph === 't') {
+ if (event.id === undefined) {
+ this.model_.importWarning({
+ type: 'flow_slice_parse_error',
+ message: 'Flow events (ph: s, t or f) require an id parameter.'
+ });
+ return false;
+ }
+ return true;
+ }
+
+ // Support Flow API v2.
+ if (event.bind_id) {
+ if (event.flow_in === undefined && event.flow_out === undefined) {
+ this.model_.importWarning({
+ type: 'flow_slice_parse_error',
+ message: 'Flow producer or consumer require flow_in or flow_out.'
+ });
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+ },
+
+ createFlowSlices_() {
+ if (this.allFlowEvents_.length === 0) return;
+
+ const createFlowEvent = function(thread, event, opt_slice) {
+ let startSlice;
+ let flowId;
+ let flowStartTs;
+
+ if (event.bind_id) {
+ // Support Flow API v2.
+ startSlice = opt_slice;
+ flowId = event.bind_id;
+ flowStartTs = this.toModelTimeFromUs_(event.ts + event.dur);
+ } else {
+ // Support Flow API v1.
+ const ts = this.toModelTimeFromUs_(event.ts);
+ startSlice = thread.sliceGroup.findSliceAtTs(ts);
+ if (startSlice === undefined) return undefined;
+ flowId = event.id;
+ flowStartTs = ts;
+ }
+
+ const flowEvent = new tr.model.FlowEvent(
+ event.cat,
+ flowId,
+ event.name,
+ getEventColor(event),
+ flowStartTs,
+ this.deepCopyAlways_(event.args));
+ flowEvent.startSlice = startSlice;
+ flowEvent.startStackFrame = this.getStackFrameForEvent_(event);
+ flowEvent.endStackFrame = undefined;
+ startSlice.outFlowEvents.push(flowEvent);
+ return flowEvent;
+ }.bind(this);
+
+ const finishFlowEventWith = function(
+ flowEvent, thread, event, refGuid, bindToParent, opt_slice) {
+ let endSlice;
+
+ if (event.bind_id) {
+ // Support Flow API v2.
+ endSlice = opt_slice;
+ } else {
+ // Support Flow API v1.
+ const ts = this.toModelTimeFromUs_(event.ts);
+ if (bindToParent) {
+ endSlice = thread.sliceGroup.findSliceAtTs(ts);
+ } else {
+ endSlice = thread.sliceGroup.findNextSliceAfter(ts, refGuid);
+ }
+ if (endSlice === undefined) return false;
+ }
+
+ endSlice.inFlowEvents.push(flowEvent);
+ flowEvent.endSlice = endSlice;
+ flowEvent.duration =
+ this.toModelTimeFromUs_(event.ts) - flowEvent.start;
+ flowEvent.endStackFrame = this.getStackFrameForEvent_(event);
+ this.mergeArgsInto_(flowEvent.args, event.args, flowEvent.title);
+ return true;
+ }.bind(this);
+
+ const processFlowConsumer = function(
+ flowIdToEvent, sliceGuidToEvent, event, slice) {
+ let flowEvent = flowIdToEvent[event.bind_id];
+ if (flowEvent === undefined) {
+ this.model_.importWarning({
+ type: 'flow_slice_ordering_error',
+ message: 'Flow consumer ' + event.bind_id + ' does not have ' +
+ 'a flow producer'});
+ return false;
+ } else if (flowEvent.endSlice) {
+ // One flow producer can have more than one flow consumers.
+ // In this case, create a new flow event using the flow producer.
+ const flowProducer = flowEvent.startSlice;
+ flowEvent = createFlowEvent(undefined,
+ sliceGuidToEvent[flowProducer.guid], flowProducer);
+ }
+
+ const refGuid = undefined;
+ const ok = finishFlowEventWith(flowEvent, undefined, event,
+ refGuid, undefined, slice);
+ if (ok) {
+ this.model_.flowEvents.push(flowEvent);
+ } else {
+ this.model_.importWarning({
+ type: 'flow_slice_end_error',
+ message: 'Flow consumer ' + event.bind_id + ' does not end ' +
+ 'at an actual slice, so cannot be created.'});
+ return false;
+ }
+
+ return true;
+ }.bind(this);
+
+ const processFlowProducer = function(
+ flowIdToEvent, flowStatus, event, slice) {
+ if (flowIdToEvent[event.bind_id] &&
+ flowStatus[event.bind_id]) {
+ // Can't open the same flow again while it's still open.
+ // This is essentially the multi-producer case which we don't support
+ this.model_.importWarning({
+ type: 'flow_slice_start_error',
+ message: 'Flow producer ' + event.bind_id + ' already seen'});
+ return false;
+ }
+
+ const flowEvent = createFlowEvent(undefined, event, slice);
+ if (!flowEvent) {
+ this.model_.importWarning({
+ type: 'flow_slice_start_error',
+ message: 'Flow producer ' + event.bind_id + ' does not start' +
+ 'a flow'});
+ return false;
+ }
+ flowIdToEvent[event.bind_id] = flowEvent;
+ }.bind(this);
+
+ // Actual import.
+ this.allFlowEvents_.sort(function(x, y) {
+ const d = x.event.ts - y.event.ts;
+ if (d !== 0) return d;
+ return x.sequenceNumber - y.sequenceNumber;
+ });
+
+ const flowIdToEvent = {};
+ const sliceGuidToEvent = {};
+ const flowStatus = {}; // true: open; false: closed.
+ for (let i = 0; i < this.allFlowEvents_.length; ++i) {
+ const data = this.allFlowEvents_[i];
+ const refGuid = data.refGuid;
+ const event = data.event;
+ const thread = data.thread;
+
+ if (!this.validateFlowEvent_(event)) continue;
+
+ // Support for Flow API v2.
+ if (event.bind_id) {
+ const slice = data.slice;
+ sliceGuidToEvent[slice.guid] = event;
+
+ if (event.flowPhase === PRODUCER) {
+ if (!processFlowProducer(flowIdToEvent, flowStatus, event, slice)) {
+ continue;
+ }
+ flowStatus[event.bind_id] = true; // open the flow.
+ } else {
+ if (!processFlowConsumer(flowIdToEvent, sliceGuidToEvent,
+ event, slice)) {
+ continue;
+ }
+ flowStatus[event.bind_id] = false; // close the flow.
+
+ if (event.flowPhase === STEP) {
+ if (!processFlowProducer(flowIdToEvent, flowStatus,
+ event, slice)) {
+ continue;
+ }
+ flowStatus[event.bind_id] = true; // open the flow again.
+ }
+ }
+ continue;
+ }
+
+ // Support for Flow API v1.
+ let flowEvent;
+ if (event.ph === 's') {
+ if (flowIdToEvent[event.id]) {
+ this.model_.importWarning({
+ type: 'flow_slice_start_error',
+ message: 'event id ' + event.id + ' already seen when ' +
+ 'encountering start of flow event.'});
+ continue;
+ }
+ flowEvent = createFlowEvent(thread, event);
+ if (!flowEvent) {
+ this.model_.importWarning({
+ type: 'flow_slice_start_error',
+ message: 'event id ' + event.id + ' does not start ' +
+ 'at an actual slice, so cannot be created.'});
+ continue;
+ }
+ flowIdToEvent[event.id] = flowEvent;
+ } else if (event.ph === 't' || event.ph === 'f') {
+ flowEvent = flowIdToEvent[event.id];
+ if (flowEvent === undefined) {
+ this.model_.importWarning({
+ type: 'flow_slice_ordering_error',
+ message: 'Found flow phase ' + event.ph + ' for id: ' + event.id +
+ ' but no flow start found.'
+ });
+ continue;
+ }
+
+ let bindToParent = event.ph === 't';
+
+ if (event.ph === 'f') {
+ if (event.bp === undefined) {
+ // TODO(yuhaoz): In flow V2, there is no notion of binding point.
+ // Removal of binding point is tracked in
+ // https://github.com/google/trace-viewer/issues/991.
+ if (event.cat.indexOf('input') > -1) {
+ bindToParent = true;
+ } else if (event.cat.indexOf('ipc.flow') > -1) {
+ bindToParent = true;
+ }
+ } else {
+ if (event.bp !== 'e') {
+ this.model_.importWarning({
+ type: 'flow_slice_bind_point_error',
+ message: 'Flow event with invalid binding point (event.bp).'
+ });
+ continue;
+ }
+ bindToParent = true;
+ }
+ }
+
+ const ok = finishFlowEventWith(flowEvent, thread, event,
+ refGuid, bindToParent);
+ if (ok) {
+ this.model_.flowEvents.push(flowEvent);
+ } else {
+ this.model_.importWarning({
+ type: 'flow_slice_end_error',
+ message: 'event id ' + event.id + ' does not end ' +
+ 'at an actual slice, so cannot be created.'});
+ }
+ flowIdToEvent[event.id] = undefined;
+
+ // If this is a step, then create another flow event.
+ if (ok && event.ph === 't') {
+ flowEvent = createFlowEvent(thread, event);
+ flowIdToEvent[event.id] = flowEvent;
+ }
+ }
+ }
+ },
+
+ /**
+ * This function creates objects described via the N, D, and O phase
+ * events.
+ */
+ createExplicitObjects_() {
+ if (this.allObjectEvents_.length === 0) return;
+
+ const processEvent = function(objectEventState) {
+ const event = objectEventState.event;
+ const scopedId = TraceEventImporter.scopedIdForEvent_(event);
+ const thread = objectEventState.thread;
+ if (event.name === undefined) {
+ this.model_.importWarning({
+ type: 'object_parse_error',
+ message: 'While processing ' + JSON.stringify(event) + ': ' +
+ 'Object events require an name parameter.'
+ });
+ }
+
+ if (scopedId === undefined || scopedId.id === undefined) {
+ this.model_.importWarning({
+ type: 'object_parse_error',
+ message: 'While processing ' + JSON.stringify(event) + ': ' +
+ 'Object events require an id parameter.'
+ });
+ }
+ const process = thread.parent;
+ const ts = this.toModelTimeFromUs_(event.ts);
+ let instance;
+ if (event.ph === 'N') {
+ try {
+ instance = process.objects.idWasCreated(
+ scopedId, event.cat, event.name, ts);
+ } catch (e) {
+ this.model_.importWarning({
+ type: 'object_parse_error',
+ message: 'While processing create of ' +
+ scopedId + ' at ts=' + ts + ': ' + e
+ });
+ return;
+ }
+ } else if (event.ph === 'O') {
+ if (event.args.snapshot === undefined) {
+ this.model_.importWarning({
+ type: 'object_parse_error',
+ message: 'While processing ' + scopedId + ' at ts=' + ts + ': ' +
+ 'Snapshots must have args: {snapshot: ...}'
+ });
+ return;
+ }
+ let snapshot;
+ try {
+ const args = this.deepCopyIfNeeded_(event.args.snapshot);
+ let cat;
+ if (args.cat) {
+ cat = args.cat;
+ delete args.cat;
+ } else {
+ cat = event.cat;
+ }
+
+ let baseTypename;
+ if (args.base_type) {
+ baseTypename = args.base_type;
+ delete args.base_type;
+ } else {
+ baseTypename = undefined;
+ }
+ snapshot = process.objects.addSnapshot(
+ scopedId, cat, event.name, ts, args, baseTypename);
+ snapshot.snapshottedOnThread = thread;
+ } catch (e) {
+ this.model_.importWarning({
+ type: 'object_parse_error',
+ message: 'While processing snapshot of ' +
+ scopedId + ' at ts=' + ts + ': ' + e
+ });
+ return;
+ }
+ instance = snapshot.objectInstance;
+ } else if (event.ph === 'D') {
+ try {
+ process.objects.idWasDeleted(scopedId, event.cat, event.name, ts);
+ const instanceMap = process.objects.getOrCreateInstanceMap_(
+ scopedId);
+ instance = instanceMap.lastInstance;
+ } catch (e) {
+ this.model_.importWarning({
+ type: 'object_parse_error',
+ message: 'While processing delete of ' +
+ scopedId + ' at ts=' + ts + ': ' + e
+ });
+ return;
+ }
+ }
+
+ if (instance) {
+ instance.colorId = getEventColor(event, instance.typeName);
+ }
+ }.bind(this);
+
+ this.allObjectEvents_.sort(function(x, y) {
+ const d = x.event.ts - y.event.ts;
+ if (d !== 0) return d;
+ return x.sequenceNumber - y.sequenceNumber;
+ });
+
+ const allObjectEvents = this.allObjectEvents_;
+ for (let i = 0; i < allObjectEvents.length; i++) {
+ const objectEventState = allObjectEvents[i];
+ try {
+ processEvent.call(this, objectEventState);
+ } catch (e) {
+ this.model_.importWarning({
+ type: 'object_parse_error',
+ message: e.message
+ });
+ }
+ }
+ },
+
+ createImplicitObjects_() {
+ for (const proc of Object.values(this.model_.processes)) {
+ this.createImplicitObjectsForProcess_(proc);
+ }
+ },
+
+ // Here, we collect all the snapshots that internally contain a
+ // Javascript-level object inside their args list that has an "id" field,
+ // and turn that into a snapshot of the instance referred to by id.
+ createImplicitObjectsForProcess_(process) {
+ function processField(referencingObject,
+ referencingObjectFieldName,
+ referencingObjectFieldValue,
+ containingSnapshot) {
+ if (!referencingObjectFieldValue) return;
+
+ if (referencingObjectFieldValue instanceof
+ tr.model.ObjectSnapshot) {
+ return null;
+ }
+ if (referencingObjectFieldValue.id === undefined) return;
+
+ const implicitSnapshot = referencingObjectFieldValue;
+
+ const rawId = implicitSnapshot.id;
+ const m = /(.+)\/(.+)/.exec(rawId);
+ if (!m) {
+ throw new Error('Implicit snapshots must have names.');
+ }
+ delete implicitSnapshot.id;
+ const name = m[1];
+ const id = m[2];
+ let res;
+
+ let cat;
+ if (implicitSnapshot.cat !== undefined) {
+ cat = implicitSnapshot.cat;
+ } else {
+ cat = containingSnapshot.objectInstance.category;
+ }
+
+ let baseTypename;
+ if (implicitSnapshot.base_type) {
+ baseTypename = implicitSnapshot.base_type;
+ } else {
+ baseTypename = undefined;
+ }
+
+ const scope = containingSnapshot.objectInstance.scopedId.scope;
+
+ try {
+ res = process.objects.addSnapshot(
+ new tr.model.ScopedId(scope, id), cat,
+ name, containingSnapshot.ts,
+ implicitSnapshot, baseTypename);
+ } catch (e) {
+ this.model_.importWarning({
+ type: 'object_snapshot_parse_error',
+ message: 'While processing implicit snapshot of ' +
+ rawId + ' at ts=' + containingSnapshot.ts + ': ' + e
+ });
+ return;
+ }
+ res.objectInstance.hasImplicitSnapshots = true;
+ res.containingSnapshot = containingSnapshot;
+ res.snapshottedOnThread = containingSnapshot.snapshottedOnThread;
+ referencingObject[referencingObjectFieldName] = res;
+ if (!(res instanceof tr.model.ObjectSnapshot)) {
+ throw new Error('Created object must be instanceof snapshot');
+ }
+ return res.args;
+ }
+
+ /**
+ * Iterates over the fields in the object, calling func for every
+ * field/value found.
+ *
+ * @return {object} If the function does not want the field's value to be
+ * iterated, return null. If iteration of the field value is desired, then
+ * return either undefined (if the field value did not change) or the new
+ * field value if it was changed.
+ */
+ function iterObject(object, func, containingSnapshot, thisArg) {
+ if (!(object instanceof Object)) return;
+
+ if (object instanceof Array) {
+ for (let i = 0; i < object.length; i++) {
+ const res = func.call(thisArg, object, i, object[i],
+ containingSnapshot);
+ if (res === null) continue;
+ if (res) {
+ iterObject(res, func, containingSnapshot, thisArg);
+ } else {
+ iterObject(object[i], func, containingSnapshot, thisArg);
+ }
+ }
+ return;
+ }
+
+ for (const key in object) {
+ const res = func.call(thisArg, object, key, object[key],
+ containingSnapshot);
+ if (res === null) continue;
+ if (res) {
+ iterObject(res, func, containingSnapshot, thisArg);
+ } else {
+ iterObject(object[key], func, containingSnapshot, thisArg);
+ }
+ }
+ }
+
+ // TODO(nduca): We may need to iterate the instances in sorted order by
+ // creationTs.
+ process.objects.iterObjectInstances(function(instance) {
+ instance.snapshots.forEach(function(snapshot) {
+ if (snapshot.args.id !== undefined) {
+ throw new Error('args cannot have an id field inside it');
+ }
+ iterObject(snapshot.args, processField, snapshot, this);
+ }, this);
+ }, this);
+ },
+
+ // Takes an object of type: PID -> [process memory dump events]
+ // Returns smallest timestamp among events or Infinity if there are none.
+ minimalTimestampInPidToEvents_(pidToEvents) {
+ let smallestTs = Infinity;
+ for (const events of Object.values(pidToEvents)) {
+ for (const event of events) {
+ if (event.ts < smallestTs) {
+ smallestTs = event.ts;
+ }
+ }
+ }
+ return smallestTs;
+ },
+
+ createMemoryDumps_() {
+ // We must create the global dumps in chronological order since later
+ // heap dumps can depend on earlier ones. Not all events within a single
+ // global dump have the same timestamp but events for two different
+ // global dumps can not be interspersed. However, for consistency,
+ // we sort the global dumps by the earliest timestamp present in an event
+ // in that dump.
+ const pairs = Object.entries(this.allMemoryDumpEvents_);
+ const key = x => this.minimalTimestampInPidToEvents_(x);
+ pairs.sort((x, y) => key(x[1]) - key(y[1]));
+ for (const [dumpId, pidToEvents] of pairs) {
+ this.createGlobalMemoryDump_(pidToEvents, dumpId);
+ }
+ },
+
+ createGlobalMemoryDump_(dumpIdEvents, dumpId) {
+ // 1. Create a GlobalMemoryDump for the provided process memory dump
+ // the events, all of which have the same dump ID.
+
+ // Calculate the range of the global memory dump.
+ const globalRange = new tr.b.math.Range();
+ for (const pid in dumpIdEvents) {
+ const processEvents = dumpIdEvents[pid];
+ for (let i = 0; i < processEvents.length; i++) {
+ globalRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));
+ }
+ }
+ if (globalRange.isEmpty) {
+ throw new Error('Internal error: Global memory dump without events');
+ }
+
+ // Create the global memory dump.
+ const globalMemoryDump = new tr.model.GlobalMemoryDump(
+ this.model_, globalRange.min);
+ globalMemoryDump.duration = globalRange.range;
+ this.model_.globalMemoryDumps.push(globalMemoryDump);
+
+ const globalMemoryAllocatorDumpsByFullName = {};
+ const levelsOfDetail = {};
+ const allMemoryAllocatorDumpsByGuid = {};
+
+ // 2. Create a ProcessMemoryDump for each PID in the provided process
+ // memory dump events. Everything except for edges between memory
+ // allocator dumps is parsed from the process memory dump trace events at
+ // this step.
+ for (const pid in dumpIdEvents) {
+ this.createProcessMemoryDump_(globalMemoryDump,
+ globalMemoryAllocatorDumpsByFullName, levelsOfDetail,
+ allMemoryAllocatorDumpsByGuid, dumpIdEvents[pid], pid, dumpId);
+ }
+
+ // 3. Set the level of detail and memory allocator dumps of the
+ // GlobalMemoryDump, which come from the process memory dump trace
+ // events parsed in the prebvious step.
+ globalMemoryDump.levelOfDetail = levelsOfDetail.global;
+
+ // Find the root allocator dumps and establish the parent links of
+ // the global memory dump.
+ globalMemoryDump.memoryAllocatorDumps =
+ this.inferMemoryAllocatorDumpTree_(
+ globalMemoryAllocatorDumpsByFullName);
+
+ // 4. Finally, parse the edges between all memory allocator dumps within
+ // the GlobalMemoryDump. This can only be done once all memory allocator
+ // dumps have been parsed (i.e. it is necessary to iterate over the
+ // process memory dump trace events once more).
+ this.parseMemoryDumpAllocatorEdges_(allMemoryAllocatorDumpsByGuid,
+ dumpIdEvents, dumpId);
+ },
+
+ createProcessMemoryDump_(globalMemoryDump,
+ globalMemoryAllocatorDumpsByFullName, levelsOfDetail,
+ allMemoryAllocatorDumpsByGuid, processEvents, pid, dumpId) {
+ // Calculate the range of the process memory dump.
+ const processRange = new tr.b.math.Range();
+ for (let i = 0; i < processEvents.length; i++) {
+ processRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));
+ }
+ if (processRange.isEmpty) {
+ throw new Error('Internal error: Process memory dump without events');
+ }
+
+ // Create the process memory dump.
+ const process = this.model_.getOrCreateProcess(pid);
+ const processMemoryDump = new tr.model.ProcessMemoryDump(
+ globalMemoryDump, process, processRange.min);
+ processMemoryDump.duration = processRange.range;
+ process.memoryDumps.push(processMemoryDump);
+ globalMemoryDump.processMemoryDumps[pid] = processMemoryDump;
+
+ const processMemoryAllocatorDumpsByFullName = {};
+
+ // Parse all process memory dump trace events for the newly created
+ // ProcessMemoryDump.
+ for (let i = 0; i < processEvents.length; i++) {
+ const processEvent = processEvents[i];
+
+ const dumps = processEvent.args.dumps;
+ if (dumps === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: '\'dumps\' field not found in a process memory dump' +
+ ' event for PID=' + pid + ' and dump ID=' + dumpId + '.'
+ });
+ continue;
+ }
+
+ // Totals, VM regions, and heap dumps for the newly created
+ // ProcessMemoryDump should be present in at most one event, so they
+ // can be added to the ProcessMemoryDump immediately.
+ this.parseMemoryDumpTotals_(processMemoryDump, dumps, pid, dumpId);
+ this.parseMemoryDumpVmRegions_(processMemoryDump, dumps, pid, dumpId);
+ this.parseMemoryDumpHeapDumps_(processMemoryDump, dumps, pid, dumpId);
+
+ // All process memory dump trace events for the newly created
+ // ProcessMemoryDump must be processed before level of detail and
+ // allocator dumps can be added to it.
+ this.parseMemoryDumpLevelOfDetail_(levelsOfDetail, dumps, pid,
+ dumpId);
+ this.parseMemoryDumpAllocatorDumps_(processMemoryDump, globalMemoryDump,
+ processMemoryAllocatorDumpsByFullName,
+ globalMemoryAllocatorDumpsByFullName,
+ allMemoryAllocatorDumpsByGuid, dumps, pid, dumpId);
+ }
+
+ if (levelsOfDetail.process === undefined) {
+ // Infer level of detail from the presence of VM regions in legacy
+ // traces (where raw process memory dump events don't contain the
+ // level_of_detail field). These traces will not have BACKGROUND mode.
+ levelsOfDetail.process = processMemoryDump.vmRegions ? DETAILED : LIGHT;
+ }
+ if (!this.updateMemoryDumpLevelOfDetail_(
+ levelsOfDetail, 'global', levelsOfDetail.process)) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'diffent levels of detail provided for global memory' +
+ ' dump (dump ID=' + dumpId + ').'
+ });
+ }
+ processMemoryDump.levelOfDetail = levelsOfDetail.process;
+ delete levelsOfDetail.process; // Reused for all process dumps.
+
+ // Find the root allocator dumps and establish the parent links of
+ // the process memory dump.
+ processMemoryDump.memoryAllocatorDumps =
+ this.inferMemoryAllocatorDumpTree_(
+ processMemoryAllocatorDumpsByFullName);
+ },
+
+ parseMemoryDumpTotals_(processMemoryDump, dumps, pid, dumpId) {
+ const rawTotals = dumps.process_totals;
+ if (rawTotals === undefined) return;
+
+ if (processMemoryDump.totals !== undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Process totals provided multiple times for' +
+ ' process memory dump for PID=' + pid +
+ ' and dump ID=' + dumpId + '.'
+ });
+ return;
+ }
+
+ const totals = {};
+ let platformSpecificTotals = undefined;
+
+ for (const rawTotalName in rawTotals) {
+ const rawTotalValue = rawTotals[rawTotalName];
+ if (rawTotalValue === undefined) continue;
+
+ // Total resident bytes.
+ if (rawTotalName === 'resident_set_bytes') {
+ totals.residentBytes = parseInt(rawTotalValue, 16);
+ continue;
+ }
+
+ // Peak resident bytes.
+ if (rawTotalName === 'peak_resident_set_bytes') {
+ totals.peakResidentBytes = parseInt(rawTotalValue, 16);
+ continue;
+ }
+ if (rawTotalName === 'is_peak_rss_resetable') {
+ totals.arePeakResidentBytesResettable = !!rawTotalValue;
+ continue;
+ }
+
+ // Private footprint
+ if (rawTotalName === 'private_footprint_bytes') {
+ totals.privateFootprintBytes = parseInt(rawTotalValue, 16);
+ continue;
+ }
+
+ // OS-specific totals (e.g. private resident on Mac).
+ if (platformSpecificTotals === undefined) {
+ platformSpecificTotals = {};
+ totals.platformSpecific = platformSpecificTotals;
+ }
+ platformSpecificTotals[rawTotalName] = parseInt(rawTotalValue, 16);
+ }
+
+ // Either both peak_resident_set_bytes and is_peak_rss_resetable should
+ // be present in the trace, or neither.
+ if (totals.peakResidentBytes === undefined &&
+ totals.arePeakResidentBytesResettable !== undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Optional field peak_resident_set_bytes found' +
+ ' but is_peak_rss_resetable not found in' +
+ ' process memory dump for PID=' + pid +
+ ' and dump ID=' + dumpId + '.'
+ });
+ }
+ if (totals.arePeakResidentBytesResettable !== undefined &&
+ totals.peakResidentBytes === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Optional field is_peak_rss_resetable found' +
+ ' but peak_resident_set_bytes not found in' +
+ ' process memory dump for PID=' + pid +
+ ' and dump ID=' + dumpId + '.'
+ });
+ }
+
+ processMemoryDump.totals = totals;
+ },
+
+ parseMemoryDumpVmRegions_(processMemoryDump, dumps, pid, dumpId) {
+ const rawProcessMmaps = dumps.process_mmaps;
+ if (rawProcessMmaps === undefined) return;
+
+ const rawVmRegions = rawProcessMmaps.vm_regions;
+ if (rawVmRegions === undefined) return;
+
+ if (processMemoryDump.vmRegions !== undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'VM regions provided multiple times for' +
+ ' process memory dump for PID=' + pid +
+ ' and dump ID=' + dumpId + '.'
+ });
+ return;
+ }
+
+ // In Chromium under //services/resource_coordinator/public see
+ // mojom/memory_instrumentation/memory_instrumentation.mojom and
+ // cpp/memory_instrumentation/tracing_observer.cc
+ const vmRegions = new Array(rawVmRegions.length);
+ for (let i = 0; i < rawVmRegions.length; i++) {
+ const rawVmRegion = rawVmRegions[i];
+
+ const byteStats = {};
+ const rawByteStats = rawVmRegion.bs;
+ for (const rawByteStatName in rawByteStats) {
+ const rawByteStatValue = rawByteStats[rawByteStatName];
+ if (rawByteStatValue === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Byte stat \'' + rawByteStatName + '\' of VM region ' +
+ i + ' (' + rawVmRegion.mf + ') in process memory dump for ' +
+ 'PID=' + pid + ' and dump ID=' + dumpId +
+ ' does not have a value.'
+ });
+ continue;
+ }
+ const byteStatName = BYTE_STAT_NAME_MAP[rawByteStatName];
+ if (byteStatName === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Unknown byte stat name \'' + rawByteStatName + '\' (' +
+ rawByteStatValue + ') of VM region ' + i + ' (' +
+ rawVmRegion.mf + ') in process memory dump for PID=' + pid +
+ ' and dump ID=' + dumpId + '.'
+ });
+ continue;
+ }
+ byteStats[byteStatName] = parseInt(rawByteStatValue, 16);
+ // OSX does not report PSS and instead emits all zeros.
+ // Zero is a valid value for some byteStats but not PSS so this could
+ // could to confusion when we later compute with and display the PSS.
+ // To avoid this we ignore zero PSS values (since PSS should never
+ // be zero). See: github.com/catapult-project/catapult/issues/3501
+ if (byteStatName === 'proportionalResident' &&
+ byteStats[byteStatName] === 0) {
+ byteStats[byteStatName] = undefined;
+ }
+ }
+
+ vmRegions[i] = new tr.model.VMRegion(
+ parseInt(rawVmRegion.sa, 16), // startAddress
+ parseInt(rawVmRegion.sz, 16), // sizeInBytes
+ rawVmRegion.pf, // protectionFlags
+ rawVmRegion.mf, // mappedFile
+ byteStats);
+ }
+
+ processMemoryDump.vmRegions =
+ tr.model.VMRegionClassificationNode.fromRegions(vmRegions);
+ },
+
+ parseMemoryDumpHeapDumps_(processMemoryDump, dumps, pid, dumpId) {
+ const idPrefix = 'p' + pid + ':';
+ let importer;
+ if (dumps.heaps) {
+ const processTypeMap = this.objectTypeNameMap_[pid];
+ if (processTypeMap === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Missing mapping from object type IDs to names.'
+ });
+ }
+ importer = new LegacyHeapDumpTraceEventImporter(this.model_,
+ processMemoryDump, processTypeMap, idPrefix, dumpId, dumps.heaps);
+ } else if (dumps.heaps_v2) {
+ const data = dumps.heaps_v2;
+ this.heapProfileExpander = this.heapProfileExpander.expandData(data);
+ // TODO(hjd): Unify how we are reading & inflating stack frame data.
+ this.addNewStackFramesFromExpander_(this.heapProfileExpander, idPrefix);
+ importer = new HeapDumpTraceEventImporter(this.heapProfileExpander,
+ this.model_.stackFrames, processMemoryDump, idPrefix, this.model_);
+ }
+
+ if (!importer) return;
+
+ const heapDumps = importer.parse();
+ if (!heapDumps) return;
+
+ if (processMemoryDump.heapDumps !== undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Heap dumps provided multiple times for' +
+ ' process memory dump for PID=' + pid +
+ ' and dump ID=' + dumpId + '.'
+ });
+ return;
+ }
+
+ if (Object.keys(heapDumps).length > 0) {
+ processMemoryDump.heapDumps = heapDumps;
+ }
+ },
+
+ addNewStackFramesFromExpander_(expander, idPrefix) {
+ const nodeMap = expander.getNewMap('nodes');
+ const newStackFrames = {};
+ for (const [id, stackFrame] of nodeMap.entries()) {
+ if (!this.model_.stackFrames[idPrefix + id]) {
+ newStackFrames[id] = {
+ id,
+ name: expander.getString(stackFrame.name_sid),
+ };
+ if (stackFrame.parent) newStackFrames[id].parent = stackFrame.parent;
+ }
+ }
+ this.importStackFrames_(newStackFrames, idPrefix);
+ },
+
+ parseMemoryDumpLevelOfDetail_(levelsOfDetail, dumps, pid,
+ dumpId) {
+ const rawLevelOfDetail = dumps.level_of_detail;
+ let level;
+ switch (rawLevelOfDetail) {
+ case 'background':
+ level = BACKGROUND;
+ break;
+ case 'light':
+ level = LIGHT;
+ break;
+ case 'detailed':
+ level = DETAILED;
+ break;
+ case undefined:
+ level = undefined;
+ break;
+ default:
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'unknown raw level of detail \'' + rawLevelOfDetail +
+ '\' of process memory dump for PID=' + pid +
+ ' and dump ID=' + dumpId + '.'
+ });
+ return;
+ }
+
+ if (!this.updateMemoryDumpLevelOfDetail_(
+ levelsOfDetail, 'process', level)) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'diffent levels of detail provided for process memory' +
+ ' dump for PID=' + pid + ' (dump ID=' + dumpId + ').'
+ });
+ }
+ },
+
+ updateMemoryDumpLevelOfDetail_(levelsOfDetail, scope, level) {
+ // If all process memory dump events have the same level of detail (for
+ // the particular 'process' or 'global' scope), return true.
+ if (!(scope in levelsOfDetail) || level === levelsOfDetail[scope]) {
+ levelsOfDetail[scope] = level;
+ return true;
+ }
+
+ // If the process memory dump events have different levels of detail (for
+ // the particular 'process' or 'global' scope), use the highest level and
+ // return false.
+ if (MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER.indexOf(level) >
+ MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER.indexOf(levelsOfDetail[scope])) {
+ levelsOfDetail[scope] = level;
+ }
+ return false;
+ },
+
+ parseMemoryDumpAllocatorDumps_(processMemoryDump,
+ globalMemoryDump, processMemoryAllocatorDumpsByFullName,
+ globalMemoryAllocatorDumpsByFullName, allMemoryAllocatorDumpsByGuid,
+ dumps, pid, dumpId) {
+ const rawAllocatorDumps = dumps.allocators;
+ if (rawAllocatorDumps === undefined) return;
+
+ // Construct the MemoryAllocatorDump objects without parent links
+ // and add them to the processMemoryAllocatorDumpsByName and
+ // globalMemoryAllocatorDumpsByName indices appropriately.
+ for (let fullName in rawAllocatorDumps) {
+ const rawAllocatorDump = rawAllocatorDumps[fullName];
+
+ // Every memory allocator dump should have a GUID. If not, then
+ // it cannot be associated with any edges.
+ const guid = rawAllocatorDump.guid;
+ if (guid === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Memory allocator dump ' + fullName + ' for PID=' + pid +
+ ' and dump ID=' + dumpId + ' does not have a GUID.'
+ });
+ }
+
+ // A memory allocator dump can have optional flags.
+ const flags = rawAllocatorDump.flags || 0;
+ const isWeakDump = !!(flags & WEAK_MEMORY_ALLOCATOR_DUMP_FLAG);
+
+ // Determine if this is a global memory allocator dump (check if
+ // it's prefixed with 'global/').
+ let containerMemoryDump;
+ let dstIndex;
+ if (fullName.startsWith(GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX)) {
+ // Global memory allocator dump.
+ fullName = fullName.substring(
+ GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX.length);
+ containerMemoryDump = globalMemoryDump;
+ dstIndex = globalMemoryAllocatorDumpsByFullName;
+ } else {
+ // Process memory allocator dump.
+ containerMemoryDump = processMemoryDump;
+ dstIndex = processMemoryAllocatorDumpsByFullName;
+ }
+
+ // Construct or retrieve a memory allocator dump with the provided
+ // GUID.
+ let allocatorDump = allMemoryAllocatorDumpsByGuid[guid];
+ if (allocatorDump === undefined) {
+ if (fullName in dstIndex) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Multiple GUIDs provided for' +
+ ' memory allocator dump ' + fullName + ': ' +
+ dstIndex[fullName].guid + ', ' + guid + ' (ignored) for' +
+ ' PID=' + pid + ' and dump ID=' + dumpId + '.'
+ });
+ continue;
+ }
+ allocatorDump = new tr.model.MemoryAllocatorDump(
+ containerMemoryDump, fullName, guid);
+ allocatorDump.weak = isWeakDump;
+ dstIndex[fullName] = allocatorDump;
+ if (guid !== undefined) {
+ allMemoryAllocatorDumpsByGuid[guid] = allocatorDump;
+ }
+ } else {
+ // A memory allocator dump with this GUID has already been
+ // dumped (so we will only add new attributes). Check that it
+ // belonged to the same process or was also global.
+ if (allocatorDump.containerMemoryDump !== containerMemoryDump) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Memory allocator dump ' + fullName +
+ ' (GUID=' + guid + ') for PID=' + pid + ' and dump ID=' +
+ dumpId + ' dumped in different contexts.'
+ });
+ continue;
+ }
+ // Check that the names of the memory allocator dumps match.
+ if (allocatorDump.fullName !== fullName) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Memory allocator dump with GUID=' + guid + ' for PID=' +
+ pid + ' and dump ID=' + dumpId + ' has multiple names: ' +
+ allocatorDump.fullName + ', ' + fullName + ' (ignored).'
+ });
+ continue;
+ }
+ if (!isWeakDump) {
+ // A MemoryAllocatorDump is non-weak if at least one process dumped
+ // it without WEAK_MEMORY_ALLOCATOR_DUMP_FLAG.
+ allocatorDump.weak = false;
+ }
+ }
+
+ // Add all new attributes to the memory allocator dump.
+ let attributes = rawAllocatorDump.attrs;
+ if (attributes === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Memory allocator dump ' + fullName + ' (GUID=' + guid +
+ ') for PID=' + pid + ' and dump ID=' + dumpId +
+ ' does not have attributes.'
+ });
+ attributes = {};
+ }
+
+ for (const attrName in attributes) {
+ const attrArgs = attributes[attrName];
+ const attrType = attrArgs.type;
+ const attrValue = attrArgs.value;
+
+ switch (attrType) {
+ case 'scalar': {
+ if (attrName in allocatorDump.numerics) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Multiple values provided for scalar attribute ' +
+ attrName + ' of memory allocator dump ' + fullName +
+ ' (GUID=' + guid + ') for PID=' + pid + ' and dump ID=' +
+ dumpId + '.'
+ });
+ break;
+ }
+ const unit = attrArgs.units === 'bytes' ?
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter :
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+ const value = parseInt(attrValue, 16);
+ allocatorDump.addNumeric(attrName,
+ new tr.b.Scalar(unit, value));
+ break;
+ }
+
+ case 'string':
+ if (attrName in allocatorDump.diagnostics) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Multiple values provided for string attribute ' +
+ attrName + ' of memory allocator dump ' + fullName +
+ ' (GUID=' + guid + ') for PID=' + pid + ' and dump ID=' +
+ dumpId + '.'
+ });
+ break;
+ }
+ allocatorDump.addDiagnostic(attrName, attrValue);
+ break;
+
+ default:
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Unknown type provided for attribute ' + attrName +
+ ' of memory allocator dump ' + fullName + ' (GUID=' + guid +
+ ') for PID=' + pid + ' and dump ID=' + dumpId + ': ' +
+ attrType
+ });
+ break;
+ }
+ }
+ }
+ },
+
+ inferMemoryAllocatorDumpTree_(memoryAllocatorDumpsByFullName) {
+ const rootAllocatorDumps = [];
+
+ const fullNames = Object.keys(memoryAllocatorDumpsByFullName);
+ fullNames.sort();
+ for (let i = 0; i < fullNames.length; i++) {
+ let fullName = fullNames[i];
+ let allocatorDump = memoryAllocatorDumpsByFullName[fullName];
+
+ // This is a loop because we might need to build implicit
+ // ancestors in case they were not present in the trace.
+ while (true) {
+ const lastSlashIndex = fullName.lastIndexOf('/');
+ if (lastSlashIndex === -1) {
+ // If the dump is a root, add it to the top-level
+ // rootAllocatorDumps list.
+ rootAllocatorDumps.push(allocatorDump);
+ break;
+ }
+
+ // If the dump is not a root, find its parent.
+ const parentFullName = fullName.substring(0, lastSlashIndex);
+ let parentAllocatorDump =
+ memoryAllocatorDumpsByFullName[parentFullName];
+
+ // If the parent dump does not exist yet, we build an implicit
+ // one and continue up the ancestor chain.
+ let parentAlreadyExisted = true;
+ if (parentAllocatorDump === undefined) {
+ parentAlreadyExisted = false;
+ parentAllocatorDump = new tr.model.MemoryAllocatorDump(
+ allocatorDump.containerMemoryDump, parentFullName);
+ if (allocatorDump.weak !== false) {
+ // If we are inferring a parent dump (e.g. 'root/parent') of a
+ // current dump (e.g. 'root/parent/current') which is weak (or
+ // was also inferred and we don't know yet whether it's weak or
+ // not), then we clear the weak flag on the parent dump because
+ // we don't know yet whether it should be weak or non-weak:
+ //
+ // * We can't mark the parent as non-weak straightaway because
+ // the parent might have no non-weak descendants (in which
+ // case we want the inferred parent to be weak, so that it
+ // would be later removed like the current dump).
+ // * We can't mark the parent as weak immediately either. If we
+ // did and later encounter a non-weak child of the parent
+ // (e.g. 'root/parent/another_child'), then we couldn't
+ // retroactively mark the inferred parent dump as non-weak
+ // because we couldn't tell whether the parent dump was
+ // dumped in the trace as weak (in which case it should stay
+ // weak and be subsequently removed) or whether it was
+ // inferred as weak (in which case it should be changed to
+ // non-weak).
+ //
+ // Therefore, we defer marking the inferred parent as
+ // weak/non-weak. If an inferred parent dump does not have any
+ // non-weak child, it will be marked as weak at the end of this
+ // method.
+ //
+ // Note that this should not be confused with the recursive
+ // propagation of the weak flag from parent dumps to their
+ // children and from owned dumps to their owners, which is
+ // performed in GlobalMemoryDump.prototype.removeWeakDumps().
+ parentAllocatorDump.weak = undefined;
+ }
+ memoryAllocatorDumpsByFullName[parentFullName] =
+ parentAllocatorDump;
+ }
+
+ // Setup the parent <-> children relationships
+ allocatorDump.parent = parentAllocatorDump;
+ parentAllocatorDump.children.push(allocatorDump);
+
+ // If the parent already existed, then its ancestors were/will be
+ // constructed in another iteration of the forEach loop.
+ if (parentAlreadyExisted) {
+ if (!allocatorDump.weak) {
+ // If the current dump is non-weak, then we must ensure that all
+ // its inferred ancestors are also non-weak.
+ while (parentAllocatorDump !== undefined &&
+ parentAllocatorDump.weak === undefined) {
+ parentAllocatorDump.weak = false;
+ parentAllocatorDump = parentAllocatorDump.parent;
+ }
+ }
+ break;
+ }
+
+ fullName = parentFullName;
+ allocatorDump = parentAllocatorDump;
+ }
+ }
+
+ // All inferred ancestor dumps that have a non-weak child have already
+ // been marked as non-weak. We now mark the rest as weak.
+ for (const fullName in memoryAllocatorDumpsByFullName) {
+ const allocatorDump = memoryAllocatorDumpsByFullName[fullName];
+ if (allocatorDump.weak === undefined) {
+ allocatorDump.weak = true;
+ }
+ }
+
+ return rootAllocatorDumps;
+ },
+
+ parseMemoryDumpAllocatorEdges_(allMemoryAllocatorDumpsByGuid,
+ dumpIdEvents, dumpId) {
+ for (const pid in dumpIdEvents) {
+ const processEvents = dumpIdEvents[pid];
+
+ for (let i = 0; i < processEvents.length; i++) {
+ const processEvent = processEvents[i];
+
+ const dumps = processEvent.args.dumps;
+ if (dumps === undefined) continue;
+
+ const rawEdges = dumps.allocators_graph;
+ if (rawEdges === undefined) continue;
+
+ for (let j = 0; j < rawEdges.length; j++) {
+ const rawEdge = rawEdges[j];
+
+ const sourceGuid = rawEdge.source;
+ const sourceDump = allMemoryAllocatorDumpsByGuid[sourceGuid];
+ if (sourceDump === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Edge for PID=' + pid + ' and dump ID=' + dumpId +
+ ' is missing source memory allocator dump (GUID=' +
+ sourceGuid + ').'
+ });
+ continue;
+ }
+
+ const targetGuid = rawEdge.target;
+ const targetDump = allMemoryAllocatorDumpsByGuid[targetGuid];
+ if (targetDump === undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Edge for PID=' + pid + ' and dump ID=' + dumpId +
+ ' is missing target memory allocator dump (GUID=' +
+ targetGuid + ').'
+ });
+ continue;
+ }
+
+ const importance = rawEdge.importance;
+ const edge = new tr.model.MemoryAllocatorDumpLink(
+ sourceDump, targetDump, importance);
+
+ switch (rawEdge.type) {
+ case 'ownership':
+ if (sourceDump.owns !== undefined) {
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Memory allocator dump ' + sourceDump.fullName +
+ ' (GUID=' + sourceGuid + ') already owns a memory' +
+ ' allocator dump (' +
+ sourceDump.owns.target.fullName + ').'
+ });
+ } else {
+ sourceDump.owns = edge;
+ targetDump.ownedBy.push(edge);
+ }
+ break;
+
+ case 'retention':
+ sourceDump.retains.push(edge);
+ targetDump.retainedBy.push(edge);
+ break;
+
+ default:
+ this.model_.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Invalid edge type: ' + rawEdge.type +
+ ' (PID=' + pid + ', dump ID=' + dumpId +
+ ', source=' + sourceGuid + ', target=' + targetGuid +
+ ', importance=' + importance + ').'
+ });
+ }
+ }
+ }
+ }
+ },
+
+ /**
+ * Converts |ts| (in microseconds) to a timestamp in the model clock domain
+ * (in milliseconds).
+ */
+ toModelTimeFromUs_(ts) {
+ if (!this.toModelTime_) {
+ this.toModelTime_ =
+ this.model_.clockSyncManager.getModelTimeTransformer(
+ this.clockDomainId_);
+ }
+
+ return this.toModelTime_(tr.b.Unit.timestampFromUs(ts));
+ },
+
+ /**
+ * Converts |ts| (in microseconds) to a timestamp in the model clock domain
+ * (in milliseconds). If |ts| is undefined, undefined is returned.
+ */
+ maybeToModelTimeFromUs_(ts) {
+ if (ts === undefined) {
+ return undefined;
+ }
+
+ return this.toModelTimeFromUs_(ts);
+ }
+ };
+
+ tr.importer.Importer.register(TraceEventImporter);
+
+ return {
+ TraceEventImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_perf_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_perf_test.html
new file mode 100644
index 00000000000..1c25c83fb57
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_perf_test.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const eventStrings = {};
+
+ // @const
+ const N_ITERATIONS = 200;
+
+ // @const
+ const TEST_NAMES = [
+ 'simple_trace',
+ 'flow',
+ ];
+ // @const
+ const TEST_FILES_PATHS = [
+ '/test_data/simple_trace.json',
+ '/test_data/flow.json',
+ ];
+
+ function stringToStream(str) {
+ const buffer = new ArrayBuffer(str.length);
+ const bufferView = new Uint8Array(buffer);
+ for (let i = 0; i < bufferView.length; i++) {
+ bufferView[i] = str.charCodeAt(i);
+ }
+ const stream = new tr.b.InMemoryTraceStream(bufferView, false);
+ return stream;
+ }
+
+ function getEvents(url, asStream) {
+ if (url in eventStrings && asStream in eventStrings[url]) {
+ return eventStrings[url][asStream];
+ }
+ if (!(url in eventStrings)) {
+ eventStrings[url] = {};
+ }
+ // TODO(ehmaldonado): See catapult:#3845.
+ // tr.b.getSync does not return a trace stream in browser mode, so we
+ // convert to stream manually.
+ eventStrings[url][asStream] = tr.b.getSync(url);
+ if (asStream) {
+ eventStrings[url][asStream] = stringToStream(eventStrings[url][asStream]);
+ }
+ return eventStrings[url][asStream];
+ }
+
+ function timedPerfTestWithEvents(name, testFn, initialOptions, asStream) {
+ if (initialOptions.setUp) {
+ throw new Error(
+ 'Per-test setUp not supported. Trivial to fix if needed.');
+ }
+
+ const options = {};
+ for (const k in initialOptions) {
+ options[k] = initialOptions[k];
+ }
+ options.setUp = function() {
+ TEST_FILES_PATHS.forEach(
+ function warmup(url) {
+ getEvents(url, asStream);
+ });
+ };
+ timedPerfTest(name, testFn, options);
+ }
+
+ for (let i = 0; i < TEST_NAMES.length; ++i) {
+ const testName = TEST_NAMES[i];
+ const testFilePath = TEST_FILES_PATHS[i];
+
+ // Import trace as a string.
+ timedPerfTestWithEvents(testName + '_string', function() {
+ const events = getEvents(testFilePath, false);
+ const m = tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false,
+ pruneContainers: false
+ });
+ }, {iterations: N_ITERATIONS}, false);
+
+ // Import trace as a stream.
+ timedPerfTestWithEvents(testName + '_stream', function() {
+ const events = getEvents(testFilePath, true);
+ const m = tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false,
+ pruneContainers: false
+ });
+ }, {iterations: N_ITERATIONS}, true);
+ }
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html
new file mode 100644
index 00000000000..c0a0b6edec3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/trace_event_importer_test.html
@@ -0,0 +1,6593 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/in_memory_trace_stream.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/time_display_modes.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/battor_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/extras/measure/measure.html">
+<link rel="import" href="/tracing/extras/v8_config.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/model/scoped_id.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const findSliceNamed = tr.c.TestUtils.findSliceNamed;
+ const ClockDomainId = tr.model.ClockDomainId;
+ const ColorScheme = tr.b.ColorScheme;
+ const MeasureAsyncSlice = tr.e.measure.MeasureAsyncSlice;
+ const ScopedId = tr.model.ScopedId;
+ const VMRegion = tr.model.VMRegion;
+ const Scalar = tr.b.Scalar;
+ const unitlessNumber_smallerIsBetter =
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+ const checkDumpNumericsAndDiagnostics =
+ tr.model.MemoryDumpTestUtils.checkDumpNumericsAndDiagnostics;
+ const checkVMRegions = tr.model.MemoryDumpTestUtils.checkVMRegions;
+ const LIGHT = tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;
+ const DETAILED = tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;
+
+ function makeModel(events, opt_shift, opt_prune) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: opt_shift,
+ pruneEmptyContainers: opt_prune
+ });
+ }
+
+ function checkHeapEntry(entry, expectedDump, expectedSize, expectedTitles,
+ expectedObjectTypeName, expectedCount) {
+ assert.strictEqual(entry.heapDump, expectedDump);
+ assert.strictEqual(entry.size, expectedSize);
+ assert.strictEqual(entry.objectTypeName, expectedObjectTypeName);
+ assert.strictEqual(entry.count, expectedCount);
+ if (expectedTitles === undefined) {
+ assert.isUndefined(entry.leafStackFrame);
+ } else {
+ assert.deepEqual(
+ entry.leafStackFrame.getUserFriendlyStackTrace(), expectedTitles);
+ }
+ }
+
+ function getFrame(heapEntry, distance) {
+ let frame = heapEntry.leafStackFrame;
+ for (; distance > 0; distance--) {
+ frame = frame.parentFrame;
+ }
+ return frame;
+ }
+
+ function stringToUint8Array(str) {
+ const buffer = new ArrayBuffer(str.length);
+ const bufferView = new Uint8Array(buffer);
+ for (let i = 0; i < bufferView.length; i++) {
+ bufferView[i] = str.charCodeAt(i);
+ }
+ return bufferView;
+ }
+
+ function checkParsedAndStreamInput(events, checkFn, opt_shift, opt_prune) {
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array(JSON.stringify(events)), false);
+
+ checkFn(makeModel(events, opt_shift, opt_prune));
+ checkFn(makeModel(stream, opt_shift, opt_prune));
+ }
+
+ test('canImportEmpty', function() {
+ assert.isFalse(tr.e.importer.TraceEventImporter.canImport([]));
+ assert.isFalse(tr.e.importer.TraceEventImporter.canImport(''));
+ });
+
+ test('basicSingleThreadNonnestedParsing', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[52];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.length, 2);
+ assert.strictEqual(t.tid, 53);
+ let slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 0);
+ assert.closeTo((560 - 520) / 1000, slice.duration, 1e-5);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ slice = t.sliceGroup.slices[1];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.category, 'bar');
+ assert.closeTo((629 - 520) / 1000, slice.start, 1e-5);
+ assert.closeTo((631 - 629) / 1000, slice.duration, 1e-5);
+ assert.strictEqual(slice.subSlices.length, 0);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'b', args: {}, pid: 52, ts: 629, cat: 'bar', tid: 53, ph: 'B'},
+ {name: 'b', args: {}, pid: 52, ts: 631, cat: 'bar', tid: 53, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nonMonotonicInstantEvents', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[52];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 3);
+ const t1 = p.threads[1];
+ assert.isDefined(t1);
+ assert.strictEqual(t1.sliceGroup.length, 3);
+
+ let slice = t1.sliceGroup.slices[1];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 2);
+ assert.strictEqual(slice.duration, 0);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ slice = t1.sliceGroup.slices[2];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 3);
+ assert.strictEqual(slice.duration, 5);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ const t2 = p.threads[2];
+ assert.isDefined(t2);
+ assert.strictEqual(t2.sliceGroup.length, 3);
+
+ slice = t2.sliceGroup.slices[1];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.start, 2);
+ assert.strictEqual(slice.duration, 0);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ slice = t2.sliceGroup.slices[2];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 3);
+ assert.strictEqual(slice.duration, 5);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ const t3 = p.threads[3];
+ assert.isDefined(t3);
+ assert.strictEqual(t3.sliceGroup.length, 3);
+
+ slice = t3.sliceGroup.slices[1];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.start, 2);
+ assert.strictEqual(slice.duration, 0);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ slice = t3.sliceGroup.slices[2];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 3);
+ assert.strictEqual(slice.duration, 5);
+ assert.strictEqual(slice.subSlices.length, 0);
+ }
+
+ const events = [
+ {name: 'x', args: {}, pid: 52, ts: 0, cat: 'foo', tid: 1, ph: 'R'},
+ {name: 'a', args: {}, pid: 52, ts: 3000, cat: 'foo', tid: 1, ph: 'X',
+ dur: 5000},
+ {name: 'b', args: {}, pid: 52, ts: 2000, cat: 'foo', tid: 1, ph: 'R'},
+
+ {name: 'x', args: {}, pid: 52, ts: 0, cat: 'foo', tid: 2, ph: 'R'},
+ {name: 'b', args: {}, pid: 52, ts: 2000, cat: 'foo', tid: 2, ph: 'R'},
+ {name: 'a', args: {}, pid: 52, ts: 3000, cat: 'foo', tid: 2, ph: 'X',
+ dur: 5000},
+
+ {name: 'x', args: {}, pid: 52, ts: 0, cat: 'foo', tid: 3, ph: 'R'},
+ {name: 'a', args: {}, pid: 52, ts: 3000, cat: 'foo', tid: 3, ph: 'B'},
+ {name: 'b', args: {}, pid: 52, ts: 2000, cat: 'foo', tid: 3, ph: 'R'},
+ {name: 'a', args: {}, pid: 52, ts: 8000, cat: 'foo', tid: 3, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('basicSingleThreadNonnestedParsingWithCpuDuration', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[52];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.length, 2);
+ assert.strictEqual(t.tid, 53);
+ let slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 0);
+ assert.closeTo((560 - 520) / 1000, slice.duration, 1e-5);
+ assert.closeTo((259 - 221) / 1000, slice.cpuDuration, 1e-5);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ slice = t.sliceGroup.slices[1];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.category, 'bar');
+ assert.closeTo((629 - 520) / 1000, slice.start, 1e-5);
+ assert.closeTo((631 - 629) / 1000, slice.duration, 1e-5);
+ assert.closeTo((331 - 329) / 1000, slice.cpuDuration, 1e-5);
+ assert.strictEqual(slice.subSlices.length, 0);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B', tts: 221}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E', tts: 259}, // @suppress longLineCheck
+ {name: 'b', args: {}, pid: 52, ts: 629, cat: 'bar', tid: 53, ph: 'B', tts: 329}, // @suppress longLineCheck
+ {name: 'b', args: {}, pid: 52, ts: 631, cat: 'bar', tid: 53, ph: 'E', tts: 331} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('argumentDupeCreatesNonFailingImportError', function() {
+ function checkModel(m) {
+ const t = m.processes[1].threads[1];
+ const sA = findSliceNamed(t.sliceGroup, 'a');
+
+ assert.strictEqual(sA.args.x, 2);
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(1, m.importWarnings.length);
+ }
+
+ const events = [
+ {name: 'a',
+ args: {'x': 1},
+ pid: 1,
+ ts: 520,
+ cat: 'foo',
+ tid: 1,
+ ph: 'B'},
+ {name: 'a',
+ args: {'x': 2},
+ pid: 1,
+ ts: 560,
+ cat: 'foo',
+ tid: 1,
+ ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMissingArgs', function() {
+ const events = [
+ {name: 'a', pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'b', pid: 52, ts: 629, cat: 'bar', tid: 53, ph: 'I'}
+ ];
+
+ // This should not throw an exception.
+ checkParsedAndStreamInput(events, m => {});
+ });
+
+ test('importDoesNotChokeOnNulls', function() {
+ const events = [
+ {name: 'a', args: { foo: null }, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'}, // @suppress longLineCheck
+ {name: 'a', pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+
+ // This should not throw an exception.
+ checkParsedAndStreamInput(events, m => {});
+ });
+
+ test('categoryBeginEndMismatchPrefersBegin', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[52];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.length, 1);
+ assert.strictEqual(t.tid, 53);
+ const slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'bar', tid: 53, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('beginEndNameMismatch', function() {
+ function checkModel(m) {
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(m.importWarnings.length, 1);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'b', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestedParsing', function() {
+ function checkModel(m) {
+ const t = m.processes[1].threads[1];
+
+ const sA = findSliceNamed(t.sliceGroup, 'a');
+ const sB = findSliceNamed(t.sliceGroup, 'b');
+
+ assert.strictEqual(sA.title, 'a');
+ assert.strictEqual(sA.category, 'foo');
+ assert.strictEqual(sA.start, 0.001);
+ assert.strictEqual(sA.duration, 0.003);
+ assert.strictEqual(sA.selfTime, 0.002);
+ assert.strictEqual(sA.cpuSelfTime, 0.001);
+
+ assert.strictEqual(sB.title, 'b');
+ assert.strictEqual(sB.category, 'bar');
+ assert.strictEqual(sB.start, 0.002);
+ assert.strictEqual(sB.duration, 0.001);
+
+ assert.strictEqual(1, sA.subSlices.length);
+ assert.strictEqual(sB, sA.subSlices[0]);
+ assert.strictEqual(sA, sB.parentSlice);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, tts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 2, tts: 2, cat: 'bar', tid: 1, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 3, tts: 3, cat: 'bar', tid: 1, ph: 'E'},
+ {name: 'a', args: {}, pid: 1, ts: 4, tts: 3, cat: 'foo', tid: 1, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('nestedParsingWithTwoSubSlices', function() {
+ function checkModel(m) {
+ const t = m.processes[1].threads[1];
+
+ const sA = findSliceNamed(t.sliceGroup, 'a');
+ const sB = findSliceNamed(t.sliceGroup, 'b');
+ const sC = findSliceNamed(t.sliceGroup, 'c');
+
+ assert.strictEqual(sA.title, 'a');
+ assert.strictEqual(sA.category, 'foo');
+ assert.strictEqual(sA.start, 0.001);
+ assert.strictEqual(sA.duration, 0.007);
+ assert.strictEqual(sA.selfTime, 0.004);
+ assert.strictEqual(sA.cpuSelfTime, 0.005);
+
+ assert.strictEqual(sB.title, 'b');
+ assert.strictEqual(sB.category, 'bar');
+ assert.strictEqual(sB.start, 0.002);
+ assert.strictEqual(sB.duration, 0.001);
+
+ assert.strictEqual(sC.title, 'c');
+ assert.strictEqual(sC.category, 'baz');
+ assert.strictEqual(sC.start, 0.005);
+ assert.strictEqual(sC.duration, 0.002);
+
+ assert.strictEqual(sA.subSlices.length, 2);
+ assert.strictEqual(sA.subSlices[0], sB);
+ assert.strictEqual(sA.subSlices[1], sC);
+ assert.strictEqual(sB.parentSlice, sA);
+ assert.strictEqual(sC.parentSlice, sA);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, tts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 2, tts: 2, cat: 'bar', tid: 1, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 3, tts: 3, cat: 'bar', tid: 1, ph: 'E'},
+ {name: 'c', args: {}, pid: 1, ts: 5, tts: 5, cat: 'baz', tid: 1, ph: 'B'},
+ {name: 'c', args: {}, pid: 1, ts: 7, tts: 6, cat: 'baz', tid: 1, ph: 'E'},
+ {name: 'a', args: {}, pid: 1, ts: 8, tts: 8, cat: 'foo', tid: 1, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('nestedParsingWithDoubleNesting', function() {
+ function checkModel(m) {
+ const t = m.processes[1].threads[1];
+
+ const sA = findSliceNamed(t.sliceGroup, 'a');
+ const sB = findSliceNamed(t.sliceGroup, 'b');
+ const sC = findSliceNamed(t.sliceGroup, 'c');
+
+ assert.strictEqual(sA.title, 'a');
+ assert.strictEqual(sA.category, 'foo');
+ assert.strictEqual(sA.start, 0.001);
+ assert.strictEqual(sA.duration, 0.007);
+ assert.strictEqual(sA.selfTime, 0.002);
+
+ assert.strictEqual(sB.title, 'b');
+ assert.strictEqual(sB.category, 'bar');
+ assert.strictEqual(sB.start, 0.002);
+ assert.strictEqual(sB.duration, 0.005);
+ assert.strictEqual(sA.selfTime, 0.002);
+
+ assert.strictEqual(sC.title, 'c');
+ assert.strictEqual(sC.category, 'baz');
+ assert.strictEqual(sC.start, 0.003);
+ assert.strictEqual(sC.duration, 0.002);
+
+ assert.strictEqual(sA.subSlices.length, 1);
+ assert.strictEqual(sA.subSlices[0], sB);
+ assert.strictEqual(sB.parentSlice, sA);
+
+ assert.strictEqual(sB.subSlices.length, 1);
+ assert.strictEqual(sB.subSlices[0], sC);
+ assert.strictEqual(sC.parentSlice, sB);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 1, ph: 'B'},
+ {name: 'c', args: {}, pid: 1, ts: 3, cat: 'baz', tid: 1, ph: 'B'},
+ {name: 'c', args: {}, pid: 1, ts: 5, cat: 'baz', tid: 1, ph: 'E'},
+ {name: 'b', args: {}, pid: 1, ts: 7, cat: 'bar', tid: 1, ph: 'E'},
+ {name: 'a', args: {}, pid: 1, ts: 8, cat: 'foo', tid: 1, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+
+ test('autoclosing', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t1 = p.threads[1];
+ const t2 = p.threads[2];
+ assert.isTrue(t1.sliceGroup.slices[0].didNotFinish);
+ assert.strictEqual(t1.sliceGroup.slices[0].end, 0.001);
+ }
+
+ const events = [
+ // Slice that doesn't finish.
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
+
+ // Slice that does finish to give an 'end time' to make autoclosing work.
+ {name: 'b', args: {}, pid: 1, ts: 1, cat: 'bar', tid: 2, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 2, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('autoclosingLoneBegin', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ const slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.isTrue(slice.didNotFinish);
+ assert.strictEqual(slice.start, 0);
+ assert.strictEqual(slice.duration, 0);
+ }
+
+ const events = [
+ // Slice that doesn't finish.
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('autoclosingWithSubTasks', function() {
+ function checkModel(m) {
+ const t = m.processes[1].threads[1];
+
+ const sA = findSliceNamed(t.sliceGroup, 'a');
+ const sB1 = findSliceNamed(t.sliceGroup, 'b1');
+ const sB2 = findSliceNamed(t.sliceGroup, 'b2');
+
+ assert.strictEqual(sA.end, 0.003);
+ assert.strictEqual(sB1.end, 0.003);
+ assert.strictEqual(sB2.end, 0.003);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'b1', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'b1', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'E'},
+ {name: 'b2', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'B'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('autoclosingWithEventsOutsideBounds', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ assert.strictEqual(t.sliceGroup.length, 2);
+
+ const slice = findSliceNamed(t.sliceGroup, 'a');
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 0);
+ assert.strictEqual(slice.duration, 0.003);
+
+ const t2 = p.threads[2];
+ const slice2 = findSliceNamed(t2.sliceGroup, 'c');
+ assert.strictEqual(slice2.title, 'c');
+ assert.strictEqual(slice2.category, 'bar');
+ assert.strictEqual(slice2.start, 0.001);
+ assert.strictEqual(slice2.duration, 0.001);
+
+ assert.strictEqual(m.bounds.min, 0.000);
+ assert.strictEqual(m.bounds.max, 0.003);
+ }
+
+ const events = [
+ // Slice that begins before min and ends after max of the other threads.
+ {name: 'a', args: {}, pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'B'},
+
+ // Slice that does finish to give an 'end time' to establish a basis
+ {name: 'c', args: {}, pid: 1, ts: 1, cat: 'bar', tid: 2, ph: 'B'},
+ {name: 'c', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 2, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestedAutoclosing', function() {
+ function checkModel(m) {
+ const t1 = m.processes[1].threads[1];
+ const t2 = m.processes[1].threads[2];
+
+ const sA1 = findSliceNamed(t1.sliceGroup, 'a1');
+ const sA2 = findSliceNamed(t1.sliceGroup, 'a2');
+ const sB = findSliceNamed(t2.sliceGroup, 'b');
+
+ assert.strictEqual(sA1.end, 0.0015);
+ assert.strictEqual(sA2.end, 0.0015);
+ }
+
+ const events = [
+ // Tasks that don't finish.
+ {name: 'a1', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'a2', args: {}, pid: 1, ts: 1.5, cat: 'foo', tid: 1, ph: 'B'},
+
+ // Slice that does finish to give an 'end time' to make autoclosing work.
+ {name: 'b', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 2, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 2, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('taskColoring', function() {
+ // The test below depends on hashing of 'a' !== 'b'. Fail early if that
+ // assumption is incorrect.
+ assert.notEqual(ColorScheme.getStringHash('a'),
+ ColorScheme.getStringHash('b'));
+
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ const a1 = t.sliceGroup.slices[0];
+ assert.strictEqual(a1.title, 'a');
+ assert.strictEqual(a1.category, 'foo');
+ const b = t.sliceGroup.slices[1];
+ assert.strictEqual(b.title, 'b');
+ assert.strictEqual(b.category, 'bar');
+ assert.notEqual(b.colorId, a1.colorId);
+ const a2 = t.sliceGroup.slices[2];
+ assert.strictEqual(a2.title, 'a');
+ assert.strictEqual(a2.category, 'baz');
+ assert.strictEqual(a1.colorId, a2.colorId);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
+ {name: 'b', args: {}, pid: 1, ts: 3, cat: 'bar', tid: 1, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 4, cat: 'bar', tid: 1, ph: 'E'},
+ {name: 'a', args: {}, pid: 1, ts: 5, cat: 'baz', tid: 1, ph: 'B'},
+ {name: 'a', args: {}, pid: 1, ts: 6, cat: 'baz', tid: 1, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('durationColorArgument', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ assert.strictEqual(t.sliceGroup.slices[0].colorId,
+ ColorScheme.getColorIdForReservedName('thread_state_unknown'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B', cname: 'thread_state_unknown'}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'E', cname: 'thread_state_unknown'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('durationColorEnd', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ assert.strictEqual(t.sliceGroup.slices[0].colorId,
+ ColorScheme.getColorIdForReservedName('thread_state_unknown'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B', cname: 'thread_state_sleeping'}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'E', cname: 'thread_state_unknown'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('completeColorArgument', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ assert.strictEqual(t.sliceGroup.slices[0].colorId,
+ ColorScheme.getColorIdForReservedName('generic_work'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, dur: 1, cat: 'foo', tid: 1, ph: 'X', cname: 'generic_work'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncColorArgument', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ assert.strictEqual(t.asyncSliceGroup.slices[0].colorId,
+ ColorScheme.getColorIdForReservedName('generic_work'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'b', id: 1, cname: 'generic_work'}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'e', id: 1, cname: 'generic_work'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncColorEnd', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ assert.strictEqual(t.asyncSliceGroup.slices[0].colorId,
+ ColorScheme.getColorIdForReservedName('generic_work'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'b', id: 1, cname: 'thread_state_unknown'}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'e', id: 1, cname: 'generic_work'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('instantThreadColorArgument', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ assert.strictEqual(t.sliceGroup.slices[0].colorId,
+ ColorScheme.getColorIdForReservedName('generic_work'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'I', id: 1, cname: 'generic_work'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('instantProcessColorArgument', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ assert.strictEqual(p.instantEvents[0].colorId,
+ ColorScheme.getColorIdForReservedName('generic_work'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'I', id: 1, s: 'p', cname: 'generic_work'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('counterColorArgument', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ assert.strictEqual(p.counters['foo.a[1]'].series[0].color,
+ ColorScheme.getColorIdForReservedName('generic_work'));
+ assert.strictEqual(p.counters['foo.a[1]'].series.length, 1);
+ }
+
+ const events = [
+ {name: 'a', args: {'cats': 10}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'C', id: 1, cname: 'generic_work'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('objectColorArgument', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const i = p.objects.instanceMapsByScopedId_.ptr[1].instances[0];
+ assert.strictEqual(i.colorId,
+ ColorScheme.getColorIdForReservedName('generic_work'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'N', id: 1, cname: 'generic_work'}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'O', id: 1, cname: 'generic_work'}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'D', id: 1, cname: 'generic_work'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('objectColorEnd', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const i = p.objects.instanceMapsByScopedId_.ptr[1].instances[0];
+ assert.strictEqual(i.colorId,
+ ColorScheme.getColorIdForReservedName('generic_work'));
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'N', id: 1, cname: 'thread_state_sleeping'}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'O', id: 1, cname: 'thread_state_unknown'}, // @suppress longLineCheck
+ {name: 'a', args: {}, pid: 1, ts: 3, cat: 'foo', tid: 1, ph: 'D', id: 1, cname: 'generic_work'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('multipleThreadParsing', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[1];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 2);
+
+ // Check thread 1.
+ let t = p.threads[1];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.length, 1);
+ assert.strictEqual(t.tid, 1);
+
+ let slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 0);
+ assert.strictEqual(slice.duration, (2 - 1) / 1000);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ // Check thread 2.
+ t = p.threads[2];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.length, 1);
+ assert.strictEqual(t.tid, 2);
+
+ slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.category, 'bar');
+ assert.strictEqual(slice.start, (3 - 1) / 1000);
+ assert.strictEqual(slice.duration, (4 - 3) / 1000);
+ assert.strictEqual(slice.subSlices.length, 0);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
+ {name: 'b', args: {}, pid: 1, ts: 3, cat: 'bar', tid: 2, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 4, cat: 'bar', tid: 2, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('multiplePidParsing', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 2);
+ let p = m.processes[1];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 1);
+
+ // Check process 1 thread 1.
+ let t = p.threads[1];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.length, 1);
+ assert.strictEqual(t.tid, 1);
+
+ let slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 0);
+ assert.strictEqual(slice.duration, (2 - 1) / 1000);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ // Check process 2 thread 2.
+ p = m.processes[2];
+ assert.isDefined(p);
+ assert.strictEqual(p.numThreads, 1);
+ t = p.threads[2];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.length, 1);
+ assert.strictEqual(t.tid, 2);
+
+ slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.category, 'bar');
+ assert.strictEqual(slice.start, (3 - 1) / 1000);
+ assert.strictEqual(slice.duration, (4 - 3) / 1000);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ // Check getAllThreads.
+ assert.deepEqual(m.getAllThreads(),
+ [m.processes[1].threads[1], m.processes[2].threads[2]]);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'a', args: {}, pid: 1, ts: 2, cat: 'foo', tid: 1, ph: 'E'},
+ {name: 'b', args: {}, pid: 2, ts: 3, cat: 'bar', tid: 2, ph: 'B'},
+ {name: 'b', args: {}, pid: 2, ts: 4, cat: 'bar', tid: 2, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ // Process names.
+ test('processNames', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.processes[1].name, 'SomeProcessName');
+ }
+
+ const events = [
+ {name: 'process_name', args: {name: 'SomeProcessName'},
+ pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'M'},
+ {name: 'process_name', args: {name: 'SomeProcessName'},
+ pid: 2, ts: 0, cat: 'foo', tid: 1, ph: 'M'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ // Process labels.
+ test('processLabels', function() {
+ function checkModel(m) {
+ assert.deepEqual(m.processes[1].labels, ['foo', 'bar', 'baz']);
+ assert.deepEqual(m.processes[2].labels, ['baz']);
+ }
+
+ const events = [
+ {name: 'process_labels', args: {labels: 'foo,bar,bar,foo,baz'},
+ pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'M'},
+ {name: 'process_labels', args: {labels: 'baz'},
+ pid: 2, ts: 0, cat: 'foo', tid: 1, ph: 'M'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ // Process uptime.
+ test('processUptime', function() {
+ const events = [
+ {name: 'process_uptime_seconds', args: {uptime: 10},
+ pid: 1, ts: 0, tid: 1, ph: 'M'},
+ {name: 'process_uptime_seconds', args: {uptime: 20},
+ pid: 2, ts: 0, tid: 1, ph: 'M'}
+ ];
+ const m = makeModel(events);
+ assert.strictEqual(m.processes[1].uptime_seconds, 10);
+ assert.strictEqual(m.processes[2].uptime_seconds, 20);
+ });
+
+ // Process sort index.
+ test('processSortIndex', function() {
+ function checkModel(m) {
+ // By name, p1 is before p2. But, its sort index overrides that.
+ assert.isAbove(m.processes[1].compareTo(m.processes[2]), 0);
+ }
+
+ const events = [
+ {name: 'process_name', args: {name: 'First'},
+ pid: 2, ts: 0, cat: 'foo', tid: 1, ph: 'M'},
+ {name: 'process_name', args: {name: 'Second'},
+ pid: 2, ts: 0, cat: 'foo', tid: 1, ph: 'M'},
+ {name: 'process_sort_index', args: {sort_index: 1},
+ pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'M'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ // Thread names.
+ test('threadNames', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.processes[1].threads[1].name, 'Thread 1');
+ assert.strictEqual(m.processes[2].threads[2].name, 'Thread 2');
+ }
+
+ const events = [
+ {name: 'thread_name', args: {name: 'Thread 1'},
+ pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'M'},
+ {name: 'thread_name', args: {name: 'Thread 2'},
+ pid: 2, ts: 0, cat: 'foo', tid: 2, ph: 'M'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false, false);
+ });
+
+ // Thread sort index.
+ test('threadSortIndex', function() {
+ function checkModel(m) {
+ // By name, t1 is before t2. But, its sort index overrides that.
+ const t1 = m.processes[1].threads[1];
+ const t2 = m.processes[1].threads[2];
+ assert.isAbove(t1.compareTo(t2), 0);
+ }
+
+ const events = [
+ {name: 'thread_name', args: {name: 'Thread 1'},
+ pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'M'},
+ {name: 'thread_name', args: {name: 'Thread 2'},
+ pid: 1, ts: 0, cat: 'foo', tid: 2, ph: 'M'},
+ {name: 'thread_sort_index', args: {sort_index: 1},
+ pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'M'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false, false);
+ });
+
+ // CPU counts.
+ test('cpuCounts', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.kernel.softwareMeasuredCpuCount, 4);
+ assert.strictEqual(m.kernel.bestGuessAtCpuCount, 4);
+ }
+
+ const events = [
+ {name: 'num_cpus', args: {number: 4},
+ pid: 7, ts: 0, cat: 'foo', tid: 0, ph: 'M'},
+ {name: 'num_cpus', args: {number: 4},
+ pid: 14, ts: 0, cat: 'foo', tid: 0, ph: 'M'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('cpuCountsWithSandboxBeingConfused', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.kernel.softwareMeasuredCpuCount, 4);
+ assert.strictEqual(m.kernel.bestGuessAtCpuCount, 4);
+ }
+
+ const events = [
+ {name: 'num_cpus', args: {number: 4},
+ pid: 7, ts: 0, cat: 'foo', tid: 0, ph: 'M'},
+ {name: 'num_cpus', args: {number: 1},
+ pid: 14, ts: 0, cat: 'foo', tid: 0, ph: 'M'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('parsingWhenEndComesFirst', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+ assert.strictEqual(t.sliceGroup.length, 1);
+ assert.strictEqual(t.sliceGroup.slices[0].title, 'a');
+ assert.strictEqual(t.sliceGroup.slices[0].category, 'foo');
+ assert.strictEqual(t.sliceGroup.slices[0].start, 0.004);
+ assert.strictEqual(t.sliceGroup.slices[0].duration, 0.001);
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(m.importWarnings.length, 1);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'E'},
+ {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'a', args: {}, pid: 1, ts: 5, cat: 'foo', tid: 1, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('immediateParsing', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[1];
+
+ assert.strictEqual(t.sliceGroup.length, 3);
+ assert.strictEqual(t.sliceGroup.slices[0].start, 0.001);
+ assert.strictEqual(t.sliceGroup.slices[0].duration, 0.003);
+ assert.strictEqual(t.sliceGroup.slices[1].start, 0.002);
+ assert.strictEqual(t.sliceGroup.slices[1].duration, 0);
+ assert.strictEqual(t.sliceGroup.slices[2].start, 0.004);
+
+ const slice = findSliceNamed(t.sliceGroup, 'a');
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.duration, 0.003);
+
+ const immed = findSliceNamed(t.sliceGroup, 'immediate');
+ assert.strictEqual(immed.title, 'immediate');
+ assert.strictEqual(immed.category, 'bar');
+ assert.strictEqual(immed.start, 0.002);
+ assert.strictEqual(immed.duration, 0);
+
+ const slower = findSliceNamed(t.sliceGroup, 'slower');
+ assert.strictEqual(slower.title, 'slower');
+ assert.strictEqual(slower.category, 'baz');
+ assert.strictEqual(slower.start, 0.004);
+ assert.strictEqual(slower.duration, 0);
+ }
+
+ const events = [
+ // Need to include immediates inside a task so the timeline
+ // recentering/zeroing doesn't clobber their timestamp.
+ {name: 'a', args: {}, pid: 1, ts: 1, cat: 'foo', tid: 1, ph: 'B'},
+ {name: 'immediate', args: {}, pid: 1, ts: 2, cat: 'bar', tid: 1, ph: 'I'},
+ {name: 'slower', args: {}, pid: 1, ts: 4, cat: 'baz', tid: 1, ph: 'i'},
+ {name: 'a', args: {}, pid: 1, ts: 4, cat: 'foo', tid: 1, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('simpleCounter', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const ctr = m.processes[1].counters['foo.ctr'];
+
+ assert.strictEqual(ctr.name, 'ctr');
+ assert.strictEqual(ctr.category, 'foo');
+ assert.strictEqual(ctr.numSamples, 3);
+ assert.strictEqual(ctr.numSeries, 1);
+
+ assert.strictEqual(ctr.series[0].name, 'value');
+ assert.strictEqual(ctr.series[0].color,
+ ColorScheme.getColorIdForGeneralPurposeString('ctr.value'));
+
+ assert.deepEqual(ctr.timestamps, [0, 0.01, 0.02]);
+
+ const samples = [];
+ ctr.series[0].samples.forEach(function(sample) {
+ samples.push(sample.value);
+ });
+ assert.deepEqual(samples, [0, 10, 0]);
+
+ assert.deepEqual(ctr.totals, [0, 10, 0]);
+ assert.strictEqual(ctr.maxTotal, 10);
+ }
+
+ const events = [
+ {name: 'ctr', args: {'value': 0}, pid: 1, ts: 0, cat: 'foo', tid: 1,
+ ph: 'C'},
+ {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
+ ph: 'C'},
+ {name: 'ctr', args: {'value': 0}, pid: 1, ts: 20, cat: 'foo', tid: 1,
+ ph: 'C'}
+
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('instanceCounter', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ let ctr = m.processes[1].counters['foo.ctr[0]'];
+ assert.strictEqual(ctr.name, 'ctr[0]');
+ assert.strictEqual(ctr.category, 'foo');
+ assert.strictEqual(ctr.numSamples, 2);
+ assert.strictEqual(ctr.numSeries, 1);
+
+ assert.deepEqual(ctr.timestamps, [0, 0.01]);
+ let samples = [];
+ ctr.series[0].samples.forEach(function(sample) {
+ samples.push(sample.value);
+ });
+ assert.deepEqual(samples, [0, 10]);
+
+ ctr = m.processes[1].counters['foo.ctr[1]'];
+ assert.strictEqual(ctr.name, 'ctr[1]');
+ assert.strictEqual(ctr.category, 'foo');
+ assert.strictEqual(ctr.numSamples, 3);
+ assert.strictEqual(ctr.numSeries, 1);
+ assert.deepEqual(ctr.timestamps, [0.01, 0.015, 0.02]);
+
+ samples = [];
+ ctr.series[0].samples.forEach(function(sample) {
+ samples.push(sample.value);
+ });
+ assert.deepEqual(samples, [10, 20, 30]);
+
+ ctr = m.processes[1].counters['bar.ctr[2]'];
+ assert.strictEqual(ctr.name, 'ctr[2]');
+ assert.strictEqual(ctr.category, 'bar');
+ assert.strictEqual(ctr.numSamples, 1);
+ assert.strictEqual(ctr.numSeries, 1);
+ assert.deepEqual(ctr.timestamps, [0.025]);
+ samples = [];
+ ctr.series[0].samples.forEach(function(sample) {
+ samples.push(sample.value);
+ });
+ assert.deepEqual(samples, [40]);
+ }
+
+ const events = [
+ {name: 'ctr', args: {'value': 0}, pid: 1, ts: 0, cat: 'foo', tid: 1,
+ ph: 'C', id: 0},
+ {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
+ ph: 'C', id: 0},
+ {name: 'ctr', args: {'value': 10}, pid: 1, ts: 10, cat: 'foo', tid: 1,
+ ph: 'C', id: 1},
+ {name: 'ctr', args: {'value': 20}, pid: 1, ts: 15, cat: 'foo', tid: 1,
+ ph: 'C', id: 1},
+ {name: 'ctr', args: {'value': 30}, pid: 1, ts: 20, cat: 'foo', tid: 1,
+ ph: 'C', id: 1},
+ {name: 'ctr', args: {'value': 40}, pid: 1, ts: 25, cat: 'bar', tid: 1,
+ ph: 'C', id: 2}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('multiCounterUpdateBounds', function() {
+ const ctr = new tr.model.Counter(undefined, 'testBasicCounter',
+ '', 'testBasicCounter');
+ const value1Series = new tr.model.CounterSeries(
+ 'value1', 'testBasicCounter.value1');
+ const value2Series = new tr.model.CounterSeries(
+ 'value2', 'testBasicCounter.value2');
+ ctr.addSeries(value1Series);
+ ctr.addSeries(value2Series);
+
+ value1Series.addCounterSample(0, 0);
+ value1Series.addCounterSample(1, 1);
+ value1Series.addCounterSample(2, 1);
+ value1Series.addCounterSample(3, 2);
+ value1Series.addCounterSample(4, 3);
+ value1Series.addCounterSample(5, 1);
+ value1Series.addCounterSample(6, 3);
+ value1Series.addCounterSample(7, 3.1);
+
+ value2Series.addCounterSample(0, 0);
+ value2Series.addCounterSample(1, 0);
+ value2Series.addCounterSample(2, 1);
+ value2Series.addCounterSample(3, 1.1);
+ value2Series.addCounterSample(4, 0);
+ value2Series.addCounterSample(5, 7);
+ value2Series.addCounterSample(6, 0);
+ value2Series.addCounterSample(7, 0.5);
+
+ ctr.updateBounds();
+
+ assert.strictEqual(ctr.bounds.min, 0);
+ assert.strictEqual(ctr.bounds.max, 7);
+ assert.strictEqual(ctr.maxTotal, 8);
+ assert.deepEqual([0, 0,
+ 1, 1,
+ 1, 2,
+ 2, 3.1,
+ 3, 3,
+ 1, 8,
+ 3, 3,
+ 3.1, 3.6], ctr.totals);
+ });
+
+ test('multiCounter', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const ctr = m.processes[1].counters['foo.ctr'];
+ assert.strictEqual(ctr.name, 'ctr');
+
+ assert.strictEqual(ctr.name, 'ctr');
+ assert.strictEqual(ctr.category, 'foo');
+ assert.strictEqual(ctr.numSamples, 3);
+ assert.strictEqual(ctr.numSeries, 2);
+
+ assert.strictEqual(ctr.series[0].name, 'value1');
+ assert.strictEqual(ctr.series[1].name, 'value2');
+ assert.strictEqual(ctr.series[0].color,
+ ColorScheme.getColorIdForGeneralPurposeString('ctr.value1'));
+ assert.strictEqual(ctr.series[1].color,
+ ColorScheme.getColorIdForGeneralPurposeString('ctr.value2'));
+
+ assert.deepEqual(ctr.timestamps, [0, 0.01, 0.02]);
+ const samples = [];
+ ctr.series[0].samples.forEach(function(sample) {
+ samples.push(sample.value);
+ });
+ assert.deepEqual(samples, [0, 10, 0]);
+
+ const samples1 = [];
+ ctr.series[1].samples.forEach(function(sample) {
+ samples1.push(sample.value);
+ });
+ assert.deepEqual(samples1, [7, 4, 1]);
+ assert.deepEqual([0, 7,
+ 10, 14,
+ 0, 1], ctr.totals);
+ assert.strictEqual(ctr.maxTotal, 14);
+ }
+
+ const events = [
+ {name: 'ctr', args: {'value1': 0, 'value2': 7}, pid: 1, ts: 0, cat: 'foo', tid: 1, ph: 'C'}, // @suppress longLineCheck
+ {name: 'ctr', args: {'value1': 10, 'value2': 4}, pid: 1, ts: 10, cat: 'foo', tid: 1, ph: 'C'}, // @suppress longLineCheck
+ {name: 'ctr', args: {'value1': 0, 'value2': 1 }, pid: 1, ts: 20, cat: 'foo', tid: 1, ph: 'C'} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importObjectInsteadOfArray', function() {
+ const events = { traceEvents: [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ] };
+
+ const m = makeModel(events);
+ assert.strictEqual(m.numProcesses, 1);
+ });
+
+ test('importString', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+
+ const m = makeModel(JSON.stringify(events));
+ assert.strictEqual(m.numProcesses, 1);
+ });
+
+ test('importStringWithLeadingSpaces', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+
+ const m = makeModel(' ' + JSON.stringify(events));
+ assert.strictEqual(m.numProcesses, 1);
+ });
+
+ test('importStringWithTrailingNewLine', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+
+ const m = makeModel(JSON.stringify(events) + '\n');
+ assert.strictEqual(m.numProcesses, 1);
+ });
+
+ test('importStringWithMissingCloseSquareBracket', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+
+ const tmp = JSON.stringify(events);
+ assert.strictEqual(tmp[tmp.length - 1], ']');
+
+ // Drop off the trailing ]
+ const dropped = tmp.substring(0, tmp.length - 1);
+ const m = makeModel(dropped);
+ assert.strictEqual(m.numProcesses, 1);
+ });
+
+ test('importStringWithEndingCommaButMissingCloseSquareBracket', function() {
+ const lines = [
+ '[',
+ '{"name": "a", "args": {}, "pid": 52, "ts": 524, "cat": "foo", "tid": 53, "ph": "B"},', // @suppress longLineCheck
+ '{"name": "a", "args": {}, "pid": 52, "ts": 560, "cat": "foo", "tid": 53, "ph": "E"},' // @suppress longLineCheck
+ ];
+ const text = lines.join('\n');
+
+ const m = makeModel(text);
+ assert.strictEqual(m.numProcesses, 1);
+ assert.strictEqual(m.processes[52].threads[53].sliceGroup.length, 1);
+ });
+
+ test('importStringWithMissingCloseSquareBracketAndNewline', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+
+ const tmp = JSON.stringify(events);
+ assert.strictEqual(tmp[tmp.length - 1], ']');
+
+ // Drop off the trailing ] and add a newline
+ const dropped = tmp.substring(0, tmp.length - 1);
+ const m = makeModel(dropped + '\n');
+ assert.strictEqual(m.numProcesses, 1);
+ });
+
+ test('ImportStringEndingCommaButMissingCloseSquareBracketCRLF', function() {
+ const lines = [
+ '[',
+ '{"name": "a", "args": {}, "pid": 52, "ts": 524, "cat": "foo", "tid": 53, "ph": "B"},', // @suppress longLineCheck
+ '{"name": "a", "args": {}, "pid": 52, "ts": 560, "cat": "foo", "tid": 53, "ph": "E"},' // @suppress longLineCheck
+ ];
+ const text = lines.join('\r\n');
+
+ const m = makeModel(text);
+ assert.strictEqual(m.numProcesses, 1);
+ assert.strictEqual(m.processes[52].threads[53].sliceGroup.length, 1);
+ });
+
+ test('importOldFormat', function() {
+ const lines = [
+ '[',
+ '{"cat":"a","pid":9,"tid":8,"ts":194,"ph":"E","name":"I","args":{}},',
+ '{"cat":"b","pid":9,"tid":8,"ts":194,"ph":"B","name":"I","args":{}}',
+ ']'
+ ];
+ const text = lines.join('\n');
+ const m = makeModel(text);
+ assert.strictEqual(m.numProcesses, 1);
+ assert.strictEqual(m.processes[9].threads[8].sliceGroup.length, 1);
+ });
+
+ test('startFinishOneSliceOneThread', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ assert.strictEqual(t.asyncSliceGroup.slices[0].title, 'a');
+ assert.strictEqual(t.asyncSliceGroup.slices[0].category, 'cat');
+ assert.isTrue(t.asyncSliceGroup.slices[0].isTopLevel);
+ assert.strictEqual(t.asyncSliceGroup.slices[0].id, ':ptr:72');
+ assert.strictEqual(t.asyncSliceGroup.slices[0].args.foo, 'bar');
+ assert.strictEqual(t.asyncSliceGroup.slices[0].start, 0);
+ assert.closeTo(
+ (60 - 24) / 1000, t.asyncSliceGroup.slices[0].duration, 1e-5);
+ assert.strictEqual(t.asyncSliceGroup.slices[0].startThread, t);
+ assert.strictEqual(t.asyncSliceGroup.slices[0].endThread, t);
+ }
+
+ const events = [
+ // Time is intentionally out of order.
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'cat', tid: 53,
+ ph: 'F', id: 72},
+ {name: 'a', pid: 52, ts: 524, cat: 'cat', tid: 53,
+ ph: 'S', id: 72, args: {'foo': 'bar'}}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('endArgsAddedToSlice', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[52];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.length, 1);
+ assert.strictEqual(t.tid, 53);
+ const slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 0);
+ assert.strictEqual(slice.subSlices.length, 0);
+ assert.strictEqual(slice.args.x, 1);
+ assert.strictEqual(slice.args.y, 2);
+ }
+
+ const events = [
+ {name: 'a', args: {x: 1}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('endArgOverrwritesOriginalArgValueIfDuplicated', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[52];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ const slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.category, 'foo');
+ assert.strictEqual(slice.start, 0);
+ assert.strictEqual(slice.subSlices.length, 0);
+ assert.strictEqual(slice.args.z, 4);
+ }
+
+ const events = [
+ {name: 'b', args: {z: 3}, pid: 52, ts: 629, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'b', args: {z: 4}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncEndArgsAddedToSlice', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'c');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.strictEqual(parentSlice.args.x, 1);
+ assert.strictEqual(parentSlice.args.y, 2);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 0);
+ }
+
+ const events = [
+ // Time is intentionally out of order.
+ {name: 'c', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'F', id: 72},
+ {name: 'c', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'S', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncEndArgOverwritesOriginalArgValueIfDuplicated', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'd');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.strictEqual(parentSlice.args.z, 4);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 0);
+ }
+
+ const events = [
+ // Time is intentionally out of order.
+ {name: 'd', args: {z: 4}, pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'F', id: 72},
+ {name: 'd', args: {z: 3}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'S', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncStepsInOneThread', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.strictEqual(parentSlice.start, 0);
+ assert.strictEqual(parentSlice.args.x, 1);
+ assert.isUndefined(parentSlice.args.y);
+ assert.strictEqual(parentSlice.args.z, 3);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 1);
+
+ const subSlice = parentSlice.subSlices[0];
+ assert.strictEqual(subSlice.title, 's1');
+ assert.strictEqual(subSlice.category, 'foo');
+ assert.isFalse(subSlice.isTopLevel);
+ assert.closeTo((548 - 524) / 1000, subSlice.start, 1e-5);
+ assert.closeTo((560 - 548) / 1000, subSlice.duration, 1e-5);
+ assert.isUndefined(subSlice.args.x);
+ assert.strictEqual(subSlice.args.y, 2);
+ assert.isUndefined(subSlice.args.z);
+ }
+
+ const events = [
+ // Time is intentionally out of order.
+ {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'F', id: 72}, // @suppress longLineCheck
+ {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo', tid: 53, ph: 'T', id: 72}, // @suppress longLineCheck
+ {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'S', id: 72} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncStepsMissingStart', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isUndefined(t);
+ }
+
+ const events = [
+ // Time is intentionally out of order.
+ {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'F', id: 72},
+ {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo',
+ tid: 53, ph: 'T', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('autoClosingAsyncStepsMissingFinish', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.strictEqual(parentSlice.start, 0);
+ assert.strictEqual(parentSlice.duration, 2);
+ assert.isTrue(parentSlice.didNotFinish);
+ assert.isDefined(parentSlice.error);
+ assert.isUndefined(parentSlice.args.y);
+ assert.strictEqual(parentSlice.args.z, 3);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 1);
+ const subSlice = parentSlice.subSlices[0];
+ assert.strictEqual(subSlice.title, 's1');
+ assert.strictEqual(subSlice.category, 'foo');
+ assert.isFalse(subSlice.isTopLevel);
+ assert.strictEqual(subSlice.start, 0);
+ assert.strictEqual(subSlice.duration, 2);
+ assert.isUndefined(subSlice.args.x);
+ assert.strictEqual(subSlice.args.y, 2);
+ assert.isUndefined(subSlice.args.z);
+ assert.isTrue(subSlice.didNotFinish);
+ assert.isDefined(subSlice.error);
+ }
+
+ const events = [
+ {name: 'a', args: {z: 3}, pid: 52, ts: 0, cat: 'foo', tid: 53,
+ ph: 'S', id: 72},
+ {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 0, cat: 'foo',
+ tid: 53, ph: 'T', id: 72},
+
+ // Slice that does finish to give an 'end time' to make autoclosing work.
+ {name: 'b', args: {}, pid: 1, ts: 1000, cat: 'bar', tid: 2, ph: 'B'},
+ {name: 'b', args: {}, pid: 1, ts: 2000, cat: 'bar', tid: 2, ph: 'E'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncStepEndEvent', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.strictEqual(parentSlice.start, 0);
+ assert.strictEqual(parentSlice.args.x, 1);
+ assert.isUndefined(parentSlice.args.y);
+ assert.strictEqual(parentSlice.args.z, 3);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 1);
+ const subSlice = parentSlice.subSlices[0];
+ assert.strictEqual(subSlice.title, 's1');
+ assert.strictEqual(subSlice.category, 'foo');
+ assert.isFalse(subSlice.isTopLevel);
+ assert.strictEqual(subSlice.start, 0);
+ assert.closeTo((548 - 524) / 1000, subSlice.duration, 1e-5);
+ assert.isUndefined(subSlice.args.x);
+ assert.strictEqual(subSlice.args.y, 2);
+ assert.isUndefined(subSlice.args.z);
+ }
+
+ const events = [
+ // Time is intentionally out of order.
+ {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'F', id: 72},
+ {name: 'a', args: {step: 's1', y: 2}, pid: 52, ts: 548, cat: 'foo',
+ tid: 53, ph: 'p', id: 72},
+ {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'S', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncStepMismatch', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isUndefined(t);
+ assert.isTrue(m.hasImportWarnings);
+ }
+
+ const events = [
+ // Time is intentionally out of order.
+ {name: 'a', args: {z: 3}, pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'F', id: 72},
+ {name: 'a', args: {step: 's2'}, pid: 52, ts: 548, cat: 'foo', tid: 53,
+ ph: 'T', id: 72},
+ {name: 'a', args: {step: 's1'}, pid: 52, ts: 548, cat: 'foo', tid: 53,
+ ph: 'p', id: 72},
+ {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'S', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncSliceWithoutCPUDuration', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 3);
+
+ const noTTSNoField = t.asyncSliceGroup.slices[0];
+ assert.isUndefined(noTTSNoField.cpuStart);
+ assert.isUndefined(noTTSNoField.cpuDuration);
+
+ const TTSNoField = t.asyncSliceGroup.slices[1];
+ assert.isUndefined(TTSNoField.cpuStart);
+ assert.isUndefined(TTSNoField.cpuDuration);
+
+ const TTSZeroField = t.asyncSliceGroup.slices[2];
+ assert.isUndefined(TTSZeroField.cpuStart);
+ assert.isUndefined(TTSZeroField.cpuDuration);
+ }
+
+ const events = [
+ // Async slice without tts field.
+ {name: 'a', args: {params: ''}, pid: 52, ts: 10, cat: 'foo', tid: 53,
+ id: 72, ph: 'b'},
+ {name: 'a', args: {params: ''}, pid: 52, ts: 20, cat: 'foo', tid: 53,
+ id: 72, ph: 'e'},
+ // Async slice with tts field but without use_async_tts marker field.
+ {name: 'b', args: {params: ''}, pid: 52, ts: 30, cat: 'foo', tid: 53,
+ id: 72, ph: 'b', tts: 30000},
+ {name: 'b', args: {params: ''}, pid: 52, ts: 40, cat: 'foo', tid: 53,
+ id: 72, ph: 'e', tts: 40000},
+ // Async slice with tts field but with use_async_tts marker set to 0.
+ {name: 'c', args: {params: ''}, pid: 52, ts: 50000, cat: 'foo', tid: 53,
+ id: 72, ph: 'b', tts: 50000, use_async_tts: 0},
+ {name: 'c', args: {params: ''}, pid: 52, ts: 60000, cat: 'foo', tid: 53,
+ id: 72, ph: 'e', tts: 60000, use_async_tts: 0}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('asyncSliceWithCPUDuration', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+
+ const asyncSlice = t.asyncSliceGroup.slices[0];
+ assert.isDefined(asyncSlice);
+ assert.strictEqual(asyncSlice.duration, 10);
+ assert.strictEqual(asyncSlice.cpuStart, 100);
+ assert.strictEqual(asyncSlice.cpuDuration, 5);
+ }
+
+ const events = [
+ {name: 'a', args: {params: ''}, pid: 52, ts: 50000, cat: 'foo', tid: 53,
+ id: 72, ph: 'b', tts: 100000, use_async_tts: 1},
+ {name: 'a', args: {params: ''}, pid: 52, ts: 60000, cat: 'foo', tid: 53,
+ id: 72, ph: 'e', tts: 105000, use_async_tts: 1}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncBasic', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 1);
+ const subSlice = parentSlice.subSlices[0];
+ assert.isFalse(subSlice.isTopLevel);
+ // Arguments should include both BEGIN and END event.
+ assert.strictEqual(subSlice.args.x, 1);
+ assert.strictEqual(subSlice.args.y, 2);
+ assert.sameMembers(subSlice.subSlices, []);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'b', args: {x: 1}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'b', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'e', id: 72},
+ {name: 'a', args: {}, pid: 52, ts: 565, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+
+ test('nestableAsyncNoArgs', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const slice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'name');
+ assert.strictEqual(slice.category, 'foo');
+ assert.isTrue(slice.isTopLevel);
+
+ assert.isDefined(slice.subSlices);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ assert.deepEqual(slice.args, {});
+ }
+
+ const events = [
+ {name: 'name', pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'name', pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncCombinedParams', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 3);
+
+ const sliceA = t.asyncSliceGroup.slices[0];
+ // Arguments should include both BEGIN and END event.
+ assert.strictEqual(sliceA.args.x, 1);
+ assert.strictEqual(sliceA.args.y, 2);
+ const paramsA = sliceA.args.params;
+ assert.isDefined(paramsA);
+ assert.strictEqual(paramsA.p1, 'hello');
+ assert.strictEqual(paramsA.p2, 123);
+ assert.strictEqual(paramsA.p3, 'hi');
+ assert.isTrue(sliceA.isTopLevel);
+
+ const sliceB = t.asyncSliceGroup.slices[1];
+ // Arguments should include both BEGIN and END event.
+ const paramsB = sliceB.args.params;
+ assert.isDefined(paramsB);
+ assert.strictEqual(paramsB.p4, 'foo');
+ assert.isTrue(sliceB.isTopLevel);
+
+ const sliceC = t.asyncSliceGroup.slices[2];
+ // Arguments should include both BEGIN and END event.
+ const paramsC = sliceC.args.params;
+ assert.isDefined(paramsC);
+ assert.strictEqual(paramsC.p5, 'bar');
+ assert.isTrue(sliceC.isTopLevel);
+ }
+
+ const events = [
+ {name: 'a', args: {x: 1, params: {p1: 'hello', p2: 123}},
+ pid: 52, ts: 525, cat: 'foo', tid: 53, ph: 'b', id: 72},
+ {name: 'a', args: {y: 2, params: {p3: 'hi'}}, pid: 52, ts: 560,
+ cat: 'foo', tid: 53, ph: 'e', id: 72},
+ {name: 'b', args: {params: {p4: 'foo'}},
+ pid: 52, ts: 525, cat: 'foo', tid: 53, ph: 'b', id: 73},
+ {name: 'b', args: {params: ''}, pid: 52, ts: 560,
+ cat: 'foo', tid: 53, ph: 'e', id: 73},
+ {name: 'c', args: {params: {p5: 'bar'}},
+ pid: 52, ts: 525, cat: 'foo', tid: 53, ph: 'b', id: 74},
+ {name: 'c', args: {}, pid: 52, ts: 560,
+ cat: 'foo', tid: 53, ph: 'e', id: 74}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncManyLevels', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ // Perfectly matched events should not produce a warning.
+ assert.isFalse(m.hasImportWarnings);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+
+ const l1Slice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(l1Slice.title, 'l1');
+ assert.closeTo(0, l1Slice.start, 1e-5);
+ assert.closeTo(9 / 1000, l1Slice.duration, 1e-5);
+ assert.isTrue(l1Slice.isTopLevel);
+
+ assert.isDefined(l1Slice.subSlices);
+ assert.strictEqual(l1Slice.subSlices.length, 1);
+ const l2Slice = l1Slice.subSlices[0];
+ assert.strictEqual(l2Slice.title, 'l2');
+ assert.closeTo(1 / 1000, l2Slice.start, 1e-5);
+ assert.closeTo(7 / 1000, l2Slice.duration, 1e-5);
+ assert.isFalse(l2Slice.isTopLevel);
+
+ assert.isDefined(l2Slice.subSlices);
+ assert.strictEqual(l2Slice.subSlices.length, 1);
+ const l3Slice = l2Slice.subSlices[0];
+ assert.strictEqual(l3Slice.title, 'l3');
+ assert.closeTo(2 / 1000, l3Slice.start, 1e-5);
+ assert.closeTo(5 / 1000, l3Slice.duration, 1e-5);
+ assert.isFalse(l3Slice.isTopLevel);
+
+ assert.isDefined(l3Slice.subSlices);
+ assert.strictEqual(l3Slice.subSlices.length, 1);
+ const l4Slice = l3Slice.subSlices[0];
+ assert.strictEqual(l4Slice.title, 'l4');
+ assert.closeTo(3 / 1000, l4Slice.start, 1e-5);
+ assert.closeTo(3 / 1000, l4Slice.duration, 1e-5);
+ assert.isFalse(l4Slice.isTopLevel);
+
+ assert.isDefined(l4Slice.subSlices);
+ assert.strictEqual(l4Slice.subSlices.length, 1);
+ const l5Slice = l4Slice.subSlices[0];
+ assert.strictEqual(l5Slice.title, 'l5');
+ assert.closeTo(4 / 1000, l5Slice.start, 1e-5);
+ assert.closeTo(1 / 1000, l5Slice.duration, 1e-5);
+ assert.isFalse(l5Slice.isTopLevel);
+ }
+
+ // There are 5 nested levels.
+ const events = [
+ {name: 'l1', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'l2', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'l3', args: {}, pid: 52, ts: 526, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'l4', args: {}, pid: 52, ts: 527, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'l5', args: {}, pid: 52, ts: 528, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'l5', args: {}, pid: 52, ts: 529, cat: 'foo', tid: 53,
+ ph: 'e', id: 72},
+ {name: 'l4', args: {}, pid: 52, ts: 530, cat: 'foo', tid: 53,
+ ph: 'e', id: 72},
+ {name: 'l3', args: {}, pid: 52, ts: 531, cat: 'foo', tid: 53,
+ ph: 'e', id: 72},
+ {name: 'l2', args: {}, pid: 52, ts: 532, cat: 'foo', tid: 53,
+ ph: 'e', id: 72},
+ {name: 'l1', args: {}, pid: 52, ts: 533, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncInstantEvent', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 2);
+ const instantSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(instantSlice.title, 'c');
+ assert.closeTo(0, instantSlice.start, 1e-5);
+ assert.closeTo(0, instantSlice.duration, 1e-5);
+ assert.sameMembers(instantSlice.subSlices, []);
+ assert.isTrue(instantSlice.isTopLevel);
+
+ const nestedSlice = t.asyncSliceGroup.slices[1];
+ assert.strictEqual(nestedSlice.title, 'a');
+ assert.closeTo(0, nestedSlice.start, 1e-5);
+ assert.closeTo((565 - 524) / 1000, nestedSlice.duration, 1e-5);
+ assert.isTrue(nestedSlice.isTopLevel);
+ assert.isDefined(nestedSlice.subSlices);
+ assert.strictEqual(nestedSlice.subSlices.length, 1);
+ const nestedInstantSlice = nestedSlice.subSlices[0];
+ assert.sameMembers(nestedInstantSlice.subSlices, []);
+ assert.strictEqual(nestedInstantSlice.title, 'd');
+ assert.isFalse(nestedInstantSlice.isTopLevel);
+ }
+
+ const events = [
+ {name: 'c', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'n', id: 71},
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'd', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'n', id: 72},
+ {name: 'a', args: {}, pid: 52, ts: 565, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncUnmatchedOuterBeginEvent', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ // Unmatched BEGIN should produce a warning.
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.closeTo(0, parentSlice.start, 0.0001);
+ // Unmatched BEGIN event ends at the last event of that ID.
+ assert.closeTo(36 / 1000, parentSlice.duration, 0.0001);
+ // Arguments should include only include its arguments.
+ assert.isUndefined(parentSlice.args.y);
+ assert.strictEqual(parentSlice.args.x, 1);
+ assert.isDefined(parentSlice.error);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 1);
+ const subSlice = parentSlice.subSlices[0];
+ assert.isFalse(subSlice.isTopLevel);
+ assert.closeTo(1 / 1000, subSlice.start, 1e-5);
+ assert.closeTo(35 / 1000, subSlice.duration, 1e-5);
+ assert.sameMembers(subSlice.subSlices, []);
+ // Arguments should include those of the END event.
+ assert.strictEqual(subSlice.args.y, 2);
+ assert.sameMembers(subSlice.subSlices, []);
+ }
+
+ const events = [
+ {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'b', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'b', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncUnmatchedInnerBeginEvent', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ // Unmatched BEGIN should produce a warning.
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.closeTo(0, parentSlice.start, 1e-5);
+ assert.closeTo(41 / 1000, parentSlice.duration, 1e-5);
+ // Arguments should include both BEGIN and END event.
+ assert.strictEqual(parentSlice.args.y, 2);
+ assert.strictEqual(parentSlice.args.z, 3);
+ assert.isUndefined(parentSlice.args.x);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 2);
+ const subSliceInstant = parentSlice.subSlices[0];
+ const subSliceUnmatched = parentSlice.subSlices[1];
+ assert.strictEqual(subSliceInstant.title, 'c');
+ assert.isFalse(subSliceInstant.isTopLevel);
+ assert.strictEqual(subSliceUnmatched.title, 'b');
+ assert.isFalse(subSliceUnmatched.isTopLevel);
+ // Unmatched BEGIN ends at the last event of that ID.
+ assert.closeTo(1 / 1000, subSliceUnmatched.start, 1e-5);
+ assert.closeTo(40 / 1000, subSliceUnmatched.duration, 1e-5);
+ assert.sameMembers(subSliceUnmatched.subSlices, []);
+ assert.strictEqual(subSliceUnmatched.args.x, 1);
+ assert.isUndefined(subSliceUnmatched.y);
+ assert.isDefined(subSliceUnmatched.error);
+ assert.closeTo(1 / 1000, subSliceInstant.start, 1e-5);
+ assert.closeTo(0, subSliceInstant.duration, 1e-5);
+ assert.sameMembers(subSliceInstant.subSlices, []);
+ }
+
+ const events = [
+ {name: 'a', args: {z: 3}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'c', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'n', id: 72},
+ {name: 'b', args: {x: 1}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'a', args: {y: 2}, pid: 52, ts: 565, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncUnmatchedOuterEndEvent', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ // Unmatched END should produce a warning.
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 2);
+ const unmatchedSlice = t.asyncSliceGroup.slices[0];
+ const slice = t.asyncSliceGroup.slices[1];
+ assert.strictEqual(unmatchedSlice.title, 'a');
+ assert.closeTo(0, unmatchedSlice.start, 1e-5);
+ assert.isTrue(unmatchedSlice.isTopLevel);
+ // Unmatched END event begins at the first event of that ID. In this
+ // case, the first event happens to be the same unmatched event.
+ assert.closeTo(0 / 1000, unmatchedSlice.duration, 1e-5);
+ assert.isUndefined(unmatchedSlice.args.x);
+ assert.isUndefined(unmatchedSlice.args.y);
+ assert.strictEqual(unmatchedSlice.args.z, 3);
+ assert.isDefined(unmatchedSlice.error);
+ assert.sameMembers(unmatchedSlice.subSlices, []);
+
+ assert.strictEqual(slice.title, 'b');
+ assert.isTrue(slice.isTopLevel);
+ assert.closeTo(1 / 1000, slice.start, 1e-5);
+ assert.closeTo(35 / 1000, slice.duration, 1e-5);
+ // Arguments should include both BEGIN and END event.
+ assert.strictEqual(slice.args.x, 1);
+ assert.strictEqual(slice.args.y, 2);
+ assert.sameMembers(slice.subSlices, []);
+ }
+
+ // Events are intentionally out-of-order.
+ const events = [
+ {name: 'b', args: {x: 1}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'b', args: {y: 2}, pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'e', id: 72},
+ {name: 'a', args: {z: 3}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncUnmatchedInnerEndEvent', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ // Unmatched END should produce a warning.
+ assert.isTrue(m.hasImportWarnings);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.closeTo(0, parentSlice.start, 1e-5);
+ assert.closeTo(41 / 1000, parentSlice.duration, 1e-5);
+ // Arguments should include both BEGIN and END event.
+ assert.strictEqual(parentSlice.args.x, 1);
+ assert.strictEqual(parentSlice.args.y, 2);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 2);
+ const subSliceInstant = parentSlice.subSlices[0];
+ const subSliceUnmatched = parentSlice.subSlices[1];
+ assert.strictEqual(subSliceInstant.title, 'c');
+ assert.isFalse(subSliceInstant.isTopLevel);
+ assert.strictEqual(subSliceUnmatched.title, 'b');
+ assert.isFalse(subSliceUnmatched.isTopLevel);
+ // Unmatched END begins at the first event of that ID.
+ assert.closeTo(0 / 1000, subSliceUnmatched.start, 1e-5);
+ assert.closeTo(1 / 1000, subSliceUnmatched.duration, 1e-5);
+ // Arguments should include both BEGIN and END event.
+ assert.isUndefined(subSliceUnmatched.args.x);
+ assert.isUndefined(subSliceUnmatched.args.y);
+ assert.strictEqual(subSliceUnmatched.args.z, 3);
+ assert.isDefined(subSliceUnmatched.error);
+
+ assert.sameMembers(subSliceUnmatched.subSlices, []);
+ assert.closeTo(1 / 1000, subSliceInstant.start, 1e-5);
+ assert.closeTo(0, subSliceInstant.duration, 1e-5);
+ assert.sameMembers(subSliceInstant.subSlices, []);
+ }
+
+ const events = [
+ {name: 'a', args: {x: 1}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'c', args: {}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'n', id: 72},
+ {name: 'b', args: {z: 3}, pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'e', id: 72},
+ {name: 'a', args: {y: 2}, pid: 52, ts: 565, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncSameIDDifferentCategory', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 2);
+ const eventASlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(eventASlice.title, 'EVENT_A');
+ assert.strictEqual(eventASlice.category, 'foo');
+ assert.strictEqual(eventASlice.id, 'foo::ptr:72');
+ assert.isTrue(eventASlice.isTopLevel);
+ assert.strictEqual(eventASlice.args.x, 1);
+ assert.sameMembers(eventASlice.subSlices, []);
+
+ const eventBSlice = t.asyncSliceGroup.slices[1];
+ assert.strictEqual(eventBSlice.title, 'EVENT_B');
+ assert.strictEqual(eventBSlice.category, 'bar');
+ assert.strictEqual(eventBSlice.id, 'bar::ptr:72');
+ assert.isTrue(eventBSlice.isTopLevel);
+ assert.strictEqual(eventBSlice.args.y, 2);
+ assert.sameMembers(eventBSlice.subSlices, []);
+ }
+
+ // Events with the same ID, but different categories should not be
+ // considered as nested.
+ const events = [
+ {name: 'EVENT_A', args: {}, pid: 52, ts: 500, cat: 'foo', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'EVENT_B', args: {y: 2}, pid: 52, ts: 550, cat: 'bar', tid: 53,
+ ph: 'b', id: 72},
+ {name: 'EVENT_B', args: {}, pid: 52, ts: 600, cat: 'bar', tid: 53,
+ ph: 'e', id: 72},
+ {name: 'EVENT_A', args: {x: 1}, pid: 52, ts: 650, cat: 'foo', tid: 53,
+ ph: 'e', id: 72}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('nestableAsyncStackFrame', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const slice = t.asyncSliceGroup.slices[0];
+
+ assert.strictEqual(slice.startStackFrame.title, 'main');
+ assert.strictEqual(slice.endStackFrame.title, 'frame7');
+ }
+
+ const events = {
+ traceEvents: [
+ {name: 'name', pid: 52, ts: 525, cat: 'foo', tid: 53,
+ ph: 'b', id: 72, sf: 1},
+ {name: 'name', pid: 52, ts: 560, cat: 'foo', tid: 53,
+ ph: 'e', id: 72, sf: 7}
+ ],
+ stackFrames: {
+ '1': {
+ category: 'm1',
+ name: 'main'
+ },
+ '7': {
+ category: 'm2',
+ name: 'frame7',
+ parent: '1'
+ }
+ }
+ };
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('processLocalAsync', function() {
+ function checkModel(m) {
+ let t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ let parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 0);
+
+ t = m.processes[54].threads[55];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'b');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.strictEqual(parentSlice.args.x, 1);
+ assert.strictEqual(parentSlice.args.y, 2);
+ assert.isTrue(parentSlice.isTopLevel);
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 0);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'b', id2: {local: 72}},
+ {name: 'b', args: {x: 1}, pid: 54, ts: 525, cat: 'foo', tid: 55,
+ ph: 'b', id2: {local: 72}},
+ {name: 'b', args: {y: 2}, pid: 54, ts: 560, cat: 'foo', tid: 55,
+ ph: 'e', id2: {local: 72}},
+ {name: 'a', args: {}, pid: 52, ts: 565, cat: 'foo', tid: 53,
+ ph: 'e', id2: {local: 72}}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('globalAsync', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+
+ assert.isDefined(parentSlice.subSlices);
+ assert.strictEqual(parentSlice.subSlices.length, 1);
+ const subSlice = parentSlice.subSlices[0];
+ assert.isFalse(subSlice.isTopLevel);
+ // Arguments should include both BEGIN and END event.
+ assert.strictEqual(subSlice.args.x, 1);
+ assert.strictEqual(subSlice.args.y, 2);
+ assert.sameMembers(subSlice.subSlices, []);
+
+ assert.isUndefined(m.processes[54].threads[55]);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53,
+ ph: 'b', id2: {global: 72}},
+ {name: 'b', args: {x: 1}, pid: 54, ts: 525, cat: 'foo', tid: 55,
+ ph: 'b', id2: {global: 72}},
+ {name: 'b', args: {y: 2}, pid: 54, ts: 560, cat: 'foo', tid: 55,
+ ph: 'e', id2: {global: 72}},
+ {name: 'a', args: {}, pid: 52, ts: 565, cat: 'foo', tid: 53,
+ ph: 'e', id2: {global: 72}}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importSamples', function() {
+ function checkModel(m) {
+ const p = m.processes[52];
+ assert.isDefined(p);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.samples_.length, 4);
+ assert.strictEqual(t.samples_[0].start, 0.0);
+ assert.strictEqual(t.samples_[1].start, 0.0);
+ assert.closeTo(0.01, t.samples_[2].start, 1e-5);
+ assert.strictEqual(t.samples_[0].leafNode.title, 'a');
+ assert.strictEqual(t.samples_[1].leafNode.title, 'b');
+ assert.strictEqual(t.samples_[2].leafNode.title, 'c');
+ assert.strictEqual(t.samples_[3].leafNode, t.samples[0].leafNode);
+ assert.isFalse(m.hasImportWarnings);
+ }
+
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
+ {name: 'b', args: {}, pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
+ {name: 'c', args: {}, pid: 52, ts: 558, cat: 'test', tid: 53, ph: 'P'},
+ {name: 'a', args: {}, pid: 52, ts: 568, cat: 'test', tid: 53, ph: 'P'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importSamplesWithStackFrames', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[2];
+
+ assert.strictEqual(t.samples.length, 1);
+ assert.strictEqual(t.samples_[0].start, 0.0);
+ assert.strictEqual(t.samples_[0].leafNode.title, 'frame7');
+ assert.isFalse(m.hasImportWarnings);
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'a', args: {}, pid: 1, ts: 0, cat: 'test', tid: 2, ph: 'P', sf: 7 } // @suppress longLineCheck
+ ],
+ stackFrames: {
+ '1': {
+ category: 'm1',
+ name: 'main'
+ },
+ '7': {
+ category: 'm2',
+ name: 'frame7',
+ parent: '1'
+ }
+ }
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importSamplesMissingArgs', function() {
+ function checkModel(m) {
+ const p = m.processes[52];
+ assert.isDefined(p);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ assert.isDefined(t);
+ assert.strictEqual(t.samples_.length, 3);
+ assert.isFalse(m.hasImportWarnings);
+ }
+
+ const events = [
+ {name: 'a', pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
+ {name: 'b', pid: 52, ts: 548, cat: 'test', tid: 53, ph: 'P'},
+ {name: 'c', pid: 52, ts: 549, cat: 'test', tid: 53, ph: 'P'}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importV8Samples', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[2];
+
+ assert.isFalse(m.hasImportWarnings);
+ assert.strictEqual(t.samples.length, 2);
+
+ let sample = t.samples_[0];
+ assert.deepEqual(
+ sample.userFriendlyStack,
+ ['foo url: http://example.com/bar.js:22', 'bar url: unknown']);
+
+ sample = t.samples_[1];
+ assert.deepEqual(sample.userFriendlyStack, ['gc url: unknown']);
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'V8Sample', args: {data: {stack: ['0x2a574306061', '0x2a574306224'], vm_state: 'js'}}, pid: 1, ts: 4, cat: 'test', tid: 2, ph: 'P' }, // @suppress longLineCheck
+ { name: 'V8Sample', args: {data: {stack: [], vm_state: 'gc'}}, pid: 1, ts: 6, cat: 'test', tid: 2, ph: 'P' }, // @suppress longLineCheck
+ { name: 'JitCodeAdded', args: {data: {code_len: 2, name: 'LazyCompile:~foo http://example.com/bar.js:23', code_start: '0x2a574306060'}}, pid: 1, ts: 1, cat: 'test', tid: 2, ph: 'M' }, // @suppress longLineCheck
+ { name: 'JitCodeAdded', args: {data: {code_len: 20, name: 'bar', code_start: '0x2a574306220'}}, pid: 1, ts: 2, cat: 'test', tid: 2, ph: 'M' }, // @suppress longLineCheck
+ { name: 'JitCodeMoved', args: {data: {code_len: 2, old_code_start: '0x2a574306220', code_start: '0x2a574306222'}}, pid: 1, ts: 3, cat: 'test', tid: 2, ph: 'M' }, // @suppress longLineCheck
+ { name: 'JitCodeAdded', args: {data: {code_len: 20, name: 'baz', code_start: '0xffffffff9f90a1a0'}}, pid: 1, ts: 4, cat: 'test', tid: 2, ph: 'M' } // @suppress longLineCheck
+ ]
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importOldFormatV8Samples', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[2];
+
+ assert.isFalse(m.hasImportWarnings);
+ assert.strictEqual(t.samples.length, 2);
+
+ let sample = t.samples_[0];
+ assert.deepEqual(
+ sample.userFriendlyStack,
+ ['foo url: http://example.com/bar.js:22', 'bar url: unknown']);
+
+ sample = t.samples_[1];
+ assert.deepEqual(sample.userFriendlyStack, ['gc url: unknown']);
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'JitCodeAdded', args: {data: {code_len: 2, name: 'LazyCompile:~foo http://example.com/bar.js:23', code_start: '0x2a574306060'}}, pid: 1, ts: 0, cat: 'test', tid: 2, ph: 'I' }, // @suppress longLineCheck
+ { name: 'JitCodeAdded', args: {data: {code_len: 20, name: 'bar', code_start: '0x2a574306220'}}, pid: 1, ts: 0, cat: 'test', tid: 2, ph: 'I' }, // @suppress longLineCheck
+ { name: 'JitCodeMoved', args: {data: {code_len: 2, old_code_start: '0x2a574306220', code_start: '0x2a574306222'}}, pid: 1, ts: 0, cat: 'test', tid: 2, ph: 'I' }, // @suppress longLineCheck
+ { name: 'JitCodeAdded', args: {data: {code_len: 20, name: 'baz', code_start: '0xffffffff9f90a1a0'}}, pid: 1, ts: 0, cat: 'test', tid: 2, ph: 'I' }, // @suppress longLineCheck
+ { name: 'V8Sample', args: {data: {stack: ['0x2a574306061', '0x2a574306224']}}, pid: 1, ts: 0, cat: 'test', tid: 2, ph: 'P' }, // @suppress longLineCheck
+ { name: 'V8Sample', args: {data: {stack: [], vm_state: 'gc'}}, pid: 1, ts: 10, cat: 'test', tid: 2, ph: 'P' } // @suppress longLineCheck
+ ]
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importSimpleObject', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.bounds.min, 10);
+ assert.strictEqual(m.bounds.max, 50);
+ assert.isFalse(m.hasImportWarnings);
+
+ const p = m.processes[1];
+ assert.isDefined(p);
+
+ const i10 = p.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x1000'), 10);
+ assert.strictEqual(i10.category, 'c');
+ assert.strictEqual(i10.creationTs, 10);
+ assert.strictEqual(i10.deletionTs, 50);
+ assert.strictEqual(i10.snapshots.length, 2);
+
+ const s15 = i10.snapshots[0];
+ assert.strictEqual(s15.ts, 15);
+ assert.strictEqual(s15.args, 15);
+
+ const s20 = i10.snapshots[1];
+ assert.strictEqual(s20.ts, 20);
+ assert.strictEqual(s20.args, 20);
+ }
+
+ const events = [
+ {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+ {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 15}}, // @suppress longLineCheck
+ {ts: 20000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 20}}, // @suppress longLineCheck
+ {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('importImplicitObjects', function() {
+ function checkModel(m) {
+ const p1 = m.processes[1];
+
+ const iA = p1.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x1000'), 10);
+ const subObjectInstances =
+ p1.objects.getAllInstancesByTypeName().subObject;
+
+ assert.strictEqual(subObjectInstances.length, 2);
+ const subObject1 = p1.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x1'), 15);
+ assert.strictEqual(subObject1.name, 'subObject');
+ assert.strictEqual(subObject1.creationTs, 15);
+
+ assert.strictEqual(subObject1.snapshots.length, 2);
+ assert.strictEqual(subObject1.snapshots[0].ts, 15);
+ assert.strictEqual(subObject1.snapshots[0].args.foo, 1);
+ assert.strictEqual(subObject1.snapshots[1].ts, 20);
+ assert.strictEqual(subObject1.snapshots[1].args.foo, 2);
+
+ const subObject2 = p1.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x2'), 20);
+ assert.strictEqual(subObject2.name, 'subObject');
+ assert.strictEqual(subObject2.creationTs, 20);
+ assert.strictEqual(subObject2.snapshots.length, 1);
+ assert.strictEqual(subObject2.snapshots[0].ts, 20);
+ }
+
+ const events = [
+ {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+ {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a',
+ args: { snapshot: [
+ { id: 'subObject/0x1',
+ foo: 1
+ }
+ ]}},
+ {ts: 20000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a',
+ args: { snapshot: [
+ { id: 'subObject/0x1',
+ foo: 2
+ },
+ { id: 'subObject/0x2',
+ foo: 1
+ }
+ ]}}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('importImplicitObjectWithCategoryOverride', function() {
+ function checkModel(m) {
+ const p1 = m.processes[1];
+
+ const iA = p1.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x1000'), 10);
+ const subObjectInstances =
+ p1.objects.getAllInstancesByTypeName().subObject;
+
+ assert.strictEqual(subObjectInstances.length, 1);
+ }
+
+ const events = [
+ {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'cat', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+ {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'otherCat', id: '0x1000', name: 'a', // @suppress longLineCheck
+ args: { snapshot: [
+ { id: 'subObject/0x1',
+ cat: 'cat',
+ foo: 1
+ }
+ ]}}
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importImplicitObjectWithBaseTypeOverride', function() {
+ function checkModel(m) {
+ const p1 = m.processes[1];
+ assert.strictEqual(m.importWarnings.length, 0);
+
+ const iA = p1.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x1000'), 10);
+ assert.strictEqual(iA.snapshots.length, 1);
+ }
+
+ const events = [
+ {ts: 10000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'PictureLayerImpl', args: { // @suppress longLineCheck
+ snapshot: {
+ base_type: 'LayerImpl'
+ }
+ }},
+ {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'LayerImpl', args: {}} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importIDRefs', function() {
+ function checkModel(m) {
+ const p1 = m.processes[1];
+
+ const iA = p1.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x1000'), 10);
+ const s15 = iA.getSnapshotAt(15);
+
+ const taskSlice = p1.threads[1].sliceGroup.slices[0];
+ assert.strictEqual(taskSlice.args.my_object, s15);
+ }
+
+ const events = [
+ // An object with two snapshots.
+ {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+ {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 15}}, // @suppress longLineCheck
+ {ts: 20000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: {snapshot: 20}}, // @suppress longLineCheck
+ {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+
+ // A slice that references the object.
+ {ts: 17000, pid: 1, tid: 1, ph: 'B', cat: 'c', name: 'taskSlice', args: {my_object: {id_ref: '0x1000'}}}, // @suppress longLineCheck
+ {ts: 17500, pid: 1, tid: 1, ph: 'E', cat: 'c', name: 'taskSlice', args: {}} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('importIDRefsThatPointAtEachOther', function() {
+ function checkModel(m) {
+ const p1 = m.processes[1];
+
+ const iA = p1.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x1000'), 15);
+ const iFoo = p1.objects.getObjectInstanceAt(
+ new ScopedId('ptr', '0x1001'), 15);
+ assert.isDefined(iA);
+ assert.isDefined(iFoo);
+
+ const a15 = iA.getSnapshotAt(15);
+ const foo15 = iFoo.getSnapshotAt(15);
+
+ const taskSlice = p1.threads[1].sliceGroup.slices[0];
+ assert.strictEqual(taskSlice.args.my_object, foo15);
+ }
+
+ const events = [
+ // An object.
+ {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+ {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: { // @suppress longLineCheck
+ snapshot: { x: {
+ id: 'foo/0x1001',
+ value: 'bar'
+ }}}},
+ {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+
+ // A slice that references the object.
+ {ts: 17000, pid: 1, tid: 1, ph: 'B', cat: 'c', name: 'taskSlice', args: {my_object: {id_ref: '0x1001'}}}, // @suppress longLineCheck
+ {ts: 17500, pid: 1, tid: 1, ph: 'E', cat: 'c', name: 'taskSlice', args: {}} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importArrayWithIDs', function() {
+ function checkModel(m) {
+ const p1 = m.processes[1];
+
+ const sA = p1.objects.getSnapshotAt(new ScopedId('ptr', '0x1000'), 15);
+ assert.isTrue(sA.args.x instanceof Array);
+ assert.strictEqual(sA.args.x.length, 3);
+ assert.isTrue(sA.args.x[0] instanceof tr.model.ObjectSnapshot);
+ assert.isTrue(sA.args.x[1] instanceof tr.model.ObjectSnapshot);
+ assert.isTrue(sA.args.x[2] instanceof tr.model.ObjectSnapshot);
+ }
+
+ const events = [
+ {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: { // @suppress longLineCheck
+ snapshot: { x: [
+ {id: 'foo/0x1001', value: 'bar1'},
+ {id: 'foo/0x1002', value: 'bar2'},
+ {id: 'foo/0x1003', value: 'bar3'}
+ ]}}}
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('importDoesNotMutateEventList', function() {
+ const events = [
+ // An object.
+ {ts: 10000, pid: 1, tid: 1, ph: 'N', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+ {ts: 15000, pid: 1, tid: 1, ph: 'O', cat: 'c', id: '0x1000', name: 'a', args: { // @suppress longLineCheck
+ snapshot: {foo: 15}}},
+ {ts: 50000, pid: 1, tid: 1, ph: 'D', cat: 'c', id: '0x1000', name: 'a', args: {}}, // @suppress longLineCheck
+
+ // A slice that references the object.
+ {ts: 17000, pid: 1, tid: 1, ph: 'B', cat: 'c', name: 'taskSlice', args: {
+ my_object: {id_ref: '0x1000'}}
+ },
+ {ts: 17500, pid: 1, tid: 1, ph: 'E', cat: 'c', name: 'taskSlice', args: {}} // @suppress longLineCheck
+ ];
+
+ // The A type family exists to mutate the args list provided to
+ // snapshots.
+ function ASnapshot() {
+ tr.model.ObjectSnapshot.apply(this, arguments);
+ this.args.foo = 7;
+ }
+ ASnapshot.prototype = {
+ __proto__: tr.model.ObjectSnapshot.prototype
+ };
+
+ // Import event while the A types are registered, causing the
+ // arguments of the snapshots to be mutated.
+ tr.model.ObjectSnapshot.subTypes.register(ASnapshot, {typeName: 'a'});
+ const m = makeModel(events);
+ tr.model.ObjectSnapshot.subTypes.unregister(ASnapshot);
+ assert.isFalse(m.hasImportWarnings);
+
+ // Verify that the events array wasn't modified.
+ assert.deepEqual(
+ events[1].args,
+ {snapshot: {foo: 15}});
+ assert.deepEqual(
+ events[3].args,
+ {my_object: {id_ref: '0x1000'}});
+ });
+
+ test('importFlowEvent', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+
+ assert.isDefined(t);
+ assert.strictEqual(m.flowEvents.length, 2);
+ assert.strictEqual(m.flowIntervalTree.size, 2);
+
+ const f0 = m.flowEvents[0];
+ assert.strictEqual(f0.title, 'a');
+ assert.strictEqual(f0.category, 'foo');
+ assert.strictEqual(f0.id, 72);
+ assert.closeTo(f0.start, 0.001, 1e-5);
+ assert.closeTo(12 / 1000, f0.duration, 1e-5);
+ assert.strictEqual(f0.startSlice.title, 'aSlice');
+ assert.strictEqual(f0.endSlice.title, 'bSlice');
+
+ // TODO(nduca): Replace this assertion with something better when
+ // flow events don't create synthetic slices on their own.
+ assert.isDefined(f0.startSlice);
+ assert.isDefined(f0.endSlice);
+
+ const f1 = m.flowEvents[1];
+ assert.strictEqual(f1.title, f0.title);
+ assert.strictEqual(f1.category, f0.category);
+ assert.strictEqual(f1.id, f0.id);
+ assert.closeTo(20 / 1000, f1.duration, 1e-5);
+
+ assert.strictEqual(f1.startSlice.title, 'bSlice');
+ assert.strictEqual(f1.endSlice.title, 'cSlice');
+
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+ assert.deepEqual(f1.startSlice.outFlowEvents, [f1]);
+ assert.deepEqual(f1.endSlice.inFlowEvents, [f1]);
+ }
+
+ const events = [
+ { name: 'aSlice', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 547, ph: 'B', args: {} }, // @suppress longLineCheck
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {} }, // @suppress longLineCheck
+ { id: 72, pid: 52, tid: 53, ts: 549, ph: 'E', args: {} }, // @suppress longLineCheck
+
+ { name: 'bSlice', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 559, ph: 'B', args: {} }, // @suppress longLineCheck
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 560, ph: 't', args: {} }, // @suppress longLineCheck
+ { id: 72, pid: 52, tid: 53, ts: 561, ph: 'E', args: {} }, // @suppress longLineCheck
+
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 580, ph: 'f', args: {} }, // @suppress longLineCheck
+ { name: 'cSlice', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 581, ph: 'B', args: {} }, // @suppress longLineCheck
+ { id: 72, pid: 52, tid: 53, ts: 582, ph: 'E', args: {} } // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importOldFlowEventBindtoNext', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 1);
+
+ const f0 = m.flowEvents[0];
+
+ assert.strictEqual(f0.title, 'flow');
+ assert.strictEqual(f0.category, 'foo');
+ assert.strictEqual(f0.id, 72);
+ assert.strictEqual(f0.start, .548);
+ assert.closeTo(32 / 1000, f0.duration, 1e-5);
+ assert.strictEqual(f0.startSlice.title, 'slice1');
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+ assert.strictEqual(f0.endSlice.title, 'slice3');
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+ }
+
+ // Old trace format without event.bp, and event.cat doesn't contain input
+ const events = [
+ { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100}, // @suppress longLineCheck
+ { name: 'flow', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {}}, // @suppress longLineCheck
+
+ { name: 'flow', cat: 'foo', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', args: {}}, // @suppress longLineCheck
+ { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, dur: 100}, // @suppress longLineCheck
+ { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, dur: 1000} // @suppress longLineCheck
+
+ ];
+ checkParsedAndStreamInput(events, checkModel, false, false);
+ });
+
+ test('importOldInputFlowEventBindtoParent', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 1);
+
+ const f0 = m.flowEvents[0];
+
+ assert.strictEqual(f0.title, 'flow');
+ assert.strictEqual(f0.category, 'input');
+ assert.strictEqual(f0.id, 72);
+ assert.strictEqual(f0.start, .548);
+ assert.closeTo(32 / 1000, f0.duration, 1e-5);
+ assert.strictEqual(f0.startSlice.title, 'slice1');
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+ assert.strictEqual(f0.endSlice.title, 'slice2');
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+ }
+
+ // Old trace format without event.bp, but event.cat contains input
+ const events = [
+ { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100}, // @suppress longLineCheck
+ { name: 'flow', cat: 'input', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {}}, // @suppress longLineCheck
+
+ { name: 'flow', cat: 'input', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', args: {}}, // @suppress longLineCheck
+ { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, dur: 100}, // @suppress longLineCheck
+ { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, dur: 1000} // @suppress longLineCheck
+
+ ];
+ checkParsedAndStreamInput(events, checkModel, false, false);
+ });
+
+ test('importOldIPCFlowEventBindtoParent', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 1);
+
+ const f0 = m.flowEvents[0];
+
+ assert.strictEqual(f0.title, 'flow');
+ assert.strictEqual(f0.category, 'disabled-by-default-ipc.flow');
+ assert.strictEqual(f0.id, 72);
+ assert.strictEqual(f0.start, .548);
+ assert.closeTo(32 / 1000, f0.duration, 1e-5);
+ assert.strictEqual(f0.startSlice.title, 'slice1');
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+ assert.strictEqual(f0.endSlice.title, 'slice2');
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+ }
+
+ // Old trace format without event.bp, but event.cat contains ipc.flow
+ const events = [
+ { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100}, // @suppress longLineCheck
+ { name: 'flow', cat: 'disabled-by-default-ipc.flow', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {}}, // @suppress longLineCheck
+
+ { name: 'flow', cat: 'disabled-by-default-ipc.flow', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', args: {}}, // @suppress longLineCheck
+ { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, dur: 100}, // @suppress longLineCheck
+ { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, dur: 1000} // @suppress longLineCheck
+
+ ];
+ checkParsedAndStreamInput(events, checkModel, false, false);
+ });
+
+ test('importNewFlowEventBindtoParent', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 1);
+
+ const f0 = m.flowEvents[0];
+
+ assert.strictEqual(f0.title, 'flow');
+ assert.strictEqual(f0.category, 'foo');
+ assert.strictEqual(f0.id, 72);
+ assert.strictEqual(f0.start, .548);
+ assert.closeTo(32 / 1000, f0.duration, 1e-5);
+ assert.strictEqual(f0.startSlice.title, 'slice1');
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+ assert.strictEqual(f0.endSlice.title, 'slice2');
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+ }
+
+ // New trace format with event.bp
+ const events = [
+ { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100}, // @suppress longLineCheck
+ { name: 'flow', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', bp: 'e', args: {}}, // @suppress longLineCheck
+
+ { name: 'flow', cat: 'foo', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', bp: 'e', args: {}}, // @suppress longLineCheck
+ { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, dur: 100}, // @suppress longLineCheck
+ { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, dur: 1000} // @suppress longLineCheck
+
+ ];
+ checkParsedAndStreamInput(events, checkModel, false, false);
+ });
+
+ test('importNewFlowEventWithInvalidBindingPoint', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 0);
+ }
+
+ // New trace format with event.bp, which however !== 'e'
+ const events = [
+ { name: 'slice1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100}, // @suppress longLineCheck
+ { name: 'flow', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', bp: 'z', args: {}}, // @suppress longLineCheck
+
+ { name: 'flow', cat: 'foo', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', bp: 'z', args: {}}, // @suppress longLineCheck
+ { name: 'slice2', cat: 'foo', pid: 70, tid: 71, ts: 570, ph: 'X', args: {}, dur: 100}, // @suppress longLineCheck
+ { name: 'slice3', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', args: {}, dur: 1000} // @suppress longLineCheck
+
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importFlowV2OnePair', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 1);
+
+ const f0 = m.flowEvents[0];
+
+ assert.strictEqual(f0.startSlice.title, 'producer');
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+ assert.strictEqual(f0.endSlice.title, 'consumer');
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+ }
+
+ // Flow V2: one flow producer one flow consumer
+ const events = [
+ { name: 'producer', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100, bind_id: '0xaaa', flow_out: true}, // @suppress longLineCheck
+ { name: 'consumer', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', dur: 1000, bind_id: '0xaaa', flow_in: true} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importFlowV2OneFlowStep', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 2);
+
+ const f0 = m.flowEvents[0];
+ const f1 = m.flowEvents[1];
+
+ assert.strictEqual(f0.startSlice.title, 'producer');
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+ assert.strictEqual(f0.endSlice.title, 'step');
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+
+ assert.strictEqual(f1.startSlice.title, 'step');
+ assert.deepEqual(f1.startSlice.outFlowEvents, [f1]);
+ assert.strictEqual(f1.endSlice.title, 'consumer');
+ assert.deepEqual(f1.endSlice.inFlowEvents, [f1]);
+ }
+
+ // Flow V2: one flow producer one flow consumer
+ const events = [
+ { name: 'producer', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100, bind_id: '0xaaa', flow_out: true}, // @suppress longLineCheck
+ { name: 'step', cat: 'foo', pid: 62, tid: 63, ts: 647, ph: 'X', dur: 100, bind_id: '0xaaa', flow_out: true, flow_in: true}, // @suppress longLineCheck
+ { name: 'consumer', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', dur: 1000, bind_id: '0xaaa', args: { 'queue_duration': 0}, flow_in: true} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importFlowV2MultipleConsumers', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 2);
+
+ const f0 = m.flowEvents[0];
+ const f1 = m.flowEvents[1];
+
+ assert.strictEqual(f0.startSlice.title, 'producer');
+ assert.strictEqual(f1.startSlice.title, 'producer');
+
+ assert.strictEqual(f0.startSlice.outFlowEvents.length, 2);
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0, f1]);
+ assert.deepEqual(f1.startSlice.outFlowEvents, [f0, f1]);
+
+ assert.strictEqual(f0.endSlice.title, 'consumer1');
+ assert.strictEqual(f1.endSlice.title, 'consumer2');
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+ assert.deepEqual(f1.endSlice.inFlowEvents, [f1]);
+ }
+
+ // Flow V2: one flow producer multiple flow consumers
+ const events = [
+ { name: 'producer', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100, bind_id: '0xaaa', flow_out: true}, // @suppress longLineCheck
+ { name: 'consumer1', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', dur: 1000, bind_id: '0xaaa', flow_in: true}, // @suppress longLineCheck
+ { name: 'consumer2', cat: 'foo', pid: 70, tid: 72, ts: 870, ph: 'X', dur: 1000, bind_id: '0xaaa', flow_in: true} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importFlowV2MultipleProducers', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 1);
+ }
+
+ // Flow V2: multiple flow producers, which is not allowed
+ const events = [
+ { name: 'producer1', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100, bind_id: '0xaaa', flow_out: true}, // @suppress longLineCheck
+ { name: 'producer2', cat: 'foo', pid: 52, tid: 54, ts: 567, ph: 'X', dur: 100, bind_id: '0xaaa', flow_out: true}, // @suppress longLineCheck
+ { name: 'consumer', cat: 'foo', pid: 70, tid: 71, ts: 770, ph: 'X', dur: 1000, bind_id: '0xaaa', flow_in: true} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ // This test creates a flow event that stops on the same timestamp that
+ // the 'X' event which it triggers begins.
+ test('importFlowEventOverlaps', function() {
+ function checkModel(m) {
+ const startT = m.processes[52].threads[53];
+ const endT = m.processes[70].threads[71];
+
+ assert.isDefined(startT);
+ assert.strictEqual(startT.sliceGroup.slices.length, 1);
+
+ assert.isDefined(endT);
+ assert.strictEqual(endT.sliceGroup.slices.length, 1);
+
+ assert.strictEqual(m.flowEvents.length, 1);
+
+ // f0 represents 's' to 'f'
+ const f0 = m.flowEvents[0];
+
+ assert.strictEqual(f0.title, 'PostTask');
+ assert.strictEqual(f0.category, 'foo');
+ assert.strictEqual(f0.id, 72);
+ assert.strictEqual(f0.start, .548);
+ assert.closeTo(32 / 1000, f0.duration, 1e-5);
+ assert.strictEqual(f0.startSlice.title, 'SomeTask');
+ assert.deepEqual(f0.startSlice.outFlowEvents, [f0]);
+ assert.strictEqual(f0.endSlice.title, 'RunTask');
+ assert.deepEqual(f0.endSlice.inFlowEvents, [f0]);
+
+ // TODO(nduca): Add assertions about the flow slices, esp that they were
+ // found correctly.
+ }
+
+ const events = [
+ { name: 'SomeTask', cat: 'foo', pid: 52, tid: 53, ts: 547, ph: 'X', dur: 100}, // @suppress longLineCheck
+ { name: 'PostTask', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {}}, // @suppress longLineCheck
+
+ { name: 'PostTask', cat: 'foo', id: 72, pid: 70, tid: 71, ts: 580, ph: 'f', args: { 'queue_duration': 0}}, // @suppress longLineCheck
+ // Note that RunTask has the same time-stamp as PostTask 'f'
+ { name: 'RunTask', cat: 'foo', pid: 70, tid: 71, ts: 580, ph: 'X', args: {'src_func': 'PostRunTask'}, dur: 1000} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('importOutOfOrderFlowEvent', function() {
+ function checkModel(m) {
+ const expected = [0.4, 0.0, 0.412];
+ assert.strictEqual(m.flowIntervalTree.size, 3);
+
+ const order = m.flowEvents.map(function(x) { return x.start; });
+ for (let i = 0; i < expected.length; ++i) {
+ assert.closeTo(expected[i], order[i], 1e-5);
+ }
+ }
+
+ const events = [
+ { name: 'SomeTask', cat: 'foo', pid: 52, tid: 53, ts: 548, ph: 'X', dur: 10}, // @suppress longLineCheck
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {} }, // @suppress longLineCheck
+
+ { name: 'SomeTask', cat: 'foo', pid: 52, tid: 53, ts: 148, ph: 'X', dur: 10}, // @suppress longLineCheck
+ { name: 'b', cat: 'foo', id: 73, pid: 52, tid: 53, ts: 148, ph: 's', args: {} }, // @suppress longLineCheck
+
+ { name: 'b', cat: 'foo', id: 73, pid: 52, tid: 53, ts: 570, ph: 'f', args: {} }, // @suppress longLineCheck
+ { name: 'SomeTask', cat: 'foo', pid: 52, tid: 53, ts: 571, ph: 'X', dur: 10}, // @suppress longLineCheck
+
+ { name: 'SomeTask', cat: 'foo', pid: 52, tid: 53, ts: 560, ph: 'X', dur: 10}, // @suppress longLineCheck
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 560, ph: 't', args: {} }, // @suppress longLineCheck
+
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 580, ph: 'f', args: {} }, // @suppress longLineCheck
+ { name: 'SomeTask', cat: 'foo', pid: 52, tid: 53, ts: 581, ph: 'X', dur: 10} // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importCompleteEvent', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[52];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.slices.length, 3);
+ assert.strictEqual(t.tid, 53);
+
+ let slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'baz');
+ assert.closeTo(0, slice.start, 1e-5);
+ assert.closeTo(1 / 1000, slice.duration, 1e-5);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ slice = t.sliceGroup.slices[1];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.category, 'foo');
+ assert.closeTo((730 - 629) / 1000, slice.start, 1e-5);
+ assert.closeTo(20 / 1000, slice.duration, 1e-5);
+ assert.strictEqual(slice.subSlices.length, 1);
+
+ slice = t.sliceGroup.slices[2];
+ assert.strictEqual(slice.title, 'c');
+ assert.isTrue(slice.didNotFinish);
+ assert.closeTo(10 / 1000, slice.duration, 1e-5);
+ }
+
+ const events = [
+ { name: 'a', args: {}, pid: 52, ts: 629, dur: 1, cat: 'baz', tid: 53, ph: 'X' }, // @suppress longLineCheck
+ { name: 'b', args: {}, pid: 52, ts: 730, dur: 20, cat: 'foo', tid: 53, ph: 'X' }, // @suppress longLineCheck
+ { name: 'c', args: {}, pid: 52, ts: 740, cat: 'baz', tid: 53, ph: 'X' }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importFlowEventsWithStackFrame', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.flowEvents.length, 2);
+
+ const f0 = m.flowEvents[0];
+ assert.strictEqual(f0.startStackFrame.title, 'fn1');
+ assert.strictEqual(f0.endStackFrame.title, 'fn2');
+
+ const f1 = m.flowEvents[1];
+ assert.strictEqual(f1.startStackFrame.title, 'fn2');
+ assert.strictEqual(f1.endStackFrame.title, 'fn3');
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'aSlice', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 547, ph: 'B', args: {} }, // @suppress longLineCheck
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 548, ph: 's', args: {}, sf: 1 }, // @suppress longLineCheck
+ { id: 72, pid: 52, tid: 53, ts: 549, ph: 'E', args: {} }, // @suppress longLineCheck
+
+ { name: 'bSlice', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 559, ph: 'B', args: {} }, // @suppress longLineCheck
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 560, ph: 't', args: {}, sf: 2 }, // @suppress longLineCheck
+ { id: 72, pid: 52, tid: 53, ts: 561, ph: 'E', args: {} }, // @suppress longLineCheck
+
+ { name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 580, ph: 'f', args: {}, sf: 3 }, // @suppress longLineCheck
+ { name: 'cSlice', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 581, ph: 'B', args: {} }, // @suppress longLineCheck
+ { id: 72, pid: 52, tid: 53, ts: 582, ph: 'E', args: {} } // @suppress longLineCheck
+ ],
+ stackFrames: {
+ '1': {
+ category: 'm1',
+ name: 'fn1'
+ },
+ '2': {
+ category: 'm2',
+ name: 'fn2'
+ },
+ '3': {
+ category: 'm3',
+ name: 'fn3'
+ }
+ }
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importCompleteEventWithCpuDuration', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.numProcesses, 1);
+ const p = m.processes[52];
+ assert.isDefined(p);
+
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[53];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.slices.length, 3);
+ assert.strictEqual(t.tid, 53);
+
+ let slice = t.sliceGroup.slices[0];
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.category, 'baz');
+ assert.closeTo(0, slice.start, 1e-5);
+ assert.closeTo(1 / 1000, slice.duration, 1e-5);
+ assert.closeTo(12 / 1000, slice.cpuStart, 1e-5);
+ assert.closeTo(1 / 1000, slice.cpuDuration, 1e-5);
+ assert.strictEqual(slice.subSlices.length, 0);
+
+ slice = t.sliceGroup.slices[1];
+ assert.strictEqual(slice.title, 'b');
+ assert.strictEqual(slice.category, 'foo');
+ assert.closeTo((730 - 629) / 1000, slice.start, 1e-5);
+ assert.closeTo(20 / 1000, slice.duration, 1e-5);
+ assert.closeTo(110 / 1000, slice.cpuStart, 1e-5);
+ assert.closeTo(16 / 1000, slice.cpuDuration, 1e-5);
+ assert.strictEqual(slice.subSlices.length, 1);
+
+ slice = t.sliceGroup.slices[2];
+ assert.strictEqual(slice.title, 'c');
+ assert.isTrue(slice.didNotFinish);
+ assert.closeTo(10 / 1000, slice.duration, 1e-5);
+ }
+
+ const events = [
+ { name: 'a', args: {}, pid: 52, ts: 629, dur: 1, cat: 'baz', tid: 53, ph: 'X', tts: 12, tdur: 1 }, // @suppress longLineCheck
+ { name: 'b', args: {}, pid: 52, ts: 730, dur: 20, cat: 'foo', tid: 53, ph: 'X', tts: 110, tdur: 16 }, // @suppress longLineCheck
+ { name: 'c', args: {}, pid: 52, ts: 740, cat: 'baz', tid: 53, ph: 'X', tts: 115 } // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importNestedCompleteEventWithTightBounds', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+
+ const sA = findSliceNamed(t.sliceGroup, 'a');
+ const sB = findSliceNamed(t.sliceGroup, 'b');
+
+ assert.strictEqual(sA.title, 'a');
+ assert.strictEqual(sA.category, 'baz');
+ assert.strictEqual(sA.start, 244654227.065);
+ assert.strictEqual(sA.duration, 36.075);
+ assert.closeTo(0.03, sA.selfTime, 1e-5);
+
+ assert.strictEqual(sB.title, 'b');
+ assert.strictEqual(sB.category, 'foo');
+ assert.strictEqual(sB.start, 244654227.095);
+ assert.strictEqual(sB.duration, 36.045);
+
+ assert.strictEqual(sA.subSlices.length, 1);
+ assert.strictEqual(sA.subSlices[0], sB);
+ assert.strictEqual(sB.parentSlice, sA);
+ }
+
+ const events = [
+ { name: 'a', args: {}, pid: 52, ts: 244654227065, dur: 36075, cat: 'baz', tid: 53, ph: 'X' }, // @suppress longLineCheck
+ { name: 'b', args: {}, pid: 52, ts: 244654227095, dur: 36045, cat: 'foo', tid: 53, ph: 'X' } // @suppress longLineCheck
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+
+ test('importCompleteEventWithStackFrame', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[2];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.slices.length, 2);
+
+ const s0 = t.sliceGroup.slices[0];
+ assert.strictEqual(s0.startStackFrame.title, 'frame7');
+ assert.isUndefined(s0.endStackFrame);
+
+ const s1 = t.sliceGroup.slices[1];
+ assert.strictEqual(s1.startStackFrame.title, 'frame8');
+ assert.strictEqual(s1.endStackFrame.title, 'frame9');
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'a', args: {}, pid: 1, ts: 0, dur: 1, cat: 'baz', tid: 2, ph: 'X', sf: 7 }, // @suppress longLineCheck
+ { name: 'b', args: {}, pid: 1, ts: 5, dur: 1, cat: 'baz', tid: 2, ph: 'X', sf: 8, esf: 9 } // @suppress longLineCheck
+ ],
+ stackFrames: {
+ '1': {
+ category: 'm1',
+ name: 'main'
+ },
+ '7': {
+ category: 'm2',
+ name: 'frame7',
+ parent: '1'
+ },
+ '8': {
+ category: 'm2',
+ name: 'frame8',
+ parent: '1'
+ },
+ '9': {
+ category: 'm2',
+ name: 'frame9',
+ parent: '1'
+ }
+ }
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importAsyncEventWithSameTimestamp', function() {
+ function checkModel(m) {
+ const t = m.processes[52].threads[53];
+
+ assert.strictEqual(t.asyncSliceGroup.slices.length, 1);
+ const parentSlice = t.asyncSliceGroup.slices[0];
+ assert.strictEqual(parentSlice.title, 'a');
+ assert.strictEqual(parentSlice.category, 'foo');
+ assert.isTrue(parentSlice.isTopLevel);
+
+ assert.isDefined(parentSlice.subSlices);
+ const subSlices = parentSlice.subSlices;
+ assert.strictEqual(subSlices.length, 1000);
+ // Slices should be sorted according to 'ts'. And if 'ts' is the same,
+ // slices should keep the order that they were recorded.
+ for (let i = 0; i < 1000; i++) {
+ assert.strictEqual(i + 1, subSlices[i].args.seq);
+ assert.isFalse(subSlices[i].isTopLevel);
+ }
+ }
+
+ const events = [];
+ // Events are added with ts 0, 1, 1, 2, 2, 3, 3 ...500, 500, 1000
+ // and use 'seq' to track the order of when the event is recorded.
+ events.push({name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 0, ph: 'S', args: {'seq': 0}}); // @suppress longLineCheck
+
+ for (let i = 1; i <= 1000; i++) {
+ events.push({name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: Math.round(i / 2), ph: 'T', args: {'seq': i}}); // @suppress longLineCheck
+ }
+
+ events.push({name: 'a', cat: 'foo', id: 72, pid: 52, tid: 53, ts: 1000, ph: 'F', args: {'seq': 1001}}); // @suppress longLineCheck
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('sampleDataSimple', function() {
+ function checkModel(m) {
+ assert.isDefined(m.kernel.cpus[0]);
+ assert.strictEqual(m.getAllThreads().length, 1);
+
+ assert.strictEqual(m.samples.length, 3);
+
+ const t1 = m.processes[1].threads[1];
+ assert.strictEqual(t1.samples.length, 3);
+
+ const c0 = m.kernel.cpus[0];
+ const c1 = m.kernel.cpus[1];
+ assert.strictEqual(c0.samples.length, 2);
+ assert.strictEqual(c1.samples.length, 1);
+
+ assert.strictEqual(m.samples[0].cpu, c0);
+ assert.strictEqual(m.samples[0].thread, t1);
+ assert.strictEqual(m.samples[0].title, 'cycles:HG');
+ assert.strictEqual(m.samples[0].start, 1);
+ assert.deepEqual(
+ ['a_sub', 'a', 'main'],
+ m.samples[0].userFriendlyStack
+ .map(x => x.substr(0, x.indexOf('url') - 1)));
+ assert.strictEqual(m.samples[0].weight, 1);
+ }
+
+ const events = {
+ 'traceEvents': [],
+ 'stackFrames': {
+ '1': {
+ 'category': 'mod',
+ 'name': 'main'
+ },
+ '2': {
+ 'category': 'mod',
+ 'name': 'a',
+ 'parent': 1
+ },
+ '3': {
+ 'category': 'mod',
+ 'name': 'a_sub',
+ 'parent': 2
+ },
+ '4': {
+ 'category': 'mod',
+ 'name': 'b',
+ 'parent': 1
+ }
+ },
+ 'samples': [
+ {
+ 'cpu': 0, 'tid': 1, 'ts': 1000.0,
+ 'name': 'cycles:HG', 'sf': 3, 'weight': 1
+ },
+ {
+ 'cpu': 0, 'tid': 1, 'ts': 2000.0,
+ 'name': 'cycles:HG', 'sf': 2, 'weight': 1
+ },
+ {
+ 'cpu': 1, 'tid': 1, 'ts': 3000.0,
+ 'name': 'cycles:HG', 'sf': 3, 'weight': 1
+ }
+ ]
+ };
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('importMemoryDumps_verifyProcessAndGlobalMemoryDumpLinks', function() {
+ function checkModel(m) {
+ const p1 = m.getProcess(42);
+ const p2 = m.getProcess(43);
+ assert.isDefined(p1);
+ assert.isDefined(p2);
+
+ // Check that Model and Process objects contain the right dumps.
+ assert.strictEqual(m.globalMemoryDumps.length, 2);
+ assert.strictEqual(p1.memoryDumps.length, 2);
+ assert.strictEqual(p2.memoryDumps.length, 1);
+
+ assert.strictEqual(m.globalMemoryDumps[0].start, 10);
+ assert.strictEqual(p1.memoryDumps[0].start, 10);
+ assert.strictEqual(p2.memoryDumps[0].start, 11);
+ assert.strictEqual(m.globalMemoryDumps[0].duration, 1);
+ assert.strictEqual(p1.memoryDumps[0].duration, 0);
+ assert.strictEqual(p2.memoryDumps[0].duration, 0);
+
+ assert.strictEqual(m.globalMemoryDumps[1].start, 13);
+ assert.strictEqual(p1.memoryDumps[1].start, 13);
+ assert.strictEqual(m.globalMemoryDumps[1].duration, 0);
+ assert.strictEqual(p1.memoryDumps[1].duration, 0);
+
+ // Check that GlobalMemoryDump and ProcessMemoryDump objects are
+ // interconnected correctly.
+ assert.strictEqual(p1.memoryDumps[0],
+ m.globalMemoryDumps[0].processMemoryDumps[42]);
+ assert.strictEqual(p2.memoryDumps[0],
+ m.globalMemoryDumps[0].processMemoryDumps[43]);
+ assert.strictEqual(
+ p1.memoryDumps[0].globalMemoryDump, m.globalMemoryDumps[0]);
+ assert.strictEqual(
+ p2.memoryDumps[0].globalMemoryDump, m.globalMemoryDumps[0]);
+
+ assert.strictEqual(p1.memoryDumps[1],
+ m.globalMemoryDumps[1].processMemoryDumps[42]);
+ assert.strictEqual(
+ p1.memoryDumps[1].globalMemoryDump, m.globalMemoryDumps[1]);
+ }
+
+ const events = [
+ // 2 process memory dump events.
+ {
+ name: 'a',
+ pid: 42,
+ ts: 10000,
+ cat: 'test',
+ tid: 53,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '100'
+ }
+ }
+ }
+ },
+ {
+ name: 'b',
+ pid: 43,
+ ts: 11000,
+ cat: 'test',
+ tid: 54,
+ ph: 'v',
+ id: '0x0001',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '200'
+ }
+ }
+ }
+ },
+ // 1 process memory dump event.
+ {
+ name: 'd',
+ pid: 42,
+ ts: 13000,
+ cat: 'test',
+ tid: 56,
+ ph: 'v',
+ id: '0xfffffff12345678',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '300'
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('importMemoryDumps_totalResidentBytesOnly', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const d = p.memoryDumps[0];
+
+ assert.strictEqual(d.totals.residentBytes, 9007199254740991);
+ assert.isUndefined(d.totals.peakResidentBytes);
+ assert.isUndefined(d.totals.arePeakResidentBytesResettable);
+ assert.isUndefined(d.totals.platformSpecific);
+ assert.isUndefined(d.mostRecentVmRegions);
+ assert.lengthOf(d.memoryAllocatorDumps, 0);
+ }
+
+ const events = [
+ {
+ pid: 42,
+ ts: 10,
+ ph: 'v',
+ id: '0x01',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '1fffffffffffff'
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_withPeakResidentBytes', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const d = p.memoryDumps[0];
+
+ assert.strictEqual(d.totals.residentBytes, 9007199254740991);
+ assert.strictEqual(d.totals.peakResidentBytes, 13510798882111488);
+ assert.isTrue(d.totals.arePeakResidentBytesResettable);
+ assert.isUndefined(d.totals.platformSpecific);
+ assert.isUndefined(d.mostRecentVmRegions);
+ assert.lengthOf(d.memoryAllocatorDumps, 0);
+ }
+
+ const events = [
+ {
+ pid: 42,
+ ts: 10,
+ ph: 'v',
+ id: '0x01',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '1fffffffffffff',
+ peak_resident_set_bytes: '2fffffffffffff',
+ is_peak_rss_resetable: true
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_platformSpecificTotals', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const d = p.memoryDumps[0];
+
+ assert.strictEqual(d.totals.residentBytes, 9007199254740991);
+ assert.isUndefined(d.totals.peakResidentBytes);
+ assert.isUndefined(d.totals.arePeakResidentBytesResettable);
+ assert.deepEqual(d.totals.platformSpecific,
+ {private_bytes: 4503599627370495, shared_bytes: 4503599627370496});
+ assert.isUndefined(d.mostRecentVmRegions);
+ assert.lengthOf(d.memoryAllocatorDumps, 0);
+ }
+
+ const events = [
+ {
+ pid: 42,
+ ts: 10,
+ ph: 'v',
+ id: '0x01',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '1fffffffffffff',
+ private_bytes: 'fffffffffffff',
+ shared_bytes: '10000000000000'
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_vmRegions', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const d = p.memoryDumps[0];
+
+ checkVMRegions(d.vmRegions, [
+ {
+ startAddress: 240,
+ sizeInBytes: 336,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE,
+ mappedFile: '[stack:20310]',
+ byteStats: {
+ privateCleanResident: 64,
+ privateDirtyResident: 32,
+ sharedCleanResident: 256,
+ sharedDirtyResident: 0,
+ proportionalResident: 158,
+ swapped: 80
+ }
+ },
+ {
+ startAddress: 848,
+ sizeInBytes: 592,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ mappedFile: '/dev/ashmem/dalvik',
+ byteStats: {
+ proportionalResident: 205,
+ privateDirtyResident: 205,
+ swapped: 0
+ }
+ },
+ {
+ startAddress: 140673331539968,
+ sizeInBytes: 262144,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE |
+ VMRegion.PROTECTION_FLAG_MAYSHARE,
+ mappedFile: '/run/shm/.org.chromium.Chromium.sqqN11 (deleted)',
+ byteStats: {
+ privateCleanResident: 0,
+ privateDirtyResident: 262144,
+ sharedCleanResident: 0,
+ sharedDirtyResident: 0,
+ proportionalResident: 262144,
+ swapped: 0
+ }
+ }
+ ]);
+
+ assert.strictEqual(d.totals.residentBytes, 0);
+ assert.isUndefined(d.totals.peakResidentBytes);
+ assert.isUndefined(d.totals.arePeakResidentBytesResettable);
+ assert.isUndefined(d.totals.platformSpecific);
+ assert.lengthOf(d.memoryAllocatorDumps, 0);
+ }
+
+ const events = [
+ {
+ name: 'some_dump_name',
+ pid: 42,
+ ts: 10,
+ cat: 'test',
+ tid: 53,
+ ph: 'v',
+ id: '000',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '0'
+ },
+ process_mmaps: {
+ vm_regions: [
+ {
+ sa: 'f0',
+ sz: '150',
+ pf: 6,
+ mf: '[stack:20310]',
+ bs: {
+ pss: '9e',
+ pc: '40',
+ pd: '20',
+ sc: '100',
+ sd: '0',
+ sw: '50'
+ }
+ },
+ {
+ sa: '350',
+ sz: '250',
+ pf: 5,
+ mf: '/dev/ashmem/dalvik',
+ bs: {
+ pss: 'cd',
+ pd: 'cd',
+ sc: undefined,
+ sw: '0'
+ }
+ },
+ {
+ sa: '7ff10ff4b000',
+ sz: '40000',
+ pf: 134,
+ mf: '/run/shm/.org.chromium.Chromium.sqqN11 (deleted)',
+ bs: {
+ pss: '40000',
+ pc: '0',
+ pd: '40000',
+ sc: '0',
+ sd: '0',
+ sw: '0'
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_explicitMemoryAllocatorDumps', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const d = p.memoryDumps[0];
+
+ assert.strictEqual(d.memoryAllocatorDumps.length, 2);
+
+ const oilpanRoot = d.getMemoryAllocatorDumpByFullName('oilpan');
+ const v8Root = d.getMemoryAllocatorDumpByFullName('v8');
+ assert.isDefined(oilpanRoot);
+ assert.isDefined(v8Root);
+ assert.include(d.memoryAllocatorDumps, oilpanRoot);
+ assert.include(d.memoryAllocatorDumps, v8Root);
+
+ checkDumpNumericsAndDiagnostics(oilpanRoot, {
+ 'objects_count': new Scalar(unitlessNumber_smallerIsBetter, 47),
+ 'size': 32768,
+ 'effective_size': 32768,
+ 'inner_size': 4096
+ }, {});
+ assert.strictEqual(oilpanRoot.children.length, 2);
+
+ const oilpanBucket1 = d.getMemoryAllocatorDumpByFullName(
+ 'oilpan/heap2/bucket1');
+ assert.isDefined(oilpanBucket1);
+ assert.strictEqual(oilpanBucket1.fullName, 'oilpan/heap2/bucket1');
+ assert.strictEqual(oilpanBucket1.name, 'bucket1');
+ checkDumpNumericsAndDiagnostics(oilpanBucket1, {
+ 'objects_count': new Scalar(unitlessNumber_smallerIsBetter, 31),
+ 'size': 8192,
+ 'effective_size': 8192,
+ 'inner_size': 8192
+ }, {});
+ assert.strictEqual(oilpanBucket1.children.length, 0);
+
+ assert.isDefined(oilpanBucket1.parent);
+ assert.strictEqual(oilpanBucket1.parent.fullName, 'oilpan/heap2');
+ assert.strictEqual(oilpanBucket1.parent.name, 'heap2');
+ assert.include(oilpanBucket1.parent.children, oilpanBucket1);
+
+ assert.isDefined(oilpanBucket1.parent.parent);
+ assert.strictEqual(oilpanBucket1.parent.parent, oilpanRoot);
+
+ assert.strictEqual(d.totals.residentBytes, 256);
+ assert.isUndefined(d.totals.peakResidentBytes);
+ assert.isUndefined(d.totals.arePeakResidentBytesResettable);
+ assert.isUndefined(d.totals.platformSpecific);
+ assert.isUndefined(d.mostRecentVmRegions);
+ }
+
+ const events = [
+ {
+ name: 'a',
+ pid: 42,
+ ts: 10,
+ cat: 'test',
+ tid: 53,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '100'
+ },
+ allocators: {
+ 'oilpan': {
+ guid: '1a',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '2f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '1000'},
+ size: {type: 'scalar', units: 'bytes', value: '8000'}
+ }
+ },
+ 'oilpan/heap1': {
+ guid: '2b',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '3f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '3000'},
+ size: {type: 'scalar', units: 'bytes', value: '4000'}
+ }
+ },
+ 'oilpan/heap2': {
+ guid: '3c',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '4f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '4000'},
+ size: {type: 'scalar', units: 'bytes', value: '4000'}
+ }
+ },
+ 'oilpan/heap2/bucket1': {
+ // Deliberately missing GUID (to check that the importer does
+ // not skip memory allocator dump without GUID).
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '1f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '2000'},
+ size: {type: 'scalar', units: 'bytes', value: '2000'}
+ }
+ },
+ 'v8': {
+ guid: '5e',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '5f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '5000'},
+ size: {type: 'scalar', units: 'bytes', value: '6000'}
+ }
+ }
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_implicitMemoryAllocatorDumps', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const d = p.memoryDumps[0];
+
+ assert.strictEqual(d.memoryAllocatorDumps.length, 2);
+
+ const oilpanRoot = d.getMemoryAllocatorDumpByFullName('oilpan');
+ const v8Root = d.getMemoryAllocatorDumpByFullName('v8');
+ assert.isDefined(oilpanRoot);
+ assert.isDefined(v8Root);
+ assert.include(d.memoryAllocatorDumps, oilpanRoot);
+ assert.include(d.memoryAllocatorDumps, v8Root);
+
+ checkDumpNumericsAndDiagnostics(oilpanRoot, {
+ 'objects_count': new Scalar(unitlessNumber_smallerIsBetter, 94),
+ 'size': 24576,
+ 'effective_size': 24576,
+ 'inner_size': 20480
+ }, {});
+ assert.strictEqual(oilpanRoot.children.length, 2);
+
+ const oilpanBucket1 = d.getMemoryAllocatorDumpByFullName(
+ 'oilpan/heap2/bucket1');
+ assert.isDefined(oilpanBucket1);
+ assert.strictEqual(oilpanBucket1.fullName, 'oilpan/heap2/bucket1');
+ assert.strictEqual(oilpanBucket1.name, 'bucket1');
+ checkDumpNumericsAndDiagnostics(oilpanBucket1, {
+ 'objects_count': new Scalar(unitlessNumber_smallerIsBetter, 31),
+ 'size': 8192,
+ 'effective_size': 8192,
+ 'inner_size': 8192
+ }, {});
+ assert.strictEqual(oilpanBucket1.children.length, 0);
+
+ assert.isDefined(oilpanBucket1.parent);
+ assert.strictEqual(oilpanBucket1.parent.fullName, 'oilpan/heap2');
+ assert.strictEqual(oilpanBucket1.parent.name, 'heap2');
+ assert.include(oilpanBucket1.parent.children, oilpanBucket1);
+
+ assert.isDefined(oilpanBucket1.parent.parent);
+ assert.strictEqual(oilpanBucket1.parent.parent, oilpanRoot);
+
+ assert.strictEqual(d.totals.residentBytes, 256);
+ assert.isUndefined(d.totals.peakResidentBytes);
+ assert.isUndefined(d.totals.arePeakResidentBytesResettable);
+ assert.isUndefined(d.totals.platformSpecific);
+ assert.isUndefined(d.mostRecentVmRegions);
+ }
+
+ const events = [
+ {
+ name: 'a',
+ pid: 42,
+ ts: 10,
+ cat: 'test',
+ tid: 53,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '100'
+ },
+ allocators: {
+ 'oilpan/heap1': {
+ guid: '999',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '3f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '3000'},
+ size: {type: 'scalar', units: 'bytes', value: '4000'}
+ }
+ },
+ 'oilpan/heap2/bucket1': {
+ guid: '888',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '1f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '2000'},
+ size: {type: 'scalar', units: 'bytes', value: '2000'}
+ }
+ },
+ 'v8': {
+ guid: '777',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '5f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '5000'},
+ size: {type: 'scalar', units: 'bytes', value: '6000'}
+ }
+ }
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_globalMemoryAllocatorDumps', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const gmd = m.globalMemoryDumps[0];
+ const pmd = p.memoryDumps[0];
+
+ assert.isUndefined(gmd.totals);
+ assert.strictEqual(pmd.totals.residentBytes, 256);
+ assert.isUndefined(pmd.totals.peakResidentBytes);
+ assert.isUndefined(pmd.totals.arePeakResidentBytesResettable);
+ assert.isUndefined(pmd.totals.platformSpecific);
+
+ assert.isUndefined(gmd.mostRecentVmRegions);
+ assert.isUndefined(pmd.mostRecentVmRegions);
+
+ assert.strictEqual(gmd.memoryAllocatorDumps.length, 1);
+ assert.strictEqual(pmd.memoryAllocatorDumps.length, 1);
+
+ // Global memory allocator dumps.
+ const sharedBitmapManager = gmd.getMemoryAllocatorDumpByFullName(
+ 'shared_bitmap_manager');
+ assert.isDefined(sharedBitmapManager);
+ assert.include(gmd.memoryAllocatorDumps, sharedBitmapManager);
+
+ checkDumpNumericsAndDiagnostics(sharedBitmapManager, {
+ 'objects_count': new Scalar(unitlessNumber_smallerIsBetter, 31),
+ 'size': 8192,
+ 'effective_size': 8192,
+ 'inner_size': 8192
+ }, {});
+ assert.lengthOf(sharedBitmapManager.children, 1);
+
+ const bitmap2 = gmd.getMemoryAllocatorDumpByFullName(
+ 'shared_bitmap_manager/bitmap2');
+ assert.isDefined(bitmap2);
+ assert.include(sharedBitmapManager.children, bitmap2);
+ assert.strictEqual(bitmap2.parent, sharedBitmapManager);
+
+ checkDumpNumericsAndDiagnostics(bitmap2, {
+ 'objects_count': new Scalar(unitlessNumber_smallerIsBetter, 31),
+ 'size': 8192,
+ 'effective_size': 8192,
+ 'inner_size': 8192
+ }, { 'weather': 'sunny' });
+ assert.lengthOf(bitmap2.children, 0);
+
+ assert.isUndefined(gmd.getMemoryAllocatorDumpByFullName('tile_manager'));
+ assert.isUndefined(
+ gmd.getMemoryAllocatorDumpByFullName('tile_manager/tile1'));
+
+ // Process memory allocator dumps.
+ const tileManagerRoot = pmd.getMemoryAllocatorDumpByFullName(
+ 'tile_manager');
+ assert.isDefined(tileManagerRoot);
+ assert.include(pmd.memoryAllocatorDumps, tileManagerRoot);
+ assert.isUndefined(tileManagerRoot.parent);
+
+ checkDumpNumericsAndDiagnostics(tileManagerRoot, {
+ 'objects_count': new Scalar(unitlessNumber_smallerIsBetter, 63),
+ 'size': 16384,
+ 'effective_size': 16384,
+ 'inner_size': 12288
+ }, {});
+ assert.lengthOf(tileManagerRoot.children, 1);
+
+ const tile1 = pmd.getMemoryAllocatorDumpByFullName(
+ 'tile_manager/tile1');
+ assert.isDefined(tile1);
+ assert.include(tileManagerRoot.children, tile1);
+ assert.strictEqual(tile1.parent, tileManagerRoot);
+
+ checkDumpNumericsAndDiagnostics(tile1, {
+ 'objects_count': new Scalar(unitlessNumber_smallerIsBetter, 63),
+ 'size': 16384,
+ 'effective_size': 16384,
+ 'inner_size': 12288
+ }, { 'weather': 'rainy' });
+ assert.lengthOf(tile1.children, 0);
+
+ assert.isUndefined(
+ pmd.getMemoryAllocatorDumpByFullName('shared_bitmap_manager'));
+ assert.isUndefined(
+ pmd.getMemoryAllocatorDumpByFullName(
+ 'shared_bitmap_manager/bitmap2'));
+ }
+
+ const events = [
+ {
+ name: 'a',
+ pid: 42,
+ ts: 10,
+ cat: 'test',
+ tid: 53,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '100'
+ },
+ allocators: {
+ 'tile_manager/tile1': {
+ guid: '21',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '3f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '3000'},
+ size: {type: 'scalar', units: 'bytes', value: '4000'},
+ weather: {type: 'string', units: '', value: 'rainy'}
+ }
+ },
+ 'global/shared_bitmap_manager/bitmap2': {
+ guid: '42',
+ attrs: {
+ objects_count: {
+ type: 'scalar', units: 'objects', value: '1f'
+ },
+ inner_size: {type: 'scalar', units: 'bytes', value: '2000'},
+ size: {type: 'scalar', units: 'bytes', value: '2000'},
+ weather: {type: 'string', units: '', value: 'sunny'}
+ }
+ }
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_memoryAllocatorDumpEdges', function() {
+ function checkModel(model) {
+ const browserProcess = model.getProcess(42);
+ const rendererProcess = model.getProcess(43);
+ const gpuProcess = model.getProcess(44);
+
+ assert.lengthOf(model.globalMemoryDumps, 1);
+ assert.lengthOf(browserProcess.memoryDumps, 1);
+ assert.lengthOf(rendererProcess.memoryDumps, 1);
+ assert.lengthOf(gpuProcess.memoryDumps, 1);
+
+ const globalDump = model.globalMemoryDumps[0];
+ const browserDump = browserProcess.memoryDumps[0];
+ const rendererDump = rendererProcess.memoryDumps[0];
+ const gpuDump = gpuProcess.memoryDumps[0];
+
+ // Global memory allocator dump.
+ assert.lengthOf(globalDump.memoryAllocatorDumps, 1);
+
+ const globalDumpShared = globalDump.getMemoryAllocatorDumpByFullName(
+ 'shared');
+ assert.isDefined(globalDumpShared);
+ assert.include(globalDump.memoryAllocatorDumps, globalDumpShared);
+ checkDumpNumericsAndDiagnostics(globalDumpShared, {
+ 'area': new Scalar(unitlessNumber_smallerIsBetter, 9)
+ }, { 'color': 'blue' });
+ assert.lengthOf(globalDumpShared.children, 0);
+ assert.isUndefined(globalDumpShared.parent);
+
+ assert.isUndefined(globalDumpShared.owns);
+ assert.lengthOf(globalDumpShared.ownedBy, 3);
+ assert.lengthOf(globalDumpShared.retains, 0);
+ assert.lengthOf(globalDumpShared.retainedBy, 0);
+
+ // Browser memory allocator dump.
+ assert.lengthOf(browserDump.memoryAllocatorDumps, 1);
+
+ const browserDumpLocal = browserDump.getMemoryAllocatorDumpByFullName(
+ 'local');
+ assert.isDefined(browserDumpLocal);
+ assert.include(browserDump.memoryAllocatorDumps, browserDumpLocal);
+ checkDumpNumericsAndDiagnostics(browserDumpLocal, {
+ 'area': new Scalar(unitlessNumber_smallerIsBetter, 9)
+ }, { 'color': 'blue', 'mood': 'very good' });
+ assert.lengthOf(browserDumpLocal.children, 0);
+ assert.isUndefined(browserDumpLocal.parent);
+
+ assert.isDefined(browserDumpLocal.owns);
+ assert.lengthOf(browserDumpLocal.ownedBy, 0);
+ assert.lengthOf(browserDumpLocal.retains, 0);
+ assert.lengthOf(browserDumpLocal.retainedBy, 0);
+
+ const browserDumpLocalOwnsLink = browserDumpLocal.owns;
+ assert.include(globalDumpShared.ownedBy, browserDumpLocalOwnsLink);
+ assert.strictEqual(browserDumpLocalOwnsLink.source, browserDumpLocal);
+ assert.strictEqual(browserDumpLocalOwnsLink.target, globalDumpShared);
+ assert.strictEqual(browserDumpLocalOwnsLink.importance, 0);
+
+ // Renderer memory allocator dump.
+ assert.lengthOf(rendererDump.memoryAllocatorDumps, 1);
+
+ const rendererDumpLocal = rendererDump.getMemoryAllocatorDumpByFullName(
+ 'local');
+ assert.isDefined(rendererDumpLocal);
+ assert.include(rendererDump.memoryAllocatorDumps, rendererDumpLocal);
+ checkDumpNumericsAndDiagnostics(rendererDumpLocal, {
+ 'area': new Scalar(unitlessNumber_smallerIsBetter, 9),
+ 'length': 3
+ }, { 'color': 'blue' });
+ assert.lengthOf(rendererDumpLocal.children, 0);
+ assert.isUndefined(rendererDumpLocal.parent);
+
+ assert.isDefined(rendererDumpLocal.owns);
+ assert.lengthOf(rendererDumpLocal.ownedBy, 0);
+ assert.lengthOf(rendererDumpLocal.retains, 0);
+ assert.lengthOf(rendererDumpLocal.retainedBy, 1);
+
+ const rendererDumpLocalOwnsLink = rendererDumpLocal.owns;
+ assert.include(globalDumpShared.ownedBy, rendererDumpLocalOwnsLink);
+ assert.strictEqual(rendererDumpLocalOwnsLink.source, rendererDumpLocal);
+ assert.strictEqual(rendererDumpLocalOwnsLink.target, globalDumpShared);
+ assert.strictEqual(rendererDumpLocalOwnsLink.importance, 1);
+
+ // GPU memory allocator dumps.
+ assert.lengthOf(gpuDump.memoryAllocatorDumps, 2);
+
+ const gpuDumpLocal1 = gpuDump.getMemoryAllocatorDumpByFullName('local1');
+ assert.isDefined(gpuDumpLocal1);
+ assert.include(gpuDump.memoryAllocatorDumps, gpuDumpLocal1);
+ checkDumpNumericsAndDiagnostics(gpuDumpLocal1, {
+ 'area': new Scalar(unitlessNumber_smallerIsBetter, 9)
+ }, { 'state': 'ON', 'color': 'blue' });
+ assert.lengthOf(gpuDumpLocal1.children, 0);
+ assert.isUndefined(gpuDumpLocal1.parent);
+
+ assert.isDefined(gpuDumpLocal1.owns);
+ assert.lengthOf(gpuDumpLocal1.ownedBy, 1);
+ assert.lengthOf(gpuDumpLocal1.retains, 1);
+ assert.lengthOf(gpuDumpLocal1.retainedBy, 0);
+
+ const gpuDumpLocal1OwnsLink = gpuDumpLocal1.owns;
+ assert.include(globalDumpShared.ownedBy, gpuDumpLocal1OwnsLink);
+ assert.strictEqual(gpuDumpLocal1OwnsLink.source, gpuDumpLocal1);
+ assert.strictEqual(gpuDumpLocal1OwnsLink.target, globalDumpShared);
+ assert.strictEqual(gpuDumpLocal1OwnsLink.importance, -1);
+
+ const gpuDumpLocal1RetainsLink = gpuDumpLocal1.retains[0];
+ assert.include(rendererDumpLocal.retainedBy, gpuDumpLocal1RetainsLink);
+ assert.strictEqual(gpuDumpLocal1RetainsLink.source, gpuDumpLocal1);
+ assert.strictEqual(gpuDumpLocal1RetainsLink.target, rendererDumpLocal);
+ assert.isUndefined(gpuDumpLocal1RetainsLink.importance);
+
+ const gpuDumpLocal2 = gpuDump.getMemoryAllocatorDumpByFullName('local2');
+ assert.isDefined(gpuDumpLocal2);
+ assert.include(gpuDump.memoryAllocatorDumps, gpuDumpLocal2);
+ checkDumpNumericsAndDiagnostics(gpuDumpLocal2, {
+ 'temperature': new Scalar(unitlessNumber_smallerIsBetter, 100)
+ }, {});
+ assert.lengthOf(gpuDumpLocal2.children, 0);
+ assert.isUndefined(gpuDumpLocal2.parent);
+
+ assert.isDefined(gpuDumpLocal2.owns);
+ assert.lengthOf(gpuDumpLocal2.ownedBy, 0);
+ assert.lengthOf(gpuDumpLocal2.retains, 0);
+ assert.lengthOf(gpuDumpLocal2.retainedBy, 0);
+
+ const gpuDumpLocal2OwnsLink = gpuDumpLocal2.owns;
+ assert.include(gpuDumpLocal1.ownedBy, gpuDumpLocal2OwnsLink);
+ assert.strictEqual(gpuDumpLocal2OwnsLink.source, gpuDumpLocal2);
+ assert.strictEqual(gpuDumpLocal2OwnsLink.target, gpuDumpLocal1);
+ assert.strictEqual(gpuDumpLocal2OwnsLink.importance, 1);
+ }
+
+ const events = [
+ {
+ name: 'browser',
+ pid: 42,
+ ts: 10,
+ cat: 'test',
+ tid: 53,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '100'
+ },
+ allocators: {
+ 'local': {
+ guid: '3',
+ attrs: {
+ mood: {type: 'string', units: '', value: 'very good'}
+ }
+ },
+ 'global/shared': {
+ guid: '7',
+ attrs: {
+ color: {type: 'string', units: '', value: 'blue'}
+ }
+ }
+ },
+ allocators_graph: [
+ {
+ source: '3',
+ target: '7',
+ type: 'ownership',
+ importance: 0
+ }
+ ]
+ }
+ }
+ },
+ {
+ name: 'renderer',
+ pid: 43,
+ ts: 11,
+ cat: 'test',
+ tid: 53,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '200'
+ },
+ allocators: {
+ 'local': {
+ guid: '4',
+ attrs: {
+ length: {type: 'scalar', units: 'bytes', value: '3'}
+ }
+ },
+ 'global/shared': {
+ guid: '7',
+ attrs: {
+ area: {type: 'scalar', units: 'sq ft', value: '9'}
+ }
+ }
+ },
+ allocators_graph: [
+ {
+ source: '4',
+ target: '7',
+ type: 'ownership',
+ importance: 1
+ }
+ ]
+ }
+ }
+ },
+ {
+ name: 'gpu',
+ pid: 44,
+ ts: 10.5,
+ cat: 'test',
+ tid: 53,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '300'
+ },
+ allocators: {
+ 'local1': {
+ guid: '5',
+ attrs: {
+ state: {type: 'string', units: '', value: 'ON'}
+ }
+ },
+ 'local2': {
+ guid: '6',
+ attrs: {
+ temperature: {type: 'scalar', units: 'C', value: '64'}
+ }
+ }
+ },
+ allocators_graph: [
+ {
+ source: '5',
+ target: '7',
+ type: 'ownership',
+ importance: -1
+ },
+ {
+ source: '6',
+ target: '5',
+ type: 'ownership',
+ importance: 1
+ },
+ {
+ source: '5',
+ target: '4',
+ type: 'retention'
+ }
+ ]
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_memoryAllocatorDumpsMissingFields', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const d = p.memoryDumps[0];
+
+ assert.strictEqual(d.memoryAllocatorDumps.length, 1);
+ const noCrashRoot = d.getMemoryAllocatorDumpByFullName('no_crash');
+ assert.lengthOf(noCrashRoot.children, 0);
+ checkDumpNumericsAndDiagnostics(noCrashRoot, {}, {});
+ assert.isUndefined(noCrashRoot.parent);
+ assert.isUndefined(noCrashRoot.guid);
+ }
+
+ const events = [
+ {
+ name: 'a',
+ pid: 42,
+ ts: 10,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ allocators: {
+ 'no_crash': {
+ /* Missing GUID and attributes. */
+ }
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_weakMemoryAllocatorDumps', function() {
+ function checkModel(m) {
+ const p = m.getProcess(42);
+ const d = p.memoryDumps[0];
+ const memoryAllocatorDumps = d.memoryAllocatorDumps;
+ assert.lengthOf(memoryAllocatorDumps, 6);
+
+ function checkDump(dump, expectedFullName, expectedGuid, expectedParent,
+ expectedChildCount, expectedOwnsLink, expectedOwnedByLinkCount) {
+ assert.strictEqual(dump.fullName, expectedFullName);
+ assert.strictEqual(dump.guid, expectedGuid);
+ assert.strictEqual(dump.parent, expectedParent);
+ assert.lengthOf(dump.children, expectedChildCount);
+ assert.strictEqual(dump.owns, expectedOwnsLink);
+ assert.lengthOf(dump.ownedBy, expectedOwnedByLinkCount);
+ assert.strictEqual(
+ d.getMemoryAllocatorDumpByFullName(expectedFullName), dump);
+ }
+
+ function checkOwnsLink(ownerDump, expectedTarget) {
+ assert.strictEqual(ownerDump.owns.source, ownerDump);
+ assert.strictEqual(ownerDump.owns.target, expectedTarget);
+ }
+
+ // Check root_sink/* dumps.
+ const rootSink = d.memoryAllocatorDumps[3];
+ checkDump(rootSink, 'root_sink', '100', undefined, 1, undefined, 2);
+ const childSink = rootSink.children[0];
+ checkDump(childSink, 'root_sink/child_sink', '200', rootSink, 1,
+ undefined, 1);
+ const descendantSink = childSink.children[0];
+ checkDump(descendantSink, 'root_sink/child_sink/descendant_sink', '300',
+ childSink, 0, undefined, 2);
+
+ // Check strong_root/* dumps.
+ const strongRoot = d.memoryAllocatorDumps[4];
+ checkDump(strongRoot, 'strong_root', '4', undefined, 0,
+ rootSink.ownedBy[0], 0);
+
+ // Check inferred_strong_root/* dumps.
+ const inferredStrongRoot = d.memoryAllocatorDumps[0];
+ checkDump(inferredStrongRoot, 'inferred_strong_root', undefined,
+ undefined, 1, undefined, 0);
+ const child2Strong = inferredStrongRoot.children[0];
+ checkDump(child2Strong, 'inferred_strong_root/child2_strong', '9',
+ inferredStrongRoot, 0, childSink.ownedBy[0], 0);
+
+ // Check inferred_strong_root2/* dumps.
+ const inferredStrongRoot2 = d.memoryAllocatorDumps[1];
+ checkDump(inferredStrongRoot2, 'inferred_strong_root2', undefined,
+ undefined, 1, undefined, 0);
+ const inferredStrongChild = inferredStrongRoot2.children[0];
+ checkDump(inferredStrongChild,
+ 'inferred_strong_root2/inferred_strong_child', undefined,
+ inferredStrongRoot2, 2, undefined, 0);
+ const desc1Strong = inferredStrongChild.children[0];
+ checkDump(desc1Strong,
+ 'inferred_strong_root2/inferred_strong_child/desc1_strong', '11',
+ inferredStrongChild, 0, descendantSink.ownedBy[0], 0);
+ const desc3Strong = inferredStrongChild.children[1];
+ checkDump(desc3Strong,
+ 'inferred_strong_root2/inferred_strong_child/desc3_strong', '13',
+ inferredStrongChild, 0, descendantSink.ownedBy[1], 0);
+
+ // Check strong_root2/* dumps.
+ const strongRoot2 = d.memoryAllocatorDumps[5];
+ checkDump(strongRoot2, 'strong_root2', '15', undefined, 0,
+ rootSink.ownedBy[1], 0);
+
+ // Check inferred_strong_root3/* dumps.
+ const inferredStrongRoot3 = d.memoryAllocatorDumps[2];
+ checkDump(inferredStrongRoot3, 'inferred_strong_root3', undefined,
+ undefined, 0, undefined, 0);
+
+ // Check the links.
+ checkOwnsLink(strongRoot, rootSink);
+ checkOwnsLink(child2Strong, childSink);
+ checkOwnsLink(desc1Strong, descendantSink);
+ checkOwnsLink(desc3Strong, descendantSink);
+ checkOwnsLink(strongRoot2, rootSink);
+
+ // Check that the removed weak dumps are not indexed.
+ [
+ 'weak_root',
+ 'weak_root/removed_child',
+ 'weak_root/inferred_removed_child',
+ 'weak_root/inferred_removed_child/removed_descendant',
+ 'strong_root/weak_child',
+ 'strong_root/inferred_weak_child/weak_descendant',
+ 'inferred_weak_root',
+ 'inferred_weak_root/inferred_weak_child',
+ 'inferred_weak_root/inferred_weak_child/weak_descendant',
+ 'inferred_strong_root/child1_weak',
+ 'inferred_strong_root/child3_weak',
+ 'inferred_strong_root2/inferred_strong_child/desc2_weak',
+ 'inferred_strong_root2/weak_child',
+ 'strong_root2/weak_child',
+ 'strong_root2/removed_descendant',
+ 'removed_root',
+ 'removed_root/removed_child',
+ 'inferred_strong_root3/removed_child'
+ ].forEach(function(fullName) {
+ assert.isUndefined(d.getMemoryAllocatorDumpByFullName(fullName));
+ });
+ }
+
+ const events = [
+ {
+ pid: 42,
+ ts: 10,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ allocators: {
+ // Sinks for ownership edges (to check that the correct ownership
+ // edges are removed).
+ 'root_sink': { guid: '100', attrs: {} },
+ 'root_sink/child_sink': { guid: '200', attrs: {} },
+ 'root_sink/child_sink/descendant_sink': {
+ guid: '300', attrs: {}
+ },
+
+ // Note: 'removed' in the name of a dump means that the dump will
+ // be removed despite being non-weak (strong), e.g. due to one of
+ // its ancestors being weak.
+
+ // All descendants of a weak root dump should be removed.
+ 'weak_root': { guid: '1', attrs: {}, flags: 1 },
+ 'weak_root/removed_child': { guid: '2', attrs: {} },
+ 'weak_root/inferred_removed_child/removed_descendant': {
+ guid: '3', attrs: {}, flags: 0
+ },
+
+ // A strong root should be kept even if all its descendants are
+ // weak.
+ 'strong_root': { guid: '4', attrs: {}, flags: 0 },
+ 'strong_root/weak_child': { guid: '5', attrs: {}, flags: 1 },
+ 'strong_root/inferred_weak_child/weak_descendant': {
+ guid: '6', attrs: {}, flags: 1
+ },
+
+ // All inferred ancestors of a weak descendant should be marked
+ // weak and, consequently, removed (provided that they don't have
+ // any non-weak descendants).
+ 'inferred_weak_root/inferred_weak_child/weak_descendant': {
+ guid: '7', attrs: {}, flags: 1
+ },
+
+ // An inferred dump should be marked non-weak if it has at least
+ // one strong descendant.
+ 'inferred_strong_root/child1_weak': {
+ guid: '8', attrs: {}, flags: 1
+ },
+ 'inferred_strong_root/child2_strong': {
+ guid: '9', attrs: {}
+ },
+ 'inferred_strong_root/child3_weak': {
+ guid: '10', attrs: {}, flags: 1
+ },
+ 'inferred_strong_root2/inferred_strong_child/desc1_strong': {
+ guid: '11', attrs: {}
+ },
+ 'inferred_strong_root2/inferred_strong_child/desc2_weak': {
+ guid: '12', attrs: {}, flags: 1
+ },
+ 'inferred_strong_root2/inferred_strong_child/desc3_strong': {
+ guid: '13', attrs: {}
+ },
+ 'inferred_strong_root2/weak_child': {
+ guid: '14', attrs: {}, flags: 1
+ },
+
+ // A desdendant dump should be removed if it has a weak ancestor.
+ 'strong_root2': { guid: '15', attrs: {} },
+ 'strong_root2/weak_child': { guid: '16', attrs: {}, flags: 1 },
+ 'strong_root2/weak_child/removed_descendant': {
+ guid: '17', attrs: {}
+ },
+
+ // Check that "weakness" also propagates across ownership edges.
+ 'removed_root': { guid: '18', attrs: {} },
+ 'removed_root/removed_child': {
+ guid: '19', attrs: {}
+ },
+ 'inferred_strong_root3/removed_child': {
+ guid: '20', attrs: {}
+ },
+ },
+ allocators_graph: [
+ { source: '1', target: '100', type: 'ownership' },
+ { source: '2', target: '200', type: 'ownership' },
+ { source: '3', target: '300', type: 'ownership' },
+
+ { source: '4', target: '100', type: 'ownership' }, // Kept.
+ { source: '5', target: '200', type: 'ownership' },
+ { source: '6', target: '300', type: 'ownership' },
+
+ { source: '7', target: '300', type: 'ownership' },
+
+ { source: '8', target: '200', type: 'ownership' },
+ { source: '9', target: '200', type: 'ownership' }, // Kept.
+ { source: '10', target: '200', type: 'ownership' },
+ { source: '11', target: '300', type: 'ownership' }, // Kept.
+ { source: '12', target: '300', type: 'ownership' },
+ { source: '13', target: '300', type: 'ownership' }, // Kept.
+ { source: '14', target: '200', type: 'ownership' },
+
+ { source: '15', target: '100', type: 'ownership' }, // Kept.
+ { source: '16', target: '200', type: 'ownership' },
+ { source: '17', target: '300', type: 'ownership' },
+
+ { source: '18', target: '3' /* not a sink */, type: 'ownership' },
+ { source: '19', target: '200', type: 'ownership' },
+ { source: '20', target: '19' /* not a sink */, type: 'ownership' }
+ ]
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_levelsOfDetail', function() {
+ function checkLevelsOfDetail(pmdSpecifications, expectedGlobalLevelOfDetail,
+ expectedProcessLevelsOfDetail, expectedHasWarnings) {
+ function checkModel(model) {
+ // Check GlobalMemoryDump level of detail.
+ assert.lengthOf(model.globalMemoryDumps, 1);
+ assert.strictEqual(model.globalMemoryDumps[0].levelOfDetail,
+ expectedGlobalLevelOfDetail);
+
+ // Check ProcessMemoryDumps levels of detail.
+ assert.lengthOf(Object.keys(model.processes),
+ expectedProcessLevelsOfDetail.length);
+ for (let i = 0; i < expectedProcessLevelsOfDetail.length; i++) {
+ const process = model.getProcess(i);
+ assert.lengthOf(process.memoryDumps, 1);
+ assert.strictEqual(process.memoryDumps[0].levelOfDetail,
+ expectedProcessLevelsOfDetail[i]);
+ }
+
+ assert.strictEqual(model.hasImportWarnings, expectedHasWarnings);
+ }
+
+ const events = [];
+ pmdSpecifications.forEach(function(singlePmdSpecifications, pid) {
+ singlePmdSpecifications.forEach(function(singlePmdSpecification) {
+ const dumps = {};
+ if (singlePmdSpecification.levelOfDetail !== undefined) {
+ dumps.level_of_detail = singlePmdSpecification.levelOfDetail;
+ }
+ if (singlePmdSpecification.vmRegions) {
+ dumps.process_mmaps = {
+ vm_regions: [
+ { sa: 'f0', sz: '150', pf: 6, mf: '[stack]', bs: { pss: 'ff'} }
+ ]
+ };
+ }
+ events.push({
+ name: 'process_' + pid,
+ pid,
+ ts: 10,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps
+ }
+ });
+ });
+ });
+ checkParsedAndStreamInput(events, checkModel);
+ }
+
+ // Legacy trace events (without levels of detail).
+ checkLevelsOfDetail([[{}]], LIGHT, [LIGHT], false);
+ checkLevelsOfDetail([[{ vmRegions: true }]], DETAILED, [DETAILED], false);
+ checkLevelsOfDetail(
+ [
+ [{}] /* raw composable PMD1 events */,
+ [{}, {}] /* raw composable PMD2 events */
+ ],
+ LIGHT /* expected GMD level of detail */,
+ [LIGHT, LIGHT] /* expected PMD levels of detail */,
+ false /* no warnings expected */);
+ checkLevelsOfDetail(
+ [
+ [{}, { vmRegions: true }, {}],
+ [{ vmRegions: true }, {}]
+ ],
+ DETAILED, [DETAILED, DETAILED], false);
+
+ // Well-formed traces events (VM regions should be irrelevant).
+ checkLevelsOfDetail(
+ [
+ [{ levelOfDetail: 'light'}],
+ [{ levelOfDetail: 'light', vmRegions: true }]
+ ],
+ LIGHT, [LIGHT, LIGHT], false);
+ checkLevelsOfDetail(
+ [
+ [
+ { levelOfDetail: 'detailed' }, { levelOfDetail: 'detailed' }
+ ],
+ [
+ { levelOfDetail: 'detailed', vmRegions: true }
+ ],
+ [
+ { levelOfDetail: 'detailed' },
+ { levelOfDetail: 'detailed', vmRegions: true },
+ { levelOfDetail: 'detailed' }
+ ]
+ ],
+ DETAILED, [DETAILED, DETAILED, DETAILED], false);
+
+ // Not so well-formed trace events.
+ checkLevelsOfDetail(
+ [
+ [{}, { levelOfDetail: 'detailed'}, {}]
+ ],
+ DETAILED, [DETAILED], true);
+ checkLevelsOfDetail(
+ [
+ [{ levelOfDetail: 'light' }],
+ [{}],
+ [{ levelOfDetail: 'detailed' }],
+ [{ levelOfDetail: 'light' }]],
+ DETAILED, [LIGHT, LIGHT, DETAILED, LIGHT], true);
+ checkLevelsOfDetail(
+ [
+ [{ levelOfDetail: 'light' }, { levelOfDetail: 'detailed' }],
+ [{}],
+ [{ levelOfDetail: 'light' }, {}]],
+ DETAILED, [DETAILED, LIGHT, LIGHT], true);
+ checkLevelsOfDetail(
+ [
+ [{ levelOfDetail: 'invalid' }, { levelOfDetail: 'light' }],
+ [{ levelOfDetail: 'invalid' }]],
+ LIGHT, [LIGHT, LIGHT], true);
+ });
+
+ test('importMemoryDumps_heapDumps_oldFormat', function() {
+ function checkModel(m) {
+ const p1 = m.getProcess(21);
+ const p2 = m.getProcess(42);
+ assert.lengthOf(m.globalMemoryDumps, 2);
+ assert.lengthOf(p1.memoryDumps, 2);
+ assert.lengthOf(p2.memoryDumps, 1);
+
+ // Stack frames.
+ const frameIdToTitle = {};
+ for (const [id, f] of Object.entries(m.stackFrames)) {
+ frameIdToTitle[id] = f.title;
+ }
+ assert.deepEqual(
+ frameIdToTitle,
+ {
+ 'p21:0': 'FrameView::layout',
+ 'p21:0:self': '<self>',
+ 'p21:1': 'MessageLoop::RunTask',
+ 'p42::self': '<self>',
+ 'p42:0': 'MessageLoop::RunTask',
+ 'p42:0:self': '<self>',
+ 'p42:1': 'TimerBase::run',
+ 'p42:TWO': 'ScheduledAction::execute',
+ 'p42:3': 'FunctionCall',
+ 'p42:3:self': '<self>',
+ 'p42:4': 'UpdateLayoutTree',
+ 'p42:4:self': '<self>',
+ 'p42:5': 'MessageLoop::JogTask',
+ 'p42:5:self': '<self>'
+ });
+
+ // 1. Process 21, first dump.
+ const pmd1 = p1.memoryDumps[0];
+ const hds1 = pmd1.heapDumps;
+ assert.sameMembers(Object.keys(hds1), ['partition_alloc']);
+
+ const partitionAllocDump1 = hds1.partition_alloc;
+ assert.strictEqual(partitionAllocDump1.processMemoryDump, pmd1);
+ assert.strictEqual(partitionAllocDump1.allocatorName, 'partition_alloc');
+ const partitionAllocEntries1 = partitionAllocDump1.entries;
+ assert.lengthOf(partitionAllocEntries1, 2);
+ checkHeapEntry(partitionAllocEntries1[0], partitionAllocDump1, 4096,
+ undefined /* root */, undefined /* sum over all types */);
+ checkHeapEntry(partitionAllocEntries1[1], partitionAllocDump1, 2748,
+ ['<self>', 'FrameView::layout', 'MessageLoop::RunTask']);
+
+ // 2. Process 21, second dump.
+ const pmd2 = p1.memoryDumps[1];
+ const hds2 = pmd2.heapDumps;
+ assert.sameMembers(Object.keys(hds2), ['partition_alloc']);
+
+ const partitionAllocDump2 = hds2.partition_alloc;
+ assert.strictEqual(partitionAllocDump2.processMemoryDump, pmd2);
+ assert.strictEqual(partitionAllocDump2.allocatorName, 'partition_alloc');
+ const partitionAllocEntries2 = partitionAllocDump2.entries;
+ assert.lengthOf(partitionAllocEntries2, 2);
+ checkHeapEntry(partitionAllocEntries2[0], partitionAllocDump2, 8192,
+ undefined /* root */, undefined /* sum over all types */);
+ checkHeapEntry(partitionAllocEntries2[1], partitionAllocDump2, 3567,
+ ['<self>', 'FrameView::layout', 'MessageLoop::RunTask'],
+ undefined /* sum over all types */);
+
+ // All heap dumps in Process 21 should use the same stack frames.
+ assert.strictEqual(
+ getFrame(partitionAllocEntries1[1], 0),
+ getFrame(partitionAllocEntries2[1], 0));
+
+ // 3. Process 42.
+ const pmd3 = p2.memoryDumps[0];
+ const hds3 = pmd3.heapDumps;
+ assert.sameMembers(Object.keys(hds3), ['partition_alloc', 'malloc']);
+
+ const partitionAllocDump3 = hds3.partition_alloc;
+ assert.strictEqual(partitionAllocDump3.processMemoryDump, pmd3);
+ assert.strictEqual(partitionAllocDump3.allocatorName, 'partition_alloc');
+ const partitionAllocEntries3 = partitionAllocDump3.entries;
+ assert.lengthOf(partitionAllocEntries3, 6);
+ checkHeapEntry(partitionAllocEntries3[0], partitionAllocDump3, 3043272,
+ undefined /* root */, 'blink::Event');
+ checkHeapEntry(partitionAllocEntries3[1], partitionAllocDump3, 6086545,
+ undefined /* root */, undefined /* sum over all types */);
+ checkHeapEntry(partitionAllocEntries3[2], partitionAllocDump3, 1521636,
+ undefined /* root */, 'blink::ContextLifecycleObserver*');
+ checkHeapEntry(partitionAllocEntries3[3], partitionAllocDump3, 5991638,
+ ['<self>'], undefined /* sum over all types */);
+ checkHeapEntry(partitionAllocEntries3[4], partitionAllocDump3, 6384,
+ ['<self>', 'UpdateLayoutTree', 'TimerBase::run',
+ 'MessageLoop::RunTask'], undefined /* sum over all types */);
+ checkHeapEntry(partitionAllocEntries3[5], partitionAllocDump3, 58280,
+ ['<self>', 'FunctionCall', 'ScheduledAction::execute',
+ 'TimerBase::run', 'MessageLoop::RunTask'],
+ undefined /* sum over all types */);
+
+ const mallocDump3 = hds3.malloc;
+ assert.strictEqual(mallocDump3.processMemoryDump, pmd3);
+ assert.strictEqual(mallocDump3.allocatorName, 'malloc');
+ const mallocEntries3 = mallocDump3.entries;
+ assert.lengthOf(mallocEntries3, 4);
+ checkHeapEntry(mallocEntries3[0], mallocDump3, 1929, undefined /* root */,
+ undefined /* sum over all types */);
+ checkHeapEntry(mallocEntries3[1], mallocDump3, 291,
+ ['<self>', 'MessageLoop::RunTask'],
+ undefined /* sum over all types */);
+ checkHeapEntry(mallocEntries3[2], mallocDump3, 1110,
+ ['<self>', 'MessageLoop::JogTask'],
+ undefined /* sum over all types */);
+ checkHeapEntry(mallocEntries3[3], mallocDump3, 205, undefined /* root */,
+ 'blink::ContextLifecycleObserver*');
+
+ // All heap dumps in Process 42 should use the same stack frames.
+ assert.strictEqual(
+ getFrame(partitionAllocEntries3[5], 3),
+ getFrame(partitionAllocEntries3[4], 2));
+ assert.strictEqual(
+ getFrame(mallocEntries3[1], 1),
+ getFrame(partitionAllocEntries3[4], 3));
+ }
+
+ const events = [ // Intentionally shuffled.
+ {
+ pid: 21,
+ ts: 9,
+ ph: 'v',
+ id: '0123',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ heaps: {
+ partition_alloc: {
+ entries: [
+ { size: '1000' },
+ { bt: '0', size: 'abc' }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ pid: 42,
+ ph: 'M',
+ name: 'stackFrames',
+ cat: 'memory-infra',
+ args: {
+ stackFrames: {
+ '0': { name: 'MessageLoop::RunTask' },
+ '1': { name: 'TimerBase::run', parent: '0' },
+ 'TWO': { name: 'ScheduledAction::execute', parent: '1' },
+ '3': { name: 'FunctionCall', parent: 'TWO' },
+ '4': { name: 'UpdateLayoutTree', parent: '1' },
+ '5': { name: 'MessageLoop::JogTask' }
+ }
+ }
+ },
+ {
+ pid: 42,
+ ph: 'M',
+ name: 'typeNames',
+ cat: 'memory-infra',
+ args: {
+ typeNames: {
+ // GCC.
+ '22': '[unknown]',
+ '23': 'testing::ManuallyAnnotatedMockClass',
+ '24': 'const char* WTF::getStringWithTypeName() [with T = ' +
+ 'blink::Event]',
+ '25': 'blink::ContextLifecycleObserver*',
+ '26': 'const char* WTF::getStringWithTypeName() [with T = ' +
+ 'blink::WebFrame*]'
+ }
+ }
+ },
+ {
+ pid: 42,
+ ts: 10,
+ ph: 'v',
+ id: '0123',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '0'
+ },
+ heaps: {
+ partition_alloc: {
+ entries: [
+ { type: '24', size: '2e6fc8' },
+ { size: '5cdf91' },
+ { type: '25', size: '1737e4' },
+ { bt: '', size: '5b6cd6' },
+ { bt: '4', size: '18f0' },
+ { bt: '3', size: 'e3a8' }
+ ]
+ },
+ malloc: {
+ entries: [
+ { size: '789' },
+ { bt: '0', size: '123' },
+ { bt: '5', size: '456' },
+ { type: '25', size: 'cd' }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ pid: 21,
+ ph: 'M',
+ name: 'stackFrames',
+ cat: 'memory-infra',
+ args: {
+ stackFrames: {
+ // Intentionally in reverse order.
+ '0': { name: 'FrameView::layout', parent: '1' },
+ '1': { name: 'MessageLoop::RunTask' }
+ }
+ }
+ },
+ {
+ pid: 21,
+ ts: 12,
+ ph: 'v',
+ id: '0987',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ heaps: {
+ partition_alloc: {
+ entries: [
+ { size: '2000' },
+ { bt: '0', size: 'def' }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('importMemoryDumps_heapDumps_newFormat', function() {
+ function checkModel(m) {
+ const p1 = m.getProcess(21);
+ const p2 = m.getProcess(42);
+ const p3 = m.getProcess(63);
+ const p4 = m.getProcess(84);
+ assert.lengthOf(m.globalMemoryDumps, 2);
+ assert.lengthOf(p1.memoryDumps, 2);
+ assert.lengthOf(p2.memoryDumps, 1);
+ assert.lengthOf(p3.memoryDumps, 1);
+ assert.lengthOf(p4.memoryDumps, 1);
+
+ // Stack frames.
+ const frameIdToTitle = {};
+ for (const [id, f] of Object.entries(m.stackFrames)) {
+ frameIdToTitle[id] = f.title;
+ }
+ assert.deepEqual(
+ frameIdToTitle,
+ {
+ 'p21:0': 'FrameView::layout',
+ 'p21:A': '<self>',
+ 'p21:1': 'MessageLoop::RunTask',
+ 'p42:-1': '<self>',
+ 'p42:0': 'MessageLoop::RunTask',
+ 'p42:0.5': '<self>',
+ 'p42:1': 'TimerBase::run',
+ 'p42:TWO': 'ScheduledAction::execute',
+ 'p42:2.72': '<self>',
+ 'p42:3': 'FunctionCall',
+ 'p42:\u03C0': '<self>',
+ 'p42:4': 'UpdateLayoutTree',
+ 'p42:FOUR-AND-A-BIT': '<self>',
+ 'p42:5': 'MessageLoop::JogTask',
+ 'p42:NaN': '<self>',
+ 'p84:5': 'MessageLoop::WalkTask'
+ });
+
+ // 1. Process 21, first dump.
+ const pmd1 = p1.memoryDumps[0];
+ const hds1 = pmd1.heapDumps;
+ assert.sameMembers(Object.keys(hds1), ['partition_alloc']);
+
+ const partitionAllocDump1 = hds1.partition_alloc;
+ assert.strictEqual(partitionAllocDump1.processMemoryDump, pmd1);
+ assert.strictEqual(partitionAllocDump1.allocatorName, 'partition_alloc');
+ const partitionAllocEntries1 = partitionAllocDump1.entries;
+ assert.lengthOf(partitionAllocEntries1, 2);
+ checkHeapEntry(partitionAllocEntries1[0], partitionAllocDump1, 4096,
+ undefined /* root */,
+ 'class v8::FunctionCallbackInfo<class v8::Value>');
+ checkHeapEntry(partitionAllocEntries1[1], partitionAllocDump1, 2748,
+ ['<self>', 'FrameView::layout', 'MessageLoop::RunTask'],
+ undefined /* sum over all types */);
+
+ // 2. Process 21, second dump.
+ const pmd2 = p1.memoryDumps[1];
+ const hds2 = pmd2.heapDumps;
+ assert.sameMembers(Object.keys(hds2), ['partition_alloc']);
+
+ const partitionAllocDump2 = hds2.partition_alloc;
+ assert.strictEqual(partitionAllocDump2.processMemoryDump, pmd2);
+ assert.strictEqual(partitionAllocDump2.allocatorName, 'partition_alloc');
+ const partitionAllocEntries2 = partitionAllocDump2.entries;
+ assert.lengthOf(partitionAllocEntries2, 3);
+ checkHeapEntry(partitionAllocEntries2[0], partitionAllocDump2, 8192,
+ undefined /* root */, undefined /* sum over all types */);
+ checkHeapEntry(partitionAllocEntries2[1], partitionAllocDump2, 3567,
+ ['<self>', 'FrameView::layout', 'MessageLoop::RunTask'],
+ 'class v8::FunctionCallbackInfo<class v8::Value>');
+ checkHeapEntry(partitionAllocEntries2[2], partitionAllocDump2, 4095,
+ ['FrameView::layout', 'MessageLoop::RunTask'],
+ undefined /* sum over all types */);
+
+ // All heap dumps in Process 21 should use the same stack frames.
+ assert.strictEqual(
+ getFrame(partitionAllocEntries1[1], 0),
+ getFrame(partitionAllocEntries2[1], 0));
+ assert.strictEqual(
+ getFrame(partitionAllocEntries2[2], 0),
+ getFrame(partitionAllocEntries2[1], 1));
+
+ // 3. Process 42.
+ const pmd3 = p2.memoryDumps[0];
+ const hds3 = pmd3.heapDumps;
+ assert.sameMembers(Object.keys(hds3), ['partition_alloc', 'malloc']);
+
+ const partitionAllocDump3 = hds3.partition_alloc;
+ assert.strictEqual(partitionAllocDump3.processMemoryDump, pmd3);
+ assert.strictEqual(partitionAllocDump3.allocatorName, 'partition_alloc');
+ const partitionAllocEntries3 = partitionAllocDump3.entries;
+ assert.lengthOf(partitionAllocEntries3, 7);
+ checkHeapEntry(partitionAllocEntries3[0], partitionAllocDump3, 6086545,
+ undefined /* root */, undefined /* sum over all types */);
+ checkHeapEntry(partitionAllocEntries3[1], partitionAllocDump3, 3043272,
+ undefined /* root */, 'blink::Event');
+ checkHeapEntry(partitionAllocEntries3[2], partitionAllocDump3, 1521636,
+ undefined /* root */, 'blink::ContextLifecycleObserver *');
+ checkHeapEntry(partitionAllocEntries3[3], partitionAllocDump3, 5991638,
+ ['<self>'], '[unknown]');
+ checkHeapEntry(partitionAllocEntries3[4], partitionAllocDump3, 6384,
+ ['<self>', 'UpdateLayoutTree', 'TimerBase::run',
+ 'MessageLoop::RunTask'], undefined /* sum over all types */, 256);
+ checkHeapEntry(partitionAllocEntries3[5], partitionAllocDump3, 3192,
+ ['<self>', 'UpdateLayoutTree', 'TimerBase::run',
+ 'MessageLoop::RunTask'], 'blink::WebFrame *');
+ checkHeapEntry(partitionAllocEntries3[6], partitionAllocDump3, 58280,
+ ['<self>', 'FunctionCall', 'ScheduledAction::execute',
+ 'TimerBase::run', 'MessageLoop::RunTask'],
+ undefined /* sum over all types */);
+
+ const mallocDump3 = hds3.malloc;
+ assert.strictEqual(mallocDump3.processMemoryDump, pmd3);
+ assert.strictEqual(mallocDump3.allocatorName, 'malloc');
+ const mallocEntries3 = mallocDump3.entries;
+ assert.lengthOf(mallocEntries3, 4);
+ checkHeapEntry(mallocEntries3[0], mallocDump3, 1929, undefined /* root */,
+ undefined /* sum over all types */, 80);
+ checkHeapEntry(mallocEntries3[1], mallocDump3, 291,
+ ['<self>', 'MessageLoop::RunTask'],
+ undefined /* sum over all types */, 96);
+ checkHeapEntry(mallocEntries3[2], mallocDump3, 1110,
+ ['<self>', 'MessageLoop::JogTask'],
+ undefined /* sum over all types */, 112);
+ checkHeapEntry(mallocEntries3[3], mallocDump3, 205,
+ ['FunctionCall', 'ScheduledAction::execute', 'TimerBase::run',
+ 'MessageLoop::RunTask'], 'blink::ContextLifecycleObserver *', 128);
+
+ // All heap dumps in Process 42 should use the same stack frames.
+ assert.strictEqual(
+ getFrame(partitionAllocEntries3[5], 0),
+ getFrame(partitionAllocEntries3[4], 0));
+ assert.strictEqual(
+ getFrame(partitionAllocEntries3[6], 3),
+ getFrame(partitionAllocEntries3[4], 2));
+ assert.strictEqual(
+ getFrame(mallocEntries3[1], 1),
+ getFrame(partitionAllocEntries3[4], 3));
+ assert.strictEqual(
+ getFrame(mallocEntries3[3], 0),
+ getFrame(partitionAllocEntries3[6], 1));
+
+ // 4. Process 63.
+ const pmd4 = p3.memoryDumps[0];
+ const hds4 = pmd4.heapDumps;
+ assert.sameMembers(Object.keys(hds4), ['winheap']);
+
+ const winheapDump = hds4.winheap;
+ assert.strictEqual(winheapDump.processMemoryDump, pmd4);
+ assert.strictEqual(winheapDump.allocatorName, 'winheap');
+ const winheapEntries = winheapDump.entries;
+ assert.lengthOf(winheapEntries, 1);
+ checkHeapEntry(winheapEntries[0], winheapDump, 65536,
+ undefined /* root */, undefined /* sum over all types */);
+
+ // 5. Process 84.
+ const pmd5 = p4.memoryDumps[0];
+ const hds5 = pmd5.heapDumps;
+ assert.sameMembers(Object.keys(hds5), ['malloc']);
+
+ const mallocDump4 = hds5.malloc;
+ assert.strictEqual(mallocDump4.processMemoryDump, pmd5);
+ assert.strictEqual(mallocDump4.allocatorName, 'malloc');
+ const mallocEntries4 = mallocDump4.entries;
+ assert.lengthOf(mallocEntries4, 1);
+ checkHeapEntry(mallocEntries4[0], mallocDump4, 43981,
+ ['MessageLoop::WalkTask'], 'content::Manually');
+ }
+
+ const events = [ // Intentionally shuffled.
+ {
+ pid: 21,
+ ts: 9,
+ ph: 'v',
+ id: '0123',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ heaps: {
+ partition_alloc: {
+ entries: [
+ { bt: '', type: '25', size: '1000' },
+ { bt: 'A', size: 'abc' }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ pid: 42,
+ ph: 'M',
+ name: 'stackFrames',
+ cat: 'memory-infra',
+ args: {
+ stackFrames: {
+ '-1': { name: '<self>' },
+ '0': { name: 'MessageLoop::RunTask' },
+ '0.5': { name: '<self>', parent: '0' },
+ '1': { name: 'TimerBase::run', parent: '0' },
+ 'TWO': { name: 'ScheduledAction::execute', parent: '1' },
+ '2.72': { name: '<self>', parent: 'TWO' },
+ '3': { name: 'FunctionCall', parent: 'TWO' },
+ '\u03C0': { name: '<self>', parent: '3' },
+ '4': { name: 'UpdateLayoutTree', parent: '1' },
+ 'FOUR-AND-A-BIT': { name: '<self>', parent: '4' },
+ '5': { name: 'MessageLoop::JogTask' },
+ 'NaN': { name: '<self>', parent: '5' }
+ }
+ }
+ },
+ {
+ pid: 42,
+ ph: 'M',
+ name: 'typeNames',
+ cat: 'memory-infra',
+ args: {
+ typeNames: {
+ // Clang.
+ '22': '[unknown]',
+ '23': 'testing::ManuallyAnnotatedMockClass',
+ '24': 'const char *WTF::getStringWithTypeName() [T = ' +
+ 'blink::Event]',
+ '25': 'blink::ContextLifecycleObserver *',
+ '26': 'const char *WTF::getStringWithTypeName() [T = ' +
+ 'blink::WebFrame *]'
+ }
+ }
+ },
+ {
+ pid: 42,
+ ts: 10,
+ ph: 'v',
+ id: '0123',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_totals: {
+ resident_set_bytes: '0'
+ },
+ heaps: {
+ partition_alloc: {
+ entries: [
+ { bt: '' /* root */, size: '5cdf91' },
+ { bt: '' /* root */, type: '24', size: '2e6fc8' },
+ { bt: '' /* root */, type: '25', size: '1737e4' },
+ { bt: '-1', type: '22', size: '5b6cd6' },
+ { bt: 'FOUR-AND-A-BIT', size: '18f0', count: '100' },
+ { bt: 'FOUR-AND-A-BIT', type: '26', size: 'c78' },
+ { bt: '\u03C0', size: 'e3a8' }
+ ]
+ },
+ malloc: {
+ entries: [
+ { bt: '', size: '789', count: '50' },
+ { bt: '0.5', size: '123', count: '60' },
+ { bt: 'NaN', size: '456', count: '70' },
+ { bt: '3', type: '25', size: 'cd', count: '80' }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ pid: 21,
+ ph: 'M',
+ name: 'stackFrames',
+ cat: 'memory-infra',
+ args: {
+ stackFrames: {
+ // Intentionally in reverse order.
+ 'A': { name: '<self>', parent: '0' },
+ '0': { name: 'FrameView::layout', parent: '1' },
+ '1': { name: 'MessageLoop::RunTask' }
+ }
+ }
+ },
+ {
+ pid: 21,
+ ts: 12,
+ ph: 'v',
+ id: '0987',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ heaps: {
+ winheap: {
+ entries: [] // Intentionally empty.
+ },
+ partition_alloc: {
+ entries: [
+ { bt: '', size: '2000' },
+ { bt: 'A', type: '25', size: 'def' },
+ { bt: '3' /* invalid */, size: 'aaa' },
+ { bt: 'A', type: '24' /* invalid */, size: 'bbb' },
+ { bt: '0', size: 'fff' }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ pid: 21,
+ ph: 'M',
+ name: 'typeNames',
+ cat: 'memory-infra',
+ args: {
+ typeNames: {
+ // Microsoft Visual C++.
+ '25': 'const char *__cdecl WTF::getStringWithTypeName<class ' +
+ 'v8::FunctionCallbackInfo<class v8::Value>>(void)'
+ }
+ }
+ },
+ {
+ pid: 63,
+ ph: 'M',
+ name: 'stackFrames',
+ cat: 'memory-infra',
+ args: {
+ stackFrames: {} // Intentionally empty.
+ }
+ },
+ {
+ pid: 63,
+ ph: 'M',
+ name: 'typeNames',
+ cat: 'memory-infra',
+ args: {
+ typeNames: {} // Intentionally empty.
+ }
+ },
+ {
+ pid: 63,
+ ts: 13,
+ ph: 'v',
+ id: '0987',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ heaps: {
+ winheap: {
+ entries: [
+ { bt: '', size: '10000' }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ pid: 84,
+ ph: 'M',
+ name: 'stackFrames',
+ cat: 'memory-infra',
+ args: {
+ stackFrames: {
+ '5': { name: 'MessageLoop::WalkTask' }
+ }
+ }
+ },
+ {
+ pid: 84,
+ ph: 'M',
+ name: 'typeNames',
+ cat: 'memory-infra',
+ args: {
+ typeNames: {
+ '0': '[unknown]',
+ '1': 'base::All',
+ '3': 'content::Manually',
+ '4': 'net::Annotated'
+ }
+ }
+ },
+ {
+ pid: 84,
+ ts: 14,
+ ph: 'v',
+ id: '0987',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ heaps: {
+ malloc: {
+ entries: [
+ { bt: '5', type: '3', size: 'abcd' }
+ ]
+ }
+ }
+ }
+ }
+ }
+ ];
+ // TODO(chiniforooshan): checkParsedAndStreamInput uses JSON.stringify and
+ // then stringToUint8Array for converting events to a trace stream. The
+ // current implementation of stringToUint8Array is not Unicode compatible.
+ const m = makeModel(events);
+ checkModel(m);
+ });
+
+ test('importMemoryDumps_composableDumps', function() {
+ function checkModel(m) {
+ function checkDumpTime(dump, expectedStart, expectedDuration) {
+ assert.closeTo(dump.start, expectedStart / 1000, 1e-5);
+ assert.closeTo(dump.duration, expectedDuration / 1000, 1e-5);
+ }
+
+ function checkLinkCounts(allocatorDump, expectedHasOwns,
+ expectedOwnedByCount, expectedRetainsCount, expectedRetainedByCount) {
+ assert.strictEqual(allocatorDump.owns !== undefined, expectedHasOwns);
+ assert.lengthOf(allocatorDump.ownedBy, expectedOwnedByCount);
+ assert.lengthOf(allocatorDump.retains, expectedRetainsCount);
+ assert.lengthOf(allocatorDump.retainedBy, expectedRetainedByCount);
+ }
+
+ // Check the overall structure of the model and memory dumps.
+ assert.sameMembers(Object.keys(m.processes), ['42', '68']);
+ assert.lengthOf(m.globalMemoryDumps, 2);
+ const gmd1 = m.globalMemoryDumps[0];
+ assert.strictEqual(gmd1.model, m);
+ checkDumpTime(gmd1, 9999, 6);
+ const gmd2 = m.globalMemoryDumps[1];
+ assert.strictEqual(gmd2.model, m);
+ checkDumpTime(gmd2, 10003, 0);
+
+ const p1 = m.getProcess(42);
+ assert.lengthOf(p1.memoryDumps, 2);
+ const pmd1 = p1.memoryDumps[0];
+ checkDumpTime(pmd1, 10000, 5);
+ assert.strictEqual(pmd1.globalMemoryDump, gmd1);
+ assert.strictEqual(pmd1.process, p1);
+ const pmd2 = p1.memoryDumps[1];
+ checkDumpTime(pmd2, 10003, 0);
+ assert.strictEqual(pmd2.globalMemoryDump, gmd2);
+ assert.strictEqual(pmd2.process, p1);
+
+ const p2 = m.getProcess(68);
+ assert.lengthOf(p2.memoryDumps, 1);
+ const pmd3 = p2.memoryDumps[0];
+ checkDumpTime(pmd3, 9999, 0);
+ assert.strictEqual(pmd3.globalMemoryDump, gmd1);
+ assert.strictEqual(pmd3.process, p2);
+
+ assert.deepEqual(gmd1.processMemoryDumps, {42: pmd1, 68: pmd3});
+ assert.deepEqual(gmd2.processMemoryDumps, {42: pmd2});
+
+ // Check the composed dump.
+ assert.strictEqual(pmd1.levelOfDetail, LIGHT);
+
+ const totals = pmd1.totals;
+ assert.strictEqual(totals.residentBytes, 256);
+ assert.isUndefined(totals.peakResidentBytes);
+ assert.isUndefined(totals.arePeakResidentBytesResettable);
+ assert.deepEqual(totals.platformSpecific, {private_bytes: 128});
+
+ const vmRegions = pmd1.vmRegions;
+ checkVMRegions(vmRegions, [
+ {
+ mappedFile: '[stack:20310]',
+ startAddress: 240,
+ sizeInBytes: 336,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE,
+ byteStats: {
+ proportionalResident: 158
+ }
+ }
+ ]);
+
+ const memoryAllocatorDumps = pmd1.memoryAllocatorDumps;
+ assert.lengthOf(memoryAllocatorDumps, 2);
+
+ const local1Dump = pmd1.getMemoryAllocatorDumpByFullName('local1');
+ assert.strictEqual(memoryAllocatorDumps[0], local1Dump);
+ assert.strictEqual(local1Dump.fullName, 'local1');
+ assert.isUndefined(local1Dump.parent);
+ assert.lengthOf(local1Dump.children, 0);
+ checkDumpNumericsAndDiagnostics(local1Dump, {},
+ { 'A': 'blue', 'B': 'red' });
+ checkLinkCounts(local1Dump, true /* owns */, 0 /* owned by */,
+ 0 /* retains */, 0 /* retained by */);
+
+ const local2Dump = pmd1.getMemoryAllocatorDumpByFullName('local2');
+ assert.strictEqual(memoryAllocatorDumps[1], local2Dump);
+ assert.strictEqual(local2Dump.fullName, 'local2');
+ assert.isUndefined(local2Dump.parent);
+ assert.lengthOf(local2Dump.children, 0);
+ checkDumpNumericsAndDiagnostics(local2Dump, {}, { 'B': 'yellow' });
+ checkLinkCounts(local2Dump, false /* owns */, 0 /* owned by */,
+ 1 /* retains */, 0 /* retained by */);
+
+ const heapDumps = pmd1.heapDumps;
+ assert.sameMembers(Object.keys(heapDumps), ['partition_alloc']);
+ const heapDump = heapDumps.partition_alloc;
+ assert.strictEqual(heapDump.processMemoryDump, pmd1);
+ assert.strictEqual(heapDump.allocatorName, 'partition_alloc');
+ const entries = heapDump.entries;
+ assert.lengthOf(entries, 1);
+ assert.strictEqual(entries[0].heapDump, heapDump);
+ assert.strictEqual(
+ entries[0].leafStackFrame.title, 'MessageLoop::RunTask');
+ assert.strictEqual(entries[0].objectTypeName, 'cc::SurfaceFactory');
+ assert.strictEqual(entries[0].size, 1280);
+
+ // Check the other dumps.
+ assert.strictEqual(pmd2.levelOfDetail, DETAILED);
+ assert.isUndefined(pmd2.vmRegions);
+ assert.lengthOf(pmd2.memoryAllocatorDumps, 1);
+ const otherLocal1Dump = pmd2.getMemoryAllocatorDumpByFullName('local1');
+ assert.strictEqual(otherLocal1Dump, pmd2.memoryAllocatorDumps[0]);
+ assert.strictEqual(otherLocal1Dump.fullName, 'local1');
+ assert.isUndefined(otherLocal1Dump.parent);
+ checkDumpNumericsAndDiagnostics(otherLocal1Dump, { 'A': 2989 }, {});
+ assert.isUndefined(pmd2.heapDumps);
+ checkLinkCounts(otherLocal1Dump, false /* owns */, 1 /* owned by */,
+ 0 /* retains */, 0 /* retained by */);
+
+ assert.strictEqual(pmd3.levelOfDetail, DETAILED);
+ const otherVmRegions = pmd3.vmRegions;
+ checkVMRegions(otherVmRegions, [
+ {
+ mappedFile: '/dev/ashmem/dalvik',
+ startAddress: 848,
+ sizeInBytes: 592,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ byteStats: {
+ privateDirtyResident: 205
+ }
+ }
+ ]);
+ assert.lengthOf(pmd3.memoryAllocatorDumps, 0);
+ assert.isUndefined(pmd3.heapDumps);
+
+ // Check the global dumps.
+ assert.lengthOf(gmd1.memoryAllocatorDumps, 2);
+ const shared1Dump = gmd1.getMemoryAllocatorDumpByFullName('shared1');
+ assert.strictEqual(shared1Dump, gmd1.memoryAllocatorDumps[0]);
+ assert.strictEqual(shared1Dump.fullName, 'shared1');
+ assert.isUndefined(shared1Dump.parent);
+ checkDumpNumericsAndDiagnostics(shared1Dump, {},
+ { 'A': 'purple', 'B': 'green' });
+ checkLinkCounts(shared1Dump, false /* owns */, 1 /* owned by */,
+ 0 /* retains */, 0 /* retained by */);
+ const shared2Dump = gmd1.getMemoryAllocatorDumpByFullName('shared2');
+ assert.strictEqual(shared2Dump, gmd1.memoryAllocatorDumps[1]);
+ assert.strictEqual(shared2Dump.fullName, 'shared2');
+ assert.isUndefined(shared2Dump.parent);
+ checkDumpNumericsAndDiagnostics(shared2Dump, {}, { 'A': 'cyan' });
+ checkLinkCounts(shared2Dump, false /* owns */, 0 /* owned by */,
+ 0 /* retains */, 1 /* retained by */);
+
+ assert.lengthOf(gmd2.memoryAllocatorDumps, 1);
+ const otherShared1Dump = gmd2.getMemoryAllocatorDumpByFullName('shared1');
+ assert.strictEqual(otherShared1Dump, gmd2.memoryAllocatorDumps[0]);
+ assert.strictEqual(otherShared1Dump.fullName, 'shared1');
+ assert.isUndefined(otherShared1Dump.parent);
+ checkDumpNumericsAndDiagnostics(otherShared1Dump, {}, { 'A': 'brown' });
+ checkLinkCounts(otherShared1Dump, true /* owns */, 0 /* owned by */,
+ 0 /* retains */, 0 /* retained by */);
+
+ // Check the edges.
+ const ownershipLink = local1Dump.owns;
+ assert.strictEqual(shared1Dump.ownedBy[0], ownershipLink);
+ assert.strictEqual(ownershipLink.source, local1Dump);
+ assert.strictEqual(ownershipLink.target, shared1Dump);
+ assert.strictEqual(ownershipLink.importance, 1);
+
+ const retentionLink = local2Dump.retains[0];
+ assert.strictEqual(shared2Dump.retainedBy[0], retentionLink);
+ assert.strictEqual(retentionLink.source, local2Dump);
+ assert.strictEqual(retentionLink.target, shared2Dump);
+ assert.isUndefined(retentionLink.importance);
+
+ const otherOwnershipLink = otherShared1Dump.owns;
+ assert.strictEqual(otherLocal1Dump.ownedBy[0], otherOwnershipLink);
+ assert.strictEqual(otherOwnershipLink.source, otherShared1Dump);
+ assert.strictEqual(otherOwnershipLink.target, otherLocal1Dump);
+ assert.isUndefined(otherOwnershipLink.importance);
+ }
+
+ // Split PMD1 over multiple PMD trace events, all of which should be merged
+ // by the importer. Also inject some PMD trace events with different PIDs
+ // or dump IDs, which should *not* be merged with the rest.
+ const events = [
+ { // Heap dumps.
+ pid: 42,
+ ts: 10000,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ level_of_detail: 'light',
+ heaps: {
+ partition_alloc: {
+ entries: [
+ { bt: '99', type: '888', size: '500' }
+ ]
+ }
+ }
+ }
+ }
+ },
+ { // PMD2 with a different dump id (should not be merged).
+ pid: 42,
+ ts: 10003, // Same PID, so it will end up in the same process.
+ ph: 'v',
+ id: '0x0002',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ level_of_detail: 'detailed',
+ allocators: {
+ 'local1': {
+ guid: '3',
+ attrs: {
+ A: {type: 'scalar', units: 'bytes', value: '0xBAD'}
+ }
+ },
+ 'global/shared1': {
+ guid: '4',
+ attrs: {
+ A: {type: 'string', units: '', value: 'brown'}
+ }
+ }
+ },
+ allocators_graph: [
+ {
+ source: '4',
+ target: '3',
+ type: 'ownership'
+ }
+ ]
+ }
+ }
+ },
+ { // Stack frames (required for heap dumps).
+ pid: 42,
+ ph: 'M',
+ name: 'stackFrames',
+ cat: 'memory-infra',
+ args: {
+ stackFrames: {
+ '99': { name: 'MessageLoop::RunTask' }
+ }
+ }
+ },
+ { // Allocator dumps.
+ pid: 42,
+ ts: 10001,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ level_of_detail: 'light',
+ allocators: {
+ 'local1': {
+ guid: '3',
+ attrs: {
+ A: {type: 'string', units: '', value: 'blue'}
+ }
+ },
+ 'global/shared1': {
+ guid: '7',
+ attrs: {
+ A: {type: 'string', units: '', value: 'purple'}
+ }
+ },
+ 'global/shared2': {
+ guid: '8',
+ attrs: {
+ A: {type: 'string', units: '', value: 'cyan'}
+ }
+ }
+ }
+ }
+ }
+ },
+ { // PMD3 with a different PID (should not be merged).
+ pid: 68,
+ ts: 9999,
+ ph: 'v',
+ id: '0x0001', // Same dump ID, so it will end up in the same GMD.
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ process_mmaps: {
+ vm_regions: [
+ {
+ sa: '350',
+ sz: '250',
+ pf: 5,
+ mf: '/dev/ashmem/dalvik',
+ bs: {
+ pd: 'cd'
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ { // VM regions.
+ pid: 42,
+ ts: 10005,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ level_of_detail: 'light',
+ process_mmaps: {
+ vm_regions: [
+ {
+ sa: 'f0',
+ sz: '150',
+ pf: 6,
+ mf: '[stack:20310]',
+ bs: {
+ pss: '9e'
+ }
+ }
+ ]
+ }
+ }
+ }
+ },
+ { // Totals.
+ pid: 42,
+ ts: 10003,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ level_of_detail: 'light',
+ process_totals: {
+ resident_set_bytes: '100',
+ private_bytes: '80' // OS-specific total.
+ }
+ }
+ }
+ },
+ { // Allocator dump edges.
+ pid: 42,
+ ts: 10004,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ level_of_detail: 'light',
+ allocators_graph: [
+ {
+ source: '4',
+ target: '8',
+ type: 'retention'
+ }
+ ]
+ }
+ }
+ },
+ { // Object type names (required for heap dumps).
+ pid: 42,
+ ph: 'M',
+ name: 'typeNames',
+ cat: 'memory-infra',
+ args: {
+ typeNames: {
+ // GCC.
+ '888': 'const char* WTF::getStringWithTypeName() [with T = ' +
+ 'cc::SurfaceFactory]'
+ }
+ }
+ },
+ { // Allocator dumps and dump edges (should be merged).
+ pid: 42,
+ ts: 10002,
+ ph: 'v',
+ id: '0x0001',
+ cat: 'memory-infra',
+ args: {
+ dumps: {
+ level_of_detail: 'light',
+ allocators: {
+ 'local1': {
+ guid: '3',
+ attrs: {
+ B: {type: 'string', units: '', value: 'red'}
+ }
+ },
+ 'local2': {
+ guid: '4',
+ attrs: {
+ B: {type: 'string', units: '', value: 'yellow'}
+ }
+ },
+ 'global/shared1': {
+ guid: '7',
+ attrs: {
+ B: {type: 'string', units: '', value: 'green'}
+ }
+ }
+ },
+ allocators_graph: [
+ {
+ source: '3',
+ target: '7',
+ type: 'ownership',
+ importance: 1
+ }
+ ]
+ }
+ }
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('importThreadInstantSliceWithStackFrame', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[2];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.slices.length, 1);
+
+ const s0 = t.sliceGroup.slices[0];
+ assert.strictEqual(s0.startStackFrame.title, 'frame7');
+ assert.isUndefined(s0.endStackFrame);
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'a', args: {}, pid: 1, ts: 0, cat: 'baz', tid: 2, ph: 'I', s: 't', sf: 7 } // @suppress longLineCheck
+ ],
+ stackFrames: {
+ '1': {
+ category: 'm1',
+ name: 'main'
+ },
+ '7': {
+ category: 'm2',
+ name: 'frame7',
+ parent: '1'
+ }
+ }
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importDurationEventsWithStackFrames', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[2];
+ assert.isDefined(t);
+ assert.strictEqual(t.sliceGroup.slices.length, 1);
+
+ const s0 = t.sliceGroup.slices[0];
+ assert.strictEqual(s0.startStackFrame.title, 'frame7');
+ assert.strictEqual(s0.endStackFrame.title, 'frame8');
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'a', args: {}, pid: 1, ts: 0, cat: 'baz', tid: 2, ph: 'B', sf: 7 }, // @suppress longLineCheck
+ { name: 'b', args: {}, pid: 1, ts: 5, cat: 'baz', tid: 2, ph: 'E', sf: 8 } // @suppress longLineCheck
+ ],
+ stackFrames: {
+ '1': {
+ category: 'm1',
+ name: 'main'
+ },
+ '7': {
+ category: 'm2',
+ name: 'frame7',
+ parent: '1'
+ },
+ '8': {
+ category: 'm2',
+ name: 'frame8',
+ parent: '1'
+ }
+ }
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('annotationParsing', function() {
+ const yComponents1 = [{stableId: '52.53', yPercentOffset: 0.5},
+ {stableId: '52', yPercentOffset: 0.3}];
+ const yComponents2 = [{stableId: '52.53', yPercentOffset: 0.7},
+ {stableId: '52', yPercentOffset: 0.4}];
+ const location1 = new tr.model.Location(0.1, yComponents1);
+ const location2 = new tr.model.Location(0.2, yComponents2);
+
+ function checkModel(m) {
+ const annotations = m.getAllAnnotations();
+ assert.strictEqual(annotations.length, 3);
+
+ assert.isTrue(annotations[0] instanceof tr.model.XMarkerAnnotation);
+ assert.strictEqual(annotations[0].timestamp, 12);
+
+ assert.isTrue(annotations[1] instanceof tr.model.RectAnnotation);
+ assert.deepEqual(annotations[1].startLocation, location1);
+ assert.deepEqual(annotations[1].endLocation, location2);
+
+ assert.isTrue(
+ annotations[2] instanceof tr.model.CommentBoxAnnotation);
+ assert.strictEqual(annotations[2].text, 'test');
+ assert.deepEqual(annotations[2].location, location1);
+ }
+
+ const eventData = { traceEvents: [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'}],
+ traceAnnotations: [
+ {typeName: 'xmarker', args: {timestamp: 12}},
+ {typeName: 'rect', args: {
+ start: location1.toDict(), end: location2.toDict()}},
+ {typeName: 'comment_box', args: {text: 'test',
+ location: location1.toDict()}}
+ ]};
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importDisplayTimeUnit', function() {
+ function checkModel(m) {
+ assert.strictEqual(m.intrinsicTimeUnit, tr.b.TimeDisplayModes.ns);
+ }
+
+ const eventData = {
+ traceEvents: [
+ {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'}],
+ displayTimeUnit: 'ns'
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ const m = makeModel(JSON.stringify(eventData));
+ checkModel(m);
+ });
+
+ test('extractBattorSubTraces', function() {
+ const battorLog = '# BattOr\n# voltage range [0.000000, 7196.484161] mV\n' +
+ '#current range [11.898481, 2110.900916] mA\n' +
+ '# sample_rate=10000Hz, gain=30.257143x\n' +
+ '# filpot_pos=3, amppot_pos=35, timer_ovf=399, timer_div=4 ovs_bits=0\n' + // @suppress longLineCheck
+ '0.0 1040.3 3984.2\n' +
+ '0.1 1081.3 3987.8\n' +
+ '0.2 1092.6 3987.8\n' +
+ '0.3 1070.0 3987.8\n' +
+ '0.4 1017.7 3994.8\n';
+
+ const eventData = {
+ traceEvents: [
+ { name: 'a', args: {}, pid: 1, ts: 0, cat: 'baz', tid: 2, ph: 'B', sf: 7 }, // @suppress longLineCheck
+ { name: 'b', args: {}, pid: 1, ts: 5, cat: 'baz', tid: 2, ph: 'E', sf: 8 } // @suppress longLineCheck
+ ],
+ powerTraceAsString: battorLog
+ };
+ let m = new tr.Model();
+ let importer = new tr.e.importer.TraceEventImporter(m, eventData);
+ let subTraces = importer.extractSubtraces();
+ assert.isTrue(subTraces instanceof Array);
+ assert.strictEqual(subTraces.length, 1);
+ assert.strictEqual(subTraces[0], battorLog);
+
+ m = new tr.Model();
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array(JSON.stringify(eventData)), false);
+ importer = new tr.e.importer.TraceEventImporter(m, stream);
+ subTraces = importer.extractSubtraces();
+ assert.isTrue(subTraces instanceof Array);
+ assert.strictEqual(subTraces.length, 1);
+ assert.strictEqual(subTraces[0], battorLog);
+ });
+
+ test('metadataParsing', function() {
+ const metadataValue = {value: {}};
+
+ function checkModel(m) {
+ assert.isTrue(m.metadata instanceof Array);
+ assert.strictEqual(m.metadata.length, 1);
+ assert.strictEqual(m.metadata[0].name, 'metadata');
+ assert.deepEqual(m.metadata[0].value, metadataValue);
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'a', args: {}, pid: 1, ts: 0, cat: 'baz', tid: 2, ph: 'B', sf: 7 }, // @suppress longLineCheck
+ { name: 'b', args: {}, pid: 1, ts: 5, cat: 'baz', tid: 2, ph: 'E', sf: 8 } // @suppress longLineCheck
+ ],
+ metadata: metadataValue
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importTraceConfigAsMetadata', function() {
+ const traceConfigData = {
+ enable_argument_filter: false,
+ enable_sampling: false,
+ enable_systrace: false,
+ record_mode: 'record-until-full'
+ };
+
+ function checkModel(m) {
+ assert.isTrue(m.metadata instanceof Array);
+ assert.strictEqual(m.metadata.length, 1);
+ assert.strictEqual(m.metadata[0].name, 'TraceConfig');
+ assert.deepEqual(m.metadata[0].value, traceConfigData);
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'TraceConfig', args: { value: traceConfigData },
+ pid: 2, ts: 0, tid: 1, ph: 'M', cat: '__metadata' },
+ ],
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('importMarks', function() {
+ function checkModel(m) {
+ const p = m.processes[1];
+ const t = p.threads[2];
+ assert.lengthOf(t.sliceGroup.slices, 2);
+
+ const s0 = t.sliceGroup.slices[0];
+ assert.strictEqual(s0.title, 'mark1');
+ assert.strictEqual(s0.start, 0);
+
+ const s1 = t.sliceGroup.slices[1];
+ assert.strictEqual(s1.title, 'mark2');
+ assert.strictEqual(s1.start, .01);
+ }
+
+ const eventData = {
+ traceEvents: [
+ { name: 'mark1', args: {}, pid: 1, tid: 2, ts: 0, tts: 0, cat: 'blink.user_timing', ph: 'R' }, // @suppress longLineCheck
+ { name: 'mark2', args: {}, pid: 1, tid: 2, ts: 10, tts: 10, cat: 'blink.user_timing', ph: 'R' } // @suppress longLineCheck
+ ]
+ };
+ checkParsedAndStreamInput(eventData, checkModel);
+ });
+
+ test('createNestableAsyncSlicesForUserTimingWithoutArgs', function() {
+ function checkModel(m) {
+ assert(m.numProcesses, 1);
+ const p = m.processes[1];
+ assert.isDefined(p);
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[2];
+ const asyncSliceGroup = t.asyncSliceGroup;
+ assert.strictEqual(asyncSliceGroup.length, 2);
+ for (let i = 0; i < asyncSliceGroup.length; ++i) {
+ assert.isTrue(asyncSliceGroup.slices[i] instanceof MeasureAsyncSlice);
+ }
+
+ const groupA = asyncSliceGroup.slices[0];
+ assert.strictEqual(groupA.viewSubGroupTitle, 'A');
+ assert.strictEqual(groupA.title, 'a1');
+ assert.strictEqual(groupA.subSlices.length, 0);
+ const groupB = asyncSliceGroup.slices[1];
+ assert.strictEqual(groupB.viewSubGroupTitle, 'B');
+ assert.strictEqual(groupB.title, 'b1');
+ assert.strictEqual(groupB.subSlices.length, 2);
+ const groupBSubSlice1 = groupB.subSlices[0];
+ assert.strictEqual(groupBSubSlice1.viewSubGroupTitle, 'B');
+ assert.strictEqual(groupBSubSlice1.title, 'b2');
+ assert.strictEqual(groupBSubSlice1.subSlices.length, 1);
+ assert.strictEqual(groupBSubSlice1.subSlices[0].viewSubGroupTitle, 'B');
+ assert.strictEqual(groupBSubSlice1.subSlices[0].title, 'b3');
+ assert.strictEqual(groupBSubSlice1.subSlices[0].subSlices.length, 0);
+ const groupBSubSlice2 = groupB.subSlices[1];
+ assert.strictEqual(groupBSubSlice2.viewSubGroupTitle, 'B');
+ assert.strictEqual(groupBSubSlice2.title, 'b4');
+ assert.strictEqual(groupBSubSlice2.subSlices.length, 0);
+ }
+
+ /**
+ * Structure of this async slices
+ *
+ * Group A:
+ *
+ * |__________|
+ * a1
+ *
+ * Group B:
+ *
+ * |______________________________|
+ * b1
+ * |__________||_|
+ * b2 b4
+ * |_|
+ * b3
+ **/
+ const events = [
+ {
+ name: 'A:a1',
+ args: {params: ''},
+ pid: 1,
+ ts: 100,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 3,
+ ph: 'b'
+ },
+ {
+ name: 'A:a1',
+ args: {params: ''},
+ pid: 1,
+ ts: 110,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 3,
+ ph: 'e'
+ },
+ {
+ name: 'B:b1',
+ args: {params: ''},
+ pid: 1,
+ ts: 120,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 4,
+ ph: 'b'
+ },
+ {
+ name: 'B:b2',
+ args: {params: ''},
+ pid: 1,
+ ts: 130,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 5,
+ ph: 'b'
+ },
+ {
+ name: 'B:b3',
+ args: {params: ''},
+ pid: 1,
+ ts: 131,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 5,
+ ph: 'b'
+ },
+ {
+ name: 'B:b3',
+ args: {params: ''},
+ pid: 1,
+ ts: 132,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 5,
+ ph: 'e'
+ },
+ {
+ name: 'B:b2',
+ args: {params: ''},
+ pid: 1,
+ ts: 140,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 5,
+ ph: 'e'
+ },
+ {
+ name: 'B:b4',
+ args: {params: ''},
+ pid: 1,
+ ts: 141,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 5,
+ ph: 'b'
+ },
+ {
+ name: 'B:b4',
+ args: {params: ''},
+ pid: 1,
+ ts: 142,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 5,
+ ph: 'e'
+ },
+ {
+ name: 'B:b1',
+ args: {params: ''},
+ pid: 1,
+ ts: 150,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 4,
+ ph: 'e'
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('createNestableAsyncSlicesForUserTimingWithArgs', function() {
+ function checkModel(m) {
+ assert(m.numProcesses, 1);
+ const p = m.processes[1];
+ assert.isDefined(p);
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[2];
+ const asyncSliceGroup = t.asyncSliceGroup;
+ assert.strictEqual(asyncSliceGroup.length, 2);
+ for (let i = 0; i < asyncSliceGroup.length; ++i) {
+ assert.isTrue(asyncSliceGroup.slices[i] instanceof MeasureAsyncSlice);
+ }
+
+ const a1 = asyncSliceGroup.slices[0];
+ assert.strictEqual(a1.viewSubGroupTitle, 'A');
+ assert.strictEqual(a1.title, 'a1');
+ assert.strictEqual(a1.subSlices.length, 0);
+ assert.deepEqual(a1.args, {a: 1});
+ const a2 = asyncSliceGroup.slices[1];
+ assert.strictEqual(a2.viewSubGroupTitle, 'A');
+ assert.strictEqual(a2.title, 'a2');
+ assert.strictEqual(a2.subSlices.length, 0);
+ assert.deepEqual(a2.args, {a: 2, b: 2});
+ }
+
+ /**
+ * Structure of this async slices
+ *
+ * Group A:
+ *
+ * |__________| |__________|
+ * a1 a2
+ *
+ * a1.args = {a: 1}
+ * a2.args = {a: 2, b: 2}
+ **/
+ const events = [
+ {
+ name: 'A:a1/eyJhIjoxfQ==',
+ args: {params: ''},
+ pid: 1,
+ ts: 100,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 3,
+ ph: 'b'
+ },
+ {
+ name: 'A:a1/eyJhIjoxfQ==',
+ args: {params: ''},
+ pid: 1,
+ ts: 110,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 3,
+ ph: 'e'
+ },
+ {
+ name: 'A:a2/eyJhIjoyLCJiIjoyfQ==',
+ args: {params: ''},
+ pid: 1,
+ ts: 120,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 4,
+ ph: 'b'
+ },
+ {
+ name: 'A:a2/eyJhIjoyLCJiIjoyfQ==',
+ args: {params: ''},
+ pid: 1,
+ ts: 130,
+ cat: 'blink.user_timing',
+ tid: 2,
+ id: 4,
+ ph: 'e'
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('UserTimingAsyncSlicesWithNormalAsyncSlices', function() {
+ function checkModel(m) {
+ assert(m.numProcesses, 1);
+ const p = m.processes[1];
+ assert.isDefined(p);
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[2];
+ const asyncSliceGroup = t.asyncSliceGroup;
+ assert.strictEqual(asyncSliceGroup.length, 3);
+ assert.isTrue(asyncSliceGroup.slices[0] instanceof MeasureAsyncSlice);
+ assert.isFalse(asyncSliceGroup.slices[1] instanceof MeasureAsyncSlice);
+ assert.isFalse(asyncSliceGroup.slices[2] instanceof MeasureAsyncSlice);
+
+ const a1 = asyncSliceGroup.slices[0];
+ assert.strictEqual(a1.viewSubGroupTitle, 'A');
+ assert.strictEqual(a1.title, 'a1');
+ assert.strictEqual(a1.subSlices.length, 1);
+ const a2 = a1.subSlices[0];
+ assert.strictEqual(a2.viewSubGroupTitle, 'A');
+ assert.strictEqual(a2.title, 'a2');
+ assert.strictEqual(a2.subSlices.length, 0);
+ const B = asyncSliceGroup.slices[1];
+ assert.strictEqual(B.viewSubGroupTitle, 'B');
+ assert.strictEqual(B.title, 'B');
+ assert.strictEqual(B.subSlices.length, 0);
+ const C = asyncSliceGroup.slices[2];
+ assert.strictEqual(C.viewSubGroupTitle, 'C');
+ assert.strictEqual(C.title, 'C');
+ assert.strictEqual(C.subSlices.length, 0);
+ }
+
+ /**
+ * Structure of user timing async slices
+ *
+ * Group A:
+ *
+ * |__________|
+ * a1
+ * |__|
+ * a2
+ *
+ * B
+ * |__|
+ * B
+ * C
+ * |_|
+ * C
+ **/
+ const events = [
+ {
+ name: 'A:a1', args: {params: ''}, pid: 1, ts: 1,
+ cat: 'blink.user_timing', tid: 2, id: 3, ph: 'b'
+ },
+ {
+ name: 'A:a1', args: {params: ''}, pid: 1, ts: 11,
+ cat: 'blink.user_timing', tid: 2, id: 3, ph: 'e'
+ },
+ {
+ name: 'A:a2', args: {params: ''}, pid: 1, ts: 2,
+ cat: 'blink.user_timing', tid: 2, id: 4, ph: 'b'
+ },
+ {
+ name: 'A:a2', args: {params: ''}, pid: 1, ts: 4,
+ cat: 'blink.user_timing', tid: 2, id: 4, ph: 'e'
+ },
+ {
+ name: 'B', args: {}, pid: 1, ts: 9, cat: 'foo',
+ tid: 2, ph: 'b', id: 5
+ },
+ {
+ name: 'B', args: {}, pid: 1, ts: 11, cat: 'foo',
+ tid: 2, ph: 'e', id: 5
+ },
+ {
+ name: 'C', args: {}, pid: 1, ts: 12, cat: 'foo',
+ tid: 2, ph: 'b', id: 6
+ },
+ {
+ name: 'C', args: {}, pid: 1, ts: 13, cat: 'foo',
+ tid: 2, ph: 'e', id: 6
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('UserTimingAsyncSlicesParsingMeasureNameShouldNotFail', function() {
+ function checkModel(m) {
+ assert(m.numProcesses, 1);
+ const p = m.processes[1];
+ assert.isDefined(p);
+ assert.strictEqual(p.numThreads, 1);
+ const t = p.threads[2];
+ const asyncSliceGroup = t.asyncSliceGroup;
+
+ assert.strictEqual(asyncSliceGroup.length, 1);
+ assert.isTrue(asyncSliceGroup.slices[0] instanceof MeasureAsyncSlice);
+
+ const slice = asyncSliceGroup.slices[0];
+ assert.strictEqual(slice.viewSubGroupTitle, '<extended@component');
+ assert.strictEqual(slice.title,
+ 'shared@dropdown/dropdown-options::ember30> (Rendering: initial)');
+ assert.strictEqual(slice.subSlices.length, 3);
+ assert.strictEqual(slice.subSlices[0].title,
+ 'shared@dropdown/dropdown-options::ember30>:didReceiveAttrs:34');
+ assert.strictEqual(slice.subSlices[1].title,
+ 'shared@dropdown/dropdown-options::ember30>:willRender:35');
+ assert.strictEqual(slice.subSlices[2].title,
+ 'shared@dropdown/dropdown-options::ember30>:willInsertElement:36');
+ }
+
+ // events from ember-perf-timeline addon performance.measure() calls
+ const events = [
+ {
+ pid: 1, tid: 2, ts: 2695561803887, ph: 'b', cat: 'blink.user_timing',
+ name: '\u003Cextended@component:shared@dropdown/dropdown-options::ember30>:didReceiveAttrs:34', // @suppress longLineCheck
+ args: {}, tts: 10533196, id: '0x9e9a4a'
+ },
+ {
+ pid: 1, tid: 2, ts: 2695561803907, ph: 'e', cat: 'blink.user_timing',
+ name: '\u003Cextended@component:shared@dropdown/dropdown-options::ember30>:didReceiveAttrs:34', // @suppress longLineCheck
+ args: {}, tts: 10533202, id: '0x9e9a4a'
+ },
+ {
+ pid: 1, tid: 2, ts: 2695561803987, ph: 'b', cat: 'blink.user_timing',
+ name: '\u003Cextended@component:shared@dropdown/dropdown-options::ember30>:willRender:35', // @suppress longLineCheck
+ args: {}, tts: 10533295, id: '0xd0fc77'
+ },
+ {
+ pid: 1, tid: 2, ts: 2695561804002, ph: 'e', cat: 'blink.user_timing',
+ name: '\u003Cextended@component:shared@dropdown/dropdown-options::ember30>:willRender:35', // @suppress longLineCheck
+ args: {}, tts: 10533300, id: '0xd0fc77'
+ },
+ {
+ pid: 1, tid: 2, ts: 2695561804252, ph: 'b', cat: 'blink.user_timing',
+ name: '\u003Cextended@component:shared@dropdown/dropdown-options::ember30>:willInsertElement:36', // @suppress longLineCheck
+ args: {}, tts: 10533557, id: '0x5dfb0b'
+ },
+ {
+ pid: 1, tid: 2, ts: 2695561804262, ph: 'e', cat: 'blink.user_timing',
+ name: '\u003Cextended@component:shared@dropdown/dropdown-options::ember30>:willInsertElement:36', // @suppress longLineCheck
+ args: {}, tts: 10533561, id: '0x5dfb0b'
+ },
+ {
+ pid: 1, tid: 2, ts: 2695561803852, ph: 'b', cat: 'blink.user_timing',
+ name: '\u003Cextended@component:shared@dropdown/dropdown-options::ember30> (Rendering: initial)', // @suppress longLineCheck
+ args: {}, tts: 10533951, id: '0xc824e5'
+ },
+ {
+ pid: 1, tid: 2, ts: 2695561804652, ph: 'e', cat: 'blink.user_timing',
+ name: '\u003Cextended@component:shared@dropdown/dropdown-options::ember30> (Rendering: initial)', // @suppress longLineCheck
+ args: {}, tts: 10533956, id: '0xc824e5'
+ }
+ ];
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('clockSync_requesterWithoutMetadata', function() {
+ const events = [{
+ name: 'clock_sync', args: {sync_id: 'abc', issue_ts: 5000},
+ pid: 1, ts: 15000, cat: '__metadata', tid: 2, ph: 'c'
+ }];
+
+ const io = new tr.importer.ImportOptions();
+ const m = new tr.Model();
+ const i = new tr.importer.Import(m, io);
+
+ m.clockSyncManager.addClockSyncMarker(
+ ClockDomainId.LINUX_FTRACE_GLOBAL, 'abc', 15);
+
+ i.importTraces([events]);
+
+ // The clock sync happened in UNKNOWN_CHROME_LEGACY at 10ms and in
+ // LINUX_FTRACE_GLOBAL at 15ms. The transformer should shift the ftrace
+ // timestamps back by 5ms.
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(5),
+ 5);
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.LINUX_FTRACE_GLOBAL)(15),
+ 10);
+ assert.isFalse(m.hasImportWarnings);
+ });
+
+ test('clockSync_requesterWithoutMetadata_stream', function() {
+ const events = [{
+ name: 'clock_sync', args: {sync_id: 'abc', issue_ts: 5000},
+ pid: 1, ts: 15000, cat: '__metadata', tid: 2, ph: 'c'
+ }];
+ const stream = new tr.b.InMemoryTraceStream(
+ stringToUint8Array(JSON.stringify(events)), false);
+
+ const io = new tr.importer.ImportOptions();
+ const m = new tr.Model();
+ const i = new tr.importer.Import(m, io);
+
+ m.clockSyncManager.addClockSyncMarker(
+ ClockDomainId.LINUX_FTRACE_GLOBAL, 'abc', 15);
+
+ i.importTraces([stream]);
+
+ // The clock sync happened in UNKNOWN_CHROME_LEGACY at 10ms and in
+ // LINUX_FTRACE_GLOBAL at 15ms. The transformer should shift the ftrace
+ // timestamps back by 5ms.
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(5),
+ 5);
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.LINUX_FTRACE_GLOBAL)(15),
+ 10);
+ assert.isFalse(m.hasImportWarnings);
+ });
+
+
+ test('clockSync_requesterWithMetadata', function() {
+ function checkModel(m) {
+ // Make sure that our clock domain was chosen as the model.
+ assert.strictEqual(
+ m.clockSyncManager
+ .getModelTimeTransformer(ClockDomainId.BATTOR)(.005),
+ .005);
+ assert.isFalse(m.hasImportWarnings);
+ }
+
+ const events = {
+ traceEvents: [{
+ name: 'clock_sync', args: {sync_id: 'abc', issue_ts: 5},
+ pid: 1, ts: 15, cat: '__metadata', tid: 2, ph: 'c'
+ }],
+ metadata: {
+ 'clock-domain': ClockDomainId.BATTOR
+ }
+ };
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('clockSync_recipient', function() {
+ function checkModel(m) {
+ m.clockSyncManager.addClockSyncMarker(
+ ClockDomainId.LINUX_CLOCK_MONOTONIC, 'abc', 15);
+
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.TELEMETRY)(10),
+ 10);
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.LINUX_CLOCK_MONOTONIC)(10),
+ 10);
+ }
+
+ const events = {
+ traceEvents: [{
+ name: 'clock_sync', args: {sync_id: 'abc'}, pid: 1, ts: 15000,
+ cat: '__metadata', tid: 2, ph: 'c'
+ }],
+ metadata: {
+ 'clock-domain': ClockDomainId.TELEMETRY
+ }
+ };
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('clockSync_missingSyncId', function() {
+ const events = [{
+ name: 'clock_sync', args: {issue_ts: 5},
+ pid: 1, ts: 15, cat: '__metadata', tid: 2, ph: 'c'
+ }];
+ checkParsedAndStreamInput(events, m => assert.isTrue(m.hasImportWarnings));
+ });
+
+ test('clockSync_legacyChrome', function() {
+ function checkModel(m) {
+ m.clockSyncManager.addClockSyncMarker(
+ ClockDomainId.TELEMETRY, 'abc', 15);
+
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(10),
+ 10);
+ assert.strictEqual(
+ m.clockSyncManager.getModelTimeTransformer(
+ ClockDomainId.TELEMETRY)(15),
+ 10);
+ }
+
+ const events = {
+ traceEvents: [
+ {
+ name: 'ClockSyncEvent.abc', ts: 5000,
+ cat: 'blink.user_timing', pid: 1, tid: 2, ph: 'S'
+ },
+ {
+ name: 'ClockSyncEvent.abc', ts: 15000,
+ cat: 'blink.user_timing', pid: 1, tid: 2, ph: 'F'
+ }
+ ]
+ };
+ checkParsedAndStreamInput(events, checkModel);
+ });
+
+ test('clockSync_legacyChromeThrowsWithInconsistentSyncID', function() {
+ const events = {
+ traceEvents: [
+ {
+ name: 'ClockSyncEvent.abc', ts: 5000,
+ cat: 'blink.user_timing', pid: 1, tid: 2, ph: 'S'
+ },
+ {
+ name: 'ClockSyncEvent.def', ts: 15000,
+ cat: 'blink.user_timing', pid: 1, tid: 2, ph: 'F'
+ }
+ ]
+ };
+
+ assert.throws(() => makeModel(events),
+ 'Inconsistent clock sync ID of legacy Chrome clock sync events');
+ // TODO(chiniforooshan): When the input is a trace stream, it is processed
+ // using the Oboe.js library. Oboe.js wraps exceptions thrown from callbacks
+ // and uses setTimeout to throw them in another event loop so that stream
+ // parsing is not interrupted.
+ //
+ // The importer's behaviour should be the same for different types of the
+ // same input. We should either modify Oboe.js to throw right away, or wrap
+ // exceptions in the importer, too.
+ });
+
+ test('importV8SamplesInStreamingFormat', function() {
+ function checkModel(m) {
+ const samples = m.samples;
+ assert.strictEqual(m.samples.length, 4);
+ assert.deepEqual(samples.map(sample => sample.start.toFixed(3)), [
+ '0.011',
+ '0.012',
+ '0.015',
+ '0.018'
+ ]);
+ assert.deepEqual(samples[0].userFriendlyStack, [
+ 'b url: b.js:1:2 Deoptimized reason: a reason',
+ 'a url: a.js:1:2'
+ ]);
+ assert.deepEqual(samples[1].userFriendlyStack, [
+ 'a url: a.js:1:2'
+ ]);
+ assert.deepEqual(samples[2].userFriendlyStack, [
+ 'd url: d.js:2:3 Deoptimized reason: another reason',
+ 'b url: b.js:1:2 Deoptimized reason: a reason',
+ 'a url: a.js:1:2'
+ ]);
+ assert.deepEqual(samples[3].userFriendlyStack, [
+ 'c url: c.js:2:3',
+ 'a url: a.js:1:2'
+ ]);
+ }
+
+ const events = {
+ 'traceEvents': [
+ {'pid': 1, 'tid': 2, 'ts': 3, 'ph': 'P',
+ 'cat': 'disabled-by-default-v8.cpu_profiler',
+ 'name': 'Profile',
+ 'args': {'data': {'startTime': 10}},
+ 'id': 123
+ },
+ {'pid': 1, 'tid': 3, 'ts': 4, 'ph': 'P',
+ 'cat': 'disabled-by-default-v8.cpu_profiler',
+ 'name': 'Profile',
+ 'args': {
+ 'data': {
+ 'timeDeltas': [1, 1],
+ 'cpuProfile': {
+ 'nodes': [
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': '(root)', 'scriptId': 0}, 'id': 1},
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': 'a', 'url': 'a.js', 'scriptId': 1, 'lineNumber': 1, 'columnNumber': 2}, 'id': 2, 'parent': 1},
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': 'b', 'url': 'b.js', 'scriptId': 2, 'lineNumber': 1, 'columnNumber': 2}, 'deoptReason': 'a reason', 'id': 3, 'parent': 2}
+ ],
+ 'samples': [3, 2]
+ }
+ }
+ },
+ 'id': 123
+ },
+ {'pid': 1, 'tid': 3, 'ts': 4, 'ph': 'P',
+ 'cat': 'disabled-by-default-v8.cpu_profiler',
+ 'name': 'Profile',
+ 'args': {
+ 'data': {
+ 'timeDeltas': [3, 3],
+ 'cpuProfile': {
+ 'nodes': [
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': 'c', 'url': 'c.js', 'scriptId': 3, 'lineNumber': 2, 'columnNumber': 3}, 'id': 4, 'parent': 2},
+ // eslint-disable-next-line
+ {'callFrame': {'functionName': 'd', 'url': 'd.js', 'scriptId': 4, 'lineNumber': 2, 'columnNumber': 3}, 'deoptReason': 'another reason', 'id': 5, 'parent': 3}
+ ],
+ 'samples': [5, 4]
+ }
+ }
+ },
+ 'id': 123
+ }
+ ]
+ };
+ checkParsedAndStreamInput(events, checkModel, false);
+ });
+
+ test('scopedIdForEvent_defaultScopeAsyncEvent', function() {
+ const event = {pid: 1, ph: 'b', id: '0x1000'};
+ const id = tr.e.importer.TraceEventImporter.scopedIdForEvent_(event);
+ assert.isDefined(id);
+ assert.strictEqual('0x1000', id.id);
+ assert.strictEqual('ptr', id.scope);
+ assert.isUndefined(id.pid);
+ });
+
+ test('scopedIdForEvent_defaultScopeContextEvent', function() {
+ const event = {pid: 1, ph: '(', id: '0x1000'};
+ const id = tr.e.importer.TraceEventImporter.scopedIdForEvent_(event);
+ assert.isDefined(id);
+ assert.strictEqual('0x1000', id.id);
+ assert.strictEqual('ptr', id.scope);
+ assert.strictEqual(1, id.pid);
+ });
+
+ test('scopedIdForEvent_defaultScopeProcessLocalId', function() {
+ const event = {pid: 1, ph: 'b', id2: {local: '0x1000'}};
+ const id = tr.e.importer.TraceEventImporter.scopedIdForEvent_(event);
+ assert.isDefined(id);
+ assert.strictEqual('0x1000', id.id);
+ assert.strictEqual('ptr', id.scope);
+ assert.strictEqual(1, id.pid);
+ });
+
+ test('scopedIdForEvent_defaultScopeGlobalId', function() {
+ const event = {pid: 1, ph: '(', id2: {global: '0x1000'}};
+ const id = tr.e.importer.TraceEventImporter.scopedIdForEvent_(event);
+ assert.isDefined(id);
+ assert.strictEqual('0x1000', id.id);
+ assert.strictEqual('ptr', id.scope);
+ assert.isUndefined(id.pid);
+ });
+
+ test('scopedIdForEvent_explicitScopeGlobalId', function() {
+ const event = {pid: 1, ph: '(', id2: {global: '0x1000'}, scope: 'scope'};
+ const id = tr.e.importer.TraceEventImporter.scopedIdForEvent_(event);
+ assert.isDefined(id);
+ assert.strictEqual('0x1000', id.id);
+ assert.strictEqual('scope', id.scope);
+ assert.isUndefined(id.pid);
+ });
+
+ // TODO(nduca): one slice, two threads
+ // TODO(nduca): one slice, two pids
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/codemap.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/codemap.html
new file mode 100644
index 00000000000..23fe39b7e37
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/codemap.html
@@ -0,0 +1,383 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/v8/splaytree.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Map addresses to dynamically created functions.
+ */
+tr.exportTo('tr.e.importer.v8', function() {
+ /**
+ * Constructs a mapper that maps addresses into code entries.
+ *
+ * @constructor
+ */
+ function CodeMap() {
+ /**
+ * Dynamic code entries. Used for JIT compiled code.
+ */
+ this.dynamics_ = new tr.e.importer.v8.SplayTree();
+
+ /**
+ * Name generator for entries having duplicate names.
+ */
+ this.dynamicsNameGen_ = new tr.e.importer.v8.CodeMap.NameGenerator();
+
+ /**
+ * Static code entries. Used for statically compiled code.
+ */
+ this.statics_ = new tr.e.importer.v8.SplayTree();
+
+ /**
+ * Libraries entries. Used for the whole static code libraries.
+ */
+ this.libraries_ = new tr.e.importer.v8.SplayTree();
+
+ /**
+ * Map of memory pages occupied with static code.
+ */
+ this.pages_ = [];
+ }
+
+ /**
+ * The number of alignment bits in a page address.
+ */
+ CodeMap.PAGE_ALIGNMENT = 12;
+
+ /**
+ * Page size in bytes.
+ */
+ CodeMap.PAGE_SIZE = 1 << CodeMap.PAGE_ALIGNMENT;
+
+ /**
+ * Adds a dynamic (i.e. moveable and discardable) code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+ CodeMap.prototype.addCode = function(start, codeEntry) {
+ this.deleteAllCoveredNodes_(this.dynamics_, start, start + codeEntry.size);
+ this.dynamics_.insert(start, codeEntry);
+ };
+
+ /**
+ * Moves a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} from The starting address of the entry being moved.
+ * @param {number} to The destination address.
+ */
+ CodeMap.prototype.moveCode = function(from, to) {
+ const removedNode = this.dynamics_.remove(from);
+ this.deleteAllCoveredNodes_(this.dynamics_, to,
+ to + removedNode.value.size);
+ this.dynamics_.insert(to, removedNode.value);
+ };
+
+ /**
+ * Discards a dynamic code entry. Throws an exception if there is no dynamic
+ * code entry with the specified starting address.
+ *
+ * @param {number} start The starting address of the entry being deleted.
+ */
+ CodeMap.prototype.deleteCode = function(start) {
+ const removedNode = this.dynamics_.remove(start);
+ };
+
+ /**
+ * Adds a library entry.
+ *
+ * @param {number} start The starting address.
+ * @param {CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+ CodeMap.prototype.addLibrary = function(
+ start, codeEntry) {
+ this.markPages_(start, start + codeEntry.size);
+ this.libraries_.insert(start, codeEntry);
+ };
+
+ /**
+ * Adds a static code entry.
+ *
+ * @param {number} start The starting address.
+ * @param {CodeMap.CodeEntry} codeEntry Code entry object.
+ */
+ CodeMap.prototype.addStaticCode = function(
+ start, codeEntry) {
+ this.statics_.insert(start, codeEntry);
+ };
+
+ /**
+ * @private
+ */
+ CodeMap.prototype.markPages_ = function(start, end) {
+ for (let addr = start; addr <= end;
+ addr += CodeMap.PAGE_SIZE) {
+ this.pages_[addr >>> CodeMap.PAGE_ALIGNMENT] = 1;
+ }
+ };
+
+ /**
+ * @private
+ */
+ CodeMap.prototype.deleteAllCoveredNodes_ = function(tree, start, end) {
+ const toDelete = [];
+ let addr = end - 1;
+ while (addr >= start) {
+ const node = tree.findGreatestLessThan(addr);
+ if (!node) break;
+ const start2 = node.key;
+ const end2 = start2 + node.value.size;
+ if (start2 < end && start < end2) toDelete.push(start2);
+ addr = start2 - 1;
+ }
+ for (let i = 0, l = toDelete.length; i < l; ++i) tree.remove(toDelete[i]);
+ };
+
+ /**
+ * @private
+ */
+ CodeMap.prototype.isAddressBelongsTo_ = function(addr, node) {
+ return addr >= node.key && addr < (node.key + node.value.size);
+ };
+
+ /**
+ * @private
+ */
+ CodeMap.prototype.findInTree_ = function(tree, addr) {
+ const node = tree.findGreatestLessThan(addr);
+ return node && this.isAddressBelongsTo_(addr, node) ? node.value : null;
+ };
+
+ /**
+ * Finds a code entry that contains the specified address in static libraries.
+ *
+ * @param {number} addr Address.
+ */
+ CodeMap.prototype.findEntryInLibraries = function(addr) {
+ const pageAddr = addr >>> CodeMap.PAGE_ALIGNMENT;
+ if (pageAddr in this.pages_) {
+ return this.findInTree_(this.libraries_, addr);
+ }
+ return undefined;
+ };
+
+ /**
+ * Finds a code entry that contains the specified address. Both static and
+ * dynamic code entries are considered.
+ *
+ * @param {number} addr Address.
+ */
+ CodeMap.prototype.findEntry = function(addr) {
+ const pageAddr = addr >>> CodeMap.PAGE_ALIGNMENT;
+ if (pageAddr in this.pages_) {
+ // Static code entries can contain "holes" of unnamed code.
+ // In this case, the whole library is assigned to this address.
+ return this.findInTree_(this.statics_, addr) ||
+ this.findInTree_(this.libraries_, addr);
+ }
+ const min = this.dynamics_.findMin();
+ const max = this.dynamics_.findMax();
+ if (max !== null && addr < (max.key + max.value.size) && addr >= min.key) {
+ const dynaEntry = this.findInTree_(this.dynamics_, addr);
+ if (dynaEntry === null) return null;
+ // Dedupe entry name.
+ if (!dynaEntry.nameUpdated_) {
+ dynaEntry.name = this.dynamicsNameGen_.getName(dynaEntry.name);
+ dynaEntry.nameUpdated_ = true;
+ }
+ return dynaEntry;
+ }
+ return null;
+ };
+
+ /**
+ * Returns a dynamic code entry using its starting address.
+ *
+ * @param {number} addr Address.
+ */
+ CodeMap.prototype.findDynamicEntryByStartAddress =
+ function(addr) {
+ const node = this.dynamics_.find(addr);
+ return node ? node.value : null;
+ };
+
+ /**
+ * Returns an array of all dynamic code entries.
+ */
+ CodeMap.prototype.getAllDynamicEntries = function() {
+ return this.dynamics_.exportValues();
+ };
+
+ /**
+ * Returns an array of pairs of all dynamic code entries and their addresses.
+ */
+ CodeMap.prototype.getAllDynamicEntriesWithAddresses = function() {
+ return this.dynamics_.exportKeysAndValues();
+ };
+
+ /**
+ * Returns an array of all static code entries.
+ */
+ CodeMap.prototype.getAllStaticEntries = function() {
+ return this.statics_.exportValues();
+ };
+
+ /**
+ * Returns an array of all libraries entries.
+ */
+ CodeMap.prototype.getAllLibrariesEntries = function() {
+ return this.libraries_.exportValues();
+ };
+
+ /**
+ * Enum for code state regarding its dynamic optimization.
+ *
+ * @enum {number}
+ */
+ CodeMap.CodeState = {
+ COMPILED: 0,
+ OPTIMIZABLE: 1,
+ OPTIMIZED: 2
+ };
+
+ /**
+ * Creates a code entry object.
+ *
+ * @param {number} size Code entry size in bytes.
+ * @param {string=} opt_name Code entry name.
+ * @constructor
+ */
+ CodeMap.CodeEntry = function(size, opt_name, opt_type) {
+ this.id = tr.b.GUID.allocateSimple();
+ this.size = size;
+ this.name_ = opt_name || '';
+ this.type = opt_type || '';
+ this.nameUpdated_ = false;
+ };
+
+ CodeMap.CodeEntry.prototype = {
+ __proto__: Object.prototype,
+
+ get name() {
+ return this.name_;
+ },
+
+ set name(value) {
+ this.name_ = value;
+ },
+
+ toString() {
+ this.name_ + ': ' + this.size.toString(16);
+ }
+ };
+
+ CodeMap.CodeEntry.TYPE = {
+ SHARED_LIB: 'SHARED_LIB',
+ CPP: 'CPP'
+ };
+
+ /**
+ * Creates a dynamic code entry.
+ *
+ * @param {number} size Code size.
+ * @param {string} type Code type.
+ * @param {CodeMap.FunctionEntry} func Shared function entry.
+ * @param {CodeMap.CodeState} state Code optimization state.
+ * @constructor
+ */
+ CodeMap.DynamicFuncCodeEntry = function(size, type, func, state) {
+ CodeMap.CodeEntry.call(this, size, '', type);
+ this.func = func;
+ this.state = state;
+ };
+
+ CodeMap.DynamicFuncCodeEntry.STATE_PREFIX = ['', '~', '*'];
+
+ CodeMap.DynamicFuncCodeEntry.prototype = {
+ __proto__: CodeMap.CodeEntry.prototype,
+
+ /**
+ * Returns node name.
+ */
+ get name() {
+ return CodeMap.DynamicFuncCodeEntry.STATE_PREFIX[this.state] +
+ this.func.name;
+ },
+
+ set name(value) {
+ this.name_ = value;
+ },
+
+ /**
+ * Returns raw node name (without type decoration).
+ */
+ getRawName() {
+ return this.func.getName();
+ },
+
+ isJSFunction() {
+ return true;
+ },
+
+ toString() {
+ return this.type + ': ' + this.name + ': ' + this.size.toString(16);
+ }
+ };
+
+ /**
+ * Creates a shared function object entry.
+ *
+ * @param {string} name Function name.
+ * @constructor
+ */
+ CodeMap.FunctionEntry = function(name) {
+ CodeMap.CodeEntry.call(this, 0, name);
+ };
+
+ CodeMap.FunctionEntry.prototype = {
+ __proto__: CodeMap.CodeEntry.prototype,
+
+ /**
+ * Returns node name.
+ */
+ get name() {
+ let name = this.name_;
+ if (name.length === 0) {
+ name = '<anonymous>';
+ } else if (name.charAt(0) === ' ') {
+ // An anonymous function with location: " aaa.js:10".
+ name = '<anonymous>' + name;
+ }
+ return name;
+ },
+
+ set name(value) {
+ this.name_ = value;
+ }
+ };
+
+ CodeMap.NameGenerator = function() {
+ this.knownNames_ = {};
+ };
+
+ CodeMap.NameGenerator.prototype.getName = function(name) {
+ if (!(name in this.knownNames_)) {
+ this.knownNames_[name] = 0;
+ return name;
+ }
+ const count = ++this.knownNames_[name];
+ return name + ' {' + count + '}';
+ };
+ return {
+ CodeMap,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/log_reader.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/log_reader.html
new file mode 100644
index 00000000000..70ac3349b81
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/log_reader.html
@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Log Reader is used to process log file produced by V8.
+ */
+tr.exportTo('tr.e.importer.v8', function() {
+ /**
+ * Creates a CSV lines parser.
+ */
+ function CsvParser() { }
+
+ /**
+ * A regex for matching a CSV field.
+ * @private
+ */
+ CsvParser.CSV_FIELD_RE_ = /^"((?:[^"]|"")*)"|([^,]*)/;
+
+ /**
+ * A regex for matching a double quote.
+ * @private
+ */
+ CsvParser.DOUBLE_QUOTE_RE_ = /""/g;
+
+ /**
+ * Parses a line of CSV-encoded values. Returns an array of fields.
+ *
+ * @param {string} line Input line.
+ */
+ CsvParser.prototype.parseLine = function(line) {
+ const fieldRe = CsvParser.CSV_FIELD_RE_;
+ const doubleQuoteRe = CsvParser.DOUBLE_QUOTE_RE_;
+ let pos = 0;
+ const endPos = line.length;
+ const fields = [];
+ if (endPos > 0) {
+ do {
+ const fieldMatch = fieldRe.exec(line.substr(pos));
+ if (typeof fieldMatch[1] === 'string') {
+ const field = fieldMatch[1];
+ pos += field.length + 3; // Skip comma and quotes.
+ fields.push(field.replace(doubleQuoteRe, '"'));
+ } else {
+ // The second field pattern will match anything, thus
+ // in the worst case the match will be an empty string.
+ const field = fieldMatch[2];
+ pos += field.length + 1; // Skip comma.
+ fields.push(field);
+ }
+ } while (pos <= endPos);
+ }
+ return fields;
+ };
+
+ /**
+ * Base class for processing log files.
+ *
+ * @param {Array.<Object>} dispatchTable A table used for parsing and
+ * processing log records.
+ *
+ * @constructor
+ */
+ function LogReader(dispatchTable) {
+ /**
+ * @type {Array.<Object>}
+ */
+ this.dispatchTable_ = dispatchTable;
+
+ /**
+ * Current line.
+ * @type {number}
+ */
+ this.lineNum_ = 0;
+
+ /**
+ * CSV lines parser.
+ * @type {CsvParser}
+ */
+ this.csvParser_ = new CsvParser();
+ }
+
+ /**
+ * Used for printing error messages.
+ *
+ * @param {string} str Error message.
+ */
+ LogReader.prototype.printError = function(str) {
+ // Do nothing.
+ };
+
+ /**
+ * Processes a portion of V8 profiler event log.
+ *
+ * @param {string} chunk A portion of log.
+ */
+ LogReader.prototype.processLogChunk = function(chunk) {
+ this.processLog_(chunk.split('\n'));
+ };
+
+ /**
+ * Processes a line of V8 profiler event log.
+ *
+ * @param {string} line A line of log.
+ */
+ LogReader.prototype.processLogLine = function(line) {
+ this.processLog_([line]);
+ };
+
+ /**
+ * Processes stack record.
+ *
+ * @param {number} pc Program counter.
+ * @param {number} func JS Function.
+ * @param {Array.<string>} stack String representation of a stack.
+ * @return {Array.<number>} Processed stack.
+ */
+ LogReader.prototype.processStack = function(pc, func, stack) {
+ const fullStack = func ? [pc, func] : [pc];
+ let prevFrame = pc;
+ for (let i = 0, n = stack.length; i < n; ++i) {
+ const frame = stack[i];
+ const firstChar = frame.charAt(0);
+ if (firstChar === '+' || firstChar === '-') {
+ // An offset from the previous frame.
+ prevFrame += parseInt(frame, 16);
+ fullStack.push(prevFrame);
+ // Filter out possible 'overflow' string.
+ } else if (firstChar !== 'o') {
+ fullStack.push(parseInt(frame, 16));
+ }
+ }
+ return fullStack;
+ };
+
+ /**
+ * Returns whether a particular dispatch must be skipped.
+ *
+ * @param {!Object} dispatch Dispatch record.
+ * @return {boolean} True if dispatch must be skipped.
+ */
+ LogReader.prototype.skipDispatch = function(dispatch) {
+ return false;
+ };
+
+ /**
+ * Does a dispatch of a log record.
+ *
+ * @param {Array.<string>} fields Log record.
+ * @private
+ */
+ LogReader.prototype.dispatchLogRow_ = function(fields) {
+ // Obtain the dispatch.
+ const command = fields[0];
+ if (!(command in this.dispatchTable_)) return;
+
+ const dispatch = this.dispatchTable_[command];
+
+ if (dispatch === null || this.skipDispatch(dispatch)) {
+ return;
+ }
+
+ // Parse fields.
+ const parsedFields = [];
+ for (let i = 0; i < dispatch.parsers.length; ++i) {
+ const parser = dispatch.parsers[i];
+ if (parser === null) {
+ parsedFields.push(fields[1 + i]);
+ } else if (typeof parser === 'function') {
+ parsedFields.push(parser(fields[1 + i]));
+ } else {
+ // var-args
+ parsedFields.push(fields.slice(1 + i));
+ break;
+ }
+ }
+
+ // Run the processor.
+ dispatch.processor.apply(this, parsedFields);
+ };
+
+ /**
+ * Processes log lines.
+ *
+ * @param {Array.<string>} lines Log lines.
+ * @private
+ */
+ LogReader.prototype.processLog_ = function(lines) {
+ for (let i = 0, n = lines.length; i < n; ++i, ++this.lineNum_) {
+ const line = lines[i];
+ if (!line) {
+ continue;
+ }
+ try {
+ const fields = this.csvParser_.parseLine(line);
+ this.dispatchLogRow_(fields);
+ } catch (e) {
+ this.printError('line ' + (this.lineNum_ + 1) + ': ' +
+ (e.message || e));
+ }
+ }
+ };
+ return {
+ LogReader,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/splaytree.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/splaytree.html
new file mode 100644
index 00000000000..3498b15658d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/splaytree.html
@@ -0,0 +1,295 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Splay tree used by CodeMap.
+ */
+tr.exportTo('tr.e.importer.v8', function() {
+ /**
+ * Constructs a Splay tree. A splay tree is a self-balancing binary
+ * search tree with the additional property that recently accessed
+ * elements are quick to access again. It performs basic operations
+ * such as insertion, look-up and removal in O(log(n)) amortized time.
+ *
+ * @constructor
+ */
+ function SplayTree() { }
+
+ /**
+ * Pointer to the root node of the tree.
+ *
+ * @type {SplayTree.Node}
+ * @private
+ */
+ SplayTree.prototype.root_ = null;
+
+ /**
+ * @return {boolean} Whether the tree is empty.
+ */
+ SplayTree.prototype.isEmpty = function() {
+ return !this.root_;
+ };
+
+ /**
+ * Inserts a node into the tree with the specified key and value if
+ * the tree does not already contain a node with the specified key. If
+ * the value is inserted, it becomes the root of the tree.
+ *
+ * @param {number} key Key to insert into the tree.
+ * @param {*} value Value to insert into the tree.
+ */
+ SplayTree.prototype.insert = function(key, value) {
+ if (this.isEmpty()) {
+ this.root_ = new SplayTree.Node(key, value);
+ return;
+ }
+ // Splay on the key to move the last node on the search path for
+ // the key to the root of the tree.
+ this.splay_(key);
+ if (this.root_.key === key) {
+ return;
+ }
+ const node = new SplayTree.Node(key, value);
+ if (key > this.root_.key) {
+ node.left = this.root_;
+ node.right = this.root_.right;
+ this.root_.right = null;
+ } else {
+ node.right = this.root_;
+ node.left = this.root_.left;
+ this.root_.left = null;
+ }
+ this.root_ = node;
+ };
+
+
+ /**
+ * Removes a node with the specified key from the tree if the tree
+ * contains a node with this key. The removed node is returned. If the
+ * key is not found, an exception is thrown.
+ *
+ * @param {number} key Key to find and remove from the tree.
+ * @return {SplayTree.Node} The removed node.
+ */
+ SplayTree.prototype.remove = function(key) {
+ if (this.isEmpty()) {
+ throw Error('Key not found: ' + key);
+ }
+ this.splay_(key);
+ if (this.root_.key !== key) {
+ throw Error('Key not found: ' + key);
+ }
+ const removed = this.root_;
+ if (!this.root_.left) {
+ this.root_ = this.root_.right;
+ } else {
+ const right = this.root_.right;
+ this.root_ = this.root_.left;
+ // Splay to make sure that the new root has an empty right child.
+ this.splay_(key);
+ // Insert the original right child as the right child of the new
+ // root.
+ this.root_.right = right;
+ }
+ return removed;
+ };
+
+
+ /**
+ * Returns the node having the specified key or null if the tree doesn't
+ * contain a node with the specified key.
+ *
+ *
+ * @param {number} key Key to find in the tree.
+ * @return {SplayTree.Node} Node having the specified key.
+ */
+ SplayTree.prototype.find = function(key) {
+ if (this.isEmpty()) return null;
+ this.splay_(key);
+ return this.root_.key === key ? this.root_ : null;
+ };
+
+ /**
+ * @return {SplayTree.Node} Node having the minimum key value.
+ */
+ SplayTree.prototype.findMin = function() {
+ if (this.isEmpty()) return null;
+ let current = this.root_;
+ while (current.left) {
+ current = current.left;
+ }
+ return current;
+ };
+
+ /**
+ * @return {SplayTree.Node} Node having the maximum key value.
+ */
+ SplayTree.prototype.findMax = function(opt_startNode) {
+ if (this.isEmpty()) return null;
+ let current = opt_startNode || this.root_;
+ while (current.right) {
+ current = current.right;
+ }
+ return current;
+ };
+
+ /**
+ * @return {SplayTree.Node} Node having the maximum key value that
+ * is less or equal to the specified key value.
+ */
+ SplayTree.prototype.findGreatestLessThan = function(key) {
+ if (this.isEmpty()) return null;
+ // Splay on the key to move the node with the given key or the last
+ // node on the search path to the top of the tree.
+ this.splay_(key);
+ // Now the result is either the root node or the greatest node in
+ // the left subtree.
+ if (this.root_.key <= key) {
+ return this.root_;
+ }
+ if (this.root_.left) {
+ return this.findMax(this.root_.left);
+ }
+ return null;
+ };
+
+ /**
+ * @return {Array<*>} An array containing all the values of tree's nodes
+ * paired with keys.
+ *
+ */
+ SplayTree.prototype.exportKeysAndValues = function() {
+ const result = [];
+ this.traverse_(function(node) { result.push([node.key, node.value]); });
+ return result;
+ };
+
+ /**
+ * @return {Array<*>} An array containing all the values of tree's nodes.
+ */
+ SplayTree.prototype.exportValues = function() {
+ const result = [];
+ this.traverse_(function(node) { result.push(node.value); });
+ return result;
+ };
+
+ /**
+ * Perform the splay operation for the given key. Moves the node with
+ * the given key to the top of the tree. If no node has the given
+ * key, the last node on the search path is moved to the top of the
+ * tree. This is the simplified top-down splaying algorithm from:
+ * "Self-adjusting Binary Search Trees" by Sleator and Tarjan
+ *
+ * @param {number} key Key to splay the tree on.
+ * @private
+ */
+ SplayTree.prototype.splay_ = function(key) {
+ if (this.isEmpty()) return;
+ // Create a dummy node. The use of the dummy node is a bit
+ // counter-intuitive: The right child of the dummy node will hold
+ // the L tree of the algorithm. The left child of the dummy node
+ // will hold the R tree of the algorithm. Using a dummy node, left
+ // and right will always be nodes and we avoid special cases.
+ const dummy = new SplayTree.Node(null, null);
+ let left = dummy;
+ let right = dummy;
+ let current = this.root_;
+ while (true) {
+ if (key < current.key) {
+ if (!current.left) {
+ break;
+ }
+ if (key < current.left.key) {
+ // Rotate right.
+ const tmp = current.left;
+ current.left = tmp.right;
+ tmp.right = current;
+ current = tmp;
+ if (!current.left) {
+ break;
+ }
+ }
+ // Link right.
+ right.left = current;
+ right = current;
+ current = current.left;
+ } else if (key > current.key) {
+ if (!current.right) {
+ break;
+ }
+ if (key > current.right.key) {
+ // Rotate left.
+ const tmp = current.right;
+ current.right = tmp.left;
+ tmp.left = current;
+ current = tmp;
+ if (!current.right) {
+ break;
+ }
+ }
+ // Link left.
+ left.right = current;
+ left = current;
+ current = current.right;
+ } else {
+ break;
+ }
+ }
+ // Assemble.
+ left.right = current.left;
+ right.left = current.right;
+ current.left = dummy.right;
+ current.right = dummy.left;
+ this.root_ = current;
+ };
+
+ /**
+ * Performs a preorder traversal of the tree.
+ *
+ * @param {function(SplayTree.Node)} f Visitor function.
+ * @private
+ */
+ SplayTree.prototype.traverse_ = function(f) {
+ const nodesToVisit = [this.root_];
+ while (nodesToVisit.length > 0) {
+ const node = nodesToVisit.shift();
+ if (node === null) continue;
+ f(node);
+ nodesToVisit.push(node.left);
+ nodesToVisit.push(node.right);
+ }
+ };
+
+ /**
+ * Constructs a Splay tree node.
+ *
+ * @param {number} key Key.
+ * @param {*} value Value.
+ */
+ SplayTree.Node = function(key, value) {
+ this.key = key;
+ this.value = value;
+ };
+
+ /**
+ * @type {SplayTree.Node}
+ */
+ SplayTree.Node.prototype.left = null;
+
+ /**
+ * @type {SplayTree.Node}
+ */
+ SplayTree.Node.prototype.right = null;
+
+ return {
+ SplayTree,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/v8_log_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/v8_log_importer.html
new file mode 100644
index 00000000000..74b140beafe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/v8_log_importer.html
@@ -0,0 +1,393 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/extras/importer/v8/codemap.html">
+<link rel="import" href="/tracing/extras/importer/v8/log_reader.html">
+<link rel="import" href="/tracing/extras/v8/v8_cpu_profile_node.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/profile_tree.html">
+<link rel="import" href="/tracing/model/slice.html">
+
+<script>
+
+'use strict';
+
+/**
+ * @fileoverview V8LogImporter imports v8.log files into the provided model.
+ */
+tr.exportTo('tr.e.importer.v8', function() {
+ const CodeEntry = tr.e.importer.v8.CodeMap.CodeEntry;
+ const CodeMap = tr.e.importer.v8.CodeMap;
+ const ColorScheme = tr.b.ColorScheme;
+ const DynamicFuncCodeEntry = tr.e.importer.v8.CodeMap.DynamicFuncCodeEntry;
+ const FunctionEntry = tr.e.importer.v8.CodeMap.FunctionEntry;
+ const ProfileNodeType = tr.model.ProfileNode.subTypes.getConstructor(
+ undefined, 'legacySample');
+
+ function V8LogImporter(model, eventData) {
+ this.importPriority = 3;
+ this.model_ = model;
+
+ this.logData_ = eventData;
+
+ this.code_map_ = new CodeMap();
+ this.v8_timer_thread_ = undefined;
+ this.v8_thread_ = undefined;
+
+ this.profileTree_ = new tr.model.ProfileTree();
+ // We predefine a unknown Profile Node so that when a stack address
+ // can't be symbolized, we make it attach to the unknown Profile Node.
+ this.profileTree_.add(new ProfileNodeType(
+ -1, {
+ url: '',
+ functionName: 'unknown'
+ }
+ ));
+
+ // We reconstruct the stack timeline from ticks.
+ this.v8_stack_timeline_ = [];
+ }
+
+ const kV8BinarySuffixes = ['/d8', '/libv8.so'];
+
+
+ const TimerEventDefaultArgs = {
+ 'V8.Execute': { pause: false, no_execution: false},
+ 'V8.External': { pause: false, no_execution: true},
+ 'V8.CompileFullCode': { pause: true, no_execution: true},
+ 'V8.RecompileSynchronous': { pause: true, no_execution: true},
+ 'V8.RecompileParallel': { pause: false, no_execution: false},
+ 'V8.CompileEval': { pause: true, no_execution: true},
+ 'V8.Parse': { pause: true, no_execution: true},
+ 'V8.PreParse': { pause: true, no_execution: true},
+ 'V8.ParseLazy': { pause: true, no_execution: true},
+ 'V8.GCScavenger': { pause: true, no_execution: true},
+ 'V8.GCCompactor': { pause: true, no_execution: true},
+ 'V8.GCContext': { pause: true, no_execution: true}
+ };
+
+ /**
+ * @return {boolean} Whether obj is a V8 log string.
+ */
+ V8LogImporter.canImport = function(eventData) {
+ if (typeof(eventData) !== 'string' && !(eventData instanceof String)) {
+ return false;
+ }
+
+ return eventData.substring(0, 11) === 'v8-version,' ||
+ eventData.substring(0, 12) === 'timer-event,' ||
+ eventData.substring(0, 5) === 'tick,' ||
+ eventData.substring(0, 15) === 'shared-library,' ||
+ eventData.substring(0, 9) === 'profiler,' ||
+ eventData.substring(0, 14) === 'code-creation,';
+ };
+
+ V8LogImporter.prototype = {
+
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'V8LogImporter';
+ },
+
+ processTimerEvent_(name, startInUs, lengthInUs) {
+ const args = TimerEventDefaultArgs[name];
+ if (args === undefined) return;
+ const startInMs = tr.b.convertUnit(startInUs,
+ tr.b.UnitPrefixScale.METRIC.MICRO,
+ tr.b.UnitPrefixScale.METRIC.MILLI);
+ const lengthInMs = tr.b.convertUnit(lengthInUs,
+ tr.b.UnitPrefixScale.METRIC.MICRO,
+ tr.b.UnitPrefixScale.METRIC.MILLI);
+ const colorId = ColorScheme.getColorIdForGeneralPurposeString(name);
+ const slice = new tr.model.ThreadSlice('v8', name, colorId, startInMs,
+ args, lengthInMs);
+ this.v8_timer_thread_.sliceGroup.pushSlice(slice);
+ },
+
+ processTimerEventStart_(name, startInUs) {
+ const args = TimerEventDefaultArgs[name];
+ if (args === undefined) return;
+ const startInMs = tr.b.convertUnit(startInUs,
+ tr.b.UnitPrefixScale.METRIC.MICRO,
+ tr.b.UnitPrefixScale.METRIC.MILLI);
+ this.v8_timer_thread_.sliceGroup.beginSlice('v8', name, startInMs, args);
+ },
+
+ processTimerEventEnd_(name, endInUs) {
+ const endInMs = tr.b.convertUnit(endInUs,
+ tr.b.UnitPrefixScale.METRIC.MICRO,
+ tr.b.UnitPrefixScale.METRIC.MILLI);
+ this.v8_timer_thread_.sliceGroup.endSlice(endInMs);
+ },
+
+ processCodeCreateEvent_(type, kind, address, size, name,
+ maybeFunc) {
+ function parseState(s) {
+ switch (s) {
+ case '': return CodeMap.CodeState.COMPILED;
+ case '~': return CodeMap.CodeState.OPTIMIZABLE;
+ case '*': return CodeMap.CodeState.OPTIMIZED;
+ }
+ throw new Error('unknown code state: ' + s);
+ }
+
+ if (maybeFunc.length) {
+ const funcAddr = parseInt(maybeFunc[0]);
+ const state = parseState(maybeFunc[1]);
+ let func = this.code_map_.findDynamicEntryByStartAddress(funcAddr);
+ if (!func) {
+ func = new FunctionEntry(name);
+ func.kind = kind;
+ this.code_map_.addCode(funcAddr, func);
+ } else if (func.name !== name) {
+ // Function object has been overwritten with a new one.
+ func.name = name;
+ }
+ let entry = this.code_map_.findDynamicEntryByStartAddress(address);
+ if (entry) {
+ if (entry.size === size && entry.func === func) {
+ // Entry state has changed.
+ entry.state = state;
+ }
+ } else {
+ entry = new DynamicFuncCodeEntry(size, type, func, state);
+ entry.kind = kind;
+ this.code_map_.addCode(address, entry);
+ }
+ } else {
+ const codeEntry = new CodeEntry(size, name);
+ codeEntry.kind = kind;
+ this.code_map_.addCode(address, codeEntry);
+ }
+ },
+
+ processCodeMoveEvent_(from, to) {
+ this.code_map_.moveCode(from, to);
+ },
+
+ processCodeDeleteEvent_(address) {
+ this.code_map_.deleteCode(address);
+ },
+
+ processSharedLibrary_(name, start, end) {
+ const codeEntry = new CodeEntry(end - start, name,
+ CodeEntry.TYPE.SHARED_LIB);
+ codeEntry.kind = -3; // External code kind.
+ for (let i = 0; i < kV8BinarySuffixes.length; i++) {
+ const suffix = kV8BinarySuffixes[i];
+ if (name.indexOf(suffix, name.length - suffix.length) >= 0) {
+ codeEntry.kind = -1; // V8 runtime code kind.
+ break;
+ }
+ }
+ this.code_map_.addLibrary(start, codeEntry);
+ },
+
+ processCppSymbol_(address, size, name) {
+ const codeEntry = new CodeEntry(size, name, CodeEntry.TYPE.CPP);
+ codeEntry.kind = -1;
+ this.code_map_.addStaticCode(address, codeEntry);
+ },
+
+ processTickEvent_(pc, startInUs, isExternalCallback,
+ tosOrExternalCallback, vmstate, stack) {
+ const startInMs = tr.b.convertUnit(startInUs,
+ tr.b.UnitPrefixScale.METRIC.MICRO,
+ tr.b.UnitPrefixScale.METRIC.MILLI);
+
+ function findChildWithEntryID(stackFrame, entryID) {
+ for (let i = 0; i < stackFrame.children.length; i++) {
+ if (stackFrame.children[i].entryID === entryID) {
+ return stackFrame.children[i];
+ }
+ }
+ return undefined;
+ }
+
+ function processStack(pc, func, stack) {
+ const fullStack = func ? [pc, func] : [pc];
+ let prevFrame = pc;
+ for (let i = 0, n = stack.length; i < n; ++i) {
+ const frame = stack[i];
+ const firstChar = frame.charAt(0);
+ if (firstChar === '+' || firstChar === '-') {
+ // An offset from the previous frame.
+ prevFrame += parseInt(frame, 16);
+ fullStack.push(prevFrame);
+ // Filter out possible 'overflow' string.
+ } else if (firstChar !== 'o') {
+ fullStack.push(parseInt(frame, 16));
+ }
+ // Otherwise, they will be skipped.
+ }
+ return fullStack;
+ }
+
+ if (isExternalCallback) {
+ // Don't use PC when in external callback code, as it can point
+ // inside callback's code, and we will erroneously report
+ // that a callback calls itself. Instead use tosOrExternalCallback,
+ // as simply resetting PC will produce unaccounted ticks.
+ pc = tosOrExternalCallback;
+ tosOrExternalCallback = 0;
+ } else if (tosOrExternalCallback) {
+ // Find out, if top of stack was pointing inside a JS function
+ // meaning that we have encountered a frameless invocation.
+ const funcEntry = this.code_map_.findEntry(tosOrExternalCallback);
+ if (!funcEntry ||
+ !funcEntry.isJSFunction ||
+ !funcEntry.isJSFunction()) {
+ tosOrExternalCallback = 0;
+ }
+ }
+
+ let processedStack = processStack(pc, tosOrExternalCallback, stack);
+ let node = undefined;
+ let lastNode = undefined;
+ // v8 log stacks are inverted, leaf first and the root at the end.
+ processedStack = processedStack.reverse();
+ for (let i = 0, n = processedStack.length; i < n; i++) {
+ const frame = processedStack[i];
+ if (!frame) break;
+ const entry = this.code_map_.findEntry(frame);
+
+ if (!entry && i !== 0) {
+ continue;
+ }
+
+ let sourceInfo = undefined;
+ if (entry && entry.type === CodeEntry.TYPE.CPP) {
+ const libEntry = this.code_map_.findEntryInLibraries(frame);
+ if (libEntry) {
+ sourceInfo = {
+ file: libEntry.name
+ };
+ }
+ }
+ const entryId = entry ? entry.id : -1;
+ node = this.profileTree_.getNode(entryId);
+ if (node === undefined) {
+ node = this.profileTree_.add(new ProfileNodeType(
+ entryId, {
+ functionName: entry.name,
+ url: sourceInfo ? sourceInfo.file : '',
+ lineNumber: sourceInfo ? sourceInfo.line : undefined,
+ columnNumber: sourceInfo ? sourceInfo.column : undefined,
+ scriptId: sourceInfo ? sourceInfo.scriptId : undefined
+ }, lastNode));
+ }
+ lastNode = node;
+ }
+ this.model_.samples.push(new tr.model.Sample(
+ startInMs, 'V8 PC', node, this.v8_thread_, undefined, 1));
+ },
+
+ processDistortion_(distortionInPicoseconds) {
+ // Do nothing.
+ },
+
+ processPlotRange_(start, end) {
+ // Do nothing.
+ },
+
+ processV8Version_(major, minor, build, patch, candidate) {
+ // Do nothing.
+ },
+
+ /**
+ * Walks through the events_ list and outputs the structures discovered to
+ * model_.
+ */
+ importEvents() {
+ const logreader = new tr.e.importer.v8.LogReader(
+ { 'timer-event': {
+ parsers: [null, parseInt, parseInt],
+ processor: this.processTimerEvent_.bind(this)
+ },
+ 'shared-library': {
+ parsers: [null, parseInt, parseInt],
+ processor: this.processSharedLibrary_.bind(this)
+ },
+ 'timer-event-start': {
+ parsers: [null, parseInt],
+ processor: this.processTimerEventStart_.bind(this)
+ },
+ 'timer-event-end': {
+ parsers: [null, parseInt],
+ processor: this.processTimerEventEnd_.bind(this)
+ },
+ 'code-creation': {
+ parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
+ processor: this.processCodeCreateEvent_.bind(this)
+ },
+ 'code-move': {
+ parsers: [parseInt, parseInt],
+ processor: this.processCodeMoveEvent_.bind(this)
+ },
+ 'code-delete': {
+ parsers: [parseInt],
+ processor: this.processCodeDeleteEvent_.bind(this)
+ },
+ 'cpp': {
+ parsers: [parseInt, parseInt, null],
+ processor: this.processCppSymbol_.bind(this)
+ },
+ 'tick': {
+ parsers: [parseInt, parseInt, parseInt, parseInt, parseInt,
+ 'var-args'],
+ processor: this.processTickEvent_.bind(this)
+ },
+ 'distortion': {
+ parsers: [parseInt],
+ processor: this.processDistortion_.bind(this)
+ },
+ 'plot-range': {
+ parsers: [parseInt, parseInt],
+ processor: this.processPlotRange_.bind(this)
+ },
+ 'v8-version': {
+ parsers: [parseInt, parseInt, parseInt, parseInt, parseInt],
+ processor: this.processV8Version_.bind(this)
+ }
+ });
+
+ this.v8_timer_thread_ =
+ this.model_.getOrCreateProcess(-32).getOrCreateThread(1);
+ this.v8_timer_thread_.name = 'V8 Timers';
+ this.v8_thread_ =
+ this.model_.getOrCreateProcess(-32).getOrCreateThread(2);
+ this.v8_thread_.name = 'V8';
+
+ const lines = this.logData_.split('\n');
+ for (let i = 0; i < lines.length; i++) {
+ logreader.processLogLine(lines[i]);
+ }
+
+ function addSlices(slices, thread) {
+ for (let i = 0; i < slices.length; i++) {
+ const duration = slices[i].end - slices[i].start;
+ const slice = new tr.model.ThreadSlice('v8', slices[i].name,
+ ColorScheme.getColorIdForGeneralPurposeString(slices[i].name),
+ slices[i].start, {}, duration);
+ thread.sliceGroup.pushSlice(slice);
+ addSlices(slices[i].children, thread);
+ }
+ }
+ addSlices(this.v8_stack_timeline_, this.v8_thread_);
+ }
+ };
+
+ tr.importer.Importer.register(V8LogImporter);
+
+ return {
+ V8LogImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/v8_log_importer_test.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/v8_log_importer_test.html
new file mode 100644
index 00000000000..e9db2f92334
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/v8/v8_log_importer_test.html
@@ -0,0 +1,290 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/v8/v8_log_importer.html">
+<link rel="import" href="/tracing/extras/v8_config.html">
+
+<script>
+
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const V8LogImporter = tr.e.importer.v8.V8LogImporter;
+
+ function newModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('tickEventInSharedLibrary', function() {
+ const lines = [
+ 'shared-library,"/usr/lib/libc++.1.dylib",0x99d8aae0,0x99dce729',
+ 'tick,0x99d8aae4,12158,0,0x0,5'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const t = p.findAllThreadsNamed('V8')[0];
+ assert.strictEqual(t.samples.length, 1);
+ assert.strictEqual(t.samples[0].title, 'V8 PC');
+ assert.strictEqual(t.samples[0].start, 12158 / 1000);
+ assert.strictEqual(t.samples[0].leafNode.title, '/usr/lib/libc++.1.dylib');
+ });
+
+ test('tickEventInGeneratedCode', function() {
+ const lines = [
+ 'shared-library,"/usr/lib/libc++.1.dylib",0x99d8aae0,0x99dce729',
+ 'code-creation,Stub,2,0x5b60ce80,1259,"StringAddStub"',
+ 'tick,0x5b60ce84,12158,0,0x0,5'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const threads = p.findAllThreadsNamed('V8');
+ const t = threads[0];
+ assert.strictEqual(t.samples.length, 1);
+ assert.strictEqual(t.samples[0].leafNode.title, 'StringAddStub');
+ });
+
+ test('tickEventInUknownCode', function() {
+ const lines = [
+ 'shared-library,"/usr/lib/libc++.1.dylib",0x99d8aae0,0x99dce729',
+ 'code-creation,Stub,2,0x5b60ce80,1259,"StringAddStub"',
+ 'tick,0x4,0xbff02f08,12158,0,0x0,5'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const threads = p.findAllThreadsNamed('V8');
+ const t = threads[0];
+ assert.strictEqual(t.samples.length, 1);
+ assert.strictEqual(t.samples[0].leafNode.title, 'unknown');
+ });
+
+ test('tickEventWithStack', function() {
+ const lines = [
+ 'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
+ 'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const t = p.findAllThreadsNamed('V8')[0];
+ assert.strictEqual(t.samples.length, 1);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown'],
+ t.samples[0].userFriendlyStack);
+ });
+
+ test('twoTickEventsWithStack', function() {
+ const lines = [
+ 'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
+ 'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304',
+ 'tick,0x7fd2a534,536213,0,0x81d8d080,0,0x2905d304'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const t = p.findAllThreadsNamed('V8')[0];
+ assert.strictEqual(t.samples.length, 2);
+ assert.strictEqual(t.samples[0].start, 528674 / 1000);
+ assert.strictEqual(t.samples[1].start, 536213 / 1000);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown'],
+ t.samples[0].userFriendlyStack);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown'],
+ t.samples[1].userFriendlyStack);
+ assert.strictEqual(t.samples[0].leafNode,
+ t.samples[1].leafNode);
+ });
+
+ test('twoTickEventsWithTwoStackFrames', function() {
+ const lines = [
+ 'code-creation,LazyCompile,0,0x2904d560,876,"Instantiate native apinatives.js:9:21",0x56b190c8,~', // @suppress longLineCheck
+ 'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
+ 'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304,0x2904d6e8',
+ 'tick,0x7fd2a534,536213,0,0x81d8d080,0,0x2905d304,0x2904d6e8'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const t = p.findAllThreadsNamed('V8')[0];
+ assert.strictEqual(t.samples.length, 2);
+
+ assert.strictEqual(t.samples[0].start, 528674 / 1000);
+ assert.strictEqual(t.samples[1].start, 536213 / 1000);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown',
+ '~Instantiate native apinatives.js:9:21 url: unknown'],
+ t.samples[0].userFriendlyStack);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown',
+ '~Instantiate native apinatives.js:9:21 url: unknown'],
+ t.samples[1].userFriendlyStack);
+
+ assert.strictEqual(t.samples[0].leafNode, t.samples[1].leafNode);
+ });
+
+ test('threeTickEventsWithTwoStackFrames', function() {
+ const lines = [
+ 'code-creation,LazyCompile,0,0x2904d560,876,"Instantiate native apinatives.js:9:21",0x56b190c8,~', // @suppress longLineCheck
+ 'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
+ 'tick,0x7fd7f75c,518328,0,0x81d86da8,2,0x2904d6e8',
+ 'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304,0x2904d6e8',
+ 'tick,0x7fd2a534,536213,0,0x81d8d080,0,0x2905d304,0x2904d6e8'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const threads = p.findAllThreadsNamed('V8');
+
+ const t = threads[0];
+ assert.strictEqual(t.samples.length, 3);
+ assert.strictEqual(t.samples[0].start, 518328 / 1000);
+ assert.strictEqual(t.samples[1].start, 528674 / 1000);
+ assert.strictEqual(t.samples[2].start, 536213 / 1000);
+ assert.deepEqual(
+ ['~Instantiate native apinatives.js:9:21 url: unknown'],
+ t.samples[0].userFriendlyStack);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown',
+ '~Instantiate native apinatives.js:9:21 url: unknown'],
+ t.samples[1].userFriendlyStack);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown',
+ '~Instantiate native apinatives.js:9:21 url: unknown'],
+ t.samples[2].userFriendlyStack);
+
+ const topLevelNode = t.samples[0].leafNode;
+ const leafNode = t.samples[1].leafNode;
+ assert.strictEqual(t.samples[2].leafNode, leafNode);
+ assert.strictEqual(topLevelNode, leafNode.parentNode);
+ });
+
+ test('twoSubStacks', function() {
+ const lines = [
+ 'code-creation,LazyCompile,0,0x2904d560,876,"Instantiate native apinatives.js:9:21",0x56b190c8,~', // @suppress longLineCheck
+ 'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
+ 'tick,0x7fd7f75c,518328,0,0x81d86da8,2,0x2904d6e8',
+ 'tick,0x7fc6fe34,528674,0,0x3,0,0x2905d304,0x2904d6e8',
+ 'tick,0x7fd2a534,536213,0,0x81d8d080,0,0x2905d304,0x2904d6e8',
+ 'code-creation,Script,0,0x2906a7c0,792,"http://www.google.com/",0x5b12fe50,~', // @suppress longLineCheck
+ 'tick,0xb6f51d30,794049,0,0xb6f7b368,2,0x2906a914',
+ 'tick,0xb6f51d30,799145,0,0xb6f7b368,0,0x2906a914'
+ ];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const threads = p.findAllThreadsNamed('V8');
+ const t = threads[0];
+ assert.strictEqual(t.samples.length, 5);
+
+ assert.strictEqual(t.samples[0].start, 518328 / 1000);
+ assert.strictEqual(t.samples[1].start, 528674 / 1000);
+ assert.strictEqual(t.samples[2].start, 536213 / 1000);
+ assert.strictEqual(t.samples[3].start, 794049 / 1000);
+ assert.strictEqual(t.samples[4].start, 799145 / 1000);
+
+ assert.deepEqual(
+ ['~Instantiate native apinatives.js:9:21 url: unknown'],
+ t.samples[0].userFriendlyStack);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown',
+ '~Instantiate native apinatives.js:9:21 url: unknown'],
+ t.samples[1].userFriendlyStack);
+ assert.deepEqual(
+ ['InstantiateFunction native apinatives.js:26:29 url: unknown',
+ '~Instantiate native apinatives.js:9:21 url: unknown'],
+ t.samples[2].userFriendlyStack);
+ assert.deepEqual(['~http://www.google.com/ url: unknown'],
+ t.samples[3].userFriendlyStack);
+ assert.deepEqual(['~http://www.google.com/ url: unknown'],
+ t.samples[4].userFriendlyStack);
+
+ const firstNode = t.samples[0].leafNode;
+ const firstChildNode = t.samples[1].leafNode;
+ assert.strictEqual(firstChildNode, t.samples[2].leafNode);
+ assert.strictEqual(firstNode, firstChildNode.parentNode);
+
+ const secondNode = t.samples[3].leafNode;
+ assert.strictEqual(secondNode, t.samples[4].leafNode);
+ assert.isUndefined(secondNode.parentNode);
+ });
+
+ test('timerEventSliceCreation', function() {
+ const lines = ['timer-event,"V8.External",38189483,3'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const threads = p.findAllThreadsNamed('V8 Timers');
+ assert.isDefined(threads);
+ assert.strictEqual(threads.length, 1);
+ const t = threads[0];
+ assert.strictEqual(t.sliceGroup.length, 1);
+ });
+
+ test('processThreadCreation', function() {
+ const lines = ['timer-event,"V8.External",38189483,3'];
+ const m = newModel(lines.join('\n'));
+ assert.isDefined(m);
+ const p = m.processes[-32];
+ assert.isDefined(p);
+ const threads = p.findAllThreadsNamed('V8 Timers');
+ assert.isDefined(threads);
+ assert.strictEqual(1, threads.length);
+ const t = threads[0];
+ assert.strictEqual('V8 Timers', t.name);
+ });
+
+ test('canImport', function() {
+ assert.isTrue(V8LogImporter.canImport(
+ 'timer-event,"V8.External",38189483,3'));
+ assert.isTrue(V8LogImporter.canImport('v8-version,4,3,66,0,0'));
+ assert.isFalse(V8LogImporter.canImport(''));
+ assert.isFalse(V8LogImporter.canImport([]));
+ });
+
+ test('CppSymbolsProcess', function() {
+ const lines = [
+ 'shared-library,"/usr/loca/v8/out/native/d8",0x00400000, 0x01860000',
+ 'cpp,0x00600000,100,"v8::internal::Heap::AllocateByteArray"',
+ 'cpp,0x00700000,100,"v8::internal::Utf8StringKey::AsHandle"',
+ 'tick,0x00600010,121,0,0x0,5',
+ 'tick,0x00700010,122,0,0x0,5',
+ 'tick,0x00800010,123,0,0x0,5'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const t = p.findAllThreadsNamed('V8')[0];
+ assert.strictEqual(t.samples.length, 3);
+ assert.strictEqual(t.samples[0].leafNode.title,
+ 'v8::internal::Heap::AllocateByteArray');
+ assert.strictEqual(t.samples[1].leafNode.title,
+ 'v8::internal::Utf8StringKey::AsHandle');
+ assert.strictEqual(t.samples[2].leafNode.title,
+ '/usr/loca/v8/out/native/d8');
+ });
+
+ test('CppSymbolsWithJsStack', function() {
+ const lines = [
+ 'shared-library,"/usr/loca/v8/out/native/d8",0x00400000, 0x01860000',
+ 'cpp,0x00600000,100,"v8::internal::Heap::AllocateByteArray"',
+ 'cpp,0x00700000,100,"v8::internal::Utf8StringKey::AsHandle"',
+ 'code-creation,LazyCompile,0,0x2905d0c0,1800,"InstantiateFunction native apinatives.js:26:29",0x56b19124,', // @suppress longLineCheck
+ 'tick,0x00700010,1,0,0x3,0,0x2905d304',
+ 'tick,0x00600010,3,0,0x3,0,0x2905d306',
+ 'tick,0x00800010,5,0,0x3,0,0x2905d306',
+ 'tick,0x01860010,5,0,0x3,0,0x2905d306'];
+ const m = newModel(lines.join('\n'));
+ const p = m.processes[-32];
+ const t = p.findAllThreadsNamed('V8')[0];
+ assert.strictEqual(t.samples.length, 4);
+ assert.deepEqual(t.samples[0].userFriendlyStack, [
+ 'v8::internal::Utf8StringKey::AsHandle url: /usr/loca/v8/out/native/d8',
+ 'InstantiateFunction native apinatives.js:26:29 url: unknown'
+ ]);
+ assert.deepEqual(t.samples[1].userFriendlyStack, [
+ 'v8::internal::Heap::AllocateByteArray url: /usr/loca/v8/out/native/d8',
+ 'InstantiateFunction native apinatives.js:26:29 url: unknown'
+ ]);
+ assert.deepEqual(t.samples[2].userFriendlyStack, [
+ '/usr/loca/v8/out/native/d8 url: unknown',
+ 'InstantiateFunction native apinatives.js:26:29 url: unknown'
+ ]);
+ assert.deepEqual(t.samples[3].userFriendlyStack, [
+ 'InstantiateFunction native apinatives.js:26:29 url: unknown'
+ ]);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/importer/zip_importer.html b/chromium/third_party/catapult/tracing/tracing/extras/importer/zip_importer.html
new file mode 100644
index 00000000000..db16134a838
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/importer/zip_importer.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/importer/gzip_importer.html">
+<link rel="import" href="/tracing/extras/importer/jszip.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview ZipImporter inflates zip compressed data and passes it along
+ * to an actual importer.
+ */
+tr.exportTo('tr.e.importer', function() {
+ function ZipImporter(model, eventData) {
+ if (eventData instanceof ArrayBuffer) {
+ eventData = new Uint8Array(eventData);
+ }
+ this.model_ = model;
+ this.eventData_ = eventData;
+ }
+
+ /**
+ * @param {eventData} string Possibly zip compressed data.
+ * @return {boolean} Whether eventData looks like zip compressed data.
+ */
+ ZipImporter.canImport = function(eventData) {
+ let header;
+ if (eventData instanceof ArrayBuffer) {
+ header = new Uint8Array(eventData.slice(0, 2));
+ } else if (typeof(eventData) === 'string' || eventData instanceof String) {
+ header = [eventData.charCodeAt(0), eventData.charCodeAt(1)];
+ } else {
+ return false;
+ }
+ return header[0] === 'P'.charCodeAt(0) && header[1] === 'K'.charCodeAt(0);
+ };
+
+ ZipImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'ZipImporter';
+ },
+
+ isTraceDataContainer() {
+ return true;
+ },
+
+ extractSubtraces() {
+ const zip = new JSZip(this.eventData_);
+ const subtraces = [];
+ for (const idx in zip.files) {
+ subtraces.push(zip.files[idx].asBinary());
+ }
+ return subtraces;
+ }
+ };
+
+ tr.importer.Importer.register(ZipImporter);
+
+ return {
+ ZipImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/lean_config.html b/chromium/third_party/catapult/tracing/tracing/extras/lean_config.html
new file mode 100644
index 00000000000..b39e51073d9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/lean_config.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+The lean config is just enough to import uncompressed, trace-event-formatted
+json blobs.
+-->
+
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/measure/measure.html b/chromium/third_party/catapult/tracing/tracing/extras/measure/measure.html
new file mode 100644
index 00000000000..05836554eda
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/measure/measure.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/measure/measure_async_slice.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/measure/measure_async_slice.html b/chromium/third_party/catapult/tracing/tracing/extras/measure/measure_async_slice.html
new file mode 100644
index 00000000000..d05d25999e9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/measure/measure_async_slice.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/model/async_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.measure', function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+
+ // Split on first : with an optional `/` + base64 suffix
+ const MEASURE_NAME_REGEX = /([^\/:]+):(.*?)(?:\/([A-Za-z0-9+/]+=?=?))?$/;
+
+ function MeasureAsyncSlice() {
+ this.groupTitle_ = 'Ungrouped Measure';
+ const matched = MEASURE_NAME_REGEX.exec(arguments[1]);
+ if (matched !== null) {
+ arguments[1] = matched[2];
+ this.groupTitle_ = matched[1];
+ }
+ AsyncSlice.apply(this, arguments);
+ }
+
+ MeasureAsyncSlice.prototype = {
+ __proto__: AsyncSlice.prototype,
+
+ get viewSubGroupTitle() {
+ return this.groupTitle_;
+ },
+
+ get title() {
+ return this.title_;
+ },
+
+ set title(title) {
+ this.title_ = title;
+ }
+ };
+
+ AsyncSlice.subTypes.register(
+ MeasureAsyncSlice,
+ {
+ categoryParts: ['blink.user_timing']
+ });
+
+ return {
+ MEASURE_NAME_REGEX,
+ MeasureAsyncSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/measure/measure_async_slice_test.html b/chromium/third_party/catapult/tracing/tracing/extras/measure/measure_async_slice_test.html
new file mode 100644
index 00000000000..cd5de5db878
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/measure/measure_async_slice_test.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/measure/measure.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+ const MeasureAsyncSlice = tr.e.measure.MeasureAsyncSlice;
+
+ test('basic', function() {
+ const s = new MeasureAsyncSlice(
+ 'blink.user_timing', 'createImports', 7, 0, {});
+ s.duration = 100;
+
+ assert.strictEqual(AsyncSlice.subTypes.getConstructor(
+ 'blink.user_timing', 'createImports'),
+ MeasureAsyncSlice);
+ assert.strictEqual(s.viewSubGroupTitle, 'Ungrouped Measure');
+ });
+
+ test('import', function() {
+ const events = [
+ {name: 'createImports', args: {}, pid: 1, ts: 100,
+ cat: 'blink.user_timing', tid: 2, ph: 'b', id: 71},
+ {name: 'createImports', args: {}, pid: 1, ts: 200,
+ cat: 'blink.user_timing', tid: 2, ph: 'e', id: 71}
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([events]);
+ const t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ assert.strictEqual(t2.asyncSliceGroup.length, 1);
+ assert.instanceOf(t2.asyncSliceGroup.slices[0], MeasureAsyncSlice);
+ });
+
+ test('groupMeasureAsyncSlice', function() {
+ const events = [
+ {name: 'createImports', args: {}, pid: 1, ts: 100,
+ cat: 'blink.user_timing', tid: 2, ph: 'b', id: 71},
+ {name: 'createImports', args: {}, pid: 1, ts: 200,
+ cat: 'blink.user_timing', tid: 2, ph: 'e', id: 71},
+ {name: 'runAutoClosers', args: {}, pid: 1, ts: 210,
+ cat: 'blink.user_timing', tid: 2, ph: 'b', id: 72},
+ {name: 'runAutoClosers', args: {}, pid: 1, ts: 310,
+ cat: 'blink.user_timing', tid: 2, ph: 'e', id: 72}
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([events]);
+ const t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ assert.strictEqual(t2.asyncSliceGroup.length, 2);
+ assert.strictEqual(t2.asyncSliceGroup.slices[0].title, 'createImports');
+ assert.strictEqual(t2.asyncSliceGroup.slices[1].title, 'runAutoClosers');
+ assert.instanceOf(t2.asyncSliceGroup.slices[0], MeasureAsyncSlice);
+ assert.instanceOf(t2.asyncSliceGroup.slices[1], MeasureAsyncSlice);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/memory/lowmemory_auditor.html b/chromium/third_party/catapult/tracing/tracing/extras/memory/lowmemory_auditor.html
new file mode 100644
index 00000000000..678393e9d43
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/memory/lowmemory_auditor.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--
+ Copyright 2017 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/core/auditor.html">
+<link rel="import" href="/tracing/model/alert.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.e.audits', function() {
+ /**
+ * Auditor that analyzes the model and annotates low memory events.
+ */
+ class LowMemoryAuditor extends tr.c.Auditor {
+ constructor(model) {
+ super();
+ this.model_ = model;
+ }
+
+ runAnnotate() {
+ this.model_.device.lowMemoryEvents = this.getLowMemoryEvents_();
+ }
+
+ /**
+ * Returns a list of low memory killer events.
+ */
+ getLowMemoryEvents_() {
+ const model = this.model_;
+ const result = [];
+ for (const process of model.getAllProcesses()) {
+ for (const e of process.getDescendantEvents()) {
+ // low memory killer events are 0-duration events.
+ if (!(e instanceof tr.model.ThreadSlice) || e.duration !== 0) {
+ continue;
+ }
+
+ if (e.category !== 'lowmemory') {
+ continue;
+ }
+
+ result.push(e);
+ }
+ }
+ return result;
+ }
+ }
+
+ tr.c.Auditor.register(LowMemoryAuditor);
+
+ return {
+ LowMemoryAuditor
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/net/net.html b/chromium/third_party/catapult/tracing/tracing/extras/net/net.html
new file mode 100644
index 00000000000..3a246c930c0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/net/net.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/net/net_async_slice.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/net/net_async_slice.html b/chromium/third_party/catapult/tracing/tracing/extras/net/net_async_slice.html
new file mode 100644
index 00000000000..fe3008bf55f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/net/net_async_slice.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/model/async_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.net', function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+
+ function NetAsyncSlice() {
+ AsyncSlice.apply(this, arguments);
+ this.url_ = undefined;
+ this.byteCount_ = undefined;
+ // Boolean variables indicating whether we have computed corresponding
+ // fields. Computing these fields needs iteration through all sub-slices and
+ // so recomputation will be costly.
+ this.isTitleComputed_ = false;
+ this.isUrlComputed_ = false;
+ }
+
+ NetAsyncSlice.prototype = {
+ __proto__: AsyncSlice.prototype,
+
+ get viewSubGroupTitle() {
+ return 'NetLog';
+ },
+
+ get title() {
+ if (this.isTitleComputed_ || !this.isTopLevel) {
+ return this.title_;
+ }
+
+ if (this.url !== undefined && this.url.length > 0) {
+ // Set the title so we do not have to recompute when it is redrawn.
+ this.title_ = this.url;
+ } else if (this.args !== undefined &&
+ this.args.source_type !== undefined) {
+ // We do not have a URL, use the source type as the title.
+ this.title_ = this.args.source_type;
+ }
+ this.isTitleComputed_ = true;
+ return this.title_;
+ },
+
+ set title(title) {
+ this.title_ = title;
+ },
+
+ // A recursive helper function that gets the url param of a slice or its
+ // nested subslices if there is one.
+ get url() {
+ if (this.isUrlComputed_) {
+ return this.url_;
+ }
+ if (this.args !== undefined && this.args.params !== undefined &&
+ this.args.params.url !== undefined) {
+ this.url_ = this.args.params.url;
+ } else if (this.subSlices !== undefined && this.subSlices.length > 0) {
+ for (let i = 0; i < this.subSlices.length && ! this.url_; i++) {
+ if (this.subSlices[i].url !== undefined) {
+ this.url_ = this.subSlices[i].url;
+ }
+ }
+ }
+ this.isUrlComputed_ = true;
+ return this.url_;
+ },
+
+ get byteCount() {
+ if (this.byteCount_ !== undefined) {
+ return this.byteCount_;
+ }
+
+ this.byteCount_ = 0;
+ if ((this.originalTitle === 'URL_REQUEST_JOB_FILTERED_BYTES_READ' ||
+ this.originalTitle === 'URL_REQUEST_JOB_BYTES_READ') &&
+ this.args !== undefined && this.args.params !== undefined &&
+ this.args.params.byte_count !== undefined) {
+ this.byteCount_ = this.args.params.byte_count;
+ }
+ for (let i = 0; i < this.subSlices.length; i++) {
+ this.byteCount_ += this.subSlices[i].byteCount;
+ }
+ return this.byteCount_;
+ }
+ };
+
+ AsyncSlice.subTypes.register(
+ NetAsyncSlice,
+ {
+ categoryParts: ['netlog', 'disabled-by-default-netlog']
+ });
+
+ return {
+ NetAsyncSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/net/net_async_slice_test.html b/chromium/third_party/catapult/tracing/tracing/extras/net/net_async_slice_test.html
new file mode 100644
index 00000000000..13f2a938189
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/net/net_async_slice_test.html
@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/extras/net/net.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+ const NetAsyncSlice = tr.e.net.NetAsyncSlice;
+
+ test('basic', function() {
+ const s = new NetAsyncSlice('netlog', 'HTTP_STREAM_JOB', 7, 0, {});
+ s.duration = 100;
+
+ assert.strictEqual(
+ AsyncSlice.subTypes.getConstructor('netlog', 'HTTP_STREAM_JOB'),
+ NetAsyncSlice);
+ assert.strictEqual(s.viewSubGroupTitle, 'NetLog');
+ });
+
+ test('import', function() {
+ const events = [
+ {name: 'HTTP_STREAM_JOB', args: {}, pid: 1, ts: 100, cat: 'netlog', tid: 2, ph: 'b', id: 71}, // @suppress longLineCheck
+ {name: 'HTTP_STREAM_JOB', args: {}, pid: 1, ts: 200, cat: 'netlog', tid: 2, ph: 'e', id: 71} // @suppress longLineCheck
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents([events]);
+ const t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ assert.strictEqual(t2.asyncSliceGroup.length, 1);
+ assert.instanceOf(t2.asyncSliceGroup.slices[0], NetAsyncSlice);
+ });
+
+ test('ExposeURLBasic', function() {
+ const slice = new NetAsyncSlice('', 'a', 0, 1,
+ {params: {url: 'https://google.com'},
+ source_type: 'b'}, 0, true);
+ // Make sure isTopLevel is populated in the constructor.
+ assert.isTrue(slice.isTopLevel);
+ // URL is exposed as the title of the parent slice.
+ assert.strictEqual(slice.title, 'https://google.com');
+ assert.strictEqual(slice.url, 'https://google.com');
+ });
+
+ test('ExposeURLNested', function() {
+ const slice = new NetAsyncSlice(
+ '', 'a', 0, 1, {params: {}, source_type: 'HELLO'}, 1, true);
+ const childSlice = new NetAsyncSlice('', 'b', 0, 1,
+ {params: {url: 'http://test.url'}});
+ slice.subSlices = [childSlice];
+ // Make sure isTopLevel is populated in the constructor.
+ assert.isTrue(slice.isTopLevel);
+ assert.isFalse(childSlice.isTopLevel);
+ // URL is exposed as the title of the parent slice.
+ assert.strictEqual(slice.title, 'http://test.url');
+ assert.strictEqual(slice.title, 'http://test.url');
+ assert.strictEqual(childSlice.title, 'b');
+ assert.strictEqual(childSlice.url, 'http://test.url');
+ });
+
+ test('ExposeURLNestedNoURL', function() {
+ const slice = new NetAsyncSlice('', 'a', 0, 1, {params: {}}, 1, true);
+ const childSlice = new NetAsyncSlice('', 'b', 0, 1, {params: {}});
+ slice.subSlices = [childSlice];
+ // Make sure isTopLevel is populated in the constructor.
+ assert.isTrue(slice.isTopLevel);
+ assert.isFalse(childSlice.isTopLevel);
+ // URL is exposed as the title of the parent slice.
+ assert.strictEqual(slice.title, 'a');
+ assert.strictEqual(slice.url, undefined);
+ assert.strictEqual(childSlice.title, 'b');
+ assert.strictEqual(childSlice.url, undefined);
+ });
+
+ test('ExposeURLNestedBothChildrenHaveURL', function() {
+ const slice = new NetAsyncSlice('', 'a', 0, 1, {params: {}}, 1, true);
+ const childSlice1 = new NetAsyncSlice('', 'b', 0, 1,
+ {params: {url: 'http://test.url.net'}});
+ const childSlice2 = new NetAsyncSlice('', 'c', 0, 1,
+ {params: {url: 'http://test.url.com'}});
+ slice.subSlices = [childSlice1, childSlice2];
+ // Make sure isTopLevel is populated in the constructor.
+ assert.isTrue(slice.isTopLevel);
+ assert.isFalse(childSlice1.isTopLevel);
+ assert.isFalse(childSlice2.isTopLevel);
+ // Parent should take the first url param that it finds.
+ assert.strictEqual(slice.title, 'http://test.url.net');
+ assert.strictEqual(childSlice1.title, 'b');
+ assert.strictEqual(childSlice2.title, 'c');
+ });
+
+ test('ExposeURLNestedBothParentAndChildHaveURL', function() {
+ const slice = new NetAsyncSlice('', 'a', 0, 1,
+ {params: {url: 'parent123.url.com'}}, 1,
+ true);
+ const childSlice1 = new NetAsyncSlice('', 'b', 0, 1,
+ {params: {url: 'http://test.url.net'}});
+ const childSlice2 = new NetAsyncSlice('', 'c', 0, 1);
+
+ slice.subSlices = [childSlice1, childSlice2];
+ // Make sure isTopLevel is populated in the constructor.
+ assert.isTrue(slice.isTopLevel);
+ assert.isFalse(childSlice1.isTopLevel);
+ assert.isFalse(childSlice2.isTopLevel);
+ // Parent should take its own url param if there is one.
+ assert.strictEqual(slice.title, 'parent123.url.com');
+ assert.strictEqual(childSlice1.title, 'b');
+ assert.strictEqual(childSlice2.title, 'c');
+ });
+
+ test('ExposeURLDoNotComputeUrlTwice', function() {
+ const slice = new NetAsyncSlice('', 'a', 0, 1, {params: {}}, 1, true);
+ const childSlice1 = new NetAsyncSlice('', 'b', 0, 1,
+ {params: {url: 'http://test.url.net'}});
+ const childSlice2 = new NetAsyncSlice('', 'c', 0, 1);
+
+ slice.subSlices = [childSlice1, childSlice2];
+ // Make sure isTopLevel is populated in the constructor.
+ assert.isTrue(slice.isTopLevel);
+ assert.isFalse(childSlice1.isTopLevel);
+ assert.isFalse(childSlice2.isTopLevel);
+ // Parent should take its child's url param.
+ assert.strictEqual(slice.title, 'http://test.url.net');
+ assert.strictEqual(childSlice1.title, 'b');
+ assert.strictEqual(childSlice2.title, 'c');
+ // Now if we change the url param of the child, the parent's title should
+ // remain the same. We do not recompute.
+ childSlice1.args.params.url = 'example.com';
+ assert.strictEqual(slice.title, 'http://test.url.net');
+ assert.strictEqual(childSlice1.title, 'b');
+ assert.strictEqual(childSlice2.title, 'c');
+ });
+
+ test('ExposeSourceTypeAsTitle', function() {
+ const slice = new NetAsyncSlice('', 'a', 0, 1,
+ {params: {}, source_type: 'UDP_SOCKET'}, 1,
+ true);
+ const childSlice1 = new NetAsyncSlice('', 'b', 0, 1,
+ {params: {}, source_type: 'SOCKET'});
+ const childSlice2 = new NetAsyncSlice('', 'c', 0, 1);
+
+ slice.subSlices = [childSlice1, childSlice2];
+ // Make sure isTopLevel is populated in the constructor.
+ assert.isTrue(slice.isTopLevel);
+ assert.isFalse(childSlice1.isTopLevel);
+ assert.isFalse(childSlice2.isTopLevel);
+ // Parent should take its own source_type.
+ assert.strictEqual(slice.title, 'UDP_SOCKET');
+ assert.strictEqual(childSlice1.title, 'b');
+ assert.strictEqual(childSlice2.title, 'c');
+ });
+
+ test('ByteCountBasic', function() {
+ const slice = new NetAsyncSlice('', 'URL_REQUEST_JOB_BYTES_READ', 0, 1,
+ {params: {byte_count: 12}}, 0, true);
+ assert.strictEqual(slice.byteCount, 12);
+ });
+
+ test('NoByteCount', function() {
+ const slice = new NetAsyncSlice('', 'a', 0, 1, {}, 0, true);
+ assert.strictEqual(slice.byteCount, 0);
+ });
+
+ test('ByteCountNested', function() {
+ const slice = new NetAsyncSlice('', 'URL_REQUEST_JOB_FILTERED_BYTES_READ',
+ 0, 1, {params: {byte_count: 12}}, 0, true);
+ const childSlice = new NetAsyncSlice('', 'URL_REQUEST_JOB_BYTES_READ', 0, 1,
+ {params: {byte_count: 50}});
+ slice.subSlices = [childSlice];
+ assert.strictEqual(slice.byteCount, 62);
+ assert.strictEqual(childSlice.byteCount, 50);
+ });
+
+ test('ByteCountTwoChildren', function() {
+ const slice = new NetAsyncSlice(
+ '', 'URL_REQUEST_JOB_FILTERED_BYTES_READ', 0, 1,
+ {params: {byte_count: 12}}, 0, true);
+ const childSlice1 = new NetAsyncSlice(
+ '', 'URL_REQUEST_JOB_BYTES_READ', 0, 1, {params: {byte_count: 50}});
+ const childSlice2 = new NetAsyncSlice(
+ '', 'URL_REQUEST_JOB_BYTES_READ', 0, 1, {params: {byte_count: 20}});
+ slice.subSlices = [childSlice1, childSlice2];
+ assert.strictEqual(slice.byteCount, 82);
+ assert.strictEqual(childSlice1.byteCount, 50);
+ assert.strictEqual(childSlice2.byteCount, 20);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/OWNERS b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/OWNERS
new file mode 100644
index 00000000000..25b1b8fc5e8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/OWNERS
@@ -0,0 +1,2 @@
+dskiba@chromium.org
+erikchen@chromium.org
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/__init__.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/__init__.py
new file mode 100644
index 00000000000..a22a6ee39a9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/addr2line-pdb.exe.sha1 b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/addr2line-pdb.exe.sha1
new file mode 100644
index 00000000000..7b6ab903155
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/addr2line-pdb.exe.sha1
@@ -0,0 +1 @@
+4e236e6ea0d9f95067eafcb6a49fa85960253cd7 \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/linux_trace_v2_presymbolization.json.gz.sha1 b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/linux_trace_v2_presymbolization.json.gz.sha1
new file mode 100644
index 00000000000..a9a23ea8f9a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/linux_trace_v2_presymbolization.json.gz.sha1
@@ -0,0 +1 @@
+cf9861aae9dc507e779fe7b34a810848d1c1b288 \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/mac_trace_v2_presymbolization.json.gz.sha1 b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/mac_trace_v2_presymbolization.json.gz.sha1
new file mode 100644
index 00000000000..bdd769b990d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/mac_trace_v2_presymbolization.json.gz.sha1
@@ -0,0 +1 @@
+4bbc69a25b711b5a9488936382298063e240ffa7 \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/windows_trace_v1_presymbolization.json.gz.sha1 b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/windows_trace_v1_presymbolization.json.gz.sha1
new file mode 100644
index 00000000000..0243761389e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/windows_trace_v1_presymbolization.json.gz.sha1
@@ -0,0 +1 @@
+4f63b242a7bab2266b76bee3e528c7d7c1e3882f \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/windows_trace_v2_presymbolization.json.gz.sha1 b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/windows_trace_v2_presymbolization.json.gz.sha1
new file mode 100644
index 00000000000..29027e5dd72
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/data/windows_trace_v2_presymbolization.json.gz.sha1
@@ -0,0 +1 @@
+520410cd56479aa54321eee65be5676acc2e8ed7 \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py
new file mode 100755
index 00000000000..e90b9ce5e30
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace.py
@@ -0,0 +1,1707 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# pylint: disable=too-many-lines
+
+"""
+This script processes trace files and symbolizes stack frames generated by
+Chrome's native heap profiler. This script assumes that the Chrome binary
+referenced in the trace contains symbols, and is the same binary used to emit
+the trace.
+
+=== Overview ===
+
+Trace file is essentially a giant JSON array of dictionaries (events).
+Events have some predefined keys (e.g. 'pid'), but otherwise are free to
+have anything inside. Trace file contains events from all Chrome processes
+that were sampled during tracing period.
+
+This script cares only about memory dump events generated with memory-infra
+category enabled.
+
+When Chrome native heap profiling is enabled, some memory dump events
+include the following extra information:
+
+* (Per allocator) Information about live allocations at the moment of the
+ memory dump (the information includes backtraces, types / categories,
+ sizes, and counts of allocations). There are several allocators in
+ Chrome: e.g. malloc, blink_gc, partition_alloc.
+
+* (Per process) Stack frame tree of all functions that called allocators
+ above.
+
+This script does the following:
+
+1. Parses the given trace file (loads JSON).
+2. Finds memory dump events and parses stack frame tree for each process.
+3. Finds stack frames that have PC addresses instead of function names.
+4. Symbolizes PCs and modifies loaded JSON.
+5. Writes modified JSON back to the file.
+
+The script supports trace files from the following platforms:
+ * Android (the script itself must be run on Linux)
+ * Linux
+ * macOS
+ * Windows
+
+Important note - the script doesn't check that it symbolizes same binaries
+that were used at the time trace was taken. I.e. if you take a trace, change
+and rebuild Chrome binaries, the script will blindly use the new binaries.
+
+=== Details ===
+
+There are two formats of heap profiler information: legacy and modern. The
+main differences relevant to this script are:
+
+* In the modern format the stack frame tree, type name mapping, and string
+ mapping nodes are dumped incrementally. These nodes are dumped in each
+ memory dump event and carry updates that occurred since the last event.
+
+ For example, let's say that when the first memory dump event is generated
+ we only know about a function foo() (called from main()) allocating objects
+ of type "int":
+
+ {
+ "args": {
+ "dumps": {
+ "heaps_v2": {
+ "maps": {
+ "nodes": [
+ { "id": 1, "name_sid": 1 },
+ { "id": 2, "parent": 1, "name_sid": 3 },
+ ],
+ "types": [
+ { "id": 1, "name_sid": 2 },
+ ],
+ "strings": [
+ { "id": 1, "string": "main()" },
+ { "id": 2, "string": "int" },
+ { "id": 3, "string": "foo()" },
+ ]
+ },
+ "allocators": { ...live allocations per allocator... },
+ ...
+ },
+ ...
+ }
+ },
+ ...
+ }
+
+ Here:
+ * 'nodes' node encodes stack frame tree
+ * 'types' node encodes type name mappings
+ * 'strings' node encodes string mapping (explained below)
+
+ Then, by the time second memory dump even is generated, we learn about
+ bar() (called from main()), which also allocated "int" objects. Only the
+ new information is dumped, i.e. bar() stack frame:
+
+ {
+ "args": {
+ "dumps": {
+ "heaps_v2": {
+ "maps": {
+ "nodes": [
+ { "id": 2, "parent": 1, "name_sid": 4 },
+ ],
+ "types": [],
+ "strings": [
+ { "id": 4, "string": "bar()" },
+ ]
+ },
+ "allocators": { ...live allocations per allocator... },
+ ...
+ },
+ ...
+ }
+ },
+ ...
+ }
+
+ Note that 'types' node is empty, since there were no updates. All three
+ nodes ('nodes', types', and 'strings') can be empty if there were no updates
+ to them.
+
+ For simplicity, when the script updates incremental nodes, it puts updated
+ content in the first node, and clears all others. I.e. the following stack
+ frame nodes:
+
+ 'nodes': [
+ { "id": 1, "name_sid": 1 },
+ { "id": 2, "parent": 1, "name_sid": 2 },
+ ]
+ 'nodes': [
+ { "id": 3, "parent": 2, "name_sid": 3 },
+ ]
+ 'nodes': [
+ { "id": 4, "parent": 3, "name_sid": 4 },
+ { "id": 5, "parent": 1, "name_sid": 5 },
+ ]
+
+ After symbolization are written as:
+
+ 'nodes': [
+ { "id": 1, "name_sid": 1 },
+ { "id": 2, "parent": 1, "name_sid": 2 },
+ { "id": 3, "parent": 2, "name_sid": 3 },
+ { "id": 4, "parent": 3, "name_sid": 4 },
+ { "id": 5, "parent": 1, "name_sid": 5 },
+ ]
+ 'nodes': []
+ 'nodes': []
+
+
+* In contrast, in the legacy format stack frame tree and type mappings are
+ dumped separately from memory dump events, once per process.
+
+ Here is how trace file with two memory dump events looks like in the
+ legacy format:
+
+ {
+ "args": {
+ "dumps": {
+ "heaps": { ...live allocations per allocator... },
+ ...
+ }
+ },
+ ...
+ }
+
+ {
+ "args": {
+ "dumps": {
+ "heaps": { ...live allocations per allocator... },
+ ...
+ }
+ },
+ ...
+ }
+
+ {
+ "args": {
+ "typeNames": {
+ 1: "int",
+ }
+ },
+ "cat": "__metadata",
+ "name": "typeNames",
+ ...
+ }
+
+ {
+ "args": {
+ "stackFrames": {
+ 1: { "name": "main" },
+ 2: { "name": "foo", "parent": 1 },
+ 3: { "name": "bar", "parent": 1 },
+ }
+ },
+ "cat": "__metadata",
+ "name": "stackFrames",
+ ...
+ }
+
+
+* Another change in the modern format is 'strings' node, which was added
+ to deduplicate stack frame names (mainly for trace file size reduction).
+ For consistency 'types' node also uses string mappings.
+
+
+See crbug.com/708930 for more information about the modern format.
+"""
+
+from __future__ import print_function
+
+import argparse
+import bisect
+import collections
+import gzip
+import json
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tarfile
+import zipfile
+import tempfile
+
+import symbols.elf_symbolizer as elf_symbolizer
+
+from tracing.extras.symbolizer import symbolize_trace_atos_regex
+from tracing.extras.symbolizer import symbolize_trace_macho_reader
+
+import py_utils.cloud_storage as cloud_storage
+
+_UNNAMED_FILE = 'unnamed'
+
+
+class NodeWrapper(object):
+ """Wraps an event data node(s).
+
+ A node is a reference into a trace event JSON. Wrappers parse nodes to
+ provide convenient APIs and update nodes when asked to propagate changes
+ back (see ApplyModifications() below).
+
+ Here is an example of legacy metadata event that contains stack frame tree:
+
+ {
+ "args": {
+ "stackFrames": { ... }
+ },
+ "cat": "__metadata",
+ "name": "stackFrames",
+ "ph": "M",
+ ...
+ }
+
+ When this event is encountered, a reference to the "stackFrames" dictionary
+ is obtained and passed down to a specific wrapped class, which knows how to
+ parse / update the dictionary.
+
+ There are two parsing patterns depending on whether node is serialized
+ incrementally:
+
+ * If node is not incremental, then parsing is done by __init__(),
+ see MemoryMap for an example.
+
+ * If node is incremental, then __init__() does nothing, and instead
+ ParseNext() method is called when next node (from a next event) is
+ encountered.
+
+ Some wrappers can also modify nodes they parsed. In such cases they have
+ additional APIs:
+
+ * 'modified' flag, which indicates whether the wrapper was changed.
+
+ * 'ApplyModifications' method, which propagates changes made to the wrapper
+ back to nodes. Successful invocation of ApplyModifications() resets
+ 'modified' flag.
+
+ """
+ pass
+
+
+class MemoryMap(NodeWrapper):
+ """Wraps 'process_mmaps' node.
+
+ 'process_mmaps' node contains information about file mappings.
+
+ "process_mmaps": {
+ "vm_regions": [
+ {
+ "mf": "<file_path>",
+ "sa": "<start_address>",
+ "sz": "<size>",
+ ...
+ },
+ ...
+ ]
+ }
+ """
+
+ class Region(object):
+ def __init__(self, start_address, size, file_path, file_offset):
+ self._start_address = start_address
+ self._size = size
+ self._file_path = file_path if file_path else _UNNAMED_FILE
+ self._file_offset = file_offset
+ self._code_id = None
+
+ @property
+ def start_address(self):
+ return self._start_address
+
+ @property
+ def end_address(self):
+ return self._start_address + self._size
+
+ @property
+ def size(self):
+ return self._size
+
+ @property
+ def code_id(self):
+ return self._code_id
+
+ @property
+ def file_path(self):
+ return self._file_path
+
+ @property
+ def file_offset(self):
+ return self._file_offset
+
+ @file_offset.setter
+ def file_offset(self, value):
+ self._file_offset = value
+
+ def __cmp__(self, other):
+ if isinstance(other, type(self)):
+ other_start_address = other._start_address
+ elif isinstance(other, (long, int)):
+ other_start_address = other
+ else:
+ raise Exception('Cannot compare with %s' % type(other))
+ if self._start_address < other_start_address:
+ return -1
+ elif self._start_address > other_start_address:
+ return 1
+ else:
+ return 0
+
+ def __repr__(self):
+ return 'Region(0x{:X} - 0x{:X}, {})'.format(
+ self.start_address, self.end_address, self.file_path)
+
+ def __init__(self, process_mmaps_node):
+ regions = []
+ for region_node in process_mmaps_node['vm_regions']:
+ file_offset = long(region_node['fo'], 16) if 'fo' in region_node else 0
+ file_path = region_node['mf'].replace(" (deleted)", "")
+ region = self.Region(long(region_node['sa'], 16),
+ long(region_node['sz'], 16),
+ file_path,
+ file_offset)
+ # Keep track of code-identifier when present.
+ if 'ts' in region_node and 'sz' in region_node:
+ region._code_id = "%08X%X" % (long(region_node['ts'], 16), region.size)
+ regions.append(region)
+
+ regions.sort()
+
+ # Iterate through the regions in order. If two regions border each other,
+ # and have the same file_path [or at least one of them is unnamed], but the
+ # latter region has file_offset == 0, then set the file_offset of the latter
+ # region to be former_region.file_offset + former_region.size.
+ #
+ # Rationale: Semantically, we want file_offset to be the distance between
+ # the base address of the region and the base address of the module [which
+ # breakpad symbols use as a relative-zero]. Technically, this is called
+ # slide (macOS) and load bias (ELF). See
+ # https://chromium-review.googlesource.com/c/chromium/src/+/568413#message-01cf829007882eea8c9d3403871814c4f336d16d
+ # for more details.
+ # Chrome does not emit slide or load bias. This usually doesn't make a
+ # difference because the TEXT segment usually has a slide or load bias of 0.
+ # In the rare cases that it doesn't [observed on Chrome Linux official
+ # builds], this heuristic correctly computes it.
+ #
+ # This hack relies on the assumption that all regions with the same name are
+ # mapped from the same file. Each region's file_offset should be computed
+ # based on the first region's base address.
+ last_region_with_file_path = {}
+ for region in regions:
+ if (region.file_path in last_region_with_file_path and
+ region.file_offset == 0):
+ region.file_offset = (
+ region.start_address -
+ last_region_with_file_path[region.file_path].start_address)
+ if (region.file_path and
+ region.file_path not in last_region_with_file_path):
+ last_region_with_file_path[region.file_path] = region
+
+ # Copy regions without duplicates and check for overlaps.
+ self._regions = []
+ previous_region = None
+ for region in regions:
+ if previous_region is not None:
+ if region == previous_region:
+ continue
+ if region.start_address < previous_region.end_address:
+ print('Regions {} and {} overlap.'.format(previous_region, region))
+ previous_region = region
+ self._regions.append(region)
+
+ @property
+ def regions(self):
+ return self._regions
+
+ def FindRegion(self, address):
+ """Finds region containing |address|. Returns None if none found."""
+
+ region_index = bisect.bisect_right(self._regions, address) - 1
+ if region_index >= 0:
+ region = self._regions[region_index]
+ if address >= region.start_address and address < region.end_address:
+ return region
+ return None
+
+
+class UnsupportedHeapDumpVersionError(Exception):
+ """Helper exception class to signal unsupported heap dump version."""
+
+ def __init__(self, version):
+ message = 'Unsupported heap dump version: {}'.format(version)
+ super(UnsupportedHeapDumpVersionError, self).__init__(message)
+
+
+class StringMap(NodeWrapper):
+ """Wraps all 'strings' nodes for a process.
+
+ 'strings' node contains incremental mappings between integer ids and strings.
+
+ "strings": [
+ {
+ "id": <string_id>,
+ "string": <string>
+ },
+ ...
+ ]
+ """
+
+ def __init__(self):
+ self._modified = False
+ self._strings_nodes = []
+ self._string_by_id = {}
+ self._id_by_string = {}
+ self._max_string_id = 0
+
+ @property
+ def modified(self):
+ """Returns True if the wrapper was modified (see NodeWrapper)."""
+ return self._modified
+
+ @property
+ def string_by_id(self):
+ return self._string_by_id
+
+ def ParseNext(self, heap_dump_version, strings_node):
+ """Parses and interns next node (see NodeWrapper)."""
+
+ if heap_dump_version != Trace.HEAP_DUMP_VERSION_1:
+ raise UnsupportedHeapDumpVersionError(heap_dump_version)
+
+ self._strings_nodes.append(strings_node)
+ for string_node in strings_node:
+ self._Insert(string_node['id'], string_node['string'])
+
+ def Clear(self):
+ """Clears all string mappings."""
+ if self._string_by_id:
+ self._modified = True
+
+ self._string_by_id = {}
+ self._id_by_string = {}
+ self._max_string_id = 0
+
+ def AddString(self, string):
+ """Adds a string (if it doesn't exist) and returns its integer id."""
+ string_id = self._id_by_string.get(string)
+ if string_id is None:
+ string_id = self._max_string_id + 1
+ self._Insert(string_id, string)
+ self._modified = True
+ return string_id
+
+ def ApplyModifications(self):
+ """Propagates modifications back to nodes (see NodeWrapper)."""
+ if not self.modified:
+ return
+
+ assert self._strings_nodes, 'no nodes'
+
+ # Serialize into the first node, and clear all others.
+
+ for strings_node in self._strings_nodes:
+ del strings_node[:]
+ strings_node = self._strings_nodes[0]
+ for string_id, string in self._string_by_id.items():
+ strings_node.append({'id': string_id, 'string': string})
+
+ self._modified = False
+
+ def _Insert(self, string_id, string):
+ self._id_by_string[string] = string_id
+ self._string_by_id[string_id] = string
+ self._max_string_id = max(self._max_string_id, string_id)
+
+
+class TypeNameMap(NodeWrapper):
+ """Wraps all 'types' nodes for a process.
+
+ 'types' nodes encode mappings between integer type ids and integer
+ string ids (from 'strings' nodes).
+
+ "types": [
+ {
+ "id": <type_id>,
+ "name_sid": <name_string_id>
+ }
+ ...
+ ]
+
+ For simplicity string ids are translated into strings during parsing,
+ and then translated back to ids in ApplyModifications().
+ """
+ def __init__(self):
+ self._modified = False
+ self._type_name_nodes = []
+ self._name_by_id = {}
+ self._id_by_name = {}
+ self._max_type_id = 0
+
+ @property
+ def modified(self):
+ """Returns True if the wrapper was modified (see NodeWrapper)."""
+ return self._modified
+
+ @property
+ def name_by_id(self):
+ """Returns {id -> name} dict (must not be changed directly)."""
+ return self._name_by_id
+
+ def ParseNext(self, heap_dump_version, type_name_node, string_map):
+ """Parses and interns next node (see NodeWrapper).
+
+ |string_map| - A StringMap object to use to translate string ids
+ to strings.
+ """
+ if heap_dump_version != Trace.HEAP_DUMP_VERSION_1:
+ raise UnsupportedHeapDumpVersionError(heap_dump_version)
+
+ self._type_name_nodes.append(type_name_node)
+ for type_node in type_name_node:
+ self._Insert(type_node['id'],
+ string_map.string_by_id[type_node['name_sid']])
+
+ def AddType(self, type_name):
+ """Adds a type name (if it doesn't exist) and returns its id."""
+ type_id = self._id_by_name.get(type_name)
+ if type_id is None:
+ type_id = self._max_type_id + 1
+ self._Insert(type_id, type_name)
+ self._modified = True
+ return type_id
+
+ def ApplyModifications(self, string_map, force=False):
+ """Propagates modifications back to nodes.
+
+ |string_map| - A StringMap object to use to translate strings to ids.
+ |force| - Whether to propagate changes regardless of 'modified' flag.
+ """
+ if not self.modified and not force:
+ return
+
+ assert self._type_name_nodes, 'no nodes'
+
+ # Serialize into the first node, and clear all others.
+
+ for types_node in self._type_name_nodes:
+ del types_node[:]
+ types_node = self._type_name_nodes[0]
+ for type_id, type_name in self._name_by_id.items():
+ types_node.append({
+ 'id': type_id,
+ 'name_sid': string_map.AddString(type_name)})
+
+ self._modified = False
+
+ def _Insert(self, type_id, type_name):
+ self._id_by_name[type_name] = type_id
+ self._name_by_id[type_id] = type_name
+ self._max_type_id = max(self._max_type_id, type_id)
+
+
+class StackFrameMap(NodeWrapper):
+ """ Wraps stack frame tree nodes for a process.
+
+ For the legacy format this wrapper expects a single 'stackFrames' node
+ (which comes from metadata event):
+
+ "stackFrames": {
+ "<frame_id>": {
+ "name": "<frame_name>"
+ "parent": "<parent_frame_id>"
+ },
+ ...
+ }
+
+ For the modern format this wrapper expects several 'nodes' nodes:
+
+ "nodes": [
+ {
+ "id": <frame_id>,
+ "parent": <parent_frame_id>,
+ "name_sid": <name_string_id>
+ },
+ ...
+ ]
+
+ In both formats frame name is a string. Native heap profiler generates
+ specially formatted frame names (e.g. "pc:10eb78dba") for function
+ addresses (PCs). Inner Frame class below parses name and extracts PC,
+ if it's there.
+ """
+ class Frame(object):
+ def __init__(self, frame_id, name, parent_frame_id):
+ self._modified = False
+ self._id = frame_id
+ self._name = name
+ self._pc = self._ParsePC(name)
+ self._parent_id = parent_frame_id
+ self._ext = None
+
+ @property
+ def modified(self):
+ """Returns True if the frame was modified.
+
+ For example changing frame's name sets this flag (since the change
+ needs to be propagated back to nodes).
+ """
+ return self._modified
+
+ @property
+ def id(self):
+ """Frame id (integer)."""
+ return self._id
+
+ @property
+ def pc(self):
+ """Parsed (integer) PC of the frame, or None."""
+ return self._pc
+
+ @property
+ def name(self):
+ """Name of the frame (see above)."""
+ return self._name
+
+ @name.setter
+ def name(self, value):
+ """Changes the name. Doesn't affect value of |pc|."""
+ self._modified = True
+ self._name = value
+
+ @property
+ def parent_id(self):
+ """Parent frame id (integer)."""
+ return self._parent_id
+
+ _PC_TAG = 'pc:'
+
+ def _ParsePC(self, name):
+ if not name.startswith(self._PC_TAG):
+ return None
+ return long(name[len(self._PC_TAG):], 16)
+
+ def _ClearModified(self):
+ self._modified = False
+
+ def __init__(self):
+ self._modified = False
+ self._heap_dump_version = None
+ self._stack_frames_nodes = []
+ self._frame_by_id = {}
+
+ @property
+ def modified(self):
+ """Returns True if the wrapper or any of its frames were modified."""
+ return (self._modified or
+ any(f.modified for f in self._frame_by_id.values()))
+
+ @property
+ def frame_by_id(self):
+ """Returns {id -> frame} dict (must not be modified directly)."""
+ return self._frame_by_id
+
+ def ParseNext(self, heap_dump_version, stack_frames_node, string_map):
+ """Parses the next stack frames node (see NodeWrapper).
+
+ For the modern format |string_map| is used to translate string ids
+ to strings.
+ """
+
+ frame_by_id = {}
+ if heap_dump_version == Trace.HEAP_DUMP_VERSION_LEGACY:
+ if self._stack_frames_nodes:
+ raise Exception('Legacy stack frames node is expected only once.')
+ for frame_id, frame_node in stack_frames_node.items():
+ frame = self.Frame(frame_id,
+ frame_node['name'],
+ frame_node.get('parent'))
+ frame_by_id[frame.id] = frame
+ else:
+ if heap_dump_version != Trace.HEAP_DUMP_VERSION_1:
+ raise UnsupportedHeapDumpVersionError(heap_dump_version)
+ for frame_node in stack_frames_node:
+ frame = self.Frame(frame_node['id'],
+ string_map.string_by_id[frame_node['name_sid']],
+ frame_node.get('parent'))
+ frame_by_id[frame.id] = frame
+
+ self._heap_dump_version = heap_dump_version
+ self._stack_frames_nodes.append(stack_frames_node)
+
+ self._frame_by_id.update(frame_by_id)
+
+ def ApplyModifications(self, string_map, force=False):
+ """Applies modifications back to nodes (see NodeWrapper)."""
+
+ if not self.modified and not force:
+ return
+
+ assert self._stack_frames_nodes, 'no nodes'
+ if self._heap_dump_version == Trace.HEAP_DUMP_VERSION_LEGACY:
+ assert string_map is None, \
+ 'string_map should not be used with the legacy format'
+
+ # Serialize frames into the first node, clear all others.
+
+ for frames_node in self._stack_frames_nodes:
+ if self._heap_dump_version == Trace.HEAP_DUMP_VERSION_LEGACY:
+ frames_node.clear()
+ else:
+ del frames_node[:]
+
+ frames_node = self._stack_frames_nodes[0]
+ for frame in self._frame_by_id.values():
+ if self._heap_dump_version == Trace.HEAP_DUMP_VERSION_LEGACY:
+ frame_node = {'name': frame.name}
+ frames_node[frame.id] = frame_node
+ else:
+ frame_node = {
+ 'id': frame.id,
+ 'name_sid': string_map.AddString(frame.name)
+ }
+ frames_node.append(frame_node)
+ if frame.parent_id is not None:
+ frame_node['parent'] = frame.parent_id
+ frame._ClearModified()
+
+ self._modified = False
+
+
+class Trace(NodeWrapper):
+ """Wrapper for the root trace node (i.e. the trace JSON itself).
+
+ This wrapper parses select nodes from memory-infra events and groups
+ parsed data per-process (see inner Process class below).
+ """
+
+ # Indicates legacy heap dump format.
+ HEAP_DUMP_VERSION_LEGACY = 'Legacy'
+
+ # Indicates variation of a modern heap dump format.
+ HEAP_DUMP_VERSION_1 = 1
+
+ class Process(object):
+ """Collection of per-process data and wrappers."""
+
+ def __init__(self, pid):
+ self._pid = pid
+ self._name = None
+ self._memory_map = None
+ self._stack_frame_map = StackFrameMap()
+ self._type_name_map = TypeNameMap()
+ self._string_map = StringMap()
+ self._heap_dump_version = None
+
+ @property
+ def modified(self):
+ return self._stack_frame_map.modified or self._type_name_map.modified
+
+ @property
+ def pid(self):
+ return self._pid
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def unique_name(self):
+ """Returns string that includes both process name and its pid."""
+ name = self._name if self._name else 'UnnamedProcess'
+ return '{}({})'.format(name, self._pid)
+
+ @property
+ def memory_map(self):
+ return self._memory_map
+
+ @property
+ def stack_frame_map(self):
+ return self._stack_frame_map
+
+ @property
+ def type_name_map(self):
+ return self._type_name_map
+
+ def ApplyModifications(self):
+ """Calls ApplyModifications() on contained wrappers."""
+ if self._heap_dump_version == Trace.HEAP_DUMP_VERSION_LEGACY:
+ self._stack_frame_map.ApplyModifications(None)
+ else:
+ if self._stack_frame_map.modified or self._type_name_map.modified:
+ self._string_map.Clear()
+ self._stack_frame_map.ApplyModifications(self._string_map, force=True)
+ self._type_name_map.ApplyModifications(self._string_map, force=True)
+ self._string_map.ApplyModifications()
+
+ def __init__(self, trace_node):
+ self._trace_node = trace_node
+ self._processes = []
+ self._heap_dump_version = None
+ self._os = None
+ self._version = None
+ self._is_chromium = True
+ self._is_64bit = False
+ self._is_win = False
+ self._is_mac = False
+ self._is_linux = False
+ self._is_cros = False
+ self._is_android = False
+
+ # Misc per-process information needed only during parsing.
+ class ProcessExt(object):
+ def __init__(self, pid):
+ self.process = Trace.Process(pid)
+ self.mapped_entry_names = set()
+ self.process_mmaps_node = None
+ self.seen_strings_node = False
+
+ process_ext_by_pid = {}
+
+ if isinstance(trace_node, dict):
+ metadata = trace_node['metadata']
+ product_version = metadata['product-version']
+ # product-version has the form "Chrome/60.0.3103.0"
+ self._version = product_version.split('/', 1)[-1]
+ self._os = metadata['os-name']
+
+ self._is_win = re.search('windows', metadata['os-name'], re.IGNORECASE)
+ self._is_mac = re.search('mac', metadata['os-name'], re.IGNORECASE)
+ self._is_linux = re.search('linux', metadata['os-name'], re.IGNORECASE)
+ self._is_cros = re.search('cros', metadata['os-name'], re.IGNORECASE)
+ self._is_android = re.search(
+ 'android', metadata['os-name'], re.IGNORECASE)
+
+ self._is_64bit = (
+ re.search('x86_64', metadata['os-arch'], re.IGNORECASE) and
+ not re.search('WOW64', metadata['user-agent'], re.IGNORECASE))
+
+ # Android traces produced via 'chrome://inspect/?tracing#devices' are
+ # just list of events.
+ events = trace_node if isinstance(trace_node, list) \
+ else trace_node['traceEvents']
+ for event in events:
+ name = event.get('name')
+ if not name:
+ continue
+
+ pid = event['pid']
+ process_ext = process_ext_by_pid.get(pid)
+ if process_ext is None:
+ process_ext = ProcessExt(pid)
+ process_ext_by_pid[pid] = process_ext
+ process = process_ext.process
+
+ phase = event['ph']
+ if phase == self._EVENT_PHASE_METADATA:
+ if name == 'process_name':
+ process._name = event['args']['name']
+ elif name == 'stackFrames':
+ process._stack_frame_map.ParseNext(
+ self._UseHeapDumpVersion(self.HEAP_DUMP_VERSION_LEGACY),
+ event['args']['stackFrames'],
+ process._string_map)
+ elif phase == self._EVENT_PHASE_MEMORY_DUMP:
+ dumps = event['args']['dumps']
+ process_mmaps = dumps.get('process_mmaps')
+ if process_mmaps:
+ # We want the most recent memory map, so parsing happens later
+ # once we finished reading all events.
+ process_ext.process_mmaps_node = process_mmaps
+ heaps = dumps.get('heaps_v2')
+ if heaps:
+ version = self._UseHeapDumpVersion(heaps['version'])
+ maps = heaps.get('maps')
+ if maps:
+ process_ext.mapped_entry_names.update(maps.keys())
+ types = maps.get('types')
+ stack_frames = maps.get('nodes')
+ strings = maps.get('strings')
+ if (strings is None and (types or stack_frames)
+ and not process_ext.seen_strings_node):
+ # ApplyModifications() for TypeNameMap and StackFrameMap puts
+ # everything into the first node and depends on StringMap. So
+ # we need to make sure that 'strings' node is there if any of
+ # other two nodes present.
+ strings = []
+ maps['strings'] = strings
+ if strings is not None:
+ process_ext.seen_strings_node = True
+ process._string_map.ParseNext(version, strings)
+ if types:
+ process._type_name_map.ParseNext(
+ version, types, process._string_map)
+ if stack_frames:
+ process._stack_frame_map.ParseNext(
+ version, stack_frames, process._string_map)
+
+ self._processes = []
+ for pe in process_ext_by_pid.values():
+ pe.process._heap_dump_version = self._heap_dump_version
+ if pe.process_mmaps_node:
+ # Now parse the most recent memory map.
+ pe.process._memory_map = MemoryMap(pe.process_mmaps_node)
+ self._processes.append(pe.process)
+
+ @property
+ def node(self):
+ """Root node (that was passed to the __init__)."""
+ return self._trace_node
+
+ @property
+ def modified(self):
+ """Returns True if trace file needs to be updated.
+
+ Before writing trace JSON back to a file ApplyModifications() needs
+ to be called.
+ """
+ return any(p.modified for p in self._processes)
+
+ @property
+ def processes(self):
+ return self._processes
+
+ @property
+ def heap_dump_version(self):
+ return self._heap_dump_version
+
+ @property
+ def version(self):
+ return self._version
+
+ @property
+ def os(self):
+ return self._os
+
+ @property
+ def is_chromium(self):
+ return self._is_chromium
+
+ @is_chromium.setter
+ def is_chromium(self, new_value):
+ self._is_chromium = new_value
+
+ @property
+ def is_mac(self):
+ return self._is_mac
+
+ @property
+ def is_win(self):
+ return self._is_win
+
+ @property
+ def is_linux(self):
+ return self._is_linux
+
+ @property
+ def is_android(self):
+ return self._is_android
+
+ @property
+ def is_64bit(self):
+ return self._is_64bit
+
+ @property
+ def library_name(self):
+ return self._trace_node['metadata'].get('chrome-library-name')
+
+ def ApplyModifications(self):
+ """Propagates modifications back to the trace JSON."""
+ for process in self._processes:
+ process.ApplyModifications()
+ assert not self.modified, 'still modified'
+
+ # Relevant trace event phases from Chromium's
+ # src/base/trace_event/common/trace_event_common.h.
+ _EVENT_PHASE_METADATA = 'M'
+ _EVENT_PHASE_MEMORY_DUMP = 'v'
+
+ def _UseHeapDumpVersion(self, version):
+ if self._heap_dump_version is None:
+ self._heap_dump_version = version
+ return version
+ elif self._heap_dump_version != version:
+ raise Exception(
+ ("Inconsistent trace file: first saw '{}' heap dump version, "
+ "then '{}'.").format(self._heap_dump_version, version))
+ else:
+ return version
+
+
+class SymbolizableFile(object):
+ """Holds file path, addresses to symbolize and stack frames to update.
+
+ This class is a link between ELFSymbolizer and a trace file: it specifies
+ what to symbolize (addresses) and what to update with the symbolization
+ result (frames).
+ """
+ def __init__(self, file_path, code_id):
+ self.path = file_path
+ self.symbolizable_path = file_path # path to use for symbolization
+ self.code_id = code_id
+ self.frames_by_address = collections.defaultdict(list)
+ self.skip_symbolization = False
+ self.has_breakpad_symbols = False
+
+
+def ResolveSymbolizableFiles(processes):
+ """Resolves and groups PCs into list of SymbolizableFiles.
+
+ As part of the grouping process, this function resolves PC from each stack
+ frame to the corresponding mmap region. Stack frames that failed to resolve
+ are symbolized with '<unresolved>'.
+ """
+ symfile_by_path = {}
+ for process in processes:
+ if not process.memory_map:
+ continue
+ for frame in process.stack_frame_map.frame_by_id.values():
+ if frame.pc is None:
+ continue
+ region = process.memory_map.FindRegion(frame.pc)
+ if region is None:
+ frame.name = '<unresolved>'
+ continue
+
+ symfile = symfile_by_path.get(region.file_path)
+ if symfile is None:
+ file_path = region.file_path
+ symfile = SymbolizableFile(file_path, region.code_id)
+ symfile_by_path[symfile.path] = symfile
+
+ relative_pc = frame.pc - region.start_address + region.file_offset
+ symfile.frames_by_address[relative_pc].append(frame)
+
+ return symfile_by_path.values()
+
+
+def FindInSystemPath(binary_name):
+ paths = os.environ['PATH'].split(os.pathsep)
+ for path in paths:
+ binary_path = os.path.join(path, binary_name)
+ if os.path.isfile(binary_path):
+ return binary_path
+ return None
+
+
+class BreakpadSymbolsModule(object):
+ """Encapsulates Breakpad logic for symbols of a specific module."""
+
+ def __init__(self, filename):
+ super(BreakpadSymbolsModule, self).__init__()
+ self.filename = filename
+ self.files = []
+ self.symbols = {}
+ self.arch = None
+ self.debug_id = None
+ self.code_id = None
+ self.binary = None
+
+ def Parse(self):
+ # see: https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
+ with open(self.filename) as fp:
+ for line in fp:
+ fragments = line.rstrip().split()
+ if fragments[0] == 'MODULE':
+ # MODULE mac x86_64 A7001116478B33F18FF9BEDE9F615F190 t
+ self.arch = fragments[2]
+ self.debug_id = fragments[3]
+ self.binary = ' '.join(fragments[4:])
+ elif fragments[0] == 'INFO' and fragments[1] == 'CODE_ID':
+ # INFO CODE_ID 595D00BD31F0000 chrome.dll
+ self.code_id = fragments[2]
+ elif fragments[0] == 'FILE':
+ # FILE 0 /b/c/b/mac64/src/out/Release/../../base/at_exit.cc
+ self.files.append(' '.join(fragments[2:]))
+ elif fragments[0] == 'PUBLIC':
+ # PUBLIC db60 0 base::mac::CallWithEHFrame(void () block_pointer)
+ self.symbols[int(fragments[1], 16)] = ' '.join(fragments[3:])
+ elif fragments[0] == 'FUNC':
+ # FUNC 567e0 264 0 Cr_z_fill_window_sse
+ self.symbols[int(fragments[1], 16)] = ' '.join(fragments[4:])
+
+
+class Symbolizer(object):
+ """Encapsulates platform-specific symbolization logic."""
+
+ def __init__(self, addr2line_executable):
+ self.is_mac = sys.platform == 'darwin'
+ self.is_win = sys.platform == 'win32'
+ if self.is_mac:
+ self.binary = 'atos'
+ self._matcher = symbolize_trace_atos_regex.AtosRegexMatcher()
+ elif self.is_win:
+ self.binary = 'addr2line-pdb.exe'
+ else:
+ self.binary = 'addr2line'
+
+ if addr2line_executable and os.path.isfile(addr2line_executable):
+ self.symbolizer_path = addr2line_executable
+ else:
+ self.symbolizer_path = FindInSystemPath(self.binary)
+
+ self.breakpad_modules = {}
+
+ def _SymbolizeLinuxAndAndroid(self, symfile):
+ def _SymbolizerCallback(sym_info, frames):
+ # Unwind inline chain to the top.
+ while sym_info.inlined_by:
+ sym_info = sym_info.inlined_by
+
+ symbolized_name = (sym_info.name if sym_info.name else
+ '<{}>'.format(symfile.path))
+ for frame in frames:
+ frame.name = symbolized_name
+
+ symbolizer = elf_symbolizer.ELFSymbolizer(symfile.symbolizable_path,
+ self.symbolizer_path,
+ _SymbolizerCallback,
+ inlines=True)
+
+ for address, frames in symfile.frames_by_address.items():
+ # SymbolizeAsync() asserts that the type of address is int. We operate
+ # on longs (since they are raw pointers possibly from 64-bit processes).
+ # It's OK to cast here because we're passing relative PC, which should
+ # always fit into int.
+ symbolizer.SymbolizeAsync(int(address), frames)
+
+ symbolizer.Join()
+
+ def _SymbolizeMac(self, symfile):
+ load_address = (symbolize_trace_macho_reader.
+ ReadMachOTextLoadAddress(symfile.symbolizable_path))
+ assert load_address is not None
+
+ address_os_file, address_file_path = tempfile.mkstemp()
+ try:
+ with os.fdopen(address_os_file, 'w') as address_file:
+ for address in symfile.frames_by_address.keys():
+ address_file.write('{:x} '.format(address + load_address))
+
+ cmd = [self.symbolizer_path, '-arch', 'x86_64', '-l',
+ '0x%x' % load_address, '-o', symfile.symbolizable_path,
+ '-f', address_file_path]
+ output_array = subprocess.check_output(cmd).split('\n')
+
+ for i, frames in enumerate(symfile.frames_by_address.values()):
+ symbolized_name = self._matcher.Match(output_array[i])
+ for frame in frames:
+ frame.name = symbolized_name
+ finally:
+ os.remove(address_file_path)
+
+ def _SymbolizeWin(self, symfile):
+ """Invoke symbolizer binary on windows and write all input in one go.
+
+ Unlike linux, on windows, symbolization talks through a shared system
+ service that handles communication with the NT symbol servers. This
+ creates an explicit serialization (and therefor lock contention) of
+ any process using the symbol API for files do not have a local PDB.
+
+ Thus, even though the windows symbolizer binary can be make command line
+ compatible with the POSIX addr2line interface, parallelizing the
+ symbolization does not yield the same performance effects. Running
+ just one symbolizer seems good enough for now. Can optimize later
+ if this becomes a bottleneck.
+ """
+ cmd = [self.symbolizer_path, '--functions', '--demangle', '--exe',
+ symfile.symbolizable_path]
+
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
+ stderr=None)
+ addrs = ["%x" % relative_pc for relative_pc in
+ symfile.frames_by_address.keys()]
+ (stdout_data, _) = proc.communicate('\n'.join(addrs))
+ # On windows, lines may contain '\r' character: e.g. "RtlUserThreadStart\r".
+ stdout_data.replace('\r', '')
+ stdout_data = stdout_data.split('\n')
+
+ # This is known to be in the same order as stderr_data.
+ for i, addr in enumerate(addrs):
+ for frame in symfile.frames_by_address[int(addr, 16)]:
+ # Output of addr2line with --functions is always 2 outputs per
+ # symbol, function name followed by source line number. Only grab
+ # the function name as line info is not always available.
+ frame.name = stdout_data[i * 2]
+
+ def _SymbolizeBreakpad(self, symfile):
+ module_filename = symfile.symbolizable_path
+ module = BreakpadSymbolsModule(module_filename)
+ module.Parse()
+
+ if module.code_id and symfile.code_id and module.code_id != symfile.code_id:
+ print("Warning: Code identifiers do not match for %s" % symfile.path)
+ print(" from trace file: %s" % symfile.code_id)
+ print(" from debug file: %s" % module.code_id)
+ return
+
+ addresses = symfile.frames_by_address.keys()
+ addresses.sort()
+
+ symbols_addresses = module.symbols.keys()
+ symbols_addresses.sort()
+ symbols_addresses.append(float('inf'))
+
+ offset = 0
+ skipped_addresses = 0
+ for symbol_offset in range(1, len(symbols_addresses)):
+ symbol_address_start = symbols_addresses[symbol_offset - 1]
+ symbol_address_end = symbols_addresses[symbol_offset]
+ resolved_symbol = module.symbols[symbol_address_start]
+ while (offset < len(addresses) and
+ addresses[offset] < symbol_address_end):
+ if addresses[offset] >= symbol_address_start:
+ for frame in symfile.frames_by_address[addresses[offset]]:
+ frame.name = resolved_symbol
+ else:
+ skipped_addresses = skipped_addresses + 1
+ offset = offset + 1
+
+ if skipped_addresses:
+ print("warning: %d unsymbolized symbols!" % skipped_addresses)
+
+ def SymbolizeSymfile(self, symfile):
+ if symfile.skip_symbolization:
+ for address, frames in symfile.frames_by_address.items():
+ unsymbolized_name = ('<' + os.path.basename(symfile.symbolizable_path)
+ + '>')
+ # Only append the address if there's a library.
+ if symfile.symbolizable_path != _UNNAMED_FILE:
+ unsymbolized_name += ' + ' + str(hex(address))
+
+ for frame in frames:
+ frame.name = unsymbolized_name
+ return
+
+ if symfile.has_breakpad_symbols:
+ self._SymbolizeBreakpad(symfile)
+ elif self.is_mac:
+ self._SymbolizeMac(symfile)
+ elif self.is_win:
+ self._SymbolizeWin(symfile)
+ else:
+ self._SymbolizeLinuxAndAndroid(symfile)
+
+ def IsSymbolizableFile(self, file_path):
+ if self.is_win:
+ extension = os.path.splitext(file_path)[1].lower()
+ return extension in ['.dll', '.exe']
+ else:
+ result = subprocess.check_output(['file', '-0', file_path])
+ type_string = result[result.find('\0') + 1:]
+ return bool(re.match(r'.*(ELF|Mach-O) (32|64)-bit\b.*',
+ type_string, re.DOTALL))
+
+
+def SymbolizeFiles(symfiles, symbolizer):
+ """Symbolizes each file in the given list of SymbolizableFiles
+ and updates stack frames with symbolization results."""
+
+ if not symfiles:
+ print('Nothing to symbolize.')
+ return
+
+ print('Symbolizing...')
+
+ def _SubPrintf(message, *args):
+ print((' ' + message).format(*args))
+
+ for symfile in symfiles:
+ problem = None
+ if symfile.skip_symbolization:
+ pass
+ elif (symfile.has_breakpad_symbols and
+ os.path.isabs(symfile.symbolizable_path) and
+ os.path.isfile(symfile.symbolizable_path)):
+ pass
+ elif not os.path.isabs(symfile.symbolizable_path):
+ problem = 'not a file'
+ elif not os.path.isfile(symfile.symbolizable_path):
+ problem = "file doesn't exist"
+ elif not symbolizer.IsSymbolizableFile(symfile.symbolizable_path):
+ problem = 'file is not symbolizable'
+ if problem:
+ _SubPrintf("Problem with '{}': {}.",
+ symfile.symbolizable_path,
+ problem)
+ symfile.skip_symbolization = True
+
+ _SubPrintf('Symbolizing {} PCs from {}...',
+ len(symfile.frames_by_address),
+ symfile.symbolizable_path)
+
+ symbolizer.SymbolizeSymfile(symfile)
+
+
+# Subpath of output path where unstripped libraries are stored.
+ANDROID_UNSTRIPPED_SUBPATH = 'lib.unstripped'
+
+
+def RemapAndroidFiles(symfiles, output_path, chrome_soname):
+ for symfile in symfiles:
+ filename = os.path.basename(symfile.path)
+ if os.path.splitext(filename)[1] == '.so':
+ symfile.symbolizable_path = os.path.join(
+ output_path, ANDROID_UNSTRIPPED_SUBPATH, filename)
+ elif os.path.splitext(filename)[1] == '.apk' and chrome_soname:
+ # If there is any pc in .apk memory map, then just assume it is from
+ # chroms.so since we memory map libraries from apk directly. This does
+ # not work for component builds.
+ symfile.symbolizable_path = os.path.join(
+ output_path, ANDROID_UNSTRIPPED_SUBPATH, chrome_soname)
+ else:
+ # Clobber file path to trigger "not a file" problem in SymbolizeFiles().
+ # Without this, files won't be symbolized with "file not found" problem,
+ # which is not accurate.
+ symfile.symbolizable_path = 'android://{}'.format(symfile.path)
+
+
+def RemapMacFiles(symfiles, symbol_base_directory, version,
+ only_symbolize_chrome_symbols):
+ suffix = ("Google Chrome Framework.dSYM/Contents/Resources/DWARF/"
+ "Google Chrome Framework")
+ symbol_sub_dir = os.path.join(symbol_base_directory, version)
+ symbolizable_path = os.path.join(symbol_sub_dir, suffix)
+
+ for symfile in symfiles:
+ if symfile.path.endswith("Google Chrome Framework"):
+ symfile.symbolizable_path = symbolizable_path
+ elif only_symbolize_chrome_symbols:
+ symfile.skip_symbolization = True
+
+
+def RemapWinFiles(symfiles, symbol_base_directory, version, is64bit,
+ only_symbolize_chrome_symbols):
+ folder = "win64" if is64bit else "win"
+ symbol_sub_dir = os.path.join(symbol_base_directory,
+ "chrome-" + folder + "-" + version)
+ for symfile in symfiles:
+ image = os.path.join(symbol_sub_dir, os.path.basename(symfile.path))
+ symbols = image + ".pdb"
+ if os.path.isfile(image) and os.path.isfile(symbols):
+ symfile.symbolizable_path = image
+ elif only_symbolize_chrome_symbols:
+ symfile.skip_symbolization = True
+
+
+def RemapBreakpadModules(symfiles, symbolizer, only_symbolize_chrome_symbols):
+ for symfile in symfiles:
+ image = os.path.basename(symfile.path).lower()
+ # Looked if the image has Breakpad symbols. Breakpad symbols are generated
+ # for Chrome modules for official builds.
+ if image in symbolizer.breakpad_modules:
+ symfile.symbolizable_path = symbolizer.breakpad_modules[image]
+ symfile.has_breakpad_symbols = True
+ elif only_symbolize_chrome_symbols:
+ symfile.skip_symbolization = True
+
+
+def SymbolizeTrace(options, trace, symbolizer):
+ symfiles = ResolveSymbolizableFiles(trace.processes)
+
+ if options.use_breakpad_symbols:
+ RemapBreakpadModules(symfiles, symbolizer,
+ options.only_symbolize_chrome_symbols)
+ else:
+ if trace.is_android:
+ if not options.output_directory:
+ sys.exit('The trace file appears to be from Android. Please '
+ 'specify output directory to properly symbolize it.')
+ RemapAndroidFiles(symfiles, os.path.abspath(options.output_directory),
+ trace.library_name)
+
+ if not trace.is_chromium:
+ if symbolizer.is_mac:
+ RemapMacFiles(symfiles, options.symbol_base_directory, trace.version,
+ options.only_symbolize_chrome_symbols)
+ if symbolizer.is_win:
+ RemapWinFiles(symfiles, options.symbol_base_directory, trace.version,
+ trace.is_64bit, options.only_symbolize_chrome_symbols)
+
+ SymbolizeFiles(symfiles, symbolizer)
+
+
+def FetchAndExtractBreakpadSymbols(symbol_base_directory,
+ breakpad_info_folder,
+ trace,
+ symbolizer,
+ cloud_storage_bucket):
+
+ if breakpad_info_folder:
+ # Using local symbols from |breakpad_info_folder|.
+ symbol_sub_dir = breakpad_info_folder
+ else:
+ # Fetching the symbols from GCS (OS dependent).
+ if trace.is_win:
+ folder = 'win64-pgo' if trace.is_64bit else 'win-pgo'
+ elif trace.is_mac:
+ folder = 'mac64'
+ elif trace.is_linux:
+ folder = 'linux64'
+ else:
+ raise Exception('OS not supported for Breakpad symbolization (%s/%s)' %
+ (trace.os, trace.version))
+
+ gsc_folder = 'desktop-*/' + trace.version + '/' + folder
+ gcs_file = gsc_folder + '/breakpad-info'
+
+ symbol_sub_dir = os.path.join(symbol_base_directory,
+ 'breakpad-info_' + trace.version + '_' + folder)
+ zip_path = symbol_sub_dir + '/breakpad-info.zip'
+
+ # Check whether symbols are already downloaded and extracted.
+ if not os.path.isdir(symbol_sub_dir):
+ if cloud_storage.Exists(cloud_storage_bucket, gcs_file + '.zip'):
+ # Some version, like mac, doesn't have the .zip extension.
+ gcs_file = gcs_file + '.zip'
+ elif not cloud_storage.Exists(cloud_storage_bucket, gcs_file):
+ print("Can't find symbols on GCS " + gcs_file + ".")
+ return False
+ print('Downloading symbols files from GCS, please wait.')
+ cloud_storage.Get(cloud_storage_bucket, gcs_file, zip_path)
+
+ with zipfile.ZipFile(zip_path, 'r') as zip_file:
+ zip_file.extractall(symbol_sub_dir)
+ os.remove(zip_path)
+
+ # Parse breakpad module header (first line) and register known modules.
+ for root, _, filenames in os.walk(symbol_sub_dir):
+ for filename in filenames:
+ full_filename = os.path.abspath(os.path.join(root, filename))
+ with open(full_filename, 'r') as file_handle:
+ first_line = file_handle.readline()
+ fragments = first_line.rstrip().split()
+ if fragments[0] == 'MODULE':
+ binary = ' '.join(fragments[4:]).lower()
+ module_name, extension = os.path.splitext(binary)
+ if extension == ".pdb":
+ binary = module_name
+ symbolizer.breakpad_modules[binary] = full_filename
+
+ return True
+
+
+def OpenTraceFile(file_path, mode):
+ if file_path.endswith('.gz'):
+ return gzip.open(file_path, mode + 'b')
+ else:
+ return open(file_path, mode + 't')
+
+
+def FetchAndExtractSymbolsMac(symbol_base_directory, version,
+ cloud_storage_bucket):
+ def GetLocalPath(base_dir, version):
+ return os.path.join(base_dir, version + ".tar.bz2")
+ def GetSymbolsPath(version):
+ return "desktop-*/" + version + "/mac64/Google Chrome.dSYM.tar.bz2"
+ def ExtractSymbolTarFile(symbol_sub_dir, symbol_tar_file):
+ os.makedirs(symbol_sub_dir)
+ with tarfile.open(os.path.expanduser(symbol_tar_file), "r:bz2") as tar:
+ tar.extractall(symbol_sub_dir)
+
+ symbol_sub_dir = os.path.join(symbol_base_directory, version)
+ if os.path.isdir(symbol_sub_dir):
+ return True
+
+ bzip_path = GetLocalPath(symbol_base_directory, version)
+ if not os.path.isfile(bzip_path):
+ if not cloud_storage.Exists(cloud_storage_bucket, GetSymbolsPath(version)):
+ print("Can't find symbols on GCS '%s'." % version)
+ return False
+ print("Downloading symbols files from GCS, please wait.")
+ cloud_storage.Get(cloud_storage_bucket, GetSymbolsPath(version), bzip_path)
+
+ ExtractSymbolTarFile(symbol_sub_dir, bzip_path)
+ os.remove(bzip_path)
+ return True
+
+
+def FetchAndExtractSymbolsWin(symbol_base_directory, version, is64bit,
+ cloud_storage_bucket):
+ def DownloadAndExtractZipFile(zip_path, source, destination):
+ if not os.path.isfile(zip_path):
+ if not cloud_storage.Exists(cloud_storage_bucket, source):
+ print("Can't find symbols on GCS '%s'." % version)
+ return False
+ print("Downloading symbols files from GCS, please wait.")
+ cloud_storage.Get(cloud_storage_bucket, source, zip_path)
+ if not os.path.isfile(zip_path):
+ print("Can't download symbols on GCS.")
+ return False
+ with zipfile.ZipFile(zip_path, "r") as zip_file:
+ for member in zip_file.namelist():
+ filename = os.path.basename(member)
+ # Skip directories.
+ if not filename:
+ continue
+ # Extract archived files.
+ source = zip_file.open(member)
+ target = file(os.path.join(destination, filename), "wb")
+ with source, target:
+ shutil.copyfileobj(source, target)
+
+ folder = "win64" if is64bit else "win"
+ # Clang build (M61+)
+ folder_suffix = "-clang"
+ gcs_folder = "desktop-*/" + version + "/" + folder + folder_suffix + "/"
+ if not cloud_storage.Exists(cloud_storage_bucket, gcs_folder):
+ # MSVC build (before M61)
+ folder_suffix = "-pgo"
+ gcs_folder = "desktop-*/" + version + "/" + folder + folder_suffix + "/"
+
+ symbol_sub_dir = os.path.join(symbol_base_directory,
+ "chrome-" + folder + "-" + version)
+ if os.path.isdir(symbol_sub_dir):
+ return True
+
+ os.makedirs(symbol_sub_dir)
+ DownloadAndExtractZipFile(
+ os.path.join(symbol_base_directory,
+ "chrome-" + folder + "-" + version + "-syms.zip"),
+ gcs_folder + "chrome-win32-syms.zip",
+ symbol_sub_dir)
+ DownloadAndExtractZipFile(
+ os.path.join(symbol_base_directory,
+ "chrome-" + folder + "-" + version + ".zip"),
+ gcs_folder + "chrome-" + folder + folder_suffix + ".zip",
+ symbol_sub_dir)
+
+ return True
+
+# Suffix used for backup files.
+BACKUP_FILE_TAG = '.BACKUP'
+
+def main(args):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'file',
+ help='Trace file to symbolize (.json or .json.gz)')
+
+ parser.add_argument(
+ '--no-backup', dest='backup', action='store_false',
+ help="Don't create {} files".format(BACKUP_FILE_TAG))
+
+ parser.add_argument(
+ '--is-local-build', action='store_true',
+ help="Indicate that the memlog trace is from a local build of Chromium.")
+
+ parser.add_argument(
+ '--output-directory',
+ help='The path to the build output directory, such as out/Debug.')
+
+ parser.add_argument(
+ '--only-symbolize-chrome-symbols',
+ action='store_true',
+ help='Prevents symbolization of non-Chrome [system] symbols.')
+
+ parser.add_argument(
+ '--cloud-storage-bucket', default='chrome-unsigned',
+ help="Bucket that holds symbols for official Chrome builds. "
+ "Used by tests, which don't have access to the default bucket.")
+
+ parser.add_argument(
+ '--addr2line-executable', default=None,
+ help="The path to the executable used to convert address to line."
+ "Default uses the executable found in the PATH environment variable."
+ "Used by tests, which don't have the executable.")
+
+ parser.add_argument(
+ '--use-breakpad-symbols',
+ action='store_true',
+ help='Use breakpad symbols files for symbolisation.')
+
+ parser.add_argument(
+ '--breakpad-symbols-directory', default=None,
+ help='A path to a directory containing breakpad symbols.')
+
+ home_dir = os.path.expanduser('~')
+ default_dir = os.path.join(home_dir, "symbols")
+ parser.add_argument(
+ '--symbol-base-directory',
+ default=default_dir,
+ help='Directory where symbols are downloaded and cached.')
+
+ options = parser.parse_args(args)
+
+ symbolizer = Symbolizer(options.addr2line_executable)
+ if (symbolizer.symbolizer_path is None and
+ not options.use_breakpad_symbols):
+ sys.exit("Can't symbolize - no %s in PATH." % symbolizer.binary)
+
+ trace_file_path = options.file
+
+ print('Reading trace file...')
+ with OpenTraceFile(trace_file_path, 'r') as trace_file:
+ trace = Trace(json.load(trace_file))
+ print('Trace loaded for %s/%s' % (trace.os, trace.version))
+
+ trace.is_chromium = options.is_local_build
+
+ # Perform some sanity checks.
+ if (trace.is_win and sys.platform != 'win32' and
+ not options.use_breakpad_symbols):
+ print("Cannot symbolize a windows trace on this architecture!")
+ return False
+
+ # If the trace is from Chromium, assume that symbols are already present.
+ # Otherwise the trace is from Google Chrome. Assume that this is not a local
+ # build of Google Chrome with symbols, and that we need to fetch symbols
+ # from gcs.
+ if trace.is_chromium or options.output_directory:
+ if options.use_breakpad_symbols and options.breakpad_symbols_directory:
+ # Local build with local symbols.
+ FetchAndExtractBreakpadSymbols(
+ options.symbol_base_directory,
+ options.breakpad_symbols_directory,
+ trace, symbolizer,
+ options.cloud_storage_bucket)
+ else:
+ has_symbols = False
+ if options.use_breakpad_symbols:
+ # Official build, using Breakpad symbolization.
+ has_symbols = FetchAndExtractBreakpadSymbols(
+ options.symbol_base_directory,
+ options.breakpad_symbols_directory,
+ trace, symbolizer,
+ options.cloud_storage_bucket)
+ else:
+ # Official build, using native symbolization.
+ if symbolizer.is_mac:
+ has_symbols = FetchAndExtractSymbolsMac(options.symbol_base_directory,
+ trace.version,
+ options.cloud_storage_bucket)
+ elif symbolizer.is_win:
+ has_symbols = FetchAndExtractSymbolsWin(options.symbol_base_directory,
+ trace.version, trace.is_64bit,
+ options.cloud_storage_bucket)
+ else:
+ raise Exception('OS not supported for native symbolization (%s/%s)' %
+ (trace.os, trace.version))
+ if not has_symbols:
+ print('Cannot fetch symbols from GCS')
+ return False
+
+ SymbolizeTrace(options, trace, symbolizer)
+
+ if trace.modified:
+ trace.ApplyModifications()
+
+ if options.backup:
+ backup_file_path = trace_file_path + BACKUP_FILE_TAG
+ print('Backing up trace file to {}'.format(backup_file_path))
+ os.rename(trace_file_path, backup_file_path)
+
+ print('Updating the trace file...')
+ with OpenTraceFile(trace_file_path, 'w') as trace_file:
+ trace_file.write(json.dumps(trace.node))
+ else:
+ print('No modifications were made - not updating the trace file.')
+ return True
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_atos_regex.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_atos_regex.py
new file mode 100644
index 00000000000..65356c3efa3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_atos_regex.py
@@ -0,0 +1,36 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+
+
+class AtosRegexMatcher(object):
+ def __init__(self):
+ """
+ Atos output has two useful forms:
+ 1. <name> (in <library name>) (<filename>:<linenumber>)
+ 2. <name> (in <library name>) + <symbol offset>
+ And two less useful forms:
+ 3. <address>
+ 4. <address> (in <library name>)
+ e.g.
+ 1. -[SKTGraphicView drawRect:] (in Sketch) (SKTGraphicView.m:445)
+ 2. malloc (in libsystem_malloc.dylib) + 42
+ 3. 0x4a12
+ 4. 0x00000d9a (in Chromium)
+
+ We don't bother checking for the latter two, and just return the full
+ output.
+ """
+ self._regex1 = re.compile(r"(.*) \(in (.+)\) \((.+):(\d+)\)")
+ self._regex2 = re.compile(r"(.*) \(in (.+)\) \+ (\d+)")
+
+ def Match(self, text):
+ result = self._regex1.match(text)
+ if result:
+ return result.group(1)
+ result = self._regex2.match(text)
+ if result:
+ return result.group(1)
+ return text
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_atos_regex_unittest.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_atos_regex_unittest.py
new file mode 100644
index 00000000000..28b488badde
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_atos_regex_unittest.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import unittest
+
+from . import symbolize_trace_atos_regex
+
+
+class AtosRegexTest(unittest.TestCase):
+ def testRegex(self):
+ if sys.platform != "darwin":
+ return
+ matcher = symbolize_trace_atos_regex.AtosRegexMatcher()
+ text = "-[SKTGraphicView drawRect:] (in Sketch) (SKTGraphicView.m:445)"
+ output = matcher.Match(text)
+ self.assertEqual("-[SKTGraphicView drawRect:]", output)
+
+ text = "malloc (in libsystem_malloc.dylib) + 42"
+ output = matcher.Match(text)
+ self.assertEqual("malloc", output)
+
+ expected_output = (
+ "content::CacheStorage::MatchAllCaches(std::__1::unique_ptr<content::Se"
+ "rviceWorkerFetchRequest, std::__1::default_delete<content::ServiceWork"
+ "erFetchRequest> >, content::CacheStorageCacheQueryParams const&, base:"
+ ":Callback<void (content::CacheStorageError, std::__1::unique_ptr<conte"
+ "nt::ServiceWorkerResponse, std::__1::default_delete<content::ServiceWo"
+ "rkerResponse> >, std::__1::unique_ptr<storage::BlobDataHandle, std::__"
+ "1::default_delete<storage::BlobDataHandle> >), (base::internal::CopyMo"
+ "de)1, (base::internal::RepeatMode)1> const&)"
+ )
+ text = expected_output + " (in Chromium Framework) (ref_counted.h:322)"
+ output = matcher.Match(text)
+ self.assertEqual(expected_output, output)
+
+ text = "0x4a12"
+ output = matcher.Match(text)
+ self.assertEqual(text, output)
+
+ text = "0x00000d9a (in Chromium)"
+ output = matcher.Match(text)
+ self.assertEqual(text, output)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_end_to_end_test_slow.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_end_to_end_test_slow.py
new file mode 100755
index 00000000000..0a416800596
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_end_to_end_test_slow.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# pylint: disable=line-too-long
+# To upload test files, use the command:
+# <path_to_depot_tools>/upload_to_google_storage.py --bucket chrome-partner-telemetry <path_to_data_dir>/linux_trace_v2_breakpad_postsymbolization.json.gz
+#
+# To run this test suite, use ./tracing/bin/run_symbolizer_tests
+
+from __future__ import print_function
+
+import json
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+from tracing.extras.symbolizer import symbolize_trace
+
+_THIS_DIR_PATH = os.path.abspath(os.path.dirname(__file__))
+_TRACING_DIR = os.path.abspath(
+ os.path.join(_THIS_DIR_PATH,
+ os.path.pardir,
+ os.path.pardir,
+ os.path.pardir))
+_PY_UTILS_PATH = os.path.abspath(os.path.join(
+ _TRACING_DIR,
+ os.path.pardir,
+ 'common',
+ 'py_utils'))
+sys.path.append(_PY_UTILS_PATH)
+import py_utils.cloud_storage as cloud_storage # pylint: disable=wrong-import-position
+
+
+def _DownloadFromCloudStorage(path):
+ print('Downloading %s from gcs.' % (path))
+ cloud_storage.GetIfChanged(path, cloud_storage.PARTNER_BUCKET)
+
+
+class SymbolizeTraceEndToEndTest(unittest.TestCase):
+ def _ValidateTrace(self, trace_path, expectations):
+ with symbolize_trace.OpenTraceFile(trace_path, 'r') as trace_file:
+ trace = symbolize_trace.Trace(json.load(trace_file))
+ # Find the browser process.
+ browser = None
+ for process in trace.processes:
+ if process.name == expectations['process']:
+ browser = process
+ self.assertTrue(browser)
+
+ # Look for a frame with a symbolize name, and check that it has the right
+ # parent.
+ frames = browser.stack_frame_map.frame_by_id
+ exact = expectations['frame_exact']
+ found = False
+ for _, frame in frames.items():
+ if frame.name.strip() == exact['frame_name']:
+ parent_id = frame.parent_id
+ if frames[parent_id].name.strip() == exact['parent_name']:
+ found = True
+ break
+
+ self.assertTrue(found)
+
+
+ def _RunSymbolizationOnTrace(self, pre_symbolization, expectations,
+ extra_options):
+ trace_presymbolization_path = os.path.join(
+ _THIS_DIR_PATH, 'data', pre_symbolization)
+ _DownloadFromCloudStorage(trace_presymbolization_path)
+ self.assertTrue(os.path.exists(trace_presymbolization_path))
+
+ temporary_fd, temporary_trace = tempfile.mkstemp(suffix='.json.gz')
+
+ symbolization_options = ['--only-symbolize-chrome-symbols',
+ '--no-backup',
+ '--cloud-storage-bucket',
+ cloud_storage.PARTNER_BUCKET,
+ temporary_trace]
+
+ symbolization_options.extend(extra_options)
+
+ # On windows, a pre-built version of addr2line-pdb is provided.
+ if sys.platform == 'win32':
+ addr2line_path = os.path.join(
+ _THIS_DIR_PATH, 'data', 'addr2line-pdb.exe')
+ _DownloadFromCloudStorage(addr2line_path)
+ self.assertTrue(os.path.exists(addr2line_path))
+ symbolization_options += ['--addr2line-executable', addr2line_path]
+
+ # Execute symbolization and compare results with the expected trace.
+ try:
+ shutil.copy(trace_presymbolization_path, temporary_trace)
+ self.assertTrue(symbolize_trace.main(symbolization_options))
+ self._ValidateTrace(temporary_trace, expectations)
+ finally:
+ os.close(temporary_fd)
+ if os.path.exists(temporary_trace):
+ os.remove(temporary_trace)
+
+
+ def testMacv2(self):
+ if sys.platform != 'darwin':
+ return
+ # The corresponding macOS Chrome symbols must be uploaded to
+ # "gs://chrome-partner-telemetry/desktop-symbolizer-test/66.0.3334.0/mac64/Google Chrome.dSYM.tar.bz2"
+ # since the waterfall bots do not have access to the chrome-unsigned bucket.
+ expectations = {}
+ expectations['process'] = 'Browser'
+ expectations['frame_exact'] = {
+ 'parent_name': 'ProfileImpl::OnPrefsLoaded(Profile::CreateMode, bool)',
+ 'frame_name': 'ProfileImpl::OnLocaleReady()'
+ }
+ self._RunSymbolizationOnTrace(
+ 'mac_trace_v2_presymbolization.json.gz',
+ expectations, [])
+
+ def testMacv2Breakpad(self):
+ # The corresponding macOS Chrome symbols must be uploaded to
+ # "gs://chrome-partner-telemetry/desktop-symbolizer-test/66.0.3334.0/mac64/breakpad-info"
+ # since the waterfall bots do not have access to the chrome-unsigned bucket.
+ expectations = {}
+ expectations['process'] = 'Browser'
+ expectations['frame_exact'] = {
+ 'parent_name': 'ProfileImpl::OnPrefsLoaded(Profile::CreateMode, bool)',
+ 'frame_name': 'ProfileImpl::OnLocaleReady()'
+ }
+ self._RunSymbolizationOnTrace(
+ 'mac_trace_v2_presymbolization.json.gz',
+ expectations, ['--use-breakpad-symbols'])
+
+ def testWin64v1(self):
+ if sys.platform != 'win32':
+ return
+
+ expectations = {}
+ expectations['process'] = 'Browser'
+ expectations['frame_exact'] = {
+ 'parent_name': 'ChromeMain',
+ 'frame_name': 'content::ContentMain'
+ }
+ # The corresponding Win64 Chrome symbols must be uploaded to
+ # "gs://chrome-partner-telemetry/desktop-symbolizer-test/61.0.3130.0/"
+ # "win64-pgo/chrome-win32-syms.zip"
+ # and the corresponding executables to
+ # "gs://chrome-partner-telemetry/desktop-symbolizer-test/61.0.3130.0/"
+ # "win64-pgo/chrome-win64-pgo.zip"
+ # since the waterfall bots do not have access to the chrome-unsigned bucket.
+ self._RunSymbolizationOnTrace('windows_trace_v1_presymbolization.json.gz',
+ expectations,
+ [])
+
+ def testWin64v2(self):
+ if sys.platform != 'win32':
+ return
+
+ expectations = {}
+ expectations['process'] = 'Browser'
+ expectations['frame_exact'] = {
+ 'parent_name': 'base::MessagePumpWin::Run',
+ 'frame_name': 'base::MessagePumpForUI::DoRunLoop'
+ }
+ # The corresponding Win64 Chrome symbols must be uploaded to
+ # "gs://chrome-partner-telemetry/desktop-symbolizer-test/61.0.3142.0/"
+ # "win64-pgo/chrome-win32-syms.zip"
+ # and the corresponding executables to
+ # "gs://chrome-partner-telemetry/desktop-symbolizer-test/61.0.3142.0/"
+ # "win64-pgo/chrome-win64-pgo.zip"
+ # since the waterfall bots do not have access to the chrome-unsigned bucket.
+ self._RunSymbolizationOnTrace('windows_trace_v2_presymbolization.json.gz',
+ expectations,
+ [])
+
+
+ def testLinuxv2(self):
+ # The corresponding Linux breakpad symbols must be uploaded to
+ # "gs://chrome-partner-telemetry/desktop-symbolizer-test/64.0.3282.24/linux64/breakpad-info.zip"
+ # since the waterfall bots do not have access to the chrome-unsigned bucket.
+ expectations = {}
+ expectations['process'] = 'Renderer'
+ expectations['frame_exact'] = {
+ 'parent_name': 'cc::LayerTreeSettings::LayerTreeSettings(cc::LayerTreeSettings const&)',
+ 'frame_name': 'viz::ResourceSettings::ResourceSettings(viz::ResourceSettings const&)'
+ }
+ self._RunSymbolizationOnTrace(
+ 'linux_trace_v2_presymbolization.json.gz',
+ expectations,
+ ['--use-breakpad-symbols'])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py
new file mode 100644
index 00000000000..ea8a6366671
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader.py
@@ -0,0 +1,26 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import subprocess
+
+
+def ReadMachOTextLoadAddress(file_name):
+ """
+ This function returns the load address of the TEXT segment of a Mach-O file.
+ """
+ regex = re.compile(r".* vmaddr 0x([\dabcdef]*)")
+ cmd = ["otool", "-l", file_name]
+ output = subprocess.check_output(cmd).split('\n')
+ for i in range(len(output) - 3):
+ # It's possible to use a regex here instead, but these conditionals are much
+ # clearer.
+ if ("cmd LC_SEGMENT_64" in output[i] and
+ "cmdsize" in output[i + 1] and
+ "segname __TEXT" in output[i + 2] and
+ "vmaddr" in output[i + 3]):
+ result = regex.match(output[i + 3])
+ assert result
+ return int(result.group(1), 16)
+ return None
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py
new file mode 100644
index 00000000000..f0058abda51
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_macho_reader_unittest.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import unittest
+
+from . import symbolize_trace_macho_reader
+
+
+class AtosRegexTest(unittest.TestCase):
+ def testRegex(self):
+ if sys.platform != "darwin":
+ return
+ file_name = "/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit"
+ result = symbolize_trace_macho_reader.ReadMachOTextLoadAddress(file_name)
+ self.assertNotEqual(None, result)
+
+ file_name = "/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa"
+ result = symbolize_trace_macho_reader.ReadMachOTextLoadAddress(file_name)
+ self.assertNotEqual(None, result)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_unittest.py b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_unittest.py
new file mode 100755
index 00000000000..1b9b7b912c5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/symbolizer/symbolize_trace_unittest.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from . import symbolize_trace
+
+class StackFrameMapTest(unittest.TestCase):
+
+ def assertStackFrame(self, stack_frame_map, frame_id, name, parent_id=None):
+ self.assertTrue(frame_id in stack_frame_map.frame_by_id)
+ frame = stack_frame_map.frame_by_id[frame_id]
+ self.assertEqual(name, frame.name)
+ self.assertEqual(parent_id, frame.parent_id)
+
+ def testParseNext(self):
+ string_map = symbolize_trace.StringMap()
+ stack_frame_map = symbolize_trace.StackFrameMap()
+
+ # Check that ParseNext() actually parses anything.
+ stack_frame_map.ParseNext(
+ symbolize_trace.Trace.HEAP_DUMP_VERSION_1,
+ [
+ {'id': 1, 'name_sid': string_map.AddString('main')},
+ {'id': 45, 'name_sid': string_map.AddString('foo'), 'parent': 1},
+ ],
+ string_map)
+ self.assertStackFrame(stack_frame_map, 1, 'main')
+ self.assertStackFrame(stack_frame_map, 45, 'foo', parent_id=1)
+
+ # Check that ParseNext() retains all previously parsed frames.
+ stack_frame_map.ParseNext(
+ symbolize_trace.Trace.HEAP_DUMP_VERSION_1,
+ [
+ {'id': 33, 'name_sid': string_map.AddString('bar')},
+ ],
+ string_map)
+ self.assertStackFrame(stack_frame_map, 1, 'main')
+ self.assertStackFrame(stack_frame_map, 45, 'foo', parent_id=1)
+ self.assertStackFrame(stack_frame_map, 33, 'bar')
+
+ def testParseNextLegacy(self):
+ stack_frame_map = symbolize_trace.StackFrameMap()
+
+ stack_frame_map.ParseNext(
+ symbolize_trace.Trace.HEAP_DUMP_VERSION_LEGACY,
+ {
+ 1: {'name': 'main'},
+ 45: {'name': 'foo', 'parent': 1},
+ },
+ string_map=None)
+ self.assertStackFrame(stack_frame_map, 1, 'main')
+ self.assertStackFrame(stack_frame_map, 45, 'foo', parent_id=1)
+
+ # When parsing legacy format, ParseNext() is expected to be called once.
+ self.assertRaises(
+ Exception,
+ stack_frame_map.ParseNext,
+ symbolize_trace.Trace.HEAP_DUMP_VERSION_LEGACY,
+ {
+ 33: {'name': 'bar'},
+ },
+ string_map=None)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/system_stats/system_stats_snapshot.html b/chromium/third_party/catapult/tracing/tracing/extras/system_stats/system_stats_snapshot.html
new file mode 100644
index 00000000000..4b23769967e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/system_stats/system_stats_snapshot.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/util.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.system_stats', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ /**
+ * @constructor
+ */
+ function SystemStatsSnapshot(objectInstance, ts, args) {
+ ObjectSnapshot.apply(this, arguments);
+ this.objectInstance = objectInstance;
+ this.ts = ts;
+ this.args = args;
+ this.stats_ = args;
+ }
+
+ SystemStatsSnapshot.prototype = {
+ __proto__: ObjectSnapshot.prototype,
+
+ initialize() {
+ if (this.args.length === 0) {
+ throw new Error('No system stats snapshot data.');
+ }
+ this.stats_ = this.args;
+ },
+
+ getStats() {
+ return this.stats_;
+ },
+
+ setStats(stats) {
+ this.stats_ = stats;
+ }
+ };
+
+ ObjectSnapshot.subTypes.register(
+ SystemStatsSnapshot,
+ {typeName: 'base::TraceEventSystemStatsMonitor::SystemStats'});
+
+ return {
+ SystemStatsSnapshot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/systrace_config.html b/chromium/third_party/catapult/tracing/tracing/extras/systrace_config.html
new file mode 100644
index 00000000000..7711959fcc7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/systrace_config.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/android/android_auditor.html">
+<link rel="import" href="/tracing/extras/cpu/cpu_usage_auditor.html">
+<link rel="import" href="/tracing/extras/importer/android/atrace_process_dump_importer.html">
+<link rel="import" href="/tracing/extras/importer/android/event_log_importer.html">
+<link rel="import" href="/tracing/extras/importer/android/process_data_importer.html">
+<link rel="import" href="/tracing/extras/importer/battor_importer.html">
+<link rel="import" href="/tracing/extras/importer/ddms_importer.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/extras/memory/lowmemory_auditor.html">
+<link rel="import" href="/tracing/extras/vsync/vsync_auditor.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/model/model.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/context.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/context.html
new file mode 100644
index 00000000000..8c893206543
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/context.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function Context() {
+ this.event = undefined;
+ this.ancestors = [];
+ }
+
+ Context.prototype = {
+ push(event) {
+ const ctx = new Context();
+ ctx.ancestors = this.ancestors.slice();
+ ctx.ancestors.push(event);
+ return ctx;
+ },
+
+ pop(event) {
+ const ctx = new Context();
+ ctx.event = this.ancestors[this.ancestors.length - 1];
+ ctx.ancestors = this.ancestors.slice(0, this.ancestors.length - 1);
+ return ctx;
+ }
+ };
+
+ return {
+ Context,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter.html
new file mode 100644
index 00000000000..62126e3fc0c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/scripting_object.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function Filter() {
+ tr.c.ScriptingObject.call(this);
+ }
+
+ Filter.normalizeFilterExpression = function(filterExpression) {
+ // Shortcut: naked strings and regexps can be used to match against slice
+ // titles.
+ if (filterExpression instanceof String ||
+ typeof(filterExpression) === 'string' ||
+ filterExpression instanceof RegExp) {
+ const filter = new tr.e.tquery.FilterHasTitle(filterExpression);
+ return filter;
+ }
+ return filterExpression;
+ };
+
+ Filter.prototype = {
+ __proto__: tr.c.ScriptingObject.prototype,
+
+ evaluate(context) {
+ throw new Error('Not implemented');
+ },
+
+ matchValue_(value, expected) {
+ if (expected instanceof RegExp) {
+ return expected.test(value);
+ } else if (expected instanceof Function) {
+ return expected(value);
+ }
+ return value === expected;
+ }
+ };
+
+ return {
+ Filter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_all_of.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_all_of.html
new file mode 100644
index 00000000000..89f187100cc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_all_of.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/extras/tquery/filter.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function FilterAllOf(opt_subExpressions) {
+ tr.e.tquery.Filter.call(this);
+ this.subExpressions = opt_subExpressions || [];
+ }
+
+ FilterAllOf.prototype = {
+ __proto__: tr.e.tquery.Filter.prototype,
+
+ set subExpressions(exprs) {
+ this.subExpressions_ = [];
+ for (let i = 0; i < exprs.length; i++) {
+ this.subExpressions_.push(
+ tr.e.tquery.Filter.normalizeFilterExpression(exprs[i]));
+ }
+ },
+
+ get subExpressions() {
+ return this.subExpressions_;
+ },
+
+ evaluate(context) {
+ if (!this.subExpressions.length) return true;
+ for (let i = 0; i < this.subExpressions.length; i++) {
+ if (!this.subExpressions[i].evaluate(context)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+ tr.c.ScriptingObjectRegistry.register(
+ function() {
+ const exprs = [];
+ for (let i = 0; i < arguments.length; i++) {
+ exprs.push(arguments[i]);
+ }
+ return new FilterAllOf(exprs);
+ },
+ {
+ name: 'allOf'
+ }
+ );
+ return {
+ FilterAllOf,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_any_of.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_any_of.html
new file mode 100644
index 00000000000..3303adc53c9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_any_of.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/extras/tquery/filter.html">
+<link rel="import" href="/tracing/extras/tquery/filter_not.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function FilterAnyOf(opt_subExpressions) {
+ tr.e.tquery.Filter.call(this);
+ this.subExpressions = opt_subExpressions || [];
+ }
+
+ FilterAnyOf.prototype = {
+ __proto__: tr.e.tquery.Filter.prototype,
+
+ set subExpressions(exprs) {
+ this.subExpressions_ = [];
+ for (let i = 0; i < exprs.length; i++) {
+ this.subExpressions_.push(
+ tr.e.tquery.Filter.normalizeFilterExpression(exprs[i]));
+ }
+ },
+
+ get subExpressions() {
+ return this.subExpressions_;
+ },
+
+ evaluate(context) {
+ if (!this.subExpressions.length) return true;
+ for (let i = 0; i < this.subExpressions.length; i++) {
+ if (this.subExpressions[i].evaluate(context)) return true;
+ }
+ return false;
+ }
+ };
+ tr.c.ScriptingObjectRegistry.register(
+ function() {
+ const exprs = Array.prototype.slice.call(arguments);
+ return new FilterAnyOf(exprs);
+ },
+ {
+ name: 'anyOf'
+ }
+ );
+ tr.c.ScriptingObjectRegistry.register(
+ function() {
+ const exprs = Array.prototype.slice.call(arguments);
+ return new tr.e.tquery.FilterNot(new FilterAnyOf(exprs));
+ },
+ {
+ name: 'noneOf'
+ }
+ );
+ return {
+ FilterAnyOf,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_ancestor.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_ancestor.html
new file mode 100644
index 00000000000..98597ccb2da
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_ancestor.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/extras/tquery/filter.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function FilterHasAncestor(opt_subExpression) {
+ this.subExpression = opt_subExpression;
+ }
+
+ FilterHasAncestor.prototype = {
+ __proto__: tr.e.tquery.Filter.prototype,
+
+ set subExpression(expr) {
+ this.subExpression_ = tr.e.tquery.Filter.normalizeFilterExpression(expr);
+ },
+
+ get subExpression() {
+ return this.subExpression_;
+ },
+
+ evaluate(context) {
+ if (!this.subExpression) {
+ return context.ancestors.length > 0;
+ }
+ while (context.ancestors.length) {
+ context = context.pop();
+ if (this.subExpression.evaluate(context)) return true;
+ }
+ return false;
+ }
+ };
+ tr.c.ScriptingObjectRegistry.register(
+ function(subExpression) {
+ return new FilterHasAncestor(subExpression);
+ },
+ {
+ name: 'hasAncestor'
+ }
+ );
+ return {
+ FilterHasAncestor,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_duration.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_duration.html
new file mode 100644
index 00000000000..ab5828e2dda
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_duration.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/extras/tquery/filter.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function FilterHasDuration(minValueOrExpected, opt_maxValue) {
+ if (minValueOrExpected !== undefined && opt_maxValue !== undefined) {
+ this.minValue = minValueOrExpected;
+ this.maxValue = opt_maxValue;
+ } else {
+ this.expected = minValueOrExpected;
+ }
+ }
+
+ FilterHasDuration.prototype = {
+ __proto__: tr.e.tquery.Filter.prototype,
+
+ evaluate(context) {
+ if (context.event.duration === undefined) return false;
+ if (this.minValue !== undefined && this.maxValue !== undefined) {
+ return context.event.duration >= this.minValue &&
+ context.event.duration <= this.maxValue;
+ }
+ return this.matchValue_(context.event.duration, this.expected);
+ }
+ };
+ tr.c.ScriptingObjectRegistry.register(
+ function(minValueOrExpected, opt_maxValue) {
+ return new FilterHasDuration(minValueOrExpected, opt_maxValue);
+ },
+ {
+ name: 'hasDuration'
+ }
+ );
+ return {
+ FilterHasDuration,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_title.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_title.html
new file mode 100644
index 00000000000..dcd4c8ac79b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_has_title.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/extras/tquery/filter.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function FilterHasTitle(expected) {
+ tr.e.tquery.Filter.call(this);
+ this.expected = expected;
+ }
+
+ FilterHasTitle.prototype = {
+ __proto__: tr.e.tquery.Filter.prototype,
+
+ evaluate(context) {
+ return this.matchValue_(context.event.title, this.expected);
+ }
+ };
+ tr.c.ScriptingObjectRegistry.register(
+ function(expected) {
+ const filter = new tr.e.tquery.FilterHasTitle(expected);
+ return filter;
+ },
+ {
+ name: 'hasTitle'
+ }
+ );
+
+ return {
+ FilterHasTitle,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_is_top_level.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_is_top_level.html
new file mode 100644
index 00000000000..24fd66d8aa3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_is_top_level.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/extras/tquery/filter.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function FilterIsTopLevel(opt_subExpression) {
+ this.subExpression = opt_subExpression;
+ }
+
+ FilterIsTopLevel.prototype = {
+ __proto__: tr.e.tquery.Filter.prototype,
+
+ set subExpression(expr) {
+ this.subExpression_ = tr.e.tquery.Filter.normalizeFilterExpression(expr);
+ },
+
+ get subExpression() {
+ return this.subExpression_;
+ },
+
+ evaluate(context) {
+ if (context.ancestors.length > 0) return false;
+ if (!this.subExpression) return true;
+ return this.subExpression.evaluate(context);
+ }
+ };
+ tr.c.ScriptingObjectRegistry.register(
+ function(subExpression) {
+ return new FilterIsTopLevel(subExpression);
+ },
+ {
+ name: 'isTopLevel'
+ }
+ );
+ return {
+ FilterIsTopLevel,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_not.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_not.html
new file mode 100644
index 00000000000..d3014376113
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/filter_not.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/extras/tquery/filter.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function FilterNot(subExpression) {
+ tr.e.tquery.Filter.call(this);
+ this.subExpression = subExpression;
+ }
+
+ FilterNot.prototype = {
+ __proto__: tr.e.tquery.Filter.prototype,
+
+ set subExpression(expr) {
+ this.subExpression_ = tr.e.tquery.Filter.normalizeFilterExpression(expr);
+ },
+
+ get subExpression() {
+ return this.subExpression_;
+ },
+
+ evaluate(context) {
+ return !this.subExpression.evaluate(context);
+ }
+ };
+ tr.c.ScriptingObjectRegistry.register(
+ function() {
+ const exprs = Array.prototype.slice.call(arguments);
+ if (exprs.length !== 1) {
+ throw new Error('not() must have exactly one subexpression');
+ }
+ return new FilterNot(exprs[0]);
+ },
+ {
+ name: 'not'
+ }
+ );
+ return {
+ FilterNot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/tquery.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/tquery.html
new file mode 100644
index 00000000000..c4b5d19e995
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/tquery.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/core/scripting_object.html">
+<link rel="import" href="/tracing/extras/tquery/context.html">
+<link rel="import" href="/tracing/extras/tquery/filter_all_of.html">
+<link rel="import" href="/tracing/extras/tquery/filter_any_of.html">
+<link rel="import" href="/tracing/extras/tquery/filter_has_ancestor.html">
+<link rel="import" href="/tracing/extras/tquery/filter_has_duration.html">
+<link rel="import" href="/tracing/extras/tquery/filter_has_title.html">
+<link rel="import" href="/tracing/extras/tquery/filter_is_top_level.html">
+<link rel="import" href="/tracing/extras/tquery/filter_not.html">
+<link rel="import" href="/tracing/model/event_set.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.tquery', function() {
+ function addEventTreeToSelection(selection, event) {
+ selection.push(event);
+ if (!event.subSlices) return;
+ event.subSlices.forEach(
+ addEventTreeToSelection.bind(undefined, selection));
+ }
+
+ function TQuery(model) {
+ tr.c.ScriptingObject.call(this);
+
+ this.model_ = model;
+ this.parent_ = undefined;
+ this.filterExpression_ = undefined;
+ // Memoized filtering result.
+ this.selection_ = undefined;
+ }
+
+ TQuery.prototype = {
+ __proto__: tr.c.ScriptingObject.prototype,
+
+ onModelChanged(model) {
+ this.model_ = model;
+ this.selection_ = undefined;
+ },
+
+ get brushingStateController() {
+ return this.brushingStateController_;
+ },
+
+ // Append a new filter expression to this query and return a query node
+ // that represents the result.
+ filter(filterExpression) {
+ const result = new TQuery(this.model_);
+ result.parent_ = this;
+ result.filterExpression_ =
+ tr.e.tquery.Filter.normalizeFilterExpression(filterExpression);
+ return result;
+ },
+
+ // Creates a graph of {Task} objects which will compute the selections for
+ // this filter object and all of its parents. The return value is an object
+ // with the following fields:
+ // - rootTask: {Task} which should be executed to kick off processing for
+ // the entire task graph.
+ // - lastTask: The final {Task} of the graph. Can be used by the caller to
+ // enqueue additional processing at the end.
+ // - lastNode: The last filter object in the task. It's selection property
+ // will contain the filtering result once |finalTask|
+ // completes.
+ createFilterTaskGraph_() {
+ // List of nodes in order from the current one to the root.
+ const nodes = [this];
+ while (nodes[nodes.length - 1].parent_) {
+ nodes.push(nodes[nodes.length - 1].parent_);
+ }
+
+ const rootTask = new tr.b.Task();
+ let lastTask = rootTask;
+ let node;
+ for (let i = nodes.length - 1; i >= 0; i--) {
+ node = nodes[i];
+ // Reuse any memoized result.
+ if (node.selection_ !== undefined) continue;
+ node.selection_ = new tr.model.EventSet();
+ if (node.parent_ === undefined) {
+ // If this is the root, start by collecting all objects from the
+ // model.
+ lastTask = lastTask.after(
+ this.selectEverythingAsTask_(node.selection_));
+ } else {
+ // Otherwise execute the filter expression for this node and fill
+ // in its selection.
+ const prevNode = nodes[i + 1];
+ lastTask = this.createFilterTaskForNode_(lastTask, node, prevNode);
+ }
+ }
+ return {rootTask, lastTask, lastNode: node};
+ },
+
+ createFilterTaskForNode_(lastTask, node, prevNode) {
+ return lastTask.after(function() {
+ // TODO(skyostil): Break into subtasks.
+ node.evaluateFilterExpression_(
+ prevNode.selection_, node.selection_);
+ }, this);
+ },
+
+ // Applies the result of a filter expression for a given event and all
+ // of its subslices and adds the matching events to an output selection.
+ evaluateFilterExpression_(inputSelection, outputSelection) {
+ const seenEvents = {};
+ inputSelection.forEach(function(event) {
+ const context = new tr.e.tquery.Context();
+ context.event = event;
+ this.evaluateFilterExpressionForEvent_(
+ context, inputSelection, outputSelection, seenEvents);
+ }.bind(this));
+ },
+
+ evaluateFilterExpressionForEvent_(
+ context, inputSelection, outputSelection, seenEvents) {
+ const event = context.event;
+ if (inputSelection.contains(event) && !seenEvents[event.guid]) {
+ seenEvents[event.guid] = true;
+ if (!this.filterExpression_ ||
+ this.filterExpression_.evaluate(context)) {
+ outputSelection.push(event);
+ }
+ }
+ if (!event.subSlices) return;
+ context = context.push(event);
+ for (let i = 0; i < event.subSlices.length; i++) {
+ context.event = event.subSlices[i];
+ this.evaluateFilterExpressionForEvent_(
+ context, inputSelection, outputSelection, seenEvents);
+ }
+ },
+
+ // Returns a task that fills the given selection with everything in the
+ // model.
+ selectEverythingAsTask_(selection) {
+ const filterTask = new tr.b.Task();
+ for (const container of this.model_.getDescendantEventContainers()) {
+ filterTask.subTask(() => {
+ for (const event of container.childEvents()) {
+ addEventTreeToSelection(selection, event);
+ }
+ }, this);
+ }
+ return filterTask;
+ },
+
+ // Returns a promise which will resolve into a {EventSet} representing the
+ // result of this query.
+ ready() {
+ return new Promise(function(resolve, reject) {
+ const graph = this.createFilterTaskGraph_();
+ graph.lastTask = graph.lastTask.after(function() {
+ resolve(this.selection_);
+ }, this);
+ tr.b.Task.RunWhenIdle(graph.rootTask);
+ }.bind(this));
+ },
+
+ get selection() {
+ if (this.selection_ === undefined) {
+ const graph = this.createFilterTaskGraph_();
+ tr.b.Task.RunSynchronously(graph.rootTask);
+ }
+ return this.selection_;
+ }
+ };
+ tr.c.ScriptingObjectRegistry.register(
+ new TQuery(),
+ {
+ name: '$t'
+ }
+ );
+
+ return {
+ TQuery,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/tquery/tquery_test.html b/chromium/third_party/catapult/tracing/tracing/extras/tquery/tquery_test.html
new file mode 100644
index 00000000000..1ecd7e6255a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/tquery/tquery_test.html
@@ -0,0 +1,247 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/tquery/tquery.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createTestModel(sliceCount) {
+ const slices = [];
+ for (let i = 0; i < sliceCount; i++) {
+ slices.push(tr.c.TestUtils.newSliceEx({start: 1, duration: 2}));
+ }
+ return createTestModelWithSlices(slices);
+ }
+
+ function createTestModelWithSlices(slices) {
+ const model = new tr.Model();
+ const cpu = model.kernel.getOrCreateCpu(1);
+ for (let i = 0; i < slices.length; i++) {
+ cpu.slices.push(slices[i]);
+ }
+ return model;
+ }
+
+ function getScriptObject(name) {
+ const typeInfos = tr.c.ScriptingObjectRegistry.getAllRegisteredTypeInfos();
+ for (let i = 0; i < typeInfos.length; i++) {
+ if (typeInfos[i].metadata.name === name) {
+ return typeInfos[i].constructor;
+ }
+ }
+ }
+
+ test('tqueryAsyncSelection', function() {
+ const model = createTestModel(3);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ return tquery.ready().then(function(selection) {
+ assert.strictEqual(selection.length, 3);
+ });
+ });
+
+ test('tquerySyncSelection', function() {
+ let model = createTestModel(3);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ assert.strictEqual(tquery.selection.length, 3);
+
+ // Selection should get reset when the model changes.
+ model = createTestModel(5);
+ tquery.onModelChanged(model);
+ assert.strictEqual(tquery.selection.length, 5);
+ });
+
+ test('tqueryPassThroughFiltering', function() {
+ const model = new createTestModel(3);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ const result = tquery.filter().filter().selection;
+ assert.strictEqual(result.length, 3);
+ });
+
+ test('tqueryFilterHasTitle', function() {
+ const hasTitle = getScriptObject('hasTitle');
+ const model = createTestModelWithSlices([
+ {guid: 1, title: 'a'},
+ {guid: 2, title: 'b'},
+ {guid: 3, title: 'c'}
+ ]);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ let result = tquery.filter(hasTitle('a')).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 1);
+
+ result = tquery.filter('b').selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 2);
+
+ result = tquery.filter(/^c$/).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 3);
+ });
+
+ test('tqueryFilterHasAncestor', function() {
+ const hasAncestor = getScriptObject('hasAncestor');
+ const model = createTestModelWithSlices([
+ {guid: 1, title: 'a'},
+ {guid: 2, title: 'b', subSlices: [{guid: 4}]},
+ {guid: 3, title: 'c'}
+ ]);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ let result = tquery.filter(hasAncestor('b')).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 4);
+
+ result = tquery.filter(hasAncestor()).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 4);
+
+ result = tquery.filter(hasAncestor('a')).selection;
+ assert.strictEqual(result.length, 0);
+ });
+
+ test('tqueryFilterAllOf', function() {
+ const allOf = getScriptObject('allOf');
+ const model = createTestModelWithSlices([
+ {guid: 1, title: 'a1'},
+ {guid: 2, title: 'b1'},
+ {guid: 3, title: 'c1'}
+ ]);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ let result = tquery.filter(allOf('a1')).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 1);
+
+ result = tquery.filter(allOf('a1', /1/)).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 1);
+
+ result = tquery.filter(allOf()).selection;
+ assert.strictEqual(result.length, 3);
+ });
+
+ test('tqueryFilterAnyOf', function() {
+ const anyOf = getScriptObject('anyOf');
+ const model = createTestModelWithSlices([
+ {guid: 1, title: 'a'},
+ {guid: 2, title: 'b'},
+ {guid: 3, title: 'c'}
+ ]);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ let result = tquery.filter(anyOf('a', 'b')).selection;
+ assert.strictEqual(result.length, 2);
+ let nextGuid = 1;
+ for (const event of result) {
+ assert.strictEqual(event.guid, nextGuid++);
+ }
+
+ result = tquery.filter(anyOf('not there', 'a')).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 1);
+
+ result = tquery.filter(anyOf()).selection;
+ assert.strictEqual(result.length, 3);
+ });
+
+ test('tqueryFilterIsTopLevel', function() {
+ const isTopLevel = getScriptObject('isTopLevel');
+ const model = createTestModelWithSlices([
+ {guid: 1, title: 'a'},
+ {guid: 2, title: 'b', subSlices: [{guid: 4}]},
+ {guid: 3, title: 'c'}
+ ]);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ let result = tquery.filter(isTopLevel()).selection;
+ assert.strictEqual(result.length, 3);
+ let nextGuid = 1;
+ for (const event of result) {
+ assert.strictEqual(event.guid, nextGuid++);
+ }
+
+ result = tquery.filter(isTopLevel('a')).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 1);
+ });
+
+ test('tqueryFilterHasDuration', function() {
+ const hasDuration = getScriptObject('hasDuration');
+ const model = createTestModelWithSlices([
+ {guid: 1, title: 'a', duration: 1},
+ {guid: 2, title: 'b', duration: 2},
+ {guid: 3, title: 'c', duration: 3},
+ {guid: 4, title: 'no duration'}
+ ]);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ let result = tquery.filter(hasDuration(1.5, 2.5)).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 2);
+
+ result = tquery.filter(hasDuration(3, Infinity)).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 3);
+
+ result = tquery.filter(hasDuration(-1, 0)).selection;
+ assert.strictEqual(result.length, 0);
+
+ result = tquery.filter(hasDuration(function(d) {
+ return d > 2;
+ })).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 3);
+ });
+
+ test('tqueryFilterNot', function() {
+ const not = getScriptObject('not');
+ const model = createTestModelWithSlices([
+ {guid: 1, title: 'a'},
+ {guid: 2, title: 'b'},
+ {guid: 3, title: 'c'}
+ ]);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ const result = tquery.filter(not(/a/)).selection;
+ assert.strictEqual(result.length, 2);
+ let nextGuid = 2;
+ for (const event of result) {
+ assert.strictEqual(event.guid, nextGuid++);
+ }
+
+ // Test a not() without any subexpressions.
+ assert.throws(function() { not(); });
+
+ // Test a not() with too many subexpressions.
+ assert.throws(function() { not(/a/, /b/); });
+ });
+
+ test('tqueryFilterNoneOf', function() {
+ const noneOf = getScriptObject('noneOf');
+ const model = createTestModelWithSlices([
+ {guid: 1, title: 'a'},
+ {guid: 2, title: 'b'},
+ {guid: 3, title: 'c'}
+ ]);
+ const tquery = new tr.e.tquery.TQuery(model);
+
+ const result = tquery.filter(noneOf(/a/, /b/)).selection;
+ assert.strictEqual(result.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(result).guid, 3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8/ic_stats_entry.html b/chromium/third_party/catapult/tracing/tracing/extras/v8/ic_stats_entry.html
new file mode 100644
index 00000000000..6717b80302d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8/ic_stats_entry.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/v8/v8_ic_stats_thread_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.v8', function() {
+ const IC_STATS_PROPERTIES = [
+ 'type', 'category', 'scriptName', 'filePosition', 'state', 'isNative',
+ 'map', 'propertiesMode', 'numberOfOwnProperties', 'instanceType'
+ ];
+
+ class ICStatsEntry {
+ constructor(obj) {
+ this.type_ = obj.type;
+ if (this.type_.includes('Store')) {
+ this.category_ = 'Store';
+ } else if (this.type_.includes('Load')) {
+ this.category_ = 'Load';
+ }
+ this.state_ = obj.state;
+ if (obj.functionName) {
+ this.functionName_ = obj.optimized ? '*' : '~';
+ this.functionName_ += obj.functionName.length === 0 ?
+ '(anonymous function)' : obj.functionName;
+ }
+ this.offset_ = obj.offset;
+ this.scriptName_ = obj.scriptName ? obj.scriptName : 'unknown';
+ this.isNative_ = obj.scriptName && obj.scriptName.includes('native');
+ this.lineNum_ = obj.lineNum ? obj.lineNum : 'unknown';
+ this.filePosition_ = this.scriptName_ + ':' + this.lineNum_;
+ if (this.functionName_) {
+ this.filePosition_ += ' ' + this.functionName_ + '+' + this.offset_;
+ }
+ this.constructor_ = obj.constructor ? false : true;
+ this.map_ = obj.map;
+ if (this.map_) {
+ this.propertiesMode_ = obj.dict === 1 ? 'slow' : 'fast';
+ } else {
+ this.propertiesMode_ = 'unknown';
+ }
+ this.numberOfOwnProperties_ = obj.own;
+ this.instanceType_ = obj.instanceType;
+ this.key_ = obj.key;
+ }
+
+ get type() {
+ return this.type_;
+ }
+
+ get category() {
+ return this.category_;
+ }
+
+ get state() {
+ return this.state_;
+ }
+
+ get functionName() {
+ return this.functionName_;
+ }
+
+ get offset() {
+ return this.offset_;
+ }
+
+ get scriptName() {
+ return this.scriptName_;
+ }
+
+ get isNative() {
+ return this.isNative_;
+ }
+
+ get lineNumber() {
+ return this.lineNum_;
+ }
+
+ get isConstructor() {
+ return this.constructor_;
+ }
+
+ get map() {
+ return this.map_;
+ }
+
+ get propertiesMode() {
+ return this.propertiesMode_;
+ }
+
+ get numberOfOwnProperties() {
+ return this.numberOfOwnProperties_;
+ }
+
+ get instanceType() {
+ return this.instanceType_;
+ }
+
+ get filePosition() {
+ return this.filePosition_;
+ }
+ }
+
+ class ICStatsEntryGroup {
+ constructor(property, key) {
+ this.property_ = property;
+ this.key_ = key;
+ this.percentage_ = 0;
+ this.entries_ = [];
+ // This is map used to cache all sub grouping result
+ this.subGroup_ = undefined;
+ }
+
+ static groupBy(groups, entries, property) {
+ for (const entry of entries) {
+ const key = entry[property];
+ let group = groups.get(key);
+ if (!group) {
+ group = new ICStatsEntryGroup(property, key);
+ groups.set(key, group);
+ }
+ group.add(entry);
+ }
+ for (const group of groups.values()) {
+ group.percentage = group.length / entries.length;
+ }
+ }
+
+ add(entry) {
+ this.entries_.push(entry);
+ }
+
+ createSubGroup() {
+ if (this.subGroup_) return this.subGroup_;
+ this.subGroup_ = new Map();
+ for (const property of IC_STATS_PROPERTIES) {
+ if (property === this.property_) continue;
+ const groups = new Map();
+ this.subGroup_.set(property, groups);
+ ICStatsEntryGroup.groupBy(groups, this.entries_, property);
+ }
+ return this.subGroup_;
+ }
+
+ get entries() {
+ return this.entries_;
+ }
+
+ get key() {
+ return this.key_;
+ }
+
+ get length() {
+ return this.entries_.length;
+ }
+
+ get percentage() {
+ return this.percentage_;
+ }
+
+ set percentage(value) {
+ this.percentage_ = value;
+ }
+ }
+
+ class ICStatsCollection {
+ constructor() {
+ this.entries_ = [];
+ // Used to cache property grouping result.
+ this.groupedEntries_ = new Map();
+ }
+
+ add(entry) {
+ this.entries_.push(entry);
+ }
+
+ groupBy(property) {
+ if (this.groupedEntries_.has(property)) {
+ return Array.from(this.groupedEntries_.get(property).values());
+ }
+ const groups = new Map();
+ this.groupedEntries_.set(property, groups);
+ ICStatsEntryGroup.groupBy(groups, this.entries_, property);
+ return Array.from(groups.values());
+ }
+
+ get entries() {
+ return this.entries_;
+ }
+
+ get length() {
+ return this.entries_.length;
+ }
+ }
+
+ return {
+ IC_STATS_PROPERTIES,
+ ICStatsEntry,
+ ICStatsEntryGroup,
+ ICStatsCollection,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8/ic_stats_entry_test.html b/chromium/third_party/catapult/tracing/tracing/extras/v8/ic_stats_entry_test.html
new file mode 100644
index 00000000000..1cb0f851552
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8/ic_stats_entry_test.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/v8/ic_stats_entry.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const obj1 = {
+ type: 'StoreIC',
+ functionName: 'f',
+ offset: 10,
+ scriptName: 'a.js',
+ lineNum: 1,
+ state: '(0->.)',
+ map: '0x000000000A',
+ dict: 0,
+ own: 3
+ };
+ const obj2 = {
+ type: 'LoadIC',
+ functionName: 'saveBuiltin',
+ offset: 11,
+ scriptName: 'extensions::SafeBuiltins',
+ lineNum: 2,
+ state: '(0->.)',
+ map: '0x00000000AA',
+ dict: 1,
+ own: 0
+ };
+ const obj3 = {
+ type: 'CompareIC',
+ functionName: 'InnerArrayForEach',
+ offset: 12,
+ scriptName: 'native array.js',
+ lineNum: 3,
+ state: '((UNINITIALIZED+UNINITIALIZED=UNINITIALIZED)->(SMI+SMI=SMI))#LT',
+ map: '0x0000000AAA'
+ };
+ const obj4 = {
+ type: 'StoreIC',
+ functionName: 'bar',
+ offset: 13,
+ scriptName: 'a.js',
+ lineNum: 4,
+ state: '(0->.)',
+ map: '0x000000AAAA',
+ dict: 1,
+ own: 7
+ };
+
+ test('ICStatsEntry', function() {
+ const entry1 = new tr.e.v8.ICStatsEntry(obj1);
+ assert.strictEqual(entry1.type, 'StoreIC');
+ assert.strictEqual(entry1.category, 'Store');
+ assert.strictEqual(entry1.state, '(0->.)');
+ assert.strictEqual(entry1.filePosition, 'a.js:1 ~f+10');
+ assert.strictEqual(entry1.isNative, false);
+ assert.strictEqual(entry1.propertiesMode, 'fast');
+ assert.strictEqual(entry1.numberOfOwnProperties, 3);
+
+ const entry2 = new tr.e.v8.ICStatsEntry(obj4);
+ assert.strictEqual(entry2.type, 'StoreIC');
+ assert.strictEqual(entry2.category, 'Store');
+ assert.strictEqual(entry2.state, '(0->.)');
+ assert.strictEqual(entry2.filePosition, 'a.js:4 ~bar+13');
+ assert.strictEqual(entry2.isNative, false);
+ assert.strictEqual(entry2.propertiesMode, 'slow');
+ assert.strictEqual(entry2.numberOfOwnProperties, 7);
+
+ const entry3 = new tr.e.v8.ICStatsEntry(obj3);
+ assert.strictEqual(entry3.isNative, true);
+ });
+
+ test('ICStatsEntryCollection', function() {
+ const entryCollection = new tr.e.v8.ICStatsCollection();
+ entryCollection.add(new tr.e.v8.ICStatsEntry(obj1));
+ entryCollection.add(new tr.e.v8.ICStatsEntry(obj2));
+ entryCollection.add(new tr.e.v8.ICStatsEntry(obj3));
+ entryCollection.add(new tr.e.v8.ICStatsEntry(obj4));
+
+ assert.strictEqual(entryCollection.length, 4);
+ });
+
+ test('ICStatsEntryGroup', function() {
+ const entryCollection = new tr.e.v8.ICStatsCollection();
+ entryCollection.add(new tr.e.v8.ICStatsEntry(obj1));
+ entryCollection.add(new tr.e.v8.ICStatsEntry(obj2));
+ entryCollection.add(new tr.e.v8.ICStatsEntry(obj3));
+ entryCollection.add(new tr.e.v8.ICStatsEntry(obj4));
+
+ const entryGroups = entryCollection.groupBy('type');
+ assert.strictEqual(entryGroups[0].length, 2);
+ assert.strictEqual(entryGroups[0].key, 'StoreIC');
+ assert.strictEqual(entryGroups[1].key, 'LoadIC');
+ assert.strictEqual(entryGroups[2].key, 'CompareIC');
+
+ const subGroups = entryGroups[0].createSubGroup();
+ assert.strictEqual(subGroups.size, 9);
+ const filePositionGroup = subGroups.get('filePosition');
+ assert.deepEqual(Array.from(filePositionGroup.keys()), [
+ 'a.js:1 ~f+10', 'a.js:4 ~bar+13'
+ ]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8/runtime_stats_entry.html b/chromium/third_party/catapult/tracing/tracing/extras/v8/runtime_stats_entry.html
new file mode 100644
index 00000000000..9895f33096f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8/runtime_stats_entry.html
@@ -0,0 +1,221 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.v8', function() {
+ class RuntimeStatsEntry {
+ /**
+ * @param time is in microseconds.
+ */
+ constructor(name, count, time) {
+ this.name_ = name;
+ this.count_ = count;
+ this.time_ = time;
+ }
+
+ get name() {
+ return this.name_;
+ }
+
+ get count() {
+ return this.count_;
+ }
+
+ get time() {
+ return this.time_;
+ }
+
+ addSample(count, time) {
+ this.count_ += count;
+ this.time_ += time;
+ }
+ }
+
+ class RuntimeStatsGroup extends RuntimeStatsEntry {
+ constructor(name, matchRegex) {
+ super(name, 0, 0);
+ this.regex_ = matchRegex;
+ this.entries_ = new Map();
+ }
+
+ match(name) {
+ return this.regex_ && name.match(this.regex_);
+ }
+
+ add(entry) {
+ const value = this.entries_.get(entry.name);
+ if (value !== undefined) {
+ value.addSample(entry.count, entry.time);
+ } else {
+ this.entries_.set(entry.name, entry);
+ }
+ this.count_ += entry.count;
+ this.time_ += entry.time;
+ }
+
+ get values() {
+ return Array.from(this.entries_.values());
+ }
+ }
+
+ class RuntimeStatsGroupCollection {
+ constructor() {
+ this.blink_cpp_group_ =
+ new RuntimeStatsGroup('Blink C++', /.*Callback.*/);
+ this.api_group_ = new RuntimeStatsGroup('API', /.*API.*/);
+
+ this.groups_ = [
+ new RuntimeStatsGroup('Total'),
+ new RuntimeStatsGroup('IC', /.*IC_.*/),
+ new RuntimeStatsGroup('Optimize-Background',
+ /(.*OptimizeConcurrent.*)|RecompileConcurrent.*/),
+ new RuntimeStatsGroup('Optimize',
+ /StackGuard|.*Optimize.*|.*Deoptimize.*|Recompile.*/),
+ new RuntimeStatsGroup('Compile-Background',
+ /(.*CompileBackground.*)/),
+ new RuntimeStatsGroup('Compile', /(^Compile.*)|(.*_Compile.*)/),
+ new RuntimeStatsGroup('Parse-Background', /.*ParseBackground.*/),
+ new RuntimeStatsGroup('Parse', /.*Parse.*/),
+ this.blink_cpp_group_,
+ this.api_group_,
+ new RuntimeStatsGroup('GC-Background-Marking',
+ /.*GC.MC.BACKGROUND.*MARKING.*/),
+ new RuntimeStatsGroup('GC-Background-Sweeping',
+ /.*GC.MC.BACKGROUND.*SWEEPING.*/),
+ new RuntimeStatsGroup('GC-Background-Scavenger',
+ /.*GC.SCAVENGER.BACKGROUND.*/),
+ new RuntimeStatsGroup('GC-Background-MinorMC',
+ /.*GC.MINOR_MC.BACKGROUND.*/),
+ new RuntimeStatsGroup('GC-Background-MajorMC',
+ /.*GC.MC.BACKGROUND.*/),
+ new RuntimeStatsGroup('GC-Background-Other', /.*GC.*BACKGROUND.*/),
+ new RuntimeStatsGroup('GC', /GC|AllocateInTargetSpace/),
+ new RuntimeStatsGroup('JavaScript', /JS_Execution/),
+ new RuntimeStatsGroup('V8 C++', /.*/)
+ ];
+
+ this.blink_group_collection_ = null;
+ }
+
+ addSlices(slices) {
+ const blinkEntries = [];
+ for (const slice of slices) {
+ if (!(slice instanceof tr.e.v8.V8ThreadSlice)) return;
+ let runtimeCallStats;
+ try {
+ runtimeCallStats = JSON.parse(slice.runtimeCallStats);
+ } catch (e) {
+ runtimeCallStats = slice.runtimeCallStats;
+ }
+ if (runtimeCallStats === undefined) continue;
+ for (const [name, stat] of Object.entries(runtimeCallStats)) {
+ // Blink RCS stats go to a separate table
+ if (name.match(/Blink_.*/)) {
+ // This counter is used to avoid counting time spent in V8 as time
+ // spent doing Blink C++, and interferes with total and percentage
+ // calculations, so we skip this counter.
+ if (name === 'Blink_V8') continue;
+ const entry = new RuntimeStatsEntry(name, stat[0], stat[1]);
+ blinkEntries.push(entry);
+ continue;
+ }
+
+ // Skip the 'Total' group
+ for (let i = 1; i < this.groups_.length; ++i) {
+ if (this.groups_[i].match(name)) {
+ if (stat.length !== 2) break;
+ const entry = new RuntimeStatsEntry(name, stat[0], stat[1]);
+ this.groups_[0].addSample(stat[0], stat[1]);
+ this.groups_[i].add(entry);
+ break;
+ }
+ }
+ }
+ }
+
+ this.blink_group_collection_ =
+ new BlinkRuntimeStatsGroupCollection(blinkEntries);
+ }
+
+ get totalTime() {
+ return this.groups_[0].time;
+ }
+
+ get totalCount() {
+ return this.groups_[0].count;
+ }
+
+ get runtimeGroups() {
+ return this.groups_;
+ }
+
+ get blinkRCSGroupCollection() {
+ return this.blink_group_collection_;
+ }
+
+ get blinkCppTotalTime() {
+ // Include API time because Blink RCS times also include V8 API times
+ return this.blink_cpp_group_.time + this.api_group_.time;
+ }
+ }
+
+ class BlinkRuntimeStatsGroupCollection {
+ constructor(entries) {
+ this.groups_ = [
+ new RuntimeStatsGroup('Blink_Bindings', /^Blink_Bindings_(.*)/),
+ new RuntimeStatsGroup('Blink_GC', /^Blink_GC_(.*)/),
+ new RuntimeStatsGroup('Blink_Layout', /^Blink_Layout_(.*)/),
+ new RuntimeStatsGroup('Blink_Parsing', /^Blink_Parsing_(.*)/),
+ new RuntimeStatsGroup('Blink_Style', /^Blink_Style_(.*)/),
+ new RuntimeStatsGroup('Blink_Callbacks', /^Blink_(.*)/)
+ ];
+ this.total_group_ = new RuntimeStatsGroup('Blink_Total', /.*/);
+
+ for (const entry of entries) {
+ for (const group of this.groups_) {
+ if (group.match(entry.name)) {
+ // Strip out category prefix
+ const newEntry = new RuntimeStatsEntry(
+ 'Blink_' + group.match(entry.name)[1], entry.count, entry.time);
+ group.add(newEntry);
+ this.total_group_.addSample(entry.count, entry.time);
+ break;
+ }
+ }
+ }
+ }
+
+ get runtimeGroups() {
+ return this.groups_.concat(this.total_group_);
+ }
+
+ get values() {
+ return this.groups_.reduce(
+ (values, group) => values.concat(group.values), []);
+ }
+
+ get totalTime() {
+ return this.total_group_.time;
+ }
+
+ get totalCount() {
+ return this.total_group_.count;
+ }
+ }
+
+ return {
+ BlinkRuntimeStatsGroupCollection,
+ RuntimeStatsEntry,
+ RuntimeStatsGroup,
+ RuntimeStatsGroupCollection,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8/runtime_stats_entry_test.html b/chromium/third_party/catapult/tracing/tracing/extras/v8/runtime_stats_entry_test.html
new file mode 100644
index 00000000000..aa5aa39ee55
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8/runtime_stats_entry_test.html
@@ -0,0 +1,322 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/v8/runtime_stats_entry.html">
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('RuntimeStatsEntry', function() {
+ const entry = new tr.e.v8.RuntimeStatsEntry('IC_Entry', 5, 1234);
+ assert.strictEqual(entry.name, 'IC_Entry');
+ assert.strictEqual(entry.count, 5);
+ assert.strictEqual(entry.time, 1234);
+
+ entry.addSample(37, 8766);
+ assert.strictEqual(entry.name, 'IC_Entry');
+ assert.strictEqual(entry.count, 42);
+ assert.strictEqual(entry.time, 10000);
+
+ entry.addSample(58, 1);
+ assert.strictEqual(entry.name, 'IC_Entry');
+ assert.strictEqual(entry.count, 100);
+ assert.strictEqual(entry.time, 10001);
+ });
+
+ test('RuntimeStatsGroup', function() {
+ const group = new tr.e.v8.RuntimeStatsGroup('IC', /.*IC_.*/);
+ assert.notEqual(group.match('IC_Entry'), undefined);
+ assert.notEqual(group.match('CallbackIC_Entry'), undefined);
+ assert.strictEqual(group.match('Callback_Entry'), null);
+
+ const entry1a = new tr.e.v8.RuntimeStatsEntry('IC_Entry', 5, 1234);
+ group.add(entry1a);
+ assert.deepEqual(group.values, [entry1a]);
+ const entry2 = new tr.e.v8.RuntimeStatsEntry('IC_Entry2', 2, 2048);
+ group.add(entry2);
+ assert.deepEqual(group.values, [entry1a, entry2]);
+ const entry1b = new tr.e.v8.RuntimeStatsEntry('IC_Entry', 37, 8766);
+ group.add(entry1b);
+ const entry1sum = new tr.e.v8.RuntimeStatsEntry('IC_Entry', 42, 10000);
+ assert.deepEqual(group.values, [entry1sum, entry2]);
+ });
+
+ function checkRuntimeGroup_(group, name, count, time) {
+ assert.strictEqual(group.name, name);
+ assert.strictEqual(group.count, count);
+ assert.strictEqual(group.time, time);
+ }
+
+ test('RuntimeStatsGroupCollection', function() {
+ const slices = [];
+ slices.push(tr.c.TestUtils.newSliceEx({
+ title: 'V8.Execute',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99],
+ RecompileConcurrent: [10, 100],
+ }
+ }
+ }));
+ slices.push(tr.c.TestUtils.newSliceEx({
+ title: 'V8.newInstance',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [2, 22],
+ HandleApiCall: [3, 33],
+ CompileFullCode: [4, 44],
+ LoadIC_Miss: [5, 55],
+ ParseLazy: [6, 66],
+ OptimizeCode: [7, 77],
+ FunctionCallback: [8, 88],
+ AllocateInTargetSpace: [9, 99],
+ API_Object_Get: [1, 11],
+ ParseBackgroundFunctionLiteral: [2, 22],
+ CompileBackgroundIgnition: [3, 33],
+ RecompileConcurrent: [5, 50],
+ }
+ }
+ }));
+
+ const groupCollection = new tr.e.v8.RuntimeStatsGroupCollection();
+ groupCollection.addSlices(slices);
+ assert.strictEqual(groupCollection.totalTime, 1195);
+
+ const groups = groupCollection.runtimeGroups;
+ assert.deepEqual(groups.length, 19);
+ checkRuntimeGroup_(groups[0], 'Total', 110, 1195);
+ checkRuntimeGroup_(groups[1], 'IC', 9, 99);
+ checkRuntimeGroup_(groups[2], 'Optimize-Background', 15, 150);
+ checkRuntimeGroup_(groups[3], 'Optimize', 13, 143);
+ checkRuntimeGroup_(groups[4], 'Compile-Background', 3, 33);
+ checkRuntimeGroup_(groups[5], 'Compile', 7, 77);
+ checkRuntimeGroup_(groups[6], 'Parse-Background', 2, 22);
+ checkRuntimeGroup_(groups[7], 'Parse', 11, 121);
+ checkRuntimeGroup_(groups[8], 'Blink C++', 15, 165);
+ checkRuntimeGroup_(groups[9], 'API', 10, 110);
+ checkRuntimeGroup_(groups[10], 'GC-Background-Marking', 0, 0);
+ checkRuntimeGroup_(groups[11], 'GC-Background-Sweeping', 0, 0);
+ checkRuntimeGroup_(groups[12], 'GC-Background-Scavenger', 0, 0);
+ checkRuntimeGroup_(groups[13], 'GC-Background-MinorMC', 0, 0);
+ checkRuntimeGroup_(groups[14], 'GC-Background-MajorMC', 0, 0);
+ checkRuntimeGroup_(groups[15], 'GC-Background-Other', 0, 0);
+ checkRuntimeGroup_(groups[16], 'GC', 17, 187);
+ checkRuntimeGroup_(groups[17], 'JavaScript', 3, 33);
+ checkRuntimeGroup_(groups[18], 'V8 C++', 5, 55);
+ });
+
+ test('BlinkRuntimeStatsGroupCollection', function() {
+ const slices = [];
+ slices.push(tr.c.TestUtils.newSliceEx({
+ title: 'V8.Execute',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99],
+ RecompileConcurrent: [10, 100],
+ }
+ }
+ }));
+ slices.push(tr.c.TestUtils.newSliceEx({
+ title: 'V8.newInstance',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [2, 22],
+ HandleApiCall: [3, 33],
+ CompileFullCode: [4, 44],
+ LoadIC_Miss: [5, 55],
+ ParseLazy: [6, 66],
+ OptimizeCode: [7, 77],
+ FunctionCallback: [8, 88],
+ AllocateInTargetSpace: [9, 99],
+ API_Object_Get: [1, 11],
+ ParseBackgroundFunctionLiteral: [2, 22],
+ CompileBackgroundIgnition: [3, 33],
+ RecompileConcurrent: [5, 50],
+ }
+ }
+ }));
+ slices.push(tr.c.TestUtils.newSliceEx({
+ title: 'BlinkRuntimeCallStats',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'disabled-by-default-v8.runtime_stats',
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [10, 25],
+ Blink_GC_CollectGarbage: [10, 20],
+ Blink_Style_UpdateStyle: [15, 30],
+ Blink_Parsing_ParseHTML: [5, 60],
+ Blink_WindowSetTimeout: [10, 15],
+ Blink_V8: [5, 100],
+ }
+ }
+ }));
+ slices.push(tr.c.TestUtils.newSliceEx({
+ title: 'BlinkRuntimeCallStats',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'disabled-by-default-v8.runtime_stats',
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [5, 10],
+ Blink_GC_CollectGarbage: [20, 50],
+ Blink_Parsing_ParseHTML: [10, 60],
+ Blink_Bindings_CreateWrapper: [100, 5],
+ Blink_NodeAppendChild: [20, 20],
+ Blink_V8: [2, 50],
+ }
+ }
+ }));
+
+ const groupCollection = new tr.e.v8.RuntimeStatsGroupCollection();
+ groupCollection.addSlices(slices);
+ assert.strictEqual(groupCollection.totalTime, 1195);
+
+ const groups = groupCollection.runtimeGroups;
+ assert.deepEqual(groups.length, 19);
+ checkRuntimeGroup_(groups[0], 'Total', 110, 1195);
+ checkRuntimeGroup_(groups[1], 'IC', 9, 99);
+ checkRuntimeGroup_(groups[2], 'Optimize-Background', 15, 150);
+ checkRuntimeGroup_(groups[3], 'Optimize', 13, 143);
+ checkRuntimeGroup_(groups[4], 'Compile-Background', 3, 33);
+ checkRuntimeGroup_(groups[5], 'Compile', 7, 77);
+ checkRuntimeGroup_(groups[6], 'Parse-Background', 2, 22);
+ checkRuntimeGroup_(groups[7], 'Parse', 11, 121);
+ checkRuntimeGroup_(groups[8], 'Blink C++', 15, 165);
+ checkRuntimeGroup_(groups[9], 'API', 10, 110);
+ checkRuntimeGroup_(groups[10], 'GC-Background-Marking', 0, 0);
+ checkRuntimeGroup_(groups[11], 'GC-Background-Sweeping', 0, 0);
+ checkRuntimeGroup_(groups[12], 'GC-Background-Scavenger', 0, 0);
+ checkRuntimeGroup_(groups[13], 'GC-Background-MinorMC', 0, 0);
+ checkRuntimeGroup_(groups[14], 'GC-Background-MajorMC', 0, 0);
+ checkRuntimeGroup_(groups[15], 'GC-Background-Other', 0, 0);
+ checkRuntimeGroup_(groups[16], 'GC', 17, 187);
+ checkRuntimeGroup_(groups[17], 'JavaScript', 3, 33);
+ checkRuntimeGroup_(groups[18], 'V8 C++', 5, 55);
+
+ const blinkGroupCollection = groupCollection.blinkRCSGroupCollection;
+ const blinkGroups = blinkGroupCollection.runtimeGroups;
+ checkRuntimeGroup_(blinkGroups[0], 'Blink_Bindings', 100, 5);
+ checkRuntimeGroup_(blinkGroups[1], 'Blink_GC', 30, 70);
+ checkRuntimeGroup_(blinkGroups[2], 'Blink_Layout', 15, 35);
+ checkRuntimeGroup_(blinkGroups[3], 'Blink_Parsing', 15, 120);
+ checkRuntimeGroup_(blinkGroups[4], 'Blink_Style', 15, 30);
+ checkRuntimeGroup_(blinkGroups[5], 'Blink_Callbacks', 30, 35);
+
+ assert.strictEqual(205, blinkGroupCollection.totalCount);
+ assert.strictEqual(295, blinkGroupCollection.totalTime);
+
+ assert.strictEqual('Blink_UpdateLayout', blinkGroups[2].values[0].name);
+ assert.strictEqual('Blink_CollectGarbage', blinkGroups[1].values[0].name);
+ });
+
+ test('RuntimeStatsBackgroundGC', function() {
+ const slices = [];
+ slices.push(tr.c.TestUtils.newSliceEx({
+ title: 'V8.Execute',
+ start: 0,
+ end: 700,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {
+ 'runtime-call-stats': {
+ GC_BACKGROUND_UNMAPPER: [1, 10],
+ GC_SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL: [10, 100],
+ GC_MINOR_MC_BACKGROUND_MARKING: [20, 200],
+ GC_MINOR_MC_BACKGROUND_EVACUATE_COPY: [30, 300],
+ GC_MC_BACKGROUND_MARKING: [40, 400],
+ GC_MC_BACKGROUND_SWEEPING: [50, 500],
+ GC_MC_BACKGROUND_EVACUATE_COPY: [60, 600],
+ GC_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS: [70, 700]
+ }
+ }
+ }));
+ slices.push(tr.c.TestUtils.newSliceEx({
+ title: 'V8.newInstance',
+ start: 1000,
+ end: 8000,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {
+ 'runtime-call-stats': {
+ GC_SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL: [100, 1000],
+ GC_MINOR_MC_BACKGROUND_MARKING: [200, 2000],
+ GC_MINOR_MC_BACKGROUND_EVACUATE_COPY: [300, 3000],
+ GC_MC_BACKGROUND_MARKING: [400, 4000],
+ GC_MC_BACKGROUND_SWEEPING: [500, 5000],
+ GC_MC_BACKGROUND_EVACUATE_COPY: [600, 6000],
+ GC_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS: [700, 7000]
+ }
+ }
+ }));
+ const groupCollection = new tr.e.v8.RuntimeStatsGroupCollection();
+ groupCollection.addSlices(slices);
+ assert.strictEqual(groupCollection.totalTime, 28000 + 2800 + 10);
+
+ const groups = groupCollection.runtimeGroups;
+ assert.deepEqual(groups.length, 19);
+ checkRuntimeGroup_(groups[0], 'Total', 2800 + 280 + 1, 28000 + 2800 + 10);
+ checkRuntimeGroup_(groups[1], 'IC', 0, 0);
+ checkRuntimeGroup_(groups[2], 'Optimize-Background', 0, 0);
+ checkRuntimeGroup_(groups[3], 'Optimize', 0, 0);
+ checkRuntimeGroup_(groups[4], 'Compile-Background', 0, 0);
+ checkRuntimeGroup_(groups[5], 'Compile', 0, 0);
+ checkRuntimeGroup_(groups[6], 'Parse-Background', 0, 0);
+ checkRuntimeGroup_(groups[7], 'Parse', 0, 0);
+ checkRuntimeGroup_(groups[8], 'Blink C++', 0, 0);
+ checkRuntimeGroup_(groups[9], 'API', 0, 0);
+ checkRuntimeGroup_(groups[10], 'GC-Background-Marking', 440, 4400);
+ checkRuntimeGroup_(groups[11], 'GC-Background-Sweeping', 550, 5500);
+ checkRuntimeGroup_(groups[12], 'GC-Background-Scavenger', 110, 1100);
+ checkRuntimeGroup_(groups[13], 'GC-Background-MinorMC',
+ 300 + 200 + 30 + 20, 3000 + 2000 + 300 + 200);
+ checkRuntimeGroup_(groups[14], 'GC-Background-MajorMC',
+ 700 + 600 + 70 + 60, 7000 + 6000 + 700 + 600);
+ checkRuntimeGroup_(groups[15], 'GC-Background-Other', 1, 10);
+ checkRuntimeGroup_(groups[16], 'GC', 0, 0);
+ checkRuntimeGroup_(groups[17], 'JavaScript', 0, 0);
+ checkRuntimeGroup_(groups[18], 'V8 C++', 0, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_cpu_profile_node.html b/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_cpu_profile_node.html
new file mode 100644
index 00000000000..b5a1855fdca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_cpu_profile_node.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/profile_node.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the V8CpuProfileNode class.
+ */
+tr.exportTo('tr.e.v8', function() {
+ const ProfileNode = tr.model.ProfileNode;
+ /**
+ * A V8CpuProfileNode represents a node in the v8 cpu profile tree,
+ * it is essentially a frame in the stack when the sample gets recorded.
+ */
+ function V8CpuProfileNode(id, callFrame, parentNode) {
+ ProfileNode.call(this, id, callFrame.functionName, parentNode);
+ this.callFrame_ = tr.b.deepCopy(callFrame);
+ this.deoptReason_ = '';
+ this.colorId_ = tr.b.ColorScheme.getColorIdForGeneralPurposeString(
+ callFrame.functionName);
+ }
+
+ V8CpuProfileNode.prototype = {
+ __proto__: ProfileNode.prototype,
+
+ get functionName() {
+ return this.callFrame_.functionName;
+ },
+
+ get scriptId() {
+ return this.callFrame_.scriptId;
+ },
+
+ get url() {
+ if (!this.callFrame_.url) {
+ return 'unknown';
+ }
+ let url = this.callFrame_.url;
+ if (this.callFrame_.lineNumber === undefined) {
+ return url;
+ }
+ url = url + ':' + this.callFrame_.lineNumber;
+ if (this.callFrame_.columnNumber === undefined) {
+ return url;
+ }
+ url = url + ':' + this.callFrame_.columnNumber;
+ return url;
+ },
+
+ get deoptReason() {
+ return this.deoptReason_;
+ },
+
+ set deoptReason(value) {
+ this.deoptReason_ = value;
+ },
+
+ get userFriendlyName() {
+ const name = this.functionName + ' url: ' + this.url;
+ return !this.deoptReason_ ?
+ name : name + ' Deoptimized reason: ' + this.deoptReason_;
+ },
+
+ get sampleTitle() {
+ return 'V8 Sample';
+ }
+ };
+
+ V8CpuProfileNode.constructFromObject = function(profileTree, node) {
+ const nodeId = node.id;
+ if (nodeId === 1) {
+ // Ignore fake root.
+ // The node with id 1 is a fake root for the profile tree,
+ // since we are using map, we don't really need it.
+ return undefined;
+ }
+ const parentNode = profileTree.getNode(node.parent);
+ const profileNode = new V8CpuProfileNode(nodeId, node.callFrame,
+ parentNode);
+ if (node.deoptReason !== undefined) {
+ profileNode.deoptReason = node.deoptReason;
+ }
+ return profileNode;
+ };
+
+ ProfileNode.subTypes.register(
+ V8CpuProfileNode,
+ {
+ typeName: 'cpuProfile',
+ name: 'v8 cpu profile node',
+ pluralName: 'v8 cpu profile nodes'
+ }
+ );
+
+ ProfileNode.subTypes.register(
+ V8CpuProfileNode,
+ {
+ typeName: 'legacySample',
+ name: 'v8 cpu profile node',
+ pluralName: 'v8 cpu profile nodes'
+ }
+ );
+
+ return {
+ ProfileNode,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_gc_stats_thread_slice.html b/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_gc_stats_thread_slice.html
new file mode 100644
index 00000000000..8e29b5fdf3a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_gc_stats_thread_slice.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/thread_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.v8', function() {
+ const ThreadSlice = tr.model.ThreadSlice;
+
+ function V8GCStatsThreadSlice() {
+ ThreadSlice.apply(this, arguments);
+ this.liveObjects_ = JSON.parse(this.args.live);
+ delete this.args.live;
+ this.deadObjects_ = JSON.parse(this.args.dead);
+ delete this.args.dead;
+ }
+
+ V8GCStatsThreadSlice.prototype = {
+ __proto__: ThreadSlice.prototype,
+
+ get liveObjects() {
+ return this.liveObjects_;
+ },
+
+ get deadObjects() {
+ return this.deadObjects_;
+ }
+ };
+
+ ThreadSlice.subTypes.register(
+ V8GCStatsThreadSlice,
+ {
+ categoryParts: ['disabled-by-default-v8.gc_stats'],
+ name: 'v8 gc stats slice',
+ pluralName: 'v8 gc stats slices'
+ }
+ );
+
+ return {
+ V8GCStatsThreadSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_ic_stats_thread_slice.html b/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_ic_stats_thread_slice.html
new file mode 100644
index 00000000000..7ee3f0c527c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_ic_stats_thread_slice.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/thread_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.v8', function() {
+ const ThreadSlice = tr.model.ThreadSlice;
+
+ function V8ICStatsThreadSlice() {
+ ThreadSlice.apply(this, arguments);
+ this.icStats_ = undefined;
+ if (this.args['ic-stats']) {
+ this.icStats_ = this.args['ic-stats'].data;
+ delete this.args['ic-stats'];
+ }
+ }
+
+ V8ICStatsThreadSlice.prototype = {
+ __proto__: ThreadSlice.prototype,
+
+ get icStats() {
+ return this.icStats_;
+ }
+ };
+
+ ThreadSlice.subTypes.register(
+ V8ICStatsThreadSlice,
+ {
+ categoryParts: ['disabled-by-default-v8.ic_stats'],
+ name: 'v8 ic stats slice',
+ pluralName: 'v8 ic stats slices'
+ }
+ );
+
+ return {
+ V8ICStatsThreadSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_thread_slice.html b/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_thread_slice.html
new file mode 100644
index 00000000000..4aaee2eeca5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8/v8_thread_slice.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/thread_slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.e.v8', function() {
+ const ThreadSlice = tr.model.ThreadSlice;
+
+ function V8ThreadSlice() {
+ ThreadSlice.apply(this, arguments);
+ this.runtimeCallStats_ = undefined;
+ }
+
+ V8ThreadSlice.prototype = {
+ __proto__: ThreadSlice.prototype,
+
+ get runtimeCallStats() {
+ if ('runtime-call-stats' in this.args) {
+ this.runtimeCallStats_ = this.args['runtime-call-stats'];
+ delete this.args['runtime-call-stats'];
+ }
+ return this.runtimeCallStats_;
+ }
+ };
+
+ ThreadSlice.subTypes.register(
+ V8ThreadSlice,
+ {
+ categoryParts: ['v8', 'disabled-by-default-v8.runtime_stats'],
+ name: 'v8 slice',
+ pluralName: 'v8 slices'
+ }
+ );
+
+ return {
+ V8ThreadSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/v8_config.html b/chromium/third_party/catapult/tracing/tracing/extras/v8_config.html
new file mode 100644
index 00000000000..7729e6c1905
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/v8_config.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/v8/v8_cpu_profile_node.html">
+<link rel="import" href="/tracing/extras/v8/v8_gc_stats_thread_slice.html">
+<link rel="import" href="/tracing/extras/v8/v8_ic_stats_thread_slice.html">
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor.html b/chromium/third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor.html
new file mode 100644
index 00000000000..df56592cde5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/auditor.html">
+
+<script>
+'use strict';
+
+function filterDuplicateTimestamps(timestamps) {
+ const dedupedTimestamps = [];
+ let lastTs = 0;
+ for (const ts of timestamps) {
+ if (ts - lastTs >= 1) {
+ dedupedTimestamps.push(ts);
+ lastTs = ts;
+ }
+ }
+ return dedupedTimestamps;
+}
+
+tr.exportTo('tr.e.audits', function() {
+ const VSYNC_COUNTER_PRECISIONS = {
+ // Android. Some versions have VSYNC split out into VSYNC-app and VSYNC-sf.
+ // Requires "gfx" systrace category to be enabled.
+ 'android.VSYNC-app': 15,
+ 'android.VSYNC': 15
+ };
+
+ const VSYNC_SLICE_PRECISIONS = {
+ // Android.
+ 'RenderWidgetHostViewAndroid::OnVSync': 5,
+ // Android. Very precise. Requires "gfx" systrace category to be enabled.
+ 'VSYNC': 10,
+ // Linux. Very precise. Requires "gpu" tracing category to be enabled.
+ 'vblank': 10,
+ // Mac. Derived from a Mac callback (CVDisplayLinkSetOutputCallback).
+ 'DisplayLinkMac::GetVSyncParameters': 5
+ };
+
+ const BEGIN_FRAME_SLICE_PRECISION = {
+ 'DisplayScheduler::BeginFrame': 10
+ };
+
+ /**
+ * Auditor that analyzes the model and, if possible, adds data to it
+ * indicating when vertical sync events took place.
+ *
+ * @constructor
+ * @extends {tr.c.Auditor}
+ */
+ function VSyncAuditor(model) {
+ tr.c.Auditor.call(this, model);
+ }
+
+ VSyncAuditor.prototype = {
+ __proto__: tr.c.Auditor.prototype,
+
+ runAnnotate() {
+ this.model.device.vSyncTimestamps = this.findVSyncTimestamps(this.model);
+ },
+
+ /**
+ * Returns an array of the most accurate VSync times available in the model.
+ */
+ findVSyncTimestamps(model) {
+ let times = [];
+
+ // Only keep the most precise VSync data.
+ let maxPrecision = Number.NEGATIVE_INFINITY;
+ let maxTitle = undefined;
+
+ function useInstead(title, precisions) {
+ const precision = precisions[title];
+ if (precision === undefined) return false;
+
+ if (title === maxTitle) return true;
+
+ if (precision <= maxPrecision) {
+ if (precision === maxPrecision) {
+ model.importWarning({
+ type: 'VSyncAuditor',
+ message: 'Encountered two different VSync events (' +
+ maxTitle + ', ' + title + ') with the same precision, ' +
+ 'ignoring the newer one (' + title + ')',
+ showToUser: false,
+ });
+ }
+ return false;
+ }
+ maxPrecision = precision;
+ maxTitle = title;
+ times = [];
+
+ return true;
+ }
+
+ for (const pid in model.processes) {
+ const process = model.processes[pid];
+ // Traverse process counters.
+ for (const cid in process.counters) {
+ if (useInstead(cid, VSYNC_COUNTER_PRECISIONS)) {
+ const counter = process.counters[cid];
+ for (let i = 0; i < counter.series.length; i++) {
+ const series = counter.series[i];
+ Array.prototype.push.apply(times, series.timestamps);
+ }
+ }
+ }
+
+ // Traverse thread slices.
+ for (const tid in process.threads) {
+ const thread = process.threads[tid];
+ for (let i = 0; i < thread.sliceGroup.slices.length; i++) {
+ const slice = thread.sliceGroup.slices[i];
+ if (useInstead(slice.title, VSYNC_SLICE_PRECISIONS)) {
+ times.push(slice.start);
+ } else if (useInstead(slice.title, BEGIN_FRAME_SLICE_PRECISION) &&
+ slice.args.args && slice.args.args.frame_time_us) {
+ // We need to check not only that we have a Scheduler::BeginFrame
+ // event, but also that we have one that has a frame time
+ // associated with it.
+ // Older versions of Scheduler::BeginFrame don't have one.
+ times.push(slice.args.args.frame_time_us / 1000.0);
+ }
+ }
+ }
+ }
+ times.sort(function(x, y) { return x - y; });
+ return filterDuplicateTimestamps(times);
+ }
+ };
+
+ tr.c.Auditor.register(VSyncAuditor);
+
+ return {
+ VSyncAuditor,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor_test.html b/chromium/third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor_test.html
new file mode 100644
index 00000000000..69aea99fd9e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/extras/vsync/vsync_auditor_test.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/vsync/vsync_auditor.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const CounterSeries = tr.model.CounterSeries;
+ const Model = tr.Model;
+ const ThreadSlice = tr.model.ThreadSlice;
+ const VSyncAuditor = tr.e.audits.VSyncAuditor;
+
+ function testFindVSyncTimestamps(slices, counters, expectedTimes) {
+ const model = buildModel(slices, counters);
+ const auditor = new VSyncAuditor(model);
+ assert.deepEqual(auditor.findVSyncTimestamps(model), expectedTimes);
+ }
+
+ function buildModel(slices, counters) {
+ const model = new Model();
+ const process = model.getOrCreateProcess(1);
+ for (let i = 0; i < slices.length; i++) {
+ const thread = process.getOrCreateThread(i);
+ for (let j = 0; j < slices[i].length; j++) {
+ thread.sliceGroup.pushSlice(slices[i][j]);
+ }
+ }
+ for (let i = 0; i < counters.length; i++) {
+ const counter = process.getOrCreateCounter(
+ counters[i].category,
+ counters[i].name);
+ counter.addSeries(counters[i].series);
+ }
+ return model;
+ }
+
+ function buildSlice(title, time) {
+ return new ThreadSlice('', title, 0, time, {});
+ }
+
+ function buildCounterSeries(name, timestamps) {
+ const series = new CounterSeries(name, '');
+ for (let i = 0; i < timestamps.length; i++) {
+ series.addCounterSample(timestamps[i], 1);
+ }
+ return series;
+ }
+
+ test('findEmpty', function() {
+ testFindVSyncTimestamps([], [], []);
+ });
+
+ test('findNoVsync', function() {
+ testFindVSyncTimestamps([
+ [buildSlice('MessageLoop::RunTask', 10),
+ buildSlice('MessageLoop::RunTask', 20)],
+ [buildSlice('MessageLoop::RunTask', 15)]
+ ], [], []);
+ });
+
+ test('findOneVsync', function() {
+ testFindVSyncTimestamps([[buildSlice('vblank', 42)]], [], [42]);
+ });
+
+ test('findMultipleVsyncs', function() {
+ testFindVSyncTimestamps([
+ [buildSlice('VSYNC', 1), buildSlice('MessageLoop::RunTask', 2)],
+ [buildSlice('MessageLoop::RunTask', 3)],
+ [buildSlice('MessageLoop::RunTask', 4), buildSlice('VSYNC', 5)],
+ [buildSlice('VSYNC', 6), buildSlice('VSYNC', 7)]
+ ], [], [1, 5, 6, 7]);
+ });
+
+ test('filterNearDuplicates', function() {
+ testFindVSyncTimestamps([
+ [buildSlice('VSYNC', 1), buildSlice('VSYNC', 1)],
+ [buildSlice('VSYNC', 2), buildSlice('VSYNC', 2.1)],
+ [buildSlice('VSYNC', 3), buildSlice('VSYNC', 4)],
+ ], [], [1, 2, 3, 4]);
+ });
+
+ test('findMultipleAndroidVsyncs', function() {
+ testFindVSyncTimestamps([
+ [buildSlice('MessageLoop::RunTask', 2)],
+ [buildSlice('MessageLoop::RunTask', 3)],
+ [buildSlice('MessageLoop::RunTask', 4)]
+ ],
+ [
+ {
+ category: 'android',
+ name: 'VSYNC-app',
+ series: buildCounterSeries('VSYNC-app', [1, 5, 6, 7])
+ }
+ ], [1, 5, 6, 7]);
+ });
+
+ test('findUnsorted', function() {
+ testFindVSyncTimestamps([
+ [buildSlice('RenderWidgetHostViewAndroid::OnVSync', 4),
+ buildSlice('MessageLoop::RunTask', 2)],
+ [buildSlice('RenderWidgetHostViewAndroid::OnVSync', 1),
+ buildSlice('RenderWidgetHostViewAndroid::OnVSync', 3)]
+ ], [], [1, 3, 4]);
+ });
+
+ test('findDifferentPrecisions', function() {
+ // vblank has higher precision than RenderWidgetHostViewAndroid::OnVSync.
+ testFindVSyncTimestamps([
+ [buildSlice('RenderWidgetHostViewAndroid::OnVSync', 1),
+ buildSlice('vblank', 2),
+ buildSlice('RenderWidgetHostViewAndroid::OnVSync', 3)]
+ ], [], [2]);
+ });
+
+ test('findBeginFrame', function() {
+ const title = 'DisplayScheduler::BeginFrame';
+ testFindVSyncTimestamps([[
+ new ThreadSlice('', title, 0, 2, { args: { frame_time_us: 1000 } }),
+ new ThreadSlice('', title, 0, 4, { args: { frame_time_us: 3000 } })
+ ]], [], [1, 3]);
+ });
+
+ test('findBeginFrame_noFrameTime', function() {
+ const title = 'DisplayScheduler::BeginFrame';
+ testFindVSyncTimestamps([[
+ new ThreadSlice('', title, 0, 2, {}),
+ new ThreadSlice('', title, 0, 4, { args: {} })
+ ]], [], []);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/clock_sync_test.html b/chromium/third_party/catapult/tracing/tracing/importer/clock_sync_test.html
new file mode 100644
index 00000000000..ce164eb881b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/clock_sync_test.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/battor_importer.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/clock_sync_manager.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains end-to-end clock sync tests that ensure
+ * clock sync behavior works as expected across traces. There are too many
+ * possible combinations of trace types to test all of them, but we aim to test
+ * many of the important ones in this file.
+ */
+tr.b.unittest.testSuite(function() {
+ test('import_noClockDomains', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([]);
+
+ assert.isFalse(m.hasImportWarnings);
+ });
+
+ test('import_traceEvent', function() {
+ const trace = JSON.stringify({
+ traceEvents: [
+ {ts: 0, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}},
+ {ts: 1000, pid: 0, tid: 0, ph: 'c', cat: 'metadata',
+ args: { issue_ts: 500, sync_id: 'abc' }},
+ {ts: 2000, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}}
+ ]});
+ const m = tr.c.TestUtils.newModelWithEvents([trace]);
+
+ assert.isFalse(m.hasImportWarnings);
+
+ assert.strictEqual(m.processes[0].threads[0].sliceGroup.slices[0].start, 0);
+ assert.strictEqual(m.processes[0].threads[0].sliceGroup.slices[1].start, 2);
+ });
+
+
+ test('import_ftrace', function() {
+ const ftrace =
+ 'SurfaceFlinger-0 [001] ...1 0.001: 0: B|1|taskA\n' +
+ ' chrome-3 [001] ...1 0.010: 0: trace_event_clock_sync: ' +
+ 'parent_ts=0.020\n';
+
+ const m = tr.c.TestUtils.newModelWithEvents([ftrace]);
+
+ assert.isFalse(m.hasImportWarnings);
+ assert.strictEqual(m.processes[1].threads[0].sliceGroup.slices[0].start, 0);
+ });
+
+ test('import_traceEventWithNoClockDomainAndFtrace', function() {
+ // Include a clock sync marker that indicates the LINUX_CLOCK_MONOTONIC time
+ // of 20ms is equal to the LINUX_FTRACE_GLOBAL time of 10ms, effectively
+ // shifting all ftrace timestamps forward by 10ms.
+ const ftrace =
+ 'SurfaceFlinger-0 [001] ...1 0.001: 0: B|1|taskA\n' +
+ ' chrome-3 [001] ...1 0.010: 0: trace_event_clock_sync: ' +
+ 'parent_ts=0.020\n';
+
+ const trace = JSON.stringify({
+ traceEvents: [
+ {ts: 0, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}},
+ {ts: 1000, pid: 0, tid: 0, ph: 'c', cat: 'metadata',
+ args: { issue_ts: 500, sync_id: 'abc' }},
+ {ts: 2000, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}}
+ ],
+ systemTraceEvents: ftrace
+ });
+ const m = tr.c.TestUtils.newModelWithEvents([trace]);
+
+ assert.isFalse(m.hasImportWarnings);
+
+ // Chrome events shouldn't be shifted.
+ assert.strictEqual(m.processes[0].threads[0].sliceGroup.slices[0].start, 0);
+ assert.strictEqual(m.processes[0].threads[0].sliceGroup.slices[1].start, 2);
+
+ // Ftrace events should be shifted forward by 10ms.
+ assert.strictEqual(
+ m.processes[1].threads[0].sliceGroup.slices[0].start, 11);
+ });
+
+ test('import_traceEventWithClockDomainAndFtrace', function() {
+ // Include a clock sync marker that indicates the LINUX_CLOCK_MONOTONIC time
+ // of 20ms is equal to the LINUX_FTRACE_GLOBAL time of 10ms, effectively
+ // shifting all ftrace timestamps forward by 10ms.
+ const ftrace =
+ 'SurfaceFlinger-0 [001] ...1 0.001: 0: B|1|taskA\n' +
+ ' chrome-3 [001] ...1 0.010: 0: trace_event_clock_sync: ' +
+ 'parent_ts=0.020\n';
+
+ const trace = JSON.stringify({
+ traceEvents: [
+ {ts: 0, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}},
+ {ts: 1000, pid: 0, tid: 0, ph: 'c', cat: 'metadata',
+ args: { issue_ts: 500, sync_id: 'abc' }},
+ {ts: 2000, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}}
+ ],
+ metadata: {
+ 'clock-domain': 'LINUX_CLOCK_MONOTONIC'
+ },
+ systemTraceEvents: ftrace
+ });
+ const m = tr.c.TestUtils.newModelWithEvents([trace]);
+
+ assert.isFalse(m.hasImportWarnings);
+
+ // Chrome events shouldn't be shifted.
+ assert.strictEqual(m.processes[0].threads[0].sliceGroup.slices[0].start, 0);
+ assert.strictEqual(m.processes[0].threads[0].sliceGroup.slices[1].start, 2);
+
+ // Ftrace events should be shifted forward by 10ms.
+ assert.strictEqual(
+ m.processes[1].threads[0].sliceGroup.slices[0].start, 11);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/context_processor.html b/chromium/third_party/catapult/tracing/tracing/importer/context_processor.html
new file mode 100644
index 00000000000..c82e80645a5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/context_processor.html
@@ -0,0 +1,206 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.importer', function() {
+ /**
+ * The context processor consumes context events and maintains a set of
+ * active contexts for a single thread.
+ *
+ * @constructor
+ */
+ function ContextProcessor(model) {
+ this.model_ = model;
+ this.activeContexts_ = [];
+ this.stackPerType_ = {};
+ // Cache of unique context objects.
+ this.contextCache_ = {};
+ // Cache of unique context object sets.
+ this.contextSetCache_ = {};
+ this.cachedEntryForActiveContexts_ = undefined;
+ // All seen context object snapshots.
+ this.seenSnapshots_ = {};
+ }
+
+ ContextProcessor.prototype = {
+ enterContext(contextType, scopedId) {
+ const newActiveContexts = [
+ this.getOrCreateContext_(contextType, scopedId),
+ ];
+ for (const oldContext of this.activeContexts_) {
+ if (oldContext.type === contextType) {
+ // If a previous context of the same type is active, it is removed
+ // and pushed onto the stack for this type.
+ this.pushContext_(oldContext);
+ } else {
+ // Otherwise the old context is it is still active.
+ newActiveContexts.push(oldContext);
+ }
+ }
+ this.activeContexts_ = newActiveContexts;
+ this.cachedEntryForActiveContexts_ = undefined;
+ },
+
+ leaveContext(contextType, scopedId) {
+ this.leaveContextImpl_(context =>
+ context.type === contextType &&
+ context.snapshot.scope === scopedId.scope &&
+ context.snapshot.idRef === scopedId.id);
+ },
+
+ destroyContext(scopedId) {
+ // Remove all matching contexts from stacks.
+ for (const stack of Object.values(this.stackPerType_)) {
+ // Perform in-place filtering instead of Array.prototype.filter to
+ // prevent creating a new array.
+ let newLength = 0;
+ for (let i = 0; i < stack.length; ++i) {
+ if (stack[i].snapshot.scope !== scopedId.scope ||
+ stack[i].snapshot.idRef !== scopedId.id) {
+ stack[newLength++] = stack[i];
+ }
+ }
+ stack.length = newLength;
+ }
+
+ // Remove all matching contexts from active context set.
+ this.leaveContextImpl_(context =>
+ context.snapshot.scope === scopedId.scope &&
+ context.snapshot.idRef === scopedId.id);
+ },
+
+ leaveContextImpl_(predicate) {
+ const newActiveContexts = [];
+ for (const oldContext of this.activeContexts_) {
+ if (predicate(oldContext)) {
+ // If we left this context, remove it from the active set and
+ // restore any previous context of the same type.
+ const previousContext = this.popContext_(oldContext.type);
+ if (previousContext) {
+ newActiveContexts.push(previousContext);
+ }
+ } else {
+ newActiveContexts.push(oldContext);
+ }
+ }
+ this.activeContexts_ = newActiveContexts;
+ this.cachedEntryForActiveContexts_ = undefined;
+ },
+
+ getOrCreateContext_(contextType, scopedId) {
+ const context = {
+ type: contextType,
+ snapshot: {
+ scope: scopedId.scope,
+ idRef: scopedId.id
+ }
+ };
+ const key = this.getContextKey_(context);
+ if (key in this.contextCache_) {
+ return this.contextCache_[key];
+ }
+ this.contextCache_[key] = context;
+ const snapshotKey = this.getSnapshotKey_(scopedId);
+ this.seenSnapshots_[snapshotKey] = true;
+ return context;
+ },
+
+ pushContext_(context) {
+ if (!(context.type in this.stackPerType_)) {
+ this.stackPerType_[context.type] = [];
+ }
+ this.stackPerType_[context.type].push(context);
+ },
+
+ popContext_(contextType) {
+ if (!(contextType in this.stackPerType_)) {
+ return undefined;
+ }
+ return this.stackPerType_[contextType].pop();
+ },
+
+ getContextKey_(context) {
+ return [
+ context.type,
+ context.snapshot.scope,
+ context.snapshot.idRef
+ ].join('\x00');
+ },
+
+ getSnapshotKey_(scopedId) {
+ return [
+ scopedId.scope,
+ scopedId.idRef
+ ].join('\x00');
+ },
+
+ get activeContexts() {
+ // Keep a single instance for each unique set of active contexts to
+ // reduce memory usage.
+ if (this.cachedEntryForActiveContexts_ === undefined) {
+ let key = [];
+ for (const context of this.activeContexts_) {
+ key.push(this.getContextKey_(context));
+ }
+ key.sort();
+ key = key.join('\x00');
+ if (key in this.contextSetCache_) {
+ this.cachedEntryForActiveContexts_ = this.contextSetCache_[key];
+ } else {
+ this.activeContexts_.sort(function(a, b) {
+ const keyA = this.getContextKey_(a);
+ const keyB = this.getContextKey_(b);
+ if (keyA < keyB) {
+ return -1;
+ }
+ if (keyA > keyB) {
+ return 1;
+ }
+ return 0;
+ }.bind(this));
+ this.contextSetCache_[key] = Object.freeze(this.activeContexts_);
+ this.cachedEntryForActiveContexts_ = this.contextSetCache_[key];
+ }
+ }
+ return this.cachedEntryForActiveContexts_;
+ },
+
+ invalidateContextCacheForSnapshot(scopedId) {
+ const snapshotKey = this.getSnapshotKey_(scopedId);
+ if (!(snapshotKey in this.seenSnapshots_)) return;
+
+ this.contextCache_ = {};
+ this.contextSetCache_ = {};
+ this.cachedEntryForActiveContexts_ = undefined;
+ this.activeContexts_ = this.activeContexts_.map(function(context) {
+ // Do not alter unrelated contexts.
+ if (context.snapshot.scope !== scopedId.scope ||
+ context.snapshot.idRef !== scopedId.id) {
+ return context;
+ }
+ // Replace the invalidated context by a deep copy.
+ return {
+ type: context.type,
+ snapshot: {
+ scope: context.snapshot.scope,
+ idRef: context.snapshot.idRef
+ }
+ };
+ });
+ this.seenSnapshots_ = {};
+ },
+ };
+
+ return {
+ ContextProcessor,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/context_processor_test.html b/chromium/third_party/catapult/tracing/tracing/importer/context_processor_test.html
new file mode 100644
index 00000000000..c033f7c28ff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/context_processor_test.html
@@ -0,0 +1,297 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/importer/context_processor.html">
+<link rel="import" href="/tracing/model/scoped_id.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ContextProcessor = tr.importer.ContextProcessor;
+
+ test('empty', function() {
+ const processor = new ContextProcessor();
+ assert.deepEqual(processor.activeContexts, []);
+ });
+
+ test('enterAndLeave', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ const expectedContext = {
+ type: 'type',
+ snapshot: {scope: 'ptr', idRef: 123},
+ };
+ processor.enterContext('type', id);
+ assert.deepEqual(processor.activeContexts, [expectedContext]);
+ processor.leaveContext('type', id);
+ assert.deepEqual(processor.activeContexts, []);
+ });
+
+ test('parallelContexts', function() {
+ const processor = new ContextProcessor();
+ const idA = new tr.model.ScopedId('ptr', 123);
+ const idB = new tr.model.ScopedId('idx', 456);
+ const expectedContextA = {type: 'A', snapshot: {scope: 'ptr', idRef: 123}};
+ const expectedContextB = {type: 'B', snapshot: {scope: 'idx', idRef: 456}};
+
+ // Entering and leaving in order.
+ processor.enterContext('A', idA);
+ assert.deepEqual(processor.activeContexts, [expectedContextA]);
+ processor.enterContext('B', idB);
+ assert.deepEqual(processor.activeContexts, [expectedContextA,
+ expectedContextB]);
+ processor.leaveContext('B', idB);
+ assert.deepEqual(processor.activeContexts, [expectedContextA]);
+ processor.leaveContext('A', idA);
+ assert.deepEqual(processor.activeContexts, []);
+
+ // Entering and leaving out of order.
+ processor.enterContext('B', idB);
+ assert.deepEqual(processor.activeContexts, [expectedContextB]);
+ processor.enterContext('A', idA);
+ assert.deepEqual(processor.activeContexts, [expectedContextA,
+ expectedContextB]);
+ processor.leaveContext('B', idB);
+ assert.deepEqual(processor.activeContexts, [expectedContextA]);
+ processor.leaveContext('A', idA);
+ assert.deepEqual(processor.activeContexts, []);
+ });
+
+ test('contextStack', function() {
+ const processor = new ContextProcessor();
+ const idA = new tr.model.ScopedId('ptr', 123);
+ const idB = new tr.model.ScopedId('idx', 456);
+ const expectedContextA = {
+ type: 'type', snapshot: {scope: 'ptr', idRef: 123}};
+ const expectedContextB = {
+ type: 'type', snapshot: {scope: 'idx', idRef: 456}};
+
+ // Entering and leaving the same context type.
+ processor.enterContext('type', idA);
+ assert.deepEqual(processor.activeContexts, [expectedContextA]);
+ processor.enterContext('type', idB);
+ assert.deepEqual(processor.activeContexts, [expectedContextB]);
+ processor.leaveContext('type', idB);
+ assert.deepEqual(processor.activeContexts, [expectedContextA]);
+ processor.leaveContext('type', idA);
+ assert.deepEqual(processor.activeContexts, []);
+ });
+
+ test('contextCached', function() {
+ const processor = new ContextProcessor();
+ const idA = new tr.model.ScopedId('ptr', 123);
+ const idB = new tr.model.ScopedId('idx', 456);
+ const expectedContextA = {
+ type: 'A', snapshot: {scope: 'ptr', idRef: 123}};
+ const expectedContextB = {
+ type: 'B', snapshot: {scope: 'idx', idRef: 456}};
+
+ processor.enterContext('A', idA);
+ const firstSet = processor.activeContexts;
+ processor.enterContext('B', idB);
+ const secondSet = processor.activeContexts;
+ processor.leaveContext('B', idB);
+ processor.leaveContext('A', idA);
+
+ assert.deepEqual(firstSet, [expectedContextA]);
+ assert.deepEqual(secondSet, [expectedContextA, expectedContextB]);
+
+ // Identical context objects should be the same instance.
+ assert(Object.is(firstSet[0], secondSet[0]));
+ });
+
+ test('contextSetCached', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ const expectedContext = {
+ type: 'type',
+ snapshot: {scope: 'ptr', idRef: 123},
+ };
+
+ processor.enterContext('type', id);
+ const firstSet = processor.activeContexts;
+ processor.leaveContext('type', id);
+
+ processor.enterContext('type', id);
+ const secondSet = processor.activeContexts;
+ processor.leaveContext('type', id);
+
+ assert.deepEqual(firstSet, [expectedContext]);
+ assert(Object.is(firstSet, secondSet));
+ });
+
+ test('contextSetIsOrdered', function() {
+ const processor = new ContextProcessor();
+ const idA = new tr.model.ScopedId('ptr', 123);
+ const idB = new tr.model.ScopedId('idx', 456);
+ const expectedContextA = {type: 'A', snapshot: {scope: 'ptr', idRef: 123}};
+ const expectedContextB = {type: 'B', snapshot: {scope: 'idx', idRef: 456}};
+
+ processor.enterContext('A', idA);
+ processor.enterContext('B', idB);
+ const firstSet = processor.activeContexts;
+ processor.leaveContext('B', idB);
+ processor.leaveContext('A', idA);
+
+ processor.enterContext('B', idB);
+ processor.enterContext('A', idA);
+ const secondSet = processor.activeContexts;
+ processor.leaveContext('A', idA);
+ processor.leaveContext('B', idB);
+
+ assert.deepEqual(firstSet, [expectedContextA, expectedContextB]);
+ assert(Object.is(firstSet, secondSet));
+ });
+
+ test('contextSetIsFrozen', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ assert(Object.isFrozen(processor.activeContexts));
+ processor.enterContext('type', id);
+ assert(Object.isFrozen(processor.activeContexts));
+ processor.leaveContext('type', id);
+ assert(Object.isFrozen(processor.activeContexts));
+ });
+
+ test('cacheInvalidation', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ const expectedContext = {
+ type: 'type',
+ snapshot: {scope: 'ptr', idRef: 123},
+ };
+
+ processor.enterContext('type', id);
+ const firstSet = processor.activeContexts;
+ processor.leaveContext('type', id);
+
+ processor.invalidateContextCacheForSnapshot(id);
+
+ processor.enterContext('type', id);
+ const secondSet = processor.activeContexts;
+ processor.leaveContext('type', id);
+
+ assert.deepEqual(firstSet, [expectedContext]);
+ assert.deepEqual(secondSet, [expectedContext]);
+ assert(!Object.is(firstSet, secondSet));
+ assert(!Object.is(firstSet[0], secondSet[0]));
+ assert(!Object.is(firstSet[0].snapshot, secondSet[0].snapshot));
+ });
+
+ test('cacheInvalidationOfAnActiveContext', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ const expectedContext = {
+ type: 'type',
+ snapshot: {scope: 'ptr', idRef: 123},
+ };
+
+ processor.enterContext('type', id);
+ const firstSet = processor.activeContexts;
+
+ processor.invalidateContextCacheForSnapshot(id);
+
+ const secondSet = processor.activeContexts;
+ processor.leaveContext('type', id);
+
+ assert.deepEqual(firstSet, [expectedContext]);
+ assert.deepEqual(secondSet, [expectedContext]);
+ assert(!Object.is(firstSet, secondSet));
+ assert(!Object.is(firstSet[0], secondSet[0]));
+ assert(!Object.is(firstSet[0].snapshot, secondSet[0].snapshot));
+ });
+
+ test('cacheInvalidationForUnrelatedSnapshot', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ const unrelatedId = new tr.model.ScopedId('ofs', 789);
+ const expectedContext = {
+ type: 'type',
+ snapshot: {scope: 'ptr', idRef: 123},
+ };
+
+ processor.enterContext('type', id);
+ const firstSet = processor.activeContexts;
+ processor.leaveContext('type', id);
+
+ processor.invalidateContextCacheForSnapshot(unrelatedId);
+
+ processor.enterContext('type', id);
+ const secondSet = processor.activeContexts;
+ processor.leaveContext('type', id);
+
+ assert.deepEqual(firstSet, [expectedContext]);
+ assert.deepEqual(secondSet, [expectedContext]);
+ assert(Object.is(firstSet, secondSet));
+ });
+
+ test('destroyBasic', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ const expectedContext = {
+ type: 'type',
+ snapshot: {scope: 'ptr', idRef: 123},
+ };
+ processor.enterContext('type', id);
+ assert.deepEqual(processor.activeContexts, [expectedContext]);
+ processor.destroyContext(id);
+ assert.deepEqual(processor.activeContexts, []);
+ });
+
+ test('destroyActiveContextWithNonEmptyStack', function() {
+ const processor = new ContextProcessor();
+ const idA = new tr.model.ScopedId('ptr', 123);
+ const idB = new tr.model.ScopedId('idx', 456);
+ const expectedContext = {
+ type: 'type',
+ snapshot: {scope: 'ptr', idRef: 123},
+ };
+ processor.enterContext('type', idA);
+ processor.enterContext('type', idB);
+ processor.destroyContext(idB);
+ assert.deepEqual(processor.activeContexts, [expectedContext]);
+ processor.leaveContext('type', idA);
+ assert.deepEqual(processor.activeContexts, []);
+ });
+
+ test('destroyInactiveContextInStack', function() {
+ const processor = new ContextProcessor();
+ const idA = new tr.model.ScopedId('ptr', 123);
+ const idB = new tr.model.ScopedId('idx', 456);
+ const expectedContext = {
+ type: 'type',
+ snapshot: {scope: 'idx', idRef: 456},
+ };
+ processor.enterContext('type', idA);
+ processor.enterContext('type', idB);
+ processor.destroyContext(idA);
+ assert.deepEqual(processor.activeContexts, [expectedContext]);
+ processor.leaveContext('type', idB);
+ assert.deepEqual(processor.activeContexts, []);
+ });
+
+ test('destroyContextEnteredWithMultipleTypes', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ processor.enterContext('A', id);
+ processor.enterContext('B', id);
+ processor.destroyContext(id);
+ assert.deepEqual(processor.activeContexts, []);
+ });
+
+ test('destroyReenteredContext', function() {
+ const processor = new ContextProcessor();
+ const id = new tr.model.ScopedId('ptr', 123);
+ processor.enterContext('type', id);
+ processor.enterContext('type', id);
+ processor.destroyContext(id);
+ assert.deepEqual(processor.activeContexts, []);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/empty_importer.html b/chromium/third_party/catapult/tracing/tracing/importer/empty_importer.html
new file mode 100644
index 00000000000..2f876b3708e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/empty_importer.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/importer/importer.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Base class for trace data importers.
+ */
+tr.exportTo('tr.importer', function() {
+ /**
+ * Importer for empty strings and arrays.
+ * @constructor
+ */
+ function EmptyImporter(events) {
+ this.importPriority = 0;
+ }
+
+ EmptyImporter.canImport = function(eventData) {
+ if (eventData instanceof Array && eventData.length === 0) {
+ return true;
+ }
+ if (typeof(eventData) === 'string' || eventData instanceof String) {
+ return eventData.length === 0;
+ }
+ return false;
+ };
+
+ EmptyImporter.prototype = {
+ __proto__: tr.importer.Importer.prototype,
+
+ get importerName() {
+ return 'EmptyImporter';
+ }
+ };
+
+ tr.importer.Importer.register(EmptyImporter);
+
+ return {
+ EmptyImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/find_input_expectations.html b/chromium/third_party/catapult/tracing/tracing/importer/find_input_expectations.html
new file mode 100644
index 00000000000..464a41853d7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/find_input_expectations.html
@@ -0,0 +1,1409 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import" href="/tracing/importer/proto_expectation.html">
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.importer', function() {
+ const ProtoExpectation = tr.importer.ProtoExpectation;
+ const INITIATOR_TYPE = tr.model.um.INITIATOR_TYPE;
+ const INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES;
+
+ const KEYBOARD_TYPE_NAMES = [
+ INPUT_TYPE.CHAR,
+ INPUT_TYPE.KEY_DOWN_RAW,
+ INPUT_TYPE.KEY_DOWN,
+ INPUT_TYPE.KEY_UP
+ ];
+ const MOUSE_RESPONSE_TYPE_NAMES = [
+ INPUT_TYPE.CLICK,
+ INPUT_TYPE.CONTEXT_MENU
+ ];
+ const MOUSE_WHEEL_TYPE_NAMES = [
+ INPUT_TYPE.MOUSE_WHEEL
+ ];
+ const MOUSE_DRAG_TYPE_NAMES = [
+ INPUT_TYPE.MOUSE_DOWN,
+ INPUT_TYPE.MOUSE_MOVE,
+ INPUT_TYPE.MOUSE_UP
+ ];
+ const TAP_TYPE_NAMES = [
+ INPUT_TYPE.TAP,
+ INPUT_TYPE.TAP_CANCEL,
+ INPUT_TYPE.TAP_DOWN
+ ];
+ const PINCH_TYPE_NAMES = [
+ INPUT_TYPE.PINCH_BEGIN,
+ INPUT_TYPE.PINCH_END,
+ INPUT_TYPE.PINCH_UPDATE
+ ];
+ const FLING_TYPE_NAMES = [
+ INPUT_TYPE.FLING_CANCEL,
+ INPUT_TYPE.FLING_START
+ ];
+ const TOUCH_TYPE_NAMES = [
+ INPUT_TYPE.TOUCH_END,
+ INPUT_TYPE.TOUCH_MOVE,
+ INPUT_TYPE.TOUCH_START
+ ];
+ const SCROLL_TYPE_NAMES = [
+ INPUT_TYPE.SCROLL_BEGIN,
+ INPUT_TYPE.SCROLL_END,
+ INPUT_TYPE.SCROLL_UPDATE
+ ];
+ const ALL_HANDLED_TYPE_NAMES = [].concat(
+ KEYBOARD_TYPE_NAMES,
+ MOUSE_RESPONSE_TYPE_NAMES,
+ MOUSE_WHEEL_TYPE_NAMES,
+ MOUSE_DRAG_TYPE_NAMES,
+ PINCH_TYPE_NAMES,
+ TAP_TYPE_NAMES,
+ FLING_TYPE_NAMES,
+ TOUCH_TYPE_NAMES,
+ SCROLL_TYPE_NAMES
+ );
+
+ const RENDERER_FLING_TITLE = 'InputHandlerProxy::HandleGestureFling::started';
+ const PLAYBACK_EVENT_TITLE = 'VideoPlayback';
+
+ const CSS_ANIMATION_TITLE = 'Animation';
+
+ const VR_COUNTER_NAMES = [
+ 'gpu.WebVR FPS',
+ 'gpu.WebVR frame time (ms)',
+ 'gpu.WebVR pose prediction (ms)',
+ ];
+ const VR_EVENT_NAMES = [
+ 'VrShellGl::AcquireFrame',
+ 'VrShellGl::DrawFrame',
+ 'VrShellGl::DrawSubmitFrameWhenReady',
+ 'VrShellGl::DrawUiView',
+ 'VrShellGl::UpdateController',
+ ];
+ /* 1s is a bit arbitrary, but it reliably avoids all the jank caused by
+ * VR entry.
+ */
+ const VR_RESPONSE_MS = 1000;
+
+ /**
+ * If there's less than this much time between the end of one event and the
+ * start of the next, then they might be merged.
+ * There was not enough thought given to this value, so if you have any slight
+ * reason to change it, then please do so. It might also be good to split this
+ * into multiple values.
+ */
+ const INPUT_MERGE_THRESHOLD_MS = 200;
+ const ANIMATION_MERGE_THRESHOLD_MS = 32; // 2x 60FPS frames
+
+ /**
+ * If two MouseWheel events begin this close together, then they're an
+ * Animation, not two responses.
+ */
+ const MOUSE_WHEEL_THRESHOLD_MS = 40;
+
+ /**
+ * If two MouseMoves are more than this far apart, then they're two Responses,
+ * not Animation.
+ */
+ const MOUSE_MOVE_THRESHOLD_MS = 40;
+
+ // TODO(#3813) Move this.
+ function compareEvents(x, y) {
+ if (x.start !== y.start) {
+ return x.start - y.start;
+ }
+ if (x.end !== y.end) {
+ return x.end - y.end;
+ }
+ if (x.guid && y.guid) {
+ return x.guid - y.guid;
+ }
+ return 0;
+ }
+
+ function forEventTypesIn(events, typeNames, cb, opt_this) {
+ events.forEach(function(event) {
+ if (typeNames.indexOf(event.typeName) >= 0) {
+ cb.call(opt_this, event);
+ }
+ });
+ }
+
+ function causedFrame(event) {
+ return event.associatedEvents.some(isImplFrameEvent);
+ }
+
+ function getSortedFrameEventsByProcess(modelHelper) {
+ const frameEventsByPid = {};
+ for (const [pid, rendererHelper] of
+ Object.entries(modelHelper.rendererHelpers)) {
+ frameEventsByPid[pid] = rendererHelper.getFrameEventsInRange(
+ tr.model.helpers.IMPL_FRAMETIME_TYPE, modelHelper.model.bounds);
+ }
+ return frameEventsByPid;
+ }
+
+ function getSortedInputEvents(modelHelper) {
+ const inputEvents = [];
+
+ const browserProcess = modelHelper.browserHelper.process;
+ const mainThread = browserProcess.findAtMostOneThreadNamed(
+ 'CrBrowserMain');
+ for (const slice of mainThread.asyncSliceGroup.getDescendantEvents()) {
+ if (!slice.isTopLevel) continue;
+
+ if (!(slice instanceof tr.e.cc.InputLatencyAsyncSlice)) continue;
+
+ if (isNaN(slice.start) ||
+ isNaN(slice.duration) ||
+ isNaN(slice.end)) {
+ continue;
+ }
+
+ inputEvents.push(slice);
+ }
+
+ return inputEvents.sort(compareEvents);
+ }
+
+ function findProtoExpectations(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ // This order is not important. Handlers are independent.
+ const handlers = [
+ handleKeyboardEvents,
+ handleMouseResponseEvents,
+ handleMouseWheelEvents,
+ handleMouseDragEvents,
+ handleTapResponseEvents,
+ handlePinchEvents,
+ handleFlingEvents,
+ handleTouchEvents,
+ handleScrollEvents,
+ handleCSSAnimations,
+ handleWebGLAnimations,
+ handleVideoAnimations,
+ handleVrAnimations,
+ ];
+ handlers.forEach(function(handler) {
+ protoExpectations.push.apply(protoExpectations, handler(
+ modelHelper, sortedInputEvents, warn));
+ });
+ protoExpectations.sort(compareEvents);
+ return protoExpectations;
+ }
+
+ /**
+ * Every keyboard event is a Response.
+ */
+ function handleKeyboardEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ forEventTypesIn(sortedInputEvents, KEYBOARD_TYPE_NAMES, function(event) {
+ const pe = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.KEYBOARD);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ });
+ return protoExpectations;
+ }
+
+ /**
+ * Some mouse events can be translated directly into Responses.
+ */
+ function handleMouseResponseEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ forEventTypesIn(
+ sortedInputEvents, MOUSE_RESPONSE_TYPE_NAMES, function(event) {
+ const pe = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.MOUSE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ });
+ return protoExpectations;
+ }
+ /**
+ * MouseWheel events are caused either by a physical wheel on a physical
+ * mouse, or by a touch-drag gesture on a track-pad. The physical wheel
+ * causes MouseWheel events that are much more spaced out, and have no
+ * chance of hitting 60fps, so they are each turned into separate Response
+ * UEs. The track-pad causes MouseWheel events that are much closer
+ * together, and are expected to be 60fps, so the first event in a sequence
+ * is turned into a Response, and the rest are merged into an Animation.
+ * NB this threshold uses the two events' start times, unlike
+ * ProtoExpectation.isNear, which compares the end time of the previous event
+ * with the start time of the next.
+ */
+ function handleMouseWheelEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ let currentPE = undefined;
+ let prevEvent_ = undefined;
+ forEventTypesIn(
+ sortedInputEvents, MOUSE_WHEEL_TYPE_NAMES, function(event) {
+ // Switch prevEvent in one place so that we can early-return later.
+ const prevEvent = prevEvent_;
+ prevEvent_ = event;
+
+ if (currentPE &&
+ (prevEvent.start + MOUSE_WHEEL_THRESHOLD_MS) >= event.start) {
+ if (currentPE.type === ProtoExpectation.ANIMATION_TYPE) {
+ currentPE.pushEvent(event);
+ } else {
+ currentPE = new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,
+ INITIATOR_TYPE.MOUSE_WHEEL);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+ return;
+ }
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.MOUSE_WHEEL);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ });
+ return protoExpectations;
+ }
+
+ /**
+ * Down events followed closely by Up events are click Responses, but the
+ * Response doesn't start until the Up event.
+ *
+ * RRR
+ * DDD UUU
+ *
+ * If there are any Move events in between a Down and an Up, then the Down
+ * and the first Move are a Response, then the rest of the Moves are an
+ * Animation:
+ *
+ * RRRRRRRAAAAAAAAAAAAAAAAAAAA
+ * DDD MMM MMM MMM MMM MMM UUU
+ */
+ function handleMouseDragEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ let currentPE = undefined;
+ let mouseDownEvent = undefined;
+ forEventTypesIn(
+ sortedInputEvents, MOUSE_DRAG_TYPE_NAMES, function(event) {
+ switch (event.typeName) {
+ case INPUT_TYPE.MOUSE_DOWN:
+ if (causedFrame(event)) {
+ const pe = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.MOUSE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ } else {
+ // Responses typically don't start until the mouse up event.
+ // Add this MouseDown to the Response that starts at the
+ // MouseUp.
+ mouseDownEvent = event;
+ }
+ break;
+
+ // There may be more than 100ms between the start of the mouse
+ // down and the start of the mouse up. Chrome and the web don't
+ // start to respond until the mouse up. Responses start deducting
+ // comfort at 100ms duration. If more than that 100ms duration is
+ // burned through while waiting for the user to release the mouse
+ // button, then ResponseExpectation will unfairly start deducting
+ // comfort before Chrome even has a mouse up to respond to. It is
+ // technically possible for a site to afford one response on mouse
+ // down and another on mouse up, but that is an edge case. The
+ // vast majority of mouse downs are not responses.
+
+ case INPUT_TYPE.MOUSE_MOVE:
+ if (!causedFrame(event)) {
+ // Ignore MouseMoves that do not affect the screen. They are not
+ // part of an interaction record by definition.
+ const pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ } else if (!currentPE ||
+ !currentPE.isNear(event, MOUSE_MOVE_THRESHOLD_MS)) {
+ // The first MouseMove after a MouseDown or after a while is a
+ // Response.
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.MOUSE);
+ currentPE.pushEvent(event);
+ if (mouseDownEvent) {
+ currentPE.associatedEvents.push(mouseDownEvent);
+ mouseDownEvent = undefined;
+ }
+ protoExpectations.push(currentPE);
+ } else {
+ // Merge this event into an Animation.
+ if (currentPE.type === ProtoExpectation.ANIMATION_TYPE) {
+ currentPE.pushEvent(event);
+ } else {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.MOUSE);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+ }
+ break;
+
+ case INPUT_TYPE.MOUSE_UP:
+ if (!mouseDownEvent) {
+ const pe = new ProtoExpectation(
+ causedFrame(event) ? ProtoExpectation.RESPONSE_TYPE :
+ ProtoExpectation.IGNORED_TYPE,
+ INITIATOR_TYPE.MOUSE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ break;
+ }
+
+ if (currentPE) {
+ currentPE.pushEvent(event);
+ } else {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.MOUSE);
+ if (mouseDownEvent) {
+ currentPE.associatedEvents.push(mouseDownEvent);
+ }
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+ mouseDownEvent = undefined;
+ currentPE = undefined;
+ break;
+ }
+ });
+ if (mouseDownEvent) {
+ currentPE = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
+ currentPE.pushEvent(mouseDownEvent);
+ protoExpectations.push(currentPE);
+ }
+ return protoExpectations;
+ }
+
+ /**
+ * Solitary Tap events are simple Responses:
+ *
+ * RRR
+ * TTT
+ *
+ * TapDowns are part of Responses.
+ *
+ * RRRRRRR
+ * DDD TTT
+ *
+ * TapCancels are part of Responses, which seems strange. They always go
+ * with scrolls, so they'll probably be merged with scroll Responses.
+ * TapCancels can take a significant amount of time and account for a
+ * significant amount of work, which should be grouped with the scroll UEs
+ * if possible.
+ *
+ * RRRRRRR
+ * DDD CCC
+ **/
+ function handleTapResponseEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ let currentPE = undefined;
+ forEventTypesIn(sortedInputEvents, TAP_TYPE_NAMES, function(event) {
+ switch (event.typeName) {
+ case INPUT_TYPE.TAP_DOWN:
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.TAP);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ break;
+
+ case INPUT_TYPE.TAP:
+ if (currentPE) {
+ currentPE.pushEvent(event);
+ } else {
+ // Sometimes we get Tap events with no TapDown, sometimes we get
+ // TapDown events. Handle both.
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.TAP);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+ currentPE = undefined;
+ break;
+
+ case INPUT_TYPE.TAP_CANCEL:
+ if (!currentPE) {
+ const pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ break;
+ }
+
+ if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
+ currentPE.pushEvent(event);
+ } else {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.TAP);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+ currentPE = undefined;
+ break;
+ }
+ });
+ return protoExpectations;
+ }
+
+ /**
+ * The PinchBegin and the first PinchUpdate comprise a Response, then the
+ * rest of the PinchUpdates comprise an Animation.
+ *
+ * RRRRRRRAAAAAAAAAAAAAAAAAAAA
+ * BBB UUU UUU UUU UUU UUU EEE
+ */
+ function handlePinchEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ let currentPE = undefined;
+ let sawFirstUpdate = false;
+ const modelBounds = modelHelper.model.bounds;
+ forEventTypesIn(sortedInputEvents, PINCH_TYPE_NAMES, function(event) {
+ switch (event.typeName) {
+ case INPUT_TYPE.PINCH_BEGIN:
+ if (currentPE &&
+ currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
+ currentPE.pushEvent(event);
+ break;
+ }
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.PINCH);
+ currentPE.pushEvent(event);
+ currentPE.isAnimationBegin = true;
+ protoExpectations.push(currentPE);
+ sawFirstUpdate = false;
+ break;
+
+ case INPUT_TYPE.PINCH_UPDATE:
+ // Like ScrollUpdates, the Begin and the first Update constitute a
+ // Response, then the rest of the Updates constitute an Animation
+ // that begins when the Response ends. If the user pauses in the
+ // middle of an extended pinch gesture, then multiple Animations
+ // will be created.
+ if (!currentPE ||
+ ((currentPE.type === ProtoExpectation.RESPONSE_TYPE) &&
+ sawFirstUpdate) ||
+ !currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.PINCH);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ } else {
+ currentPE.pushEvent(event);
+ sawFirstUpdate = true;
+ }
+ break;
+
+ case INPUT_TYPE.PINCH_END:
+ if (currentPE) {
+ currentPE.pushEvent(event);
+ } else {
+ const pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ }
+ currentPE = undefined;
+ break;
+ }
+ });
+ return protoExpectations;
+ }
+
+ /**
+ * Flings are defined by 3 types of events: FlingStart, FlingCancel, and the
+ * renderer fling event. Flings do not begin with a Response. Flings end
+ * either at the beginning of a FlingCancel, or at the end of the renderer
+ * fling event.
+ *
+ * AAAAAAAAAAAAAAAAAAAAAAAAAA
+ * SSS
+ * RRRRRRRRRRRRRRRRRRRRRR
+ *
+ *
+ * AAAAAAAAAAA
+ * SSS CCC
+ */
+ function handleFlingEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ let currentPE = undefined;
+
+ function isRendererFling(event) {
+ return event.title === RENDERER_FLING_TITLE;
+ }
+ const browserHelper = modelHelper.browserHelper;
+ const flingEvents = browserHelper.getAllAsyncSlicesMatching(
+ isRendererFling);
+
+ forEventTypesIn(sortedInputEvents, FLING_TYPE_NAMES, function(event) {
+ flingEvents.push(event);
+ });
+ flingEvents.sort(compareEvents);
+
+ flingEvents.forEach(function(event) {
+ if (event.title === RENDERER_FLING_TITLE) {
+ if (currentPE) {
+ currentPE.pushEvent(event);
+ } else {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.FLING);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+ return;
+ }
+
+ switch (event.typeName) {
+ case INPUT_TYPE.FLING_START:
+ if (currentPE) {
+ warn({
+ type: 'UserModelBuilder',
+ message: 'Unexpected FlingStart',
+ showToUser: false,
+ });
+ currentPE.pushEvent(event);
+ } else {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.FLING);
+ currentPE.pushEvent(event);
+ // Set end to an invalid value so that it can be noticed and fixed
+ // later.
+ currentPE.end = 0;
+ protoExpectations.push(currentPE);
+ }
+ break;
+
+ case INPUT_TYPE.FLING_CANCEL:
+ if (currentPE) {
+ currentPE.pushEvent(event);
+ // FlingCancel events start when TouchStart events start, which is
+ // typically when a Response starts. FlingCancel events end when
+ // chrome acknowledges them, not when they update the screen. So
+ // there might be one more frame during the FlingCancel, after
+ // this Animation ends. That won't affect the scoring algorithms,
+ // and it will make the UEs look more correct if they don't
+ // overlap unnecessarily.
+ currentPE.end = event.start;
+ currentPE = undefined;
+ } else {
+ const pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ }
+ break;
+ }
+ });
+ // If there was neither a FLING_CANCEL nor a renderer fling after the
+ // FLING_START, then assume that it ends at the end of the model, so set
+ // the end of currentPE to the end of the model.
+ if (currentPE && !currentPE.end) {
+ currentPE.end = modelHelper.model.bounds.max;
+ }
+ return protoExpectations;
+ }
+
+ /**
+ * The TouchStart and the first TouchMove comprise a Response, then the
+ * rest of the TouchMoves comprise an Animation.
+ *
+ * RRRRRRRAAAAAAAAAAAAAAAAAAAA
+ * SSS MMM MMM MMM MMM MMM EEE
+ *
+ * If there are no TouchMove events in between a TouchStart and a TouchEnd,
+ * then it's just a Response.
+ *
+ * RRRRRRR
+ * SSS EEE
+ */
+ function handleTouchEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ let currentPE = undefined;
+ let sawFirstMove = false;
+ forEventTypesIn(sortedInputEvents, TOUCH_TYPE_NAMES, function(event) {
+ switch (event.typeName) {
+ case INPUT_TYPE.TOUCH_START:
+ if (currentPE) {
+ // NB: currentPE will probably be merged with something from
+ // handlePinchEvents(). Multiple TouchStart events without an
+ // intervening TouchEnd logically implies that multiple fingers
+ // are on the screen, so this is probably a pinch gesture.
+ currentPE.pushEvent(event);
+ } else {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.TOUCH);
+ currentPE.pushEvent(event);
+ currentPE.isAnimationBegin = true;
+ protoExpectations.push(currentPE);
+ sawFirstMove = false;
+ }
+ break;
+
+ case INPUT_TYPE.TOUCH_MOVE:
+ if (!currentPE) {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.TOUCH);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ break;
+ }
+
+ // Like Scrolls and Pinches, the Response is defined to be the
+ // TouchStart plus the first TouchMove, then the rest of the
+ // TouchMoves constitute an Animation.
+ if ((sawFirstMove &&
+ (currentPE.type === ProtoExpectation.RESPONSE_TYPE)) ||
+ !currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
+ // If there's already a touchmove in the currentPE or it's not
+ // near event, then finish it and start a new animation.
+ const prevEnd = currentPE.end;
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.TOUCH);
+ currentPE.pushEvent(event);
+ // It's possible for there to be a gap between TouchMoves, but
+ // that doesn't mean that there should be an Idle UE there.
+ currentPE.start = prevEnd;
+ protoExpectations.push(currentPE);
+ } else {
+ currentPE.pushEvent(event);
+ sawFirstMove = true;
+ }
+ break;
+
+ case INPUT_TYPE.TOUCH_END:
+ if (!currentPE) {
+ const pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ break;
+ }
+ if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
+ currentPE.pushEvent(event);
+ } else {
+ const pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ }
+ currentPE = undefined;
+ break;
+ }
+ });
+ return protoExpectations;
+ }
+
+ /**
+ * The first ScrollBegin and the first ScrollUpdate comprise a Response,
+ * then the rest comprise an Animation.
+ *
+ * RRRRRRRAAAAAAAAAAAAAAAAAAAA
+ * BBB UUU UUU UUU UUU UUU EEE
+ */
+ function handleScrollEvents(modelHelper, sortedInputEvents, warn) {
+ const protoExpectations = [];
+ let currentPE = undefined;
+ let sawFirstUpdate = false;
+ forEventTypesIn(sortedInputEvents, SCROLL_TYPE_NAMES, function(event) {
+ switch (event.typeName) {
+ case INPUT_TYPE.SCROLL_BEGIN:
+ // Always begin a new PE even if there already is one, unlike
+ // PinchBegin.
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.SCROLL);
+ currentPE.pushEvent(event);
+ currentPE.isAnimationBegin = true;
+ protoExpectations.push(currentPE);
+ sawFirstUpdate = false;
+ break;
+
+ case INPUT_TYPE.SCROLL_UPDATE:
+ if (currentPE) {
+ if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS) &&
+ ((currentPE.type === ProtoExpectation.ANIMATION_TYPE) ||
+ !sawFirstUpdate)) {
+ currentPE.pushEvent(event);
+ sawFirstUpdate = true;
+ } else {
+ currentPE = new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,
+ INITIATOR_TYPE.SCROLL);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+ } else {
+ // ScrollUpdate without ScrollBegin.
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.SCROLL);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+ break;
+
+ case INPUT_TYPE.SCROLL_END:
+ if (!currentPE) {
+ warn({
+ type: 'UserModelBuilder',
+ message: 'Unexpected ScrollEnd',
+ showToUser: false,
+ });
+ const pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
+ pe.pushEvent(event);
+ protoExpectations.push(pe);
+ break;
+ }
+ currentPE.pushEvent(event);
+ break;
+ }
+ });
+ return protoExpectations;
+ }
+
+ /**
+ * Returns proto expectations for video animation events.
+ *
+ * Video animations represent video playback, and are based on
+ * VideoPlayback async events (going from the VideoFrameCompositor::Start
+ * to VideoFrameCompositor::Stop calls)
+ */
+ function handleVideoAnimations(modelHelper, sortedInputEvents, warn) {
+ const events = [];
+ for (const pid in modelHelper.rendererHelpers) {
+ for (const tid in modelHelper.rendererHelpers[pid].process.threads) {
+ for (const asyncSlice of
+ modelHelper.rendererHelpers[pid].process.threads[tid]
+ .asyncSliceGroup.slices) {
+ if (asyncSlice.title === PLAYBACK_EVENT_TITLE) {
+ events.push(asyncSlice);
+ }
+ }
+ }
+ }
+
+ events.sort(tr.importer.compareEvents);
+
+ const protoExpectations = [];
+ for (const event of events) {
+ const currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.VIDEO);
+ currentPE.start = event.start;
+ currentPE.end = event.end;
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ }
+
+ return protoExpectations;
+ }
+
+ /**
+ * Returns proto expectations for VR animation events.
+ */
+ function handleVrAnimations(modelHelper, sortedInputEvents, warn) {
+ const events = [];
+
+ // Find all the processes we should check
+ const processes = [];
+ if (typeof modelHelper.gpuHelper !== 'undefined') {
+ processes.push(modelHelper.gpuHelper.process);
+ }
+ for (const helper of Object.values(modelHelper.rendererHelpers)) {
+ processes.push(helper.process);
+ }
+ for (const helper of Object.values(modelHelper.browserHelpers)) {
+ processes.push(helper.process);
+ }
+
+ // Add all counter samples to the list of events we care about
+ let vrCounterStart = Number.MAX_SAFE_INTEGER;
+ let vrEventStart = Number.MAX_SAFE_INTEGER;
+ for (const proc of processes) {
+ for (const [counterName, counterSeries] of
+ Object.entries(proc.counters)) {
+ if (VR_COUNTER_NAMES.includes(counterName)) {
+ for (const series of counterSeries.series) {
+ for (const sample of series.samples) {
+ events.push(sample);
+ vrCounterStart = Math.min(vrCounterStart, sample.timestamp);
+ }
+ }
+ }
+ }
+ for (const thread of Object.values(proc.threads)) {
+ for (const container of thread.childEventContainers()) {
+ for (const slice of container.slices) {
+ if (VR_EVENT_NAMES.includes(slice.title)) {
+ events.push(slice);
+ vrEventStart = Math.min(vrEventStart, slice.start);
+ }
+ }
+ }
+ }
+ }
+
+ if (events.length === 0) {
+ return [];
+ }
+
+ events.sort(function(x, y) {
+ if (x.range.min !== y.range.min) {
+ return x.range.min - y.range.min;
+ }
+ return x.guid - y.guid;
+ });
+
+ vrCounterStart = (vrCounterStart === Number.MAX_SAFE_INTEGER) ?
+ 0 : vrCounterStart;
+ vrEventStart = (vrEventStart === Number.MAX_SAFE_INTEGER) ?
+ 0 : vrEventStart;
+ const vrAnimationStart = Math.max(vrCounterStart, vrEventStart) +
+ VR_RESPONSE_MS;
+ const responsePE = new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,
+ INITIATOR_TYPE.VR);
+ const animationPE = new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,
+ INITIATOR_TYPE.VR);
+ let lastResponseEvent;
+
+ for (const event of events) {
+ // Categorize the first 1s of VR time as entry/response
+ // TODO(bsheedy): Make this smarter by basing response duration off trace
+ // data instead of a fixed duration
+ if (event.range.min < vrAnimationStart) {
+ if (event instanceof tr.model.CounterSample) {
+ responsePE.pushSample(event);
+ } else {
+ responsePE.pushEvent(event);
+ }
+ lastResponseEvent = event;
+ } else {
+ if (event instanceof tr.model.CounterSample) {
+ animationPE.pushSample(event);
+ } else {
+ animationPE.pushEvent(event);
+ }
+ }
+ }
+
+ // Make sure that there isn't a gap between the two expectations
+ if (lastResponseEvent instanceof tr.model.CounterSample) {
+ animationPE.pushSample(lastResponseEvent);
+ } else {
+ animationPE.pushEvent(lastResponseEvent);
+ }
+ return [responsePE, animationPE];
+ }
+
+ /**
+ * CSS Animations are merged into AnimationExpectations when they intersect.
+ */
+ function handleCSSAnimations(modelHelper, sortedInputEvents, warn) {
+ // First find all the top-level CSS Animation async events.
+ const animationEvents = modelHelper.browserHelper.
+ getAllAsyncSlicesMatching(function(event) {
+ return ((event.title === CSS_ANIMATION_TITLE) &&
+ event.isTopLevel &&
+ (event.duration > 0));
+ });
+
+
+ // Time ranges where animations are actually running will be collected here.
+ // Each element will contain {min, max, animation}.
+ const animationRanges = [];
+
+ // This helper function will be called when a time range is found
+ // during which the animation is actually running.
+ function pushAnimationRange(start, end, animation) {
+ const range = tr.b.math.Range.fromExplicitRange(start, end);
+ range.animation = animation;
+ animationRanges.push(range);
+ }
+
+ animationEvents.forEach(function(animation) {
+ if (animation.subSlices.length === 0) {
+ pushAnimationRange(animation.start, animation.end, animation);
+ } else {
+ // Now run a state machine over the animation's subSlices, which
+ // indicate the animations running/paused/finished states, in order to
+ // find ranges where the animation was actually running.
+ let start = undefined;
+ animation.subSlices.forEach(function(sub) {
+ if ((sub.args.data.state === 'running') &&
+ (start === undefined)) {
+ // It's possible for the state to alternate between running and
+ // pending, but the animation is still running in that case,
+ // so only set start if the state is changing from one of the halted
+ // states.
+ start = sub.start;
+ } else if ((sub.args.data.state === 'paused') ||
+ (sub.args.data.state === 'idle') ||
+ (sub.args.data.state === 'finished')) {
+ if (start === undefined) {
+ // An animation was already running when the trace started.
+ // (Actually, it's possible that the animation was in the 'idle'
+ // state when tracing started, but that should be rare, and will
+ // be fixed when async events are buffered.)
+ // http: //crbug.com/565627
+ start = modelHelper.model.bounds.min;
+ }
+
+ pushAnimationRange(start, sub.start, animation);
+ start = undefined;
+ }
+ });
+
+ // An animation was still running when the
+ // top-level animation event ended.
+ if (start !== undefined) {
+ pushAnimationRange(start, animation.end, animation);
+ }
+ }
+ });
+
+ // Now we have a set of time ranges when css animations were actually
+ // running.
+ // Leave merging intersecting animations to mergeIntersectingAnimations(),
+ // after findFrameEventsForAnimations removes frame-less animations.
+
+ return animationRanges.map(function(range) {
+ const protoExpectation = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.CSS);
+ protoExpectation.start = range.min;
+ protoExpectation.end = range.max;
+ protoExpectation.associatedEvents.push(range.animation);
+ return protoExpectation;
+ });
+ }
+
+ /**
+ * Get all the events (prepareMailbox and serviceScriptedAnimations)
+ * relevant to WebGL. Note that modelHelper is the helper object containing
+ * the model, and mailboxEvents and animationEvents are arrays where the
+ * events are being pushed into (DrawingBuffer::prepareMailbox events go
+ * into mailboxEvents; PageAnimator::serviceScriptedAnimations events go
+ * into animationEvents). The function does not return anything but
+ * modifies mailboxEvents and animationEvents.
+ */
+ function findWebGLEvents(modelHelper, mailboxEvents, animationEvents) {
+ for (const event of modelHelper.model.getDescendantEvents()) {
+ if (event.title === 'DrawingBuffer::prepareMailbox') {
+ mailboxEvents.push(event);
+ } else if (event.title === 'PageAnimator::serviceScriptedAnimations') {
+ animationEvents.push(event);
+ }
+ }
+ }
+
+ /**
+ * Returns a list of events in mailboxEvents that have an event in
+ * animationEvents close by (within ANIMATION_MERGE_THRESHOLD_MS).
+ */
+ function findMailboxEventsNearAnimationEvents(
+ mailboxEvents, animationEvents) {
+ if (animationEvents.length === 0) return [];
+
+ mailboxEvents.sort(compareEvents);
+ animationEvents.sort(compareEvents);
+ const animationIterator = animationEvents[Symbol.iterator]();
+ let animationEvent = animationIterator.next().value;
+
+ const filteredEvents = [];
+
+ // We iterate through the mailboxEvents. With each event, we check if
+ // there is a animationEvent near it, and if so, add it to the result.
+ for (const event of mailboxEvents) {
+ // If the current animationEvent is too far before the mailboxEvent,
+ // we advance until we get to the next animationEvent that is not too
+ // far before the animationEvent.
+ while (animationEvent &&
+ (animationEvent.start < (
+ event.start - ANIMATION_MERGE_THRESHOLD_MS))) {
+ animationEvent = animationIterator.next().value;
+ }
+
+ // If there aren't any more animationEvents, then that means all the
+ // remaining mailboxEvents are too far after the animationEvents, so
+ // we can quit now.
+ if (!animationEvent) break;
+
+ // If there's a animationEvent close to the mailboxEvent, then we push
+ // the current mailboxEvent onto the stack.
+ if (animationEvent.start < (event.start + ANIMATION_MERGE_THRESHOLD_MS)) {
+ filteredEvents.push(event);
+ }
+ }
+ return filteredEvents;
+ }
+
+ /**
+ * Merge consecutive mailbox events into a ProtoExpectation. Note: Only
+ * the drawingBuffer::prepareMailbox events will end up in the
+ * associatedEvents. The PageAnimator::serviceScriptedAnimations events
+ * will not end up in the associatedEvents.
+ */
+ function createProtoExpectationsFromMailboxEvents(mailboxEvents) {
+ const protoExpectations = [];
+ let currentPE = undefined;
+ for (const event of mailboxEvents) {
+ if (currentPE === undefined || !currentPE.isNear(
+ event, ANIMATION_MERGE_THRESHOLD_MS)) {
+ currentPE = new ProtoExpectation(
+ ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.WEBGL);
+ currentPE.pushEvent(event);
+ protoExpectations.push(currentPE);
+ } else {
+ currentPE.pushEvent(event);
+ }
+ }
+ return protoExpectations;
+ }
+
+ // WebGL animations are identified by the DrawingBuffer::prepareMailbox
+ // and PageAnimator::serviceScriptedAnimations events (one of each per frame)
+ // and consecutive frames are merged into the same animation.
+ function handleWebGLAnimations(modelHelper, sortedInputEvents, warn) {
+ // Get the prepareMailbox and scriptedAnimation events.
+ const prepareMailboxEvents = [];
+ const scriptedAnimationEvents = [];
+
+ findWebGLEvents(modelHelper, prepareMailboxEvents, scriptedAnimationEvents);
+ const webGLMailboxEvents = findMailboxEventsNearAnimationEvents(
+ prepareMailboxEvents, scriptedAnimationEvents);
+
+ return createProtoExpectationsFromMailboxEvents(webGLMailboxEvents);
+ }
+
+
+ function postProcessProtoExpectations(modelHelper, protoExpectations) {
+ // protoExpectations is input only. Returns a modified set of
+ // ProtoExpectations. The order is important.
+ protoExpectations = findFrameEventsForAnimations(
+ modelHelper, protoExpectations);
+ protoExpectations = mergeIntersectingResponses(protoExpectations);
+ protoExpectations = mergeIntersectingAnimations(protoExpectations);
+ protoExpectations = fixResponseAnimationStarts(protoExpectations);
+ protoExpectations = fixTapResponseTouchAnimations(protoExpectations);
+ return protoExpectations;
+ }
+
+ /**
+ * TouchStarts happen at the same time as ScrollBegins.
+ * It's easier to let multiple handlers create multiple overlapping
+ * Responses and then merge them, rather than make the handlers aware of the
+ * other handlers' PEs.
+ *
+ * For example:
+ * RR
+ * RRR -> RRRRR
+ * RR
+ *
+ * protoExpectations is input only.
+ * Returns a modified set of ProtoExpectations.
+ */
+ function mergeIntersectingResponses(protoExpectations) {
+ const newPEs = [];
+ while (protoExpectations.length) {
+ const pe = protoExpectations.shift();
+ newPEs.push(pe);
+
+ // Only consider Responses for now.
+ if (pe.type !== ProtoExpectation.RESPONSE_TYPE) continue;
+
+ for (let i = 0; i < protoExpectations.length; ++i) {
+ const otherPE = protoExpectations[i];
+
+ if (otherPE.type !== pe.type) continue;
+
+ if (!otherPE.intersects(pe)) continue;
+
+ // Don't merge together Responses of the same type.
+ // If handleTouchEvents wanted two of its Responses to be merged, then
+ // it would have made them that way to begin with.
+ const typeNames = pe.associatedEvents.map(function(event) {
+ return event.typeName;
+ });
+ if (otherPE.containsTypeNames(typeNames)) continue;
+
+ pe.merge(otherPE);
+ protoExpectations.splice(i, 1);
+
+ // Don't skip the next otherPE!
+ --i;
+ }
+ }
+ return newPEs;
+ }
+
+ /**
+ * An animation is simply an expectation of 60fps between start and end.
+ * If two animations overlap, then merge them.
+ *
+ * For example:
+ * AA
+ * AAA -> AAAAA
+ * AA
+ *
+ * protoExpectations is input only.
+ * Returns a modified set of ProtoExpectations.
+ */
+ function mergeIntersectingAnimations(protoExpectations) {
+ const newPEs = [];
+ while (protoExpectations.length) {
+ const pe = protoExpectations.shift();
+ newPEs.push(pe);
+
+ // Only consider Animations for now.
+ if (pe.type !== ProtoExpectation.ANIMATION_TYPE) continue;
+
+ const isCSS = pe.initiatorType === INITIATOR_TYPE.CSS;
+ const isFling = pe.containsTypeNames([INPUT_TYPE.FLING_START]);
+ const isVideo = pe.initiatorType === INITIATOR_TYPE.VIDEO;
+
+ for (let i = 0; i < protoExpectations.length; ++i) {
+ const otherPE = protoExpectations[i];
+
+ if (otherPE.type !== pe.type) continue;
+
+ // Don't merge some animation types with others.
+ if ((isCSS && otherPE.initiatorType !== INITIATOR_TYPE.CSS) ||
+ isFling !== otherPE.containsTypeNames([INPUT_TYPE.FLING_START]) ||
+ isVideo && otherPE.initiatorType !== INITIATOR_TYPE.VIDEO ||
+ otherPE.initiatorType === INITIATOR_TYPE.VR) {
+ continue;
+ }
+
+ if (isCSS) {
+ if (!pe.isNear(otherPE, ANIMATION_MERGE_THRESHOLD_MS)) {
+ continue;
+ }
+ } else if (!otherPE.intersects(pe)) {
+ continue;
+ }
+
+ pe.merge(otherPE);
+ protoExpectations.splice(i, 1);
+ // Don't skip the next otherPE!
+ --i;
+ }
+ }
+ return newPEs;
+ }
+
+ /**
+ * The ends of responses frequently overlap the starts of animations.
+ * Fix the animations to reflect the fact that the user can only start to
+ * expect 60fps after the response.
+ *
+ * For example:
+ * RRR -> RRRAA
+ * AAAA
+ *
+ * protoExpectations is input only.
+ * Returns a modified set of ProtoExpectations.
+ */
+ function fixResponseAnimationStarts(protoExpectations) {
+ protoExpectations.forEach(function(ape) {
+ // Only consider animations for now.
+ if (ape.type !== ProtoExpectation.ANIMATION_TYPE) {
+ return;
+ }
+
+ protoExpectations.forEach(function(rpe) {
+ // Only consider responses for now.
+ if (rpe.type !== ProtoExpectation.RESPONSE_TYPE) {
+ return;
+ }
+
+ // Only consider responses that end during the animation.
+ if (!ape.containsTimestampInclusive(rpe.end)) {
+ return;
+ }
+
+ // Ignore Responses that are entirely contained by the animation.
+ if (ape.containsTimestampInclusive(rpe.start)) {
+ return;
+ }
+
+ // Move the animation start to the response end.
+ ape.start = rpe.end;
+ // Remove any frames that were part of the animation but are now before
+ // the animation.
+ if (ape.associatedEvents !== undefined) {
+ ape.associatedEvents = ape.associatedEvents.filter(
+ e => (!isImplFrameEvent(e) || e.start >= ape.start));
+ }
+ });
+ });
+ return protoExpectations;
+ }
+
+ function isImplFrameEvent(event) {
+ return event.title === tr.model.helpers.IMPL_RENDERING_STATS;
+ }
+
+ /**
+ * Merge Tap Responses that overlap Touch-only Animations.
+ * https: *github.com/catapult-project/catapult/issues/1431
+ */
+ function fixTapResponseTouchAnimations(protoExpectations) {
+ function isTapResponse(pe) {
+ return (pe.type === ProtoExpectation.RESPONSE_TYPE) &&
+ pe.containsTypeNames([INPUT_TYPE.TAP]);
+ }
+ function isTouchAnimation(pe) {
+ return (pe.type === ProtoExpectation.ANIMATION_TYPE) &&
+ pe.containsTypeNames([INPUT_TYPE.TOUCH_MOVE]) &&
+ !pe.containsTypeNames([
+ INPUT_TYPE.SCROLL_UPDATE, INPUT_TYPE.PINCH_UPDATE]);
+ }
+ const newPEs = [];
+ while (protoExpectations.length) {
+ const pe = protoExpectations.shift();
+ newPEs.push(pe);
+
+ // protoExpectations are sorted by start time, and we don't know whether
+ // the Tap Response or the Touch Animation will be first
+ const peIsTapResponse = isTapResponse(pe);
+ const peIsTouchAnimation = isTouchAnimation(pe);
+ if (!peIsTapResponse && !peIsTouchAnimation) {
+ continue;
+ }
+
+ for (let i = 0; i < protoExpectations.length; ++i) {
+ const otherPE = protoExpectations[i];
+
+ if (!otherPE.intersects(pe)) continue;
+
+ if (peIsTapResponse && !isTouchAnimation(otherPE)) continue;
+
+ if (peIsTouchAnimation && !isTapResponse(otherPE)) continue;
+
+ // pe might be the Touch Animation, but the merged ProtoExpectation
+ // should be a Response.
+ pe.type = ProtoExpectation.RESPONSE_TYPE;
+
+ pe.merge(otherPE);
+ protoExpectations.splice(i, 1);
+ // Don't skip the next otherPE!
+ --i;
+ }
+ }
+ return newPEs;
+ }
+
+ function findFrameEventsForAnimations(modelHelper, protoExpectations) {
+ const newPEs = [];
+ const frameEventsByPid = getSortedFrameEventsByProcess(modelHelper);
+
+ for (const pe of protoExpectations) {
+ if (pe.type !== ProtoExpectation.ANIMATION_TYPE) {
+ newPEs.push(pe);
+ continue;
+ }
+
+ const frameEvents = [];
+ for (const pid of Object.keys(modelHelper.rendererHelpers)) {
+ const range = tr.b.math.Range.fromExplicitRange(pe.start, pe.end);
+ frameEvents.push.apply(frameEvents,
+ range.filterArray(frameEventsByPid[pid], e => e.start));
+ }
+
+ // If a tree falls in a forest...
+ // If there were not actually any frames while the animation was
+ // running, then it wasn't really an animation, now, was it?
+ // Philosophy aside, the system_health Animation metrics fail hard if
+ // there are no frames in an AnimationExpectation.
+ // Since WebGL and VR animations don't generate this type of frame
+ // event, don't remove them if it's a WebGL or VR animation.
+ if (frameEvents.length === 0 &&
+ !(pe.initiatorType === INITIATOR_TYPE.WEBGL ||
+ pe.initiatorType === INITIATOR_TYPE.VR)) {
+ pe.type = ProtoExpectation.IGNORED_TYPE;
+ newPEs.push(pe);
+ continue;
+ }
+
+ pe.associatedEvents.addEventSet(frameEvents);
+ newPEs.push(pe);
+ }
+
+ return newPEs;
+ }
+
+ /**
+ * Check that none of the handlers accidentally ignored an input event.
+ */
+ function checkAllInputEventsHandled(
+ modelHelper, sortedInputEvents, protoExpectations, warn) {
+ const handledEvents = [];
+ protoExpectations.forEach(function(protoExpectation) {
+ protoExpectation.associatedEvents.forEach(function(event) {
+ // Ignore CSS Animations that might have multiple active ranges.
+ if ((event.title === CSS_ANIMATION_TITLE) &&
+ (event.subSlices.length > 0)) {
+ return;
+ }
+
+ if ((handledEvents.indexOf(event) >= 0) &&
+ (!isImplFrameEvent(event))) {
+ warn({
+ type: 'UserModelBuilder',
+ message: `double-handled event: ${event.typeName} @ ${event.start}`,
+ showToUser: false,
+ });
+ return;
+ }
+ handledEvents.push(event);
+ });
+ });
+
+ sortedInputEvents.forEach(function(event) {
+ if (handledEvents.indexOf(event) < 0) {
+ warn({
+ type: 'UserModelBuilder',
+ message: `double-handled event: ${event.typeName} @ ${event.start}`,
+ showToUser: false,
+ });
+ }
+ });
+ }
+
+ /**
+ * Find ProtoExpectations, post-process them, convert them to real UEs.
+ */
+ function findInputExpectations(modelHelper) {
+ // Prevent helper functions from producing too many import warnings.
+ let warning;
+ function warn(w) {
+ // Keep only the first warning.
+ if (warning) return;
+ warning = w;
+ }
+
+ const sortedInputEvents = getSortedInputEvents(modelHelper);
+ let protoExpectations = findProtoExpectations(
+ modelHelper, sortedInputEvents, warn);
+ protoExpectations = postProcessProtoExpectations(
+ modelHelper, protoExpectations);
+ checkAllInputEventsHandled(
+ modelHelper, sortedInputEvents, protoExpectations, warn);
+
+ if (warning) modelHelper.model.importWarning(warning);
+
+ const expectations = [];
+ protoExpectations.forEach(function(protoExpectation) {
+ const ir = protoExpectation.createInteractionRecord(modelHelper.model);
+ if (ir) {
+ expectations.push(ir);
+ }
+ });
+ return expectations;
+ }
+
+ return {
+ findInputExpectations,
+ compareEvents,
+ CSS_ANIMATION_TITLE,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html b/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html
new file mode 100644
index 00000000000..a5a3265e0b8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html
@@ -0,0 +1,325 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/extras/chrome/time_to_interactive.html">
+<link rel="import" href="/tracing/model/user_model/load_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.importer', function() {
+ const LONG_TASK_THRESHOLD_MS = 50;
+
+ const IGNORE_URLS = [
+ // Blank URLs correspond to initial empty loads and we want to ignore
+ // them.
+ '',
+ 'about:blank',
+ ];
+
+
+ /**
+ * @param {!tr.model.Process} process
+ * @param {!tr.b.math.Range} range
+ * @return {Array.<tr.model.Event>} An array of network events of a process
+ * and that are intersecting a range.
+ */
+ function getNetworkEventsInRange(process, range) {
+ const networkEvents = [];
+ for (const thread of Object.values(process.threads)) {
+ const threadHelper = new tr.model.helpers.ChromeThreadHelper(thread);
+ const events = threadHelper.getNetworkEvents();
+ for (const event of events) {
+ if (range.intersectsExplicitRangeInclusive(event.start, event.end)) {
+ networkEvents.push(event);
+ }
+ }
+ }
+ return networkEvents;
+ }
+
+ function findFrameLoaderSnapshotAt(rendererHelper, frameIdRef, ts) {
+ const objects = rendererHelper.process.objects;
+ const frameLoaderInstances = objects.instancesByTypeName_.FrameLoader;
+ if (frameLoaderInstances === undefined) return undefined;
+
+ let snapshot;
+ for (const instance of frameLoaderInstances) {
+ if (!instance.isAliveAt(ts)) continue;
+ const maybeSnapshot = instance.getSnapshotAt(ts);
+ if (frameIdRef !== maybeSnapshot.args.frame.id_ref) continue;
+ snapshot = maybeSnapshot;
+ }
+
+ return snapshot;
+ }
+
+ function findFirstMeaningfulPaintCandidates(rendererHelper) {
+ const candidatesForFrameId = {};
+ for (const ev of rendererHelper.process.getDescendantEvents()) {
+ if (!tr.e.chrome.EventFinderUtils.hasCategoryAndName(
+ ev, 'loading', 'firstMeaningfulPaintCandidate')) {
+ continue;
+ }
+ if (rendererHelper.isTelemetryInternalEvent(ev)) continue;
+ const frameIdRef = ev.args.frame;
+ if (frameIdRef === undefined) continue;
+ let list = candidatesForFrameId[frameIdRef];
+ if (list === undefined) {
+ candidatesForFrameId[frameIdRef] = list = [];
+ }
+ list.push(ev);
+ }
+ return candidatesForFrameId;
+ }
+
+ /**
+ * Returns Time to Interactive and First CPU Idle for the
+ * given parameters. See the time_to_interactive.html module for detailed
+ * description and implementation of these metrics. The two metrics are
+ * computed together in the same function because almost all the computed
+ * parameters, for example list of relevant long tasks, are same for these two
+ * metrics, and this helps avoid duplicate computation.
+ *
+ * @param {tr.model.helpers.ChromeRendererHelper} rendererHelper - Renderer
+ * helper for the renderer of interest.
+ * @param {tr.model.ThreadSlice} navigationStart - The navigation start
+ * event for which loading metrics is being computed.
+ * @param {tr.model.ThreadSlice} fmpEvent - The first meaningful paint
+ * event for which loading metrics is being computed.
+ * @param {tr.model.ThreadSlice} domContentLoadedEndEvent - Event
+ * corresponding to finish of dom content loading
+ * @param {number} searchWindowEnd - Time till when to search for a TTI. This
+ * value is either the start of next navigation or the end of the trace.
+ * @returns {interactiveSample: {number}|undefined,
+ * firstCpuIdleTime: {number}|undefined}
+ */
+ function computeInteractivityMetricSample_(rendererHelper, navigationStart,
+ fmpEvent, domContentLoadedEndEvent, searchWindowEnd) {
+ // Cannot determine TTI if DomContentLoadedEnd was never reached or if
+ // there is no corresponding fmpEvent.
+ if (domContentLoadedEndEvent === undefined || fmpEvent === undefined) {
+ return {interactiveTime: undefined, firstCpuIdleTime: undefined};
+ }
+
+ const firstMeaningfulPaintTime = fmpEvent.start;
+ const mainThreadTasks =
+ tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(
+ rendererHelper.mainThread);
+
+ const longTasks = mainThreadTasks.filter(
+ task => task.duration >= LONG_TASK_THRESHOLD_MS);
+ const longTasksInWindow = longTasks.filter(
+ task => task.range.intersectsExplicitRangeInclusive(
+ firstMeaningfulPaintTime, searchWindowEnd));
+
+ const resourceLoadEvents = getNetworkEventsInRange(rendererHelper.process,
+ tr.b.math.Range.fromExplicitRange(navigationStart.start,
+ searchWindowEnd));
+
+ const firstCpuIdleTime =
+ tr.e.chrome.findFirstCpuIdleTime(
+ firstMeaningfulPaintTime, searchWindowEnd,
+ domContentLoadedEndEvent.start, longTasksInWindow);
+
+ // If we did not find any resource load events, interactiveTime should not
+ // be computed to avoid reporting misleading values.
+ const interactiveTime = resourceLoadEvents.length > 0 ?
+ tr.e.chrome.findInteractiveTime(
+ firstMeaningfulPaintTime, searchWindowEnd,
+ domContentLoadedEndEvent.start, longTasksInWindow,
+ resourceLoadEvents) : undefined;
+
+ return {interactiveTime, firstCpuIdleTime};
+ }
+
+ /* Constructs a loading metrics for the specified navigation start event and
+ * the corresponding fmpEvent and returns a sample including the metrics and
+ * navigationStartEvent, fmpEvent, url and the frameId.
+ *
+ * @param {tr.model.helpers.ChromeRendererHelper} rendererHelper - Renderer
+ * helper for the renderer of interest.
+ * @param {Map.<string, Array<!tr.model.ThreadSlice>>} frameToNavStartEvents -
+ * Map from frame ids to sorted array of navigation start events.
+ * @param {Map.<string, Array<!tr.model.ThreadSlice>>}
+ * frameToDomContentLoadedEndEvents - Map from frame ids to sorted array
+ * of DOMContentLoadedEnd events.
+ * @param {tr.model.ThreadSlice} navigationStart - The navigation start
+ * event for which loading metrics is being computed.
+ * @param {tr.model.ThreadSlice} fmpEvent - The first meaningful paint
+ * event for which loading metrics is being computed.
+ * @param {number} searchWindowEnd - The end of the current navigation either
+ * because new navigation has started or the trace has ended.
+ * @param {string} url - URL of the current main frame document.
+ * @param {number} frameId - fameId.
+ * @returns {{start: {number}, duration: {number},
+ * fmpEvent: {tr.model.ThreadSlice}, navStart: {tr.model.ThreadSlice},
+ * dclEndTime: {tr.model.ThreadSlice}, firstCpuIdleTime: {number}|undefined,
+ * interactiveSample: {number}|undefined, url: {string}, frameId: {number}}}
+ */
+ function constructLoadingExpectation_(rendererHelper,
+ frameToDomContentLoadedEndEvents, navigationStart, fmpEvent,
+ searchWindowEnd, url, frameId) {
+ // Find when dom content has loaded.
+ const dclTimesForFrame =
+ frameToDomContentLoadedEndEvents.get(frameId) || [];
+ const dclSearchRange = tr.b.math.Range.fromExplicitRange(
+ navigationStart.start, searchWindowEnd);
+ const dclTimesInWindow =
+ dclSearchRange.filterArray(dclTimesForFrame, event => event.start);
+ let domContentLoadedEndEvent = undefined;
+ if (dclTimesInWindow.length !== 0) {
+ // TODO(catapult:#3796): Ideally a frame should reach DomContentLoadedEnd
+ // at most once within two navigationStarts, but sometimes there is a
+ // strange DclEnd event immediately following the navigationStart, and
+ // then the 'real' dclEnd happens later. It is not clear how to best
+ // determine the correct dclEnd value. For now, if there are multiple
+ // DclEnd events in the search window, we just pick the last one.
+ domContentLoadedEndEvent =
+ dclTimesInWindow[dclTimesInWindow.length - 1];
+ }
+
+ const {interactiveTime, firstCpuIdleTime} =
+ computeInteractivityMetricSample_(
+ rendererHelper, navigationStart, fmpEvent,
+ domContentLoadedEndEvent, searchWindowEnd);
+
+ const duration = (interactiveTime === undefined) ?
+ searchWindowEnd - navigationStart.start :
+ interactiveTime - navigationStart.start;
+
+ return new tr.model.um.LoadExpectation(
+ rendererHelper.modelHelper.model,
+ tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL, navigationStart.start,
+ duration, rendererHelper.process, navigationStart, fmpEvent,
+ domContentLoadedEndEvent, firstCpuIdleTime, interactiveTime, url,
+ frameId);
+ }
+
+ /**
+ * Computes the loading expectations for a renderer represented by
+ * |rendererHelper| and returns a list of samples. The loading
+ * expectation is the time between navigation start and the time to
+ * be interactive. There will be one load expectation corresponding
+ * to each navigation start for loading main frames.
+ *
+ * Also, computes Time to First Meaningful Paint (TTFMP), and
+ * Time to First CPU Idle (TTFCI) along with time to interactive (TTI)
+ * and returns them along with the load expectation.
+ *
+ * First meaningful paint is the paint following the layout with the highest
+ * "Layout Significance". The Layout Significance is computed inside Blink,
+ * by FirstMeaningfulPaintDetector class. It logs
+ * "firstMeaningfulPaintCandidate" event every time the Layout Significance
+ * marks a record. TTFMP is the time between NavigationStart and the last
+ * firstMeaningfulPaintCandidate event.
+ *
+ * Design doc: https://goo.gl/vpaxv6
+ *
+ * Time to Interactive and Time to First CPU Idle is based on heuristics
+ * involving main thread and network activity, as well as First Meaningful
+ * Paint and DOMContentLoadedEnd event. See time_to_interactive.html module
+ * for detailed description and implementation of these two metrics.
+ */
+ function collectLoadExpectationsForRenderer(
+ rendererHelper) {
+ const samples = [];
+ const frameToNavStartEvents =
+ tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(
+ rendererHelper, 'navigationStart', 'blink.user_timing');
+ const frameToDomContentLoadedEndEvents =
+ tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(
+ rendererHelper, 'domContentLoadedEventEnd', 'blink.user_timing');
+
+ function addSamples(frameIdRef, navigationStart, fmpCandidateEvents,
+ searchWindowEnd, url) {
+ let fmpMarkerEvent =
+ tr.e.chrome.EventFinderUtils.
+ findLastEventStartingOnOrBeforeTimestamp(fmpCandidateEvents,
+ searchWindowEnd);
+ if (fmpMarkerEvent !== undefined &&
+ navigationStart.start > fmpMarkerEvent.start) {
+ // Don't use fmpCandidate if it is not corresponding this navigation.
+ fmpMarkerEvent = undefined;
+ }
+ samples.push(constructLoadingExpectation_(
+ rendererHelper, frameToDomContentLoadedEndEvents, navigationStart,
+ fmpMarkerEvent, searchWindowEnd, url, frameIdRef));
+ }
+
+ const candidatesForFrameId =
+ findFirstMeaningfulPaintCandidates(rendererHelper);
+
+ for (const [frameIdRef, navStartEvents] of frameToNavStartEvents) {
+ const fmpCandidateEvents = candidatesForFrameId[frameIdRef] || [];
+ let prevNavigation = {navigationEvent: undefined, url: undefined};
+
+ for (let index = 0; index < navStartEvents.length; index++) {
+ const currNavigation = navStartEvents[index];
+ let url;
+ let isLoadingMainFrame = false;
+
+ if (currNavigation.args.data) {
+ url = currNavigation.args.data.documentLoaderURL;
+ isLoadingMainFrame = currNavigation.args.data.isLoadingMainFrame;
+ } else {
+ // TODO(#4358): Delete old path of obtaining URL.
+ const snapshot = findFrameLoaderSnapshotAt(
+ rendererHelper, frameIdRef, currNavigation.start);
+ if (snapshot) {
+ url = snapshot.args.documentLoaderURL;
+ isLoadingMainFrame = snapshot.args.isLoadingMainFrame;
+ }
+ }
+
+ // Filter navigationStartEvents that do not correspond to a loading main
+ // frame, or has a URL that we do not care about.
+ if (!isLoadingMainFrame) continue;
+ if (url === undefined || IGNORE_URLS.includes(url)) continue;
+
+ if (prevNavigation.navigationEvent !== undefined) {
+ // Add a LoadExpectation for the previous navigation ending on or
+ // before current navigation.
+ addSamples(frameIdRef, prevNavigation.navigationEvent,
+ fmpCandidateEvents, currNavigation.start, prevNavigation.url);
+ }
+
+ prevNavigation = {navigationEvent: currNavigation, url};
+ }
+
+ // Handle the last navigation here.
+ if (prevNavigation.navigationEvent !== undefined) {
+ addSamples(frameIdRef, prevNavigation.navigationEvent,
+ fmpCandidateEvents, rendererHelper.modelHelper.chromeBounds.max,
+ prevNavigation.url);
+ }
+ }
+ return samples;
+ }
+
+
+ function findLoadExpectations(modelHelper) {
+ const loads = [];
+
+ const chromeHelper = modelHelper.model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ for (const pid in chromeHelper.rendererHelpers) {
+ const rendererHelper = chromeHelper.rendererHelpers[pid];
+ if (rendererHelper.isChromeTracingUI) continue;
+
+ loads.push.apply(loads,
+ collectLoadExpectationsForRenderer(rendererHelper));
+ }
+ return loads;
+ }
+
+ return {
+ findLoadExpectations,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/find_startup_expectations.html b/chromium/third_party/catapult/tracing/tracing/importer/find_startup_expectations.html
new file mode 100644
index 00000000000..72415a62604
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/find_startup_expectations.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/user_model/startup_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.importer', function() {
+ function getAllFrameEvents(modelHelper) {
+ const frameEvents = [];
+ frameEvents.push.apply(frameEvents,
+ modelHelper.browserHelper.getFrameEventsInRange(
+ tr.model.helpers.IMPL_FRAMETIME_TYPE, modelHelper.model.bounds));
+
+ for (const renderer of Object.values(modelHelper.rendererHelpers)) {
+ frameEvents.push.apply(frameEvents, renderer.getFrameEventsInRange(
+ tr.model.helpers.IMPL_FRAMETIME_TYPE, modelHelper.model.bounds));
+ }
+ return frameEvents.sort(tr.importer.compareEvents);
+ }
+
+ // If a thread contains a typical initialization slice, then the first event
+ // on that thread is a startup event.
+ function getStartupEvents(modelHelper) {
+ function isStartupSlice(slice) {
+ return slice.title === 'BrowserMainLoop::CreateThreads';
+ }
+ const events = modelHelper.browserHelper.getAllAsyncSlicesMatching(
+ isStartupSlice);
+ const deduper = new tr.model.EventSet();
+ events.forEach(function(event) {
+ const sliceGroup = event.parentContainer.sliceGroup;
+ const slice = sliceGroup && sliceGroup.findFirstSlice();
+ if (slice) {
+ deduper.push(slice);
+ }
+ });
+ return deduper.toArray();
+ }
+
+ // Match every event in |openingEvents| to the first following event from
+ // |closingEvents| and return an array containing a load interaction record
+ // for each pair.
+ function findStartupExpectations(modelHelper) {
+ const openingEvents = getStartupEvents(modelHelper);
+ const closingEvents = getAllFrameEvents(modelHelper);
+ const startups = [];
+ openingEvents.forEach(function(openingEvent) {
+ closingEvents.forEach(function(closingEvent) {
+ // Ignore opening event that already have a closing event.
+ if (openingEvent.closingEvent) return;
+
+ // Ignore closing events that already belong to an opening event.
+ if (closingEvent.openingEvent) return;
+
+ // Ignore closing events before |openingEvent|.
+ if (closingEvent.start <= openingEvent.start) return;
+
+ // Ignore events from different threads.
+ if (openingEvent.parentContainer.parent.pid !==
+ closingEvent.parentContainer.parent.pid) {
+ return;
+ }
+
+ // This is the first closing event for this opening event, record it.
+ openingEvent.closingEvent = closingEvent;
+ closingEvent.openingEvent = openingEvent;
+ const se = new tr.model.um.StartupExpectation(
+ modelHelper.model, openingEvent.start,
+ closingEvent.end - openingEvent.start);
+ se.associatedEvents.push(openingEvent);
+ se.associatedEvents.push(closingEvent);
+ startups.push(se);
+ });
+ });
+ return startups;
+ }
+
+ return {
+ findStartupExpectations,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/import.html b/chromium/third_party/catapult/tracing/tracing/importer/import.html
new file mode 100644
index 00000000000..8893120c2c5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/import.html
@@ -0,0 +1,339 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/importer/empty_importer.html">
+<link rel="import" href="/tracing/importer/importer.html">
+<link rel="import" href="/tracing/importer/user_model_builder.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.importer', function() {
+ const Timing = tr.b.Timing;
+
+ function ImportOptions() {
+ this.shiftWorldToZero = true;
+ this.pruneEmptyContainers = true;
+ this.showImportWarnings = true;
+ this.trackDetailedModelStats = false;
+
+ // Callback called after
+ // importers run in which more data can be added to the model, before it is
+ // finalized.
+ this.customizeModelCallback = undefined;
+
+ const auditorTypes = tr.c.Auditor.getAllRegisteredTypeInfos();
+ this.auditorConstructors = auditorTypes.map(function(typeInfo) {
+ return typeInfo.constructor;
+ });
+ }
+
+ function Import(model, opt_options) {
+ if (model === undefined) {
+ throw new Error('Must provide model to import into.');
+ }
+
+ // TODO(dsinclair): Check the model is empty.
+
+ this.importing_ = false;
+ this.importOptions_ = opt_options || new ImportOptions();
+
+ this.model_ = model;
+ this.model_.importOptions = this.importOptions_;
+ }
+
+ Import.prototype = {
+ __proto__: Object.prototype,
+
+ /**
+ * Imports the provided traces into the model. The eventData type
+ * is undefined and will be passed to all the importers registered
+ * via Importer.register. The first importer that returns true
+ * for canImport(events) will be used to import the events.
+ *
+ * The primary trace is provided via the eventData variable. If multiple
+ * traces are to be imported, specify the first one as events, and the
+ * remainder in the opt_additionalEventData array.
+ *
+ * @param {Array} traces An array of eventData to be imported. Each
+ * eventData should correspond to a single trace file and will be handled by
+ * a separate importer.
+ */
+ importTraces(traces) {
+ const progressMeter = {
+ update(msg) {}
+ };
+
+ tr.b.Task.RunSynchronously(
+ this.createImportTracesTask(progressMeter, traces));
+ },
+
+ /**
+ * Imports a trace with the usual options from importTraces, but
+ * does so using idle callbacks, putting up an import dialog
+ * during the import process.
+ */
+ importTracesWithProgressDialog(traces) {
+ if (tr.isHeadless) {
+ throw new Error('Cannot use this method in headless mode.');
+ }
+
+ const overlay = tr.ui.b.Overlay();
+ overlay.title = 'Importing...';
+ overlay.userCanClose = false;
+ overlay.msgEl = document.createElement('div');
+ Polymer.dom(overlay).appendChild(overlay.msgEl);
+ overlay.msgEl.style.margin = '20px';
+ overlay.update = function(msg) {
+ Polymer.dom(this.msgEl).textContent = msg;
+ };
+ overlay.visible = true;
+
+ const promise =
+ tr.b.Task.RunWhenIdle(this.createImportTracesTask(overlay, traces));
+ promise.then(
+ function() { overlay.visible = false; },
+ function(err) { overlay.visible = false; }
+ );
+ return promise;
+ },
+
+ /**
+ * Creates a task that will import the provided traces into the model,
+ * updating the progressMeter as it goes. Parameters are as defined in
+ * importTraces.
+ */
+ createImportTracesTask(progressMeter, traces) {
+ const importStartTimeMs = tr.b.Timing.getCurrentTimeMs();
+
+ if (this.importing_) {
+ throw new Error('Already importing.');
+ }
+ this.importing_ = true;
+
+ // Just some simple setup. It is useful to have a no-op first
+ // task so that we can set up the lastTask = lastTask.after()
+ // pattern that follows.
+ const importTask = new tr.b.Task(function prepareImport() {
+ progressMeter.update('I will now import your traces for you...');
+ }, this);
+ let lastTask = importTask;
+
+ const importers = [];
+
+ function addImportStage(title, callback) {
+ lastTask = lastTask.after(() => progressMeter.update(title));
+ lastTask.updatesUi = true;
+ lastTask = lastTask.after(callback);
+ }
+
+ function addStageForEachImporter(title, callback) {
+ lastTask = lastTask.after((task) => {
+ importers.forEach((importer, index) => {
+ const uiSubTask = task.subTask(() => {
+ progressMeter.update(
+ `${title} ${index + 1} of ${importers.length}`);
+ });
+ uiSubTask.updatesUi = true;
+ task.subTask(() => callback(importer));
+ });
+ });
+ }
+
+ addImportStage('Creating importers...', () => {
+ // Copy the traces array, we may mutate it.
+ traces = traces.slice(0);
+ progressMeter.update('Creating importers...');
+ // Figure out which importers to use.
+ for (let i = 0; i < traces.length; ++i) {
+ importers.push(this.createImporter_(traces[i]));
+ }
+
+ // Some traces have other traces inside them. Before doing the full
+ // import, ask the importer if it has any subtraces, and if so, create
+ // importers for them, also.
+ for (let i = 0; i < importers.length; i++) {
+ const subtraces = importers[i].extractSubtraces();
+ for (let j = 0; j < subtraces.length; j++) {
+ try {
+ traces.push(subtraces[j]);
+ importers.push(this.createImporter_(subtraces[j]));
+ } catch (error) {
+ this.model_.importWarning({
+ type: error.name,
+ message: error.message,
+ showToUser: true,
+ });
+ continue;
+ }
+ }
+ }
+
+ if (traces.length && !this.hasEventDataDecoder_(importers)) {
+ throw new Error(
+ 'Could not find an importer for the provided eventData.');
+ }
+
+ // Sort them on priority. This ensures importing happens in a
+ // predictable order, e.g. ftrace_importer before
+ // trace_event_importer.
+ importers.sort(function(x, y) {
+ return x.importPriority - y.importPriority;
+ });
+ });
+
+ // We import clock sync markers before all other events. This is necessary
+ // because we need the clock sync markers in order to know by how much we
+ // need to shift the timestamps of other events.
+ addStageForEachImporter('Importing clock sync markers',
+ importer => importer.importClockSyncMarkers());
+
+ addStageForEachImporter('Importing', importer => importer.importEvents());
+
+ // Run the cusomizeModelCallback if needed.
+ if (this.importOptions_.customizeModelCallback) {
+ addImportStage('Customizing', () => {
+ this.importOptions_.customizeModelCallback(this.model_);
+ });
+ }
+
+ // Import sample data.
+ addStageForEachImporter('Importing sample data',
+ importer => importer.importSampleData());
+
+ // Autoclose open slices and create subSlices.
+ addImportStage('Autoclosing open slices...', () => {
+ this.model_.autoCloseOpenSlices();
+ this.model_.createSubSlices();
+ });
+
+ // Finalize import.
+ addStageForEachImporter('Finalizing import',
+ importer => importer.finalizeImport());
+
+ // Run preinit.
+ addImportStage('Initializing objects (step 1/2)...',
+ () => this.model_.preInitializeObjects());
+
+ // Prune empty containers.
+ if (this.importOptions_.pruneEmptyContainers) {
+ addImportStage('Pruning empty containers...',
+ () => this.model_.pruneEmptyContainers());
+ }
+
+ // Merge kernel and userland slices on each thread.
+ addImportStage('Merging kernel with userland...',
+ () => this.model_.mergeKernelWithUserland());
+
+ // Create auditors
+ let auditors = [];
+ addImportStage('Adding arbitrary data to model...', () => {
+ auditors = this.importOptions_.auditorConstructors.map(
+ auditorConstructor => new auditorConstructor(this.model_));
+ auditors.forEach((auditor) => {
+ auditor.runAnnotate();
+ auditor.installUserFriendlyCategoryDriverIfNeeded();
+ });
+ });
+
+ addImportStage('Computing final world bounds...', () => {
+ this.model_.computeWorldBounds(this.importOptions_.shiftWorldToZero);
+ });
+
+ addImportStage('Building flow event map...',
+ () => this.model_.buildFlowEventIntervalTree());
+
+ // Join refs.
+ addImportStage('Joining object refs...', () => this.model_.joinRefs());
+
+ // Delete any undeleted objects.
+ addImportStage('Cleaning up undeleted objects...',
+ () => this.model_.cleanupUndeletedObjects());
+
+ // Sort global and process memory dumps.
+ addImportStage('Sorting memory dumps...',
+ () => this.model_.sortMemoryDumps());
+
+ // Finalize memory dump graphs.
+ addImportStage('Finalizing memory dump graphs...',
+ () => this.model_.finalizeMemoryGraphs());
+
+ // Run initializers.
+ addImportStage('Initializing objects (step 2/2)...',
+ () => this.model_.initializeObjects());
+
+ // Build event indices mapping from an event id to all flow events.
+ addImportStage('Building event indices...',
+ () => this.model_.buildEventIndices());
+
+ // Build the UserModel.
+ addImportStage('Building UserModel...', () => {
+ const userModelBuilder = new tr.importer.UserModelBuilder(this.model_);
+ userModelBuilder.buildUserModel();
+ });
+
+ // Sort Expectations.
+ addImportStage('Sorting user expectations...',
+ () => this.model_.userModel.sortExpectations());
+
+ // Run audits.
+ addImportStage('Running auditors...', () => {
+ auditors.forEach(auditor => auditor.runAudit());
+ });
+
+ addImportStage('Updating alerts...', () => this.model_.sortAlerts());
+
+ addImportStage('Update bounds...', () => this.model_.updateBounds());
+
+ addImportStage('Looking for warnings...', () => {
+ // Log an import warning if the clock is low resolution.
+ if (!this.model_.isTimeHighResolution) {
+ this.model_.importWarning({
+ type: 'low_resolution_timer',
+ message: 'Trace time is low resolution, trace may be unusable.',
+ showToUser: true
+ });
+ }
+ });
+
+ // Cleanup.
+ lastTask.after(() => {
+ this.importing_ = false;
+ this.model_.stats.traceImportDurationMs =
+ tr.b.Timing.getCurrentTimeMs() - importStartTimeMs;
+ });
+ return importTask;
+ },
+
+ createImporter_(eventData) {
+ const importerConstructor = tr.importer.Importer.findImporterFor(
+ eventData);
+ if (!importerConstructor) {
+ throw new Error('Couldn\'t create an importer for the provided ' +
+ 'eventData.');
+ }
+ return new importerConstructor(this.model_, eventData);
+ },
+
+ hasEventDataDecoder_(importers) {
+ for (let i = 0; i < importers.length; ++i) {
+ if (!importers[i].isTraceDataContainer()) return true;
+ }
+
+ return false;
+ }
+ };
+
+ return {
+ ImportOptions,
+ Import,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/import_test.html b/chromium/third_party/catapult/tracing/tracing/importer/import_test.html
new file mode 100644
index 00000000000..77787402719
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/import_test.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/extras/importer/v8/v8_log_importer.html">
+<link rel="import" href="/tracing/extras/importer/zip_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Base64 = tr.b.Base64;
+
+ test('canImportEmpty', function() {
+ let m = tr.c.TestUtils.newModelWithEvents([]);
+ assert.isDefined(m.modelIndices);
+ m = new tr.Model('');
+ });
+
+ test('canImportSubtraces', function() {
+ const systraceLines = [
+ 'SurfaceFlinger-2 [001] ...1 1000.0: 0: B|1|taskA',
+ 'SurfaceFlinger-2 [001] ...1 2000.0: 0: E',
+ ' chrome-3 [001] ...1 2000.0: 0: trace_event_clock_sync: ' +
+ 'parent_ts=0'
+ ];
+ const traceEvents = [
+ {ts: 1000, pid: 1, tid: 3, ph: 'B', cat: 'c', name: 'taskB', args: {
+ my_object: {id_ref: '0x1000'}
+ }},
+ {ts: 2000, pid: 1, tid: 3, ph: 'E', cat: 'c', name: 'taskB', args: {}}
+ ];
+
+ const combined = JSON.stringify({
+ traceEvents,
+ systemTraceEvents: systraceLines.join('\n')
+ });
+
+ const m = tr.c.TestUtils.newModelWithEvents([combined]);
+ assert.strictEqual(Object.values(m.processes).length, 1);
+
+ const p1 = m.processes[1];
+ assert.isDefined(p1);
+
+ const t2 = p1.threads[2];
+ const t3 = p1.threads[3];
+ assert.isDefined(t2);
+ assert.isDefined(t3);
+
+ assert.strictEqual(1, 1, t2.sliceGroup.length);
+ assert.strictEqual(t2.sliceGroup.slices[0].title, 'taskA');
+
+ assert.strictEqual(t3.sliceGroup.length, 1);
+ assert.strictEqual(t3.sliceGroup.slices[0].title, 'taskB');
+ });
+
+ test('canImportCompressedSingleSubtrace', function() {
+ const compressedTrace = Base64.atob(
+ 'H4sIACKfFVUC/wsuLUpLTE51y8nMS08t0jVSUIg2MDCMV' +
+ 'dDT0zNUMDQwMNAzsFIAIqcaw5qSxOJsR65gfDqMEDpcATiC61ZbAAAA');
+ const m = tr.c.TestUtils.newModelWithEvents([compressedTrace]);
+ assert.strictEqual(1, Object.values(m.processes).length);
+
+ const p1 = m.processes[1];
+ assert.isDefined(p1);
+
+ const t2 = p1.threads[2];
+ assert.isDefined(t2);
+
+ assert.strictEqual(1, t2.sliceGroup.length, 1);
+ assert.strictEqual('taskA', t2.sliceGroup.slices[0].title);
+ });
+
+ test('canImportSubtracesRecursively', function() {
+ const systraceLines = [
+ 'SurfaceFlinger-2 [001] ...1 1000.0: 0: B|1|taskA',
+ 'SurfaceFlinger-2 [001] ...1 2000.0: 0: E',
+ ' chrome-3 [001] ...1 2000.0: 0: trace_event_clock_sync: ' +
+ 'parent_ts=0'
+ ];
+ const outerTraceEvents = [
+ {ts: 1000, pid: 1, tid: 3, ph: 'B', cat: 'c', name: 'taskB', args: {
+ my_object: {id_ref: '0x1000'}
+ }}
+ ];
+
+ const innerTraceEvents = [
+ {ts: 2000, pid: 1, tid: 3, ph: 'E', cat: 'c', name: 'taskB', args: {}}
+ ];
+
+ const innerTrace = JSON.stringify({
+ traceEvents: innerTraceEvents,
+ systemTraceEvents: systraceLines.join('\n')
+ });
+
+ const outerTrace = JSON.stringify({
+ traceEvents: outerTraceEvents,
+ systemTraceEvents: innerTrace
+ });
+
+ const m = tr.c.TestUtils.newModelWithEvents([outerTrace]);
+ assert.strictEqual(Object.values(m.processes).length, 1);
+
+ const p1 = m.processes[1];
+ assert.isDefined(p1);
+
+ const t2 = p1.threads[2];
+ const t3 = p1.threads[3];
+ assert.isDefined(t2);
+ assert.isDefined(t3);
+
+ assert.strictEqual(1, 1, t2.sliceGroup.length);
+ assert.strictEqual(t2.sliceGroup.slices[0].title, 'taskA');
+
+ assert.strictEqual(t3.sliceGroup.length, 1);
+ assert.strictEqual(t3.sliceGroup.slices[0].title, 'taskB');
+ });
+
+ test('withImportFailure', function() {
+ assert.throw(function() {
+ tr.c.TestUtils.newModelWithEvents([malformed]);
+ });
+ });
+
+ test('customizeCallback', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback(m) {
+ const browserProcess = m.getOrCreateProcess(1);
+ const browserMain = browserProcess.getOrCreateThread(2);
+ browserMain.sliceGroup.beginSlice('cat', 'Task', 0);
+ browserMain.sliceGroup.beginSlice('cat', 'SubTask', 1);
+ browserMain.sliceGroup.endSlice(9);
+ browserMain.sliceGroup.endSlice(10);
+ browserMain.sliceGroup.beginSlice('cat', 'Task', 20);
+ browserMain.sliceGroup.endSlice(30);
+ }
+ });
+ const t2 = m.processes[1].threads[2];
+ assert.strictEqual(t2.sliceGroup.length, 3);
+ assert.strictEqual(t2.sliceGroup.topLevelSlices.length, 2);
+ });
+
+ test('sortsSamples', function() {
+ // The 184, 0 and 185 are the tick-times
+ // and irrespective of the order
+ // in which the lines appear in the trace,
+ // the samples should always be sorted by sampling time.
+ const m = tr.c.TestUtils.newModelWithEvents([
+ 'tick,0x9a,184,0,0x0,5',
+ 'tick,0x9b,0,0,0x0,5',
+ 'tick,0x9c,185,0,0x0,5']);
+ assert.strictEqual(m.samples[0].start, 0);
+ assert.strictEqual(m.samples[1].start, 0.184);
+ assert.strictEqual(m.samples[2].start, 0.185);
+ });
+
+ test('sortsGlobalMemoryDumps', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([], {
+ pruneContainers: false,
+ customizeModelCallback(m) {
+ m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 1));
+ m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 5));
+ m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 3));
+ }
+ });
+ assert.strictEqual(m.globalMemoryDumps[0].start, 0);
+ assert.strictEqual(m.globalMemoryDumps[1].start, 2);
+ assert.strictEqual(m.globalMemoryDumps[2].start, 4);
+ });
+
+ test('finalizesProcessMemoryDumps', function() {
+ let p;
+ const m = tr.c.TestUtils.newModelWithEvents([], {
+ pruneContainers: false,
+ customizeModelCallback(m) {
+ p = m.getOrCreateProcess(1);
+
+ const g = new tr.model.GlobalMemoryDump(m, -1);
+ m.globalMemoryDumps.push(g);
+
+ const pmd1 = new tr.model.ProcessMemoryDump(g, p, 1);
+ p.memoryDumps.push(pmd1);
+
+ const pmd2 = new tr.model.ProcessMemoryDump(g, p, 5);
+ p.memoryDumps.push(pmd2);
+
+ const pmd3 = new tr.model.ProcessMemoryDump(g, p, 3);
+ p.memoryDumps.push(pmd3);
+ pmd3.vmRegions = [];
+ }
+ });
+
+ // Check the sort order.
+ assert.strictEqual(p.memoryDumps[0].start, 2);
+ assert.strictEqual(p.memoryDumps[1].start, 4);
+ assert.strictEqual(p.memoryDumps[2].start, 6);
+
+ // Check that the most recent VM regions are linked correctly.
+ assert.isUndefined(p.memoryDumps[0].mostRecentVmRegions);
+ assert.lengthOf(p.memoryDumps[1].mostRecentVmRegions, 0);
+ assert.strictEqual(
+ p.memoryDumps[1].mostRecentVmRegions,
+ p.memoryDumps[2].mostRecentVmRegions);
+ });
+
+ test('setsModelStatsTraceImportDurationMs', function() {
+ const traceEvents = [
+ {ts: 1000, pid: 1, tid: 3, ph: 'B', cat: 'c', name: 'taskB', args: {
+ my_object: {id_ref: '0x1000'}
+ }},
+ {ts: 2000, pid: 1, tid: 3, ph: 'E', cat: 'c', name: 'taskB', args: {}}
+ ];
+ const m = tr.c.TestUtils.newModelWithEvents(JSON.stringify({traceEvents}));
+
+ assert.isAbove(m.stats.traceImportDurationMs, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/importer.html b/chromium/third_party/catapult/tracing/tracing/importer/importer.html
new file mode 100644
index 00000000000..66accd2b840
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/importer.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/extension_registry.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Base class for trace data importers.
+ */
+tr.exportTo('tr.importer', function() {
+ function Importer() { }
+
+ Importer.prototype = {
+ __proto__: Object.prototype,
+
+ get importerName() {
+ return 'Importer';
+ },
+
+ /**
+ * Called by the Model to check whether the importer type stores the actual
+ * trace data or just holds it as container for further extraction.
+ */
+ isTraceDataContainer() {
+ return false;
+ },
+
+ /**
+ * Called by the Model to extract one or more subtraces from the event data.
+ */
+ extractSubtraces() {
+ return [];
+ },
+
+ /**
+ * Called to import clock sync markers into the Model.
+ */
+ importClockSyncMarkers() {
+ },
+
+ /**
+ * Called to import events into the Model.
+ */
+ importEvents() {
+ },
+
+ /**
+ * Called to import sample data into the Model.
+ */
+ importSampleData() {
+ },
+
+ /**
+ * Called by the Model after all other importers have imported their
+ * events.
+ */
+ finalizeImport() {
+ }
+ };
+
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ options.defaultMetadata = {};
+ options.mandatoryBaseClass = Importer;
+ tr.b.decorateExtensionRegistry(Importer, options);
+
+ Importer.findImporterFor = function(eventData) {
+ const typeInfo = Importer.findTypeInfoMatching(function(ti) {
+ return ti.constructor.canImport(eventData);
+ });
+ if (typeInfo) {
+ return typeInfo.constructor;
+ }
+ return undefined;
+ };
+
+ return {
+ Importer,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html b/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html
new file mode 100644
index 00000000000..3deaac7d934
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html
@@ -0,0 +1,202 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/core/auditor.html">
+<link rel="import" href="/tracing/model/event_info.html">
+<link rel="import" href="/tracing/model/user_model/animation_expectation.html">
+<link rel="import" href="/tracing/model/user_model/response_expectation.html">
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.importer', function() {
+ // This is an intermediate data format between InputLatencyAsyncSlices and
+ // Responses and Animations.
+ function ProtoExpectation(type, initiatorType) {
+ this.type = type;
+ this.initiatorType = initiatorType;
+ this.start = Infinity;
+ this.end = -Infinity;
+ this.associatedEvents = new tr.model.EventSet();
+ this.isAnimationBegin = false;
+ }
+
+ ProtoExpectation.RESPONSE_TYPE = 'r';
+ ProtoExpectation.ANIMATION_TYPE = 'a';
+
+ // Explicitly ignore some input events to allow
+ // UserModelBuilder.checkAllInputEventsHandled() to determine which events
+ // were unintentionally ignored due to a bug.
+ ProtoExpectation.IGNORED_TYPE = 'ignored';
+
+ /**
+ * Combine initiator titles by selecting the initiator title first in a
+ * hard-coded hierarchy. Higher up in the hierarchy are more "specific"
+ * initiator titles (e.g. a scroll is higher than a touch, because a
+ * touch could mean many different things, of which a scroll is one)
+ */
+ const INITIATOR_HIERARCHY = [
+ tr.model.um.INITIATOR_TYPE.PINCH,
+ tr.model.um.INITIATOR_TYPE.FLING,
+ tr.model.um.INITIATOR_TYPE.MOUSE_WHEEL,
+ tr.model.um.INITIATOR_TYPE.SCROLL,
+ tr.model.um.INITIATOR_TYPE.VR,
+ tr.model.um.INITIATOR_TYPE.VIDEO,
+ tr.model.um.INITIATOR_TYPE.WEBGL,
+ tr.model.um.INITIATOR_TYPE.CSS,
+ tr.model.um.INITIATOR_TYPE.MOUSE,
+ tr.model.um.INITIATOR_TYPE.KEYBOARD,
+ tr.model.um.INITIATOR_TYPE.TAP,
+ tr.model.um.INITIATOR_TYPE.TOUCH
+ ];
+
+ function combineInitiatorTypes(title1, title2) {
+ for (const item of INITIATOR_HIERARCHY) {
+ if (title1 === item || title2 === item) return item;
+ }
+ throw new Error('Invalid titles in combineInitiatorTypes');
+ }
+
+ ProtoExpectation.prototype = {
+ get isValid() {
+ return this.end > this.start;
+ },
+
+ // Return true if any associatedEvent's typeName is in typeNames.
+ containsTypeNames(typeNames) {
+ return this.associatedEvents.some(
+ x => typeNames.indexOf(x.typeName) >= 0);
+ },
+
+ containsSliceTitle(title) {
+ return this.associatedEvents.some(x => title === x.title);
+ },
+
+ createInteractionRecord(model) {
+ if (this.type !== ProtoExpectation.IGNORED_TYPE && !this.isValid) {
+ model.importWarning({
+ type: 'ProtoExpectation',
+ message: 'Please file a bug with this trace. ' + this.debug(),
+ showToUser: true
+ });
+ return undefined;
+ }
+
+ const duration = this.end - this.start;
+
+ let ir = undefined;
+ switch (this.type) {
+ case ProtoExpectation.RESPONSE_TYPE:
+ ir = new tr.model.um.ResponseExpectation(
+ model, this.initiatorType, this.start, duration,
+ this.isAnimationBegin);
+ break;
+ case ProtoExpectation.ANIMATION_TYPE:
+ ir = new tr.model.um.AnimationExpectation(
+ model, this.initiatorType, this.start, duration);
+ break;
+ }
+ if (!ir) return undefined;
+
+ ir.sourceEvents.addEventSet(this.associatedEvents);
+
+ function pushAssociatedEvents(event) {
+ ir.associatedEvents.push(event);
+
+ // |event| is either an InputLatencyAsyncSlice (which collects all of
+ // its associated events transitively) or a CSS Animation (which doesn't
+ // have any associated events). So this does not need to recurse.
+ if (event.associatedEvents) {
+ ir.associatedEvents.addEventSet(event.associatedEvents);
+ }
+ }
+
+ this.associatedEvents.forEach(function(event) {
+ pushAssociatedEvents(event);
+
+ // Old-style InputLatencyAsyncSlices have subSlices.
+ if (event.subSlices) {
+ event.subSlices.forEach(pushAssociatedEvents);
+ }
+ });
+
+ return ir;
+ },
+
+ // Merge the other ProtoExpectation into this one.
+ // The types need not match: ignored ProtoExpectations might be merged
+ // into overlapping ProtoExpectations, and Touch-only Animations are merged
+ // into Tap Responses.
+ merge(other) {
+ this.initiatorType = combineInitiatorTypes(
+ this.initiatorType, other.initiatorType);
+
+ // Don't use pushEvent(), which would lose special start, end.
+ this.associatedEvents.addEventSet(other.associatedEvents);
+ this.start = Math.min(this.start, other.start);
+ this.end = Math.max(this.end, other.end);
+ if (other.isAnimationBegin) {
+ this.isAnimationBegin = true;
+ }
+ },
+
+ // Include |event| in this ProtoExpectation, expanding start/end to include
+ // it.
+ pushEvent(event) {
+ // Usually, this method will be called while iterating over a list of
+ // events sorted by start time, so this method won't usually change
+ // this.start. However, this will sometimes be called for
+ // ProtoExpectations created by previous handlers, in which case
+ // event.start could possibly be before this.start.
+ this.start = Math.min(this.start, event.start);
+ this.end = Math.max(this.end, event.end);
+ this.associatedEvents.push(event);
+ },
+
+ // Include |sample| in this ProtoExpectation, expanding start/end to
+ // include it.
+ pushSample(sample) {
+ this.start = Math.min(this.start, sample.timestamp);
+ this.end = Math.max(this.end, sample.timestamp);
+ this.associatedEvents.push(sample);
+ },
+
+ // Returns true if timestamp is contained in this ProtoExpectation.
+ containsTimestampInclusive(timestamp) {
+ return (this.start <= timestamp) && (timestamp <= this.end);
+ },
+
+ // Return true if the other event intersects this ProtoExpectation.
+ intersects(other) {
+ // http://stackoverflow.com/questions/325933
+ return (other.start < this.end) && (other.end > this.start);
+ },
+
+ isNear(event, threshold) {
+ return (this.end + threshold) > event.start;
+ },
+
+ // Return a string describing this ProtoExpectation for debugging.
+ debug() {
+ let debugString = this.type + '(';
+ debugString += parseInt(this.start) + ' ';
+ debugString += parseInt(this.end);
+ this.associatedEvents.forEach(function(event) {
+ debugString += ' ' + event.typeName;
+ });
+ return debugString + ')';
+ }
+ };
+
+ return {
+ ProtoExpectation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/simple_line_reader.html b/chromium/third_party/catapult/tracing/tracing/importer/simple_line_reader.html
new file mode 100644
index 00000000000..ff94c9d74ba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/simple_line_reader.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.importer', function() {
+ class SimpleLineReader {
+ constructor(text) {
+ this.data_ = text instanceof tr.b.TraceStream ?
+ text : text.split(new RegExp('\r?\n'));
+ this.curLine_ = 0;
+ this.readLastLine_ = false;
+ this.savedLines_ = undefined;
+ }
+
+ * [Symbol.iterator]() {
+ let lastLine = undefined;
+ while (this.hasData_) {
+ if (this.readLastLine_) {
+ this.curLine_++;
+ this.readLastLine_ = false;
+ } else if (this.data_ instanceof tr.b.TraceStream) {
+ this.curLine_++;
+ const line = this.data_.readUntilDelimiter('\n');
+ if (line.endsWith('\r\n')) {
+ lastLine = line.slice(0, -2);
+ } else if (line.endsWith('\n')) {
+ lastLine = line.slice(0, -1);
+ } else {
+ lastLine = line;
+ }
+ } else {
+ this.curLine_++;
+ lastLine = this.data_[this.curLine_ - 1];
+ }
+ yield lastLine;
+ }
+ }
+
+ get curLineNumber() {
+ return this.curLine_;
+ }
+
+ get hasData_() {
+ if (this.data_ instanceof tr.b.TraceStream) return this.data_.hasData;
+ return this.curLine_ < this.data_.length;
+ }
+
+ advanceToLineMatching(regex) {
+ for (const line of this) {
+ if (this.savedLines_ !== undefined) this.savedLines_.push(line);
+ if (regex.test(line)) {
+ this.goBack_();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ goBack_() {
+ if (this.readLastLine_) {
+ throw new Error('There should be at least one nextLine call between ' +
+ 'any two goBack calls.');
+ }
+ if (this.curLine_ === 0) {
+ throw new Error('There should be at least one nextLine call before ' +
+ 'the first goBack call.');
+ }
+ this.readLastLine_ = true;
+ this.curLine_--;
+ }
+
+ beginSavingLines() {
+ this.savedLines_ = [];
+ }
+
+ endSavingLinesAndGetResult() {
+ const tmp = this.savedLines_;
+ this.savedLines_ = undefined;
+ return tmp;
+ }
+ }
+
+ return {
+ SimpleLineReader,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/user_expectation_verifier.html b/chromium/third_party/catapult/tracing/tracing/importer/user_expectation_verifier.html
new file mode 100644
index 00000000000..ccaef12de51
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/user_expectation_verifier.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/importer/user_model_builder.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.importer', function() {
+ function compareEvents(x, y) {
+ if (x.start !== y.start) return x.start - y.start;
+ return x.guid - y.guid;
+ }
+
+ class UserExpectationVerifier {
+ constructor() {
+ this.customizeModelCallback_ = undefined;
+ this.expectedUEs_ = undefined;
+ this.expectedSegments_ = undefined;
+ }
+
+ set customizeModelCallback(cmc) {
+ this.customizeModelCallback_ = cmc;
+ }
+
+ /**
+ * @param {!Array.<!Object>} ues must be sorted by start time.
+ */
+ set expectedUEs(ues) {
+ this.expectedUEs_ = ues;
+ }
+
+ get expectedUEs() {
+ return this.expectedUEs_;
+ }
+
+ /**
+ * @param {!Array.<!Object>} segments must be sorted by start time.
+ */
+ set expectedSegments(segments) {
+ this.expectedSegments_ = segments;
+ }
+
+ verify() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(
+ this.customizeModelCallback_);
+
+ let failure = undefined;
+ try {
+ this.verifyExpectations_([...model.userModel.expectations]);
+ this.verifySegments_(model.userModel.segments);
+ } catch (e) {
+ failure = e;
+ }
+
+ if (failure) throw failure;
+ }
+
+ verifyExpectations_(expectations) {
+ assert.lengthOf(expectations, this.expectedUEs.length);
+ for (let i = 0; i < this.expectedUEs.length; ++i) {
+ this.verifyExpectation_(
+ this.expectedUEs[i], expectations[i], `UEs[${i}]`);
+ }
+ }
+
+ verifySegments_(segments) {
+ assert.lengthOf(segments, this.expectedSegments_.length);
+ for (let i = 0; i < this.expectedSegments_.length; ++i) {
+ this.verifySegment_(
+ this.expectedSegments_[i], segments[i], `segments[${i}].`);
+ }
+ }
+
+ verifyExpectation_(expected, actual, at) {
+ assert.strictEqual(expected.title, actual.title, at + 'title');
+ if (expected.name !== undefined) {
+ assert.strictEqual(expected.name, actual.name, at + 'name');
+ }
+ assert.strictEqual(expected.start, actual.start, at + 'start');
+ assert.strictEqual(expected.end, actual.end, at + 'end');
+ assert.strictEqual(expected.eventCount,
+ actual.associatedEvents.length, at + 'eventCount');
+ if (actual instanceof tr.model.um.ResponseExpectation) {
+ assert.strictEqual(expected.isAnimationBegin || false,
+ actual.isAnimationBegin, at + 'isAnimationBegin');
+ }
+ }
+
+ verifySegment_(expected, actual, at) {
+ assert.strictEqual(expected.start, actual.start, at + 'start');
+ assert.strictEqual(expected.end, actual.end, at + 'end');
+ assert.lengthOf(actual.expectations, expected.expectations.length,
+ at + 'expectations.length');
+ for (let i = 0; i < expected.expectations.length; ++i) {
+ this.verifyExpectation_(
+ expected.expectations[i], actual.expectations[i],
+ at + `expectations[${i}].`);
+ }
+ }
+ }
+
+ return {
+ UserExpectationVerifier,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder.html b/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder.html
new file mode 100644
index 00000000000..c5cf14137f0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder.html
@@ -0,0 +1,277 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/core/auditor.html">
+<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import" href="/tracing/importer/find_input_expectations.html">
+<link rel="import" href="/tracing/importer/find_load_expectations.html">
+<link rel="import" href="/tracing/importer/find_startup_expectations.html">
+<link rel="import" href="/tracing/model/event_info.html">
+<link rel="import" href="/tracing/model/ir_coverage.html">
+<link rel="import" href="/tracing/model/user_model/idle_expectation.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.importer', function() {
+ const INSIGNIFICANT_MS = 1;
+
+ class UserModelBuilder {
+ constructor(model) {
+ this.model = model;
+ this.modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ }
+
+ static supportsModelHelper(modelHelper) {
+ return modelHelper.browserHelper !== undefined;
+ }
+
+ /**
+ * This is called during the trace model import process.
+ */
+ buildUserModel() {
+ if (!this.modelHelper || !this.modelHelper.browserHelper) return;
+
+ try {
+ for (const ue of this.findUserExpectations()) {
+ // This is an EventSet, not an Array, so it can't use push(...).
+ // https://github.com/catapult-project/catapult/issues/3157
+ this.model.userModel.expectations.push(ue);
+ }
+ this.model.userModel.segments.push(...this.findSegments());
+ // There are not currently any known cases when this could throw,
+ // but there have been in the past and there could be again, so
+ // keep handling exceptions here to be friendly to the future.
+ } catch (error) {
+ this.model.importWarning({
+ type: 'UserModelBuilder',
+ message: error,
+ showToUser: true
+ });
+ }
+ }
+
+ /**
+ * Returns an array of Segments covering the trace Model. A Segment
+ * represents a range of time during which the set of active
+ * UserExpectations does not change. Because of this, segments are
+ * guaranteed to not overlap, whereas UserExpectations can.
+ *
+ * @return {!Array.<!tr.model.um.Segment>}
+ */
+ findSegments() {
+ let timestamps = new Set();
+ for (const expectation of this.model.userModel.expectations) {
+ timestamps.add(expectation.start);
+ timestamps.add(expectation.end);
+ }
+ timestamps = [...timestamps];
+ timestamps.sort((x, y) => x - y);
+ const segments = [];
+ for (let i = 0; i < timestamps.length - 1; ++i) {
+ const segment = new tr.model.um.Segment(
+ timestamps[i], timestamps[i + 1] - timestamps[i]);
+ segments.push(segment);
+ const segmentRange = tr.b.math.Range.fromExplicitRange(
+ segment.start, segment.end);
+ for (const expectation of this.model.userModel.expectations) {
+ const expectationRange = tr.b.math.Range.fromExplicitRange(
+ expectation.start, expectation.end);
+ if (segmentRange.intersectsRangeExclusive(expectationRange)) {
+ segment.expectations.push(expectation);
+ }
+ }
+ }
+ return segments;
+ }
+
+ /**
+ * Returns an array of UserExpectations covering the trace Model. A
+ * UserExpectation represents a range of time during which the user is
+ * expecting something from Chrome, either to startup or load a page or
+ * respond to input or play an animation, or just sit there idle. Users can
+ * have multiple expectations at any given time, so UserExpectations can
+ * overlap.
+ *
+ * @return {!Array.<!tr.model.um.UserExpectation>}
+ */
+ findUserExpectations() {
+ const expectations = [];
+ expectations.push.apply(expectations, tr.importer.findStartupExpectations(
+ this.modelHelper));
+ expectations.push.apply(expectations, tr.importer.findLoadExpectations(
+ this.modelHelper));
+ expectations.push.apply(expectations, tr.importer.findInputExpectations(
+ this.modelHelper));
+ // findIdleExpectations must be called last!
+ expectations.push.apply(
+ expectations, this.findIdleExpectations(expectations));
+ this.collectUnassociatedEvents_(expectations);
+ return expectations;
+ }
+
+ // Find all unassociated top-level ThreadSlices. If they start during an
+ // Idle or Load UE, then add their entire hierarchy to that UE.
+ collectUnassociatedEvents_(expectations) {
+ const vacuumUEs = [];
+ for (const expectation of expectations) {
+ if (expectation instanceof tr.model.um.IdleExpectation ||
+ expectation instanceof tr.model.um.LoadExpectation ||
+ expectation instanceof tr.model.um.StartupExpectation) {
+ vacuumUEs.push(expectation);
+ }
+ }
+ if (vacuumUEs.length === 0) return;
+
+ const allAssociatedEvents = tr.model.getAssociatedEvents(expectations);
+ const unassociatedEvents = tr.model.getUnassociatedEvents(
+ this.model, allAssociatedEvents);
+
+ for (const event of unassociatedEvents) {
+ if (!(event instanceof tr.model.ThreadSlice)) continue;
+
+ if (!event.isTopLevel) continue;
+
+ for (let index = 0; index < vacuumUEs.length; ++index) {
+ const expectation = vacuumUEs[index];
+
+ if ((event.start >= expectation.start) &&
+ (event.start < expectation.end)) {
+ expectation.associatedEvents.addEventSet(event.entireHierarchy);
+ break;
+ }
+ }
+ }
+ }
+
+ // Fill in the empty space between UEs with IdleUEs.
+ findIdleExpectations(otherUEs) {
+ if (this.model.bounds.isEmpty) return;
+
+ const emptyRanges = tr.b.math.findEmptyRangesBetweenRanges(
+ tr.b.math.convertEventsToRanges(otherUEs),
+ this.model.bounds);
+ const expectations = [];
+ const model = this.model;
+ for (const range of emptyRanges) {
+ // Ignore insignificantly tiny idle ranges.
+ if (range.max < (range.min + INSIGNIFICANT_MS)) continue;
+
+ expectations.push(new tr.model.um.IdleExpectation(
+ model, range.min, range.max - range.min));
+ }
+ return expectations;
+ }
+ }
+
+ function createCustomizeModelLinesFromModel(model) {
+ const modelLines = [];
+ modelLines.push(' audits.addEvent(model.browserMain,');
+ modelLines.push(' {title: \'model start\', start: 0, end: 1});');
+
+ const typeNames = {};
+ for (const typeName in tr.e.cc.INPUT_EVENT_TYPE_NAMES) {
+ typeNames[tr.e.cc.INPUT_EVENT_TYPE_NAMES[typeName]] = typeName;
+ }
+
+ let modelEvents = new tr.model.EventSet();
+ for (const ue of model.userModel.expectations) {
+ modelEvents.addEventSet(ue.sourceEvents);
+ }
+ modelEvents = modelEvents.toArray();
+ modelEvents.sort(tr.importer.compareEvents);
+
+ for (const event of modelEvents) {
+ const startAndEnd = 'start: ' + parseInt(event.start) + ', ' +
+ 'end: ' + parseInt(event.end) + '});';
+ if (event instanceof tr.e.cc.InputLatencyAsyncSlice) {
+ modelLines.push(' audits.addInputEvent(model, INPUT_TYPE.' +
+ typeNames[event.typeName] + ',');
+ } else if (event.title === 'RenderFrameImpl::didCommitProvisionalLoad') {
+ modelLines.push(' audits.addCommitLoadEvent(model,');
+ } else if (event.title ===
+ 'InputHandlerProxy::HandleGestureFling::started') {
+ modelLines.push(' audits.addFlingAnimationEvent(model,');
+ } else if (event.title === tr.model.helpers.IMPL_RENDERING_STATS) {
+ modelLines.push(' audits.addFrameEvent(model,');
+ } else if (event.title === tr.importer.CSS_ANIMATION_TITLE) {
+ modelLines.push(' audits.addEvent(model.rendererMain, {');
+ modelLines.push(' title: \'Animation\', ' + startAndEnd);
+ return;
+ } else {
+ throw new Error(
+ 'You must extend createCustomizeModelLinesFromModel()' +
+ 'to support this event:\n' + event.title + '\n');
+ }
+ modelLines.push(' {' + startAndEnd);
+ }
+
+ modelLines.push(' audits.addEvent(model.browserMain,');
+ modelLines.push(' {' +
+ 'title: \'model end\', ' +
+ 'start: ' + (parseInt(model.bounds.max) - 1) + ', ' +
+ 'end: ' + parseInt(model.bounds.max) + '});');
+ return modelLines;
+ }
+
+ function createExpectedUELinesFromModel(model) {
+ const expectedLines = [];
+ const ueCount = model.userModel.expectations.length;
+ for (let index = 0; index < ueCount; ++index) {
+ const expectation = model.userModel.expectations[index];
+ let ueString = ' {';
+ ueString += 'title: \'' + expectation.title + '\', ';
+ ueString += 'start: ' + parseInt(expectation.start) + ', ';
+ ueString += 'end: ' + parseInt(expectation.end) + ', ';
+ ueString += 'eventCount: ' + expectation.sourceEvents.length;
+ ueString += '}';
+ if (index < (ueCount - 1)) ueString += ',';
+ expectedLines.push(ueString);
+ }
+ return expectedLines;
+ }
+
+ function createUEFinderTestCaseStringFromModel(model) {
+ const filename = window.location.hash.substr(1);
+ let testName = filename.substr(filename.lastIndexOf('/') + 1);
+ testName = testName.substr(0, testName.indexOf('.'));
+
+ // createCustomizeModelLinesFromModel() throws an error if there's an
+ // unsupported event.
+ try {
+ const testLines = [];
+ testLines.push(' /*');
+ testLines.push(' This test was generated from');
+ testLines.push(' ' + filename + '');
+ testLines.push(' */');
+ testLines.push(' test(\'' + testName + '\', function() {');
+ testLines.push(' const verifier = new UserExpectationVerifier();');
+ testLines.push(' verifier.customizeModelCallback = function(model) {');
+ testLines.push.apply(testLines,
+ createCustomizeModelLinesFromModel(model));
+ testLines.push(' };');
+ testLines.push(' verifier.expectedUEs = [');
+ testLines.push.apply(testLines, createExpectedUELinesFromModel(model));
+ testLines.push(' ];');
+ testLines.push(' verifier.verify();');
+ testLines.push(' });');
+ return testLines.join('\n');
+ } catch (error) {
+ return error;
+ }
+ }
+
+ return {
+ UserModelBuilder,
+ createUEFinderTestCaseStringFromModel,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html b/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html
new file mode 100644
index 00000000000..4379316e8ae
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html
@@ -0,0 +1,1649 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/importer/user_expectation_verifier.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES;
+ const ChromeTestUtils = tr.e.chrome.ChromeTestUtils;
+ const UserExpectationVerifier = tr.importer.UserExpectationVerifier;
+
+ function addFrameEventForInput(model, event) {
+ const frame = ChromeTestUtils.addFrameEvent(model,
+ {start: event.start, end: event.end, isTopLevel: true});
+ model.flowEvents.push(tr.c.TestUtils.newFlowEventEx({
+ id: event.id,
+ start: event.start,
+ end: event.end,
+ startSlice: frame,
+ endSlice: frame
+ }));
+ }
+
+ test('empty', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ };
+ verifier.expectedUEs = [];
+ verifier.expectedSegments = [];
+ verifier.verify();
+ });
+
+ test('vrExpectations', function() {
+ const verifier = new UserExpectationVerifier();
+
+ verifier.customizeModelCallback = function(model) {
+ model.gpuProcess = model.getOrCreateProcess(3);
+ model.gpuMain = model.gpuProcess.getOrCreateThread(6);
+ model.gpuMain.name = 'CrGpuMain';
+
+ const series = new tr.model.CounterSeries('gpu.WebVR FPS');
+ series.addCounterSample(0, 1);
+ series.addCounterSample(990, 2);
+ series.addCounterSample(1005, 3);
+ series.addCounterSample(1500, 4);
+ model.gpuProcess.getOrCreateCounter('gpu',
+ 'WebVR FPS').addSeries(series);
+
+ model.gpuMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {title: 'VrShellGl::DrawFrame', start: 5, end: 10,
+ type: tr.model.ThreadSlice}));
+ model.gpuMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {title: 'VrShellGl::DrawFrame', start: 995, end: 1000,
+ type: tr.model.ThreadSlice}));
+ model.gpuMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {title: 'VrShellGl::DrawFrame', start: 1010, end: 1050,
+ type: tr.model.ThreadSlice}));
+ };
+
+ verifier.expectedUEs = [
+ {title: 'VR Response', start: 0, end: 1000, eventCount: 4},
+ {title: 'VR Animation', start: 1000, end: 1500, eventCount: 4},
+ ];
+
+ verifier.expectedSegments = [
+ {start: 0, end: 1000, expectations: [verifier.expectedUEs[0]]},
+ {start: 1000, end: 1500, expectations: [verifier.expectedUEs[1]]},
+ ];
+
+ verifier.verify();
+ });
+
+ test('videoExpectations_gapInMiddle', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'VideoPlayback', start: 0, end: 100, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 10, end: 20});
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'VideoPlayback', start: 200, end: 300, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 210, end: 220});
+ };
+ verifier.expectedUEs = [
+ {title: 'Video Animation', start: 0, end: 100, eventCount: 2},
+ {title: 'Idle', start: 100, end: 200, eventCount: 0},
+ {title: 'Video Animation', start: 200, end: 300, eventCount: 2},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ {start: 100, end: 200, expectations: [verifier.expectedUEs[1]]},
+ {start: 200, end: 300, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('videoExpectations_overlapping', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'VideoPlayback', start: 0, end: 200, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 10, end: 20});
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'VideoPlayback', start: 100, end: 300, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 210, end: 220});
+ };
+ verifier.expectedUEs = [
+ {title: 'Video Animation', start: 0, end: 300, eventCount: 4},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 300, expectations: [verifier.expectedUEs[0]]},
+ ];
+ verifier.verify();
+ });
+
+ test('videoExpectations_oneInTheOther', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'VideoPlayback', start: 0, end: 300, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 10, end: 20});
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'VideoPlayback', start: 100, end: 200, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 110, end: 120});
+ };
+ verifier.expectedUEs = [
+ {title: 'Video Animation', start: 0, end: 300, eventCount: 4},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 300, expectations: [verifier.expectedUEs[0]]},
+ ];
+ verifier.verify();
+ });
+
+ test('videoExpectations_dontMergeWithOtherAnimations', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = model => {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'VideoPlayback', start: 0, end: 100, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 10, end: 20}),
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'Animation', start: 90, end: 190, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 110, end: 120});
+ };
+ verifier.expectedUEs = [
+ {title: 'Video Animation', start: 0, end: 100, eventCount: 2},
+ {title: 'CSS Animation', start: 90, end: 190, eventCount: 2},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 90, expectations: [verifier.expectedUEs[0]]},
+ {
+ start: 90,
+ end: 100,
+ expectations: [verifier.expectedUEs[0], verifier.expectedUEs[1]]
+ },
+ {start: 100, end: 190, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('slowMouseMoveResponses', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 10});
+ let mouseMove = ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_MOVE, {start: 10, end: 20, id: '0x100'});
+ addFrameEventForInput(model, mouseMove);
+
+ mouseMove = ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_MOVE, {start: 70, end: 80, id: '0x101'});
+ addFrameEventForInput(model, mouseMove);
+
+ mouseMove = ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_MOVE, {start: 130, end: 140, id: '0x102'});
+ addFrameEventForInput(model, mouseMove);
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 10, eventCount: 0},
+ {title: 'Mouse Response', start: 10, end: 20, eventCount: 4},
+ {title: 'Idle', start: 20, end: 70, eventCount: 0},
+ {title: 'Mouse Response', start: 70, end: 80, eventCount: 3},
+ {title: 'Idle', start: 80, end: 130, eventCount: 0},
+ {title: 'Mouse Response', start: 130, end: 140, eventCount: 3}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 10, expectations: [verifier.expectedUEs[0]]},
+ {start: 10, end: 20, expectations: [verifier.expectedUEs[1]]},
+ {start: 20, end: 70, expectations: [verifier.expectedUEs[2]]},
+ {start: 70, end: 80, expectations: [verifier.expectedUEs[3]]},
+ {start: 80, end: 130, expectations: [verifier.expectedUEs[4]]},
+ {start: 130, end: 140, expectations: [verifier.expectedUEs[5]]}
+ ];
+ verifier.verify();
+ });
+
+ test('mouseEventResponses', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ const mouseDown = ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 50, id: '0x100'});
+ addFrameEventForInput(model, mouseDown);
+
+ const mouseUp = ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_UP,
+ {start: 50, end: 100, id: '0x101'});
+ addFrameEventForInput(model, mouseUp);
+
+ const mouseMove = ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_MOVE, {start: 200, end: 250, id: '0x102'});
+ addFrameEventForInput(model, mouseMove);
+ };
+ verifier.expectedUEs = [
+ {title: 'Mouse Response', start: 0, end: 50, eventCount: 3},
+ {title: 'Mouse Response', start: 50, end: 100, eventCount: 3},
+ {title: 'Idle', start: 100, end: 200, eventCount: 0},
+ {title: 'Mouse Response', start: 200, end: 250, eventCount: 3}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 50, expectations: [verifier.expectedUEs[0]]},
+ {start: 50, end: 100, expectations: [verifier.expectedUEs[1]]},
+ {start: 100, end: 200, expectations: [verifier.expectedUEs[2]]},
+ {start: 200, end: 250, expectations: [verifier.expectedUEs[3]]}
+ ];
+ verifier.verify();
+ });
+
+ test('mouseEventsIgnored', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE,
+ {start: 0, end: 50});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN,
+ {start: 50, end: 100});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 100, eventCount: 0}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]}
+ ];
+ verifier.verify();
+ });
+
+ test('unassociatedEvents', function() {
+ // Unassociated ThreadSlices that start during an Idle should be associated
+ // with it. Expect the IdleExpectation to have 2 associated events: both of
+ // the ThreadSlices in the model.
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ const start = tr.c.TestUtils.newSliceEx(
+ {title: 'model start', start: 0, end: 1, type: tr.model.ThreadSlice});
+ start.isTopLevel = true;
+ model.browserMain.sliceGroup.pushSlice(start);
+
+ const end = tr.c.TestUtils.newSliceEx(
+ {title: 'model end', start: 9, end: 10, type: tr.model.ThreadSlice});
+ end.isTopLevel = true;
+ model.browserMain.sliceGroup.pushSlice(end);
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 10, eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 10, expectations: [verifier.expectedUEs[0]]}
+ ];
+ verifier.verify();
+ });
+
+ test('stillLoading', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader',
+ 25, {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
+ ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 11,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ ChromeTestUtils.addFirstContentfulPaintEvent(model, {start: 20});
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 30,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 40,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ ChromeTestUtils.addFrameEvent(model, {start: 100, end: 130});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 11, eventCount: 1},
+ {title: 'Successful Load', start: 11, end: 130, eventCount: 4}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 11, expectations: [verifier.expectedUEs[0]]},
+ {start: 11, end: 130, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('overlappingIdleAndLoadCollectUnassociatedEvents', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
+ model.rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader',
+ 15, {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
+ ChromeTestUtils.addFrameEvent(model, {start: 20, end: 40});
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 20,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start: 20,
+ duration: 5.0,
+ }));
+ ChromeTestUtils.addFirstContentfulPaintEvent(model, {start: 20});
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 30,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 40,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ ChromeTestUtils.addFrameEvent(model, {start: 5000, end: 5050});
+ // 3 Idle events.
+ ChromeTestUtils.addRenderingEvent(model, {start: 5, end: 15});
+ ChromeTestUtils.addRenderingEvent(model, {start: 11, end: 15});
+ ChromeTestUtils.addRenderingEvent(model, {start: 13, end: 15});
+ // 1 Idle event.
+ ChromeTestUtils.addRenderingEvent(model, {start: 5045, end: 5046});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 20, eventCount: 4},
+ {title: 'Successful Load', start: 20, end: 40, eventCount: 4},
+ {title: 'Idle', start: 40, end: 5050, eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 20, expectations: [verifier.expectedUEs[0]]},
+ {start: 20, end: 40, expectations: [verifier.expectedUEs[1]]},
+ {start: 40, end: 5050, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('flingFlingFling', function() {
+ // This trace gave me so many different kinds of trouble that I'm just going
+ // to copy it straight in here, without trying to clarify it at all.
+ // measurmt-traces/mobile/cnet_fling_up_fling_down_motox_2013.json
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 919, end: 998});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL,
+ {start: 919, end: 1001});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_DOWN,
+ {start: 919, end: 1001});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL,
+ {start: 974, end: 1020});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN,
+ {start: 974, end: 1020});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 974, end: 1040});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 1039, end: 1040, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 974, end: 1054});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 990, end: 1021});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 990, end: 1052});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 1051, end: 1052, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1006, end: 1021});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1022, end: 1036});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1022, end: 1052});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1038, end: 1049});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1038, end: 1068});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 1067, end: 1068, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_END,
+ {start: 1046, end: 1050});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 1046, end: 1077});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 1432, end: 2238});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL,
+ {start: 1432, end: 2241});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1516, end: 2605});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN,
+ {start: 1532, end: 2274});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1532, end: 2294});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 2293, end: 2294, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1549, end: 2310});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 2309, end: 2310, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_END,
+ {start: 1627, end: 2275});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 1627, end: 2310});
+ ChromeTestUtils.addFrameEvent(model, {start: 2990, end: 3000});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 919, eventCount: 1},
+ {title: 'Scroll Response', start: 919, end: 1054,
+ eventCount: 6, isAnimationBegin: true},
+ {title: 'Scroll Animation', start: 1054, end: 1068,
+ eventCount: 9},
+ {title: 'Fling Animation', start: 1054, end: 1432,
+ eventCount: 3},
+ {title: 'Scroll Response', start: 1432, end: 2605,
+ eventCount: 5, isAnimationBegin: true},
+ {title: 'Scroll Animation', start: 1549, end: 2310,
+ eventCount: 3},
+ {title: 'Fling Animation', start: 2605, end: 3000,
+ eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 919, expectations: [verifier.expectedUEs[0]]},
+ {start: 919, end: 1054, expectations: [verifier.expectedUEs[1]]},
+ {start: 1054, end: 1068, expectations: [
+ verifier.expectedUEs[2],
+ verifier.expectedUEs[3],
+ ]},
+ {start: 1068, end: 1432, expectations: [verifier.expectedUEs[3]]},
+ {start: 1432, end: 1549, expectations: [verifier.expectedUEs[4]]},
+ {start: 1549, end: 2310, expectations: [
+ verifier.expectedUEs[4],
+ verifier.expectedUEs[5],
+ ]},
+ {start: 2310, end: 2605, expectations: [verifier.expectedUEs[4]]},
+ {start: 2605, end: 3000, expectations: [verifier.expectedUEs[6]]},
+ ];
+ verifier.verify();
+ });
+
+ test('keyboardEvents', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.KEY_DOWN_RAW,
+ {start: 0, end: 45});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.CHAR,
+ {start: 10, end: 50});
+ };
+ verifier.expectedUEs = [
+ {title: 'Keyboard Response', start: 0, end: 50, eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 50, expectations: [verifier.expectedUEs[0]]}
+ ];
+ verifier.verify();
+ });
+
+ test('mouseResponses', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.CLICK,
+ {start: 0, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.CONTEXT_MENU,
+ {start: 200, end: 300});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL,
+ {start: 400, end: 500});
+ };
+ verifier.expectedUEs = [
+ {title: 'Mouse Response', start: 0, end: 100, eventCount: 1},
+ {title: 'Idle', start: 100, end: 200, eventCount: 0},
+ {title: 'Mouse Response', start: 200, end: 300, eventCount: 1},
+ {title: 'Idle', start: 300, end: 400, eventCount: 0},
+ {title: 'MouseWheel Response', start: 400, end: 500,
+ eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ {start: 100, end: 200, expectations: [verifier.expectedUEs[1]]},
+ {start: 200, end: 300, expectations: [verifier.expectedUEs[2]]},
+ {start: 300, end: 400, expectations: [verifier.expectedUEs[3]]},
+ {start: 400, end: 500, expectations: [verifier.expectedUEs[4]]},
+ ];
+ verifier.verify();
+ });
+
+ test('mouseWheelAnimation', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL,
+ {start: 0, end: 20});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 19, end: 20, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL,
+ {start: 16, end: 36});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 35, end: 36, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL,
+ {start: 55, end: 75});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 74, end: 75, isTopLevel: true});
+
+ // This threshold uses both events' start times, not end...start.
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL,
+ {start: 100, end: 150});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 149, end: 150, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL,
+ {start: 141, end: 191});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 190, end: 191, isTopLevel: true});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL,
+ {start: 182, end: 200});
+ ChromeTestUtils.addFrameEvent(model,
+ {start: 199, end: 200, isTopLevel: true});
+ };
+ verifier.expectedUEs = [
+ {title: 'MouseWheel Response', start: 0, end: 20, eventCount: 1},
+ {title: 'MouseWheel Animation', start: 20, end: 75,
+ eventCount: 4},
+ {title: 'Idle', start: 75, end: 100, eventCount: 0},
+ {title: 'MouseWheel Response', start: 100, end: 150,
+ eventCount: 1},
+ {title: 'MouseWheel Response', start: 141, end: 191,
+ eventCount: 1},
+ {title: 'MouseWheel Response', start: 182, end: 200,
+ eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 20, expectations: [verifier.expectedUEs[0]]},
+ {start: 20, end: 75, expectations: [verifier.expectedUEs[1]]},
+ {start: 75, end: 100, expectations: [verifier.expectedUEs[2]]},
+ {start: 100, end: 141, expectations: [verifier.expectedUEs[3]]},
+ {start: 141, end: 150, expectations: [
+ verifier.expectedUEs[3],
+ verifier.expectedUEs[4],
+ ]},
+ {start: 150, end: 182, expectations: [verifier.expectedUEs[4]]},
+ {start: 182, end: 191, expectations: [
+ verifier.expectedUEs[4],
+ verifier.expectedUEs[5],
+ ]},
+ {start: 191, end: 200, expectations: [verifier.expectedUEs[5]]},
+ ];
+ verifier.verify();
+ });
+
+ test('mouseDownUpResponse', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN,
+ {start: 0, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_UP,
+ {start: 200, end: 210});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 200, eventCount: 0},
+ {title: 'Mouse Response', start: 200, end: 210, eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 200, expectations: [verifier.expectedUEs[0]]},
+ {start: 200, end: 210, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('ignoreLoneMouseMoves', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE,
+ {start: 0, end: 100});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 100, eventCount: 0}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]}
+ ];
+ verifier.verify();
+ });
+
+ test('mouseDrags', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 100});
+ let mouseMove = ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_MOVE, {start: 200, end: 215});
+ addFrameEventForInput(model, mouseMove);
+ mouseMove = ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_MOVE, {start: 210, end: 220});
+ addFrameEventForInput(model, mouseMove);
+ mouseMove = ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.MOUSE_MOVE, {start: 221, end: 240});
+ addFrameEventForInput(model, mouseMove);
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 200, eventCount: 0},
+ {title: 'Mouse Response', start: 200, end: 215, eventCount: 4},
+ {title: 'Mouse Animation', start: 215, end: 240, eventCount: 6}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 200, expectations: [verifier.expectedUEs[0]]},
+ {start: 200, end: 215, expectations: [verifier.expectedUEs[1]]},
+ {start: 215, end: 240, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('twoScrollsNoFling', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN,
+ {start: 0, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 20, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 40, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 60, end: 150});
+ ChromeTestUtils.addFrameEvent(model, {start: 149, end: 150});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 70, end: 150});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_END,
+ {start: 80, end: 150});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN,
+ {start: 300, end: 400});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 320, end: 400});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 330, end: 450});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 340, end: 450});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 350, end: 500});
+ ChromeTestUtils.addFrameEvent(model, {start: 499, end: 500});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_END,
+ {start: 360, end: 500});
+ };
+ verifier.expectedUEs = [
+ {title: 'Scroll Response', start: 0, end: 100, eventCount: 2,
+ isAnimationBegin: true},
+ {title: 'Scroll Animation', start: 100, end: 150, eventCount: 5},
+ {title: 'Idle', start: 150, end: 300, eventCount: 0},
+ {title: 'Scroll Response', start: 300, end: 400, eventCount: 2,
+ isAnimationBegin: true},
+ {title: 'Scroll Animation', start: 400, end: 500, eventCount: 5}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ {start: 100, end: 150, expectations: [verifier.expectedUEs[1]]},
+ {start: 150, end: 300, expectations: [verifier.expectedUEs[2]]},
+ {start: 300, end: 400, expectations: [verifier.expectedUEs[3]]},
+ {start: 400, end: 500, expectations: [verifier.expectedUEs[4]]},
+ ];
+ verifier.verify();
+ });
+
+ test('webGLAnimations_oneAnimation', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'DrawingBuffer::prepareMailbox', start: 0, end: 2}));
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 18, end: 19});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 20, end: 22});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 38, end: 39});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 40, end: 42});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 58, end: 59});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 60, end: 62});
+ };
+ verifier.expectedUEs = [
+ {title: 'WebGL Animation', start: 0, end: 62, eventCount: 4},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 62, expectations: [verifier.expectedUEs[0]]}
+ ];
+ verifier.verify();
+ });
+
+ test('webGLAnimations_twoAnimations', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'DrawingBuffer::prepareMailbox', start: 0, end: 2}));
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 18, end: 19});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 20, end: 22});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 38, end: 39});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 40, end: 42});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 58, end: 59});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 60, end: 62});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 218, end: 19});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 220, end: 222});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 238, end: 39});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 240, end: 242});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 258, end: 59});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 260, end: 262});
+ };
+ verifier.expectedUEs = [
+ {title: 'WebGL Animation', start: 0, end: 62, eventCount: 4},
+ {title: 'Idle', start: 62, end: 220, eventCount: 0},
+ {title: 'WebGL Animation', start: 220, end: 262, eventCount: 3}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 62, expectations: [verifier.expectedUEs[0]]},
+ {start: 62, end: 220, expectations: [verifier.expectedUEs[1]]},
+ {start: 220, end: 262, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('webGLAnimations_oneWithAnimationEventsOneWithout', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'DrawingBuffer::prepareMailbox', start: 0, end: 2}));
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 18, end: 19});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 20, end: 22});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 38, end: 39});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 40, end: 42});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 58, end: 59});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 60, end: 62});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 220, end: 222});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 240, end: 242});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 260, end: 262});
+ };
+ verifier.expectedUEs = [
+ {title: 'WebGL Animation', start: 0, end: 62, eventCount: 4},
+ {title: 'Idle', start: 62, end: 262, eventCount: 0},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 62, expectations: [verifier.expectedUEs[0]]},
+ {start: 62, end: 262, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('webGLAnimations_noAnimationEvents', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'DrawingBuffer::prepareMailbox', start: 0, end: 2}));
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 20, end: 22});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 40, end: 42});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 60, end: 62});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 220, end: 222});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 240, end: 242});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'DrawingBuffer::prepareMailbox', start: 260, end: 262});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 262, eventCount: 0},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 262, expectations: [verifier.expectedUEs[0]]},
+ ];
+ verifier.verify();
+ });
+
+ test('webGLAnimations_animationEventsOnly', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'PageAnimator::serviceScriptedAnimations',
+ start: 0, end: 2}));
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 20, end: 22});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 40, end: 42});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 42, eventCount: 0},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 42, expectations: [verifier.expectedUEs[0]]},
+ ];
+ verifier.verify();
+ });
+
+ test('webGLAnimations_oneEvent', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'DrawingBuffer::prepareMailbox', start: 0, end: 2}));
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'PageAnimator::serviceScriptedAnimations',
+ start: 4, end: 6});
+ };
+ verifier.expectedUEs = [
+ {title: 'WebGL Animation', start: 0, end: 2, eventCount: 1},
+ {title: 'Idle', start: 2, end: 6, eventCount: 0},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 2, expectations: [verifier.expectedUEs[0]]},
+ {start: 2, end: 6, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('cssAnimations', function() {
+ // CSS Animations happen on the renderer process, not the browser process.
+ // They are merged if they overlap.
+ // They are merged with other kinds of animations.
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'Animation', start: 0, end: 130, isTopLevel: true}));
+ ChromeTestUtils.addFrameEvent(model, {start: 10, end: 20});
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'Animation', start: 131, end: 200, isTopLevel: true});
+ ChromeTestUtils.addFrameEvent(model, {start: 150, end: 160});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 150, end: 180});
+ ChromeTestUtils.addFrameEvent(model, {start: 290, end: 300});
+ };
+ verifier.expectedUEs = [
+ {title: 'CSS Animation', start: 0, end: 200, eventCount: 4},
+ {title: 'Fling Animation', start: 150, end: 300, eventCount: 3}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 150, expectations: [verifier.expectedUEs[0]]},
+ {start: 150, end: 200, expectations: [
+ verifier.expectedUEs[0],
+ verifier.expectedUEs[1],
+ ]},
+ {start: 200, end: 300, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('cssAnimationStatesRunningAtEnd', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ // If a top-level Animation async slice has state-change instant
+ // events and the last one is a "running" event, then it will run
+ // to the end of the top level event.
+ const animationA = tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'Animation', start: 0, end: 500, isTopLevel: true});
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 100, args: {data: {state: 'running'}}}));
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 200, args: {data: {state: 'idle'}}}));
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 300, args: {data: {state: 'running'}}}));
+ model.rendererMain.asyncSliceGroup.push(animationA);
+ ChromeTestUtils.addFrameEvent(model, {start: 50, end: 60});
+ ChromeTestUtils.addFrameEvent(model, {start: 150, end: 160});
+ ChromeTestUtils.addFrameEvent(model, {start: 250, end: 260});
+ ChromeTestUtils.addFrameEvent(model, {start: 350, end: 360});
+ ChromeTestUtils.addFrameEvent(model, {start: 450, end: 460});
+ // We include a frame event off the end of the top level animation slice
+ // so we can test that it correctly stops the AnimationExpectation
+ // at the end of the top-level event, not tne end of the whole trace,
+ ChromeTestUtils.addFrameEvent(model, {start: 1050, end: 1060});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 100, eventCount: 1},
+ {title: 'CSS Animation', start: 100, end: 200, eventCount: 5},
+ {title: 'Idle', start: 200, end: 300, eventCount: 1},
+ {title: 'CSS Animation', start: 300, end: 500, eventCount: 6},
+ {title: 'Idle', start: 500, end: 1060, eventCount: 1},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ {start: 100, end: 200, expectations: [verifier.expectedUEs[1]]},
+ {start: 200, end: 300, expectations: [verifier.expectedUEs[2]]},
+ {start: 300, end: 500, expectations: [verifier.expectedUEs[3]]},
+ {start: 500, end: 1060, expectations: [verifier.expectedUEs[4]]},
+ ];
+ verifier.verify();
+ });
+
+ test('cssAnimationStates', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ // If a top-level Animation async slice does not have state-change instant
+ // subSlices, then assume that the animation was running throughout the
+ // async slice.
+ ChromeTestUtils.addEvent(model.rendererMain, {
+ title: 'Animation', start: 181, end: 250, isTopLevel: true});
+ ChromeTestUtils.addFrameEvent(model, {start: 200, end: 240});
+
+ // Animation ranges should be merged if there is less than 32ms dead time
+ // between them.
+
+ // If a top-level Animation async slice has state-change instant events,
+ // then run a state machine to find the time ranges when the animation was
+ // actually running.
+
+ // This animation was running from 10-40 and 50-60.
+ const animationA = tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'Animation', start: 50, end: 500, isTopLevel: true});
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 71, args: {data: {state: 'running'}}}));
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 104, args: {data: {state: 'pending'}}}));
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 137, args: {data: {state: 'running'}}}));
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 150, args: {data: {state: 'paused'}}}));
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 281, args: {data: {state: 'running'}}}));
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 350, args: {data: {state: 'idle'}}}));
+ model.rendererMain.asyncSliceGroup.push(animationA);
+ ChromeTestUtils.addFrameEvent(model, {start: 80, end: 90});
+ ChromeTestUtils.addFrameEvent(model, {start: 290, end: 300});
+
+ // An animation without a frame event isn't really an animation.
+ const animationC = tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'Animation', start: 350, end: 382, isTopLevel: true});
+ model.rendererMain.asyncSliceGroup.push(animationC);
+ animationA.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 350, args: {data: {state: 'idle'}}}));
+
+ // This animation was running from model.bounds.min-50 and
+ // 70-model.bounds.max.
+ const animationB = tr.c.TestUtils.newAsyncSliceEx(
+ {title: 'Animation', start: 0, end: 500, isTopLevel: true});
+ animationB.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 40, args: {data: {state: 'finished'}}}));
+ animationB.subSlices.push(tr.c.TestUtils.newInstantEvent(
+ {title: 'Animation', start: 382, args: {data: {state: 'running'}}}));
+ model.rendererMain.asyncSliceGroup.push(animationB);
+ ChromeTestUtils.addFrameEvent(model, {start: 10, end: 20});
+ ChromeTestUtils.addFrameEvent(model, {start: 390, end: 400});
+ };
+ verifier.expectedUEs = [
+ {title: 'CSS Animation', start: 0, end: 350, eventCount: 16},
+ {title: 'Idle', start: 350, end: 382, eventCount: 0},
+ {title: 'CSS Animation', start: 382, end: 500, eventCount: 4},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 350, expectations: [verifier.expectedUEs[0]]},
+ {start: 350, end: 382, expectations: [verifier.expectedUEs[1]]},
+ {start: 382, end: 500, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('flingThatIsntstopped', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 32, end: 100});
+ ChromeTestUtils.addFlingAnimationEvent(model, {start: 38, end: 200});
+ ChromeTestUtils.addFrameEvent(model, {start: 199, end: 200});
+ ChromeTestUtils.addFrameEvent(model, {start: 290, end: 300});
+ };
+ verifier.expectedUEs = [
+ {title: 'Fling Animation', start: 32, end: 200, eventCount: 3},
+ {title: 'Idle', start: 200, end: 300, eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 32, end: 200, expectations: [verifier.expectedUEs[0]]},
+ {start: 200, end: 300, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('flingThatIsStopped', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 32, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL,
+ {start: 105, end: 150});
+ ChromeTestUtils.addFrameEvent(model, {start: 104, end: 105});
+ ChromeTestUtils.addFrameEvent(model, {start: 149, end: 150});
+ };
+ verifier.expectedUEs = [
+ {title: 'Fling Animation', start: 32, end: 105, eventCount: 3},
+ {title: 'Idle', start: 105, end: 150, eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 32, end: 105, expectations: [verifier.expectedUEs[0]]},
+ {start: 105, end: 150, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('flingFling', function() {
+ // measurmt-traces/mobile/facebook_obama_scroll_dialog_box.html
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 0, end: 30});
+ ChromeTestUtils.addFrameEvent(model, {start: 40, end: 41});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 100, end: 130});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL,
+ {start: 100, end: 130});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 110, end: 140});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 170, end: 180});
+ ChromeTestUtils.addFrameEvent(model, {start: 150, end: 151});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_END,
+ {start: 200, end: 210});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 200, end: 220});
+ ChromeTestUtils.addFrameEvent(model, {start: 230, end: 240});
+ };
+ verifier.expectedUEs = [
+ {title: 'Fling Animation', start: 0, end: 100, eventCount: 3},
+ {title: 'Touch Response', start: 100, end: 140, eventCount: 2,
+ isAnimationBegin: true},
+ {title: 'Touch Animation', start: 140, end: 210, eventCount: 3},
+ {title: 'Fling Animation', start: 200, end: 240, eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ {start: 100, end: 140, expectations: [verifier.expectedUEs[1]]},
+ {start: 140, end: 200, expectations: [verifier.expectedUEs[2]]},
+ {start: 200, end: 210, expectations: [
+ verifier.expectedUEs[2],
+ verifier.expectedUEs[3],
+ ]},
+ {start: 210, end: 240, expectations: [verifier.expectedUEs[3]]},
+ ];
+ verifier.verify();
+ });
+
+ test('load', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ model.rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader',
+ 25, {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start: 0,
+ duration: 5.0,
+ }));
+ ChromeTestUtils.addFirstContentfulPaintEvent(model, {start: 20});
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 30,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 40,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 50,
+ duration: 300,
+ }));
+ ChromeTestUtils.addFrameEvent(model, {start: 7000, end: 7130});
+ };
+
+ verifier.expectedUEs = [
+ {title: 'Successful Load', start: 0, end: 350, eventCount: 4},
+ {title: 'Idle', start: 350, end: 7130, eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 350, expectations: [verifier.expectedUEs[0]]},
+ {start: 350, end: 7130, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('loadStartup', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addRenderingEvent(model, {start: 2, end: 3});
+ ChromeTestUtils.addCreateThreadsEvent(model, {start: 5, end: 10});
+ // findStartupExpectations() should ignore subsequent CreateThreads
+ // events.
+ ChromeTestUtils.addCreateThreadsEvent(model, {start: 25, end: 30});
+ ChromeTestUtils.addFrameEvent(model, {start: 11, end: 20});
+ };
+ verifier.expectedUEs = [
+ {title: 'Startup', start: 2, end: 20, eventCount: 3},
+ {title: 'Idle', start: 20, end: 30, eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 2, end: 20, expectations: [verifier.expectedUEs[0]]},
+ {start: 20, end: 30, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('totalIdle', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 10, eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 10, expectations: [verifier.expectedUEs[0]]},
+ ];
+ verifier.verify();
+ });
+
+ test('multipleIdles', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
+ model.rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader',
+ 25, {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
+ ChromeTestUtils.addFrameEvent(model, {start: 10, end: 20});
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 10,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start: 10,
+ duration: 5.0,
+ }));
+ ChromeTestUtils.addFirstContentfulPaintEvent(model, {start: 20});
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 30,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 40,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 50,
+ duration: 300,
+ }));
+ ChromeTestUtils.addFrameEvent(model, {start: 7000, end: 7130});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 10, eventCount: 1},
+ {title: 'Successful Load', start: 10, end: 350, eventCount: 5},
+ {title: 'Idle', start: 350, end: 7130, eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 10, expectations: [verifier.expectedUEs[0]]},
+ {start: 10, end: 350, expectations: [verifier.expectedUEs[1]]},
+ {start: 350, end: 7130, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('touchStartTouchEndTap', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 0, end: 10});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_END,
+ {start: 200, end: 210});
+ };
+ verifier.expectedUEs = [
+ {title: 'Touch Response', start: 0, end: 210, eventCount: 2,
+ isAnimationBegin: true}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 210, expectations: [verifier.expectedUEs[0]]},
+ ];
+ verifier.verify();
+ });
+
+ test('touchMoveResponseAnimation', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 0, end: 10});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 50, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 70, end: 150});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_END,
+ {start: 200, end: 300});
+ ChromeTestUtils.addFrameEvent(model, {start: 299, end: 300});
+ };
+ verifier.expectedUEs = [
+ {title: 'Touch Response', start: 0, end: 100, eventCount: 2,
+ isAnimationBegin: true},
+ {title: 'Touch Animation', start: 100, end: 300, eventCount: 3}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ {start: 100, end: 300, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ test('tapEvents', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP,
+ {start: 0, end: 50});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_DOWN,
+ {start: 300, end: 310});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP,
+ {start: 320, end: 350});
+ };
+ verifier.expectedUEs = [
+ {title: 'Tap Response', start: 0, end: 50, eventCount: 1},
+ {title: 'Idle', start: 50, end: 300, eventCount: 0},
+ {title: 'Tap Response', start: 300, end: 350, eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 50, expectations: [verifier.expectedUEs[0]]},
+ {start: 50, end: 300, expectations: [verifier.expectedUEs[1]]},
+ {start: 300, end: 350, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('tapAndTapCancelResponses', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_DOWN,
+ {start: 0, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL,
+ {start: 300, end: 350});
+ };
+ verifier.expectedUEs = [
+ {title: 'Tap Response', start: 0, end: 100, eventCount: 1},
+ {title: 'Idle', start: 100, end: 300, eventCount: 0},
+ {title: 'Tap Response', start: 300, end: 350, eventCount: 1}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ {start: 100, end: 300, expectations: [verifier.expectedUEs[1]]},
+ {start: 300, end: 350, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('tapCancelResponse', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_DOWN,
+ {start: 0, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL,
+ {start: 150, end: 200});
+ };
+ verifier.expectedUEs = [
+ {title: 'Tap Response', start: 0, end: 200, eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 200, expectations: [verifier.expectedUEs[0]]},
+ ];
+ verifier.verify();
+ });
+
+ test('pinchResponseAnimation', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_BEGIN,
+ {start: 100, end: 150});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE,
+ {start: 130, end: 160});
+ ChromeTestUtils.addFrameEvent(model, {start: 159, end: 160});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE,
+ {start: 140, end: 200});
+ ChromeTestUtils.addFrameEvent(model, {start: 199, end: 200});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE,
+ {start: 150, end: 205});
+ ChromeTestUtils.addFrameEvent(model, {start: 204, end: 205});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE,
+ {start: 210, end: 220});
+ ChromeTestUtils.addFrameEvent(model, {start: 219, end: 220});
+ // pause > 200ms
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE,
+ {start: 421, end: 470});
+ ChromeTestUtils.addFrameEvent(model, {start: 469, end: 470});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_END,
+ {start: 460, end: 500});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 100, eventCount: 1},
+ {title: 'Pinch Response', start: 100, end: 160, eventCount: 2,
+ isAnimationBegin: true},
+ {title: 'Pinch Animation', start: 160, end: 220, eventCount: 6},
+ {title: 'Idle', start: 220, end: 421, eventCount: 0},
+ {title: 'Pinch Animation', start: 421, end: 500, eventCount: 3}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ {start: 100, end: 160, expectations: [verifier.expectedUEs[1]]},
+ {start: 160, end: 220, expectations: [verifier.expectedUEs[2]]},
+ {start: 220, end: 421, expectations: [verifier.expectedUEs[3]]},
+ {start: 421, end: 500, expectations: [verifier.expectedUEs[4]]},
+ ];
+ verifier.verify();
+ });
+
+ test('tapThenScroll', function() {
+ // measurmt-traces/mobile/google_io_instrument_strumming.json
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 0, end: 20});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_END,
+ {start: 40, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 50, end: 120});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 80, end: 150});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 180, end: 200});
+ ChromeTestUtils.addFrameEvent(model, {start: 199, end: 200});
+ };
+ verifier.expectedUEs = [
+ {title: 'Touch Response', start: 0, end: 100, eventCount: 2,
+ isAnimationBegin: true},
+ {title: 'Touch Response', start: 50, end: 150, eventCount: 2,
+ isAnimationBegin: true},
+ {title: 'Touch Animation', start: 150, end: 200, eventCount: 2}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 50, expectations: [verifier.expectedUEs[0]]},
+ {start: 50, end: 100, expectations: [
+ verifier.expectedUEs[0],
+ verifier.expectedUEs[1],
+ ]},
+ {start: 100, end: 150, expectations: [verifier.expectedUEs[1]]},
+ {start: 150, end: 200, expectations: [verifier.expectedUEs[2]]},
+ ];
+ verifier.verify();
+ });
+
+ test('pinchFlingTapTouchEventsOverlap', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addFrameEvent(model, {start: 0, end: 10});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 20, end: 50});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_DOWN,
+ {start: 20, end: 30});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL,
+ {start: 20, end: 50});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 60, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 60, end: 110});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_BEGIN,
+ {start: 60, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL,
+ {start: 65, end: 75});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 70, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE,
+ {start: 70, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 75, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 80, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 85, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN,
+ {start: 75, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 150, end: 200});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 150, end: 200});
+ ChromeTestUtils.addFrameEvent(model, {start: 199, end: 200});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 180, end: 210});
+ ChromeTestUtils.addFrameEvent(model, {start: 209, end: 210});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_END,
+ {start: 190, end: 210});
+ ChromeTestUtils.addFrameEvent(model, {start: 215, end: 220});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 20, eventCount: 1},
+ {title: 'Pinch Response', start: 20, end: 110,
+ eventCount: 9, isAnimationBegin: true},
+ {title: 'Scroll Animation', start: 110, end: 210,
+ eventCount: 7},
+ {title: 'Fling Animation', start: 180, end: 220, eventCount: 4}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 20, expectations: [verifier.expectedUEs[0]]},
+ {start: 20, end: 110, expectations: [verifier.expectedUEs[1]]},
+ {start: 110, end: 180, expectations: [verifier.expectedUEs[2]]},
+ {start: 180, end: 210, expectations: [
+ verifier.expectedUEs[2],
+ verifier.expectedUEs[3],
+ ]},
+ {start: 210, end: 220, expectations: [verifier.expectedUEs[3]]},
+ ];
+ verifier.verify();
+ });
+
+ test('scrollThenFling', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 0, end: 40});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 50, end: 100});
+ ChromeTestUtils.addFrameEvent(model, {start: 99, end: 100});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 80, end: 100});
+ ChromeTestUtils.addFrameEvent(model, {start: 190, end: 200});
+ };
+ verifier.expectedUEs = [
+ {title: 'Scroll Animation', start: 0, end: 100, eventCount: 3},
+ {title: 'Fling Animation', start: 80, end: 200, eventCount: 3}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 80, expectations: [verifier.expectedUEs[0]]},
+ {start: 80, end: 100, expectations: [
+ verifier.expectedUEs[0],
+ verifier.expectedUEs[1],
+ ]},
+ {start: 100, end: 200, expectations: [verifier.expectedUEs[1]]},
+ ];
+ verifier.verify();
+ });
+
+ /*
+ This test was generated from
+ /test_data/measurmt-traces/mobile/fling_HN_to_rest.json
+ */
+ test('flingHNToRest', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addEvent(model.browserMain,
+ {title: 'model start', start: 0, end: 1});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_START,
+ {start: 1274, end: 1297});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_DOWN,
+ {start: 1274, end: 1305});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1343, end: 1350});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1359, end: 1366});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL,
+ {start: 1359, end: 1366});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN,
+ {start: 1359, end: 1367});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1359, end: 1387});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1375, end: 1385});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1375, end: 1416});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1389, end: 1404});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1389, end: 1429});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1405, end: 1418});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1405, end: 1449});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 1419, end: 1432});
+ ChromeTestUtils.addFrameEvent(model, {start: 1431, end: 1432});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 1419, end: 1474});
+ ChromeTestUtils.addFrameEvent(model, {start: 1473, end: 1474});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_END,
+ {start: 1427, end: 1435});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.FLING_START,
+ {start: 1427, end: 1474});
+ ChromeTestUtils.addFlingAnimationEvent(model, {start: 1440, end: 2300});
+ ChromeTestUtils.addEvent(model.browserMain,
+ {title: 'model end', start: 3184, end: 3185});
+ };
+ verifier.expectedUEs = [
+ {title: 'Idle', start: 0, end: 1274, eventCount: 0},
+ {title: 'Scroll Response', start: 1274, end: 1387,
+ eventCount: 6, isAnimationBegin: true},
+ {title: 'Scroll Animation', start: 1387, end: 1474,
+ eventCount: 12},
+ {title: 'Fling Animation', start: 1427, end: 2300,
+ eventCount: 4},
+ {title: 'Idle', start: 2300, end: 3185, eventCount: 0}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 1274, expectations: [verifier.expectedUEs[0]]},
+ {start: 1274, end: 1387, expectations: [verifier.expectedUEs[1]]},
+ {start: 1387, end: 1427, expectations: [verifier.expectedUEs[2]]},
+ {start: 1427, end: 1474, expectations: [
+ verifier.expectedUEs[2],
+ verifier.expectedUEs[3],
+ ]},
+ {start: 1474, end: 2300, expectations: [verifier.expectedUEs[3]]},
+ {start: 2300, end: 3185, expectations: [verifier.expectedUEs[4]]},
+ ];
+ verifier.verify();
+ });
+
+ test('TapResponseOverlappingTouchAnimation', function() {
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 0, end: 10});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 5, end: 15});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE,
+ {start: 10, end: 20});
+ ChromeTestUtils.addFrameEvent(model, {start: 19, end: 20});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.TAP,
+ {start: 15, end: 100});
+ };
+ verifier.expectedUEs = [
+ {title: 'Tap Response', start: 0, end: 100,
+ eventCount: 5}
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 100, expectations: [verifier.expectedUEs[0]]},
+ ];
+ verifier.verify();
+ });
+
+ test('responseFramesNotInScrollAnimation', function() {
+ // fixResponseAnimationStarts in find_input_expectations moves the start of
+ // the Scroll Animation and needs to remove frame events that now lie
+ // out of the Scroll Animation's interval
+ const verifier = new UserExpectationVerifier();
+ verifier.customizeModelCallback = function(model) {
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN,
+ {start: 0, end: 20});
+ ChromeTestUtils.addFrameEvent(model, {start: 5, end: 6});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 20, end: 40});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE,
+ {start: 20, end: 210});
+ // don't associate the follwing event to the Scroll Animation
+ ChromeTestUtils.addFrameEvent(model, {start: 25, end: 26});
+ ChromeTestUtils.addFrameEvent(model, {start: 190, end: 191});
+ ChromeTestUtils.addInputEvent(model, INPUT_TYPE.SCROLL_END,
+ {start: 200, end: 250});
+ };
+ verifier.expectedUEs = [
+ {title: 'Scroll Response', start: 0, end: 40,
+ eventCount: 2, isAnimationBegin: true},
+ {title: 'Scroll Animation', start: 40, end: 250, eventCount: 3},
+ ];
+ verifier.expectedSegments = [
+ {start: 0, end: 40, expectations: [verifier.expectedUEs[0]]},
+ {start: 40, end: 250, expectations: [verifier.expectedUEs[1]]}
+ ];
+ verifier.verify();
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/index.js b/chromium/third_party/catapult/tracing/tracing/index.js
new file mode 100644
index 00000000000..e9e5967c518
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/index.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+
+const catapultPath = fs.realpathSync(path.join(__dirname, '..', '..'));
+const catapultBuildPath = path.join(catapultPath, 'catapult_build');
+
+const nodeBootstrap = require(path.join(
+ catapultBuildPath, 'node_bootstrap.js'));
+
+HTMLImportsLoader.addArrayToSourcePath(
+ nodeBootstrap.getSourcePathsForProject('tracing'));
+
+// Go!
+HTMLImportsLoader.loadHTML('/tracing/importer/import.html');
+HTMLImportsLoader.loadHTML('/tracing/model/model.html');
+HTMLImportsLoader.loadHTML('/tracing/extras/full_config.html');
+
+// Make the tracing namespace the main tracing export.
+module.exports = global.tr;
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/__init__.py b/chromium/third_party/catapult/tracing/tracing/metrics/__init__.py
new file mode 100644
index 00000000000..cffcee63c42
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/__init__.py
@@ -0,0 +1,15 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+
+_CATAPULT_DIR = os.path.abspath(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), '..', '..', '..'))
+
+_PI_PATH = os.path.join(_CATAPULT_DIR, 'perf_insights')
+
+if _PI_PATH not in sys.path:
+ sys.path.insert(1, _PI_PATH)
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/accessibility_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/accessibility_metric.html
new file mode 100644
index 00000000000..43c6b393dbe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/accessibility_metric.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ function accessibilityMetric(histograms, model) {
+ const browserAccessibilityEventsHist = new tr.v.Histogram(
+ 'browser_accessibility_events',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ browserAccessibilityEventsHist.description =
+ 'Browser accessibility events time';
+
+ const renderAccessibilityEventsHist = new tr.v.Histogram(
+ 'render_accessibility_events',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ renderAccessibilityEventsHist.description =
+ 'Render accessibility events time';
+
+ const renderAccessibilityLocationsHist = new tr.v.Histogram(
+ 'render_accessibility_locations',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ renderAccessibilityLocationsHist.description =
+ 'Render accessibility locations time';
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (chromeHelper === undefined) return;
+
+ for (const rendererHelper of Object.values(chromeHelper.rendererHelpers)) {
+ const mainThread = rendererHelper.mainThread;
+ if (mainThread === undefined) continue;
+
+ for (const slice of mainThread.getDescendantEvents()) {
+ if (!(slice instanceof tr.model.ThreadSlice)) continue;
+
+ if (slice.title ===
+ 'RenderAccessibilityImpl::SendPendingAccessibilityEvents') {
+ renderAccessibilityEventsHist.addSample(slice.duration,
+ {event: new tr.v.d.RelatedEventSet(slice)});
+ }
+ if (slice.title ===
+ 'RenderAccessibilityImpl::SendLocationChanges') {
+ renderAccessibilityLocationsHist.addSample(slice.duration,
+ {event: new tr.v.d.RelatedEventSet(slice)});
+ }
+ }
+ }
+
+ for (const browserHelper of Object.values(chromeHelper.browserHelpers)) {
+ const mainThread = browserHelper.mainThread;
+ if (mainThread === undefined) continue;
+
+ for (const slice of mainThread.getDescendantEvents()) {
+ if (slice.title ===
+ 'BrowserAccessibilityManager::OnAccessibilityEvents') {
+ browserAccessibilityEventsHist.addSample(slice.duration,
+ {event: new tr.v.d.RelatedEventSet(slice)});
+ }
+ }
+ }
+
+ histograms.addHistogram(browserAccessibilityEventsHist);
+ histograms.addHistogram(renderAccessibilityEventsHist);
+ histograms.addHistogram(renderAccessibilityLocationsHist);
+ }
+
+ tr.metrics.MetricRegistry.register(accessibilityMetric);
+
+ return {
+ accessibilityMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/accessibility_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/accessibility_metric_test.html
new file mode 100644
index 00000000000..27dbf178637
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/accessibility_metric_test.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/accessibility_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function makeTestModel() {
+ return tr.c.TestUtils.newModel(function(model) {
+ const browserProcess = model.getOrCreateProcess(99);
+ browserProcess.name = 'Browser';
+ const browserThread = browserProcess.getOrCreateThread(2);
+ browserThread.name = 'CrBrowserMain';
+ browserThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'accessibility',
+ title: 'BrowserAccessibilityManager::OnAccessibilityEvents',
+ start: 1000,
+ dur: 71,
+ end: 1071,
+ }));
+ browserThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'accessibility',
+ title: 'BrowserAccessibilityManager::OnAccessibilityEvents',
+ start: 1500,
+ dur: 22,
+ end: 1522,
+ }));
+
+ const renderThread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ renderThread.name = 'CrRendererMain';
+ renderThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'accessibility',
+ title: 'RenderAccessibilityImpl::SendPendingAccessibilityEvents',
+ start: 800,
+ dur: 228,
+ end: 1028,
+ }));
+ renderThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'accessibility',
+ title: 'RenderAccessibilityImpl::SendLocationChanges',
+ start: 900,
+ dur: 12,
+ end: 912,
+ }));
+ renderThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'accessibility',
+ title: 'RenderAccessibilityImpl::SendPendingAccessibilityEvents',
+ start: 1400,
+ dur: 188,
+ end: 1588,
+ }));
+ });
+ }
+
+ test('accessibilityMetric', function() {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.accessibilityMetric(histograms, makeTestModel());
+ assert.closeTo(93, histograms.getHistogramNamed(
+ 'browser_accessibility_events').sum, 1e-2);
+ assert.closeTo(416, histograms.getHistogramNamed(
+ 'render_accessibility_events').sum, 1e-2);
+ assert.closeTo(12, histograms.getHistogramNamed(
+ 'render_accessibility_locations').sum, 1e-2);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/all_fixed_color_schemes.html b/chromium/third_party/catapult/tracing/tracing/metrics/all_fixed_color_schemes.html
new file mode 100644
index 00000000000..be843ee9aca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/all_fixed_color_schemes.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!-- We import all files that register fixed color schemes which are used by
+ metrics so that metrics code can depend on a single place. -->
+<link rel="import" href="/tracing/extras/chrome/chrome_processes.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html b/chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html
new file mode 100644
index 00000000000..68c1b2f34ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/all_metrics.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/accessibility_metric.html">
+<link rel="import" href="/tracing/metrics/android_startup_metric.html">
+<link rel="import" href="/tracing/metrics/android_systrace_metric.html">
+<link rel="import" href="/tracing/metrics/blink/gc_metric.html">
+<link rel="import" href="/tracing/metrics/blink/leak_detection_metric.html">
+<link rel="import" href="/tracing/metrics/console_error_metric.html">
+<link rel="import" href="/tracing/metrics/cpu_process_metric.html">
+<link rel="import" href="/tracing/metrics/media_metric.html">
+<link rel="import" href="/tracing/metrics/rendering/rendering_metric.html">
+<link rel="import" href="/tracing/metrics/sample_exception_metric.html">
+<link rel="import" href="/tracing/metrics/sample_metric.html">
+<link rel="import" href="/tracing/metrics/spa_navigation_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/clock_sync_latency_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/cpu_time_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/expected_queueing_time_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/limited_cpu_time_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/loading_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/long_tasks_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/memory_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/new_cpu_time_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/power_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/responsiveness_metric.html">
+<link rel="import" href="/tracing/metrics/system_health/webview_startup_metric.html">
+<link rel="import" href="/tracing/metrics/tabs_metric.html">
+<link rel="import" href="/tracing/metrics/tracing_metric.html">
+<link rel="import" href="/tracing/metrics/v8/execution_metric.html">
+<link rel="import" href="/tracing/metrics/v8/gc_metric.html">
+<link rel="import" href="/tracing/metrics/v8/runtime_stats_metric.html">
+<link rel="import" href="/tracing/metrics/v8/v8_metrics.html">
+<link rel="import" href="/tracing/metrics/vr/frame_cycle_duration_metric.html">
+<link rel="import" href="/tracing/metrics/vr/webvr_metric.html">
+<link rel="import" href="/tracing/metrics/webrtc/webrtc_rendering_metric.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html
new file mode 100644
index 00000000000..4b6bc49ee68
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+// The |androidStartupMetric| produces metrics that start counting at the
+// earliest moment the Chrome code on Android is executed.
+// A few histograms are produced with the names as described below:
+// 1. messageloop_start_time - time till the message loop of the browser main
+// starts processing posted tasts (after having loaded the Profile)
+// 2. first_contentful_paint_time - time to the first contentful paint of the
+// page loaded at startup
+// The metric also supports multiple browser restarts, in this case multiple
+// samples would be added to the histograms above.
+tr.exportTo('tr.metrics.sh', function() {
+ const MESSAGE_LOOP_EVENT_NAME =
+ 'Startup.BrowserMessageLoopStartTimeFromMainEntry3';
+ const FIRST_CONTENTFUL_PAINT_EVENT_NAME = 'firstContentfulPaint';
+ function androidStartupMetric(histograms, model) {
+ // Walk the browser slices, extract timestamps for the browser start,
+ // message loop start. TODO(crbug.com/883290): re-introduce
+ // request_start_time.
+ let messageLoopStartEvents = [];
+ const chromeHelper =
+ model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ if (!chromeHelper) return;
+ for (const helper of chromeHelper.browserHelpers) {
+ for (const ev of helper.mainThread.asyncSliceGroup.childEvents()) {
+ if (ev.title === MESSAGE_LOOP_EVENT_NAME) {
+ messageLoopStartEvents.push(ev);
+ }
+ }
+ }
+
+ // Walk the renderer slices and extract the 'first contentful paint'
+ // histogram samples.
+ let firstContentfulPaintEvents = [];
+ const rendererHelpers = chromeHelper.rendererHelpers;
+ const pids = Object.keys(rendererHelpers);
+ for (const rendererHelper of Object.values(chromeHelper.rendererHelpers)) {
+ if (!rendererHelper.mainThread) continue;
+ for (const ev of rendererHelper.mainThread.sliceGroup.childEvents()) {
+ if (ev.title === FIRST_CONTENTFUL_PAINT_EVENT_NAME) {
+ firstContentfulPaintEvents.push(ev);
+ // There are usually several 'First Contentful Paint' events recorded
+ // for each page load. Take only the first one per renderer.
+ break;
+ }
+ }
+ }
+
+ // Fallback to scanning all processes if important events are not found.
+ let totalBrowserStarts = messageLoopStartEvents.length;
+ let totalFcpEvents = firstContentfulPaintEvents.length;
+ if (totalFcpEvents !== totalBrowserStarts || totalBrowserStarts === 0) {
+ messageLoopStartEvents = [];
+ firstContentfulPaintEvents = [];
+ // Sometimes either the browser process or the renderer process does not
+ // have the proper name attached. This often happens when both chrome
+ // trace and systrace are merged. Other multi-process trickery, like
+ // Perfetto, may also cause this.
+ for (const proc of Object.values(model.processes)) {
+ for (const ev of proc.getDescendantEvents()) {
+ if (ev.title === MESSAGE_LOOP_EVENT_NAME) {
+ messageLoopStartEvents.push(ev);
+ }
+ }
+ for (const ev of proc.getDescendantEvents()) {
+ if (ev.title === FIRST_CONTENTFUL_PAINT_EVENT_NAME) {
+ firstContentfulPaintEvents.push(ev);
+ break;
+ }
+ }
+ }
+ totalBrowserStarts = messageLoopStartEvents.length;
+ totalFcpEvents = firstContentfulPaintEvents.length;
+ }
+
+ // Sometimes a number of early trace events are not recorded because tracing
+ // takes time to start. This leads to having more FCP events than
+ // messageloop_start events. As a workaround ignore the FCP events for which
+ // there are no browser starts.
+ function orderEvents(event1, event2) {
+ return event1.start - event2.start;
+ }
+ messageLoopStartEvents.sort(orderEvents);
+ firstContentfulPaintEvents.sort(orderEvents);
+
+ if (totalFcpEvents < totalBrowserStarts) {
+ throw new Error('Found less FCP events (' + totalFcpEvents +
+ ') than browser starts (' + totalBrowserStarts + ')');
+ }
+
+ // Group the relevant events with the corresponding browser starts and emit
+ // the metrics.
+ const messageLoopStartHistogram = histograms.createHistogram(
+ 'messageloop_start_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, []);
+ const firstContentfulPaintHistogram = histograms.createHistogram(
+ 'first_contentful_paint_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, []);
+ // The earliest browser start is skipped because it is affected by the state
+ // of the system coming from the time before the benchmark started. Removing
+ // these influencing factors allows reducing measurement noise.
+ // Note: Two early starts are ignored below, the reasons for spurious
+ // slowdowns of the 2nd run are not known yet, see http://crbug.com/891797.
+ let fcpIndex = 0;
+ for (let loopStartIndex = 0; loopStartIndex < totalBrowserStarts;) {
+ const startEvent = messageLoopStartEvents[loopStartIndex];
+ if (fcpIndex === totalFcpEvents) {
+ break;
+ }
+
+ // Skip all FCP events that appear before the next browser start.
+ const fcpEvent = firstContentfulPaintEvents[fcpIndex];
+ if (fcpEvent.start < startEvent.start) {
+ fcpIndex++;
+ continue;
+ }
+
+ // The pair of matching events is found.
+ loopStartIndex++;
+
+ // Skip the two initial FCP events and (potentially missing) browser
+ // starts.
+ if (fcpIndex < 2) {
+ continue;
+ }
+
+ // Record the histograms.
+ messageLoopStartHistogram.addSample(startEvent.duration,
+ {events: new tr.v.d.RelatedEventSet([startEvent])});
+ firstContentfulPaintHistogram.addSample(
+ fcpEvent.end - startEvent.start,
+ {events: new tr.v.d.RelatedEventSet([startEvent, fcpEvent])});
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(androidStartupMetric);
+
+ return {
+ androidStartupMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html
new file mode 100644
index 00000000000..5ebf601fec6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/android_startup_metric_test.html
@@ -0,0 +1,191 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/android_startup_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createBrowserThread(model) {
+ const browserProcess = model.getOrCreateProcess(tr.b.GUID.allocateSimple());
+ const mainThread = browserProcess.getOrCreateThread(
+ tr.b.GUID.allocateSimple());
+ // Initializing the thread name helps passing validation checks made by the
+ // ChromeModelHelper.
+ mainThread.name = 'CrBrowserMain';
+ return mainThread;
+ }
+
+ function createRendererThread(model) {
+ const rendererProcess = model.getOrCreateProcess(
+ tr.b.GUID.allocateSimple());
+ const rendererMainThread =
+ rendererProcess.getOrCreateThread(tr.b.GUID.allocateSimple());
+ rendererMainThread.name = 'CrRendererMain';
+ return rendererMainThread;
+ }
+
+ // Adds a browser and renderer to the process, with a few key events necessary
+ // to calculate the |androidStartupMetric|. An |offset| can be added to all
+ // events and the length of a few events can be extended by
+ // |incrementForMetrics|.
+ function fillModelWithOneBrowserSession(model, offset, incrementForMetrics) {
+ // In order for the tests below to succeed with strictEqual, the floating
+ // point values should have exact representation as IEEE754 float.
+ createBrowserThread(model).asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'startup',
+ title: 'Startup.BrowserMessageLoopStartTimeFromMainEntry3',
+ start: (offset + 6800.125),
+ duration: (incrementForMetrics + 1700.0625)}));
+ const rendererMainThread = createRendererThread(model);
+ rendererMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: (offset + 8400.125 + incrementForMetrics),
+ duration: 0.0,
+ args: {frame: '0x0'}}));
+
+ // Add an extra FCP event in the same renderer process appearing after the
+ // initial FCP even to check that it is ignored by metric computations.
+ rendererMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: (offset + 8400.125 + incrementForMetrics + 0.125),
+ duration: 0.0,
+ args: {frame: '0x0'}}));
+ }
+
+ // Adds early messageloop and FCP events. The metric should ignore these very
+ // first messageloop start and FCP events in the trace. The specific lengths
+ // are not important.
+ function addEarlyEventsToBeIgnored(model, offset) {
+ createBrowserThread(model).asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'startup',
+ title: 'Startup.BrowserMessageLoopStartTimeFromMainEntry3',
+ start: (offset + 1.0),
+ duration: 10.0}));
+ createRendererThread(model).sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: (offset + 2.0),
+ duration: 1.0,
+ args: {frame: '0x0'}}));
+ }
+
+ function makeTestModel(offset, incrementForMetrics) {
+ return tr.c.TestUtils.newModel(function(model) {
+ fillModelWithOneBrowserSession(model, offset, incrementForMetrics);
+ addEarlyEventsToBeIgnored(model, offset);
+ addEarlyEventsToBeIgnored(model, offset + 20.0);
+ });
+ }
+
+ // Checks recording of the main histograms in the simplest case.
+ test('androidStartupMetric_simple', function() {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.androidStartupMetric(histograms, makeTestModel(0.0, 0.0));
+ const messageLoopStartHistogram = histograms.getHistogramNamed(
+ 'messageloop_start_time');
+ assert.strictEqual(1, messageLoopStartHistogram.numValues);
+ assert.strictEqual(1700.0625, messageLoopStartHistogram.average);
+ const firstContentfulPaintHistogram = histograms.getHistogramNamed(
+ 'first_contentful_paint_time');
+ assert.strictEqual(1, firstContentfulPaintHistogram.numValues);
+ assert.strictEqual(1600.0, firstContentfulPaintHistogram.average);
+ });
+
+ // Emulates loss of the initial message loop start event. Checks that this
+ // event is ignored and the |androidStartupMetric| does not crash.
+ test('androidStartupMetric_missingOneBrowserStart', function() {
+ function makeTestModelWithOneEventMissing() {
+ return tr.c.TestUtils.newModel(function(model) {
+ fillModelWithOneBrowserSession(model, 0.0, 0.0);
+ // Note: the initial Startup.BrowserMessageLoopStartTimeFromMainEntry3'
+ // is intentionally missing.
+ createRendererThread(model).sliceGroup.pushSlice(
+ tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: 2.0,
+ duration: 1.0,
+ args: {frame: '0x0'}}));
+ createBrowserThread(model).asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'startup',
+ title: 'Startup.BrowserMessageLoopStartTimeFromMainEntry3',
+ start: (20.0 + 1.0),
+ duration: 10.0}));
+ createRendererThread(model).sliceGroup.pushSlice(
+ tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: (20.0 + 2.0),
+ duration: 1.0,
+ args: {frame: '0x0'}}));
+ });
+ }
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.androidStartupMetric(histograms,
+ makeTestModelWithOneEventMissing(0.0));
+ const messageLoopStartHistogram = histograms.getHistogramNamed(
+ 'messageloop_start_time');
+ assert.strictEqual(1, messageLoopStartHistogram.numValues);
+ assert.strictEqual(1700.0625, messageLoopStartHistogram.average);
+ const firstContentfulPaintHistogram = histograms.getHistogramNamed(
+ 'first_contentful_paint_time');
+ assert.strictEqual(1, firstContentfulPaintHistogram.numValues);
+ assert.strictEqual(1600.0, firstContentfulPaintHistogram.average);
+ });
+
+ // Checks the metrics after adding an offset to events in the model, and
+ // making a few durations longer by a constant.
+ test('androidStartupMetric_withOffsetAndLongerTask', function() {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.androidStartupMetric(histograms, makeTestModel(5.0, 7.0));
+ const messageLoopStartHistogram = histograms.getHistogramNamed(
+ 'messageloop_start_time');
+ assert.strictEqual(1, messageLoopStartHistogram.numValues);
+ assert.strictEqual(1707.0625, messageLoopStartHistogram.average);
+ const firstContentfulPaintHistogram = histograms.getHistogramNamed(
+ 'first_contentful_paint_time');
+ assert.strictEqual(1, firstContentfulPaintHistogram.numValues);
+ assert.strictEqual(1607.0, firstContentfulPaintHistogram.average);
+ });
+
+ test('androidStartupMetric_twoSessions', function() {
+ function makeTestModelWithTwoSessionsOneDelayed(
+ offset, incrementForMetrics) {
+ return tr.c.TestUtils.newModel(function(model) {
+ fillModelWithOneBrowserSession(model, 0.0, 0.0);
+ fillModelWithOneBrowserSession(model, offset, incrementForMetrics);
+ addEarlyEventsToBeIgnored(model, 0.0, 0.0);
+ addEarlyEventsToBeIgnored(model, 0.0, 1.0);
+ });
+ }
+ const delta = 0.125;
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.androidStartupMetric(histograms,
+ makeTestModelWithTwoSessionsOneDelayed(10000.0, delta));
+ const messageLoopStartHistogram = histograms.getHistogramNamed(
+ 'messageloop_start_time');
+ assert.strictEqual(2, messageLoopStartHistogram.numValues);
+ assert.strictEqual(1700.0625, messageLoopStartHistogram.min);
+ assert.strictEqual(1700.0625 + delta, messageLoopStartHistogram.max);
+ const firstContentfulPaintHistogram = histograms.getHistogramNamed(
+ 'first_contentful_paint_time');
+ assert.strictEqual(2, firstContentfulPaintHistogram.numValues);
+ assert.strictEqual(1600.0, firstContentfulPaintHistogram.min);
+ assert.strictEqual(1600.0 + delta, firstContentfulPaintHistogram.max);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/android_systrace_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/android_systrace_metric.html
new file mode 100644
index 00000000000..96c1ca0295c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/android_systrace_metric.html
@@ -0,0 +1,224 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ const MAX_INPUT_EVENT_TO_STARTUP_DELAY_IN_MS = 2000;
+ // Post-startup activity draw delay.
+ const MIN_DRAW_DELAY_IN_MS = 80;
+ const MAX_DRAW_DELAY_IN_MS = 2000;
+
+ function findProcess(processName, model) {
+ for (const pid in model.processes) {
+ const process = model.processes[pid];
+ if (process.name === processName) {
+ return process;
+ }
+ }
+ return undefined;
+ }
+
+ function findThreads(process, threadPrefix) {
+ if (process === undefined) return undefined;
+ const threads = [];
+ for (const tid in process.threads) {
+ const thread = process.threads[tid];
+ if (thread.name.startsWith(threadPrefix)) {
+ threads.push(thread);
+ }
+ }
+ return threads;
+ }
+
+ function findUIThread(process) {
+ if (process === undefined) return undefined;
+ const threads = findThreads(process, 'UI Thread');
+ if (threads !== undefined && threads.length === 1) {
+ return threads[0];
+ }
+ return process.threads[process.pid];
+ }
+
+ // Returns slices with actual app's process startup, excluding other delays.
+ function findLaunchSlices(model) {
+ const launches = [];
+ const binders = findThreads(findProcess('system_server', model), 'Binder');
+ for (const binderId in binders) {
+ const binder = binders[binderId];
+ for (const sliceId in binder.asyncSliceGroup.slices) {
+ const slice = binder.asyncSliceGroup.slices[sliceId];
+ if (slice.title.startsWith('launching:')) {
+ launches.push(slice);
+ }
+ }
+ }
+ return launches;
+ }
+
+ // Try to find draw event when activity just shown.
+ function findDrawSlice(appName, startNotBefore, model) {
+ let drawSlice = undefined;
+ const thread = findUIThread(findProcess(appName, model));
+ if (thread === undefined) return undefined;
+
+ for (const sliceId in thread.sliceGroup.slices) {
+ const slice = thread.sliceGroup.slices[sliceId];
+ if (slice.start < startNotBefore + MIN_DRAW_DELAY_IN_MS ||
+ slice.start > startNotBefore + MAX_DRAW_DELAY_IN_MS) continue;
+ if (slice.title !== 'draw') continue;
+ // TODO(kraynov): Add reportFullyDrawn() support.
+ if (drawSlice === undefined || slice.start < drawSlice.start) {
+ drawSlice = slice;
+ }
+ }
+ return drawSlice;
+ }
+
+ // Try to find input event before a process starts.
+ function findInputEventSlice(endNotAfter, model) {
+ const endNotBefore = endNotAfter - MAX_INPUT_EVENT_TO_STARTUP_DELAY_IN_MS;
+ let inputSlice = undefined;
+ const systemUi = findUIThread(findProcess('com.android.systemui', model));
+ if (systemUi === undefined) return undefined;
+
+ for (const sliceId in systemUi.asyncSliceGroup.slices) {
+ const slice = systemUi.asyncSliceGroup.slices[sliceId];
+ if (slice.end > endNotAfter || slice.end < endNotBefore) continue;
+ if (slice.title !== 'deliverInputEvent') continue;
+ if (inputSlice === undefined || slice.end > inputSlice.end) {
+ inputSlice = slice;
+ }
+ }
+ return inputSlice;
+ }
+
+ function computeStartupTimeInMs(appName, launchSlice, model) {
+ let startupStart = launchSlice.start;
+ let startupEnd = launchSlice.end;
+ const drawSlice = findDrawSlice(appName, launchSlice.end, model);
+ if (drawSlice !== undefined) {
+ startupEnd = drawSlice.end;
+ }
+ const inputSlice = findInputEventSlice(launchSlice.start, model);
+ if (inputSlice !== undefined) {
+ startupStart = inputSlice.start;
+ }
+ return startupEnd - startupStart;
+ }
+
+ // App startup time metric.
+ function measureStartup(histograms, model) {
+ const launches = findLaunchSlices(model);
+ for (const sliceId in launches) {
+ const launchSlice = launches[sliceId];
+ const appName = launchSlice.title.split(': ')[1];
+ const startupMs = computeStartupTimeInMs(appName, launchSlice, model);
+ histograms.createHistogram(`android:systrace:startup:${appName}`,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, startupMs);
+ }
+ }
+
+ // Metric which measures time spent by process threads in each thread state.
+ // The value of metric is a time percentage relative to the length of selected
+ // range of interest.
+ function measureThreadStates(histograms, model, rangeOfInterest) {
+ for (const pid in model.processes) {
+ const process = model.processes[pid];
+ if (process.name === undefined) continue;
+
+ let hasSlices = false;
+ let timeRunning = 0;
+ let timeRunnable = 0;
+ let timeSleeping = 0;
+ let timeUninterruptible = 0;
+ let timeBlockIO = 0;
+ let timeUnknown = 0;
+
+ for (const tid in process.threads) {
+ const thread = process.threads[tid];
+ if (thread.timeSlices === undefined) continue;
+
+ for (const sliceId in thread.timeSlices) {
+ const slice = thread.timeSlices[sliceId];
+ const sliceRange =
+ tr.b.math.Range.fromExplicitRange(slice.start, slice.end);
+ const intersection = rangeOfInterest.findIntersection(sliceRange);
+ const duration = intersection.duration;
+ if (duration === 0) continue;
+ hasSlices = true;
+
+ if (slice.title === 'Running') {
+ timeRunning += duration;
+ } else if (slice.title === 'Runnable') {
+ timeRunnable += duration;
+ } else if (slice.title === 'Sleeping') {
+ timeSleeping += duration;
+ } else if (slice.title.startsWith('Uninterruptible')) {
+ timeUninterruptible += duration;
+ if (slice.title.includes('Block I/O')) timeBlockIO += duration;
+ } else {
+ timeUnknown += duration;
+ }
+ }
+ }
+
+ if (hasSlices) {
+ // For sake of simplicity we don't count wall time for each
+ // thread/process and just calculate relative values against selected
+ // range of interest.
+ const wall = rangeOfInterest.max - rangeOfInterest.min;
+ histograms.createHistogram(
+ `android:systrace:threadtime:${process.name}:running`,
+ tr.b.Unit.byName.normalizedPercentage, timeRunning / wall);
+ histograms.createHistogram(
+ `android:systrace:threadtime:${process.name}:runnable`,
+ tr.b.Unit.byName.normalizedPercentage, timeRunnable / wall);
+ histograms.createHistogram(
+ `android:systrace:threadtime:${process.name}:sleeping`,
+ tr.b.Unit.byName.normalizedPercentage, timeSleeping / wall);
+ histograms.createHistogram(
+ `android:systrace:threadtime:${process.name}:blockio`,
+ tr.b.Unit.byName.normalizedPercentage, timeBlockIO / wall);
+ histograms.createHistogram(
+ `android:systrace:threadtime:${process.name}:uninterruptible`,
+ tr.b.Unit.byName.normalizedPercentage, timeUninterruptible / wall);
+
+ // In case of changing names in systrace and importer.
+ if (timeUnknown > 0) {
+ histograms.createHistogram(
+ `android:systrace:threadtime:${process.name}:unknown`,
+ tr.b.Unit.byName.normalizedPercentage, timeUnknown / wall);
+ }
+ }
+ }
+ }
+
+ function androidSystraceMetric(histograms, model, options) {
+ let rangeOfInterest = model.bounds;
+ if (options !== undefined && options.rangeOfInterest !== undefined) {
+ rangeOfInterest = options.rangeOfInterest;
+ }
+
+ measureStartup(histograms, model);
+ measureThreadStates(histograms, model, rangeOfInterest);
+ }
+
+ tr.metrics.MetricRegistry.register(androidSystraceMetric, {
+ supportsRangeOfInterest: true
+ });
+
+ return {
+ androidSystraceMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/android_systrace_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/android_systrace_metric_test.html
new file mode 100644
index 00000000000..76936416503
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/android_systrace_metric_test.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/android_systrace_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const SYSTRACE_CLOCK_SYNC =
+ '<100>-100 (-----) [000] ...1 0.000000: tracing_mark_write: ' +
+ 'trace_event_clock_sync: parent_ts=0\n' +
+ '<100>-100 (-----) [000] ...1 0.000000: tracing_mark_write: ' +
+ 'trace_event_clock_sync: realtime_ts=1487002000000';
+
+ // Some event is required to help importer detect a parent process.
+ const SYSTRACE_SYSTEM_SERVER_ANNOTATION =
+ 'system_server-101 ( 101) [000] ...1 0.550000: ' +
+ 'tracing_mark_write: S|101|dummyEvent|201\n' +
+ 'system_server-101 ( 101) [000] ...1 0.551000: ' +
+ 'tracing_mark_write: F|101|dummyEvent|201';
+
+ const SYSTRACE_TOUCH_SLICE =
+ 'com.android.systemui-102 ( 102) [000] ...1 2.500000: ' +
+ 'tracing_mark_write: S|102|deliverInputEvent|202\n' +
+ 'com.android.systemui-102 ( 102) [000] ...1 2.510000: ' +
+ 'tracing_mark_write: F|102|deliverInputEvent|202';
+
+ const SYSTRACE_LAUNCH_SLICE =
+ 'Binder:101_C-103 ( 101) [000] ...1 2.750000: ' +
+ 'tracing_mark_write: S|101|launching: com.android.apps.sms|203\n' +
+ 'android.display-104 ( 101) [000] ...1 4.250000: ' +
+ 'tracing_mark_write: F|101|launching: com.android.apps.sms|203';
+
+ const SYSTRACE_DRAW_SLICE =
+ 'com.android.apps.sms-105 ( 105) [000] ...1 4.450000: ' +
+ 'tracing_mark_write: B|105|draw\n' +
+ 'com.android.apps.sms-105 ( 105) [000] ...1 4.455000: ' +
+ 'tracing_mark_write: E';
+
+ function makeModel(systraceLines) {
+ const events = JSON.stringify({
+ traceEvents: [],
+ systemTraceEvents: SYSTRACE_CLOCK_SYNC + '\n' + systraceLines.join('\n')
+ });
+ const model = tr.c.TestUtils.newModelWithEvents([events]);
+ // Fix missing process names.
+ for (const pid in model.processes) {
+ const process = model.processes[pid];
+ if (process.name !== undefined) continue;
+ if (process.threads[pid] !== undefined) {
+ process.name = process.threads[pid].name;
+ }
+ }
+ return model;
+ }
+
+ function testStartup(systrace, expectedTimeInMs) {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.androidSystraceMetric(histograms, makeModel(systrace));
+ assert.lengthOf(histograms, 1);
+ const startupHist = histograms.getHistogramNamed(
+ 'android:systrace:startup:com.android.apps.sms').running;
+ assert.strictEqual(startupHist.count, 1);
+ assert.closeTo(startupHist.mean, expectedTimeInMs, 1e-5);
+ }
+
+ test('androidSystraceMetric_startup_noData', function() {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.androidSystraceMetric(histograms, makeModel([]));
+ assert.lengthOf(histograms, 0);
+ });
+
+ test('androidSystraceMetric_startup_simple', function() {
+ const systrace = [
+ SYSTRACE_SYSTEM_SERVER_ANNOTATION,
+ SYSTRACE_TOUCH_SLICE,
+ SYSTRACE_LAUNCH_SLICE,
+ SYSTRACE_DRAW_SLICE
+ ];
+ testStartup(systrace, 1955);
+ });
+
+ test('androidSystraceMetric_startup_noTouch', function() {
+ const systrace = [
+ SYSTRACE_SYSTEM_SERVER_ANNOTATION,
+ SYSTRACE_LAUNCH_SLICE,
+ SYSTRACE_DRAW_SLICE
+ ];
+ testStartup(systrace, 1705);
+ });
+
+ test('androidSystraceMetric_startup_noDraw', function() {
+ const systrace = [
+ SYSTRACE_SYSTEM_SERVER_ANNOTATION,
+ SYSTRACE_TOUCH_SLICE,
+ SYSTRACE_LAUNCH_SLICE,
+ ];
+ testStartup(systrace, 1750);
+ });
+
+ test('androidSystraceMetric_startup_noTouchNoDraw', function() {
+ const systrace = [
+ SYSTRACE_SYSTEM_SERVER_ANNOTATION,
+ SYSTRACE_LAUNCH_SLICE,
+ ];
+ testStartup(systrace, 1500);
+ });
+
+ test('androidSystraceMetric_threadtime_simple', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ const process = model.getOrCreateProcess(42);
+ process.name = 'garbage_producer';
+ const thread = process.getOrCreateThread(42);
+ thread.timeSlices = [
+ tr.c.TestUtils.newThreadSlice(thread, 'Sleeping', 0, 100),
+ tr.c.TestUtils.newThreadSlice(thread, 'Running', 100, 400)
+ ];
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.androidSystraceMetric(histograms, model);
+ assert.lengthOf(histograms, 5);
+
+ const assertHistValue = function(name, expectedValue) {
+ const hist = histograms.getHistogramNamed(
+ `android:systrace:threadtime:garbage_producer:${name}`);
+ assert.strictEqual(hist.running.count, 1);
+ assert.closeTo(hist.running.mean, expectedValue, 1e-5);
+ };
+ assertHistValue('running', 0.8);
+ assertHistValue('runnable', 0);
+ assertHistValue('sleeping', 0.2);
+ assertHistValue('blockio', 0);
+ assertHistValue('uninterruptible', 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric.html
new file mode 100644
index 00000000000..641c8bd0c9f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric.html
@@ -0,0 +1,265 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/v8/utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.blink', function() {
+ // Maps the Blink GC events in timeline to telemetry friendly names.
+ const BLINK_TOP_GC_EVENTS = {
+ 'BlinkGC.AtomicPhase': 'blink-gc-atomic-phase',
+ 'BlinkGC.CompleteSweep': 'blink-gc-complete-sweep',
+ 'BlinkGC.IncrementalMarkingStartMarking': 'blink-gc-incremental-start',
+ 'BlinkGC.IncrementalMarkingStep': 'blink-gc-incremental-step',
+ 'BlinkGC.LazySweepInIdle': 'blink-gc-lazy-sweep-idle',
+ 'BlinkGC.LazySweepOnAllocation': 'blink-gc-lazy-sweep-allocation'
+ };
+
+ function blinkGarbageCollectionEventName(event) {
+ return BLINK_TOP_GC_EVENTS[event.title];
+ }
+
+ function isNonForcedBlinkGarbageCollectionEvent(event) {
+ return event.title in BLINK_TOP_GC_EVENTS &&
+ (!event.args || !event.args.forced) &&
+ !tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);
+ }
+
+ function isNonNestedNonForcedBlinkGarbageCollectionEvent(event) {
+ return isNonForcedBlinkGarbageCollectionEvent(event) &&
+ !tr.metrics.v8.utils.findParent(event,
+ tr.metrics.v8.utils.isGarbageCollectionEvent);
+ }
+
+ function blinkGcMetric(histograms, model) {
+ addDurationOfTopEvents(histograms, model);
+ addTotalDurationOfTopEvents(histograms, model);
+ addIdleTimesOfTopEvents(histograms, model);
+ addTotalIdleTimesOfTopEvents(histograms, model);
+ addTotalDurationOfBlinkAndV8TopEvents(histograms, model);
+ }
+
+ tr.metrics.MetricRegistry.register(blinkGcMetric);
+
+ const timeDurationInMs_smallerIsBetter =
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;
+ const percentage_biggerIsBetter =
+ tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;
+
+ // 0.1 steps from 0 to 20 since it is the most common range.
+ // Exponentially increasing steps from 20 to 200.
+ const CUSTOM_BOUNDARIES = tr.v.HistogramBinBoundaries.createLinear(0, 20, 200)
+ .addExponentialBins(200, 100);
+
+ function createNumericForTopEventTime(name) {
+ const n = new tr.v.Histogram(name,
+ timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ n.customizeSummaryOptions({
+ avg: true,
+ count: true,
+ max: true,
+ min: false,
+ std: true,
+ sum: true,
+ percentile: [0.90]});
+ return n;
+ }
+
+ function createNumericForTotalEventTime(name) {
+ const n = new tr.v.Histogram(name,
+ timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ n.customizeSummaryOptions({
+ avg: false,
+ count: true,
+ max: false,
+ min: false,
+ std: false,
+ sum: true,
+ percentile: [0.90]});
+ return n;
+ }
+
+ function createNumericForUnifiedEventTime(name) {
+ const n = new tr.v.Histogram(name,
+ timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ n.customizeSummaryOptions({
+ avg: false,
+ count: true,
+ max: true,
+ min: false,
+ std: false,
+ sum: true,
+ percentile: [0.90]});
+ return n;
+ }
+
+ function createNumericForIdleTime(name) {
+ const n = new tr.v.Histogram(name,
+ timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ n.customizeSummaryOptions({
+ avg: true,
+ count: false,
+ max: true,
+ min: false,
+ std: false,
+ sum: true,
+ percentile: []
+ });
+ return n;
+ }
+
+ function createPercentage(name, numerator, denominator) {
+ const histogram = new tr.v.Histogram(name, percentage_biggerIsBetter);
+ if (denominator === 0) {
+ histogram.addSample(0);
+ } else {
+ histogram.addSample(numerator / denominator);
+ }
+ return histogram;
+ }
+
+ /**
+ * Example output:
+ * - blink-gc-atomic-phase
+ */
+ function addDurationOfTopEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ isNonForcedBlinkGarbageCollectionEvent,
+ blinkGarbageCollectionEventName,
+ function(name, events) {
+ const cpuDuration = createNumericForTopEventTime(name);
+ for (const event of events) {
+ cpuDuration.addSample(event.cpuDuration);
+ }
+ histograms.addHistogram(cpuDuration);
+ }
+ );
+ }
+
+ /**
+ * Example output:
+ * - blink-gc-total_sum
+ */
+ function addTotalDurationOfTopEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ isNonForcedBlinkGarbageCollectionEvent,
+ event => 'blink-gc-total',
+ function(name, events) {
+ const cpuDuration = createNumericForTotalEventTime(name);
+ for (const event of events) {
+ cpuDuration.addSample(event.cpuDuration);
+ }
+ histograms.addHistogram(cpuDuration);
+ }
+ );
+ }
+
+ /**
+ * Example output:
+ * - blink-gc-atomic-phase_idle_deadline_overrun,
+ * - blink-gc-atomic-phase_outside_idle,
+ * - blink-gc-atomic-phase_percentage_idle.
+ */
+ function addIdleTimesOfTopEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ isNonForcedBlinkGarbageCollectionEvent,
+ blinkGarbageCollectionEventName,
+ function(name, events) {
+ addIdleTimes(histograms, model, name, events);
+ }
+ );
+ }
+
+ /**
+ * Example output:
+ * - blink-gc-total_idle_deadline_overrun,
+ * - blink-gc-total_outside_idle,
+ * - blink-gc-total_percentage_idle.
+ */
+ function addTotalIdleTimesOfTopEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ isNonForcedBlinkGarbageCollectionEvent,
+ event => 'blink-gc-total',
+ function(name, events) {
+ addIdleTimes(histograms, model, name, events);
+ }
+ );
+ }
+
+ function addIdleTimes(histograms, model, name, events) {
+ const cpuDuration = createNumericForIdleTime(name + '_cpu');
+ const insideIdle = createNumericForIdleTime(name + '_inside_idle');
+ const outsideIdle = createNumericForIdleTime(name + '_outside_idle');
+ const idleDeadlineOverrun = createNumericForIdleTime(
+ name + '_idle_deadline_overrun');
+ for (const event of events) {
+ const idleTask = tr.metrics.v8.utils.findParent(
+ event, tr.metrics.v8.utils.isIdleTask);
+ let inside = 0;
+ let overrun = 0;
+ if (idleTask) {
+ const allottedTime = idleTask.args.allotted_time_ms;
+ if (event.duration > allottedTime) {
+ overrun = event.duration - allottedTime;
+ // Don't count time over the deadline as being inside idle time.
+ // Since the deadline should be relative to wall clock we
+ // compare allotted_time_ms with wall duration instead of thread
+ // duration, and then assume the thread duration was inside idle
+ // for the same percentage of time.
+ inside = event.cpuDuration * allottedTime / event.duration;
+ } else {
+ inside = event.cpuDuration;
+ }
+ }
+ cpuDuration.addSample(event.cpuDuration);
+ insideIdle.addSample(inside);
+ outsideIdle.addSample(event.cpuDuration - inside);
+ idleDeadlineOverrun.addSample(overrun);
+ }
+ histograms.addHistogram(idleDeadlineOverrun);
+ histograms.addHistogram(outsideIdle);
+ const percentage = createPercentage(
+ name + '_percentage_idle', insideIdle.sum, cpuDuration.sum);
+ histograms.addHistogram(percentage);
+ }
+
+ function isV8OrBlinkTopLevelGarbageCollectionEvent(event) {
+ return tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent(event) ||
+ isNonNestedNonForcedBlinkGarbageCollectionEvent(event);
+ }
+
+ /**
+ * Example output:
+ * - unified-gc-total_sum
+ * - unified-gc-total_max
+ * - unified-gc-total_count
+ */
+ function addTotalDurationOfBlinkAndV8TopEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ isV8OrBlinkTopLevelGarbageCollectionEvent,
+ event => 'unified-gc-total',
+ function(name, events) {
+ const cpuDuration = createNumericForUnifiedEventTime(name);
+ for (const event of events) {
+ cpuDuration.addSample(event.cpuDuration);
+ }
+ histograms.addHistogram(cpuDuration);
+ }
+ );
+ }
+
+ return {
+ blinkGcMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html
new file mode 100644
index 00000000000..924527f126b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/blink/gc_metric_test.html
@@ -0,0 +1,347 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/blink/gc_metric.html">
+<link rel="import" href="/tracing/metrics/v8/utils.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createModel(start, end, slices) {
+ const opts = {
+ customizeModelCallback(model) {
+ const process = model.getOrCreateProcess(1);
+ const thread = process.getOrCreateThread(2);
+ const group = thread.sliceGroup;
+ slices.forEach(function(slice) {
+ group.pushSlice(tr.c.TestUtils.newSliceEx(slice));
+ });
+ group.createSubSlices();
+ }
+ };
+ const model = tr.c.TestUtils.newModelWithEvents([], opts);
+ return model;
+ }
+
+ function constructName(name, suffix) {
+ return name + '_' + suffix;
+ }
+
+ function run(slices) {
+ const histograms = new tr.v.HistogramSet();
+ const startTime = slices.reduce(
+ (acc, slice) => (Math.min(acc, slice.start)));
+ const endTime = slices.reduce((acc, slice) => (Math.max(acc, slice.end)));
+ const model = createModel(startTime - 1, endTime + 1, slices);
+ tr.metrics.blink.blinkGcMetric(histograms, model);
+ return histograms;
+ }
+
+ test('topEvents', function() {
+ const events = {
+ 'BlinkGC.AtomicPhase': 'blink-gc-atomic-phase',
+ 'BlinkGC.CompleteSweep': 'blink-gc-complete-sweep',
+ 'BlinkGC.LazySweepInIdle': 'blink-gc-lazy-sweep-idle'
+ };
+ for (const [timelineName, telemetryName] of Object.entries(events)) {
+ const slices = [
+ {
+ title: timelineName, args: {}, start: 100, end: 200,
+ cpuStart: 100, cpuEnd: 200
+ }
+ ];
+ const actual = run(slices);
+
+ let value = actual.getHistogramNamed(telemetryName);
+ assert.strictEqual(value.running.sum, 100);
+ assert.strictEqual(value.numValues, 1);
+ assert.strictEqual(value.average, 100);
+ assert.strictEqual(value.running.max, 100);
+ assert.closeTo(value.getApproximatePercentile(0.90), 100, 1);
+
+ value = actual.getHistogramNamed(
+ `${telemetryName}_idle_deadline_overrun`);
+ assert.strictEqual(value.running.sum, 0);
+ assert.strictEqual(value.numValues, 1);
+ assert.strictEqual(value.average, 0);
+ assert.strictEqual(value.running.max, 0);
+
+ value = actual.getHistogramNamed(`${telemetryName}_outside_idle`);
+ assert.strictEqual(value.running.sum, 100);
+ assert.strictEqual(value.numValues, 1);
+ assert.strictEqual(value.average, 100);
+
+ value = actual.getHistogramNamed(`${telemetryName}_percentage_idle`);
+ assert.strictEqual(value.average, 0);
+ }
+ });
+
+ test('idleTimes', function() {
+ const histograms = new tr.v.HistogramSet();
+ const slices = [
+ {
+ title: 'SingleThreadIdleTaskRunner::RunTask',
+ args: {'allotted_time_ms': 100}, start: 100, end: 200,
+ cpuStart: 100, cpuEnd: 200
+ },
+ {
+ title: 'BlinkGC.AtomicPhase', args: {}, start: 110, end: 190,
+ cpuStart: 110, cpuEnd: 190
+ }
+ ];
+ const actual = run(slices);
+
+ let value = actual.getHistogramNamed('blink-gc-atomic-phase');
+ assert.strictEqual(value.running.sum, 80);
+ assert.strictEqual(value.numValues, 1);
+ assert.strictEqual(value.average, 80);
+ assert.strictEqual(value.running.max, 80);
+
+ value = actual.getHistogramNamed(
+ 'blink-gc-atomic-phase_idle_deadline_overrun');
+ assert.strictEqual(value.running.sum, 0);
+ assert.strictEqual(value.average, 0);
+ assert.strictEqual(value.running.max, 0);
+
+ value = actual.getHistogramNamed('blink-gc-atomic-phase_outside_idle');
+ assert.strictEqual(value.running.sum, 0);
+ assert.strictEqual(value.average, 0);
+ assert.strictEqual(value.running.max, 0);
+
+ value = actual.getHistogramNamed('blink-gc-atomic-phase_percentage_idle');
+ assert.strictEqual(value.average, 1);
+ });
+
+ test('idleTimeOverrun', function() {
+ const histograms = new tr.v.HistogramSet();
+ const slices = [
+ {
+ title: 'SingleThreadIdleTaskRunner::RunTask',
+ args: {'allotted_time_ms': 10}, start: 100, end: 200,
+ cpuStart: 100, cpuEnd: 200
+ },
+ {
+ title: 'BlinkGC.AtomicPhase', args: {}, start: 110, end: 190,
+ cpuStart: 110, cpuEnd: 190
+ }
+ ];
+ const actual = run(slices);
+
+ let value = actual.getHistogramNamed('blink-gc-atomic-phase');
+ assert.strictEqual(value.running.sum, 80);
+ assert.strictEqual(value.numValues, 1);
+ assert.strictEqual(value.average, 80);
+ assert.strictEqual(value.running.max, 80);
+
+ value = actual.getHistogramNamed(
+ 'blink-gc-atomic-phase_idle_deadline_overrun');
+ assert.strictEqual(value.running.sum, 70);
+ assert.strictEqual(value.average, 70);
+ assert.strictEqual(value.running.max, 70);
+
+ value = actual.getHistogramNamed('blink-gc-atomic-phase_outside_idle');
+ assert.strictEqual(value.running.sum, 70);
+ assert.strictEqual(value.average, 70);
+ assert.strictEqual(value.running.max, 70);
+
+ value = actual.getHistogramNamed('blink-gc-atomic-phase_percentage_idle');
+ assert.closeTo(value.average, 1 / 8, 1e-6);
+ });
+
+ test('totalTimeForBlinkGC', function() {
+ const histograms = new tr.v.HistogramSet();
+ const slices = [
+ {
+ title: 'BlinkGC.AtomicPhase', args: {}, start: 100, end: 200,
+ cpuStart: 100, cpuEnd: 200
+ },
+ {
+ title: 'BlinkGC.LazySweepInIdle', args: {}, start: 210,
+ end: 290, cpuStart: 210, cpuEnd: 290
+ }
+ ];
+ const actual = run(slices);
+
+ let value = actual.getHistogramNamed('blink-gc-total');
+ assert.strictEqual(value.running.sum, 180);
+ assert.strictEqual(value.numValues, 2);
+ assert.strictEqual(value.average, 90);
+ assert.strictEqual(value.running.max, 100);
+
+ value = actual.getHistogramNamed('blink-gc-total_idle_deadline_overrun');
+ assert.strictEqual(value.running.sum, 0);
+ assert.strictEqual(value.average, 0);
+ assert.strictEqual(value.running.max, 0);
+
+ value = actual.getHistogramNamed('blink-gc-total_outside_idle');
+ assert.strictEqual(value.running.sum, 180);
+ assert.strictEqual(value.average, 90);
+ assert.strictEqual(value.running.max, 100);
+
+ value = actual.getHistogramNamed('blink-gc-total_percentage_idle');
+ assert.strictEqual(value.average, 0);
+ });
+
+ test('totalTimeForUnifiedGC', function() {
+ const histograms = new tr.v.HistogramSet();
+ const slices = [
+ {
+ title: 'V8.GCFinalizeMC', args: {},
+ start: 100, end: 300, cpuStart: 100, cpuEnd: 300
+ },
+ {
+ title: 'BlinkGC.AtomicPhase', args: {},
+ start: 310, end: 410, cpuStart: 310, cpuEnd: 410
+ }
+ ];
+ const actual = run(slices);
+
+ const value = actual.getHistogramNamed('unified-gc-total');
+ assert.strictEqual(value.running.sum, 300);
+ assert.strictEqual(value.numValues, 2);
+ assert.strictEqual(value.average, 150);
+ assert.strictEqual(value.running.max, 200);
+ });
+
+ test('totalTimeForUnifiedGCBlinkNestedInV8', function() {
+ // Nested Blink GC in V8 top-level GC can happen during unified garbage
+ // collection, or when callbacks that trigger e.g. sweeping are fired
+ // from V8's GC. These should only be accounted once.
+ const histograms = new tr.v.HistogramSet();
+ const slices = [
+ {
+ title: 'V8.GCFinalizeMC', args: {},
+ start: 100, end: 300, cpuStart: 100, cpuEnd: 300
+ },
+ // Nested events should be ignored.
+ {
+ title: 'BlinkGC.CompleteSweep', args: {},
+ start: 200, end: 270, cpuStart: 200, cpuEnd: 270
+ },
+ {
+ title: 'BlinkGC.IncrementalMarkingStartMarking', args: {},
+ start: 280, end: 290, cpuStart: 280, cpuEnd: 290
+ },
+ // Next event is outside of nesting and should be accounted for.
+ {
+ title: 'BlinkGC.IncrementalMarkingStartMarking', args: {},
+ start: 310, end: 320, cpuStart: 310, cpuEnd: 320
+ },
+ ];
+ const actual = run(slices);
+
+ const value = actual.getHistogramNamed('unified-gc-total');
+ assert.strictEqual(value.running.sum, 210);
+ assert.strictEqual(value.numValues, 2);
+ assert.strictEqual(value.average, 105);
+ assert.strictEqual(value.running.max, 200);
+ });
+
+ function getSlicesWithForcedV8GCs() {
+ return [
+ {
+ title: tr.metrics.v8.utils.forcedGCEventName(), args: {},
+ start: 100, end: 300, cpuStart: 100, cpuEnd: 300
+ },
+ // Following nested events should be ignored.
+ {
+ title: 'V8.GCFinalizeMC', args: {},
+ start: 100, end: 300, cpuStart: 100, cpuEnd: 300
+ },
+ {
+ title: 'BlinkGC.CompleteSweep', args: {},
+ start: 200, end: 270, cpuStart: 200, cpuEnd: 270
+ },
+ {
+ title: 'BlinkGC.IncrementalMarkingStartMarking', args: {},
+ start: 280, end: 290, cpuStart: 280, cpuEnd: 290
+ },
+ // Next event happens after the forced GC and should be accounted for.
+ {
+ title: 'BlinkGC.IncrementalMarkingStartMarking', args: {},
+ start: 310, end: 320, cpuStart: 310, cpuEnd: 320
+ },
+ {
+ title: 'BlinkGC.AtomicPhase', args: {'forced': false},
+ start: 320, end: 330, cpuStart: 320, cpuEnd: 330
+ },
+ ];
+ }
+
+ test('ignoreForcedV8GCEventsForUnifiedMetric', function() {
+ // Any events nested in a forced GC should be ignored.
+ const histograms = new tr.v.HistogramSet();
+ const actual = run(getSlicesWithForcedV8GCs());
+ const value = actual.getHistogramNamed('unified-gc-total');
+ assert.strictEqual(value.running.sum, 20);
+ assert.strictEqual(value.numValues, 2);
+ assert.strictEqual(value.average, 10);
+ assert.strictEqual(value.running.max, 10);
+ });
+
+ test('ignoreForcedV8GCEventsForBlinkMetric', function() {
+ // Any events nested in a forced GC should be ignored.
+ const histograms = new tr.v.HistogramSet();
+ const actual = run(getSlicesWithForcedV8GCs());
+ const value = actual.getHistogramNamed('blink-gc-total');
+ assert.strictEqual(value.running.sum, 20);
+ assert.strictEqual(value.numValues, 2);
+ assert.strictEqual(value.average, 10);
+ assert.strictEqual(value.running.max, 10);
+ });
+
+ function getSlicesWithForcedBlinkGCs() {
+ return [
+ // Following nested events should be ignored.
+ {
+ title: 'BlinkGC.CompleteSweep', args: {'forced': true},
+ start: 200, end: 270, cpuStart: 200, cpuEnd: 270
+ },
+ {
+ title: 'BlinkGC.AtomicPhase', args: {'forced': true},
+ start: 280, end: 290, cpuStart: 280, cpuEnd: 290
+ },
+ // Next events are not forced and should be accounted for.
+ {
+ title: 'BlinkGC.AtomicPhase', args: {},
+ start: 310, end: 320, cpuStart: 310, cpuEnd: 320
+ },
+ {
+ title: 'BlinkGC.AtomicPhase', args: {'forced': false},
+ start: 320, end: 330, cpuStart: 320, cpuEnd: 330
+ },
+ ];
+ }
+
+ test('ignoreForcedBlinkGCEventsForUnifiedMetric', function() {
+ // Any forced Blink GC events should be ignored.
+ const histograms = new tr.v.HistogramSet();
+ const actual = run(getSlicesWithForcedBlinkGCs());
+ const value = actual.getHistogramNamed('unified-gc-total');
+ assert.strictEqual(value.running.sum, 20);
+ assert.strictEqual(value.numValues, 2);
+ assert.strictEqual(value.average, 10);
+ assert.strictEqual(value.running.max, 10);
+ });
+
+ test('ignoreForcedBlinkGCEventsForBlinkMetric', function() {
+ // Any forced Blink GC events should be ignored.
+ const histograms = new tr.v.HistogramSet();
+ const actual = run(getSlicesWithForcedBlinkGCs());
+ const value = actual.getHistogramNamed('blink-gc-total');
+ assert.strictEqual(value.running.sum, 20);
+ assert.strictEqual(value.numValues, 2);
+ assert.strictEqual(value.average, 10);
+ assert.strictEqual(value.running.max, 10);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/blink/leak_detection_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/blink/leak_detection_metric.html
new file mode 100644
index 00000000000..432b41d5d73
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/blink/leak_detection_metric.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.blink', function() {
+ function leakDetectionMetric(histograms, model) {
+ // Extract renderer pids.
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (modelHelper === undefined) {
+ throw new Error('Chrome is not present.');
+ }
+ const rendererHelpers = modelHelper.rendererHelpers;
+ if (Object.keys(rendererHelpers).length === 0) {
+ throw new Error('Renderer process is not present.');
+ }
+ const pids = Object.keys(rendererHelpers);
+
+ // Get the dumps.
+ const chromeDumps = tr.metrics.sh
+ .splitGlobalDumpsByBrowserName(model, undefined).get('chrome');
+
+ const sumCounter = new Map();
+ // Add up counters for all the renderer processes.
+
+ for (const pid of pids) {
+ for (const [key, count] of countLeakedBlinkObjects(chromeDumps, pid)) {
+ sumCounter.set(key, (sumCounter.get(key) || 0) + count);
+ }
+ }
+
+ for (const [key, count] of sumCounter) {
+ histograms.createHistogram('Leaked ' + key,
+ tr.b.Unit.byName.count_smallerIsBetter, count);
+ }
+
+ for (const [key, count] of sumCounter) {
+ if (count > 0) {
+ throw new Error('Memory leak is found.');
+ }
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(leakDetectionMetric);
+
+ function countLeakedBlinkObjects(dumps, pid) {
+ if (dumps === undefined || dumps.length < 2) {
+ throw new Error('Expected at least two memory dumps.');
+ }
+ const firstCounter = countBlinkObjects(dumps[0], pid);
+ const lastCounter = countBlinkObjects(dumps[dumps.length - 1], pid);
+ const diffCounter = new Map();
+ for (const [key, lastCount] of lastCounter) {
+ diffCounter.set(key, lastCount - firstCounter.get(key));
+ }
+ return diffCounter;
+ }
+
+ function countBlinkObjects(dump, pid) {
+ const counter = new Map();
+ const processesMemoryDumps = dump.processMemoryDumps;
+ if (processesMemoryDumps[pid] === undefined) return counter;
+ const blinkObjectsDump = processesMemoryDumps[pid].memoryAllocatorDumps
+ .find(dump => dump.fullName === 'blink_objects');
+ for (const v of blinkObjectsDump.children) {
+ counter.set(v.name, v.numerics.object_count.value);
+ }
+ return counter;
+ }
+
+ return {
+ leakDetectionMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/blink/leak_detection_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/blink/leak_detection_metric_test.html
new file mode 100644
index 00000000000..f5b2e4add39
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/blink/leak_detection_metric_test.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/blink/leak_detection_metric.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const BLINK_OBJECT_LIST = ['AudioHandler', 'Document', 'Frame',
+ 'JSEventListener', 'LayoutObject', 'MediaKeys', 'MediaKeySession', 'Node',
+ 'Resource', 'ScriptPromise', 'PausableObject', 'V8PerContextData',
+ 'WorkerGlobalScope'];
+ const addProcessMemoryDump =
+ tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
+ const addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const allZeroArray = new Array(BLINK_OBJECT_LIST.length).fill(0);
+ const oneLeakArray = new Array(BLINK_OBJECT_LIST.length).fill(0);
+ oneLeakArray[1] = 1;
+ const multipleLeaksArray = new Array(BLINK_OBJECT_LIST.length).fill(1);
+
+ function createProcessWithName(model, name) {
+ const uniquePid =
+ Math.max.apply(null, Object.keys(model.processes).concat([0])) + 1;
+ const process = model.getOrCreateProcess(uniquePid);
+ process.name = name;
+ process.getOrCreateThread(1).name = 'Cr' + name + 'Main';
+ return process;
+ }
+
+ function createTimestamp(model, browser, rendererValuePairs, timestamp) {
+ const gmd1 = addGlobalMemoryDump(model, {ts: timestamp});
+ const pmdBrowser1 = addProcessMemoryDump(gmd1, browser, {ts: timestamp});
+ for (const pair of rendererValuePairs) {
+ addDumpsToRenderer(gmd1, pair.renderer, pair.values, timestamp);
+ }
+ }
+
+ function addDumpsToRenderer(gmd, renderer, values, timestamp) {
+ const pmdRenderer = addProcessMemoryDump(gmd, renderer, {ts: timestamp});
+ pmdRenderer.memoryAllocatorDumps = [
+ newAllocatorDump(pmdRenderer, 'blink_objects', { children:
+ createBlinkObjectCountList(pmdRenderer, values)})];
+ }
+
+ function getNumericLeakCount(histograms, index) {
+ return histograms.getHistogramNamed('Leaked ' +
+ BLINK_OBJECT_LIST[index]).statisticsScalars.get('sum').value;
+ }
+
+ function createBlinkObjectCountList(renderer, values) {
+ const blinkObjectCountList = [];
+ for (let i = 0; i < values.length; i++) {
+ blinkObjectCountList.push(newAllocatorDump(renderer,
+ 'blink_objects/' + BLINK_OBJECT_LIST[i], { numerics:
+ { object_count: values[i] }}));
+ }
+ return blinkObjectCountList;
+ }
+
+ test('testNoRenderer', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ createProcessWithName(model, 'Browser');
+ });
+ const histograms = new tr.v.HistogramSet();
+ assert.throws(
+ function() {tr.metrics.blink.leakDetectionMetric(histograms, model);},
+ 'Renderer process is not present.');
+ });
+
+ test('testZeroDump', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ createProcessWithName(model, 'Browser');
+ createProcessWithName(model, 'Renderer');
+ });
+ const histograms = new tr.v.HistogramSet();
+ assert.throws(
+ function() {tr.metrics.blink.leakDetectionMetric(histograms, model);},
+ 'Expected at least two memory dumps.');
+ });
+
+ test('testOnlyOneDump', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const browser = createProcessWithName(model, 'Browser');
+ const renderer = createProcessWithName(model, 'Renderer');
+ const pair = [{renderer, values: allZeroArray}];
+ createTimestamp(model, browser, pair, 40);
+ });
+ const histograms = new tr.v.HistogramSet();
+ assert.throws(
+ function() {tr.metrics.blink.leakDetectionMetric(histograms, model);},
+ 'Expected at least two memory dumps.');
+ });
+
+ test('testNoLeak', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const browser = createProcessWithName(model, 'Browser');
+ const renderer = createProcessWithName(model, 'Renderer');
+ const pair = [{renderer, 'values': allZeroArray}];
+ createTimestamp(model, browser, pair, 20);
+ createTimestamp(model, browser, pair, 40);
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.blink.leakDetectionMetric(histograms, model);
+ for (let i = 0; i < BLINK_OBJECT_LIST.length; i++) {
+ assert.strictEqual(getNumericLeakCount(histograms, i), 0);
+ }
+ });
+
+ test('testOneLeakDetection', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const browser = createProcessWithName(model, 'Browser');
+ const renderer = createProcessWithName(model, 'Renderer');
+ const pair1 = [{renderer, 'values': allZeroArray}];
+ const pair2 = [{renderer, 'values': oneLeakArray}];
+ createTimestamp(model, browser, pair1, 20);
+ createTimestamp(model, browser, pair2, 40);
+ });
+ const histograms = new tr.v.HistogramSet();
+ assert.throws(
+ function() {tr.metrics.blink.leakDetectionMetric(histograms, model);},
+ 'Memory leak is found.');
+ for (let i = 0; i < BLINK_OBJECT_LIST.length; i++) {
+ if (i === 1) {
+ assert.strictEqual(getNumericLeakCount(histograms, i), 1);
+ } else {
+ assert.strictEqual(getNumericLeakCount(histograms, i), 0);
+ }
+ }
+ });
+
+ test('testMultipleLeakDetections', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const browser = createProcessWithName(model, 'Browser');
+ const renderer = createProcessWithName(model, 'Renderer');
+ const pair1 = [{renderer, 'values': allZeroArray}];
+ const pair2 = [{renderer, 'values': multipleLeaksArray}];
+ createTimestamp(model, browser, pair1, 20);
+ createTimestamp(model, browser, pair2, 40);
+ });
+ const histograms = new tr.v.HistogramSet();
+ assert.throws(
+ function() {tr.metrics.blink.leakDetectionMetric(histograms, model);},
+ 'Memory leak is found.');
+ for (let i = 0; i < BLINK_OBJECT_LIST.length; i++) {
+ assert.strictEqual(getNumericLeakCount(histograms, i), 1);
+ }
+ });
+
+ test('testMultipleRendererWithLeaks', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const browser = createProcessWithName(model, 'Browser');
+ const renderer1 = createProcessWithName(model, 'Renderer');
+ const renderer2 = createProcessWithName(model, 'Renderer');
+ const pair1 = [{'renderer': renderer1, 'values': allZeroArray},
+ {'renderer': renderer2, 'values': allZeroArray}];
+ const pair2 = [{'renderer': renderer1, 'values': multipleLeaksArray},
+ {'renderer': renderer2, 'values': multipleLeaksArray}];
+ createTimestamp(model, browser, pair1, 20);
+ createTimestamp(model, browser, pair2, 40);
+ });
+ const histograms = new tr.v.HistogramSet();
+ assert.throws(
+ function() {tr.metrics.blink.leakDetectionMetric(histograms, model);},
+ 'Memory leak is found.');
+ for (let i = 0; i < BLINK_OBJECT_LIST.length; i++) {
+ assert.strictEqual(getNumericLeakCount(histograms, i), 2);
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/buildbot_output_for_compare_samples_test.txt b/chromium/third_party/catapult/tracing/tracing/metrics/buildbot_output_for_compare_samples_test.txt
new file mode 100644
index 00000000000..a8d19745dae
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/buildbot_output_for_compare_samples_test.txt
@@ -0,0 +1,187 @@
+IMPORTANT DEBUGGING NOTE: batches of tests are run inside their
+own process. For debugging a test inside a debugger, use the
+--gtest_filter=<your_test_name> flag along with
+--single-process-tests.
+Using sharding settings from environment. This is shard 0/1
+Using 1 parallel jobs.
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D31.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_13273\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D31.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_13273\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D31.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_13273\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D31.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_13273\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D31.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_13273\test_results.xml" --test-launcher-print-test-stdio=always
+[ RUN ] IndexDataManagerPerfTest.Run
+*RESULT IndexDataManger_run: score= 281471 score
+[ OK ] IndexDataManagerPerfTest.Run (5008 ms)
+[1/37] IndexDataManagerPerfTest.Run (5008 ms)
+[ RUN ] BufferSubDataBenchmark.Run/d3d11_float4_every1
+*RESULT BufferSubData_d3d11_float4_every1: score= 232 score
+[ OK ] BufferSubDataBenchmark.Run/d3d11_float4_every1 (5117 ms)
+[2/37] BufferSubDataBenchmark.Run/d3d11_float4_every1 (5117 ms)
+[ RUN ] BufferSubDataBenchmark.Run/d3d9_float4_every1
+*RESULT BufferSubData_d3d9_float4_every1: score= 237 score
+[ OK ] BufferSubDataBenchmark.Run/d3d9_float4_every1 (5386 ms)
+[3/37] BufferSubDataBenchmark.Run/d3d9_float4_every1 (5386 ms)
+[ RUN ] BufferSubDataBenchmark.Run/gl_float4_every1
+*RESULT BufferSubData_gl_float4_every1: score= 245 score
+[ OK ] BufferSubDataBenchmark.Run/gl_float4_every1 (5195 ms)
+[4/37] BufferSubDataBenchmark.Run/gl_float4_every1 (5195 ms)
+[ RUN ] DrawCallPerfBenchmark.Run/d3d9
+*RESULT DrawCallPerf_d3d9: score= 2993 score
+[ OK ] DrawCallPerfBenchmark.Run/d3d9 (10062 ms)
+[5/37] DrawCallPerfBenchmark.Run/d3d9 (10062 ms)
+[ RUN ] DrawCallPerfBenchmark.Run/d3d9_null
+*RESULT DrawCallPerf_d3d9_null: score= 25046 score
+[ OK ] DrawCallPerfBenchmark.Run/d3d9_null (10047 ms)
+[6/37] DrawCallPerfBenchmark.Run/d3d9_null (10047 ms)
+[ RUN ] DrawCallPerfBenchmark.Run/d3d11
+*RESULT DrawCallPerf_d3d11: score= 2741 score
+[ OK ] DrawCallPerfBenchmark.Run/d3d11 (10015 ms)
+[7/37] DrawCallPerfBenchmark.Run/d3d11 (10015 ms)
+[ RUN ] DrawCallPerfBenchmark.Run/d3d11_null
+*RESULT DrawCallPerf_d3d11_null: score= 28607 score
+[ OK ] DrawCallPerfBenchmark.Run/d3d11_null (9999 ms)
+[8/37] DrawCallPerfBenchmark.Run/d3d11_null (9999 ms)
+[ RUN ] DrawCallPerfBenchmark.Run/d3d11_render_to_texture_null
+*RESULT DrawCallPerf_d3d11_render_to_texture_null: score= 25868 score
+[ OK ] DrawCallPerfBenchmark.Run/d3d11_render_to_texture_null (10015 ms)
+[9/37] DrawCallPerfBenchmark.Run/d3d11_render_to_texture_null (10015 ms)
+[ RUN ] DrawCallPerfBenchmark.Run/gl
+*RESULT DrawCallPerf_gl: score= 4123 score
+[ OK ] DrawCallPerfBenchmark.Run/gl (10031 ms)
+[10/37] DrawCallPerfBenchmark.Run/gl (10031 ms)
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D32.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_8457\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D32.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_8457\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D32.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_8457\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D32.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_8457\test_results.xml" --test-launcher-print-test-stdio=always
+[ RUN ] DrawCallPerfBenchmark.Run/gl_null
+*RESULT DrawCallPerf_gl_null: score= 189804 score
+[ OK ] DrawCallPerfBenchmark.Run/gl_null (10015 ms)
+[11/37] DrawCallPerfBenchmark.Run/gl_null (10015 ms)
+[ RUN ] DrawCallPerfBenchmark.Run/gl_render_to_texture_null
+*RESULT DrawCallPerf_gl_render_to_texture_null: score= 189155 score
+[ OK ] DrawCallPerfBenchmark.Run/gl_render_to_texture_null (10031 ms)
+[12/37] DrawCallPerfBenchmark.Run/gl_render_to_texture_null (10031 ms)
+[ RUN ] DrawCallPerfBenchmark.Run/default_validation_only
+*RESULT DrawCallPerf_default_validation_only: score= 2690 score
+[ OK ] DrawCallPerfBenchmark.Run/default_validation_only (5023 ms)
+[13/37] DrawCallPerfBenchmark.Run/default_validation_only (5023 ms)
+[ RUN ] DynamicPromotionPerfTest.Run/d3d11
+*RESULT DynamicPromotion_d3d11: score= 39354 score
+[ OK ] DynamicPromotionPerfTest.Run/d3d11 (6552 ms)
+[14/37] DynamicPromotionPerfTest.Run/d3d11 (6552 ms)
+[ RUN ] DynamicPromotionPerfTest.Run/d3d9
+*RESULT DynamicPromotion_d3d9: score= 21060 score
+[ OK ] DynamicPromotionPerfTest.Run/d3d9 (5522 ms)
+[15/37] DynamicPromotionPerfTest.Run/d3d9 (5522 ms)
+[ RUN ] EGLInitializePerfTest.Run/ES2_D3D11
+*RESULT EGLInitialize_run: score= 155 score
+*RESULT EGLInitialize_run: LoadDLLs= 0.0000000000 ms
+*RESULT EGLInitialize_run: D3D11CreateDevice= 4.0051480051 ms
+*RESULT EGLInitialize_run: InitResources= 0.0000000000 ms
+[ OK ] EGLInitializePerfTest.Run/ES2_D3D11 (5008 ms)
+[16/37] EGLInitializePerfTest.Run/ES2_D3D11 (5008 ms)
+[ RUN ] IndexConversionPerfTest.Run/d3d11
+*RESULT IndexConversionPerfTest_d3d11: score= 5135 score
+[ OK ] IndexConversionPerfTest.Run/d3d11 (3166 ms)
+[17/37] IndexConversionPerfTest.Run/d3d11 (3166 ms)
+[ RUN ] IndexConversionPerfTest.Run/index_range_d3d11
+*RESULT IndexConversionPerfTest_index_range_d3d11: score= 68785 score
+[ OK ] IndexConversionPerfTest.Run/index_range_d3d11 (3011 ms)
+[18/37] IndexConversionPerfTest.Run/index_range_d3d11 (3011 ms)
+[ RUN ] InstancingPerfBenchmark.Run/d3d11
+*RESULT InstancingPerf_d3d11: score= 479 score
+[ OK ] InstancingPerfBenchmark.Run/d3d11 (10046 ms)
+[19/37] InstancingPerfBenchmark.Run/d3d11 (10046 ms)
+[ RUN ] InstancingPerfBenchmark.Run/d3d9
+*RESULT InstancingPerf_d3d9: score= 464 score
+[ OK ] InstancingPerfBenchmark.Run/d3d9 (10057 ms)
+[20/37] InstancingPerfBenchmark.Run/d3d9 (10057 ms)
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D44.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_12336\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D44.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_12336\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D44.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_12336\test_results.xml" --test-launcher-print-test-stdio=always
+[ RUN ] InstancingPerfBenchmark.Run/gl
+*RESULT InstancingPerf_gl: score= 427 score
+[ OK ] InstancingPerfBenchmark.Run/gl (10124 ms)
+[21/37] InstancingPerfBenchmark.Run/gl (10124 ms)
+[ RUN ] InterleavedAttributeDataBenchmark.Run/d3d11
+*RESULT InterleavedAttributeData_d3d11: score= 19 score
+[ OK ] InterleavedAttributeDataBenchmark.Run/d3d11 (5117 ms)
+[22/37] InterleavedAttributeDataBenchmark.Run/d3d11 (5117 ms)
+[ RUN ] InterleavedAttributeDataBenchmark.Run/d3d11_9_3
+*RESULT InterleavedAttributeData_d3d11: score= 25 score
+[ OK ] InterleavedAttributeDataBenchmark.Run/d3d11_9_3 (5225 ms)
+[23/37] InterleavedAttributeDataBenchmark.Run/d3d11_9_3 (5225 ms)
+[ RUN ] InterleavedAttributeDataBenchmark.Run/d3d9
+*RESULT InterleavedAttributeData_d3d9: score= 25 score
+[ OK ] InterleavedAttributeDataBenchmark.Run/d3d9 (5211 ms)
+[24/37] InterleavedAttributeDataBenchmark.Run/d3d9 (5211 ms)
+[ RUN ] InterleavedAttributeDataBenchmark.Run/gl
+*RESULT InterleavedAttributeData_gl: score= 25 score
+[ OK ] InterleavedAttributeDataBenchmark.Run/gl (5101 ms)
+[25/37] InterleavedAttributeDataBenchmark.Run/gl (5101 ms)
+[ RUN ] PointSpritesBenchmark.Run/d3d11_10_3px_3vars
+*RESULT PointSprites_d3d11_10_3px_3vars: score= 644 score
+[ OK ] PointSpritesBenchmark.Run/d3d11_10_3px_3vars (5023 ms)
+[26/37] PointSpritesBenchmark.Run/d3d11_10_3px_3vars (5023 ms)
+[ RUN ] PointSpritesBenchmark.Run/d3d9_10_3px_3vars
+*RESULT PointSprites_d3d9_10_3px_3vars: score= 730 score
+[ OK ] PointSpritesBenchmark.Run/d3d9_10_3px_3vars (5141 ms)
+[27/37] PointSpritesBenchmark.Run/d3d9_10_3px_3vars (5141 ms)
+[ RUN ] PointSpritesBenchmark.Run/gl_10_3px_3vars
+*RESULT PointSprites_gl_10_3px_3vars: score= 2159 score
+[ OK ] PointSpritesBenchmark.Run/gl_10_3px_3vars (5086 ms)
+[28/37] PointSpritesBenchmark.Run/gl_10_3px_3vars (5086 ms)
+[ RUN ] TexSubImageBenchmark.Run/d3d11
+*RESULT TexSubImage_d3d11: score= 294 score
+[ OK ] TexSubImageBenchmark.Run/d3d11 (5023 ms)
+[29/37] TexSubImageBenchmark.Run/d3d11 (5023 ms)
+[ RUN ] TexSubImageBenchmark.Run/d3d9
+*RESULT TexSubImage_d3d9: score= 298 score
+[ OK ] TexSubImageBenchmark.Run/d3d9 (5305 ms)
+[30/37] TexSubImageBenchmark.Run/d3d9 (5305 ms)
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D45.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_4706\test_results.xml" --test-launcher-print-test-stdio=always
+Still waiting for the following processes to finish:
+ "C:\b\c\b\Win_7_ATI_GPU_Perf__2_\src\out\Release_x64\angle_perftests.exe" --gtest_flagfile="C:\Users\chrome-bot\AppData\Local\Temp\scoped_dir3192_23891\8D45.tmp" --single-process-tests --test-launcher-jobs=1 --test-launcher-output="C:\Users\CHROME~1\AppData\Local\Temp\3192_4706\test_results.xml" --test-launcher-print-test-stdio=always
+[ RUN ] TexSubImageBenchmark.Run/gl
+*RESULT TexSubImage_gl: score= 323 score
+[ OK ] TexSubImageBenchmark.Run/gl (5070 ms)
+[31/37] TexSubImageBenchmark.Run/gl (5070 ms)
+[ RUN ] TextureSamplingBenchmark.Run/d3d11_2samplers
+*RESULT TextureSampling_d3d11_2samplers: score= 128 score
+[ OK ] TextureSamplingBenchmark.Run/d3d11_2samplers (5070 ms)
+[32/37] TextureSamplingBenchmark.Run/d3d11_2samplers (5070 ms)
+[ RUN ] TextureSamplingBenchmark.Run/d3d9_2samplers
+*RESULT TextureSampling_d3d9_2samplers: score= 128 score
+[ OK ] TextureSamplingBenchmark.Run/d3d9_2samplers (5668 ms)
+[33/37] TextureSamplingBenchmark.Run/d3d9_2samplers (5668 ms)
+[ RUN ] TextureSamplingBenchmark.Run/gl_2samplers
+*RESULT TextureSampling_gl_2samplers: score= 136 score
+[ OK ] TextureSamplingBenchmark.Run/gl_2samplers (5054 ms)
+[34/37] TextureSamplingBenchmark.Run/gl_2samplers (5054 ms)
+[ RUN ] UniformsBenchmark.Run/d3d11_200_vertex_uniforms_200_fragment_uniforms
+*RESULT Uniforms_d3d11_200_vertex_uniforms_200_fragment_uniforms: score= 1797 score
+[ OK ] UniformsBenchmark.Run/d3d11_200_vertex_uniforms_200_fragment_uniforms (5195 ms)
+[35/37] UniformsBenchmark.Run/d3d11_200_vertex_uniforms_200_fragment_uniforms (5195 ms)
+[ RUN ] UniformsBenchmark.Run/d3d9_200_vertex_uniforms_200_fragment_uniforms
+*RESULT Uniforms_d3d9_200_vertex_uniforms_200_fragment_uniforms: score= 1912 score
+[ OK ] UniformsBenchmark.Run/d3d9_200_vertex_uniforms_200_fragment_uniforms (5223 ms)
+[36/37] UniformsBenchmark.Run/d3d9_200_vertex_uniforms_200_fragment_uniforms (5223 ms)
+[ RUN ] UniformsBenchmark.Run/gl_200_vertex_uniforms_200_fragment_uniforms
+*RESULT Uniforms_gl_200_vertex_uniforms_200_fragment_uniforms: score= 5509 score
+[ OK ] UniformsBenchmark.Run/gl_200_vertex_uniforms_200_fragment_uniforms (5070 ms)
+[37/37] UniformsBenchmark.Run/gl_200_vertex_uniforms_200_fragment_uniforms (5070 ms)
+SUCCESS: all tests passed.
+Tests took 243 seconds.
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples.py b/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples.py
new file mode 100644
index 00000000000..6fb10a34b6f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples.py
@@ -0,0 +1,54 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+import tracing_project
+import vinn
+
+FORMAT_TO_METHOD = {
+ 'chartjson': 'compareCharts',
+ 'buildbot': 'compareBuildbotOutputs'
+}
+
+_COMPARE_SAMPLES_CMD_LINE = os.path.join(
+ os.path.dirname(__file__), 'compare_samples_cmdline.html')
+
+
+def CompareSamples(sample_a, sample_b, metric, data_format='chartjson'):
+ """Compare the values of a metric from two samples from benchmark output.
+
+ Args:
+ sample_a, sample_b (str): comma-separated lists of paths to the benchmark
+ output.
+ metric (str): Metric name in slash-separated format [2 or 3 part].
+ data_format (str): The format the samples are in. Supported values are:
+ 'chartjson', 'valueset', 'buildbot'.
+ Returns:
+ JSON encoded dict with the values parsed form the samples and the result of
+ the hypothesis testing comparison of the samples under the 'result' key.
+ Possible values for the result key are:
+ 'NEED_MORE_DATA', 'REJECT' and 'FAIL_TO_REJECT'.
+ Where the null hypothesis is that the samples belong to the same population.
+ i.e. a 'REJECT' result would make it reasonable to conclude that
+ there is a significant difference between the samples. (e.g. a perf
+ regression).
+ """
+
+ method = FORMAT_TO_METHOD[data_format]
+ project = tracing_project.TracingProject()
+ all_source_paths = list(project.source_paths)
+
+ def MakeAbsPaths(l):
+ return ','.join(map(os.path.abspath, l.split(',')))
+
+ return vinn.RunFile(
+ _COMPARE_SAMPLES_CMD_LINE,
+ source_paths=all_source_paths,
+ js_args=[
+ method,
+ MakeAbsPaths(sample_a),
+ MakeAbsPaths(sample_b),
+ metric
+ ])
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_cmdline.html b/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_cmdline.html
new file mode 100644
index 00000000000..f774f03f1bd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_cmdline.html
@@ -0,0 +1,225 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/base/xhr.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+const escapeChars = s => s.replace(/[\:|=\/#&,]/g, '_');
+
+function findUnescapedKey(escaped, d) {
+ if (!d) {
+ return undefined;
+ }
+
+ for (const k of Object.keys(d)) {
+ if (escapeChars(k) === escapeChars(escaped)) {
+ return k;
+ }
+ }
+}
+
+function geoMeanFromHistogram(h) {
+ if (!h.hasOwnProperty('buckets')) return 0.0;
+ let count = 0;
+ let sumOfLogs = 0;
+ for (const bucket of h.buckets) {
+ if (bucket.hasOwnProperty('high')) {
+ bucket.mean = (bucket.low + bucket.high) / 2.0;
+ } else {
+ bucket.mean = bucket.low;
+ }
+
+ if (bucket.mean > 0) {
+ sumOfLogs += Math.log(bucket.mean) * bucket.count;
+ count += bucket.count;
+ }
+ }
+ if (count === 0) return 0.0;
+ return Math.exp(sumOfLogs / count);
+}
+
+function guessFullTIRMetricName(metricName) {
+ const parts = metricName.split('/');
+ if (parts.length === 2) {
+ return metricName + '/summary';
+ }
+ return undefined;
+}
+
+function splitMetric(metricName) {
+ const parts = metricName.split('/');
+ let interactionName;
+ let traceName = 'summary';
+ let chartName = parts[0];
+ if (parts.length === 3) {
+ // parts[1] is the interactionName
+ if (parts[1]) chartName = parts[1] + '@@' + chartName;
+ traceName = parts[2];
+ } else if (parts.length === 2) {
+ if (chartName !== parts[1]) traceName = parts[1];
+ } else {
+ throw new Error('Could not parse metric name.');
+ }
+ return [chartName, traceName];
+}
+
+function valuesFromCharts(listOfCharts, metricName) {
+ const allValues = [];
+ const chartAndTrace = splitMetric(metricName);
+ for (const charts of listOfCharts) {
+ const chartName = findUnescapedKey(chartAndTrace[0], charts.charts);
+ if (chartName) {
+ const traceName = findUnescapedKey(
+ chartAndTrace[1], charts.charts[chartName]);
+ if (traceName) {
+ if (charts.charts[chartName][traceName].type ===
+ 'list_of_scalar_values') {
+ if (charts.charts[chartName][traceName].values === null) continue;
+ allValues.push(tr.b.math.Statistics.mean(
+ charts.charts[chartName][traceName].values));
+ }
+ if (charts.charts[chartName][traceName].type === 'histogram') {
+ allValues.push(
+ geoMeanFromHistogram(charts.charts[chartName][traceName]));
+ }
+ if (charts.charts[chartName][traceName].type === 'scalar') {
+ allValues.push(charts.charts[chartName][traceName].value);
+ }
+ }
+ }
+ }
+ return allValues;
+}
+
+function valuesFromChartsWithFallback(listOfCharts, metricName) {
+ const allValues = valuesFromCharts(listOfCharts, metricName);
+ if (allValues.length > 0) return allValues;
+
+ // If this had a tir_label, the "summary" part may have been stripped by
+ // the dashboard during upload. We can re-add it here.
+ const fullMetricName = guessFullTIRMetricName(metricName);
+ if (!fullMetricName) return [];
+
+ return valuesFromCharts(listOfCharts, fullMetricName);
+}
+
+function parseFiles(files) {
+ const results = [];
+ for (const path of files) {
+ const current = tr.b.getSync('file://' + path);
+ results.push(JSON.parse(current));
+ }
+ return results;
+}
+
+const escapeForRegExp = s => s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+
+const strFromRE = re => re.toString().split('/')[1];
+
+function valuesFromBuildbotOutput(out, metric) {
+ if (!out) return [];
+
+ let stringVals = [];
+ const floatVals = [];
+ const chartAndTrace = splitMetric(metric);
+ const metricRE = escapeForRegExp(
+ 'RESULT ' + chartAndTrace[0] + ': ' + chartAndTrace[1] + '=');
+ const singleResultRE = new RegExp(metricRE +
+ strFromRE(/\s*([-]?[\d\.]+)/), 'g');
+ const multiResultsRE = new RegExp(metricRE +
+ strFromRE(/\s*\[\s*([\d\., -]+)\s*\]/), 'g');
+ const meanStdDevRE = new RegExp(metricRE +
+ strFromRE(/\s*\{\s*([-]?\d*(?:\.\d*)?),\s*([-]?\d*(?:\.\d*)?)\}/), 'g');
+ for (const line of out.split(/\r?\n/)) {
+ const singleResultMatch = singleResultRE.exec(line);
+ const multiResultsMatch = multiResultsRE.exec(line);
+ const meanStdDevMatch = meanStdDevRE.exec(line);
+ if (singleResultMatch && singleResultMatch.length > 1) {
+ stringVals.push(singleResultMatch[1]);
+ } else if (multiResultsMatch && multiResultsMatch.length > 1) {
+ const values = multiResultsMatch[1].split(',');
+ stringVals = stringVals.concat(values);
+ } else if (meanStdDevMatch && meanStdDevMatch.length > 1) {
+ stringVals.push(meanStdDevMatch[1]);
+ }
+ }
+ for (const val of stringVals) {
+ const f = parseFloat(val);
+ if (!isNaN(f)) floatVals.push(f);
+ }
+ return floatVals;
+}
+
+function parseMultipleBuildbotStreams(files, metric) {
+ let allValues = [];
+ for (const path of files) {
+ let contents;
+ try {
+ contents = tr.b.getSync('file://' + path);
+ } catch (ex) {
+ const err = new Error('Could not open' + path);
+ err.name = 'File loading error';
+ throw err;
+ }
+ allValues = allValues.concat(valuesFromBuildbotOutput(contents, metric));
+ }
+ return allValues;
+}
+
+const buildComparisonResultOutput = function(a, b) {
+ let comparisonResult;
+ if (!a.length || !b.length) {
+ comparisonResult = {
+ significance: tr.b.math.Statistics.Significance.NEED_MORE_DATA
+ };
+ } else {
+ comparisonResult = tr.b.math.Statistics.mwu(
+ a, b, tr.b.math.Statistics.DEFAULT_ALPHA,
+ tr.b.math.Statistics.MAX_SUGGESTED_SAMPLE_SIZE).asDict();
+ }
+ return {
+ sampleA: a,
+ sampleB: b,
+ result: comparisonResult
+ };
+};
+
+const SampleComparison = {
+
+ compareBuildbotOutputs(
+ buildbotOutputAPathList, buildbotOutputBPathList, metric) {
+ const aPaths = buildbotOutputAPathList.split(',');
+ const bPaths = buildbotOutputBPathList.split(',');
+ const sampleA = parseMultipleBuildbotStreams(aPaths, metric);
+ const sampleB = parseMultipleBuildbotStreams(bPaths, metric);
+ return buildComparisonResultOutput(sampleA, sampleB);
+ },
+
+ compareCharts(chartPathListA, chartPathListB, metric) {
+ const aPaths = chartPathListA.split(',');
+ const bPaths = chartPathListB.split(',');
+ const chartsA = parseFiles(aPaths);
+ const chartsB = parseFiles(bPaths);
+ const sampleA = valuesFromChartsWithFallback(chartsA, metric);
+ const sampleB = valuesFromChartsWithFallback(chartsB, metric);
+ return buildComparisonResultOutput(sampleA, sampleB);
+ }
+
+};
+
+if (tr.isHeadless) {
+ const [method, ...rest] = sys.argv.slice(1);
+ if (SampleComparison[method]) {
+ console.log(JSON.stringify(SampleComparison[method](...rest)));
+ }
+}
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py b/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py
new file mode 100644
index 00000000000..df58e8ba8ce
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/compare_samples_unittest.py
@@ -0,0 +1,336 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import json
+import math
+import os
+import random
+import tempfile
+import unittest
+
+from tracing.metrics import compare_samples
+
+
+REJECT = 'REJECT'
+FAIL_TO_REJECT = 'FAIL_TO_REJECT'
+NEED_MORE_DATA = 'NEED_MORE_DATA'
+
+
+def Mean(l):
+ if len(l):
+ return float(sum(l))/len(l)
+ return 0
+
+
+class CompareSamplesUnittest(unittest.TestCase):
+ def setUp(self):
+ self._tempfiles = []
+ self._tempdir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ for tf in self._tempfiles:
+ try:
+ os.remove(tf)
+ except OSError:
+ pass
+ try:
+ os.rmdir(self._tempdir)
+ except OSError:
+ pass
+
+ def NewJsonTempfile(self, jsonable_contents):
+ f_handle, new_json_file = tempfile.mkstemp(
+ suffix='.json',
+ dir=self._tempdir,
+ text=True)
+ os.close(f_handle)
+ self._tempfiles.append(new_json_file)
+ with open(new_json_file, 'w') as f:
+ json.dump(jsonable_contents, f)
+ return new_json_file
+
+ def MakeMultipleChartJSONHistograms(self, metric, seed, mu, sigma, n, m):
+ result = []
+ random.seed(seed)
+ for _ in range(m):
+ result.append(self.MakeChartJSONHistogram(metric, mu, sigma, n))
+ return result
+
+ def MakeChartJSONHistogram(self, metric, mu, sigma, n):
+ """Creates a histogram for a normally distributed pseudo-random sample.
+
+ This function creates a deterministic pseudo-random sample and stores it in
+ chartjson histogram format to facilitate the testing of the sample
+ comparison logic.
+
+ For simplicity we use sqrt(n) buckets with equal widths.
+
+ Args:
+ metric (str pair): name of chart, name of the trace.
+ seed (hashable obj): to make the sequences deterministic we seed the RNG.
+ mu (float): desired mean for the sample
+ sigma (float): desired standard deviation for the sample
+ n (int): number of values to generate.
+ """
+ chart_name, trace_name = metric
+ values = [random.gauss(mu, sigma) for _ in range(n)]
+ bucket_count = int(math.ceil(math.sqrt(len(values))))
+ width = (max(values) - min(values))/(bucket_count - 1)
+ prev_bucket = min(values)
+ buckets = []
+ for _ in range(bucket_count):
+ buckets.append({'low': prev_bucket,
+ 'high': prev_bucket + width,
+ 'count': 0})
+ prev_bucket += width
+ for value in values:
+ for bucket in buckets:
+ if value >= bucket['low'] and value < bucket['high']:
+ bucket['count'] += 1
+ break
+ charts = {
+ 'charts': {
+ chart_name: {
+ trace_name: {
+ 'type': 'histogram',
+ 'buckets': buckets
+ }
+ }
+ }
+ }
+ return self.NewJsonTempfile(charts)
+
+ def MakeChart(self, metric, seed, mu, sigma, n, keys=None):
+ """Creates a normally distributed pseudo-random sample. (continuous).
+
+ This function creates a deterministic pseudo-random sample and stores it in
+ chartjson format to facilitate the testing of the sample comparison logic.
+
+ Args:
+ metric (str pair): name of chart, name of the trace.
+ seed (hashable obj): to make the sequences deterministic we seed the RNG.
+ mu (float): desired mean for the sample
+ sigma (float): desired standard deviation for the sample
+ n (int): number of values to generate.
+ """
+ chart_name, trace_name = metric
+ random.seed(seed)
+ values = [random.gauss(mu, sigma) for _ in range(n)]
+ charts = {
+ 'charts': {
+ chart_name: {
+ trace_name: {
+ 'type': 'list_of_scalar_values',
+ 'values': values}
+ }
+ }
+ }
+ if keys:
+ grouping_keys = dict(enumerate(keys))
+ charts['charts'][chart_name][trace_name]['grouping_keys'] = grouping_keys
+ return self.NewJsonTempfile(charts)
+
+ def MakeNoneValuesChart(self, metric, keys=None):
+ """Creates a chart with merged None values.
+
+ Args:
+ metric (str pair): name of chart, name of the trace.
+ """
+ chart_name, trace_name = metric
+ charts = {
+ 'charts': {
+ chart_name: {
+ trace_name: {
+ 'type': 'list_of_scalar_values',
+ 'values': None
+ }
+ }
+ }
+ }
+ if keys:
+ grouping_keys = dict(enumerate(keys))
+ charts['charts'][chart_name][trace_name]['grouping_keys'] = grouping_keys
+ return self.NewJsonTempfile(charts)
+
+ def MakeCharts(self, metric, seed, mu, sigma, n, keys=None):
+ return [
+ self.MakeChartJSONScalar(metric, seed + '%d' % i, mu, sigma, keys)
+ for i in range(n)]
+
+ def MakeChartJSONScalar(self, metric, seed, mu, sigma, keys=None):
+ """Creates a normally distributed pseudo-random sample. (continuous).
+
+ This function creates a deterministic pseudo-random sample and stores it in
+ chartjson format to facilitate the testing of the sample comparison logic.
+
+ Args:
+ metric (str pair): name of chart, name of the trace.
+ seed (hashable obj): to make the sequences deterministic we seed the RNG.
+ mu (float): desired mean for the sample
+ sigma (float): desired standard deviation for the sample
+ """
+ chart_name, trace_name = metric
+ random.seed(seed)
+ charts = {
+ 'charts': {
+ chart_name: {
+ trace_name: {
+ 'type': 'scalar',
+ 'value': random.gauss(mu, sigma)}
+ }
+ }
+ }
+ if keys:
+ grouping_keys = dict(enumerate(keys))
+ charts['charts'][chart_name][trace_name]['grouping_keys'] = grouping_keys
+ return self.NewJsonTempfile(charts)
+
+ def testCompareClearRegressionListOfScalars(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join(self.MakeCharts(metric=metric, seed='lower',
+ mu=10, sigma=1, n=10))
+ higher_values = ','.join(self.MakeCharts(metric=metric, seed='higher',
+ mu=20, sigma=2, n=10))
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric)).stdout)
+ self.assertEqual(result['result']['significance'], REJECT)
+
+ def testCompareListOfScalarsWithNoneValue(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join(self.MakeCharts(metric=metric, seed='lower',
+ mu=10, sigma=1, n=10))
+ lower_values += ',' + self.MakeNoneValuesChart(metric=metric)
+ higher_values = ','.join(self.MakeCharts(metric=metric, seed='higher',
+ mu=20, sigma=2, n=10))
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric)).stdout)
+ self.assertEqual(result['result']['significance'], REJECT)
+
+ def testCompareClearRegressionScalars(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join(
+ [self.MakeChartJSONScalar(
+ metric=metric, seed='lower', mu=10, sigma=1) for _ in range(10)])
+ higher_values = ','.join(
+ [self.MakeChartJSONScalar(
+ metric=metric, seed='higher', mu=20, sigma=2) for _ in range(10)])
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric)).stdout)
+ self.assertEqual(result['result']['significance'], REJECT)
+
+ def testCompareUnlikelyRegressionWithMultipleRuns(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join(
+ self.MakeCharts(
+ metric=metric, seed='lower', mu=10, sigma=1, n=20))
+ higher_values = ','.join(
+ self.MakeCharts(
+ metric=metric, seed='higher', mu=10.01, sigma=0.95, n=20))
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric)).stdout)
+ self.assertEqual(result['result']['significance'], FAIL_TO_REJECT)
+
+ def testCompareTIRLabel(self):
+ tir_metric = ('some_chart', 'some_label', 'some_trace')
+ tir_metric_name = ('%s@@%s' % (tir_metric[1], tir_metric[0]), tir_metric[2])
+ lower_values = ','.join(self.MakeCharts(
+ metric=tir_metric_name, seed='lower', mu=10, sigma=1, n=10))
+ higher_values = ','.join(self.MakeCharts(
+ metric=tir_metric_name, seed='higher', mu=20, sigma=2, n=10))
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(tir_metric)).stdout)
+ self.assertEqual(result['result']['significance'], REJECT)
+
+ def testCompareTIRLabelMissingSummary(self):
+ tir_metric = ('some_chart', 'some_label')
+ tir_metric_name = ('%s@@%s' % (tir_metric[1], tir_metric[0]), 'summary')
+ lower_values = ','.join(self.MakeCharts(
+ metric=tir_metric_name, seed='lower', mu=10, sigma=1, n=10))
+ higher_values = ','.join(self.MakeCharts(
+ metric=tir_metric_name, seed='higher', mu=20, sigma=2, n=10))
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(tir_metric)).stdout)
+ self.assertEqual(result['result']['significance'], REJECT)
+
+ def testCompareInsufficientData(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join([self.MakeChart(metric=metric, seed='lower',
+ mu=10, sigma=1, n=5)])
+ higher_values = ','.join([self.MakeChart(metric=metric, seed='higher',
+ mu=10.40, sigma=0.95, n=5)])
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric)).stdout)
+ self.assertEqual(result['result']['significance'], NEED_MORE_DATA)
+
+ def testCompareMissingFile(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join([self.MakeChart(metric=metric, seed='lower',
+ mu=10, sigma=1, n=5)])
+ higher_values = '/path/does/not/exist.json'
+ with self.assertRaises(RuntimeError):
+ compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric))
+
+ def testCompareMissingMetric(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join([self.MakeChart(metric=metric, seed='lower',
+ mu=10, sigma=1, n=5)])
+ higher_values = ','.join([self.MakeChart(metric=metric, seed='higher',
+ mu=20, sigma=2, n=5)])
+ metric = ('some_chart', 'missing_trace')
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric)).stdout)
+ self.assertEqual(result['result']['significance'], NEED_MORE_DATA)
+
+ def testCompareBadChart(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join([self.MakeChart(metric=metric, seed='lower',
+ mu=10, sigma=1, n=5)])
+ higher_values = self.NewJsonTempfile(['obviously', 'not', 'a', 'chart]'])
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric)).stdout)
+ self.assertEqual(result['result']['significance'], NEED_MORE_DATA)
+
+ def testCompareBuildbotOutput(self):
+ bb = os.path.join(os.path.dirname(__file__),
+ 'buildbot_output_for_compare_samples_test.txt')
+ result = compare_samples.CompareSamples(
+ bb, bb, 'DrawCallPerf_gl/score',
+ data_format='buildbot')
+ result = json.loads(result.stdout)
+ self.assertEqual(result['result']['significance'], NEED_MORE_DATA)
+ self.assertEqual(Mean(result['sampleA']), 4123)
+ self.assertEqual(Mean(result['sampleB']), 4123)
+
+ def testCompareChartJsonHistogram(self):
+ metric = ('some_chart', 'some_trace')
+ lower_values = ','.join(self.MakeMultipleChartJSONHistograms(
+ metric=metric, seed='lower', mu=10, sigma=1, n=100, m=10))
+ higher_values = ','.join(self.MakeMultipleChartJSONHistograms(
+ metric=metric, seed='higher', mu=20, sigma=2, n=100, m=10))
+ result = json.loads(compare_samples.CompareSamples(
+ lower_values, higher_values, '/'.join(metric)).stdout)
+ self.assertEqual(result['result']['significance'], REJECT)
+
+ def testParseComplexMetricName(self):
+ full_metric_name = ('memory:chrome:all_processes:reported_by_os:'
+ 'system_memory:native_heap:'
+ 'proportional_resident_size_avg/blank_about/'
+ 'blank_about_blank')
+ chart_name = ('blank_about@@memory:chrome:all_processes:reported_by_os:'
+ 'system_memory:native_heap:proportional_resident_size_avg')
+ trace_name = 'blank:about:blank'
+ metric = chart_name, trace_name
+ keys = 'blank', 'about'
+ lower_values = ','.join(self.MakeCharts(metric=metric, seed='lower',
+ mu=10, sigma=1, n=10, keys=keys))
+ higher_values = ','.join(self.MakeCharts(metric=metric, seed='higher',
+ mu=20, sigma=2, n=10, keys=keys))
+ result = compare_samples.CompareSamples(
+ lower_values, higher_values, full_metric_name).stdout
+ print(result)
+ result = json.loads(result)
+ self.assertEqual(result['result']['significance'], REJECT)
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/console_error_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/console_error_metric.html
new file mode 100644
index 00000000000..5ed27d0f6be
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/console_error_metric.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.console', function() {
+ const COUNT_BOUNDARIES = tr.v.HistogramBinBoundaries.createExponential(
+ 1, 1e4, 30);
+ // We store a single value, so we only need one of the statistics to keep
+ // track. We choose the average for that.
+ const SUMMARY_OPTIONS = tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;
+
+ // Sources of console error message that we are interested in.
+ const SOURCES = ['all', 'js', 'network'];
+
+ /**
+ * This metric counts slices named 'ConsoleErrorMessage' and adds:
+ * - console:error:all - all console error messages.
+ * - console:error:js - console error messages coming from JS.
+ * - console:error:network - console error messages coming from network.
+ * If a console error message does not come from JS or network, it is still
+ * accounted in the console_error_all.
+ */
+ function consoleErrorMetric(histograms, model) {
+ const counts = {};
+ for (const source of SOURCES) {
+ counts[source] = 0;
+ }
+ for (const slice of model.getDescendantEvents()) {
+ if (slice.category === 'blink.console' &&
+ slice.title === 'ConsoleMessage::Error') {
+ const source = slice.args.source.toLowerCase();
+ counts.all++;
+ if (source in counts) {
+ counts[source]++;
+ }
+ }
+ if (slice.category === 'v8.console' && (
+ slice.title === 'V8ConsoleMessage::Exception' ||
+ slice.title === 'V8ConsoleMessage::Error' ||
+ slice.title === 'V8ConsoleMessage::Assert')) {
+ counts.all++;
+ counts.js++;
+ }
+ }
+ for (const source of SOURCES) {
+ histograms.createHistogram(
+ `console:error:${source}`,
+ tr.b.Unit.byName.count_smallerIsBetter,
+ counts[source], {
+ description: `Number of ${source} console error messages`,
+ summaryOptions: SUMMARY_OPTIONS
+ });
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(consoleErrorMetric);
+
+ return {
+ consoleErrorMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/console_error_metric_unittest.html b/chromium/third_party/catapult/tracing/tracing/metrics/console_error_metric_unittest.html
new file mode 100644
index 00000000000..eff2917fc47
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/console_error_metric_unittest.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/console_error_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function makeEvent(cat, name, source, timestamp) {
+ return {
+ cat,
+ name,
+ args: {source},
+ ts: timestamp,
+ pid: 52,
+ tid: 53,
+ ph: 'B'
+ };
+ }
+
+ test('consoleErrorMetric_noErrors', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ makeEvent('foo', '', 10),
+ makeEvent('bar', '', 20)
+ ];
+ tr.metrics.console.consoleErrorMetric(histograms,
+ tr.c.TestUtils.newModelWithEvents([events]));
+ const all = histograms.getHistogramNamed('console:error:all').running;
+ assert.strictEqual(all.count, 1);
+ assert.strictEqual(all.mean, 0);
+ const js = histograms.getHistogramNamed('console:error:js').running;
+ assert.strictEqual(js.count, 1);
+ assert.strictEqual(js.mean, 0);
+ const net = histograms.getHistogramNamed('console:error:network').running;
+ assert.strictEqual(net.count, 1);
+ assert.strictEqual(net.mean, 0);
+ });
+
+ test('consoleErrorMetric_Errors', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ makeEvent('blink.console', 'foo', '', 10),
+ makeEvent('blink.console', 'ConsoleMessage::Error', 'XML', 20),
+ makeEvent('blink.console', 'bar', '', 30),
+ makeEvent('blink.console', 'ConsoleMessage::Error', 'Network', 40),
+ makeEvent('blink.console', 'ConsoleMessage::Error', 'JS', 50),
+ makeEvent('blink.console', 'ConsoleMessage::Error', 'Network', 60),
+ makeEvent('blink.console', 'ConsoleMessage::Error', 'Network', 70),
+ makeEvent('blink.console', 'ConsoleMessage::Error', 'JS', 80),
+ makeEvent('blink.console', 'ConsoleMessage::Error', 'Network', 90),
+ makeEvent('bar', '', 300)
+ ];
+ tr.metrics.console.consoleErrorMetric(histograms,
+ tr.c.TestUtils.newModelWithEvents([events]));
+ const all = histograms.getHistogramNamed('console:error:all').running;
+ assert.strictEqual(all.count, 1);
+ assert.strictEqual(all.mean, 7);
+ const js = histograms.getHistogramNamed('console:error:js').running;
+ assert.strictEqual(js.count, 1);
+ assert.strictEqual(js.mean, 2);
+ const net = histograms.getHistogramNamed('console:error:network').running;
+ assert.strictEqual(net.count, 1);
+ assert.strictEqual(net.mean, 4);
+ });
+
+ test('consoleErrorMetric_V8', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ makeEvent('v8.console', 'foo', '', 10),
+ makeEvent('v8.console', 'V8ConsoleMessage::Error', '', 20),
+ makeEvent('v8.console', 'bar', '', 30),
+ makeEvent('v8.console', 'V8ConsoleMessage::Exception', '', 40),
+ makeEvent('v8.console', 'V8ConsoleMessage::Assert', '', 50),
+ makeEvent('v8.console', 'V8ConsoleMessage::Ignore', '', 60),
+ makeEvent('v8.console', 'V8ConsoleMessage::Ignore', '', 70),
+ makeEvent('v8.console', 'bar', '', 300)
+ ];
+ tr.metrics.console.consoleErrorMetric(histograms,
+ tr.c.TestUtils.newModelWithEvents([events]));
+ const all = histograms.getHistogramNamed('console:error:all').running;
+ assert.strictEqual(all.count, 1);
+ assert.strictEqual(all.mean, 3);
+ const js = histograms.getHistogramNamed('console:error:js').running;
+ assert.strictEqual(js.count, 1);
+ assert.strictEqual(js.mean, 3);
+ const net = histograms.getHistogramNamed('console:error:network').running;
+ assert.strictEqual(net.count, 1);
+ assert.strictEqual(net.mean, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/cpu_process_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/cpu_process_metric.html
new file mode 100644
index 00000000000..c858a8bcb2d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/cpu_process_metric.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ function getCpuSnapshotsFromModel(model) {
+ const snapshots = [];
+ for (const pid in model.processes) {
+ const snapshotInstances =
+ model.processes[pid].objects.getAllInstancesNamed('CPUSnapshots');
+ if (!snapshotInstances) continue;
+
+ for (const object of snapshotInstances[0].snapshots) {
+ snapshots.push(object.args.processes);
+ }
+ }
+ return snapshots;
+ }
+
+ function getProcessSumsFromSnapshot(snapshot) {
+ const processSums = new Map();
+ for (const processData of snapshot) {
+ const processName = processData.name;
+ if (!(processSums.has(processName))) {
+ processSums.set(processName, {sum: 0.0, paths: new Set()});
+ }
+ processSums.get(processName).sum += parseFloat(processData.pCpu);
+ // The process path may be missing on Windows because of AccessDenied
+ // error thrown by psutil package used by CPU tracing agent.
+ if (processData.path) {
+ processSums.get(processName).paths.add(processData.path);
+ }
+ }
+ return processSums;
+ }
+
+ function buildNumericsFromSnapshots(snapshots) {
+ const processNumerics = new Map();
+ for (const snapshot of snapshots) {
+ const processSums = getProcessSumsFromSnapshot(snapshot);
+ for (const [processName, processData] of processSums.entries()) {
+ if (!(processNumerics.has(processName))) {
+ processNumerics.set(processName, {
+ numeric: new tr.v.Histogram('cpu:percent:' + processName,
+ tr.b.Unit.byName.normalizedPercentage_smallerIsBetter),
+ paths: new Set()
+ });
+ }
+ processNumerics.get(processName).numeric.addSample(
+ processData.sum / 100.0);
+ for (const path of processData.paths) {
+ processNumerics.get(processName).paths.add(path);
+ }
+ }
+ }
+ return processNumerics;
+ }
+
+ function cpuProcessMetric(histograms, model) {
+ const snapshots = getCpuSnapshotsFromModel(model);
+ const processNumerics = buildNumericsFromSnapshots(snapshots);
+ for (const [processName, processData] of processNumerics) {
+ const numeric = processData.numeric;
+ // Treat missing snapshots as zeros. A process is missing from a snapshots
+ // when its CPU usage was below minimum threshold when the snapshot was
+ // taken.
+ const missingSnapshotCount = snapshots.length - numeric.numValues;
+ for (let i = 0; i < missingSnapshotCount; i++) {
+ numeric.addSample(0);
+ }
+ numeric.diagnostics.set('paths', new
+ tr.v.d.GenericSet([...processData.paths]));
+ histograms.addHistogram(numeric);
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(cpuProcessMetric);
+
+ return {
+ cpuProcessMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/cpu_process_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/cpu_process_metric_test.html
new file mode 100644
index 00000000000..55e404c5b4d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/cpu_process_metric_test.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/cpu_process_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function makeModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events]);
+ }
+
+ test('cpuProcessMetric_noData', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'}
+ ];
+ tr.metrics.sh.cpuProcessMetric(histograms, makeModel(events));
+ assert.lengthOf(histograms, 0);
+ });
+
+ test('cpuProcessMetric_singleSnapshots', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ {
+ 'name': 'CPUSnapshots',
+ 'args': {
+ 'snapshot': {
+ 'processes': [
+ {'path': '/usr/sbin/crudd', 'pCpu': '99.0', 'pid': '13495',
+ 'pMem': '0.0', 'name': 'crudd'},
+ {'path': '/opt/chrome/chrome', 'pCpu': '0.8',
+ 'pid': '29660', 'pMem': '0.9', 'name': 'chrome'},
+ {'path': '/opt/chrome/chrome', 'pCpu': '0.3',
+ 'pid': '29661', 'pMem': '0.9', 'name': 'chrome'}
+ ]
+ }
+ },
+ 'pid': 52, 'ts': '2226221225693.658', 'tid': 53, 'ph': 'O',
+ 'local': true, 'id': '0x1000'
+ }
+ ];
+ tr.metrics.sh.cpuProcessMetric(histograms, makeModel(events));
+
+ assert.isDefined(histograms.getHistogramNamed('cpu:percent:chrome'));
+ assert.isDefined(histograms.getHistogramNamed('cpu:percent:crudd'));
+ const chromeValue = histograms.getHistogramNamed('cpu:percent:chrome');
+ const chromeStatistics = chromeValue.running;
+ assert.strictEqual(chromeStatistics.count, 1);
+ assert.closeTo(chromeStatistics.mean, 0.011, 1e-5);
+ assert.closeTo(chromeStatistics.max, 0.011, 1e-5);
+ assert.instanceOf(chromeValue.diagnostics.get('paths'), tr.v.d.GenericSet);
+ const paths = tr.b.getOnlyElement(chromeValue.diagnostics.get('paths'));
+ assert.strictEqual(paths, '/opt/chrome/chrome');
+ });
+
+ test('cpuProcessMetric_multipleSnapshots', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ {
+ 'name': 'CPUSnapshots',
+ 'args': {
+ 'snapshot': {
+ 'processes': [
+ {'path': '/usr/sbin/crudd', 'pCpu': '99.0', 'pid': '13495',
+ 'pMem': '0.0', 'name': 'crudd'},
+ {'path': '/opt/chrome/chrome', 'pCpu': '0.8',
+ 'pid': '29660', 'pMem': '0.9', 'name': 'chrome'}
+ ]
+ }
+ },
+ 'pid': 52, 'ts': '2226221225693.658', 'tid': 53,
+ 'ph': 'O', 'local': true, 'id': '0x1000'
+ },
+ {
+ 'name': 'CPUSnapshots',
+ 'args': {
+ 'snapshot': {
+ 'processes': [
+ {'path': '/usr/sbin/crudd', 'pCpu': '1.3', 'pid': '13495',
+ 'pMem': '0.0', 'name': 'crudd'},
+ {'path': '/opt/chrome/chrome', 'pCpu': '0.6',
+ 'pid': '29660', 'pMem': '0.9', 'name': 'chrome'},
+ {'path': '/opt/chromium/chrome', 'pCpu': '0.1',
+ 'pid': '29660', 'pMem': '0.9', 'name': 'chrome'},
+ {'path': '/usr/sbin/mnp_logger', 'pCpu': '0.2', 'pid': '6543',
+ 'pMem': '0.1', 'name': 'mnp_logger'}
+ ]
+ }
+ },
+ 'pid': 52, 'ts': '2226222262064.4473', 'tid': 53,
+ 'ph': 'O', 'local': true, 'id': '0x1000'
+ }
+ ];
+ tr.metrics.sh.cpuProcessMetric(histograms, makeModel(events));
+ assert.isDefined(histograms.getHistogramNamed('cpu:percent:chrome'));
+ assert.isDefined(histograms.getHistogramNamed('cpu:percent:crudd'));
+ assert.isDefined(histograms.getHistogramNamed('cpu:percent:mnp_logger'));
+ const chromeValue = histograms.getHistogramNamed('cpu:percent:chrome');
+ const chromeStatistics = chromeValue.running;
+ assert.strictEqual(chromeStatistics.count, 2);
+ assert.closeTo(chromeStatistics.mean, 0.0075, 1e-5);
+ assert.strictEqual(chromeStatistics.max, 0.008);
+ assert.instanceOf(chromeValue.diagnostics.get('paths'), tr.v.d.GenericSet);
+ const paths = Array.from(chromeValue.diagnostics.get('paths'));
+ assert.lengthOf(paths, 2);
+ assert.strictEqual(paths[0], '/opt/chrome/chrome');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/discover.py b/chromium/third_party/catapult/tracing/tracing/metrics/discover.py
new file mode 100644
index 00000000000..ef532c6d0df
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/discover.py
@@ -0,0 +1,34 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+
+import tracing_project
+import vinn
+
+
+_DISCOVER_CMD_LINE = os.path.join(
+ os.path.dirname(__file__), 'discover_cmdline.html')
+
+
+def DiscoverMetrics(modules_to_load):
+ """ Returns a list of registered metrics.
+
+ Args:
+ modules_to_load: a list of modules (string) to be loaded before discovering
+ the registered metrics.
+ """
+ assert isinstance(modules_to_load, list)
+ project = tracing_project.TracingProject()
+ all_source_paths = list(project.source_paths)
+
+ res = vinn.RunFile(
+ _DISCOVER_CMD_LINE, source_paths=all_source_paths,
+ js_args=modules_to_load)
+
+ if res.returncode != 0:
+ raise RuntimeError('Error running metrics_discover_cmdline: ' + res.stdout)
+ else:
+ return [str(m) for m in json.loads(res.stdout)]
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/discover_cmdline.html b/chromium/third_party/catapult/tracing/tracing/metrics/discover_cmdline.html
new file mode 100644
index 00000000000..c8aab5cd98d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/discover_cmdline.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+function discoverMetrics(args) {
+ for (let i = 0; i < args.length; i++) {
+ const filename = args[i];
+ HTMLImportsLoader.loadHTML(filename);
+ }
+
+ const metrics = tr.metrics.MetricRegistry.getAllRegisteredTypeInfos();
+ const discoveredMetricNames = [];
+ for (let i = 0; i < metrics.length; i++) {
+ discoveredMetricNames.push(metrics[i].constructor.name);
+ }
+ console.log(JSON.stringify(discoveredMetricNames));
+ return 0;
+}
+
+if (tr.isHeadless) {
+ quit(discoverMetrics(sys.argv.slice(1)));
+}
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py b/chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py
new file mode 100644
index 00000000000..10b81b547c8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/discover_unittest.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.metrics import discover
+
+class MetricsDiscoverUnittest(unittest.TestCase):
+ def testMetricsDiscoverEmpty(self):
+ self.assertFalse(discover.DiscoverMetrics([]))
+
+ def testMetricsDiscoverNonEmpty(self):
+ self.assertEquals(['sampleMetric'], discover.DiscoverMetrics(
+ ['/tracing/metrics/sample_metric.html']))
+
+ def testMetricsDiscoverMultipleMetrics(self):
+ self.assertGreater(
+ len(discover.DiscoverMetrics(
+ ['/tracing/metrics/all_metrics.html'])), 1)
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html
new file mode 100644
index 00000000000..2e1ec342a5e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/media_metric.html
@@ -0,0 +1,395 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+media_metric uses Chrome trace events to calculate metrics about video
+and audio playback. It is meant to be used for pages with <video> and/or
+<audio> elements. It is used by videostack-eng@google.com team for
+regression testing.
+
+See class PerPlaybackData for details on each of the values that are measured.
+
+This metric supports media playbacks happening simultaneously over multiple
+pages, supports multiple media elements on a page, and supports multiple
+playbacks with each element. It does not support media playback using
+flash or any other technology not provided by Chrome videostack team.
+
+Please inform crouleau@chromium.org and johnchen@chromium.org about
+changes to this file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ function mediaMetric(histograms, model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (chromeHelper === undefined) return;
+
+ for (const rendererHelper of Object.values(chromeHelper.rendererHelpers)) {
+ // Find the threads we're interested in, and if a needed thread
+ // is missing, no need to look further in this process.
+ const mainThread = rendererHelper.mainThread;
+ if (mainThread === undefined) continue;
+
+ const compositorThread = rendererHelper.compositorThread;
+ const audioThreads =
+ rendererHelper.process.findAllThreadsNamed('AudioOutputDevice');
+ if (compositorThread === undefined && audioThreads.length === 0) continue;
+
+ const processData = new PerProcessData();
+
+ processData.recordPlayStarts(mainThread);
+ if (!processData.hasPlaybacks) continue;
+
+ if (compositorThread !== undefined) {
+ processData.calculateTimeToVideoPlays(compositorThread);
+ processData.calculateDroppedFrameCounts(compositorThread);
+ }
+
+ if (audioThreads.length !== 0) {
+ processData.calculateTimeToAudioPlays(audioThreads);
+ }
+
+ processData.calculateSeekTimes(mainThread);
+ processData.calculateBufferingTimes(mainThread);
+
+ processData.addMetricToHistograms(histograms);
+ }
+ }
+
+ // PerProcessData manages all metric values associated with a renderer
+ // process. The process can have multiple media playbacks.
+ class PerProcessData {
+ constructor() {
+ // All the perf data we collect for a process are stored in a Map.
+ // Each key of the map is an ID of a media playback, and the value
+ // associated with each key is a PerPlaybackData object containing
+ // all the perf data for that playback.
+ this.playbackIdToDataMap_ = new Map();
+ }
+
+ recordPlayStarts(mainThread) {
+ for (const event of mainThread.sliceGroup.getDescendantEvents()) {
+ if (event.title === 'WebMediaPlayerImpl::DoLoad') {
+ const id = event.args.id;
+ if (this.playbackIdToDataMap_.has(id)) {
+ throw new Error(
+ 'Unexpected multiple initialization of a media playback');
+ }
+ this.playbackIdToDataMap_.set(id, new PerPlaybackData(event.start));
+ }
+ }
+ }
+
+ get hasPlaybacks() {
+ return this.playbackIdToDataMap_.size > 0;
+ }
+
+ calculateTimeToVideoPlays(compositorThread) {
+ for (const event of compositorThread.sliceGroup.getDescendantEvents()) {
+ if (event.title === 'VideoRendererImpl::Render') {
+ this.getPerPlaybackObject_(event.args.id)
+ .processVideoRenderTime(event.start);
+ }
+ }
+ }
+
+ calculateTimeToAudioPlays(audioThreads) {
+ for (const audioThread of audioThreads) {
+ for (const event of audioThread.sliceGroup.getDescendantEvents()) {
+ if (event.title === 'AudioRendererImpl::Render') {
+ this.getPerPlaybackObject_(event.args.id)
+ .processAudioRenderTime(event.start);
+ }
+ }
+ }
+ }
+
+ calculateSeekTimes(mainThread) {
+ for (const event of mainThread.sliceGroup.getDescendantEvents()) {
+ if (event.title === 'WebMediaPlayerImpl::DoSeek') {
+ this.getPerPlaybackObject_(event.args.id)
+ .processDoSeek(event.args.target, event.start);
+ } else if (event.title === 'WebMediaPlayerImpl::OnPipelineSeeked') {
+ this.getPerPlaybackObject_(event.args.id)
+ .processOnPipelineSeeked(event.args.target, event.start);
+ } else if (event.title === 'WebMediaPlayerImpl::BufferingHaveEnough') {
+ this.getPerPlaybackObject_(event.args.id)
+ .processBufferingHaveEnough(event.start);
+ }
+ }
+ }
+
+ calculateBufferingTimes(mainThread) {
+ for (const event of mainThread.sliceGroup.getDescendantEvents()) {
+ if (event.title === 'WebMediaPlayerImpl::OnEnded') {
+ this.getPerPlaybackObject_(event.args.id)
+ .processOnEnded(event.start, event.args.duration);
+ }
+ }
+ }
+
+ calculateDroppedFrameCounts(compositorThread) {
+ for (const event of compositorThread.sliceGroup.getDescendantEvents()) {
+ if (event.title === 'VideoFramesDropped') {
+ this.getPerPlaybackObject_(event.args.id)
+ .processVideoFramesDropped(event.args.count);
+ }
+ }
+ }
+
+ addMetricToHistograms(histograms) {
+ for (const [id, playbackData] of this.playbackIdToDataMap_) {
+ playbackData.addMetricToHistograms(histograms);
+ }
+ }
+
+ // @private
+ getPerPlaybackObject_(playbackId) {
+ let perPlaybackObject = this.playbackIdToDataMap_.get(playbackId);
+ if (perPlaybackObject === undefined) {
+ // The trace isn't complete, and didn't contain the DoLoad event for
+ // this playback. Create a new PerPlaybackData object for this playback.
+ perPlaybackObject = new PerPlaybackData(undefined);
+ this.playbackIdToDataMap_.set(playbackId, perPlaybackObject);
+ }
+ return perPlaybackObject;
+ }
+ }
+
+ // PerPlaybackData contains all metric values associated with a single
+ // media playback.
+ class PerPlaybackData {
+ constructor(playStartTime) {
+ this.playStart_ = playStartTime;
+ this.timeToVideoPlay_ = undefined;
+ this.timeToAudioPlay_ = undefined;
+ this.bufferingTime_ = undefined;
+ this.droppedFrameCount_ = 0;
+ this.seekError_ = false;
+ this.seekTimes_ = new Map();
+ this.currentSeek_ = undefined;
+ }
+
+ // API methods for retrieving metric values. Each method returns undefined
+ // if no value is available (e.g., timeToVideoPlay() returns undefined for
+ // an audio-only playback).
+
+ // Returns how long after a video is requested to start playing before
+ // the video actually starts. If time_to_video_play regresses, then users
+ // will click to play videos and then have to wait longer before the videos
+ // start actually playing.
+ get timeToVideoPlay() {
+ return this.timeToVideoPlay_;
+ }
+
+ // Similar to timeToVideoPlay, but measures the time delay before audio
+ // starts playing.
+ get timeToAudioPlay() {
+ return this.timeToAudioPlay_;
+ }
+
+ // Returns the difference between the actual play time of media vs its
+ // expected play time. Ideally the two should be the same. If actual play
+ // time is significantly longer than expected play time, it indicates that
+ // there were stalls during the play for buffering or some other reasons.
+ // Current limitation: Buffering time isn't calculated if seek occurred
+ // during playback, and it gives incorrect value if the playback isn't
+ // from beginning to end without pauses.
+ get bufferingTime() {
+ return this.bufferingTime_;
+ }
+
+ // Reports the number of video frames that were dropped. Ideally this
+ // should be 0. If a large number of frames are dropped, the video playback
+ // will not be smooth.
+ get droppedFrameCount() {
+ // We should report dropped frame count as long as video was played.
+ return (this.timeToVideoPlay_ !== undefined) ?
+ this.droppedFrameCount_ : undefined;
+ }
+
+ // Returns a Map containing seek times. The keys of the map are numerical
+ // values indicating the target location of the seek, in unit of seconds.
+ // The values of the map are objects with the following public properties:
+ // * pipelineSeekTime: amount of time taken by media pipeline to process
+ // this seek operation, from when the seek request is received, to when
+ // the pipeline starts processing at the new location, in milliseconds.
+ // * seekTime: how long after a user requests a seek operation before the
+ // seek completes and the media starts playing at the new location, as
+ // perceived by the user, in milliseconds.
+ get seekTimes() {
+ if (this.seekError_ || this.currentSeek_ !== undefined) return new Map();
+ return this.seekTimes_;
+ }
+
+ // API methods for processing data from trace events.
+
+ processVideoRenderTime(videoRenderTime) {
+ // Each video playback can generate multiple Render events, one for
+ // each frame. For calculating time to video play, we only use the
+ // first Render event.
+ if (this.playStart_ !== undefined &&
+ this.timeToVideoPlay_ === undefined) {
+ this.timeToVideoPlay_ = videoRenderTime - this.playStart_;
+ }
+ }
+
+ processAudioRenderTime(audioRenderTime) {
+ if (this.playStart_ !== undefined &&
+ this.timeToAudioPlay_ === undefined) {
+ this.timeToAudioPlay_ = audioRenderTime - this.playStart_;
+ }
+ }
+
+ processVideoFramesDropped(count) {
+ this.droppedFrameCount_ += count;
+ }
+
+ // We support multiple seeks per element, as long as they seek to different
+ // target time. Thus the seek times are stored in a Map instead of a scalar
+ // property. The key of the map is event.args.target, which is a numerical
+ // value indicating the target location of the seek, in unit of seconds.
+ // For example, with a seek to 5 seconds mark, event.args.target === 5.
+ // The value of the map is an object with 4 properties (the first two are
+ // added during object creation, the latter two are added as the data
+ // become available):
+ // * target: seek target time (same as the map key)
+ // * startTime: timestamp of the event marking start of seek
+ // * pipelineSeekTime: amount of time taken by media pipeline to process
+ // this seek (milliseconds)
+ // * seekTime: amount of seek time perceived by the user (milliseconds)
+ // If any unexpected conditions occur, we stop processing and set an error
+ // flag this.seekError_.
+ // TODO(https://github.com/catapult-project/catapult/issues/3976):
+ // Emit detailed warnings.
+ processDoSeek(target, startTime) {
+ // currentSeek_ refers to the object associated with the
+ // seek that is currently being processed for this media element.
+ // It is used to match seek end events against seek start events.
+ if (this.currentSeek_ !== undefined) {
+ // TODO(https://github.com/catapult-project/catapult/issues/3976):
+ // Warning 'Overlapping seek not supported'.
+ this.seekError_ = true;
+ return;
+ }
+ this.currentSeek_ = { target, startTime };
+ this.seekTimes_.set(target, this.currentSeek_);
+ }
+
+ processOnPipelineSeeked(target, time) {
+ if (this.seekError_) return;
+ const currentSeek = this.currentSeek_;
+ if (currentSeek === undefined) {
+ // OK to have this event when there is no active seek, as this event
+ // can be generated for other reasons, e.g., initial loading of media
+ // generates this event with target of 0 seconds.
+ return;
+ }
+ if (currentSeek.target !== target) {
+ // TODO(https://github.com/catapult-project/catapult/issues/3976):
+ // Warning 'WebMediaPlayerImpl::OnPipelineSeeked to unexpected target'.
+ this.seekError_ = true;
+ return;
+ }
+ if (currentSeek.pipelineSeekTime !== undefined) {
+ // TODO(https://github.com/catapult-project/catapult/issues/3976):
+ // Warning 'Multiple WebMediaPlayerImpl::OnPipelineSeeked events'.
+ this.seekError_ = true;
+ return;
+ }
+ currentSeek.pipelineSeekTime = time - currentSeek.startTime;
+ }
+
+ processBufferingHaveEnough(time) {
+ if (this.seekError_) return;
+ const currentSeek = this.currentSeek_;
+ if (currentSeek === undefined) {
+ // No current seek means this event is generated by non-seek related
+ // events, e.g., initial loading of media.
+ return;
+ }
+ if (currentSeek.pipelineSeekTime === undefined) {
+ // Since we haven't seen WebMediaPlayerImpl::OnPipelineSeeked event
+ // event yet, this event is triggered by something else, e.g., a
+ // have_nothing->have_enough cycle due to underflow from decoders.
+ return;
+ }
+ currentSeek.seekTime = time - currentSeek.startTime;
+ // Finished processing current seek.
+ this.currentSeek_ = undefined;
+ }
+
+ processOnEnded(playEndTime, duration) {
+ if (this.playStart_ === undefined) return;
+ // Can't calculate buffering time if there were any seeks.
+ if (this.seekTimes_.size !== 0 || this.seekError_) return;
+ // Play was resumed after it ended previously.
+ if (this.bufferingTime_ !== undefined) return;
+ // Convert duration from seconds to milliseconds.
+ duration = tr.b.convertUnit(duration, tr.b.UnitPrefixScale.METRIC.NONE,
+ tr.b.UnitPrefixScale.METRIC.MILLI);
+ const playTime = playEndTime - this.playStart_;
+ if (this.timeToVideoPlay_ !== undefined) {
+ this.bufferingTime_ = playTime - duration - this.timeToVideoPlay_;
+ } else if (this.timeToAudioPlay !== undefined) {
+ this.bufferingTime_ = playTime - duration - this.timeToAudioPlay_;
+ }
+ }
+
+ addMetricToHistograms(histograms) {
+ this.addSample_(histograms, 'time_to_video_play',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ this.timeToVideoPlay);
+ this.addSample_(histograms, 'time_to_audio_play',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ this.timeToAudioPlay);
+ this.addSample_(histograms, 'dropped_frame_count',
+ tr.b.Unit.byName.count_smallerIsBetter,
+ this.droppedFrameCount);
+ for (const [key, value] of this.seekTimes.entries()) {
+ // key is a numerical value that can have '.' when converted to
+ // string. However, '.' causes problems in histogram names, so
+ // replace with '_'.
+ const keyString = key.toString().replace('.', '_');
+ this.addSample_(histograms, 'pipeline_seek_time_' + keyString,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ value.pipelineSeekTime);
+ this.addSample_(histograms, 'seek_time_' + keyString,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ value.seekTime);
+ }
+ this.addSample_(histograms, 'buffering_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ this.bufferingTime);
+ }
+
+ // @private
+ addSample_(histograms, name, unit, sample) {
+ if (sample === undefined) return;
+ const histogram = histograms.getHistogramNamed(name);
+ if (histogram === undefined) {
+ histograms.createHistogram(name, unit, sample);
+ } else {
+ histogram.addSample(sample);
+ }
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(mediaMetric);
+
+ return {
+ mediaMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/media_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/media_metric_test.html
new file mode 100644
index 00000000000..a404b8e1980
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/media_metric_test.html
@@ -0,0 +1,423 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/media_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ // Arbitrarily selected process ID and thread IDs we'll use in test data
+ const procId = 52;
+ const tidMain = 1;
+ const tidCompositor = 53;
+ const tidAudio = 55;
+
+ function doLoadEvent(timestamp, opt_id) {
+ return {name: 'WebMediaPlayerImpl::DoLoad', args: {id: opt_id || 0},
+ pid: procId, ts: timestamp, cat: 'media', tid: tidMain, ph: 'X'};
+ }
+
+ function videoRenderEvent(timestamp, opt_id) {
+ return {name: 'VideoRendererImpl::Render', args: {id: opt_id || 0},
+ pid: procId, ts: timestamp, cat: 'media', tid: tidCompositor, ph: 'X'};
+ }
+
+ function audioRenderEvent(timestamp, opt_id) {
+ return {name: 'AudioRendererImpl::Render', args: {id: opt_id || 0},
+ pid: procId, ts: timestamp, cat: 'media', tid: tidAudio, ph: 'X'};
+ }
+
+ function videoFramesDroppedEvent(timestamp, frameCount, opt_id) {
+ return {name: 'VideoFramesDropped',
+ args: {count: frameCount, id: opt_id || 0},
+ pid: procId, ts: timestamp, cat: 'media', tid: tidCompositor, ph: 'X'};
+ }
+
+ function onEndedEvent(timestamp, mediaDuration, opt_id) {
+ return {name: 'WebMediaPlayerImpl::OnEnded',
+ args: {duration: mediaDuration, id: opt_id || 0},
+ pid: procId, ts: timestamp, cat: 'media', tid: tidMain, ph: 'X'};
+ }
+
+ function doSeekEvent(timestamp, targetTime, opt_id) {
+ return {name: 'WebMediaPlayerImpl::DoSeek',
+ args: {target: targetTime, id: opt_id || 0},
+ pid: procId, ts: timestamp, cat: 'media', tid: tidMain, ph: 'X'};
+ }
+
+ function seekedEvent(timestamp, targetTime, opt_id) {
+ return {name: 'WebMediaPlayerImpl::OnPipelineSeeked',
+ args: {target: targetTime, id: opt_id || 0},
+ pid: procId, ts: timestamp, cat: 'media', tid: tidMain, ph: 'X'};
+ }
+
+ function bufferEnoughEvent(timestamp, opt_id) {
+ return {name: 'WebMediaPlayerImpl::BufferingHaveEnough',
+ args: {id: opt_id || 0},
+ pid: procId, ts: timestamp, cat: 'media', tid: tidMain, ph: 'X'};
+ }
+
+ function threadMarker(threadName, threadId) {
+ return {name: 'thread_name', args: {name: threadName},
+ pid: procId, ts: 0, cat: '__metadata', tid: threadId, ph: 'M'};
+ }
+
+ const mainThreadMarker = threadMarker('CrRendererMain', tidMain);
+ const compositorThreadMarker = threadMarker('Compositor', tidCompositor);
+ const audioThreadMarker = threadMarker('AudioOutputDevice', tidAudio);
+
+ function makeModel(events) {
+ return tr.c.TestUtils.newModelWithEvents([events]);
+ }
+
+ function checkCloseTo(histograms, histogramName, expectedValue) {
+ assert.isDefined(histograms.getHistogramNamed(histogramName));
+ const value = histograms.getHistogramNamed(histogramName);
+ const statistics = value.running;
+ assert.strictEqual(statistics.count, 1);
+ assert.closeTo(statistics.mean, expectedValue, 1e-5);
+ }
+
+ function checkCloseToMultiple(histograms, histogramName, expectedCount,
+ expectedMin, expectedMean, expectedMax) {
+ assert.isDefined(histograms.getHistogramNamed(histogramName));
+ const value = histograms.getHistogramNamed(histogramName);
+ const statistics = value.running;
+ assert.strictEqual(statistics.count, expectedCount);
+ assert.closeTo(statistics.min, expectedMin, 1e-5);
+ assert.closeTo(statistics.mean, expectedMean, 1e-5);
+ assert.closeTo(statistics.max, expectedMax, 1e-5);
+ }
+
+ function checkEqual(histograms, histogramName, expectedValue) {
+ assert.isDefined(histograms.getHistogramNamed(histogramName));
+ const value = histograms.getHistogramNamed(histogramName);
+ const statistics = value.running;
+ assert.strictEqual(statistics.count, 1);
+ assert.strictEqual(statistics.mean, expectedValue);
+ }
+
+ test('mediaMetric_noData', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ assert.lengthOf(histograms, 0);
+ });
+
+ test('mediaMetric_videoTimeToPlay', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(100),
+ videoRenderEvent(300),
+ // Video renderer always generate multiple render events,
+ // one for each frame. For calculation of time-to-play,
+ // only the first render event is relevant. Here we put in
+ // a second render event to make sure it's ignored by the
+ // metric computation code.
+ videoRenderEvent(400),
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkCloseTo(histograms, 'time_to_video_play', 0.2);
+ });
+
+ test('mediaMetric_audioTimeToPlay', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ mainThreadMarker,
+ audioThreadMarker,
+ doLoadEvent(1000),
+ audioRenderEvent(1100),
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkCloseTo(histograms, 'time_to_audio_play', 0.1);
+ });
+
+ test('mediaMetric_bufferingTimeVideo', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(1500),
+ videoRenderEvent(1600),
+ onEndedEvent(10051500, 10),
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkCloseTo(histograms, 'buffering_time', 50);
+ });
+
+ test('mediaMetric_bufferingTimeAudio', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ mainThreadMarker,
+ audioThreadMarker,
+ doLoadEvent(1000),
+ audioRenderEvent(1500),
+ onEndedEvent(5002500, 5),
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkCloseTo(histograms, 'buffering_time', 1);
+ });
+
+ // With seek, no buffering time should be reported
+ test('mediaMetric_noBufferingTime', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(1500),
+ videoRenderEvent(1600),
+ onEndedEvent(10066666, 10),
+ doSeekEvent(525, 1.2),
+ seekedEvent(719, 1.2),
+ bufferEnoughEvent(825),
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ assert.isUndefined(histograms.getHistogramNamed('buffering_time'));
+ });
+
+ test('mediaMetric_droppedFrameCount', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(1500),
+ videoFramesDroppedEvent(123456, 3),
+ videoFramesDroppedEvent(234567, 6),
+ videoFramesDroppedEvent(345678, 1),
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkEqual(histograms, 'dropped_frame_count', 10);
+ });
+
+ test('mediaMetric_droppedFrameCountZero', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(1500),
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkEqual(histograms, 'dropped_frame_count', 0);
+ });
+
+ test('mediaMetric_droppedFrameCountNoVideo', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ audioRenderEvent(1500),
+ mainThreadMarker,
+ audioThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ assert.isUndefined(histograms.getHistogramNamed('dropped_frame_count'));
+ });
+
+ test('mediaMetric_seekTimeVideo', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(1500),
+ doSeekEvent(2000, 1.2),
+ seekedEvent(2500, 1.2),
+ bufferEnoughEvent(3000),
+ doSeekEvent(15000, 3.7),
+ seekedEvent(75000, 3.7),
+ bufferEnoughEvent(95000),
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkCloseTo(histograms, 'pipeline_seek_time_1_2', 0.5);
+ checkCloseTo(histograms, 'seek_time_1_2', 1);
+ checkCloseTo(histograms, 'pipeline_seek_time_3_7', 60);
+ checkCloseTo(histograms, 'seek_time_3_7', 80);
+ });
+
+ test('mediaMetric_seekTimeAudio', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ audioRenderEvent(1500),
+ doSeekEvent(2000, 1.2),
+ seekedEvent(2500, 1.2),
+ bufferEnoughEvent(3000),
+ doSeekEvent(15000, 3.7),
+ seekedEvent(75000, 3.7),
+ bufferEnoughEvent(95000),
+ mainThreadMarker,
+ audioThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkCloseTo(histograms, 'pipeline_seek_time_1_2', 0.5);
+ checkCloseTo(histograms, 'seek_time_1_2', 1);
+ checkCloseTo(histograms, 'pipeline_seek_time_3_7', 60);
+ checkCloseTo(histograms, 'seek_time_3_7', 80);
+ });
+
+ test('mediaMetric_seekOverlap', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(1500),
+ doSeekEvent(2000, 1.2),
+ seekedEvent(2500, 1.2),
+ doSeekEvent(2800, 3.7), // Out of order
+ bufferEnoughEvent(3000),
+ seekedEvent(75000, 3.7),
+ bufferEnoughEvent(95000),
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ assert.isDefined(histograms.getHistogramNamed('time_to_video_play'));
+ assert.isUndefined(histograms.getHistogramNamed('seek_time_1_2'));
+ });
+
+ test('mediaMetric_seekIncomplete', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(1500),
+ doSeekEvent(2000, 1.2),
+ seekedEvent(2500, 1.2),
+ // Missing bufferEnoughEvent
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ assert.isDefined(histograms.getHistogramNamed('time_to_video_play'));
+ assert.isUndefined(histograms.getHistogramNamed('seek_time_1_2'));
+ });
+
+ test('mediaMetric_seekWrongTarget', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(1500),
+ doSeekEvent(2000, 1.2),
+ seekedEvent(2500, 2.7), // Wrong target, should be 1.2
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ assert.isDefined(histograms.getHistogramNamed('time_to_video_play'));
+ assert.isUndefined(histograms.getHistogramNamed('seek_time_1_2'));
+ });
+
+ test('mediaMetric_multiplePlaybacks', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000, 0),
+ doLoadEvent(1100, 1),
+ videoRenderEvent(1400, 1),
+ videoRenderEvent(1500, 0),
+ doLoadEvent(2000, 2),
+ doSeekEvent(2000, 1.2, 0),
+ doSeekEvent(2100, 1.2, 1),
+ videoRenderEvent(2100, 2),
+ doSeekEvent(2200, 1.2, 2),
+ seekedEvent(2500, 1.2, 2),
+ seekedEvent(2600, 1.2, 1),
+ seekedEvent(2700, 1.2, 0),
+ bufferEnoughEvent(3000, 0),
+ bufferEnoughEvent(3100, 1),
+ bufferEnoughEvent(3800, 2),
+ mainThreadMarker,
+ compositorThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ // Values are 0.5, 0.3, 0.1, with min 0.1, mean 0.3, max 0.5.
+ checkCloseToMultiple(histograms, 'time_to_video_play', 3, 0.1, 0.3, 0.5);
+ // Values are 0.7, 0.5, 0.3, with min 0.3, mean 0.5, max 0.7.
+ checkCloseToMultiple(histograms,
+ 'pipeline_seek_time_1_2', 3, 0.3, 0.5, 0.7);
+ // Values are 1, 1, 1.6, with min 1, mean 1.2, max 1.6
+ checkCloseToMultiple(histograms, 'seek_time_1_2', 3, 1, 1.2, 1.6);
+ });
+
+ // Scenario: Play mixed audio/video from start to finish
+ test('mediaMetric_playVideoScenario', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(2000),
+ videoRenderEvent(3000),
+ audioRenderEvent(3200),
+ videoRenderEvent(3300),
+ videoFramesDroppedEvent(123456, 4),
+ videoFramesDroppedEvent(234567, 2),
+ onEndedEvent(10013000, 10),
+ mainThreadMarker,
+ compositorThreadMarker,
+ audioThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkCloseTo(histograms, 'time_to_video_play', 1);
+ checkCloseTo(histograms, 'time_to_audio_play', 1.2);
+ checkCloseTo(histograms, 'buffering_time', 10);
+ checkEqual(histograms, 'dropped_frame_count', 6);
+ });
+
+ // Scenario: Play audio from start to finish
+ test('mediaMetric_playAudioScenario', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ audioRenderEvent(1500),
+ onEndedEvent(10002500, 10),
+ mainThreadMarker,
+ audioThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ assert.isUndefined(histograms.getHistogramNamed('time_to_video_play'));
+ checkCloseTo(histograms, 'time_to_audio_play', 0.5);
+ checkCloseTo(histograms, 'buffering_time', 1);
+ assert.isUndefined(histograms.getHistogramNamed('dropped_frame_count'));
+ });
+
+ // Scenario: Play audio/video with two seeks
+ test('mediaMetric_seekScenario', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ doLoadEvent(1000),
+ videoRenderEvent(2000),
+ audioRenderEvent(2020),
+ videoRenderEvent(2040),
+ doSeekEvent(5000, 0.5),
+ seekedEvent(5200, 0.5),
+ bufferEnoughEvent(6000),
+ videoFramesDroppedEvent(123456, 4),
+ doSeekEvent(200000, 9),
+ seekedEvent(210000, 9),
+ bufferEnoughEvent(220000),
+ videoFramesDroppedEvent(234567, 2),
+ onEndedEvent(300000, 10),
+ mainThreadMarker,
+ compositorThreadMarker,
+ audioThreadMarker,
+ ];
+ tr.metrics.mediaMetric(histograms, makeModel(events));
+ checkCloseTo(histograms, 'time_to_video_play', 1);
+ checkCloseTo(histograms, 'time_to_audio_play', 1.02);
+ assert.isUndefined(histograms.getHistogramNamed('buffering_time'));
+ checkEqual(histograms, 'dropped_frame_count', 6);
+ checkCloseTo(histograms, 'pipeline_seek_time_0_5', 0.2);
+ checkCloseTo(histograms, 'seek_time_0_5', 1);
+ checkCloseTo(histograms, 'pipeline_seek_time_9', 10);
+ checkCloseTo(histograms, 'seek_time_9', 20);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html b/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html
new file mode 100644
index 00000000000..1b9ac12e1cc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function.html
@@ -0,0 +1,216 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/all_metrics.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/mre/failure.html">
+<link rel="import" href="/tracing/mre/function_handle.html">
+<link rel="import" href="/tracing/value/diagnostics/reserved_names.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ /**
+ * @param {!tr.model.Model} model
+ * @param {!Object} options
+ * @param {!Array.<string>} options.metrics
+ * @param {!Function} addFailureCb
+ * @return {!tr.v.HistogramSet}
+ */
+ function runMetrics(model, options, addFailureCb) {
+ if (options === undefined) {
+ throw new Error('Options are required.');
+ }
+
+ const metricNames = options.metrics;
+ if (!metricNames) {
+ throw new Error('Metric names should be specified.');
+ }
+
+ const allMetricsStart = new Date();
+ const durationBreakdown = new tr.v.d.Breakdown();
+
+ const categories = getTraceCategories(model);
+
+ const histograms = new tr.v.HistogramSet();
+
+ histograms.createHistogram('trace_import_duration',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ model.stats.traceImportDurationMs, {
+ binBoundaries: tr.v.HistogramBinBoundaries.createExponential(
+ 1e-3, 1e5, 30),
+ description:
+ 'Duration that trace viewer required to import the trace',
+ summaryOptions: tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS,
+ });
+
+ for (const metricName of metricNames) {
+ const metricStart = new Date();
+ const metric = tr.metrics.MetricRegistry.findTypeInfoWithName(metricName);
+ if (metric === undefined) {
+ throw new Error(`"${metricName}" is not a registered metric.`);
+ }
+ validateTraceCategories(metric.metadata.requiredCategories, categories);
+ try {
+ metric.constructor(histograms, model, options);
+ } catch (e) {
+ const err = tr.b.normalizeException(e);
+ addFailureCb(new tr.mre.Failure(
+ undefined, 'metricMapFunction', model.canonicalUrl, err.typeName,
+ err.message, err.stack));
+ }
+ const metricMs = new Date() - metricStart;
+ histograms.createHistogram(
+ metricName + '_duration',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [metricMs]);
+ durationBreakdown.set(metricName, metricMs);
+ }
+
+ validateDiagnosticNames(histograms);
+
+ const allMetricsMs = new Date() - allMetricsStart +
+ model.stats.traceImportDurationMs;
+ durationBreakdown.set('traceImport', model.stats.traceImportDurationMs);
+ durationBreakdown.set('other', allMetricsMs - tr.b.math.Statistics.sum(
+ durationBreakdown, ([metricName, metricMs]) => metricMs));
+ const breakdownNames = tr.v.d.RelatedNameMap.fromEntries(new Map(
+ metricNames.map(metricName => [metricName, metricName + '_duration'])));
+ breakdownNames.set('traceImport', 'trace_import_duration');
+ histograms.createHistogram(
+ 'metrics_duration',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [
+ {
+ value: allMetricsMs,
+ diagnostics: {breakdown: durationBreakdown},
+ },
+ ], {
+ diagnostics: {breakdown: breakdownNames},
+ });
+
+ return histograms;
+ }
+
+ function getTraceCategories(model) {
+ for (const metadata of model.metadata) {
+ let config;
+ if (metadata.name === 'TraceConfig' && metadata.value) {
+ config = metadata.value;
+ }
+ if (metadata.name === 'metadata' && metadata.value &&
+ metadata.value['trace-config'] &&
+ metadata.value['trace-config'] !== '__stripped__') {
+ config = JSON.parse(metadata.value['trace-config']);
+ }
+ if (config) {
+ return {
+ excluded: config.excluded_categories || [],
+ included: config.included_categories || [],
+ };
+ }
+ }
+ }
+
+ function validateTraceCategories(requiredCategories, categories) {
+ if (!requiredCategories) return;
+
+ if (!categories) throw new Error('Missing trace config metadata');
+
+ for (const cat of requiredCategories) {
+ const isDisabledByDefault = (cat.indexOf('disabled-by-default') === 0);
+ let missing = false;
+ if (isDisabledByDefault) {
+ if (!categories.included.includes(cat)) {
+ missing = true;
+ }
+ } else if (categories.excluded.includes(cat)) {
+ missing = true;
+ }
+ if (missing) {
+ throw new Error(`Trace is missing required category "${cat}"`);
+ }
+ }
+ }
+
+ /**
+ * Ensure that metrics don't use reserved diagnostic names.
+ *
+ * @param {!tr.v.HistogramSet} histograms
+ */
+ function validateDiagnosticNames(histograms) {
+ for (const hist of histograms) {
+ for (const name of hist.diagnostics.keys()) {
+ if (tr.v.d.RESERVED_NAMES_SET.has(name)) {
+ throw new Error(
+ `Illegal diagnostic name "${name}" on Histogram "${hist.name}"`);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!tr.model.Model} model
+ */
+ function addTelemetryInfo(histograms, model) {
+ for (const metadata of model.metadata) {
+ if (!metadata.value || !metadata.value.telemetry) continue;
+
+ const traceUrls = metadata.value.telemetry[
+ tr.v.d.RESERVED_NAMES.TRACE_URLS];
+ if (traceUrls && model.canonicalUrl !== traceUrls[0]) {
+ throw new Error(`canonicalUrl "${model.canonicalUrl}" != ` +
+ `traceUrl "${traceUrls[0]}"`);
+ }
+
+ for (const [name, value] of Object.entries(metadata.value.telemetry)) {
+ const type = tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);
+ if (type === undefined) {
+ throw new Error(`Unexpected telemetry.${name}`);
+ }
+ histograms.addSharedDiagnosticToAllHistograms(name, new type(value));
+ }
+ }
+ }
+
+ /**
+ * @param {!tr.mre.MreResult} result
+ * @param {!tr.model.Model} model
+ * @param {!Object} options
+ * @param {!Array.<string>} options.metrics
+ */
+ function metricMapFunction(result, model, options) {
+ const histograms = runMetrics(
+ model, options, result.addFailure.bind(result));
+ addTelemetryInfo(histograms, model);
+
+ result.addPair('histograms', histograms.asDicts());
+
+ const scalarDicts = [];
+ for (const value of histograms) {
+ for (const [statName, scalar] of value.statisticsScalars) {
+ scalarDicts.push({
+ name: value.name + '_' + statName,
+ numeric: scalar.asDict(),
+ description: value.description,
+ });
+ }
+ }
+ result.addPair('scalars', scalarDicts);
+ }
+
+ tr.mre.FunctionRegistry.register(metricMapFunction);
+
+ return {
+ metricMapFunction,
+ runMetrics,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function_test.html
new file mode 100644
index 00000000000..5be41925424
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/metric_map_function_test.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/metric_map_function.html">
+<link rel="import" href="/tracing/metrics/sample_metric.html">
+<link rel="import" href="/tracing/mre/mre_result.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TestUtils = tr.c.TestUtils;
+ const ThreadSlice = tr.model.ThreadSlice;
+
+ test('metricMapTest', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+ const m = TestUtils.newModelWithEvents(JSON.stringify(events), {
+ shiftWorldToZero: false,
+ pruneEmptyContainers: false,
+ trackDetailedModelStats: true,
+ customizeModelCallback(m) {
+ const p1 = m.getOrCreateProcess(1);
+ const t2 = p1.getOrCreateThread(2);
+ t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
+ type: ThreadSlice,
+ name: 'some_slice',
+ start: 0, end: 10
+ }));
+ t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
+ type: ThreadSlice,
+ name: 'some_slice',
+ start: 20, end: 30
+ }));
+ }
+ });
+
+ assert.throw(function() {
+ const result = new tr.mre.MreResult();
+ tr.metrics.metricMapFunction(result, m, {});
+ }, Error, 'Metric names should be specified.');
+
+ assert.throw(function() {
+ const result = new tr.mre.MreResult();
+ tr.metrics.metricMapFunction(result, m, {'metrics': ['wrongMetric']});
+ }, Error, '"wrongMetric" is not a registered metric.');
+
+ const result = new tr.mre.MreResult();
+ tr.metrics.metricMapFunction(
+ result, m, {'metrics': ['sampleMetric']});
+ assert.property(result.pairs, 'histograms');
+ assert.strictEqual(result.pairs.histograms.length, 4);
+ assert.property(result.pairs, 'scalars');
+ assert.strictEqual(result.pairs.scalars.length, 19);
+ assert.lengthOf(result.failures, 0);
+ });
+
+ test('exceptionMetric', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+ const m = TestUtils.newModelWithEvents(JSON.stringify(events), {
+ shiftWorldToZero: false,
+ pruneEmptyContainers: false,
+ trackDetailedModelStats: true,
+ customizeModelCallback(m) {
+ const p1 = m.getOrCreateProcess(1);
+ const t2 = p1.getOrCreateThread(2);
+ t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
+ type: ThreadSlice,
+ name: 'some_slice',
+ start: 0, end: 10
+ }));
+ t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
+ type: ThreadSlice,
+ name: 'some_slice',
+ start: 20, end: 30
+ }));
+ }
+ });
+
+ const result = new tr.mre.MreResult();
+ tr.metrics.metricMapFunction(
+ result, m, {'metrics': ['sampleExceptionMetric']});
+ assert.property(result.pairs, 'histograms');
+ assert.strictEqual(result.pairs.histograms.length, 4);
+ assert.property(result.pairs, 'scalars');
+ assert.strictEqual(result.pairs.scalars.length, 19);
+ assert.lengthOf(result.failures, 1);
+ });
+
+ function invalidDiagnosticNameMetric(histograms, model) {
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [], {diagnostics: {
+ [tr.v.d.RESERVED_NAMES.BOTS]: new tr.v.d.GenericSet([]),
+ }});
+ }
+
+ tr.metrics.MetricRegistry.register(invalidDiagnosticNameMetric);
+
+ test('validateDiagnosticNames', function() {
+ const result = new tr.mre.MreResult();
+ const m = TestUtils.newModel();
+
+ assert.throw(function() {
+ tr.metrics.metricMapFunction(result, m, {
+ 'metrics': ['invalidDiagnosticNameMetric'],
+ });
+ }, Error, 'Illegal diagnostic name ' +
+ `"${tr.v.d.RESERVED_NAMES.BOTS}" on Histogram "a"`);
+ });
+
+ test('validateCanonicalUrl', function() {
+ const result = new tr.mre.MreResult();
+ const m = TestUtils.newModel(model => {
+ model.canonicalUrl = 'canonical url';
+ model.metadata = [{
+ value: {
+ telemetry: {
+ traceUrls: ['trace url'],
+ },
+ },
+ }];
+ });
+ assert.throw(function() {
+ tr.metrics.metricMapFunction(result, m, {metrics: ['sampleMetric']});
+ }, Error, 'canonicalUrl "canonical url" != traceUrl "trace url"');
+ });
+
+ function requiresDefaultCategoryMetric(histograms, model) {
+ }
+
+ tr.metrics.MetricRegistry.register(requiresDefaultCategoryMetric, {
+ requiredCategories: ['foo'],
+ });
+
+ function requiresDisabledCategoryMetric(histograms, model) {
+ }
+
+ tr.metrics.MetricRegistry.register(requiresDisabledCategoryMetric, {
+ requiredCategories: ['disabled-by-default-foo'],
+ });
+
+ test('validateRequiredCategories', function() {
+ const result = new tr.mre.MreResult();
+ let m = TestUtils.newModel(model => {
+ model.metadata = [{
+ name: 'metadata',
+ value: {
+ 'trace-config': JSON.stringify({
+ excluded_categories: ['foo'],
+ }),
+ },
+ }];
+ });
+
+ assert.throw(function() {
+ tr.metrics.metricMapFunction(result, m, {metrics:
+ ['requiresDefaultCategoryMetric']});
+ }, Error, 'Trace is missing required category "foo"');
+
+ m = TestUtils.newModel(model => {
+ model.metadata = [{
+ name: 'TraceConfig',
+ value: {
+ },
+ }];
+ });
+
+ assert.throw(function() {
+ tr.metrics.metricMapFunction(result, m, {metrics:
+ ['requiresDisabledCategoryMetric']});
+ }, Error, 'Trace is missing required category "disabled-by-default-foo"');
+ });
+
+ test('processStrippedConfig', function() {
+ const result = new tr.mre.MreResult();
+ const m = TestUtils.newModel(model => {
+ model.metadata = [{
+ name: 'metadata',
+ value: {
+ 'trace-config': '__stripped__'
+ },
+ }];
+ });
+ tr.metrics.metricMapFunction(
+ result, m, {'metrics': ['sampleMetric']});
+ assert.lengthOf(result.failures, 0);
+ });
+
+ test('metricMetrics', function() {
+ const model = new tr.Model();
+ // We can't customize the model the normal way using
+ // test_utils.newModel(customizeModelCallback) because that callback is run
+ // before the end of the import phase, so our import duration will be
+ // overwritten.
+ model.stats.traceImportDurationMs = 10;
+
+ const histograms = tr.metrics.runMetrics(
+ model, {'metrics': ['sampleMetric']});
+
+ assert.strictEqual(
+ histograms.getHistogramNamed('trace_import_duration').average, 10);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/metric_registry.html b/chromium/third_party/catapult/tracing/tracing/metrics/metric_registry.html
new file mode 100644
index 00000000000..05ea36dd12f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/metric_registry.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/extension_registry.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ function MetricRegistry() {}
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ options.defaultMetadata = {};
+ tr.b.decorateExtensionRegistry(MetricRegistry, options);
+
+ function camelCaseToHackerString(camelCase) {
+ let hackerString = '';
+ for (const c of camelCase) {
+ const lowered = c.toLocaleLowerCase();
+ if (lowered === c) {
+ hackerString += c;
+ } else {
+ hackerString += '_' + lowered;
+ }
+ }
+ return hackerString;
+ }
+
+ function getCallStack() {
+ try {
+ throw new Error();
+ } catch (error) {
+ return error.stack;
+ }
+ }
+
+ function getPathsFromStack(stack) {
+ return stack.split('\n').map(line => {
+ line = line.replace(/^ */, '').split(':');
+ if (line.length < 4) return '';
+ return line[line.length - 3].split('/');
+ }).filter(x => x);
+ }
+
+ MetricRegistry.checkFilename = function(metricName, opt_metricPathForTest) {
+ if (metricName === 'runtimeStatsTotalMetric' ||
+ metricName === 'v8AndMemoryMetrics') {
+ // TODO(crbug.com/688342) Remove the runtimeStatsTotalMetric exception.
+ // TODO(3275) Remove the v8AndMemoryMetrics exception.
+ // https://github.com/catapult-project/catapult/issues/3275
+ return;
+ }
+
+ const expectedFilename = camelCaseToHackerString(metricName) + '.html';
+ const stack = getCallStack();
+
+ let metricPath = opt_metricPathForTest;
+ if (metricPath === undefined) {
+ const paths = getPathsFromStack(stack);
+ const METRIC_STACK_INDEX = 5;
+
+ // This filename is in paths[0]. If this file is not vulcanized, then the
+ // metric's filename is in paths[METRIC_STACK_INDEX]. If this file is
+ // vulcanized, then they are the same, and paths[METRIC_STACK_INDEX] is
+ // not the metric's filename.
+ if (paths.length <= METRIC_STACK_INDEX ||
+ paths[METRIC_STACK_INDEX].join('/') === paths[0].join('/')) {
+ return;
+ }
+
+ metricPath = paths[METRIC_STACK_INDEX].slice(
+ paths[METRIC_STACK_INDEX].length - 2);
+ }
+
+ if (!metricPath[1].endsWith('_test.html') &&
+ !metricPath[1].endsWith('_test.html.js') &&
+ metricPath[1] !== expectedFilename &&
+ metricPath[1] !== expectedFilename + '.js' &&
+ metricPath.join('_') !== expectedFilename &&
+ metricPath.join('_') !== expectedFilename + '.js') {
+ throw new Error(
+ 'Expected ' + metricName + ' to be in a file named ' +
+ expectedFilename + '; actual: ' + metricPath.join('/') +
+ '; stack: ' + stack.replace(/\n/g, '\n '));
+ }
+ };
+
+ MetricRegistry.addEventListener('will-register', function(e) {
+ const metric = e.typeInfo.constructor;
+ if (!(metric instanceof Function)) {
+ throw new Error('Metrics must be functions.');
+ }
+
+ if (!metric.name.endsWith('Metric') &&
+ !metric.name.endsWith('Metrics')) {
+ throw new Error('Metric names must end with "Metric" or "Metrics".');
+ }
+
+ if (metric.length < 2) {
+ throw new Error('Metrics take a HistogramSet and a Model and ' +
+ 'optionally an options dictionary.');
+ }
+
+ MetricRegistry.checkFilename(metric.name);
+ });
+
+ return {
+ MetricRegistry,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/metric_registry_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/metric_registry_test.html
new file mode 100644
index 00000000000..c4123024ae6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/metric_registry_test.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('FindMetricByName', function() {
+ function aMetric(histograms, model) {
+ const n1 = new tr.v.Histogram('foo', tr.b.Unit.byName.count);
+ n1.addSample(1);
+ histograms.addHistogram(n1);
+ }
+ tr.metrics.MetricRegistry.register(aMetric);
+
+ function bMetric(histograms, model) {
+ const n1 = new tr.v.Histogram('foo', tr.b.Unit.byName.count);
+ const n2 = new tr.v.Histogram('bar', tr.b.Unit.byName.count);
+ n1.addSample(1);
+ n2.addSample(2);
+ histograms.addHistogram(n1);
+ histograms.addHistogram(n2);
+ }
+ tr.metrics.MetricRegistry.register(bMetric);
+
+ function cMetric(histograms, model) {
+ const n1 = new tr.v.Histogram('foo', tr.b.Unit.byName.count);
+ const n2 = new tr.v.Histogram('bar', tr.b.Unit.byName.count);
+ const n3 = new tr.v.Histogram('baz', tr.b.Unit.byName.count);
+ n1.addSample(1);
+ n2.addSample(2);
+ n3.addSample(3);
+ histograms.addHistogram(n1);
+ histograms.addHistogram(n2);
+ histograms.addHistogram(n3);
+ }
+ tr.metrics.MetricRegistry.register(cMetric);
+
+ const typeInfo = tr.metrics.MetricRegistry.findTypeInfoWithName(
+ 'bMetric');
+ assert.strictEqual(typeInfo.constructor, bMetric);
+ });
+
+ test('registerNonFunctionThrows', function() {
+ // Metrics must be functions.
+ assert.throws(function() {
+ tr.metrics.MetricRegistry.register('not a function');
+ });
+
+ // Metric names must end with "Metric" or "Metrics".
+ assert.throws(function() {
+ tr.metrics.MetricRegistry.register(function foo(histograms, model) {});
+ });
+
+ // Metrics take a HistogramSet and a Model and optionally an options
+ // dictionary.
+ assert.throws(function() {
+ tr.metrics.MetricRegistry.register(function fooMetric() {});
+ });
+
+ // Metrics take a HistogramSet and a Model and optionally an options
+ // dictionary.
+ assert.throws(function() {
+ tr.metrics.MetricRegistry.register(function fooMetric(a) {});
+ });
+ });
+
+ test('checkFilename', function() {
+ tr.metrics.MetricRegistry.checkFilename(
+ 'aMetric', ['metrics', 'a_metric.html']);
+ tr.metrics.MetricRegistry.checkFilename(
+ 'fooBarMetric', ['foo', 'bar_metric.html']);
+
+ // Expected fooMetric to be in a file named foo_metric.html; actual:
+ // foo/bar_metric.html
+ assert.throws(() => tr.metrics.MetricRegistry.checkFilename(
+ 'fooMetric', ['foo', 'bar_metric.html']));
+
+ // Expected fooMetric to be in a file named foo_metric.html; actual:
+ // cat/bar_metric.html
+ assert.throws(() => tr.metrics.MetricRegistry.checkFilename(
+ 'fooMetric', ['cat', 'bar_metric.html']));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/metric_runner.py b/chromium/third_party/catapult/tracing/tracing/metrics/metric_runner.py
new file mode 100644
index 00000000000..b8cc2af8dde
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/metric_runner.py
@@ -0,0 +1,75 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+from tracing.mre import function_handle
+from tracing.mre import gtest_progress_reporter
+from tracing.mre import map_runner
+from tracing.mre import file_handle
+from tracing.mre import job as job_module
+
+
+try:
+ StringTypes = basestring
+except NameError:
+ StringTypes = str
+
+
+_METRIC_MAP_FUNCTION_FILENAME = 'metric_map_function.html'
+
+_METRIC_MAP_FUNCTION_NAME = 'metricMapFunction'
+
+def _GetMetricsDir():
+ return os.path.dirname(os.path.abspath(__file__))
+
+def _GetMetricRunnerHandle(metrics):
+ assert isinstance(metrics, list)
+ for metric in metrics:
+ assert isinstance(metric, StringTypes)
+ metrics_dir = _GetMetricsDir()
+ metric_mapper_path = os.path.join(metrics_dir, _METRIC_MAP_FUNCTION_FILENAME)
+
+ modules_to_load = [function_handle.ModuleToLoad(filename=metric_mapper_path)]
+ options = {'metrics': metrics}
+ map_function_handle = function_handle.FunctionHandle(
+ modules_to_load, _METRIC_MAP_FUNCTION_NAME, options)
+
+ return job_module.Job(map_function_handle, None)
+
+def RunMetric(filename, metrics, extra_import_options=None,
+ report_progress=True, canonical_url=None):
+ filename_url = 'file://' + filename
+ if canonical_url is None:
+ canonical_url = filename_url
+ trace_handle = file_handle.URLFileHandle(canonical_url, filename_url)
+ result = RunMetricOnTraceHandles(
+ [trace_handle], metrics, extra_import_options, report_progress)
+ return result[canonical_url]
+
+def RunMetricOnTraceHandles(trace_handles, metrics, extra_import_options=None,
+ report_progress=True):
+ job = _GetMetricRunnerHandle(metrics)
+ with open(os.devnull, 'w') as devnull_f:
+ o_stream = sys.stdout
+ if not report_progress:
+ o_stream = devnull_f
+
+ runner = map_runner.MapRunner(
+ trace_handles, job, extra_import_options=extra_import_options,
+ progress_reporter=gtest_progress_reporter.GTestProgressReporter(
+ output_stream=o_stream))
+ map_results = runner.RunMapper()
+
+ return map_results
+
+def RunMetricOnTraces(filenames, metrics,
+ extra_import_options=None, report_progress=True):
+ trace_handles = []
+ for filename in filenames:
+ filename_url = 'file://' + filename
+ trace_handles.append(file_handle.URLFileHandle(filename_url, filename_url))
+
+ return RunMetricOnTraceHandles(trace_handles, metrics, extra_import_options,
+ report_progress)
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html
new file mode 100644
index 00000000000..e1ea92fd04a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization.html
@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/value/diagnostics/breakdown.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains implementations of the following metrics.
+ *
+ * The addCpuUtilizationHistograms method can generate the following sets of
+ * metrics, dependeing on the input values for segments, shouldNormalize, and
+ * segmentCostFunc.
+ *
+ * thread_{thread group}_cpu_time_per_second
+ * =========================================
+ * segments: any set of interesting segments
+ * shouldNormalize: True
+ * segmentCostFunc: thread.getCpuTimeForRange
+ *
+ * This set of metrics show how much a thread group was busy during specific
+ * segments marked by a test. More precisely, it shows the average amount of CPU
+ * cores per seconds the thread group consumes during the segments.
+ *
+ * thread_{thread group}_cpu_time_per_frame
+ * ========================================
+ * segments: display compositor's frames
+ * shouldNormalize: False
+ * segmentCostFunc: thread.getCpuTimeForRange
+ *
+ * This set of metrics show the distribution of CPU usage of a thread
+ * group in each display compositor's frame.
+ *
+ * tasks_per_second_{thread group}
+ * ===============================
+ * segments: any set of interesting segments
+ * shouldNormalize: True
+ * segmentCostFunc: thread.getNumToplevelSlicesForRange
+ *
+ * This set of metrics show the average number of tasks per second of a thread
+ * group during specific segments marked by a test.
+ *
+ * tasks_per_frame_{thread group}
+ * ==============================
+ * segments: display compositor's frames
+ * shouldNormalize: False
+ * segmentCostFunc: thread.getNumToplevelSlicesForRange
+ *
+ * This set of metrics show the distribution of the number of task in each
+ * display compositor's frame of a thread group.
+ *
+ * Note: the CPU usage in all above-mentioned metrics, is approximated from
+ * top-level trace events in each thread; it does not come from the OS. So, the
+ * metric may be noisy and not be very meaningful for threads that do not have a
+ * message loop.
+ */
+tr.exportTo('tr.metrics.rendering', function() {
+ const UNKNOWN_THREAD_NAME = 'Unknown';
+
+ const CATEGORY_THREAD_MAP = new Map();
+ CATEGORY_THREAD_MAP.set('total_all', [/.*/]);
+ CATEGORY_THREAD_MAP.set(
+ 'browser', [/^Browser Compositor$/, /^CrBrowserMain$/]);
+ CATEGORY_THREAD_MAP.set('display_compositor', [/^VizCompositorThread$/]);
+ CATEGORY_THREAD_MAP.set(
+ 'total_fast_path', [
+ /^Browser Compositor$/, /^Chrome_InProcGpuThread$/, /^Compositor$/,
+ /^CrBrowserMain$/, /^CrGpuMain$/, /IOThread/, /^VizCompositorThread$/]);
+ CATEGORY_THREAD_MAP.set('GPU', [/^Chrome_InProcGpuThread$/, /^CrGpuMain$/]);
+ CATEGORY_THREAD_MAP.set('IO', [/IOThread/]);
+ CATEGORY_THREAD_MAP.set('raster', [/CompositorTileWorker/]);
+ CATEGORY_THREAD_MAP.set('renderer_compositor', [/^Compositor$/]);
+ CATEGORY_THREAD_MAP.set('renderer_main', [/^CrRendererMain$/]);
+
+ const ALL_CATEGORIES = [...CATEGORY_THREAD_MAP.keys(), 'other'];
+
+ function addValueToMap_(map, key, value) {
+ const oldValue = map.get(key) || 0;
+ map.set(key, oldValue + value);
+ }
+
+ function* getCategories_(threadName) {
+ let isOther = true;
+ for (const [category, regexps] of CATEGORY_THREAD_MAP) {
+ for (const regexp of regexps) {
+ if (regexp.test(threadName)) {
+ if (category !== 'total_all') isOther = false;
+ yield category;
+ break;
+ }
+ }
+ }
+ if (isOther) yield 'other';
+ }
+
+ function isSubset_(regexps1, regexps2) {
+ for (const r1 of regexps1) {
+ if (regexps2.find(r2 => r2.toString() === r1.toString()) === undefined) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function addCpuUtilizationHistograms(
+ histograms, model, segments, shouldNormalize, segmentCostFunc,
+ histogramNameFunc, description, unit) {
+ if (!unit) unit = tr.b.Unit.byName.unitlessNumber;
+ const histogramMap = new Map();
+ for (const category of ALL_CATEGORIES) {
+ const histogram = histograms.createHistogram(
+ histogramNameFunc(category), unit, [], {
+ binBoundaries:
+ tr.v.HistogramBinBoundaries.createExponential(1, 50, 20),
+ description,
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ histogramMap.set(category, histogram);
+ }
+
+ // Add histogram breakdowns.
+ for (const [category, regexps] of CATEGORY_THREAD_MAP) {
+ const relatedCategories = new tr.v.d.RelatedNameMap();
+ const histogram = histogramMap.get(category);
+ for (const [otherCategory, otherRegexps] of CATEGORY_THREAD_MAP) {
+ if (otherCategory === category) continue;
+ if (category !== 'all' && !isSubset_(otherRegexps, regexps)) continue;
+ const otherHistogram = histogramMap.get(otherCategory);
+ relatedCategories.set(otherCategory, otherHistogram.name);
+ }
+ if ([...relatedCategories.values()].length > 0) {
+ histogram.diagnostics.set('breakdown', relatedCategories);
+ }
+ }
+
+ for (const segment of segments) {
+ const threadValues = new Map();
+ // Compute and store CPU times per categories and thread name.
+ for (const thread of model.getAllThreads()) {
+ addValueToMap_(
+ threadValues,
+ thread.name || UNKNOWN_THREAD_NAME,
+ segmentCostFunc(thread, segment));
+ }
+ const categoryValues = new Map();
+ const breakdowns = new Map();
+ for (const [threadName, coresPerSec] of threadValues) {
+ for (const category of getCategories_(threadName)) {
+ addValueToMap_(categoryValues, category, coresPerSec);
+ if (!breakdowns.has(category)) {
+ breakdowns.set(category, new tr.v.d.Breakdown());
+ }
+ // TODO(chiniforooshan): We break down the CPU usage of each category
+ // by the thread name here. It will be more useful if we could add
+ // task names too. On the other hand, breaking down at task level may
+ // be too granular and we may end up with a ton of tiny slices that
+ // will not be that useful. Maybe we can break down by just top x
+ // tasks, or top x (thread, task) pairs?
+ //
+ // Another possbility to investigate is to break down by initiator
+ // type of the animation expectation.
+ breakdowns.get(category).set(threadName, coresPerSec);
+ }
+ }
+
+ for (const category of ALL_CATEGORIES) {
+ let value = categoryValues.get(category) || 0;
+ if (shouldNormalize) value /= segment.duration;
+ const diagnostics = new tr.v.d.DiagnosticMap();
+ const breakdown = breakdowns.get(category);
+ if (breakdown) diagnostics.set('breakdown', breakdown);
+ const histogram = histogramMap.get(category);
+ histogram.addSample(value, diagnostics);
+ }
+ }
+ }
+
+ const SUMMARY_OPTIONS = {
+ percentile: [0.90, 0.95],
+ };
+
+ return {
+ addCpuUtilizationHistograms,
+ SUMMARY_OPTIONS,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html
new file mode 100644
index 00000000000..3f58d2868f0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/cpu_utilization_test.html
@@ -0,0 +1,280 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/rendering/cpu_utilization.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('cpuPerSecond', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ // A slice during the animation with CPU duration 2.
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 1, end: 4, cpuStart: 0, cpuEnd: 2 }));
+ // A slice after the animation.
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 10, end: 12, cpuStart: 2, cpuEnd: 3 }));
+
+
+ const rendererMain = model.getOrCreateProcess(1).getOrCreateThread(0);
+ rendererMain.name = 'CrRendererMain';
+ // A slice half of which intersects with the animation.
+ rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 15, cpuStart: 0, cpuEnd: 8 }));
+
+ const rendererIO = model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererIO.name = 'Chrome_ChildIOThread';
+ rendererIO.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addCpuUtilizationHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 10)], true,
+ (thread, segment) => thread.getCpuTimeForRange(segment.boundsRange),
+ category => `thread_${category}_cpu_time_per_second`, 'description');
+
+ // Verify the browser and renderer main threads and IO threads CPU usage.
+ let hist = histograms.getHistogramNamed(
+ 'thread_browser_cpu_time_per_second');
+ assert.closeTo(0.2, hist.min, 1e-6);
+ assert.closeTo(0.2, hist.max, 1e-6);
+ assert.closeTo(0.2, hist.average, 1e-6);
+
+ hist = histograms.getHistogramNamed(
+ 'thread_renderer_main_cpu_time_per_second');
+ assert.closeTo(0.4, hist.min, 1e-6);
+ assert.closeTo(0.4, hist.max, 1e-6);
+ assert.closeTo(0.4, hist.average, 1e-6);
+
+ hist = histograms.getHistogramNamed('thread_IO_cpu_time_per_second');
+ assert.closeTo(0.1, hist.min, 1e-6);
+ assert.closeTo(0.1, hist.max, 1e-6);
+ assert.closeTo(0.1, hist.average, 1e-6);
+
+ // Also, verify fast_path threads, that includs IO threads and the browser
+ // main thread, but not the renderer main thread.
+ hist = histograms.getHistogramNamed(
+ 'thread_total_fast_path_cpu_time_per_second');
+ assert.closeTo(0.3, hist.min, 1e-6);
+ assert.closeTo(0.3, hist.max, 1e-6);
+ assert.closeTo(0.3, hist.average, 1e-6);
+
+ // Verify sum of all threads.
+ hist = histograms.getHistogramNamed('thread_total_all_cpu_time_per_second');
+ assert.closeTo(0.7, hist.min, 1e-6);
+ assert.closeTo(0.7, hist.max, 1e-6);
+ assert.closeTo(0.7, hist.average, 1e-6);
+ });
+
+ test('cpuPerFrame', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ // A slice during the animation with CPU duration 2.
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 1, end: 4, cpuStart: 0, cpuEnd: 2 }));
+ // A slice after the animation.
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 10, end: 12, cpuStart: 2, cpuEnd: 3 }));
+
+
+ const rendererMain = model.getOrCreateProcess(1).getOrCreateThread(0);
+ rendererMain.name = 'CrRendererMain';
+ // A slice half of which intersects with the animation.
+ rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 15, cpuStart: 0, cpuEnd: 8 }));
+
+ const rendererIO = model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererIO.name = 'Chrome_ChildIOThread';
+ rendererIO.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addCpuUtilizationHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 10)], false,
+ (thread, segment) => thread.getCpuTimeForRange(segment.boundsRange),
+ category => `thread_${category}_cpu_time_per_frame`, 'description');
+
+ // Verify the browser and renderer main threads and IO threads CPU usage.
+ let hist = histograms.getHistogramNamed(
+ 'thread_browser_cpu_time_per_frame');
+ assert.closeTo(2, hist.min, 1e-6);
+ assert.closeTo(2, hist.max, 1e-6);
+ assert.closeTo(2, hist.average, 1e-6);
+
+ hist = histograms.getHistogramNamed(
+ 'thread_renderer_main_cpu_time_per_frame');
+ assert.closeTo(4, hist.min, 1e-6);
+ assert.closeTo(4, hist.max, 1e-6);
+ assert.closeTo(4, hist.average, 1e-6);
+
+ hist = histograms.getHistogramNamed('thread_IO_cpu_time_per_frame');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(1, hist.max, 1e-6);
+ assert.closeTo(1, hist.average, 1e-6);
+
+ // Also, verify fast_path threads, that includs IO threads and the browser
+ // main thread, but not the renderer main thread.
+ hist = histograms.getHistogramNamed(
+ 'thread_total_fast_path_cpu_time_per_frame');
+ assert.closeTo(3, hist.min, 1e-6);
+ assert.closeTo(3, hist.max, 1e-6);
+ assert.closeTo(3, hist.average, 1e-6);
+
+ // Verify sum of all threads.
+ hist = histograms.getHistogramNamed('thread_total_all_cpu_time_per_frame');
+ assert.closeTo(7, hist.min, 1e-6);
+ assert.closeTo(7, hist.max, 1e-6);
+ assert.closeTo(7, hist.average, 1e-6);
+ });
+
+ test('multipleSegments', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 1, end: 4, cpuStart: 0, cpuEnd: 2 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 8, end: 12, cpuStart: 2, cpuEnd: 4 }));
+
+
+ const rendererMain = model.getOrCreateProcess(1).getOrCreateThread(0);
+ rendererMain.name = 'CrRendererMain';
+ rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 15, cpuStart: 0, cpuEnd: 8 }));
+
+ const rendererIO = model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererIO.name = 'Chrome_ChildIOThread';
+ rendererIO.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addCpuUtilizationHistograms(
+ histograms, model,
+ [new tr.model.um.Segment(0, 5), new tr.model.um.Segment(5, 5)], false,
+ (thread, segment) => thread.getCpuTimeForRange(segment.boundsRange),
+ category => `thread_${category}_cpu_time_per_frame`, 'description');
+
+ // The first slice is in the first segment, using 2ms of CPU. The rest are
+ // in the second segment, using 1 + 4 + 1 = 6ms of CPU.
+ const hist = histograms.getHistogramNamed(
+ 'thread_total_all_cpu_time_per_frame');
+ assert.closeTo(2, hist.min, 1e-6);
+ assert.closeTo(6, hist.max, 1e-6);
+ assert.closeTo(4, hist.average, 1e-6);
+ });
+
+ test('otherThreads', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ // A slice during the animation with CPU duration 2.
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 1, end: 4, cpuStart: 0, cpuEnd: 2 }));
+ // A slice after the animation.
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 10, end: 12, cpuStart: 2, cpuEnd: 3 }));
+
+
+ const thread1 = model.getOrCreateProcess(1).getOrCreateThread(0);
+ thread1.name = 'Thread1';
+ // A slice half of which intersects with the animation.
+ thread1.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 15, cpuStart: 0, cpuEnd: 8 }));
+
+ const thread2 = model.getOrCreateProcess(1).getOrCreateThread(1);
+ thread2.name = 'Thread2';
+ thread2.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addCpuUtilizationHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 10)], false,
+ (thread, segment) => thread.getCpuTimeForRange(segment.boundsRange),
+ category => `thread_${category}_cpu_time_per_frame`, 'description');
+
+ // Verify the browser and renderer main threads and IO threads CPU usage.
+ let hist = histograms.getHistogramNamed(
+ 'thread_browser_cpu_time_per_frame');
+ assert.closeTo(2, hist.min, 1e-6);
+ assert.closeTo(2, hist.max, 1e-6);
+ assert.closeTo(2, hist.average, 1e-6);
+
+ hist = histograms.getHistogramNamed('thread_other_cpu_time_per_frame');
+ assert.closeTo(5, hist.min, 1e-6);
+ assert.closeTo(5, hist.max, 1e-6);
+ assert.closeTo(5, hist.average, 1e-6);
+ });
+
+ test('tasksPerFrame', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ // A slice during the animation with CPU duration 2.
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 1, end: 4, cpuStart: 0, cpuEnd: 2 }));
+ // A slice after the animation.
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 10, end: 12, cpuStart: 2, cpuEnd: 3 }));
+
+
+ const rendererMain = model.getOrCreateProcess(1).getOrCreateThread(0);
+ rendererMain.name = 'CrRendererMain';
+ // A slice half of which intersects with the animation.
+ rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 15, cpuStart: 0, cpuEnd: 8 }));
+
+ const rendererIO = model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererIO.name = 'Chrome_ChildIOThread';
+ rendererIO.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { start: 5, end: 6, cpuStart: 1, cpuEnd: 2 }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addCpuUtilizationHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 10)], false,
+ (thread, segment) =>
+ thread.getNumToplevelSlicesForRange(segment.boundsRange),
+ category => `tasks_per_frame_${category}`, 'description');
+
+ // Verify the browser and renderer main threads and IO threads number of
+ // tasks.
+ let hist = histograms.getHistogramNamed('tasks_per_frame_browser');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(1, hist.max, 1e-6);
+ assert.closeTo(1, hist.average, 1e-6);
+
+ hist = histograms.getHistogramNamed('tasks_per_frame_renderer_main');
+ assert.closeTo(0.5, hist.min, 1e-6);
+ assert.closeTo(0.5, hist.max, 1e-6);
+ assert.closeTo(0.5, hist.average, 1e-6);
+
+ hist = histograms.getHistogramNamed('tasks_per_frame_IO');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(1, hist.max, 1e-6);
+ assert.closeTo(1, hist.average, 1e-6);
+
+ // Also, verify fast_path threads, that includs IO threads and the browser
+ // main thread, but not the renderer main thread.
+ hist = histograms.getHistogramNamed('tasks_per_frame_total_fast_path');
+ assert.closeTo(2, hist.min, 1e-6);
+ assert.closeTo(2, hist.max, 1e-6);
+ assert.closeTo(2, hist.average, 1e-6);
+
+ // Verify sum of all threads.
+ hist = histograms.getHistogramNamed('tasks_per_frame_total_all');
+ assert.closeTo(2.5, hist.min, 1e-6);
+ assert.closeTo(2.5, hist.max, 1e-6);
+ assert.closeTo(2.5, hist.average, 1e-6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_time.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_time.html
new file mode 100644
index 00000000000..1c465423654
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_time.html
@@ -0,0 +1,272 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/metrics/rendering/cpu_utilization.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains implementations of the following metrics.
+ *
+ * frame_times
+ * ===========
+ * The distribution of durations between consecutive display compositor's swap
+ * buffer calls, or DRM page flips on ChromeOS devices, during animations.
+ *
+ * percentage_smooth
+ * =================
+ * The percentage of frame_times that are less than 17ms.
+ *
+ * TODO(chiniforooshan): This metric weighs all frames equally. So, e.g.
+ * percentage_smooth is lower (worse) if we have 10 100ms-frames instead of 5
+ * 1s-frames. I think it makes more sense to compute the percentage of
+ * non-smooth time during animation.
+ *
+ * frame_lengths (Android only)
+ * ============================
+ * frame_times in vsyncs instead of milli-seconds. In other words, frame_lengths
+ * is the distribution of durations between consecutive display compositor's
+ * swap buffer calls, in terms of vsyncs. Short frames (ones shorter than half
+ * of the refresh period) are filtered out, unlike in frame_times.
+ *
+ * avg_surface_fps (Android only)
+ * ==============================
+ * Average number of frames, ignoring short frames, per second during
+ * animations.
+ *
+ * jank_count (Android only)
+ * =========================
+ * The number of times that frame lengths are increased, during animations. For
+ * example, if frame lengths are 1, 1, 1, 2, 3, 1, 1 vsyncs, then jank_count
+ * will be 2 (1 -> 2 and 2 -> 3).
+ *
+ * ui_frame_times
+ * ==============
+ * The distribution of durations between consecutive UI compositor frame's
+ * presentation times, during UI animations. In ChromeOS, if Ash uses its own
+ * instance of ui::compositor, then frames submitted by that compositor will be
+ * used. Otherwise, frames submitted by the browser's ui::compositor will be
+ * used.
+ *
+ * TODO(crbug.com/896231): we may want to consider reporting frame_times for all
+ * ui::compositors separately, e.g. as ash_frame_times and browser_frame_times.
+ *
+ * ui_percentage_smooth
+ * ====================
+ * The percentage of ui_frame_times that are less than 17ms.
+ */
+tr.exportTo('tr.metrics.rendering', function() {
+ // Various tracing events.
+ const DISPLAY_EVENT = 'BenchmarkInstrumentation::DisplayRenderingStats';
+ const DRM_EVENT = 'DrmEventFlipComplete';
+ const SURFACE_FLINGER_EVENT = 'vsync_before';
+ const COMPOSITOR_FRAME_PRESENTED_EVENT = 'FramePresented';
+
+ // In computing frame_lengths, avg_surface_fps, and jank_count, frames that
+ // are shorter than half a vsync are ignored.
+ const MIN_FRAME_LENGTH = 0.5;
+
+ // In computing the number of janks, frame length differences that are at
+ // least PAUSE_THRESHOLD vsyncs are considered pauses, not janks.
+ const PAUSE_THRESHOLD = 20;
+
+ const ASH_ENVIRONMENT = 'ash';
+ const BROWSER_ENVIRONMENT = 'browser';
+
+ function getDisplayCompositorPresentationEvents_(modelHelper) {
+ if (!modelHelper || !modelHelper.browserProcess) return [];
+ // On ChromeOS, DRM events, if they exist, are the source of truth. On
+ // Android, Surface Flinger events are the source of truth. Otherwise, look
+ // for display rendering stats. With viz, display rendering stats are
+ // emitted from the GPU process; otherwise, they are emitted from the
+ // browser process.
+ let events = [];
+ if (modelHelper.surfaceFlingerProcess) {
+ events = [...modelHelper.surfaceFlingerProcess.findTopmostSlicesNamed(
+ SURFACE_FLINGER_EVENT)];
+ if (events.length > 0) return events;
+ }
+ if (modelHelper.gpuHelper) {
+ const gpuProcess = modelHelper.gpuHelper.process;
+ events = [...gpuProcess.findTopmostSlicesNamed(DRM_EVENT)];
+ if (events.length > 0) return events;
+ events = [...gpuProcess.findTopmostSlicesNamed(DISPLAY_EVENT)];
+ if (events.length > 0) return events;
+ }
+ return [...modelHelper.browserProcess.findTopmostSlicesNamed(
+ DISPLAY_EVENT)];
+ }
+
+ function getUIPresentationEvents_(modelHelper) {
+ if (!modelHelper || !modelHelper.browserProcess) return [];
+
+ const legacyEvents = [];
+ const eventsByEnvironment = {};
+ eventsByEnvironment[ASH_ENVIRONMENT] = [];
+ eventsByEnvironment[BROWSER_ENVIRONMENT] = [];
+ for (const event of modelHelper.browserProcess.findTopmostSlicesNamed(
+ COMPOSITOR_FRAME_PRESENTED_EVENT)) {
+ if (!('environment' in event.args)) {
+ // For chrome versions before crrev.com/c/1282039.
+ legacyEvents.push(event);
+ } else {
+ eventsByEnvironment[event.args.environment].push(event);
+ }
+ }
+
+ if (eventsByEnvironment[ASH_ENVIRONMENT].length > 0) {
+ return eventsByEnvironment[ASH_ENVIRONMENT];
+ }
+ if (eventsByEnvironment[BROWSER_ENVIRONMENT].length > 0) {
+ return eventsByEnvironment[BROWSER_ENVIRONMENT];
+ }
+ return legacyEvents;
+ }
+
+ function addSurfaceFlingerHistograms_(
+ histograms, frameSegments, refreshPeriod) {
+ let frameLengths = frameSegments.map(x => x.duration / refreshPeriod);
+ frameLengths = frameLengths.filter(length => length >= MIN_FRAME_LENGTH);
+ histograms.createHistogram(
+ 'frame_lengths',
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter,
+ frameLengths,
+ { binBoundaries: tr.v.HistogramBinBoundaries.createLinear(0, 5, 20),
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ description: 'Frame times in vsyncs.' });
+
+ histograms.createHistogram(
+ 'avg_surface_fps',
+ tr.b.Unit.byName.unitlessNumber_biggerIsBetter,
+ frameLengths.length / tr.b.convertUnit(
+ tr.b.math.Statistics.sum(frameSegments, x => x.duration),
+ tr.b.UnitScale.TIME.MILLI_SEC, tr.b.UnitScale.TIME.SEC),
+ { description: 'Average frames per second.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+
+ let jankCount = 0;
+ for (let i = 1; i < frameLengths.length; i++) {
+ const change = Math.round(frameLengths[i] - frameLengths[i - 1]);
+ if (change > 0 && change < PAUSE_THRESHOLD) jankCount++;
+ }
+ histograms.createHistogram(
+ 'jank_count',
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter,
+ jankCount,
+ { description: 'Number of changes in frame rate.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ }
+
+ function computeFrameSegments_(timestamps, segments) {
+ // We use filterArray for the sake of a cleaner code. The time complexity
+ // will be O(m + n log m), where m is |timestamps| and n is |segments|.
+ // Alternatively, we could directly loop through the timestamps and segments
+ // here for a slightly better time complexity of O(m + n).
+ const frameSegments = [];
+ for (const segment of segments) {
+ const filtered = segment.boundsRange.filterArray(timestamps, x => x[0]);
+ for (let i = 1; i < filtered.length; i++) {
+ const duration = filtered[i][1] - filtered[i - 1][1];
+ frameSegments.push(
+ new tr.model.um.Segment(filtered[i - 1][0], duration));
+ }
+ }
+ return frameSegments;
+ }
+
+ function addBasicFrameTimeHistograms_(histograms, frameSegments, prefix) {
+ // TODO(chiniforooshan): Figure out what kind of break down makes sense
+ // here. Perhaps break down by tasks in the Viz/Browser process?
+ const frameTimes = frameSegments.map(x => x.duration);
+ histograms.createHistogram(
+ `${prefix}frame_times`,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ frameTimes,
+ { binBoundaries: tr.v.HistogramBinBoundaries.createLinear(0, 50, 20),
+ description: 'Raw frame times.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ histograms.createHistogram(
+ `${prefix}percentage_smooth`,
+ tr.b.Unit.byName.unitlessNumber_biggerIsBetter,
+ 100 * tr.b.math.Statistics.sum(frameTimes, (x => (x < 17 ? 1 : 0))) /
+ frameTimes.length,
+ { description: 'Percentage of frames that were hitting 60 FPS.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ }
+
+ function addFrameTimeHistograms(histograms, model, segments) {
+ const events = getDisplayCompositorPresentationEvents_(
+ model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper));
+ if (!events) return;
+
+ // Presentation Timestamps should be sorted.
+ const timestamps = events.map(
+ event => [event.start,
+ event.title !== DRM_EVENT ? event.start : (
+ tr.b.convertUnit(
+ event.args.data['vblank.tv_sec'],
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC) +
+ tr.b.convertUnit(
+ event.args.data['vblank.tv_usec'],
+ tr.b.UnitScale.TIME.MICRO_SEC, tr.b.UnitScale.TIME.MILLI_SEC))]
+ );
+ const frameSegments = computeFrameSegments_(timestamps, segments);
+ addBasicFrameTimeHistograms_(histograms, frameSegments, '');
+ tr.metrics.rendering.addCpuUtilizationHistograms(
+ histograms, model, frameSegments, false,
+ (thread, segment) => thread.getCpuTimeForRange(segment.boundsRange),
+ category => `thread_${category}_cpu_time_per_frame`,
+ 'CPU cores of a thread group per frame',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ tr.metrics.rendering.addCpuUtilizationHistograms(
+ histograms, model, frameSegments, false,
+ (thread, segment) =>
+ thread.getNumToplevelSlicesForRange(segment.boundsRange),
+ category => `tasks_per_frame_${category}`,
+ 'Number of tasks of a thread group per frame',
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter);
+
+ // If Surface Flinger information is captured, add Surface Flinger
+ // histograms.
+ for (const metadata of model.metadata) {
+ if (metadata.value && metadata.value.surface_flinger) {
+ addSurfaceFlingerHistograms_(
+ histograms, frameSegments,
+ metadata.value.surface_flinger.refresh_period);
+ return;
+ }
+ }
+ }
+
+ function addUIFrameTimeHistograms(histograms, model, segments) {
+ const events = getUIPresentationEvents_(
+ model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper));
+ if (!events) return;
+
+ // Presentation Timestamps should be sorted.
+ const timestamps = events.map(event => [event.start, event.start]);
+ const frameSements = computeFrameSegments_(timestamps, segments);
+ addBasicFrameTimeHistograms_(histograms, frameSements, 'ui_');
+ }
+
+ return {
+ addFrameTimeHistograms,
+ addUIFrameTimeHistograms,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_time_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_time_test.html
new file mode 100644
index 00000000000..0304a5cc0c5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/frame_time_test.html
@@ -0,0 +1,301 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/rendering/frame_time.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('frameTimes', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ // Add four swap buffer events, at times 1, 2, 19, 21
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 1, end: 1 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 2, end: 2 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 19, end: 19 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 21, end: 21 }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addFrameTimeHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 20)]);
+
+ // The fourth frame is outside the interaction perdiod and should be
+ // discarded. The durations between the remaining three frames are 1 and 17.
+ let hist = histograms.getHistogramNamed('frame_times');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(17, hist.max, 1e-6);
+ assert.closeTo(9, hist.average, 1e-6);
+
+ // One of the two frame times is not smooth.
+ hist = histograms.getHistogramNamed('percentage_smooth');
+ assert.closeTo(50, hist.min, 1e-6);
+ assert.closeTo(50, hist.max, 1e-6);
+ assert.closeTo(50, hist.average, 1e-6);
+ });
+
+ test('frameTimes_drmEvents', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+
+ const gpuMain = model.getOrCreateProcess(1).getOrCreateThread(0);
+ gpuMain.name = 'CrGpuMain';
+ gpuMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'DrmEventFlipComplete', start: 1, end: 1,
+ args: { data: { 'vblank.tv_sec': 0, 'vblank.tv_usec': 1000 } } }));
+ gpuMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'DrmEventFlipComplete', start: 3, end: 3,
+ args: { data: { 'vblank.tv_sec': 0, 'vblank.tv_usec': 2000 } } }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addFrameTimeHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 6)]);
+
+ // When computing frame times from DRM events, VBlank times should be used.
+ const hist = histograms.getHistogramNamed('frame_times');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(1, hist.max, 1e-6);
+ assert.closeTo(1, hist.average, 1e-6);
+ });
+
+ test('frameTimes_surfaceFlingerEvents', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 1, end: 1 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 2, end: 2 }));
+
+ const surfaceFlingerProcess = model.getOrCreateProcess(2);
+ surfaceFlingerProcess.name = 'SurfaceFlinger';
+ const surfaceFlingerThread = surfaceFlingerProcess.getOrCreateThread(2);
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 1, end: 1}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 3, end: 3}));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addFrameTimeHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 6)]);
+
+ // Data from the Surface Flinger process should be used if it exists.
+ const hist = histograms.getHistogramNamed('frame_times');
+ assert.closeTo(2, hist.min, 1e-6);
+ assert.closeTo(2, hist.max, 1e-6);
+ assert.closeTo(2, hist.average, 1e-6);
+ });
+
+ test('frameLengths', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ model.metadata = [{
+ name: 'metadata',
+ value: {
+ surface_flinger: {
+ refresh_period: 3,
+ },
+ },
+ }];
+
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+
+ const surfaceFlingerProcess = model.getOrCreateProcess(2);
+ surfaceFlingerProcess.name = 'SurfaceFlinger';
+ const surfaceFlingerThread = surfaceFlingerProcess.getOrCreateThread(2);
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 1, end: 1}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 4, end: 4}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 10, end: 10}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 13, end: 13}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 14, end: 14}));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addFrameTimeHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 20)]);
+
+ // Frame lengths are 3/3, 6/3, 3/3, and 1/3. The last one is too small and
+ // should be filtered out. So, the final result is [1, 2, 1].
+ const hist = histograms.getHistogramNamed('frame_lengths');
+ assert.closeTo(3, hist.numValues, 1e-6);
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(2, hist.max, 1e-6);
+ assert.closeTo(4, hist.sum, 1e-6);
+ });
+
+ test('avgSurfaceFPS', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ model.metadata = [{
+ name: 'metadata',
+ value: {
+ surface_flinger: {
+ refresh_period: 3,
+ },
+ },
+ }];
+
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+
+ const surfaceFlingerProcess = model.getOrCreateProcess(2);
+ surfaceFlingerProcess.name = 'SurfaceFlinger';
+ const surfaceFlingerThread = surfaceFlingerProcess.getOrCreateThread(2);
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 1, end: 1}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 4, end: 4}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 10, end: 10}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 13, end: 13}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 14, end: 14}));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addFrameTimeHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 20)]);
+
+ // We have 3 frames (ignoring the very short ones) in 13 milliseconds.
+ const hist = histograms.getHistogramNamed('avg_surface_fps');
+ assert.closeTo(1, hist.numValues, 1e-6);
+ assert.closeTo(3 / 0.013, hist.min, 1e-6);
+ });
+
+ test('jankCount', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ model.metadata = [{
+ name: 'metadata',
+ value: {
+ surface_flinger: {
+ refresh_period: 3,
+ },
+ },
+ }];
+
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+
+ const surfaceFlingerProcess = model.getOrCreateProcess(2);
+ surfaceFlingerProcess.name = 'SurfaceFlinger';
+ const surfaceFlingerThread = surfaceFlingerProcess.getOrCreateThread(2);
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 1, end: 1}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 4, end: 4}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 7, end: 7}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 13, end: 13}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 16, end: 16}));
+ surfaceFlingerThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'vsync_before', start: 79, end: 79}));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addFrameTimeHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 100)]);
+
+ // There is 1 jank in [1, 1, 2, 1, 21]. The last long frame is a pause.
+ const hist = histograms.getHistogramNamed('jank_count');
+ assert.closeTo(1, hist.numValues, 1e-6);
+ assert.closeTo(1, hist.min, 1e-6);
+ });
+
+ test('uiFrameTimes', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ // Add four swap buffer events, at times 1, 2, 19, 21
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'FramePresented', start: 1, end: 1 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'FramePresented', start: 2, end: 2 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'FramePresented', start: 19, end: 19 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'FramePresented', start: 21, end: 21 }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addUIFrameTimeHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 20)]);
+
+ // The fourth frame is outside the interaction perdiod and should be
+ // discarded. The durations between the remaining three frames are 1 and 17.
+ let hist = histograms.getHistogramNamed('ui_frame_times');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(17, hist.max, 1e-6);
+ assert.closeTo(9, hist.average, 1e-6);
+
+ // One of the two frame times is not smooth.
+ hist = histograms.getHistogramNamed('ui_percentage_smooth');
+ assert.closeTo(50, hist.min, 1e-6);
+ assert.closeTo(50, hist.max, 1e-6);
+ assert.closeTo(50, hist.average, 1e-6);
+ });
+
+ test('uiFrameTimesWithEnvironmentArg', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ // Add four swap buffer events, at times 1, 2, 3, 19
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'FramePresented',
+ start: 1,
+ end: 1,
+ args: { environment: 'ash' }
+ }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'FramePresented',
+ start: 2,
+ end: 2,
+ args: { environment: 'ash' }
+ }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'FramePresented',
+ start: 3,
+ end: 3,
+ args: { environment: 'browser' }
+ }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'FramePresented',
+ start: 19,
+ end: 19,
+ args: { environment: 'ash' }
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addUIFrameTimeHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 20)]);
+
+ // The 3rd frame is from 'browser' and should be discarded. Remaining
+ // timestamps are 1, 2, and 19 which indicate frame times of 1 and 17.
+ const hist = histograms.getHistogramNamed('ui_frame_times');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(17, hist.max, 1e-6);
+ assert.closeTo(2, hist.numValues, 1e-6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/latency.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/latency.html
new file mode 100644
index 00000000000..cbd691dacf3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/latency.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import" href="/tracing/model/async_slice_group.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains implementations of the following metrics.
+ *
+ * input_event_latency
+ * ===================
+ * The distribution of durations between the time when an input event is
+ * generated to the time when the GPU service swaps buffers due to the input
+ * event. The time when an input is generated is the first of the following
+ * three timestamps that we can get:
+ *
+ * 1. Original kernel timestamp of the input event.
+ * 2. Timestamp when the UI event is created.
+ * 3. Timestamp when the input event is sent from RenderWidgetHost to the
+ * renderer.
+ *
+ * main_thread_scroll_latency
+ * ==========================
+ * The distribution of durations between the time when the main thread scroll
+ * listener update is begun to the time when the GPU service swaps buffers due
+ * to the scroll event.
+ *
+ * first_gesture_scroll_update_latency
+ * ===================================
+ * This shows the latency, as defined in input_event_latency, of the first
+ * gesture scroll update input event. The first event can often get delayed by
+ * work related to page loading.
+ */
+tr.exportTo('tr.metrics.rendering', function() {
+ // Interesting latency info component names.
+ const BEGIN_SCROLL_UPDATE_COMP_NAME =
+ 'LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT';
+ const END_COMP_NAME = 'INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT';
+
+ function* iterAsyncEvents_(processHelpers, ranges, processEventFn) {
+ for (const processHelper of processHelpers) {
+ const process = processHelper.process;
+ for (const event of process.getDescendantEventsInSortedRanges(
+ ranges, container => container instanceof tr.model.AsyncSliceGroup)) {
+ yield* processEventFn(event);
+ }
+ }
+ }
+
+ function* processInputLatencyEvent(event) {
+ if (!(event instanceof tr.e.cc.InputLatencyAsyncSlice)) return;
+ const latency = event.inputLatency;
+ if (latency === undefined) return;
+ yield tr.b.Unit.timestampFromUs(latency);
+ }
+
+ function* processLatencyEvent(event) {
+ if (event.title !== 'Latency::ScrollUpdate' ||
+ !('data' in event.args) || !(END_COMP_NAME in event.args.data)) {
+ return;
+ }
+ const data = event.args.data;
+ const endTime = data[END_COMP_NAME].time;
+ if (BEGIN_SCROLL_UPDATE_COMP_NAME in data) {
+ yield tr.b.Unit.timestampFromUs(
+ endTime - data[BEGIN_SCROLL_UPDATE_COMP_NAME].time);
+ } else {
+ throw new Error('LatencyInfo has no begin component');
+ }
+ }
+
+ function* processGestureScrollUpdateLatencyEvent(event) {
+ if (event.title !== 'InputLatency::GestureScrollUpdate') return;
+ if (!(event instanceof tr.e.cc.InputLatencyAsyncSlice)) {
+ throw new Error('Gesture scroll update latency event is not an ' +
+ 'instance of tr.e.cc.InputLatencyAsyncSlice');
+ }
+ const latency = event.inputLatency;
+ if (latency === undefined) return;
+ yield [event.start, tr.b.Unit.timestampFromUs(latency)];
+ }
+
+ function addLatencyHistograms(histograms, model, segments) {
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!modelHelper) return;
+
+ const ranges = segments.map(s => s.boundsRange);
+ const inputEventLatencies = [...iterAsyncEvents_(
+ modelHelper.browserHelpers, ranges, processInputLatencyEvent)];
+ histograms.createHistogram(
+ 'input_event_latency',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ inputEventLatencies,
+ { binBoundaries: tr.v.HistogramBinBoundaries.createLinear(0, 50, 20),
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ description: 'Input event latencies.' });
+
+ const mainThreadScrollLatencies = [...iterAsyncEvents_(
+ Object.values(modelHelper.rendererHelpers), ranges,
+ processLatencyEvent)];
+ histograms.createHistogram(
+ 'main_thread_scroll_latency',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ mainThreadScrollLatencies,
+ { binBoundaries: tr.v.HistogramBinBoundaries.createLinear(0, 50, 50),
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ description: 'Main thread scroll latencies.' });
+
+ const gestureScrollUpdateLatencies = [...iterAsyncEvents_(
+ modelHelper.browserHelpers, ranges,
+ processGestureScrollUpdateLatencyEvent)].sort((x, y) => x[0] - y[0]);
+ if (gestureScrollUpdateLatencies.length) {
+ histograms.createHistogram(
+ 'first_gesture_scroll_update_latency',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ gestureScrollUpdateLatencies[0][1],
+ { binBoundaries: tr.v.HistogramBinBoundaries.createLinear(0, 50, 20),
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ description: 'Latency of the first gesture scroll update.' });
+ }
+ }
+
+ return {
+ addLatencyHistograms,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/latency_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/latency_test.html
new file mode 100644
index 00000000000..4a68b8e4655
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/latency_test.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/rendering/latency.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('inputEventLatency', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browser = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browser.name = 'CrBrowserMain';
+ browser.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ start: 9, end: 10,
+ args: {
+ data: {
+ INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT: {time: 10000},
+ INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT: {time: 9000}
+ }
+ }
+ }));
+ browser.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ start: 7, end: 8,
+ args: {
+ data: {
+ INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT: {time: 8000},
+ INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT: {time: 7000},
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT: {time: 6000},
+ }
+ }
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addLatencyHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 10)]);
+
+ // The first input latency is 10 - 9 = 1. The second input latency is
+ // 8 - 6 = 2.
+ const hist = histograms.getHistogramNamed('input_event_latency');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(2, hist.max, 1e-6);
+ assert.closeTo(1.5, hist.average, 1e-6);
+ });
+
+ test('mainThreadScrollLatency', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ model.getOrCreateProcess(0).getOrCreateThread(0).name = 'CrBrowserMain';
+ const renderer = model.getOrCreateProcess(1).getOrCreateThread(0);
+ renderer.name = 'CrRendererMain';
+ renderer.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({
+ title: 'Latency::ScrollUpdate',
+ start: 9, end: 10,
+ args: {
+ data: {
+ INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT: {time: 10000},
+ LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT: {time: 9000}
+ }
+ }
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addLatencyHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 10)]);
+
+ const hist = histograms.getHistogramNamed('main_thread_scroll_latency');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(1, hist.max, 1e-6);
+ assert.closeTo(1, hist.average, 1e-6);
+ });
+
+ test('firstGestureScrollUpdateLatency', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browser = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browser.name = 'CrBrowserMain';
+ browser.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ start: 10, end: 11,
+ args: {
+ data: {
+ INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT: {time: 10000},
+ INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT: {time: 9000}
+ }
+ }
+ }));
+ browser.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ start: 7, end: 8,
+ args: {
+ data: {
+ INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT: {time: 8000},
+ INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT: {time: 7000},
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT: {time: 6000},
+ }
+ }
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addLatencyHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 20)]);
+
+ // The chronologically first gesture scroll update latency is 8 - 6 = 2.
+ const hist = histograms.getHistogramNamed(
+ 'first_gesture_scroll_update_latency');
+ assert.closeTo(2, hist.min, 1e-6);
+ assert.closeTo(2, hist.max, 1e-6);
+ assert.closeTo(2, hist.average, 1e-6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pipeline.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pipeline.html
new file mode 100644
index 00000000000..1b68e5d6a31
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pipeline.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/diagnostics/breakdown.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains implementations of the following metrics.
+ *
+ * TODO(crbug.com/872334): document pipeline:* metrics here.
+ */
+tr.exportTo('tr.metrics.rendering', function() {
+ function eventIsValidGraphicsEvent_(event, eventMap) {
+ if (event.title !== 'Graphics.Pipeline' || !event.bindId || !event.args ||
+ !event.args.step) {
+ return false;
+ }
+ const bindId = event.bindId;
+ if (eventMap.has(bindId) && event.args.step in eventMap.get(bindId)) {
+ // It is possible for a client to submit multiple compositor frames for
+ // one begin-message. So most steps can be present multiple times.
+ // However, a begin-frame is issued only once, and received only once. So
+ // these steps should not be repeated.
+ if (event.args.step === 'IssueBeginFrame' ||
+ event.args.step === 'ReceiveBeginFrame') {
+ throw new Error('Unexpected duplicate step: ' + event.args.step);
+ }
+ return false;
+ }
+ return true;
+ }
+
+ function generateBreakdownForCompositorPipelineInClient_(flow) {
+ const breakdown = new tr.v.d.Breakdown();
+ breakdown.set('time before GenerateRenderPass',
+ flow.GenerateRenderPass.start - flow.ReceiveBeginFrame.start);
+ breakdown.set('GenerateRenderPass duration',
+ flow.GenerateRenderPass.duration);
+ breakdown.set('GenerateCompositorFrame duration',
+ flow.GenerateCompositorFrame.duration);
+ breakdown.set('SubmitCompositorFrame duration',
+ flow.SubmitCompositorFrame.duration);
+ return breakdown;
+ }
+
+ function generateBreakdownForCompositorPipelineInService_(flow) {
+ const breakdown = new tr.v.d.Breakdown();
+ breakdown.set('Processing CompositorFrame on reception',
+ flow.ReceiveCompositorFrame.duration);
+ breakdown.set('Delay before SurfaceAggregation',
+ flow.SurfaceAggregation.start - flow.ReceiveCompositorFrame.end);
+ breakdown.set('SurfaceAggregation duration',
+ flow.SurfaceAggregation.duration);
+ return breakdown;
+ }
+
+ function generateBreakdownForDraw_(drawEvent) {
+ const breakdown = new tr.v.d.Breakdown();
+ for (const slice of drawEvent.subSlices) {
+ breakdown.set(slice.title, slice.duration);
+ }
+ return breakdown;
+ }
+
+ function getDisplayCompositorThread_(model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const gpuHelper = chromeHelper.gpuHelper;
+ if (gpuHelper) {
+ const thread =
+ gpuHelper.process.findAtMostOneThreadNamed('VizCompositorThread');
+ if (thread) {
+ return thread;
+ }
+ }
+ if (!chromeHelper.browserProcess) return null;
+ return chromeHelper.browserProcess.findAtMostOneThreadNamed(
+ 'CrBrowserMain');
+ }
+
+ function getRasterTaskTimes(sourceFrameNumber, model) {
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ const renderers = modelHelper.telemetryHelper.renderersWithIR;
+ const rasterThreads = renderers[0].rasterWorkerThreads;
+
+ let earliestStart = undefined;
+ let lastEnd = undefined;
+ for (const rasterThread of rasterThreads) {
+ for (const slice of [...rasterThread.
+ findTopmostSlicesNamed('TaskGraphRunner::RunTask')]) {
+ if (slice.args &&
+ slice.args.source_frame_number_ &&
+ slice.args.source_frame_number_ === sourceFrameNumber) {
+ if (earliestStart === undefined || slice.start < earliestStart) {
+ earliestStart = slice.start;
+ }
+ if (lastEnd === undefined || slice.end > lastEnd) {
+ lastEnd = slice.end;
+ }
+ }
+ }
+ }
+ return {start: earliestStart, end: lastEnd};
+ }
+
+ function addPipelineHistograms(histograms, model, segments) {
+ const ranges = segments.map(s => s.boundsRange);
+ const bindEvents = new Map();
+ for (const thread of model.getAllThreads()) {
+ for (const event of thread.sliceGroup.childEvents()) {
+ if (!eventIsValidGraphicsEvent_(event, bindEvents)) continue;
+ for (const range of ranges) {
+ if (range.containsExplicitRangeInclusive(event.start, event.end)) {
+ if (!bindEvents.has(event.bindId)) bindEvents.set(event.bindId, {});
+ break;
+ }
+ }
+ if (bindEvents.has(event.bindId)) {
+ bindEvents.get(event.bindId)[event.args.step] = event;
+ }
+ }
+ }
+
+ const dcThread = getDisplayCompositorThread_(model);
+ const drawEvents = {};
+ if (dcThread) {
+ const events =
+ [...dcThread.findTopmostSlicesNamed('Graphics.Pipeline.DrawAndSwap')];
+ for (const segment of segments) {
+ const filteredEvents = segment.boundsRange.filterArray(events,
+ evt => evt.start);
+ for (const event of filteredEvents) {
+ if ((event.args && event.args.status === 'canceled') ||
+ !event.id.startsWith(':ptr:')) {
+ continue;
+ }
+ const id = parseInt(event.id.substring(5), 16);
+ if (id in drawEvents) {
+ throw new Error('Duplicate draw events: ' + id);
+ }
+ drawEvents[id] = event;
+ }
+ }
+ }
+
+ const issueToReceipt = histograms.createHistogram(
+ 'pipeline:begin_frame_transport',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [], {
+ description: 'Latency of begin-frame message from the display ' +
+ 'compositor to the client, including the IPC latency and task-' +
+ 'queue time in the client.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ const issueToRasterStart = histograms.createHistogram(
+ 'pipeline:begin_frame_to_raster_start',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [], {
+ description: 'Latency between begin-frame message and ' +
+ 'the beginning of the first CompositorTask run in the compositor.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ const issueToRasterEnd = histograms.createHistogram(
+ 'pipeline:begin_frame_to_raster_end',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [], {
+ description: 'Latency between begin-frame message and ' +
+ 'the end of the last CompositorTask run in the compositor.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ const receiptToSubmit = histograms.createHistogram(
+ 'pipeline:begin_frame_to_frame_submission',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [], {
+ description: 'Latency between begin-frame reception and ' +
+ 'CompositorFrame submission in the renderer.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ const submitToAggregate = histograms.createHistogram(
+ 'pipeline:frame_submission_to_display',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [], {
+ description: 'Latency between CompositorFrame submission in the ' +
+ 'renderer to display in the display-compositor, including IPC ' +
+ 'latency, task-queue time in the display-compositor, and ' +
+ 'additional processing (e.g. surface-sync etc.)',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ const aggregateToDraw = histograms.createHistogram(
+ 'pipeline:draw',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [], {
+ description: 'How long it takes for the gpu-swap step.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+
+ for (const flow of bindEvents.values()) {
+ // Report only for the cases that go through the complete pipeline.
+ if (!flow.IssueBeginFrame || !flow.ReceiveBeginFrame ||
+ !flow.SubmitCompositorFrame || !flow.SurfaceAggregation) {
+ continue;
+ }
+
+ const sourceFrameNumber = flow.SubmitCompositorFrame.parentSlice
+ .args.source_frame_number_;
+
+ const rasterDuration =
+ getRasterTaskTimes(sourceFrameNumber, model);
+
+ issueToReceipt.addSample(flow.ReceiveBeginFrame.start -
+ flow.IssueBeginFrame.start);
+ receiptToSubmit.addSample(
+ flow.SubmitCompositorFrame.end - flow.ReceiveBeginFrame.start,
+ {breakdown: generateBreakdownForCompositorPipelineInClient_(flow)});
+ submitToAggregate.addSample(
+ flow.SurfaceAggregation.end - flow.SubmitCompositorFrame.end,
+ {breakdown: generateBreakdownForCompositorPipelineInService_(flow)});
+
+ if (rasterDuration.start && rasterDuration.end) {
+ const receiveToStart = rasterDuration.start -
+ flow.ReceiveBeginFrame.start;
+ const receiveToEnd = rasterDuration.end - flow.ReceiveBeginFrame.end;
+
+ // receiveToStart can be negative if the earliest raster task for
+ // a frame starts before receiveBeginFrame starts.
+ // The same is true for receiveToEnd
+ // Only positive samples are added.
+ if (receiveToEnd > 0) {
+ issueToRasterStart.addSample(receiveToStart > 0 ? receiveToStart : 0);
+ issueToRasterEnd.addSample(receiveToEnd);
+ }
+ }
+ if (flow.SurfaceAggregation.args &&
+ flow.SurfaceAggregation.args.display_trace) {
+ const displayTrace = flow.SurfaceAggregation.args.display_trace;
+ if (!(displayTrace in drawEvents)) continue;
+ const drawEvent = drawEvents[displayTrace];
+ aggregateToDraw.addSample(drawEvent.duration,
+ {breakdown: generateBreakdownForDraw_(drawEvent)});
+ }
+ }
+ }
+
+ return {
+ addPipelineHistograms,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pipeline_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pipeline_test.html
new file mode 100644
index 00000000000..332767c0e79
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pipeline_test.html
@@ -0,0 +1,366 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/rendering/pipeline.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function addPipelineForOneFrame(compositor, renderer, rasterWorker,
+ id, frame, displayTrace) {
+ const EVENT_NAME = 'Graphics.Pipeline';
+ if (frame.IssueBeginFrame) {
+ compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: EVENT_NAME,
+ start: frame.IssueBeginFrame, duration: 1, bindId: id,
+ args: {step: 'IssueBeginFrame'}}));
+ }
+ if (frame.ReceiveBeginFrame) {
+ renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: EVENT_NAME,
+ start: frame.ReceiveBeginFrame, duration: 1, bindId: id,
+ args: {step: 'ReceiveBeginFrame'}}));
+ }
+ renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: EVENT_NAME,
+ start: frame.GenerateRenderPass, duration: 1, bindId: id,
+ args: {step: 'GenerateRenderPass'}}));
+ renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: EVENT_NAME,
+ start: frame.GenerateCompositorFrame, duration: 1, bindId: id,
+ args: {step: 'GenerateCompositorFrame'}}));
+ renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: EVENT_NAME,
+ start: frame.SubmitCompositorFrame, duration: 1, bindId: id,
+ args: {source_frame_number_: id}}));
+ renderer.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: EVENT_NAME,
+ start: frame.SubmitCompositorFrame, duration: 1, bindId: id,
+ args: {step: 'SubmitCompositorFrame'}}));
+ compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: EVENT_NAME,
+ start: frame.ReceiveCompositorFrame, duration: 1, bindId: id,
+ args: {step: 'ReceiveCompositorFrame'}}));
+ compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: EVENT_NAME,
+ start: frame.SurfaceAggregation, duration: 1, bindId: id,
+ args: {step: 'SurfaceAggregation', display_trace: displayTrace}}));
+ renderer.sliceGroup.createSubSlices();
+ rasterWorker.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'TaskGraphRunner::RunTask',
+ start: frame.rasterTaskStart, duration: 6, bindId: id,
+ args: {source_frame_number_: id}}));
+ }
+
+ function addDrawSlice(compositor, displayTrace, start, steps, opt_args) {
+ const EVENT_NAME = 'Graphics.Pipeline.DrawAndSwap';
+ let totalDuration = 0;
+ for (const duration of Object.values(steps)) {
+ totalDuration += duration;
+ }
+ const slice = tr.c.TestUtils.newAsyncSliceNamed(
+ EVENT_NAME, start, totalDuration);
+ slice.id = ':ptr:' + displayTrace;
+ slice.args = opt_args;
+ compositor.sliceGroup.pushSlice(slice);
+ totalDuration = 0;
+ for (const step in steps) {
+ slice.subSlices.push(tr.c.TestUtils.newAsyncSliceNamed(
+ step, start + totalDuration, steps[step]));
+ totalDuration += steps[step];
+ }
+ }
+
+ test('graphicsPipeline', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ const rendererCompositor =
+ model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererCompositor.name = 'Compositor';
+
+ // Creates a renderer thread
+ const renderer = model.getOrCreateProcess(2).getOrCreateThread(2);
+ renderer.name = 'CrRendererMain';
+ renderer.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Action', 1, 1));
+
+ const rasterWorker = model.getOrCreateProcess(2).getOrCreateThread(5);
+ rasterWorker.name = 'CompositorTileWorker';
+
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorker, 1, {
+ IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
+ GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
+ ReceiveCompositorFrame: 6, SurfaceAggregation: 10,
+ rasterTaskStart: 2
+ });
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorker, 2, {
+ IssueBeginFrame: 15, ReceiveBeginFrame: 16,
+ GenerateRenderPass: 17, GenerateCompositorFrame: 18,
+ SubmitCompositorFrame: 19, ReceiveCompositorFrame: 20,
+ SurfaceAggregation: 21, rasterTaskStart: 22
+ });
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorker, 3, {
+ IssueBeginFrame: 32, ReceiveBeginFrame: 34,
+ GenerateRenderPass: 35, GenerateCompositorFrame: 36,
+ SubmitCompositorFrame: 37, SubmitCompositorFrame: 38,
+ ReceiveCompositorFrame: 41, SurfaceAggregation: 44,
+ rasterTaskStart: 25
+ });
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addPipelineHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 50)]);
+
+
+ const beginFrameTransport = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_transport');
+ const frameSubmission = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_to_frame_submission');
+ const surfaceAggregation = histograms.getHistogramNamed(
+ 'pipeline:frame_submission_to_display');
+ const rasterStart = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_to_raster_start');
+ const rasterEnd = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_to_raster_end');
+ assert.closeTo(beginFrameTransport.average, 4 / 3, 1e-6);
+ assert.closeTo(frameSubmission.average, 13 / 3, 1e-6);
+ assert.closeTo(surfaceAggregation.average, 13 / 3, 1e-6);
+ assert.closeTo(rasterStart.average, 6 / 2, 1e-6);
+ assert.closeTo(rasterEnd.average, 16 / 2, 1e-6);
+ });
+
+ test('graphicsPipeline_duplicateSteps', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ const rendererCompositor =
+ model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererCompositor.name = 'Compositor';
+
+ // Creates a renderer thread
+ const renderer = model.getOrCreateProcess(2).getOrCreateThread(2);
+ renderer.name = 'CrRendererMain';
+ renderer.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Action', 1, 1));
+
+ const rasterWorker = model.getOrCreateProcess(2).getOrCreateThread(5);
+ rasterWorker.name = 'CompositorTileWorker';
+
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorker, 1, {
+ IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
+ GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
+ ReceiveCompositorFrame: 6, SurfaceAggregation: 9,
+ rasterTaskStart: 3
+ });
+
+ // Add duplicate steps for SubmitCompositorFrame and the subsequent
+ // steps for the same trace-id.
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorker, 1, {
+ GenerateRenderPass: 10, GenerateCompositorFrame: 11,
+ SubmitCompositorFrame: 12, ReceiveCompositorFrame: 15,
+ SurfaceAggregation: 18, rasterTaskStart: 3
+ });
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addPipelineHistograms(
+ histograms, model,
+ [new tr.model.um.Segment(0, 50), new tr.model.um.Segment(0, 20)]);
+
+ const beginFrameTransport = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_transport');
+ const frameSubmission = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_to_frame_submission');
+ const surfaceAggregation = histograms.getHistogramNamed(
+ 'pipeline:frame_submission_to_display');
+ const rasterStart = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_to_raster_start');
+ const rasterEnd = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_to_raster_end');
+ assert.strictEqual(beginFrameTransport.average, 1);
+ assert.strictEqual(frameSubmission.average, 4);
+ assert.strictEqual(surfaceAggregation.average, 4);
+ assert.strictEqual(rasterStart.average, 1);
+ assert.strictEqual(rasterEnd.average, 6);
+ });
+
+ test('graphicsPipeline_duplicateRenderers', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ const rendererCompositor =
+ model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererCompositor.name = 'Compositor';
+
+ // Creates a renderer thread
+ const rendererWithIR = model.getOrCreateProcess(2).getOrCreateThread(2);
+ rendererWithIR.name = 'CrRendererMain';
+ rendererWithIR.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Action', 1, 1));
+
+ const rasterWorkerWithIR = model.getOrCreateProcess(2)
+ .getOrCreateThread(5);
+ rasterWorkerWithIR.name = 'CompositorTileWorker';
+
+ const rendererWithoutIR = model.getOrCreateProcess(3)
+ .getOrCreateThread(2);
+ rendererWithoutIR.name = 'CrRendererMain';
+
+ const rasterWorkerWithoutIR = model.getOrCreateProcess(3)
+ .getOrCreateThread(5);
+ rasterWorkerWithoutIR.name = 'CompositorTileWorker';
+
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorkerWithIR, 1, {
+ IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
+ GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
+ ReceiveCompositorFrame: 6, SurfaceAggregation: 10,
+ rasterTaskStart: 3
+ });
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorkerWithoutIR, 2, {
+ IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
+ GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
+ ReceiveCompositorFrame: 6, SurfaceAggregation: 10,
+ rasterTaskStart: 4
+ });
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addPipelineHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 50)]);
+
+ const rasterStart = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_to_raster_start');
+ const rasterEnd = histograms.getHistogramNamed(
+ 'pipeline:begin_frame_to_raster_end');
+ assert.strictEqual(rasterStart.average, 1);
+ assert.strictEqual(rasterEnd.average, 6);
+ });
+
+ test('graphicsPipeline_drawSteps', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ const rendererCompositor =
+ model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererCompositor.name = 'Compositor';
+
+ // Creates a renderer thread
+ const renderer = model.getOrCreateProcess(2).getOrCreateThread(2);
+ renderer.name = 'CrRendererMain';
+ renderer.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Action', 1, 1));
+
+ const rasterWorker = model.getOrCreateProcess(2).getOrCreateThread(5);
+ rasterWorker.name = 'CompositorTileWorker';
+
+ const displayTrace = '1';
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorker, 1, {
+ IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
+ GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
+ ReceiveCompositorFrame: 6, SurfaceAggregation: 9,
+ rasterTaskStart: 3
+ }, displayTrace);
+
+ addDrawSlice(browserMain, displayTrace, 10,
+ {Draw: 2, Swap: 1, WaitForAck: 5}, {});
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addPipelineHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 50)]);
+
+ const drawHistogram = histograms.getHistogramNamed('pipeline:draw');
+ assert.strictEqual(drawHistogram.average, 8);
+ });
+
+ test('graphicsPipeline_drawCanceled', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ const rendererCompositor =
+ model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererCompositor.name = 'Compositor';
+
+ // Creates a renderer thread
+ const renderer = model.getOrCreateProcess(2).getOrCreateThread(2);
+ renderer.name = 'CrRendererMain';
+ renderer.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Action', 1, 1));
+
+ const rasterWorker = model.getOrCreateProcess(2).getOrCreateThread(5);
+ rasterWorker.name = 'CompositorTileWorker';
+
+ const displayTrace = '1';
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorker, 1, {
+ IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
+ GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
+ ReceiveCompositorFrame: 6, SurfaceAggregation: 9,
+ rasterTaskStart: 3
+ }, displayTrace);
+
+ addDrawSlice(browserMain, displayTrace, 10,
+ {Draw: 2, Swap: 1, WaitForAck: 5}, {status: 'canceled'});
+ addDrawSlice(browserMain, displayTrace, 15,
+ {Draw: 2, Swap: 1, WaitForAck: 5});
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addPipelineHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 50)]);
+
+ const drawHistogram = histograms.getHistogramNamed('pipeline:draw');
+ assert.strictEqual(drawHistogram.average, 8);
+ });
+
+ test('graphicsPipeline_receiveCFAfterAnimation', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ const rendererCompositor =
+ model.getOrCreateProcess(1).getOrCreateThread(1);
+ rendererCompositor.name = 'Compositor';
+
+ // Creates a renderer thread
+ const renderer = model.getOrCreateProcess(2).getOrCreateThread(2);
+ renderer.name = 'CrRendererMain';
+ renderer.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Action', 1, 1));
+
+ const rasterWorker = model.getOrCreateProcess(2).getOrCreateThread(5);
+ rasterWorker.name = 'CompositorTileWorker';
+
+ addPipelineForOneFrame(browserMain, rendererCompositor,
+ rasterWorker, 1, {
+ IssueBeginFrame: 1, ReceiveBeginFrame: 2, GenerateRenderPass: 3,
+ GenerateCompositorFrame: 4, SubmitCompositorFrame: 5,
+ ReceiveCompositorFrame: 11, SurfaceAggregation: 15,
+ rasterTaskStart: 2
+ });
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addPipelineHistograms(
+ histograms, model,
+ [new tr.model.um.Segment(0, 10), new tr.model.um.Segment(14, 16)]);
+
+ const surfaceAggregation = histograms.getHistogramNamed(
+ 'pipeline:frame_submission_to_display');
+ assert.strictEqual(surfaceAggregation.average, 10);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pixels.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pixels.html
new file mode 100644
index 00000000000..7f3060561d8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pixels.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains implementations of the following metrics.
+ *
+ * mean_pixels_approximated
+ * ========================
+ * The percentage of tiles which are missing or of low or non-ideal resolution.
+ *
+ * TODO(crbug.com/875010): The documentation claims that
+ * mean_pixels_approximated should be greater than or equal to
+ * mean_pixels_checkerboarded. This claim is not consistent with numbers from
+ * the perf dashboard. We should either correct the documentations or fix the
+ * metrics.
+ *
+ * mean_pixels_checkerboarded
+ * ==========================
+ * The percentage of tiles which are only missing. It does not take into
+ * consideration tiles which are of low or non-ideal resolution.
+ */
+tr.exportTo('tr.metrics.rendering', function() {
+ const IMPL_THREAD_RENDERING_STATS_EVENT =
+ 'BenchmarkInstrumentation::ImplThreadRenderingStats';
+ const VISIBLE_CONTENT_DATA = 'visible_content_area';
+ const APPROXIMATED_VISIBLE_CONTENT_DATA = 'approximated_visible_content_area';
+ const CHECKERBOARDED_VISIBLE_CONTENT_DATA =
+ 'checkerboarded_visible_content_area';
+
+ function addPixelsHistograms(histograms, model, segments) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!chromeHelper) return;
+
+ const approximatedPixelPercentages = [];
+ const checkerboardedPixelPercentages = [];
+ const ranges = segments.map(s => s.boundsRange);
+ for (const rendererHelper of Object.values(chromeHelper.rendererHelpers)) {
+ if (rendererHelper.compositorThread === undefined) continue;
+ const slices = rendererHelper.compositorThread.sliceGroup;
+ for (const slice of slices.getDescendantEventsInSortedRanges(ranges)) {
+ if (slice.title !== IMPL_THREAD_RENDERING_STATS_EVENT) continue;
+ const data = slice.args.data;
+ if (!(VISIBLE_CONTENT_DATA in data)) {
+ throw new Error(`${VISIBLE_CONTENT_DATA} is missing`);
+ }
+ const visibleContentArea = data[VISIBLE_CONTENT_DATA];
+ if (visibleContentArea === 0) {
+ // TODO(crbug.com/877056): This is reported as an error in the legacy
+ // code, which indicates there should be no rendering stats event with
+ // zero visible content area. But, the TBMv2 implementation encounters
+ // such events. Maybe they are coming from OOPIFs which are ignored in
+ // the legacy code? Investigate why they exist and what should be
+ // done.
+ //
+ // throw new Error(`${VISIBLE_CONTENT_DATA} is zero`);
+ continue;
+ }
+ if (APPROXIMATED_VISIBLE_CONTENT_DATA in data) {
+ approximatedPixelPercentages.push(
+ data[APPROXIMATED_VISIBLE_CONTENT_DATA] / visibleContentArea);
+ }
+ if (CHECKERBOARDED_VISIBLE_CONTENT_DATA in data) {
+ checkerboardedPixelPercentages.push(
+ data[CHECKERBOARDED_VISIBLE_CONTENT_DATA] / visibleContentArea);
+ }
+ }
+ }
+
+ // TODO(crbug.com/892501): The averages are multiplied by 100 to match an
+ // error in legacy code so that we have continuity in graphs in the perf
+ // dashboard. We should fix historic data and remove the multiplication.
+ histograms.createHistogram(
+ 'mean_pixels_approximated',
+ tr.b.Unit.byName.normalizedPercentage_smallerIsBetter,
+ 100 * tr.b.math.Statistics.mean(approximatedPixelPercentages),
+ { description: 'Percentage of pixels that were approximated ' +
+ '(checkerboarding, low-resolution tiles, etc.).',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ histograms.createHistogram(
+ 'mean_pixels_checkerboarded',
+ tr.b.Unit.byName.normalizedPercentage_smallerIsBetter,
+ 100 * tr.b.math.Statistics.mean(checkerboardedPixelPercentages),
+ { description: 'Percentage of pixels that were checkerboarded.',
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ });
+ }
+
+ return {
+ addPixelsHistograms,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pixels_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pixels_test.html
new file mode 100644
index 00000000000..10a77215c47
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/pixels_test.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/rendering/pixels.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('pixelsApproximated', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ // Metric computation assumes that there is always a browser process.
+ model.getOrCreateProcess(0).getOrCreateThread(0).name = 'CrBrowserMain';
+
+ const compositor = model.getOrCreateProcess(1).getOrCreateThread(1);
+ compositor.name = 'Compositor';
+ compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'BenchmarkInstrumentation::ImplThreadRenderingStats',
+ start: 1, end: 1,
+ args: {
+ data: {
+ visible_content_area: 50,
+ approximated_visible_content_area: 8,
+ checkerboarded_visible_content_area: 3
+ }
+ }
+ }));
+ compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'BenchmarkInstrumentation::ImplThreadRenderingStats',
+ start: 2, end: 2,
+ args: {
+ data: {
+ visible_content_area: 25,
+ approximated_visible_content_area: 6,
+ checkerboarded_visible_content_area: 5
+ }
+ }
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addPixelsHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 10)]);
+
+ // The mean of 8/50 and 6/25 is 0.2.
+ let hist = histograms.getHistogramNamed('mean_pixels_approximated');
+ assert.closeTo(20, hist.min, 1e-6);
+ assert.closeTo(20, hist.max, 1e-6);
+ assert.closeTo(20, hist.average, 1e-6);
+
+ // The mean of 3/50 and 5/25 is 0.13.
+ hist = histograms.getHistogramNamed('mean_pixels_checkerboarded');
+ assert.closeTo(13, hist.min, 1e-6);
+ assert.closeTo(13, hist.max, 1e-6);
+ assert.closeTo(13, hist.average, 1e-6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html
new file mode 100644
index 00000000000..386bd444658
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains implementations of the following metrics.
+ *
+ * queueing_durations
+ * ==================
+ * This quantifies how out of sync the compositor and renderer threads are. It
+ * is the amount of wall time that elapses between a
+ * ScheduledActionSendBeginMainFrame event in the compositor thread and the
+ * corresponding BeginMainFrame event in the main thread.
+ *
+ * TODO(chiniforooshan): Does it make sense to just ignore data from OOPIF
+ * processes, like what we are doing here?
+ */
+tr.exportTo('tr.metrics.rendering', function() {
+ // Various tracing events.
+ const BEGIN_MAIN_FRAME_EVENT = 'ThreadProxy::BeginMainFrame';
+ const SEND_BEGIN_FRAME_EVENT =
+ 'ThreadProxy::ScheduledActionSendBeginMainFrame';
+
+ function getEventTimesByBeginFrameId_(thread, title, ranges) {
+ const out = new Map();
+ const slices = thread.sliceGroup;
+ for (const slice of slices.getDescendantEventsInSortedRanges(ranges)) {
+ if (slice.title !== title) continue;
+ const id = slice.args.begin_frame_id;
+ if (id === undefined) throw new Error('Event is missing begin_frame_id');
+ if (out.has(id)) throw new Error(`There must be exactly one ${title}`);
+ out.set(id, slice.start);
+ }
+ return out;
+ }
+
+ function addQueueingDurationHistograms(histograms, model, segments) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!chromeHelper) return;
+
+ let targetRenderers = chromeHelper.telemetryHelper.renderersWithIR;
+ if (targetRenderers.length === 0) {
+ targetRenderers = Object.values(chromeHelper.rendererHelpers);
+ }
+ const queueingDurations = [];
+ const ranges = segments.map(s => s.boundsRange);
+ for (const rendererHelper of targetRenderers) {
+ const mainThread = rendererHelper.mainThread;
+ const compositorThread = rendererHelper.compositorThread;
+ if (mainThread === undefined || compositorThread === undefined) continue;
+
+ const beginMainFrameTimes = getEventTimesByBeginFrameId_(
+ mainThread, BEGIN_MAIN_FRAME_EVENT, ranges);
+ const sendBeginFrameTimes = getEventTimesByBeginFrameId_(
+ compositorThread, SEND_BEGIN_FRAME_EVENT, ranges);
+ for (const [id, time] of sendBeginFrameTimes) {
+ queueingDurations.push(beginMainFrameTimes.get(id) - time);
+ }
+ }
+
+ histograms.createHistogram(
+ 'queueing_durations',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, queueingDurations, {
+ binBoundaries:
+ tr.v.HistogramBinBoundaries.createExponential(0.01, 2, 20),
+ summaryOptions: tr.metrics.rendering.SUMMARY_OPTIONS,
+ description: 'Time between ScheduledActionSendBeginMainFrame in ' +
+ 'the compositor thread and the corresponding ' +
+ 'BeginMainFrame in the main thread.'
+ });
+ }
+
+ return {
+ addQueueingDurationHistograms,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration_test.html
new file mode 100644
index 00000000000..2ca870810dd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/queueing_duration_test.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/rendering/queueing_duration.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('queueingDurations', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ // Metric computation assumes that there is always a browser process.
+ model.getOrCreateProcess(0).getOrCreateThread(0).name = 'CrBrowserMain';
+
+ const compositor = model.getOrCreateProcess(1).getOrCreateThread(1);
+ compositor.name = 'Compositor';
+ compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'ThreadProxy::ScheduledActionSendBeginMainFrame',
+ start: 3, end: 3,
+ args: { begin_frame_id: 2 }}));
+ compositor.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'ThreadProxy::ScheduledActionSendBeginMainFrame',
+ start: 4, end: 4,
+ args: { begin_frame_id: 1 }}));
+
+ const main = model.getOrCreateProcess(1).getOrCreateThread(0);
+ main.name = 'CrRendererMain';
+ main.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'ThreadProxy::BeginMainFrame',
+ start: 5, end: 5,
+ args: { begin_frame_id: 1 }}));
+ main.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'ThreadProxy::BeginMainFrame',
+ start: 6, end: 6,
+ args: { begin_frame_id: 2 }}));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.addQueueingDurationHistograms(
+ histograms, model, [new tr.model.um.Segment(0, 10)]);
+
+ const hist = histograms.getHistogramNamed('queueing_durations');
+ assert.closeTo(1, hist.min, 1e-6);
+ assert.closeTo(3, hist.max, 1e-6);
+ assert.closeTo(2, hist.average, 1e-6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html
new file mode 100644
index 00000000000..1024c9baa87
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/rendering/frame_time.html">
+<link rel="import" href="/tracing/metrics/rendering/latency.html">
+<link rel="import" href="/tracing/metrics/rendering/pipeline.html">
+<link rel="import" href="/tracing/metrics/rendering/pixels.html">
+<link rel="import" href="/tracing/metrics/rendering/queueing_duration.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.rendering', function() {
+ // Various tracing events.
+ const GESTURE_EVENT = 'SyntheticGestureController::running';
+
+ function renderingMetric(histograms, model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!chromeHelper) return;
+
+ const segments = chromeHelper.telemetryHelper.segments;
+ if (segments.length > 0) {
+ tr.metrics.rendering.addFrameTimeHistograms(histograms, model, segments);
+ tr.metrics.rendering.addLatencyHistograms(histograms, model, segments);
+ tr.metrics.rendering.addPipelineHistograms(histograms, model, segments);
+ tr.metrics.rendering.addPixelsHistograms(histograms, model, segments);
+ tr.metrics.rendering.addQueueingDurationHistograms(
+ histograms, model, segments);
+ }
+
+ const uiSegments = chromeHelper.telemetryHelper.uiSegments;
+ if (uiSegments.length > 0) {
+ tr.metrics.rendering.addUIFrameTimeHistograms(
+ histograms, model, chromeHelper.telemetryHelper.uiSegments);
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(renderingMetric, {
+ requiredCategories: ['benchmark', 'toplevel'],
+ });
+
+ return {
+ renderingMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html
new file mode 100644
index 00000000000..77e0a2d9dd1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/rendering/rendering_metric_test.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/rendering/rendering_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('renderingMetric_gestureIR', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const rendererMain = model.getOrCreateProcess(1).getOrCreateThread(0);
+ rendererMain.name = 'CrRendererMain';
+ rendererMain.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed(
+ 'Interaction.Gesture_LoadAction', 10, 10));
+
+ const browserMain = model.getOrCreateProcess(0).getOrCreateThread(0);
+ browserMain.name = 'CrBrowserMain';
+ browserMain.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed(
+ 'SyntheticGestureController::running', 0, 5));
+ browserMain.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed(
+ 'SyntheticGestureController::running', 10, 5));
+ // Add four swap buffer events, at times 1, 2, 11, 13, 16
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 1, end: 1 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 2, end: 2 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 11, end: 11 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 13, end: 13 }));
+ browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ { title: 'BenchmarkInstrumentation::DisplayRenderingStats',
+ start: 16, end: 16 }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.rendering.renderingMetric(histograms, model);
+
+ // The gesture interaction record should be adjusted to [10, 15]. So, the
+ // first two frames and the fifth frame are outside the interaction record
+ // and should be discarded. The remaining frames are 11 and 13 which result
+ // in a single frame time of 2 = 13 - 11.
+ const hist = histograms.getHistogramNamed('frame_times');
+ assert.closeTo(2, hist.min, 1e-6);
+ assert.closeTo(2, hist.max, 2e-6);
+ assert.closeTo(2, hist.average, 1e-6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/sample_exception_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/sample_exception_metric.html
new file mode 100644
index 00000000000..01dd58cdf9c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/sample_exception_metric.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ function sampleExceptionMetric(histograms, model) {
+ const hist = new tr.v.Histogram(
+ 'foo', tr.b.Unit.byName.sizeInBytes_smallerIsBetter);
+ hist.addSample(9);
+ hist.addSample(91, {bar: new tr.v.d.GenericSet([{hello: 42}])});
+
+ for (const expectation of model.userModel.expectations) {
+ if (expectation instanceof tr.model.um.ResponseExpectation) {
+ } else if (expectation instanceof tr.model.um.AnimationExpectation) {
+ } else if (expectation instanceof tr.model.um.IdleExpectation) {
+ } else if (expectation instanceof tr.model.um.LoadExpectation) {
+ }
+ }
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ for (const [pid, process] of Object.entries(model.processes)) {
+ }
+
+ histograms.addHistogram(hist);
+ throw new Error('There was an error');
+ }
+
+ tr.metrics.MetricRegistry.register(sampleExceptionMetric);
+
+ return {
+ sampleExceptionMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/sample_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/sample_metric.html
new file mode 100644
index 00000000000..4a8be86b0d7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/sample_metric.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ function sampleMetric(histograms, model) {
+ const hist = new tr.v.Histogram(
+ 'foo', tr.b.Unit.byName.sizeInBytes_smallerIsBetter);
+ hist.addSample(9);
+ hist.addSample(91, {bar: new tr.v.d.GenericSet([{hello: 42}])});
+
+ for (const expectation of model.userModel.expectations) {
+ if (expectation instanceof tr.model.um.ResponseExpectation) {
+ } else if (expectation instanceof tr.model.um.AnimationExpectation) {
+ } else if (expectation instanceof tr.model.um.IdleExpectation) {
+ } else if (expectation instanceof tr.model.um.LoadExpectation) {
+ }
+ }
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ for (const [pid, process] of Object.entries(model.processes)) {
+ }
+
+ histograms.addHistogram(hist);
+ }
+
+ tr.metrics.MetricRegistry.register(sampleMetric);
+
+ return {
+ sampleMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_helper.html b/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_helper.html
new file mode 100644
index 00000000000..fcc5c8df4ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_helper.html
@@ -0,0 +1,248 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview This file contains helper functions to identify
+ * FrameLoader::updateForSameDocumentNavigation events on all renderer
+ * processes and find their preceding navigation start events.
+ *_______________________________________________________________
+ * browser: InputLatency/NavigationControllerImpl::GoToIndex |
+ *----------------------------------------
+ * renderer: LatencyInfo.Flow
+ * WebViewImpl::handleInputEvent
+ * FrameLoader::updateForSameDocumentNavigation
+ *----------------------------------------------------
+ * FrameLoader::updateForSameDocumentNavigation is called when SPA
+ * in-app navigation occurs.
+ * For details about how SPA in-app navigation is defined and
+ * how it is found based on FrameLoader::updateForSameDocumentNavigation,
+ * read the doc: https://goo.gl/1I3tqd.
+ */
+tr.exportTo('tr.metrics', function() {
+ const HANDLE_INPUT_EVENT_TITLE = 'WebViewImpl::handleInputEvent';
+
+ /**
+ * @returns {Map.<tr.model.Slice, tr.model.Slice>} A map of the
+ * elements in eventsB which immediately precede events in eventsA.
+ * For instance:
+ * eventsA: A1 A2 A3 A4
+ * eventsB: B1 B2 B3 B4 B5
+ * output: {A1: B2, A2: B3, A3: B4, A4: B5}
+ * or
+ * eventsA: A1 A2 A3 A4
+ * eventsB: B1
+ * output: {A1: B1, A2: B1, A3: B1, A4: B1}
+ */
+ function findPrecedingEvents_(eventsA, eventsB) {
+ const events = new Map();
+ let eventsBIndex = 0;
+ for (const eventA of eventsA) {
+ for (; eventsBIndex < eventsB.length; eventsBIndex++) {
+ if (eventsB[eventsBIndex].start > eventA.start) break;
+ }
+ // If statement prevents the situation when eventsB is empty.
+ if (eventsBIndex > 0) {
+ events.set(eventA, eventsB[eventsBIndex - 1]);
+ }
+ }
+ return events;
+ }
+
+ /**
+ * @returns {Map.<tr.model.Slice, tr.model.Slice>} A map of
+ * the elements in eventsB which immediately follow events
+ * in eventsA.
+ * For instance:
+ * eventsA: A1 A2 A3 A4
+ * eventsB: B1 B2 B3 B4 B5
+ * output: {A1:B2, A2:B3, A3:B4, A4:B5}
+ * or
+ * eventsA: A1 A2 A3 A4
+ * eventsB: B1
+ * output: {A1:B1, A2:B1, A3:B1}
+ */
+ function findFollowingEvents_(eventsA, eventsB) {
+ const events = new Map();
+ let eventsBIndex = 0;
+ for (const eventA of eventsA) {
+ for (; eventsBIndex < eventsB.length; eventsBIndex++) {
+ if (eventsB[eventsBIndex].start >= eventA.start) break;
+ }
+ // If statement prevents the situation when eventsB is empty
+ // and when it reaches the end of loop.
+ if (eventsBIndex >= 0 && eventsBIndex < eventsB.length) {
+ events.set(eventA, eventsB[eventsBIndex]);
+ }
+ }
+ return events;
+ }
+
+ /**
+ * @return {Array.<tr.model.Slice>} An array of events that may
+ * be qualified as a SPA navigation start candidate such as
+ * WebViewImpl::handleInputEvent and NavigationControllerImpl::GoToIndex.
+ */
+ function getSpaNavigationStartCandidates_(rendererHelper, browserHelper) {
+ const isNavStartEvent = e => {
+ if (e.title === HANDLE_INPUT_EVENT_TITLE && e.args.type === 'MouseUp') {
+ return true;
+ }
+ return e.title === 'NavigationControllerImpl::GoToIndex';
+ };
+
+ return [
+ ...rendererHelper.mainThread.sliceGroup.getDescendantEvents(),
+ ...browserHelper.mainThread.sliceGroup.getDescendantEvents()
+ ].filter(isNavStartEvent);
+ }
+
+ /**
+ * @return {Array.<tr.model.Slice>} An array of SPA navigation events.
+ * A SPA navigation event indicates the happening of a SPA navigation.
+ */
+ function getSpaNavigationEvents_(rendererHelper) {
+ const isNavEvent = e => e.category === 'blink' &&
+ e.title === 'FrameLoader::updateForSameDocumentNavigation';
+
+ return [...rendererHelper.mainThread.sliceGroup.getDescendantEvents()]
+ .filter(isNavEvent);
+ }
+
+ /**
+ * @return {Array.<tr.model.AsyncSlice>} An array of InputLatency events from
+ * the browser main thread.
+ */
+ function getInputLatencyEvents_(browserHelper) {
+ const isInputLatencyEvent = e => e.title === 'InputLatency::MouseUp';
+
+ return browserHelper.getAllAsyncSlicesMatching(isInputLatencyEvent);
+ }
+
+ /**
+ * @return {Map.<number, tr.model.Slice>} A mapping of trace_id value
+ * in each InputLatency event to the respective InputLatency event itself.
+ */
+ function getInputLatencyEventByBindIdMap_(browserHelper) {
+ const inputLatencyEventByBindIdMap = new Map();
+ for (const event of getInputLatencyEvents_(browserHelper)) {
+ inputLatencyEventByBindIdMap.set(event.args.data.trace_id, event);
+ }
+ return inputLatencyEventByBindIdMap;
+ }
+
+ /**
+ * @returns {Map.<tr.model.Slice, tr.model.AsyncSlice>} A mapping
+ * from a FrameLoader update navigation slice to its respective
+ * navigation start event, which can be an InputLatency async
+ * slice or a NavigationControllerImpl::GoToIndex slice.
+ */
+ function getSpaNavigationEventToNavigationStartMap_(
+ rendererHelper, browserHelper) {
+ const mainThread = rendererHelper.mainThread;
+ const spaNavEvents = getSpaNavigationEvents_(rendererHelper);
+ const navStartCandidates = getSpaNavigationStartCandidates_(
+ rendererHelper, browserHelper).sort(tr.importer.compareEvents);
+ const spaNavEventToNavStartCandidateMap =
+ findPrecedingEvents_(spaNavEvents, navStartCandidates);
+
+ const inputLatencyEventByBindIdMap =
+ getInputLatencyEventByBindIdMap_(browserHelper);
+ const spaNavEventToNavStartEventMap = new Map();
+ for (const [spaNavEvent, navStartCandidate] of
+ spaNavEventToNavStartCandidateMap) {
+ if (navStartCandidate.title === HANDLE_INPUT_EVENT_TITLE) {
+ const inputLatencySlice = inputLatencyEventByBindIdMap.get(
+ Number(navStartCandidate.parentSlice.bindId));
+ if (inputLatencySlice) {
+ spaNavEventToNavStartEventMap.set(spaNavEvent, inputLatencySlice);
+ }
+ } else {
+ spaNavEventToNavStartEventMap.set(spaNavEvent, navStartCandidate);
+ }
+ }
+ return spaNavEventToNavStartEventMap;
+ }
+
+ /**
+ * @return {Array.<tr.model.Slice>} An array of first paint events.
+ */
+ function getFirstPaintEvents_(rendererHelper) {
+ const isFirstPaintEvent = e => e.category === 'blink' &&
+ e.title === 'PaintLayerCompositor::updateIfNeededRecursive';
+
+ return [...rendererHelper.mainThread.sliceGroup.getDescendantEvents()]
+ .filter(isFirstPaintEvent);
+ }
+
+ /**
+ * @returns {Map.<tr.model.Slice, tr.model.Slice>} A mapping
+ * from a FrameLoader update navigation slice to its respective
+ * first paint slice.
+ */
+ function getSpaNavigationEventToFirstPaintEventMap_(rendererHelper) {
+ const spaNavEvents = getSpaNavigationEvents_(
+ rendererHelper).sort(tr.importer.compareEvents);
+ const firstPaintEvents = getFirstPaintEvents_(
+ rendererHelper).sort(tr.importer.compareEvents);
+
+ return findFollowingEvents_(spaNavEvents, firstPaintEvents);
+ }
+
+ /**
+ * @typedef {NavStartCandidates}
+ * @property {tr.model.AsyncSlice} inputLatencyAsyncSlice
+ * @property {tr.model.Slice} goToIndexSlice
+ */
+
+ /**
+ * @typedef {SpaNavObject}
+ * @property {NavStartCandidates} navStartCandidates
+ * @property {tr.model.Slice} firstPaintEvent
+ * @property {string} url
+ */
+
+ /**
+ * @returns {Array.<SpaNavObject>}
+ */
+ function findSpaNavigationsOnRenderer(rendererHelper, browserHelper) {
+ const spaNavEventToNavStartMap =
+ getSpaNavigationEventToNavigationStartMap_(
+ rendererHelper, browserHelper);
+ const spaNavEventToFirstPaintEventMap =
+ getSpaNavigationEventToFirstPaintEventMap_(rendererHelper);
+ const spaNavigations = [];
+ for (const [spaNavEvent, navStartEvent] of
+ spaNavEventToNavStartMap) {
+ if (spaNavEventToFirstPaintEventMap.has(spaNavEvent)) {
+ const firstPaintEvent =
+ spaNavEventToFirstPaintEventMap.get(spaNavEvent);
+ const isNavStartAsyncSlice =
+ navStartEvent instanceof tr.model.AsyncSlice;
+ spaNavigations.push({
+ navStartCandidates: {
+ inputLatencyAsyncSlice:
+ isNavStartAsyncSlice ? navStartEvent : undefined,
+ goToIndexSlice: isNavStartAsyncSlice ? undefined : navStartEvent
+ },
+ firstPaintEvent,
+ url: spaNavEvent.args.url
+ });
+ }
+ }
+ return spaNavigations;
+ }
+
+ return {
+ findSpaNavigationsOnRenderer,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_helper_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_helper_test.html
new file mode 100644
index 00000000000..ae87c1834e7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_helper_test.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/spa_navigation_helper.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const RENDERER_PROCESS_ID = 1234;
+ const RENDERER_PROCESS_MAIN_THREAD_ID = 1;
+ const BROWSER_PROCESS_ID = 1;
+ const BROWSER_PROCESS_MAIN_THREAD_ID = 12;
+ const PAINT_UPDATE_TITLE =
+ 'PaintLayerCompositor::updateIfNeededRecursive';
+ const SPA_NAVIGATION_EVENT_TITLE =
+ 'FrameLoader::updateForSameDocumentNavigation';
+
+ function createChromeProcessesOnModel(model) {
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(
+ RENDERER_PROCESS_MAIN_THREAD_ID);
+ mainThread.name = 'CrRendererMain';
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const browserMainThread = browserProcess.getOrCreateThread(
+ BROWSER_PROCESS_MAIN_THREAD_ID);
+ browserMainThread.name = 'CrBrowserMain';
+ }
+
+ function addThreadSlice(model, title, timestamp, args) {
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(
+ RENDERER_PROCESS_MAIN_THREAD_ID);
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink',
+ title,
+ start: timestamp,
+ duration: 0.1,
+ args
+ }));
+ }
+
+ function addLatencyInfoFlowEvent(model, timestamp, bindId) {
+ const latencyInfoFlowSlice = tr.c.TestUtils.newSliceEx({
+ cat: 'input,benchmark',
+ title: 'LatencyInfo.Flow',
+ start: timestamp,
+ duration: 0.1,
+ bindId,
+ args: {step: 'handleInputEventMain'}
+ });
+ const handleInputEventSlice = tr.c.TestUtils.newSliceEx({
+ cat: 'blink,rail',
+ title: 'WebViewImpl::handleInputEvent',
+ start: timestamp + 1, // Assume handleInputEvent always delays 1ms.
+ duration: 0.1,
+ args: {type: 'MouseUp'}
+ });
+
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(
+ RENDERER_PROCESS_MAIN_THREAD_ID);
+
+ handleInputEventSlice.parentSlice = latencyInfoFlowSlice;
+ mainThread.sliceGroup.pushSlice(latencyInfoFlowSlice);
+ mainThread.sliceGroup.pushSlice(handleInputEventSlice);
+ }
+
+ function addInputLatencySlice(model, start, traceId) {
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const browserMainThread = browserProcess.getOrCreateThread(
+ BROWSER_PROCESS_MAIN_THREAD_ID);
+
+ browserMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'benchmark,latencyInfo,rail',
+ title: 'InputLatency::MouseUp',
+ start,
+ duration: 0.1,
+ args: {
+ data: {
+ trace_id: traceId
+ }
+ }
+ }));
+ }
+
+ function addGoToIndexSlice(model, timestamp) {
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const browserMainThread = browserProcess.getOrCreateThread(
+ BROWSER_PROCESS_MAIN_THREAD_ID);
+
+ browserMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'browser,navigation,benchmark',
+ title: 'NavigationControllerImpl::GoToIndex',
+ start: timestamp,
+ duration: 0.1
+ }));
+ }
+
+ function getSpaNavigations(model) {
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelpers = modelHelper.rendererHelpers;
+ const browserHelper = modelHelper.browserHelper;
+ let spaNavigations = [];
+ for (const rendererHelper of Object.values(rendererHelpers)) {
+ spaNavigations = spaNavigations.concat(
+ tr.metrics.findSpaNavigationsOnRenderer(
+ rendererHelper, browserHelper));
+ }
+ return spaNavigations;
+ }
+
+ test('findSpaNavigations_noSpaNavEvent', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addLatencyInfoFlowEvent(model, 75, '0x600000057');
+ addInputLatencySlice(model, 55, 25769803863);
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
+ });
+ const spaNavigations = getSpaNavigations(model);
+ assert.lengthOf(spaNavigations, 0);
+ });
+
+ test('findSpaNavigations_noLatencyInfoFlowEvent', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100);
+ addInputLatencySlice(model, 55, 25769803863);
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
+ });
+ const spaNavigations = getSpaNavigations(model);
+ assert.lengthOf(spaNavigations, 0);
+ });
+
+ test('findSpaNavigations_noNavStartEvent', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100);
+ addLatencyInfoFlowEvent(model, 75, '0x600000057');
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
+ });
+ const spaNavigations = getSpaNavigations(model);
+ assert.lengthOf(spaNavigations, 0);
+ });
+
+ test('findSpaNavigations_noFirstPaintEvent', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100);
+ addLatencyInfoFlowEvent(model, 75, '0x600000057');
+ addInputLatencySlice(model, 55, 25769803863);
+ });
+ const spaNavigations = getSpaNavigations(model);
+ assert.lengthOf(spaNavigations, 0);
+ });
+
+ test('findSpaNavigations_inputLatencyAsNavStart', function() {
+ const URL = 'https://11111';
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100,
+ {url: URL});
+ addLatencyInfoFlowEvent(model, 75, '0x600000057');
+ addInputLatencySlice(model, 55, 25769803863);
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
+ });
+ const spaNavigations = getSpaNavigations(model);
+ assert.lengthOf(spaNavigations, 1);
+ assert.strictEqual(
+ spaNavigations[0].navStartCandidates.inputLatencyAsyncSlice.start, 55);
+ assert.strictEqual(
+ spaNavigations[0].navStartCandidates.goToIndexSlice, undefined);
+ assert.strictEqual(spaNavigations[0].firstPaintEvent.start, 101);
+ assert.strictEqual(spaNavigations[0].url, URL);
+ });
+
+ test('findSpaNavigations_goToIndexAsNavStart', function() {
+ const URL = 'https://11111';
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100,
+ {url: URL});
+ addGoToIndexSlice(model, 55);
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
+ });
+ const spaNavigations = getSpaNavigations(model);
+ assert.lengthOf(spaNavigations, 1);
+ assert.strictEqual(
+ spaNavigations[0].navStartCandidates.goToIndexSlice.start, 55);
+ assert.strictEqual(
+ spaNavigations[0].navStartCandidates.inputLatencyAsyncSlice, undefined);
+ assert.strictEqual(spaNavigations[0].firstPaintEvent.start, 101);
+ assert.strictEqual(spaNavigations[0].url, URL);
+ });
+
+ test('findSpaNavigations_multipleSpaNavs', function() {
+ const URL1 = 'https://11111';
+ const URL2 = 'https://22222';
+ const URL3 = 'https://33333';
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 100,
+ {url: URL1});
+ addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 200,
+ {url: URL2});
+ addThreadSlice(model, SPA_NAVIGATION_EVENT_TITLE, 300,
+ {url: URL3});
+
+ addLatencyInfoFlowEvent(model, 75, '0x600000057');
+ addLatencyInfoFlowEvent(model, 175, '0x6000000c2');
+ addLatencyInfoFlowEvent(model, 275, '0x60000010d');
+
+ addInputLatencySlice(model, 55, 25769803863);
+ addGoToIndexSlice(model, 65);
+ addInputLatencySlice(model, 155, 25769803970);
+ addInputLatencySlice(model, 255, 25769804045);
+
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 101);
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 102);
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 201);
+ addThreadSlice(model, PAINT_UPDATE_TITLE, 301);
+ });
+ const spaNavigations = getSpaNavigations(model);
+ assert.lengthOf(spaNavigations, 3);
+ spaNavigations.sort((spa1, spa2) =>
+ spa1.navStartCandidates.inputLatencyAsyncSlice.start -
+ spa2.navStartCandidates.inputLatencyAsyncSlice.start);
+ assert.strictEqual(
+ spaNavigations[0].navStartCandidates.inputLatencyAsyncSlice.start, 55);
+ assert.strictEqual(
+ spaNavigations[1].navStartCandidates.inputLatencyAsyncSlice.start, 155);
+ assert.strictEqual(
+ spaNavigations[2].navStartCandidates.inputLatencyAsyncSlice.start, 255);
+
+ assert.strictEqual(
+ spaNavigations[0].navStartCandidates.goToIndexSlice, undefined);
+ assert.strictEqual(
+ spaNavigations[1].navStartCandidates.goToIndexSlice, undefined);
+ assert.strictEqual(
+ spaNavigations[2].navStartCandidates.goToIndexSlice, undefined);
+
+ assert.strictEqual(spaNavigations[0].firstPaintEvent.start, 101);
+ assert.strictEqual(spaNavigations[1].firstPaintEvent.start, 201);
+ assert.strictEqual(spaNavigations[2].firstPaintEvent.start, 301);
+
+ assert.strictEqual(spaNavigations[0].url, URL1);
+ assert.strictEqual(spaNavigations[1].url, URL2);
+ assert.strictEqual(spaNavigations[2].url, URL3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_metric.html
new file mode 100644
index 00000000000..f8d6bb537f6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_metric.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/spa_navigation_helper.html">
+<link rel="import" href="/tracing/metrics/system_health/breakdown_tree_helpers.html">
+<link rel="import" href="/tracing/metrics/system_health/loading_metric.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ const SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY =
+ tr.v.HistogramBinBoundaries.createExponential(1, 1000, 50);
+
+ /**
+ * This metric measures the duration between the input event
+ * causing a SPA navigation and the first paint event after it.
+ */
+ function spaNavigationMetric(histograms, model) {
+ const histogram = new tr.v.Histogram(
+ 'spaNavigationStartToFpDuration',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY);
+ histogram.description = 'Latency between the input event causing' +
+ ' a SPA navigation and the first paint event after it';
+ histogram.customizeSummaryOptions({
+ count: false,
+ sum: false,
+ });
+
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!modelHelper) {
+ // Chrome isn't present.
+ return;
+ }
+ const rendererHelpers = modelHelper.rendererHelpers;
+ if (!rendererHelpers) {
+ // We couldn't find any renderer processes.
+ return;
+ }
+ const browserHelper = modelHelper.browserHelper;
+ for (const rendererHelper of Object.values(rendererHelpers)) {
+ const spaNavigations = tr.metrics.findSpaNavigationsOnRenderer(
+ rendererHelper, browserHelper);
+ for (const spaNav of spaNavigations) {
+ let beginTs = 0;
+ if (spaNav.navStartCandidates.inputLatencyAsyncSlice) {
+ const beginData =
+ spaNav.navStartCandidates.inputLatencyAsyncSlice.args.data;
+ // TODO(sunjian): rename convertTimestampToModelTime to something like
+ // convertTraceEventTsToModelTs and get rid of the first parameter.
+ beginTs = model.convertTimestampToModelTime(
+ 'traceEventClock',
+ beginData.INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT.time);
+ } else {
+ beginTs = spaNav.navStartCandidates.goToIndexSlice.start;
+ }
+ const rangeOfInterest = tr.b.math.Range.fromExplicitRange(
+ beginTs, spaNav.firstPaintEvent.start);
+ const networkEvents = tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, rangeOfInterest);
+ const breakdownDict = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, rangeOfInterest);
+ const breakdownDiagnostic = new tr.v.d.Breakdown();
+ breakdownDiagnostic.colorScheme =
+ tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;
+ for (const label in breakdownDict) {
+ breakdownDiagnostic.set(label,
+ parseInt(breakdownDict[label].total * 1e3) / 1e3);
+ }
+ histogram.addSample(
+ rangeOfInterest.duration,
+ {
+ 'Breakdown of [navStart, firstPaint]': breakdownDiagnostic,
+ 'Start': new tr.v.d.RelatedEventSet(spaNav.navigationStart),
+ 'End': new tr.v.d.RelatedEventSet(spaNav.firstPaintEvent),
+ 'Navigation infos': new tr.v.d.GenericSet([{
+ url: spaNav.url,
+ pid: rendererHelper.pid,
+ navStart: beginTs,
+ firstPaint: spaNav.firstPaintEvent.start
+ }]),
+ });
+ }
+ }
+ histograms.addHistogram(histogram);
+ }
+
+ tr.metrics.MetricRegistry.register(spaNavigationMetric);
+
+ return {
+ spaNavigationMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_metric_test.html
new file mode 100644
index 00000000000..44c38038d3b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/spa_navigation_metric_test.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/spa_navigation_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const RENDERER_PROCESS_ID = 1234;
+ const RENDERER_PROCESS_MAIN_THREAD_ID = 1;
+ const BROWSER_PROCESS_ID = 1;
+ const BROWSER_PROCESS_MAIN_THREAD_ID = 12;
+ const SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION =
+ 'spaNavigationStartToFpDuration';
+
+ function createChromeProcessesOnModel(model) {
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(
+ RENDERER_PROCESS_MAIN_THREAD_ID);
+ mainThread.name = 'CrRendererMain';
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const browserMainThread = browserProcess.getOrCreateThread(
+ BROWSER_PROCESS_MAIN_THREAD_ID);
+ browserMainThread.name = 'CrBrowserMain';
+ }
+
+ function addSpaNavigationEvent(model, timestamp, args) {
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(
+ RENDERER_PROCESS_MAIN_THREAD_ID);
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink',
+ title: 'FrameLoader::updateForSameDocumentNavigation',
+ start: timestamp,
+ duration: 0.1,
+ args
+ }));
+ }
+
+ function addGoToIndexSlice(model, timestamp) {
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const browserMainThread = browserProcess.getOrCreateThread(
+ BROWSER_PROCESS_MAIN_THREAD_ID);
+ browserMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'browser,navigation,benchmark',
+ title: 'NavigationControllerImpl::GoToIndex',
+ start: timestamp,
+ duration: 0.1
+ }));
+ }
+
+ function addFirstPaintSlice(model, timestamp) {
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(
+ RENDERER_PROCESS_MAIN_THREAD_ID);
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink',
+ title: 'PaintLayerCompositor::updateIfNeededRecursive',
+ start: timestamp,
+ duration: 0.1
+ }));
+ }
+
+ function addInputLatencyRelatedSlices(model, timestamp) {
+ const latencyInfoFlowSlice = tr.c.TestUtils.newSliceEx({
+ cat: 'input,benchmark',
+ title: 'LatencyInfo.Flow',
+ start: timestamp - 2,
+ duration: 0.1,
+ bindId: '0x600000057',
+ args: {step: 'handleInputEventMain'}
+ });
+ const handleInputEventSlice = tr.c.TestUtils.newSliceEx({
+ cat: 'blink,rail',
+ title: 'WebViewImpl::handleInputEvent',
+ start: timestamp - 1, // Assume handleInputEvent always delays 1ms.
+ duration: 0.1,
+ args: {type: 'MouseUp'}
+ });
+
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(
+ RENDERER_PROCESS_MAIN_THREAD_ID);
+
+ handleInputEventSlice.parentSlice = latencyInfoFlowSlice;
+ mainThread.sliceGroup.pushSlice(latencyInfoFlowSlice);
+ mainThread.sliceGroup.pushSlice(handleInputEventSlice);
+
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const browserMainThread = browserProcess.getOrCreateThread(
+ BROWSER_PROCESS_MAIN_THREAD_ID);
+ browserMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'benchmark,latencyInfo,rail',
+ title: 'InputLatency::MouseUp',
+ start: timestamp - 3,
+ duration: 0.1,
+ args: {
+ data: {
+ trace_id: 25769803863,
+ INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT: {
+ time: timestamp - 3 + 0.1
+ }
+ }
+ }
+ }));
+ }
+
+ function getHistogramNamed(name, model) {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.spaNavigationMetric(histograms, model);
+ const spaNavigationStartToFpDurationHist = histograms.getHistogramNamed(
+ name);
+ return spaNavigationStartToFpDurationHist;
+ }
+
+ test('spaNavStartToFirstPaintDuration_noChromeProcess', function() {
+ const model = tr.c.TestUtils.newModel();
+ const histogram = getHistogramNamed(
+ SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION, model);
+ assert(!histogram);
+ });
+
+ test('spaNavStartToFirstPaintDuration_noSpaNavStart', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addSpaNavigationEvent(model, 100);
+ addFirstPaintSlice(model, 101);
+ });
+ const histogram = getHistogramNamed(
+ SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION, model);
+ assert.strictEqual(0, histogram.numValues);
+ });
+
+ test('spaNavStartToFirstPaintDuration_noFirstPaint', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addInputLatencyRelatedSlices(model, 99);
+ addSpaNavigationEvent(model, 100);
+ });
+ const histogram = getHistogramNamed(
+ SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION, model);
+ assert.strictEqual(0, histogram.numValues);
+ });
+
+ test('spaNavStartToFirstPaintDuration_inputLatencyAsNavStart', function() {
+ const URL = 'https://11111';
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addInputLatencyRelatedSlices(model, 99);
+ addSpaNavigationEvent(model, 100, {url: URL});
+ addFirstPaintSlice(model, 101);
+ });
+ const histogram = getHistogramNamed(
+ SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION, model);
+ assert.strictEqual(1, histogram.running.count);
+ const navStartTs = model.convertTimestampToModelTime(
+ 'traceEventClock', 99 - 3 + 0.1);
+ const expectedDuration = 101 - navStartTs;
+ assert.closeTo(expectedDuration, histogram.running.sum, 0.5);
+
+ const binsWithSampleDiagnosticMaps =
+ histogram.allBins.filter(bin => bin.diagnosticMaps.length > 0);
+ const diagnostic = tr.b.getOnlyElement(binsWithSampleDiagnosticMaps[0]
+ .diagnosticMaps[0].get('Navigation infos'));
+ assert.strictEqual(diagnostic.url, URL);
+ assert.strictEqual(diagnostic.pid, RENDERER_PROCESS_ID);
+ assert.strictEqual(diagnostic.navStart, navStartTs);
+ assert.strictEqual(diagnostic.firstPaint, 101);
+ });
+
+ test('spaNavStartToFirstPaintDuration_goToIndexAsNavStart', function() {
+ const URL = 'https://11111';
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addGoToIndexSlice(model, 99);
+ addSpaNavigationEvent(model, 100, {url: URL});
+ addFirstPaintSlice(model, 101);
+ });
+ const histogram = getHistogramNamed(
+ SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION, model);
+ assert.strictEqual(1, histogram.running.count);
+ const expectedDuration = 101 - 99;
+ assert.closeTo(expectedDuration, histogram.running.sum, 0.5);
+
+ const binsWithSampleDiagnosticMaps =
+ histogram.allBins.filter(bin => bin.diagnosticMaps.length > 0);
+ const diagnostic = tr.b.getOnlyElement(binsWithSampleDiagnosticMaps[0]
+ .diagnosticMaps[0].get('Navigation infos'));
+ assert.strictEqual(diagnostic.url, URL);
+ assert.strictEqual(diagnostic.pid, RENDERER_PROCESS_ID);
+ assert.strictEqual(diagnostic.navStart, 99);
+ assert.strictEqual(diagnostic.firstPaint, 101);
+ });
+
+ test('spaNavStartToFirstPaintDuration_multipleSpaNavs', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ createChromeProcessesOnModel(model);
+ addInputLatencyRelatedSlices(model, 99);
+ addSpaNavigationEvent(model, 100);
+ addFirstPaintSlice(model, 101);
+
+ addInputLatencyRelatedSlices(model, 198);
+ addSpaNavigationEvent(model, 200);
+ addFirstPaintSlice(model, 201);
+
+ addInputLatencyRelatedSlices(model, 297);
+ addSpaNavigationEvent(model, 300);
+ addFirstPaintSlice(model, 301);
+ });
+ const histogram = getHistogramNamed(
+ SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION, model);
+ assert.strictEqual(3, histogram.running.count);
+ const expectedDuration1 = 101 - model.convertTimestampToModelTime(
+ 'traceEventClock', 99 - 3 + 0.1);
+ const expectedDuration2 = 201 - model.convertTimestampToModelTime(
+ 'traceEventClock', 198 - 3 + 0.1);
+ const expectedDuration3 = 301 - model.convertTimestampToModelTime(
+ 'traceEventClock', 297 - 3 + 0.1);
+ assert.closeTo(expectedDuration1 + expectedDuration2 + expectedDuration3,
+ histogram.running.sum, 0.5);
+ assert.closeTo(expectedDuration3, histogram.running.max, 0.5);
+ assert.closeTo(expectedDuration1, histogram.running.min, 0.5);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers.html
new file mode 100644
index 00000000000..4bbe2a694f4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers.html
@@ -0,0 +1,275 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/category_util.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ /**
+ * Returns the total self time of |event| within |rangeOfInterest|. Total self
+ * time is computed by finding time ranges that do not contain a descendant
+ * slice. Example:
+ *
+ * [ A ]
+ * | [ B ] [ C ] |
+ * | | [ D ] | | | |
+ * | | | | | |
+ * v v v v v v
+ * Ts : 0 50 80 100 150 180 200
+ * RoI : [ ]
+ *
+ * Total self time for A within |rangeOfInterest| is 100 - 30 = 70.
+ *
+ * @param {!tr.b.Event} event
+ * @param {!tr.b.math.Range} rangeOfInterest
+ * @return {number}
+ */
+ function getWallClockSelfTime_(event, rangeOfInterest) {
+ if (event.duration === 0) return 0;
+
+ const selfTimeRanges = [rangeOfInterest.findIntersection(event.range)];
+ for (const subSlice of event.subSlices) {
+ if (selfTimeRanges.length === 0) return 0;
+
+ const lastRange = selfTimeRanges.pop();
+ selfTimeRanges.push(
+ ...tr.b.math.Range.findDifference(lastRange, subSlice.range));
+ }
+
+ return tr.b.math.Statistics.sum(selfTimeRanges, r => r.duration);
+ }
+
+ /**
+ * Returns the CPU self time of |event| within |rangeOfInterest|. CPU self
+ * time of a slice is assumed to be evenly distributed over the wall clock
+ * self time ranges of the slice.
+ *
+ * @param {!tr.b.Event} event
+ * @param {!tr.b.math.Range} rangeOfInterest
+ * @return {number}
+ */
+ function getCPUSelfTime_(event, rangeOfInterest) {
+ if (event.duration === 0 || event.selfTime === 0) return 0;
+ if (event.cpuSelfTime === undefined) return 0;
+ const cpuTimeDensity = event.cpuSelfTime / event.selfTime;
+ return getWallClockSelfTime_(event, rangeOfInterest) * cpuTimeDensity;
+ }
+
+ /**
+ * @callback getEventAttributeCallback
+ * @param {!tr.b.Event} event The event to read an attribute from.
+ * @return {number} The value of the attribute.
+ */
+
+ /**
+ * Generate a breakdown tree from all slices of |mainThread| in
+ * |rangeOfInterest|. The callback function |getEventSelfTime| specify how to
+ * get self time from a given event.
+ *
+ * @param {!tr.model.Thread} mainThread
+ * @param {!tr.b.math.Range} rangeOfInterest
+ * @callback {getEventAttributeCallback} getEventSelfTime
+ * @return {Object.<string, Object>} A time breakdown object whose keys are
+ * Chrome userfriendly title & values are an object that show the total spent
+ * in |rangeOfInterest|, and the list of event labels of the
+ * group and their total time in |rangeOfInterest|.
+ *
+ * Example:
+ * {
+ * layout: {
+ * total: 100,
+ * events: {'FrameView::performPreLayoutTasks': 20,..}},
+ * v8_runtime: {
+ * total: 500,
+ * events: {'String::NewExternalTwoByte': 0.5,..}},
+ * ...
+ * }
+ */
+ function generateTimeBreakdownTree(mainThread, rangeOfInterest,
+ getEventSelfTime) {
+ if (mainThread === null) return;
+ const breakdownTree = {};
+ for (const title of
+ tr.e.chrome.ChromeUserFriendlyCategoryDriver.ALL_TITLES) {
+ breakdownTree[title] = {total: 0, events: {}};
+ }
+ // We do not look at async slices here.
+ for (const event of mainThread.sliceGroup.childEvents()) {
+ if (!rangeOfInterest.intersectsRangeExclusive(event.range)) continue;
+ const eventSelfTime = getEventSelfTime(event, rangeOfInterest);
+ const title =
+ tr.e.chrome.ChromeUserFriendlyCategoryDriver.fromEvent(event);
+
+ breakdownTree[title].total += eventSelfTime;
+ if (breakdownTree[title].events[event.title] === undefined) {
+ breakdownTree[title].events[event.title] = 0;
+ }
+ breakdownTree[title].events[event.title] +=
+ eventSelfTime;
+
+ let timeIntersectionRatio = 0;
+ if (event.duration > 0) {
+ timeIntersectionRatio =
+ rangeOfInterest.findExplicitIntersectionDuration(
+ event.start, event.end) / event.duration;
+ }
+
+ // TODO(#3846): v8_runtime is being double counted.
+ // TODO(#3846): v8_runtime slice name is wrong. It's 'stats'.
+ // TODO(#4296): v8_runtime should not be added for cpu time.
+ const v8Runtime = event.args['runtime-call-stat'];
+ if (v8Runtime !== undefined) {
+ const v8RuntimeObject = JSON.parse(v8Runtime);
+ for (const runtimeCall in v8RuntimeObject) {
+ // When the V8 Runtime Object contains 2 values, the 2nd value
+ // always represents the V8 Runtime duration.
+ if (v8RuntimeObject[runtimeCall].length === 2) {
+ if (breakdownTree.v8_runtime.events[runtimeCall] === undefined) {
+ breakdownTree.v8_runtime.events[runtimeCall] = 0;
+ }
+ const runtimeTime = tr.b.Unit.timestampFromUs(
+ v8RuntimeObject[runtimeCall][1] * timeIntersectionRatio);
+ breakdownTree.v8_runtime.total += runtimeTime;
+ breakdownTree.v8_runtime.events[runtimeCall] += runtimeTime;
+ }
+ }
+ }
+ }
+ return breakdownTree;
+ }
+
+ /**
+ * Adds 'blocked_on_network' and 'idle' to the |breakdownTree| that has been
+ * generated by |generateTimeBreakdownTree|. Taking into account the
+ * |networkEvents|, this function is able to distinguish between these two
+ * types of cpu idle time during the range |rangeOfInterest| not used by
+ * events of the main thread |mainThreadEvents|.
+ *
+ * @param {!Object.<string, Object>} breakdownTree The breakdownTree that has
+ * been generated by |generateTimeBreakdownTree|.
+ * @param {!tr.b.Event} mainThreadEvents The top level events of the main
+ * thread.
+ * @param {!tr.b.Event} networkEvents The network events in the renderer.
+ * @param {!tr.b.math.Range} rangeOfInterest The range for which
+ * |breakdownTree| is calculated.
+ */
+ function addIdleAndBlockByNetworkBreakdown_(breakdownTree, mainThreadEvents,
+ networkEvents, rangeOfInterest) {
+ const mainThreadEventRanges = tr.b.math.convertEventsToRanges(
+ mainThreadEvents);
+ const networkEventRanges = tr.b.math.convertEventsToRanges(
+ networkEvents);
+ const eventRanges = mainThreadEventRanges.concat(networkEventRanges);
+ const idleRanges =
+ tr.b.math.findEmptyRangesBetweenRanges(eventRanges, rangeOfInterest);
+ const totalFreeDuration = tr.b.math.Statistics.sum(idleRanges,
+ range => range.duration);
+ breakdownTree.idle = {total: totalFreeDuration, events: {}};
+
+ let totalBlockedDuration = rangeOfInterest.duration;
+ for (const [title, component] of Object.entries(breakdownTree)) {
+ // v8_runtime is a subcategory of script_execute.
+ // See github.com/catapult-project/catapult/commit/f3881d commit message.
+ // TODO(#2572) Make user friendly category hierarchy friend so this is not
+ // needed.
+ if (title === 'v8_runtime') continue;
+ totalBlockedDuration -= component.total;
+ }
+
+ breakdownTree.blocked_on_network = {
+ // Clamp breakdown at 0 to prevent negative values.
+ // TODO(#4299): Since we do not explicitly prevent overlapping slices on
+ // the same thread, slices can end up with negative wall clock self time
+ // and thus breakdown values can be negative. If we can prevent
+ // overlapping slices in the model, we can do this clamping for very small
+ // (e.g. < -0.1) values, accounting only for floating point errors, and
+ // fail loudly otherwise.
+ total: Math.max(totalBlockedDuration, 0),
+ events: {}
+ };
+ }
+
+ /**
+ * Generate a breakdown that attributes where wall clock time goes in
+ * |rangeOfInterest| on the renderer thread.
+ *
+ * @param {!tr.model.Thread} mainThread
+ * @param {!tr.b.math.Range} rangeOfInterest
+ * @return {Object.<string, Object>} A time breakdown object whose keys are
+ * Chrome userfriendly titles & values are an object that shows the total
+ * wall clock time spent in |rangeOfInterest|, and the list of event
+ * labels of the group and their total wall clock time in |rangeOfInterest|.
+ *
+ * Example:
+ * {
+ * layout: {
+ * total: 100,
+ * events: {'FrameView::performPreLayoutTasks': 20,..}},
+ * v8_runtime: {
+ * total: 500,
+ * events: {'String::NewExternalTwoByte': 0.5,..}},
+ * ...
+ * }
+ */
+ function generateWallClockTimeBreakdownTree(
+ mainThread, networkEvents, rangeOfInterest) {
+ const breakdownTree = generateTimeBreakdownTree(
+ mainThread, rangeOfInterest, getWallClockSelfTime_);
+ const mainThreadEventsInRange = tr.model.helpers.getSlicesIntersectingRange(
+ rangeOfInterest, mainThread.sliceGroup.topLevelSlices);
+ addIdleAndBlockByNetworkBreakdown_(
+ breakdownTree, mainThreadEventsInRange, networkEvents, rangeOfInterest);
+ return breakdownTree;
+ }
+
+ /**
+ * Generate a breakdown that attributes where CPU time goes in
+ * |rangeOfInterest| on the renderer thread.
+ *
+ * Due to approximations, it is possible for breakdowns to not add up to total
+ * CPU time in |rangeOfInterest|. Note that |rangeOfInterest| is a range of
+ * wall times, not CPU time.
+ *
+ * @param {!tr.model.Thread} mainThread
+ * @param {!tr.b.math.Range} rangeOfInterest
+ * @return {Object.<string, Object>} A time breakdown object whose keys are
+ * Chrome userfriendly titles & values are an object that shows the total
+ * CPU time spent in |rangeOfInterestCpuTime|, and the list of event labels
+ * of the group and their total durations in |rangeOfInterestCpuTime|.
+ *
+ * Example:
+ * {
+ * layout: {
+ * total: 100,
+ * events: {'FrameView::performPreLayoutTasks': 20,..}},
+ * v8_runtime: {
+ * total: 500,
+ * events: {'String::NewExternalTwoByte': 0.5,..}},
+ * ...
+ * }
+ */
+ function generateCpuTimeBreakdownTree(mainThread, rangeOfInterest) {
+ return generateTimeBreakdownTree(mainThread, rangeOfInterest,
+ getCPUSelfTime_);
+ }
+
+ return {
+ generateTimeBreakdownTree,
+ generateWallClockTimeBreakdownTree,
+ generateCpuTimeBreakdownTree,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html
new file mode 100644
index 00000000000..883c915c07f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/breakdown_tree_helpers_test.html
@@ -0,0 +1,337 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/system_health/loading_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const rendererPid = 12345;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const rendererProcess = model.getOrCreateProcess(rendererPid);
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'CrRendererMain';
+
+ // Our main thread looks like:
+ //
+ // [ parseHTML ] [ layout ] [ V8.Exec ]
+ // | [ V8.Exec ] | | | | [ layout ] |
+ // | | | | | | | | | |
+ // | | | | | | | | | |
+ // v v v v v v v v v v
+ // Ts: 200 250 300 400 450 550 570 600 620 650
+ // Cpu:1160 1200 1240 1320 1360 1440 1456 1480 1496 1520
+
+ // Add layout categories
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink',
+ title: 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser',
+ start: 200,
+ duration: 200,
+ cpuStart: 1160,
+ cpuDuration: 160,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'devtools.timeline',
+ title: 'Script',
+ start: 250,
+ duration: 50,
+ cpuStart: 1200,
+ cpuDuration: 40,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ start: 250,
+ duration: 50,
+ args: {'runtime-call-stat': '{"ICMiss": [3, 150], "GC": [10, 60]}'},
+ cpuStart: 1200,
+ cpuDuration: 40,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink',
+ title: 'LocalFrameView::layout',
+ start: 450,
+ duration: 100,
+ cpuStart: 1360,
+ cpuDuration: 80,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ start: 570,
+ duration: 80,
+ args: {'runtime-call-stat': '{"DeOptimize": [1, 42], "GC": [3, 50]}'},
+ cpuStart: 1456,
+ cpuDuration: 64,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink',
+ title: 'WebViewImpl::updateAllLifecyclePhases',
+ start: 600,
+ duration: 20,
+ cpuStart: 1480,
+ cpuDuration: 16,
+ }));
+ });
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ const rendererHelper = chromeHelper.rendererHelpers[rendererPid];
+
+ test('testWallClockTimeBreakdownNoIntersectingBoundary', function() {
+ const rangeOfInterest = tr.b.math.Range.fromExplicitRange(0, 1000);
+ const networkEvents = tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, rangeOfInterest);
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, rangeOfInterest);
+ assert.deepEqual({
+ total: 150,
+ events: {
+ 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser': 150
+ }
+ }, breakdownTree.parseHTML);
+ assert.deepEqual({
+ total: 120,
+ events: {
+ 'LocalFrameView::layout': 100,
+ 'WebViewImpl::updateAllLifecyclePhases': 20,
+ }
+ }, breakdownTree.layout);
+ assert.deepEqual({
+ total: 110,
+ events: {
+ 'V8.Execute': 110,
+ }
+ }, breakdownTree.script_execute);
+ assert.deepEqual({
+ total: 0.302,
+ events: {
+ 'DeOptimize': 0.042,
+ 'GC': 0.11,
+ 'ICMiss': 0.15,
+ }
+ }, breakdownTree.v8_runtime);
+ });
+
+ test('testWallClockTimeBreakdownIntersectingBoundary', function() {
+ // Our main thread looks like:
+ //
+ // [ parseHTML ] [ layout ] [ V8.Exec ]
+ // | [ V8.Exec ] | | | | [ layout ] |
+ // | | | | | | | | | |
+ // | | | | | | | | | |
+ // v v v v v v v v v v
+ // Ts: 200 250 300 400 450 550 570 600 620 650
+ // | |
+ // 275 610
+ const rangeOfInterest = tr.b.math.Range.fromExplicitRange(275, 610);
+ const networkEvents = tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, rangeOfInterest);
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, rangeOfInterest);
+ assert.deepEqual({
+ total: 100,
+ events: {
+ 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser': 100
+ }
+ }, breakdownTree.parseHTML);
+ assert.deepEqual({
+ total: 110,
+ events: {
+ 'LocalFrameView::layout': 100,
+ 'WebViewImpl::updateAllLifecyclePhases': 10,
+ }
+ }, breakdownTree.layout);
+ assert.deepEqual({
+ total: 55,
+ events: {
+ 'V8.Execute': 55,
+ }
+ }, breakdownTree.script_execute);
+ assert.deepEqual({
+ total: 0.151,
+ events: {
+ 'DeOptimize': 0.021,
+ 'GC': 0.055,
+ 'ICMiss': 0.075,
+ }
+ }, breakdownTree.v8_runtime);
+ });
+
+ test('testCpuTimeBreakdownNoIntersectingBoundary', function() {
+ const rangeOfInterest = tr.b.math.Range.fromExplicitRange(100, 800);
+ const breakdownTree = tr.metrics.sh.generateCpuTimeBreakdownTree(
+ rendererHelper.mainThread,
+ rangeOfInterest);
+ assert.deepEqual({
+ total: 120,
+ events: {
+ 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser': 120
+ }
+ }, breakdownTree.parseHTML);
+ assert.deepEqual({
+ total: 96,
+ events: {
+ 'LocalFrameView::layout': 80,
+ 'WebViewImpl::updateAllLifecyclePhases': 16,
+ }
+ }, breakdownTree.layout);
+ assert.deepEqual({
+ total: 88,
+ events: {
+ 'V8.Execute': 88,
+ }
+ }, breakdownTree.script_execute);
+ assert.deepEqual({
+ total: 0.302,
+ events: {
+ 'DeOptimize': 0.042,
+ 'GC': 0.11,
+ 'ICMiss': 0.15,
+ }
+ }, breakdownTree.v8_runtime);
+ });
+
+ test('testCpuTimeBreakdownIntersectingBoundary', function() {
+ // Our main thread looks like:
+ //
+ // [ parseHTML ] [ layout ] [ V8.Exec ]
+ // | [ V8.Exec ] | | | | [ layout ] |
+ // | | | | | | | | | |
+ // | | | | | | | | | |
+ // v v v v v v v v v v
+ // Ts: 200 250 300 400 450 550 570 600 620 650
+ // Cpu:1160 1200 1240 1320 1360 1440 1456 1480 1496 1520
+ // [ ]
+ // Ts RoI 275 610
+ const rangeOfInterest = tr.b.math.Range.fromExplicitRange(275, 610);
+ const breakdownTree = tr.metrics.sh.generateCpuTimeBreakdownTree(
+ rendererHelper.mainThread,
+ rangeOfInterest);
+ assert.deepEqual({
+ total: 80,
+ events: {
+ 'HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser': 80
+ }
+ }, breakdownTree.parseHTML);
+ assert.deepEqual({
+ total: 88,
+ events: {
+ 'LocalFrameView::layout': 80,
+ 'WebViewImpl::updateAllLifecyclePhases': 8,
+ }
+ }, breakdownTree.layout);
+ assert.deepEqual({
+ total: 44,
+ events: {
+ 'V8.Execute': 44,
+ }
+ }, breakdownTree.script_execute);
+ assert.deepEqual({
+ total: 0.151,
+ events: {
+ 'DeOptimize': 0.021,
+ 'GC': 0.055,
+ 'ICMiss': 0.075
+ }
+ }, breakdownTree.v8_runtime);
+ });
+
+ function createNetworkEvent(start, end, cat) {
+ return tr.c.TestUtils.newAsyncSliceEx({
+ cat,
+ title: 'network events',
+ start,
+ duration: end - start,
+ });
+ }
+
+ test('testBlockedOnNetwork_onlyNetEvent', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ const mainThread = model.getOrCreateProcess(0)
+ .getOrCreateThread(0);
+ mainThread.name = 'CrRendererMain';
+ const networkEvent = createNetworkEvent(100, 200, 'net');
+ mainThread.asyncSliceGroup.push(networkEvent);
+ });
+ const rendererHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper)
+ .rendererHelpers[0];
+ const rangeOfInterest = tr.b.math.Range.fromExplicitRange(0, 150);
+ const networkEvents = tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, rangeOfInterest);
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, rangeOfInterest);
+ assert.strictEqual(breakdownTree.blocked_on_network.total, 50);
+ assert.strictEqual(breakdownTree.idle.total, 100);
+ });
+
+ test('testBlockedOnNetwork_netEventAndMainThreadEvent', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ const mainThread = model.getOrCreateProcess(0)
+ .getOrCreateThread(0);
+ mainThread.name = 'CrRendererMain';
+ const networkEvent = createNetworkEvent(100, 200, 'net');
+ mainThread.asyncSliceGroup.push(networkEvent);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink',
+ title: 'LocalFrameView::layout',
+ start: 160,
+ duration: 140,
+ }));
+ });
+ const rendererHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper)
+ .rendererHelpers[0];
+ const rangeOfInterest = tr.b.math.Range.fromExplicitRange(150, 320);
+ const networkEvents = tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, rangeOfInterest);
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, rangeOfInterest);
+ assert.strictEqual(breakdownTree.layout.total, 140);
+ assert.strictEqual(breakdownTree.blocked_on_network.total, 10);
+ assert.strictEqual(breakdownTree.idle.total, 20);
+ });
+
+ test('testBlockedOnNetwork_rangeEmpty', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ const mainThread = model.getOrCreateProcess(0)
+ .getOrCreateThread(0);
+ mainThread.name = 'CrRendererMain';
+ const networkEvent = createNetworkEvent(100, 200, 'net');
+ mainThread.asyncSliceGroup.push(networkEvent);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink',
+ title: 'FrameView::layout',
+ start: 160,
+ duration: 140,
+ }));
+ });
+ const rendererHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper)
+ .rendererHelpers[0];
+ const rangeOfInterest = new tr.b.math.Range();
+ const networkEvents = tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, rangeOfInterest);
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, rangeOfInterest);
+ assert.strictEqual(breakdownTree.layout.total, 0);
+ assert.strictEqual(breakdownTree.blocked_on_network.total, 0);
+ assert.strictEqual(breakdownTree.idle.total, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/clock_sync_latency_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/clock_sync_latency_metric.html
new file mode 100644
index 00000000000..8493e899025
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/clock_sync_latency_metric.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ // Bin boundaries for clock sync latency. 0-20 ms with 0.2 ms bins.
+ // 20 ms is a good upper limit because the highest latencies we've seen are
+ // around 10-15 ms, and we expect average latency to go down as we improve
+ // the clock sync mechanism.
+ const LATENCY_BOUNDS = tr.v.HistogramBinBoundaries.createLinear(0, 20, 100);
+
+ function clockSyncLatencyMetric(values, model) {
+ const domains = Array.from(model.clockSyncManager.domainsSeen).sort();
+ for (let i = 0; i < domains.length; i++) {
+ for (let j = i + 1; j < domains.length; j++) {
+ const latency = model.clockSyncManager.getTimeTransformerError(
+ domains[i], domains[j]);
+ const hist = new tr.v.Histogram('clock_sync_latency_' +
+ domains[i].toLowerCase() + '_to_' + domains[j].toLowerCase(),
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, LATENCY_BOUNDS);
+ hist.customizeSummaryOptions({
+ avg: true,
+ count: false,
+ max: false,
+ min: false,
+ std: false,
+ sum: false,
+ });
+ hist.description = 'Clock sync latency for domain ' + domains[i] +
+ ' to domain ' + domains[j];
+ hist.addSample(latency);
+ values.addHistogram(hist);
+ }
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(clockSyncLatencyMetric);
+
+ return {
+ clockSyncLatencyMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/clock_sync_latency_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/clock_sync_latency_metric_test.html
new file mode 100644
index 00000000000..27b5371763e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/clock_sync_latency_metric_test.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/system_health/clock_sync_latency_metric.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('clockSyncLatencyMetric', function() {
+ const model = new tr.Model();
+ model.clockSyncManager.addClockSyncMarker(
+ tr.model.ClockDomainId.TELEMETRY, 'ID01', 1.0, 4.0);
+ model.clockSyncManager.addClockSyncMarker(
+ tr.model.ClockDomainId.TELEMETRY, 'ID02', 2.0, 8.0);
+ model.clockSyncManager.addClockSyncMarker(
+ tr.model.ClockDomainId.BATTOR, 'ID01', 2.5);
+ model.clockSyncManager.addClockSyncMarker(
+ tr.model.ClockDomainId.WIN_QPC, 'ID02', 5.0);
+
+ const battorToWinQpcName = 'clock_sync_latency_' +
+ tr.model.ClockDomainId.BATTOR.toLowerCase() + '_to_' +
+ tr.model.ClockDomainId.WIN_QPC.toLowerCase();
+ const winQpcToTelemetryName = 'clock_sync_latency_' +
+ tr.model.ClockDomainId.TELEMETRY.toLowerCase() + '_to_' +
+ tr.model.ClockDomainId.WIN_QPC.toLowerCase();
+ const battorToTelemetryName = 'clock_sync_latency_' +
+ tr.model.ClockDomainId.BATTOR.toLowerCase() + '_to_' +
+ tr.model.ClockDomainId.TELEMETRY.toLowerCase();
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.clockSyncLatencyMetric(histograms, model);
+
+ let battorToWinQpcValue = undefined;
+ let winQpcToTelemetryValue = undefined;
+ let battorToTelemetryValue = undefined;
+ for (const value of histograms) {
+ if (value.name === battorToWinQpcName) {
+ battorToWinQpcValue = value;
+ } else if (value.name === winQpcToTelemetryName) {
+ winQpcToTelemetryValue = value;
+ } else if (value.name === battorToTelemetryName) {
+ battorToTelemetryValue = value;
+ }
+ }
+
+ // Clock sync graph is:
+ // [WIN_QPC] --6ms-> [TELEMETRY] --3ms-> [BATTOR]
+
+ assert.isDefined(battorToWinQpcValue);
+ assert.isDefined(winQpcToTelemetryValue);
+ assert.isDefined(battorToTelemetryValue);
+ assert.closeTo(battorToWinQpcValue.average, 9.0, 1e-5);
+ assert.closeTo(winQpcToTelemetryValue.average, 6.0, 1e-5);
+ assert.closeTo(battorToTelemetryValue.average, 3.0, 1e-5);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html
new file mode 100644
index 00000000000..f8a63e84ba7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_renderer_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ // Use a lower bound of 0.01 for the metric boundaries (when no CPU time
+ // is consumed) and an upper bound of 50 (fifty cores are all active
+ // for the entire time). We can't use zero exactly for the lower bound with an
+ // exponential histogram.
+ const CPU_TIME_PERCENTAGE_BOUNDARIES =
+ tr.v.HistogramBinBoundaries.createExponential(0.01, 50, 200);
+
+ /**
+ * This metric measures total CPU time for Chrome processes, per second of
+ * clock time.
+ * This metric requires only the 'toplevel' tracing category.
+ *
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!tr.model.Model} model
+ * @param {!Object=} opt_options
+ */
+ function cpuTimeMetric(histograms, model, opt_options) {
+ let rangeOfInterest = model.bounds;
+
+ if (opt_options && opt_options.rangeOfInterest) {
+ rangeOfInterest = opt_options.rangeOfInterest;
+ } else {
+ // If no range of interest is provided, limit the relevant range to
+ // Chrome processes. This prevents us from normalizing against non-Chrome
+ // related slices in the trace.
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (chromeHelper) {
+ const chromeBounds = chromeHelper.chromeBounds;
+ if (chromeBounds) {
+ rangeOfInterest = chromeBounds;
+ }
+ }
+ }
+
+ let allProcessCpuTime = 0;
+
+ for (const pid in model.processes) {
+ const process = model.processes[pid];
+ if (tr.model.helpers.ChromeRendererHelper.isTracingProcess(process)) {
+ continue;
+ }
+
+ let processCpuTime = 0;
+ for (const tid in process.threads) {
+ const thread = process.threads[tid];
+ processCpuTime += thread.getCpuTimeForRange(rangeOfInterest);
+ }
+ allProcessCpuTime += processCpuTime;
+ }
+
+ // Normalize cpu time by clock time.
+ let normalizedAllProcessCpuTime = 0;
+ if (rangeOfInterest.duration > 0) {
+ normalizedAllProcessCpuTime =
+ allProcessCpuTime / rangeOfInterest.duration;
+ }
+
+ const unit = tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;
+ const cpuTimeHist = new tr.v.Histogram(
+ 'cpu_time_percentage', unit, CPU_TIME_PERCENTAGE_BOUNDARIES);
+ cpuTimeHist.description =
+ 'Percent CPU utilization, normalized against a single core. Can be ' +
+ 'greater than 100% if machine has multiple cores.';
+ cpuTimeHist.customizeSummaryOptions({
+ avg: true,
+ count: false,
+ max: false,
+ min: false,
+ std: false,
+ sum: false
+ });
+ cpuTimeHist.addSample(normalizedAllProcessCpuTime);
+ histograms.addHistogram(cpuTimeHist);
+ }
+
+ tr.metrics.MetricRegistry.register(cpuTimeMetric, {
+ supportsRangeOfInterest: true
+ });
+
+ return {
+ cpuTimeMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric_test.html
new file mode 100644
index 00000000000..e68b452f4f7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_metric_test.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/metrics/system_health/cpu_time_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function computeCpuTime(customizeModelCallback, opt_options) {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ customizeModelCallback(model);
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.cpuTimeMetric(histograms, model, opt_options);
+ return tr.b.getOnlyElement(histograms).average;
+ }
+
+ // There are two slices, each of length 50. The total bounds is 3000.
+ // This yields total CPU time of 100ms, averaged over 3 seconds is 33ms.
+ test('cpuTimeMetric_oneProcess', function() {
+ const sliceDuration = 50;
+ const totalDuration = 3000;
+ const value = computeCpuTime(function(model) {
+ model.rendererProcess = model.getOrCreateProcess(2);
+ model.rendererMain = model.rendererProcess.getOrCreateThread(3);
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: sliceDuration,
+ cpuStart: 0,
+ cpuDuration: sliceDuration,
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: totalDuration - sliceDuration,
+ duration: sliceDuration,
+ cpuStart: totalDuration - sliceDuration,
+ cpuDuration: sliceDuration,
+ }));
+ });
+ assert.closeTo(value, 0.033, 0.001);
+ });
+
+ // Normalize against chrome processes, whose slices (both with and without
+ // CPU data) go from 2900 to 3000.
+ test('cpuTimeMetric_browserProcess', function() {
+ const sliceDuration = 50;
+ const totalDuration = 3000;
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ model.browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: totalDuration - 2 * sliceDuration,
+ duration: 2 * sliceDuration,
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: totalDuration - sliceDuration,
+ duration: sliceDuration,
+ cpuStart: totalDuration - sliceDuration,
+ cpuDuration: sliceDuration,
+ }));
+
+ const nonChromeProcess = model.getOrCreateProcess(1234);
+ nonChromeProcess.name = 'Telemetry';
+ const nonChromeThread = nonChromeProcess.getOrCreateThread(1);
+ nonChromeThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: sliceDuration,
+ cpuStart: 0,
+ cpuDuration: sliceDuration,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.cpuTimeMetric(histograms, model);
+ const value = tr.b.getOnlyElement(histograms).average;
+ assert.closeTo(value, 0.5, 0.001);
+ });
+
+ // Makes sure that rangeOfInterest works correctly.
+ test('cpuTimeMetric_oneProcess_rangeOfInterest', function() {
+ const sliceDuration = 50;
+ const totalDuration = 3000;
+ const rangeOfInterest = new tr.b.math.Range.fromExplicitRange(-10, 30);
+ const options = {};
+ options.rangeOfInterest = rangeOfInterest;
+ const value = computeCpuTime(function(model) {
+ model.rendererProcess = model.getOrCreateProcess(2);
+ model.rendererMain = model.rendererProcess.getOrCreateThread(3);
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: sliceDuration,
+ cpuStart: 0,
+ cpuDuration: sliceDuration,
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: totalDuration - sliceDuration,
+ duration: sliceDuration,
+ cpuStart: totalDuration - sliceDuration,
+ cpuDuration: sliceDuration,
+ }));
+ }, options);
+ assert.closeTo(value, 0.75, 0.001);
+ });
+
+ // Process 1: There are two slices, each of length 50. The total bounds is
+ // 3000. Process 2: There is one slice of length 50.
+ // This yields total CPU time of 150ms, averaged over 3 seconds is 50ms.
+ test('cpuTimeMetric_twoProcesses', function() {
+ const sliceDuration = 50;
+ const totalDuration = 3000;
+ const value = computeCpuTime(function(model) {
+ model.rendererProcess = model.getOrCreateProcess(2);
+ model.rendererMain = model.rendererProcess.getOrCreateThread(3);
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: sliceDuration,
+ cpuStart: 0,
+ cpuDuration: sliceDuration,
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: totalDuration - sliceDuration,
+ duration: sliceDuration,
+ cpuStart: totalDuration - sliceDuration,
+ cpuDuration: sliceDuration,
+ }));
+
+ const otherProcess = model.getOrCreateProcess(3);
+ const otherThread = otherProcess.getOrCreateThread(4);
+ otherThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: sliceDuration,
+ cpuStart: 0,
+ cpuDuration: sliceDuration,
+ }));
+ });
+ assert.closeTo(value, 0.05, 0.001);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_tree_data_reporter.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_tree_data_reporter.html
new file mode 100644
index 00000000000..6d88c1b81ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_tree_data_reporter.html
@@ -0,0 +1,182 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ const CPU_PERCENTAGE_UNIT =
+ tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;
+ const CPU_TIME_UNIT = tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;
+
+ /**
+ * Returns a deep clone of CPU time multidimensional view path object.
+ *
+ * @param {!Array.<!Array.<string>>} previousPath
+ * @returns {!Array.<!Array.<string>>}
+ */
+ function clonePath_(previousPath) {
+ return previousPath.map(subPath => subPath.map(x => x));
+ }
+
+
+ /**
+ * Returns an object containing the processType, threadType, railStage, and
+ * initiatorType encoded in the provided CPU time multidimensional view path
+ * object. Decoding the path into this object can make code easier to
+ * understand than indexing directly into the path array.
+ *
+ * @param {!Array.<!Array.<string>>} path - A path in a CPU time
+ * multidimensional tree view.
+ * @returns {Object.<string, string>}
+ */
+ function decodePath_(path) {
+ return {
+ processType: path[0][0],
+ threadType: path[1][0],
+ railStage: path[2][0],
+ initiatorType: path[2][1]
+ };
+ }
+
+ /**
+ * Returns a unique string representation of |path|.
+ *
+ * Paths are of the following form in CPU time multidimensional trees:
+ * [[processType], [threadType], [railStage, initiatorType]]
+ *
+ * The returned string is of the form
+ * "$processtype:$threadType:$railStage:$initiatorType".
+ *
+ * @param {Array.<!Array.<string>>} path
+ * @returns {string}
+ */
+ function stringifyPathName_(path) {
+ const decodedPath = decodePath_(path);
+ return [
+ decodedPath.processType,
+ decodedPath.threadType,
+ decodedPath.railStage,
+ decodedPath.initiatorType
+ ].join(':');
+ }
+
+ /**
+ * This class is used to traverse a multidimensional tree view and report CPU
+ * percentage and CPU time from the tree as histograms.
+ */
+ class CpuTimeTreeDataReporter {
+ constructor() {
+ this.visitedSet_ = new Set();
+ }
+
+ /**
+ * Extracts CPU percentage and CPU time values from |node| located at |path|
+ * and adds values as histograms to |this.histogramSet_|. Each value is
+ * added as a single sample histogram.
+ *
+ * @param {!tr.b.MultiDimensionalViewNode} node
+ * @param {!Array.<!Array.<string>>} path
+ */
+ reportValuesFromNode_(node, path) {
+ const decodedPath = decodePath_(path);
+ const processType = decodedPath.processType || 'all_processes';
+ const threadType = decodedPath.threadType || 'all_threads';
+
+ // We need some RAIL stage and some initiator type to process a node.
+ // All RAIL stages and all initiator types are handled by the special
+ // 'all_stages' and 'all_initiators' nodes respectively.
+ if (!decodedPath.railStage || !decodedPath.initiatorType) return;
+ const {railStage, initiatorType} = decodedPath;
+
+ const serializedPathName =
+ [processType, threadType, railStage, initiatorType].join(':');
+
+ // node.values is a two element array. The first element holds
+ // cpuPercentage data and the second holds cpuTime data. The final
+ // '.total' (as opposed to '.self') signifies we're including all the data
+ // from children nodes. This is an artifact of how the multidimensional
+ // view data structure works and is not very relevant - we exclusively use
+ // '.total' for CPU time.
+ const cpuPercentageValue = node.values[0].total;
+ const cpuTimeValue = node.values[1].total;
+
+ this.histogramSet_.createHistogram(`cpuPercentage:${serializedPathName}`,
+ CPU_PERCENTAGE_UNIT, cpuPercentageValue);
+ this.histogramSet_.createHistogram(`cpuTime:${serializedPathName}`,
+ CPU_TIME_UNIT, cpuTimeValue);
+ }
+
+
+ /**
+ * Traverses all the paths of a multidimensional view subtree and reports
+ * node data to |this.histogramSet_|.
+ *
+ * @param {!tr.b.MultiDimensionalViewNode} root - Root of the subtree.
+ * @param {!Array.<!Array.<string>>} rootPath - Path of the subtree root
+ * node with respect to |this.rootNode_|.
+ */
+ reportDataFromTree_(root, rootPath) {
+ const rootPathString = stringifyPathName_(rootPath);
+ if (this.visitedSet_.has(rootPathString)) return;
+ this.visitedSet_.add(rootPathString);
+
+ this.reportValuesFromNode_(root, rootPath);
+
+ for (let dimension = 0; dimension < root.children.length; dimension++) {
+ const children = root.children[dimension];
+ for (const [name, node] of children) {
+ const childPath = clonePath_(rootPath);
+ childPath[dimension].push(name);
+ this.reportDataFromTree_(node, childPath);
+ }
+ }
+ }
+
+ /**
+ * Adds values from the multidimensional tree view rooted at |rootNode| as
+ * single value histograms in |histogramSet|.
+ *
+ * @param {!tr.b.MultiDimensionalViewNode} rootNode
+ * @param {!tr.v.HistogramSet} histogramSet
+ */
+ addTreeValuesToHistogramSet(rootNode, histogramSet) {
+ const rootPath = [[], [], []];
+ this.rootNode_ = rootNode;
+ this.histogramSet_ = histogramSet;
+ this.reportDataFromTree_(this.rootNode_, rootPath);
+ }
+
+ /**
+ * Reports values from the multidimensional tree view rooted at |rootNode|
+ * as single value histograms in |histogramSet|.
+ *
+ * The histograms are dynamically generated from the tree. The histogram
+ * names are of the form
+ * "${cpuTime|cpuPercentage}:${processType}:${threadType}:" +
+ * "${railStage}:${railStageInitiator}"
+ *
+ * cpuTime histograms contain total consumed cpu time, while cpuPercentage
+ * histograms contain cpu time as a percentage of wall time. In multicore
+ * situations, this percentage can be larger than 100.
+ *
+ * @param {!tr.b.MultiDimensionalViewNode} rootNode
+ * @param {!tr.v.HistogramSet} histogramSet
+ */
+ static reportToHistogramSet(rootNode, histogramSet) {
+ const reporter = new CpuTimeTreeDataReporter();
+ reporter.addTreeValuesToHistogramSet(rootNode, histogramSet);
+ }
+ }
+
+ return {
+ CpuTimeTreeDataReporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_tree_data_reporter_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_tree_data_reporter_test.html
new file mode 100644
index 00000000000..cd72b21868d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/cpu_time_tree_data_reporter_test.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/multi_dimensional_view.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_processes.html">
+<link rel="import" href="/tracing/metrics/system_health/cpu_time_tree_data_reporter.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const reportToHistogramSet =
+ tr.metrics.sh.CpuTimeTreeDataReporter.reportToHistogramSet;
+
+ test('reportToHistogramSet_reportsLeafNodes', () => {
+ const mdvBuilder = new tr.b.MultiDimensionalViewBuilder(
+ 3 /* dimensions (process, thread and rail stage / initiator) */,
+ 2 /* valueCount (cpuPercentage and cpuTime) */);
+ mdvBuilder.addPath(
+ [['browser_process'], ['CrBrowserMain'], ['Animation', 'CSS']],
+ [42, 43], tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL);
+ const rootNode = mdvBuilder.buildTopDownTreeView();
+
+ const histograms = new tr.v.HistogramSet();
+ reportToHistogramSet(rootNode, histograms);
+
+ const cpuPercentageHistogram = histograms.getHistogramNamed(
+ 'cpuPercentage:browser_process:CrBrowserMain:Animation:CSS');
+ const cpuTimeHistogram = histograms.getHistogramNamed(
+ 'cpuTime:browser_process:CrBrowserMain:Animation:CSS');
+
+ // Histograms exist.
+ assert.isDefined(cpuPercentageHistogram);
+ assert.isDefined(cpuTimeHistogram);
+
+ // Each histogram contains a single sample.
+ assert.strictEqual(cpuPercentageHistogram.running.count, 1);
+ assert.strictEqual(cpuTimeHistogram.running.count, 1);
+
+ // Histogram sample value is correct.
+ assert.closeTo(cpuPercentageHistogram.sum, 42, 1e-7);
+ assert.closeTo(cpuTimeHistogram.sum, 43, 1e-7);
+ });
+
+ test('reportToHistogramSet_reportsAllProcesses', () => {
+ const mdvBuilder = new tr.b.MultiDimensionalViewBuilder(
+ 3 /* dimensions (process, thread and rail stage / initiator) */,
+ 2 /* valueCount (cpuPercentage and cpuTime) */);
+ mdvBuilder.addPath(
+ [['browser_process'], ['CrBrowserMain'], ['Animation', 'CSS']],
+ [42, 43], tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL);
+ const rootNode = mdvBuilder.buildTopDownTreeView();
+
+ const histograms = new tr.v.HistogramSet();
+ reportToHistogramSet(rootNode, histograms);
+
+ const cpuPercentageHistogram = histograms.getHistogramNamed(
+ 'cpuPercentage:all_processes:CrBrowserMain:Animation:CSS');
+ const cpuTimeHistogram = histograms.getHistogramNamed(
+ 'cpuTime:all_processes:CrBrowserMain:Animation:CSS');
+
+ // Histograms exist.
+ assert.isDefined(cpuPercentageHistogram);
+ assert.isDefined(cpuTimeHistogram);
+
+ // Each histogram contains a single sample.
+ assert.strictEqual(cpuPercentageHistogram.running.count, 1);
+ assert.strictEqual(cpuTimeHistogram.running.count, 1);
+
+ // Histogram sample value is correct.
+ assert.closeTo(cpuPercentageHistogram.sum, 42, 1e-7);
+ assert.closeTo(cpuTimeHistogram.sum, 43, 1e-7);
+ });
+
+ test('reportToHistogramSet_reportsAllThreads', () => {
+ const mdvBuilder = new tr.b.MultiDimensionalViewBuilder(
+ 3 /* dimensions (process, thread and rail stage / initiator) */,
+ 2 /* valueCount (cpuPercentage and cpuTime) */);
+ mdvBuilder.addPath(
+ [['browser_process'], ['CrBrowserMain'], ['Animation', 'CSS']],
+ [42, 43], tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL);
+ const rootNode = mdvBuilder.buildTopDownTreeView();
+
+ const histograms = new tr.v.HistogramSet();
+ reportToHistogramSet(rootNode, histograms);
+
+ const cpuPercentageHistogram = histograms.getHistogramNamed(
+ 'cpuPercentage:browser_process:all_threads:Animation:CSS');
+ const cpuTimeHistogram = histograms.getHistogramNamed(
+ 'cpuTime:browser_process:all_threads:Animation:CSS');
+
+ // Histograms exist.
+ assert.isDefined(cpuPercentageHistogram);
+ assert.isDefined(cpuTimeHistogram);
+
+ // Each histogram contains a single sample.
+ assert.strictEqual(cpuPercentageHistogram.running.count, 1);
+ assert.strictEqual(cpuTimeHistogram.running.count, 1);
+
+ // Histogram sample value is correct.
+ assert.closeTo(cpuPercentageHistogram.sum, 42, 1e-7);
+ assert.closeTo(cpuTimeHistogram.sum, 43, 1e-7);
+ });
+
+ test('reportToHistogramSet_doesNotAggregateStagesWithoutAllStagesNode',
+ () => {
+ const mdvBuilder = new tr.b.MultiDimensionalViewBuilder(
+ 3 /* dimensions (process, thread and rail stage / initiator) */,
+ 2 /* valueCount (cpuPercentage and cpuTime) */);
+ mdvBuilder.addPath(
+ [['browser_process'], ['CrBrowserMain'], ['Animation', 'CSS']],
+ [42, 43], tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL);
+ const rootNode = mdvBuilder.buildTopDownTreeView();
+
+ const histograms = new tr.v.HistogramSet();
+ reportToHistogramSet(rootNode, histograms);
+
+ // all_stages:CSS does not make sense (e.g. we will never
+ // aggregate Scroll Response and Scroll Animation, even if that's a
+ // thing), so we use all_stages:all_initiators here.
+ assert.isUndefined(histograms.getHistogramNamed(
+ 'cpuPercentage:' +
+ 'browser_process:CrBrowserMain:all_stages:all_initiators'));
+ assert.isUndefined(histograms.getHistogramNamed(
+ 'cpuTime:' +
+ 'browser_process:CrBrowserMain:all_stages:all_initiators'));
+ });
+
+ test('reportToHistogramSet_' +
+ 'doesNotAggregateInitiatorsWithoutAllInitiatorsNode',
+ () => {
+ const mdvBuilder = new tr.b.MultiDimensionalViewBuilder(
+ 3 /* dimensions (process, thread and rail stage / initiator) */,
+ 2 /* valueCount (cpuPercentage and cpuTime) */);
+ mdvBuilder.addPath(
+ [['browser_process'], ['CrBrowserMain'], ['Animation', 'CSS']],
+ [42, 43], tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL);
+ const rootNode = mdvBuilder.buildTopDownTreeView();
+
+ const histograms = new tr.v.HistogramSet();
+ reportToHistogramSet(rootNode, histograms);
+
+ assert.isUndefined(histograms.getHistogramNamed(
+ 'cpuPercentage:' +
+ 'browser_process:CrBrowserMain:Animation:all_initiators'));
+ assert.isUndefined(histograms.getHistogramNamed(
+ 'cpuTime:browser_process:CrBrowserMain:Animation:all_initiators'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/expected_queueing_time_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/expected_queueing_time_metric.html
new file mode 100644
index 00000000000..b9ef3de7ebd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/expected_queueing_time_metric.html
@@ -0,0 +1,462 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/extras/chrome/estimated_input_latency.html">
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/extras/v8/runtime_stats_entry.html">
+<link rel="import" href="/tracing/metrics/v8/utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview
+ * This file defines the input latency metric estimated as the maximum
+ * expected queueing time (EQT) in sliding window of size 500ms.
+ *
+ * The EQT is defined as the average queueing time of a hypothetical input
+ * event arriving at a random time in the given time window.
+ * For more information see:
+ * - https://goo.gl/OQ2bX6
+ * - https://goo.gl/jmWpMl
+ * - https://goo.gl/lga4iO
+ */
+tr.exportTo('tr.metrics.sh', function() {
+ // The size of the sliding window is chosen arbitrarily (see
+ // https://goo.gl/lga4iO).
+ const WINDOW_SIZE_MS = 500;
+ const EQT_BOUNDARIES = tr.v.HistogramBinBoundaries
+ .createExponential(0.01, WINDOW_SIZE_MS, 50);
+
+ /**
+ * Returns true if the slice contains a forced GC event. Some stories force
+ * garbage collection before sampling memory usage. Since a forced GC takes
+ * long time we need to ignore it to avoid biasing the input latency results.
+ */
+ function containsForcedGC_(slice) {
+ return slice.findTopmostSlicesRelativeToThisSlice(
+ tr.metrics.v8.utils.isForcedGarbageCollectionEvent).length > 0;
+ }
+
+ /**
+ * @param {!string} name Name of the histogram.
+ * @param {!string} description Description of the histogram.
+ * @returns {!tr.v.Histogram}
+ */
+ function getOrCreateHistogram_(histograms, name, description) {
+ return histograms.getHistogramNamed(name) || histograms.createHistogram(
+ name, tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: EQT_BOUNDARIES,
+ description,
+ summaryOptions: {
+ avg: false,
+ count: false,
+ max: true,
+ min: false,
+ std: false,
+ sum: false,
+ },
+ });
+ }
+
+ /**
+ * Computes the maximum expected queueing time in the sliding time window
+ * of size 500ms (WINDOW_SIZE_MS). The function produces four Histograms:
+ * - total:500ms_window:renderer_eqt,
+ * - total:500ms_window:renderer_eqt_cpu,
+ * - interactive:500ms_window:renderer_eqt.
+ * - interactive:500ms_window:renderer_eqt_cpu.
+ * The 'total' histograms are computed for the whole trace. The 'interactive'
+ * histograms are computed for the time while the page is interactive.
+ * The 'cpu' histograms use the CPU time of the events instead of the wall-
+ * clock times. Each renderer process adds one sample to the histograms.
+ */
+ function expectedQueueingTimeMetric(histograms, model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelpers = Object.values(chromeHelper.rendererHelpers);
+ const rendererToInteractiveTimestamps =
+ tr.e.chrome.getInteractiveTimestamps(model);
+ addExpectedQueueingTimeMetric_(
+ 'renderer_eqt',
+ event => {return {start: event.start, duration: event.duration};},
+ false, rendererHelpers, rendererToInteractiveTimestamps, histograms,
+ model);
+ addExpectedQueueingTimeMetric_(
+ 'renderer_eqt_cpu',
+ event => {return {start: event.cpuStart, duration: event.cpuDuration};},
+ true, rendererHelpers, rendererToInteractiveTimestamps, histograms,
+ model);
+ }
+
+ /**
+ * @callback EventTimesCallback
+ * @param {!tr.b.Event} event
+ * @return {{start: !number, duration: !number}} event start time and duration.
+ */
+
+ /**
+ * The actual implementation of the EQT metric.
+ * @param {!string} eqtName the metric name part of the histogram name.
+ * @param {!EventTimesCallback} getEventTimes.
+ * @param {!Array.<tr.model.helpers.ChromeRendererHelper>} rendererHelpers.
+ * @param {!Map.<number, Array.<number>>} rendererToInteractiveTimestamps
+ * a map from renderer pid to an array of interactive timestamps.
+ */
+ function addExpectedQueueingTimeMetric_(eqtName, getEventTimes, isCpuTime,
+ rendererHelpers, rendererToInteractiveTimestamps, histograms, model) {
+ /**
+ * Extracts tasks for EQT computation from the given renderer.
+ * A task is a pair of {start, end} times.
+ */
+ function getTasks(rendererHelper) {
+ const tasks = [];
+ for (const slice of
+ tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(
+ rendererHelper.mainThread)) {
+ const times = getEventTimes(slice);
+ if (times.duration > 0 && !containsForcedGC_(slice)) {
+ tasks.push({start: times.start, end: times.start + times.duration});
+ }
+ }
+ return tasks;
+ }
+ const totalHistogram = getOrCreateHistogram_(
+ histograms,
+ `total:${WINDOW_SIZE_MS}ms_window:${eqtName}`,
+ `The maximum EQT in a ${WINDOW_SIZE_MS}ms sliding window` +
+ ' for a given renderer');
+ const interactiveHistogram = getOrCreateHistogram_(
+ histograms,
+ `interactive:${WINDOW_SIZE_MS}ms_window:${eqtName}`,
+ `The maximum EQT in a ${WINDOW_SIZE_MS}ms sliding window` +
+ ' for a given renderer while the page is interactive');
+ for (const rendererHelper of rendererHelpers) {
+ if (rendererHelper.isChromeTracingUI) continue;
+ // Renderers with lifetime smaller than WINDOW_SIZE_MS do not have
+ // meaningful EQT.
+ if (rendererHelper.mainThread.bounds.duration < WINDOW_SIZE_MS) continue;
+
+ const tasks = getTasks(rendererHelper);
+ const {totalBreakdown, interactiveBreakdown} = getV8Contribution_(
+ eqtName,
+ getEventTimes,
+ isCpuTime,
+ totalHistogram,
+ interactiveHistogram,
+ rendererToInteractiveTimestamps,
+ histograms,
+ rendererHelper,
+ model);
+ totalHistogram.addSample(
+ tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(
+ rendererHelper.mainThread.bounds.min,
+ rendererHelper.mainThread.bounds.max,
+ WINDOW_SIZE_MS, tasks), {v8: totalBreakdown});
+ const interactiveTimestamps =
+ rendererToInteractiveTimestamps.get(rendererHelper.pid);
+ if (interactiveTimestamps.length === 0) continue;
+ if (interactiveTimestamps.length > 1) {
+ // TODO(ulan): Support multiple interactive time windows when
+ // https://crbug.com/692112 is fixed.
+ continue;
+ }
+ const interactiveWindow =
+ tr.b.math.Range.fromExplicitRange(interactiveTimestamps[0], Infinity)
+ .findIntersection(rendererHelper.mainThread.bounds);
+ interactiveHistogram.addSample(
+ tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(
+ interactiveWindow.min, interactiveWindow.max,
+ WINDOW_SIZE_MS, tasks), {v8: interactiveBreakdown});
+ }
+ }
+
+ /**
+ * Computes the contribution of the selected events to the expected queueing
+ * time. We define the contribution as the maximum expected queueing time in
+ * the sliding time window of size 500ms (WINDOW_SIZE_MS) for the trace that
+ * is modified as follows:
+ * - from each top-level task remove all subevents except the selected events.
+ * - removing subevents shrinks a task by shifting its end time closer to
+ * the start time. The start time does not change.
+ *
+ * Similar to the expectedQueueingTime this function computes two histograms:
+ * total and interactive. For example:
+ * - total:500ms_window:renderer_eqt:v8,
+ * - interactive:500ms_window:renderer_eqt:v8.
+ * Each renderer process adds one sample to the histograms.
+ * Both histograms are added to the given histogram set.
+ *
+ * @param {!string} eqtName the metric name part of the histogram name.
+ * @param {!EventTimesCallback} getEventTimes.
+ * @param {boolean} isCpuTime
+ * @param {!tr.v.Histogram} totalEqtHistogram
+ * @param {!tr.v.Histogram} interactiveEqtHistogram
+ * @param {!Map.<number, Array.<number>>} rendererToInteractiveTimestamps
+ * a map from renderer pid to an array of interactive timestamps.
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!tr.model.helpers.ChromeRendererHelper} rendererHelper
+ * @param {!tr.model.Model} model
+ * @return {{totalBreakdown: !tr.v.d.Breakdown,
+ * interactiveBreakdown: !tr.v.d.Breakdown}}
+ */
+ function getV8Contribution_(
+ eqtName, getEventTimes, isCpuTime, totalEqtHistogram,
+ interactiveEqtHistogram, rendererToInteractiveTimestamps, histograms,
+ rendererHelper, model) {
+ if (!model.categories.includes('v8')) return {};
+
+ const totalBreakdown = new tr.v.d.Breakdown();
+ const interactiveBreakdown = new tr.v.d.Breakdown();
+ // Include task extractors that use tracing.
+ const eventNamesWithTaskExtractors =
+ getV8EventNamesWithTaskExtractors_(getEventTimes);
+ if (!isCpuTime) {
+ // Include task extractors that use RCS. RCS does not provide cpu time
+ // so include these only for wall clock time.
+ const taskExtractorsUsingRCS =
+ getV8EventNamesWithTaskExtractorsUsingRCS_(getEventTimes);
+ for (const [eventName, getTasks] of taskExtractorsUsingRCS) {
+ eventNamesWithTaskExtractors.set(eventName, getTasks);
+ }
+ }
+
+ let totalNames = totalEqtHistogram.diagnostics.get('v8');
+ if (!totalNames) {
+ totalNames = new tr.v.d.RelatedNameMap();
+ totalEqtHistogram.diagnostics.set('v8', totalNames);
+ }
+ let interactiveNames = interactiveEqtHistogram.diagnostics.get('v8');
+ if (!interactiveNames) {
+ interactiveNames = new tr.v.d.RelatedNameMap();
+ interactiveEqtHistogram.diagnostics.set('v8', interactiveNames);
+ }
+
+ for (const [eventName, getTasks] of eventNamesWithTaskExtractors) {
+ const totalHistogram = getOrCreateHistogram_(histograms,
+ `total:${WINDOW_SIZE_MS}ms_window:${eqtName}:${eventName}`,
+ `Contribution to the expected queueing time by ${eventName}` +
+ ' for a given renderer. It is computed as the maximum EQT in' +
+ ` a ${WINDOW_SIZE_MS}ms sliding window after shrinking top-level` +
+ ` tasks to contain only ${eventName} subevents`);
+ const interactiveHistogram = getOrCreateHistogram_(histograms,
+ `interactive:${WINDOW_SIZE_MS}ms_window:${eqtName}:${eventName}`,
+ `Contribution to the expected queueing time by ${eventName}` +
+ ' for a given renderer while the page is interactive. It is' +
+ ` computed as the maximum EQT in a ${WINDOW_SIZE_MS}ms sliding` +
+ ' window after shrinking top-level tasks to contain only' +
+ ` ${eventName} subevents`);
+
+ const tasks = getTasks(rendererHelper);
+ const totalSample = tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(
+ rendererHelper.mainThread.bounds.min,
+ rendererHelper.mainThread.bounds.max,
+ WINDOW_SIZE_MS, tasks);
+ totalHistogram.addSample(totalSample);
+ totalBreakdown.set(eventName, totalSample);
+ totalNames.set(eventName, totalHistogram.name);
+
+ const interactiveTimestamps =
+ rendererToInteractiveTimestamps.get(rendererHelper.pid);
+ if (interactiveTimestamps.length === 0) continue;
+ if (interactiveTimestamps.length > 1) {
+ // TODO(ulan): Support multiple interactive time windows when
+ // https://crbug.com/692112 is fixed.
+ continue;
+ }
+ const interactiveWindow =
+ tr.b.math.Range.fromExplicitRange(interactiveTimestamps[0], Infinity)
+ .findIntersection(rendererHelper.mainThread.bounds);
+ const interactiveSample =
+ tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(
+ interactiveWindow.min, interactiveWindow.max,
+ WINDOW_SIZE_MS, tasks);
+ interactiveHistogram.addSample(interactiveSample);
+ interactiveBreakdown.set(eventName, interactiveSample);
+ interactiveNames.set(eventName, interactiveHistogram.name);
+ }
+ return {totalBreakdown, interactiveBreakdown};
+ }
+
+ /**
+ * @callback TaskExtractor
+ * @param {!tr.model.helpers.ChromeRendererHelper} rendererHelper
+ * @return {Array.<{start: !number, end: !number}>}
+ */
+
+ /**
+ * @param {!EventTimesCallback} getEventTimes.
+ * @returns {!Map.<string, TaskExtractor>} a map from V8 event names to
+ * the corresponding task extractor functions.
+ */
+ function getV8EventNamesWithTaskExtractors_(getEventTimes, cpuMetrics) {
+ /**
+ * @param {!tr.b.Event} slice.
+ * @param {!function(tr.b.Event): boolean} predicate that selects V8 events.
+ * @param {function(tr.b.Event): boolean} excludePredicate that excludes
+ * V8 events.
+ * @returns {!number} the total duration of topmost subslices of the given
+ * slice that satisfy the given |predicate| after filtering out any
+ * events that satisfy the |excludePredicate| in the subslices.
+ */
+ function durationOfTopmostSubSlices(slice, predicate, excludePredicate) {
+ let duration = 0;
+ for (const sub of slice.findTopmostSlicesRelativeToThisSlice(predicate)) {
+ duration += getEventTimes(sub).duration;
+ if (excludePredicate !== null && excludePredicate !== undefined) {
+ duration -= durationOfTopmostSubSlices(sub, excludePredicate);
+ }
+ }
+ return duration;
+ }
+
+ /**
+ * @param {!function(tr.b.Event): boolean} predicate that selects V8 events.
+ * @param {function(tr.b.Event): boolean} excludePredicate that excludes
+ * V8 events.
+ * @returns {!TaskExtractor} a function that extracts tasks from the given
+ * renderer. Each task is a pair of {start, end} times and its duration
+ * represents the contribution of the events selected by the
+ * given |predicate| and |excludePredicate|.
+ */
+ function taskExtractor(predicate, excludePredicate) {
+ return function(rendererHelper) {
+ const slices = tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(
+ rendererHelper.mainThread);
+ const result = [];
+ for (const slice of slices) {
+ const times = getEventTimes(slice);
+ if (times.duration > 0 && !containsForcedGC_(slice)) {
+ const duration = durationOfTopmostSubSlices(
+ slice, predicate, excludePredicate);
+ result.push({start: times.start, end: times.start + duration});
+ }
+ }
+ return result;
+ };
+ }
+
+ return new Map([
+ [
+ 'v8',
+ taskExtractor(tr.metrics.v8.utils.isV8Event)
+ ],
+ [
+ 'v8:execute',
+ taskExtractor(tr.metrics.v8.utils.isV8ExecuteEvent)
+ ],
+ [
+ 'v8:gc',
+ taskExtractor(tr.metrics.v8.utils.isGarbageCollectionEvent)
+ ],
+ [
+ 'v8:gc:full-mark-compactor',
+ taskExtractor(tr.metrics.v8.utils.isFullMarkCompactorEvent)
+ ],
+ [
+ 'v8:gc:incremental-marking',
+ taskExtractor(tr.metrics.v8.utils.isIncrementalMarkingEvent)
+ ],
+ [
+ 'v8:gc:latency-mark-compactor',
+ taskExtractor(tr.metrics.v8.utils.isLatencyMarkCompactorEvent)
+ ],
+ [
+ 'v8:gc:memory-mark-compactor',
+ taskExtractor(tr.metrics.v8.utils.isMemoryMarkCompactorEvent)
+ ],
+ [
+ 'v8:gc:scavenger',
+ taskExtractor(tr.metrics.v8.utils.isScavengerEvent)
+ ]
+ ]);
+ }
+
+ /**
+ * @param {!EventTimesCallback} getEventTimes.
+ * @param {!function(!string): boolean} predicate that selects RCS category.
+ * @param {!tr.model.helpers.ChromeRendererHelper} rendererHelper
+ * @returns {Array.<{start: !number, end: !number}>} a list of tasks. Each
+ * task is a pair of {start, end} times and its duration represents the
+ * the contribution of the events selected by the given |predicate|.
+ */
+ function extractTaskRCS(getEventTimes, predicate, rendererHelper) {
+ const result = [];
+ for (const topSlice of
+ rendererHelper.mainThread.sliceGroup.topLevelSlices) {
+ const times = getEventTimes(topSlice);
+ if (times.duration <= 0 || containsForcedGC_(topSlice)) {
+ continue;
+ }
+ // Find all V8ThreadSlices in the top level slice.
+ const v8ThreadSlices = [];
+ for (const slice of topSlice.descendentSlices) {
+ if (tr.metrics.v8.utils.isV8RCSEvent(slice)) {
+ v8ThreadSlices.push(slice);
+ }
+ }
+
+ // Find the event specified by predicate.
+ const runtimeGroupCollection =
+ new tr.e.v8.RuntimeStatsGroupCollection();
+ runtimeGroupCollection.addSlices(v8ThreadSlices);
+ let duration = 0;
+ for (const runtimeGroup of runtimeGroupCollection.runtimeGroups) {
+ if (predicate(runtimeGroup.name)) {
+ duration += runtimeGroup.time;
+ }
+ }
+
+ duration = tr.b.convertUnit(
+ duration,
+ tr.b.UnitPrefixScale.METRIC.MICRO,
+ tr.b.UnitPrefixScale.METRIC.MILLI);
+ result.push({start: times.start, end: times.start + duration});
+ }
+ return result;
+ }
+
+ /**
+ * @param {!EventTimesCallback} getEventTimes.
+ * @returns {!Map.<string, TaskExtractor>} a map from V8 event names to
+ * the corresponding task extractor functions.
+ */
+ function getV8EventNamesWithTaskExtractorsUsingRCS_(getEventTimes) {
+ const extractors = new Map();
+ extractors.set('v8:compile_rcs',
+ rendererHelper => extractTaskRCS(
+ getEventTimes,
+ tr.metrics.v8.utils.isCompileRCSCategory,
+ rendererHelper));
+ extractors.set('v8:compile:optimize_rcs',
+ rendererHelper => extractTaskRCS(
+ getEventTimes,
+ tr.metrics.v8.utils.isCompileOptimizeRCSCategory,
+ rendererHelper));
+ extractors.set('v8:compile:parse_rcs',
+ rendererHelper => extractTaskRCS(
+ getEventTimes,
+ tr.metrics.v8.utils.isCompileParseRCSCategory,
+ rendererHelper));
+ extractors.set('v8:compile:compile-unoptimize_rcs',
+ rendererHelper => extractTaskRCS(
+ getEventTimes,
+ tr.metrics.v8.utils.isCompileUnoptimizeRCSCategory,
+ rendererHelper));
+ return extractors;
+ }
+
+ tr.metrics.MetricRegistry.register(expectedQueueingTimeMetric);
+
+ return {
+ expectedQueueingTimeMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/expected_queueing_time_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/expected_queueing_time_metric_test.html
new file mode 100644
index 00000000000..b300c523964
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/expected_queueing_time_metric_test.html
@@ -0,0 +1,409 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import"
+ href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/metrics/system_health/expected_queueing_time_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function addInteractiveTimestamp(rendererProcess, mainThread, timestamp) {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: timestamp,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.asyncSliceGroup.push(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start: timestamp,
+ duration: 5.0,
+ }));
+ rendererProcess.objects.addSnapshot(
+ 'ptr', 'loading', 'FrameLoader', timestamp, {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: timestamp + 1,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: timestamp + 1,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ }
+
+ test('expectedQueueingTime', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ addInteractiveTimestamp(rendererProcess, mainThread, 200);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 0,
+ duration: 100,
+ cpuStart: 0,
+ cpuDuration: 50,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 3000,
+ duration: 10,
+ cpuStart: 3000,
+ cpuDuration: 5,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9000,
+ duration: 10,
+ cpuStart: 9000,
+ cpuDuration: 5,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.expectedQueueingTimeMetric(histograms, model);
+ const interactiveEqt = histograms.getHistogramNamed(
+ 'interactive:500ms_window:renderer_eqt');
+ assert.strictEqual(0.1, interactiveEqt.average);
+ const totalEqt = histograms.getHistogramNamed(
+ 'total:500ms_window:renderer_eqt');
+ assert.strictEqual(10, totalEqt.average);
+ const interactiveEqtCpu = histograms.getHistogramNamed(
+ 'interactive:500ms_window:renderer_eqt_cpu');
+ assert.strictEqual(0.025, interactiveEqtCpu.average);
+ const totalEqtCpu = histograms.getHistogramNamed(
+ 'total:500ms_window:renderer_eqt_cpu');
+ assert.strictEqual(2.5, totalEqtCpu.average);
+ });
+
+ test('expectedQueueingTime_noInteractive', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 0,
+ duration: 100,
+ cpuStart: 0,
+ cpuDuration: 100,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 3000,
+ duration: 10,
+ cpuStart: 3000,
+ cpuDuration: 10,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9000,
+ duration: 10,
+ cpuStart: 9000,
+ cpuDuration: 10,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.expectedQueueingTimeMetric(histograms, model);
+ const interactiveEQT = histograms.getHistogramNamed(
+ 'interactive:500ms_window:renderer_eqt');
+ assert.strictEqual(0, interactiveEQT.numValues);
+ });
+
+ test('expectedQueueingTime_multipleInteractive', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ addInteractiveTimestamp(rendererProcess, mainThread, 200);
+ addInteractiveTimestamp(rendererProcess, mainThread, 6000);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 0,
+ duration: 100,
+ cpuStart: 0,
+ cpuDuration: 100,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 3000,
+ duration: 10,
+ cpuStart: 3000,
+ cpuDuration: 10,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 12000,
+ duration: 10,
+ cpuStart: 9000,
+ cpuDuration: 10,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.expectedQueueingTimeMetric(histograms, model);
+ const interactiveEQT = histograms.getHistogramNamed(
+ 'interactive:500ms_window:renderer_eqt');
+ // TODO(ulan): Support multiple interactive time windows when
+ // https://crbug.com/692112 is fixed.
+ assert.strictEqual(0, interactiveEQT.numValues);
+ });
+
+ test('expectedQueueingTime_multipleRenderersAggregates', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ addInteractiveTimestamp(rendererProcess, mainThread, 200);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 0,
+ duration: 100,
+ cpuStart: 0,
+ cpuDuration: 100,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 3000,
+ duration: 10,
+ cpuStart: 3000,
+ cpuDuration: 10,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9000,
+ duration: 10,
+ cpuStart: 9000,
+ cpuDuration: 10,
+ }));
+ const rendererProcess2 = model.getOrCreateProcess(1985);
+ const mainThread2 = rendererProcess2.getOrCreateThread(2);
+ mainThread2.name = 'CrRendererMain';
+ addInteractiveTimestamp(rendererProcess2, mainThread2, 200);
+ mainThread2.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9000,
+ duration: 0,
+ cpuStart: 9000,
+ cpuDuration: 0,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.expectedQueueingTimeMetric(histograms, model);
+ const eqt = histograms.getHistogramNamed(
+ 'interactive:500ms_window:renderer_eqt');
+ assert.strictEqual(0.05, eqt.average);
+ });
+
+ test('expectedQueueingTime_relatedV8Histograms', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ addInteractiveTimestamp(rendererProcess, mainThread, 200);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 0,
+ duration: 100,
+ cpuStart: 0,
+ cpuDuration: 100,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.GCFinalizeMC',
+ start: 50,
+ duration: 50,
+ cpuStart: 50,
+ cpuDuration: 50,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 3000,
+ duration: 10,
+ cpuStart: 3000,
+ cpuDuration: 10,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-v8.compile',
+ title: 'V8.RecompileSynchronous',
+ start: 3000,
+ duration: 5,
+ cpuStart: 3000,
+ cpuDuration: 5,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9000,
+ duration: 10,
+ cpuStart: 9000,
+ cpuDuration: 10,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.GCFinalizeMC',
+ start: 9000,
+ duration: 5,
+ cpuStart: 9000,
+ cpuDuration: 5,
+ }));
+ mainThread.sliceGroup.createSubSlices();
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.expectedQueueingTimeMetric(histograms, model);
+
+ const eqt = histograms.getHistogramNamed(
+ 'interactive:500ms_window:renderer_eqt');
+ assert.strictEqual('interactive:500ms_window:renderer_eqt:v8',
+ eqt.diagnostics.get('v8').get('v8'));
+ assert.strictEqual(0.025,
+ eqt.getBinForValue(0.1).diagnosticMaps[0].get('v8').get('v8'));
+
+ const eqtCpu = histograms.getHistogramNamed(
+ 'interactive:500ms_window:renderer_eqt_cpu');
+ assert.strictEqual('interactive:500ms_window:renderer_eqt_cpu:v8',
+ eqtCpu.diagnostics.get('v8').get('v8'));
+ assert.strictEqual(0.025,
+ eqtCpu.getBinForValue(0.1).diagnosticMaps[0].get('v8').get('v8'));
+ });
+
+ test('expectedQueueingTimeRCS', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ addInteractiveTimestamp(rendererProcess, mainThread, 200);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 0,
+ duration: 100,
+ cpuStart: 0,
+ cpuDuration: 100,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.newInstance',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 12555,
+ duration: 990,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ ParseLazy: [5, 3],
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 3000,
+ duration: 100,
+ cpuStart: 3000,
+ cpuDuration: 100,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 3000,
+ duration: 100,
+ cpuStart: 3000,
+ cpuDuration: 100,
+ args: {
+ 'runtime-call-stats': {
+ CompileIgnition: [3, 5000],
+ OptimizeCode: [6, 40000],
+ JS_Execution: [1, 11000],
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 4000,
+ duration: 100,
+ cpuStart: 4000,
+ cpuDuration: 100,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 4000,
+ duration: 100,
+ cpuStart: 4000,
+ cpuDuration: 100,
+ args: {
+ 'runtime-call-stats': {
+ CompileIgnition: [20, 20000],
+ ParseLazy: [5, 10000],
+ CompileBackgroundIgnition: [3, 30000]
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9000,
+ duration: 10,
+ cpuStart: 9000,
+ cpuDuration: 10,
+ }));
+ mainThread.sliceGroup.createSubSlices();
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.expectedQueueingTimeMetric(histograms, model);
+
+ const eqt = histograms.getHistogramNamed(
+ 'total:500ms_window:renderer_eqt');
+ assert.strictEqual(
+ 'total:500ms_window:renderer_eqt:v8:compile:optimize_rcs',
+ eqt.diagnostics.get('v8').get('v8:compile:optimize_rcs'));
+ assert.strictEqual(1.6, eqt.getBinForValue(10).diagnosticMaps[0].get(
+ 'v8').get('v8:compile:optimize_rcs'));
+
+ assert.strictEqual('total:500ms_window:renderer_eqt:v8:compile:parse_rcs',
+ eqt.diagnostics.get('v8').get('v8:compile:parse_rcs'));
+ assert.strictEqual(0.1, eqt.getBinForValue(10).diagnosticMaps[0].get(
+ 'v8').get('v8:compile:parse_rcs'));
+
+ assert.strictEqual(
+ 'total:500ms_window:renderer_eqt:v8:compile:compile-unoptimize_rcs',
+ eqt.diagnostics.get('v8').get('v8:compile:compile-unoptimize_rcs'));
+ assert.strictEqual(0.4, eqt.getBinForValue(10).diagnosticMaps[0].get(
+ 'v8').get('v8:compile:compile-unoptimize_rcs'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/limited_cpu_time_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/limited_cpu_time_metric.html
new file mode 100644
index 00000000000..40d5722c1a4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/limited_cpu_time_metric.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/new_cpu_time_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ const includeHistogramNames = [
+ 'cpuTime:all_processes:all_threads:all_stages:all_initiators',
+ 'cpuPercentage:all_processes:all_threads:all_stages:all_initiators',
+ 'cpuTime:browser_process:all_threads:all_stages:all_initiators',
+ 'cpuPercentage:browser_process:all_threads:all_stages:all_initiators',
+ 'cpuTime:renderer_processes:all_threads:all_stages:all_initiators',
+ 'cpuPercentage:renderer_processes:all_threads:all_stages:all_initiators',
+ 'cpuTime:gpu_process:all_threads:all_stages:all_initiators',
+ 'cpuPercentage:gpu_process:all_threads:all_stages:all_initiators',
+ 'cpuTime:renderer_processes:CrRendererMain:all_stages:all_initiators',
+ 'cpuPercentage:renderer_processes:CrRendererMain:all_stages:all_initiators',
+ 'cpuTime:browser_process:CrBrowserMain:all_stages:all_initiators',
+ 'cpuPercentage:browser_process:CrBrowserMain:all_stages:all_initiators',
+ 'cpuTime:all_processes:all_threads:Load:Successful',
+ 'cpuPercentage:all_processes:all_threads:Load:Successful',
+ ];
+
+ /**
+ * This metric is a limited version of new CPU Time metric. The new cpu time
+ * metric produces 300-500 histograms for a trace, which is overwhelming for
+ * some systems. This file exposes a subset of those histograms.
+ *
+ * TODO(#4044): Remove this metric once histogram pipeline is ready.
+ *
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!tr.model.Model} model
+ * @param {!Object=} opt_options
+ */
+ function limitedCpuTimeMetric(histograms, model, opt_options) {
+ const allCpuHistograms = new tr.v.HistogramSet();
+ tr.metrics.sh.newCpuTimeMetric(allCpuHistograms, model, opt_options);
+
+ for (const histogramName of includeHistogramNames) {
+ const histogram = allCpuHistograms.getHistogramNamed(histogramName);
+ if (histogram) histograms.addHistogram(histogram);
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(limitedCpuTimeMetric, {
+ supportsRangeOfInterest: true
+ });
+
+ return {
+ limitedCpuTimeMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html
new file mode 100644
index 00000000000..b439f2e7d15
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric.html
@@ -0,0 +1,623 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/category_util.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/extras/chrome/time_to_interactive.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/breakdown_tree_helpers.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_thread_helper.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ const LONG_TASK_THRESHOLD_MS = 50;
+ const timeDurationInMs_smallerIsBetter =
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;
+ const RelatedEventSet = tr.v.d.RelatedEventSet;
+ const hasCategoryAndName = tr.metrics.sh.hasCategoryAndName;
+ const EventFinderUtils = tr.e.chrome.EventFinderUtils;
+
+ /**
+ * @param {!tr.model.Process} process
+ * @param {!tr.b.math.Range} range
+ * @return {Array.<tr.model.Event>} An array of network events of a process
+ * and that are intersecting a range.
+ */
+ function getNetworkEventsInRange(process, range) {
+ const networkEvents = [];
+ for (const thread of Object.values(process.threads)) {
+ const threadHelper = new tr.model.helpers.ChromeThreadHelper(thread);
+ const events = threadHelper.getNetworkEvents();
+ for (const event of events) {
+ if (range.intersectsExplicitRangeInclusive(event.start, event.end)) {
+ networkEvents.push(event);
+ }
+ }
+ }
+ return networkEvents;
+ }
+
+ /**
+ * @param {!Object.<string, Object>} breakdownTree
+ * @return {tr.v.d.Breakdown} A breakdown with categories and the total time
+ * (ms) spent under each category.
+ */
+ function createBreakdownDiagnostic(breakdownTree) {
+ const breakdownDiagnostic = new tr.v.d.Breakdown();
+ breakdownDiagnostic.colorScheme =
+ tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;
+
+ for (const label in breakdownTree) {
+ breakdownDiagnostic.set(label, breakdownTree[label].total);
+ }
+ return breakdownDiagnostic;
+ }
+
+ const LOADING_METRIC_BOUNDARIES = tr.v.HistogramBinBoundaries
+ .createLinear(0, 1e3, 20) // 50ms step to 1s
+ .addLinearBins(3e3, 20) // 100ms step to 3s
+ .addExponentialBins(20e3, 20);
+
+ const TIME_TO_INTERACTIVE_BOUNDARIES = tr.v.HistogramBinBoundaries
+ // 90-th percentiile of TTI is around 40 seconds, across warm and cold
+ // loads. Data obtained through Cluster Telemetry analysis.
+ .createExponential(1, 40e3, 35)
+ .addExponentialBins(80e3, 15);
+
+ const SUMMARY_OPTIONS = {
+ avg: true,
+ count: false,
+ max: true,
+ min: true,
+ std: true,
+ sum: false,
+ };
+
+ function findFrameLoaderSnapshotAt(rendererHelper, frameIdRef, ts) {
+ const objects = rendererHelper.process.objects;
+ const frameLoaderInstances = objects.instancesByTypeName_.FrameLoader;
+ if (frameLoaderInstances === undefined) return undefined;
+
+ let snapshot;
+ for (const instance of frameLoaderInstances) {
+ if (!instance.isAliveAt(ts)) continue;
+ const maybeSnapshot = instance.getSnapshotAt(ts);
+ if (frameIdRef !== maybeSnapshot.args.frame.id_ref) continue;
+ snapshot = maybeSnapshot;
+ }
+
+ return snapshot;
+ }
+
+ function findAllEvents(rendererHelper, category, title) {
+ const targetEvents = [];
+
+ for (const ev of rendererHelper.process.getDescendantEvents()) {
+ if (!hasCategoryAndName(ev, category, title)) continue;
+ targetEvents.push(ev);
+ }
+
+ return targetEvents;
+ }
+
+ function getMostRecentValidEvent(rendererHelper, category, title) {
+ const targetEvents = findAllEvents(rendererHelper, category, title);
+ // Want to keep the event with the most recent timestamp
+ let validEvent;
+ for (const targetEvent of targetEvents) {
+ if (rendererHelper.isTelemetryInternalEvent(targetEvent)) continue;
+ if (validEvent === undefined) {
+ validEvent = targetEvent;
+ } else {
+ // Want to keep the event with the most recent timestamp
+ if (validEvent.start < targetEvent.start) {
+ validEvent = targetEvent;
+ }
+ }
+ }
+ return validEvent;
+ }
+
+ function getAboveTheFoldLoadedToVisibleSamples(rendererHelper,
+ navIdToNavStartEvents) {
+ const samples = [];
+ // Want to measure the time from when navigation starts to when the load
+ // event fired for all non-ad resources. This done with the associated
+ // navigation start event to the pc mark in the amp code, correlated by
+ // navigation id.
+ const pcEvent = getMostRecentValidEvent(
+ rendererHelper, 'blink.user_timing', 'pc');
+ if (pcEvent === undefined) return samples;
+
+ if (rendererHelper.isTelemetryInternalEvent(pcEvent)) return samples;
+ const navigationStartEvent = navIdToNavStartEvents.get(
+ pcEvent.args.data.navigationId);
+ if (navigationStartEvent === undefined) return samples;
+ const navStartToEventRange = tr.b.math.Range.fromExplicitRange(
+ navigationStartEvent.start, pcEvent.start);
+ const networkEvents = getNetworkEventsInRange(
+ rendererHelper.process, navStartToEventRange);
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, navStartToEventRange);
+ samples.push({
+ value: navStartToEventRange.duration,
+ breakdownTree,
+ diagnostics: {
+ breakdown: createBreakdownDiagnostic(breakdownTree),
+ Start: new RelatedEventSet(navigationStartEvent),
+ End: new RelatedEventSet(pcEvent)
+ }
+ });
+
+ return samples;
+ }
+
+ function getFirstViewportReadySamples(rendererHelper) {
+ const samples = [];
+ // Want to measure the time from when the document is visible to the time
+ // when the load event fired for all non-ad resources. This is done with
+ // two marks in the amp code: pc and visible.
+ const pcEvent = getMostRecentValidEvent(
+ rendererHelper, 'blink.user_timing', 'pc');
+ const visibleEvent = getMostRecentValidEvent(
+ rendererHelper, 'blink.user_timing', 'visible');
+ if (pcEvent !== undefined && visibleEvent !== undefined) {
+ samples.push({
+ value: pcEvent.start - visibleEvent.start,
+ diagnostics: {
+ Start: new RelatedEventSet(visibleEvent),
+ End: new RelatedEventSet(pcEvent)
+ }
+ });
+ }
+ return samples;
+ }
+
+ function findTimeToXEntries(
+ category, eventName, rendererHelper, frameToNavStartEvents,
+ navIdToNavStartEvents) {
+ const targetEvents = findAllEvents(rendererHelper, category, eventName);
+ const entries = [];
+ for (const targetEvent of targetEvents) {
+ if (rendererHelper.isTelemetryInternalEvent(targetEvent)) continue;
+ const frameIdRef = targetEvent.args.frame;
+ const snapshot = findFrameLoaderSnapshotAt(
+ rendererHelper, frameIdRef, targetEvent.start);
+ if (snapshot === undefined || !snapshot.args.isLoadingMainFrame) continue;
+ const url = snapshot.args.documentLoaderURL;
+ if (tr.e.chrome.CHROME_INTERNAL_URLS.includes(url)) continue;
+ let navigationStartEvent;
+ if (targetEvent.args.data === undefined ||
+ targetEvent.args.data.navigationId === undefined) {
+ navigationStartEvent =
+ EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(
+ frameToNavStartEvents.get(frameIdRef) || [], targetEvent.start);
+ } else {
+ navigationStartEvent = navIdToNavStartEvents.get(
+ targetEvent.args.data.navigationId);
+ }
+
+ // Ignore layout w/o preceding navigationStart, as they are not
+ // attributed to any time-to-X metric.
+ if (navigationStartEvent === undefined) continue;
+ entries.push({
+ navigationStartEvent,
+ targetEvent,
+ url,
+ });
+ }
+ return entries;
+ }
+
+ function collectTimeToEvent(rendererHelper, timeToXEntries) {
+ const samples = [];
+ for (const { targetEvent, navigationStartEvent, url } of timeToXEntries) {
+ const navStartToEventRange = tr.b.math.Range.fromExplicitRange(
+ navigationStartEvent.start, targetEvent.start);
+ const networkEvents = getNetworkEventsInRange(
+ rendererHelper.process, navStartToEventRange);
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, navStartToEventRange);
+ samples.push({
+ value: navStartToEventRange.duration,
+ breakdownTree,
+ diagnostics: {
+ breakdown: createBreakdownDiagnostic(breakdownTree),
+ url: new tr.v.d.GenericSet([url]),
+ Start: new RelatedEventSet(navigationStartEvent),
+ End: new RelatedEventSet(targetEvent)
+ }
+ });
+ }
+ return samples;
+ }
+
+ function collectTimeToEventInCpuTime(rendererHelper, timeToXEntries) {
+ const samples = [];
+ for (const { targetEvent, navigationStartEvent, url } of timeToXEntries) {
+ const navStartToEventRange = tr.b.math.Range.fromExplicitRange(
+ navigationStartEvent.start, targetEvent.start);
+
+ const mainThreadCpuTime =
+ rendererHelper.mainThread.getCpuTimeForRange(navStartToEventRange);
+
+ const breakdownTree = tr.metrics.sh.generateCpuTimeBreakdownTree(
+ rendererHelper.mainThread, navStartToEventRange);
+ samples.push({
+ value: mainThreadCpuTime,
+ breakdownTree,
+ diagnostics: {
+ breakdown: createBreakdownDiagnostic(breakdownTree),
+ start: new RelatedEventSet(navigationStartEvent),
+ end: new RelatedEventSet(targetEvent),
+ infos: new tr.v.d.GenericSet([{
+ pid: rendererHelper.pid,
+ start: navigationStartEvent.start,
+ event: targetEvent.start,
+ }]),
+ }
+ });
+ }
+ return samples;
+ }
+
+ function addFirstMeaningfulPaintSample(samples, rendererHelper,
+ navigationStart, fmpMarkerEvent, url) {
+ const navStartToFMPRange = tr.b.math.Range.fromExplicitRange(
+ navigationStart.start, fmpMarkerEvent.start);
+ const networkEvents = getNetworkEventsInRange(
+ rendererHelper.process, navStartToFMPRange);
+ const timeToFirstMeaningfulPaint = navStartToFMPRange.duration;
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents, navStartToFMPRange);
+ samples.push({
+ value: timeToFirstMeaningfulPaint,
+ breakdownTree,
+ diagnostics: {
+ breakdown: createBreakdownDiagnostic(breakdownTree),
+ start: new RelatedEventSet(navigationStart),
+ end: new RelatedEventSet(fmpMarkerEvent),
+ infos: new tr.v.d.GenericSet([{
+ url,
+ pid: rendererHelper.pid,
+ start: navigationStart.start,
+ fmp: fmpMarkerEvent.start,
+ }]),
+ }
+ });
+ }
+
+ function addFirstMeaningfulPaintCpuTimeSample(samples, rendererHelper,
+ navigationStart, fmpMarkerEvent, url) {
+ const navStartToFMPRange = tr.b.math.Range.fromExplicitRange(
+ navigationStart.start, fmpMarkerEvent.start);
+
+ const mainThreadCpuTime =
+ rendererHelper.mainThread.getCpuTimeForRange(navStartToFMPRange);
+
+ const breakdownTree = tr.metrics.sh.generateCpuTimeBreakdownTree(
+ rendererHelper.mainThread, navStartToFMPRange);
+ samples.push({
+ value: mainThreadCpuTime,
+ breakdownTree,
+ diagnostics: {
+ breakdown: createBreakdownDiagnostic(breakdownTree),
+ start: new RelatedEventSet(navigationStart),
+ end: new RelatedEventSet(fmpMarkerEvent),
+ infos: new tr.v.d.GenericSet([{
+ url,
+ pid: rendererHelper.pid,
+ start: navigationStart.start,
+ fmp: fmpMarkerEvent.start,
+ }]),
+ }
+ });
+ }
+
+ /**
+ * Object containing one value and associated diagnostics info for that value
+ * for a metric.
+ * @typedef {{value: number, diagnostics: !tr.v.d.DiagnosticMap}} MetricSample
+ */
+
+ /**
+ * Returns a MetricSample for interactivity metrics - First CPU Idle and Time
+ * to Interactive.
+ *
+ * @param {tr.model.helpers.ChromeRendererHelper} rendererHelper
+ * @param {?number} eventTimestamp - Timestamp of the event for which the
+ * sample is being generated.
+ * @param {tr.model.ThreadSlice} navigationStartEvent
+ * @param {number} firstMeaningfulPaintTime
+ * @param {number} domContentLoadedEndTime
+ * @param {string} url - URL of the current main frame document.
+ * @returns {MetricSample|undefined}
+ */
+ function decorateInteractivitySampleWithDiagnostics_(rendererHelper,
+ eventTimestamp, navigationStartEvent, firstMeaningfulPaintTime,
+ domContentLoadedEndTime, url) {
+ if (eventTimestamp === undefined) return undefined;
+ const navigationStartTime = navigationStartEvent.start;
+ const navStartToEventTimeRange =
+ tr.b.math.Range.fromExplicitRange(
+ navigationStartTime, eventTimestamp);
+ const networkEvents = getNetworkEventsInRange(
+ rendererHelper.process, navStartToEventTimeRange);
+ const breakdownTree = tr.metrics.sh.generateWallClockTimeBreakdownTree(
+ rendererHelper.mainThread, networkEvents,
+ navStartToEventTimeRange);
+ const breakdownDiagnostic = createBreakdownDiagnostic(breakdownTree);
+ return {
+ value: navStartToEventTimeRange.duration,
+ diagnostics: tr.v.d.DiagnosticMap.fromObject({
+ 'Start': new RelatedEventSet(navigationStartEvent),
+ 'Navigation infos': new tr.v.d.GenericSet([{
+ url,
+ pid: rendererHelper.pid,
+ navigationStartTime,
+ firstMeaningfulPaintTime,
+ domContentLoadedEndTime,
+ // eventTimestamp can be derived from value and navigationStartEvent,
+ // but it's useful to directly see the value in the UI.
+ eventTimestamp,
+ }]),
+ 'Breakdown of [navStart, eventTimestamp]': breakdownDiagnostic,
+ }),
+ };
+ }
+
+ function collectLoadingMetricsForRenderer(rendererHelper) {
+ const frameToNavStartEvents =
+ EventFinderUtils.getSortedMainThreadEventsByFrame(
+ rendererHelper, 'navigationStart', 'blink.user_timing');
+ const navIdToNavStartEvents =
+ EventFinderUtils.getSortedMainThreadEventsByNavId(
+ rendererHelper, 'navigationStart', 'blink.user_timing');
+ const firstPaintSamples = collectTimeToEvent(rendererHelper,
+ findTimeToXEntries('loading', 'firstPaint', rendererHelper,
+ frameToNavStartEvents, navIdToNavStartEvents));
+ const timeToFCPEntries = findTimeToXEntries('loading',
+ 'firstContentfulPaint', rendererHelper, frameToNavStartEvents,
+ navIdToNavStartEvents);
+ const firstContentfulPaintSamples = collectTimeToEvent(rendererHelper,
+ timeToFCPEntries);
+ const firstContentfulPaintCpuTimeSamples = collectTimeToEventInCpuTime(
+ rendererHelper, timeToFCPEntries);
+ const onLoadSamples = collectTimeToEvent(rendererHelper, findTimeToXEntries(
+ 'blink.user_timing', 'loadEventStart', rendererHelper,
+ frameToNavStartEvents, navIdToNavStartEvents));
+ const aboveTheFoldLoadedToVisibleSamples =
+ getAboveTheFoldLoadedToVisibleSamples(
+ rendererHelper, navIdToNavStartEvents);
+ const firstViewportReadySamples = getFirstViewportReadySamples(
+ rendererHelper);
+
+ return {
+ frameToNavStartEvents,
+ firstPaintSamples,
+ firstContentfulPaintSamples,
+ firstContentfulPaintCpuTimeSamples,
+ onLoadSamples,
+ aboveTheFoldLoadedToVisibleSamples,
+ firstViewportReadySamples,
+ };
+ }
+
+ function collectMetricsFromLoadExpectations(model, chromeHelper) {
+ // Add FMP, firstCpuIdle and interactive samples from load UE
+ const interactiveSamples = [];
+ const firstCpuIdleSamples = [];
+ const firstMeaningfulPaintSamples = [];
+ const firstMeaningfulPaintCpuTimeSamples = [];
+ for (const expectation of model.userModel.expectations) {
+ if (!(expectation instanceof tr.model.um.LoadExpectation)) continue;
+ if (tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)) {
+ continue;
+ }
+ const rendererHelper = chromeHelper.rendererHelpers[
+ expectation.renderProcess.pid];
+ if (expectation.fmpEvent !== undefined) {
+ addFirstMeaningfulPaintSample(firstMeaningfulPaintSamples,
+ rendererHelper, expectation.navigationStart, expectation.fmpEvent,
+ expectation.url);
+ addFirstMeaningfulPaintCpuTimeSample(firstMeaningfulPaintCpuTimeSamples,
+ rendererHelper, expectation.navigationStart, expectation.fmpEvent,
+ expectation.url);
+ }
+ if (expectation.firstCpuIdleTime !== undefined) {
+ firstCpuIdleSamples.push(decorateInteractivitySampleWithDiagnostics_(
+ rendererHelper, expectation.firstCpuIdleTime,
+ expectation.navigationStart,
+ expectation.fmpEvent.start,
+ expectation.domContentLoadedEndEvent.start, expectation.url));
+ }
+ if (expectation.timeToInteractive !== undefined) {
+ interactiveSamples.push(decorateInteractivitySampleWithDiagnostics_(
+ rendererHelper, expectation.timeToInteractive,
+ expectation.navigationStart,
+ expectation.fmpEvent.start,
+ expectation.domContentLoadedEndEvent.start, expectation.url));
+ }
+ }
+
+ return {
+ firstMeaningfulPaintSamples,
+ firstMeaningfulPaintCpuTimeSamples,
+ firstCpuIdleSamples,
+ interactiveSamples,
+ };
+ }
+
+ function addSamplesToHistogram(samples, histogram, histograms) {
+ for (const sample of samples) {
+ histogram.addSample(sample.value, sample.diagnostics);
+
+ // Only add breakdown histograms for FCP.
+ // http://crbug.com/771610
+ if (histogram.name !== 'timeToFirstContentfulPaint') continue;
+
+ if (!sample.breakdownTree) continue;
+ for (const [category, breakdown] of Object.entries(
+ sample.breakdownTree)) {
+ const relatedName = `${histogram.name}:${category}`;
+ let relatedHist = histograms.getHistogramsNamed(relatedName)[0];
+ if (!relatedHist) {
+ relatedHist = histograms.createHistogram(
+ relatedName, histogram.unit, [], {
+ binBoundaries: LOADING_METRIC_BOUNDARIES,
+ summaryOptions: {
+ count: false,
+ max: false,
+ min: false,
+ sum: false,
+ },
+ });
+
+ let relatedNames = histogram.diagnostics.get('breakdown');
+ if (!relatedNames) {
+ relatedNames = new tr.v.d.RelatedNameMap();
+ histogram.diagnostics.set('breakdown', relatedNames);
+ }
+ relatedNames.set(category, relatedName);
+ }
+ relatedHist.addSample(breakdown.total, {
+ breakdown: tr.v.d.Breakdown.fromEntries(
+ Object.entries(breakdown.events)),
+ });
+ }
+ }
+ }
+
+ function loadingMetric(histograms, model) {
+ const firstPaintHistogram = histograms.createHistogram(
+ 'timeToFirstPaint', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: LOADING_METRIC_BOUNDARIES,
+ description: 'time to first paint',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const firstContentfulPaintHistogram = histograms.createHistogram(
+ 'timeToFirstContentfulPaint', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: LOADING_METRIC_BOUNDARIES,
+ description: 'time to first contentful paint',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const firstContentfulPaintCpuTimeHistogram = histograms.createHistogram(
+ 'cpuTimeToFirstContentfulPaint', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: LOADING_METRIC_BOUNDARIES,
+ description: 'CPU time to first contentful paint',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const onLoadHistogram = histograms.createHistogram(
+ 'timeToOnload', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: LOADING_METRIC_BOUNDARIES,
+ description: 'time to onload. ' +
+ 'This is temporary metric used for PCv1/v2 sanity checking',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const firstMeaningfulPaintHistogram = histograms.createHistogram(
+ 'timeToFirstMeaningfulPaint', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: LOADING_METRIC_BOUNDARIES,
+ description: 'time to first meaningful paint',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const firstMeaningfulPaintCpuTimeHistogram = histograms.createHistogram(
+ 'cpuTimeToFirstMeaningfulPaint', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: LOADING_METRIC_BOUNDARIES,
+ description: 'CPU time to first meaningful paint',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const timeToInteractiveHistogram = histograms.createHistogram(
+ 'timeToInteractive', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: TIME_TO_INTERACTIVE_BOUNDARIES,
+ description: 'Time to Interactive',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const timeToFirstCpuIdleHistogram = histograms.createHistogram(
+ 'timeToFirstCpuIdle', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: TIME_TO_INTERACTIVE_BOUNDARIES,
+ description: 'Time to First CPU Idle',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const aboveTheFoldLoadedToVisibleHistogram = histograms.createHistogram(
+ 'aboveTheFoldLoadedToVisible', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: TIME_TO_INTERACTIVE_BOUNDARIES,
+ description: 'Time from first visible to load for AMP pages only.',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ const firstViewportReadyHistogram = histograms.createHistogram(
+ 'timeToFirstViewportReady', timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: TIME_TO_INTERACTIVE_BOUNDARIES,
+ description: 'Time from navigation to load for AMP pages only. ',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ for (const pid in chromeHelper.rendererHelpers) {
+ const rendererHelper = chromeHelper.rendererHelpers[pid];
+ if (rendererHelper.isChromeTracingUI) continue;
+
+ const samplesSet =
+ collectLoadingMetricsForRenderer(rendererHelper);
+
+ addSamplesToHistogram(
+ samplesSet.firstPaintSamples, firstPaintHistogram, histograms);
+ addSamplesToHistogram(
+ samplesSet.firstContentfulPaintSamples,
+ firstContentfulPaintHistogram,
+ histograms);
+ addSamplesToHistogram(
+ samplesSet.firstContentfulPaintCpuTimeSamples,
+ firstContentfulPaintCpuTimeHistogram,
+ histograms);
+ addSamplesToHistogram(
+ samplesSet.onLoadSamples, onLoadHistogram, histograms);
+ addSamplesToHistogram(
+ samplesSet.aboveTheFoldLoadedToVisibleSamples,
+ aboveTheFoldLoadedToVisibleHistogram,
+ histograms);
+ addSamplesToHistogram(
+ samplesSet.firstViewportReadySamples,
+ firstViewportReadyHistogram,
+ histograms);
+ }
+
+ const samplesSet = collectMetricsFromLoadExpectations(model, chromeHelper);
+ addSamplesToHistogram(
+ samplesSet.firstMeaningfulPaintSamples,
+ firstMeaningfulPaintHistogram,
+ histograms);
+ addSamplesToHistogram(
+ samplesSet.firstMeaningfulPaintCpuTimeSamples,
+ firstMeaningfulPaintCpuTimeHistogram,
+ histograms);
+ addSamplesToHistogram(
+ samplesSet.interactiveSamples,
+ timeToInteractiveHistogram,
+ histograms);
+ addSamplesToHistogram(
+ samplesSet.firstCpuIdleSamples,
+ timeToFirstCpuIdleHistogram,
+ histograms);
+ }
+
+ tr.metrics.MetricRegistry.register(loadingMetric);
+
+ return {
+ loadingMetric,
+ getNetworkEventsInRange,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html
new file mode 100644
index 00000000000..16b2dad797f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/loading_metric_test.html
@@ -0,0 +1,1142 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import"
+ href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/metrics/system_health/loading_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('timeToFirstPaint', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'rail,loading,devtools.timeline',
+ title: 'firstPaint',
+ start: 1001,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('timeToFirstPaint');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(801, hist.running.mean);
+ });
+
+
+ test('timeToFirstContentfulPaint', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'ResourceDispatcher::OnRequestComplete',
+ start: 200,
+ duration: 100,
+ cpuStart: 210,
+ cpuDuration: 25,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('timeToFirstContentfulPaint');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(800, hist.running.mean);
+ const fcpResourceLoading = histograms.getHistogramNamed(
+ 'timeToFirstContentfulPaint:resource_loading');
+ assert.strictEqual(
+ hist.diagnostics.get('breakdown').get(
+ 'resource_loading'),
+ 'timeToFirstContentfulPaint:resource_loading');
+ assert.strictEqual(fcpResourceLoading.sum, 100);
+ assert.strictEqual(tr.b.getOnlyElement(hist.getBinForValue(
+ 800).diagnosticMaps).get('breakdown').get('resource_loading'), 100);
+ });
+
+
+ test('timeToFirstViewportReady', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'pc',
+ start: 1200,
+ duration: 0.0,
+ args: {data: {navigationId: '0xsecondnav'}}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'pc',
+ start: 1300,
+ duration: 0.0,
+ args: {data: {navigationId: '0xsecondnav'}}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'visible',
+ start: 300,
+ duration: 0.0,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('timeToFirstViewportReady');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(1000, hist.running.mean);
+ });
+
+
+ test('aboveTheFoldLoadedToVisibleHistogram', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'pc',
+ start: 1300,
+ duration: 0.0,
+ args: {data: {navigationId: '0xsecondnav'}}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 300,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef', data: {navigationId: '0xfirstnav'}}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 400,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef', data: {navigationId: '0xsecondnav'}}
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed(
+ 'aboveTheFoldLoadedToVisible');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(900, hist.running.mean);
+ });
+
+
+ test('timeToFirstContentfulPaintIgnoringWarmCache', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ // warm cache navigation
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'blink.console',
+ title: 'telemetry.internal.warm_cache.warm.start',
+ start: 250,
+ duration: 0.0
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'blink.console',
+ title: 'telemetry.internal.warm_cache.warm.end',
+ start: 1250,
+ duration: 0.0
+ }));
+
+ // measurement navigation
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 2000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 2100,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: 2400,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('timeToFirstContentfulPaint');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(400, hist.running.mean);
+ });
+
+ test('timeToFirstContentfulPaintInCpuTime', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'ResourceDispatcher::OnRequestComplete',
+ start: 200,
+ duration: 100,
+ cpuStart: 210,
+ cpuDuration: 25,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('cpuTimeToFirstContentfulPaint');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(25, hist.running.mean);
+ assert.strictEqual(tr.b.getOnlyElement(hist.getBinForValue(
+ 25).diagnosticMaps).get('breakdown').get('resource_loading'), 25);
+ });
+
+ test('timeToFirstContentfulPaintWithNavId', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef', data: {navigationId: '0xfirstnav'}}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 400,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef', data: {navigationId: '0xsecondnav'}}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef', data: {navigationId: '0xfirstnav'}}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'ResourceDispatcher::OnRequestComplete',
+ start: 200,
+ duration: 100,
+ cpuStart: 210,
+ cpuDuration: 25,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('timeToFirstContentfulPaint');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(800, hist.running.mean);
+ const fcpResourceLoading = histograms.getHistogramNamed(
+ 'timeToFirstContentfulPaint:resource_loading');
+ assert.strictEqual(
+ hist.diagnostics.get('breakdown').get(
+ 'resource_loading'),
+ 'timeToFirstContentfulPaint:resource_loading');
+ assert.strictEqual(fcpResourceLoading.sum, 100);
+ assert.strictEqual(tr.b.getOnlyElement(hist.getBinForValue(
+ 800).diagnosticMaps).get('breakdown').get('resource_loading'), 100);
+ });
+
+ test('timeToFirstMeaningfulPaint', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 600,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('timeToFirstMeaningfulPaint');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(800, hist.running.mean);
+ });
+
+ // [-------CPU: 300-----------]
+ // | [---CPU: 100---] |
+ // | | | |
+ // v v v v
+ // Ts: 100 200 Start 300 500 600
+ // | |
+ // Start FMP
+ test('cpuTimeToFirstMeaningfulPaint_withEmbeddedSlices', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ cpuStart: 1160,
+ cpuDuration: 0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 600,
+ duration: 0.0,
+ cpuStart: 1480,
+ cpuDuration: 0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 100,
+ duration: 400,
+ cpuStart: 1000,
+ cpuDuration: 300,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'ResourceDispatcher::OnRequestComplete',
+ start: 200,
+ duration: 100,
+ cpuStart: 1150,
+ cpuDuration: 100,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('cpuTimeToFirstMeaningfulPaint');
+ assert.deepEqual(hist.sampleValues, [225]);
+ const histBin = hist.getBinForValue(225);
+ assert.closeTo(histBin.diagnosticMaps[0]
+ .get('breakdown').get('other'), 400 / 3, 0.1);
+ assert.strictEqual(histBin.diagnosticMaps[0]
+ .get('breakdown').get('resource_loading'), 100);
+ });
+
+ // [-------------] [------------------]
+ // | | | |
+ // v v v v
+ // Ts: 100 Start 300 500 FMP 700
+ // | |
+ // 200 600
+ test('cpuTimeToFirstMeaningfulPaint_withIntersectingBoundary', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ cpuStart: 1160,
+ cpuDuration: 0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 600,
+ duration: 0.0,
+ cpuStart: 1280,
+ cpuDuration: 0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 100,
+ duration: 200,
+ cpuStart: 1060,
+ cpuDuration: 180,
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 500,
+ duration: 200,
+ cpuStart: 1250,
+ cpuDuration: 100,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('cpuTimeToFirstMeaningfulPaint');
+ assert.strictEqual(1, hist.running.count);
+ assert.strictEqual(140, hist.running.mean);
+ });
+
+ // Render 1:
+ //
+ // [--------]
+ // | |
+ // v v
+ // CPU Time: Start 1180 1230 FMP
+ // | |
+ // 1160 1280
+ //
+ // Render 2:
+ //
+ // [-------------]
+ // | |
+ // v v
+ // CPU Time: Start 1170 1270 FMP
+ // | |
+ // 1160 1280
+ test('cpuTimeToFirstMeaningfulPaint_multipleRenderers', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess1 = model.rendererProcess;
+ let mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ cpuStart: 1160,
+ cpuDuration: 0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess1.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 600,
+ duration: 0.0,
+ cpuStart: 1280,
+ cpuDuration: 0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loader',
+ title: 'ResourceDispatcher::OnRequestComplete',
+ start: 300,
+ duration: 200,
+ cpuStart: 1180,
+ cpuDuration: 50
+ }));
+
+ const rendererProcess2 = model.getOrCreateProcess(10);
+ mainThread = rendererProcess2.getOrCreateThread(20);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ cpuStart: 1160,
+ cpuDuration: 0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess2.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 600,
+ duration: 0.0,
+ cpuStart: 1280,
+ cpuDuration: 0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 300,
+ duration: 200,
+ cpuStart: 1170,
+ cpuDuration: 100,
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('cpuTimeToFirstMeaningfulPaint');
+ assert.deepEqual(hist.sampleValues, [50, 100]);
+ const histBin1 = hist.getBinForValue(50);
+ assert.strictEqual(histBin1.diagnosticMaps[0]
+ .get('breakdown').get('resource_loading'), 50);
+ const histBin2 = hist.getBinForValue(100);
+ assert.strictEqual(histBin2.diagnosticMaps[0]
+ .get('breakdown').get('other'), 100);
+ });
+
+ function addFrameLoaderObject_(rendererProcess, timestamp) {
+ rendererProcess.objects.addSnapshot(
+ 'ptr', 'loading', 'FrameLoader', timestamp, {
+ isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com',
+ });
+ }
+
+ function addNavigationStart_(rendererMain, timestamp, opt_data) {
+ rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: timestamp,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef', data: opt_data}
+ }));
+ }
+
+ // Some utility functions to make tests easier to read.
+ function addFirstMeaningfulPaint_(rendererMain, timestamp) {
+ rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: timestamp,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ }
+
+ function addDomContentLoadedEnd_(rendererMain, timestamp) {
+ rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: timestamp,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ }
+
+ function addTopLevelTask_(rendererMain, start, duration) {
+ rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start,
+ duration,
+ }));
+ }
+
+ function addNetworkRequest_(rendererMain, start, duration) {
+ const networkEvents = [];
+ rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start,
+ duration,
+ }));
+ }
+
+ test('loadExpectationMetrics_urlDirectlyFromNavStartEvent', function() {
+ // If the navigation start event contains the URL, we should not require a
+ // FrameLoader snapshot before the event. See https://crbug.com/824761.
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200,
+ {isLoadingMainFrame: true, documentLoaderURL: 'http://example.com'});
+ addNetworkRequest_(mainThread, 200, 250);
+ // FrameLoader creation time after navigation start.
+ rendererProcess.objects.idWasCreated(
+ 'ptr', 'loading', 'FrameLoader', 250);
+ rendererProcess.objects.addSnapshot(
+ 'ptr', 'loading', 'FrameLoader', 300, {
+ isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com',
+ });
+
+ addFirstMeaningfulPaint_(mainThread, 500);
+ addDomContentLoadedEnd_(mainThread, 600);
+
+ // New navigation to close the search window.
+ addNavigationStart_(mainThread, 7000,
+ {isLoadingMainFrame: true, documentLoaderURL: 'http://example.com'});
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const fmpHist = histograms.getHistogramNamed('timeToFirstMeaningfulPaint');
+ assert.strictEqual(1, fmpHist.running.count);
+ assert.strictEqual(300, fmpHist.running.mean);
+ // Both TTI and First CPU Idle firing at DCL.
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(1, ttiHist.running.count);
+ assert.strictEqual(400, ttiHist.running.mean);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(1, firstCpuIdleHist.running.count);
+ assert.strictEqual(400, firstCpuIdleHist.running.mean);
+ });
+
+ test('interactivityMetrics_notAffectedByShortTasks', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addNetworkRequest_(mainThread, 200, 250);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addFirstMeaningfulPaint_(mainThread, 500);
+ addDomContentLoadedEnd_(mainThread, 600);
+
+ const mainThreadTopLevelTasks = [
+ {start: 800, duration: 100}, // Long task
+ {start: 1500, duration: 200}, // Last long task. TTI at 1700.
+ {start: 2000, duration: 49}, // Short task.
+ ];
+ for (const task of mainThreadTopLevelTasks) {
+ addTopLevelTask_(mainThread, task.start, task.duration);
+ }
+
+ // New navigation to close the search window.
+ addNavigationStart_(mainThread, 7000);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(1, ttiHist.running.count);
+ // 1700 - 200 (navStart) = 1500.
+ assert.strictEqual(1500, ttiHist.running.mean);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(1, firstCpuIdleHist.running.count);
+ // 1700 - 200 (navStart) = 1500.
+ assert.strictEqual(1500, firstCpuIdleHist.running.mean);
+ });
+
+ test('interactivityMetrics_longTaskBeforeFMP', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addNetworkRequest_(mainThread, 200, 50);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addDomContentLoadedEnd_(mainThread, 600);
+ addTopLevelTask_(mainThread, 600, 200);
+ addFirstMeaningfulPaint_(mainThread, 1000); // TTI at FMP.
+ // New navigation to close the search window.
+ addNavigationStart_(mainThread, 7000);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(1, ttiHist.running.count);
+ // 1000 - 200 (navStart) = 800.
+ assert.strictEqual(800, ttiHist.running.mean);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(1, firstCpuIdleHist.running.count);
+ // 1000 - 200 (navStart) = 800.
+ assert.strictEqual(800, firstCpuIdleHist.running.mean);
+ });
+
+ test('interactivityMetrics_interactiveAtDCL', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addNetworkRequest_(mainThread, 200, 50);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addFirstMeaningfulPaint_(mainThread, 1000);
+ addDomContentLoadedEnd_(mainThread, 3000);
+ // New navigation to close the search window.
+ addNavigationStart_(mainThread, 7000);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(1, ttiHist.running.count);
+ // 3000 - 200 (navStart) = 2800.
+ assert.strictEqual(2800, ttiHist.running.mean);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(1, firstCpuIdleHist.running.count);
+ // 3000 - 200 (navStart) = 2800.
+ assert.strictEqual(2800, firstCpuIdleHist.running.mean);
+ });
+
+ test('interactivityMetrics_networkBusyBlocksInteractivity', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addFirstMeaningfulPaint_(mainThread, 1000);
+ addDomContentLoadedEnd_(mainThread, 1100);
+ // Network busy requires at least three network requests.
+ addNetworkRequest_(mainThread, 1000, 7000);
+ addNetworkRequest_(mainThread, 1001, 7001);
+ addNetworkRequest_(mainThread, 1002, 7002);
+ // 400ms task makes a "heavy task cluster" for idle.
+ addTopLevelTask_(mainThread, 1200, 400);
+ // Next long task is more than five seconds away, but TTI is not reached
+ // yet since network is busy. TTI is at the at of this task.
+ addTopLevelTask_(mainThread, 6800, 200);
+ // New navigation to close the search window.
+ addNavigationStart_(mainThread, 13000);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(1, ttiHist.running.count);
+ // 7000 - 200 (navStart) = 6800.
+ assert.strictEqual(6800, ttiHist.running.mean);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(1, firstCpuIdleHist.running.count);
+ // 1600 - 200 (navStart) = 1400. CPU Idle is not affected by network.
+ assert.strictEqual(1400, firstCpuIdleHist.running.mean);
+ });
+
+ test('interactivityMetrics_notReportedIfTracingEndsEarly', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addNetworkRequest_(mainThread, 200, 50);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addDomContentLoadedEnd_(mainThread, 600);
+ addFirstMeaningfulPaint_(mainThread, 1000);
+ addTopLevelTask_(mainThread, 2000, 400);
+ // Last task in the model. 2501 will be considered end of tracing.
+ addTopLevelTask_(mainThread, 2500, 1);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(0, ttiHist.numValues);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(0, firstCpuIdleHist.numValues);
+ });
+
+ test('interactivityMetrics_notReportedIfNextNavigationIsEarly', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addNetworkRequest_(mainThread, 200, 50);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addDomContentLoadedEnd_(mainThread, 600);
+ addFirstMeaningfulPaint_(mainThread, 1000);
+ addTopLevelTask_(mainThread, 2000, 400);
+ // New navigation to close the search window. The window is not big enough
+ // to reach TTI.
+ addNavigationStart_(mainThread, 3000);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(0, ttiHist.numValues);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(0, firstCpuIdleHist.numValues);
+ });
+
+ test('interactivityMetrics_reportsValueForLastNavigation', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addNetworkRequest_(mainThread, 200, 50);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addDomContentLoadedEnd_(mainThread, 600);
+ addFirstMeaningfulPaint_(mainThread, 1000);
+ addTopLevelTask_(mainThread, 2000, 400);
+ // Last task in the model. 8001 will be considered end of tracing, so
+ // there is sufficiently large window to detect TTI.
+ addTopLevelTask_(mainThread, 8000, 1);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(1, ttiHist.running.count);
+ // 2400 - 200 (navStart) = 2200.
+ assert.strictEqual(2200, ttiHist.running.mean);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(1, firstCpuIdleHist.running.count);
+ // 2400 - 200 (navStart) = 2200.
+ assert.strictEqual(2200, firstCpuIdleHist.running.mean);
+ });
+
+ test('interactivityMetrics_multipleRenderers', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const renderers =
+ [model.getOrCreateProcess(1984), model.getOrCreateProcess(1985)];
+
+ for (const i of [0, 1]) {
+ const rendererProcess = renderers[i];
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'CrRendererMain';
+ addNavigationStart_(mainThread, 200);
+ addNetworkRequest_(mainThread, 200, 50);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addDomContentLoadedEnd_(mainThread, 600);
+ addFirstMeaningfulPaint_(mainThread, 1000);
+ // Durations are 400 and 800 for i value of 0 an 1.
+ addTopLevelTask_(mainThread, 2000, (i + 1) * 400);
+ // New navigation to close the search window.
+ addNavigationStart_(mainThread, 10000);
+ }
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(2, ttiHist.running.count);
+ // 2800 - 200 (navStart) = 2200, and 2400 - 200 = 2200.
+ assert.strictEqual(2600, ttiHist.running.max);
+ assert.strictEqual(2200, ttiHist.running.min);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(2, firstCpuIdleHist.running.count);
+ // 2800 - 200 (navStart) = 2200, and 2400 - 200 = 2200.
+ assert.strictEqual(2600, firstCpuIdleHist.running.max);
+ assert.strictEqual(2200, firstCpuIdleHist.running.min);
+ });
+
+ test('interactivityMetrics_eventsFromMultipleFrame', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addNetworkRequest_(mainThread, 200, 50);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addFirstMeaningfulPaint_(mainThread, 1000);
+ // No long task. TTI is reached at 3000.
+ addDomContentLoadedEnd_(mainThread, 3000);
+
+ // DomContentLoadedEnd and NavigationStart for a different frame.
+ rendererProcess.objects.addSnapshot(
+ 'ptr', 'loading', 'FrameLoader', 4000, {
+ isLoadingMainFrame: true, frame: {id_ref: '0xffffffff'},
+ documentLoaderURL: 'http://example.com'
+ });
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 4000,
+ duration: 0.0,
+ args: {frame: '0xffffffff'},
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 4500,
+ duration: 0.0,
+ args: {frame: '0xffffffff'}
+ }));
+
+ // Last task in the model. 8001 will be considered end of tracing, so
+ // there is sufficiently large window to detect TTI.
+ addTopLevelTask_(mainThread, 8000, 1);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(1, ttiHist.running.count);
+ // 3000 - 200 (navStart) = 2800.
+ assert.strictEqual(2800, ttiHist.running.mean);
+ const firstCpuIdleHist = histograms.getHistogramNamed('timeToFirstCpuIdle');
+ assert.strictEqual(1, firstCpuIdleHist.running.count);
+ // 3000 - 200 (navStart) = 2800.
+ assert.strictEqual(2800, firstCpuIdleHist.running.mean);
+ });
+
+ test('timeToInteractive_notReportedWithoutResourceLoadEvents', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+
+ addNavigationStart_(mainThread, 200);
+ addFrameLoaderObject_(rendererProcess, 300);
+ addDomContentLoadedEnd_(mainThread, 600);
+ addFirstMeaningfulPaint_(mainThread, 1000);
+ addTopLevelTask_(mainThread, 2000, 400);
+ // Last task in the model. 8001 will be considered end of tracing, so
+ // there is sufficiently large window to detect TTI.
+ addTopLevelTask_(mainThread, 8000, 1);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const ttiHist = histograms.getHistogramNamed('timeToInteractive');
+ assert.strictEqual(0, ttiHist.numValues);
+ });
+
+
+ test('webView', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const process = model.rendererProcess;
+ const rendererThread = model.rendererMain;
+ rendererThread.name = 'Chrome_InProcRendererThread';
+ rendererThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ process.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {
+ isLoadingMainFrame: true,
+ frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'
+ });
+ rendererThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading,rail,devtools.timeline',
+ title: 'firstContentfulPaint',
+ start: 600,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.loadingMetric(histograms, model);
+ const fcp = histograms.getHistogramNamed('timeToFirstContentfulPaint');
+ assert.strictEqual(1, fcp.running.count);
+ assert.strictEqual(400, fcp.running.mean);
+ const fmp = histograms.getHistogramNamed('timeToFirstMeaningfulPaint');
+ assert.strictEqual(1, fmp.running.count);
+ assert.strictEqual(800, fmp.running.mean);
+ });
+
+ test('testGetNetworkEvents', function() {
+ // Our renderer looks like:
+ // [ irrelevant syncEvent ]
+ // [ irrelevant asyncEvent ]
+ // | [ d..netlog]
+ // [ netlog ] [ d..network] [ net ]
+ // | | | | | |
+ // | | | | | |
+ // | | | | | |
+ // v v v v v v
+ // Ts: 100 200 400 450 510 520
+ const rendererPid = 245;
+ const netEvent1 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'netlog',
+ title: 'Generic Network event',
+ start: 100,
+ duration: 100,
+ });
+ const netEvent2 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start: 400,
+ duration: 50,
+ });
+ const netEvent3 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'net',
+ title: 'ResourceLoad',
+ start: 510,
+ duration: 10,
+ });
+ const netEvent4 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'disabled-by-default-netlog',
+ title: 'ResourceLoad',
+ start: 510,
+ duration: 10,
+ });
+ const irrelevantAsyncEvent = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'irrelevant',
+ title: 'ResourceLoad',
+ start: 0,
+ duration: 510,
+ });
+ const irrelevantSyncEvent = tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 510,
+ args: {frame: '0xdeadbeef'}
+ });
+
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const rendererProcess = model.getOrCreateProcess(rendererPid);
+ const thread1 = rendererProcess.getOrCreateThread(1);
+ thread1.name = 'CrRendererMain';
+ thread1.asyncSliceGroup.push(netEvent1);
+ const thread2 = rendererProcess.getOrCreateThread(2);
+ thread2.name = 'thread2';
+ thread2.asyncSliceGroup.push(netEvent2);
+ const thread3 = rendererProcess.getOrCreateThread(3);
+ thread3.name = 'thread2';
+ thread3.asyncSliceGroup.push(netEvent3);
+ const thread4 = rendererProcess.getOrCreateThread(4);
+ thread4.name = 'thread2';
+ thread4.asyncSliceGroup.push(netEvent4);
+ const thread5 = rendererProcess.getOrCreateThread(5);
+ thread5.name = 'thread5';
+ thread5.asyncSliceGroup.push(irrelevantAsyncEvent);
+ const thread6 = rendererProcess.getOrCreateThread(6);
+ thread6.name = 'thread6';
+ thread6.sliceGroup.pushSlice(irrelevantSyncEvent);
+ });
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelper = chromeHelper.rendererHelpers[rendererPid];
+ const allNetworkEvents = tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, tr.b.math.Range.fromExplicitRange(0, 550));
+ assert.sameDeepMembers(
+ [netEvent1, netEvent2, netEvent3, netEvent4],
+ allNetworkEvents);
+
+ const partialNetworkEvents = tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, tr.b.math.Range.fromExplicitRange(0, 460));
+ assert.strictEqual(2, partialNetworkEvents.length);
+ assert.sameDeepMembers(
+ [netEvent1, netEvent2],
+ partialNetworkEvents);
+
+ const networkEventsWithIntersecting =
+ tr.metrics.sh.getNetworkEventsInRange(
+ rendererHelper.process, tr.b.math.Range.fromExplicitRange(0, 410));
+ assert.sameDeepMembers(
+ [netEvent1, netEvent2],
+ partialNetworkEvents);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/long_tasks_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/long_tasks_metric.html
new file mode 100644
index 00000000000..e42683d3164
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/long_tasks_metric.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ const LONG_TASK_MS = 50;
+
+ // Anything longer than this should be so rare that its length beyond this is
+ // uninteresting.
+ const LONGEST_TASK_MS = 1000;
+
+ /**
+ * This helper function calls |cb| for each of the top-level tasks on the
+ * given thread in the given range whose duration is longer than LONG_TASK_MS.
+ *
+ * @param {tr.model.Thread} thread
+ * @param {tr.b.math.Range=} opt_range
+ * @param {function()} cb
+ * @param {Object=} opt_this
+ */
+ function iterateLongTopLevelTasksOnThreadInRange(
+ thread, opt_range, cb, opt_this) {
+ thread.sliceGroup.topLevelSlices.forEach(function(slice) {
+ if (opt_range &&
+ !opt_range.intersectsExplicitRangeInclusive(slice.start, slice.end)) {
+ return;
+ }
+
+ if (slice.duration < LONG_TASK_MS) return;
+
+ cb.call(opt_this, slice);
+ });
+ }
+
+ /**
+ * This helper function calls |cb| for each of the main renderer threads in
+ * the model.
+ *
+ * @param {tr.model.Model} model The model.
+ * @param {function()} cb Callback.
+ * @param {Object=} opt_this Context object.
+ */
+ function iterateRendererMainThreads(model, cb, opt_this) {
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (modelHelper !== undefined) {
+ Object.values(modelHelper.rendererHelpers).forEach(
+ function(rendererHelper) {
+ if (!rendererHelper.mainThread) return;
+
+ cb.call(opt_this, rendererHelper.mainThread);
+ });
+ }
+ }
+
+ const BIN_BOUNDARIES = tr.v.HistogramBinBoundaries.createLinear(
+ LONG_TASK_MS, LONGEST_TASK_MS, 40);
+
+ /**
+ * This metric directly measures long tasks on renderer main threads.
+ * This metric requires only the 'toplevel' tracing category.
+ *
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!tr.model.Model} model
+ * @param {!Object=} opt_options
+ */
+ function longTasksMetric(histograms, model, opt_options) {
+ const rangeOfInterest = opt_options ? opt_options.rangeOfInterest :
+ undefined;
+ const longTaskHist = histograms.createHistogram(
+ 'longTasks', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: BIN_BOUNDARIES,
+ description: 'durations of long tasks',
+ });
+
+ const relatedNames = new tr.v.d.RelatedNameMap();
+ longTaskHist.diagnostics.set('categories', relatedNames);
+
+ iterateRendererMainThreads(model, function(thread) {
+ iterateLongTopLevelTasksOnThreadInRange(
+ thread, rangeOfInterest, function(task) {
+ const breakdown = new tr.v.d.Breakdown();
+ breakdown.colorScheme =
+ tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;
+ for (const slice of task.descendentSlices) {
+ const sample = slice.cpuSelfTime;
+ if (sample === undefined) continue;
+
+ const category = model.getUserFriendlyCategoryFromEvent(slice);
+ const histName = 'longTasks:' + category;
+ let hist = histograms.getHistogramNamed(histName);
+ if (hist === undefined) {
+ hist = histograms.createHistogram(histName,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: BIN_BOUNDARIES,
+ });
+ relatedNames.set(category, hist.name);
+ }
+ hist.addSample(sample, {
+ events: new tr.v.d.RelatedEventSet([slice]),
+ });
+ breakdown.set(category, sample + breakdown.get(category));
+ }
+
+ longTaskHist.addSample(task.duration, {
+ events: new tr.v.d.RelatedEventSet([task]),
+ categories: breakdown,
+ });
+ });
+ });
+ }
+
+ tr.metrics.MetricRegistry.register(longTasksMetric, {
+ supportsRangeOfInterest: true,
+ requiredCategories: ['toplevel'],
+ });
+
+ return {
+ longTasksMetric,
+ iterateLongTopLevelTasksOnThreadInRange,
+ iterateRendererMainThreads,
+ LONG_TASK_MS,
+ LONGEST_TASK_MS,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/long_tasks_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/long_tasks_metric_test.html
new file mode 100644
index 00000000000..ecfeabd2a5a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/long_tasks_metric_test.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/metrics/system_health/long_tasks_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('longTasksMetric', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const proc = model.getOrCreateProcess(1);
+ const thread = proc.getOrCreateThread(2);
+ thread.name = 'CrRendererMain';
+ const longTask = tr.c.TestUtils.newSliceEx({
+ title: 'foo',
+ start: 0,
+ duration: 50,
+ });
+ thread.sliceGroup.pushSlice(longTask);
+
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'UpdateLayerTree',
+ start: 0,
+ duration: 1,
+ cpuStart: 0,
+ cpuDuration: 1,
+ }));
+
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'minorGC',
+ start: 1,
+ duration: 1,
+ cpuStart: 1,
+ cpuDuration: 1,
+ }));
+
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'Decode Image',
+ start: 2,
+ duration: 1,
+ cpuStart: 2,
+ cpuDuration: 1,
+ }));
+
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: 'Layout',
+ start: 3,
+ duration: 1,
+ cpuStart: 3,
+ cpuDuration: 1,
+ }));
+
+ model.addUserFriendlyCategoryDriver(
+ tr.e.chrome.ChromeUserFriendlyCategoryDriver);
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.longTasksMetric(histograms, model);
+
+ const longTaskHist = histograms.getHistogramNamed('longTasks');
+ assert.strictEqual(1, longTaskHist.numValues);
+
+ const relatedNames = longTaskHist.diagnostics.get('categories');
+ assert.instanceOf(relatedNames, tr.v.d.RelatedNameMap);
+ assert.strictEqual(relatedNames.get('layout'), 'longTasks:layout');
+ assert.strictEqual(relatedNames.get('gc'), 'longTasks:gc');
+ assert.strictEqual(relatedNames.get('composite'), 'longTasks:composite');
+ assert.strictEqual(relatedNames.get('imageDecode'),
+ 'longTasks:imageDecode');
+
+ const bin = longTaskHist.getBinForValue(longTaskHist.average);
+ const diagnostics = tr.b.getOnlyElement(bin.diagnosticMaps);
+ const breakdown = diagnostics.get('categories');
+ assert.instanceOf(breakdown, tr.v.d.Breakdown);
+ assert.strictEqual(breakdown.size, 4);
+
+ const taskEventSet = diagnostics.get('events');
+ assert.instanceOf(taskEventSet, tr.v.d.RelatedEventSet);
+ assert.lengthOf(taskEventSet, 1);
+
+ const layoutHist = histograms.getHistogramNamed('longTasks:layout');
+ assert.strictEqual(1, layoutHist.numValues);
+ assert.lengthOf(tr.b.getOnlyElement(layoutHist.getBinForValue(
+ layoutHist.average).diagnosticMaps).get('events'), 1);
+
+ const gcHist = histograms.getHistogramNamed('longTasks:gc');
+ assert.strictEqual(1, gcHist.numValues);
+ assert.lengthOf(tr.b.getOnlyElement(gcHist.getBinForValue(
+ gcHist.average).diagnosticMaps).get('events'), 1);
+
+ const compositeHist = histograms.getHistogramNamed('longTasks:composite');
+ assert.strictEqual(1, compositeHist.numValues);
+ assert.lengthOf(tr.b.getOnlyElement(compositeHist.getBinForValue(
+ compositeHist.average).diagnosticMaps).get('events'), 1);
+
+ const imageDecodeHist = histograms.getHistogramNamed(
+ 'longTasks:imageDecode');
+ assert.strictEqual(1, imageDecodeHist.numValues);
+ assert.lengthOf(tr.b.getOnlyElement(imageDecodeHist.getBinForValue(
+ imageDecodeHist.average).diagnosticMaps).get('events'), 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html
new file mode 100644
index 00000000000..68a90814bd0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric.html
@@ -0,0 +1,1332 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/multi_dimensional_view.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_processes.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/value/diagnostics/breakdown.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ const BACKGROUND = tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;
+ const LIGHT = tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;
+ const DETAILED = tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const count_smallerIsBetter = tr.b.Unit.byName.count_smallerIsBetter;
+ const DISPLAYED_SIZE_NUMERIC_NAME =
+ tr.model.MemoryAllocatorDump.DISPLAYED_SIZE_NUMERIC_NAME;
+
+ const LEVEL_OF_DETAIL_NAMES = new Map();
+ LEVEL_OF_DETAIL_NAMES.set(BACKGROUND, 'background');
+ LEVEL_OF_DETAIL_NAMES.set(LIGHT, 'light');
+ LEVEL_OF_DETAIL_NAMES.set(DETAILED, 'detailed');
+
+ // Some detailed dumps contain heap profiler information.
+ const HEAP_PROFILER_DETAIL_NAME = 'heap_profiler';
+
+ const BOUNDARIES_FOR_UNIT_MAP = new WeakMap();
+ // For unitless numerics (process counts), we use 20 linearly scaled bins
+ // from 0 to 20.
+ BOUNDARIES_FOR_UNIT_MAP.set(count_smallerIsBetter,
+ tr.v.HistogramBinBoundaries.createLinear(0, 20, 20));
+ // For size numerics (subsystem and vm stats), we use 1 bin from 0 B to
+ // 1 KiB and 4*24 exponentially scaled bins from 1 KiB to 16 GiB (=2^24 KiB).
+ BOUNDARIES_FOR_UNIT_MAP.set(sizeInBytes_smallerIsBetter,
+ new tr.v.HistogramBinBoundaries(0)
+ .addBinBoundary(1024 /* 1 KiB */)
+ .addExponentialBins(16 * 1024 * 1024 * 1024 /* 16 GiB */, 4 * 24));
+
+ const CHROME_PROCESS_NAMES =
+ tr.e.chrome.chrome_processes.CHROME_PROCESS_NAMES;
+
+ function memoryMetric(values, model, opt_options) {
+ const rangeOfInterest =
+ opt_options ? opt_options.rangeOfInterest : undefined;
+ const browserNameToGlobalDumps =
+ tr.metrics.sh.splitGlobalDumpsByBrowserName(model, rangeOfInterest);
+ addGeneralMemoryDumpValues(browserNameToGlobalDumps, values);
+ addDetailedMemoryDumpValues(browserNameToGlobalDumps, values);
+ addMemoryDumpCountValues(browserNameToGlobalDumps, values);
+ }
+
+ const USER_FRIENDLY_BROWSER_NAMES = {
+ 'chrome': 'Chrome',
+ 'webview': 'WebView',
+ 'unknown_browser': 'an unknown browser'
+ };
+
+ /**
+ * Convert a canonical browser name used in value names to a user-friendly
+ * name used in value descriptions.
+ *
+ * Examples:
+ *
+ * CANONICAL BROWSER NAME -> USER-FRIENDLY NAME
+ * chrome -> Chrome
+ * unknown_browser -> an unknown browser
+ * webview2 -> WebView(2)
+ * unexpected -> 'unexpected' browser
+ */
+ function convertBrowserNameToUserFriendlyName(browserName) {
+ for (const baseName in USER_FRIENDLY_BROWSER_NAMES) {
+ if (!browserName.startsWith(baseName)) continue;
+
+ const userFriendlyBaseName = USER_FRIENDLY_BROWSER_NAMES[baseName];
+ const suffix = browserName.substring(baseName.length);
+ if (suffix.length === 0) {
+ return userFriendlyBaseName;
+ } else if (/^\d+$/.test(suffix)) {
+ return userFriendlyBaseName + '(' + suffix + ')';
+ }
+ }
+ return '\'' + browserName + '\' browser';
+ }
+
+
+ /**
+ * Convert a canonical process name used in value names to a user-friendly
+ * name used in value descriptions.
+ */
+ function convertProcessNameToUserFriendlyName(processName,
+ opt_requirePlural) {
+ switch (processName) {
+ case CHROME_PROCESS_NAMES.BROWSER:
+ return opt_requirePlural ? 'browser processes' : 'the browser process';
+ case CHROME_PROCESS_NAMES.RENDERER:
+ return 'renderer processes';
+ case CHROME_PROCESS_NAMES.GPU:
+ return opt_requirePlural ? 'GPU processes' : 'the GPU process';
+ case CHROME_PROCESS_NAMES.PPAPI:
+ return opt_requirePlural ? 'PPAPI processes' : 'the PPAPI process';
+ case CHROME_PROCESS_NAMES.ALL:
+ return 'all processes';
+ case CHROME_PROCESS_NAMES.UNKNOWN:
+ return 'unknown processes';
+ default:
+ return '\'' + processName + '\' processes';
+ }
+ }
+
+ /**
+ * Add general memory dump values calculated from all global memory dumps to
+ * |values|. In particular, this function adds the following values:
+ *
+ * * PROCESS COUNTS
+ * memory:{chrome, webview}:
+ * {browser_process, renderer_processes, ..., all_processes}:
+ * process_count
+ * type: tr.v.Histogram (over all matching global memory dumps)
+ * unit: count_smallerIsBetter
+ *
+ * * MEMORY USAGE REPORTED BY CHROME
+ * memory:{chrome, webview}:
+ * {browser_process, renderer_processes, ..., all_processes}:
+ * reported_by_chrome[:{v8, malloc, ...}]:
+ * {effective_size, allocated_objects_size, locked_size}
+ * type: tr.v.Histogram (over all matching global memory dumps)
+ * unit: sizeInBytes_smallerIsBetter
+ */
+ function addGeneralMemoryDumpValues(browserNameToGlobalDumps, values) {
+ addMemoryDumpValues(browserNameToGlobalDumps,
+ gmd => true /* process all global memory dumps */,
+ function(processDump, addProcessScalar) {
+ // Increment memory:<browser-name>:<process-name>:process_count value.
+ addProcessScalar({
+ source: 'process_count',
+ property: PROCESS_COUNT,
+ value: 1
+ });
+
+ if (processDump.totals !== undefined) {
+ addProcessScalar({
+ source: 'reported_by_os',
+ property: RESIDENT_SIZE,
+ component: ['system_memory'],
+ value: processDump.totals.residentBytes
+ });
+ addProcessScalar({
+ source: 'reported_by_os',
+ property: PEAK_RESIDENT_SIZE,
+ component: ['system_memory'],
+ value: processDump.totals.peakResidentBytes
+ });
+ addProcessScalar({
+ source: 'reported_by_os',
+ property: PRIVATE_FOOTPRINT_SIZE,
+ component: ['system_memory'],
+ value: processDump.totals.privateFootprintBytes,
+ });
+ }
+
+ // Add memory:<browser-name>:<process-name>:reported_by_chrome:...
+ // values.
+ if (processDump.memoryAllocatorDumps === undefined) return;
+
+ processDump.memoryAllocatorDumps.forEach(function(rootAllocatorDump) {
+ CHROME_VALUE_PROPERTIES.forEach(function(property) {
+ addProcessScalar({
+ source: 'reported_by_chrome',
+ component: [rootAllocatorDump.name],
+ property,
+ value: rootAllocatorDump.numerics[property.name]
+ });
+ });
+ // Some dump providers add allocated objects size as
+ // "allocated_objects" child dump.
+ if (rootAllocatorDump.numerics.allocated_objects_size ===
+ undefined) {
+ const allocatedObjectsDump =
+ rootAllocatorDump.getDescendantDumpByFullName(
+ 'allocated_objects');
+ if (allocatedObjectsDump !== undefined) {
+ addProcessScalar({
+ source: 'reported_by_chrome',
+ component: [rootAllocatorDump.name],
+ property: ALLOCATED_OBJECTS_SIZE,
+ value: allocatedObjectsDump.numerics.size
+ });
+ }
+ }
+ });
+
+ // Add memory:<browser-name>:<process-name>:reported_by_chrome:
+ // {malloc, blinkgc, partitionalloc}:<largestCategory>:...
+ addTopHeapDumpCategoryValue(processDump, addProcessScalar);
+
+ // Add memory:<browser-name>:<process-name>:reported_by_chrome:v8:
+ // {heap, allocated_by_malloc}:...
+ addV8MemoryDumpValues(processDump, addProcessScalar);
+ },
+ function(componentTree) {
+ // Subtract memory:<browser-name>:<process-name>:reported_by_chrome:
+ // tracing:<size-property> from memory:<browser-name>:<process-name>:
+ // reported_by_chrome:<size-property> if applicable.
+ const tracingNode = componentTree.children[1].get('tracing');
+ if (tracingNode === undefined) return;
+
+ for (let i = 0; i < componentTree.values.length; i++) {
+ componentTree.values[i].total -= tracingNode.values[i].total;
+ }
+ }, values);
+ }
+
+ /**
+ * Add memory dump values for the top category in each allocator heap dump in
+ * the process dump.
+ *
+ * @param {!tr.model.ProcessMemoryDump} processDump The process memory dump.
+ * @param {!function} addProcessScalar The callback for adding a scalar value.
+ */
+ function addTopHeapDumpCategoryValue(processDump, addProcessScalar) {
+ if (!processDump.heapDumps) {
+ return;
+ }
+ for (const allocatorName in processDump.heapDumps) {
+ const heapDump = processDump.heapDumps[allocatorName];
+ if (heapDump.entries === undefined || heapDump.entries.length === 0) {
+ return;
+ }
+ // Create a map of category to total size.
+ const typeToSize = {};
+ for (let i = 0; i < heapDump.entries.length; i += 1) {
+ const entry = heapDump.entries[i];
+ // Count only the entries with empty backtrace which contains totals for
+ // the object type.
+ if (!entry.objectTypeName || entry.leafStackFrame) {
+ continue;
+ }
+ if (!typeToSize[entry.objectTypeName]) {
+ typeToSize[entry.objectTypeName] = 0;
+ }
+ typeToSize[entry.objectTypeName] += entry.size;
+ }
+
+ // Find the largest type in the heap dump.
+ let largestValue = 0;
+ let largestType = '';
+ for (const key in typeToSize) {
+ if (largestValue < typeToSize[key]) {
+ largestValue = typeToSize[key];
+ largestType = key;
+ }
+ }
+ addProcessScalar({
+ source: 'reported_by_chrome',
+ component: [allocatorName, largestType],
+ property: HEAP_CATEGORY_SIZE,
+ value: largestValue
+ });
+ }
+ }
+
+ /**
+ * Add memory dump values calculated from V8 components excluding
+ * 'heap_spaces/other_spaces'.
+ *
+ * @param {!tr.model.ProcessMemoryDump} processDump The process memory dump.
+ * @param {!function} addProcessScalar The callback for adding a scalar value.
+ */
+ function addV8MemoryDumpValues(processDump, addProcessScalar) {
+ const v8Dump = processDump.getMemoryAllocatorDumpByFullName('v8');
+ if (v8Dump === undefined) return;
+
+ v8Dump.children.forEach(function(isolateDump) {
+ // v8:allocated_by_malloc:...
+ const mallocDump = isolateDump.getDescendantDumpByFullName('malloc');
+ if (mallocDump !== undefined) {
+ addV8ComponentValues(mallocDump, ['v8', 'allocated_by_malloc'],
+ addProcessScalar);
+ }
+ // v8:heap:...
+ let heapDump = isolateDump.getDescendantDumpByFullName('heap');
+ if (heapDump === undefined) {
+ // Old V8 memory dumps call this 'heap_spaces'.
+ heapDump = isolateDump.getDescendantDumpByFullName('heap_spaces');
+ }
+ if (heapDump !== undefined) {
+ addV8ComponentValues(heapDump, ['v8', 'heap'], addProcessScalar);
+ heapDump.children.forEach(function(spaceDump) {
+ if (spaceDump.name === 'other_spaces') return;
+
+ addV8ComponentValues(spaceDump, ['v8', 'heap', spaceDump.name],
+ addProcessScalar);
+ });
+ }
+ });
+
+ // V8 generates bytecode when interpreting and code objects when
+ // compiling the javascript. Total code size includes the size
+ // of code and bytecode objects.
+ addProcessScalar({
+ source: 'reported_by_chrome',
+ component: ['v8'],
+ property: CODE_AND_METADATA_SIZE,
+ value: v8Dump.numerics.code_and_metadata_size
+ });
+ addProcessScalar({
+ source: 'reported_by_chrome',
+ component: ['v8'],
+ property: CODE_AND_METADATA_SIZE,
+ value: v8Dump.numerics.bytecode_and_metadata_size
+ });
+ }
+
+ /**
+ * Add memory dump values calculated from the specified V8 component.
+ *
+ * @param {!tr.model.MemoryAllocatorDump} v8Dump The V8 memory dump.
+ * @param {!Array<string>} componentPath The component path for reporting.
+ * @param {!function} addProcessScalar The callback for adding a scalar value.
+ */
+ function addV8ComponentValues(componentDump, componentPath,
+ addProcessScalar) {
+ CHROME_VALUE_PROPERTIES.forEach(function(property) {
+ addProcessScalar({
+ source: 'reported_by_chrome',
+ component: componentPath,
+ property,
+ value: componentDump.numerics[property.name]
+ });
+ });
+ }
+
+ const PROCESS_COUNT = {
+ unit: count_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ if (componentPath.length > 0) {
+ throw new Error('Unexpected process count non-empty component path: ' +
+ componentPath.join(':'));
+ }
+ return 'total number of ' + convertProcessNameToUserFriendlyName(
+ processName, true /* opt_requirePlural */);
+ }
+ };
+
+ const EFFECTIVE_SIZE = {
+ name: 'effective_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyName: 'effective size',
+ componentPreposition: 'of'
+ });
+ }
+ };
+
+ const ALLOCATED_OBJECTS_SIZE = {
+ name: 'allocated_objects_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyName: 'size of all objects allocated',
+ totalUserFriendlyPropertyName: 'size of all allocated objects',
+ componentPreposition: 'by'
+ });
+ }
+ };
+
+ const SHIM_ALLOCATED_OBJECTS_SIZE = {
+ name: 'shim_allocated_objects_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyName: 'size of all objects allocated through shim',
+ totalUserFriendlyPropertyName:
+ 'size of all allocated objects through shim',
+ componentPreposition: 'by'
+ });
+ }
+ };
+
+ const LOCKED_SIZE = {
+ name: 'locked_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyName: 'locked (pinned) size',
+ componentPreposition: 'of'
+ });
+ }
+ };
+
+ const PEAK_SIZE = {
+ name: 'peak_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyName: 'peak size',
+ componentPreposition: 'of'
+ });
+ }
+ };
+
+ const HEAP_CATEGORY_SIZE = {
+ name: 'heap_category_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyName: 'heap profiler category size',
+ componentPreposition: 'for'
+ });
+ }
+ };
+
+ const CODE_AND_METADATA_SIZE = {
+ name: 'code_and_metadata_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildChromeValueDescriptionPrefix(componentPath, processName, {
+ userFriendlyPropertyNamePrefix: 'size of',
+ userFriendlyPropertyName: 'code and metadata'
+ });
+ }
+ };
+
+ const CHROME_VALUE_PROPERTIES = [
+ EFFECTIVE_SIZE,
+ ALLOCATED_OBJECTS_SIZE,
+ SHIM_ALLOCATED_OBJECTS_SIZE,
+ LOCKED_SIZE,
+ PEAK_SIZE
+ ];
+
+ /**
+ * Build a description prefix for a memory:<browser-name>:<process-name>:
+ * reported_by_chrome:... value.
+ *
+ * @param {!Array<string>} componentPath The underlying component path (e.g.
+ * ['malloc']).
+ * @param {string} processName The canonical name of the process.
+ * @param {{
+ * userFriendlyPropertyName: string,
+ * userFriendlyPropertyNamePrefix: (string|undefined),
+ * totalUserFriendlyPropertyName: (string|undefined),
+ * componentPreposition: (string|undefined) }}
+ * formatSpec Specification of how the property should be formatted.
+ * @return {string} Prefix for the value's description (e.g.
+ * 'effective size of malloc in the browser process').
+ */
+ function buildChromeValueDescriptionPrefix(
+ componentPath, processName, formatSpec) {
+ const nameParts = [];
+ if (componentPath.length === 0) {
+ nameParts.push('total');
+ if (formatSpec.totalUserFriendlyPropertyName) {
+ nameParts.push(formatSpec.totalUserFriendlyPropertyName);
+ } else {
+ if (formatSpec.userFriendlyPropertyNamePrefix) {
+ nameParts.push(formatSpec.userFriendlyPropertyNamePrefix);
+ }
+ nameParts.push(formatSpec.userFriendlyPropertyName);
+ }
+ nameParts.push('reported by Chrome for');
+ } else {
+ if (formatSpec.componentPreposition === undefined) {
+ // Use component name as an adjective
+ // (e.g. 'size of V8 code and metadata').
+ if (formatSpec.userFriendlyPropertyNamePrefix) {
+ nameParts.push(formatSpec.userFriendlyPropertyNamePrefix);
+ }
+ nameParts.push(componentPath.join(':'));
+ nameParts.push(formatSpec.userFriendlyPropertyName);
+ } else {
+ // Use component name as a noun with a preposition
+ // (e.g. 'size of all objects allocated BY MALLOC').
+ if (formatSpec.userFriendlyPropertyNamePrefix) {
+ nameParts.push(formatSpec.userFriendlyPropertyNamePrefix);
+ }
+ nameParts.push(formatSpec.userFriendlyPropertyName);
+ nameParts.push(formatSpec.componentPreposition);
+ if (componentPath[componentPath.length - 1] === 'allocated_by_malloc') {
+ nameParts.push('objects allocated by malloc for');
+ nameParts.push(
+ componentPath.slice(0, componentPath.length - 1).join(':'));
+ } else {
+ nameParts.push(componentPath.join(':'));
+ }
+ }
+ nameParts.push('in');
+ }
+ nameParts.push(convertProcessNameToUserFriendlyName(processName));
+ return nameParts.join(' ');
+ }
+
+ const RESIDENT_SIZE = {
+ name: 'resident_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'resident set size (RSS)');
+ }
+ };
+
+ const PEAK_RESIDENT_SIZE = {
+ name: 'peak_resident_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'peak resident set size');
+ }
+ };
+
+ const PROPORTIONAL_RESIDENT_SIZE = {
+ name: 'proportional_resident_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'proportional resident size (PSS)');
+ }
+ };
+
+ const PRIVATE_DIRTY_SIZE = {
+ name: 'private_dirty_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'private dirty size');
+ }
+ };
+
+ const PRIVATE_FOOTPRINT_SIZE = {
+ name: 'private_footprint_size',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'private footprint size');
+ }
+ };
+
+ const JAVA_BASE_CLEAN_RESIDENT = {
+ name: 'java_base_clean_resident',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'java base odex and vdex total clean resident size');
+ }
+ };
+
+ const JAVA_BASE_PSS = {
+ name: 'java_base_pss',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'java base odex and vdex proportional resident size');
+ }
+ };
+
+ const NATIVE_LIBRARY_PRIVATE_CLEAN_RESIDENT = {
+ name: 'native_library_private_clean_resident',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'native library private clean resident size');
+ }
+ };
+
+ const NATIVE_LIBRARY_SHARED_CLEAN_RESIDENT = {
+ name: 'native_library_shared_clean_resident',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'native library shared clean resident size');
+ }
+ };
+
+ const NATIVE_LIBRARY_PROPORTIONAL_RESIDENT = {
+ name: 'native_library_proportional_resident',
+ unit: sizeInBytes_smallerIsBetter,
+ buildDescriptionPrefix(componentPath, processName) {
+ return buildOsValueDescriptionPrefix(componentPath, processName,
+ 'native library proportional resident size');
+ }
+ };
+
+ /**
+ * Build a description prefix for a memory:<browser-name>:<process-name>:
+ * reported_by_os:... value.
+ *
+ * @param {!Array<string>} componentPath The underlying component path (e.g.
+ * ['system', 'java_heap']).
+ * @param {string} processName The canonical name of the process.
+ * @param {string} userFriendlyPropertyName User-friendly name of the
+ * underlying property (e.g. 'private dirty size').
+ * @return {string} Prefix for the value's description (e.g.
+ * 'total private dirty size of the Java heal in the GPU process').
+ */
+ function buildOsValueDescriptionPrefix(
+ componentPath, processName, userFriendlyPropertyName) {
+ if (componentPath.length > 2) {
+ throw new Error('OS value component path for \'' +
+ userFriendlyPropertyName + '\' too long: ' + componentPath.join(':'));
+ }
+
+ const nameParts = [];
+ if (componentPath.length < 2) {
+ nameParts.push('total');
+ }
+
+ nameParts.push(userFriendlyPropertyName);
+
+ if (componentPath.length > 0) {
+ switch (componentPath[0]) {
+ case 'system_memory':
+ if (componentPath.length > 1) {
+ const userFriendlyComponentName =
+ SYSTEM_VALUE_COMPONENTS[componentPath[1]].userFriendlyName;
+ if (userFriendlyComponentName === undefined) {
+ throw new Error('System value sub-component for \'' +
+ userFriendlyPropertyName + '\' unknown: ' +
+ componentPath.join(':'));
+ }
+ nameParts.push('of', userFriendlyComponentName, 'in');
+ } else {
+ nameParts.push('of system memory (RAM) used by');
+ }
+ break;
+
+ case 'gpu_memory':
+ if (componentPath.length > 1) {
+ nameParts.push('of the', componentPath[1]);
+ nameParts.push('Android memtrack component in');
+ } else {
+ nameParts.push('of GPU memory (Android memtrack) used by');
+ }
+ break;
+
+ default:
+ throw new Error('OS value component for \'' +
+ userFriendlyPropertyName + '\' unknown: ' +
+ componentPath.join(':'));
+ }
+ } else {
+ nameParts.push('reported by the OS for');
+ }
+
+ nameParts.push(convertProcessNameToUserFriendlyName(processName));
+ return nameParts.join(' ');
+ }
+
+ /**
+ * Add heavy memory dump values calculated from heavy global memory dumps to
+ * |values|. In particular, this function adds the following values:
+ *
+ * * MEMORY USAGE REPORTED BY THE OS
+ * memory:{chrome, webview}:
+ * {browser_process, renderer_processes, ..., all_processes}:
+ * reported_by_os:system_memory:[{ashmem, native_heap, java_heap}:]
+ * {proportional_resident_size, private_dirty_size}
+ * memory:{chrome, webview}:
+ * {browser_process, renderer_processes, ..., all_processes}:
+ * reported_by_os:gpu_memory:[{gl, graphics, ...}:]
+ * proportional_resident_size
+ * type: tr.v.Histogram (over matching heavy global memory dumps)
+ * unit: sizeInBytes_smallerIsBetter
+ *
+ * * MEMORY USAGE REPORTED BY CHROME
+ * memory:{chrome, webview}:
+ * {browser_process, renderer_processes, ..., all_processes}:
+ * reported_by_chrome:v8:code_and_metadata_size
+ * type: tr.v.Histogram (over matching heavy global memory dumps)
+ * unit: sizeInBytes_smallerIsBetter
+ */
+ function addDetailedMemoryDumpValues(browserNameToGlobalDumps, values) {
+ addMemoryDumpValues(browserNameToGlobalDumps,
+ g => g.levelOfDetail === DETAILED,
+ function(processDump, addProcessScalar) {
+ // Add memory:<browser-name>:<process-name>:reported_by_os:
+ // system_memory:... values.
+ for (const [componentName, componentSpec] of
+ Object.entries(SYSTEM_VALUE_COMPONENTS)) {
+ const node = getDescendantVmRegionClassificationNode(
+ processDump.vmRegions, componentSpec.classificationPath);
+ const componentPath = ['system_memory'];
+ if (componentName) componentPath.push(componentName);
+ addProcessScalar({
+ source: 'reported_by_os',
+ component: componentPath,
+ property: PROPORTIONAL_RESIDENT_SIZE,
+ value: node === undefined ?
+ 0 : (node.byteStats.proportionalResident || 0)
+ });
+ addProcessScalar({
+ source: 'reported_by_os',
+ component: componentPath,
+ property: PRIVATE_DIRTY_SIZE,
+ value: node === undefined ?
+ 0 : (node.byteStats.privateDirtyResident || 0)
+ });
+
+ // Only add java base stats when they are nonzero.
+ if (node) {
+ if (node.byteStats.javaBasePss) {
+ addProcessScalar({
+ source: 'reported_by_os',
+ component: componentPath,
+ property: JAVA_BASE_PSS,
+ value: node.byteStats.javaBasePss
+ });
+ }
+ if (node.byteStats.javaBaseCleanResident) {
+ addProcessScalar({
+ source: 'reported_by_os',
+ component: componentPath,
+ property: JAVA_BASE_CLEAN_RESIDENT,
+ value: node.byteStats.javaBaseCleanResident
+ });
+ }
+ }
+
+ // Only add native library stats when they are nonzero.
+ if (node) {
+ if (node.byteStats.nativeLibraryPrivateCleanResident) {
+ addProcessScalar({
+ source: 'reported_by_os',
+ component: componentPath,
+ property: NATIVE_LIBRARY_PRIVATE_CLEAN_RESIDENT,
+ value: node.byteStats.nativeLibraryPrivateCleanResident
+ });
+ }
+ if (node.byteStats.nativeLibrarySharedCleanResident) {
+ addProcessScalar({
+ source: 'reported_by_os',
+ component: componentPath,
+ property: NATIVE_LIBRARY_SHARED_CLEAN_RESIDENT,
+ value: node.byteStats.nativeLibrarySharedCleanResident
+ });
+ }
+ if (node.byteStats.nativeLibraryProportionalResident) {
+ addProcessScalar({
+ source: 'reported_by_os',
+ component: componentPath,
+ property: NATIVE_LIBRARY_PROPORTIONAL_RESIDENT,
+ value: node.byteStats.nativeLibraryProportionalResident
+ });
+ }
+ }
+ }
+
+ // Add memory:<browser-name>:<process-name>:reported_by_os:
+ // gpu_memory:... values.
+ const memtrackDump = processDump.getMemoryAllocatorDumpByFullName(
+ 'gpu/android_memtrack');
+ if (memtrackDump !== undefined) {
+ memtrackDump.children.forEach(function(memtrackChildDump) {
+ addProcessScalar({
+ source: 'reported_by_os',
+ component: ['gpu_memory', memtrackChildDump.name],
+ property: PROPORTIONAL_RESIDENT_SIZE,
+ value: memtrackChildDump.numerics.memtrack_pss
+ });
+ });
+ }
+ }, function(componentTree) {}, values);
+ }
+
+ // Specifications of components reported by the system.
+ const SYSTEM_VALUE_COMPONENTS = {
+ '': {
+ classificationPath: [],
+ },
+ 'java_heap': {
+ classificationPath: ['Android', 'Java runtime', 'Spaces'],
+ userFriendlyName: 'the Java heap'
+ },
+ 'ashmem': {
+ classificationPath: ['Android', 'Ashmem'],
+ userFriendlyName: 'ashmem'
+ },
+ 'native_heap': {
+ classificationPath: ['Native heap'],
+ userFriendlyName: 'the native heap'
+ },
+ 'stack': {
+ classificationPath: ['Stack'],
+ userFriendlyName: 'the thread stacks'
+ }
+ };
+
+ /**
+ * Get the descendant of a VM region classification |node| specified by the
+ * given |path| of child node titles. If |node| is undefined or such a
+ * descendant does not exist, this function returns undefined.
+ */
+ function getDescendantVmRegionClassificationNode(node, path) {
+ for (let i = 0; i < path.length; i++) {
+ if (node === undefined) break;
+
+ node = node.children.find(c => c.title === path[i]);
+ }
+ return node;
+ }
+
+ /**
+ * Add global memory dump counts to |values|. In particular, this function
+ * adds the following values:
+ *
+ * * DUMP COUNTS
+ * memory:{chrome, webview}:all_processes:dump_count
+ * [:{light, detailed, heap_profiler}]
+ * type: tr.v.Histogram
+ * unit: count_smallerIsBetter
+ *
+ * Note that unlike all other values generated by the memory metric, the
+ * global memory dump counts are NOT instances of tr.v.Histogram
+ * because it doesn't make sense to aggregate them (they are already counts
+ * over all global dumps associated with the relevant browser).
+ */
+ function addMemoryDumpCountValues(browserNameToGlobalDumps, values) {
+ browserNameToGlobalDumps.forEach(function(globalDumps, browserName) {
+ let totalDumpCount = 0;
+ const levelOfDetailNameToDumpCount = {};
+ LEVEL_OF_DETAIL_NAMES.forEach(function(levelOfDetailName) {
+ levelOfDetailNameToDumpCount[levelOfDetailName] = 0;
+ });
+ levelOfDetailNameToDumpCount[HEAP_PROFILER_DETAIL_NAME] = 0;
+
+ globalDumps.forEach(function(globalDump) {
+ totalDumpCount++;
+
+ // Increment the level-of-detail-specific dump count (if possible).
+ const levelOfDetailName =
+ LEVEL_OF_DETAIL_NAMES.get(globalDump.levelOfDetail);
+ if (levelOfDetailName === undefined) {
+ return; // Unknown level of detail.
+ }
+ levelOfDetailNameToDumpCount[levelOfDetailName]++;
+ if (globalDump.levelOfDetail === DETAILED) {
+ if (detectHeapProfilerInMemoryDump(globalDump)) {
+ levelOfDetailNameToDumpCount[HEAP_PROFILER_DETAIL_NAME]++;
+ }
+ }
+ });
+
+ // Add memory:<browser-name>:all_processes:dump_count[:<level>] values.
+ reportMemoryDumpCountAsValue(browserName, undefined /* total */,
+ totalDumpCount, values);
+ for (const [levelOfDetailName, levelOfDetailDumpCount] of
+ Object.entries(levelOfDetailNameToDumpCount)) {
+ reportMemoryDumpCountAsValue(browserName, levelOfDetailName,
+ levelOfDetailDumpCount, values);
+ }
+ });
+ }
+
+ /**
+ * Check whether detailed global dump has heap profiler information or not.
+ */
+ function detectHeapProfilerInMemoryDump(globalDump) {
+ for (const processDump of Object.values(globalDump.processMemoryDumps)) {
+ if (processDump.heapDumps && processDump.heapDumps.malloc) {
+ const mallocDump = processDump.heapDumps.malloc;
+ if (mallocDump.entries && mallocDump.entries.length > 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Add a tr.v.Histogram value to |values| reporting that the number of
+ * |levelOfDetailName| memory dumps added by |browserName| was
+ * |levelOfDetailCount|.
+ */
+ function reportMemoryDumpCountAsValue(
+ browserName, levelOfDetailName, levelOfDetailDumpCount, values) {
+ // Construct the name of the memory value.
+ const nameParts = ['memory', browserName, 'all_processes', 'dump_count'];
+ if (levelOfDetailName !== undefined) {
+ nameParts.push(levelOfDetailName);
+ }
+ const name = nameParts.join(':');
+
+ // Build the underlying histogram for the memory value.
+ const histogram = new tr.v.Histogram(name, count_smallerIsBetter,
+ BOUNDARIES_FOR_UNIT_MAP.get(count_smallerIsBetter));
+ histogram.addSample(levelOfDetailDumpCount);
+
+ // If |levelOfDetail| argument is undefined it means a total value.
+ const userFriendlyLevelOfDetail =
+ (levelOfDetailName || 'all').replace('_', ' ');
+
+ // Build the options for the memory value.
+ histogram.description = [
+ 'total number of',
+ userFriendlyLevelOfDetail,
+ 'memory dumps added by',
+ convertBrowserNameToUserFriendlyName(browserName),
+ 'to the trace'
+ ].join(' ');
+
+ // Report the memory value.
+ values.addHistogram(histogram);
+ }
+
+ /**
+ * Add generic values extracted from process memory dumps and aggregated by
+ * process name and component path into |values|.
+ *
+ * For each browser and set of global dumps in |browserNameToGlobalDumps|,
+ * |customProcessDumpValueExtractor| is applied to every process memory dump
+ * associated with the global memory dump. The second argument provided to the
+ * callback is a function for adding extracted values:
+ *
+ * function sampleProcessDumpCallback(processDump, addProcessValue) {
+ * ...
+ * addProcessScalar({
+ * source: 'reported_by_chrome',
+ * component: ['system', 'native_heap'],
+ * property: 'proportional_resident_size',
+ * value: pssExtractedFromProcessDump2,
+ * descriptionPrefixBuilder(componentPath) {
+ * return 'PSS of ' + componentPath.join('/') + ' in';
+ * }
+ * });
+ * ...
+ * }
+ *
+ * For each global memory dump, the extracted values are summed by process
+ * name (browser_process, renderer_processes, ..., all_processes) and
+ * component path (e.g. gpu is a sum of gpu:gl, gpu:graphics, ...). The sums
+ * are then aggregated over all global memory dumps associated with the given
+ * browser. For example, assuming that |customProcessDumpValueExtractor|
+ * extracts 'proportional_resident_size' values for component paths
+ * ['X', 'A'], ['X', 'B'] and ['Y'] under the same 'source' from each process
+ * memory dump, the following values will be reported (for Chrome):
+ *
+ * memory:chrome:browser_process:source:X:A:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of X:A in all 'browser' process dumps in global dump 1,
+ * ...
+ * sum of X:A in all 'browser' process dumps in global dump N
+ * ]
+ *
+ * memory:chrome:browser_process:source:X:B:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of X:B in all 'browser' process dumps in global dump 1,
+ * ...
+ * sum of X:B in all 'browser' process dumps in global dump N
+ * ]
+ *
+ * memory:chrome:browser_process:source:X:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of X:A+X:B in all 'browser' process dumps in global dump 1,
+ * ...
+ * sum of X:A+X:B in all 'browser' process dumps in global dump N
+ * ]
+ *
+ * memory:chrome:browser_process:source:Y:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of Y in all 'browser' process dumps in global dump 1,
+ * ...
+ * sum of Y in all 'browser' process dumps in global dump N
+ * ]
+ *
+ * memory:chrome:browser_process:source:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of X:A+X:B+Y in all 'browser' process dumps in global dump 1,
+ * ...
+ * sum of X:A+X:B+Y in all 'browser' process dumps in global dump N
+ * ]
+ *
+ * ...
+ *
+ * memory:chrome:all_processes:source:X:A:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of X:A in all process dumps in global dump 1,
+ * ...
+ * sum of X:A in all process dumps in global dump N,
+ * ]
+ *
+ * memory:chrome:all_processes:source:X:B:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of X:B in all process dumps in global dump 1,
+ * ...
+ * sum of X:B in all process dumps in global dump N,
+ * ]
+ *
+ * memory:chrome:all_processes:source:X:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of X:A+X:B in all process dumps in global dump 1,
+ * ...
+ * sum of X:A+X:B in all process dumps in global dump N,
+ * ]
+ *
+ * memory:chrome:all_processes:source:Y:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of Y in all process dumps in global dump 1,
+ * ...
+ * sum of Y in all process dumps in global dump N
+ * ]
+ *
+ * memory:chrome:all_processes:source:proportional_resident_size :
+ * Histogram aggregated over [
+ * sum of X:A+X:B+Y in all process dumps in global dump 1,
+ * ...
+ * sum of X:A+X:B+Y in all process dumps in global dump N
+ * ]
+ *
+ * where global dumps 1 to N are the global dumps associated with the given
+ * browser.
+ *
+ * @param {!Map<string, !Array<!tr.model.GlobalMemoryDump>}
+ * browserNameToGlobalDumps Map from browser names to arrays of global
+ * memory dumps. The generic values will be extracted from the associated
+ * process memory dumps.
+ * @param {!function(!tr.model.GlobalMemoryDump): boolean}
+ * customGlobalDumpFilter Predicate for filtering global memory dumps.
+ * @param {!function(
+ * !tr.model.ProcessMemoryDump,
+ * !function(!{
+ * source: string,
+ * componentPath: (!Array<string>|undefined),
+ * property: !{name: string, unit: !tr.b.Unit, buildDescriptionPrefix:
+ * !function(!Array<string>, string): string},
+ * value: (!tr.v.Histogram|number|undefined)
+ * }))}
+ * customProcessDumpValueExtractor Callback for extracting values from a
+ * process memory dump.
+ * @param {!function(!tr.b.MultiDimensionalViewNode)}
+ * customComponentTreeModifier Callback applied to every component tree
+ * wrt each process name.
+ * @param {!tr.v.HistogramSet} values List of values to which the
+ * resulting aggregated values are added.
+ */
+ function addMemoryDumpValues(browserNameToGlobalDumps, customGlobalDumpFilter,
+ customProcessDumpValueExtractor, customComponentTreeModifier,
+ values) {
+ browserNameToGlobalDumps.forEach(function(globalDumps, browserName) {
+ const filteredGlobalDumps = globalDumps.filter(customGlobalDumpFilter);
+ const sourceToPropertyToBuilder = extractDataFromGlobalDumps(
+ filteredGlobalDumps, customProcessDumpValueExtractor);
+ reportDataAsValues(sourceToPropertyToBuilder, browserName,
+ customComponentTreeModifier, values);
+ });
+ }
+
+ /**
+ * For each global memory dump in |globalDumps|, calculate per-process-name
+ * sums of values extracted by |customProcessDumpValueExtractor| from the
+ * associated process memory dumps.
+ *
+ * This function returns the following nested map structure:
+ *
+ * Source name (Map key, e.g. 'reported_by_os')
+ * -> Property (Map key, e.g. PROPORTIONAL_RESIDENT_SIZE)
+ * -> processAndComponentTreeBuilder
+ *
+ * where |processAndComponentTreeBuilder| is a
+ * tr.b.MultiDimensionalViewBuilder:
+ *
+ * Process name (0th dimension key, e.g. 'browser_process') x
+ * Component path (1st dimension keys, e.g. ['system', 'native_heap'])
+ * -> Sum of value over the processes (number).
+ *
+ * See addMemoryDumpValues for more details.
+ */
+ function extractDataFromGlobalDumps(
+ globalDumps, customProcessDumpValueExtractor) {
+ const sourceToPropertyToBuilder = new Map();
+ const dumpCount = globalDumps.length;
+ globalDumps.forEach(function(globalDump, dumpIndex) {
+ for (const processDump of Object.values(globalDump.processMemoryDumps)) {
+ extractDataFromProcessDump(
+ processDump, sourceToPropertyToBuilder, dumpIndex, dumpCount,
+ customProcessDumpValueExtractor);
+ }
+ });
+ return sourceToPropertyToBuilder;
+ }
+
+ function extractDataFromProcessDump(processDump, sourceToPropertyToBuilder,
+ dumpIndex, dumpCount, customProcessDumpValueExtractor) {
+ // Process name is typically 'browser', 'renderer', etc.
+ const rawProcessName = processDump.process.name;
+ const processNamePath =
+ [tr.e.chrome.chrome_processes.canonicalizeProcessName(rawProcessName)];
+
+ customProcessDumpValueExtractor(
+ processDump,
+ function addProcessScalar(spec) {
+ if (spec.value === undefined) return;
+
+ const component = spec.component || [];
+ function createDetailsForErrorMessage() {
+ return ['source=', spec.source, ', property=',
+ spec.property.name || '(undefined)', ', component=',
+ component.length === 0 ? '(empty)' : component.join(':'),
+ ' in ', processDump.process.userFriendlyName].join('');
+ }
+
+ let value;
+ if (spec.value instanceof tr.b.Scalar) {
+ value = spec.value.value;
+ if (spec.value.unit !== spec.property.unit) {
+ throw new Error('Scalar unit for ' +
+ createDetailsForErrorMessage() + ' (' +
+ spec.value.unit.unitName +
+ ') doesn\'t match the unit of the property (' +
+ spec.property.unit.unitName + ')');
+ }
+ } else {
+ value = spec.value;
+ }
+
+ let propertyToBuilder = sourceToPropertyToBuilder.get(spec.source);
+ if (propertyToBuilder === undefined) {
+ propertyToBuilder = new Map();
+ sourceToPropertyToBuilder.set(spec.source, propertyToBuilder);
+ }
+
+ let builder = propertyToBuilder.get(spec.property);
+ if (builder === undefined) {
+ builder = new tr.b.MultiDimensionalViewBuilder(
+ 2 /* dimensions (process name and component path) */,
+ dumpCount /* valueCount */),
+ propertyToBuilder.set(spec.property, builder);
+ }
+
+ const values = new Array(dumpCount);
+ values[dumpIndex] = value;
+
+ builder.addPath(
+ [processNamePath, component] /* path */, values,
+ tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL /* valueKind */);
+ });
+ }
+
+ function reportDataAsValues(sourceToPropertyToBuilder, browserName,
+ customComponentTreeModifier, values) {
+ // For each source name (e.g. 'reported_by_os')...
+ sourceToPropertyToBuilder.forEach(function(propertyToBuilder, sourceName) {
+ // For each property (e.g. EFFECTIVE_SIZE)...
+ propertyToBuilder.forEach(function(builders, property) {
+ const tree = builders.buildTopDownTreeView();
+ reportComponentDataAsValues(browserName, sourceName, property,
+ [] /* processPath */, [] /* componentPath */, tree, values,
+ customComponentTreeModifier);
+ });
+ });
+ }
+
+ /**
+ * For the given |browserName| (e.g. 'chrome'), |property|
+ * (e.g. EFFECTIVE_SIZE), |processPath| (e.g. ['browser_process']),
+ * |componentPath| (e.g. ['v8']), add
+ * a tr.v.Histogram with |unit| aggregating the total
+ * values of the associated |componentNode| across all timestamps
+ * (corresponding to global memory dumps associated with the given browser)
+ * |values| for each process (e.g. 'gpu_process', 'browser_process', etc).
+ * We also report a special 'all_processes' histogram which agregates all
+ * others, this has a RelatedNameMap diagnostic explaining
+ * how it is built from the other histograms.
+ *
+ * See addMemoryDumpValues for more details.
+ */
+ function reportComponentDataAsValues(browserName, sourceName, property,
+ processPath, componentPath, tree, values, customComponentTreeModifier,
+ opt_cachedHistograms) {
+ const cachedHistograms = opt_cachedHistograms || new Map();
+ function recurse(processPath, componentPath, node) {
+ return reportComponentDataAsValues(browserName, sourceName, property,
+ processPath, componentPath, node, values,
+ customComponentTreeModifier, cachedHistograms);
+ }
+
+ function buildHistogram(processPath, componentPath, node) {
+ return buildNamedMemoryNumericFromNode(
+ browserName,
+ sourceName,
+ property,
+ processPath.length === 0 ? 'all_processes' : processPath[0],
+ componentPath,
+ node);
+ }
+
+ customComponentTreeModifier(tree);
+ const histogram = buildHistogram(processPath, componentPath, tree);
+ if (cachedHistograms.has(histogram.name)) {
+ return cachedHistograms.get(histogram.name);
+ }
+ cachedHistograms.set(histogram.name, histogram);
+
+ const processNames = new tr.v.d.RelatedNameMap();
+ for (const [childProcessName, childProcessNode] of tree.children[0]) {
+ processPath.push(childProcessName);
+ const childProcessHistogram =
+ recurse(processPath, componentPath, childProcessNode);
+ processNames.set(childProcessName, childProcessHistogram.name);
+ processPath.pop();
+ }
+
+ const componentNames = new tr.v.d.RelatedNameMap();
+ for (const [childComponentName, childComponentNode] of tree.children[1]) {
+ componentPath.push(childComponentName);
+ const childComponentHistogram =
+ recurse(processPath, componentPath, childComponentNode);
+ componentNames.set(childComponentName, childComponentHistogram.name);
+ componentPath.pop();
+ }
+
+ values.addHistogram(histogram);
+ if (tree.children[0].size > 0) {
+ histogram.diagnostics.set('processes', processNames);
+ }
+ if (tree.children[1].size > 0) {
+ histogram.diagnostics.set('components', componentNames);
+ }
+
+ return histogram;
+ }
+
+ /**
+ * Gets the name for a histogram.
+ * The histograms have the following naming scheme:
+ * memory:chrome:browser_process:reported_by_chrome:v8:heap:effective_size_avg
+ * ^browser ^process ^source ^component ^property
+ */
+ function getNumericName(
+ browserName, sourceName, propertyName, processName, componentPath) {
+ // Construct the name of the memory value.
+ const nameParts = ['memory', browserName, processName, sourceName].concat(
+ componentPath);
+ if (propertyName !== undefined) nameParts.push(propertyName);
+ return nameParts.join(':');
+ }
+
+ /**
+ * Gets the description of a histogram.
+ */
+ function getNumericDescription(
+ property, browserName, processName, componentPath) {
+ return [
+ property.buildDescriptionPrefix(componentPath, processName),
+ 'in',
+ convertBrowserNameToUserFriendlyName(browserName)
+ ].join(' ');
+ }
+
+ /**
+ * Create a memory tr.v.Histogram with |unit| and add all total values in
+ * |node| to it. Names and describes the histogram according to the
+ * |browserName|, |sourceName|, |property|, |processName| and
+ * |componentPath|.
+ */
+ function buildNamedMemoryNumericFromNode(
+ browserName, sourceName, property, processName, componentPath, node) {
+ const name = getNumericName(
+ browserName, sourceName, property.name, processName, componentPath);
+ const description = getNumericDescription(
+ property, browserName, processName, componentPath);
+
+ // Build the underlying numeric for the memory value.
+ const numeric = buildMemoryNumericFromNode(name, node, property.unit);
+ numeric.description = description;
+ return numeric;
+ }
+
+ function buildSampleDiagnostics(value, node) {
+ if (node.children.length < 2) return undefined;
+ const diagnostics = new Map();
+ const i = node.values.indexOf(value);
+
+ const processBreakdown = new tr.v.d.Breakdown();
+ processBreakdown.colorScheme =
+ tr.e.chrome.chrome_processes.PROCESS_COLOR_SCHEME_NAME;
+ for (const [name, subNode] of node.children[0]) {
+ processBreakdown.set(name, subNode.values[i].total);
+ }
+ if (processBreakdown.size > 0) {
+ diagnostics.set('processes', processBreakdown);
+ }
+
+ const componentBreakdown = new tr.v.d.Breakdown();
+ for (const [name, subNode] of node.children[1]) {
+ componentBreakdown.set(name, subNode.values[i].total);
+ }
+ if (componentBreakdown.size > 0) {
+ diagnostics.set('components', componentBreakdown);
+ }
+
+ if (diagnostics.size === 0) return undefined;
+ return diagnostics;
+ }
+
+ /**
+ * Create a memory tr.v.Histogram with |unit| and add all total values in
+ * |node| to it.
+ */
+ function buildMemoryNumericFromNode(name, node, unit) {
+ const histogram = new tr.v.Histogram(
+ name, unit, BOUNDARIES_FOR_UNIT_MAP.get(unit));
+
+ node.values.forEach(v => histogram.addSample(
+ v.total, buildSampleDiagnostics(v, node)));
+
+ return histogram;
+ }
+
+ tr.metrics.MetricRegistry.register(memoryMetric, {
+ supportsRangeOfInterest: true
+ });
+
+ return {
+ memoryMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html
new file mode 100644
index 00000000000..e3a6c40d327
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/memory_metric_test.html
@@ -0,0 +1,4249 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/system_health/memory_metric.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/heap_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const VMRegion = tr.model.VMRegion;
+ const VMRegionClassificationNode = tr.model.VMRegionClassificationNode;
+ const BACKGROUND = tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;
+ const LIGHT = tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;
+ const DETAILED = tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;
+ const SIZE_DELTA = tr.model.MemoryDumpTestUtils.SIZE_DELTA;
+ const addProcessMemoryDump =
+ tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
+ const addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const addChildDump = tr.model.MemoryDumpTestUtils.addChildDump;
+ const addOwnershipLink = tr.model.MemoryDumpTestUtils.addOwnershipLink;
+ const count_smallerIsBetter = tr.b.Unit.byName.count_smallerIsBetter;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const StackFrame = tr.model.StackFrame;
+ const HeapEntry = tr.model.HeapEntry;
+ const HeapDump = tr.model.HeapDump;
+
+ function memoryMetricTest(
+ name, modelCallback, opt_options, expectedNumerics) {
+ test(name, function() {
+ // Create a model and a fake value list.
+ const model = tr.c.TestUtils.newModel(modelCallback);
+ const valueNameToValues = {};
+ const fakeValueList = {
+ addHistogram(value) {
+ let values = valueNameToValues[value.name];
+ if (values === undefined) {
+ valueNameToValues[value.name] = values = [];
+ }
+ values.push(value);
+ }
+ };
+
+ // Run the memory metric on the model.
+ tr.metrics.sh.memoryMetric(fakeValueList, model, opt_options);
+
+ // Check that the names of the added values match expectations.
+ const actualValueNames = Object.keys(valueNameToValues).sort();
+ const expectedValueNames = Object.keys(expectedNumerics).sort();
+ assert.deepEqual(actualValueNames, expectedValueNames, {
+ // Build the long error message lazily.
+ toString() {
+ const errorMessageParts = [];
+ function addValueNamesToError(type, valueNames, otherValueNames) {
+ const otherValueNamesSet = new Set(otherValueNames);
+ errorMessageParts.push(type, ' value names:');
+ if (valueNames.length === 0) {
+ errorMessageParts.push('\n(empty)');
+ } else {
+ valueNames.forEach(function(valueName) {
+ errorMessageParts.push('\n');
+ if (!otherValueNamesSet.has(valueName)) {
+ errorMessageParts.push('+++');
+ }
+ errorMessageParts.push(valueName);
+ });
+ }
+ }
+ addValueNamesToError('Expected', expectedValueNames,
+ actualValueNames);
+ errorMessageParts.push('\n');
+ addValueNamesToError('Actual', actualValueNames, expectedValueNames);
+ return errorMessageParts.join('');
+ }
+ });
+
+ // Check that the numeric values of the added values match expectations.
+ for (const [valueName, actualValues] of
+ Object.entries(valueNameToValues)) {
+ assert.lengthOf(actualValues, 1,
+ 'Multiple \'' + valueName + '\' values');
+ const actualHistogram = actualValues[0];
+ assert.instanceOf(actualHistogram, tr.v.Histogram);
+
+ const expectedHistogram = expectedNumerics[valueName];
+ assert.strictEqual(actualHistogram.unit, expectedHistogram.unit,
+ 'Invalid \'' + valueName + '\' unit (expected: ' +
+ expectedHistogram.unit.unitName, + ', actual: ' +
+ actualHistogram.unit.unitName + ')');
+
+ if (!(expectedHistogram.value instanceof Array)) {
+ assert.fail('Test sanity check: expected value must be an array');
+ }
+
+ assert.instanceOf(actualHistogram, tr.v.Histogram,
+ 'Invalid \'' + valueName + '\' class');
+ assert.strictEqual(actualHistogram.numValues,
+ expectedHistogram.value.length,
+ 'Invalid \'' + valueName + '\' Histogram numValues');
+ assert.closeTo(actualHistogram.sum,
+ expectedHistogram.value.reduce((a, b) => a + b, 0), SIZE_DELTA,
+ 'Invalid \'' + valueName + '\' Histogram sum');
+
+ // Check that the bin counts match.
+ const binToCount = new Map();
+ expectedHistogram.value.forEach(function(value) {
+ const bin = actualHistogram.getBinForValue(value);
+ binToCount.set(bin, (binToCount.get(bin) || 0) + 1);
+ });
+ actualHistogram.allBins.forEach(function(bin) {
+ binToCount.set(bin, (binToCount.get(bin) || 0) - bin.count);
+ });
+ binToCount.forEach(function(count, bin) {
+ assert.strictEqual(count, 0, 'Invalid \'' + valueName +
+ '\' bin count for range ' + bin.min + '-' + bin.max);
+ });
+
+ // Check that the description matches expectations.
+ assert.strictEqual(
+ actualHistogram.description, expectedHistogram.description,
+ 'Invalid \'' + valueName + '\' description');
+ }
+ });
+ }
+
+ function createProcessWithName(model, name) {
+ const uniquePid =
+ Math.max.apply(null, Object.keys(model.processes).concat([0])) + 1;
+ const process = model.getOrCreateProcess(uniquePid);
+ process.name = name;
+ return process;
+ }
+
+ function createChromeBrowserProcess(model) {
+ const process = createProcessWithName(model, 'Browser');
+ process.getOrCreateThread(1).name = 'CrBrowserMain';
+ return process;
+ }
+
+ function createWebViewProcess(model) {
+ const process = createChromeBrowserProcess(model);
+ process.getOrCreateThread(2).name = 'Chrome_InProcRendererThread';
+ return process;
+ }
+
+ memoryMetricTest('noDumps_noBrowser', function(model) {
+ createProcessWithName(model, 'Non-browser');
+ }, undefined /* opt_options */, {
+ /* no values */
+ });
+
+ memoryMetricTest('noDumps_chrome', function(model) {
+ createChromeBrowserProcess(model);
+ }, undefined /* opt_options */, {
+ 'memory:chrome:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:light': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by Chrome ' +
+ 'to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'Chrome to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by Chrome to the ' +
+ 'trace'
+ }
+ });
+
+ memoryMetricTest('noDumps_multipleBrowsers', function(model) {
+ createChromeBrowserProcess(model);
+ createWebViewProcess(model);
+ createProcessWithName(model, 'Non-browser');
+ createChromeBrowserProcess(model);
+ }, undefined /* opt_options */, {
+ 'memory:chrome2:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by Chrome(2) ' +
+ 'to the trace'
+ },
+ 'memory:chrome2:all_processes:dump_count:light': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by Chrome(2) to ' +
+ 'the trace'
+ },
+ 'memory:chrome2:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by ' +
+ 'Chrome(2) to the trace'
+ },
+ 'memory:chrome2:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'Chrome(2) to the trace'
+ },
+ 'memory:chrome2:all_processes:dump_count': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by Chrome(2) to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:light': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by Chrome ' +
+ 'to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'Chrome to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by Chrome to the ' +
+ 'trace'
+ },
+ 'memory:webview:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by WebView ' +
+ 'to the trace'
+ },
+ 'memory:webview:all_processes:dump_count:light': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by WebView to ' +
+ 'the trace'
+ },
+ 'memory:webview:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by WebView ' +
+ 'to the trace'
+ },
+ 'memory:webview:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'WebView to the trace'
+ },
+ 'memory:webview:all_processes:dump_count': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by WebView to the ' +
+ 'trace'
+ }
+ });
+
+ memoryMetricTest('dumpCountsOnly_unknownBrowser', function(model) {
+ addGlobalMemoryDump(model, {ts: 45, levelOfDetail: DETAILED});
+ addGlobalMemoryDump(model, {ts: 65, levelOfDetail: BACKGROUND});
+ addGlobalMemoryDump(model, {ts: 68, levelOfDetail: LIGHT});
+ addGlobalMemoryDump(model, {ts: 89, levelOfDetail: DETAILED});
+ }, undefined /* opt_options */, {
+ 'memory:unknown_browser:all_processes:dump_count:detailed': {
+ value: [2],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:light': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by an unknown ' +
+ 'browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:background': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count': {
+ value: [4],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by an unknown ' +
+ 'browser to the trace'
+ }
+ });
+
+ memoryMetricTest('dumpCountsOnly_webview', function(model) {
+ const p = createWebViewProcess(model);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 45, levelOfDetail: LIGHT}), p, {ts: 45});
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 68, levelOfDetail: LIGHT}), p, {ts: 68});
+ }, undefined /* opt_options */, {
+ 'memory:webview:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by WebView ' +
+ 'to the trace'
+ },
+ 'memory:webview:all_processes:dump_count:light': {
+ value: [2],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by WebView to ' +
+ 'the trace'
+ },
+ 'memory:webview:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by WebView ' +
+ 'to the trace'
+ },
+ 'memory:webview:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'WebView to the trace'
+ },
+ 'memory:webview:all_processes:dump_count': {
+ value: [2],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by WebView to the ' +
+ 'trace'
+ },
+ 'memory:webview:all_processes:process_count': {
+ value: [1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in WebView'
+ },
+ 'memory:webview:browser_process:process_count': {
+ value: [1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in WebView'
+ }
+ });
+
+ memoryMetricTest('generalValues_chrome', function(model) {
+ const pBrowser = createChromeBrowserProcess(model);
+ const pRendererA = createProcessWithName(model, 'Renderer');
+ const pRendererB = createProcessWithName(model, 'Renderer');
+ const pPpapi = createProcessWithName(model, 'PPAPI Process');
+ const pUnknown = createProcessWithName(model, undefined);
+
+ // Timestamp 1.
+ const gmd1 = addGlobalMemoryDump(model, {ts: 20});
+ const pmdBrowser1 = addProcessMemoryDump(gmd1, pBrowser, {ts: 19});
+ pmdBrowser1.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser1, 'malloc', {numerics: {
+ size: 8,
+ allocated_objects_size: 4,
+ shim_allocated_objects_size: 3,
+ }})
+ ];
+ pmdBrowser1.totals = {
+ residentBytes: 200,
+ peakResidentBytes: 230,
+ privateFootprintBytes: 240,
+ };
+ const browserHeapDump = new HeapDump(pmdBrowser1);
+ const rootFrame1 = new StackFrame(
+ undefined, tr.b.GUID.allocateSimple(), undefined);
+ const childFrame1 = new StackFrame(
+ rootFrame1, tr.b.GUID.allocateSimple(), 'draw');
+ rootFrame1.addChild(childFrame1);
+ browserHeapDump.addEntry(
+ undefined, 'HTMLImportLoader', 1024, undefined);
+ browserHeapDump.addEntry(
+ rootFrame1, 'HTMLImportLoader', 1048576, undefined);
+ browserHeapDump.addEntry(undefined, '[unknown]', 17332, 42);
+ browserHeapDump.addEntry(childFrame1, '[unknown]', 26309, 10);
+ pmdBrowser1.heapDumps = {};
+ pmdBrowser1.heapDumps.malloc = browserHeapDump;
+
+ const pmdRendererA1 = addProcessMemoryDump(gmd1, pRendererA, {ts: 20});
+ pmdRendererA1.memoryAllocatorDumps = (function() {
+ const mallocDump =
+ newAllocatorDump(pmdRendererA1, 'malloc', {numerics: {size: 16}});
+ const partitionAllocDump =
+ newAllocatorDump(pmdRendererA1, 'partition_alloc');
+ const v8Dump = newAllocatorDump(pmdRendererA1, 'v8',
+ {numerics: {code_and_metadata_size: 16}});
+ addOwnershipLink(
+ addChildDump(partitionAllocDump, 'allocated_objects',
+ {numerics: {size: 32}}),
+ addChildDump(partitionAllocDump, 'partitions',
+ {numerics: {size: 24}}));
+ return [mallocDump, partitionAllocDump, v8Dump];
+ })();
+ const pmdGpu1 = addProcessMemoryDump(gmd1, pPpapi, {ts: 21});
+ pmdGpu1.memoryAllocatorDumps = [
+ newAllocatorDump(pmdGpu1, 'gpu', {numerics: {
+ size: 30,
+ allocated_objects_size: 25
+ }})
+ ];
+
+ // Timestamp 2.
+ const gmd2 = addGlobalMemoryDump(model, {ts: 40});
+ const pmdBrowser2 = addProcessMemoryDump(gmd2, pBrowser, {ts: 41});
+ pmdBrowser2.memoryAllocatorDumps = (function() {
+ const mallocDump = newAllocatorDump(pmdBrowser2, 'malloc',
+ {numerics: {size: 120}});
+ const tracingDump =
+ newAllocatorDump(pmdBrowser2, 'tracing', {numerics: {size: 40}});
+ return [mallocDump, tracingDump];
+ })();
+ const pmdRendererA2 = addProcessMemoryDump(gmd2, pRendererA, {ts: 39});
+ pmdRendererA2.memoryAllocatorDumps = (function() {
+ const partitionAllocDump =
+ newAllocatorDump(pmdRendererA2, 'partition_alloc');
+ addOwnershipLink(
+ addChildDump(partitionAllocDump, 'allocated_objects',
+ {numerics: {size: 320}}),
+ addChildDump(partitionAllocDump, 'partitions',
+ {numerics: {size: 240}}));
+ const v8Dump = newAllocatorDump(pmdRendererA2, 'v8',
+ {numerics: {size: 650}});
+ const isolateDumpA = addChildDump(v8Dump, 'isolate_A');
+ addChildDump(isolateDumpA, 'malloc', {numerics: {
+ size: 1,
+ peak_size: 2
+ }});
+ const heapDumpA = addChildDump(isolateDumpA, 'heap_spaces', {numerics: {
+ size: 42,
+ allocated_objects_size: 36
+ }});
+ addChildDump(heapDumpA, 'code_space', {numerics: {
+ allocated_objects_size: 1,
+ size: 2
+ }});
+ addChildDump(heapDumpA, 'large_object_space', {numerics: {
+ allocated_objects_size: 3,
+ size: 4
+ }});
+ addChildDump(heapDumpA, 'map_space', {numerics: {
+ allocated_objects_size: 5,
+ size: 6,
+ }});
+ addChildDump(heapDumpA, 'new_space', {numerics: {
+ allocated_objects_size: 7,
+ size: 8
+ }});
+ addChildDump(heapDumpA, 'old_space', {numerics: {
+ allocated_objects_size: 9,
+ size: 10
+ }});
+ addChildDump(heapDumpA, 'other_spaces', {numerics: {
+ allocated_objects_size: 11,
+ size: 12
+ }});
+ const isolateDumpB = addChildDump(v8Dump, 'isolate_B');
+ addChildDump(isolateDumpB, 'malloc', {numerics: {
+ size: 10,
+ peak_size: 20
+ }});
+ const heapDumpB = addChildDump(isolateDumpB, 'heap_spaces', {numerics: {
+ size: 12,
+ allocated_objects_size: 6
+ }});
+ addChildDump(heapDumpB, 'code_space', {numerics: {
+ allocated_objects_size: 1,
+ size: 2
+ }});
+ addChildDump(heapDumpB, 'large_object_space', {numerics: {
+ allocated_objects_size: 1,
+ size: 2
+ }});
+ addChildDump(heapDumpB, 'map_space', {numerics: {
+ allocated_objects_size: 1,
+ size: 2,
+ }});
+ addChildDump(heapDumpB, 'new_space', {numerics: {
+ allocated_objects_size: 1,
+ size: 2
+ }});
+ addChildDump(heapDumpB, 'old_space', {numerics: {
+ allocated_objects_size: 1,
+ size: 2
+ }});
+ addChildDump(heapDumpB, 'other_spaces', {numerics: {
+ allocated_objects_size: 1,
+ size: 2
+ }});
+ const isolateDumpC = addChildDump(v8Dump, 'isolate_C');
+ addChildDump(isolateDumpC, 'malloc', {numerics: {
+ size: 100,
+ }});
+ addChildDump(isolateDumpC, 'heap_spaces', {numerics: {
+ size: 2,
+ allocated_objects_size: 1
+ }});
+ const isolateDumpD = addChildDump(v8Dump, 'isolate_D');
+ addChildDump(isolateDumpD, 'malloc', {numerics: {
+ peak_size: 200,
+ }});
+ return [partitionAllocDump, v8Dump];
+ })();
+ const pmdRendererB2 = addProcessMemoryDump(gmd2, pRendererB, {ts: 40});
+ pmdRendererB2.memoryAllocatorDumps = [
+ newAllocatorDump(pmdRendererB2, 'v8', {numerics: {
+ size: 970,
+ allocated_objects_size: 860,
+ bytecode_and_metadata_size: 678
+ }}),
+ newAllocatorDump(pmdRendererB2, 'malloc',
+ {numerics: {allocated_objects_size: 750}})
+ ];
+ const pmdUnknown = addProcessMemoryDump(gmd2, pUnknown, {ts: 42});
+ pmdUnknown.memoryAllocatorDumps = [
+ newAllocatorDump(pmdRendererB2, 'v8', {numerics: {size: 111}})
+ ];
+
+ // Timestamp 3.
+ const gmd3 = addGlobalMemoryDump(model, {ts: 60});
+ const pmdBrowser3 = addProcessMemoryDump(gmd3, pBrowser, {ts: 60});
+ pmdBrowser3.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser3, 'malloc', {numerics: {
+ size: 8000,
+ allocated_objects_size: 4000,
+ shim_allocated_objects_size: 3000
+ }})
+ ];
+ const pmdRendererB3 = addProcessMemoryDump(gmd3, pRendererB, {ts: 61});
+ // Intentionally pmdRendererB3.memoryAllocatorDumps undefined.
+ const pmdGpu3 = addProcessMemoryDump(gmd3, pPpapi, {ts: 59});
+ pmdGpu3.memoryAllocatorDumps = [
+ newAllocatorDump(pmdGpu3, 'gpu', {numerics: {size: 300}})
+ ];
+
+ // Timestamp 4.
+ const gmd4 = addGlobalMemoryDump(model, {ts: 80});
+ const pmdBrowser4 = addProcessMemoryDump(gmd4, pBrowser, {ts: 81});
+ pmdBrowser4.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser4, 'malloc', {numerics: {size: 80000}})
+ ];
+ const pmdRendererB4 = addProcessMemoryDump(gmd4, pRendererB, {ts: 79});
+ pmdRendererB4.memoryAllocatorDumps = (function() {
+ const v8Dump = newAllocatorDump(pmdRendererB4, 'v8', {numerics: {
+ code_and_metadata_size: 21,
+ bytecode_and_metadata_size: 35,
+ size: 9e5
+ }});
+ const partitionAllocDump = newAllocatorDump(pmdRendererB4,
+ 'partition_alloc', {numerics: {size: 5e5}});
+ addOwnershipLink(partitionAllocDump, v8Dump);
+ return [v8Dump, partitionAllocDump];
+ })();
+ const rendererBHeapDump4 = new HeapDump(pmdRendererB4);
+ rendererBHeapDump4.addEntry(
+ undefined, 'BlinkObject', 1687992, undefined);
+ rendererBHeapDump4.addEntry(undefined, undefined, 2243546, 42);
+ rendererBHeapDump4.addEntry(undefined, 'BlinkObject', 1252376, 10);
+
+ pmdRendererB4.heapDumps = {};
+ pmdRendererB4.heapDumps.blinkgc = rendererBHeapDump4;
+
+ const pmdGpu4 = addProcessMemoryDump(gmd4, pPpapi, {ts: 80});
+ pmdGpu4.memoryAllocatorDumps = [
+ newAllocatorDump(pmdGpu4, 'gpu',
+ {numerics: {memtrack_pss: 666 /* ignored */}})
+ ];
+ }, undefined /* opt_options */, {
+ 'memory:chrome:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:light': {
+ value: [4],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by Chrome ' +
+ 'to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'Chrome to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count': {
+ value: [4],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by Chrome to the ' +
+ 'trace'
+ },
+ 'memory:chrome:all_processes:process_count': {
+ value: [3, 4, 3, 3],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:effective_size': {
+ value: [30 + (8 + 16) + 32, (120 - 40) + 320 + (650 + 970) + 111,
+ 300 + 8000, 80000 + 5e5 + 4e5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:allocated_objects_size': {
+ value: [25 + 4 + 32, (36 + 6 + 1) + 750 + 860 + 320 + 40, 4000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects reported by Chrome ' +
+ 'for all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:blinkgc:BlinkObject:heap_category_size':
+ {
+ value: [0, 0, 1687992 + 1252376, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'heap profiler category size for blinkgc:BlinkObject in ' +
+ 'all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:blinkgc:heap_category_size':
+ {
+ value: [0, 0, 1687992 + 1252376, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'heap profiler category size for blinkgc in all processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:shim_allocated_objects_size':
+ {
+ value: [3, 0, 3000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects through shim ' +
+ 'reported by Chrome for all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:peak_size':
+ {
+ value: [0, 2 + 20 + 200, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total peak size reported by Chrome for all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:resident_size': {
+ value: [200, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total resident set size (RSS) reported by the OS for all' +
+ ' processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:peak_resident_size': {
+ value: [230, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total peak resident set size reported by the OS for all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:private_footprint_size': {
+ value: [240, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private footprint size reported by the OS for all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:resident_size': {
+ value: [200, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total resident set size (RSS) of system memory (RAM) ' +
+ 'used by all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:peak_resident_size':
+ {
+ value: [230, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total peak resident set size of system memory (RAM) ' +
+ 'used by all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:private_footprint_size': { // eslint-disable-line max-len
+ value: [240, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private footprint size of system memory (RAM) ' +
+ 'used by all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:gpu:effective_size': {
+ value: [30, 0, 300, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of gpu in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:heap_category_size': {
+ value: [17332, 0, 1687992 + 1252376, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total heap profiler category size reported by Chrome for ' +
+ 'all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:[unknown]:heap_category_size':
+ {
+ value: [17332, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'heap profiler category size for malloc:[unknown] in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:gpu:allocated_objects_size':
+ {
+ value: [25, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by gpu in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:effective_size': {
+ value: [8 + 16, 120 - 40, 8000, 80000],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:heap_category_size':
+ {
+ value: [17332, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'heap profiler category size for malloc in all processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:shim_allocated_objects_size':
+ {
+ value: [3, 0, 3000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated through shim by malloc in ' +
+ 'all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:allocated_objects_size':
+ {
+ value: [4, 40 + 750, 4000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by malloc in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:partition_alloc:allocated_objects_size':
+ {
+ value: [32, 320, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by partition_alloc in ' +
+ 'all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:partition_alloc:effective_size':
+ {
+ value: [32, 320, 0, 5e5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of partition_alloc in all processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:tracing:effective_size': {
+ value: [0, 40, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of tracing in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:allocated_by_malloc:effective_size':
+ {
+ value: [0, 1 + 10 + 100, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of objects allocated by malloc for v8 ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:allocated_by_malloc:peak_size':
+ {
+ value: [0, 2 + 20 + 200, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'peak size of objects allocated by malloc for v8 ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:code_and_metadata_size':
+ {
+ value: [16, 678, 0, 21 + 35],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of code and metadata reported by Chrome ' +
+ 'for all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:code_and_metadata_size':
+ {
+ value: [16, 678, 0, 21 + 35],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of v8 code and metadata in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:allocated_objects_size':
+ {
+ value: [0, 36 + 6 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:effective_size': {
+ value: [0, 42 + 12 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:code_space:allocated_objects_size':
+ {
+ value: [0, 1 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:code_space ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:code_space:effective_size':
+ {
+ value: [0, 2 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:code_space in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:large_object_space:allocated_objects_size':
+ {
+ value: [0, 3 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by ' +
+ 'v8:heap:large_object_space in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:large_object_space:effective_size':
+ {
+ value: [0, 4 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:large_object_space in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:map_space:allocated_objects_size':
+ {
+ value: [0, 5 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:map_space ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:map_space:effective_size':
+ {
+ value: [0, 6 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:map_space in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:new_space:allocated_objects_size':
+ {
+ value: [0, 7 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:new_space ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:new_space:effective_size':
+ {
+ value: [0, 8 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:new_space in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:old_space:allocated_objects_size':
+ {
+ value: [0, 9 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:old_space ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:heap:old_space:effective_size':
+ {
+ value: [0, 10 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:old_space in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:effective_size': {
+ value: [0, 650 + 970 + 111, 0, 4e5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:allocated_objects_size':
+ {
+ value: [0, (36 + 6 + 1) + 860, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8 in all processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:v8:peak_size':
+ {
+ value: [0, 2 + 20 + 200, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'peak size of v8 in all processes in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:peak_resident_size': {
+ value: [230, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total peak resident set size reported by the OS for the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:peak_resident_size':
+ {
+ value: [230, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total peak resident set size of system memory (RAM) ' +
+ 'used by the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:private_footprint_size': {
+ value: [240, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private footprint size reported by the OS for the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:private_footprint_size':
+ {
+ value: [240, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private footprint size of system memory (RAM) ' +
+ 'used by the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:resident_size': {
+ value: [200, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total resident set size (RSS) reported by the OS for the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:resident_size':
+ {
+ value: [200, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total resident set size (RSS) of system memory (RAM) ' +
+ 'used by the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:process_count': {
+ value: [1, 1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:effective_size': {
+ value: [8, (120 - 40), 8000, 80000],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:heap_category_size': {
+ value: [17332, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total heap profiler category size reported by Chrome for ' +
+ 'the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:[unknown]:heap_category_size':
+ {
+ value: [17332, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'heap profiler category size for malloc:[unknown] in the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:allocated_objects_size': {
+ value: [4 + 40, 0, 4000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects reported by Chrome ' +
+ 'for the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:shim_allocated_objects_size':
+ {
+ value: [3, 0, 3000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects through shim ' +
+ 'reported by Chrome for the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:effective_size': {
+ value: [8, 120 - 40, 8000, 80000],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:heap_category_size':
+ {
+ value: [17332, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'heap profiler category size for malloc in the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:allocated_objects_size':
+ {
+ value: [4 + 40, 0, 4000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by malloc in the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:shim_allocated_objects_size':
+ {
+ value: [3, 0, 3000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated through shim by malloc in ' +
+ 'the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:tracing:effective_size': {
+ value: [0, 40, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of tracing in the browser process in Chrome'
+ },
+ 'memory:chrome:ppapi_process:process_count': {
+ value: [1, 0, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of PPAPI processes in Chrome'
+ },
+ 'memory:chrome:ppapi_process:reported_by_chrome:effective_size': {
+ value: [30, 0, 300, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for the PPAPI ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:ppapi_process:reported_by_chrome:allocated_objects_size': {
+ value: [25, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects reported by Chrome ' +
+ 'for the PPAPI process in Chrome'
+ },
+ 'memory:chrome:ppapi_process:reported_by_chrome:gpu:effective_size': {
+ value: [30, 0, 300, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of gpu in the PPAPI process in Chrome'
+ },
+ 'memory:chrome:ppapi_process:reported_by_chrome:gpu:allocated_objects_size':
+ {
+ value: [25, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by gpu in the PPAPI ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:renderer_processes:process_count': {
+ value: [1, 2, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:effective_size': {
+ value: [16 + 32, 320 + 650 + 970, 0, 5e5 + 4e5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:allocated_objects_size':
+ {
+ value: [32, (36 + 6 + 1) + 750 + 860 + 320, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects reported by ' +
+ 'Chrome for renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:blinkgc:BlinkObject:heap_category_size':
+ {
+ value: [0, 0, 1687992 + 1252376, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'heap profiler category size for blinkgc:BlinkObject in ' +
+ 'renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:blinkgc:heap_category_size':
+ {
+ value: [0, 0, 1687992 + 1252376, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'heap profiler category size for blinkgc in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:peak_size':
+ {
+ value: [0, 2 + 20 + 200, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total peak size reported by Chrome ' +
+ 'for renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:malloc:effective_size':
+ {
+ value: [16, 0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in renderer processes in ' +
+ 'Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:heap_category_size': {
+ value: [0, 0, 1687992 + 1252376, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total heap profiler category size reported by Chrome for ' +
+ 'renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:malloc:allocated_objects_size':
+ {
+ value: [0, 750, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by malloc in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:partition_alloc:allocated_objects_size':
+ {
+ value: [32, 320, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by partition_alloc in ' +
+ 'renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:partition_alloc:effective_size':
+ {
+ value: [32, 320, 0, 5e5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of partition_alloc in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:allocated_by_malloc:effective_size':
+ {
+ value: [0, 1 + 10 + 100, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of objects allocated by malloc for v8 ' +
+ 'in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:allocated_by_malloc:peak_size':
+ {
+ value: [0, 2 + 20 + 200, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'peak size of objects allocated by malloc for v8 ' +
+ 'in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:allocated_objects_size':
+ {
+ value: [0, 36 + 6 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:code_and_metadata_size':
+ {
+ value: [16, 678, 0, 21 + 35],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of code and metadata reported by Chrome ' +
+ 'for renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:code_and_metadata_size':
+ {
+ value: [16, 678, 0, 21 + 35],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of v8 code and metadata in renderer processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:effective_size':
+ {
+ value: [0, 42 + 12 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap in renderer processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:code_space:allocated_objects_size':
+ {
+ value: [0, 1 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:code_space ' +
+ 'in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:code_space:effective_size':
+ {
+ value: [0, 2 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:code_space in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:large_object_space:allocated_objects_size':
+ {
+ value: [0, 3 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by ' +
+ 'v8:heap:large_object_space in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:large_object_space:effective_size':
+ {
+ value: [0, 4 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:large_object_space in ' +
+ 'renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:map_space:allocated_objects_size':
+ {
+ value: [0, 5 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:map_space ' +
+ 'in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:map_space:effective_size':
+ {
+ value: [0, 6 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:map_space in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:new_space:allocated_objects_size':
+ {
+ value: [0, 7 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:new_space ' +
+ 'in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:new_space:effective_size':
+ {
+ value: [0, 8 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:new_space in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:old_space:allocated_objects_size':
+ {
+ value: [0, 9 + 1, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:old_space ' +
+ 'in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:heap:old_space:effective_size':
+ {
+ value: [0, 10 + 2, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:old_space in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:effective_size': {
+ value: [0, 650 + 970, 0, 4e5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:allocated_objects_size':
+ {
+ value: [0, (36 + 6 + 1) + 860, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8 in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:v8:peak_size':
+ {
+ value: [0, 2 + 20 + 200, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'peak size of v8 in renderer processes in Chrome'
+ },
+ 'memory:chrome:unknown_processes:process_count': {
+ value: [0, 1, 0, 0],
+ unit: count_smallerIsBetter,
+ description: 'total number of unknown processes in Chrome'
+ },
+ 'memory:chrome:unknown_processes:reported_by_chrome:effective_size': {
+ value: [0, 111, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for unknown ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:unknown_processes:reported_by_chrome:v8:effective_size': {
+ value: [0, 111, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in unknown processes in Chrome'
+ },
+ });
+
+
+ memoryMetricTest('newV8Values', function(model) {
+ const pRendererA = createProcessWithName(model, 'Renderer');
+ const gmd1 = addGlobalMemoryDump(model, {ts: 20});
+ const pmdRendererA = addProcessMemoryDump(gmd1, pRendererA, {ts: 20});
+ pmdRendererA.memoryAllocatorDumps = (function() {
+ const v8Dump = newAllocatorDump(pmdRendererA, 'v8',
+ {numerics: {size: 0}});
+ const isolateDumpA = addChildDump(v8Dump, 'main');
+ const heapDumpA = addChildDump(isolateDumpA, 'heap');
+ addChildDump(heapDumpA, 'code_space', {numerics: {
+ allocated_objects_size: 10,
+ size: 20
+ }});
+ const workersDump = addChildDump(v8Dump, 'workers');
+ const heapDumpB = addChildDump(workersDump, 'heap');
+ const codeSpaceDumpB = addChildDump(heapDumpB, 'code_space');
+ addChildDump(codeSpaceDumpB, 'isolate_0x1234', {numerics: {
+ allocated_objects_size: 1,
+ size: 2
+ }});
+ addChildDump(codeSpaceDumpB, 'isolate_0x5678', {numerics: {
+ allocated_objects_size: 3,
+ size: 4
+ }});
+ return [v8Dump];
+ })();
+ }, undefined /* opt_options */, {
+ 'memory:unknown_browser:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:light': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'an unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by an unknown ' +
+ 'browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:process_count': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:effective_size': {
+ value: [26],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for all ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:allocated_objects_size':
+ {
+ value: [14],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects reported by Chrome ' +
+ 'for all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:v8:heap:allocated_objects_size':
+ {
+ value: [14],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap in all ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:v8:heap:effective_size':
+ {
+ value: [26],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap in all processes in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:v8:heap:code_space:allocated_objects_size':
+ {
+ value: [14],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:code_space ' +
+ 'in all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:v8:heap:code_space:effective_size':
+ {
+ value: [26],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:code_space in all ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:v8:effective_size':
+ {
+ value: [26],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:v8:allocated_objects_size':
+ {
+ value: [14],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8 in all processes ' +
+ 'in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:process_count': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_chrome:effective_size':
+ {
+ value: [26],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for renderer ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_chrome:allocated_objects_size':
+ {
+ value: [14],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects reported by Chrome ' +
+ 'for renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_chrome:v8:heap:allocated_objects_size':
+ {
+ value: [14],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap in renderer ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_chrome:v8:heap:effective_size':
+ {
+ value: [26],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap in renderer processes in ' +
+ 'an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_chrome:v8:heap:code_space:allocated_objects_size':
+ {
+ value: [14],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8:heap:code_space ' +
+ 'in renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_chrome:v8:heap:code_space:effective_size':
+ {
+ value: [26],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8:heap:code_space in renderer ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_chrome:v8:effective_size':
+ {
+ value: [26],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in renderer processes in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_chrome:v8:allocated_objects_size':
+ {
+ value: [14],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8 in renderer ' +
+ 'processes in an unknown browser'
+ }
+ });
+
+
+ memoryMetricTest('detailedValues_unknownBrowser', function(model) {
+ const pBrowser = createProcessWithName(model, 'Browser');
+ const pRendererA = createProcessWithName(model, 'Renderer');
+ const pRendererB = createProcessWithName(model, 'Renderer');
+ const pRendererC = createProcessWithName(model, 'Renderer');
+ const pGpu = createProcessWithName(model, 'GPU Process');
+
+ // Timestamp 1.
+ const gmd1 = addGlobalMemoryDump(model, {ts: 10, levelOfDetail: DETAILED});
+ const pmdBrowser1 = addProcessMemoryDump(gmd1, pBrowser, {ts: 9});
+ pmdBrowser1.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 128, 0, '/dev/ashmem/dalvik-non moving space',
+ {privateDirtyResident: 8}),
+ new VMRegion(0xFBCD, 64, 5, '/data/chrome-WXYZ/base.apk',
+ { privateCleanResident: 8, sharedCleanResident: 4,
+ proportionalResident: 10}),
+ new VMRegion(0xFCCD, 64, 5, '/data/chrome-WXYZ/out/arm/base.odex',
+ { privateCleanResident: 0, sharedCleanResident: 6,
+ proportionalResident: 5})
+ ]);
+ pmdBrowser1.heapDumps = (function() {
+ const mallocDump = new tr.model.HeapDump(pmdBrowser1, 'malloc');
+ mallocDump.addEntry(undefined, undefined, 100, 500);
+ return {'malloc': mallocDump};
+ })();
+
+ const pmdRendererA1 = addProcessMemoryDump(gmd1, pRendererA, {ts: 10});
+ pmdRendererA1.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xEF01, 256, 0, '[anon:libc_malloc]',
+ {privateDirtyResident: 17}),
+ new VMRegion(0xFBCD, 64, 5, '/data/chrome-WXYZ/base.apk',
+ { privateCleanResident: 3, sharedCleanResident: 4,
+ proportionalResident: 5})
+ ]);
+ const pmdRendererB1 = addProcessMemoryDump(gmd1, pRendererB, {ts: 11});
+ pmdRendererB1.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0x2345, 512, 0, '[heap]',
+ {proportionalResident: 67, privateDirtyResident: 34}),
+ new VMRegion(0x7f29, 128, 0, '[stack:25451]',
+ {proportionalResident: 20, privateDirtyResident: 16})
+ ]);
+ const pmdGpu1 = addProcessMemoryDump(gmd1, pGpu, {ts: 10});
+ pmdGpu1.memoryAllocatorDumps = (function() {
+ const gpuDump = newAllocatorDump(pmdGpu1, 'gpu');
+ const memtrackDump = addChildDump(gpuDump, 'android_memtrack');
+ addChildDump(memtrackDump, 'gl', {numerics: {memtrack_pss: 100}});
+ addChildDump(memtrackDump, 'graphics', {numerics: {memtrack_pss: 200}});
+ return [gpuDump];
+ })();
+
+ // Timestamp 2 (light global memory dump, so it should be skipped for
+ // mmaps_* values).
+ const gmd2 = addGlobalMemoryDump(model, {ts: 20, levelOfDetail: LIGHT});
+ const pmdBrowser2 = addProcessMemoryDump(gmd2, pBrowser, {ts: 18});
+ pmdBrowser2.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0x999, 999, 999, '/dev/ashmem/dalvik-main space',
+ {proportionalResident: 999})
+ ]);
+ const pmdRendererB2 = addProcessMemoryDump(gmd2, pRendererB, {ts: 21});
+ const pmdRendererC2 = addProcessMemoryDump(gmd2, pRendererC, {ts: 22});
+ const pmdGpu2 = addProcessMemoryDump(gmd2, pGpu, {ts: 20});
+ pmdGpu2.memoryAllocatorDumps = (function() {
+ const gpuDump = newAllocatorDump(pmdGpu2, 'gpu');
+ const memtrackDump = addChildDump(gpuDump, 'android_memtrack');
+ addChildDump(memtrackDump, 'gl', {numerics: {memtrack_pss: 12345}});
+ return [gpuDump];
+ })();
+
+ // Timestamp 3.
+ const gmd3 = addGlobalMemoryDump(model, {ts: 30, levelOfDetail: DETAILED});
+ const pmdBrowser3 = addProcessMemoryDump(gmd3, pBrowser, {ts: 30});
+ pmdBrowser3.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 1024, 0, '/dev/ashmem/dalvik-non moving space',
+ {proportionalResident: 3, privateDirtyResident: 80})
+ ]);
+ const pmdRendererA3 = addProcessMemoryDump(gmd3, pRendererA, {ts: 29});
+ // Intentionally pmdRendererA3.vmRegions undefined.
+ const pmdRendererC3 = addProcessMemoryDump(gmd3, pRendererC, {ts: 31});
+ pmdRendererC3.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0x2345, 2048, 0, '/no/matching/category',
+ {proportionalResident: 200}),
+ new VMRegion(0x2345, 2048, 0, '/dev/ashmem', {proportionalResident: 500}),
+ ]);
+ const pmdGpu3 = addProcessMemoryDump(gmd3, pGpu, {ts: 30});
+ pmdGpu3.memoryAllocatorDumps = (function() {
+ const gpuDump = newAllocatorDump(pmdGpu3, 'gpu',
+ {numerics: {memtrack_pss: 6000 /* ignored */}});
+ const memtrackDump = addChildDump(gpuDump, 'android_memtrack',
+ {numerics: {memtrack_pss: 5000 /* ignored */}});
+ addChildDump(memtrackDump, 'gl', {numerics: {memtrack_pss: 3000}});
+ addChildDump(memtrackDump, 'graphics', {numerics: {ignored: 2000}});
+ addChildDump(memtrackDump, 'gfx', {numerics: {memtrack_pss: 1000}});
+ return [gpuDump];
+ })();
+ pmdGpu3.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xCDCD, 4096, 0, '/dev/ashmem/dalvik-zygote space',
+ {proportionalResident: 150, privateDirtyResident: 90})
+ ]);
+
+ // Timestamp 4.
+ const gmd4 = addGlobalMemoryDump(model, {ts: 40, levelOfDetail: DETAILED});
+ const pmdBrowser4 = addProcessMemoryDump(gmd4, pBrowser, {ts: 40});
+ }, undefined /* opt_options */, {
+ 'memory:unknown_browser:all_processes:dump_count:detailed': {
+ value: [3],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:light': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by an unknown ' +
+ 'browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:heap_profiler': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count': {
+ value: [4],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by an unknown ' +
+ 'browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:process_count': {
+ value: [4, 4, 4, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:gpu_memory:proportional_resident_size':
+ {
+ value: [100 + 200, 3000 + 1000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of GPU memory ' +
+ '(Android memtrack) used by all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:java_base_clean_resident':
+ {
+ value: [6, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total java base odex and vdex total clean resident size ' +
+ 'reported by the OS for all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:java_base_pss':
+ {
+ value: [5, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total java base odex and vdex proportional resident size ' +
+ 'reported by the OS for all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:native_library_private_clean_resident':
+ {
+ value: [8, 3, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library private clean resident size ' +
+ 'reported by the OS for all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:native_library_proportional_resident':
+ {
+ value: [10, 5, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library proportional resident size ' +
+ 'reported by the OS for all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:native_library_shared_clean_resident':
+ {
+ value: [4, 4, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library shared clean resident size ' +
+ 'reported by the OS for all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:gpu_memory:gfx:proportional_resident_size':
+ {
+ value: [0, 1000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the gfx Android ' +
+ 'memtrack component in all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:gpu_memory:gl:proportional_resident_size':
+ {
+ value: [100, 3000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the gl Android ' +
+ 'memtrack component in all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:gpu_memory:graphics:proportional_resident_size':
+ {
+ value: [200, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the graphics ' +
+ 'Android memtrack component in all processes in an unknown ' +
+ 'browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:private_dirty_size': {
+ value: [17 + 34 + 16 + 8, 80 + 90, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for all ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:proportional_resident_size':
+ {
+ value: [67 + 20 + 100 + 200, 700 + 3 + 1000 + 150 + 3000, 15 + 5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by ' +
+ 'the OS for all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [17 + 34 + 16 + 8, 80 + 90, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [67 + 20, 700 + 3 + 150, 15 + 5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in all processes in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 500, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in all ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:java_base_clean_resident':
+ {
+ value: [6, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total java base odex and vdex total clean resident size ' +
+ 'of system memory (RAM) used by all processes in an unknown ' +
+ 'browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:java_base_pss':
+ {
+ value: [5, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total java base odex and vdex proportional resident size ' +
+ 'of system memory (RAM) used by all processes in an unknown ' +
+ 'browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [8, 80 + 90, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in all processes ' +
+ 'in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 3 + 150, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [17 + 34, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in all ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [67, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:native_library_private_clean_resident':
+ {
+ value: [8, 3, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library private clean resident size of ' +
+ 'system memory (RAM) used by all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:native_library_proportional_resident':
+ {
+ value: [10, 5, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library proportional resident size of ' +
+ 'system memory (RAM) used by all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:native_library_shared_clean_resident':
+ {
+ value: [4, 4, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library shared clean resident size of ' +
+ 'system memory (RAM) used by all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [16, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in all ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [20, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:process_count': {
+ value: [1, 1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:java_base_clean_resident':
+ {
+ value: [6, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total java base odex and vdex total clean resident size ' +
+ 'reported by the OS for the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:java_base_pss':
+ {
+ value: [5, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total java base odex and vdex proportional resident size ' +
+ 'reported by the OS for the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:native_library_private_clean_resident':
+ {
+ value: [8, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library private clean resident size ' +
+ 'reported by the OS for the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:native_library_proportional_resident':
+ {
+ value: [10, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library proportional resident size ' +
+ 'reported by the OS for the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:native_library_shared_clean_resident':
+ {
+ value: [4, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library shared clean resident size ' +
+ 'reported by the OS for the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:private_dirty_size':
+ {
+ value: [8, 80, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for the ' +
+ 'browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:proportional_resident_size':
+ {
+ value: [15, 3, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by ' +
+ 'the OS for the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [8, 80, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [13, 5, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in the browser process ' +
+ 'in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in the ' +
+ 'browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:java_base_clean_resident':
+ {
+ value: [6, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total java base odex and vdex total clean resident size ' +
+ 'of system memory (RAM) used by the browser process in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:java_base_pss':
+ {
+ value: [5, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total java base odex and vdex proportional resident size ' +
+ 'of system memory (RAM) used by the browser process in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [8, 80, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in the browser ' +
+ 'process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 3, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in the browser ' +
+ 'process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:native_library_private_clean_resident':
+ {
+ value: [8, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library private clean resident size of ' +
+ 'system memory (RAM) used by the browser process in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:native_library_proportional_resident':
+ {
+ value: [10, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library proportional resident size of ' +
+ 'system memory (RAM) used by the browser process in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:native_library_shared_clean_resident':
+ {
+ value: [4, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library shared clean resident size of ' +
+ 'system memory (RAM) used by the browser process in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in the browser ' +
+ 'process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in the browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:process_count': {
+ value: [1, 1, 1, 0],
+ unit: count_smallerIsBetter,
+ description: 'total number of GPU processes in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:proportional_resident_size':
+ {
+ value: [100 + 200, 3000 + 1000 + 150, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by ' +
+ 'the OS for the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:private_dirty_size': {
+ value: [0, 90, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for the GPU ' +
+ 'process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:gpu_memory:proportional_resident_size':
+ {
+ value: [100 + 200, 3000 + 1000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of GPU memory ' +
+ '(Android memtrack) used by the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:gpu_memory:gfx:proportional_resident_size':
+ {
+ value: [0, 1000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the gfx Android ' +
+ 'memtrack component in the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:gpu_memory:gl:proportional_resident_size':
+ {
+ value: [100, 3000, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the gl Android ' +
+ 'memtrack component in the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:gpu_memory:graphics:proportional_resident_size':
+ {
+ value: [200, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the graphics ' +
+ 'Android memtrack component in the GPU process in an unknown ' +
+ 'browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [0, 90, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 150, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in the GPU process in ' +
+ 'an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in the ' +
+ 'GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [0, 90, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in the GPU ' +
+ 'process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 150, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in the GPU ' +
+ 'process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in the GPU ' +
+ 'process in an unknown browser'
+ },
+ 'memory:unknown_browser:gpu_process:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in the GPU process in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:process_count': {
+ value: [2, 2, 2, 0],
+ unit: count_smallerIsBetter,
+ description: 'total number of renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:native_library_private_clean_resident':
+ {
+ value: [3, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library private clean resident size ' +
+ 'reported by the OS for renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:native_library_proportional_resident':
+ {
+ value: [5, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library proportional resident size ' +
+ 'reported by the OS for renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:native_library_shared_clean_resident':
+ {
+ value: [4, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library shared clean resident size ' +
+ 'reported by the OS for renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:private_dirty_size':
+ {
+ value: [17 + 34 + 16, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for ' +
+ 'renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:proportional_resident_size':
+ {
+ value: [67 + 20, 700, 5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by ' +
+ 'the OS for renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [17 + 34 + 16, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [67 + 20, 700, 5],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in renderer processes ' +
+ 'in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 500, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in ' +
+ 'renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in renderer ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [17 + 34, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in renderer ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [67, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in renderer processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:native_library_private_clean_resident':
+ {
+ value: [3, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library private clean resident size of ' +
+ 'system memory (RAM) used by renderer processes in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:native_library_proportional_resident':
+ {
+ value: [5, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library proportional resident size of ' +
+ 'system memory (RAM) used by renderer processes in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:native_library_shared_clean_resident':
+ {
+ value: [4, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total native library shared clean resident size of ' +
+ 'system memory (RAM) used by renderer processes in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [16, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in renderer ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:renderer_processes:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [20, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in renderer processes in an unknown browser'
+ }
+ });
+
+ memoryMetricTest('combined_chrome', function(model) {
+ const pBrowser = createChromeBrowserProcess(model);
+
+ // Timestamp 1.
+ const gmd1 = addGlobalMemoryDump(model, {ts: 10, levelOfDetail: DETAILED});
+ const pmdBrowser1 = addProcessMemoryDump(gmd1, pBrowser, {ts: 10});
+ pmdBrowser1.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 128, 0, '/dev/ashmem/dalvik-non moving space',
+ {privateDirtyResident: 100})
+ ]);
+
+ // Timestamp 2 (light global memory dump, so it should be skipped for
+ // mmaps_* values).
+ const gmd2 = addGlobalMemoryDump(model, {ts: 20, levelOfDetail: LIGHT});
+ const pmdBrowser2 = addProcessMemoryDump(gmd2, pBrowser, {ts: 20});
+ pmdBrowser2.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser2, 'malloc', {numerics: {size: 32}})
+ ];
+
+ // Timestamp 3.
+ const gmd3 = addGlobalMemoryDump(model, {ts: 30, levelOfDetail: DETAILED});
+ const pmdBrowser3 = addProcessMemoryDump(gmd3, pBrowser, {ts: 30});
+ pmdBrowser3.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser3, 'malloc', {numerics: {size: 48}})
+ ];
+ pmdBrowser3.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 1024, 0, '/dev/ashmem/dalvik-non moving space',
+ {privateDirtyResident: 150})
+ ]);
+ }, {} /* opt_options */, {
+ 'memory:chrome:all_processes:dump_count:detailed': {
+ value: [2],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:light': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by Chrome ' +
+ 'to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'Chrome to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count': {
+ value: [3],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by Chrome to the ' +
+ 'trace'
+ },
+ 'memory:chrome:all_processes:process_count': {
+ value: [1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:effective_size': {
+ value: [0, 32, 48],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:effective_size': {
+ value: [0, 32, 48],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:private_dirty_size': {
+ value: [100, 150],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:proportional_resident_size': {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by the ' +
+ 'OS for all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [100, 150],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in all processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [100, 150],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by all processes in Chrome'
+ },
+ 'memory:chrome:browser_process:process_count': {
+ value: [1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:effective_size': {
+ value: [0, 32, 48],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:effective_size': {
+ value: [0, 32, 48],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:private_dirty_size': {
+ value: [100, 150],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:proportional_resident_size': {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by the ' +
+ 'OS for the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in the browser process ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [100, 150],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [100, 150],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by the browser process in Chrome'
+ }
+ });
+
+ memoryMetricTest('combined_multipleBrowsers', function(model) {
+ const pWebView = createWebViewProcess(model);
+ const pChrome1 = createChromeBrowserProcess(model);
+ const pRenderer1 = createProcessWithName(model, 'Renderer');
+ const pGpu1 = createProcessWithName(model, 'GPU Process');
+ const pUnknownBrowser = createProcessWithName(model, 'Browser');
+ const pChrome2 = createChromeBrowserProcess(model);
+ const pRenderer2 = createProcessWithName(model, 'Renderer');
+
+ // Timestamp 1 (WebView).
+ const gmd1 = addGlobalMemoryDump(model, {ts: 0, levelOfDetail: LIGHT});
+ const pmdBrowser1 = addProcessMemoryDump(gmd1, pWebView, {ts: 0});
+ pmdBrowser1.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser1, 'malloc', {numerics: {size: 2}}),
+ newAllocatorDump(pmdBrowser1, 'v8', {numerics: {size: 4}})
+ ];
+
+ // Timestamp 2 (Chrome 1 + Renderer + GPU Process).
+ const gmd2 = addGlobalMemoryDump(model, {ts: 10, levelOfDetail: DETAILED});
+ const pmdBrowser2 = addProcessMemoryDump(gmd2, pChrome1, {ts: 12});
+ pmdBrowser2.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 9999, 0, '/dev/ashmem/dalvik-non moving space',
+ {privateDirtyResident: 8})
+ ]);
+ const pmdGpu2 = addProcessMemoryDump(gmd2, pGpu1, {ts: 8});
+ pmdGpu2.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 9999, 0, '/dev/ashmem/dalvik-non moving space',
+ {privateDirtyResident: 16})
+ ]);
+ const pmdRenderer2 = addProcessMemoryDump(gmd2, pRenderer1, {ts: 8});
+ pmdRenderer2.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser2, 'malloc', {numerics: {size: 32}})
+ ];
+
+ // Timestamp 3 (Chrome 2).
+ const gmd3 = addGlobalMemoryDump(model, {ts: 20, levelOfDetail: DETAILED});
+ const pmdBrowser3 = addProcessMemoryDump(gmd3, pChrome2, {ts: 20});
+ pmdBrowser3.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser3, 'malloc', {numerics: {size: 64}}),
+ newAllocatorDump(pmdBrowser3, 'sqlite', {numerics: {size: 128}}),
+ newAllocatorDump(pmdBrowser3, 'discardable', {numerics: {
+ size: 8388608,
+ locked_size: 4194304
+ }})
+ ];
+ pmdBrowser3.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 99, 0, '/dev/ashmem/dalvik-non moving space',
+ {privateDirtyResident: 256})
+ ]);
+
+ // Timestamp 4 (Chrome 2 + Renderer).
+ const gmd4 = addGlobalMemoryDump(model, {ts: 30, levelOfDetail: LIGHT});
+ const pmdBrowser4 = addProcessMemoryDump(gmd4, pChrome2, {ts: 28});
+ pmdBrowser4.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser4, 'malloc', {numerics: {size: 512}}),
+ newAllocatorDump(pmdBrowser3, 'discardable', {numerics: {size: 16777216}})
+ ];
+ const pmdRenderer4 = addProcessMemoryDump(gmd4, pRenderer2, {ts: 32});
+ pmdRenderer4.memoryAllocatorDumps = [
+ newAllocatorDump(pmdRenderer4, 'malloc', {numerics: {size: 1024}}),
+ newAllocatorDump(pmdRenderer4, 'v8', {numerics: {size: 2048}})
+ ];
+
+ // Timestamp 5 (Unknown browser).
+ const gmd5 = addGlobalMemoryDump(model, {ts: 40, levelOfDetail: LIGHT});
+ const pmdBrowser5 = addProcessMemoryDump(gmd5, pUnknownBrowser, {ts: 40});
+ pmdBrowser5.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser5, 'malloc', {numerics: {size: 4096}}),
+ newAllocatorDump(pmdBrowser5, 'sqlite', {numerics: {size: 8192}}),
+ ];
+
+ // Timestamp 6 (WebView).
+ const gmd6 = addGlobalMemoryDump(model, {ts: 50, levelOfDetail: DETAILED});
+ const pmdBrowser6 = addProcessMemoryDump(gmd6, pWebView, {ts: 50});
+ pmdBrowser6.memoryAllocatorDumps = (function() {
+ const mallocDump = newAllocatorDump(pmdBrowser6, 'malloc',
+ {numerics: {size: 16384}});
+ const v8Dump = newAllocatorDump(pmdBrowser6, 'v8', {numerics: {
+ allocated_objects_size: 32768,
+ code_and_metadata_size: 33554432,
+ size: 67108864
+ }});
+ const isolateDump = addChildDump(v8Dump, 'isolateA');
+ addChildDump(isolateDump, 'malloc', {numerics: {
+ size: 1,
+ peak_size: 2
+ }});
+ return [mallocDump, v8Dump];
+ })();
+ pmdBrowser6.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 99999, 0, '/dev/ashmem/dalvik-non moving space',
+ {privateDirtyResident: 65536})
+ ]);
+
+ // Timestamp 7 (Chrome 1 + GPU Process).
+ const gmd7 = addGlobalMemoryDump(model, {ts: 60, levelOfDetail: DETAILED});
+ const pmdBrowser7 = addProcessMemoryDump(gmd7, pChrome1, {ts: 63});
+ pmdBrowser7.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser4, 'malloc', {numerics: {size: 131072}}),
+ newAllocatorDump(pmdBrowser4, 'sqlite', {numerics: {size: 262144}})
+ ];
+ pmdBrowser7.vmRegions = VMRegionClassificationNode.fromRegions([
+ new VMRegion(0xABCD, 999999, 0, '/dev/ashmem/dalvik-non moving space',
+ {privateDirtyResident: 524288})
+ ]);
+ const pmdGpu7 = addProcessMemoryDump(gmd7, pGpu1, {ts: 57});
+ pmdGpu7.memoryAllocatorDumps = (function() {
+ const gpuDump = newAllocatorDump(pmdGpu7, 'gpu',
+ {numerics: {size: 1048576}});
+ const memtrackDump = addChildDump(gpuDump, 'android_memtrack');
+ addChildDump(memtrackDump, 'gl', {numerics: {memtrack_pss: 2097152}});
+ return [gpuDump];
+ })();
+
+ // Timestamp 8 (Chrome 1).
+ const gmd8 = addGlobalMemoryDump(
+ model, {ts: 76, levelOfDetail: BACKGROUND});
+ const pmdBrowser8 = addProcessMemoryDump(gmd8, pChrome1, {ts: 80});
+ pmdBrowser8.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser5, 'malloc', {numerics: {size: 1024}}),
+ newAllocatorDump(pmdBrowser5, 'sqlite', {numerics: {size: 2048}}),
+ ];
+
+ // Timestamp 9 (WebView).
+ const gmd9 = addGlobalMemoryDump(
+ model, {ts: 90, levelOfDetail: BACKGROUND});
+ const pmdBrowser9 = addProcessMemoryDump(gmd9, pWebView, {ts: 90});
+ pmdBrowser9.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser5, 'v8', {numerics: {size: 4096}}),
+ newAllocatorDump(pmdBrowser5, 'sqlite', {numerics: {size: 2048}}),
+ ];
+ }, undefined /* opt_options */, {
+ // WebView (GMD1, GMD6).
+ 'memory:webview:all_processes:dump_count:detailed': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by WebView ' +
+ 'to the trace'
+ },
+ 'memory:webview:all_processes:dump_count:light': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by WebView to ' +
+ 'the trace'
+ },
+ 'memory:webview:all_processes:dump_count:background': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by WebView ' +
+ 'to the trace'
+ },
+ 'memory:webview:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'WebView to the trace'
+ },
+ 'memory:webview:all_processes:dump_count': {
+ value: [3],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by WebView to the ' +
+ 'trace'
+ },
+ 'memory:webview:all_processes:process_count': {
+ value: [1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:effective_size': {
+ value: [4 + 2, 16384 + 67108864, 4096 + 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:code_and_metadata_size': {
+ value: [0, 33554432, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of code and metadata reported by Chrome for ' +
+ 'all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:allocated_objects_size': {
+ value: [0, 32768, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects reported by Chrome ' +
+ 'for all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:peak_size':
+ {
+ value: [0, 2, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total peak size reported by Chrome for all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:malloc:effective_size': {
+ value: [2, 16384, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:sqlite:effective_size': {
+ value: [0, 2048, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of sqlite in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:v8:allocated_by_malloc:effective_size':
+ {
+ value: [0, 1, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of objects allocated by malloc for v8 ' +
+ 'in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:v8:allocated_by_malloc:peak_size':
+ {
+ value: [0, 2, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'peak size of objects allocated by malloc for v8 ' +
+ 'in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:v8:effective_size': {
+ value: [4, 67108864, 4096],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:v8:code_and_metadata_size':
+ {
+ value: [0, 33554432, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of v8 code and metadata in all processes in ' +
+ 'WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:v8:allocated_objects_size':
+ {
+ value: [0, 32768, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8 in all processes ' +
+ 'in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_chrome:v8:peak_size':
+ {
+ value: [0, 2, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'peak size of v8 in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:private_dirty_size': {
+ value: [65536],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:proportional_resident_size': {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by the ' +
+ 'OS for all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in all processes in ' +
+ 'WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [65536],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in all processes ' +
+ 'in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [65536],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by all processes in WebView'
+ },
+ 'memory:webview:browser_process:process_count': {
+ value: [1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:effective_size': {
+ value: [4 + 2, 16384 + 67108864, 4096 + 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for the browser ' +
+ 'process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:allocated_objects_size':
+ {
+ value: [0, 32768, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of all allocated objects reported by ' +
+ 'Chrome for the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:code_and_metadata_size':
+ {
+ value: [0, 33554432, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total size of code and metadata reported by Chrome ' +
+ 'for the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:peak_size':
+ {
+ value: [0, 2, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total peak size reported by Chrome ' +
+ 'for the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:malloc:effective_size': {
+ value: [2, 16384, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:v8:allocated_by_malloc:effective_size':
+ {
+ value: [0, 1, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of objects allocated by malloc for v8 ' +
+ 'in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:v8:allocated_by_malloc:peak_size':
+ {
+ value: [0, 2, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'peak size of objects allocated by malloc for v8 ' +
+ 'in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:sqlite:effective_size': {
+ value: [0, 0, 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of sqlite in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:v8:effective_size': {
+ value: [4, 67108864, 4096],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:v8:allocated_objects_size':
+ {
+ value: [0, 32768, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of all objects allocated by v8 in the browser ' +
+ 'process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:v8:code_and_metadata_size':
+ {
+ value: [0, 33554432, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'size of v8 code and metadata in the browser process ' +
+ 'in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_chrome:v8:peak_size':
+ {
+ value: [0, 2, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'peak size of v8 in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:private_dirty_size': {
+ value: [65536],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for the ' +
+ 'browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by ' +
+ 'the OS for the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in the browser process ' +
+ 'in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in the ' +
+ 'browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [65536],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in the browser ' +
+ 'process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in the browser ' +
+ 'process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in the browser ' +
+ 'process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [65536],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by the browser process in WebView'
+ },
+
+ // Chrome 1 (GMD3, GMD4).
+ 'memory:chrome:all_processes:reported_by_os:gpu_memory:gl:proportional_resident_size':
+ {
+ value: [0, 2097152],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the gl Android ' +
+ 'memtrack component in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:dump_count:detailed': {
+ value: [2],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:light': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:background': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by Chrome ' +
+ 'to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'Chrome to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count': {
+ value: [3],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by Chrome to the ' +
+ 'trace'
+ },
+ 'memory:chrome:all_processes:process_count': {
+ value: [3, 2, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:effective_size': {
+ value: [32, 1048576 + 131072 + 262144, 1024 + 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:gpu:effective_size': {
+ value: [0, 1048576, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of gpu in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:malloc:effective_size': {
+ value: [32, 131072, 1024],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_chrome:sqlite:effective_size': {
+ value: [0, 262144, 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of sqlite in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:private_dirty_size': {
+ value: [8 + 16, 524288],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:proportional_resident_size': {
+ value: [0, 2097152],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by the ' +
+ 'OS for all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:gpu_memory:proportional_resident_size':
+ {
+ value: [0, 2097152],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of GPU memory ' +
+ '(Android memtrack) used by all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [8 + 16, 524288],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in all processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in all ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [8 + 16, 524288],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by all processes in Chrome'
+ },
+ 'memory:chrome:all_processes:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by all processes in Chrome'
+ },
+ 'memory:chrome:browser_process:process_count': {
+ value: [1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:effective_size': {
+ value: [0, 131072 + 262144, 1024 + 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:malloc:effective_size': {
+ value: [0, 131072, 1024],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_chrome:sqlite:effective_size': {
+ value: [0, 262144, 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of sqlite in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:private_dirty_size': {
+ value: [8, 524288],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:proportional_resident_size': {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by the ' +
+ 'OS for the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in the browser process ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in the ' +
+ 'browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [8, 524288],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in the browser ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [8, 524288],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by the browser process in Chrome'
+ },
+ 'memory:chrome:browser_process:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by the browser process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_chrome:effective_size': {
+ value: [0, 1048576, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for the GPU ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:gpu_memory:proportional_resident_size':
+ {
+ value: [0, 2097152],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of GPU memory ' +
+ '(Android memtrack) used by the GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:gpu_memory:gl:proportional_resident_size':
+ {
+ value: [0, 2097152],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the gl Android ' +
+ 'memtrack component in the GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:process_count': {
+ value: [1, 1, 0],
+ unit: count_smallerIsBetter,
+ description: 'total number of GPU processes in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_chrome:gpu:effective_size': {
+ value: [0, 1048576, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of gpu in the GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:private_dirty_size': {
+ value: [16, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for the GPU ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:proportional_resident_size': {
+ value: [0, 2097152],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by the ' +
+ 'OS for the GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in the GPU process in ' +
+ 'Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in the ' +
+ 'GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [16, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in the GPU ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'the GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in the GPU ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in the GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in the GPU ' +
+ 'process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in the GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [16, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by the GPU process in Chrome'
+ },
+ 'memory:chrome:gpu_process:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by the GPU process in Chrome'
+ },
+ 'memory:chrome:renderer_processes:process_count': {
+ value: [1, 0, 0],
+ unit: count_smallerIsBetter,
+ description: 'total number of renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:effective_size': {
+ value: [32, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_chrome:malloc:effective_size':
+ {
+ value: [32, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in renderer processes in ' +
+ 'Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:private_dirty_size': {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by ' +
+ 'the OS for renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in renderer processes ' +
+ 'in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in ' +
+ 'renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in renderer ' +
+ 'processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by renderer processes in Chrome'
+ },
+ 'memory:chrome:renderer_processes:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by renderer processes in Chrome'
+ },
+
+ // Chrome 2 (GMD2, GMD7).
+ 'memory:chrome2:all_processes:dump_count:detailed': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by Chrome(2) ' +
+ 'to the trace'
+ },
+ 'memory:chrome2:all_processes:dump_count:light': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by Chrome(2) to ' +
+ 'the trace'
+ },
+ 'memory:chrome2:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by ' +
+ 'Chrome(2) to the trace'
+ },
+ 'memory:chrome2:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'Chrome(2) to the trace'
+ },
+ 'memory:chrome2:all_processes:dump_count': {
+ value: [2],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by Chrome(2) to ' +
+ 'the trace'
+ },
+ 'memory:chrome2:all_processes:process_count': {
+ value: [1, 2],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_chrome:discardable:effective_size':
+ {
+ value: [8388608, 16777216],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of discardable in all processes in ' +
+ 'Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_chrome:locked_size': {
+ value: [4194304, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total locked (pinned) size reported by Chrome for all ' +
+ 'processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_chrome:discardable:locked_size': {
+ value: [4194304, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'locked (pinned) size of discardable in all processes in ' +
+ 'Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_chrome:effective_size': {
+ value: [64 + 8388608 + 128, 512 + 1024 + 2048 + 16777216],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for all ' +
+ 'processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_chrome:malloc:effective_size': {
+ value: [64, 512 + 1024],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_chrome:sqlite:effective_size': {
+ value: [128, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of sqlite in all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_chrome:v8:effective_size': {
+ value: [0, 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:private_dirty_size': {
+ value: [256],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for all ' +
+ 'processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:proportional_resident_size': {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by the ' +
+ 'OS for all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in all processes in ' +
+ 'Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in all ' +
+ 'processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [256],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in all processes ' +
+ 'in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in all ' +
+ 'processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in all ' +
+ 'processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [256],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by all processes in Chrome(2)'
+ },
+ 'memory:chrome2:all_processes:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by all processes in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:process_count': {
+ value: [1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_chrome:effective_size': {
+ value: [64 + 8388608 + 128, 512 + 16777216],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for the browser ' +
+ 'process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_chrome:locked_size': {
+ value: [4194304, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total locked (pinned) size reported by Chrome for the ' +
+ 'browser process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_chrome:malloc:effective_size': {
+ value: [64, 512],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in the browser process in ' +
+ 'Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_chrome:discardable:effective_size':
+ {
+ value: [8388608, 16777216],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of discardable in the browser process ' +
+ 'in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_chrome:discardable:locked_size':
+ {
+ value: [4194304, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'locked (pinned) size of discardable in the browser ' +
+ 'process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_chrome:sqlite:effective_size': {
+ value: [128, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of sqlite in the browser process in ' +
+ 'Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:private_dirty_size': {
+ value: [256],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for the ' +
+ 'browser process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by ' +
+ 'the OS for the browser process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in the browser process ' +
+ 'in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in the ' +
+ 'browser process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [256],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in the browser ' +
+ 'process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'the browser process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in the browser ' +
+ 'process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in the browser process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in the browser ' +
+ 'process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in the browser process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [256],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by the browser process in Chrome(2)'
+ },
+ 'memory:chrome2:browser_process:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by the browser process in Chrome(2)'
+ },
+ 'memory:chrome2:renderer_processes:process_count': {
+ value: [0, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of renderer processes in Chrome(2)'
+ },
+ 'memory:chrome2:renderer_processes:reported_by_chrome:effective_size': {
+ value: [0, 1024 + 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for renderer ' +
+ 'processes in Chrome(2)'
+ },
+ 'memory:chrome2:renderer_processes:reported_by_chrome:malloc:effective_size':
+ {
+ value: [0, 1024],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in renderer processes in ' +
+ 'Chrome(2)'
+ },
+ 'memory:chrome2:renderer_processes:reported_by_chrome:v8:effective_size': {
+ value: [0, 2048],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of v8 in renderer processes in Chrome(2)'
+ },
+
+ // Unknown browser (GMD5).
+ 'memory:unknown_browser:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:light': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by an unknown ' +
+ 'browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by an unknown ' +
+ 'browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:process_count': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:effective_size': {
+ value: [4096 + 8192],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for all ' +
+ 'processes in an unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:malloc:effective_size':
+ {
+ value: [4096],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in all processes in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:all_processes:reported_by_chrome:sqlite:effective_size':
+ {
+ value: [8192],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of sqlite in all processes in an ' +
+ 'unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:process_count': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_chrome:effective_size':
+ {
+ value: [4096 + 8192],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total effective size reported by Chrome for the ' +
+ 'browser process in an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_chrome:malloc:effective_size':
+ {
+ value: [4096],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of malloc in the browser process in ' +
+ 'an unknown browser'
+ },
+ 'memory:unknown_browser:browser_process:reported_by_chrome:sqlite:effective_size':
+ {
+ value: [8192],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'effective size of sqlite in the browser process in ' +
+ 'an unknown browser'
+ }
+ });
+
+ memoryMetricTest('rangeOfInterest', function(model) {
+ const pChrome = createChromeBrowserProcess(model);
+ const pWebView = createWebViewProcess(model);
+
+ // Chrome: only the LIGHT dumps should be kept.
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 5, duration: 4, levelOfDetail: DETAILED}), pChrome);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 10, duration: 2, levelOfDetail: LIGHT}), pChrome);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 13, duration: 3, levelOfDetail: LIGHT}), pChrome);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 20, duration: 1, levelOfDetail: BACKGROUND}), pChrome);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 22, duration: 5, levelOfDetail: DETAILED}), pChrome);
+
+ // WebView: only the DETAILED dumps should be kept.
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 4, duration: 1, levelOfDetail: LIGHT}), pWebView);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 5, duration: 5, levelOfDetail: DETAILED}), pWebView);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 10, duration: 0, levelOfDetail: DETAILED}), pWebView);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 11, duration: 7, levelOfDetail: BACKGROUND}), pWebView);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 19, duration: 2, levelOfDetail: DETAILED}), pWebView);
+ addProcessMemoryDump(addGlobalMemoryDump(
+ model, {ts: 21, duration: 5, levelOfDetail: LIGHT}), pWebView);
+
+ // Unknown browser: only the LIGHT dump should be kept.
+ addGlobalMemoryDump(model, {ts: 5, duration: 3, levelOfDetail: DETAILED});
+ addGlobalMemoryDump(model, {ts: 9, duration: 12, levelOfDetail: LIGHT});
+ addGlobalMemoryDump(model, {ts: 22, duration: 3, levelOfDetail: DETAILED});
+ }, { /* opt_options */
+ rangeOfInterest: tr.b.math.Range.fromExplicitRange(10, 20)
+ }, {
+ 'memory:chrome:all_processes:dump_count': {
+ value: [3],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by Chrome to the ' +
+ 'trace'
+ },
+ 'memory:chrome:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:light': {
+ value: [2],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by Chrome to ' +
+ 'the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:background': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by Chrome ' +
+ 'to the trace'
+ },
+ 'memory:chrome:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'Chrome to the trace'
+ },
+ 'memory:chrome:all_processes:process_count': {
+ value: [1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in Chrome'
+ },
+ 'memory:chrome:browser_process:process_count': {
+ value: [1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in Chrome'
+ },
+
+ 'memory:webview:all_processes:dump_count': {
+ value: [4],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by WebView to the ' +
+ 'trace'
+ },
+ 'memory:webview:all_processes:dump_count:detailed': {
+ value: [3],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by WebView ' +
+ 'to the trace'
+ },
+ 'memory:webview:all_processes:dump_count:light': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by WebView to ' +
+ 'the trace'
+ },
+ 'memory:webview:all_processes:dump_count:background': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by WebView ' +
+ 'to the trace'
+ },
+ 'memory:webview:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by ' +
+ 'WebView to the trace'
+ },
+ 'memory:webview:all_processes:process_count': {
+ value: [1, 1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:private_dirty_size': {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:proportional_resident_size': {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by the ' +
+ 'OS for all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in all processes in ' +
+ 'WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in all processes ' +
+ 'in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in all ' +
+ 'processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by all processes in WebView'
+ },
+ 'memory:webview:all_processes:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by all processes in WebView'
+ },
+ 'memory:webview:browser_process:process_count': {
+ value: [1, 1, 1, 1],
+ unit: count_smallerIsBetter,
+ description: 'total number of browser processes in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:private_dirty_size': {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size reported by the OS for the ' +
+ 'browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) reported by ' +
+ 'the OS for the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:ashmem:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of ashmem in the browser process ' +
+ 'in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:ashmem:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of ashmem in the ' +
+ 'browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:java_heap:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the Java heap in the browser ' +
+ 'process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:java_heap:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the Java heap in ' +
+ 'the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:native_heap:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the native heap in the browser ' +
+ 'process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:native_heap:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the native heap ' +
+ 'in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:stack:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'private dirty size of the thread stacks in the browser ' +
+ 'process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:stack:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'proportional resident size (PSS) of the thread stacks ' +
+ 'in the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:private_dirty_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total private dirty size of system memory (RAM) used ' +
+ 'by the browser process in WebView'
+ },
+ 'memory:webview:browser_process:reported_by_os:system_memory:proportional_resident_size':
+ {
+ value: [0, 0, 0],
+ unit: sizeInBytes_smallerIsBetter,
+ description: 'total proportional resident size (PSS) of system ' +
+ 'memory (RAM) used by the browser process in WebView'
+ },
+ 'memory:unknown_browser:all_processes:dump_count': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of all memory dumps added by an unknown ' +
+ 'browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:detailed': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of detailed memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:light': {
+ value: [1],
+ unit: count_smallerIsBetter,
+ description: 'total number of light memory dumps added by an unknown ' +
+ 'browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:background': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of background memory dumps added by an ' +
+ 'unknown browser to the trace'
+ },
+ 'memory:unknown_browser:all_processes:dump_count:heap_profiler': {
+ value: [0],
+ unit: count_smallerIsBetter,
+ description: 'total number of heap profiler memory dumps added by an ' +
+ 'unknown browser to the trace'
+ }
+ });
+
+ test('allProcessesHasBreakdown', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const pBrowser = createChromeBrowserProcess(model);
+ const pRenderer = createProcessWithName(model, 'Renderer');
+ const pGpu = createProcessWithName(model, 'GPU Process');
+
+ const gmd = addGlobalMemoryDump(model, {ts: 20});
+ const pmdBrowser = addProcessMemoryDump(gmd, pBrowser, {ts: 19});
+ pmdBrowser.memoryAllocatorDumps = [
+ newAllocatorDump(pmdBrowser, 'malloc', {numerics: {
+ size: 8,
+ allocated_objects_size: 4
+ }})
+ ];
+
+ const pmdRenderer = addProcessMemoryDump(gmd, pRenderer, {ts: 20});
+ pmdRenderer.memoryAllocatorDumps = [
+ newAllocatorDump(pmdRenderer, 'malloc', {numerics: {size: 16}})
+ ];
+
+ const pmdGpu = addProcessMemoryDump(gmd, pGpu, {ts: 21});
+ pmdGpu.memoryAllocatorDumps = [
+ newAllocatorDump(pmdGpu, 'gpu', {numerics: {
+ size: 30,
+ allocated_objects_size: 25
+ }})
+ ];
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.memoryMetric(histograms, model);
+ const prefix = 'memory:chrome:';
+ const suffix = ':reported_by_chrome:malloc:effective_size';
+ const allHistogram =
+ histograms.getHistogramNamed(`${prefix}all_processes${suffix}`);
+ const rendererHistogram =
+ histograms.getHistogramNamed(`${prefix}renderer_processes${suffix}`);
+ const browserHistogram =
+ histograms.getHistogramNamed(`${prefix}browser_process${suffix}`);
+
+ const relatedNameMap = allHistogram.diagnostics.get('processes');
+ assert.strictEqual(relatedNameMap.get('browser_process'),
+ browserHistogram.name);
+ assert.strictEqual(relatedNameMap.get('renderer_processes'),
+ rendererHistogram.name);
+ assert.strictEqual(relatedNameMap.get('gpu_process'), undefined);
+
+ const bin = allHistogram.getBinForValue(allHistogram.average);
+ const breakdown = tr.b.getOnlyElement(bin.diagnosticMaps).get('processes');
+ assert.strictEqual(breakdown.get('browser_process'),
+ browserHistogram.average);
+ assert.strictEqual(breakdown.get('renderer_processes'),
+ rendererHistogram.average);
+ });
+
+ test('componentsHaveBreakdowns', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const pBrowser = createChromeBrowserProcess(model);
+
+ const gmd = addGlobalMemoryDump(model, {ts: 20});
+ const pmdBrowser = addProcessMemoryDump(gmd, pBrowser, {ts: 19});
+ const v8Dump = newAllocatorDump(pmdBrowser, 'v8', {numerics: {
+ size: 10,
+ }});
+
+ const isolateDumpA = addChildDump(v8Dump, 'isolate_A');
+ addChildDump(isolateDumpA, 'malloc', {numerics: {
+ size: 1,
+ peak_size: 2
+ }});
+
+ const heapDumpA = addChildDump(isolateDumpA, 'heap_spaces', {numerics: {
+ size: 42,
+ allocated_objects_size: 36
+ }});
+
+ addChildDump(heapDumpA, 'code_space', {numerics: {
+ allocated_objects_size: 1,
+ size: 2
+ }});
+
+ pmdBrowser.memoryAllocatorDumps = [v8Dump];
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.memoryMetric(histograms, model);
+ const prefix = 'memory:chrome:browser_process:reported_by_chrome';
+ const suffix = 'effective_size';
+ const browserHistogram = histograms.getHistogramNamed(
+ `${prefix}:v8:${suffix}`);
+ const heapHistogram = histograms.getHistogramNamed(
+ `${prefix}:v8:heap:${suffix}`);
+ const codeSpaceHistogram = histograms.getHistogramNamed(
+ `${prefix}:v8:heap:code_space:${suffix}`);
+
+ assert.strictEqual(browserHistogram.diagnostics.get('components').get(
+ 'heap'), heapHistogram.name);
+ assert.strictEqual(heapHistogram.diagnostics.get('components').get(
+ 'code_space'), codeSpaceHistogram.name);
+
+ const browserBin = browserHistogram.getBinForValue(
+ browserHistogram.average);
+ const browserBreakdown = tr.b.getOnlyElement(
+ browserBin.diagnosticMaps).get('components');
+ assert.strictEqual(browserBreakdown.get('heap'), heapHistogram.average);
+
+ const heapBin = heapHistogram.getBinForValue(heapHistogram.average);
+ const heapBreakdown = tr.b.getOnlyElement(
+ heapBin.diagnosticMaps).get('components');
+ assert.strictEqual(heapBreakdown.get('code_space'),
+ codeSpaceHistogram.average);
+ });
+
+ test('dumpIdBrowserClashThrows', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const pWebView = createWebViewProcess(model);
+ const pChrome = createChromeBrowserProcess(model);
+
+ const gmd = addGlobalMemoryDump(model, {ts: 10});
+ addProcessMemoryDump(gmd, pWebView, {ts: 9});
+ addProcessMemoryDump(gmd, pChrome, {ts: 11});
+ });
+ const histograms = new tr.v.HistogramSet();
+
+ assert.throws(function() {
+ tr.metrics.sh.memoryMetric(histograms, model);
+ }, 'Memory dump ID clash across multiple browsers with PIDs: 1 and 2');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/new_cpu_time_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/new_cpu_time_metric.html
new file mode 100644
index 00000000000..81b4f65ca79
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/new_cpu_time_metric.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cpu_time.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/cpu_time_tree_data_reporter.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Implements the new CPU time metric. This will eventually
+ * replace the current cpu_time_metric.html, but we're running this alongside
+ * the existing metric while we monitor its quality.
+ *
+ */
+tr.exportTo('tr.metrics.sh', function() {
+ /**
+ * This metric measures total CPU time and CPU time per unit of wall clock
+ * time for all combinations of process type, thread type, RAIL
+ * stage, and RAIL stage initiator present in the model.
+ *
+ * The metric generates histograms of the form
+ * ${cpuTime|cpuPercentage}:${process_type}:${thread_type}:
+ * ${rail_stage}:${rail_stage_initiator}
+ *
+ * 'cpuTime' histograms represent total consumed CPU time, while
+ * 'cpuPercentage' histograms represent CPU time as a percentage of wall clock
+ * time.
+ *
+ * Example histograms generated by this metric:
+ * - cpuTime:browser_process:CrBrowserMain:Animation:CSS
+ * - cpuPercentage:gpu_process:CrGpuMain:Response:Scroll
+
+ * For a given model, a single sample is generated for each histogram. For
+ * example, if the model contains three renderer processes, and 10 different
+ * Scroll Response ranges, the histogram
+ * cpuPercentage:renderer_process:CrRendererMain:Response:Scroll will still
+ * contain a single sample: the total CPU time consumed by all three renderer
+ * main threads over all 10 Scroll Response phases, divided by the total
+ * duration of those ranges. Since the three different main threads can
+ * potentially be running on three different CPU cores, the sample value of a
+ * cpuPercentage histogram can be more than 100%.
+ *
+ * The histograms are created as needed from the model - if a certain
+ * combination of process, thread, RAIL stage and initiator does not occur in
+ * the model, the histogram for that combination is not added.
+ *
+ * This metric requires only the 'toplevel' tracing category.
+ *
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!tr.model.Model} model
+ * @param {!Object=} opt_options
+ */
+ function newCpuTimeMetric(histograms, model, opt_options) {
+ const rangeOfInterest = opt_options && opt_options.rangeOfInterest ?
+ opt_options.rangeOfInterest : model.bounds;
+
+ const rootNode = tr.e.chrome.CpuTime.constructMultiDimensionalView(
+ model, rangeOfInterest);
+
+ tr.metrics.sh.CpuTimeTreeDataReporter.reportToHistogramSet(
+ rootNode, histograms);
+ }
+
+ tr.metrics.MetricRegistry.register(newCpuTimeMetric, {
+ supportsRangeOfInterest: true
+ });
+
+ return {
+ newCpuTimeMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/new_cpu_time_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/new_cpu_time_metric_test.html
new file mode 100644
index 00000000000..a21b6b83ca6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/new_cpu_time_metric_test.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/multi_dimensional_view.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/system_health/new_cpu_time_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const cpuTimeMetric = tr.metrics.sh.newCpuTimeMetric;
+ const CHROME_PROCESS_NAMES =
+ tr.e.chrome.chrome_processes.CHROME_PROCESS_NAMES;
+
+ test('cpuTimeMetric_customRangeOfInterest', () => {
+ const model = tr.c.TestUtils.newModel(model => {
+ const process = model.getOrCreateProcess(1);
+ process.name = 'Browser';
+ const thread = process.getOrCreateThread(1);
+ thread.name = 'CrBrowserMain';
+
+ // Slice from 0 to 50.
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: 50,
+ cpuStart: 0,
+ cpuDuration: 25
+ }));
+
+ // Slice from 300 to 350.
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 300,
+ duration: 50,
+ cpuStart: 100,
+ cpuDuration: 25
+ }));
+ });
+
+ const metricNameSuffix = CHROME_PROCESS_NAMES.BROWSER +
+ ':CrBrowserMain:all_stages:all_initiators';
+ const rangeOfInterest = new tr.b.math.Range.fromExplicitRange(0, 200);
+ const histograms = new tr.v.HistogramSet();
+ cpuTimeMetric(histograms, model, {rangeOfInterest});
+
+ const cpuPercentageHistogram = histograms.getHistogramNamed(
+ 'cpuPercentage:' + metricNameSuffix);
+ const cpuTimeHistogram = histograms.getHistogramNamed(
+ 'cpuTime:' + metricNameSuffix);
+
+ // Histograms exist.
+ assert.isDefined(cpuPercentageHistogram);
+ assert.isDefined(cpuTimeHistogram);
+
+ // Each histogram contains a single sample.
+ assert.strictEqual(cpuPercentageHistogram.running.count, 1);
+ assert.strictEqual(cpuTimeHistogram.running.count, 1);
+
+ // Assert histogram sample value is correct:
+ // rangeOfInterest only contains the first slice (with a CPU time of 25),
+ // and total duration of the range is 200.
+ assert.closeTo(cpuPercentageHistogram.sum, 25 / 200, 1e-7);
+ assert.closeTo(cpuTimeHistogram.sum, 25, 1e-7);
+ });
+
+ test('cpuTimeMetric_rangeOfInterestBeyondModelBounds', () => {
+ const model = tr.c.TestUtils.newModel(model => {
+ const process = model.getOrCreateProcess(1);
+ process.name = 'Browser';
+ const thread = process.getOrCreateThread(1);
+ thread.name = 'CrBrowserMain';
+
+ // Slice from 0 to 50.
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: 50,
+ cpuStart: 0,
+ cpuDuration: 25
+ }));
+
+ // Slice from 300 to 350.
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 300,
+ duration: 50,
+ cpuStart: 100,
+ cpuDuration: 25
+ }));
+ });
+
+ const metricNameSuffix = CHROME_PROCESS_NAMES.BROWSER +
+ ':CrBrowserMain:all_stages:all_initiators';
+ const rangeOfInterest = new tr.b.math.Range.fromExplicitRange(-100, 200);
+ const histograms = new tr.v.HistogramSet();
+ cpuTimeMetric(histograms, model, {rangeOfInterest});
+
+ const cpuPercentageHistogram = histograms.getHistogramNamed(
+ 'cpuPercentage:' + metricNameSuffix);
+ const cpuTimeHistogram = histograms.getHistogramNamed(
+ 'cpuTime:' + metricNameSuffix);
+
+ // Histograms exist.
+ assert.isDefined(cpuPercentageHistogram);
+ assert.isDefined(cpuTimeHistogram);
+
+ // Each histogram contains a single sample.
+ assert.strictEqual(cpuPercentageHistogram.running.count, 1);
+ assert.strictEqual(cpuTimeHistogram.running.count, 1);
+
+ // Assert histogram sample value is correct:
+ // model.bounds is [0, 350] here. If rangeOfInterest is beyond these bounds,
+ // the effective range for calculating total duration for cpuPercentage is
+ // the intersection of rangeOfInterest and model.bounds, which is [0, 200]
+ // here. rangeOfInterest only contains the first slice, with a CPU time of
+ // 25, and the total effective duration is 200, not 300.
+ assert.closeTo(cpuPercentageHistogram.sum, 25 / 200, 1e-7);
+ assert.closeTo(cpuTimeHistogram.sum, 25, 1e-7);
+ });
+
+ test('cpuTimeMetric_defaultRangeOfInterest', () => {
+ const model = tr.c.TestUtils.newModel(model => {
+ const process = model.getOrCreateProcess(1);
+ process.name = 'Browser';
+ const thread = process.getOrCreateThread(1);
+ thread.name = 'CrBrowserMain';
+
+ // Slice from 0 to 50.
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: 50,
+ cpuStart: 0,
+ cpuDuration: 25
+ }));
+
+ // Slice from 300 to 350.
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 300,
+ duration: 50,
+ cpuStart: 100,
+ cpuDuration: 25
+ }));
+ });
+
+ const metricNameSuffix = CHROME_PROCESS_NAMES.BROWSER +
+ ':CrBrowserMain:all_stages:all_initiators';
+ const histograms = new tr.v.HistogramSet();
+ cpuTimeMetric(histograms, model);
+
+ const cpuPercentageHistogram = histograms.getHistogramNamed(
+ 'cpuPercentage:' + metricNameSuffix);
+ const cpuTimeHistogram = histograms.getHistogramNamed(
+ 'cpuTime:' + metricNameSuffix);
+
+ // Histograms exist.
+ assert.isDefined(cpuPercentageHistogram);
+ assert.isDefined(cpuTimeHistogram);
+
+ // Each histogram contains a single sample.
+ assert.strictEqual(cpuPercentageHistogram.running.count, 1);
+ assert.strictEqual(cpuTimeHistogram.running.count, 1);
+
+ // Assert histogram sample value is correct:
+ // When no custom rangeOfInterest is set, the effective range for
+ // calculating CPU usage should be model.bounds, which is [0, 350] here.
+ // Total CPU time is 25 + 25 from the two slices.
+ assert.closeTo(cpuPercentageHistogram.sum, (25 + 25) / 350, 1e-7);
+ assert.closeTo(cpuTimeHistogram.sum, 25 + 25, 1e-7);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/power_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/power_metric.html
new file mode 100644
index 00000000000..8b343e07f49
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/power_metric.html
@@ -0,0 +1,348 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/importer/find_input_expectations.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ // If the power series doesn't cover the entire Chrome trace, then
+ // the results from Chrome tracing metrics will likely be inaccurate,
+ // so we don't report them. However, we allow the power series bounds
+ // to be up to 1 ms inside the Chrome trace and still count as
+ // covering the Chrome trace. This is to allow for small deviations
+ // due to clock sync latency and the finite sampling rate of the
+ // BattOr.
+ const CHROME_POWER_GRACE_PERIOD_MS = 1;
+
+ /**
+ * Creates an empty histogram to hold data for a given time interval.
+ *
+ * @returns {Object} An object of the form:
+ *
+ * {
+ * perSecond {boolean}: Whether the data for this time interval is given
+ * as per second, If not, it's given as an integral over the
+ * whole interval.
+ * energy {tr.v.Histogram}: Histogram giving energy use (i.e. energy in J
+ * if perSecond = False, power in W if perSecond = True)
+ * }
+ */
+ function createEmptyHistogram_(interval, histograms) {
+ if (interval.perSecond) {
+ return {
+ perSecond: true,
+ energy: histograms.createHistogram(`${interval.name}:power`,
+ tr.b.Unit.byName.powerInWatts_smallerIsBetter, [], {
+ description:
+ `Energy consumption rate for ${interval.description}`,
+ summaryOptions: {
+ avg: true,
+ count: false,
+ max: true,
+ min: true,
+ std: false,
+ sum: false,
+ },
+ }),
+ };
+ }
+ return {
+ perSecond: false,
+ energy: histograms.createHistogram(`${interval.name}:energy`,
+ tr.b.Unit.byName.energyInJoules_smallerIsBetter, [], {
+ description: `Energy consumed in ${interval.description}`,
+ summaryOptions: {
+ avg: false,
+ count: false,
+ max: true,
+ min: true,
+ std: false,
+ sum: true,
+ },
+ }),
+ };
+ }
+
+ function createHistograms_(data, interval, histograms) {
+ if (data.histograms[interval.name] === undefined) {
+ data.histograms[interval.name] = createEmptyHistogram_(interval,
+ histograms);
+ }
+ if (data.histograms[interval.name].perSecond) {
+ for (const sample of data.model.device.powerSeries.getSamplesWithinRange(
+ interval.bounds.min, interval.bounds.max)) {
+ data.histograms[interval.name].energy.addSample(sample.powerInW);
+ }
+ } else {
+ const energyInJ = data.model.device.powerSeries.getEnergyConsumedInJ(
+ interval.bounds.min, interval.bounds.max);
+ data.histograms[interval.name].energy.addSample(energyInJ);
+ }
+ }
+
+ /**
+ * Returns the intervals of time between navigation event and time to
+ * interactive.
+ */
+ function getNavigationTTIIntervals_(model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const intervals = [];
+ for (const expectation of model.userModel.expectations) {
+ if (!(expectation instanceof tr.model.um.LoadExpectation)) continue;
+ if (tr.e.chrome.CHROME_INTERNAL_URLS.includes(
+ expectation.url)) {
+ continue;
+ }
+ if (expectation.timeToInteractive !== undefined) {
+ intervals.push(tr.b.math.Range.fromExplicitRange(
+ expectation.navigationStart.start, expectation.timeToInteractive));
+ }
+ }
+ return intervals.sort((x, y) => x.min - y.min);
+ }
+
+ /**
+ * Generates the set of time intervals that metrics should be run over.
+ * Time intervals include each UE (for UE-based metrics), the whole
+ * story (for the full-story metric), etc. Each time interval is given
+ * in the following form:
+ *
+ * {
+ * bounds {tr.b.math.Range}: Boundaries of the time interval.
+ * name {string}: Name of this interval. Used to generate the
+ * metric names.
+ * description {string}: Human readable description of the interval.
+ * Used to generate the metric descriptions.
+ * perSecond {boolean}: Whether metrics over this interval should be
+ * reported as per-second values (e.g. power). If not, integrated values
+ * over the whole interval (e.g. energy) are reported.
+ * }
+ *
+ */
+ function* computeTimeIntervals_(model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const powerSeries = model.device.powerSeries;
+ if (powerSeries === undefined ||
+ powerSeries.samples.length === 0) {
+ return;
+ }
+ // Output the full story power metrics, which exists regardless of
+ // the presence of a Chrome trace.
+ yield {
+ bounds: model.bounds,
+ name: 'story',
+ description: 'user story',
+ perSecond: true
+ };
+
+ const chromeBounds = computeChromeBounds_(model);
+ if (chromeBounds.isEmpty) return;
+
+ const powerSeriesBoundsWithGracePeriod = tr.b.math.Range.fromExplicitRange(
+ powerSeries.bounds.min - CHROME_POWER_GRACE_PERIOD_MS,
+ powerSeries.bounds.max + CHROME_POWER_GRACE_PERIOD_MS);
+ if (!powerSeriesBoundsWithGracePeriod.containsRangeExclusive(
+ chromeBounds)) {
+ return;
+ }
+
+ // If Chrome bounds are good and the power trace covers the Chrome bounds,
+ // then output the Chrome specific metrics (loading and RAIL stages). Note
+ // that only the part of the time interval that overlaps the Chrome bounds
+ // should be included.
+ for (const interval of getRailStageIntervals_(model)) {
+ yield {
+ bounds: interval.bounds.findIntersection(chromeBounds),
+ name: interval.name,
+ description: interval.description,
+ perSecond: interval.perSecond
+ };
+ }
+
+ for (const interval of getLoadingIntervals_(model, chromeBounds)) {
+ yield {
+ bounds: interval.bounds.findIntersection(chromeBounds),
+ name: interval.name,
+ description: interval.description,
+ perSecond: interval.perSecond
+ };
+ }
+ }
+
+ /**
+ * Gets a list of time intervals for the RAIL stages. Each RAIL stage
+ * generates a time interval with the name equal to the name of the RAIL
+ * stage except made into lower case and with spaces replaced bu underscores
+ * e.g. "Scroll Animation" --> "scroll_animation". Each time interval is given
+ * in the following form:
+ *
+ * {
+ * bounds {tr.b.math.Range}: Boundaries of the time interval.
+ * name {string}: Name of this interval. Used to generate the
+ * metric names.
+ * description {string}: Human readable description of the interval.
+ * Used to generate the metric descriptions.
+ * perSecond {boolean}: Whether metrics over this interval should be
+ * reported as per-second values (e.g. power). If not, integrated values
+ * over the whole interval (e.g. energy) are reported.
+ * }
+ *
+ */
+ function* getRailStageIntervals_(model) {
+ for (const exp of model.userModel.expectations) {
+ const histogramName = exp.title.toLowerCase().replace(' ', '_');
+ const energyHist = undefined;
+ if (histogramName.includes('response')) {
+ yield {
+ bounds: tr.b.math.Range.fromExplicitRange(exp.start, exp.end),
+ name: histogramName,
+ description: 'RAIL stage ' + histogramName,
+ perSecond: false
+ };
+ } else if (histogramName.includes('animation') ||
+ histogramName.includes('idle')) {
+ yield {
+ bounds: tr.b.math.Range.fromExplicitRange(exp.start, exp.end),
+ name: histogramName,
+ description: 'RAIL stage ' + histogramName,
+ perSecond: true
+ };
+ }
+ }
+ }
+
+ /**
+ * Gets a list of time intervals for the RAIL stages. Each RAIL stage
+ * generates a time interval with the name equal to the name of the RAIL
+ * stage except made into lower case and with spaces replaced bu underscores
+ * e.g. "Scroll Animation" --> "scroll_animation". Each time interval is given
+ * in the following form:
+ *
+ * {
+ * bounds {tr.b.math.Range}: Boundaries of the time interval.
+ * name {string}: Name of this interval. Used to generate the
+ * metric names.
+ * description {string}: Human readable description of the interval.
+ * Used to generate the metric descriptions.
+ * perSecond {boolean}: Whether metrics over this interval should be
+ * reported as per-second values (e.g. power). If not, integrated values
+ * over the whole interval (e.g. energy) are reported.
+ * }
+ *
+ */
+ function* getLoadingIntervals_(model, chromeBounds) {
+ const ttiIntervals = getNavigationTTIIntervals_(model);
+ for (const ttiInterval of ttiIntervals) {
+ yield {
+ bounds: ttiInterval,
+ name: 'load',
+ description: 'page loads',
+ perSecond: false
+ };
+ }
+ }
+
+ /**
+ * @returns {tr.b.math.Range} The boundaries of the Chrome portion of the
+ * trace.
+ */
+ function computeChromeBounds_(model) {
+ const chromeBounds = new tr.b.math.Range();
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (chromeHelper === undefined) return chromeBounds;
+ for (const helper of chromeHelper.browserHelpers) {
+ if (helper.mainThread) {
+ chromeBounds.addRange(helper.mainThread.bounds);
+ }
+ }
+ for (const pid in chromeHelper.rendererHelpers) {
+ if (chromeHelper.rendererHelpers[pid].mainThread) {
+ chromeBounds.addRange(
+ chromeHelper.rendererHelpers[pid].mainThread.bounds);
+ }
+ }
+ return chromeBounds;
+ }
+
+ /**
+ * Adds the power histograms to the histogram set.
+ *
+ * Each power histogram is based on a specific time interval, and is named as
+ * follows:
+ *
+ * - [time_interval_name]:power, which contains a sample for each power
+ * sample data point during any time interval with the given type. Each
+ * sample represents the power draw during the period covered by that
+ * power sample.
+ *
+ * - [time_interval_name]:energy, which contains a sample for each time
+ * interval with the given type present in the trace. Each sample
+ * represents the total energy used over that time interval.
+ *
+ * The time intervals are as follows:
+ *
+ * - "story": The time interval covering the entire user story. There is
+ * always exactly one "story" interval.
+ *
+ * - "load" : The time interval covered by a page load, from navigationStart
+ * to timeToInteractive. There is one "load" interval for each page load
+ * in the trace.
+ *
+ * - "[user_expectation_type]" : Each Response, Animation, or Idle
+ * UE in the trace generates a time interval whose name is that of the UE,
+ * converted to lower case and with underscores in place of spaces.
+ * For instance, if there are three "Scroll Response" UEs in the trace,
+ * then there will be three "scroll_response" time intervals, so the
+ * histogram scroll_response:energy will contain three samples.
+ *
+ * Note that each time interval type only generates ONE of the "power" or
+ * "energy" histograms. Power histograms are generated for time intervals
+ * that represent events that occur over a period of time. This includes
+ * the following intervals
+ *
+ * - "story"
+ * - Any Animation or Idle UE
+ *
+ * For instance, "the energy it takes to play a video"
+ * does not have meaning because it depends on how long the video
+ * is; thus a more meaningful metric is power. In contrast, energy histograms
+ * are generated for time intervals that represent particular tasks
+ * which must be completed. This includes the following intervals:
+ *
+ * - "load"
+ * - Any Response UE
+ *
+ * For instance, if a change causes a response to take longer to process, then
+ * we want to count that as taking the energy over a longer period of time.
+ */
+ function powerMetric(histograms, model) {
+ const data = {
+ model,
+ histograms: {}
+ };
+ for (const interval of computeTimeIntervals_(model)) {
+ createHistograms_(data, interval, histograms);
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(powerMetric);
+
+ return {
+ powerMetric
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/power_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/power_metric_test.html
new file mode 100644
index 00000000000..9e8d47ea258
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/power_metric_test.html
@@ -0,0 +1,742 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import"
+ href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/importer/find_input_expectations.html">
+<link rel="import" href="/tracing/metrics/system_health/power_metric.html">
+<link rel="import" href="/tracing/model/user_model/idle_expectation.html">
+<link rel="import" href="/tracing/model/user_model/load_expectation.html">
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+function containsData(histograms, name) {
+ for (const value of histograms) {
+ if (value.name === name) {
+ return (value.running !== undefined);
+ }
+ }
+
+ return undefined;
+}
+
+function getMetricValueCount(histograms, name) {
+ for (const value of histograms) {
+ if (value.name === name && value.running !== undefined) {
+ return value.running.count;
+ }
+ }
+
+ return undefined;
+}
+
+function getMetricValueSum(histograms, name) {
+ for (const value of histograms) {
+ if (value.name === name && value.running !== undefined) {
+ return value.running.sum;
+ }
+ }
+
+ return undefined;
+}
+
+function getMetricValueMin(histograms, name) {
+ for (const value of histograms) {
+ if (value.name === name && value.running !== undefined) {
+ return value.running.min;
+ }
+ }
+
+ return undefined;
+}
+
+function getMetricValueAvg(histograms, name) {
+ for (const value of histograms) {
+ if (value.name === name && value.running !== undefined) {
+ return value.running.mean;
+ }
+ }
+
+ return undefined;
+}
+
+function getMetricValueMax(histograms, name) {
+ for (const value of histograms) {
+ if (value.name === name && value.running !== undefined) {
+ return value.running.max;
+ }
+ }
+
+ return undefined;
+}
+
+tr.b.unittest.testSuite(function() {
+ test('powerMetric_computesChromeBoundsCorrectly', function() {
+ // Tests if Chrome bounds are computed correctly when there
+ // are both browser and renderer threads in the trace.
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const rendererThread = model.rendererMain;
+ const browserProcess = model.browserProcess;
+ const browserThread = model.browserMain;
+ rendererThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200.0,
+ duration: 500.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ browserThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000.0,
+ duration: 500.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 2000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 0, 2000));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueMin(histograms, 'idle:power'), 200.0, .01);
+ assert.closeTo(getMetricValueAvg(histograms, 'idle:power'), 849.5, .01);
+ assert.closeTo(getMetricValueMax(histograms, 'idle:power'), 1499.0, .01);
+ });
+
+ test('powerMetric_noPowerSeries', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.lengthOf(histograms, 0);
+ });
+
+ test('powerMetric_emptyPowerSeries', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.lengthOf(histograms, 0);
+ });
+
+ test('powerMetric_noChromeTrace', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ // Only the whole trace power metric should contain data.
+ assert(containsData(histograms, 'story:power'));
+ assert(!containsData(histograms, 'load:energy'));
+ assert(!containsData(histograms, 'after_load:power'));
+ });
+
+ test('powerMetric_emptyChromeTrace', function() {
+ const histograms = new tr.v.HistogramSet();
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.LoadExpectation(
+ model, tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL, 0, 500));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 500, 500));
+ });
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert(containsData(histograms, 'story:power'));
+ assert(!containsData(histograms, 'load:energy'));
+ assert(!containsData(histograms, 'after_load:power'));
+ });
+
+ test('powerMetric_powerSeriesStartsLate', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 300; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.LoadExpectation(
+ model, tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL, 0, 500));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 500, 500));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert(containsData(histograms, 'story:power'));
+ assert(!containsData(histograms, 'load:energy'));
+ assert(!containsData(histograms, 'after_load:power'));
+ });
+
+ test('powerMetric_powerSeriesEndsEarly', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 700; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.LoadExpectation(
+ model, tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL, 0, 500));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 500, 500));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert(containsData(histograms, 'story:power'));
+ assert(!containsData(histograms, 'load:energy'));
+ assert(!containsData(histograms, 'after_load:power'));
+ });
+
+ test('powerMetric_generic_oneStageEachType_irBeyondChrome', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const rendererProcess = model.getOrCreateProcess(1234);
+ const mainThread = rendererProcess.getOrCreateThread(1);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.ResponseExpectation(
+ model, tr.model.um.INITIATOR_TYPE.SCROLL, 0, 500));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 500, 1500));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueSum(histograms,
+ 'scroll_response:energy'), 125, 0.5);
+ assert.closeTo(getMetricValueAvg(histograms,
+ 'idle:power'), 750, 0.5);
+ assert.closeTo(getMetricValueAvg(histograms,
+ 'story:power'), 500, 0.5);
+ });
+
+ test('powerMetric_story_minAvgMax', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.ResponseExpectation(
+ model, tr.model.um.INITIATOR_TYPE.SCROLL, 0, 500));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 500, 1500));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueMin(histograms, 'story:power'), 0, .01);
+ assert.closeTo(getMetricValueAvg(histograms, 'story:power'), 500, .01);
+ assert.closeTo(getMetricValueMax(histograms, 'story:power'), 1000, .01);
+ });
+
+ test('powerMetric_generic_oneUEBeforeChrome', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const rendererProcess = model.getOrCreateProcess(1234);
+ const mainThread = rendererProcess.getOrCreateThread(1);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 500,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 0, 300));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 300, 1000));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueAvg(histograms,
+ 'idle:power'), 750, 0.5);
+ });
+
+ test('powerMetric_generic_multipleStagesEachType', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const rendererProcess = model.getOrCreateProcess(1234);
+ const mainThread = rendererProcess.getOrCreateThread(1);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.ResponseExpectation(
+ model, tr.model.um.INITIATOR_TYPE.SCROLL, 0, 200));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 200, 300));
+ model.userModel.expectations.push(new tr.model.um.ResponseExpectation(
+ model, tr.model.um.INITIATOR_TYPE.SCROLL, 500, 400));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 900, 100));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueSum(histograms,
+ 'scroll_response:energy'), 300, 0.6);
+ assert.closeTo(getMetricValueAvg(histograms,
+ 'idle:power'), 500, 0.6);
+ assert.strictEqual(getMetricValueCount(histograms,
+ 'scroll_response:energy'), 2);
+ assert.strictEqual(getMetricValueCount(histograms,
+ 'idle:power'), 400);
+ });
+
+ test('powerMetric_loading_oneInterval_samplesBeyondChrome', function() {
+ // Interval of load is [200, 15400].
+ // Trace goes until 22150.
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start: 200,
+ duration: 5.0
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 9180,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 9200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 9200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9350,
+ duration: 100,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 11150,
+ duration: 100,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 12550,
+ duration: 100,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 14900,
+ duration: 500,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 22150,
+ duration: 10,
+ }));
+
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 15400; i++) {
+ model.device.powerSeries.addPowerSample(i, 20);
+ }
+ for (let i = 15401; i <= 22160; i++) {
+ model.device.powerSeries.addPowerSample(i, 10);
+ }
+ for (let i = 22160; i <= 30000; i++) {
+ model.device.powerSeries.addPowerSample(i, 10);
+ }
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+ // Energy for first load is 20 W * 15.2 s
+ // (interval from 0.2 s to 15.4 s)
+ assert.closeTo(
+ getMetricValueAvg(histograms, 'load:energy'), 304, 0.1);
+ });
+
+ test('powerMetric_loading_noMeaningfulPaint', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9350,
+ duration: 100,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 11150,
+ duration: 100,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 12550,
+ duration: 100,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 14950,
+ duration: 500,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 22150,
+ duration: 10,
+ }));
+
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 15400; i++) {
+ model.device.powerSeries.addPowerSample(i, 20);
+ }
+ for (let i = 15401; i <= 22160; i++) {
+ model.device.powerSeries.addPowerSample(i, 10);
+ }
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+ // Energy for first load is 20 W * 15.2 s
+ // (interval from 0.2 s to 15.4 s)
+ assert.isUndefined(getMetricValueCount(histograms, 'after_load:power'));
+ });
+
+ test('powerMetric_scroll_oneStageEachType', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, tr.model.um.INITIATOR_TYPE.SCROLL, 0, 500));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 500, 500));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueAvg(histograms,
+ 'scroll_animation:power'), 250, 0.5);
+ });
+
+ test('powerMetric_scroll_multipleStagesEachType', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, tr.model.um.INITIATOR_TYPE.SCROLL, 0, 200));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 200, 300));
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, tr.model.um.INITIATOR_TYPE.SCROLL, 500, 200));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 700, 300));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueAvg(histograms,
+ 'scroll_animation:power'), 350, 0.6);
+ });
+
+ test('powerMetric_video_oneStageEachType', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, tr.model.um.INITIATOR_TYPE.VIDEO, 0, 500));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 500, 500));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueAvg(histograms, 'video_animation:power'),
+ 250, 0.5);
+ });
+
+ test('powerMetric_video_multipleStagesEachType', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 0,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 1000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.device.powerSeries = new tr.model.PowerSeries(model.device);
+ for (let i = 0; i <= 1000; i++) {
+ model.device.powerSeries.addPowerSample(i, i);
+ }
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, tr.model.um.INITIATOR_TYPE.VIDEO, 0, 200));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 200, 300));
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, tr.model.um.INITIATOR_TYPE.VIDEO, 500, 200));
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 700, 300));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.powerMetric(histograms, model);
+
+ assert.closeTo(getMetricValueAvg(histograms, 'video_animation:power'),
+ 350, 0.6);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/responsiveness_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/responsiveness_metric.html
new file mode 100644
index 00000000000..911c2d66d48
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/responsiveness_metric.html
@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+<link rel="import" href="/tracing/model/user_model/animation_expectation.html">
+<link rel="import" href="/tracing/model/user_model/load_expectation.html">
+<link rel="import" href="/tracing/model/user_model/response_expectation.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ // In the case of Response, Load, and DiscreteAnimation UEs, Responsiveness is
+ // derived from the time between when the user thinks they begin an interation
+ // (expectedStart) and the time when the screen first changes to reflect the
+ // interaction (actualEnd). There may be a delay between expectedStart and
+ // when chrome first starts processing the interaction (actualStart) if the
+ // main thread is busy. The user doesn't know when actualStart is, they only
+ // know when expectedStart is. User responsiveness, by definition, considers
+ // only what the user experiences, so "duration" is defined as actualEnd -
+ // expectedStart.
+
+ function computeAnimationThroughput(animationExpectation) {
+ if (animationExpectation.frameEvents === undefined ||
+ animationExpectation.frameEvents.length === 0) {
+ throw new Error('Animation missing frameEvents ' +
+ animationExpectation.stableId);
+ }
+
+ const durationInS = tr.b.convertUnit(animationExpectation.duration,
+ tr.b.UnitPrefixScale.METRIC.MILLI,
+ tr.b.UnitPrefixScale.METRIC.NONE);
+ return animationExpectation.frameEvents.length / durationInS;
+ }
+
+ function computeAnimationframeTimeDiscrepancy(animationExpectation) {
+ if (animationExpectation.frameEvents === undefined ||
+ animationExpectation.frameEvents.length === 0) {
+ throw new Error('Animation missing frameEvents ' +
+ animationExpectation.stableId);
+ }
+
+ let frameTimestamps = animationExpectation.frameEvents;
+ frameTimestamps = frameTimestamps.toArray().map(function(event) {
+ return event.start;
+ });
+
+ const absolute = true;
+ return tr.b.math.Statistics.timestampsDiscrepancy(
+ frameTimestamps, absolute);
+ }
+
+ /**
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!tr.model.Model} model
+ * @param {!Object=} opt_options
+ */
+ function responsivenessMetric(histograms, model, opt_options) {
+ const responseNumeric = new tr.v.Histogram('response latency',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ tr.v.HistogramBinBoundaries.createLinear(100, 1e3, 50));
+ const throughputNumeric = new tr.v.Histogram('animation throughput',
+ tr.b.Unit.byName.unitlessNumber_biggerIsBetter,
+ tr.v.HistogramBinBoundaries.createLinear(10, 60, 10));
+ const frameTimeDiscrepancyNumeric = new tr.v.Histogram(
+ 'animation frameTimeDiscrepancy',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ tr.v.HistogramBinBoundaries.createLinear(0, 1e3, 50).
+ addExponentialBins(1e4, 10));
+ const latencyNumeric = new tr.v.Histogram('animation latency',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ tr.v.HistogramBinBoundaries.createLinear(0, 300, 60));
+
+ model.userModel.expectations.forEach(function(ue) {
+ if (opt_options && opt_options.rangeOfInterest &&
+ !opt_options.rangeOfInterest.intersectsExplicitRangeInclusive(
+ ue.start, ue.end)) {
+ return;
+ }
+
+ const sampleDiagnosticMap = tr.v.d.DiagnosticMap.fromObject(
+ {relatedEvents: new tr.v.d.RelatedEventSet([ue])});
+
+ // Responsiveness is not defined for Idle or Startup expectations.
+ if (ue instanceof tr.model.um.IdleExpectation) {
+ return;
+ } else if (ue instanceof tr.model.um.StartupExpectation) {
+ return;
+ } else if (ue instanceof tr.model.um.LoadExpectation) {
+ // This is already covered by loadingMetric.
+ } else if (ue instanceof tr.model.um.ResponseExpectation) {
+ responseNumeric.addSample(ue.duration, sampleDiagnosticMap);
+ } else if (ue instanceof tr.model.um.AnimationExpectation) {
+ if (ue.frameEvents === undefined || ue.frameEvents.length === 0) {
+ // Ignore animation stages that do not have associated frames:
+ // https://github.com/catapult-project/catapult/issues/2446
+ return;
+ }
+ const throughput = computeAnimationThroughput(ue);
+ if (throughput === undefined) {
+ throw new Error('Missing throughput for ' +
+ ue.stableId);
+ }
+
+ throughputNumeric.addSample(throughput, sampleDiagnosticMap);
+
+ const frameTimeDiscrepancy = computeAnimationframeTimeDiscrepancy(ue);
+ if (frameTimeDiscrepancy === undefined) {
+ throw new Error('Missing frameTimeDiscrepancy for ' +
+ ue.stableId);
+ }
+
+ frameTimeDiscrepancyNumeric.addSample(
+ frameTimeDiscrepancy, sampleDiagnosticMap);
+
+ ue.associatedEvents.forEach(function(event) {
+ if (!(event instanceof tr.e.cc.InputLatencyAsyncSlice)) {
+ return;
+ }
+
+ latencyNumeric.addSample(event.duration, sampleDiagnosticMap);
+ });
+ } else {
+ throw new Error('Unrecognized stage for ' + ue.stableId);
+ }
+ });
+
+ [
+ responseNumeric, throughputNumeric, frameTimeDiscrepancyNumeric,
+ latencyNumeric
+ ].forEach(function(numeric) {
+ numeric.customizeSummaryOptions({
+ avg: true,
+ max: true,
+ min: true,
+ std: true
+ });
+ });
+
+ histograms.addHistogram(responseNumeric);
+ histograms.addHistogram(throughputNumeric);
+ histograms.addHistogram(frameTimeDiscrepancyNumeric);
+ histograms.addHistogram(latencyNumeric);
+ }
+
+ tr.metrics.MetricRegistry.register(responsivenessMetric, {
+ supportsRangeOfInterest: true,
+ requiredCategories: ['rail'],
+ });
+
+ return {
+ responsivenessMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/responsiveness_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/responsiveness_metric_test.html
new file mode 100644
index 00000000000..dbe10addd27
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/responsiveness_metric_test.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/system_health/responsiveness_metric.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createModel(collectionOfFrameTimestamps) {
+ const opts = {
+ customizeModelCallback(model) {
+ const thread = tr.c.TestUtils.newFakeThread();
+ collectionOfFrameTimestamps.forEach(function(frameTimestamps) {
+ frameTimestamps.sort((a, b) => a - b);
+ const ue = new tr.model.um.AnimationExpectation(
+ model, 'test', frameTimestamps[0],
+ frameTimestamps[frameTimestamps.length - 1]);
+ const group = new tr.model.SliceGroup(thread);
+ frameTimestamps.forEach(function(time) {
+ group.pushSlice(tr.c.TestUtils.newSliceEx({
+ title: tr.model.helpers.IMPL_RENDERING_STATS,
+ start: time,
+ end: time,
+ cpuStart: time,
+ cpuEnd: time
+ }));
+ });
+ group.createSubSlices();
+ group.slices.forEach(function(slice) {
+ ue.associatedEvents.push(slice);
+ });
+ model.userModel.expectations.push(ue);
+ model.userModel.expectations.push(
+ new tr.model.um.StartupExpectation(model, 0, 1));
+ model.userModel.expectations.push(
+ new tr.model.um.ResponseExpectation(model, 'test', 1, 1));
+ });
+ }
+ };
+ return tr.c.TestUtils.newModelWithEvents([], opts);
+ }
+
+ test('animationThroughputNoFrames', function() {
+ const model = createModel([[]]);
+ const valueList = new tr.v.HistogramSet();
+ tr.metrics.sh.responsivenessMetric(valueList, model);
+ const value = valueList.getHistogramNamed('animation throughput');
+ assert.strictEqual(value.numValues, 0);
+ });
+
+ test('animationThroughputFramesAndNoFrames', function() {
+ const model = createModel([[0, 100], []]);
+ const valueList = new tr.v.HistogramSet();
+ tr.metrics.sh.responsivenessMetric(valueList, model);
+ const value = valueList.getHistogramNamed('animation throughput');
+ assert.strictEqual(value.average, 20);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/utils.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/utils.html
new file mode 100644
index 00000000000..92bb7c71fb1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/utils.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/extras/chrome/chrome_processes.html">
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ // Returns a weight for this score.
+ // score should be a number between 0 and 1 inclusive.
+ // This function is expected to be passed to tr.b.math.Statistics.weightedMean
+ // as its weightCallback.
+ function perceptualBlend(ir, index, score) {
+ // Lower scores are exponentially more important than higher scores
+ // due to the Peak-end rule.
+ // Other than that general rule, there is no specific reasoning behind this
+ // specific formula -- it is fairly arbitrary.
+ return Math.exp(1 - score);
+ }
+
+ function filterExpectationsByRange(irs, opt_range) {
+ const filteredExpectations = [];
+ irs.forEach(function(ir) {
+ if (!(ir instanceof tr.model.um.UserExpectation)) return;
+
+ if (!opt_range ||
+ opt_range.intersectsExplicitRangeInclusive(ir.start, ir.end)) {
+ filteredExpectations.push(ir);
+ }
+ });
+ return filteredExpectations;
+ }
+
+ /**
+ * Splits the global memory dumps in |model| by browser name.
+ *
+ * @param {!tr.Model} model The trace model from which the global dumps
+ * should be extracted.
+ * @param {!tr.b.math.Range=} opt_rangeOfInterest If provided, global memory
+ * dumps that do not inclusively intersect the range will be skipped.
+ * @return {!Map<string, !Array<!tr.model.GlobalMemoryDump>} A map from
+ * browser names to the associated global memory dumps.
+ */
+ function splitGlobalDumpsByBrowserName(model, opt_rangeOfInterest) {
+ const chromeModelHelper =
+ model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ const browserNameToGlobalDumps = new Map();
+ const globalDumpToBrowserHelper = new WeakMap();
+
+ // 1. For each browser process in the model, add its global memory dumps to
+ // |browserNameToGlobalDumps|. |chromeModelHelper| can be undefined if
+ // it fails to find any browser, renderer or GPU process (see
+ // tr.model.helpers.ChromeModelHelper.supportsModel).
+
+ if (chromeModelHelper) {
+ chromeModelHelper.browserHelpers.forEach(function(helper) {
+ // Retrieve the associated global memory dumps and check that they
+ // haven't been classified as belonging to another browser process.
+ const globalDumps = skipDumpsThatDoNotIntersectRange(
+ helper.process.memoryDumps.map(d => d.globalMemoryDump),
+ opt_rangeOfInterest);
+ globalDumps.forEach(function(globalDump) {
+ const existingHelper = globalDumpToBrowserHelper.get(globalDump);
+ if (existingHelper !== undefined) {
+ throw new Error('Memory dump ID clash across multiple browsers ' +
+ 'with PIDs: ' + existingHelper.pid + ' and ' + helper.pid);
+ }
+ globalDumpToBrowserHelper.set(globalDump, helper);
+ });
+
+ makeKeyUniqueAndSet(browserNameToGlobalDumps,
+ tr.e.chrome.chrome_processes.canonicalizeName(helper.browserName),
+ globalDumps);
+ });
+ }
+
+ // 2. If any global memory dump does not have any associated browser
+ // process for some reason, associate it with an 'unknown_browser' browser
+ // so that we don't lose the data.
+
+ const unclassifiedGlobalDumps = skipDumpsThatDoNotIntersectRange(
+ model.globalMemoryDumps.filter(g => !globalDumpToBrowserHelper.has(g)),
+ opt_rangeOfInterest);
+ if (unclassifiedGlobalDumps.length > 0) {
+ makeKeyUniqueAndSet(
+ browserNameToGlobalDumps, 'unknown_browser', unclassifiedGlobalDumps);
+ }
+
+ return browserNameToGlobalDumps;
+ }
+
+ /**
+ * Function for adding entries with duplicate keys to a map without
+ * overriding existing entries.
+ *
+ * This is achieved by appending numeric indices (2, 3, 4, ...) to duplicate
+ * keys. Example:
+ *
+ * const map = new Map();
+ * // map = Map {}.
+ *
+ * makeKeyUniqueAndSet(map, 'key', 'a');
+ * // map = Map {"key" => "a"}.
+ *
+ * makeKeyUniqueAndSet(map, 'key', 'b');
+ * // map = Map {"key" => "a", "key2" => "b"}.
+ * ^^^^
+ * makeKeyUniqueAndSet(map, 'key', 'c');
+ * // map = Map {"key" => "a", "key2" => "b", "key3" => "c"}.
+ * ^^^^ ^^^^
+ */
+ function makeKeyUniqueAndSet(map, key, value) {
+ let uniqueKey = key;
+ let nextIndex = 2;
+ while (map.has(uniqueKey)) {
+ uniqueKey = key + nextIndex;
+ nextIndex++;
+ }
+ map.set(uniqueKey, value);
+ }
+
+ function skipDumpsThatDoNotIntersectRange(dumps, opt_range) {
+ if (!opt_range) return dumps;
+ return dumps.filter(d => opt_range.intersectsExplicitRangeInclusive(
+ d.start, d.end));
+ }
+
+ /**
+ * Returns true if |category| is one of the categories of |event|, and |event|
+ * has title |title|.
+ *
+ * TODO(dproy): Make this a method on a suitable parent class of the
+ * event/slice classes that are used with this function.
+ */
+ function hasCategoryAndName(event, category, title) {
+ return event.title === title && event.category &&
+ tr.b.getCategoryParts(event.category).includes(category);
+ }
+
+ return {
+ hasCategoryAndName,
+ filterExpectationsByRange,
+ perceptualBlend,
+ splitGlobalDumpsByBrowserName
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/webview_startup_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/webview_startup_metric.html
new file mode 100644
index 00000000000..f7bea627333
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/webview_startup_metric.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.sh', function() {
+ function webviewStartupMetric(histograms, model) {
+ const startupWallHist = new tr.v.Histogram('webview_startup_wall_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ startupWallHist.description = 'WebView startup wall time';
+ const startupCPUHist = new tr.v.Histogram('webview_startup_cpu_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ startupCPUHist.description = 'WebView startup CPU time';
+ const loadWallHist = new tr.v.Histogram('webview_url_load_wall_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ loadWallHist.description = 'WebView blank URL load wall time';
+ const loadCPUHist = new tr.v.Histogram('webview_url_load_cpu_time',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);
+ loadCPUHist.description = 'WebView blank URL load CPU time';
+
+ // TODO(alexandermont): Only iterate over the processes and threads that
+ // could contain these events.
+ for (const slice of model.getDescendantEvents()) {
+ if (!(slice instanceof tr.model.ThreadSlice)) continue;
+
+ // WebViewStartupInterval is the title of the section of code that is
+ // entered (via android.os.Trace.beginSection) when WebView is started
+ // up. This value is defined in TelemetryActivity.java.
+ if (slice.title === 'WebViewStartupInterval') {
+ startupWallHist.addSample(slice.duration);
+ startupCPUHist.addSample(slice.cpuDuration);
+ }
+
+ // WebViewBlankUrlLoadInterval is the title of the section of code
+ // that is entered (via android.os.Trace.beginSection) when WebView
+ // is started up. This value is defined in TelemetryActivity.java.
+ if (slice.title === 'WebViewBlankUrlLoadInterval') {
+ loadWallHist.addSample(slice.duration);
+ loadCPUHist.addSample(slice.cpuDuration);
+ }
+ }
+
+ histograms.addHistogram(startupWallHist);
+ histograms.addHistogram(startupCPUHist);
+ histograms.addHistogram(loadWallHist);
+ histograms.addHistogram(loadCPUHist);
+ }
+
+ tr.metrics.MetricRegistry.register(webviewStartupMetric);
+
+ return {
+ webviewStartupMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/system_health/webview_startup_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/webview_startup_metric_test.html
new file mode 100644
index 00000000000..9f3c15224d9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/system_health/webview_startup_metric_test.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/system_health/webview_startup_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ function makeTestModel() {
+ return tr.c.TestUtils.newModel(function(model) {
+ const mainThread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'webview',
+ title: 'WebViewStartupInterval',
+ start: 200,
+ duration: 42.0,
+ cpuStart: 150,
+ cpuDuration: 32.0
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'webview',
+ title: 'WebViewBlankUrlLoadInterval',
+ start: 250,
+ duration: 27.0,
+ cpuStart: 190,
+ cpuDuration: 17.0
+ }));
+ });
+ }
+
+ test('webviewStartupMetric', function() {
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.sh.webviewStartupMetric(histograms, makeTestModel());
+ assert.closeTo(42, histograms.getHistogramNamed(
+ 'webview_startup_wall_time').average, 1e-2);
+ assert.closeTo(32, histograms.getHistogramNamed(
+ 'webview_startup_cpu_time').average, 1e-2);
+ assert.closeTo(27, histograms.getHistogramNamed(
+ 'webview_url_load_wall_time').average, 1e-2);
+ assert.closeTo(17, histograms.getHistogramNamed(
+ 'webview_url_load_cpu_time').average, 1e-2);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/tabs_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/tabs_metric.html
new file mode 100644
index 00000000000..a4b456353c3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/tabs_metric.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.tabs', function() {
+ function tabsMetric(histograms, model, opt_options) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ if (!chromeHelper) {
+ // Chrome isn't present.
+ return;
+ }
+
+ const tabSwitchRequestDelays = [];
+ const TAB_SWITCHING_REQUEST_TITLE = 'TabSwitchVisibilityRequest';
+ // initialization, *startTabSwitchVisibilityRequest stores the
+ // first legal TabSwitchVisibilityRequest's start time.
+ let startTabSwitchVisibilityRequest = Number.MAX_SAFE_INTEGER;
+ for (const helper of chromeHelper.browserHelpers) {
+ if (!helper.mainThread) continue;
+ for (const slice of helper.mainThread.asyncSliceGroup.slices) {
+ if (slice.title === TAB_SWITCHING_REQUEST_TITLE && !slice.error) {
+ tabSwitchRequestDelays.push(slice.duration);
+ // find the first legal TabSwitchVisibilityRequest's start time
+ if (slice.start < startTabSwitchVisibilityRequest) {
+ startTabSwitchVisibilityRequest = slice.start;
+ }
+ }
+ }
+ }
+
+ histograms.createHistogram('tab_switching_request_delay',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ tabSwitchRequestDelays, {
+ description: 'Delay before tab-request is made',
+ summaryOptions: {sum: false}});
+
+ const tabSwitchLatencies = [];
+ const TAB_SWITCHING_SLICE_TITLE = 'TabSwitching::Latency';
+
+ function extractLatencyFromHelpers(helpers, legacy) {
+ for (const helper of helpers) {
+ if (!helper.mainThread) {
+ continue;
+ }
+ const thread = helper.mainThread;
+ for (const slice of thread.asyncSliceGroup.slices) {
+ if (slice.title === TAB_SWITCHING_SLICE_TITLE &&
+ (legacy || slice.args.latency) &&
+ slice.start > startTabSwitchVisibilityRequest) {
+ // push legal tabSwitchLatency which only starts after the
+ // first legal TabSwitchVisibilityRequest's start time
+ tabSwitchLatencies.push(
+ legacy ? slice.duration : slice.args.latency);
+ }
+ }
+ }
+ }
+
+ extractLatencyFromHelpers(chromeHelper.browserHelpers);
+ extractLatencyFromHelpers(Object.values(chromeHelper.rendererHelpers));
+
+ if (tabSwitchLatencies.length === 0) {
+ extractLatencyFromHelpers(chromeHelper.browserHelpers, true);
+ }
+
+ histograms.createHistogram('tab_switching_latency',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ tabSwitchLatencies, { description: 'Tab switching time in ms',
+ summaryOptions: {sum: false}});
+ }
+
+ tr.metrics.MetricRegistry.register(tabsMetric, {
+ supportsRangeOfInterest: false,
+ });
+
+ return {
+ tabsMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/tabs_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/tabs_metric_test.html
new file mode 100644
index 00000000000..a6d3f6b9606
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/tabs_metric_test.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/tabs_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('tabsMetric_tabSwitching', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserThread = setUpBrowserThread(model);
+ addTabSwitchingData(browserThread);
+
+ const rendererMainThread = setUpRendererMainThread(model);
+ addTabSwitchingData(rendererMainThread);
+
+ const group = browserThread.asyncSliceGroup;
+ group.push(tr.c.TestUtils.newAsyncSliceEx({cat: 'latency',
+ title: 'TabSwitchVisibilityRequest', start: 3, duration: 10}));
+ group.push(tr.c.TestUtils.newAsyncSliceEx({cat: 'latency',
+ title: 'TabSwitchVisibilityRequest', start: 15, duration: 6}));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.tabs.tabsMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('tab_switching_latency');
+ assert.strictEqual(hist.max, 43.0);
+ assert.strictEqual(hist.min, 24.0);
+ assert.strictEqual(hist.average, 33.0);
+ assert.strictEqual(hist.numValues, 6);
+ });
+
+ test('tabsMetric_tabSwitching_legacy', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserThread = setUpBrowserThread(model);
+ addTabSwitchingData(browserThread, true);
+
+ const group = browserThread.asyncSliceGroup;
+ group.push(tr.c.TestUtils.newAsyncSliceEx({cat: 'latency',
+ title: 'TabSwitchVisibilityRequest', start: 3, duration: 10}));
+ group.push(tr.c.TestUtils.newAsyncSliceEx({cat: 'latency',
+ title: 'TabSwitchVisibilityRequest', start: 15, duration: 6}));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.tabs.tabsMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('tab_switching_latency');
+ assert.strictEqual(hist.max, 37.0);
+ assert.strictEqual(hist.min, 14.0);
+ assert.strictEqual(hist.average, 25.0);
+ assert.strictEqual(hist.numValues, 3);
+ });
+
+ test('tabsMetric_tabSwitchRequestDelay', function() {
+ const model = tr.c.TestUtils.newModel((model) => {
+ const browserThread = setUpBrowserThread(model);
+ const group = browserThread.asyncSliceGroup;
+ group.push(tr.c.TestUtils.newAsyncSliceEx({cat: 'latency',
+ title: 'TabSwitchVisibilityRequest', start: 0, duration: 10}));
+ group.push(tr.c.TestUtils.newAsyncSliceEx({cat: 'latency',
+ title: 'TabSwitchVisibilityRequest', start: 15, duration: 6}));
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.tabs.tabsMetric(histograms, model);
+ const hist = histograms.getHistogramNamed('tab_switching_request_delay');
+ assert.strictEqual(hist.average, 8);
+ });
+
+ function setUpBrowserThread(model) {
+ const BROWSER_PROCESS_ID = 1234;
+ const browserProcess = model.getOrCreateProcess(BROWSER_PROCESS_ID);
+ const browserThread = browserProcess.getOrCreateThread(2);
+ browserThread.name = 'CrBrowserMain';
+ return browserThread;
+ }
+
+ function setUpRendererMainThread(model) {
+ const RENDERER_PROCESS_ID = 2345;
+ const rendererProcess = model.getOrCreateProcess(RENDERER_PROCESS_ID);
+ const mainThread = rendererProcess.getOrCreateThread(23);
+ mainThread.name = 'CrRendererMain';
+ return mainThread;
+ }
+
+ function addTabSwitchingData(thread, legacy) {
+ const group = thread.asyncSliceGroup;
+ group.push(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'latency',
+ title: 'TabSwitching::Latency',
+ start: 2,
+ duration: 24,
+ args: legacy ? {} : {latency: 24 },
+ }));
+ group.push(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'latency',
+ title: 'TabSwitching::Latency',
+ start: 4,
+ duration: 24,
+ args: legacy ? {} : {latency: 24 },
+ }));
+ group.push(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'latency',
+ title: 'TabSwitching::Latency',
+ start: 5,
+ duration: 14,
+ args: legacy ? {} : {latency: 32 },
+ }));
+ group.push(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'latency',
+ title: 'TabSwitching::Latency',
+ start: 6,
+ duration: 37,
+ args: legacy ? {} : {latency: 43 },
+ }));
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/tracing_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/tracing_metric.html
new file mode 100644
index 00000000000..332a2b1cd04
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/tracing_metric.html
@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics', function() {
+ const MEMORY_INFRA_TRACING_CATEGORY = 'disabled-by-default-memory-infra';
+
+ const TIME_BOUNDARIES = tr.v.HistogramBinBoundaries.createExponential(
+ 1e-3, 1e5, 30);
+
+ const BYTE_BOUNDARIES = tr.v.HistogramBinBoundaries.createExponential(
+ 1, 1e9, 30);
+
+ const COUNT_BOUNDARIES = tr.v.HistogramBinBoundaries.createExponential(
+ 1, 1e5, 30);
+
+ // By default, we store a single value, so we only need one of the
+ // statistics to keep track. We choose the average for that.
+ const SUMMARY_OPTIONS = tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;
+
+ // Adds histograms specific to memory-infra dumps.
+ function addMemoryInfraHistograms(
+ histograms, model, categoryNamesToTotalEventSizes) {
+ const memoryDumpCount = model.globalMemoryDumps.length;
+ if (memoryDumpCount === 0) return;
+
+ let totalOverhead = 0;
+ let nonMemoryInfraThreadOverhead = 0;
+ const overheadByProvider = {};
+ for (const process of Object.values(model.processes)) {
+ for (const thread of Object.values(process.threads)) {
+ for (const slice of Object.values(thread.sliceGroup.slices)) {
+ if (slice.category !== MEMORY_INFRA_TRACING_CATEGORY) continue;
+
+ totalOverhead += slice.duration;
+ if (thread.name !== 'MemoryInfra') {
+ nonMemoryInfraThreadOverhead += slice.duration;
+ }
+ if (slice.args && slice.args['dump_provider.name']) {
+ const providerName = slice.args['dump_provider.name'];
+ let durationAndCount = overheadByProvider[providerName];
+ if (durationAndCount === undefined) {
+ overheadByProvider[providerName] = durationAndCount =
+ {duration: 0, count: 0};
+ }
+ durationAndCount.duration += slice.duration;
+ durationAndCount.count++;
+ }
+ }
+ }
+ }
+
+ histograms.createHistogram('memory_dump_cpu_overhead',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ totalOverhead / memoryDumpCount, {
+ binBoundaries: TIME_BOUNDARIES,
+ description:
+ 'Average CPU overhead on all threads per memory-infra dump',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+
+ histograms.createHistogram('nonmemory_thread_memory_dump_cpu_overhead',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ nonMemoryInfraThreadOverhead / memoryDumpCount, {
+ binBoundaries: TIME_BOUNDARIES,
+ description: 'Average CPU overhead on non-memory-infra threads ' +
+ 'per memory-infra dump',
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+
+ for (const [providerName, overhead] of Object.entries(overheadByProvider)) {
+ histograms.createHistogram(`${providerName}_memory_dump_cpu_overhead`,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ overhead.duration / overhead.count, {
+ binBoundaries: TIME_BOUNDARIES,
+ description:
+ `Average CPU overhead of ${providerName} per OnMemoryDump call`,
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ }
+
+ const memoryInfraEventsSize =
+ categoryNamesToTotalEventSizes.get(MEMORY_INFRA_TRACING_CATEGORY);
+ const memoryInfraTraceBytesValue = new tr.v.Histogram(
+ 'total_memory_dump_size',
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, BYTE_BOUNDARIES);
+ memoryInfraTraceBytesValue.description =
+ 'Total trace size of memory-infra dumps in bytes';
+ memoryInfraTraceBytesValue.customizeSummaryOptions(SUMMARY_OPTIONS);
+ memoryInfraTraceBytesValue.addSample(memoryInfraEventsSize);
+ histograms.addHistogram(memoryInfraTraceBytesValue);
+
+ const traceBytesPerDumpValue = new tr.v.Histogram(
+ 'memory_dump_size',
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, BYTE_BOUNDARIES);
+ traceBytesPerDumpValue.description =
+ 'Average trace size of memory-infra dumps in bytes';
+ traceBytesPerDumpValue.customizeSummaryOptions(SUMMARY_OPTIONS);
+ traceBytesPerDumpValue.addSample(memoryInfraEventsSize / memoryDumpCount);
+ histograms.addHistogram(traceBytesPerDumpValue);
+ }
+
+ // TODO(charliea): The metrics in this file should be renamed to have names
+ // more consistent with those in the rest of the codebase
+ // (e.g. 'trace_size_growth_per_second', not 'Max event size in bytes per
+ // second').
+ // https://github.com/catapult-project/catapult/issues/3233
+ function tracingMetric(histograms, model) {
+ if (!model.stats.hasEventSizesinBytes) return;
+
+ const eventStats = model.stats.allTraceEventStatsInTimeIntervals;
+ eventStats.sort((a, b) => a.timeInterval - b.timeInterval);
+
+ const totalTraceBytes = eventStats.reduce(
+ (a, b) => a + b.totalEventSizeinBytes, 0);
+
+ // We maintain a sliding window of records [start ... end-1] where end
+ // increments each time through the loop, and we move start just far enough
+ // to keep the window less than 1 second wide. Note that we need to compute
+ // the number of time intervals (i.e. units that timeInterval is given in)
+ // in one second to know how wide the sliding window should be.
+ let maxEventCountPerSec = 0;
+ let maxEventBytesPerSec = 0;
+ const INTERVALS_PER_SEC = Math.floor(
+ 1000 / model.stats.TIME_INTERVAL_SIZE_IN_MS);
+
+ let runningEventNumPerSec = 0;
+ let runningEventBytesPerSec = 0;
+ let start = 0;
+ let end = 0;
+
+ while (end < eventStats.length) {
+ // Slide the end marker forward. Moving the end marker from N
+ // to N+1 adds eventStats[N] to the sliding window.
+ runningEventNumPerSec += eventStats[end].numEvents;
+ runningEventBytesPerSec += eventStats[end].totalEventSizeinBytes;
+ end++;
+
+ // Slide the start marker forward so that the time interval covered
+ // by the window is less than 1 second wide.
+ while ((eventStats[end - 1].timeInterval -
+ eventStats[start].timeInterval) >= INTERVALS_PER_SEC) {
+ runningEventNumPerSec -= eventStats[start].numEvents;
+ runningEventBytesPerSec -= eventStats[start].totalEventSizeinBytes;
+ start++;
+ }
+
+ // Update maximum values.
+ maxEventCountPerSec = Math.max(maxEventCountPerSec,
+ runningEventNumPerSec);
+ maxEventBytesPerSec = Math.max(maxEventBytesPerSec,
+ runningEventBytesPerSec);
+ }
+
+ const stats = model.stats.allTraceEventStats;
+ const categoryNamesToTotalEventSizes = (
+ stats.reduce((map, stat) => (
+ map.set(stat.category,
+ ((map.get(stat.category) || 0) +
+ stat.totalEventSizeinBytes))), new Map()));
+
+ // Determine the category with the highest total event size.
+ const maxCatNameAndBytes = Array.from(
+ categoryNamesToTotalEventSizes.entries()).reduce(
+ (a, b) => ((b[1] >= a[1]) ? b : a));
+ const maxEventBytesPerCategory = maxCatNameAndBytes[1];
+ const categoryWithMaxEventBytes = maxCatNameAndBytes[0];
+
+ const maxEventCountPerSecValue = new tr.v.Histogram(
+ 'peak_event_rate', tr.b.Unit.byName.count_smallerIsBetter,
+ COUNT_BOUNDARIES);
+ maxEventCountPerSecValue.description = 'Max number of events per second';
+ maxEventCountPerSecValue.customizeSummaryOptions(SUMMARY_OPTIONS);
+ maxEventCountPerSecValue.addSample(maxEventCountPerSec);
+
+ const maxEventBytesPerSecValue = new tr.v.Histogram(
+ 'peak_event_size_rate', tr.b.Unit.byName.sizeInBytes_smallerIsBetter,
+ BYTE_BOUNDARIES);
+ maxEventBytesPerSecValue.description = 'Max event size in bytes per second';
+ maxEventBytesPerSecValue.customizeSummaryOptions(SUMMARY_OPTIONS);
+ maxEventBytesPerSecValue.addSample(maxEventBytesPerSec);
+
+ const totalTraceBytesValue = new tr.v.Histogram('trace_size',
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, BYTE_BOUNDARIES);
+ totalTraceBytesValue.customizeSummaryOptions(SUMMARY_OPTIONS);
+ totalTraceBytesValue.addSample(totalTraceBytes);
+
+ const biggestCategory = {
+ name: categoryWithMaxEventBytes,
+ size_in_bytes: maxEventBytesPerCategory
+ };
+
+ totalTraceBytesValue.diagnostics.set(
+ 'category_with_max_event_size',
+ new tr.v.d.GenericSet([biggestCategory]));
+ histograms.addHistogram(totalTraceBytesValue);
+
+ maxEventCountPerSecValue.diagnostics.set(
+ 'category_with_max_event_size',
+ new tr.v.d.GenericSet([biggestCategory]));
+ histograms.addHistogram(maxEventCountPerSecValue);
+
+ maxEventBytesPerSecValue.diagnostics.set(
+ 'category_with_max_event_size',
+ new tr.v.d.GenericSet([biggestCategory]));
+ histograms.addHistogram(maxEventBytesPerSecValue);
+
+ addMemoryInfraHistograms(histograms, model, categoryNamesToTotalEventSizes);
+ }
+
+ tr.metrics.MetricRegistry.register(tracingMetric);
+
+ return {
+ tracingMetric,
+ // For testing only:
+ MEMORY_INFRA_TRACING_CATEGORY,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/tracing_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/tracing_metric_test.html
new file mode 100644
index 00000000000..5fbffe98f94
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/tracing_metric_test.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/tracing_metric.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function makeModel(events, opt_track) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ trackDetailedModelStats: opt_track
+ });
+ }
+
+ function getEventStringSize(events, indices) {
+ return indices.reduce(function(sum, index) {
+ return sum + JSON.stringify(events[index]).length;
+ }, 0);
+ }
+
+ function checkDurationHistogram(histograms, metricName, expected) {
+ const histogram = histograms.getHistogramNamed(metricName);
+ assert.closeTo(1000 * histogram.average, expected, 0.1);
+ }
+
+ test('tracingMetric_hasEventSizesInBytes', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'}
+ ];
+
+ const model = makeModel(JSON.stringify(events), true);
+ assert.isTrue(model.importOptions.trackDetailedModelStats);
+ tr.metrics.tracingMetric(histograms, model);
+ });
+
+ test('tracingMetric_totalTraceSize', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'}
+ ];
+ const model = makeModel(JSON.stringify(events), true);
+ tr.metrics.tracingMetric(histograms, model);
+
+ const eventStringSize = getEventStringSize(events, [0, 1]);
+ const histogram = histograms.getHistogramNamed('trace_size');
+ assert.strictEqual(histogram.average, eventStringSize);
+ });
+
+ test('tracingMetric_maxValuePerSec', function() {
+ const ONE_SEC_IN_US = 1000000;
+ const events = [
+ {name: 'a', pid: 52, ts: 1, cat: 'foo', ph: 'B'},
+ {name: 'a', pid: 52, ts: ONE_SEC_IN_US + 1, cat: 'foo', ph: 'B'},
+ {name: 'a', pid: 52, ts: 2 * ONE_SEC_IN_US + 1, cat: 'foo', ph: 'B'},
+ {name: 'a', pid: 52, ts: 2 * ONE_SEC_IN_US + 3, cat: 'foo', ph: 'B'},
+ {name: 'a', pid: 52, ts: ONE_SEC_IN_US + 2, cat: 'foo', ph: 'B'},
+ {name: 'a', pid: 52, ts: 2 * ONE_SEC_IN_US + 2, cat: 'foo', ph: 'B'}
+ ];
+ const model = makeModel(JSON.stringify(events), true);
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.tracingMetric(histograms, model);
+
+ const maxEventCountPerSec = 3;
+ let histogram = histograms.getHistogramNamed('peak_event_rate');
+ assert.strictEqual(histogram.average, maxEventCountPerSec);
+
+ const maxEventBytesPerSec = getEventStringSize(events, [2, 3, 5]);
+ histogram = histograms.getHistogramNamed('peak_event_size_rate');
+ assert.strictEqual(histogram.average, maxEventBytesPerSec);
+ });
+
+ test('tracingMetric_diagnostics', function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 535, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'bb', args: {}, pid: 52, ts: 546, cat: 'bar', tid: 53, ph: 'E'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'bb', args: {}, pid: 52, ts: 578, cat: 'bar', tid: 53, ph: 'E'}
+ ];
+ const model = makeModel(JSON.stringify(events), true);
+ tr.metrics.tracingMetric(histograms, model);
+
+ const DIAGNOSTIC_HISTOGRAMS = [
+ 'Max number of events per second',
+ 'Max event size in bytes per second',
+ 'Total trace size in bytes'
+ ];
+ for (const histogram of histograms) {
+ if (!DIAGNOSTIC_HISTOGRAMS.includes(histogram.name)) continue;
+
+ const d = histogram.diagnostics.get('category_with_max_event_size').value;
+ assert.strictEqual(d.name, 'foo');
+ assert.strictEqual(d.size_in_bytes, getEventStringSize(
+ events, [0, 1, 3]));
+ }
+ });
+
+ test('tracingMetric_memoryInfraTracingMetrics', function() {
+ const MEMORY_INFRA_TRACING_CATEGORY =
+ tr.metrics.MEMORY_INFRA_TRACING_CATEGORY;
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ {name: 'OnMemoryDump', pid: 1, ts: 510, tid: 1, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {'dump_provider.name': 'mdp1'}, dur: 4}, // @suppress longLineCheck
+ {name: 'OnMemoryDump', pid: 1, ts: 520, tid: 7, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {'dump_provider.name': 'mdp2'}, dur: 15}, // @suppress longLineCheck
+ {name: 'OnMemoryDump', pid: 1, ts: 530, tid: 7, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {'dump_provider.name': 'mdp3'}, dur: 5}, // @suppress longLineCheck
+ {name: 'OnMemoryDump', pid: 2, ts: 510, tid: 2, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {'dump_provider.name': 'mdp1'}, dur: 9}, // @suppress longLineCheck
+ {name: 'OnMemoryDump', pid: 2, ts: 520, tid: 8, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {'dump_provider.name': 'mdp2'}, dur: 17}, // @suppress longLineCheck
+ {name: 'OnMemoryDump', pid: 2, ts: 530, tid: 8, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {'dump_provider.name': 'mdp3'}, dur: 7}, // @suppress longLineCheck
+ {name: 'OnMemoryDump', pid: 2, ts: 540, tid: 3, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {'dump_provider.name': 'mdp4'}, dur: 8}, // @suppress longLineCheck
+ {name: 'ProcessDumps', pid: 1, ts: 550, tid: 1, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {guid: 4}, dur: 8}, // @suppress longLineCheck
+ {name: 'ProcessDumps', pid: 2, ts: 540, tid: 2, ph: 'X', cat: MEMORY_INFRA_TRACING_CATEGORY, args: {guid: 4}, dur: 18}, // @suppress longLineCheck
+ {name: 'thread_name', pid: 1, ts: 0, tid: 1, ph: 'M', cat: '__metadata', args: {name: 'CrBrowsermain'}}, // @suppress longLineCheck
+ {name: 'thread_name', pid: 1, ts: 0, tid: 7, ph: 'M', cat: '__metadata', args: {name: 'MemoryInfra'}}, // @suppress longLineCheck
+ {name: 'thread_name', pid: 2, ts: 0, tid: 2, ph: 'M', cat: '__metadata', args: {name: 'CrRendererMain'}}, // @suppress longLineCheck
+ {name: 'thread_name', pid: 2, ts: 0, tid: 8, ph: 'M', cat: '__metadata', args: {name: 'MemoryInfra'}}, // @suppress longLineCheck
+ {name: 'thread_name', pid: 2, ts: 0, tid: 3, ph: 'M', cat: '__metadata', args: {name: 'Compositor'}} // @suppress longLineCheck
+ ];
+
+ const model = makeModel(JSON.stringify(events), true);
+ tr.model.MemoryDumpTestUtils.addGlobalMemoryDump(model, {ts: 550});
+ tr.metrics.tracingMetric(histograms, model);
+
+ const memoryCategorySize = events.filter(
+ slice => slice.cat === MEMORY_INFRA_TRACING_CATEGORY).reduce(
+ (acc, slice) => acc + JSON.stringify(slice).length, 0);
+ const totalSizeHistogram = histograms.getHistogramNamed(
+ 'total_memory_dump_size');
+ assert.strictEqual(totalSizeHistogram.average, memoryCategorySize);
+ const sizePerDumpHistogram = histograms.getHistogramNamed(
+ 'memory_dump_size');
+ assert.strictEqual(sizePerDumpHistogram.average, memoryCategorySize);
+
+ checkDurationHistogram(histograms, 'mdp1_memory_dump_cpu_overhead', 6.5);
+ checkDurationHistogram(histograms, 'mdp2_memory_dump_cpu_overhead', 16);
+ checkDurationHistogram(histograms, 'mdp3_memory_dump_cpu_overhead', 6);
+ checkDurationHistogram(histograms, 'mdp4_memory_dump_cpu_overhead', 8);
+ checkDurationHistogram(
+ histograms, 'nonmemory_thread_memory_dump_cpu_overhead', 47);
+ checkDurationHistogram(histograms, 'memory_dump_cpu_overhead', 91);
+ });
+
+ test('tracingMetric_traceImportDurationMetricWithoutTrackDetailedModelStats',
+ function() {
+ const histograms = new tr.v.HistogramSet();
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 524, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'}
+ ];
+
+ const model = makeModel(JSON.stringify(events), false);
+ assert.isFalse(model.importOptions.trackDetailedModelStats);
+ tr.metrics.tracingMetric(histograms, model);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/execution_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/execution_metric.html
new file mode 100644
index 00000000000..87992515679
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/execution_metric.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.v8', function() {
+ const CUSTOM_BOUNDARIES = tr.v.HistogramBinBoundaries.createLinear(
+ 4, 200, 100);
+
+ function computeExecuteMetrics(histograms, model) {
+ const cpuTotalExecution = new tr.v.Histogram('v8_execution_cpu_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuTotalExecution.description = 'cpu total time spent in script execution';
+ const wallTotalExecution = new tr.v.Histogram('v8_execution_wall_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallTotalExecution.description =
+ 'wall total time spent in script execution';
+ const cpuSelfExecution = new tr.v.Histogram('v8_execution_cpu_self',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuSelfExecution.description = 'cpu self time spent in script execution';
+ const wallSelfExecution = new tr.v.Histogram('v8_execution_wall_self',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallSelfExecution.description = 'wall self time spent in script execution';
+
+ for (const e of model.findTopmostSlicesNamed('V8.Execute')) {
+ cpuTotalExecution.addSample(e.cpuDuration);
+ wallTotalExecution.addSample(e.duration);
+ cpuSelfExecution.addSample(e.cpuSelfTime);
+ wallSelfExecution.addSample(e.selfTime);
+ }
+
+ histograms.addHistogram(cpuTotalExecution);
+ histograms.addHistogram(wallTotalExecution);
+ histograms.addHistogram(cpuSelfExecution);
+ histograms.addHistogram(wallSelfExecution);
+ }
+
+ function computeParseLazyMetrics(histograms, model) {
+ const cpuSelfParseLazy = new tr.v.Histogram('v8_parse_lazy_cpu_self',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuSelfParseLazy.description =
+ 'cpu self time spent performing lazy parsing';
+ const wallSelfParseLazy = new tr.v.Histogram('v8_parse_lazy_wall_self',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallSelfParseLazy.description =
+ 'wall self time spent performing lazy parsing';
+
+ for (const e of model.findTopmostSlicesNamed('V8.ParseLazyMicroSeconds')) {
+ cpuSelfParseLazy.addSample(e.cpuSelfTime);
+ wallSelfParseLazy.addSample(e.selfTime);
+ }
+ for (const e of model.findTopmostSlicesNamed('V8.ParseLazy')) {
+ cpuSelfParseLazy.addSample(e.cpuSelfTime);
+ wallSelfParseLazy.addSample(e.selfTime);
+ }
+
+ histograms.addHistogram(cpuSelfParseLazy);
+ histograms.addHistogram(wallSelfParseLazy);
+ }
+
+ function computeCompileFullCodeMetrics(histograms, model) {
+ const cpuSelfCompileFullCode = new tr.v.Histogram(
+ 'v8_compile_full_code_cpu_self',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuSelfCompileFullCode.description =
+ 'cpu self time spent performing compiling full code';
+ const wallSelfCompileFullCode = new tr.v.Histogram(
+ 'v8_compile_full_code_wall_self',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallSelfCompileFullCode.description =
+ 'wall self time spent performing compiling full code';
+
+ for (const e of model.findTopmostSlicesNamed('V8.CompileFullCode')) {
+ cpuSelfCompileFullCode.addSample(e.cpuSelfTime);
+ wallSelfCompileFullCode.addSample(e.selfTime);
+ }
+
+ histograms.addHistogram(cpuSelfCompileFullCode);
+ histograms.addHistogram(wallSelfCompileFullCode);
+ }
+
+ function computeCompileIgnitionMetrics(histograms, model) {
+ const cpuSelfCompileIgnition = new tr.v.Histogram(
+ 'v8_compile_ignition_cpu_self',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuSelfCompileIgnition.description =
+ 'cpu self time spent in compile ignition';
+ const wallSelfCompileIgnition = new tr.v.Histogram(
+ 'v8_compile_ignition_wall_self',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallSelfCompileIgnition.description =
+ 'wall self time spent in compile ignition';
+
+ for (const e of model.findTopmostSlicesNamed('V8.CompileIgnition')) {
+ cpuSelfCompileIgnition.addSample(e.cpuSelfTime);
+ wallSelfCompileIgnition.addSample(e.selfTime);
+ }
+
+ histograms.addHistogram(cpuSelfCompileIgnition);
+ histograms.addHistogram(wallSelfCompileIgnition);
+ }
+
+ function computeRecompileMetrics(histograms, model) {
+ const cpuTotalRecompileSynchronous = new tr.v.Histogram(
+ 'v8_recompile_synchronous_cpu_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuTotalRecompileSynchronous.description =
+ 'cpu total time spent in synchronous recompilation';
+ const wallTotalRecompileSynchronous = new tr.v.Histogram(
+ 'v8_recompile_synchronous_wall_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallTotalRecompileSynchronous.description =
+ 'wall total time spent in synchronous recompilation';
+ const cpuTotalRecompileConcurrent = new tr.v.Histogram(
+ 'v8_recompile_concurrent_cpu_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuTotalRecompileConcurrent.description =
+ 'cpu total time spent in concurrent recompilation';
+ const wallTotalRecompileConcurrent = new tr.v.Histogram(
+ 'v8_recompile_concurrent_wall_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallTotalRecompileConcurrent.description =
+ 'wall total time spent in concurrent recompilation';
+ // TODO(eakuefner): Stop computing overall histograms once dash v2 is ready.
+ // https://github.com/catapult-project/catapult/issues/2180
+ const cpuTotalRecompileOverall = new tr.v.Histogram(
+ 'v8_recompile_overall_cpu_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuTotalRecompileOverall.description =
+ 'cpu total time spent in synchronous or concurrent recompilation';
+ const wallTotalRecompileOverall = new tr.v.Histogram(
+ 'v8_recompile_overall_wall_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallTotalRecompileOverall.description =
+ 'wall total time spent in synchronous or concurrent recompilation';
+
+ for (const e of model.findTopmostSlicesNamed('V8.RecompileSynchronous')) {
+ cpuTotalRecompileSynchronous.addSample(e.cpuDuration);
+ wallTotalRecompileSynchronous.addSample(e.duration);
+ cpuTotalRecompileOverall.addSample(e.cpuDuration);
+ wallTotalRecompileOverall.addSample(e.duration);
+ }
+
+ histograms.addHistogram(cpuTotalRecompileSynchronous);
+ histograms.addHistogram(wallTotalRecompileSynchronous);
+
+ for (const e of model.findTopmostSlicesNamed('V8.RecompileConcurrent')) {
+ cpuTotalRecompileConcurrent.addSample(e.cpuDuration);
+ wallTotalRecompileConcurrent.addSample(e.duration);
+ cpuTotalRecompileOverall.addSample(e.cpuDuration);
+ wallTotalRecompileOverall.addSample(e.duration);
+ }
+
+ histograms.addHistogram(cpuTotalRecompileConcurrent);
+ histograms.addHistogram(wallTotalRecompileConcurrent);
+ histograms.addHistogram(cpuTotalRecompileOverall);
+ histograms.addHistogram(wallTotalRecompileOverall);
+ }
+
+ function computeOptimizeCodeMetrics(histograms, model) {
+ const cpuTotalOptimizeCode = new tr.v.Histogram(
+ 'v8_optimize_code_cpu_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuTotalOptimizeCode.description =
+ 'cpu total time spent in code optimization';
+ const wallTotalOptimizeCode = new tr.v.Histogram(
+ 'v8_optimize_code_wall_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallTotalOptimizeCode.description =
+ 'wall total time spent in code optimization';
+
+ for (const e of model.findTopmostSlicesNamed('V8.OptimizeCode')) {
+ cpuTotalOptimizeCode.addSample(e.cpuDuration);
+ wallTotalOptimizeCode.addSample(e.duration);
+ }
+
+ histograms.addHistogram(cpuTotalOptimizeCode);
+ histograms.addHistogram(wallTotalOptimizeCode);
+ }
+
+ function computeDeoptimizeCodeMetrics(histograms, model) {
+ const cpuTotalDeoptimizeCode = new tr.v.Histogram(
+ 'v8_deoptimize_code_cpu_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ cpuTotalDeoptimizeCode.description =
+ 'cpu total time spent in code deoptimization';
+ const wallTotalDeoptimizeCode = new tr.v.Histogram(
+ 'v8_deoptimize_code_wall_total',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ wallTotalDeoptimizeCode.description =
+ 'wall total time spent in code deoptimization';
+
+ for (const e of model.findTopmostSlicesNamed('V8.DeoptimizeCode')) {
+ cpuTotalDeoptimizeCode.addSample(e.cpuDuration);
+ wallTotalDeoptimizeCode.addSample(e.duration);
+ }
+
+ histograms.addHistogram(cpuTotalDeoptimizeCode);
+ histograms.addHistogram(wallTotalDeoptimizeCode);
+ }
+
+ function executionMetric(histograms, model) {
+ computeExecuteMetrics(histograms, model);
+ computeParseLazyMetrics(histograms, model);
+ computeCompileIgnitionMetrics(histograms, model);
+ computeCompileFullCodeMetrics(histograms, model);
+ computeRecompileMetrics(histograms, model);
+ computeOptimizeCodeMetrics(histograms, model);
+ computeDeoptimizeCodeMetrics(histograms, model);
+ }
+
+ tr.metrics.MetricRegistry.register(executionMetric);
+
+ return {
+ executionMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/execution_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/execution_metric_test.html
new file mode 100644
index 00000000000..d42c5476706
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/execution_metric_test.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/v8/execution_metric.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('executionMetricBasic', function() {
+ const model = tr.c.TestUtils.newModel();
+ const histograms = new tr.v.HistogramSet();
+
+ tr.metrics.v8.executionMetric(histograms, model);
+
+ [
+ 'v8_execution_cpu_total',
+ 'v8_execution_wall_total',
+ 'v8_execution_cpu_self',
+ 'v8_execution_wall_self',
+ 'v8_parse_lazy_cpu_self',
+ 'v8_parse_lazy_wall_self',
+ 'v8_compile_full_code_cpu_self',
+ 'v8_compile_full_code_wall_self',
+ 'v8_compile_ignition_cpu_self',
+ 'v8_compile_ignition_wall_self',
+ 'v8_recompile_synchronous_cpu_total',
+ 'v8_recompile_synchronous_wall_total',
+ 'v8_recompile_concurrent_cpu_total',
+ 'v8_recompile_concurrent_wall_total',
+ 'v8_recompile_overall_cpu_total',
+ 'v8_recompile_overall_wall_total',
+ 'v8_optimize_code_cpu_total',
+ 'v8_optimize_code_wall_total',
+ 'v8_deoptimize_code_cpu_total',
+ 'v8_deoptimize_code_wall_total',
+ ].forEach(function(name) {
+ assert.isDefined(histograms.getHistogramNamed(name));
+ });
+ });
+
+ test('noDoubleCounting', function() {
+ const events = [
+ {name: 'V8.Execute', args: {}, pid: 52, ts: 0, cat: 'foo', tid: 53,
+ ph: 'B'},
+ {name: 'V8.Execute', args: {}, pid: 52, ts: 100, cat: 'foo', tid: 53,
+ ph: 'E'},
+ {name: 'V8.Execute', args: {}, pid: 52, ts: 20, cat: 'foo', tid: 53,
+ ph: 'B'},
+ {name: 'V8.Execute', args: {}, pid: 52, ts: 40, cat: 'foo', tid: 53,
+ ph: 'E'}
+ ];
+
+ const model = tr.c.TestUtils.newModelWithEvents(JSON.stringify(events), {
+ shiftWorldToZero: false
+ });
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.v8.executionMetric(histograms, model);
+
+ const value = histograms.getHistogramNamed('v8_execution_wall_total');
+ assert.closeTo(value.running.sum, 0.1, 1e-5);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html
new file mode 100644
index 00000000000..c3d90cc2786
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric.html
@@ -0,0 +1,297 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/v8/utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/diagnostics/breakdown.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.v8', function() {
+ // The time window size for mutator utilization computation.
+ // It is equal to the duration of one frame corresponding to 60 FPS rendering.
+ const TARGET_FPS = 60;
+ const MS_PER_SECOND = 1000;
+ const WINDOW_SIZE_MS = MS_PER_SECOND / TARGET_FPS;
+
+ function gcMetric(histograms, model) {
+ addDurationOfTopEvents(histograms, model);
+ addTotalDurationOfTopEvents(histograms, model);
+ addDurationOfSubEvents(histograms, model);
+ addPercentageInV8ExecuteOfTopEvents(histograms, model);
+ addTotalPercentageInV8Execute(histograms, model);
+ addMarkCompactorMutatorUtilization(histograms, model);
+ addTotalMarkCompactorTime(histograms, model);
+ addTotalMarkCompactorMarkingTime(histograms, model);
+ }
+
+ tr.metrics.MetricRegistry.register(gcMetric);
+
+ const timeDurationInMs_smallerIsBetter =
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;
+ const percentage_biggerIsBetter =
+ tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;
+ const percentage_smallerIsBetter =
+ tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;
+
+ // 0.1 steps from 0 to 20 since it is the most common range.
+ // Exponentially increasing steps from 20 to 200.
+ const CUSTOM_BOUNDARIES = tr.v.HistogramBinBoundaries.createLinear(0, 20, 200)
+ .addExponentialBins(200, 100);
+
+ function createNumericForTopEventTime(name) {
+ const n = new tr.v.Histogram(name,
+ timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ n.customizeSummaryOptions({
+ avg: true,
+ count: true,
+ max: true,
+ min: false,
+ std: true,
+ sum: true,
+ percentile: [0.90]});
+ return n;
+ }
+
+ function createNumericForSubEventTime(name) {
+ const n = new tr.v.Histogram(name,
+ timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ n.customizeSummaryOptions({
+ avg: true,
+ count: false,
+ max: true,
+ min: false,
+ std: false,
+ sum: false,
+ percentile: [0.90]
+ });
+ return n;
+ }
+
+ function createNumericForIdleTime(name) {
+ const n = new tr.v.Histogram(name,
+ timeDurationInMs_smallerIsBetter, CUSTOM_BOUNDARIES);
+ n.customizeSummaryOptions({
+ avg: true,
+ count: false,
+ max: true,
+ min: false,
+ std: false,
+ sum: true,
+ percentile: []
+ });
+ return n;
+ }
+
+ function createPercentage(name, numerator, denominator, unit) {
+ const hist = new tr.v.Histogram(name, unit);
+ if (denominator === 0) {
+ hist.addSample(0);
+ } else {
+ hist.addSample(numerator / denominator);
+ }
+ hist.customizeSummaryOptions({
+ avg: true,
+ count: false,
+ max: false,
+ min: false,
+ std: false,
+ sum: false,
+ percentile: []
+ });
+ return hist;
+ }
+
+ /**
+ * Example output:
+ * - v8-gc-full-mark-compactor.
+ */
+ function addDurationOfTopEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,
+ tr.metrics.v8.utils.topGarbageCollectionEventName,
+ function(name, events) {
+ const cpuDuration = createNumericForTopEventTime(name);
+ events.forEach(function(event) {
+ cpuDuration.addSample(event.cpuDuration);
+ });
+ histograms.addHistogram(cpuDuration);
+ }
+ );
+ }
+
+ /**
+ * Example output:
+ * - v8-gc-total
+ */
+ function addTotalDurationOfTopEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,
+ event => 'v8-gc-total',
+ function(name, events) {
+ const cpuDuration = createNumericForTopEventTime(name);
+ events.forEach(function(event) {
+ cpuDuration.addSample(event.cpuDuration);
+ });
+ histograms.addHistogram(cpuDuration);
+ }
+ );
+ }
+
+ function isV8MarkCompactorSummary(event) {
+ return !tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event) &&
+ tr.metrics.v8.utils.isMarkCompactorSummaryEvent(event);
+ }
+
+ function isV8MarkCompactorMarkingSummary(event) {
+ return !tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event) &&
+ tr.metrics.v8.utils.isMarkCompactorMarkingSummaryEvent(event);
+ }
+
+ function createHistogramFromSummary(histograms, name, events) {
+ const foregroundDuration =
+ createNumericForTopEventTime(name + '-foreground');
+ const backgroundDuration =
+ createNumericForTopEventTime(name + '-background');
+ const totalDuration =
+ createNumericForTopEventTime(name + '-total');
+ const relatedNames = new tr.v.d.RelatedNameMap();
+ relatedNames.set('foreground', foregroundDuration.name);
+ relatedNames.set('background', backgroundDuration.name);
+ for (const event of events) {
+ foregroundDuration.addSample(event.args.duration);
+ backgroundDuration.addSample(event.args.background_duration);
+ const breakdownForTotal = new tr.v.d.Breakdown();
+ breakdownForTotal.set('foreground', event.args.duration);
+ breakdownForTotal.set('background', event.args.background_duration);
+ totalDuration.addSample(
+ event.args.duration + event.args.background_duration,
+ {breakdown: breakdownForTotal});
+ }
+ histograms.addHistogram(foregroundDuration);
+ histograms.addHistogram(backgroundDuration);
+ histograms.addHistogram(totalDuration, {breakdown: relatedNames});
+ }
+
+ /**
+ * Example output:
+ * - v8-gc-mark-compactor-foreground
+ * - v8-gc-mark-compactor-background
+ * - v8-gc-mark-compactor-total
+ */
+ function addTotalMarkCompactorTime(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ isV8MarkCompactorSummary,
+ event => 'v8-gc-mark-compactor',
+ (name, events) => createHistogramFromSummary(histograms, name, events)
+ );
+ }
+
+ /**
+ * Example output:
+ * - v8-gc-mark-compactor-marking-foreground
+ * - v8-gc-mark-compactor-marking-background
+ * - v8-gc-mark-compactor-marking-total
+ */
+ function addTotalMarkCompactorMarkingTime(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ isV8MarkCompactorMarkingSummary,
+ event => 'v8-gc-mark-compactor-marking',
+ (name, events) => createHistogramFromSummary(histograms, name, events)
+ );
+ }
+
+ /**
+ * Example output:
+ * - v8-gc-full-mark-compactor-evacuate.
+ */
+ function addDurationOfSubEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ tr.metrics.v8.utils.isNotForcedSubGarbageCollectionEvent,
+ tr.metrics.v8.utils.subGarbageCollectionEventName,
+ function(name, events) {
+ const cpuDuration = createNumericForSubEventTime(name);
+ events.forEach(function(event) {
+ cpuDuration.addSample(event.cpuDuration);
+ });
+ histograms.addHistogram(cpuDuration);
+ }
+ );
+ }
+
+ /**
+ * Example output:
+ * - v8-gc-full-mark-compactor_percentage_in_v8_execute.
+ */
+ function addPercentageInV8ExecuteOfTopEvents(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,
+ tr.metrics.v8.utils.topGarbageCollectionEventName,
+ function(name, events) {
+ addPercentageInV8Execute(histograms, model, name, events);
+ }
+ );
+ }
+
+ /**
+ * Example output:
+ * - v8-gc-total_percentage_in_v8_execute.
+ */
+ function addTotalPercentageInV8Execute(histograms, model) {
+ tr.metrics.v8.utils.groupAndProcessEvents(model,
+ tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,
+ event => 'v8-gc-total',
+ function(name, events) {
+ addPercentageInV8Execute(histograms, model, name, events);
+ }
+ );
+ }
+
+ function addPercentageInV8Execute(histograms, model, name, events) {
+ let cpuDurationInV8Execute = 0;
+ let cpuDurationTotal = 0;
+ events.forEach(function(event) {
+ const v8Execute = tr.metrics.v8.utils.findParent(
+ event, tr.metrics.v8.utils.isV8ExecuteEvent);
+ if (v8Execute) {
+ cpuDurationInV8Execute += event.cpuDuration;
+ }
+ cpuDurationTotal += event.cpuDuration;
+ });
+ const percentage = createPercentage(
+ name + '_percentage_in_v8_execute', cpuDurationInV8Execute,
+ cpuDurationTotal, percentage_smallerIsBetter);
+ histograms.addHistogram(percentage);
+ }
+
+ /**
+ * Example output:
+ * - v8-gc-mark-compactor-mmu-100ms_window.
+ */
+ function addMarkCompactorMutatorUtilization(histograms, model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ const rendererHelpers = Object.values(chromeHelper.rendererHelpers);
+ tr.metrics.v8.utils.addMutatorUtilization(
+ 'v8-gc-mark-compactor-mmu',
+ tr.metrics.v8.utils.isNotForcedMarkCompactorEvent,
+ [100],
+ rendererHelpers,
+ histograms);
+ }
+
+ return {
+ gcMetric,
+ WINDOW_SIZE_MS, // For testing purposes only.
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html
new file mode 100644
index 00000000000..8c38b563e62
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/gc_metric_test.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/v8/gc_metric.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createModel(start, end, slices) {
+ return tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ const group = mainThread.sliceGroup;
+ for (const slice of slices) {
+ group.pushSlice(tr.c.TestUtils.newSliceEx(slice));
+ }
+ group.createSubSlices();
+ mainThread.updateBounds();
+ });
+ }
+
+ function constructName(name, suffix) {
+ return name + '_' + suffix;
+ }
+
+ function run(slices) {
+ const histograms = new tr.v.HistogramSet();
+ const startTime = slices.reduce(
+ (acc, slice) => (Math.min(acc, slice.start)));
+ const endTime = slices.reduce((acc, slice) => (Math.max(acc, slice.end)));
+ const model = createModel(startTime - 1, endTime + 1, slices);
+ tr.metrics.v8.gcMetric(histograms, model);
+ return histograms;
+ }
+
+ test('topEvents', function() {
+ const events = {
+ 'V8.GCCompactor': 'v8-gc-full-mark-compactor',
+ 'V8.GCFinalizeMC': 'v8-gc-latency-mark-compactor',
+ 'V8.GCFinalizeMCReduceMemory': 'v8-gc-memory-mark-compactor',
+ 'V8.GCIncrementalMarking': 'v8-gc-incremental-step',
+ 'V8.GCIncrementalMarkingFinalize': 'v8-gc-incremental-finalize',
+ 'V8.GCIncrementalMarkingStart': 'v8-gc-incremental-start',
+ 'V8.GCPhantomHandleProcessingCallback': 'v8-gc-phantom-handle-callback',
+ 'V8.GCScavenger': 'v8-gc-scavenger'
+ };
+ for (const [timelineName, telemetryName] of Object.entries(events)) {
+ const slices = [
+ {
+ title: timelineName, args: {}, start: 100, end: 200,
+ cpuStart: 100, cpuEnd: 200
+ }
+ ];
+ const actual = run(slices);
+
+ const value = actual.getHistogramNamed(telemetryName);
+ assert.strictEqual(value.running.sum, 100);
+ assert.strictEqual(value.numValues, 1);
+ assert.strictEqual(value.average, 100);
+ assert.strictEqual(value.running.max, 100);
+ assert.closeTo(value.getApproximatePercentile(0.90), 100, 1);
+ }
+ });
+
+ test('subEvents', function() {
+ const slices = [
+ {
+ title: 'V8.GCFinalizeMC', args: {}, start: 100, end: 200,
+ cpuStart: 100, cpuEnd: 200
+ },
+ {
+ title: 'V8.GC_MC_MARK', args: {}, start: 110, end: 190,
+ cpuStart: 110, cpuEnd: 190
+ },
+ ];
+ const actual = run(slices);
+ const telemetryName = 'v8-gc-latency-mark-compactor-mark';
+ const value = actual.getHistogramNamed(telemetryName);
+ assert.strictEqual(value.average, 80);
+ assert.strictEqual(value.running.max, 80);
+ assert.closeTo(value.getApproximatePercentile(0.90), 80, 1);
+ });
+
+ test('total', function() {
+ const slices = [
+ {
+ title: 'V8.GCFinalizeMC', args: {}, start: 100, end: 200,
+ cpuStart: 100, cpuEnd: 200
+ },
+ {
+ title: 'V8.GCIncrementalMarking', args: {}, start: 210, end: 290,
+ cpuStart: 210, cpuEnd: 290
+ }
+ ];
+ const actual = run(slices);
+
+ const value = actual.getHistogramNamed('v8-gc-total');
+ assert.strictEqual(value.running.sum, 180);
+ assert.strictEqual(value.numValues, 2);
+ assert.strictEqual(value.average, 90);
+ assert.strictEqual(value.running.max, 100);
+ });
+
+ test('percentageInV8Execute', function() {
+ const slices = [
+ {
+ title: 'V8.Execute',
+ args: {}, start: 100, end: 200,
+ cpuStart: 100, cpuEnd: 200
+ },
+ {
+ title: 'V8.GCFinalizeMC', args: {}, start: 110, end: 190,
+ cpuStart: 110, cpuEnd: 190
+ },
+ {
+ title: 'V8.GCFinalizeMC', args: {}, start: 210, end: 220,
+ cpuStart: 210, cpuEnd: 220
+ }
+ ];
+ const actual = run(slices);
+ const value = actual.getHistogramNamed(
+ 'v8-gc-latency-mark-compactor_percentage_in_v8_execute');
+ assert.strictEqual(value.average,
+ (190 - 110) / ((190 - 110) + (220 - 210)));
+ });
+
+ test('markCompactorMutatorUtilization', function() {
+ const slices = [
+ {
+ title: 'V8.GCIncrementalMarkingStart',
+ args: {}, start: 100, end: 110,
+ cpuStart: 100, cpuEnd: 110
+ },
+ {
+ title: 'V8.GCIncrementalMarking',
+ args: {}, start: 150, end: 160,
+ cpuStart: 150, cpuEnd: 160
+ },
+ {
+ title: 'V8.GCIncrementalMarkingFinalize',
+ args: {}, start: 200, end: 220,
+ cpuStart: 200, cpuEnd: 220
+ },
+ {
+ title: 'V8.GCFinalizeMC',
+ args: {}, start: 250, end: 300,
+ cpuStart: 250, cpuEnd: 300
+ }
+ ];
+ const histograms = run(slices);
+ const mmu = histograms.getHistogramNamed(
+ 'v8-gc-mark-compactor-mmu-100ms_window');
+ assert.closeTo(0.3, mmu.min, 1e-3);
+ assert.strictEqual(mmu.summaryOptions.get('min'), true);
+ assert.strictEqual(mmu.summaryOptions.get('max'), false);
+ });
+
+ test('markCompactorSummary', function() {
+ const slices = [
+ {
+ title: 'V8.GCMarkCompactorSummary',
+ args: {'duration': 3.1, 'background_duration': 1.3},
+ start: 100, end: 100,
+ cpuStart: 100, cpuEnd: 100
+ },
+ ];
+ const histograms = run(slices);
+ const markCompactorForeground = histograms.getHistogramNamed(
+ 'v8-gc-mark-compactor-foreground');
+ assert.closeTo(3.1, markCompactorForeground.sum, 1e-3);
+ const markCompactorBackground = histograms.getHistogramNamed(
+ 'v8-gc-mark-compactor-background');
+ assert.closeTo(1.3, markCompactorBackground.sum, 1e-3);
+ const markCompactorTotal = histograms.getHistogramNamed(
+ 'v8-gc-mark-compactor-total');
+ assert.closeTo(4.4, markCompactorTotal.sum, 1e-3);
+ });
+
+ test('markCompactorMarkingSummary', function() {
+ const slices = [
+ {
+ title: 'V8.GCMarkCompactorMarkingSummary',
+ args: {'duration': 4.1, 'background_duration': 1.4},
+ start: 100, end: 100,
+ cpuStart: 100, cpuEnd: 100
+ },
+ ];
+ const histograms = run(slices);
+ const markCompactorForeground = histograms.getHistogramNamed(
+ 'v8-gc-mark-compactor-marking-foreground');
+ assert.closeTo(4.1, markCompactorForeground.sum, 1e-3);
+ const markCompactorBackground = histograms.getHistogramNamed(
+ 'v8-gc-mark-compactor-marking-background');
+ assert.closeTo(1.4, markCompactorBackground.sum, 1e-3);
+ const markCompactorTotal = histograms.getHistogramNamed(
+ 'v8-gc-mark-compactor-marking-total');
+ assert.closeTo(5.5, markCompactorTotal.sum, 1e-3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/runtime_stats_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/runtime_stats_metric.html
new file mode 100644
index 00000000000..286cbaa32f1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/runtime_stats_metric.html
@@ -0,0 +1,374 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/extras/chrome/event_finder_utils.html">
+<link rel="import" href="/tracing/extras/v8/runtime_stats_entry.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/diagnostics/related_name_map.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.v8', function() {
+ const COUNT_CUSTOM_BOUNDARIES = tr.v.HistogramBinBoundaries
+ .createExponential(1, 1000000, 50);
+ const DURATION_CUSTOM_BOUNDARIES = tr.v.HistogramBinBoundaries
+ .createExponential(0.1, 10000, 50);
+ const SUMMARY_OPTIONS = {
+ std: false,
+ count: false,
+ sum: false,
+ min: false,
+ max: false,
+ };
+
+ function computeDomContentLoadedTime_(model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ let domContentLoadedTime = 0;
+
+ for (const rendererHelper of Object.values(chromeHelper.rendererHelpers)) {
+ for (const ev of rendererHelper.mainThread.sliceGroup.childEvents()) {
+ if (ev.title === 'domContentLoadedEventEnd' &&
+ ev.start > domContentLoadedTime) {
+ domContentLoadedTime = ev.start;
+ }
+ }
+ }
+ return domContentLoadedTime;
+ }
+
+ function computeInteractiveTime_(model) {
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ let interactiveTime = 0;
+ for (const expectation of model.userModel.expectations) {
+ if (tr.e.chrome.CHROME_INTERNAL_URLS.includes(
+ expectation.url)) {
+ continue;
+ }
+ if (!(expectation instanceof tr.model.um.LoadExpectation)) continue;
+ if (expectation.timeToInteractive === undefined) continue;
+ // TODO(fmeawad): Support multiple navigations.
+ if (interactiveTime !== 0) throw new Error('Too many navigations');
+ interactiveTime = expectation.timeToInteractive;
+ }
+ return interactiveTime;
+ }
+
+ function convertMicroToMilli_(time) {
+ return tr.b.convertUnit(time,
+ tr.b.UnitPrefixScale.METRIC.MICRO, tr.b.UnitPrefixScale.METRIC.MILLI);
+ }
+
+ // TODO(crbug.com/688342): Remove this function when runtimeStatsMetric is
+ // removed.
+ function computeRuntimeStats(histograms, slices) {
+ const runtimeGroupCollection = new tr.e.v8.RuntimeStatsGroupCollection();
+ runtimeGroupCollection.addSlices(slices);
+
+ function addHistogramsForRuntimeGroup(runtimeGroup, optRelatedNameMaps) {
+ histograms.createHistogram(
+ `${runtimeGroup.name}:duration`,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, {
+ value: convertMicroToMilli_(runtimeGroup.time),
+ diagnostics: optRelatedNameMaps ?
+ {samples: optRelatedNameMaps.durationBreakdown} : {}
+ }, {
+ binBoundaries: DURATION_CUSTOM_BOUNDARIES,
+ summaryOptions: SUMMARY_OPTIONS,
+ diagnostics: optRelatedNameMaps ?
+ {samples: optRelatedNameMaps.durationNames} : {}
+ });
+
+ histograms.createHistogram(
+ `${runtimeGroup.name}:count`,
+ tr.b.Unit.byName.count_smallerIsBetter, {
+ value: runtimeGroup.count,
+ diagnostics: optRelatedNameMaps ?
+ {samples: optRelatedNameMaps.countBreakdown} : {}
+ }, {
+ binBoundaries: COUNT_CUSTOM_BOUNDARIES,
+ summaryOptions: SUMMARY_OPTIONS,
+ diagnostics: optRelatedNameMaps ?
+ {samples: optRelatedNameMaps.countNames} : {}
+ });
+ }
+
+ function addDetailedHistogramsForRuntimeGroup(runtimeGroup) {
+ const durationNames = new tr.v.d.RelatedNameMap();
+ const durationBreakdown = new tr.v.d.Breakdown();
+ const countNames = new tr.v.d.RelatedNameMap();
+ const countBreakdown = new tr.v.d.Breakdown();
+
+ for (const entry of runtimeGroup.values) {
+ const durationSampleHistogram = histograms.createHistogram(
+ `${entry.name}:duration`,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ convertMicroToMilli_(entry.time), {
+ binBoundaries: DURATION_CUSTOM_BOUNDARIES,
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ durationNames.set(entry.name, durationSampleHistogram.name);
+ durationBreakdown.set(entry.name, convertMicroToMilli_(entry.time));
+
+ const countSampleHistogram = histograms.createHistogram(
+ `${entry.name}:count`,
+ tr.b.Unit.byName.count_smallerIsBetter,
+ entry.count, {
+ binBoundaries: COUNT_CUSTOM_BOUNDARIES,
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ countNames.set(entry.name, countSampleHistogram.name);
+ countBreakdown.set(entry.name, entry.count);
+ }
+
+ addHistogramsForRuntimeGroup(runtimeGroup, {
+ durationNames,
+ durationBreakdown,
+ countNames,
+ countBreakdown
+ });
+ }
+
+ for (const runtimeGroup of runtimeGroupCollection.runtimeGroups) {
+ addHistogramsForRuntimeGroup(runtimeGroup);
+ }
+
+ const blinkGroupCollection = runtimeGroupCollection.blinkRCSGroupCollection;
+ if (blinkGroupCollection.totalTime > 0) {
+ blinkGroupCollection.runtimeGroups.forEach(
+ addDetailedHistogramsForRuntimeGroup);
+ }
+ }
+
+ // TODO(crbug.com/688342): Remove this metric and use runtimeStatsTotalMetric
+ // instead when the runtimeStatsTotalMetric is stable.
+ function runtimeStatsMetric(histograms, model) {
+ const interactiveTime = computeInteractiveTime_(model);
+ const domContentLoadedTime = computeDomContentLoadedTime_(model);
+ const endTime = Math.max(interactiveTime, domContentLoadedTime);
+ const slices = [...model.getDescendantEvents()].filter(event =>
+ event instanceof tr.e.v8.V8ThreadSlice && event.start <= endTime);
+ computeRuntimeStats(histograms, slices);
+ }
+
+ function addDurationHistogram(railStageName, runtimeGroupName, sampleValue,
+ histograms, durationNamesByGroupName) {
+ const histName = `${railStageName}_${runtimeGroupName}:duration`;
+ histograms.createHistogram(
+ histName,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ convertMicroToMilli_(sampleValue), {
+ binBoundaries: DURATION_CUSTOM_BOUNDARIES,
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ let relatedNames = durationNamesByGroupName.get(runtimeGroupName);
+ if (!relatedNames) {
+ relatedNames = new tr.v.d.RelatedNameMap();
+ durationNamesByGroupName.set(runtimeGroupName, relatedNames);
+ }
+ relatedNames.set(railStageName, histName);
+ }
+
+ function addCountHistogram(railStageName, runtimeGroupName, sampleValue,
+ histograms, countNamesByGroupName) {
+ const histName = `${railStageName}_${runtimeGroupName}:count`;
+ histograms.createHistogram(
+ histName,
+ tr.b.Unit.byName.count_smallerIsBetter, sampleValue, {
+ binBoundaries: COUNT_CUSTOM_BOUNDARIES,
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ let relatedNames = countNamesByGroupName.get(runtimeGroupName);
+ if (!relatedNames) {
+ relatedNames = new tr.v.d.RelatedNameMap();
+ countNamesByGroupName.set(runtimeGroupName, relatedNames);
+ }
+ relatedNames.set(railStageName, histName);
+ }
+
+ function addTotalDurationHistogram(histogramName, time, histograms,
+ relatedNames) {
+ const value = convertMicroToMilli_(time);
+ const breakdown = new tr.v.d.Breakdown();
+ if (relatedNames) {
+ for (const [cat, histName] of relatedNames) {
+ breakdown.set(cat, histograms.getHistogramNamed(histName).average);
+ }
+ }
+ histograms.createHistogram(
+ `${histogramName}:duration`,
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ {value, diagnostics: {'RAIL stages': breakdown}}, {
+ binBoundaries: DURATION_CUSTOM_BOUNDARIES,
+ summaryOptions: SUMMARY_OPTIONS,
+ diagnostics: {'RAIL stages': relatedNames},
+ });
+ }
+
+ function addTotalCountHistogram(histogramName, value, histograms,
+ relatedNames) {
+ const breakdown = new tr.v.d.Breakdown();
+ if (relatedNames) {
+ for (const [cat, histName] of relatedNames) {
+ breakdown.set(cat, histograms.getHistogramNamed(histName).average);
+ }
+ }
+ histograms.createHistogram(
+ `${histogramName}:count`,
+ tr.b.Unit.byName.count_smallerIsBetter,
+ {value, diagnostics: {'RAIL stages': breakdown}}, {
+ binBoundaries: COUNT_CUSTOM_BOUNDARIES,
+ summaryOptions: SUMMARY_OPTIONS,
+ diagnostics: {'RAIL stages': relatedNames},
+ });
+ }
+
+ function computeRuntimeStatsBucketOnUE(histograms, slices,
+ v8SlicesBucketOnUEMap) {
+ const durationNamesByGroupName = new Map();
+ const countNamesByGroupName = new Map();
+
+ // Compute runtimeStats in each of the UE buckets. Also record the
+ // histograms in RelatedNameMap. These histograms are added to the
+ // corresponding histograms in the total bucket as a diagnostic. This keeps
+ // the data grouped.
+ for (const [name, slicesUE] of v8SlicesBucketOnUEMap) {
+ const runtimeGroupCollection = new tr.e.v8.RuntimeStatsGroupCollection();
+ runtimeGroupCollection.addSlices(slicesUE);
+
+ let overallV8Time = runtimeGroupCollection.totalTime;
+ let overallV8Count = runtimeGroupCollection.totalCount;
+ for (const runtimeGroup of runtimeGroupCollection.runtimeGroups) {
+ addDurationHistogram(name, runtimeGroup.name, runtimeGroup.time,
+ histograms, durationNamesByGroupName);
+ if (runtimeGroup.name === 'Blink C++') {
+ overallV8Time -= runtimeGroup.time;
+ }
+
+ addCountHistogram(name, runtimeGroup.name, runtimeGroup.count,
+ histograms, countNamesByGroupName);
+ if (runtimeGroup.name === 'Blink C++') {
+ overallV8Count -= runtimeGroup.count;
+ }
+ }
+
+ if (runtimeGroupCollection.blinkRCSGroupCollection.totalTime > 0) {
+ const blinkRCSGroupCollection =
+ runtimeGroupCollection.blinkRCSGroupCollection;
+ for (const group of blinkRCSGroupCollection.runtimeGroups) {
+ addDurationHistogram(name, group.name, group.time, histograms,
+ durationNamesByGroupName);
+ addCountHistogram(name, group.name, group.count, histograms,
+ countNamesByGroupName);
+ }
+ }
+
+ // Add V8 only time that is Total - Blink C++ duration.
+ addDurationHistogram(name, 'V8-Only', overallV8Time, histograms,
+ durationNamesByGroupName);
+ addCountHistogram(name, 'V8-Only', overallV8Count, histograms,
+ countNamesByGroupName);
+ }
+
+ // Add the runtimeStats for all the samples. Please note, the values in
+ // the UE buckets may not add upto the values computed here. Since UEs
+ // can overlap, we count some of the samples in multiple UE buckets.
+ const runtimeGroupCollection = new tr.e.v8.RuntimeStatsGroupCollection();
+ runtimeGroupCollection.addSlices(slices);
+
+ let overallV8Time = runtimeGroupCollection.totalTime;
+ let overallV8Count = runtimeGroupCollection.totalCount;
+ for (const runtimeGroup of runtimeGroupCollection.runtimeGroups) {
+ addTotalDurationHistogram(runtimeGroup.name, runtimeGroup.time,
+ histograms, durationNamesByGroupName.get(runtimeGroup.name));
+ if (runtimeGroup.name === 'Blink C++') {
+ overallV8Time -= runtimeGroup.time;
+ }
+
+ addTotalCountHistogram(runtimeGroup.name, runtimeGroup.count, histograms,
+ countNamesByGroupName.get(runtimeGroup.name));
+ if (runtimeGroup.name === 'Blink C++') {
+ overallV8Count -= runtimeGroup.count;
+ }
+ }
+
+ if (runtimeGroupCollection.blinkRCSGroupCollection.totalTime > 0) {
+ const blinkRCSGroupCollection =
+ runtimeGroupCollection.blinkRCSGroupCollection;
+ for (const group of blinkRCSGroupCollection.runtimeGroups) {
+ addTotalDurationHistogram(group.name, group.time, histograms,
+ durationNamesByGroupName.get(group.name));
+ addTotalCountHistogram(group.name, group.count, histograms,
+ countNamesByGroupName.get(group.name));
+ }
+ }
+
+ // Add V8 only time that is Total - Blink C++ duration.
+ addTotalDurationHistogram('V8-Only', overallV8Time, histograms,
+ durationNamesByGroupName.get('V8-Only'));
+ addTotalCountHistogram('V8-Only', overallV8Count, histograms,
+ countNamesByGroupName.get('V8-Only'));
+ }
+
+ function runtimeStatsTotalMetric(histograms, model) {
+ const v8ThreadSlices = [...model.getDescendantEvents()].filter(event =>
+ event instanceof tr.e.v8.V8ThreadSlice).sort((e1, e2) =>
+ e1.start - e2.start);
+ const v8SlicesBucketOnUEMap = new Map();
+ // User expectations can sometime overlap. So, certain v8 slices can be
+ // included in more than one expectation. We count such slices in each
+ // of the expectations. This is done so as to minimize the noise due to
+ // the differences in the extent of overlap between the runs.
+ for (const expectation of model.userModel.expectations) {
+ if (tr.e.chrome.CHROME_INTERNAL_URLS.includes(
+ expectation.url)) {
+ continue;
+ }
+ const slices = expectation.range.filterArray(v8ThreadSlices,
+ event => event.start);
+ if (slices.length === 0) continue;
+ // filterArray filters the array that intersects the range inclusively.
+ // Expectations are not inclusive i.e. expectations are like [0, 1),
+ // [1, 2). v8ThreadSlices that start at 1 should be counted only in [1,2)
+ // bucket. Filter out sample at the boundary so that they are not counted
+ // twice.
+ const lastSlice = slices[slices.length - 1];
+ if (!expectation.range.intersectsRangeExclusive(lastSlice.range)) {
+ slices.pop();
+ }
+
+ if (v8SlicesBucketOnUEMap.get(expectation.stageTitle) === undefined) {
+ v8SlicesBucketOnUEMap.set(expectation.stageTitle, slices);
+ } else {
+ const totalSlices = v8SlicesBucketOnUEMap.get(expectation.stageTitle)
+ .concat(slices);
+ v8SlicesBucketOnUEMap.set(expectation.stageTitle, totalSlices);
+ }
+ }
+
+ // Compute runtimeStats in each of the UE buckets and also compute
+ // runtimeStats on all of the samples. The values in UE buckets do not add
+ // up to the total of all samples, since we duplicate some of the samples in
+ // multiple buckets when the UEs overlap.
+ computeRuntimeStatsBucketOnUE(histograms, v8ThreadSlices,
+ v8SlicesBucketOnUEMap);
+ }
+
+ tr.metrics.MetricRegistry.register(runtimeStatsTotalMetric);
+ tr.metrics.MetricRegistry.register(runtimeStatsMetric);
+
+ return {
+ runtimeStatsMetric,
+ runtimeStatsTotalMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/runtime_stats_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/runtime_stats_metric_test.html
new file mode 100644
index 00000000000..91bc8b7a10e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/runtime_stats_metric_test.html
@@ -0,0 +1,718 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import"
+ href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
+<link rel="import" href="/tracing/metrics/v8/runtime_stats_metric.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function checkRuntimeHistogram_(histograms, name, count, duration,
+ breakdownHistograms) {
+ const countHistogram = histograms.getHistogramNamed(`${name}:count`);
+ assert.strictEqual(tr.b.getOnlyElement(countHistogram.sampleValues), count);
+ const durationHistogram = histograms.getHistogramNamed(`${name}:duration`);
+ assert.strictEqual(
+ tr.b.getOnlyElement(durationHistogram.sampleValues), duration);
+
+ if (breakdownHistograms === undefined) return;
+ const countBin = tr.b.getOnlyElement(countHistogram.allBins.filter(
+ bin => bin.diagnosticMaps.length > 0));
+ const durationBin = tr.b.getOnlyElement(durationHistogram.allBins.filter(
+ bin => bin.diagnosticMaps.length > 0));
+ for (const name of breakdownHistograms) {
+ assert.notEqual(tr.b.getOnlyElement(countBin.diagnosticMaps)
+ .get('samples').get(name + ':count'), undefined);
+ assert.notEqual(tr.b.getOnlyElement(durationBin.diagnosticMaps)
+ .get('samples').get(name + ':duration'), undefined);
+ }
+ }
+
+ test('runtimeStatsMetricUsingTTI', function() {
+ // The renderer thread timeline looks like:
+ //
+ // * [V8.NewInstance] * [BlinkRuntimeCallStats,V8.Execute] * ...[V8.Ignored]
+ // | | |
+ // | | |
+ // v v v
+ // First navigation FMP TTI
+ // 200 9200 15400
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ model.rendererMain.asyncSliceGroup.push(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'ResourceLoad',
+ start: 200,
+ duration: 5.0
+ }));
+ rendererProcess.objects.addSnapshot('ptr', 'loading', 'FrameLoader', 300,
+ {isLoadingMainFrame: true, frame: {id_ref: '0xdeadbeef'},
+ documentLoaderURL: 'http://example.com'});
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 9200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 10000,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.newInstance',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 12555,
+ duration: 990,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99]
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 9180,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'loading',
+ title: 'firstMeaningfulPaintCandidate',
+ start: 9200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 9200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 9350,
+ duration: 100,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 11150,
+ duration: 100,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 12550,
+ duration: 1000,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-v8.runtime_stats',
+ title: 'runtime-call-stats',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 13550,
+ duration: 1000,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [15, 60],
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 13555,
+ duration: 990,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ StoreIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99],
+ ParseBackgroundFunctionLiteral: [2, 22],
+ CompileBackgroundIgnition: [3, 33]
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 14950,
+ duration: 500,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'toplevel',
+ title: tr.e.chrome.SCHEDULER_TOP_LEVEL_TASK_TITLE,
+ start: 22150,
+ duration: 10,
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Ignored',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 30000,
+ duration: 1000,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99],
+ ParseBackgroundFunctionLiteral: [2, 22],
+ CompileBackgroundIgnition: [3, 33]
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'disabled-by-default-v8.runtime_stats',
+ title: 'V8.Ignored',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 30000,
+ duration: 1000,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [15, 60],
+ }
+ }
+ }));
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.v8.runtimeStatsMetric(histograms, model);
+ assert.strictEqual(histograms.length, 54);
+ assert.strictEqual(histograms.sourceHistograms.length, 52);
+
+ // A few of the top level ones.
+ checkRuntimeHistogram_(histograms, 'IC', 8, 0.088);
+ checkRuntimeHistogram_(histograms, 'API', 18, 0.198);
+ checkRuntimeHistogram_(histograms, 'Compile', 6, 0.066);
+ checkRuntimeHistogram_(histograms, 'Total', 95, 1.045);
+ // Lower level one for Blink.
+ checkRuntimeHistogram_(histograms, 'Blink_UpdateLayout', 15, 0.06);
+ });
+
+ test('runtimeStatsMetricUsingDomContentLoaded', function() {
+ // The renderer thread timeline looks like:
+ //
+ // * [V8.NewInstance] * [ V8.Execute ] * [V8.Ignored]
+ // | | |
+ // | | |
+ // v v v
+ // First navigation DCL DCL
+ // 200 1300 2400
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const rendererProcess = model.rendererProcess;
+ const mainThread = model.rendererMain;
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.newInstance',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 300,
+ duration: 990,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99]
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 1300,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 1400,
+ duration: 990,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ StoreIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99]
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'domContentLoadedEventEnd',
+ start: 2400,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Ignored',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 2450,
+ duration: 1000,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99]
+ }
+ }
+ }));
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.v8.runtimeStatsMetric(histograms, model);
+ assert.strictEqual(histograms.length, 38);
+ assert.strictEqual(histograms.sourceHistograms.length, 38);
+
+ // A few of the top level ones.
+ checkRuntimeHistogram_(histograms, 'IC', 8, 0.088);
+ checkRuntimeHistogram_(histograms, 'API', 18, 0.198);
+ checkRuntimeHistogram_(histograms, 'Compile', 6, 0.066);
+ checkRuntimeHistogram_(histograms, 'Total', 90, 0.99);
+ });
+
+ test('runtimeStatsMetricBucketOnUE', function() {
+ // Test that v8 statistics are properly bucketed when UEs overlap.
+ // The renderer thread timeline looks like:
+ //
+ // * * [ V8 ] * [ V8 ] * [ V8 ] * [ V8 ] * [ V8 ] *
+ // | | | | | | |
+ // | | | | | | |
+ // v v v v v v v
+ // First LoadStart LoadEnd AnimStart RespEnd AnimEnd IdleEnd
+ // nav RespStart IdleStart
+ // 200 300 1000 2000 2100 3000 3500
+
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const rendererProcess = model.getOrCreateProcess(1984);
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ // Add User expectations.
+ model.userModel.expectations.push(new tr.model.um.LoadExpectation(
+ model, tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL, 0, 1000));
+
+ model.userModel.expectations.push(new tr.model.um.ResponseExpectation(
+ model, tr.model.um.INITIATOR_TYPE.SCROLL, 1000, 1100));
+
+ model.userModel.expectations.push(new tr.model.um.AnimationExpectation(
+ model, tr.model.um.INITIATOR_TYPE.VIDEO, 2000, 1000));
+
+ model.userModel.expectations.push(new tr.model.um.IdleExpectation(
+ model, 3000, 500));
+
+ // Add V8 ThreadSlices corresponding to Load UE.
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.newInstance',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 300,
+ duration: 600,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 10],
+ HandleApiCall: [2, 11],
+ CompileFullCode: [3, 12],
+ LoadIC_Miss: [4, 13],
+ ParseLazy: [5, 14],
+ OptimizeCode: [6, 15],
+ FunctionCallback: [7, 16],
+ AllocateInTargetSpace: [8, 17],
+ API_Object_Get: [9, 18]
+ }
+ }
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'disabled-by-default-v8.runtime_stats',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 350,
+ duration: 400,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [30, 150],
+ Blink_Style_UpdateStyle: [20, 100],
+ }
+ }
+ }));
+
+ // Add V8 Thread slices corresponding to Response UE
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 1000,
+ duration: 800,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99]
+ }
+ }
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'disabled-by-default-v8.runtime_stats',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 1100,
+ duration: 600,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [10, 300],
+ Blink_Style_UpdateStyle: [15, 200],
+ }
+ }
+ }));
+
+ // V8 slices in the overlap range of animation + response
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 2000,
+ duration: 99,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 1],
+ HandleApiCall: [2, 2],
+ CompileFunctionLiteral: [3, 7],
+ LoadIC_Miss: [4, 4],
+ ParseLazy: [5, 5],
+ OptimizeCode: [6, 6],
+ FunctionCallback: [7, 7],
+ AllocateInTargetSpace: [8, 8],
+ API_Object_Get: [9, 9]
+ }
+ }
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'disabled-by-default-v8.runtime_stats',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 2010,
+ duration: 79,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [1, 10],
+ Blink_Style_UpdateStyle: [1, 10],
+ }
+ }
+ }));
+
+ // V8 slices in animation UE range.
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 2200,
+ duration: 700,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 1],
+ HandleApiCall: [2, 2],
+ CompileFullCode: [3, 3],
+ StoreIC_Miss: [4, 4],
+ ParseLazy: [5, 5],
+ OptimizeCode: [6, 6],
+ FunctionCallback: [7, 7],
+ AllocateInTargetSpace: [8, 8],
+ API_Object_Get: [9, 9]
+ }
+ }
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'disabled-by-default-v8.runtime_stats',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 2300,
+ duration: 600,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [20, 200],
+ Blink_Style_UpdateStyle: [15, 150],
+ }
+ }
+ }));
+
+ // Add V8 slices corresponding to Idle UE.
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 3001,
+ duration: 499,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseLazy: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Object_Get: [9, 99]
+ }
+ }
+ }));
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'disabled-by-default-v8.runtime_stats',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 3100,
+ duration: 300,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [1, 10],
+ Blink_Style_UpdateStyle: [10, 100],
+ }
+ }
+ }));
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.v8.runtimeStatsTotalMetric(histograms, model);
+ assert.strictEqual(histograms.length, 270);
+
+ // Check total:
+ checkRuntimeHistogram_(histograms, 'IC', 20, 0.109);
+ checkRuntimeHistogram_(histograms, 'API', 45, 0.234);
+ checkRuntimeHistogram_(histograms, 'Total', 225, 1.21);
+ checkRuntimeHistogram_(histograms, 'Blink C++', 35, 0.184);
+ checkRuntimeHistogram_(histograms, 'V8-Only', 190, 1.026);
+ checkRuntimeHistogram_(histograms, 'Blink_Layout', 62, 0.67);
+
+ // Check Load bucket:
+ checkRuntimeHistogram_(histograms, 'Load_Parse', 5, 0.014);
+ checkRuntimeHistogram_(histograms, 'Load_JavaScript', 1, 0.01);
+ checkRuntimeHistogram_(histograms, 'Load_Blink C++', 7, 0.016);
+ checkRuntimeHistogram_(histograms, 'Load_V8-Only', 38, 0.11);
+ checkRuntimeHistogram_(histograms, 'Load_Blink_Style', 20, 0.1);
+
+ // Check Response bucket:
+ checkRuntimeHistogram_(histograms, 'Response_Parse', 10, 0.06);
+ checkRuntimeHistogram_(histograms, 'Response_Compile', 6, 0.04);
+ checkRuntimeHistogram_(histograms, 'Response_Blink_Layout', 11, 0.31);
+
+ // Check Animation bucket:
+ checkRuntimeHistogram_(histograms, 'Animation_Parse', 10, 0.01);
+ checkRuntimeHistogram_(histograms, 'Animation_Blink_Style', 16, 0.16);
+
+ // Check Idle bucket:
+ checkRuntimeHistogram_(histograms, 'Idle_Parse', 5, 0.055);
+ checkRuntimeHistogram_(histograms, 'Idle_Blink_Parsing', 0, 0);
+ });
+
+ test('runtimeStatsMetricTotalNoUE', function() {
+ // Test that total v8 count works even without UE.
+ // The renderer thread timeline looks like:
+ //
+ // * [V8.NewInstance] * [ V8.Execute ] *
+ // |
+ // v
+ // First navigation
+ // 200
+
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const rendererProcess = model.getOrCreateProcess(1984);
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'CrRendererMain';
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'blink.user_timing',
+ title: 'navigationStart',
+ start: 200,
+ duration: 0.0,
+ args: {frame: '0xdeadbeef'}
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.newInstance',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 300,
+ duration: 600,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 10],
+ HandleApiCall: [2, 11],
+ CompileFullCode: [3, 12],
+ StoreIC_Miss: [4, 13],
+ ParseLazy: [5, 14],
+ OptimizeCode: [6, 15],
+ FunctionCallback: [7, 16],
+ AllocateInTargetSpace: [8, 17],
+ API_Object_Get: [9, 18]
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'disabled-by-default-v8.runtime_stats',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 350,
+ duration: 400,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [5, 100],
+ Blink_Style_UpdateStyle: [2, 50],
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'V8.Execute',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 1100,
+ duration: 800,
+ args: {
+ 'runtime-call-stats': {
+ JS_Execution: [1, 11],
+ HandleApiCall: [2, 22],
+ CompileFullCode: [3, 33],
+ LoadIC_Miss: [4, 44],
+ ParseFunctionLiteral: [5, 55],
+ OptimizeCode: [6, 66],
+ FunctionCallback: [7, 77],
+ AllocateInTargetSpace: [8, 88],
+ API_Context_New: [9, 99]
+ }
+ }
+ }));
+
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'v8',
+ title: 'disabled-by-default-v8.runtime_stats',
+ type: tr.e.v8.V8ThreadSlice,
+ start: 1200,
+ duration: 500,
+ args: {
+ 'runtime-call-stats': {
+ Blink_Layout_UpdateLayout: [10, 200],
+ Blink_Style_UpdateStyle: [10, 100],
+ }
+ }
+ }));
+ });
+
+ const histograms = new tr.v.HistogramSet();
+ tr.metrics.v8.runtimeStatsTotalMetric(histograms, model);
+ assert.strictEqual(histograms.length, 54);
+
+ // Check total:
+ checkRuntimeHistogram_(histograms, 'IC', 8, 0.057);
+ checkRuntimeHistogram_(histograms, 'API', 18, 0.117);
+ checkRuntimeHistogram_(histograms, 'Parse', 10, 0.069);
+ checkRuntimeHistogram_(histograms, 'Total', 90, 0.621);
+ checkRuntimeHistogram_(histograms, 'Blink C++', 14, 0.093);
+ checkRuntimeHistogram_(histograms, 'V8-Only', 76, 0.528);
+ checkRuntimeHistogram_(histograms, 'Blink_Layout', 15, 0.3);
+ checkRuntimeHistogram_(histograms, 'Blink_Style', 12, 0.15);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html
new file mode 100644
index 00000000000..b9ec7ed80bd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils.html
@@ -0,0 +1,490 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/category_util.html">
+<link rel="import" href="/tracing/base/math/piecewise_linear_function.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.v8.utils', function() {
+ // The title of the idle task event.
+ const IDLE_TASK_EVENT = 'SingleThreadIdleTaskRunner::RunTask';
+
+ // V8 execution event.
+ const V8_EXECUTE = 'V8.Execute';
+
+ // GC events start with this prefix.
+ const GC_EVENT_PREFIX = 'V8.GC';
+
+ // Special handling is required for full GCs inside low memory notification.
+ const FULL_GC_EVENT = 'V8.GCCompactor';
+
+ const LOW_MEMORY_EVENT = 'V8.GCLowMemoryNotification';
+
+ const MAJOR_GC_EVENT = 'MajorGC';
+ const MINOR_GC_EVENT = 'MinorGC';
+
+ // Maps the top-level GC events in timeline to telemetry friendly names.
+ const TOP_GC_EVENTS = {
+ 'V8.GCCompactor': 'v8-gc-full-mark-compactor',
+ 'V8.GCFinalizeMC': 'v8-gc-latency-mark-compactor',
+ 'V8.GCFinalizeMCReduceMemory': 'v8-gc-memory-mark-compactor',
+ 'V8.GCIncrementalMarking': 'v8-gc-incremental-step',
+ 'V8.GCIncrementalMarkingFinalize': 'v8-gc-incremental-finalize',
+ 'V8.GCIncrementalMarkingStart': 'v8-gc-incremental-start',
+ 'V8.GCPhantomHandleProcessingCallback': 'v8-gc-phantom-handle-callback',
+ 'V8.GCScavenger': 'v8-gc-scavenger'
+ };
+
+ const MARK_COMPACTOR_EVENTS = new Set([
+ 'V8.GCCompactor',
+ 'V8.GCFinalizeMC',
+ 'V8.GCFinalizeMCReduceMemory',
+ 'V8.GCIncrementalMarking',
+ 'V8.GCIncrementalMarkingFinalize',
+ 'V8.GCIncrementalMarkingStart',
+ 'V8.GCPhantomHandleProcessingCallback'
+ ]);
+
+ const LOW_MEMORY_MARK_COMPACTOR = 'v8-gc-low-memory-mark-compactor';
+
+ /**
+ * Finds the first parent of the |event| for which the |predicate| holds.
+ */
+ function findParent(event, predicate) {
+ let parent = event.parentSlice;
+ while (parent) {
+ if (predicate(parent)) {
+ return parent;
+ }
+ parent = parent.parentSlice;
+ }
+ return null;
+ }
+
+ function isIdleTask(event) {
+ return event.title === IDLE_TASK_EVENT;
+ }
+
+ function isLowMemoryEvent(event) {
+ return event.title === LOW_MEMORY_EVENT;
+ }
+
+ function isV8Event(event) {
+ return event.title.startsWith('V8.');
+ }
+
+ function isV8ExecuteEvent(event) {
+ return event.title === V8_EXECUTE;
+ }
+
+ function isTopV8ExecuteEvent(event) {
+ return isV8ExecuteEvent(event) && findParent(isV8ExecuteEvent) === null;
+ }
+
+ function isGarbageCollectionEvent(event) {
+ // Low memory notification is handled specially because it contains
+ // several full mark compact events.
+ return event.title && event.title.startsWith(GC_EVENT_PREFIX) &&
+ event.title !== LOW_MEMORY_EVENT;
+ }
+
+ function isTopGarbageCollectionEvent(event) {
+ return event.title in TOP_GC_EVENTS;
+ }
+
+ function isForcedGarbageCollectionEvent(event) {
+ return findParent(event, isLowMemoryEvent) !== null;
+ }
+
+ function isSubGarbageCollectionEvent(event) {
+ // To reduce number of results, we return only the first level of GC
+ // subevents. Some subevents are nested in MajorGC or MinorGC events, so
+ // we have to check for it explicitly.
+ return isGarbageCollectionEvent(event) &&
+ event.parentSlice &&
+ (isTopGarbageCollectionEvent(event.parentSlice) ||
+ event.parentSlice.title === MAJOR_GC_EVENT ||
+ event.parentSlice.title === MINOR_GC_EVENT);
+ }
+
+ function isNotForcedTopGarbageCollectionEvent(event) {
+ // We exclude garbage collection events forced by benchmark runner,
+ // because they cannot happen in real world.
+ return tr.metrics.v8.utils.isTopGarbageCollectionEvent(event) &&
+ !tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);
+ }
+
+ function isNotForcedSubGarbageCollectionEvent(event) {
+ // We exclude garbage collection events forced by benchmark runner,
+ // because they cannot happen in real world.
+ return tr.metrics.v8.utils.isSubGarbageCollectionEvent(event) &&
+ !tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);
+ }
+
+ function isFullMarkCompactorEvent(event) {
+ return event.title === 'V8.GCCompactor';
+ }
+
+ function isMarkCompactorSummaryEvent(event) {
+ return event.title === 'V8.GCMarkCompactorSummary';
+ }
+
+ function isMarkCompactorMarkingSummaryEvent(event) {
+ return event.title === 'V8.GCMarkCompactorMarkingSummary';
+ }
+
+ function isIncrementalMarkingEvent(event) {
+ return event.title.startsWith('V8.GCIncrementalMarking');
+ }
+
+ function isLatencyMarkCompactorEvent(event) {
+ return event.title === 'V8.GCFinalizeMC';
+ }
+
+ function isMemoryMarkCompactorEvent(event) {
+ return event.title === 'V8.GCFinalizeMCReduceMemory';
+ }
+
+ function isScavengerEvent(event) {
+ return event.title === 'V8.GCScavenger';
+ }
+
+ function isCompileOptimizeRCSCategory(name) {
+ return name === 'Optimize';
+ }
+
+ function isCompileUnoptimizeRCSCategory(name) {
+ return name === 'Compile';
+ }
+
+ function isCompileParseRCSCategory(name) {
+ return name === 'Parse';
+ }
+
+ function isCompileRCSCategory(name) {
+ return name === 'Compile' || name === 'Optimize' || name === 'Parse';
+ }
+
+ function isV8RCSEvent(event) {
+ return event instanceof tr.e.v8.V8ThreadSlice;
+ }
+
+ function isMarkCompactorEvent(event) {
+ return MARK_COMPACTOR_EVENTS.has(event.title);
+ }
+
+ function isNotForcedMarkCompactorEvent(event) {
+ return !isForcedGarbageCollectionEvent(event) &&
+ isMarkCompactorEvent(event);
+ }
+
+ function forcedGCEventName() {
+ return LOW_MEMORY_EVENT;
+ }
+
+ function topGarbageCollectionEventName(event) {
+ if (event.title === FULL_GC_EVENT) {
+ // Full mark compact events inside a low memory notification
+ // are counted as low memory mark compacts.
+ if (findParent(event, isLowMemoryEvent)) {
+ return LOW_MEMORY_MARK_COMPACTOR;
+ }
+ }
+ return TOP_GC_EVENTS[event.title];
+ }
+
+ function subGarbageCollectionEventName(event) {
+ const topEvent = findParent(event, isTopGarbageCollectionEvent);
+ const prefix = topEvent ? topGarbageCollectionEventName(topEvent) :
+ 'unknown';
+ // Remove redundant prefixes and convert to lower case.
+ const name = event.title.replace('V8.GC_MC_', '')
+ .replace('V8.GC_SCAVENGER_', '')
+ .replace('V8.GC_', '')
+ .replace(/_/g, '-').toLowerCase();
+ return prefix + '-' + name;
+ }
+
+ /**
+ * Filters events using the |filterCallback|, then groups events by the user
+ * the name computed using the |nameCallback|, and then invokes
+ * the |processCallback| with the grouped events.
+ * @param {Function} filterCallback Takes an event and returns a boolean.
+ * @param {Function} nameCallback Takes event and returns a string.
+ * @param {Function} processCallback Takes a name, and an array of events.
+ */
+ function groupAndProcessEvents(model, filterCallback,
+ nameCallback, processCallback) {
+ // Map: name -> [events].
+ const nameToEvents = {};
+ for (const event of model.getDescendantEvents()) {
+ if (!filterCallback(event)) continue;
+ const name = nameCallback(event);
+ nameToEvents[name] = nameToEvents[name] || [];
+ nameToEvents[name].push(event);
+ }
+ for (const [name, events] of Object.entries(nameToEvents)) {
+ processCallback(name, events);
+ }
+ }
+
+ /**
+ * Given a list of intervals, returns a new list with all overalapping
+ * intervals merged into a single interval.
+ */
+ function unionOfIntervals(intervals) {
+ if (intervals.length === 0) return [];
+ return tr.b.math.mergeRanges(
+ intervals.map(x => { return { min: x.start, max: x.end }; }), 1e-6,
+ function(ranges) {
+ return {
+ start: ranges.reduce(
+ (acc, x) => Math.min(acc, x.min), ranges[0].min),
+ end: ranges.reduce((acc, x) => Math.max(acc, x.max), ranges[0].max)
+ };
+ }
+ );
+ }
+
+ function hasV8Stats(globalMemoryDump) {
+ let v8stats = undefined;
+ globalMemoryDump.iterateContainerDumps(function(dump) {
+ v8stats = v8stats || dump.getMemoryAllocatorDumpByFullName('v8');
+ });
+ return !!v8stats;
+ }
+
+ function rangeForMemoryDumps(model) {
+ const startOfFirstDumpWithV8 =
+ model.globalMemoryDumps.filter(hasV8Stats).reduce(
+ (start, dump) => Math.min(start, dump.start), Infinity);
+ // Empty range.
+ if (startOfFirstDumpWithV8 === Infinity) return new tr.b.math.Range();
+ return tr.b.math.Range.fromExplicitRange(startOfFirstDumpWithV8, Infinity);
+ }
+
+ /**
+ * An end-point of a window that is sliding from left to right
+ * over |points| starting from time |start|.
+ * It is intended to be used only by the |mutatorUtilization| function.
+ * @constructor
+ */
+ class WindowEndpoint {
+ constructor(start, points) {
+ this.points = points;
+ // The index of the last passed point.
+ this.lastIndex = -1;
+ // The position of the end-point in the time line.
+ this.position = start;
+ this.distanceUntilNextPoint = points[0].position - start;
+ // The cumulative duration of GC pauses until this position.
+ this.cummulativePause = 0;
+ // The number of entered GC intervals.
+ this.stackDepth = 0;
+ }
+
+ // Advance the end-point by the given |delta|.
+ advance(delta) {
+ if (delta < this.distanceUntilNextPoint) {
+ this.position += delta;
+ this.cummulativePause += this.stackDepth > 0 ? delta : 0;
+ this.distanceUntilNextPoint =
+ this.points[this.lastIndex + 1].position - this.position;
+ } else {
+ this.position += this.distanceUntilNextPoint;
+ this.cummulativePause +=
+ this.stackDepth > 0 ? this.distanceUntilNextPoint : 0;
+ this.distanceUntilNextPoint = 0;
+ this.lastIndex++;
+ if (this.lastIndex < this.points.length) {
+ this.stackDepth += this.points[this.lastIndex].delta;
+ if (this.lastIndex + 1 < this.points.length) {
+ this.distanceUntilNextPoint =
+ this.points[this.lastIndex + 1].position - this.position;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns mutator utilization as a piecewise linear function.
+ * Mutator utilization for a window size w is a function of time mu_w(t)
+ * that shows how much time in [t, t+w] is left for the mutator relative
+ * to the time window size.
+ * More formally:
+ * mu_w(t) = (w - total_time_spent_in_gc_in(t, t + w)) / w.
+ * The range of mu_w(t) is [0..1].
+ * See "A Parallel, Real-Time Garbage Collector" by Cheng et. al. for
+ * more info [https://www.cs.cmu.edu/~guyb/papers/gc2001.pdf].
+ *
+ * All parameters must use the same time unit.
+ * @param {number} start The start time of execution.
+ * @param {number} end The end time of execution.
+ * @param {number} timeWindow The size of the time window.
+ * @param {!Array<!{start: number, end: number}>} intervals The list of
+ * GC pauses.
+ */
+ function mutatorUtilization(start, end, timeWindow, intervals) {
+ const mu = new tr.b.math.PiecewiseLinearFunction();
+ // If the interval is smaller than the time window, then the function is
+ // empty.
+ if (end - start <= timeWindow) {
+ return mu;
+ }
+
+ // If there are GC pauses then the mutator utilization is 1.0.
+ if (intervals.length === 0) {
+ mu.push(start, 1.0, end - timeWindow, 1.0);
+ return mu;
+ }
+
+ intervals = unionOfIntervals(intervals);
+
+ // Create a point for the start and the end of each interval.
+ const points = [];
+ for (const interval of intervals) {
+ points.push({position: interval.start, delta: 1});
+ points.push({position: interval.end, delta: -1});
+ }
+ points.sort((a, b) => a.position - b.position);
+ points.push({position: end, delta: 0});
+
+ // The left and the right limit of the sliding window.
+ const left = new WindowEndpoint(start, points);
+ const right = new WindowEndpoint(start, points);
+
+ // Advance the right end-point until we get the correct window size.
+ // Allow the floating-point precision errors of this magnitude.
+ const EPSILON = 1e-6;
+ while (right.position - left.position < timeWindow - EPSILON) {
+ right.advance(timeWindow - (right.position - left.position));
+ }
+
+ while (right.lastIndex < points.length) {
+ // Advance the window end-points by the largest possible amount
+ // without jumping over a point.
+ const distanceUntilNextPoint =
+ Math.min(left.distanceUntilNextPoint, right.distanceUntilNextPoint);
+ const position1 = left.position;
+ const value1 = right.cummulativePause - left.cummulativePause;
+ left.advance(distanceUntilNextPoint);
+ right.advance(distanceUntilNextPoint);
+ // Add a new mutator utilization segment only if it is non-trivial.
+ if (distanceUntilNextPoint > 0) {
+ const position2 = left.position;
+ const value2 = right.cummulativePause - left.cummulativePause;
+ mu.push(position1, 1.0 - value1 / timeWindow,
+ position2, 1.0 - value2 / timeWindow);
+ }
+ }
+ return mu;
+ }
+
+ /**
+ * Computes the minimum mutator utilization (MMU) metric for the given time
+ * windows and the given renderers. The results are added as histograms to
+ * the given histogram set.
+ *
+ * For example, passing 'v8-gc-mark-compactor-mmu' as the metric name and
+ * [16, 50, 100] as the time windows will produce the following:
+ * - v8-gc-mark-compactor-mmu-16ms_window
+ * - v8-gc-mark-compactor-mmu-50ms_window
+ * - v8-gc-mark-compactor-mmu-100ms_window
+ *
+ * @param {!string} metricName the name of the metric.
+ * @param {!function(tr.b.Event): boolean} eventFilter the predicate for
+ * filtering the events that will be used for computing the MMU.
+ * @param {!Array.<tr.model.helpers.ChromeRendererHelper>} rendererHelpers
+ * @param {!tr.v.HistogramSet} histograms
+ */
+ function addMutatorUtilization(
+ metricName, eventFilter, timeWindows, rendererHelpers, histograms) {
+ const histogramMap = new Map();
+
+ for (const timeWindow of timeWindows) {
+ const summaryOptions = {
+ avg: false,
+ count: false,
+ max: false,
+ min: true,
+ std: false,
+ sum: false
+ };
+ const description =
+ `The minimum mutator utilization in ${timeWindow}ms time window`;
+ const histogram = histograms.createHistogram(
+ `${metricName}-${timeWindow}ms_window`,
+ tr.b.Unit.byName.normalizedPercentage_biggerIsBetter,
+ [], {summaryOptions, description});
+ histogramMap.set(timeWindow, histogram);
+ }
+
+ for (const rendererHelper of rendererHelpers) {
+ if (rendererHelper.isChromeTracingUI) continue;
+ const pauses = [];
+ for (const event of rendererHelper.mainThread.sliceGroup.childEvents()) {
+ if (eventFilter(event) && event.end > event.start) {
+ pauses.push({start: event.start, end: event.end});
+ }
+ }
+ pauses.sort((a, b) => a.start - b.start);
+ const start = rendererHelper.mainThread.bounds.min;
+ const end = rendererHelper.mainThread.bounds.max;
+ for (const timeWindow of timeWindows) {
+ const mu = mutatorUtilization(start, end, timeWindow, pauses);
+ histogramMap.get(timeWindow).addSample(mu.min);
+ }
+ }
+ }
+
+
+ return {
+ addMutatorUtilization,
+ findParent,
+ forcedGCEventName,
+ groupAndProcessEvents,
+ isForcedGarbageCollectionEvent,
+ isFullMarkCompactorEvent,
+ isGarbageCollectionEvent,
+ isIdleTask,
+ isIncrementalMarkingEvent,
+ isLatencyMarkCompactorEvent,
+ isLowMemoryEvent,
+ isMarkCompactorSummaryEvent,
+ isMarkCompactorMarkingSummaryEvent,
+ isMemoryMarkCompactorEvent,
+ isNotForcedMarkCompactorEvent,
+ isNotForcedTopGarbageCollectionEvent,
+ isNotForcedSubGarbageCollectionEvent,
+ isScavengerEvent,
+ isSubGarbageCollectionEvent,
+ isTopGarbageCollectionEvent,
+ isTopV8ExecuteEvent,
+ isV8Event,
+ isV8ExecuteEvent,
+ isV8RCSEvent,
+ isCompileRCSCategory,
+ isCompileOptimizeRCSCategory,
+ isCompileUnoptimizeRCSCategory,
+ isCompileParseRCSCategory,
+ mutatorUtilization,
+ rangeForMemoryDumps,
+ subGarbageCollectionEventName,
+ topGarbageCollectionEventName,
+ unionOfIntervals,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils_test.html
new file mode 100644
index 00000000000..dc45524508a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/utils_test.html
@@ -0,0 +1,189 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/v8/utils.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function addDumpWithAllocator(model, process, allocator, start) {
+ const gmd = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump(
+ model, {ts: start});
+ const pmd = tr.model.MemoryDumpTestUtils.addProcessMemoryDump(gmd, process);
+ pmd.memoryAllocatorDumps =
+ [tr.model.MemoryDumpTestUtils.newAllocatorDump(pmd, allocator)];
+ }
+
+ const unionOfIntervals = tr.metrics.v8.utils.unionOfIntervals;
+
+ function interval(start, end) {
+ return {start, end};
+ }
+
+ /**
+ * Brute force computation of the mutator utilization.
+ * The function steps from the start to the end and for each step
+ * computes the mutator utilization.
+ */
+ function mutatorUtilizationSlow(start, end, timeWindow, intervals) {
+ const STEP = 0.001;
+ function timeToIndex(time) {
+ return Math.floor((time - start) / STEP);
+ }
+ const N = timeToIndex(end) + 1;
+ // bitmap[i] === true means that GC is active at time i.
+ const bitmap = new Array(N);
+ for (let i = 0; i < N; i++) {
+ bitmap[i] = false;
+ }
+ intervals.forEach(function(interval) {
+ const start = timeToIndex(interval.start);
+ const end = timeToIndex(interval.end);
+ for (let i = start; i < end; i++) {
+ bitmap[i] = true;
+ }
+ });
+ const pause = new Array(N);
+ for (let i = 0; i < N; i++) {
+ pause[i] = (i > 0 ? pause[i - 1] : 0) + (bitmap[i] ? 1 : 0);
+ }
+ const windowWidth = timeToIndex(timeWindow);
+ const mu = new Array(Math.max(N - windowWidth, 0));
+ for (let i = 0; i < mu.length; i++) {
+ const value = pause[i + windowWidth] - pause[i];
+ mu[i] = 1.0 - value / windowWidth;
+ }
+ mu.sort((a, b) => a - b);
+ return {
+ average: mu.reduce((acc, x) => (acc + x), 0) / mu.length,
+ min: mu.reduce((acc, x) => Math.min(acc, x), 0),
+ max: mu.reduce((acc, x) => Math.max(acc, x), 0),
+ percentile(percent) {
+ return mu[Math.floor(percent * (mu.length - 1))];
+ }
+ };
+ }
+
+ /**
+ * Constructs PiecewiseLinearFunction from pieces.
+ * @param {!Array<!{x1: number, y1: number, x2: number, y2: number}>} pieces
+ * The list of pieces ordered by the x coordinate.
+ */
+ function createExpectedFunction(pieces) {
+ const f = new tr.b.math.PiecewiseLinearFunction();
+ pieces.forEach(function(p) {
+ f.push(p.x1, p.y1, p.x2, p.y2);
+ });
+ return f;
+ }
+
+ test('unionOfIntervals', function() {
+ assert.deepEqual(unionOfIntervals([]), []);
+ assert.deepEqual(unionOfIntervals([interval(1, 1)]), [interval(1, 1)]);
+ assert.deepEqual(
+ unionOfIntervals([interval(0, 1), interval(1, 2), interval(2, 3)]),
+ [interval(0, 3)]);
+ assert.deepEqual(
+ unionOfIntervals([interval(0, 1), interval(1, 2), interval(3, 3)]),
+ [interval(0, 2), interval(3, 3)]);
+ assert.deepEqual(
+ unionOfIntervals([interval(0, 10), interval(1, 2), interval(3, 3)]),
+ [interval(0, 10)]);
+ assert.deepEqual(
+ unionOfIntervals([interval(0, 10), interval(1, 2), interval(3, 11)]),
+ [interval(0, 11)]);
+ assert.deepEqual(
+ unionOfIntervals([interval(3, 10), interval(1, 2), interval(11, 11)]),
+ [interval(1, 2), interval(3, 10), interval(11, 11)]);
+ });
+
+ test('basicMutatorUtilization', function() {
+ assert.deepEqual(
+ tr.metrics.v8.utils.mutatorUtilization(0, 40, 10, [interval(10, 20)]),
+ createExpectedFunction([
+ { x1: 0, y1: 1.0, x2: 10, y2: 0.0 },
+ { x1: 10, y1: 0.0, x2: 20, y2: 1.0 },
+ { x1: 20, y1: 1.0, x2: 30, y2: 1.0 }])
+ );
+ assert.deepEqual(
+ tr.metrics.v8.utils.mutatorUtilization(0, 40, 10, [interval(10, 15)]),
+ createExpectedFunction([
+ { x1: 0, y1: 1.0, x2: 5, y2: 0.5 },
+ { x1: 5, y1: 0.5, x2: 10, y2: 0.5 },
+ { x1: 10, y1: 0.5, x2: 15, y2: 1.0 },
+ { x1: 15, y1: 1.0, x2: 30, y2: 1.0 }])
+ );
+ assert.deepEqual(
+ tr.metrics.v8.utils.mutatorUtilization(0, 60, 20,
+ [interval(30, 35), interval(40, 45)]),
+ createExpectedFunction([
+ { x1: 0, y1: 1.0, x2: 10, y2: 1.0 },
+ { x1: 10, y1: 1.0, x2: 15, y2: 0.75 },
+ { x1: 15, y1: 0.75, x2: 20, y2: 0.75 },
+ { x1: 20, y1: 0.75, x2: 25, y2: 0.5 },
+ { x1: 25, y1: 0.5, x2: 30, y2: 0.5 },
+ { x1: 30, y1: 0.5, x2: 35, y2: 0.75 },
+ { x1: 35, y1: 0.75, x2: 40, y2: 0.75 }])
+ );
+ });
+
+ test('mutatorUtilization', function() {
+ const pauses = [
+ interval(10, 20),
+ interval(15, 23),
+ interval(30, 31),
+ interval(33, 34),
+ interval(60, 61),
+ interval(61, 63),
+ interval(80, 88)];
+ const actual = tr.metrics.v8.utils.mutatorUtilization(0, 100, 7, pauses);
+ const expected = mutatorUtilizationSlow(0, 100, 7, pauses);
+ assert.closeTo(expected.average, actual.average, 1e-3);
+ assert.closeTo(expected.max, actual.max, 1e-3);
+ assert.closeTo(expected.min, actual.min, 1e-3);
+ assert.closeTo(expected.percentile(0.5), actual.percentile(0.5), 1e-3);
+ assert.closeTo(expected.percentile(0.9), actual.percentile(0.9), 1e-3);
+ });
+
+ test('mutatorUtilizationMakesProgress', function() {
+ const start = 44173.32375717163;
+ const end = 80378.0457572937;
+ const pauses = [
+ interval(500, 700),
+ interval(900, 990)];
+ const actual = tr.metrics.v8.utils.mutatorUtilization(
+ start, end, 16.67, pauses);
+ assert.closeTo(0.9548, actual.average, 1e-3);
+ });
+
+
+ test('rangeForMemoryDumps', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ addDumpWithAllocator(model, process, 'dummy', 10);
+ addDumpWithAllocator(model, process, 'v8', 20);
+ });
+ const range = tr.metrics.v8.utils.rangeForMemoryDumps(model);
+ assert.isFalse(range.isEmpty);
+ assert.strictEqual(range.min, 20);
+ assert.strictEqual(range.max, Infinity);
+ });
+
+ test('rangeForMemoryDumpsEmpty', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ addDumpWithAllocator(model, process, 'dummy', 10);
+ addDumpWithAllocator(model, process, 'dummy', 20);
+ });
+ const range = tr.metrics.v8.utils.rangeForMemoryDumps(model);
+ assert.isTrue(range.isEmpty);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html b/chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html
new file mode 100644
index 00000000000..507d23e6119
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/v8/v8_metrics.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/system_health/memory_metric.html">
+<link rel="import" href="/tracing/metrics/v8/execution_metric.html">
+<link rel="import" href="/tracing/metrics/v8/gc_metric.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.v8', function() {
+ function v8AndMemoryMetrics(histograms, model) {
+ tr.metrics.v8.executionMetric(histograms, model);
+ tr.metrics.v8.gcMetric(histograms, model);
+ tr.metrics.sh.memoryMetric(histograms, model,
+ {rangeOfInterest: tr.metrics.v8.utils.rangeForMemoryDumps(model)});
+ }
+
+ tr.metrics.MetricRegistry.register(v8AndMemoryMetrics);
+
+ return {
+ v8AndMemoryMetrics,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/vr/frame_cycle_duration_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/vr/frame_cycle_duration_metric.html
new file mode 100644
index 00000000000..1a3f4b4d5af
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/vr/frame_cycle_duration_metric.html
@@ -0,0 +1,261 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.vr', function() {
+ function createHistograms(histograms, name, options, hasCpuTime) {
+ const createdHistograms = {
+ wall: histograms.createHistogram(
+ name + '_wall', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [],
+ options)
+ };
+ if (hasCpuTime) {
+ createdHistograms.cpu = histograms.createHistogram(name + '_cpu',
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], options);
+ }
+ return createdHistograms;
+ }
+
+ function frameCycleDurationMetric(histograms, model, opt_options) {
+ const histogramsByEventTitle = new Map();
+ histogramsByEventTitle.set('Vr.DrawFrame',
+ createHistograms(histograms, 'draw_frame',
+ {description: 'Duration to render one frame'}, true));
+ histogramsByEventTitle.set('Vr.AcquireGvrFrame',
+ createHistograms(histograms, 'acquire_frame',
+ {description: 'Duration acquire a frame from GVR'}, true));
+ histogramsByEventTitle.set(
+ 'Vr.ProcessControllerInput',
+ createHistograms(
+ histograms, 'update_controller',
+ {description: 'Duration to query input from the controller'},
+ true));
+ histogramsByEventTitle.set(
+ 'Vr.ProcessControllerInputForWebXr',
+ createHistograms(
+ histograms, 'update_controller_webxr',
+ {description: 'Duration to query input from the controller ' +
+ 'for WebXR'},
+ true));
+ histogramsByEventTitle.set('Vr.SubmitFrameNow',
+ createHistograms(histograms, 'submit_frame',
+ {description: 'Duration to submit a frame to GVR'}, true));
+ histogramsByEventTitle.set('Vr.PostSubmitDrawOnGpu',
+ createHistograms(histograms, 'post_submit_draw_on_gpu',
+ {description: 'Duration to draw a frame on GPU post submit to ' +
+ 'GVR. Note this duration may include time spent on ' +
+ 'reprojection'}, false));
+
+ // TODO(crbug/884259): Remove the following aliases after some time.
+ histogramsByEventTitle.set('VrShellGl::DrawFrame',
+ histogramsByEventTitle.get('Vr.DrawFrame'));
+ histogramsByEventTitle.set('VrShellGl::AcquireFrame',
+ histogramsByEventTitle.get('Vr.AcquireGvrFrame'));
+ histogramsByEventTitle.set('VrShellGl::UpdateController',
+ histogramsByEventTitle.get('Vr.ProcessControllerInput'));
+ histogramsByEventTitle.set('VrShellGl::DrawFrameSubmitNow',
+ histogramsByEventTitle.get('Vr.SubmitFrameNow'));
+ histogramsByEventTitle.set('VrShellGl::PostSubmitDrawOnGpu',
+ histogramsByEventTitle.get('Vr.PostSubmitDrawOnGpu'));
+
+ // Scene update metrics.
+ histogramsByEventTitle.set(
+ 'UiScene::OnBeginFrame.UpdateAnimationsAndOpacity',
+ createHistograms(
+ histograms, 'update_animations_and_opacity',
+ {description: 'Duration to apply animation and opacity changes'},
+ true));
+ histogramsByEventTitle.set(
+ 'UiScene::OnBeginFrame.UpdateBindings',
+ createHistograms(
+ histograms, 'update_bindings',
+ {description: 'Duration to push binding values'}, true));
+ histogramsByEventTitle.set(
+ 'UiScene::OnBeginFrame.UpdateLayout',
+ createHistograms(histograms, 'update_layout', {
+ description: 'Duration to compute element sizes, layout and textures'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiScene::OnBeginFrame.UpdateWorldSpaceTransform',
+ createHistograms(histograms, 'update_world_space_transforms', {
+ description: 'Duration to calculate element transforms in world space'
+ }, true));
+ // Draw metrics.
+ histogramsByEventTitle.set(
+ 'UiRenderer::DrawUiView',
+ createHistograms(histograms, 'draw_ui', {
+ description: 'Duration to draw the UI'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawTexturedQuad',
+ createHistograms(histograms, 'draw_textured_quad', {
+ description: 'Duration to draw a textured element'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawGradientQuad',
+ createHistograms(histograms, 'draw_gradient_quad', {
+ description: 'Duration to draw a gradient element'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawGradientGridQuad',
+ createHistograms(histograms, 'draw_gradient_grid_quad', {
+ description: 'Duration to draw a gradient grid element'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawController',
+ createHistograms(histograms, 'draw_controller', {
+ description: 'Duration to draw the controller'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawLaser',
+ createHistograms(histograms, 'draw_laser', {
+ description: 'Duration to draw the laser'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawReticle',
+ createHistograms(histograms, 'draw_reticle', {
+ description: 'Duration to draw the reticle'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawShadow',
+ createHistograms(histograms, 'draw_shadow', {
+ description: 'Duration to draw a shadow element'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawStars',
+ createHistograms(histograms, 'draw_stars', {
+ description: 'Duration to draw the stars'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawBackground',
+ createHistograms(histograms, 'draw_background', {
+ description: 'Duration to draw the textured background'
+ }, true));
+ histogramsByEventTitle.set(
+ 'UiElementRenderer::DrawKeyboard',
+ createHistograms(histograms, 'draw_keyboard', {
+ description: 'Duration to draw the keyboard'
+ }, true));
+
+ // Maps from the GUID of a UiRenderer::DrawUiView slice to each of its
+ // children slices.
+ const drawUiSubSlicesMap = new Map();
+
+ const chromeHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ let rangeOfInterest = model.bounds;
+ const userExpectationsOfInterest = [tr.model.um.AnimationExpectation];
+
+ if (opt_options && opt_options.rangeOfInterest) {
+ rangeOfInterest = opt_options.rangeOfInterest;
+ userExpectationsOfInterest.push(tr.model.um.ResponseExpectation);
+ }
+
+ for (const ue of model.userModel.expectations) {
+ // Skip user expecations not of the right type or not inside the range of
+ // interest.
+ if (ue.initiatorType !== tr.model.um.INITIATOR_TYPE.VR) {
+ continue;
+ }
+ if (!userExpectationsOfInterest.some(function(ueOfInterest) {
+ return ue instanceof ueOfInterest;
+ })) {
+ continue;
+ }
+ if (!rangeOfInterest.intersectsExplicitRangeInclusive(
+ ue.start, ue.end)) {
+ continue;
+ }
+
+ for (const helper of chromeHelper.browserHelpers) {
+ // The events are traced on the GL thread in the browser process.
+ // Unfortunately, this thread has no name.
+ // TODO(tiborg): Give GL thread a name and reference the thread by
+ // the given name.
+ const glThreads = helper.process.findAllThreadsMatching(
+ thread => !thread.name);
+
+ for (const glThread of glThreads) {
+ for (const event of glThread.getDescendantEvents()) {
+ // Skip events that are neither in the user expecation, range of
+ // interest nor part of the frame cycle durations.
+ if (!(histogramsByEventTitle.has(event.title))) {
+ continue;
+ }
+ if (event.start < ue.start || event.end > ue.end) {
+ continue;
+ }
+ if (event.start < rangeOfInterest.min ||
+ event.end > rangeOfInterest.max) {
+ continue;
+ }
+
+ // There can be multiple UiElementRenderer::Draw... events per frame
+ // but this metric should calculate the across frame average of
+ // durations. Thus, collect UiElementRenderer::Draw... slices here
+ // in order to process them below.
+ if (event.parentSlice &&
+ event.parentSlice.title === 'UiRenderer::DrawUiView') {
+ const guid = event.parentSlice.guid;
+ if (!drawUiSubSlicesMap.has(guid)) {
+ drawUiSubSlicesMap.set(guid, []);
+ }
+ drawUiSubSlicesMap.get(guid).push(event);
+ continue;
+ }
+
+ const {wall: wallHist, cpu: cpuHist} =
+ histogramsByEventTitle.get(event.title);
+ wallHist.addSample(event.duration);
+ if (cpuHist !== undefined) {
+ cpuHist.addSample(event.cpuDuration);
+ }
+ }
+ }
+ }
+ }
+
+ // Calculate the average of the per frame sums of UiElementRenderer::Draw...
+ // events.
+ for (const subSlices of drawUiSubSlicesMap.values()) {
+ const eventMap = new Map();
+ for (const event of subSlices) {
+ if (!eventMap.has(event.title)) {
+ eventMap.set(event.title, {
+ wall: 0,
+ cpu: 0
+ });
+ }
+ eventMap.get(event.title).wall += event.duration;
+ eventMap.get(event.title).cpu += event.cpuDuration;
+ }
+ for (const [title, values] of eventMap.entries()) {
+ const {wall: wallHist, cpu: cpuHist} =
+ histogramsByEventTitle.get(title);
+ wallHist.addSample(values.wall);
+ if (cpuHist !== undefined) {
+ cpuHist.addSample(values.cpu);
+ }
+ }
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(frameCycleDurationMetric, {
+ supportsRangeOfInterest: true,
+ });
+
+ return {
+ frameCycleDurationMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/vr/frame_cycle_duration_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/vr/frame_cycle_duration_metric_test.html
new file mode 100644
index 00000000000..e6500713167
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/vr/frame_cycle_duration_metric_test.html
@@ -0,0 +1,333 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/vr/frame_cycle_duration_metric.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ const TOLERANCE = 1e-6;
+
+ function createSubSlices(durations, currentTime, sliceGroup) {
+ if (durations === undefined) {
+ return [];
+ }
+ const slices = [];
+ for (const duration of durations) {
+ const option = {
+ cat: 'gpu',
+ title: duration.title,
+ start: currentTime,
+ end: currentTime + duration.wall,
+ };
+ if (duration.cpu !== undefined) {
+ option.cpuStart = currentTime;
+ option.cpuEnd = currentTime + duration.cpu;
+ }
+ const slice = tr.c.TestUtils.newSliceEx(option);
+ slice.subSlices = createSubSlices(
+ duration.sub, currentTime + 0.1, sliceGroup);
+ sliceGroup.pushSlice(slice);
+ slices.push(slice);
+ const maxDuration = duration.cpu === undefined ?
+ duration.wall : Math.max(duration.wall, duration.cpu);
+ currentTime += maxDuration + 1;
+ }
+ return slices;
+ }
+
+ test('frameCycleDurationMetric', function() {
+ const durations = [
+ {
+ title: 'Vr.DrawFrame',
+ wall: 390,
+ cpu: 340,
+ sub: [
+ {title: 'Vr.AcquireGvrFrame', wall: 2, cpu: 2},
+ {title: 'Vr.AcquireGvrFrame', wall: 2.5, cpu: 1.5},
+ {
+ title: 'UiScene::OnBeginFrame.UpdateAnimationsAndOpacity',
+ wall: 3,
+ cpu: 2
+ },
+ {
+ title: 'UiScene::OnBeginFrame.UpdateAnimationsAndOpacity',
+ wall: 2,
+ cpu: 1
+ },
+ {title: 'UiScene::OnBeginFrame.UpdateBindings', wall: 3, cpu: 2},
+ {title: 'UiScene::OnBeginFrame.UpdateBindings', wall: 2, cpu: 1},
+ {title: 'UiScene::OnBeginFrame.UpdateLayout', wall: 3, cpu: 2},
+ {title: 'UiScene::OnBeginFrame.UpdateLayout', wall: 2, cpu: 1},
+ {
+ title: 'UiScene::OnBeginFrame.UpdateWorldSpaceTransform',
+ wall: 3,
+ cpu: 2
+ },
+ {
+ title: 'UiScene::OnBeginFrame.UpdateWorldSpaceTransform',
+ wall: 2,
+ cpu: 1
+ },
+ {title: 'Vr.ProcessControllerInput', wall: 1, cpu: 0.5},
+ {title: 'Vr.ProcessControllerInput', wall: 0.5, cpu: 0.4},
+ {title: 'Vr.ProcessControllerInputForWebXr', wall: 1, cpu: 0.5},
+ {title: 'Vr.ProcessControllerInputForWebXr', wall: 1.5, cpu: 0.6},
+ {
+ title: 'UiRenderer::DrawUiView',
+ wall: 250,
+ cpu: 230,
+ sub: [
+ {title: 'UiElementRenderer::DrawTexturedQuad', wall: 1, cpu: 0.5},
+ {title: 'UiElementRenderer::DrawGradientQuad', wall: 3, cpu: 2},
+ {title: 'UiElementRenderer::DrawGradientQuad', wall: 4, cpu: 3},
+ {title: 'UiElementRenderer::DrawTexturedQuad', wall: 2, cpu: 1},
+ {
+ title: 'UiElementRenderer::DrawGradientGridQuad',
+ wall: 5,
+ cpu: 4
+ },
+ {
+ title: 'UiElementRenderer::DrawGradientGridQuad',
+ wall: 6,
+ cpu: 5
+ },
+ {title: 'UiElementRenderer::DrawController', wall: 7, cpu: 6},
+ {title: 'UiElementRenderer::DrawController', wall: 8, cpu: 7},
+ {title: 'UiElementRenderer::DrawLaser', wall: 9, cpu: 8},
+ {title: 'UiElementRenderer::DrawLaser', wall: 10, cpu: 9},
+ {title: 'UiElementRenderer::DrawReticle', wall: 11, cpu: 10},
+ {title: 'UiElementRenderer::DrawReticle', wall: 12, cpu: 11},
+ {title: 'UiElementRenderer::DrawShadow', wall: 13, cpu: 12},
+ {title: 'UiElementRenderer::DrawShadow', wall: 14, cpu: 13},
+ {title: 'UiElementRenderer::DrawStars', wall: 15, cpu: 14},
+ {title: 'UiElementRenderer::DrawStars', wall: 16, cpu: 15},
+ {title: 'UiElementRenderer::DrawBackground', wall: 17, cpu: 16},
+ {title: 'UiElementRenderer::DrawBackground', wall: 18, cpu: 17},
+ {title: 'UiElementRenderer::DrawKeyboard', wall: 19, cpu: 18},
+ {title: 'UiElementRenderer::DrawKeyboard', wall: 20, cpu: 19},
+ ]
+ },
+ {
+ title: 'UiRenderer::DrawUiView',
+ wall: 80,
+ cpu: 75,
+ sub: [
+ {title: 'UiElementRenderer::DrawTexturedQuad', wall: 2, cpu: 1},
+ {title: 'UiElementRenderer::DrawGradientQuad', wall: 3, cpu: 2},
+ {
+ title: 'UiElementRenderer::DrawGradientGridQuad',
+ wall: 4,
+ cpu: 3
+ },
+ {title: 'UiElementRenderer::DrawController', wall: 5, cpu: 4},
+ {title: 'UiElementRenderer::DrawLaser', wall: 6, cpu: 5},
+ {title: 'UiElementRenderer::DrawReticle', wall: 7, cpu: 6},
+ {title: 'UiElementRenderer::DrawShadow', wall: 8, cpu: 7},
+ {title: 'UiElementRenderer::DrawStars', wall: 9, cpu: 8},
+ {title: 'UiElementRenderer::DrawBackground', wall: 10, cpu: 9},
+ {title: 'UiElementRenderer::DrawKeyboard', wall: 11, cpu: 10},
+ ]
+ },
+ {title: 'Vr.SubmitFrameNow', wall: 3, cpu: 0.5},
+ {title: 'Vr.SubmitFrameNow', wall: 3.5, cpu: 0.5},
+ {title: 'Vr.PostSubmitDrawOnGpu', wall: 3},
+ {title: 'Vr.PostSubmitDrawOnGpu', wall: 4},
+ ]
+ },
+ {title: 'Vr.DrawFrame', wall: 20, cpu: 10},
+ // This event should be filtered out by the user expecation.
+ {title: 'Vr.DrawFrame', wall: 20, cpu: 10},
+ ];
+ const histograms = new tr.v.HistogramSet();
+ const model = tr.c.TestUtils.newModel(function(model) {
+ model.userModel.expectations.push(
+ new tr.model.um.AnimationExpectation(model,
+ tr.model.um.INITIATOR_TYPE.VR, 0, 411));
+ const browserProcess = model.getOrCreateProcess(0);
+ const browserMainThread = browserProcess.getOrCreateThread(0);
+ browserMainThread.name = 'CrBrowserMain';
+ const browserGlThread = browserProcess.getOrCreateThread(1);
+ const group = browserGlThread.sliceGroup;
+ createSubSlices(durations, 0, group);
+ group.createSubSlices();
+ });
+
+ tr.metrics.vr.frameCycleDurationMetric(histograms, model);
+
+ assert.closeTo(histograms.getHistogramNamed('draw_frame_wall').average,
+ 205, TOLERANCE);
+ assert.closeTo(histograms.getHistogramNamed('draw_frame_cpu').average,
+ 175, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('acquire_frame_wall').average,
+ 2.25, TOLERANCE);
+ assert.closeTo(histograms.getHistogramNamed('acquire_frame_cpu').average,
+ 1.75, TOLERANCE);
+
+ assert.isUndefined(
+ histograms.getHistogramNamed('post_submit_draw_on_gpu_cpu'));
+ assert.closeTo(
+ histograms.getHistogramNamed('post_submit_draw_on_gpu_wall').average,
+ 3.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('update_controller_wall').average,
+ 0.75, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('update_controller_cpu').average,
+ 0.45, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('update_controller_webxr_wall').average,
+ 1.25, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('update_controller_webxr_cpu').average,
+ 0.55, TOLERANCE);
+
+ assert.closeTo(histograms.getHistogramNamed('submit_frame_wall').average,
+ 3.25, TOLERANCE);
+ assert.closeTo(histograms.getHistogramNamed('submit_frame_cpu').average,
+ 0.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('update_animations_and_opacity_wall')
+ .average,
+ 2.5, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('update_animations_and_opacity_cpu')
+ .average,
+ 1.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('update_bindings_wall').average, 2.5,
+ TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('update_bindings_cpu').average, 1.5,
+ TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('update_layout_wall').average, 2.5,
+ TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('update_layout_cpu').average, 1.5,
+ TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('update_world_space_transforms_wall')
+ .average,
+ 2.5, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('update_world_space_transforms_cpu')
+ .average,
+ 1.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_ui_wall')
+ .average,
+ 165, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_ui_cpu')
+ .average,
+ 152.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_textured_quad_wall')
+ .average,
+ 2.5, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_textured_quad_cpu')
+ .average,
+ 1.25, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_gradient_quad_wall')
+ .average,
+ 5, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_gradient_quad_cpu')
+ .average,
+ 3.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_gradient_grid_quad_wall')
+ .average,
+ 7.5, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_gradient_grid_quad_cpu')
+ .average,
+ 6, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_controller_wall')
+ .average,
+ 10, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_controller_cpu')
+ .average,
+ 8.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_laser_wall')
+ .average,
+ 12.5, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_laser_cpu')
+ .average,
+ 11, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_reticle_wall')
+ .average,
+ 15, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_reticle_cpu')
+ .average,
+ 13.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_shadow_wall')
+ .average,
+ 17.5, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_shadow_cpu')
+ .average,
+ 16.0, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_stars_wall')
+ .average,
+ 20, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_stars_cpu')
+ .average,
+ 18.5, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_background_wall')
+ .average,
+ 22.5, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_background_cpu')
+ .average,
+ 21, TOLERANCE);
+
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_keyboard_wall')
+ .average,
+ 25, TOLERANCE);
+ assert.closeTo(
+ histograms.getHistogramNamed('draw_keyboard_cpu')
+ .average,
+ 23.5, TOLERANCE);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/vr/webvr_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/vr/webvr_metric.html
new file mode 100644
index 00000000000..254267053ea
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/vr/webvr_metric.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.vr', function() {
+ function webvrMetric(histograms, model, opt_options) {
+ // Maps VR trace counters to histogram.
+ const WEBVR_COUNTERS = new Map([
+ ['gpu.WebVR FPS', {
+ name: 'webvr_fps',
+ unit: tr.b.Unit.byName.count_biggerIsBetter,
+ samples: {},
+ options: {
+ description: 'WebVR frame per second',
+ binBoundaries: tr.v.HistogramBinBoundaries.createLinear(20, 120, 25),
+ },
+ }],
+ ['gpu.WebVR frame time (ms)', {
+ name: 'webvr_frame_time',
+ unit: tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ samples: {},
+ options: {
+ description: 'WebVR frame time in ms',
+ binBoundaries: tr.v.HistogramBinBoundaries.createLinear(20, 120, 25),
+ },
+ }],
+ ['gpu.WebVR pose prediction (ms)', {
+ name: 'webvr_pose_prediction',
+ unit: tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ samples: {},
+ options: {
+ description: 'WebVR pose prediction in ms',
+ binBoundaries: tr.v.HistogramBinBoundaries.createLinear(20, 120, 25),
+ },
+ }],
+ ]);
+
+ for (const ue of model.userModel.expectations) {
+ const rangeOfInterestEnabled = opt_options && opt_options.rangeOfInterest;
+ if (rangeOfInterestEnabled &&
+ !opt_options.rangeOfInterest.intersectsExplicitRangeInclusive(
+ ue.start, ue.end)) {
+ continue;
+ }
+
+ // By default, only do calculations in the VR animation expectation, i.e.
+ // some time after we've entered VR, in order to avoid skewed results
+ // caused by VR entry, but allow calculation on the response expectation
+ // if we've manually selected it as a range of interest
+ if (ue.initiatorType !== tr.model.um.INITIATOR_TYPE.VR) continue;
+ if (!rangeOfInterestEnabled) {
+ if (!(ue instanceof tr.model.um.AnimationExpectation)) continue;
+ } else {
+ if (!(ue instanceof tr.model.um.AnimationExpectation ||
+ ue instanceof tr.model.um.ResponseExpectation)) continue;
+ }
+
+ for (const counter of model.getAllCounters()) {
+ if (!(WEBVR_COUNTERS.has(counter.id))) continue;
+
+ for (const series of counter.series) {
+ if (!(series.name in WEBVR_COUNTERS.get(counter.id).samples)) {
+ WEBVR_COUNTERS.get(counter.id).samples[series.name] = [];
+ }
+ for (const sample of series.samples) {
+ if (sample.timestamp < ue.start || sample.timestamp >= ue.end) {
+ continue;
+ }
+ if (rangeOfInterestEnabled &&
+ !opt_options.rangeOfInterest.intersectsExplicitRangeInclusive(
+ sample.timestamp, sample.timestamp)) {
+ continue;
+ }
+
+ WEBVR_COUNTERS.get(counter.id).samples[series.name].push(
+ sample.value);
+ }
+ }
+ }
+ }
+
+ // Make sure we always report a value for WebVR FPS so that failing to
+ // submit frames will show up as a regression
+ if (!('value' in WEBVR_COUNTERS.get('gpu.WebVR FPS').samples)) {
+ WEBVR_COUNTERS.get('gpu.WebVR FPS').samples.value = [0];
+ }
+
+ for (const [key, value] of WEBVR_COUNTERS) {
+ for (const [seriesName, samples] of Object.entries(value.samples)) {
+ let histogramName = value.name;
+ if (seriesName !== 'value') {
+ histogramName = `${histogramName}_${seriesName}`;
+ }
+ histograms.createHistogram(histogramName, value.unit,
+ samples, value.options);
+ }
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(webvrMetric, {
+ supportsRangeOfInterest: true,
+ });
+
+ return {
+ webvrMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/vr/webvr_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/vr/webvr_metric_test.html
new file mode 100644
index 00000000000..75d73aeeb8a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/vr/webvr_metric_test.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/metrics/vr/webvr_metric.html">
+<link rel="import" href="/tracing/model/counter.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createModel() {
+ const model = tr.c.TestUtils.newModel(
+ function(model) {
+ model.userModel.expectations.push(
+ new tr.model.um.AnimationExpectation(model,
+ tr.model.um.INITIATOR_TYPE.VR, 0, 5));
+ const process = model.getOrCreateProcess(1);
+ const fpsCounter = process.getOrCreateCounter('gpu', 'WebVR FPS');
+ const fpsSeries = new tr.model.CounterSeries('value', 0);
+ fpsSeries.addCounterSample(1, 59);
+ fpsSeries.addCounterSample(3, 60);
+ fpsCounter.addSeries(fpsSeries);
+
+ const frameTimeCounter = process.getOrCreateCounter(
+ 'gpu', 'WebVR frame time (ms)');
+ const renderingSeries = new tr.model.CounterSeries('rendering', 0);
+ renderingSeries.addCounterSample(1, 3);
+ renderingSeries.addCounterSample(2, 4);
+ frameTimeCounter.addSeries(renderingSeries);
+ const javascriptSeries = new tr.model.CounterSeries('javascript', 0);
+ javascriptSeries.addCounterSample(1, 5);
+ javascriptSeries.addCounterSample(2, 6);
+ frameTimeCounter.addSeries(javascriptSeries);
+ });
+ return model;
+ }
+
+ test('webvrMetric', function() {
+ const histograms = new tr.v.HistogramSet();
+ const model = createModel();
+ tr.metrics.vr.webvrMetric(histograms, model);
+
+ const fpsValue = histograms.getHistogramNamed('webvr_fps');
+ assert.strictEqual(fpsValue.max, 60);
+ assert.strictEqual(fpsValue.min, 59);
+ assert.strictEqual(fpsValue.average, 59.5);
+
+ const renderingValue = histograms.getHistogramNamed(
+ 'webvr_frame_time_rendering');
+ assert.strictEqual(renderingValue.max, 4);
+ assert.strictEqual(renderingValue.min, 3);
+ assert.strictEqual(renderingValue.average, 3.5);
+
+ const javascriptValue = histograms.getHistogramNamed(
+ 'webvr_frame_time_javascript');
+ assert.strictEqual(javascriptValue.max, 6);
+ assert.strictEqual(javascriptValue.min, 5);
+ assert.strictEqual(javascriptValue.average, 5.5);
+ });
+
+ test('webvrMetric_alwaysReportFps', function() {
+ const histograms = new tr.v.HistogramSet();
+ const model = tr.c.TestUtils.newModel();
+ tr.metrics.vr.webvrMetric(histograms, model);
+
+ const fpsValue = histograms.getHistogramNamed('webvr_fps');
+ assert.strictEqual(fpsValue.max, 0);
+ assert.strictEqual(fpsValue.min, 0);
+
+ const renderingValue = histograms.getHistogramNamed(
+ 'webvr_frame_time_rendering');
+ assert.strictEqual(renderingValue, undefined);
+
+ const javascriptValue = histograms.getHistogramNamed(
+ 'webvr_frame_time_javascript');
+ assert.strictEqual(javascriptValue, undefined);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/webrtc/webrtc_rendering_metric.html b/chromium/third_party/catapult/tracing/tracing/metrics/webrtc/webrtc_rendering_metric.html
new file mode 100644
index 00000000000..a8414ec46d4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/webrtc/webrtc_rendering_metric.html
@@ -0,0 +1,364 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/metrics/v8/utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+
+<script>
+'use strict';
+
+tr.exportTo('tr.metrics.webrtc', function() {
+ const DISPLAY_HERTZ = 60.0;
+ const VSYNC_DURATION_US = 1e6 / DISPLAY_HERTZ;
+ // How much more severe is a 'Badly out of sync' render event compared to an
+ // 'Out of sync' one when calculating the smoothness score.
+ const SEVERITY = 3;
+ // How many vsyncs a frame should be displayed to be considered frozen.
+ const FROZEN_FRAME_VSYNC_COUNT_THRESHOLD = 6;
+
+ const WEB_MEDIA_PLAYER_UPDATE_TITLE = 'UpdateCurrentFrame';
+ // These four are args for WebMediaPlayerMS update events.
+ const IDEAL_RENDER_INSTANT_NAME = 'Ideal Render Instant';
+ const ACTUAL_RENDER_BEGIN_NAME = 'Actual Render Begin';
+ const ACTUAL_RENDER_END_NAME = 'Actual Render End';
+ // The events of interest have a 'Serial' argument which represents the
+ // stream ID.
+ const STREAM_ID_NAME = 'Serial';
+
+ const REQUIRED_EVENT_ARGS_NAMES = [
+ IDEAL_RENDER_INSTANT_NAME, ACTUAL_RENDER_BEGIN_NAME, ACTUAL_RENDER_END_NAME,
+ STREAM_ID_NAME
+ ];
+
+ // By default, we store a single value, so we only need one of the
+ // statistics to keep track. We choose the average for that.
+ const SUMMARY_OPTIONS = tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;
+
+ const count_smallerIsBetter =
+ tr.b.Unit.byName.count_smallerIsBetter;
+ const percentage_biggerIsBetter =
+ tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;
+ const percentage_smallerIsBetter =
+ tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;
+ const timeDurationInMs_smallerIsBetter =
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;
+ const unitlessNumber_biggerIsBetter =
+ tr.b.Unit.byName.unitlessNumber_biggerIsBetter;
+
+ /*
+ * Verify that the event is a valid event.
+ *
+ * An event is valid if it is a UpdateCurrentFrame event,
+ * and has all of the mandatory arguments. See MANDATORY above.
+ */
+ function isValidEvent(event) {
+ if (event.title !== WEB_MEDIA_PLAYER_UPDATE_TITLE || !event.args) {
+ return false;
+ }
+ for (const parameter of REQUIRED_EVENT_ARGS_NAMES) {
+ if (!(parameter in event.args)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function webrtcRenderingMetric(histograms, model) {
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ let webMediaPlayerMSEvents = [];
+ for (const rendererPid in modelHelper.rendererHelpers) {
+ const rendererHelper = modelHelper.rendererHelpers[rendererPid];
+ const compositorThread = rendererHelper.compositorThread;
+ if (compositorThread !== undefined) {
+ webMediaPlayerMSEvents = webMediaPlayerMSEvents.concat(
+ compositorThread.sliceGroup.slices.filter(isValidEvent));
+ }
+ }
+ const eventsByStreamName = tr.b.groupIntoMap(
+ webMediaPlayerMSEvents,
+ event => event.args[STREAM_ID_NAME]
+ );
+ for (const [streamName, events] of eventsByStreamName) {
+ getTimeStats(histograms, streamName, events);
+ }
+ }
+
+ tr.metrics.MetricRegistry.register(webrtcRenderingMetric);
+
+ function getTimeStats(histograms, streamName, events) {
+ const frameHist = getFrameDistribution(histograms, events);
+ addFpsFromFrameDistribution(histograms, frameHist);
+ addFreezingScore(histograms, frameHist);
+
+ const driftTimeStats = getDriftStats(events);
+ histograms.createHistogram('WebRTCRendering_drift_time',
+ timeDurationInMs_smallerIsBetter, driftTimeStats.driftTime, {
+ summaryOptions: {
+ count: false,
+ min: false,
+ percentile: [0.75, 0.9],
+ },
+ });
+ histograms.createHistogram('WebRTCRendering_rendering_length_error',
+ percentage_smallerIsBetter,
+ driftTimeStats.renderingLengthError, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+
+ const smoothnessStats = getSmoothnessStats(driftTimeStats.driftTime);
+ histograms.createHistogram('WebRTCRendering_percent_badly_out_of_sync',
+ percentage_smallerIsBetter, smoothnessStats.percentBadlyOutOfSync, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ histograms.createHistogram('WebRTCRendering_percent_out_of_sync',
+ percentage_smallerIsBetter, smoothnessStats.percentOutOfSync, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ histograms.createHistogram('WebRTCRendering_smoothness_score',
+ percentage_biggerIsBetter, smoothnessStats.smoothnessScore, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ histograms.createHistogram('WebRTCRendering_frames_out_of_sync',
+ count_smallerIsBetter, smoothnessStats.framesOutOfSync, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ histograms.createHistogram('WebRTCRendering_frames_badly_out_of_sync',
+ count_smallerIsBetter, smoothnessStats.framesSeverelyOutOfSync, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ }
+
+ const FRAME_DISTRIBUTION_BIN_BOUNDARIES =
+ tr.v.HistogramBinBoundaries.createLinear(1, 50, 49);
+
+ /**
+ * Create the frame distribution.
+ *
+ * If the overall display distribution is A1:A2:..:An, this will tell how
+ * many times a frame stays displayed during Ak*VSYNC_DURATION_US, also known
+ * as 'source to output' distribution.
+ *
+ * In other terms, a distribution B where
+ * B[k] = number of frames that are displayed k times.
+ *
+ * @param {tr.v.HistogramSet} histograms
+ * @param {Array.<event>} events - An array of events.
+ * @returns {tr.v.Histogram} frameHist - The frame distribution.
+ */
+ function getFrameDistribution(histograms, events) {
+ const cadence = tr.b.runLengthEncoding(
+ events.map(e => e.args[IDEAL_RENDER_INSTANT_NAME]));
+ return histograms.createHistogram('WebRTCRendering_frame_distribution',
+ count_smallerIsBetter, cadence.map(ticks => ticks.count), {
+ binBoundaries: FRAME_DISTRIBUTION_BIN_BOUNDARIES,
+ summaryOptions: {
+ percentile: [0.75, 0.9],
+ },
+ });
+ }
+
+ /**
+ * Calculate the apparent FPS from frame distribution.
+ *
+ * Knowing the display frequency and the frame distribution, it is possible to
+ * calculate the video apparent frame rate as played by WebMediaPlayerMs
+ * module.
+ *
+ * @param {tr.v.HistogramSet} histograms
+ * @param {tr.v.Histogram} frameHist - The frame distribution. See
+ * getFrameDistribution.
+ */
+ function addFpsFromFrameDistribution(histograms, frameHist) {
+ let numberFrames = 0;
+ let numberVsyncs = 0;
+ for (let ticks = 1; ticks < frameHist.allBins.length; ++ticks) {
+ const count = frameHist.allBins[ticks].count;
+ numberFrames += count;
+ numberVsyncs += ticks * count;
+ }
+ const meanRatio = numberVsyncs / numberFrames;
+ histograms.createHistogram('WebRTCRendering_fps',
+ unitlessNumber_biggerIsBetter, DISPLAY_HERTZ / meanRatio, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ }
+
+ /**
+ * Returns the weighted penalty for a number of frozen frames.
+ *
+ * In a series of repeated frames of length > 5, all frames after the first
+ * are considered frozen. Conversely, no frames in a series of repeated frames
+ * of length <= 5 will be considered frozen.
+ *
+ * This means the weight for 0 to 4 frozen frames is 0.
+ *
+ * @param {Number} numberFrozenFrames - The number of frozen frames.
+ * @returns {Number} - The weight penalty for the number of frozen frames.
+ */
+ function frozenPenaltyWeight(numberFrozenFrames) {
+ const penalty = {
+ 5: 1,
+ 6: 5,
+ 7: 15,
+ 8: 25
+ };
+ return penalty[numberFrozenFrames] || (8 * (numberFrozenFrames - 4));
+ }
+
+ /**
+ * Adds the freezing score.
+ *
+ * @param {tr.v.HistogramSet} histograms
+ * @param {tr.v.Histogram} frameHist - The frame distribution.
+ * See getFrameDistribution.
+ */
+ function addFreezingScore(histograms, frameHist) {
+ let numberVsyncs = 0;
+ let freezingScore = 0;
+ let frozenFramesCount = 0;
+ for (let ticks = 1; ticks < frameHist.allBins.length; ++ticks) {
+ const count = frameHist.allBins[ticks].count;
+ numberVsyncs += ticks * count;
+ if (ticks >= FROZEN_FRAME_VSYNC_COUNT_THRESHOLD) {
+ // The first frame of the series is not considered frozen.
+ frozenFramesCount += count * (ticks - 1);
+ freezingScore += count * frozenPenaltyWeight(ticks - 1);
+ }
+ }
+ freezingScore = 1 - freezingScore / numberVsyncs;
+ if (freezingScore < 0) {
+ freezingScore = 0;
+ }
+ histograms.createHistogram('WebRTCRendering_frozen_frames_count',
+ count_smallerIsBetter, frozenFramesCount, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ histograms.createHistogram('WebRTCRendering_freezing_score',
+ percentage_biggerIsBetter, freezingScore, {
+ summaryOptions: SUMMARY_OPTIONS,
+ });
+ }
+
+ /**
+ * Get the drift time statistics.
+ *
+ * This method will calculate:
+ * - Drift Time: The difference between the Actual Render Begin and the Ideal
+ * Render Instant for each event.
+ * - Rendering Length Error: The alignment error of the Ideal Render
+ * Instants. The Ideal Render Instants should be equally spaced by
+ * intervals of length VSYNC_DURATION_US. The Rendering Length error
+ * measures how much they are misaligned.
+ *
+ * @param {Array.<event>} events - An array of events.
+ * @returns {Object.<Array.<Number>, Number>} - The drift time and rendering
+ * length error.
+ */
+ function getDriftStats(events) {
+ const driftTime = [];
+ const discrepancy = [];
+ let oldIdealRender = 0;
+ let expectedIdealRender = 0;
+
+ for (const event of events) {
+ const currentIdealRender = event.args[IDEAL_RENDER_INSTANT_NAME];
+ // The expected time of the next 'Ideal Render' event begins as the
+ // current 'Ideal Render' time and increases by VSYNC_DURATION_US on every
+ // frame.
+ expectedIdealRender += VSYNC_DURATION_US;
+ if (currentIdealRender === oldIdealRender) {
+ continue;
+ }
+ const actualRenderBegin = event.args[ACTUAL_RENDER_BEGIN_NAME];
+ // When was the frame rendered vs. when it would've been ideal.
+ driftTime.push(actualRenderBegin - currentIdealRender);
+ // The discrepancy is the absolute difference between the current Ideal
+ // Render and the expected Ideal Render.
+ discrepancy.push(Math.abs(currentIdealRender - expectedIdealRender));
+ expectedIdealRender = currentIdealRender;
+ oldIdealRender = currentIdealRender;
+ }
+
+ const discrepancySum = tr.b.math.Statistics.sum(discrepancy) -
+ discrepancy[0];
+ const lastIdealRender =
+ events[events.length - 1].args[IDEAL_RENDER_INSTANT_NAME];
+ const firstIdealRender = events[0].args[IDEAL_RENDER_INSTANT_NAME];
+ const idealRenderSpan = lastIdealRender - firstIdealRender;
+
+ const renderingLengthError = discrepancySum / idealRenderSpan;
+
+ return {driftTime, renderingLengthError};
+ }
+
+ /**
+ * Get the smoothness stats from the normalized drift time.
+ *
+ * This method will calculate the smoothness score, along with the percentage
+ * of frames badly out of sync and the percentage of frames out of sync.
+ * To be considered badly out of sync, a frame has to have missed rendering by
+ * at least 2 * VSYNC_DURATION_US.
+ * To be considered out of sync, a frame has to have missed rendering by at
+ * least one VSYNC_DURATION_US.
+ * The smoothness score is a measure of how out of sync the frames are.
+ *
+ * @param {Array.<Number>} driftTimes - See getDriftStats.
+ * @returns {Object.<Number, Number, Number>} - The percentBadlyOutOfSync,
+ * percentOutOfSync and smoothnesScore calculated from the driftTimes array.
+ */
+ function getSmoothnessStats(driftTimes) {
+ const meanDriftTime = tr.b.math.Statistics.mean(driftTimes);
+ const normDriftTimes = driftTimes.map(driftTime =>
+ Math.abs(driftTime - meanDriftTime));
+
+ // How many times is a frame later/earlier than T=2*VSYNC_DURATION_US. Time
+ // is in microseconds
+ const framesSeverelyOutOfSync = normDriftTimes
+ .filter(driftTime => driftTime > 2 * VSYNC_DURATION_US)
+ .length;
+ // How many times is a frame later/earlier than VSYNC_DURATION_US.
+ const framesOutOfSync = normDriftTimes
+ .filter(driftTime => driftTime > VSYNC_DURATION_US)
+ .length;
+
+ const percentBadlyOutOfSync = framesSeverelyOutOfSync /
+ driftTimes.length;
+ const percentOutOfSync = framesOutOfSync / driftTimes.length;
+
+ const framesOutOfSyncOnlyOnce = framesOutOfSync - framesSeverelyOutOfSync;
+
+ // Calculate smoothness metric. From the formula, we can see that smoothness
+ // score can be negative.
+ let smoothnessScore = 1 - (framesOutOfSyncOnlyOnce +
+ SEVERITY * framesSeverelyOutOfSync) / driftTimes.length;
+
+ // Minimum smoothness_score value allowed is zero.
+ if (smoothnessScore < 0) {
+ smoothnessScore = 0;
+ }
+
+ return {
+ framesOutOfSync,
+ framesSeverelyOutOfSync,
+ percentBadlyOutOfSync,
+ percentOutOfSync,
+ smoothnessScore
+ };
+ }
+
+ return {
+ webrtcRenderingMetric,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/metrics/webrtc/webrtc_rendering_metric_test.html b/chromium/third_party/catapult/tracing/tracing/metrics/webrtc/webrtc_rendering_metric_test.html
new file mode 100644
index 00000000000..17505faa9d7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/metrics/webrtc/webrtc_rendering_metric_test.html
@@ -0,0 +1,456 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/metrics/webrtc/webrtc_rendering_metric.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const DISPLAY_HERTZ = 60.0;
+ const VSYNC_DURATION_US = 1e6 / DISPLAY_HERTZ;
+
+ /**
+ * @param {Array.<Number>} pair - An array of length 2, from which a valid
+ * WebMediaPlayerMS event will be generated.
+ * @returns {event} A valid WebMediaPlayerMS event where the Ideal Render
+ * Instant is the first element and the Actual Render Begin is the second
+ * element.
+ */
+ function eventFromPair(pair) {
+ return {
+ title: 'UpdateCurrentFrame',
+ start: pair[1],
+ duration: 1,
+ args: {
+ 'Ideal Render Instant': pair[0],
+ 'Actual Render Begin': pair[1],
+ 'Actual Render End': 0,
+ 'Serial': 0,
+ }
+ };
+ }
+
+ /**
+ * @param {Array.<Number>} driftTimes - An array with the desired driftTimes.
+ * @return {Array.<event>} An array of events such that the drift times
+ * computed by webrtcRenderingMetric is the same as driftTimes.
+ */
+ function eventsFromDriftTimes(driftTimes) {
+ const pairs = [];
+ for (let i = 1; i <= driftTimes.length; ++i) {
+ pairs.push([i, i + driftTimes[i - 1]]);
+ }
+ return pairs.map(eventFromPair);
+ }
+
+ /**
+ * @param {Array.<Number>} normDriftTimes - To decide if a frame is out of
+ * sync or badly out of sync, we use the normalized drift times, that we get
+ * by subtracting the mean from each entry of the drift times array. The sum
+ * of the normDriftTimes must equal 0.
+ * @return {Array.<event>) An array of events such that when we normalize the
+ * drift times computed by webrtcRenderingMetric, we get the normDriftTimes
+ * array.
+ */
+ function eventsFromNormDriftTimes(normDriftTimes) {
+ /* Let
+ * B[i] = normDriftTimes[i]
+ * A[i] = driftTimes[i] be the array we want to find.
+ *
+ * We require that:
+ * sum(B[i]) = 0
+ *
+ * Then
+ * B[i] = A[i] - mean(A)
+ * => B[i] - B[0] = A[i] - mean(A) - A[0] + mean(A)
+ * => B[i] - B[0] = A[i] - A[0]
+ * => A[i] = B[i] - B[0] + A[0]
+ *
+ * We can fix A[0] to any number we want.
+ *
+ * Let's make sure that the array A we found generates the array B when
+ * normalized:
+ * A[i] - mean(A)
+ * = A[i] - sum(A[j]) / n
+ * = B[i] - B[0] + A[0] - sum(B[j] - B[0] + A[0]) / n
+ * = B[i] - B[0] + A[0] - (sum(B[j]) - n B[0] / n + n A[0] / n)
+ * = B[i] - B[0] + A[0] - sum(B[j]) + B[0] - A[0]
+ * = B[i] - sum(B[j])
+ * = B[i] since we require sum(B[j]) = 0
+ */
+ const driftTimes = [10000];
+ for (let i = 1; i < normDriftTimes.length; ++i) {
+ driftTimes.push(normDriftTimes[i] - normDriftTimes[0] + driftTimes[0]);
+ }
+ return eventsFromDriftTimes(driftTimes);
+ }
+
+ /**
+ * @param {Array.<Array.<Number>>} frameDistribution - An array of pairs
+ * encoding the source to output distribution. That is an array where each
+ * [ticks, count] entry says that there are 'count' frames that are displayed
+ * 'ticks' times.
+ * @returns {Array.<events>} The events that give rise to the given
+ * frameDistribution.
+ */
+ function eventsFromFrameDistribution(frameDistribution) {
+ let frameId = 0;
+ const pairs = [];
+ for (const [ticks, count] of frameDistribution) {
+ // We need 'count' runs, each run consisting of 'ticks' repeated elements.
+ for (let i = 0; i < count; ++i) {
+ frameId += 1;
+ for (let j = 0; j < ticks; ++j) {
+ // Frames are decided by the Ideal Render Instant.
+ pairs.push([frameId, 0]);
+ }
+ }
+ }
+ return pairs.map(eventFromPair);
+ }
+
+ function newModel(fakeEvents) {
+ function customizeModelCallback(model) {
+ const rendererProcess = model.getOrCreateProcess(1);
+ const mainThread = rendererProcess.getOrCreateThread(2);
+ mainThread.name = 'Compositor';
+ for (const event of fakeEvents) {
+ mainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(event));
+ }
+ }
+ return tr.c.TestUtils.newModelWithEvents([], {customizeModelCallback});
+ }
+
+ function runWebrtcRenderingMetric(fakeEvents) {
+ const histograms = new tr.v.HistogramSet();
+ const model = newModel(fakeEvents);
+ tr.metrics.webrtc.webrtcRenderingMetric(histograms, model);
+ return histograms;
+ }
+
+ test('frameDistribution', function() {
+ // These numbers don't mean anything, we just want to make sure we can
+ // recover them after running webrtcRenderingMetric.
+ const frameDistribution = [[10, 3], [5, 15], [3, 146], [1, 546], [2, 10]];
+ const frameHist = new tr.v.Histogram('', tr.b.Unit.byName.unitlessNumber);
+ for (const [ticks, count] of frameDistribution) {
+ for (let i = 0; i < count; ++i) {
+ frameHist.addSample(ticks);
+ }
+ }
+ const fakeEvents = eventsFromFrameDistribution(frameDistribution);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ // We don't have access to the values stored in the histogram, so we check
+ // for equality in the summary statistics.
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_frame_distribution');
+ assert.strictEqual(hist.sum, frameHist.sum);
+ assert.strictEqual(hist.numValues, frameHist.numValues);
+ assert.strictEqual(hist.running.min, frameHist.running.min);
+ assert.strictEqual(hist.running.max, frameHist.running.max);
+ assert.closeTo(hist.standardDeviation, frameHist.standardDeviation, 1e-2);
+ });
+
+ test('driftTime', function() {
+ // These numbers don't mean anything. We just want to make sure we can
+ // recover them after running the metric.
+ const fakeDriftTimes = [16700, 17640, 15000, 24470, 16700, 14399, 17675];
+ const fakeEvents = eventsFromDriftTimes(fakeDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ // We don't have access to the values stored in the histogram, so we check
+ // for equality in the summary statistics.
+ const hist = histograms.getHistogramNamed('WebRTCRendering_drift_time');
+ assert.strictEqual(hist.sum, tr.b.math.Statistics.sum(fakeDriftTimes));
+ assert.strictEqual(hist.numValues, fakeDriftTimes.length);
+ assert.strictEqual(hist.running.min,
+ tr.b.math.Statistics.min(fakeDriftTimes));
+ assert.strictEqual(hist.running.max,
+ tr.b.math.Statistics.max(fakeDriftTimes));
+ assert.closeTo(hist.standardDeviation,
+ tr.b.math.Statistics.stddev(fakeDriftTimes), 1e-2);
+ });
+
+ test('framesBadlyOutOfSyncPerfect', function() {
+ // None of these will exceed the threshold for badly out of sync events,
+ // which is about 33 333.
+ const normDriftTimes = [-16700, 17640, 15000, -17640, -15000, 16700];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_frames_badly_out_of_sync');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 0);
+ });
+
+ test('framesBadylOutOfSync', function() {
+ // Only 34 000 will exceed the threshold for badly out of sync events,
+ // which is about 33 333.
+ const normDriftTimes = [-34000, 10000, 10000, 10000, 4000];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_frames_badly_out_of_sync');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 1);
+ });
+
+ test('framesOutOfSyncPerfect', function() {
+ // None of these will exceed the threshold for badly out of sync, which is
+ // about 16 667.
+ const normDriftTimes = [-16600, 15640, 15000, -15640, -15000, 16600];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_frames_out_of_sync');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 0);
+ });
+
+ test('framesOutOfSync', function() {
+ // Only 17000 will exceed the threshold for badly out of sync, which is
+ // about 16 667.
+ const normDriftTimes = [-17000, 5000, 5000, 5000, 2000];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_frames_out_of_sync');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 1);
+ });
+
+ test('percentBadlyOutOfSyncPerfect', function() {
+ // None of these will exceed the threshold for badly out of sync events,
+ // which is about 33 333.
+ const normDriftTimes = [-16700, 17640, 15000, -17640, -15000, 16700];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_percent_badly_out_of_sync');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 0);
+ });
+
+ test('percentBadylOutOfSync', function() {
+ // Only 34 000 will exceed the threshold for badly out of sync events,
+ // which is about 33 333.
+ const normDriftTimes = [-34000, 10000, 10000, 10000, 4000];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_percent_badly_out_of_sync');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, .2);
+ });
+
+ test('percentOutOfSyncPerfect', function() {
+ // None of these will exceed the threshold for badly out of sync, which is
+ // about 16 667.
+ const normDriftTimes = [-16600, 15640, 15000, -15640, -15000, 16600];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_percent_out_of_sync');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 0);
+ });
+
+ test('percentOutOfSync', function() {
+ // Only 17000 will exceed the threshold for badly out of sync, which is
+ // about 16 667.
+ const normDriftTimes = [-17000, 5000, 5000, 5000, 2000];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_percent_out_of_sync');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, .2);
+ });
+
+ test('smoothnessScorePerfect', function() {
+ // None of these will exceed the threshold for badly out of sync, which is
+ // about 16 667, so the smoothnessScore wil be perfect.
+ const normDriftTimes = [-16600, 15640, 15000, -15640, -15000, 16600];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_smoothness_score');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 1);
+ });
+
+ test('smoothnessScore', function() {
+ // One will exceed the threshold for frames badly out of sync (33 333) and
+ // another two the threshold for frames out of sync (16 667). So the
+ // smoothness score is
+ // 1 - (frames out of sync + 3 * frames badly out of sync) / n
+ // = 1 - (2 + 3) / 5 = 0
+ const normDriftTimes = [-17000, 34000, -17000, -10000, 10000];
+ assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
+ const fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_smoothness_score');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 0);
+ });
+
+ test('fpsPerfect', function() {
+ // Every frame is displayed once. This is a perfect FPS of 60.
+ const frameDistribution = [[1, 10]];
+ const fakeEvents = eventsFromFrameDistribution(frameDistribution);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist = histograms.getHistogramNamed('WebRTCRendering_fps');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 60);
+ });
+
+ test('fps', function() {
+ // Every frame is displayed 15 times. This means an FPS of 4.
+ const frameDistribution = [[15, 10]];
+ const fakeEvents = eventsFromFrameDistribution(frameDistribution);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist = histograms.getHistogramNamed('WebRTCRendering_fps');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 4);
+ });
+
+ test('frozenFramesCountPerfect', function() {
+ // 10 frames are displayed one time, and 10 frames are displayed twice.
+ // This means no frames exceed the threshold of 6, and so no frames are
+ // considered frozen.
+ const frameDistribution = [[1, 10], [2, 10]];
+ const fakeEvents = eventsFromFrameDistribution(frameDistribution);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_frozen_frames_count');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 0);
+ });
+
+ test('frozenFramesCount', function() {
+ // 82 frames are displayed 1 time, 5 frames are displayed 2 times,
+ // and 1 frame is displayed 6 times.
+ // Only the drame displayed 6 times satisfies the threshold of 6. Since the
+ // first appearance is not considered frozen, there are 5 frozen frames.
+ const frameDistribution = [[1, 82], [2, 5], [6, 1]];
+ const fakeEvents = eventsFromFrameDistribution(frameDistribution);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_frozen_frames_count');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 5);
+ });
+
+ test('freezingScorePerfect', function() {
+ // Every frame is displayed 1 times. This means a perfect freezing score of
+ // 100.
+ const frameDistribution = [[1, 10]];
+ const fakeEvents = eventsFromFrameDistribution(frameDistribution);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist = histograms.getHistogramNamed('WebRTCRendering_freezing_score');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, 1);
+ });
+
+ test('freezingScore', function() {
+ // 82 frames are displayed 1 time, 5 frames are displayed 2 times,
+ // and 1 frame is displayed 8 times.
+ // This means that the total number of frames displayed is
+ // 82 * 1 + 5 * 2 + 1 * 8 = 100
+ // And the freezing score is
+ // 1 - 82 / 100 * weight[0]
+ // - 5 / 100 * weight[1]
+ // - 1 / 100 * weight[7]
+ // = 1 - .82 * 0 since weight[0] = 0
+ // - .05 * 0 since weight[1] = 0 too
+ // - .01 * 15 since weight[7] = 15
+ // = 1 - .15 = .85
+ // See frozenPenaltyWeight for information on the weights and
+ // addFreezingScore for the definition of the freezingScore.
+ const frameDistribution = [[1, 82], [2, 5], [8, 1]];
+ const fakeEvents = eventsFromFrameDistribution(frameDistribution);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist = histograms.getHistogramNamed('WebRTCRendering_freezing_score');
+ assert.strictEqual(hist.numValues, 1);
+ assert.strictEqual(hist.running.mean, .85);
+ });
+
+ test('renderingLengthErrorPerfect', function() {
+ const fakePairs = [];
+ for (let i = 1; i < 10; ++i) {
+ // Each frame's Ideal Render Instant is exactly VSYNC_DURATION_US after
+ // the previous one, so that the rendering length error is 0.
+ fakePairs.push([VSYNC_DURATION_US * i, 0]);
+ }
+ const fakeEvents = fakePairs.map(eventFromPair);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_rendering_length_error');
+ assert.strictEqual(hist.numValues, 1);
+ assert.closeTo(hist.running.mean, 0, 1e-3);
+ });
+
+ test('renderingLengthError', function() {
+ const errors = [1000, 3000, 0, 5000, 0, 2000];
+ const fakePairs = [[1, 0]];
+ for (let i = 0; i < errors.length; ++i) {
+ // Each frame's Ideal Render Instant is close to VSYNC_DURATION_US after
+ // the previous one, but with a known delay.
+ fakePairs.push([fakePairs[i][0] + VSYNC_DURATION_US + errors[i], 0]);
+ }
+
+ // The rendering length error is then the sum of the errors, normalized by
+ // the span between the first and the last Ideal Render Instants.
+ const idealRenderSpan = fakePairs[fakePairs.length - 1][0] -
+ fakePairs[0][0];
+ const expectedRenderingLengthError = tr.b.math.Statistics.sum(errors) /
+ idealRenderSpan;
+
+ const fakeEvents = fakePairs.map(eventFromPair);
+ const histograms = runWebrtcRenderingMetric(fakeEvents);
+
+ const hist =
+ histograms.getHistogramNamed('WebRTCRendering_rendering_length_error');
+ assert.strictEqual(hist.numValues, 1);
+ assert.closeTo(hist.running.mean, expectedRenderingLengthError, 1e-3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/activity.html b/chromium/third_party/catapult/tracing/tracing/model/activity.html
new file mode 100644
index 00000000000..2db257c7e06
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/activity.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/color_scheme.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Class representing a user activity that is running
+ * in the process.
+ * On the Android platform, activities are mapped to Android Activities
+ * running in the foreground of the process.
+ * On Windows/OS X this could for example represent
+ * the currently active window of the process.
+ */
+tr.exportTo('tr.model', function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ /**
+ * @constructor
+ * @param {String} name Name of the activity
+ * @param {String} category Category of the activities
+ * @param {String} range The time range where the activity was running
+ * @param {String} args Additional arguments
+ */
+ function Activity(name, category, range, args) {
+ tr.model.TimedEvent.call(this, range.min);
+ this.title = name;
+ this.category = category;
+ this.colorId = ColorScheme.getColorIdForGeneralPurposeString(name);
+ this.duration = range.duration;
+ this.args = args;
+ this.name = name;
+ }
+
+ Activity.prototype = {
+ __proto__: tr.model.TimedEvent.prototype,
+
+ shiftTimestampsForward(amount) {
+ this.start += amount;
+ },
+
+ addBoundsToRange(range) {
+ range.addValue(this.start);
+ range.addValue(this.end);
+ }
+ };
+ return {
+ Activity,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/alert.html b/chromium/third_party/catapult/tracing/tracing/model/alert.html
new file mode 100644
index 00000000000..a8955caec93
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/alert.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/event_info.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ function Alert(info, start, opt_associatedEvents, opt_args) {
+ tr.model.TimedEvent.call(this, start);
+ this.info = info;
+ this.args = opt_args || {};
+ this.associatedEvents = new tr.model.EventSet(opt_associatedEvents);
+ this.associatedEvents.forEach(function(event) {
+ event.addAssociatedAlert(this);
+ }, this);
+ }
+
+ Alert.prototype = {
+ __proto__: tr.model.TimedEvent.prototype,
+
+ get title() {
+ return this.info.title;
+ },
+
+ get colorId() {
+ return this.info.colorId;
+ },
+
+ get userFriendlyName() {
+ return 'Alert ' + this.title + ' at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.start);
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ Alert,
+ {
+ name: 'alert',
+ pluralName: 'alerts'
+ });
+
+ return {
+ Alert,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/annotation.html b/chromium/third_party/catapult/tracing/tracing/model/annotation.html
new file mode 100644
index 00000000000..9a3c1a726ba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/annotation.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+<link rel="import" href="/tracing/base/guid.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * Annotation is a base class that represents all annotation objects that
+ * can be drawn on the timeline.
+ *
+ * @constructor
+ */
+ function Annotation() {
+ this.guid_ = tr.b.GUID.allocateSimple();
+ this.view_ = undefined;
+ }
+
+ Annotation.fromDictIfPossible = function(args) {
+ if (args.typeName === undefined) {
+ throw new Error('Missing typeName argument');
+ }
+
+ const typeInfo = Annotation.findTypeInfoMatching(function(typeInfo) {
+ return typeInfo.metadata.typeName === args.typeName;
+ });
+
+ if (typeInfo === undefined) return undefined;
+
+ return typeInfo.constructor.fromDict(args);
+ };
+
+ Annotation.fromDict = function() {
+ throw new Error('Not implemented');
+ };
+
+ Annotation.prototype = {
+ get guid() {
+ return this.guid_;
+ },
+
+ // Invoked by trace model when this annotation is removed.
+ onRemove() {
+ },
+
+ toDict() {
+ throw new Error('Not implemented');
+ },
+
+ getOrCreateView(viewport) {
+ if (!this.view_) {
+ this.view_ = this.createView_(viewport);
+ }
+ return this.view_;
+ },
+
+ createView_() {
+ throw new Error('Not implemented');
+ }
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b. BASIC_REGISTRY_MODE);
+ tr.b.decorateExtensionRegistry(Annotation, options);
+
+ Annotation.addEventListener('will-register', function(e) {
+ if (!e.typeInfo.constructor.hasOwnProperty('fromDict')) {
+ throw new Error('Must have fromDict method');
+ }
+
+ if (!e.typeInfo.metadata.typeName) {
+ throw new Error('Registered Annotations must provide typeName');
+ }
+ });
+
+ return {
+ Annotation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/annotation_test.html b/chromium/third_party/catapult/tracing/tracing/model/annotation_test.html
new file mode 100644
index 00000000000..f0d38843a3f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/annotation_test.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/comment_box_annotation.html">
+<link rel="import" href="/tracing/model/location.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/rect_annotation.html">
+<link rel="import" href="/tracing/model/x_marker_annotation.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('rectAnnotation', function() {
+ const fakeYComponents1 = [{stableId: '1.2', yPercentOffset: 0.3}];
+ const fakeYComponents2 = [{stableId: '1.2', yPercentOffset: 0.9}];
+ const start = new tr.model.Location(50, fakeYComponents1);
+ const end = new tr.model.Location(100, fakeYComponents2);
+ const rectAnnotation = new tr.model.RectAnnotation(start, end);
+ assert.strictEqual(rectAnnotation.startLocation, start);
+ assert.strictEqual(rectAnnotation.endLocation, end);
+ });
+
+ test('xMarkerAnnotation', function() {
+ const xMarkerAnnotation = new tr.model.XMarkerAnnotation(90);
+ assert.strictEqual(xMarkerAnnotation.timestamp, 90);
+ });
+
+ test('commentBoxAnnotation', function() {
+ const fakeYComponents = [{stableId: '1.2', yPercentOffset: 0.5}];
+ const location = new tr.model.Location(120, fakeYComponents);
+ const text = 'abc';
+ const commentBoxAnnotation =
+ new tr.model.CommentBoxAnnotation(location, text);
+ assert.strictEqual(commentBoxAnnotation.location, location);
+ assert.strictEqual(commentBoxAnnotation.text, text);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/async_slice.html b/chromium/third_party/catapult/tracing/tracing/model/async_slice.html
new file mode 100644
index 00000000000..9e395ab4cb7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/async_slice.html
@@ -0,0 +1,169 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the AsyncSlice class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * A AsyncSlice represents an interval of time during which an
+ * asynchronous operation is in progress. An AsyncSlice consumes no CPU time
+ * itself and so is only associated with Threads at its start and end point.
+ *
+ * @constructor
+ */
+ function AsyncSlice(category, title, colorId, start, args, duration,
+ opt_isTopLevel, opt_cpuStart, opt_cpuDuration,
+ opt_argsStripped) {
+ tr.model.TimedEvent.call(this, start);
+
+ this.category = category || '';
+ // We keep the original title from the trace file in originalTitle since
+ // some sub-classes, e.g. NetAsyncSlice, change the title field.
+ this.originalTitle = title;
+ this.title = title;
+ this.colorId = colorId;
+ this.args = args;
+ this.startStackFrame = undefined;
+ this.endStackFrame = undefined;
+ this.didNotFinish = false;
+ this.important = false;
+ this.subSlices = [];
+ this.parentContainer_ = undefined;
+
+ this.id = undefined;
+ this.startThread = undefined;
+ this.endThread = undefined;
+ this.cpuStart = undefined;
+ this.cpuDuration = undefined;
+ this.argsStripped = false;
+
+ this.startStackFrame = undefined;
+ this.endStackFrame = undefined;
+
+ this.duration = duration;
+
+ // isTopLevel is set at import because only NESTABLE_ASYNC events might not
+ // be topLevel. All legacy async events are toplevel by definition.
+ this.isTopLevel = (opt_isTopLevel === true);
+
+ if (opt_cpuStart !== undefined) {
+ this.cpuStart = opt_cpuStart;
+ }
+
+ if (opt_cpuDuration !== undefined) {
+ this.cpuDuration = opt_cpuDuration;
+ }
+
+ if (opt_argsStripped !== undefined) {
+ this.argsStripped = opt_argsStripped;
+ }
+ }
+
+ AsyncSlice.prototype = {
+ __proto__: tr.model.TimedEvent.prototype,
+
+ get analysisTypeName() {
+ return this.title;
+ },
+
+ get parentContainer() {
+ return this.parentContainer_;
+ },
+
+ set parentContainer(parentContainer) {
+ this.parentContainer_ = parentContainer;
+ for (let i = 0; i < this.subSlices.length; i++) {
+ const subSlice = this.subSlices[i];
+ if (subSlice.parentContainer === undefined) {
+ subSlice.parentContainer = parentContainer;
+ }
+ }
+ },
+
+ get viewSubGroupTitle() {
+ return this.title;
+ },
+
+ // Certain AsyncSlices can provide a grouping key to group a set of
+ // independent tracks, while grouping by |viewSubGroupTitle| puts slices
+ // into a single (maybe multi-row but single) track.
+ get viewSubGroupGroupingKey() {
+ return undefined;
+ },
+
+ get userFriendlyName() {
+ return 'Async slice ' + this.title + ' at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.start);
+ },
+
+ get stableId() {
+ const parentAsyncSliceGroup = this.parentContainer.asyncSliceGroup;
+ return parentAsyncSliceGroup.stableId + '.' +
+ parentAsyncSliceGroup.slices.indexOf(this);
+ },
+
+ * findTopmostSlicesRelativeToThisSlice(eventPredicate, opt_this) {
+ if (eventPredicate(this)) {
+ yield this;
+ return;
+ }
+ for (const s of this.subSlices) {
+ yield* s.findTopmostSlicesRelativeToThisSlice(eventPredicate);
+ }
+ },
+
+ findDescendentSlice(targetTitle) {
+ if (!this.subSlices) return undefined;
+
+ for (let i = 0; i < this.subSlices.length; i++) {
+ if (this.subSlices[i].title === targetTitle) {
+ return this.subSlices[i];
+ }
+ const slice = this.subSlices[i].findDescendentSlice(targetTitle);
+ if (slice) return slice;
+ }
+ return undefined;
+ },
+
+ * enumerateAllDescendents() {
+ for (const slice of this.subSlices) {
+ yield slice;
+ }
+ for (const slice of this.subSlices) {
+ // Slices might contain sub-events different from AsyncSlice.
+ // We don't go any deeper in that case.
+ if (slice.enumerateAllDescendents !== undefined) {
+ yield* slice.enumerateAllDescendents();
+ }
+ }
+ },
+
+ compareTo(that) {
+ return this.title.localeCompare(that.title);
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ AsyncSlice,
+ {
+ name: 'asyncSlice',
+ pluralName: 'asyncSlices'
+ });
+
+
+ return {
+ AsyncSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/async_slice_group.html b/chromium/third_party/catapult/tracing/tracing/model/async_slice_group.html
new file mode 100644
index 00000000000..249e6396667
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/async_slice_group.html
@@ -0,0 +1,211 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/async_slice.html">
+<link rel="import" href="/tracing/model/event_container.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the AsyncSliceGroup class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * Group of AsyncSlices associated with a thread or an upper-level
+ * AsyncSliceGroup. Thread can have number of AsyncSliceGroups and these
+ * groups can have nested groups too. No further nested levels are allowed.
+ */
+ class AsyncSliceGroup extends tr.model.EventContainer {
+ /**
+ * @param {Thread} parentContainer Thread on which async slices start.
+ * @param {String} opt_name Optional name (no IDs please) for settings key.
+ */
+ constructor(parentContainer, opt_name) {
+ super();
+ this.parentContainer_ = parentContainer;
+ this.name_ = opt_name;
+ this.slices = [];
+ this.viewSubGroups_ = undefined;
+
+ // Default values for the root group.
+ // Nested groups will get these values reassigned.
+ this.nestedLevel_ = 0;
+ this.hasNestedSubGroups_ = true;
+ this.title_ = undefined;
+ }
+
+ get parentContainer() {
+ return this.parentContainer_;
+ }
+
+ get model() {
+ return this.parentContainer_.parent.model;
+ }
+
+ get stableId() {
+ return this.parentContainer_.stableId + '.AsyncSliceGroup';
+ }
+
+ get title() {
+ // Title isn't defined for the root group (nested level 0) because
+ // slices it contains aren't grouped on that level.
+ // All the nested groups have their title which is:
+ // - |slice.viewSubGroupGroupingKey| if defined (level 1 only), or
+ // - |slice.viewSubGroupTitle| otherwise (most cases).
+ if (this.nested_level_ === 0) {
+ return '<root>';
+ }
+ return this.title_;
+ }
+
+ getSettingsKey() {
+ if (this.name_ === undefined) {
+ return undefined;
+ }
+ const parentKey = this.parentContainer_.getSettingsKey();
+ if (parentKey === undefined) {
+ return undefined;
+ }
+ return parentKey + '.' + this.name_;
+ }
+
+ /**
+ * Helper function that pushes the provided slice onto the slices array.
+ */
+ push(slice) {
+ if (this.viewSubGroups_ !== undefined) {
+ throw new Error(
+ 'No new slices are allowed when view sub-groups already formed.');
+ }
+ slice.parentContainer = this.parentContainer;
+ this.slices.push(slice);
+ return slice;
+ }
+
+ /**
+ * @return {Number} The number of slices in this group.
+ */
+ get length() {
+ return this.slices.length;
+ }
+
+ /**
+ * Shifts all the timestamps inside this group forward by the amount
+ * specified, including all nested subSlices if there are any.
+ */
+ shiftTimestampsForward(amount) {
+ for (const slice of this.childEvents()) {
+ slice.start += amount;
+ }
+ }
+
+ /**
+ * Updates the bounds for this group based on the slices it contains.
+ */
+ updateBounds() {
+ this.bounds.reset();
+ for (let i = 0; i < this.slices.length; i++) {
+ this.bounds.addValue(this.slices[i].start);
+ this.bounds.addValue(this.slices[i].end);
+ }
+ }
+
+ /**
+ * Closes any open slices.
+ * All open slices assumed as finished at the end of model's time bounds.
+ */
+ autoCloseOpenSlices() {
+ const maxTimestamp = this.parentContainer_.parent.model.bounds.max;
+ for (const slice of this.childEvents()) {
+ if (slice.didNotFinish) {
+ slice.duration = maxTimestamp - slice.start;
+ }
+ }
+ }
+
+ /**
+ * Get AsyncSlice sub-groups arranged by title and grouping key.
+ *
+ * @return {Array} An array of AsyncSliceGroups where each group has
+ * a title and sub-set of the original slices. Returns an empty array
+ * if group can't be sub-divided.
+ */
+ get viewSubGroups() {
+ // Only 2 nested levels are allowed (see class description).
+ // Also it's always known in advance whether group will be sub-divided or
+ // not (most of them). Root group is always divisible.
+ if (!this.hasNestedSubGroups_ || this.nestedLevel_ === 2) {
+ return [];
+ }
+ if (this.viewSubGroups_ !== undefined) {
+ return this.viewSubGroups_;
+ }
+
+ const subGroupsByTitle = new Map();
+
+ for (const slice of this.slices) {
+ // Group by title by default.
+ let subGroupTitle = slice.viewSubGroupTitle;
+ let hasNestedSubGroups = false;
+
+ // Apply custom grouping rules for special slice classes.
+ if (this.nestedLevel_ === 0 &&
+ slice.viewSubGroupGroupingKey !== undefined) {
+ subGroupTitle = slice.viewSubGroupGroupingKey;
+ hasNestedSubGroups = true;
+ }
+
+ let subGroup = subGroupsByTitle.get(subGroupTitle);
+ if (subGroup === undefined) {
+ let name;
+ if (this.name_ !== undefined) {
+ name = this.name_ + '.' + subGroupTitle;
+ } else {
+ name = subGroupTitle;
+ }
+ subGroup = new AsyncSliceGroup(this.parentContainer_, name);
+ subGroup.title_ = subGroupTitle;
+ subGroup.hasNestedSubGroups_ = hasNestedSubGroups;
+ subGroup.nestedLevel_ = this.nestedLevel_ + 1;
+ subGroupsByTitle.set(subGroupTitle, subGroup);
+ }
+ subGroup.push(slice);
+ }
+
+ this.viewSubGroups_ = Array.from(subGroupsByTitle.values());
+ this.viewSubGroups_.sort((a, b) => a.title.localeCompare(b.title));
+ return this.viewSubGroups_;
+ }
+
+ * findTopmostSlicesInThisContainer(eventPredicate, opt_this) {
+ for (const slice of this.slices) {
+ if (slice.isTopLevel) {
+ yield* slice.findTopmostSlicesRelativeToThisSlice(
+ eventPredicate, opt_this);
+ }
+ }
+ }
+
+ * childEvents() {
+ for (const slice of this.slices) {
+ yield slice;
+ yield* slice.enumerateAllDescendents();
+ }
+ }
+
+ * childEventContainers() {
+ }
+ }
+
+ return {
+ AsyncSliceGroup,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/async_slice_group_test.html b/chromium/third_party/catapult/tracing/tracing/model/async_slice_group_test.html
new file mode 100644
index 00000000000..f996a63f2b9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/async_slice_group_test.html
@@ -0,0 +1,171 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome_config.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Process = tr.model.Process;
+ const Thread = tr.model.Thread;
+ const AsyncSlice = tr.model.AsyncSlice;
+ const AsyncSliceGroup = tr.model.AsyncSliceGroup;
+ const newAsyncSlice = tr.c.TestUtils.newAsyncSlice;
+ const newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx;
+ const newModel = tr.c.TestUtils.newModel;
+
+ test('asyncSliceGroupBounds_Empty', function() {
+ const thread = {};
+ const g = new AsyncSliceGroup(thread);
+ g.updateBounds();
+ assert.isTrue(g.bounds.isEmpty);
+ });
+
+ test('asyncSliceGroupBounds_Basic', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = p1.getOrCreateThread(456);
+ const g = new AsyncSliceGroup(t1);
+ g.push(newAsyncSlice(0, 1, t1, t1));
+ g.push(newAsyncSlice(1, 1.5, t1, t1));
+ assert.strictEqual(g.length, 2);
+ g.updateBounds();
+ assert.strictEqual(g.bounds.min, 0);
+ assert.strictEqual(g.bounds.max, 2.5);
+ });
+
+ test('asyncSliceGroupChildEvents', function() {
+ const t1 = {}; // Fake thread.
+ const g = new AsyncSliceGroup(t1);
+ const sl1 = newAsyncSlice(0, 1, t1, t1);
+ const sl2 = newAsyncSlice(1, 3, t1, t1);
+ const sl2sub1 = newAsyncSlice(1, 2, t1, t1);
+ sl2.subSlices.push(sl2sub1);
+ const sl2sub1sub1 = newAsyncSlice(2, 1, t1, t1);
+ sl2sub1.subSlices.push(sl2sub1sub1);
+ const sl2sub2 = newAsyncSlice(3, 1, t1, t1);
+ sl2.subSlices.push(sl2sub2);
+ g.push(sl1);
+ g.push(sl2);
+
+ assert.sameMembers(
+ Array.from(g.childEvents()), [sl1, sl2, sl2sub1, sl2sub1sub1, sl2sub2]);
+ });
+
+ test('asyncSliceGroupShiftTimestamps', function() {
+ const t1 = {}; // Fake thread.
+ const g = new AsyncSliceGroup(t1);
+ const sl1 = newAsyncSlice(1, 2, t1, t1);
+ const sl2 = newAsyncSlice(3, 4, t1, t1);
+ const sl2sub1 = newAsyncSlice(3.5, 2, t1, t1);
+ sl2.subSlices.push(sl2sub1);
+ const sl2sub1sub1 = newAsyncSlice(4, 0.5, t1, t1);
+ sl2sub1.subSlices.push(sl2sub1sub1);
+ g.push(sl1);
+ g.push(sl2);
+
+ g.updateBounds();
+ assert.strictEqual(g.bounds.min, 1);
+ assert.strictEqual(g.bounds.max, 7);
+
+ g.shiftTimestampsForward(1.5);
+ g.updateBounds();
+ assert.strictEqual(g.bounds.min, 2.5);
+ assert.strictEqual(g.bounds.max, 8.5);
+ assert.strictEqual(sl2sub1.start, 5);
+ assert.strictEqual(sl2sub1.duration, 2);
+ assert.strictEqual(sl2sub1sub1.start, 5.5);
+ assert.strictEqual(sl2sub1sub1.duration, 0.5);
+ });
+
+ test('asyncSliceGroupViewSubGroups', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ p1.name = 'Renderer';
+ const t1 = p1.getOrCreateThread(321);
+ t1.name = 'MainThread';
+ const g = new AsyncSliceGroup(t1);
+ g.push(newAsyncSliceEx(
+ { title: 'VeryBusy',
+ start: 0, duration: 1 }));
+ g.push(newAsyncSliceEx(
+ { cat: 'renderer.scheduler',
+ id: ':ptr:0xdeadbeef', title: 'FrameScheduler.Foo',
+ start: 0.5, duration: 0.1 }));
+ g.push(newAsyncSliceEx(
+ { cat: 'renderer.scheduler',
+ id: ':ptr:0xdeadbeef', title: 'FrameScheduler.Bar',
+ start: 0.55, duration: 0.2 }));
+ g.push(newAsyncSliceEx(
+ { cat: 'renderer.scheduler',
+ id: ':ptr:0x1ee7beef', title: 'FrameScheduler.Baz',
+ start: 0.3, duration: 0.3 }));
+ g.push(newAsyncSliceEx(
+ { cat: 'renderer.scheduler',
+ id: ':ptr:0x1ee7beef', title: 'FrameScheduler.Baz',
+ start: 0.7, duration: 0.2 }));
+ g.push(newAsyncSliceEx(
+ { title: 'VeryBusy',
+ start: 1, duration: 1.5 }));
+ g.push(newAsyncSliceEx(
+ { title: 'Loading',
+ start: 0, duration: 5 }));
+ assert.strictEqual(g.length, 7);
+
+ const vsg = g.viewSubGroups;
+ assert.strictEqual(vsg.length, 4);
+ // Groups must be sorted by title.
+ assert.strictEqual(vsg[0].title, 'Frame:ptr:0x1ee7beef');
+ assert.strictEqual(vsg[1].title, 'Frame:ptr:0xdeadbeef');
+ assert.strictEqual(vsg[2].title, 'Loading');
+ assert.strictEqual(vsg[3].title, 'VeryBusy');
+ // Check nested view sub-groups.
+ assert.strictEqual(vsg[2].viewSubGroups.length, 0);
+ assert.strictEqual(vsg[3].viewSubGroups.length, 0);
+ const wf1vsg = vsg[0].viewSubGroups;
+ assert.strictEqual(wf1vsg.length, 1);
+ assert.strictEqual(wf1vsg[0].title, 'Baz');
+ assert.strictEqual(wf1vsg[0].getSettingsKey(),
+ 'processes.Renderer.MainThread.Frame:ptr:0x1ee7beef.Baz');
+ const wf2vsg = vsg[1].viewSubGroups;
+ assert.strictEqual(wf2vsg.length, 2);
+ assert.strictEqual(wf2vsg[0].title, 'Bar');
+ assert.strictEqual(wf2vsg[0].getSettingsKey(),
+ 'processes.Renderer.MainThread.Frame:ptr:0xdeadbeef.Bar');
+ assert.strictEqual(wf2vsg[1].title, 'Foo');
+ assert.strictEqual(wf2vsg[1].getSettingsKey(),
+ 'processes.Renderer.MainThread.Frame:ptr:0xdeadbeef.Foo');
+ });
+
+ test('asyncSliceGroupStableId', function() {
+ const model = new tr.Model();
+ const process = model.getOrCreateProcess(123);
+ const thread = process.getOrCreateThread(456);
+ const group = new AsyncSliceGroup(thread);
+
+ assert.strictEqual(process.stableId, 123);
+ assert.strictEqual(thread.stableId, '123.456');
+ assert.strictEqual(group.stableId, '123.456.AsyncSliceGroup');
+ });
+
+ test('asyncSliceParentContainerSetAtPush', function() {
+ const m = newModel(function(m) {
+ m.process = m.getOrCreateProcess(123);
+ m.thread = m.process.getOrCreateThread(456);
+ m.group = new AsyncSliceGroup(m.thread);
+
+ m.sA = m.group.push(newAsyncSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ });
+
+ assert.deepEqual(m.sA.parentContainer, m.thread);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/async_slice_test.html b/chromium/third_party/catapult/tracing/tracing/model/async_slice_test.html
new file mode 100644
index 00000000000..1de8493035e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/async_slice_test.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+ const Process = tr.model.Process;
+ const Thread = tr.model.Thread;
+ const newAsyncSlice = tr.c.TestUtils.newAsyncSlice;
+ const newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx;
+ const newFakeThread = tr.c.TestUtils.newFakeThread;
+
+ test('stableId', function() {
+ const thread = newFakeThread();
+ const group = thread.asyncSliceGroup;
+
+ const sA = group.push(newAsyncSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.push(newAsyncSliceEx(
+ { title: 'sB', start: 10.0, duration: 20.0 }));
+ const sC = group.push(newAsyncSliceEx(
+ { title: 'sC', start: 20.0, duration: 30.0 }));
+
+ assert.strictEqual(group.stableId + '.0', sA.stableId);
+ assert.strictEqual(group.stableId + '.1', sB.stableId);
+ assert.strictEqual(group.stableId + '.2', sC.stableId);
+ });
+
+ test('setParentContainerForSubSlices', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const asyncSlice = newAsyncSlice(0, 10, t1, t1);
+ const subSlice1 = newAsyncSlice(1, 5, t1, t1);
+ const subSlice2 = newAsyncSlice(6, 9, t1, t1);
+ const subSlice3 = newAsyncSlice(2, 3, t1, t1);
+ subSlice1.subSlices.push(subSlice3);
+ asyncSlice.subSlices.push(subSlice1);
+ asyncSlice.subSlices.push(subSlice2);
+ asyncSlice.parentContainer = t1;
+ assert.strictEqual(asyncSlice.subSlices.length, 2);
+ assert.strictEqual(subSlice1.subSlices.length, 1);
+ assert.deepEqual(asyncSlice.parentContainer, t1);
+ assert.deepEqual(subSlice1.parentContainer, t1);
+ assert.deepEqual(subSlice2.parentContainer, t1);
+ assert.deepEqual(subSlice3.parentContainer, t1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html b/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html
new file mode 100644
index 00000000000..cb9a30bad79
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager.html
@@ -0,0 +1,467 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const ClockDomainId = {
+ BATTOR: 'BATTOR',
+
+ // NOTE: Exists for backwards compatibility with old Chrome traces which
+ // didn't explicitly specify the clock being used.
+ UNKNOWN_CHROME_LEGACY: 'UNKNOWN_CHROME_LEGACY',
+
+ LINUX_CLOCK_MONOTONIC: 'LINUX_CLOCK_MONOTONIC',
+ LINUX_FTRACE_GLOBAL: 'LINUX_FTRACE_GLOBAL',
+ MAC_MACH_ABSOLUTE_TIME: 'MAC_MACH_ABSOLUTE_TIME',
+ WIN_ROLLOVER_PROTECTED_TIME_GET_TIME:
+ 'WIN_ROLLOVER_PROTECTED_TIME_GET_TIME',
+ WIN_QPC: 'WIN_QPC',
+
+ // 'TELEMETRY' and 'SYSTRACE' aren't really clock domains because they
+ // actually can use one of several clock domains, just like Chrome. However,
+ // because there's a chance that they are running off of the same clock as
+ // Chrome (e.g. LINUX_CLOCK_MONOTONIC) but on a separate device (i.e. on a
+ // a host computer with Chrome running on an attached phone), there's a
+ // chance that Chrome and the controller will erroneously get put into
+ // the same clock domain. The solution for this is that clock domains should
+ // actually be some (unique_device_id, clock_id) tuple. For now, though,
+ // we'll hack around this by putting Telemetry into its own clock domain.
+ SYSTRACE: 'SYSTRACE',
+ TELEMETRY: 'TELEMETRY'
+ };
+
+ const POSSIBLE_CHROME_CLOCK_DOMAINS = new Set([
+ ClockDomainId.UNKNOWN_CHROME_LEGACY,
+ ClockDomainId.LINUX_CLOCK_MONOTONIC,
+ ClockDomainId.MAC_MACH_ABSOLUTE_TIME,
+ ClockDomainId.WIN_ROLLOVER_PROTECTED_TIME_GET_TIME,
+ ClockDomainId.WIN_QPC
+ ]);
+
+ // The number of milliseconds above which the BattOr sync is no longer
+ // considered "fast", and it's more accurate to use the sync start timestamp
+ // instead of the normal sync timestamp due to a bug in the Chrome serial code
+ // making serial reads too slow.
+ const BATTOR_FAST_SYNC_THRESHOLD_MS = 3;
+
+ /**
+ * A ClockSyncManager holds clock sync markers and uses them to shift
+ * timestamps from agents' clock domains onto the model's clock domain.
+ *
+ * In this context, a "clock domain" is a single perspective on the passage
+ * of time. A single computer can have multiple clock domains because it
+ * can have multiple methods of retrieving a timestamp (e.g.
+ * clock_gettime(CLOCK_MONOTONIC) and clock_gettime(CLOCK_REALTIME) on Linux).
+ * Another common reason for multiple clock domains within a single trace
+ * is that traces can span devices (e.g. a laptop collecting a Chrome trace
+ * can have its power consumption recorded by a second device and the two
+ * traces can be viewed alongside each other).
+ *
+ * For more information on how to synchronize multiple time domains using this
+ * method, see: http://bit.ly/1OVkqju.
+ *
+ * @constructor
+ */
+ function ClockSyncManager() {
+ // A set of all domains seen by the ClockSyncManager.
+ this.domainsSeen_ = new Set();
+ this.markersBySyncId_ = new Map();
+ // transformerMapByDomainId_[fromDomainId][toDomainId] returns the function
+ // that converts timestamps in the "from" domain to timestamps in the "to"
+ // domain.
+ this.transformerMapByDomainId_ = {};
+ }
+
+ ClockSyncManager.prototype = {
+ /**
+ * Adds a clock sync marker to the list of known markers.
+ *
+ * @param {string} domainId The clock domain that the marker is in.
+ * @param {string} syncId The identifier shared by both sides of the clock
+ * sync marker.
+ * @param {number} startTs The time (in ms) at which the sync started.
+ * @param {number=} opt_endTs The time (in ms) at which the sync ended. If
+ * unspecified, it's assumed to be the same as the start,
+ * indicating an instantaneous sync.
+ */
+ addClockSyncMarker(domainId, syncId, startTs, opt_endTs) {
+ this.onDomainSeen_(domainId);
+
+ if (Object.values(ClockDomainId).indexOf(domainId) < 0) {
+ throw new Error('"' + domainId + '" is not in the list of known ' +
+ 'clock domain IDs.');
+ }
+
+ if (this.modelDomainId_) {
+ throw new Error('Cannot add new clock sync markers after getting ' +
+ 'a model time transformer.');
+ }
+
+ const marker = new ClockSyncMarker(domainId, startTs, opt_endTs);
+
+ if (!this.markersBySyncId_.has(syncId)) {
+ this.markersBySyncId_.set(syncId, [marker]);
+ return;
+ }
+
+ const markers = this.markersBySyncId_.get(syncId);
+
+ if (markers.length === 2) {
+ throw new Error('Clock sync with ID "' + syncId + '" is already ' +
+ 'complete - cannot add a third clock sync marker to it.');
+ }
+
+ if (markers[0].domainId === domainId) {
+ throw new Error('A clock domain cannot sync with itself.');
+ }
+
+ markers.push(marker);
+ this.onSyncCompleted_(markers[0], marker);
+ },
+
+ // TODO(charliea): Remove this once the clockSyncMetric is no longer using
+ // it.
+ get markersBySyncId() {
+ return this.markersBySyncId_;
+ },
+
+ /** @return {Set<String>} The string IDs of the domains seen so far. */
+ get domainsSeen() {
+ return this.domainsSeen_;
+ },
+
+ /**
+ * Returns a function that, given a timestamp in the domain with |domainId|,
+ * returns a timestamp in the model's clock domain.
+ *
+ * NOTE: All clock sync markers should be added before calling this function
+ * for the first time. This is because the first time that this function is
+ * called, a model clock domain is selected. This clock domain must have
+ * syncs connecting it with all other clock domains. If multiple clock
+ * domains are viable candidates, the one with the clock domain ID that is
+ * the first alphabetically is selected.
+ */
+ getModelTimeTransformer(domainId) {
+ this.onDomainSeen_(domainId);
+
+ if (!this.modelDomainId_) {
+ this.selectModelDomainId_();
+ }
+
+ return this.getTimeTransformerRaw_(domainId, this.modelDomainId_).fn;
+ },
+
+ /**
+ * Returns the error associated with the transformation given by
+ * |getModelTimeTransformer(domainId)|.
+ */
+ getTimeTransformerError(fromDomainId, toDomainId) {
+ this.onDomainSeen_(fromDomainId);
+ this.onDomainSeen_(toDomainId);
+ return this.getTimeTransformerRaw_(fromDomainId, toDomainId).error;
+ },
+
+ getTimeTransformerRaw_(fromDomainId, toDomainId) {
+ const transformer =
+ this.getTransformerBetween_(fromDomainId, toDomainId);
+ if (!transformer) {
+ throw new Error('No clock sync markers exist pairing clock domain "' +
+ fromDomainId + '" ' + 'with target clock domain "' +
+ toDomainId + '".');
+ }
+
+ return transformer;
+ },
+
+ /**
+ * Returns a function that, given a timestamp in the "from" domain, returns
+ * a timestamp in the "to" domain.
+ */
+ getTransformerBetween_(fromDomainId, toDomainId) {
+ // Do a breadth-first search from the "from" domain until we reach the
+ // "to" domain.
+ const visitedDomainIds = new Set();
+ // Keep a queue of nodes to visit, starting with the "from" domain.
+ const queue = [{
+ domainId: fromDomainId,
+ transformer: Transformer.IDENTITY
+ }];
+
+ while (queue.length > 0) {
+ // NOTE: Using a priority queue here would theoretically be much more
+ // efficient, but the actual performance difference is negligible given
+ // how few clock domains we have in a trace.
+ queue.sort((domain1, domain2) =>
+ domain1.transformer.error - domain2.transformer.error);
+
+ const current = queue.shift();
+
+ if (current.domainId === toDomainId) {
+ return current.transformer;
+ }
+
+ if (visitedDomainIds.has(current.domainId)) {
+ continue;
+ }
+ visitedDomainIds.add(current.domainId);
+
+ const outgoingTransformers =
+ this.transformerMapByDomainId_[current.domainId];
+
+ if (!outgoingTransformers) continue;
+
+ // Add all nodes that are directly connected to this one to the queue.
+ for (const outgoingDomainId in outgoingTransformers) {
+ // We have two transformers: one to get us from the "from" domain to
+ // the current domain, and another to get us from the current domain
+ // to the next domain. By composing those two transformers, we can
+ // create one that gets us from the "from" domain to the next domain.
+ const toNextDomainTransformer =
+ outgoingTransformers[outgoingDomainId];
+ const toCurrentDomainTransformer = current.transformer;
+
+ queue.push({
+ domainId: outgoingDomainId,
+ transformer: Transformer.compose(
+ toNextDomainTransformer, toCurrentDomainTransformer)
+ });
+ }
+ }
+
+ return undefined;
+ },
+
+ /**
+ * Selects the domain to use as the model domain from among the domains
+ * with registered markers.
+ *
+ * This is necessary because some common domain must be chosen before all
+ * timestamps can be shifted onto the same domain.
+ *
+ * For the time being, preference is given to Chrome clock domains. If no
+ * Chrome clock domain is present, the first clock domain alphabetically
+ * is selected.
+ */
+ selectModelDomainId_() {
+ this.ensureAllDomainsAreConnected_();
+
+ // While we're migrating to the new clock sync system, we have to make
+ // sure to prefer the Chrome clock domain because legacy clock sync
+ // mechanisms assume that's the case.
+ for (const chromeDomainId of POSSIBLE_CHROME_CLOCK_DOMAINS) {
+ if (this.domainsSeen_.has(chromeDomainId)) {
+ this.modelDomainId_ = chromeDomainId;
+ return;
+ }
+ }
+
+ const domainsSeenArray = Array.from(this.domainsSeen_);
+ domainsSeenArray.sort();
+ this.modelDomainId_ = domainsSeenArray[0];
+ },
+
+ /** Throws an error if all domains are not connected. */
+ ensureAllDomainsAreConnected_() {
+ // NOTE: this is a ridiculously inefficient way to do this. Given how few
+ // clock domains we're likely to have, this shouldn't be a problem.
+ let firstDomainId = undefined;
+ for (const domainId of this.domainsSeen_) {
+ if (!firstDomainId) {
+ firstDomainId = domainId;
+ continue;
+ }
+
+ if (!this.getTransformerBetween_(firstDomainId, domainId)) {
+ throw new Error('Unable to select a master clock domain because no ' +
+ 'path can be found from "' + firstDomainId + '" to "' + domainId +
+ '".');
+ }
+ }
+
+ return true;
+ },
+
+ /** Observer called each time that a clock domain is seen. */
+ onDomainSeen_(domainId) {
+ if (domainId === ClockDomainId.UNKNOWN_CHROME_LEGACY &&
+ !this.domainsSeen_.has(ClockDomainId.UNKNOWN_CHROME_LEGACY)) {
+ // UNKNOWN_CHROME_LEGACY was just seen for the first time: collapse it
+ // and the other Chrome clock domains into one.
+ //
+ // This makes sure that we don't have two separate clock sync graphs:
+ // one attached to UNKNOWN_CHROME_LEGACY and the other attached to the
+ // real Chrome clock domain.
+ for (const chromeDomainId of POSSIBLE_CHROME_CLOCK_DOMAINS) {
+ if (chromeDomainId === ClockDomainId.UNKNOWN_CHROME_LEGACY) {
+ continue;
+ }
+
+ this.collapseDomains_(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY, chromeDomainId);
+ }
+ }
+
+ this.domainsSeen_.add(domainId);
+ },
+
+ /**
+ * Observer called when a complete sync is made involving |marker1| and
+ * |marker2|.
+ */
+ onSyncCompleted_(marker1, marker2) {
+ const forwardTransformer = Transformer.fromMarkers(marker1, marker2);
+ const backwardTransformer = Transformer.fromMarkers(marker2, marker1);
+
+ const existingTransformer =
+ this.getOrCreateTransformerMap_(marker1.domainId)[marker2.domainId];
+ if (!existingTransformer ||
+ forwardTransformer.error < existingTransformer.error) {
+ this.getOrCreateTransformerMap_(marker1.domainId)[marker2.domainId] =
+ forwardTransformer;
+ this.getOrCreateTransformerMap_(marker2.domainId)[marker1.domainId] =
+ backwardTransformer;
+ }
+ },
+
+ /** Makes timestamps in the two clock domains interchangeable. */
+ collapseDomains_(domain1Id, domain2Id) {
+ this.getOrCreateTransformerMap_(domain1Id)[domain2Id] =
+ this.getOrCreateTransformerMap_(domain2Id)[domain1Id] =
+ Transformer.IDENTITY;
+ },
+
+ /**
+ * Returns (and creates if it doesn't exist) the transformer map describing
+ * how to transform timestamps between directly connected clock domains.
+ */
+ getOrCreateTransformerMap_(domainId) {
+ if (!this.transformerMapByDomainId_[domainId]) {
+ this.transformerMapByDomainId_[domainId] = {};
+ }
+
+ return this.transformerMapByDomainId_[domainId];
+ },
+
+ /**
+ * @return {string} The clock sync graph represented in the DOT language.
+ * This is useful for debugging incorrect clock sync behavior.
+ */
+ computeDotGraph() {
+ let dotString = 'graph {\n';
+
+ const domainsSeen = [...this.domainsSeen_].sort();
+ for (const domainId of domainsSeen) {
+ dotString += ` ${domainId}[shape=box]\n`;
+ }
+
+ const markersBySyncIdEntries = [...this.markersBySyncId_.entries()].sort(
+ ([syncId1, markers1], [syncId2, markers2]) =>
+ syncId1.localeCompare(syncId2));
+
+ for (const [syncId, markers] of markersBySyncIdEntries) {
+ const sortedMarkers = markers.sort(
+ (a, b) => a.domainId.localeCompare(b.domainId));
+ for (const m of markers) {
+ dotString += ` "${syncId}" -- ${m.domainId} `;
+ dotString += `[label="[${m.startTs}, ${m.endTs}]"]\n`;
+ }
+ }
+
+ dotString += '}';
+
+ return dotString;
+ }
+ };
+
+ /**
+ * A ClockSyncMarker is an internal entity that represents a marker in a
+ * trace log indicating that a clock sync happened at a specified time.
+ *
+ * If no end timestamp argument is specified in the constructor, it's assumed
+ * that the end timestamp is the same as the start (i.e. the clock sync
+ * was instantaneous).
+ */
+ function ClockSyncMarker(domainId, startTs, opt_endTs) {
+ this.domainId = domainId;
+ this.startTs = startTs;
+ this.endTs = opt_endTs === undefined ? startTs : opt_endTs;
+ }
+
+ ClockSyncMarker.prototype = {
+ get duration() { return this.endTs - this.startTs; },
+ get ts() { return this.startTs + this.duration / 2; }
+ };
+
+ /**
+ * A Transformer encapsulates information about how to turn timestamps in one
+ * clock domain into timestamps in another. It also stores additional data
+ * about the maximum error involved in doing so.
+ */
+ function Transformer(fn, error) {
+ this.fn = fn;
+ this.error = error;
+ }
+
+ Transformer.IDENTITY = new Transformer((x => x), 0);
+
+ /**
+ * Given two transformers, creates a third that's a composition of the two.
+ *
+ * @param {function(Number): Number} aToB A function capable of converting a
+ * timestamp from domain A to domain B.
+ * @param {function(Number): Number} bToC A function capable of converting a
+ * timestamp from domain B to domain C.
+ *
+ * @return {function(Number): Number} A function capable of converting a
+ * timestamp from domain A to domain C.
+ */
+ Transformer.compose = function(aToB, bToC) {
+ return new Transformer(
+ (ts) => bToC.fn(aToB.fn(ts)), aToB.error + bToC.error);
+ };
+
+ /**
+ * Returns a function that, given a timestamp in |fromMarker|'s domain,
+ * returns a timestamp in |toMarker|'s domain.
+ */
+ Transformer.fromMarkers = function(fromMarker, toMarker) {
+ let fromTs = fromMarker.ts;
+ let toTs = toMarker.ts;
+
+ // TODO(charliea): Usually, we estimate that the clock sync marker is
+ // issued by the agent exactly in the middle of the controller's start and
+ // end timestamps. However, there's currently a bug in the Chrome serial
+ // code that's making the clock sync ack for BattOr take much longer to
+ // read than it should (by about 8ms). This is causing the above estimate
+ // of the controller's sync timestamp to be off by a substantial enough
+ // amount that it makes traces hard to read. For now, make an exception
+ // for BattOr and just use the controller's start timestamp as the sync
+ // time. In the medium term, we should fix the Chrome serial code in order
+ // to remove this special logic and get an even more accurate estimate.
+ if (fromMarker.domainId === ClockDomainId.BATTOR &&
+ toMarker.duration > BATTOR_FAST_SYNC_THRESHOLD_MS) {
+ toTs = toMarker.startTs;
+ } else if (toMarker.domainId === ClockDomainId.BATTOR &&
+ fromMarker.duration > BATTOR_FAST_SYNC_THRESHOLD_MS) {
+ fromTs = fromMarker.startTs;
+ }
+
+ const tsShift = toTs - fromTs;
+ return new Transformer(
+ (ts) => ts + tsShift, fromMarker.duration + toMarker.duration);
+ };
+
+ return {
+ ClockDomainId,
+ ClockSyncManager,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager_test.html b/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager_test.html
new file mode 100644
index 00000000000..a35049396de
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/clock_sync_manager_test.html
@@ -0,0 +1,471 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/clock_sync_manager.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ClockDomainId = tr.model.ClockDomainId;
+ const ClockSyncManager = tr.model.ClockSyncManager;
+
+ const testOptions = {
+ setUp() {
+ // Add a few testing clock domains to the list of permissible domains.
+ ClockDomainId.DOMAIN_1 = 'DOMAIN1';
+ ClockDomainId.DOMAIN_2 = 'DOMAIN2';
+ ClockDomainId.DOMAIN_3 = 'DOMAIN3';
+ ClockDomainId.DOMAIN_4 = 'DOMAIN4';
+ ClockDomainId.DOMAIN_5 = 'DOMAIN5';
+ },
+
+ tearDown() {
+ delete ClockDomainId.DOMAIN_1;
+ delete ClockDomainId.DOMAIN_2;
+ delete ClockDomainId.DOMAIN_3;
+ delete ClockDomainId.DOMAIN_4;
+ delete ClockDomainId.DOMAIN_5;
+ }
+ };
+
+ test('addClockSyncMarker_throwsWithUnknownDomain', function() {
+ const mgr = new ClockSyncManager();
+
+ assert.throws(function() {
+ mgr.addClockSyncMarker('unknown', 'sync1', 100, 200);
+ }, '"unknown" is not in the list of known clock domain IDs.');
+ }, testOptions);
+
+
+ test('addClockSyncMarker_throwsWhenSelfSyncing', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100, 200);
+
+ assert.throws(function() {
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 200, 300);
+ }, 'A clock domain cannot sync with itself.');
+ }, testOptions);
+
+ test('addClockSyncMarker_throwsWhenAddingThirdSyncMarkerToSync', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 100);
+
+ assert.throws(function() {
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_3, 'sync1', 100);
+ }, 'Clock sync with ID "sync1" is already complete - cannot add a third ' +
+ 'clock sync marker to it.');
+ }, testOptions);
+
+ test('addClockSyncMarker_throwsAfterGetModelTimeTransformer', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 100);
+
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1);
+
+ assert.throws(function() {
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 100);
+ }, 'Cannot add new clock sync markers after getting a model time ' +
+ 'transformer.');
+ }, testOptions);
+
+ test('getModelTimeTransformer_noMarkers', function() {
+ const mgr = new ClockSyncManager();
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 100);
+ }, testOptions);
+
+ test('getModelTimeTransformer_noMarkersSecondDomainThrows', function() {
+ const mgr = new ClockSyncManager();
+
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1);
+
+ assert.throws(function() {
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2);
+ }, 'No clock sync markers exist pairing clock domain "DOMAIN2" with' +
+ ' target clock domain "DOMAIN1".');
+ }, testOptions);
+
+ test('getModelTimeTransformer_noMarkersChromeLegacyFirst', function() {
+ const mgr = new ClockSyncManager();
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.UNKNOWN_CHROME_LEGACY)(100),
+ 100);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.LINUX_CLOCK_MONOTONIC)(100),
+ 100);
+ }, testOptions);
+
+ test('getModelTimeTransformer_noMarkersChromeLegacySecond', function() {
+ const mgr = new ClockSyncManager();
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.LINUX_CLOCK_MONOTONIC)(100),
+ 100);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.UNKNOWN_CHROME_LEGACY)(100),
+ 100);
+ }, testOptions);
+
+ test('getModelTimeTransformer_oneMarker', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 100);
+ }, testOptions);
+
+ test('getModelTimeTransformer_oneCompleteSync', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 350);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(350), 100);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 100);
+ }, testOptions);
+
+ test('getModelTimeTransformer_oneCompleteSyncWithChromeLegacyBefore',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY, 'sync1', 350);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(350),
+ 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.LINUX_CLOCK_MONOTONIC)(350),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_oneCompleteSyncWithChromeLegacyAfter',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(
+ ClockDomainId.LINUX_CLOCK_MONOTONIC, 'sync1', 350);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(350),
+ 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.LINUX_CLOCK_MONOTONIC)(350),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_twoCompleteSyncs', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 350);
+
+ const tx = mgr.getTransformerBetween_('DOMAIN1', 'DOMAIN3');
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync2', 200);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_3, 'sync2', 250);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(350), 100);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 100);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_3)(250), 200);
+ }, testOptions);
+
+ test('getModelTimeTransformer_twoSyncMarkersWithEndTs', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100, 200);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 350);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(350), 150);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(150), 150);
+ }, testOptions);
+
+ test('getModelTimeTransformer_indirectlyConnectedGraph',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 200);
+
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 200);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_3, 'sync2', 300);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 100);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_3)(300), 100);
+ }, testOptions);
+
+ test('getModelTimeTransformer_usesPathWithLeastError', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync2', 100, 150);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 100);
+
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100, 200);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 100);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(125), 125);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(100), 125);
+ }, testOptions);
+
+ // NOTE: This is the same test as the above, but reversed to ensure that
+ // the result didn't stem from some ordering coincidence.
+ test('getModelTimeTransformer_usesPathWithLeastErrorReverse', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100, 150);
+
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync2', 100, 200);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(125), 125);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(100), 125);
+ }, testOptions);
+
+ test('getModelTimeTransformer_battorSyncUsesNormalTimestampWhenFast',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100, 102);
+ mgr.addClockSyncMarker(ClockDomainId.BATTOR, 'sync1', 350);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(101),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_battorSyncUsesChromeLegacyStartTsWhenTooSlow',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100, 200);
+ mgr.addClockSyncMarker(ClockDomainId.BATTOR, 'sync1', 350);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_prefersChromeLegacyDomain', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.UNKNOWN_CHROME_LEGACY, 'sync1', 350);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100),
+ 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.UNKNOWN_CHROME_LEGACY)(350),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_collapsesUnknownChromeLegacyDomainLinux',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY, 'sync1', 350);
+
+ mgr.addClockSyncMarker(
+ ClockDomainId.LINUX_CLOCK_MONOTONIC, 'sync2', 350);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 450);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(450), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.LINUX_CLOCK_MONOTONIC)(350),
+ 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(350),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_collapsesUnknownChromeLegacyDomainMac',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY, 'sync1', 350);
+
+ mgr.addClockSyncMarker(
+ ClockDomainId.MAC_MACH_ABSOLUTE_TIME, 'sync2', 350);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 450);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(450), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.MAC_MACH_ABSOLUTE_TIME)(350),
+ 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(350),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_collapsesUnknownChromeLegacyDomainWinLoRes',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY, 'sync1', 350);
+
+ mgr.addClockSyncMarker(
+ ClockDomainId.WIN_ROLLOVER_PROTECTED_TIME_GET_TIME, 'sync2', 350);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 450);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(450), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.WIN_ROLLOVER_PROTECTED_TIME_GET_TIME)(350),
+ 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(350),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_collapsesChromeLegacyDomainWinHiRes',
+ function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY, 'sync1', 350);
+
+ mgr.addClockSyncMarker(ClockDomainId.WIN_QPC, 'sync2', 350);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 450);
+
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_1)(100), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_2)(450), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(ClockDomainId.WIN_QPC)(350), 350);
+ assert.strictEqual(
+ mgr.getModelTimeTransformer(
+ ClockDomainId.UNKNOWN_CHROME_LEGACY)(350),
+ 350);
+ }, testOptions);
+
+ test('getModelTimeTransformer_throwsWithTwoDistinctGraphs', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 100);
+
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync2', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_3, 'sync2', 100);
+
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_4, 'sync3', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_5, 'sync3', 100);
+
+ assert.throws(function() {
+ mgr.getModelTimeTransformer(ClockDomainId.DOMAIN_5);
+ }, 'Unable to select a master clock domain because no path can be found ' +
+ 'from "DOMAIN1" to "DOMAIN4"');
+ }, testOptions);
+
+ test('computeDotGraph_noMarkers', function() {
+ const mgr = new ClockSyncManager();
+
+ assert.strictEqual(mgr.computeDotGraph(), [
+ 'graph {',
+ '}'
+ ].join('\n'));
+ }, testOptions);
+
+ test('computeDotGraph_oneMarker', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+
+ assert.strictEqual(mgr.computeDotGraph(), [
+ 'graph {',
+ ' DOMAIN1[shape=box]',
+ ' "sync1" -- DOMAIN1 [label="[100, 100]"]',
+ '}'
+ ].join('\n'));
+ }, testOptions);
+
+ test('computeDotGraph_oneCompleteSync', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 350);
+
+ assert.strictEqual(mgr.computeDotGraph(), [
+ 'graph {',
+ ' DOMAIN1[shape=box]',
+ ' DOMAIN2[shape=box]',
+ ' "sync1" -- DOMAIN1 [label="[100, 100]"]',
+ ' "sync1" -- DOMAIN2 [label="[350, 350]"]',
+ '}'
+ ].join('\n'));
+ }, testOptions);
+
+ test('computeDotGraph_twoCompleteSyncs', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync2', 0, 50);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_3, 'sync2', 400);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 350);
+
+ assert.strictEqual(mgr.computeDotGraph(), [
+ 'graph {',
+ ' DOMAIN1[shape=box]',
+ ' DOMAIN2[shape=box]',
+ ' DOMAIN3[shape=box]',
+ ' "sync1" -- DOMAIN1 [label="[100, 100]"]',
+ ' "sync1" -- DOMAIN2 [label="[350, 350]"]',
+ ' "sync2" -- DOMAIN2 [label="[0, 50]"]',
+ ' "sync2" -- DOMAIN3 [label="[400, 400]"]',
+ '}'
+ ].join('\n'));
+ }, testOptions);
+
+ test('computeDotGraph_oneCompleteSyncOneIncompleteSync', function() {
+ const mgr = new ClockSyncManager();
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_1, 'sync1', 100);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_2, 'sync1', 350);
+ mgr.addClockSyncMarker(ClockDomainId.DOMAIN_3, 'sync2', 450);
+
+ assert.strictEqual(mgr.computeDotGraph(), [
+ 'graph {',
+ ' DOMAIN1[shape=box]',
+ ' DOMAIN2[shape=box]',
+ ' DOMAIN3[shape=box]',
+ ' "sync1" -- DOMAIN1 [label="[100, 100]"]',
+ ' "sync1" -- DOMAIN2 [label="[350, 350]"]',
+ ' "sync2" -- DOMAIN3 [label="[450, 450]"]',
+ '}'
+ ].join('\n'));
+ }, testOptions);
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/comment_box_annotation.html b/chromium/third_party/catapult/tracing/tracing/model/comment_box_annotation.html
new file mode 100644
index 00000000000..16d2cb098bc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/comment_box_annotation.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/annotation.html">
+<link rel="import" href="/tracing/model/location.html">
+<link rel="import" href="/tracing/model/rect_annotation.html">
+<link rel="import" href="/tracing/ui/annotations/comment_box_annotation_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ function CommentBoxAnnotation(location, text) {
+ tr.model.Annotation.apply(this, arguments);
+
+ this.location = location;
+ this.text = text;
+ }
+
+ CommentBoxAnnotation.fromDict = function(dict) {
+ const args = dict.args;
+ const location =
+ new tr.model.Location(args.location.xWorld, args.location.yComponents);
+ return new tr.model.CommentBoxAnnotation(location, args.text);
+ };
+
+ CommentBoxAnnotation.prototype = {
+ __proto__: tr.model.Annotation.prototype,
+
+ onRemove() {
+ this.view_.removeTextArea();
+ },
+
+ toDict() {
+ return {
+ typeName: 'comment_box',
+ args: {
+ text: this.text,
+ location: this.location.toDict()
+ }
+ };
+ },
+
+ createView_(viewport) {
+ return new tr.ui.annotations.CommentBoxAnnotationView(viewport, this);
+ }
+ };
+
+ tr.model.Annotation.register(
+ CommentBoxAnnotation, {typeName: 'comment_box'});
+
+ return {
+ CommentBoxAnnotation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/compound_event_selection_state.html b/chromium/third_party/catapult/tracing/tracing/model/compound_event_selection_state.html
new file mode 100644
index 00000000000..cefc2247095
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/compound_event_selection_state.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * Indicates how much of a compound-event is selected [if any].
+ *
+ * The CompoundEventSelectionState enum is used with events that are
+ * directly selectable, but also have associated events, too, that can be
+ * selected. In this situation, there are a variety of different
+ * selected states other than just "yes, no". This enum encodes those
+ * various possible states.
+ */
+ const CompoundEventSelectionState = {
+ // Basic bit states.
+ NOT_SELECTED: 0,
+ EVENT_SELECTED: 0x1,
+ SOME_ASSOCIATED_EVENTS_SELECTED: 0x2,
+ ALL_ASSOCIATED_EVENTS_SELECTED: 0x4,
+
+ // Common combinations.
+ EVENT_AND_SOME_ASSOCIATED_SELECTED: 0x1 | 0x2,
+ EVENT_AND_ALL_ASSOCIATED_SELECTED: 0x1 | 0x4
+ };
+
+ return {
+ CompoundEventSelectionState,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/constants.html b/chromium/third_party/catapult/tracing/tracing/model/constants.html
new file mode 100644
index 00000000000..0bf134ec7fe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/constants.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ return {
+ // Since the PID of the browser process is not known to the child processes,
+ // we let them use "pid_ref = -1" to reference an object created in the
+ // browser process.
+ BROWSER_PROCESS_PID_REF: -1,
+
+ // The default scope of object events, when not explicitly specified.
+ OBJECT_DEFAULT_SCOPE: 'ptr',
+
+ // Event phases that have process-local IDs, unless a global ID is
+ // explicitly specified.
+ LOCAL_ID_PHASES: new Set(['N', 'D', 'O', '(', ')'])
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/container_memory_dump.html b/chromium/third_party/catapult/tracing/tracing/model/container_memory_dump.html
new file mode 100644
index 00000000000..1078b764862
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/container_memory_dump.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the ContainerMemoryDump class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * The ContainerMemoryDump represents an abstract container memory dump.
+ * @constructor
+ */
+ function ContainerMemoryDump(start) {
+ tr.model.TimedEvent.call(this, start);
+
+ this.levelOfDetail = undefined;
+
+ this.memoryAllocatorDumps_ = undefined;
+ this.memoryAllocatorDumpsByFullName_ = undefined;
+ }
+
+ /**
+ * Memory dump level of detail. See base::trace_event::MemoryDumpLevelOfDetail
+ * in the Chromium repository.
+ *
+ * @enum
+ */
+ ContainerMemoryDump.LevelOfDetail = {
+ BACKGROUND: 0,
+ LIGHT: 1,
+ DETAILED: 2
+ };
+
+ ContainerMemoryDump.prototype = {
+ __proto__: tr.model.TimedEvent.prototype,
+
+ shiftTimestampsForward(amount) {
+ this.start += amount;
+ },
+
+ get memoryAllocatorDumps() {
+ return this.memoryAllocatorDumps_;
+ },
+
+ set memoryAllocatorDumps(memoryAllocatorDumps) {
+ this.memoryAllocatorDumps_ = memoryAllocatorDumps;
+ this.forceRebuildingMemoryAllocatorDumpByFullNameIndex();
+ },
+
+ getMemoryAllocatorDumpByFullName(fullName) {
+ if (this.memoryAllocatorDumps_ === undefined) return undefined;
+
+ // Lazily generate the index if necessary.
+ if (this.memoryAllocatorDumpsByFullName_ === undefined) {
+ const index = {};
+ function addDumpsToIndex(dumps) {
+ dumps.forEach(function(dump) {
+ index[dump.fullName] = dump;
+ addDumpsToIndex(dump.children);
+ });
+ }
+ addDumpsToIndex(this.memoryAllocatorDumps_);
+ this.memoryAllocatorDumpsByFullName_ = index;
+ }
+
+ return this.memoryAllocatorDumpsByFullName_[fullName];
+ },
+
+ forceRebuildingMemoryAllocatorDumpByFullNameIndex() {
+ // Clear the index and generate it lazily.
+ this.memoryAllocatorDumpsByFullName_ = undefined;
+ },
+
+ iterateRootAllocatorDumps(fn, opt_this) {
+ if (this.memoryAllocatorDumps === undefined) return;
+ this.memoryAllocatorDumps.forEach(fn, opt_this || this);
+ }
+ };
+
+ return {
+ ContainerMemoryDump,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/container_memory_dump_test.html b/chromium/third_party/catapult/tracing/tracing/model/container_memory_dump_test.html
new file mode 100644
index 00000000000..a6b2009c96e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/container_memory_dump_test.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ContainerMemoryDump = tr.model.ContainerMemoryDump;
+ const MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+ const Scalar = tr.b.Scalar;
+ const unitlessNumber_smallerIsBetter =
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const addChildDump = tr.model.MemoryDumpTestUtils.addChildDump;
+
+ test('memoryAllocatorDumps_undefined', function() {
+ const md = new ContainerMemoryDump(42);
+
+ assert.isUndefined(md.memoryAllocatorDumps);
+ assert.isUndefined(md.getMemoryAllocatorDumpByFullName('malloc'));
+ });
+
+ test('memoryAllocatorDumps_zero', function() {
+ const md = new ContainerMemoryDump(42);
+ md.memoryAllocatorDumps = [];
+
+ assert.lengthOf(md.memoryAllocatorDumps, 0);
+ assert.isUndefined(md.getMemoryAllocatorDumpByFullName('malloc'));
+ });
+
+ test('memoryAllocatorDumps_flat', function() {
+ const md = new ContainerMemoryDump(42);
+
+ const oilpanDump = newAllocatorDump(md, 'oilpan', {
+ size: 1024,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 7),
+ inner_size: 768
+ });
+ const v8Dump = newAllocatorDump(md, 'v8', {
+ size: 2048,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 15),
+ inner_size: 1999
+ });
+ md.memoryAllocatorDumps = [oilpanDump, v8Dump];
+
+ assert.lengthOf(md.memoryAllocatorDumps, 2);
+ assert.strictEqual(md.memoryAllocatorDumps[0], oilpanDump);
+ assert.strictEqual(md.memoryAllocatorDumps[1], v8Dump);
+
+ assert.strictEqual(
+ md.getMemoryAllocatorDumpByFullName('oilpan'), oilpanDump);
+ assert.strictEqual(md.getMemoryAllocatorDumpByFullName('v8'), v8Dump);
+ assert.isUndefined(md.getMemoryAllocatorDumpByFullName('malloc'));
+ });
+
+ test('memoryAllocatorDumps_nested', function() {
+ const md = new ContainerMemoryDump(42);
+
+ const oilpanDump = newAllocatorDump(md, 'oilpan', {
+ size: 1024,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 7),
+ inner_size: 768
+ });
+
+ const oilpanBucket1Dump = addChildDump(oilpanDump, 'bucket1', {
+ size: 512,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 3),
+ inner_size: 256
+ });
+
+ const oilpanBucket2Dump = addChildDump(oilpanDump, 'bucket2', {
+ size: 512,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 4),
+ inner_size: 512
+ });
+
+ const oilpanBucket2StringsDump = addChildDump(
+ oilpanBucket2Dump, 'strings', {
+ size: 512,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 4),
+ inner_size: 512
+ });
+
+ const v8Dump = newAllocatorDump(md, 'v8', {
+ size: 2048,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 15),
+ inner_size: 1999
+ });
+
+ md.memoryAllocatorDumps = [oilpanDump, v8Dump];
+
+ assert.lengthOf(md.memoryAllocatorDumps, 2);
+ assert.strictEqual(md.memoryAllocatorDumps[0], oilpanDump);
+ assert.strictEqual(md.memoryAllocatorDumps[1], v8Dump);
+
+ assert.strictEqual(
+ md.getMemoryAllocatorDumpByFullName('oilpan'), oilpanDump);
+ assert.strictEqual(md.getMemoryAllocatorDumpByFullName('oilpan/bucket1'),
+ oilpanBucket1Dump);
+ assert.strictEqual(md.getMemoryAllocatorDumpByFullName('oilpan/bucket2'),
+ oilpanBucket2Dump);
+ assert.strictEqual(
+ md.getMemoryAllocatorDumpByFullName('oilpan/bucket2/strings'),
+ oilpanBucket2StringsDump);
+ assert.strictEqual(md.getMemoryAllocatorDumpByFullName('v8'), v8Dump);
+ assert.isUndefined(md.getMemoryAllocatorDumpByFullName('malloc'));
+ });
+
+ test('iterateRootAllocatorDumps', function() {
+ const containerDump = new ContainerMemoryDump(42);
+
+ const oilpanDump = new MemoryAllocatorDump(containerDump, 'oilpan');
+ const v8Dump = new MemoryAllocatorDump(containerDump, 'v8');
+ addChildDump(v8Dump, 'heaps');
+
+ containerDump.memoryAllocatorDumps = [oilpanDump, v8Dump];
+
+ const visitedAllocatorDumps = [];
+ containerDump.iterateRootAllocatorDumps(
+ function(dump) { this.visitedAllocatorDumps.push(dump); },
+ { visitedAllocatorDumps });
+ assert.sameMembers(visitedAllocatorDumps, [oilpanDump, v8Dump]);
+ });
+
+ test('forceRebuildingMemoryAllocatorDumpByFullNameIndex', function() {
+ const containerDump = new ContainerMemoryDump(42);
+
+ const v8Dump = new MemoryAllocatorDump(containerDump, 'v8');
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps');
+ const v8HeapSmallDump = addChildDump(v8HeapsDump, 'S');
+
+ // Setting the memory allocator dumps should update the index properly.
+ containerDump.memoryAllocatorDumps = [v8Dump];
+ assert.strictEqual(
+ containerDump.getMemoryAllocatorDumpByFullName('v8'), v8Dump);
+ assert.strictEqual(containerDump.getMemoryAllocatorDumpByFullName(
+ 'v8/heaps'), v8HeapsDump);
+ assert.strictEqual(containerDump.getMemoryAllocatorDumpByFullName(
+ 'v8/heaps/S'), v8HeapSmallDump);
+
+ // Add a second grandchild (v8/heaps/L).
+ const v8HeapLargeDump = addChildDump(v8HeapsDump, 'L');
+
+ // Setting the memory allocator dumps again should update the index
+ // properly again.
+ containerDump.memoryAllocatorDumps = [v8Dump];
+ assert.strictEqual(
+ containerDump.getMemoryAllocatorDumpByFullName('v8'), v8Dump);
+ assert.strictEqual(containerDump.getMemoryAllocatorDumpByFullName(
+ 'v8/heaps'), v8HeapsDump);
+ assert.strictEqual(containerDump.getMemoryAllocatorDumpByFullName(
+ 'v8/heaps/S'), v8HeapSmallDump);
+ assert.strictEqual(containerDump.getMemoryAllocatorDumpByFullName(
+ 'v8/heaps/L'), v8HeapLargeDump);
+
+ // Remove the first grandchild (v8/heaps/S).
+ v8HeapsDump.children.splice(0, 1);
+
+ // Force rebuilding the index and check that it was updated properly.
+ containerDump.forceRebuildingMemoryAllocatorDumpByFullNameIndex();
+ assert.strictEqual(
+ containerDump.getMemoryAllocatorDumpByFullName('v8'), v8Dump);
+ assert.strictEqual(containerDump.getMemoryAllocatorDumpByFullName(
+ 'v8/heaps'), v8HeapsDump);
+ assert.isUndefined(containerDump.getMemoryAllocatorDumpByFullName(
+ 'v8/heaps/S'));
+ assert.strictEqual(containerDump.getMemoryAllocatorDumpByFullName(
+ 'v8/heaps/L'), v8HeapLargeDump);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/counter.html b/chromium/third_party/catapult/tracing/tracing/model/counter.html
new file mode 100644
index 00000000000..5b276984fd2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/counter.html
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+<link rel="import" href="/tracing/model/event_container.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * A container holding all series of a given type of measurement.
+ *
+ * As an example, if we're measuring the throughput of data sent over several
+ * USB connections, the throughput of each cable might be added as a separate
+ * series to a single counter.
+ *
+ * @constructor
+ * @extends {EventContainer}
+ */
+ function Counter(parent, id, category, name) {
+ tr.model.EventContainer.call(this);
+
+ this.parent_ = parent;
+ this.id_ = id;
+ this.category_ = category || '';
+ this.name_ = name;
+
+ this.series_ = [];
+ this.totals = [];
+ }
+
+ Counter.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ get parent() {
+ return this.parent_;
+ },
+
+ get id() {
+ return this.id_;
+ },
+
+ get category() {
+ return this.category_;
+ },
+
+ get name() {
+ return this.name_;
+ },
+
+ * childEvents() {
+ },
+
+ * childEventContainers() {
+ yield* this.series;
+ },
+
+ set timestamps(arg) {
+ throw new Error('Bad counter API. No cookie.');
+ },
+
+ set seriesNames(arg) {
+ throw new Error('Bad counter API. No cookie.');
+ },
+
+ set seriesColors(arg) {
+ throw new Error('Bad counter API. No cookie.');
+ },
+
+ set samples(arg) {
+ throw new Error('Bad counter API. No cookie.');
+ },
+
+ addSeries(series) {
+ series.counter = this;
+ series.seriesIndex = this.series_.length;
+ this.series_.push(series);
+ return series;
+ },
+
+ getSeries(idx) {
+ return this.series_[idx];
+ },
+
+ get series() {
+ return this.series_;
+ },
+
+ get numSeries() {
+ return this.series_.length;
+ },
+
+ get numSamples() {
+ if (this.series_.length === 0) return 0;
+ return this.series_[0].length;
+ },
+
+ get timestamps() {
+ if (this.series_.length === 0) return [];
+ return this.series_[0].timestamps;
+ },
+
+ /**
+ * Obtains min, max, avg, values, start, and end for different series for
+ * a given counter
+ * getSampleStatistics([0,1])
+ * The statistics objects that this returns are an array of objects, one
+ * object for each series for the counter in the form:
+ * {min: minVal, max: maxVal, avg: avgVal, start: startVal, end: endVal}
+ *
+ * @param {Array.<Number>} Indices to summarize.
+ * @return {Object} An array of statistics. Each element in the array
+ * has data for one of the series in the selected counter.
+ */
+ getSampleStatistics(sampleIndices) {
+ sampleIndices.sort();
+
+ const ret = [];
+ this.series_.forEach(function(series) {
+ ret.push(series.getStatistics(sampleIndices));
+ });
+ return ret;
+ },
+
+ /**
+ * Shifts all the timestamps inside this counter forward by the amount
+ * specified.
+ */
+ shiftTimestampsForward(amount) {
+ for (let i = 0; i < this.series_.length; ++i) {
+ this.series_[i].shiftTimestampsForward(amount);
+ }
+ },
+
+ /**
+ * Updates the bounds for this counter based on the samples it contains.
+ */
+ updateBounds() {
+ this.totals = [];
+ this.maxTotal = 0;
+ this.bounds.reset();
+
+ if (this.series_.length === 0) return;
+
+ const firstSeries = this.series_[0];
+ const lastSeries = this.series_[this.series_.length - 1];
+
+ this.bounds.addValue(firstSeries.getTimestamp(0));
+ this.bounds.addValue(lastSeries.getTimestamp(lastSeries.length - 1));
+
+ const numSeries = this.numSeries;
+ this.maxTotal = -Infinity;
+
+ // Sum the samples at each timestamp.
+ // Note, this assumes that all series have all timestamps.
+ for (let i = 0; i < firstSeries.length; ++i) {
+ let total = 0;
+ this.series_.forEach(function(series) {
+ total += series.getSample(i).value;
+ this.totals.push(total);
+ }.bind(this));
+
+ this.maxTotal = Math.max(total, this.maxTotal);
+ }
+ }
+ };
+
+ /**
+ * Comparison between counters that orders by parent.compareTo, then name.
+ */
+ Counter.compare = function(x, y) {
+ let tmp = x.parent.compareTo(y.parent);
+ if (tmp !== 0) return tmp;
+ tmp = x.name.localeCompare(y.name);
+ if (tmp === 0) return x.tid - y.tid;
+ return tmp;
+ };
+
+ return {
+ Counter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/counter_sample.html b/chromium/third_party/catapult/tracing/tracing/model/counter_sample.html
new file mode 100644
index 00000000000..3da38c349c7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/counter_sample.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/event_registry.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * The value of a given measurement at a given time.
+ *
+ * As an example, if we're measuring the throughput of data sent over a USB
+ * connection, each counter sample might represent the instantaneous
+ * throughput of the connection at a given time.
+ *
+ * @constructor
+ * @extends {Event}
+ */
+ function CounterSample(series, timestamp, value) {
+ tr.model.Event.call(this);
+ this.series_ = series;
+ this.timestamp_ = timestamp;
+ this.value_ = value;
+ }
+
+ CounterSample.groupByTimestamp = function(samples) {
+ const samplesByTimestamp = tr.b.groupIntoMap(samples, s => s.timestamp);
+ const timestamps = Array.from(samplesByTimestamp.keys());
+ timestamps.sort();
+ const groups = [];
+ for (const ts of timestamps) {
+ const group = samplesByTimestamp.get(ts);
+ group.sort((x, y) => x.series.seriesIndex - y.series.seriesIndex);
+ groups.push(group);
+ }
+ return groups;
+ };
+
+ CounterSample.prototype = {
+ __proto__: tr.model.Event.prototype,
+
+ get series() {
+ return this.series_;
+ },
+
+ get timestamp() {
+ return this.timestamp_;
+ },
+
+ get value() {
+ return this.value_;
+ },
+
+ set timestamp(timestamp) {
+ this.timestamp_ = timestamp;
+ },
+
+ addBoundsToRange(range) {
+ range.addValue(this.timestamp);
+ },
+
+ getSampleIndex() {
+ return tr.b.findLowIndexInSortedArray(
+ this.series.timestamps,
+ function(x) { return x; },
+ this.timestamp_);
+ },
+
+ get userFriendlyName() {
+ return 'Counter sample from ' + this.series_.title + ' at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.timestamp);
+ }
+ };
+
+
+ tr.model.EventRegistry.register(
+ CounterSample,
+ {
+ name: 'counterSample',
+ pluralName: 'counterSamples'
+ });
+
+ return {
+ CounterSample,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/counter_sample_test.html b/chromium/third_party/catapult/tracing/tracing/model/counter_sample_test.html
new file mode 100644
index 00000000000..d4ad8fcb0d4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/counter_sample_test.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/counter.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Counter = tr.model.Counter;
+ const CounterSeries = tr.model.CounterSeries;
+ const CounterSample = tr.model.CounterSample;
+
+ test('groupByTimestamp', function() {
+ const counter = new Counter();
+ const slice0 = counter.addSeries(new CounterSeries('x', 0));
+ const slice1 = counter.addSeries(new CounterSeries('y', 1));
+
+ const slice0Sample0 = slice0.addCounterSample(0, 100);
+ const slice0Sample1 = slice1.addCounterSample(0, 200);
+ const slice1Sample0 = slice0.addCounterSample(1, 100);
+ const slice1Sample1 = slice1.addCounterSample(1, 200);
+
+ const groups = CounterSample.groupByTimestamp([slice0Sample1, slice0Sample0,
+ slice1Sample1, slice1Sample0]);
+ assert.strictEqual(groups.length, 2);
+ assert.deepEqual(groups[0], [slice0Sample0, slice0Sample1]);
+ assert.deepEqual(groups[1], [slice1Sample0, slice1Sample1]);
+ });
+
+ test('getSampleIndex', function() {
+ const ctr = new Counter(null, 0, '', 'myCounter');
+ const slice0 = new CounterSeries('a', 0);
+ ctr.addSeries(slice0);
+
+ const slice0Sample0 = slice0.addCounterSample(0, 0);
+ const slice0Sample1 = slice0.addCounterSample(1, 100);
+ assert.strictEqual(slice0Sample0.getSampleIndex(), 0);
+ assert.strictEqual(slice0Sample1.getSampleIndex(), 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/counter_series.html b/chromium/third_party/catapult/tracing/tracing/model/counter_series.html
new file mode 100644
index 00000000000..b2ab8f4fe58
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/counter_series.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/counter_sample.html">
+<link rel="import" href="/tracing/model/event_container.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const CounterSample = tr.model.CounterSample;
+
+ /**
+ * A container holding all samples of a given measurement over time.
+ *
+ * As an example, a counter series might measure the throughput of data sent
+ * over a USB connection, with each sample representing the instantaneous
+ * throughput of the connection.
+ *
+ * @constructor
+ * @extends {EventContainer}
+ */
+ function CounterSeries(name, color) {
+ tr.model.EventContainer.call(this);
+
+ this.name_ = name;
+ this.color_ = color;
+
+ this.timestamps_ = [];
+ this.samples_ = [];
+
+ // Set by counter.addSeries
+ this.counter = undefined;
+ this.seriesIndex = undefined;
+ }
+
+ CounterSeries.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ get length() {
+ return this.timestamps_.length;
+ },
+
+ get name() {
+ return this.name_;
+ },
+
+ get color() {
+ return this.color_;
+ },
+
+ get samples() {
+ return this.samples_;
+ },
+
+ get timestamps() {
+ return this.timestamps_;
+ },
+
+ getSample(idx) {
+ return this.samples_[idx];
+ },
+
+ getTimestamp(idx) {
+ return this.timestamps_[idx];
+ },
+
+ addCounterSample(ts, val) {
+ const sample = new CounterSample(this, ts, val);
+ this.addSample(sample);
+ return sample;
+ },
+
+ addSample(sample) {
+ this.timestamps_.push(sample.timestamp);
+ this.samples_.push(sample);
+ },
+
+ getStatistics(sampleIndices) {
+ let sum = 0;
+ let min = Number.MAX_VALUE;
+ let max = -Number.MAX_VALUE;
+
+ for (let i = 0; i < sampleIndices.length; ++i) {
+ const sample = this.getSample(sampleIndices[i]).value;
+
+ sum += sample;
+ min = Math.min(sample, min);
+ max = Math.max(sample, max);
+ }
+
+ return {
+ min,
+ max,
+ avg: (sum / sampleIndices.length),
+ start: this.getSample(sampleIndices[0]).value,
+ end: this.getSample(sampleIndices.length - 1).value
+ };
+ },
+
+ shiftTimestampsForward(amount) {
+ for (let i = 0; i < this.timestamps_.length; ++i) {
+ this.timestamps_[i] += amount;
+ this.samples_[i].timestamp = this.timestamps_[i];
+ }
+ },
+
+ * childEvents() {
+ yield* this.samples_;
+ },
+
+ * childEventContainers() {
+ }
+ };
+
+ return {
+ CounterSeries,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/counter_test.html b/chromium/third_party/catapult/tracing/tracing/model/counter_test.html
new file mode 100644
index 00000000000..5c64e7c273d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/counter_test.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/counter.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/process.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Counter = tr.model.Counter;
+ const CounterSeries = tr.model.CounterSeries;
+ const CounterSample = tr.model.CounterSample;
+
+ const createCounterWithTwoSeries = function() {
+ const ctr = new Counter(null, 0, '', 'myCounter');
+ const aSeries = new CounterSeries('a', 0);
+ const bSeries = new CounterSeries('b', 0);
+ ctr.addSeries(aSeries);
+ ctr.addSeries(bSeries);
+
+ aSeries.addCounterSample(0, 5);
+ aSeries.addCounterSample(1, 6);
+ aSeries.addCounterSample(2, 5);
+ aSeries.addCounterSample(3, 7);
+
+ bSeries.addCounterSample(0, 10);
+ bSeries.addCounterSample(1, 15);
+ bSeries.addCounterSample(2, 12);
+ bSeries.addCounterSample(3, 16);
+
+ return ctr;
+ };
+
+ test('getSampleStatisticsWithSingleSelection', function() {
+ const ctr = createCounterWithTwoSeries();
+ const ret = ctr.getSampleStatistics([0]);
+
+ assert.strictEqual(ret[0].min, 5);
+ assert.strictEqual(ret[0].max, 5);
+ assert.strictEqual(ret[0].avg, 5);
+ assert.strictEqual(ret[0].start, 5);
+ assert.strictEqual(ret[0].end, 5);
+
+ assert.strictEqual(ret[1].min, 10);
+ assert.strictEqual(ret[1].max, 10);
+ assert.strictEqual(ret[1].avg, 10);
+ assert.strictEqual(ret[1].start, 10);
+ assert.strictEqual(ret[1].end, 10);
+ });
+
+ test('getSampleStatisticsWithMultipleSelections', function() {
+ const ctr = createCounterWithTwoSeries();
+ const ret = ctr.getSampleStatistics([0, 1]);
+
+ assert.strictEqual(ret[0].min, 5);
+ assert.strictEqual(ret[0].max, 6);
+ assert.strictEqual(ret[0].avg, (5 + 6) / 2);
+ assert.strictEqual(ret[0].start, 5);
+ assert.strictEqual(ret[0].end, 6);
+
+ assert.strictEqual(ret[1].min, 10);
+ assert.strictEqual(ret[1].max, 15);
+ assert.strictEqual(ret[1].avg, (10 + 15) / 2);
+ assert.strictEqual(ret[1].start, 10);
+ assert.strictEqual(ret[1].end, 15);
+ });
+
+ test('getSampleStatisticsWithOutofOrderIndices', function() {
+ const ctr = createCounterWithTwoSeries();
+ const ret = ctr.getSampleStatistics([1, 0]);
+
+ assert.strictEqual(ret[0].min, 5);
+ assert.strictEqual(ret[0].max, 6);
+ assert.strictEqual(ret[0].avg, (5 + 6) / 2);
+ assert.strictEqual(ret[0].start, 5);
+ assert.strictEqual(ret[0].end, 6);
+
+ assert.strictEqual(ret[1].min, 10);
+ assert.strictEqual(ret[1].max, 15);
+ assert.strictEqual(ret[1].avg, (10 + 15) / 2);
+ assert.strictEqual(ret[1].start, 10);
+ assert.strictEqual(ret[1].end, 15);
+ });
+
+ test('getSampleStatisticsWithAllSelections', function() {
+ const ctr = createCounterWithTwoSeries();
+ const ret = ctr.getSampleStatistics([1, 0, 2, 3]);
+
+ assert.strictEqual(ret[0].min, 5);
+ assert.strictEqual(ret[0].max, 7);
+ assert.strictEqual(ret[0].avg, (5 + 6 + 5 + 7) / 4);
+ assert.strictEqual(ret[0].start, 5);
+ assert.strictEqual(ret[0].end, 7);
+
+ assert.strictEqual(ret[1].min, 10);
+ assert.strictEqual(ret[1].max, 16);
+ assert.strictEqual(ret[1].avg, (10 + 15 + 12 + 16) / 4);
+ assert.strictEqual(ret[1].start, 10);
+ assert.strictEqual(ret[1].end, 16);
+ });
+
+ test('testCounterSortRemainInOrder', function() {
+ const model = new tr.Model();
+ const process = new tr.model.Process(model, 4);
+ const ctr1 = new Counter(process, 0, '', 'a');
+ const ctr2 = new Counter(process, 0, '', 'b');
+
+ const array = [ctr1, ctr2];
+ array.sort(tr.model.Counter.compare);
+
+ assert.strictEqual(array[0], ctr1);
+ assert.strictEqual(array[1], ctr2);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/cpu.html b/chromium/third_party/catapult/tracing/tracing/model/cpu.html
new file mode 100644
index 00000000000..beb2f63e7cf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/cpu.html
@@ -0,0 +1,282 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/counter.html">
+<link rel="import" href="/tracing/model/cpu_slice.html">
+<link rel="import" href="/tracing/model/process_base.html">
+<link rel="import" href="/tracing/model/thread_time_slice.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Cpu class.
+ */
+tr.exportTo('tr.model', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Counter = tr.model.Counter;
+ const CpuSlice = tr.model.CpuSlice;
+
+ /**
+ * The Cpu represents a Cpu from the kernel's point of view.
+ * @constructor
+ */
+ function Cpu(kernel, number) {
+ if (kernel === undefined || number === undefined) {
+ throw new Error('Missing arguments');
+ }
+ this.kernel = kernel;
+ this.cpuNumber = number;
+ this.slices = [];
+ this.counters = {};
+ this.bounds_ = new tr.b.math.Range();
+ this.samples_ = undefined; // Set during createSubSlices
+
+ // Start timestamp of the last active thread.
+ this.lastActiveTimestamp_ = undefined;
+
+ // Identifier of the last active thread. On Linux, it's a pid while on
+ // Windows it's a thread id.
+ this.lastActiveThread_ = undefined;
+
+ // Name and arguments of the last active thread.
+ this.lastActiveName_ = undefined;
+ this.lastActiveArgs_ = undefined;
+ }
+
+ Cpu.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ get samples() {
+ return this.samples_;
+ },
+
+ get userFriendlyName() {
+ return 'CPU ' + this.cpuNumber;
+ },
+
+ * findTopmostSlicesInThisContainer(eventPredicate, opt_this) {
+ // All CpuSlices are toplevel since CpuSlices do not nest.
+ for (const s of this.slices) {
+ yield* s.findTopmostSlicesRelativeToThisSlice(
+ eventPredicate, opt_this);
+ }
+ },
+
+ * childEvents() {
+ yield* this.slices;
+
+ if (this.samples_) {
+ yield* this.samples_;
+ }
+ },
+
+ * childEventContainers() {
+ yield* Object.values(this.counters);
+ },
+
+ /**
+ * @return {Counter} The counter on this CPU with the given category/name
+ * combination, creating it if it doesn't exist.
+ */
+ getOrCreateCounter(cat, name) {
+ const id = cat + '.' + name;
+ if (!this.counters[id]) {
+ this.counters[id] = new Counter(this, id, cat, name);
+ }
+ return this.counters[id];
+ },
+
+ /**
+ * @return {Counter} the counter on this CPU with the given category/name
+ * combination, or undefined if it doesn't exist.
+ */
+ getCounter(cat, name) {
+ const id = cat + '.' + name;
+ if (!this.counters[id]) {
+ return undefined;
+ }
+ return this.counters[id];
+ },
+
+ /**
+ * Shifts all the timestamps inside this CPU forward by the amount
+ * specified.
+ */
+ shiftTimestampsForward(amount) {
+ for (let sI = 0; sI < this.slices.length; sI++) {
+ this.slices[sI].start = (this.slices[sI].start + amount);
+ }
+ for (const id in this.counters) {
+ this.counters[id].shiftTimestampsForward(amount);
+ }
+ },
+
+ /**
+ * Updates the range based on the current slices attached to the cpu.
+ */
+ updateBounds() {
+ this.bounds_.reset();
+ if (this.slices.length) {
+ this.bounds_.addValue(this.slices[0].start);
+ this.bounds_.addValue(this.slices[this.slices.length - 1].end);
+ }
+ for (const id in this.counters) {
+ this.counters[id].updateBounds();
+ this.bounds_.addRange(this.counters[id].bounds);
+ }
+ if (this.samples_ && this.samples_.length) {
+ this.bounds_.addValue(this.samples_[0].start);
+ this.bounds_.addValue(
+ this.samples_[this.samples_.length - 1].end);
+ }
+ },
+
+ createSubSlices() {
+ this.samples_ = this.kernel.model.samples.filter(function(sample) {
+ return sample.cpu === this;
+ }, this);
+ },
+
+ addCategoriesToDict(categoriesDict) {
+ for (let i = 0; i < this.slices.length; i++) {
+ categoriesDict[this.slices[i].category] = true;
+ }
+ for (const id in this.counters) {
+ categoriesDict[this.counters[id].category] = true;
+ }
+ for (let i = 0; i < this.samples_.length; i++) {
+ categoriesDict[this.samples_[i].category] = true;
+ }
+ },
+
+ /*
+ * Returns the index of the slice in the CPU's slices, or undefined.
+ */
+ indexOf(cpuSlice) {
+ const i = tr.b.findLowIndexInSortedArray(
+ this.slices,
+ function(slice) { return slice.start; },
+ cpuSlice.start);
+ if (this.slices[i] !== cpuSlice) return undefined;
+ return i;
+ },
+
+ /**
+ * Closes the thread running on the CPU. |endTimestamp| is the timestamp
+ * at which the thread was unscheduled. |args| is merged with the arguments
+ * specified when the thread was initially scheduled.
+ */
+ closeActiveThread(endTimestamp, args) {
+ // Don't generate a slice if the last active thread is the idle task.
+ if (this.lastActiveThread_ === undefined ||
+ this.lastActiveThread_ === 0) {
+ return;
+ }
+
+ if (endTimestamp < this.lastActiveTimestamp_) {
+ throw new Error('The end timestamp of a thread running on CPU ' +
+ this.cpuNumber + ' is before its start timestamp.');
+ }
+
+ // Merge |args| with |this.lastActiveArgs_|. If a key is in both
+ // dictionaries, the value from |args| is used.
+ for (const key in args) {
+ this.lastActiveArgs_[key] = args[key];
+ }
+
+ const duration = endTimestamp - this.lastActiveTimestamp_;
+ const slice = new tr.model.CpuSlice(
+ '', this.lastActiveName_,
+ ColorScheme.getColorIdForGeneralPurposeString(this.lastActiveName_),
+ this.lastActiveTimestamp_,
+ this.lastActiveArgs_,
+ duration);
+ slice.cpu = this;
+ this.slices.push(slice);
+
+ // Clear the last state.
+ this.lastActiveTimestamp_ = undefined;
+ this.lastActiveThread_ = undefined;
+ this.lastActiveName_ = undefined;
+ this.lastActiveArgs_ = undefined;
+ },
+
+ switchActiveThread(timestamp, oldThreadArgs, newThreadId,
+ newThreadName, newThreadArgs) {
+ // Close the previous active thread and generate a slice.
+ this.closeActiveThread(timestamp, oldThreadArgs);
+
+ // Keep track of the new thread.
+ this.lastActiveTimestamp_ = timestamp;
+ this.lastActiveThread_ = newThreadId;
+ this.lastActiveName_ = newThreadName;
+ this.lastActiveArgs_ = newThreadArgs;
+ },
+
+ /**
+ * Returns the frequency statistics for this CPU;
+ * the returned object contains the frequencies as keys,
+ * and the duration at this frequency in milliseconds as the value,
+ * for the range that was specified.
+ */
+ getFreqStatsForRange(range) {
+ const stats = {};
+
+ function addStatsForFreq(freqSample, index) {
+ // Counters don't have an explicit end or duration;
+ // calculate the end by looking at the starting point
+ // of the next value in the series, or if that doesn't
+ // exist, assume this frequency is held until the end.
+ const freqEnd = (index < freqSample.series_.length - 1) ?
+ freqSample.series_.samples_[index + 1].timestamp : range.max;
+
+ const freqRange = tr.b.math.Range.fromExplicitRange(
+ freqSample.timestamp, freqEnd);
+ const intersection = freqRange.findIntersection(range);
+ if (!(freqSample.value in stats)) {
+ stats[freqSample.value] = 0;
+ }
+ stats[freqSample.value] += intersection.duration;
+ }
+
+ const freqCounter = this.getCounter('', 'Clock Frequency');
+ if (freqCounter !== undefined) {
+ const freqSeries = freqCounter.getSeries(0);
+ if (!freqSeries) return;
+
+ tr.b.iterateOverIntersectingIntervals(freqSeries.samples_,
+ function(x) { return x.timestamp; },
+ function(x, index) {
+ if (index < freqSeries.length - 1) {
+ return freqSeries.samples_[index + 1].timestamp;
+ }
+ return range.max;
+ },
+ range.min,
+ range.max,
+ addStatsForFreq);
+ }
+
+ return stats;
+ }
+ };
+
+ /**
+ * Comparison between processes that orders by cpuNumber.
+ */
+ Cpu.compare = function(x, y) {
+ return x.cpuNumber - y.cpuNumber;
+ };
+
+
+ return {
+ Cpu,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/cpu_slice.html b/chromium/third_party/catapult/tracing/tracing/model/cpu_slice.html
new file mode 100644
index 00000000000..6faf5d143fa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/cpu_slice.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/thread_time_slice.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the CpuSlice class.
+ */
+tr.exportTo('tr.model', function() {
+ const Slice = tr.model.Slice;
+
+ /**
+ * A CpuSlice represents a slice of time on a CPU.
+ *
+ * @constructor
+ */
+ function CpuSlice(cat, title, colorId, start, args, opt_duration) {
+ Slice.apply(this, arguments);
+ this.threadThatWasRunning = undefined;
+ this.cpu = undefined;
+ }
+
+ CpuSlice.prototype = {
+ __proto__: Slice.prototype,
+
+ get analysisTypeName() {
+ return 'tr.ui.analysis.CpuSlice';
+ },
+
+ getAssociatedTimeslice() {
+ if (!this.threadThatWasRunning) {
+ return undefined;
+ }
+ const timeSlices = this.threadThatWasRunning.timeSlices;
+ for (let i = 0; i < timeSlices.length; i++) {
+ const timeSlice = timeSlices[i];
+ if (timeSlice.start !== this.start) {
+ continue;
+ }
+ if (timeSlice.duration !== this.duration) {
+ continue;
+ }
+ return timeSlice;
+ }
+ return undefined;
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ CpuSlice,
+ {
+ name: 'cpuSlice',
+ pluralName: 'cpuSlices'
+ });
+
+ return {
+ CpuSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/cpu_test.html b/chromium/third_party/catapult/tracing/tracing/model/cpu_test.html
new file mode 100644
index 00000000000..49f01dff4f3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/cpu_test.html
@@ -0,0 +1,206 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Cpu = tr.model.Cpu;
+ const newThreadSlice = tr.c.TestUtils.newThreadSlice;
+
+ test('cpuBounds_Empty', function() {
+ const cpu = new Cpu({}, 1);
+ cpu.updateBounds();
+ assert.isUndefined(cpu.bounds.min);
+ assert.isUndefined(cpu.bounds.max);
+ });
+
+ test('cpuBounds_OneSlice', function() {
+ const cpu = new Cpu({}, 1);
+ cpu.slices.push(tr.c.TestUtils.newSliceEx({start: 1, duration: 3}));
+ cpu.updateBounds();
+ assert.strictEqual(cpu.bounds.min, 1);
+ assert.strictEqual(cpu.bounds.max, 4);
+ });
+
+ test('getOrCreateCounter', function() {
+ const cpu = new Cpu({}, 1);
+ const ctrBar = cpu.getOrCreateCounter('foo', 'bar');
+ const ctrBar2 = cpu.getOrCreateCounter('foo', 'bar');
+ assert.strictEqual(ctrBar, ctrBar2);
+ });
+
+ test('shiftTimestampsForward', function() {
+ const cpu = new Cpu({}, 1);
+ const ctr = cpu.getOrCreateCounter('foo', 'bar');
+ cpu.slices.push(tr.c.TestUtils.newSliceEx({start: 1, duration: 3}));
+ let shiftCount = 0;
+ ctr.shiftTimestampsForward = function(ts) {
+ if (ts === 0.32) {
+ shiftCount++;
+ }
+ };
+ cpu.slices.push(tr.c.TestUtils.newSliceEx({start: 1, duration: 3}));
+ cpu.shiftTimestampsForward(0.32);
+ assert.strictEqual(1, shiftCount);
+ assert.strictEqual(cpu.slices[0].start, 1.32);
+ });
+
+
+ function newCpuSliceNamed(cpu, name, start, duration, opt_thread) {
+ const s = new tr.model.CpuSlice(
+ 'cat', name, 0, start, {}, duration);
+ s.cpu = cpu;
+ if (opt_thread) {
+ s.threadThatWasRunning = opt_thread;
+ }
+ return s;
+ }
+
+ test('getTimesliceForCpuSlice', function() {
+ const m = new tr.Model();
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const cpu = m.kernel.getOrCreateCpu(1);
+ const t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ t2.timeSlices = [newThreadSlice(t2, SCHEDULING_STATE.RUNNING, 0, 10, cpu),
+ newThreadSlice(t2, SCHEDULING_STATE.SLEEPING, 10, 10),
+ newThreadSlice(t2, SCHEDULING_STATE.RUNNING, 20, 10, cpu)];
+ cpu.slices = [newCpuSliceNamed(cpu, 'x', 0, 10, t2),
+ newCpuSliceNamed(cpu, 'x', 20, 10, t2)];
+ assert.strictEqual(
+ cpu.slices[0].getAssociatedTimeslice(), t2.timeSlices[0]);
+ assert.strictEqual(
+ cpu.slices[1].getAssociatedTimeslice(), t2.timeSlices[2]);
+
+ assert.strictEqual(t2.timeSlices[0].getAssociatedCpuSlice(), cpu.slices[0]);
+ assert.isUndefined(t2.timeSlices[1].getAssociatedCpuSlice());
+ assert.strictEqual(t2.timeSlices[2].getAssociatedCpuSlice(), cpu.slices[1]);
+
+ assert.strictEqual(cpu.indexOf(cpu.slices[0]), 0);
+ assert.strictEqual(cpu.indexOf(cpu.slices[1]), 1);
+
+ assert.strictEqual(t2.indexOfTimeSlice(t2.timeSlices[0]), 0);
+ assert.strictEqual(t2.indexOfTimeSlice(t2.timeSlices[1]), 1);
+ assert.strictEqual(t2.indexOfTimeSlice(t2.timeSlices[2]), 2);
+ });
+
+ test('putToSleepFor', function() {
+ const m = new tr.Model();
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const cpu = m.kernel.getOrCreateCpu(1);
+
+ const t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const t3 = m.getOrCreateProcess(1).getOrCreateThread(3);
+ t2.timeSlices = [newThreadSlice(t2, SCHEDULING_STATE.RUNNING, 0, 10, cpu),
+ newThreadSlice(t2, SCHEDULING_STATE.SLEEPING, 10, 10),
+ newThreadSlice(t2, SCHEDULING_STATE.RUNNING, 20, 10, cpu)];
+ t3.timeSlices = [newThreadSlice(t3, SCHEDULING_STATE.RUNNING, 10, 5, cpu)];
+ cpu.slices = [newCpuSliceNamed(cpu, 'x', 0, 10, t2),
+ newCpuSliceNamed(cpu, 'x', 10, 5, t3),
+ newCpuSliceNamed(cpu, 'x', 20, 10, t2)];
+
+ // At timeslice 0, the thread is running.
+ assert.isUndefined(t2.timeSlices[0].getCpuSliceThatTookCpu());
+
+ // t2 lost the cpu to t3 at t=10
+ assert.strictEqual(
+ cpu.slices[1],
+ t2.timeSlices[1].getCpuSliceThatTookCpu());
+ });
+
+ test('putToSleepForNothing', function() {
+ const m = new tr.Model();
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const cpu = m.kernel.getOrCreateCpu(1);
+
+ const t2 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const t3 = m.getOrCreateProcess(1).getOrCreateThread(3);
+ t2.timeSlices = [newThreadSlice(t2, SCHEDULING_STATE.RUNNING, 0, 10, cpu),
+ newThreadSlice(t2, SCHEDULING_STATE.SLEEPING, 10, 10),
+ newThreadSlice(t2, SCHEDULING_STATE.RUNNING, 20, 10, cpu)];
+ t3.timeSlices = [newThreadSlice(t3, SCHEDULING_STATE.RUNNING, 15, 5, cpu)];
+ cpu.slices = [newCpuSliceNamed(cpu, 'x', 0, 10, t2),
+ newCpuSliceNamed(cpu, 'x', 15, 5, t3),
+ newCpuSliceNamed(cpu, 'x', 20, 10, t2)];
+ assert.isUndefined(t2.timeSlices[1].getCpuSliceThatTookCpu());
+ });
+
+ test('switchActiveThread', function() {
+ const m = new tr.Model();
+ const cpu = m.kernel.getOrCreateCpu(1);
+
+ cpu.switchActiveThread(5, {}, 0, 'idle thread', {});
+ cpu.switchActiveThread(10, {}, 1, 'thread one', {a: 1});
+ cpu.switchActiveThread(15, {b: 2}, 2, 'thread two', {c: 3});
+ cpu.switchActiveThread(30, {c: 4, d: 5}, 3, 'thread three', {e: 6});
+ cpu.closeActiveThread(40, {f: 7});
+ cpu.switchActiveThread(50, {}, 4, 'thread four', {g: 8});
+ cpu.switchActiveThread(60, {}, 1, 'thread one', {});
+ cpu.closeActiveThread(70, {});
+
+ assert.strictEqual(cpu.slices.length, 5);
+
+ assert.strictEqual(cpu.slices[0].title, 'thread one');
+ assert.strictEqual(cpu.slices[0].start, 10);
+ assert.strictEqual(cpu.slices[0].duration, 5);
+ assert.strictEqual(Object.keys(cpu.slices[0].args).length, 2);
+ assert.strictEqual(cpu.slices[0].args.a, 1);
+ assert.strictEqual(cpu.slices[0].args.b, 2);
+
+ assert.strictEqual(cpu.slices[1].title, 'thread two');
+ assert.strictEqual(cpu.slices[1].start, 15);
+ assert.strictEqual(cpu.slices[1].duration, 15);
+ assert.strictEqual(Object.keys(cpu.slices[1].args).length, 2);
+ assert.strictEqual(cpu.slices[1].args.c, 4);
+ assert.strictEqual(cpu.slices[1].args.d, 5);
+
+ assert.strictEqual(cpu.slices[2].title, 'thread three');
+ assert.strictEqual(cpu.slices[2].start, 30);
+ assert.strictEqual(cpu.slices[2].duration, 10);
+ assert.strictEqual(Object.keys(cpu.slices[2].args).length, 2);
+ assert.strictEqual(cpu.slices[2].args.e, 6);
+ assert.strictEqual(cpu.slices[2].args.f, 7);
+
+ assert.strictEqual(cpu.slices[3].title, 'thread four');
+ assert.strictEqual(cpu.slices[3].start, 50);
+ assert.strictEqual(cpu.slices[3].duration, 10);
+ assert.strictEqual(Object.keys(cpu.slices[3].args).length, 1);
+ assert.strictEqual(cpu.slices[3].args.g, 8);
+
+ assert.strictEqual(cpu.slices[4].title, 'thread one');
+ assert.strictEqual(cpu.slices[4].start, 60);
+ assert.strictEqual(cpu.slices[4].duration, 10);
+ assert.strictEqual(Object.keys(cpu.slices[4].args).length, 0);
+ });
+
+ test('getFrequencyStats', function() {
+ const m = new tr.Model();
+ const cpu = m.kernel.getOrCreateCpu(1);
+ const powerCounter = cpu.getOrCreateCounter('', 'Clock Frequency');
+ const series = powerCounter.addSeries(new tr.model.CounterSeries('state',
+ ColorScheme.getColorIdForGeneralPurposeString('test')));
+
+ series.addCounterSample(0, 100000);
+ series.addCounterSample(20, 300000);
+ series.addCounterSample(30, 100000);
+ series.addCounterSample(80, 500000);
+ series.addCounterSample(100, 300000);
+
+ const range = tr.b.math.Range.fromExplicitRange(10, 90);
+ const stats = cpu.getFreqStatsForRange(range);
+ assert.strictEqual(stats[100000], 60);
+ assert.strictEqual(stats[300000], 10);
+ assert.strictEqual(stats[500000], 10);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/device.html b/chromium/third_party/catapult/tracing/tracing/model/device.html
new file mode 100644
index 00000000000..5dca1e03151
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/device.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/cpu.html">
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/power_series.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Device class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * Device represents the device-level objects in the model.
+ * @constructor
+ * @extends {tr.model.EventContainer}
+ */
+ function Device(model) {
+ if (!model) {
+ throw new Error('Must provide a model.');
+ }
+
+ tr.model.EventContainer.call(this);
+
+ this.powerSeries_ = undefined;
+ this.cpuUsageSeries_ = undefined;
+ this.vSyncTimestamps_ = [];
+ }
+
+ Device.compare = function(x, y) {
+ return x.guid - y.guid;
+ };
+
+ Device.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ compareTo(that) {
+ return Device.compare(this, that);
+ },
+
+ get userFriendlyName() {
+ return 'Device';
+ },
+
+ get userFriendlyDetails() {
+ return 'Device';
+ },
+
+ get stableId() {
+ return 'Device';
+ },
+
+ getSettingsKey() {
+ return 'device';
+ },
+
+ get powerSeries() {
+ return this.powerSeries_;
+ },
+
+ set powerSeries(powerSeries) {
+ this.powerSeries_ = powerSeries;
+ },
+
+ get cpuUsageSeries() {
+ return this.cpuUsageSeries_;
+ },
+
+ set cpuUsageSeries(cpuUsageSeries) {
+ this.cpuUsageSeries_ = cpuUsageSeries;
+ },
+
+ get vSyncTimestamps() {
+ return this.vSyncTimestamps_;
+ },
+
+ set vSyncTimestamps(value) {
+ this.vSyncTimestamps_ = value;
+ },
+
+ updateBounds() {
+ this.bounds.reset();
+ for (const child of this.childEventContainers()) {
+ child.updateBounds();
+ this.bounds.addRange(child.bounds);
+ }
+ },
+
+ shiftTimestampsForward(amount) {
+ for (const child of this.childEventContainers()) {
+ child.shiftTimestampsForward(amount);
+ }
+
+ for (let i = 0; i < this.vSyncTimestamps_.length; i++) {
+ this.vSyncTimestamps_[i] += amount;
+ }
+ },
+
+ addCategoriesToDict(categoriesDict) {
+ },
+
+ * childEventContainers() {
+ if (this.powerSeries_) {
+ yield this.powerSeries_;
+ }
+ if (this.cpuUsageSeries_) {
+ yield this.cpuUsageSeries_;
+ }
+ }
+ };
+
+ return {
+ Device,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/device_test.html b/chromium/third_party/catapult/tracing/tracing/model/device_test.html
new file mode 100644
index 00000000000..6e46cced01b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/device_test.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/device.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_series.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Device = tr.model.Device;
+ const Model = tr.Model;
+ const PowerSeries = tr.model.PowerSeries;
+
+ test('updateBounds', function() {
+ const device = new Device(new Model());
+ device.powerSeries = new PowerSeries(device);
+
+ // Verify that the bounds match the lowest and highest timestamps.
+ device.powerSeries.addPowerSample(100, 5);
+ device.powerSeries.addPowerSample(200, 5);
+ device.updateBounds();
+
+ assert.strictEqual(device.bounds.min, 100);
+ assert.strictEqual(device.bounds.max, 200);
+
+ // Add a new sample and verify that the bounds change.
+ device.powerSeries.addPowerSample(700, 5);
+ device.updateBounds();
+
+ assert.strictEqual(device.bounds.min, 100);
+ assert.strictEqual(device.bounds.max, 700);
+ });
+
+ test('shiftTimestampsForward', function() {
+ const device = new Device(new Model());
+ device.powerSeries = new PowerSeries(device);
+
+ device.powerSeries.addPowerSample(100, 2);
+ device.powerSeries.addPowerSample(200, 2);
+ device.shiftTimestampsForward(2);
+
+ assert.strictEqual(device.powerSeries.samples[0].start, 102);
+ assert.strictEqual(device.powerSeries.samples[1].start, 202);
+ });
+
+ test('childEventContainers_noPowerSeries', function() {
+ const device = new Device(new Model());
+ const childEventContainers = [];
+ for (const container of device.childEventContainers()) {
+ childEventContainers.push(container);
+ }
+ assert.deepEqual(childEventContainers, []);
+ });
+
+ test('childEventContainers_powerSeries', function() {
+ const device = new Device(new Model());
+ device.powerSeries = new PowerSeries(device);
+ const childEventContainers = [];
+ for (const container of device.childEventContainers()) {
+ childEventContainers.push(container);
+ }
+ assert.deepEqual(childEventContainers, [device.powerSeries]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/event.html b/chromium/third_party/catapult/tracing/tracing/model/event.html
new file mode 100644
index 00000000000..99495fcc913
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/event.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/selectable_item.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Event class.
+ */
+tr.exportTo('tr.model', function() {
+ const SelectableItem = tr.model.SelectableItem;
+ const SelectionState = tr.model.SelectionState;
+ const IMMUTABLE_EMPTY_SET = tr.model.EventSet.IMMUTABLE_EMPTY_SET;
+
+ /**
+ * An Event is the base type for any non-container, selectable piece
+ * of data in the trace model.
+ *
+ * @constructor
+ * @extends {SelectableItem}
+ */
+ function Event() {
+ SelectableItem.call(this, this /* modelItem */);
+ this.guid_ = tr.b.GUID.allocateSimple();
+ this.selectionState = SelectionState.NONE;
+ this.info = undefined;
+ }
+
+ Event.prototype = {
+ __proto__: SelectableItem.prototype,
+
+ get guid() {
+ return this.guid_;
+ },
+
+ get stableId() {
+ return undefined;
+ },
+
+ get range() {
+ const range = new tr.b.math.Range();
+ this.addBoundsToRange(range);
+ return range;
+ },
+
+ // Empty by default. Lazily initialized on an instance in
+ // addAssociatedAlert(). See #1930.
+ associatedAlerts: IMMUTABLE_EMPTY_SET,
+
+ addAssociatedAlert(alert) {
+ if (this.associatedAlerts === IMMUTABLE_EMPTY_SET) {
+ this.associatedAlerts = new tr.model.EventSet();
+ }
+ this.associatedAlerts.push(alert);
+ },
+
+ // Adds the range of timestamps for this event to the specified range.
+ // If this is not overridden in subclass, it means that type of event
+ // doesn't have timestamps.
+ addBoundsToRange(range) {}
+ };
+
+ return {
+ Event,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/event_container.html b/chromium/third_party/catapult/tracing/tracing/model/event_container.html
new file mode 100644
index 00000000000..8c71eb4b688
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/event_container.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * EventContainer is a base class for any class in the trace model that
+ * contains child events or child EventContainers.
+ *
+ * For all EventContainers, updateBounds() must be called after modifying the
+ * container's events if an up-to-date bounds is expected.
+ *
+ * @constructor
+ */
+ function EventContainer() {
+ this.guid_ = tr.b.GUID.allocateSimple();
+ this.important = true;
+ this.bounds_ = new tr.b.math.Range();
+ }
+
+ EventContainer.prototype = {
+ get guid() {
+ return this.guid_;
+ },
+
+ /**
+ * @return {String} A stable and unique identifier that describes this
+ * container's position in the event tree relative to the root. If an event
+ * container 'B' is a child to another event container 'A', then container
+ * B's stable ID would be 'A.B'.
+ */
+ get stableId() {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * Returns the bounds of the event container, which describe the range
+ * of timestamps for all ancestor events.
+ */
+ get bounds() {
+ return this.bounds_;
+ },
+
+ // TODO(charliea): A default implementation of this method could likely be
+ // provided that iterates throuch getDescendantEvents.
+ /**
+ * Updates the bounds of the event container. After updating, this.bounds
+ * will describe the range of timestamps of all ancestor events.
+ */
+ updateBounds() {
+ throw new Error('Not implemented');
+ },
+
+ // TODO(charliea): A default implementation of this method could likely be
+ // provided that iterates through getDescendantEvents.
+ /**
+ * Shifts the timestamps for ancestor events by 'amount' milliseconds.
+ */
+ shiftTimestampsForward(amount) {
+ throw new Error('Not implemented');
+ },
+
+
+ /**
+ * Returns an iterable of all child events.
+ */
+ * childEvents() {
+ },
+
+ /**
+ * Returns an iterable of all events in this and descendant
+ * event containers.
+ */
+ * getDescendantEvents() {
+ yield* this.childEvents();
+ for (const container of this.childEventContainers()) {
+ yield* container.getDescendantEvents();
+ }
+ },
+
+ /**
+ * Returns an iterable of all child event containers.
+ */
+ * childEventContainers() {
+ },
+
+ /**
+ * Returns an iterable containing this and all descendant event containers.
+ */
+ * getDescendantEventContainers() {
+ yield this;
+ for (const container of this.childEventContainers()) {
+ yield* container.getDescendantEventContainers();
+ }
+ },
+
+ /**
+ * Returns an iterable of all events in this and descendant event containers
+ * in a given set of ranges.
+ *
+ * This base class provides a default implementation with no assumptions
+ * about the order of events. A container can override this implementation
+ * with a more efficient one, for example if its events are sorted.
+ */
+ * getDescendantEventsInSortedRanges(ranges, opt_containerPredicate) {
+ if (opt_containerPredicate === undefined ||
+ opt_containerPredicate(this)) {
+ for (const event of this.childEvents()) {
+ const i = tr.b.findFirstTrueIndexInSortedArray(
+ ranges, range => event.start <= range.max);
+ if (i < ranges.length && event.end >= ranges[i].min) yield event;
+ }
+ }
+
+ for (const container of this.childEventContainers()) {
+ yield* container.getDescendantEventsInSortedRanges(
+ ranges, opt_containerPredicate);
+ }
+ },
+
+ /**
+ * Finds topmost slices in this container (see docstring for
+ * findTopmostSlices).
+ */
+ * findTopmostSlicesInThisContainer(eventPredicate, opt_this) {
+ },
+
+ /**
+ * The findTopmostSlices* series of helpers find all topmost slices
+ * satisfying the given predicates.
+ *
+ * As an example, suppose we are trying to find slices named 'C', with the
+ * following thread:
+ *
+ * -> |---C---| |-----D-----|
+ * |-C-| |---C---| <-
+ *
+ * findTopmostSlices would locate the pointed-to Cs, because the bottom C on
+ * the left is not the topmost C, and the right one is, even though it is
+ * not itself a top-level slice.
+ */
+ * findTopmostSlices(eventPredicate) {
+ for (const ec of this.getDescendantEventContainers()) {
+ yield* ec.findTopmostSlicesInThisContainer(eventPredicate);
+ }
+ },
+
+ * findTopmostSlicesNamed(name) {
+ yield* this.findTopmostSlices(e => e.title === name);
+ }
+ };
+
+ return {
+ EventContainer,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/event_container_test.html b/chromium/third_party/catapult/tracing/tracing/model/event_container_test.html
new file mode 100644
index 00000000000..06b06a391c2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/event_container_test.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('getDescendantEventsInSortedRanges', function() {
+ class ContainerTypeX extends tr.model.EventContainer {
+ * childEvents() {
+ const event1 = new tr.model.TimedEvent(4);
+ event1.duration = 2;
+ event1.title = 'X-1';
+ yield event1;
+
+ const event2 = new tr.model.TimedEvent(1);
+ event2.duration = 2;
+ event2.title = 'X-2';
+ yield event2;
+ }
+ }
+
+ class ContainerTypeY extends tr.model.EventContainer {
+ constructor() {
+ super();
+ this.childContainer_ = new ContainerTypeX();
+ }
+
+ * childEvents() {
+ const event1 = new tr.model.TimedEvent(5);
+ event1.duration = 4;
+ event1.title = 'Y-1';
+ yield event1;
+
+ const event2 = new tr.model.TimedEvent(6);
+ event2.duration = 2;
+ event2.title = 'Y-2';
+ yield event2;
+ }
+
+ * childEventContainers() {
+ yield this.childContainer_;
+ }
+ }
+
+ // We have the following timed events:
+ // 1 2 3 4 5 6 7 8 9
+ // ContainerTypeY <----- Y-1 ----->
+ // <- Y2 ->
+ // ContainerTypeX <- X-2 -> <- X-1 ->
+ const container = new ContainerTypeY();
+
+ // [2, 5] intersect X-1, X-2, and Y-1.
+ const r1 = new tr.b.math.Range.fromExplicitRange(2, 5);
+ let slices = [...container.getDescendantEventsInSortedRanges([r1])];
+ slices = slices.map(s => s.title).sort();
+ assert.strictEqual(slices.length, 3);
+ assert.strictEqual(slices[0], 'X-1');
+ assert.strictEqual(slices[1], 'X-2');
+ assert.strictEqual(slices[2], 'Y-1');
+
+ // [2, 5], [7, 8] intersect X-1, X-2, Y-1, and Y-2.
+ const r2 = new tr.b.math.Range.fromExplicitRange(7, 8);
+ slices = [...container.getDescendantEventsInSortedRanges([r1, r2])];
+ slices = slices.map(s => s.title).sort();
+ assert.strictEqual(slices.length, 4);
+ assert.strictEqual(slices[0], 'X-1');
+ assert.strictEqual(slices[1], 'X-2');
+ assert.strictEqual(slices[2], 'Y-1');
+ assert.strictEqual(slices[3], 'Y-2');
+
+ // We should see events from ContainerTypeX only.
+ slices = [...container.getDescendantEventsInSortedRanges(
+ [r1], container => container instanceof ContainerTypeX)];
+ slices = slices.map(s => s.title).sort();
+ assert.strictEqual(slices.length, 2);
+ assert.strictEqual(slices[0], 'X-1');
+ assert.strictEqual(slices[1], 'X-2');
+
+ // We should see events from ContainerTypeY only.
+ slices = [...container.getDescendantEventsInSortedRanges(
+ [r1], container => container instanceof ContainerTypeY)];
+ slices = slices.map(s => s.title).sort();
+ assert.strictEqual(slices.length, 1);
+ assert.strictEqual(slices[0], 'Y-1');
+ });
+});
diff --git a/chromium/third_party/catapult/tracing/tracing/model/event_info.html b/chromium/third_party/catapult/tracing/tracing/model/event_info.html
new file mode 100644
index 00000000000..ecc309d471a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/event_info.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/color_scheme.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ /**
+ * EventInfo is an annotation added to Events in order to document
+ * what they represent, and override their title/colorId values.
+ *
+ * TODO(ccraik): eventually support more complex structure/paragraphs.
+ *
+ * @param {string} title A user-visible title for the event.
+ * @param {string} description A user-visible description of the event.
+ * @param {Array} docLinks A list of Objects, each of the form
+ * {label: str, textContent: str, href: str}
+ *
+ * @constructor
+ */
+ function EventInfo(title, description, docLinks) {
+ this.title = title;
+ this.description = description;
+ this.docLinks = docLinks;
+ this.colorId = ColorScheme.getColorIdForGeneralPurposeString(title);
+ }
+
+ return {
+ EventInfo,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/event_registry.html b/chromium/third_party/catapult/tracing/tracing/model/event_registry.html
new file mode 100644
index 00000000000..7913d7ffe80
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/event_registry.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the EventRegistry class.
+ */
+tr.exportTo('tr.model', function() {
+ // Create the type registry.
+ function EventRegistry() {
+ }
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ tr.b.decorateExtensionRegistry(EventRegistry, options);
+
+ // Enforce all options objects have the right fields.
+ EventRegistry.addEventListener('will-register', function(e) {
+ const metadata = e.typeInfo.metadata;
+ if (metadata.name === undefined) {
+ throw new Error('Registered events must provide name metadata');
+ }
+ if (metadata.pluralName === undefined) {
+ throw new Error('Registered events must provide pluralName metadata');
+ }
+
+ // Add a subtype registry to every event so that all events can be
+ // extended
+ if (metadata.subTypes === undefined) {
+ metadata.subTypes = {};
+ const options = new tr.b.ExtensionRegistryOptions(
+ tr.b.TYPE_BASED_REGISTRY_MODE);
+ options.mandatoryBaseClass = e.typeInfo.constructor;
+ options.defaultConstructor = e.typeInfo.constructor;
+ tr.b.decorateExtensionRegistry(metadata.subTypes, options);
+ } else {
+ if (!metadata.subTypes.register) {
+ throw new Error('metadata.subTypes must be an extension registry.');
+ }
+ }
+
+ e.typeInfo.constructor.subTypes = metadata.subTypes;
+ });
+
+ // Helper: lookup Events indexed by type name.
+ let eventsByTypeName = undefined;
+ EventRegistry.getEventTypeInfoByTypeName = function(typeName) {
+ if (eventsByTypeName === undefined) {
+ eventsByTypeName = {};
+ EventRegistry.getAllRegisteredTypeInfos().forEach(function(typeInfo) {
+ eventsByTypeName[typeInfo.metadata.name] = typeInfo;
+ });
+ }
+ return eventsByTypeName[typeName];
+ };
+
+ // Ensure eventsByTypeName stays current.
+ EventRegistry.addEventListener('registry-changed', function() {
+ eventsByTypeName = undefined;
+ });
+
+ function convertCamelCaseToTitleCase(name) {
+ let result = name.replace(/[A-Z]/g, ' $&');
+ result = result.charAt(0).toUpperCase() + result.slice(1);
+ return result;
+ }
+
+ EventRegistry.getUserFriendlySingularName = function(typeName) {
+ const typeInfo = EventRegistry.getEventTypeInfoByTypeName(typeName);
+ const str = typeInfo.metadata.name;
+ return convertCamelCaseToTitleCase(str);
+ };
+
+ EventRegistry.getUserFriendlyPluralName = function(typeName) {
+ const typeInfo = EventRegistry.getEventTypeInfoByTypeName(typeName);
+ const str = typeInfo.metadata.pluralName;
+ return convertCamelCaseToTitleCase(str);
+ };
+
+ return {
+ EventRegistry,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/event_set.html b/chromium/third_party/catapult/tracing/tracing/model/event_set.html
new file mode 100644
index 00000000000..8805a6302ba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/event_set.html
@@ -0,0 +1,302 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_registry.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const EventRegistry = tr.model.EventRegistry;
+
+ const RequestSelectionChangeEvent = tr.b.Event.bind(
+ undefined, 'requestSelectionChange', true, false);
+
+ /**
+ * Represents a event set within a and its associated set of tracks.
+ * @constructor
+ */
+ function EventSet(opt_events) {
+ this.bounds_ = new tr.b.math.Range();
+ this.events_ = new Set();
+ this.guid_ = tr.b.GUID.allocateSimple();
+
+ if (opt_events) {
+ if (opt_events instanceof Array) {
+ for (const event of opt_events) {
+ this.push(event);
+ }
+ } else if (opt_events instanceof EventSet) {
+ this.addEventSet(opt_events);
+ } else {
+ this.push(opt_events);
+ }
+ }
+ }
+
+ EventSet.prototype = {
+ __proto__: Object.prototype,
+
+ get bounds() {
+ return this.bounds_;
+ },
+
+ get duration() {
+ if (this.bounds_.isEmpty) return 0;
+ return this.bounds_.max - this.bounds_.min;
+ },
+
+ get length() {
+ return this.events_.size;
+ },
+
+ get guid() {
+ return this.guid_;
+ },
+
+ * [Symbol.iterator]() {
+ for (const event of this.events_) {
+ yield event;
+ }
+ },
+
+ clear() {
+ this.bounds_ = new tr.b.math.Range();
+ this.events_.clear();
+ },
+
+ /**
+ * Pushes each argument onto the EventSet. Returns the number of
+ * arguments pushed.
+ */
+ push(...events) {
+ let numPushed;
+ for (const event of events) {
+ if (event.guid === undefined) {
+ throw new Error('Event must have a GUID');
+ }
+
+ if (!this.events_.has(event)) {
+ this.events_.add(event);
+ // Some uses of eventSet (e.g. in tests) have Events as objects that
+ // don't have addBoundsToRange as a function. Thus we need to handle
+ // this case.
+ if (event.addBoundsToRange) {
+ if (this.bounds_ !== undefined) {
+ event.addBoundsToRange(this.bounds_);
+ }
+ }
+ }
+ numPushed++;
+ }
+ return numPushed;
+ },
+
+ contains(event) {
+ if (this.events_.has(event)) return event;
+ return undefined;
+ },
+
+ addEventSet(eventSet) {
+ for (const event of eventSet) {
+ this.push(event);
+ }
+ },
+
+ intersectionIsEmpty(otherEventSet) {
+ return !this.some(event => otherEventSet.contains(event));
+ },
+
+ equals(that) {
+ if (this.length !== that.length) return false;
+ return this.every(event => that.contains(event));
+ },
+
+ sortEvents(compare) {
+ // Convert to array, then sort, then convert back
+ const ary = this.toArray();
+ ary.sort(compare);
+
+ this.clear();
+ for (const event of ary) {
+ this.push(event);
+ }
+ },
+
+ getEventsOrganizedByBaseType(opt_pruneEmpty) {
+ const allTypeInfos = EventRegistry.getAllRegisteredTypeInfos();
+
+ const events = this.getEventsOrganizedByCallback(function(event) {
+ let maxEventIndex = -1;
+ let maxEventTypeInfo = undefined;
+
+ allTypeInfos.forEach(function(eventTypeInfo, eventIndex) {
+ if (!(event instanceof eventTypeInfo.constructor)) return;
+
+ if (eventIndex > maxEventIndex) {
+ maxEventIndex = eventIndex;
+ maxEventTypeInfo = eventTypeInfo;
+ }
+ });
+
+ if (maxEventIndex === -1) {
+ throw new Error(`Unrecognized event type: ${event.constructor.name}`);
+ }
+
+ return maxEventTypeInfo.metadata.name;
+ });
+
+ if (!opt_pruneEmpty) {
+ allTypeInfos.forEach(function(eventTypeInfo) {
+ if (events[eventTypeInfo.metadata.name] === undefined) {
+ events[eventTypeInfo.metadata.name] = new EventSet();
+ }
+ });
+ }
+
+ return events;
+ },
+
+ getEventsOrganizedByTitle() {
+ return this.getEventsOrganizedByCallback(function(event) {
+ if (event.title === undefined) {
+ throw new Error('An event didn\'t have a title!');
+ }
+ return event.title;
+ });
+ },
+
+ /**
+ * @param {!function(!tr.model.Event):string} cb
+ * @param {*=} opt_this
+ * @return {!Object} TODO(#3432) Return Map.
+ */
+ getEventsOrganizedByCallback(cb, opt_this) {
+ const groupedEvents = tr.b.groupIntoMap(this, cb, opt_this || this);
+ const groupedEventsDict = {};
+ for (const [k, events] of groupedEvents) {
+ groupedEventsDict[k] = new EventSet(events);
+ }
+ return groupedEventsDict;
+ },
+
+ enumEventsOfType(type, func) {
+ for (const event of this) {
+ if (event instanceof type) {
+ func(event);
+ }
+ }
+ },
+
+ get userFriendlyName() {
+ if (this.length === 0) {
+ throw new Error('Empty event set');
+ }
+
+ const eventsByBaseType = this.getEventsOrganizedByBaseType(true);
+ const eventTypeName = Object.keys(eventsByBaseType)[0];
+
+ if (this.length === 1) {
+ const tmp = EventRegistry.getUserFriendlySingularName(eventTypeName);
+ return tr.b.getOnlyElement(this.events_).userFriendlyName;
+ }
+
+ const numEventTypes = Object.keys(eventsByBaseType).length;
+ if (numEventTypes !== 1) {
+ return this.length + ' events of various types';
+ }
+
+ const tmp = EventRegistry.getUserFriendlyPluralName(eventTypeName);
+ return this.length + ' ' + tmp;
+ },
+
+ filter(fn, opt_this) {
+ const res = new EventSet();
+ for (const event of this) {
+ if (fn.call(opt_this, event)) {
+ res.push(event);
+ }
+ }
+
+ return res;
+ },
+
+ toArray() {
+ const ary = [];
+ for (const event of this) {
+ ary.push(event);
+ }
+ return ary;
+ },
+
+ forEach(fn, opt_this) {
+ for (const event of this) {
+ fn.call(opt_this, event);
+ }
+ },
+
+ map(fn, opt_this) {
+ const res = [];
+ for (const event of this) {
+ res.push(fn.call(opt_this, event));
+ }
+ return res;
+ },
+
+ every(fn, opt_this) {
+ for (const event of this) {
+ if (!fn.call(opt_this, event)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ some(fn, opt_this) {
+ for (const event of this) {
+ if (fn.call(opt_this, event)) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ asDict() {
+ const stableIds = [];
+ for (const event of this) {
+ stableIds.push(event.stableId);
+ }
+ return {'events': stableIds};
+ },
+
+ asSet() {
+ return this.events_;
+ }
+ };
+
+ EventSet.IMMUTABLE_EMPTY_SET = (function() {
+ const s = new EventSet();
+ s.push = function() {
+ throw new Error('Cannot push to an immutable event set');
+ };
+ s.addEventSet = function() {
+ throw new Error('Cannot add to an immutable event set');
+ };
+ Object.freeze(s);
+ return s;
+ })();
+
+ return {
+ EventSet,
+ RequestSelectionChangeEvent,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/event_set_test.html b/chromium/third_party/catapult/tracing/tracing/model/event_set_test.html
new file mode 100644
index 00000000000..9f597ed0984
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/event_set_test.html
@@ -0,0 +1,360 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newModel = tr.c.TestUtils.newModel;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ test('eventSetObject', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 5, {}, 1));
+
+ const eventSet = new tr.model.EventSet();
+ eventSet.push(t1.sliceGroup.slices[0]);
+
+ assert.strictEqual(eventSet.bounds.min, 1);
+ assert.strictEqual(eventSet.bounds.max, 4);
+ assert.deepEqual(eventSet.asSet(), new tr.model.EventSet(
+ t1.sliceGroup.slices[0]).asSet());
+
+ eventSet.push(t1.sliceGroup.slices[1]);
+ assert.strictEqual(eventSet.bounds.min, 1);
+ assert.strictEqual(eventSet.bounds.max, 6);
+ assert.deepEqual(eventSet.asSet(), new tr.model.EventSet(
+ [t1.sliceGroup.slices[0], t1.sliceGroup.slices[1]]).asSet());
+
+ eventSet.clear();
+ assert.strictEqual(eventSet.length, 0);
+ });
+
+ test('push_noEvents', function() {
+ const eventSet = new tr.model.EventSet();
+ eventSet.push();
+ assert.strictEqual(eventSet.length, 0);
+ });
+
+ test('push_oneEvent', function() {
+ const eventSet = new tr.model.EventSet();
+ eventSet.push({guid: 1});
+ assert.strictEqual(eventSet.length, 1);
+ });
+
+ test('push_multipleEvents', function() {
+ const eventSet = new tr.model.EventSet();
+ eventSet.push({guid: 1}, {guid: 2}, {guid: 3});
+ assert.strictEqual(eventSet.length, 3);
+ });
+
+ test('push_multiplePushes', function() {
+ const eventSet = new tr.model.EventSet();
+ eventSet.push({guid: 1}, {guid: 2}, {guid: 3});
+ eventSet.push({guid: 4}, {guid: 5}, {guid: 6});
+ assert.strictEqual(eventSet.length, 6);
+ });
+
+ test('push_noGuidThrows', function() {
+ const eventSet = new tr.model.EventSet();
+ assert.throws(() => eventSet.push({guid: 1}, {badItem: 2}, {guid: 3}),
+ 'Event must have a GUID');
+ });
+
+ test('iteration', function() {
+ const eventSet = new tr.model.EventSet([{guid: 1}, {guid: 2}, {guid: 3}]);
+
+ let expectedId = 1;
+ for (const event of eventSet) {
+ assert.strictEqual(event.guid, expectedId++);
+ }
+ });
+
+ test('uniqueContents', function() {
+ const sample1 = {guid: 1};
+ const sample2 = {guid: 2};
+
+ const eventSet = new tr.model.EventSet();
+
+ eventSet.push(sample1);
+ eventSet.push(sample2);
+ assert.strictEqual(eventSet.length, 2);
+
+ eventSet.push(sample1);
+ assert.strictEqual(eventSet.length, 2);
+ });
+
+ test('userFriendlyNameSingular', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ const selection = new tr.model.EventSet(t1.sliceGroup.slices[0]);
+ assert.isDefined(selection.userFriendlyName);
+ });
+
+ test('userFriendlyNamePlural', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3));
+ const eventSet = new tr.model.EventSet([
+ t1.sliceGroup.slices[0],
+ t1.sliceGroup.slices[1]
+ ]);
+ assert.isDefined(eventSet.userFriendlyName);
+ });
+
+ test('userFriendlyNameMixedPlural', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3));
+
+ const i10 = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'name', 10);
+ const s10 = i10.addSnapshot(10, {foo: 1});
+
+ const eventSet = new tr.model.EventSet([
+ t1.sliceGroup.slices[0],
+ s10
+ ]);
+ assert.isDefined(eventSet.userFriendlyName);
+ });
+
+ test('groupEventsByTitle', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'b', 0, 3, {}, 3));
+ const eventSet = new tr.model.EventSet([
+ t1.sliceGroup.slices[0],
+ t1.sliceGroup.slices[1],
+ t1.sliceGroup.slices[2]
+ ]);
+
+ const eventsByTitle = eventSet.getEventsOrganizedByTitle();
+ assert.strictEqual(2, Object.keys(eventsByTitle).length);
+ assert.sameMembers(eventsByTitle.a.toArray(),
+ [t1.sliceGroup.slices[0], t1.sliceGroup.slices[1]]);
+ assert.sameMembers(eventsByTitle.b.toArray(),
+ [t1.sliceGroup.slices[2]]);
+ });
+
+ test('groupEventsByCallback', function() {
+ const a1 = new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3);
+ const a2 = new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3);
+ const b1 = new tr.model.ThreadSlice('', 'b', 0, 1, {}, 3);
+ const eventSet = new tr.model.EventSet([a1, a2, b1]);
+ function getEventKey(event) {
+ return 's' + event.start;
+ }
+ const eventsByCallback = eventSet.getEventsOrganizedByCallback(getEventKey);
+ assert.strictEqual(2, Object.keys(eventsByCallback).length);
+ assert.sameMembers(eventsByCallback.s1.toArray(), [a1, b1]);
+ assert.sameMembers(eventsByCallback.s2.toArray(), [a2]);
+ });
+
+ test('groupEventsByBaseType', function() {
+ const a = new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3);
+ const b = new tr.model.ThreadSlice('', 'b', 0, 1, {}, 3);
+ const c = new tr.model.AsyncSlice('', 'c', 0, 1, {}, 3);
+ const eventSet = new tr.model.EventSet([a, b, c]);
+ let eventsByBaseType = eventSet.getEventsOrganizedByBaseType(true);
+ assert.strictEqual(2, Object.keys(eventsByBaseType).length);
+ assert.sameMembers(eventsByBaseType.slice.toArray(), [a, b]);
+ assert.sameMembers(eventsByBaseType.asyncSlice.toArray(), [c]);
+
+ eventsByBaseType = eventSet.getEventsOrganizedByBaseType(false);
+ assert.isTrue(2 < Object.keys(eventsByBaseType).length);
+ assert.sameMembers(eventsByBaseType.slice.toArray(), [a, b]);
+ assert.sameMembers(eventsByBaseType.asyncSlice.toArray(), [c]);
+ for (const baseType in eventsByBaseType) {
+ if (baseType !== 'slice' && baseType !== 'asyncSlice') {
+ assert.strictEqual(0, eventsByBaseType[baseType].length);
+ }
+ }
+ });
+
+ test('intersectionIsEmpty1', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'b', 0, 3, {}, 3));
+
+ const set1 = new tr.model.EventSet([
+ t1.sliceGroup.slices[0],
+ t1.sliceGroup.slices[1],
+ t1.sliceGroup.slices[2]
+ ]);
+ const set2 = new tr.model.EventSet([
+ t1.sliceGroup.slices[2]
+ ]);
+ assert.isFalse(set1.intersectionIsEmpty(set2));
+ });
+
+ test('intersectionIsNonEmpty2', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 2, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'b', 0, 3, {}, 3));
+
+ const set1 = new tr.model.EventSet([
+ t1.sliceGroup.slices[0],
+ t1.sliceGroup.slices[1]
+ ]);
+ const set2 = new tr.model.EventSet([
+ t1.sliceGroup.slices[2]
+ ]);
+ assert.isTrue(set1.intersectionIsEmpty(set2));
+ });
+
+ test('equals', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'b', 0, 2, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'c', 0, 3, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'd', 0, 4, {}, 5));
+
+ const eventSet1 = new tr.model.EventSet([
+ t1.sliceGroup.slices[0],
+ t1.sliceGroup.slices[1],
+ t1.sliceGroup.slices[2]
+ ]);
+ const eventSet2 = new tr.model.EventSet([
+ t1.sliceGroup.slices[1],
+ t1.sliceGroup.slices[0],
+ t1.sliceGroup.slices[2]
+ ]);
+ const eventSet3 = new tr.model.EventSet([
+ t1.sliceGroup.slices[1],
+ t1.sliceGroup.slices[0],
+ t1.sliceGroup.slices[3]
+ ]);
+ const eventSet4 = new tr.model.EventSet([
+ t1.sliceGroup.slices[1],
+ t1.sliceGroup.slices[0]
+ ]);
+ assert.isTrue(eventSet1.equals(eventSet2));
+ assert.isFalse(eventSet1.equals(eventSet3));
+ assert.isFalse(eventSet1.equals(eventSet4));
+ });
+
+ test('filter', function() {
+ const m = newModel(function(m) {
+ const p = m.getOrCreateProcess(1);
+ const t = p.getOrCreateThread(1);
+
+ m.s0 = t.sliceGroup.pushSlice(newSliceEx(
+ { title: 's0', start: 0.0, duration: 1.0 }));
+ m.s1 = t.sliceGroup.pushSlice(newSliceEx(
+ { title: 's1', start: 0.0, duration: 1.0 }));
+ m.s2 = t.sliceGroup.pushSlice(newSliceEx(
+ { title: 's2', start: 0.0, duration: 1.0 }));
+
+ m.eventSet = new tr.model.EventSet([m.s0, m.s1, m.s2]);
+ });
+
+ const res = m.eventSet.filter(function(slice) {
+ return slice.title === 's0';
+ });
+
+ assert.isTrue(res.equals(new tr.model.EventSet([m.s0])));
+ });
+
+ test('toArray', function() {
+ const samples = [
+ {guid: 1},
+ {guid: 2}
+ ];
+ const eventSet = new tr.model.EventSet(samples);
+
+ assert.deepEqual(eventSet.toArray(), samples);
+ });
+
+ test('asDict', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'b', 0, 2, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'c', 0, 3, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'd', 0, 4, {}, 5));
+
+ const eventSet = new tr.model.EventSet([
+ t1.sliceGroup.slices[0],
+ t1.sliceGroup.slices[1],
+ t1.sliceGroup.slices[2]
+ ]);
+
+ assert.deepEqual(
+ {'events':
+ ['1.1.SliceGroup.0', '1.1.SliceGroup.1', '1.1.SliceGroup.2']},
+ eventSet.asDict());
+ });
+
+ test('immutableEmptySet', function() {
+ const s = tr.model.EventSet.IMMUTABLE_EMPTY_SET;
+ assert.lengthOf(s, 0);
+ assert.isTrue(s.bounds.isEmpty);
+
+ // Check that the iteration methods still work correctly.
+ function throwOnCall() {
+ throw new Error('This function should never be called!!!');
+ }
+ assert.deepEqual(s.map(throwOnCall), []);
+ s.forEach(throwOnCall);
+
+ // Check that the set is indeed immutable.
+ assert.throws(function() { s[0] = b; });
+ assert.throws(function() { s.push(b); });
+ assert.throws(function() { s.addEventSet(new tr.model.EventSet()); });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/event_test.html b/chromium/third_party/catapult/tracing/tracing/model/event_test.html
new file mode 100644
index 00000000000..efbf26b1d13
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/event_test.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/alert.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/event_info.html">
+<link rel="import" href="/tracing/model/event_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Alert = tr.model.Alert;
+ const Event = tr.model.Event;
+ const EventInfo = tr.model.EventInfo;
+ const EventSet = tr.model.EventSet;
+ const ImmutableEventSet = tr.model.ImmutableEventSet;
+
+ test('checkModelItem', function() {
+ const event = new Event;
+ assert.strictEqual(event.modelItem, event);
+ });
+
+ test('checkAssociatedAlerts', function() {
+ const event = new Event();
+ assert.strictEqual(event.associatedAlerts, EventSet.IMMUTABLE_EMPTY_SET);
+ assert.sameMembers(event.associatedAlerts.toArray(), []);
+
+ const info1 = new EventInfo('Critical', 'Critical alert!!!', []);
+ const alert1 = new Alert(info1, 7);
+ event.addAssociatedAlert(alert1);
+ assert.instanceOf(event.associatedAlerts, EventSet);
+ assert.sameMembers(event.associatedAlerts.toArray(), [alert1]);
+
+ const info2 = new EventInfo('Warning', 'Warning alert???', []);
+ const alert2 = new Alert(info2, 42);
+ event.addAssociatedAlert(alert2);
+ assert.instanceOf(event.associatedAlerts, EventSet);
+ assert.sameMembers(event.associatedAlerts.toArray(), [alert1, alert2]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/flow_event.html b/chromium/third_party/catapult/tracing/tracing/model/flow_event.html
new file mode 100644
index 00000000000..9b85217d6f8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/flow_event.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Flow class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * A Flow represents an interval of time plus parameters associated
+ * with that interval.
+ *
+ * @constructor
+ */
+ function FlowEvent(category, id, title, colorId, start, args, opt_duration) {
+ tr.model.TimedEvent.call(this, start);
+
+ this.category = category || '';
+ this.title = title;
+ this.colorId = colorId;
+ this.start = start;
+ this.args = args;
+
+ this.id = id;
+
+ this.startSlice = undefined;
+ this.endSlice = undefined;
+
+ this.startStackFrame = undefined;
+ this.endStackFrame = undefined;
+
+ if (opt_duration !== undefined) {
+ this.duration = opt_duration;
+ }
+ }
+
+ FlowEvent.prototype = {
+ __proto__: tr.model.TimedEvent.prototype,
+
+ get userFriendlyName() {
+ return 'Flow event named ' + this.title + ' at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.timestamp);
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ FlowEvent,
+ {
+ name: 'flowEvent',
+ pluralName: 'flowEvents'
+ });
+
+ return {
+ FlowEvent,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/frame.html b/chromium/third_party/catapult/tracing/tracing/model/frame.html
new file mode 100644
index 00000000000..6d1051a603d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/frame.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/event_set.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Class describing rendered frames.
+ *
+ * Because a frame is produced by multiple threads, it does not inherit from
+ * TimedEvent, and has no duration.
+ */
+tr.exportTo('tr.model', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Statistics = tr.b.math.Statistics;
+
+ const FRAME_PERF_CLASS = {
+ GOOD: 'good',
+ BAD: 'bad',
+ TERRIBLE: 'terrible',
+ NEUTRAL: 'generic_work'
+ };
+
+ /**
+ * @constructor
+ * @param {Array} associatedEvents Selection of events composing the frame.
+ * @param {Array} threadTimeRanges Array of {thread, start, end}
+ * for each thread, describing the critical path of the frame.
+ */
+ function Frame(associatedEvents, threadTimeRanges, opt_args) {
+ tr.model.Event.call(this);
+
+ this.threadTimeRanges = threadTimeRanges;
+ this.associatedEvents = new tr.model.EventSet(associatedEvents);
+ this.args = opt_args || {};
+
+ this.title = 'Frame';
+ this.start = Statistics.min(
+ threadTimeRanges, function(x) { return x.start; });
+ this.end = Statistics.max(
+ threadTimeRanges, function(x) { return x.end; });
+ this.totalDuration = Statistics.sum(
+ threadTimeRanges, function(x) { return x.end - x.start; });
+
+ this.perfClass = FRAME_PERF_CLASS.NEUTRAL;
+ }
+
+ Frame.prototype = {
+ __proto__: tr.model.Event.prototype,
+
+ set perfClass(perfClass) {
+ this.colorId = ColorScheme.getColorIdForReservedName(perfClass);
+ this.perfClass_ = perfClass;
+ },
+
+ get perfClass() {
+ return this.perfClass_;
+ },
+
+ shiftTimestampsForward(amount) {
+ this.start += amount;
+ this.end += amount;
+
+ for (let i = 0; i < this.threadTimeRanges.length; i++) {
+ this.threadTimeRanges[i].start += amount;
+ this.threadTimeRanges[i].end += amount;
+ }
+ },
+
+ addBoundsToRange(range) {
+ range.addValue(this.start);
+ range.addValue(this.end);
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ Frame,
+ {
+ name: 'frame',
+ pluralName: 'frames'
+ });
+
+ return {
+ Frame,
+ FRAME_PERF_CLASS,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/global_memory_dump.html b/chromium/third_party/catapult/tracing/tracing/model/global_memory_dump.html
new file mode 100644
index 00000000000..058f52f14e9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/global_memory_dump.html
@@ -0,0 +1,849 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/event_registry.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the GlobalMemoryDump class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * The GlobalMemoryDump represents a simultaneous memory dump of all
+ * processes.
+ * @constructor
+ */
+ function GlobalMemoryDump(model, start) {
+ tr.model.ContainerMemoryDump.call(this, start);
+ this.model = model;
+ this.processMemoryDumps = {};
+ }
+
+ // Size numeric names.
+ const SIZE_NUMERIC_NAME = tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME;
+ const EFFECTIVE_SIZE_NUMERIC_NAME =
+ tr.model.MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME;
+
+ // Size numeric info types.
+ const MemoryAllocatorDumpInfoType = tr.model.MemoryAllocatorDumpInfoType;
+ const PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN =
+ MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN;
+ const PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER =
+ MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER;
+
+ function getSize(dump) {
+ const numeric = dump.numerics[SIZE_NUMERIC_NAME];
+ if (numeric === undefined) return 0;
+ return numeric.value;
+ }
+
+ function hasSize(dump) {
+ return dump.numerics[SIZE_NUMERIC_NAME] !== undefined;
+ }
+
+ function optional(value, defaultValue) {
+ if (value === undefined) return defaultValue;
+ return value;
+ }
+
+ GlobalMemoryDump.prototype = {
+ __proto__: tr.model.ContainerMemoryDump.prototype,
+
+ get userFriendlyName() {
+ return 'Global memory dump at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.start);
+ },
+
+ get containerName() {
+ return 'global space';
+ },
+
+ finalizeGraph() {
+ // 1. Transitively remove weak memory allocator dumps and all their
+ // owners and descendants from the model. This must be performed before
+ // any other steps.
+ this.removeWeakDumps();
+
+ // 2. Add ownership links from tracing MADs to descendants of malloc or
+ // winheap MADs so that tracing would be automatically discounted from
+ // them later (step 3).
+ this.setUpTracingOverheadOwnership();
+
+ // 3. Aggregate all other numerics of all MADs (*excluding* sizes and
+ // effective sizes) and propagate numerics from global MADs to their
+ // owners (*including* sizes and effective sizes). This step must be
+ // carried out before the sizes of all MADs are calculated (step 3).
+ // Otherwise, the propagated sizes of all MADs would not be aggregated.
+ this.aggregateNumerics();
+
+ // 4. Calculate the sizes of all memory allocator dumps (MADs). This step
+ // requires that the memory allocator dump graph has been finalized (step
+ // 1) and numerics were propagated from global MADs (step 2). Subsequent
+ // modifications of the graph will most likely break the calculation
+ // invariants.
+ this.calculateSizes();
+
+ // 5. Calculate the effective sizes of all MADs. This step requires that
+ // the sizes of all MADs have already been calculated (step 3).
+ this.calculateEffectiveSizes();
+
+ // 6. Discount tracing from VM regions stats. This steps requires that
+ // resident sizes (step 2) and sizes (step 3) of the tracing MADs have
+ // already been calculated.
+ this.discountTracingOverheadFromVmRegions();
+
+ // 7. The above steps (especially steps 1 and 3) can create new memory
+ // allocator dumps, so we force rebuilding the memory allocator dump
+ // indices of all container memory dumps.
+ this.forceRebuildingMemoryAllocatorDumpByFullNameIndices();
+ },
+
+ removeWeakDumps() {
+ // Mark all transitive owners and children of weak memory allocator dumps
+ // as weak.
+ this.traverseAllocatorDumpsInDepthFirstPreOrder(function(dump) {
+ if (dump.weak) return;
+ if ((dump.owns !== undefined && dump.owns.target.weak) ||
+ (dump.parent !== undefined && dump.parent.weak)) {
+ dump.weak = true;
+ }
+ });
+
+ function removeWeakDumpsFromListRecursively(dumps) {
+ tr.b.inPlaceFilter(dumps, function(dump) {
+ if (dump.weak) {
+ // The dump is weak, so remove it. This will implicitly remove all
+ // its descendants, which are also weak due to the initial marking
+ // step.
+ return false;
+ }
+
+ // This dump is non-weak, so keep it. Recursively remove its weak
+ // descendants and ownership links from weak dumps instead.
+ removeWeakDumpsFromListRecursively(dump.children);
+ tr.b.inPlaceFilter(dump.ownedBy, function(ownershipLink) {
+ return !ownershipLink.source.weak;
+ });
+
+ return true;
+ });
+ }
+
+ this.iterateContainerDumps(function(containerDump) {
+ const memoryAllocatorDumps = containerDump.memoryAllocatorDumps;
+ if (memoryAllocatorDumps !== undefined) {
+ removeWeakDumpsFromListRecursively(memoryAllocatorDumps);
+ }
+ });
+ },
+
+ /**
+ * Calculate the size of all memory allocator dumps in the dump graph.
+ *
+ * The size refers to the allocated size of a (sub)component. It is a
+ * natural extension of the optional size numeric provided by
+ * MemoryAllocatorDump(s):
+ *
+ * - If a MAD provides a size numeric, then its size is assumed to be
+ * equal to it.
+ * - If a MAD does not provide a size numeric, then its size is assumed
+ * to be the maximum of (1) the size of the largest owner of the MAD
+ * and (2) the aggregated size of the MAD's children.
+ *
+ * Metric motivation: "How big is a (sub)system?"
+ *
+ * Please refer to the Memory Dump Graph Metric Calculation design document
+ * for more details (https://goo.gl/fKg0dt).
+ */
+ calculateSizes() {
+ this.traverseAllocatorDumpsInDepthFirstPostOrder(
+ this.calculateMemoryAllocatorDumpSize_.bind(this));
+ },
+
+ /**
+ * Calculate the size of the given MemoryAllocatorDump. This method assumes
+ * that the size of both the children and owners of the dump has already
+ * been calculated.
+ */
+ calculateMemoryAllocatorDumpSize_(dump) {
+ // This flag becomes true if the size numeric of the current dump should
+ // be defined, i.e. if (1) the current dump's size numeric is defined,
+ // (2) the size of at least one of its children is defined or (3) the
+ // size of at least one of its owners is defined.
+ let shouldDefineSize = false;
+
+ // This helper function returns the value of the size numeric of the
+ // given dependent memory allocator dump. If the numeric is defined, the
+ // shouldDefineSize flag above is also set to true (because condition
+ // (2) or (3) is satisfied). Otherwise, zero is returned (and the flag is
+ // left unchanged).
+ function getDependencySize(dependencyDump) {
+ const numeric = dependencyDump.numerics[SIZE_NUMERIC_NAME];
+ if (numeric === undefined) return 0;
+ shouldDefineSize = true;
+ return numeric.value;
+ }
+
+ // 1. Get the size provided by the dump. If present, define a function
+ // for checking dependent size consistency (a dump must always be bigger
+ // than all its children aggregated together and/or its largest owner).
+ const sizeNumeric = dump.numerics[SIZE_NUMERIC_NAME];
+ let size = 0;
+ let checkDependencySizeIsConsistent = function() { /* no-op */ };
+ if (sizeNumeric !== undefined) {
+ size = sizeNumeric.value;
+ shouldDefineSize = true;
+ if (sizeNumeric.unit !== tr.b.Unit.byName.sizeInBytes_smallerIsBetter) {
+ this.model.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Invalid unit of \'size\' numeric of memory allocator ' +
+ 'dump ' + dump.quantifiedName + ': ' +
+ sizeNumeric.unit.unitName + '.'
+ });
+ }
+ checkDependencySizeIsConsistent = function(
+ dependencySize, dependencyInfoType, dependencyName) {
+ if (size >= dependencySize) return;
+ this.model.importWarning({
+ type: 'memory_dump_parse_error',
+ message: 'Size provided by memory allocator dump \'' +
+ dump.fullName + '\'' +
+ tr.b.Unit.byName.sizeInBytes.format(size) +
+ ') is less than ' + dependencyName + ' (' +
+ tr.b.Unit.byName.sizeInBytes.format(dependencySize) + ').'
+ });
+ dump.infos.push({
+ type: dependencyInfoType,
+ providedSize: size,
+ dependencySize
+ });
+ }.bind(this);
+ }
+
+ // 2. Aggregate size of children. The recursive function traverses all
+ // descendants and ensures that double-counting due to ownership within a
+ // subsystem is avoided.
+ let aggregatedChildrenSize = 0;
+ // Owned child dump name -> (Owner child dump name -> overlapping size).
+ const allOverlaps = {};
+ dump.children.forEach(function(childDump) {
+ function aggregateDescendantDump(descendantDump) {
+ // Don't count this descendant dump if it owns another descendant of
+ // the current dump (would cause double-counting).
+ const ownedDumpLink = descendantDump.owns;
+ if (ownedDumpLink !== undefined &&
+ ownedDumpLink.target.isDescendantOf(dump)) {
+ // If the target owned dump is a descendant of a *different* child
+ // of the the current dump (i.e. not childDump), then we remember
+ // the ownership so that we could explain why the size of the
+ // current dump is not equal to the sum of its children.
+ let ownedChildDump = ownedDumpLink.target;
+ while (ownedChildDump.parent !== dump) {
+ ownedChildDump = ownedChildDump.parent;
+ }
+ if (childDump !== ownedChildDump) {
+ const ownedBySiblingSize = getDependencySize(descendantDump);
+ if (ownedBySiblingSize > 0) {
+ const previousTotalOwnedBySiblingSize =
+ ownedChildDump.ownedBySiblingSizes.get(childDump) || 0;
+ const updatedTotalOwnedBySiblingSize =
+ previousTotalOwnedBySiblingSize + ownedBySiblingSize;
+ ownedChildDump.ownedBySiblingSizes.set(
+ childDump, updatedTotalOwnedBySiblingSize);
+ }
+ }
+ return;
+ }
+
+ // If this descendant dump is a leaf node, add its size to the
+ // aggregated size.
+ if (descendantDump.children.length === 0) {
+ aggregatedChildrenSize += getDependencySize(descendantDump);
+ return;
+ }
+
+ // If this descendant dump is an intermediate node, recurse down into
+ // its children. Note that the dump's size is NOT added because it is
+ // an aggregate of its children (would cause double-counting).
+ descendantDump.children.forEach(aggregateDescendantDump);
+ }
+ aggregateDescendantDump(childDump);
+ });
+ checkDependencySizeIsConsistent(
+ aggregatedChildrenSize,
+ PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN,
+ 'the aggregated size of its children');
+
+ // 3. Calculate the largest owner size.
+ let largestOwnerSize = 0;
+ dump.ownedBy.forEach(function(ownershipLink) {
+ const owner = ownershipLink.source;
+ const ownerSize = getDependencySize(owner);
+ largestOwnerSize = Math.max(largestOwnerSize, ownerSize);
+ });
+ checkDependencySizeIsConsistent(
+ largestOwnerSize,
+ PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER,
+ 'the size of its largest owner');
+
+ // If neither the dump nor any of its dependencies (children and owners)
+ // provide a size, do NOT add a zero size numeric.
+ if (!shouldDefineSize) {
+ // The rest of the pipeline relies on size being either a valid
+ // Scalar, or undefined.
+ delete dump.numerics[SIZE_NUMERIC_NAME];
+ return;
+ }
+
+ // A dump must always be bigger than all its children aggregated
+ // together and/or its largest owner.
+ size = Math.max(size, aggregatedChildrenSize, largestOwnerSize);
+
+ dump.numerics[SIZE_NUMERIC_NAME] = new tr.b.Scalar(
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, size);
+
+ // Add a virtual child to make up for extra size of the dump with
+ // respect to its children (if applicable).
+ if (aggregatedChildrenSize < size &&
+ dump.children !== undefined && dump.children.length > 0) {
+ const virtualChild = new tr.model.MemoryAllocatorDump(
+ dump.containerMemoryDump, dump.fullName + '/<unspecified>');
+ virtualChild.parent = dump;
+ dump.children.unshift(virtualChild);
+ virtualChild.numerics[SIZE_NUMERIC_NAME] = new tr.b.Scalar(
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter,
+ size - aggregatedChildrenSize);
+ }
+ },
+
+ /**
+ * Calculate the effective size of all memory allocator dumps in the dump
+ * graph.
+ *
+ * The effective size refers to the amount of memory a particular component
+ * is using/consuming. In other words, every (reported) byte of used memory
+ * is uniquely attributed to exactly one component. Consequently, unlike
+ * size, effective size is cumulative, i.e. the sum of the effective sizes
+ * of (top-level) components is equal to the total amount of (reported)
+ * used memory.
+ *
+ * Metric motivation: "How much memory does a (sub)system use?" or "For how
+ * much memory should a (sub)system be 'charged'?"
+ *
+ * Please refer to the Memory Dump Graph Metric Calculation design document
+ * for more details (https://goo.gl/fKg0dt).
+ *
+ * This method assumes that the size of all contained memory allocator
+ * dumps has already been calculated [see calculateSizes()].
+ */
+ calculateEffectiveSizes() {
+ // 1. Calculate not-owned and not-owning sub-sizes of all MADs
+ // (depth-first post-order traversal).
+ this.traverseAllocatorDumpsInDepthFirstPostOrder(
+ this.calculateDumpSubSizes_.bind(this));
+
+ // 2. Calculate owned and owning coefficients of owned and owner MADs
+ // respectively (arbitrary traversal).
+ this.traverseAllocatorDumpsInDepthFirstPostOrder(
+ this.calculateDumpOwnershipCoefficient_.bind(this));
+
+ // 3. Calculate cumulative owned and owning coefficients of all MADs
+ // (depth-first pre-order traversal).
+ this.traverseAllocatorDumpsInDepthFirstPreOrder(
+ this.calculateDumpCumulativeOwnershipCoefficient_.bind(this));
+
+ // 4. Calculate the effective sizes of all MADs (depth-first post-order
+ // traversal).
+ this.traverseAllocatorDumpsInDepthFirstPostOrder(
+ this.calculateDumpEffectiveSize_.bind(this));
+ },
+
+ /**
+ * Calculate not-owned and not-owning sub-sizes of a memory allocator dump
+ * from its children's (sub-)sizes.
+ *
+ * Not-owned sub-size refers to the aggregated memory of all children which
+ * is not owned by other MADs. Conversely, not-owning sub-size is the
+ * aggregated memory of all children which do not own another MAD. The
+ * diagram below illustrates these two concepts:
+ *
+ * ROOT 1 ROOT 2
+ * size: 4 size: 5
+ * not-owned sub-size: 4 not-owned sub-size: 1 (!)
+ * not-owning sub-size: 0 (!) not-owning sub-size: 5
+ *
+ * ^ ^
+ * | |
+ *
+ * PARENT 1 ===== owns =====> PARENT 2
+ * size: 4 size: 5
+ * not-owned sub-size: 4 not-owned sub-size: 5
+ * not-owning sub-size: 4 not-owning sub-size: 5
+ *
+ * ^ ^
+ * | |
+ *
+ * CHILD 1 CHILD 2
+ * size [given]: 4 size [given]: 5
+ * not-owned sub-size: 4 not-owned sub-size: 5
+ * not-owning sub-size: 4 not-owning sub-size: 5
+ *
+ * This method assumes that (1) the size of the dump, its children, and its
+ * owners [see calculateSizes()] and (2) the not-owned and not-owning
+ * sub-sizes of both the children and owners of the dump have already been
+ * calculated [depth-first post-order traversal].
+ */
+ calculateDumpSubSizes_(dump) {
+ // Completely skip dumps with undefined size.
+ if (!hasSize(dump)) return;
+
+ // If the dump is a leaf node, then both sub-sizes are equal to the size.
+ if (dump.children === undefined || dump.children.length === 0) {
+ const size = getSize(dump);
+ dump.notOwningSubSize_ = size;
+ dump.notOwnedSubSize_ = size;
+ return;
+ }
+
+ // Calculate this dump's not-owning sub-size by summing up the not-owning
+ // sub-sizes of children MADs which do not own another MAD.
+ let notOwningSubSize = 0;
+ dump.children.forEach(function(childDump) {
+ if (childDump.owns !== undefined) return;
+ notOwningSubSize += optional(childDump.notOwningSubSize_, 0);
+ });
+ dump.notOwningSubSize_ = notOwningSubSize;
+
+ // Calculate this dump's not-owned sub-size.
+ let notOwnedSubSize = 0;
+ dump.children.forEach(function(childDump) {
+ // If the child dump is not owned, then add its not-owned sub-size.
+ if (childDump.ownedBy.length === 0) {
+ notOwnedSubSize += optional(childDump.notOwnedSubSize_, 0);
+ return;
+ }
+ // If the child dump is owned, then add the difference between its size
+ // and the largest owner.
+ let largestChildOwnerSize = 0;
+ childDump.ownedBy.forEach(function(ownershipLink) {
+ largestChildOwnerSize = Math.max(
+ largestChildOwnerSize, getSize(ownershipLink.source));
+ });
+ notOwnedSubSize += getSize(childDump) - largestChildOwnerSize;
+ });
+ dump.notOwnedSubSize_ = notOwnedSubSize;
+ },
+
+ /**
+ * Calculate owned and owning coefficients of a memory allocator dump and
+ * its owners.
+ *
+ * The owning coefficient refers to the proportion of a dump's not-owning
+ * sub-size which is attributed to the dump (only relevant to owning MADs).
+ * Conversely, the owned coefficient is the proportion of a dump's
+ * not-owned sub-size, which is attributed to it (only relevant to owned
+ * MADs).
+ *
+ * The not-owned size of the owned dump is split among its owners in the
+ * order of the ownership importance as demonstrated by the following
+ * example:
+ *
+ * memory allocator dumps
+ * OWNED OWNER1 OWNER2 OWNER3 OWNER4
+ * not-owned sub-size [given] 10 - - - -
+ * not-owning sub-size [given] - 6 7 5 8
+ * importance [given] - 2 2 1 0
+ * attributed not-owned sub-size 2 - - - -
+ * attributed not-owning sub-size - 3 4 0 1
+ * owned coefficient 2/10 - - - -
+ * owning coefficient - 3/6 4/7 0/5 1/8
+ *
+ * Explanation: Firstly, 6 bytes are split equally among OWNER1 and OWNER2
+ * (highest importance). OWNER2 owns one more byte, so its attributed
+ * not-owning sub-size is 6/2 + 1 = 4 bytes. OWNER3 is attributed no size
+ * because it is smaller than the owners with higher priority. However,
+ * OWNER4 is larger, so it's attributed the difference 8 - 7 = 1 byte.
+ * Finally, 2 bytes remain unattributed and are hence kept in the OWNED
+ * dump as attributed not-owned sub-size. The coefficients are then
+ * directly calculated as fractions of the sub-sizes and corresponding
+ * attributed sub-sizes.
+ *
+ * Note that we always assume that all ownerships of a dump overlap (e.g.
+ * OWNER3 is subsumed by both OWNER1 and OWNER2). Hence, the table could
+ * be alternatively represented as follows:
+ *
+ * owned memory range
+ * 0 1 2 3 4 5 6 7 8 9 10
+ * Priority 2 | OWNER1 + OWNER2 (split) | OWNER2 |
+ * Priority 1 | (already attributed) |
+ * Priority 0 | - - - (already attributed) - - - | OWNER4 |
+ * Remainder | - - - - - (already attributed) - - - - - - | OWNED |
+ *
+ * This method assumes that (1) the size of the dump [see calculateSizes()]
+ * and (2) the not-owned size of the dump and not-owning sub-sizes of its
+ * owners [see the first step of calculateEffectiveSizes()] have already
+ * been calculated. Note that the method doesn't make any assumptions about
+ * the order in which dumps are visited.
+ */
+ calculateDumpOwnershipCoefficient_(dump) {
+ // Completely skip dumps with undefined size.
+ if (!hasSize(dump)) return;
+
+ // We only need to consider owned dumps.
+ if (dump.ownedBy.length === 0) return;
+
+ // Sort the owners in decreasing order of ownership importance and
+ // increasing order of not-owning sub-size (in case of equal importance).
+ const owners = dump.ownedBy.map(function(ownershipLink) {
+ return {
+ dump: ownershipLink.source,
+ importance: optional(ownershipLink.importance, 0),
+ notOwningSubSize: optional(ownershipLink.source.notOwningSubSize_, 0)
+ };
+ });
+ owners.sort(function(a, b) {
+ if (a.importance === b.importance) {
+ return a.notOwningSubSize - b.notOwningSubSize;
+ }
+ return b.importance - a.importance;
+ });
+
+ // Loop over the list of owners and distribute the owned dump's not-owned
+ // sub-size among them according to their ownership importance and
+ // not-owning sub-size.
+ let currentImportanceStartPos = 0;
+ let alreadyAttributedSubSize = 0;
+ while (currentImportanceStartPos < owners.length) {
+ const currentImportance = owners[currentImportanceStartPos].importance;
+
+ // Find the position of the first owner with lower priority.
+ let nextImportanceStartPos = currentImportanceStartPos + 1;
+ while (nextImportanceStartPos < owners.length &&
+ owners[nextImportanceStartPos].importance ===
+ currentImportance) {
+ nextImportanceStartPos++;
+ }
+
+ // Visit the owners with the same importance in increasing order of
+ // not-owned sub-size, split the owned memory among them appropriately,
+ // and calculate their owning coefficients.
+ let attributedNotOwningSubSize = 0;
+ for (let pos = currentImportanceStartPos; pos < nextImportanceStartPos;
+ pos++) {
+ const owner = owners[pos];
+ const notOwningSubSize = owner.notOwningSubSize;
+ if (notOwningSubSize > alreadyAttributedSubSize) {
+ attributedNotOwningSubSize +=
+ (notOwningSubSize - alreadyAttributedSubSize) /
+ (nextImportanceStartPos - pos);
+ alreadyAttributedSubSize = notOwningSubSize;
+ }
+
+ let owningCoefficient = 0;
+ if (notOwningSubSize !== 0) {
+ owningCoefficient = attributedNotOwningSubSize / notOwningSubSize;
+ }
+ owner.dump.owningCoefficient_ = owningCoefficient;
+ }
+
+ currentImportanceStartPos = nextImportanceStartPos;
+ }
+
+ // Attribute the remainder of the owned dump's not-owned sub-size to
+ // the dump itself and calculate its owned coefficient.
+ const notOwnedSubSize = optional(dump.notOwnedSubSize_, 0);
+ const remainderSubSize = notOwnedSubSize - alreadyAttributedSubSize;
+ let ownedCoefficient = 0;
+ if (notOwnedSubSize !== 0) {
+ ownedCoefficient = remainderSubSize / notOwnedSubSize;
+ }
+ dump.ownedCoefficient_ = ownedCoefficient;
+ },
+
+ /**
+ * Calculate cumulative owned and owning coefficients of a memory allocator
+ * dump from its (non-cumulative) owned and owning coefficients and the
+ * cumulative coefficients of its parent and/or owned dump.
+ *
+ * The cumulative coefficients represent the total effect of all
+ * (non-strict) ancestor ownerships on a memory allocator dump. The
+ * cumulative owned coefficient of a MAD can be calculated simply as:
+ *
+ * cumulativeOwnedC(M) = ownedC(M) * cumulativeOwnedC(parent(M))
+ *
+ * This reflects the assumption that if a parent of a child MAD is
+ * (partially) owned, then the parent's owner also indirectly owns (a part
+ * of) the child MAD.
+ *
+ * The cumulative owning coefficient of a MAD depends on whether the MAD
+ * owns another dump:
+ *
+ * [if M doesn't own another MAD]
+ * / cumulativeOwningC(parent(M))
+ * cumulativeOwningC(M) =
+ * \ [if M owns another MAD]
+ * owningC(M) * cumulativeOwningC(owned(M))
+ *
+ * The reasoning behind the first case is similar to the one for cumulative
+ * owned coefficient above. The only difference is that we don't need to
+ * include the dump's (non-cumulative) owning coefficient because it is
+ * implicitly 1.
+ *
+ * The formula for the second case is derived as follows: Since the MAD
+ * owns another dump, its memory is not included in its parent's not-owning
+ * sub-size and hence shouldn't be affected by the parent's corresponding
+ * cumulative coefficient. Instead, the MAD indirectly owns everything
+ * owned by its owned dump (and so it should be affected by the
+ * corresponding coefficient).
+ *
+ * Note that undefined coefficients (and coefficients of non-existent
+ * dumps) are implicitly assumed to be 1.
+ *
+ * This method assumes that (1) the size of the dump [see calculateSizes()],
+ * (2) the (non-cumulative) owned and owning coefficients of the dump [see
+ * the second step of calculateEffectiveSizes()], and (3) the cumulative
+ * coefficients of the dump's parent and owned MADs (if present)
+ * [depth-first pre-order traversal] have already been calculated.
+ */
+ calculateDumpCumulativeOwnershipCoefficient_(dump) {
+ // Completely skip dumps with undefined size.
+ if (!hasSize(dump)) return;
+
+ let cumulativeOwnedCoefficient = optional(dump.ownedCoefficient_, 1);
+ const parent = dump.parent;
+ if (dump.parent !== undefined) {
+ cumulativeOwnedCoefficient *= dump.parent.cumulativeOwnedCoefficient_;
+ }
+ dump.cumulativeOwnedCoefficient_ = cumulativeOwnedCoefficient;
+
+ let cumulativeOwningCoefficient;
+ if (dump.owns !== undefined) {
+ cumulativeOwningCoefficient = dump.owningCoefficient_ *
+ dump.owns.target.cumulativeOwningCoefficient_;
+ } else if (dump.parent !== undefined) {
+ cumulativeOwningCoefficient = dump.parent.cumulativeOwningCoefficient_;
+ } else {
+ cumulativeOwningCoefficient = 1;
+ }
+ dump.cumulativeOwningCoefficient_ = cumulativeOwningCoefficient;
+ },
+
+ /**
+ * Calculate the effective size of a memory allocator dump.
+ *
+ * In order to simplify the (already complex) calculation, we use the fact
+ * that effective size is cumulative (unlike regular size), i.e. the
+ * effective size of a non-leaf node is equal to the sum of effective sizes
+ * of its children. The effective size of a leaf MAD is calculated as:
+ *
+ * effectiveSize(M) = size(M) * cumulativeOwningC(M) * cumulativeOwnedC(M)
+ *
+ * This method assumes that (1) the size of the dump and its children [see
+ * calculateSizes()] and (2) the cumulative owning and owned coefficients
+ * of the dump (if it's a leaf node) [see the third step of
+ * calculateEffectiveSizes()] or the effective sizes of its children (if
+ * it's a non-leaf node) [depth-first post-order traversal] have already
+ * been calculated.
+ */
+ calculateDumpEffectiveSize_(dump) {
+ // Completely skip dumps with undefined size. As a result, each dump will
+ // have defined effective size if and only if it has defined size.
+ if (!hasSize(dump)) {
+ // The rest of the pipeline relies on effective size being either a
+ // valid Scalar, or undefined.
+ delete dump.numerics[EFFECTIVE_SIZE_NUMERIC_NAME];
+ return;
+ }
+
+ let effectiveSize;
+ if (dump.children === undefined || dump.children.length === 0) {
+ // Leaf dump.
+ effectiveSize = getSize(dump) * dump.cumulativeOwningCoefficient_ *
+ dump.cumulativeOwnedCoefficient_;
+ } else {
+ // Non-leaf dump.
+ effectiveSize = 0;
+ dump.children.forEach(function(childDump) {
+ if (!hasSize(childDump)) return;
+ effectiveSize +=
+ childDump.numerics[EFFECTIVE_SIZE_NUMERIC_NAME].value;
+ });
+ }
+ dump.numerics[EFFECTIVE_SIZE_NUMERIC_NAME] = new tr.b.Scalar(
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, effectiveSize);
+ },
+
+ aggregateNumerics() {
+ // 1. Aggregate numerics in this global memory dump.
+ this.iterateRootAllocatorDumps(function(dump) {
+ dump.aggregateNumericsRecursively(this.model);
+ });
+
+ // 2. Propagate numerics and diagnostics from global memory allocator
+ // dumps to their owners.
+ this.iterateRootAllocatorDumps(
+ this.propagateNumericsAndDiagnosticsRecursively);
+
+ // 3. Aggregate numerics in the associated process memory dumps.
+ for (const processMemoryDump of Object.values(this.processMemoryDumps)) {
+ processMemoryDump.iterateRootAllocatorDumps(function(dump) {
+ dump.aggregateNumericsRecursively(this.model);
+ }, this);
+ }
+ },
+
+ propagateNumericsAndDiagnosticsRecursively(globalAllocatorDump) {
+ ['numerics', 'diagnostics'].forEach(function(field) {
+ for (const [name, value] of
+ Object.entries(globalAllocatorDump[field])) {
+ globalAllocatorDump.ownedBy.forEach(function(ownershipLink) {
+ const processAllocatorDump = ownershipLink.source;
+ if (processAllocatorDump[field][name] !== undefined) {
+ // Numerics and diagnostics provided by process memory allocator
+ // dumps themselves have precedence over numerics and diagnostics
+ // propagated from global memory allocator dumps.
+ return;
+ }
+ processAllocatorDump[field][name] = value;
+ });
+ }
+ });
+
+ // Recursively propagate numerics from all child memory allocator dumps.
+ globalAllocatorDump.children.forEach(
+ this.propagateNumericsAndDiagnosticsRecursively, this);
+ },
+
+ setUpTracingOverheadOwnership() {
+ for (const dump of Object.values(this.processMemoryDumps)) {
+ dump.setUpTracingOverheadOwnership(this.model);
+ }
+ },
+
+ discountTracingOverheadFromVmRegions() {
+ // TODO(petrcermak): Consider factoring out all the finalization code and
+ // constants to a single file.
+ for (const dump of Object.values(this.processMemoryDumps)) {
+ dump.discountTracingOverheadFromVmRegions(this.model);
+ }
+ },
+
+ forceRebuildingMemoryAllocatorDumpByFullNameIndices() {
+ this.iterateContainerDumps(function(containerDump) {
+ containerDump.forceRebuildingMemoryAllocatorDumpByFullNameIndex();
+ });
+ },
+
+ iterateContainerDumps(fn) {
+ fn.call(this, this);
+ for (const processDump of Object.values(this.processMemoryDumps)) {
+ fn.call(this, processDump);
+ }
+ },
+
+ iterateAllRootAllocatorDumps(fn) {
+ this.iterateContainerDumps(function(containerDump) {
+ containerDump.iterateRootAllocatorDumps(fn, this);
+ });
+ },
+
+ /**
+ * Traverse the memory dump graph in a depth first post-order, i.e.
+ * children and owners of a memory allocator dump are visited before the
+ * dump itself. This method will throw an exception if the graph contains
+ * a cycle.
+ */
+ traverseAllocatorDumpsInDepthFirstPostOrder(fn) {
+ const visitedDumps = new WeakSet();
+ const openDumps = new WeakSet();
+
+ function visit(dump) {
+ if (visitedDumps.has(dump)) return;
+
+ if (openDumps.has(dump)) {
+ throw new Error(dump.userFriendlyName + ' contains a cycle');
+ }
+ openDumps.add(dump);
+
+ // Visit owners before the dumps they own.
+ dump.ownedBy.forEach(function(ownershipLink) {
+ visit.call(this, ownershipLink.source);
+ }, this);
+
+ // Visit children before parents.
+ dump.children.forEach(visit, this);
+
+ // Actually visit the current memory allocator dump.
+ fn.call(this, dump);
+ visitedDumps.add(dump);
+
+ openDumps.delete(dump);
+ }
+
+ this.iterateAllRootAllocatorDumps(visit);
+ },
+
+ /**
+ * Traverse the memory dump graph in a depth first pre-order, i.e.
+ * children and owners of a memory allocator dump are visited after the
+ * dump itself. This method will not visit some dumps if the graph contains
+ * a cycle.
+ */
+ traverseAllocatorDumpsInDepthFirstPreOrder(fn) {
+ const visitedDumps = new WeakSet();
+
+ function visit(dump) {
+ if (visitedDumps.has(dump)) return;
+
+ // If this dumps owns another dump which hasn't been visited yet, then
+ // wait for this dump to be visited later.
+ if (dump.owns !== undefined && !visitedDumps.has(dump.owns.target)) {
+ return;
+ }
+
+ // If this dump's parent hasn't been visited yet, then wait for this
+ // dump to be visited later.
+ if (dump.parent !== undefined && !visitedDumps.has(dump.parent)) {
+ return;
+ }
+
+ // Actually visit the current memory allocator dump.
+ fn.call(this, dump);
+ visitedDumps.add(dump);
+
+ // Visit owners after the dumps they own.
+ dump.ownedBy.forEach(function(ownershipLink) {
+ visit.call(this, ownershipLink.source);
+ }, this);
+
+ // Visit children after parents.
+ dump.children.forEach(visit, this);
+ }
+
+ this.iterateAllRootAllocatorDumps(visit);
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ GlobalMemoryDump,
+ {
+ name: 'globalMemoryDump',
+ pluralName: 'globalMemoryDumps'
+ });
+
+ return {
+ GlobalMemoryDump,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/global_memory_dump_test.html b/chromium/third_party/catapult/tracing/tracing/model/global_memory_dump_test.html
new file mode 100644
index 00000000000..219ce0f28d8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/global_memory_dump_test.html
@@ -0,0 +1,3954 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const GlobalMemoryDump = tr.model.GlobalMemoryDump;
+ const ProcessMemoryDump = tr.model.ProcessMemoryDump;
+ const MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+ const MemoryAllocatorDumpLink = tr.model.MemoryAllocatorDumpLink;
+ const Scalar = tr.b.Scalar;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const addChildDump = tr.model.MemoryDumpTestUtils.addChildDump;
+ const addOwnershipLink = tr.model.MemoryDumpTestUtils.addOwnershipLink;
+ const checkDumpNumericsAndDiagnostics =
+ tr.model.MemoryDumpTestUtils.checkDumpNumericsAndDiagnostics;
+ const SIZE_DELTA = tr.model.MemoryDumpTestUtils.SIZE_DELTA;
+ const MemoryAllocatorDumpInfoType = tr.model.MemoryAllocatorDumpInfoType;
+ const PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN =
+ MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN;
+ const PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER =
+ MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER;
+
+ function buildArgPusher(array) {
+ return function(arg) { array.push(arg); };
+ }
+
+ function assertEqualUniqueMembers(actualArray, expectedArray) {
+ assert.lengthOf(actualArray, expectedArray.length);
+ assert.sameMembers(actualArray, expectedArray);
+ }
+
+ function assertUndefinedNumeric(dump, numericName) {
+ const numeric = dump.numerics[numericName];
+ assert.isUndefined(numeric, 'expected numeric \'' + numericName +
+ '\' of memory allocator dump \'' + dump.fullName + '\' in ' +
+ dump.containerMemoryDump.userFriendlyName + ' to be undefined');
+ }
+
+ function assertDefinedNumeric(dump, numericName, expectedUnit, expectedValue,
+ opt_delta) {
+ const numeric = dump.numerics[numericName];
+ const errorMessagePrefix = 'expected numeric \'' + numericName +
+ '\' of memory allocator dump \'' + dump.fullName + '\' in ' +
+ dump.containerMemoryDump.userFriendlyName + ' to ';
+
+ assert.instanceOf(numeric, Scalar,
+ errorMessagePrefix + 'be an instance of Scalar');
+ assert.strictEqual(numeric.unit, expectedUnit,
+ errorMessagePrefix + 'have unit \'' + expectedUnit.unitName +
+ '\' but got \'' + numeric.unit.unitName + '\' instead');
+
+ const valueErrorMessage = errorMessagePrefix + 'have value \'' +
+ expectedValue + '\' but got \'' + numeric.value + '\'';
+ if (opt_delta !== undefined) {
+ assert.closeTo(
+ numeric.value, expectedValue, opt_delta, valueErrorMessage);
+ } else {
+ assert.strictEqual(numeric.value, expectedValue, valueErrorMessage);
+ }
+ }
+
+ function assertSizeNumeric(dump, sizeName, expectedValue) {
+ if (expectedValue === undefined) {
+ assertUndefinedNumeric(dump, sizeName);
+ } else {
+ assertDefinedNumeric(dump, sizeName, sizeInBytes_smallerIsBetter,
+ expectedValue, SIZE_DELTA);
+ }
+ }
+
+ function assertDumpSizes(dump, expectedSize, expectedEffectiveSize,
+ opt_expectedInfos, opt_expectedOwnedBySiblingSizes) {
+ // Check the 'size' numeric.
+ assertSizeNumeric(dump, 'size', expectedSize);
+
+ // Check the 'effective_size' numeric.
+ assertSizeNumeric(dump, 'effective_size', expectedEffectiveSize);
+
+ // Check the 'infos' list.
+ const expectedInfos = opt_expectedInfos || [];
+ const actualInfos = dump.infos;
+ assert.lengthOf(actualInfos, expectedInfos.length,
+ 'expected memory allocator dump \'' + dump.fullName + '\' in ' +
+ dump.containerMemoryDump.userFriendlyName + ' to have ' +
+ expectedInfos.length + ' infos but got ' + actualInfos.length);
+ for (let k = 0; k < actualInfos.length; k++) {
+ assert.deepEqual(actualInfos[k], expectedInfos[k],
+ 'info ' + k + ' of memory allocator dump \'' + dump.fullName +
+ '\' in ' + dump.containerMemoryDump.userFriendlyName +
+ ' doesn\'t match the expected info');
+ }
+
+ // Checked the 'ownedBySiblingSizes' map.
+ const expectedOwnedBySiblingSizes = opt_expectedOwnedBySiblingSizes || {};
+ const actualOwnedBySiblingSizes = {};
+ for (const siblingDump of dump.ownedBySiblingSizes.keys()) {
+ assert.strictEqual(siblingDump.parent, dump.parent);
+ actualOwnedBySiblingSizes[siblingDump.name] =
+ dump.ownedBySiblingSizes.get(siblingDump);
+ }
+ assert.deepEqual(actualOwnedBySiblingSizes, expectedOwnedBySiblingSizes,
+ 'ownedBySiblingSizes of memory allocator dump \'' + dump.fullName +
+ '\' in ' + dump.containerMemoryDump.userFriendlyName +
+ ' doesn\'t contain the expected values');
+ }
+
+ function createContainerDumps(processMemoryDumpCount, opt_model) {
+ let model = opt_model;
+ if (model === undefined) {
+ model = new Model();
+ }
+
+ const gmd = new GlobalMemoryDump(model, 0);
+ model.globalMemoryDumps.push(gmd);
+
+ const pmds = [];
+ for (let i = 0; i < processMemoryDumpCount; i++) {
+ const process = model.getOrCreateProcess(i);
+ const pmd = new ProcessMemoryDump(gmd, process, 0);
+ gmd.processMemoryDumps[i] = pmd;
+ process.memoryDumps.push(pmd);
+ pmds.push(pmd);
+ }
+
+ return [gmd].concat(pmds);
+ }
+
+ /**
+ * Build container memory dumps from tree recipes. This function returns
+ * a list containing a global memory dump and zero or more process memory
+ * dumps constructed from the provided function argument as follows:
+ *
+ * allTreeRecipes (argument):
+ *
+ * [
+ * [tree recipe GA, tree recipe GB, ...],
+ * [tree recipe P1A, tree recipe P1B, ...],
+ * [tree recipe P2A, tree recipe P2B ...],
+ * ...
+ * ]
+ *
+ * return value:
+ *
+ * [
+ * GlobalMemoryDump with root MemoryAllocatorDump(s) [GA, GB, ...],
+ * ProcessMemoryDump with root MemoryAllocatorDump(s) [P1A, P1B, ...],
+ * ProcessMemoryDump with root MemoryAllocatorDump(s) [P2A, P2B, ...],
+ * ...
+ * ]
+ *
+ * where a tree recipe is an object (a recursive data structure) with the
+ * following fields:
+ *
+ * name: Name of the resulting MAD.
+ * guid: GUID of the resulting MAD (can be undefined).
+ * owns: GUID of another MAD owned by the resulting MAD (no owned MAD if
+ * undefined).
+ * importance: Importance of the above ownership (can be undefined).
+ * size: Value of the 'size' numeric of the resulting MAD (no 'size'
+ * numeric if undefined).
+ * numerics: Extra numerics of the resulting MAD (dictionary).
+ * diagnostics: Extra diagnostics of the resulting MAD (dictionary).
+ * weak: Whether the resulting MAD should be weak (undefined implies
+ * non-weak).
+ * children: List of tree recipes for child MADs (no children if undefined).
+ * skip_build: If this optional property is set to true, this function will
+ * skip the corresponding tree recipe node and will not create a MAD
+ * for it (not allowed in root recipes).
+ *
+ * Other fields (most importantly 'expected_size') of a tree recipe are
+ * ignored by this function.
+ */
+ function buildDumpTrees(allTreeRecipes, opt_model) {
+ assert.isAbove(allTreeRecipes.length, 0);
+
+ // owned GUID -> {dump: owner, importance: optional}.
+ const ownerDumps = {};
+ const ownableDumps = {}; // ownable GUID -> ownable dump.
+
+ function buildAndAddDumpTrees(containerDump, treeRecipes) {
+ if (treeRecipes === undefined) return;
+
+ function buildDumpTreeRecursively(treeRecipe, namePrefix) {
+ const skipBuild = treeRecipe.skip_build;
+ const name = treeRecipe.name;
+ const guid = treeRecipe.guid;
+ const owns = treeRecipe.owns;
+ const size = treeRecipe.size;
+ const numerics = treeRecipe.numerics;
+ const diagnostics = treeRecipe.diagnostics;
+ const importance = treeRecipe.importance;
+ const weak = treeRecipe.weak;
+
+ assert.notStrictEqual(skipBuild, true);
+ assert.isDefined(name);
+
+ const fullName = namePrefix + name;
+ const dump = new MemoryAllocatorDump(containerDump, fullName, guid);
+
+ if (size !== undefined) {
+ dump.addNumeric(
+ 'size', new Scalar(sizeInBytes_smallerIsBetter, size));
+ }
+ if (guid !== undefined) {
+ assert.notProperty(guid, ownableDumps);
+ ownableDumps[guid] = dump;
+ }
+ if (owns !== undefined) {
+ if (!(owns in ownerDumps)) {
+ ownerDumps[owns] = [];
+ }
+ ownerDumps[owns].push({dump, importance});
+ } else {
+ assert.isUndefined(importance); // Test sanity check.
+ }
+
+ if (treeRecipe.children !== undefined) {
+ treeRecipe.children.forEach(function(childTreeRecipe) {
+ // Virtual children are added during size calculation.
+ if (childTreeRecipe.skip_build === true) return;
+ const childDump =
+ buildDumpTreeRecursively(childTreeRecipe, fullName + '/');
+ childDump.parent = dump;
+ dump.children.push(childDump);
+ });
+ }
+
+ if (numerics !== undefined) {
+ for (const [name, item] of Object.entries(numerics)) {
+ dump.addNumeric(name, item);
+ }
+ }
+ if (diagnostics !== undefined) {
+ for (const [name, item] of Object.entries(diagnostics)) {
+ dump.addDiagnostic(name, item);
+ }
+ }
+
+ if (weak) dump.weak = true;
+
+ return dump;
+ }
+
+ const memoryAllocatorDumps = treeRecipes.map(function(treeRecipe) {
+ return buildDumpTreeRecursively(treeRecipe, '');
+ });
+ containerDump.memoryAllocatorDumps = memoryAllocatorDumps;
+ }
+
+ // Recursively build memory allocator dump trees for all container dumps.
+ const containerDumps = createContainerDumps(
+ allTreeRecipes.length - 1, opt_model);
+ for (let i = 0; i < allTreeRecipes.length; i++) {
+ buildAndAddDumpTrees(containerDumps[i], allTreeRecipes[i]);
+ }
+
+ // Hook up ownership links.
+ for (const [ownedGuid, ownershipInfos] of Object.entries(ownerDumps)) {
+ const ownedDump = ownableDumps[ownedGuid];
+ assert.isDefined(ownedDump, 'Tree recipes don\'t contain a memory ' +
+ 'allocator dump with guid \'' + ownedGuid + '\'');
+
+ ownershipInfos.forEach(function(ownershipInfo) {
+ addOwnershipLink(
+ ownershipInfo.dump, ownedDump, ownershipInfo.importance);
+ });
+ }
+
+ return containerDumps;
+ }
+
+ // Check that the buildDumpTrees testing helper method above builds a
+ // hierarchy of container and memory allocator dumps from tree recipes
+ // correctly.
+ test('testSanityCheck_buildDumpTrees', function() {
+ const containerDumps = buildDumpTrees([
+ [ // GMD.
+ {
+ 'name': 'globalSharedDump1',
+ 'size': 123
+ },
+ {
+ 'name': 'globalSharedDump2',
+ 'subsystem_size': 999,
+ 'owns': 7,
+ 'importance': -1
+ }
+ ],
+ undefined, // PMD1.
+ [ // PMD2.
+ {
+ 'name': 'v8',
+ 'children': [
+ {
+ 'name': 'isolate1',
+ 'guid': 7,
+ 'weak': true
+ },
+ {
+ 'name': 'isolate2',
+ 'skip_build': true
+ },
+ {
+ 'name': 'isolate3',
+ 'size': 54,
+ 'guid': 60,
+ 'children': [
+ {
+ 'name': 'obj1',
+ 'size': 89,
+ 'guid': 3
+ },
+ {
+ 'name': 'obj2',
+ 'owns': 3,
+ 'weak': true
+ },
+ {
+ 'name': 'obj3',
+ 'owns': 3,
+ 'importance': 2
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+ assert.lengthOf(containerDumps, 3);
+ const gmd = containerDumps[0];
+ const pmd1 = containerDumps[1];
+ const pmd2 = containerDumps[2];
+
+ function checkDump(dump, expectedGuid, expectedFullName, expectedParent,
+ expectedChildrenCount, expectedSize, expectedIsOwner,
+ expectedOwnersCount, expectedContainerDump, opt_expectedWeak) {
+ assert.isDefined(dump);
+ assert.instanceOf(dump, MemoryAllocatorDump);
+ assert.strictEqual(dump.guid, expectedGuid);
+ assert.strictEqual(dump.fullName, expectedFullName);
+ assert.strictEqual(dump.parent, expectedParent);
+ assert.lengthOf(dump.children, expectedChildrenCount);
+
+ assertSizeNumeric(dump, 'size', expectedSize);
+ assertSizeNumeric(dump, 'subsystem_size', undefined);
+
+ if (expectedIsOwner) {
+ assert.isDefined(dump.owns);
+ } else {
+ assert.isUndefined(dump.owns);
+ }
+ assert.lengthOf(dump.ownedBy, expectedOwnersCount);
+
+ assert.strictEqual(dump.containerMemoryDump, expectedContainerDump);
+ assert.strictEqual(expectedContainerDump.getMemoryAllocatorDumpByFullName(
+ expectedFullName), dump);
+ assert.strictEqual(dump.weak, !!opt_expectedWeak);
+ }
+
+ function checkOwnershipLink(expectedSourceDump, expectedTargetDump,
+ expectedImportance) {
+ const link = expectedSourceDump.owns;
+ assert.isDefined(link);
+ assert.instanceOf(link, MemoryAllocatorDumpLink);
+ assert.strictEqual(link.source, expectedSourceDump);
+ assert.strictEqual(link.target, expectedTargetDump);
+ assert.strictEqual(link.importance, expectedImportance);
+ assert.include(expectedTargetDump.ownedBy, link);
+ }
+
+ // GMD memory allocator dumps.
+ assert.lengthOf(gmd.memoryAllocatorDumps, 2);
+ const globalSharedDump1 = gmd.memoryAllocatorDumps[0];
+ checkDump(globalSharedDump1, undefined, 'globalSharedDump1', undefined, 0,
+ 123, false, 0, gmd);
+ const globalSharedDump2 = gmd.memoryAllocatorDumps[1];
+ checkDump(globalSharedDump2, undefined, 'globalSharedDump2', undefined, 0,
+ undefined, true, 0, gmd);
+
+ // PMD1 memory allocator dumps.
+ assert.isUndefined(pmd1.memoryAllocatorDumps);
+
+ // PMD2 memory allocator dumps.
+ assert.lengthOf(pmd2.memoryAllocatorDumps, 1);
+ const v8Dump = pmd2.memoryAllocatorDumps[0];
+ checkDump(v8Dump, undefined, 'v8', undefined, 2, undefined, false, 0,
+ pmd2);
+ const isolate1Dump = v8Dump.children[0];
+ checkDump(isolate1Dump, 7, 'v8/isolate1', v8Dump, 0, undefined, false, 1,
+ pmd2, true /* weak dump */);
+ const isolate3Dump = v8Dump.children[1];
+ checkDump(isolate3Dump, 60, 'v8/isolate3', v8Dump, 3, 54, false, 0, pmd2);
+ const obj1Dump = isolate3Dump.children[0];
+ checkDump(obj1Dump, 3, 'v8/isolate3/obj1', isolate3Dump, 0, 89, false, 2,
+ pmd2);
+ const obj2Dump = isolate3Dump.children[1];
+ checkDump(obj2Dump, undefined, 'v8/isolate3/obj2', isolate3Dump, 0,
+ undefined, true, 0, pmd2, true /* weak dump */);
+ const obj3Dump = isolate3Dump.children[2];
+ checkDump(obj3Dump, undefined, 'v8/isolate3/obj3', isolate3Dump, 0,
+ undefined, true, 0, pmd2);
+
+ // Ownership links.
+ checkOwnershipLink(globalSharedDump2, isolate1Dump, -1);
+ checkOwnershipLink(obj2Dump, obj1Dump, undefined);
+ checkOwnershipLink(obj3Dump, obj1Dump, 2);
+ });
+
+ /**
+ * Check that container memory dumps have the expected structure with sizes
+ * as described by tree recipes. The fields of a tree recipe are used by this
+ * function to check the properties of a MemoryAllocatorDump as follows (see
+ * the buildDumpTrees documentation for more details about the structure of
+ * tree recipes):
+ *
+ * name: Expected name of the MAD.
+ * expected_removed: If provided and true, it is expected that there is no
+ * dump for the recipe.
+ * expected_size: Expected value of the 'size' numeric of the MAD (no
+ * 'size' numeric expected if undefined).
+ * expected_effective_size: Expected value of the 'effective_size'
+ * numeric of the MAD (no 'effective_size' numeric expected if
+ * undefined).
+ * expected_infos: List of expected MAD infos (zero infos expected if
+ * undefined).
+ * weak: Whether the MAD is expected to be weak (non-weak if undefined).
+ * owns: Expected GUID of the dump owned by the MAD.
+ * importance: Expected importance of the owhership from this MAD.
+ * expected_owned_by_links_count: Expected number of 'ownedBy' links of the
+ * MAD.
+ * children: List of tree recipes for child MADs (no children expected if
+ * undefined).
+ *
+ * Other fields of a tree recipe (including 'skip_build') are ignored by this
+ * function.
+ */
+ function checkDumpTrees(containerDumps, allTreeRecipes) {
+ assert.lengthOf(containerDumps, allTreeRecipes.length);
+
+ for (let i = 0; i < containerDumps.length; i++) {
+ const containerDump = containerDumps[i];
+ const treeRecipes = allTreeRecipes[i];
+
+ const memoryAllocatorDumps = containerDump.memoryAllocatorDumps;
+ if (treeRecipes === undefined) {
+ assert.isUndefined(memoryAllocatorDumps,
+ 'expected undefined memory allocator dumps in ' +
+ containerDump.userFriendlyName);
+ continue;
+ }
+
+ const expectedTreeRecipes = treeRecipes.filter(function(treeRecipe) {
+ return !treeRecipe.expected_removed;
+ });
+
+ assert.isDefined(memoryAllocatorDumps,
+ 'expected defined memory allocator dumps in ' +
+ containerDump.userFriendlyName);
+ assert.lengthOf(memoryAllocatorDumps, expectedTreeRecipes.length,
+ 'expected ' + expectedTreeRecipes.length + ' root memory allocator ' +
+ 'dumps but got ' + memoryAllocatorDumps.length + ' in ' +
+ containerDump.userFriendlyName);
+
+ function checkDumpTree(dump, treeRecipe, expectedParent, namePrefix) {
+ // Test sanity check.
+ assert.isFalse(!!treeRecipe.expected_removed);
+
+ // Check full name, parent, and container dump.
+ const expectedFullName = namePrefix + treeRecipe.name;
+ const quantifiedName = dump.quantifiedName;
+ assert.strictEqual(dump.fullName, expectedFullName,
+ quantifiedName + ' has invalid full name');
+ assert.strictEqual(dump.parent, expectedParent,
+ quantifiedName + ' has invalid parent');
+ assert.strictEqual(dump.containerMemoryDump, containerDump,
+ quantifiedName + ' has invalid container memory dump');
+ assert.strictEqual(containerDump.getMemoryAllocatorDumpByFullName(
+ expectedFullName), dump, quantifiedName +
+ 'is not indexed in its container memory dump');
+
+ // Check the guid of the dump.
+ assert.strictEqual(dump.guid, treeRecipe.guid,
+ quantifiedName + ' has invalid guid');
+
+ // Check that the 'weak' flag is correct.
+ assert.strictEqual(dump.weak, !!treeRecipe.weak,
+ quantifiedName + ' has invalid weak flag');
+
+ // Check that sizes were calculated correctly.
+ assertDumpSizes(dump,
+ treeRecipe.expected_size,
+ treeRecipe.expected_effective_size,
+ treeRecipe.expected_infos,
+ treeRecipe.expected_owned_by_sibling_sizes);
+
+ // Check that the 'owns' link is correct.
+ if (treeRecipe.owns === undefined) {
+ assert.isUndefined(dump.owns,
+ quantifiedName + ' was expected not to own another dump');
+ } else {
+ const ownershipLink = dump.owns;
+ assert.isDefined(dump.owns, quantifiedName +
+ ' was expected to have an \'owns\' link');
+ assert.strictEqual(ownershipLink.source, dump,
+ 'the \'owns\' link of ' + quantifiedName + ' has invalid source');
+ const expectedImportance = treeRecipe.importance;
+ assert.strictEqual(ownershipLink.importance, expectedImportance,
+ 'expected the importance of the \'owns\' link of ' +
+ quantifiedName + ' to be ' + expectedImportance +
+ ' but got ' + ownershipLink.importance);
+ const ownedDump = ownershipLink.target;
+ assert.strictEqual(ownedDump.guid, treeRecipe.owns,
+ 'the \'owns\' link of ' + quantifiedName +
+ ' has an invalid target');
+ assert.include(ownedDump.ownedBy, ownershipLink,
+ 'the target of the \'owns\' link of ' + quantifiedName +
+ ' doesn\'t have the link in its \'ownedBy\' list');
+ }
+
+ // Check that the number of 'ownedBy' links is correct.
+ const expectedOwnedByLinksCount =
+ treeRecipe.expected_owned_by_links_count;
+ if (expectedOwnedByLinksCount !== undefined) {
+ assert.lengthOf(dump.ownedBy, expectedOwnedByLinksCount,
+ 'expected ' + quantifiedName + ' to have ' +
+ expectedOwnedByLinksCount + ' \'ownedBy\' links but got ' +
+ dump.ownedBy.length);
+ }
+
+ // Check children recursively.
+ const actualChildren = dump.children;
+ const expectedChildren = (treeRecipe.children || []).filter(
+ function(childRecipe) {
+ return !childRecipe.expected_removed;
+ });
+ assert.lengthOf(actualChildren, expectedChildren.length,
+ 'expected ' + quantifiedName + ' to have ' +
+ expectedChildren.length + ' children but got ' +
+ actualChildren.length);
+ for (let k = 0; k < actualChildren.length; k++) {
+ checkDumpTree(actualChildren[k], expectedChildren[k], dump,
+ expectedFullName + '/');
+ }
+ }
+
+ for (let j = 0; j < memoryAllocatorDumps.length; j++) {
+ checkDumpTree(
+ memoryAllocatorDumps[j], expectedTreeRecipes[j], undefined, '');
+ }
+ }
+ }
+
+ // Check that the checkDumpTrees testing helper method above actually
+ // performs the expected checks. Since it will be used heavily throughout
+ // this file (where it is expected to pass), we only need to verify that it
+ // does indeed fail in several cases where it should.
+ test('testSanityCheck_checkDumpTrees_invalidName', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ const v8Dump = new MemoryAllocatorDump(gmd, 'v8');
+ const heapsDump =
+ new MemoryAllocatorDump(gmd, 'heaps'); // Should be 'v8/heaps'.
+ v8Dump.children.push(heapsDump);
+ heapsDump.parent = v8Dump;
+ gmd.memoryAllocatorDumps = [v8Dump];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'v8',
+ 'children': [
+ {
+ 'name': 'heaps'
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /'heaps'.*invalid full name/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidGuid', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ gmd.memoryAllocatorDumps = [new MemoryAllocatorDump(gmd, 'v8', 42)];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'v8',
+ 'guid': 43 // This should be 42.
+ }
+ ]
+ ]);
+ }, /'v8'.*\binvalid guid\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidStructure', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ const rootDump = new MemoryAllocatorDump(gmd, 'root');
+ addChildDump(rootDump, 'child1');
+ gmd.memoryAllocatorDumps = [rootDump];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'root',
+ 'children': [
+ {
+ 'name': 'child1'
+ },
+ {
+ // This child is not present in the dump.
+ 'name': 'child2',
+ 'skip_build': true
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /expected.*\b2\b.*children.*got.*\b1\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidParentLink', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ const rootDump = new MemoryAllocatorDump(gmd, 'root');
+ const parentDump = addChildDump(rootDump, 'parent');
+ const childDump = addChildDump(parentDump, 'child');
+ childDump.parent = rootDump; // This should correctly be parentDump.
+ gmd.memoryAllocatorDumps = [rootDump];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'root',
+ 'children': [
+ {
+ 'name': 'parent',
+ 'children': [
+ {
+ 'name': 'child'
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+ }, 'invalid parent');
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidSize', function() {
+ const containerDumps = createContainerDumps(1);
+ const gmd = containerDumps[0];
+ const pmd = containerDumps[1];
+ const rootDump = newAllocatorDump(pmd, 'root', {numerics: {size: 100}});
+ addChildDump(rootDump, 'parent', {numerics: {size: 49}});
+ pmd.memoryAllocatorDumps = [rootDump];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ undefined,
+ [
+ {
+ 'name': 'root',
+ 'expected_size': 100,
+ 'children': [
+ {
+ 'name': 'parent',
+ 'expected_size': 50 // This should be 49.
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /expected.*'size'.*value.*\b50\b.*got.*\b49\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidEffectiveSize', function() {
+ const containerDumps = createContainerDumps(1);
+ const gmd = containerDumps[0];
+ const pmd = containerDumps[1];
+ const rootDump = newAllocatorDump(pmd, 'root',
+ {numerics: {effective_size: 99}});
+ addChildDump(rootDump, 'parent', {numerics: {effective_size: 50}});
+ pmd.memoryAllocatorDumps = [rootDump];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ undefined,
+ [
+ {
+ 'name': 'root',
+ 'expected_effective_size': 100, // This should be 99.
+ 'children': [
+ {
+ 'name': 'parent',
+ 'expected_effective_size': 50
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /expected.*'effective_size'.*value.*\b100\b.*got.*\b99\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidInfoCount', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ gmd.memoryAllocatorDumps = [
+ newAllocatorDump(gmd, 'v8', {numerics: {size: 50}})
+ ];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'v8',
+ 'expected_size': 50,
+ 'expected_infos': [
+ {
+ type: PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN,
+ providedSize: 50,
+ dependencySize: 60
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /expected.*'v8'.*\b1 infos\b.*\bgot\b.*\b0\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidInfo', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ const v8Dump = newAllocatorDump(gmd, 'v8', {numerics: {size: 50}});
+ v8Dump.infos.push({
+ type: PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN,
+ providedSize: 40,
+ dependencySize: 50
+ });
+ gmd.memoryAllocatorDumps = [v8Dump];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'v8',
+ 'expected_size': 50,
+ 'expected_infos': [
+ {
+ // Should be PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN below.
+ type: PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER,
+ providedSize: 40,
+ dependencySize: 50
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /\binfo 0\b.*'v8'.*\bexpected\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidOwnedBySiblingSizes', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ const v8Dump = new MemoryAllocatorDump(gmd, 'v8');
+ addChildDump(v8Dump, 'child1', {guid: 42});
+ addChildDump(v8Dump, 'child2');
+ gmd.memoryAllocatorDumps = [v8Dump];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'v8',
+ 'children': [
+ {
+ 'name': 'child1',
+ 'guid': 42
+ },
+ {
+ 'name': 'child2',
+ 'expected_owned_by_sibling_sizes': {
+ 'child1': 40 // This should be 30.
+ }
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /\bownedBySiblingSizes\b.*'v8\/child2'.*\bexpected\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidWeakFlag',
+ function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ const parentDump = new MemoryAllocatorDump(gmd, 'parent');
+ const childDump = addChildDump(parentDump, 'child');
+ childDump.weak = true;
+ gmd.memoryAllocatorDumps = [parentDump];
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'parent',
+ 'children': [
+ {
+ 'name': 'child',
+ // Missing "'weak': true".
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /'parent\/child'.*\binvalid weak flag\b/);
+
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'parent',
+ 'weak': true, // This should be false (or not provided).
+ 'children': [
+ {
+ 'name': 'child',
+ 'weak': true
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /'parent'.*\binvalid weak flag\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_dumpNotRemoved', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+ const parentDump = new MemoryAllocatorDump(gmd, 'parent');
+ for (let i = 1; i <= 3; i++) {
+ addChildDump(parentDump, 'child' + i);
+ }
+ const otherDump = new MemoryAllocatorDump(gmd, 'other');
+ gmd.memoryAllocatorDumps = [parentDump, otherDump];
+
+ // Child MAD not removed.
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'parent',
+ 'children': [
+ {
+ 'name': 'child1',
+ },
+ {
+ 'name': 'child2',
+ 'expected_removed': true
+ },
+ {
+ 'name': 'child3',
+ }
+ ]
+ },
+ {
+ 'name': 'other'
+ }
+ ]
+ ]);
+ }, /\bexpected\b.*'parent'.*\b2 children\b.*\bgot 3\b/);
+
+ // Root MAD not removed.
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'parent',
+ 'children': [
+ {
+ 'name': 'child1',
+ },
+ {
+ 'name': 'child2'
+ },
+ {
+ 'name': 'child3',
+ }
+ ]
+ },
+ {
+ 'name': 'other',
+ 'expected_removed': true
+ }
+ ]
+ ]);
+ }, /\bexpected\b.*\b1 root memory allocator dumps\b.*\bgot 2\b/);
+ });
+
+ test('testSanityCheck_checkDumpTrees_invalidOwnership', function() {
+ const containerDumps = createContainerDumps(1);
+ const gmd = containerDumps[0];
+ const pmd1 = containerDumps[1];
+ const ownedDump = new MemoryAllocatorDump(gmd, 'owned', 42);
+ const ownerDump1 = new MemoryAllocatorDump(pmd1, 'owner1');
+ const link1 = addOwnershipLink(ownerDump1, ownedDump);
+ const ownerDump2 = new MemoryAllocatorDump(pmd1, 'owner2');
+ const link2 = addOwnershipLink(ownerDump2, ownedDump, 3);
+ const nonOwnerDump = new MemoryAllocatorDump(pmd1, 'non-owner', 90);
+ gmd.memoryAllocatorDumps = [ownedDump];
+ pmd1.memoryAllocatorDumps = [ownerDump1, ownerDump2, nonOwnerDump];
+
+ // Missing 'owns' link.
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'owned',
+ 'guid': 42
+ }
+ ],
+ [
+ {
+ 'name': 'owner1',
+ 'owns': 42
+ },
+ {
+ 'name': 'owner2',
+ 'importance': 3,
+ 'owns': 42
+ },
+ {
+ 'name': 'non-owner',
+ 'guid': 90,
+ 'owns': 42 // This should not be here.
+ }
+ ]
+ ]);
+ }, /'non-owner'.*\bwas expected to have\b.*'owns' link\b/);
+
+ // Extra 'owns' link.
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'owned',
+ 'guid': 42
+ }
+ ],
+ [
+ {
+ 'name': 'owner1'
+ // Missing: "'owns': 42".
+ },
+ {
+ 'name': 'owner2',
+ 'importance': 3,
+ 'owns': 42
+ },
+ {
+ 'name': 'non-owner',
+ 'guid': 90
+ }
+ ]
+ ]);
+ }, /'owner1'.*\bwas expected not to own\b/);
+
+ // Invalid ownership importance.
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'owned',
+ 'guid': 42
+ }
+ ],
+ [
+ {
+ 'name': 'owner1',
+ 'owns': 42
+ },
+ {
+ 'name': 'owner2',
+ 'importance': 2, // This should be 3.
+ 'owns': 42
+ },
+ {
+ 'name': 'non-owner',
+ 'guid': 90
+ }
+ ]
+ ]);
+ }, /\bexpected\b.*\bimportance\b.*'owner2'.*\b2 but got 3\b/);
+
+ // Invalid ownership target.
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'owned',
+ 'guid': 42
+ }
+ ],
+ [
+ {
+ 'name': 'owner1',
+ 'owns': 90 // This should be 42.
+ },
+ {
+ 'name': 'owner2',
+ 'importance': 3,
+ 'owns': 42
+ },
+ {
+ 'name': 'non-owner',
+ 'guid': 90
+ }
+ ]
+ ]);
+ }, /'owner1'.*\binvalid target\b/);
+
+ // Invalid 'ownedBy' ownership links count.
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'owned',
+ 'guid': 42,
+ 'expected_owned_by_links_count': 3 // This should be 2.
+ }
+ ],
+ [
+ {
+ 'name': 'owner1',
+ 'owns': 42
+ },
+ {
+ 'name': 'owner2',
+ 'importance': 3,
+ 'owns': 42
+ },
+ {
+ 'name': 'non-owner',
+ 'guid': 90
+ }
+ ]
+ ]);
+ }, /'owned'.*\bhave 3 'ownedBy' links\b.*\bgot 2\b/);
+
+ // Invalid ownership source.
+ link1.source = ownerDump2;
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'owned',
+ 'guid': 42
+ }
+ ],
+ [
+ {
+ 'name': 'owner1',
+ 'owns': 42
+ },
+ {
+ 'name': 'owner2',
+ 'importance': 3,
+ 'owns': 42
+ },
+ {
+ 'name': 'non-owner',
+ 'guid': 90
+ }
+ ]
+ ]);
+ }, /'owns' link\b.*'owner1'.*\binvalid source\b/);
+ link1.source = ownerDump1;
+
+ // Ownership link not in target's 'ownedBy' list.
+ ownedDump.ownedBy.pop();
+ assert.throws(function() {
+ checkDumpTrees(containerDumps, [
+ [
+ {
+ 'name': 'owned',
+ 'guid': 42
+ }
+ ],
+ [
+ {
+ 'name': 'owner1',
+ 'owns': 42
+ },
+ {
+ 'name': 'owner2',
+ 'importance': 3,
+ 'owns': 42
+ },
+ {
+ 'name': 'non-owner',
+ 'guid': 90
+ }
+ ]
+ ]);
+ }, /\btarget of\b.*'owner2'.*'ownedBy' list\b/);
+ ownedDump.ownedBy.push(link2);
+ });
+
+ /**
+ * Build container memory dumps from tree recipes, let the resulting
+ * GlobalMemoryDump calculate sizes and effective sizes, and then check that
+ * the augmented container memory dumps have the expected structure with
+ * correct sizes and effective sizes (as described by the same tree recipes).
+ *
+ * See the documentation for buildDumpTrees and checkDumpTrees for more
+ * details about the structure of tree recipes.
+ */
+ function testSizesCalculation(allTreeRecipes) {
+ const m = new Model();
+ const io = new tr.importer.ImportOptions();
+ io.showImportWarnings = false;
+ m.importOptions = io;
+
+ const containerDumps = buildDumpTrees(allTreeRecipes, m);
+ const gmd = containerDumps[0];
+ gmd.calculateSizes();
+ gmd.calculateEffectiveSizes();
+ gmd.forceRebuildingMemoryAllocatorDumpByFullNameIndices();
+ checkDumpTrees(containerDumps, allTreeRecipes);
+ }
+
+ // Check that the testSizesCalculation testing helper method above
+ // actually performs the expected checks. Since it will be used heavily
+ // throughout this file (where it is expected to pass), we only need to
+ // verify that it does indeed fail when it should.
+ test('testSanityCheck_testSizesCalculation', function() {
+ assert.throws(function() {
+ testSizesCalculation([
+ [],
+ undefined,
+ [
+ {
+ 'name': 'winheap'
+ },
+ {
+ 'name': 'malloc',
+ 'expected_size': 100,
+ 'children': [
+ {
+ 'name': 'allocated_objects',
+ 'size': 100,
+ 'expected_size': 100
+ },
+ {
+ 'name': 'extra',
+ 'size': 20,
+ 'expected_size': 20
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /expected.*'size'.*value.*\b100\b.*got.*\b120\b/);
+ });
+
+ function calculationTest(caseName, treeRecipes) {
+ test('calculateSizes_' + caseName, function() {
+ testSizesCalculation(treeRecipes);
+ });
+ }
+
+ /**
+ * Build container memory dumps from tree recipes, let the resulting
+ * GlobalMemoryDump remove weak memory dumps, and then check that the updated
+ * container memory dumps have the expected structure (as described by the
+ * same tree recipes).
+ *
+ * See the documentation for buildDumpTrees and checkDumpTrees for more
+ * details about the structure of tree recipes.
+ */
+ function testWeakDumpRemoval(allTreeRecipes) {
+ const m = new tr.Model();
+ const io = new tr.importer.ImportOptions();
+ io.showImportWarnings = false;
+ m.importOptions = io;
+
+ const containerDumps = buildDumpTrees(allTreeRecipes, m);
+ const gmd = containerDumps[0];
+ gmd.removeWeakDumps();
+ gmd.forceRebuildingMemoryAllocatorDumpByFullNameIndices();
+ checkDumpTrees(containerDumps, allTreeRecipes);
+ }
+
+ // Similarly to testSanityCheck_testSizesCalculation, check that the
+ // testWeakDumpRemoval testing helper method above actually performs the
+ // expected checks.
+ test('testSanityCheck_testWeakDumpRemoval', function() {
+ assert.throws(function() {
+ testWeakDumpRemoval([
+ [],
+ undefined,
+ [
+ {
+ 'name': 'winheap'
+ },
+ {
+ 'name': 'malloc',
+ 'children': [
+ {
+ 'name': 'allocated_objects'
+ },
+ {
+ 'name': 'directly_weak',
+ 'guid': 42,
+ 'weak': true,
+ 'expected_removed': true
+ },
+ {
+ 'name': 'indirectly_weak',
+ 'owns': 42
+ // Missing: "'expected_removed': true".
+ }
+ ]
+ }
+ ]
+ ]);
+ }, /expected.*'malloc'.*\b2 children\b.*\bgot 1\b/);
+ });
+
+ function weakDumpRemovalTest(caseName, treeRecipes) {
+ test('removeWeakDumps_' + caseName, function() {
+ testWeakDumpRemoval(treeRecipes);
+ });
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Actual tests begin here.
+ /////////////////////////////////////////////////////////////////////////////
+
+ test('iterateContainerDumps_withoutProcessMemoryDumps', function() {
+ const containerDumps = createContainerDumps(0);
+ const gmd = containerDumps[0];
+
+ const visitedContainerDumps = [];
+ gmd.iterateContainerDumps(buildArgPusher(visitedContainerDumps));
+ assertEqualUniqueMembers(visitedContainerDumps, containerDumps);
+ });
+
+ test('iterateContainerDumps_withProcessMemoryDumps', function() {
+ const containerDumps = createContainerDumps(2);
+ const gmd = containerDumps[0];
+
+ const visitedContainerDumps = [];
+ gmd.iterateContainerDumps(buildArgPusher(visitedContainerDumps));
+ assertEqualUniqueMembers(visitedContainerDumps, containerDumps);
+ });
+
+ test('iterateAllRootAllocatorDumps', function() {
+ const containerDumps = buildDumpTrees([
+ [ // GMD.
+ {
+ 'name': 'globalSharedDump1'
+ },
+ {
+ 'name': 'globalSharedDump2'
+ }
+ ],
+ [ // PMD.
+ {
+ 'name': 'v8',
+ 'children': [
+ {
+ 'name': 'isolate'
+ }
+ ]
+ }
+ ]
+ ]);
+ const gmd = containerDumps[0];
+ const pmd = containerDumps[1];
+
+ const visitedAllocatorDumps = [];
+ gmd.iterateAllRootAllocatorDumps(buildArgPusher(visitedAllocatorDumps));
+ assertEqualUniqueMembers(visitedAllocatorDumps, [
+ gmd.getMemoryAllocatorDumpByFullName('globalSharedDump1'),
+ gmd.getMemoryAllocatorDumpByFullName('globalSharedDump2'),
+ pmd.getMemoryAllocatorDumpByFullName('v8')
+ ]);
+ });
+
+ test('traverseAllocatorDumpsInDepthFirstOrder_oneTreeWithoutOwners',
+ function() {
+ const containerDumps = buildDumpTrees([
+ [ // GMD.
+ {
+ 'name': 'root',
+ 'children': [
+ {
+ 'name': 'parent',
+ 'children': [
+ {
+ 'name': 'child1'
+ },
+ {
+ 'name': 'child2'
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+ const gmd = containerDumps[0];
+
+ // Post-order.
+ let visitedAllocatorDumps = [];
+ gmd.traverseAllocatorDumpsInDepthFirstPostOrder(
+ buildArgPusher(visitedAllocatorDumps));
+ assert.deepEqual(visitedAllocatorDumps, [
+ gmd.getMemoryAllocatorDumpByFullName('root/parent/child1'),
+ gmd.getMemoryAllocatorDumpByFullName('root/parent/child2'),
+ gmd.getMemoryAllocatorDumpByFullName('root/parent'),
+ gmd.getMemoryAllocatorDumpByFullName('root')
+ ]);
+
+ // Pre-order.
+ visitedAllocatorDumps = [];
+ gmd.traverseAllocatorDumpsInDepthFirstPreOrder(
+ buildArgPusher(visitedAllocatorDumps));
+ assert.deepEqual(visitedAllocatorDumps, [
+ gmd.getMemoryAllocatorDumpByFullName('root'),
+ gmd.getMemoryAllocatorDumpByFullName('root/parent'),
+ gmd.getMemoryAllocatorDumpByFullName('root/parent/child1'),
+ gmd.getMemoryAllocatorDumpByFullName('root/parent/child2')
+ ]);
+ });
+
+ test('traverseAllocatorDumpsInDepthFirstOrder_oneTreeWithOwners',
+ function() {
+ const containerDumps = buildDumpTrees([
+ [], // GMD.
+ [ // PMD.
+ {
+ 'name': 'root',
+ 'children': [
+ {
+ 'name': 'parent',
+ 'children': [
+ {
+ 'name': 'child1',
+ 'owns': 0
+ },
+ {
+ 'name': 'child2',
+ 'guid': 0
+ },
+ {
+ 'name': 'child3',
+ 'owns': 0
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+ const gmd = containerDumps[0];
+ const pmd = containerDumps[1];
+
+ // Post-order.
+ let visitedAllocatorDumps = [];
+ gmd.traverseAllocatorDumpsInDepthFirstPostOrder(
+ buildArgPusher(visitedAllocatorDumps));
+ assert.deepEqual(visitedAllocatorDumps, [
+ pmd.getMemoryAllocatorDumpByFullName('root/parent/child1'),
+ pmd.getMemoryAllocatorDumpByFullName('root/parent/child3'),
+ pmd.getMemoryAllocatorDumpByFullName('root/parent/child2'),
+ pmd.getMemoryAllocatorDumpByFullName('root/parent'),
+ pmd.getMemoryAllocatorDumpByFullName('root')
+ ]);
+
+ // Pre-order.
+ visitedAllocatorDumps = [];
+ gmd.traverseAllocatorDumpsInDepthFirstPreOrder(
+ buildArgPusher(visitedAllocatorDumps));
+ assert.deepEqual(visitedAllocatorDumps, [
+ pmd.getMemoryAllocatorDumpByFullName('root'),
+ pmd.getMemoryAllocatorDumpByFullName('root/parent'),
+ pmd.getMemoryAllocatorDumpByFullName('root/parent/child2'),
+ pmd.getMemoryAllocatorDumpByFullName('root/parent/child1'),
+ pmd.getMemoryAllocatorDumpByFullName('root/parent/child3')
+ ]);
+ });
+
+ test('traverseAllocatorDumpsInDepthFirstOrder_multipleTrees', function() {
+ const containerDumps = buildDumpTrees([
+ [ // GMD.
+ {
+ 'name': 'shared',
+ 'children': [
+ {
+ 'name': 'pool1',
+ 'guid': 1
+ },
+ {
+ 'name': 'pool2',
+ 'owns': 3
+ }
+ ]
+ }
+ ],
+ [ // PMD.
+ {
+ 'name': 'oilpan',
+ 'children': [
+ {
+ 'name': 'objects'
+ },
+ {
+ 'name': 'heaps',
+ 'owns': 1,
+ 'children': [
+ {
+ 'name': 'small',
+ 'guid': 2
+ },
+ {
+ 'name': 'large'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'v8',
+ 'children': [
+ {
+ 'name': 'isolate1',
+ 'owns': 2
+ },
+ {
+ 'name': 'isolate2',
+ 'guid': 3
+ }
+ ]
+ }
+ ]
+ ]);
+ const gmd = containerDumps[0];
+ const pmd = containerDumps[1];
+
+ // Post-order.
+ let visitedAllocatorDumps = [];
+ gmd.traverseAllocatorDumpsInDepthFirstPostOrder(
+ buildArgPusher(visitedAllocatorDumps));
+ assert.deepEqual(visitedAllocatorDumps, [
+ pmd.getMemoryAllocatorDumpByFullName('v8/isolate1'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan/heaps/small'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan/heaps/large'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan/heaps'),
+ gmd.getMemoryAllocatorDumpByFullName('shared/pool1'),
+ gmd.getMemoryAllocatorDumpByFullName('shared/pool2'),
+ gmd.getMemoryAllocatorDumpByFullName('shared'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan/objects'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan'),
+ pmd.getMemoryAllocatorDumpByFullName('v8/isolate2'),
+ pmd.getMemoryAllocatorDumpByFullName('v8')
+ ]);
+
+ // Pre-order.
+ visitedAllocatorDumps = [];
+ gmd.traverseAllocatorDumpsInDepthFirstPreOrder(
+ buildArgPusher(visitedAllocatorDumps));
+ assert.deepEqual(visitedAllocatorDumps, [
+ gmd.getMemoryAllocatorDumpByFullName('shared'),
+ gmd.getMemoryAllocatorDumpByFullName('shared/pool1'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan/objects'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan/heaps'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan/heaps/small'),
+ pmd.getMemoryAllocatorDumpByFullName('oilpan/heaps/large'),
+ pmd.getMemoryAllocatorDumpByFullName('v8'),
+ pmd.getMemoryAllocatorDumpByFullName('v8/isolate1'),
+ pmd.getMemoryAllocatorDumpByFullName('v8/isolate2'),
+ gmd.getMemoryAllocatorDumpByFullName('shared/pool2')
+ ]);
+ });
+
+ test('traverseAllocatorDumpsInDepthFirstPostOrder_cycle', function() {
+ const containerDumps = buildDumpTrees([
+ [ // GMD.
+ {
+ 'name': 'shared',
+ 'owns': 2,
+ 'children': [
+ {
+ 'name': 'pool',
+ 'guid': 1
+ }
+ ]
+ }
+ ],
+ [ // PMD.
+ {
+ 'name': 'oilpan',
+ 'owns': 1,
+ 'children': [
+ {
+ 'name': 'objects',
+ 'guid': 2
+ }
+ ]
+ }
+ ]
+ ]);
+ const gmd = containerDumps[0];
+
+ // Post-order.
+ assert.throws(function() {
+ gmd.traverseAllocatorDumpsInDepthFirstPostOrder(function() {});
+ }, /contains.*cycle/);
+
+ // Pre-order.
+ const visitedAllocatorDumps = [];
+ gmd.traverseAllocatorDumpsInDepthFirstPreOrder(
+ buildArgPusher(visitedAllocatorDumps));
+ assert.deepEqual(visitedAllocatorDumps, []);
+ });
+
+ // Just check that the method doesn't crash upon encountering empty and/or
+ // undefined memory allocator dumps.
+ calculationTest('noDumps', [
+ undefined, // GMD.
+ [], // PMD1.
+ undefined // PMD2.
+ ]);
+
+ calculationTest('flatDumps', [
+ [ // GMD.
+ {
+ 'name': 'shared',
+ 'size': 1024,
+ 'expected_size': 1024,
+ 'expected_effective_size': 1024
+ }
+ ],
+ [ // PMD.
+ {
+ 'name': 'gpu'
+ }
+ ]
+ ]);
+
+ calculationTest('zeroSizes', [
+ [ // GMD.
+ {
+ 'name': 'shared',
+ 'size': 0,
+ 'expected_size': 0,
+ 'expected_effective_size': 0
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'gpu',
+ 'expected_size': 0,
+ 'expected_effective_size': 0,
+ 'children': [
+ {
+ 'name': 'zero',
+ 'size': 0,
+ 'expected_size': 0,
+ 'expected_effective_size': 0
+ }
+ ]
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'gpu',
+ 'expected_size': 0,
+ 'expected_effective_size': 0,
+ 'children': [
+ {
+ 'name': 'zero',
+ 'size': 0,
+ 'expected_size': 0,
+ 'expected_effective_size': 0
+ },
+ {
+ 'name': 'undefined'
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_allSizesUndefined', [
+ [
+ {
+ 'name': 'parent',
+ 'children': [
+ {
+ 'name': 'child1'
+ },
+ {
+ 'name': 'child2'
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_parentSizeUndefined', [
+ [
+ {
+ 'name': 'parent',
+ 'expected_size': 384,
+ 'expected_effective_size': 384,
+ 'children': [
+ {
+ 'name': 'child1',
+ 'size': 128,
+ 'expected_size': 128,
+ 'expected_effective_size': 128
+ },
+ {
+ 'name': 'child2',
+ 'size': 256,
+ 'expected_size': 256,
+ 'expected_effective_size': 256
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_parentSizeDefined_childrenAddUp', [
+ [
+ {
+ 'name': 'parent',
+ 'size': 0,
+ 'expected_size': 0,
+ 'expected_effective_size': 0,
+ 'children': [
+ {
+ 'name': 'child1'
+ },
+ {
+ 'name': 'child2'
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_parentSizeDefined_childrenDontAddUp', [
+ [
+ {
+ 'name': 'parent',
+ 'size': 2048,
+ 'expected_size': 2048,
+ 'expected_effective_size': 2048,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 2048,
+ 'expected_effective_size': 2048
+ },
+ {
+ 'name': 'child1'
+ },
+ {
+ 'name': 'child2'
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_oneChildSizeUndefined_childrenAddUp', [
+ [
+ {
+ 'name': 'parent',
+ 'size': 4096,
+ 'expected_size': 4096,
+ 'expected_effective_size': 4096,
+ 'children': [
+ {
+ 'name': 'child1'
+ },
+ {
+ 'name': 'child2',
+ 'size': 4096,
+ 'expected_size': 4096,
+ 'expected_effective_size': 4096
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_oneChildSizeUndefined_childrenDontAddUp', [
+ [
+ {
+ 'name': 'parent',
+ 'size': 6144,
+ 'expected_size': 6144,
+ 'expected_effective_size': 6144,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 2048,
+ 'expected_effective_size': 2048
+ },
+ {
+ 'name': 'child1'
+ },
+ {
+ 'name': 'child2',
+ 'size': 4096,
+ 'expected_size': 4096,
+ 'expected_effective_size': 4096
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_allSizesDefined_childrenAddUp', [
+ [
+ {
+ 'name': 'parent',
+ 'size': 100,
+ 'expected_size': 100,
+ 'expected_effective_size': 100,
+ 'children': [
+ {
+ 'name': 'child1',
+ 'size': 70,
+ 'expected_size': 70,
+ 'expected_effective_size': 70
+ },
+ {
+ 'name': 'child2',
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_allSizesDefined_childrenDontUp', [
+ [
+ {
+ 'name': 'parent',
+ 'size': 150,
+ 'expected_size': 150,
+ 'expected_effective_size': 150,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 50,
+ 'expected_effective_size': 50
+ },
+ {
+ 'name': 'child1',
+ 'size': 70,
+ 'expected_size': 70,
+ 'expected_effective_size': 70
+ },
+ {
+ 'name': 'child2',
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_oneChildSizeDefined', [
+ [
+ {
+ 'name': 'parent',
+ 'expected_size': 49,
+ 'expected_effective_size': 49,
+ 'children': [
+ {
+ 'name': 'child1',
+ 'size': 49,
+ 'expected_size': 49,
+ 'expected_effective_size': 49
+ },
+ {
+ 'name': 'child2'
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('children_multipleLevels', [
+ [], // GMD.
+ [ // PMD.
+ {
+ 'name': 'v8',
+ 'expected_size': 36,
+ 'expected_effective_size': 36,
+ 'children': [
+ {
+ 'name': 'isolate1',
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 10,
+ 'children': [
+ {
+ 'skip_build': true,
+ 'name': '<unspecified>',
+ 'expected_size': 3,
+ 'expected_effective_size': 3
+ },
+ {
+ 'name': 'objects',
+ 'size': 3,
+ 'expected_size': 3,
+ 'expected_effective_size': 3
+ },
+ {
+ 'name': 'heaps',
+ 'size': 4,
+ 'expected_size': 4,
+ 'expected_effective_size': 4
+ }
+ ]
+ },
+ {
+ 'name': 'isolate2',
+ 'size': 12,
+ 'expected_size': 12,
+ 'expected_effective_size': 12,
+ 'children': [
+ {
+ 'name': 'objects',
+ 'size': 5,
+ 'expected_size': 5,
+ 'expected_effective_size': 5
+ },
+ {
+ 'name': 'heaps',
+ 'size': 7,
+ 'expected_size': 7,
+ 'expected_effective_size': 7
+ }
+ ]
+ },
+ {
+ 'name': 'isolate3',
+ 'expected_size': 14,
+ 'expected_effective_size': 14,
+ 'children': [
+ {
+ 'name': 'objects',
+ 'size': 14,
+ 'expected_size': 14,
+ 'expected_effective_size': 14
+ },
+ {
+ 'name': 'heaps'
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('owners_allSizesUndefined', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'guid': 7
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'tile',
+ 'owns': 7,
+ 'importance': 1
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'chunk',
+ 'owns': 7
+ }
+ ]
+ ]);
+
+ calculationTest('owners_ownedSizeDefined', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'size': 15,
+ 'expected_size': 15,
+ 'expected_effective_size': 15,
+ 'guid': 7
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'tile',
+ 'owns': 7
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'chunk',
+ 'owns': 7
+ }
+ ]
+ ]);
+
+ calculationTest('owners_ownedSizeUndefined', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'expected_size': 9,
+ 'expected_effective_size': 0,
+ 'guid': 7
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'tile',
+ 'size': 5,
+ 'expected_size': 5,
+ 'expected_effective_size': 2.5,
+ 'owns': 7
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'chunk',
+ 'size': 9,
+ 'expected_size': 9,
+ 'expected_effective_size': 6.5,
+ 'owns': 7
+ }
+ ]
+ ]);
+
+ calculationTest('owners_oneOwnerSizeDefined', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'expected_size': 16,
+ 'expected_effective_size': 0,
+ 'guid': 7
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'tile',
+ 'size': 16,
+ 'expected_size': 16,
+ 'expected_effective_size': 16,
+ 'owns': 7
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'chunk',
+ 'owns': 7
+ }
+ ]
+ ]);
+
+ calculationTest('owners_oneOwnerSizeUndefined', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'size': 20,
+ 'expected_size': 20,
+ 'expected_effective_size': 2,
+ 'guid': 7
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'tile',
+ 'owns': 7
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'chunk',
+ 'size': 18,
+ 'expected_size': 18,
+ 'expected_effective_size': 18,
+ 'owns': 7
+ }
+ ]
+ ]);
+
+ calculationTest('owners_allSizesDefined', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'size': 60,
+ 'expected_size': 60,
+ 'expected_effective_size': 31,
+ 'guid': 7
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'tile',
+ 'size': 29,
+ 'expected_size': 29,
+ 'expected_effective_size': 19.5,
+ 'owns': 7
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'chunk',
+ 'size': 19,
+ 'expected_size': 19,
+ 'expected_effective_size': 9.5,
+ 'owns': 7
+ }
+ ]
+ ]);
+
+ calculationTest('owners_hierarchy', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'expected_size': 50,
+ 'expected_effective_size': 0,
+ 'guid': 7
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'tile',
+ 'expected_size': 50,
+ 'expected_effective_size': 0,
+ 'owns': 7,
+ 'guid': 0
+ },
+ {
+ 'name': 'object1',
+ 'size': 30,
+ 'owns': 0,
+ 'expected_size': 30,
+ 'expected_effective_size': 9
+ },
+ {
+ 'name': 'object2',
+ 'owns': 0
+ },
+ {
+ 'name': 'object3',
+ 'size': 50,
+ 'owns': 0,
+ 'expected_size': 50,
+ 'expected_effective_size': 21
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'chunk',
+ 'size': 40,
+ 'expected_size': 40,
+ 'expected_effective_size': 20,
+ 'owns': 7
+ }
+ ]
+ ]);
+
+ calculationTest('owners_withChildren', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'guid': 7,
+ 'expected_size': 48,
+ 'expected_effective_size': 17,
+ 'children': [
+ {
+ 'name': 'subbitmap1',
+ 'size': 32,
+ 'expected_size': 32,
+ 'expected_effective_size': 17 * (32 / 48)
+ },
+ {
+ 'name': 'subbitmap2',
+ 'size': 16,
+ 'expected_size': 16,
+ 'expected_effective_size': 17 * (16 / 48)
+ }
+ ]
+ }
+ ],
+ [ // PMD.
+ {
+ 'name': 'tile',
+ 'expected_size': 31,
+ 'expected_effective_size': 0,
+ 'guid': 8,
+ 'owns': 7,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 7,
+ 'expected_effective_size': 0
+ },
+ {
+ 'name': 'subtile',
+ 'size': 24,
+ 'expected_size': 24,
+ 'expected_effective_size': 0
+ }
+ ]
+ },
+ {
+ 'name': 'cc',
+ 'owns': 8,
+ 'size': 31,
+ 'expected_size': 31,
+ 'expected_effective_size': 31
+ }
+ ]
+ ]);
+
+ calculationTest('owners_withParents', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'size': 96,
+ 'expected_size': 96,
+ 'expected_effective_size': 32,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 32,
+ 'expected_effective_size': 32
+ },
+ {
+ 'name': 'subbitmap',
+ 'guid': 2,
+ 'expected_size': 64,
+ 'expected_effective_size': 0
+ }
+ ]
+ }
+ ],
+ [ // PMD.
+ {
+ 'name': 'tile',
+ 'expected_size': 64,
+ 'expected_effective_size': 0,
+ 'children': [
+ {
+ 'name': 'subtile',
+ 'guid': 1,
+ 'owns': 2,
+ 'expected_size': 64,
+ 'expected_effective_size': 0
+ }
+ ]
+ },
+ {
+ 'name': 'cc',
+ 'owns': 1,
+ 'size': 64,
+ 'expected_size': 64,
+ 'expected_effective_size': 64
+ }
+ ]
+ ]);
+
+ calculationTest('owners_multipleLevels', [
+ [ // GMD.
+ {
+ 'name': 'bitmap',
+ 'size': 96,
+ 'expected_size': 96,
+ 'expected_effective_size': 32,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 32,
+ 'expected_effective_size': 32
+ },
+ {
+ 'name': 'subbitmap',
+ 'guid': 2,
+ 'expected_size': 64,
+ 'expected_effective_size': 0
+ }
+ ]
+ }
+ ],
+ [ // PMD.
+ {
+ 'name': 'tile',
+ 'expected_size': 64,
+ 'expected_effective_size': 0,
+ 'owns': 2,
+ 'children': [
+ {
+ 'name': 'subtile',
+ 'guid': 1,
+ 'expected_size': 64,
+ 'expected_effective_size': 0
+ }
+ ]
+ },
+ {
+ 'name': 'cc',
+ 'owns': 1,
+ 'size': 64,
+ 'expected_size': 64,
+ 'expected_effective_size': 64
+ }
+ ]
+ ]);
+
+ calculationTest('views_allSizesUndefined', [
+ [
+ {
+ 'name': 'v8',
+ 'children': [
+ {
+ 'name': 'v8/heaps',
+ 'guid': 1
+ },
+ {
+ 'name': 'v8/objects',
+ 'owns': 1
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_ownedSizeDefined', [
+ [
+ {
+ 'name': 'v8',
+ 'expected_size': 10,
+ 'expected_effective_size': 10,
+ 'children': [
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 10
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_ownerSizeDefined', [
+ [
+ {
+ 'name': 'v8',
+ 'expected_size': 20,
+ 'expected_effective_size': 20,
+ 'children': [
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'expected_size': 20,
+ 'expected_effective_size': 0,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 20
+ }
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1,
+ 'size': 20,
+ 'expected_size': 20,
+ 'expected_effective_size': 20
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_parentSizeUndefined', [
+ [
+ {
+ 'name': 'v8',
+ 'expected_size': 30,
+ 'expected_effective_size': 30,
+ 'children': [
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 10,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 20
+ }
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1,
+ 'size': 20,
+ 'expected_size': 20,
+ 'expected_effective_size': 20
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_ownerSizeUndefined_childrenAddUp', [
+ [
+ {
+ 'name': 'v8',
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30,
+ 'children': [
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_ownerSizeUndefined_childrenDontAddUp', [
+ [
+ {
+ 'name': 'v8',
+ 'size': 40,
+ 'expected_size': 40,
+ 'expected_effective_size': 40,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 10,
+ 'expected_effective_size': 10
+ },
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_ownedSizeUndefined_childrenAddUp', [
+ [
+ {
+ 'name': 'v8',
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30,
+ 'children': [
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'expected_size': 30,
+ 'expected_effective_size': 0,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 30
+ }
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1,
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_ownedSizeUndefined_childrenDontAddUp', [
+ [
+ {
+ 'name': 'v8',
+ 'size': 40,
+ 'expected_size': 40,
+ 'expected_effective_size': 40,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 10,
+ 'expected_effective_size': 10
+ },
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'expected_size': 30,
+ 'expected_effective_size': 0,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 30
+ }
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1,
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_allSizesDefined_childrenAddUp', [
+ [
+ {
+ 'name': 'v8',
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 30,
+ 'children': [
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 16,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 14
+ }
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1,
+ 'size': 14,
+ 'expected_size': 14,
+ 'expected_effective_size': 14
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_allSizesDefined_childrenDontAddUp', [
+ [
+ {
+ 'name': 'v8',
+ 'size': 35,
+ 'expected_size': 35,
+ 'expected_effective_size': 35,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 5,
+ 'expected_effective_size': 5
+ },
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'size': 30,
+ 'expected_size': 30,
+ 'expected_effective_size': 16,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 14
+ }
+ },
+ {
+ 'name': 'objects',
+ 'owns': 1,
+ 'size': 14,
+ 'expected_size': 14,
+ 'expected_effective_size': 14
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_deep', [
+ [
+ {
+ 'name': 'root',
+ 'expected_size': 17,
+ 'expected_effective_size': 17,
+ 'children': [
+ {
+ 'name': 'parent1',
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 5,
+ 'expected_owned_by_sibling_sizes': {
+ 'parent2': 5
+ },
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 2,
+ 'expected_effective_size': 2
+ },
+ {
+ 'name': 'child',
+ 'guid': 1,
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 3
+ }
+ ]
+ },
+ {
+ 'name': 'parent2',
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 5,
+ 'expected_owned_by_sibling_sizes': {
+ 'parent3': 3
+ },
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 3,
+ 'expected_effective_size': 3
+ },
+ {
+ 'name': 'child',
+ 'guid': 2,
+ 'owns': 1,
+ 'size': 5,
+ 'expected_size': 5,
+ 'expected_effective_size': 2
+ }
+ ]
+ },
+ {
+ 'name': 'parent3',
+ 'size': 7,
+ 'expected_size': 7,
+ 'expected_effective_size': 7,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 4,
+ 'expected_effective_size': 4
+ },
+ {
+ 'name': 'child',
+ 'owns': 2,
+ 'size': 3,
+ 'expected_size': 3,
+ 'expected_effective_size': 3
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('views_nested', [
+ [
+ {
+ 'name': 'system',
+ 'expected_size': 7,
+ 'expected_effective_size': 7,
+ 'children': [
+ {
+ 'name': 'subsystem-A',
+ 'owns': 15,
+ 'expected_size': 5,
+ 'expected_effective_size': 5,
+ 'children': [
+ {
+ 'name': 'objects',
+ 'owns': 30,
+ 'size': 3,
+ 'expected_size': 3,
+ 'expected_effective_size': 3
+ },
+ {
+ 'name': 'heaps',
+ 'guid': 30,
+ 'size': 5,
+ 'expected_size': 5,
+ 'expected_effective_size': 2,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 3
+ }
+ }
+ ]
+ },
+ {
+ 'name': 'subsystem-B',
+ 'guid': 15,
+ 'expected_size': 7,
+ 'expected_effective_size': 2,
+ 'expected_owned_by_sibling_sizes': {
+ 'subsystem-A': 5
+ },
+ 'children': [
+ {
+ 'name': 'objects',
+ 'owns': 40,
+ 'size': 7,
+ 'expected_size': 7,
+ 'expected_effective_size': 2
+ },
+ {
+ 'name': 'heaps',
+ 'guid': 40,
+ 'expected_size': 7,
+ 'expected_effective_size': 0,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 7
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('importance_equal', [
+ [ // GMD (both importances undefined and equal sizes).
+ {
+ 'name': 'owned',
+ 'guid': 1,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 4
+ },
+ {
+ 'name': 'owner1',
+ 'owns': 1,
+ 'size': 6,
+ 'expected_size': 6,
+ 'expected_effective_size': 3
+ },
+ {
+ 'name': 'owner2',
+ 'owns': 1,
+ 'size': 6,
+ 'expected_size': 6,
+ 'expected_effective_size': 3
+ }
+ ],
+ [ // PMD1 (only one importance defined and different sizes).
+ {
+ 'name': 'owned',
+ 'guid': 2,
+ 'size': 20,
+ 'expected_size': 20,
+ 'expected_effective_size': 5
+ },
+ {
+ 'name': 'owner1',
+ 'owns': 2,
+ 'importance': 0,
+ 'size': 15,
+ 'expected_size': 15,
+ 'expected_effective_size': 10 / 2 + 5
+ },
+ {
+ 'name': 'owner2',
+ 'owns': 2,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 10 / 2
+ }
+ ],
+ [ // PMD2 (all importances defined and different sizes).
+ {
+ 'name': 'owned',
+ 'guid': 3,
+ 'size': 15,
+ 'expected_size': 15,
+ 'expected_effective_size': 5
+ },
+ {
+ 'name': 'owner1',
+ 'owns': 3,
+ 'importance': 3,
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 8 / 3
+ },
+ {
+ 'name': 'owner2',
+ 'owns': 3,
+ 'importance': 3,
+ 'size': 9,
+ 'expected_size': 9,
+ 'expected_effective_size': 8 / 3 + 1 / 2
+ },
+ {
+ 'name': 'owner3',
+ 'owns': 3,
+ 'importance': 3,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 8 / 3 + 1 / 2 + 1
+ }
+ ]
+ ]);
+
+ calculationTest('importance_notEqual', [
+ [ // GMD (one importance undefined and equal sizes).
+ {
+ 'name': 'owned',
+ 'guid': 1,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 4
+ },
+ {
+ 'name': 'owner1',
+ 'owns': 1,
+ 'size': 6,
+ 'expected_size': 6,
+ 'expected_effective_size': 0
+ },
+ {
+ 'name': 'owner2',
+ 'owns': 1,
+ 'importance': 1,
+ 'size': 6,
+ 'expected_size': 6,
+ 'expected_effective_size': 6
+ }
+ ],
+ [ // PMD1 (one importance undefined and different sizes).
+ {
+ 'name': 'owned',
+ 'guid': 2,
+ 'size': 20,
+ 'expected_size': 20,
+ 'expected_effective_size': 4
+ },
+ {
+ 'name': 'owner1',
+ 'owns': 2,
+ 'importance': -1,
+ 'size': 16,
+ 'expected_size': 16,
+ 'expected_effective_size': 6
+ },
+ {
+ 'name': 'owner2',
+ 'owns': 2,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 10
+ }
+ ],
+ [ // PMD2 (all importances defined and different sizes).
+ {
+ 'name': 'owned',
+ 'guid': 3,
+ 'size': 15,
+ 'expected_size': 15,
+ 'expected_effective_size': 5
+ },
+ {
+ 'name': 'owner1',
+ 'owns': 3,
+ 'importance': 4,
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 8
+ },
+ {
+ 'name': 'owner2',
+ 'owns': 3,
+ 'importance': 3,
+ 'size': 6,
+ 'expected_size': 6,
+ 'expected_effective_size': 0
+ },
+ {
+ 'name': 'owner3',
+ 'owns': 3,
+ 'importance': 2,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 2
+ }
+ ]
+ ]);
+
+ // Example taken from GlobalMemoryDump.calculateDumpOwnershipCoefficient_()
+ // documentation.
+ calculationTest('importance_manyOwners', [
+ [ // GMD.
+ {
+ 'name': 'owned',
+ 'guid': 4,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 2
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'owner1',
+ 'owns': 4,
+ 'importance': 2,
+ 'size': 6,
+ 'expected_size': 6,
+ 'expected_effective_size': 6 / 2
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'some_parent',
+ 'expected_size': 7,
+ 'expected_effective_size': 6 / 2 + 1,
+ 'children': [
+ {
+ 'name': 'owner2',
+ 'owns': 4,
+ 'importance': 2,
+ 'size': 7,
+ 'expected_size': 7,
+ 'expected_effective_size': 6 / 2 + 1
+ }
+ ]
+ }
+ ],
+ [ // PMD3.
+ {
+ 'name': 'owner3',
+ 'owns': 4,
+ 'importance': 1,
+ 'size': 5,
+ 'expected_size': 5,
+ 'expected_effective_size': 0
+ },
+ {
+ 'name': 'owner4',
+ 'owns': 4,
+ 'importance': 0,
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 1
+ }
+ ]
+ ]);
+
+ calculationTest('importance_chainOwnerships', [
+ [ // GMD.
+ {
+ 'name': 'owned',
+ 'guid': 5,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 2
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'owner1',
+ 'owns': 5,
+ 'importance': 2,
+ 'guid': 6,
+ 'size': 6,
+ 'expected_size': 6,
+ 'expected_effective_size': 2
+ },
+ {
+ 'name': 'subowner1',
+ 'owns': 6,
+ 'size': 4,
+ 'expected_size': 4,
+ 'expected_effective_size': 4
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'owner2',
+ 'owns': 5,
+ 'importance': 1,
+ 'guid': 8,
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 2 - 2 / 4
+ },
+ {
+ 'name': 'subowner2',
+ 'owns': 8,
+ 'size': 2,
+ 'expected_size': 2,
+ 'expected_effective_size': 2 / 4
+ }
+ ]
+ ]);
+
+ calculationTest('importance_nested', [
+ [
+ {
+ 'name': 'grey',
+ 'guid': 15,
+ 'size': 20,
+ 'expected_size': 20,
+ 'expected_effective_size': 6
+ },
+ {
+ 'name': 'blue',
+ 'guid': 18,
+ 'owns': 15,
+ 'importance': 1,
+ 'size': 14,
+ 'expected_size': 14,
+ 'expected_effective_size': 1
+ },
+ {
+ 'name': 'purple',
+ 'owns': 15,
+ 'importance': 2,
+ 'size': 7,
+ 'expected_size': 7,
+ 'expected_effective_size': 7
+ },
+ {
+ 'name': 'yellow',
+ 'owns': 21,
+ 'importance': 3,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 3
+ },
+ {
+ 'name': 'red',
+ 'guid': 21,
+ 'owns': 18,
+ 'size': 12,
+ 'expected_size': 12,
+ 'expected_effective_size': 1
+ },
+ {
+ 'name': 'green',
+ 'owns': 21,
+ 'importance': 3,
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 2
+ }
+ ]
+ ]);
+
+ calculationTest('importance_singleRefinement', [
+ [
+ {
+ 'name': 'v8',
+ 'expected_size': 13,
+ 'expected_effective_size': 13,
+ 'children': [
+ {
+ 'name': 'objects',
+ 'owns': 1,
+ 'size': 11,
+ 'expected_size': 11,
+ 'expected_effective_size': 11,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 4,
+ 'expected_effective_size': 4
+ },
+ {
+ 'name': 'object1',
+ 'owns': 2,
+ 'size': 7,
+ 'expected_size': 7,
+ 'expected_effective_size': 7
+ }
+ ]
+ },
+ {
+ 'name': 'heaps',
+ 'guid': 1,
+ 'size': 13,
+ 'expected_size': 13,
+ 'expected_effective_size': 2,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 11
+ },
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 3,
+ 'expected_effective_size': 1
+ },
+ {
+ 'name': 'heap1',
+ 'guid': 2,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 1,
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+
+ calculationTest('importance_sharedRefinement', [
+ [ // GMD.
+ {
+ 'name': 'shared_bitmap',
+ 'guid': 0,
+ 'size': 23,
+ 'expected_size': 23,
+ 'expected_effective_size': 5,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 13,
+ 'expected_effective_size': 13 * 5 / (13 + 3)
+ },
+ {
+ 'name': 'bitmap0x7',
+ 'guid': 999,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 3 * 5 / (13 + 3),
+ }
+ ]
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'tile_manager',
+ 'owns': 0,
+ 'importance': 2,
+ 'size': 12,
+ 'expected_size': 12,
+ 'expected_effective_size': 5 + 2,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 5,
+ 'expected_effective_size': 5
+ },
+ {
+ 'name': 'tile42',
+ 'owns': 999,
+ 'importance': 1,
+ 'size': 7,
+ 'expected_size': 7,
+ 'expected_effective_size': 2,
+ }
+ ]
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'gpu',
+ 'owns': 0,
+ 'importance': 1,
+ 'size': 16,
+ 'expected_size': 16,
+ 'expected_effective_size': 6 + 5,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 11,
+ 'expected_effective_size': 6
+ },
+ {
+ 'name': 'chunk-3.14',
+ 'owns': 999,
+ 'importance': 2,
+ 'size': 5,
+ 'expected_size': 5,
+ 'expected_effective_size': 5,
+ }
+ ]
+ }
+ ]
+ ]);
+
+ // Example taken from https://goo.gl/fKg0dt.
+ calculationTest('documentationExample', [
+ [ // GMD, Global (shared) memory.
+ {
+ 'name': 'unknown',
+ 'guid': 2,
+ 'expected_size': 16,
+ 'expected_effective_size': 0,
+ }
+ ],
+ [ // PMD1, Browser process.
+ {
+ 'name': 'sharedbitmap',
+ 'size': 17,
+ 'expected_size': 17,
+ 'expected_effective_size': 9,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 1,
+ 'expected_effective_size': 1
+ },
+ {
+ 'name': '0x7',
+ 'size': 16,
+ 'expected_size': 16,
+ 'expected_effective_size': 8,
+ 'owns': 2,
+ 'importance': 1,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 16,
+ 'expected_effective_size': 8
+ },
+ {
+ 'name': 'y'
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ [ // PMD2, Renderer process.
+ {
+ 'name': 'v8',
+ 'expected_size': 13,
+ 'expected_effective_size': 13,
+ 'children': [
+ {
+ 'name': 'heaps',
+ 'guid': 100,
+ 'expected_size': 12,
+ 'expected_effective_size': 3,
+ 'expected_owned_by_sibling_sizes': {
+ 'objects': 9
+ },
+ 'children': [
+ {
+ 'name': '1',
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 2,
+ 'owns': 2,
+ 'importance': 2
+ },
+ {
+ 'name': '2',
+ 'expected_size': 4,
+ 'expected_effective_size': 1,
+ 'size': 4
+ }
+ ]
+ },
+ {
+ 'name': 'objects',
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 10,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 1,
+ 'expected_effective_size': 1
+ },
+ {
+ 'name': 'strings',
+ 'size': 9,
+ 'expected_size': 9,
+ 'expected_effective_size': 9,
+ 'owns': 100
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+
+ // This should never happen. Nevertheless, this test checks that we can
+ // handle invalid sizes (parent dump being smaller than its aggregated
+ // children and owned dump being smaller than its largest owner) gracefully.
+ calculationTest('invalidSizes', [
+ [
+ {
+ 'name': 'root1',
+ 'size': 24,
+ 'expected_size': 24,
+ 'expected_effective_size': 4,
+ 'children': [
+ {
+ 'name': '<unspecified>',
+ 'skip_build': true,
+ 'expected_size': 4,
+ 'expected_effective_size': 4
+ },
+ {
+ 'name': 'parent',
+ 'guid': 2,
+ 'size': 17, // Invalid: child has larger size.
+ 'expected_size': 20,
+ 'expected_infos': [
+ {
+ type: PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN,
+ providedSize: 17,
+ dependencySize: 20
+ },
+ {
+ type: PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER,
+ providedSize: 17,
+ dependencySize: 18
+ }
+ ],
+ 'expected_effective_size': 0,
+ 'children': [
+ {
+ 'name': 'child',
+ 'guid': 1,
+ 'size': 10, // Invalid: owner has larger size.
+ 'expected_size': 20,
+ 'expected_infos': [
+ {
+ type: PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER,
+ providedSize: 10,
+ dependencySize: 20
+ }
+ ],
+ 'expected_effective_size': 0,
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'name': 'root2',
+ 'owns': 1,
+ 'size': 20,
+ 'expected_size': 20,
+ 'expected_effective_size': 20
+ },
+ {
+ 'name': 'root3',
+ 'owns': 2,
+ 'importance': -1,
+ 'size': 18,
+ 'expected_size': 18,
+ 'expected_effective_size': 18
+ }
+ ]
+ ]);
+
+ calculationTest('multipleInfos', [
+ [
+ {
+ 'name': 'root',
+ 'expected_size': 10,
+ 'expected_effective_size': 10,
+ 'children': [
+ {
+ 'name': 'parent1',
+ 'size': 5,
+ 'expected_size': 10,
+ 'expected_infos': [
+ {
+ type: PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN,
+ providedSize: 5,
+ dependencySize: 10
+ }
+ ],
+ 'expected_effective_size': 1,
+ 'expected_owned_by_sibling_sizes': {
+ 'parent2': 17,
+ 'parent3': 7
+ },
+ 'children': [
+ {
+ 'name': 'child',
+ 'guid': 3,
+ 'size': 10,
+ 'expected_size': 10,
+ 'expected_effective_size': 1,
+ }
+ ]
+ },
+ {
+ 'name': 'parent2',
+ // NOTE(petrcermak): The expected size here is a little strange
+ // because the children both own the same dump (namely
+ // root/parent1/child). It would, therefore, probably make more
+ // sense for the calculated size to be 9. Since this is an unlikely
+ // case and would complicate the (already complex) size
+ // calculation, we will now keep the algorithm as is.
+ 'expected_size': 17,
+ 'expected_effective_size': 14 / 3 + 2,
+ 'children': [
+ {
+ 'name': 'child1',
+ 'owns': 3,
+ 'size': 9,
+ 'expected_size': 9,
+ 'expected_effective_size': 7 / 3 + 1 / 2 + 1,
+ },
+ {
+ 'name': 'child2',
+ 'owns': 3,
+ 'size': 8,
+ 'expected_size': 8,
+ 'expected_effective_size': 7 / 3 + 1 / 2,
+ }
+ ]
+ },
+ {
+ 'name': 'parent3',
+ 'size': 7,
+ 'expected_size': 7,
+ 'expected_effective_size': 7 / 3,
+ 'owns': 3
+ }
+ ]
+ }
+ ]
+ ]);
+
+ // Check that size calculation is NOT preceded by numeric aggregation, which
+ // would recursively sum up size numerics.
+ test('finalizeGraph_aggregation', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ buildDumpTrees([
+ undefined, // GMD.
+ [ // PMD.
+ {
+ 'name': 'root',
+ 'children': [
+ {
+ 'name': 'owner_child',
+ 'owns': 9,
+ 'size': 7
+ },
+ {
+ 'name': 'owned_child',
+ 'guid': 9,
+ 'size': 20
+ }
+ ]
+ }
+ ]
+ ], model);
+ });
+ const pmd = model.getProcess(0).memoryDumps[0];
+
+ const rootDump = pmd.getMemoryAllocatorDumpByFullName('root');
+ assertDumpSizes(rootDump, 20, 20);
+
+ const ownerChildDump = pmd.getMemoryAllocatorDumpByFullName(
+ 'root/owner_child');
+ assertDumpSizes(ownerChildDump, 7, 7);
+
+ const ownedChildDump = pmd.getMemoryAllocatorDumpByFullName(
+ 'root/owned_child');
+ assertDumpSizes(ownedChildDump, 20, 13, [] /* expectedInfos */,
+ {'owner_child': 7} /* expectedOwnedBySiblingSizes */);
+ });
+
+ // Check that numeric and diagnostics propagation and aggregation are
+ // performed in the correct order.
+ test('finalizeGraph_propagation', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ buildDumpTrees([
+ [ // GMD.
+ {
+ 'name': 'owned_root',
+ 'guid': 1,
+ 'size': 10,
+ 'diagnostics': {
+ 'url': 'https://hello.world.com:42'
+ },
+ 'children': [
+ {
+ 'name': 'owned_child1',
+ 'numerics': {
+ 'summed': new Scalar(sizeInBytes_smallerIsBetter, 12)
+ },
+ 'diagnostics': {
+ 'url2': 'http://not.aggregated.to/owned/parent/dump'
+ }
+ },
+ {
+ 'name': 'owned_child2',
+ 'numerics': {
+ 'summed': new Scalar(sizeInBytes_smallerIsBetter, 15)
+ }
+ }
+ ]
+ }
+ ],
+ [ // PMD.
+ {
+ 'name': 'direct_owner',
+ 'owns': 1,
+ 'guid': 2,
+ 'diagnostics': {
+ 'url': 'file://not_overriden.html'
+ }
+ },
+ {
+ 'name': 'parent_owner',
+ 'children': [
+ {
+ 'name': 'child_owner',
+ 'owns': 1
+ },
+ {
+ 'name': 'sibling',
+ 'size': 5,
+ 'numerics': {
+ 'summed': new Scalar(sizeInBytes_smallerIsBetter, 13)
+ }
+ }
+ ]
+ },
+ {
+ 'name': 'precedent_owner',
+ 'owns': 1,
+ 'numerics': {
+ 'summed': new Scalar(sizeInBytes_smallerIsBetter, 0)
+ }
+ },
+ {
+ 'name': 'indirect_owner',
+ 'owns': 2
+ }
+ ]
+ ], model);
+ });
+ const pmd = model.getProcess(0).memoryDumps[0];
+
+ checkDumpNumericsAndDiagnostics(
+ pmd.getMemoryAllocatorDumpByFullName('direct_owner'),
+ {
+ size: 10,
+ effective_size: 3.3333,
+ summed: 27
+ },
+ {
+ url: 'file://not_overriden.html'
+ });
+ checkDumpNumericsAndDiagnostics(
+ pmd.getMemoryAllocatorDumpByFullName('parent_owner/child_owner'),
+ {
+ size: 10,
+ effective_size: 3.3333,
+ summed: 27
+ },
+ {
+ url: 'https://hello.world.com:42'
+ });
+ checkDumpNumericsAndDiagnostics(
+ pmd.getMemoryAllocatorDumpByFullName('parent_owner'),
+ {
+ size: 15,
+ effective_size: 8.3333,
+ summed: 40
+ }, {});
+ checkDumpNumericsAndDiagnostics(
+ pmd.getMemoryAllocatorDumpByFullName('precedent_owner'),
+ {
+ size: 10,
+ effective_size: 3.3333,
+ summed: 0
+ },
+ {
+ url: 'https://hello.world.com:42'
+ });
+ checkDumpNumericsAndDiagnostics(
+ pmd.getMemoryAllocatorDumpByFullName('indirect_owner'), {}, {});
+ });
+
+ // Check that weak dumps are removed before size size calculation.
+ test('finalizeGraph_weakDumpRemoval', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ buildDumpTrees([
+ undefined, // GMD.
+ [ // PMD.
+ {
+ 'name': 'root',
+ 'children': [
+ {
+ 'name': 'directly_weak_child',
+ 'weak': true,
+ 'guid': 5,
+ 'owns': 10,
+ 'size': 100
+ },
+ {
+ 'name': 'strong_child',
+ 'guid': 10,
+ 'size': 120
+ },
+ {
+ 'name': 'indirectly_weak_child',
+ 'owns': 5,
+ 'size': 70
+ },
+ {
+ 'name': 'separate_weak_child',
+ 'weak': true,
+ 'size': 300
+ }
+ ]
+ }
+ ]
+ ], model);
+ });
+ const pmd = model.getProcess(0).memoryDumps[0];
+
+ const rootDump = pmd.getMemoryAllocatorDumpByFullName('root');
+ assertDumpSizes(rootDump, 120, 120);
+ assert.lengthOf(rootDump.children, 1);
+
+ const strongChildDump = pmd.getMemoryAllocatorDumpByFullName(
+ 'root/strong_child');
+ assertDumpSizes(strongChildDump, 120, 120);
+ assert.lengthOf(strongChildDump.ownedBy, 0);
+
+ assert.isUndefined(pmd.getMemoryAllocatorDumpByFullName(
+ 'root/directly_weak_child'));
+ assert.isUndefined(pmd.getMemoryAllocatorDumpByFullName(
+ 'root/indirectly_weak_child'));
+ assert.isUndefined(pmd.getMemoryAllocatorDumpByFullName(
+ 'root/separate_weak_child'));
+ });
+
+ test('indicesUpdatedCorrectly', function() {
+ let gmd;
+ let rootDump;
+ let childDump;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ gmd = new GlobalMemoryDump(model, 10);
+ model.globalMemoryDumps.push(gmd);
+
+ rootDump = newAllocatorDump(gmd, 'root', {numerics: {size: 64}});
+ childDump = addChildDump(rootDump, 'child', {numerics: {size: 48}});
+
+ gmd.memoryAllocatorDumps = [rootDump];
+
+ // Before model is finalized.
+ assert.strictEqual(
+ gmd.getMemoryAllocatorDumpByFullName('root'), rootDump);
+ assert.strictEqual(
+ gmd.getMemoryAllocatorDumpByFullName('root/child'), childDump);
+ assert.isUndefined(
+ gmd.getMemoryAllocatorDumpByFullName('root/<unspecified>'));
+ });
+
+ // Test sanity check.
+ assert.isDefined(gmd);
+ assert.isDefined(rootDump);
+ assert.isDefined(childDump);
+
+ // After model is finalized.
+ assert.strictEqual(gmd.getMemoryAllocatorDumpByFullName('root'), rootDump);
+ assert.strictEqual(
+ gmd.getMemoryAllocatorDumpByFullName('root/child'), childDump);
+ const unspecifiedDump =
+ gmd.getMemoryAllocatorDumpByFullName('root/<unspecified>');
+ assert.strictEqual(unspecifiedDump.fullName, 'root/<unspecified>');
+ assert.strictEqual(unspecifiedDump.parent, rootDump);
+ assert.strictEqual(rootDump.children[0], unspecifiedDump);
+ });
+
+ weakDumpRemovalTest('allDumpsNonWeak', [
+ [ // GMD.
+ {
+ 'name': 'malloc',
+ 'children': [
+ {
+ 'name': 'allocated_objects',
+ 'children': [
+ {
+ 'name': 'obj42',
+ 'guid': 5,
+ 'expected_owned_by_links_count': 2
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ undefined, // PMD1.
+ [ // PMD2.
+ {
+ 'name': 'oilpan'
+ },
+ {
+ 'name': 'v8',
+ 'children': [
+ {
+ 'name': 'heaps',
+ 'children': [
+ {
+ 'name': 'S',
+ 'owns': 5
+ },
+ {
+ 'name': 'L',
+ 'owns': 5
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+
+ weakDumpRemovalTest('weakRootDump', [
+ [], // GMD.
+ [ // PMD1.
+ {
+ 'name': 'strong1'
+ },
+ {
+ 'name': 'weak',
+ 'weak': true,
+ 'expected_removed': true
+ },
+ {
+ 'name': 'strong2'
+ }
+ ]
+ ]);
+
+ weakDumpRemovalTest('weakChildDump', [
+ [ // GMD.
+ {
+ 'name': 'root',
+ 'children': [
+ {
+ 'name': 'parent',
+ 'children': [
+ {
+ 'name': 'strong1'
+ },
+ {
+ 'name': 'weak',
+ 'weak': true,
+ 'expected_removed': true,
+ 'children': [
+ {
+ 'name': 'implicitly-removed'
+ }
+ ]
+ },
+ {
+ 'name': 'strong2'
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ]);
+
+ weakDumpRemovalTest('transitiveOwnerRemoval', [
+ [ // GMD.
+ {
+ 'name': 'not-removed-strong-dump',
+ 'guid': 0,
+ 'expected_owned_by_links_count': 1
+ },
+ {
+ 'name': 'weak-owned-dump',
+ 'guid': 1,
+ 'owns': 0,
+ 'weak': true,
+ 'expected_removed': true
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'direct-owner-dump',
+ 'guid': 2,
+ 'owns': 1,
+ 'expected_removed': true
+ },
+ {
+ 'name': 'also-not-removed-strong-dump',
+ 'owns': 0
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'indirect-owner-dump',
+ 'owns': 2,
+ 'expected_removed': true
+ }
+ ]
+ ]);
+
+ weakDumpRemovalTest('transitiveDescendantRemoval', [
+ [ // GMD.
+ {
+ 'name': 'A',
+ 'owns': 10,
+ // A =owns=> B -child-of-> C -> D => E -> F -> G (weak).
+ 'expected_removed': true
+ },
+ {
+ 'name': 'D',
+ 'owns': 5,
+ 'expected_removed': true, // D =owns=> E -child-of-> F -> G (weak).
+ 'children': [
+ {
+ 'name': 'C',
+ 'children': [
+ {
+ 'name': 'B',
+ 'guid': 10
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ undefined, // PMD1.
+ [ // PMD2.
+ {
+ 'name': 'first-retained-dump',
+ 'children': [
+ {
+ 'name': 'G',
+ 'weak': true,
+ 'expected_removed': true,
+ 'children': [
+ {
+ 'name': 'F',
+ 'children': [
+ {
+ 'name': 'E',
+ 'guid': 5
+ }
+ ]
+ },
+ {
+ 'name': 'H',
+ 'children': [
+ {
+ 'name': 'I',
+ 'children': [
+ {
+ 'name': 'J',
+ 'owns': 2
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ [ // PMD3.
+ {
+ 'name': 'second-retained-dump',
+ 'guid': 2,
+ // The only owner (J) is removed because J -child-of-> I -> H ->
+ // G (weak).
+ 'expected_owned_by_links_count': 0
+ }
+ ]
+ ]);
+
+ weakDumpRemovalTest('subownerships', [
+ [ // GMD.
+ {
+ 'name': 'root1',
+ 'owns': 20,
+ 'expected_removed': true, // root1 =owns=> root2 (weak).
+ 'children': [
+ {
+ 'name': 'child1',
+ 'owns': 2
+ }
+ ]
+ },
+ {
+ 'name': 'root2',
+ 'guid': 20,
+ 'owns': 30,
+ 'weak': true,
+ 'expected_removed': true,
+ 'children': [
+ {
+ 'name': 'child2',
+ 'guid': 2,
+ 'owns': 3
+ }
+ ]
+ },
+ {
+ 'name': 'root3',
+ 'guid': 30,
+ 'owns': 40,
+ 'expected_owned_by_links_count': 0,
+ 'children': [
+ {
+ 'name': 'child3',
+ 'guid': 3,
+ 'owns': 4,
+ 'weak': true,
+ 'expected_removed': true
+ }
+ ]
+ }
+ ],
+ [ // PMD1.
+ {
+ 'name': 'root4',
+ 'guid': 40,
+ 'expected_owned_by_links_count': 1,
+ 'children': [
+ {
+ 'name': 'child4',
+ 'guid': 4,
+ 'expected_owned_by_links_count': 0
+ }
+ ]
+ }
+ ],
+ [ // PMD2.
+ {
+ 'name': 'root5',
+ 'owns': 60,
+ 'expected_removed': true, // root5 =owns=> root6 => root7 (weak).
+ 'children': [
+ {
+ 'name': 'child5',
+ 'owns': 6
+ }
+ ]
+ },
+ {
+ 'name': 'root6',
+ 'guid': 60,
+ 'owns': 70,
+ 'expected_removed': true, // root6 =owns=> root7 (weak).
+ 'children': [
+ {
+ 'name': 'child6',
+ 'guid': 6,
+ 'owns': 7
+ }
+ ]
+ },
+ {
+ 'name': 'root7',
+ 'guid': 70,
+ 'owns': 40,
+ 'weak': true,
+ 'expected_removed': true,
+ 'children': [
+ {
+ 'name': 'child7',
+ 'guid': 7,
+ 'owns': 4
+ }
+ ]
+ }
+ ]
+ ]);
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/heap_dump.html b/chromium/third_party/catapult/tracing/tracing/model/heap_dump.html
new file mode 100644
index 00000000000..ec81a382b6f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/heap_dump.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * HeapEntry represents a single value describing the state of the heap of an
+ * allocator in a single process.
+ *
+ * An entry specifies how much space (e.g. 19 MiB) was allocated in a
+ * particular context, which consists of a codepath (e.g. drawQuad <- draw <-
+ * MessageLoop::RunTask) and an object type (e.g. HTMLImportLoader).
+ *
+ * If |valuesAreTotals| is true the size and count of this entry are totals
+ * for this and all more specific entries, otherwise they are values just for
+ * this specific entry.
+ *
+ * @{constructor}
+ */
+ function HeapEntry(
+ heapDump, leafStackFrame, objectTypeName, size, count, valuesAreTotals) {
+ this.heapDump = heapDump;
+
+ // The leaf stack frame of the associated backtrace (e.g. drawQuad for the
+ // drawQuad <- draw <- MessageLoop::RunTask backtrace). If undefined, the
+ // backtrace is empty.
+ this.leafStackFrame = leafStackFrame;
+
+ // The name of the allocated object type (e.g. 'HTMLImportLoader'). If
+ // undefined, the entry represents the sum over all object types.
+ this.objectTypeName = objectTypeName;
+
+ this.size = size;
+ this.count = count;
+ this.valuesAreTotals = valuesAreTotals;
+ }
+
+ /**
+ * HeapDump represents a dump of the heap of an allocator in a single process
+ * at a particular timestamp.
+ *
+ * @{constructor}
+ */
+ function HeapDump(processMemoryDump, allocatorName, isComplete) {
+ this.processMemoryDump = processMemoryDump;
+ this.allocatorName = allocatorName;
+ this.isComplete = isComplete;
+ this.entries = [];
+ }
+
+ HeapDump.prototype = {
+ addEntry(
+ leafStackFrame, objectTypeName, size, count, opt_valuesAreTotals) {
+ if (opt_valuesAreTotals === undefined) opt_valuesAreTotals = true;
+ const valuesAreTotals = opt_valuesAreTotals;
+ const entry = new HeapEntry(
+ this, leafStackFrame, objectTypeName, size, count, valuesAreTotals);
+ this.entries.push(entry);
+ return entry;
+ }
+ };
+
+ return {
+ HeapEntry,
+ HeapDump,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/heap_dump_test.html b/chromium/third_party/catapult/tracing/tracing/model/heap_dump_test.html
new file mode 100644
index 00000000000..9ce01725c03
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/heap_dump_test.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/heap_dump.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+<link rel="import" href="/tracing/model/stack_frame.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const GlobalMemoryDump = tr.model.GlobalMemoryDump;
+ const ProcessMemoryDump = tr.model.ProcessMemoryDump;
+ const StackFrame = tr.model.StackFrame;
+ const HeapEntry = tr.model.HeapEntry;
+ const HeapDump = tr.model.HeapDump;
+
+ test('heapDumps', function() {
+ const model = new tr.Model();
+ const process = model.getOrCreateProcess(89);
+ const gmd = new GlobalMemoryDump(model, 42);
+ model.globalMemoryDumps.push(gmd);
+ const pmd = new ProcessMemoryDump(gmd, process, 42);
+ process.memoryDumps.push(pmd);
+
+ const rootFrame = new StackFrame(
+ undefined, tr.b.GUID.allocateSimple(), undefined);
+ const childFrame = new StackFrame(
+ rootFrame, tr.b.GUID.allocateSimple(), 'draw');
+ rootFrame.addChild(childFrame);
+
+ const dump = new HeapDump(pmd);
+ assert.strictEqual(dump.processMemoryDump, pmd);
+ assert.lengthOf(dump.entries, 0);
+
+ const entry1 = dump.addEntry(
+ childFrame, 'HTMLImportLoader', 1024, undefined);
+ assert.strictEqual(entry1.heapDump, dump);
+ assert.strictEqual(entry1.leafStackFrame, childFrame);
+ assert.strictEqual(entry1.objectTypeName, 'HTMLImportLoader');
+ assert.strictEqual(entry1.size, 1024);
+ assert.isUndefined(entry1.count);
+
+ const entry2 = dump.addEntry(undefined, undefined, 1048576, 42);
+ assert.strictEqual(entry2.heapDump, dump);
+ assert.isUndefined(entry2.leafStackFrame);
+ assert.isUndefined(entry2.objectTypeName);
+ assert.strictEqual(entry2.size, 1048576);
+ assert.strictEqual(entry2.count, 42);
+
+ assert.deepEqual(dump.entries, [entry1, entry2]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/android_app.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/android_app.html
new file mode 100644
index 00000000000..9cabb504606
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/android_app.html
@@ -0,0 +1,344 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/frame.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Class for managing android-specific model meta data,
+ * such as rendering apps, and frames rendered.
+ */
+tr.exportTo('tr.model.helpers', function() {
+ const Frame = tr.model.Frame;
+ const Statistics = tr.b.math.Statistics;
+
+ const UI_DRAW_TYPE = {
+ NONE: 'none',
+ LEGACY: 'legacy',
+ MARSHMALLOW: 'marshmallow'
+ };
+
+ const UI_THREAD_DRAW_NAMES = {
+ 'performTraversals': UI_DRAW_TYPE.LEGACY,
+ 'Choreographer#doFrame': UI_DRAW_TYPE.MARSHMALLOW
+ };
+
+ const RENDER_THREAD_DRAW_NAME = 'DrawFrame';
+ const RENDER_THREAD_INDEP_DRAW_NAME = 'doFrame';
+ const RENDER_THREAD_QUEUE_NAME = 'queueBuffer';
+ const RENDER_THREAD_SWAP_NAME = 'eglSwapBuffers';
+ const THREAD_SYNC_NAME = 'syncFrameState';
+
+ function getSlicesForThreadTimeRanges(threadTimeRanges) {
+ const ret = [];
+ threadTimeRanges.forEach(function(threadTimeRange) {
+ const slices = [];
+
+ threadTimeRange.thread.sliceGroup.iterSlicesInTimeRange(
+ function(slice) { slices.push(slice); },
+ threadTimeRange.start, threadTimeRange.end);
+ ret.push.apply(ret, slices);
+ });
+ return ret;
+ }
+
+ function makeFrame(threadTimeRanges, surfaceFlinger) {
+ const args = {};
+ if (surfaceFlinger && surfaceFlinger.hasVsyncs) {
+ const start = Statistics.min(threadTimeRanges,
+ function(threadTimeRanges) { return threadTimeRanges.start; });
+ args.deadline = surfaceFlinger.getFrameDeadline(start);
+ args.frameKickoff = surfaceFlinger.getFrameKickoff(start);
+ }
+ const events = getSlicesForThreadTimeRanges(threadTimeRanges);
+ return new Frame(events, threadTimeRanges, args);
+ }
+
+ function findOverlappingDrawFrame(renderThread, uiDrawSlice) {
+ if (!renderThread) return undefined;
+
+ // of all top level renderthread slices, find the one that has a 'sync'
+ // within the uiDrawSlice
+ let overlappingDrawFrame;
+ const slices = tr.b.iterateOverIntersectingIntervals(
+ renderThread.sliceGroup.slices,
+ function(range) { return range.start; },
+ function(range) { return range.end; },
+ uiDrawSlice.start,
+ uiDrawSlice.end,
+ function(rtDrawSlice) {
+ if (rtDrawSlice.title === RENDER_THREAD_DRAW_NAME) {
+ const rtSyncSlice = rtDrawSlice.findDescendentSlice(
+ THREAD_SYNC_NAME);
+ if (rtSyncSlice &&
+ rtSyncSlice.start >= uiDrawSlice.start &&
+ rtSyncSlice.end <= uiDrawSlice.end) {
+ // sync observed which overlaps ui draw. This means the RT draw
+ // corresponds to the UI draw
+ overlappingDrawFrame = rtDrawSlice;
+ }
+ }
+ });
+ return overlappingDrawFrame;
+ }
+
+ /**
+ * Builds an array of {start, end} ranges grouping common work of a frame
+ * that occurs just before performTraversals().
+ *
+ * Only necessary before Choreographer#doFrame tracing existed.
+ */
+ function getPreTraversalWorkRanges(uiThread) {
+ if (!uiThread) return [];
+
+ // gather all frame work that occurs outside of performTraversals
+ const preFrameEvents = [];
+ uiThread.sliceGroup.slices.forEach(function(slice) {
+ if (slice.title === 'obtainView' ||
+ slice.title === 'setupListItem' ||
+ slice.title === 'deliverInputEvent' ||
+ slice.title === 'RV Scroll') {
+ preFrameEvents.push(slice);
+ }
+ });
+ uiThread.asyncSliceGroup.slices.forEach(function(slice) {
+ if (slice.title === 'deliverInputEvent') {
+ preFrameEvents.push(slice);
+ }
+ });
+
+ return tr.b.math.mergeRanges(
+ tr.b.math.convertEventsToRanges(preFrameEvents),
+ 3,
+ function(events) {
+ return {
+ start: events[0].min,
+ end: events[events.length - 1].max
+ };
+ });
+ }
+
+ function getFrameStartTime(traversalStart, preTraversalWorkRanges) {
+ const preTraversalWorkRange =
+ tr.b.findClosestIntervalInSortedIntervals(
+ preTraversalWorkRanges,
+ function(range) { return range.start; },
+ function(range) { return range.end; },
+ traversalStart,
+ 3);
+
+ if (preTraversalWorkRange) {
+ return preTraversalWorkRange.start;
+ }
+ return traversalStart;
+ }
+
+ function getRtFrameEndTime(rtDrawSlice) {
+ // First try and get time that frame is queued:
+ const rtQueueSlice = rtDrawSlice.findDescendentSlice(
+ RENDER_THREAD_QUEUE_NAME);
+ if (rtQueueSlice) {
+ return rtQueueSlice.end;
+ }
+ // failing that, end of swapbuffers:
+ const rtSwapSlice = rtDrawSlice.findDescendentSlice(
+ RENDER_THREAD_SWAP_NAME);
+ if (rtSwapSlice) {
+ return rtSwapSlice.end;
+ }
+ // failing that, end of renderthread frame trace
+ return rtDrawSlice.end;
+ }
+
+ function getUiThreadDrivenFrames(app) {
+ if (!app.uiThread) return [];
+
+ let preTraversalWorkRanges = [];
+ if (app.uiDrawType === UI_DRAW_TYPE.LEGACY) {
+ preTraversalWorkRanges = getPreTraversalWorkRanges(app.uiThread);
+ }
+
+ const frames = [];
+ app.uiThread.sliceGroup.slices.forEach(function(slice) {
+ if (!(slice.title in UI_THREAD_DRAW_NAMES)) {
+ return;
+ }
+
+ const threadTimeRanges = [];
+ const uiThreadTimeRange = {
+ thread: app.uiThread,
+ start: getFrameStartTime(slice.start, preTraversalWorkRanges),
+ end: slice.end
+ };
+ threadTimeRanges.push(uiThreadTimeRange);
+
+ // on SDK 21+ devices with RenderThread,
+ // account for time taken on RenderThread
+ const rtDrawSlice = findOverlappingDrawFrame(
+ app.renderThread, slice);
+ if (rtDrawSlice) {
+ const rtSyncSlice = rtDrawSlice.findDescendentSlice(THREAD_SYNC_NAME);
+ if (rtSyncSlice) {
+ // Generally, the UI thread is only on the critical path
+ // until the start of sync.
+ uiThreadTimeRange.end = Math.min(uiThreadTimeRange.end,
+ rtSyncSlice.start);
+ }
+
+ threadTimeRanges.push({
+ thread: app.renderThread,
+ start: rtDrawSlice.start,
+ end: getRtFrameEndTime(rtDrawSlice)
+ });
+ }
+ frames.push(makeFrame(threadTimeRanges, app.surfaceFlinger));
+ });
+ return frames;
+ }
+
+ function getRenderThreadDrivenFrames(app) {
+ if (!app.renderThread) return [];
+
+ const frames = [];
+ app.renderThread.sliceGroup.getSlicesOfName(RENDER_THREAD_INDEP_DRAW_NAME)
+ .forEach(function(slice) {
+ const threadTimeRanges = [{
+ thread: app.renderThread,
+ start: slice.start,
+ end: slice.end
+ }];
+ frames.push(makeFrame(threadTimeRanges, app.surfaceFlinger));
+ });
+ return frames;
+ }
+
+ function getUiDrawType(uiThread) {
+ if (!uiThread) {
+ return UI_DRAW_TYPE.NONE;
+ }
+
+ const slices = uiThread.sliceGroup.slices;
+ for (let i = 0; i < slices.length; i++) {
+ if (slices[i].title in UI_THREAD_DRAW_NAMES) {
+ return UI_THREAD_DRAW_NAMES[slices[i].title];
+ }
+ }
+ return UI_DRAW_TYPE.NONE;
+ }
+
+ function getInputSamples(process) {
+ let samples = undefined;
+ for (const counterName in process.counters) {
+ if (/^android\.aq\:pending/.test(counterName) &&
+ process.counters[counterName].numSeries === 1) {
+ samples = process.counters[counterName].series[0].samples;
+ break;
+ }
+ }
+
+ if (!samples) return [];
+
+ // output rising edges only, since those are user inputs
+ const inputSamples = [];
+ let lastValue = 0;
+ samples.forEach(function(sample) {
+ if (sample.value > lastValue) {
+ inputSamples.push(sample);
+ }
+ lastValue = sample.value;
+ });
+ return inputSamples;
+ }
+
+ function getAnimationAsyncSlices(uiThread) {
+ if (!uiThread) return [];
+
+ const slices = [];
+ for (const slice of uiThread.asyncSliceGroup.getDescendantEvents()) {
+ if (/^animator\:/.test(slice.title)) {
+ slices.push(slice);
+ }
+ }
+ return slices;
+ }
+
+ /**
+ * Model for Android App specific data.
+ * @constructor
+ */
+ function AndroidApp(process, uiThread, renderThread, surfaceFlinger,
+ uiDrawType) {
+ this.process = process;
+ this.uiThread = uiThread;
+ this.renderThread = renderThread;
+ this.surfaceFlinger = surfaceFlinger;
+ this.uiDrawType = uiDrawType;
+
+ this.frames_ = undefined;
+ this.inputs_ = undefined;
+ }
+
+ AndroidApp.createForProcessIfPossible = function(process, surfaceFlinger) {
+ let uiThread = process.getThread(process.pid);
+ const uiDrawType = getUiDrawType(uiThread);
+ if (uiDrawType === UI_DRAW_TYPE.NONE) {
+ uiThread = undefined;
+ }
+ const renderThreads = process.findAllThreadsNamed('RenderThread');
+ const renderThread = (renderThreads.length === 1 ?
+ renderThreads[0] : undefined);
+
+ if (uiThread || renderThread) {
+ return new AndroidApp(process, uiThread, renderThread, surfaceFlinger,
+ uiDrawType);
+ }
+ };
+
+ AndroidApp.prototype = {
+ /**
+ * Returns a list of all frames in the trace for the app,
+ * constructed on first query.
+ */
+ getFrames() {
+ if (!this.frames_) {
+ const uiFrames = getUiThreadDrivenFrames(this);
+ const rtFrames = getRenderThreadDrivenFrames(this);
+ this.frames_ = uiFrames.concat(rtFrames);
+
+ // merge frames by sorting by end timestamp
+ this.frames_.sort(function(a, b) { a.end - b.end; });
+ }
+ return this.frames_;
+ },
+
+ /**
+ * Returns list of CounterSamples for each input event enqueued to the app.
+ */
+ getInputSamples() {
+ if (!this.inputs_) {
+ this.inputs_ = getInputSamples(this.process);
+ }
+ return this.inputs_;
+ },
+
+ getAnimationAsyncSlices() {
+ if (!this.animations_) {
+ this.animations_ = getAnimationAsyncSlices(this.uiThread);
+ }
+ return this.animations_;
+ }
+ };
+
+ return {
+ AndroidApp,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/android_model_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/android_model_helper.html
new file mode 100644
index 00000000000..76239a31942
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/android_model_helper.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/core/auditor.html">
+<link rel="import" href="/tracing/model/helpers/android_app.html">
+<link rel="import" href="/tracing/model/helpers/android_surface_flinger.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Class for managing android-specific model meta data,
+ * such as rendering apps, frames rendered, and SurfaceFlinger.
+ */
+tr.exportTo('tr.model.helpers', function() {
+ const AndroidApp = tr.model.helpers.AndroidApp;
+ const AndroidSurfaceFlinger = tr.model.helpers.AndroidSurfaceFlinger;
+
+ const IMPORTANT_SURFACE_FLINGER_SLICES = {
+ 'doComposition': true,
+ 'updateTexImage': true,
+ 'postFramebuffer': true
+ };
+ const IMPORTANT_UI_THREAD_SLICES = {
+ 'Choreographer#doFrame': true,
+ 'performTraversals': true,
+ 'deliverInputEvent': true
+ };
+ const IMPORTANT_RENDER_THREAD_SLICES = {
+ 'doFrame': true
+ };
+
+ function iterateImportantThreadSlices(thread, important, callback) {
+ if (!thread) return;
+
+ thread.sliceGroup.slices.forEach(function(slice) {
+ if (slice.title in important) {
+ callback(slice);
+ }
+ });
+ }
+
+ /**
+ * Model for Android-specific data.
+ * @constructor
+ */
+ function AndroidModelHelper(model) {
+ this.model = model;
+ this.apps = [];
+ this.surfaceFlinger = undefined;
+
+ const processes = model.getAllProcesses();
+ for (let i = 0; i < processes.length && !this.surfaceFlinger; i++) {
+ this.surfaceFlinger =
+ AndroidSurfaceFlinger.createForProcessIfPossible(processes[i]);
+ }
+
+ model.getAllProcesses().forEach(function(process) {
+ const app = AndroidApp.createForProcessIfPossible(
+ process, this.surfaceFlinger);
+ if (app) {
+ this.apps.push(app);
+ }
+ }, this);
+ }
+
+ AndroidModelHelper.guid = tr.b.GUID.allocateSimple();
+
+ AndroidModelHelper.supportsModel = function(model) {
+ return true;
+ };
+
+ AndroidModelHelper.prototype = {
+ iterateImportantSlices(callback) {
+ if (this.surfaceFlinger) {
+ iterateImportantThreadSlices(
+ this.surfaceFlinger.thread,
+ IMPORTANT_SURFACE_FLINGER_SLICES,
+ callback);
+ }
+
+ this.apps.forEach(function(app) {
+ iterateImportantThreadSlices(
+ app.uiThread,
+ IMPORTANT_UI_THREAD_SLICES,
+ callback);
+ iterateImportantThreadSlices(
+ app.renderThread,
+ IMPORTANT_RENDER_THREAD_SLICES,
+ callback);
+ });
+ }
+ };
+
+ return {
+ AndroidModelHelper,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/android_model_helper_test.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/android_model_helper_test.html
new file mode 100644
index 00000000000..0add58195af
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/android_model_helper_test.html
@@ -0,0 +1,267 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/android/android_auditor.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AndroidModelHelper = tr.model.helpers.AndroidModelHelper;
+ const newAsyncSliceNamed = tr.c.TestUtils.newAsyncSliceNamed;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newCounterNamed = tr.c.TestUtils.newCounterNamed;
+ const newCounterSeries = tr.c.TestUtils.newCounterSeries;
+
+ function createSurfaceFlinger(model, vsyncCallback) {
+ if (model.getProcess(2)) {
+ throw new Error('process already exists');
+ }
+
+ const sfProcess = model.getOrCreateProcess(2);
+ const sfThread = sfProcess.getOrCreateThread(2); // main thread, tid = pid
+ sfThread.name = '/system/bin/surfaceflinger';
+
+ // ensure slicegroup has data
+ sfThread.sliceGroup.pushSlice(newSliceEx({
+ title: 'doComposition',
+ start: 8,
+ duration: 2
+ }));
+
+ vsyncCallback(sfProcess);
+ }
+
+ function createSurfaceFlingerWithVsync(model) {
+ createSurfaceFlinger(model, function(sfProcess) {
+ const counter = sfProcess.getOrCreateCounter('android', 'VSYNC');
+ const series = newCounterSeries();
+ for (let i = 0; i <= 10; i++) {
+ series.addCounterSample(i * 10, i % 2);
+ }
+ counter.addSeries(series);
+ });
+ }
+
+ /*
+ * List of customizeModelCallbacks which produce different 80ms frames,
+ * each starting at 10ms, and with a single important slice
+ */
+ const SINGLE_FRAME_CUSTOM_MODELS = [
+ function(model) {
+ // UI thread only
+ const uiThread = model.getOrCreateProcess(120).getOrCreateThread(120);
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 10, duration: 80}));
+
+ model.uiThread = uiThread;
+ },
+
+ function(model) {
+ // RenderThread only
+ const renderThread = model.getOrCreateProcess(120).getOrCreateThread(200);
+ renderThread.name = 'RenderThread';
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'doFrame', start: 10, duration: 80}));
+
+ model.renderThread = renderThread;
+ },
+
+ function(model) {
+ const uiThread = model.getOrCreateProcess(120).getOrCreateThread(120);
+
+ // UI thread time - 19 (from 10 to 29, ignored after)
+ uiThread.asyncSliceGroup.push(
+ newAsyncSliceNamed('deliverInputEvent', 10, 9, uiThread, uiThread));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 20, duration: 110}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'draw', start: 20, duration: 108}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'Record View#draw()', start: 20, duration: 8}));
+
+ // RenderThread time - 61 (from 29 to 90, ignored after)
+ const renderThread = model.getOrCreateProcess(120).getOrCreateThread(200);
+ renderThread.name = 'RenderThread';
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'DrawFrame', start: 29, duration: 70}));
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'syncFrameState', start: 29, duration: 1}));
+ renderThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'queueBuffer', start: 89, duration: 1}));
+
+ model.uiThread = uiThread;
+ model.renderThread = renderThread;
+ }
+ ];
+
+ test('getThreads', function() {
+ SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) {
+ const model = tr.c.TestUtils.newModel(customizeModelCallback);
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+ assert.strictEqual(helper.apps[0].uiThread, model.uiThread);
+ assert.strictEqual(helper.apps[0].renderThread, model.renderThread);
+ });
+ });
+
+ test('iterateImportantSlices', function() {
+ SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) {
+ const model = tr.c.TestUtils.newModel(customizeModelCallback);
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+
+ let seen = 0;
+ helper.iterateImportantSlices(function(importantSlice) {
+ assert.isTrue(importantSlice instanceof tr.model.Slice);
+ seen++;
+ });
+ assert.strictEqual(seen, 1);
+ });
+ });
+
+ test('getFrames', function() {
+ SINGLE_FRAME_CUSTOM_MODELS.forEach(function(customizeModelCallback) {
+ const model = tr.c.TestUtils.newModel(customizeModelCallback);
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+ assert.strictEqual(helper.apps.length, 1);
+
+ const frames = helper.apps[0].getFrames();
+ assert.strictEqual(frames.length, 1);
+ assert.closeTo(frames[0].totalDuration, 80, 1e-5);
+
+ assert.closeTo(frames[0].start, 10, 1e-5);
+ assert.closeTo(frames[0].end, 90, 1e-5);
+ });
+ });
+
+ test('surfaceFlingerVsyncs', function() {
+ const model = tr.c.TestUtils.newModel(createSurfaceFlingerWithVsync);
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+ assert.isTrue(helper.surfaceFlinger.hasVsyncs);
+
+ // test querying the vsyncs
+ assert.closeTo(helper.surfaceFlinger.getFrameKickoff(5), 0, 1e-5);
+ assert.closeTo(helper.surfaceFlinger.getFrameDeadline(95), 100, 1e-5);
+
+ assert.closeTo(helper.surfaceFlinger.getFrameKickoff(10), 10, 1e-5);
+ assert.closeTo(helper.surfaceFlinger.getFrameDeadline(90), 100, 1e-5);
+
+ // test undefined behavior outside of vsyncs.
+ assert.isUndefined(helper.surfaceFlinger.getFrameKickoff(-5));
+ assert.isUndefined(helper.surfaceFlinger.getFrameDeadline(105));
+ });
+
+ test('surfaceFlingerShiftedVsyncs', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ createSurfaceFlinger(model, function(sfProcess) {
+ const appSeries = newCounterSeries();
+ const sfSeries = newCounterSeries();
+ for (let i = 0; i <= 10; i++) {
+ // SF vsync is 4ms after app
+ appSeries.addCounterSample(i * 16, i % 2);
+ sfSeries.addCounterSample(i * 16 + 4, i % 2);
+ }
+ sfProcess.getOrCreateCounter('android', 'VSYNC-sf')
+ .addSeries(sfSeries);
+ sfProcess.getOrCreateCounter('android', 'VSYNC-app')
+ .addSeries(appSeries);
+ });
+ });
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+ assert.isTrue(helper.surfaceFlinger.hasVsyncs);
+
+ // test querying the vsyncs - Frames should have 20ms window
+ assert.closeTo(helper.surfaceFlinger.getFrameKickoff(0), 0, 1e-5);
+ assert.closeTo(helper.surfaceFlinger.getFrameDeadline(0), 20, 1e-5);
+
+ assert.closeTo(helper.surfaceFlinger.getFrameKickoff(16), 16, 1e-5);
+ assert.closeTo(helper.surfaceFlinger.getFrameDeadline(16), 36, 1e-5);
+
+ // test undefined behavior outside of vsyncs.
+ assert.isUndefined(helper.surfaceFlinger.getFrameKickoff(-5));
+ assert.isUndefined(helper.surfaceFlinger.getFrameDeadline(165));
+ });
+
+ test('frameVsyncInterop', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ // app - 3 good, 3 bad frames
+ const uiThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 1, duration: 8}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 10, duration: 8}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 20, duration: 8}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 31, duration: 11}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 45, duration: 6}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 60, duration: 20}));
+
+ // surface flinger - vsync every 10ms
+ createSurfaceFlingerWithVsync(model);
+ });
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+
+ const frames = helper.apps[0].getFrames();
+ assert.strictEqual(frames.length, 6);
+ for (let i = 0; i < 6; i++) {
+ const shouldMissDeadline = i >= 3;
+ const missedDeadline = frames[i].args.deadline < frames[i].end;
+ assert.strictEqual(shouldMissDeadline, missedDeadline);
+ }
+ });
+
+ test('appInputs', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(120);
+ const uiThread = process.getOrCreateThread(120);
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 20, duration: 4}));
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 40, duration: 4}));
+
+ const counter = process.getOrCreateCounter('android', 'aq:pending:foo');
+ const series = newCounterSeries();
+ series.addCounterSample(10, 1);
+ series.addCounterSample(20, 0);
+ series.addCounterSample(30, 1);
+ series.addCounterSample(40, 2);
+ series.addCounterSample(50, 0);
+ counter.addSeries(series);
+ });
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+ assert.strictEqual(helper.apps.length, 1);
+
+ const inputSamples = helper.apps[0].getInputSamples();
+ assert.strictEqual(inputSamples.length, 3);
+ assert.strictEqual(inputSamples[0].timestamp, 10);
+ assert.strictEqual(inputSamples[1].timestamp, 30);
+ assert.strictEqual(inputSamples[2].timestamp, 40);
+ });
+
+ test('appAnimations', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(120);
+ const uiThread = process.getOrCreateThread(120);
+ uiThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'performTraversals', start: 10, duration: 10}));
+ uiThread.asyncSliceGroup.push(newAsyncSliceNamed('animator:foo', 0, 10,
+ uiThread, uiThread));
+ });
+ const helper = model.getOrCreateHelper(AndroidModelHelper);
+ assert.strictEqual(helper.apps.length, 1);
+
+ const animations = helper.apps[0].getAnimationAsyncSlices();
+ assert.strictEqual(animations.length, 1);
+ assert.strictEqual(animations[0].start, 0);
+ assert.strictEqual(animations[0].end, 10);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/android_surface_flinger.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/android_surface_flinger.html
new file mode 100644
index 00000000000..7595be059b3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/android_surface_flinger.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Class for representing SurfaceFlinger process and its Vsyncs.
+ */
+tr.exportTo('tr.model.helpers', function() {
+ const findLowIndexInSortedArray = tr.b.findLowIndexInSortedArray;
+
+ const VSYNC_SF_NAME = 'android.VSYNC-sf';
+ const VSYNC_APP_NAME = 'android.VSYNC-app';
+ const VSYNC_FALLBACK_NAME = 'android.VSYNC';
+
+ // when sampling vsync, push samples back by this much to ensure
+ // frame start samples *between* vsyncs
+ const TIMESTAMP_FUDGE_MS = 0.01;
+
+ function getVsyncTimestamps(process, counterName) {
+ let vsync = process.counters[counterName];
+ if (!vsync) {
+ vsync = process.counters[VSYNC_FALLBACK_NAME];
+ }
+
+ if (vsync && vsync.numSeries === 1 && vsync.numSamples > 1) {
+ return vsync.series[0].timestamps;
+ }
+ return undefined;
+ }
+
+ /**
+ * Model for SurfaceFlinger specific data.
+ * @constructor
+ */
+ function AndroidSurfaceFlinger(process, thread) {
+ this.process = process;
+ this.thread = thread;
+
+ this.appVsync_ = undefined;
+ this.sfVsync_ = undefined;
+
+ this.appVsyncTimestamps_ = getVsyncTimestamps(process, VSYNC_APP_NAME);
+ this.sfVsyncTimestamps_ = getVsyncTimestamps(process, VSYNC_SF_NAME);
+
+ // separation of vsync of app vs sf - assume app has at least window of 5ms
+ this.deadlineDelayMs_ =
+ this.appVsyncTimestamps_ !== this.sfVsyncTimestamps_ ?
+ 5 : TIMESTAMP_FUDGE_MS;
+ }
+
+ AndroidSurfaceFlinger.createForProcessIfPossible = function(process) {
+ const mainThread = process.getThread(process.pid);
+
+ // newer versions - main thread, lowercase name, preceeding forward slash
+ if (mainThread && mainThread.name &&
+ /surfaceflinger/.test(mainThread.name)) {
+ return new AndroidSurfaceFlinger(process, mainThread);
+ }
+
+ // older versions - another thread is named SurfaceFlinger
+ const primaryThreads = process.findAllThreadsNamed('SurfaceFlinger');
+ if (primaryThreads.length === 1) {
+ return new AndroidSurfaceFlinger(process, primaryThreads[0]);
+ }
+ return undefined;
+ };
+
+ AndroidSurfaceFlinger.prototype = {
+ get hasVsyncs() {
+ return !!this.appVsyncTimestamps_ && !!this.sfVsyncTimestamps_;
+ },
+
+ getFrameKickoff(timestamp) {
+ if (!this.hasVsyncs) {
+ throw new Error('cannot query vsync info without vsyncs');
+ }
+
+ const firstGreaterIndex =
+ findLowIndexInSortedArray(this.appVsyncTimestamps_,
+ function(x) { return x; },
+ timestamp + TIMESTAMP_FUDGE_MS);
+
+ if (firstGreaterIndex < 1) return undefined;
+ return this.appVsyncTimestamps_[firstGreaterIndex - 1];
+ },
+
+ getFrameDeadline(timestamp) {
+ if (!this.hasVsyncs) {
+ throw new Error('cannot query vsync info without vsyncs');
+ }
+
+ const firstGreaterIndex =
+ findLowIndexInSortedArray(this.sfVsyncTimestamps_,
+ function(x) { return x; },
+ timestamp + this.deadlineDelayMs_);
+ if (firstGreaterIndex >= this.sfVsyncTimestamps_.length) {
+ return undefined;
+ }
+ return this.sfVsyncTimestamps_[firstGreaterIndex];
+ }
+ };
+
+ return {
+ AndroidSurfaceFlinger,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_browser_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_browser_helper.html
new file mode 100644
index 00000000000..9c9cb6e473b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_browser_helper.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_process_helper.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Utilities for accessing trace data about the Chrome browser.
+ */
+tr.exportTo('tr.model.helpers', function() {
+ function ChromeBrowserHelper(modelHelper, process) {
+ tr.model.helpers.ChromeProcessHelper.call(this, modelHelper, process);
+ this.mainThread_ = process.findAtMostOneThreadNamed('CrBrowserMain');
+ if (!process.name) {
+ process.name = ChromeBrowserHelper.PROCESS_NAME;
+ }
+ }
+
+ ChromeBrowserHelper.PROCESS_NAME = 'Browser';
+
+ ChromeBrowserHelper.isBrowserProcess = function(process) {
+ return !!process.findAtMostOneThreadNamed('CrBrowserMain');
+ };
+
+ ChromeBrowserHelper.prototype = {
+ __proto__: tr.model.helpers.ChromeProcessHelper.prototype,
+
+ // TODO(petrcermak): Pass browser name in a metadata event (see
+ // crbug.com/605088).
+ get browserName() {
+ const hasInProcessRendererThread = this.process.findAllThreadsNamed(
+ 'Chrome_InProcRendererThread').length > 0;
+ return hasInProcessRendererThread ? 'webview' : 'chrome';
+ },
+
+ get mainThread() {
+ return this.mainThread_;
+ },
+
+ get rendererHelpers() {
+ return this.modelHelper.rendererHelpers;
+ },
+
+ getLoadingEventsInRange(rangeOfInterest) {
+ return this.getAllAsyncSlicesMatching(function(slice) {
+ return slice.title.indexOf('WebContentsImpl Loading') === 0 &&
+ rangeOfInterest.intersectsExplicitRangeInclusive(
+ slice.start, slice.end);
+ });
+ },
+
+ getCommitProvisionalLoadEventsInRange(rangeOfInterest) {
+ return this.getAllAsyncSlicesMatching(function(slice) {
+ return slice.title === 'RenderFrameImpl::didCommitProvisionalLoad' &&
+ rangeOfInterest.intersectsExplicitRangeInclusive(
+ slice.start, slice.end);
+ });
+ },
+
+ get hasLatencyEvents() {
+ let hasLatency = false;
+ for (const thread of this.modelHelper.model.getAllThreads()) {
+ for (const event of thread.getDescendantEvents()) {
+ if (!event.isTopLevel) continue;
+ if (!(event instanceof tr.e.cc.InputLatencyAsyncSlice)) {
+ continue;
+ }
+ hasLatency = true;
+ }
+ }
+ return hasLatency;
+ },
+
+ getLatencyEventsInRange(rangeOfInterest) {
+ return this.getAllAsyncSlicesMatching(function(slice) {
+ return (slice.title.indexOf('InputLatency') === 0) &&
+ rangeOfInterest.intersectsExplicitRangeInclusive(
+ slice.start, slice.end);
+ });
+ },
+
+ getAllAsyncSlicesMatching(pred, opt_this) {
+ const events = [];
+ this.iterAllThreads(function(thread) {
+ for (const slice of thread.getDescendantEvents()) {
+ if (pred.call(opt_this, slice)) {
+ events.push(slice);
+ }
+ }
+ });
+ return events;
+ },
+
+ iterAllThreads(func, opt_this) {
+ for (const thread of Object.values(this.process.threads)) {
+ func.call(opt_this, thread);
+ }
+
+ for (const rendererHelper of Object.values(this.rendererHelpers)) {
+ const rendererProcess = rendererHelper.process;
+ for (const thread of Object.values(rendererProcess.threads)) {
+ func.call(opt_this, thread);
+ }
+ }
+ }
+ };
+
+ return {
+ ChromeBrowserHelper,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_browser_helper_test.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_browser_helper_test.html
new file mode 100644
index 00000000000..a53f31127ea
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_browser_helper_test.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/helpers/chrome_browser_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES;
+
+ function getRange(min, max) {
+ const range = new tr.b.math.Range();
+ range.min = min;
+ range.max = max;
+ return range;
+ }
+
+ test('LoadingEvent', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { });
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ tr.e.chrome.ChromeTestUtils.addLoadingEvent(model, {start: 1, end: 10});
+ assert.strictEqual(1, modelHelper.browserHelper.getLoadingEventsInRange(
+ getRange(0, 100)).length);
+ });
+
+ test('ProvisionalLoadEvent', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { });
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ tr.e.chrome.ChromeTestUtils.addCommitLoadEvent(model, {start: 1, end: 10});
+ assert.strictEqual(1,
+ modelHelper.browserHelper.getCommitProvisionalLoadEventsInRange(
+ getRange(0, 100)).length);
+ });
+
+ test('LatencyEvent', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { });
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ tr.e.chrome.ChromeTestUtils.addInputEvent(
+ model, INPUT_TYPE.UNKNOWN, {start: 1, end: 10});
+ assert.strictEqual(1, modelHelper.browserHelper.getLatencyEventsInRange(
+ getRange(0, 100)).length);
+ });
+
+ test('browserName_chrome', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { });
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ assert.strictEqual(modelHelper.browserHelper.browserName, 'chrome');
+ });
+
+ test('browserName_webview', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function() { });
+ model.browserProcess.getOrCreateThread(42).name =
+ 'Chrome_InProcRendererThread';
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ assert.strictEqual(modelHelper.browserHelper.browserName, 'webview');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_gpu_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_gpu_helper.html
new file mode 100644
index 00000000000..cf3857f1636
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_gpu_helper.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/model/helpers/chrome_process_helper.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Utilities for accessing the Chrome GPU Process.
+ */
+tr.exportTo('tr.model.helpers', function() {
+ // TODO(charliea): This method should probably throw if this isn't a Chrome
+ // GPU process.
+ function ChromeGpuHelper(modelHelper, process) {
+ tr.model.helpers.ChromeProcessHelper.call(this, modelHelper, process);
+ if (!process.name) {
+ process.name = ChromeGpuHelper.PROCESS_NAME;
+ }
+ }
+
+ ChromeGpuHelper.PROCESS_NAME = 'GPU Process';
+
+ ChromeGpuHelper.isGpuProcess = function(process) {
+ // In some Android builds the GPU thread is not in a separate process.
+ if (process.findAtMostOneThreadNamed('CrBrowserMain') ||
+ process.findAtMostOneThreadNamed('CrRendererMain')) {
+ return false;
+ }
+
+ // On Android, there can sometimes be GPU processes with multiple main
+ // threads. We need to recognize those processes as GPU processes.
+ return process.findAllThreadsNamed('CrGpuMain').length > 0;
+ };
+
+ ChromeGpuHelper.prototype = {
+ __proto__: tr.model.helpers.ChromeProcessHelper.prototype
+ };
+
+ return {
+ ChromeGpuHelper,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_gpu_helper_test.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_gpu_helper_test.html
new file mode 100644
index 00000000000..11f3be603b0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_gpu_helper_test.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_gpu_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ChromeGpuHelper = tr.model.helpers.ChromeGpuHelper;
+
+ test('constructor_doesntThrowIfMultipleMainThreads', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1).getOrCreateThread(1).name = 'CrGpuMain';
+ model.getOrCreateProcess(1).getOrCreateThread(2).name = 'CrGpuMain';
+ });
+
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ new ChromeGpuHelper(modelHelper, model.getOrCreateProcess(1));
+ });
+
+ test('constructor_doesntThrowIfNoMainThread', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1);
+ });
+
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ new ChromeGpuHelper(modelHelper, model.getOrCreateProcess(1));
+ });
+
+ test('constructor_namesProcessIfUnnamed', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1);
+ });
+
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ new ChromeGpuHelper(modelHelper, model.getOrCreateProcess(1));
+ assert.strictEqual(model.getOrCreateProcess(1).name, 'GPU Process');
+ });
+
+ test('constructor_doesntNameProcessIfNamed', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1).name = 'Example process name';
+ });
+
+ const modelHelper = model.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+
+ new ChromeGpuHelper(modelHelper, model.getOrCreateProcess(1));
+ assert.strictEqual(
+ model.getOrCreateProcess(1).name, 'Example process name');
+ });
+
+ test('isGpuProcess_falseIfNoMainThread', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1);
+ });
+
+ assert.isFalse(ChromeGpuHelper.isGpuProcess(model.getOrCreateProcess(1)));
+ });
+
+ test('isGpuProcess', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1).getOrCreateThread(1).name = 'CrGpuMain';
+ });
+
+ assert.isTrue(ChromeGpuHelper.isGpuProcess(model.getOrCreateProcess(1)));
+ });
+
+ test('isGpuProcess_trueIfMultipleMainThreads', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1).getOrCreateThread(1).name = 'CrGpuMain';
+ model.getOrCreateProcess(1).getOrCreateThread(2).name = 'CrGpuMain';
+ });
+
+ assert.isTrue(ChromeGpuHelper.isGpuProcess(model.getOrCreateProcess(1)));
+ });
+
+ test('isGpuProcess_falseIfBrowserProcess', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1).getOrCreateThread(1).name = 'CrGpuMain';
+ model.getOrCreateProcess(1).getOrCreateThread(2).name = 'CrBrowserMain';
+ });
+
+ assert.isFalse(ChromeGpuHelper.isGpuProcess(model.getOrCreateProcess(1)));
+ });
+
+ test('isGpuProcess_falseIfRendererProcess', function() {
+ const model = tr.c.TestUtils.newModel(model => {
+ model.getOrCreateProcess(1).getOrCreateThread(1).name = 'CrGpuMain';
+ model.getOrCreateProcess(1).getOrCreateThread(2).name = 'CrRendererMain';
+ });
+
+ assert.isFalse(ChromeGpuHelper.isGpuProcess(model.getOrCreateProcess(1)));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_model_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_model_helper.html
new file mode 100644
index 00000000000..156a96b1304
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_model_helper.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_browser_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_gpu_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_renderer_helper.html">
+<link rel="import" href="/tracing/model/helpers/telemetry_helper.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Utilities for accessing trace data about the Chrome browser.
+ */
+tr.exportTo('tr.model.helpers', function() {
+ function findChromeBrowserProcesses(model) {
+ return model.getAllProcesses(
+ tr.model.helpers.ChromeBrowserHelper.isBrowserProcess);
+ }
+
+ function findChromeRenderProcesses(model) {
+ return model.getAllProcesses(
+ tr.model.helpers.ChromeRendererHelper.isRenderProcess);
+ }
+
+ function findChromeGpuProcess(model) {
+ const gpuProcesses = model.getAllProcesses(
+ tr.model.helpers.ChromeGpuHelper.isGpuProcess);
+ if (gpuProcesses.length !== 1) return undefined;
+ return gpuProcesses[0];
+ }
+
+ function findTelemetrySurfaceFlingerProcess(model) {
+ const surfaceFlingerProcesses = model.getAllProcesses(
+ process => (process.name === 'SurfaceFlinger'));
+ if (surfaceFlingerProcesses.length !== 1) return undefined;
+ return surfaceFlingerProcesses[0];
+ }
+
+ function ChromeModelHelper(model) {
+ this.model_ = model;
+
+ // Find browserHelpers.
+ const browserProcesses = findChromeBrowserProcesses(model);
+ this.browserHelpers_ = browserProcesses.map(
+ p => new tr.model.helpers.ChromeBrowserHelper(this, p));
+
+ // Find gpuHelper.
+ const gpuProcess = findChromeGpuProcess(model);
+ if (gpuProcess) {
+ this.gpuHelper_ = new tr.model.helpers.ChromeGpuHelper(
+ this, gpuProcess);
+ } else {
+ this.gpuHelper_ = undefined;
+ }
+
+ // Find rendererHelpers.
+ const rendererProcesses_ = findChromeRenderProcesses(model);
+
+ this.rendererHelpers_ = {};
+ rendererProcesses_.forEach(function(renderProcess) {
+ const rendererHelper = new tr.model.helpers.ChromeRendererHelper(
+ this, renderProcess);
+ this.rendererHelpers_[rendererHelper.pid] = rendererHelper;
+ }, this);
+
+ this.surfaceFlingerProcess_ = findTelemetrySurfaceFlingerProcess(model);
+
+ this.chromeBounds_ = undefined;
+
+ this.telemetryHelper_ = new tr.model.helpers.TelemetryHelper(this);
+ }
+
+ ChromeModelHelper.guid = tr.b.GUID.allocateSimple();
+
+ ChromeModelHelper.supportsModel = function(model) {
+ if (findChromeBrowserProcesses(model).length) return true;
+ if (findChromeRenderProcesses(model).length) return true;
+ return false;
+ };
+
+ ChromeModelHelper.prototype = {
+ get pid() {
+ throw new Error('woah');
+ },
+
+ get process() {
+ throw new Error('woah');
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ // TODO: Make all users of ChromeModelHelper support multiple browsers and
+ // remove this getter (see #2119).
+ get browserProcess() {
+ if (this.browserHelper === undefined) return undefined;
+ return this.browserHelper.process;
+ },
+
+ // TODO: Make all users of ChromeModelHelper support multiple browsers and
+ // remove this getter (see #2119).
+ get browserHelper() {
+ return this.browserHelpers_[0];
+ },
+
+ get browserHelpers() {
+ return this.browserHelpers_;
+ },
+
+ get gpuHelper() {
+ return this.gpuHelper_;
+ },
+
+ get rendererHelpers() {
+ return this.rendererHelpers_;
+ },
+
+ get surfaceFlingerProcess() {
+ return this.surfaceFlingerProcess_;
+ },
+
+ /**
+ * Returns the minimal bounds that includes all Chrome-related slices, or
+ * undefined if no such minimal bounds could be established. This relies on
+ * the assumption that all Chrome-relevant traces are bounded by the browser
+ * process.
+ */
+ get chromeBounds() {
+ if (!this.chromeBounds_) {
+ this.chromeBounds_ = new tr.b.math.Range();
+ for (const browserHelper of Object.values(this.browserHelpers)) {
+ this.chromeBounds_.addRange(browserHelper.process.bounds);
+ }
+
+ for (const rendererHelper of Object.values(this.rendererHelpers)) {
+ this.chromeBounds_.addRange(rendererHelper.process.bounds);
+ }
+
+ if (this.gpuHelper) {
+ this.chromeBounds_.addRange(this.gpuHelper.process.bounds);
+ }
+ }
+
+ if (this.chromeBounds_.isEmpty) {
+ return undefined;
+ }
+
+ return this.chromeBounds_;
+ },
+
+ get telemetryHelper() {
+ return this.telemetryHelper_;
+ }
+ };
+
+ return {
+ ChromeModelHelper,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_model_helper_test.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_model_helper_test.html
new file mode 100644
index 00000000000..e347cd883ba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_model_helper_test.html
@@ -0,0 +1,238 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/helpers/chrome_browser_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx;
+
+ test('getLatencyData', function() {
+ const m = tr.e.chrome.ChromeTestUtils.newChromeModel(function(m) {
+ m.browserMain.asyncSliceGroup.push(newAsyncSliceEx({
+ title: 'InputLatency::GestureScrollUpdate',
+ cat: 'benchmark',
+ start: 0,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ args: {
+ data: {
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT: {'time': 0},
+ INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT: {time: 10}
+ }
+ }
+ }));
+ });
+
+ const modelHelper = m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ const latencyEvents = modelHelper.browserHelper.getLatencyEventsInRange(
+ m.bounds);
+ assert.strictEqual(latencyEvents.length, 1);
+ });
+
+ test('getFrametime', function() {
+ let frameTs;
+ const events = [];
+ // Browser process 3507
+ events.push({'cat': '__metadata', 'pid': 3507, 'tid': 3507, 'ts': 0, 'ph': 'M', 'name': 'thread_name', 'args': {'name': 'CrBrowserMain'}}); // @suppress longLineCheck
+
+ // Renderer process 3508
+ events.push({'cat': '__metadata', 'pid': 3508, 'tid': 3508, 'ts': 0, 'ph': 'M', 'name': 'thread_name', 'args': {'name': 'CrRendererMain'}}); // @suppress longLineCheck
+ // Compositor thread 3510
+ events.push({'cat': '__metadata', 'pid': 3508, 'tid': 3510, 'ts': 0, 'ph': 'M', 'name': 'thread_name', 'args': {'name': 'Compositor'}}); // @suppress longLineCheck
+
+ // Renderer process 3509
+ events.push({'cat': '__metadata', 'pid': 3509, 'tid': 3509, 'ts': 0, 'ph': 'M', 'name': 'thread_name', 'args': {'name': 'CrRendererMain'}}); // @suppress longLineCheck
+
+ // Compositor thread 3511
+ events.push({'cat': '__metadata', 'pid': 3509, 'tid': 3511, 'ts': 0, 'ph': 'M', 'name': 'thread_name', 'args': {'name': 'Compositor'}}); // @suppress longLineCheck
+
+ frameTs = 0;
+ // Add impl rendering stats for browser process 3507
+ for (let i = 0; i < 10; i++) {
+ events.push({'cat': 'benchmark', 'pid': 3507, 'tid': 3507, 'ts': frameTs, 'ph': 'i', 'name': 'BenchmarkInstrumentation::ImplThreadRenderingStats', 's': 't'}); // @suppress longLineCheck
+ frameTs += 16000 + 1000 * (i % 2);
+ }
+
+ frameTs = 0;
+ // Add main rendering stats for renderer process 3508
+ for (let i = 0; i < 10; i++) {
+ events.push({'cat': 'benchmark', 'pid': 3508, 'tid': 3508, 'ts': frameTs, 'ph': 'i', 'name': 'BenchmarkInstrumentation::MainThreadRenderingStats', 's': 't'}); // @suppress longLineCheck
+ frameTs += 16000 + 1000 * (i % 2);
+ }
+ events.push({'cat': 'benchmark', 'pid': 3508, 'tid': 3510, 'ts': 1600, 'ph': 'i', 'name': 'KeepAlive', 's': 't'}); // @suppress longLineCheck
+
+ frameTs = 0;
+ // Add impl and main rendering stats for renderer process 3509
+ for (let i = 0; i < 10; i++) {
+ events.push({'cat': 'benchmark', 'pid': 3509, 'tid': 3511, 'ts': frameTs, 'ph': 'i', 'name': 'BenchmarkInstrumentation::ImplThreadRenderingStats', 's': 't'}); // @suppress longLineCheck
+ events.push({'cat': 'benchmark', 'pid': 3509, 'tid': 3509, 'ts': frameTs, 'ph': 'i', 'name': 'BenchmarkInstrumentation::MainThreadRenderingStats', 's': 't'}); // @suppress longLineCheck
+ frameTs += 16000 + 1000 * (i % 2);
+ }
+
+ const m = tr.c.TestUtils.newModelWithEvents([events]);
+ const modelHelper = m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+
+ // Testing browser impl and main rendering stats.
+ let frameEvents = modelHelper.browserHelper.getFrameEventsInRange(
+ tr.model.helpers.IMPL_FRAMETIME_TYPE, m.bounds);
+ let frametimeData = tr.model.helpers.getFrametimeDataFromEvents(
+ frameEvents);
+ assert.strictEqual(frametimeData.length, 9);
+ for (let i = 0; i < frametimeData.length; i++) {
+ assert.strictEqual(frametimeData[i].frametime, 16 + i % 2);
+ }
+ // No main rendering stats.
+ frameEvents = modelHelper.browserHelper.getFrameEventsInRange(
+ tr.model.helpers.MAIN_FRAMETIME_TYPE, m.bounds);
+ assert.strictEqual(frameEvents.length, 0);
+
+
+ // Testing renderer 3508 impl and main rendering stats.
+ frameEvents = modelHelper.rendererHelpers[3508].getFrameEventsInRange(
+ tr.model.helpers.MAIN_FRAMETIME_TYPE, m.bounds);
+ frametimeData = tr.model.helpers.getFrametimeDataFromEvents(frameEvents);
+ assert.strictEqual(frametimeData.length, 9);
+ for (let i = 0; i < frametimeData.length; i++) {
+ assert.strictEqual(frametimeData[i].frametime, 16 + i % 2);
+ }
+
+ // No impl rendering stats.
+ frameEvents = modelHelper.rendererHelpers[3508].getFrameEventsInRange(
+ tr.model.helpers.IMPL_FRAMETIME_TYPE, m.bounds);
+ assert.strictEqual(frameEvents.length, 0);
+
+
+ // Testing renderer 3509 impl and main rendering stats.
+ frameEvents = modelHelper.rendererHelpers[3509].getFrameEventsInRange(
+ tr.model.helpers.IMPL_FRAMETIME_TYPE, m.bounds);
+ frametimeData = tr.model.helpers.getFrametimeDataFromEvents(frameEvents);
+ assert.strictEqual(frametimeData.length, 9);
+ for (let i = 0; i < frametimeData.length; i++) {
+ assert.strictEqual(frametimeData[i].frametime, 16 + i % 2);
+ }
+
+ frameEvents = modelHelper.rendererHelpers[3509].getFrameEventsInRange(
+ tr.model.helpers.MAIN_FRAMETIME_TYPE, m.bounds);
+ frametimeData = tr.model.helpers.getFrametimeDataFromEvents(frameEvents);
+ assert.strictEqual(frametimeData.length, 9);
+ for (let i = 0; i < frametimeData.length; i++) {
+ assert.strictEqual(frametimeData[i].frametime, 16 + i % 2);
+ }
+ });
+
+ test('multipleBrowsers', function() {
+ const m = tr.c.TestUtils.newModel(function(model) {
+ const browserProcess1 = model.getOrCreateProcess(1);
+ browserProcess1.getOrCreateThread(2).name = 'CrBrowserMain';
+
+ const browserProcess2 = model.getOrCreateProcess(3);
+ browserProcess2.getOrCreateThread(4);
+ browserProcess2.getOrCreateThread(5).name = 'CrBrowserMain';
+
+ const nonBrowserProcess = model.getOrCreateProcess(6);
+ nonBrowserProcess.getOrCreateThread(7);
+
+ const browserProcess3 = model.getOrCreateProcess(8);
+ browserProcess3.getOrCreateThread(9).name = 'CrBrowserMain';
+ browserProcess3.getOrCreateThread(10);
+ });
+
+ const modelHelper = m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ const browserHelpers = modelHelper.browserHelpers;
+
+ // Check that the correct processes were marked as Chrome browser processes.
+ assert.sameMembers(browserHelpers.map(h => h.process.pid), [1, 3, 8]);
+
+ // Check that the browser helpers have the correct structure.
+ browserHelpers.forEach(function(helper) {
+ assert.instanceOf(helper, tr.model.helpers.ChromeBrowserHelper);
+ assert.strictEqual(helper.modelHelper, modelHelper);
+ });
+ });
+
+ test('chromeBounds_considersAllChromeProcesses', function() {
+ const model1 = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ model.browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: 100,
+ }));
+ model.rendererMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 200,
+ duration: 100,
+ }));
+ });
+
+ const model2 = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ const gpuProcess = model.getOrCreateProcess(42);
+ const gpuMainThread = gpuProcess.getOrCreateThread(1);
+ gpuMainThread.name = 'CrGpuMain';
+ gpuMainThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: 50,
+ }));
+ model.browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 100,
+ duration: 50,
+ }));
+ });
+
+ const modelHelper1 =
+ model1.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ assert.strictEqual(modelHelper1.chromeBounds.min, 0);
+ assert.strictEqual(modelHelper1.chromeBounds.max, 300);
+
+ const modelHelper2 =
+ model2.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ assert.strictEqual(modelHelper2.chromeBounds.min, 0);
+ assert.strictEqual(modelHelper2.chromeBounds.max, 150);
+ });
+
+ test('chromeBounds_onlyConsidersChromeProcesses', function() {
+ const model = tr.e.chrome.ChromeTestUtils.newChromeModel(function(model) {
+ model.browserMain.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 0,
+ duration: 100,
+ }));
+
+ // The bounds of this process should not be included in chrome bounds.
+ const nonChromeProcess = model.getOrCreateProcess(1234);
+ nonChromeProcess.name = 'Telemetry';
+ const nonChromeThread = nonChromeProcess.getOrCreateThread(1);
+ nonChromeThread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: 200,
+ duration: 100,
+ }));
+ });
+
+ const modelHelper =
+ model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ assert.strictEqual(modelHelper.chromeBounds.min, 0);
+ assert.strictEqual(modelHelper.chromeBounds.max, 100);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_process_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_process_helper.html
new file mode 100644
index 00000000000..208a4131c34
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_process_helper.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Utilities for accessing trace data about the Chrome browser.
+ */
+tr.exportTo('tr.model.helpers', function() {
+ const MAIN_FRAMETIME_TYPE = 'main_frametime_type';
+ const IMPL_FRAMETIME_TYPE = 'impl_frametime_type';
+
+ const MAIN_RENDERING_STATS =
+ 'BenchmarkInstrumentation::MainThreadRenderingStats';
+ const IMPL_RENDERING_STATS =
+ 'BenchmarkInstrumentation::ImplThreadRenderingStats';
+
+
+ function getSlicesIntersectingRange(rangeOfInterest, slices) {
+ const slicesInFilterRange = [];
+ for (let i = 0; i < slices.length; i++) {
+ const slice = slices[i];
+ if (rangeOfInterest.intersectsExplicitRangeInclusive(
+ slice.start, slice.end)) {
+ slicesInFilterRange.push(slice);
+ }
+ }
+ return slicesInFilterRange;
+ }
+
+
+ function ChromeProcessHelper(modelHelper, process) {
+ this.modelHelper = modelHelper;
+ this.process = process;
+ this.telemetryInternalRanges_ = undefined;
+ }
+
+ ChromeProcessHelper.prototype = {
+ get pid() {
+ return this.process.pid;
+ },
+
+ isTelemetryInternalEvent(slice) {
+ if (this.telemetryInternalRanges_ === undefined) {
+ this.findTelemetryInternalRanges_();
+ }
+ for (const range of this.telemetryInternalRanges_) {
+ if (range.containsExplicitRangeInclusive(slice.start, slice.end)) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ findTelemetryInternalRanges_() {
+ this.telemetryInternalRanges_ = [];
+ let start = 0;
+ for (const thread of Object.values(this.process.threads)) {
+ for (const slice of thread.asyncSliceGroup.getDescendantEvents()) {
+ if (/^telemetry\.internal\..*\.start$/.test(slice.title)) {
+ start = slice.start;
+ } else if (/^telemetry\.internal\..*\.end$/.test(slice.title) &&
+ start !== undefined) {
+ this.telemetryInternalRanges_.push(
+ tr.b.math.Range.fromExplicitRange(start, slice.end));
+ start = undefined;
+ }
+ }
+ }
+ },
+
+ getFrameEventsInRange(frametimeType, range) {
+ const titleToGet = (frametimeType === MAIN_FRAMETIME_TYPE ?
+ MAIN_RENDERING_STATS : IMPL_RENDERING_STATS);
+
+ const frameEvents = [];
+ for (const event of this.process.getDescendantEvents()) {
+ if (event.title === titleToGet) {
+ if (range.intersectsExplicitRangeInclusive(event.start, event.end)) {
+ frameEvents.push(event);
+ }
+ }
+ }
+
+ frameEvents.sort(function(a, b) {return a.start - b.start;});
+ return frameEvents;
+ }
+ };
+
+ function getFrametimeDataFromEvents(frameEvents) {
+ const frametimeData = [];
+ for (let i = 1; i < frameEvents.length; i++) {
+ const diff = frameEvents[i].start - frameEvents[i - 1].start;
+ frametimeData.push({
+ 'x': frameEvents[i].start,
+ 'frametime': diff
+ });
+ }
+ return frametimeData;
+ }
+
+ return {
+ ChromeProcessHelper,
+
+ MAIN_FRAMETIME_TYPE,
+ IMPL_FRAMETIME_TYPE,
+ MAIN_RENDERING_STATS,
+ IMPL_RENDERING_STATS,
+
+ getSlicesIntersectingRange,
+ getFrametimeDataFromEvents,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_renderer_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_renderer_helper.html
new file mode 100644
index 00000000000..a10e7eaff01
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_renderer_helper.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/helpers/chrome_process_helper.html">
+<link rel="import" href="/tracing/model/helpers/chrome_thread_helper.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.helpers', function() {
+ const ChromeThreadHelper = tr.model.helpers.ChromeThreadHelper;
+
+ function ChromeRendererHelper(modelHelper, process) {
+ tr.model.helpers.ChromeProcessHelper.call(this, modelHelper, process);
+ this.mainThread_ = process.findAtMostOneThreadNamed('CrRendererMain') ||
+ process.findAtMostOneThreadNamed('Chrome_InProcRendererThread');
+ this.compositorThread_ = process.findAtMostOneThreadNamed('Compositor');
+ this.rasterWorkerThreads_ = process.findAllThreadsMatching(function(t) {
+ if (t.name === undefined) return false;
+ if (t.name.indexOf('CompositorTileWorker') === 0) return true;
+ if (t.name.indexOf('CompositorRasterWorker') === 0) return true;
+ return false;
+ });
+
+ if (!process.name) {
+ process.name = ChromeRendererHelper.PROCESS_NAME;
+ }
+ }
+
+ ChromeRendererHelper.PROCESS_NAME = 'Renderer';
+
+ // Returns true if there is either a main thread or a compositor thread.
+ ChromeRendererHelper.isRenderProcess = function(process) {
+ if (process.findAtMostOneThreadNamed('CrRendererMain')) return true;
+ if (process.findAtMostOneThreadNamed('Compositor')) return true;
+ return false;
+ };
+
+ ChromeRendererHelper.isTracingProcess = function(process) {
+ return process.labels !== undefined &&
+ process.labels.length === 1 &&
+ process.labels[0] === 'chrome://tracing';
+ };
+
+ ChromeRendererHelper.prototype = {
+ __proto__: tr.model.helpers.ChromeProcessHelper.prototype,
+
+ // May be undefined.
+ get mainThread() {
+ return this.mainThread_;
+ },
+
+ // May be undefined.
+ get compositorThread() {
+ return this.compositorThread_;
+ },
+
+ // May be empty.
+ get rasterWorkerThreads() {
+ return this.rasterWorkerThreads_;
+ },
+
+ get isChromeTracingUI() {
+ return ChromeRendererHelper.isTracingProcess(this.process);
+ },
+ };
+
+ return {
+ ChromeRendererHelper,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_renderer_helper_test.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_renderer_helper_test.html
new file mode 100644
index 00000000000..8ca62f70d25
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_renderer_helper_test.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_thread_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_thread_helper.html
new file mode 100644
index 00000000000..39d6159ec60
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_thread_helper.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.helpers', function() {
+ const NET_CATEGORIES = new Set(['net', 'netlog',
+ 'disabled-by-default-netlog', 'disabled-by-default-network']);
+
+ class ChromeThreadHelper {
+ constructor(thread) {
+ this.thread = thread;
+ }
+
+ getNetworkEvents() {
+ const networkEvents = [];
+ for (const slice of this.thread.asyncSliceGroup.slices) {
+ const categories = tr.b.getCategoryParts(slice.category);
+ const isNetEvent = category => NET_CATEGORIES.has(category);
+ if (categories.filter(isNetEvent).length === 0) continue;
+ networkEvents.push(slice);
+ }
+ return networkEvents;
+ }
+ }
+
+ return {
+ ChromeThreadHelper,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_thread_helper_test.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_thread_helper_test.html
new file mode 100644
index 00000000000..49dbdd63938
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/chrome_thread_helper_test.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_thread_helper.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Process = tr.model.Process;
+ const Thread = tr.model.Thread;
+ const ChromeThreadHelper = tr.model.helpers.ChromeThreadHelper;
+
+ test('getNetworkEvents_empty', function() {
+ const model = new tr.Model();
+ const t = new Thread(new tr.model.Process(model, 7), 1);
+ const threadHelper = new ChromeThreadHelper(t);
+ assert.sameDeepMembers([],
+ threadHelper.getNetworkEvents());
+ });
+
+ test('getNetworkEvents_withIrrelevantEvents', function() {
+ const model = new tr.Model();
+ const t = new Thread(new Process(model, 7), 1);
+ const netEvent1 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'netlog',
+ title: 'Generic Network event',
+ start: 100,
+ duration: 200,
+ });
+ t.asyncSliceGroup.push(netEvent1);
+ const netEvent2 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'net',
+ title: 'Generic Network event',
+ start: 101,
+ duration: 201,
+ });
+ t.asyncSliceGroup.push(netEvent2);
+ t.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'irrelevant async event',
+ title: 'irrelevant async event',
+ start: 100,
+ duration: 200,
+ }));
+ t.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ cat: 'irrelevant sync event',
+ title: 'irrelevant sync event',
+ start: 100,
+ duration: 200,
+ }));
+ const threadHelper = new ChromeThreadHelper(t);
+ assert.sameDeepMembers([netEvent1, netEvent2],
+ threadHelper.getNetworkEvents());
+ });
+
+ test('getNetworkEvents_allTypes', function() {
+ const model = new tr.Model();
+ const t = new Thread(new Process(model, 7), 1);
+ const netEvent1 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'netlog',
+ title: 'Generic Network event',
+ start: 100,
+ duration: 200,
+ });
+ t.asyncSliceGroup.push(netEvent1);
+ const netEvent2 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'net',
+ title: 'Generic Network event',
+ start: 101,
+ duration: 201,
+ });
+ t.asyncSliceGroup.push(netEvent2);
+ const netEvent3 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'disabled-by-default-netlog',
+ title: 'Generic Network event',
+ start: 101,
+ duration: 201,
+ });
+ t.asyncSliceGroup.push(netEvent3);
+ const netEvent4 = tr.c.TestUtils.newAsyncSliceEx({
+ cat: 'disabled-by-default-network',
+ title: 'Generic Network event',
+ start: 101,
+ duration: 201,
+ });
+ t.asyncSliceGroup.push(netEvent4);
+ const threadHelper = new ChromeThreadHelper(t);
+ assert.sameDeepMembers([netEvent1, netEvent2, netEvent3, netEvent4],
+ threadHelper.getNetworkEvents());
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html
new file mode 100644
index 00000000000..0c4486f8b54
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/model/helpers/chrome_renderer_helper.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.helpers', function() {
+ const GESTURE_EVENT = 'SyntheticGestureController::running';
+ const IR_REG_EXP = /Interaction\.([^/]+)(\/[^/]*)?$/;
+ const ChromeRendererHelper = tr.model.helpers.ChromeRendererHelper;
+
+ class TelemetryHelper {
+ constructor(modelHelper) {
+ this.modelHelper = modelHelper;
+
+ this.renderersWithIR_ = undefined;
+ this.segments_ = undefined;
+ this.uiSegments_ = undefined;
+ }
+
+ get renderersWithIR() {
+ this.findIRs_();
+ return this.renderersWithIR_;
+ }
+
+ get segments() {
+ this.findIRs_();
+ return this.segments_;
+ }
+
+ get uiSegments() {
+ this.findIRs_();
+ return this.uiSegments_;
+ }
+
+ /**
+ * Finds interesting segments we want to compute metrics in. We use trace
+ * events produced by Telemetry. One drawback of this method is that we
+ * cannot compute the metric from Chrome traces that are not produced by
+ * Telemetry. Alternatively, we could use the user model to detect
+ * interesting segments, like animation segments in the following way:
+ *
+ * const animationSegments = model.userModel.segments.filter(
+ * segment => segment.expectations.find(
+ * ue => ue instanceof tr.model.um.AnimationExpectation));
+ *
+ * However, the user model cannot detect all types of animations, yet. For
+ * more discussion about using test generated interaction records vs the
+ * user model please refer to http://bit.ly/ir-tbmv2. TODO(chiniforooshan):
+ * Improve the user model detection of animations.
+ *
+ * Also, some of the metrics we compute here are not animations specific.
+ */
+ findIRs_() {
+ if (this.segments_ !== undefined) return;
+
+ this.renderersWithIR_ = [];
+ const gestureEvents = [];
+ const interactionRecords = [];
+ const processes = Object.values(this.modelHelper.rendererHelpers)
+ .concat(this.modelHelper.browserHelpers)
+ .map(processHelper => processHelper.process);
+ for (const process of processes) {
+ let foundIR = false;
+ for (const thread of Object.values(process.threads)) {
+ for (const slice of thread.asyncSliceGroup.slices) {
+ if (slice.title === GESTURE_EVENT) {
+ gestureEvents.push(slice);
+ } else if (IR_REG_EXP.test(slice.title)) {
+ interactionRecords.push(slice);
+ foundIR = true;
+ }
+ }
+ }
+ if (foundIR && ChromeRendererHelper.isRenderProcess(process) &&
+ !ChromeRendererHelper.isTracingProcess(process)) {
+ this.renderersWithIR_.push(
+ new ChromeRendererHelper(this.modelHelper, process));
+ }
+ }
+
+ // Convert interaction record slices to segments. If an interaction record
+ // contains a gesture whose time range overlaps with the interaction
+ // record's range, use the gesture's time range.
+ //
+ // The synthetic gesture controller inserts a trace marker to precisely
+ // demarcate when the gesture was running. We check for overlap, not
+ // inclusion, because gesture actions can start/end slightly outside the
+ // telemetry markers on Windows.
+ this.segments_ = [];
+ this.uiSegments_ = [];
+ for (const ir of interactionRecords) {
+ const parts = IR_REG_EXP.exec(ir.title);
+ let gestureEventFound = false;
+ if (parts[1].startsWith('Gesture_')) {
+ for (const gestureEvent of gestureEvents) {
+ if (ir.boundsRange.intersectsRangeInclusive(
+ gestureEvent.boundsRange)) {
+ this.segments_.push(new tr.model.um.Segment(
+ gestureEvent.start, gestureEvent.duration));
+ gestureEventFound = true;
+ break;
+ }
+ }
+ } else if (parts[1].startsWith('ui_')) {
+ this.uiSegments_.push(new tr.model.um.Segment(ir.start, ir.duration));
+ }
+ if (!gestureEventFound) {
+ this.segments_.push(new tr.model.um.Segment(ir.start, ir.duration));
+ }
+ }
+
+ this.segments_.sort((x, y) => x.start - y.start);
+ this.uiSegments_.sort((x, y) => x.start - y.start);
+ }
+ }
+
+ return {
+ TelemetryHelper,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html b/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html
new file mode 100644
index 00000000000..1434603886e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/helpers/telemetry_helper_test.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/helpers/chrome_renderer_helper.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('renderersWithIR', function() {
+ const m = tr.c.TestUtils.newModel((m) => {
+ m.getOrCreateProcess(0).getOrCreateThread(0).name = 'CrBrowserMain';
+
+ // There is no IR in this renderer process.
+ const r1 = m.getOrCreateProcess(1).getOrCreateThread(1);
+ r1.name = 'CrRendererMain';
+ r1.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('AnAsyncSlice', 1, 1));
+
+ // This is the renderer created by Telemetry.
+ const r2 = m.getOrCreateProcess(2).getOrCreateThread(2);
+ r2.name = 'CrRendererMain';
+ r2.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Action', 1, 1));
+
+ // This is the Telemetry process, not a real renderer process.
+ const r3 = m.getOrCreateProcess(3).getOrCreateThread(3);
+ r3.name = 'CrRendererMain';
+ r3.parent.labels = ['chrome://tracing'];
+ r3.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Action', 1, 1));
+ });
+ const modelHelper = m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ const renderers = modelHelper.telemetryHelper.renderersWithIR;
+ assert.strictEqual(1, renderers.length);
+ assert.strictEqual(2, renderers[0].process.pid);
+ });
+
+ test('segments', function() {
+ const m = tr.c.TestUtils.newModel((m) => {
+ // There is no IR in this renderer process.
+ const r = m.getOrCreateProcess(1).getOrCreateThread(1);
+ r.name = 'CrRendererMain';
+ r.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceNamed(
+ 'SyntheticGestureController::running', 6, 2));
+ r.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.A', 1, 1));
+ r.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Gesture_C', 5, 2));
+ r.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.ui_B', 3, 1));
+ });
+
+ // Async slices are:
+ //
+ // 1 2 3 4 5 6 7 8
+ // Interactions <-- A --> <-- B --> <------ C ------>
+ // Gestures <--------------->
+ //
+ // Segments should be: [1, 2], [3, 4], and [6, 8].
+ const modelHelper = m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ const segments = modelHelper.telemetryHelper.segments;
+ assert.strictEqual(3, segments.length);
+ assert.deepEqual([1, 2], [segments[0].start, segments[0].end]);
+ assert.deepEqual([3, 4], [segments[1].start, segments[1].end]);
+ assert.deepEqual([6, 8], [segments[2].start, segments[2].end]);
+ });
+
+ test('uiSegments', function() {
+ const m = tr.c.TestUtils.newModel((m) => {
+ // There is no IR in this renderer process.
+ const r = m.getOrCreateProcess(1).getOrCreateThread(1);
+ r.name = 'CrRendererMain';
+ r.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSliceNamed(
+ 'SyntheticGestureController::running', 6, 2));
+ r.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.A', 1, 1));
+ r.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.Gesture_C', 5, 2));
+ r.asyncSliceGroup.push(
+ tr.c.TestUtils.newAsyncSliceNamed('Interaction.ui_B', 3, 1));
+ });
+
+ // Async slices are:
+ //
+ // 1 2 3 4 5 6 7 8
+ // Interactions <-- A --> <-- B --> <------ C ------>
+ // Gestures <--------------->
+ //
+ // The only UI segment is [3, 4].
+ const modelHelper = m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ const uiSegments = modelHelper.telemetryHelper.uiSegments;
+ assert.strictEqual(1, uiSegments.length);
+ assert.deepEqual([3, 4], [uiSegments[0].start, uiSegments[0].end]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/instant_event.html b/chromium/third_party/catapult/tracing/tracing/model/instant_event.html
new file mode 100644
index 00000000000..d2f6cfbfd0b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/instant_event.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const InstantEventType = {
+ GLOBAL: 1,
+ PROCESS: 2
+ };
+
+ /**
+ * An InstantEvent is a zero-duration event.
+ *
+ * @constructor
+ */
+ function InstantEvent(category, title, colorId, start, args) {
+ tr.model.TimedEvent.call(this, start);
+
+ this.category = category || '';
+ this.title = title;
+ this.colorId = colorId;
+ this.args = args;
+
+ this.type = undefined;
+ }
+
+ InstantEvent.prototype = {
+ __proto__: tr.model.TimedEvent.prototype
+ };
+
+ /**
+ * A GlobalInstantEvent is a zero-duration event that's not tied to any
+ * particular process.
+ *
+ * An example is a trace event that's issued when a new USB device is plugged
+ * into the machine.
+ *
+ * @constructor
+ */
+ function GlobalInstantEvent(category, title, colorId, start, args) {
+ InstantEvent.apply(this, arguments);
+ this.type = InstantEventType.GLOBAL;
+ }
+
+ GlobalInstantEvent.prototype = {
+ __proto__: InstantEvent.prototype,
+ get userFriendlyName() {
+ return 'Global instant event ' + this.title + ' @ ' +
+ tr.b.Unit.byName.timeStampInMs.format(start);
+ }
+ };
+
+ /**
+ * A ProcessInstantEvent is a zero-duration event that's tied to a
+ * particular process.
+ *
+ * An example is a trace event that's issued when a kill signal is received.
+ *
+ * @constructor
+ */
+ function ProcessInstantEvent(category, title, colorId, start, args) {
+ InstantEvent.apply(this, arguments);
+ this.type = InstantEventType.PROCESS;
+ }
+
+ ProcessInstantEvent.prototype = {
+ __proto__: InstantEvent.prototype,
+
+ get userFriendlyName() {
+ return 'Process-level instant event ' + this.title + ' @ ' +
+ tr.b.Unit.byName.timeStampInMs.format(start);
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ InstantEvent,
+ {
+ name: 'instantEvent',
+ pluralName: 'instantEvents'
+ });
+
+ return {
+ GlobalInstantEvent,
+ ProcessInstantEvent,
+
+ InstantEventType,
+ InstantEvent,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/interaction_record_test.html b/chromium/third_party/catapult/tracing/tracing/model/interaction_record_test.html
new file mode 100644
index 00000000000..8380bcb0849
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/interaction_record_test.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/user_model/stub_expectation.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TestUtils = tr.c.TestUtils;
+ const CompoundEventSelectionState = tr.model.CompoundEventSelectionState;
+
+ function createModel(opt_customizeModelCallback) {
+ return TestUtils.newModel(function(model) {
+ model.p1 = model.getOrCreateProcess(1);
+ model.t2 = model.p1.getOrCreateThread(2);
+
+ model.s1 = model.t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
+ title: 'a', start: 10, end: 20
+ }));
+ model.s2 = model.t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
+ title: 'b', start: 20, end: 30
+ }));
+
+ model.ir1 = new tr.model.um.StubExpectation({
+ parentModel: model,
+ start: 100, end: 200,
+ typeName: 'Response',
+ normalizedEfficiency: 1.,
+ normalizedUserComfort: 0.0
+ });
+ model.userModel.expectations.push(model.ir1);
+ model.ir1.associatedEvents.push(model.s1);
+ model.ir1.associatedEvents.push(model.s2);
+
+ if (opt_customizeModelCallback) {
+ opt_customizeModelCallback(model);
+ }
+ });
+ }
+ test('notSelected', function() {
+ const model = createModel();
+
+ const sel = new tr.model.EventSet();
+
+ assert.strictEqual(CompoundEventSelectionState.NOT_SELECTED,
+ model.ir1.computeCompoundEvenSelectionState(sel));
+ });
+
+ test('directSelected', function() {
+ const model = createModel();
+
+ const sel = new tr.model.EventSet();
+ sel.push(model.ir1);
+
+ assert.strictEqual(CompoundEventSelectionState.EVENT_SELECTED,
+ model.ir1.computeCompoundEvenSelectionState(sel));
+ });
+
+ test('directAndSomeAssociatedSelected', function() {
+ const model = createModel();
+
+ const sel = new tr.model.EventSet();
+ sel.push(model.ir1);
+ sel.push(model.s1);
+
+ assert.strictEqual(
+ CompoundEventSelectionState.EVENT_AND_SOME_ASSOCIATED_SELECTED,
+ model.ir1.computeCompoundEvenSelectionState(sel));
+ });
+
+ test('allAssociatedEventsSelected', function() {
+ const model = createModel();
+
+ const sel = new tr.model.EventSet();
+ sel.push(model.s1);
+ sel.push(model.s2);
+
+ assert.strictEqual(
+ CompoundEventSelectionState.ALL_ASSOCIATED_EVENTS_SELECTED,
+ model.ir1.computeCompoundEvenSelectionState(sel));
+ });
+
+ test('directAndAllAssociated', function() {
+ const model = createModel();
+
+ const sel = new tr.model.EventSet();
+ sel.push(model.ir1);
+ sel.push(model.s1);
+ sel.push(model.s2);
+
+ assert.strictEqual(
+ CompoundEventSelectionState.EVENT_AND_ALL_ASSOCIATED_SELECTED,
+ model.ir1.computeCompoundEvenSelectionState(sel));
+ });
+
+ test('stableId', function() {
+ const model = TestUtils.newModel();
+
+ const ir1 = TestUtils.newInteractionRecord(model, 0, 10);
+ const ir2 = TestUtils.newInteractionRecord(model, 10, 10);
+ const ir3 = TestUtils.newInteractionRecord(model, 20, 10);
+
+ assert.strictEqual('UserExpectation.' + ir1.guid, ir1.stableId);
+ assert.strictEqual('UserExpectation.' + ir2.guid, ir2.stableId);
+ assert.strictEqual('UserExpectation.' + ir3.guid, ir3.stableId);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/ir_coverage.html b/chromium/third_party/catapult/tracing/tracing/model/ir_coverage.html
new file mode 100644
index 00000000000..2b8264ac276
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/ir_coverage.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ function getAssociatedEvents(irs) {
+ const allAssociatedEvents = new tr.model.EventSet();
+ irs.forEach(function(ir) {
+ ir.associatedEvents.forEach(function(event) {
+ // FlowEvents don't have parentContainers or cpuDurations, and it's
+ // annoying to highlight them.
+ if (event instanceof tr.model.FlowEvent) return;
+ allAssociatedEvents.push(event);
+ });
+ });
+ return allAssociatedEvents;
+ }
+
+ function getUnassociatedEvents(model, associatedEvents) {
+ const unassociatedEvents = new tr.model.EventSet();
+ // The set of unassociated events contains only events that are not in
+ // the set of associated events.
+ // Only add event to the set of unassociated events if it is not in
+ // the set of associated events.
+ for (const proc of model.getAllProcesses()) {
+ for (const thread of Object.values(proc.threads)) {
+ for (const event of thread.sliceGroup.getDescendantEvents()) {
+ if (!associatedEvents.contains(event)) {
+ unassociatedEvents.push(event);
+ }
+ }
+ }
+ }
+ return unassociatedEvents;
+ }
+
+ function getTotalCpuDuration(events) {
+ let cpuMs = 0;
+ events.forEach(function(event) {
+ // Add up events' cpu self time if they have any.
+ if (event.cpuSelfTime) {
+ cpuMs += event.cpuSelfTime;
+ }
+ });
+ return cpuMs;
+ }
+
+ function getIRCoverageFromModel(model) {
+ const associatedEvents = getAssociatedEvents(model.userModel.expectations);
+
+ if (!associatedEvents.length) return undefined;
+
+ const unassociatedEvents = getUnassociatedEvents(
+ model, associatedEvents);
+
+ const associatedCpuMs = getTotalCpuDuration(associatedEvents);
+ const unassociatedCpuMs = getTotalCpuDuration(unassociatedEvents);
+
+ const totalEventCount = associatedEvents.length + unassociatedEvents.length;
+ const totalCpuMs = associatedCpuMs + unassociatedCpuMs;
+ let coveredEventsCpuTimeRatio = undefined;
+ if (totalCpuMs !== 0) {
+ coveredEventsCpuTimeRatio = associatedCpuMs / totalCpuMs;
+ }
+
+ return {
+ associatedEventsCount: associatedEvents.length,
+ unassociatedEventsCount: unassociatedEvents.length,
+ associatedEventsCpuTimeMs: associatedCpuMs,
+ unassociatedEventsCpuTimeMs: unassociatedCpuMs,
+ coveredEventsCountRatio: associatedEvents.length / totalEventCount,
+ coveredEventsCpuTimeRatio
+ };
+ }
+
+ return {
+ getIRCoverageFromModel,
+ getAssociatedEvents,
+ getUnassociatedEvents,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/ir_coverage_test.html b/chromium/third_party/catapult/tracing/tracing/model/ir_coverage_test.html
new file mode 100644
index 00000000000..4a3b471ae6f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/ir_coverage_test.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/ir_coverage.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ function createModel() {
+ return tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ const thread = process.getOrCreateThread(2);
+ const s0 = thread.sliceGroup.pushSlice(newSliceEx(
+ {title: 's0', start: 0.0, duration: 1.0}));
+ s0.isTopLevel = true;
+ const unassociatedEvent = thread.sliceGroup.pushSlice(newSliceEx(
+ {title: 's1', start: 6.0, duration: 1.0}));
+ unassociatedEvent.isTopLevel = true;
+ const s2 = thread.sliceGroup.pushSlice(newSliceEx(
+ {title: 's2', start: 2.0, duration: 1.0}));
+ s2.isTopLevel = true;
+ const f0 = tr.c.TestUtils.newFlowEventEx({
+ title: 'test1',
+ start: 0,
+ end: 10,
+ startSlice: s0,
+ endSlice: s2,
+ id: '0x100'
+ });
+ model.flowEvents.push(f0);
+ const as1 = tr.c.TestUtils.newAsyncSliceEx({
+ title: 'InputLatency::GestureTap',
+ cat: 'benchmark,latencyInfo',
+ start: 2,
+ end: 10,
+ id: '0x100',
+ isTopLevel: true,
+ startThread: thread
+ });
+ thread.asyncSliceGroup.push(as1);
+ const ir = new tr.model.um.StubExpectation(
+ {parentModel: model, start: 0, duration: 7});
+ ir.associatedEvents.push(as1);
+ ir.associatedEvents.push(s0);
+ ir.associatedEvents.push(s2);
+ ir.associatedEvents.push(f0);
+ model.userModel.expectations.push(ir);
+ });
+ }
+
+ test('computeCoverage', function() {
+ const model = createModel();
+ for (const event of model.getDescendantEvents()) {
+ if (event.title === 's0' || event.title === 's2') {
+ event.cpuSelfTime = 0.4;
+ } else if (event.title === 's1') {
+ event.cpuSelfTime = 0.8;
+ }
+ }
+
+ const coverage = tr.model.getIRCoverageFromModel(model);
+ assert.strictEqual(3, coverage.associatedEventsCount);
+ assert.strictEqual(1, coverage.unassociatedEventsCount);
+ assert.closeTo(0.75, coverage.coveredEventsCountRatio, 1e-3);
+ assert.closeTo(0.8, coverage.associatedEventsCpuTimeMs, 1e-3);
+ assert.closeTo(0.8, coverage.unassociatedEventsCpuTimeMs, 1e-3);
+ assert.closeTo(0.5, coverage.coveredEventsCpuTimeRatio, 1e-3);
+ });
+
+ test('zeroCPU', function() {
+ const model = createModel();
+ const coverage = tr.model.getIRCoverageFromModel(model);
+ assert.strictEqual(3, coverage.associatedEventsCount);
+ assert.strictEqual(1, coverage.unassociatedEventsCount);
+ assert.closeTo(0.75, coverage.coveredEventsCountRatio, 1e-3);
+ assert.closeTo(0.0, coverage.associatedEventsCpuTimeMs, 1e-3);
+ assert.closeTo(0.0, coverage.unassociatedEventsCpuTimeMs, 1e-3);
+ assert.strictEqual(undefined, coverage.coveredEventsCpuTimeRatio, 1e-3);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/kernel.html b/chromium/third_party/catapult/tracing/tracing/model/kernel.html
new file mode 100644
index 00000000000..834a91eea06
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/kernel.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/cpu.html">
+<link rel="import" href="/tracing/model/process_base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Process class.
+ */
+tr.exportTo('tr.model', function() {
+ const Cpu = tr.model.Cpu;
+ const ProcessBase = tr.model.ProcessBase;
+
+ /**
+ * The Kernel represents kernel-level objects in the model.
+ * @constructor
+ */
+ function Kernel(model) {
+ ProcessBase.call(this, model);
+
+ this.cpus = {};
+ this.softwareMeasuredCpuCount_ = undefined;
+ }
+
+ /**
+ * Comparison between kernels is pretty meaningless.
+ */
+ Kernel.compare = function(x, y) {
+ return 0;
+ };
+
+ Kernel.prototype = {
+ __proto__: ProcessBase.prototype,
+
+ compareTo(that) {
+ return Kernel.compare(this, that);
+ },
+
+ get userFriendlyName() {
+ return 'Kernel';
+ },
+
+ get userFriendlyDetails() {
+ return 'Kernel';
+ },
+
+ get stableId() {
+ return 'Kernel';
+ },
+
+ /**
+ * @return {Cpu} Gets a specific Cpu or creates one if
+ * it does not exist.
+ */
+ getOrCreateCpu(cpuNumber) {
+ if (!this.cpus[cpuNumber]) {
+ this.cpus[cpuNumber] = new Cpu(this, cpuNumber);
+ }
+ return this.cpus[cpuNumber];
+ },
+
+ get softwareMeasuredCpuCount() {
+ return this.softwareMeasuredCpuCount_;
+ },
+
+ set softwareMeasuredCpuCount(softwareMeasuredCpuCount) {
+ if (this.softwareMeasuredCpuCount_ !== undefined &&
+ this.softwareMeasuredCpuCount_ !== softwareMeasuredCpuCount) {
+ throw new Error(
+ 'Cannot change the softwareMeasuredCpuCount once it is set');
+ }
+
+ this.softwareMeasuredCpuCount_ = softwareMeasuredCpuCount;
+ },
+
+ /**
+ * Estimates how many cpus are in the system, for use in system load
+ * estimation.
+ *
+ * If kernel trace was provided, uses that data. Otherwise, uses the
+ * software measured cpu count.
+ */
+ get bestGuessAtCpuCount() {
+ const realCpuCount = Object.keys(this.cpus).length;
+ if (realCpuCount !== 0) {
+ return realCpuCount;
+ }
+ return this.softwareMeasuredCpuCount;
+ },
+
+ updateBounds() {
+ ProcessBase.prototype.updateBounds.call(this);
+ for (const cpuNumber in this.cpus) {
+ const cpu = this.cpus[cpuNumber];
+ cpu.updateBounds();
+ this.bounds.addRange(cpu.bounds);
+ }
+ },
+
+ createSubSlices() {
+ ProcessBase.prototype.createSubSlices.call(this);
+ for (const cpuNumber in this.cpus) {
+ const cpu = this.cpus[cpuNumber];
+ cpu.createSubSlices();
+ }
+ },
+
+ addCategoriesToDict(categoriesDict) {
+ ProcessBase.prototype.addCategoriesToDict.call(this, categoriesDict);
+ for (const cpuNumber in this.cpus) {
+ this.cpus[cpuNumber].addCategoriesToDict(categoriesDict);
+ }
+ },
+
+ getSettingsKey() {
+ return 'kernel';
+ },
+
+ * childEventContainers() {
+ yield* ProcessBase.prototype.childEventContainers.call(this);
+ yield* Object.values(this.cpus);
+ },
+ };
+
+ return {
+ Kernel,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/kernel_test.html b/chromium/third_party/catapult/tracing/tracing/model/kernel_test.html
new file mode 100644
index 00000000000..ffe145adef6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/kernel_test.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/kernel.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function newModel(events, callback) {
+ return tr.c.TestUtils.newModelWithEvents([events], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback: callback
+ });
+ }
+
+ test('bestGuessAtCpuCountWithNoData', function() {
+ const m = newModel([]);
+ assert.isUndefined(m.kernel.bestGuessAtCpuCount);
+ });
+
+ test('bestGuessAtCpuCountWithCpuData', function() {
+ const m = newModel([], function(m) {
+ const c1 = m.kernel.getOrCreateCpu(1);
+ const c2 = m.kernel.getOrCreateCpu(2);
+ });
+ assert.strictEqual(m.kernel.bestGuessAtCpuCount, 2);
+ });
+
+ test('bestGuessAtCpuCountWithSoftwareCpuCount', function() {
+ const m = newModel([], function(m) {
+ m.kernel.softwareMeasuredCpuCount = 2;
+ });
+ assert.strictEqual(m.kernel.bestGuessAtCpuCount, 2);
+ });
+
+ test('kernelStableId', function() {
+ const model = newModel([]);
+ assert.strictEqual(model.kernel.stableId, 'Kernel');
+ });
+
+ test('kernelTimeShifting', function() {
+ const m = newModel([]);
+ const ctr1 = m.kernel.getOrCreateCounter('cat', 'ctr1');
+ const series1 = new tr.model.CounterSeries('a', 0);
+ series1.addCounterSample(100, 5);
+ series1.addCounterSample(200, 5);
+ ctr1.addSeries(series1);
+
+ const ctr2 = m.kernel.getOrCreateCpu(1).getOrCreateCounter('cat', 'ctr2');
+ const series2 = new tr.model.CounterSeries('b', 0);
+ series2.addCounterSample(300, 5);
+ series2.addCounterSample(400, 5);
+ ctr2.addSeries(series2);
+
+ m.kernel.shiftTimestampsForward(2);
+
+ assert.strictEqual(ctr1.series[0].samples[0].timestamp, 102);
+ assert.strictEqual(ctr1.series[0].samples[1].timestamp, 202);
+
+ assert.strictEqual(ctr2.series[0].samples[0].timestamp, 302);
+ assert.strictEqual(ctr2.series[0].samples[1].timestamp, 402);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/location.html b/chromium/third_party/catapult/tracing/tracing/model/location.html
new file mode 100644
index 00000000000..b6403ae4c3f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/location.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * YComponent is a class that handles storing the stableId and the percentage
+ * offset in the y direction of all tracks within a specific viewX and viewY
+ * coordinate.
+ * @constructor
+ */
+ function YComponent(stableId, yPercentOffset) {
+ this.stableId = stableId;
+ this.yPercentOffset = yPercentOffset;
+ }
+
+ YComponent.prototype = {
+ toDict() {
+ return {
+ stableId: this.stableId,
+ yPercentOffset: this.yPercentOffset
+ };
+ }
+ };
+
+ /**
+ * Location is a class that represents a spatial location on the timeline
+ * that is specified by percent offsets within tracks rather than specific
+ * points.
+ *
+ * @constructor
+ */
+ function Location(xWorld, yComponents) {
+ this.xWorld_ = xWorld;
+ this.yComponents_ = yComponents;
+ }
+
+ /**
+ * Returns a new Location given by x and y coordinates with respect to
+ * the timeline's drawing canvas.
+ */
+ Location.fromViewCoordinates = function(viewport, viewX, viewY) {
+ const dt = viewport.currentDisplayTransform;
+ const xWorld = dt.xViewToWorld(viewX);
+ const yComponents = [];
+
+ // Since we're given coordinates within the timeline canvas, we need to
+ // convert them to document coordinates to get the element.
+ let elem = document.elementFromPoint(
+ viewX + viewport.modelTrackContainer.canvas.offsetLeft,
+ viewY + viewport.modelTrackContainer.canvas.offsetTop);
+ // Build yComponents by calculating percentage offset with respect to
+ // each parent track.
+ while (elem instanceof tr.ui.tracks.Track) {
+ if (elem.eventContainer) {
+ const boundRect = elem.getBoundingClientRect();
+ const yPercentOffset = (viewY - boundRect.top) / boundRect.height;
+ yComponents.push(
+ new YComponent(elem.eventContainer.stableId, yPercentOffset));
+ }
+ elem = elem.parentElement;
+ }
+
+ if (yComponents.length === 0) return;
+ return new Location(xWorld, yComponents);
+ };
+
+ Location.fromStableIdAndTimestamp = function(viewport, stableId, ts) {
+ const xWorld = ts;
+ const yComponents = [];
+
+ // The y components' percentage offsets will be calculated with respect to
+ // the boundingRect's top of containing track.
+ const containerToTrack = viewport.containerToTrackMap;
+ let elem = containerToTrack.getTrackByStableId(stableId);
+ if (!elem) return;
+
+ const firstY = elem.getBoundingClientRect().top;
+ while (elem instanceof tr.ui.tracks.Track) {
+ if (elem.eventContainer) {
+ const boundRect = elem.getBoundingClientRect();
+ const yPercentOffset = (firstY - boundRect.top) / boundRect.height;
+ yComponents.push(
+ new YComponent(elem.eventContainer.stableId, yPercentOffset));
+ }
+ elem = elem.parentElement;
+ }
+
+ if (yComponents.length === 0) return;
+ return new Location(xWorld, yComponents);
+ };
+
+ Location.prototype = {
+
+ get xWorld() {
+ return this.xWorld_;
+ },
+
+ /**
+ * Returns the first valid containing track based on the
+ * internal yComponents.
+ */
+ getContainingTrack(viewport) {
+ const containerToTrack = viewport.containerToTrackMap;
+ for (const i in this.yComponents_) {
+ const yComponent = this.yComponents_[i];
+ const track = containerToTrack.getTrackByStableId(yComponent.stableId);
+ if (track !== undefined) return track;
+ }
+ },
+
+ /**
+ * Calculates and returns x and y coordinates of the current location with
+ * respect to the timeline's canvas.
+ */
+ toViewCoordinates(viewport) {
+ const dt = viewport.currentDisplayTransform;
+ const containerToTrack = viewport.containerToTrackMap;
+ const viewX = dt.xWorldToView(this.xWorld_);
+
+ let viewY = -1;
+ for (const index in this.yComponents_) {
+ const yComponent = this.yComponents_[index];
+ const track = containerToTrack.getTrackByStableId(yComponent.stableId);
+ if (track !== undefined) {
+ const boundRect = track.getBoundingClientRect();
+ viewY = yComponent.yPercentOffset * boundRect.height + boundRect.top;
+ break;
+ }
+ }
+
+ return {
+ viewX,
+ viewY
+ };
+ },
+
+ toDict() {
+ return {
+ xWorld: this.xWorld_,
+ yComponents: this.yComponents_
+ };
+ }
+ };
+
+ return {
+ Location,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/memory_allocator_dump.html b/chromium/third_party/catapult/tracing/tracing/model/memory_allocator_dump.html
new file mode 100644
index 00000000000..0a723b8a9d9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/memory_allocator_dump.html
@@ -0,0 +1,221 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the MemoryAllocatorDump class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * @constructor
+ */
+ function MemoryAllocatorDump(containerMemoryDump, fullName, opt_guid) {
+ this.fullName = fullName;
+ this.parent = undefined;
+ this.children = [];
+
+ // String -> Scalar.
+ this.numerics = {};
+
+ // String -> string.
+ this.diagnostics = {};
+
+ // The associated container memory dump.
+ this.containerMemoryDump = containerMemoryDump;
+
+ // Ownership relationship between memory allocator dumps.
+ this.owns = undefined;
+ this.ownedBy = [];
+
+ // Map from sibling dumps (other children of this dump's parent) to the
+ // proportion of this dump's size which they (or their descendants) own.
+ this.ownedBySiblingSizes = new Map();
+
+ // Retention relationship between memory allocator dumps.
+ this.retains = [];
+ this.retainedBy = [];
+
+ // Weak memory allocator dumps are removed from the model after import in
+ // tr.model.GlobalMemoryDump.removeWeakDumps(). See
+ // base::trace_event::MemoryAllocatorDump::Flags::WEAK in the Chromium
+ // codebase.
+ this.weak = false;
+
+ // A list of information about the memory allocator dump (e.g. about how
+ // its fields were calculated). Each item should be an object with
+ // a mandatory 'type' property and type-specific extra arguments (see
+ // MemoryAllocatorDumpInfoType).
+ this.infos = [];
+
+ // For debugging purposes.
+ this.guid = opt_guid;
+ }
+
+ /**
+ * Size numeric names. Please refer to the Memory Dump Graph Metric
+ * Calculation design document for more details (https://goo.gl/fKg0dt).
+ */
+ MemoryAllocatorDump.SIZE_NUMERIC_NAME = 'size';
+ MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME = 'effective_size';
+ MemoryAllocatorDump.RESIDENT_SIZE_NUMERIC_NAME = 'resident_size';
+ MemoryAllocatorDump.DISPLAYED_SIZE_NUMERIC_NAME =
+ MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME;
+
+ MemoryAllocatorDump.prototype = {
+ get name() {
+ return this.fullName.substring(this.fullName.lastIndexOf('/') + 1);
+ },
+
+ get quantifiedName() {
+ return '\'' + this.fullName + '\' in ' +
+ this.containerMemoryDump.containerName;
+ },
+
+ getDescendantDumpByFullName(fullName) {
+ return this.containerMemoryDump.getMemoryAllocatorDumpByFullName(
+ this.fullName + '/' + fullName);
+ },
+
+ isDescendantOf(otherDump) {
+ if (this === otherDump) return true;
+ if (this.parent === undefined) return false;
+ return this.parent.isDescendantOf(otherDump);
+ },
+
+ addNumeric(name, numeric) {
+ if (!(numeric instanceof tr.b.Scalar)) {
+ throw new Error('Numeric value must be an instance of Scalar.');
+ }
+ if (name in this.numerics) {
+ throw new Error('Duplicate numeric name: ' + name + '.');
+ }
+ this.numerics[name] = numeric;
+ },
+
+ addDiagnostic(name, text) {
+ if (typeof text !== 'string') {
+ throw new Error('Diagnostic text must be a string.');
+ }
+ if (name in this.diagnostics) {
+ throw new Error('Duplicate diagnostic name: ' + name + '.');
+ }
+ this.diagnostics[name] = text;
+ },
+
+ aggregateNumericsRecursively(opt_model) {
+ const numericNames = new Set();
+
+ // Aggregate descendants's numerics recursively and gather children's
+ // numeric names.
+ this.children.forEach(function(child) {
+ child.aggregateNumericsRecursively(opt_model);
+ for (const [item, value] of Object.entries(child.numerics)) {
+ numericNames.add(item, value);
+ }
+ }, this);
+
+ // Aggregate children's numerics.
+ numericNames.forEach(function(numericName) {
+ if (numericName === MemoryAllocatorDump.SIZE_NUMERIC_NAME ||
+ numericName === MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME ||
+ this.numerics[numericName] !== undefined) {
+ // Don't aggregate size and effective size numerics. These are
+ // calculated in GlobalMemoryDump.prototype.calculateSizes() and
+ // GlobalMemoryDump.prototype.calculateEffectiveSizes respectively.
+ // Also don't aggregate numerics that the parent already has.
+ return;
+ }
+
+ this.numerics[numericName] = MemoryAllocatorDump.aggregateNumerics(
+ this.children.map(function(child) {
+ return child.numerics[numericName];
+ }), opt_model);
+ }, this);
+ }
+ };
+
+ // TODO(petrcermak): Consider moving this to tr.v.Histogram.
+ MemoryAllocatorDump.aggregateNumerics = function(numerics, opt_model) {
+ let shouldLogWarning = !!opt_model;
+ let aggregatedUnit = undefined;
+ let aggregatedValue = 0;
+
+ // Aggregate the units and sum up the values of the numerics.
+ numerics.forEach(function(numeric) {
+ if (numeric === undefined) return;
+
+ const unit = numeric.unit;
+ if (aggregatedUnit === undefined) {
+ aggregatedUnit = unit;
+ } else if (aggregatedUnit !== unit) {
+ if (shouldLogWarning) {
+ opt_model.importWarning({
+ type: 'numeric_parse_error',
+ message: 'Multiple units provided for numeric: \'' +
+ aggregatedUnit.unitName + '\' and \'' + unit.unitName + '\'.'
+ });
+ shouldLogWarning = false; // Don't log multiple warnings.
+ }
+ // Use the most generic unit when the numerics don't agree (best
+ // effort).
+ aggregatedUnit = tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+ }
+
+ aggregatedValue += numeric.value;
+ }, this);
+
+ if (aggregatedUnit === undefined) return undefined;
+
+ return new tr.b.Scalar(aggregatedUnit, aggregatedValue);
+ };
+
+ /**
+ * @constructor
+ */
+ function MemoryAllocatorDumpLink(source, target, opt_importance) {
+ this.source = source;
+ this.target = target;
+ this.importance = opt_importance;
+ this.size = undefined;
+ }
+
+ /**
+ * Types of size numeric information.
+ *
+ * @enum
+ */
+ const MemoryAllocatorDumpInfoType = {
+ // The provided size of a MemoryAllocatorDump was less than the aggregated
+ // size of its children.
+ //
+ // Mandatory extra args:
+ // * providedSize: The inconsistent provided size.
+ // * dependencySize: The aggregated size of the children.
+ PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN: 0,
+
+ // The provided size of a MemoryAllocatorDump was less than the size of its
+ // largest owner.
+ //
+ // Mandatory extra args:
+ // * providedSize: The inconsistent provided size.
+ // * dependencySize: The size of the largest owner.
+ PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER: 1
+ };
+
+ return {
+ MemoryAllocatorDump,
+ MemoryAllocatorDumpLink,
+ MemoryAllocatorDumpInfoType,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/memory_allocator_dump_test.html b/chromium/third_party/catapult/tracing/tracing/model/memory_allocator_dump_test.html
new file mode 100644
index 00000000000..7cc100dce25
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/memory_allocator_dump_test.html
@@ -0,0 +1,221 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ContainerMemoryDump = tr.model.ContainerMemoryDump;
+ const MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+ const MemoryAllocatorDumpLink = tr.model.MemoryAllocatorDumpLink;
+ const Scalar = tr.b.Scalar;
+ const unitlessNumber_smallerIsBetter =
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+ const sizeInBytes = tr.b.Unit.byName.sizeInBytes;
+ const powerInWatts = tr.b.Unit.byName.powerInWatts;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const addChildDump = tr.model.MemoryDumpTestUtils.addChildDump;
+ const checkDumpNumericsAndDiagnostics =
+ tr.model.MemoryDumpTestUtils.checkDumpNumericsAndDiagnostics;
+
+ test('memoryAllocatorDump_instantiate', function() {
+ const containerDump = new ContainerMemoryDump(42);
+ containerDump.containerName = 'super dump';
+ const dump = new MemoryAllocatorDump(containerDump, 'v8/objects/object7');
+
+ assert.strictEqual(dump.name, 'object7');
+ assert.strictEqual(dump.fullName, 'v8/objects/object7');
+ assert.strictEqual(dump.containerMemoryDump, containerDump);
+ assert.strictEqual(
+ dump.quantifiedName, '\'v8/objects/object7\' in super dump');
+ });
+
+ test('memoryAllocatorDumps_aggregateNumericsRecursively', function() {
+ const md = new ContainerMemoryDump(42);
+
+ const oilpanDump = newAllocatorDump(md, 'oilpan', {numerics: {
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 7)
+ }});
+
+ addChildDump(oilpanDump, 'bucket1', {numerics: {
+ size: 512,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 3),
+ inner_size: 256,
+ outer_size: 1024
+ }});
+
+ const oilpanBucket2Dump = addChildDump(oilpanDump, 'bucket2');
+
+ const oilpanBucket2StringsDump = addChildDump(
+ oilpanBucket2Dump, 'strings', {numerics: {
+ size: 512,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 4),
+ inner_size: 512,
+ outer_size: 2048
+ }});
+
+ oilpanDump.aggregateNumericsRecursively();
+
+ // oilpan has *some* numerics aggregated.
+ checkDumpNumericsAndDiagnostics(oilpanDump, {
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 7),
+ inner_size: 768,
+ outer_size: 3072
+ }, {});
+
+ // oilpan/bucket2 has *all* numerics aggregated (except for size).
+ checkDumpNumericsAndDiagnostics(oilpanBucket2Dump, {
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 4),
+ inner_size: 512,
+ outer_size: 2048
+ }, {});
+
+ // oilpan/bucket2/strings has *no* numerics aggregated.
+ checkDumpNumericsAndDiagnostics(oilpanBucket2StringsDump, {
+ size: 512,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 4),
+ inner_size: 512,
+ outer_size: 2048
+ }, {});
+ });
+
+ test('memoryAllocatorDump_aggregateNumerics', function() {
+ function checkAggregateNumerics(numerics, expectedValue, expectedUnit,
+ opt_expectedWarningCount) {
+ function checkResult(result) {
+ if (expectedValue === undefined) {
+ assert.isUndefined(result);
+ assert.isUndefined(expectedUnit); // Test sanity check.
+ } else {
+ assert.instanceOf(result, Scalar);
+ assert.strictEqual(result.value, expectedValue);
+ assert.strictEqual(result.unit, expectedUnit);
+ }
+ }
+
+ // Without model parameter.
+ const result1 = MemoryAllocatorDump.aggregateNumerics(numerics);
+ checkResult(result1);
+
+ // With model parameter.
+ const mockModel = {
+ warnings: [],
+ importWarning(warning) {
+ this.warnings.push(warning);
+ }
+ };
+ const result2 = MemoryAllocatorDump.aggregateNumerics(
+ numerics, mockModel);
+ checkResult(result2);
+ assert.lengthOf(mockModel.warnings, opt_expectedWarningCount || 0);
+ }
+
+ // No defined numerics.
+ checkAggregateNumerics([], undefined);
+ checkAggregateNumerics([undefined], undefined);
+ checkAggregateNumerics([undefined, undefined], undefined);
+
+ // Consistent units.
+ checkAggregateNumerics(
+ [new Scalar(unitlessNumber_smallerIsBetter, 10)],
+ 10, unitlessNumber_smallerIsBetter);
+ checkAggregateNumerics(
+ [new Scalar(sizeInBytes, 10),
+ new Scalar(sizeInBytes, 20),
+ new Scalar(sizeInBytes, 40)],
+ 70, sizeInBytes);
+ checkAggregateNumerics(
+ [undefined,
+ new Scalar(sizeInBytes, 16),
+ undefined,
+ new Scalar(sizeInBytes, 32),
+ undefined],
+ 48, sizeInBytes);
+
+ // Inconsistent units.
+ checkAggregateNumerics(
+ [new Scalar(sizeInBytes, 10),
+ new Scalar(powerInWatts, 20)],
+ 30, unitlessNumber_smallerIsBetter, 1 /* opt_expectedWarningCount */);
+ checkAggregateNumerics(
+ [undefined,
+ new Scalar(powerInWatts, 16),
+ undefined,
+ new Scalar(unitlessNumber_smallerIsBetter, 32),
+ undefined,
+ new Scalar(sizeInBytes, 64),
+ undefined],
+ 112, unitlessNumber_smallerIsBetter, 1 /* opt_expectedWarningCount */);
+ });
+
+ test('memoryAllocatorDumps_isDescendantOf', function() {
+ const md = new ContainerMemoryDump(42);
+
+ const v8Dump = new MemoryAllocatorDump(md, 'v8');
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps');
+ const v8ObjectsDump = addChildDump(v8Dump, 'objects');
+ const v8Object1Dump = addChildDump(v8ObjectsDump, 'obj1');
+ const v8Object2Dump = addChildDump(v8ObjectsDump, 'obj2');
+
+ const oilpanDump = new MemoryAllocatorDump(md, 'oilpan');
+
+ assert.isTrue(v8Dump.isDescendantOf(v8Dump));
+ assert.isTrue(v8HeapsDump.isDescendantOf(v8Dump));
+ assert.isTrue(v8ObjectsDump.isDescendantOf(v8Dump));
+ assert.isTrue(v8Object1Dump.isDescendantOf(v8Dump));
+ assert.isTrue(v8Object2Dump.isDescendantOf(v8Dump));
+ assert.isTrue(v8ObjectsDump.isDescendantOf(v8ObjectsDump));
+ assert.isTrue(v8Object1Dump.isDescendantOf(v8ObjectsDump));
+ assert.isTrue(v8Object2Dump.isDescendantOf(v8ObjectsDump));
+ assert.isTrue(oilpanDump.isDescendantOf(oilpanDump));
+
+ assert.isFalse(v8Dump.isDescendantOf(oilpanDump));
+ assert.isFalse(v8Dump.isDescendantOf(v8HeapsDump));
+ assert.isFalse(v8Dump.isDescendantOf(v8ObjectsDump));
+ assert.isFalse(v8Dump.isDescendantOf(v8Object1Dump));
+ assert.isFalse(v8Dump.isDescendantOf(v8Object2Dump));
+ assert.isFalse(v8Object1Dump.isDescendantOf(v8Object2Dump));
+ assert.isFalse(v8Object2Dump.isDescendantOf(v8Object1Dump));
+ });
+
+ test('memoryAllocatorDumps_getDescendantDumpByFullName', function() {
+ const containerDump = new ContainerMemoryDump(42);
+
+ const gpuDump = new MemoryAllocatorDump(containerDump, 'gpu');
+ containerDump.memoryAllocatorDumps = [gpuDump];
+
+ const memtrackDump = addChildDump(gpuDump, 'android_memtrack');
+ const glDump = addChildDump(memtrackDump, 'gl');
+ const gfxDump = addChildDump(memtrackDump, 'gfx');
+ const tileDump = addChildDump(gfxDump, 'tile');
+
+ assert.strictEqual(gpuDump.getDescendantDumpByFullName(
+ 'android_memtrack'), memtrackDump);
+ assert.strictEqual(gpuDump.getDescendantDumpByFullName(
+ 'android_memtrack/gfx/tile'), tileDump);
+ assert.strictEqual(memtrackDump.getDescendantDumpByFullName('gl'), glDump);
+ assert.strictEqual(memtrackDump.getDescendantDumpByFullName(
+ 'gfx/tile'), tileDump);
+ });
+
+ test('memoryAllocatorDumpLink_instantiate', function() {
+ const d1 = new MemoryAllocatorDump('v8/isolate1');
+ const d2 = new MemoryAllocatorDump('oilpan/document1');
+ const link = new MemoryAllocatorDumpLink(d1, d2, 3);
+
+ assert.strictEqual(link.source, d1);
+ assert.strictEqual(link.target, d2);
+ assert.strictEqual(link.importance, 3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/memory_dump_test_utils.html b/chromium/third_party/catapult/tracing/tracing/model/memory_dump_test_utils.html
new file mode 100644
index 00000000000..de3413f7f44
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/memory_dump_test_utils.html
@@ -0,0 +1,220 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Helper functions for tests involving memory dumps.
+ */
+tr.exportTo('tr.model', function() {
+ const GlobalMemoryDump = tr.model.GlobalMemoryDump;
+ const ProcessMemoryDump = tr.model.ProcessMemoryDump;
+ const MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+ const MemoryAllocatorDumpLink = tr.model.MemoryAllocatorDumpLink;
+ const VMRegion = tr.model.VMRegion;
+ const VMRegionClassificationNode = tr.model.VMRegionClassificationNode;
+ const Scalar = tr.b.Scalar;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const LIGHT = tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;
+
+ function castToScalar(value) {
+ if (typeof value === 'number') {
+ return new Scalar(sizeInBytes_smallerIsBetter, value);
+ }
+ assert.instanceOf(value, Scalar);
+ return value;
+ }
+
+ function getOption(opt_options, key, opt_defaultValue) {
+ if (opt_options && (key in opt_options)) {
+ return opt_options[key];
+ }
+ return opt_defaultValue;
+ }
+
+ function MemoryDumpTestUtils() {
+ throw new Error('Static class');
+ }
+
+ MemoryDumpTestUtils.SIZE_DELTA = 0.0001;
+
+ /**
+ * Create a new global memory dump and add it to a model.
+ *
+ * @param {!tr.Model} model The trace model to which the new global dump
+ * should be added.
+ * @param {!{
+ * ts: (number|undefined),
+ * duration: (number|undefined),
+ * levelOfDetail: (!tr.model.ContainerMemoryDump.LevelOfDetail|undefined)
+ * }=} opt_options Options for creating the new global dump.
+ * @return {!tr.model.GlobalMemoryDump} The newly created global memory dump.
+ */
+ MemoryDumpTestUtils.addGlobalMemoryDump = function(model, opt_options) {
+ const timestamp = getOption(opt_options, 'ts', 0);
+ const gmd = new GlobalMemoryDump(model, timestamp);
+ gmd.levelOfDetail = getOption(opt_options, 'levelOfDetail', LIGHT);
+ gmd.duration = getOption(opt_options, 'duration', 0);
+ model.globalMemoryDumps.push(gmd);
+ return gmd;
+ };
+
+ /**
+ * Create a new process memory dump and add it to a global memory dump.
+ *
+ * @param {!tr.model.GlobalMemoryDump} gmd The global dump to which the new
+ * process dump should be added.
+ * @param {!tr.model.Process} pmd The process associated with the process
+ * dump.
+ * @param {!{
+ * ts: (number|undefined)
+ * }=} opt_options Options for creating the new process dump.
+ * @return {!tr.model.ProcessMemoryDump} The newly created process memory
+ * dump.
+ */
+ MemoryDumpTestUtils.addProcessMemoryDump =
+ function(gmd, process, opt_options) {
+ const timestamp = getOption(opt_options, 'ts', gmd.start);
+ const pmd = new ProcessMemoryDump(gmd, process, timestamp);
+ process.memoryDumps.push(pmd);
+ if (process.pid in gmd.processMemoryDumps) {
+ // Test sanity check.
+ throw new Error('Process memory dump for process with pid=' +
+ process.pid + ' has already been provided');
+ }
+ gmd.processMemoryDumps[process.pid] = pmd;
+ return pmd;
+ };
+
+ /**
+ * Create a new memory allocator dump.
+ *
+ * @param {!tr.model.ContainerMemoryDump} containerDump The container dump
+ * associated with the new allocator dump.
+ * @param {string} fullName The full name of the new allocator dump
+ * (including ancestors).
+ * @param {!{
+ * guid: (number|undefined),
+ * numerics: (!Object<string, (number|!tr.b.Scalar)>|undefined)
+ * }=} opt_options Options for creating the new allocator dump.
+ * @return {!tr.model.MemoryAllocatorDump} The newly created memory allocator
+ * dump.
+ */
+ MemoryDumpTestUtils.newAllocatorDump = function(
+ containerDump, fullName, opt_options) {
+ const dump = new MemoryAllocatorDump(containerDump, fullName,
+ getOption(opt_options, 'guid'));
+ const numerics = getOption(opt_options, 'numerics');
+ if (numerics) {
+ for (const [numericName, value] of Object.entries(numerics)) {
+ dump.addNumeric(numericName, castToScalar(value));
+ }
+ }
+ const children = getOption(opt_options, 'children');
+ if (children) dump.children = children;
+ return dump;
+ };
+
+ /**
+ * Create a new child memory allocator dump and add it to a parent memory
+ * allocator dump.
+ *
+ * @param {!tr.model.MemoryAllocatorDump} parentDump The parent allocator
+ * dump.
+ * @param {string} name The name of the child allocator dump (excluding
+ * ancestors).
+ * @param {!{
+ * guid: (number|undefined),
+ * numerics: (!Object<string, (number|!tr.b.Scalar)>|undefined)
+ * }=} opt_options Options for creating the child allocator dump.
+ * @return {!tr.model.MemoryAllocatorDump} The newly created child memory
+ * allocator dump.
+ */
+ MemoryDumpTestUtils.addChildDump = function(parentDump, name, opt_options) {
+ const childDump = MemoryDumpTestUtils.newAllocatorDump(
+ parentDump.containerMemoryDump, parentDump.fullName + '/' + name,
+ opt_options);
+ childDump.parent = parentDump;
+ parentDump.children.push(childDump);
+ return childDump;
+ };
+
+ MemoryDumpTestUtils.addOwnershipLink = function(
+ ownerDump, ownedDump, opt_importance) {
+ assert.isUndefined(ownerDump.owns); // Sanity check.
+ const ownershipLink =
+ new MemoryAllocatorDumpLink(ownerDump, ownedDump, opt_importance);
+ ownerDump.owns = ownershipLink;
+ ownedDump.ownedBy.push(ownershipLink);
+ return ownershipLink;
+ };
+
+ MemoryDumpTestUtils.checkDumpNumericsAndDiagnostics =
+ function(dump, expectedNumerics, expectedDiagnostics) {
+ const actualNumerics = dump.numerics;
+ assert.sameMembers(
+ Object.keys(actualNumerics), Object.keys(expectedNumerics));
+ for (const numericName in actualNumerics) {
+ const actualNumeric = actualNumerics[numericName];
+ const expectedNumeric = castToScalar(expectedNumerics[numericName]);
+ assert.instanceOf(actualNumeric, tr.b.Scalar);
+ assert.strictEqual(actualNumeric.unit, expectedNumeric.unit);
+ assert.closeTo(actualNumeric.value, expectedNumeric.value,
+ MemoryDumpTestUtils.SIZE_DELTA);
+ }
+
+ assert.deepEqual(dump.diagnostics, expectedDiagnostics);
+ };
+
+ MemoryDumpTestUtils.checkVMRegions = function(vmRegions, expectedRegions) {
+ if (vmRegions instanceof VMRegionClassificationNode) {
+ vmRegions = vmRegions.allRegionsForTesting;
+ }
+
+ const expectedRegionsMap = new Map();
+ expectedRegions.forEach(function(region) {
+ if (!(region instanceof VMRegion)) {
+ region = VMRegion.fromDict(region);
+ }
+ expectedRegionsMap.set(region.uniqueIdWithinProcess, region);
+ });
+ const actualRegionsMap = new Map();
+ vmRegions.forEach(function(region) {
+ actualRegionsMap.set(region.uniqueIdWithinProcess, region);
+ });
+
+ assert.strictEqual(actualRegionsMap.size, expectedRegionsMap.size);
+ for (const id of expectedRegionsMap.keys()) {
+ const expectedRegion = expectedRegionsMap.get(id);
+ const actualRegion = actualRegionsMap.get(id);
+
+ assert.instanceOf(actualRegion, VMRegion);
+ assert.strictEqual(actualRegion.startAddress,
+ expectedRegion.startAddress);
+ assert.strictEqual(actualRegion.sizeInBytes, expectedRegion.sizeInBytes);
+ assert.strictEqual(actualRegion.protectionFlags,
+ expectedRegion.protectionFlags);
+ assert.strictEqual(actualRegion.mappedFile, expectedRegion.mappedFile);
+ assert.deepEqual(actualRegion.byteStats, expectedRegion.byteStats);
+ }
+ };
+
+ return {
+ MemoryDumpTestUtils,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/model.html b/chromium/third_party/catapult/tracing/tracing/model/model.html
new file mode 100644
index 00000000000..022b7cf7fbe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/model.html
@@ -0,0 +1,670 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/interval_tree.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/base/time_display_modes.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/core/auditor.html">
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/model/alert.html">
+<link rel="import" href="/tracing/model/clock_sync_manager.html">
+<link rel="import" href="/tracing/model/constants.html">
+<link rel="import" href="/tracing/model/device.html">
+<link rel="import" href="/tracing/model/flow_event.html">
+<link rel="import" href="/tracing/model/frame.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/instant_event.html">
+<link rel="import" href="/tracing/model/kernel.html">
+<link rel="import" href="/tracing/model/model_indices.html">
+<link rel="import" href="/tracing/model/model_stats.html">
+<link rel="import" href="/tracing/model/object_snapshot.html">
+<link rel="import" href="/tracing/model/process.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+<link rel="import" href="/tracing/model/sample.html">
+<link rel="import" href="/tracing/model/stack_frame.html">
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+<link rel="import" href="/tracing/model/user_model/user_model.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Model is a parsed representation of the
+ * TraceEvents obtained from base/trace_event in which the begin-end
+ * tokens are converted into a hierarchy of processes, threads,
+ * subrows, and slices.
+ *
+ * The building block of the model is a slice. A slice is roughly
+ * equivalent to function call executing on a specific thread. As a
+ * result, slices may have one or more subslices.
+ *
+ * A thread contains one or more subrows of slices. Row 0 corresponds to
+ * the "root" slices, e.g. the topmost slices. Row 1 contains slices that
+ * are nested 1 deep in the stack, and so on. We use these subrows to draw
+ * nesting tasks.
+ *
+ */
+tr.exportTo('tr', function() {
+ const Process = tr.model.Process;
+ const Device = tr.model.Device;
+ const Kernel = tr.model.Kernel;
+ const GlobalMemoryDump = tr.model.GlobalMemoryDump;
+ const GlobalInstantEvent = tr.model.GlobalInstantEvent;
+ const FlowEvent = tr.model.FlowEvent;
+ const Alert = tr.model.Alert;
+ const Sample = tr.model.Sample;
+
+ /**
+ * @constructor
+ */
+ function Model() {
+ tr.model.EventContainer.call(this);
+ tr.b.EventTarget.decorate(this);
+
+ this.timestampShiftToZeroAmount_ = 0;
+
+ this.faviconHue = 'blue'; // Should be a key from favicons.html
+
+ this.device = new Device(this);
+ this.kernel = new Kernel(this);
+ this.processes = {};
+ this.metadata = [];
+ this.categories = [];
+ this.instantEvents = [];
+ this.flowEvents = [];
+ this.clockSyncManager = new tr.model.ClockSyncManager();
+ this.intrinsicTimeUnit_ = undefined;
+
+ this.stackFrames = {};
+ this.samples = [];
+
+ this.alerts = [];
+ this.userModel = new tr.model.um.UserModel(this);
+
+ this.flowIntervalTree = new tr.b.IntervalTree((f) => f.start, (f) => f.end);
+ this.globalMemoryDumps = [];
+
+ this.userFriendlyCategoryDrivers_ = [];
+
+ this.annotationsByGuid_ = {};
+ this.modelIndices = undefined;
+
+ this.stats = new tr.model.ModelStats();
+
+ this.importWarnings_ = [];
+ this.reportedImportWarnings_ = {};
+
+ this.isTimeHighResolution_ = true;
+
+ this.patchupsToApply_ = [];
+
+ this.doesHelperGUIDSupportThisModel_ = {};
+ this.helpersByConstructorGUID_ = {};
+ this.eventsByStableId_ = undefined;
+ }
+
+ Model.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ getEventByStableId(stableId) {
+ if (this.eventsByStableId_ === undefined) {
+ this.eventsByStableId_ = {};
+ for (const event of this.getDescendantEvents()) {
+ this.eventsByStableId_[event.stableId] = event;
+ }
+ }
+ return this.eventsByStableId_[stableId];
+ },
+
+ getOrCreateHelper(constructor) {
+ if (!constructor.guid) {
+ throw new Error('Helper constructors must have GUIDs');
+ }
+
+ if (this.helpersByConstructorGUID_[constructor.guid] === undefined) {
+ if (this.doesHelperGUIDSupportThisModel_[constructor.guid] ===
+ undefined) {
+ this.doesHelperGUIDSupportThisModel_[constructor.guid] =
+ constructor.supportsModel(this);
+ }
+
+ if (!this.doesHelperGUIDSupportThisModel_[constructor.guid]) {
+ return undefined;
+ }
+
+ this.helpersByConstructorGUID_[constructor.guid] = new constructor(
+ this);
+ }
+ return this.helpersByConstructorGUID_[constructor.guid];
+ },
+
+ * childEvents() {
+ yield* this.globalMemoryDumps;
+ yield* this.instantEvents;
+ yield* this.flowEvents;
+ yield* this.alerts;
+ yield* this.samples;
+ },
+
+ * childEventContainers() {
+ yield this.userModel;
+ yield this.device;
+ yield this.kernel;
+ yield* Object.values(this.processes);
+ },
+
+ /**
+ * Some objects in the model can persist their state in ModelSettings.
+ *
+ * This iterates through them.
+ */
+ iterateAllPersistableObjects(callback) {
+ this.kernel.iterateAllPersistableObjects(callback);
+ for (const pid in this.processes) {
+ this.processes[pid].iterateAllPersistableObjects(callback);
+ }
+ },
+
+ updateBounds() {
+ this.bounds.reset();
+ const bounds = this.bounds;
+ for (const ec of this.childEventContainers()) {
+ ec.updateBounds();
+ bounds.addRange(ec.bounds);
+ }
+ for (const event of this.childEvents()) {
+ event.addBoundsToRange(bounds);
+ }
+ },
+
+ shiftWorldToZero() {
+ const shiftAmount = -this.bounds.min;
+ this.timestampShiftToZeroAmount_ = shiftAmount;
+ for (const ec of this.childEventContainers()) {
+ ec.shiftTimestampsForward(shiftAmount);
+ }
+
+ for (const event of this.childEvents()) {
+ event.start += shiftAmount;
+ }
+ this.updateBounds();
+ },
+
+ convertTimestampToModelTime(sourceClockDomainName, ts) {
+ if (sourceClockDomainName !== 'traceEventClock') {
+ throw new Error('Only traceEventClock is supported.');
+ }
+ return tr.b.Unit.timestampFromUs(ts) +
+ this.timestampShiftToZeroAmount_;
+ },
+
+ get numProcesses() {
+ let n = 0;
+ for (const p in this.processes) {
+ n++;
+ }
+ return n;
+ },
+
+ /**
+ * @return {Process} Gets a TimelineProcess for a specified pid. Returns
+ * undefined if the process doesn't exist.
+ */
+ getProcess(pid) {
+ return this.processes[pid];
+ },
+
+ /**
+ * @return {Process} Gets a TimelineProcess for a specified pid or
+ * creates one if it does not exist.
+ */
+ getOrCreateProcess(pid) {
+ if (!this.processes[pid]) {
+ this.processes[pid] = new Process(this, pid);
+ }
+ return this.processes[pid];
+ },
+
+ addStackFrame(stackFrame) {
+ if (this.stackFrames[stackFrame.id]) {
+ throw new Error('Stack frame already exists');
+ }
+ this.stackFrames[stackFrame.id] = stackFrame;
+ return stackFrame;
+ },
+
+ /**
+ * Generates the set of categories from the slices and counters.
+ */
+ updateCategories_() {
+ const categoriesDict = {};
+ this.userModel.addCategoriesToDict(categoriesDict);
+ this.device.addCategoriesToDict(categoriesDict);
+ this.kernel.addCategoriesToDict(categoriesDict);
+ for (const pid in this.processes) {
+ this.processes[pid].addCategoriesToDict(categoriesDict);
+ }
+
+ this.categories = [];
+ for (const category in categoriesDict) {
+ if (category !== '') {
+ this.categories.push(category);
+ }
+ }
+ },
+
+ getAllThreads() {
+ const threads = [];
+ for (const tid in this.kernel.threads) {
+ threads.push(process.threads[tid]);
+ }
+ for (const pid in this.processes) {
+ const process = this.processes[pid];
+ for (const tid in process.threads) {
+ threads.push(process.threads[tid]);
+ }
+ }
+ return threads;
+ },
+
+ /**
+ * @param {(!function(!tr.model.Process): boolean)=} opt_predicate Optional
+ * predicate for filtering the returned processes. If undefined, all
+ * process in the model will be returned.
+ * @return {!Array<!tr.model.Process>} An array of processes in the model.
+ */
+ getAllProcesses(opt_predicate) {
+ const processes = [];
+ for (const pid in this.processes) {
+ const process = this.processes[pid];
+ if (opt_predicate === undefined || opt_predicate(process)) {
+ processes.push(process);
+ }
+ }
+ return processes;
+ },
+
+ /**
+ * @return {Array} An array of all the counters in the model.
+ */
+ getAllCounters() {
+ const counters = [];
+ counters.push.apply(
+ counters, Object.values(this.device.counters || {}));
+ counters.push.apply(
+ counters, Object.values(this.kernel.counters || {}));
+ for (const pid in this.processes) {
+ const process = this.processes[pid];
+ for (const tid in process.counters) {
+ counters.push(process.counters[tid]);
+ }
+ }
+ return counters;
+ },
+
+ getAnnotationByGUID(guid) {
+ return this.annotationsByGuid_[guid];
+ },
+
+ addAnnotation(annotation) {
+ if (!annotation.guid) {
+ throw new Error('Annotation with undefined guid given');
+ }
+
+ this.annotationsByGuid_[annotation.guid] = annotation;
+ tr.b.dispatchSimpleEvent(this, 'annotationChange');
+ },
+
+ removeAnnotation(annotation) {
+ this.annotationsByGuid_[annotation.guid].onRemove();
+ delete this.annotationsByGuid_[annotation.guid];
+ tr.b.dispatchSimpleEvent(this, 'annotationChange');
+ },
+
+ getAllAnnotations() {
+ return Object.values(this.annotationsByGuid_);
+ },
+
+ addUserFriendlyCategoryDriver(ufcd) {
+ this.userFriendlyCategoryDrivers_.push(ufcd);
+ },
+
+ /**
+ * Gets the user friendly category string from an event.
+ *
+ * Returns undefined if none is known.
+ */
+ getUserFriendlyCategoryFromEvent(event) {
+ for (let i = 0; i < this.userFriendlyCategoryDrivers_.length; i++) {
+ const ufc = this.userFriendlyCategoryDrivers_[i].fromEvent(event);
+ if (ufc !== undefined) return ufc;
+ }
+ return undefined;
+ },
+
+ /**
+ * @param {String} The name of the thread to find.
+ * @return {Array} An array of all the matched threads.
+ */
+ findAllThreadsNamed(name) {
+ const namedThreads = [];
+ namedThreads.push.apply(
+ namedThreads,
+ this.kernel.findAllThreadsNamed(name));
+ for (const pid in this.processes) {
+ namedThreads.push.apply(
+ namedThreads,
+ this.processes[pid].findAllThreadsNamed(name));
+ }
+ return namedThreads;
+ },
+
+ get importOptions() {
+ return this.importOptions_;
+ },
+
+ set importOptions(options) {
+ this.importOptions_ = options;
+ },
+
+ /**
+ * Returns a time unit that is used to format values and determines the
+ * precision of the timestamp values.
+ */
+ get intrinsicTimeUnit() {
+ if (this.intrinsicTimeUnit_ === undefined) {
+ return tr.b.TimeDisplayModes.ms;
+ }
+ return this.intrinsicTimeUnit_;
+ },
+
+ set intrinsicTimeUnit(value) {
+ if (this.intrinsicTimeUnit_ === value) return;
+ if (this.intrinsicTimeUnit_ !== undefined) {
+ throw new Error('Intrinsic time unit already set');
+ }
+ this.intrinsicTimeUnit_ = value;
+ },
+
+ get isTimeHighResolution() {
+ return this.isTimeHighResolution_;
+ },
+
+ set isTimeHighResolution(value) {
+ this.isTimeHighResolution_ = value;
+ },
+
+ /**
+ * Returns a link to a trace data file that this model was imported from.
+ * This is NOT the URL of a site being traced, but instead an indicator of
+ * where the data is stored.
+ */
+ get canonicalUrl() {
+ return this.canonicalUrl_;
+ },
+
+ set canonicalUrl(value) {
+ if (this.canonicalUrl_ === value) return;
+ if (this.canonicalUrl_ !== undefined) {
+ throw new Error('canonicalUrl already set');
+ }
+ this.canonicalUrl_ = value;
+ },
+
+ /**
+ * Saves a warning that happened during import.
+ *
+ * Warnings are typically logged to the console, and optionally, the
+ * more critical ones are shown to the user.
+ *
+ * @param {Object} data The import warning data. Data must provide two
+ * accessors: type, message. The types are used to determine if we
+ * should output the message, we'll only output one message of each type.
+ * The message is the actual warning content.
+ */
+ importWarning(data) {
+ data.showToUser = !!data.showToUser;
+
+ this.importWarnings_.push(data);
+
+ // Only log each warning type once. We may want to add some kind of
+ // flag to allow reporting all importer warnings.
+ if (this.reportedImportWarnings_[data.type] === true) return;
+
+ this.reportedImportWarnings_[data.type] = true;
+ },
+
+ get hasImportWarnings() {
+ return (this.importWarnings_.length > 0);
+ },
+
+ get importWarnings() {
+ return this.importWarnings_;
+ },
+
+ get importWarningsThatShouldBeShownToUser() {
+ return this.importWarnings_.filter(function(warning) {
+ return warning.showToUser;
+ });
+ },
+
+ autoCloseOpenSlices() {
+ // Sort the samples.
+ this.samples.sort(function(x, y) {
+ return x.start - y.start;
+ });
+
+ this.updateBounds();
+ this.kernel.autoCloseOpenSlices();
+ for (const pid in this.processes) {
+ this.processes[pid].autoCloseOpenSlices();
+ }
+ },
+
+ createSubSlices() {
+ this.kernel.createSubSlices();
+ for (const pid in this.processes) {
+ this.processes[pid].createSubSlices();
+ }
+ },
+
+ preInitializeObjects() {
+ for (const pid in this.processes) {
+ this.processes[pid].preInitializeObjects();
+ }
+ },
+
+ initializeObjects() {
+ for (const pid in this.processes) {
+ this.processes[pid].initializeObjects();
+ }
+ },
+
+ pruneEmptyContainers() {
+ this.kernel.pruneEmptyContainers();
+ for (const pid in this.processes) {
+ this.processes[pid].pruneEmptyContainers();
+ }
+ },
+
+ mergeKernelWithUserland() {
+ for (const pid in this.processes) {
+ this.processes[pid].mergeKernelWithUserland();
+ }
+ },
+
+ computeWorldBounds(shiftWorldToZero) {
+ this.updateBounds();
+ this.updateCategories_();
+
+ if (shiftWorldToZero) {
+ this.shiftWorldToZero();
+ }
+ },
+
+ buildFlowEventIntervalTree() {
+ for (let i = 0; i < this.flowEvents.length; ++i) {
+ const flowEvent = this.flowEvents[i];
+ this.flowIntervalTree.insert(flowEvent);
+ }
+ this.flowIntervalTree.updateHighValues();
+ },
+
+ cleanupUndeletedObjects() {
+ for (const pid in this.processes) {
+ this.processes[pid].autoDeleteObjects(this.bounds.max);
+ }
+ },
+
+ sortMemoryDumps() {
+ this.globalMemoryDumps.sort(function(x, y) {
+ return x.start - y.start;
+ });
+
+ for (const pid in this.processes) {
+ this.processes[pid].sortMemoryDumps();
+ }
+ },
+
+ finalizeMemoryGraphs() {
+ this.globalMemoryDumps.forEach(function(dump) {
+ dump.finalizeGraph();
+ });
+ },
+
+ buildEventIndices() {
+ this.modelIndices = new tr.model.ModelIndices(this);
+ },
+
+ sortAlerts() {
+ this.alerts.sort(function(x, y) {
+ return x.start - y.start;
+ });
+ },
+
+ applyObjectRefPatchups() {
+ // Change all the fields pointing at id_refs to their real values.
+ const unresolved = [];
+ this.patchupsToApply_.forEach(function(patchup) {
+ if (patchup.pidRef in this.processes) {
+ const snapshot = this.processes[patchup.pidRef].objects.getSnapshotAt(
+ patchup.scopedId, patchup.ts);
+ if (snapshot) {
+ patchup.object[patchup.field] = snapshot;
+ snapshot.referencedAt(patchup.item, patchup.object, patchup.field);
+ return;
+ }
+ }
+ unresolved.push(patchup);
+ }, this);
+ this.patchupsToApply_ = unresolved;
+ },
+
+ replacePIDRefsInPatchups(oldPidRef, newPidRef) {
+ this.patchupsToApply_.forEach(function(patchup) {
+ if (patchup.pidRef === oldPidRef) {
+ patchup.pidRef = newPidRef;
+ }
+ });
+ },
+
+ /**
+ * Called by the model to join references between objects, after final model
+ * bounds have been computed.
+ */
+ joinRefs() {
+ this.joinObjectRefs_();
+ this.applyObjectRefPatchups();
+ },
+
+ joinObjectRefs_() {
+ for (const [pid, process] of Object.entries(this.processes)) {
+ this.joinObjectRefsForProcess_(pid, process);
+ }
+ },
+
+ joinObjectRefsForProcess_(pid, process) {
+ // Iterate the world, looking for id_refs
+ for (const thread of Object.values(process.threads)) {
+ thread.asyncSliceGroup.slices.forEach(function(item) {
+ this.searchItemForIDRefs_(pid, 'start', item);
+ }, this);
+ thread.sliceGroup.slices.forEach(function(item) {
+ this.searchItemForIDRefs_(pid, 'start', item);
+ }, this);
+ }
+ process.objects.iterObjectInstances(function(instance) {
+ instance.snapshots.forEach(function(item) {
+ this.searchItemForIDRefs_(pid, 'ts', item);
+ }, this);
+ }, this);
+ },
+
+ searchItemForIDRefs_(pid, itemTimestampField, item) {
+ if (!item.args && !item.contexts) return;
+ const patchupsToApply = this.patchupsToApply_;
+
+ function handleField(object, fieldName, fieldValue) {
+ if (!fieldValue || (!fieldValue.id_ref && !fieldValue.idRef)) {
+ return;
+ }
+
+ const scope = fieldValue.scope || tr.model.OBJECT_DEFAULT_SCOPE;
+ const idRef = fieldValue.id_ref || fieldValue.idRef;
+ const scopedId = new tr.model.ScopedId(scope, idRef);
+ const pidRef = fieldValue.pid_ref || fieldValue.pidRef || pid;
+ const ts = item[itemTimestampField];
+ // We have to delay the actual change to the new value until after all
+ // refs have been located. Otherwise, we could end up recursing in
+ // ways we definitely didn't intend.
+ patchupsToApply.push({
+ item,
+ object,
+ field: fieldName,
+ pidRef,
+ scopedId,
+ ts});
+ }
+ function iterObjectFieldsRecursively(object) {
+ if (!(object instanceof Object)) return;
+
+ if ((object instanceof tr.model.ObjectSnapshot) ||
+ (object instanceof Float32Array) ||
+ (object instanceof tr.b.math.Quad)) {
+ return;
+ }
+
+ if (object instanceof Array) {
+ for (let i = 0; i < object.length; i++) {
+ handleField(object, i, object[i]);
+ iterObjectFieldsRecursively(object[i]);
+ }
+ return;
+ }
+
+ for (const key in object) {
+ const value = object[key];
+ handleField(object, key, value);
+ iterObjectFieldsRecursively(value);
+ }
+ }
+
+ iterObjectFieldsRecursively(item.args);
+ iterObjectFieldsRecursively(item.contexts);
+ }
+ };
+
+ return {
+ Model,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/model_indices.html b/chromium/third_party/catapult/tracing/tracing/model/model_indices.html
new file mode 100644
index 00000000000..27f89dba0b0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/model_indices.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Event Index class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * A Event Index maps an id to all the events that have that particular id
+ *
+ * @constructor
+ */
+ function ModelIndices(model) {
+ // For now the only indices we construct are for flowEvents
+ this.flowEventsById_ = {};
+ model.flowEvents.forEach(function(fe) {
+ if (fe.id !== undefined) {
+ if (!this.flowEventsById_.hasOwnProperty(fe.id)) {
+ this.flowEventsById_[fe.id] = [];
+ }
+ this.flowEventsById_[fe.id].push(fe);
+ }
+ }, this);
+ }
+
+ ModelIndices.prototype = {
+ addEventWithId(id, event) {
+ if (!this.flowEventsById_.hasOwnProperty(id)) {
+ this.flowEventsById_[id] = [];
+ }
+ this.flowEventsById_[id].push(event);
+ },
+
+ getFlowEventsWithId(id) {
+ if (!this.flowEventsById_.hasOwnProperty(id)) {
+ return [];
+ }
+ return this.flowEventsById_[id];
+ }
+ };
+
+ return {
+ ModelIndices,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/model_indices_test.html b/chromium/third_party/catapult/tracing/tracing/model/model_indices_test.html
new file mode 100644
index 00000000000..bc5d99a0a29
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/model_indices_test.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newFlowEventEx = tr.c.TestUtils.newFlowEventEx;
+ const newModel = tr.c.TestUtils.newModel;
+
+ test('getCorrectModelIndices', function() {
+ const m = newModel(function(m) {
+ m.f1 = newFlowEventEx({
+ title: 'test1',
+ start: 0,
+ end: 10,
+ id: '0x100'
+ });
+
+ m.f2 = newFlowEventEx({
+ title: 'test2',
+ start: 0,
+ end: 10,
+ id: '0x100'
+ });
+
+ m.flowEvents.push(m.f1);
+ m.flowEvents.push(m.f2);
+ });
+
+ assert.isDefined(m.modelIndices);
+ const modelIndices = m.modelIndices;
+ assert.strictEqual(modelIndices.getFlowEventsWithId('0x100').length, 2);
+ assert.strictEqual(
+ modelIndices.getFlowEventsWithId('0x100')[0].id, '0x100');
+ assert.strictEqual(modelIndices.getFlowEventsWithId('0x101').length, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/model_settings.html b/chromium/third_party/catapult/tracing/tracing/model/model_settings.html
new file mode 100644
index 00000000000..c34040183d2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/model_settings.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/settings.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const Settings = tr.b.Settings;
+
+ /**
+ * A way to persist settings specific to parts of a trace model.
+ *
+ * This object should not be persisted because it builds up internal data
+ * structures that map model objects to settings keys. It should thus be
+ * created for the duration of whatever interaction(s) you're going to do with
+ * model settings, and then discarded.
+ *
+ * This system works on a notion of an object key: for an object's key, it
+ * considers all the other keys in the model. If it is unique, then the key is
+ * persisted to tr.b.Settings. However, if it is not unique, then the
+ * setting is stored on the object itself. Thus, objects with unique keys will
+ * be persisted across page reloads, whereas objects with nonunique keys will
+ * not.
+ */
+ function ModelSettings(model) {
+ this.model = model;
+ this.objectsByKey_ = [];
+ this.nonuniqueKeys_ = [];
+ this.buildObjectsByKeyMap_();
+ this.removeNonuniqueKeysFromSettings_();
+ this.ephemeralSettingsByGUID_ = {};
+ }
+
+ ModelSettings.prototype = {
+ buildObjectsByKeyMap_() {
+ const objects = [];
+ this.model.iterateAllPersistableObjects(function(o) {
+ objects.push(o);
+ });
+
+ const objectsByKey = {};
+ const NONUNIQUE_KEY = 'nonuniqueKey';
+ for (let i = 0; i < objects.length; i++) {
+ const object = objects[i];
+ const objectKey = object.getSettingsKey();
+ if (!objectKey) continue;
+ if (objectsByKey[objectKey] === undefined) {
+ objectsByKey[objectKey] = object;
+ continue;
+ }
+ objectsByKey[objectKey] = NONUNIQUE_KEY;
+ }
+
+ const nonuniqueKeys = {};
+ Object.keys(objectsByKey).forEach(function(objectKey) {
+ if (objectsByKey[objectKey] !== NONUNIQUE_KEY) {
+ return;
+ }
+ delete objectsByKey[objectKey];
+ nonuniqueKeys[objectKey] = true;
+ });
+
+ this.nonuniqueKeys = nonuniqueKeys;
+ this.objectsByKey_ = objectsByKey;
+ },
+
+ removeNonuniqueKeysFromSettings_() {
+ const settings = Settings.get('trace_model_settings', {});
+ let settingsChanged = false;
+ Object.keys(settings).forEach(function(objectKey) {
+ if (!this.nonuniqueKeys[objectKey]) {
+ return;
+ }
+ settingsChanged = true;
+ delete settings[objectKey];
+ }, this);
+ if (settingsChanged) {
+ Settings.set('trace_model_settings', settings);
+ }
+ },
+
+ hasUniqueSettingKey(object) {
+ const objectKey = object.getSettingsKey();
+ if (!objectKey) return false;
+ return this.objectsByKey_[objectKey] !== undefined;
+ },
+
+ getSettingFor(object, objectLevelKey, defaultValue) {
+ const objectKey = object.getSettingsKey();
+ if (!objectKey || !this.objectsByKey_[objectKey]) {
+ const settings = this.getEphemeralSettingsFor_(object);
+ const ephemeralValue = settings[objectLevelKey];
+ if (ephemeralValue !== undefined) {
+ return ephemeralValue;
+ }
+ return defaultValue;
+ }
+
+ const settings = Settings.get('trace_model_settings', {});
+ if (!settings[objectKey]) {
+ settings[objectKey] = {};
+ }
+ const value = settings[objectKey][objectLevelKey];
+ if (value !== undefined) {
+ return value;
+ }
+ return defaultValue;
+ },
+
+ setSettingFor(object, objectLevelKey, value) {
+ const objectKey = object.getSettingsKey();
+ if (!objectKey || !this.objectsByKey_[objectKey]) {
+ this.getEphemeralSettingsFor_(object)[objectLevelKey] = value;
+ return;
+ }
+
+ const settings = Settings.get('trace_model_settings', {});
+ if (!settings[objectKey]) {
+ settings[objectKey] = {};
+ }
+ if (settings[objectKey][objectLevelKey] === value) {
+ return;
+ }
+ settings[objectKey][objectLevelKey] = value;
+ Settings.set('trace_model_settings', settings);
+ },
+
+ getEphemeralSettingsFor_(object) {
+ if (object.guid === undefined) {
+ throw new Error('Only objects with GUIDs can be persisted');
+ }
+ if (this.ephemeralSettingsByGUID_[object.guid] === undefined) {
+ this.ephemeralSettingsByGUID_[object.guid] = {};
+ }
+ return this.ephemeralSettingsByGUID_[object.guid];
+ }
+ };
+
+ return {
+ ModelSettings,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/model_settings_test.html b/chromium/third_party/catapult/tracing/tracing/model/model_settings_test.html
new file mode 100644
index 00000000000..cec8898180c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/model_settings_test.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/model_settings.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('process_name_uniqueness_0', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const settings = new tr.model.ModelSettings(model);
+ assert.isFalse(settings.hasUniqueSettingKey(p1));
+ });
+
+ test('process_name_uniqueness_1', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ p1.name = 'Browser';
+ const settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.hasUniqueSettingKey(p1));
+ });
+
+ test('process_name_uniqueness_2', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const p2 = model.getOrCreateProcess(2);
+ p1.name = 'Renderer';
+ p2.name = 'Renderer';
+ const settings = new tr.model.ModelSettings(model);
+ assert.isFalse(settings.hasUniqueSettingKey(p1));
+ assert.isFalse(settings.hasUniqueSettingKey(p2));
+ });
+
+ test('process_name_uniqueness_3', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const p2 = model.getOrCreateProcess(2);
+ p1.name = 'Renderer';
+ p1.labels.push('Google Search');
+ p2.name = 'Renderer';
+ const settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.hasUniqueSettingKey(p1));
+ assert.isTrue(settings.hasUniqueSettingKey(p2));
+ });
+
+ test('thread_name_uniqueness_0', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const p2 = model.getOrCreateProcess(2);
+ const t1 = p1.getOrCreateThread(1);
+ const t2 = p2.getOrCreateThread(2);
+ p1.name = 'Browser';
+ p2.name = 'Renderer';
+ t1.name = 'Main';
+ t2.name = 'Main';
+ const settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.hasUniqueSettingKey(t1));
+ assert.isTrue(settings.hasUniqueSettingKey(t2));
+ });
+
+ test('thread_name_uniqueness_1', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const p2 = model.getOrCreateProcess(2);
+ const t1 = p1.getOrCreateThread(1);
+ const t2 = p2.getOrCreateThread(2);
+ p1.name = 'Renderer';
+ p2.name = 'Renderer';
+ t1.name = 'Main';
+ t2.name = 'Main';
+ const settings = new tr.model.ModelSettings(model);
+ assert.isFalse(settings.hasUniqueSettingKey(t1));
+ assert.isFalse(settings.hasUniqueSettingKey(t2));
+ });
+
+ test('process_persistence_when_not_unique', function() {
+ let model = new tr.Model();
+ let p1 = model.getOrCreateProcess(1);
+ let settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.getSettingFor(p1, 'true_by_default', true));
+
+ settings.setSettingFor(p1, 'true_by_default', false);
+ assert.isFalse(settings.getSettingFor(p1, 'true_by_default', true));
+
+ // Now, clobber the model, and verify that it didn't persist.
+ model = new tr.Model();
+ p1 = model.getOrCreateProcess(1);
+ settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.getSettingFor(p1, 'true_by_default', true));
+ });
+
+ test('process_persistence_when_not_unique_with_name', function() {
+ let model = new tr.Model();
+ let p1 = model.getOrCreateProcess(1);
+ p1.name = 'Browser';
+ let settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.getSettingFor(p1, 'true_by_default', true));
+
+ settings.setSettingFor(p1, 'true_by_default', false);
+ assert.isFalse(settings.getSettingFor(p1, 'true_by_default', true));
+
+ // Now, clobber the model, and verify that it persisted.
+ model = new tr.Model();
+ p1 = model.getOrCreateProcess(1);
+ p1.name = 'Browser';
+ settings = new tr.model.ModelSettings(model);
+ assert.isFalse(settings.getSettingFor(p1, 'true_by_default', true));
+ });
+
+ test('thread_persistence_when_not_unique', function() {
+ let model = new tr.Model();
+ let p1 = model.getOrCreateProcess(1);
+ let p2 = model.getOrCreateProcess(2);
+ let t1 = p1.getOrCreateThread(1);
+ let t2 = p2.getOrCreateThread(2);
+ p1.name = 'Renderer';
+ p2.name = 'Renderer';
+ t1.name = 'Main';
+ t2.name = 'Main';
+ let settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.getSettingFor(t1, 'true_by_default', true));
+
+ settings.setSettingFor(t1, 'true_by_default', false);
+ assert.isFalse(settings.getSettingFor(t1, 'true_by_default', true));
+
+ // Now, clobber the model, and verify that it persisted.
+ model = new tr.Model();
+ p1 = model.getOrCreateProcess(1);
+ p2 = model.getOrCreateProcess(2);
+ t1 = p1.getOrCreateThread(1);
+ t2 = p2.getOrCreateThread(2);
+ p1.name = 'Renderer';
+ p2.name = 'Renderer';
+ t1.name = 'Main';
+ t2.name = 'Main';
+ settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.getSettingFor(t1, 'true_by_default', true));
+ });
+
+ test('thread_persistence_when_unique', function() {
+ let model = new tr.Model();
+ let p1 = model.getOrCreateProcess(1);
+ let p2 = model.getOrCreateProcess(2);
+ let t1 = p1.getOrCreateThread(1);
+ let t2 = p2.getOrCreateThread(2);
+ p1.name = 'Browser';
+ p2.name = 'Renderer';
+ t1.name = 'Main';
+ t2.name = 'Main';
+ let settings = new tr.model.ModelSettings(model);
+ assert.isTrue(settings.getSettingFor(t1, 'true_by_default', true));
+
+ settings.setSettingFor(t1, 'true_by_default', false);
+ assert.isFalse(settings.getSettingFor(t1, 'true_by_default', true));
+
+ // Now, clobber the model, and verify that it persisted.
+ model = new tr.Model();
+ p1 = model.getOrCreateProcess(1);
+ p2 = model.getOrCreateProcess(2);
+ t1 = p1.getOrCreateThread(1);
+ t2 = p2.getOrCreateThread(2);
+ p1.name = 'Browser';
+ p2.name = 'Renderer';
+ t1.name = 'Main';
+ t2.name = 'Main';
+ settings = new tr.model.ModelSettings(model);
+ assert.isFalse(settings.getSettingFor(t1, 'true_by_default', true));
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/model_stats.html b/chromium/third_party/catapult/tracing/tracing/model/model_stats.html
new file mode 100644
index 00000000000..41f7dd64602
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/model_stats.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * @constructor
+ */
+ function ModelStats() {
+ this.traceEventCountsByKey_ = new Map();
+ this.allTraceEventStats_ = [];
+
+ this.traceEventStatsInTimeIntervals_ = new Map();
+ this.allTraceEventStatsInTimeIntervals_ = [];
+
+ this.hasEventSizesinBytes_ = false;
+
+ this.traceImportDurationMs_ = undefined;
+ }
+
+ ModelStats.prototype = {
+ TIME_INTERVAL_SIZE_IN_MS: 100,
+
+ willProcessBasicTraceEvent(phase, category, title, ts,
+ opt_eventSizeinBytes) {
+ const key = phase + '/' + category + '/' + title;
+ let eventStats = this.traceEventCountsByKey_.get(key);
+ if (eventStats === undefined) {
+ eventStats = {
+ phase,
+ category,
+ title,
+ numEvents: 0,
+ totalEventSizeinBytes: 0
+ };
+ this.traceEventCountsByKey_.set(key, eventStats);
+ this.allTraceEventStats_.push(eventStats);
+ }
+ eventStats.numEvents++;
+
+ const timeIntervalKey = Math.floor(
+ tr.b.Unit.timestampFromUs(ts) / this.TIME_INTERVAL_SIZE_IN_MS);
+ let eventStatsByTimeInverval =
+ this.traceEventStatsInTimeIntervals_.get(timeIntervalKey);
+ if (eventStatsByTimeInverval === undefined) {
+ eventStatsByTimeInverval = {
+ timeInterval: timeIntervalKey,
+ numEvents: 0,
+ totalEventSizeinBytes: 0
+ };
+ this.traceEventStatsInTimeIntervals_.set(timeIntervalKey,
+ eventStatsByTimeInverval);
+ this.allTraceEventStatsInTimeIntervals_.push(eventStatsByTimeInverval);
+ }
+ eventStatsByTimeInverval.numEvents++;
+
+ if (opt_eventSizeinBytes !== undefined) {
+ this.hasEventSizesinBytes_ = true;
+ eventStats.totalEventSizeinBytes += opt_eventSizeinBytes;
+ eventStatsByTimeInverval.totalEventSizeinBytes += opt_eventSizeinBytes;
+ }
+ },
+
+ get allTraceEventStats() {
+ return this.allTraceEventStats_;
+ },
+
+ get allTraceEventStatsInTimeIntervals() {
+ return this.allTraceEventStatsInTimeIntervals_;
+ },
+
+ get hasEventSizesinBytes() {
+ return this.hasEventSizesinBytes_;
+ },
+
+ get traceImportDurationMs() {
+ return this.traceImportDurationMs_;
+ },
+
+ set traceImportDurationMs(traceImportDurationMs) {
+ this.traceImportDurationMs_ = traceImportDurationMs;
+ }
+ };
+
+ return {
+ ModelStats,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/model_stats_test.html b/chromium/third_party/catapult/tracing/tracing/model/model_stats_test.html
new file mode 100644
index 00000000000..a1108b1b57a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/model_stats_test.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/model/model_stats.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ModelStats = tr.model.ModelStats;
+
+ test('getTraceEventStatsByCategory', function() {
+ const modelStats = new ModelStats();
+ modelStats.willProcessBasicTraceEvent('X', 'cat1', 'title1');
+ modelStats.willProcessBasicTraceEvent('X', 'cat1', 'title1');
+ modelStats.willProcessBasicTraceEvent('X', 'cat2', 'title3');
+
+ assert.strictEqual(modelStats.allTraceEventStats.length, 2);
+ assert.strictEqual(
+ modelStats.traceEventCountsByKey_.get('X/cat1/title1').numEvents,
+ 2);
+ assert.strictEqual(
+ modelStats.traceEventCountsByKey_.get('X/cat2/title3').numEvents,
+ 1);
+ });
+
+ test('getTraceEventStatsInTimeIntervals', function() {
+ const modelStats = new ModelStats();
+ const timeIntervalSizeInUs = modelStats.TIME_INTERVAL_SIZE_IN_MS * 1000;
+ modelStats.willProcessBasicTraceEvent('X', 'cat1', 'title1', 1, 1);
+ modelStats.willProcessBasicTraceEvent(
+ 'X', 'cat1', 'title1', timeIntervalSizeInUs + 1, 2);
+ modelStats.willProcessBasicTraceEvent(
+ 'X', 'cat1', 'title1', 2 * timeIntervalSizeInUs + 1, 3);
+ modelStats.willProcessBasicTraceEvent(
+ 'X', 'cat2', 'title3', 2 * timeIntervalSizeInUs + 2, 4);
+
+ assert.strictEqual(modelStats.allTraceEventStatsInTimeIntervals.length, 3);
+ assert.strictEqual(
+ modelStats.traceEventStatsInTimeIntervals_.get(0).numEvents, 1);
+ assert.strictEqual(
+ modelStats.traceEventStatsInTimeIntervals_.get(1).numEvents, 1);
+ assert.strictEqual(
+ modelStats.traceEventStatsInTimeIntervals_.get(2).numEvents, 2);
+
+ assert.isTrue(modelStats.hasEventSizesinBytes);
+ assert.strictEqual(
+ modelStats.traceEventStatsInTimeIntervals_.get(0).totalEventSizeinBytes,
+ 1);
+ assert.strictEqual(
+ modelStats.traceEventStatsInTimeIntervals_.get(1).totalEventSizeinBytes,
+ 2);
+ assert.strictEqual(
+ modelStats.traceEventStatsInTimeIntervals_.get(2).totalEventSizeinBytes,
+ 7);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/model_test.html b/chromium/third_party/catapult/tracing/tracing/model/model_test.html
new file mode 100644
index 00000000000..7613b421254
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/model_test.html
@@ -0,0 +1,343 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/time_display_modes.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/model/annotation.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ThreadSlice = tr.model.ThreadSlice;
+ const TitleOrCategoryFilter = tr.c.TitleOrCategoryFilter;
+ const Frame = tr.model.Frame;
+
+ const createModelWithOneOfEverything = function() {
+ const m = new tr.Model();
+ const cpu = m.kernel.getOrCreateCpu(1);
+ cpu.slices.push(tr.c.TestUtils.newSliceEx({start: 1, duration: 3}));
+
+ const p = m.getOrCreateProcess(1);
+ const t = p.getOrCreateThread(1);
+ const slice = new ThreadSlice('', 'a', 0, 1, {}, 4);
+ t.sliceGroup.pushSlice(slice);
+ t.asyncSliceGroup.push(tr.c.TestUtils.newAsyncSlice(0, 1, t, t));
+
+ const c = p.getOrCreateCounter('', 'ProcessCounter');
+ let aSeries = new tr.model.CounterSeries('a', 0);
+ let bSeries = new tr.model.CounterSeries('b', 0);
+ c.addSeries(aSeries);
+ c.addSeries(bSeries);
+
+ aSeries.addCounterSample(0, 5);
+ aSeries.addCounterSample(1, 6);
+ aSeries.addCounterSample(2, 5);
+ aSeries.addCounterSample(3, 7);
+
+ bSeries.addCounterSample(0, 10);
+ bSeries.addCounterSample(1, 15);
+ bSeries.addCounterSample(2, 12);
+ bSeries.addCounterSample(3, 16);
+
+ const c1 = cpu.getOrCreateCounter('', 'CpuCounter');
+ aSeries = new tr.model.CounterSeries('a', 0);
+ bSeries = new tr.model.CounterSeries('b', 0);
+ c1.addSeries(aSeries);
+ c1.addSeries(bSeries);
+
+ aSeries.addCounterSample(0, 5);
+ aSeries.addCounterSample(1, 6);
+ aSeries.addCounterSample(2, 5);
+ aSeries.addCounterSample(3, 7);
+
+ bSeries.addCounterSample(0, 10);
+ bSeries.addCounterSample(1, 15);
+ bSeries.addCounterSample(2, 12);
+ bSeries.addCounterSample(3, 16);
+
+ const frame1 = new Frame([slice], [{thread: t, start: 1, end: 5}]);
+ p.frames.push.apply(p.frames, frame1);
+
+ const gd = new tr.model.GlobalMemoryDump(m, 2);
+ const pd = new tr.model.ProcessMemoryDump(gd, p, 2);
+ gd.processMemoryDumps[1] = pd;
+ m.globalMemoryDumps.push(gd);
+ p.memoryDumps.push(pd);
+
+ m.updateBounds();
+
+ return m;
+ };
+
+ test('helper', function() {
+ function Helper(model) {
+ this.model = model;
+ }
+ Helper.guid = tr.b.GUID.allocateSimple();
+ Helper.supportsModel = function(model) {
+ return true;
+ };
+
+ const m = new tr.Model();
+ const h = m.getOrCreateHelper(Helper);
+ assert.isTrue(h instanceof Helper);
+ assert.isTrue(h === m.getOrCreateHelper(Helper));
+
+ function UnsupportedHelper(model) {
+ this.model = model;
+ }
+ UnsupportedHelper.guid = tr.b.GUID.allocateSimple();
+ UnsupportedHelper.supportsModel = function(model) {
+ return false;
+ };
+
+ assert.isUndefined(m.getOrCreateHelper(UnsupportedHelper));
+ // Try again to test doesHelperGUIDSupportThisModel_ .
+ assert.isUndefined(m.getOrCreateHelper(UnsupportedHelper));
+ });
+
+ test('modelBounds_EmptyModel', function() {
+ const m = new tr.Model();
+ m.updateBounds();
+ assert.isUndefined(m.bounds.min);
+ assert.isUndefined(m.bounds.max);
+ });
+
+ test('modelBounds_OneEmptyThread', function() {
+ const m = new tr.Model();
+ const t = m.getOrCreateProcess(1).getOrCreateThread(1);
+ m.updateBounds();
+ assert.isUndefined(m.bounds.min);
+ assert.isUndefined(m.bounds.max);
+ });
+
+ test('modelBounds_OneThread', function() {
+ const m = new tr.Model();
+ const t = m.getOrCreateProcess(1).getOrCreateThread(1);
+ t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
+ m.updateBounds();
+ assert.strictEqual(m.bounds.min, 1);
+ assert.strictEqual(m.bounds.max, 4);
+ });
+
+ test('modelBounds_OneThreadAndOneEmptyThread', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
+ const t2 = m.getOrCreateProcess(1).getOrCreateThread(1);
+ m.updateBounds();
+ assert.strictEqual(m.bounds.min, 1);
+ assert.strictEqual(m.bounds.max, 4);
+ });
+
+ test('modelBounds_OneCpu', function() {
+ const m = new tr.Model();
+ const cpu = m.kernel.getOrCreateCpu(1);
+ cpu.slices.push(tr.c.TestUtils.newSliceEx({start: 1, duration: 3}));
+ m.updateBounds();
+ assert.strictEqual(m.bounds.min, 1);
+ assert.strictEqual(m.bounds.max, 4);
+ });
+
+ test('modelBounds_OneCpuOneThread', function() {
+ const m = new tr.Model();
+ const cpu = m.kernel.getOrCreateCpu(1);
+ cpu.slices.push(tr.c.TestUtils.newSliceEx({start: 1, duration: 3}));
+
+ const t = m.getOrCreateProcess(1).getOrCreateThread(1);
+ t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 4));
+
+ m.updateBounds();
+ assert.strictEqual(m.bounds.min, 1);
+ assert.strictEqual(m.bounds.max, 5);
+ });
+
+ test('modelBounds_GlobalMemoryDumps', function() {
+ const m = new tr.Model();
+ m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 1));
+ m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 3));
+ m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 5));
+
+ m.updateBounds();
+ assert.strictEqual(m.bounds.min, 1);
+ assert.strictEqual(m.bounds.max, 5);
+ });
+
+ test('modelBounds_ProcessMemoryDumps', function() {
+ const m = new tr.Model();
+ const p = m.getOrCreateProcess(1);
+ const gd = new tr.model.GlobalMemoryDump(m, -1);
+ p.memoryDumps.push(new tr.model.ProcessMemoryDump(gd, m, 1));
+ p.memoryDumps.push(new tr.model.ProcessMemoryDump(gd, m, 3));
+ p.memoryDumps.push(new tr.model.ProcessMemoryDump(gd, m, 5));
+
+ m.updateBounds();
+ assert.strictEqual(m.bounds.min, 1);
+ assert.strictEqual(m.bounds.max, 5);
+ });
+
+
+ test('modelConvertsTimestampToModelTime', function() {
+ const m = new tr.Model();
+ const traceEvents = [
+ {ts: 1000, pid: 1, tid: 1, ph: 'B', cat: 'a', name: 'taskA', args: {}},
+ {ts: 2000, pid: 1, tid: 1, ph: 'E', cat: 'a', name: 'taskA', args: {}}
+ ];
+ const i = new tr.importer.Import(m);
+ i.importTraces([traceEvents]);
+ assert.strictEqual(
+ m.convertTimestampToModelTime('traceEventClock', 1000), 0);
+ assert.strictEqual(
+ m.convertTimestampToModelTime('traceEventClock', 2000), 1);
+ });
+
+ test('TitleOrCategoryFilter', function() {
+ const s0 = tr.c.TestUtils.newSliceEx({start: 1, duration: 3});
+ assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s0));
+ assert.isFalse(new TitleOrCategoryFilter('x').matchSlice(s0));
+
+ const s1 = tr.c.TestUtils.newSliceEx({title: 'ba', start: 1, duration: 3});
+ assert.isTrue(new TitleOrCategoryFilter('a').matchSlice(s1));
+ assert.isTrue(new TitleOrCategoryFilter('ba').matchSlice(s1));
+ assert.isFalse(new TitleOrCategoryFilter('x').matchSlice(s1));
+ });
+
+ test('model_findAllThreadsNamed', function() {
+ const m = new tr.Model();
+ const t = m.getOrCreateProcess(1).getOrCreateThread(1);
+ t.name = 'CrBrowserMain';
+
+ m.updateBounds();
+ let f = m.findAllThreadsNamed('CrBrowserMain');
+ assert.deepEqual([t], f);
+ f = m.findAllThreadsNamed('NoSuchThread');
+ assert.strictEqual(f.length, 0);
+ });
+
+ test('model_updateCategories', function() {
+ const m = new tr.Model();
+ const t = m.getOrCreateProcess(1).getOrCreateThread(1);
+ t.sliceGroup.pushSlice(new ThreadSlice('categoryA', 'a', 0, 1, {}, 3));
+ t.sliceGroup.pushSlice(new ThreadSlice('categoryA', 'a', 0, 1, {}, 3));
+ t.sliceGroup.pushSlice(new ThreadSlice('categoryB', 'a', 0, 1, {}, 3));
+ t.sliceGroup.pushSlice(new ThreadSlice('categoryA', 'a', 0, 1, {}, 3));
+ t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
+ m.updateCategories_();
+ assert.deepEqual(['categoryA', 'categoryB'], m.categories);
+ });
+
+ test('getEventByStableId', function() {
+ const m = new tr.Model();
+ const p = m.getOrCreateProcess(0);
+ const t = p.getOrCreateThread(1);
+ const slice = tr.c.TestUtils.newSliceEx({start: 0, duration: 10});
+ t.sliceGroup.pushSlice(slice);
+ const ue = tr.c.TestUtils.newInteractionRecord(m, 0, 10);
+ m.userModel.expectations.push(ue);
+ const gie = tr.c.TestUtils.newInstantEvent({
+ title: 'gie',
+ start: 0,
+ colorId: 0
+ });
+ m.instantEvents.push(gie);
+
+ assert.strictEqual(slice, m.getEventByStableId(slice.stableId));
+ assert.strictEqual(ue, m.getEventByStableId(ue.stableId));
+ assert.strictEqual(gie, m.getEventByStableId(gie.stableId));
+ });
+
+ test('model_annotationAddRemove', function() {
+ const m = new tr.Model();
+ const a1 = new tr.model.Annotation();
+ const a2 = new tr.model.Annotation();
+
+ assert.strictEqual(m.getAllAnnotations().length, 0);
+ m.addAnnotation(a1);
+ assert.strictEqual(m.getAllAnnotations().length, 1);
+ m.addAnnotation(a2);
+ assert.strictEqual(m.getAllAnnotations().length, 2);
+
+ assert.strictEqual(m.getAnnotationByGUID(a1.guid), a1);
+ assert.strictEqual(m.getAnnotationByGUID(a2.guid), a2);
+
+ m.removeAnnotation(a1);
+ assert.isUndefined(m.getAnnotationByGUID(a1.guid));
+ assert.strictEqual(m.getAnnotationByGUID(a2.guid), a2);
+ assert.strictEqual(m.getAllAnnotations().length, 1);
+ });
+
+ test('model_intrinsicTimeUnit', function() {
+ const unit = tr.b.TimeDisplayModes;
+ const m = new tr.Model();
+
+ // by default it should be milliseconds
+ assert.strictEqual(m.intrinsicTimeUnit, unit.ms);
+
+ m.intrinsicTimeUnit = unit.ns;
+ assert.strictEqual(m.intrinsicTimeUnit, unit.ns);
+ // should be able to set to the same
+ m.intrinsicTimeUnit = unit.ns;
+ assert.strictEqual(m.intrinsicTimeUnit, unit.ns);
+ // should not be able to change it after fixing it
+ assert.throw(function() { m.intrinsicTimeUnit = unit.ms; });
+ assert.strictEqual(m.intrinsicTimeUnit, unit.ns);
+ });
+
+ test('model_getAllProcesses', function() {
+ const m = new tr.Model();
+ const p1 = m.getOrCreateProcess(1);
+ const p2 = m.getOrCreateProcess(2);
+ const p3 = m.getOrCreateProcess(3);
+ const p4 = m.getOrCreateProcess(4);
+ const p5 = m.getOrCreateProcess(5);
+
+ assert.sameMembers(m.getAllProcesses(), [p1, p2, p3, p4, p5]);
+ assert.sameMembers(m.getAllProcesses(p => true), [p1, p2, p3, p4, p5]);
+ assert.sameMembers(m.getAllProcesses(p => false), []);
+ assert.sameMembers(m.getAllProcesses(p => p.pid % 2 === 0), [p2, p4]);
+ });
+
+ test('model_joinRefs', function() {
+ function RefCountingSnapshot() {
+ tr.model.ObjectSnapshot.apply(this, arguments);
+ this.refCount = 0;
+ }
+
+ RefCountingSnapshot.prototype = {
+ __proto__: tr.model.ObjectSnapshot.prototype,
+
+ referencedAt() {
+ ++this.refCount;
+ }
+ };
+
+ const typeName = 'RefCountingSnapshot';
+ tr.model.ObjectSnapshot.subTypes.register(
+ RefCountingSnapshot,
+ {typeName});
+
+ const m = new tr.Model();
+ const p = m.getOrCreateProcess(1);
+ const s1 = p.objects.addSnapshot(new tr.model.ScopedId(typeName, '0x1'),
+ 'cat', typeName, 1000, {});
+ const s2 = p.objects.addSnapshot(new tr.model.ScopedId(typeName, '0x2'),
+ 'cat', typeName, 2000, {
+ myRef: {
+ scope: typeName,
+ id_ref: '0x1'
+ }
+ });
+ m.joinRefs();
+ assert.strictEqual(s1.refCount, 1);
+ assert.strictEqual(s2.refCount, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/object_collection.html b/chromium/third_party/catapult/tracing/tracing/model/object_collection.html
new file mode 100644
index 00000000000..5b4ed2325dc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/object_collection.html
@@ -0,0 +1,229 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+<link rel="import" href="/tracing/model/time_to_object_instance_map.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the ObjectCollection class.
+ */
+tr.exportTo('tr.model', function() {
+ const ObjectInstance = tr.model.ObjectInstance;
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ /**
+ * A collection of object instances and their snapshots, accessible by id and
+ * time, or by object name.
+ *
+ * @constructor
+ */
+ function ObjectCollection(parent) {
+ tr.model.EventContainer.call(this);
+ this.parent = parent;
+ // scope -> {id -> TimeToObjectInstanceMap}
+ this.instanceMapsByScopedId_ = {};
+ this.instancesByTypeName_ = {};
+ this.createObjectInstance_ = this.createObjectInstance_.bind(this);
+ }
+
+ ObjectCollection.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ * childEvents() {
+ for (const instance of this.getAllObjectInstances()) {
+ yield instance;
+ yield* instance.snapshots;
+ }
+ },
+
+ createObjectInstance_(
+ parent, scopedId, category, name, creationTs, opt_baseTypeName) {
+ const constructor = tr.model.ObjectInstance.subTypes.getConstructor(
+ category, name);
+ const instance = new constructor(
+ parent, scopedId, category, name, creationTs, opt_baseTypeName);
+ const typeName = instance.typeName;
+ let instancesOfTypeName = this.instancesByTypeName_[typeName];
+ if (!instancesOfTypeName) {
+ instancesOfTypeName = [];
+ this.instancesByTypeName_[typeName] = instancesOfTypeName;
+ }
+ instancesOfTypeName.push(instance);
+ return instance;
+ },
+
+ getOrCreateInstanceMap_(scopedId) {
+ let dict;
+ if (scopedId.scope in this.instanceMapsByScopedId_) {
+ dict = this.instanceMapsByScopedId_[scopedId.scope];
+ } else {
+ dict = {};
+ this.instanceMapsByScopedId_[scopedId.scope] = dict;
+ }
+ let instanceMap = dict[scopedId.id];
+ if (instanceMap) return instanceMap;
+ instanceMap = new tr.model.TimeToObjectInstanceMap(
+ this.createObjectInstance_, this.parent, scopedId);
+ dict[scopedId.id] = instanceMap;
+ return instanceMap;
+ },
+
+ idWasCreated(scopedId, category, name, ts) {
+ const instanceMap = this.getOrCreateInstanceMap_(scopedId);
+ return instanceMap.idWasCreated(category, name, ts);
+ },
+
+ addSnapshot(
+ scopedId, category, name, ts, args, opt_baseTypeName) {
+ const instanceMap = this.getOrCreateInstanceMap_(scopedId);
+ const snapshot = instanceMap.addSnapshot(
+ category, name, ts, args, opt_baseTypeName);
+ if (snapshot.objectInstance.category !== category) {
+ const msg = 'Added snapshot name=' + name + ' with cat=' + category +
+ ' impossible. It instance was created/snapshotted with cat=' +
+ snapshot.objectInstance.category + ' name=' +
+ snapshot.objectInstance.name;
+ throw new Error(msg);
+ }
+ if (opt_baseTypeName &&
+ snapshot.objectInstance.baseTypeName !== opt_baseTypeName) {
+ throw new Error('Could not add snapshot with baseTypeName=' +
+ opt_baseTypeName + '. It ' +
+ 'was previously created with name=' +
+ snapshot.objectInstance.baseTypeName);
+ }
+ if (snapshot.objectInstance.name !== name) {
+ throw new Error('Could not add snapshot with name=' + name + '. It ' +
+ 'was previously created with name=' +
+ snapshot.objectInstance.name);
+ }
+ return snapshot;
+ },
+
+ idWasDeleted(scopedId, category, name, ts) {
+ const instanceMap = this.getOrCreateInstanceMap_(scopedId);
+ const deletedInstance = instanceMap.idWasDeleted(category, name, ts);
+ if (!deletedInstance) return;
+
+ if (deletedInstance.category !== category) {
+ const msg = 'Deleting object ' + deletedInstance.name +
+ ' with a different category ' +
+ 'than when it was created. It previous had cat=' +
+ deletedInstance.category + ' but the delete command ' +
+ 'had cat=' + category;
+ throw new Error(msg);
+ }
+ if (deletedInstance.baseTypeName !== name) {
+ throw new Error('Deletion requested for name=' +
+ name + ' could not proceed: ' +
+ 'An existing object with baseTypeName=' +
+ deletedInstance.baseTypeName + ' existed.');
+ }
+ },
+
+ autoDeleteObjects(maxTimestamp) {
+ for (const imapById of Object.values(this.instanceMapsByScopedId_)) {
+ for (const i2imap of Object.values(imapById)) {
+ const lastInstance = i2imap.lastInstance;
+ if (lastInstance.deletionTs !== Number.MAX_VALUE) continue;
+ i2imap.idWasDeleted(
+ lastInstance.category, lastInstance.name, maxTimestamp);
+ // idWasDeleted will cause lastInstance.deletionTsWasExplicit to be
+ // set to true. Unset it here.
+ lastInstance.deletionTsWasExplicit = false;
+ }
+ }
+ },
+
+ getObjectInstanceAt(scopedId, ts) {
+ let instanceMap;
+ if (scopedId.scope in this.instanceMapsByScopedId_) {
+ instanceMap = this.instanceMapsByScopedId_[scopedId.scope][scopedId.id];
+ }
+ if (!instanceMap) return undefined;
+ return instanceMap.getInstanceAt(ts);
+ },
+
+ getSnapshotAt(scopedId, ts) {
+ const instance = this.getObjectInstanceAt(scopedId, ts);
+ if (!instance) return undefined;
+ return instance.getSnapshotAt(ts);
+ },
+
+ iterObjectInstances(iter, opt_this) {
+ opt_this = opt_this || this;
+ for (const imapById of Object.values(this.instanceMapsByScopedId_)) {
+ for (const i2imap of Object.values(imapById)) {
+ i2imap.instances.forEach(iter, opt_this);
+ }
+ }
+ },
+
+ getAllObjectInstances() {
+ const instances = [];
+ this.iterObjectInstances(function(i) { instances.push(i); });
+ return instances;
+ },
+
+ getAllInstancesNamed(name) {
+ return this.instancesByTypeName_[name];
+ },
+
+ getAllInstancesByTypeName() {
+ return this.instancesByTypeName_;
+ },
+
+ preInitializeAllObjects() {
+ this.iterObjectInstances(function(instance) {
+ instance.preInitialize();
+ });
+ },
+
+ initializeAllObjects() {
+ this.iterObjectInstances(function(instance) {
+ instance.initialize();
+ });
+ },
+
+ initializeInstances() {
+ this.iterObjectInstances(function(instance) {
+ instance.initialize();
+ });
+ },
+
+ updateBounds() {
+ this.bounds.reset();
+ this.iterObjectInstances(function(instance) {
+ instance.updateBounds();
+ this.bounds.addRange(instance.bounds);
+ }, this);
+ },
+
+ shiftTimestampsForward(amount) {
+ this.iterObjectInstances(function(instance) {
+ instance.shiftTimestampsForward(amount);
+ });
+ },
+
+ addCategoriesToDict(categoriesDict) {
+ this.iterObjectInstances(function(instance) {
+ categoriesDict[instance.category] = true;
+ });
+ }
+ };
+
+ return {
+ ObjectCollection,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/object_collection_test.html b/chromium/third_party/catapult/tracing/tracing/model/object_collection_test.html
new file mode 100644
index 00000000000..a04c23ff656
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/object_collection_test.html
@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/object_collection.html">
+<link rel="import" href="/tracing/model/scoped_id.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TestObjectInstance = function(
+ parent, scopedId, category, name, creationTs) {
+ tr.model.ObjectInstance.call(
+ this, parent, scopedId, category, name, creationTs);
+ };
+
+ TestObjectInstance.prototype = {
+ __proto__: tr.model.ObjectInstance.prototype
+ };
+
+ test('objectInstanceSubtype', function() {
+ // Register that TestObjects are bound to TestObjectInstance.
+ tr.model.ObjectInstance.subTypes.register(
+ TestObjectInstance,
+ {typeName: 'TestObject'});
+
+ try {
+ const collection = new tr.model.ObjectCollection({ });
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ collection.idWasCreated(
+ scopedId, 'tr.e.cc', 'Frame', 10);
+ collection.idWasDeleted(
+ scopedId, 'tr.e.cc', 'Frame', 15);
+ collection.idWasCreated(
+ scopedId, 'skia', 'TestObject', 20);
+ collection.idWasDeleted(
+ scopedId, 'skia', 'TestObject', 25);
+
+ const testFrame = collection.getObjectInstanceAt(scopedId, 10);
+ assert.instanceOf(testFrame, tr.model.ObjectInstance);
+ assert.notInstanceOf(testFrame, TestObjectInstance);
+
+ const testObject = collection.getObjectInstanceAt(scopedId, 20);
+ assert.instanceOf(testObject, tr.model.ObjectInstance);
+ assert.instanceOf(testObject, TestObjectInstance);
+ } finally {
+ tr.model.ObjectInstance.subTypes.unregister(TestObjectInstance);
+ }
+ });
+
+ test('twoSnapshots', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ collection.idWasCreated(
+ scopedId, 'cat', 'Frame', 10);
+ collection.addSnapshot(
+ scopedId, 'cat', 'Frame', 10, {foo: 1});
+ collection.addSnapshot(
+ scopedId, 'cat', 'Frame', 20, {foo: 2});
+
+ collection.updateBounds();
+ assert.strictEqual(collection.bounds.min, 10);
+ assert.strictEqual(collection.bounds.max, 20);
+
+ const s0 = collection.getSnapshotAt(scopedId, 1);
+ assert.isUndefined(s0);
+
+ const s1 = collection.getSnapshotAt(scopedId, 10);
+ assert.strictEqual(s1.args.foo, 1);
+
+ const s2 = collection.getSnapshotAt(scopedId, 15);
+ assert.strictEqual(s2.args.foo, 1);
+ assert.strictEqual(s1, s2);
+
+ const s3 = collection.getSnapshotAt(scopedId, 20);
+ assert.strictEqual(s3.args.foo, 2);
+ assert.strictEqual(s1.object, s3.object);
+
+ const s4 = collection.getSnapshotAt(scopedId, 25);
+ assert.strictEqual(s4, s3);
+ });
+
+ test('twoObjectsSharingOneID', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ collection.idWasCreated(
+ scopedId, 'tr.e.cc', 'Frame', 10);
+ collection.idWasDeleted(
+ scopedId, 'tr.e.cc', 'Frame', 15);
+ collection.idWasCreated(
+ scopedId, 'skia', 'Picture', 20);
+ collection.idWasDeleted(
+ scopedId, 'skia', 'Picture', 25);
+
+ const frame = collection.getObjectInstanceAt(scopedId, 10);
+ assert.strictEqual(frame.category, 'tr.e.cc');
+ assert.strictEqual(frame.name, 'Frame');
+
+ const picture = collection.getObjectInstanceAt(scopedId, 20);
+ assert.strictEqual(picture.category, 'skia');
+ assert.strictEqual(picture.name, 'Picture');
+
+ const typeNames = Object.keys(collection.getAllInstancesByTypeName());
+ typeNames.sort();
+ assert.deepEqual(
+ ['Frame', 'Picture'],
+ typeNames);
+ assert.deepEqual(
+ [frame],
+ collection.getAllInstancesByTypeName().Frame);
+ assert.deepEqual(
+ [picture],
+ collection.getAllInstancesByTypeName().Picture);
+ });
+
+ test('createSnapDelete', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ collection.idWasCreated(
+ scopedId, 'cat', 'Frame', 10);
+ collection.addSnapshot(
+ scopedId, 'cat', 'Frame', 10, {foo: 1});
+ collection.idWasDeleted(
+ scopedId, 'cat', 'Frame', 15);
+
+ collection.updateBounds();
+ assert.strictEqual(collection.bounds.min, 10);
+ assert.strictEqual(collection.bounds.max, 15);
+
+ const s10 = collection.getSnapshotAt(scopedId, 10);
+ const i10 = s10.objectInstance;
+ assert.strictEqual(i10.creationTs, 10);
+ assert.strictEqual(i10.deletionTs, 15);
+ });
+
+ test('boundsOnUndeletedObject', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ collection.idWasCreated(
+ scopedId, 'cat', 'Frame', 10);
+ collection.addSnapshot(
+ scopedId, 'cat', 'Frame', 15, {foo: 1});
+
+ collection.updateBounds();
+ assert.strictEqual(10, collection.bounds.min);
+ assert.strictEqual(15, collection.bounds.max);
+ });
+
+ test('snapshotWithCustomBaseTypeThenDelete', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ const s10 = collection.addSnapshot(
+ scopedId, 'cat', 'cc::PictureLayerImpl', 10, {}, 'cc::LayerImpl');
+ collection.idWasDeleted(
+ scopedId, 'cat', 'cc::LayerImpl', 15);
+ collection.updateBounds();
+ assert.strictEqual(10, collection.bounds.min);
+ assert.strictEqual(15, collection.bounds.max);
+ assert.strictEqual(s10.objectInstance.name, 'cc::PictureLayerImpl');
+ assert.strictEqual(s10.objectInstance.baseTypeName, 'cc::LayerImpl');
+ });
+
+ test('newWithSnapshotThatChangesBaseType', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ const i10 = collection.idWasCreated(
+ scopedId, 'cat', 'cc::LayerImpl', 10);
+ const s15 = collection.addSnapshot(
+ scopedId, 'cat', 'cc::PictureLayerImpl', 15, {}, 'cc::LayerImpl');
+ collection.updateBounds();
+ assert.strictEqual(10, collection.bounds.min);
+ assert.strictEqual(15, collection.bounds.max);
+ assert.strictEqual(s15.objectInstance, i10);
+ assert.strictEqual(i10.name, 'cc::PictureLayerImpl');
+ assert.strictEqual(i10.baseTypeName, 'cc::LayerImpl');
+ });
+
+ test('deleteThenSnapshotWithCustomBase', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ collection.idWasDeleted(
+ scopedId, 'cat', 'cc::LayerImpl', 10);
+ const s15 = collection.addSnapshot(
+ scopedId, 'cat', 'cc::PictureLayerImpl', 15, {}, 'cc::LayerImpl');
+ collection.updateBounds();
+ assert.strictEqual(10, collection.bounds.min);
+ assert.strictEqual(15, collection.bounds.max);
+ assert.strictEqual(s15.objectInstance.name, 'cc::PictureLayerImpl');
+ });
+
+ test('autoDelete', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId = new tr.model.ScopedId('ptr', '0x1000');
+ collection.idWasCreated(
+ scopedId, 'cat', 'Frame', 10);
+ collection.addSnapshot(
+ scopedId, 'cat', 'Frame', 10, {foo: 1});
+ collection.autoDeleteObjects(15);
+
+ const s10 = collection.getSnapshotAt(scopedId, 10);
+ const i10 = s10.objectInstance;
+ assert.strictEqual(15, i10.deletionTs);
+ });
+
+ test('differentScopes', function() {
+ const collection = new tr.model.ObjectCollection({});
+ const scopedId1 = new tr.model.ScopedId('ptr', '0x1000');
+ const scopedId2 = new tr.model.ScopedId('cc', '0x1000');
+ collection.idWasCreated(
+ scopedId1, 'cat', 'ptr::object', 10);
+ collection.idWasDeleted(
+ scopedId1, 'cat', 'ptr::object', 15);
+ collection.idWasCreated(
+ scopedId2, 'cat', 'cc::object', 10);
+ collection.idWasDeleted(
+ scopedId2, 'cat', 'cc::object', 15);
+
+ let instance = collection.getObjectInstanceAt(scopedId1, 10);
+ assert.strictEqual(instance.name, 'ptr::object');
+
+ instance = collection.getObjectInstanceAt(scopedId2, 10);
+ assert.strictEqual(instance.name, 'cc::object');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/object_instance.html b/chromium/third_party/catapult/tracing/tracing/model/object_instance.html
new file mode 100644
index 00000000000..659ed22ad11
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/object_instance.html
@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/object_snapshot.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the ObjectSnapshot and ObjectHistory classes.
+ */
+tr.exportTo('tr.model', function() {
+ const ObjectSnapshot = tr.model.ObjectSnapshot;
+
+ /**
+ * An object with a specific id, whose state has been snapshotted several
+ * times.
+ *
+ * @constructor
+ */
+ function ObjectInstance(
+ parent, scopedId, category, name, creationTs, opt_baseTypeName) {
+ tr.model.Event.call(this);
+ this.parent = parent;
+ this.scopedId = scopedId;
+ this.category = category;
+ this.baseTypeName = opt_baseTypeName ? opt_baseTypeName : name;
+ this.name = name;
+ this.creationTs = creationTs;
+ this.creationTsWasExplicit = false;
+ this.deletionTs = Number.MAX_VALUE;
+ this.deletionTsWasExplicit = false;
+ this.colorId = 0;
+ this.bounds = new tr.b.math.Range();
+ this.snapshots = [];
+ this.hasImplicitSnapshots = false;
+ }
+
+ ObjectInstance.prototype = {
+ __proto__: tr.model.Event.prototype,
+
+ get typeName() {
+ return this.name;
+ },
+
+ addBoundsToRange(range) {
+ range.addRange(this.bounds);
+ },
+
+ addSnapshot(ts, args, opt_name, opt_baseTypeName) {
+ if (ts < this.creationTs) {
+ throw new Error('Snapshots must be >= instance.creationTs');
+ }
+ if (ts >= this.deletionTs) {
+ throw new Error('Snapshots cannot be added after ' +
+ 'an objects deletion timestamp.');
+ }
+
+ let lastSnapshot;
+ if (this.snapshots.length > 0) {
+ lastSnapshot = this.snapshots[this.snapshots.length - 1];
+ if (lastSnapshot.ts === ts) {
+ throw new Error('Snapshots already exists at this time!');
+ }
+ if (ts < lastSnapshot.ts) {
+ throw new Error(
+ 'Snapshots must be added in increasing timestamp order');
+ }
+ }
+
+ // Update baseTypeName if needed.
+ if (opt_name &&
+ (this.name !== opt_name)) {
+ if (!opt_baseTypeName) {
+ throw new Error('Must provide base type name for name update');
+ }
+ if (this.baseTypeName !== opt_baseTypeName) {
+ throw new Error('Cannot update type name: base types dont match');
+ }
+ this.name = opt_name;
+ }
+
+ const snapshotConstructor =
+ tr.model.ObjectSnapshot.subTypes.getConstructor(
+ this.category, this.name);
+ const snapshot = new snapshotConstructor(this, ts, args);
+ this.snapshots.push(snapshot);
+ return snapshot;
+ },
+
+ wasDeleted(ts) {
+ let lastSnapshot;
+ if (this.snapshots.length > 0) {
+ lastSnapshot = this.snapshots[this.snapshots.length - 1];
+ if (lastSnapshot.ts > ts) {
+ throw new Error(
+ 'Instance cannot be deleted at ts=' +
+ ts + '. A snapshot exists that is older.');
+ }
+ }
+ this.deletionTs = ts;
+ this.deletionTsWasExplicit = true;
+ },
+
+ /**
+ * See ObjectSnapshot constructor notes on object initialization.
+ */
+ preInitialize() {
+ for (let i = 0; i < this.snapshots.length; i++) {
+ this.snapshots[i].preInitialize();
+ }
+ },
+
+ /**
+ * See ObjectSnapshot constructor notes on object initialization.
+ */
+ initialize() {
+ for (let i = 0; i < this.snapshots.length; i++) {
+ this.snapshots[i].initialize();
+ }
+ },
+
+ isAliveAt(ts) {
+ if (ts < this.creationTs && this.creationTsWasExplicit) {
+ return false;
+ }
+ if (ts > this.deletionTs) {
+ return false;
+ }
+
+ return true;
+ },
+
+ getSnapshotAt(ts) {
+ if (ts < this.creationTs) {
+ if (this.creationTsWasExplicit) {
+ throw new Error('ts must be within lifetime of this instance');
+ }
+ return this.snapshots[0];
+ }
+ if (ts > this.deletionTs) {
+ throw new Error('ts must be within lifetime of this instance');
+ }
+
+ const snapshots = this.snapshots;
+ const i = tr.b.findIndexInSortedIntervals(
+ snapshots,
+ function(snapshot) { return snapshot.ts; },
+ function(snapshot, i) {
+ if (i === snapshots.length - 1) {
+ return snapshots[i].objectInstance.deletionTs;
+ }
+ return snapshots[i + 1].ts - snapshots[i].ts;
+ },
+ ts);
+ if (i < 0) {
+ // Note, this is a little bit sketchy: this lets early ts point at the
+ // first snapshot, even before it is taken. We do this because raster
+ // tasks usually post before their tile snapshots are dumped. This may
+ // be a good line of code to re-visit if we start seeing strange and
+ // confusing object references showing up in the traces.
+ return this.snapshots[0];
+ }
+ if (i >= this.snapshots.length) {
+ return this.snapshots[this.snapshots.length - 1];
+ }
+ return this.snapshots[i];
+ },
+
+ updateBounds() {
+ this.bounds.reset();
+ this.bounds.addValue(this.creationTs);
+ if (this.deletionTs !== Number.MAX_VALUE) {
+ this.bounds.addValue(this.deletionTs);
+ } else if (this.snapshots.length > 0) {
+ this.bounds.addValue(this.snapshots[this.snapshots.length - 1].ts);
+ }
+ },
+
+ shiftTimestampsForward(amount) {
+ this.creationTs += amount;
+ if (this.deletionTs !== Number.MAX_VALUE) {
+ this.deletionTs += amount;
+ }
+ this.snapshots.forEach(function(snapshot) {
+ snapshot.ts += amount;
+ });
+ },
+
+ get userFriendlyName() {
+ return this.typeName + ' object ' + this.scopedId;
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ ObjectInstance,
+ {
+ name: 'objectInstance',
+ pluralName: 'objectInstances'
+ });
+
+ return {
+ ObjectInstance,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/object_instance_test.html b/chromium/third_party/catapult/tracing/tracing/model/object_instance_test.html
new file mode 100644
index 00000000000..703e98d37c0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/object_instance_test.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('getSnapshotAtWithImplicitCreation', function() {
+ const instance = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'n', 10);
+ let s10 = instance.addSnapshot(10, 'a');
+ instance.addSnapshot(40, 'b');
+ instance.wasDeleted(60);
+
+ const s1 = instance.getSnapshotAt(1);
+ assert.strictEqual(s1, s10);
+
+ s10 = instance.getSnapshotAt(10);
+ assert.strictEqual(s10.args, 'a');
+ assert.strictEqual(instance.getSnapshotAt(15), s10);
+
+ const s40 = instance.getSnapshotAt(40);
+ assert.strictEqual(s40.args, 'b');
+ assert.strictEqual(instance.getSnapshotAt(50), s40);
+ assert.strictEqual(instance.getSnapshotAt(59.9), s40);
+ });
+
+ test('getSnapshotAtWithExplicitCreation', function() {
+ const instance = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'n', 10);
+ instance.creationTsWasExplicit = true;
+ instance.addSnapshot(10, 'a');
+ instance.wasDeleted(60);
+
+ assert.throws(function() {
+ instance.getSnapshotAt(1);
+ });
+
+ const s10 = instance.getSnapshotAt(10);
+ assert.strictEqual(s10.args, 'a');
+ assert.strictEqual(instance.getSnapshotAt(15), s10);
+ });
+
+ test('getSnapshotBeforeFirstSnapshot', function() {
+ const instance = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'n', 10);
+ const s15 = instance.addSnapshot(15, 'a');
+ instance.wasDeleted(40);
+
+ assert.strictEqual(instance.getSnapshotAt(10), s15);
+ });
+
+ test('getSnapshotAfterLastSnapshot', function() {
+ const instance = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'n', 10);
+ const s15 = instance.addSnapshot(15, 'a');
+ instance.wasDeleted(40);
+
+ assert.strictEqual(instance.getSnapshotAt(20), s15);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/object_snapshot.html b/chromium/third_party/catapult/tracing/tracing/model/object_snapshot.html
new file mode 100644
index 00000000000..09678f34a45
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/object_snapshot.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/event.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * A snapshot of an object instance, at a given moment in time.
+ *
+ * Initialization of snapshots and instances is three phased:
+ *
+ * 1. Instances and snapshots are constructed. This happens during event
+ * importing. Little should be done here, because the object's data
+ * are still being used by the importer to reconstruct object references.
+ *
+ * 2. Instances and snapshtos are preinitialized. This happens after implicit
+ * objects have been found, but before any references have been found and
+ * switched to direct references. Thus, every snapshot stands on its own.
+ * This is a good time to do global field renaming and type conversion,
+ * e.g. recognizing domain-specific types and converting from C++ naming
+ * convention to JS.
+ *
+ * 3. Instances and snapshtos are initialized. At this point, {id_ref:
+ * '0x1000'} fields have been converted to snapshot references. This is a
+ * good time to generic initialization steps and argument verification.
+ *
+ * @constructor
+ */
+ function ObjectSnapshot(objectInstance, ts, args) {
+ tr.model.Event.call(this);
+ this.objectInstance = objectInstance;
+ this.ts = ts;
+ this.args = args;
+ }
+
+ ObjectSnapshot.prototype = {
+ __proto__: tr.model.Event.prototype,
+
+ /**
+ * See ObjectSnapshot constructor notes on object initialization.
+ */
+ preInitialize() {
+ },
+
+ /**
+ * See ObjectSnapshot constructor notes on object initialization.
+ */
+ initialize() {
+ },
+
+ /**
+ * Called when an object reference is resolved as this ObjectSnapshot.
+ * @param {Object} item The event (async slice, slice or object) containing
+ * the resolved reference.
+ * @param {Object} object The object directly containing the reference.
+ * @param {String} field The field name of the reference in |object|.
+ */
+ referencedAt(item, object, field) {
+ },
+
+ addBoundsToRange(range) {
+ range.addValue(this.ts);
+ },
+
+ get userFriendlyName() {
+ return 'Snapshot of ' + this.objectInstance.userFriendlyName + ' @ ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.ts);
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ ObjectSnapshot,
+ {
+ name: 'objectSnapshot',
+ pluralName: 'objectSnapshots'
+ });
+
+ return {
+ ObjectSnapshot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/object_snapshot_test.html b/chromium/third_party/catapult/tracing/tracing/model/object_snapshot_test.html
new file mode 100644
index 00000000000..c026851e5aa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/object_snapshot_test.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/object_instance.html">
+<link rel="import" href="/tracing/model/object_snapshot.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('snapshotTypeRegistry', function() {
+ function MySnapshot() {
+ tr.model.ObjectSnapshot.apply(this, arguments);
+ this.myFoo = this.args.foo;
+ }
+
+ MySnapshot.prototype = {
+ __proto__: tr.model.ObjectSnapshot.prototype
+ };
+
+ const instance = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'MySnapshot', 10);
+ try {
+ tr.model.ObjectSnapshot.subTypes.register(
+ MySnapshot,
+ {typeName: 'MySnapshot'});
+ const snapshot = instance.addSnapshot(15, {foo: 'bar'});
+ assert.instanceOf(snapshot, MySnapshot);
+ assert.strictEqual(snapshot.myFoo, 'bar');
+ } finally {
+ tr.model.ObjectSnapshot.subTypes.unregister(MySnapshot);
+ }
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/power_sample.html b/chromium/third_party/catapult/tracing/tracing/model/power_sample.html
new file mode 100644
index 00000000000..b9816f76159
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/power_sample.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/event_registry.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const Event = tr.model.Event;
+ const EventRegistry = tr.model.EventRegistry;
+
+ /**
+ * A sample that contains a power measurement (in W).
+ *
+ * @constructor
+ * @extends {Event}
+ */
+ function PowerSample(series, start, powerInW) {
+ Event.call(this);
+
+ this.series_ = series;
+ this.start_ = parseFloat(start);
+ this.powerInW_ = parseFloat(powerInW);
+ }
+
+ PowerSample.prototype = {
+ __proto__: Event.prototype,
+
+ get series() {
+ return this.series_;
+ },
+
+ get start() {
+ return this.start_;
+ },
+
+ set start(value) {
+ this.start_ = value;
+ },
+
+ get powerInW() {
+ return this.powerInW_;
+ },
+
+ set powerInW(value) {
+ this.powerInW_ = value;
+ },
+
+ addBoundsToRange(range) {
+ range.addValue(this.start);
+ }
+ };
+
+ EventRegistry.register(
+ PowerSample,
+ {
+ name: 'powerSample',
+ pluralName: 'powerSamples'
+ });
+
+ return {
+ PowerSample,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/power_sample_test.html b/chromium/third_party/catapult/tracing/tracing/model/power_sample_test.html
new file mode 100644
index 00000000000..ebed90bd2b5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/power_sample_test.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_sample.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const PowerSample = tr.model.PowerSample;
+
+ test('powerSample', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const sample1 = new PowerSample(series, 0.0, 1000.0);
+ const sample2 = new PowerSample(series, 1.0, 2000.0);
+
+ assert.strictEqual(sample1.series, series);
+ assert.strictEqual(sample1.start, 0.0);
+ assert.strictEqual(sample1.powerInW, 1000.0);
+
+ assert.strictEqual(sample2.series, series);
+ assert.strictEqual(sample2.start, 1.0);
+ assert.strictEqual(sample2.powerInW, 2000.0);
+ });
+
+ test('addBoundsToRange', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const sample1 = new PowerSample(series, 0.0, 1000.0);
+ const sample2 = new PowerSample(series, 1.0, 2000.0);
+
+ const range = new tr.b.math.Range();
+ sample1.addBoundsToRange(range);
+
+ assert.strictEqual(range.min, 0);
+ assert.strictEqual(range.max, 0);
+
+ sample2.addBoundsToRange(range);
+
+ assert.strictEqual(range.min, 0);
+ assert.strictEqual(range.max, 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/power_series.html b/chromium/third_party/catapult/tracing/tracing/model/power_series.html
new file mode 100644
index 00000000000..c496b1e4810
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/power_series.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/power_sample.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const PowerSample = tr.model.PowerSample;
+
+ /**
+ * A container holding a time series of power samples.
+ *
+ * @constructor
+ * @extends {EventContainer}
+ */
+ function PowerSeries(device) {
+ tr.model.EventContainer.call(this);
+
+ this.device_ = device;
+ this.samples_ = [];
+ }
+
+ PowerSeries.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ get device() {
+ return this.device_;
+ },
+
+ get samples() {
+ return this.samples_;
+ },
+
+ get stableId() {
+ return this.device_.stableId + '.PowerSeries';
+ },
+
+ /**
+ * Adds a power sample to the series and returns it.
+ *
+ * Note: Samples must be added in chronological order.
+ */
+ addPowerSample(ts, val) {
+ const sample = new PowerSample(this, ts, val);
+ this.samples_.push(sample);
+ return sample;
+ },
+
+ /**
+ * Returns the total energy (in Joules) consumed between the specified
+ * start and end timestamps (in milliseconds).
+ */
+ getEnergyConsumedInJ(start, end) {
+ const measurementRange = tr.b.math.Range.fromExplicitRange(start, end);
+
+ let energyConsumedInJ = 0;
+ let startIndex = tr.b.findLowIndexInSortedArray(
+ this.samples, x => x.start, start) - 1;
+ const endIndex = tr.b.findLowIndexInSortedArray(
+ this.samples, x => x.start, end);
+
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+
+ for (let i = startIndex; i < endIndex; i++) {
+ const sample = this.samples[i];
+ const nextSample = this.samples[i + 1];
+
+ const sampleRange = new tr.b.math.Range();
+ sampleRange.addValue(sample.start);
+ sampleRange.addValue(nextSample ? nextSample.start : sample.start);
+
+ const intersectionRangeInMs = measurementRange.findIntersection(
+ sampleRange);
+
+ const durationInS = tr.b.convertUnit(intersectionRangeInMs.duration,
+ tr.b.UnitPrefixScale.METRIC.MILLI,
+ tr.b.UnitPrefixScale.METRIC.NONE);
+
+ energyConsumedInJ += durationInS * sample.powerInW;
+ }
+
+ return energyConsumedInJ;
+ },
+
+ getSamplesWithinRange(start, end) {
+ const startIndex = tr.b.findLowIndexInSortedArray(
+ this.samples, x => x.start, start);
+ const endIndex = tr.b.findLowIndexInSortedArray(
+ this.samples, x => x.start, end);
+ return this.samples.slice(startIndex, endIndex);
+ },
+
+ shiftTimestampsForward(amount) {
+ for (let i = 0; i < this.samples_.length; ++i) {
+ this.samples_[i].start += amount;
+ }
+ },
+
+ updateBounds() {
+ this.bounds.reset();
+
+ if (this.samples_.length === 0) return;
+
+ this.bounds.addValue(this.samples_[0].start);
+ this.bounds.addValue(this.samples_[this.samples_.length - 1].start);
+ },
+
+ * childEvents() {
+ yield* this.samples_;
+ },
+ };
+
+ return {
+ PowerSeries,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/power_series_test.html b/chromium/third_party/catapult/tracing/tracing/model/power_series_test.html
new file mode 100644
index 00000000000..aa1e1c46d54
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/power_series_test.html
@@ -0,0 +1,151 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/device.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_series.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const PowerSeries = tr.model.PowerSeries;
+
+ test('stableId', function() {
+ const device = { stableId: 'test' };
+ const series = new PowerSeries(device);
+
+ assert.strictEqual(series.stableId, 'test.PowerSeries');
+ });
+
+ test('device', function() {
+ const device = new tr.model.Device(new Model());
+ const series = new PowerSeries(device);
+
+ assert.strictEqual(series.device, device);
+ });
+
+ test('addPowerSample', function() {
+ const series = new PowerSeries(new Model().device);
+
+ assert.strictEqual(series.samples.length, 0);
+
+ const sample1 = series.addPowerSample(0, 1);
+ const sample2 = series.addPowerSample(1, 2);
+
+ assert.deepEqual(series.samples, [sample1, sample2]);
+ });
+
+ test('getEnergyConsumed_oneInterval', function() {
+ const series = new PowerSeries(new Model().device);
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1000, 2);
+
+ assert.strictEqual(series.getEnergyConsumedInJ(0, 1000), 1);
+ });
+
+ test('getEnergyConsumed_twoIntervals', function() {
+ const series = new PowerSeries(new Model().device);
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1000, 2);
+ series.addPowerSample(2000, 2);
+
+ assert.strictEqual(series.getEnergyConsumedInJ(0, 2000), 3);
+ });
+
+ test('getEnergyConsumed_oneSample', function() {
+ const series = new PowerSeries(new Model().device);
+ series.addPowerSample(1000, 1);
+
+ assert.strictEqual(series.getEnergyConsumedInJ(0, 2000), 0);
+ });
+
+ test('getEnergyConsumed_samplesAfterStart', function() {
+ const series = new PowerSeries(new Model().device);
+ series.addPowerSample(1000, 1);
+ series.addPowerSample(2000, 2);
+
+ assert.strictEqual(series.getEnergyConsumedInJ(0, 2000), 1);
+ });
+
+ test('getEnergyConsumed_extraSamplesBeforeStart', function() {
+ const series = new PowerSeries(new Model().device);
+ series.addPowerSample(0, 10);
+ series.addPowerSample(1000, 1);
+ series.addPowerSample(2000, 1);
+ series.addPowerSample(3000, 1);
+
+ assert.strictEqual(series.getEnergyConsumedInJ(2000, 4000), 1);
+ });
+
+ test('getEnergyConsumed_extraSamplesAfterEnd', function() {
+ const series = new PowerSeries(new Model().device);
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1000, 1);
+ series.addPowerSample(2000, 1);
+ series.addPowerSample(3000, 10);
+
+ assert.strictEqual(series.getEnergyConsumedInJ(0, 2000), 2);
+ });
+
+ test('shiftTimestampsForward', function() {
+ const series = new PowerSeries(new Model().device);
+
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+
+ series.shiftTimestampsForward(2);
+
+ assert.strictEqual(series.samples[0].start, 2);
+ assert.strictEqual(series.samples[1].start, 3);
+
+ series.shiftTimestampsForward(-4);
+
+ assert.strictEqual(series.samples[0].start, -2);
+ assert.strictEqual(series.samples[1].start, -1);
+ });
+
+
+ test('updateBounds', function() {
+ const series = new PowerSeries(new Model().device);
+
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.updateBounds();
+
+ assert.strictEqual(series.bounds.min, 0);
+ assert.strictEqual(series.bounds.max, 1);
+
+ series.addPowerSample(4, 3);
+ series.updateBounds();
+
+ assert.strictEqual(series.bounds.min, 0);
+ assert.strictEqual(series.bounds.max, 4);
+ });
+
+ test('childEvents_empty', function() {
+ const series = new PowerSeries(new Model().device);
+ const eventsInSeries = [];
+ for (const event of series.childEvents()) {
+ eventsInSeries.push(event);
+ }
+ assert.deepEqual(eventsInSeries, []);
+ });
+
+ test('childEvents_nonempty', function() {
+ const series = new PowerSeries(new Model().device);
+ const sample1 = series.addPowerSample(0, 1);
+ const sample2 = series.addPowerSample(1, 2);
+ const eventsInSeries = [];
+ for (const event of series.childEvents()) {
+ eventsInSeries.push(event);
+ }
+ assert.deepEqual(eventsInSeries, [sample1, sample2]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/process.html b/chromium/third_party/catapult/tracing/tracing/model/process.html
new file mode 100644
index 00000000000..facaa3b1923
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/process.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/process_base.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Process class.
+ */
+tr.exportTo('tr.model', function() {
+ const ProcessBase = tr.model.ProcessBase;
+ const ProcessInstantEvent = tr.model.ProcessInstantEvent;
+ const Frame = tr.model.Frame;
+ const ProcessMemoryDump = tr.model.ProcessMemoryDump;
+
+ /**
+ * The Process represents a single userland process in the
+ * trace.
+ * @constructor
+ */
+ function Process(model, pid) {
+ if (model === undefined) {
+ throw new Error('model must be provided');
+ }
+ if (pid === undefined) {
+ throw new Error('pid must be provided');
+ }
+ tr.model.ProcessBase.call(this, model);
+ this.pid = pid;
+ this.name = undefined;
+ this.labels = [];
+ this.uptime_seconds = 0;
+ this.instantEvents = [];
+ this.memoryDumps = [];
+ this.frames = [];
+ this.activities = [];
+ }
+
+ /**
+ * Comparison between processes that orders by pid.
+ */
+ Process.compare = function(x, y) {
+ let tmp = tr.model.ProcessBase.compare(x, y);
+ if (tmp) return tmp;
+
+ if (x.name !== undefined) {
+ if (y.name !== undefined) {
+ tmp = x.name.localeCompare(y.name);
+ } else {
+ tmp = -1;
+ }
+ } else if (y.name !== undefined) {
+ tmp = 1;
+ }
+ if (tmp) return tmp;
+
+ tmp = tr.b.compareArrays(x.labels, y.labels,
+ function(x, y) { return x.localeCompare(y); });
+ if (tmp) return tmp;
+
+ return x.pid - y.pid;
+ };
+
+ Process.prototype = {
+ __proto__: tr.model.ProcessBase.prototype,
+
+ get stableId() {
+ return this.pid;
+ },
+
+ compareTo(that) {
+ return Process.compare(this, that);
+ },
+
+ * childEvents() {
+ yield* ProcessBase.prototype.childEvents.call(this);
+ yield* this.instantEvents;
+ yield* this.frames;
+ yield* this.memoryDumps;
+ },
+
+ addLabelIfNeeded(labelName) {
+ for (let i = 0; i < this.labels.length; i++) {
+ if (this.labels[i] === labelName) return;
+ }
+ this.labels.push(labelName);
+ },
+
+ get userFriendlyName() {
+ let res;
+ if (this.name) {
+ res = this.name + ' (pid ' + this.pid + ')';
+ } else {
+ res = 'Process ' + this.pid;
+ }
+ if (this.labels.length) {
+ res += ': ' + this.labels.join(', ');
+ }
+ if (this.uptime_seconds) {
+ res += ', uptime:' + this.uptime_seconds + 's';
+ }
+ return res;
+ },
+
+ get userFriendlyDetails() {
+ if (this.name) {
+ return this.name + ' (pid ' + this.pid + ')';
+ }
+ return 'pid: ' + this.pid;
+ },
+
+ getSettingsKey() {
+ if (!this.name) return undefined;
+ if (!this.labels.length) return 'processes.' + this.name;
+ return 'processes.' + this.name + '.' + this.labels.join('.');
+ },
+
+ shiftTimestampsForward(amount) {
+ for (let i = 0; i < this.instantEvents.length; i++) {
+ this.instantEvents[i].start += amount;
+ }
+
+ for (let i = 0; i < this.frames.length; i++) {
+ this.frames[i].shiftTimestampsForward(amount);
+ }
+
+ for (let i = 0; i < this.memoryDumps.length; i++) {
+ this.memoryDumps[i].shiftTimestampsForward(amount);
+ }
+
+ for (let i = 0; i < this.activities.length; i++) {
+ this.activities[i].shiftTimestampsForward(amount);
+ }
+
+ tr.model.ProcessBase.prototype
+ .shiftTimestampsForward.apply(this, arguments);
+ },
+
+ updateBounds() {
+ tr.model.ProcessBase.prototype.updateBounds.apply(this);
+
+ for (let i = 0; i < this.frames.length; i++) {
+ this.frames[i].addBoundsToRange(this.bounds);
+ }
+
+ for (let i = 0; i < this.memoryDumps.length; i++) {
+ this.memoryDumps[i].addBoundsToRange(this.bounds);
+ }
+
+ for (let i = 0; i < this.activities.length; i++) {
+ this.activities[i].addBoundsToRange(this.bounds);
+ }
+ },
+
+ sortMemoryDumps() {
+ this.memoryDumps.sort(function(x, y) {
+ return x.start - y.start;
+ });
+ tr.model.ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(
+ this.memoryDumps);
+ }
+ };
+
+ return {
+ Process,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/process_base.html b/chromium/third_party/catapult/tracing/tracing/model/process_base.html
new file mode 100644
index 00000000000..8ba031a764c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/process_base.html
@@ -0,0 +1,244 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/counter.html">
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/object_collection.html">
+<link rel="import" href="/tracing/model/thread.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the ProcessBase class.
+ */
+tr.exportTo('tr.model', function() {
+ const Thread = tr.model.Thread;
+ const Counter = tr.model.Counter;
+
+ /**
+ * The ProcessBase is a partial base class, upon which Kernel
+ * and Process are built.
+ *
+ * @constructor
+ * @extends {tr.model.EventContainer}
+ */
+ function ProcessBase(model) {
+ if (!model) {
+ throw new Error('Must provide a model');
+ }
+ tr.model.EventContainer.call(this);
+ this.model = model;
+ this.threads = {};
+ this.counters = {};
+ this.objects = new tr.model.ObjectCollection(this);
+ this.sortIndex = 0;
+ }
+
+ ProcessBase.compare = function(x, y) {
+ return x.sortIndex - y.sortIndex;
+ };
+
+ ProcessBase.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ get stableId() {
+ throw new Error('Not implemented');
+ },
+
+ * childEventContainers() {
+ yield* Object.values(this.threads);
+ yield* Object.values(this.counters);
+ yield this.objects;
+ },
+
+ iterateAllPersistableObjects(cb) {
+ cb(this);
+ for (const tid in this.threads) {
+ this.threads[tid].iterateAllPersistableObjects(cb);
+ }
+ },
+
+ /**
+ * Gets the number of threads in this process.
+ */
+ get numThreads() {
+ let n = 0;
+ for (const p in this.threads) {
+ n++;
+ }
+ return n;
+ },
+
+ /**
+ * Shifts all the timestamps inside this process forward by the amount
+ * specified.
+ */
+ shiftTimestampsForward(amount) {
+ for (const child of this.childEventContainers()) {
+ child.shiftTimestampsForward(amount);
+ }
+ },
+
+ /**
+ * Closes any open slices.
+ */
+ autoCloseOpenSlices() {
+ for (const tid in this.threads) {
+ const thread = this.threads[tid];
+ thread.autoCloseOpenSlices();
+ }
+ },
+
+ autoDeleteObjects(maxTimestamp) {
+ this.objects.autoDeleteObjects(maxTimestamp);
+ },
+
+ /**
+ * Called by the model after finalizing imports,
+ * but before joining refs.
+ */
+ preInitializeObjects() {
+ this.objects.preInitializeAllObjects();
+ },
+
+ /**
+ * Called by the model after joining refs.
+ */
+ initializeObjects() {
+ this.objects.initializeAllObjects();
+ },
+
+ /**
+ * Merge slices from the kernel with those from userland for each thread.
+ */
+ mergeKernelWithUserland() {
+ for (const tid in this.threads) {
+ const thread = this.threads[tid];
+ thread.mergeKernelWithUserland();
+ }
+ },
+
+ updateBounds() {
+ this.bounds.reset();
+ for (const tid in this.threads) {
+ this.threads[tid].updateBounds();
+ this.bounds.addRange(this.threads[tid].bounds);
+ }
+ for (const id in this.counters) {
+ this.counters[id].updateBounds();
+ this.bounds.addRange(this.counters[id].bounds);
+ }
+ this.objects.updateBounds();
+ this.bounds.addRange(this.objects.bounds);
+ },
+
+ addCategoriesToDict(categoriesDict) {
+ for (const tid in this.threads) {
+ this.threads[tid].addCategoriesToDict(categoriesDict);
+ }
+ for (const id in this.counters) {
+ categoriesDict[this.counters[id].category] = true;
+ }
+ this.objects.addCategoriesToDict(categoriesDict);
+ },
+
+ findAllThreadsMatching(predicate, opt_this) {
+ const threads = [];
+ for (const tid in this.threads) {
+ const thread = this.threads[tid];
+ if (predicate.call(opt_this, thread)) {
+ threads.push(thread);
+ }
+ }
+ return threads;
+ },
+
+ /**
+ * @param {String} The name of the thread to find.
+ * @return {Array} An array of all the matched threads.
+ */
+ findAllThreadsNamed(name) {
+ const threads = this.findAllThreadsMatching(function(thread) {
+ if (!thread.name) return false;
+ return thread.name === name;
+ });
+ return threads;
+ },
+
+ findAtMostOneThreadNamed(name) {
+ const threads = this.findAllThreadsNamed(name);
+ if (threads.length === 0) return undefined;
+ if (threads.length > 1) {
+ throw new Error('Expected no more than one ' + name);
+ }
+ return threads[0];
+ },
+
+ /**
+ * Removes threads from the process that are fully empty.
+ */
+ pruneEmptyContainers() {
+ const threadsToKeep = {};
+ for (const tid in this.threads) {
+ const thread = this.threads[tid];
+ if (!thread.isEmpty) {
+ threadsToKeep[tid] = thread;
+ }
+ }
+ this.threads = threadsToKeep;
+ },
+
+ /**
+ * @return {TimelineThread} The thread identified by tid on this process,
+ * or undefined if it doesn't exist.
+ */
+ getThread(tid) {
+ return this.threads[tid];
+ },
+
+ /**
+ * @return {TimelineThread} The thread identified by tid on this process,
+ * creating it if it doesn't exist.
+ */
+ getOrCreateThread(tid) {
+ if (!this.threads[tid]) {
+ this.threads[tid] = new Thread(this, tid);
+ }
+ return this.threads[tid];
+ },
+
+ /**
+ * @return {Counter} The counter on this process with the given
+ * category/name combination, creating it if it doesn't exist.
+ */
+ getOrCreateCounter(cat, name) {
+ const id = cat + '.' + name;
+ if (!this.counters[id]) {
+ this.counters[id] = new Counter(this, id, cat, name);
+ }
+ return this.counters[id];
+ },
+
+ getSettingsKey() {
+ throw new Error('Not implemented');
+ },
+
+ createSubSlices() {
+ for (const tid in this.threads) {
+ this.threads[tid].createSubSlices();
+ }
+ }
+ };
+
+ return {
+ ProcessBase,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/process_memory_dump.html b/chromium/third_party/catapult/tracing/tracing/model/process_memory_dump.html
new file mode 100644
index 00000000000..1c9248e6eaf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/process_memory_dump.html
@@ -0,0 +1,247 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the ProcessMemoryDump class.
+ */
+tr.exportTo('tr.model', function() {
+ // Names of MemoryAllocatorDump(s) from which tracing overhead should be
+ // discounted.
+ const DISCOUNTED_ALLOCATOR_NAMES = ['winheap', 'malloc'];
+
+ // The path to where the tracing overhead dump should be added to the
+ // winheap/malloc allocator dump tree.
+ const TRACING_OVERHEAD_PATH = ['allocated_objects', 'tracing_overhead'];
+
+ const SIZE_NUMERIC_NAME = tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME;
+ const RESIDENT_SIZE_NUMERIC_NAME =
+ tr.model.MemoryAllocatorDump.RESIDENT_SIZE_NUMERIC_NAME;
+
+ function getSizeNumericValue(dump, sizeNumericName) {
+ const sizeNumeric = dump.numerics[sizeNumericName];
+ if (sizeNumeric === undefined) return 0;
+ return sizeNumeric.value;
+ }
+
+ /**
+ * The ProcessMemoryDump represents a memory dump of a single process.
+ * @constructor
+ */
+ function ProcessMemoryDump(globalMemoryDump, process, start) {
+ tr.model.ContainerMemoryDump.call(this, start);
+ this.process = process;
+ this.globalMemoryDump = globalMemoryDump;
+
+ // Process memory totals (optional object) with the following fields (also
+ // optional):
+ // - residentBytes: Total resident bytes (number)
+ // - peakResidentBytes: Peak resident bytes (number)
+ // - arePeakResidentBytesResettable: Flag whether peak resident bytes are
+ // resettable (boolean)
+ // - privateFootprintBytes: Private footprint bytes (number)
+ // - platformSpecific: Map from OS-specific total names (string) to sizes
+ // (number)
+ this.totals = undefined;
+
+ this.vmRegions = undefined;
+
+ // Map from allocator names to heap dumps.
+ this.heapDumps = undefined;
+
+ this.tracingOverheadOwnershipSetUp_ = false;
+ this.tracingOverheadDiscountedFromVmRegions_ = false;
+ }
+
+ ProcessMemoryDump.prototype = {
+ __proto__: tr.model.ContainerMemoryDump.prototype,
+
+ get userFriendlyName() {
+ return 'Process memory dump at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.start);
+ },
+
+ get containerName() {
+ return this.process.userFriendlyName;
+ },
+
+ get processMemoryDumps() {
+ const dumps = {};
+ dumps[this.process.pid] = this;
+ return dumps;
+ },
+
+ get hasOwnVmRegions() {
+ return this.vmRegions !== undefined;
+ },
+
+ setUpTracingOverheadOwnership(opt_model) {
+ // Make sure that calling this method twice won't lead to
+ // 'double-discounting'.
+ if (this.tracingOverheadOwnershipSetUp_) return;
+
+ this.tracingOverheadOwnershipSetUp_ = true;
+
+ const tracingDump = this.getMemoryAllocatorDumpByFullName('tracing');
+ if (tracingDump === undefined || tracingDump.owns !== undefined) {
+ // The tracing dump either doesn't exist, or it already owns another
+ // dump.
+ return;
+ }
+
+ if (tracingDump.owns !== undefined) return;
+
+ // Add an ownership link from tracing to
+ // malloc/allocated_objects/tracing_overhead or
+ // winheap/allocated_objects/tracing_overhead.
+ const hasDiscountedFromAllocatorDumps = DISCOUNTED_ALLOCATOR_NAMES.some(
+ function(allocatorName) {
+ // First check if the allocator root exists.
+ const allocatorDump = this.getMemoryAllocatorDumpByFullName(
+ allocatorName);
+ if (allocatorDump === undefined) {
+ return false; // Allocator doesn't exist, try another one.
+ }
+
+ let nextPathIndex = 0;
+ let currentDump = allocatorDump;
+ let currentFullName = allocatorName;
+
+ // Descend from the root towards tracing_overhead as long as the
+ // dumps on the path exist.
+ for (; nextPathIndex < TRACING_OVERHEAD_PATH.length;
+ nextPathIndex++) {
+ const childFullName = currentFullName + '/' +
+ TRACING_OVERHEAD_PATH[nextPathIndex];
+ const childDump = this.getMemoryAllocatorDumpByFullName(
+ childFullName);
+ if (childDump === undefined) break;
+
+ currentDump = childDump;
+ currentFullName = childFullName;
+ }
+
+ // Create the missing descendant dumps on the path from the root
+ // towards tracing_overhead.
+ for (; nextPathIndex < TRACING_OVERHEAD_PATH.length;
+ nextPathIndex++) {
+ const childFullName = currentFullName + '/' +
+ TRACING_OVERHEAD_PATH[nextPathIndex];
+ const childDump = new tr.model.MemoryAllocatorDump(
+ currentDump.containerMemoryDump, childFullName);
+ childDump.parent = currentDump;
+ currentDump.children.push(childDump);
+
+ currentFullName = childFullName;
+ currentDump = childDump;
+ }
+
+ // Add the ownership link.
+ const ownershipLink =
+ new tr.model.MemoryAllocatorDumpLink(tracingDump, currentDump);
+ tracingDump.owns = ownershipLink;
+ currentDump.ownedBy.push(ownershipLink);
+ return true;
+ }, this);
+
+ // Force rebuilding the memory allocator dump index (if we've just added
+ // a new memory allocator dump).
+ if (hasDiscountedFromAllocatorDumps) {
+ this.forceRebuildingMemoryAllocatorDumpByFullNameIndex();
+ }
+ },
+
+ discountTracingOverheadFromVmRegions(opt_model) {
+ // Make sure that calling this method twice won't lead to
+ // 'double-discounting'.
+ if (this.tracingOverheadDiscountedFromVmRegions_) return;
+ this.tracingOverheadDiscountedFromVmRegions_ = true;
+
+ const tracingDump = this.getMemoryAllocatorDumpByFullName('tracing');
+ if (tracingDump === undefined) return;
+
+ const discountedSize =
+ getSizeNumericValue(tracingDump, SIZE_NUMERIC_NAME);
+ const discountedResidentSize =
+ getSizeNumericValue(tracingDump, RESIDENT_SIZE_NUMERIC_NAME);
+
+ if (discountedSize <= 0 && discountedResidentSize <= 0) return;
+
+ // Subtract the tracing size from the totals.
+ if (this.totals !== undefined) {
+ if (this.totals.residentBytes !== undefined) {
+ this.totals.residentBytes -= discountedResidentSize;
+ }
+ if (this.totals.peakResidentBytes !== undefined) {
+ this.totals.peakResidentBytes -= discountedResidentSize;
+ }
+ }
+
+ // Subtract the tracing size from VM regions. More precisely, subtract
+ // tracing resident_size from byte stats (private dirty and PSS) and
+ // tracing size from virtual size by injecting a fake VM region with
+ // negative values.
+ if (this.vmRegions !== undefined) {
+ const hasSizeInBytes = this.vmRegions.sizeInBytes !== undefined;
+ const hasPrivateDirtyResident =
+ this.vmRegions.byteStats.privateDirtyResident !== undefined;
+ const hasProportionalResident =
+ this.vmRegions.byteStats.proportionalResident !== undefined;
+
+ if ((hasSizeInBytes && discountedSize > 0) ||
+ ((hasPrivateDirtyResident || hasProportionalResident) &&
+ discountedResidentSize > 0)) {
+ const byteStats = {};
+ if (hasPrivateDirtyResident) {
+ byteStats.privateDirtyResident = -discountedResidentSize;
+ }
+ if (hasProportionalResident) {
+ byteStats.proportionalResident = -discountedResidentSize;
+ }
+ this.vmRegions.addRegion(tr.model.VMRegion.fromDict({
+ mappedFile: '[discounted tracing overhead]',
+ sizeInBytes: hasSizeInBytes ? -discountedSize : undefined,
+ byteStats
+ }));
+ }
+ }
+ }
+ };
+
+ ProcessMemoryDump.hookUpMostRecentVmRegionsLinks = function(processDumps) {
+ let mostRecentVmRegions = undefined;
+
+ processDumps.forEach(function(processDump) {
+ // Update the most recent VM regions from the current dump.
+ if (processDump.vmRegions !== undefined) {
+ mostRecentVmRegions = processDump.vmRegions;
+ }
+
+ // Set the most recent VM regions of the current dump.
+ processDump.mostRecentVmRegions = mostRecentVmRegions;
+ });
+ };
+
+ tr.model.EventRegistry.register(
+ ProcessMemoryDump,
+ {
+ name: 'processMemoryDump',
+ pluralName: 'processMemoryDumps'
+ });
+
+ return {
+ ProcessMemoryDump,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/process_memory_dump_test.html b/chromium/third_party/catapult/tracing/tracing/model/process_memory_dump_test.html
new file mode 100644
index 00000000000..3d507e879c9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/process_memory_dump_test.html
@@ -0,0 +1,561 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const GlobalMemoryDump = tr.model.GlobalMemoryDump;
+ const ProcessMemoryDump = tr.model.ProcessMemoryDump;
+ const VMRegion = tr.model.VMRegion;
+ const VMRegionClassificationNode = tr.model.VMRegionClassificationNode;
+ const Scalar = tr.b.Scalar;
+ const unitlessNumber_smallerIsBetter =
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const addChildDump = tr.model.MemoryDumpTestUtils.addChildDump;
+ const addOwnershipLink = tr.model.MemoryDumpTestUtils.addOwnershipLink;
+ const checkDumpNumericsAndDiagnostics =
+ tr.model.MemoryDumpTestUtils.checkDumpNumericsAndDiagnostics;
+ const checkVMRegions = tr.model.MemoryDumpTestUtils.checkVMRegions;
+
+ function createClassificationNode(opt_sizeInBytes, opt_byteStats) {
+ const node = new VMRegionClassificationNode();
+ if (opt_sizeInBytes !== undefined || opt_byteStats !== undefined) {
+ node.addRegion(VMRegion.fromDict({
+ mappedFile: 'mock.so',
+ sizeInBytes: opt_sizeInBytes,
+ byteStats: opt_byteStats
+ }));
+ }
+ return node;
+ }
+
+ function createProcessMemoryDump(timestamp, model) {
+ const gmd = new GlobalMemoryDump(model, timestamp);
+ model.globalMemoryDumps.push(gmd);
+ const p = model.getOrCreateProcess(123);
+ const pmd = new ProcessMemoryDump(gmd, p, timestamp + 1);
+ gmd.processMemoryDumps[123] = pmd;
+ p.memoryDumps.push(pmd);
+ return pmd;
+ }
+
+ function createFinalizedProcessMemoryDump(timestamp, opt_createdCallback) {
+ return createFinalizedProcessMemoryDumps([timestamp], function(pmds) {
+ if (opt_createdCallback !== undefined) {
+ opt_createdCallback(pmds[0]);
+ }
+ })[0];
+ }
+
+ function createFinalizedProcessMemoryDumps(timestamps, createdCallback) {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const pmds = timestamps.map(function(timestamp) {
+ return createProcessMemoryDump(timestamp, model);
+ });
+ createdCallback(pmds);
+ });
+ const pmds = model.getProcess(123).memoryDumps;
+ assert.lengthOf(pmds, timestamps.length);
+ return pmds;
+ }
+
+ test('processMemoryDumps', function() {
+ const pmd = createFinalizedProcessMemoryDump(42);
+ const pmds = pmd.processMemoryDumps;
+ assert.lengthOf(Object.keys(pmds), 1);
+ assert.strictEqual(pmds[123], pmd);
+ });
+
+ test('hookUpMostRecentVmRegionsLinks_emptyArray', function() {
+ const dumps = [];
+ ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(dumps);
+ assert.lengthOf(dumps, 0);
+ });
+
+ test('hookUpMostRecentVmRegionsLinks_nonEmptyArray', function() {
+ const m = new tr.Model();
+
+ // A dump with no VM regions or allocator dumps.
+ const dump1 = createProcessMemoryDump(1, m);
+
+ // A dump with VM regions and malloc and Oilpan allocator dumps.
+ const dump2 = createProcessMemoryDump(2, m);
+ dump2.vmRegions = createClassificationNode();
+ dump2.memoryAllocatorDumps = [
+ newAllocatorDump(dump2, 'oilpan', {numerics: {
+ size: 1024,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 7),
+ inner_size: 768
+ }}),
+ newAllocatorDump(dump2, 'v8', {numerics: {
+ size: 2048,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 15),
+ inner_size: 1999
+ }})
+ ];
+
+ // A dump with malloc and V8 allocator dumps.
+ const dump3 = createProcessMemoryDump(3, m);
+ dump3.memoryAllocatorDumps = [
+ newAllocatorDump(dump3, 'malloc', {numerics: {
+ size: 1024,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 7),
+ inner_size: 768
+ }}),
+ newAllocatorDump(dump3, 'v8', {numerics: {
+ size: 2048,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 15),
+ inner_size: 1999
+ }})
+ ];
+
+ // A dump with VM regions.
+ const dump4 = createProcessMemoryDump(4, m);
+ dump4.vmRegions = createClassificationNode();
+
+ const dumps = [dump1, dump2, dump3, dump4];
+ ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(dumps);
+
+ assert.lengthOf(dumps, 4);
+
+ assert.strictEqual(dumps[0], dump1);
+ assert.isUndefined(dump1.mostRecentVmRegions);
+
+ assert.strictEqual(dumps[1], dump2);
+ assert.strictEqual(dump2.mostRecentVmRegions, dump2.vmRegions);
+
+ assert.strictEqual(dumps[2], dump3);
+ assert.strictEqual(dump3.mostRecentVmRegions, dump2.vmRegions);
+
+ assert.strictEqual(dumps[3], dump4);
+ assert.strictEqual(dump4.mostRecentVmRegions, dump4.vmRegions);
+ });
+
+ test('checkDiscountTracingOverhead_undefinedFields', function() {
+ const pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+ pmd.memoryAllocatorDumps = [
+ newAllocatorDump(pmd, 'v8', {numerics: {size: 2048}}),
+ newAllocatorDump(pmd, 'tracing', {numerics: {size: 1024}})
+ ];
+ });
+
+ assert.isUndefined(pmd.totals);
+ assert.isUndefined(pmd.vmRegions);
+
+ const v8Dump = pmd.getMemoryAllocatorDumpByFullName('v8');
+ checkDumpNumericsAndDiagnostics(v8Dump, {
+ size: 2048,
+ effective_size: 2048
+ }, {});
+
+ const tracingDump = pmd.getMemoryAllocatorDumpByFullName('tracing');
+ checkDumpNumericsAndDiagnostics(tracingDump, {
+ size: 1024,
+ effective_size: 1024
+ }, {});
+ });
+
+ test('checkDiscountTracingOverhead_definedFields', function() {
+ const pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+ pmd.totals = {residentBytes: 10240};
+ pmd.vmRegions = createClassificationNode(6000, {
+ privateDirtyResident: 4096,
+ proportionalResident: 5120,
+ swapped: 1536
+ });
+
+ const mallocDump = newAllocatorDump(pmd, 'malloc',
+ {numerics: {size: 3072}});
+ addChildDump(mallocDump, 'allocated_objects', {numerics: {size: 2560}});
+
+ const tracingDump = newAllocatorDump(
+ pmd, 'tracing', {numerics: {size: 1024, resident_size: 1000}});
+
+ pmd.memoryAllocatorDumps = [mallocDump, tracingDump];
+ });
+
+ assert.strictEqual(pmd.totals.residentBytes, 9240);
+ assert.isUndefined(pmd.totals.peakResidentBytes);
+
+ const vmRegions = pmd.vmRegions;
+ assert.strictEqual(vmRegions.sizeInBytes, 4976);
+ assert.deepEqual(vmRegions.byteStats, {
+ privateDirtyResident: 3096,
+ proportionalResident: 4120,
+ swapped: 1536
+ });
+
+ checkVMRegions(vmRegions, [
+ {
+ mappedFile: 'mock.so',
+ sizeInBytes: 6000,
+ byteStats: {
+ privateDirtyResident: 4096,
+ proportionalResident: 5120,
+ swapped: 1536
+ }
+ },
+ {
+ mappedFile: '[discounted tracing overhead]',
+ sizeInBytes: -1024,
+ byteStats: {
+ privateDirtyResident: -1000,
+ proportionalResident: -1000
+ }
+ }
+ ]);
+
+ const mallocDump = pmd.getMemoryAllocatorDumpByFullName('malloc');
+ checkDumpNumericsAndDiagnostics(mallocDump, {
+ size: 3072,
+ effective_size: 2048
+ }, {});
+ assert.lengthOf(
+ mallocDump.children, 2 /* 'allocated_objects' and '<unspecified>' */);
+
+ const allocatedObjectsDump = pmd.getMemoryAllocatorDumpByFullName(
+ 'malloc/allocated_objects');
+ checkDumpNumericsAndDiagnostics(allocatedObjectsDump, {
+ size: 2560,
+ effective_size: 1536
+ }, {});
+ assert.lengthOf(
+ allocatedObjectsDump.children,
+ 2 /* 'tracing_overhead' and '<unspecified>' */);
+
+ const discountDump = pmd.getMemoryAllocatorDumpByFullName(
+ 'malloc/allocated_objects/tracing_overhead');
+ assert.strictEqual(discountDump.parent, allocatedObjectsDump);
+ assert.include(allocatedObjectsDump.children, discountDump);
+ checkDumpNumericsAndDiagnostics(discountDump, {
+ size: 1024,
+ effective_size: 0
+ }, {});
+
+ const tracingDump = pmd.getMemoryAllocatorDumpByFullName('tracing');
+ checkDumpNumericsAndDiagnostics(tracingDump, {
+ size: 1024,
+ effective_size: 1024,
+ resident_size: 1000
+ }, {});
+ assert.strictEqual(tracingDump.owns.target, discountDump);
+ });
+
+ test('checkDiscountTracingOverhead_winheap', function() {
+ const pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+ pmd.memoryAllocatorDumps = [
+ newAllocatorDump(pmd, 'tracing', {numerics: {size: 2048}}),
+ newAllocatorDump(pmd, 'winheap', {numerics: {size: 5120}})
+ ];
+ });
+
+ assert.isUndefined(pmd.totals);
+ assert.isUndefined(pmd.vmRegions);
+
+ const winheapDump = pmd.getMemoryAllocatorDumpByFullName('winheap');
+ checkDumpNumericsAndDiagnostics(winheapDump, {
+ size: 5120,
+ effective_size: 3072
+ }, {});
+ assert.lengthOf(winheapDump.children,
+ 2 /* 'allocated_objects' and '<unspecified>' */);
+
+ const allocatedObjectsDump = pmd.getMemoryAllocatorDumpByFullName(
+ 'winheap/allocated_objects');
+ checkDumpNumericsAndDiagnostics(allocatedObjectsDump, {
+ size: 2048,
+ effective_size: 0
+ }, {});
+ assert.lengthOf(
+ allocatedObjectsDump.children, 1 /* 'tracing_overhead' */);
+
+ const discountDump = pmd.getMemoryAllocatorDumpByFullName(
+ 'winheap/allocated_objects/tracing_overhead');
+ assert.strictEqual(discountDump.parent, allocatedObjectsDump);
+ assert.include(allocatedObjectsDump.children, discountDump);
+ checkDumpNumericsAndDiagnostics(discountDump, {
+ size: 2048,
+ effective_size: 0
+ }, {});
+
+ const tracingDump = pmd.getMemoryAllocatorDumpByFullName('tracing');
+ checkDumpNumericsAndDiagnostics(tracingDump, {
+ size: 2048,
+ effective_size: 2048
+ }, {});
+ assert.strictEqual(tracingDump.owns.target, discountDump);
+ });
+
+ test('checkDiscountTracingOverhead_withMostRecentVmRegionsLinks', function() {
+ const pmds = createFinalizedProcessMemoryDumps([42, 90], function(pmds) {
+ pmds[0].totals = {residentBytes: 1000, peakResidentBytes: 2000};
+ pmds[0].vmRegions = createClassificationNode(6000, {
+ privateDirtyResident: 4096
+ });
+ pmds[0].memoryAllocatorDumps = [
+ newAllocatorDump(pmds[0], 'tracing',
+ {numerics: {size: 300, resident_size: 100}})
+ ];
+
+ pmds[1].totals = {peakResidentBytes: 3000};
+ pmds[1].memoryAllocatorDumps = [
+ newAllocatorDump(pmds[0], 'tracing', {numerics: {resident_size: 200}})
+ ];
+ });
+
+ // First PMD: Both total resident and private dirty resident size should be
+ // reduced by 100. Virtual size should be reduced by 300.
+ assert.strictEqual(pmds[0].totals.residentBytes, 900);
+ assert.strictEqual(pmds[0].totals.peakResidentBytes, 1900);
+ assert.strictEqual(pmds[0].vmRegions.sizeInBytes, 5700);
+ assert.deepEqual(pmds[0].vmRegions.byteStats, {
+ privateDirtyResident: 3996
+ });
+ checkVMRegions(pmds[0].vmRegions, [
+ {
+ mappedFile: 'mock.so',
+ sizeInBytes: 6000,
+ byteStats: {
+ privateDirtyResident: 4096,
+ }
+ },
+ {
+ mappedFile: '[discounted tracing overhead]',
+ sizeInBytes: -300,
+ byteStats: {
+ privateDirtyResident: -100
+ }
+ }
+ ]);
+ assert.strictEqual(pmds[0].mostRecentVmRegions, pmds[0].vmRegions);
+
+ // Second PMD: Total resident size should be reduced by 200, whereas private
+ // dirty resident size should be reduced by 100 (because it comes from
+ // the VM regions in the first dump). Similarly, virtual size should be
+ // reduced by 300.
+ assert.isUndefined(pmds[1].totals.residentBytes);
+ assert.strictEqual(pmds[1].totals.peakResidentBytes, 2800);
+ assert.isUndefined(pmds[1].vmRegions);
+ assert.strictEqual(pmds[1].mostRecentVmRegions, pmds[0].vmRegions);
+ });
+
+ test('checkDiscountTracingOverhead_allDiscountedVmRegionFields', function() {
+ const pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+ pmd.vmRegions = createClassificationNode(10000, {
+ privateDirtyResident: 4096,
+ proportionalResident: 8192,
+ swapped: 1536
+ });
+ pmd.memoryAllocatorDumps = [
+ newAllocatorDump(pmd, 'tracing',
+ {numerics: {size: 1000, resident_size: 1024}})
+ ];
+ });
+
+ const vmRegions = pmd.vmRegions;
+ assert.strictEqual(vmRegions.sizeInBytes, 9000);
+ assert.deepEqual(vmRegions.byteStats, {
+ privateDirtyResident: 3072,
+ proportionalResident: 7168,
+ swapped: 1536
+ });
+ checkVMRegions(vmRegions, [
+ {
+ mappedFile: 'mock.so',
+ sizeInBytes: 10000,
+ byteStats: {
+ privateDirtyResident: 4096,
+ proportionalResident: 8192,
+ swapped: 1536
+ }
+ },
+ {
+ mappedFile: '[discounted tracing overhead]',
+ sizeInBytes: -1000,
+ byteStats: {
+ privateDirtyResident: -1024,
+ proportionalResident: -1024
+ }
+ }
+ ]);
+ });
+
+ test('checkDiscountTracingOverhead_twoDiscountedVmRegionField', function() {
+ const pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+ pmd.vmRegions = createClassificationNode(10000, {
+ privateDirtyResident: 4096,
+ swapped: 1536
+ });
+ pmd.memoryAllocatorDumps = [
+ newAllocatorDump(pmd, 'tracing',
+ {numerics: {size: 1000, resident_size: 1024}})
+ ];
+ });
+
+ const vmRegions = pmd.vmRegions;
+ assert.strictEqual(vmRegions.sizeInBytes, 9000);
+ assert.deepEqual(vmRegions.byteStats, {
+ privateDirtyResident: 3072,
+ swapped: 1536
+ });
+ checkVMRegions(vmRegions, [
+ {
+ mappedFile: 'mock.so',
+ sizeInBytes: 10000,
+ byteStats: {
+ privateDirtyResident: 4096,
+ swapped: 1536
+ }
+ },
+ {
+ mappedFile: '[discounted tracing overhead]',
+ sizeInBytes: -1000,
+ byteStats: {
+ privateDirtyResident: -1024
+ }
+ }
+ ]);
+ });
+
+ test('checkDiscountTracingOverhead_oneDiscountedVmRegionField', function() {
+ const pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+ pmd.vmRegions = createClassificationNode(10000);
+ pmd.memoryAllocatorDumps = [
+ newAllocatorDump(pmd, 'tracing',
+ {numerics: {size: 1000, resident_size: 1024}})
+ ];
+ });
+
+ const vmRegions = pmd.vmRegions;
+ assert.strictEqual(vmRegions.sizeInBytes, 9000);
+ assert.deepEqual(vmRegions.byteStats, {});
+ checkVMRegions(vmRegions, [
+ {
+ mappedFile: 'mock.so',
+ sizeInBytes: 10000
+ },
+ {
+ mappedFile: '[discounted tracing overhead]',
+ sizeInBytes: -1000
+ }
+ ]);
+ });
+
+ test('checkDiscountTracingOverhead_noDiscountedVmRegionFields', function() {
+ const pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+ pmd.vmRegions = createClassificationNode(undefined, {
+ swapped: 1536
+ });
+ pmd.memoryAllocatorDumps = [
+ newAllocatorDump(pmd, 'tracing',
+ {numerics: {size: 1000, resident_size: 1024}})
+ ];
+ });
+
+ const vmRegions = pmd.vmRegions;
+ assert.isUndefined(vmRegions.sizeInBytes);
+ assert.deepEqual(vmRegions.byteStats, {
+ swapped: 1536
+ });
+ checkVMRegions(vmRegions, [
+ {
+ mappedFile: 'mock.so',
+ byteStats: {
+ swapped: 1536
+ }
+ }
+ ]);
+ });
+
+ test('checkDiscountTracingOverhead_existingLink', function() {
+ const pmd = createFinalizedProcessMemoryDump(42, function(pmd) {
+ pmd.totals = {residentBytes: 10240};
+
+ pmd.vmRegions = createClassificationNode(6000, {
+ privateDirtyResident: 4096,
+ swapped: 1536,
+ proportionalResident: 5120
+ });
+
+ const mallocDump = newAllocatorDump(pmd, 'malloc',
+ {numerics: {size: 3072}});
+ const tracingDump = newAllocatorDump(pmd, 'tracing',
+ {numerics: {size: 1024, resident_size: 1000}});
+ const ownedDump = newAllocatorDump(pmd, 'owned');
+
+ // The code for discounting tracing overhead should *not* override an
+ // existing ownership.
+ addOwnershipLink(tracingDump, ownedDump);
+
+ pmd.memoryAllocatorDumps = [mallocDump, tracingDump, ownedDump];
+ });
+
+ assert.strictEqual(pmd.totals.residentBytes, 9240);
+ assert.isUndefined(pmd.totals.peakResidentBytes);
+
+ const vmRegions = pmd.vmRegions;
+ assert.strictEqual(vmRegions.sizeInBytes, 4976);
+ assert.deepEqual(vmRegions.byteStats, {
+ privateDirtyResident: 3096,
+ proportionalResident: 4120,
+ swapped: 1536
+ });
+ checkVMRegions(vmRegions, [
+ {
+ mappedFile: 'mock.so',
+ sizeInBytes: 6000,
+ byteStats: {
+ privateDirtyResident: 4096,
+ proportionalResident: 5120,
+ swapped: 1536
+ }
+ },
+ {
+ mappedFile: '[discounted tracing overhead]',
+ sizeInBytes: -1024,
+ byteStats: {
+ privateDirtyResident: -1000,
+ proportionalResident: -1000
+ }
+ }
+ ]);
+
+ const mallocDump = pmd.getMemoryAllocatorDumpByFullName('malloc');
+ checkDumpNumericsAndDiagnostics(mallocDump, {
+ size: 3072,
+ effective_size: 3072
+ }, {});
+ assert.lengthOf(mallocDump.children, 0);
+
+ const ownedDump = pmd.getMemoryAllocatorDumpByFullName('owned');
+ checkDumpNumericsAndDiagnostics(ownedDump, {
+ size: 1024,
+ effective_size: 0
+ }, {});
+ assert.lengthOf(ownedDump.children, 0);
+
+ const tracingDump = pmd.getMemoryAllocatorDumpByFullName('tracing');
+ checkDumpNumericsAndDiagnostics(tracingDump, {
+ size: 1024,
+ effective_size: 1024,
+ resident_size: 1000
+ }, {});
+ assert.strictEqual(tracingDump.owns.target, ownedDump);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/process_test.html b/chromium/third_party/catapult/tracing/tracing/model/process_test.html
new file mode 100644
index 00000000000..9355971c099
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/process_test.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/frame.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/instant_event.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/process.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('getOrCreateCounter', function() {
+ const model = new tr.Model();
+ const process = new tr.model.Process(model, 7);
+ const ctrBar = process.getOrCreateCounter('foo', 'bar');
+ const ctrBar2 = process.getOrCreateCounter('foo', 'bar');
+ assert.strictEqual(ctrBar2, ctrBar);
+ });
+
+ test('shiftTimestampsForward', function() {
+ const model = new tr.Model();
+ const process = new tr.model.Process(model, 7);
+ const ctr = process.getOrCreateCounter('foo', 'bar');
+ const thread = process.getOrCreateThread(1);
+
+ const instantEvent = new tr.model.InstantEvent('cat', 'event1', 1, 100);
+ process.instantEvents.push(instantEvent);
+
+ const slice = new tr.model.ThreadSlice('', 'a', 0, 1, {}, 4);
+ const frame =
+ new tr.model.Frame([slice], [{thread, start: 100, end: 200}]);
+ process.frames.push(frame);
+
+ const memoryDump = new tr.model.GlobalMemoryDump(model, 100);
+ process.memoryDumps.push(memoryDump);
+
+ let shiftCount = 0;
+ thread.shiftTimestampsForward = function(ts) {
+ if (ts === 0.32) {
+ shiftCount++;
+ }
+ };
+ ctr.shiftTimestampsForward = function(ts) {
+ if (ts === 0.32) {
+ shiftCount++;
+ }
+ };
+
+ process.shiftTimestampsForward(0.32);
+ assert.strictEqual(shiftCount, 2);
+ assert.strictEqual(instantEvent.start, 100.32);
+ assert.strictEqual(frame.start, 100.32);
+ assert.strictEqual(frame.end, 200.32);
+ assert.strictEqual(memoryDump.start, 100.32);
+ });
+
+ test('compareOnPID', function() {
+ let model = new tr.Model();
+ const p1 = new tr.model.Process(model, 1);
+ p1.name = 'Renderer';
+
+ model = new tr.Model();
+ const p2 = new tr.model.Process(model, 2);
+ p2.name = 'Renderer';
+
+ assert.isBelow(p1.compareTo(p2), 0);
+ });
+
+ test('compareOnSortIndex', function() {
+ const model = new tr.Model();
+ const p1 = new tr.model.Process(model, 1);
+ p1.name = 'Renderer';
+ p1.sortIndex = 1;
+
+ const p2 = new tr.model.Process(model, 2);
+ p2.name = 'Renderer';
+
+ assert.isAbove(p1.compareTo(p2), 0);
+ });
+
+ test('compareOnName', function() {
+ const model = new tr.Model();
+ const p1 = new tr.model.Process(model, 1);
+ p1.name = 'Browser';
+
+ const p2 = new tr.model.Process(model, 2);
+ p2.name = 'Renderer';
+
+ assert.isBelow(p1.compareTo(p2), 0);
+ });
+
+ test('compareOnLabels', function() {
+ const model = new tr.Model();
+ const p1 = new tr.model.Process(model, 1);
+ p1.name = 'Renderer';
+ p1.labels = ['a'];
+
+ const p2 = new tr.model.Process(model, 2);
+ p2.name = 'Renderer';
+ p2.labels = ['b'];
+
+ assert.isBelow(p1.compareTo(p2), 0);
+ });
+
+ test('compareOnUptime', function() {
+ const model = new tr.Model();
+ const p1 = new tr.model.Process(model, 1);
+ p1.name = 'Renderer';
+ p1.uptime_seconds = 10;
+
+ const p2 = new tr.model.Process(model, 2);
+ p2.name = 'Renderer';
+ p2.uptime_seconds = 20;
+
+ assert.isBelow(p1.compareTo(p2), 0);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/profile_node.html b/chromium/third_party/catapult/tracing/tracing/model/profile_node.html
new file mode 100644
index 00000000000..edb47b77852
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/profile_node.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the ProfileNode class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * A ProfileNode represents a node in the profile tree,
+ * it is essentially a frame in the stack when the sample gets recorded.
+ */
+ // TODO(lpy) Move V8 specific part out of ProfileNode.
+ function ProfileNode(id, title, parentNode) {
+ this.id_ = id;
+ this.title_ = title;
+ this.parentNode_ = parentNode;
+ this.colorId_ = -1;
+ // Cache the constructed call stack starting from this node to root.
+ this.userFriendlyStack_ = [];
+ }
+
+ ProfileNode.prototype = {
+ __proto__: Object.prototype,
+
+ get title() {
+ return this.title_;
+ },
+
+ get parentNode() {
+ return this.parentNode_;
+ },
+
+ set parentNode(value) {
+ this.parentNode_ = value;
+ },
+
+ get id() {
+ return this.id_;
+ },
+
+ get colorId() {
+ return this.colorId_;
+ },
+
+ set colorId(value) {
+ this.colorId_ = value;
+ },
+
+ get userFriendlyName() {
+ return this.title_;
+ },
+
+ get userFriendlyStack() {
+ if (this.userFriendlyStack_.length === 0) {
+ this.userFriendlyStack_ = [this.userFriendlyName];
+ if (this.parentNode_ !== undefined) {
+ this.userFriendlyStack_ =
+ this.userFriendlyStack_.concat(this.parentNode_.userFriendlyStack);
+ }
+ }
+ return this.userFriendlyStack_;
+ },
+
+ get sampleTitle() {
+ throw new Error('Not implemented.');
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ ProfileNode,
+ {
+ name: 'Node',
+ pluralName: 'Nodes'
+ }
+ );
+
+ return {
+ ProfileNode,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/profile_tree.html b/chromium/third_party/catapult/tracing/tracing/model/profile_tree.html
new file mode 100644
index 00000000000..57e73ed27b0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/profile_tree.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Sample class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * A ProfileTree represents all call stack we collect in sampling
+ * in the form of a tree.
+ * By traversing from root to a leaf we get a call stack
+ * that belongs to some samples we collect.
+ */
+ function ProfileTree() {
+ this.startTime_ = undefined;
+ this.endTime_ = undefined;
+ this.tree_ = new Map();
+ this.pid_ = -1;
+ this.tid_ = -1;
+ }
+
+ ProfileTree.prototype = {
+ __proto__: Object.prototype,
+
+ get pid() {
+ return this.pid_;
+ },
+
+ set pid(value) {
+ this.pid_ = value;
+ },
+
+ get tid() {
+ return this.tid_;
+ },
+
+ set tid(value) {
+ this.tid_ = value;
+ },
+
+ get tree() {
+ return this.tree_;
+ },
+
+ get startTime() {
+ return this.startTime_;
+ },
+
+ set startTime(value) {
+ this.startTime_ = value;
+ this.endTime_ = value;
+ },
+
+ get endTime() {
+ return this.endTime_;
+ },
+
+ set endTime(value) {
+ this.endTime_ = value;
+ },
+
+ add(node) {
+ if (this.tree_.has(node.id)) {
+ throw new Error('Conflict id in the profile tree.');
+ }
+ this.tree_.set(node.id, node);
+ return node;
+ },
+
+ getNode(nodeId) {
+ return this.tree_.get(nodeId);
+ }
+ };
+
+ return {
+ ProfileTree,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/proxy_selectable_item.html b/chromium/third_party/catapult/tracing/tracing/model/proxy_selectable_item.html
new file mode 100644
index 00000000000..d61a944569b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/proxy_selectable_item.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/selectable_item.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const SelectableItem = tr.model.SelectableItem;
+ const SelectionState = tr.model.SelectionState;
+
+ /**
+ * A ProxySelectableItem is a selectable item which is not a model item itself
+ * but instead acts as a proxy for a model item.
+ *
+ * @constructor
+ * @extends {SelectableItem}
+ */
+ function ProxySelectableItem(modelItem) {
+ SelectableItem.call(this, modelItem);
+ }
+
+ ProxySelectableItem.prototype = {
+ __proto__: SelectableItem.prototype,
+
+ get selectionState() {
+ const modelItem = this.modelItem_;
+ if (modelItem === undefined) {
+ return SelectionState.NONE;
+ }
+ return modelItem.selectionState;
+ }
+ };
+
+ return {
+ ProxySelectableItem,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/proxy_selectable_item_test.html b/chromium/third_party/catapult/tracing/tracing/model/proxy_selectable_item_test.html
new file mode 100644
index 00000000000..c7dba2c88a8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/proxy_selectable_item_test.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/proxy_selectable_item.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ProxySelectableItem = tr.model.ProxySelectableItem;
+ const SelectionState = tr.model.SelectionState;
+
+ test('checkSelectionState_undefinedModelItem', function() {
+ const proxyItem = new ProxySelectableItem(undefined);
+ assert.isFalse(proxyItem.selected);
+ assert.strictEqual(proxyItem.selectionState, SelectionState.NONE);
+ });
+
+ test('checkSelectionState_definedModelItem', function() {
+ // Start with a selected model event.
+ const modelItem = {selectionState: SelectionState.SELECTED};
+ const proxyItem = new ProxySelectableItem(modelItem);
+ assert.isTrue(proxyItem.selected);
+ assert.strictEqual(proxyItem.selectionState, SelectionState.SELECTED);
+
+ // Change the selection state of the model event to highlighted.
+ modelItem.selectionState = SelectionState.HIGHLIGHTED;
+ assert.isFalse(proxyItem.selected);
+ assert.strictEqual(proxyItem.selectionState, SelectionState.HIGHLIGHTED);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/rect_annotation.html b/chromium/third_party/catapult/tracing/tracing/model/rect_annotation.html
new file mode 100644
index 00000000000..0ba5daf3ca5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/rect_annotation.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/annotation.html">
+<link rel="import" href="/tracing/model/location.html">
+<link rel="import" href="/tracing/ui/annotations/rect_annotation_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ function RectAnnotation(start, end) {
+ tr.model.Annotation.apply(this, arguments);
+
+ this.startLocation_ = start; // Location of top-left corner.
+ this.endLocation_ = end; // Location of bottom-right corner.
+ this.fillStyle = 'rgba(255, 180, 0, 0.3)';
+ }
+
+ RectAnnotation.fromDict = function(dict) {
+ const args = dict.args;
+ const startLoc =
+ new tr.model.Location(args.start.xWorld, args.start.yComponents);
+ const endLoc =
+ new tr.model.Location(args.end.xWorld, args.end.yComponents);
+ return new tr.model.RectAnnotation(startLoc, endLoc);
+ };
+
+ RectAnnotation.prototype = {
+ __proto__: tr.model.Annotation.prototype,
+
+ get startLocation() {
+ return this.startLocation_;
+ },
+
+ get endLocation() {
+ return this.endLocation_;
+ },
+
+ toDict() {
+ return {
+ typeName: 'rect',
+ args: {
+ start: this.startLocation.toDict(),
+ end: this.endLocation.toDict()
+ }
+ };
+ },
+
+ createView_(viewport) {
+ return new tr.ui.annotations.RectAnnotationView(viewport, this);
+ }
+ };
+
+ tr.model.Annotation.register(RectAnnotation, {typeName: 'rect'});
+
+ return {
+ RectAnnotation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/resource_usage_sample.html b/chromium/third_party/catapult/tracing/tracing/model/resource_usage_sample.html
new file mode 100644
index 00000000000..5ede6b97cff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/resource_usage_sample.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/event_registry.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const Event = tr.model.Event;
+ const EventRegistry = tr.model.EventRegistry;
+
+ /**
+ * A sample containing data about what fraction of a resource
+ * (CPU or GPU) is being used at a given point in time.
+ */
+ class ResourceUsageSample extends Event {
+ /**
+ * @param {ResourceUsageSeries } series The ResourceUsageSeries that this
+ * sample will be a part of.
+ * @param {float} start Time of the sample.
+ * @param {float} usage Fraction of the resource (CPU or GPU) in use at the
+ * time of the sample.
+ */
+ constructor(series, start, usage) {
+ super();
+
+ this.series_ = series;
+ this.start_ = start;
+ this.usage_ = usage;
+ }
+
+ get series() {
+ return this.series_;
+ }
+
+ get start() {
+ return this.start_;
+ }
+
+ set start(value) {
+ this.start_ = value;
+ }
+
+ get usage() {
+ return this.usage_;
+ }
+
+ set usage(value) {
+ this.usage_ = value;
+ }
+
+ addBoundsToRange(range) {
+ range.addValue(this.start);
+ }
+ }
+
+ EventRegistry.register(
+ ResourceUsageSample,
+ {
+ name: 'resourceUsageSample',
+ pluralName: 'resourceUsageSamples'
+ });
+
+ return {
+ ResourceUsageSample,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/resource_usage_sample_test.html b/chromium/third_party/catapult/tracing/tracing/model/resource_usage_sample_test.html
new file mode 100644
index 00000000000..003ef6a327e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/resource_usage_sample_test.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/resource_usage_sample.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ResourceUsageSample = tr.model.ResourceUsageSample;
+
+ test('usageSample', function() {
+ const series = new tr.model.ResourceUsageSeries(new tr.Model().device);
+
+ const sample1 = new ResourceUsageSample(series, 0.0, 0.11);
+ const sample2 = new ResourceUsageSample(series, 1.0, 0.22);
+
+ assert.strictEqual(sample1.series, series);
+ assert.strictEqual(sample1.start, 0.0);
+ assert.strictEqual(sample1.usage, 0.11);
+
+ assert.strictEqual(sample2.series, series);
+ assert.strictEqual(sample2.start, 1.0);
+ assert.strictEqual(sample2.usage, 0.22);
+ });
+
+ test('addBoundsToRange', function() {
+ const series = new tr.model.ResourceUsageSeries(new tr.Model().device);
+
+ const sample1 = new ResourceUsageSample(series, 0.0, 0.11);
+ const sample2 = new ResourceUsageSample(series, 1.0, 0.22);
+
+ const range = new tr.b.math.Range();
+ sample1.addBoundsToRange(range);
+
+ assert.strictEqual(range.min, 0);
+ assert.strictEqual(range.max, 0);
+
+ sample2.addBoundsToRange(range);
+
+ assert.strictEqual(range.min, 0);
+ assert.strictEqual(range.max, 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/resource_usage_series.html b/chromium/third_party/catapult/tracing/tracing/model/resource_usage_series.html
new file mode 100644
index 00000000000..16f28c8d2a1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/resource_usage_series.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/resource_usage_sample.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const ResourceUsageSample = tr.model.ResourceUsageSample;
+
+ /**
+ * A container holding a time series of samples giving the
+ * fraction of usage of a resource (e.g. CPU or GPU) at each
+ * sample time.
+ */
+
+ class ResourceUsageSeries extends tr.model.EventContainer {
+ constructor(device) {
+ super();
+
+ this.device_ = device;
+ this.samples_ = [];
+ }
+
+ get device() {
+ return this.device_;
+ }
+
+ get samples() {
+ return this.samples_;
+ }
+
+ get stableId() {
+ return this.device_.stableId + '.ResourceUsageSeries';
+ }
+
+ /**
+ * Adds a usage sample to the series and returns it.
+ *
+ * Note: Samples must be added in chronological order.
+ */
+ addUsageSample(ts, val) {
+ const sample = new ResourceUsageSample(this, ts, val);
+ this.samples_.push(sample);
+ return sample;
+ }
+
+ /**
+ * Returns the total time consumed by a resource (e.g. CPU or GPU) between
+ * the specified start and end timestamps (in milliseconds).
+ */
+ computeResourceTimeConsumedInMs(start, end) {
+ const measurementRange = tr.b.math.Range.fromExplicitRange(start, end);
+
+ let resourceTimeInMs = 0;
+ let startIndex = tr.b.findLowIndexInSortedArray(
+ this.samples, x => x.start, start) - 1;
+ const endIndex = tr.b.findLowIndexInSortedArray(
+ this.samples, x => x.start, end);
+
+ if (startIndex < 0) startIndex = 0;
+
+ for (let i = startIndex; i < endIndex; i++) {
+ const sample = this.samples[i];
+ const nextSample = this.samples[i + 1];
+
+ const sampleRange = new tr.b.math.Range();
+ sampleRange.addValue(sample.start);
+ sampleRange.addValue(nextSample ? nextSample.start : sample.start);
+
+ const intersectionRangeInMs = measurementRange.findIntersection(
+ sampleRange);
+
+ resourceTimeInMs += intersectionRangeInMs.duration * sample.usage;
+ }
+
+ return resourceTimeInMs;
+ }
+
+ getSamplesWithinRange(start, end) {
+ const startIndex = tr.b.findLowIndexInSortedArray(
+ this.samples, x => x.start, start);
+ const endIndex = tr.b.findLowIndexInSortedArray(
+ this.samples, x => x.start, end);
+ return this.samples.slice(startIndex, endIndex);
+ }
+
+ shiftTimestampsForward(amount) {
+ for (let i = 0; i < this.samples_.length; ++i) {
+ this.samples_[i].start += amount;
+ }
+ }
+
+ updateBounds() {
+ this.bounds.reset();
+
+ if (this.samples_.length === 0) return;
+
+ this.bounds.addValue(this.samples_[0].start);
+ this.bounds.addValue(this.samples_[this.samples_.length - 1].start);
+ }
+
+ * childEvents() {
+ yield* this.samples_;
+ }
+ }
+
+ return {
+ ResourceUsageSeries,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/resource_usage_series_test.html b/chromium/third_party/catapult/tracing/tracing/model/resource_usage_series_test.html
new file mode 100644
index 00000000000..80981e0ca26
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/resource_usage_series_test.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/device.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/resource_usage_series.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const ResourceUsageSeries = tr.model.ResourceUsageSeries;
+
+ test('stableId', function() {
+ const device = { stableId: 'test' };
+ const series = new ResourceUsageSeries(device);
+
+ assert.strictEqual(series.stableId, 'test.ResourceUsageSeries');
+ });
+
+ test('device', function() {
+ const device = new tr.model.Device(new Model());
+ const series = new ResourceUsageSeries(device);
+
+ assert.strictEqual(series.device, device);
+ });
+
+ test('addUsageSample', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+
+ assert.strictEqual(series.samples.length, 0);
+
+ const sample1 = series.addUsageSample(0, 1);
+ const sample2 = series.addUsageSample(1, 2);
+
+ assert.deepEqual(series.samples, [sample1, sample2]);
+ });
+
+ test('getResourceTimeConsumed_oneInterval', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+ series.addUsageSample(0, 1);
+ series.addUsageSample(1000, 2);
+
+ assert.strictEqual(series.computeResourceTimeConsumedInMs(0, 1000), 1000);
+ });
+
+ test('getResourceTimeConsumed_twoIntervals', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+ series.addUsageSample(0, 1);
+ series.addUsageSample(1000, 2);
+ series.addUsageSample(2000, 2);
+
+ assert.strictEqual(series.computeResourceTimeConsumedInMs(0, 2000), 3000);
+ });
+
+ test('getResourceTimeConsumed_oneSample', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+ series.addUsageSample(1000, 1);
+
+ assert.strictEqual(series.computeResourceTimeConsumedInMs(0, 2000), 0);
+ });
+
+ test('getResourceTimeConsumed_samplesAfterStart', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+ series.addUsageSample(1000, 1);
+ series.addUsageSample(2000, 2);
+
+ assert.strictEqual(series.computeResourceTimeConsumedInMs(0, 2000), 1000);
+ });
+
+ test('getResourceTimeConsumed_extraSamplesBeforeStart', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+ series.addUsageSample(0, 10);
+ series.addUsageSample(1000, 1);
+ series.addUsageSample(2000, 1);
+ series.addUsageSample(3000, 1);
+
+ assert.strictEqual(
+ series.computeResourceTimeConsumedInMs(2000, 4000), 1000);
+ });
+
+ test('getResourceTimeConsumed_extraSamplesAfterEnd', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+ series.addUsageSample(0, 1);
+ series.addUsageSample(1000, 1);
+ series.addUsageSample(2000, 1);
+ series.addUsageSample(3000, 10);
+
+ assert.strictEqual(series.computeResourceTimeConsumedInMs(0, 2000), 2000);
+ });
+
+ test('shiftTimestampsForward', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+
+ series.addUsageSample(0, 1);
+ series.addUsageSample(1, 2);
+
+ series.shiftTimestampsForward(2);
+
+ assert.strictEqual(series.samples[0].start, 2);
+ assert.strictEqual(series.samples[1].start, 3);
+
+ series.shiftTimestampsForward(-4);
+
+ assert.strictEqual(series.samples[0].start, -2);
+ assert.strictEqual(series.samples[1].start, -1);
+ });
+
+
+ test('updateBounds', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+
+ series.addUsageSample(0, 1);
+ series.addUsageSample(1, 2);
+ series.updateBounds();
+
+ assert.strictEqual(series.bounds.min, 0);
+ assert.strictEqual(series.bounds.max, 1);
+
+ series.addUsageSample(4, 3);
+ series.updateBounds();
+
+ assert.strictEqual(series.bounds.min, 0);
+ assert.strictEqual(series.bounds.max, 4);
+ });
+
+ test('childEvents_empty', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+ const eventsInSeries = [];
+ for (const event of series.childEvents()) {
+ eventsInSeries.push(event);
+ }
+ assert.deepEqual(eventsInSeries, []);
+ });
+
+ test('childEvents_nonempty', function() {
+ const series = new ResourceUsageSeries(new Model().device);
+ const sample1 = series.addUsageSample(0, 1);
+ const sample2 = series.addUsageSample(1, 2);
+ const eventsInSeries = [];
+ for (const event of series.childEvents()) {
+ eventsInSeries.push(event);
+ }
+ assert.deepEqual(eventsInSeries, [sample1, sample2]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/sample.html b/chromium/third_party/catapult/tracing/tracing/model/sample.html
new file mode 100644
index 00000000000..59a34771d8b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/sample.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Sample class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * A Sample represents a sample taken at an instant in time,
+ * plus its call stack and parameters associated with that sample.
+ *
+ * @constructor
+ */
+ function Sample(start, title, leafNode, thread, opt_cpu, opt_weight,
+ opt_args) {
+ tr.model.TimedEvent.call(this, start);
+
+ this.start_ = start;
+ this.title_ = title;
+ this.leafNode_ = leafNode;
+ this.thread_ = thread;
+ this.colorId_ = leafNode.colorId;
+
+ this.cpu_ = opt_cpu;
+ this.weight_ = opt_weight;
+ this.args = opt_args || {};
+ }
+
+ Sample.prototype = {
+ __proto__: tr.model.TimedEvent.prototype,
+
+ get title() {
+ return this.title_;
+ },
+
+ get colorId() {
+ return this.colorId_;
+ },
+
+ get thread() {
+ return this.thread_;
+ },
+
+ get leafNode() {
+ return this.leafNode_;
+ },
+
+ get userFriendlyName() {
+ return 'Sample at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.start);
+ },
+
+ get userFriendlyStack() {
+ return this.leafNode_.userFriendlyStack;
+ },
+
+ getNodesAsArray() {
+ const nodes = [];
+ let node = this.leafNode_;
+ while (node !== undefined) {
+ nodes.push(node);
+ node = node.parentNode;
+ }
+ return nodes;
+ },
+
+ get cpu() {
+ return this.cpu_;
+ },
+
+ get weight() {
+ return this.weight_;
+ },
+ };
+
+ tr.model.EventRegistry.register(
+ Sample,
+ {
+ name: 'Sample',
+ pluralName: 'Samples'
+ });
+
+ return {
+ Sample,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/sample_test.html b/chromium/third_party/catapult/tracing/tracing/model/sample_test.html
new file mode 100644
index 00000000000..f329f1096d9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/sample_test.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Sample = tr.model.Sample;
+ const StackFrame = tr.model.StackFrame;
+ const Thread = tr.model.Thread;
+
+ test('sampleStackTrace', function() {
+ const thread = tr.c.TestUtils.newFakeThread();
+
+ const model = new tr.Model();
+ const node = tr.c.TestUtils.newProfileNodes(model, ['a', 'b', 'c']);
+
+ const s = new Sample(
+ 10, 'instructions_retired', node, thread, undefined, 10);
+ assert.deepEqual(s.userFriendlyStack, ['c', 'b', 'a']);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/scoped_id.html b/chromium/third_party/catapult/tracing/tracing/model/scoped_id.html
new file mode 100644
index 00000000000..b7b64a2e443
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/scoped_id.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/model/constants.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ function ScopedId(scope, id, pid) {
+ if (scope === undefined) {
+ throw new Error('Scope should be defined. Use \'' +
+ tr.model.OBJECT_DEFAULT_SCOPE +
+ '\' as the default scope.');
+ }
+ this.scope = scope;
+ this.id = id;
+ this.pid = pid;
+ }
+
+ ScopedId.prototype = {
+ toString() {
+ const pidStr = this.pid === undefined ? '' : 'pid: ' + this.pid + ', ';
+ return '{' + pidStr + 'scope: ' + this.scope + ', id: ' + this.id + '}';
+ },
+
+ toStringWithDelimiter(delim) {
+ return (this.pid === undefined ? '' : this.pid) + delim +
+ this.scope + delim + this.id;
+ }
+ };
+
+ return {
+ ScopedId,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/selectable_item.html b/chromium/third_party/catapult/tracing/tracing/model/selectable_item.html
new file mode 100644
index 00000000000..3492dc00b9f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/selectable_item.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/selection_state.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the SelectableItem class.
+ */
+tr.exportTo('tr.model', function() {
+ const SelectionState = tr.model.SelectionState;
+
+ /**
+ * A SelectableItem is the abstract base class for any non-container data that
+ * has an associated model item in the trace model (possibly itself).
+ *
+ * Subclasses must provide a selectionState property (or getter).
+ *
+ * @constructor
+ */
+ function SelectableItem(modelItem) {
+ this.modelItem_ = modelItem;
+ }
+
+ SelectableItem.prototype = {
+ get modelItem() {
+ return this.modelItem_;
+ },
+
+ get selected() {
+ return this.selectionState === SelectionState.SELECTED;
+ },
+
+ addToSelection(selection) {
+ const modelItem = this.modelItem_;
+ if (!modelItem) return;
+ selection.push(modelItem);
+ },
+
+ addToTrackMap(eventToTrackMap, track) {
+ const modelItem = this.modelItem_;
+ if (!modelItem) return;
+ eventToTrackMap.addEvent(modelItem, track);
+ }
+ };
+
+ return {
+ SelectableItem,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/selectable_item_test.html b/chromium/third_party/catapult/tracing/tracing/model/selectable_item_test.html
new file mode 100644
index 00000000000..120773852d9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/selectable_item_test.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/selectable_item.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/tracks/event_to_track_map.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Event = tr.model.Event;
+ const EventToTrackMap = tr.ui.tracks.EventToTrackMap;
+ const SelectableItem = tr.model.SelectableItem;
+ const SelectionState = tr.model.SelectionState;
+
+ test('checkModelItem', function() {
+ const selectableItem1 = new SelectableItem(undefined);
+ assert.isUndefined(selectableItem1.modelItem);
+
+ const event = new Event();
+ const selectableItem2 = new SelectableItem(event);
+ assert.strictEqual(selectableItem2.modelItem, event);
+ });
+
+ test('checkSelected', function() {
+ const selectableItem = new SelectableItem(undefined);
+
+ selectableItem.selectionState = SelectionState.NONE;
+ assert.isFalse(selectableItem.selected);
+
+ selectableItem.selectionState = SelectionState.SELECTED;
+ assert.isTrue(selectableItem.selected);
+
+ selectableItem.selectionState = SelectionState.HIGHLIGHTED;
+ assert.isFalse(selectableItem.selected);
+ });
+
+ test('checkAddToSelection_undefinedModelItem', function() {
+ const selectableItem = new SelectableItem(undefined);
+ const selection = [];
+ selectableItem.addToSelection(selection);
+ assert.lengthOf(selection, 0);
+ });
+
+ test('checkAddToSelection_definedModelItem', function() {
+ const event = new Event();
+ const selectableItem = new SelectableItem(event);
+ const selection = [];
+ selectableItem.addToSelection(selection);
+ assert.lengthOf(selection, 1);
+ assert.strictEqual(selection[0], event);
+ });
+
+ test('checkAddToTrackMap_undefinedModelItem', function() {
+ const selectableItem = new SelectableItem(undefined);
+ const eventToTrackMap = new EventToTrackMap();
+ const track = {};
+ selectableItem.addToTrackMap(eventToTrackMap, track);
+ assert.lengthOf(Object.keys(eventToTrackMap), 0);
+ });
+
+ test('checkAddToTrackMap_definedModelItem', function() {
+ const event = new Event();
+ const selectableItem = new SelectableItem(event);
+ const eventToTrackMap = new EventToTrackMap();
+ const track = {};
+ selectableItem.addToTrackMap(eventToTrackMap, track);
+ assert.lengthOf(Object.keys(eventToTrackMap), 1);
+ assert.strictEqual(eventToTrackMap[event.guid], track);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/selection_state.html b/chromium/third_party/catapult/tracing/tracing/model/selection_state.html
new file mode 100644
index 00000000000..3e68d65a72b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/selection_state.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/color_scheme.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the SelectionState class.
+ */
+tr.exportTo('tr.model', function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ /**
+ * Describes the level of visual highlighting to apply to an event when shown.
+ *
+ * color_scheme.html defines N variations off of a base color palette,
+ * one for each selection state, all concatenated into one flat array. To
+ * pick the final colorId for a given variations, the SelectionState is
+ * multiplied by the number of base colors.
+ *
+ * Thus, the values here must be kept in sync with color_scheme's palette
+ * layout.
+ */
+ const SelectionState = {
+ NONE: 0,
+
+ // Legacy names.
+ SELECTED: ColorScheme.properties.brightenedOffsets[0],
+ HIGHLIGHTED: ColorScheme.properties.brightenedOffsets[1],
+ DIMMED: ColorScheme.properties.dimmedOffsets[0],
+
+ // Modern names.
+ BRIGHTENED0: ColorScheme.properties.brightenedOffsets[0],
+ BRIGHTENED1: ColorScheme.properties.brightenedOffsets[1],
+ BRIGHTENED2: ColorScheme.properties.brightenedOffsets[2],
+
+ DIMMED0: ColorScheme.properties.dimmedOffsets[0],
+ DIMMED1: ColorScheme.properties.dimmedOffsets[1],
+ DIMMED2: ColorScheme.properties.dimmedOffsets[2]
+ };
+
+ const brighteningLevels = [
+ SelectionState.NONE,
+ SelectionState.BRIGHTENED0,
+ SelectionState.BRIGHTENED1,
+ SelectionState.BRIGHTENED2
+ ];
+ SelectionState.getFromBrighteningLevel = function(level) {
+ return brighteningLevels[level];
+ };
+
+ const dimmingLevels = [
+ SelectionState.DIMMED0,
+ SelectionState.DIMMED1,
+ SelectionState.DIMMED2
+ ];
+ SelectionState.getFromDimmingLevel = function(level) {
+ return dimmingLevels[level];
+ };
+
+ return {
+ SelectionState,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/slice.html b/chromium/third_party/catapult/tracing/tracing/model/slice.html
new file mode 100644
index 00000000000..2ea422561e6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/slice.html
@@ -0,0 +1,302 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Slice class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * A Slice represents an interval of time plus parameters associated
+ * with that interval.
+ *
+ * @constructor
+ */
+ function Slice(category, title, colorId, start, args, opt_duration,
+ opt_cpuStart, opt_cpuDuration, opt_argsStripped,
+ opt_bindId) {
+ if (new.target) {
+ throw new Error('Can\'t instantiate pure virtual class Slice');
+ }
+ tr.model.TimedEvent.call(this, start);
+
+ this.category = category || '';
+ this.title = title;
+ this.colorId = colorId;
+ this.args = args;
+ this.startStackFrame = undefined;
+ this.endStackFrame = undefined;
+ this.didNotFinish = false;
+ this.inFlowEvents = [];
+ this.outFlowEvents = [];
+ this.subSlices = [];
+ this.selfTime = undefined;
+ this.cpuSelfTime = undefined;
+ this.important = false;
+ this.parentContainer = undefined;
+ this.argsStripped = false;
+
+ this.bind_id_ = opt_bindId;
+
+ // parentSlice and isTopLevel will be set by SliceGroup.
+ this.parentSlice = undefined;
+ this.isTopLevel = false;
+ // After SliceGroup processes Slices, isTopLevel should be equivalent to
+ // !parentSlice.
+
+ if (opt_duration !== undefined) {
+ this.duration = opt_duration;
+ }
+
+ if (opt_cpuStart !== undefined) {
+ this.cpuStart = opt_cpuStart;
+ }
+
+ if (opt_cpuDuration !== undefined) {
+ this.cpuDuration = opt_cpuDuration;
+ }
+
+ if (opt_argsStripped !== undefined) {
+ this.argsStripped = true;
+ }
+ }
+
+ Slice.prototype = {
+ __proto__: tr.model.TimedEvent.prototype,
+
+
+ get analysisTypeName() {
+ return this.title;
+ },
+
+ get userFriendlyName() {
+ return 'Slice ' + this.title + ' at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.start);
+ },
+
+ get stableId() {
+ const parentSliceGroup = this.parentContainer.sliceGroup;
+ return parentSliceGroup.stableId + '.' +
+ parentSliceGroup.slices.indexOf(this);
+ },
+
+ get bindId() {
+ return this.bind_id_;
+ },
+
+ findDescendentSlice(targetTitle) {
+ if (!this.subSlices) {
+ return undefined;
+ }
+
+ for (let i = 0; i < this.subSlices.length; i++) {
+ if (this.subSlices[i].title === targetTitle) {
+ return this.subSlices[i];
+ }
+ const slice = this.subSlices[i].findDescendentSlice(targetTitle);
+ if (slice) return slice;
+ }
+ return undefined;
+ },
+
+ get mostTopLevelSlice() {
+ if (!this.parentSlice) return this;
+ return this.parentSlice.mostTopLevelSlice;
+ },
+
+ getProcess() {
+ const thread = this.parentContainer;
+ if (thread && thread.getProcess) {
+ return thread.getProcess();
+ }
+ return undefined;
+ },
+
+ get model() {
+ const process = this.getProcess();
+ if (process !== undefined) {
+ return this.getProcess().model;
+ }
+ return undefined;
+ },
+
+ /**
+ * Finds all topmost slices relative to this slice.
+ *
+ * Slices may have multiple direct descendants which satisfy
+ * |eventPredicate|, and in this case, all of them are topmost as long as
+ * this slice does not satisfy the predicate.
+ *
+ * For instance, suppose we are passing a predicate that checks whether
+ * events titles begin with 'C'.
+ * C1.findTopmostSlicesRelativeToThisSlice() returns C1 in this example:
+ * [ C1 ]
+ * [ C2 ]
+ *
+ * and D.findTopmostSlicesRelativeToThisSlice() returns C1 and C2 in this
+ * example:
+ * [ D ]
+ * [C1] [C2]
+ */
+ * findTopmostSlicesRelativeToThisSlice(eventPredicate) {
+ if (eventPredicate(this)) {
+ yield this;
+ return;
+ }
+ for (const s of this.subSlices) {
+ yield* s.findTopmostSlicesRelativeToThisSlice(eventPredicate);
+ }
+ },
+
+ /**
+ * Obtains all subsequent slices of this slice.
+ *
+ * Subsequent slices are slices that get executed after a particular
+ * slice, i.e., all the functions that are called after the current one.
+ *
+ * For instance, E.iterateAllSubsequentSlices() in the following example:
+ * [ A ]
+ * [ B][ D ][ G ]
+ * [C] [E][F] [H]
+ * will pass F, G, then H to the provided callback.
+ *
+ * The reason we need subsequent slices of a particular slice is that
+ * when there is flow event goes into, e.g., E, we only want to highlight
+ * E's subsequent slices to indicate the execution order.
+ *
+ * The idea to calculate the subsequent slices of slice E is to view
+ * the slice group as a tree where the top-level slice A is the root node.
+ * The preorder depth-first-search (DFS) order is naturally equivalent
+ * to the function call order. We just need to perform a DFS, and start
+ * recording the slices after we see the occurance of E.
+ */
+ iterateAllSubsequentSlices(callback, opt_this) {
+ const parentStack = [];
+ let started = false;
+
+ // get the root node and push it to the DFS stack
+ const topmostSlice = this.mostTopLevelSlice;
+ parentStack.push(topmostSlice);
+
+ // Using the stack to perform DFS
+ while (parentStack.length !== 0) {
+ const curSlice = parentStack.pop();
+
+ if (started) {
+ callback.call(opt_this, curSlice);
+ } else {
+ started = (curSlice.guid === this.guid);
+ }
+
+ for (let i = curSlice.subSlices.length - 1; i >= 0; i--) {
+ parentStack.push(curSlice.subSlices[i]);
+ }
+ }
+ },
+
+ get subsequentSlices() {
+ const res = [];
+
+ this.iterateAllSubsequentSlices(function(subseqSlice) {
+ res.push(subseqSlice);
+ });
+
+ return res;
+ },
+
+ /**
+ * Obtains the parents of a slice, from the most immediate to the root.
+ *
+ * For instance, E.enumerateAllAncestors() in the following example:
+ * [ A ]
+ * [ B][ D ][ G ]
+ * [C] [E][F] [H]
+ * will yield D, then A, in the order from the leaves to the root.
+ */
+ * enumerateAllAncestors() {
+ let curSlice = this.parentSlice;
+ while (curSlice) {
+ yield curSlice;
+ curSlice = curSlice.parentSlice;
+ }
+ },
+
+ get ancestorSlices() {
+ return Array.from(this.enumerateAllAncestors());
+ },
+
+ iterateEntireHierarchy(callback, opt_this) {
+ const mostTopLevelSlice = this.mostTopLevelSlice;
+ callback.call(opt_this, mostTopLevelSlice);
+ mostTopLevelSlice.iterateAllSubsequentSlices(callback, opt_this);
+ },
+
+ get entireHierarchy() {
+ const res = [];
+
+ this.iterateEntireHierarchy(function(slice) {
+ res.push(slice);
+ });
+
+ return res;
+ },
+
+ /**
+ * Returns this slice, and its ancestor and subsequent slices.
+ *
+ * For instance, E.ancestorAndSubsequentSlices in the following example:
+ * [ A ]
+ * [ B][ D ][ G ]
+ * [C] [E][F] [H]
+ * will return E, D, A, F, G, and H, where E is itself, D and A are
+ * E's ancestors, and F, G, and H are subsequent slices of E
+ */
+ get ancestorAndSubsequentSlices() {
+ const res = [];
+
+ res.push(this);
+
+ for (const aSlice of this.enumerateAllAncestors()) {
+ res.push(aSlice);
+ }
+
+ this.iterateAllSubsequentSlices(function(sSlice) {
+ res.push(sSlice);
+ });
+
+ return res;
+ },
+
+ * enumerateAllDescendents() {
+ for (const slice of this.subSlices) {
+ yield slice;
+ }
+ for (const slice of this.subSlices) {
+ yield* slice.enumerateAllDescendents();
+ }
+ },
+
+ get descendentSlices() {
+ const res = [];
+ for (const slice of this.enumerateAllDescendents()) {
+ res.push(slice);
+ }
+ return res;
+ }
+
+ };
+
+ return {
+ Slice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/slice_group.html b/chromium/third_party/catapult/tracing/tracing/model/slice_group.html
new file mode 100644
index 00000000000..82d24283cf4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/slice_group.html
@@ -0,0 +1,720 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the SliceGroup class.
+ */
+tr.exportTo('tr.model', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const ThreadSlice = tr.model.ThreadSlice;
+
+ function getSliceLo(s) {
+ return s.start;
+ }
+
+ function getSliceHi(s) {
+ return s.end;
+ }
+
+ /**
+ * A group of Slices, plus code to create them from B/E events, as
+ * well as arrange them into subRows.
+ *
+ * Do not mutate the slices array directly. Modify it only by
+ * SliceGroup mutation methods.
+ *
+ * @constructor
+ * @param {function(new:Slice, category, title, colorId, start, args)=}
+ * opt_sliceConstructor The constructor to use when creating slices.
+ * @extends {tr.model.EventContainer}
+ */
+ function SliceGroup(parentContainer, opt_sliceConstructor, opt_name) {
+ tr.model.EventContainer.call(this);
+
+ this.parentContainer_ = parentContainer;
+
+ const sliceConstructor = opt_sliceConstructor || ThreadSlice;
+ this.sliceConstructor = sliceConstructor;
+ this.sliceConstructorSubTypes = this.sliceConstructor.subTypes;
+ if (!this.sliceConstructorSubTypes) {
+ throw new Error('opt_sliceConstructor must have a subtype registry.');
+ }
+
+ this.openPartialSlices_ = [];
+
+ this.slices = [];
+ this.topLevelSlices = [];
+ this.haveTopLevelSlicesBeenBuilt = false;
+ this.name_ = opt_name;
+
+ if (this.model === undefined) {
+ throw new Error('SliceGroup must have model defined.');
+ }
+ }
+
+ SliceGroup.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ get parentContainer() {
+ return this.parentContainer_;
+ },
+
+ get model() {
+ return this.parentContainer_.model;
+ },
+
+ get stableId() {
+ return this.parentContainer_.stableId + '.SliceGroup';
+ },
+
+ getSettingsKey() {
+ if (!this.name_) return undefined;
+ const parentKey = this.parentContainer_.getSettingsKey();
+ if (!parentKey) return undefined;
+ return parentKey + '.' + this.name;
+ },
+
+ /**
+ * @return {Number} The number of slices in this group.
+ */
+ get length() {
+ return this.slices.length;
+ },
+
+ /**
+ * Helper function that pushes the provided slice onto the slices array.
+ * @param {Slice} slice The slice to be added to the slices array.
+ */
+ pushSlice(slice) {
+ this.haveTopLevelSlicesBeenBuilt = false;
+ slice.parentContainer = this.parentContainer_;
+ this.slices.push(slice);
+ return slice;
+ },
+
+ /**
+ * Helper function that pushes the provided slices onto the slices array.
+ * @param {Array.<Slice>} slices An array of slices to be added.
+ */
+ pushSlices(slices) {
+ this.haveTopLevelSlicesBeenBuilt = false;
+ slices.forEach(function(slice) {
+ slice.parentContainer = this.parentContainer_;
+ this.slices.push(slice);
+ }, this);
+ },
+
+ /**
+ * Opens a new slice in the group's slices.
+ *
+ * Calls to beginSlice and
+ * endSlice must be made with non-monotonically-decreasing timestamps.
+ *
+ * @param {String} category Category name of the slice to add.
+ * @param {String} title Title of the slice to add.
+ * @param {Number} ts The timetsamp of the slice, in milliseconds.
+ * @param {Object.<string, Object>=} opt_args Arguments associated with
+ * the slice.
+ * @param {Number=} opt_colorId The color of the slice, defined by
+ * its palette id (see base/color_scheme.html).
+ */
+ beginSlice(category, title, ts, opt_args, opt_tts,
+ opt_argsStripped, opt_colorId, opt_bindId) {
+ const colorId = opt_colorId ||
+ ColorScheme.getColorIdForGeneralPurposeString(title);
+ const sliceConstructorSubTypes = this.sliceConstructorSubTypes;
+ const sliceType = sliceConstructorSubTypes.getConstructor(
+ category, title);
+ const slice = new sliceType(category, title, colorId, ts,
+ opt_args ? opt_args : {}, null,
+ opt_tts, undefined,
+ opt_argsStripped, opt_bindId);
+ this.openPartialSlices_.push(slice);
+ slice.didNotFinish = true;
+ this.pushSlice(slice);
+
+ return slice;
+ },
+
+ isTimestampValidForBeginOrEnd(ts) {
+ if (!this.openPartialSlices_.length) return true;
+ const top = this.openPartialSlices_[this.openPartialSlices_.length - 1];
+ return ts >= top.start;
+ },
+
+ /**
+ * @return {Number} The number of beginSlices for which an endSlice has not
+ * been issued.
+ */
+ get openSliceCount() {
+ return this.openPartialSlices_.length;
+ },
+
+ get mostRecentlyOpenedPartialSlice() {
+ if (!this.openPartialSlices_.length) return undefined;
+ return this.openPartialSlices_[this.openPartialSlices_.length - 1];
+ },
+
+ /**
+ * Ends the last begun slice in this group and pushes it onto the slice
+ * array.
+ *
+ * @param {Number} ts Timestamp when the slice ended
+ * @param {Number=} opt_colorId The color of the slice, defined by
+ * its palette id (see base/color_scheme.html).
+ * @return {Slice} slice.
+ */
+ endSlice(ts, opt_tts, opt_colorId) {
+ if (!this.openSliceCount) {
+ throw new Error('endSlice called without an open slice');
+ }
+
+ const slice = this.openPartialSlices_[this.openSliceCount - 1];
+ this.openPartialSlices_.splice(this.openSliceCount - 1, 1);
+ if (ts < slice.start) {
+ throw new Error('Slice ' + slice.title +
+ ' end time is before its start.');
+ }
+
+ slice.duration = ts - slice.start;
+ slice.didNotFinish = false;
+ slice.colorId = opt_colorId || slice.colorId;
+
+ if (opt_tts && slice.cpuStart !== undefined) {
+ slice.cpuDuration = opt_tts - slice.cpuStart;
+ }
+
+ return slice;
+ },
+
+ /**
+ * Push a complete event as a Slice into the slice list.
+ * The timestamp can be in any order.
+ *
+ * @param {String} category Category name of the slice to add.
+ * @param {String} title Title of the slice to add.
+ * @param {Number} ts The timetsamp of the slice, in milliseconds.
+ * @param {Number} duration The duration of the slice, in milliseconds.
+ * @param {Object.<string, Object>=} opt_args Arguments associated with
+ * the slice.
+ * @param {Number=} opt_colorId The color of the slice, as defined by
+ * its palette id (see base/color_scheme.html).
+ */
+ pushCompleteSlice(category, title, ts, duration, tts,
+ cpuDuration, opt_args, opt_argsStripped,
+ opt_colorId, opt_bindId) {
+ const colorId = opt_colorId ||
+ ColorScheme.getColorIdForGeneralPurposeString(title);
+ const sliceConstructorSubTypes = this.sliceConstructorSubTypes;
+ const sliceType = sliceConstructorSubTypes.getConstructor(
+ category, title);
+ const slice = new sliceType(category, title, colorId, ts,
+ opt_args ? opt_args : {},
+ duration, tts, cpuDuration,
+ opt_argsStripped, opt_bindId);
+ if (duration === undefined) {
+ slice.didNotFinish = true;
+ }
+ this.pushSlice(slice);
+ return slice;
+ },
+
+ /**
+ * Closes any open slices.
+ * @param {Number=} opt_maxTimestamp The end time to use for the closed
+ * slices. If not provided,
+ * the max timestamp for this slice is provided.
+ */
+ autoCloseOpenSlices() {
+ this.updateBounds();
+ const maxTimestamp = this.bounds.max;
+ for (let sI = 0; sI < this.slices.length; sI++) {
+ const slice = this.slices[sI];
+ if (slice.didNotFinish) {
+ slice.duration = maxTimestamp - slice.start;
+ }
+ }
+ this.openPartialSlices_ = [];
+ },
+
+ /**
+ * Shifts all the timestamps inside this group forward by the amount
+ * specified.
+ */
+ shiftTimestampsForward(amount) {
+ for (let sI = 0; sI < this.slices.length; sI++) {
+ const slice = this.slices[sI];
+ slice.start = (slice.start + amount);
+ }
+ },
+
+ /**
+ * Updates the bounds for this group based on the slices it contains.
+ */
+ updateBounds() {
+ this.bounds.reset();
+ for (let i = 0; i < this.slices.length; i++) {
+ this.bounds.addValue(this.slices[i].start);
+ this.bounds.addValue(this.slices[i].end);
+ }
+ },
+
+ copySlice(slice) {
+ const sliceConstructorSubTypes = this.sliceConstructorSubTypes;
+ const sliceType = sliceConstructorSubTypes.getConstructor(slice.category,
+ slice.title);
+ const newSlice = new sliceType(slice.category, slice.title,
+ slice.colorId, slice.start,
+ slice.args, slice.duration, slice.cpuStart, slice.cpuDuration);
+ newSlice.didNotFinish = slice.didNotFinish;
+ return newSlice;
+ },
+
+ * findTopmostSlicesInThisContainer(eventPredicate, opt_this) {
+ if (!this.haveTopLevelSlicesBeenBuilt) {
+ throw new Error('Nope');
+ }
+
+ for (const s of this.topLevelSlices) {
+ yield* s.findTopmostSlicesRelativeToThisSlice(eventPredicate);
+ }
+ },
+
+ * childEvents() {
+ yield* this.slices;
+ },
+
+ * childEventContainers() {
+ },
+
+ /**
+ * Provides a more efficient implementation than the default implementation
+ * in event_container.html, since child events are sorted.
+ */
+ * getDescendantEventsInSortedRanges(ranges, opt_containerPredicate) {
+ if (opt_containerPredicate === undefined ||
+ opt_containerPredicate(this)) {
+ let rangeIndex = 0;
+ let range = ranges[rangeIndex];
+ for (const event of this.childEvents()) {
+ while (event.start > range.max) {
+ rangeIndex++;
+ if (rangeIndex >= ranges.length) return;
+ range = ranges[rangeIndex];
+ }
+ if (event.end >= range.min) yield event;
+ }
+ }
+ },
+
+ getSlicesOfName(title) {
+ const slices = [];
+ for (let i = 0; i < this.slices.length; i++) {
+ if (this.slices[i].title === title) {
+ slices.push(this.slices[i]);
+ }
+ }
+ return slices;
+ },
+
+ iterSlicesInTimeRange(callback, start, end) {
+ const ret = [];
+ tr.b.iterateOverIntersectingIntervals(
+ this.topLevelSlices,
+ function(s) { return s.start; },
+ function(s) { return s.duration; },
+ start,
+ end,
+ function(topLevelSlice) {
+ callback(topLevelSlice);
+ for (const slice of topLevelSlice.enumerateAllDescendents()) {
+ callback(slice);
+ }
+ });
+ return ret;
+ },
+
+ findFirstSlice() {
+ if (!this.haveTopLevelSlicesBeenBuilt) {
+ throw new Error('Nope');
+ }
+ if (0 === this.slices.length) return undefined;
+ return this.slices[0];
+ },
+
+ findSliceAtTs(ts) {
+ if (!this.haveTopLevelSlicesBeenBuilt) throw new Error('Nope');
+ let i = tr.b.findIndexInSortedClosedIntervals(
+ this.topLevelSlices,
+ getSliceLo, getSliceHi,
+ ts);
+ if (i === -1 || i === this.topLevelSlices.length) {
+ return undefined;
+ }
+
+ let curSlice = this.topLevelSlices[i];
+
+ // Now recurse on slice looking for subSlice of given ts.
+ while (true) {
+ i = tr.b.findIndexInSortedClosedIntervals(
+ curSlice.subSlices,
+ getSliceLo, getSliceHi,
+ ts);
+ if (i === -1 || i === curSlice.subSlices.length) {
+ return curSlice;
+ }
+ curSlice = curSlice.subSlices[i];
+ }
+ },
+
+ findNextSliceAfter(ts, refGuid) {
+ let i = tr.b.findLowIndexInSortedArray(this.slices, getSliceLo, ts);
+ if (i === this.slices.length) {
+ return undefined;
+ }
+ for (; i < this.slices.length; i++) {
+ const slice = this.slices[i];
+ if (slice.start > ts) return slice;
+ if (slice.guid <= refGuid) continue;
+ return slice;
+ }
+ return undefined;
+ },
+
+ /**
+ * This function assumes that if any slice has a cpu duration then
+ * then the group is considered to have cpu duration.
+ */
+ hasCpuDuration_() {
+ if (this.slices.some(function(slice) {
+ return slice.cpuDuration !== undefined;
+ })) return true;
+ return false;
+ },
+
+ /**
+ * Construct subSlices for this group.
+ * Populate the group topLevelSlices, parent slices get a subSlices[],
+ * a selfThreadTime and a selfTime, child slices get a parentSlice
+ * reference.
+ */
+ createSubSlices() {
+ this.haveTopLevelSlicesBeenBuilt = true;
+ this.createSubSlicesImpl_();
+ // If another source has cpu time, we can augment the cpuDuration of the
+ // slices in the group with that cpu time. This should be done only if
+ // the original source does not include cpuDuration.
+ if (!this.hasCpuDuration_() && this.parentContainer.timeSlices) {
+ this.addCpuTimeToSubslices_(this.parentContainer.timeSlices);
+ }
+ this.slices.forEach(function(slice) {
+ let selfTime = slice.duration;
+ for (let i = 0; i < slice.subSlices.length; i++) {
+ selfTime -= slice.subSlices[i].duration;
+ }
+ slice.selfTime = selfTime;
+
+ if (slice.cpuDuration === undefined) return;
+
+ let cpuSelfTime = slice.cpuDuration;
+ for (let i = 0; i < slice.subSlices.length; i++) {
+ if (slice.subSlices[i].cpuDuration !== undefined) {
+ cpuSelfTime -= slice.subSlices[i].cpuDuration;
+ }
+ }
+ slice.cpuSelfTime = cpuSelfTime;
+ });
+ },
+ createSubSlicesImpl_() {
+ const precisionUnit = this.model.intrinsicTimeUnit;
+
+
+ // Note that this doesn't check whether |child| should be added to
+ // |parent|'s descendant slices instead of |parent| directly.
+ function addSliceIfBounds(parent, child) {
+ if (parent.bounds(child, precisionUnit)) {
+ child.parentSlice = parent;
+ if (parent.subSlices === undefined) {
+ parent.subSlices = [];
+ }
+ parent.subSlices.push(child);
+ return true;
+ }
+ return false;
+ }
+
+ if (!this.slices.length) return;
+
+ const ops = [];
+ for (let i = 0; i < this.slices.length; i++) {
+ if (this.slices[i].subSlices) {
+ this.slices[i].subSlices.splice(0,
+ this.slices[i].subSlices.length);
+ }
+ ops.push(i);
+ }
+
+ const originalSlices = this.slices;
+ ops.sort(function(ix, iy) {
+ const x = originalSlices[ix];
+ const y = originalSlices[iy];
+ if (x.start !== y.start) {
+ return x.start - y.start;
+ }
+
+ // Elements get inserted into the slices array in order of when the
+ // slices start. Because slices must be properly nested, we break
+ // start-time ties by assuming that the elements appearing earlier
+ // in the slices array (and thus ending earlier) start earlier.
+ return ix - iy;
+ });
+
+ const slices = new Array(this.slices.length);
+ for (let i = 0; i < ops.length; i++) {
+ slices[i] = originalSlices[ops[i]];
+ }
+
+ // Actually build the subrows.
+ let rootSlice = slices[0];
+ this.topLevelSlices = [];
+ this.topLevelSlices.push(rootSlice);
+ rootSlice.isTopLevel = true;
+ for (let i = 1; i < slices.length; i++) {
+ const slice = slices[i];
+ while (rootSlice !== undefined &&
+ (!addSliceIfBounds(rootSlice, slice))) {
+ rootSlice = rootSlice.parentSlice;
+ }
+ if (rootSlice === undefined) {
+ this.topLevelSlices.push(slice);
+ slice.isTopLevel = true;
+ }
+ rootSlice = slice;
+ }
+
+ // Keep the slices in sorted form.
+ this.slices = slices;
+ },
+ addCpuTimeToSubslices_(timeSlices) {
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ let sliceIdx = 0;
+ timeSlices.forEach(function(timeSlice) {
+ if (timeSlice.schedulingState === SCHEDULING_STATE.RUNNING) {
+ while (sliceIdx < this.topLevelSlices.length) {
+ if (this.addCpuTimeToSubslice_(this.topLevelSlices[sliceIdx],
+ timeSlice)) {
+ // The current top-level slice and children are fully
+ // accounted for, proceed to next top-level slice.
+ sliceIdx++;
+ } else {
+ // The current top-level runs beyond the time slice, break out
+ // so we can potentially add more time slices to it
+ break;
+ }
+ }
+ }
+ }, this);
+ },
+ /* Add run-time of this timeSlice to the passed in slice
+ * and all of it's children (recursively).
+ * Returns whether the slice ends before or at the end of the
+ * time slice, signaling we are done with this slice.
+ */
+ addCpuTimeToSubslice_(slice, timeSlice) {
+ // Make sure they overlap
+ if (slice.start > timeSlice.end || slice.end < timeSlice.start) {
+ return slice.end <= timeSlice.end;
+ }
+
+ // Compute actual overlap
+ let duration = timeSlice.duration;
+ if (slice.start > timeSlice.start) {
+ duration -= slice.start - timeSlice.start;
+ }
+ if (timeSlice.end > slice.end) {
+ duration -= timeSlice.end - slice.end;
+ }
+
+ if (slice.cpuDuration) {
+ slice.cpuDuration += duration;
+ } else {
+ slice.cpuDuration = duration;
+ }
+
+ for (let i = 0; i < slice.subSlices.length; i++) {
+ this.addCpuTimeToSubslice_(slice.subSlices[i], timeSlice);
+ }
+
+ return slice.end <= timeSlice.end;
+ }
+ };
+
+ /**
+ * Merge two slice groups.
+ *
+ * If the two groups do not nest properly some of the slices of groupB will
+ * be split to accomodate the improper nesting. This is done to accomodate
+ * combined kernel and userland call stacks on Android. Because userland
+ * tracing is done by writing to the trace_marker file, the kernel calls
+ * that get invoked as part of that write may not be properly nested with
+ * the userland call trace. For example the following sequence may occur:
+ *
+ * kernel enter sys_write (the write to trace_marker)
+ * user enter some_function
+ * kernel exit sys_write
+ * ...
+ * kernel enter sys_write (the write to trace_marker)
+ * user exit some_function
+ * kernel exit sys_write
+ *
+ * This is handled by splitting the sys_write call into two slices as
+ * follows:
+ *
+ * | sys_write | some_function | sys_write (cont.) |
+ * | sys_write (cont.) | | sys_write |
+ *
+ * The colorId of both parts of the split slices are kept the same, and the
+ * " (cont.)" suffix is appended to the later parts of a split slice.
+ *
+ * The two input SliceGroups are not modified by this, and the merged
+ * SliceGroup will contain a copy of each of the input groups' slices (those
+ * copies may be split).
+ */
+ SliceGroup.merge = function(groupA, groupB) {
+ // This is implemented by traversing the two slice groups in reverse
+ // order. The slices in each group are sorted by ascending end-time, so
+ // we must do the traversal from back to front in order to maintain the
+ // sorting.
+ //
+ // We traverse the two groups simultaneously, merging as we go. At each
+ // iteration we choose the group from which to take the next slice based
+ // on which group's next slice has the greater end-time. During this
+ // traversal we maintain a stack of currently "open" slices for each input
+ // group. A slice is considered "open" from the time it gets reached in
+ // our input group traversal to the time we reach an slice in this
+ // traversal with an end-time before the start time of the "open" slice.
+ //
+ // Each time a slice from groupA is opened or closed (events corresponding
+ // to the end-time and start-time of the input slice, respectively) we
+ // split all of the currently open slices from groupB.
+
+ if (groupA.openPartialSlices_.length > 0) {
+ throw new Error('groupA has open partial slices');
+ }
+
+ if (groupB.openPartialSlices_.length > 0) {
+ throw new Error('groupB has open partial slices');
+ }
+
+ if (groupA.parentContainer !== groupB.parentContainer) {
+ throw new Error('Different parent threads. Cannot merge');
+ }
+
+ if (groupA.sliceConstructor !== groupB.sliceConstructor) {
+ throw new Error('Different slice constructors. Cannot merge');
+ }
+
+ const result = new SliceGroup(groupA.parentContainer,
+ groupA.sliceConstructor,
+ groupA.name_);
+
+ const slicesA = groupA.slices;
+ const slicesB = groupB.slices;
+ let idxA = 0;
+ let idxB = 0;
+ const openA = [];
+ const openB = [];
+
+ const splitOpenSlices = function(when) {
+ for (let i = 0; i < openB.length; i++) {
+ const oldSlice = openB[i];
+ const oldEnd = oldSlice.end;
+ if (when < oldSlice.start || oldEnd < when) {
+ throw new Error('slice should not be split');
+ }
+
+ const newSlice = result.copySlice(oldSlice);
+ newSlice.start = when;
+ newSlice.duration = oldEnd - when;
+ if (newSlice.title.indexOf(' (cont.)') === -1) {
+ newSlice.title += ' (cont.)';
+ }
+ oldSlice.duration = when - oldSlice.start;
+ openB[i] = newSlice;
+ result.pushSlice(newSlice);
+ }
+ };
+
+ const closeOpenSlices = function(upTo) {
+ while (openA.length > 0 || openB.length > 0) {
+ const nextA = openA[openA.length - 1];
+ const nextB = openB[openB.length - 1];
+ const endA = nextA && nextA.end;
+ const endB = nextB && nextB.end;
+
+ if ((endA === undefined || endA > upTo) &&
+ (endB === undefined || endB > upTo)) {
+ return;
+ }
+
+ if (endB === undefined || endA < endB) {
+ splitOpenSlices(endA);
+ openA.pop();
+ } else {
+ openB.pop();
+ }
+ }
+ };
+
+ while (idxA < slicesA.length || idxB < slicesB.length) {
+ const sA = slicesA[idxA];
+ const sB = slicesB[idxB];
+ let nextSlice;
+ let isFromB;
+
+ if (sA === undefined || (sB !== undefined && sA.start > sB.start)) {
+ nextSlice = result.copySlice(sB);
+ isFromB = true;
+ idxB++;
+ } else {
+ nextSlice = result.copySlice(sA);
+ isFromB = false;
+ idxA++;
+ }
+
+ closeOpenSlices(nextSlice.start);
+
+ result.pushSlice(nextSlice);
+
+ if (isFromB) {
+ openB.push(nextSlice);
+ } else {
+ splitOpenSlices(nextSlice.start);
+ openA.push(nextSlice);
+ }
+ }
+
+ closeOpenSlices();
+
+ return result;
+ };
+
+ return {
+ SliceGroup,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/slice_group_test.html b/chromium/third_party/catapult/tracing/tracing/model/slice_group_test.html
new file mode 100644
index 00000000000..573456fba82
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/slice_group_test.html
@@ -0,0 +1,935 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Slice = tr.model.Slice;
+ const SliceGroup = tr.model.SliceGroup;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newThreadSlice = tr.c.TestUtils.newThreadSlice;
+ const newModel = tr.c.TestUtils.newModel;
+ const newFakeThread = tr.c.TestUtils.newFakeThread;
+
+ test('basicBeginEnd', function() {
+ const group = new SliceGroup(newFakeThread());
+ assert.strictEqual(group.openSliceCount, 0);
+ const sliceA = group.beginSlice('', 'a', 1, {a: 1});
+ assert.strictEqual(group.openSliceCount, 1);
+ assert.strictEqual(sliceA.title, 'a');
+ assert.strictEqual(sliceA.start, 1);
+ assert.strictEqual(sliceA.args.a, 1);
+
+ const sliceB = group.endSlice(3);
+ assert.strictEqual(sliceA, sliceB);
+ assert.strictEqual(sliceB.duration, 2);
+ });
+
+ test('subSlicesBuilderBasic', function() {
+ const group = new SliceGroup(newFakeThread());
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 2}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 3, duration: 1}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 2);
+ assert.deepEqual(group.topLevelSlices, [sA, sB]);
+ assert.strictEqual(group.findSliceAtTs(0), undefined);
+ assert.strictEqual(group.findSliceAtTs(1), sA);
+ assert.strictEqual(group.findSliceAtTs(3), sA);
+ assert.strictEqual(group.findSliceAtTs(3.1), sB);
+ assert.strictEqual(group.findSliceAtTs(4), sB);
+ assert.strictEqual(group.findSliceAtTs(5), undefined);
+ });
+
+ test('subSlicesBuilderBasic2', function() {
+ const group = new SliceGroup(newFakeThread());
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 4}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 3, duration: 1}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 1);
+ assert.deepEqual(group.topLevelSlices, [sA]);
+
+ assert.strictEqual(sA.subSlices.length, 1);
+ assert.deepEqual(sA.subSlices, [sB]);
+ assert.strictEqual(sA.selfTime, 3);
+
+ assert.strictEqual(sA, sB.parentSlice);
+ assert.isTrue(sA.isTopLevel);
+ assert.isFalse(sB.isTopLevel);
+ });
+
+ test('subSlicesBuilderNestedExactly', function() {
+ const group = new SliceGroup(newFakeThread());
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 1, duration: 4}));
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 4}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 1);
+ assert.deepEqual(group.topLevelSlices, [sB]);
+
+ assert.strictEqual(sB.subSlices.length, 1);
+ assert.deepEqual(sB.subSlices, [sA]);
+ assert.strictEqual(sB.selfTime, 0);
+
+ assert.strictEqual(sB, sA.parentSlice);
+ assert.isTrue(sB.isTopLevel);
+ assert.isFalse(sA.isTopLevel);
+
+ assert.strictEqual(group.findSliceAtTs(0), undefined);
+ assert.strictEqual(group.findSliceAtTs(1), sA);
+ assert.strictEqual(group.findSliceAtTs(2), sA);
+ assert.strictEqual(group.findSliceAtTs(5), sA);
+ assert.strictEqual(group.findSliceAtTs(6), undefined);
+ });
+
+ test('subSlicesBuilderInstantEvents', function() {
+ const group = new SliceGroup(newFakeThread());
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 0}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 2, duration: 0}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 2);
+ assert.deepEqual(group.topLevelSlices, [sA, sB]);
+ assert.strictEqual(group.findSliceAtTs(1), sA);
+ assert.strictEqual(group.findSliceAtTs(1.5), undefined);
+ assert.strictEqual(group.findSliceAtTs(2), sB);
+ });
+
+ test('subSlicesBuilderTwoInstantEvents', function() {
+ const group = new SliceGroup(newFakeThread());
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 0}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 1, duration: 0}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 1);
+ assert.deepEqual(group.topLevelSlices, [sA]);
+
+ assert.strictEqual(sA.subSlices.length, 1);
+ assert.deepEqual(sA.subSlices, [sB]);
+ assert.strictEqual(sA.selfTime, 0);
+
+ assert.strictEqual(sA, sB.parentSlice);
+ assert.isTrue(sA.isTopLevel);
+ assert.isFalse(sB.isTopLevel);
+ assert.strictEqual(group.findSliceAtTs(1), sB);
+ assert.strictEqual(group.findSliceAtTs(1.0001), undefined);
+ });
+
+ test('subSlicesBuilderOutOfOrderAddition', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // Pattern being tested:
+ // [ a ][ b ]
+ // Where insertion is done backward.
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 3, duration: 1}));
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 2}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 2);
+ assert.deepEqual(group.topLevelSlices, [sA, sB]);
+ assert.isTrue(sA.isTopLevel);
+ assert.isTrue(sB.isTopLevel);
+ assert.strictEqual(group.findSliceAtTs(3), sA);
+ });
+
+ test('subRowBuilderOutOfOrderAddition2', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // Pattern being tested:
+ // [ a ]
+ // [ b ]
+ // Where insertion is done backward.
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 3, duration: 1}));
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 5}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 1);
+ assert.deepEqual(group.topLevelSlices, [sA]);
+
+ assert.strictEqual(sA.subSlices.length, 1);
+ assert.deepEqual(sA.subSlices, [sB]);
+ assert.strictEqual(sA.selfTime, 4);
+
+ assert.strictEqual(sA, sB.parentSlice);
+ assert.isTrue(sA.isTopLevel);
+ assert.isFalse(sB.isTopLevel);
+ assert.strictEqual(group.findSliceAtTs(1.5), sA);
+ assert.strictEqual(group.findSliceAtTs(3), sB);
+ assert.strictEqual(group.findSliceAtTs(3.5), sB);
+ assert.strictEqual(group.findSliceAtTs(4), sB);
+ assert.strictEqual(group.findSliceAtTs(4.5), sA);
+ });
+
+ test('subSlicesBuilderOnNestedZeroLength', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // Pattern being tested:
+ // [ a ]
+ // [ b1 ] []<- b2 where b2.duration = 0 and b2.end === a.end.
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 3}));
+ const sB1 = group.pushSlice(newSliceEx(
+ {title: 'b1', start: 1, duration: 2}));
+ const sB2 = group.pushSlice(newSliceEx(
+ {title: 'b2', start: 4, duration: 0}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 1);
+ assert.deepEqual(group.topLevelSlices, [sA]);
+
+ assert.strictEqual(sA.subSlices.length, 2);
+ assert.deepEqual(sA.subSlices, [sB1, sB2]);
+ assert.strictEqual(sA.selfTime, 1);
+
+ assert.strictEqual(sA, sB1.parentSlice);
+ assert.strictEqual(sA, sB2.parentSlice);
+ assert.strictEqual(group.findSliceAtTs(1), sB1);
+ assert.strictEqual(group.findSliceAtTs(4), sB2);
+ });
+
+ test('subSlicesBuilderOnGroup1', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // Pattern being tested:
+ // [ a ] [ c ]
+ // [ b ]
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 3}));
+ const sB = group.pushSlice(newSliceEx(
+ {title: 'b', start: 1.5, duration: 1}));
+ const sC = group.pushSlice(newSliceEx({title: 'c', start: 5, duration: 0}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 2);
+ assert.deepEqual(group.topLevelSlices, [sA, sC]);
+
+ assert.strictEqual(sA.subSlices.length, 1);
+ assert.deepEqual(sA.subSlices, [sB]);
+ assert.strictEqual(sA.selfTime, 2);
+
+ assert.strictEqual(sA, sB.parentSlice);
+ assert.strictEqual(group.findSliceAtTs(1), sA);
+ assert.strictEqual(group.findSliceAtTs(2), sB);
+ assert.strictEqual(group.findSliceAtTs(3), sA);
+ assert.strictEqual(group.findSliceAtTs(4.5), undefined);
+ assert.strictEqual(group.findSliceAtTs(5), sC);
+ });
+
+ test('subSlicesBuilderOnGroup2', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // Pattern being tested:
+ // [ a ] [ d ]
+ // [ b ]
+ // [ c ]
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 3}));
+ const sB = group.pushSlice(newSliceEx(
+ {title: 'b', start: 1.5, duration: 1}));
+ const sC = group.pushSlice(newSliceEx(
+ {title: 'c', start: 1.75, duration: 0.5}));
+ const sD = group.pushSlice(newSliceEx(
+ {title: 'd', start: 5, duration: 0.25}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 2);
+ assert.deepEqual(group.topLevelSlices, [sA, sD]);
+
+ assert.strictEqual(sA.subSlices.length, 1);
+ assert.deepEqual(sA.subSlices, [sB]);
+ assert.strictEqual(sA.selfTime, 2);
+
+ assert.strictEqual(sA, sB.parentSlice);
+ assert.strictEqual(sB.subSlices.length, 1);
+ assert.deepEqual(sB.subSlices, [sC]);
+ assert.strictEqual(sB.selfTime, 0.5);
+
+ assert.strictEqual(sB, sC.parentSlice);
+ assert.strictEqual(group.findSliceAtTs(2), sC);
+ });
+
+ test('findFirstSlice', function() {
+ const group = new SliceGroup(newFakeThread());
+ // Pattern being tested:
+ // [ a ] [ d ]
+ // [b] [ c ] where b is dur=0
+ const sC = group.pushSlice(newSliceEx({title: 'c', start: 2, end: 3}));
+ const sD = group.pushSlice(newSliceEx({title: 'd', start: 5, end: 6}));
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, end: 4}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 1, end: 1}));
+
+ assert.throws(group.findFirstSlice);
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.findFirstSlice(), sA);
+ });
+
+ test('findNextSliceAfterBasic', function() {
+ const group = new SliceGroup(newFakeThread());
+ // Pattern being tested:
+ // [ a ] [ d ]
+ // [b] [ c ] where b is dur=0
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, end: 4}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 1, end: 1}));
+ const sC = group.pushSlice(newSliceEx({title: 'c', start: 2, end: 3}));
+ const sD = group.pushSlice(newSliceEx({title: 'd', start: 5, end: 6}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.findNextSliceAfter(0, 0), sA);
+ assert.strictEqual(group.findNextSliceAfter(1, sA.guid), sB);
+ assert.strictEqual(group.findNextSliceAfter(1, sB.guid), sC);
+ assert.strictEqual(group.findNextSliceAfter(2, sC.guid), sD);
+ assert.strictEqual(group.findNextSliceAfter(6, 0), undefined);
+ });
+
+ test('subSlicesBuilderTolerateFPInaccuracy', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // Pattern being tested:
+ // [ a ]
+ // [ b ] where b.end contains a tiny FP calculation error.
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 3}));
+ const sB = group.pushSlice(newSliceEx(
+ {title: 'b', start: 1, duration: 3.0000000001}));
+
+ group.createSubSlices();
+
+ assert.strictEqual(group.topLevelSlices.length, 1);
+ assert.deepEqual(group.topLevelSlices, [sA]);
+
+ assert.strictEqual(sA.subSlices.length, 1);
+ assert.deepEqual(sA.subSlices, [sB]);
+ assert.strictEqual(sA, sB.parentSlice);
+ assert.strictEqual(group.findSliceAtTs(1), sB);
+ assert.strictEqual(group.findSliceAtTs(3), sB);
+ });
+
+ test('basicMerge', function() {
+ function TestSlice(
+ cat, title, colorId, start, args, opt_duration,
+ opt_cpuStart, opt_cpuDuration) {
+ Slice.call(this, cat, title, colorId, start, args, opt_duration,
+ opt_cpuStart, opt_cpuDuration);
+ }
+ TestSlice.prototype = {
+ __proto__: Slice.prototype
+ };
+ TestSlice.subTypes = {
+ getConstructor(category, title) {
+ return TestSlice;
+ }
+ };
+
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread, TestSlice);
+ const b = new SliceGroup(thread, TestSlice);
+ a.beginSlice('', 'one', 1);
+ a.endSlice(2);
+ b.beginSlice('', 'two', 3);
+ b.endSlice(5);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 2);
+
+ assert.strictEqual(m.slices[0].title, 'one');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 1);
+
+ assert.strictEqual(m.slices[1].title, 'two');
+ assert.strictEqual(m.slices[1].start, 3);
+ assert.strictEqual(m.slices[1].duration, 2);
+
+ // ensure constructor merged correctly
+ assert.strictEqual(m.sliceConstructor, TestSlice);
+ });
+
+ test('nestedMerge', function() {
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread);
+ const b = new SliceGroup(thread);
+ a.beginSlice('', 'one', 1);
+ a.endSlice(4);
+ b.beginSlice('', 'two', 2);
+ b.endSlice(3);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 2);
+
+ assert.strictEqual(m.slices[0].title, 'one');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 3);
+
+ assert.strictEqual(m.slices[1].title, 'two');
+ assert.strictEqual(m.slices[1].start, 2);
+ assert.strictEqual(m.slices[1].duration, 1);
+ });
+
+ test('startSplitMerge', function() {
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread);
+ const b = new SliceGroup(thread);
+ a.beginSlice('', 'one', 2);
+ a.endSlice(4);
+ b.beginSlice('', 'two', 1);
+ b.endSlice(3);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 3);
+
+ assert.strictEqual(m.slices[0].title, 'two');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 1);
+
+ assert.strictEqual(m.slices[1].title, 'one');
+ assert.strictEqual(m.slices[1].start, 2);
+ assert.strictEqual(m.slices[1].duration, 2);
+
+ assert.strictEqual(m.slices[2].title, 'two (cont.)');
+ assert.strictEqual(m.slices[2].start, 2);
+ assert.strictEqual(m.slices[2].duration, 1);
+ });
+
+ test('startSplitTwoMerge', function() {
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread);
+ const b = new SliceGroup(thread);
+ a.beginSlice('', 'one', 3);
+ a.endSlice(6);
+ b.beginSlice('', 'two', 1);
+ b.beginSlice('', 'three', 2);
+ b.endSlice(4);
+ b.endSlice(5);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 5);
+
+ assert.strictEqual(m.slices[0].title, 'two');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 2);
+
+ assert.strictEqual(m.slices[1].title, 'three');
+ assert.strictEqual(m.slices[1].start, 2);
+ assert.strictEqual(m.slices[1].duration, 1);
+
+ assert.strictEqual(m.slices[2].title, 'one');
+ assert.strictEqual(m.slices[2].start, 3);
+ assert.strictEqual(m.slices[2].duration, 3);
+
+ assert.strictEqual(m.slices[3].title, 'two (cont.)');
+ assert.strictEqual(m.slices[3].start, 3);
+ assert.strictEqual(m.slices[3].duration, 2);
+
+ assert.strictEqual(m.slices[4].title, 'three (cont.)');
+ assert.strictEqual(m.slices[4].start, 3);
+ assert.strictEqual(m.slices[4].duration, 1);
+ });
+
+ test('startSplitTwiceMerge', function() {
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread);
+ const b = new SliceGroup(thread);
+ a.beginSlice('', 'one', 2);
+ a.beginSlice('', 'two', 3);
+ a.endSlice(5);
+ a.endSlice(6);
+ b.beginSlice('', 'three', 1);
+ b.endSlice(4);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 5);
+
+ assert.strictEqual(m.slices[0].title, 'three');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 1);
+
+ assert.strictEqual(m.slices[1].title, 'one');
+ assert.strictEqual(m.slices[1].start, 2);
+ assert.strictEqual(m.slices[1].duration, 4);
+
+ assert.strictEqual(m.slices[2].title, 'three (cont.)');
+ assert.strictEqual(m.slices[2].start, 2);
+ assert.strictEqual(m.slices[2].duration, 1);
+
+ assert.strictEqual(m.slices[3].title, 'two');
+ assert.strictEqual(m.slices[3].start, 3);
+ assert.strictEqual(m.slices[3].duration, 2);
+
+ assert.strictEqual(m.slices[4].title, 'three (cont.)');
+ assert.strictEqual(m.slices[4].start, 3);
+ assert.strictEqual(m.slices[4].duration, 1);
+ });
+
+ test('endSplitMerge', function() {
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread);
+ const b = new SliceGroup(thread);
+ a.beginSlice('', 'one', 1);
+ a.endSlice(3);
+ b.beginSlice('', 'two', 2);
+ b.endSlice(4);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 3);
+
+ assert.strictEqual(m.slices[0].title, 'one');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 2);
+
+ assert.strictEqual(m.slices[1].title, 'two');
+ assert.strictEqual(m.slices[1].start, 2);
+ assert.strictEqual(m.slices[1].duration, 1);
+
+ assert.strictEqual(m.slices[2].title, 'two (cont.)');
+ assert.strictEqual(m.slices[2].start, 3);
+ assert.strictEqual(m.slices[2].duration, 1);
+ });
+
+ test('endSplitTwoMerge', function() {
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread);
+ const b = new SliceGroup(thread);
+ a.beginSlice('', 'one', 1);
+ a.endSlice(4);
+ b.beginSlice('', 'two', 2);
+ b.beginSlice('', 'three', 3);
+ b.endSlice(5);
+ b.endSlice(6);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 5);
+
+ assert.strictEqual(m.slices[0].title, 'one');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 3);
+
+ assert.strictEqual(m.slices[1].title, 'two');
+ assert.strictEqual(m.slices[1].start, 2);
+ assert.strictEqual(m.slices[1].duration, 2);
+
+ assert.strictEqual(m.slices[2].title, 'three');
+ assert.strictEqual(m.slices[2].start, 3);
+ assert.strictEqual(m.slices[2].duration, 1);
+
+ assert.strictEqual(m.slices[3].title, 'two (cont.)');
+ assert.strictEqual(m.slices[3].start, 4);
+ assert.strictEqual(m.slices[3].duration, 2);
+
+ assert.strictEqual(m.slices[4].title, 'three (cont.)');
+ assert.strictEqual(m.slices[4].start, 4);
+ assert.strictEqual(m.slices[4].duration, 1);
+ });
+
+ test('endSplitTwiceMerge', function() {
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread);
+ const b = new SliceGroup(thread);
+ a.beginSlice('', 'one', 1);
+ a.beginSlice('', 'two', 2);
+ a.endSlice(4);
+ a.endSlice(5);
+ b.beginSlice('', 'three', 3);
+ b.endSlice(6);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 5);
+
+ assert.strictEqual(m.slices[0].title, 'one');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 4);
+
+ assert.strictEqual(m.slices[1].title, 'two');
+ assert.strictEqual(m.slices[1].start, 2);
+ assert.strictEqual(m.slices[1].duration, 2);
+
+ assert.strictEqual(m.slices[2].title, 'three');
+ assert.strictEqual(m.slices[2].start, 3);
+ assert.strictEqual(m.slices[2].duration, 1);
+
+ assert.strictEqual(m.slices[3].title, 'three (cont.)');
+ assert.strictEqual(m.slices[3].start, 4);
+ assert.strictEqual(m.slices[3].duration, 1);
+
+ assert.strictEqual(m.slices[4].title, 'three (cont.)');
+ assert.strictEqual(m.slices[4].start, 5);
+ assert.strictEqual(m.slices[4].duration, 1);
+ });
+
+ // Input:
+ // A: | one | | two |
+ //
+ // B: | three |
+ //
+ // Output:
+ // | one | three | two |
+ // | three | | three |
+ test('splitTwiceMerge', function() {
+ const thread = newFakeThread();
+ const a = new SliceGroup(thread);
+ const b = new SliceGroup(thread);
+ a.beginSlice('', 'one', 1);
+ a.endSlice(3);
+ a.beginSlice('', 'two', 4);
+ a.endSlice(6);
+ b.beginSlice('', 'three', 2);
+ b.endSlice(5);
+
+ const m = SliceGroup.merge(a, b);
+ assert.strictEqual(m.slices.length, 5);
+
+ assert.strictEqual(m.slices[0].title, 'one');
+ assert.strictEqual(m.slices[0].start, 1);
+ assert.strictEqual(m.slices[0].duration, 2);
+
+ assert.strictEqual(m.slices[1].title, 'three');
+ assert.strictEqual(m.slices[1].start, 2);
+ assert.strictEqual(m.slices[1].duration, 1);
+
+ assert.strictEqual(m.slices[2].title, 'three (cont.)');
+ assert.strictEqual(m.slices[2].start, 3);
+ assert.strictEqual(m.slices[2].duration, 1);
+
+ assert.strictEqual(m.slices[3].title, 'two');
+ assert.strictEqual(m.slices[3].start, 4);
+ assert.strictEqual(m.slices[3].duration, 2);
+
+ assert.strictEqual(m.slices[4].title, 'three (cont.)');
+ assert.strictEqual(m.slices[4].start, 4);
+ assert.strictEqual(m.slices[4].duration, 1);
+ });
+
+ test('bounds', function() {
+ const group = new SliceGroup(newFakeThread());
+ group.updateBounds();
+ assert.isUndefined(group.bounds.min);
+ assert.isUndefined(group.bounds.max);
+
+ group.pushSlice(newSliceEx({start: 1, duration: 3}));
+ group.pushSlice(newSliceEx({start: 7, duration: 2}));
+ group.updateBounds();
+ assert.strictEqual(group.bounds.min, 1);
+ assert.strictEqual(group.bounds.max, 9);
+ });
+
+ test('boundsWithPartial', function() {
+ const group = new SliceGroup(newFakeThread());
+ group.beginSlice('', 'a', 7);
+ group.updateBounds();
+ assert.strictEqual(group.bounds.min, 7);
+ assert.strictEqual(group.bounds.max, 7);
+ });
+
+ test('boundsWithTwoPartials', function() {
+ const group = new SliceGroup(newFakeThread());
+ group.beginSlice('', 'a', 0);
+ group.beginSlice('', 'a', 1);
+ group.updateBounds();
+ assert.strictEqual(group.bounds.min, 0);
+ assert.strictEqual(group.bounds.max, 1);
+ });
+
+ test('boundsWithBothPartialAndRegular', function() {
+ const group = new SliceGroup(newFakeThread());
+ group.updateBounds();
+ assert.isUndefined(group.bounds.min);
+ assert.isUndefined(group.bounds.max);
+
+ group.pushSlice(newSliceEx({start: 1, duration: 3}));
+ group.beginSlice('', 'a', 7);
+ group.updateBounds();
+ assert.strictEqual(group.bounds.min, 1);
+ assert.strictEqual(group.bounds.max, 7);
+ });
+
+ test('autocloserBasic', function() {
+ const group = new SliceGroup(newFakeThread());
+ assert.strictEqual(0, group.openSliceCount);
+
+ group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 0.5}));
+
+ group.beginSlice('', 'b', 2);
+ group.beginSlice('', 'c', 2.5);
+ group.endSlice(3);
+
+ group.autoCloseOpenSlices();
+ group.updateBounds();
+
+ assert.strictEqual(group.bounds.min, 1);
+ assert.strictEqual(group.bounds.max, 3);
+ assert.strictEqual(group.slices.length, 3);
+
+ assert.strictEqual(group.slices[0].title, 'a');
+ assert.isFalse(group.slices[0].didNotFinish);
+
+ assert.strictEqual(group.slices[1].title, 'b');
+ assert.isTrue(group.slices[1].didNotFinish);
+ assert.strictEqual(group.slices[1].duration, 1);
+
+ assert.strictEqual(group.slices[2].title, 'c');
+ assert.isFalse(group.slices[2].didNotFinish);
+ });
+
+ test('autocloserWithSubTasks', function() {
+ const group = new SliceGroup(newFakeThread());
+ assert.strictEqual(0, group.openSliceCount);
+
+ group.beginSlice('', 'a', 1);
+ group.beginSlice('', 'b1', 2);
+ group.endSlice(3);
+ group.beginSlice('', 'b2', 3);
+
+ group.autoCloseOpenSlices();
+ assert.strictEqual(group.slices.length, 3);
+
+ assert.strictEqual(group.slices[0].title, 'a');
+ assert.isTrue(group.slices[0].didNotFinish);
+ assert.strictEqual(group.slices[0].duration, 2);
+
+ assert.strictEqual(group.slices[1].title, 'b1');
+ assert.isFalse(group.slices[1].didNotFinish);
+ assert.strictEqual(group.slices[1].duration, 1);
+
+ assert.strictEqual(group.slices[2].title, 'b2');
+ assert.isTrue(group.slices[2].didNotFinish);
+ assert.strictEqual(group.slices[2].duration, 0);
+ });
+
+ test('autocloseCompleteSlice', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ group.pushCompleteSlice('', 'a', 1, undefined);
+ group.pushCompleteSlice('', 'b', 2, 3);
+
+ group.autoCloseOpenSlices();
+ assert.strictEqual(group.slices.length, 2);
+
+ assert.strictEqual(group.slices[0].title, 'a');
+ assert.isTrue(group.slices[0].didNotFinish);
+ assert.strictEqual(group.slices[0].duration, 4);
+
+ assert.strictEqual(group.slices[1].title, 'b');
+ assert.isFalse(group.slices[1].didNotFinish);
+ assert.strictEqual(group.slices[1].duration, 3);
+ });
+
+ test('sliceGroupStableId', function() {
+ const model = new tr.Model();
+ const process = model.getOrCreateProcess(123);
+ const thread = process.getOrCreateThread(456);
+ const group = new SliceGroup(thread);
+
+ assert.strictEqual(process.stableId, 123);
+ assert.strictEqual(thread.stableId, '123.456');
+ assert.strictEqual(group.stableId, '123.456.SliceGroup');
+ });
+
+ test('getSlicesOfName', function() {
+ const group = new SliceGroup(newFakeThread());
+ const expected = [];
+
+ for (let i = 0; i < 10; i++) {
+ const aSlice = newSliceEx({title: 'a', start: i, duration: i + 1});
+ group.pushSlice(aSlice);
+ group.pushSlice(newSliceEx({title: 'b', start: i + 1, duration: i + 2}));
+ expected.push(aSlice);
+ }
+
+ assert.deepEqual(group.getSlicesOfName('a'), expected);
+ });
+
+ test('iterSlicesInTimeRange', function() {
+ const group = new SliceGroup(newFakeThread());
+ const expected = [];
+
+ for (let i = 0; i < 10; i++) {
+ const slice = newSliceEx({title: 'a', start: i, duration: 1});
+ group.pushSlice(slice);
+ if (4 <= i && i <= 7) {
+ expected.push(slice);
+ }
+ }
+ group.createSubSlices();
+
+ const observed = [];
+ group.iterSlicesInTimeRange(function(slice) { observed.push(slice); },
+ 4.5, 7.5);
+ assert.deepEqual(observed, expected);
+ });
+
+ test('computeCpuDurationNoOverlap', function() {
+ const model = new tr.Model();
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const process = model.getOrCreateProcess(123);
+ const t = process.getOrCreateThread(456);
+ t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 20),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 40, 10),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 50, 10)];
+ const group = new SliceGroup(t);
+ group.pushSlice(newSliceEx({title: 'draw', start: 0, duration: 20}));
+ group.pushSlice(newSliceEx({title: 'render', start: 60, duration: 20}));
+ group.createSubSlices();
+ assert.strictEqual(group.slices[0].cpuDuration, 0);
+ assert.strictEqual(group.slices[1].cpuDuration, 0);
+ });
+
+ test('computeCpuDurationPartialOverlap', function() {
+ const model = new tr.Model();
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const process = model.getOrCreateProcess(123);
+ const t = process.getOrCreateThread(456);
+ t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 20),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 40, 10),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 50, 10)];
+ const group = new SliceGroup(t);
+ group.pushSlice(newSliceEx({title: 'draw', start: 10, duration: 30}));
+ group.pushSlice(newSliceEx({title: 'render', start: 50, duration: 20}));
+ group.createSubSlices();
+ assert.strictEqual(group.slices[0].cpuDuration, 20);
+ assert.strictEqual(group.slices[1].cpuDuration, 10);
+ });
+
+ test('computeCpuDurationFullOverlap', function() {
+ const model = new tr.Model();
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const process = model.getOrCreateProcess(123);
+ const t = process.getOrCreateThread(456);
+ t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 20),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 40, 10),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 50, 20)];
+ const group = new SliceGroup(t);
+ group.pushSlice(newSliceEx({title: 'draw', start: 20, duration: 30}));
+ group.pushSlice(newSliceEx({title: 'render', start: 50, duration: 20}));
+ group.createSubSlices();
+ assert.strictEqual(group.slices[0].cpuDuration, 20);
+ assert.strictEqual(group.slices[1].cpuDuration, 20);
+ });
+
+ test('computeCpuSelfDurationWithSubslices', function() {
+ const model = new tr.Model();
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const process = model.getOrCreateProcess(123);
+ const t = process.getOrCreateThread(456);
+ t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 20),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 40, 10),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 50, 20)];
+ const group = new SliceGroup(t);
+ group.pushSlice(newSliceEx({title: 'draw', start: 20, duration: 30}));
+ group.pushSlice(newSliceEx({title: 'render', start: 21, duration: 8}));
+ group.pushSlice(newSliceEx({title: 'flush', start: 29, duration: 11}));
+ group.createSubSlices();
+ assert.strictEqual(group.slices[0].cpuDuration, 20);
+ assert.strictEqual(group.slices[0].cpuSelfTime, 1);
+ assert.strictEqual(group.slices[1].cpuDuration, 8);
+ assert.strictEqual(group.slices[1].cpuSelfTime, 8);
+ assert.strictEqual(group.slices[2].cpuDuration, 11);
+ assert.strictEqual(group.slices[2].cpuSelfTime, 11);
+ });
+
+ test('computeCpuDurationSmallTimeslices', function() {
+ const model = new tr.Model();
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const process = model.getOrCreateProcess(123);
+ const t = process.getOrCreateThread(456);
+ t.timeSlices = [newThreadSlice(t, SCHEDULING_STATE.RUNNING, 20, 1),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 21, 1),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 22, 1),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 23, 1),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 24, 1),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 25, 1),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 26, 1),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 27, 1),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 28, 1),
+ newThreadSlice(t, SCHEDULING_STATE.SLEEPING, 29, 1),
+ newThreadSlice(t, SCHEDULING_STATE.RUNNING, 30, 1)];
+ const group = new SliceGroup(t);
+ group.pushSlice(newSliceEx(
+ {title: 'draw', start: 20, duration: 11})); // 20,[22,24,26,28],30
+ group.pushSlice(newSliceEx(
+ {title: 'render', start: 22, duration: 8})); // 22,[24, 26, 28]
+ group.pushSlice(newSliceEx(
+ {title: 'flush', start: 24, duration: 6})); // 24, 26, 28
+ group.createSubSlices();
+ assert.strictEqual(group.slices[0].cpuDuration, 6);
+ assert.strictEqual(group.slices[0].cpuSelfTime, 2);
+ assert.strictEqual(group.slices[1].cpuDuration, 4);
+ assert.strictEqual(group.slices[1].cpuSelfTime, 1);
+ assert.strictEqual(group.slices[2].cpuDuration, 3);
+ assert.strictEqual(group.slices[2].cpuSelfTime, 3);
+ });
+
+ test('sliceParentContainerSetAtPush', function() {
+ const m = newModel(function(m) {
+ m.process = m.getOrCreateProcess(123);
+ m.thread = m.process.getOrCreateThread(456);
+ m.group = new SliceGroup(m.thread);
+
+ m.sA = m.group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+
+ m.group.createSubSlices();
+ });
+
+ assert.deepEqual(m.sA.parentContainer, m.thread);
+ });
+
+ test('getDescendantEventsInSortedRanges', function() {
+ // Create the following slices:
+ // 0 1 2 3 4 5 6 7 8 9 10
+ // <------------- 0 ------------->
+ // <- 2 -> <---- 3 ---->
+ // <- 1 ->
+ const group = new SliceGroup(newFakeThread());
+ group.pushSlice(newSliceEx({title: 's0', start: 0, end: 10}));
+ group.pushSlice(newSliceEx({title: 's1', start: 7, end: 9}));
+ group.pushSlice(newSliceEx({title: 's2', start: 3, end: 5}));
+ group.pushSlice(newSliceEx({title: 's3', start: 6, end: 10}));
+ group.createSubSlices();
+
+ // [0, 5] intersects s0 and s2.
+ const r1 = new tr.b.math.Range.fromExplicitRange(0, 5);
+ let slices = [...group.getDescendantEventsInSortedRanges([r1])];
+ assert.strictEqual(slices.length, 2);
+ assert.strictEqual(slices[0].title, 's0');
+ assert.strictEqual(slices[1].title, 's2');
+
+ // [10, 11] intersects s0 and s3.
+ const r2 = new tr.b.math.Range.fromExplicitRange(10, 11);
+ slices = [...group.getDescendantEventsInSortedRanges([r2])];
+ assert.strictEqual(slices.length, 2);
+ assert.strictEqual(slices[0].title, 's0');
+ assert.strictEqual(slices[1].title, 's3');
+
+ // [0, 5], [10, 11] intersects s0, s2, and s3.
+ slices = [...group.getDescendantEventsInSortedRanges([r1, r2])];
+ assert.strictEqual(slices.length, 3);
+ assert.strictEqual(slices[0].title, 's0');
+ assert.strictEqual(slices[1].title, 's2');
+ assert.strictEqual(slices[2].title, 's3');
+
+ // Ranges can be nested, too.
+ const r3 = new tr.b.math.Range.fromExplicitRange(1, 2);
+ slices = [...group.getDescendantEventsInSortedRanges([r1, r3])];
+ assert.strictEqual(slices.length, 2);
+ assert.strictEqual(slices[0].title, 's0');
+ assert.strictEqual(slices[1].title, 's2');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/slice_test.html b/chromium/third_party/catapult/tracing/tracing/model/slice_test.html
new file mode 100644
index 00000000000..a9d5b18ef7e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/slice_test.html
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Slice = tr.model.Slice;
+ const SliceGroup = tr.model.SliceGroup;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newFakeThread = tr.c.TestUtils.newFakeThread;
+
+ test('findDescendentSlice', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ const sA = group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.pushSlice(newSliceEx(
+ { title: 'sB', start: 0.0, duration: 4.0 }));
+ const sC = group.pushSlice(newSliceEx(
+ { title: 'sC', start: 0.0, duration: 2.0 }));
+
+ group.createSubSlices();
+
+ assert.deepEqual(sB, sA.findDescendentSlice('sB'));
+ assert.deepEqual(sC, sA.findDescendentSlice('sC'));
+ assert.isUndefined(sA.findDescendentSlice('sD'));
+ });
+
+ test('findTopmostSlicesRelativeToThisSliceBaseCase', function() {
+ const PREDICATE = slice => slice.title.startsWith('sC');
+
+ const group = new SliceGroup(newFakeThread());
+
+ const sC1 = group.pushSlice(newSliceEx(
+ { title: 'sC1', start: 0.0, duration: 10.0 }));
+ const sC2 = group.pushSlice(newSliceEx(
+ { title: 'sC2', start: 0.0, duration: 4.0 }));
+
+ group.createSubSlices();
+
+ const foundSlices = [];
+ for (const slice of sC1.findTopmostSlicesRelativeToThisSlice(PREDICATE)) {
+ foundSlices.push(slice);
+ }
+
+ assert.deepEqual([sC1], foundSlices);
+ });
+
+ test('findTopmostSlicesRelativeToThisSliceRecursive', function() {
+ const PREDICATE = slice => slice.title.startsWith('sC');
+
+ const group = new SliceGroup(newFakeThread());
+
+ const sD = group.pushSlice(newSliceEx(
+ { title: 'sD', start: 0.0, duration: 10.0 }));
+ const sC1 = group.pushSlice(newSliceEx(
+ { title: 'sC1', start: 0.0, duration: 4.0 }));
+ const sC2 = group.pushSlice(newSliceEx(
+ { title: 'sC2', start: 6.0, duration: 3.0 }));
+
+ group.createSubSlices();
+
+ const foundSlices = [];
+ for (const slice of sD.findTopmostSlicesRelativeToThisSlice(PREDICATE)) {
+ foundSlices.push(slice);
+ }
+ assert.deepEqual([sC1, sC2], foundSlices);
+ });
+
+ test('enumerateAllDescendents', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ const sA = group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.pushSlice(newSliceEx(
+ { title: 'sB', start: 0.0, duration: 4.0 }));
+ const sC = group.pushSlice(newSliceEx(
+ { title: 'sC', start: 0.0, duration: 2.0 }));
+
+ group.createSubSlices();
+
+ assert.deepEqual(sA.descendentSlices, [sB, sC]);
+ assert.deepEqual(sC.descendentSlices, []);
+ });
+
+ test('mostTopLevelSlice', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ const sA = group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.pushSlice(newSliceEx(
+ { title: 'sB', start: 0.0, duration: 4.0 }));
+ const sC = group.pushSlice(newSliceEx(
+ { title: 'sC', start: 0.0, duration: 2.0 }));
+
+ group.createSubSlices();
+
+ assert.strictEqual(sA.mostTopLevelSlice, sA);
+ assert.strictEqual(sB.mostTopLevelSlice, sA);
+ assert.strictEqual(sC.mostTopLevelSlice, sA);
+ });
+
+ test('enumerateAllAncestors', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ const sA = group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.pushSlice(newSliceEx(
+ { title: 'sB', start: 0.0, duration: 4.0 }));
+ const sC = group.pushSlice(newSliceEx(
+ { title: 'sC', start: 0.0, duration: 2.0 }));
+
+ group.createSubSlices();
+
+ // Note that we iterate ancestors from the leaves to the root
+ assert.deepEqual(sC.ancestorSlices, [sB, sA]);
+ assert.deepEqual(sA.ancestorSlices, []);
+ });
+
+ test('iterateAllSubsequentSlices', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // [ A ]
+ // [ B ][ D ][F]
+ // [C] [E]
+
+ const sA = group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.pushSlice(newSliceEx(
+ { title: 'sB', start: 0.0, duration: 4.0 }));
+ const sC = group.pushSlice(newSliceEx(
+ { title: 'sC', start: 0.0, duration: 2.0 }));
+ const sD = group.pushSlice(newSliceEx(
+ { title: 'sD', start: 5.0, duration: 2.0 }));
+ const sE = group.pushSlice(newSliceEx(
+ { title: 'sE', start: 5.0, duration: 1.0 }));
+ const sF = group.pushSlice(newSliceEx(
+ { title: 'sF', start: 8.0, duration: 2.0 }));
+
+ group.createSubSlices();
+
+ assert.deepEqual(sA.subsequentSlices, [sB, sC, sD, sE, sF]);
+ assert.deepEqual(sD.subsequentSlices, [sE, sF]);
+ assert.deepEqual(sF.subsequentSlices, []);
+ });
+
+ test('ancestorAndSubsequentSlices', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // [ A ]
+ // [ B ][ D ][F]
+ // [C] [E]
+
+ const sA = group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.pushSlice(newSliceEx(
+ { title: 'sB', start: 0.0, duration: 4.0 }));
+ const sC = group.pushSlice(newSliceEx(
+ { title: 'sC', start: 0.0, duration: 2.0 }));
+ const sD = group.pushSlice(newSliceEx(
+ { title: 'sD', start: 5.0, duration: 2.0 }));
+ const sE = group.pushSlice(newSliceEx(
+ { title: 'sE', start: 5.0, duration: 1.0 }));
+ const sF = group.pushSlice(newSliceEx(
+ { title: 'sF', start: 8.0, duration: 2.0 }));
+
+ group.createSubSlices();
+
+ assert.deepEqual(sD.ancestorAndSubsequentSlices, [sD, sA, sE, sF]);
+ });
+
+ test('entireHierarchy', function() {
+ const group = new SliceGroup(newFakeThread());
+
+ // [ A ]
+ // [ B ][ D ][F]
+ // [C] [E]
+
+ const sA = group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.pushSlice(newSliceEx(
+ { title: 'sB', start: 0.0, duration: 4.0 }));
+ const sC = group.pushSlice(newSliceEx(
+ { title: 'sC', start: 0.0, duration: 2.0 }));
+ const sD = group.pushSlice(newSliceEx(
+ { title: 'sD', start: 5.0, duration: 2.0 }));
+ const sE = group.pushSlice(newSliceEx(
+ { title: 'sE', start: 5.0, duration: 1.0 }));
+ const sF = group.pushSlice(newSliceEx(
+ { title: 'sF', start: 8.0, duration: 2.0 }));
+
+ group.createSubSlices();
+
+ assert.deepEqual(sD.entireHierarchy, [sA, sB, sC, sD, sE, sF]);
+ });
+
+ test('stableId', function() {
+ const thread = newFakeThread();
+ const group = thread.sliceGroup;
+
+ const sA = group.pushSlice(newSliceEx(
+ { title: 'sA', start: 0.0, duration: 10.0 }));
+ const sB = group.pushSlice(newSliceEx(
+ { title: 'sB', start: 10.0, duration: 20.0 }));
+ const sC = group.pushSlice(newSliceEx(
+ { title: 'sC', start: 20.0, duration: 30.0 }));
+
+ assert.strictEqual(group.stableId + '.0', sA.stableId);
+ assert.strictEqual(group.stableId + '.1', sB.stableId);
+ assert.strictEqual(group.stableId + '.2', sC.stableId);
+ });
+
+ test('cantInstantiateDirectly', function() {
+ assert.throws(function() {
+ new Slice('', 'Test', 0, 0, { });
+ });
+ });
+
+ test('canInstantiateSubclasses', function() {
+ function TestSlice() {
+ Slice.call(this, '', 'Test', 0, 0, { });
+ }
+ TestSlice.prototype = {
+ __proto__: Slice.prototype
+ };
+ assert.doesNotThrow(function() {
+ new TestSlice();
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/source_info/js_source_info.html b/chromium/third_party/catapult/tracing/tracing/model/source_info/js_source_info.html
new file mode 100644
index 00000000000..37b975b0b6e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/source_info/js_source_info.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/source_info/source_info.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.source_info', function() {
+ function JSSourceInfo(file, line, column, isNative, scriptId, state) {
+ tr.model.source_info.SourceInfo.call(this, file, line, column);
+
+ this.isNative_ = isNative;
+ this.scriptId_ = scriptId;
+ this.state_ = state;
+ }
+
+ JSSourceInfo.prototype = {
+ __proto__: tr.model.source_info.SourceInfo.prototype,
+
+ get state() {
+ return this.state_;
+ },
+
+ get isNative() {
+ return this.isNative_;
+ },
+
+ get scriptId() {
+ return this.scriptId_;
+ },
+
+ toString() {
+ const str = this.isNative_ ? '[native v8] ' : '';
+ return str +
+ tr.model.source_info.SourceInfo.prototype.toString.call(this);
+ }
+ };
+
+ const JSSourceState = {
+ COMPILED: 'compiled',
+ OPTIMIZABLE: 'optimizable',
+ OPTIMIZED: 'optimized',
+ UNKNOWN: 'unknown',
+ };
+
+ return {
+ JSSourceInfo,
+ JSSourceState,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/source_info/source_info.html b/chromium/third_party/catapult/tracing/tracing/model/source_info/source_info.html
new file mode 100644
index 00000000000..a8cf526d6c5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/source_info/source_info.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.source_info', function() {
+ function SourceInfo(file, opt_line, opt_column) {
+ this.file_ = file;
+ this.line_ = opt_line || -1;
+ this.column_ = opt_column || -1;
+ }
+
+ SourceInfo.prototype = {
+ get file() {
+ return this.file_;
+ },
+
+ get line() {
+ return this.line_;
+ },
+
+ get column() {
+ return this.column_;
+ },
+
+ get domain() {
+ if (!this.file_) return undefined;
+ const domain = this.file_.match(/(.*:\/\/[^:\/]*)/i);
+ return domain ? domain[1] : undefined;
+ },
+
+ toString() {
+ let str = '';
+
+ if (this.file_) {
+ str += this.file_;
+ }
+ if (this.line_ > 0) {
+ str += ':' + this.line_;
+ }
+ if (this.column_ > 0) {
+ str += ':' + this.column_;
+ }
+ return str;
+ }
+ };
+
+ return {
+ SourceInfo,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/source_info/source_info_test.html b/chromium/third_party/catapult/tracing/tracing/model/source_info/source_info_test.html
new file mode 100644
index 00000000000..269de596d10
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/source_info/source_info_test.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/source_info/source_info.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('domain', function() {
+ const urlDomains = {
+ 'http://www.google.com': 'http://www.google.com',
+ 'http://www.google.com/bla': 'http://www.google.com',
+ 'http://www.google.com:1234': 'http://www.google.com',
+ 'bad url': undefined
+ };
+ for (const url in urlDomains) {
+ const sourceInfo = new tr.model.source_info.SourceInfo(url);
+ assert.strictEqual(urlDomains[url], sourceInfo.domain);
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/stack_frame.html b/chromium/third_party/catapult/tracing/tracing/model/stack_frame.html
new file mode 100644
index 00000000000..b417d20f94c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/stack_frame.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ function StackFrame(parentFrame, id, title, colorId, opt_sourceInfo) {
+ if (id === undefined) {
+ throw new Error('id must be given');
+ }
+ this.parentFrame_ = parentFrame;
+ this.id = id;
+ this.title_ = title;
+ this.colorId = colorId;
+ this.children = [];
+ this.sourceInfo_ = opt_sourceInfo;
+
+ if (this.parentFrame_) {
+ this.parentFrame_.addChild(this);
+ }
+ }
+
+ StackFrame.prototype = {
+ get parentFrame() {
+ return this.parentFrame_;
+ },
+
+ get title() {
+ if (this.sourceInfo_) {
+ const src = this.sourceInfo_.toString();
+ return this.title_ + (src === '' ? '' : ' ' + src);
+ }
+ return this.title_;
+ },
+
+ /**
+ * Attempts to find the domain of the origin of the script either from this
+ * stack trace or from its ancestors.
+ */
+ get domain() {
+ let result = 'unknown';
+ if (this.sourceInfo_ && this.sourceInfo_.domain) {
+ result = this.sourceInfo_.domain;
+ }
+ if (result === 'unknown' && this.parentFrame) {
+ result = this.parentFrame.domain;
+ }
+ return result;
+ },
+
+ get sourceInfo() {
+ return this.sourceInfo_;
+ },
+
+ set parentFrame(parentFrame) {
+ if (this.parentFrame_) {
+ Polymer.dom(this.parentFrame_).removeChild(this);
+ }
+ this.parentFrame_ = parentFrame;
+ if (this.parentFrame_) {
+ this.parentFrame_.addChild(this);
+ }
+ },
+
+ addChild(child) {
+ this.children.push(child);
+ },
+
+ removeChild(child) {
+ const i = this.children.indexOf(child.id);
+ if (i === -1) {
+ throw new Error('omg');
+ }
+ this.children.splice(i, 1);
+ },
+
+ removeAllChildren() {
+ for (let i = 0; i < this.children.length; i++) {
+ this.children[i].parentFrame_ = undefined;
+ }
+ this.children.splice(0, this.children.length);
+ },
+
+ /**
+ * Returns stackFrames where the most specific frame is first.
+ */
+ get stackTrace() {
+ const stack = [this];
+ let cur = this.parentFrame;
+ while (cur) {
+ stack.push(cur);
+ cur = cur.parentFrame;
+ }
+ return stack;
+ },
+
+ getUserFriendlyStackTrace() {
+ return this.stackTrace.map(function(x) { return x.title; });
+ }
+ };
+
+ return {
+ StackFrame,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/stack_frame_test.html b/chromium/third_party/catapult/tracing/tracing/model/stack_frame_test.html
new file mode 100644
index 00000000000..d0b971ecb78
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/stack_frame_test.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/source_info/source_info.html">
+<link rel="import" href="/tracing/model/stack_frame.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('domain', function() {
+ const stackFrame1 = new tr.model.StackFrame(undefined, 1, '1', 1);
+ assert.strictEqual('unknown', stackFrame1.domain);
+
+ const sourceInfo = new tr.model.source_info.SourceInfo(
+ 'http://www.google.com:1234');
+ const stackFrame2 = new tr.model.StackFrame(
+ stackFrame1, 2, '2', 2, sourceInfo);
+ assert.strictEqual('http://www.google.com', stackFrame2.domain);
+
+ const stackFrame3 = new tr.model.StackFrame(stackFrame2, 3, '3', 3);
+ assert.strictEqual('http://www.google.com', stackFrame3.domain);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/thread.html b/chromium/third_party/catapult/tracing/tracing/model/thread.html
new file mode 100644
index 00000000000..54826bd29db
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/thread.html
@@ -0,0 +1,358 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/async_slice_group.html">
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Thread class.
+ */
+tr.exportTo('tr.model', function() {
+ const AsyncSlice = tr.model.AsyncSlice;
+ const AsyncSliceGroup = tr.model.AsyncSliceGroup;
+ const SliceGroup = tr.model.SliceGroup;
+ const ThreadSlice = tr.model.ThreadSlice;
+ const ThreadTimeSlice = tr.model.ThreadTimeSlice;
+
+ /**
+ * A Thread stores all the trace events collected for a particular
+ * thread. We organize the synchronous slices on a thread by "subrows," where
+ * subrow 0 has all the root slices, subrow 1 those nested 1 deep, and so on.
+ * The asynchronous slices are stored in an AsyncSliceGroup object.
+ *
+ * The slices stored on a Thread should be instances of
+ * ThreadSlice.
+ *
+ * @constructor
+ * @extends {tr.model.EventContainer}
+ */
+ function Thread(parent, tid) {
+ if (!parent) {
+ throw new Error('Parent must be provided.');
+ }
+
+ tr.model.EventContainer.call(this);
+ this.parent = parent;
+ this.sortIndex = 0;
+ this.tid = tid;
+ this.name = undefined;
+ this.samples_ = undefined; // Set during createSubSlices
+
+ this.sliceGroup = new SliceGroup(this, ThreadSlice, 'slices');
+ this.timeSlices = undefined;
+ this.kernelSliceGroup = new SliceGroup(
+ this, ThreadSlice, 'kernel-slices');
+ this.asyncSliceGroup = new AsyncSliceGroup(this, 'async-slices');
+ }
+
+ Thread.prototype = {
+ __proto__: tr.model.EventContainer.prototype,
+
+ get model() {
+ return this.parent.model;
+ },
+
+ get stableId() {
+ return this.parent.stableId + '.' + this.tid;
+ },
+
+ compareTo(that) {
+ return Thread.compare(this, that);
+ },
+
+ * childEventContainers() {
+ if (this.sliceGroup.length) {
+ yield this.sliceGroup;
+ }
+ if (this.kernelSliceGroup.length) {
+ yield this.kernelSliceGroup;
+ }
+ if (this.asyncSliceGroup.length) {
+ yield this.asyncSliceGroup;
+ }
+ },
+
+ * childEvents() {
+ if (this.timeSlices) {
+ yield* this.timeSlices;
+ }
+ },
+
+ iterateAllPersistableObjects(cb) {
+ cb(this);
+ if (this.sliceGroup.length) {
+ cb(this.sliceGroup);
+ }
+ this.asyncSliceGroup.viewSubGroups.forEach(cb);
+ },
+
+ /**
+ * Shifts all the timestamps inside this thread forward by the amount
+ * specified.
+ */
+ shiftTimestampsForward(amount) {
+ this.sliceGroup.shiftTimestampsForward(amount);
+
+ if (this.timeSlices) {
+ for (let i = 0; i < this.timeSlices.length; i++) {
+ const slice = this.timeSlices[i];
+ slice.start += amount;
+ }
+ }
+
+ this.kernelSliceGroup.shiftTimestampsForward(amount);
+ this.asyncSliceGroup.shiftTimestampsForward(amount);
+ },
+
+ /**
+ * Determines whether this thread is empty. If true, it usually implies
+ * that it should be pruned from the model.
+ */
+ get isEmpty() {
+ if (this.sliceGroup.length) return false;
+ if (this.sliceGroup.openSliceCount) return false;
+ if (this.timeSlices && this.timeSlices.length) return false;
+ if (this.kernelSliceGroup.length) return false;
+ if (this.asyncSliceGroup.length) return false;
+ if (this.samples_.length) return false;
+ return true;
+ },
+
+ /**
+ * Updates the bounds based on the
+ * current objects associated with the thread.
+ */
+ updateBounds() {
+ this.bounds.reset();
+
+ this.sliceGroup.updateBounds();
+ this.bounds.addRange(this.sliceGroup.bounds);
+
+ this.kernelSliceGroup.updateBounds();
+ this.bounds.addRange(this.kernelSliceGroup.bounds);
+
+ this.asyncSliceGroup.updateBounds();
+ this.bounds.addRange(this.asyncSliceGroup.bounds);
+
+ if (this.timeSlices && this.timeSlices.length) {
+ this.bounds.addValue(this.timeSlices[0].start);
+ this.bounds.addValue(
+ this.timeSlices[this.timeSlices.length - 1].end);
+ }
+
+ if (this.samples_ && this.samples_.length) {
+ this.bounds.addValue(this.samples_[0].start);
+ this.bounds.addValue(
+ this.samples_[this.samples_.length - 1].end);
+ }
+ },
+
+ addCategoriesToDict(categoriesDict) {
+ for (let i = 0; i < this.sliceGroup.length; i++) {
+ categoriesDict[this.sliceGroup.slices[i].category] = true;
+ }
+ for (let i = 0; i < this.kernelSliceGroup.length; i++) {
+ categoriesDict[this.kernelSliceGroup.slices[i].category] = true;
+ }
+ for (let i = 0; i < this.asyncSliceGroup.length; i++) {
+ categoriesDict[this.asyncSliceGroup.slices[i].category] = true;
+ }
+ if (this.samples_) {
+ for (let i = 0; i < this.samples_.length; i++) {
+ categoriesDict[this.samples_[i].category] = true;
+ }
+ }
+ },
+
+ autoCloseOpenSlices() {
+ this.sliceGroup.autoCloseOpenSlices();
+ this.asyncSliceGroup.autoCloseOpenSlices();
+ this.kernelSliceGroup.autoCloseOpenSlices();
+ },
+
+ mergeKernelWithUserland() {
+ if (this.kernelSliceGroup.length > 0) {
+ const newSlices = SliceGroup.merge(
+ this.sliceGroup, this.kernelSliceGroup);
+ this.sliceGroup.slices = newSlices.slices;
+ this.kernelSliceGroup = new SliceGroup(this);
+ this.updateBounds();
+ }
+ },
+
+ createSubSlices() {
+ this.sliceGroup.createSubSlices();
+ this.samples_ = this.parent.model.samples.filter(sample =>
+ sample.thread === this);
+ },
+
+ /**
+ * @return {String} A user-friendly name for this thread.
+ */
+ get userFriendlyName() {
+ return this.name || this.tid;
+ },
+
+ /**
+ * @return {String} User friendly details about this thread.
+ */
+ get userFriendlyDetails() {
+ return 'tid: ' + this.tid +
+ (this.name ? ', name: ' + this.name : '');
+ },
+
+ getSettingsKey() {
+ if (!this.name) return undefined;
+ const parentKey = this.parent.getSettingsKey();
+ if (!parentKey) return undefined;
+ return parentKey + '.' + this.name;
+ },
+
+ getProcess() {
+ return this.parent;
+ },
+
+ /*
+ * Returns the index of the slice in the timeSlices array, or undefined.
+ */
+ indexOfTimeSlice(timeSlice) {
+ const i = tr.b.findLowIndexInSortedArray(
+ this.timeSlices,
+ function(slice) { return slice.start; },
+ timeSlice.start);
+ if (this.timeSlices[i] !== timeSlice) return undefined;
+ return i;
+ },
+
+ sumOverToplevelSlicesInRange(range, func) {
+ let sum = 0;
+ tr.b.iterateOverIntersectingIntervals(
+ this.sliceGroup.topLevelSlices,
+ slice => slice.start, slice => slice.end,
+ range.min, range.max,
+ slice => {
+ let fractionOfSliceInsideRangeOfInterest = 1;
+ if (slice.duration > 0) {
+ const intersection = range.findIntersection(slice.range);
+ fractionOfSliceInsideRangeOfInterest =
+ intersection.duration / slice.duration;
+ }
+ // We assume that if a slice doesn't lie entirely inside the range
+ // of interest, then |func| is evenly distributed inside of the
+ // slice.
+ sum += func(slice) * fractionOfSliceInsideRangeOfInterest;
+ });
+ return sum;
+ },
+
+ /**
+ * Returns the total cpu time consumed within |range| by this thread.
+ */
+ getCpuTimeForRange(range) {
+ return this.sumOverToplevelSlicesInRange(
+ range, slice => slice.cpuDuration || 0);
+ },
+
+ /**
+ * Returns the total number of top-level slices within |range| in this
+ * thread. If a slice overlaps with |range| and is not completely inside it,
+ * then we attribute the portion that is inside the range only. For example,
+ * |getNumToplevelSlicesForRange| will return 1 + 1/3 when we have:
+ *
+ * 01 02 03 04 05 06 07 08 09 10
+ * <---------- range ---------->
+ * <- slice #1 -> <- slice #2 ->
+ */
+ getNumToplevelSlicesForRange(range) {
+ return this.sumOverToplevelSlicesInRange(range, slice => 1);
+ },
+
+ getSchedulingStatsForRange(start, end) {
+ const stats = {};
+
+ if (!this.timeSlices) return stats;
+
+ function addStatsForSlice(threadTimeSlice) {
+ const overlapStart = Math.max(threadTimeSlice.start, start);
+ const overlapEnd = Math.min(threadTimeSlice.end, end);
+ const schedulingState = threadTimeSlice.schedulingState;
+
+ if (!(schedulingState in stats)) stats[schedulingState] = 0;
+ stats[schedulingState] += overlapEnd - overlapStart;
+ }
+
+ tr.b.iterateOverIntersectingIntervals(this.timeSlices,
+ function(x) { return x.start; },
+ function(x) { return x.end; },
+ start,
+ end,
+ addStatsForSlice);
+ return stats;
+ },
+
+ get samples() {
+ return this.samples_;
+ },
+
+ /**
+ * Returns substring of this.name from beginning to the first numeric
+ * character or the character '/'.
+ *
+ * Example:
+ * ThreadName12 -> ThreadName
+ * ThreadName/34123 -> ThreadName
+ * ThreadName1/34123 -> ThreadName
+ */
+ get type() {
+ const re = /^[^0-9|\/]+/;
+ const matches = re.exec(this.name);
+ if (matches && matches[0]) return matches[0];
+
+ // If a thread is named 42GPU, let's not try to find its type.
+ // We should fix the thread name.
+ throw new Error('Could not determine thread type for thread name ' +
+ this.name);
+ }
+ };
+
+ /**
+ * Comparison between threads that orders first by parent.compareTo,
+ * then by names, then by tid.
+ */
+ Thread.compare = function(x, y) {
+ let tmp = x.parent.compareTo(y.parent);
+ if (tmp) return tmp;
+
+ tmp = x.sortIndex - y.sortIndex;
+ if (tmp) return tmp;
+
+ if (x.name !== undefined) {
+ if (y.name !== undefined) {
+ tmp = x.name.localeCompare(y.name);
+ } else {
+ tmp = -1;
+ }
+ } else if (y.name !== undefined) {
+ tmp = 1;
+ }
+ if (tmp) return tmp;
+
+ return x.tid - y.tid;
+ };
+
+ return {
+ Thread,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/thread_slice.html b/chromium/third_party/catapult/tracing/tracing/model/thread_slice.html
new file mode 100644
index 00000000000..f67d20d3e5d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/thread_slice.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/slice.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the Thread class.
+ */
+tr.exportTo('tr.model', function() {
+ const Slice = tr.model.Slice;
+
+ /**
+ * A ThreadSlice represents an interval of time on a thread resource
+ * with associated nesting slice information.
+ *
+ * ThreadSlices are typically associated with a specific trace event pair on a
+ * specific thread.
+ * For example,
+ * TRACE_EVENT_BEGIN1("x","myArg", 7) at time=0.1ms
+ * TRACE_EVENT_END0() at time=0.3ms
+ * This results in a single slice from 0.1 with duration 0.2 on a
+ * specific thread.
+ *
+ * @constructor
+ */
+ function ThreadSlice(cat, title, colorId, start, args, opt_duration,
+ opt_cpuStart, opt_cpuDuration, opt_argsStripped,
+ opt_bindId) {
+ Slice.call(this, cat, title, colorId, start, args, opt_duration,
+ opt_cpuStart, opt_cpuDuration, opt_argsStripped, opt_bindId);
+ // Do not modify this directly.
+ // subSlices is configured by SliceGroup.rebuildSubRows_.
+ this.subSlices = [];
+ }
+
+ ThreadSlice.prototype = {
+ __proto__: Slice.prototype,
+
+ get overlappingSamples() {
+ const samples = new tr.model.EventSet();
+ if (!this.parentContainer || !this.parentContainer.samples) {
+ return samples;
+ }
+ this.parentContainer.samples.forEach(function(sample) {
+ if (this.start <= sample.start && sample.start <= this.end) {
+ samples.push(sample);
+ }
+ }, this);
+ return samples;
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ ThreadSlice,
+ {
+ name: 'slice',
+ pluralName: 'slices'
+ });
+
+ return {
+ ThreadSlice,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/thread_slice_test.html b/chromium/third_party/catapult/tracing/tracing/model/thread_slice_test.html
new file mode 100644
index 00000000000..b69efb79ac4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/thread_slice_test.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ThreadSlice = tr.model.ThreadSlice;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newFakeThread = tr.c.TestUtils.newFakeThread;
+
+ test('getOverlappingSamples', function() {
+ const model = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+ const node = tr.c.TestUtils.newProfileNodes(m, ['fake']);
+ m.samples.push(
+ new tr.model.Sample(1, 'a_1', node, m.t2),
+ new tr.model.Sample(2, 'a_2', node, m.t2),
+ new tr.model.Sample(3, 'a_3', node, m.t2),
+ new tr.model.Sample(5, 'b', node, m.t2)
+ );
+ });
+ const threadSlice = newSliceEx({title: 'a', start: 0, end: 4,
+ type: tr.model.ThreadSlice});
+ threadSlice.parentContainer = model;
+ const samplesIter = threadSlice.overlappingSamples[Symbol.iterator]();
+ assert.strictEqual(samplesIter.next().value.title, 'a_1');
+ assert.strictEqual(samplesIter.next().value.title, 'a_2');
+ assert.strictEqual(samplesIter.next().value.title, 'a_3');
+ assert.strictEqual(samplesIter.next().done, true);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/thread_test.html b/chromium/third_party/catapult/tracing/tracing/model/thread_test.html
new file mode 100644
index 00000000000..4d2bccf0790
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/thread_test.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ThreadSlice = tr.model.ThreadSlice;
+ const Process = tr.model.Process;
+ const Thread = tr.model.Thread;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newAsyncSlice = tr.c.TestUtils.newAsyncSlice;
+ const newThreadSlice = tr.c.TestUtils.newThreadSlice;
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+
+ test('threadBounds_Empty', function() {
+ const model = new tr.Model();
+ const t = new Thread(new Process(model, 7), 1);
+ t.updateBounds();
+ assert.isUndefined(t.bounds.min);
+ assert.isUndefined(t.bounds.max);
+ });
+
+ test('threadBounds_SubRow', function() {
+ const model = new tr.Model();
+ const t = new Thread(new Process(model, 7), 1);
+ t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
+ t.updateBounds();
+ assert.strictEqual(t.bounds.min, 1);
+ assert.strictEqual(t.bounds.max, 4);
+ });
+
+ test('threadBounds_AsyncSliceGroup', function() {
+ const model = new tr.Model();
+ const t = new Thread(new Process(model, 7), 1);
+ t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 3));
+ t.asyncSliceGroup.push(newAsyncSlice(0.1, 5, t, t));
+ t.updateBounds();
+ assert.strictEqual(t.bounds.min, 0.1);
+ assert.strictEqual(t.bounds.max, 5.1);
+ });
+
+ test('threadBounds_Cpu', function() {
+ const model = new tr.Model();
+ const t = new Thread(new Process(model, 7), 1);
+ t.timeSlices = [newSliceEx({title: 'x', start: 0, duration: 1})];
+ t.updateBounds();
+ assert.strictEqual(t.bounds.min, 0);
+ assert.strictEqual(t.bounds.max, 1);
+ });
+
+ test('shiftTimestampsForwardWithCpu', function() {
+ const model = new tr.Model();
+ const t = new Thread(new Process(model, 7), 1);
+ t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 0, {}, 3));
+ t.asyncSliceGroup.push(newAsyncSlice(0, 5, t, t));
+ t.timeSlices = [newSliceEx({title: 'x', start: 0, duration: 1})];
+
+ let shiftCount = 0;
+ t.asyncSliceGroup.shiftTimestampsForward = function(ts) {
+ if (ts === 0.32) {
+ shiftCount++;
+ }
+ };
+
+ t.shiftTimestampsForward(0.32);
+
+ assert.strictEqual(shiftCount, 1);
+ assert.strictEqual(t.sliceGroup.slices[0].start, 0.32);
+ assert.strictEqual(t.timeSlices[0].start, 0.32);
+ });
+
+ test('shiftTimestampsForwardWithoutCpu', function() {
+ const model = new tr.Model();
+ const t = new Thread(new Process(model, 7), 1);
+ t.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 0, {}, 3));
+ t.asyncSliceGroup.push(newAsyncSlice(0, 5, t, t));
+
+ let shiftCount = 0;
+ t.asyncSliceGroup.shiftTimestampsForward = function(ts) {
+ if (ts === 0.32) {
+ shiftCount++;
+ }
+ };
+
+ t.shiftTimestampsForward(0.32);
+
+ assert.strictEqual(shiftCount, 1);
+ assert.strictEqual(t.sliceGroup.slices[0].start, 0.32);
+ });
+
+ test('getSchedulingStatsForRange', function() {
+ let scheduledThread = undefined;
+ let unscheduledThread = undefined;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ unscheduledThread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ unscheduledThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'work', start: 0, duration: 20}));
+
+ scheduledThread = model.getOrCreateProcess(2).getOrCreateThread(2);
+ scheduledThread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'work', start: 0, duration: 20}));
+ scheduledThread.timeSlices = [
+ newThreadSlice(scheduledThread, SCHEDULING_STATE.RUNNING, 0, 3),
+ newThreadSlice(scheduledThread, SCHEDULING_STATE.RUNNABLE, 3, 5),
+ newThreadSlice(scheduledThread, SCHEDULING_STATE.RUNNING, 8, 2),
+ newThreadSlice(scheduledThread, SCHEDULING_STATE.SLEEPING, 10, 10)
+ ];
+ });
+
+ // thread without scheduling states
+ let stats = unscheduledThread.getSchedulingStatsForRange(0, 20);
+ assert.deepEqual(stats, {});
+
+ // no scheduling info
+ stats = scheduledThread.getSchedulingStatsForRange(50, 100);
+ assert.deepEqual(stats, {});
+
+ // simple query
+ stats = scheduledThread.getSchedulingStatsForRange(0, 3);
+ let expected = {};
+ expected[SCHEDULING_STATE.RUNNING] = 3;
+ assert.deepEqual(stats, expected);
+
+ // aggregation
+ stats = scheduledThread.getSchedulingStatsForRange(0, 20);
+ expected = {};
+ expected[SCHEDULING_STATE.RUNNING] = 5;
+ expected[SCHEDULING_STATE.RUNNABLE] = 5;
+ expected[SCHEDULING_STATE.SLEEPING] = 10;
+ assert.deepEqual(stats, expected);
+ });
+
+ test('getCpuTimeForRange', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ const sliceSpecs = [
+ {wallTimeBounds: [100, 200], cpuStart: 120, cpuDuration: 50},
+ {wallTimeBounds: [300, 600], cpuStart: 350, cpuDuration: 150}
+ ];
+ for (const sliceSpec of sliceSpecs) {
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ isTopLevel: true,
+ start: sliceSpec.wallTimeBounds[0],
+ duration: sliceSpec.wallTimeBounds[1] - sliceSpec.wallTimeBounds[0],
+ cpuStart: sliceSpec.cpuStart,
+ cpuDuration: sliceSpec.cpuDuration,
+ }));
+ }
+ });
+
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(1);
+ const bounds = new tr.b.math.Range.fromExplicitRange(150, 400);
+ // 1/2 of first slice + 1/3 of second slice
+ const expectedCpuTime = 25 + 50;
+
+ // Should be essentially equal, but choosing a very small epsilon 1e-7
+ // to allow for floating point errors.
+ assert.closeTo(thread.getCpuTimeForRange(bounds), expectedCpuTime, 1e-7);
+ });
+
+ test('typeGetterReturnsCorrectType', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ const thread1 = process.getOrCreateThread(1);
+ const thread2 = process.getOrCreateThread(2);
+ const thread3 = process.getOrCreateThread(3);
+ const thread4 = process.getOrCreateThread(4);
+
+ thread1.name = 'ThreadName12';
+ thread2.name = 'ThreadName/34123';
+ thread3.name = 'ThreadName1/34123';
+ thread4.name = 'ThreadName';
+
+ assert.strictEqual(thread1.type, 'ThreadName');
+ assert.strictEqual(thread2.type, 'ThreadName');
+ assert.strictEqual(thread3.type, 'ThreadName');
+ assert.strictEqual(thread4.type, 'ThreadName');
+ });
+ });
+
+ test('typeGetterThrowsIfThreadNameStartsWithNumberOrSlash', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ const thread1 = process.getOrCreateThread(1);
+ const thread2 = process.getOrCreateThread(2);
+ const thread3 = process.getOrCreateThread(3);
+
+ thread1.name = '123';
+ thread2.name = '42GPU';
+ thread3.name = '/123';
+
+ assert.throws(() => thread1.type);
+ assert.throws(() => thread2.type);
+ assert.throws(() => thread3.type);
+ });
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/thread_time_slice.html b/chromium/third_party/catapult/tracing/tracing/model/thread_time_slice.html
new file mode 100644
index 00000000000..69437c76819
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/thread_time_slice.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/slice.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ const Slice = tr.model.Slice;
+
+
+ const SCHEDULING_STATE = {
+ DEBUG: 'Debug',
+ EXIT_DEAD: 'Exit Dead',
+ RUNNABLE: 'Runnable',
+ RUNNING: 'Running',
+ SLEEPING: 'Sleeping',
+ STOPPED: 'Stopped',
+ TASK_DEAD: 'Task Dead',
+ UNINTR_SLEEP: 'Uninterruptible Sleep',
+ UNINTR_SLEEP_WAKE_KILL: 'Uninterruptible Sleep | WakeKill',
+ UNINTR_SLEEP_WAKING: 'Uninterruptible Sleep | Waking',
+ UNINTR_SLEEP_IO: 'Uninterruptible Sleep - Block I/O',
+ UNINTR_SLEEP_WAKE_KILL_IO: 'Uninterruptible Sleep | WakeKill - Block I/O',
+ UNINTR_SLEEP_WAKING_IO: 'Uninterruptible Sleep | Waking - Block I/O',
+ UNKNOWN: 'UNKNOWN',
+ WAKE_KILL: 'Wakekill',
+ WAKING: 'Waking',
+ ZOMBIE: 'Zombie'
+ };
+
+ /**
+ * A ThreadTimeSlice is a slice of time on a specific thread where that thread
+ * was running on a specific CPU, or in a specific sleep state.
+ *
+ * As a thread switches moves through its life, it sometimes goes to sleep and
+ * can't run. Other times, its runnable but isn't actually assigned to a CPU.
+ * Finally, sometimes it gets put on a CPU to actually execute. Each of these
+ * states is represented by a ThreadTimeSlice:
+ *
+ * Sleeping or runnable: cpuOnWhichThreadWasRunning is undefined
+ * Running: cpuOnWhichThreadWasRunning is set.
+ *
+ * @constructor
+ */
+ function ThreadTimeSlice(thread, schedulingState, cat,
+ start, args, opt_duration) {
+ Slice.call(this, cat, schedulingState,
+ this.getColorForState_(schedulingState),
+ start, args, opt_duration);
+ this.thread = thread;
+ this.schedulingState = schedulingState;
+ this.cpuOnWhichThreadWasRunning = undefined;
+ }
+
+ ThreadTimeSlice.prototype = {
+ __proto__: Slice.prototype,
+
+ getColorForState_(state) {
+ const getColorIdForReservedName =
+ tr.b.ColorScheme.getColorIdForReservedName;
+
+ switch (state) {
+ case SCHEDULING_STATE.RUNNABLE:
+ return getColorIdForReservedName('thread_state_runnable');
+ case SCHEDULING_STATE.RUNNING:
+ return getColorIdForReservedName('thread_state_running');
+ case SCHEDULING_STATE.SLEEPING:
+ return getColorIdForReservedName('thread_state_sleeping');
+ case SCHEDULING_STATE.DEBUG:
+ case SCHEDULING_STATE.EXIT_DEAD:
+ case SCHEDULING_STATE.STOPPED:
+ case SCHEDULING_STATE.TASK_DEAD:
+ case SCHEDULING_STATE.UNINTR_SLEEP:
+ case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL:
+ case SCHEDULING_STATE.UNINTR_SLEEP_WAKING:
+ case SCHEDULING_STATE.UNKNOWN:
+ case SCHEDULING_STATE.WAKE_KILL:
+ case SCHEDULING_STATE.WAKING:
+ case SCHEDULING_STATE.ZOMBIE:
+ return getColorIdForReservedName('thread_state_uninterruptible');
+ case SCHEDULING_STATE.UNINTR_SLEEP_IO:
+ case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO:
+ case SCHEDULING_STATE.UNINTR_SLEEP_WAKING_IO:
+ return getColorIdForReservedName('thread_state_iowait');
+ default:
+ return getColorIdForReservedName('thread_state_unknown');
+ }
+ },
+
+ get analysisTypeName() {
+ return 'tr.ui.analysis.ThreadTimeSlice';
+ },
+
+ getAssociatedCpuSlice() {
+ if (!this.cpuOnWhichThreadWasRunning) return undefined;
+ const cpuSlices = this.cpuOnWhichThreadWasRunning.slices;
+ for (let i = 0; i < cpuSlices.length; i++) {
+ const cpuSlice = cpuSlices[i];
+ if (cpuSlice.start !== this.start) continue;
+ if (cpuSlice.duration !== this.duration) continue;
+ return cpuSlice;
+ }
+ return undefined;
+ },
+
+ getCpuSliceThatTookCpu() {
+ if (this.cpuOnWhichThreadWasRunning) return undefined;
+ let curIndex = this.thread.indexOfTimeSlice(this);
+ let cpuSliceWhenLastRunning;
+ while (curIndex >= 0) {
+ const curSlice = this.thread.timeSlices[curIndex];
+ if (!curSlice.cpuOnWhichThreadWasRunning) {
+ curIndex--;
+ continue;
+ }
+ cpuSliceWhenLastRunning = curSlice.getAssociatedCpuSlice();
+ break;
+ }
+ if (!cpuSliceWhenLastRunning) return undefined;
+
+ const cpu = cpuSliceWhenLastRunning.cpu;
+ const indexOfSliceOnCpuWhenLastRunning =
+ cpu.indexOf(cpuSliceWhenLastRunning);
+ const nextRunningSlice = cpu.slices[indexOfSliceOnCpuWhenLastRunning + 1];
+ if (!nextRunningSlice) return undefined;
+ if (Math.abs(nextRunningSlice.start - cpuSliceWhenLastRunning.end) <
+ 0.00001) {
+ return nextRunningSlice;
+ }
+ return undefined;
+ }
+ };
+
+ tr.model.EventRegistry.register(
+ ThreadTimeSlice,
+ {
+ name: 'threadTimeSlice',
+ pluralName: 'threadTimeSlices'
+ });
+
+
+ return {
+ ThreadTimeSlice,
+ SCHEDULING_STATE,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/time_to_object_instance_map.html b/chromium/third_party/catapult/tracing/tracing/model/time_to_object_instance_map.html
new file mode 100644
index 00000000000..3c05b08d4a2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/time_to_object_instance_map.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the TimeToObjectInstanceMap class.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * Tracks all the instances associated with a given ID over its lifetime.
+ *
+ * A scoped id can be used multiple times throughout a trace, referring to
+ * different objects at different times. This data structure does the
+ * bookkeeping to figure out what ObjectInstance is referred to at a given
+ * timestamp.
+ *
+ * @constructor
+ */
+ function TimeToObjectInstanceMap(
+ createObjectInstanceFunction, parent, scopedId) {
+ this.createObjectInstanceFunction_ = createObjectInstanceFunction;
+ this.parent = parent;
+ this.scopedId = scopedId;
+ this.instances = [];
+ }
+
+ TimeToObjectInstanceMap.prototype = {
+ idWasCreated(category, name, ts) {
+ if (this.instances.length === 0) {
+ this.instances.push(this.createObjectInstanceFunction_(
+ this.parent, this.scopedId, category, name, ts));
+ this.instances[0].creationTsWasExplicit = true;
+ return this.instances[0];
+ }
+
+ let lastInstance = this.instances[this.instances.length - 1];
+ if (ts < lastInstance.deletionTs) {
+ throw new Error('Mutation of the TimeToObjectInstanceMap must be ' +
+ 'done in ascending timestamp order.');
+ }
+ lastInstance = this.createObjectInstanceFunction_(
+ this.parent, this.scopedId, category, name, ts);
+ lastInstance.creationTsWasExplicit = true;
+ this.instances.push(lastInstance);
+ return lastInstance;
+ },
+
+ addSnapshot(category, name, ts, args, opt_baseTypeName) {
+ if (this.instances.length === 0) {
+ this.instances.push(this.createObjectInstanceFunction_(
+ this.parent, this.scopedId, category, name, ts, opt_baseTypeName));
+ }
+
+ const i = tr.b.findIndexInSortedIntervals(
+ this.instances,
+ function(inst) { return inst.creationTs; },
+ function(inst) { return inst.deletionTs - inst.creationTs; },
+ ts);
+
+ let instance;
+ if (i < 0) {
+ instance = this.instances[0];
+ if (ts > instance.deletionTs ||
+ instance.creationTsWasExplicit) {
+ throw new Error(
+ 'At the provided timestamp, no instance was still alive');
+ }
+
+ if (instance.snapshots.length !== 0) {
+ throw new Error(
+ 'Cannot shift creationTs forward, ' +
+ 'snapshots have been added. First snap was at ts=' +
+ instance.snapshots[0].ts + ' and creationTs was ' +
+ instance.creationTs);
+ }
+ instance.creationTs = ts;
+ } else if (i >= this.instances.length) {
+ instance = this.instances[this.instances.length - 1];
+ if (ts >= instance.deletionTs) {
+ // The snap is added after our oldest and deleted instance. This means
+ // that this is a new implicit instance.
+ instance = this.createObjectInstanceFunction_(
+ this.parent, this.scopedId, category, name, ts, opt_baseTypeName);
+ this.instances.push(instance);
+ } else {
+ // If the ts is before the last objects deletion time, then the caller
+ // is trying to add a snapshot when there may have been an instance
+ // alive. In that case, try to move an instance's creationTs to
+ // include this ts, provided that it has an implicit creationTs.
+
+ // Search backward from the right for an instance that was definitely
+ // deleted before this ts. Any time an instance is found that has a
+ // moveable creationTs
+ let lastValidIndex;
+ for (let i = this.instances.length - 1; i >= 0; i--) {
+ const tmp = this.instances[i];
+ if (ts >= tmp.deletionTs) break;
+ if (tmp.creationTsWasExplicit === false &&
+ tmp.snapshots.length === 0) {
+ lastValidIndex = i;
+ }
+ }
+ if (lastValidIndex === undefined) {
+ throw new Error(
+ 'Cannot add snapshot. No instance was alive that was mutable.');
+ }
+ instance = this.instances[lastValidIndex];
+ instance.creationTs = ts;
+ }
+ } else {
+ instance = this.instances[i];
+ }
+
+ return instance.addSnapshot(ts, args, name, opt_baseTypeName);
+ },
+
+ get lastInstance() {
+ if (this.instances.length === 0) return undefined;
+ return this.instances[this.instances.length - 1];
+ },
+
+ idWasDeleted(category, name, ts) {
+ if (this.instances.length === 0) {
+ this.instances.push(this.createObjectInstanceFunction_(
+ this.parent, this.scopedId, category, name, ts));
+ }
+ let lastInstance = this.instances[this.instances.length - 1];
+ if (ts < lastInstance.creationTs) {
+ throw new Error('Cannot delete an id before it was created');
+ }
+ if (lastInstance.deletionTs === Number.MAX_VALUE) {
+ lastInstance.wasDeleted(ts);
+ return lastInstance;
+ }
+
+ if (ts < lastInstance.deletionTs) {
+ throw new Error('id was already deleted earlier.');
+ }
+
+ // A new instance was deleted with no snapshots in-between.
+ // Create an instance then kill it.
+ lastInstance = this.createObjectInstanceFunction_(
+ this.parent, this.scopedId, category, name, ts);
+ this.instances.push(lastInstance);
+ lastInstance.wasDeleted(ts);
+ return lastInstance;
+ },
+
+ getInstanceAt(ts) {
+ const i = tr.b.findIndexInSortedIntervals(
+ this.instances,
+ function(inst) { return inst.creationTs; },
+ function(inst) { return inst.deletionTs - inst.creationTs; },
+ ts);
+ if (i < 0) {
+ if (this.instances[0].creationTsWasExplicit) {
+ return undefined;
+ }
+ return this.instances[0];
+ } else if (i >= this.instances.length) {
+ return undefined;
+ }
+ return this.instances[i];
+ }
+ };
+
+ return {
+ TimeToObjectInstanceMap,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/time_to_object_instance_map_test.html b/chromium/third_party/catapult/tracing/tracing/model/time_to_object_instance_map_test.html
new file mode 100644
index 00000000000..70cd9ad0d5f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/time_to_object_instance_map_test.html
@@ -0,0 +1,164 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+<link rel="import" href="/tracing/model/time_to_object_instance_map.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const createObjectInstance = function(
+ parent, id, category, name, creationTs) {
+ return new tr.model.ObjectInstance(
+ parent, id, category, name, creationTs);
+ };
+
+ test('timeToObjectInstanceMap', function() {
+ const m = new tr.model.TimeToObjectInstanceMap(
+ createObjectInstance, {}, 7);
+ m.addSnapshot('cat', 'name', 10, 'a1');
+ m.addSnapshot('cat', 'name', 20, 'a2');
+ m.idWasDeleted('cat', 'name', 30);
+ m.addSnapshot('cat', 'name', 40, 'b');
+
+ assert.strictEqual(m.instances.length, 2);
+
+ const i0 = m.getInstanceAt(0);
+ const i10 = m.getInstanceAt(10);
+ assert.strictEqual(i0, i10);
+
+ assert.isDefined(i10);
+ assert.strictEqual(i10.snapshots.length, 2);
+ assert.strictEqual(i10.snapshots[0].args, 'a1');
+ assert.strictEqual(i10.snapshots[1].args, 'a2');
+
+ assert.strictEqual(i10.deletionTs, 30);
+
+ const i15 = m.getInstanceAt(15);
+ assert.strictEqual(i15, i10);
+
+ const i20 = m.getInstanceAt(20);
+ assert.strictEqual(i20, i10);
+
+ const i30 = m.getInstanceAt(30);
+ assert.isUndefined(i30);
+
+ const i35 = m.getInstanceAt(35);
+ assert.isUndefined(i35);
+
+ const i40 = m.getInstanceAt(40);
+ assert.isDefined(i40);
+ assert.notEqual(i40, i10);
+ assert.strictEqual(i40.snapshots.length, 1);
+ assert.strictEqual(i40.creationTs, 40);
+ assert.strictEqual(i40.deletionTs, Number.MAX_VALUE);
+
+ const i41 = m.getInstanceAt(41);
+ assert.strictEqual(i40, i41);
+ });
+
+ test('timeToObjectInstanceMapsBoundsLogic', function() {
+ const m = new tr.model.TimeToObjectInstanceMap(
+ createObjectInstance, {}, 7);
+ m.addSnapshot('cat', 'name', 10, 'a1');
+ m.addSnapshot('cat', 'name', 20, 'a2');
+ m.idWasDeleted('cat', 'name', 30);
+ m.addSnapshot('cat', 'name', 40, 'b');
+ m.addSnapshot('cat', 'name', 41, 'b');
+
+ m.instances.forEach(function(i) { i.updateBounds(); });
+
+ const iA = m.getInstanceAt(10);
+ assert.strictEqual(iA.bounds.min, 10);
+ assert.strictEqual(iA.bounds.max, 30);
+
+ const iB = m.getInstanceAt(40);
+ assert.strictEqual(iB.bounds.min, 40);
+ assert.strictEqual(iB.bounds.max, 41);
+ });
+
+ test('earlySnapshot', function() {
+ const m = new tr.model.TimeToObjectInstanceMap(
+ createObjectInstance, {}, 7);
+ const i10 = m.idWasCreated('cat', 'name', 10, 'a1');
+ m.idWasDeleted('cat', 'name', 20);
+
+ assert.throws(function() {
+ m.addSnapshot('cat', 'name', 5, 'a1');
+ });
+ assert.strictEqual(i10.creationTs, 10);
+ assert.strictEqual(i10.deletionTs, 20);
+ });
+
+ test('earlySnapshotWithImplicitCreate', function() {
+ const m = new tr.model.TimeToObjectInstanceMap(
+ createObjectInstance, {}, 7);
+ const i10 = m.idWasDeleted('cat', 'name', 20);
+ m.addSnapshot('cat', 'name', 5, 'a1');
+ assert.strictEqual(i10.creationTs, 5);
+ assert.strictEqual(i10.deletionTs, 20);
+ });
+
+ test('getInstanceBeforeCreationImplicitCreate', function() {
+ const m = new tr.model.TimeToObjectInstanceMap(
+ createObjectInstance, {}, 7);
+ const i10 = m.idWasCreated('cat', 'name', 10, 'a1');
+ m.idWasDeleted('cat', 'name', 20);
+ assert.isUndefined(m.getInstanceAt(5));
+ });
+
+ test('getInstanceBeforeCreationImplicitCreateWithSnapshot', function() {
+ const m = new tr.model.TimeToObjectInstanceMap(
+ createObjectInstance, {}, 7);
+ const s5 = m.addSnapshot('cat', 'name', 5, 'a1');
+ const i10 = m.idWasDeleted('cat', 'name', 20);
+ assert.strictEqual(m.getInstanceAt(5), i10);
+ });
+
+ test('successiveDeletions', function() {
+ const m = new tr.model.TimeToObjectInstanceMap(
+ createObjectInstance, {}, 7);
+ const i20 = m.idWasDeleted('cat', 'name', 20);
+ const i30 = m.idWasDeleted('cat', 'name', 30);
+ const i40 = m.idWasDeleted('cat', 'name', 40);
+ assert.strictEqual(i20.creationTs, 20);
+ assert.isFalse(i20.creationTsWasExplicit);
+ assert.strictEqual(i20.deletionTs, 20);
+ assert.isTrue(i20.deletionTsWasExplicit);
+
+ assert.strictEqual(i30.creationTs, 30);
+ assert.isFalse(i30.creationTsWasExplicit);
+ assert.strictEqual(i30.deletionTs, 30);
+ assert.isTrue(i30.deletionTsWasExplicit);
+
+
+ assert.strictEqual(i40.creationTs, 40);
+ assert.isFalse(i40.creationTsWasExplicit);
+ assert.strictEqual(i40.deletionTs, 40);
+ assert.isTrue(i40.deletionTsWasExplicit);
+ });
+
+ test('snapshotAfterDeletion', function() {
+ const m = new tr.model.TimeToObjectInstanceMap(
+ createObjectInstance, {}, 7);
+ const i10 = m.idWasCreated('cat', 'name', 10, 'a1');
+ m.idWasDeleted('cat', 'name', 20);
+
+ const s25 = m.addSnapshot('cat', 'name', 25, 'a1');
+ const i25 = s25.objectInstance;
+
+ assert.strictEqual(i10.creationTs, 10);
+ assert.strictEqual(i10.deletionTs, 20);
+ assert.notEqual(i25, i10);
+ assert.strictEqual(i25.creationTs, 25);
+ assert.strictEqual(i25.deletionTs, Number.MAX_VALUE);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/model/timed_event.html b/chromium/third_party/catapult/tracing/tracing/model/timed_event.html
new file mode 100644
index 00000000000..4916162a4e1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/timed_event.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/time_display_modes.html">
+<link rel="import" href="/tracing/model/event.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ /**
+ * TimedEvent is a base type for any entity in the trace model with a specific
+ * start and duration.
+ *
+ * @constructor
+ */
+ function TimedEvent(start) {
+ tr.model.Event.call(this);
+ this.start = start;
+ this.duration = 0;
+ this.cpuStart = undefined;
+ this.cpuDuration = undefined;
+ // The set of contexts this event belongs to (order is unimportant). This
+ // array should never be modified.
+ this.contexts = Object.freeze([]);
+ }
+
+ TimedEvent.prototype = {
+ __proto__: tr.model.Event.prototype,
+
+ get end() {
+ return this.start + this.duration;
+ },
+
+ get boundsRange() {
+ return tr.b.math.Range.fromExplicitRange(this.start, this.end);
+ },
+
+ addBoundsToRange(range) {
+ range.addValue(this.start);
+ range.addValue(this.end);
+ },
+
+ // TODO(charliea): Can this be implemented in terms of Event.range()?
+ // Returns true if 'that' TimedEvent is fully contained within 'this' timed
+ // event.
+ bounds(that, opt_precisionUnit) {
+ if (opt_precisionUnit === undefined) {
+ opt_precisionUnit = tr.b.TimeDisplayModes.ms;
+ }
+
+ const startsBefore = opt_precisionUnit.roundedLess(
+ that.start, this.start);
+ const endsAfter = opt_precisionUnit.roundedLess(this.end, that.end);
+ return !startsBefore && !endsAfter;
+ }
+ };
+
+ return {
+ TimedEvent,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/timed_event_test.html b/chromium/third_party/catapult/tracing/tracing/model/timed_event_test.html
new file mode 100644
index 00000000000..f635dcf677d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/timed_event_test.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('bounds_startPrecision', function() {
+ const unit = tr.b.TimeDisplayModes;
+
+ const outer = new tr.model.TimedEvent(10.0001);
+ outer.duration = 0.9999;
+ const inner = new tr.model.TimedEvent(10.0000);
+ inner.duration = 1.0000;
+
+ assert.isTrue(outer.bounds(inner));
+ assert.isTrue(outer.bounds(inner, unit.ms));
+
+ assert.isFalse(outer.bounds(inner, unit.ns));
+ });
+
+ test('bounds_endPrecision', function() {
+ const unit = tr.b.TimeDisplayModes;
+
+ const outer = new tr.model.TimedEvent(10.0000);
+ outer.duration = 0.9999;
+ const inner = new tr.model.TimedEvent(10.0000);
+ inner.duration = 1.0000;
+
+ assert.isTrue(outer.bounds(inner));
+ assert.isTrue(outer.bounds(inner, unit.ms));
+
+ assert.isFalse(outer.bounds(inner, unit.ns));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/animation_expectation.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/animation_expectation.html
new file mode 100644
index 00000000000..a3fced6de2c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/animation_expectation.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.um', function() {
+ function AnimationExpectation(
+ parentModel, initiatorTitle, start, duration) {
+ tr.model.um.UserExpectation.call(
+ this, parentModel, initiatorTitle, start, duration);
+ this.frameEvents_ = undefined;
+ }
+
+ AnimationExpectation.prototype = {
+ __proto__: tr.model.um.UserExpectation.prototype,
+ constructor: AnimationExpectation,
+
+ get frameEvents() {
+ if (this.frameEvents_) {
+ return this.frameEvents_;
+ }
+
+ this.frameEvents_ = new tr.model.EventSet();
+
+ this.associatedEvents.forEach(function(event) {
+ if (event.title === tr.model.helpers.IMPL_RENDERING_STATS) {
+ this.frameEvents_.push(event);
+ }
+ }, this);
+
+ return this.frameEvents_;
+ }
+ };
+
+ tr.model.um.UserExpectation.subTypes.register(AnimationExpectation, {
+ stageTitle: 'Animation',
+ colorId: tr.b.ColorScheme.getColorIdForReservedName('rail_animation')
+ });
+
+ return {
+ AnimationExpectation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/idle_expectation.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/idle_expectation.html
new file mode 100644
index 00000000000..2312d46b62a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/idle_expectation.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.um', function() {
+ function IdleExpectation(parentModel, start, duration) {
+ const initiatorTitle = '';
+ tr.model.um.UserExpectation.call(
+ this, parentModel, initiatorTitle, start, duration);
+ }
+
+ IdleExpectation.prototype = {
+ __proto__: tr.model.um.UserExpectation.prototype,
+ constructor: IdleExpectation
+ };
+
+ tr.model.um.UserExpectation.subTypes.register(IdleExpectation, {
+ stageTitle: 'Idle',
+ colorId: tr.b.ColorScheme.getColorIdForReservedName('rail_idle')
+ });
+
+ return {
+ IdleExpectation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/load_expectation.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/load_expectation.html
new file mode 100644
index 00000000000..fb5298a46ed
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/load_expectation.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.um', function() {
+ const LOAD_SUBTYPE_NAMES = {
+ SUCCESSFUL: 'Successful',
+ FAILED: 'Failed',
+ };
+
+ const DOES_LOAD_SUBTYPE_NAME_EXIST = {};
+ for (const key in LOAD_SUBTYPE_NAMES) {
+ DOES_LOAD_SUBTYPE_NAME_EXIST[LOAD_SUBTYPE_NAMES[key]] = true;
+ }
+
+ function LoadExpectation(parentModel, initiatorTitle, start, duration,
+ renderer, navigationStart, fmpEvent, dclEndEvent, cpuIdleTime,
+ timeToInteractive, url, frameId) {
+ if (!DOES_LOAD_SUBTYPE_NAME_EXIST[initiatorTitle]) {
+ throw new Error(initiatorTitle + ' is not in LOAD_SUBTYPE_NAMES');
+ }
+
+ tr.model.um.UserExpectation.call(
+ this, parentModel, initiatorTitle, start, duration);
+
+ // |renderProcess| is the renderer process that contains the loading
+ // RenderFrame.
+ this.renderProcess = renderer;
+
+ // |renderMainThread| is the CrRendererMain thread in the |renderProcess|
+ // that contains the loading RenderFrame.
+ this.renderMainThread = undefined;
+
+ // |routingId| identifies the loading RenderFrame within the renderer
+ // process.
+ this.routingId = undefined;
+
+ // |parentRoutingId| identifies the RenderFrame that created and contains
+ // the loading RenderFrame.
+ this.parentRoutingId = undefined;
+
+ // |loadFinishedEvent|, if present, signals that this is a main frame.
+ this.loadFinishedEvent = undefined;
+
+ // Startup LoadExpectations do not have renderProcess, routingId, or
+ // parentRoutingId. Maybe RenderLoadExpectation should be a separate class?
+
+ // Navigation start event. The start of this event is the start time of
+ // load expectation.
+ this.navigationStart = navigationStart;
+
+ // First meaningful event corresponding to the navigation start event.
+ this.fmpEvent = fmpEvent;
+
+ // DomcontentLoadedEndEvent corresponding to the navigation start event.
+ this.domContentLoadedEndEvent = dclEndEvent;
+
+ // The computed firstCpuIdleTime. Please look at time_to_interactive.html
+ // for further details about this.
+ this.firstCpuIdleTime = cpuIdleTime;
+
+ // The time at which renderer is interactive. Please look at
+ // time_to_interactive.html for further details on how this is computed.
+ this.timeToInteractive = timeToInteractive;
+
+ this.url = url;
+ this.frameId = frameId;
+ }
+
+ LoadExpectation.prototype = {
+ __proto__: tr.model.um.UserExpectation.prototype,
+ constructor: LoadExpectation
+ };
+
+ tr.model.um.UserExpectation.subTypes.register(LoadExpectation, {
+ stageTitle: 'Load',
+ colorId: tr.b.ColorScheme.getColorIdForReservedName('rail_load')
+ });
+
+ return {
+ LOAD_SUBTYPE_NAMES,
+ LoadExpectation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/response_expectation.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/response_expectation.html
new file mode 100644
index 00000000000..83faacb27c3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/response_expectation.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.um', function() {
+ function ResponseExpectation(
+ parentModel, initiatorTitle, start, duration, opt_isAnimationBegin) {
+ tr.model.um.UserExpectation.call(
+ this, parentModel, initiatorTitle, start, duration);
+ this.isAnimationBegin = opt_isAnimationBegin || false;
+ }
+
+ ResponseExpectation.prototype = {
+ __proto__: tr.model.um.UserExpectation.prototype,
+ constructor: ResponseExpectation
+ };
+
+ tr.model.um.UserExpectation.subTypes.register(ResponseExpectation, {
+ stageTitle: 'Response',
+ colorId: tr.b.ColorScheme.getColorIdForReservedName('rail_response')
+ });
+
+ return {
+ ResponseExpectation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/segment.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/segment.html
new file mode 100644
index 00000000000..61da1e26363
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/segment.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.um', function() {
+ /**
+ * Segment represents a range of time during which the set of active
+ * UserExpectations does not change. Segments are guaranteed to not overlap,
+ * whereas UserExpectations can overlap. After UserModelBuilder builds the
+ * UserExpectations in the model, it segments the timeline into
+ * non-overlapping Segments and adds the constituent UserExpectations to each
+ * Segment.
+ */
+ class Segment extends tr.model.TimedEvent {
+ constructor(start, duration) {
+ super(start);
+ this.duration = duration;
+ this.expectations_ = [];
+ }
+
+ get expectations() {
+ return this.expectations_;
+ }
+
+ clone() {
+ const clone = new Segment(this.start, this.duration);
+ clone.expectations.push(...this.expectations);
+ return clone;
+ }
+
+ addSegment(other) {
+ this.duration += other.duration;
+ this.expectations.push(...other.expectations);
+ }
+ }
+
+ return {
+ Segment,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/startup_expectation.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/startup_expectation.html
new file mode 100644
index 00000000000..809debc3fb3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/startup_expectation.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.um', function() {
+ function StartupExpectation(parentModel, start, duration) {
+ tr.model.um.UserExpectation.call(
+ this, parentModel, '', start, duration);
+ }
+
+ StartupExpectation.prototype = {
+ __proto__: tr.model.um.UserExpectation.prototype,
+ constructor: StartupExpectation
+ };
+
+ tr.model.um.UserExpectation.subTypes.register(StartupExpectation, {
+ stageTitle: 'Startup',
+ colorId: tr.b.ColorScheme.getColorIdForReservedName('startup')
+ });
+
+ return {
+ StartupExpectation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/stub_expectation.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/stub_expectation.html
new file mode 100644
index 00000000000..4bd48ffba58
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/stub_expectation.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/user_model/user_expectation.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Stub version of UserExpectation for testing.
+ */
+tr.exportTo('tr.model.um', function() {
+ function StubExpectation(args) {
+ this.stageTitle_ = args.stageTitle || 'Idle';
+ this.initiatorTitle_ = args.initiatorTitle || '';
+
+ this.title_ = args.title;
+ if (!this.title_) {
+ const defaultTitle = [];
+ if (this.initiatorTitle_) {
+ defaultTitle.push(this.initiatorTitle_);
+ }
+ if (this.stageTitle_) {
+ defaultTitle.push(this.stageTitle_);
+ }
+ this.title_ = defaultTitle.join(' ') || 'title';
+ }
+
+ this.normalizedUserComfort_ = args.normalizedUserComfort || 0;
+ this.normalizedEfficiency_ = args.normalizedEfficiency || 0;
+
+ const sd = tr.c.TestUtils.getStartAndDurationFromDict(args);
+
+ tr.model.um.UserExpectation.call(
+ this, args.parentModel, this.initiatorTitle, sd.start, sd.duration);
+
+ // Must be set after base class call.
+ this.colorId_ = args.colorId || 0;
+
+ if (args.associatedEvents) {
+ args.associatedEvents.forEach(function(event) {
+ this.associatedEvents.push(event);
+ }, this);
+ }
+ }
+
+ StubExpectation.prototype = {
+ __proto__: tr.model.um.UserExpectation.prototype,
+
+ get colorId() {
+ return this.colorId_;
+ },
+
+ get title() {
+ return this.title_;
+ },
+
+ get stageTitle() {
+ return this.stageTitle_;
+ },
+
+ get initiatorTitle() {
+ return this.initiatorTitle_;
+ }
+ };
+
+ return {
+ StubExpectation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/user_expectation.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/user_expectation.html
new file mode 100644
index 00000000000..04363da142a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/user_expectation.html
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/compound_event_selection_state.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/timed_event.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.um', function() {
+ const CompoundEventSelectionState = tr.model.CompoundEventSelectionState;
+
+ function UserExpectation(parentModel, initiatorType, start, duration) {
+ tr.model.TimedEvent.call(this, start);
+ this.associatedEvents = new tr.model.EventSet();
+ this.duration = duration;
+ this.initiatorType_ = initiatorType;
+ this.parentModel = parentModel;
+ this.typeInfo_ = undefined;
+
+ // sourceEvents are the ones that caused the UserModelBuilder to create this
+ // UserExpectation.
+ this.sourceEvents = new tr.model.EventSet();
+ }
+
+ // Strings used to name UEs.
+ const INITIATOR_TYPE = {
+ KEYBOARD: 'Keyboard',
+ MOUSE: 'Mouse',
+ MOUSE_WHEEL: 'MouseWheel',
+ TAP: 'Tap',
+ PINCH: 'Pinch',
+ FLING: 'Fling',
+ TOUCH: 'Touch',
+ SCROLL: 'Scroll',
+ CSS: 'CSS',
+ WEBGL: 'WebGL',
+ VIDEO: 'Video',
+ VR: 'VR',
+ };
+
+ UserExpectation.prototype = {
+ __proto__: tr.model.TimedEvent.prototype,
+
+ computeCompoundEvenSelectionState(selection) {
+ let cess = CompoundEventSelectionState.NOT_SELECTED;
+ if (selection.contains(this)) {
+ cess |= CompoundEventSelectionState.EVENT_SELECTED;
+ }
+
+ if (this.associatedEvents.intersectionIsEmpty(selection)) {
+ return cess;
+ }
+
+ const allContained = this.associatedEvents.every(function(event) {
+ return selection.contains(event);
+ });
+
+ if (allContained) {
+ cess |= CompoundEventSelectionState.ALL_ASSOCIATED_EVENTS_SELECTED;
+ } else {
+ cess |= CompoundEventSelectionState.SOME_ASSOCIATED_EVENTS_SELECTED;
+ }
+ return cess;
+ },
+
+ // Returns samples which are overlapping with V8.Execute
+ get associatedSamples() {
+ const samples = new tr.model.EventSet();
+ this.associatedEvents.forEach(function(event) {
+ if (event instanceof tr.model.ThreadSlice) {
+ samples.addEventSet(event.overlappingSamples);
+ }
+ });
+ return samples;
+ },
+
+ get userFriendlyName() {
+ return this.title + ' User Expectation at ' +
+ tr.b.Unit.byName.timeStampInMs.format(this.start);
+ },
+
+ get stableId() {
+ return ('UserExpectation.' + this.guid);
+ },
+
+ get typeInfo() {
+ if (!this.typeInfo_) {
+ this.typeInfo_ = UserExpectation.subTypes.findTypeInfo(
+ this.constructor);
+ }
+
+ // If you set Subclass.prototype = {}, then you must explicitly specify
+ // constructor in that prototype object!
+ // http://javascript.info/tutorial/constructor
+
+ if (!this.typeInfo_) {
+ throw new Error('Unregistered UserExpectation');
+ }
+
+ return this.typeInfo_;
+ },
+
+ get colorId() {
+ return this.typeInfo.metadata.colorId;
+ },
+
+ get stageTitle() {
+ return this.typeInfo.metadata.stageTitle;
+ },
+
+ get initiatorType() {
+ return this.initiatorType_;
+ },
+
+ get title() {
+ if (!this.initiatorType) {
+ return this.stageTitle;
+ }
+
+ return this.initiatorType + ' ' + this.stageTitle;
+ },
+
+ /**
+ * Returns the sum of the number of CPU ms spent by this UserExpectation.
+ */
+ get totalCpuMs() {
+ let cpuMs = 0;
+ this.associatedEvents.forEach(function(event) {
+ if (event.cpuSelfTime) {
+ cpuMs += event.cpuSelfTime;
+ }
+ });
+ return cpuMs;
+ }
+ };
+
+ const subTypes = {};
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ tr.b.decorateExtensionRegistry(subTypes, options);
+
+ subTypes.addEventListener('will-register', function(e) {
+ const metadata = e.typeInfo.metadata;
+
+ if (metadata.stageTitle === undefined) {
+ throw new Error('Registered UserExpectations must provide ' +
+ 'stageTitle');
+ }
+
+ if (metadata.colorId === undefined) {
+ throw new Error('Registered UserExpectations must provide ' +
+ 'colorId');
+ }
+ });
+
+ tr.model.EventRegistry.register(
+ UserExpectation,
+ {
+ name: 'userExpectation',
+ pluralName: 'userExpectations',
+ subTypes
+ });
+
+ return {
+ UserExpectation,
+ INITIATOR_TYPE,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/user_model.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/user_model.html
new file mode 100644
index 00000000000..38b6e13a00c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/user_model.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_container.html">
+<link rel="import" href="/tracing/model/user_model/segment.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model.um', function() {
+ class UserModel extends tr.model.EventContainer {
+ constructor(parentModel) {
+ super();
+ this.parentModel_ = parentModel;
+ this.expectations_ = new tr.model.EventSet();
+ this.segments_ = [];
+ }
+
+ get stableId() {
+ return 'UserModel';
+ }
+
+ get parentModel() {
+ return this.parentModel_;
+ }
+
+ sortExpectations() {
+ this.expectations_.sortEvents((x, y) => (x.start - y.start));
+ }
+
+ get expectations() {
+ return this.expectations_;
+ }
+
+ shiftTimestampsForward(amount) {
+ }
+
+ addCategoriesToDict(categoriesDict) {
+ }
+
+ get segments() {
+ return this.segments_;
+ }
+
+ * childEvents() {
+ yield* this.expectations;
+ }
+
+ * childEventContainers() {
+ }
+
+ updateBounds() {
+ this.bounds.reset();
+ for (const expectation of this.expectations) {
+ expectation.addBoundsToRange(this.bounds);
+ }
+ }
+
+ /**
+ * Return a new array of new Segments by merging adjacent segments when
+ * |getKeyForSegment| returns identical keys.
+ * |getKeyForSegment| is called with each Segment and the index of that
+ * Segment.
+ *
+ * @param {!function(!tr.model.um.Segment, number):*} getKeyForSegment
+ * @return {!Array.<!tr.model.um.Segment>}
+ */
+ resegment(getKeyForSegment) {
+ const newSegments = [];
+ let prevKey = undefined;
+ let prevSegment = undefined;
+ for (let i = 0; i < this.segments.length; ++i) {
+ const segment = this.segments[i];
+ const key = getKeyForSegment(segment, i);
+ if (prevSegment !== undefined && key === prevKey) {
+ prevSegment.addSegment(segment);
+ } else {
+ prevSegment = segment.clone();
+ newSegments.push(prevSegment);
+ }
+ prevKey = key;
+ }
+ return newSegments;
+ }
+ }
+
+ return {
+ UserModel,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/user_model/user_model_test.html b/chromium/third_party/catapult/tracing/tracing/model/user_model/user_model_test.html
new file mode 100644
index 00000000000..c2a09c5074e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/user_model/user_model_test.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/user_model/segment.html">
+<link rel="import" href="/tracing/model/user_model/user_model.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('resegment', function() {
+ const userModel = new tr.model.um.UserModel(undefined);
+ userModel.segments.push(new tr.model.um.Segment(0, 1));
+ userModel.segments.push(new tr.model.um.Segment(1, 1));
+ userModel.segments.push(new tr.model.um.Segment(2, 1));
+ userModel.segments.push(new tr.model.um.Segment(3, 1));
+
+ userModel.segments[0].expectations.push('a');
+ userModel.segments[1].expectations.push('b');
+ userModel.segments[2].expectations.push('c');
+ userModel.segments[3].expectations.push('d');
+
+ const newSegments = userModel.resegment(
+ (segment, index) => Math.floor(index / 2));
+
+ assert.lengthOf(newSegments, 2);
+ assert.strictEqual(0, newSegments[0].start);
+ assert.strictEqual(2, newSegments[0].end);
+ assert.strictEqual(2, newSegments[1].start);
+ assert.strictEqual(4, newSegments[1].end);
+
+ assert.lengthOf(newSegments[0].expectations, 2);
+ assert.lengthOf(newSegments[1].expectations, 2);
+
+ assert.strictEqual('a', newSegments[0].expectations[0]);
+ assert.strictEqual('b', newSegments[0].expectations[1]);
+ assert.strictEqual('c', newSegments[1].expectations[0]);
+ assert.strictEqual('d', newSegments[1].expectations[1]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/vm_region.html b/chromium/third_party/catapult/tracing/tracing/model/vm_region.html
new file mode 100644
index 00000000000..4b02f7c24cc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/vm_region.html
@@ -0,0 +1,444 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides classes for representing and classifying VM regions.
+ *
+ * See https://goo.gl/5SSPv0 for more details.
+ */
+tr.exportTo('tr.model', function() {
+ /**
+ * A single virtual memory region (also called a memory map).
+ *
+ * @constructor
+ */
+ function VMRegion(startAddress, sizeInBytes, protectionFlags,
+ mappedFile, byteStats) {
+ this.startAddress = startAddress;
+ this.sizeInBytes = sizeInBytes;
+ this.protectionFlags = protectionFlags;
+ this.mappedFile = mappedFile || '';
+ this.byteStats = byteStats || {};
+ }
+
+ VMRegion.PROTECTION_FLAG_READ = 4;
+ VMRegion.PROTECTION_FLAG_WRITE = 2;
+ VMRegion.PROTECTION_FLAG_EXECUTE = 1;
+ VMRegion.PROTECTION_FLAG_MAYSHARE = 128;
+
+ VMRegion.prototype = {
+ get uniqueIdWithinProcess() {
+ // This value is assumed to be unique within a process.
+ return this.mappedFile + '#' + this.startAddress;
+ },
+
+ get protectionFlagsToString() {
+ if (this.protectionFlags === undefined) return undefined;
+ return (
+ (this.protectionFlags & VMRegion.PROTECTION_FLAG_READ ? 'r' : '-') +
+ (this.protectionFlags & VMRegion.PROTECTION_FLAG_WRITE ? 'w' : '-') +
+ (this.protectionFlags & VMRegion.PROTECTION_FLAG_EXECUTE ?
+ 'x' : '-') +
+ (this.protectionFlags & VMRegion.PROTECTION_FLAG_MAYSHARE ? 's' : 'p')
+ );
+ }
+ };
+
+ VMRegion.fromDict = function(dict) {
+ return new VMRegion(
+ dict.startAddress,
+ dict.sizeInBytes,
+ dict.protectionFlags,
+ dict.mappedFile,
+ dict.byteStats);
+ };
+
+ /**
+ * Node in a VM region classification tree.
+ *
+ * Note: Most users of this class should use the
+ * VMRegionClassificationNode.fromRegions static method instead of this
+ * constructor because it leads to better performance due to fewer memory
+ * allocations.
+ *
+ * @constructor
+ */
+ function VMRegionClassificationNode(opt_rule) {
+ this.rule_ = opt_rule || VMRegionClassificationNode.CLASSIFICATION_RULES;
+
+ // True iff this node or any of its descendant classification nodes has at
+ // least one classified VM region.
+ this.hasRegions = false;
+
+ // Total virtual size and byte stats of all regions matching this node's
+ // rule (including its sub-rules).
+ this.sizeInBytes = undefined;
+ this.byteStats = {};
+
+ // Array of child classification nodes if this is an intermediate node.
+ this.children_ = undefined;
+
+ // Array of VM regions. If this is an intermediate node, then the regions
+ // are cached for lazy tree construction (i.e. its child classification
+ // nodes yet have to be built).
+ this.regions_ = [];
+ }
+
+ /**
+ * Rules for classifying memory maps.
+ *
+ * These rules are derived from core/jni/android_os_Debug.cpp in Android.
+ */
+ VMRegionClassificationNode.CLASSIFICATION_RULES = {
+ name: 'Total',
+ children: [
+ {
+ name: 'Android',
+ file: /^\/dev\/ashmem(?!\/libc malloc)/,
+ children: [
+ {
+ name: 'Java runtime',
+ file: /^\/dev\/ashmem\/dalvik-/,
+ children: [
+ {
+ name: 'Spaces',
+ file: /\/dalvik-(alloc|main|large object|non moving|zygote) space/, // @suppress longLineCheck
+ children: [
+ {
+ name: 'Normal',
+ file: /\/dalvik-(alloc|main)/
+ },
+ {
+ name: 'Large',
+ file: /\/dalvik-large object/
+ },
+ {
+ name: 'Zygote',
+ file: /\/dalvik-zygote/
+ },
+ {
+ name: 'Non-moving',
+ file: /\/dalvik-non moving/
+ }
+ ]
+ },
+ {
+ name: 'Linear Alloc',
+ file: /\/dalvik-LinearAlloc/
+ },
+ {
+ name: 'Indirect Reference Table',
+ file: /\/dalvik-indirect.ref/
+ },
+ {
+ name: 'Cache',
+ file: /\/dalvik-jit-code-cache/
+ },
+ {
+ name: 'Accounting'
+ }
+ ]
+ },
+ {
+ name: 'Cursor',
+ file: /\/CursorWindow/
+ },
+ {
+ name: 'Ashmem'
+ }
+ ]
+ },
+ {
+ name: 'Native heap',
+ file: /^((\[heap\])|(\[anon:)|(\/dev\/ashmem\/libc malloc)|(\[discounted tracing overhead\])|$)/ // @suppress longLineCheck
+ },
+ {
+ name: 'Stack',
+ file: /^\[stack/
+ },
+ {
+ name: 'Files',
+ file: /\.((((jar)|(apk)|(ttf)|(odex)|(oat)|(art))$)|(dex)|(so))/,
+ children: [
+ {
+ name: 'so',
+ file: /\.so/
+ },
+ {
+ name: 'jar',
+ file: /\.jar$/
+ },
+ {
+ name: 'apk',
+ file: /\.apk$/
+ },
+ {
+ name: 'ttf',
+ file: /\.ttf$/
+ },
+ {
+ name: 'dex',
+ file: /\.((dex)|(odex$))/
+ },
+ {
+ name: 'oat',
+ file: /\.oat$/
+ },
+ {
+ name: 'art',
+ file: /\.art$/
+ }
+ ]
+ },
+ {
+ name: 'Devices',
+ file: /(^\/dev\/)|(anon_inode:dmabuf)/,
+ children: [
+ {
+ name: 'GPU',
+ file: /\/((nv)|(mali)|(kgsl))/
+ },
+ {
+ name: 'DMA',
+ file: /anon_inode:dmabuf/
+ }
+ ]
+ }
+ ]
+ };
+ VMRegionClassificationNode.OTHER_RULE = { name: 'Other' };
+
+ VMRegionClassificationNode.fromRegions = function(regions, opt_rules) {
+ const tree = new VMRegionClassificationNode(opt_rules);
+ tree.regions_ = regions;
+ for (let i = 0; i < regions.length; i++) {
+ tree.addStatsFromRegion_(regions[i]);
+ }
+ return tree;
+ };
+
+ VMRegionClassificationNode.prototype = {
+ get title() {
+ return this.rule_.name;
+ },
+
+ get children() {
+ if (this.isLeafNode) {
+ return undefined; // Leaf nodes don't have children (by definition).
+ }
+ if (this.children_ === undefined) {
+ this.buildTree_(); // Lazily classify VM regions.
+ }
+ return this.children_;
+ },
+
+ get regions() {
+ if (!this.isLeafNode) {
+ // Intermediate nodes only temporarily cache VM regions for lazy tree
+ // construction.
+ return undefined;
+ }
+ return this.regions_;
+ },
+
+ get allRegionsForTesting() {
+ if (this.regions_ !== undefined) {
+ if (this.children_ !== undefined) {
+ throw new Error('Internal error: a VM region classification node ' +
+ 'cannot have both regions and children');
+ }
+ // Leaf node (or caching internal node).
+ return this.regions_;
+ }
+
+ // Intermediate node.
+ let regions = [];
+ this.children_.forEach(function(childNode) {
+ regions = regions.concat(childNode.allRegionsForTesting);
+ });
+ return regions;
+ },
+
+ get isLeafNode() {
+ const children = this.rule_.children;
+ return children === undefined || children.length === 0;
+ },
+
+ addRegion(region) {
+ this.addRegionRecursively_(region, true /* addStatsToThisNode */);
+ },
+
+ someRegion(fn, opt_this) {
+ if (this.regions_ !== undefined) {
+ // Leaf node (or caching internal node).
+ return this.regions_.some(fn, opt_this);
+ }
+
+ // Intermediate node.
+ return this.children_.some(function(childNode) {
+ return childNode.someRegion(fn, opt_this);
+ });
+ },
+
+ addRegionRecursively_(region, addStatsToThisNode) {
+ if (addStatsToThisNode) {
+ this.addStatsFromRegion_(region);
+ }
+
+ if (this.regions_ !== undefined) {
+ if (this.children_ !== undefined) {
+ throw new Error('Internal error: a VM region classification node ' +
+ 'cannot have both regions and children');
+ }
+ // Leaf node or an intermediate node caching VM regions (add the
+ // region to this node and don't classify further).
+ this.regions_.push(region);
+ return;
+ }
+
+ // Non-leaf rule (classify region row further down the tree).
+ function regionRowMatchesChildNide(child) {
+ const fileRegExp = child.rule_.file;
+ if (fileRegExp === undefined) return true;
+ return fileRegExp.test(region.mappedFile);
+ }
+
+ let matchedChild = this.children_.find(regionRowMatchesChildNide);
+ if (matchedChild === undefined) {
+ // Region belongs to the 'Other' node (created lazily).
+ if (this.children_.length !== this.rule_.children.length) {
+ throw new Error('Internal error');
+ }
+ matchedChild = new VMRegionClassificationNode(
+ VMRegionClassificationNode.OTHER_RULE);
+ this.children_.push(matchedChild);
+ }
+
+ matchedChild.addRegionRecursively_(region, true);
+ },
+
+ buildTree_() {
+ const cachedRegions = this.regions_;
+ this.regions_ = undefined;
+
+ this.buildChildNodesRecursively_();
+ for (let i = 0; i < cachedRegions.length; i++) {
+ // Note that we don't add the VM region's stats to this node because
+ // they have already been added to it.
+ this.addRegionRecursively_(
+ cachedRegions[i], false /* addStatsToThisNode */);
+ }
+ },
+
+ buildChildNodesRecursively_() {
+ if (this.children_ !== undefined) {
+ throw new Error(
+ 'Internal error: Classification node already has children');
+ }
+ if (this.regions_ !== undefined && this.regions_.length !== 0) {
+ throw new Error(
+ 'Internal error: Classification node should have no regions');
+ }
+
+ if (this.isLeafNode) {
+ return; // Leaf node: Nothing to do.
+ }
+
+ // Intermediate node: Clear regions and build children recursively.
+ this.regions_ = undefined;
+ this.children_ = this.rule_.children.map(function(childRule) {
+ const child = new VMRegionClassificationNode(childRule);
+ child.buildChildNodesRecursively_();
+ return child;
+ });
+ },
+
+ addStatsFromRegion_(region) {
+ this.hasRegions = true;
+
+ // Aggregate virtual size.
+ const regionSizeInBytes = region.sizeInBytes;
+ if (regionSizeInBytes !== undefined) {
+ this.sizeInBytes = (this.sizeInBytes || 0) + regionSizeInBytes;
+ }
+
+ // Aggregate byte stats.
+ const thisByteStats = this.byteStats;
+ const regionByteStats = region.byteStats;
+ for (const byteStatName in regionByteStats) {
+ const regionByteStatValue = regionByteStats[byteStatName];
+ if (regionByteStatValue === undefined) continue;
+ thisByteStats[byteStatName] =
+ (thisByteStats[byteStatName] || 0) + regionByteStatValue;
+ }
+
+ // Aggregate java base.* stats.
+ if (region.mappedFile.includes('/base.odex') ||
+ region.mappedFile.includes('/base.vdex')) {
+ if (region.byteStats.proportionalResident !== undefined) {
+ thisByteStats.javaBasePss =
+ (thisByteStats.javaBasePss || 0) +
+ region.byteStats.proportionalResident;
+ }
+ if (region.byteStats.privateCleanResident !== undefined) {
+ thisByteStats.javaBaseCleanResident =
+ (thisByteStats.javaBaseCleanResident || 0) +
+ region.byteStats.privateCleanResident;
+ }
+ if (region.byteStats.sharedCleanResident !== undefined) {
+ thisByteStats.javaBaseCleanResident =
+ (thisByteStats.javaBaseCleanResident || 0) +
+ region.byteStats.sharedCleanResident;
+ }
+ }
+
+ // Aggregate native library stats.
+ const textProtectionFlags = (VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE);
+ // On post-M devices, the native library is mapped from /base.apk. On M
+ // and earlier devices, it's mapped from /libchrome.so. In both cases only
+ // the regions that are readable and executable should be counted.
+ // TODO(mattcary): if both mappings are seen, something has gone wrong and
+ // some sort of error or fatal should be done. This should be tracked
+ // across regions, which means adding state to |this|.
+ if ((region.protectionFlags === textProtectionFlags) &&
+ (region.mappedFile.includes('/base.apk') ||
+ region.mappedFile.includes('/libchrome.so'))) {
+ if (regionSizeInBytes !== undefined) {
+ this.nativeLibrarySizeInBytes =
+ (this.nativeLibrarySizeInBytes || 0) + regionSizeInBytes;
+ }
+ if (region.byteStats.privateCleanResident !== undefined) {
+ thisByteStats.nativeLibraryPrivateCleanResident =
+ (thisByteStats.nativeLibraryPrivateCleanResident || 0) +
+ region.byteStats.privateCleanResident;
+ }
+ if (region.byteStats.sharedCleanResident !== undefined) {
+ thisByteStats.nativeLibrarySharedCleanResident =
+ (thisByteStats.nativeLibrarySharedCleanResident || 0) +
+ region.byteStats.sharedCleanResident;
+ }
+ if (region.byteStats.proportionalResident !== undefined) {
+ thisByteStats.nativeLibraryProportionalResident =
+ (thisByteStats.nativeLibraryProportionalResident || 0) +
+ region.byteStats.proportionalResident;
+ }
+ }
+ }
+ };
+
+ return {
+ VMRegion,
+ VMRegionClassificationNode,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/vm_region_test.html b/chromium/third_party/catapult/tracing/tracing/model/vm_region_test.html
new file mode 100644
index 00000000000..93b8ad1647c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/vm_region_test.html
@@ -0,0 +1,1216 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const VMRegion = tr.model.VMRegion;
+ const VMRegionClassificationNode = tr.model.VMRegionClassificationNode;
+ const checkVMRegions = tr.model.MemoryDumpTestUtils.checkVMRegions;
+
+ function checkProtectionFlagsToString(protectionFlags, expectedString) {
+ const vmRegion = VMRegion.fromDict({
+ startAddress: 256,
+ sizeInBytes: 336,
+ protectionFlags,
+ mappedFile: '[stack:20310]',
+ byteStats: {
+ privateDirtyResident: 96,
+ swapped: 144,
+ proportionalResident: 158
+ }
+ });
+ assert.strictEqual(vmRegion.protectionFlagsToString, expectedString);
+ }
+
+ const TEST_RULES = {
+ name: 'Root',
+ children: [
+ {
+ name: 'Words',
+ file: /^[a-zA-Z]/,
+ children: [
+ {
+ name: 'A-D',
+ file: /^[a-dA-D]/
+ },
+ {
+ name: 'E-H',
+ file: /^[e-hE-H]/
+ }
+ ]
+ },
+ {
+ name: 'Digits',
+ file: /\d$/,
+ children: []
+ }
+ ]
+ };
+
+ // Constant representing the expectation that the children of a
+ // VMRegionClassificationNode have not been built yet.
+ const CHILDREN_NOT_BUILT_YET = {};
+
+ function checkTree(node, expectedStructure) {
+ assert.strictEqual(node.title, expectedStructure.title);
+ assert.strictEqual(node.hasRegions, expectedStructure.hasRegions);
+ assert.strictEqual(node.sizeInBytes, expectedStructure.sizeInBytes);
+ assert.deepEqual(node.byteStats, expectedStructure.byteStats || {});
+ assert.strictEqual(node.isLeafNode, expectedStructure.isLeafNode);
+
+ const actualRegions = node.regions;
+ const expectedRegions = expectedStructure.regions;
+ if (expectedRegions === undefined) {
+ assert.isUndefined(actualRegions);
+ } else {
+ assert.instanceOf(actualRegions, Array);
+ checkVMRegions(actualRegions, expectedRegions);
+ }
+
+ const expectedChildren = expectedStructure.children;
+ if (expectedChildren === CHILDREN_NOT_BUILT_YET) {
+ assert.isUndefined(node.children_);
+ } else if (expectedChildren === undefined) {
+ assert.isUndefined(node.children);
+ } else {
+ const actualChildrenMap = new Map();
+ node.children.forEach(function(childNode) {
+ actualChildrenMap.set(childNode.title, childNode);
+ });
+ const expectedChildrenMap = new Map();
+ expectedChildren.forEach(function(childNode) {
+ expectedChildrenMap.set(childNode.title, childNode);
+ });
+ assert.strictEqual(actualChildrenMap.size, expectedChildrenMap.size);
+ for (const title of expectedChildrenMap.keys()) {
+ checkTree(actualChildrenMap.get(title),
+ expectedChildrenMap.get(title));
+ }
+ }
+ }
+
+ function checkClassificationRules(mappedFile, expectedPath) {
+ const region = VMRegion.fromDict({
+ mappedFile,
+ sizeInBytes: 16,
+ byteStats: {
+ privateDirtyResident: 7
+ }
+ });
+ let node = VMRegionClassificationNode.fromRegions([region]);
+ for (const title of expectedPath) {
+ node = node.children.find(c => c.title === title);
+ }
+ assert.deepEqual(node.regions, [region]);
+ }
+
+ test('vmRegion_protectionFlagsToString', function() {
+ checkProtectionFlagsToString(undefined, undefined);
+ checkProtectionFlagsToString(0, '---p');
+ checkProtectionFlagsToString(VMRegion.PROTECTION_FLAG_READ, 'r--p');
+ checkProtectionFlagsToString(
+ VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_MAYSHARE,
+ 'r--s');
+ checkProtectionFlagsToString(
+ VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_EXECUTE,
+ 'r-xp');
+ checkProtectionFlagsToString(
+ VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_WRITE,
+ 'rw-p');
+ checkProtectionFlagsToString(
+ VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_WRITE |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ 'rwxp');
+ checkProtectionFlagsToString(
+ VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_WRITE |
+ VMRegion.PROTECTION_FLAG_MAYSHARE,
+ 'rw-s');
+ checkProtectionFlagsToString(
+ VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_EXECUTE |
+ VMRegion.PROTECTION_FLAG_MAYSHARE,
+ 'r-xs');
+ checkProtectionFlagsToString(
+ VMRegion.PROTECTION_FLAG_READ | VMRegion.PROTECTION_FLAG_WRITE |
+ VMRegion.PROTECTION_FLAG_EXECUTE |
+ VMRegion.PROTECTION_FLAG_MAYSHARE,
+ 'rwxs');
+ });
+
+ // The add(After|Before)Build tests below check that the classification tree
+ // has the correct structure regardless of the ordering of adding regions and
+ // the lazy construction.
+
+ test('vmRegionClassificationNode_constructor_addAfterBuild', function() {
+ const rootNode = new VMRegionClassificationNode(TEST_RULES);
+
+ // Check the root node and verify that the full tree structure has *not*
+ // been constructed yet.
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: false,
+ isLeafNode: false,
+ children: CHILDREN_NOT_BUILT_YET
+ });
+
+ // Reading the children of the root node *should* trigger building the
+ // full tree.
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: false,
+ isLeafNode: false,
+ children: [
+ {
+ title: 'Words',
+ hasRegions: false,
+ isLeafNode: false,
+ children: [
+ {
+ title: 'A-D',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'E-H',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ }
+ ]
+ },
+ {
+ title: 'Digits',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ }
+ ]
+ });
+
+ // Add VM regions to the tree *after* it has been fully built.
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: 'W2', // Root/Words/Other.
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }));
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: '__42', // Root/Digits.
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ }));
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32 + 33,
+ privateDirtyResident: 77,
+ swapped: 64
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'Words',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'A-D',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'E-H',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'Other',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: 'W2',
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ title: 'Digits',
+ hasRegions: true,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: '__42',
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ }
+ ]
+ }
+ ]
+ });
+ });
+
+ test('vmRegionClassificationNode_constructor_addBeforeBuild', function() {
+ const rootNode = new VMRegionClassificationNode(TEST_RULES);
+
+ // Add regions to the tree *before* it has been fully built. This should
+ // *not* trigger building the full tree (but the total sizeInBytes and
+ // byteStats should be updated accordingly).
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: '__42', // Root/Digits.
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ }));
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: 'W2', // Root/Words/Other.
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }));
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32 + 33,
+ privateDirtyResident: 77,
+ swapped: 64
+ },
+ isLeafNode: false,
+ children: CHILDREN_NOT_BUILT_YET
+ });
+
+ // Reading the children of the root node should trigger building the full
+ // tree.
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32 + 33,
+ privateDirtyResident: 77,
+ swapped: 64
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'Words',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'A-D',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'E-H',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'Other',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: 'W2',
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ title: 'Digits',
+ hasRegions: true,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: '__42',
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ }
+ ]
+ }
+ ]
+ });
+
+ // Add more VM regions *after* the tree has been fully built.
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: '%invalid%', // Root/Other.
+ sizeInBytes: 123
+ }));
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: '__43', // Root/Digits.
+ byteStats: {
+ swapped: 19
+ }
+ }));
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: 'free', // Root/Words/E-H.
+ sizeInBytes: undefined
+ }));
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ sizeInBytes: 16 + 123,
+ byteStats: {
+ proportionalResident: 32 + 33,
+ privateDirtyResident: 77,
+ swapped: 64 + 19,
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'Words',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'A-D',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'E-H',
+ hasRegions: true,
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: 'free'
+ }
+ ]
+ },
+ {
+ title: 'Other',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: 'W2',
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ title: 'Digits',
+ hasRegions: true,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77,
+ swapped: 19
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: '__42',
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ },
+ {
+ mappedFile: '__43',
+ byteStats: {
+ swapped: 19
+ }
+ }
+ ]
+ },
+ {
+ title: 'Other',
+ hasRegions: true,
+ sizeInBytes: 123,
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: '%invalid%',
+ sizeInBytes: 123
+ }
+ ]
+ }
+ ]
+ });
+ });
+
+ test('vmRegionClassificationNode_fromRegions_addAfterBuild', function() {
+ // Construct the root node from a list of regions. This should *not*
+ // trigger building the full tree (but the total sizeInBytes and byteStats
+ // should be updated accordingly).
+ const rootNode = VMRegionClassificationNode.fromRegions([
+ VMRegion.fromDict({
+ mappedFile: '__42', // Root/Digits.
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '__43', // Root/Digits.
+ byteStats: {
+ swapped: 19
+ }
+ })
+ ], TEST_RULES);
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77,
+ swapped: 19
+ },
+ isLeafNode: false,
+ children: CHILDREN_NOT_BUILT_YET
+ });
+
+ // Reading the children of the root node should trigger building the full
+ // tree.
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77,
+ swapped: 19
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'Words',
+ hasRegions: false,
+ isLeafNode: false,
+ children: [
+ {
+ title: 'A-D',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'E-H',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ }
+ ]
+ },
+ {
+ title: 'Digits',
+ hasRegions: true,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77,
+ swapped: 19
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: '__42',
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ },
+ {
+ mappedFile: '__43',
+ byteStats: {
+ swapped: 19
+ }
+ }
+ ]
+ }
+ ]
+ });
+
+ // Add more VM regions *after* the tree has been fully built.
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: 'W2', // Root/Words/Other.
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }));
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32 + 33,
+ privateDirtyResident: 77,
+ swapped: 19 + 64,
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'Words',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'A-D',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'E-H',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'Other',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: 'W2',
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ title: 'Digits',
+ hasRegions: true,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77,
+ swapped: 19
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: '__42',
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ },
+ {
+ mappedFile: '__43',
+ byteStats: {
+ swapped: 19
+ }
+ }
+ ]
+ }
+ ]
+ });
+ });
+
+ test('vmRegionClassificationNode_fromRegions_addBeforeBuild', function() {
+ // Construct the root node from a list of regions and then add another
+ // region. This should *not* trigger building the full tree (but the total
+ // sizeInBytes and byteStats should be updated accordingly).
+ const rootNode = VMRegionClassificationNode.fromRegions([
+ VMRegion.fromDict({
+ mappedFile: '__42', // Root/Digits.
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '__43', // Root/Digits.
+ byteStats: {
+ swapped: 19
+ }
+ })
+ ], TEST_RULES);
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: '__42', // Root/Digits.
+ startAddress: 2048, // Necessary to distinguish from the first region.
+ sizeInBytes: 1000,
+ byteStats: {
+ privateDirtyResident: 500
+ }
+ }));
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ sizeInBytes: 1000,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77 + 500,
+ swapped: 19
+ },
+ isLeafNode: false,
+ children: CHILDREN_NOT_BUILT_YET
+ });
+
+ // Reading the children of the root node should trigger building the full
+ // tree.
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ sizeInBytes: 1000,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77 + 500,
+ swapped: 19
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'Words',
+ hasRegions: false,
+ isLeafNode: false,
+ children: [
+ {
+ title: 'A-D',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'E-H',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ }
+ ]
+ },
+ {
+ title: 'Digits',
+ hasRegions: true,
+ sizeInBytes: 1000,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77 + 500,
+ swapped: 19
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: '__42',
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ },
+ {
+ mappedFile: '__43',
+ byteStats: {
+ swapped: 19
+ }
+ },
+ {
+ mappedFile: '__42',
+ startAddress: 2048,
+ sizeInBytes: 1000,
+ byteStats: {
+ privateDirtyResident: 500
+ }
+ }
+ ]
+ }
+ ]
+ });
+
+ // Add more VM regions *after* the tree has been fully built.
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: 'W2', // Root/Words/Other.
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }));
+ checkTree(rootNode, {
+ title: 'Root',
+ hasRegions: true,
+ sizeInBytes: 1000 + 16,
+ byteStats: {
+ proportionalResident: 32 + 33,
+ privateDirtyResident: 500 + 77,
+ swapped: 19 + 64,
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'Words',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: false,
+ children: [
+ {
+ title: 'A-D',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'E-H',
+ hasRegions: false,
+ isLeafNode: true,
+ regions: []
+ },
+ {
+ title: 'Other',
+ hasRegions: true,
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: 'W2',
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ title: 'Digits',
+ hasRegions: true,
+ sizeInBytes: 1000,
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 500 + 77,
+ swapped: 19
+ },
+ isLeafNode: true,
+ regions: [
+ {
+ mappedFile: '__42',
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ },
+ {
+ mappedFile: '__43',
+ byteStats: {
+ swapped: 19
+ }
+ },
+ {
+ mappedFile: '__42',
+ startAddress: 2048,
+ sizeInBytes: 1000,
+ byteStats: {
+ privateDirtyResident: 500
+ }
+ }
+ ]
+ }
+ ]
+ });
+ });
+
+ test('vmRegionClassificationNode_someRegion', function() {
+ const rootNode = new VMRegionClassificationNode(TEST_RULES);
+
+ // There are no regions in the tree, so the method should always return
+ // false.
+ assert.isFalse(rootNode.someRegion(function(region) {
+ throw new Error('There are no regions in the tree!!!');
+ }));
+
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: 'W2', // Root/Words/Other.
+ sizeInBytes: 16,
+ byteStats: {
+ proportionalResident: 32,
+ swapped: 64
+ }
+ }));
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: '__42', // Root/Digits.
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ }));
+ rootNode.addRegion(VMRegion.fromDict({
+ mappedFile: '__43', // Root/Digits.
+ byteStats: {
+ proportionalResident: 33,
+ privateDirtyResident: 77
+ }
+ }));
+
+ function checkSomeRegion() {
+ // Find the order in which the regions are traversed and checked that all
+ // regions were visited.
+ const visitedRegionMappedFiles = [];
+ assert.isFalse(rootNode.someRegion(function(region) {
+ visitedRegionMappedFiles.push(region.mappedFile);
+ return false;
+ }));
+ assert.lengthOf(visitedRegionMappedFiles, 3);
+ assert.sameMembers(visitedRegionMappedFiles, ['W2', '__42', '__43']);
+
+ // Assuming the traversal order is deterministic, we check that once the
+ // callback returns true, no further regions are visited.
+ visitedRegionMappedFiles.forEach(
+ function(mappedFileToMatch, index) {
+ const visitedRegionMappedFiles2 = [];
+ assert.isTrue(rootNode.someRegion(function(region) {
+ this.files.push(region.mappedFile);
+ return region.mappedFile === mappedFileToMatch;
+ }, { files: visitedRegionMappedFiles2 } /* opt_this */));
+ assert.deepEqual(visitedRegionMappedFiles2,
+ visitedRegionMappedFiles.slice(0, index + 1));
+ });
+ }
+
+ // Before lazy construction (single node with a flat list of regions).
+ checkSomeRegion();
+ assert.isUndefined(rootNode.children_);
+
+ // After lazy construction (tree of nodes with lists of regions).
+ assert.isDefined(rootNode.children); // Force building the tree.
+ assert.isDefined(rootNode.children_);
+ checkSomeRegion();
+ });
+
+ test('vmRegionClassificationNode_libraryMemory', function() {
+ const regions = [
+ VMRegion.fromDict({
+ sizeInBytes: 20,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ mappedFile: '[stack:1234]',
+ byteStats: {
+ privateDirtyResident: 100,
+ proportionalResident: 124
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 500000,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ mappedFile: '/data/app/com.google.chrome/base.apk',
+ byteStats: {
+ privateCleanResident: 100000,
+ proportionalResident: 124000
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 1000,
+ protectionFlags: (VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE),
+ mappedFile: '/data/app/com.google.chrome/base.apk',
+ byteStats: {
+ privateCleanResident: 100,
+ proportionalResident: 124
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 300,
+ protectionFlags: (VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE),
+ mappedFile: '/data/app/com.google.chrome/base.apk',
+ byteStats: {
+ proportionalResident: 58,
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 400,
+ protectionFlags: (VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE),
+ mappedFile: '/data/app/com.google.chrome/base.apk',
+ byteStats: {
+ privateCleanResident: 76,
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 50,
+ protectionFlags: (VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE),
+ mappedFile: '/data/app/com.google.chrome/base.apk',
+ byteStats: {
+ privateCleanResident: 8,
+ proportionalResident: 24,
+ sharedCleanResident: 10,
+ }
+ })];
+ const node = VMRegionClassificationNode.fromRegions(regions);
+ assert.strictEqual(node.sizeInBytes, 20 + 500000 + 1000 + 300 + 400 + 50);
+ assert.strictEqual(node.nativeLibrarySizeInBytes,
+ 1000 + 300 + 400 + 50);
+
+ assert.deepEqual(node.byteStats, {
+ proportionalResident: 124 + 124000 + 124 + 58 + 24,
+ privateDirtyResident: 100,
+ privateCleanResident: 100000 + 100 + 76 + 8,
+ sharedCleanResident: 10,
+ nativeLibraryPrivateCleanResident: 100 + 76 + 8,
+ nativeLibrarySharedCleanResident: 10,
+ nativeLibraryProportionalResident: 124 + 58 + 24,
+ });
+ });
+
+ test('vmRegionClassificationNode_javaBaseMemory', function() {
+ const regions = [
+ VMRegion.fromDict({
+ sizeInBytes: 20,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ mappedFile: '[stack:1234]',
+ byteStats: {
+ privateDirtyResident: 100,
+ proportionalResident: 124
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 500000,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ mappedFile: '/data/app/com.google.chrome/oat/arm/base.vdex',
+ byteStats: {
+ privateCleanResident: 100000,
+ proportionalResident: 124000
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 1000,
+ protectionFlags: (VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE),
+ mappedFile: '/data/app/com.google.chrome/some/other.odex',
+ byteStats: {
+ privateCleanResident: 100,
+ proportionalResident: 124
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 300,
+ protectionFlags: (VMRegion.PROTECTION_FLAG_READ),
+ mappedFile: '/data/app/com.google.chrome/oat/arm/base.odex',
+ byteStats: {
+ proportionalResident: 58,
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 400,
+ protectionFlags: (VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE),
+ mappedFile: '/data/app/com.google.chrome/base.vdex',
+ byteStats: {
+ privateCleanResident: 76,
+ privateDirtyResident: 17,
+ }
+ }),
+ VMRegion.fromDict({
+ sizeInBytes: 50,
+ protectionFlags: (VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE),
+ mappedFile: '/data/app/com.google.chrome/another/path/base.odex',
+ byteStats: {
+ privateCleanResident: 8,
+ proportionalResident: 24,
+ sharedCleanResident: 10,
+ }
+ })];
+ const node = VMRegionClassificationNode.fromRegions(regions);
+ assert.strictEqual(node.sizeInBytes, 20 + 500000 + 1000 + 300 + 400 + 50);
+
+ assert.deepEqual(node.byteStats, {
+ proportionalResident: 124 + 124000 + 124 + 58 + 24,
+ privateDirtyResident: 100 + 17,
+ privateCleanResident: 100000 + 100 + 76 + 8,
+ sharedCleanResident: 10,
+ javaBasePss: 124000 + 58 + 24,
+ javaBaseCleanResident: 100000 + 76 + 8 + 10,
+ });
+ });
+
+ test('classificationRules', function() {
+ checkClassificationRules('/dev/ashmem/dalvik-main space (deleted)',
+ ['Android', 'Java runtime', 'Spaces', 'Normal']);
+ checkClassificationRules('/dev/ashmem/dalvik-non moving space',
+ ['Android', 'Java runtime', 'Spaces', 'Non-moving']);
+ checkClassificationRules('/dev/ashmem/dalvik-zygote space (deleted)',
+ ['Android', 'Java runtime', 'Spaces', 'Zygote']);
+ checkClassificationRules('/dev/ashmem/dalvik-allocation stack (deleted)',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules(
+ '/dev/ashmem/dalvik-allocspace main rosalloc space 1 live-bitmap 2',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules(
+ '/dev/ashmem/dalvik-allocspace non moving space live-bitmap 4',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules('/dev/ashmem/dalvik-allocspace zygote / ' +
+ 'non moving space live-bitmap 0 (deleted)',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules('/dev/ashmem/dalvik-card table (deleted)',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules('/dev/ashmem/dalvik-large live objects (deleted)',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules('/dev/ashmem/dalvik-live stack (deleted)',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules(
+ '/dev/ashmem/dalvik-mark sweep sweep array free buffer (deleted)',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules('/dev/ashmem/dalvik-rosalloc page map (deleted)',
+ ['Android', 'Java runtime', 'Accounting']);
+ checkClassificationRules('/dev/ashmem/dalvik-indirect ref table (deleted)',
+ ['Android', 'Java runtime', 'Indirect Reference Table']);
+ checkClassificationRules('/dev/ashmem/dalvik-LinearAlloc (deleted)',
+ ['Android', 'Java runtime', 'Linear Alloc']);
+ checkClassificationRules('/dev/ashmem/dalvik-jit-code-cache (deleted)',
+ ['Android', 'Java runtime', 'Cache']);
+ checkClassificationRules('/dev/ashmem/CursorWindow (deleted)',
+ ['Android', 'Cursor']);
+ checkClassificationRules('/dev/ashmem (deleted)', ['Android', 'Ashmem']);
+ checkClassificationRules('/dev/ashmem/GFXStats-10082',
+ ['Android', 'Ashmem']);
+
+ checkClassificationRules('[stack:23164]', ['Stack']);
+ checkClassificationRules('[stack]', ['Stack']);
+
+ checkClassificationRules('[discounted tracing overhead]', ['Native heap']);
+ checkClassificationRules('', ['Native heap']);
+ checkClassificationRules('[heap]', ['Native heap']);
+ checkClassificationRules('[anon:libc_malloc]', ['Native heap']);
+ checkClassificationRules('[anon:thread signal stack]', ['Native heap']);
+ checkClassificationRules('/dev/ashmem/libc malloc (deleted)',
+ ['Native heap']);
+
+ checkClassificationRules('/usr/lib/nvidia-340/libGL.so.331.79',
+ ['Files', 'so']);
+ checkClassificationRules('/usr/lib/x86_64-linux-gnu/libibus-1.0.so.5.0.505',
+ ['Files', 'so']);
+ checkClassificationRules('/data/data/com.google.android.apps.chrome/' +
+ 'app_chrome/RELRO:libchrome.so (deleted)', ['Files', 'so']);
+ checkClassificationRules(
+ '/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman.ttf',
+ ['Files', 'ttf']);
+ checkClassificationRules(
+ '/data/app/com.google.android.apps.chrome-2/base.apk',
+ ['Files', 'apk']);
+ checkClassificationRules(
+ '/data/app/com.google.android.apps.chrome-2/lib/arm/libchrome.so',
+ ['Files', 'so']);
+ checkClassificationRules(
+ '/data/app/com.google.android.apps.chrome-2/oat/arm/base.odex',
+ ['Files', 'dex']);
+ checkClassificationRules(
+ '/data/dalvik-cache/arm/system@framework@boot.art', ['Files', 'art']);
+ checkClassificationRules(
+ '/data/dalvik-cache/arm/system@framework@boot.oat', ['Files', 'oat']);
+
+ checkClassificationRules('/dev/nvidia0', ['Devices', 'GPU']);
+ checkClassificationRules('/dev/kgsl-3d0', ['Devices', 'GPU']);
+ checkClassificationRules('anon_inode:dmabuf', ['Devices', 'DMA']);
+ checkClassificationRules('/dev/binder', ['Devices', 'Other']);
+
+ checkClassificationRules('/src/out/Release/chrome', ['Other']);
+ checkClassificationRules('/tmp/gluY4SVp (deleted)', ['Other']);
+ checkClassificationRules('/src/out/Release/resources.pak', ['Other']);
+ checkClassificationRules('[vdso]', ['Other']);
+ checkClassificationRules('[vsyscall]', ['Other']);
+ checkClassificationRules('[vectors]', ['Other']);
+ checkClassificationRules('[vvar]', ['Other']);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/model/x_marker_annotation.html b/chromium/third_party/catapult/tracing/tracing/model/x_marker_annotation.html
new file mode 100644
index 00000000000..7eb79b1d78e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/model/x_marker_annotation.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/annotation.html">
+<link rel="import" href="/tracing/ui/annotations/x_marker_annotation_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.model', function() {
+ function XMarkerAnnotation(timestamp) {
+ tr.model.Annotation.apply(this, arguments);
+
+ this.timestamp = timestamp;
+ this.strokeStyle = 'rgba(0, 0, 255, 0.5)';
+ }
+
+ XMarkerAnnotation.fromDict = function(dict) {
+ return new XMarkerAnnotation(dict.args.timestamp);
+ };
+
+ XMarkerAnnotation.prototype = {
+ __proto__: tr.model.Annotation.prototype,
+
+ toDict() {
+ return {
+ typeName: 'xmarker',
+ args: {
+ timestamp: this.timestamp
+ }
+ };
+ },
+
+ createView_(viewport) {
+ return new tr.ui.annotations.XMarkerAnnotationView(viewport, this);
+ }
+ };
+
+ tr.model.Annotation.register(
+ XMarkerAnnotation, {typeName: 'xmarker'});
+
+ return {
+ XMarkerAnnotation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/__init__.py b/chromium/third_party/catapult/tracing/tracing/mre/__init__.py
new file mode 100644
index 00000000000..50b23dff631
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py b/chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py
new file mode 100644
index 00000000000..877ddaa0645
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/cloud_storage.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import subprocess
+import sys
+
+_GSUTIL_PATH = os.path.abspath(
+ os.path.join(
+ os.path.dirname(__file__),
+ '..', '..', 'third_party', 'gsutil', 'gsutil'))
+
+
+class CloudStorageError(Exception):
+
+ @staticmethod
+ def _GetConfigInstructions():
+ command = _GSUTIL_PATH
+ return ('To configure your credentials:\n'
+ ' 1. Run "%s config" and follow its instructions.\n'
+ ' 2. If you have a @google.com account, use that account.\n'
+ ' 3. For the project-id, just enter 0.' % command)
+
+
+class PermissionError(CloudStorageError):
+
+ def __init__(self):
+ super(PermissionError, self).__init__(
+ 'Attempted to access a file from Cloud Storage but you don\'t '
+ 'have permission. ' + self._GetConfigInstructions())
+
+
+class CredentialsError(CloudStorageError):
+
+ def __init__(self):
+ super(CredentialsError, self).__init__(
+ 'Attempted to access a file from Cloud Storage but you have no '
+ 'configured credentials. ' + self._GetConfigInstructions())
+
+
+class NotFoundError(CloudStorageError):
+ pass
+
+
+class ServerError(CloudStorageError):
+ pass
+
+
+def Copy(src, dst):
+ # TODO(simonhatch): switch to use py_utils.cloud_storage.
+ args = [sys.executable, _GSUTIL_PATH, 'cp', src, dst]
+ gsutil = subprocess.Popen(args, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ _, stderr = gsutil.communicate()
+
+ if gsutil.returncode:
+ if stderr.startswith((
+ 'You are attempting to access protected data with no configured',
+ 'Failure: No handler was ready to authenticate.')):
+ raise CredentialsError()
+ if ('status=403' in stderr or 'status 403' in stderr or
+ '403 Forbidden' in stderr):
+ raise PermissionError()
+ if (stderr.startswith('InvalidUriError') or 'No such object' in stderr or
+ 'No URLs matched' in stderr or
+ 'One or more URLs matched no' in stderr):
+ raise NotFoundError(stderr)
+ if '500 Internal Server Error' in stderr:
+ raise ServerError(stderr)
+ raise CloudStorageError(stderr)
+ return gsutil.returncode
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/corpus_driver.py b/chromium/third_party/catapult/tracing/tracing/mre/corpus_driver.py
new file mode 100644
index 00000000000..28bb8a208b7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/corpus_driver.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class CorpusDriver(object):
+
+ def GetTraceHandles(self):
+ raise NotImplementedError()
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/corpus_driver_cmdline.py b/chromium/third_party/catapult/tracing/tracing/mre/corpus_driver_cmdline.py
new file mode 100644
index 00000000000..06d70ba8f68
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/corpus_driver_cmdline.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from tracing.mre import local_directory_corpus_driver
+
+
+_CORPUS_DRIVERS = {
+ 'local-directory': {
+ 'description': 'Use traces from a local directory.',
+ 'class': local_directory_corpus_driver.LocalDirectoryCorpusDriver
+ }
+}
+_CORPUS_DRIVER_DEFAULT = 'local-directory'
+
+
+def GetCorpusDriver(parser, args):
+ # With parse_known_args, optional arguments aren't guaranteed to be there so
+ # we need to check if it's there, and use the default otherwise.
+ corpus = _CORPUS_DRIVER_DEFAULT
+
+ cls = _CORPUS_DRIVERS[corpus]['class']
+ init_args = cls.CheckAndCreateInitArguments(parser, args)
+ return cls(**init_args)
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/failure.html b/chromium/third_party/catapult/tracing/tracing/mre/failure.html
new file mode 100644
index 00000000000..7b12cf775da
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/failure.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.mre', function() {
+ function Failure(job, functionHandleString, traceCanonicalUrl,
+ failureTypeName, description, stack) {
+ this.job = job;
+ this.functionHandleString = functionHandleString;
+ this.traceCanonicalUrl = traceCanonicalUrl;
+ this.failureTypeName = failureTypeName;
+ this.description = description;
+ this.stack = stack;
+ }
+
+ Failure.prototype = {
+ asDict() {
+ // TODO(eakuefner): Serialize job once reduction is implemented.
+ return {
+ function_handle_string: this.functionHandleString,
+ trace_canonical_url: this.traceCanonicalUrl,
+ type: this.failureTypeName,
+ description: this.description,
+ stack: this.stack
+ };
+ }
+ };
+
+ Failure.fromDict = function(failureDict) {
+ return new Failure(undefined, failureDict.function_handle_string,
+ failureDict.trace_canonical_url, failureDict.type,
+ failureDict.description, failureDict.stack);
+ };
+
+ return {
+ Failure,
+ };
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/failure.py b/chromium/third_party/catapult/tracing/tracing/mre/failure.py
new file mode 100644
index 00000000000..8c0713e1d8b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/failure.py
@@ -0,0 +1,53 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from tracing.mre import job as job_module
+
+
+class Failure(object):
+
+ def __init__(self, job, function_handle_string, trace_canonical_url,
+ failure_type_name, description, stack):
+ assert isinstance(job, job_module.Job)
+
+ self.job = job
+ self.function_handle_string = function_handle_string
+ self.trace_canonical_url = trace_canonical_url
+ self.failure_type_name = failure_type_name
+ self.description = description
+ self.stack = stack
+
+ def __str__(self):
+ return (
+ 'Failure for job %s with function handle %s and trace handle %s:\n'
+ 'of type %s wtih description %s. Stack:\n\n%s' % (
+ self.job.guid, self.function_handle_string,
+ self.trace_canonical_url, self.failure_type_name,
+ self.description, self.stack))
+
+ def AsDict(self):
+ return {
+ 'job_guid': str(self.job.guid),
+ 'function_handle_string': self.function_handle_string,
+ 'trace_canonical_url': self.trace_canonical_url,
+ 'type': self.failure_type_name,
+ 'description': self.description,
+ 'stack': self.stack
+ }
+
+ @staticmethod
+ def FromDict(failure_dict, job, failure_names_to_constructors=None):
+ if failure_names_to_constructors is None:
+ failure_names_to_constructors = {}
+ failure_type_name = failure_dict['type']
+ if failure_type_name in failure_names_to_constructors:
+ cls = failure_names_to_constructors[failure_type_name]
+ else:
+ cls = Failure
+
+ return cls(job,
+ failure_dict['function_handle_string'],
+ failure_dict['trace_canonical_url'],
+ failure_type_name, failure_dict['description'],
+ failure_dict['stack'])
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/failure_test.html b/chromium/third_party/catapult/tracing/tracing/mre/failure_test.html
new file mode 100644
index 00000000000..c20b67a45f5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/failure_test.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/mre/failure.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('failureAsDictTest', function() {
+ const failure = new tr.mre.Failure(undefined, 'foo.html:Foo',
+ 'file://foo.html', 'err', 'desc', 'stack');
+
+ assert.deepEqual(failure.asDict(), {
+ function_handle_string: 'foo.html:Foo',
+ trace_canonical_url: 'file://foo.html',
+ type: 'err',
+ description: 'desc',
+ stack: 'stack'
+ });
+ });
+
+ test('failureFromDictTest', function() {
+ const failureDict = {
+ function_handle_string: 'foo.html:Foo',
+ trace_canonical_url: 'file://foo.html',
+ type: 'err',
+ description: 'desc',
+ stack: 'stack'
+ };
+
+ const failure = tr.mre.Failure.fromDict(failureDict);
+
+ assert.strictEqual(failure.functionHandleString, 'foo.html:Foo');
+ assert.strictEqual(failure.traceCanonicalUrl, 'file://foo.html');
+ assert.strictEqual(failure.failureTypeName, 'err');
+ assert.strictEqual(failure.description, 'desc');
+ assert.strictEqual(failure.stack, 'stack');
+ });
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py
new file mode 100644
index 00000000000..1140b17aa66
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/failure_unittest.py
@@ -0,0 +1,56 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.mre import function_handle
+from tracing.mre import failure as failure_module
+from tracing.mre import job as job_module
+
+
+def _SingleFileFunctionHandle(filename, function_name, guid):
+ return function_handle.FunctionHandle(
+ modules_to_load=[function_handle.ModuleToLoad(filename=filename)],
+ function_name=function_name, guid=guid)
+
+
+class FailureTests(unittest.TestCase):
+
+ def testAsDict(self):
+ map_function_handle = _SingleFileFunctionHandle('foo.html', 'Foo', '2')
+ job = job_module.Job(map_function_handle, '1')
+ failure = failure_module.Failure(job, 'foo.html:Foo',
+ 'file://foo.html',
+ 'err', 'desc', 'stack')
+
+ self.assertEquals(failure.AsDict(), {
+ 'job_guid': '1',
+ 'function_handle_string': 'foo.html:Foo',
+ 'trace_canonical_url': 'file://foo.html',
+ 'type': 'err',
+ 'description': 'desc',
+ 'stack': 'stack'
+ })
+
+ def testFromDict(self):
+ map_function_handle = _SingleFileFunctionHandle('foo.html', 'Foo', '2')
+ job = job_module.Job(map_function_handle, '1')
+
+ failure_dict = {
+ 'job_guid': '1',
+ 'function_handle_string': 'foo.html:Foo',
+ 'trace_canonical_url': 'file://foo.html',
+ 'type': 'err',
+ 'description': 'desc',
+ 'stack': 'stack'
+ }
+
+ failure = failure_module.Failure.FromDict(failure_dict, job)
+
+ self.assertEquals(failure.job.guid, '1')
+ self.assertEquals(failure.function_handle_string, 'foo.html:Foo')
+ self.assertEquals(failure.trace_canonical_url, 'file://foo.html')
+ self.assertEquals(failure.failure_type_name, 'err')
+ self.assertEquals(failure.description, 'desc')
+ self.assertEquals(failure.stack, 'stack')
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/file_handle.html b/chromium/third_party/catapult/tracing/tracing/mre/file_handle.html
new file mode 100644
index 00000000000..7d3ad6f6d5c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/file_handle.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/extras/full_config.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/model/model.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.mre', function() {
+ function FileHandle(canonicalUrl) {
+ this.canonicalUrl_ = canonicalUrl;
+ }
+
+ FileHandle.prototype = {
+ get canonicalUrl() { return this.canonicalUrl_; },
+
+ asDict() {
+ const d = {
+ canonical_url: this.canonicalUrl_
+ };
+
+ this.asDictInto_(d);
+ if (d.type === undefined) {
+ throw new Error('asDictInto_ must set type field');
+ }
+ },
+
+ load() {
+ throw new Error('Not implemented');
+ }
+ };
+
+ FileHandle.fromDict = function(handleDict) {
+ if (handleDict.type === 'url') {
+ return URLFileHandle.fromDict(handleDict);
+ }
+ if (handleDict.type === 'in-memory') {
+ return InMemoryFileHandle.fromDict(handleDict);
+ }
+
+ throw new Error('Not implemented: fromDict for ' + handleDict.type);
+ };
+
+
+ function URLFileHandle(canonicalUrl, urlToLoad) {
+ // TODO(eakuefner): assert startswith file://
+ FileHandle.call(this, canonicalUrl);
+ this.urlToLoad = urlToLoad;
+ this.loadAsTraceStream_ = false;
+ }
+
+ URLFileHandle.prototype = {
+ __proto__: FileHandle.prototype,
+
+ asDictInto_(handleDict) {
+ handleDict.urlToLoad = this.urlToLoad;
+ handleDict.type = 'url';
+ },
+
+ load() {
+ try {
+ return tr.b.getSync(this.urlToLoad, this.loadAsTraceStream_);
+ } catch (ex) {
+ const err = new Error('Could not open ' + this.urlToLoad);
+ err.name = 'FileLoadingError';
+ throw err;
+ }
+ }
+ };
+
+
+ URLFileHandle.fromDict = function(handleDict) {
+ return new URLFileHandle(handleDict.canonical_url, handleDict.url_to_load);
+ };
+
+ function InMemoryFileHandle(fileData, canonicalUrl) {
+ FileHandle.call(this, canonicalUrl);
+ this.fileData = fileData;
+ }
+
+ InMemoryFileHandle.prototype = {
+ __proto__: FileHandle.prototype,
+
+ asDictInto_(handleDict) {
+ handleDict.data = this.fileData;
+ handleDict.type = 'in-memory';
+ },
+
+ load() {
+ return this.fileData;
+ }
+ };
+
+ InMemoryFileHandle.fromDict = function(handleDict) {
+ return new InMemoryFileHandle(
+ handleDict.data, handleDict.canonical_url);
+ };
+
+ return {
+ FileHandle,
+ URLFileHandle,
+ InMemoryFileHandle,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/file_handle.py b/chromium/third_party/catapult/tracing/tracing/mre/file_handle.py
new file mode 100644
index 00000000000..e89b2f348f0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/file_handle.py
@@ -0,0 +1,100 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import contextlib
+import os
+import tempfile
+
+from tracing.mre import cloud_storage
+
+
+class FilePreparationError(Exception):
+ """Raised if something goes wrong while preparing a file for processing."""
+
+
+class FileHandle(object):
+ def __init__(self, canonical_url):
+ self._canonical_url = canonical_url
+
+ @property
+ def canonical_url(self):
+ return self._canonical_url
+
+ @contextlib.contextmanager
+ def PrepareFileForProcessing(self):
+ """Ensure that the URL to the file will be acessible during processing.
+
+ This function must do any pre-work to ensure that mappers will
+ be able to read from the URL contained in the file handle.
+
+ Raises:
+ FilePreparationError: If something went wrong while preparing the file.
+ """
+ yield self._WillProcess()
+ self._DidProcess()
+
+ def _WillProcess(self):
+ raise NotImplementedError()
+
+ def _DidProcess(self):
+ raise NotImplementedError()
+
+
+class URLFileHandle(FileHandle):
+ def __init__(self, canonical_url, url_to_load):
+ super(URLFileHandle, self).__init__(canonical_url)
+
+ self._url_to_load = url_to_load
+
+ def AsDict(self):
+ return {
+ 'type': 'url',
+ 'canonical_url': self._canonical_url,
+ 'url_to_load': self._url_to_load
+ }
+
+ def _WillProcess(self):
+ return self
+
+ def _DidProcess(self):
+ pass
+
+
+class GCSFileHandle(FileHandle):
+ def __init__(self, canonical_url, cache_directory):
+ super(GCSFileHandle, self).__init__(canonical_url)
+ file_name = canonical_url.split('/')[-1]
+ self.cache_file = os.path.join(
+ cache_directory, file_name + '.gz')
+
+ def _WillProcess(self):
+ if not os.path.exists(self.cache_file):
+ try:
+ cloud_storage.Copy(self.canonical_url, self.cache_file)
+ except cloud_storage.CloudStorageError:
+ return None
+ return URLFileHandle(self.canonical_url, 'file://' + self.cache_file)
+
+ def _DidProcess(self):
+ pass
+
+
+class InMemoryFileHandle(FileHandle):
+ def __init__(self, canonical_url, data):
+ super(InMemoryFileHandle, self).__init__(canonical_url)
+
+ self.data = data
+ self._temp_file_path = None
+
+ def _WillProcess(self):
+ temp_file = tempfile.NamedTemporaryFile(delete=False)
+ temp_file.write(self.data)
+ temp_file.close()
+ self._temp_file_path = temp_file.name
+
+ return URLFileHandle(self.canonical_url, 'file://' + self._temp_file_path)
+
+ def _DidProcess(self):
+ os.remove(self._temp_file_path)
+ self._temp_file_path = None
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/function_handle.html b/chromium/third_party/catapult/tracing/tracing/mre/function_handle.html
new file mode 100644
index 00000000000..8a2a5fc1dad
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/function_handle.html
@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.mre', function() {
+ const FunctionRegistry = {
+ allFunctions_: [],
+ allFunctionsByName_: {},
+ get allFunctions() { return this.allFunctions_; },
+ get allFunctionsByName() { return this.allFunctionsByName_; }
+ };
+
+ FunctionRegistry.getFunction = function(name) {
+ return this.allFunctionsByName_[name];
+ };
+
+ FunctionRegistry.register = function(func) {
+ if (func.name === '') {
+ throw new Error('Registered functions must not be anonymous');
+ }
+ if (this.allFunctionsByName[func.name] !== undefined) {
+ throw new Error('Function named ' + func.name + 'is already registered.');
+ }
+ this.allFunctionsByName[func.name] = func;
+ this.allFunctions.push(func);
+ };
+
+ function ModuleToLoad(href, filename) {
+ if ((href !== undefined) ? (filename !== undefined) :
+ (filename === undefined)) {
+ throw new Error('ModuleToLoad must specify exactly one of href or ' +
+ 'filename');
+ }
+ this.href = href;
+ this.filename = filename;
+ }
+
+ ModuleToLoad.prototype = {
+ asDict() {
+ if (this.href !== undefined) {
+ return {'href': this.href};
+ }
+ return {'filename': this.filename};
+ },
+
+ toString() {
+ if (this.href !== undefined) {
+ return 'ModuleToLoad(href="' + this.href + '")';
+ }
+ return 'ModuleToLoad(filename="' + this.filename + '")';
+ }
+ };
+
+ ModuleToLoad.fromDict = function(moduleDict) {
+ return new ModuleToLoad(moduleDict.href, moduleDict.filename);
+ };
+
+ function FunctionHandle(modulesToLoad, functionName, opt_options) {
+ if (!(modulesToLoad instanceof Array)) {
+ throw new Error('modulesToLoad in FunctionHandle must be an array');
+ }
+ if (typeof(functionName) !== 'string') {
+ throw new Error('functionName in FunctionHandle must be a string');
+ }
+ this.modulesToLoad = modulesToLoad;
+ this.functionName = functionName;
+ this.options_ = opt_options;
+ }
+
+ FunctionHandle.prototype = {
+ get options() {
+ return this.options_;
+ },
+
+ asDict() {
+ return {
+ 'modules_to_load': this.modulesToLoad.map(
+ function(m) {return m.asDict();}),
+ 'function_name': this.functionName,
+ 'options': this.options_
+ };
+ },
+
+ asUserFriendlyString() {
+ const parts = this.modulesToLoad.map(mtl => mtl.filename);
+ parts.push(this.functionName);
+ parts.push(JSON.stringify(this.options_));
+ return parts.join(',');
+ },
+
+ hasHrefs() {
+ for (const module in this.modulesToLoad) {
+ if (this.modulesToLoad[module].href !== undefined) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ load() {
+ if (this.hasHrefs()) {
+ const err = new Error(
+ 'FunctionHandle named ' + this.functionName +
+ ' specifies hrefs, which cannot be loaded.');
+ err.name = 'FunctionLoadingError';
+ throw err;
+ }
+
+ for (const module in this.modulesToLoad) {
+ const filename = this.modulesToLoad[module].filename;
+ try {
+ HTMLImportsLoader.loadHTMLFile(filename);
+ } catch (err) {
+ err.name = 'FunctionLoadingError';
+ throw err;
+ }
+ }
+
+ const func = FunctionRegistry.getFunction(this.functionName);
+ if (func === undefined) {
+ const err = new Error(
+ 'No registered function named ' + this.functionName);
+ err.name = 'FunctionNotDefinedError';
+ throw err;
+ }
+
+ return func;
+ },
+
+ toString() {
+ const modulesToLoadStr = this.modulesToLoad.map(function(module) {
+ return module.toString();
+ });
+ return 'FunctionHandle(modulesToLoad=[' + modulesToLoadStr + '], ' +
+ 'functionName="' + this.functionName + '", options="' +
+ JSON.stringify(this.options_) + '")';
+ }
+ };
+
+ FunctionHandle.loadFromFilename_ = function(filename) {
+ try {
+ const numFunctionsBefore = FunctionRegistry.allFunctions.length;
+ HTMLImportsLoader.loadHTMLFile(filename);
+ } catch (err) {
+ err.name = 'FunctionLoadingError';
+ throw err;
+ }
+
+ // Verify a new function was registered.
+ const numFunctionsNow = FunctionRegistry.allFunctions.length;
+ if (numFunctionsNow !== (numFunctionsBefore + 1)) {
+ const err = new Error(
+ filename + ' didn\'t call FunctionRegistry.register');
+ err.name = 'FunctionNotDefinedError';
+ throw err;
+ }
+
+ return FunctionRegistry.allFunctions[numFunctionsNow - 1];
+ };
+
+ FunctionHandle.fromDict = function(handleDict) {
+ const options = handleDict.options;
+ let modulesToLoad;
+ if (handleDict.modules_to_load !== undefined) {
+ modulesToLoad = handleDict.modules_to_load.map(function(module) {
+ return ModuleToLoad.fromDict(module);
+ });
+ }
+ return new FunctionHandle(modulesToLoad, handleDict.function_name, options);
+ };
+
+ return {
+ FunctionHandle,
+ ModuleToLoad,
+ FunctionRegistry,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/function_handle.py b/chromium/third_party/catapult/tracing/tracing/mre/function_handle.py
new file mode 100644
index 00000000000..1efa5d647a9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/function_handle.py
@@ -0,0 +1,139 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import uuid
+
+
+class AbspathInvalidError(Exception):
+ """Raised if an abspath cannot be sanitized based on an app's source paths."""
+
+
+class UserFriendlyStringInvalidError(Exception):
+ """Raised if a user friendly string cannot be parsed."""
+
+
+class ModuleToLoad(object):
+
+ def __init__(self, href=None, filename=None):
+ if bool(href) == bool(filename):
+ raise Exception('ModuleToLoad must specify exactly one of href and '
+ 'filename.')
+ self.href = href
+ self.filename = filename
+
+ def __repr__(self):
+ if self.href:
+ return 'ModuleToLoad(href="%s")' % self.href
+ return 'ModuleToLoad(filename="%s")' % self.filename
+
+ def AsDict(self):
+ if self.href:
+ return {'href': self.href}
+ return {'filename': self.filename}
+
+ @staticmethod
+ def FromDict(module_dict):
+ return ModuleToLoad(module_dict.get('href'), module_dict.get('filename'))
+
+
+class FunctionHandle(object):
+
+ def __init__(self, modules_to_load=None, function_name=None,
+ options=None, guid=uuid.uuid4()):
+ self.modules_to_load = modules_to_load
+ self.function_name = function_name
+ self.options = options
+ self._guid = guid
+
+ def __repr__(self):
+ return 'FunctionHandle(modules_to_load=[%s], function_name="%s")' % (
+ ', '.join([str(module) for module in self.modules_to_load]),
+ self.function_name)
+
+ @property
+ def guid(self):
+ return self._guid
+
+ @property
+ def has_hrefs(self):
+ return any(module.href for module in self.modules_to_load)
+
+ def AsDict(self):
+ handle_dict = {
+ 'function_name': self.function_name
+ }
+
+ if self.modules_to_load is not None:
+ handle_dict['modules_to_load'] = [module.AsDict() for module in
+ self.modules_to_load]
+ if self.options is not None:
+ handle_dict['options'] = self.options
+
+ return handle_dict
+
+ def ConvertHrefsToAbsFilenames(self, app):
+ """Converts hrefs to absolute filenames in the context of |app|.
+
+ In an app-serving context, functions must only reside in files which the app
+ is serving, in order to prevent directory traversal attacks. In addition, we
+ rely on paths being absolute when actually executing functions.
+
+ Args:
+ app: A dev server instance requesting abspath conversion.
+
+ Returns:
+ A new FunctionHandle instance with no hrefs.
+
+ Raises:
+ AbspathInvalidError: If there is no source path with which a given abspath
+ shares a common prefix.
+ """
+ new_modules_to_load = []
+ for module in self.modules_to_load:
+ if module.href:
+ abspath = app.GetAbsFilenameForHref(module.href)
+ else:
+ assert os.path.abspath(module.filename) == module.filename
+ abspath = module.filename
+
+ if not abspath:
+ raise AbspathInvalidError('Filename %s invalid', abspath)
+
+ new_modules_to_load.append(ModuleToLoad(filename=abspath))
+
+ return FunctionHandle(modules_to_load=new_modules_to_load,
+ function_name=self.function_name)
+
+ @staticmethod
+ def FromDict(handle_dict):
+ if handle_dict.get('modules_to_load') is not None:
+ modules_to_load = [ModuleToLoad.FromDict(module_dict) for module_dict in
+ handle_dict['modules_to_load']]
+ else:
+ modules_to_load = []
+ options = handle_dict.get('options')
+ return FunctionHandle(modules_to_load=modules_to_load,
+ function_name=handle_dict['function_name'],
+ options=options)
+
+ def AsUserFriendlyString(self, app):
+ parts = [module.filename for module in
+ self.ConvertHrefsToAbsFilenames(app).modules_to_load]
+ parts.append(self.function_name)
+
+ return ':'.join(parts)
+
+ @staticmethod
+ def FromUserFriendlyString(user_str):
+ parts = user_str.split(':')
+ if len(parts) < 2:
+ raise UserFriendlyStringInvalidError(
+ 'Tried to deserialize string with less than two parts: ' + user_str)
+
+ modules_to_load = [ModuleToLoad(filename=name) for name in parts[:-1]]
+
+ return FunctionHandle(modules_to_load=modules_to_load,
+ function_name=parts[-1])
+
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/function_handle_test.html b/chromium/third_party/catapult/tracing/tracing/mre/function_handle_test.html
new file mode 100644
index 00000000000..ab83edae429
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/function_handle_test.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/mre/function_handle.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('moduleToLoadExactlyOneHrefOrFilename', function() {
+ assert.throws(function() {tr.mre.ModuleToLoad('foo', 'foo');});
+ assert.throws(tr.mre.ModuleToLoad);
+ });
+
+ test('moduleToLoadAsDictTest', function() {
+ const mtl0 = new tr.mre.ModuleToLoad('/foo');
+ const mtl1 = new tr.mre.ModuleToLoad(undefined, 'foo.html');
+
+ assert.deepEqual(mtl0.asDict(), {'href': '/foo'});
+ assert.deepEqual(mtl1.asDict(), {'filename': 'foo.html'});
+ });
+
+ test('moduleToLoadFromDictTest', function() {
+ const moduleDict0 = {
+ href: '/foo'
+ };
+ const moduleDict1 = {
+ filename: 'foo.html'
+ };
+
+ const mtl0 = tr.mre.ModuleToLoad.fromDict(moduleDict0);
+ const mtl1 = tr.mre.ModuleToLoad.fromDict(moduleDict1);
+
+ assert.strictEqual(mtl0.href, '/foo');
+ assert.isUndefined(mtl0.filename);
+ assert.strictEqual(mtl1.filename, 'foo.html');
+ assert.isUndefined(mtl1.href);
+ });
+
+ test('moduleToLoadToStringTest', function() {
+ const mtl0 = new tr.mre.ModuleToLoad('/foo');
+ const mtl1 = new tr.mre.ModuleToLoad(undefined, 'foo.html');
+
+ assert.strictEqual(
+ mtl0.toString(),
+ 'ModuleToLoad(href="/foo")');
+ assert.strictEqual(
+ mtl1.toString(),
+ 'ModuleToLoad(filename="foo.html")');
+ });
+
+ test('modulesToLoadMustBeArrayTest', function() {
+ assert.throws(tr.mre.FunctionHandle);
+ });
+
+ test('functionNameMustBeStringTest', function() {
+ assert.throws(function() {tr.mre.FunctionHandle([], 3);});
+ });
+
+ test('asDictTest', function() {
+ const module = new tr.mre.ModuleToLoad('/foo');
+ const handle = new tr.mre.FunctionHandle([module], 'Bar', {'a': 'b'});
+
+ assert.deepEqual(handle.asDict(), {
+ modules_to_load: [{href: '/foo'}],
+ function_name: 'Bar',
+ options: {'a': 'b'}
+ });
+ });
+
+ test('fromDictTest', function() {
+ const handleDict = {
+ modules_to_load: [{href: '/foo'}],
+ function_name: 'Bar'
+ };
+
+ const handle = tr.mre.FunctionHandle.fromDict(handleDict);
+
+ assert.strictEqual(handle.modulesToLoad.length, 1);
+ assert.strictEqual(handle.modulesToLoad[0].href, '/foo');
+ assert.strictEqual(handle.functionName, 'Bar');
+ });
+
+ test('hasHrefsTest', function() {
+ const module0 = new tr.mre.ModuleToLoad('/foo');
+ const handle0 = new tr.mre.FunctionHandle([module0], 'Bar');
+ const module1 = new tr.mre.ModuleToLoad(undefined, 'foo.html');
+ const handle1 = new tr.mre.FunctionHandle([module1], 'Bar');
+
+ assert.isTrue(handle0.hasHrefs());
+ assert.isFalse(handle1.hasHrefs());
+ });
+
+ test('loadFailsWithHrefs', function() {
+ const module = new tr.mre.ModuleToLoad('/foo');
+ const handle = new tr.mre.FunctionHandle([module], 'railMapFunction');
+
+ assert.throws(handle.load);
+ });
+
+ test('loadFailsUnregistered', function() {
+ const handle = new tr.mre.FunctionHandle([], 'Bar');
+
+ assert.throws(handle.load);
+ });
+
+ test('toStringTest', function() {
+ const module = new tr.mre.ModuleToLoad('/foo');
+ const handle = new tr.mre.FunctionHandle([module], 'Bar', {'a': 'b'});
+
+ assert.strictEqual(
+ handle.toString(),
+ 'FunctionHandle(modulesToLoad=[ModuleToLoad(href="/foo")], ' +
+ 'functionName="Bar", options="{"a":"b"}")');
+ });
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py
new file mode 100644
index 00000000000..d3bf71dfe66
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/function_handle_unittest.py
@@ -0,0 +1,86 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.mre import function_handle
+
+
+class ModuleToLoadTests(unittest.TestCase):
+
+ def testExactlyOneHrefOrFilename(self):
+ with self.assertRaises(Exception):
+ function_handle.ModuleToLoad()
+
+ with self.assertRaises(Exception):
+ function_handle.ModuleToLoad('foo', 'foo')
+
+ def testRepr(self):
+ mtl0 = function_handle.ModuleToLoad(href='/foo')
+ mtl1 = function_handle.ModuleToLoad(filename='foo.html')
+
+ self.assertEquals(str(mtl0), 'ModuleToLoad(href="/foo")')
+ self.assertEquals(str(mtl1), 'ModuleToLoad(filename="foo.html")')
+
+ def testAsDict(self):
+ mtl0 = function_handle.ModuleToLoad(href='/foo')
+ mtl1 = function_handle.ModuleToLoad(filename='foo.html')
+
+ self.assertEquals(mtl0.AsDict(), {
+ 'href': '/foo'
+ })
+
+ self.assertEquals(mtl1.AsDict(), {
+ 'filename': 'foo.html'
+ })
+
+ def testFromDict(self):
+ module_dict0 = {
+ 'href': '/foo'
+ }
+
+ module_dict1 = {
+ 'filename': 'foo.html'
+ }
+
+ mtl0 = function_handle.ModuleToLoad.FromDict(module_dict0)
+ mtl1 = function_handle.ModuleToLoad.FromDict(module_dict1)
+
+ self.assertEquals(mtl0.href, '/foo')
+ self.assertIsNone(mtl0.filename)
+ self.assertEquals(mtl1.filename, 'foo.html')
+ self.assertIsNone(mtl1.href)
+
+
+class FunctionHandleTests(unittest.TestCase):
+
+ def testRepr(self):
+ module = function_handle.ModuleToLoad(href='/foo')
+ handle = function_handle.FunctionHandle([module], 'Bar')
+
+ self.assertEquals(
+ str(handle),
+ 'FunctionHandle(modules_to_load=[ModuleToLoad(href="/foo")], '
+ 'function_name="Bar")')
+
+ def testAsDict(self):
+ module = function_handle.ModuleToLoad(href='/foo')
+ handle = function_handle.FunctionHandle([module], 'Bar')
+
+ self.assertEquals(
+ handle.AsDict(), {
+ 'modules_to_load': [{'href': '/foo'}],
+ 'function_name': 'Bar'
+ })
+
+ def testFromDict(self):
+ handle_dict = {
+ 'modules_to_load': [{'href': '/foo'}],
+ 'function_name': 'Bar'
+ }
+
+ handle = function_handle.FunctionHandle.FromDict(handle_dict)
+ self.assertEquals(len(handle.modules_to_load), 1)
+ self.assertEquals(handle.modules_to_load[0].href, '/foo')
+ self.assertEquals(handle.function_name, 'Bar')
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/gtest_progress_reporter.py b/chromium/third_party/catapult/tracing/tracing/mre/gtest_progress_reporter.py
new file mode 100644
index 00000000000..2557b08e809
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/gtest_progress_reporter.py
@@ -0,0 +1,91 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import time
+import sys
+
+from tracing.mre import progress_reporter
+
+
+class GTestRunReporter(progress_reporter.RunReporter):
+
+ def __init__(self, canonical_url, output_stream, timestamp):
+ super(GTestRunReporter, self).__init__(canonical_url)
+ self._output_stream = output_stream
+ self._timestamp = timestamp
+
+ def _GetMs(self):
+ assert self._timestamp is not None, 'Did not call WillRun.'
+ return (time.time() - self._timestamp) * 1000
+
+ def DidAddFailure(self, failure):
+ super(GTestRunReporter, self).DidAddFailure(failure)
+ print(failure.stack.encode('utf-8'), file=self._output_stream)
+ self._output_stream.flush()
+
+ def DidRun(self, run_failed):
+ super(GTestRunReporter, self).DidRun(run_failed)
+ if run_failed:
+ print('[ FAILED ] %s (%0.f ms)' % (self.canonical_url, self._GetMs()),
+ file=self._output_stream)
+ else:
+ print('[ OK ] %s (%0.f ms)' % (self.canonical_url, self._GetMs()),
+ file=self._output_stream)
+ self._output_stream.flush()
+
+
+class GTestProgressReporter(progress_reporter.ProgressReporter):
+ """A progress reporter that outputs the progress report in gtest style.
+
+ Be careful each print should only handle one string. Otherwise, the output
+ might be interrupted by Chrome logging, and the output interpretation might
+ be incorrect. For example:
+ print("[ OK ]", testname, file=self._output_stream)
+ should be written as
+ print("[ OK ] %s" % testname, file=self._output_stream)
+ """
+
+ def __init__(self, output_stream=sys.stdout):
+ super(GTestProgressReporter, self).__init__()
+ self._output_stream = output_stream
+
+ def WillRun(self, canonical_url):
+ super(GTestProgressReporter, self).WillRun(canonical_url)
+ print('[ RUN ] %s' % canonical_url.encode('utf-8'),
+ file=self._output_stream)
+ self._output_stream.flush()
+ return GTestRunReporter(canonical_url, self._output_stream, time.time())
+
+ def DidFinishAllRuns(self, result_list):
+ super(GTestProgressReporter, self).DidFinishAllRuns(result_list)
+ successful_runs = 0
+ failed_canonical_urls = []
+ failed_runs = 0
+ for run in result_list:
+ if len(run.failures) != 0:
+ failed_runs += 1
+ for f in run.failures:
+ failed_canonical_urls.append(f.trace_canonical_url)
+ else:
+ successful_runs += 1
+
+ unit = 'test' if successful_runs == 1 else 'tests'
+ print('[ PASSED ] %d %s.' % (successful_runs, unit),
+ file=self._output_stream)
+ if len(failed_canonical_urls) > 0:
+ unit = 'test' if len(failed_canonical_urls) == 1 else 'tests'
+ print('[ FAILED ] %d %s, listed below:' % (failed_runs, unit),
+ file=self._output_stream)
+ for failed_canonical_url in failed_canonical_urls:
+ print('[ FAILED ] %s' % failed_canonical_url.encode('utf-8'),
+ file=self._output_stream)
+ print(file=self._output_stream)
+ count = len(failed_canonical_urls)
+ unit = 'TEST' if count == 1 else 'TESTS'
+ print('%d FAILED %s' % (count, unit), file=self._output_stream)
+ print(file=self._output_stream)
+
+ self._output_stream.flush()
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/job.html b/chromium/third_party/catapult/tracing/tracing/mre/job.html
new file mode 100644
index 00000000000..5424ef751f0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/job.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/mre/function_handle.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.mre', function() {
+ function Job(mapFunctionHandle, opt_guid) {
+ this.mapFunctionHandle_ = mapFunctionHandle;
+ if (opt_guid === undefined) {
+ this.guid_ = tr.b.GUID.allocateSimple();
+ } else {
+ this.guid_ = opt_guid;
+ }
+ }
+
+ Job.prototype = {
+ get mapFunctionHandle() { return this.mapFunctionHandle_; },
+ get guid() { return this.guid_; },
+
+ asDict() {
+ return {
+ map_function_handle: this.mapFunctionHandle_.asDict(),
+ guid: this.guid_.toString()
+ };
+ }
+ };
+
+ Job.fromDict = function(jobDict) {
+ let mapFunctionHandle = null;
+ if (jobDict.map_function_handle !== null) {
+ mapFunctionHandle = tr.mre.FunctionHandle.fromDict(
+ jobDict.map_function_handle);
+ }
+
+ return new Job(mapFunctionHandle, jobDict.guid);
+ };
+
+ return {
+ Job,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/job.py b/chromium/third_party/catapult/tracing/tracing/mre/job.py
new file mode 100644
index 00000000000..d8493c3b651
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/job.py
@@ -0,0 +1,39 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import uuid
+
+from tracing.mre import function_handle
+
+
+class Job(object):
+
+ def __init__(self, map_function_handle, guid=None):
+ if guid is None:
+ guid = uuid.uuid4()
+
+ assert map_function_handle is not None
+
+ self._map_function_handle = map_function_handle
+ self._guid = guid
+
+ @property
+ def guid(self):
+ return self._guid
+
+ @property
+ def map_function_handle(self):
+ return self._map_function_handle
+
+ def AsDict(self):
+ values_dict = {
+ 'map_function_handle': self._map_function_handle.AsDict(),
+ 'guid': str(self._guid)
+ }
+ return values_dict
+
+ @staticmethod
+ def FromDict(job_dict):
+ return Job(
+ function_handle.FunctionHandle.FromDict(
+ job_dict['map_function_handle']))
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/job_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/job_unittest.py
new file mode 100644
index 00000000000..625dff2a15e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/job_unittest.py
@@ -0,0 +1,15 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.mre import job
+
+
+class JobTest(unittest.TestCase):
+
+ def testNoDuplicateUUID(self):
+ job0 = job.Job('not none')
+ job1 = job.Job('not none')
+ self.assertNotEqual(job0.guid, job1.guid)
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py b/chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py
new file mode 100644
index 00000000000..aafc8838de3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/json_output_formatter.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+
+from tracing.mre import output_formatter
+
+
+class JSONOutputFormatter(output_formatter.OutputFormatter):
+
+ def __init__(self, output_file):
+ # TODO(nduca): Resolve output_file here vs output_stream in base class.
+ super(JSONOutputFormatter, self).__init__(output_file)
+ self.output_file = output_file
+
+ def Format(self, result_list):
+ d = [result.AsDict() for result in result_list]
+ json.dump(d, self.output_file, indent=2)
+ if hasattr(self.output_file, 'flush'):
+ self.output_file.flush()
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py b/chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py
new file mode 100644
index 00000000000..a235f916baf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/local_directory_corpus_driver.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from tracing.mre import corpus_driver
+from tracing.mre import file_handle
+
+
+def _GetFilesIn(basedir):
+ data_files = []
+ for dirpath, dirnames, filenames in os.walk(basedir, followlinks=True):
+ new_dirnames = [d for d in dirnames if not d.startswith('.')]
+ del dirnames[:]
+ dirnames += new_dirnames
+ for f in filenames:
+ if f.startswith('.'):
+ continue
+ if f == 'README.md':
+ continue
+ full_f = os.path.join(dirpath, f)
+ rel_f = os.path.relpath(full_f, basedir)
+ data_files.append(rel_f)
+
+ data_files.sort()
+ return data_files
+
+
+def _DefaultUrlResover(abspath):
+ return 'file:///%s' % abspath
+
+
+class LocalDirectoryCorpusDriver(corpus_driver.CorpusDriver):
+
+ def __init__(self, trace_directory, url_resolver=_DefaultUrlResover):
+ self.directory = trace_directory
+ self.url_resolver = url_resolver
+
+ @staticmethod
+ def CheckAndCreateInitArguments(parser, args):
+ del args # Unused by LocalDirectoryCorpusDriver.
+ trace_dir = os.getcwd()
+ if not os.path.exists(trace_dir):
+ parser.error('Trace directory does not exist')
+ return None
+ return {'trace_directory': trace_dir}
+
+ @staticmethod
+ def AddArguments(parser):
+ parser.add_argument(
+ '--trace_directory',
+ help='Local directory containing traces to process.')
+
+ def GetTraceHandles(self):
+ trace_handles = []
+
+ files = _GetFilesIn(self.directory)
+ for rel_filename in files:
+ filename = os.path.join(self.directory, rel_filename)
+
+ url = self.url_resolver(filename)
+ if url is None:
+ url = _DefaultUrlResover(filename)
+
+ th = file_handle.URLFileHandle(url, 'file://' + filename)
+ trace_handles.append(th)
+
+ return trace_handles
+
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_runner.py b/chromium/third_party/catapult/tracing/tracing/mre/map_runner.py
new file mode 100644
index 00000000000..5b3deca8ab8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_runner.py
@@ -0,0 +1,105 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import multiprocessing
+import sys
+
+from tracing.mre import map_single_trace
+from tracing.mre import threaded_work_queue
+from tracing.mre import gtest_progress_reporter
+
+AUTO_JOB_COUNT = -1
+
+
+class MapError(Exception):
+
+ def __init__(self, *args):
+ super(MapError, self).__init__(*args)
+ self.canonical_url = None
+
+
+class MapRunner(object):
+ def __init__(self, trace_handles, job,
+ stop_on_error=False, progress_reporter=None,
+ jobs=AUTO_JOB_COUNT,
+ output_formatters=None,
+ extra_import_options=None):
+ self._job = job
+ self._stop_on_error = stop_on_error
+ self._failed_canonical_url_to_dump = None
+ if progress_reporter is None:
+ self._progress_reporter = gtest_progress_reporter.GTestProgressReporter(
+ sys.stdout)
+ else:
+ self._progress_reporter = progress_reporter
+ self._output_formatters = output_formatters or []
+ self._extra_import_options = extra_import_options
+
+ self._trace_handles = trace_handles
+ self._num_traces_merged_into_results = 0
+ self._map_results = None
+ self._map_results_file = None
+
+ if jobs == AUTO_JOB_COUNT:
+ jobs = multiprocessing.cpu_count()
+ self._wq = threaded_work_queue.ThreadedWorkQueue(num_threads=jobs)
+
+ def _ProcessOneTrace(self, trace_handle):
+ canonical_url = trace_handle.canonical_url
+ run_reporter = self._progress_reporter.WillRun(canonical_url)
+ result = map_single_trace.MapSingleTrace(
+ trace_handle,
+ self._job,
+ extra_import_options=self._extra_import_options)
+
+ had_failure = len(result.failures) > 0
+
+ for f in result.failures:
+ run_reporter.DidAddFailure(f)
+ run_reporter.DidRun(had_failure)
+
+ self._wq.PostMainThreadTask(
+ self._MergeResultIntoMaster, result, trace_handle)
+
+ def _MergeResultIntoMaster(self, result, trace_handle):
+ self._map_results[trace_handle.canonical_url] = result
+
+ had_failure = len(result.failures) > 0
+ if self._stop_on_error and had_failure:
+ err = MapError("Mapping error")
+ self._AbortMappingDueStopOnError(err)
+ raise err
+
+ self._num_traces_merged_into_results += 1
+ if self._num_traces_merged_into_results == len(self._trace_handles):
+ self._wq.PostMainThreadTask(self._AllMappingDone)
+
+ def _AbortMappingDueStopOnError(self, err):
+ self._wq.Stop(err)
+
+ def _AllMappingDone(self):
+ self._wq.Stop()
+
+ def RunMapper(self):
+ self._map_results = {}
+
+ if not self._trace_handles:
+ err = MapError("No trace handles specified.")
+ raise err
+
+ if self._job.map_function_handle:
+ for trace_handle in self._trace_handles:
+ self._wq.PostAnyThreadTask(self._ProcessOneTrace, trace_handle)
+
+ self._wq.Run()
+
+ return self._map_results
+
+ def Run(self):
+ results_by_trace = self.RunMapper()
+ results = results_by_trace.values()
+
+ for of in self._output_formatters:
+ of.Format(results)
+
+ return results
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.html b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.html
new file mode 100644
index 00000000000..104ac919e20
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/extras/full_config.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/mre/failure.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.mre', function() {
+ const Failure = tr.mre.Failure;
+
+ function runAndConvertErrorsToFailures(result, job,
+ traceHandle, cb, opt_this) {
+ try {
+ cb.call(opt_this);
+ } catch (e) {
+ const err = tr.b.normalizeException(e);
+ // TODO(eakuefner): Set job once reduction is implemented.
+ result.addFailure(new Failure(
+ job, job.mapFunctionHandle.asUserFriendlyString(),
+ traceHandle.canonicalUrl, err.typeName, err.message, err.stack));
+ }
+ }
+
+ function mapSingleTrace(result, model, options, mapFunction) {
+ // Map the function.
+ const numPairsBeforeMapping = Object.keys(result.pairs).length;
+ const numFailuresBeforeMapping = result.failures.length;
+ try {
+ mapFunction(result, model, options);
+ } catch (ex) {
+ ex.name = 'MapFunctionError';
+ throw ex;
+ }
+
+ const addedPairs = (Object.keys(result.pairs).length >
+ numPairsBeforeMapping);
+ const addedFailures = result.failures.length > numFailuresBeforeMapping;
+ if (!(addedPairs || addedFailures)) {
+ const err = new Error('Mapper did not add any results!');
+ err.name = 'NoResultsAddedError';
+ throw err;
+ }
+ }
+
+ return {
+ mapSingleTrace,
+ runAndConvertErrorsToFailures
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py
new file mode 100644
index 00000000000..83b7177984a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace.py
@@ -0,0 +1,196 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import os
+import re
+import sys
+import tempfile
+import platform
+
+import tracing_project
+import vinn
+
+from tracing.mre import failure
+from tracing.mre import file_handle
+from tracing.mre import function_handle
+from tracing.mre import mre_result
+from tracing.mre import job as job_module
+
+_MAP_SINGLE_TRACE_CMDLINE_PATH = os.path.join(
+ tracing_project.TracingProject.tracing_src_path, 'mre',
+ 'map_single_trace_cmdline.html')
+
+class TemporaryMapScript(object):
+ def __init__(self, js):
+ tempfile_kwargs = {'mode': 'w+', 'delete': False}
+ if sys.version_info >= (3,):
+ tempfile_kwargs['encoding'] = 'utf-8'
+ temp_file = tempfile.NamedTemporaryFile(**tempfile_kwargs)
+
+ temp_file.write("""
+<!DOCTYPE html>
+<script>
+%s
+</script>
+""" % js)
+ temp_file.close()
+ self._filename = temp_file.name
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ os.remove(self._filename)
+ self._filename = None
+
+ @property
+ def filename(self):
+ return self._filename
+
+
+class FunctionLoadingFailure(failure.Failure):
+ pass
+
+class FunctionNotDefinedFailure(failure.Failure):
+ pass
+
+class MapFunctionFailure(failure.Failure):
+ pass
+
+class FileLoadingFailure(failure.Failure):
+ pass
+
+class TraceImportFailure(failure.Failure):
+ pass
+
+class NoResultsAddedFailure(failure.Failure):
+ pass
+
+class InternalMapError(Exception):
+ pass
+
+_FAILURE_NAME_TO_FAILURE_CONSTRUCTOR = {
+ 'FileLoadingError': FileLoadingFailure,
+ 'FunctionLoadingError': FunctionLoadingFailure,
+ 'FunctionNotDefinedError': FunctionNotDefinedFailure,
+ 'TraceImportError': TraceImportFailure,
+ 'MapFunctionError': MapFunctionFailure,
+ 'NoResultsAddedError': NoResultsAddedFailure
+}
+
+
+def MapSingleTrace(trace_handle,
+ job,
+ extra_import_options=None):
+ assert (isinstance(extra_import_options, (type(None), dict))), (
+ 'extra_import_options should be a dict or None.')
+ project = tracing_project.TracingProject()
+
+ all_source_paths = list(project.source_paths)
+ all_source_paths.append(project.trace_processor_root_path)
+
+ result = mre_result.MreResult()
+
+ with trace_handle.PrepareFileForProcessing() as prepared_trace_handle:
+ js_args = [
+ json.dumps(prepared_trace_handle.AsDict()),
+ json.dumps(job.AsDict()),
+ ]
+ if extra_import_options:
+ js_args.append(json.dumps(extra_import_options))
+
+ # Use 8gb heap space to make sure we don't OOM'ed on big trace, but not
+ # on ARM devices since we use 32-bit d8 binary.
+ if platform.machine() == 'armv7l' or platform.machine() == 'aarch64':
+ v8_args = None
+ else:
+ v8_args = ['--max-old-space-size=8192']
+
+ res = vinn.RunFile(
+ _MAP_SINGLE_TRACE_CMDLINE_PATH,
+ source_paths=all_source_paths,
+ js_args=js_args,
+ v8_args=v8_args)
+
+ stdout = res.stdout
+ if not isinstance(stdout, str):
+ stdout = stdout.decode('utf-8', errors='replace')
+
+ if res.returncode != 0:
+ sys.stderr.write(stdout)
+ result.AddFailure(failure.Failure(
+ job,
+ trace_handle.canonical_url,
+ 'Error', 'vinn runtime error while mapping trace.',
+ 'vinn runtime error while mapping trace.', 'Unknown stack'))
+ return result
+
+ for line in stdout.split('\n'):
+ m = re.match('^MRE_RESULT: (.+)', line, re.DOTALL)
+ if m:
+ found_dict = json.loads(m.group(1))
+ failures = [
+ failure.Failure.FromDict(f, job, _FAILURE_NAME_TO_FAILURE_CONSTRUCTOR)
+ for f in found_dict['failures']]
+
+ for f in failures:
+ result.AddFailure(f)
+
+ for k, v in found_dict['pairs'].items():
+ result.AddPair(k, v)
+
+ else:
+ if len(line) > 0:
+ sys.stderr.write(line)
+ sys.stderr.write('\n')
+
+ if not (len(result.pairs) or len(result.failures)):
+ raise InternalMapError('Internal error: No results were produced!')
+
+ return result
+
+
+def ExecuteTraceMappingCode(trace_file_path, process_trace_func_code,
+ extra_import_options=None,
+ trace_canonical_url=None):
+ """Execute |process_trace_func_code| on the input |trace_file_path|.
+
+ process_trace_func_code must contain a function named 'process_trace' with
+ signature as follows:
+
+ function processTrace(results, model) {
+ // call results.addPair(<key>, <value>) to add data to results object.
+ }
+
+ Whereas results is an instance of tr.mre.MreResult, and model is an instance
+ of tr.model.Model which was resulted from parsing the input trace.
+
+ Returns:
+ This function returns the dictionay that represents data collected in
+ |results|.
+
+ Raises:
+ RuntimeError if there is any error with execute trace mapping code.
+ """
+
+ with TemporaryMapScript("""
+ //# sourceURL=processTrace
+ %s;
+ tr.mre.FunctionRegistry.register(processTrace);
+ """ % process_trace_func_code) as map_script:
+ handle = function_handle.FunctionHandle(
+ [function_handle.ModuleToLoad(filename=map_script.filename)],
+ function_name='processTrace')
+ mapping_job = job_module.Job(handle)
+ trace_file_path = os.path.abspath(trace_file_path)
+ if not trace_canonical_url:
+ trace_canonical_url = 'file://%s' % trace_file_path
+ trace_handle = file_handle.URLFileHandle(
+ trace_file_path, trace_canonical_url)
+ results = MapSingleTrace(trace_handle, mapping_job, extra_import_options)
+ if results.failures:
+ raise RuntimeError(
+ 'Failures mapping trace:\n%s' %
+ ('\n'.join(str(f) for f in results.failures)))
+ return results.pairs
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_cmdline.html b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_cmdline.html
new file mode 100644
index 00000000000..b79f9ec67c7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_cmdline.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/mre/failure.html">
+<link rel="import" href="/tracing/mre/file_handle.html">
+<link rel="import" href="/tracing/mre/function_handle.html">
+<link rel="import" href="/tracing/mre/job.html">
+<link rel="import" href="/tracing/mre/map_single_trace.html">
+<link rel="import" href="/tracing/mre/mre_result.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+tr.exportTo('tr.mre', function() {
+ const Failure = tr.mre.Failure;
+
+ function createModelFromTraceData(traceData,
+ canonicalUrl,
+ opt_extraImportOptions) {
+ const model = new tr.Model();
+ try {
+ const importOptions = new tr.importer.ImportOptions();
+ importOptions.pruneEmptyContainers = false;
+ importOptions.showImportWarnings = false;
+ if (opt_extraImportOptions !== undefined) {
+ for (const property in opt_extraImportOptions) {
+ if (opt_extraImportOptions.hasOwnProperty(property)) {
+ importOptions[property] = opt_extraImportOptions[property];
+ }
+ }
+ }
+
+ const i = new tr.importer.Import(model, importOptions);
+ i.importTraces([traceData]);
+ } catch (ex) {
+ ex.name = 'TraceImportError';
+ throw ex;
+ }
+
+ model.canonicalUrl = canonicalUrl;
+
+ return model;
+ }
+
+ function mapSingleTraceWithResult(options) {
+ const result = new tr.mre.MreResult();
+
+ tr.mre.runAndConvertErrorsToFailures(
+ result, options.job, options.traceHandle,
+ function() {
+ const mapFunction = options.job.mapFunctionHandle.load();
+ const traceData = options.traceHandle.load();
+ const model = createModelFromTraceData(
+ traceData, options.traceHandle.canonicalUrl,
+ options.extraImportOptions);
+ const opt_options = options.job.mapFunctionHandle.options;
+ tr.mre.mapSingleTrace(result, model, opt_options, mapFunction);
+ });
+ return result;
+ }
+
+ function mapSingleTraceMain(args) {
+ if (args.length !== 2 && args.length !== 3) {
+ throw new Error('Must provide two or three arguments.');
+ }
+
+ const options = {
+ traceHandle: tr.mre.FileHandle.fromDict(JSON.parse(args[0])),
+ job: tr.mre.Job.fromDict(JSON.parse(args[1])),
+ extraImportOptions: args.length === 3 ? JSON.parse(args[2]) : undefined
+ };
+
+ const result = mapSingleTraceWithResult(options);
+
+ console.log('MRE_RESULT: ' + JSON.stringify(result.asDict()));
+ return 0;
+ }
+
+ return {
+ mapSingleTraceMain,
+ mapSingleTraceWithResult
+ };
+});
+
+if (tr.isHeadless) {
+ quit(tr.mre.mapSingleTraceMain(sys.argv.slice(1)));
+}
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py
new file mode 100644
index 00000000000..fb6b5bff071
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_single_trace_unittest.py
@@ -0,0 +1,235 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import unittest
+
+from tracing.mre import function_handle
+from tracing.mre import map_single_trace
+from tracing.mre import file_handle
+from tracing.mre import failure
+from tracing.mre import job as job_module
+
+
+def _Handle(filename):
+ module = function_handle.ModuleToLoad(filename=filename)
+ map_handle = function_handle.FunctionHandle(
+ modules_to_load=[module], function_name='MyMapFunction')
+ return job_module.Job(map_handle, None)
+
+
+class MapSingleTraceTests(unittest.TestCase):
+
+ def testPassingMapScript(self):
+ events = [
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'a', 'cat': 'c',
+ 'ts': 0, 'dur': 10, 'args': {}},
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'b', 'cat': 'c',
+ 'ts': 3, 'dur': 5, 'args': {}}
+ ]
+ trace_handle = file_handle.InMemoryFileHandle(
+ '/a.json', json.dumps(events).encode('utf-8'))
+
+ with map_single_trace.TemporaryMapScript("""
+ tr.mre.FunctionRegistry.register(
+ function MyMapFunction(result, model) {
+ var canonicalUrl = model.canonicalUrl;
+ result.addPair('result', {
+ numProcesses: model.getAllProcesses().length
+ });
+ });
+ """) as map_script:
+ result = map_single_trace.MapSingleTrace(trace_handle,
+ _Handle(map_script.filename))
+
+ self.assertFalse(result.failures)
+ r = result.pairs['result']
+ self.assertEquals(r['numProcesses'], 1)
+
+
+ def testProcessingGiantTrace(self):
+ # Populate a string trace of 2 million events.
+ trace_events = ['[']
+ for i in range(2000000):
+ trace_events.append(
+ '{"pid": 1, "tid": %i, "ph": "X", "name": "a", "cat": "c",'
+ '"ts": %i, "dur": 1, "args": {}},' % (i % 5, 2 * i))
+ trace_events.append('{}]')
+ trace_data = ''.join(trace_events)
+ if not isinstance(trace_data, bytes):
+ trace_data = trace_data.encode('utf-8')
+ trace_handle = file_handle.InMemoryFileHandle(
+ '/a.json', trace_data)
+
+ with map_single_trace.TemporaryMapScript("""
+ tr.mre.FunctionRegistry.register(
+ function MyMapFunction(result, model) {
+ var canonicalUrl = model.canonicalUrl;
+ var numEvents = 0;
+ for (var e of model.getProcess(1).getDescendantEvents()) {
+ numEvents++;
+ }
+ result.addPair('result', {
+ numEvents: numEvents
+ });
+ });
+ """) as map_script:
+ result = map_single_trace.MapSingleTrace(trace_handle,
+ _Handle(map_script.filename))
+
+ self.assertFalse(result.failures,
+ msg='\n'.join(str(f) for f in result.failures))
+ r = result.pairs['result']
+ self.assertEquals(r['numEvents'], 2000000)
+
+
+
+ def testTraceDidntImport(self):
+ trace_string = b'This is intentionally not a trace-formatted string.'
+ trace_handle = file_handle.InMemoryFileHandle(
+ '/a.json', trace_string)
+
+ with map_single_trace.TemporaryMapScript("""
+ tr.mre.FunctionRegistry.register(
+ function MyMapFunction(results, model) {
+ });
+ """) as map_script:
+ result = map_single_trace.MapSingleTrace(trace_handle,
+ _Handle(map_script.filename))
+
+ self.assertEquals(len(result.failures), 1)
+ self.assertEquals(len(result.pairs), 0)
+ f = result.failures[0]
+ self.assertIsInstance(f, map_single_trace.TraceImportFailure)
+
+ def testMapFunctionThatThrows(self):
+ events = [
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'a', 'cat': 'c',
+ 'ts': 0, 'dur': 10, 'args': {}},
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'b', 'cat': 'c',
+ 'ts': 3, 'dur': 5, 'args': {}}
+ ]
+ trace_handle = file_handle.InMemoryFileHandle(
+ '/a.json', json.dumps(events).encode('utf-8'))
+
+ with map_single_trace.TemporaryMapScript("""
+ tr.mre.FunctionRegistry.register(
+ function MyMapFunction(results, model) {
+ throw new Error('Expected error');
+ });
+ """) as map_script:
+ result = map_single_trace.MapSingleTrace(trace_handle,
+ _Handle(map_script.filename))
+
+ self.assertEquals(len(result.failures), 1)
+ self.assertEquals(len(result.pairs), 0)
+ f = result.failures[0]
+ self.assertIsInstance(f, map_single_trace.MapFunctionFailure)
+
+ def testMapperWithLoadError(self):
+ events = [
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'a', 'cat': 'c',
+ 'ts': 0, 'dur': 10, 'args': {}},
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'b', 'cat': 'c',
+ 'ts': 3, 'dur': 5, 'args': {}}
+ ]
+ trace_handle = file_handle.InMemoryFileHandle(
+ '/a.json', json.dumps(events).encode('utf-8'))
+
+ with map_single_trace.TemporaryMapScript("""
+ throw new Error('Expected load error');
+ """) as map_script:
+ result = map_single_trace.MapSingleTrace(trace_handle,
+ _Handle(map_script.filename))
+
+ self.assertEquals(len(result.failures), 1)
+ self.assertEquals(len(result.pairs), 0)
+ f = result.failures[0]
+ self.assertIsInstance(f, map_single_trace.FunctionLoadingFailure)
+
+ def testMapperWithUnexpectedError(self):
+ events = [
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'a', 'cat': 'c',
+ 'ts': 0, 'dur': 10, 'args': {}},
+ ]
+ trace_handle = file_handle.InMemoryFileHandle(
+ '/a.json', json.dumps(events).encode('utf-8'))
+
+ with map_single_trace.TemporaryMapScript("""
+ quit(100);
+ """) as map_script:
+ result = map_single_trace.MapSingleTrace(trace_handle,
+ _Handle(map_script.filename))
+
+ self.assertEquals(len(result.failures), 1)
+ self.assertEquals(len(result.pairs), 0)
+ f = result.failures[0]
+ self.assertIsInstance(f, failure.Failure)
+
+ def testNoMapper(self):
+ events = [
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'a', 'cat': 'c',
+ 'ts': 0, 'dur': 10, 'args': {}},
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'b', 'cat': 'c',
+ 'ts': 3, 'dur': 5, 'args': {}}
+ ]
+ trace_handle = file_handle.InMemoryFileHandle(
+ '/a.json', json.dumps(events).encode('utf-8'))
+
+ with map_single_trace.TemporaryMapScript("""
+ """) as map_script:
+ result = map_single_trace.MapSingleTrace(trace_handle,
+ _Handle(map_script.filename))
+
+ self.assertEquals(len(result.failures), 1)
+ self.assertEquals(len(result.pairs), 0)
+ f = result.failures[0]
+ self.assertIsInstance(f, map_single_trace.FunctionNotDefinedFailure)
+
+ def testMapperDoesntAddValues(self):
+ events = [
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'a', 'cat': 'c',
+ 'ts': 0, 'dur': 10, 'args': {}},
+ {'pid': 1, 'tid': 2, 'ph': 'X', 'name': 'b', 'cat': 'c',
+ 'ts': 3, 'dur': 5, 'args': {}}
+ ]
+ trace_handle = file_handle.InMemoryFileHandle(
+ '/a.json', json.dumps(events).encode('utf-8'))
+
+ with map_single_trace.TemporaryMapScript("""
+ tr.mre.FunctionRegistry.register(
+ function MyMapFunction(results, model) {
+ });
+ """) as map_script:
+ result = map_single_trace.MapSingleTrace(trace_handle,
+ _Handle(map_script.filename))
+
+ self.assertEquals(len(result.failures), 1)
+ self.assertEquals(len(result.pairs), 0)
+ f = result.failures[0]
+ self.assertIsInstance(f, map_single_trace.NoResultsAddedFailure)
+
+ def testExecuteTraceMappingCode(self):
+ test_trace_path = os.path.join(os.path.dirname(__file__), 'test_trace.json')
+ results = map_single_trace.ExecuteTraceMappingCode(
+ test_trace_path,
+ """
+ function processTrace(results, model) {
+ var canonicalUrl = model.canonicalUrl;
+ results.addPair('numProcesses', model.getAllProcesses().length);
+ };
+ """)
+ self.assertEquals(results['numProcesses'], 2)
+
+ def testExecuteTraceMappingCodeWithError(self):
+ test_trace_path = os.path.join(os.path.dirname(__file__), 'test_trace.json')
+ with self.assertRaises(RuntimeError):
+ map_single_trace.ExecuteTraceMappingCode(
+ test_trace_path,
+ """
+ function processTrace(results, model) {
+ throw new Error('Expected error');
+ };
+ """)
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_traces.py b/chromium/third_party/catapult/tracing/tracing/mre/map_traces.py
new file mode 100644
index 00000000000..749e7acab39
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_traces.py
@@ -0,0 +1,67 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import argparse
+import sys
+
+from tracing.mre import corpus_driver_cmdline
+from tracing.mre import map_runner
+from tracing.mre import function_handle
+from tracing.mre import job as job_module
+from tracing.mre import json_output_formatter
+
+
+def Main(argv):
+ parser = argparse.ArgumentParser(
+ description='Bulk trace processing')
+ parser.add_argument('--map_function_handle')
+ parser.add_argument('-j', '--jobs', type=int,
+ default=map_runner.AUTO_JOB_COUNT)
+ parser.add_argument('-o', '--output-file')
+ parser.add_argument('-s', '--stop-on-error',
+ action='store_true')
+
+ if len(sys.argv) == 1:
+ parser.print_help()
+ sys.exit(0)
+
+ args = parser.parse_args(argv[1:])
+
+ corpus_driver = corpus_driver_cmdline.GetCorpusDriver(parser, args)
+
+ if args.output_file:
+ ofile = open(args.output_file, 'w')
+ else:
+ ofile = sys.stdout
+
+ output_formatter = json_output_formatter.JSONOutputFormatter(ofile)
+
+ try:
+ map_handle = None
+ if args.map_function_handle:
+ map_handle = function_handle.FunctionHandle.FromUserFriendlyString(
+ args.map_function_handle)
+ job = job_module.Job(map_handle)
+ except function_handle.UserFriendlyStringInvalidError:
+ error_lines = [
+ 'The map_traces command-line API has changed! You must now specify the',
+ 'filenames to load and the map function name, separated by :. For '
+ 'example, a mapper in',
+ 'foo.html called Foo would be written as foo.html:Foo .'
+ ]
+ parser.error('\n'.join(error_lines))
+
+ try:
+ trace_handles = corpus_driver.GetTraceHandles()
+ runner = map_runner.MapRunner(trace_handles, job,
+ stop_on_error=args.stop_on_error,
+ jobs=args.jobs,
+ output_formatters=[output_formatter])
+ results = runner.Run()
+ if not any(result.failures for result in results):
+ return 0
+ else:
+ return 255
+ finally:
+ if ofile != sys.stdout:
+ ofile.close()
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/map_traces_handler.py b/chromium/third_party/catapult/tracing/tracing/mre/map_traces_handler.py
new file mode 100644
index 00000000000..ea9b0b6d533
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/map_traces_handler.py
@@ -0,0 +1,14 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import webapp2
+
+
+def MapTrace(trace_corpus_driver): # pylint: disable=unused-argument
+ pass
+
+
+class MapTracesHandler(webapp2.RequestHandler):
+
+ def post(self, *args, **kwargs): # pylint: disable=unused-argument
+ pass
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/mre_result.html b/chromium/third_party/catapult/tracing/tracing/mre/mre_result.html
new file mode 100644
index 00000000000..3251bb051ff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/mre_result.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/mre/failure.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.mre', function() {
+ class MreResult {
+ constructor(failures, pairs) {
+ if (failures === undefined) {
+ failures = [];
+ }
+ if (pairs === undefined) {
+ pairs = {};
+ }
+ this.failures = failures;
+ this.pairs = pairs;
+ }
+
+ addFailure(failure) {
+ this.failures.push(failure);
+ }
+
+ addPair(key, value) {
+ if (key in this.pairs) {
+ throw new Error('Key ' + key + ' already exists in result.');
+ }
+ this.pairs[key] = value;
+ }
+
+ asDict() {
+ const d = {
+ pairs: this.pairs
+ };
+
+ if (this.failures) {
+ d.failures = this.failures.map(function(f) {return f.asDict();});
+ }
+
+ return d;
+ }
+
+ hadFailures() {
+ return this.failures.length > 0;
+ }
+
+ static fromDict(resultDict) {
+ const failures = (resultDict.failures !== undefined) ?
+ resultDict.failures.map(tr.mre.Failure.fromDict) : undefined;
+ const pairs = resultDict.pairs;
+ return new MreResult(failures, pairs);
+ }
+ }
+
+ return {
+ MreResult,
+ };
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/mre_result.py b/chromium/third_party/catapult/tracing/tracing/mre/mre_result.py
new file mode 100644
index 00000000000..f3d128e23a8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/mre_result.py
@@ -0,0 +1,48 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from tracing.mre import failure as failure_module
+
+class DuplicateKeyError(Exception):
+ """Raised if an attempt is made to set a key more than once."""
+
+
+class MreResult(object):
+
+ def __init__(self, failures=None, pairs=None):
+ if failures is None:
+ failures = []
+ if pairs is None:
+ pairs = {}
+ self._failures = failures
+ self._pairs = pairs
+
+ @property
+ def failures(self):
+ return self._failures
+
+ @property
+ def pairs(self):
+ return self._pairs
+
+ def AsDict(self):
+ d = {
+ 'pairs': self._pairs
+ }
+
+ if self.failures:
+ d['failures'] = [failure.AsDict() for failure in self._failures]
+
+ return d
+
+ def AddFailure(self, failure):
+ if not isinstance(failure, failure_module.Failure):
+ raise ValueError('Attempted to add %s as Failure', failure)
+
+ self._failures.append(failure)
+
+ def AddPair(self, key, value):
+ if key in self._pairs:
+ raise DuplicateKeyError('Key ' + key + 'already exists in result.')
+ self._pairs[key] = value
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/mre_result_test.html b/chromium/third_party/catapult/tracing/tracing/mre/mre_result_test.html
new file mode 100644
index 00000000000..5b8946990ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/mre_result_test.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/mre/failure.html">
+<link rel="import" href="/tracing/mre/mre_result.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('mreResultAsDictTest', function() {
+ const result = new tr.mre.MreResult();
+
+ const failure = new tr.mre.Failure('1', '2', '3', 'err', 'desc', 'stack');
+ result.addFailure(failure);
+
+ result.addPair('foo', 'bar');
+
+ const resultDict = result.asDict();
+
+ assert.deepEqual(resultDict.failures, [failure.asDict()]);
+ assert.deepEqual(resultDict.pairs, {foo: 'bar'});
+ });
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py
new file mode 100644
index 00000000000..2bdb5a8f19a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/mre_result_unittest.py
@@ -0,0 +1,46 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.mre import function_handle
+from tracing.mre import map_single_trace
+from tracing.mre import failure as failure_module
+from tracing.mre import job as job_module
+from tracing.mre import mre_result
+
+
+class MreResultTests(unittest.TestCase):
+
+ def testAsDict(self):
+ result = mre_result.MreResult()
+
+ with map_single_trace.TemporaryMapScript("""
+ tr.mre.FunctionRegistry.register(
+ function MyMapFunction(result, model) {
+ var canonicalUrl = model.canonicalUrl;
+ result.addPair('result', {
+ numProcesses: model.getAllProcesses().length
+ });
+ });
+ """) as map_script:
+
+ module = function_handle.ModuleToLoad(filename=map_script.filename)
+ map_handle = function_handle.FunctionHandle(
+ modules_to_load=[module], function_name='MyMapFunction')
+ job = job_module.Job(map_handle, None)
+ failure = failure_module.Failure(job, '2', '3', 'err', 'desc', 'stack')
+ result.AddFailure(failure)
+
+ result.AddPair('foo', 'bar')
+
+ result_dict = result.AsDict()
+
+ self.assertEquals(result_dict['failures'], [failure.AsDict()])
+ self.assertEquals(result_dict['pairs'], {'foo': 'bar'})
+
+ def testAddingNonFailure(self):
+ result = mre_result.MreResult()
+ with self.assertRaises(ValueError):
+ result.AddFailure('foo')
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/output_formatter.py b/chromium/third_party/catapult/tracing/tracing/mre/output_formatter.py
new file mode 100644
index 00000000000..5a4be13acce
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/output_formatter.py
@@ -0,0 +1,19 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Derived from telemetry OutputFormatter. Should stay close in architecture
+# to telemetry OutputFormatter.
+
+
+class OutputFormatter(object):
+
+ def __init__(self, output_stream):
+ self._output_stream = output_stream
+
+ def Format(self, results):
+ raise NotImplementedError()
+
+ @property
+ def output_stream(self):
+ return self._output_stream
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/progress_reporter.py b/chromium/third_party/catapult/tracing/tracing/mre/progress_reporter.py
new file mode 100644
index 00000000000..b33d744da13
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/progress_reporter.py
@@ -0,0 +1,27 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class RunReporter(object):
+
+ def __init__(self, canonical_url):
+ self.canonical_url = canonical_url
+
+ def DidAddFailure(self, failure):
+ pass
+
+ def DidRun(self, run_failed):
+ pass
+
+
+# Derived from telemetry ProgressReporter. Should stay close in architecture
+# to telemetry ProgressReporter.
+class ProgressReporter(object):
+
+ def WillRun(self, canonical_url):
+ return RunReporter(canonical_url)
+
+ # TODO(eakuefner): Implement reduction, make this not take a result list.
+ def DidFinishAllRuns(self, result_list):
+ pass
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/reduce_map_results.html b/chromium/third_party/catapult/tracing/tracing/mre/reduce_map_results.html
new file mode 100644
index 00000000000..9e64041f3e3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/reduce_map_results.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/mre/failure.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.mre', function() {
+ function reduceMapResults(jobResults, key, mapResults, reduceFunction) {
+ try {
+ const result = reduceFunction(key, mapResults);
+ jobResults.addPair(key, result);
+ } catch (ex) {
+ ex.name = 'ReduceFunctionError';
+ throw ex;
+ }
+ }
+
+ return {
+ reduceMapResults
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/reduce_map_results_cmdline.html b/chromium/third_party/catapult/tracing/tracing/mre/reduce_map_results_cmdline.html
new file mode 100644
index 00000000000..ac6e578b6c5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/reduce_map_results_cmdline.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/mre/file_handle.html">
+<link rel="import" href="/tracing/mre/job.html">
+<link rel="import" href="/tracing/mre/mre_result.html">
+<link rel="import" href="/tracing/mre/reduce_map_results.html">
+<link rel="import" href="/tracing/mre/run_and_convert_errors_to_failures.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+tr.exportTo('tr.mre', function() {
+ function jsonReplacer(key, value) {
+ if (value instanceof tr.v.Histogram) {
+ return value.asDict();
+ }
+ return value;
+ }
+
+ function reduceMapResultsMain(args) {
+ if (args.length !== 3) {
+ throw new Error('Must provide three arguments');
+ }
+
+ const options = {
+ key: args[0],
+ fileHandle: tr.mre.FileHandle.fromDict(JSON.parse(args[1])),
+ job: tr.mre.Job.fromDict(JSON.parse(args[2]))
+ };
+
+ const mapResultsLoaded = options.fileHandle.load();
+ const mapResults = JSON.parse(mapResultsLoaded);
+
+ const jobResults = new tr.mre.MreResult();
+
+ tr.mre.runAndConvertErrorsToFailures(
+ jobResults, options.job, options.job.reduceFunctionHandle,
+ undefined,
+ function() {
+ const reduceFunction = options.job.reduceFunctionHandle.load();
+ tr.mre.reduceMapResults(jobResults, options.key, mapResults.pairs,
+ reduceFunction);
+ });
+
+ if (Object.keys(jobResults.pairs).length !== 0) {
+ console.log('JOB_RESULTS: ' + JSON.stringify(jobResults.pairs,
+ jsonReplacer));
+ }
+ jobResults.failures.forEach(function(failure) {
+ console.log('JOB_FAILURE: ' + JSON.stringify(failure.asDict()));
+ });
+ return 0;
+ }
+
+ return {
+ reduceMapResultsMain
+ };
+});
+
+
+if (tr.isHeadless) {
+ quit(tr.mre.reduceMapResultsMain(sys.argv.slice(1)));
+}
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/run_and_convert_errors_to_failures.html b/chromium/third_party/catapult/tracing/tracing/mre/run_and_convert_errors_to_failures.html
new file mode 100644
index 00000000000..70ca7aed12d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/run_and_convert_errors_to_failures.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/mre/failure.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.mre', function() {
+ function runAndConvertErrorsToFailures(results, job, functionHandle,
+ traceHandle, cb, opt_this) {
+ try {
+ cb.call(opt_this);
+ } catch (e) {
+ const err = tr.b.normalizeException(e);
+ results.addFailure(new tr.mre.Failure(
+ job, functionHandle, traceHandle, err.typeName,
+ err.message, err.stack));
+ }
+ }
+
+ return {
+ runAndConvertErrorsToFailures
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/test_trace.json b/chromium/third_party/catapult/tracing/tracing/mre/test_trace.json
new file mode 100644
index 00000000000..c44efce2579
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/test_trace.json
@@ -0,0 +1,6 @@
+[
+ {"pid": 1, "tid": 2, "ph": "X", "name": "a", "cat": "c",
+ "ts": 0, "dur": 10, "args": {}},
+ {"pid": 2, "tid": 2, "ph": "X", "name": "b", "cat": "c",
+ "ts": 3, "dur": 5, "args": {}}
+]
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue.py b/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue.py
new file mode 100644
index 00000000000..ccd0e6b7985
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue.py
@@ -0,0 +1,124 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import threading
+import traceback
+try:
+ import queue
+except ImportError:
+ import Queue as queue
+
+
+class ThreadedWorkQueue(object):
+
+ def __init__(self, num_threads):
+ self._num_threads = num_threads
+
+ self._main_thread_tasks = None
+ self._any_thread_tasks = None
+
+ self._running = False
+ self._stop = False
+ self._stop_result = None
+
+ self.Reset()
+
+ @property
+ def is_running(self):
+ return self._running
+
+ def Run(self):
+ if self.is_running:
+ raise Exception('Already running')
+
+ self._running = True
+ self._stop = False
+ self._stop_result = None
+
+ if self._num_threads == 1:
+ self._RunSingleThreaded()
+ else:
+ self._RunMultiThreaded()
+
+ self._main_thread_tasks = queue.Queue()
+ self._any_thread_tasks = queue.Queue()
+
+ r = self._stop_result
+ self._stop_result = None
+ self._running = False
+
+ return r
+
+ def Stop(self, stop_result=None):
+ if not self.is_running:
+ raise Exception('Not running')
+
+ if self._stop:
+ return False
+ self._stop_result = stop_result
+ self._stop = True
+ return True
+
+ def Reset(self):
+ assert not self.is_running
+ self._main_thread_tasks = queue.Queue()
+ self._any_thread_tasks = queue.Queue()
+
+ def PostMainThreadTask(self, cb, *args, **kwargs):
+ def RunTask():
+ cb(*args, **kwargs)
+ self._main_thread_tasks.put(RunTask)
+
+ def PostAnyThreadTask(self, cb, *args, **kwargs):
+ def RunTask():
+ cb(*args, **kwargs)
+ self._any_thread_tasks.put(RunTask)
+
+ def _TryToRunOneTask(self, task_queue, block=False):
+ if block:
+ try:
+ task = task_queue.get(True, 0.1)
+ except queue.Empty:
+ return
+ else:
+ if task_queue.empty():
+ return
+ task = task_queue.get()
+
+ try:
+ task()
+ except KeyboardInterrupt as ex:
+ raise ex
+ except Exception: # pylint: disable=broad-except
+ traceback.print_exc()
+ finally:
+ task_queue.task_done()
+
+ def _RunSingleThreaded(self):
+ while True:
+ if self._stop:
+ break
+ self._TryToRunOneTask(self._any_thread_tasks)
+ self._TryToRunOneTask(self._main_thread_tasks)
+
+ def _RunMultiThreaded(self):
+ threads = []
+ for _ in range(self._num_threads):
+ t = threading.Thread(target=self._ThreadMain)
+ t.setDaemon(True)
+ t.start()
+ threads.append(t)
+
+ while True:
+ if self._stop:
+ break
+ self._TryToRunOneTask(self._main_thread_tasks)
+
+ for t in threads:
+ t.join()
+
+ def _ThreadMain(self):
+ while True:
+ if self._stop:
+ break
+ self._TryToRunOneTask(self._any_thread_tasks, block=True)
diff --git a/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py b/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py
new file mode 100644
index 00000000000..6e93744540a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/mre/threaded_work_queue_unittest.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from tracing.mre import threaded_work_queue
+
+
+class ThreadedWorkQueueTests(unittest.TestCase):
+
+ def testSingleThreaded(self):
+ wq = threaded_work_queue.ThreadedWorkQueue(num_threads=1)
+ self._RunSimpleDecrementingTest(wq)
+
+ def testMultiThreaded(self):
+ wq = threaded_work_queue.ThreadedWorkQueue(num_threads=4)
+ self._RunSimpleDecrementingTest(wq)
+
+ def _RunSimpleDecrementingTest(self, wq):
+
+ remaining = [10]
+
+ def Decrement():
+ remaining[0] -= 1
+ if remaining[0]:
+ wq.PostMainThreadTask(Done)
+
+ def Done():
+ wq.Stop(314)
+
+ wq.PostAnyThreadTask(Decrement)
+ res = wq.Run()
+ self.assertEquals(res, 314)
diff --git a/chromium/third_party/catapult/tracing/tracing/tests.html b/chromium/third_party/catapult/tracing/tracing/tests.html
new file mode 100644
index 00000000000..beb5ab1d75a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/tests.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+ <title>Trace-Viewer Tests: loading...</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <link rel="shortcut icon" href="data:image/x-icon;base64,"
+ type="image/x-icon">
+
+ <script src="/components/webcomponentsjs/HTMLImports.js"></script>
+ <link rel="import" href="/tracing/ui/base/base.html" data-suppress-import-order>
+ <link rel="import" href="/tracing/base/unittest/interactive_test_runner.html">
+ <style>
+ html, body {
+ box-sizing: border-box;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ margin: 0px;
+ }
+ </style>
+</head>
+<body>
+ <script>
+ 'use strict';
+ window.addEventListener('load', function() {
+ HTMLImports.whenReady(function loadAndRunTests(e) {
+ tr.b.unittest.loadAndRunTests({
+ title: 'All Trace-Viewer Tests',
+ getAllSuiteRelPathsAsync() {
+ return tr.b.getAsync('/tracing/tests').then(function(json) {
+ return JSON.parse(json).test_relpaths;
+ }).catch(function(e) {
+ throw e;
+ });
+ },
+ testLinks: [
+ {linkPath: '/tracing_examples/skia_debugger.html',
+ title: 'Skia Debugger'},
+ {linkPath: '/tracing_examples/trace_viewer.html',
+ title: 'Trace File Viewer'}
+ ]
+ });
+ });
+ });
+ </script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/tracing/tracing/trace2html.html b/chromium/third_party/catapult/tracing/tracing/trace2html.html
new file mode 100644
index 00000000000..640f042bc3d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/trace2html.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/ui/base/base.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
+<script>
+'use strict';
+
+let g_timelineViewEl;
+
+(function() {
+ const styleEl = document.createElement('style');
+ const lines = [
+ 'html, body {',
+ ' box-sizing: border-box;',
+ ' overflow: hidden;',
+ ' margin: 0px;',
+ ' padding: 0;',
+ ' width: 100%;',
+ ' height: 100%;',
+ '}',
+ 'tr-ui-timeline-view {',
+ ' width: 100%;',
+ ' height: 100%;',
+ '}',
+ 'tr-ui-timeline-view:focus {',
+ ' outline: none;',
+ '}'
+ ];
+ Polymer.dom(styleEl).textContent = lines.join('\n');
+ Polymer.dom(document.head).appendChild(styleEl);
+})();
+
+document.addEventListener('DOMContentLoaded', function() {
+ const container = document.createElement('track-view-container');
+ container.id = 'track_view_container';
+
+ g_timelineViewEl = document.createElement('tr-ui-timeline-view');
+ Polymer.dom(g_timelineViewEl).appendChild(container);
+
+ Polymer.dom(document.body).appendChild(g_timelineViewEl);
+
+ const traces = [];
+ const viewerDataScripts = Polymer.dom(document).querySelectorAll(
+ '#viewer-data');
+ for (let i = 0; i < viewerDataScripts.length; i++) {
+ let text = Polymer.dom(viewerDataScripts[i]).textContent;
+ // Trim leading newlines off the text. They happen during writing.
+ while (text[0] === '\n') {
+ text = text.substring(1);
+ }
+ traces.push(tr.b.Base64.atob(text));
+ }
+
+ const m = new tr.Model();
+ const i = new tr.importer.Import(m);
+ const p = i.importTracesWithProgressDialog(traces);
+ p.then(
+ function() {
+ g_timelineViewEl.model = m;
+ g_timelineViewEl.updateDocumentFavicon();
+ g_timelineViewEl.globalMode = true;
+ g_timelineViewEl.viewTitle = document.title;
+ },
+ function(err) {
+ const overlay = new tr.ui.b.Overlay();
+ Polymer.dom(overlay).textContent = tr.b.normalizeException(err).message;
+ overlay.title = 'Import error';
+ overlay.visible = true;
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py b/chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py
new file mode 100644
index 00000000000..bdb1f26b0b7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/trace_data/__init__.py
@@ -0,0 +1,4 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
diff --git a/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py b/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py
new file mode 100644
index 00000000000..b0ad325e8de
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data.py
@@ -0,0 +1,346 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import json
+import logging
+import os
+import shutil
+import subprocess
+import tempfile
+import time
+
+
+try:
+ StringTypes = basestring
+except NameError:
+ StringTypes = str
+
+
+_TRACING_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ os.path.pardir, os.path.pardir)
+_TRACE2HTML_PATH = os.path.join(_TRACING_DIR, 'bin', 'trace2html')
+
+
+class NonSerializableTraceData(Exception):
+ """Raised when raw trace data cannot be serialized to TraceData."""
+ pass
+
+
+class TraceDataPart(object):
+ """TraceData can have a variety of events.
+
+ These are called "parts" and are accessed by the following fixed field names.
+ """
+ def __init__(self, raw_field_name):
+ self._raw_field_name = raw_field_name
+
+ def __repr__(self):
+ return 'TraceDataPart("%s")' % self._raw_field_name
+
+ @property
+ def raw_field_name(self):
+ return self._raw_field_name
+
+ def __eq__(self, other):
+ return self.raw_field_name == other.raw_field_name
+
+ def __hash__(self):
+ return hash(self.raw_field_name)
+
+
+ANDROID_PROCESS_DATA_PART = TraceDataPart('androidProcessDump')
+ATRACE_PART = TraceDataPart('systemTraceEvents')
+ATRACE_PROCESS_DUMP_PART = TraceDataPart('atraceProcessDump')
+CHROME_TRACE_PART = TraceDataPart('traceEvents')
+CPU_TRACE_DATA = TraceDataPart('cpuSnapshots')
+INSPECTOR_TRACE_PART = TraceDataPart('inspectorTimelineEvents')
+TELEMETRY_PART = TraceDataPart('telemetry')
+WALT_TRACE_PART = TraceDataPart('waltTraceEvents')
+
+ALL_TRACE_PARTS = {ANDROID_PROCESS_DATA_PART,
+ ATRACE_PART,
+ ATRACE_PROCESS_DUMP_PART,
+ CHROME_TRACE_PART,
+ CPU_TRACE_DATA,
+ INSPECTOR_TRACE_PART,
+ TELEMETRY_PART}
+
+ALL_TRACE_PARTS_RAW_NAMES = set(k.raw_field_name for k in ALL_TRACE_PARTS)
+
+def _HasTraceFor(part, raw):
+ assert isinstance(part, TraceDataPart)
+ if part.raw_field_name not in raw:
+ return False
+ return len(raw[part.raw_field_name]) > 0
+
+
+def _GetFilePathForTrace(trace, dir_path):
+ """ Return path to a file that contains |trace|.
+
+ Note: if |trace| is an instance of TraceFileHandle, this reuses the trace path
+ that the trace file handle holds. Otherwise, it creates a new trace file
+ in |dir_path| directory.
+ """
+ if isinstance(trace, TraceFileHandle):
+ return trace.file_path
+ with tempfile.NamedTemporaryFile(mode='w', dir=dir_path, delete=False) as fp:
+ if isinstance(trace, StringTypes):
+ fp.write(trace)
+ elif isinstance(trace, dict) or isinstance(trace, list):
+ json.dump(trace, fp)
+ else:
+ raise TypeError('Trace is of unknown type.')
+ return fp.name
+
+
+class TraceData(object):
+ """ TraceData holds a collection of traces from multiple sources.
+
+ A TraceData can have multiple active parts. Each part represents traces
+ collected from a different trace agent.
+ """
+ def __init__(self):
+ """Creates TraceData from the given data."""
+ self._raw_data = {}
+ self._events_are_safely_mutable = False
+
+ def _SetFromBuilder(self, d):
+ self._raw_data = d
+ self._events_are_safely_mutable = True
+
+ @property
+ def events_are_safely_mutable(self):
+ """Returns true if the events in this value are completely sealed.
+
+ Some importers want to take complex fields out of the TraceData and add
+ them to the model, changing them subtly as they do so. If the TraceData
+ was constructed with data that is shared with something outside the trace
+ data, for instance a test harness, then this mutation is unexpected. But,
+ if the values are sealed, then mutating the events is a lot faster.
+
+ We know if events are sealed if the value came from a string, or if the
+ value came from a TraceDataBuilder.
+ """
+ return self._events_are_safely_mutable
+
+ @property
+ def active_parts(self):
+ return {p for p in ALL_TRACE_PARTS if p.raw_field_name in self._raw_data}
+
+ def HasTracesFor(self, part):
+ return _HasTraceFor(part, self._raw_data)
+
+ def GetTracesFor(self, part):
+ """ Return the list of traces for |part| in string or dictionary forms.
+
+ Note: since this API return the traces that can be directly accessed in
+ memory, it may require lots of memory usage as some of the trace can be
+ very big.
+ For references, we have cases where Telemetry is OOM'ed because the memory
+ required for processing the trace in Python is too big (crbug.com/672097).
+ """
+ assert isinstance(part, TraceDataPart)
+ if not self.HasTracesFor(part):
+ return []
+ traces_list = self._raw_data[part.raw_field_name]
+ # Since this API return the traces in memory form, and since the memory
+ # bottleneck of Telemetry is for keeping trace in memory, there is no uses
+ # in keeping the on-disk form of tracing beyond this point. Hence we convert
+ # all traces for part of form TraceFileHandle to the JSON form.
+ for i, data in enumerate(traces_list):
+ if isinstance(data, TraceFileHandle):
+ traces_list[i] = data.AsTraceData()
+ return traces_list
+
+ def GetTraceFor(self, part):
+ assert isinstance(part, TraceDataPart)
+ traces = self.GetTracesFor(part)
+ assert len(traces) == 1
+ return traces[0]
+
+ def CleanUpAllTraces(self):
+ """ Remove all the traces that this has handles to.
+
+ Those include traces stored in memory & on disk. After invoking this,
+ one can no longer uses this object for collecting the traces.
+ """
+ for traces_list in self._raw_data.values():
+ for trace in traces_list:
+ if isinstance(trace, TraceFileHandle):
+ trace.Clean()
+ self._raw_data = {}
+
+ def Serialize(self, file_path, trace_title=''):
+ """Serializes the trace result to |file_path|.
+
+ """
+ if not self._raw_data:
+ logging.warning('No traces to convert to html.')
+ return
+ temp_dir = tempfile.mkdtemp()
+ trace_files = []
+ try:
+ trace_size_data = {}
+ for part, traces_list in self._raw_data.items():
+ for trace in traces_list:
+ path = _GetFilePathForTrace(trace, temp_dir)
+ trace_size_data.setdefault(part, 0)
+ trace_size_data[part] += os.path.getsize(path)
+ trace_files.append(path)
+ logging.info('Trace sizes in bytes: %s', trace_size_data)
+
+ start_time = time.time()
+ cmd = (
+ ['python', _TRACE2HTML_PATH] + trace_files +
+ ['--output', file_path] + ['--title', trace_title])
+ subprocess.check_output(cmd)
+
+ elapsed_time = time.time() - start_time
+ logging.info('trace2html finished in %.02f seconds.', elapsed_time)
+ finally:
+ shutil.rmtree(temp_dir)
+
+
+class TraceFileHandle(object):
+ """A trace file handle object allows storing trace data on disk.
+
+ TraceFileHandle API allows one to collect traces from Chrome into disk instead
+ of keeping them in memory. This is important for keeping memory usage of
+ Telemetry low to avoid OOM (see:
+ https://github.com/catapult-project/catapult/issues/3119).
+
+ The fact that this uses a file underneath to store tracing data means the
+ callsite is repsonsible for discarding the file when they no longer need the
+ tracing data. Call TraceFileHandle.Clean when you done using this object.
+ """
+ def __init__(self):
+ self._backing_file = None
+ self._file_path = None
+ self._trace_data = None
+
+ def Open(self):
+ assert not self._backing_file and not self._file_path
+ self._backing_file = tempfile.NamedTemporaryFile(delete=False, mode='a')
+
+ def AppendTraceData(self, partial_trace_data):
+ assert isinstance(partial_trace_data, StringTypes)
+ self._backing_file.write(partial_trace_data)
+
+ @property
+ def file_path(self):
+ assert self._file_path, (
+ 'Either the handle need to be closed first or this handle is cleaned')
+ return self._file_path
+
+ def Close(self):
+ assert self._backing_file
+ self._backing_file.close()
+ self._file_path = self._backing_file.name
+ self._backing_file = None
+
+ def AsTraceData(self):
+ """Get the object form of trace data that this handle manages.
+
+ *Warning: this can have large memory footprint if the trace data is big.
+
+ Since this requires the in-memory form of the trace, it is no longer useful
+ to still keep the backing file underneath, invoking this will also discard
+ the file to avoid the risk of leaking the backing trace file.
+ """
+ if self._trace_data:
+ return self._trace_data
+ assert self._file_path
+ with open(self._file_path) as f:
+ self._trace_data = json.load(f)
+ self.Clean()
+ return self._trace_data
+
+ def Clean(self):
+ """Remove the backing file used for storing trace on disk.
+
+ This should be called when and only when you no longer need to use
+ TraceFileHandle.
+ """
+ assert self._file_path
+ os.remove(self._file_path)
+ self._file_path = None
+
+
+class TraceDataBuilder(object):
+ """TraceDataBuilder helps build up a trace from multiple trace agents.
+
+ TraceData is supposed to be immutable, but it is useful during recording to
+ have a mutable version. That is TraceDataBuilder.
+ """
+ def __init__(self):
+ self._raw_data = {}
+
+ def AsData(self):
+ if self._raw_data is None:
+ raise Exception('Can only AsData once')
+ data = TraceData()
+ data._SetFromBuilder(self._raw_data)
+ self._raw_data = None
+ return data
+
+ def AddTraceFor(self, part, trace):
+ assert isinstance(part, TraceDataPart), part
+ if part == CHROME_TRACE_PART:
+ assert (isinstance(trace, dict) or
+ isinstance(trace, list) or
+ isinstance(trace, TraceFileHandle))
+ else:
+ assert (isinstance(trace, StringTypes) or
+ isinstance(trace, dict) or
+ isinstance(trace, list))
+
+ if self._raw_data is None:
+ raise Exception('Already called AsData() on this builder.')
+
+ self._raw_data.setdefault(part.raw_field_name, [])
+ self._raw_data[part.raw_field_name].append(trace)
+
+ def HasTracesFor(self, part):
+ return _HasTraceFor(part, self._raw_data)
+
+
+def CreateTraceDataFromRawData(raw_data):
+ """Convenient method for creating a TraceData object from |raw_data|.
+ This is mostly used for testing.
+
+ Args:
+ raw_data can be:
+ + A dictionary that repsents multiple trace parts. Keys of the
+ dictionary must always contain 'traceEvents', as chrome trace
+ must always present.
+ + A list that represents Chrome trace events.
+ + JSON string of either above.
+
+ """
+ raw_data = copy.deepcopy(raw_data)
+ if isinstance(raw_data, StringTypes):
+ json_data = json.loads(raw_data)
+ else:
+ json_data = raw_data
+
+ b = TraceDataBuilder()
+ if not json_data:
+ return b.AsData()
+ if isinstance(json_data, dict):
+ assert 'traceEvents' in json_data, 'Only raw chrome trace is supported'
+ trace_parts_keys = []
+ for k in json_data:
+ if k != 'traceEvents' and k in ALL_TRACE_PARTS_RAW_NAMES:
+ trace_parts_keys.append(k)
+ b.AddTraceFor(TraceDataPart(k), json_data[k])
+ # Delete the data for extra keys to form trace data for Chrome part only.
+ for k in trace_parts_keys:
+ del json_data[k]
+ b.AddTraceFor(CHROME_TRACE_PART, json_data)
+ elif isinstance(json_data, list):
+ b.AddTraceFor(CHROME_TRACE_PART, {'traceEvents': json_data})
+ else:
+ raise NonSerializableTraceData('Unrecognized data format.')
+ return b.AsData()
diff --git a/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py b/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py
new file mode 100644
index 00000000000..4917efc5019
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/trace_data/trace_data_unittest.py
@@ -0,0 +1,98 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import datetime
+import os
+import shutil
+import tempfile
+import unittest
+
+from tracing.trace_data import trace_data
+from tracing_build import html2trace
+
+
+class TraceDataTest(unittest.TestCase):
+ def testSerialize(self):
+ test_dir = tempfile.mkdtemp()
+ trace_path = os.path.join(test_dir, 'test_trace.json')
+ try:
+ ri = trace_data.CreateTraceDataFromRawData({'traceEvents': [1, 2, 3]})
+ ri.Serialize(trace_path)
+ with open(trace_path) as f:
+ json_traces = html2trace.ReadTracesFromHTMLFile(f)
+ self.assertEqual(json_traces, [{'traceEvents': [1, 2, 3]}])
+ finally:
+ shutil.rmtree(test_dir)
+
+ def testEmptyArrayValue(self):
+ # We can import empty lists and empty string.
+ d = trace_data.CreateTraceDataFromRawData([])
+ self.assertFalse(d.HasTracesFor(trace_data.CHROME_TRACE_PART))
+
+ def testInvalidTrace(self):
+ with self.assertRaises(AssertionError):
+ trace_data.CreateTraceDataFromRawData({'hello': 1})
+
+ def testListForm(self):
+ d = trace_data.CreateTraceDataFromRawData([{'ph': 'B'}])
+ self.assertTrue(d.HasTracesFor(trace_data.CHROME_TRACE_PART))
+ events = d.GetTracesFor(trace_data.CHROME_TRACE_PART)[0].get(
+ 'traceEvents', [])
+ self.assertEquals(1, len(events))
+
+ def testStringForm(self):
+ d = trace_data.CreateTraceDataFromRawData('[{"ph": "B"}]')
+ self.assertTrue(d.HasTracesFor(trace_data.CHROME_TRACE_PART))
+ events = d.GetTracesFor(trace_data.CHROME_TRACE_PART)[0].get(
+ 'traceEvents', [])
+ self.assertEquals(1, len(events))
+
+
+class TraceDataBuilderTest(unittest.TestCase):
+ def testBasicChrome(self):
+ builder = trace_data.TraceDataBuilder()
+ builder.AddTraceFor(trace_data.CHROME_TRACE_PART,
+ {'traceEvents': [1, 2, 3]})
+
+ d = builder.AsData()
+ self.assertTrue(d.HasTracesFor(trace_data.CHROME_TRACE_PART))
+
+ self.assertRaises(Exception, builder.AsData)
+
+ def testSetTraceFor(self):
+ telemetry_trace = {
+ 'traceEvents': [1, 2, 3],
+ 'metadata': {
+ 'field1': 'value1'
+ }
+ }
+
+ builder = trace_data.TraceDataBuilder()
+ builder.AddTraceFor(trace_data.TELEMETRY_PART, telemetry_trace)
+ d = builder.AsData()
+
+ self.assertEqual(d.GetTracesFor(trace_data.TELEMETRY_PART),
+ [telemetry_trace])
+
+ def testSetTraceForRaisesWithInvalidPart(self):
+ builder = trace_data.TraceDataBuilder()
+
+ self.assertRaises(AssertionError,
+ lambda: builder.AddTraceFor('not_a_trace_part', {}))
+
+ def testSetTraceForRaisesWithInvalidTrace(self):
+ builder = trace_data.TraceDataBuilder()
+
+ self.assertRaises(
+ AssertionError,
+ lambda: builder.AddTraceFor(trace_data.TELEMETRY_PART,
+ datetime.time.min))
+
+ def testSetTraceForRaisesAfterAsData(self):
+ builder = trace_data.TraceDataBuilder()
+ builder.AsData()
+
+ self.assertRaises(
+ Exception,
+ lambda: builder.AddTraceFor(trace_data.TELEMETRY_PART, {}))
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view.html
new file mode 100644
index 00000000000..b44741aace1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<dom-module id='tr-ui-a-alert-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ #table {
+ flex: 1 1 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table">
+ </tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-alert-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ ready() {
+ this.currentSelection_ = undefined;
+ this.$.table.tableColumns = [
+ {
+ title: 'Label',
+ value(row) { return row.name; },
+ width: '150px'
+ },
+ {
+ title: 'Value',
+ width: '100%',
+ value(row) { return row.value; }
+ }
+ ];
+ this.$.table.showHeader = false;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+ this.updateContents_();
+ },
+
+ getRowsForSingleAlert_(alert) {
+ const rows = [];
+
+ // Arguments
+ for (const argName in alert.args) {
+ const argView =
+ document.createElement('tr-ui-a-generic-object-view');
+ argView.object = alert.args[argName];
+ rows.push({ name: argName, value: argView });
+ }
+
+ // Associated events
+ if (alert.associatedEvents.length) {
+ alert.associatedEvents.forEach(function(event, i) {
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(
+ new tr.model.EventSet(event), event.title);
+
+ let valueString = '';
+ if (event instanceof tr.model.TimedEvent) {
+ valueString = 'took ' + event.duration.toFixed(2) + 'ms';
+ }
+
+ rows.push({
+ name: linkEl,
+ value: valueString
+ });
+ });
+ }
+
+ // Description
+ const descriptionEl = tr.ui.b.createDiv({
+ textContent: alert.info.description,
+ maxWidth: '300px'
+ });
+ rows.push({
+ name: 'Description',
+ value: descriptionEl
+ });
+
+ // Additional Reading Links
+ if (alert.info.docLinks) {
+ alert.info.docLinks.forEach(function(linkObject) {
+ const linkEl = document.createElement('a');
+ linkEl.target = '_blank';
+ linkEl.href = linkObject.href;
+ Polymer.dom(linkEl).textContent = Polymer.dom(linkObject).textContent;
+ rows.push({
+ name: linkObject.label,
+ value: linkEl
+ });
+ });
+ }
+ return rows;
+ },
+
+ getRowsForAlerts_(alerts) {
+ if (alerts.length === 1) {
+ const rows = [{
+ name: 'Alert',
+ value: tr.b.getOnlyElement(alerts).title
+ }];
+ const detailRows = this.getRowsForSingleAlert_(tr.b.getOnlyElement(
+ alerts));
+ rows.push.apply(rows, detailRows);
+ return rows;
+ }
+ return alerts.map(function(alert) {
+ return {
+ name: 'Alert',
+ value: alert.title,
+ isExpanded: alerts.size < 10, // This is somewhat arbitrary for now.
+ subRows: this.getRowsForSingleAlert_(alert)
+ };
+ }, this);
+ },
+
+ updateContents_() {
+ if (this.currentSelection_ === undefined) {
+ this.$.table.rows = [];
+ this.$.table.rebuild();
+ return;
+ }
+
+ const alerts = this.currentSelection_;
+ this.$.table.tableRows = this.getRowsForAlerts_(alerts);
+ this.$.table.rebuild();
+ },
+
+ get relatedEventsToHighlight() {
+ if (!this.currentSelection_) return undefined;
+ const result = new tr.model.EventSet();
+ for (const event of this.currentSelection_) {
+ result.addEventSet(event.associatedEvents);
+ }
+ return result;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-alert-sub-view',
+ tr.model.Alert,
+ {
+ multi: false,
+ title: 'Alert',
+ });
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-alert-sub-view',
+ tr.model.Alert,
+ {
+ multi: true,
+ title: 'Alerts',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html
new file mode 100644
index 00000000000..574cf5f0b86
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/alert_sub_view_test.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ test('instantiate', function() {
+ const slice = newSliceEx({title: 'b', start: 0, duration: 0.002});
+
+ const alertInfo = new tr.model.EventInfo(
+ 'alertInfo', 'Critical alert',
+ [{
+ label: 'Project Page',
+ textContent: 'Trace-Viewer Github Project',
+ href: 'https://github.com/google/trace-viewer/'
+ }]);
+
+ const alert = new tr.model.Alert(alertInfo, 5, [slice]);
+ assert.strictEqual(1, alert.associatedEvents.length);
+
+ const subView = document.createElement('tr-ui-a-alert-sub-view');
+ subView.selection = new tr.model.EventSet(alert);
+ assert.isTrue(
+ subView.relatedEventsToHighlight.equals(alert.associatedEvents));
+ this.addHTMLOutput(subView);
+
+ const table = tr.ui.b.findDeepElementMatching(
+ subView, 'tr-ui-b-table');
+
+ const rows = table.tableRows;
+ const columns = table.tableColumns;
+ assert.lengthOf(rows, 4);
+ assert.lengthOf(columns, 2);
+ });
+
+ test('instantiate_twoAlertsWithRelatedEvents', function() {
+ const slice1 = newSliceEx({title: 'b', start: 0, duration: 0.002});
+ const slice2 = newSliceEx({title: 'b', start: 1, duration: 0.002});
+
+ const alertInfo1 = new tr.model.EventInfo(
+ 'alertInfo1', 'Critical alert',
+ [{
+ label: 'Project Page',
+ textContent: 'Trace-Viewer Github Project',
+ href: 'https://github.com/google/trace-viewer/'
+ }]);
+
+ const alertInfo2 = new tr.model.EventInfo(
+ 'alertInfo2', 'Critical alert',
+ [{
+ label: 'Google Homepage',
+ textContent: 'Google Search Page',
+ href: 'http://www.google.com'
+ }]);
+
+ const alert1 = new tr.model.Alert(alertInfo1, 5, [slice1]);
+ const alert2 = new tr.model.Alert(alertInfo2, 5, [slice2]);
+
+ const subView = document.createElement('tr-ui-a-alert-sub-view');
+ subView.selection = new tr.model.EventSet([alert1, alert2]);
+ assert.isTrue(subView.relatedEventsToHighlight.equals(
+ new tr.model.EventSet([
+ tr.b.getOnlyElement(alert1.associatedEvents),
+ tr.b.getOnlyElement(alert2.associatedEvents)
+ ])));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_link.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_link.html
new file mode 100644
index 00000000000..8d996afeeb9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_link.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+
+<dom-module id='tr-ui-a-analysis-link'>
+ <template>
+ <style>
+ :host {
+ display: inline;
+ cursor: pointer;
+ cursor: pointer;
+ white-space: nowrap;
+ }
+ a {
+ text-decoration: underline;
+ }
+ </style>
+ <a href="{{href}}" on-click="onClicked_" on-mouseenter="onMouseEnter_" on-mouseleave="onMouseLeave_"><slot></slot></a>
+
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-analysis-link',
+
+ properties: {
+ href: {
+ type: String
+ }
+ },
+
+ listeners: {
+ 'click': 'onClicked_',
+ 'mouseenter': 'onMouseEnter_',
+ 'mouseleave': 'onMouseLeave_'
+ },
+
+ ready() {
+ this.selection_ = undefined;
+ },
+
+ attached() {
+ // Save an instance of the controller since it's going to be used in
+ // detached() where it can no longer be obtained.
+ this.controller_ =
+ tr.c.BrushingStateController.getControllerForElement(this);
+ },
+
+ detached() {
+ // Reset highlights.
+ this.clearHighlight_();
+ this.controller_ = undefined;
+ },
+
+ set color(c) {
+ this.style.color = c;
+ },
+
+ /**
+ * @return {*|function():*}
+ */
+ get selection() {
+ return this.selection_;
+ },
+
+ /**
+ * |selection| can be anything except a function, or else a function that
+ * can return anything.
+ *
+ * In the context of trace_viewer, |selection| is typically an EventSet,
+ * whose events will be highlighted by trace_viewer when this link is
+ * clicked or mouse-entered.
+ *
+ * If |selection| is not a function, then it will be dispatched to this
+ * link's embedder via a RequestSelectionChangeEvent when this link is
+ * clicked or mouse-entered.
+ *
+ * If |selection| is a function, then it will be called when this link is
+ * clicked or mouse-entered, and its result will be dispatched to this
+ * link's embedder via a RequestSelectionChangeEvent.
+ *
+ * @param {*|function():*} selection
+ */
+ set selection(selection) {
+ this.selection_ = selection;
+ Polymer.dom(this).textContent = selection.userFriendlyName;
+ },
+
+ setSelectionAndContent(selection, opt_textContent) {
+ this.selection_ = selection;
+ if (opt_textContent) {
+ Polymer.dom(this).textContent = opt_textContent;
+ }
+ },
+
+ /**
+ * If |selection| is a function, call it and return the result.
+ * Otherwise return |selection| directly.
+ *
+ * @return {*}
+ */
+ getCurrentSelection_() {
+ // Gets the current selection, invoking the selection function if needed.
+ if (typeof this.selection_ === 'function') {
+ return this.selection_();
+ }
+ return this.selection_;
+ },
+
+ setHighlight_(opt_eventSet) {
+ if (this.controller_) {
+ this.controller_.changeAnalysisLinkHoveredEvents(opt_eventSet);
+ }
+ },
+
+ clearHighlight_(opt_eventSet) {
+ this.setHighlight_();
+ },
+
+ onClicked_(clickEvent) {
+ if (!this.selection_) return;
+
+ clickEvent.stopPropagation();
+
+ const event = new tr.model.RequestSelectionChangeEvent();
+ event.selection = this.getCurrentSelection_();
+ this.dispatchEvent(event);
+ },
+
+ onMouseEnter_() {
+ this.setHighlight_(this.getCurrentSelection_());
+ },
+
+ onMouseLeave_() {
+ this.clearHighlight_();
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_link_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_link_test.html
new file mode 100644
index 00000000000..e8caed8f601
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_link_test.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('testBasic', function() {
+ const link = document.createElement('tr-ui-a-analysis-link');
+
+ const i10 = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'name', 10);
+ const s10 = i10.addSnapshot(10, {foo: 1});
+
+ link.selection = new tr.model.EventSet(s10);
+ this.addHTMLOutput(link);
+
+ let didRSC = false;
+ link.addEventListener('requestSelectionChange', function(e) {
+ didRSC = true;
+ assert.isTrue(e.selection.equals(new tr.model.EventSet(s10)));
+ });
+ link.click();
+ assert.isTrue(didRSC);
+ });
+
+ test('testGeneratorVersion', function() {
+ const link = document.createElement('tr-ui-a-analysis-link');
+
+ const i10 = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'name', 10);
+ const s10 = i10.addSnapshot(10, {foo: 1});
+
+ function selectionGenerator() {
+ return new tr.model.EventSet(s10);
+ }
+ selectionGenerator.userFriendlyName = 'hello world';
+ link.selection = selectionGenerator;
+ this.addHTMLOutput(link);
+
+ let didRSC = false;
+ link.addEventListener('requestSelectionChange', function(e) {
+ assert.isTrue(e.selection.equals(new tr.model.EventSet(s10)));
+ didRSC = true;
+ });
+ link.click();
+ assert.isTrue(didRSC);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_sub_view.html
new file mode 100644
index 00000000000..8bd967c8c75
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_sub_view.html
@@ -0,0 +1,266 @@
+<!DOCTYPE html>
+<!--
+Copyright 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+
+<!--
+@fileoverview Polymer element for various analysis sub-views.
+-->
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const AnalysisSubView = {
+ set tabLabel(label) {
+ Polymer.dom(this).setAttribute('tab-label', label);
+ },
+
+ get tabLabel() {
+ return this.getAttribute('tab-label');
+ },
+
+ get requiresTallView() {
+ return false;
+ },
+
+ get relatedEventsToHighlight() {
+ return undefined;
+ },
+
+ /**
+ * Each element extending this one must implement
+ * a 'selection' property.
+ */
+ set selection(selection) {
+ throw new Error('Not implemented!');
+ },
+
+ get selection() {
+ throw new Error('Not implemented!');
+ }
+ };
+
+ // Basic registry.
+ const allTypeInfosByEventProto = new Map();
+ let onlyRootTypeInfosByEventProto = undefined;
+ let eventProtoToRootTypeInfoMap = undefined;
+
+ function AnalysisSubViewTypeInfo(eventConstructor, options) {
+ if (options.multi === undefined) {
+ throw new Error('missing field: multi');
+ }
+ if (options.title === undefined) {
+ throw new Error('missing field: title');
+ }
+ this.eventConstructor = eventConstructor;
+
+ this.singleTagName = undefined;
+ this.singleTitle = undefined;
+
+ this.multiTagName = undefined;
+ this.multiTitle = undefined;
+
+ // This is computed by rebuildRootSubViewTypeInfos, so don't muck with it!
+ this.childrenTypeInfos_ = undefined;
+ }
+
+ AnalysisSubViewTypeInfo.prototype = {
+ get childrenTypeInfos() {
+ return this.childrenTypeInfos_;
+ },
+
+ resetchildrenTypeInfos() {
+ this.childrenTypeInfos_ = [];
+ }
+ };
+
+ AnalysisSubView.register = function(tagName, eventConstructor, options) {
+ let typeInfo = allTypeInfosByEventProto.get(eventConstructor.prototype);
+ if (typeInfo === undefined) {
+ typeInfo = new AnalysisSubViewTypeInfo(eventConstructor, options);
+ allTypeInfosByEventProto.set(typeInfo.eventConstructor.prototype,
+ typeInfo);
+
+ onlyRootTypeInfosByEventProto = undefined;
+ }
+
+ if (!options.multi) {
+ if (typeInfo.singleTagName !== undefined) {
+ throw new Error('SingleTagName already set');
+ }
+ typeInfo.singleTagName = tagName;
+ typeInfo.singleTitle = options.title;
+ } else {
+ if (typeInfo.multiTagName !== undefined) {
+ throw new Error('MultiTagName already set');
+ }
+ typeInfo.multiTagName = tagName;
+ typeInfo.multiTitle = options.title;
+ }
+ return typeInfo;
+ };
+
+ function rebuildRootSubViewTypeInfos() {
+ onlyRootTypeInfosByEventProto = new Map();
+ allTypeInfosByEventProto.forEach(function(typeInfo) {
+ typeInfo.resetchildrenTypeInfos();
+ });
+
+ // Find all root typeInfos.
+ allTypeInfosByEventProto.forEach(function(typeInfo, eventProto) {
+ const eventPrototype = typeInfo.eventConstructor.prototype;
+
+ let lastEventProto = eventPrototype;
+ let curEventProto = eventPrototype.__proto__;
+ while (true) {
+ if (!allTypeInfosByEventProto.has(curEventProto)) {
+ const rootTypeInfo = allTypeInfosByEventProto.get(lastEventProto);
+ const rootEventProto = lastEventProto;
+
+ const isNew = onlyRootTypeInfosByEventProto.has(rootEventProto);
+ onlyRootTypeInfosByEventProto.set(rootEventProto,
+ rootTypeInfo);
+ break;
+ }
+
+ lastEventProto = curEventProto;
+ curEventProto = curEventProto.__proto__;
+ }
+ });
+
+ // Build the childrenTypeInfos array.
+ allTypeInfosByEventProto.forEach(function(typeInfo, eventProto) {
+ const eventPrototype = typeInfo.eventConstructor.prototype;
+ const parentEventProto = eventPrototype.__proto__;
+ const parentTypeInfo = allTypeInfosByEventProto.get(parentEventProto);
+ if (!parentTypeInfo) return;
+ parentTypeInfo.childrenTypeInfos.push(typeInfo);
+ });
+
+ // Build the eventProto to rootTypeInfo map.
+ eventProtoToRootTypeInfoMap = new Map();
+ allTypeInfosByEventProto.forEach(function(typeInfo, eventProto) {
+ const eventPrototype = typeInfo.eventConstructor.prototype;
+
+ let curEventProto = eventPrototype;
+ while (true) {
+ if (onlyRootTypeInfosByEventProto.has(curEventProto)) {
+ const rootTypeInfo = onlyRootTypeInfosByEventProto.get(
+ curEventProto);
+ eventProtoToRootTypeInfoMap.set(eventPrototype,
+ rootTypeInfo);
+ break;
+ }
+ curEventProto = curEventProto.__proto__;
+ }
+ });
+ }
+
+ function findLowestTypeInfoForEvents(thisTypeInfo, events) {
+ if (events.length === 0) return thisTypeInfo;
+ const event0 = tr.b.getFirstElement(events);
+
+ let candidateSubTypeInfo;
+ for (let i = 0; i < thisTypeInfo.childrenTypeInfos.length; i++) {
+ const childTypeInfo = thisTypeInfo.childrenTypeInfos[i];
+ if (event0 instanceof childTypeInfo.eventConstructor) {
+ candidateSubTypeInfo = childTypeInfo;
+ break;
+ }
+ }
+ if (!candidateSubTypeInfo) return thisTypeInfo;
+
+ // Validate that all the other events are instances of the candidate type.
+ let allMatch = true;
+ for (const event of events) {
+ if (event instanceof candidateSubTypeInfo.eventConstructor) continue;
+ allMatch = false;
+ break;
+ }
+
+ if (!allMatch) {
+ return thisTypeInfo;
+ }
+
+ return findLowestTypeInfoForEvents(candidateSubTypeInfo, events);
+ }
+
+ const primaryEventProtoToTypeInfoMap = new Map();
+ function getRootTypeInfoForEvent(event) {
+ const curProto = event.__proto__;
+ const typeInfo = primaryEventProtoToTypeInfoMap.get(curProto);
+ if (typeInfo) return typeInfo;
+ return getRootTypeInfoForEventSlow(event);
+ }
+
+ function getRootTypeInfoForEventSlow(event) {
+ let typeInfo;
+ let curProto = event.__proto__;
+ while (true) {
+ if (curProto === Object.prototype) {
+ throw new Error('No view registered for ' + event.toString());
+ }
+ typeInfo = onlyRootTypeInfosByEventProto.get(curProto);
+ if (typeInfo) {
+ primaryEventProtoToTypeInfoMap.set(event.__proto__, typeInfo);
+ return typeInfo;
+ }
+ curProto = curProto.__proto__;
+ }
+ }
+
+ AnalysisSubView.getEventsOrganizedByTypeInfo = function(selection) {
+ if (onlyRootTypeInfosByEventProto === undefined) {
+ rebuildRootSubViewTypeInfos();
+ }
+
+ // Base grouping.
+ const eventsByRootTypeInfo = tr.b.groupIntoMap(
+ selection,
+ function(event) {
+ return getRootTypeInfoForEvent(event);
+ },
+ this, tr.model.EventSet);
+
+ // Now, try to lower the typeinfo to the most specific type that still
+ // encompasses the event group.
+ //
+ // For instance, if we have 3 ThreadSlices, and all three are V8 slices,
+ // then we can convert this to use the V8Slices's typeinfos. But, if one
+ // of those slices was not a V8Slice, then we must still use
+ // ThreadSlice.
+ //
+ // The reason for this is for the confusion that might arise from the
+ // alternative. Suppose you click on a set of mixed slices, we want to show
+ // you the most correct information, and let you navigate to . If we instead
+ // showed you a V8 slices tab, and a Slices tab, we present the user with an
+ // ambiguity: is the V8 slice also in the Slices tab? Or is it not? Better,
+ // we think, to just only ever show an event in one place at a time, and
+ // avoid the possible confusion.
+ const eventsByLowestTypeInfo = new Map();
+ eventsByRootTypeInfo.forEach(function(events, typeInfo) {
+ const lowestTypeInfo = findLowestTypeInfoForEvents(typeInfo, events);
+ eventsByLowestTypeInfo.set(lowestTypeInfo, events);
+ });
+
+ return eventsByLowestTypeInfo;
+ };
+
+ return {
+ AnalysisSubView,
+ AnalysisSubViewTypeInfo,
+ };
+});
+
+// Dummy element for testing
+Polymer({
+ is: 'tr-ui-a-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView]
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_sub_view_test.html
new file mode 100644
index 00000000000..0f3e85ea4ec
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_sub_view_test.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('subViewThrowsNotImplementedErrors', function() {
+ const subView = document.createElement('tr-ui-a-sub-view');
+
+ assert.throw(function() {
+ subView.selection = new tr.model.EventSet();
+ }, 'Not implemented!');
+
+ assert.throw(function() {
+ const viewSelection = subView.selection;
+ }, 'Not implemented!');
+
+ subView.tabLabel = 'Tab Label';
+ assert.strictEqual(subView.getAttribute('tab-label'), 'Tab Label');
+ assert.strictEqual(subView.tabLabel, 'Tab Label');
+
+ subView.tabLabel = 'New Label';
+ assert.strictEqual(subView.getAttribute('tab-label'), 'New Label');
+ assert.strictEqual(subView.tabLabel, 'New Label');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_view.html
new file mode 100644
index 00000000000..edc14edca11
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_view.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/alert_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/container_memory_dump_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/counter_sample_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_async_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_cpu_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_flow_event_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_frame_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/multi_instant_event_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_object_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_power_sample_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_sample_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_thread_slice_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/multi_thread_time_slice_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/multi_user_expectation_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_async_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_cpu_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_flow_event_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_frame_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/single_instant_event_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/single_object_instance_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/single_object_snapshot_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/single_power_sample_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_sample_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/single_thread_slice_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/single_thread_time_slice_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/single_user_expectation_sub_view.html">
+<link rel="import" href="/tracing/ui/base/tab_view.html">
+
+<!--
+@fileoverview A component used to display an analysis of a selection,
+using custom elements specialized for different event types.
+-->
+<dom-module id='tr-ui-a-analysis-view'>
+ <template>
+ <style>
+ :host {
+ background-color: white;
+ display: flex;
+ flex-direction: column;
+ height: 275px;
+ overflow: auto;
+ }
+
+ :host(.tall-mode) {
+ height: 525px;
+ }
+ </style>
+ <slot></slot>
+ </template>
+</dom-module>
+<script>
+'use strict';
+(function() {
+ const EventRegistry = tr.model.EventRegistry;
+
+ /** Returns the label that goes next to the list of tabs. */
+ function getTabStripLabel(numEvents) {
+ if (numEvents === 0) {
+ return 'Nothing selected. Tap stuff.';
+ } else if (numEvents === 1) {
+ return '1 item selected.';
+ }
+ return numEvents + ' items selected.';
+ }
+
+ function createSubView(subViewTypeInfo, selection) {
+ let tagName;
+ if (selection.length === 1) {
+ tagName = subViewTypeInfo.singleTagName;
+ } else {
+ tagName = subViewTypeInfo.multiTagName;
+ }
+
+ if (tagName === undefined) {
+ throw new Error('No view registered for ' +
+ subViewTypeInfo.eventConstructor.name);
+ }
+ const subView = document.createElement(tagName);
+
+ let title;
+ if (selection.length === 1) {
+ title = subViewTypeInfo.singleTitle;
+ } else {
+ title = subViewTypeInfo.multiTitle;
+ }
+ title += ' (' + selection.length + ')';
+ subView.tabLabel = title;
+
+ subView.selection = selection;
+ return subView;
+ }
+
+ Polymer({
+ is: 'tr-ui-a-analysis-view',
+
+ ready() {
+ this.brushingStateController_ = undefined;
+ this.lastSelection_ = undefined;
+ this.tabView_ = document.createElement('tr-ui-b-tab-view');
+ this.tabView_.addEventListener(
+ 'selected-tab-change', this.onSelectedSubViewChanged_.bind(this));
+
+ Polymer.dom(this).appendChild(this.tabView_);
+ },
+
+ set tallMode(value) {
+ Polymer.dom(this).classList.toggle('tall-mode', value);
+ },
+
+ get tallMode() {
+ return Polymer.dom(this).classList.contains('tall-mode');
+ },
+
+ get tabView() {
+ return this.tabView_;
+ },
+
+ get brushingStateController() {
+ return this.brushingStateController_;
+ },
+
+ set brushingStateController(brushingStateController) {
+ if (this.brushingStateController_) {
+ this.brushingStateController_.removeEventListener(
+ 'change', this.onSelectionChanged_.bind(this));
+ }
+
+ this.brushingStateController_ = brushingStateController;
+ if (this.brushingStateController) {
+ this.brushingStateController_.addEventListener(
+ 'change', this.onSelectionChanged_.bind(this));
+ }
+
+ // The new brushing controller may have a different selection than the
+ // last one, so we have to refresh the subview.
+ this.onSelectionChanged_();
+ },
+
+ get selection() {
+ return this.brushingStateController_.selection;
+ },
+
+ onSelectionChanged_(e) {
+ if (this.lastSelection_ && this.selection.equals(this.lastSelection_)) {
+ return;
+ }
+ this.lastSelection_ = this.selection;
+
+ this.tallMode = false;
+
+ this.tabView_.label = getTabStripLabel(this.selection.length);
+ const eventsByBaseTypeName =
+ this.selection.getEventsOrganizedByBaseType(true);
+
+ const ASV = tr.ui.analysis.AnalysisSubView;
+ const eventsByTagName = ASV.getEventsOrganizedByTypeInfo(this.selection);
+ const newSubViews = [];
+ eventsByTagName.forEach(function(events, typeInfo) {
+ newSubViews.push(createSubView(typeInfo, events));
+ });
+
+ this.tabView_.resetSubViews(newSubViews);
+ },
+
+ onSelectedSubViewChanged_() {
+ const selectedSubView = this.tabView_.selectedSubView;
+
+ if (!selectedSubView) {
+ this.tallMode = false;
+ this.maybeChangeRelatedEvents_(undefined);
+ return;
+ }
+
+ this.tallMode = selectedSubView.requiresTallView;
+ this.maybeChangeRelatedEvents_(selectedSubView.relatedEventsToHighlight);
+ },
+
+ /** Changes the highlighted related events if possible. */
+ maybeChangeRelatedEvents_(events) {
+ if (this.brushingStateController) {
+ this.brushingStateController.changeAnalysisViewRelatedEvents(events);
+ }
+ }
+ });
+})();
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_view_test.html
new file mode 100644
index 00000000000..fa7b51256a6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/analysis_view_test.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/counter.html">
+<link rel="import" href="/tracing/model/counter_sample.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/user_model/stub_expectation.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+<link rel="import" href="/tracing/ui/extras/full_config.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventSet = tr.model.EventSet;
+ const BrushingStateController = tr.c.BrushingStateController;
+ const Model = tr.Model;
+ const Counter = tr.model.Counter;
+ const CounterSeries = tr.model.CounterSeries;
+ const CounterSample = tr.model.CounterSample;
+ const newThreadSlice = tr.c.TestUtils.newThreadSlice;
+ const SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
+ const StubExpectation = tr.model.um.StubExpectation;
+
+ function assertEventSet(actualEventSet, expectedEvents) {
+ const expectedEventSet = new EventSet(expectedEvents);
+ assert.isTrue(actualEventSet.equals(expectedEventSet),
+ 'EventSet objects are not equal');
+ }
+
+ function checkTab(tab, expectedTagName, expectedSelectionEvents) {
+ assert.strictEqual(tab.tagName, expectedTagName.toUpperCase());
+ assertEventSet(tab.selection, expectedSelectionEvents);
+ }
+
+ test('selectedTabChange', function() {
+ // Set up the model.
+ const model = new Model();
+ const process = model.getOrCreateProcess(1);
+
+ const counter = process.getOrCreateCounter('universe', 'planets');
+ const series = counter.addSeries(new CounterSeries('x', 0));
+ const sample1 = series.addCounterSample(0, 100);
+ const sample2 = series.addCounterSample(1, 90);
+ const sample3 = series.addCounterSample(2, 80);
+
+ const thread = process.getOrCreateThread(2);
+ const slice1 = newThreadSlice(thread, SCHEDULING_STATE.RUNNING, 0, 1);
+ const slice2 = newThreadSlice(thread, SCHEDULING_STATE.SLEEPING, 1, 2.718);
+ thread.timeSlices = [slice1, slice2];
+
+ const record1 = new StubExpectation(
+ {parentModel: model, initiatorTitle: 'r1', start: 200, duration: 300});
+ record1.associatedEvents.push(sample1);
+ record1.associatedEvents.push(slice1);
+ const record2 = new StubExpectation(
+ {parentModel: model, initiatorTitle: 'r2', start: 600, duration: 100});
+ record2.associatedEvents.push(sample2);
+ record2.associatedEvents.push(sample3);
+ record2.associatedEvents.push(slice1);
+
+ // Set up the analysis views and brushing state controller.
+ const analysisView = document.createElement('tr-ui-a-analysis-view');
+ this.addHTMLOutput(analysisView);
+ const tabView = analysisView.tabView;
+ const controller = new BrushingStateController(undefined);
+ analysisView.brushingStateController = controller;
+
+ function checkSelectedTab(expectedSelectedTab, expectedRelatedEvents) {
+ assert.strictEqual(tabView.selectedSubView, expectedSelectedTab);
+ assertEventSet(controller.currentBrushingState.analysisViewRelatedEvents,
+ expectedRelatedEvents);
+ }
+
+ // 1. Empty selection (implicit).
+ assert.lengthOf(tabView.tabs, 0);
+ checkSelectedTab(undefined, []);
+
+ // 2. Event selection: two samples and one thread slice.
+ controller.changeSelectionFromRequestSelectionChangeEvent(
+ new EventSet([sample1, slice1, sample2]));
+ assert.lengthOf(tabView.tabs, 2);
+ const sampleTab2 = tabView.tabs[0];
+ checkTab(sampleTab2,
+ 'tr-ui-a-counter-sample-sub-view',
+ [sample1, sample2]);
+ const singleThreadSliceTab2 = tabView.tabs[1];
+ checkTab(singleThreadSliceTab2,
+ 'tr-ui-a-single-thread-time-slice-sub-view',
+ [slice1]);
+ // First tab should be selected.
+ checkSelectedTab(sampleTab2, []);
+
+ // 3. Tab selection: single thread slice tab.
+ tabView.selectedSubView = singleThreadSliceTab2;
+ checkSelectedTab(singleThreadSliceTab2, []);
+
+ // 4. Event selection: one sample, two thread slices, and one
+ // user expectation.
+ controller.changeSelectionFromRequestSelectionChangeEvent(
+ new EventSet([slice1, slice2, sample3, record1]));
+ assert.lengthOf(tabView.tabs, 3);
+ const sampleTab4 = tabView.tabs[1];
+ checkTab(sampleTab4,
+ 'tr-ui-a-counter-sample-sub-view',
+ [sample3]);
+ const singleRecordTab4 = tabView.tabs[2];
+ checkTab(singleRecordTab4,
+ 'tr-ui-a-single-user-expectation-sub-view',
+ [record1]);
+ const multiThreadSliceTab4 = tabView.tabs[0];
+ checkTab(multiThreadSliceTab4,
+ 'tr-ui-a-multi-thread-time-slice-sub-view',
+ [slice1, slice2]);
+ // Remember selected tab (even though the tab was destroyed).
+ checkSelectedTab(multiThreadSliceTab4, []);
+
+ // 5. Tab selection: single user expectation tab.
+ tabView.selectedSubView = singleRecordTab4;
+ checkSelectedTab(singleRecordTab4, [sample1, slice1]);
+
+ // 6. Event selection: one user expectation.
+ controller.changeSelectionFromRequestSelectionChangeEvent(
+ new EventSet([record2]));
+ assert.lengthOf(tabView.tabs, 1);
+ const singleRecordTab6 = tabView.tabs[0];
+ checkTab(singleRecordTab6,
+ 'tr-ui-a-single-user-expectation-sub-view',
+ [record2]);
+ // Remember selected tab.
+ checkSelectedTab(singleRecordTab6, [sample2, sample3, slice1]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view.html
new file mode 100644
index 00000000000..cc0e9155358
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_header_pane.html">
+<link rel="import" href="/tracing/ui/analysis/stacked_pane_view.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-container-memory-dump-sub-view'>
+ <template>
+ <style>
+ tr-ui-b-table {
+ font-size: 12px;
+ }
+ </style>
+ <div id="content"></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ Polymer({
+ is: 'tr-ui-a-container-memory-dump-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ set selection(selection) {
+ if (selection === undefined) {
+ this.currentSelection_ = undefined;
+ this.dumpsByContainerName_ = undefined;
+ this.updateContents_();
+ return;
+ }
+
+ // Check that the selection contains only container memory dumps.
+ selection.forEach(function(event) {
+ if (!(event instanceof tr.model.ContainerMemoryDump)) {
+ throw new Error(
+ 'Memory dump sub-view only supports container memory dumps');
+ }
+ });
+ this.currentSelection_ = selection;
+
+ // Group the selected memory dumps by container name and sort them
+ // chronologically.
+ this.dumpsByContainerName_ = tr.b.groupIntoMap(
+ this.currentSelection_.toArray(), dump => dump.containerName);
+ for (const dumps of this.dumpsByContainerName_.values()) {
+ dumps.sort((a, b) => a.start - b.start);
+ }
+
+ this.updateContents_();
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ get requiresTallView() {
+ return true;
+ },
+
+ updateContents_() {
+ Polymer.dom(this.$.content).textContent = '';
+
+ if (this.dumpsByContainerName_ === undefined) return;
+
+ const containerNames = Array.from(this.dumpsByContainerName_.keys());
+ if (containerNames.length === 0) return;
+
+ if (containerNames.length > 1) {
+ this.buildViewForMultipleContainerNames_();
+ } else {
+ this.buildViewForSingleContainerName_();
+ }
+ },
+
+ buildViewForSingleContainerName_() {
+ const containerMemoryDumps = tr.b.getFirstElement(
+ this.dumpsByContainerName_.values());
+ const dumpView = this.ownerDocument.createElement(
+ 'tr-ui-a-stacked-pane-view');
+ Polymer.dom(this.$.content).appendChild(dumpView);
+ dumpView.setPaneBuilder(function() {
+ const headerPane = document.createElement(
+ 'tr-ui-a-memory-dump-header-pane');
+ headerPane.containerMemoryDumps = containerMemoryDumps;
+ return headerPane;
+ });
+ },
+
+ buildViewForMultipleContainerNames_() {
+ // TODO(petrcermak): Provide a more sophisticated view for this case.
+ const ownerDocument = this.ownerDocument;
+
+ const rows = [];
+ for (const [containerName, dumps] of this.dumpsByContainerName_) {
+ rows.push({
+ containerName,
+ subRows: dumps,
+ isExpanded: true,
+ });
+ }
+ rows.sort(function(a, b) {
+ return a.containerName.localeCompare(b.containerName);
+ });
+
+ const columns = [
+ {
+ title: 'Dump',
+
+ value(row) {
+ if (row.subRows === undefined) {
+ return this.singleDumpValue_(row);
+ }
+ return this.groupedDumpValue_(row);
+ },
+
+ singleDumpValue_(row) {
+ const linkEl = ownerDocument.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(new tr.model.EventSet([row]));
+ Polymer.dom(linkEl).appendChild(tr.v.ui.createScalarSpan(
+ row.start, {
+ unit: tr.b.Unit.byName.timeStampInMs,
+ ownerDocument
+ }));
+ return linkEl;
+ },
+
+ groupedDumpValue_(row) {
+ const linkEl = ownerDocument.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(new tr.model.EventSet(row.subRows));
+ Polymer.dom(linkEl).appendChild(tr.ui.b.createSpan({
+ ownerDocument,
+ textContent: row.subRows.length + ' memory dump' +
+ (row.subRows.length === 1 ? '' : 's') + ' in '
+ }));
+ Polymer.dom(linkEl).appendChild(tr.ui.b.createSpan({
+ ownerDocument,
+ textContent: row.containerName,
+ bold: true
+ }));
+ return linkEl;
+ }
+ }
+ ];
+
+ const table = this.ownerDocument.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.showHeader = false;
+ table.rebuild();
+ Polymer.dom(this.$.content).appendChild(table);
+ }
+ });
+
+ tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-container-memory-dump-sub-view',
+ tr.model.GlobalMemoryDump,
+ {
+ multi: false,
+ title: 'Global Memory Dump',
+ });
+
+ tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-container-memory-dump-sub-view',
+ tr.model.GlobalMemoryDump,
+ {
+ multi: true,
+ title: 'Global Memory Dumps',
+ });
+
+ tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-container-memory-dump-sub-view',
+ tr.model.ProcessMemoryDump,
+ {
+ multi: false,
+ title: 'Process Memory Dump',
+ });
+
+ tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-container-memory-dump-sub-view',
+ tr.model.ProcessMemoryDump,
+ {
+ multi: true,
+ title: 'Process Memory Dumps',
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html
new file mode 100644
index 00000000000..974837f545e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/container_memory_dump_sub_view_test.html
@@ -0,0 +1,351 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import"
+ href="/tracing/ui/analysis/container_memory_dump_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/memory_dump_sub_view_test_utils.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventSet = tr.model.EventSet;
+ const extractVmRegions = tr.ui.analysis.extractVmRegions;
+ const extractMemoryAllocatorDumps =
+ tr.ui.analysis.extractMemoryAllocatorDumps;
+ const extractHeapDumps = tr.ui.analysis.extractHeapDumps;
+
+ function createViewWithSelection(selection, opt_parentElement) {
+ const viewEl = document.createElement(
+ 'tr-ui-a-container-memory-dump-sub-view');
+ if (opt_parentElement) {
+ Polymer.dom(opt_parentElement).appendChild(viewEl);
+ }
+ if (selection === undefined) {
+ viewEl.selection = undefined;
+ } else {
+ // Rotate the list of selected dumps to check that the sub-view sorts
+ // them properly.
+ const length = selection.length;
+ viewEl.selection = new tr.model.EventSet(
+ selection.slice(length / 2, length).concat(
+ selection.slice(0, length / 2)));
+ }
+ return viewEl;
+ }
+
+ function createAndCheckContainerMemoryDumpView(
+ test, containerMemoryDumps, detailsCheckCallback, opt_parentElement) {
+ const viewEl =
+ createViewWithSelection(containerMemoryDumps, opt_parentElement);
+ if (!opt_parentElement) {
+ test.addHTMLOutput(viewEl);
+ }
+
+ // The view should contain a stacked pane view with memory dump header and
+ // overview panes.
+ const stackedPaneViewEl = tr.ui.b.findDeepElementMatching(
+ viewEl, 'tr-ui-a-stacked-pane-view');
+ const headerPaneEl = tr.ui.b.findDeepElementMatching(
+ stackedPaneViewEl, 'tr-ui-a-memory-dump-header-pane');
+ const overviewPaneEl = tr.ui.b.findDeepElementMatching(
+ stackedPaneViewEl, 'tr-ui-a-memory-dump-overview-pane');
+
+ // Check that the header pane and overview pane are correctly set up.
+ const processMemoryDumps = containerMemoryDumps.map(
+ containerDump => containerDump.processMemoryDumps);
+ assert.deepEqual(
+ Array.from(headerPaneEl.containerMemoryDumps), containerMemoryDumps);
+ assert.deepEqual(overviewPaneEl.processMemoryDumps, processMemoryDumps);
+ assert.strictEqual(
+ overviewPaneEl.aggregationMode, headerPaneEl.aggregationMode);
+
+ // Get the overview pane table to drive the details pane checks.
+ const overviewTableEl = tr.ui.b.findDeepElementMatching(
+ overviewPaneEl, 'tr-ui-b-table');
+
+ function checkVmRegionsPane(pid) {
+ const detailsPaneEl = tr.ui.b.findDeepElementMatching(
+ stackedPaneViewEl, 'tr-ui-a-memory-dump-vm-regions-details-pane');
+ if (pid === undefined) {
+ assert.isUndefined(detailsPaneEl);
+ } else {
+ assert.deepEqual(Array.from(detailsPaneEl.vmRegions),
+ extractVmRegions(processMemoryDumps, pid));
+ assert.strictEqual(
+ detailsPaneEl.aggregationMode, headerPaneEl.aggregationMode);
+ }
+ }
+
+ function checkAllocatorPane(pid, allocatorName, withHeapDetailsPane) {
+ const allocatorDetailsPaneEl = tr.ui.b.findDeepElementMatching(
+ stackedPaneViewEl, 'tr-ui-a-memory-dump-allocator-details-pane');
+ if (pid === undefined) {
+ assert.isUndefined(allocatorDetailsPaneEl);
+ assert.isUndefined(allocatorName); // Test sanity check.
+ assert.isUndefined(withHeapDetailsPane); // Test sanity check.
+ return;
+ }
+
+ assert.deepEqual(
+ Array.from(allocatorDetailsPaneEl.memoryAllocatorDumps),
+ extractMemoryAllocatorDumps(processMemoryDumps, pid, allocatorName));
+ assert.strictEqual(
+ allocatorDetailsPaneEl.aggregationMode, headerPaneEl.aggregationMode);
+
+ const heapDetailsPaneEl = tr.ui.b.findDeepElementMatching(
+ stackedPaneViewEl, 'tr-ui-a-memory-dump-heap-details-pane');
+ if (!withHeapDetailsPane) {
+ assert.isUndefined(heapDetailsPaneEl);
+ return;
+ }
+
+ assert.deepEqual(Array.from(heapDetailsPaneEl.heapDumps),
+ extractHeapDumps(processMemoryDumps, pid, allocatorName));
+ assert.strictEqual(
+ heapDetailsPaneEl.aggregationMode, headerPaneEl.aggregationMode);
+ }
+
+ detailsCheckCallback(
+ overviewTableEl, checkVmRegionsPane, checkAllocatorPane);
+ }
+
+ test('instantiate_empty', function() {
+ // All these views should be completely empty.
+ const unsetViewEl = document.createElement(
+ 'tr-ui-a-container-memory-dump-sub-view');
+ this.addHTMLOutput(unsetViewEl);
+ assert.strictEqual(unsetViewEl.getBoundingClientRect().width, 0);
+ assert.strictEqual(unsetViewEl.getBoundingClientRect().height, 0);
+
+ const undefinedViewEl = createViewWithSelection(undefined);
+ this.addHTMLOutput(undefinedViewEl);
+ assert.strictEqual(undefinedViewEl.getBoundingClientRect().width, 0);
+ assert.strictEqual(undefinedViewEl.getBoundingClientRect().height, 0);
+
+ const emptyViewEl = createViewWithSelection([]);
+ this.addHTMLOutput(emptyViewEl);
+ assert.strictEqual(emptyViewEl.getBoundingClientRect().width, 0);
+ assert.strictEqual(emptyViewEl.getBoundingClientRect().height, 0);
+ });
+
+ test('instantiate_singleGlobalMemoryDump', function() {
+ createAndCheckContainerMemoryDumpView(this,
+ [tr.ui.analysis.createSingleTestGlobalMemoryDump()],
+ function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) {
+ // Nothing should be selected initially.
+ assert.isUndefined(overviewTableEl.selectedTableRow);
+ assert.isUndefined(overviewTableEl.selectedColumnIndex);
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(undefined);
+
+ // Total resident of Process 1.
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0];
+ overviewTableEl.selectedColumnIndex = 1;
+ checkVmRegionsPane(1 /* PID */);
+ checkAllocatorPane(undefined);
+
+ // PSS of process 4.
+ overviewTableEl.selectedColumnIndex = 3;
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[2];
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(undefined);
+
+ // Malloc of process 2.
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[1];
+ overviewTableEl.selectedColumnIndex = 10;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(2 /* PID */, 'malloc',
+ false /* no heap details pane */);
+ });
+ });
+
+ test('instantiate_multipleGlobalMemoryDumps', function() {
+ createAndCheckContainerMemoryDumpView(this,
+ tr.ui.analysis.createMultipleTestGlobalMemoryDumps(),
+ function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) {
+ // Nothing should be selected initially.
+ assert.isUndefined(overviewTableEl.selectedTableRow);
+ assert.isUndefined(overviewTableEl.selectedColumnIndex);
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(undefined);
+
+ // Blink of Process 1.
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0];
+ overviewTableEl.selectedColumnIndex = 8;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(undefined);
+
+ // Peak total resident of Process 4.
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[3];
+ overviewTableEl.selectedColumnIndex = 2;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(undefined);
+
+ // V8 of Process 3.
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[2];
+ overviewTableEl.selectedColumnIndex = 12;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(3 /* PID */, 'v8', true /* heap details pane */);
+ });
+ });
+
+ test('instantiate_singleProcessMemoryDump', function() {
+ createAndCheckContainerMemoryDumpView(this,
+ [tr.ui.analysis.createSingleTestProcessMemoryDump()],
+ function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) {
+ // Nothing should be selected initially.
+ assert.isUndefined(overviewTableEl.selectedTableRow);
+ assert.isUndefined(overviewTableEl.selectedColumnIndex);
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(undefined);
+
+ // Tracing of Process 2.
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0];
+ overviewTableEl.selectedColumnIndex = 13;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(2 /* PID */, 'tracing',
+ false /* no heap details pane */);
+
+ // Blink of Process 2.
+ overviewTableEl.selectedColumnIndex = 8;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(2 /* PID */, 'blink',
+ false /* no heap details pane */);
+
+ // Total resident of Process 2.
+ overviewTableEl.selectedColumnIndex = 1;
+ checkVmRegionsPane(2 /* PID */);
+ checkAllocatorPane(undefined);
+ });
+ });
+
+ test('instantiate_multipleProcessMemoryDumps', function() {
+ createAndCheckContainerMemoryDumpView(this,
+ tr.ui.analysis.createMultipleTestProcessMemoryDumps(),
+ function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) {
+ // Nothing should be selected initially.
+ assert.isUndefined(overviewTableEl.selectedTableRow);
+ assert.isUndefined(overviewTableEl.selectedColumnIndex);
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(undefined);
+
+ // Tracing of Process 2.
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0];
+ overviewTableEl.selectedColumnIndex = 13;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(2 /* PID */, 'tracing',
+ false /* no heap details pane */);
+
+ // V8 of Process 2.
+ overviewTableEl.selectedColumnIndex = 12;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(2 /* PID */, 'v8',
+ false /* no heap details pane */);
+
+ // PSS of Process 2.
+ overviewTableEl.selectedColumnIndex = 3;
+ checkVmRegionsPane(2 /* PID */);
+ checkAllocatorPane(undefined);
+ });
+ });
+
+ test('memory', function() {
+ const containerEl = document.createElement('div');
+ containerEl.brushingStateController =
+ new tr.c.BrushingStateController(undefined);
+
+ // Create the first container memory view.
+ createAndCheckContainerMemoryDumpView(this,
+ [tr.ui.analysis.createSingleTestProcessMemoryDump()],
+ function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) {
+ // Nothing should be selected initially.
+ assert.isUndefined(overviewTableEl.selectedTableRow);
+ assert.isUndefined(overviewTableEl.selectedColumnIndex);
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(undefined);
+
+ // Select V8 of Process 2.
+ overviewTableEl.selectedTableRow = overviewTableEl.tableRows[0];
+ overviewTableEl.selectedColumnIndex = 12;
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(2 /* PID */, 'v8',
+ false /* no heap details pane */);
+ }, containerEl);
+
+ // Destroy the first container memory view.
+ Polymer.dom(containerEl).textContent = '';
+
+ // Create the second container memory view.
+ createAndCheckContainerMemoryDumpView(this,
+ tr.ui.analysis.createMultipleTestGlobalMemoryDumps(),
+ function(overviewTableEl, checkVmRegionsPane, checkAllocatorPane) {
+ // V8 of Process 2 should still be selected (even though the selection
+ // changed).
+ assert.strictEqual(
+ overviewTableEl.selectedTableRow, overviewTableEl.tableRows[1]);
+ assert.strictEqual(overviewTableEl.selectedColumnIndex, 12);
+ checkVmRegionsPane(undefined);
+ checkAllocatorPane(2 /* PID */, 'v8',
+ false /* no heap details pane */);
+ }, containerEl);
+ });
+
+ test('instantiate_differentProcessMemoryDumps', function() {
+ const globalMemoryDumps =
+ tr.ui.analysis.createMultipleTestGlobalMemoryDumps();
+ // 2 dumps in Process 1, 3 dumps in Process 2, and 1 dump in Process 4
+ // (intentionally shuffled to check sorting).
+ const differentProcessDumps = [
+ globalMemoryDumps[1].processMemoryDumps[2],
+ globalMemoryDumps[0].processMemoryDumps[1],
+ globalMemoryDumps[0].processMemoryDumps[2],
+ globalMemoryDumps[1].processMemoryDumps[4],
+ globalMemoryDumps[1].processMemoryDumps[1],
+ globalMemoryDumps[2].processMemoryDumps[2]
+ ];
+
+ const viewEl = createViewWithSelection(differentProcessDumps);
+ this.addHTMLOutput(viewEl);
+
+ const tableEl = tr.ui.b.findDeepElementMatching(viewEl, 'tr-ui-b-table');
+ assert.lengthOf(tableEl.tableRows, 3);
+ assert.lengthOf(tableEl.tableColumns, 1);
+ const rows = tableEl.tableRows;
+ const col = tableEl.tableColumns[0];
+
+ assert.strictEqual(Polymer.dom(col.value(rows[0])).textContent,
+ '2 memory dumps in Process 1');
+ assert.strictEqual(Polymer.dom(col.value(rows[1])).textContent,
+ '3 memory dumps in Process 2');
+ assert.strictEqual(Polymer.dom(col.value(rows[2])).textContent,
+ '1 memory dump in Process 4');
+
+ // Check that the analysis link is associated with the right dumps.
+ assert.isTrue(col.value(rows[1]).selection.equals(new tr.model.EventSet([
+ globalMemoryDumps[0].processMemoryDumps[2],
+ globalMemoryDumps[1].processMemoryDumps[2],
+ globalMemoryDumps[2].processMemoryDumps[2]
+ ])));
+
+ assert.lengthOf(rows[1].subRows, 3);
+ const subRow = rows[1].subRows[0];
+
+ // Check the timestamp.
+ assert.strictEqual(col.value(subRow).children[0].value, 42);
+
+ // Check that the analysis link is associated with the right dump.
+ assert.isTrue(col.value(subRow).selection.equals(
+ new tr.model.EventSet(globalMemoryDumps[0].processMemoryDumps[2])));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/counter_sample_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/counter_sample_sub_view.html
new file mode 100644
index 00000000000..a9275b19d0c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/counter_sample_sub_view.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-a-counter-sample-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ tr-ui-b-table {
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id='table'></tr-ui-b-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+(function() {
+ const COUNTER_SAMPLE_TABLE_COLUMNS = [
+ {
+ title: 'Counter',
+ width: '150px',
+ value(row) { return row.counter; }
+ },
+ {
+ title: 'Series',
+ width: '150px',
+ value(row) { return row.series; }
+ },
+ {
+ title: 'Time',
+ width: '150px',
+ value(row) { return row.start; }
+ },
+ {
+ title: 'Value',
+ width: '100%',
+ value(row) { return row.value; }
+ }
+ ];
+
+ Polymer({
+ is: 'tr-ui-a-counter-sample-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ ready() {
+ this.currentSelection_ = undefined;
+ this.$.table.tableColumns = COUNTER_SAMPLE_TABLE_COLUMNS;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ this.$.table.tableRows =
+ this.selection ? this.getRows_(this.selection.toArray()) : [];
+ this.$.table.rebuild();
+ },
+
+ /**
+ * Returns the table rows for the specified samples.
+ *
+ * We print each counter/series combination the first time that it
+ * appears. For subsequent samples in each series, we omit the counter
+ * and series name. This makes it easy to scan to find the next series.
+ *
+ * Each series can be collapsed. In the expanded state, all samples
+ * are shown. In the collapsed state, only the first sample is displayed.
+ */
+ getRows_(samples) {
+ const samplesByCounter = tr.b.groupIntoMap(
+ samples, sample => sample.series.counter.guid);
+
+ const rows = [];
+ for (const counterSamples of samplesByCounter.values()) {
+ const samplesBySeries = tr.b.groupIntoMap(
+ counterSamples, sample => sample.series.guid);
+
+ for (const seriesSamples of samplesBySeries.values()) {
+ const seriesRows = this.getRowsForSamples_(seriesSamples);
+ seriesRows[0].counter = seriesSamples[0].series.counter.name;
+ seriesRows[0].series = seriesSamples[0].series.name;
+
+ if (seriesRows.length > 1) {
+ seriesRows[0].subRows = seriesRows.slice(1);
+ seriesRows[0].isExpanded = true;
+ }
+
+ rows.push(seriesRows[0]);
+ }
+ }
+
+ return rows;
+ },
+
+ getRowsForSamples_(samples) {
+ return samples.map(function(sample) {
+ return {
+ start: sample.timestamp,
+ value: sample.value
+ };
+ });
+ }
+ });
+
+ tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-counter-sample-sub-view',
+ tr.model.CounterSample,
+ {
+ multi: false,
+ title: 'Counter Sample',
+ });
+
+ tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-counter-sample-sub-view',
+ tr.model.CounterSample,
+ {
+ multi: true,
+ title: 'Counter Samples',
+ });
+})();
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/counter_sample_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/counter_sample_sub_view_test.html
new file mode 100644
index 00000000000..9d7fa370313
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/counter_sample_sub_view_test.html
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/counter.html">
+<link rel="import" href="/tracing/model/counter_series.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/counter_sample_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Counter = tr.model.Counter;
+ const CounterSeries = tr.model.CounterSeries;
+ const EventSet = tr.model.EventSet;
+
+ test('instantiate_undefinedSelection', function() {
+ const analysisEl = document.createElement(
+ 'tr-ui-a-counter-sample-sub-view');
+ analysisEl.selection = new EventSet(undefined);
+
+ assert.lengthOf(analysisEl.$.table.tableRows, 0);
+ });
+
+ test('instantiate_oneCounterOneSeries', function() {
+ const series = new CounterSeries('series1', 0);
+ series.addCounterSample(0, 0);
+ series.addCounterSample(1, 10);
+
+ const counter = new Counter(null, 0, 'cat', 'ctr1');
+ counter.addSeries(series);
+
+ const analysisEl = document.createElement(
+ 'tr-ui-a-counter-sample-sub-view');
+ analysisEl.selection = new EventSet(series.samples);
+ this.addHTMLOutput(analysisEl);
+
+ // The first sample should be listed as a collapsible header row for the
+ // series.
+ const rows = analysisEl.$.table.tableRows;
+ assert.lengthOf(rows, 1);
+ assert.isTrue(rows[0].isExpanded);
+ assert.strictEqual(rows[0].counter, 'ctr1');
+ assert.strictEqual(rows[0].series, 'series1');
+ assert.strictEqual(rows[0].start, 0);
+ assert.strictEqual(rows[0].value, 0);
+
+ // The second sample should be listed as a subrow of the first.
+ const subRows = rows[0].subRows;
+ assert.lengthOf(subRows, 1);
+ assert.isUndefined(subRows[0].counter);
+ assert.isUndefined(subRows[0].series);
+ assert.strictEqual(subRows[0].start, 1);
+ assert.strictEqual(subRows[0].value, 10);
+ });
+
+ test('instantiate_singleSampleDoesntHaveSubrows', function() {
+ const series = new CounterSeries('series1', 0);
+ series.addCounterSample(0, 0);
+
+ const counter = new Counter(null, 0, 'cat', 'ctr1');
+ counter.addSeries(series);
+
+ const analysisEl = document.createElement(
+ 'tr-ui-a-counter-sample-sub-view');
+ analysisEl.selection = new EventSet(series.samples);
+ this.addHTMLOutput(analysisEl);
+
+ // The first sample should be listed as a collapsible header row for the
+ // series.
+ const rows = analysisEl.$.table.tableRows;
+ assert.lengthOf(rows, 1);
+ assert.strictEqual(rows[0].counter, 'ctr1');
+ assert.strictEqual(rows[0].series, 'series1');
+ assert.strictEqual(rows[0].start, 0);
+ assert.strictEqual(rows[0].value, 0);
+ assert.isUndefined(rows[0].subRows);
+ });
+
+ test('instantiate_oneCounterTwoSeries', function() {
+ const series1 = new CounterSeries('series1', 0);
+ series1.addCounterSample(1, 10);
+ series1.addCounterSample(2, 20);
+
+ const series2 = new CounterSeries('series2', 0);
+ series2.addCounterSample(3, 30);
+
+ const counter = new Counter(null, 0, 'cat', 'ctr1');
+ counter.addSeries(series1);
+ counter.addSeries(series2);
+
+ const analysisEl = document.createElement(
+ 'tr-ui-a-counter-sample-sub-view');
+ analysisEl.selection =
+ new EventSet(series1.samples.concat(series2.samples));
+ this.addHTMLOutput(analysisEl);
+
+ // The first samples should be listed as collapsible header rows for the
+ // series.
+ const rows = analysisEl.$.table.tableRows;
+ assert.lengthOf(rows, 2);
+ assert.strictEqual(rows[0].counter, 'ctr1');
+ assert.strictEqual(rows[0].series, 'series1');
+ assert.strictEqual(rows[0].start, 1);
+ assert.strictEqual(rows[0].value, 10);
+
+ assert.strictEqual(rows[1].counter, 'ctr1');
+ assert.strictEqual(rows[1].series, 'series2');
+ assert.strictEqual(rows[1].start, 3);
+ assert.strictEqual(rows[1].value, 30);
+
+ // The subsequent samples should be listed as subrows of the first.
+ const subRows1 = rows[0].subRows;
+ assert.lengthOf(subRows1, 1);
+ assert.isUndefined(subRows1[0].counter);
+ assert.isUndefined(subRows1[0].series);
+ assert.strictEqual(subRows1[0].start, 2);
+ assert.strictEqual(subRows1[0].value, 20);
+
+ assert.isUndefined(rows[1].subRows);
+ });
+
+ test('instantiate_twoCountersTwoSeries', function() {
+ const series1 = new CounterSeries('series1', 0);
+ series1.addCounterSample(1, 10);
+
+ const series2 = new CounterSeries('series2', 0);
+ series2.addCounterSample(2, 20);
+
+ const counter1 = new Counter(null, 0, 'cat', 'ctr1');
+ const counter2 = new Counter(null, 0, 'cat', 'ctr2');
+ counter1.addSeries(series1);
+ counter2.addSeries(series2);
+
+ const analysisEl = document.createElement(
+ 'tr-ui-a-counter-sample-sub-view');
+ analysisEl.selection =
+ new EventSet(series1.samples.concat(series2.samples));
+ this.addHTMLOutput(analysisEl);
+
+ // Each sample should be a header row with no subrows.
+ const rows = analysisEl.$.table.tableRows;
+ assert.lengthOf(rows, 2);
+ assert.strictEqual(rows[0].counter, 'ctr1');
+ assert.strictEqual(rows[0].series, 'series1');
+ assert.strictEqual(rows[0].start, 1);
+ assert.strictEqual(rows[0].value, 10);
+ assert.isUndefined(rows[0].subRows);
+
+ assert.strictEqual(rows[1].counter, 'ctr2');
+ assert.strictEqual(rows[1].series, 'series2');
+ assert.strictEqual(rows[1].start, 2);
+ assert.strictEqual(rows[1].value, 20);
+ assert.isUndefined(rows[1].subRows);
+ });
+
+ test('instantiate_contentsClearedEachSelection', function() {
+ const series = new CounterSeries('series1', 0);
+ series.addCounterSample(0, 0);
+
+ const counter = new Counter(null, 0, 'cat', 'ctr1');
+ counter.addSeries(series);
+
+ const analysisEl = document.createElement(
+ 'tr-ui-a-counter-sample-sub-view');
+ analysisEl.selection = new EventSet(series.samples);
+ analysisEl.selection = new EventSet(series.samples);
+ this.addHTMLOutput(analysisEl);
+
+ assert.lengthOf(analysisEl.$.table.tableRows, 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/flow_classifier.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/flow_classifier.html
new file mode 100644
index 00000000000..1773a09f32f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/flow_classifier.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const FLOW_IN = 0x1;
+ const FLOW_OUT = 0x2;
+ const FLOW_IN_OUT = FLOW_IN | FLOW_OUT;
+
+ function FlowClassifier() {
+ this.numEvents_ = 0;
+ this.eventsByGUID_ = {};
+ }
+
+ FlowClassifier.prototype = {
+ getFS_(event) {
+ let fs = this.eventsByGUID_[event.guid];
+ if (fs === undefined) {
+ this.numEvents_++;
+ fs = {
+ state: 0,
+ event
+ };
+ this.eventsByGUID_[event.guid] = fs;
+ }
+ return fs;
+ },
+
+ addInFlow(event) {
+ const fs = this.getFS_(event);
+ fs.state |= FLOW_IN;
+ return event;
+ },
+
+ addOutFlow(event) {
+ const fs = this.getFS_(event);
+ fs.state |= FLOW_OUT;
+ return event;
+ },
+
+ hasEvents() {
+ return this.numEvents_ > 0;
+ },
+
+ get inFlowEvents() {
+ const selection = new tr.model.EventSet();
+ for (const guid in this.eventsByGUID_) {
+ const fs = this.eventsByGUID_[guid];
+ if (fs.state === FLOW_IN) {
+ selection.push(fs.event);
+ }
+ }
+ return selection;
+ },
+
+ get outFlowEvents() {
+ const selection = new tr.model.EventSet();
+ for (const guid in this.eventsByGUID_) {
+ const fs = this.eventsByGUID_[guid];
+ if (fs.state === FLOW_OUT) {
+ selection.push(fs.event);
+ }
+ }
+ return selection;
+ },
+
+ get internalFlowEvents() {
+ const selection = new tr.model.EventSet();
+ for (const guid in this.eventsByGUID_) {
+ const fs = this.eventsByGUID_[guid];
+ if (fs.state === FLOW_IN_OUT) {
+ selection.push(fs.event);
+ }
+ }
+ return selection;
+ }
+ };
+
+ return {
+ FlowClassifier,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/flow_classifier_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/flow_classifier_test.html
new file mode 100644
index 00000000000..ba68f671b57
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/flow_classifier_test.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/flow_classifier.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newFlowEventEx = tr.c.TestUtils.newFlowEventEx;
+
+ test('basic', function() {
+ const a = newFlowEventEx({
+ title: 'a', start: 0, end: 10 });
+ const b = newFlowEventEx({
+ title: 'b', start: 10, end: 20 });
+ const c = newFlowEventEx({
+ title: 'c', start: 20, end: 25 });
+ const d = newFlowEventEx({
+ title: 'd', start: 30, end: 35 });
+
+ const fc = new tr.ui.analysis.FlowClassifier();
+ fc.addInFlow(a);
+
+ fc.addInFlow(b);
+ fc.addOutFlow(b);
+
+ fc.addInFlow(c);
+ fc.addOutFlow(c);
+
+ fc.addOutFlow(d);
+
+ function asSortedArray(selection) {
+ const events = Array.from(selection);
+ events.sort(function(a, b) {
+ return a.guid - b.guid;
+ });
+ return events;
+ }
+
+ assert.deepEqual(Array.from(fc.inFlowEvents), [a]);
+ assert.deepEqual(Array.from(fc.outFlowEvents), [d]);
+ assert.deepEqual(Array.from(fc.internalFlowEvents), [b, c]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart.html
new file mode 100644
index 00000000000..bc3f4fcead8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/base/line_chart.html">
+
+<!--
+@fileoverview A line chart showing milliseconds since the start of the frame on
+the x-axis and power consumption on the y-axis. Each frame is shown as a
+separate line in the chart. Vertical sync events are used as the start of each
+frame.
+
+This chart aims to help users understand the shape of the power consumption
+curve over the course of a frame or set of frames.
+-->
+<dom-module id='tr-ui-a-frame-power-usage-chart'>
+ <template>
+ <div id="content"></div>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+const EventSet = tr.model.EventSet;
+
+const CHART_TITLE = 'Power (W) by ms since vertical sync';
+
+Polymer({
+ is: 'tr-ui-a-frame-power-usage-chart',
+
+ ready() {
+ this.chart_ = undefined;
+ this.samples_ = new EventSet();
+ this.vSyncTimestamps_ = [];
+ },
+
+ attached() {
+ if (this.samples_) this.updateContents_();
+ },
+
+ get chart() {
+ return this.chart_;
+ },
+
+ get samples() {
+ return this.samples_;
+ },
+
+ get vSyncTimestamps() {
+ return this.vSyncTimestamps_;
+ },
+
+ /**
+ * Sets the data that powers the chart. Vsync timestamps must be in
+ * chronological order.
+ */
+ setData(samples, vSyncTimestamps) {
+ this.samples_ = (samples === undefined) ? new EventSet() : samples;
+ this.vSyncTimestamps_ =
+ (vSyncTimestamps === undefined) ? [] : vSyncTimestamps;
+ if (this.isAttached) this.updateContents_();
+ },
+
+ updateContents_() {
+ this.clearChart_();
+
+ const data = this.getDataForLineChart_();
+
+ if (data.length === 0) return;
+
+ this.chart_ = new tr.ui.b.LineChart();
+ Polymer.dom(this.$.content).appendChild(this.chart_);
+ this.chart_.chartTitle = CHART_TITLE;
+ this.chart_.data = data;
+ },
+
+ clearChart_() {
+ const content = this.$.content;
+ while (Polymer.dom(content).firstChild) {
+ Polymer.dom(content).removeChild(Polymer.dom(content).firstChild);
+ }
+
+ this.chart_ = undefined;
+ },
+
+ // TODO(charliea): Limit the ms since vsync to the median frame length. The
+ // vertical syncs are not 100% regular and highlighting any sample that's
+ // in one of these 'vertical sync lulls' makes the x-axis have a much larger
+ // scale than it should, effectively squishing the other samples into the
+ // left side of the chart.
+ /**
+ * Returns an array of data points for the chart. Each element in the array
+ * is of the form { x: <ms since vsync>, f<frame#>: <power in mW> }.
+ */
+ getDataForLineChart_() {
+ const sortedSamples = this.sortSamplesByTimestampAscending_(this.samples);
+ const vSyncTimestamps = this.vSyncTimestamps.slice();
+
+ let lastVSyncTimestamp = undefined;
+ const points = [];
+
+ // For each power sample, find and record the frame number that it belongs
+ // to as well as the amount of time elapsed since that frame began.
+ let frameNumber = 0;
+ sortedSamples.forEach(function(sample) {
+ while (vSyncTimestamps.length > 0 && vSyncTimestamps[0] <= sample.start) {
+ lastVSyncTimestamp = vSyncTimestamps.shift();
+ frameNumber++;
+ }
+
+ // If no vertical sync occurred before the power sample, don't use the
+ // power sample.
+ if (lastVSyncTimestamp === undefined) return;
+
+ const point = { x: sample.start - lastVSyncTimestamp };
+ point['f' + frameNumber] = sample.powerInW;
+ points.push(point);
+ });
+
+ return points;
+ },
+
+ sortSamplesByTimestampAscending_(samples) {
+ return samples.toArray().sort(function(smpl1, smpl2) {
+ return smpl1.start - smpl2.start;
+ });
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_perf_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_perf_test.html
new file mode 100644
index 00000000000..caf4601f33c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_perf_test.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_sample.html">
+<link rel="import" href="/tracing/model/power_series.html">
+<link rel="import" href="/tracing/ui/analysis/frame_power_usage_chart.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function instantiateManyFrames() {
+ const model = new tr.Model();
+ const numFrames = 200;
+ const samplesPerFrame = 200;
+
+ // Set up the test data.
+ const series = new tr.model.PowerSeries(model.device);
+ const vsyncTimestamps = [];
+ for (let i = 0; i < numFrames; i++) {
+ vsyncTimestamps.push(i * samplesPerFrame);
+ for (let j = 0; j < samplesPerFrame; j++) {
+ series.addPowerSample(vsyncTimestamps[i] + j, j);
+ }
+ }
+ const samples = series.samples;
+
+ // Display the chart.
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(samples), vsyncTimestamps);
+ this.addHTMLOutput(chart);
+ }
+
+ timedPerfTest('frame_power_usage_chart', instantiateManyFrames, {
+ iterations: 1
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html
new file mode 100644
index 00000000000..04ba9388852
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/frame_power_usage_chart_test.html
@@ -0,0 +1,267 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_sample.html">
+<link rel="import" href="/tracing/model/power_series.html">
+<link rel="import" href="/tracing/ui/analysis/frame_power_usage_chart.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate_noSamples', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(undefined, [0]);
+
+ assert.isUndefined(chart.chart);
+ });
+
+ test('instantiate_noVSyncs', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), []);
+
+ assert.isUndefined(chart.chart);
+ });
+
+ test('instantiate_noSamplesOrVSyncs', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(undefined, []);
+
+ assert.isUndefined(chart.chart);
+ });
+
+ test('instantiate_oneFrame', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const vSyncTimestamps = [0];
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), vSyncTimestamps);
+
+ this.addHTMLOutput(chart);
+
+ const expectedChartData = [
+ { x: 0, f1: 1 },
+ { x: 1, f1: 2 },
+ { x: 2, f1: 3 },
+ { x: 3, f1: 2 }
+ ];
+ assert.sameDeepMembers(chart.chart.data, expectedChartData);
+ });
+
+ test('instantiate_twoFrames', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const vSyncTimestamps = [0, 4];
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+ series.addPowerSample(4, 2);
+ series.addPowerSample(5, 3);
+ series.addPowerSample(6, 4);
+ series.addPowerSample(7, 3);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), vSyncTimestamps);
+
+ this.addHTMLOutput(chart);
+
+ const expectedChartData = [
+ { x: 0, f1: 1 },
+ { x: 1, f1: 2 },
+ { x: 2, f1: 3 },
+ { x: 3, f1: 2 },
+ { x: 0, f2: 2 },
+ { x: 1, f2: 3 },
+ { x: 2, f2: 4 },
+ { x: 3, f2: 3 }
+ ];
+ assert.sameDeepMembers(chart.chart.data, expectedChartData);
+ });
+
+ test('instantiate_twoFramesDifferentXValues', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ // Power samples taken at 0, 1, 2, and 3s after frame start.
+ const vSyncTimestamps = [0, 4];
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+ // Power samples taken at 0.5, 1.5, 2.5, and 3.5s after frame start.
+ series.addPowerSample(4.5, 2);
+ series.addPowerSample(5.5, 3);
+ series.addPowerSample(6.5, 4);
+ series.addPowerSample(7.5, 3);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), vSyncTimestamps);
+
+ this.addHTMLOutput(chart);
+
+ const expectedChartData = [
+ { x: 0, f1: 1 },
+ { x: 1, f1: 2 },
+ { x: 2, f1: 3 },
+ { x: 3, f1: 2 },
+ { x: 0.5, f2: 2 },
+ { x: 1.5, f2: 3 },
+ { x: 2.5, f2: 4 },
+ { x: 3.5, f2: 3 }
+ ];
+ assert.sameDeepMembers(chart.chart.data, expectedChartData);
+ });
+
+ test('instantiate_samplesBeforeFirstVSync', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const vSyncTimestamps = [4];
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+ series.addPowerSample(4, 2);
+ series.addPowerSample(5, 3);
+ series.addPowerSample(6, 4);
+ series.addPowerSample(7, 3);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), vSyncTimestamps);
+
+ this.addHTMLOutput(chart);
+
+ const expectedChartData = [
+ { x: 0, f1: 2 },
+ { x: 1, f1: 3 },
+ { x: 2, f1: 4 },
+ { x: 3, f1: 3 }
+ ];
+ assert.sameDeepMembers(chart.chart.data, expectedChartData);
+ });
+
+ test('instantiate_allSamplesBeforeFirstVSync', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const vSyncTimestamps = [4];
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), vSyncTimestamps);
+
+ const expectedChartData = [
+ { x: 0, f1: 2 },
+ { x: 1, f1: 3 },
+ { x: 2, f1: 4 },
+ { x: 3, f1: 3 }
+ ];
+ assert.isUndefined(chart.chart);
+ });
+
+ test('instantiate_vSyncsAfterLastPowerSample', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const vSyncTimestamps = [0, 4, 8, 12];
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+ series.addPowerSample(4, 2);
+ series.addPowerSample(5, 3);
+ series.addPowerSample(6, 4);
+ series.addPowerSample(7, 3);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), vSyncTimestamps);
+
+ this.addHTMLOutput(chart);
+
+ const expectedChartData = [
+ { x: 0, f1: 1 },
+ { x: 1, f1: 2 },
+ { x: 2, f1: 3 },
+ { x: 3, f1: 2 },
+ { x: 0, f2: 2 },
+ { x: 1, f2: 3 },
+ { x: 2, f2: 4 },
+ { x: 3, f2: 3 }
+ ];
+ assert.sameDeepMembers(chart.chart.data, expectedChartData);
+ });
+
+ test('instantiate_onlyVSyncAfterLastPowerSample', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const vSyncTimestamps = [8];
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+ series.addPowerSample(4, 2);
+ series.addPowerSample(5, 3);
+ series.addPowerSample(6, 4);
+ series.addPowerSample(7, 3);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), vSyncTimestamps);
+
+ assert.isUndefined(chart.chart);
+ });
+
+
+ test('instantiate_samplesNotInChronologicalOrder', function() {
+ const series = new tr.model.PowerSeries(new tr.Model().device);
+
+ const vSyncTimestamps = [0, 4];
+ series.addPowerSample(4, 2);
+ series.addPowerSample(5, 3);
+ series.addPowerSample(6, 4);
+ series.addPowerSample(7, 3);
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1, 2);
+ series.addPowerSample(2, 3);
+ series.addPowerSample(3, 2);
+
+ const chart = document.createElement('tr-ui-a-frame-power-usage-chart');
+ chart.setData(new tr.model.EventSet(series.samples), vSyncTimestamps);
+
+ this.addHTMLOutput(chart);
+
+ const expectedChartData = [
+ { x: 0, f1: 1 },
+ { x: 1, f1: 2 },
+ { x: 2, f1: 3 },
+ { x: 3, f1: 2 },
+ { x: 0, f2: 2 },
+ { x: 1, f2: 3 },
+ { x: 2, f2: 4 },
+ { x: 3, f2: 3 }
+ ];
+ assert.sameDeepMembers(chart.chart.data, expectedChartData);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html
new file mode 100644
index 00000000000..e0c33df1231
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view.html
@@ -0,0 +1,347 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+<link rel="import" href="/tracing/model/object_snapshot.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-generic-object-view'>
+ <template>
+ <style>
+ :host {
+ display: block;
+ font-family: monospace;
+ }
+ </style>
+ <div id="content">
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+function isTable(object) {
+ if (!(object instanceof Array) ||
+ (object.length < 2)) return false;
+ for (const colName in object[0]) {
+ if (typeof colName !== 'string') return false;
+ }
+ for (let i = 0; i < object.length; ++i) {
+ if (!(object[i] instanceof Object)) return false;
+ for (const colName in object[i]) {
+ if (i && (object[0][colName] === undefined)) return false;
+ const cellType = typeof object[i][colName];
+ if (cellType !== 'string' && cellType !== 'number') return false;
+ }
+ if (i) {
+ for (const colName in object[0]) {
+ if (object[i][colName] === undefined) return false;
+ }
+ }
+ }
+ return true;
+}
+
+Polymer({
+ is: 'tr-ui-a-generic-object-view',
+
+ ready() {
+ this.object_ = undefined;
+ },
+
+ get object() {
+ return this.object_;
+ },
+
+ set object(object) {
+ this.object_ = object;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ Polymer.dom(this.$.content).textContent = '';
+ this.appendElementsForType_('', this.object_, 0, 0, 5, '');
+ },
+
+ appendElementsForType_(
+ label, object, indent, depth, maxDepth, suffix) {
+ if (depth > maxDepth) {
+ this.appendSimpleText_(
+ label, indent, '<recursion limit reached>', suffix);
+ return;
+ }
+
+ if (object === undefined) {
+ this.appendSimpleText_(label, indent, 'undefined', suffix);
+ return;
+ }
+
+ if (object === null) {
+ this.appendSimpleText_(label, indent, 'null', suffix);
+ return;
+ }
+
+ if (!(object instanceof Object)) {
+ const type = typeof object;
+ if (type !== 'string') {
+ return this.appendSimpleText_(label, indent, object, suffix);
+ }
+ let objectReplaced = false;
+ if ((object[0] === '{' && object[object.length - 1] === '}') ||
+ (object[0] === '[' && object[object.length - 1] === ']')) {
+ try {
+ object = JSON.parse(object);
+ objectReplaced = true;
+ } catch (e) {
+ }
+ }
+ if (!objectReplaced) {
+ if (object.includes('\n')) {
+ const lines = object.split('\n');
+ lines.forEach(function(line, i) {
+ let text;
+ let ioff;
+ let ll;
+ let ss;
+ if (i === 0) {
+ text = '"' + line;
+ ioff = 0;
+ ll = label;
+ ss = '';
+ } else if (i < lines.length - 1) {
+ text = line;
+ ioff = 1;
+ ll = '';
+ ss = '';
+ } else {
+ text = line + '"';
+ ioff = 1;
+ ll = '';
+ ss = suffix;
+ }
+
+ const el = this.appendSimpleText_(
+ ll, indent + ioff * label.length + ioff, text, ss);
+ el.style.whiteSpace = 'pre';
+ return el;
+ }, this);
+ return;
+ }
+ if (tr.b.isUrl(object)) {
+ const link = document.createElement('a');
+ link.href = object;
+ link.textContent = object;
+ this.appendElementWithLabel_(label, indent, link, suffix);
+ return;
+ }
+ this.appendSimpleText_(
+ label, indent, '"' + object + '"', suffix);
+ return;
+ }
+ }
+
+ if (object instanceof tr.model.ObjectSnapshot) {
+ const link = document.createElement('tr-ui-a-analysis-link');
+ link.selection = new tr.model.EventSet(object);
+ this.appendElementWithLabel_(label, indent, link, suffix);
+ return;
+ }
+
+ if (object instanceof tr.model.ObjectInstance) {
+ const link = document.createElement('tr-ui-a-analysis-link');
+ link.selection = new tr.model.EventSet(object);
+ this.appendElementWithLabel_(label, indent, link, suffix);
+ return;
+ }
+
+ if (object instanceof tr.b.math.Rect) {
+ this.appendSimpleText_(label, indent, object.toString(), suffix);
+ return;
+ }
+
+ if (object instanceof tr.b.Scalar) {
+ const el = this.ownerDocument.createElement('tr-v-ui-scalar-span');
+ el.value = object;
+ el.inline = true;
+ this.appendElementWithLabel_(label, indent, el, suffix);
+ return;
+ }
+
+ if (object instanceof Array) {
+ this.appendElementsForArray_(
+ label, object, indent, depth, maxDepth, suffix);
+ return;
+ }
+
+ this.appendElementsForObject_(
+ label, object, indent, depth, maxDepth, suffix);
+ },
+
+ appendElementsForArray_(
+ label, object, indent, depth, maxDepth, suffix) {
+ if (object.length === 0) {
+ this.appendSimpleText_(label, indent, '[]', suffix);
+ return;
+ }
+
+ if (isTable(object)) {
+ const table = document.createElement('tr-ui-b-table');
+ const columns = [];
+ for (const colName of Object.keys(object[0])) {
+ let allStrings = true;
+ let allNumbers = true;
+ for (let i = 0; i < object.length; ++i) {
+ if (typeof(object[i][colName]) !== 'string') {
+ allStrings = false;
+ }
+
+ if (typeof(object[i][colName]) !== 'number') {
+ allNumbers = false;
+ }
+
+ if (!allStrings && !allNumbers) break;
+ }
+
+ const column = {title: colName};
+ column.value = function(row) {
+ return row[colName];
+ };
+
+ if (allStrings) {
+ column.cmp = function(x, y) {
+ return x[colName].localeCompare(y[colName]);
+ };
+ } else if (allNumbers) {
+ column.cmp = function(x, y) {
+ return x[colName] - y[colName];
+ };
+ }
+ columns.push(column);
+ }
+ table.tableColumns = columns;
+ table.tableRows = object;
+ this.appendElementWithLabel_(label, indent, table, suffix);
+ table.rebuild();
+ return;
+ }
+
+ this.appendElementsForType_(
+ label + '[',
+ object[0],
+ indent, depth + 1, maxDepth,
+ object.length > 1 ? ',' : ']' + suffix);
+ for (let i = 1; i < object.length; i++) {
+ this.appendElementsForType_(
+ '',
+ object[i],
+ indent + label.length + 1, depth + 1, maxDepth,
+ i < object.length - 1 ? ',' : ']' + suffix);
+ }
+ return;
+ },
+
+ appendElementsForObject_(
+ label, object, indent, depth, maxDepth, suffix) {
+ const keys = Object.keys(object);
+ if (keys.length === 0) {
+ this.appendSimpleText_(label, indent, '{}', suffix);
+ return;
+ }
+
+ this.appendElementsForType_(
+ label + '{' + keys[0] + ': ',
+ object[keys[0]],
+ indent, depth, maxDepth,
+ keys.length > 1 ? ',' : '}' + suffix);
+ for (let i = 1; i < keys.length; i++) {
+ this.appendElementsForType_(
+ keys[i] + ': ',
+ object[keys[i]],
+ indent + label.length + 1, depth + 1, maxDepth,
+ i < keys.length - 1 ? ',' : '}' + suffix);
+ }
+ },
+
+ appendElementWithLabel_(label, indent, dataElement, suffix) {
+ const row = document.createElement('div');
+
+ const indentSpan = document.createElement('span');
+ indentSpan.style.whiteSpace = 'pre';
+ for (let i = 0; i < indent; i++) {
+ Polymer.dom(indentSpan).textContent += ' ';
+ }
+ Polymer.dom(row).appendChild(indentSpan);
+
+ const labelSpan = document.createElement('span');
+ Polymer.dom(labelSpan).textContent = label;
+ Polymer.dom(row).appendChild(labelSpan);
+
+ Polymer.dom(row).appendChild(dataElement);
+ const suffixSpan = document.createElement('span');
+ Polymer.dom(suffixSpan).textContent = suffix;
+ Polymer.dom(row).appendChild(suffixSpan);
+
+ row.dataElement = dataElement;
+ Polymer.dom(this.$.content).appendChild(row);
+ },
+
+ appendSimpleText_(label, indent, text, suffix) {
+ const el = this.ownerDocument.createElement('span');
+ Polymer.dom(el).textContent = text;
+ this.appendElementWithLabel_(label, indent, el, suffix);
+ return el;
+ }
+});
+</script>
+
+<dom-module id='tr-ui-a-generic-object-view-with-label'>
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+ </style>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-generic-object-view-with-label',
+
+ ready() {
+ this.labelEl_ = document.createElement('div');
+ this.genericObjectView_ =
+ document.createElement('tr-ui-a-generic-object-view');
+ Polymer.dom(this.root).appendChild(this.labelEl_);
+ Polymer.dom(this.root).appendChild(this.genericObjectView_);
+ },
+
+ get label() {
+ return Polymer.dom(this.labelEl_).textContent;
+ },
+
+ set label(label) {
+ Polymer.dom(this.labelEl_).textContent = label;
+ },
+
+ get object() {
+ return this.genericObjectView_.object;
+ },
+
+ set object(object) {
+ this.genericObjectView_.object = object;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html
new file mode 100644
index 00000000000..2e7812e2730
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/generic_object_view_test.html
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/object_instance.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('undefinedValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = undefined;
+ assert.strictEqual(Polymer.dom(view.$.content).textContent, 'undefined');
+ });
+
+ test('nullValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = null;
+ assert.strictEqual(Polymer.dom(view.$.content).textContent, 'null');
+ });
+
+ test('stringValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = 'string value';
+ assert.strictEqual(
+ Polymer.dom(view.$.content).textContent, '"string value"');
+ });
+
+ test('multiLineStringValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = 'i am a\n string value\ni have\n various indents';
+ this.addHTMLOutput(view);
+ const c = view.$.content;
+ });
+
+ test('multiLineStringValueInsideObject', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = {key: 'i am a\n string value\ni have\n various indents',
+ value: 'simple'};
+ this.addHTMLOutput(view);
+ const c = view.$.content;
+ });
+
+ test('jsonObjectStringValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = '{"x": 1}';
+ assert.strictEqual(view.$.content.children.length, 1);
+ assert.strictEqual(view.$.content.children[0].children.length, 4);
+ });
+
+ test('jsonArrayStringValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = '[1,2,3]';
+ assert.strictEqual(view.$.content.children.length, 3);
+ });
+
+ test('booleanValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = false;
+ assert.strictEqual(Polymer.dom(view.$.content).textContent, 'false');
+ });
+
+ test('numberValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = 3.14159;
+ assert.strictEqual(Polymer.dom(view.$.content).textContent, '3.14159');
+ });
+
+ test('objectSnapshotValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+
+ const i10 = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'name', 10);
+ const s10 = i10.addSnapshot(10, {foo: 1});
+
+ view.object = s10;
+ this.addHTMLOutput(view);
+ assert.strictEqual(view.$.content.children[0].dataElement.tagName,
+ 'TR-UI-A-ANALYSIS-LINK');
+ });
+
+ test('objectInstanceValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+
+ const i10 = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'name', 10);
+ const s10 = i10.addSnapshot(10, {foo: 1});
+
+ view.object = i10;
+ assert.strictEqual(view.$.content.children[0].dataElement.tagName,
+ 'TR-UI-A-ANALYSIS-LINK');
+ });
+
+ test('instantiate_emptyArrayValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = [];
+ this.addHTMLOutput(view);
+ });
+
+ test('instantiate_twoValueArrayValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = [1, 2];
+ this.addHTMLOutput(view);
+ });
+
+ test('instantiate_twoValueBArrayValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = [1, {x: 1}];
+ this.addHTMLOutput(view);
+ });
+
+ test('instantiate_arrayValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = [1, 2, 'three'];
+ this.addHTMLOutput(view);
+ });
+
+ test('instantiate_arrayWithSimpleObjectValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = [{simple: 'object'}];
+ this.addHTMLOutput(view);
+ });
+
+ test('instantiate_arrayWithComplexObjectValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = [{col0: 'object', col1: 0},
+ {col2: 'Object', col3: 1}];
+ this.addHTMLOutput(view);
+ assert.strictEqual(undefined, tr.ui.b.findDeepElementMatching(
+ view.$.content, 'table'));
+ });
+
+ test('instantiate_arrayWithDeepObjectValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = [{key: {deep: 'object values make isTable() return false'}}];
+ this.addHTMLOutput(view);
+ assert.strictEqual(undefined, tr.ui.b.findDeepElementMatching(
+ view.$.content, 'table'));
+ });
+
+ test('jsonTableValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = [
+ {col0: 'object', col1: 0, col2: 'foo'},
+ {col0: 'Object', col1: 1, col2: 42}
+ ];
+ this.addHTMLOutput(view);
+
+ const table = tr.ui.b.findDeepElementMatching(
+ view.$.content, 'tr-ui-b-table');
+ assert.strictEqual('col0', table.tableColumns[0].title);
+ assert.strictEqual('col1', table.tableColumns[1].title);
+ assert.strictEqual(
+ 'object', table.tableColumns[0].value(table.tableRows[0]));
+ assert.strictEqual(
+ 'Object', table.tableColumns[0].value(table.tableRows[1]));
+ assert.strictEqual(0, table.tableColumns[1].value(table.tableRows[0]));
+ assert.strictEqual(1, table.tableColumns[1].value(table.tableRows[1]));
+ assert.isDefined(table.tableColumns[0].cmp);
+ assert.isDefined(table.tableColumns[1].cmp);
+ assert.isUndefined(table.tableColumns[2].cmp);
+ });
+
+ test('instantiate_objectValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = {
+ 'entry_one': 'entry_one_value',
+ 'entry_two': 2,
+ 'entry_three': [3, 4, 5]
+ };
+ this.addHTMLOutput(view);
+ });
+
+ test('timeDurationValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object =
+ new tr.b.Scalar(tr.b.Unit.byName.timeDurationInMs, 3);
+ this.addHTMLOutput(view);
+ assert.isDefined(tr.ui.b.findDeepElementMatching(
+ view.$.content, 'tr-v-ui-scalar-span'));
+ });
+
+ test('timeStampValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object = new tr.b.Scalar(tr.b.Unit.byName.timeStampInMs, 3);
+ this.addHTMLOutput(view);
+ assert.isDefined(tr.ui.b.findDeepElementMatching(
+ view.$.content, 'tr-v-ui-scalar-span'));
+ });
+
+ test('scalarValue', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ view.object =
+ new tr.b.Scalar(tr.b.Unit.byName.normalizedPercentage, .3);
+ this.addHTMLOutput(view);
+ const m = tr.ui.b.findDeepElementMatching(
+ view.$.content, 'tr-v-ui-scalar-span');
+ assert.isDefined(m);
+ assert.strictEqual(m.value, .3);
+ assert.strictEqual(m.unit, tr.b.Unit.byName.normalizedPercentage);
+ });
+
+ test('httpLink', function() {
+ const view = document.createElement('tr-ui-a-generic-object-view');
+ const url = 'https://google.com/chrome';
+ view.object = {a: url};
+ this.addHTMLOutput(view);
+ const a = tr.ui.b.findDeepElementMatching(view.$.content, 'a');
+ assert.isDefined(a);
+ assert.strictEqual(url, a.href);
+ assert.strictEqual(url, a.textContent);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html
new file mode 100644
index 00000000000..88b3c3ccc7c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html
@@ -0,0 +1,893 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_heap_details_pane.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/analysis/stacked_pane.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+
+<dom-module id='tr-ui-a-memory-dump-allocator-details-pane'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+
+ #label {
+ flex: 0 0 auto;
+ padding: 8px;
+
+ background-color: #eee;
+ border-bottom: 1px solid #8e8e8e;
+ border-top: 1px solid white;
+
+ font-size: 15px;
+ font-weight: bold;
+ }
+
+ #contents {
+ flex: 1 0 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+
+ #info_text {
+ padding: 8px;
+ color: #666;
+ font-style: italic;
+ text-align: center;
+ }
+
+ #table {
+ display: none; /* Hide until memory allocator dumps are set. */
+ flex: 1 0 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <div id="label">Component details</div>
+ <div id="contents">
+ <div id="info_text">No memory allocator dump selected</div>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ // Link to docs.
+ const URL_TO_SIZE_VS_EFFECTIVE_SIZE = 'https://chromium.googlesource.com/chromium/src/+/master/docs/memory-infra/README.md#effective_size-vs_size';
+
+ // Constant representing the context in suballocation rows.
+ const SUBALLOCATION_CONTEXT = true;
+
+ // Size numeric info types.
+ const MemoryAllocatorDumpInfoType = tr.model.MemoryAllocatorDumpInfoType;
+ const PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN =
+ MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN;
+ const PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER =
+ MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER;
+
+ // Unicode symbols used for memory cell info icons and messages.
+ const LEFTWARDS_OPEN_HEADED_ARROW = String.fromCharCode(0x21FD);
+ const RIGHTWARDS_OPEN_HEADED_ARROW = String.fromCharCode(0x21FE);
+ const EN_DASH = String.fromCharCode(0x2013);
+ const CIRCLED_LATIN_SMALL_LETTER_I = String.fromCharCode(0x24D8);
+
+ /** @constructor */
+ function AllocatorDumpNameColumn() {
+ tr.ui.analysis.TitleColumn.call(this, 'Component');
+ }
+
+ AllocatorDumpNameColumn.prototype = {
+ __proto__: tr.ui.analysis.TitleColumn.prototype,
+
+ formatTitle(row) {
+ if (!row.suballocation) {
+ return row.title;
+ }
+ return tr.ui.b.createSpan({
+ textContent: row.title,
+ italic: true,
+ tooltip: row.fullNames === undefined ?
+ undefined : row.fullNames.join(', ')
+ });
+ }
+ };
+
+ /**
+ * Retrieve the entry associated with a given name from a map and increment
+ * its count.
+ *
+ * If there is no entry associated with the name, a new entry is created, the
+ * creation callback is called, the entry's count is incremented (from 0 to
+ * 1) and the newly created entry is returned.
+ */
+ function getAndUpdateEntry(map, name, createdCallback) {
+ let entry = map.get(name);
+ if (entry === undefined) {
+ entry = {count: 0};
+ createdCallback(entry);
+ map.set(name, entry);
+ }
+ entry.count++;
+ return entry;
+ }
+
+ /**
+ * Helper class for building size and effective size column info messages.
+ *
+ * @constructor
+ */
+ function SizeInfoMessageBuilder() {
+ this.parts_ = [];
+ this.indent_ = 0;
+ }
+
+ SizeInfoMessageBuilder.prototype = {
+ append(/* arguments */) {
+ this.parts_.push.apply(
+ this.parts_, Array.prototype.slice.apply(arguments));
+ },
+
+ /**
+ * Append the entries of a map to the message according to the following
+ * rules:
+ *
+ * 1. If the map is empty, append emptyText to the message (if provided).
+ * Examples:
+ *
+ * emptyText=undefined
+ * Hello, World! ====================> Hello, World!
+ *
+ * emptyText='empty'
+ * The bottle is ====================> The bottle is empty
+ *
+ * 2. If the map contains a single entry, append a space and call
+ * itemCallback on the entry (which is in turn expected to append a
+ * message for the entry). Example:
+ *
+ * Please do not ====================> Please do not [item-message]
+ *
+ * 3. If the map contains multiple entries, append them as a list
+ * with itemCallback called on each entry. If hasPluralSuffix is true,
+ * 's' will be appended to the message before the list. Examples:
+ *
+ * hasPluralSuffix=false
+ * I need to buy ====================> I need to buy:
+ * - [item1-message]
+ * - [item2-message]
+ * [...]
+ * - [itemN-message]
+ *
+ * hasPluralSuffix=true
+ * Suspected CL ====================> Suspected CLs:
+ * - [item1-message]
+ * - [item2-message]
+ * [...]
+ * - [itemN-message]
+ */
+ appendMap(
+ map, hasPluralSuffix, emptyText, itemCallback, opt_this) {
+ opt_this = opt_this || this;
+ if (map.size === 0) {
+ if (emptyText) {
+ this.append(emptyText);
+ }
+ } else if (map.size === 1) {
+ this.parts_.push(' ');
+ const key = map.keys().next().value;
+ itemCallback.call(opt_this, key, map.get(key));
+ } else {
+ if (hasPluralSuffix) {
+ this.parts_.push('s');
+ }
+ this.parts_.push(':');
+ this.indent_++;
+ for (const key of map.keys()) {
+ this.parts_.push('\n', ' '.repeat(3 * (this.indent_ - 1)), ' - ');
+ itemCallback.call(opt_this, key, map.get(key));
+ }
+ this.indent_--;
+ }
+ },
+
+ appendImportanceRange(range) {
+ this.append(' (importance: ');
+ if (range.min === range.max) {
+ this.append(range.min);
+ } else {
+ this.append(range.min, EN_DASH, range.max);
+ }
+ this.append(')');
+ },
+
+ appendSizeIfDefined(size) {
+ if (size !== undefined) {
+ this.append(' (', tr.b.Unit.byName.sizeInBytes.format(size), ')');
+ }
+ },
+
+ appendSomeTimestampsQuantifier() {
+ this.append(
+ ' ', tr.ui.analysis.MemoryColumn.SOME_TIMESTAMPS_INFO_QUANTIFIER);
+ },
+
+ build() {
+ return this.parts_.join('');
+ }
+ };
+
+ /** @constructor */
+ function EffectiveSizeColumn(name, cellPath, aggregationMode) {
+ tr.ui.analysis.DetailsNumericMemoryColumn.call(
+ this, name, cellPath, aggregationMode);
+ }
+
+ EffectiveSizeColumn.prototype = {
+ __proto__: tr.ui.analysis.DetailsNumericMemoryColumn.prototype,
+
+ get title() {
+ return tr.ui.b.createLink({
+ textContent: this.name,
+ tooltip: 'Memory used by this component',
+ href: URL_TO_SIZE_VS_EFFECTIVE_SIZE
+ });
+ },
+
+ addInfos(numerics, memoryAllocatorDumps, infos) {
+ if (memoryAllocatorDumps === undefined) return;
+
+ // Quantified name of an owner dump (of the given dump) -> {count,
+ // importanceRange}.
+ const ownerNameToEntry = new Map();
+
+ // Quantified name of an owned dump (by the given dump) -> {count,
+ // importanceRange, sharerNameToEntry}, where sharerNameToEntry is a map
+ // from quantified names of other owners of the owned dump to {count,
+ // importanceRange}.
+ const ownedNameToEntry = new Map();
+
+ for (let i = 0; i < numerics.length; i++) {
+ if (numerics[i] === undefined) continue;
+
+ const dump = memoryAllocatorDumps[i];
+ if (dump === SUBALLOCATION_CONTEXT) {
+ return; // No ownership of suballocation internal rows.
+ }
+
+ // Gather owners of this dump.
+ dump.ownedBy.forEach(function(ownerLink) {
+ const ownerDump = ownerLink.source;
+ this.getAndUpdateOwnershipEntry_(
+ ownerNameToEntry, ownerDump, ownerLink);
+ }, this);
+
+ // Gather dumps owned by this dump and other owner dumps sharing them
+ // (with this dump).
+ const ownedLink = dump.owns;
+ if (ownedLink !== undefined) {
+ const ownedDump = ownedLink.target;
+ const ownedEntry = this.getAndUpdateOwnershipEntry_(ownedNameToEntry,
+ ownedDump, ownedLink, true /* opt_withSharerNameToEntry */);
+ const sharerNameToEntry = ownedEntry.sharerNameToEntry;
+ ownedDump.ownedBy.forEach(function(sharerLink) {
+ const sharerDump = sharerLink.source;
+ if (sharerDump === dump) return;
+ this.getAndUpdateOwnershipEntry_(
+ sharerNameToEntry, sharerDump, sharerLink);
+ }, this);
+ }
+ }
+
+ // Emit a single info listing all owners of this dump.
+ if (ownerNameToEntry.size > 0) {
+ const messageBuilder = new SizeInfoMessageBuilder();
+ messageBuilder.append('shared by');
+ messageBuilder.appendMap(
+ ownerNameToEntry,
+ false /* hasPluralSuffix */,
+ undefined /* emptyText */,
+ function(ownerName, ownerEntry) {
+ messageBuilder.append(ownerName);
+ if (ownerEntry.count < numerics.length) {
+ messageBuilder.appendSomeTimestampsQuantifier();
+ }
+ messageBuilder.appendImportanceRange(ownerEntry.importanceRange);
+ }, this);
+ infos.push({
+ message: messageBuilder.build(),
+ icon: LEFTWARDS_OPEN_HEADED_ARROW,
+ color: 'green'
+ });
+ }
+
+ // Emit a single info listing all dumps owned by this dump together
+ // with list(s) of other owner dumps sharing them with this dump.
+ if (ownedNameToEntry.size > 0) {
+ const messageBuilder = new SizeInfoMessageBuilder();
+ messageBuilder.append('shares');
+ messageBuilder.appendMap(
+ ownedNameToEntry,
+ false /* hasPluralSuffix */,
+ undefined /* emptyText */,
+ function(ownedName, ownedEntry) {
+ messageBuilder.append(ownedName);
+ const ownedCount = ownedEntry.count;
+ if (ownedCount < numerics.length) {
+ messageBuilder.appendSomeTimestampsQuantifier();
+ }
+ messageBuilder.appendImportanceRange(ownedEntry.importanceRange);
+ messageBuilder.append(' with');
+ messageBuilder.appendMap(
+ ownedEntry.sharerNameToEntry,
+ false /* hasPluralSuffix */,
+ ' no other dumps',
+ function(sharerName, sharerEntry) {
+ messageBuilder.append(sharerName);
+ if (sharerEntry.count < ownedCount) {
+ messageBuilder.appendSomeTimestampsQuantifier();
+ }
+ messageBuilder.appendImportanceRange(
+ sharerEntry.importanceRange);
+ }, this);
+ }, this);
+ infos.push({
+ message: messageBuilder.build(),
+ icon: RIGHTWARDS_OPEN_HEADED_ARROW,
+ color: 'green'
+ });
+ }
+ },
+
+ getAndUpdateOwnershipEntry_(
+ map, dump, link, opt_withSharerNameToEntry) {
+ const entry = getAndUpdateEntry(map, dump.quantifiedName,
+ function(newEntry) {
+ newEntry.importanceRange = new tr.b.math.Range();
+ if (opt_withSharerNameToEntry) {
+ newEntry.sharerNameToEntry = new Map();
+ }
+ });
+ entry.importanceRange.addValue(link.importance || 0);
+ return entry;
+ }
+ };
+
+ /** @constructor */
+ function SizeColumn(name, cellPath, aggregationMode) {
+ tr.ui.analysis.DetailsNumericMemoryColumn.call(
+ this, name, cellPath, aggregationMode);
+ }
+
+ SizeColumn.prototype = {
+ __proto__: tr.ui.analysis.DetailsNumericMemoryColumn.prototype,
+
+ get title() {
+ return tr.ui.b.createLink({
+ textContent: this.name,
+ tooltip: 'Memory requested by this component',
+ href: URL_TO_SIZE_VS_EFFECTIVE_SIZE
+ });
+ },
+
+ addInfos(numerics, memoryAllocatorDumps, infos) {
+ if (memoryAllocatorDumps === undefined) return;
+ this.addOverlapInfo_(numerics, memoryAllocatorDumps, infos);
+ this.addProvidedSizeWarningInfos_(numerics, memoryAllocatorDumps, infos);
+ },
+
+ addOverlapInfo_(numerics, memoryAllocatorDumps, infos) {
+ // Sibling allocator dump name -> {count, size}. The latter field (size)
+ // is omitted in multi-selection mode.
+ const siblingNameToEntry = new Map();
+ for (let i = 0; i < numerics.length; i++) {
+ if (numerics[i] === undefined) continue;
+ const dump = memoryAllocatorDumps[i];
+ if (dump === SUBALLOCATION_CONTEXT) {
+ return; // No ownership of suballocation internal rows.
+ }
+ const ownedBySiblingSizes = dump.ownedBySiblingSizes;
+ for (const siblingDump of ownedBySiblingSizes.keys()) {
+ const siblingName = siblingDump.name;
+ getAndUpdateEntry(siblingNameToEntry, siblingName,
+ function(newEntry) {
+ if (numerics.length === 1 /* single-selection mode */) {
+ newEntry.size = ownedBySiblingSizes.get(siblingDump);
+ }
+ });
+ }
+ }
+
+ // Emit a single info describing all overlaps with siblings (if
+ // applicable).
+ if (siblingNameToEntry.size > 0) {
+ const messageBuilder = new SizeInfoMessageBuilder();
+ messageBuilder.append('overlaps with its sibling');
+ messageBuilder.appendMap(
+ siblingNameToEntry,
+ true /* hasPluralSuffix */,
+ undefined /* emptyText */,
+ function(siblingName, siblingEntry) {
+ messageBuilder.append('\'', siblingName, '\'');
+ messageBuilder.appendSizeIfDefined(siblingEntry.size);
+ if (siblingEntry.count < numerics.length) {
+ messageBuilder.appendSomeTimestampsQuantifier();
+ }
+ }, this);
+ infos.push({
+ message: messageBuilder.build(),
+ icon: CIRCLED_LATIN_SMALL_LETTER_I,
+ color: 'blue'
+ });
+ }
+ },
+
+ addProvidedSizeWarningInfos_(numerics, memoryAllocatorDumps,
+ infos) {
+ // Info type (see MemoryAllocatorDumpInfoType) -> {count, providedSize,
+ // dependencySize}. The latter two fields (providedSize and
+ // dependencySize) are omitted in multi-selection mode.
+ const infoTypeToEntry = new Map();
+ for (let i = 0; i < numerics.length; i++) {
+ if (numerics[i] === undefined) continue;
+ const dump = memoryAllocatorDumps[i];
+ if (dump === SUBALLOCATION_CONTEXT) {
+ return; // Suballocation internal rows have no provided size.
+ }
+ dump.infos.forEach(function(dumpInfo) {
+ getAndUpdateEntry(infoTypeToEntry, dumpInfo.type, function(newEntry) {
+ if (numerics.length === 1 /* single-selection mode */) {
+ newEntry.providedSize = dumpInfo.providedSize;
+ newEntry.dependencySize = dumpInfo.dependencySize;
+ }
+ });
+ });
+ }
+
+ // Emit a warning info for every info type.
+ for (const infoType of infoTypeToEntry.keys()) {
+ const entry = infoTypeToEntry.get(infoType);
+ const messageBuilder = new SizeInfoMessageBuilder();
+ messageBuilder.append('provided size');
+ messageBuilder.appendSizeIfDefined(entry.providedSize);
+ let dependencyName;
+ switch (infoType) {
+ case PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN:
+ dependencyName = 'the aggregated size of the children';
+ break;
+ case PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER:
+ dependencyName = 'the size of the largest owner';
+ break;
+ default:
+ dependencyName = 'an unknown dependency';
+ break;
+ }
+ messageBuilder.append(' was less than ', dependencyName);
+ messageBuilder.appendSizeIfDefined(entry.dependencySize);
+ if (entry.count < numerics.length) {
+ messageBuilder.appendSomeTimestampsQuantifier();
+ }
+ infos.push(tr.ui.analysis.createWarningInfo(messageBuilder.build()));
+ }
+ }
+ };
+
+ const NUMERIC_COLUMN_RULES = [
+ {
+ condition: tr.model.MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME,
+ importance: 10,
+ columnConstructor: EffectiveSizeColumn
+ },
+ {
+ condition: tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME,
+ importance: 9,
+ columnConstructor: SizeColumn
+ },
+ {
+ condition: 'page_size',
+ importance: 0,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ condition: /size/,
+ importance: 5,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ // All other columns.
+ importance: 0,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ }
+ ];
+
+ const DIAGNOSTIC_COLUMN_RULES = [
+ {
+ importance: 0,
+ columnConstructor: tr.ui.analysis.StringMemoryColumn
+ }
+ ];
+
+ Polymer({
+ is: 'tr-ui-a-memory-dump-allocator-details-pane',
+ behaviors: [tr.ui.analysis.StackedPane],
+
+ created() {
+ this.memoryAllocatorDumps_ = undefined;
+ this.heapDumps_ = undefined;
+ this.aggregationMode_ = undefined;
+ },
+
+ ready() {
+ this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ },
+
+ /**
+ * Sets the memory allocator dumps and schedules rebuilding the pane.
+ *
+ * The provided value should be a chronological list of memory allocator
+ * dumps. All dumps are assumed to belong to the same process and have
+ * the same full name. Example:
+ *
+ * [
+ * tr.model.MemoryAllocatorDump {}, // MAD at timestamp 1.
+ * undefined, // MAD not provided at timestamp 2.
+ * tr.model.MemoryAllocatorDump {}, // MAD at timestamp 3.
+ * ]
+ */
+ set memoryAllocatorDumps(memoryAllocatorDumps) {
+ this.memoryAllocatorDumps_ = memoryAllocatorDumps;
+ this.scheduleRebuild_();
+ },
+
+ get memoryAllocatorDumps() {
+ return this.memoryAllocatorDumps_;
+ },
+
+ // TODO(petrcermak): Don't plumb the heap dumps through the allocator
+ // details pane. Maybe add support for multiple child panes to stacked pane
+ // (view) instead.
+ set heapDumps(heapDumps) {
+ this.heapDumps_ = heapDumps;
+ this.scheduleRebuild_();
+ },
+
+ set aggregationMode(aggregationMode) {
+ this.aggregationMode_ = aggregationMode;
+ this.scheduleRebuild_();
+ },
+
+ get aggregationMode() {
+ return this.aggregationMode_;
+ },
+
+ onRebuild_() {
+ if (this.memoryAllocatorDumps_ === undefined ||
+ this.memoryAllocatorDumps_.length === 0) {
+ // Show the info text (hide the table).
+ this.$.info_text.style.display = 'block';
+ this.$.table.style.display = 'none';
+
+ this.$.table.clear();
+ this.$.table.rebuild();
+
+ // Hide the heap details pane (if applicable).
+ this.childPaneBuilder = undefined;
+ return;
+ }
+
+ // Show the table (hide the info text).
+ this.$.info_text.style.display = 'none';
+ this.$.table.style.display = 'block';
+
+ const rows = this.createRows_();
+ const columns = this.createColumns_(rows);
+ rows.forEach(function(rootRow) {
+ tr.ui.analysis.aggregateTableRowCellsRecursively(rootRow, columns,
+ function(contexts) {
+ // Only aggregate suballocation rows (numerics of regular rows
+ // corresponding to MADs have already been aggregated by the
+ // model in MemoryAllocatorDump.aggregateNumericsRecursively).
+ return contexts !== undefined && contexts.some(function(context) {
+ return context === SUBALLOCATION_CONTEXT;
+ });
+ });
+ });
+
+ this.$.table.tableRows = rows;
+ this.$.table.tableColumns = columns;
+ this.$.table.rebuild();
+ tr.ui.analysis.expandTableRowsRecursively(this.$.table);
+
+ // Show/hide the heap details pane.
+ if (this.heapDumps_ === undefined) {
+ this.childPaneBuilder = undefined;
+ } else {
+ this.childPaneBuilder = function() {
+ const pane =
+ document.createElement('tr-ui-a-memory-dump-heap-details-pane');
+ pane.heapDumps = this.heapDumps_;
+ pane.aggregationMode = this.aggregationMode_;
+ return pane;
+ }.bind(this);
+ }
+ },
+
+ createRows_() {
+ return [
+ this.createAllocatorRowRecursively_(this.memoryAllocatorDumps_)
+ ];
+ },
+
+ createAllocatorRowRecursively_(dumps) {
+ // Get the name of the memory allocator dumps. We can use any defined
+ // dump in dumps since they all have the same name.
+ const definedDump = dumps.find(x => x);
+ const title = definedDump.name;
+ const fullName = definedDump.fullName;
+
+ // Transform a chronological list of memory allocator dumps into two
+ // dictionaries of cells (where each cell contains a chronological list
+ // of the values of one of its numerics or diagnostics).
+ const numericCells = tr.ui.analysis.createCells(dumps, function(dump) {
+ return dump.numerics;
+ });
+ const diagnosticCells = tr.ui.analysis.createCells(dumps, function(dump) {
+ return dump.diagnostics;
+ });
+
+ // Determine whether the memory allocator dump is a suballocation. A
+ // dump is assumed to be a suballocation if (1) its name starts with
+ // two underscores, (2) it has an owner from within the same process at
+ // some timestamp, and (3) it is undefined, has no owners, or has the
+ // same owner (and no other owners) at all other timestamps.
+ let suballocatedBy = undefined;
+ if (title.startsWith('__')) {
+ for (let i = 0; i < dumps.length; i++) {
+ const dump = dumps[i];
+ if (dump === undefined || dump.ownedBy.length === 0) {
+ // Ignore timestamps where the dump is undefined or doesn't
+ // have any owner.
+ continue;
+ }
+ const ownerDump = dump.ownedBy[0].source;
+ if (dump.ownedBy.length > 1 ||
+ dump.children.length > 0 ||
+ ownerDump.containerMemoryDump !== dump.containerMemoryDump) {
+ // If the dump has (1) any children, (2) multiple owners, or
+ // (3) its owner is in a different process (otherwise, the
+ // modified title would be ambiguous), then it's not considered
+ // to be a suballocation.
+ suballocatedBy = undefined;
+ break;
+ }
+ if (suballocatedBy === undefined) {
+ suballocatedBy = ownerDump.fullName;
+ } else if (suballocatedBy !== ownerDump.fullName) {
+ // The full name of the owner dump changed over time, so this
+ // dump is not a suballocation.
+ suballocatedBy = undefined;
+ break;
+ }
+ }
+ }
+
+ const row = {
+ title,
+ fullNames: [fullName],
+ contexts: dumps,
+ numericCells,
+ diagnosticCells,
+ suballocatedBy
+ };
+
+ // Child memory dump name (dict key) -> Timestamp (list index) ->
+ // Child dump.
+ const childDumpNameToDumps = tr.b.invertArrayOfDicts(dumps,
+ function(dump) {
+ const results = {};
+ for (const child of dump.children) {
+ results[child.name] = child;
+ }
+ return results;
+ });
+
+ // Recursively create sub-rows for children (if applicable).
+ const subRows = [];
+ let suballocationClassificationRootNode = undefined;
+ for (const childDumps of Object.values(childDumpNameToDumps)) {
+ const childRow = this.createAllocatorRowRecursively_(childDumps);
+ if (childRow.suballocatedBy === undefined) {
+ // Not a suballocation row: just append it.
+ subRows.push(childRow);
+ } else {
+ // Suballocation row: classify it in a tree of suballocations.
+ suballocationClassificationRootNode =
+ this.classifySuballocationRow_(
+ childRow, suballocationClassificationRootNode);
+ }
+ }
+
+ // Build the tree of suballocations (if applicable).
+ if (suballocationClassificationRootNode !== undefined) {
+ const suballocationRow = this.createSuballocationRowRecursively_(
+ 'suballocations', suballocationClassificationRootNode);
+ subRows.push(suballocationRow);
+ }
+
+ if (subRows.length > 0) {
+ row.subRows = subRows;
+ }
+
+ return row;
+ },
+
+ classifySuballocationRow_(suballocationRow, rootNode) {
+ if (rootNode === undefined) {
+ rootNode = {
+ children: {},
+ row: undefined
+ };
+ }
+
+ const suballocationLevels = suballocationRow.suballocatedBy.split('/');
+ let currentNode = rootNode;
+ for (let i = 0; i < suballocationLevels.length; i++) {
+ const suballocationLevel = suballocationLevels[i];
+ let nextNode = currentNode.children[suballocationLevel];
+ if (nextNode === undefined) {
+ currentNode.children[suballocationLevel] = nextNode = {
+ children: {},
+ row: undefined
+ };
+ }
+ currentNode = nextNode;
+ }
+
+ const existingRow = currentNode.row;
+ if (existingRow !== undefined) {
+ // On rare occasions it can happen that one dump (e.g. sqlite) owns
+ // different suballocations at different timestamps (e.g.
+ // malloc/allocated_objects/_7d35 and malloc/allocated_objects/_511e).
+ // When this happens, we merge the two suballocations into a single row
+ // (malloc/allocated_objects/suballocations/sqlite).
+ for (let i = 0; i < suballocationRow.contexts.length; i++) {
+ const newContext = suballocationRow.contexts[i];
+ if (newContext === undefined) continue;
+
+ if (existingRow.contexts[i] !== undefined) {
+ throw new Error('Multiple suballocations with the same owner name');
+ }
+
+ existingRow.contexts[i] = newContext;
+ ['numericCells', 'diagnosticCells'].forEach(function(cellKey) {
+ const suballocationCells = suballocationRow[cellKey];
+ if (suballocationCells === undefined) return;
+ for (const [cellName, cell] of Object.entries(suballocationCells)) {
+ if (cell === undefined) continue;
+ const fields = cell.fields;
+ if (fields === undefined) continue;
+ const field = fields[i];
+ if (field === undefined) continue;
+ let existingCells = existingRow[cellKey];
+ if (existingCells === undefined) {
+ existingCells = {};
+ existingRow[cellKey] = existingCells;
+ }
+ let existingCell = existingCells[cellName];
+ if (existingCell === undefined) {
+ existingCell = new tr.ui.analysis.MemoryCell(
+ new Array(fields.length));
+ existingCells[cellName] = existingCell;
+ }
+ existingCell.fields[i] = field;
+ }
+ });
+ }
+ existingRow.fullNames.push.apply(
+ existingRow.fullNames, suballocationRow.fullNames);
+ } else {
+ currentNode.row = suballocationRow;
+ }
+
+ return rootNode;
+ },
+
+ createSuballocationRowRecursively_(name, node) {
+ const childCount = Object.keys(node.children).length;
+ if (childCount === 0) {
+ if (node.row === undefined) {
+ throw new Error('Suballocation node must have a row or children');
+ }
+ // Leaf row of the suballocation tree: Change the row's title from
+ // '__MEANINGLESSHASH' to the name of the suballocation owner.
+ const row = node.row;
+ row.title = name;
+ row.suballocation = true;
+ return row;
+ }
+
+ // Internal row of the suballocation tree: Recursively create its
+ // sub-rows.
+ const subRows = [];
+ for (const [subName, subNode] of Object.entries(node.children)) {
+ subRows.push(this.createSuballocationRowRecursively_(subName, subNode));
+ }
+
+ if (node.row !== undefined) {
+ // Very unlikely case: Both an ancestor (e.g. 'skia') and one of its
+ // descendants (e.g. 'skia/sk_glyph_cache') both suballocate from the
+ // same MemoryAllocatorDump (e.g. 'malloc/allocated_objects'). In
+ // this case, the suballocation from the ancestor must be mapped to
+ // 'malloc/allocated_objects/suballocations/skia/<unspecified>' so
+ // that 'malloc/allocated_objects/suballocations/skia' could
+ // aggregate the numerics of the two suballocations properly.
+ const row = node.row;
+ row.title = '<unspecified>';
+ row.suballocation = true;
+ subRows.unshift(row);
+ }
+
+ // An internal row of the suballocation tree is assumed to be defined
+ // at a given timestamp if at least one of its sub-rows is defined at
+ // the timestamp.
+ const contexts = new Array(subRows[0].contexts.length);
+ for (let i = 0; i < subRows.length; i++) {
+ subRows[i].contexts.forEach(function(subContext, index) {
+ if (subContext !== undefined) {
+ contexts[index] = SUBALLOCATION_CONTEXT;
+ }
+ });
+ }
+
+ return {
+ title: name,
+ suballocation: true,
+ contexts,
+ subRows
+ };
+ },
+
+ createColumns_(rows) {
+ const titleColumn = new AllocatorDumpNameColumn();
+ titleColumn.width = '200px';
+
+ const numericColumns = tr.ui.analysis.MemoryColumn.fromRows(rows, {
+ cellKey: 'numericCells',
+ aggregationMode: this.aggregationMode_,
+ rules: NUMERIC_COLUMN_RULES
+ });
+ const diagnosticColumns = tr.ui.analysis.MemoryColumn.fromRows(rows, {
+ cellKey: 'diagnosticCells',
+ aggregationMode: this.aggregationMode_,
+ rules: DIAGNOSTIC_COLUMN_RULES
+ });
+ const fieldColumns = numericColumns.concat(diagnosticColumns);
+ tr.ui.analysis.MemoryColumn.spaceEqually(fieldColumns);
+
+ const columns = [titleColumn].concat(fieldColumns);
+ return columns;
+ }
+ });
+
+ return {
+ // All exports are for testing only.
+ SUBALLOCATION_CONTEXT,
+ AllocatorDumpNameColumn,
+ EffectiveSizeColumn,
+ SizeColumn,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane_test.html
new file mode 100644
index 00000000000..6fda765b34b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane_test.html
@@ -0,0 +1,1261 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/heap_dump.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_allocator_details_pane.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+ const Scalar = tr.b.Scalar;
+ const unitlessNumber_smallerIsBetter =
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const HeapDump = tr.model.HeapDump;
+ const AggregationMode = tr.ui.analysis.MemoryColumn.AggregationMode;
+ const checkNumericFields = tr.ui.analysis.checkNumericFields;
+ const checkSizeNumericFields = tr.ui.analysis.checkSizeNumericFields;
+ const checkStringFields = tr.ui.analysis.checkStringFields;
+ const checkColumnInfosAndColor = tr.ui.analysis.checkColumnInfosAndColor;
+ const checkColumns = tr.ui.analysis.checkColumns;
+ const isElementDisplayed = tr.ui.analysis.isElementDisplayed;
+ const AllocatorDumpNameColumn = tr.ui.analysis.AllocatorDumpNameColumn;
+ const EffectiveSizeColumn = tr.ui.analysis.EffectiveSizeColumn;
+ const SizeColumn = tr.ui.analysis.SizeColumn;
+ const StringMemoryColumn = tr.ui.analysis.StringMemoryColumn;
+ const NumericMemoryColumn = tr.ui.analysis.NumericMemoryColumn;
+ const addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
+ const addProcessMemoryDump =
+ tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const addChildDump = tr.model.MemoryDumpTestUtils.addChildDump;
+ const addOwnershipLink = tr.model.MemoryDumpTestUtils.addOwnershipLink;
+
+ const SUBALLOCATION_CONTEXT = tr.ui.analysis.SUBALLOCATION_CONTEXT;
+ const MemoryAllocatorDumpInfoType = tr.model.MemoryAllocatorDumpInfoType;
+ const PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN =
+ MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN;
+ const PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER =
+ MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER;
+
+ function addRootDumps(containerMemoryDump, rootNames, addedCallback) {
+ // Test sanity check.
+ assert.isUndefined(containerMemoryDump.memoryAllocatorDumps);
+
+ const rootDumps = rootNames.map(function(rootName) {
+ return new MemoryAllocatorDump(containerMemoryDump, rootName);
+ });
+ addedCallback.apply(null, rootDumps);
+ containerMemoryDump.memoryAllocatorDumps = rootDumps;
+ }
+
+ function newSuballocationDump(ownerDump, parentDump, name, size) {
+ const suballocationDump = addChildDump(parentDump, name,
+ {numerics: {size}});
+ if (ownerDump !== undefined) {
+ addOwnershipLink(ownerDump, suballocationDump);
+ }
+ return suballocationDump;
+ }
+
+ function createProcessMemoryDumps() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+
+ // First timestamp.
+ const gmd1 = addGlobalMemoryDump(model, {ts: -10});
+ const pmd1 = addProcessMemoryDump(gmd1, process, {ts: -11});
+ pmd1.memoryAllocatorDumps = (function() {
+ const v8Dump = newAllocatorDump(pmd1, 'v8', {numerics: {
+ size: 1073741824 /* 1 GiB */,
+ inner_size: 2097152 /* 2 MiB */,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 204)
+ }});
+
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 805306368 /* 768 MiB */}});
+ addChildDump(v8HeapsDump, 'heap42',
+ {numerics: {size: 804782080 /* 767.5 MiB */}});
+
+ const v8ObjectsDump = addChildDump(v8Dump, 'objects');
+ v8ObjectsDump.addDiagnostic('url', 'http://example.com');
+ addChildDump(v8ObjectsDump, 'foo',
+ {numerics: {size: 1022976 /* 999 KiB */}});
+ addChildDump(v8ObjectsDump, 'bar',
+ {numerics: {size: 1024000 /* 1000 KiB */}});
+
+ const oilpanDump = newAllocatorDump(pmd1, 'oilpan',
+ {numerics: {size: 125829120 /* 120 MiB */}});
+ newSuballocationDump(
+ oilpanDump, v8Dump, '__99BEAD', 150994944 /* 144 MiB */);
+
+ const oilpanSubDump = addChildDump(oilpanDump, 'animals');
+
+ const oilpanSubDump1 = addChildDump(oilpanSubDump, 'cow',
+ {numerics: {size: 33554432 /* 32 MiB */}});
+ newSuballocationDump(
+ oilpanSubDump1, v8Dump, '__42BEEF', 67108864 /* 64 MiB */);
+
+ const oilpanSubDump2 = addChildDump(oilpanSubDump, 'chicken',
+ {numerics: {size: 16777216 /* 16 MiB */}});
+ newSuballocationDump(
+ oilpanSubDump2, v8Dump, '__68DEAD', 33554432 /* 32 MiB */);
+
+ const skiaDump = newAllocatorDump(pmd1, 'skia',
+ {numerics: {size: 8388608 /* 8 MiB */}});
+ const suballocationDump = newSuballocationDump(
+ skiaDump, v8Dump, '__15FADE', 16777216 /* 16 MiB */);
+
+ const ccDump = newAllocatorDump(pmd1, 'cc',
+ {numerics: {size: 4194304 /* 4 MiB */}});
+ newSuballocationDump(
+ ccDump, v8Dump, '__12FEED', 5242880 /* 5 MiB */).addDiagnostic(
+ 'url', 'localhost:1234');
+
+ return [v8Dump, oilpanDump, skiaDump, ccDump];
+ })();
+
+ // Second timestamp.
+ const gmd2 = addGlobalMemoryDump(model, {ts: 10});
+ const pmd2 = addProcessMemoryDump(gmd2, process, {ts: 11});
+ pmd2.memoryAllocatorDumps = (function() {
+ const v8Dump = newAllocatorDump(pmd2, 'v8', {numerics: {
+ size: 1073741824 /* 1 GiB */,
+ inner_size: 2097152 /* 2 MiB */,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 204)
+ }});
+
+ const v8ObjectsDump = addChildDump(v8Dump, 'objects');
+ v8ObjectsDump.addDiagnostic('url', 'http://sample.net');
+ addChildDump(v8ObjectsDump, 'foo',
+ {numerics: {size: 1020928 /* 997 KiB */}});
+ addChildDump(v8ObjectsDump, 'bar',
+ {numerics: {size: 1026048 /* 1002 KiB */}});
+
+ newSuballocationDump(
+ undefined, v8Dump, '__99BEAD', 268435456 /* 256 MiB */);
+
+ const ccDump = newAllocatorDump(pmd2, 'cc',
+ {numerics: {size: 7340032 /* 7 MiB */}});
+ newSuballocationDump(
+ ccDump, v8Dump, '__13DEED', 11534336 /* 11 MiB */).addDiagnostic(
+ 'url', 'localhost:5678');
+
+ return [v8Dump, ccDump];
+ })();
+ });
+
+ return model.processes[1].memoryDumps;
+ }
+
+ function createSizeFields(values) {
+ return values.map(function(value) {
+ if (value === undefined) return undefined;
+ return new Scalar(sizeInBytes_smallerIsBetter, value);
+ });
+ }
+
+ const EXPECTED_COLUMNS = [
+ { title: 'Component', type: AllocatorDumpNameColumn, noAggregation: true },
+ { title: 'effective_size', type: EffectiveSizeColumn },
+ { title: 'size', type: SizeColumn },
+ { title: 'inner_size', type: NumericMemoryColumn },
+ { title: 'objects_count', type: NumericMemoryColumn },
+ { title: 'url', type: StringMemoryColumn }
+ ];
+
+ function checkRow(columns, row, expectations) {
+ const formattedTitle = columns[0].formatTitle(row);
+ const expectedTitle = expectations.title;
+ if (typeof expectedTitle === 'function') {
+ expectedTitle(formattedTitle);
+ } else {
+ assert.strictEqual(formattedTitle, expectedTitle);
+ }
+
+ checkSizeNumericFields(row, columns[1], expectations.size);
+ checkSizeNumericFields(row, columns[2], expectations.effective_size);
+ checkSizeNumericFields(row, columns[3], expectations.inner_size);
+ checkNumericFields(row, columns[4], expectations.objects_count,
+ unitlessNumber_smallerIsBetter);
+ checkStringFields(row, columns[5], expectations.url);
+
+ const expectedSubRowCount = expectations.sub_row_count;
+ if (expectedSubRowCount === undefined) {
+ assert.isUndefined(row.subRows);
+ } else {
+ assert.lengthOf(row.subRows, expectedSubRowCount);
+ }
+
+ const expectedContexts = expectations.contexts;
+ if (expectedContexts === undefined) {
+ assert.isUndefined(row.contexts);
+ } else {
+ assert.deepEqual(Array.from(row.contexts), expectedContexts);
+ }
+ }
+
+ function buildProcessMemoryDumps(count, preFinalizeDumpsCallback) {
+ const pmds = new Array(count);
+ tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ for (let i = 0; i < count; i++) {
+ const timestamp = 10 + i;
+ const gmd = addGlobalMemoryDump(model, {ts: timestamp});
+ pmds[i] = addProcessMemoryDump(gmd, process, {ts: timestamp});
+ }
+ preFinalizeDumpsCallback(pmds);
+ });
+ return pmds;
+ }
+
+ function getAllocatorDumps(pmds, fullName) {
+ return pmds.map(function(pmd) {
+ if (pmd === undefined) return undefined;
+ return pmd.getMemoryAllocatorDumpByFullName(fullName);
+ });
+ }
+
+ function checkAllocatorPaneColumnInfosAndColor(
+ column, dumps, numericName, expectedInfos) {
+ const numerics = dumps.map(function(dump) {
+ if (dump === undefined) return undefined;
+ return dump.numerics[numericName];
+ });
+ checkColumnInfosAndColor(
+ column, numerics, dumps, expectedInfos, undefined /* no color */);
+ }
+
+ test('instantiate_empty', function() {
+ tr.ui.analysis.createAndCheckEmptyPanes(this,
+ 'tr-ui-a-memory-dump-allocator-details-pane', 'memoryAllocatorDumps',
+ function(viewEl) {
+ // Check that the info text is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.info_text));
+ assert.isFalse(isElementDisplayed(viewEl.$.table));
+ });
+ });
+
+ test('instantiate_single', function() {
+ const processMemoryDumps = createProcessMemoryDumps().slice(0, 1);
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-allocator-details-pane');
+ viewEl.memoryAllocatorDumps = getAllocatorDumps(processMemoryDumps, 'v8');
+ viewEl.rebuild();
+ assert.deepEqual(viewEl.requestedChildPanes, [undefined]);
+ this.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, undefined /* no aggregation */);
+ const rows = table.tableRows;
+ assert.lengthOf(rows, 1);
+
+ // Check the rows of the table.
+ const rootRow = rows[0];
+ checkRow(columns, rootRow, {
+ title: 'v8',
+ size: [942619648],
+ effective_size: [1081031680],
+ inner_size: [2097152],
+ objects_count: [204],
+ sub_row_count: 3,
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8'),
+ });
+
+ const heapsSubRow = rootRow.subRows[0];
+ checkRow(columns, heapsSubRow, {
+ title: 'heaps',
+ size: [805306368],
+ effective_size: [805306368],
+ sub_row_count: 2,
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/heaps'),
+ });
+
+ const heapsUnspecifiedSubRow = heapsSubRow.subRows[0];
+ checkRow(columns, heapsUnspecifiedSubRow, {
+ title: '<unspecified>',
+ size: [524288],
+ effective_size: [524288],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/heaps/<unspecified>'),
+ });
+
+ const suballocationsSubRow = rootRow.subRows[2];
+ checkRow(columns, suballocationsSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(
+ Polymer.dom(formattedTitle).textContent, 'suballocations');
+ assert.strictEqual(formattedTitle.title, '');
+ },
+ size: [135266304],
+ effective_size: [273678336],
+ sub_row_count: 3,
+ contexts: [SUBALLOCATION_CONTEXT],
+ });
+
+ const oilpanSuballocationSubRow = suballocationsSubRow.subRows[0];
+ checkRow(columns, oilpanSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'oilpan');
+ assert.strictEqual(formattedTitle.title, '');
+ },
+ size: [125829120],
+ effective_size: [251658240],
+ sub_row_count: 2,
+ contexts: [SUBALLOCATION_CONTEXT],
+ });
+
+ const oilpanUnspecifiedSuballocationSubRow =
+ oilpanSuballocationSubRow.subRows[0];
+ checkRow(columns, oilpanUnspecifiedSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(
+ Polymer.dom(formattedTitle).textContent, '<unspecified>');
+ assert.strictEqual(formattedTitle.title, 'v8/__99BEAD');
+ },
+ size: [75497472],
+ effective_size: [150994944],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/__99BEAD'),
+ });
+
+ const oilpanAnimalsSuballocationSubRow =
+ oilpanSuballocationSubRow.subRows[1];
+ checkRow(columns, oilpanAnimalsSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'animals');
+ assert.strictEqual(formattedTitle.title, '');
+ },
+ size: [50331648],
+ effective_size: [100663296],
+ sub_row_count: 2,
+ contexts: [SUBALLOCATION_CONTEXT],
+ });
+
+ const oilpanCowSuballocationSubRow =
+ oilpanAnimalsSuballocationSubRow.subRows[0];
+ checkRow(columns, oilpanCowSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'cow');
+ assert.strictEqual(formattedTitle.title, 'v8/__42BEEF');
+ },
+ size: [33554432],
+ effective_size: [67108864],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/__42BEEF'),
+ });
+
+ const skiaSuballocationSubRow = suballocationsSubRow.subRows[1];
+ checkRow(columns, skiaSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'skia');
+ assert.strictEqual(formattedTitle.title, 'v8/__15FADE');
+ },
+ size: [8388608],
+ effective_size: [16777216],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/__15FADE'),
+ });
+
+ const ccSuballocationSubRow = suballocationsSubRow.subRows[2];
+ checkRow(columns, ccSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'cc');
+ assert.strictEqual(formattedTitle.title, 'v8/__12FEED');
+ },
+ size: [1048576],
+ effective_size: [5242880],
+ url: ['localhost:1234'],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/__12FEED')
+ });
+ });
+
+ test('instantiate_multipleDiff', function() {
+ const processMemoryDumps = createProcessMemoryDumps();
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-allocator-details-pane');
+ viewEl.memoryAllocatorDumps = getAllocatorDumps(processMemoryDumps, 'v8');
+ viewEl.aggregationMode = AggregationMode.DIFF;
+ viewEl.rebuild();
+ assert.deepEqual(viewEl.requestedChildPanes, [undefined]);
+ this.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, AggregationMode.DIFF);
+ const rows = table.tableRows;
+ assert.lengthOf(rows, 1);
+
+ // Check the rows of the table.
+ const rootRow = rows[0];
+ checkRow(columns, rootRow, {
+ title: 'v8',
+ size: [942619648, 1066401792],
+ effective_size: [1081031680, 1073741824],
+ inner_size: [2097152, 2097152],
+ objects_count: [204, 204],
+ sub_row_count: 4,
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8'),
+ });
+
+ const heapsSubRow = rootRow.subRows[0];
+ checkRow(columns, heapsSubRow, {
+ title: 'heaps',
+ size: [805306368, undefined],
+ effective_size: [805306368, undefined],
+ sub_row_count: 2,
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/heaps'),
+ });
+
+ const heapsUnspecifiedSubRow = heapsSubRow.subRows[0];
+ checkRow(columns, heapsUnspecifiedSubRow, {
+ title: '<unspecified>',
+ size: [524288, undefined],
+ effective_size: [524288, undefined],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/heaps/<unspecified>'),
+ });
+
+ const unspecifiedSubRow = rootRow.subRows[2];
+ checkRow(columns, unspecifiedSubRow, {
+ title: '<unspecified>',
+ size: [undefined, 791725056],
+ effective_size: [undefined, 791725056],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/<unspecified>'),
+ });
+
+ const suballocationsSubRow = rootRow.subRows[3];
+ checkRow(columns, suballocationsSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(
+ Polymer.dom(formattedTitle).textContent, 'suballocations');
+ assert.strictEqual(formattedTitle.title, '');
+ },
+ size: [135266304, 272629760],
+ effective_size: [273678336, 279969792],
+ sub_row_count: 3,
+ contexts: [SUBALLOCATION_CONTEXT, SUBALLOCATION_CONTEXT],
+ });
+
+ const oilpanSuballocationSubRow = suballocationsSubRow.subRows[0];
+ checkRow(columns, oilpanSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'oilpan');
+ assert.strictEqual(formattedTitle.title, '');
+ },
+ size: [125829120, 268435456],
+ effective_size: [251658240, 268435456],
+ sub_row_count: 2,
+ contexts: [SUBALLOCATION_CONTEXT, SUBALLOCATION_CONTEXT],
+ });
+
+ const oilpanUnspecifiedSuballocationSubRow =
+ oilpanSuballocationSubRow.subRows[0];
+ checkRow(columns, oilpanUnspecifiedSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(
+ Polymer.dom(formattedTitle).textContent, '<unspecified>');
+ assert.strictEqual(formattedTitle.title, 'v8/__99BEAD');
+ },
+ size: [75497472, 268435456],
+ effective_size: [150994944, 268435456],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/__99BEAD'),
+ });
+
+ const oilpanAnimalsSuballocationSubRow =
+ oilpanSuballocationSubRow.subRows[1];
+ checkRow(columns, oilpanAnimalsSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'animals');
+ assert.strictEqual(formattedTitle.title, '');
+ },
+ size: [50331648, undefined],
+ effective_size: [100663296, undefined],
+ sub_row_count: 2,
+ contexts: [SUBALLOCATION_CONTEXT, undefined],
+ });
+
+ const oilpanCowSuballocationSubRow =
+ oilpanAnimalsSuballocationSubRow.subRows[0];
+ checkRow(columns, oilpanCowSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'cow');
+ assert.strictEqual(formattedTitle.title, 'v8/__42BEEF');
+ },
+ size: [33554432, undefined],
+ effective_size: [67108864, undefined],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/__42BEEF'),
+ });
+
+ const skiaSuballocationSubRow = suballocationsSubRow.subRows[1];
+ checkRow(columns, skiaSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'skia');
+ assert.strictEqual(formattedTitle.title, 'v8/__15FADE');
+ },
+ size: [8388608, undefined],
+ effective_size: [16777216, undefined],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/__15FADE'),
+ });
+
+ const ccSuballocationSubRow = suballocationsSubRow.subRows[2];
+ checkRow(columns, ccSuballocationSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(Polymer.dom(formattedTitle).textContent, 'cc');
+ assert.strictEqual(formattedTitle.title, 'v8/__12FEED, v8/__13DEED');
+ },
+ size: [1048576, 4194304],
+ effective_size: [5242880, 11534336],
+ url: ['localhost:1234', 'localhost:5678'],
+ contexts: [
+ processMemoryDumps[0].getMemoryAllocatorDumpByFullName('v8/__12FEED'),
+ processMemoryDumps[1].getMemoryAllocatorDumpByFullName('v8/__13DEED')
+ ]
+ });
+ });
+
+ test('instantiate_multipleMax', function() {
+ const processMemoryDumps = createProcessMemoryDumps();
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-allocator-details-pane');
+ viewEl.memoryAllocatorDumps = getAllocatorDumps(processMemoryDumps, 'v8');
+ viewEl.aggregationMode = AggregationMode.MAX;
+ viewEl.rebuild();
+ assert.deepEqual(viewEl.requestedChildPanes, [undefined]);
+ this.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ // Just check that the aggregation mode was propagated to the columns.
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, AggregationMode.MAX);
+ const rows = table.tableRows;
+ assert.lengthOf(rows, 1);
+ });
+
+ test('instantiate_multipleWithUndefined', function() {
+ const processMemoryDumps = createProcessMemoryDumps();
+ processMemoryDumps.splice(1, 0, undefined);
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-allocator-details-pane');
+ viewEl.memoryAllocatorDumps = getAllocatorDumps(processMemoryDumps, 'v8');
+ viewEl.aggregationMode = AggregationMode.DIFF;
+ viewEl.rebuild();
+ assert.deepEqual(viewEl.requestedChildPanes, [undefined]);
+ this.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, AggregationMode.DIFF);
+ const rows = table.tableRows;
+ assert.lengthOf(rows, 1);
+
+ // Check only a few rows of the table.
+ const rootRow = rows[0];
+ checkRow(columns, rootRow, {
+ title: 'v8',
+ size: [942619648, undefined, 1066401792],
+ effective_size: [1081031680, undefined, 1073741824],
+ inner_size: [2097152, undefined, 2097152],
+ objects_count: [204, undefined, 204],
+ sub_row_count: 4,
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8'),
+ });
+
+ const unspecifiedSubRow = rootRow.subRows[2];
+ checkRow(columns, unspecifiedSubRow, {
+ title: '<unspecified>',
+ size: [undefined, undefined, 791725056],
+ effective_size: [undefined, undefined, 791725056],
+ contexts: getAllocatorDumps(processMemoryDumps, 'v8/<unspecified>'),
+ });
+
+ const suballocationsSubRow = rootRow.subRows[3];
+ checkRow(columns, suballocationsSubRow, {
+ title(formattedTitle) {
+ assert.strictEqual(
+ Polymer.dom(formattedTitle).textContent, 'suballocations');
+ assert.strictEqual(formattedTitle.title, '');
+ },
+ size: [135266304, undefined, 272629760],
+ effective_size: [273678336, undefined, 279969792],
+ sub_row_count: 3,
+ contexts: [SUBALLOCATION_CONTEXT, undefined, SUBALLOCATION_CONTEXT],
+ });
+ });
+
+ test('heapDumpsPassThrough', function() {
+ const processMemoryDumps = createProcessMemoryDumps();
+ const heapDumps = processMemoryDumps.map(function(dump) {
+ if (dump === undefined) return undefined;
+ return new HeapDump(dump, 'v8');
+ });
+
+ // Start by creating a component details pane without any heap dumps.
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-allocator-details-pane');
+ viewEl.memoryAllocatorDumps = getAllocatorDumps(processMemoryDumps, 'v8');
+ viewEl.aggregationMode = AggregationMode.MAX;
+ viewEl.rebuild();
+
+ assert.lengthOf(viewEl.requestedChildPanes, 1);
+ assert.isUndefined(viewEl.requestedChildPanes[0]);
+
+ // Set the heap dumps. This should trigger creating a heap details pane.
+ viewEl.heapDumps = heapDumps;
+ viewEl.aggregationMode = AggregationMode.DIFF;
+ viewEl.rebuild();
+
+ assert.lengthOf(viewEl.requestedChildPanes, 2);
+ assert.strictEqual(viewEl.requestedChildPanes[1].tagName,
+ 'TR-UI-A-MEMORY-DUMP-HEAP-DETAILS-PANE');
+ assert.strictEqual(viewEl.requestedChildPanes[1].heapDumps, heapDumps);
+ assert.strictEqual(viewEl.requestedChildPanes[1].aggregationMode,
+ AggregationMode.DIFF);
+
+ // Unset the heap dumps. This should trigger removing the heap details pane.
+ viewEl.heapDumps = undefined;
+ viewEl.rebuild();
+
+ assert.lengthOf(viewEl.requestedChildPanes, 3);
+ assert.isUndefined(viewEl.requestedChildPanes[2]);
+ });
+
+ test('allocatorDumpNameColumn', function() {
+ const c = new AllocatorDumpNameColumn();
+
+ // Regular row.
+ assert.strictEqual(c.formatTitle({title: 'Regular row'}), 'Regular row');
+
+ // Sub-allocation row.
+ const row = c.formatTitle({
+ title: 'Suballocation row',
+ suballocation: true,
+ });
+ assert.strictEqual(Polymer.dom(row).textContent, 'Suballocation row');
+ assert.strictEqual(row.style.fontStyle, 'italic');
+ });
+
+ test('effectiveSizeColumn_noContext', function() {
+ const c = new EffectiveSizeColumn('Effective Size', 'bytes', (x => x),
+ AggregationMode.DIFF);
+
+ // Single selection.
+ checkColumnInfosAndColor(c,
+ createSizeFields([128]),
+ undefined /* no context */,
+ [] /* no infos */,
+ undefined /* no color */);
+
+ // Multi-selection.
+ checkColumnInfosAndColor(c,
+ createSizeFields([128, 256, undefined, 64]),
+ undefined /* no context */,
+ [] /* no infos */,
+ undefined /* no color */);
+ });
+
+ test('effectiveSizeColumn_suballocationContext', function() {
+ const c = new EffectiveSizeColumn('Effective Size', 'bytes', (x => x),
+ AggregationMode.MAX);
+
+ // Single selection.
+ checkColumnInfosAndColor(c,
+ createSizeFields([128]),
+ [SUBALLOCATION_CONTEXT],
+ [] /* no infos */,
+ undefined /* no color */);
+
+ // Multi-selection.
+ checkColumnInfosAndColor(c,
+ createSizeFields([undefined, 256, undefined, 64]),
+ [undefined, SUBALLOCATION_CONTEXT, SUBALLOCATION_CONTEXT,
+ SUBALLOCATION_CONTEXT],
+ [] /* no infos */,
+ undefined /* no color */);
+ });
+
+ test('effectiveSizeColumn_dumpContext_noOwnership', function() {
+ const c = new EffectiveSizeColumn('Effective Size', 'bytes', (x => x),
+ AggregationMode.DIFF);
+ const pmds = buildProcessMemoryDumps(4 /* count */, function(pmds) {
+ addRootDumps(pmds[0], ['v8'], function(v8Dump) {
+ addChildDump(v8Dump, 'heaps', {numerics: {size: 64}});
+ });
+ addRootDumps(pmds[2], ['v8'], function(v8Dump) {
+ addChildDump(v8Dump, 'heaps', {numerics: {size: 128}});
+ });
+ addRootDumps(pmds[3], ['v8'], function(v8Dump) {});
+ });
+ const v8HeapsDumps = getAllocatorDumps(pmds, 'v8/heaps');
+
+ // Single selection.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapsDumps[0]],
+ 'effective_size',
+ [] /* no infos */);
+
+ // Multi-selection, all dumps defined.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapsDumps[0], v8HeapsDumps[2]],
+ 'effective_size',
+ [] /* no infos */);
+
+ // Multi-selection, some dumps missing.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ v8HeapsDumps,
+ 'effective_size',
+ [] /* no infos */);
+ });
+
+ test('effectiveSizeColumn_dumpContext_singleOwnership', function() {
+ const c = new EffectiveSizeColumn('Effective Size', 'bytes', (x => x),
+ AggregationMode.MAX);
+ const pmds = buildProcessMemoryDumps(5 /* count */, function(pmds) {
+ addRootDumps(pmds[0], ['v8', 'oilpan'], function(v8Dump, oilpanDump) {
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 32}});
+ const oilpanObjectsDump =
+ addChildDump(oilpanDump, 'objects', {numerics: {size: 64}});
+ addOwnershipLink(v8HeapsDump, oilpanObjectsDump);
+ });
+ addRootDumps(pmds[1], ['v8'], function(v8Dump) {
+ addChildDump(v8Dump, 'heaps', {numerics: {size: 32}});
+ // Missing oilpan/objects dump.
+ });
+ addRootDumps(pmds[2], ['v8', 'oilpan'], function(v8Dump, oilpanDump) {
+ addChildDump(oilpanDump, 'objects', {numerics: {size: 64}});
+ // Missing v8/heaps dump.
+ });
+ addRootDumps(pmds[3], ['v8', 'oilpan'], function(v8Dump, oilpanDump) {
+ addChildDump(v8Dump, 'heaps', {numerics: {size: 32}});
+ addChildDump(oilpanDump, 'objects', {numerics: {size: 64}});
+ // Missing ownership link.
+ });
+ addRootDumps(pmds[4], ['v8', 'oilpan'], function(v8Dump, oilpanDump) {
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 32}});
+ const oilpanObjectsDump =
+ addChildDump(oilpanDump, 'objects', {numerics: {size: 64}});
+ addOwnershipLink(v8HeapsDump, oilpanObjectsDump, 2);
+ });
+ });
+ const v8HeapsDump = getAllocatorDumps(pmds, 'v8/heaps');
+ const oilpanObjectsDump = getAllocatorDumps(pmds, 'oilpan/objects');
+
+ // Single selection.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapsDump[0]],
+ 'effective_size',
+ [
+ {
+ icon: '\u21FE',
+ message: 'shares \'oilpan/objects\' in Process 1 (importance: 0) ' +
+ 'with no other dumps',
+ color: 'green'
+ }
+ ]);
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [oilpanObjectsDump[4]],
+ 'effective_size',
+ [
+ {
+ icon: '\u21FD',
+ message: 'shared by \'v8/heaps\' in Process 1 (importance: 2)',
+ color: 'green'
+ }
+ ]);
+
+ // Multi-selection, all dumps defined.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapsDump[0], v8HeapsDump[4]],
+ 'effective_size',
+ [
+ {
+ icon: '\u21FE',
+ message: 'shares \'oilpan/objects\' in Process 1 (importance: ' +
+ '0\u20132) with no other dumps',
+ color: 'green'
+ }
+ ]);
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [oilpanObjectsDump[0], oilpanObjectsDump[4]],
+ 'effective_size',
+ [
+ {
+ icon: '\u21FD',
+ message: 'shared by \'v8/heaps\' in Process 1 (importance: ' +
+ '0\u20132)',
+ color: 'green'
+ }
+ ]);
+
+ // Multi-selection, some dumps missing.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ v8HeapsDump,
+ 'effective_size',
+ [
+ {
+ icon: '\u21FE',
+ message: 'shares \'oilpan/objects\' in Process 1 at some ' +
+ 'selected timestamps (importance: 0\u20132) with no other ' +
+ 'dumps',
+ color: 'green'
+ }
+ ]);
+ checkAllocatorPaneColumnInfosAndColor(c,
+ oilpanObjectsDump,
+ 'effective_size',
+ [
+ {
+ icon: '\u21FD',
+ message: 'shared by \'v8/heaps\' in Process 1 at some selected ' +
+ 'timestamps (importance: 0\u20132)',
+ color: 'green'
+ }
+ ]);
+ });
+
+ test('effectiveSizeColumn_dumpContext_multipleOwnerships', function() {
+ const c = new EffectiveSizeColumn('Effective Size', 'bytes', (x => x),
+ AggregationMode.DIFF);
+ const pmds = buildProcessMemoryDumps(6 /* count */, function(pmds) {
+ addRootDumps(pmds[0], ['v8', 'oilpan'], function(v8Dump, oilpanDump) {
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 32}});
+ const v8QueuesDump = addChildDump(v8Dump, 'queues',
+ {numerics: {size: 8}});
+ const oilpanObjectsDump =
+ addChildDump(oilpanDump, 'objects', {numerics: {size: 64}});
+ addOwnershipLink(v8HeapsDump, oilpanObjectsDump);
+ addOwnershipLink(v8QueuesDump, oilpanObjectsDump, 1);
+ });
+ addRootDumps(pmds[1], ['v8'], function(v8Dump) {});
+ addRootDumps(pmds[2], ['v8', 'oilpan'], function(v8Dump, oilpanDump) {
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 32}});
+ const v8QueuesDump = addChildDump(v8Dump, 'queues',
+ {numerics: {size: 8}});
+ const v8PilesDump = addChildDump(v8Dump, 'piles',
+ {numerics: {size: 48}});
+ const oilpanObjectsDump =
+ addChildDump(oilpanDump, 'objects', {numerics: {size: 64}});
+ addOwnershipLink(v8HeapsDump, oilpanObjectsDump, 2);
+ addOwnershipLink(v8QueuesDump, oilpanObjectsDump, 1);
+ addOwnershipLink(v8PilesDump, oilpanObjectsDump);
+ });
+ addRootDumps(pmds[3], ['v8', 'blink'], function(v8Dump, blinkDump) {
+ const blinkHandlesDump = addChildDump(blinkDump, 'handles',
+ {numerics: {size: 32}});
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 64}});
+ const blinkObjectsDump = addChildDump(blinkDump, 'objects',
+ {numerics: {size: 32}});
+ addOwnershipLink(blinkHandlesDump, v8HeapsDump, -273);
+ addOwnershipLink(v8HeapsDump, blinkObjectsDump, 3);
+ });
+ addRootDumps(pmds[4], ['v8', 'gpu'], function(v8Dump, gpuDump) {
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 64}});
+ const gpuTile1Dump = addChildDump(gpuDump, 'tile1',
+ {numerics: {size: 100}});
+ const gpuTile2Dump = addChildDump(gpuDump, 'tile2',
+ {numerics: {size: 99}});
+ addOwnershipLink(v8HeapsDump, gpuTile1Dump, 3);
+ addOwnershipLink(gpuTile2Dump, gpuTile1Dump, -1);
+ });
+ addRootDumps(pmds[5], ['v8', 'oilpan'], function(v8Dump, oilpanDump) {
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 32}});
+ const v8QueuesDump = addChildDump(v8Dump, 'queues',
+ {numerics: {size: 8}});
+ const v8PilesDump = addChildDump(v8Dump, 'piles',
+ {numerics: {size: 48}});
+ const oilpanObjectsDump =
+ addChildDump(oilpanDump, 'objects', {numerics: {size: 64}});
+ addOwnershipLink(v8HeapsDump, oilpanObjectsDump, 1);
+ addOwnershipLink(v8QueuesDump, oilpanObjectsDump, 1);
+ addOwnershipLink(v8PilesDump, oilpanObjectsDump, 7);
+ });
+ });
+ const v8HeapsDump = getAllocatorDumps(pmds, 'v8/heaps');
+ const oilpanObjectsDump = getAllocatorDumps(pmds, 'oilpan/objects');
+ const gpuTile1Dump = getAllocatorDumps(pmds, 'gpu/tile1');
+
+ // Single selection.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapsDump[4]],
+ 'effective_size',
+ [
+ {
+ icon: '\u21FE',
+ message: 'shares \'gpu/tile1\' in Process 1 (importance: 3) with ' +
+ '\'gpu/tile2\' in Process 1 (importance: -1)',
+ color: 'green'
+ }
+ ]);
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [gpuTile1Dump[4]],
+ 'effective_size',
+ [
+ {
+ icon: '\u21FD',
+ message: 'shared by:\n' +
+ ' - \'v8/heaps\' in Process 1 (importance: 3)\n' +
+ ' - \'gpu/tile2\' in Process 1 (importance: -1)',
+ color: 'green'
+ }
+ ]);
+
+ // Multi-selection, all dumps defined.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapsDump[2], v8HeapsDump[5]],
+ 'effective_size',
+ [
+ {
+ icon: '\u21FE',
+ message: 'shares \'oilpan/objects\' in Process 1 (importance: ' +
+ '1\u20132) with:\n' +
+ ' - \'v8/queues\' in Process 1 (importance: 1)\n' +
+ ' - \'v8/piles\' in Process 1 (importance: 0\u20137)',
+ color: 'green'
+ }
+ ]);
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [oilpanObjectsDump[2], oilpanObjectsDump[5]],
+ 'effective_size',
+ [
+ {
+ icon: '\u21FD',
+ message: 'shared by:\n' +
+ ' - \'v8/heaps\' in Process 1 (importance: 1\u20132)\n' +
+ ' - \'v8/queues\' in Process 1 (importance: 1)\n' +
+ ' - \'v8/piles\' in Process 1 (importance: 0\u20137)',
+ color: 'green'
+ }
+ ]);
+
+ // Multi-selection, some dumps missing.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ v8HeapsDump,
+ 'effective_size',
+ [ // v8/objects is both owned (first info) and an owner (second info).
+ {
+ icon: '\u21FD',
+ message: 'shared by \'blink/handles\' in Process 1 at some ' +
+ 'selected timestamps (importance: -273)',
+ color: 'green'
+ },
+ {
+ icon: '\u21FE',
+ message: 'shares:\n' +
+ ' - \'oilpan/objects\' in Process 1 at some selected ' +
+ 'timestamps (importance: 0\u20132) with:\n' +
+ ' - \'v8/queues\' in Process 1 (importance: 1)\n' +
+ ' - \'v8/piles\' in Process 1 at some selected ' +
+ 'timestamps (importance: 0\u20137)\n' +
+ ' - \'blink/objects\' in Process 1 at some selected ' +
+ 'timestamps (importance: 3) with no other dumps\n' +
+ ' - \'gpu/tile1\' in Process 1 at some selected timestamps ' +
+ '(importance: 3) with \'gpu/tile2\' in Process 1 ' +
+ '(importance: -1)',
+ color: 'green'
+ }
+ ]);
+ checkAllocatorPaneColumnInfosAndColor(c,
+ oilpanObjectsDump,
+ 'effective_size',
+ [
+ {
+ icon: '\u21FD',
+ message: 'shared by:\n' +
+ ' - \'v8/heaps\' in Process 1 at some selected timestamps ' +
+ '(importance: 0\u20132)\n' +
+ ' - \'v8/queues\' in Process 1 at some selected timestamps ' +
+ '(importance: 1)\n' +
+ ' - \'v8/piles\' in Process 1 at some selected timestamps ' +
+ '(importance: 0\u20137)',
+ color: 'green'
+ }
+ ]);
+ });
+
+ test('sizeColumn_noContext', function() {
+ const c = new SizeColumn('Size', 'bytes', (x => x),
+ AggregationMode.DIFF);
+
+ // Single selection.
+ checkColumnInfosAndColor(c,
+ createSizeFields([128]),
+ undefined /* no context */,
+ [] /* no infos */,
+ undefined /* no color */);
+
+ // Multi-selection.
+ checkColumnInfosAndColor(c,
+ createSizeFields([128, 256, undefined, 64]),
+ undefined /* no context */,
+ [] /* no infos */,
+ undefined /* no color */);
+ });
+
+ test('sizeColumn_suballocationContext', function() {
+ const c = new SizeColumn('Size', 'bytes', (x => x),
+ AggregationMode.MAX);
+
+ // Single selection.
+ checkColumnInfosAndColor(c,
+ createSizeFields([128]),
+ [SUBALLOCATION_CONTEXT],
+ [] /* no infos */,
+ undefined /* no color */);
+
+ // Multi-selection.
+ checkColumnInfosAndColor(c,
+ createSizeFields([undefined, 256, undefined, 64]),
+ [undefined, SUBALLOCATION_CONTEXT, undefined, SUBALLOCATION_CONTEXT],
+ [] /* no infos */,
+ undefined /* no color */);
+ });
+
+ test('sizeColumn_dumpContext', function() {
+ const c = new SizeColumn('Size', 'bytes', (x => x), AggregationMode.DIFF);
+ const pmds = buildProcessMemoryDumps(7 /* count */, function(pmds) {
+ addRootDumps(pmds[0], ['v8'], function(v8Dump) {
+ // Single direct overlap (v8/objects -> v8/heaps).
+ const v8ObjectsDump = addChildDump(v8Dump, 'objects',
+ {numerics: {size: 1536}});
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 2048}});
+ addOwnershipLink(v8ObjectsDump, v8HeapsDump);
+ });
+ // pmd[1] intentionally skipped.
+ addRootDumps(pmds[2], ['v8'], function(v8Dump, oilpanDump) {
+ // Single direct overlap with inconsistent owned dump size.
+ const v8ObjectsDump = addChildDump(v8Dump, 'objects',
+ {numerics: {size: 3072}});
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 2048}});
+ addOwnershipLink(v8ObjectsDump, v8HeapsDump);
+ });
+ addRootDumps(pmds[3], ['v8'], function(v8Dump) {
+ // Single indirect overlap (v8/objects/X -> v8/heaps/42).
+ const v8ObjectsDump = addChildDump(v8Dump, 'objects',
+ {numerics: {size: 1536}});
+ const v8ObjectsXDump = addChildDump(v8ObjectsDump, 'X',
+ {numerics: {size: 512}});
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 2048}});
+ const v8Heaps42Dump = addChildDump(v8HeapsDump, '42',
+ {numerics: {size: 1024}});
+ addOwnershipLink(v8ObjectsXDump, v8Heaps42Dump);
+ });
+ addRootDumps(pmds[4], ['v8'], function(v8Dump) {
+ // Multiple overlaps.
+ const v8ObjectsDump = addChildDump(v8Dump, 'objects',
+ {numerics: {size: 1024}});
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 2048}});
+
+ const v8ObjectsXDump = addChildDump(v8ObjectsDump, 'X',
+ {numerics: {size: 512}});
+ const v8Heaps42Dump = addChildDump(v8HeapsDump, '42',
+ {numerics: {size: 1280}});
+ addOwnershipLink(v8ObjectsXDump, v8Heaps42Dump);
+
+ const v8ObjectsYDump = addChildDump(v8ObjectsDump, 'Y',
+ {numerics: {size: 128}});
+ const v8Heaps90Dump = addChildDump(v8HeapsDump, '90',
+ {numerics: {size: 256}});
+ addOwnershipLink(v8ObjectsYDump, v8Heaps90Dump);
+
+ const v8BlocksDump = addChildDump(v8Dump, 'blocks',
+ {numerics: {size: 768}});
+ addOwnershipLink(v8BlocksDump, v8Heaps42Dump);
+ });
+ addRootDumps(pmds[5], ['v8'], function(v8Dump) {
+ // No overlaps, inconsistent parent size.
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 2048}});
+ addChildDump(v8HeapsDump, '42', {numerics: {size: 1536}});
+ addChildDump(v8HeapsDump, '90', {numerics: {size: 615}});
+ });
+ addRootDumps(pmds[6], ['v8', 'oilpan'], function(v8Dump, oilpanDump) {
+ // No overlaps, inconsistent parent and owned dump size.
+ const v8HeapsDump = addChildDump(v8Dump, 'heaps',
+ {numerics: {size: 2048}});
+ addChildDump(v8HeapsDump, '42', {numerics: {size: 1536}});
+ addChildDump(v8HeapsDump, '90', {numerics: {size: 615}});
+ const oilpanObjectsDump =
+ addChildDump(oilpanDump, 'objects', {numerics: {size: 3072}});
+ addOwnershipLink(oilpanObjectsDump, v8HeapsDump);
+ });
+ });
+ const v8HeapDumps = getAllocatorDumps(pmds, 'v8/heaps');
+
+ // Single selection, single overlap.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapDumps[0]],
+ 'size',
+ [
+ {
+ icon: '\u24D8',
+ message: 'overlaps with its sibling \'objects\' (1.5 KiB)',
+ color: 'blue'
+ }
+ ]);
+
+ // Single selection, multiple overlaps.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapDumps[4]],
+ 'size',
+ [
+ {
+ icon: '\u24D8',
+ message: 'overlaps with its siblings:\n' +
+ ' - \'objects\' (640.0 B)\n' +
+ ' - \'blocks\' (768.0 B)',
+ color: 'blue'
+ }
+ ]);
+
+ // Single selection, warnings with no overlaps.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapDumps[6]],
+ 'size',
+ [
+ {
+ icon: '\u26A0',
+ message: 'provided size (2.0 KiB) was less than the aggregated ' +
+ 'size of the children (2.1 KiB)',
+ color: 'red'
+ },
+ {
+ icon: '\u26A0',
+ message: 'provided size (2.0 KiB) was less than the size of the ' +
+ 'largest owner (3.0 KiB)',
+ color: 'red'
+ }
+ ]);
+
+ // Single selection, single overlap with a warning.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapDumps[2]],
+ 'size',
+ [
+ {
+ icon: '\u24D8',
+ message: 'overlaps with its sibling \'objects\' (3.0 KiB)',
+ color: 'blue'
+ },
+ {
+ icon: '\u26A0',
+ message: 'provided size (2.0 KiB) was less than the size of the ' +
+ 'largest owner (3.0 KiB)',
+ color: 'red'
+ }
+ ]);
+
+ // Multi-selection, single overlap.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapDumps[0], v8HeapDumps[3]],
+ 'size',
+ [
+ {
+ icon: '\u24D8',
+ message: 'overlaps with its sibling \'objects\'',
+ color: 'blue'
+ }
+ ]);
+
+ // Multi-selection, multiple overlaps.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapDumps[0], v8HeapDumps[4]],
+ 'size',
+ [
+ {
+ icon: '\u24D8',
+ message: 'overlaps with its siblings:\n' +
+ ' - \'objects\'\n' +
+ ' - \'blocks\' at some selected timestamps',
+ color: 'blue'
+ }
+ ]);
+
+ // Multi-selection, warnings with no overlaps.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ [v8HeapDumps[5], v8HeapDumps[6]],
+ 'size',
+ [
+ {
+ icon: '\u26A0',
+ message: 'provided size was less than the aggregated ' +
+ 'size of the children',
+ color: 'red'
+ },
+ {
+ icon: '\u26A0',
+ message: 'provided size was less than the size of the largest ' +
+ 'owner at some selected timestamps',
+ color: 'red'
+ }
+ ]);
+
+ // Multi-selection, multiple overlaps with warnings.
+ checkAllocatorPaneColumnInfosAndColor(c,
+ v8HeapDumps,
+ 'size',
+ [
+ {
+ icon: '\u24D8',
+ message: 'overlaps with its siblings:\n' +
+ ' - \'objects\' at some selected timestamps\n' +
+ ' - \'blocks\' at some selected timestamps',
+ color: 'blue'
+ },
+ {
+ icon: '\u26A0',
+ message: 'provided size was less than the size of the largest ' +
+ 'owner at some selected timestamps',
+ color: 'red'
+ },
+ {
+ icon: '\u26A0',
+ message: 'provided size was less than the aggregated size of ' +
+ 'the children at some selected timestamps',
+ color: 'red'
+ }
+ ]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_header_pane.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_header_pane.html
new file mode 100644
index 00000000000..1141116ec86
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_header_pane.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_overview_pane.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/analysis/stacked_pane.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+
+<dom-module id='tr-ui-a-memory-dump-header-pane'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ background-color: #d0d0d0;
+ border-bottom: 1px solid #8e8e8e;
+ border-top: 1px solid white;
+ }
+
+ #label {
+ flex: 1 1 auto;
+ padding: 6px;
+ font-size: 15px;
+ }
+
+ #aggregation_mode_container {
+ display: none;
+ flex: 0 0 auto;
+ padding: 5px;
+ font-size: 15px;
+ }
+ </style>
+ </tr-ui-b-view-specific-brushing-state>
+ <div id="label"></div>
+ <div id="aggregation_mode_container">
+ <span>Metric aggregation:</span>
+ <!-- Aggregation mode selector (added in Polymer.ready()) -->
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ Polymer({
+ is: 'tr-ui-a-memory-dump-header-pane',
+ behaviors: [tr.ui.analysis.StackedPane],
+
+ created() {
+ this.containerMemoryDumps_ = undefined;
+ },
+
+ ready() {
+ Polymer.dom(this.$.aggregation_mode_container).appendChild(
+ tr.ui.b.createSelector(this, 'aggregationMode',
+ 'memoryDumpHeaderPane.aggregationMode',
+ tr.ui.analysis.MemoryColumn.AggregationMode.DIFF, [
+ {
+ label: 'Diff',
+ value: tr.ui.analysis.MemoryColumn.AggregationMode.DIFF
+ },
+ {
+ label: 'Max',
+ value: tr.ui.analysis.MemoryColumn.AggregationMode.MAX
+ }
+ ]));
+ },
+
+ /**
+ * Sets the container memory dumps and schedules rebuilding the pane.
+ *
+ * The provided value should be a chronologically sorted list of
+ * ContainerMemoryDump objects. All of the dumps must be associated with
+ * the same container (i.e. containerMemoryDumps must be either a list of
+ * ProcessMemoryDump(s) belonging to the same process, or a list of
+ * GlobalMemoryDump(s)). Example:
+ *
+ * [
+ * tr.model.ProcessMemoryDump {}, // PMD at timestamp 1.
+ * tr.model.ProcessMemoryDump {}, // PMD at timestamp 2.
+ * tr.model.ProcessMemoryDump {} // PMD at timestamp 3.
+ * ]
+ */
+ set containerMemoryDumps(containerMemoryDumps) {
+ this.containerMemoryDumps_ = containerMemoryDumps;
+ this.scheduleRebuild_();
+ },
+
+ get containerMemoryDumps() {
+ return this.containerMemoryDumps_;
+ },
+
+ set aggregationMode(aggregationMode) {
+ this.aggregationMode_ = aggregationMode;
+ this.scheduleRebuild_();
+ },
+
+ get aggregationMode() {
+ return this.aggregationMode_;
+ },
+
+ onRebuild_() {
+ this.updateLabel_();
+ this.updateAggregationModeSelector_();
+ this.changeChildPane_();
+ },
+
+ updateLabel_() {
+ Polymer.dom(this.$.label).textContent = '';
+
+ if (this.containerMemoryDumps_ === undefined ||
+ this.containerMemoryDumps_.length <= 0) {
+ Polymer.dom(this.$.label).textContent = 'No memory dumps selected';
+ return;
+ }
+
+ const containerDumpCount = this.containerMemoryDumps_.length;
+ const isMultiSelection = containerDumpCount > 1;
+
+ Polymer.dom(this.$.label).appendChild(document.createTextNode(
+ 'Selected ' + containerDumpCount + ' memory dump' +
+ (isMultiSelection ? 's' : '') +
+ ' in ' + this.containerMemoryDumps_[0].containerName + ' at '));
+ // TODO(petrcermak): Use <tr-v-ui-scalar-span> once it can be displayed
+ // inline. See https://github.com/catapult-project/catapult/issues/1371.
+ Polymer.dom(this.$.label).appendChild(document.createTextNode(
+ tr.b.Unit.byName.timeStampInMs.format(
+ this.containerMemoryDumps_[0].start)));
+ if (isMultiSelection) {
+ const ELLIPSIS = String.fromCharCode(8230);
+ Polymer.dom(this.$.label).appendChild(
+ document.createTextNode(ELLIPSIS));
+ Polymer.dom(this.$.label).appendChild(document.createTextNode(
+ tr.b.Unit.byName.timeStampInMs.format(
+ this.containerMemoryDumps_[containerDumpCount - 1].start)));
+ }
+ },
+
+ updateAggregationModeSelector_() {
+ let displayStyle;
+ if (this.containerMemoryDumps_ === undefined ||
+ this.containerMemoryDumps_.length <= 1) {
+ displayStyle = 'none';
+ } else {
+ displayStyle = 'initial';
+ }
+ this.$.aggregation_mode_container.style.display = displayStyle;
+ },
+
+ changeChildPane_() {
+ this.childPaneBuilder = function() {
+ if (this.containerMemoryDumps_ === undefined ||
+ this.containerMemoryDumps_.length <= 0) {
+ return undefined;
+ }
+
+ const overviewPane = document.createElement(
+ 'tr-ui-a-memory-dump-overview-pane');
+ overviewPane.processMemoryDumps = this.containerMemoryDumps_.map(
+ function(containerDump) {
+ return containerDump.processMemoryDumps;
+ });
+ overviewPane.aggregationMode = this.aggregationMode;
+ return overviewPane;
+ }.bind(this);
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_header_pane_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_header_pane_test.html
new file mode 100644
index 00000000000..3d5d20a7c47
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_header_pane_test.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/memory_dump_header_pane.html">
+<link rel="import"
+ href="/tracing/ui/analysis/memory_dump_sub_view_test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AggregationMode = tr.ui.analysis.MemoryColumn.AggregationMode;
+ const isElementDisplayed = tr.ui.analysis.isElementDisplayed;
+
+ function createAndCheckMemoryDumpHeaderPane(test, containerMemoryDumps,
+ expectedLabelText, expectedChildPaneRequested, expectedSelectorVisible) {
+ const viewEl =
+ tr.ui.analysis.createTestPane('tr-ui-a-memory-dump-header-pane');
+ viewEl.containerMemoryDumps = containerMemoryDumps;
+ viewEl.rebuild();
+ test.addHTMLOutput(viewEl);
+ checkMemoryDumpHeaderPane(viewEl, containerMemoryDumps, expectedLabelText,
+ expectedChildPaneRequested, expectedSelectorVisible);
+ }
+
+ function checkMemoryDumpHeaderPane(viewEl, containerMemoryDumps,
+ expectedLabelText, expectedChildPaneRequested, expectedSelectorVisible) {
+ // The default aggregation mode is DIFF.
+ assert.strictEqual(viewEl.aggregationMode, AggregationMode.DIFF);
+
+ // Check the text in the label.
+ assert.strictEqual(
+ Polymer.dom(viewEl.$.label).textContent, expectedLabelText);
+
+ // Check the visibility of aggregation mode selector.
+ const aggregationModeContainerVisible =
+ isElementDisplayed(viewEl.$.aggregation_mode_container);
+ const childPanes = viewEl.requestedChildPanes;
+
+ // Check the requested child panes.
+ if (containerMemoryDumps === undefined ||
+ containerMemoryDumps.length === 0) {
+ assert.isTrue(!expectedSelectorVisible); // Test sanity check.
+ assert.isFalse(aggregationModeContainerVisible);
+ assert.lengthOf(childPanes, 1);
+ assert.isUndefined(childPanes[0]);
+ return;
+ }
+
+ const expectedProcessMemoryDumps = containerMemoryDumps.map(
+ function(containerMemoryDump) {
+ return containerMemoryDump.processMemoryDumps;
+ });
+ function checkLastChildPane(expectedChildPaneCount) {
+ assert.lengthOf(childPanes, expectedChildPaneCount);
+ const lastChildPane = childPanes[expectedChildPaneCount - 1];
+ assert.strictEqual(
+ lastChildPane.tagName, 'TR-UI-A-MEMORY-DUMP-OVERVIEW-PANE');
+ assert.deepEqual(lastChildPane.processMemoryDumps,
+ expectedProcessMemoryDumps);
+ assert.strictEqual(lastChildPane.aggregationMode, viewEl.aggregationMode);
+ }
+
+ checkLastChildPane(1);
+
+ // Check the behavior of aggregation mode selector (if visible).
+ if (!expectedSelectorVisible) {
+ assert.isFalse(aggregationModeContainerVisible);
+ return;
+ }
+
+ assert.isTrue(aggregationModeContainerVisible);
+ const selector = tr.ui.b.findDeepElementMatching(viewEl, 'select');
+
+ selector.selectedValue = AggregationMode.MAX;
+ viewEl.rebuild();
+ assert.strictEqual(viewEl.aggregationMode, AggregationMode.MAX);
+ checkLastChildPane(2);
+
+ selector.selectedValue = AggregationMode.DIFF;
+ viewEl.rebuild();
+ assert.strictEqual(viewEl.aggregationMode, AggregationMode.DIFF);
+ checkLastChildPane(3);
+ }
+
+ test('instantiate_empty', function() {
+ tr.ui.analysis.createAndCheckEmptyPanes(this,
+ 'tr-ui-a-memory-dump-header-pane', 'containerMemoryDumps',
+ function(viewEl) {
+ checkMemoryDumpHeaderPane(viewEl, [], 'No memory dumps selected',
+ false /* no child pane requested */,
+ false /* aggregation mode selector hidden */);
+ });
+ });
+
+ test('instantiate_singleGlobalMemoryDump', function() {
+ createAndCheckMemoryDumpHeaderPane(this,
+ [tr.ui.analysis.createSingleTestGlobalMemoryDump()],
+ 'Selected 1 memory dump in global space at 68.000 ms',
+ true /* child pane requested */,
+ false /* aggregation mode selector hidden */);
+ });
+
+ test('instantiate_multipleGlobalMemoryDumps', function() {
+ createAndCheckMemoryDumpHeaderPane(this,
+ tr.ui.analysis.createMultipleTestGlobalMemoryDumps(),
+ 'Selected 3 memory dumps in global space at 42.000 ms\u2026100.000 ms',
+ true /* child pane requested */,
+ true /* aggregation selector visible */);
+ });
+
+ test('instantiate_singleProcessMemoryDump', function() {
+ createAndCheckMemoryDumpHeaderPane(this,
+ [tr.ui.analysis.createSingleTestProcessMemoryDump()],
+ 'Selected 1 memory dump in Process 2 at 69.000 ms',
+ true /* child pane requested */,
+ false /* aggregation mode selector hidden */);
+ });
+
+ test('instantiate_multipleProcessMemoryDumps', function() {
+ createAndCheckMemoryDumpHeaderPane(this,
+ tr.ui.analysis.createMultipleTestProcessMemoryDumps(),
+ 'Selected 3 memory dumps in Process 2 at 42.000 ms\u2026102.000 ms',
+ true /* child pane requested */,
+ true /* aggregation selector visible */);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html
new file mode 100644
index 00000000000..9d17e39ce85
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html
@@ -0,0 +1,354 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_heap_details_util.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/analysis/rebuildable_behavior.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/tab_view.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_context_controller.html">
+
+<dom-module id='tr-ui-a-memory-dump-heap-details-breakdown-view'>
+ <template>
+ <tr-ui-b-tab-view id="tabs"></tr-ui-b-tab-view>
+ </template>
+</dom-module>
+
+<dom-module id='tr-ui-a-memory-dump-heap-details-breakdown-view-tab'>
+ <template>
+ <tr-v-ui-scalar-context-controller></tr-v-ui-scalar-context-controller>
+ <tr-ui-b-info-bar id="info" hidden></tr-ui-b-info-bar>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const RESONABLE_NUMBER_OF_ROWS = 200;
+
+ const TabUiState = {
+ NO_LONG_TAIL: 0,
+ HIDING_LONG_TAIL: 1,
+ SHOWING_LONG_TAIL: 2,
+ };
+
+ /** @constructor */
+ function EmptyFillerColumn() {}
+
+ EmptyFillerColumn.prototype = {
+ title: '',
+
+ value() {
+ return '';
+ },
+ };
+
+ Polymer({
+ is: 'tr-ui-a-memory-dump-heap-details-breakdown-view',
+ behaviors: [tr.ui.analysis.RebuildableBehavior],
+
+ created() {
+ this.displayedNode_ = undefined;
+ this.dimensionToTab_ = new Map();
+ },
+
+ ready() {
+ this.scheduleRebuild_();
+ this.root.addEventListener('keydown', this.onKeyDown_.bind(this), true);
+ },
+
+ get displayedNode() {
+ return this.displayedNode_;
+ },
+
+ set displayedNode(node) {
+ this.displayedNode_ = node;
+ this.scheduleRebuild_();
+ },
+
+ get aggregationMode() {
+ return this.aggregationMode_;
+ },
+
+ set aggregationMode(aggregationMode) {
+ this.aggregationMode_ = aggregationMode;
+ for (const tab of this.$.tabs.tabs) {
+ tab.aggregationMode = aggregationMode;
+ }
+ },
+
+ onRebuild_() {
+ const previouslySelectedTab = this.$.tabs.selectedSubView;
+ let previouslySelectedTabFocused = false;
+ let previouslySelectedDimension = undefined;
+ if (previouslySelectedTab) {
+ previouslySelectedTabFocused = previouslySelectedTab.isFocused;
+ previouslySelectedDimension = previouslySelectedTab.dimension;
+ }
+
+ for (const tab of this.$.tabs.tabs) {
+ tab.nodes = undefined;
+ }
+ this.$.tabs.clearSubViews();
+
+ if (this.displayedNode_ === undefined) {
+ this.$.tabs.label = 'No heap node provided.';
+ return;
+ }
+
+ for (const [dimension, children] of this.displayedNode_.childNodes) {
+ if (!this.dimensionToTab_.has(dimension)) {
+ this.dimensionToTab_.set(dimension, document.createElement(
+ 'tr-ui-a-memory-dump-heap-details-breakdown-view-tab'));
+ }
+ const tab = this.dimensionToTab_.get(dimension);
+ tab.aggregationMode = this.aggregationMode_;
+ tab.dimension = dimension;
+ tab.nodes = children;
+ this.$.tabs.addSubView(tab);
+ tab.rebuild();
+ if (dimension === previouslySelectedDimension) {
+ this.$.tabs.selectedSubView = tab;
+ if (previouslySelectedTabFocused) {
+ tab.focus();
+ }
+ }
+ }
+
+ if (this.$.tabs.tabs.length > 0) {
+ this.$.tabs.label = 'Break selected node further by:';
+ } else {
+ this.$.tabs.label = 'Selected node cannot be broken down any further.';
+ }
+ },
+
+ onKeyDown_(keyEvent) {
+ if (!this.displayedNode_) return;
+
+ let keyHandled = false;
+ switch (keyEvent.keyCode) {
+ case 8: {
+ // Backspace.
+ if (!this.displayedNode_.parentNode) break;
+
+ // Enter the parent node upon pressing backspace.
+ const viewEvent = new tr.b.Event('enter-node');
+ viewEvent.node = this.displayedNode_.parentNode;
+ this.dispatchEvent(viewEvent);
+ keyHandled = true;
+ break;
+ }
+
+ case 37: // Left arrow.
+ case 39: // Right arrow.
+ {
+ const wasFocused = this.$.tabs.selectedSubView.isFocused;
+ keyHandled = keyEvent.keyCode === 37 ?
+ this.$.tabs.selectPreviousTabIfPossible() :
+ this.$.tabs.selectNextTabIfPossible();
+ if (wasFocused && keyHandled) {
+ this.$.tabs.selectedSubView.focus(); // Restore focus to new tab.
+ }
+ }
+ }
+
+ if (!keyHandled) return;
+ keyEvent.stopPropagation();
+ keyEvent.preventDefault();
+ }
+ });
+
+ Polymer({
+ is: 'tr-ui-a-memory-dump-heap-details-breakdown-view-tab',
+ behaviors: [tr.ui.analysis.RebuildableBehavior],
+
+ created() {
+ this.dimension_ = undefined;
+ this.nodes_ = undefined;
+ this.aggregationMode_ = undefined;
+ this.displayLongTail_ = false;
+ },
+
+ ready() {
+ this.$.table.addEventListener('step-into', function(tableEvent) {
+ const viewEvent = new tr.b.Event('enter-node');
+ viewEvent.node = tableEvent.tableRow;
+ this.dispatchEvent(viewEvent);
+ }.bind(this));
+ },
+
+ get displayLongTail() {
+ return this.displayLongTail_;
+ },
+
+ set displayLongTail(newValue) {
+ if (this.displayLongTail === newValue) return;
+ this.displayLongTail_ = newValue;
+ this.scheduleRebuild_();
+ },
+
+ get dimension() {
+ return this.dimension_;
+ },
+
+ set dimension(dimension) {
+ this.dimension_ = dimension;
+ this.scheduleRebuild_();
+ },
+
+ get nodes() {
+ return this.nodes_;
+ },
+
+ set nodes(nodes) {
+ this.nodes_ = nodes;
+ this.scheduleRebuild_();
+ },
+
+ get nodes() {
+ return this.nodes_ || [];
+ },
+
+ get dimensionLabel_() {
+ if (this.dimension_ === undefined) return '(undefined)';
+ return this.dimension_.label;
+ },
+
+ get tabLabel() {
+ let nodeCount = 0;
+ if (this.nodes_) {
+ nodeCount = this.nodes_.length;
+ }
+ return this.dimensionLabel_ + ' (' + nodeCount + ')';
+ },
+
+ get tabIcon() {
+ if (this.dimension_ === undefined ||
+ this.dimension_ === tr.ui.analysis.HeapDetailsRowDimension.ROOT) {
+ return undefined;
+ }
+ return {
+ text: this.dimension_.symbol,
+ style: 'color: ' + tr.b.ColorScheme.getColorForReservedNameAsString(
+ this.dimension_.color) + ';'
+ };
+ },
+
+ get aggregationMode() {
+ return this.aggregationMode_;
+ },
+
+ set aggregationMode(aggregationMode) {
+ this.aggregationMode_ = aggregationMode;
+ this.scheduleRebuild_();
+ },
+
+ focus() {
+ this.$.table.focus();
+ },
+
+ blur() {
+ this.$.table.blur();
+ },
+
+ get isFocused() {
+ return this.$.table.isFocused;
+ },
+
+ onRebuild_() {
+ this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ this.$.table.emptyValue = 'Cannot break down by ' +
+ this.dimensionLabel_.toLowerCase() + ' any further.';
+ const [state, rows] = this.getRows_();
+ const total = this.nodes.length;
+ const displayed = rows.length;
+ const hidden = total - displayed;
+ this.updateInfoBar_(state, [total, displayed, hidden]);
+ this.$.table.tableRows = rows;
+ this.$.table.tableColumns = this.createColumns_(rows);
+ if (this.$.table.sortColumnIndex === undefined) {
+ this.$.table.sortColumnIndex = 0;
+ this.$.table.sortDescending = false;
+ }
+ this.$.table.rebuild();
+ },
+
+ createColumns_(rows) {
+ const titleColumn = new tr.ui.analysis.HeapDetailsTitleColumn(
+ this.dimensionLabel_);
+ titleColumn.width = '400px';
+
+ const numericColumns = tr.ui.analysis.MemoryColumn.fromRows(rows, {
+ cellKey: 'cells',
+ aggregationMode: this.aggregationMode_,
+ rules: tr.ui.analysis.HEAP_DETAILS_COLUMN_RULES,
+ shouldSetContextGroup: true
+ });
+ if (numericColumns.length === 0) {
+ numericColumns.push(new EmptyFillerColumn());
+ }
+ tr.ui.analysis.MemoryColumn.spaceEqually(numericColumns);
+
+ const columns = [titleColumn].concat(numericColumns);
+ return columns;
+ },
+
+ getRows_() {
+ let rows = this.nodes;
+ if (rows.length <= RESONABLE_NUMBER_OF_ROWS) {
+ return [TabUiState.NO_LONG_TAIL, rows];
+ } else if (this.displayLongTail) {
+ return [TabUiState.SHOWING_LONG_TAIL, rows];
+ }
+ const absSize = row => Math.max(row.cells.Size.fields[0].value);
+ rows.sort((a, b) => absSize(b) - absSize(a));
+ rows = rows.slice(0, RESONABLE_NUMBER_OF_ROWS);
+ return [TabUiState.HIDING_LONG_TAIL, rows];
+ },
+
+ updateInfoBar_(state, rowStats) {
+ if (state === TabUiState.SHOWING_LONG_TAIL) {
+ this.longTailVisibleInfoBar_(rowStats);
+ } else if (state === TabUiState.HIDING_LONG_TAIL) {
+ this.longTailHiddenInfoBar_(rowStats);
+ } else {
+ this.hideInfoBar_();
+ }
+ },
+
+ longTailVisibleInfoBar_(rowStats) {
+ const [total, visible, hidden] = rowStats;
+ const couldHide = total - RESONABLE_NUMBER_OF_ROWS;
+ this.$.info.message = 'Showing ' + total + ' rows. This may be slow.';
+ this.$.info.removeAllButtons();
+ const buttonText = 'Hide ' + couldHide + ' rows.';
+ this.$.info.addButton(buttonText, () => this.displayLongTail = false);
+ this.$.info.visible = true;
+ },
+
+ longTailHiddenInfoBar_(rowStats) {
+ const [total, visible, hidden] = rowStats;
+ this.$.info.message = 'Hiding the smallest ' + hidden + ' rows.';
+ this.$.info.removeAllButtons();
+ this.$.info.addButton('Show all.', () => this.displayLongTail = true);
+ this.$.info.visible = true;
+ },
+
+ hideInfoBar_() {
+ this.$.info.visible = false;
+ },
+
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_pane.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_pane.html
new file mode 100644
index 00000000000..a43fdaa8189
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_pane.html
@@ -0,0 +1,451 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/multi_dimensional_view.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_heap_details_breakdown_view.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_heap_details_path_view.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_heap_details_util.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/analysis/stacked_pane.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<link rel="import" href="/tracing/ui/base/info_bar.html">
+
+<dom-module id='tr-ui-a-memory-dump-heap-details-pane'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+
+ #header {
+ flex: 0 0 auto;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ background-color: #eee;
+ border-bottom: 1px solid #8e8e8e;
+ border-top: 1px solid white;
+ }
+
+ #label {
+ flex: 1 1 auto;
+ padding: 8px;
+ font-size: 15px;
+ font-weight: bold;
+ }
+
+ #view_mode_container {
+ display: none;
+ flex: 0 0 auto;
+ padding: 5px;
+ font-size: 15px;
+ }
+
+ #contents {
+ flex: 1 0 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+
+ #info_text {
+ padding: 8px;
+ color: #666;
+ font-style: italic;
+ text-align: center;
+ }
+
+ #split_view {
+ display: none; /* Hide until memory allocator dumps are set. */
+ flex: 1 0 auto;
+ align-self: stretch;
+ flex-direction: row;
+ }
+
+ #path_view {
+ width: 50%;
+ }
+
+ #breakdown_view {
+ flex: 1 1 auto;
+ width: 0;
+ }
+
+ #path_view, #breakdown_view {
+ overflow-x: auto; /* Show scrollbar if necessary. */
+ }
+ </style>
+ <div id="header">
+ <div id="label">Heap details</div>
+ <div id="view_mode_container">
+ <span>View mode:</span>
+ <!-- View mode selector (added in Polymer.ready()) -->
+ </div>
+ </div>
+ <div id="contents">
+ <tr-ui-b-info-bar id="info_bar" hidden>
+ </tr-ui-b-info-bar>
+
+ <div id="info_text">No heap dump selected</div>
+
+ <div id="split_view">
+ <tr-ui-a-memory-dump-heap-details-path-view id="path_view">
+ </tr-ui-a-memory-dump-heap-details-path-view>
+ <tr-ui-b-drag-handle id="drag_handle"></tr-ui-b-drag-handle>
+ <tr-ui-a-memory-dump-heap-details-breakdown-view id="breakdown_view">
+ </tr-ui-a-memory-dump-heap-details-breakdown-view>
+ </div>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const Scalar = tr.b.Scalar;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const count_smallerIsBetter = tr.b.Unit.byName.count_smallerIsBetter;
+ const MultiDimensionalViewBuilder = tr.b.MultiDimensionalViewBuilder;
+ const TotalState = tr.b.MultiDimensionalViewNode.TotalState;
+
+ /** @{constructor} */
+ function HeapDumpTreeNode(
+ stackFrameNodes, dimension, title, heavyView, parentNode) {
+ this.dimension = dimension;
+ this.title = title;
+ this.parentNode = parentNode;
+
+ this.heavyView_ = heavyView;
+ this.stackFrameNodes_ = stackFrameNodes;
+ this.lazyCells_ = undefined;
+ this.lazyChildNodes_ = undefined;
+ }
+
+ HeapDumpTreeNode.prototype = {
+ get minDisplayedTotalState_() {
+ if (this.heavyView_) {
+ // Show lower-bound and exact values in heavy views.
+ return TotalState.LOWER_BOUND;
+ }
+ // Show only exact values in tree view.
+ return TotalState.EXACT;
+ },
+
+ get childNodes() {
+ if (!this.lazyChildNodes_) {
+ this.lazyChildNodes_ = new Map();
+ this.addDimensionChildNodes_(
+ tr.ui.analysis.HeapDetailsRowDimension.STACK_FRAME, 0);
+ this.addDimensionChildNodes_(
+ tr.ui.analysis.HeapDetailsRowDimension.OBJECT_TYPE, 1);
+ this.releaseStackFrameNodesIfPossible_();
+ }
+ return this.lazyChildNodes_;
+ },
+
+ get cells() {
+ if (!this.lazyCells_) {
+ this.addCells_();
+ this.releaseStackFrameNodesIfPossible_();
+ }
+ return this.lazyCells_;
+ },
+
+ releaseStackFrameNodesIfPossible_() {
+ if (this.lazyCells_ && this.lazyChildNodes_) {
+ // Don't unnecessarily hold a reference to the stack frame nodes when
+ // we don't need them anymore.
+ this.stackFrameNodes_ = undefined;
+ }
+ },
+
+ addDimensionChildNodes_(dimension, dimensionIndex) {
+ // Child title -> Timestamp (list index) -> Child
+ // MultiDimensionalViewNode.
+ const dimensionChildTitleToStackFrameNodes = tr.b.invertArrayOfDicts(
+ this.stackFrameNodes_,
+ node => this.convertStackFrameNodeDimensionToChildDict_(
+ node, dimensionIndex));
+
+ // Child title (list index) -> Child HeapDumpTreeNode.
+ const dimensionChildNodes = [];
+ for (const [childTitle, childStackFrameNodes] of
+ Object.entries(dimensionChildTitleToStackFrameNodes)) {
+ dimensionChildNodes.push(new HeapDumpTreeNode(childStackFrameNodes,
+ dimension, childTitle, this.heavyView_, this));
+ }
+ this.lazyChildNodes_.set(dimension, dimensionChildNodes);
+ },
+
+ convertStackFrameNodeDimensionToChildDict_(
+ stackFrameNode, dimensionIndex) {
+ const childDict = {};
+ let displayedChildrenTotalSize = 0;
+ let displayedChildrenTotalCount = 0;
+ let hasDisplayedChildren = false;
+ let allDisplayedChildrenHaveDisplayedCounts = true;
+ for (const child of stackFrameNode.children[dimensionIndex].values()) {
+ if (child.values[0].totalState < this.minDisplayedTotalState_) {
+ continue;
+ }
+ if (child.values[1].totalState < this.minDisplayedTotalState_) {
+ allDisplayedChildrenHaveDisplayedCounts = false;
+ }
+ childDict[child.title[dimensionIndex]] = child;
+ displayedChildrenTotalSize += child.values[0].total;
+ displayedChildrenTotalCount += child.values[1].total;
+ hasDisplayedChildren = true;
+ }
+
+ const nodeTotalSize = stackFrameNode.values[0].total;
+ const nodeTotalCount = stackFrameNode.values[1].total;
+
+ // Add '<other>' node if necessary in tree-view.
+ const hasUnclassifiedSizeOrCount =
+ displayedChildrenTotalSize < nodeTotalSize ||
+ displayedChildrenTotalCount < nodeTotalCount;
+ if (!this.heavyView_ && hasUnclassifiedSizeOrCount &&
+ hasDisplayedChildren) {
+ const otherTitle = stackFrameNode.title.slice();
+ otherTitle[dimensionIndex] = '<other>';
+ const otherNode = new tr.b.MultiDimensionalViewNode(otherTitle, 2);
+ childDict[otherTitle[dimensionIndex]] = otherNode;
+
+ // '<other>' node size.
+ otherNode.values[0].total = nodeTotalSize - displayedChildrenTotalSize;
+ otherNode.values[0].totalState = this.minDisplayedTotalState_;
+
+ // '<other>' node allocation count.
+ otherNode.values[1].total =
+ nodeTotalCount - displayedChildrenTotalCount;
+ // Don't show allocation count of the '<other>' node if there is a
+ // displayed child node that did NOT display allocation count.
+ otherNode.values[1].totalState =
+ allDisplayedChildrenHaveDisplayedCounts ?
+ this.minDisplayedTotalState_ : TotalState.NOT_PROVIDED;
+ }
+
+ return childDict;
+ },
+
+ addCells_() {
+ // Transform a chronological list of heap stack frame tree nodes into a
+ // dictionary of cells (where each cell contains a chronological list
+ // of the values of its numeric).
+ this.lazyCells_ = tr.ui.analysis.createCells(this.stackFrameNodes_,
+ function(stackFrameNode) {
+ const size = stackFrameNode.values[0].total;
+ const numerics = {
+ 'Size': new Scalar(sizeInBytes_smallerIsBetter, size)
+ };
+ const countValue = stackFrameNode.values[1];
+ if (countValue.totalState >= this.minDisplayedTotalState_) {
+ const count = countValue.total;
+ numerics.Count = new Scalar(
+ count_smallerIsBetter, count);
+ }
+ return numerics;
+ }, this);
+ }
+ };
+
+ Polymer({
+ is: 'tr-ui-a-memory-dump-heap-details-pane',
+ behaviors: [tr.ui.analysis.StackedPane],
+
+ created() {
+ this.heapDumps_ = undefined;
+ this.viewMode_ = undefined;
+ this.aggregationMode_ = undefined;
+ this.cachedBuilders_ = new Map();
+ },
+
+ ready() {
+ this.$.info_bar.message = 'Note: Values displayed in the heavy view ' +
+ 'are lower bounds (except for the root).';
+
+ Polymer.dom(this.$.view_mode_container).appendChild(
+ tr.ui.b.createSelector(
+ this, 'viewMode', 'memoryDumpHeapDetailsPane.viewMode',
+ MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW,
+ [
+ {
+ label: 'Top-down (Tree)',
+ value: MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW
+ },
+ {
+ label: 'Top-down (Heavy)',
+ value:
+ MultiDimensionalViewBuilder.ViewType.TOP_DOWN_HEAVY_VIEW
+ },
+ {
+ label: 'Bottom-up (Heavy)',
+ value:
+ MultiDimensionalViewBuilder.ViewType.BOTTOM_UP_HEAVY_VIEW
+ }
+ ]));
+
+ this.$.drag_handle.target = this.$.path_view;
+ this.$.drag_handle.horizontal = false;
+
+ // If the user selects a node in the path view, show its children in the
+ // breakdown view.
+ this.$.path_view.addEventListener('selected-node-changed', (function(e) {
+ this.$.breakdown_view.displayedNode = this.$.path_view.selectedNode;
+ }).bind(this));
+
+ // If the user double-clicks on a node in the breakdown view, select the
+ // node in the path view.
+ this.$.breakdown_view.addEventListener('enter-node', (function(e) {
+ this.$.path_view.selectedNode = e.node;
+ }).bind(this));
+ },
+
+ /**
+ * Sets the heap dumps and schedules rebuilding the pane.
+ *
+ * The provided value should be a chronological list of heap dumps. All
+ * dumps are assumed to belong to the same process and belong to the same
+ * allocator. Example:
+ *
+ * [
+ * tr.model.HeapDump {}, // Heap dump at timestamp 1.
+ * undefined, // Heap dump not provided at timestamp 2.
+ * tr.model.HeapDump {}, // Heap dump at timestamp 3.
+ * ]
+ */
+ set heapDumps(heapDumps) {
+ this.heapDumps_ = heapDumps;
+ this.scheduleRebuild_();
+ },
+
+ get heapDumps() {
+ return this.heapDumps_;
+ },
+
+ set aggregationMode(aggregationMode) {
+ this.aggregationMode_ = aggregationMode;
+ this.$.path_view.aggregationMode = aggregationMode;
+ this.$.breakdown_view.aggregationMode = aggregationMode;
+ },
+
+ get aggregationMode() {
+ return this.aggregationMode_;
+ },
+
+ set viewMode(viewMode) {
+ this.viewMode_ = viewMode;
+ this.scheduleRebuild_();
+ },
+
+ get viewMode() {
+ return this.viewMode_;
+ },
+
+ get heavyView() {
+ switch (this.viewMode) {
+ case MultiDimensionalViewBuilder.ViewType.TOP_DOWN_HEAVY_VIEW:
+ case MultiDimensionalViewBuilder.ViewType.BOTTOM_UP_HEAVY_VIEW:
+ return true;
+ default:
+ return false;
+ }
+ },
+
+ onRebuild_() {
+ if (this.heapDumps_ === undefined ||
+ this.heapDumps_.length === 0) {
+ // Show the info text (hide the table and the view mode selector).
+ this.$.info_text.style.display = 'block';
+ this.$.split_view.style.display = 'none';
+ this.$.view_mode_container.style.display = 'none';
+ this.$.info_bar.hidden = true;
+ this.$.path_view.selectedNode = undefined;
+ return;
+ }
+
+ // Show the table and the view mode selector (hide the info text).
+ this.$.info_text.style.display = 'none';
+ this.$.split_view.style.display = 'flex';
+ this.$.view_mode_container.style.display = 'block';
+
+ // Show the info bar if in heavy view mode.
+ this.$.info_bar.hidden = !this.heavyView;
+
+ this.$.path_view.selectedNode = this.createHeapTree_();
+ this.$.path_view.rebuild();
+ this.$.breakdown_view.rebuild();
+ },
+
+ createHeapTree_() {
+ const definedHeapDump = this.heapDumps_.find(x => x);
+ if (definedHeapDump === undefined) return undefined;
+
+ // The title of the root node is the name of the allocator.
+ const rootRowTitle = definedHeapDump.allocatorName;
+
+ const stackFrameTrees = this.createStackFrameTrees_(this.heapDumps_);
+
+ return new HeapDumpTreeNode(stackFrameTrees,
+ tr.ui.analysis.HeapDetailsRowDimension.ROOT, rootRowTitle,
+ this.heavyView);
+ },
+
+ createStackFrameTrees_(heapDumps) {
+ const builders = heapDumps.map(heapDump => this.createBuilder_(heapDump));
+ const views = builders.map(builder => {
+ if (builder === undefined) return undefined;
+ return builder.buildView(this.viewMode);
+ });
+ return views;
+ },
+
+ createBuilder_(heapDump) {
+ if (heapDump === undefined) return undefined;
+
+ if (this.cachedBuilders_.has(heapDump)) {
+ return this.cachedBuilders_.get(heapDump);
+ }
+
+ const dimensions = 2; // stack frames, object type
+ const valueCount = 2; // size, count
+ const builder = new MultiDimensionalViewBuilder(dimensions, valueCount);
+
+ // Build the heap tree.
+ for (const entry of heapDump.entries) {
+ const leafStackFrame = entry.leafStackFrame;
+ const stackTracePath = leafStackFrame === undefined ?
+ [] : leafStackFrame.getUserFriendlyStackTrace().reverse();
+
+ const objectTypeName = entry.objectTypeName;
+ const objectTypeNamePath = objectTypeName === undefined ?
+ [] : [objectTypeName];
+
+ const valueKind = entry.valuesAreTotals ?
+ MultiDimensionalViewBuilder.ValueKind.TOTAL :
+ MultiDimensionalViewBuilder.ValueKind.SELF;
+
+ builder.addPath([stackTracePath, objectTypeNamePath],
+ [entry.size, entry.count],
+ valueKind);
+ }
+
+ builder.complete = heapDump.isComplete;
+ this.cachedBuilders_.set(heapDump, builder);
+ return builder;
+ },
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_pane_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_pane_test.html
new file mode 100644
index 00000000000..947cc532e7a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_pane_test.html
@@ -0,0 +1,4045 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel='import' href='/tracing/base/multi_dimensional_view.html'>
+<link rel='import' href='/tracing/base/unit.html'>
+<link rel='import' href='/tracing/base/utils.html'>
+<link rel='import' href='/tracing/core/test_utils.html'>
+<link rel='import' href='/tracing/model/heap_dump.html'>
+<link rel='import' href='/tracing/model/memory_dump_test_utils.html'>
+<link rel='import'
+ href='/tracing/ui/analysis/memory_dump_heap_details_pane.html'>
+<link rel='import'
+ href='/tracing/ui/analysis/memory_dump_sub_view_test_utils.html'>
+<link rel='import' href='/tracing/ui/analysis/memory_dump_sub_view_util.html'>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ViewType = tr.b.MultiDimensionalViewBuilder.ViewType;
+ const TOP_DOWN_TREE_VIEW = ViewType.TOP_DOWN_TREE_VIEW;
+ const TOP_DOWN_HEAVY_VIEW = ViewType.TOP_DOWN_HEAVY_VIEW;
+ const BOTTOM_UP_HEAVY_VIEW = ViewType.BOTTOM_UP_HEAVY_VIEW;
+ const HeapDump = tr.model.HeapDump;
+ const HeapDetailsRowDimension = tr.ui.analysis.HeapDetailsRowDimension;
+ const ROOT = HeapDetailsRowDimension.ROOT;
+ const STACK_FRAME = HeapDetailsRowDimension.STACK_FRAME;
+ const OBJECT_TYPE = HeapDetailsRowDimension.OBJECT_TYPE;
+ const TitleColumn = tr.ui.analysis.TitleColumn;
+ const NumericMemoryColumn = tr.ui.analysis.NumericMemoryColumn;
+ const AggregationMode = tr.ui.analysis.MemoryColumn.AggregationMode;
+ const addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
+ const addProcessMemoryDump =
+ tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
+ const checkColumns = tr.ui.analysis.checkColumns;
+ const checkNumericFields = tr.ui.analysis.checkNumericFields;
+ const checkSizeNumericFields = tr.ui.analysis.checkSizeNumericFields;
+ const isElementDisplayed = tr.ui.analysis.isElementDisplayed;
+ const count_smallerIsBetter = tr.b.Unit.byName.count_smallerIsBetter;
+
+ function createHeapDumps(withCount) {
+ const model = new tr.Model();
+ const process = model.getOrCreateProcess(1);
+
+ function addHeapEntry(heapDump, stackFrames, objectTypeName, size, count) {
+ const leafStackFrame = stackFrames === undefined ? undefined :
+ tr.c.TestUtils.newStackTrace(model, stackFrames);
+ heapDump.addEntry(leafStackFrame, objectTypeName, size,
+ withCount ? count : undefined);
+ }
+
+ // First timestamp.
+ const gmd1 = addGlobalMemoryDump(model, {ts: -10});
+ const pmd1 = addProcessMemoryDump(gmd1, process, {ts: -11});
+ const hd1 = new HeapDump(pmd1, 'partition_alloc');
+
+ addHeapEntry(hd1, undefined /* sum over all traces */,
+ undefined /* sum over all types */, 4194304 /* 4 MiB */, 1000);
+ addHeapEntry(hd1, undefined /* sum over all traces */, 'v8::Context',
+ 1048576 /* 1 MiB */, 200);
+ addHeapEntry(hd1, undefined /* sum over all traces */, 'blink::Node',
+ 331776 /* 324 KiB */, 10);
+ addHeapEntry(hd1, ['MessageLoop::RunTask'],
+ undefined /* sum over all types */, 4194304 /* 4 MiB */, 1000);
+ addHeapEntry(hd1, ['MessageLoop::RunTask'], 'v8::Context',
+ 1048576 /* 1 MiB */, 200);
+
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'FunctionCall'],
+ undefined /* sum over all types */, 1406976 /* 1.3 MiB */, 299);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'FunctionCall'],
+ 'blink::Node', 331776 /* 324 KiB */, 10);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'FunctionCall'], 'v8::Context',
+ 1024000 /* 1000 KiB */, 176);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'FunctionCall', '<self>'],
+ undefined /* sum over all types */, 102400 /* 100 KiB */, 30);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'FunctionCall', 'V8.Execute'],
+ 'v8::Context', 716800 /* 700 KiB */, 100);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'FunctionCall', 'V8.Execute'],
+ undefined /* sum over all types */, 1048576 /* 1 MiB */, 101);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'FunctionCall', 'FunctionCall'],
+ undefined /* sum over all types */,
+ 153600 /* 150 KiB, lower than the actual sum (should be ignored) */,
+ 25 /* the allocation count should, however, NOT be ignored */);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'FunctionCall', 'FunctionCall'],
+ 'v8::Context', 153600 /* 150 KiB */, 15);
+
+ // The following entry should not appear in the tree-view because there is
+ // no entry for its parent stack frame.
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'MissingParent', 'FunctionCall'],
+ undefined /* sum over all types */, 10 /* 10 B */, 2);
+
+ // The following entry should not appear in the tree-view because there is
+ // no sum over all types (for the given stack trace). However, it will lead
+ // to a visible increase of the (incorrectly provided) sum over all types
+ // of MessageLoop::RunTask -> FunctionCall -> FunctionCall by 50 KiB.
+ addHeapEntry(hd1,
+ ['MessageLoop::RunTask', 'FunctionCall', 'FunctionCall',
+ 'FunctionCall'],
+ 'MissingSumOverAllTypes', 51200 /* 50 KiB */, 9);
+
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'V8.Execute'],
+ undefined /* sum over all types */, 2404352 /* 2.3 MiB */, 399);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall'],
+ undefined /* sum over all types */, 2404352 /* 2.3 MiB */, 399);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall'],
+ 'v8::Context', 20480 /* 20 KiB */, 6);
+ addHeapEntry(hd1,
+ ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall', '<self>'],
+ 'v8::Context', 15360 /* 15 KiB */, 5);
+ addHeapEntry(hd1,
+ ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall', 'V8.Execute'],
+ undefined /* sum over all types */, 2097152 /* 2 MiB */, 99);
+ addHeapEntry(hd1,
+ ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall', 'V8.Execute',
+ 'V8.Execute'],
+ undefined /* sum over all types */, 2097152 /* 2 MiB */, 99);
+ addHeapEntry(hd1,
+ ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall', '<self>'],
+ undefined /* sum over all types */, 307200 /* 300 KiB */, 300);
+
+ // Second timestamp.
+ const gmd2 = addGlobalMemoryDump(model, {ts: 10});
+ const pmd2 = addProcessMemoryDump(gmd2, process, {ts: 11});
+ const hd2 = new HeapDump(pmd2, 'partition_alloc');
+
+ addHeapEntry(hd2, undefined /* sum over all traces */,
+ undefined /* sum over all types */,
+ 3145728 /* 3 MiB, lower than the actual sum (should be ignored) */,
+ 900 /* the allocation count should, however, NOT be ignored */);
+ addHeapEntry(hd2, undefined /* sum over all traces */,
+ 'v8::Context', 1258291 /* 1.2 MiB */, 520);
+ addHeapEntry(hd2, undefined /* sum over all traces */,
+ 'blink::Node', 1048576 /* 1 MiB */, 5);
+ addHeapEntry(hd2, ['<self>'], undefined /* sum over all types */,
+ 131072 /* 128 KiB */, 16);
+ addHeapEntry(hd2, ['<self>'], 'v8::Context', 131072 /* 128 KiB */, 16);
+ addHeapEntry(hd2, ['MessageLoop::RunTask'],
+ undefined /* sum over all types */, 4823449 /* 4.6 MiB */, 884);
+ addHeapEntry(hd2, ['MessageLoop::RunTask'], 'v8::Context',
+ 1127219 /* 1.1 MiB */, 317);
+
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall'],
+ undefined /* sum over all types */, 2170880 /* 2.1 MiB */, 600);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall'], 'v8::Context',
+ 1024000 /* 1000 KiB */, 500);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall'], 'blink::Node',
+ 819200 /* 800 KiB */, 4);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall', 'V8.Execute'],
+ undefined /* sum over all types */, 1572864 /* 1.5 MiB */, 270);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall', 'V8.Execute'],
+ 'v8::Context', 614400 /* 600 KiB */, 123);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall', 'V8.Execute'],
+ 'blink::Node', 819200 /* 800 KiB */, 4);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall', 'FunctionCall'],
+ undefined /* sum over all types */, 204800 /* 200 KiB */, 313);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall', 'FunctionCall'],
+ 'v8::Context', 122880 /* 120 KiB */, 270);
+ addHeapEntry(hd2,
+ ['MessageLoop::RunTask', 'FunctionCall', 'FunctionCall',
+ 'FunctionCall'],
+ undefined /* sum over all types */, 204800 /* 200 KiB */, 313);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'FunctionCall', '<self>'],
+ undefined /* sum over all types */, 393216 /* 384 KiB */, 17);
+
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'V8.Execute'],
+ undefined /* sum over all types */, 2621440 /* 2.5 MiB */, 199);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall'],
+ undefined /* sum over all types */, 2621440 /* 2.5 MiB */, 199);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall'],
+ 'v8::Context', 20480 /* 20 KiB */, 4);
+ addHeapEntry(hd2, ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall'],
+ 'WTF::StringImpl', 126362 /* 123.4 KiB */, 56);
+ addHeapEntry(hd2,
+ ['MessageLoop::RunTask', 'V8.Execute', 'FunctionCall', 'V8.Execute'],
+ undefined /* sum over all types */, 2516582 /* 2.4 MiB */, 158);
+
+ return [hd1, hd2];
+ }
+
+ function createSelfHeapDumps(withCount) {
+ const model = new tr.Model();
+ const process = model.getOrCreateProcess(1);
+
+ function addHeapEntry(heapDump, stackFrames, objectTypeName, size, count) {
+ const leafStackFrame = stackFrames === undefined ? undefined :
+ tr.c.TestUtils.newStackTrace(model, stackFrames);
+ heapDump.addEntry(leafStackFrame, objectTypeName, size,
+ withCount ? count : undefined, false /* valuesAreTotals */);
+ }
+
+ // First timestamp.
+ const gmd1 = addGlobalMemoryDump(model, {ts: -10});
+ const pmd1 = addProcessMemoryDump(gmd1, process, {ts: -11});
+ const hd1 = new HeapDump(pmd1, 'partition_alloc');
+ hd1.isComplete = true;
+
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'a', 'AllocSomething'],
+ 'v8::Context', 1024, 100);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'a', 'b', 'AllocSomething'],
+ 'v8::Context', 1024, 100);
+ addHeapEntry(hd1, ['MessageLoop::RunTask', 'a', 'b', 'c', 'AllocSomething'],
+ 'v8::Context', 1024, 100);
+
+ return [hd1];
+ }
+
+
+ function checkDisplayedElements(viewEl, displayExpectations) {
+ assert.strictEqual(isElementDisplayed(viewEl.$.info_text),
+ displayExpectations.infoText);
+ assert.strictEqual(isElementDisplayed(viewEl.$.info_bar),
+ displayExpectations.infoBar);
+ assert.strictEqual(isElementDisplayed(viewEl.$.split_view),
+ displayExpectations.tableAndSplitView);
+ assert.strictEqual(isElementDisplayed(viewEl.$.view_mode_container),
+ displayExpectations.tableAndSplitView);
+ }
+
+ const EXPECTED_COLUMNS_WITHOUT_COUNT = [
+ { title: 'Current path', type: TitleColumn, noAggregation: true },
+ { title: 'Size', type: NumericMemoryColumn }
+ ];
+
+ const EXPECTED_COLUMNS_WITH_COUNT = EXPECTED_COLUMNS_WITHOUT_COUNT.concat([
+ { title: 'Count', type: NumericMemoryColumn },
+ ]);
+
+ const EXPECTED_CELLS = ['Size', 'Count'];
+
+ function checkNode(node, expectedNodeStructure, expectedParentNode) {
+ assert.strictEqual(node.title, expectedNodeStructure.title);
+ assert.strictEqual(node.dimension, expectedNodeStructure.dimension);
+ assert.strictEqual(node.parentNode, expectedParentNode);
+
+ // Check that there AREN'T any cells that we are NOT expecting.
+ const cells = node.cells;
+ assert.includeMembers(EXPECTED_CELLS, Object.keys(cells));
+
+ const sizeCell = cells.Size;
+ const sizeFields = sizeCell ? sizeCell.fields : undefined;
+ checkSizeNumericFields(sizeFields, undefined, expectedNodeStructure.size);
+
+ const countCell = cells.Count;
+ const countFields = countCell ? countCell.fields : undefined;
+ checkNumericFields(countFields, undefined, expectedNodeStructure.count,
+ count_smallerIsBetter);
+
+ assert.strictEqual(node.childNodes.size, 2);
+
+ // If |expectedNodeStructure.children| is undefined, check that there are
+ // no child nodes.
+ if (!expectedNodeStructure.children) {
+ assert.lengthOf(node.childNodes.get(STACK_FRAME), 0);
+ assert.lengthOf(node.childNodes.get(OBJECT_TYPE), 0);
+ return;
+ }
+
+ // If |expectedNodeStructure.children| is just a number, check total number
+ // of child nodes.
+ if (typeof expectedNodeStructure.children === 'number') {
+ assert.strictEqual(expectedNodeStructure.children,
+ node.childNodes.get(STACK_FRAME).length +
+ node.childNodes.get(OBJECT_TYPE).length);
+ return;
+ }
+
+ // Check child nodes wrt both dimensions.
+ checkNodes(node.childNodes.get(STACK_FRAME),
+ expectedNodeStructure.children.filter(c => c.dimension === STACK_FRAME),
+ node);
+ checkNodes(node.childNodes.get(OBJECT_TYPE),
+ expectedNodeStructure.children.filter(c => c.dimension === OBJECT_TYPE),
+ node);
+ }
+
+ function checkNodes(nodes, expectedStructure, expectedParentNode) {
+ assert.lengthOf(nodes, expectedStructure.length);
+ for (let i = 0; i < expectedStructure.length; i++) {
+ checkNode(nodes[i], expectedStructure[i], expectedParentNode);
+ }
+ }
+
+ function checkSplitView(viewEl, expectedConfig, expectedStructure) {
+ checkDisplayedElements(viewEl, {
+ infoText: false,
+ tableAndSplitView: true,
+ infoBar: !!expectedConfig.expectedInfoBarDisplayed
+ });
+
+ // Both the split view and breakdown view should be displaying the same
+ // node.
+ const selectedNode = viewEl.$.path_view.selectedNode;
+ assert.strictEqual(viewEl.$.breakdown_view.displayedNode, selectedNode);
+ checkNodes([selectedNode], expectedStructure,
+ undefined /* expectedParentNode */);
+
+ // TODO: Add proper tests for tr-ui-a-memory-dump-heap-details-path-view
+ // and tr-ui-a-memory-dump-heap-details-breakdown-view.
+ const expectedColumns = expectedConfig.expectedCountColumns ?
+ EXPECTED_COLUMNS_WITH_COUNT : EXPECTED_COLUMNS_WITHOUT_COUNT;
+ checkColumns(viewEl.$.path_view.$.table.tableColumns, expectedColumns,
+ expectedConfig.expectedAggregationMode);
+ }
+
+ function changeView(viewEl, viewType) {
+ tr.ui.b.findDeepElementMatching(viewEl, 'select').selectedValue = viewType;
+ viewEl.rebuild();
+ }
+
+ test('instantiate_empty', function() {
+ tr.ui.analysis.createAndCheckEmptyPanes(this,
+ 'tr-ui-a-memory-dump-heap-details-pane', 'heapDumps',
+ function(viewEl) {
+ // Check that the info text is shown.
+ checkDisplayedElements(viewEl, {
+ infoText: true,
+ tableAndSplitView: false,
+ infoBar: false
+ });
+ });
+ });
+
+ test('instantiate_noEntries', function() {
+ const heapDumps = createHeapDumps(false).slice(0, 1);
+ heapDumps[0].entries = [];
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-heap-details-pane');
+ viewEl.heapDumps = heapDumps;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ // Top-down tree view (default).
+ checkSplitView(viewEl,
+ { /* empty expectedConfig */ },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [0],
+ defined: [true]
+ }
+ ]);
+
+ changeView(viewEl, TOP_DOWN_HEAVY_VIEW);
+ checkSplitView(viewEl,
+ { expectedInfoBarDisplayed: true },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [0],
+ defined: [true]
+ }
+ ]);
+
+ changeView(viewEl, BOTTOM_UP_HEAVY_VIEW);
+ checkSplitView(viewEl,
+ { expectedInfoBarDisplayed: true },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [0],
+ defined: [true]
+ }
+ ]);
+
+ changeView(viewEl, TOP_DOWN_TREE_VIEW);
+ });
+
+ test('instantiate_single', function() {
+ const heapDumps = createHeapDumps(false).slice(0, 1);
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-heap-details-pane');
+ viewEl.heapDumps = heapDumps;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ // Top-down tree view (default).
+ checkSplitView(viewEl,
+ { /* empty expectedConfig */ },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [4194304],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [4194304],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1406976],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [102400],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [331776],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600 + 51200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [153600],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [51200],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1024000],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [153600],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [307200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [291840],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [5120],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [2383872],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [382976],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [153600],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [24576],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [3145728],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [153600],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [24576],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [2813952],
+ defined: [true],
+ }
+ ]
+ }
+ ]);
+
+ changeView(viewEl, BOTTOM_UP_HEAVY_VIEW);
+ checkSplitView(viewEl,
+ { expectedInfoBarDisplayed: true },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [4194304],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [4194304],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576],
+ defined: [true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [3811338],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1406976],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1024000],
+ defined: [true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [204800],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [204800],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [153600],
+ defined: [true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [153600],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [153600],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MissingParent',
+ size: [10],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [10],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [20480],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [331776],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1044480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1024000],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [153600],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [20480],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [409600],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [409600],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [102400],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [307200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [307200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [15360],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [15360],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [15360],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [3452928],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [3145728],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [2097152],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [716800],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [2097152],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [2097152],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [737280],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [716800],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [716800],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [20480],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MissingParent',
+ size: [10],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [10],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1048576],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1044480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1024000],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [153600],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [20480],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [15360],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [15360],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [737280],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [716800],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [716800],
+ defined: [true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [20480],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [331776],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [331776],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [331776],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]);
+
+ changeView(viewEl, TOP_DOWN_HEAVY_VIEW);
+ checkSplitView(viewEl,
+ { expectedInfoBarDisplayed: true }, [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [4194304],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [4194304],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1406976],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [102400],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600 + 51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [153600],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1024000],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MissingParent',
+ size: [10],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [10],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [307200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [331776],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1406976 + 10 + 2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [102400 + 307200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [1048576 + 2097152],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600 + 51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [153600],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1024000 + 20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [102400 + 307200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [1048576 + 2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [2404352],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [307200],
+ defined: [true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152],
+ defined: [true],
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800 + 20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MissingParent',
+ size: [10],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [10],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1048576],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000 + 20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800 + 20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [331776],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [331776],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [331776],
+ defined: [true],
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200],
+ defined: [true],
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]);
+ });
+
+ test('instantiate_multipleDiff', function() {
+ const heapDumps = createHeapDumps(true /* with allocation counts */);
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-heap-details-pane');
+ viewEl.heapDumps = heapDumps;
+ viewEl.aggregationMode = AggregationMode.DIFF;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ changeView(viewEl, TOP_DOWN_HEAVY_VIEW);
+ checkSplitView(viewEl,
+ {
+ expectedAggregationMode: AggregationMode.DIFF,
+ expectedInfoBarDisplayed: true,
+ expectedCountColumns: true
+ },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [4194304, 4954521],
+ count: [1000, 900],
+ averageSize: [4194304 / 1000, 4954521 / 900],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [4194304, 4823449],
+ count: [1000, 884],
+ averageSize: [4194304 / 1000, 4823449 / 884],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1406976, 2170880],
+ count: [299, 600],
+ averageSize: [1406976 / 299, 2170880 / 600],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [102400, 393216],
+ count: [30, 17],
+ averageSize: [102400 / 30, 393216 / 17],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [1048576, 1572864],
+ count: [101, 270],
+ averageSize: [1048576 / 101, 1572864 / 270],
+ defined: [true, true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [204800, 204800],
+ count: [25, 313],
+ averageSize: [204800 / 25, 204800 / 313],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, 204800],
+ count: [9, 313],
+ averageSize: [51200 / 9, 204800 / 313],
+ defined: [true, true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776, 819200],
+ count: [10, 4],
+ averageSize: [331776 / 10, 819200 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1024000, 1024000],
+ count: [176, 500],
+ averageSize: [1024000 / 176, 1024000 / 500],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MissingParent',
+ size: [10, undefined],
+ count: [2, undefined],
+ averageSize: [10 / 2, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [10, undefined],
+ count: [2, undefined],
+ averageSize: [10 / 2, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2404352, 2621440],
+ count: [399, 199],
+ averageSize: [2404352 / 399, 2621440 / 199],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [2404352, 2621440],
+ count: [399, 199],
+ averageSize: [2404352 / 399, 2621440 / 199],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [307200, undefined],
+ count: [300, undefined],
+ averageSize: [307200 / 300, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152, 2516582],
+ count: [99, 158],
+ averageSize: [2097152 / 99, 2516582 / 158],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152, undefined],
+ count: [99, undefined],
+ averageSize: [2097152 / 99, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'WTF::StringImpl',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'WTF::StringImpl',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576, 1127219],
+ count: [200, 504],
+ averageSize: [1048576 / 200, 1127219 / 504],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000, 1024000],
+ count: [176, 500],
+ averageSize: [1024000 / 176, 1024000 / 500],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776, 819200],
+ count: [10, 4],
+ averageSize: [331776 / 10, 819200 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [331776, 819200],
+ count: [10, 4],
+ averageSize: [331776 / 10, 819200 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'WTF::StringImpl',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [3811338, 4792320],
+ count: [700, 799],
+ averageSize: [3811338 / 700, 4792320 / 799],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [409600, 393216],
+ count: [330, 17],
+ averageSize: [409600 / 330, 393216 / 17],
+ defined: [true, true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [3145728, 4089446],
+ count: [200, 428],
+ averageSize: [3145728 / 200, 4089446 / 428],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152, undefined],
+ count: [99, undefined],
+ averageSize: [2097152 / 99, undefined],
+ defined: [true, false]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [204800, 204800],
+ count: [25, 313],
+ averageSize: [204800 / 25, 204800 / 313],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, 204800],
+ count: [9, 313],
+ averageSize: [51200 / 9, 204800 / 313],
+ defined: [true, true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776, 819200],
+ count: [10, 4],
+ averageSize: [331776 / 10, 819200 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1044480, 1044480],
+ count: [182, 504],
+ averageSize: [1044480 / 182, 1044480 / 504],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'WTF::StringImpl',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [409600, 524288],
+ count: [330, 33],
+ averageSize: [409600 / 330, 524288 / 33],
+ defined: [true, true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360, 131072],
+ count: [5, 16],
+ averageSize: [15360 / 5, 131072 / 16],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [3452928, 4194304],
+ count: [500, 469],
+ averageSize: [3452928 / 500, 4194304 / 469],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [2404352, 2621440],
+ count: [399, 199],
+ averageSize: [2404352 / 399, 2621440 / 199],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [307200, undefined],
+ count: [300, undefined],
+ averageSize: [307200 / 300, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152, 2516582],
+ count: [99, 158],
+ averageSize: [2097152 / 99, 2516582 / 158],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152, undefined],
+ count: [99, undefined],
+ averageSize: [2097152 / 99, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'WTF::StringImpl',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152, undefined],
+ count: [99, undefined],
+ averageSize: [2097152 / 99, undefined],
+ defined: [true, false]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [737280, 634880],
+ count: [106, 127],
+ averageSize: [737280 / 106, 634880 / 127],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'WTF::StringImpl',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'MissingParent',
+ size: [10, undefined],
+ count: [2, undefined],
+ averageSize: [10 / 2, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [10, undefined],
+ count: [2, undefined],
+ averageSize: [10 / 2, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576, 1258291],
+ count: [200, 520],
+ averageSize: [1048576 / 200, 1258291 / 520],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1048576, 1127219],
+ count: [200, 504],
+ averageSize: [1048576 / 200, 1127219 / 504],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000, 1024000],
+ count: [176, 500],
+ averageSize: [1024000 / 176, 1024000 / 500],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1044480, 1044480],
+ count: [182, 504],
+ averageSize: [1044480 / 182, 1044480 / 504],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, 131072],
+ count: [5, 16],
+ averageSize: [15360 / 5, 131072 / 16],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [737280, 634880],
+ count: [106, 127],
+ averageSize: [737280 / 106, 634880 / 127],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776, 1048576],
+ count: [10, 5],
+ averageSize: [331776 / 10, 1048576 / 5],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [331776, 819200],
+ count: [10, 4],
+ averageSize: [331776 / 10, 819200 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [331776, 819200],
+ count: [10, 4],
+ averageSize: [331776 / 10, 819200 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [331776, 819200],
+ count: [10, 4],
+ averageSize: [331776 / 10, 819200 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'MissingSumOverAllTypes',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [51200, undefined],
+ count: [9, undefined],
+ averageSize: [51200 / 9, undefined],
+ defined: [true, false]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'WTF::StringImpl',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]);
+
+ changeView(viewEl, TOP_DOWN_TREE_VIEW);
+ checkSplitView(viewEl,
+ {
+ expectedAggregationMode: AggregationMode.DIFF,
+ expectedCountColumns: true
+ },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [4194304, 4954521],
+ count: [1000, 900],
+ averageSize: [4194304 / 1000, 4954521 / 900],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [4194304, 4823449],
+ count: [1000, 884],
+ averageSize: [4194304 / 1000, 4823449 / 884],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1406976, 2170880],
+ count: [299, 600],
+ averageSize: [1406976 / 299, 2170880 / 600],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [102400, 393216],
+ count: [30, 17],
+ averageSize: [102400 / 30, 393216 / 17],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [1048576, 1572864],
+ count: [101, 270],
+ averageSize: [1048576 / 101, 1572864 / 270],
+ defined: [true, true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [331776, 139264],
+ count: [1, 143],
+ averageSize: [331776 / 1, 139264 / 143],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [204800, 204800],
+ count: [25, 313],
+ averageSize: [204800 / 25, 204800 / 313],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [undefined, 204800],
+ count: [undefined, 313],
+ averageSize: [undefined, 204800 / 313],
+ defined: [false, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [51200, 81920],
+ count: [10, 43],
+ averageSize: [51200 / 10, 81920 / 43],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [51200, undefined],
+ count: [143, undefined],
+ averageSize: [51200 / 143, undefined],
+ defined: [true, false]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776, 819200],
+ count: [10, 4],
+ averageSize: [331776 / 10, 819200 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [undefined, 819200],
+ count: [undefined, 4],
+ averageSize: [undefined, 819200 / 4],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1024000, 1024000],
+ count: [176, 500],
+ averageSize: [1024000 / 176, 1024000 / 500],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [153600, 286720],
+ count: [61, 107],
+ averageSize: [153600 / 61, 286720 / 107],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [51200, 327680],
+ count: [113, 96],
+ averageSize: [51200 / 113, 327680 / 96],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2404352, 2621440],
+ count: [399, 199],
+ averageSize: [2404352 / 399, 2621440 / 199],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [2404352, 2621440],
+ count: [399, 199],
+ averageSize: [2404352 / 399, 2621440 / 199],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [307200, undefined],
+ count: [300, undefined],
+ averageSize: [307200 / 300, undefined],
+ defined: [true, false],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [291840, undefined],
+ count: [295, undefined],
+ averageSize: [291840 / 295, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152, 2516582],
+ count: [99, 158],
+ averageSize: [2097152 / 99, 2516582 / 158],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [2097152, undefined],
+ count: [99, undefined],
+ averageSize: [2097152 / 99, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [undefined, 104858],
+ count: [undefined, 41],
+ averageSize: [undefined, 104858 / 41],
+ defined: [false, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [20480, 20480],
+ count: [6, 4],
+ averageSize: [20480 / 6, 20480 / 4],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [15360, undefined],
+ count: [5, undefined],
+ averageSize: [15360 / 5, undefined],
+ defined: [true, false]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [5120, undefined],
+ count: [1, undefined],
+ averageSize: [5120 / 1, undefined],
+ defined: [true, false]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [2383872, 2474598],
+ count: [393, 139],
+ averageSize: [2383872 / 393, 2474598 / 139],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'WTF::StringImpl',
+ size: [undefined, 126362],
+ count: [undefined, 56],
+ averageSize: [undefined, 126362 / 56],
+ defined: [false, true]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [382976, 31129],
+ count: [302, 85],
+ averageSize: [382976 / 302, 31129 / 85],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576, 1127219],
+ count: [200, 504],
+ averageSize: [1048576 / 200, 1127219 / 504],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000, 1024000],
+ count: [176, 500],
+ averageSize: [1024000 / 176, 1024000 / 500],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [153600, 286720],
+ count: [61, 107],
+ averageSize: [153600 / 61, 286720 / 107],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [24576, 103219],
+ count: [24, 4],
+ averageSize: [24576 / 24, 103219 / 4],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [3145728, 3696230],
+ count: [800, 380],
+ averageSize: [3145728 / 800, 3696230 / 380],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [undefined, 131072],
+ count: [undefined, 16],
+ averageSize: [undefined, 131072 / 16],
+ defined: [false, true],
+ children: [
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [undefined, 131072],
+ count: [undefined, 16],
+ averageSize: [undefined, 131072 / 16],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'v8::Context',
+ size: [1048576, 1258291],
+ count: [200, 520],
+ averageSize: [1048576 / 200, 1258291 / 520],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'MessageLoop::RunTask',
+ size: [1048576, 1127219],
+ count: [200, 504],
+ averageSize: [1048576 / 200, 1127219 / 504],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [1024000, 1024000],
+ count: [176, 500],
+ averageSize: [1024000 / 176, 1024000 / 500],
+ defined: [true, true],
+ children: [
+ {
+ dimension: STACK_FRAME,
+ title: 'V8.Execute',
+ size: [716800, 614400],
+ count: [100, 123],
+ averageSize: [716800 / 100, 614400 / 123],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: 'FunctionCall',
+ size: [153600, 122880],
+ count: [15, 270],
+ averageSize: [153600 / 15, 122880 / 270],
+ defined: [true, true]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [153600, 286720],
+ count: [61, 107],
+ averageSize: [153600 / 61, 286720 / 107],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<other>',
+ size: [24576, 103219],
+ count: [24, 4],
+ averageSize: [24576 / 24, 103219 / 4],
+ defined: [true, true]
+ }
+ ]
+ },
+ {
+ dimension: STACK_FRAME,
+ title: '<self>',
+ size: [undefined, 131072],
+ count: [undefined, 16],
+ averageSize: [undefined, 131072 / 16],
+ defined: [false, true]
+ }
+ ]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: 'blink::Node',
+ size: [331776, 1048576],
+ count: [10, 5],
+ averageSize: [331776 / 10, 1048576 / 5],
+ defined: [true, true]
+ },
+ {
+ dimension: OBJECT_TYPE,
+ title: '<other>',
+ size: [2813952, 2647654],
+ count: [790, 375],
+ averageSize: [2813952 / 790, 2647654 / 375],
+ defined: [true, true]
+ }
+ ]
+ }
+ ]);
+ });
+
+ test('instantiate_multipleMax', function() {
+ const heapDumps = createHeapDumps(false);
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-heap-details-pane');
+ viewEl.heapDumps = heapDumps;
+ viewEl.aggregationMode = AggregationMode.MAX;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ changeView(viewEl, TOP_DOWN_HEAVY_VIEW);
+ checkSplitView(viewEl,
+ {
+ expectedAggregationMode: AggregationMode.MAX,
+ expectedInfoBarDisplayed: true
+ },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [4194304, 4954521],
+ defined: [true, true],
+ children: 9 // No need to check the full structure again.
+ }
+ ]);
+ });
+
+ test('instantiate_multipleWithUndefined', function() {
+ const heapDumps = createHeapDumps(false);
+ heapDumps.splice(1, 0, undefined);
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-heap-details-pane');
+ viewEl.heapDumps = heapDumps;
+ viewEl.aggregationMode = AggregationMode.DIFF;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ // Top-down tree view (default).
+ checkSplitView(viewEl,
+ { expectedAggregationMode: AggregationMode.DIFF },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [4194304, undefined, 4954521],
+ defined: [true, false, true],
+ children: 5 // No need to check the full structure again.
+ }
+ ]);
+ });
+
+ test('instantiate_selfHeapSingle', function() {
+ const heapDumps = createSelfHeapDumps(true).slice(0, 1);
+
+ const viewEl = tr.ui.analysis.createTestPane(
+ 'tr-ui-a-memory-dump-heap-details-pane');
+ viewEl.heapDumps = heapDumps;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ // Top-down tree view (default).
+ checkSplitView(viewEl,
+ { expectedCountColumns: true },
+ [
+ {
+ dimension: ROOT,
+ title: 'partition_alloc',
+ size: [1024 * 3],
+ count: [300],
+ defined: [true],
+ children: 2 // No need to check the full structure again.
+ }
+ ]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_path_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_path_view.html
new file mode 100644
index 00000000000..1cc3c8d7e5f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_path_view.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_heap_details_util.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/analysis/rebuildable_behavior.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_context_controller.html">
+
+<dom-module id='tr-ui-a-memory-dump-heap-details-path-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ </style>
+ <tr-v-ui-scalar-context-controller></tr-v-ui-scalar-context-controller>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const DOWNWARDS_ARROW_WITH_TIP_RIGHTWARDS = String.fromCharCode(0x21B3);
+
+ function HeapDetailsPathColumn(title) {
+ tr.ui.analysis.HeapDetailsTitleColumn.call(this, title);
+ }
+
+ HeapDetailsPathColumn.prototype = {
+ __proto__: tr.ui.analysis.HeapDetailsTitleColumn.prototype,
+
+ formatTitle(row) {
+ const title = tr.ui.analysis.HeapDetailsTitleColumn.prototype.
+ formatTitle.call(this, row);
+ if (row.dimension === tr.ui.analysis.HeapDetailsRowDimension.ROOT) {
+ return title;
+ }
+
+ const arrowEl = document.createElement('span');
+ Polymer.dom(arrowEl).textContent = DOWNWARDS_ARROW_WITH_TIP_RIGHTWARDS;
+ arrowEl.style.paddingRight = '2px';
+ arrowEl.style.fontWeight = 'bold';
+ arrowEl.style.color = tr.b.ColorScheme.getColorForReservedNameAsString(
+ 'heap_dump_child_node_arrow');
+
+ const rowEl = document.createElement('span');
+ Polymer.dom(rowEl).appendChild(arrowEl);
+ Polymer.dom(rowEl).appendChild(tr.ui.b.asHTMLOrTextNode(title));
+ return rowEl;
+ }
+ };
+
+ Polymer({
+ is: 'tr-ui-a-memory-dump-heap-details-path-view',
+ behaviors: [tr.ui.analysis.RebuildableBehavior],
+
+ created() {
+ this.selectedNode_ = undefined;
+ this.aggregationMode_ = undefined;
+ },
+
+ ready() {
+ this.$.table.addEventListener('selection-changed', function(event) {
+ this.selectedNode_ = this.$.table.selectedTableRow;
+ this.didSelectedNodeChange_();
+ }.bind(this));
+ },
+
+ didSelectedNodeChange_() {
+ this.dispatchEvent(new tr.b.Event('selected-node-changed'));
+ },
+
+ get selectedNode() {
+ return this.selectedNode_;
+ },
+
+ set selectedNode(node) {
+ this.selectedNode_ = node;
+ this.didSelectedNodeChange_();
+ this.scheduleRebuild_();
+ },
+
+ get aggregationMode() {
+ return this.aggregationMode_;
+ },
+
+ set aggregationMode(aggregationMode) {
+ this.aggregationMode_ = aggregationMode;
+ this.scheduleRebuild_();
+ },
+
+ onRebuild_() {
+ if (this.selectedNode_ === undefined) {
+ this.$.table.clear();
+ return;
+ }
+
+ if (this.$.table.tableRows.includes(this.selectedNode_)) {
+ this.$.table.selectedTableRow = this.selectedNode_;
+ return;
+ }
+
+ this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ this.$.table.userCanModifySortOrder = false;
+ const rows = this.createRows_(this.selectedNode_);
+ this.$.table.tableRows = rows;
+ this.$.table.tableColumns = this.createColumns_(rows);
+ this.$.table.selectedTableRow = rows[rows.length - 1];
+ },
+
+ createRows_(node) {
+ const rows = [];
+ while (node) {
+ rows.push(node);
+ node = node.parentNode;
+ }
+ rows.reverse();
+ return rows;
+ },
+
+ createColumns_(rows) {
+ const titleColumn = new HeapDetailsPathColumn('Current path');
+ titleColumn.width = '200px';
+
+ const numericColumns = tr.ui.analysis.MemoryColumn.fromRows(rows, {
+ cellKey: 'cells',
+ aggregationMode: this.aggregationMode_,
+ rules: tr.ui.analysis.HEAP_DETAILS_COLUMN_RULES,
+ shouldSetContextGroup: true
+ });
+ tr.ui.analysis.MemoryColumn.spaceEqually(numericColumns);
+
+ return [titleColumn].concat(numericColumns);
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_util.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_util.html
new file mode 100644
index 00000000000..2cf6c6ec8b1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_heap_details_util.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const LATIN_SMALL_LETTER_F_WITH_HOOK = String.fromCharCode(0x0192);
+ const CIRCLED_LATIN_CAPITAL_LETTER_T = String.fromCharCode(0x24C9);
+
+ /** @{enum} */
+ const HeapDetailsRowDimension = {
+ ROOT: {},
+ STACK_FRAME: {
+ label: 'Stack frame',
+ symbol: LATIN_SMALL_LETTER_F_WITH_HOOK,
+ color: 'heap_dump_stack_frame'
+ },
+ OBJECT_TYPE: {
+ label: 'Object type',
+ symbol: CIRCLED_LATIN_CAPITAL_LETTER_T,
+ color: 'heap_dump_object_type'
+ }
+ };
+
+ /** @{constructor} */
+ function HeapDetailsTitleColumn(title) {
+ tr.ui.analysis.TitleColumn.call(this, title);
+ }
+
+ HeapDetailsTitleColumn.prototype = {
+ __proto__: tr.ui.analysis.TitleColumn.prototype,
+
+ formatTitle(row) {
+ if (row.dimension === HeapDetailsRowDimension.ROOT) {
+ return row.title;
+ }
+
+ const symbolEl = document.createElement('span');
+ Polymer.dom(symbolEl).textContent = row.dimension.symbol;
+ symbolEl.title = row.dimension.label;
+ symbolEl.style.color = tr.b.ColorScheme.getColorForReservedNameAsString(
+ row.dimension.color);
+ symbolEl.style.paddingRight = '4px';
+ symbolEl.style.cursor = 'help';
+ symbolEl.style.fontWeight = 'bold';
+
+ const titleEl = document.createElement('span');
+ Polymer.dom(titleEl).appendChild(symbolEl);
+ Polymer.dom(titleEl).appendChild(document.createTextNode(row.title));
+
+ return titleEl;
+ }
+ };
+
+ /** @constructor */
+ function AllocationCountColumn(name, cellPath, aggregationMode) {
+ tr.ui.analysis.DetailsNumericMemoryColumn.call(
+ this, name, cellPath, aggregationMode);
+ }
+
+ AllocationCountColumn.prototype = {
+ __proto__: tr.ui.analysis.DetailsNumericMemoryColumn.prototype,
+
+ getFormattingContext(unit) {
+ return { minimumFractionDigits: 0 };
+ }
+ };
+
+ const HEAP_DETAILS_COLUMN_RULES = [
+ {
+ condition: 'Size',
+ importance: 2,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ condition: 'Count',
+ importance: 1,
+ columnConstructor: AllocationCountColumn
+ },
+ {
+ importance: 0,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ }
+ ];
+
+ return {
+ HeapDetailsRowDimension,
+ HeapDetailsTitleColumn,
+ AllocationCountColumn,
+ HEAP_DETAILS_COLUMN_RULES,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane.html
new file mode 100644
index 00000000000..5df80bb88b4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane.html
@@ -0,0 +1,774 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/fixed_color_scheme.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_allocator_details_pane.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html">
+<link rel="import" href="/tracing/ui/analysis/stacked_pane.html">
+<link rel="import" href="/tracing/ui/base/color_legend.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/view_specific_brushing_state.html">
+
+<dom-module id='tr-ui-a-memory-dump-overview-pane'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+
+ #label {
+ flex: 0 0 auto;
+ padding: 8px;
+
+ background-color: #eee;
+ border-bottom: 1px solid #8e8e8e;
+ border-top: 1px solid white;
+
+ font-size: 15px;
+ font-weight: bold;
+ }
+
+ #label a {
+ font-weight: normal;
+ float: right;
+ }
+
+ #contents {
+ flex: 1 0 auto;
+ align-self: stretch;
+ font-size: 12px;
+ overflow: auto;
+ }
+
+ #info_text {
+ padding: 8px;
+ color: #666;
+ font-style: italic;
+ text-align: center;
+ }
+
+ #table {
+ display: none; /* Hide until memory dumps are set. */
+ flex: 1 0 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-view-specific-brushing-state id="state"
+ view-id="analysis.memory_dump_overview_pane">
+ </tr-ui-b-view-specific-brushing-state>
+ <div id="label">Overview <a href="https://chromium.googlesource.com/chromium/src/+/master/docs/memory-infra">Help</a></div>
+ <div id="contents">
+ <div id="info_text">No memory memory dumps selected</div>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const MemoryColumnColorScheme = tr.b.MemoryColumnColorScheme;
+ const Scalar = tr.b.Scalar;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+
+ const PLATFORM_SPECIFIC_TOTAL_NAME_SUFFIX = '_bytes';
+
+ const DISPLAYED_SIZE_NUMERIC_NAME =
+ tr.model.MemoryAllocatorDump.DISPLAYED_SIZE_NUMERIC_NAME;
+ const SOME_TIMESTAMPS_INFO_QUANTIFIER =
+ tr.ui.analysis.MemoryColumn.SOME_TIMESTAMPS_INFO_QUANTIFIER;
+
+ // Unicode symbols used for memory cell info icons and messages.
+ const RIGHTWARDS_ARROW_WITH_HOOK = String.fromCharCode(0x21AA);
+ const RIGHTWARDS_ARROW_FROM_BAR = String.fromCharCode(0x21A6);
+ const GREATER_THAN_OR_EQUAL_TO = String.fromCharCode(0x2265);
+ const UNMARRIED_PARTNERSHIP_SYMBOL = String.fromCharCode(0x26AF);
+ const TRIGRAM_FOR_HEAVEN = String.fromCharCode(0x2630);
+
+ function lazyMap(list, fn, opt_this) {
+ opt_this = opt_this || this;
+ let result = undefined;
+ list.forEach(function(item, index) {
+ const value = fn.call(opt_this, item, index);
+ if (value === undefined) return;
+ if (result === undefined) {
+ result = new Array(list.length);
+ }
+ result[index] = value;
+ });
+ return result;
+ }
+
+ /** @constructor */
+ function ProcessNameColumn() {
+ tr.ui.analysis.TitleColumn.call(this, 'Process');
+ }
+
+ ProcessNameColumn.prototype = {
+ __proto__: tr.ui.analysis.TitleColumn.prototype,
+
+ formatTitle(row) {
+ if (row.contexts === undefined) {
+ return row.title; // Total row.
+ }
+ const titleEl = document.createElement('tr-ui-b-color-legend');
+ titleEl.label = row.title;
+ return titleEl;
+ }
+ };
+
+ /** @constructor */
+ function UsedMemoryColumn(name, cellPath, aggregationMode) {
+ tr.ui.analysis.NumericMemoryColumn.call(
+ this, name, cellPath, aggregationMode);
+ }
+
+ UsedMemoryColumn.COLOR =
+ MemoryColumnColorScheme.getColor('used_memory_column').toString();
+ UsedMemoryColumn.OLDER_COLOR =
+ MemoryColumnColorScheme.getColor('older_used_memory_column').toString();
+
+ UsedMemoryColumn.prototype = {
+ __proto__: tr.ui.analysis.NumericMemoryColumn.prototype,
+
+ get title() {
+ return tr.ui.b.createSpan({
+ textContent: this.name,
+ color: UsedMemoryColumn.COLOR
+ });
+ },
+
+ getFormattingContext(unit) {
+ return { unitPrefix: tr.b.UnitPrefixScale.BINARY.MEBI };
+ },
+
+ color(numerics, processMemoryDumps) {
+ return UsedMemoryColumn.COLOR;
+ },
+
+ getChildPaneBuilder(processMemoryDumps) {
+ if (processMemoryDumps === undefined) return undefined;
+
+ const vmRegions = lazyMap(processMemoryDumps, function(pmd) {
+ if (pmd === undefined) return undefined;
+ return pmd.mostRecentVmRegions;
+ });
+ if (vmRegions === undefined) return undefined;
+
+ return function() {
+ const pane = document.createElement(
+ 'tr-ui-a-memory-dump-vm-regions-details-pane');
+ pane.vmRegions = vmRegions;
+ pane.aggregationMode = this.aggregationMode;
+ return pane;
+ }.bind(this);
+ }
+ };
+
+ /** @constructor */
+ function PeakMemoryColumn(name, cellPath, aggregationMode) {
+ UsedMemoryColumn.call(this, name, cellPath, aggregationMode);
+ }
+
+ PeakMemoryColumn.prototype = {
+ __proto__: UsedMemoryColumn.prototype,
+
+ addInfos(numerics, processMemoryDumps, infos) {
+ if (processMemoryDumps === undefined) return; // Total row.
+
+ let resettableValueCount = 0;
+ let nonResettableValueCount = 0;
+ for (let i = 0; i < numerics.length; i++) {
+ if (numerics[i] === undefined) continue;
+ if (processMemoryDumps[i].arePeakResidentBytesResettable) {
+ resettableValueCount++;
+ } else {
+ nonResettableValueCount++;
+ }
+ }
+
+ if (resettableValueCount > 0 && nonResettableValueCount > 0) {
+ infos.push(tr.ui.analysis.createWarningInfo('Both resettable and ' +
+ 'non-resettable peak RSS values were provided by the process'));
+ } else if (resettableValueCount > 0) {
+ infos.push({
+ icon: RIGHTWARDS_ARROW_WITH_HOOK,
+ message: 'Peak RSS since previous memory dump.'
+ });
+ } else {
+ infos.push({
+ icon: RIGHTWARDS_ARROW_FROM_BAR,
+ message: 'Peak RSS since process startup. Finer grained ' +
+ 'peaks require a Linux kernel version ' +
+ GREATER_THAN_OR_EQUAL_TO + ' 4.0.'
+ });
+ }
+ }
+ };
+
+ /** @constructor */
+ function ByteStatColumn(name, cellPath, aggregationMode) {
+ UsedMemoryColumn.call(this, name, cellPath, aggregationMode);
+ }
+
+ ByteStatColumn.prototype = {
+ __proto__: UsedMemoryColumn.prototype,
+
+ color(numerics, processMemoryDumps) {
+ if (processMemoryDumps === undefined) {
+ return UsedMemoryColumn.COLOR; // Total row.
+ }
+
+ const allOlderValues = processMemoryDumps.every(
+ function(processMemoryDump) {
+ if (processMemoryDump === undefined) return true;
+ return !processMemoryDump.hasOwnVmRegions;
+ });
+
+ // Show the cell in lighter blue if all values were older (i.e. none of
+ // the defined process memory dumps had own VM regions).
+ if (allOlderValues) {
+ return UsedMemoryColumn.OLDER_COLOR;
+ }
+ return UsedMemoryColumn.COLOR;
+ },
+
+ addInfos(numerics, processMemoryDumps, infos) {
+ if (processMemoryDumps === undefined) return; // Total row.
+
+ let olderValueCount = 0;
+ for (let i = 0; i < numerics.length; i++) {
+ const processMemoryDump = processMemoryDumps[i];
+ if (processMemoryDump !== undefined &&
+ !processMemoryDump.hasOwnVmRegions) {
+ olderValueCount++;
+ }
+ }
+
+ if (olderValueCount === 0) {
+ return; // There are no older values.
+ }
+
+ const infoQuantifier = olderValueCount < numerics.length ?
+ ' ' + SOME_TIMESTAMPS_INFO_QUANTIFIER : /* some values are older */
+ ''; /* all values are older */
+
+ // Emit an info if there was at least one older value (i.e. at least one
+ // defined process memory dump did not have own VM regions).
+ infos.push({
+ message: 'Older value' + infoQuantifier +
+ ' (only heavy (purple) memory dumps contain memory maps).',
+ icon: UNMARRIED_PARTNERSHIP_SYMBOL
+ });
+ }
+ };
+
+ // Rules for constructing and sorting used memory columns.
+ UsedMemoryColumn.RULES = [
+ {
+ condition: 'Total resident',
+ importance: 10,
+ columnConstructor: UsedMemoryColumn
+ },
+ {
+ condition: 'Peak total resident',
+ importance: 9,
+ columnConstructor: PeakMemoryColumn
+ },
+ {
+ condition: 'PSS',
+ importance: 8,
+ columnConstructor: ByteStatColumn
+ },
+ {
+ condition: 'Private dirty',
+ importance: 7,
+ columnConstructor: ByteStatColumn
+ },
+ {
+ condition: 'Swapped',
+ importance: 6,
+ columnConstructor: ByteStatColumn
+ },
+ {
+ // All other columns.
+ importance: 0,
+ columnConstructor: UsedMemoryColumn
+ }
+ ];
+
+ // Map from ProcessMemoryDump totals fields to column names.
+ UsedMemoryColumn.TOTALS_MAP = {
+ 'residentBytes': 'Total resident',
+ 'peakResidentBytes': 'Peak total resident',
+ 'privateFootprintBytes': 'Private footprint',
+ };
+
+ // Map from ProcessMemoryDump platform-specific totals fields to column names.
+ UsedMemoryColumn.PLATFORM_SPECIFIC_TOTALS_MAP = {
+ 'vm': 'Total virtual',
+ 'swp': 'Swapped',
+ 'pc': 'Private clean',
+ 'pd': 'Private dirty',
+ 'sc': 'Shared clean',
+ 'sd': 'Shared dirty',
+ 'gpu_egl': 'GPU EGL',
+ 'gpu_egl_pss': 'GPU EGL PSS',
+ 'gpu_gl': 'GPU GL',
+ 'gpu_gl_pss': 'GPU GL PSS',
+ 'gpu_etc': 'GPU Other',
+ 'gpu_etc_pss': 'GPU Other PSS',
+ };
+
+ // Map from VMRegionByteStats field names to column names.
+ UsedMemoryColumn.BYTE_STAT_MAP = {
+ 'proportionalResident': 'PSS',
+ 'privateDirtyResident': 'Private dirty',
+ 'swapped': 'Swapped'
+ };
+
+ /** @constructor */
+ function AllocatorColumn(name, cellPath, aggregationMode) {
+ tr.ui.analysis.NumericMemoryColumn.call(
+ this, name, cellPath, aggregationMode);
+ }
+
+ AllocatorColumn.prototype = {
+ __proto__: tr.ui.analysis.NumericMemoryColumn.prototype,
+
+ get title() {
+ const titleEl = document.createElement('tr-ui-b-color-legend');
+ titleEl.label = this.name;
+ return titleEl;
+ },
+
+ getFormattingContext(unit) {
+ return { unitPrefix: tr.b.UnitPrefixScale.BINARY.MEBI };
+ },
+
+ addInfos(numerics, processMemoryDumps, infos) {
+ if (processMemoryDumps === undefined) return;
+
+ let heapDumpCount = 0;
+ let missingSizeCount = 0;
+
+ for (let i = 0; i < processMemoryDumps.length; i++) {
+ const processMemoryDump = processMemoryDumps[i];
+ if (processMemoryDump === undefined) continue;
+
+ const heapDumps = processMemoryDump.heapDumps;
+ if (heapDumps !== undefined && heapDumps[this.name] !== undefined) {
+ heapDumpCount++;
+ }
+ const allocatorDump =
+ processMemoryDump.getMemoryAllocatorDumpByFullName(this.name);
+
+ if (allocatorDump !== undefined &&
+ allocatorDump.numerics[DISPLAYED_SIZE_NUMERIC_NAME] === undefined) {
+ missingSizeCount++;
+ }
+ }
+
+ // Emit a heap dump info if at least one of the process memory dumps has
+ // a heap dump associated with this allocator.
+ if (heapDumpCount > 0) {
+ const infoQuantifier = heapDumpCount < numerics.length ?
+ ' ' + SOME_TIMESTAMPS_INFO_QUANTIFIER : '';
+ infos.push({
+ message: 'Heap dump provided' + infoQuantifier + '.',
+ icon: TRIGRAM_FOR_HEAVEN
+ });
+ }
+
+ // Emit a warning if this allocator did not provide size in at least one
+ // of the process memory dumps.
+ if (missingSizeCount > 0) {
+ const infoQuantifier = missingSizeCount < numerics.length ?
+ ' ' + SOME_TIMESTAMPS_INFO_QUANTIFIER : '';
+ infos.push(tr.ui.analysis.createWarningInfo(
+ 'Size was not provided' + infoQuantifier + '.'));
+ }
+ },
+
+ getChildPaneBuilder(processMemoryDumps) {
+ if (processMemoryDumps === undefined) return undefined;
+
+ const memoryAllocatorDumps = lazyMap(processMemoryDumps, function(pmd) {
+ if (pmd === undefined) return undefined;
+ return pmd.getMemoryAllocatorDumpByFullName(this.name);
+ }, this);
+ if (memoryAllocatorDumps === undefined) return undefined;
+
+ const heapDumps = lazyMap(processMemoryDumps, function(pmd) {
+ if (pmd === undefined || pmd.heapDumps === undefined) return undefined;
+ return pmd.heapDumps[this.name];
+ }, this);
+
+ return function() {
+ const pane = document.createElement(
+ 'tr-ui-a-memory-dump-allocator-details-pane');
+ pane.memoryAllocatorDumps = memoryAllocatorDumps;
+ pane.heapDumps = heapDumps;
+ pane.aggregationMode = this.aggregationMode;
+ return pane;
+ }.bind(this);
+ }
+ };
+
+ /** @constructor */
+ function TracingColumn(name, cellPath, aggregationMode) {
+ AllocatorColumn.call(this, name, cellPath, aggregationMode);
+ }
+
+ TracingColumn.COLOR =
+ MemoryColumnColorScheme.getColor('tracing_memory_column').toString();
+
+ TracingColumn.prototype = {
+ __proto__: AllocatorColumn.prototype,
+
+ get title() {
+ return tr.ui.b.createSpan({
+ textContent: this.name,
+ color: TracingColumn.COLOR
+ });
+ },
+
+ color(numerics, processMemoryDumps) {
+ return TracingColumn.COLOR;
+ }
+ };
+
+ // Rules for constructing and sorting allocator columns.
+ AllocatorColumn.RULES = [
+ {
+ condition: 'tracing',
+ importance: 0,
+ columnConstructor: TracingColumn
+ },
+ {
+ // All other columns.
+ importance: 1,
+ columnConstructor: AllocatorColumn
+ }
+ ];
+
+ Polymer({
+ is: 'tr-ui-a-memory-dump-overview-pane',
+ behaviors: [tr.ui.analysis.StackedPane],
+
+ created() {
+ this.processMemoryDumps_ = undefined;
+ this.aggregationMode_ = undefined;
+ },
+
+ ready() {
+ this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.CELL;
+ this.$.table.addEventListener('selection-changed',
+ function(tableEvent) {
+ tableEvent.stopPropagation();
+ this.changeChildPane_();
+ }.bind(this));
+ },
+
+ /**
+ * Sets the process memory dumps and schedules rebuilding the pane.
+ *
+ * The provided value should be a chronological list of dictionaries
+ * mapping process IDs to process memory dumps. Example:
+ *
+ * [
+ * {
+ * // PMDs at timestamp 1.
+ * 42: tr.model.ProcessMemoryDump {}
+ * },
+ * {
+ * // PMDs at timestamp 2.
+ * 42: tr.model.ProcessMemoryDump {},
+ * 89: tr.model.ProcessMemoryDump {}
+ * }
+ * ]
+ */
+ set processMemoryDumps(processMemoryDumps) {
+ this.processMemoryDumps_ = processMemoryDumps;
+ this.scheduleRebuild_();
+ },
+
+ get processMemoryDumps() {
+ return this.processMemoryDumps_;
+ },
+
+ set aggregationMode(aggregationMode) {
+ this.aggregationMode_ = aggregationMode;
+ this.scheduleRebuild_();
+ },
+
+ get aggregationMode() {
+ return this.aggregationMode_;
+ },
+
+ get selectedMemoryCell() {
+ if (this.processMemoryDumps_ === undefined ||
+ this.processMemoryDumps_.length === 0) {
+ return undefined;
+ }
+
+ const selectedTableRow = this.$.table.selectedTableRow;
+ if (!selectedTableRow) return undefined;
+
+ const selectedColumnIndex = this.$.table.selectedColumnIndex;
+ if (selectedColumnIndex === undefined) return undefined;
+
+ const selectedColumn = this.$.table.tableColumns[selectedColumnIndex];
+ const selectedMemoryCell = selectedColumn.cell(selectedTableRow);
+ return selectedMemoryCell;
+ },
+
+ changeChildPane_() {
+ this.storeSelection_();
+ this.childPaneBuilder = this.determineChildPaneBuilderFromSelection_();
+ },
+
+ determineChildPaneBuilderFromSelection_() {
+ if (this.processMemoryDumps_ === undefined ||
+ this.processMemoryDumps_.length === 0) {
+ return undefined;
+ }
+
+ const selectedTableRow = this.$.table.selectedTableRow;
+ if (!selectedTableRow) return undefined;
+
+ const selectedColumnIndex = this.$.table.selectedColumnIndex;
+ if (selectedColumnIndex === undefined) return undefined;
+ const selectedColumn = this.$.table.tableColumns[selectedColumnIndex];
+
+ return selectedColumn.getChildPaneBuilder(selectedTableRow.contexts);
+ },
+
+ onRebuild_() {
+ if (this.processMemoryDumps_ === undefined ||
+ this.processMemoryDumps_.length === 0) {
+ // Show the info text (hide the table).
+ this.$.info_text.style.display = 'block';
+ this.$.table.style.display = 'none';
+
+ this.$.table.clear();
+ this.$.table.rebuild();
+ return;
+ }
+
+ // Show the table (hide the info text).
+ this.$.info_text.style.display = 'none';
+ this.$.table.style.display = 'block';
+
+ const rows = this.createRows_();
+ const columns = this.createColumns_(rows);
+ const footerRows = this.createFooterRows_(rows, columns);
+
+ this.$.table.tableRows = rows;
+ this.$.table.footerRows = footerRows;
+ this.$.table.tableColumns = columns;
+ this.$.table.rebuild();
+
+ this.restoreSelection_();
+ },
+
+ createRows_() {
+ // Timestamp (list index) -> Process ID (dict key) -> PMD.
+ const timeToPidToProcessMemoryDump = this.processMemoryDumps_;
+
+ // Process ID (dict key) -> Timestamp (list index) -> PMD or undefined.
+ const pidToTimeToProcessMemoryDump = tr.b.invertArrayOfDicts(
+ timeToPidToProcessMemoryDump);
+
+ // Process (list index) -> Component (dict key) -> Cell.
+ const rows = [];
+ for (const [pid, timeToDump] of
+ Object.entries(pidToTimeToProcessMemoryDump)) {
+ // Get the process associated with the dumps. We can use any defined
+ // process memory dump in timeToDump since they all have the same
+ // pid.
+ const process = timeToDump.find(x => x).process;
+
+ // Used memory (total resident, PSS, ...).
+ const usedMemoryCells = tr.ui.analysis.createCells(timeToDump,
+ function(dump) {
+ const sizes = {};
+
+ const totals = dump.totals;
+ if (totals !== undefined) {
+ // Common totals.
+ for (const [totalName, cellName] of
+ Object.entries(UsedMemoryColumn.TOTALS_MAP)) {
+ const total = totals[totalName];
+ if (total === undefined) continue;
+ sizes[cellName] = new Scalar(
+ sizeInBytes_smallerIsBetter, total);
+ }
+
+ // Platform-specific totals (e.g. private resident on Mac).
+ const platformSpecific = totals.platformSpecific;
+ if (platformSpecific !== undefined) {
+ for (const [name, size] of Object.entries(platformSpecific)) {
+ let newName = name;
+ if (UsedMemoryColumn.PLATFORM_SPECIFIC_TOTALS_MAP[name] ===
+ undefined) {
+ // Change raw OS-specific total name to a friendly
+ // column title (e.g. 'private_bytes' -> 'Private').
+ if (name.endsWith(PLATFORM_SPECIFIC_TOTAL_NAME_SUFFIX)) {
+ newName = name.substring(0, name.length -
+ PLATFORM_SPECIFIC_TOTAL_NAME_SUFFIX.length);
+ }
+ newName = newName.replace('_', ' ').trim();
+ newName =
+ newName.charAt(0).toUpperCase() + newName.slice(1);
+ } else {
+ newName =
+ UsedMemoryColumn.PLATFORM_SPECIFIC_TOTALS_MAP[name];
+ }
+ sizes[newName] = new Scalar(
+ sizeInBytes_smallerIsBetter, size);
+ }
+ }
+ }
+
+ // VM regions byte stats.
+ const vmRegions = dump.mostRecentVmRegions;
+ if (vmRegions !== undefined) {
+ for (const [byteStatName, cellName] of
+ Object.entries(UsedMemoryColumn.BYTE_STAT_MAP)) {
+ const byteStat = vmRegions.byteStats[byteStatName];
+ if (byteStat === undefined) continue;
+ sizes[cellName] = new Scalar(
+ sizeInBytes_smallerIsBetter, byteStat);
+ }
+ }
+
+ return sizes;
+ });
+
+ // Allocator memory (v8, oilpan, ...).
+ const allocatorCells = tr.ui.analysis.createCells(timeToDump,
+ function(dump) {
+ const memoryAllocatorDumps = dump.memoryAllocatorDumps;
+ if (memoryAllocatorDumps === undefined) return undefined;
+
+ const sizes = {};
+ memoryAllocatorDumps.forEach(function(allocatorDump) {
+ let rootDisplayedSizeNumeric = allocatorDump.numerics[
+ DISPLAYED_SIZE_NUMERIC_NAME];
+ if (rootDisplayedSizeNumeric === undefined) {
+ rootDisplayedSizeNumeric =
+ new Scalar(sizeInBytes_smallerIsBetter, 0);
+ }
+ sizes[allocatorDump.fullName] = rootDisplayedSizeNumeric;
+ });
+ return sizes;
+ });
+
+ rows.push({
+ title: process.userFriendlyName,
+ contexts: timeToDump,
+ usedMemoryCells,
+ allocatorCells
+ });
+ }
+ return rows;
+ },
+
+ createFooterRows_(rows, columns) {
+ // Add a 'Total' row if there are at least two process memory dumps.
+ if (rows.length <= 1) return [];
+
+ const totalRow = {title: 'Total'};
+ tr.ui.analysis.aggregateTableRowCells(totalRow, rows, columns);
+
+ return [totalRow];
+ },
+
+ createColumns_(rows) {
+ const titleColumn = new ProcessNameColumn();
+ titleColumn.width = '200px';
+
+ const usedMemorySizeColumns = tr.ui.analysis.MemoryColumn.fromRows(rows, {
+ cellKey: 'usedMemoryCells',
+ aggregationMode: this.aggregationMode_,
+ rules: UsedMemoryColumn.RULES
+ });
+
+ const allocatorSizeColumns = tr.ui.analysis.MemoryColumn.fromRows(rows, {
+ cellKey: 'allocatorCells',
+ aggregationMode: this.aggregationMode_,
+ rules: AllocatorColumn.RULES
+ });
+
+ const sizeColumns = usedMemorySizeColumns.concat(allocatorSizeColumns);
+ tr.ui.analysis.MemoryColumn.spaceEqually(sizeColumns);
+
+ const columns = [titleColumn].concat(sizeColumns);
+ return columns;
+ },
+
+ storeSelection_() {
+ let selectedRowTitle;
+ const selectedRow = this.$.table.selectedTableRow;
+ if (selectedRow !== undefined) {
+ selectedRowTitle = selectedRow.title;
+ }
+
+ let selectedColumnName;
+ const selectedColumnIndex = this.$.table.selectedColumnIndex;
+ if (selectedColumnIndex !== undefined) {
+ const selectedColumn = this.$.table.tableColumns[selectedColumnIndex];
+ selectedColumnName = selectedColumn.name;
+ }
+
+ this.$.state.set(
+ {rowTitle: selectedRowTitle, columnName: selectedColumnName});
+ },
+
+ restoreSelection_() {
+ const settings = this.$.state.get();
+ if (settings === undefined || settings.rowTitle === undefined ||
+ settings.columnName === undefined) {
+ return;
+ }
+
+ const selectedColumnIndex = this.$.table.tableColumns.findIndex(
+ col => col.name === settings.columnName);
+ if (selectedColumnIndex === -1) return;
+
+ const selectedRowTitle = settings.rowTitle;
+ const selectedRow = this.$.table.tableRows.find(
+ row => row.title === selectedRowTitle);
+ if (selectedRow === undefined) return;
+
+ this.$.table.selectedTableRow = selectedRow;
+ this.$.table.selectedColumnIndex = selectedColumnIndex;
+ }
+ });
+
+ return {
+ // All exports are for testing only.
+ ProcessNameColumn,
+ UsedMemoryColumn,
+ PeakMemoryColumn,
+ ByteStatColumn,
+ AllocatorColumn,
+ TracingColumn,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane_test.html
new file mode 100644
index 00000000000..80127e020a8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_overview_pane_test.html
@@ -0,0 +1,840 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/heap_dump.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_overview_pane.html">
+<link rel="import"
+ href="/tracing/ui/analysis/memory_dump_sub_view_test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Scalar = tr.b.Scalar;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const MemoryAllocatorDump = tr.model.MemoryAllocatorDump;
+ const HeapDump = tr.model.HeapDump;
+ const AggregationMode = tr.ui.analysis.MemoryColumn.AggregationMode;
+ const checkSizeNumericFields = tr.ui.analysis.checkSizeNumericFields;
+ const checkColor = tr.ui.analysis.checkColor;
+ const checkColumns = tr.ui.analysis.checkColumns;
+ const checkColumnInfosAndColor = tr.ui.analysis.checkColumnInfosAndColor;
+ const convertToProcessMemoryDumps =
+ tr.ui.analysis.convertToProcessMemoryDumps;
+ const extractProcessMemoryDumps = tr.ui.analysis.extractProcessMemoryDumps;
+ const extractVmRegions = tr.ui.analysis.extractVmRegions;
+ const extractMemoryAllocatorDumps =
+ tr.ui.analysis.extractMemoryAllocatorDumps;
+ const isElementDisplayed = tr.ui.analysis.isElementDisplayed;
+ const addProcessMemoryDump =
+ tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
+ const addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
+ const ProcessNameColumn = tr.ui.analysis.ProcessNameColumn;
+ const UsedMemoryColumn = tr.ui.analysis.UsedMemoryColumn;
+ const PeakMemoryColumn = tr.ui.analysis.PeakMemoryColumn;
+ const ByteStatColumn = tr.ui.analysis.ByteStatColumn;
+ const AllocatorColumn = tr.ui.analysis.AllocatorColumn;
+ const TracingColumn = tr.ui.analysis.TracingColumn;
+
+ function spanMatcher(expectedTitle) {
+ return function(actualTitle) {
+ assert.instanceOf(actualTitle, HTMLElement);
+ assert.strictEqual(actualTitle.tagName, 'SPAN');
+ assert.strictEqual(Polymer.dom(actualTitle).textContent, expectedTitle);
+ };
+ }
+
+ function colorLegendMatcher(expectedTitle) {
+ return function(actualTitle) {
+ assert.instanceOf(actualTitle, HTMLElement);
+ assert.strictEqual(actualTitle.tagName, 'TR-UI-B-COLOR-LEGEND');
+ assert.strictEqual(actualTitle.label, expectedTitle);
+ };
+ }
+
+ const EXPECTED_COLUMNS = [
+ { title: 'Process', type: ProcessNameColumn, noAggregation: true },
+ { title: spanMatcher('Total resident'), type: UsedMemoryColumn },
+ { title: spanMatcher('Peak total resident'), type: PeakMemoryColumn },
+ { title: spanMatcher('PSS'), type: ByteStatColumn },
+ { title: spanMatcher('Private dirty'), type: ByteStatColumn },
+ { title: spanMatcher('Swapped'), type: ByteStatColumn },
+ { title: spanMatcher('Private'), type: UsedMemoryColumn },
+ { title: spanMatcher('Private footprint'), type: UsedMemoryColumn },
+ { title: colorLegendMatcher('blink'), type: AllocatorColumn },
+ { title: colorLegendMatcher('gpu'), type: AllocatorColumn },
+ { title: colorLegendMatcher('malloc'), type: AllocatorColumn },
+ { title: colorLegendMatcher('oilpan'), type: AllocatorColumn },
+ { title: colorLegendMatcher('v8'), type: AllocatorColumn },
+ { title: spanMatcher('tracing'), type: TracingColumn }
+ ];
+
+ function checkRow(columns, row, expectedTitle, expectedSizes,
+ expectedContexts) {
+ // Check title.
+ const formattedTitle = columns[0].formatTitle(row);
+ if (typeof expectedTitle === 'function') {
+ expectedTitle(formattedTitle);
+ } else {
+ assert.strictEqual(formattedTitle, expectedTitle);
+ }
+
+ // Check all sizes. The first assert below is a test sanity check.
+ assert.lengthOf(expectedSizes, columns.length - 1 /* all except title */);
+ for (let i = 0; i < expectedSizes.length; i++) {
+ checkSizeNumericFields(row, columns[i + 1], expectedSizes[i]);
+ }
+
+ // There should be no row nesting on the overview pane.
+ assert.isUndefined(row.subRows);
+
+ if (expectedContexts) {
+ assert.deepEqual(Array.from(row.contexts), expectedContexts);
+ } else {
+ assert.isUndefined(row.contexts);
+ }
+ }
+
+ function checkRows(columns, actualRows, expectedRows) {
+ if (expectedRows === undefined) {
+ assert.isUndefined(actualRows);
+ return;
+ }
+ assert.lengthOf(actualRows, expectedRows.length);
+ for (let i = 0; i < expectedRows.length; i++) {
+ const actualRow = actualRows[i];
+ const expectedRow = expectedRows[i];
+ checkRow(columns, actualRow, expectedRow.title, expectedRow.sizes,
+ expectedRow.contexts);
+ }
+ }
+
+ function checkSpanWithColor(span, expectedText, expectedColor) {
+ assert.strictEqual(span.tagName, 'SPAN');
+ assert.strictEqual(Polymer.dom(span).textContent, expectedText);
+ checkColor(span.style.color, expectedColor);
+ }
+
+ function checkColorLegend(legend, expectedLabel) {
+ assert.strictEqual(legend.tagName, 'TR-UI-B-COLOR-LEGEND');
+ assert.strictEqual(legend.label, expectedLabel);
+ }
+
+ function createAndCheckMemoryDumpOverviewPane(
+ test, processMemoryDumps, expectedRows, expectedFooterRows,
+ aggregationMode) {
+ const viewEl =
+ tr.ui.analysis.createTestPane('tr-ui-a-memory-dump-overview-pane');
+ viewEl.processMemoryDumps = processMemoryDumps;
+ viewEl.aggregationMode = aggregationMode;
+ viewEl.rebuild();
+ test.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ assert.isUndefined(viewEl.createChildPane());
+
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, aggregationMode);
+ const rows = table.tableRows;
+
+ checkRows(columns, table.tableRows, expectedRows);
+ checkRows(columns, table.footerRows, expectedFooterRows);
+ }
+
+ const FIELD = 1 << 0;
+ const DUMP = 1 << 1;
+
+ function checkOverviewColumnInfosAndColor(column, fieldAndDumpMask,
+ dumpCreatedCallback, expectedInfos, expectedColorReservedName) {
+ const fields = fieldAndDumpMask.map(function(mask, index) {
+ return mask & FIELD ?
+ new Scalar(sizeInBytes_smallerIsBetter, 1024 + 32 * index) :
+ undefined;
+ });
+
+ let contexts;
+ if (dumpCreatedCallback === undefined) {
+ contexts = undefined;
+ } else {
+ tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ fieldAndDumpMask.forEach(function(mask, i) {
+ const timestamp = 10 + i;
+ const gmd = addGlobalMemoryDump(model, {ts: timestamp});
+ if (mask & DUMP) {
+ const pmd = addProcessMemoryDump(gmd, process, {ts: timestamp});
+ dumpCreatedCallback(pmd, mask);
+ }
+ });
+ contexts = model.globalMemoryDumps.map(function(gmd) {
+ return gmd.processMemoryDumps[1];
+ });
+ });
+ }
+
+ checkColumnInfosAndColor(
+ column, fields, contexts, expectedInfos, expectedColorReservedName);
+ }
+
+ test('colorsAreDefined', function() {
+ // We use these constants in the code and the tests so here we guard
+ // against them being undefined and causing all the tests to still
+ // pass while the we end up with no colors.
+ assert.isDefined(UsedMemoryColumn.COLOR);
+ assert.isDefined(UsedMemoryColumn.OLDER_COLOR);
+ assert.isDefined(TracingColumn.COLOR);
+ });
+
+ test('instantiate_empty', function() {
+ tr.ui.analysis.createAndCheckEmptyPanes(this,
+ 'tr-ui-a-memory-dump-overview-pane', 'processMemoryDumps',
+ function(viewEl) {
+ // Check that the info text is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.info_text));
+ assert.isFalse(isElementDisplayed(viewEl.$.table));
+ });
+ });
+
+ test('instantiate_singleGlobalMemoryDump', function() {
+ const processMemoryDumps = convertToProcessMemoryDumps(
+ [tr.ui.analysis.createSingleTestGlobalMemoryDump()]);
+ createAndCheckMemoryDumpOverviewPane(this,
+ processMemoryDumps,
+ [ // Table rows.
+ {
+ title: colorLegendMatcher('Process 1'),
+ sizes: [[29884416], undefined, [9437184], [5767168], undefined,
+ undefined, undefined, undefined, undefined, [7340032], undefined,
+ undefined, [2097152]],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 1)
+ },
+ {
+ title: colorLegendMatcher('Process 2'),
+ sizes: [[17825792], [39845888], [18350080], [0], [32], [8912896],
+ [15728640], [7340032], [0], [1048576], [1], [5242880],
+ [1572864]],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 2)
+ },
+ {
+ title: colorLegendMatcher('Process 4'),
+ sizes: [undefined, [17825792], undefined, undefined, undefined,
+ undefined, undefined, undefined, undefined, undefined,
+ undefined, undefined, undefined],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 4)
+ }
+ ],
+ [ // Footer rows.
+ {
+ title: 'Total',
+ sizes: [[47710208], [57671680], [27787264], [5767168], [32],
+ [8912896], [15728640], [7340032], [0], [8388608], [1],
+ [5242880], [3670016]],
+ contexts: undefined
+ }
+ ],
+ undefined /* no aggregation */);
+ });
+
+ test('instantiate_multipleGlobalMemoryDumps', function() {
+ const processMemoryDumps = convertToProcessMemoryDumps(
+ tr.ui.analysis.createMultipleTestGlobalMemoryDumps());
+ createAndCheckMemoryDumpOverviewPane(this,
+ processMemoryDumps,
+ [ // Table rows.
+ {
+ title: colorLegendMatcher('Process 1'),
+ sizes: [[31457280, 29884416, undefined], undefined,
+ [10485760, 9437184, undefined], [8388608, 5767168, undefined],
+ undefined, undefined, undefined, undefined, undefined,
+ [undefined, 7340032, undefined], undefined, undefined,
+ [undefined, 2097152, undefined]],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 1)
+ },
+ {
+ title: colorLegendMatcher('Process 2'),
+ sizes: [[19398656, 17825792, 15728640],
+ [40370176, 39845888, 40894464], [18350080, 18350080, 18350080],
+ [0, 0, -2621440], [32, 32, 64], [10485760, 8912896, 7340032],
+ [15728640, 15728640, 15728640], [undefined, 7340032, 6291456],
+ [undefined, 0, 1048576], [2097152, 1048576, 786432],
+ [undefined, 1, undefined], [5242880, 5242880, 5767168],
+ [1048576, 1572864, 2097152]],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 2)
+ },
+ {
+ title: colorLegendMatcher('Process 3'),
+ sizes: [undefined, undefined, undefined, undefined, undefined,
+ undefined, undefined, undefined, undefined, undefined,
+ [2147483648, undefined, 1073741824],
+ [1073741824, undefined, 2147483648], undefined],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 3)
+ },
+ {
+ title: colorLegendMatcher('Process 4'),
+ sizes: [undefined, [undefined, 17825792, 17825792], undefined,
+ undefined, undefined, undefined, undefined, undefined,
+ undefined, undefined, undefined, undefined, undefined],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 4)
+ }
+ ],
+ [ // Footer rows.
+ {
+ title: 'Total',
+ sizes: [[50855936, 47710208, 15728640],
+ [40370176, 57671680, 58720256], [28835840, 27787264, 18350080],
+ [8388608, 5767168, -2621440], [32, 32, 64],
+ [10485760, 8912896, 7340032], [15728640, 15728640, 15728640],
+ [undefined, 7340032, 6291456], [undefined, 0, 1048576],
+ [2097152, 8388608, 786432], [2147483648, 1, 1073741824],
+ [1078984704, 5242880, 2153250816],
+ [1048576, 3670016, 2097152]],
+ contexts: undefined
+ }
+ ],
+ AggregationMode.DIFF);
+ });
+
+ test('instantiate_singleProcessMemoryDump', function() {
+ const processMemoryDumps = convertToProcessMemoryDumps(
+ [tr.ui.analysis.createSingleTestProcessMemoryDump()]);
+ createAndCheckMemoryDumpOverviewPane(this,
+ processMemoryDumps,
+ [ // Table rows.
+ {
+ title: colorLegendMatcher('Process 2'),
+ sizes: [[17825792], [39845888], [18350080], [0], [32], [8912896],
+ [15728640], [7340032], [0], [1048576], [1], [5242880],
+ [1572864]],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 2)
+ }
+ ],
+ [] /* footer rows */,
+ undefined /* no aggregation */);
+ });
+
+ test('instantiate_multipleProcessMemoryDumps', function() {
+ const processMemoryDumps = convertToProcessMemoryDumps(
+ tr.ui.analysis.createMultipleTestProcessMemoryDumps());
+ createAndCheckMemoryDumpOverviewPane(this,
+ processMemoryDumps,
+ [ // Table rows.
+ {
+ title: colorLegendMatcher('Process 2'),
+ sizes: [[19398656, 17825792, 15728640],
+ [40370176, 39845888, 40894464], [18350080, 18350080, 18350080],
+ [0, 0, -2621440], [32, 32, 64], [10485760, 8912896, 7340032],
+ [15728640, 15728640, 15728640], [undefined, 7340032, 6291456],
+ [undefined, 0, 1048576], [2097152, 1048576, 786432],
+ [undefined, 1, undefined], [5242880, 5242880, 5767168],
+ [1048576, 1572864, 2097152]],
+ contexts: extractProcessMemoryDumps(processMemoryDumps, 2)
+ }
+ ],
+ [] /* footer rows */,
+ AggregationMode.MAX);
+ });
+
+ test('selection', function() {
+ const processMemoryDumps = convertToProcessMemoryDumps(
+ tr.ui.analysis.createMultipleTestGlobalMemoryDumps());
+
+ const viewEl =
+ tr.ui.analysis.createTestPane('tr-ui-a-memory-dump-overview-pane');
+ viewEl.processMemoryDumps = processMemoryDumps;
+ viewEl.aggregationMode = AggregationMode.DIFF;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ const table = viewEl.$.table;
+
+ // Simulate clicking on the 'malloc' cell of the second process.
+ table.selectedTableRow = table.tableRows[1];
+ table.selectedColumnIndex = 10;
+ assert.lengthOf(viewEl.requestedChildPanes, 2);
+ let lastChildPane = viewEl.requestedChildPanes[1];
+ assert.strictEqual(
+ lastChildPane.tagName, 'TR-UI-A-MEMORY-DUMP-ALLOCATOR-DETAILS-PANE');
+ assert.strictEqual(lastChildPane.aggregationMode, AggregationMode.DIFF);
+ assert.deepEqual(lastChildPane.memoryAllocatorDumps,
+ extractMemoryAllocatorDumps(processMemoryDumps, 2, 'malloc'));
+
+ // Simulate clicking on the 'Oilpan' cell of the second process.
+ table.selectedColumnIndex = 10;
+ assert.lengthOf(viewEl.requestedChildPanes, 3);
+ lastChildPane = viewEl.requestedChildPanes[2];
+ assert.isUndefined(viewEl.lastChildPane);
+ });
+
+ test('memory', function() {
+ const processMemoryDumps = convertToProcessMemoryDumps(
+ tr.ui.analysis.createMultipleTestGlobalMemoryDumps());
+ const containerEl = document.createElement('div');
+ containerEl.brushingStateController =
+ new tr.c.BrushingStateController(undefined);
+
+ function simulateView(pids, aggregationMode,
+ expectedSelectedCellFieldValues, expectedSelectedRowTitle,
+ expectedSelectedColumnIndex, callback) {
+ const viewEl =
+ tr.ui.analysis.createTestPane('tr-ui-a-memory-dump-overview-pane');
+ const table = viewEl.$.table;
+ Polymer.dom(containerEl).textContent = '';
+ Polymer.dom(containerEl).appendChild(viewEl);
+
+ const displayedProcessMemoryDumps = processMemoryDumps.map(
+ function(memoryDumps) {
+ const result = {};
+ for (const [pid, pmd] of Object.entries(memoryDumps)) {
+ if (pids.includes(pmd.process.pid)) result[pid] = pmd;
+ }
+ return result;
+ });
+ viewEl.processMemoryDumps = displayedProcessMemoryDumps;
+ viewEl.aggregationMode = aggregationMode;
+ viewEl.rebuild();
+
+ if (expectedSelectedCellFieldValues === undefined) {
+ assert.isUndefined(viewEl.childPaneBuilder);
+ } else {
+ checkSizeNumericFields(table.selectedTableRow,
+ table.tableColumns[table.selectedColumnIndex],
+ expectedSelectedCellFieldValues);
+ }
+
+ assert.strictEqual(
+ table.selectedColumnIndex, expectedSelectedColumnIndex);
+ if (expectedSelectedRowTitle === undefined) {
+ assert.isUndefined(table.selectedTableRow);
+ } else {
+ assert.strictEqual(
+ table.selectedTableRow.title, expectedSelectedRowTitle);
+ }
+
+ callback(viewEl, viewEl.$.table);
+ }
+
+ simulateView(
+ [1, 2, 3, 4], // All processes.
+ AggregationMode.DIFF,
+ undefined, undefined, undefined, // No cell should be selected.
+ function(view, table) {
+ assert.isUndefined(view.createChildPane());
+
+ // Select the 'PSS' column of the second process.
+ table.selectedTableRow = table.tableRows[1];
+ table.selectedColumnIndex = 3;
+ });
+
+ simulateView(
+ [2, 3],
+ AggregationMode.MAX,
+ [18350080, 18350080, 18350080], 'Process 2', 3, /* PSS */
+ function(view, table) {
+ const childPane = view.createChildPane();
+ assert.strictEqual(
+ childPane.tagName, 'TR-UI-A-MEMORY-DUMP-VM-REGIONS-DETAILS-PANE');
+ assert.deepEqual(Array.from(childPane.vmRegions),
+ extractVmRegions(processMemoryDumps, 2));
+ assert.strictEqual(childPane.aggregationMode, AggregationMode.MAX);
+ });
+
+ simulateView(
+ [3],
+ undefined, /* No aggregation */
+ undefined, undefined, undefined, // No cell selected.
+ function(view, table) {
+ assert.isUndefined(view.createChildPane());
+ });
+
+ simulateView(
+ [1, 2, 3, 4],
+ AggregationMode.DIFF,
+ [18350080, 18350080, 18350080], 'Process 2', 3, /* PSS */
+ function(view, table) {
+ const childPane = view.createChildPane();
+ assert.strictEqual(
+ childPane.tagName, 'TR-UI-A-MEMORY-DUMP-VM-REGIONS-DETAILS-PANE');
+ assert.deepEqual(Array.from(childPane.vmRegions),
+ extractVmRegions(processMemoryDumps, 2));
+ assert.strictEqual(childPane.aggregationMode, AggregationMode.DIFF);
+
+ // Select the 'v8' column of the first process (empty cell).
+ table.selectedTableRow = table.tableRows[0];
+ table.selectedColumnIndex = 11;
+ });
+
+ simulateView(
+ [1],
+ undefined, /* No aggregation */
+ undefined, undefined, undefined, // No cell should selected.
+ function(view, table) {
+ assert.isUndefined(view.createChildPane());
+
+ // Select 'Total resident' column of the first process.
+ table.selectedTableRow = table.tableRows[0];
+ table.selectedColumnIndex = 1;
+ });
+
+ simulateView(
+ [1, 2, 3, 4],
+ AggregationMode.MAX,
+ [31457280, 29884416, undefined], 'Process 1', 1, /* Total resident */
+ function(view, table) {
+ const childPane = view.createChildPane();
+ assert.strictEqual(
+ childPane.tagName, 'TR-UI-A-MEMORY-DUMP-VM-REGIONS-DETAILS-PANE');
+ assert.deepEqual(Array.from(childPane.vmRegions),
+ extractVmRegions(processMemoryDumps, 1));
+ assert.strictEqual(childPane.aggregationMode, AggregationMode.MAX);
+ });
+ });
+
+ test('processNameColumn_formatTitle', function() {
+ const c = new ProcessNameColumn();
+
+ // With context (total row).
+ assert.strictEqual(c.formatTitle({
+ title: 'Total',
+ usedMemoryCells: {}
+ }), 'Total');
+
+ // Without context (process row).
+ const title = c.formatTitle({
+ title: 'Process 1',
+ usedMemoryCells: {},
+ contexts: [tr.ui.analysis.createSingleTestProcessMemoryDump()]
+ });
+ checkColorLegend(title, 'Process 1');
+ });
+
+ test('usedMemoryColumn', function() {
+ const c = new UsedMemoryColumn('Private', 'bytes', (x => x),
+ AggregationMode.DIFF);
+ checkSpanWithColor(c.title, 'Private',
+ UsedMemoryColumn.COLOR /* blue (column title) */);
+ checkColor(c.color(undefined /* contexts */),
+ UsedMemoryColumn.COLOR /* blue (column cells) */);
+ });
+
+ test('peakMemoryColumn', function() {
+ const c = new PeakMemoryColumn('Peak', 'bytes', (x => x),
+ AggregationMode.MAX);
+ checkSpanWithColor(c.title, 'Peak',
+ UsedMemoryColumn.COLOR /* blue (column title) */);
+ checkColor(c.color(undefined) /* contexts */,
+ UsedMemoryColumn.COLOR /* blue (column cells) */);
+
+ const RESETTABLE_PEAK = 1 << 2;
+ const NON_RESETTABLE_PEAK = 1 << 3;
+ function checkPeakColumnInfosAndColor(fieldAndDumpMask, expectedInfos) {
+ checkOverviewColumnInfosAndColor(c,
+ fieldAndDumpMask,
+ function(pmd, mask) {
+ if (mask & RESETTABLE_PEAK) {
+ assert.strictEqual(
+ mask & NON_RESETTABLE_PEAK, 0); // Test sanity check.
+ pmd.arePeakResidentBytesResettable = true;
+ } else if (mask & NON_RESETTABLE_PEAK) {
+ pmd.arePeakResidentBytesResettable = false;
+ }
+ },
+ expectedInfos,
+ UsedMemoryColumn.COLOR);
+ }
+
+ // No context.
+ checkOverviewColumnInfosAndColor(c,
+ [FIELD],
+ undefined /* no context */,
+ [] /* no infos */,
+ UsedMemoryColumn.COLOR /* blue color */);
+ checkOverviewColumnInfosAndColor(c,
+ [FIELD, FIELD, 0, FIELD],
+ undefined /* no context */,
+ [] /* no infos */,
+ UsedMemoryColumn.COLOR /* blue color */);
+
+ // All resettable.
+ const EXPECTED_RESETTABLE_INFO = {
+ icon: '\u21AA',
+ message: 'Peak RSS since previous memory dump.'
+ };
+ checkPeakColumnInfosAndColor([
+ FIELD | DUMP | RESETTABLE_PEAK
+ ], [EXPECTED_RESETTABLE_INFO]);
+ checkPeakColumnInfosAndColor([
+ FIELD | DUMP | RESETTABLE_PEAK,
+ DUMP /* ignored because there's no field */,
+ 0,
+ FIELD | DUMP | RESETTABLE_PEAK
+ ], [EXPECTED_RESETTABLE_INFO]);
+
+ // All non-resettable.
+ const EXPECTED_NON_RESETTABLE_INFO = {
+ icon: '\u21A6',
+ message: 'Peak RSS since process startup. Finer grained peaks require ' +
+ 'a Linux kernel version \u2265 4.0.'
+ };
+ checkPeakColumnInfosAndColor([
+ FIELD | DUMP | NON_RESETTABLE_PEAK
+ ], [EXPECTED_NON_RESETTABLE_INFO]);
+ checkPeakColumnInfosAndColor([
+ 0,
+ DUMP | RESETTABLE_PEAK /* ignored because there's no field */,
+ FIELD | DUMP | NON_RESETTABLE_PEAK,
+ FIELD | DUMP | NON_RESETTABLE_PEAK
+ ], [EXPECTED_NON_RESETTABLE_INFO]);
+
+ // Combination (warning).
+ const EXPECTED_COMBINATION_INFO = {
+ icon: '\u26A0',
+ message: 'Both resettable and non-resettable peak RSS values were ' +
+ 'provided by the process',
+ color: 'red'
+ };
+ checkPeakColumnInfosAndColor([
+ FIELD | DUMP | NON_RESETTABLE_PEAK,
+ 0,
+ FIELD | DUMP | RESETTABLE_PEAK,
+ 0
+ ], [EXPECTED_COMBINATION_INFO]);
+ });
+
+ test('byteStatColumn', function() {
+ const c = new ByteStatColumn('Stat', 'bytes', (x => x),
+ AggregationMode.DIFF);
+ checkSpanWithColor(c.title, 'Stat',
+ UsedMemoryColumn.COLOR /* blue (column title) */);
+
+ const HAS_OWN_VM_REGIONS = 1 << 2;
+ function checkByteStatColumnInfosAndColor(
+ fieldAndDumpMask, expectedInfos, expectedIsOlderColor) {
+ checkOverviewColumnInfosAndColor(c,
+ fieldAndDumpMask,
+ function(pmd, mask) {
+ if (mask & HAS_OWN_VM_REGIONS) {
+ pmd.vmRegions = [];
+ }
+ },
+ expectedInfos,
+ expectedIsOlderColor ?
+ UsedMemoryColumn.OLDER_COLOR /* light blue */ :
+ UsedMemoryColumn.COLOR /* blue color */);
+ }
+
+ const EXPECTED_ALL_OLDER_VALUES = {
+ icon: '\u26AF',
+ message: 'Older value (only heavy (purple) memory dumps contain ' +
+ 'memory maps).'
+ };
+ const EXPECTED_SOME_OLDER_VALUES = {
+ icon: '\u26AF',
+ message: 'Older value at some selected timestamps (only heavy ' +
+ '(purple) memory dumps contain memory maps).'
+ };
+
+ // No context.
+ checkOverviewColumnInfosAndColor(c,
+ [FIELD],
+ undefined /* no context */,
+ [] /* no infos */,
+ UsedMemoryColumn.COLOR /* blue color */);
+ checkOverviewColumnInfosAndColor(c,
+ [FIELD, FIELD, 0, FIELD],
+ undefined /* no context */,
+ [] /* no infos */,
+ UsedMemoryColumn.COLOR /* blue color */);
+
+ // All process memory dumps have own VM regions.
+ checkByteStatColumnInfosAndColor([
+ FIELD | DUMP | HAS_OWN_VM_REGIONS
+ ], [] /* no infos */, false /* blue color */);
+ checkByteStatColumnInfosAndColor([
+ FIELD | DUMP | HAS_OWN_VM_REGIONS,
+ FIELD | DUMP | HAS_OWN_VM_REGIONS,
+ 0,
+ FIELD | DUMP | HAS_OWN_VM_REGIONS
+ ], [] /* no infos */, false /* blue color */);
+
+ // No process memory dumps have own VM regions.
+ checkByteStatColumnInfosAndColor([
+ FIELD | DUMP
+ ], [EXPECTED_ALL_OLDER_VALUES], true /* light blue */);
+ checkByteStatColumnInfosAndColor([
+ FIELD | DUMP,
+ FIELD | DUMP
+ ], [EXPECTED_ALL_OLDER_VALUES], true /* light blue */);
+
+ // Some process memory dumps don't have own VM regions.
+ checkByteStatColumnInfosAndColor([
+ FIELD | DUMP,
+ 0,
+ FIELD | DUMP
+ ], [EXPECTED_SOME_OLDER_VALUES], true /* light blue */);
+ checkByteStatColumnInfosAndColor([
+ FIELD | DUMP | HAS_OWN_VM_REGIONS,
+ FIELD | DUMP,
+ FIELD | DUMP | HAS_OWN_VM_REGIONS
+ ], [EXPECTED_SOME_OLDER_VALUES], false /* blue */);
+ });
+
+ test('allocatorColumn', function() {
+ const c = new AllocatorColumn('Allocator', 'bytes', (x => x),
+ AggregationMode.MAX);
+ checkColorLegend(c.title, 'Allocator');
+ checkColor(c.color(undefined /* contexts */),
+ undefined /* no color (column cells) */);
+
+ const HAS_HEAP_DUMPS = 1 << 2;
+ const HAS_ALLOCATOR_HEAP_DUMP = 1 << 3;
+ const MISSING_SIZE = 1 << 4;
+ function checkAllocatorColumnInfosAndColor(fieldAndDumpMask,
+ expectedInfos) {
+ checkOverviewColumnInfosAndColor(c,
+ fieldAndDumpMask,
+ function(pmd, mask) {
+ if (mask & HAS_HEAP_DUMPS) {
+ pmd.heapDumps = {};
+ }
+ if (mask & HAS_ALLOCATOR_HEAP_DUMP) {
+ pmd.heapDumps.Allocator = new HeapDump(pmd, 'Allocator');
+ }
+ const mad = new MemoryAllocatorDump(pmd, 'Allocator');
+ if (!(mask & MISSING_SIZE)) {
+ mad.addNumeric('size',
+ new Scalar(sizeInBytes_smallerIsBetter, 7));
+ }
+ pmd.memoryAllocatorDumps = [mad];
+ },
+ expectedInfos,
+ undefined /* no color */);
+ }
+
+ // No context.
+ checkOverviewColumnInfosAndColor(c,
+ [FIELD],
+ undefined /* no context */,
+ [] /* no infos */,
+ undefined /* no color */);
+ checkOverviewColumnInfosAndColor(c,
+ [FIELD, FIELD, 0, FIELD],
+ undefined /* no context */,
+ [] /* no infos */,
+ undefined /* no color */);
+
+ // No infos.
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP
+ ], [] /* no infos */);
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP,
+ FIELD | DUMP | HAS_HEAP_DUMPS,
+ 0,
+ FIELD | DUMP
+ ], [] /* infos */);
+
+ const EXPECTED_ALL_HAVE_ALLOCATOR_HEAP_DUMP = {
+ icon: '\u2630',
+ message: 'Heap dump provided.'
+ };
+ const EXPECTED_SOME_HAVE_ALLOCATOR_HEAP_DUMP = {
+ icon: '\u2630',
+ message: 'Heap dump provided at some selected timestamps.'
+ };
+
+ // All process memory dumps have heap dumps.
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP
+ ], [EXPECTED_ALL_HAVE_ALLOCATOR_HEAP_DUMP]);
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP,
+ FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP,
+ FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP
+ ], [EXPECTED_ALL_HAVE_ALLOCATOR_HEAP_DUMP]);
+
+ // Some process memory dumps have heap dumps.
+ checkAllocatorColumnInfosAndColor([
+ 0,
+ FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP
+ ], [EXPECTED_SOME_HAVE_ALLOCATOR_HEAP_DUMP]);
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP,
+ FIELD | DUMP | HAS_HEAP_DUMPS,
+ FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP
+ ], [EXPECTED_SOME_HAVE_ALLOCATOR_HEAP_DUMP]);
+
+ const EXPECTED_ALL_MISSING_SIZE = {
+ icon: '\u26A0',
+ message: 'Size was not provided.',
+ color: 'red'
+ };
+ const EXPECTED_SOME_MISSING_SIZE = {
+ icon: '\u26A0',
+ message: 'Size was not provided at some selected timestamps.',
+ color: 'red'
+ };
+
+ // All process memory dumps are missing allocator size.
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP | MISSING_SIZE
+ ], [EXPECTED_ALL_MISSING_SIZE]);
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP | MISSING_SIZE,
+ FIELD | DUMP | MISSING_SIZE,
+ FIELD | DUMP | MISSING_SIZE
+ ], [EXPECTED_ALL_MISSING_SIZE]);
+
+ // Some process memory dumps use Android memtrack PSS fallback.
+ checkAllocatorColumnInfosAndColor([
+ 0,
+ FIELD | DUMP | MISSING_SIZE
+ ], [EXPECTED_SOME_MISSING_SIZE]);
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP | MISSING_SIZE,
+ FIELD | DUMP,
+ FIELD | DUMP | MISSING_SIZE
+ ], [EXPECTED_SOME_MISSING_SIZE]);
+
+ // Combination of heap dump and memtrack fallback infos.
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP | MISSING_SIZE | HAS_HEAP_DUMPS |
+ HAS_ALLOCATOR_HEAP_DUMP
+ ], [
+ EXPECTED_ALL_HAVE_ALLOCATOR_HEAP_DUMP,
+ EXPECTED_ALL_MISSING_SIZE
+ ]);
+ checkAllocatorColumnInfosAndColor([
+ FIELD | DUMP | HAS_HEAP_DUMPS | HAS_ALLOCATOR_HEAP_DUMP,
+ FIELD | DUMP,
+ FIELD | DUMP | MISSING_SIZE
+ ], [
+ EXPECTED_SOME_HAVE_ALLOCATOR_HEAP_DUMP,
+ EXPECTED_SOME_MISSING_SIZE
+ ]);
+ });
+
+ test('tracingColumn', function() {
+ const c = new TracingColumn('Tracing', 'bytes', (x => x),
+ AggregationMode.DIFF);
+ checkSpanWithColor(c.title, 'Tracing',
+ TracingColumn.COLOR /* expected column title gray color */);
+ checkColor(c.color(undefined /* contexts */),
+ TracingColumn.COLOR /* expected column cells gray color */);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_test_utils.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_test_utils.html
new file mode 100644
index 00000000000..2f702242140
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_test_utils.html
@@ -0,0 +1,593 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color.html">
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/heap_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Helper functions for memory dump analysis sub-view tests.
+ */
+tr.exportTo('tr.ui.analysis', function() {
+ const Color = tr.b.Color;
+ const ColorScheme = tr.b.ColorScheme;
+ const GlobalMemoryDump = tr.model.GlobalMemoryDump;
+ const ProcessMemoryDump = tr.model.ProcessMemoryDump;
+ const VMRegion = tr.model.VMRegion;
+ const VMRegionClassificationNode = tr.model.VMRegionClassificationNode;
+ const Scalar = tr.b.Scalar;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const unitlessNumber_smallerIsBetter =
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+ const HeapDump = tr.model.HeapDump;
+ const addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
+ const addProcessMemoryDump =
+ tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const addOwnershipLink = tr.model.MemoryDumpTestUtils.addOwnershipLink;
+
+ function createMultipleTestGlobalMemoryDumps() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const pA = model.getOrCreateProcess(1);
+ const pB = model.getOrCreateProcess(2);
+ const pC = model.getOrCreateProcess(3);
+ const pD = model.getOrCreateProcess(4);
+
+ // ======================================================================
+ // First timestamp.
+ // ======================================================================
+ const gmd1 = addGlobalMemoryDump(model, {ts: 42});
+
+ // Totals and VM regions.
+ const pmd1A = addProcessMemoryDump(gmd1, pA, {ts: 41});
+ pmd1A.totals = {residentBytes: 31457280 /* 30 MiB */};
+ pmd1A.vmRegions = VMRegionClassificationNode.fromRegions([
+ VMRegion.fromDict({
+ startAddress: 1024,
+ sizeInBytes: 20971520, /* 20 MiB */
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ mappedFile: '[stack]',
+ byteStats: {
+ privateDirtyResident: 8388608, /* 8 MiB */
+ sharedCleanResident: 12582912, /* 12 MiB */
+ proportionalResident: 10485760 /* 10 MiB */
+ }
+ })
+ ]);
+
+ // Everything.
+ const pmd1B = addProcessMemoryDump(gmd1, pB, {ts: 42});
+ pmd1B.totals = {
+ residentBytes: 20971520, /* 20 MiB */
+ peakResidentBytes: 41943040, /* 40 MiB */
+ arePeakResidentBytesResettable: false,
+ privateFootprintBytes: 15728640, /* 15 MiB */
+ platformSpecific: {
+ private_bytes: 10485760 /* 10 MiB */
+ }
+ };
+ pmd1B.vmRegions = VMRegionClassificationNode.fromRegions([
+ VMRegion.fromDict({
+ startAddress: 256,
+ sizeInBytes: 6000,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE,
+ mappedFile: '[stack:20310]',
+ byteStats: {
+ proportionalResident: 15728640, /* 15 MiB */
+ privateDirtyResident: 1572864, /* 1.5 MiB */
+ swapped: 32 /* 32 B */
+ }
+ }),
+ VMRegion.fromDict({
+ startAddress: 100000,
+ sizeInBytes: 4096,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ mappedFile: '/usr/lib/libwtf.so',
+ byteStats: {
+ proportionalResident: 4194304, /* 4 MiB */
+ privateDirtyResident: 0,
+ swapped: 0 /* 32 B */
+ }
+ })
+ ]);
+ pmd1B.memoryAllocatorDumps = [
+ newAllocatorDump(pmd1B, 'malloc',
+ {numerics: {size: 3145728 /* 3 MiB */}}),
+ newAllocatorDump(pmd1B, 'v8', {numerics: {size: 5242880 /* 5 MiB */}}),
+ newAllocatorDump(pmd1B, 'tracing', {numerics: {
+ size: 1048576 /* 1 MiB */,
+ resident_size: 1572864 /* 1.5 MiB */
+ }})
+ ];
+
+ // Allocator dumps only.
+ const pmd1C = addProcessMemoryDump(gmd1, pC, {ts: 43});
+ pmd1C.memoryAllocatorDumps = (function() {
+ const oilpanDump = newAllocatorDump(pmd1C, 'oilpan', {numerics: {
+ size: 3221225472 /* 3 GiB */,
+ inner_size: 5242880 /* 5 MiB */,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 2015)
+ }});
+ const v8Dump = newAllocatorDump(pmd1C, 'v8', {numerics: {
+ size: 1073741824 /* 1 GiB */,
+ inner_size: 2097152 /* 2 MiB */,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 204)
+ }});
+
+ addOwnershipLink(v8Dump, oilpanDump);
+
+ return [oilpanDump, v8Dump];
+ })();
+ pmd1C.heapDumps = {
+ 'v8': (function() {
+ const v8HeapDump = new HeapDump(pmd1C, 'v8');
+ v8HeapDump.addEntry(
+ tr.c.TestUtils.newStackTrace(model,
+ ['V8.Execute', 'UpdateLayoutTree']),
+ undefined /* sum over all object types */,
+ 536870912 /* 512 MiB */);
+ return v8HeapDump;
+ })()
+ };
+
+ // ======================================================================
+ // Second timestamp.
+ // ======================================================================
+ const gmd2 = addGlobalMemoryDump(model, {ts: 68});
+
+ // Everything.
+ const pmd2A = addProcessMemoryDump(gmd2, pA, {ts: 67});
+ pmd2A.totals = {residentBytes: 32505856 /* 31 MiB */};
+ pmd2A.vmRegions = VMRegionClassificationNode.fromRegions([
+ VMRegion.fromDict({
+ startAddress: 1024,
+ sizeInBytes: 20971520, /* 20 MiB */
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ mappedFile: '[stack]',
+ byteStats: {
+ privateDirtyResident: 8388608, /* 8 MiB */
+ sharedCleanResident: 11534336, /* 11 MiB */
+ proportionalResident: 11534336 /* 11 MiB */
+ }
+ }),
+ VMRegion.fromDict({
+ startAddress: 104857600,
+ sizeInBytes: 5242880, /* 5 MiB */
+ protectionFlags: VMRegion.PROTECTION_FLAG_EXECUTE,
+ mappedFile: '/usr/bin/google-chrome',
+ byteStats: {
+ privateDirtyResident: 0,
+ sharedCleanResident: 4194304, /* 4 MiB */
+ proportionalResident: 524288 /* 512 KiB */
+ }
+ })
+ ]);
+ pmd2A.memoryAllocatorDumps = [
+ newAllocatorDump(pmd2A, 'malloc', {numerics: {
+ size: 9437184 /* 9 MiB */
+ }}),
+ newAllocatorDump(pmd2A, 'tracing', {numerics: {
+ size: 2097152 /* 2 MiB */,
+ resident_size: 2621440 /* 2.5 MiB */
+ }})
+ ];
+
+ // Totals and allocator dumps only.
+ const pmd2B = addProcessMemoryDump(gmd2, pB, {ts: 69});
+ pmd2B.totals = {
+ residentBytes: 19922944, /* 19 MiB */
+ peakResidentBytes: 41943040, /* 40 MiB */
+ arePeakResidentBytesResettable: false,
+ privateFootprintBytes: 15728640, /* 15 MiB */
+ platformSpecific: {
+ private_bytes: 8912896 /* 8.5 MiB */
+ }
+ };
+ pmd2B.memoryAllocatorDumps = [
+ newAllocatorDump(pmd2B, 'malloc', {numerics: {
+ size: 2621440 /* 2.5 MiB */
+ }}),
+ newAllocatorDump(pmd2B, 'v8', {numerics: {
+ size: 5242880 /* 5 MiB */
+ }}),
+ newAllocatorDump(pmd2B, 'blink', {numerics: {
+ size: 7340032 /* 7 MiB */
+ }}),
+ newAllocatorDump(pmd2B, 'oilpan', {numerics: {size: 1}}),
+ newAllocatorDump(pmd2B, 'tracing', {numerics: {
+ size: 1572864 /* 1.5 MiB */,
+ resident_size: 2097152 /* 2 MiB */
+ }}),
+ newAllocatorDump(pmd2B, 'gpu', {numerics: {
+ memtrack_pss: 524288 /* 512 KiB */
+ }})
+ ];
+
+ // Resettable peak total size only.
+ const pmd2D = addProcessMemoryDump(gmd2, pD, {ts: 71});
+ pmd2D.totals = {
+ peakResidentBytes: 17825792, /* 17 MiB */
+ arePeakResidentBytesResettable: true
+ };
+
+ // ======================================================================
+ // Third timestamp.
+ // ======================================================================
+ const gmd3 = addGlobalMemoryDump(model, {ts: 100});
+
+ // Everything.
+ const pmd3B = addProcessMemoryDump(gmd3, pB, {ts: 102});
+ pmd3B.totals = {
+ residentBytes: 18874368, /* 18 MiB */
+ peakResidentBytes: 44040192, /* 42 MiB */
+ privateFootprintBytes: 15728640, /* 16 MiB */
+ arePeakResidentBytesResettable: false,
+ platformSpecific: {
+ private_bytes: 7340032 /* 7 MiB */
+ }
+ };
+ pmd3B.vmRegions = VMRegionClassificationNode.fromRegions([
+ VMRegion.fromDict({
+ startAddress: 256,
+ sizeInBytes: 6000,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE,
+ mappedFile: '[stack:20310]',
+ byteStats: {
+ proportionalResident: 21495808, /* 20.5 MiB */
+ privateDirtyResident: 524288, /* 0.5 MiB */
+ swapped: 64 /* 32 B */
+ }
+ })
+ ]);
+ pmd3B.memoryAllocatorDumps = [
+ newAllocatorDump(pmd3B, 'malloc', {numerics: {
+ size: 2883584 /* 2.75 MiB */
+ }}),
+ newAllocatorDump(pmd3B, 'v8', {numerics: {
+ size: 5767168 /* 5.5 MiB */
+ }}),
+ newAllocatorDump(pmd3B, 'blink', {numerics: {
+ size: 6291456 /* 7 MiB */
+ }}),
+ newAllocatorDump(pmd3B, 'tracing', {numerics: {
+ size: 2097152 /* 2 MiB */,
+ resident_size: 3145728 /* 3 MiB */
+ }}),
+ newAllocatorDump(pmd3B, 'gpu', {numerics: {
+ size: 1048576 /* 1 MiB */,
+ memtrack_pss: 786432 /* 768 KiB */
+ }})
+ ];
+
+ // Allocator dumps only.
+ const pmd3C = addProcessMemoryDump(gmd3, pC, {ts: 100});
+ pmd3C.memoryAllocatorDumps = (function() {
+ const oilpanDump = newAllocatorDump(pmd3C, 'oilpan', {numerics: {
+ size: 3221225472 /* 3 GiB */,
+ inner_size: 5242880 /* 5 MiB */,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 2015)
+ }});
+ const v8Dump = newAllocatorDump(pmd3C, 'v8', {numerics: {
+ size: 2147483648 /* 2 GiB */,
+ inner_size: 2097152 /* 2 MiB */,
+ objects_count: new Scalar(unitlessNumber_smallerIsBetter, 204)
+ }});
+
+ addOwnershipLink(v8Dump, oilpanDump);
+
+ return [oilpanDump, v8Dump];
+ })();
+ pmd3C.heapDumps = {
+ 'v8': (function() {
+ const v8HeapDump = new HeapDump(pmd1C, 'v8');
+ v8HeapDump.addEntry(
+ tr.c.TestUtils.newStackTrace(model,
+ ['V8.Execute', 'UpdateLayoutTree']),
+ undefined /* sum over all object types */,
+ 268435456 /* 256 MiB */);
+ v8HeapDump.addEntry(
+ tr.c.TestUtils.newStackTrace(model,
+ ['V8.Execute', 'FrameView::layout']),
+ undefined /* sum over all object types */,
+ 134217728 /* 128 MiB */);
+ return v8HeapDump;
+ })()
+ };
+
+ // Resettable peak total size only.
+ const pmd3D = addProcessMemoryDump(gmd3, pD, {ts: 99});
+ pmd3D.totals = {
+ peakResidentBytes: 17825792, /* 17 MiB */
+ arePeakResidentBytesResettable: true
+ };
+ });
+
+ return model.globalMemoryDumps;
+ }
+
+ function createSingleTestGlobalMemoryDump() {
+ return createMultipleTestGlobalMemoryDumps()[1];
+ }
+
+ function createMultipleTestProcessMemoryDumps() {
+ return createMultipleTestGlobalMemoryDumps().map(function(gmd) {
+ return gmd.processMemoryDumps[2];
+ });
+ }
+
+ function createSingleTestProcessMemoryDump() {
+ return createMultipleTestProcessMemoryDumps()[1];
+ }
+
+ function checkNumericFields(row, column, expectedValues, expectedUnit) {
+ let fields;
+ if (column === undefined) {
+ fields = row;
+ } else {
+ fields = column.fields(row);
+ }
+
+ if (expectedValues === undefined) {
+ assert.isUndefined(fields);
+ return;
+ }
+
+ assert.lengthOf(fields, expectedValues.length);
+ for (let i = 0; i < fields.length; i++) {
+ const field = fields[i];
+ const expectedValue = expectedValues[i];
+ if (expectedValue === undefined) {
+ assert.isUndefined(field);
+ } else {
+ assert.isDefined(expectedUnit); // Test sanity check.
+ assert.instanceOf(field, Scalar);
+ assert.strictEqual(field.value, expectedValue);
+ assert.strictEqual(field.unit, expectedUnit);
+ }
+ }
+ }
+
+ function checkSizeNumericFields(row, column, expectedValues) {
+ checkNumericFields(row, column, expectedValues,
+ sizeInBytes_smallerIsBetter);
+ }
+
+ function checkStringFields(row, column, expectedStrings) {
+ const fields = column.fields(row);
+
+ if (expectedStrings === undefined) {
+ assert.isUndefined(fields);
+ return;
+ }
+
+ assert.deepEqual(Array.from(fields), expectedStrings);
+ }
+
+ /**
+ * Check the titles, types and aggregation modes of a list of columns.
+ * expectedColumns is a list of dictionaries with the following fields:
+ *
+ * - title: Either the expected title (string), or a matcher for it
+ * (function that accepts the actual title as its argument).
+ * - type: The expected class of the column.
+ * - noAggregation: If true, the column is expected to have no aggregation
+ * mode (regardless of expectedAggregationMode).
+ */
+ function checkColumns(columns, expectedColumns, expectedAggregationMode) {
+ assert.lengthOf(columns, expectedColumns.length);
+ for (let i = 0; i < expectedColumns.length; i++) {
+ const actualColumn = columns[i];
+ const expectedColumn = expectedColumns[i];
+ const expectedTitle = expectedColumn.title;
+ if (typeof expectedTitle === 'function') {
+ expectedTitle(actualColumn.title); // Custom title matcher.
+ } else if (actualColumn.title.innerText) {
+ // HTML title.
+ assert.strictEqual(actualColumn.title.innerText, expectedTitle);
+ } else {
+ assert.strictEqual(actualColumn.title, expectedTitle); // String title.
+ }
+ assert.instanceOf(actualColumn, expectedColumn.type);
+ assert.strictEqual(actualColumn.aggregationMode,
+ expectedColumn.noAggregation ? undefined : expectedAggregationMode);
+ }
+ }
+
+ function checkColumnInfosAndColor(
+ column, fields, contexts, expectedInfos, expectedColorReservedName) {
+ // Test sanity checks.
+ assert.isDefined(fields);
+ if (contexts !== undefined) {
+ assert.lengthOf(contexts, fields.length);
+ }
+
+ // Check infos.
+ const infos = [];
+ column.addInfos(fields, contexts, infos);
+ assert.lengthOf(infos, expectedInfos.length);
+ for (let i = 0; i < expectedInfos.length; i++) {
+ assert.deepEqual(infos[i], expectedInfos[i]);
+ }
+
+ // Check color.
+ const actualColor = typeof column.color === 'function' ?
+ column.color(fields, contexts) :
+ column.color;
+ checkColor(actualColor, expectedColorReservedName);
+ }
+
+ function checkColor(actualColorString, expectedColorString) {
+ if (actualColorString === undefined) {
+ assert.isUndefined(expectedColorString);
+ return;
+ }
+ const actualColor = Color.fromString(actualColorString);
+ const expectedColor = Color.fromString(expectedColorString);
+ assert.deepEqual(actualColor, expectedColor);
+ }
+
+ function createAndCheckEmptyPanes(
+ test, paneTagName, propertyName, opt_callback) {
+ // Unset property.
+ const unsetViewEl = createTestPane(paneTagName);
+ unsetViewEl.rebuild();
+ assert.isUndefined(unsetViewEl.createChildPane());
+ test.addHTMLOutput(unsetViewEl);
+
+ // Undefined property.
+ const undefinedViewEl = createTestPane(paneTagName);
+ undefinedViewEl[propertyName] = undefined;
+ undefinedViewEl.rebuild();
+ assert.isUndefined(undefinedViewEl.createChildPane());
+ test.addHTMLOutput(undefinedViewEl);
+
+ // Empty property.
+ const emptyViewEl = createTestPane(paneTagName);
+ emptyViewEl[propertyName] = [];
+ emptyViewEl.rebuild();
+ assert.isUndefined(undefinedViewEl.createChildPane());
+ test.addHTMLOutput(emptyViewEl);
+
+ // Check that all the panes have the same dimensions.
+ const unsetBounds = unsetViewEl.getBoundingClientRect();
+ const undefinedBounds = undefinedViewEl.getBoundingClientRect();
+ const emptyBounds = emptyViewEl.getBoundingClientRect();
+ assert.strictEqual(undefinedBounds.width, unsetBounds.width);
+ assert.strictEqual(emptyBounds.width, unsetBounds.width);
+ assert.strictEqual(undefinedBounds.height, unsetBounds.height);
+ assert.strictEqual(emptyBounds.height, unsetBounds.height);
+
+ // Custom checks (if provided).
+ if (opt_callback) {
+ opt_callback(unsetViewEl);
+ opt_callback(undefinedViewEl);
+ opt_callback(emptyViewEl);
+ }
+ }
+
+ function createTestPane(tagName) {
+ const paneEl = document.createElement(tagName);
+
+ // Store a list of requested child panes (for inspection in tests).
+ paneEl.requestedChildPanes = [];
+ paneEl.addEventListener('request-child-pane-change', function() {
+ paneEl.requestedChildPanes.push(paneEl.createChildPane());
+ });
+
+ paneEl.createChildPane = function() {
+ const childPaneBuilder = this.childPaneBuilder;
+ if (childPaneBuilder === undefined) return undefined;
+ return childPaneBuilder();
+ };
+
+ return paneEl;
+ }
+
+ // TODO(petrcermak): Consider moving this to tracing/ui/base/dom_helpers.html.
+ function isElementDisplayed(element) {
+ const style = getComputedStyle(element);
+ const displayed = style.display;
+ if (displayed === undefined) return true;
+ return displayed.indexOf('none') === -1;
+ }
+
+ /**
+ * Convert a list of ContainerMemoryDump(s) to a list of dictionaries of the
+ * underlying ProcessMemoryDump(s).
+ */
+ function convertToProcessMemoryDumps(containerMemoryDumps) {
+ return containerMemoryDumps.map(function(containerMemoryDump) {
+ return containerMemoryDump.processMemoryDumps;
+ });
+ }
+
+ /**
+ * Extract a chronological list of ProcessMemoryDump(s) (for a given process)
+ * from a chronological list of dictionaries of ProcessMemoryDump(s).
+ */
+ function extractProcessMemoryDumps(processMemoryDumps, pid) {
+ return processMemoryDumps.map(function(memoryDumps) {
+ return memoryDumps[pid];
+ });
+ }
+
+ /**
+ * Extract a chronological list of lists of VMRegion(s) (for a given process)
+ * from a chronological list of dictionaries of ProcessMemoryDump(s).
+ */
+ function extractVmRegions(processMemoryDumps, pid) {
+ return processMemoryDumps.map(function(memoryDumps) {
+ const processMemoryDump = memoryDumps[pid];
+ if (processMemoryDump === undefined) return undefined;
+ return processMemoryDump.mostRecentVmRegions;
+ });
+ }
+
+ /**
+ * Extract a chronological list of MemoryAllocatorDump(s) (for a given
+ * process and allocator name) from a chronological list of dictionaries of
+ * ProcessMemoryDump(s).
+ */
+ function extractMemoryAllocatorDumps(processMemoryDumps, pid, allocatorName) {
+ return processMemoryDumps.map(function(memoryDumps) {
+ const processMemoryDump = memoryDumps[pid];
+ if (processMemoryDump === undefined) return undefined;
+ return processMemoryDump.getMemoryAllocatorDumpByFullName(allocatorName);
+ });
+ }
+
+ /**
+ * Extract a chronological list of HeapDump(s) (for a given process and
+ * allocator name) from a chronological list of dictionaries of
+ * ProcessMemoryDump(s).
+ */
+ function extractHeapDumps(processMemoryDumps, pid, allocatorName) {
+ return processMemoryDumps.map(function(memoryDumps) {
+ const processMemoryDump = memoryDumps[pid];
+ if (processMemoryDump === undefined ||
+ processMemoryDump.heapDumps === undefined) {
+ return undefined;
+ }
+ return processMemoryDump.heapDumps[allocatorName];
+ });
+ }
+
+ return {
+ createSingleTestGlobalMemoryDump,
+ createMultipleTestGlobalMemoryDumps,
+ createSingleTestProcessMemoryDump,
+ createMultipleTestProcessMemoryDumps,
+ checkNumericFields,
+ checkSizeNumericFields,
+ checkStringFields,
+ checkColumns,
+ checkColumnInfosAndColor,
+ checkColor,
+ createAndCheckEmptyPanes,
+ createTestPane,
+ isElementDisplayed,
+ convertToProcessMemoryDumps,
+ extractProcessMemoryDumps,
+ extractVmRegions,
+ extractMemoryAllocatorDumps,
+ extractHeapDumps,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util.html
new file mode 100644
index 00000000000..654ce0ea73f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util.html
@@ -0,0 +1,915 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Helper code for memory dump sub-views.
+ */
+tr.exportTo('tr.ui.analysis', function() {
+ const NO_BREAK_SPACE = String.fromCharCode(160);
+ const RIGHTWARDS_ARROW = String.fromCharCode(8594);
+
+ const COLLATOR = new Intl.Collator(undefined, {numeric: true});
+
+ /**
+ * A table column for displaying memory dump row titles.
+ *
+ * @constructor
+ */
+ function TitleColumn(title) {
+ this.title = title;
+ }
+
+ TitleColumn.prototype = {
+ supportsCellSelection: false,
+
+ /**
+ * Get the title associated with a given row.
+ *
+ * This method will decorate the title with color and '+++'/'---' prefix if
+ * appropriate (as determined by the optional row.contexts field).
+ * Examples:
+ *
+ * +----------------------+-----------------+--------+--------+
+ * | Contexts provided at | Interpretation | Prefix | Color |
+ * +----------------------+-----------------+--------+--------+
+ * | 1111111111 | always present | | |
+ * | 0000111111 | added | +++ | red |
+ * | 1111111000 | deleted | --- | green |
+ * | 1100111111* | flaky | | purple |
+ * | 0001001111 | added + flaky | +++ | purple |
+ * | 1111100010 | deleted + flaky | --- | purple |
+ * +----------------------+-----------------+--------+--------+
+ *
+ * *) This means that, given a selection of 10 memory dumps, a particular
+ * row (e.g. a process) was present in the first 2 and last 6 of them
+ * (but not in the third and fourth dump).
+ *
+ * This method should therefore NOT be overriden by subclasses. The
+ * formatTitle method should be overriden instead when necessary.
+ */
+ value(row) {
+ const formattedTitle = this.formatTitle(row);
+
+ const contexts = row.contexts;
+ if (contexts === undefined || contexts.length === 0) {
+ return formattedTitle;
+ }
+
+ // Determine if the row was provided in the first and last row and how
+ // many times it changed between being provided and not provided.
+ const firstContext = contexts[0];
+ const lastContext = contexts[contexts.length - 1];
+ let changeDefinedContextCount = 0;
+ for (let i = 1; i < contexts.length; i++) {
+ if ((contexts[i] === undefined) !== (contexts[i - 1] === undefined)) {
+ changeDefinedContextCount++;
+ }
+ }
+
+ // Determine the color and prefix of the title.
+ let color = undefined;
+ let prefix = undefined;
+ if (!firstContext && lastContext) {
+ // The row was added.
+ color = 'red';
+ prefix = '+++';
+ } else if (firstContext && !lastContext) {
+ // The row was removed.
+ color = 'green';
+ prefix = '---';
+ }
+ if (changeDefinedContextCount > 1) {
+ // The row was flaky (added/removed more than once).
+ color = 'purple';
+ }
+
+ if (color === undefined && prefix === undefined) {
+ return formattedTitle;
+ }
+
+ const titleEl = document.createElement('span');
+ if (prefix !== undefined) {
+ const prefixEl = tr.ui.b.createSpan({textContent: prefix});
+ // Enforce same width of '+++' and '---'.
+ prefixEl.style.fontFamily = 'monospace';
+ Polymer.dom(titleEl).appendChild(prefixEl);
+ Polymer.dom(titleEl).appendChild(
+ tr.ui.b.asHTMLOrTextNode(NO_BREAK_SPACE));
+ }
+ if (color !== undefined) {
+ titleEl.style.color = color;
+ }
+ Polymer.dom(titleEl).appendChild(
+ tr.ui.b.asHTMLOrTextNode(formattedTitle));
+ return titleEl;
+ },
+
+ /**
+ * Format the title associated with a given row. This method is intended to
+ * be overriden by subclasses.
+ */
+ formatTitle(row) {
+ return row.title;
+ },
+
+ cmp(rowA, rowB) {
+ return COLLATOR.compare(rowA.title, rowB.title);
+ }
+ };
+
+ /**
+ * Abstract table column for displaying memory dump data.
+ *
+ * @constructor
+ */
+ function MemoryColumn(name, cellPath, aggregationMode) {
+ this.name = name;
+ this.cellPath = cellPath;
+ this.shouldSetContextGroup = false;
+
+ // See MemoryColumn.AggregationMode enum in this file.
+ this.aggregationMode = aggregationMode;
+ }
+
+ /**
+ * Construct columns from cells in a hierarchy of rows and a list of rules.
+ *
+ * The list of rules contains objects with three fields:
+ *
+ * condition: Optional string or regular expression matched against the
+ * name of a cell. If omitted, the rule will match any cell.
+ * importance: Mandatory number which determines the final order of the
+ * columns. The column with the highest importance will be first in the
+ * returned array.
+ * columnConstructor: Mandatory memory column constructor.
+ *
+ * Example:
+ *
+ * const importanceRules = [
+ * {
+ * condition: 'page_size',
+ * columnConstructor: NumericMemoryColumn,
+ * importance: 8
+ * },
+ * {
+ * condition: /size/,
+ * columnConstructor: CustomNumericMemoryColumn,
+ * importance: 10
+ * },
+ * {
+ * // No condition: matches all columns.
+ * columnConstructor: NumericMemoryColumn,
+ * importance: 9
+ * }
+ * ];
+ *
+ * Given a name of a cell, the corresponding column constructor and
+ * importance are determined by the first rule whose condition matches the
+ * column's name. For example, given a cell with name 'inner_size', the
+ * corresponding column will be constructed using CustomNumericMemoryColumn
+ * and its importance (for sorting purposes) will be 10 (second rule).
+ *
+ * After columns are constructed for all cell names, they are sorted in
+ * descending order of importance and the resulting list is returned. In the
+ * example above, the constructed columns will be sorted into three groups as
+ * follows:
+ *
+ * [most important, left in the resulting table]
+ * 1. columns whose name contains 'size' excluding 'page_size' because it
+ * would have already matched the first rule (Note that string matches
+ * must be exact so a column named 'page_size2' would not match the
+ * first rule and would therefore belong to this group).
+ * 2. columns whose name does not contain 'size'.
+ * 3. columns whose name is 'page_size'.
+ * [least important, right in the resulting table]
+ *
+ * where columns will be sorted alphabetically within each group.
+ *
+ * @param {!Array.<!Object>} rows
+ * @param {!Object} config
+ * @param {string} config.cellKey
+ * @param {!MemoryColumn.AggregationMode=} config.aggregationMode
+ * @param {!Array.<!{
+ * condition: (string|!RegExp)=,
+ * importance: number,
+ * columnConstructor: !function(new: MemoryColumn, ...)=,
+ * shouldSetContextGroup: boolean=
+ * }>} config.rules
+ */
+ MemoryColumn.fromRows = function(rows, config) {
+ // Recursively find the names of all cells of the rows (and their sub-rows).
+ const cellNames = new Set();
+ function gatherCellNames(rows) {
+ rows.forEach(function(row) {
+ if (row === undefined) return;
+ const fieldCells = row[config.cellKey];
+ if (fieldCells !== undefined) {
+ for (const [fieldName, fieldCell] of Object.entries(fieldCells)) {
+ if (fieldCell === undefined || fieldCell.fields === undefined) {
+ continue;
+ }
+ cellNames.add(fieldName);
+ }
+ }
+ const subRows = row.subRows;
+ if (subRows !== undefined) {
+ gatherCellNames(subRows);
+ }
+ });
+ }
+ gatherCellNames(rows);
+
+ // Based on the provided list of rules, construct the columns and calculate
+ // their importance.
+ const positions = [];
+ cellNames.forEach(function(cellName) {
+ const cellPath = [config.cellKey, cellName];
+ const matchingRule = MemoryColumn.findMatchingRule(
+ cellName, config.rules);
+ const constructor = matchingRule.columnConstructor;
+ const column = new constructor(
+ cellName, cellPath, config.aggregationMode);
+ column.shouldSetContextGroup = !!config.shouldSetContextGroup;
+ positions.push({
+ importance: matchingRule.importance,
+ column
+ });
+ });
+
+ positions.sort(function(a, b) {
+ // Sort columns with the same importance alphabetically.
+ if (a.importance === b.importance) {
+ return COLLATOR.compare(a.column.name, b.column.name);
+ }
+
+ // Sort columns in descending order of importance.
+ return b.importance - a.importance;
+ });
+
+ return positions.map(function(position) { return position.column; });
+ };
+
+ MemoryColumn.spaceEqually = function(columns) {
+ const columnWidth = (100 / columns.length).toFixed(3) + '%';
+ columns.forEach(function(column) {
+ column.width = columnWidth;
+ });
+ };
+
+ MemoryColumn.findMatchingRule = function(name, rules) {
+ for (let i = 0; i < rules.length; i++) {
+ const rule = rules[i];
+ if (MemoryColumn.nameMatchesCondition(name, rule.condition)) {
+ return rule;
+ }
+ }
+ return undefined;
+ };
+
+ MemoryColumn.nameMatchesCondition = function(name, condition) {
+ // Rules without conditions match all columns.
+ if (condition === undefined) return true;
+
+ // String conditions must match the column name exactly.
+ if (typeof(condition) === 'string') return name === condition;
+
+ // If the condition is not a string, assume it is a RegExp.
+ return condition.test(name);
+ };
+
+ /** @enum */
+ MemoryColumn.AggregationMode = {
+ DIFF: 0,
+ MAX: 1
+ };
+
+ MemoryColumn.SOME_TIMESTAMPS_INFO_QUANTIFIER = 'at some selected timestamps';
+
+ MemoryColumn.prototype = {
+ get title() {
+ return this.name;
+ },
+
+ cell(row) {
+ let cell = row;
+ const cellPath = this.cellPath;
+ for (let i = 0; i < cellPath.length; i++) {
+ if (cell === undefined) return undefined;
+ cell = cell[cellPath[i]];
+ }
+ return cell;
+ },
+
+ aggregateCells(row, subRows) {
+ // No generic aggregation.
+ },
+
+ fields(row) {
+ const cell = this.cell(row);
+ if (cell === undefined) return undefined;
+ return cell.fields;
+ },
+
+ /**
+ * Format a cell associated with this column from the given row. This
+ * method is not intended to be overriden.
+ */
+ value(row) {
+ const fields = this.fields(row);
+ if (this.hasAllRelevantFieldsUndefined(fields)) return '';
+
+ // Determine the color and infos of the resulting element.
+ const contexts = row.contexts;
+ const color = this.color(fields, contexts);
+ const infos = [];
+ this.addInfos(fields, contexts, infos);
+
+ // Format the actual fields.
+ const formattedFields = this.formatFields(fields);
+
+ // If no color is specified and there are no infos, there is no need to
+ // wrap the value in a span element.#
+ if ((color === undefined || formattedFields === '') &&
+ infos.length === 0) {
+ return formattedFields;
+ }
+
+ const fieldEl = document.createElement('span');
+ fieldEl.style.display = 'flex';
+ fieldEl.style.alignItems = 'center';
+ fieldEl.style.justifyContent = 'flex-end';
+ Polymer.dom(fieldEl).appendChild(
+ tr.ui.b.asHTMLOrTextNode(formattedFields));
+
+ // Add info icons with tooltips.
+ infos.forEach(function(info) {
+ const infoEl = document.createElement('span');
+ infoEl.style.paddingLeft = '4px';
+ infoEl.style.cursor = 'help';
+ infoEl.style.fontWeight = 'bold';
+ Polymer.dom(infoEl).textContent = info.icon;
+ if (info.color !== undefined) {
+ infoEl.style.color = info.color;
+ }
+ infoEl.title = info.message;
+ Polymer.dom(fieldEl).appendChild(infoEl);
+ }, this);
+
+ // Set the color of the element.
+ if (color !== undefined) {
+ fieldEl.style.color = color;
+ }
+
+ return fieldEl;
+ },
+
+ /**
+ * Returns true iff all fields of a row which are relevant for the current
+ * aggregation mode (e.g. first and last field for diff mode) are undefined.
+ */
+ hasAllRelevantFieldsUndefined(fields) {
+ if (fields === undefined) return true;
+
+ switch (this.aggregationMode) {
+ case MemoryColumn.AggregationMode.DIFF:
+ // Only the first and last field are relevant.
+ return fields[0] === undefined &&
+ fields[fields.length - 1] === undefined;
+
+ case MemoryColumn.AggregationMode.MAX:
+ default:
+ // All fields are relevant.
+ return fields.every(function(field) { return field === undefined; });
+ }
+ },
+
+ /**
+ * Get the color of the given fields formatted by this column. At least one
+ * field relevant for the current aggregation mode is guaranteed to be
+ * defined.
+ */
+ color(fields, contexts) {
+ return undefined;
+ },
+
+ /**
+ * Format an arbitrary number of fields. At least one field relevant for
+ * the current aggregation mode is guaranteed to be defined.
+ */
+ formatFields(fields) {
+ if (fields.length === 1) {
+ return this.formatSingleField(fields[0]);
+ }
+ return this.formatMultipleFields(fields);
+ },
+
+ /**
+ * Format a single defined field.
+ *
+ * This method is intended to be overriden by field type specific columns
+ * (e.g. show '1.0 KiB' instead of '1024' for Scalar(s) representing
+ * bytes).
+ */
+ formatSingleField(field) {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * Format multiple fields. At least one field relevant for the current
+ * aggregation mode is guaranteed to be defined.
+ *
+ * The aggregation mode specializations of this method (e.g.
+ * formatMultipleFieldsDiff) are intended to be overriden by field type
+ * specific columns.
+ */
+ formatMultipleFields(fields) {
+ switch (this.aggregationMode) {
+ case MemoryColumn.AggregationMode.DIFF:
+ return this.formatMultipleFieldsDiff(
+ fields[0], fields[fields.length - 1]);
+
+ case MemoryColumn.AggregationMode.MAX:
+ return this.formatMultipleFieldsMax(fields);
+
+ default:
+ return tr.ui.b.createSpan({
+ textContent: '(unsupported aggregation mode)',
+ italic: true
+ });
+ }
+ },
+
+ formatMultipleFieldsDiff(firstField, lastField) {
+ throw new Error('Not implemented');
+ },
+
+ formatMultipleFieldsMax(fields) {
+ return this.formatSingleField(this.getMaxField(fields));
+ },
+
+ cmp(rowA, rowB) {
+ const fieldsA = this.fields(rowA);
+ const fieldsB = this.fields(rowB);
+
+ // Sanity check.
+ if (fieldsA !== undefined && fieldsB !== undefined &&
+ fieldsA.length !== fieldsB.length) {
+ throw new Error('Different number of fields');
+ }
+
+ // Handle empty fields.
+ const undefinedA = this.hasAllRelevantFieldsUndefined(fieldsA);
+ const undefinedB = this.hasAllRelevantFieldsUndefined(fieldsB);
+ if (undefinedA && undefinedB) return 0;
+ if (undefinedA) return -1;
+ if (undefinedB) return 1;
+
+ return this.compareFields(fieldsA, fieldsB);
+ },
+
+ /**
+ * Compare a pair of single or multiple fields. At least one field relevant
+ * for the current aggregation mode is guaranteed to be defined in each of
+ * the two lists.
+ */
+ compareFields(fieldsA, fieldsB) {
+ if (fieldsA.length === 1) {
+ return this.compareSingleFields(fieldsA[0], fieldsB[0]);
+ }
+ return this.compareMultipleFields(fieldsA, fieldsB);
+ },
+
+ /**
+ * Compare a pair of single defined fields.
+ *
+ * This method is intended to be overriden by field type specific columns.
+ */
+ compareSingleFields(fieldA, fieldB) {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * Compare a pair of multiple fields. At least one field relevant for the
+ * current aggregation mode is guaranteed to be defined in each of the two
+ * lists.
+ *
+ * The aggregation mode specializations of this method (e.g.
+ * compareMultipleFieldsDiff) are intended to be overriden by field type
+ * specific columns.
+ */
+ compareMultipleFields(fieldsA, fieldsB) {
+ switch (this.aggregationMode) {
+ case MemoryColumn.AggregationMode.DIFF:
+ return this.compareMultipleFieldsDiff(
+ fieldsA[0], fieldsA[fieldsA.length - 1],
+ fieldsB[0], fieldsB[fieldsB.length - 1]);
+
+ case MemoryColumn.AggregationMode.MAX:
+ return this.compareMultipleFieldsMax(fieldsA, fieldsB);
+
+ default:
+ return 0;
+ }
+ },
+
+ compareMultipleFieldsDiff(firstFieldA, lastFieldA, firstFieldB,
+ lastFieldB) {
+ throw new Error('Not implemented');
+ },
+
+ compareMultipleFieldsMax(fieldsA, fieldsB) {
+ return this.compareSingleFields(
+ this.getMaxField(fieldsA), this.getMaxField(fieldsB));
+ },
+
+ getMaxField(fields) {
+ return fields.reduce(function(accumulator, field) {
+ if (field === undefined) {
+ return accumulator;
+ }
+ if (accumulator === undefined ||
+ this.compareSingleFields(field, accumulator) > 0) {
+ return field;
+ }
+ return accumulator;
+ }.bind(this), undefined);
+ },
+
+ addInfos(fields, contexts, infos) {
+ // No generic infos.
+ },
+
+ getImportance(importanceRules) {
+ if (importanceRules.length === 0) return 0;
+
+ // Find the first matching rule.
+ const matchingRule =
+ MemoryColumn.findMatchingRule(this.name, importanceRules);
+ if (matchingRule !== undefined) {
+ return matchingRule.importance;
+ }
+
+ // No matching rule. Return lower importance than all rules.
+ let minImportance = importanceRules[0].importance;
+ for (let i = 1; i < importanceRules.length; i++) {
+ minImportance = Math.min(minImportance, importanceRules[i].importance);
+ }
+ return minImportance - 1;
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function StringMemoryColumn(name, cellPath, aggregationMode) {
+ MemoryColumn.call(this, name, cellPath, aggregationMode);
+ }
+
+ StringMemoryColumn.prototype = {
+ __proto__: MemoryColumn.prototype,
+
+ formatSingleField(string) {
+ return string;
+ },
+
+ formatMultipleFieldsDiff(firstString, lastString) {
+ if (firstString === undefined) {
+ // String was added ("+NEW_VALUE" in red).
+ const spanEl = tr.ui.b.createSpan({color: 'red'});
+ Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode('+'));
+ Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(
+ this.formatSingleField(lastString)));
+ return spanEl;
+ } else if (lastString === undefined) {
+ // String was removed ("-OLD_VALUE" in green).
+ const spanEl = tr.ui.b.createSpan({color: 'green'});
+ Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode('-'));
+ Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(
+ this.formatSingleField(firstString)));
+ return spanEl;
+ } else if (firstString === lastString) {
+ // String didn't change ("VALUE" with unchanged color).
+ return this.formatSingleField(firstString);
+ }
+ // String changed ("OLD_VALUE -> NEW_VALUE" in orange).
+ const spanEl = tr.ui.b.createSpan({color: 'DarkOrange'});
+ Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(
+ this.formatSingleField(firstString)));
+ Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(
+ ' ' + RIGHTWARDS_ARROW + ' '));
+ Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(
+ this.formatSingleField(lastString)));
+ return spanEl;
+ },
+
+ compareSingleFields(stringA, stringB) {
+ return COLLATOR.compare(stringA, stringB);
+ },
+
+ compareMultipleFieldsDiff(firstStringA, lastStringA, firstStringB,
+ lastStringB) {
+ // If one of the strings was added (and the other one wasn't), mark the
+ // corresponding diff as greater.
+ if (firstStringA === undefined && firstStringB !== undefined) {
+ return 1;
+ }
+ if (firstStringA !== undefined && firstStringB === undefined) {
+ return -1;
+ }
+
+ // If both strings were added, compare the last values (greater last
+ // value implies greater diff).
+ if (firstStringA === undefined && firstStringB === undefined) {
+ return this.compareSingleFields(lastStringA, lastStringB);
+ }
+
+ // If one of the strings was removed (and the other one wasn't), mark the
+ // corresponding diff as lower.
+ if (lastStringA === undefined && lastStringB !== undefined) {
+ return -1;
+ }
+ if (lastStringA !== undefined && lastStringB === undefined) {
+ return 1;
+ }
+
+ // If both strings were removed, compare the first values (greater first
+ // value implies smaller (!) diff).
+ if (lastStringA === undefined && lastStringB === undefined) {
+ return this.compareSingleFields(firstStringB, firstStringA);
+ }
+
+ const areStringsAEqual = firstStringA === lastStringA;
+ const areStringsBEqual = firstStringB === lastStringB;
+
+ // Consider diffs of strings that did not change to be smaller than diffs
+ // of strings that did change.
+ if (areStringsAEqual && areStringsBEqual) return 0;
+ if (areStringsAEqual) return -1;
+ if (areStringsBEqual) return 1;
+
+ // Both strings changed. We are unable to determine the ordering of the
+ // diffs.
+ return 0;
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function NumericMemoryColumn(name, cellPath, aggregationMode) {
+ MemoryColumn.call(this, name, cellPath, aggregationMode);
+ }
+
+ // Avoid tiny positive/negative diffs (displayed in the UI as '+0.0 B' and
+ // '-0.0 B') due to imprecise floating-point arithmetic by treating all diffs
+ // within the (-DIFF_EPSILON, DIFF_EPSILON) range as zeros.
+ NumericMemoryColumn.DIFF_EPSILON = 0.0001;
+
+ NumericMemoryColumn.prototype = {
+ __proto__: MemoryColumn.prototype,
+
+ align: tr.ui.b.TableFormat.ColumnAlignment.RIGHT,
+
+ aggregateCells(row, subRows) {
+ const subRowCells = subRows.map(this.cell, this);
+
+ // Determine if there is at least one defined numeric in the sub-row
+ // cells and the timestamp count.
+ let hasDefinedSubRowNumeric = false;
+ let timestampCount = undefined;
+ subRowCells.forEach(function(subRowCell) {
+ if (subRowCell === undefined) return;
+
+ const subRowNumerics = subRowCell.fields;
+ if (subRowNumerics === undefined) return;
+
+ if (timestampCount === undefined) {
+ timestampCount = subRowNumerics.length;
+ } else if (timestampCount !== subRowNumerics.length) {
+ throw new Error('Sub-rows have different numbers of timestamps');
+ }
+
+ if (hasDefinedSubRowNumeric) {
+ return; // Avoid unnecessary traversals of the numerics.
+ }
+ hasDefinedSubRowNumeric = subRowNumerics.some(function(numeric) {
+ return numeric !== undefined;
+ });
+ });
+ if (!hasDefinedSubRowNumeric) {
+ return; // No numeric to aggregate.
+ }
+
+ // Get or create the row cell.
+ const cellPath = this.cellPath;
+ let rowCell = row;
+ for (let i = 0; i < cellPath.length; i++) {
+ const nextStepName = cellPath[i];
+ let nextStep = rowCell[nextStepName];
+ if (nextStep === undefined) {
+ if (i < cellPath.length - 1) {
+ nextStep = {};
+ } else {
+ nextStep = new MemoryCell(undefined);
+ }
+ rowCell[nextStepName] = nextStep;
+ }
+ rowCell = nextStep;
+ }
+ if (rowCell.fields === undefined) {
+ rowCell.fields = new Array(timestampCount);
+ } else if (rowCell.fields.length !== timestampCount) {
+ throw new Error(
+ 'Row has a different number of timestamps than sub-rows');
+ }
+
+ for (let i = 0; i < timestampCount; i++) {
+ if (rowCell.fields[i] !== undefined) continue;
+ rowCell.fields[i] = tr.model.MemoryAllocatorDump.aggregateNumerics(
+ subRowCells.map(function(subRowCell) {
+ if (subRowCell === undefined || subRowCell.fields === undefined) {
+ return undefined;
+ }
+ return subRowCell.fields[i];
+ }));
+ }
+ },
+
+ formatSingleField(numeric) {
+ return tr.v.ui.createScalarSpan(numeric, {
+ context: this.getFormattingContext(numeric.unit),
+ contextGroup: this.shouldSetContextGroup ? this.name : undefined,
+ inline: true,
+ });
+ },
+
+ getFormattingContext(unit) {
+ return undefined;
+ },
+
+ formatMultipleFieldsDiff(firstNumeric, lastNumeric) {
+ return this.formatSingleField(
+ this.getDiffField_(firstNumeric, lastNumeric));
+ },
+
+ compareSingleFields(numericA, numericB) {
+ return numericA.value - numericB.value;
+ },
+
+ compareMultipleFieldsDiff(firstNumericA, lastNumericA,
+ firstNumericB, lastNumericB) {
+ return this.getDiffFieldValue_(firstNumericA, lastNumericA) -
+ this.getDiffFieldValue_(firstNumericB, lastNumericB);
+ },
+
+ getDiffField_(firstNumeric, lastNumeric) {
+ const definedNumeric = firstNumeric || lastNumeric;
+ return new tr.b.Scalar(definedNumeric.unit.correspondingDeltaUnit,
+ this.getDiffFieldValue_(firstNumeric, lastNumeric));
+ },
+
+ getDiffFieldValue_(firstNumeric, lastNumeric) {
+ const firstValue = firstNumeric === undefined ? 0 : firstNumeric.value;
+ const lastValue = lastNumeric === undefined ? 0 : lastNumeric.value;
+ const diff = lastValue - firstValue;
+ return Math.abs(diff) < NumericMemoryColumn.DIFF_EPSILON ? 0 : diff;
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function MemoryCell(fields) {
+ this.fields = fields;
+ }
+
+ MemoryCell.extractFields = function(cell) {
+ if (cell === undefined) return undefined;
+ return cell.fields;
+ };
+
+ /** Limit for the number of sub-rows for recursive table row expansion. */
+ const RECURSIVE_EXPANSION_MAX_VISIBLE_ROW_COUNT = 10;
+
+ function expandTableRowsRecursively(table) {
+ let currentLevelRows = table.tableRows;
+ let totalVisibleRowCount = currentLevelRows.length;
+
+ while (currentLevelRows.length > 0) {
+ // Calculate the total number of sub-rows on the current level.
+ let nextLevelRowCount = 0;
+ currentLevelRows.forEach(function(currentLevelRow) {
+ const subRows = currentLevelRow.subRows;
+ if (subRows === undefined || subRows.length === 0) return;
+ nextLevelRowCount += subRows.length;
+ });
+
+ // Determine whether expanding all rows on the current level would cause
+ // the total number of visible rows go over the limit.
+ if (totalVisibleRowCount + nextLevelRowCount >
+ RECURSIVE_EXPANSION_MAX_VISIBLE_ROW_COUNT) {
+ break;
+ }
+
+ // Expand all rows on the current level and gather their sub-rows.
+ const nextLevelRows = new Array(nextLevelRowCount);
+ let nextLevelRowIndex = 0;
+ currentLevelRows.forEach(function(currentLevelRow) {
+ const subRows = currentLevelRow.subRows;
+ if (subRows === undefined || subRows.length === 0) return;
+ table.setExpandedForTableRow(currentLevelRow, true);
+ subRows.forEach(function(subRow) {
+ nextLevelRows[nextLevelRowIndex++] = subRow;
+ });
+ });
+
+ // Update the total number of visible rows and progress to the next level.
+ totalVisibleRowCount += nextLevelRowCount;
+ currentLevelRows = nextLevelRows;
+ }
+ }
+
+ function aggregateTableRowCellsRecursively(row, columns, opt_predicate) {
+ const subRows = row.subRows;
+ if (subRows === undefined || subRows.length === 0) return;
+
+ subRows.forEach(function(subRow) {
+ aggregateTableRowCellsRecursively(subRow, columns, opt_predicate);
+ });
+
+ if (opt_predicate === undefined || opt_predicate(row.contexts)) {
+ aggregateTableRowCells(row, subRows, columns);
+ }
+ }
+
+ function aggregateTableRowCells(row, subRows, columns) {
+ columns.forEach(function(column) {
+ if (!(column instanceof MemoryColumn)) return;
+ column.aggregateCells(row, subRows);
+ });
+ }
+
+ function createCells(timeToValues, valueFieldsGetter, opt_this) {
+ opt_this = opt_this || this;
+ const fieldNameToFields = tr.b.invertArrayOfDicts(
+ timeToValues, valueFieldsGetter, opt_this);
+ const result = {};
+ for (const [fieldName, fields] of Object.entries(fieldNameToFields)) {
+ result[fieldName] = new tr.ui.analysis.MemoryCell(fields);
+ }
+ return result;
+ }
+
+ function createWarningInfo(message) {
+ return {
+ message,
+ icon: String.fromCharCode(9888),
+ color: 'red'
+ };
+ }
+
+ // TODO(petrcermak): Use a context manager instead
+ // (https://github.com/catapult-project/catapult/issues/2420).
+ function DetailsNumericMemoryColumn(name, cellPath, aggregationMode) {
+ NumericMemoryColumn.call(this, name, cellPath, aggregationMode);
+ }
+
+ DetailsNumericMemoryColumn.prototype = {
+ __proto__: NumericMemoryColumn.prototype,
+
+ getFormattingContext(unit) {
+ if (unit.baseUnit === tr.b.Unit.byName.sizeInBytes) {
+ return { unitPrefix: tr.b.UnitPrefixScale.BINARY.KIBI };
+ }
+ return undefined;
+ }
+ };
+
+ return {
+ TitleColumn,
+ MemoryColumn,
+ StringMemoryColumn,
+ NumericMemoryColumn,
+ MemoryCell,
+ expandTableRowsRecursively,
+ aggregateTableRowCellsRecursively,
+ aggregateTableRowCells,
+ createCells,
+ createWarningInfo,
+ DetailsNumericMemoryColumn,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util_test.html
new file mode 100644
index 00000000000..859f78433d6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_sub_view_util_test.html
@@ -0,0 +1,1241 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TitleColumn = tr.ui.analysis.TitleColumn;
+ const MemoryColumn = tr.ui.analysis.MemoryColumn;
+ const AggregationMode = MemoryColumn.AggregationMode;
+ const StringMemoryColumn = tr.ui.analysis.StringMemoryColumn;
+ const NumericMemoryColumn = tr.ui.analysis.NumericMemoryColumn;
+ const MemoryCell = tr.ui.analysis.MemoryCell;
+ const expandTableRowsRecursively = tr.ui.analysis.expandTableRowsRecursively;
+ const aggregateTableRowCells = tr.ui.analysis.aggregateTableRowCells;
+ const aggregateTableRowCellsRecursively =
+ tr.ui.analysis.aggregateTableRowCellsRecursively;
+ const Scalar = tr.b.Scalar;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+ const checkSizeNumericFields = tr.ui.analysis.checkSizeNumericFields;
+ const checkNumericFields = tr.ui.analysis.checkNumericFields;
+ const checkStringFields = tr.ui.analysis.checkStringFields;
+ const createCells = tr.ui.analysis.createCells;
+ const createWarningInfo = tr.ui.analysis.createWarningInfo;
+
+ function checkPercent(string, expectedPercent) {
+ assert.strictEqual(Number(string.slice(0, -1)), expectedPercent);
+ assert.strictEqual(string.slice(-1), '%');
+ }
+
+ function checkMemoryColumnFieldFormat(test, column, fields,
+ expectedTextContent, opt_expectedColor) {
+ const value = column.formatMultipleFields(fields);
+ if (expectedTextContent === undefined) {
+ assert.strictEqual(value, '');
+ assert.isUndefined(opt_expectedColor); // Test sanity check.
+ return;
+ }
+
+ const node = tr.ui.b.asHTMLOrTextNode(value);
+ const spanEl = document.createElement('span');
+ Polymer.dom(spanEl).appendChild(node);
+ test.addHTMLOutput(spanEl);
+
+ assert.strictEqual(Polymer.dom(node).textContent, expectedTextContent);
+ if (opt_expectedColor === undefined) {
+ assert.notInstanceOf(node, HTMLElement);
+ } else {
+ assert.strictEqual(node.style.color, opt_expectedColor);
+ }
+ }
+
+ function checkCompareFieldsEqual(column, fieldValuesA, fieldValuesB) {
+ assert.strictEqual(column.compareFields(fieldValuesA, fieldValuesB), 0);
+ }
+
+ function checkCompareFieldsLess(column, fieldValuesA, fieldValuesB) {
+ assert.isBelow(column.compareFields(fieldValuesA, fieldValuesB), 0);
+ assert.isAbove(column.compareFields(fieldValuesB, fieldValuesA), 0);
+ }
+
+ function checkNumericMemoryColumnFieldFormat(test, column, fieldValues, unit,
+ expectedValue) {
+ const value = column.formatMultipleFields(
+ buildScalarCell(unit, fieldValues).fields);
+ if (expectedValue === undefined) {
+ assert.strictEqual(value, '');
+ assert.isUndefined(expectedUnits); // Test sanity check.
+ return;
+ }
+
+ test.addHTMLOutput(value);
+ assert.strictEqual(value.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(value.value, expectedValue);
+ assert.strictEqual(value.unit, unit);
+ }
+
+ function buildScalarCell(unit, values) {
+ return new MemoryCell(values.map(function(value) {
+ if (value === undefined) return undefined;
+ return new Scalar(unit, value);
+ }));
+ }
+
+ function buildTestRows() {
+ return [
+ {
+ title: 'Row 1',
+ fields: {
+ 'cpu_temperature': new MemoryCell(['below zero', 'absolute zero'])
+ },
+ subRows: [
+ {
+ title: 'Row 1A',
+ fields: {
+ 'page_size': buildScalarCell(sizeInBytes_smallerIsBetter,
+ [1024, 1025])
+ }
+ },
+ {
+ title: 'Row 1B',
+ fields: {
+ 'page_size': buildScalarCell(sizeInBytes_smallerIsBetter,
+ [512, 513]),
+ 'mixed': new MemoryCell(['0.01', '0.10']),
+ 'mixed2': new MemoryCell([
+ new Scalar(tr.b.Unit.byName.powerInWatts, 2.43e18),
+ new Scalar(tr.b.Unit.byName.powerInWatts, 0.5433)
+ ])
+ }
+ }
+ ]
+ },
+ {
+ title: 'Row 2',
+ fields: {
+ 'cpu_temperature': undefined,
+ 'mixed': buildScalarCell(tr.b.Unit.byName.timeDurationInMs,
+ [0.99, 0.999])
+ }
+ }
+ ];
+ }
+
+ function checkCellValue(
+ test, value, expectedText, expectedColor, opt_expectedInfos) {
+ const expectedInfos = opt_expectedInfos || [];
+ assert.lengthOf(Polymer.dom(value).childNodes, 1 + expectedInfos.length);
+ assert.strictEqual(value.style.color, expectedColor);
+ if (typeof expectedText === 'string') {
+ assert.strictEqual(
+ Polymer.dom(Polymer.dom(value).childNodes[0]).textContent,
+ expectedText);
+ } else {
+ expectedText(Polymer.dom(value).childNodes[0]);
+ }
+ for (let i = 0; i < expectedInfos.length; i++) {
+ const expectedInfo = expectedInfos[i];
+ const infoEl = Polymer.dom(value).childNodes[i + 1];
+ assert.strictEqual(Polymer.dom(infoEl).textContent, expectedInfo.icon);
+ assert.strictEqual(infoEl.title, expectedInfo.message);
+ assert.strictEqual(infoEl.style.color, expectedInfo.color || '');
+ }
+ test.addHTMLOutput(value);
+ }
+
+ function sizeSpanMatcher(
+ expectedValue, opt_expectedIsDelta, opt_expectedContext) {
+ return function(element) {
+ assert.strictEqual(element.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(element.value, expectedValue);
+ assert.strictEqual(element.unit, opt_expectedIsDelta ?
+ tr.b.Unit.byName.sizeInBytesDelta_smallerIsBetter :
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter);
+ assert.deepEqual(element.context, opt_expectedContext);
+ };
+ }
+
+ test('checkTitleColumn_value', function() {
+ const column = new TitleColumn('column_title');
+ assert.strictEqual(column.title, 'column_title');
+ assert.isFalse(column.supportsCellSelection);
+
+ let row = {title: 'undefined', contexts: undefined};
+ assert.strictEqual(column.formatTitle(row), 'undefined');
+ assert.strictEqual(column.value(row), 'undefined');
+
+ row = {title: 'constant', contexts: [{}, {}, {}, {}]};
+ assert.strictEqual(column.formatTitle(row), 'constant');
+ assert.strictEqual(column.value(row), 'constant');
+
+ row = {title: 'added', contexts: [undefined, undefined, undefined, {}]};
+ assert.strictEqual(column.formatTitle(row), 'added');
+ let value = column.value(row);
+ assert.strictEqual(Polymer.dom(value).textContent, '+++\u00A0added');
+ assert.strictEqual(value.style.color, 'red');
+
+ row = {title: 'removed', contexts: [true, true, undefined, undefined]};
+ assert.strictEqual(column.formatTitle(row), 'removed');
+ value = column.value(row);
+ assert.strictEqual(Polymer.dom(value).textContent, '---\u00A0removed');
+ assert.strictEqual(value.style.color, 'green');
+
+ row = {title: 'flaky', contexts: [true, undefined, true, true]};
+ assert.strictEqual(column.formatTitle(row), 'flaky');
+ value = column.value(row);
+ assert.strictEqual(Polymer.dom(value).textContent, 'flaky');
+ assert.strictEqual(value.style.color, 'purple');
+
+ row = {title: 'added-flaky', contexts: [undefined, {}, undefined, true]};
+ assert.strictEqual(column.formatTitle(row), 'added-flaky');
+ value = column.value(row);
+ assert.strictEqual(Polymer.dom(value).textContent, '+++\u00A0added-flaky');
+ assert.strictEqual(value.style.color, 'purple');
+
+ row = {title: 'removed-flaky', contexts: [true, undefined, {}, undefined]};
+ assert.strictEqual(column.formatTitle(row), 'removed-flaky');
+ value = column.value(row);
+ assert.strictEqual(
+ Polymer.dom(value).textContent, '---\u00A0removed-flaky');
+ assert.strictEqual(value.style.color, 'purple');
+ });
+
+ test('checkTitleColumn_cmp', function() {
+ const column = new TitleColumn('column_title');
+
+ assert.isBelow(column.cmp({title: 'a'}, {title: 'b'}), 0);
+ assert.strictEqual(column.cmp({title: 'cc'}, {title: 'cc'}), 0);
+ assert.isAbove(column.cmp({title: '10'}, {title: '2'}), 0);
+ });
+
+ test('checkMemoryColumn_fromRows', function() {
+ function MockColumn0() {
+ MemoryColumn.apply(this, arguments);
+ }
+ MockColumn0.prototype = {
+ __proto__: MemoryColumn.prototype,
+ get title() { return 'MockColumn0'; }
+ };
+
+ function MockColumn1() {
+ MemoryColumn.apply(this, arguments);
+ }
+ MockColumn1.prototype = {
+ __proto__: MemoryColumn.prototype,
+ get title() { return 'MockColumn1'; }
+ };
+
+ function MockColumn2() {
+ MemoryColumn.apply(this, arguments);
+ }
+ MockColumn2.prototype = {
+ __proto__: MemoryColumn.prototype,
+ get title() { return 'MockColumn2'; }
+ };
+
+ const rules = [
+ {
+ condition: /size/,
+ importance: 10,
+ columnConstructor: MockColumn0
+ },
+ {
+ condition: 'cpu_temperature',
+ importance: 0,
+ columnConstructor: MockColumn1
+ },
+ {
+ condition: 'unmatched',
+ importance: -1,
+ get columnConstructor() {
+ throw new Error('The constructor should never be retrieved');
+ }
+ },
+ {
+ importance: 1,
+ columnConstructor: MockColumn2
+ }
+ ];
+
+ const rows = buildTestRows();
+ const columns = MemoryColumn.fromRows(rows, {
+ cellKey: 'fields',
+ aggregationMode: AggregationMode.MAX,
+ rules,
+ shouldSetContextGroup: true
+ });
+ assert.lengthOf(columns, 4);
+
+ const pageSizeColumn = columns[0];
+ assert.strictEqual(pageSizeColumn.name, 'page_size');
+ assert.strictEqual(pageSizeColumn.title, 'MockColumn0');
+ assert.strictEqual(pageSizeColumn.aggregationMode, AggregationMode.MAX);
+ assert.strictEqual(pageSizeColumn.cell({fields: {page_size: 'large'}}),
+ 'large');
+ assert.isTrue(pageSizeColumn.shouldSetContextGroup);
+ assert.instanceOf(pageSizeColumn, MockColumn0);
+
+ const mixedColumn = columns[1];
+ assert.strictEqual(mixedColumn.name, 'mixed');
+ assert.strictEqual(mixedColumn.title, 'MockColumn2');
+ assert.strictEqual(mixedColumn.aggregationMode, AggregationMode.MAX);
+ assert.strictEqual(mixedColumn.cell({fields: {mixed: 89}}), 89);
+ assert.isTrue(mixedColumn.shouldSetContextGroup);
+ assert.instanceOf(mixedColumn, MockColumn2);
+
+ const mixed2Column = columns[2];
+ assert.strictEqual(mixed2Column.name, 'mixed2');
+ assert.strictEqual(mixed2Column.title, 'MockColumn2');
+ assert.strictEqual(mixed2Column.aggregationMode, AggregationMode.MAX);
+ assert.strictEqual(mixed2Column.cell({fields: {mixed2: 'invalid'}}),
+ 'invalid');
+ assert.isTrue(mixed2Column.shouldSetContextGroup);
+ assert.instanceOf(mixed2Column, MockColumn2);
+
+ const cpuTemperatureColumn = columns[3];
+ assert.strictEqual(cpuTemperatureColumn.name, 'cpu_temperature');
+ assert.strictEqual(cpuTemperatureColumn.title, 'MockColumn1');
+ assert.strictEqual(cpuTemperatureColumn.aggregationMode,
+ AggregationMode.MAX);
+ assert.strictEqual(
+ cpuTemperatureColumn.cell({fields: {cpu_temperature: 42}}), 42);
+ assert.isTrue(cpuTemperatureColumn.shouldSetContextGroup);
+ assert.instanceOf(cpuTemperatureColumn, MockColumn1);
+ });
+
+ test('checkMemoryColumn_spaceEqually', function() {
+ // Zero columns.
+ let columns = [];
+ MemoryColumn.spaceEqually(columns);
+
+ // One column.
+ columns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; }
+ }
+ ];
+ MemoryColumn.spaceEqually(columns);
+ checkPercent(columns[0].width, 100);
+
+ // Two columns.
+ columns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; }
+ },
+ {
+ title: 'Second Column',
+ value(row) { return row.firstData; }
+ }
+ ];
+ MemoryColumn.spaceEqually(columns);
+ checkPercent(columns[0].width, 50);
+ checkPercent(columns[1].width, 50);
+ });
+
+ test('checkMemoryColumn_instantiate', function() {
+ const c = new MemoryColumn('test_column', ['x'], AggregationMode.MAX);
+ assert.strictEqual(c.name, 'test_column');
+ assert.strictEqual(c.title, 'test_column');
+ assert.strictEqual(c.cell({x: 95}), 95);
+ assert.isUndefined(c.width);
+ assert.isUndefined(c.color());
+ });
+
+ test('checkMemoryColumn_cell', function() {
+ const c = new MemoryColumn('test_column', ['a', 'b'], AggregationMode.MAX);
+ const cell = new MemoryCell(undefined);
+
+ assert.isUndefined(c.cell(undefined));
+ assert.isUndefined(c.cell({b: cell}));
+ assert.isUndefined(c.cell({a: {c: cell}}));
+ assert.strictEqual(c.cell({a: {b: cell, c: 42}}), cell);
+ });
+
+ test('checkMemoryColumn_fields', function() {
+ const c = new MemoryColumn('test_column', ['x'],
+ AggregationMode.MAX);
+
+ // Undefined cell or field inside cell.
+ assert.isUndefined(c.fields({}));
+ assert.isUndefined(c.fields({x: new MemoryCell(undefined)}));
+
+ // Defined field(s) inside cell.
+ const field1 = new Scalar(tr.b.Unit.byName.powerInWatts, 1013.25);
+ const field2 = new Scalar(tr.b.Unit.byName.powerInWatts, 1065);
+ const row1 = {x: new MemoryCell([field1])};
+ const row2 = {x: new MemoryCell([field1, field2])};
+ assert.deepEqual(c.fields(row1), [field1]);
+ assert.deepEqual(c.fields(row2), [field1, field2]);
+ });
+
+ test('checkMemoryColumn_hasAllRelevantFieldsUndefined', function() {
+ // Single field.
+ const c1 = new MemoryColumn('single_column', ['x'],
+ undefined /* aggregation mode */);
+ assert.isTrue(c1.hasAllRelevantFieldsUndefined([undefined]));
+ assert.isFalse(c1.hasAllRelevantFieldsUndefined(
+ [new Scalar(sizeInBytes_smallerIsBetter, 16)]));
+
+ // Multiple fields, diff aggregation mode.
+ const c2 = new MemoryColumn('diff_column', ['x'],
+ AggregationMode.DIFF);
+ assert.isTrue(c2.hasAllRelevantFieldsUndefined([undefined, undefined]));
+ assert.isTrue(c2.hasAllRelevantFieldsUndefined(
+ [undefined, undefined, undefined]));
+ assert.isTrue(c2.hasAllRelevantFieldsUndefined(
+ [undefined, new Scalar(sizeInBytes_smallerIsBetter, 16), undefined]));
+ assert.isFalse(c2.hasAllRelevantFieldsUndefined(
+ [undefined, new Scalar(sizeInBytes_smallerIsBetter, 32)]));
+ assert.isFalse(c2.hasAllRelevantFieldsUndefined(
+ [new Scalar(sizeInBytes_smallerIsBetter, 32), undefined, undefined]));
+ assert.isFalse(c2.hasAllRelevantFieldsUndefined([
+ new Scalar(sizeInBytes_smallerIsBetter, 16),
+ undefined,
+ new Scalar(sizeInBytes_smallerIsBetter, 32)
+ ]));
+
+ // Multiple fields, max aggregation mode.
+ const c3 = new MemoryColumn('max_column', ['x'],
+ AggregationMode.MAX);
+ assert.isTrue(c3.hasAllRelevantFieldsUndefined([undefined, undefined]));
+ assert.isTrue(c3.hasAllRelevantFieldsUndefined(
+ [undefined, undefined, undefined]));
+ assert.isFalse(c3.hasAllRelevantFieldsUndefined(
+ [undefined, new Scalar(sizeInBytes_smallerIsBetter, 16), undefined]));
+ assert.isFalse(c3.hasAllRelevantFieldsUndefined(
+ [undefined, new Scalar(sizeInBytes_smallerIsBetter, 32)]));
+ assert.isFalse(c3.hasAllRelevantFieldsUndefined([
+ new Scalar(sizeInBytes_smallerIsBetter, 32),
+ undefined,
+ new Scalar(sizeInBytes_smallerIsBetter, 16)
+ ]));
+ });
+
+ test('checkMemoryColumn_value_allFieldsUndefined', function() {
+ const c1 = new MemoryColumn('no_color', ['x'],
+ AggregationMode.MAX);
+ const c2 = new MemoryColumn('color', ['x'],
+ AggregationMode.DIFF);
+ Object.defineProperty(c2, 'color', {
+ get() {
+ throw new Error('The color should never be retrieved');
+ }
+ });
+
+ // Infos should be completely ignored.
+ c1.addInfos = c2.addInfos = function() {
+ throw new Error('This method should never be called');
+ };
+
+ [c1, c2].forEach(function(c) {
+ assert.strictEqual(c.value({}), '');
+ assert.strictEqual(c.value({x: new MemoryCell(undefined)}), '');
+ assert.strictEqual(c.value({x: new MemoryCell([undefined])}), '');
+ assert.strictEqual(
+ c.value({x: new MemoryCell([undefined, undefined])}), '');
+ });
+
+ // Diff should only take into account the first and last field value.
+ assert.strictEqual(c2.value({
+ x: new MemoryCell([
+ undefined,
+ new Scalar(sizeInBytes_smallerIsBetter, 16),
+ undefined
+ ])
+ }), '');
+ });
+
+ test('checkMemoryColumn_getImportance', function() {
+ const c = new NumericMemoryColumn('test_column', ['x']);
+
+ const rules1 = [];
+ assert.strictEqual(c.getImportance(rules1), 0);
+
+ const rules2 = [
+ {
+ condition: 'test',
+ importance: 4
+ },
+ {
+ condition: /test$/,
+ importance: 2
+ }
+ ];
+ assert.strictEqual(c.getImportance(rules2), 1);
+
+ const rules3 = [
+ {
+ condition: 'test_column',
+ importance: 10
+ },
+ {
+ importance: 5
+ }
+ ];
+ assert.strictEqual(c.getImportance(rules3), 10);
+
+ const rules4 = [
+ {
+ condition: 'test_column2',
+ importance: 8
+ },
+ {
+ condition: /column/,
+ importance: 12
+ }
+ ];
+ assert.strictEqual(c.getImportance(rules4), 12);
+ });
+
+ test('checkMemoryColumn_nameMatchesCondition', function() {
+ const c = new NumericMemoryColumn('test_column', ['x']);
+
+ assert.isTrue(MemoryColumn.nameMatchesCondition('test_column', undefined));
+
+ assert.isFalse(MemoryColumn.nameMatchesCondition('test_column', 'test'));
+ assert.isTrue(
+ MemoryColumn.nameMatchesCondition('test_column', 'test_column'));
+ assert.isFalse(
+ MemoryColumn.nameMatchesCondition('test_column', 'test_column2'));
+
+ assert.isTrue(MemoryColumn.nameMatchesCondition('test_column', /test/));
+ assert.isTrue(
+ MemoryColumn.nameMatchesCondition('test_column', /^[^_]*_[^_]*$/));
+ assert.isFalse(MemoryColumn.nameMatchesCondition('test_column', /test$/));
+ });
+
+ test('checkStringMemoryColumn_value_singleField', function() {
+ const c = new StringMemoryColumn('', ['x'], AggregationMode.MAX);
+ c.color = function(fields, contexts) {
+ if (fields[0] < '0') return 'green';
+ if (contexts && contexts[0] % 2 === 0) return 'red';
+ return undefined;
+ };
+
+ const infos1 = [{ icon: '\u{1F648}', message: 'Some info', color: 'blue' }];
+ const infos2 = [
+ { icon: '\u{1F649}', message: 'Start', color: 'cyan' },
+ { icon: '\u{1F64A}', message: 'Stop' }
+ ];
+ c.addInfos = function(fields, contexts, infos) {
+ if (fields[0] < '0') {
+ infos.push.apply(infos, infos1);
+ } else if (contexts && contexts[0] % 2 === 0) {
+ infos.push.apply(infos, infos2);
+ }
+ };
+
+ let row = {x: new MemoryCell(['123'])};
+ assert.strictEqual(c.value(row), '123');
+
+ row = {x: new MemoryCell(['-123']), contexts: [undefined]};
+ checkCellValue(this, c.value(row), '-123', 'green', infos1);
+
+ row = {x: new MemoryCell(['123']), contexts: [42]};
+ checkCellValue(this, c.value(row), '123', 'red', infos2);
+ });
+
+ test('checkStringMemoryColumn_value_multipleFields', function() {
+ const c1 = new StringMemoryColumn('test_column1', ['x'],
+ undefined /* aggregation mode */);
+ const c2 = new StringMemoryColumn('test_column2', ['x'],
+ AggregationMode.DIFF);
+ c2.color = function(fields, contexts) {
+ return '#009999';
+ };
+ const c3 = new StringMemoryColumn('test_column3', ['x'],
+ AggregationMode.MAX);
+ c3.color = function(fields, contexts) {
+ if (fields[0] < '0') {
+ return 'green';
+ } else if (contexts && contexts[contexts.length - 1] % 2 === 0) {
+ return 'red';
+ }
+ return undefined;
+ };
+
+ const infos1 = [{ icon: '\u{1F648}', message: 'Some info', color: 'blue' }];
+ const infos2 = [
+ { icon: '\u{1F649}', message: 'Start', color: 'cyan' },
+ { icon: '\u{1F64A}', message: 'Stop' }
+ ];
+ c1.addInfos = c2.addInfos = c3.addInfos =
+ function(fields, contexts, infos) {
+ if (fields[0] < '0') {
+ infos.push.apply(infos, infos1);
+ } else if (contexts && contexts[contexts.length - 1] % 2 === 0) {
+ infos.push.apply(infos, infos2);
+ }
+ };
+
+ let row = {x: new MemoryCell(['123', '456'])};
+ checkCellValue(this, c1.value(row), '(unsupported aggregation mode)', '');
+ checkCellValue(this, c2.value(row), '123 \u2192 456', 'rgb(0, 153, 153)');
+ assert.strictEqual(c3.value(row), '456');
+
+ row = {
+ x: new MemoryCell(['-123', undefined, '+123']),
+ contexts: [12, 14, undefined]
+ };
+ checkCellValue(this, c1.value(row), '(unsupported aggregation mode)', '',
+ infos1);
+ checkCellValue(this, c2.value(row), '-123 \u2192 +123', 'rgb(0, 153, 153)',
+ infos1);
+ checkCellValue(this, c3.value(row), '+123', 'green', infos1);
+
+ row = {
+ x: new MemoryCell(['123', undefined, '456']),
+ contexts: [31, 7, -2]
+ };
+ checkCellValue(this, c1.value(row), '(unsupported aggregation mode)', '',
+ infos2);
+ checkCellValue(this, c2.value(row), '123 \u2192 456', 'rgb(0, 153, 153)',
+ infos2);
+ checkCellValue(this, c3.value(row), '456', 'red', infos2);
+ });
+
+ test('checkStringMemoryColumn_formatSingleField', function() {
+ const c = new StringMemoryColumn('test_column', ['x'],
+ undefined /* aggregation mode */);
+
+ assert.strictEqual(c.formatSingleField('1024'), '1024');
+ assert.strictEqual(c.formatSingleField('~10'), '~10');
+ });
+
+ test('checkStringMemoryColumn_formatMultipleFields_diff', function() {
+ const c = new StringMemoryColumn('test_column', ['x'],
+ AggregationMode.DIFF);
+
+ // Added value.
+ checkMemoryColumnFieldFormat(this, c, [undefined, 'few'], '+few', 'red');
+ checkMemoryColumnFieldFormat(this, c, [undefined, 64, 32], '+32', 'red');
+
+ // Removed value.
+ checkMemoryColumnFieldFormat(this, c, ['00', undefined], '-00', 'green');
+ checkMemoryColumnFieldFormat(this, c, [1, undefined, 2, undefined], '-1',
+ 'green');
+
+ // Identical values.
+ checkMemoryColumnFieldFormat(this, c, ['Unchanged', 'Unchanged'],
+ 'Unchanged', undefined /* unchanged color (not an HTML element) */);
+ checkMemoryColumnFieldFormat(this, c, [16, 32, undefined, 64, 16], '16',
+ undefined /* unchanged color (not an HTML element) */);
+
+ // Different values.
+ checkMemoryColumnFieldFormat(this, c, ['A', 'C', undefined, 'C', 'B'],
+ 'A \u2192 B', 'darkorange');
+ checkMemoryColumnFieldFormat(this, c, [16, undefined, 64], '16 \u2192 64',
+ 'darkorange');
+ });
+
+ test('checkStringMemoryColumn_formatMultipleFields_max', function() {
+ const c = new StringMemoryColumn('test_column', ['x'],
+ AggregationMode.MAX);
+
+ // Different values.
+ checkMemoryColumnFieldFormat(this, c, ['A', 'B', 'A'], 'B',
+ undefined /* unchanged color (not an HTML element) */);
+ checkMemoryColumnFieldFormat(this, c, [16, 16, undefined, 17], '17',
+ undefined /* unchanged color (not an HTML element) */);
+
+ // Identical values.
+ checkMemoryColumnFieldFormat(this, c, ['X', 'X'], 'X',
+ undefined /* unchanged color (not an HTML element) */);
+ checkMemoryColumnFieldFormat(this, c, [7, undefined, 7, undefined, 7], '7',
+ undefined /* unchanged color (not an HTML element) */);
+ });
+
+ test('checkStringMemoryColumn_compareSingleFields', function() {
+ const c = new StringMemoryColumn('test_column', ['x'],
+ undefined /* aggregation mode */);
+
+ assert.isBelow(c.compareSingleFields(
+ new Scalar(sizeInBytes_smallerIsBetter, 2),
+ new Scalar(sizeInBytes_smallerIsBetter, 10)), 0);
+ assert.strictEqual(c.compareSingleFields('equal', 'equal'), 0);
+ assert.isAbove(c.compareSingleFields('100', '99'), 0);
+ });
+
+ test('checkStringMemoryColumn_compareMultipleFields_diff', function() {
+ const c = new StringMemoryColumn('test_column', ['x'],
+ AggregationMode.DIFF);
+
+ // One field was added.
+ checkCompareFieldsLess(c, [-10, 10], [undefined, 5]);
+ checkCompareFieldsLess(c,
+ [-100, undefined, undefined], [undefined, 4, 5]);
+ checkCompareFieldsLess(c,
+ [1, 2, 3, 4], [undefined, 'x', undefined, 'y']);
+
+ // Both fields were added.
+ checkCompareFieldsEqual(c,
+ [undefined, 'C', undefined, 'A'], [undefined, 'B', 'D', 'A']);
+ checkCompareFieldsLess(c, [undefined, 1], [undefined, 2]);
+ checkCompareFieldsLess(c, [undefined, 6, 3], [undefined, 5, 4]);
+
+ // One field was removed (neither was added).
+ checkCompareFieldsLess(c, ['B', undefined], ['A', 'A']);
+ checkCompareFieldsLess(c,
+ [5, undefined, undefined], [undefined, -5, -10]);
+
+ // Both fields were removed (neither was added)
+ checkCompareFieldsEqual(c, ['T', 'A', undefined, undefined],
+ ['T', 'B', 'C', undefined]);
+ checkCompareFieldsLess(c, [5, undefined], [4, undefined]);
+
+ // Neither field was added or removed.
+ checkCompareFieldsLess(c, ['BB', 'BB'], ['AA', 'CC']);
+ checkCompareFieldsEqual(c, [7, 8, 9], [6, 9, 10]);
+ checkCompareFieldsEqual(c, [5, undefined, 5], [4, 3, 4]);
+ });
+
+ test('checkStringMemoryColumn_compareMultipleFields_max', function() {
+ const c = new StringMemoryColumn('test_column', ['x'],
+ AggregationMode.MAX);
+
+ // At least one field has multiple values.
+ checkCompareFieldsEqual(c, [0, 1, 3], [1, 3, 2]);
+ checkCompareFieldsLess(c, ['4', undefined, '4'], ['3', '4', '5']);
+ checkCompareFieldsLess(c, [3, 3, 3], [9, undefined, 10]);
+
+ // Both fields have single values.
+ checkCompareFieldsEqual(c,
+ [undefined, 'ttt', undefined], ['ttt', 'ttt', undefined]);
+ checkCompareFieldsLess(c, [undefined, -1, undefined], [-2, -2, -2]);
+ checkCompareFieldsLess(c, ['Q', 'Q', undefined], ['X', undefined, 'X']);
+ });
+
+ test('checkStringMemoryColumn_cmp', function() {
+ const c = new StringMemoryColumn('test_column', ['x'],
+ AggregationMode.DIFF);
+
+ // Cell (or the associated field) undefined in one or both rows.
+ assert.strictEqual(c.cmp({}, {y: new MemoryCell([undefined])}), 0);
+ assert.strictEqual(c.cmp({x: new MemoryCell(undefined)}, {}), 0);
+ assert.strictEqual(
+ c.cmp({x: new MemoryCell([undefined, undefined])}, {}), 0);
+ assert.isAbove(c.cmp({x: new MemoryCell(['negative'])}, {}), 0);
+ assert.isAbove(c.cmp({x: new MemoryCell(['negative'])},
+ {x: new MemoryCell([undefined])}), 0);
+ assert.isBelow(c.cmp({}, {x: new MemoryCell(['positive'])}), 0);
+ assert.isBelow(c.cmp({x: new MemoryCell(undefined)},
+ {x: new MemoryCell(['positive'])}), 0);
+
+ // Single field.
+ assert.strictEqual(c.cmp({x: new MemoryCell(['equal'])},
+ {x: new MemoryCell(['equal'])}), 0);
+ assert.isAbove(c.cmp({x: new MemoryCell(['bigger'])},
+ {x: new MemoryCell(['BIG'])}), 0);
+ assert.isBelow(c.cmp({x: new MemoryCell(['small'])},
+ {x: new MemoryCell(['smaLL'])}), 0);
+
+ // Multiple fields.
+ assert.isBelow(c.cmp(
+ {x: new MemoryCell(['MemoryColumn', 'supports*', undefined])},
+ {x: new MemoryCell(['comparing', 'multiple', 'values :-)'])}), 0);
+ });
+
+ test('checkNumericMemoryColumn_value', function() {
+ const c = new NumericMemoryColumn('test_column', ['x'],
+ AggregationMode.DIFF);
+ c.color = function(fields, contexts) {
+ return '#009999';
+ };
+ const infos1 = [createWarningInfo('Attention!')];
+ c.addInfos = function(fields, contexts, infos) {
+ infos.push.apply(infos, infos1);
+ };
+
+ // Undefined field values.
+ let row = {x: buildScalarCell(sizeInBytes_smallerIsBetter,
+ [undefined, 1, undefined])};
+ assert.strictEqual(c.value(row), '');
+
+ // Single field value.
+ row = {x: buildScalarCell(sizeInBytes_smallerIsBetter,
+ [5.4975581e13/* 50 TiB */])};
+ checkCellValue(this, c.value(row), sizeSpanMatcher(5.4975581e13),
+ 'rgb(0, 153, 153)', infos1);
+
+ // Multiple field values.
+ row = {
+ x: buildScalarCell(sizeInBytes_smallerIsBetter,
+ [5.4975581e13/* 50 TiB */, undefined, 2.1990233e13/* 20 TiB */])
+ };
+ checkCellValue(this, c.value(row),
+ sizeSpanMatcher(-3.2985348e13, true /* opt_expectedIsDelta */),
+ 'rgb(0, 153, 153)', infos1);
+
+ // With custom formatting context.
+ c.getFormattingContext = function(unit) {
+ assert.strictEqual(unit,
+ tr.b.Unit.byName.sizeInBytesDelta_smallerIsBetter);
+ return { minimumFractionDigits: 2 };
+ };
+ checkCellValue(this, c.value(row),
+ sizeSpanMatcher(-3.2985348e13, true /* opt_expectedIsDelta */,
+ { minimumFractionDigits: 2 }),
+ 'rgb(0, 153, 153)', infos1);
+ });
+
+ test('checkNumericMemoryColumn_formatSingleField', function() {
+ let c = new NumericMemoryColumn('non_bytes_column', ['x'],
+ undefined /* aggregation mode */);
+ let value = c.formatSingleField(new Scalar(
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter, 123));
+ assert.strictEqual(value.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(value.value, 123);
+ assert.strictEqual(value.unit,
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter);
+ assert.isUndefined(value.contextGroup);
+ this.addHTMLOutput(value);
+
+ c = new NumericMemoryColumn('bytes_column', ['x'],
+ undefined /* aggregation mode */);
+ c.shouldSetContextGroup = true;
+ value = c.formatSingleField(new Scalar(
+ sizeInBytes_smallerIsBetter, 456));
+ assert.strictEqual(value.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(value.value, 456);
+ assert.strictEqual(value.unit,
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter);
+ assert.strictEqual(value.contextGroup, 'bytes_column');
+ this.addHTMLOutput(value);
+ });
+
+ test('checkNumericMemoryColumn_formatMultipleFields_diff',
+ function() {
+ let c = new NumericMemoryColumn(
+ 'non_bytes_column', ['x'], AggregationMode.DIFF);
+ checkNumericMemoryColumnFieldFormat(this, c, [1, 2, 3],
+ tr.b.Unit.byName.unitlessNumberDelta_smallerIsBetter, 2);
+ checkNumericMemoryColumnFieldFormat(this, c, [10, undefined],
+ tr.b.Unit.byName.unitlessNumberDelta_smallerIsBetter, -10);
+ checkNumericMemoryColumnFieldFormat(this, c, [undefined, 60, 0],
+ tr.b.Unit.byName.unitlessNumberDelta_smallerIsBetter, 0);
+ checkNumericMemoryColumnFieldFormat(
+ this, c, [2.71828, 2.71829] /* diff within epsilon */,
+ tr.b.Unit.byName.unitlessNumberDelta_smallerIsBetter, 0);
+
+ c = new NumericMemoryColumn(
+ 'bytes_column', ['x'], AggregationMode.DIFF);
+ checkNumericMemoryColumnFieldFormat(this, c, [1, 2, 3],
+ tr.b.Unit.byName.sizeInBytesDelta_smallerIsBetter, 2);
+ checkNumericMemoryColumnFieldFormat(this, c, [10, undefined],
+ tr.b.Unit.byName.sizeInBytesDelta_smallerIsBetter, -10);
+ checkNumericMemoryColumnFieldFormat(this, c, [undefined, 60, 0],
+ tr.b.Unit.byName.sizeInBytesDelta_smallerIsBetter, 0);
+ checkNumericMemoryColumnFieldFormat(
+ this, c, [1.41421, 1.41422] /* diff within epsilon */,
+ tr.b.Unit.byName.sizeInBytesDelta_smallerIsBetter, 0);
+ });
+
+ test('checkNumericMemoryColumn_formatMultipleFields_max',
+ function() {
+ let c = new NumericMemoryColumn(
+ 'non_bytes_column', ['x'], AggregationMode.MAX);
+ checkNumericMemoryColumnFieldFormat(this, c, [1, 2, 3],
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter, 3);
+ checkNumericMemoryColumnFieldFormat(this, c, [10, undefined],
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter, 10);
+ checkNumericMemoryColumnFieldFormat(this, c, [undefined, 60, 0],
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter, 60);
+ checkNumericMemoryColumnFieldFormat(
+ this, c, [undefined, 10, 20, undefined],
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter, 20);
+
+ c = new NumericMemoryColumn(
+ 'bytes_column', ['x'], AggregationMode.MAX);
+ checkNumericMemoryColumnFieldFormat(this, c, [1, 2, 3],
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, 3);
+ checkNumericMemoryColumnFieldFormat(this, c, [10, undefined],
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, 10);
+ checkNumericMemoryColumnFieldFormat(this, c, [undefined, 60, 0],
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, 60);
+ checkNumericMemoryColumnFieldFormat(
+ this, c, [undefined, 10, 20, undefined],
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter, 20);
+ });
+
+ test('checkNumericMemoryColumn_cmp', function() {
+ const c = new NumericMemoryColumn(
+ 'test_column', ['x'], AggregationMode.DIFF);
+
+ // Undefined field values.
+ assert.isAbove(c.cmp({x: buildScalarCell(sizeInBytes_smallerIsBetter,
+ [-9999999999])},
+ {x: undefined}), 0);
+ assert.isBelow(c.cmp({x: new MemoryCell(undefined)},
+ {x: buildScalarCell(sizeInBytes_smallerIsBetter, [748, 749])}), 0);
+ assert.strictEqual(
+ c.cmp({}, {
+ x: buildScalarCell(
+ sizeInBytes_smallerIsBetter, [undefined, undefined])
+ }), 0);
+
+ // Single field value.
+ assert.isBelow(c.cmp(
+ {x: buildScalarCell(sizeInBytes_smallerIsBetter, [16384])},
+ {x: buildScalarCell(sizeInBytes_smallerIsBetter, [32768])}), 0);
+
+ // Multiple field values.
+ assert.strictEqual(c.cmp(
+ {x: buildScalarCell(
+ sizeInBytes_smallerIsBetter, [999, undefined, 1001])},
+ {x: buildScalarCell(
+ sizeInBytes_smallerIsBetter, [undefined, 5, 2])}), 0);
+ });
+
+ test('checkNumericMemoryColumn_compareSingleFields', function() {
+ const c = new NumericMemoryColumn('test_column', ['x'],
+ undefined /* aggregation mode */);
+
+ assert.isBelow(c.compareSingleFields(
+ new Scalar(
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, 99),
+ new Scalar(
+ tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, 100)), 0);
+ assert.strictEqual(c.compareSingleFields(
+ new Scalar(tr.b.Unit.byName.unitlessNumber, 0xEEE),
+ new Scalar(tr.b.Unit.byName.unitlessNumber, 0xEEE)), 0);
+ assert.isAbove(c.compareSingleFields(
+ new Scalar(sizeInBytes_smallerIsBetter, 10),
+ new Scalar(sizeInBytes_smallerIsBetter, 2)), 0);
+ });
+
+ test('checkNumericMemoryColumn_compareMultipleFields_diff', function() {
+ const c = new NumericMemoryColumn('test_column', ['x'],
+ AggregationMode.DIFF);
+
+ assert.isBelow(c.compareMultipleFields(
+ buildScalarCell(sizeInBytes_smallerIsBetter,
+ [10000, 10001, 10002] /* diff +2 */).fields,
+ buildScalarCell(sizeInBytes_smallerIsBetter,
+ [5, 7, 8] /* diff +3 */).fields), 0);
+ assert.strictEqual(c.compareMultipleFields(
+ buildScalarCell(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [4, undefined] /* diff -4 */).fields,
+ buildScalarCell(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [999, 995] /* diff -4 */).fields), 0);
+ assert.isAbove(c.compareMultipleFields(
+ buildScalarCell(sizeInBytes_smallerIsBetter,
+ [10, undefined, 12] /* diff +2 */).fields,
+ buildScalarCell(sizeInBytes_smallerIsBetter,
+ [11, 50, 12] /* diff +1 */).fields), 0);
+ assert.strictEqual(c.compareMultipleFields(
+ buildScalarCell(tr.b.Unit.byName.powerInWatts_smallerIsBetter,
+ [17, undefined, 17] /* diff 0 */).fields,
+ buildScalarCell(tr.b.Unit.byName.powerInWatts_smallerIsBetter,
+ [undefined, 100, undefined] /* diff 0 */).fields), 0);
+ assert.strictEqual(c.compareMultipleFields(
+ buildScalarCell(sizeInBytes_smallerIsBetter,
+ [3.14159, undefined, 3.14160] /* diff within epsilon */).fields,
+ buildScalarCell(sizeInBytes_smallerIsBetter,
+ [100, 100, 100] /* diff 0 */).fields), 0);
+ });
+
+ test('checkNumericMemoryColumn_compareMultipleFields_max', function() {
+ const c = new NumericMemoryColumn('test_column', ['x'],
+ AggregationMode.MAX);
+
+ assert.isBelow(c.compareMultipleFields(
+ buildScalarCell(sizeInBytes_smallerIsBetter,
+ [10, undefined, 12]).fields,
+ buildScalarCell(sizeInBytes_smallerIsBetter, [11, 50, 12]).fields), 0);
+ assert.strictEqual(c.compareMultipleFields(
+ buildScalarCell(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [999, undefined, -8888]).fields,
+ buildScalarCell(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ [undefined, 999, undefined]).fields), 0);
+ assert.isAbove(c.compareMultipleFields(
+ buildScalarCell(sizeInBytes_smallerIsBetter,
+ [10000, 10001, 10002]).fields,
+ buildScalarCell(sizeInBytes_smallerIsBetter, [5, 7, 8]).fields), 0);
+ assert.isBelow(c.compareMultipleFields(
+ buildScalarCell(tr.b.Unit.byName.powerInWatts_smallerIsBetter,
+ [17, undefined, 17]).fields,
+ buildScalarCell(tr.b.Unit.byName.powerInWatts_smallerIsBetter,
+ [undefined, 100, undefined]).fields), 0);
+ });
+
+ test('checkNumericMemoryColumn_getDiffFieldValue', function() {
+ const c = new NumericMemoryColumn('test_column', ['x'],
+ AggregationMode.MAX);
+ function checkDiffValue(first, last, expectedDiffValue) {
+ const actualDiffValue = c.getDiffFieldValue_(
+ first === undefined ? undefined :
+ new Scalar(sizeInBytes_smallerIsBetter, first),
+ last === undefined ? undefined :
+ new Scalar(sizeInBytes_smallerIsBetter, last));
+ assert.closeTo(actualDiffValue, expectedDiffValue, 1e-8);
+ }
+
+ // Diff outside epsilon range.
+ checkDiffValue(0, 0.0002, 0.0002);
+ checkDiffValue(undefined, 0.0003, 0.0003);
+ checkDiffValue(0.3334, 0.3332, -0.0002);
+ checkDiffValue(0.0005, undefined, -0.0005);
+
+ // Diff inside epsilon range.
+ checkDiffValue(5, 5.00009, 0);
+ checkDiffValue(undefined, 0.0000888, 0);
+ checkDiffValue(0.29999, 0.3, 0);
+ checkDiffValue(0.00009, undefined, 0);
+ checkDiffValue(0.777777, 0.777777, 0);
+ checkDiffValue(undefined, undefined, 0);
+ });
+
+ test('checkExpandTableRowsRecursively', function() {
+ const columns = [
+ {
+ title: 'Single column',
+ value(row) { return row.data; },
+ width: '100px'
+ }
+ ];
+
+ const rows = [
+ {
+ data: 'allocated',
+ subRows: [
+ {
+ data: 'v8',
+ subRows: []
+ },
+ {
+ data: 'oilpan',
+ subRows: [
+ {
+ data: 'still_visible',
+ subRows: [
+ {
+ data: 'not_visible_any_more'
+ }
+ ]
+ },
+ {
+ data: 'also_visible'
+ }
+ ]
+ }
+ ]
+ },
+ {
+ data: 'no_sub_rows'
+ },
+ {
+ data: 'fragmentation',
+ subRows: [
+ {
+ data: 'internal'
+ },
+ {
+ data: 'external',
+ subRows: [
+ {
+ data: 'unexpanded'
+ }
+ ]
+ }
+ ]
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ expandTableRowsRecursively(table);
+
+ function isExpanded(row) { return table.getExpandedForTableRow(row); }
+
+ // Level 0 (3 rows) should be expanded (except for nodes which have no
+ // sub-rows).
+ assert.isTrue(isExpanded(rows[0] /* allocated */));
+ assert.isFalse(isExpanded(rows[1] /* no_sub_rows */));
+ assert.isTrue(isExpanded(rows[2] /* overhead */));
+
+ // Level 1 (4 rows) should be expanded (except for nodes which have no
+ // sub-rows).
+ assert.isFalse(isExpanded(rows[0].subRows[0] /* allocated/v8 */));
+ assert.isTrue(isExpanded(rows[0].subRows[1] /* allocated/oilpan */));
+ assert.isFalse(isExpanded(rows[2].subRows[0] /* fragmentation/internal */));
+ assert.isTrue(isExpanded(rows[2].subRows[1] /* fragmentation/external */));
+
+ // Level 2 (3 rows) should not be expanded any more.
+ assert.isFalse(isExpanded(
+ rows[0].subRows[1].subRows[0] /* allocated/oilpan/still_visible */));
+ assert.isFalse(isExpanded(
+ rows[0].subRows[1].subRows[1] /* allocated/oilpan/also_visible */));
+ assert.isFalse(isExpanded(
+ rows[2].subRows[1].subRows[0] /* fragmentation/external/unexpanded */));
+ });
+
+ test('checkMemoryCell_extractFields', function() {
+ assert.isUndefined(MemoryCell.extractFields(undefined));
+
+ assert.isUndefined(MemoryCell.extractFields(new MemoryCell(undefined)));
+
+ const fields = [new Scalar(sizeInBytes_smallerIsBetter, 1024)];
+ assert.strictEqual(
+ MemoryCell.extractFields(new MemoryCell(fields)), fields);
+ });
+
+ test('checkAggregateTableRowCellsRecursively', function() {
+ const row = {
+ testCells: {
+ a: buildScalarCell(sizeInBytes_smallerIsBetter, [17])
+ },
+ subRows: [
+ {
+ // Intentionally no testCells.
+ subRows: [
+ {
+ testCells: {
+ b: buildScalarCell(sizeInBytes_smallerIsBetter, [103]),
+ c: new MemoryCell(['should-not-propagate-upwards']),
+ d: buildScalarCell(sizeInBytes_smallerIsBetter, [-200])
+ }
+ // Intentionally no subRows.
+ },
+ {
+ testCells: {},
+ subRows: []
+ }
+ ],
+ contexts: ['skip-row-when-using-predicate']
+ },
+ {
+ testCells: {
+ b: buildScalarCell(sizeInBytes_smallerIsBetter, [20]),
+ a: buildScalarCell(sizeInBytes_smallerIsBetter, [13]),
+ e: buildScalarCell(sizeInBytes_smallerIsBetter, [-300])
+ },
+ contexts: ['don\'t-skip']
+ }
+ ]
+ };
+
+ // Without a predicate.
+ const ca = new NumericMemoryColumn('column_a', ['testCells', 'a']);
+ const cb = new NumericMemoryColumn('column_b', ['testCells', 'b']);
+ const cc = new StringMemoryColumn('column_c', ['testCells', 'c']);
+ aggregateTableRowCellsRecursively(row, [ca, cb, cc]);
+ checkSizeNumericFields(row, ca, [17]);
+ checkSizeNumericFields(row, cb, [123]);
+ checkStringFields(row, cc, undefined);
+
+ // With a predicate.
+ const cd = new NumericMemoryColumn('column_d', ['testCells', 'd']);
+ const ce = new NumericMemoryColumn('column_e', ['testCells', 'e']);
+ aggregateTableRowCellsRecursively(row, [cd, ce], function(contexts) {
+ return contexts === undefined || !contexts[0].startsWith('skip');
+ });
+ checkSizeNumericFields(row, cd, undefined);
+ checkSizeNumericFields(row, ce, [-300]);
+ });
+
+ test('checkAggregateTableRowCells', function() {
+ const row = {
+ // Intentionally no testCells.
+ otherCells: {
+ a: buildScalarCell(tr.b.Unit.byName.unitlessNumber,
+ [5, undefined, undefined])
+ }
+ };
+ const subRows = [
+ {
+ testCells: {
+ a: buildScalarCell(sizeInBytes_smallerIsBetter, [1, 9])
+ },
+ subRows: [
+ {
+ testCells: {
+ c: buildScalarCell(sizeInBytes_smallerIsBetter, [13])
+ }
+ }
+ ]
+ },
+ {
+ testCells: {
+ a: buildScalarCell(sizeInBytes_smallerIsBetter, [2, 17]),
+ b: buildScalarCell(sizeInBytes_smallerIsBetter, [5])
+ },
+ otherCells: {
+ a: buildScalarCell(tr.b.Unit.byName.unitlessNumber,
+ [153, undefined, 257]),
+ b: new MemoryCell(['field-should-not-propagate-upwards', ''])
+ }
+ }
+ ];
+
+ const cta = new NumericMemoryColumn('column_test_a', ['testCells', 'a']);
+ const ctb = new NumericMemoryColumn('column_test_b', ['testCells', 'b']);
+ const ctc = new NumericMemoryColumn('column_test_c', ['testCells', 'c']);
+ const coa = new NumericMemoryColumn('column_other_a', ['otherCells', 'a']);
+ const cob = new StringMemoryColumn('column_other_b', ['otherCells', 'b']);
+
+ aggregateTableRowCells(row, subRows, [cta, ctb, ctc, coa, cob]);
+
+ checkSizeNumericFields(row, cta, [3, 26]);
+ checkSizeNumericFields(row, ctb, [5]);
+ checkSizeNumericFields(row, ctc, undefined);
+
+ checkNumericFields(row, coa, [5, undefined, 257],
+ tr.b.Unit.byName.unitlessNumber);
+ checkStringFields(row, cob, undefined);
+ });
+
+ test('checkCreateCells', function() {
+ const values = [
+ {
+ a: 9,
+ b: 314
+ },
+ {
+ b: 159,
+ c: undefined
+ },
+ undefined,
+ {
+ b: 265,
+ d: 0
+ }
+ ];
+
+ const mockColumn = new MemoryColumn('', [], undefined);
+
+ const cells = createCells(values, function(dict) {
+ const fields = {};
+ for (const [key, value] of Object.entries(dict)) {
+ if (value === undefined) continue;
+ fields[key] = new Scalar(sizeInBytes_smallerIsBetter, value);
+ }
+ return fields;
+ });
+ assert.deepEqual(Object.keys(cells), ['a', 'b', 'd']);
+ checkSizeNumericFields(
+ cells.a, mockColumn, [9, undefined, undefined, undefined]);
+ checkSizeNumericFields(cells.b, mockColumn, [314, 159, undefined, 265]);
+ checkSizeNumericFields(
+ cells.d, mockColumn, [undefined, undefined, undefined, 0]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html
new file mode 100644
index 00000000000..2a20bb3c27e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html
@@ -0,0 +1,382 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import" href="/tracing/ui/analysis/stacked_pane.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-a-memory-dump-vm-regions-details-pane'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+
+ #label {
+ flex: 0 0 auto;
+ padding: 8px;
+
+ background-color: #eee;
+ border-bottom: 1px solid #8e8e8e;
+ border-top: 1px solid white;
+
+ font-size: 15px;
+ font-weight: bold;
+ }
+
+ #contents {
+ flex: 1 0 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+
+ #info_text {
+ padding: 8px;
+ color: #666;
+ font-style: italic;
+ text-align: center;
+ }
+
+ #table {
+ display: none; /* Hide until memory dumps are set. */
+ flex: 1 0 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <div id="label">Memory maps</div>
+ <div id="contents">
+ <div id="info_text">No memory maps selected</div>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const Scalar = tr.b.Scalar;
+ const sizeInBytes_smallerIsBetter =
+ tr.b.Unit.byName.sizeInBytes_smallerIsBetter;
+
+ const CONSTANT_COLUMN_RULES = [
+ {
+ condition: 'Start address',
+ importance: 0,
+ columnConstructor: tr.ui.analysis.StringMemoryColumn
+ }
+ ];
+
+ const VARIABLE_COLUMN_RULES = [
+ {
+ condition: 'Virtual size',
+ importance: 7,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ condition: 'Protection flags',
+ importance: 6,
+ columnConstructor: tr.ui.analysis.StringMemoryColumn
+ },
+ {
+ condition: 'PSS',
+ importance: 5,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ condition: 'Private dirty',
+ importance: 4,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ condition: 'Private clean',
+ importance: 3,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ condition: 'Shared dirty',
+ importance: 2,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ condition: 'Shared clean',
+ importance: 1,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ },
+ {
+ condition: 'Swapped',
+ importance: 0,
+ columnConstructor: tr.ui.analysis.DetailsNumericMemoryColumn
+ }
+ ];
+
+ const BYTE_STAT_COLUMN_MAP = {
+ 'proportionalResident': 'PSS',
+ 'privateDirtyResident': 'Private dirty',
+ 'privateCleanResident': 'Private clean',
+ 'sharedDirtyResident': 'Shared dirty',
+ 'sharedCleanResident': 'Shared clean',
+ 'swapped': 'Swapped'
+ };
+
+ function hexString(address, is64BitAddress) {
+ if (address === undefined) return undefined;
+ const hexPadding = is64BitAddress ? '0000000000000000' : '00000000';
+ return (hexPadding + address.toString(16)).substr(-hexPadding.length);
+ }
+
+ function pruneEmptyRuleRows(row) {
+ if (row.subRows === undefined || row.subRows.length === 0) return;
+
+ // Either all sub-rows are rule rows, or all sub-rows are VM region rows.
+ if (row.subRows[0].rule === undefined) {
+ // VM region rows: Early out to avoid filtering a large array for
+ // performance reasons (no sub-rows would be removed, but the whole array
+ // would be unnecessarily copied to a new array).
+ return;
+ }
+
+ row.subRows.forEach(pruneEmptyRuleRows);
+ row.subRows = row.subRows.filter(function(subRow) {
+ return subRow.subRows.length > 0;
+ });
+ }
+
+ Polymer({
+ is: 'tr-ui-a-memory-dump-vm-regions-details-pane',
+ behaviors: [tr.ui.analysis.StackedPane],
+
+ created() {
+ this.vmRegions_ = undefined;
+ this.aggregationMode_ = undefined;
+ },
+
+ ready() {
+ this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ },
+
+ /**
+ * Sets the VM regions and schedules rebuilding the pane.
+ *
+ * The provided value should be a chronological list of lists of VM
+ * regions. All VM regions are assumed to belong to the same process.
+ * Example:
+ *
+ * [
+ * [
+ * // VM regions at timestamp 1.
+ * tr.model.VMRegion {},
+ * tr.model.VMRegion {},
+ * tr.model.VMRegion {}
+ * ],
+ * undefined, // No VM regions provided at timestamp 2.
+ * [
+ * // VM regions at timestamp 3.
+ * tr.model.VMRegion {},
+ * tr.model.VMRegion {}
+ * ]
+ * ]
+ */
+ set vmRegions(vmRegions) {
+ this.vmRegions_ = vmRegions;
+ this.scheduleRebuild_();
+ },
+
+ get vmRegions() {
+ return this.vmRegions_;
+ },
+
+ set aggregationMode(aggregationMode) {
+ this.aggregationMode_ = aggregationMode;
+ this.scheduleRebuild_();
+ },
+
+ get aggregationMode() {
+ return this.aggregationMode_;
+ },
+
+ onRebuild_() {
+ if (this.vmRegions_ === undefined || this.vmRegions_.length === 0) {
+ // Show the info text (hide the table).
+ this.$.info_text.style.display = 'block';
+ this.$.table.style.display = 'none';
+
+ this.$.table.clear();
+ this.$.table.rebuild();
+ return;
+ }
+
+ // Show the table (hide the info text).
+ this.$.info_text.style.display = 'none';
+ this.$.table.style.display = 'block';
+
+ const rows = this.createRows_(this.vmRegions_);
+ const columns = this.createColumns_(rows);
+
+ // Note: There is no need to aggregate fields of the VM regions because
+ // the classification tree already takes care of that.
+
+ this.$.table.tableRows = rows;
+ this.$.table.tableColumns = columns;
+
+ // TODO(petrcermak): This can be quite slow. Consider doing this somehow
+ // asynchronously.
+ this.$.table.rebuild();
+
+ tr.ui.analysis.expandTableRowsRecursively(this.$.table);
+ },
+
+ createRows_(timeToVmRegionTree) {
+ // Determine if any start address is outside the 32-bit range.
+ const is64BitAddress = timeToVmRegionTree.some(function(vmRegionTree) {
+ if (vmRegionTree === undefined) return false;
+ return vmRegionTree.someRegion(function(region) {
+ if (region.startAddress === undefined) return false;
+ return region.startAddress >= 4294967296; /* 2^32 */
+ });
+ });
+
+ return [
+ this.createClassificationNodeRow(timeToVmRegionTree, is64BitAddress)
+ ];
+ },
+
+ createClassificationNodeRow(timeToNode, is64BitAddress) {
+ // Get any defined classification node so that we can extract the
+ // properties which don't change over time.
+ const definedNode = timeToNode.find(x => x);
+
+ // Child node ID (list index) -> Timestamp (list index) ->
+ // VM region classification node.
+ const childNodeIdToTimeToNode = Object.values(
+ tr.b.invertArrayOfDicts(timeToNode, function(node) {
+ const children = node.children;
+ if (children === undefined) return undefined;
+ const childMap = {};
+ children.forEach(function(childNode) {
+ if (!childNode.hasRegions) return;
+ childMap[childNode.title] = childNode;
+ });
+ return childMap;
+ }));
+ const childNodeSubRows = childNodeIdToTimeToNode.map(
+ function(timeToChildNode) {
+ return this.createClassificationNodeRow(
+ timeToChildNode, is64BitAddress);
+ }, this);
+
+ // Region ID (list index) -> Timestamp (list index) -> VM region.
+ const regionIdToTimeToRegion = Object.values(
+ tr.b.invertArrayOfDicts(timeToNode, function(node) {
+ const regions = node.regions;
+ if (regions === undefined) return undefined;
+
+ const results = {};
+ for (const region of regions) {
+ results[region.uniqueIdWithinProcess] = region;
+ }
+ return results;
+ }));
+ const regionSubRows = regionIdToTimeToRegion.map(function(timeToRegion) {
+ return this.createRegionRow_(timeToRegion, is64BitAddress);
+ }, this);
+
+ const subRows = childNodeSubRows.concat(regionSubRows);
+
+ return {
+ title: definedNode.title,
+ contexts: timeToNode,
+ variableCells: this.createVariableCells_(timeToNode),
+ subRows
+ };
+ },
+
+ createRegionRow_(timeToRegion, is64BitAddress) {
+ // Get any defined VM region so that we can extract the properties which
+ // don't change over time.
+ const definedRegion = timeToRegion.find(x => x);
+
+ return {
+ title: definedRegion.mappedFile,
+ contexts: timeToRegion,
+ constantCells: this.createConstantCells_(definedRegion, is64BitAddress),
+ variableCells: this.createVariableCells_(timeToRegion)
+ };
+ },
+
+ /**
+ * Create cells for VM region properties which DON'T change over time.
+ *
+ * Note that there are currently no such properties of classification nodes.
+ */
+ createConstantCells_(definedRegion, is64BitAddress) {
+ return tr.ui.analysis.createCells([definedRegion], function(region) {
+ const startAddress = region.startAddress;
+ if (startAddress === undefined) return undefined;
+ return { 'Start address': hexString(startAddress, is64BitAddress) };
+ });
+ },
+
+ /**
+ * Create cells for VM region (classification node) properties which DO
+ * change over time.
+ */
+ createVariableCells_(timeToRegion) {
+ return tr.ui.analysis.createCells(timeToRegion, function(region) {
+ const fields = {};
+
+ const sizeInBytes = region.sizeInBytes;
+ if (sizeInBytes !== undefined) {
+ fields['Virtual size'] = new Scalar(
+ sizeInBytes_smallerIsBetter, sizeInBytes);
+ }
+ const protectionFlags = region.protectionFlagsToString;
+ if (protectionFlags !== undefined) {
+ fields['Protection flags'] = protectionFlags;
+ }
+
+ for (const [byteStatName, columnName] of
+ Object.entries(BYTE_STAT_COLUMN_MAP)) {
+ const byteStat = region.byteStats[byteStatName];
+ if (byteStat === undefined) continue;
+ fields[columnName] = new Scalar(
+ sizeInBytes_smallerIsBetter, byteStat);
+ }
+
+ return fields;
+ });
+ },
+
+ createColumns_(rows) {
+ const titleColumn = new tr.ui.analysis.TitleColumn('Mapped file');
+ titleColumn.width = '200px';
+
+ const constantColumns = tr.ui.analysis.MemoryColumn.fromRows(rows, {
+ cellKey: 'constantCells',
+ aggregationMode: undefined,
+ rules: CONSTANT_COLUMN_RULES
+ });
+ const variableColumns = tr.ui.analysis.MemoryColumn.fromRows(rows, {
+ cellKey: 'variableCells',
+ aggregationMode: this.aggregationMode_,
+ rules: VARIABLE_COLUMN_RULES
+ });
+ const fieldColumns = constantColumns.concat(variableColumns);
+ tr.ui.analysis.MemoryColumn.spaceEqually(fieldColumns);
+
+ const columns = [titleColumn].concat(fieldColumns);
+ return columns;
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane_test.html
new file mode 100644
index 00000000000..7534727091b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/memory_dump_vm_regions_details_pane_test.html
@@ -0,0 +1,496 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+<link rel="import"
+ href="/tracing/ui/analysis/memory_dump_sub_view_test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/memory_dump_sub_view_util.html">
+<link rel="import"
+ href="/tracing/ui/analysis/memory_dump_vm_regions_details_pane.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const VMRegion = tr.model.VMRegion;
+ const VMRegionClassificationNode = tr.model.VMRegionClassificationNode;
+ const TitleColumn = tr.ui.analysis.TitleColumn;
+ const StringMemoryColumn = tr.ui.analysis.StringMemoryColumn;
+ const NumericMemoryColumn = tr.ui.analysis.NumericMemoryColumn;
+ const AggregationMode = tr.ui.analysis.MemoryColumn.AggregationMode;
+ const addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
+ const addProcessMemoryDump =
+ tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
+ const checkSizeNumericFields = tr.ui.analysis.checkSizeNumericFields;
+ const checkStringFields = tr.ui.analysis.checkStringFields;
+ const checkColumns = tr.ui.analysis.checkColumns;
+ const isElementDisplayed = tr.ui.analysis.isElementDisplayed;
+ const DETAILED = tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;
+
+ function createVMRegions() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+
+ // First timestamp.
+ const gmd1 = addGlobalMemoryDump(
+ model, {ts: 42, levelOfDetail: DETAILED});
+ const pmd1 = addProcessMemoryDump(gmd1, process, {ts: 42});
+ pmd1.vmRegions = VMRegionClassificationNode.fromRegions([
+ VMRegion.fromDict({
+ mappedFile: '/lib/chrome.so',
+ startAddress: 65536,
+ sizeInBytes: 536870912,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ byteStats: {
+ proportionalResident: 8192
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0',
+ startAddress: 140296983150592,
+ sizeInBytes: 2097152,
+ protectionFlags: 0,
+ byteStats: {
+ proportionalResident: 0
+ }
+ }),
+ VMRegion.fromDict({
+ startAddress: 10995116277760,
+ sizeInBytes: 2147483648,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE,
+ byteStats: {
+ privateDirtyResident: 0,
+ swapped: 0
+ }
+ }),
+ VMRegion.fromDict({
+ startAddress: 12094627905536,
+ sizeInBytes: 2147483648,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE,
+ byteStats: {
+ privateDirtyResident: 0,
+ swapped: 0
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '/dev/ashmem/dalvik-zygote space',
+ startAddress: 13194139533312,
+ sizeInBytes: 100,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ byteStats: {
+ proportionalResident: 100,
+ privateDirtyResident: 0,
+ swapped: 0
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '/dev/ashmem/libc malloc',
+ startAddress: 14293651161088,
+ sizeInBytes: 200,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ byteStats: {
+ proportionalResident: 200,
+ privateDirtyResident: 96,
+ swapped: 0
+ }
+ })
+ ]);
+
+ // This is here so that we could test that tracing is discounted from the
+ // 'Native heap' category.
+ pmd1.memoryAllocatorDumps = [
+ newAllocatorDump(pmd1, 'tracing',
+ {numerics: {size: 500, resident_size: 32}})
+ ];
+
+ // Second timestamp.
+ const gmd2 = addGlobalMemoryDump(
+ model, {ts: 42, levelOfDetail: DETAILED});
+ const pmd2 = addProcessMemoryDump(gmd2, process, {ts: 42});
+ pmd2.vmRegions = VMRegionClassificationNode.fromRegions([
+ VMRegion.fromDict({
+ mappedFile: '/lib/chrome.so',
+ startAddress: 65536,
+ sizeInBytes: 536870912,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ byteStats: {
+ proportionalResident: 9216
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '/lib/chrome.so',
+ startAddress: 140296983150592,
+ sizeInBytes: 536870912,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ byteStats: {
+ proportionalResident: 10240
+ }
+ }),
+ VMRegion.fromDict({
+ startAddress: 10995116277760,
+ sizeInBytes: 2147483648,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE,
+ byteStats: {
+ privateDirtyResident: 0,
+ swapped: 32
+ }
+ }),
+ VMRegion.fromDict({
+ startAddress: 12094627905536,
+ sizeInBytes: 2147483648,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_WRITE,
+ byteStats: {
+ privateDirtyResident: 0,
+ swapped: 0
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '/dev/ashmem/dalvik-zygote space',
+ startAddress: 13194139533312,
+ sizeInBytes: 100,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ byteStats: {
+ proportionalResident: 0,
+ privateDirtyResident: 100,
+ swapped: 0
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '/dev/ashmem/libc malloc',
+ startAddress: 14293651161088,
+ sizeInBytes: 200,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ |
+ VMRegion.PROTECTION_FLAG_EXECUTE,
+ byteStats: {
+ proportionalResident: 100,
+ privateDirtyResident: 96,
+ swapped: 0
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: '/usr/share/fonts/DejaVuSansMono.ttf',
+ startAddress: 140121259503616,
+ sizeInBytes: 335872,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ byteStats: {
+ proportionalResident: 22528
+ }
+ }),
+ VMRegion.fromDict({
+ mappedFile: 'another-map',
+ startAddress: 52583094233905872,
+ sizeInBytes: 1,
+ byteStats: {
+ proportionalResident: 1,
+ privateDirtyResident: 1,
+ swapped: 1
+ }
+ })
+ ]);
+ });
+
+ return model.processes[1].memoryDumps.map(function(pmd) {
+ return pmd.mostRecentVmRegions;
+ });
+ }
+
+ const EXPECTED_COLUMNS = [
+ { title: 'Mapped file', type: TitleColumn, noAggregation: true },
+ { title: 'Start address', type: StringMemoryColumn, noAggregation: true },
+ { title: 'Virtual size', type: NumericMemoryColumn },
+ { title: 'Protection flags', type: StringMemoryColumn },
+ { title: 'PSS', type: NumericMemoryColumn },
+ { title: 'Private dirty', type: NumericMemoryColumn },
+ { title: 'Swapped', type: NumericMemoryColumn }
+ ];
+
+ function checkRow(columns, row, expectedTitle, expectedStartAddress,
+ expectedVirtualSize, expectedProtectionFlags,
+ expectedProportionalResidentValues, expectedPrivateDirtyResidentValues,
+ expectedSwappedValues, expectedSubRowCount, expectedContexts) {
+ assert.strictEqual(columns[0].formatTitle(row), expectedTitle);
+ checkStringFields(row, columns[1], expectedStartAddress);
+ checkSizeNumericFields(row, columns[2], expectedVirtualSize);
+ checkStringFields(row, columns[3], expectedProtectionFlags);
+ checkSizeNumericFields(row, columns[4], expectedProportionalResidentValues);
+ checkSizeNumericFields(row, columns[5], expectedPrivateDirtyResidentValues);
+ checkSizeNumericFields(row, columns[6], expectedSwappedValues);
+
+ if (expectedSubRowCount === undefined) {
+ assert.isUndefined(row.subRows);
+ } else {
+ assert.lengthOf(row.subRows, expectedSubRowCount);
+ }
+
+ if (typeof expectedContexts === 'function') {
+ expectedContexts(row.contexts);
+ } else if (expectedContexts !== undefined) {
+ assert.deepEqual(Array.from(row.contexts), expectedContexts);
+ } else {
+ assert.isUndefined(row.contexts);
+ }
+ }
+
+ function genericMatcher(callback, defined) {
+ return function(actualValues) {
+ assert.lengthOf(actualValues, defined.length);
+ for (let i = 0; i < defined.length; i++) {
+ const actualValue = actualValues[i];
+ if (defined[i]) {
+ callback(actualValue);
+ } else {
+ assert.isUndefined(actualValue);
+ }
+ }
+ };
+ }
+
+ function vmRegionsMatcher(expectedMappedFile, expectedStartAddress, defined) {
+ return genericMatcher(function(actualRegion) {
+ assert.instanceOf(actualRegion, VMRegion);
+ assert.strictEqual(actualRegion.mappedFile, expectedMappedFile);
+ assert.strictEqual(actualRegion.startAddress, expectedStartAddress);
+ }, defined);
+ }
+
+ function classificationNodesMatcher(expectedTitle, defined) {
+ return genericMatcher(function(actualNode) {
+ assert.instanceOf(actualNode, VMRegionClassificationNode);
+ assert.strictEqual(actualNode.title, expectedTitle);
+ }, defined);
+ }
+
+ test('instantiate_empty', function() {
+ tr.ui.analysis.createAndCheckEmptyPanes(this,
+ 'tr-ui-a-memory-dump-vm-regions-details-pane', 'vmRegions',
+ function(viewEl) {
+ // Check that the info text is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.info_text));
+ assert.isFalse(isElementDisplayed(viewEl.$.table));
+ });
+ });
+
+ test('instantiate_single', function() {
+ const vmRegions = createVMRegions().slice(0, 1);
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-memory-dump-vm-regions-details-pane');
+ viewEl.vmRegions = vmRegions;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, undefined /* no aggregation */);
+ const rows = table.tableRows;
+ assert.lengthOf(rows, 1);
+
+ // Check the rows of the table.
+ const totalRow = rows[0];
+ checkRow(columns, totalRow, 'Total', undefined, [4833935160], undefined,
+ [8460], [64], [0], 3, vmRegions);
+
+ const androidRow = totalRow.subRows[0];
+ checkRow(columns, androidRow, 'Android', undefined, [100], undefined,
+ [100], [0], [0], 1, classificationNodesMatcher('Android', [true]));
+
+ const javaRuntimeRow = androidRow.subRows[0];
+ checkRow(columns, javaRuntimeRow, 'Java runtime', undefined, [100],
+ undefined, [100], [0], [0], 1,
+ classificationNodesMatcher('Java runtime', [true]));
+
+ const spacesRow = javaRuntimeRow.subRows[0];
+ checkRow(columns, spacesRow, 'Spaces', undefined, [100], undefined, [100],
+ [0], [0], 1, classificationNodesMatcher('Spaces', [true]));
+
+ const nativeHeapRow = totalRow.subRows[1];
+ checkRow(columns, nativeHeapRow, 'Native heap', undefined, [4294966996],
+ undefined, [168], [64], [0], 4,
+ classificationNodesMatcher('Native heap', [true]));
+
+ const discountedTracingOverheadRow = nativeHeapRow.subRows[3];
+ checkRow(columns, discountedTracingOverheadRow,
+ '[discounted tracing overhead]', undefined, [-500], undefined, [-32],
+ [-32], undefined, undefined,
+ vmRegionsMatcher('[discounted tracing overhead]', undefined, [true]));
+
+ const filesRow = totalRow.subRows[2];
+ checkRow(columns, filesRow, 'Files', undefined, [538968064], undefined,
+ [8192], undefined, undefined, 1,
+ classificationNodesMatcher('Files', [true]));
+
+ const soRow = filesRow.subRows[0];
+ checkRow(columns, soRow, 'so', undefined, [538968064], undefined,
+ [8192], undefined, undefined, 2,
+ classificationNodesMatcher('so', [true]));
+
+ const mmapChromeRow = soRow.subRows[0];
+ checkRow(columns, mmapChromeRow, '/lib/chrome.so', ['0000000000010000'],
+ [536870912], ['r-xp'], [8192], undefined, undefined, undefined,
+ vmRegionsMatcher('/lib/chrome.so', 65536, [true]));
+
+ const mmapLibX11Row = soRow.subRows[1];
+ checkRow(columns, mmapLibX11Row,
+ '/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0', ['00007f996fd80000'],
+ [2097152], ['---p'], [0], undefined, undefined, undefined,
+ vmRegionsMatcher('/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0',
+ 140296983150592, [true]));
+ });
+
+ test('instantiate_multipleDiff', function() {
+ const vmRegions = createVMRegions();
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-memory-dump-vm-regions-details-pane');
+ viewEl.vmRegions = vmRegions;
+ viewEl.aggregationMode = AggregationMode.DIFF;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, AggregationMode.DIFF);
+ const rows = table.tableRows;
+ assert.lengthOf(rows, 1);
+
+ // Check the rows of the table.
+ const totalRow = rows[0];
+ checkRow(columns, totalRow, 'Total', undefined, [4833935160, 5369045293],
+ undefined, [8460, 42085], [64, 197], [0, 33], 4, vmRegions);
+
+ const androidRow = totalRow.subRows[0];
+ checkRow(columns, androidRow, 'Android', undefined, [100, 100], undefined,
+ [100, 0], [0, 100], [0, 0], 1,
+ classificationNodesMatcher('Android', [true, true]));
+
+ const javaRuntimeRow = androidRow.subRows[0];
+ checkRow(columns, javaRuntimeRow, 'Java runtime', undefined, [100, 100],
+ undefined, [100, 0], [0, 100], [0, 0], 1,
+ classificationNodesMatcher('Java runtime', [true, true]));
+
+ const spacesRow = javaRuntimeRow.subRows[0];
+ checkRow(columns, spacesRow, 'Spaces', undefined, [100, 100], undefined,
+ [100, 0], [0, 100], [0, 0], 1,
+ classificationNodesMatcher('Spaces', [true, true]));
+
+ const nativeHeapRow = totalRow.subRows[1];
+ checkRow(columns, nativeHeapRow, 'Native heap', undefined,
+ [4294966996, 4294967496], undefined, [168, 100], [64, 96], [0, 32], 4,
+ classificationNodesMatcher('Native heap', [true, true]));
+
+ const discountedTracingOverheadRow = nativeHeapRow.subRows[3];
+ checkRow(columns, discountedTracingOverheadRow,
+ '[discounted tracing overhead]', undefined, [-500, undefined],
+ undefined, [-32, undefined], [-32, undefined], undefined, undefined,
+ vmRegionsMatcher('[discounted tracing overhead]', undefined,
+ [true, false]));
+
+ const filesRow = totalRow.subRows[2];
+ checkRow(columns, filesRow, 'Files', undefined, [538968064, 1074077696],
+ undefined, [8192, 41984], undefined, undefined, 2,
+ classificationNodesMatcher('Files', [true, true]));
+
+ const soRow = filesRow.subRows[0];
+ checkRow(columns, soRow, 'so', undefined, [538968064, 1073741824],
+ undefined, [8192, 19456], undefined, undefined, 3,
+ classificationNodesMatcher('so', [true, true]));
+
+ const mmapChromeRow = soRow.subRows[0];
+ checkRow(columns, mmapChromeRow, '/lib/chrome.so', ['0000000000010000'],
+ [536870912, 536870912], ['r-xp', 'r-xp'], [8192, 9216], undefined,
+ undefined, undefined,
+ vmRegionsMatcher('/lib/chrome.so', 65536, [true, true]));
+
+ const mmapLibX11Row = soRow.subRows[1];
+ checkRow(columns, mmapLibX11Row,
+ '/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0', ['00007f996fd80000'],
+ [2097152, undefined], ['---p', undefined], [0, undefined], undefined,
+ undefined, undefined,
+ vmRegionsMatcher('/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0',
+ 140296983150592, [true, false]));
+
+ const otherRow = totalRow.subRows[3];
+ checkRow(columns, otherRow, 'Other', undefined, [undefined, 1], undefined,
+ [undefined, 1], [undefined, 1], [undefined, 1], 1,
+ classificationNodesMatcher('Other', [false, true]));
+
+ const anotherMapRow = otherRow.subRows[0];
+ checkRow(columns, anotherMapRow, 'another-map', ['00bad00bad00bad0'],
+ [undefined, 1], undefined, [undefined, 1], [undefined, 1],
+ [undefined, 1], undefined,
+ vmRegionsMatcher('another-map', 52583094233905872, [false, true]));
+ });
+
+ test('instantiate_multipleMax', function() {
+ const vmRegions = createVMRegions();
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-memory-dump-vm-regions-details-pane');
+ viewEl.vmRegions = vmRegions;
+ viewEl.aggregationMode = AggregationMode.MAX;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ // Just check that the aggregation mode was propagated to the columns.
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, AggregationMode.MAX);
+ const rows = table.tableRows;
+ assert.lengthOf(rows, 1);
+ });
+
+ test('instantiate_multipleWithUndefined', function() {
+ const vmRegions = createVMRegions();
+ vmRegions.splice(1, 0, undefined);
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-memory-dump-vm-regions-details-pane');
+ viewEl.vmRegions = vmRegions;
+ viewEl.aggregationMode = AggregationMode.DIFF;
+ viewEl.rebuild();
+ this.addHTMLOutput(viewEl);
+
+ // Check that the table is shown.
+ assert.isTrue(isElementDisplayed(viewEl.$.table));
+ assert.isFalse(isElementDisplayed(viewEl.$.info_text));
+
+ // Just check that the table has the right shape.
+ const table = viewEl.$.table;
+ const columns = table.tableColumns;
+ checkColumns(columns, EXPECTED_COLUMNS, AggregationMode.DIFF);
+ const rows = table.tableRows;
+ assert.lengthOf(rows, 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view.html
new file mode 100644
index 00000000000..0bb39b7e0f2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/related_events.html">
+
+<dom-module id='tr-ui-a-multi-async-slice-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ }
+ #container {
+ display: flex;
+ flex: 1 1 auto;
+ }
+ #events {
+ margin-left: 8px;
+ flex: 0 1 200px;
+ }
+ </style>
+ <div id="container">
+ <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view>
+ <div id="events">
+ <tr-ui-a-related-events id="relatedEvents"></tr-ui-a-related-events>
+ </div>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-async-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.content.selection = selection;
+ this.$.relatedEvents.setRelatedEvents(selection);
+ if (this.$.relatedEvents.hasRelatedEvents()) {
+ this.$.relatedEvents.style.display = '';
+ } else {
+ this.$.relatedEvents.style.display = 'none';
+ }
+ },
+
+ get relatedEventsToHighlight() {
+ if (!this.$.content.selection) return undefined;
+
+ const selection = new tr.model.EventSet();
+ this.$.content.selection.forEach(function(asyncEvent) {
+ if (!asyncEvent.associatedEvents) return;
+
+ asyncEvent.associatedEvents.forEach(function(event) {
+ selection.push(event);
+ });
+ });
+ if (selection.length) return selection;
+ return undefined;
+ }
+});
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-async-slice-sub-view',
+ tr.model.AsyncSlice,
+ {
+ multi: true,
+ title: 'Async Slices',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view_test.html
new file mode 100644
index 00000000000..20fb52c058f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_async_slice_sub_view_test.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/multi_async_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx;
+
+ test('instantiate', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.asyncSliceGroup.push(newAsyncSliceEx({
+ title: 'a',
+ start: 10,
+ end: 20,
+ startThread: t1,
+ endThread: t1
+ }));
+ t1.asyncSliceGroup.push(newAsyncSliceEx({
+ title: 'b',
+ start: 25,
+ end: 40,
+ startThread: t1,
+ endThread: t1
+ }));
+
+ const selection = new tr.model.EventSet();
+ selection.push(t1.asyncSliceGroup.slices[0]);
+ selection.push(t1.asyncSliceGroup.slices[1]);
+
+ const viewEl = document.createElement('tr-ui-a-multi-async-slice-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view.html
new file mode 100644
index 00000000000..4525df0e8c2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+
+<dom-module id='tr-ui-a-multi-cpu-slice-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ }
+ #content {
+ flex: 1 1 auto;
+ }
+ </style>
+ <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-cpu-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ ready() {
+ this.$.content.eventsHaveSubRows = false;
+ },
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.content.setSelectionWithoutErrorChecks(selection);
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-cpu-slice-sub-view',
+ tr.model.CpuSlice,
+ {
+ multi: true,
+ title: 'CPU Slices',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view_test.html
new file mode 100644
index 00000000000..36dc99bd338
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_cpu_slice_sub_view_test.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/multi_cpu_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createBasicModel() {
+ const lines = [
+ 'Android.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D ==> next_comm=Android.launcher next_pid=584 next_prio=120', // @suppress longLineCheck
+ 'Android.launcher-584 [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001', // @suppress longLineCheck
+ 'Android.launcher-584 [001] d..3 12622.506950: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: B|128|queueBuffer', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E',
+ ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
+ ];
+
+ return tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('instantiate', function() {
+ const m = createBasicModel();
+ const cpu = m.kernel.cpus[1];
+ assert.isDefined(cpu);
+
+ const selection = new tr.model.EventSet();
+ selection.push(cpu.slices[0]);
+ selection.push(cpu.slices[1]);
+
+ const viewEl = document.createElement('tr-ui-a-multi-cpu-slice-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view.html
new file mode 100644
index 00000000000..52908c620bc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view.html
@@ -0,0 +1,211 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_summary_table.html">
+<link rel="import" href="/tracing/ui/analysis/selection_summary_table.html">
+<link rel="import" href="/tracing/ui/base/radio_picker.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/value/diagnostics/scalar.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/ui/histogram_span.html">
+
+<dom-module id='tr-ui-a-multi-event-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ overflow: auto;
+ }
+ #content {
+ display: flex;
+ flex-direction: column;
+ flex: 0 1 auto;
+ align-self: stretch;
+ }
+ #content > * {
+ flex: 0 0 auto;
+ align-self: stretch;
+ }
+ #histogramContainer {
+ display: flex;
+ }
+
+ tr-ui-a-multi-event-summary-table {
+ border-bottom: 1px solid #aaa;
+ }
+
+ tr-ui-a-selection-summary-table {
+ margin-top: 1.25em;
+ border-top: 1px solid #aaa;
+ background-color: #eee;
+ font-weight: bold;
+ margin-bottom: 1.25em;
+ border-bottom: 1px solid #aaa;
+ }
+ </style>
+ <div id="content">
+ <tr-ui-a-multi-event-summary-table id="eventSummaryTable">
+ </tr-ui-a-multi-event-summary-table>
+ <tr-ui-a-selection-summary-table id="selectionSummaryTable">
+ </tr-ui-a-selection-summary-table>
+ <tr-ui-b-radio-picker id="radioPicker">
+ </tr-ui-b-radio-picker>
+ <div id="histogramContainer">
+ <tr-v-ui-histogram-span id="histogramSpan">
+ </tr-v-ui-histogram-span>
+ </div>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const EVENT_FIELD = [
+ {key: 'start', label: 'Start'},
+ {key: 'cpuDuration', label: 'CPU Duration'},
+ {key: 'duration', label: 'Duration'},
+ {key: 'cpuSelfTime', label: 'CPU Self Time'},
+ {key: 'selfTime', label: 'Self Time'}
+ ];
+
+ function buildDiagnostics_(slice) {
+ const diagnostics = {};
+ for (const item of EVENT_FIELD) {
+ const fieldName = item.key;
+ if (slice[fieldName] === undefined) continue;
+ diagnostics[fieldName] = new tr.v.d.Scalar(new tr.b.Scalar(
+ tr.b.Unit.byName.timeDurationInMs, slice[fieldName]));
+ }
+ diagnostics.args = new tr.v.d.GenericSet([slice.args]);
+ diagnostics.event = new tr.v.d.RelatedEventSet(slice);
+ return diagnostics;
+ }
+
+ Polymer({
+ is: 'tr-ui-a-multi-event-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ this.eventsHaveDuration_ = true;
+ this.eventsHaveSubRows_ = true;
+ },
+
+ ready() {
+ this.$.radioPicker.style.display = 'none';
+ this.$.radioPicker.items = EVENT_FIELD;
+ this.$.radioPicker.select('cpuSelfTime');
+ this.$.radioPicker.addEventListener('change', () => {
+ if (this.isAttached) this.updateContents_();
+ });
+
+ this.$.histogramSpan.graphWidth = 400;
+ this.$.histogramSpan.canMergeSampleDiagnostics = false;
+ this.$.histogramContainer.style.display = 'none';
+ },
+
+ attached() {
+ if (this.currentSelection_ !== undefined) this.updateContents_();
+ },
+
+ set selection(selection) {
+ if (selection.length <= 1) {
+ throw new Error('Only supports multiple items');
+ }
+ this.setSelectionWithoutErrorChecks(selection);
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ setSelectionWithoutErrorChecks(selection) {
+ this.currentSelection_ = selection;
+ if (this.isAttached) this.updateContents_();
+ },
+
+ get eventsHaveDuration() {
+ return this.eventsHaveDuration_;
+ },
+
+ set eventsHaveDuration(eventsHaveDuration) {
+ this.eventsHaveDuration_ = eventsHaveDuration;
+ if (this.isAttached) this.updateContents_();
+ },
+
+ get eventsHaveSubRows() {
+ return this.eventsHaveSubRows_;
+ },
+
+ set eventsHaveSubRows(eventsHaveSubRows) {
+ this.eventsHaveSubRows_ = eventsHaveSubRows;
+ if (this.isAttached) this.updateContents_();
+ },
+
+ buildHistogram_(selectedKey) {
+ let leftBoundary = Number.MAX_VALUE;
+ let rightBoundary = tr.b.math.Statistics.percentile(
+ this.currentSelection_, 0.95,
+ function(value) {
+ leftBoundary = Math.min(leftBoundary, value[selectedKey]);
+ return value[selectedKey];
+ });
+
+ if (leftBoundary === rightBoundary) rightBoundary += 1;
+ const histogram = new tr.v.Histogram(
+ '',
+ tr.b.Unit.byName.timeDurationInMs,
+ tr.v.HistogramBinBoundaries.createLinear(
+ leftBoundary, rightBoundary,
+ Math.ceil(Math.sqrt(this.currentSelection_.length))));
+ histogram.customizeSummaryOptions({sum: false});
+ for (const slice of this.currentSelection_) {
+ histogram.addSample(slice[selectedKey],
+ buildDiagnostics_(slice));
+ }
+
+ return histogram;
+ },
+
+ updateContents_() {
+ const selection = this.currentSelection_;
+ if (!selection) return;
+
+ const eventsByTitle = selection.getEventsOrganizedByTitle();
+ const numTitles = Object.keys(eventsByTitle).length;
+
+ this.$.eventSummaryTable.configure({
+ showTotals: numTitles > 1,
+ eventsByTitle,
+ eventsHaveDuration: this.eventsHaveDuration_,
+ eventsHaveSubRows: this.eventsHaveSubRows_
+ });
+
+ this.$.selectionSummaryTable.selection = this.currentSelection_;
+
+ if (numTitles === 1) {
+ this.$.radioPicker.style.display = 'block';
+ this.$.histogramContainer.style.display = 'flex';
+ this.$.histogramSpan.build(
+ this.buildHistogram_(this.$.radioPicker.selectedKey));
+ if (this.$.histogramSpan.histogram.numValues === 0) {
+ this.$.histogramContainer.style.display = 'none';
+ }
+ } else {
+ this.$.radioPicker.style.display = 'none';
+ this.$.histogramContainer.style.display = 'none';
+ }
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html
new file mode 100644
index 00000000000..9958b7db81c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_sub_view_test.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const Thread = tr.model.Thread;
+ const EventSet = tr.model.EventSet;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ test('differentTitles', function() {
+ const model = new Model();
+ const t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
+ t53.sliceGroup.pushSlice(newSliceEx(
+ {title: 'a', start: 0.0, duration: 0.04}));
+ t53.sliceGroup.pushSlice(newSliceEx(
+ {title: 'a', start: 0.12, duration: 0.06}));
+ t53.sliceGroup.pushSlice(newSliceEx(
+ {title: 'aa', start: 0.5, duration: 0.5}));
+ t53.sliceGroup.createSubSlices();
+
+ const t53track = {};
+ t53track.thread = t53;
+
+ const selection = new EventSet();
+ selection.push(t53.sliceGroup.slices[0]);
+ selection.push(t53.sliceGroup.slices[1]);
+ selection.push(t53.sliceGroup.slices[2]);
+
+ const viewEl = document.createElement('tr-ui-a-multi-event-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+
+ const summaryTableEl = tr.ui.b.findDeepElementMatching(
+ viewEl, 'tr-ui-a-multi-event-summary-table');
+ assert.isTrue(summaryTableEl.showTotals);
+ assert.lengthOf(Object.keys(summaryTableEl.eventsByTitle), 2);
+
+ const selectionSummaryTableEl = tr.ui.b.findDeepElementMatching(
+ viewEl, 'tr-ui-a-selection-summary-table');
+ assert.strictEqual(selectionSummaryTableEl.selection, selection);
+
+ const radioPickerEl =
+ tr.ui.b.findDeepElementMatching(viewEl, 'tr-ui-b-radio-picker');
+ assert.strictEqual(radioPickerEl.style.display, 'none');
+ });
+
+ test('sameTitles', function() {
+ const model = new Model();
+ const t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
+ t53.sliceGroup.pushSlice(newSliceEx(
+ {title: 'c', start: 0.0, duration: 0.04}));
+ t53.sliceGroup.pushSlice(newSliceEx(
+ {title: 'c', start: 0.12, duration: 0.06}));
+ t53.sliceGroup.createSubSlices();
+
+ const t53track = {};
+ t53track.thread = t53;
+
+ const selection = new EventSet();
+ selection.push(t53.sliceGroup.slices[0]);
+ selection.push(t53.sliceGroup.slices[1]);
+
+ const viewEl = document.createElement('tr-ui-a-multi-event-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+
+ const summaryTableEl = tr.ui.b.findDeepElementMatching(
+ viewEl, 'tr-ui-a-multi-event-summary-table');
+ assert.isFalse(summaryTableEl.showTotals);
+ assert.lengthOf(Object.keys(summaryTableEl.eventsByTitle), 1);
+
+ const selectionSummaryTableEl = tr.ui.b.findDeepElementMatching(
+ viewEl, 'tr-ui-a-selection-summary-table');
+ assert.strictEqual(selectionSummaryTableEl.selection, selection);
+
+ const radioPickerEl =
+ tr.ui.b.findDeepElementMatching(viewEl, 'tr-ui-b-radio-picker');
+ assert.strictEqual(radioPickerEl.style.display, 'block');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary.html
new file mode 100644
index 00000000000..886e315863e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.ui.analysis', function() {
+ function MultiEventSummary(title, events) {
+ this.title = title;
+ this.duration_ = undefined;
+ this.selfTime_ = undefined;
+ this.events_ = events;
+
+ this.cpuTimesComputed_ = false;
+ this.cpuSelfTime_ = undefined;
+ this.cpuDuration_ = undefined;
+
+ this.maxDuration_ = undefined;
+ this.maxCpuDuration_ = undefined;
+ this.maxSelfTime_ = undefined;
+ this.maxCpuSelfTime_ = undefined;
+
+ this.untotallableArgs_ = [];
+ this.totalledArgs_ = undefined;
+ }
+ MultiEventSummary.prototype = {
+
+ set title(title) {
+ if (title === 'Totals') {
+ this.totalsRow = true;
+ }
+ this.title_ = title;
+ },
+
+ get title() {
+ return this.title_;
+ },
+
+ get duration() {
+ if (this.duration_ === undefined) {
+ this.duration_ = tr.b.math.Statistics.sum(
+ this.events_, function(event) {
+ return event.duration;
+ });
+ }
+ return this.duration_;
+ },
+
+ get cpuSelfTime() {
+ this.computeCpuTimesIfNeeded_();
+ return this.cpuSelfTime_;
+ },
+
+ get cpuDuration() {
+ this.computeCpuTimesIfNeeded_();
+ return this.cpuDuration_;
+ },
+
+ computeCpuTimesIfNeeded_() {
+ if (this.cpuTimesComputed_) return;
+ this.cpuTimesComputed_ = true;
+
+ let cpuSelfTime = 0;
+ let cpuDuration = 0;
+ let hasCpuData = false;
+ for (const event of this.events_) {
+ if (event.cpuDuration !== undefined) {
+ cpuDuration += event.cpuDuration;
+ hasCpuData = true;
+ }
+
+ if (event.cpuSelfTime !== undefined) {
+ cpuSelfTime += event.cpuSelfTime;
+ hasCpuData = true;
+ }
+ }
+ if (hasCpuData) {
+ this.cpuDuration_ = cpuDuration;
+ this.cpuSelfTime_ = cpuSelfTime;
+ }
+ },
+
+ get selfTime() {
+ if (this.selfTime_ === undefined) {
+ this.selfTime_ = 0;
+ for (const event of this.events_) {
+ if (event.selfTime !== undefined) {
+ this.selfTime_ += event.selfTime;
+ }
+ }
+ }
+ return this.selfTime_;
+ },
+
+ get events() {
+ return this.events_;
+ },
+
+ get numEvents() {
+ return this.events_.length;
+ },
+
+ get numAlerts() {
+ if (this.numAlerts_ === undefined) {
+ this.numAlerts_ = tr.b.math.Statistics.sum(this.events_, event =>
+ event.associatedAlerts.length
+ );
+ }
+ return this.numAlerts_;
+ },
+
+ get untotallableArgs() {
+ this.updateArgsIfNeeded_();
+ return this.untotallableArgs_;
+ },
+
+ get totalledArgs() {
+ this.updateArgsIfNeeded_();
+ return this.totalledArgs_;
+ },
+
+
+ get maxDuration() {
+ if (this.maxDuration_ === undefined) {
+ this.maxDuration_ = tr.b.math.Statistics.max(
+ this.events_, function(event) {
+ return event.duration;
+ });
+ }
+ return this.maxDuration_;
+ },
+
+
+ get maxCpuDuration() {
+ if (this.maxCpuDuration_ === undefined) {
+ this.maxCpuDuration_ = tr.b.math.Statistics.max(
+ this.events_, function(event) {
+ return event.cpuDuration;
+ });
+ }
+ return this.maxCpuDuration_;
+ },
+
+
+ get maxSelfTime() {
+ if (this.maxSelfTime_ === undefined) {
+ this.maxSelfTime_ = tr.b.math.Statistics.max(
+ this.events_, function(event) {
+ return event.selfTime;
+ });
+ }
+ return this.maxSelfTime_;
+ },
+
+
+ get maxCpuSelfTime() {
+ if (this.maxCpuSelfTime_ === undefined) {
+ this.maxCpuSelfTime_ = tr.b.math.Statistics.max(
+ this.events_, function(event) {
+ return event.cpuSelfTime;
+ });
+ }
+ return this.maxCpuSelfTime_;
+ },
+
+
+ updateArgsIfNeeded_() {
+ if (this.totalledArgs_ !== undefined) return;
+
+ const untotallableArgs = {};
+ const totalledArgs = {};
+ for (const event of this.events_) {
+ for (const argName in event.args) {
+ const argVal = event.args[argName];
+ const type = typeof argVal;
+ if (type !== 'number') {
+ untotallableArgs[argName] = true;
+ delete totalledArgs[argName];
+ continue;
+ }
+ if (untotallableArgs[argName]) {
+ continue;
+ }
+
+ if (totalledArgs[argName] === undefined) {
+ totalledArgs[argName] = 0;
+ }
+ totalledArgs[argName] += argVal;
+ }
+ }
+ this.untotallableArgs_ = Object.keys(untotallableArgs);
+ this.totalledArgs_ = totalledArgs;
+ }
+ };
+
+ return {
+ MultiEventSummary,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_table.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_table.html
new file mode 100644
index 00000000000..1b32d606f61
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_table.html
@@ -0,0 +1,358 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_summary.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-multi-event-summary-table'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ }
+ #table {
+ flex: 1 1 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table">
+ </tr-ui-b-table>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-event-summary-table',
+
+ ready() {
+ this.showTotals_ = false;
+ this.eventsHaveDuration_ = true;
+ this.eventsHaveSubRows_ = true;
+ this.eventsByTitle_ = undefined;
+ },
+
+ updateTableColumns_(rows, maxValues) {
+ let hasCpuData = false;
+ let hasAlerts = false;
+ rows.forEach(function(row) {
+ if (row.cpuDuration !== undefined) {
+ hasCpuData = true;
+ }
+ if (row.cpuSelfTime !== undefined) {
+ hasCpuData = true;
+ }
+ if (row.numAlerts) {
+ hasAlerts = true;
+ }
+ });
+
+ const ownerDocument = this.ownerDocument;
+
+ const columns = [];
+
+ columns.push({
+ title: 'Name',
+ value(row) {
+ if (row.title === 'Totals') return 'Totals';
+ const container = document.createElement('div');
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(function() {
+ return new tr.model.EventSet(row.events);
+ }, row.title);
+ container.appendChild(linkEl);
+
+ if (tr.isExported('tr-ui-e-chrome-codesearch')) {
+ const link = document.createElement('tr-ui-e-chrome-codesearch');
+ link.searchPhrase = row.title;
+ container.appendChild(link);
+ }
+ return container;
+ },
+ width: '350px',
+ cmp(rowA, rowB) {
+ return rowA.title.localeCompare(rowB.title);
+ }
+ });
+ if (this.eventsHaveDuration_) {
+ columns.push({
+ title: 'Wall Duration',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.duration, {
+ unit: tr.b.Unit.byName.timeDurationInMs,
+ customContextRange: row.totalsRow ? undefined :
+ tr.b.math.Range.fromExplicitRange(0, maxValues.duration),
+ ownerDocument,
+ });
+ },
+ width: '<upated further down>',
+ cmp(rowA, rowB) {
+ return rowA.duration - rowB.duration;
+ }
+ });
+ }
+
+ if (this.eventsHaveDuration_ && hasCpuData) {
+ columns.push({
+ title: 'CPU Duration',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.cpuDuration, {
+ unit: tr.b.Unit.byName.timeDurationInMs,
+ customContextRange: row.totalsRow ? undefined :
+ tr.b.math.Range.fromExplicitRange(0, maxValues.cpuDuration),
+ ownerDocument,
+ });
+ },
+ width: '<upated further down>',
+ cmp(rowA, rowB) {
+ return rowA.cpuDuration - rowB.cpuDuration;
+ }
+ });
+ }
+
+ if (this.eventsHaveSubRows_ && this.eventsHaveDuration_) {
+ columns.push({
+ title: 'Self time',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.selfTime, {
+ unit: tr.b.Unit.byName.timeDurationInMs,
+ customContextRange: row.totalsRow ? undefined :
+ tr.b.math.Range.fromExplicitRange(0, maxValues.selfTime),
+ ownerDocument,
+ });
+ },
+ width: '<upated further down>',
+ cmp(rowA, rowB) {
+ return rowA.selfTime - rowB.selfTime;
+ }
+ });
+ }
+
+ if (this.eventsHaveSubRows_ && this.eventsHaveDuration_ && hasCpuData) {
+ columns.push({
+ title: 'CPU Self Time',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.cpuSelfTime, {
+ unit: tr.b.Unit.byName.timeDurationInMs,
+ customContextRange: row.totalsRow ? undefined :
+ tr.b.math.Range.fromExplicitRange(0, maxValues.cpuSelfTime),
+ ownerDocument,
+ });
+ },
+ width: '<upated further down>',
+ cmp(rowA, rowB) {
+ return rowA.cpuSelfTime - rowB.cpuSelfTime;
+ }
+ });
+ }
+
+ if (this.eventsHaveDuration_) {
+ columns.push({
+ title: 'Average ' + (hasCpuData ? 'CPU' : 'Wall') + ' Duration',
+ value(row) {
+ const totalDuration = hasCpuData ? row.cpuDuration : row.duration;
+ return tr.v.ui.createScalarSpan(totalDuration / row.numEvents, {
+ unit: tr.b.Unit.byName.timeDurationInMs,
+ customContextRange: row.totalsRow ? undefined :
+ tr.b.math.Range.fromExplicitRange(0, maxValues.duration),
+ ownerDocument,
+ });
+ },
+ width: '<upated further down>',
+ cmp(rowA, rowB) {
+ if (hasCpuData) {
+ return rowA.cpuDuration / rowA.numEvents -
+ rowB.cpuDuration / rowB.numEvents;
+ }
+ return rowA.duration / rowA.numEvents -
+ rowB.duration / rowB.numEvents;
+ }
+ });
+ }
+
+ columns.push({
+ title: 'Occurrences',
+ value(row) {
+ return row.numEvents;
+ },
+ width: '<upated further down>',
+ cmp(rowA, rowB) {
+ return rowA.numEvents - rowB.numEvents;
+ }
+ });
+
+ let alertsColumnIndex;
+ if (hasAlerts) {
+ columns.push({
+ title: 'Num Alerts',
+ value(row) {
+ return row.numAlerts;
+ },
+ width: '<upated further down>',
+ cmp(rowA, rowB) {
+ return rowA.numAlerts - rowB.numAlerts;
+ }
+ });
+ alertsColumnIndex = columns.length - 1;
+ }
+ let colWidthPercentage;
+ if (columns.length === 1) {
+ colWidthPercentage = '100%';
+ } else {
+ colWidthPercentage = (100 / (columns.length - 1)).toFixed(3) + '%';
+ }
+
+ for (let i = 1; i < columns.length; i++) {
+ columns[i].width = colWidthPercentage;
+ }
+
+ this.$.table.tableColumns = columns;
+
+ if (hasAlerts) {
+ this.$.table.sortColumnIndex = alertsColumnIndex;
+ this.$.table.sortDescending = true;
+ }
+ },
+
+ configure(config) {
+ if (config.eventsByTitle === undefined) {
+ throw new Error('Required: eventsByTitle');
+ }
+
+ if (config.showTotals !== undefined) {
+ this.showTotals_ = config.showTotals;
+ } else {
+ this.showTotals_ = true;
+ }
+
+ if (config.eventsHaveDuration !== undefined) {
+ this.eventsHaveDuration_ = config.eventsHaveDuration;
+ } else {
+ this.eventsHaveDuration_ = true;
+ }
+
+ if (config.eventsHaveSubRows !== undefined) {
+ this.eventsHaveSubRows_ = config.eventsHaveSubRows;
+ } else {
+ this.eventsHaveSubRows_ = true;
+ }
+
+ this.eventsByTitle_ = config.eventsByTitle;
+ this.updateContents_();
+ },
+
+ get showTotals() {
+ return this.showTotals_;
+ },
+
+ set showTotals(showTotals) {
+ this.showTotals_ = showTotals;
+ this.updateContents_();
+ },
+
+ get eventsHaveDuration() {
+ return this.eventsHaveDuration_;
+ },
+
+ set eventsHaveDuration(eventsHaveDuration) {
+ this.eventsHaveDuration_ = eventsHaveDuration;
+ this.updateContents_();
+ },
+
+ get eventsHaveSubRows() {
+ return this.eventsHaveSubRows_;
+ },
+
+ set eventsHaveSubRows(eventsHaveSubRows) {
+ this.eventsHaveSubRows_ = eventsHaveSubRows;
+ this.updateContents_();
+ },
+
+ get eventsByTitle() {
+ return this.eventsByTitle_;
+ },
+
+ set eventsByTitle(eventsByTitle) {
+ this.eventsByTitle_ = eventsByTitle;
+ this.updateContents_();
+ },
+
+ get selectionBounds() {
+ return this.selectionBounds_;
+ },
+
+ set selectionBounds(selectionBounds) {
+ this.selectionBounds_ = selectionBounds;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ let eventsByTitle;
+ if (this.eventsByTitle_ !== undefined) {
+ eventsByTitle = this.eventsByTitle_;
+ } else {
+ eventsByTitle = [];
+ }
+
+ const allEvents = new tr.model.EventSet();
+ const rows = [];
+ for (const [title, eventsOfSingleTitle] of Object.entries(eventsByTitle)) {
+ for (const event of eventsOfSingleTitle) allEvents.push(event);
+ const row = new tr.ui.analysis.MultiEventSummary(
+ title, eventsOfSingleTitle);
+ rows.push(row);
+ }
+
+ this.updateTableColumns_(rows);
+ this.$.table.tableRows = rows;
+
+ const maxValues = {
+ duration: undefined,
+ selfTime: undefined,
+ cpuSelfTime: undefined,
+ cpuDuration: undefined
+ };
+
+ if (this.eventsHaveDuration) {
+ for (const column in maxValues) {
+ maxValues[column] = tr.b.math.Statistics.max(rows, function(event) {
+ return event[column];
+ });
+ }
+ }
+
+ const footerRows = [];
+
+ if (this.showTotals_) {
+ const multiEventSummary = new tr.ui.analysis.MultiEventSummary(
+ 'Totals', allEvents);
+ footerRows.push(multiEventSummary);
+ }
+
+
+ this.updateTableColumns_(rows, maxValues);
+ this.$.table.tableRows = rows;
+
+ // TODO(selection bounds).
+
+ // TODO(sorting)
+
+ this.$.table.footerRows = footerRows;
+ this.$.table.rebuild();
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_table_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_table_test.html
new file mode 100644
index 00000000000..32efc0de1ff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_table_test.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_summary_table.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const EventSet = tr.model.EventSet;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ test('basicNoCpu', function() {
+ const model = new Model();
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ const tsg = thread.sliceGroup;
+ tsg.pushSlice(newSliceEx({title: 'a', start: 0, duration: 0.5}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 1, duration: 0.5}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 2, duration: 0.5}));
+ tsg.createSubSlices();
+
+ const threadTrack = {};
+ threadTrack.thread = thread;
+
+ const selection = new EventSet(tsg.slices);
+
+ const viewEl = document.createElement('tr-ui-a-multi-event-summary-table');
+ viewEl.configure({
+ showTotals: true,
+ eventsHaveDuration: true,
+ eventsByTitle: selection.getEventsOrganizedByTitle()
+ });
+ this.addHTMLOutput(viewEl);
+ });
+
+ test('basicWithCpu', function() {
+ const model = new Model();
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ const tsg = thread.sliceGroup;
+ tsg.pushSlice(newSliceEx({title: 'a', start: 0, end: 3,
+ cpuStart: 0, cpuEnd: 3}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 1, end: 2,
+ cpuStart: 1, cpuEnd: 1.75}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 4, end: 5,
+ cpuStart: 3, cpuEnd: 3.75}));
+ tsg.createSubSlices();
+
+ const threadTrack = {};
+ threadTrack.thread = thread;
+
+ const selection = new EventSet(tsg.slices);
+
+ const viewEl = document.createElement('tr-ui-a-multi-event-summary-table');
+ viewEl.configure({
+ showTotals: true,
+ eventsHaveDuration: true,
+ eventsByTitle: selection.getEventsOrganizedByTitle()
+ });
+ this.addHTMLOutput(viewEl);
+
+ const totals = tr.ui.b.findDeepElementMatchingPredicate(
+ viewEl, e => e.tagName === 'TFOOT');
+ const scalars = tr.ui.b.findDeepElementsMatchingPredicate(
+ totals, e => e.tagName === 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(scalars[0].value, 5);
+ assert.closeTo(scalars[1].value, 4.5, 1e-6);
+ assert.strictEqual(scalars[2].value, 4);
+ assert.closeTo(scalars[3].value, 3.75, 1e-6);
+ assert.closeTo(scalars[4].value, 1.5, 1e-6);
+ assert.strictEqual('3', totals.children[0].children[6].textContent);
+ });
+
+ test('noSelfTimeNoSubRows', function() {
+ const model = new Model();
+
+ const fe1 = new tr.model.FlowEvent('cat', 1234, 'title', 7, 10, {});
+ const fe2 = new tr.model.FlowEvent('cat', 1234, 'title', 8, 20, {});
+
+ // Make reading some properties an explosion, as a way to ensure that they
+ // aren't read. Note that 'duration' is read since it is used by the
+ // EventSet to get the range.
+ const failProp = {
+ get() {
+ throw new Error('Should not be called');
+ }
+ };
+ Object.defineProperty(fe1, 'subRows', failProp);
+ Object.defineProperty(fe2, 'subRows', failProp);
+
+ Object.defineProperty(fe1, 'selfTime', failProp);
+ Object.defineProperty(fe2, 'selfTime', failProp);
+
+ model.flowEvents.push(fe1);
+ model.flowEvents.push(fe2);
+
+ const selection = new EventSet([fe1, fe2]);
+
+ const viewEl = document.createElement('tr-ui-a-multi-event-summary-table');
+ viewEl.configure({
+ showTotals: true,
+ eventsHaveDuration: false,
+ eventsHaveSubRows: false,
+ eventsByTitle: selection.getEventsOrganizedByTitle()
+ });
+ this.addHTMLOutput(viewEl);
+ });
+
+ // TODO(nduca): Tooltippish stuff.
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_test.html
new file mode 100644
index 00000000000..fcc73e1d608
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_event_summary_test.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_summary.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ test('summaryRowNoCpu', function() {
+ const model = new Model();
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ const tsg = thread.sliceGroup;
+
+ tsg.pushSlice(newSliceEx({title: 'a', start: 0, end: 3}));
+ tsg.pushSlice(newSliceEx({title: 'bb', start: 1, end: 2}));
+ tsg.pushSlice(newSliceEx({title: 'bb', start: 4, end: 5}));
+ tsg.createSubSlices();
+
+ const row = new tr.ui.analysis.MultiEventSummary('x', tsg.slices.slice(0));
+ assert.strictEqual(row.duration, 5);
+ assert.strictEqual(row.selfTime, 4);
+ assert.isUndefined(row.cpuDuration);
+ assert.isUndefined(row.cpuSelfTime);
+ });
+
+ test('summaryRowWithCpu', function() {
+ const model = new Model();
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ const tsg = thread.sliceGroup;
+
+ tsg.pushSlice(newSliceEx({title: 'a', start: 0, end: 3,
+ cpuStart: 0, cpuEnd: 3}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 1, end: 2,
+ cpuStart: 1, cpuEnd: 1.75}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 4, end: 5,
+ cpuStart: 3, cpuEnd: 3.75}));
+ tsg.createSubSlices();
+
+ const row = new tr.ui.analysis.MultiEventSummary('x', tsg.slices.slice(0));
+ assert.strictEqual(row.duration, 5);
+ assert.strictEqual(row.selfTime, 4);
+ assert.strictEqual(row.cpuDuration, 4.5);
+ assert.strictEqual(row.cpuSelfTime, 3.75);
+ assert.strictEqual(row.maxDuration, 3);
+ assert.strictEqual(row.maxSelfTime, 2);
+ assert.strictEqual(row.maxCpuDuration, 3);
+ assert.strictEqual(row.maxCpuSelfTime, 2.25);
+ });
+
+ test('summaryRowNonSlice', function() {
+ const model = new Model();
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ const tsg = thread.sliceGroup;
+
+ const fe1 = new tr.model.FlowEvent('cat', 1234, 'title', 7, 10, {});
+ const fe2 = new tr.model.FlowEvent('cat', 1234, 'title', 8, 20, {});
+ model.flowEvents.push(fe1);
+ model.flowEvents.push(fe2);
+
+ const row = new tr.ui.analysis.MultiEventSummary('a', [fe1, fe2]);
+ assert.strictEqual(row.duration, 0);
+ assert.strictEqual(row.selfTime, 0);
+ assert.isUndefined(row.cpuDuration);
+ assert.isUndefined(row.cpuSelfTime);
+ assert.strictEqual(row.maxDuration, 0);
+ });
+
+ test('summaryNumAlerts', function() {
+ const slice = newSliceEx({title: 'b', start: 0, duration: 0.002});
+
+ const ALERT_INFO_1 = new tr.model.EventInfo(
+ 'Alert 1', 'Critical alert');
+
+ const alert = new tr.model.Alert(ALERT_INFO_1, 5, [slice]);
+
+ const row = new tr.ui.analysis.MultiEventSummary('a', [slice]);
+ assert.strictEqual(row.numAlerts, 1);
+ });
+
+ test('argSummary', function() {
+ const model = new Model();
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ const tsg = thread.sliceGroup;
+
+ tsg.pushSlice(newSliceEx({title: 'a', start: 0, end: 3,
+ args: {value1: 3, value2: 'x', value3: 1}}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 1, end: 2,
+ args: {value1: 3, value2: 'y', value3: 2}}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 4, end: 5,
+ args: {value1: 3, value2: 'z', value3: 'x'}}));
+ tsg.createSubSlices();
+
+ const row = new tr.ui.analysis.MultiEventSummary('x', tsg.slices.slice(0));
+ assert.deepEqual(row.totalledArgs, {value1: 9});
+ assert.deepEqual(row.untotallableArgs, ['value2', 'value3']);
+ assert.strictEqual(row.maxDuration, 3);
+ assert.strictEqual(row.maxSelfTime, 2);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_flow_event_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_flow_event_sub_view.html
new file mode 100644
index 00000000000..3e509508732
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_flow_event_sub_view.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+
+<dom-module id='tr-ui-a-multi-flow-event-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ }
+ </style>
+ <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-flow-event-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ ready() {
+ this.$.content.eventsHaveDuration = false;
+ this.$.content.eventsHaveSubRows = false;
+ },
+
+ set selection(selection) {
+ this.$.content.selection = selection;
+ },
+
+ get selection() {
+ return this.$.content.selection;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-flow-event-sub-view',
+ tr.model.FlowEvent,
+ {
+ multi: true,
+ title: 'Flow Events',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_flow_event_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_flow_event_sub_view_test.html
new file mode 100644
index 00000000000..8b1d98d7bd1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_flow_event_sub_view_test.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const EventSet = tr.model.EventSet;
+
+ test('analyzeSelectionWithSingleEvent', function() {
+ const model = new Model();
+
+ const fe1 = new tr.model.FlowEvent('cat', 1234, 'title', 7, 10, {});
+ const fe2 = new tr.model.FlowEvent('cat', 1234, 'title', 8, 20, {});
+ model.flowEvents.push(fe1);
+ model.flowEvents.push(fe2);
+
+ const selection = new EventSet();
+ selection.push(fe1);
+ selection.push(fe2);
+ assert.strictEqual(selection.length, 2);
+
+ const subView = document.createElement('tr-ui-a-multi-flow-event-sub-view');
+ subView.selection = selection;
+
+ this.addHTMLOutput(subView);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_frame_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_frame_sub_view.html
new file mode 100644
index 00000000000..cdf71245df3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_frame_sub_view.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-frame-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ set selection(selection) {
+ Polymer.dom(this).textContent = '';
+ const realView = document.createElement('tr-ui-a-multi-event-sub-view');
+ realView.eventsHaveDuration = false;
+ realView.eventsHaveSubRows = false;
+
+ Polymer.dom(this).appendChild(realView);
+ realView.setSelectionWithoutErrorChecks(selection);
+
+ this.currentSelection_ = selection;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ get relatedEventsToHighlight() {
+ if (!this.currentSelection_) return undefined;
+
+ const selection = new tr.model.EventSet();
+ this.currentSelection_.forEach(function(frameEvent) {
+ frameEvent.associatedEvents.forEach(function(event) {
+ selection.push(event);
+ });
+ });
+ return selection;
+ }
+});
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-frame-sub-view',
+ tr.model.Frame,
+ {
+ multi: true,
+ title: 'Frames',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_instant_event_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_instant_event_sub_view.html
new file mode 100644
index 00000000000..c2252f90e14
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_instant_event_sub_view.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+
+<dom-module id='tr-ui-a-multi-instant-event-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+ </style>
+ <div id='content'></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-instant-event-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ set selection(selection) {
+ Polymer.dom(this.$.content).textContent = '';
+ const realView = document.createElement('tr-ui-a-multi-event-sub-view');
+ realView.eventsHaveDuration = false;
+ realView.eventsHaveSubRows = false;
+
+ Polymer.dom(this.$.content).appendChild(realView);
+ realView.setSelectionWithoutErrorChecks(selection);
+
+ this.currentSelection_ = selection;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_instant_event_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_instant_event_sub_view_test.html
new file mode 100644
index 00000000000..ca228515de5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_instant_event_sub_view_test.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const EventSet = tr.model.EventSet;
+
+ test('analyzeSelectionWithSingleEvent', function() {
+ const model = new Model();
+ const p52 = model.getOrCreateProcess(52);
+ const t53 = p52.getOrCreateThread(53);
+
+ const ie1 = new tr.model.ProcessInstantEvent('cat', 'title', 7, 10, {});
+ const ie2 = new tr.model.ProcessInstantEvent('cat', 'title', 7, 20, {});
+ p52.instantEvents.push(ie1);
+ p52.instantEvents.push(ie2);
+
+
+ const selection = new EventSet();
+ selection.push(ie1);
+ selection.push(ie2);
+ assert.strictEqual(selection.length, 2);
+
+ const subView =
+ document.createElement('tr-ui-a-multi-instant-event-sub-view');
+ subView.selection = selection;
+
+ this.addHTMLOutput(subView);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_object_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_object_sub_view.html
new file mode 100644
index 00000000000..089f4b011a2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_object_sub_view.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-multi-object-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="content"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-object-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ ready() {
+ this.$.content.showHeader = false;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+
+ const objectEvents = Array.from(selection).sort(
+ tr.b.math.Range.compareByMinTimes);
+
+ const timeSpanConfig = {
+ unit: tr.b.Unit.byName.timeStampInMs,
+ ownerDocument: this.ownerDocument
+ };
+ const table = this.$.content;
+ table.tableColumns = [
+ {
+ title: 'First',
+ value(event) {
+ if (event instanceof tr.model.ObjectSnapshot) {
+ return tr.v.ui.createScalarSpan(event.ts, timeSpanConfig);
+ }
+
+ const spanEl = document.createElement('span');
+ Polymer.dom(spanEl).appendChild(tr.v.ui.createScalarSpan(
+ event.creationTs, timeSpanConfig));
+ Polymer.dom(spanEl).appendChild(tr.ui.b.createSpan({
+ textContent: '-',
+ marginLeft: '4px',
+ marginRight: '4px'
+ }));
+ if (event.deletionTs !== Number.MAX_VALUE) {
+ Polymer.dom(spanEl).appendChild(tr.v.ui.createScalarSpan(
+ event.deletionTs, timeSpanConfig));
+ }
+ return spanEl;
+ },
+ width: '200px'
+ },
+ {
+ title: 'Second',
+ value(event) {
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(function() {
+ return new tr.model.EventSet(event);
+ }, event.userFriendlyName);
+ return linkEl;
+ },
+ width: '100%'
+ }
+ ];
+ table.tableRows = objectEvents;
+ table.rebuild();
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-object-sub-view',
+ tr.model.ObjectInstance,
+ {
+ multi: true,
+ title: 'Object Instances',
+ });
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-object-sub-view',
+ tr.model.ObjectSnapshot,
+ {
+ multi: true,
+ title: 'Object Snapshots',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_object_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_object_sub_view_test.html
new file mode 100644
index 00000000000..18e62170e7d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_object_sub_view_test.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventSet = tr.model.EventSet;
+ const ObjectInstance = tr.model.ObjectInstance;
+
+ test('instantiate_analysisWithObjects', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const objects = p1.objects;
+ const i10 = objects.idWasCreated(
+ '0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 10);
+ const s10 = objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl',
+ 10, 'snapshot-1');
+ const s25 = objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl',
+ 25, 'snapshot-2');
+ const s40 = objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl',
+ 40, 'snapshot-3');
+ objects.idWasDeleted('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 45);
+
+ const track = {};
+ const selection = new EventSet();
+ selection.push(i10);
+ selection.push(s10);
+ selection.push(s25);
+ selection.push(s40);
+
+ const analysisEl = document.createElement('tr-ui-a-multi-object-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_power_sample_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_power_sample_sub_view.html
new file mode 100644
index 00000000000..32315c220a1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_power_sample_sub_view.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/frame_power_usage_chart.html">
+<link rel="import" href="/tracing/ui/analysis/power_sample_summary_table.html">
+
+<dom-module id='tr-ui-a-multi-power-sample-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: row;
+ }
+ #tables {
+ display: flex;
+ flex-direction: column;
+ width: 50%;
+ }
+ #chart {
+ width: 50%;
+ }
+ </style>
+ <div id="tables">
+ <tr-ui-a-power-sample-summary-table id="summaryTable">
+ </tr-ui-a-power-sample-summary-table>
+ </div>
+ <tr-ui-a-frame-power-usage-chart id="chart">
+ </tr-ui-a-frame-power-usage-chart>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+// TODO(charliea): Add a dropdown that allows the user to select which type of
+// power sample analysis view they want (e.g. table of samples, graph).
+Polymer({
+ is: 'tr-ui-a-multi-power-sample-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ ready() {
+ this.currentSelection_ = undefined;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ const samples = this.selection;
+ const vSyncTimestamps = (!samples ? [] :
+ tr.b.getFirstElement(samples).series.device.vSyncTimestamps);
+
+ this.$.summaryTable.samples = samples;
+ this.$.chart.setData(this.selection, vSyncTimestamps);
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-power-sample-sub-view',
+ tr.model.PowerSample,
+ {
+ multi: true,
+ title: 'Power Samples',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_power_sample_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_power_sample_sub_view_test.html
new file mode 100644
index 00000000000..f7759572e28
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_power_sample_sub_view_test.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_series.html">
+<link rel="import" href="/tracing/ui/analysis/multi_power_sample_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate_noSamplesOrVSyncs', function() {
+ const viewEl = document.createElement(
+ 'tr-ui-a-multi-power-sample-sub-view');
+ viewEl.selection = undefined;
+ this.addHTMLOutput(viewEl);
+ });
+
+ test('instantiate_noVSyncs', function() {
+ const model = new tr.Model();
+ const series = new tr.model.PowerSeries(model.device);
+
+ model.device.vSyncTimestamps = [];
+ series.addPowerSample(1, 1);
+ series.addPowerSample(2, 2);
+ series.addPowerSample(3, 3);
+ series.addPowerSample(4, 2);
+
+ const view = document.createElement('tr-ui-a-multi-power-sample-sub-view');
+ const eventSet = new tr.model.EventSet(series.samples);
+ view.selection = eventSet;
+
+ this.addHTMLOutput(view);
+
+ assert.deepEqual(view.$.chart.samples, eventSet);
+ assert.sameDeepMembers(view.$.chart.vSyncTimestamps, []);
+ });
+
+ test('instantiate', function() {
+ const model = new tr.Model();
+ const series = new tr.model.PowerSeries(model.device);
+
+ model.device.vSyncTimestamps = [0];
+ series.addPowerSample(1, 1);
+ series.addPowerSample(2, 2);
+ series.addPowerSample(3, 3);
+ series.addPowerSample(4, 2);
+
+ const view = document.createElement('tr-ui-a-multi-power-sample-sub-view');
+ const eventSet = new tr.model.EventSet(series.samples);
+ view.selection = eventSet;
+
+ this.addHTMLOutput(view);
+
+ assert.deepEqual(view.$.chart.samples, eventSet);
+ assert.sameDeepMembers(view.$.chart.vSyncTimestamps, [0]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view.html
new file mode 100644
index 00000000000..1737894f875
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/multi_dimensional_view.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-multi-sample-sub-view'>
+ <template>
+ <style>
+ :host { display: block; }
+ #control {
+ background-color: #e6e6e6;
+ background-image: -webkit-gradient(linear, 0 0, 0 100%,
+ from(#E5E5E5), to(#D1D1D1));
+ flex: 0 0 auto;
+ overflow-x: auto;
+ }
+ #control::-webkit-scrollbar { height: 0px; }
+ #control {
+ font-size: 12px;
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+ margin: 1px;
+ margin-right: 2px;
+ }
+ tr-ui-b-table {
+ font-size: 12px;
+ }
+ </style>
+ <div id="control">
+ Sample View Option
+ </div>
+ <tr-ui-b-table id="table">
+ </tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+(function() {
+ const MultiDimensionalViewBuilder = tr.b.MultiDimensionalViewBuilder;
+
+ Polymer({
+ is: 'tr-ui-a-multi-sample-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.viewOption_ = undefined;
+ this.selection_ = undefined;
+ },
+
+ ready() {
+ const viewSelector = tr.ui.b.createSelector(
+ this, 'viewOption', 'tracing.ui.analysis.multi_sample_sub_view',
+ MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW,
+ [
+ {
+ label: 'Top-down (Tree)',
+ value: MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW
+ },
+ {
+ label: 'Top-down (Heavy)',
+ value: MultiDimensionalViewBuilder.ViewType.TOP_DOWN_HEAVY_VIEW
+ },
+ {
+ label: 'Bottom-up (Heavy)',
+ value: MultiDimensionalViewBuilder.ViewType.BOTTOM_UP_HEAVY_VIEW
+ }
+ ]);
+ Polymer.dom(this.$.control).appendChild(viewSelector);
+ this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ },
+
+ get selection() {
+ return this.selection_;
+ },
+
+ set selection(selection) {
+ this.selection_ = selection;
+ this.updateContents_();
+ },
+
+ get viewOption() {
+ return this.viewOption_;
+ },
+
+ set viewOption(viewOption) {
+ this.viewOption_ = viewOption;
+ this.updateContents_();
+ },
+
+ createSamplingSummary_(selection, viewOption) {
+ const builder = new MultiDimensionalViewBuilder(
+ 1 /* dimensions */, 1 /* valueCount */);
+ const samples = selection.filter(
+ event => event instanceof tr.model.Sample);
+
+ samples.forEach(function(sample) {
+ builder.addPath([sample.userFriendlyStack.reverse()],
+ [1], MultiDimensionalViewBuilder.ValueKind.SELF);
+ });
+
+ return builder.buildView(viewOption);
+ },
+
+ processSampleRows_(rows) {
+ for (const row of rows) {
+ let title = row.title[0];
+ let results = /(.*) (Deoptimized reason: .*)/.exec(title);
+ if (results !== null) {
+ row.deoptReason = results[2];
+ title = results[1];
+ }
+ results = /(.*) url: (.*)/.exec(title);
+ if (results !== null) {
+ row.functionName = results[1];
+ row.url = results[2];
+ if (row.functionName === '') {
+ row.functionName = '(anonymous function)';
+ }
+ if (row.url === '') {
+ row.url = 'unknown';
+ }
+ } else {
+ row.functionName = title;
+ row.url = 'unknown';
+ }
+ this.processSampleRows_(row.subRows);
+ }
+ },
+
+ updateContents_() {
+ if (this.selection === undefined) {
+ this.$.table.tableColumns = [];
+ this.$.table.tableRows = [];
+ this.$.table.rebuild();
+ return;
+ }
+
+ const samplingData = this.createSamplingSummary_(
+ this.selection, this.viewOption);
+ const total = samplingData.values[0].total;
+ const columns = [
+ this.createPercentColumn_('Total', total),
+ this.createSamplesColumn_('Total'),
+ this.createPercentColumn_('Self', total),
+ this.createSamplesColumn_('Self'),
+ {
+ title: 'Function Name',
+ value(row) {
+ // For function that got deoptimized, show function name
+ // as red italic with a tooltip
+ if (row.deoptReason !== undefined) {
+ const spanEl = tr.ui.b.createSpan({
+ italic: true,
+ color: '#F44336',
+ tooltip: row.deoptReason
+ });
+ spanEl.innerText = row.functionName;
+ return spanEl;
+ }
+ return row.functionName;
+ },
+ width: '150px',
+ cmp: (a, b) => a.functionName.localeCompare(b.functionName),
+ showExpandButtons: true
+ },
+ {
+ title: 'Location',
+ value(row) { return row.url; },
+ width: '250px',
+ cmp: (a, b) => a.url.localeCompare(b.url),
+ }
+ ];
+
+ this.processSampleRows_(samplingData.subRows);
+ this.$.table.tableColumns = columns;
+ this.$.table.sortColumnIndex = 1; /* Total samples */
+ this.$.table.sortDescending = true;
+ this.$.table.tableRows = samplingData.subRows;
+ this.$.table.rebuild();
+ },
+
+ createPercentColumn_(title, samplingDataTotal) {
+ const field = title.toLowerCase();
+ return {
+ title: title + ' percent',
+ value(row) {
+ return tr.v.ui.createScalarSpan(
+ row.values[0][field] / samplingDataTotal, {
+ customContextRange: tr.b.math.Range.PERCENT_RANGE,
+ unit: tr.b.Unit.byName.normalizedPercentage,
+ context: { minimumFractionDigits: 2, maximumFractionDigits: 2 },
+ });
+ },
+ width: '60px',
+ cmp: (a, b) => a.values[0][field] - b.values[0][field]
+ };
+ },
+
+ createSamplesColumn_(title) {
+ const field = title.toLowerCase();
+ return {
+ title: title + ' samples',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.values[0][field], {
+ unit: tr.b.Unit.byName.unitlessNumber,
+ context: { maximumFractionDigits: 0 },
+ });
+ },
+ width: '60px',
+ cmp: (a, b) => a.values[0][field] - b.values[0][field]
+ };
+ }
+ });
+
+ tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-sample-sub-view',
+ tr.model.Sample,
+ {
+ multi: true,
+ title: 'Samples',
+ });
+})();
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view_test.html
new file mode 100644
index 00000000000..e148a2d7c95
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_sample_sub_view_test.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/multi_sample_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSampleNamed = tr.c.TestUtils.newSampleNamed;
+
+ function instantiateWithTraces(traces) {
+ let t53;
+ const m = tr.c.TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback(model) {
+ t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
+ traces.forEach(function(trace, index) {
+ model.samples.push(
+ newSampleNamed(t53, 'X', 'cat', trace, index * 0.02));
+ });
+ }
+ });
+
+ const t53track = {};
+ t53track.thread = t53;
+
+ const selection = new tr.model.EventSet();
+ for (let i = 0; i < t53.samples.length; i++) {
+ selection.push(t53.samples[i]);
+ }
+
+ const view = document.createElement('tr-ui-a-multi-sample-sub-view');
+ view.style.height = '500px';
+ this.addHTMLOutput(view);
+ view.selection = selection;
+ return view;
+ }
+
+ test('instantiate_flat', function() {
+ instantiateWithTraces.call(this, [
+ ['BBB'],
+ ['AAA'],
+ ['AAA'],
+ ['Sleeping'],
+ ['BBB'],
+ ['AAA'],
+ ['CCC'],
+ ['Sleeping']
+ ]);
+ });
+
+ test('instantiate_nested', function() {
+ instantiateWithTraces.call(this, [
+ ['AAA', 'BBB'],
+ ['AAA', 'BBB', 'CCC'],
+ ['AAA', 'BBB'],
+ ['BBB', 'AAA', 'BBB'],
+ ['BBB', 'AAA', 'BBB'],
+ ['BBB', 'AAA', 'BBB']
+ ]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view.html
new file mode 100644
index 00000000000..b896a7bf699
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/related_events.html">
+
+<dom-module id='tr-ui-a-multi-thread-slice-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ }
+ #content {
+ display: flex;
+ flex: 1 1 auto;
+ min-width: 0;
+ }
+ #content > tr-ui-a-related-events {
+ margin-left: 8px;
+ flex: 0 1 200px;
+ }
+ </style>
+ <div id="content"></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-thread-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.selection_ = undefined;
+ },
+
+ get selection() {
+ return this.selection_;
+ },
+
+ set selection(selection) {
+ this.selection_ = selection;
+
+ // TODO(nduca): This is a gross hack for cc Frame Viewer, but its only
+ // the frame viewer that needs this feature, so ~shrug~.
+ // We check for its presence so that we do not have a hard dependency
+ // on frame viewer.
+ if (tr.isExported('tr.ui.e.chrome.cc.RasterTaskSelection')) {
+ if (tr.ui.e.chrome.cc.RasterTaskSelection.supports(selection)) {
+ const ltvSelection = new tr.ui.e.chrome.cc.RasterTaskSelection(
+ selection);
+
+ const ltv = new tr.ui.e.chrome.cc.LayerTreeHostImplSnapshotView();
+ ltv.objectSnapshot = ltvSelection.containingSnapshot;
+ ltv.selection = ltvSelection;
+ ltv.extraHighlightsByLayerId = ltvSelection.extraHighlightsByLayerId;
+
+ Polymer.dom(this.$.content).textContent = '';
+ Polymer.dom(this.$.content).appendChild(ltv);
+
+ this.requiresTallView_ = true;
+ return;
+ }
+ }
+
+ Polymer.dom(this.$.content).textContent = '';
+
+ const mesv = document.createElement('tr-ui-a-multi-event-sub-view');
+ mesv.selection = selection;
+ Polymer.dom(this.$.content).appendChild(mesv);
+
+ const relatedEvents = document.createElement('tr-ui-a-related-events');
+ relatedEvents.setRelatedEvents(selection);
+
+ if (relatedEvents.hasRelatedEvents()) {
+ Polymer.dom(this.$.content).appendChild(relatedEvents);
+ }
+ },
+
+ get requiresTallView() {
+ if (this.$.content.children.length === 0) return false;
+ const childTagName = this.$.content.children[0].tagName;
+ if (childTagName === 'TR-UI-A-MULTI-EVENT-SUB-VIEW') {
+ return false;
+ }
+
+ // Using raster task view.
+ return true;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-thread-slice-sub-view',
+ tr.model.ThreadSlice,
+ {
+ multi: true,
+ title: 'Slices',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view_test.html
new file mode 100644
index 00000000000..a44419cf536
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_slice_sub_view_test.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+<link rel="import" href="/tracing/ui/analysis/multi_thread_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newFlowEventEx = tr.c.TestUtils.newFlowEventEx;
+
+ test('instantiate', function() {
+ const model = new tr.Model();
+ const t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
+ t53.sliceGroup.pushSlice(
+ newSliceEx({title: 'a', start: 0.0, duration: 0.5,
+ type: tr.model.ThreadSlice}));
+ t53.sliceGroup.pushSlice(
+ newSliceEx({title: 'b', start: 1.0, duration: 2,
+ type: tr.model.ThreadSlice}));
+ t53.sliceGroup.createSubSlices();
+
+ const selection = new tr.model.EventSet();
+ selection.push(t53.sliceGroup.slices[0]);
+ selection.push(t53.sliceGroup.slices[1]);
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-multi-thread-slice-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ });
+
+ test('withFlows', function() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+
+ m.t2 = m.p1.getOrCreateThread(2);
+ m.t3 = m.p1.getOrCreateThread(3);
+ m.t4 = m.p1.getOrCreateThread(4);
+
+ m.sA = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'a', start: 0, end: 5,
+ type: tr.model.ThreadSlice}));
+ m.sB = m.t3.sliceGroup.pushSlice(
+ newSliceEx({title: 'b', start: 10, end: 15,
+ type: tr.model.ThreadSlice}));
+ m.sC = m.t4.sliceGroup.pushSlice(
+ newSliceEx({title: 'c', start: 20, end: 20,
+ type: tr.model.ThreadSlice}));
+
+ m.t2.createSubSlices();
+ m.t3.createSubSlices();
+ m.t4.createSubSlices();
+
+ m.f1 = newFlowEventEx({
+ title: 'flowish', start: 0, end: 10,
+ startSlice: m.sA,
+ endSlice: m.sB
+ });
+ m.f2 = newFlowEventEx({
+ title: 'flowish', start: 15, end: 21,
+ startSlice: m.sB,
+ endSlice: m.sC
+ });
+ });
+
+ const selection = new tr.model.EventSet();
+ selection.push(m.sA);
+ selection.push(m.sB);
+ selection.push(m.sC);
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-multi-thread-slice-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view.html
new file mode 100644
index 00000000000..f1f0666fc43
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+
+<dom-module id='tr-ui-a-multi-thread-time-slice-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ }
+ #content {
+ flex: 1 1 auto;
+ min-width: 0;
+ }
+ </style>
+ <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-thread-time-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ ready() {
+ this.$.content.eventsHaveSubRows = false;
+ },
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.content.setSelectionWithoutErrorChecks(selection);
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-thread-time-slice-sub-view',
+ tr.model.ThreadTimeSlice,
+ {
+ multi: true,
+ title: 'Thread Timeslices',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view_test.html
new file mode 100644
index 00000000000..e3489fe1c9c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_thread_time_slice_sub_view_test.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/multi_thread_time_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createBasicModel() {
+ const lines = [
+ 'Android.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D ==> next_comm=Android.launcher next_pid=584 next_prio=120', // @suppress longLineCheck
+ 'Android.launcher-584 [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001', // @suppress longLineCheck
+ 'Android.launcher-584 [001] d..3 12622.506950: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: B|128|queueBuffer', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E',
+ ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
+ ];
+
+ return tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('instantiate', function() {
+ const m = createBasicModel();
+
+ const thread = m.findAllThreadsNamed('Binder_1')[0];
+
+ const selection = new tr.model.EventSet();
+ selection.push(thread.timeSlices[0]);
+ selection.push(thread.timeSlices[1]);
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-multi-thread-time-slice-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_user_expectation_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_user_expectation_sub_view.html
new file mode 100644
index 00000000000..b89e3fd0724
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/multi_user_expectation_sub_view.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_event_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/user_expectation_related_samples_table.html">
+
+<dom-module id='tr-ui-a-multi-user-expectation-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex: 1 1 auto;
+ }
+ #events {
+ margin-left: 8px;
+ flex: 0 1 200px;
+ }
+ </style>
+ <tr-ui-a-multi-event-sub-view id="realView"></tr-ui-a-multi-event-sub-view>
+ <div id="events">
+ <tr-ui-a-user-expectation-related-samples-table id="relatedSamples"></tr-ui-a-user-expectation-related-samples-table>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-multi-interaction-record-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+ this.$.realView.setSelectionWithoutErrorChecks(selection);
+
+ this.currentSelection_ = selection;
+
+ this.$.relatedSamples.selection = selection;
+ if (this.$.relatedSamples.hasRelatedSamples()) {
+ this.$.events.style.display = '';
+ } else {
+ this.$.events.style.display = 'none';
+ }
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ get relatedEventsToHighlight() {
+ if (!this.currentSelection_) return undefined;
+
+ const selection = new tr.model.EventSet();
+ this.currentSelection_.forEach(function(ir) {
+ ir.associatedEvents.forEach(function(event) {
+ selection.push(event);
+ });
+ });
+ return selection;
+ }
+});
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-user-expectation-sub-view',
+ tr.model.um.UserExpectation,
+ {
+ multi: true,
+ title: 'User Expectations',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/object_instance_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/object_instance_view.html
new file mode 100644
index 00000000000..3c76dc8c9e3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/object_instance_view.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const ObjectInstanceView = tr.ui.b.define('object-instance-view');
+
+ ObjectInstanceView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.objectInstance_ = undefined;
+ },
+
+ get requiresTallView() {
+ return true;
+ },
+
+ set modelEvent(obj) {
+ this.objectInstance = obj;
+ },
+
+ get modelEvent() {
+ return this.objectInstance;
+ },
+
+ get objectInstance() {
+ return this.objectInstance_;
+ },
+
+ set objectInstance(i) {
+ this.objectInstance_ = i;
+ this.updateContents();
+ },
+
+ updateContents() {
+ throw new Error('Not implemented');
+ }
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(
+ tr.b.TYPE_BASED_REGISTRY_MODE);
+ options.mandatoryBaseClass = ObjectInstanceView;
+ options.defaultMetadata = {
+ showInTrackView: true
+ };
+ tr.b.decorateExtensionRegistry(ObjectInstanceView, options);
+
+ return {
+ ObjectInstanceView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/object_snapshot_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/object_snapshot_view.html
new file mode 100644
index 00000000000..a42ed0ec02b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/object_snapshot_view.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const ObjectSnapshotView = tr.ui.b.define('object-snapshot-view');
+
+ ObjectSnapshotView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.objectSnapshot_ = undefined;
+ },
+
+ get requiresTallView() {
+ return true;
+ },
+
+ set modelEvent(obj) {
+ this.objectSnapshot = obj;
+ },
+
+ get modelEvent() {
+ return this.objectSnapshot;
+ },
+
+ get objectSnapshot() {
+ return this.objectSnapshot_;
+ },
+
+ set objectSnapshot(i) {
+ this.objectSnapshot_ = i;
+ this.updateContents();
+ },
+
+ updateContents() {
+ throw new Error('Not implemented');
+ }
+ };
+
+ const options = new tr.b.ExtensionRegistryOptions(
+ tr.b.TYPE_BASED_REGISTRY_MODE);
+ options.mandatoryBaseClass = ObjectSnapshotView;
+ options.defaultMetadata = {
+ showInstances: true,
+ showInTrackView: true
+ };
+ tr.b.decorateExtensionRegistry(ObjectSnapshotView, options);
+
+ return {
+ ObjectSnapshotView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/power_sample_summary_table.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/power_sample_summary_table.html
new file mode 100644
index 00000000000..337e4f5ba56
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/power_sample_summary_table.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-a-power-sample-summary-table'>
+ <template>
+ <style>
+ tr-ui-b-table {
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-power-sample-summary-table',
+
+ ready() {
+ this.$.table.tableColumns = [
+ {
+ title: 'Min power',
+ width: '100px',
+ value(row) {
+ return tr.b.Unit.byName.powerInWatts.format(row.min);
+ }
+ },
+ {
+ title: 'Max power',
+ width: '100px',
+ value(row) {
+ return tr.b.Unit.byName.powerInWatts.format(row.max);
+ }
+ },
+ {
+ title: 'Time-weighted average',
+ width: '100px',
+ value(row) {
+ return tr.b.Unit.byName.powerInWatts.format(
+ row.timeWeightedAverageInW);
+ }
+ },
+ {
+ title: 'Energy consumed',
+ width: '100px',
+ value(row) {
+ return tr.b.Unit.byName.energyInJoules.format(row.energyConsumedInJ);
+ }
+ },
+ {
+ title: 'Sample count',
+ width: '100%',
+ value(row) { return row.sampleCount; }
+ }
+ ];
+ this.samples = new tr.model.EventSet();
+ },
+
+ get samples() {
+ return this.samples_;
+ },
+
+ set samples(samples) {
+ if (samples === this.samples) return;
+
+ this.samples_ =
+ (samples === undefined) ? new tr.model.EventSet() : samples;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ if (this.samples.length === 0) {
+ this.$.table.tableRows = [];
+ } else {
+ this.$.table.tableRows = [{
+ min: this.getMin(),
+ max: this.getMax(),
+ timeWeightedAverageInW: this.getTimeWeightedAverageInW(),
+ energyConsumedInJ: this.getEnergyConsumedInJ(),
+ sampleCount: this.samples.length
+ }];
+ }
+
+ this.$.table.rebuild();
+ },
+
+ getMin() {
+ return Math.min.apply(null, this.samples.map(function(sample) {
+ return sample.powerInW;
+ }));
+ },
+
+ getMax() {
+ return Math.max.apply(null, this.samples.map(function(sample) {
+ return sample.powerInW;
+ }));
+ },
+
+ /**
+ * Returns a time-weighted average of the power consumption (Watts)
+ * in between the first sample (inclusive) and last sample (exclusive).
+ */
+ getTimeWeightedAverageInW() {
+ const energyConsumedInJ = this.getEnergyConsumedInJ();
+
+ if (energyConsumedInJ === 'N/A') return 'N/A';
+
+ const durationInS = tr.b.convertUnit(this.samples.bounds.duration,
+ tr.b.UnitPrefixScale.METRIC.MILLI,
+ tr.b.UnitPrefixScale.METRIC.NONE);
+
+ return energyConsumedInJ / durationInS;
+ },
+
+
+ getEnergyConsumedInJ() {
+ if (this.samples.length < 2) return 'N/A';
+
+ const bounds = this.samples.bounds;
+ const series = tr.b.getFirstElement(this.samples).series;
+ return series.getEnergyConsumedInJ(bounds.min, bounds.max);
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/power_sample_summary_table_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/power_sample_summary_table_test.html
new file mode 100644
index 00000000000..f5bf8c7d5a0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/power_sample_summary_table_test.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_series.html">
+<link rel="import" href="/tracing/ui/analysis/power_sample_summary_table.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventSet = tr.model.EventSet;
+ const Model = tr.Model;
+ const PowerSeries = tr.model.PowerSeries;
+
+ test('instantiate', function() {
+ const series = new PowerSeries(new Model().device);
+
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1000, 2);
+ series.addPowerSample(2000, 3);
+ series.addPowerSample(3000, 4);
+
+ const table = document.createElement('tr-ui-a-power-sample-summary-table');
+ table.samples = new EventSet(series.samples);
+
+ this.addHTMLOutput(table);
+ });
+
+ test('setSamples_undefinedPowerSamples', function() {
+ const table = document.createElement('tr-ui-a-power-sample-summary-table');
+ table.samples = undefined;
+
+ assert.lengthOf(table.$.table.tableRows, 0);
+ });
+
+ test('setSamples_noPowerSamples', function() {
+ const table = document.createElement('tr-ui-a-power-sample-summary-table');
+ table.samples = new EventSet([]);
+
+ assert.lengthOf(table.$.table.tableRows, 0);
+ });
+
+ test('setSamples_onePowerSample', function() {
+ const series = new PowerSeries(new Model().device);
+
+ series.addPowerSample(0, 1);
+
+ const table = document.createElement('tr-ui-a-power-sample-summary-table');
+ table.samples = new EventSet(series.samples);
+
+ assert.lengthOf(table.$.table.tableRows, 1);
+ assert.strictEqual(table.$.table.tableRows[0].min, 1);
+ assert.strictEqual(table.$.table.tableRows[0].max, 1);
+ assert.strictEqual(
+ table.$.table.tableRows[0].timeWeightedAverageInW, 'N/A');
+ assert.strictEqual(table.$.table.tableRows[0].energyConsumedInJ, 'N/A');
+ assert.strictEqual(table.$.table.tableRows[0].sampleCount, 1);
+ });
+
+ test('setSamples_twoPowerSamples', function() {
+ const series = new PowerSeries(new Model().device);
+
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1000, 2);
+
+ const table = document.createElement('tr-ui-a-power-sample-summary-table');
+ table.samples = new EventSet(series.samples);
+
+ assert.lengthOf(table.$.table.tableRows, 1);
+ assert.strictEqual(table.$.table.tableRows[0].min, 1);
+ assert.strictEqual(table.$.table.tableRows[0].max, 2);
+ assert.strictEqual(table.$.table.tableRows[0].timeWeightedAverageInW, 1);
+ assert.strictEqual(table.$.table.tableRows[0].energyConsumedInJ, 1);
+ assert.strictEqual(table.$.table.tableRows[0].sampleCount, 2);
+ });
+
+ test('setSamples_threePowerSamples', function() {
+ const series = new PowerSeries(new Model().device);
+
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1000, 2);
+ series.addPowerSample(2000, 3);
+
+ const table = document.createElement('tr-ui-a-power-sample-summary-table');
+ table.samples = new EventSet(series.samples);
+
+ assert.lengthOf(table.$.table.tableRows, 1);
+ assert.strictEqual(table.$.table.tableRows[0].min, 1);
+ assert.strictEqual(table.$.table.tableRows[0].max, 3);
+ assert.strictEqual(table.$.table.tableRows[0].timeWeightedAverageInW, 1.5);
+ assert.strictEqual(table.$.table.tableRows[0].energyConsumedInJ, 3);
+ assert.strictEqual(table.$.table.tableRows[0].sampleCount, 3);
+ });
+
+ test('setSamples_columnsInitialized', function() {
+ const series = new PowerSeries(new Model().device);
+
+ series.addPowerSample(0, 1);
+ series.addPowerSample(1000, 2);
+ series.addPowerSample(2000, 3);
+
+ const table = document.createElement('tr-ui-a-power-sample-summary-table');
+ table.samples = new EventSet(series.samples);
+
+ const row = table.$.table.tableRows[0];
+ const columns = table.$.table.tableColumns;
+
+ assert.lengthOf(columns, 5);
+
+ assert.strictEqual(columns[0].title, 'Min power');
+ assert.strictEqual(columns[0].width, '100px');
+ assert.strictEqual(columns[0].value(row), '1.000 W');
+
+ assert.strictEqual(columns[1].title, 'Max power');
+ assert.strictEqual(columns[1].width, '100px');
+ assert.strictEqual(columns[1].value(row), '3.000 W');
+
+ assert.strictEqual(columns[2].title, 'Time-weighted average');
+ assert.strictEqual(columns[2].width, '100px');
+ assert.strictEqual(columns[2].value(row), '1.500 W');
+
+ assert.strictEqual(columns[3].title, 'Energy consumed');
+ assert.strictEqual(columns[3].width, '100px');
+ assert.strictEqual(columns[3].value(row), '3.000 J');
+
+ assert.strictEqual(columns[4].title, 'Sample count');
+ assert.strictEqual(columns[4].width, '100%');
+ assert.strictEqual(columns[4].value(row), 3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/rebuildable_behavior.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/rebuildable_behavior.html
new file mode 100644
index 00000000000..62abbe8076b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/rebuildable_behavior.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/raf.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const RebuildableBehavior = {
+ rebuild() {
+ /**
+ * Rebuild the pane if necessary.
+ *
+ * This method is not intended to be overriden by subclasses. Please
+ * override scheduleRebuild_() instead.
+ */
+ if (!this.paneDirty_) {
+ // Avoid rebuilding unnecessarily as it breaks things like table
+ // selection.
+ return;
+ }
+
+ this.paneDirty_ = false;
+ this.onRebuild_();
+ },
+
+ /**
+ * Mark the UI state of the pane as dirty and schedule a rebuild.
+ *
+ * This method is intended to be called by subclasses.
+ */
+ scheduleRebuild_() {
+ if (this.paneDirty_) return;
+ this.paneDirty_ = true;
+ tr.b.requestAnimationFrame(this.rebuild.bind(this));
+ },
+
+ /**
+ * Called when the pane is dirty and a rebuild is triggered.
+ *
+ * This method is intended to be overriden by subclasses (instead of
+ * directly overriding rebuild()).
+ */
+ onRebuild_() {
+ }
+ };
+
+ return {
+ RebuildableBehavior,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/rebuildable_behavior_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/rebuildable_behavior_test.html
new file mode 100644
index 00000000000..2a2f083ceb3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/rebuildable_behavior_test.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/rebuildable_behavior.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ Polymer({
+ is: 'tr-ui-analysis-rebuildable-test-element',
+ behaviors: [tr.ui.analysis.RebuildableBehavior]
+ });
+
+ test('rebuild', function() {
+ const el = document.createElement(
+ 'tr-ui-analysis-rebuildable-test-element');
+ let didFireOnRebuild;
+ el.onRebuild_ = function() {
+ assert.strictEqual(this, el);
+ didFireOnRebuild = true;
+ };
+
+ function checkManualRebuild(expectedDidFireOnRebuild) {
+ didFireOnRebuild = false;
+ el.rebuild();
+ assert.strictEqual(didFireOnRebuild, expectedDidFireOnRebuild);
+ }
+
+ function checkRAFRebuild(expectedDidFireOnRebuild) {
+ didFireOnRebuild = false;
+ tr.b.forcePendingRAFTasksToRun();
+ assert.strictEqual(didFireOnRebuild, expectedDidFireOnRebuild);
+ }
+
+ // No rebuilds should occur when not scheduled.
+ checkManualRebuild(false);
+ checkRAFRebuild(false);
+
+ // Single rebuild should occur when scheduled once.
+ el.scheduleRebuild_();
+ checkManualRebuild(true);
+ checkManualRebuild(false);
+
+ el.scheduleRebuild_();
+ checkRAFRebuild(true);
+ checkRAFRebuild(false);
+
+ // Only a single rebuild should occur even when scheduled multiple times.
+ el.scheduleRebuild_();
+ el.scheduleRebuild_();
+ checkManualRebuild(true);
+ checkRAFRebuild(false);
+ checkManualRebuild(false);
+
+ el.scheduleRebuild_();
+ el.scheduleRebuild_();
+ checkRAFRebuild(true);
+ checkRAFRebuild(false);
+ checkManualRebuild(false);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/related_events.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/related_events.html
new file mode 100644
index 00000000000..b4036837bf5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/related_events.html
@@ -0,0 +1,354 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/flow_classifier.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-a-related-events'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ #table {
+ flex: 1 1 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+function* getEventInFlowEvents(event) {
+ if (!event.inFlowEvents) return;
+ yield* event.inFlowEvents;
+}
+
+function* getEventOutFlowEvents(event) {
+ if (!event.outFlowEvents) return;
+ yield* event.outFlowEvents;
+}
+
+function* getEventAncestors(event) {
+ if (!event.enumerateAllAncestors) return;
+ yield* event.enumerateAllAncestors();
+}
+
+function* getEventDescendents(event) {
+ if (!event.enumerateAllDescendents) return;
+ yield* event.enumerateAllDescendents();
+}
+
+Polymer({
+ is: 'tr-ui-a-related-events',
+
+ ready() {
+ this.eventGroups_ = [];
+ this.cancelFunctions_ = [];
+
+ this.$.table.tableColumns = [
+ {
+ title: 'Event(s)',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.type;
+ if (row.tooltip) {
+ typeEl.title = row.tooltip;
+ }
+ return typeEl;
+ },
+ width: '150px'
+ },
+ {
+ title: 'Link',
+ width: '100%',
+ value(row) {
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ if (row.name) {
+ linkEl.setSelectionAndContent(row.selection, row.name);
+ } else {
+ linkEl.selection = row.selection;
+ }
+ return linkEl;
+ }
+ }
+ ];
+ },
+
+ hasRelatedEvents() {
+ return (this.eventGroups_ && this.eventGroups_.length > 0);
+ },
+
+ setRelatedEvents(eventSet) {
+ this.cancelAllTasks_();
+ this.eventGroups_ = [];
+ this.addRuntimeCallStats_(eventSet);
+ this.addOverlappingV8ICStats_(eventSet);
+ this.addV8GCObjectStats_(eventSet);
+ this.addV8Slices_(eventSet);
+ this.addConnectedFlows_(eventSet);
+ this.addConnectedEvents_(eventSet);
+ this.addOverlappingSamples_(eventSet);
+ this.updateContents_();
+ },
+
+ addConnectedFlows_(eventSet) {
+ const classifier = new tr.ui.analysis.FlowClassifier();
+ eventSet.forEach(function(slice) {
+ if (slice.inFlowEvents) {
+ slice.inFlowEvents.forEach(function(flow) {
+ classifier.addInFlow(flow);
+ });
+ }
+ if (slice.outFlowEvents) {
+ slice.outFlowEvents.forEach(function(flow) {
+ classifier.addOutFlow(flow);
+ });
+ }
+ });
+ if (!classifier.hasEvents()) return;
+
+ const addToEventGroups = function(type, flowEvent) {
+ this.eventGroups_.push({
+ type,
+ selection: new tr.model.EventSet(flowEvent),
+ name: flowEvent.title
+ });
+ };
+
+ classifier.inFlowEvents.forEach(
+ addToEventGroups.bind(this, 'Incoming flow'));
+ classifier.outFlowEvents.forEach(
+ addToEventGroups.bind(this, 'Outgoing flow'));
+ classifier.internalFlowEvents.forEach(
+ addToEventGroups.bind(this, 'Internal flow'));
+ },
+
+ cancelAllTasks_() {
+ this.cancelFunctions_.forEach(function(cancelFunction) {
+ cancelFunction();
+ });
+ this.cancelFunctions_ = [];
+ },
+
+ addConnectedEvents_(eventSet) {
+ this.cancelFunctions_.push(this.createEventsLinkIfNeeded_(
+ 'Preceding events',
+ 'Add all events that have led to the selected one(s), connected by ' +
+ 'flow arrows or by call stack.',
+ eventSet,
+ function* (event) {
+ yield* getEventInFlowEvents(event);
+ yield* getEventAncestors(event);
+ if (event.startSlice) {
+ yield event.startSlice;
+ }
+ }.bind(this)));
+ this.cancelFunctions_.push(this.createEventsLinkIfNeeded_(
+ 'Following events',
+ 'Add all events that have been caused by the selected one(s), ' +
+ 'connected by flow arrows or by call stack.',
+ eventSet,
+ function* (event) {
+ yield* getEventOutFlowEvents(event);
+ yield* getEventDescendents(event);
+ if (event.endSlice) {
+ yield event.endSlice;
+ }
+ }.bind(this)));
+ this.cancelFunctions_.push(this.createEventsLinkIfNeeded_(
+ 'All connected events',
+ 'Add all events connected to the selected one(s) by flow arrows or ' +
+ 'by call stack.',
+ eventSet,
+ function* (event) {
+ yield* getEventInFlowEvents(event);
+ yield* getEventOutFlowEvents(event);
+ yield* getEventAncestors(event);
+ yield* getEventDescendents(event);
+ if (event.startSlice) {
+ yield event.startSlice;
+ }
+ if (event.endSlice) {
+ yield event.endSlice;
+ }
+ }.bind(this)));
+ },
+
+ createEventsLinkIfNeeded_(title, tooltip, events, connectedFn) {
+ events = new tr.model.EventSet(events);
+ const eventsToProcess = new Set(events);
+ // for (let event of events)
+ // eventsToProcess.add(event);
+ let wasChanged = false;
+ let task;
+ let isCanceled = false;
+ function addEventsUntilTimeout() {
+ if (isCanceled) return;
+ // Let's grant ourselves a budget of 8 ms. If time runs out, then
+ // create another task to do the rest.
+ const timeout = window.performance.now() + 8;
+ // TODO(alexandermont): Don't check window.performance.now
+ // every iteration.
+ while (eventsToProcess.size > 0 &&
+ window.performance.now() <= timeout) {
+ // Get the next event.
+ const nextEvent = tr.b.getFirstElement(eventsToProcess);
+ eventsToProcess.delete(nextEvent);
+
+ // Add the connected events to the list.
+ for (const eventToAdd of connectedFn(nextEvent)) {
+ if (!events.contains(eventToAdd)) {
+ events.push(eventToAdd);
+ eventsToProcess.add(eventToAdd);
+ wasChanged = true;
+ }
+ }
+ }
+ if (eventsToProcess.size > 0) {
+ // There are still events to process, but we ran out of time. Post
+ // more work for later.
+ const newTask = new tr.b.Task(
+ addEventsUntilTimeout.bind(this), this);
+ task.after(newTask);
+ task = newTask;
+ return;
+ }
+ // Went through all events, add the link.
+ if (!wasChanged) return;
+ this.eventGroups_.push({
+ type: title,
+ tooltip,
+ selection: events
+ });
+ this.updateContents_();
+ }
+ function cancelTask() {
+ isCanceled = true;
+ }
+ task = new tr.b.Task(addEventsUntilTimeout.bind(this), this);
+ tr.b.Task.RunWhenIdle(task);
+ return cancelTask;
+ },
+
+ addOverlappingSamples_(eventSet) {
+ const samples = new tr.model.EventSet();
+ for (const slice of eventSet) {
+ if (!slice.parentContainer || !slice.parentContainer.samples) {
+ continue;
+ }
+ const candidates = slice.parentContainer.samples;
+ const range = tr.b.math.Range.fromExplicitRange(
+ slice.start, slice.start + slice.duration);
+ const filteredSamples = range.filterArray(
+ candidates, function(value) {return value.start;});
+ for (const sample of filteredSamples) {
+ samples.push(sample);
+ }
+ }
+ if (samples.length > 0) {
+ this.eventGroups_.push({
+ type: 'Overlapping samples',
+ tooltip: 'All samples overlapping the selected slice(s).',
+ selection: samples
+ });
+ }
+ },
+
+ addV8Slices_(eventSet) {
+ const v8Slices = new tr.model.EventSet();
+ for (const slice of eventSet) {
+ if (slice.category === 'v8') {
+ v8Slices.push(slice);
+ }
+ }
+ if (v8Slices.length > 0) {
+ this.eventGroups_.push({
+ type: 'V8 Slices',
+ tooltip: 'All V8 slices in the selected slice(s).',
+ selection: v8Slices
+ });
+ }
+ },
+
+ addRuntimeCallStats_(eventSet) {
+ const slices = eventSet.filter(function(slice) {
+ return (slice.category === 'v8' ||
+ slice.category === 'disabled-by-default-v8.runtime_stats') &&
+ slice.runtimeCallStats;
+ });
+ if (slices.length > 0) {
+ this.eventGroups_.push({
+ type: 'Runtime call stats table',
+ // eslint-disable-next-line
+ tooltip: 'All V8 slices containing runtime call stats table in the selected slice(s).',
+ selection: slices
+ });
+ }
+ },
+
+ addV8GCObjectStats_(eventSet) {
+ const slices = new tr.model.EventSet();
+ for (const slice of eventSet) {
+ if (slice.title === 'V8.GC_Objects_Stats') {
+ slices.push(slice);
+ }
+ }
+ if (slices.length > 0) {
+ this.eventGroups_.push({
+ type: 'V8 GC stats table',
+ tooltip: 'All V8 GC statistics slices in the selected set.',
+ selection: slices
+ });
+ }
+ },
+
+ addOverlappingV8ICStats_(eventSet) {
+ const slices = new tr.model.EventSet();
+ for (const slice of eventSet) {
+ if (!slice.parentContainer || !slice.parentContainer.sliceGroup) {
+ continue;
+ }
+ const sliceGroup = slice.parentContainer.sliceGroup.slices;
+ const range = tr.b.math.Range.fromExplicitRange(
+ slice.start, slice.start + slice.duration);
+ const filteredSlices = range.filterArray(
+ sliceGroup, value => value.start);
+ const icSlices = filteredSlices.filter(x => x.title === 'V8.ICStats');
+ for (const icSlice of icSlices) {
+ slices.push(icSlice);
+ }
+ }
+ if (slices.length > 0) {
+ this.eventGroups_.push({
+ type: 'Overlapping V8 IC stats',
+ tooltip: 'All V8 IC statistics overlapping the selected set.',
+ selection: slices
+ });
+ }
+ },
+
+ updateContents_() {
+ const table = this.$.table;
+ if (this.eventGroups_ === undefined) {
+ table.tableRows = [];
+ } else {
+ table.tableRows = this.eventGroups_.slice();
+ }
+ table.rebuild();
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/related_events_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/related_events_test.html
new file mode 100644
index 00000000000..5d14d68faa3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/related_events_test.html
@@ -0,0 +1,221 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/sample.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+<link rel="import" href="/tracing/ui/analysis/related_events.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newFlowEventEx = tr.c.TestUtils.newFlowEventEx;
+
+ function createModel() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+
+ m.t2 = m.p1.getOrCreateThread(2);
+ m.t3 = m.p1.getOrCreateThread(3);
+ m.t4 = m.p1.getOrCreateThread(4);
+ const node = tr.c.TestUtils.newProfileNodes(m, ['fake']);
+
+ // Setup samples and slices in this way:
+ // 0 5 10 15 20
+ // _____________________________
+ // t2 *
+ // [ a ][ ]aa
+ // -----------------------------
+ // t3 * * * * *
+ // * *
+ // [ b ]
+ // [bb]
+ // []bbb
+ // -----------------------------
+ // t4 |c
+ // -----------------------------
+ m.samples.push(
+ new tr.model.Sample(10, 'b10_1', node, m.t3),
+ new tr.model.Sample(7, 'b7', node, m.t3),
+ new tr.model.Sample(12, 'b12', node, m.t3),
+ new tr.model.Sample(20, 'b20', node, m.t3),
+ new tr.model.Sample(10, 'b10_2', node, m.t3),
+ new tr.model.Sample(15, 'b15_1', node, m.t3),
+ new tr.model.Sample(15, 'b15_2', node, m.t3),
+ new tr.model.Sample(12, 'a12', node, m.t2)
+ );
+
+ m.sA = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'a', start: 0, end: 5,
+ type: tr.model.ThreadSlice}));
+ m.sAA = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'aa', start: 6, end: 8,
+ type: tr.model.ThreadSlice}));
+ m.sB = m.t3.sliceGroup.pushSlice(
+ newSliceEx({title: 'b', start: 10, end: 15,
+ type: tr.model.ThreadSlice}));
+ m.sBB = m.t3.sliceGroup.pushSlice(
+ newSliceEx({title: 'bb', start: 11, end: 14,
+ type: tr.model.ThreadSlice}));
+ m.sBBB = m.t3.sliceGroup.pushSlice(
+ newSliceEx({title: 'bbb', start: 12, end: 13,
+ type: tr.model.ThreadSlice}));
+ m.sC = m.t4.sliceGroup.pushSlice(
+ newSliceEx({title: 'c', start: 20, end: 20,
+ type: tr.model.ThreadSlice}));
+
+ m.t2.createSubSlices();
+ m.t3.createSubSlices();
+ m.t4.createSubSlices();
+
+ // Add flow events.
+ m.f0 = newFlowEventEx({
+ title: 'a_aa', start: 5, end: 6,
+ startSlice: m.sA,
+ endSlice: m.sAA
+ });
+ m.f1 = newFlowEventEx({
+ title: 'a_b', start: 0, end: 10,
+ startSlice: m.sA,
+ endSlice: m.sB
+ });
+ m.f2 = newFlowEventEx({
+ title: 'b_bbb', start: 10, end: 12,
+ startSlice: m.sB,
+ endSlice: m.sBBB
+ });
+ m.f3 = newFlowEventEx({
+ title: 'bbb_c', start: 13, end: 20,
+ startSlice: m.sBBB,
+ endSlice: m.sC
+ });
+ });
+ return m;
+ }
+
+ test('instantiate', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement('tr-ui-a-related-events');
+ const selection = new tr.model.EventSet(
+ [m.sA, m.f0, m.sAA, m.f1, m.sB, m.f2, m.sBB, m.sBBB, m.f3, m.sC]);
+ viewEl.setRelatedEvents(selection);
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+
+ // Check that the element handles multiple setRelatedEvents calls correctly.
+ assert.lengthOf(viewEl.$.table.tableRows, 5);
+ viewEl.setRelatedEvents(selection);
+ assert.lengthOf(viewEl.$.table.tableRows, 5);
+ });
+
+ test('validateFlows', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement('tr-ui-a-related-events');
+ viewEl.setRelatedEvents(new tr.model.EventSet([m.sB, m.sBB, m.sBBB]));
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+
+ let inFlows;
+ let outFlows;
+ let internalFlows;
+ viewEl.$.table.tableRows.forEach(function(row) {
+ if (row.type === 'Incoming flow') {
+ assert.isUndefined(inFlows);
+ inFlows = row.selection;
+ }
+ if (row.type === 'Outgoing flow') {
+ assert.isUndefined(outFlows);
+ outFlows = row.selection;
+ }
+ if (row.type === 'Internal flow') {
+ assert.isUndefined(internalFlows);
+ internalFlows = row.selection;
+ }
+ });
+ assert.strictEqual(inFlows.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(inFlows).title, 'a_b');
+ assert.strictEqual(outFlows.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(outFlows).title, 'bbb_c');
+ assert.strictEqual(internalFlows.length, 1);
+ assert.strictEqual(tr.b.getOnlyElement(internalFlows).title, 'b_bbb');
+ });
+
+ test('validateConnectedEvents', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement('tr-ui-a-related-events');
+ viewEl.setRelatedEvents(new tr.model.EventSet([m.sBB]));
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+
+ let precedingEvents;
+ let followingEvents;
+ let allEvents;
+ viewEl.$.table.tableRows.forEach(function(row) {
+ if (row.type === 'Preceding events') {
+ assert.isUndefined(precedingEvents);
+ precedingEvents = row.selection;
+ }
+ if (row.type === 'Following events') {
+ assert.isUndefined(followingEvents);
+ followingEvents = row.selection;
+ }
+ if (row.type === 'All connected events') {
+ assert.isUndefined(allEvents);
+ allEvents = row.selection;
+ }
+ });
+
+ const precedingTitles = precedingEvents.map(function(e) {
+ return e.title;
+ });
+ assert.sameMembers(precedingTitles, ['a', 'a_b', 'b', 'bb']);
+
+ const followingTitles = followingEvents.map(function(e) {
+ return e.title;
+ });
+ assert.sameMembers(followingTitles, ['bb', 'bbb', 'bbb_c', 'c']);
+
+ const allTitles = allEvents.map(function(e) {
+ return e.title;
+ });
+ assert.sameMembers(allTitles,
+ ['a', 'a_aa', 'aa', 'a_b', 'b', 'bb', 'bbb', 'b_bbb', 'bbb_c', 'c']);
+ });
+
+ test('validateOverlappingSamples', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement('tr-ui-a-related-events');
+ viewEl.setRelatedEvents(new tr.model.EventSet([m.sB]));
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+
+ let overlappingSamples;
+ viewEl.$.table.tableRows.forEach(function(row) {
+ if (row.type === 'Overlapping samples') {
+ assert.isUndefined(overlappingSamples);
+ overlappingSamples = row.selection;
+ }
+ });
+
+ const samplesTitles = overlappingSamples.map(function(e) {
+ return e.title;
+ });
+ assert.sameMembers(samplesTitles,
+ ['b10_1', 'b10_2', 'b12', 'b15_1', 'b15_2']);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/selection_summary_table.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/selection_summary_table.html
new file mode 100644
index 00000000000..68ca4d533d4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/selection_summary_table.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-selection-summary-table'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ }
+ #table {
+ flex: 1 1 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table">
+ </tr-ui-b-table>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-selection-summary-table',
+ created() {
+ this.selection_ = new tr.b.math.Range();
+ },
+
+ ready() {
+ this.$.table.showHeader = false;
+ this.$.table.tableColumns = [
+ {
+ title: 'Name',
+ value(row) { return row.title; },
+ width: '350px'
+ },
+ {
+ title: 'Value',
+ width: '100%',
+ value(row) {
+ return row.value;
+ }
+ }
+ ];
+ },
+
+ get selection() {
+ return this.selection_;
+ },
+
+ set selection(selection) {
+ this.selection_ = selection;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ const selection = this.selection_;
+ const rows = [];
+ let hasRange;
+ if (this.selection_ && (!selection.bounds.isEmpty)) {
+ hasRange = true;
+ } else {
+ hasRange = false;
+ }
+
+ rows.push({
+ title: 'Selection start',
+ value: hasRange ? tr.v.ui.createScalarSpan(
+ selection.bounds.min, {
+ unit: tr.b.Unit.byName.timeStampInMs,
+ ownerDocument: this.ownerDocument
+ }) : '<empty>'
+ });
+ rows.push({
+ title: 'Selection extent',
+ value: hasRange ? tr.v.ui.createScalarSpan(
+ selection.bounds.range, {
+ unit: tr.b.Unit.byName.timeDurationInMs,
+ ownerDocument: this.ownerDocument
+ }) : '<empty>'
+ });
+
+ this.$.table.tableRows = rows;
+ this.$.table.rebuild();
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/selection_summary_table_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/selection_summary_table_test.html
new file mode 100644
index 00000000000..20a8daf3b47
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/selection_summary_table_test.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/selection_summary_table.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const EventSet = tr.model.EventSet;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ test('noSelection', function() {
+ const summaryTable =
+ document.createElement('tr-ui-a-selection-summary-table');
+ summaryTable.selection = undefined;
+ this.addHTMLOutput(summaryTable);
+
+ const tableEl = tr.ui.b.findDeepElementMatching(
+ summaryTable, 'tr-ui-b-table');
+ assert.strictEqual(tableEl.tableRows[0].value, '<empty>');
+ assert.strictEqual(tableEl.tableRows[1].value, '<empty>');
+ });
+
+ test('emptySelection', function() {
+ const summaryTable =
+ document.createElement('tr-ui-a-selection-summary-table');
+ const selection = new EventSet();
+ summaryTable.selection = selection;
+ this.addHTMLOutput(summaryTable);
+
+ const tableEl = tr.ui.b.findDeepElementMatching(
+ summaryTable, 'tr-ui-b-table');
+ assert.strictEqual(tableEl.tableRows[0].value, '<empty>');
+ assert.strictEqual(tableEl.tableRows[1].value, '<empty>');
+ });
+
+ test('selection', function() {
+ const model = new Model();
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ const tsg = thread.sliceGroup;
+
+ tsg.pushSlice(newSliceEx({title: 'a', start: 0, end: 3}));
+ tsg.pushSlice(newSliceEx({title: 'b', start: 1, end: 2}));
+
+ const selection = new EventSet();
+ selection.push(tsg.slices[0]);
+ selection.push(tsg.slices[1]);
+
+ const summaryTable =
+ document.createElement('tr-ui-a-selection-summary-table');
+ summaryTable.selection = selection;
+ this.addHTMLOutput(summaryTable);
+
+ const tableEl = tr.ui.b.findDeepElementMatching(
+ summaryTable, 'tr-ui-b-table');
+ assert.strictEqual(tableEl.tableRows[0].value.value, 0);
+ assert.strictEqual(tableEl.tableRows[0].value.unit,
+ tr.b.Unit.byName.timeStampInMs);
+ assert.strictEqual(tableEl.tableRows[1].value.value, 3);
+ assert.strictEqual(tableEl.tableRows[1].value.unit,
+ tr.b.Unit.byName.timeDurationInMs);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view.html
new file mode 100644
index 00000000000..cc7f7b840dd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/related_events.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+
+<dom-module id='tr-ui-a-single-async-slice-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: row;
+ }
+ #events {
+ display:flex;
+ flex-direction: column;
+ }
+ </style>
+ <tr-ui-a-single-event-sub-view id="content"></tr-ui-a-single-event-sub-view>
+ <div id="events">
+ <tr-ui-a-related-events id="relatedEvents"></tr-ui-a-related-events>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-async-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ if (selection.length !== 1) {
+ throw new Error('Only supports single slices');
+ }
+ this.$.content.setSelectionWithoutErrorChecks(selection);
+ this.$.relatedEvents.setRelatedEvents(selection);
+ if (this.$.relatedEvents.hasRelatedEvents()) {
+ this.$.relatedEvents.style.display = '';
+ } else {
+ this.$.relatedEvents.style.display = 'none';
+ }
+ },
+
+ getEventRows_(event) {
+ // TODO(nduca): Figure out if there is a cleaner way to do this.
+ const rows = this.__proto__.__proto__.getEventRows_(event);
+
+ // Put the ID up top.
+ rows.splice(0, 0, {
+ name: 'ID',
+ value: event.id
+ });
+ return rows;
+ },
+
+ get relatedEventsToHighlight() {
+ if (!this.currentSelection_) return undefined;
+ return tr.b.getOnlyElement(this.currentSelection_).associatedEvents;
+ }
+});
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-async-slice-sub-view',
+ tr.model.AsyncSlice,
+ {
+ multi: false,
+ title: 'Async Slice',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view_test.html
new file mode 100644
index 00000000000..6cd341011bb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_async_slice_sub_view_test.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/single_async_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newAsyncSliceEx = tr.c.TestUtils.newAsyncSliceEx;
+
+ test('instantiate', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.asyncSliceGroup.push(newAsyncSliceEx({
+ id: 31415,
+ title: 'a',
+ start: 10,
+ duration: 20,
+ startThread: t1,
+ endThread: t1
+ }));
+
+ const selection = new tr.model.EventSet();
+ selection.push(t1.asyncSliceGroup.slices[0]);
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-single-async-slice-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view.html
new file mode 100644
index 00000000000..12040ca9bad
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-single-cpu-slice-sub-view'>
+ <template>
+ <style>
+ table {
+ border-collapse: collapse;
+ border-width: 0;
+ margin-bottom: 25px;
+ width: 100%;
+ }
+
+ table tr > td:first-child {
+ padding-left: 2px;
+ }
+
+ table tr > td {
+ padding: 2px 4px 2px 4px;
+ vertical-align: text-top;
+ width: 150px;
+ }
+
+ table td td {
+ padding: 0 0 0 0;
+ width: auto;
+ }
+ tr {
+ vertical-align: top;
+ }
+
+ tr:nth-child(2n+0) {
+ background-color: #e2e2e2;
+ }
+ </style>
+ <table>
+ <tr>
+ <td>Running process:</td><td id="process-name"></td>
+ </tr>
+ <tr>
+ <td>Running thread:</td><td id="thread-name"></td>
+ </tr>
+ <tr>
+ <td>Start:</td>
+ <td>
+ <tr-v-ui-scalar-span id="start">
+ </tr-v-ui-scalar-span>
+ </td>
+ </tr>
+ <tr>
+ <td>Duration:</td>
+ <td>
+ <tr-v-ui-scalar-span id="duration">
+ </tr-v-ui-scalar-span>
+ </td>
+ </tr>
+ <tr>
+ <td>Active slices:</td><td id="running-thread"></td>
+ </tr>
+ <tr>
+ <td>Args:</td>
+ <td>
+ <tr-ui-a-generic-object-view id="args">
+ </tr-ui-a-generic-object-view>
+ </td>
+ </tr>
+ </table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-cpu-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ const cpuSlice = tr.b.getOnlyElement(selection);
+ if (!(cpuSlice instanceof tr.model.CpuSlice)) {
+ throw new Error('Only supports thread time slices');
+ }
+
+ this.currentSelection_ = selection;
+
+ const thread = cpuSlice.threadThatWasRunning;
+
+ const root = Polymer.dom(this.root);
+ if (thread) {
+ Polymer.dom(root.querySelector('#process-name')).textContent =
+ thread.parent.userFriendlyName;
+ Polymer.dom(root.querySelector('#thread-name')).textContent =
+ thread.userFriendlyName;
+ } else {
+ root.querySelector('#process-name').parentElement.style.display =
+ 'none';
+ Polymer.dom(root.querySelector('#thread-name')).textContent =
+ cpuSlice.title;
+ }
+
+ root.querySelector('#start').setValueAndUnit(
+ cpuSlice.start, tr.b.Unit.byName.timeStampInMs);
+ root.querySelector('#duration').setValueAndUnit(
+ cpuSlice.duration, tr.b.Unit.byName.timeDurationInMs);
+
+ const runningThreadEl = root.querySelector('#running-thread');
+
+ const timeSlice = cpuSlice.getAssociatedTimeslice();
+ if (!timeSlice) {
+ runningThreadEl.parentElement.style.display = 'none';
+ } else {
+ const threadLink = document.createElement('tr-ui-a-analysis-link');
+ threadLink.selection = new tr.model.EventSet(timeSlice);
+ Polymer.dom(threadLink).textContent = 'Click to select';
+ runningThreadEl.parentElement.style.display = '';
+ Polymer.dom(runningThreadEl).textContent = '';
+ Polymer.dom(runningThreadEl).appendChild(threadLink);
+ }
+
+ root.querySelector('#args').object = cpuSlice.args;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-cpu-slice-sub-view',
+ tr.model.CpuSlice,
+ {
+ multi: false,
+ title: 'CPU Slice',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view_test.html
new file mode 100644
index 00000000000..ee47fe5c58a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_cpu_slice_sub_view_test.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/single_cpu_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createBasicModel() {
+ const lines = [
+ 'Android.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D ==> next_comm=Android.launcher next_pid=584 next_prio=120', // @suppress longLineCheck
+ 'Android.launcher-584 [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001', // @suppress longLineCheck
+ 'Android.launcher-584 [001] d..3 12622.506950: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: B|128|queueBuffer', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E',
+ ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
+ ];
+
+ return tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('cpuSliceView_withCpuSliceOnExistingThread', function() {
+ const m = createBasicModel();
+
+ const cpu = m.kernel.cpus[1];
+ assert.isDefined(cpu);
+ const cpuSlice = cpu.slices[0];
+ assert.strictEqual('Binder_1', cpuSlice.title);
+
+ const thread = m.findAllThreadsNamed('Binder_1')[0];
+ assert.isDefined(thread);
+ assert.strictEqual(cpuSlice.threadThatWasRunning, thread);
+
+ const view = document.createElement('tr-ui-a-single-cpu-slice-sub-view');
+ const selection = new tr.model.EventSet();
+ selection.push(cpuSlice);
+ view.selection = selection;
+ this.addHTMLOutput(view);
+
+ // Clicking the analysis link should focus the Binder1's timeslice.
+ let didSelectionChangeHappen = false;
+ view.addEventListener('requestSelectionChange', function(e) {
+ assert.isTrue(e.selection.equals(
+ new tr.model.EventSet(thread.timeSlices[0])));
+ didSelectionChangeHappen = true;
+ });
+ Polymer.dom(view.root).querySelector('tr-ui-a-analysis-link').click();
+ assert.isTrue(didSelectionChangeHappen);
+ });
+
+ test('cpuSliceViewWithCpuSliceOnMissingThread', function() {
+ const m = createBasicModel();
+
+ const cpu = m.kernel.cpus[1];
+ assert.isDefined(cpu);
+ const cpuSlice = cpu.slices[1];
+ assert.strictEqual('Android.launcher', cpuSlice.title);
+ assert.isUndefined(cpuSlice.thread);
+
+ const selection = new tr.model.EventSet();
+ selection.push(cpuSlice);
+
+ const view = document.createElement('tr-ui-a-single-cpu-slice-sub-view');
+ view.selection = selection;
+ this.addHTMLOutput(view);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_event_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_event_sub_view.html
new file mode 100644
index 00000000000..d49125af9e3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_event_sub_view.html
@@ -0,0 +1,356 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/analysis/stack_frame.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-single-event-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex: 0 1;
+ flex-direction: column;
+ }
+ #table {
+ flex: 0 1 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table">
+ </tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-event-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ properties: {
+ isFlow: {
+ type: Boolean,
+ value: false
+ }
+ },
+
+ ready() {
+ this.currentSelection_ = undefined;
+ this.$.table.tableColumns = [
+ {
+ title: 'Label',
+ value(row) { return row.name; },
+ width: '150px'
+ },
+ {
+ title: 'Value',
+ width: '100%',
+ value(row) { return row.value; }
+ }
+ ];
+ this.$.table.showHeader = false;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ if (selection.length !== 1) {
+ throw new Error('Only supports single slices');
+ }
+ this.setSelectionWithoutErrorChecks(selection);
+ },
+
+ setSelectionWithoutErrorChecks(selection) {
+ this.currentSelection_ = selection;
+ this.updateContents_();
+ },
+
+ getFlowEventRows_(event) {
+ // TODO(nduca): Figure out if there is a cleaner way to do this.
+
+ const rows = this.getEventRowsHelper_(event);
+
+ // Put the ID up top.
+ rows.splice(0, 0, {
+ name: 'ID',
+ value: event.id
+ });
+
+ function createLinkTo(slice) {
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(function() {
+ return new tr.model.EventSet(slice);
+ });
+ Polymer.dom(linkEl).textContent = slice.userFriendlyName;
+ return linkEl;
+ }
+
+ rows.push({
+ name: 'From',
+ value: createLinkTo(event.startSlice)
+ });
+ rows.push({
+ name: 'To',
+ value: createLinkTo(event.endSlice)
+ });
+ return rows;
+ },
+
+ getEventRowsHelper_(event) {
+ const rows = [];
+
+ if (event.error) {
+ rows.push({ name: 'Error', value: event.error });
+ }
+
+ if (event.title) {
+ let title = event.title;
+ if (tr.isExported('tr-ui-e-chrome-codesearch')) {
+ const container = document.createElement('div');
+ container.appendChild(document.createTextNode(title));
+ const link = document.createElement('tr-ui-e-chrome-codesearch');
+ link.searchPhrase = title;
+ container.appendChild(link);
+ title = container;
+ }
+ rows.push({ name: 'Title', value: title });
+ }
+
+ if (event.category) {
+ rows.push({ name: 'Category', value: event.category });
+ }
+
+ if (event.model !== undefined) {
+ const ufc = event.model.getUserFriendlyCategoryFromEvent(event);
+ if (ufc !== undefined) {
+ rows.push({ name: 'User Friendly Category', value: ufc });
+ }
+ }
+
+ if (event.name) {
+ rows.push({ name: 'Name', value: event.name });
+ }
+
+ rows.push({
+ name: 'Start',
+ value: tr.v.ui.createScalarSpan(event.start, {
+ unit: tr.b.Unit.byName.timeStampInMs
+ })
+ });
+
+ if (event.duration) {
+ rows.push({
+ name: 'Wall Duration',
+ value: tr.v.ui.createScalarSpan(event.duration, {
+ unit: tr.b.Unit.byName.timeDurationInMs
+ })
+ });
+ }
+
+ if (event.cpuDuration) {
+ rows.push({
+ name: 'CPU Duration',
+ value: tr.v.ui.createScalarSpan(event.cpuDuration, {
+ unit: tr.b.Unit.byName.timeDurationInMs
+ })
+ });
+ }
+
+ if (event.subSlices !== undefined && event.subSlices.length !== 0) {
+ if (event.selfTime) {
+ rows.push({
+ name: 'Self Time',
+ value: tr.v.ui.createScalarSpan(event.selfTime, {
+ unit: tr.b.Unit.byName.timeDurationInMs
+ })
+ });
+ }
+
+ if (event.cpuSelfTime) {
+ const cpuSelfTimeEl = tr.v.ui.createScalarSpan(event.cpuSelfTime, {
+ unit: tr.b.Unit.byName.timeDurationInMs
+ });
+ if (event.cpuSelfTime > event.selfTime) {
+ cpuSelfTimeEl.warning =
+ ' Note that CPU Self Time is larger than Self Time. ' +
+ 'This is a known limitation of this system, which occurs ' +
+ 'due to several subslices, rounding issues, and imprecise ' +
+ 'time at which we get cpu- and real-time.';
+ }
+ rows.push({ name: 'CPU Self Time', value: cpuSelfTimeEl });
+ }
+ }
+
+ if (event.durationInUserTime) {
+ rows.push({
+ name: 'Duration (U)',
+ value: tr.v.ui.createScalarSpan(event.durationInUserTime, {
+ unit: tr.b.Unit.byName.timeDurationInMs
+ })
+ });
+ }
+
+ function createStackFrameEl(sf) {
+ const sfEl = document.createElement('tr-ui-a-stack-frame');
+ sfEl.stackFrame = sf;
+ return sfEl;
+ }
+ if (event.startStackFrame && event.endStackFrame) {
+ if (event.startStackFrame === event.endStackFrame) {
+ rows.push({name: 'Start+End Stack Trace',
+ value: createStackFrameEl(event.startStackFrame)});
+ } else {
+ rows.push({ name: 'Start Stack Trace',
+ value: createStackFrameEl(event.startStackFrame)});
+ rows.push({ name: 'End Stack Trace',
+ value: createStackFrameEl(event.endStackFrame)});
+ }
+ } else if (event.startStackFrame) {
+ rows.push({ name: 'Start Stack Trace',
+ value: createStackFrameEl(event.startStackFrame)});
+ } else if (event.endStackFrame) {
+ rows.push({ name: 'End Stack Trace',
+ value: createStackFrameEl(event.endStackFrame)});
+ }
+
+ if (event.info) {
+ const descriptionEl = tr.ui.b.createDiv({
+ textContent: event.info.description,
+ maxWidth: '300px'
+ });
+ rows.push({
+ name: 'Description',
+ value: descriptionEl
+ });
+
+
+ if (event.info.docLinks) {
+ event.info.docLinks.forEach(function(linkObject) {
+ const linkEl = document.createElement('a');
+ linkEl.target = '_blank';
+ linkEl.href = linkObject.href;
+ Polymer.dom(linkEl).textContent = Polymer.dom(linkObject).textContent;
+ rows.push({
+ name: linkObject.label,
+ value: linkEl
+ });
+ });
+ }
+ }
+
+ if (event.associatedAlerts.length) {
+ const alertSubRows = [];
+ event.associatedAlerts.forEach(function(alert) {
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(function() {
+ return new tr.model.EventSet(alert);
+ }, alert.info.description);
+ alertSubRows.push({
+ name: alert.title,
+ value: linkEl
+ });
+ });
+
+ rows.push({
+ name: 'Alerts', value: '',
+ isExpanded: true, subRows: alertSubRows
+ });
+ }
+ return rows;
+ },
+
+ getEventRows_(event) {
+ if (this.isFlow) {
+ return this.getFlowEventRows_(event);
+ }
+
+ return this.getEventRowsHelper_(event);
+ },
+
+ addArgsToRows_(rows, args) {
+ let n = 0;
+ for (const argName in args) {
+ n += 1;
+ }
+ if (n > 0) {
+ const subRows = [];
+ for (const argName in args) {
+ n += 1;
+ }
+ if (n > 0) {
+ const subRows = [];
+ for (const argName in args) {
+ const argView =
+ document.createElement('tr-ui-a-generic-object-view');
+ argView.object = args[argName];
+ subRows.push({name: argName, value: argView});
+ }
+ rows.push({
+ name: 'Args',
+ value: '',
+ isExpanded: true,
+ subRows
+ });
+ }
+ }
+ },
+
+ addContextsToRows_(rows, contexts) {
+ if (contexts.length) {
+ const subRows = contexts.map(function(context) {
+ const contextView =
+ document.createElement('tr-ui-a-generic-object-view');
+ contextView.object = context;
+ return {name: 'Context', value: contextView};
+ });
+ rows.push({
+ name: 'Contexts',
+ value: '',
+ isExpanded: true,
+ subRows
+ });
+ }
+ },
+
+ updateContents_() {
+ if (this.currentSelection_ === undefined) {
+ this.$.table.rows = [];
+ this.$.table.rebuild();
+ return;
+ }
+
+ const event = tr.b.getOnlyElement(this.currentSelection_);
+
+ const rows = this.getEventRows_(event);
+ if (event.argsStripped) {
+ rows.push({ name: 'Args', value: 'Stripped' });
+ } else {
+ this.addArgsToRows_(rows, event.args);
+ }
+ this.addContextsToRows_(rows, event.contexts);
+
+ const customizeRowsEvent = new tr.b.Event('customize-rows');
+ customizeRowsEvent.rows = rows;
+ this.dispatchEvent(customizeRowsEvent);
+
+ this.$.table.tableRows = rows;
+ this.$.table.rebuild();
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_event_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_event_sub_view_test.html
new file mode 100644
index 00000000000..41c42308e3e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_event_sub_view_test.html
@@ -0,0 +1,277 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const Thread = tr.model.Thread;
+ const EventSet = tr.model.EventSet;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ function createSelection(customizeThreadCallback) {
+ const model = tr.c.TestUtils.newModelWithEvents([], {
+ customizeModelCallback(model) {
+ const t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
+ customizeThreadCallback(t53, model);
+ }
+ });
+
+ const t53 = model.processes[52].threads[53];
+ const t53track = {};
+ t53track.thread = t53;
+
+ const selection = new EventSet();
+ selection.push(t53.sliceGroup.slices[0]);
+ assert.strictEqual(selection.length, 1);
+
+ return selection;
+ }
+
+ function createSelectionWithSingleSlice(opt_options) {
+ const options = opt_options || {};
+ return createSelection(function(t53, model) {
+ let fA;
+ let fB;
+ if (options.withStartStackFrame || options.withEndStackFrame) {
+ fA = tr.c.TestUtils.newStackTrace(model, ['a1', 'a2']);
+ fB = tr.c.TestUtils.newStackTrace(model, ['b1', 'b2']);
+ }
+
+ const slice = newSliceEx({title: 'b', start: 0, duration: 0.002});
+ slice.category = options.withCategory ? 'foo' : '';
+
+ if (options.withStartStackFrame) {
+ slice.startStackFrame = options.withStartStackFrame === 'a' ? fA : fB;
+ }
+
+ if (options.withEndStackFrame) {
+ slice.endStackFrame = options.withEndStackFrame === 'a' ? fA : fB;
+ }
+
+ t53.sliceGroup.pushSlice(slice);
+ });
+ }
+
+ test('instantiate_withSingleSlice', function() {
+ const selection = createSelectionWithSingleSlice();
+
+ const analysisEl = document.createElement('tr-ui-a-single-event-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+ });
+
+ test('alerts', function() {
+ const slice = newSliceEx({title: 'b', start: 0, duration: 0.002});
+
+ const ALERT_INFO_1 = new tr.model.EventInfo(
+ 'Alert 1', 'Critical alert');
+
+ const alert = new tr.model.Alert(ALERT_INFO_1, 5, [slice]);
+
+ const selection = new EventSet();
+ selection.push(slice);
+
+ const analysisEl = document.createElement('tr-ui-a-single-event-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+ });
+
+ test('instantiate_withSingleSliceWithArg', function() {
+ const selection = createSelection(function(t53) {
+ const slice = newSliceEx({title: 'my_slice', start: 0, duration: 1.0});
+ slice.args = {
+ 'complex': {
+ 'b': '2 as a string',
+ 'c': [3, 4, 5]
+ }
+ };
+ t53.sliceGroup.pushSlice(slice);
+ });
+
+ const subView = document.createElement('tr-ui-a-single-event-sub-view');
+ subView.selection = selection;
+ this.addHTMLOutput(subView);
+
+ const gov = tr.ui.b.findDeepElementMatching(subView,
+ 'tr-ui-a-generic-object-view');
+ assert.isDefined(gov);
+ });
+
+
+ test('instantiate_withSingleSliceCategory', function() {
+ const selection = createSelectionWithSingleSlice({withCategory: true});
+
+ const analysisEl = document.createElement('tr-ui-a-single-event-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+ });
+
+ test('instantiate_withSingleStartStackFrame', function() {
+ const selection = createSelectionWithSingleSlice(
+ {withStartStackFrame: 'a'});
+
+ const analysisEl = document.createElement('tr-ui-a-single-event-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+
+ const e = tr.ui.b.findDeepElementWithTextContent(
+ analysisEl, /Start Stack Trace/);
+ assert.isDefined(e);
+ assert.isDefined(Polymer.dom(e).nextSibling.children[0].stackFrame);
+ });
+
+ test('instantiate_withSingleEndStackFrame', function() {
+ const selection = createSelectionWithSingleSlice(
+ {withEndStackFrame: 'b'});
+
+ const analysisEl = document.createElement('tr-ui-a-single-event-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+
+ const e = tr.ui.b.findDeepElementWithTextContent(
+ analysisEl, /End Stack Trace/);
+ assert.isDefined(e);
+ assert.isDefined(Polymer.dom(e).nextSibling.children[0].stackFrame);
+ assert.strictEqual(
+ Polymer.dom(e).nextSibling.children[0].stackFrame.title, 'b2');
+ });
+
+ test('instantiate_withDifferentStartAndEndStackFrames', function() {
+ const selection = createSelectionWithSingleSlice(
+ {withStartStackFrame: 'a',
+ withEndStackFrame: 'b'});
+
+ const analysisEl = document.createElement('tr-ui-a-single-event-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+
+ const eA = tr.ui.b.findDeepElementWithTextContent(
+ analysisEl, /Start Stack Trace/);
+ assert.isDefined(eA);
+ assert.isDefined(Polymer.dom(eA).nextSibling.children[0].stackFrame);
+ assert.strictEqual(
+ Polymer.dom(eA).nextSibling.children[0].stackFrame.title, 'a2');
+
+ const eB = tr.ui.b.findDeepElementWithTextContent(
+ analysisEl, /End Stack Trace/);
+ assert.isDefined(eB);
+ assert.isDefined(Polymer.dom(eB).nextSibling.children[0].stackFrame);
+ assert.strictEqual(
+ Polymer.dom(eB).nextSibling.children[0].stackFrame.title, 'b2');
+ });
+
+ test('instantiate_withSameStartAndEndStackFrames', function() {
+ const selection = createSelectionWithSingleSlice(
+ {withStartStackFrame: 'a',
+ withEndStackFrame: 'a'});
+
+ const analysisEl = document.createElement('tr-ui-a-single-event-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+
+ const e = tr.ui.b.findDeepElementWithTextContent(
+ analysisEl, /Start\+End Stack Trace/);
+ assert.isDefined(e);
+ assert.isDefined(Polymer.dom(e).nextSibling.children[0].stackFrame);
+ assert.strictEqual(
+ Polymer.dom(e).nextSibling.children[0].stackFrame.title, 'a2');
+ });
+
+ test('analyzeSelectionWithSingleSlice', function() {
+ const selection = createSelectionWithSingleSlice();
+ const subView = document.createElement('tr-ui-a-single-event-sub-view');
+ subView.selection = selection;
+ this.addHTMLOutput(subView);
+
+ const table = tr.ui.b.findDeepElementMatching(
+ subView, 'tr-ui-b-table');
+ assert.strictEqual(table.tableRows.length, 3);
+ if (tr.isExported('tr-ui-e-chrome-codesearch')) {
+ assert.strictEqual(table.tableRows[0].value.innerText, 'b');
+ } else {
+ assert.strictEqual(table.tableRows[0].value, 'b');
+ }
+ assert.strictEqual(table.tableRows[1].value.value, 0);
+ assert.strictEqual(table.tableRows[1].value.unit,
+ tr.b.Unit.byName.timeStampInMs);
+ assert.strictEqual(table.tableRows[2].value.value, 0.002);
+ assert.strictEqual(table.tableRows[2].value.unit,
+ tr.b.Unit.byName.timeDurationInMs);
+ });
+
+ test('analyzeSelectionWithSingleSliceCategory', function() {
+ const selection = createSelectionWithSingleSlice({withCategory: true});
+
+ const subView = document.createElement('tr-ui-a-single-event-sub-view');
+ subView.selection = selection;
+ this.addHTMLOutput(subView);
+
+ const table = tr.ui.b.findDeepElementMatching(
+ subView, 'tr-ui-b-table');
+ assert.strictEqual(table.tableRows.length, 4);
+ if (tr.isExported('tr-ui-e-chrome-codesearch')) {
+ assert.strictEqual(table.tableRows[0].value.innerText, 'b');
+ } else {
+ assert.strictEqual(table.tableRows[0].value, 'b');
+ }
+ assert.strictEqual(table.tableRows[1].value, 'foo');
+ assert.strictEqual(table.tableRows[2].value.value, 0);
+ assert.strictEqual(table.tableRows[2].value.unit,
+ tr.b.Unit.byName.timeStampInMs);
+ assert.strictEqual(table.tableRows[3].value.value, 0.002);
+ assert.strictEqual(table.tableRows[3].value.unit,
+ tr.b.Unit.byName.timeDurationInMs);
+ });
+
+ test('instantiate_withSingleSliceContainingIDRef', function() {
+ const model = new Model();
+ const p1 = model.getOrCreateProcess(1);
+ const myObjectSlice = p1.objects.addSnapshot(
+ '0x1000', 'cat', 'my_object', 0);
+
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(newSliceEx({title: 'b', start: 0, duration: 2}));
+ t1.sliceGroup.slices[0].args.my_object = myObjectSlice;
+
+ const t1track = {};
+ t1track.thread = t1;
+
+ const selection = new EventSet();
+ selection.push(t1.sliceGroup.slices[0]);
+ assert.strictEqual(selection.length, 1);
+
+ const subView = document.createElement('tr-ui-a-single-event-sub-view');
+ subView.selection = selection;
+ this.addHTMLOutput(subView);
+
+ const analysisLink = tr.ui.b.findDeepElementMatching(subView,
+ 'tr-ui-a-analysis-link');
+ assert.isDefined(analysisLink);
+ });
+
+ test('instantiate_withSingleSliceContainingInfo', function() {
+ const slice = newSliceEx({title: 'b', start: 0, duration: 1});
+ slice.info = new tr.model.EventInfo(
+ 'Info title', 'Description');
+
+ const selection = new EventSet();
+ selection.push(slice);
+
+ const analysisEl = document.createElement('tr-ui-a-single-event-sub-view');
+ analysisEl.selection = selection;
+ this.addHTMLOutput(analysisEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view.html
new file mode 100644
index 00000000000..b201b161ffd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+
+<dom-module id="tr-ui-a-single-flow-event-sub-view">
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+ </style>
+ <tr-ui-a-single-event-sub-view id="singleEventSubView">
+ </tr-ui-a-single-event-sub-view>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+function createAnalysisLinkTo(event) {
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(
+ new tr.model.EventSet(event), event.userFriendlyName);
+ return linkEl;
+}
+
+Polymer({
+ is: 'tr-ui-a-single-flow-event-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ listeners: {
+ 'singleEventSubView.customize-rows': 'onCustomizeRows_'
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+ this.$.singleEventSubView.setSelectionWithoutErrorChecks(selection);
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ /**
+ * Event handler for an event that's fired after the single event sub view has
+ * finished row construction. This hook gives us the opportunity to customize
+ * the rows present in the sub view.
+ */
+ onCustomizeRows_(e) {
+ const event = tr.b.getOnlyElement(this.currentSelection_);
+ const rows = e.rows;
+
+ rows.unshift({
+ name: 'ID',
+ value: event.id
+ });
+ rows.push({
+ name: 'From',
+ value: createAnalysisLinkTo(event.startSlice)
+ });
+ rows.push({
+ name: 'To',
+ value: createAnalysisLinkTo(event.endSlice)
+ });
+ }
+});
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-flow-event-sub-view',
+ tr.model.FlowEvent,
+ {
+ multi: false,
+ title: 'Flow Event',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view_test.html
new file mode 100644
index 00000000000..31e3eb18f25
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_flow_event_sub_view_test.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const EventSet = tr.model.EventSet;
+ const TestUtils = tr.c.TestUtils;
+
+ test('analyzeSelectionWithSingleEvent', function() {
+ const model = TestUtils.newModel(function(model) {
+ model.p1 = model.getOrCreateProcess(1);
+ model.t2 = model.p1.getOrCreateThread(model.p1);
+ model.sA = model.t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
+ title: 'a', start: 0, end: 2
+ }));
+ model.sB = model.t2.sliceGroup.pushSlice(TestUtils.newSliceEx({
+ title: 'b', start: 9, end: 11
+ }));
+ model.fe = TestUtils.newFlowEventEx({
+ cat: 'cat',
+ id: 1234,
+ title: 'MyFlow',
+ start: 1,
+ end: 10,
+ startSlice: model.sA,
+ endSlice: model.sB
+ });
+ model.flowEvents.push(model.fe);
+ });
+
+ const selection = new EventSet();
+ selection.push(model.fe);
+ assert.strictEqual(selection.length, 1);
+
+ const subView = document.createElement('tr-ui-a-single-event-sub-view');
+ subView.isFlow = true;
+ subView.selection = selection;
+ this.addHTMLOutput(subView);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_frame_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_frame_sub_view.html
new file mode 100644
index 00000000000..e89fa2626ef
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_frame_sub_view.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/alert_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+
+<dom-module id='tr-ui-a-single-frame-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ #asv {
+ flex: 0 0 auto;
+ align-self: stretch;
+ }
+ </style>
+ <tr-ui-a-alert-sub-view id="asv">
+ </tr-ui-a-alert-sub-view>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-frame-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ ready() {
+ this.currentSelection_ = undefined;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+ this.$.asv.selection = tr.b.getOnlyElement(selection).associatedAlerts;
+ },
+
+ get relatedEventsToHighlight() {
+ if (!this.currentSelection_) return undefined;
+ return tr.b.getOnlyElement(this.currentSelection_).associatedEvents;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-frame-sub-view',
+ tr.model.Frame,
+ {
+ multi: false,
+ title: 'Frame',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_instant_event_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_instant_event_sub_view.html
new file mode 100644
index 00000000000..43b0e8a80cd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_instant_event_sub_view.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+
+<dom-module id='tr-ui-a-single-instant-event-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+ </style>
+ <div id='content'></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-instant-event-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ set selection(selection) {
+ Polymer.dom(this.$.content).textContent = '';
+ const realView = document.createElement('tr-ui-a-single-event-sub-view');
+ realView.setSelectionWithoutErrorChecks(selection);
+
+ Polymer.dom(this.$.content).appendChild(realView);
+
+ this.currentSelection_ = selection;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-instant-event-sub-view',
+ tr.model.InstantEvent,
+ {
+ multi: false,
+ title: 'Instant Event',
+ });
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-multi-instant-event-sub-view',
+ tr.model.InstantEvent,
+ {
+ multi: true,
+ title: 'Instant Events',
+ });
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_instant_event_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_instant_event_sub_view_test.html
new file mode 100644
index 00000000000..4ad85d2e6db
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_instant_event_sub_view_test.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const Thread = tr.model.Thread;
+ const EventSet = tr.model.EventSet;
+
+ test('analyzeSelectionWithSingleEvent', function() {
+ const model = new Model();
+ const p52 = model.getOrCreateProcess(52);
+ const t53 = p52.getOrCreateThread(53);
+
+ const ie = new tr.model.ProcessInstantEvent('cat', 'title', 7, 10, {});
+ ie.duration = 20;
+ p52.instantEvents.push(ie);
+
+
+ const selection = new EventSet();
+ selection.push(ie);
+ assert.strictEqual(selection.length, 1);
+
+ const subView = document.createElement(
+ 'tr-ui-a-single-instant-event-sub-view');
+ subView.selection = selection;
+
+ this.addHTMLOutput(subView);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_instance_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_instance_sub_view.html
new file mode 100644
index 00000000000..49810ab3fbd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_instance_sub_view.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/analysis/object_instance_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+
+<dom-module id='tr-ui-a-single-object-instance-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+
+ #snapshots > * {
+ display: block;
+ }
+
+ :host {
+ overflow: auto;
+ display: block;
+ }
+
+ * {
+ -webkit-user-select: text;
+ }
+
+ .title {
+ border-bottom: 1px solid rgb(128, 128, 128);
+ font-size: 110%;
+ font-weight: bold;
+ }
+
+ td, th {
+ font-family: monospace;
+ vertical-align: top;
+ }
+ </style>
+ <div id='content'></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-object-instance-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ get requiresTallView() {
+ if (this.$.content.children.length === 0) {
+ return false;
+ }
+ if (this.$.content.children[0] instanceof
+ tr.ui.analysis.ObjectInstanceView) {
+ return this.$.content.children[0].requiresTallView;
+ }
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ const instance = tr.b.getOnlyElement(selection);
+ if (!(instance instanceof tr.model.ObjectInstance)) {
+ throw new Error('Only supports object instances');
+ }
+
+ Polymer.dom(this.$.content).textContent = '';
+ this.currentSelection_ = selection;
+
+ const typeInfo = tr.ui.analysis.ObjectInstanceView.getTypeInfo(
+ instance.category, instance.typeName);
+ if (typeInfo) {
+ const customView = new typeInfo.constructor();
+ Polymer.dom(this.$.content).appendChild(customView);
+ customView.modelEvent = instance;
+ } else {
+ this.appendGenericAnalysis_(instance);
+ }
+ },
+
+ appendGenericAnalysis_(instance) {
+ let html = '';
+ html += '<div class="title">' +
+ instance.typeName + ' ' +
+ instance.id + '</div>\n';
+ html += '<table>';
+ html += '<tr>';
+ html += '<tr><td>creationTs:</td><td>' +
+ instance.creationTs + '</td></tr>\n';
+ if (instance.deletionTs !== Number.MAX_VALUE) {
+ html += '<tr><td>deletionTs:</td><td>' +
+ instance.deletionTs + '</td></tr>\n';
+ } else {
+ html += '<tr><td>deletionTs:</td><td>not deleted</td></tr>\n';
+ }
+ html += '<tr><td>snapshots:</td><td id="snapshots"></td></tr>\n';
+ html += '</table>';
+ Polymer.dom(this.$.content).innerHTML = html;
+ const snapshotsEl = Polymer.dom(this.$.content).querySelector('#snapshots');
+ instance.snapshots.forEach(function(snapshot) {
+ const snapshotLink = document.createElement('tr-ui-a-analysis-link');
+ snapshotLink.selection = new tr.model.EventSet(snapshot);
+ Polymer.dom(snapshotsEl).appendChild(snapshotLink);
+ });
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-object-instance-sub-view',
+ tr.model.ObjectInstance,
+ {
+ multi: false,
+ title: 'Object Instance',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_instance_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_instance_sub_view_test.html
new file mode 100644
index 00000000000..f5414dd957a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_instance_sub_view_test.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/single_object_instance_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ObjectInstance = tr.model.ObjectInstance;
+
+ test('analyzeSelectionWithObjectInstanceUnknownType', function() {
+ const i10 = new ObjectInstance(
+ {}, '0x1000', 'cat', 'someUnhandledName', 10);
+ const s10 = i10.addSnapshot(10, {foo: 1});
+ const s20 = i10.addSnapshot(20, {foo: 2});
+
+ const selection = new tr.model.EventSet();
+ selection.push(i10);
+
+ const view =
+ document.createElement('tr-ui-a-single-object-instance-sub-view');
+ view.selection = selection;
+ this.addHTMLOutput(view);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_snapshot_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_snapshot_sub_view.html
new file mode 100644
index 00000000000..5565db8d004
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_snapshot_sub_view.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/analysis/object_instance_view.html">
+<link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-single-object-snapshot-sub-view'>
+ <template>
+ <style>
+ #args {
+ white-space: pre;
+ }
+
+ :host {
+ overflow: auto;
+ display: flex;
+ }
+
+ ::content * {
+ -webkit-user-select: text;
+ }
+
+ ::content .title {
+ border-bottom: 1px solid rgb(128, 128, 128);
+ font-size: 110%;
+ font-weight: bold;
+ }
+
+ ::content td, th {
+ font-family: monospace;
+ vertical-align: top;
+ }
+ </style>
+ <slot></slot>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-object-snapshot-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ get requiresTallView() {
+ if (this.children.length === 0) {
+ return false;
+ }
+ if (this.children[0] instanceof tr.ui.analysis.ObjectSnapshotView) {
+ return this.children[0].requiresTallView;
+ }
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ const snapshot = tr.b.getOnlyElement(selection);
+ if (!(snapshot instanceof tr.model.ObjectSnapshot)) {
+ throw new Error('Only supports object instances');
+ }
+
+ Polymer.dom(this).textContent = '';
+ this.currentSelection_ = selection;
+
+ const typeInfo = tr.ui.analysis.ObjectSnapshotView.getTypeInfo(
+ snapshot.objectInstance.category, snapshot.objectInstance.typeName);
+ if (typeInfo) {
+ const customView = new typeInfo.constructor();
+ Polymer.dom(this).appendChild(customView);
+ customView.modelEvent = snapshot;
+ } else {
+ this.appendGenericAnalysis_(snapshot);
+ }
+ },
+
+ appendGenericAnalysis_(snapshot) {
+ const instance = snapshot.objectInstance;
+
+ Polymer.dom(this).textContent = '';
+
+ const titleEl = document.createElement('div');
+ Polymer.dom(titleEl).classList.add('title');
+ Polymer.dom(titleEl).appendChild(document.createTextNode('Snapshot of '));
+ Polymer.dom(this).appendChild(titleEl);
+
+ const instanceLinkEl = document.createElement('tr-ui-a-analysis-link');
+ instanceLinkEl.selection = new tr.model.EventSet(instance);
+ Polymer.dom(titleEl).appendChild(instanceLinkEl);
+
+ Polymer.dom(titleEl).appendChild(document.createTextNode(' @ '));
+
+ Polymer.dom(titleEl).appendChild(tr.v.ui.createScalarSpan(snapshot.ts, {
+ unit: tr.b.Unit.byName.timeStampInMs,
+ ownerDocument: this.ownerDocument,
+ inline: true,
+ }));
+
+ const tableEl = document.createElement('table');
+ Polymer.dom(this).appendChild(tableEl);
+
+ const rowEl = document.createElement('tr');
+ Polymer.dom(tableEl).appendChild(rowEl);
+
+ const labelEl = document.createElement('td');
+ Polymer.dom(labelEl).textContent = 'args:';
+ Polymer.dom(rowEl).appendChild(labelEl);
+
+ const argsEl = document.createElement('td');
+ argsEl.id = 'args';
+ Polymer.dom(rowEl).appendChild(argsEl);
+
+ const objectViewEl = document.createElement('tr-ui-a-generic-object-view');
+ objectViewEl.object = snapshot.args;
+ Polymer.dom(argsEl).appendChild(objectViewEl);
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-object-snapshot-sub-view',
+ tr.model.ObjectSnapshot,
+ {
+ multi: false,
+ title: 'Object Snapshot',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_snapshot_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_snapshot_sub_view_test.html
new file mode 100644
index 00000000000..41fca173931
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_object_snapshot_sub_view_test.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/single_object_snapshot_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate_snapshotView', function() {
+ const i10 = new tr.model.ObjectInstance(
+ {}, '0x1000', 'cat', 'name', 10);
+ const s10 = i10.addSnapshot(10, {foo: 1});
+ i10.updateBounds();
+
+ const selection = new tr.model.EventSet();
+ selection.push(s10);
+
+ const view =
+ document.createElement('tr-ui-a-single-object-snapshot-sub-view');
+ view.selection = selection;
+ this.addHTMLOutput(view);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_power_sample_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_power_sample_sub_view.html
new file mode 100644
index 00000000000..7396cfa3eca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_power_sample_sub_view.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-power-sample-table'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-power-sample-table',
+
+ ready() {
+ this.$.table.tableColumns = [
+ {
+ title: 'Time',
+ width: '100px',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.start, {
+ unit: tr.b.Unit.byName.timeStampInMs
+ });
+ }
+ },
+ {
+ title: 'Power',
+ width: '100%',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.powerInW, {
+ unit: tr.b.Unit.byName.powerInWatts
+ });
+ }
+ }
+ ];
+ this.sample = undefined;
+ },
+
+ get sample() {
+ return this.sample_;
+ },
+
+ set sample(sample) {
+ this.sample_ = sample;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ if (this.sample === undefined) {
+ this.$.table.tableRows = [];
+ } else {
+ this.$.table.tableRows = [this.sample];
+ }
+ this.$.table.rebuild();
+ }
+});
+</script>
+
+<dom-module id='tr-ui-a-single-power-sample-sub-view'>
+ <template>
+ <style>
+ :host { display: block; }
+ </style>
+ <tr-ui-a-power-sample-table id="samplesTable">
+ </tr-ui-a-power-sample-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-power-sample-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ ready() {
+ this.currentSelection_ = undefined;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ if (this.selection.length !== 1) {
+ throw new Error('Cannot pass multiple samples to sample table.');
+ }
+ this.$.samplesTable.sample = tr.b.getOnlyElement(this.selection);
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-power-sample-sub-view',
+ tr.model.PowerSample,
+ {
+ multi: false,
+ title: 'Power Sample',
+ });
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_power_sample_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_power_sample_sub_view_test.html
new file mode 100644
index 00000000000..8ee1dfcf899
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_power_sample_sub_view_test.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_series.html">
+<link rel="import" href="/tracing/ui/analysis/single_power_sample_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const model = new tr.Model();
+ const series = new tr.model.PowerSeries(model.device);
+ series.addPowerSample(1, 1);
+
+ const view = document.createElement('tr-ui-a-single-power-sample-sub-view');
+ view.selection = new tr.model.EventSet(series.samples);
+
+ this.addHTMLOutput(view);
+ });
+
+ test('setSelection', function() {
+ const model = new tr.Model();
+ const series = new tr.model.PowerSeries(model.device);
+ series.addPowerSample(1, 1);
+
+ const view = document.createElement('tr-ui-a-single-power-sample-sub-view');
+ const eventSet = new tr.model.EventSet(series.samples);
+ view.selection = eventSet;
+
+ assert.deepEqual(view.$.samplesTable.sample,
+ tr.b.getOnlyElement(series.samples));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_sample_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_sample_sub_view.html
new file mode 100644
index 00000000000..851c60952ff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_sample_sub_view.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/stack_frame.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-single-sample-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="content"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-sample-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ ready() {
+ this.$.content.tableColumns = [
+ {
+ title: '',
+ value: row => row.title,
+ width: '100px'
+ },
+ {
+ title: '',
+ value: row => row.value,
+ width: '100%'
+ }
+ ];
+ this.$.content.showHeader = false;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+
+ if (this.currentSelection_ === undefined) {
+ this.$.content.tableRows = [];
+ return;
+ }
+
+ const sample = tr.b.getOnlyElement(this.currentSelection_);
+ const table = this.$.content;
+ const rows = [];
+
+ rows.push({
+ title: 'Title',
+ value: sample.title
+ });
+
+ rows.push({
+ title: 'Sample time',
+ value: tr.v.ui.createScalarSpan(sample.start, {
+ unit: tr.b.Unit.byName.timeStampInMs,
+ ownerDocument: this.ownerDocument
+ })
+ });
+
+ const callStackTableEl = document.createElement('tr-ui-b-table');
+ callStackTableEl.tableRows = sample.getNodesAsArray().reverse();
+ callStackTableEl.tableColumns = [
+ {
+ title: 'function name',
+ value: row => row.functionName || '(anonymous function)'
+ },
+ {
+ title: 'location',
+ value: row => row.url
+ }
+ ];
+ callStackTableEl.rebuild();
+ rows.push({
+ title: 'Call stack',
+ value: callStackTableEl
+ });
+ table.tableRows = rows;
+ table.rebuild();
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-sample-sub-view',
+ tr.model.Sample,
+ {
+ multi: false,
+ title: 'Sample',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_sample_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_sample_sub_view_test.html
new file mode 100644
index 00000000000..7f8c131f82c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_sample_sub_view_test.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/single_sample_sub_view.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const EventSet = tr.model.EventSet;
+ const newSampleNamed = tr.c.TestUtils.newSampleNamed;
+
+ test('instantiate_withSingleSample', function() {
+ let t53;
+ const model = tr.c.TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback(model) {
+ t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
+ model.samples.push(newSampleNamed(t53, 'X', 'my-category',
+ ['a', 'b', 'c'], 0.184));
+ }
+ });
+
+ const t53track = {};
+ t53track.thread = t53;
+
+ const selection = new EventSet();
+
+ assert.strictEqual(selection.length, 0);
+ selection.push(t53.samples[0]);
+ assert.strictEqual(selection.length, 1);
+
+ const view = document.createElement('tr-ui-a-single-sample-sub-view');
+ view.selection = selection;
+ this.addHTMLOutput(view);
+
+ const table = tr.ui.b.findDeepElementMatching(
+ view, 'tr-ui-b-table');
+
+ const rows = table.tableRows;
+ assert.strictEqual(rows.length, 3);
+ assert.strictEqual(rows[0].value, 'X');
+ assert.strictEqual(rows[1].value.value, 0.184);
+ assert.strictEqual(rows[1].value.unit, tr.b.Unit.byName.timeStampInMs);
+
+ const callStackRows = rows[2].value.tableRows;
+ assert.lengthOf(callStackRows, 3);
+ assert.deepEqual(callStackRows.map(x => x.title), ['a', 'b', 'c']);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view.html
new file mode 100644
index 00000000000..720fdfeb65a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/related_events.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+
+<dom-module id='tr-ui-a-single-thread-slice-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: row;
+ }
+ #events {
+ display: flex;
+ flex-direction: column;
+ }
+
+ </style>
+ <tr-ui-a-single-event-sub-view id="content"></tr-ui-a-single-event-sub-view>
+ <div id="events">
+ <tr-ui-a-related-events id="relatedEvents">
+ </tr-ui-a-related-events>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-thread-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.content.selection = selection;
+ this.$.relatedEvents.setRelatedEvents(selection);
+ if (this.$.relatedEvents.hasRelatedEvents()) {
+ this.$.relatedEvents.style.display = '';
+ } else {
+ this.$.relatedEvents.style.display = 'none';
+ }
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-thread-slice-sub-view',
+ tr.model.ThreadSlice,
+ {
+ multi: false,
+ title: 'Slice',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view_test.html
new file mode 100644
index 00000000000..84bb292384e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_slice_sub_view_test.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+<link rel="import" href="/tracing/ui/analysis/single_thread_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const newFlowEventEx = tr.c.TestUtils.newFlowEventEx;
+
+ test('instantiate', function() {
+ const model = new tr.Model();
+ const t53 = model.getOrCreateProcess(52).getOrCreateThread(53);
+ t53.sliceGroup.pushSlice(
+ newSliceEx({title: 'a', start: 0.0, duration: 0.5}));
+ t53.sliceGroup.createSubSlices();
+
+ const selection = new tr.model.EventSet();
+ selection.push(t53.sliceGroup.slices[0]);
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-single-thread-slice-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ });
+
+ test('instantiateWithFlowEvent', function() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+
+ m.t2 = m.p1.getOrCreateThread(2);
+ m.t3 = m.p1.getOrCreateThread(3);
+ m.t4 = m.p1.getOrCreateThread(4);
+
+ m.sA = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'a', start: 0, end: 5,
+ type: tr.model.ThreadSlice}));
+ m.sB = m.t3.sliceGroup.pushSlice(
+ newSliceEx({title: 'b', start: 10, end: 15,
+ type: tr.model.ThreadSlice}));
+ m.sC = m.t4.sliceGroup.pushSlice(
+ newSliceEx({title: 'c', start: 20, end: 20,
+ type: tr.model.ThreadSlice}));
+
+ m.t2.createSubSlices();
+ m.t3.createSubSlices();
+ m.t4.createSubSlices();
+
+ m.f1 = newFlowEventEx({
+ title: 'flowish', start: 0, end: 10,
+ startSlice: m.sA,
+ endSlice: m.sB
+ });
+ m.f2 = newFlowEventEx({
+ title: 'flowish', start: 15, end: 21,
+ startSlice: m.sB,
+ endSlice: m.sC
+ });
+ });
+
+ const selection = new tr.model.EventSet();
+ selection.push(m.sA);
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-single-thread-slice-sub-view');
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view.html
new file mode 100644
index 00000000000..225b2729769
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-single-thread-time-slice-sub-view'>
+ <template>
+ <style>
+ table {
+ border-collapse: collapse;
+ border-width: 0;
+ margin-bottom: 25px;
+ width: 100%;
+ }
+
+ table tr > td:first-child {
+ padding-left: 2px;
+ }
+
+ table tr > td {
+ padding: 2px 4px 2px 4px;
+ vertical-align: text-top;
+ width: 150px;
+ }
+
+ table td td {
+ padding: 0 0 0 0;
+ width: auto;
+ }
+ tr {
+ vertical-align: top;
+ }
+
+ tr:nth-child(2n+0) {
+ background-color: #e2e2e2;
+ }
+ </style>
+ <table>
+ <tr>
+ <td>Running process:</td><td id="process-name"></td>
+ </tr>
+ <tr>
+ <td>Running thread:</td><td id="thread-name"></td>
+ </tr>
+ <tr>
+ <td>State:</td>
+ <td><b><span id="state"></span></b></td>
+ </tr>
+ <tr>
+ <td>Start:</td>
+ <td>
+ <tr-v-ui-scalar-span id="start">
+ </tr-v-ui-scalar-span>
+ </td>
+ </tr>
+ <tr>
+ <td>Duration:</td>
+ <td>
+ <tr-v-ui-scalar-span id="duration">
+ </tr-v-ui-scalar-span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>On CPU:</td><td id="on-cpu"></td>
+ </tr>
+
+ <tr>
+ <td>Running instead:</td><td id="running-instead"></td>
+ </tr>
+
+ <tr>
+ <td>Args:</td><td id="args"></td>
+ </tr>
+ </table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-thread-time-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ const timeSlice = tr.b.getOnlyElement(selection);
+
+ if (!(timeSlice instanceof tr.model.ThreadTimeSlice)) {
+ throw new Error('Only supports thread time slices');
+ }
+
+ this.currentSelection_ = selection;
+
+ const thread = timeSlice.thread;
+
+ const root = Polymer.dom(this.root);
+ Polymer.dom(root.querySelector('#state')).textContent =
+ timeSlice.title;
+ const stateColor = tr.b.ColorScheme.colorsAsStrings[timeSlice.colorId];
+ root.querySelector('#state').style.backgroundColor = stateColor;
+
+ Polymer.dom(root.querySelector('#process-name')).textContent =
+ thread.parent.userFriendlyName;
+ Polymer.dom(root.querySelector('#thread-name')).textContent =
+ thread.userFriendlyName;
+
+ root.querySelector('#start').setValueAndUnit(
+ timeSlice.start, tr.b.Unit.byName.timeStampInMs);
+ root.querySelector('#duration').setValueAndUnit(
+ timeSlice.duration, tr.b.Unit.byName.timeDurationInMs);
+
+ const onCpuEl = root.querySelector('#on-cpu');
+ Polymer.dom(onCpuEl).textContent = '';
+ const runningInsteadEl = root.querySelector('#running-instead');
+ if (timeSlice.cpuOnWhichThreadWasRunning) {
+ Polymer.dom(runningInsteadEl.parentElement).removeChild(runningInsteadEl);
+
+ const cpuLink = document.createElement('tr-ui-a-analysis-link');
+ cpuLink.selection = new tr.model.EventSet(
+ timeSlice.getAssociatedCpuSlice());
+ Polymer.dom(cpuLink).textContent =
+ timeSlice.cpuOnWhichThreadWasRunning.userFriendlyName;
+ Polymer.dom(onCpuEl).appendChild(cpuLink);
+ } else {
+ Polymer.dom(onCpuEl.parentElement).removeChild(onCpuEl);
+
+ const cpuSliceThatTookCpu = timeSlice.getCpuSliceThatTookCpu();
+ if (cpuSliceThatTookCpu) {
+ const cpuLink = document.createElement('tr-ui-a-analysis-link');
+ cpuLink.selection = new tr.model.EventSet(cpuSliceThatTookCpu);
+ if (cpuSliceThatTookCpu.thread) {
+ Polymer.dom(cpuLink).textContent =
+ cpuSliceThatTookCpu.thread.userFriendlyName;
+ } else {
+ Polymer.dom(cpuLink).textContent = cpuSliceThatTookCpu.title;
+ }
+ Polymer.dom(runningInsteadEl).appendChild(cpuLink);
+ } else {
+ Polymer.dom(runningInsteadEl.parentElement).removeChild(
+ runningInsteadEl);
+ }
+ }
+
+ const argsEl = root.querySelector('#args');
+ if (Object.keys(timeSlice.args).length > 0) {
+ const argsView =
+ document.createElement('tr-ui-a-generic-object-view');
+ argsView.object = timeSlice.args;
+
+ argsEl.parentElement.style.display = '';
+ Polymer.dom(argsEl).textContent = '';
+ Polymer.dom(argsEl).appendChild(argsView);
+ } else {
+ argsEl.parentElement.style.display = 'none';
+ }
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-thread-time-slice-sub-view',
+ tr.model.ThreadTimeSlice,
+ {
+ multi: false,
+ title: 'Thread Timeslice',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view_test.html
new file mode 100644
index 00000000000..bfffd41861b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view_test.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/single_thread_time_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createBasicModel() {
+ const lines = [
+ 'Android.launcher-584 [001] d..3 12622.506890: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] d..3 12622.506918: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=D ==> next_comm=Android.launcher next_pid=584 next_prio=120', // @suppress longLineCheck
+ 'Android.launcher-584 [001] d..4 12622.506936: sched_wakeup: comm=Binder_1 pid=217 prio=120 success=1 target_cpu=001', // @suppress longLineCheck
+ 'Android.launcher-584 [001] d..3 12622.506950: sched_switch: prev_comm=Android.launcher prev_pid=584 prev_prio=120 prev_state=R+ ==> next_comm=Binder_1 next_pid=217 next_prio=120', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507057: tracing_mark_write: B|128|queueBuffer', // @suppress longLineCheck
+ ' Binder_1-217 [001] ...1 12622.507175: tracing_mark_write: E',
+ ' Binder_1-217 [001] d..3 12622.507253: sched_switch: prev_comm=Binder_1 prev_pid=217 prev_prio=120 prev_state=S ==> next_comm=Android.launcher next_pid=584 next_prio=120' // @suppress longLineCheck
+ ];
+
+ return tr.c.TestUtils.newModelWithEvents([lines.join('\n')], {
+ shiftWorldToZero: false
+ });
+ }
+
+ test('runningSlice', function() {
+ const m = createBasicModel();
+
+ const cpu = m.kernel.cpus[1];
+ const binderSlice = cpu.slices[0];
+ assert.strictEqual(binderSlice.title, 'Binder_1');
+ const launcherSlice = cpu.slices[1];
+ assert.strictEqual(launcherSlice.title, 'Android.launcher');
+
+
+ const thread = m.findAllThreadsNamed('Binder_1')[0];
+
+ const view = document.createElement(
+ 'tr-ui-a-single-thread-time-slice-sub-view');
+ const selection = new tr.model.EventSet();
+ selection.push(thread.timeSlices[0]);
+ view.selection = selection;
+ this.addHTMLOutput(view);
+
+ // Clicking the analysis link should focus the Binder1's timeslice.
+ let didSelectionChangeHappen = false;
+ view.addEventListener('requestSelectionChange', function(e) {
+ assert.isTrue(e.selection.equals(new tr.model.EventSet(binderSlice)));
+ didSelectionChangeHappen = true;
+ });
+ Polymer.dom(view.root).querySelector('tr-ui-a-analysis-link').click();
+ assert.isTrue(didSelectionChangeHappen);
+ });
+
+ test('sleepingSlice', function() {
+ const m = createBasicModel();
+
+ const cpu = m.kernel.cpus[1];
+ const binderSlice = cpu.slices[0];
+ assert.strictEqual(binderSlice.title, 'Binder_1');
+ const launcherSlice = cpu.slices[1];
+ assert.strictEqual(launcherSlice.title, 'Android.launcher');
+
+
+ const thread = m.findAllThreadsNamed('Binder_1')[0];
+
+ const view = document.createElement(
+ 'tr-ui-a-single-thread-time-slice-sub-view');
+ const selection = new tr.model.EventSet();
+ selection.push(thread.timeSlices[1]);
+ view.selection = selection;
+ this.addHTMLOutput(view);
+
+ // Clicking the analysis link should focus the Android.launcher slice
+ let didSelectionChangeHappen = false;
+ view.addEventListener('requestSelectionChange', function(e) {
+ assert.isTrue(e.selection.equals(new tr.model.EventSet(launcherSlice)));
+ didSelectionChangeHappen = true;
+ });
+ Polymer.dom(view.root).querySelector('tr-ui-a-analysis-link').click();
+ assert.isTrue(didSelectionChangeHappen);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_user_expectation_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_user_expectation_sub_view.html
new file mode 100644
index 00000000000..76110b4b468
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/single_user_expectation_sub_view.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+<link rel="import"
+ href="/tracing/ui/analysis/user_expectation_related_samples_table.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-a-single-user-expectation-sub-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: row;
+ }
+ #events {
+ display: flex;
+ flex-direction: column;
+ }
+ </style>
+ <tr-ui-a-single-event-sub-view id="realView"></tr-ui-a-single-event-sub-view>
+ <div id="events">
+ <tr-ui-a-user-expectation-related-samples-table id="relatedSamples"></tr-ui-a-user-expectation-related-samples-table>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-single-user-expectation-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ created() {
+ this.currentSelection_ = undefined;
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ set selection(selection) {
+ this.$.realView.addEventListener('customize-rows',
+ this.onCustomizeRows_.bind(this));
+
+ this.currentSelection_ = selection;
+ this.$.realView.setSelectionWithoutErrorChecks(selection);
+
+ this.$.relatedSamples.selection = selection;
+ if (this.$.relatedSamples.hasRelatedSamples()) {
+ this.$.events.style.display = '';
+ } else {
+ this.$.events.style.display = 'none';
+ }
+ },
+
+ get relatedEventsToHighlight() {
+ if (!this.currentSelection_) return undefined;
+ return tr.b.getOnlyElement(this.currentSelection_).associatedEvents;
+ },
+
+ onCustomizeRows_(event) {
+ const ue = tr.b.getOnlyElement(this.selection);
+
+ if (ue.rawCpuMs) {
+ event.rows.push({
+ name: 'Total CPU',
+ value: tr.v.ui.createScalarSpan(ue.totalCpuMs, {
+ unit: tr.b.Unit.byName.timeDurationInMs
+ })
+ });
+ }
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-single-user-expectation-sub-view',
+ tr.model.um.UserExpectation,
+ {
+ multi: false,
+ title: 'User Expectation',
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/stack_frame.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stack_frame.html
new file mode 100644
index 00000000000..92c4594af5f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stack_frame.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-a-stack-frame'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-stack-frame',
+
+ ready() {
+ this.stackFrame_ = undefined;
+ this.$.table.tableColumns = [];
+ this.$.table.showHeader = true;
+ },
+
+ get stackFrame() {
+ return this.stackFrame_;
+ },
+
+ set stackFrame(stackFrame) {
+ const table = this.$.table;
+
+ this.stackFrame_ = stackFrame;
+ if (stackFrame === undefined) {
+ table.tableColumns = [];
+ table.tableRows = [];
+ table.rebuild();
+ return;
+ }
+
+ let hasName = false;
+ let hasTitle = false;
+
+ table.tableRows = stackFrame.stackTrace;
+ table.tableRows.forEach(function(row) {
+ hasName |= row.name !== undefined;
+ hasTitle |= row.title !== undefined;
+ });
+
+ const cols = [];
+ if (hasName) {
+ cols.push({
+ title: 'Name',
+ value(row) { return row.name; }
+ });
+ }
+
+ if (hasTitle) {
+ cols.push({
+ title: 'Title',
+ value(row) { return row.title; }
+ });
+ }
+
+ table.tableColumns = cols;
+ table.rebuild();
+ },
+
+ tableForTesting() {
+ return this.$.table;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/stack_frame_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stack_frame_test.html
new file mode 100644
index 00000000000..4523906a321
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stack_frame_test.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/analysis/stack_frame.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const model = new tr.Model();
+ const fA = tr.c.TestUtils.newStackTrace(model, ['a1', 'a2', 'a3']);
+
+ const stackFrameView = document.createElement('tr-ui-a-stack-frame');
+ stackFrameView.stackFrame = fA;
+ this.addHTMLOutput(stackFrameView);
+ });
+
+ test('clearingStackFrame', function() {
+ const model = new tr.Model();
+ const fA = tr.c.TestUtils.newStackTrace(model, ['a1', 'a2', 'a3']);
+
+ const stackFrameView = document.createElement('tr-ui-a-stack-frame');
+ stackFrameView.stackFrame = fA;
+ stackFrameView.stackFrame = undefined;
+
+ assert.isUndefined(stackFrameView.stackFrame);
+ assert.lengthOf(stackFrameView.$.table.$.body.children, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane.html
new file mode 100644
index 00000000000..0e4f633fb00
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/rebuildable_behavior.html">
+
+<!--
+@fileoverview Analysis view stacked pane. See the stacked pane view element
+(tr-ui-a-stacked-pane-view) documentation for more details.
+-->
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ const StackedPaneImpl = {
+ /**
+ * Request changing the child pane of this pane in the associated stacked
+ * pane view. If the assigned builder is undefined, request removing the
+ * current child pane.
+ *
+ * Note that setting this property before appended() is called will have no
+ * effect (as there will be no listener attached to the pane).
+ *
+ * This method is intended to be called by subclasses.
+ */
+ set childPaneBuilder(childPaneBuilder) {
+ this.childPaneBuilder_ = childPaneBuilder;
+ this.dispatchEvent(new tr.b.Event('request-child-pane-change'));
+ },
+
+ get childPaneBuilder() {
+ return this.childPaneBuilder_;
+ },
+
+ /**
+ * Called right after the pane is appended to a pane view.
+ *
+ * This method triggers an immediate rebuild by default. Subclasses are
+ * free to change this behavior (e.g. if a pane has lots of data to display,
+ * it might decide to defer rebuilding in order not to cause jank).
+ */
+ appended() {
+ this.rebuild();
+ }
+ };
+
+ const StackedPane = [tr.ui.analysis.RebuildableBehavior, StackedPaneImpl];
+
+ return {
+ StackedPane,
+ };
+});
+
+Polymer({
+ is: 'tr-ui-a-stacked-pane',
+ behaviors: [tr.ui.analysis.StackedPane]
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_test.html
new file mode 100644
index 00000000000..7af70fa3d7a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_test.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/stacked_pane.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('changeChildPane', function() {
+ const pane = document.createElement('tr-ui-a-stacked-pane');
+ let didFireEvent;
+ pane.addEventListener('request-child-pane-change', function() {
+ didFireEvent = true;
+ });
+
+ didFireEvent = false;
+ pane.childPaneBuilder = undefined;
+ assert.isTrue(didFireEvent);
+
+ didFireEvent = false;
+ pane.childPaneBuilder = function() {
+ return undefined;
+ };
+ assert.isTrue(didFireEvent);
+
+ didFireEvent = false;
+ pane.childPaneBuilder = function() {
+ return document.createElement('tr-ui-a-stacked-pane');
+ };
+ assert.isTrue(didFireEvent);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_view.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_view.html
new file mode 100644
index 00000000000..e8bea2dd034
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_view.html
@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<!--
+@fileoverview Analysis view container which displays vertically stacked panes.
+The panes represent a hierarchy where a child pane contains the details of the
+current selection in its parent pane. The container provides simple primitives
+for panes to request changing their child pane:
+
+ +=<tr-ui-a-stacked-pane-view>=+ +=<tr-ui-a-stacked-pane-view>=+
+ |+.<tr-ui-a-stacked-pane>....+| |+.<tr-ui-a-stacked-pane>....+|
+ |: Pane 1 +| ===========> |: Pane 1 +|
+ |+...........................+| Pane 1 |+...........................+|
+ |+.<tr-ui-a-stacked-pane>....+| requests |+.<tr-ui-a-stacked-pane>....+|
+ |: Pane 2 (detail of Pane 1) +| child pane |: Pane 4 (detail of Pane 1) +|
+ |+...........................+| change (e.g. |+...........................+|
+ |+.<tr-ui-a-stacked-pane>....+| selection +=============================+
+ |: Pane 3 (detail of Pane 2) +| changed)
+ |+...........................+|
+ +=============================+
+
+Note that the actual UI provided by tr-ui-a-stacked-pane-view and
+tr-ui-a-stacked-pane is merely a wrapper container with flex box vertical
+stacking. No other visual features (such as pane spacing or borders) is
+provided by either element.
+
+The stacked pane element (tr-ui-a-stacked-pane) is defined in a separate file.
+
+Sample use case:
+
+ Create an empty stacked pane view and add it to the DOM:
+
+ const paneView = document.createElement('tr-ui-a-stacked-pane-view');
+ Polymer.dom(someParentView).appendChild(paneView);
+
+ Define one or more pane subclasses:
+
+ TODO(polymer): Write this documentation
+ <polymer-element name="some-pane-1" extends="tr-ui-a-stacked-pane">
+ ...
+ </polymer-element>
+
+ Set the top-level pane (by providing a builder function):
+
+ paneView.setPaneBuilder(function() {
+ const topPane = document.createElement('some-pane-1');
+ pane.someProperty = someValue;
+ return topPane;
+ });
+
+ Show a child pane with details upon user interaction (these methods should be
+ in the definition of the pane subclass Polymer element):
+
+ ready: function() {
+ this.$.table.addEventListener(
+ 'selection-changed', this.changeChildPane_.bind(this));
+ }
+
+ changeChildPane_: function() {
+ this.childPaneBuilder = function() {
+ const selectedRow = this.$.table.selectedTableRow;
+ const detailsPane = document.createElement('some-pane-2');
+ detailsPane.someProperty = selectedRow;
+ return detailsPane;
+ }.bind(this);
+ }
+-->
+<dom-module id='tr-ui-a-stacked-pane-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+
+ #pane_container > * {
+ flex: 0 0 auto;
+ }
+ </style>
+ <div id="pane_container">
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-stacked-pane-view',
+
+ /**
+ * Add a pane to the stacked pane view. This method performs two operations:
+ *
+ * 1. Remove existing descendant panes
+ * If the optional parent pane is provided, all its current descendant
+ * panes are removed. Otherwise, all panes are removed from the view.
+ *
+ * 2. Build and add new pane
+ * If a pane builder is provided and returns a pane, the new pane is
+ * appended to the view (after the provided parent, or at the top).
+ */
+ setPaneBuilder(paneBuilder, opt_parentPane) {
+ const paneContainer = this.$.pane_container;
+
+ // If the parent pane is provided, it must be an HTML element and a child
+ // of the pane container.
+ if (opt_parentPane) {
+ if (!(opt_parentPane instanceof HTMLElement)) {
+ throw new Error('Parent pane must be an HTML element');
+ }
+ if (opt_parentPane.parentElement !== paneContainer) {
+ throw new Error('Parent pane must be a child of the pane container');
+ }
+ }
+
+ // Remove all descendants of the parent pane (or all panes if no parent
+ // pane was specified) in reverse order.
+ while (Polymer.dom(paneContainer).lastElementChild !== null &&
+ Polymer.dom(paneContainer).lastElementChild !== opt_parentPane) {
+ const removedPane = Polymer.dom(this.$.pane_container).lastElementChild;
+ const listener = this.listeners_.get(removedPane);
+ if (listener === undefined) {
+ throw new Error('No listener associated with pane');
+ }
+ this.listeners_.delete(removedPane);
+ removedPane.removeEventListener(
+ 'request-child-pane-change', listener);
+ Polymer.dom(paneContainer).removeChild(removedPane);
+ }
+
+ if (opt_parentPane && opt_parentPane.parentElement !== paneContainer) {
+ throw new Error('Parent pane was removed from the pane container');
+ }
+
+ // This check is performed here (and not at the beginning of the method)
+ // because undefined pane builder means that the parent pane requested
+ // having no child pane (e.g. when selection is cleared).
+ if (!paneBuilder) return;
+
+ const pane = paneBuilder();
+ if (!pane) return;
+
+ if (!(pane instanceof HTMLElement)) {
+ throw new Error('Pane must be an HTML element');
+ }
+
+ // Listen for child pane change requests from the newly added pane.
+ const listener = function(event) {
+ this.setPaneBuilder(pane.childPaneBuilder, pane);
+ }.bind(this);
+ if (!this.listeners_) {
+ // Instead of initializing the listeners map in a created() callback,
+ // we do it lazily here so that subclasses could provide their own
+ // created() callback (Polymer currently doesn't allow calling overriden
+ // superclass methods in strict mode).
+ this.listeners_ = new WeakMap();
+ }
+ this.listeners_.set(pane, listener);
+ pane.addEventListener('request-child-pane-change', listener);
+
+ Polymer.dom(paneContainer).appendChild(pane);
+ pane.appended();
+ },
+
+ /**
+ * Request rebuilding all panes in the view. The panes are rebuilt from the
+ * top to the bottom (so that parent panes could request changing their
+ * child panes when they're being rebuilt and the newly constructed child
+ * panes would be rebuilt as well).
+ */
+ rebuild() {
+ let currentPane = Polymer.dom(this.$.pane_container).firstElementChild;
+ while (currentPane) {
+ currentPane.rebuild();
+ currentPane = currentPane.nextElementSibling;
+ }
+ },
+
+ // For testing purposes.
+ get panesForTesting() {
+ const panes = [];
+ let currentChild = Polymer.dom(this.$.pane_container).firstElementChild;
+ while (currentChild) {
+ panes.push(currentChild);
+ currentChild = currentChild.nextElementSibling;
+ }
+ return panes;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_view_test.html
new file mode 100644
index 00000000000..ceae19ab0db
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stacked_pane_view_test.html
@@ -0,0 +1,205 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/stacked_pane.html">
+<link rel="import" href="/tracing/ui/analysis/stacked_pane_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createPaneView() {
+ return document.createElement('tr-ui-a-stacked-pane-view');
+ }
+
+ function createPane(paneId, opt_rebuildPaneCallback, opt_appendedCallback) {
+ const paneEl = document.createElement('tr-ui-a-stacked-pane');
+ paneEl.paneId = paneId;
+
+ const divEl = document.createElement('div');
+ Polymer.dom(divEl).textContent = 'Pane ' + paneId;
+ divEl.style.width = '400px';
+ divEl.style.background = '#ccc';
+ divEl.style.textAlign = 'center';
+ Polymer.dom(paneEl).appendChild(divEl);
+
+ if (opt_rebuildPaneCallback) {
+ paneEl.onRebuild_ = opt_rebuildPaneCallback;
+ }
+
+ if (opt_appendedCallback) {
+ paneEl.appended = opt_appendedCallback;
+ }
+
+ return paneEl;
+ }
+
+ function createPaneBuilder(paneId, opt_rebuildPaneCallback,
+ opt_appendedCallback) {
+ return createPane.bind(
+ undefined, paneId, opt_rebuildPaneCallback, opt_appendedCallback);
+ }
+
+ function assertPanes(paneView, expectedPaneIds) {
+ const actualPaneIds = paneView.panesForTesting.map(function(pane) {
+ return pane.paneId;
+ });
+ assert.deepEqual(actualPaneIds, expectedPaneIds);
+ }
+
+ test('instantiate_empty', function() {
+ const viewEl = createPaneView();
+ viewEl.rebuild();
+ assertPanes(viewEl, []);
+ // Don't add the pane to HTML output because it has zero height.
+ });
+
+ test('instantiate_singlePane', function() {
+ const viewEl = createPaneView();
+
+ viewEl.setPaneBuilder(createPaneBuilder(1));
+ viewEl.rebuild();
+
+ assertPanes(viewEl, [1]);
+ this.addHTMLOutput(viewEl);
+ });
+
+ test('instantiate_multiplePanes', function() {
+ const viewEl = createPaneView();
+
+ viewEl.setPaneBuilder(createPaneBuilder(1));
+ viewEl.setPaneBuilder(createPaneBuilder(2), viewEl.panesForTesting[0]);
+ viewEl.setPaneBuilder(createPaneBuilder(3), viewEl.panesForTesting[1]);
+
+ assertPanes(viewEl, [1, 2, 3]);
+ this.addHTMLOutput(viewEl);
+ });
+
+ test('changePanes', function() {
+ const viewEl = createPaneView();
+
+ viewEl.setPaneBuilder(createPaneBuilder(1));
+ assertPanes(viewEl, [1]);
+
+ viewEl.setPaneBuilder(null);
+ assertPanes(viewEl, []);
+
+ viewEl.setPaneBuilder(createPaneBuilder(2));
+ assertPanes(viewEl, [2]);
+
+ viewEl.setPaneBuilder(createPaneBuilder(3), viewEl.panesForTesting[0]);
+ assertPanes(viewEl, [2, 3]);
+
+ viewEl.setPaneBuilder(createPaneBuilder(4), viewEl.panesForTesting[0]);
+ assertPanes(viewEl, [2, 4]);
+
+ viewEl.setPaneBuilder(createPaneBuilder(5), viewEl.panesForTesting[1]);
+ assertPanes(viewEl, [2, 4, 5]);
+
+ viewEl.setPaneBuilder(createPaneBuilder(6), viewEl.panesForTesting[2]);
+ assertPanes(viewEl, [2, 4, 5, 6]);
+
+ viewEl.setPaneBuilder(createPaneBuilder(7), viewEl.panesForTesting[1]);
+ assertPanes(viewEl, [2, 4, 7]);
+
+ this.addHTMLOutput(viewEl);
+ });
+
+ test('childPanes', function() {
+ const viewEl = createPaneView();
+
+ viewEl.setPaneBuilder(createPaneBuilder(1));
+ assertPanes(viewEl, [1]);
+
+ // Pane 1 requests a child pane 2.
+ const pane1 = viewEl.panesForTesting[0];
+ pane1.childPaneBuilder = createPaneBuilder(2);
+ assertPanes(viewEl, [1, 2]);
+
+ // Pane 2 requests removing its child pane (nothing happens).
+ const pane2 = viewEl.panesForTesting[1];
+ pane2.childPaneBuilder = undefined;
+ assertPanes(viewEl, [1, 2]);
+
+ // Pane 2 requests a child pane 3.
+ pane2.childPaneBuilder = createPaneBuilder(3);
+ assertPanes(viewEl, [1, 2, 3]);
+
+ // Pane 2 requests a child pane 4 (its previous child pane 3 is removed).
+ pane2.childPaneBuilder = createPaneBuilder(4);
+ assertPanes(viewEl, [1, 2, 4]);
+
+ // Pane 1 requests removing its child pane (panes 2 and 4 are removed).
+ pane1.childPaneBuilder = undefined;
+ assertPanes(viewEl, [1]);
+
+ // Check that removed panes cannot affect the pane view.
+ pane2.childPaneBuilder = createPaneBuilder(5);
+ assertPanes(viewEl, [1]);
+
+ // Pane 1 requests a child pane 6 (check that everything still works).
+ pane1.childPaneBuilder = createPaneBuilder(6);
+ assertPanes(viewEl, [1, 6]);
+
+ // Change the top pane to pane 7.
+ viewEl.setPaneBuilder(createPaneBuilder(7));
+ assertPanes(viewEl, [7]);
+
+ // Check that removed panes cannot affect the pane view.
+ pane1.childPaneBuilder = createPaneBuilder(5);
+ assertPanes(viewEl, [7]);
+ });
+
+ test('rebuild', function() {
+ const viewEl = createPaneView();
+
+ const rebuiltPaneIds = [];
+ const rebuildPaneCallback = function() {
+ rebuiltPaneIds.push(this.paneId);
+ };
+
+ viewEl.setPaneBuilder(createPaneBuilder(1, rebuildPaneCallback));
+ viewEl.setPaneBuilder(createPaneBuilder(2, rebuildPaneCallback),
+ viewEl.panesForTesting[0]);
+ viewEl.setPaneBuilder(createPaneBuilder(3, rebuildPaneCallback),
+ viewEl.panesForTesting[1]);
+
+ // Rebuild isn't triggered.
+ assert.deepEqual(rebuiltPaneIds, []);
+
+ // Rebuild is triggered, but it isn't necessary (all panes are clean).
+ viewEl.rebuild();
+ assert.deepEqual(rebuiltPaneIds, []);
+
+ // All panes are now marked as dirty, but rebuild isn't triggered (it was
+ // only scheduled).
+ viewEl.panesForTesting.forEach(function(pane) {
+ pane.scheduleRebuild_();
+ });
+ assert.deepEqual(rebuiltPaneIds, []);
+
+ // Finally, rebuild was triggered and the panes are dirty.
+ viewEl.rebuild();
+ assert.deepEqual(rebuiltPaneIds, [1, 2, 3]);
+
+ // Make sure that panes are clean after the previous rebuild.
+ viewEl.rebuild();
+ assert.deepEqual(rebuiltPaneIds, [1, 2, 3]);
+ });
+
+ test('appended', function() {
+ const viewEl = createPaneView();
+ let didFireAppended;
+
+ didFireAppended = false;
+ viewEl.setPaneBuilder(createPaneBuilder(1, undefined, function() {
+ didFireAppended = true;
+ }));
+ assert.isTrue(didFireAppended);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/stub_analysis_table.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stub_analysis_table.html
new file mode 100644
index 00000000000..b371eac4cf9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/stub_analysis_table.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ function StubAnalysisTable() {
+ this.ownerDocument_ = document;
+ this.nodes_ = [];
+ }
+
+ StubAnalysisTable.prototype = {
+ __proto__: Object.protoype,
+
+ get ownerDocument() {
+ return this.ownerDocument_;
+ },
+
+ appendChild(node) {
+ if (node.tagName === 'TFOOT' || node.tagName === 'THEAD' ||
+ node.tagName === 'TBODY') {
+ node.__proto__ = StubAnalysisTable.prototype;
+ node.nodes_ = [];
+ node.ownerDocument_ = document;
+ }
+ this.nodes_.push(node);
+ },
+
+ get lastNode() {
+ return this.nodes_.pop();
+ },
+
+ get nodeCount() {
+ return this.nodes_.length;
+ }
+ };
+
+ return {
+ StubAnalysisTable,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/user_expectation_related_samples_table.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/user_expectation_related_samples_table.html
new file mode 100644
index 00000000000..3c2bfdbd9cf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/user_expectation_related_samples_table.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-a-user-expectation-related-samples-table'>
+ <template>
+ <style>
+ #table {
+ flex: 1 1 auto;
+ align-self: stretch;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-a-user-expectation-related-samples-table',
+
+ ready() {
+ this.samples_ = [];
+ this.$.table.tableColumns = [
+ {
+ title: 'Event(s)',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.type;
+ if (row.tooltip) {
+ typeEl.title = row.tooltip;
+ }
+ return typeEl;
+ },
+ width: '150px'
+ },
+ {
+ title: 'Link',
+ width: '100%',
+ value(row) {
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ if (row.name) {
+ linkEl.setSelectionAndContent(row.selection, row.name);
+ } else {
+ linkEl.selection = row.selection;
+ }
+ return linkEl;
+ }
+ }
+ ];
+ },
+
+ hasRelatedSamples() {
+ return (this.samples_ && this.samples_.length > 0);
+ },
+
+ set selection(eventSet) {
+ this.samples_ = [];
+ const samples = new tr.model.EventSet;
+ eventSet.forEach(function(ue) {
+ samples.addEventSet(ue.associatedSamples);
+ }.bind(this));
+
+ if (samples.length > 0) {
+ this.samples_.push({
+ type: 'Overlapping samples',
+ tooltip: 'All samples overlapping the selected user expectation(s).',
+ selection: samples
+ });
+ }
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ const table = this.$.table;
+ if (this.samples_ && this.samples_.length > 0) {
+ table.tableRows = this.samples_.slice();
+ } else {
+ table.tableRows = [];
+ }
+ table.rebuild();
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/analysis/user_expectation_related_samples_table_test.html b/chromium/third_party/catapult/tracing/tracing/ui/analysis/user_expectation_related_samples_table_test.html
new file mode 100644
index 00000000000..368f41ce6c6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/analysis/user_expectation_related_samples_table_test.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/sample.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+<link rel="import"
+ href="/tracing/ui/analysis/user_expectation_related_samples_table.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createModel() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+ const node = tr.c.TestUtils.newProfileNodes(m, ['fake']);
+ const s1 = new tr.model.Sample(1, 'a_1', node, m.t2);
+ const s2 = new tr.model.Sample(2, 'a_2', node, m.t2);
+ const s3 = new tr.model.Sample(3, 'a_3', node, m.t2);
+ const s4 = new tr.model.Sample(4, 'a_4', node, m.t2);
+ const s5 = new tr.model.Sample(5, 'a_5', node, m.t2);
+ const s6 = new tr.model.Sample(6, 'a_6', node, m.t2);
+ m.samples.push(s1, s2, s3, s4, s5, s6);
+ m.ve = new tr.c.TestUtils.newSliceEx(
+ {title: 'V8.Execute', start: 0, end: 4, type: tr.model.ThreadSlice});
+ m.t2.sliceGroup.pushSlice(m.ve);
+ m.up = new tr.c.TestUtils.newInteractionRecord(m, 0, 4);
+ m.up.associatedEvents.push(m.ve);
+ m.userModel.expectations.push(m.up);
+ });
+ return m;
+ }
+
+ test('overlappingSamples', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement(
+ 'tr-ui-a-user-expectation-related-samples-table');
+ viewEl.selection = new tr.model.EventSet([m.up]);
+
+ let overlappingSamples;
+ viewEl.$.table.tableRows.forEach(function(row) {
+ if (row.type === 'Overlapping samples') {
+ assert.isUndefined(overlappingSamples);
+ overlappingSamples = row.selection;
+ }
+ });
+
+ const samplesTitles = overlappingSamples.map(function(e) {
+ return e.title;
+ });
+ assert.sameMembers(samplesTitles,
+ ['a_1', 'a_2', 'a_3', 'a_4']);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/annotations/annotation_view.html b/chromium/third_party/catapult/tracing/tracing/ui/annotations/annotation_view.html
new file mode 100644
index 00000000000..48ba2ac9fa7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/annotations/annotation_view.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.annotations', function() {
+ /**
+ * A base class for all annotation views.
+ * @constructor
+ */
+ function AnnotationView(viewport, annotation) {
+ }
+
+ AnnotationView.prototype = {
+ draw(ctx) {
+ throw new Error('Not implemented');
+ }
+ };
+
+ return {
+ AnnotationView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/annotations/annotation_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/annotations/annotation_view_test.html
new file mode 100644
index 00000000000..3a3b3615f91
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/annotations/annotation_view_test.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/comment_box_annotation.html">
+<link rel="import" href="/tracing/model/location.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/rect_annotation.html">
+<link rel="import" href="/tracing/model/x_marker_annotation.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createPopulatedTimeline() {
+ const model = new tr.Model();
+ const process = model.getOrCreateProcess(1);
+ const thread = process.getOrCreateThread(2);
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {title: 'a', start: 80, duration: 50}));
+
+ const timeline = document.createElement('tr-ui-timeline-track-view');
+ const vp = new tr.ui.TimelineViewport(timeline);
+ timeline.model = model;
+ timeline.style.maxHeight = '600px';
+
+ return timeline;
+ }
+
+ test('rectAnnotation', function() {
+ const fakeYComponents1 = [{stableId: '1.2', yPercentOffset: 0.3}];
+ const fakeYComponents2 = [{stableId: '1.2', yPercentOffset: 0.9}];
+ const start = new tr.model.Location(50, fakeYComponents1);
+ const end = new tr.model.Location(100, fakeYComponents2);
+ const rectAnnotation = new tr.model.RectAnnotation(start, end);
+
+ const timeline = createPopulatedTimeline();
+ timeline.model.addAnnotation(rectAnnotation);
+ this.addHTMLOutput(timeline);
+ });
+
+ test('xMarkerAnnotation', function() {
+ const xMarkerAnnotation = new tr.model.XMarkerAnnotation(90);
+
+ const timeline = createPopulatedTimeline();
+ const model = timeline.model;
+ timeline.model.addAnnotation(xMarkerAnnotation);
+ this.addHTMLOutput(timeline);
+ });
+
+ test('commentBoxAnnotation', function() {
+ const fakeYComponents = [{stableId: '1.2', yPercentOffset: 0.5}];
+ const location = new tr.model.Location(120, fakeYComponents);
+ const text = 'abc';
+ const commentBoxAnnotation =
+ new tr.model.CommentBoxAnnotation(location, text);
+
+ const timeline = createPopulatedTimeline();
+ timeline.model.addAnnotation(commentBoxAnnotation);
+ this.addHTMLOutput(timeline);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/annotations/comment_box_annotation_view.html b/chromium/third_party/catapult/tracing/tracing/ui/annotations/comment_box_annotation_view.html
new file mode 100644
index 00000000000..5237b9b0f55
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/annotations/comment_box_annotation_view.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/annotations/annotation_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.annotations', function() {
+ /**
+ * A view of a comment box consisting of a textarea and a line to the
+ * actual location.
+ * @extends {AnnotationView}
+ * @constructor
+ */
+ function CommentBoxAnnotationView(viewport, annotation) {
+ this.viewport_ = viewport;
+ this.annotation_ = annotation;
+ this.textArea_ = undefined;
+
+ this.styleWidth = 250;
+ this.styleHeight = 50;
+ this.fontSize = 10;
+ this.rightOffset = 50;
+ this.topOffset = 25;
+ }
+
+ CommentBoxAnnotationView.prototype = {
+ __proto__: tr.ui.annotations.AnnotationView.prototype,
+
+ removeTextArea() {
+ Polymer.dom(Polymer.dom(this.textArea_).parentNode).removeChild(
+ this.textArea_);
+ },
+
+ draw(ctx) {
+ const coords = this.annotation_.location.toViewCoordinates(
+ this.viewport_);
+ if (coords.viewX < 0) {
+ if (this.textArea_) {
+ this.textArea_.style.visibility = 'hidden';
+ }
+ return;
+ }
+
+ // Set up textarea element.
+ if (!this.textArea_) {
+ this.textArea_ = document.createElement('textarea');
+ this.textArea_.style.position = 'absolute';
+ this.textArea_.readOnly = true;
+ this.textArea_.value = this.annotation_.text;
+ // Set the z-index so that this is shown on top of canvas.
+ this.textArea_.style.zIndex = 1;
+ Polymer.dom(Polymer.dom(ctx.canvas).parentNode)
+ .appendChild(this.textArea_);
+ }
+
+ this.textArea_.style.width = this.styleWidth + 'px';
+ this.textArea_.style.height = this.styleHeight + 'px';
+ this.textArea_.style.fontSize = this.fontSize + 'px';
+ this.textArea_.style.visibility = 'visible';
+
+ // Update positions to latest coordinate.
+ this.textArea_.style.left =
+ coords.viewX + ctx.canvas.getBoundingClientRect().left +
+ this.rightOffset + 'px';
+ this.textArea_.style.top =
+ coords.viewY - ctx.canvas.getBoundingClientRect().top -
+ this.topOffset + 'px';
+
+ // Draw pointer line from offset to actual location.
+ ctx.strokeStyle = 'rgb(0, 0, 0)';
+ ctx.lineWidth = 2;
+ ctx.beginPath();
+ tr.ui.b.drawLine(ctx, coords.viewX,
+ coords.viewY - ctx.canvas.getBoundingClientRect().top,
+ coords.viewX + this.rightOffset,
+ coords.viewY - this.topOffset -
+ ctx.canvas.getBoundingClientRect().top);
+ ctx.stroke();
+ }
+ };
+
+ return {
+ CommentBoxAnnotationView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/annotations/rect_annotation_view.html b/chromium/third_party/catapult/tracing/tracing/ui/annotations/rect_annotation_view.html
new file mode 100644
index 00000000000..16e5f920eea
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/annotations/rect_annotation_view.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/annotations/annotation_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.annotations', function() {
+ /**
+ * A view responsible for drawing a single highlight rectangle box on
+ * the timeline.
+ * @extends {AnnotationView}
+ * @constructor
+ */
+ function RectAnnotationView(viewport, annotation) {
+ this.viewport_ = viewport;
+ this.annotation_ = annotation;
+ }
+
+ RectAnnotationView.prototype = {
+ __proto__: tr.ui.annotations.AnnotationView.prototype,
+
+ draw(ctx) {
+ const dt = this.viewport_.currentDisplayTransform;
+ const startCoords =
+ this.annotation_.startLocation.toViewCoordinates(this.viewport_);
+ const endCoords =
+ this.annotation_.endLocation.toViewCoordinates(this.viewport_);
+
+ // Prevent drawing into the ruler track by clamping the initial Y
+ // point and the rect's Y size.
+ let startY = startCoords.viewY - ctx.canvas.getBoundingClientRect().top;
+ const sizeY = endCoords.viewY - startCoords.viewY;
+ if (startY + sizeY < 0) {
+ // In this case sizeY is negative. If final Y is negative,
+ // overwrite startY so that the rectangle ends at y=0.
+ startY = sizeY;
+ } else if (startY < 0) {
+ startY = 0;
+ }
+
+ ctx.fillStyle = this.annotation_.fillStyle;
+ ctx.fillRect(startCoords.viewX, startY,
+ endCoords.viewX - startCoords.viewX, sizeY);
+ }
+ };
+
+ return {
+ RectAnnotationView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/annotations/x_marker_annotation_view.html b/chromium/third_party/catapult/tracing/tracing/ui/annotations/x_marker_annotation_view.html
new file mode 100644
index 00000000000..933ea17ca57
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/annotations/x_marker_annotation_view.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/annotations/annotation_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.annotations', function() {
+ /**
+ * A view that draws a vertical line on the timeline at a specific timestamp.
+ * @extends {AnnotationView}
+ * @constructor
+ */
+ function XMarkerAnnotationView(viewport, annotation) {
+ this.viewport_ = viewport;
+ this.annotation_ = annotation;
+ }
+
+ XMarkerAnnotationView.prototype = {
+ __proto__: tr.ui.annotations.AnnotationView.prototype,
+
+ draw(ctx) {
+ const dt = this.viewport_.currentDisplayTransform;
+ const viewX = dt.xWorldToView(this.annotation_.timestamp);
+
+ ctx.beginPath();
+ tr.ui.b.drawLine(ctx, viewX, 0, viewX, ctx.canvas.height);
+ ctx.strokeStyle = this.annotation_.strokeStyle;
+ ctx.stroke();
+ }
+ };
+
+ return {
+ XMarkerAnnotationView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/animation.html b/chromium/third_party/catapult/tracing/tracing/ui/base/animation.html
new file mode 100644
index 00000000000..46c62818fc3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/animation.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * Represents a procedural animation that can be run by an
+ * tr.ui.b.AnimationController.
+ *
+ * @constructor
+ */
+ function Animation() {
+ }
+
+ Animation.prototype = {
+
+ /**
+ * Called when an animation has been queued after a running animation.
+ *
+ * @return {boolean} True if the animation can take on the responsibilities
+ * of the running animation. If true, takeOverFor will be called on the
+ * animation.
+ *
+ * This can be used to build animations that accelerate as pairs of them are
+ * queued.
+ */
+ canTakeOverFor(existingAnimation) {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * Called to take over responsiblities of an existingAnimation.
+ *
+ * At this point, the existingAnimation has been ticked one last time, then
+ * stopped. This animation will be started after this returns and has the
+ * job of finishing(or transitioning away from) the effect the existing
+ * animation was trying to accomplish.
+ */
+ takeOverFor(existingAnimation, newStartTimestamp, target) {
+ throw new Error('Not implemented');
+ },
+
+ start(timestamp, target) {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * Called when an animation is stopped before it finishes. The animation can
+ * do what it wants here, usually nothing.
+ *
+ * @param {Number} timestamp When the animation was stopped.
+ * @param {Object} target The object being animated. May be undefined, take
+ * care.
+ * @param {boolean} willBeTakenOverByAnotherAnimation Whether this animation
+ * is going to be handed to another animation's takeOverFor function.
+ */
+ didStopEarly(timestamp, target,
+ willBeTakenOverByAnotherAnimation) {
+ },
+
+ /**
+ * @return {boolean} true if the animation is finished.
+ */
+ tick(timestamp, target) {
+ throw new Error('Not implemented');
+ }
+ };
+
+ return {
+ Animation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/animation_controller.html b/chromium/third_party/catapult/tracing/tracing/ui/base/animation_controller.html
new file mode 100644
index 00000000000..a6149cba5fb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/animation_controller.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/ui/base/animation.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * Manages execution, queueing and blending of tr.ui.b.Animations against
+ * a single target.
+ *
+ * Targets must have a cloneAnimationState() method that returns all the
+ * animatable states of that target.
+ *
+ * @constructor
+ * @extends {tr.b.EventTarget}
+ */
+ function AnimationController() {
+ tr.b.EventTarget.call(this);
+
+ this.target_ = undefined;
+
+ this.activeAnimation_ = undefined;
+
+ this.tickScheduled_ = false;
+ }
+
+ AnimationController.prototype = {
+ __proto__: tr.b.EventTarget.prototype,
+
+ get target() {
+ return this.target_;
+ },
+
+ set target(target) {
+ if (this.activeAnimation_) {
+ throw new Error('Cannot change target while animation is running.');
+ }
+ if (target.cloneAnimationState === undefined ||
+ typeof target.cloneAnimationState !== 'function') {
+ throw new Error('target must have a cloneAnimationState function');
+ }
+
+ this.target_ = target;
+ },
+
+ get activeAnimation() {
+ return this.activeAnimation_;
+ },
+
+ get hasActiveAnimation() {
+ return !!this.activeAnimation_;
+ },
+
+ queueAnimation(animation, opt_now) {
+ if (this.target_ === undefined) {
+ throw new Error('Cannot queue animations without a target');
+ }
+
+ let now;
+ if (opt_now !== undefined) {
+ now = opt_now;
+ } else {
+ now = window.performance.now();
+ }
+
+ if (this.activeAnimation_) {
+ // Must tick the animation before stopping it case its about to stop,
+ // and to update the target with its final sets of edits up to this
+ // point.
+ const done = this.activeAnimation_.tick(now, this.target_);
+ if (done) {
+ this.activeAnimation_ = undefined;
+ }
+ }
+
+ if (this.activeAnimation_) {
+ if (animation.canTakeOverFor(this.activeAnimation_)) {
+ this.activeAnimation_.didStopEarly(now, this.target_, true);
+ animation.takeOverFor(this.activeAnimation_, now, this.target_);
+ } else {
+ this.activeAnimation_.didStopEarly(now, this.target_, false);
+ }
+ }
+ this.activeAnimation_ = animation;
+ this.activeAnimation_.start(now, this.target_);
+
+ if (this.tickScheduled_) return;
+ this.tickScheduled_ = true;
+ tr.b.requestAnimationFrame(this.tickActiveAnimation_, this);
+ },
+
+ cancelActiveAnimation(opt_now) {
+ if (!this.activeAnimation_) return;
+ let now;
+ if (opt_now !== undefined) {
+ now = opt_now;
+ } else {
+ now = window.performance.now();
+ }
+ this.activeAnimation_.didStopEarly(now, this.target_, false);
+ this.activeAnimation_ = undefined;
+ },
+
+ tickActiveAnimation_(frameBeginTime) {
+ this.tickScheduled_ = false;
+ if (!this.activeAnimation_) return;
+
+ if (this.target_ === undefined) {
+ this.activeAnimation_.didStopEarly(frameBeginTime, this.target_, false);
+ return;
+ }
+
+ const oldTargetState = this.target_.cloneAnimationState();
+
+ const done = this.activeAnimation_.tick(frameBeginTime, this.target_);
+ if (done) {
+ this.activeAnimation_ = undefined;
+ }
+
+ if (this.activeAnimation_) {
+ this.tickScheduled_ = true;
+ tr.b.requestAnimationFrame(this.tickActiveAnimation_, this);
+ }
+
+ if (oldTargetState) {
+ const e = new tr.b.Event('didtick');
+ e.oldTargetState = oldTargetState;
+ this.dispatchEvent(e, false, false);
+ }
+ }
+ };
+
+ return {
+ AnimationController,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/animation_controller_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/animation_controller_test.html
new file mode 100644
index 00000000000..9366ab4db2b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/animation_controller_test.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/animation_controller.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function SimpleAnimation(options) {
+ this.stopTime = options.stopTime;
+
+ this.startCalled = false;
+ this.didStopEarlyCalled = false;
+ this.wasTakenOver = false;
+ this.tickCount = 0;
+ }
+
+ SimpleAnimation.prototype = {
+ __proto__: tr.ui.b.Animation.prototype,
+
+ canTakeOverFor(existingAnimation) {
+ return false;
+ },
+
+ takeOverFor(existingAnimation, newStartTimestamp, target) {
+ throw new Error('Not implemented');
+ },
+
+ start(timestamp, target) {
+ this.startCalled = true;
+ },
+
+ didStopEarly(timestamp, target, willBeTakenOver) {
+ this.didStopEarlyCalled = true;
+ this.wasTakenOver = willBeTakenOver;
+ },
+
+ /**
+ * @return {boolean} true if the animation is finished.
+ */
+ tick(timestamp, target) {
+ this.tickCount++;
+ return timestamp >= this.stopTime;
+ }
+ };
+
+ test('cancel', function() {
+ const target = {
+ x: 0,
+ cloneAnimationState() { return {x: this.x}; }
+ };
+
+ const controller = new tr.ui.b.AnimationController();
+ controller.target = target;
+
+ const animation = new SimpleAnimation({stopTime: 100});
+ controller.queueAnimation(animation);
+
+ tr.b.forcePendingRAFTasksToRun(0);
+ assert.strictEqual(animation.tickCount, 1);
+ controller.cancelActiveAnimation();
+ assert.isFalse(controller.hasActiveAnimation);
+ assert.isTrue(animation.didStopEarlyCalled);
+ });
+
+ test('simple', function() {
+ const target = {
+ x: 0,
+ cloneAnimationState() { return {x: this.x}; }
+ };
+
+ const controller = new tr.ui.b.AnimationController();
+ controller.target = target;
+
+ const animation = new SimpleAnimation({stopTime: 100});
+ controller.queueAnimation(animation);
+
+ tr.b.forcePendingRAFTasksToRun(0);
+ assert.strictEqual(animation.tickCount, 1);
+ assert.isTrue(controller.hasActiveAnimation);
+
+ tr.b.forcePendingRAFTasksToRun(100);
+ assert.strictEqual(animation.tickCount, 2);
+ assert.isFalse(controller.hasActiveAnimation);
+ });
+
+ test('queueTwo', function() {
+ // Clear all pending rafs so if something is lingering it will blow up here.
+ tr.b.forcePendingRAFTasksToRun(0);
+
+ const target = {
+ x: 0,
+ cloneAnimationState() { return {x: this.x}; }
+ };
+
+ const controller = new tr.ui.b.AnimationController();
+ controller.target = target;
+
+ const a1 = new SimpleAnimation({stopTime: 100});
+ const a2 = new SimpleAnimation({stopTime: 100});
+ controller.queueAnimation(a1, 0);
+ assert.isTrue(a1.startCalled);
+ controller.queueAnimation(a2, 50);
+ assert.isTrue(a1.didStopEarlyCalled);
+ assert.isTrue(a2.startCalled);
+
+ tr.b.forcePendingRAFTasksToRun(150);
+ assert.isFalse(controller.hasActiveAnimation);
+ assert.isAbove(a2.tickCount, 0);
+ });
+
+ /**
+ * @constructor
+ */
+ function AnimationThatCanTakeOverForSimpleAnimation() {
+ this.takeOverForAnimation = undefined;
+ }
+
+ AnimationThatCanTakeOverForSimpleAnimation.prototype = {
+ __proto__: tr.ui.b.Animation.prototype,
+
+
+ canTakeOverFor(existingAnimation) {
+ return existingAnimation instanceof SimpleAnimation;
+ },
+
+ takeOverFor(existingAnimation, newStartTimestamp, target) {
+ this.takeOverForAnimation = existingAnimation;
+ },
+
+ start(timestamp, target) {
+ this.startCalled = true;
+ }
+ };
+
+ test('takeOver', function() {
+ const target = {
+ x: 0,
+ cloneAnimationState() { return {x: this.x}; }
+ };
+
+ const controller = new tr.ui.b.AnimationController();
+ controller.target = target;
+
+ const a1 = new SimpleAnimation({stopTime: 100});
+ const a2 = new AnimationThatCanTakeOverForSimpleAnimation();
+ controller.queueAnimation(a1, 0);
+ assert.isTrue(a1.startCalled);
+ assert.strictEqual(a1.tickCount, 0);
+ controller.queueAnimation(a2, 10);
+ assert.isTrue(a1.didStopEarlyCalled);
+ assert.isTrue(a1.wasTakenOver);
+ assert.strictEqual(a1.tickCount, 1);
+
+ assert.strictEqual(a1, a2.takeOverForAnimation);
+ assert.isTrue(a2.startCalled);
+
+ controller.cancelActiveAnimation();
+ assert.isFalse(controller.hasActiveAnimation);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/bar_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/base/bar_chart.html
new file mode 100644
index 00000000000..1745861cbe4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/bar_chart.html
@@ -0,0 +1,253 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/column_chart.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const BarChart = tr.ui.b.define('bar-chart', tr.ui.b.ColumnChart);
+
+ BarChart.prototype = {
+ __proto__: tr.ui.b.ColumnChart.prototype,
+
+ decorate() {
+ super.decorate();
+ this.verticalScale_ = undefined;
+ this.horizontalScale_ = undefined;
+ this.isWaterfall_ = false;
+ },
+
+ updateScales_() {
+ super.updateScales_();
+ this.yScale_.range([this.graphWidth, 0]);
+ this.xScale_.range([0, this.graphHeight]);
+ this.verticalScale_ = this.isYLogScale_ ? d3.scale.log(10) :
+ d3.scale.linear();
+ this.verticalScale_.domain(this.xScale_.domain());
+ this.verticalScale_.range([this.graphHeight, 0]);
+ this.horizontalScale_ = d3.scale.linear();
+ this.horizontalScale_.domain(this.yScale_.domain());
+ this.horizontalScale_.range([0, this.graphWidth]);
+ },
+
+ set isWaterfall(waterfall) {
+ this.isWaterfall_ = waterfall;
+ if (waterfall) {
+ this.getDataSeries('hide').color = 'transparent';
+ }
+ this.updateContents_();
+ },
+
+ get isWaterfall() {
+ return this.isWaterfall_;
+ },
+
+ get defaultGraphHeight() {
+ return Math.max(20, 10 * this.data_.length);
+ },
+
+ get defaultGraphWidth() {
+ return 100;
+ },
+
+ get barHeight() {
+ return this.graphHeight / this.data.length;
+ },
+
+ drawBrush_(brushRectsSel) {
+ brushRectsSel
+ .attr('x', 0)
+ .attr('width', this.graphWidth)
+ .attr('y', d => this.verticalScale_(d.max))
+ .attr('height', d =>
+ this.verticalScale_(d.min) - this.verticalScale_(d.max))
+ .attr('fill', 'rgb(213, 236, 229)');
+ },
+
+ getDataPointAtChartPoint_(chartPoint) {
+ const flippedPoint = {
+ x: this.graphHeight - chartPoint.y,
+ y: this.graphWidth - chartPoint.x
+ };
+ return super.getDataPointAtChartPoint_(flippedPoint);
+ },
+
+ drawXAxis_(xAxis) {
+ xAxis.attr('transform', 'translate(0,' + this.graphHeight + ')')
+ .call(d3.svg.axis()
+ .scale(this.horizontalScale_)
+ .orient('bottom'));
+ },
+
+ get yAxisWidth() {
+ return this.computeScaleTickWidth_(this.verticalScale_);
+ },
+
+ drawYAxis_(yAxis) {
+ const axisModifier = d3.svg.axis()
+ .scale(this.verticalScale_)
+ .orient('left');
+ yAxis.call(axisModifier);
+ },
+
+ drawHoverValueBox_(rect) {
+ const rectHoverEvent = new tr.b.Event('rect-mouseenter');
+ rectHoverEvent.rect = rect;
+ this.dispatchEvent(rectHoverEvent);
+
+ if (!this.enableHoverBox || (this.isWaterfall_ && rect.key === 'hide')) {
+ return;
+ }
+
+ const seriesKeys = [...this.seriesByKey_.keys()];
+ const chartAreaSel = d3.select(this.chartAreaElement);
+ chartAreaSel.selectAll('.hover').remove();
+ let keyWidthPx = 0;
+ let keyHeightPx = 0;
+ let xWidthPx = 0;
+ let xHeightPx = 0;
+ let groupWidthPx = 0;
+ let groupHeightPx = 0;
+ if (seriesKeys.length > 1 && !this.isGrouped && !this.isWaterfall_) {
+ keyWidthPx = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, rect.key).width;
+ keyHeightPx = this.textHeightPx_;
+ }
+ if (this.data.length > 1 && !this.isWaterfall_) {
+ xWidthPx = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, '' + rect.datum.x).width;
+ xHeightPx = this.textHeightPx_;
+ }
+ if (this.isGrouped && rect.datum.group !== undefined) {
+ groupWidthPx = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, rect.datum.group).width;
+ groupHeightPx = this.textHeightPx_;
+ }
+ const valueWidthPx = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, rect.value).width;
+ const valueHeightPx = this.textHeightPx_;
+ const maxWidthPx = Math.max(keyWidthPx, xWidthPx,
+ groupWidthPx, valueWidthPx) + 5;
+ const hoverWidthPx = this.isGrouped ? maxWidthPx : Math.min(maxWidthPx,
+ Math.max(50, rect.widthPx));
+ let hoverTopPx = rect.topPx;
+ hoverTopPx = Math.min(
+ hoverTopPx, this.getBoundingClientRect().height -
+ valueHeightPx);
+ let hoverLeftPx = rect.leftPx + (rect.widthPx / 2);
+ hoverLeftPx = Math.max(hoverLeftPx - hoverWidthPx, -this.margin.left);
+
+ chartAreaSel
+ .append('rect')
+ .attr('class', 'hover')
+ .attr('fill', 'white')
+ .attr('x', hoverLeftPx)
+ .attr('y', hoverTopPx)
+ .attr('width', hoverWidthPx)
+ .attr('height', keyHeightPx + xHeightPx +
+ valueHeightPx + groupHeightPx);
+
+ if (seriesKeys.length > 1 && !this.isGrouped && !this.isWaterfall_) {
+ chartAreaSel
+ .append('text')
+ .attr('class', 'hover')
+ .attr('fill', rect.color === 'transparent' ? '#000000' : rect.color)
+ .attr('x', hoverLeftPx + 2)
+ .attr('y', hoverTopPx + keyHeightPx - 3)
+ .text(rect.key);
+ }
+ if (this.data.length > 1 && !this.isWaterfall_) {
+ chartAreaSel
+ .append('text')
+ .attr('class', 'hover')
+ .attr('fill', rect.color === 'transparent' ? '#000000' : rect.color)
+ .attr('x', hoverLeftPx + 2)
+ .attr('y', hoverTopPx + keyHeightPx + valueHeightPx - 3)
+ .text('' + rect.datum.x);
+ }
+ if (this.isGrouped && rect.datum.group !== undefined) {
+ chartAreaSel
+ .append('text')
+ .on('mouseleave', () => this.clearHoverValueBox_(rect))
+ .attr('class', 'hover')
+ .attr('fill', rect.color === 'transparent' ? '#000000' : rect.color)
+ .attr('x', hoverLeftPx + 2)
+ .attr('y', hoverTopPx + keyHeightPx + xHeightPx + groupHeightPx - 3)
+ .text(rect.datum.group);
+ }
+ chartAreaSel
+ .append('text')
+ .attr('class', 'hover')
+ .attr('fill', rect.color === 'transparent' ? '#000000' : rect.color)
+ .attr('x', hoverLeftPx + 2)
+ .attr('y', hoverTopPx + xHeightPx + keyHeightPx +
+ groupHeightPx + valueHeightPx - 3)
+ .text(rect.value);
+ },
+
+ flipRect_(rect) {
+ // Flip |rect| around |y=x|.
+ return {
+ datum: rect.datum,
+ index: rect.index,
+ key: rect.key,
+ value: rect.value,
+ color: rect.color,
+ topPx: this.graphHeight - rect.leftPx - rect.widthPx,
+ leftPx: this.graphWidth - rect.topPx - rect.heightPx,
+ widthPx: rect.heightPx,
+ heightPx: rect.widthPx,
+ underflow: rect.underflow,
+ overflow: rect.overflow,
+ };
+ },
+
+ drawRect_(rect, sel) {
+ super.drawRect_(this.flipRect_(rect), sel);
+ },
+
+ drawUnderflow_(rect, rectsSel) {
+ let sel = rectsSel.data([rect]);
+ sel.enter().append('text')
+ .text('*')
+ .attr('fill', rect.color)
+ .attr('x', 0)
+ .attr('y', this.graphHeight - rect.leftPx +
+ 3 + (rect.widthPx / 2));
+ sel.exit().remove();
+
+ sel = rectsSel.data([rect]);
+ sel.enter().append('rect')
+ .attr('fill', 'rgba(0, 0, 0, 0)')
+ .attr('x', 0)
+ .attr('y', this.graphHeight - rect.leftPx - rect.widthPx)
+ .attr('width', 10)
+ .attr('height', rect.widthPx)
+ .on('mouseenter', () => this.drawHoverValueBox_(this.flipRect_(rect)))
+ .on('mouseleave', () => this.clearHoverValueBox_(rect));
+ sel.exit().remove();
+ },
+
+ drawOverflow_(rect, sel) {
+ sel = sel.data([rect]);
+ sel.enter().append('text')
+ .text('*')
+ .attr('fill', rect.color)
+ .attr('x', this.graphWidth)
+ .attr('y', this.graphHeight - rect.leftPx +
+ 3 + (rect.widthPx / 2));
+ sel.exit().remove();
+ }
+ };
+
+ return {
+ BarChart,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/bar_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/bar_chart_test.html
new file mode 100644
index 00000000000..48e5ff778aa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/bar_chart_test.html
@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/assert_utils.html">
+<link rel="import" href="/tracing/ui/base/bar_chart.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiation_singleSeries', function() {
+ const chart = new tr.ui.b.BarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, value: 100},
+ {x: 20, value: 110},
+ {x: 30, value: 100},
+ {x: 40, value: 50}
+ ];
+ });
+
+ test('instantiation_singleDatum', function() {
+ const chart = new tr.ui.b.BarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, value: 100},
+ ];
+ });
+
+ test('instantiation_stacked', function() {
+ const chart = new tr.ui.b.BarChart();
+ chart.isStacked = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, foo: 10, bar: 5, qux: 7},
+ {x: 20, foo: 11, bar: 6, qux: 3},
+ {x: 30, foo: 10, bar: 4, qux: 8},
+ {x: 40, foo: 5, bar: 1, qux: 2}
+ ];
+ });
+
+ test('undefined', function() {
+ const chart = new tr.ui.b.BarChart();
+ assert.throws(function() {
+ chart.data = undefined;
+ });
+ });
+
+ test('instantiation_twoSeries', function() {
+ const chart = new tr.ui.b.BarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 100, beta: 50},
+ {x: 20, alpha: 110, beta: 75},
+ {x: 30, alpha: 100, beta: 125},
+ {x: 40, alpha: 50, beta: 125}
+ ];
+ chart.brushedRange = tr.b.math.Range.fromExplicitRange(20, 40);
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueSparse', function() {
+ const chart = new tr.ui.b.BarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 20, beta: undefined},
+ {x: 20, alpha: undefined, beta: 10},
+ {x: 30, alpha: 10, beta: undefined},
+ {x: 45, alpha: undefined, beta: 20},
+ {x: 50, alpha: 25, beta: 30}
+ ];
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueNotSparse', function() {
+ const chart = new tr.ui.b.BarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 20, beta: 40},
+ {x: 20, alpha: undefined, beta: 10},
+ {x: 30, alpha: 10, beta: undefined},
+ {x: 45, alpha: undefined, beta: 20},
+ {x: 50, alpha: 30, beta: undefined}
+ ];
+ });
+
+ test('instantiation_interactiveBrushing', function() {
+ const chart = new tr.ui.b.BarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, value: 50},
+ {x: 20, value: 60},
+ {x: 30, value: 80},
+ {x: 40, value: 20},
+ {x: 50, value: 30},
+ {x: 60, value: 20},
+ {x: 70, value: 15},
+ {x: 80, value: 20}
+ ];
+
+ let mouseDownX = undefined;
+ let curMouseX = undefined;
+
+ function updateBrushedRange() {
+ if (mouseDownX === undefined || (mouseDownX === curMouseX)) {
+ chart.brushedRange = new tr.b.math.Range();
+ return;
+ }
+ const r = new tr.b.math.Range();
+ r.min = Math.min(mouseDownX, curMouseX);
+ r.max = Math.max(mouseDownX, curMouseX);
+ chart.brushedRange = r;
+ }
+
+ chart.addEventListener('item-mousedown', function(e) {
+ mouseDownX = e.x;
+ curMouseX = e.x;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mousemove', function(e) {
+ if (e.button === undefined) return;
+ curMouseX = e.x;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mouseup', function(e) {
+ curMouseX = e.x;
+ updateBrushedRange();
+ });
+ });
+
+ test('instantiation_overrideDataRange', function() {
+ let chart = new tr.ui.b.BarChart();
+ chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(10, 90);
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, value: -20},
+ {x: 1, value: 100},
+ {x: 2, value: -40},
+ {x: 3, value: 100},
+ ];
+
+ chart = new tr.ui.b.BarChart();
+ chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(-10, 100);
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, value: 0},
+ {x: 1, value: 50},
+ ];
+ });
+
+ test('instantiation_Waterfall', function() {
+ const chart = new tr.ui.b.BarChart();
+ chart.graphWidth = 300;
+ chart.graphHeight = 200;
+ chart.isStacked = true;
+ chart.isGrouped = true;
+ chart.isWaterfall = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, alpha: 40, group: 'group1' },
+ {x: 1, alpha: 30, group: 'group2' },
+ {x: 2},
+ {x: 3, hide: 40, beta: 55, group: 'group1' },
+ {x: 4, hide: 40, beta: 65, group: 'group2' },
+ {x: 5},
+ {x: 6, hide: 95, omega: 10, group: 'group1' },
+ {x: 7, hide: 95, omega: 20, group: 'group2' }
+ ];
+ });
+
+ test('instantiation_showHoverValuesForTransparentData', function() {
+ const chart = new tr.ui.b.BarChart();
+ chart.graphWidth = 300;
+ chart.graphHeight = 200;
+ chart.isStacked = true;
+ chart.isGrouped = true;
+ chart.displayXInHover = true;
+ chart.getDataSeries('alpha').color = 'transparent';
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, alpha: 40, beta: 32, omega: 13, group: 'group1' },
+ {x: 1, alpha: 30, beta: 22, omega: 14, group: 'group2' },
+ {x: 2},
+ {x: 3, alpha: 55, beta: 35, omega: 15, group: 'group1' },
+ {x: 4, alpha: 45, beta: 40, omega: 16, group: 'group2' },
+ {x: 5},
+ {x: 6, alpha: 50, beta: 10, omega: 17, group: 'group1' },
+ {x: 7, alpha: 60, beta: 15, omega: 18, group: 'group2' }
+ ];
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/base.html b/chromium/third_party/catapult/tracing/tracing/ui/base/base.html
new file mode 100644
index 00000000000..e0ca9e23c6b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/base.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/polymer_preload.html" data-suppress-import-order>
+
+<!--
+Polymer is imported through third-party HTML files, which means that we have to
+manually list all recursive imports.
+-->
+<link rel="import" href="/components/polymer/polymer-micro.html" data-suppress-import-order>
+<link rel="import" href="/components/polymer/polymer-mini.html" data-suppress-import-order>
+<link rel="import" href="/components/polymer/polymer.html" data-suppress-import-order>
+
+<link rel="import" href="/tracing/ui/base/polymer_postload.html" data-suppress-import-order>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/box_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/base/box_chart.html
new file mode 100644
index 00000000000..9138d1ea8b0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/box_chart.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/name_column_chart.html">
+<link rel="import" href="/tracing/ui/base/name_line_chart.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const BoxChart = tr.ui.b.define('box-chart', tr.ui.b.NameLineChart);
+
+ BoxChart.prototype = {
+ __proto__: tr.ui.b.NameLineChart.prototype,
+
+ get hideLegend() {
+ return true;
+ },
+
+ updateDataRange_() {
+ if (this.overrideDataRange_ !== undefined) {
+ return;
+ }
+
+ this.autoDataRange_.reset();
+ for (const datum of this.data_) {
+ this.autoDataRange_.addValue(datum.percentile_0);
+ this.autoDataRange_.addValue(datum.percentile_100);
+ }
+ },
+
+ updateScales_() {
+ super.updateScales_();
+ this.xScale_.domain([0, this.data_.length]);
+ },
+
+ get xAxisTickOffset() {
+ return 0.5;
+ },
+
+ updateDataRange_() {
+ if (this.overrideDataRange_ !== undefined) return;
+
+ this.autoDataRange_.reset();
+ for (const datum of this.data_) {
+ this.autoDataRange_.addValue(datum.percentile_0);
+ this.autoDataRange_.addValue(datum.percentile_100);
+ }
+ },
+
+ updateXAxis_(xAxis) {
+ xAxis.selectAll('*').remove();
+ if (this.hideXAxis) return;
+
+ tr.ui.b.NameColumnChart.prototype.updateXAxis_.call(this, xAxis);
+
+ const baseline = xAxis.selectAll('path').data([this]);
+ baseline.enter().append('line')
+ .attr('stroke', 'black')
+ .attr('x1', this.xScale_(0))
+ .attr('x2', this.xScale_(this.data_.length))
+ .attr('y1', this.graphHeight)
+ .attr('y2', this.graphHeight);
+ baseline.exit().remove();
+ },
+
+ updateDataContents_(dataSel) {
+ dataSel.selectAll('*').remove();
+ const boxesSel = dataSel.selectAll('path');
+ for (let index = 0; index < this.data_.length; ++index) {
+ const datum = this.data_[index];
+ const color = datum.color || 'black';
+
+ // Draw a box between percentiles 25 and 75:
+ let sel = boxesSel.data([datum]);
+ sel.enter().append('rect')
+ .attr('fill', color)
+ .attr('x', this.xScale_(index + 0.2))
+ .attr('width',
+ this.xScale_(index + 0.8) - this.xScale_(index + 0.2))
+ .attr('y', this.yScale_(datum.percentile_75))
+ .attr('height', this.yScale_(datum.percentile_25) -
+ this.yScale_(datum.percentile_75));
+ sel.exit().remove();
+
+ // Draw a horizontal line for percentile_50:
+ sel = boxesSel.data([datum]);
+ sel.enter().append('line')
+ .attr('stroke', color)
+ .attr('x1', this.xScale_(index))
+ .attr('x2', this.xScale_(index + 1))
+ .attr('y1', this.yScale_(datum.percentile_50))
+ .attr('y2', this.yScale_(datum.percentile_50));
+ sel.exit().remove();
+
+ // Draw two shorter horizontal lines for percentiles 0 and 100:
+ sel = boxesSel.data([datum]);
+ sel.enter().append('line')
+ .attr('stroke', color)
+ .attr('x1', this.xScale_(index + 0.4))
+ .attr('x2', this.xScale_(index + 0.6))
+ .attr('y1', this.yScale_(datum.percentile_0))
+ .attr('y2', this.yScale_(datum.percentile_0));
+ sel.exit().remove();
+ sel = boxesSel.data([datum]);
+ sel.enter().append('line')
+ .attr('stroke', color)
+ .attr('x1', this.xScale_(index + 0.4))
+ .attr('x2', this.xScale_(index + 0.6))
+ .attr('y1', this.yScale_(datum.percentile_100))
+ .attr('y2', this.yScale_(datum.percentile_100));
+ sel.exit().remove();
+
+ // Draw a vertical line between percentiles 0 and 100.
+ sel = boxesSel.data([datum]);
+ sel.enter().append('line')
+ .attr('stroke', color)
+ .attr('x1', this.xScale_(index + 0.5))
+ .attr('x2', this.xScale_(index + 0.5))
+ .attr('y1', this.yScale_(datum.percentile_100))
+ .attr('y2', this.yScale_(datum.percentile_0));
+ sel.exit().remove();
+ }
+ }
+ };
+
+ return {
+ BoxChart,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/box_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/box_chart_test.html
new file mode 100644
index 00000000000..da2c7665ace
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/box_chart_test.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/box_chart.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiation_singleSeries', function() {
+ const chart = new tr.ui.b.BoxChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {
+ x: 'a'.repeat(15) + 'A',
+ percentile_0: 30,
+ percentile_25: 60,
+ percentile_50: 110,
+ percentile_75: 160,
+ percentile_100: 210,
+ },
+ {
+ x: 'b'.repeat(10) + 'B',
+ percentile_0: 0,
+ percentile_25: 50,
+ percentile_50: 100,
+ percentile_75: 150,
+ percentile_100: 200,
+ },
+ {
+ x: 'c'.repeat(5) + 'C',
+ percentile_0: 100,
+ percentile_25: 150,
+ percentile_50: 200,
+ percentile_75: 250,
+ percentile_100: 300,
+ },
+ ];
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/camera.html b/chromium/third_party/catapult/tracing/tracing/ui/base/camera.html
new file mode 100644
index 00000000000..540f8e1c7ff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/camera.html
@@ -0,0 +1,350 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const deg2rad = tr.b.math.deg2rad;
+
+ const constants = {
+ DEFAULT_SCALE: 0.5,
+ DEFAULT_EYE_DISTANCE: 10000,
+ MINIMUM_DISTANCE: 1000,
+ MAXIMUM_DISTANCE: 100000,
+ FOV: 15,
+ RESCALE_TIMEOUT_MS: 200,
+ MAXIMUM_TILT: 80,
+ SETTINGS_NAMESPACE: 'tr.ui_camera'
+ };
+
+ const Camera = tr.ui.b.define('camera');
+
+ Camera.prototype = {
+ __proto__: HTMLUnknownElement.prototype,
+
+ decorate(eventSource) {
+ this.eventSource_ = eventSource;
+
+ this.eventSource_.addEventListener('beginpan',
+ this.onPanBegin_.bind(this));
+ this.eventSource_.addEventListener('updatepan',
+ this.onPanUpdate_.bind(this));
+ this.eventSource_.addEventListener('endpan',
+ this.onPanEnd_.bind(this));
+
+ this.eventSource_.addEventListener('beginzoom',
+ this.onZoomBegin_.bind(this));
+ this.eventSource_.addEventListener('updatezoom',
+ this.onZoomUpdate_.bind(this));
+ this.eventSource_.addEventListener('endzoom',
+ this.onZoomEnd_.bind(this));
+
+ this.eventSource_.addEventListener('beginrotate',
+ this.onRotateBegin_.bind(this));
+ this.eventSource_.addEventListener('updaterotate',
+ this.onRotateUpdate_.bind(this));
+ this.eventSource_.addEventListener('endrotate',
+ this.onRotateEnd_.bind(this));
+
+ this.eye_ = [0, 0, constants.DEFAULT_EYE_DISTANCE];
+ this.gazeTarget_ = [0, 0, 0];
+ this.rotation_ = [0, 0];
+
+ this.pixelRatio_ = window.devicePixelRatio || 1;
+ },
+
+
+ get modelViewMatrix() {
+ const mvMatrix = mat4.create();
+
+ mat4.lookAt(mvMatrix, this.eye_, this.gazeTarget_, [0, 1, 0]);
+ return mvMatrix;
+ },
+
+ get projectionMatrix() {
+ const rect =
+ tr.ui.b.windowRectForElement(this.canvas_).
+ scaleSize(this.pixelRatio_);
+
+ const aspectRatio = rect.width / rect.height;
+ const matrix = mat4.create();
+ mat4.perspective(
+ matrix, deg2rad(constants.FOV), aspectRatio, 1, 100000);
+
+ return matrix;
+ },
+
+ set canvas(c) {
+ this.canvas_ = c;
+ },
+
+ set deviceRect(rect) {
+ this.deviceRect_ = rect;
+ },
+
+ get stackingDistanceDampening() {
+ const gazeVector = [
+ this.gazeTarget_[0] - this.eye_[0],
+ this.gazeTarget_[1] - this.eye_[1],
+ this.gazeTarget_[2] - this.eye_[2]];
+ vec3.normalize(gazeVector, gazeVector);
+ return 1 + gazeVector[2];
+ },
+
+ loadCameraFromSettings(settings) {
+ this.eye_ = settings.get(
+ 'eye', this.eye_, constants.SETTINGS_NAMESPACE);
+ this.gazeTarget_ = settings.get(
+ 'gaze_target', this.gazeTarget_, constants.SETTINGS_NAMESPACE);
+ this.rotation_ = settings.get(
+ 'rotation', this.rotation_, constants.SETTINGS_NAMESPACE);
+
+ this.dispatchRenderEvent_();
+ },
+
+ saveCameraToSettings(settings) {
+ settings.set(
+ 'eye', this.eye_, constants.SETTINGS_NAMESPACE);
+ settings.set(
+ 'gaze_target', this.gazeTarget_, constants.SETTINGS_NAMESPACE);
+ settings.set(
+ 'rotation', this.rotation_, constants.SETTINGS_NAMESPACE);
+ },
+
+ resetCamera() {
+ this.eye_ = [0, 0, constants.DEFAULT_EYE_DISTANCE];
+ this.gazeTarget_ = [0, 0, 0];
+ this.rotation_ = [0, 0];
+
+ const settings = tr.b.SessionSettings();
+ const keys = settings.keys(constants.SETTINGS_NAMESPACE);
+ if (keys.length !== 0) {
+ this.loadCameraFromSettings(settings);
+ return;
+ }
+
+ if (this.deviceRect_) {
+ const rect = tr.ui.b.windowRectForElement(this.canvas_).
+ scaleSize(this.pixelRatio_);
+
+ this.eye_[0] = this.deviceRect_.width / 2;
+ this.eye_[1] = this.deviceRect_.height / 2;
+
+ this.gazeTarget_[0] = this.deviceRect_.width / 2;
+ this.gazeTarget_[1] = this.deviceRect_.height / 2;
+ }
+
+ this.saveCameraToSettings(settings);
+ this.dispatchRenderEvent_();
+ },
+
+ updatePanByDelta(delta) {
+ const rect =
+ tr.ui.b.windowRectForElement(this.canvas_).
+ scaleSize(this.pixelRatio_);
+
+ // Get the eye vector, since we'll be adjusting gazeTarget.
+ const eyeVector = [
+ this.eye_[0] - this.gazeTarget_[0],
+ this.eye_[1] - this.gazeTarget_[1],
+ this.eye_[2] - this.gazeTarget_[2]];
+ const length = vec3.length(eyeVector);
+ vec3.normalize(eyeVector, eyeVector);
+
+ const halfFov = constants.FOV / 2;
+ const multiplier =
+ 2.0 * length * Math.tan(deg2rad(halfFov)) / rect.height;
+
+ // Get the up and right vectors.
+ const up = [0, 1, 0];
+ const rotMatrix = mat4.create();
+ mat4.rotate(
+ rotMatrix, rotMatrix, deg2rad(this.rotation_[1]), [0, 1, 0]);
+ mat4.rotate(
+ rotMatrix, rotMatrix, deg2rad(this.rotation_[0]), [1, 0, 0]);
+ vec3.transformMat4(up, up, rotMatrix);
+
+ const right = [0, 0, 0];
+ vec3.cross(right, eyeVector, up);
+ vec3.normalize(right, right);
+
+ // Update the gaze target.
+ for (let i = 0; i < 3; ++i) {
+ this.gazeTarget_[i] +=
+ delta[0] * multiplier * right[i] - delta[1] * multiplier * up[i];
+
+ this.eye_[i] = this.gazeTarget_[i] + length * eyeVector[i];
+ }
+
+ // If we have some z offset, we need to reposition gazeTarget
+ // to be on the plane z = 0 with normal [0, 0, 1].
+ if (Math.abs(this.gazeTarget_[2]) > 1e-6) {
+ const gazeVector = [-eyeVector[0], -eyeVector[1], -eyeVector[2]];
+ const newLength = tr.b.math.clamp(
+ -this.eye_[2] / gazeVector[2],
+ constants.MINIMUM_DISTANCE,
+ constants.MAXIMUM_DISTANCE);
+
+ for (let i = 0; i < 3; ++i) {
+ this.gazeTarget_[i] = this.eye_[i] + newLength * gazeVector[i];
+ }
+ }
+
+ this.saveCameraToSettings(tr.b.SessionSettings());
+ this.dispatchRenderEvent_();
+ },
+
+ updateZoomByDelta(delta) {
+ let deltaY = delta[1];
+ deltaY = tr.b.math.clamp(deltaY, -50, 50);
+ let scale = 1.0 - deltaY / 100.0;
+
+ const eyeVector = [0, 0, 0];
+ vec3.subtract(eyeVector, this.eye_, this.gazeTarget_);
+
+ const length = vec3.length(eyeVector);
+
+ // Clamp the length to allowed values by changing the scale.
+ if (length * scale < constants.MINIMUM_DISTANCE) {
+ scale = constants.MINIMUM_DISTANCE / length;
+ } else if (length * scale > constants.MAXIMUM_DISTANCE) {
+ scale = constants.MAXIMUM_DISTANCE / length;
+ }
+
+ vec3.scale(eyeVector, eyeVector, scale);
+ vec3.add(this.eye_, this.gazeTarget_, eyeVector);
+
+ this.saveCameraToSettings(tr.b.SessionSettings());
+ this.dispatchRenderEvent_();
+ },
+
+ updateRotateByDelta(delta) {
+ delta[0] *= 0.5;
+ delta[1] *= 0.5;
+
+ if (Math.abs(this.rotation_[0] + delta[1]) > constants.MAXIMUM_TILT) {
+ return;
+ }
+ if (Math.abs(this.rotation_[1] - delta[0]) > constants.MAXIMUM_TILT) {
+ return;
+ }
+
+ const eyeVector = [0, 0, 0, 0];
+ vec3.subtract(eyeVector, this.eye_, this.gazeTarget_);
+
+ // Undo the current rotation.
+ const rotMatrix = mat4.create();
+ mat4.rotate(
+ rotMatrix, rotMatrix, -deg2rad(this.rotation_[0]), [1, 0, 0]);
+ mat4.rotate(
+ rotMatrix, rotMatrix, -deg2rad(this.rotation_[1]), [0, 1, 0]);
+ vec4.transformMat4(eyeVector, eyeVector, rotMatrix);
+
+ // Update rotation values.
+ this.rotation_[0] += delta[1];
+ this.rotation_[1] -= delta[0];
+
+ // Redo the new rotation.
+ mat4.identity(rotMatrix);
+ mat4.rotate(
+ rotMatrix, rotMatrix, deg2rad(this.rotation_[1]), [0, 1, 0]);
+ mat4.rotate(
+ rotMatrix, rotMatrix, deg2rad(this.rotation_[0]), [1, 0, 0]);
+ vec4.transformMat4(eyeVector, eyeVector, rotMatrix);
+
+ vec3.add(this.eye_, this.gazeTarget_, eyeVector);
+
+ this.saveCameraToSettings(tr.b.SessionSettings());
+ this.dispatchRenderEvent_();
+ },
+
+
+ // Event callbacks.
+ onPanBegin_(e) {
+ this.panning_ = true;
+ this.lastMousePosition_ = this.getMousePosition_(e);
+ },
+
+ onPanUpdate_(e) {
+ if (!this.panning_) return;
+
+ const delta = this.getMouseDelta_(e, this.lastMousePosition_);
+ this.lastMousePosition_ = this.getMousePosition_(e);
+ this.updatePanByDelta(delta);
+ },
+
+ onPanEnd_(e) {
+ this.panning_ = false;
+ },
+
+ onZoomBegin_(e) {
+ this.zooming_ = true;
+
+ const p = this.getMousePosition_(e);
+
+ this.lastMousePosition_ = p;
+ this.zoomPoint_ = p;
+ },
+
+ onZoomUpdate_(e) {
+ if (!this.zooming_) return;
+
+ const delta = this.getMouseDelta_(e, this.lastMousePosition_);
+ this.lastMousePosition_ = this.getMousePosition_(e);
+ this.updateZoomByDelta(delta);
+ },
+
+ onZoomEnd_(e) {
+ this.zooming_ = false;
+ this.zoomPoint_ = undefined;
+ },
+
+ onRotateBegin_(e) {
+ this.rotating_ = true;
+ this.lastMousePosition_ = this.getMousePosition_(e);
+ },
+
+ onRotateUpdate_(e) {
+ if (!this.rotating_) return;
+
+ const delta = this.getMouseDelta_(e, this.lastMousePosition_);
+ this.lastMousePosition_ = this.getMousePosition_(e);
+ this.updateRotateByDelta(delta);
+ },
+
+ onRotateEnd_(e) {
+ this.rotating_ = false;
+ },
+
+
+ // Misc helper functions.
+ getMousePosition_(e) {
+ const rect = tr.ui.b.windowRectForElement(this.canvas_);
+ return [(e.clientX - rect.x) * this.pixelRatio_,
+ (e.clientY - rect.y) * this.pixelRatio_];
+ },
+
+ getMouseDelta_(e, p) {
+ const newP = this.getMousePosition_(e);
+ return [newP[0] - p[0], newP[1] - p[1]];
+ },
+
+ dispatchRenderEvent_() {
+ tr.b.dispatchSimpleEvent(this, 'renderrequired', false, false);
+ }
+ };
+
+ return {
+ Camera,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html
new file mode 100644
index 00000000000..7083856c539
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/camera_test.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/bbox2.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/ui/base/quad_stack_view.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createQuads() {
+ const quads = [
+ tr.b.math.Quad.fromXYWH(-500, -500, 30, 30), // 4 corners
+ tr.b.math.Quad.fromXYWH(-500, 470, 30, 30),
+ tr.b.math.Quad.fromXYWH(470, -500, 30, 30),
+ tr.b.math.Quad.fromXYWH(470, 470, 30, 30),
+ tr.b.math.Quad.fromXYWH(-250, -250, 250, 250), // crosshairs
+ tr.b.math.Quad.fromXYWH(0, -250, 250, 250), // crosshairs
+ tr.b.math.Quad.fromXYWH(-250, 0, 250, 250), // crosshairs
+ tr.b.math.Quad.fromXYWH(0, 0, 250, 250) // crosshairs
+ ];
+ quads[0].stackingGroupId = 0;
+ quads[1].stackingGroupId = 0;
+ quads[2].stackingGroupId = 0;
+ quads[3].stackingGroupId = 0;
+ quads[4].stackingGroupId = 1;
+ quads[5].stackingGroupId = 1;
+ quads[6].stackingGroupId = 1;
+ quads[7].stackingGroupId = 1;
+ return quads;
+ }
+
+ function createQuadStackView(testFramework) {
+ const quads = createQuads();
+ const view = new tr.ui.b.QuadStackView();
+ // simulate the constraints of the layer-tree-view
+ view.style.height = '400px';
+ view.style.width = '800px';
+ view.deviceRect = tr.b.math.Rect.fromXYWH(-250, -250, 500, 500);
+ view.quads = quads;
+
+ testFramework.addHTMLOutput(view);
+ return view;
+ }
+
+ test('initialState', function() {
+ const view = createQuadStackView(this);
+
+ const viewRect =
+ view.getBoundingClientRect();
+ assert.strictEqual(viewRect.height, 400);
+ assert.strictEqual(viewRect.width, 800);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base.html b/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base.html
new file mode 100644
index 00000000000..3d1359fe61b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base.html
@@ -0,0 +1,453 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/ui/base/chart_legend_key.html">
+<link rel="import" href="/tracing/ui/base/d3.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<template id="chart-base-template">
+ <svg> <!-- svg tag is dropped by ChartBase.decorate. -->
+ <g xmlns="http://www.w3.org/2000/svg" id="chart-area">
+ <g class="x axis"></g>
+ <g class="y axis"></g>
+ <text id="title"></text>
+ </g>
+ </svg>
+</template>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const DataSeriesEnableChangeEventType = 'data-series-enabled-change';
+
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ const svgNS = 'http://www.w3.org/2000/svg';
+ const ColorScheme = tr.b.ColorScheme;
+
+ function getColorOfKey(key, selected) {
+ let id = ColorScheme.getColorIdForGeneralPurposeString(key);
+ if (selected) {
+ id += ColorScheme.properties.brightenedOffsets[0];
+ }
+ return ColorScheme.colorsAsStrings[id];
+ }
+
+ /**
+ * Returns width and height of SVG text node.
+ *
+ * @param {!Element} parentNode
+ * @param {string} text
+ * @param {function(!Element)=} opt_callback
+ * @param {*=} opt_this
+ * @returns {!Object}
+ */
+ function getSVGTextSize(parentNode, text, opt_callback, opt_this) {
+ const textNode = document.createElementNS(
+ 'http://www.w3.org/2000/svg', 'text');
+ textNode.setAttributeNS(null, 'x', 0);
+ textNode.setAttributeNS(null, 'y', 0);
+ textNode.setAttributeNS(null, 'fill', 'black');
+ textNode.appendChild(document.createTextNode(text));
+ parentNode.appendChild(textNode);
+ if (opt_callback) {
+ opt_callback.call(opt_this || parentNode, textNode);
+ }
+ const width = textNode.getComputedTextLength();
+ const height = textNode.getBBox().height;
+ parentNode.removeChild(textNode);
+ return {width, height};
+ }
+
+ function DataSeries(key) {
+ this.key_ = key;
+ this.target_ = undefined;
+ this.title_ = '';
+ this.optional_ = false;
+ this.enabled_ = true;
+ this.color_ = getColorOfKey(key, false);
+ this.highlightedColor_ = getColorOfKey(key, true);
+ }
+
+ DataSeries.prototype = {
+ get key() {
+ return this.key_;
+ },
+
+ get title() {
+ return this.title_;
+ },
+
+ set title(t) {
+ this.title_ = t;
+ },
+
+ get color() {
+ return this.color_;
+ },
+
+ set color(c) {
+ this.color_ = c;
+ },
+
+ get highlightedColor() {
+ return this.highlightedColor_;
+ },
+
+ set highlightedColor(c) {
+ this.highlightedColor_ = c;
+ },
+
+ get optional() {
+ return this.optional_;
+ },
+
+ set optional(optional) {
+ this.optional_ = optional;
+ },
+
+ get enabled() {
+ return this.enabled_;
+ },
+
+ set enabled(enabled) {
+ // If the caller is disabling a data series, but it wasn't optional, then
+ // force it to be optional.
+ if (!this.optional && !enabled) {
+ this.optional = true;
+ }
+ this.enabled_ = enabled;
+ },
+
+ get target() {
+ return this.target_;
+ },
+
+ set target(t) {
+ this.target_ = t;
+ }
+ };
+
+ /**
+ * A virtual base class for basic charts that provides basic chart
+ * infrastructure such as a title and legend.
+ *
+ * Generally, setting a field on a chart instance will cause it to update its
+ * contents, which assumes that the chart is attached to a document, so
+ * callers should create the chart and immediately attach it to a document
+ * before configuring it. Embedders that are polymer dom-modules can use the
+ * attached() callback to wait to configure the chart until they are attached
+ * to a document.
+ *
+ * TODO(#3058) Use a class for Polymer 2.0.
+ *
+ * @constructor
+ */
+ const ChartBase = tr.ui.b.define('svg', undefined, svgNS);
+
+ ChartBase.prototype = {
+ __proto__: HTMLUnknownElement.prototype,
+
+ getDataSeries(key) {
+ if (!this.seriesByKey_.has(key)) {
+ this.seriesByKey_.set(key, new DataSeries(key));
+ }
+ return this.seriesByKey_.get(key);
+ },
+
+ decorate() {
+ Polymer.dom(this).classList.add('chart-base');
+ this.setAttribute('style', 'cursor: default; user-select: none;');
+ this.chartTitle_ = undefined;
+ this.seriesByKey_ = new Map();
+ this.graphWidth_ = undefined;
+ this.graphHeight_ = undefined;
+ this.margin = {
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ };
+ this.hideLegend_ = false;
+ this.showTitleInLegend_ = false;
+ this.titleHeight_ = '16pt';
+
+ // This should use tr.ui.b.instantiateTemplate. However, creating
+ // svg-namespaced elements inside a template isn't possible. Thus, this
+ // hack.
+ const template =
+ Polymer.dom(THIS_DOC).querySelector('#chart-base-template');
+ const svgEl = Polymer.dom(template.content).querySelector('svg');
+ for (let i = 0; i < Polymer.dom(svgEl).children.length; i++) {
+ Polymer.dom(this).appendChild(
+ Polymer.dom(svgEl.children[i]).cloneNode(true));
+ }
+
+ this.addEventListener(DataSeriesEnableChangeEventType,
+ this.onDataSeriesEnableChange_.bind(this));
+ },
+
+ get hideLegend() {
+ return this.hideLegend_;
+ },
+
+ set hideLegend(h) {
+ this.hideLegend_ = h;
+ this.updateContents_();
+ },
+
+ get showTitleInLegend() {
+ return this.showTitleInLegend_;
+ },
+
+ set showTitleInLegend(s) {
+ this.showTitleInLegend_ = s;
+ this.updateContents_();
+ },
+
+ isSeriesEnabled(key) {
+ return this.getDataSeries(key).enabled;
+ },
+
+ onDataSeriesEnableChange_(event) {
+ this.getDataSeries(event.key).enabled = event.enabled;
+ this.updateContents_();
+ },
+
+ get chartTitle() {
+ return this.chartTitle_;
+ },
+
+ set chartTitle(chartTitle) {
+ this.chartTitle_ = chartTitle;
+ this.updateContents_();
+ },
+
+ get chartAreaElement() {
+ return Polymer.dom(this).querySelector('#chart-area');
+ },
+
+ get graphWidth() {
+ if (this.graphWidth_ === undefined) return this.defaultGraphWidth;
+ return this.graphWidth_;
+ },
+
+ set graphWidth(width) {
+ this.graphWidth_ = width;
+ this.updateContents_();
+ },
+
+ get defaultGraphWidth() {
+ return 0;
+ },
+
+ get graphHeight() {
+ if (this.graphHeight_ === undefined) return this.defaultGraphHeight;
+ return this.graphHeight_;
+ },
+
+ set graphHeight(height) {
+ this.graphHeight_ = height;
+ this.updateContents_();
+ },
+
+ get titleHeight() {
+ return this.titleHeight_;
+ },
+
+ set titleHeight(height) {
+ this.titleHeight_ = height;
+ this.updateContents_();
+ },
+
+ get defaultGraphHeight() {
+ return 0;
+ },
+
+ get totalWidth() {
+ return this.margin.left + this.graphWidth + this.margin.right;
+ },
+
+ get totalHeight() {
+ return this.margin.top + this.graphHeight + this.margin.bottom;
+ },
+
+ updateMargins_() {
+ const legendSize = this.computeLegendSize_();
+ this.margin.right = Math.max(this.margin.right, legendSize.width);
+ this.margin.bottom = Math.max(
+ this.margin.bottom,
+ legendSize.height - this.graphHeight);
+
+ if (this.chartTitle_) {
+ const titleSize = getSVGTextSize(this, this.chartTitle_, textNode => {
+ textNode.style.fontSize = '16pt';
+ });
+ this.margin.top = Math.max(this.margin.top, titleSize.height + 15);
+ const horizontalOverhangPx = (titleSize.width - this.graphWidth) / 2;
+ this.margin.left = Math.max(this.margin.left, horizontalOverhangPx);
+ this.margin.right = Math.max(this.margin.right, horizontalOverhangPx);
+ }
+ },
+
+ computeLegendSize_() {
+ let width = 0;
+ let height = 0;
+ if (this.hideLegend) return {width, height};
+
+ let series = [...this.seriesByKey_.values()];
+ if (this.showTitleInLegend) {
+ series = series.filter(series => series.title !== '');
+ }
+
+ for (const seriesEntry of series) {
+ const legendText = this.showTitleInLegend ? seriesEntry.title :
+ seriesEntry.key;
+ const textSize = getSVGTextSize(this, legendText);
+ width = Math.max(width, textSize.width + 30);
+ height += textSize.height;
+ }
+
+ return {width, height};
+ },
+
+ updateDimensions_() {
+ const thisSel = d3.select(this);
+ thisSel.attr('width', this.totalWidth);
+ thisSel.attr('height', this.totalHeight);
+
+ d3.select(this.chartAreaElement).attr(
+ 'transform',
+ 'translate(' + this.margin.left + ', ' + this.margin.top + ')');
+ },
+
+ updateContents_() {
+ this.updateMargins_();
+ this.updateDimensions_();
+ this.updateTitle_();
+ this.updateLegend_();
+ },
+
+ updateTitle_() {
+ const titleSel = d3.select(this.chartAreaElement).select('#title');
+ if (!this.chartTitle_) {
+ titleSel.style('display', 'none');
+ return;
+ }
+ titleSel.attr('transform', 'translate(' + this.graphWidth * 0.5 + ',-15)')
+ .style('display', undefined)
+ .style('text-anchor', 'middle')
+ .style('font-size', this.titleHeight)
+ .attr('class', 'title')
+ .attr('width', this.graphWidth)
+ .text(this.chartTitle_);
+ },
+
+ updateLegend_() {
+ const chartAreaSel = d3.select(this.chartAreaElement);
+ chartAreaSel.selectAll('.legend').remove();
+ if (this.hideLegend) return;
+
+ let series;
+ let seriesText;
+ if (this.showTitleInLegend) {
+ series = [...this.seriesByKey_.values()].
+ filter(series => series.title !== '').
+ filter(series => series.color !== 'transparent').reverse();
+ seriesText = series => series.title;
+ } else {
+ series = [...this.seriesByKey_.values()].
+ filter(series => series.color !== 'transparent').reverse();
+ seriesText = series => series.key;
+ }
+
+ const legendEntriesSel = chartAreaSel.selectAll('.legend').data(series);
+
+ legendEntriesSel.enter()
+ .append('foreignObject')
+ .attr('class', 'legend')
+ .attr('x', this.graphWidth + 2)
+ .attr('width', this.margin.right)
+ .attr('height', 18)
+ .attr('transform', (series, i) => 'translate(0,' + i * 18 + ')')
+ .append('xhtml:body')
+ .style('margin', 0)
+ .append('tr-ui-b-chart-legend-key')
+ .property('color', series =>
+ ((this.currentHighlightedLegendKey === series.key) ?
+ series.highlightedColor : series.color))
+ .property('width', this.margin.right)
+ .property('target', series => series.target)
+ .property('title', series => series.title)
+ .property('optional', series => series.optional)
+ .property('enabled', series => series.enabled)
+ .text(seriesText);
+ legendEntriesSel.exit().remove();
+ },
+
+ get highlightedLegendKey() {
+ return this.highlightedLegendKey_;
+ },
+
+ set highlightedLegendKey(highlightedLegendKey) {
+ this.highlightedLegendKey_ = highlightedLegendKey;
+ this.updateHighlight_();
+ },
+
+ get currentHighlightedLegendKey() {
+ if (this.tempHighlightedLegendKey_) {
+ return this.tempHighlightedLegendKey_;
+ }
+ return this.highlightedLegendKey_;
+ },
+
+ pushTempHighlightedLegendKey(key) {
+ if (this.tempHighlightedLegendKey_) {
+ throw new Error('push cannot nest');
+ }
+ this.tempHighlightedLegendKey_ = key;
+ this.updateHighlight_();
+ },
+
+ popTempHighlightedLegendKey(key) {
+ if (this.tempHighlightedLegendKey_ !== key) {
+ throw new Error('pop cannot happen');
+ }
+ this.tempHighlightedLegendKey_ = undefined;
+ this.updateHighlight_();
+ },
+
+ updateHighlight_() {
+ // Update label colors.
+ const chartAreaSel = d3.select(this.chartAreaElement);
+ const legendEntriesSel = chartAreaSel.selectAll('.legend');
+ const getDataSeries = chart.getDataSeries.bind(chart);
+ const currentHighlightedLegendKey = chart.currentHighlightedLegendKey;
+ legendEntriesSel.each(function(key) {
+ // NOTE: this = legendEntry
+ const dataSeries = getDataSeries(key);
+ if (key === currentHighlightedLegendKey) {
+ this.style.fill = dataSeries.highlightedColor;
+ this.style.fontWeight = 'bold';
+ } else {
+ this.style.fill = dataSeries.color;
+ this.style.fontWeight = '';
+ }
+ });
+ }
+ };
+
+ return {
+ ChartBase,
+ DataSeriesEnableChangeEventType,
+ getColorOfKey,
+ getSVGTextSize,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base_2d.html b/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base_2d.html
new file mode 100644
index 00000000000..a17e7b74853
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base_2d.html
@@ -0,0 +1,571 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/chart_base.html">
+<link rel="import" href="/tracing/ui/base/mouse_tracker.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ // This does not include the tick labels.
+ const D3_Y_AXIS_WIDTH_PX = 9;
+
+ // This includes the tick labels.
+ const D3_X_AXIS_HEIGHT_PX = 23;
+
+ // For charts with log y-axes, the y-axis tick values may need to be sanitized
+ // if the data is zero or negative.
+ function sanitizePower(x, defaultValue) {
+ if (!isNaN(x) && isFinite(x) && (x !== 0)) return x;
+ return defaultValue;
+ }
+
+ const ChartBase2D = tr.ui.b.define('chart-base-2d', tr.ui.b.ChartBase);
+
+ ChartBase2D.prototype = {
+ __proto__: tr.ui.b.ChartBase.prototype,
+
+ decorate() {
+ super.decorate();
+ Polymer.dom(this).classList.add('chart-base-2d');
+
+ this.xScale_ = d3.scale.linear();
+ this.yScale_ = d3.scale.linear();
+ this.isYLogScale_ = false;
+ this.yLogScaleBase_ = 10;
+ this.yLogScaleMin_ = undefined;
+ this.autoDataRange_ = new tr.b.math.Range();
+ this.overrideDataRange_ = undefined;
+ this.hideXAxis_ = false;
+ this.hideYAxis_ = false;
+ this.data_ = [];
+ this.xAxisLabel_ = '';
+ this.yAxisLabel_ = '';
+ this.textHeightPx_ = 0;
+ this.unit_ = undefined;
+
+ d3.select(this.chartAreaElement)
+ .append('g')
+ .attr('id', 'brushes');
+ d3.select(this.chartAreaElement)
+ .append('g')
+ .attr('id', 'series');
+
+ this.addEventListener('mousedown', this.onMouseDown_.bind(this));
+ },
+
+ get yLogScaleBase() {
+ return this.yLogScaleBase_;
+ },
+
+ set yLogScaleBase(b) {
+ this.yLogScaleBase_ = b;
+ },
+
+ get unit() {
+ return this.unit_;
+ },
+
+ set unit(unit) {
+ this.unit_ = unit;
+ this.updateContents_();
+ },
+
+ get xAxisLabel() {
+ return this.xAxisLabel_;
+ },
+
+ set xAxisLabel(label) {
+ this.xAxisLabel_ = label;
+ },
+
+ get yAxisLabel() {
+ return this.yAxisLabel_;
+ },
+
+ set yAxisLabel(label) {
+ this.yAxisLabel_ = label;
+ },
+
+ get hideXAxis() {
+ return this.hideXAxis_;
+ },
+
+ set hideXAxis(h) {
+ this.hideXAxis_ = h;
+ this.updateContents_();
+ },
+
+ get hideYAxis() {
+ return this.hideYAxis_;
+ },
+
+ set hideYAxis(h) {
+ this.hideYAxis_ = h;
+ this.updateContents_();
+ },
+
+ get data() {
+ return this.data_;
+ },
+
+ /**
+ * Sets the data array for the object
+ *
+ * @param {Array} data The data. Each element must be an object, with at
+ * least an x property. All other properties become series names in the
+ * chart. The data can be sparse (i.e. every x value does not have to
+ * contain data for every series).
+ */
+ set data(data) {
+ if (data === undefined) {
+ throw new Error('data must be an Array');
+ }
+
+ this.data_ = data;
+ this.updateSeriesKeys_();
+ this.updateDataRange_();
+ this.updateContents_();
+ },
+
+ set isYLogScale(logScale) {
+ if (logScale) {
+ this.yScale_ = d3.scale.log().base(this.yLogScaleBase);
+ } else {
+ this.yScale_ = d3.scale.linear();
+ }
+ this.isYLogScale_ = logScale;
+ },
+
+ getYScaleMin_() {
+ return this.isYLogScale_ ? this.yLogScaleMin_ : 0;
+ },
+
+ getYScaleDomain_(minValue, maxValue) {
+ if (this.overrideDataRange_ !== undefined) {
+ return [this.dataRange.min, this.dataRange.max];
+ }
+ if (this.isYLogScale_) {
+ return [this.getYScaleMin_(), maxValue];
+ }
+ return [Math.min(minValue, this.getYScaleMin_()), maxValue];
+ },
+
+ getSampleWidth_(data, index, leftSide) {
+ let leftIndex;
+ let rightIndex;
+ if (leftSide) {
+ leftIndex = Math.max(index - 1, 0);
+ rightIndex = index;
+ } else {
+ leftIndex = index;
+ rightIndex = Math.min(index + 1, data.length - 1);
+ }
+ const leftWidth = this.getXForDatum_(data[index], index) -
+ this.getXForDatum_(data[leftIndex], leftIndex);
+ const rightWidth = this.getXForDatum_(data[rightIndex], rightIndex) -
+ this.getXForDatum_(data[index], index);
+ return tr.b.math.Statistics.mean([leftWidth, rightWidth]);
+ },
+
+ updateSeriesKeys_() {
+ // Don't clear seriesByKey_; the caller might have put state in it using
+ // getDataSeries() before setting data.
+ this.data_.forEach(function(datum) {
+ Object.keys(datum).forEach(function(key) {
+ if (this.isDatumFieldSeries_(key)) {
+ this.getDataSeries(key);
+ }
+ }, this);
+ }, this);
+ },
+
+ isDatumFieldSeries_(fieldName) {
+ return fieldName !== 'x';
+ },
+
+ getXForDatum_(datum, index) {
+ return datum.x;
+ },
+
+ updateMargins_() {
+ this.margin.left = this.hideYAxis ? 0 : this.yAxisWidth;
+ this.margin.bottom = this.hideXAxis ? 0 : this.xAxisHeight;
+
+ if (this.hideXAxis && !this.hideYAxis) {
+ this.margin.bottom = 10;
+ }
+ if (this.hideYAxis && !this.hideXAxis) {
+ this.margin.left = 10;
+ }
+ this.margin.top = this.hideYAxis ? 0 : 10;
+
+ if (this.yAxisLabel) {
+ this.margin.top += this.textHeightPx_;
+ }
+ if (this.xAxisLabel) {
+ this.margin.right = Math.max(this.margin.right,
+ 16 + tr.ui.b.getSVGTextSize(this, this.xAxisLabel).width);
+ }
+
+ super.updateMargins_();
+ },
+
+ get xAxisHeight() {
+ return D3_X_AXIS_HEIGHT_PX;
+ },
+
+ computeScaleTickWidth_(scale) {
+ if (this.data.length === 0) return 0;
+
+ let tickValues = scale.ticks();
+ let tickFormat = scale.tickFormat();
+
+ if (this.isYLogScale_) {
+ const enclosingPowers = this.dataRange.enclosingPowers();
+ tickValues = [];
+ const maxPower = sanitizePower(enclosingPowers.max, this.yLogScaleBase);
+ for (let power = sanitizePower(enclosingPowers.min, 1);
+ power <= maxPower;
+ power *= this.yLogScaleBase) {
+ tickValues.push(power);
+ }
+ tickFormat = v => v.toString();
+ }
+
+ if (this.unit) {
+ tickFormat = v => this.unit.format(v);
+ }
+
+ let maxTickWidth = 0;
+ for (const tickValue of tickValues) {
+ maxTickWidth = Math.max(maxTickWidth,
+ tr.ui.b.getSVGTextSize(this, tickFormat(tickValue)).width);
+ }
+
+ return D3_Y_AXIS_WIDTH_PX + maxTickWidth;
+ },
+
+ get yAxisWidth() {
+ return this.computeScaleTickWidth_(this.yScale_);
+ },
+
+ updateScales_() {
+ if (this.data_.length === 0) return;
+
+ this.xScale_.range([0, this.graphWidth]);
+ this.xScale_.domain(d3.extent(this.data_, this.getXForDatum_.bind(this)));
+
+ this.yScale_.range([this.graphHeight, 0]);
+ this.yScale_.domain([this.dataRange.min, this.dataRange.max]);
+ },
+
+ updateBrushContents_(brushSel) {
+ brushSel.selectAll('*').remove();
+ },
+
+ updateXAxis_(xAxis) {
+ xAxis.selectAll('*').remove();
+ xAxis[0][0].style.opacity = 0;
+ if (this.hideXAxis) return;
+
+ this.drawXAxis_(xAxis);
+
+ const label = xAxis.append('text').attr('class', 'label');
+ this.drawXAxisTicks_(xAxis);
+ this.drawXAxisLabel_(label);
+ xAxis[0][0].style.opacity = 1;
+ },
+
+ drawXAxis_(xAxis) {
+ xAxis.attr('transform', 'translate(0,' + this.graphHeight + ')')
+ .call(d3.svg.axis()
+ .scale(this.xScale_)
+ .orient('bottom'));
+ },
+
+ drawXAxisLabel_(label) {
+ label
+ .attr('x', this.graphWidth + 16)
+ .attr('y', 8)
+ .text(this.xAxisLabel);
+ },
+
+ drawXAxisTicks_(xAxis) {
+ let previousRight = undefined;
+ xAxis.selectAll('.tick')[0].forEach(function(tick) {
+ const currentLeft = tick.transform.baseVal[0].matrix.e;
+ if ((previousRight === undefined) ||
+ (currentLeft > (previousRight + 3))) {
+ const currentWidth = tick.getBBox().width;
+ previousRight = currentLeft + currentWidth;
+ } else {
+ tick.style.opacity = 0;
+ }
+ });
+ },
+
+ set overrideDataRange(range) {
+ this.overrideDataRange_ = range;
+ },
+
+ get dataRange() {
+ if (this.overrideDataRange_ !== undefined) {
+ return this.overrideDataRange_;
+ }
+ return this.autoDataRange_;
+ },
+
+ updateDataRange_() {
+ if (this.overrideDataRange_ !== undefined) return;
+
+ const dataBySeriesKey = this.getDataBySeriesKey_();
+ this.autoDataRange_.reset();
+ for (const [series, values] of Object.entries(dataBySeriesKey)) {
+ for (let i = 0; i < values.length; i++) {
+ this.autoDataRange_.addValue(values[i][series]);
+ }
+ }
+
+ // Choose the closest power of yLogScaleBase, rounded down, as the
+ // smallest tick to display.
+ this.yLogScaleMin_ = undefined;
+ if (this.autoDataRange_.min !== undefined) {
+ let minValue = this.autoDataRange_.min;
+ if (minValue === 0) {
+ minValue = 1;
+ }
+
+ const onePowerLess = tr.b.math.lesserPower(
+ minValue / this.yLogScaleBase);
+ this.yLogScaleMin_ = onePowerLess;
+ }
+ },
+
+ updateYAxis_(yAxis) {
+ yAxis.selectAll('*').remove();
+ yAxis[0][0].style.opacity = 0;
+ if (this.hideYAxis) return;
+
+ this.drawYAxis_(yAxis);
+ this.drawYAxisTicks_(yAxis);
+
+ const label = yAxis.append('text').attr('class', 'label');
+ this.drawYAxisLabel_(label);
+ },
+
+ drawYAxis_(yAxis) {
+ let axisModifier = d3.svg.axis()
+ .scale(this.yScale_)
+ .orient('left');
+
+ let tickFormat;
+
+ if (this.isYLogScale_) {
+ if (this.yLogScaleMin_ === undefined) return;
+ const tickValues = [];
+ const enclosingPowers = this.dataRange.enclosingPowers();
+ const maxPower = sanitizePower(enclosingPowers.max, this.yLogScaleBase);
+ for (let power = sanitizePower(enclosingPowers.min, 1);
+ power <= maxPower;
+ power *= this.yLogScaleBase) {
+ tickValues.push(power);
+ }
+
+ // The default tickFormat() for log scales always uses scientific
+ // notation. Override it to use Number.toString(), which only uses
+ // scientific notation for extreme values, and uses decimal notation for
+ // a broader range of values. Decimal notation is generally slightly
+ // easier to skim than scientific notation in the context of chart axes.
+ axisModifier = axisModifier.tickValues(tickValues);
+ tickFormat = v => v.toString();
+ }
+
+ if (this.unit) {
+ tickFormat = v => this.unit.format(v);
+ }
+
+ if (tickFormat) {
+ axisModifier = axisModifier.tickFormat(tickFormat);
+ }
+
+ yAxis.call(axisModifier);
+ },
+
+ drawYAxisLabel_(label) {
+ const labelWidthPx = Math.ceil(tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, this.yAxisLabel).width);
+ label
+ .attr('x', -labelWidthPx)
+ .attr('y', -8)
+ .text(this.yAxisLabel);
+ },
+
+ drawYAxisTicks_(yAxis) {
+ let previousTop = undefined;
+ yAxis.selectAll('.tick')[0].forEach(function(tick) {
+ const bbox = tick.getBBox();
+ const currentTop = tick.transform.baseVal[0].matrix.f;
+ const currentBottom = currentTop + bbox.height;
+ if ((previousTop === undefined) ||
+ (previousTop > (currentBottom + 3))) {
+ previousTop = currentTop;
+ } else {
+ tick.style.opacity = 0;
+ }
+ });
+ yAxis[0][0].style.opacity = 1;
+ },
+
+ updateContents_() {
+ if (this.textHeightPx_ === 0) {
+ // Measure the height of a string that is as tall as it can be,
+ // with both an ascender and a descender.
+ // https://en.wikipedia.org/wiki/Ascender_(typography)
+ this.textHeightPx_ = tr.ui.b.getSVGTextSize(this, 'Ay').height;
+ // If the chart is not yet rooted in a document, then the height will be
+ // 0. Callers should make sure that updateContents_ is called at least
+ // once after the chart is rooted in a document so that textHeightPx_
+ // can be computed.
+ }
+
+ this.updateScales_();
+ super.updateContents_();
+ const chartAreaSel = d3.select(this.chartAreaElement);
+ this.updateXAxis_(chartAreaSel.select('.x.axis'));
+ this.updateYAxis_(chartAreaSel.select('.y.axis'));
+ for (const child of this.querySelectorAll('.axis path, .axis line')) {
+ child.style.fill = 'none';
+ child.style.shapeRendering = 'crispEdges';
+ child.style.stroke = 'black';
+ }
+ this.updateBrushContents_(chartAreaSel.select('#brushes'));
+ this.updateDataContents_(chartAreaSel.select('#series'));
+ },
+
+ updateDataContents_(seriesSel) {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * Returns a map of series key to the data for that series.
+ *
+ * Example:
+ * // returns {y: [{x: 1, y: 1}, {x: 3, y: 3}], z: [{x: 2, z: 2}]}
+ * this.data_ = [{x: 1, y: 1}, {x: 2, z: 2}, {x: 3, y: 3}];
+ * this.getDataBySeriesKey_();
+ * @return {Object} A map of series data by series key.
+ */
+ getDataBySeriesKey_() {
+ const dataBySeriesKey = {};
+ for (const [key, series] of this.seriesByKey_) {
+ dataBySeriesKey[key] = [];
+ }
+
+ this.data_.forEach(function(multiSeriesDatum, index) {
+ const x = this.getXForDatum_(multiSeriesDatum, index);
+
+ d3.keys(multiSeriesDatum).forEach(function(seriesKey) {
+ // Skip 'x' - it's not a series
+ if (seriesKey === 'x') return;
+
+ if (multiSeriesDatum[seriesKey] === undefined) return;
+
+ if (!this.isDatumFieldSeries_(seriesKey)) return;
+
+ const singleSeriesDatum = {x};
+ singleSeriesDatum[seriesKey] = multiSeriesDatum[seriesKey];
+ dataBySeriesKey[seriesKey].push(singleSeriesDatum);
+ }, this);
+ }, this);
+
+ return dataBySeriesKey;
+ },
+
+ getChartPointAtClientPoint_(clientPoint) {
+ const rect = this.getBoundingClientRect();
+ return {
+ x: clientPoint.x - rect.left - this.margin.left,
+ y: clientPoint.y - rect.top - this.margin.top
+ };
+ },
+
+ getDataPointAtChartPoint_(chartPoint) {
+ return {
+ x: tr.b.math.clamp(this.xScale_.invert(chartPoint.x),
+ this.xScale_.domain()[0], this.xScale_.domain()[1]),
+ y: tr.b.math.clamp(this.yScale_.invert(chartPoint.y),
+ this.yScale_.domain()[0], this.yScale_.domain()[1])
+ };
+ },
+
+ getDataPointAtClientPoint_(clientX, clientY) {
+ const chartPoint = this.getChartPointAtClientPoint_(
+ {x: clientX, y: clientY});
+ return this.getDataPointAtChartPoint_(chartPoint);
+ },
+
+ prepareDataEvent_(mouseEvent, dataEvent) {
+ const dataPoint = this.getDataPointAtClientPoint_(
+ mouseEvent.clientX, mouseEvent.clientY);
+ dataEvent.x = dataPoint.x;
+ dataEvent.y = dataPoint.y;
+ },
+
+ onMouseDown_(mouseEvent) {
+ tr.ui.b.trackMouseMovesUntilMouseUp(
+ this.onMouseMove_.bind(this, mouseEvent.button),
+ this.onMouseUp_.bind(this, mouseEvent.button));
+ mouseEvent.preventDefault();
+ mouseEvent.stopPropagation();
+ const dataEvent = new tr.b.Event('item-mousedown');
+ dataEvent.button = mouseEvent.button;
+ this.prepareDataEvent_(mouseEvent, dataEvent);
+ this.dispatchEvent(dataEvent);
+ for (const child of this.querySelector('#brushes').children) {
+ child.setAttribute('fill', 'rgb(103, 199, 165)');
+ }
+ },
+
+ onMouseMove_(button, mouseEvent) {
+ if (mouseEvent.buttons !== undefined) {
+ mouseEvent.preventDefault();
+ mouseEvent.stopPropagation();
+ }
+ const dataEvent = new tr.b.Event('item-mousemove');
+ dataEvent.button = button;
+ this.prepareDataEvent_(mouseEvent, dataEvent);
+ this.dispatchEvent(dataEvent);
+ for (const child of this.querySelector('#brushes').children) {
+ child.setAttribute('fill', 'rgb(103, 199, 165)');
+ }
+ },
+
+ onMouseUp_(button, mouseEvent) {
+ mouseEvent.preventDefault();
+ mouseEvent.stopPropagation();
+ const dataEvent = new tr.b.Event('item-mouseup');
+ dataEvent.button = button;
+ this.prepareDataEvent_(mouseEvent, dataEvent);
+ this.dispatchEvent(dataEvent);
+ for (const child of this.querySelector('#brushes').children) {
+ child.setAttribute('fill', 'rgb(213, 236, 229)');
+ }
+ }
+ };
+
+ return {
+ ChartBase2D,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base_2d_brushable_x.html b/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base_2d_brushable_x.html
new file mode 100644
index 00000000000..cba736ee811
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/chart_base_2d_brushable_x.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/chart_base_2d.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const ChartBase2D = tr.ui.b.ChartBase2D;
+ const ChartBase2DBrushX = tr.ui.b.define(
+ 'chart-base-2d-brush-1d', ChartBase2D);
+
+ ChartBase2DBrushX.prototype = {
+ __proto__: ChartBase2D.prototype,
+
+ decorate() {
+ super.decorate();
+ this.brushedRange_ = new tr.b.math.Range();
+ },
+
+ set brushedRange(range) {
+ this.brushedRange_.reset();
+ this.brushedRange_.addRange(range);
+ this.updateContents_();
+ },
+
+ get brushedRange() {
+ return tr.b.math.Range.fromDict(this.brushedRange_.toJSON());
+ },
+
+ computeBrushRangeFromIndices(indexA, indexB) {
+ indexA = tr.b.math.clamp(indexA, 0, this.data_.length - 1);
+ indexB = tr.b.math.clamp(indexB, 0, this.data_.length - 1);
+ const leftIndex = Math.min(indexA, indexB);
+ const rightIndex = Math.max(indexA, indexB);
+
+ const brushRange = new tr.b.math.Range();
+ brushRange.addValue(
+ this.getXForDatum_(this.data_[leftIndex], leftIndex) -
+ this.getSampleWidth_(this.data_, leftIndex, true));
+ brushRange.addValue(
+ this.getXForDatum_(this.data_[rightIndex], rightIndex) +
+ this.getSampleWidth_(this.data_, rightIndex, false));
+ return brushRange;
+ },
+
+ getDataIndex_(dataX) {
+ if (this.data.length === 0) return undefined;
+ const bisect = d3.bisector(this.getXForDatum_.bind(this)).right;
+ return bisect(this.data_, dataX) - 1;
+ },
+
+ prepareDataEvent_(mouseEvent, dataEvent) {
+ ChartBase2D.prototype.prepareDataEvent_.call(
+ this, mouseEvent, dataEvent);
+ dataEvent.index = this.getDataIndex_(dataEvent.x);
+ if (dataEvent.index !== undefined) {
+ dataEvent.data = this.data_[dataEvent.index];
+ }
+ },
+
+ updateBrushContents_(brushSel) {
+ brushSel.selectAll('*').remove();
+ const brushes = this.brushedRange_.isEmpty ? [] : [this.brushedRange_];
+ const brushRectsSel = brushSel.selectAll('rect').data(brushes);
+ brushRectsSel.enter().append('rect');
+ brushRectsSel.exit().remove();
+ this.drawBrush_(brushRectsSel);
+ },
+
+ drawBrush_(brushRectsSel) {
+ brushRectsSel
+ .attr('x', d => this.xScale_(d.min))
+ .attr('y', 0)
+ .attr('width', d => this.xScale_(d.max) - this.xScale_(d.min))
+ .attr('height', this.graphHeight)
+ .attr('fill', 'rgb(213, 236, 229)');
+ }
+ };
+
+ return {
+ ChartBase2DBrushX,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/chart_legend_key.html b/chromium/third_party/catapult/tracing/tracing/ui/base/chart_legend_key.html
new file mode 100644
index 00000000000..1b5b4943898
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/chart_legend_key.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<dom-module id="tr-ui-b-chart-legend-key">
+ <template>
+ <style>
+ #checkbox {
+ margin: 0;
+ visibility: hidden;
+ vertical-align: text-top;
+ }
+ #label, #link {
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ display: inline-block;
+ }
+ </style>
+
+ <input type=checkbox id="checkbox" checked>
+ <tr-ui-a-analysis-link id="link"></tr-ui-a-analysis-link>
+ <label id="label"></label>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-chart-legend-key',
+
+ ready() {
+ this.$.checkbox.addEventListener(
+ 'change', this.onCheckboxChange_.bind(this));
+ },
+
+ /**
+ * Dispatch an event when the checkbox is toggled.
+ * The checkbox is visible when optional is set to true.
+ */
+ onCheckboxChange_() {
+ tr.b.dispatchSimpleEvent(this, tr.ui.b.DataSeriesEnableChangeEventType,
+ true, false,
+ {key: Polymer.dom(this).textContent, enabled: this.enabled});
+ },
+
+ set textContent(t) {
+ Polymer.dom(this.$.label).textContent = t;
+ Polymer.dom(this.$.link).textContent = t;
+ this.updateContents_();
+ },
+
+ set width(w) {
+ w -= 20; // reserve 20px for the checkbox
+ this.$.link.style.width = w + 'px';
+ this.$.label.style.width = w + 'px';
+ },
+
+ get textContent() {
+ return Polymer.dom(this.$.label).textContent;
+ },
+
+ /**
+ * When a legend-key is "optional", then its checkbox is visible to allow
+ * the user to enable/disable the data series for the key.
+ *
+ * @param {boolean} optional
+ */
+ set optional(optional) {
+ this.$.checkbox.style.visibility = optional ? 'visible' : 'hidden';
+ },
+
+ get optional() {
+ return this.$.checkbox.style.visibility === 'visible';
+ },
+
+ set enabled(enabled) {
+ this.$.checkbox.checked = enabled ? 'checked' : '';
+ },
+
+ get enabled() {
+ return this.$.checkbox.checked;
+ },
+
+ set color(c) {
+ this.$.label.style.color = c;
+ this.$.link.color = c;
+ },
+
+ /**
+ * When target is defined, label is hidden and link is shown.
+ * When the link is clicked, then a RequestSelectionChangeEvent is
+ * dispatched containing the target.
+ * When target is undefined, label is shown and link is hidden, so that the
+ * link is not clickable.
+ */
+ set target(target) {
+ this.$.link.setSelectionAndContent(
+ target, Polymer.dom(this.$.label).textContent);
+ this.updateContents_();
+ },
+
+ get target() {
+ return this.$.link.selection;
+ },
+
+ set title(title) {
+ this.$.link.title = title;
+ },
+
+ updateContents_() {
+ this.$.link.style.display = this.target ? '' : 'none';
+ this.$.label.style.display = this.target ? 'none' : '';
+ this.$.label.htmlFor = this.optional ? 'checkbox' : '';
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox.html b/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox.html
new file mode 100644
index 00000000000..0de935ed327
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<dom-module id='tr-ui-b-checkbox'>
+ <template>
+ <style>
+ .inline {
+ display: inline-block;
+ }
+ </style>
+
+ <input type="checkbox" id="checkbox" class="inline"/>
+ <div id="label" class="inline"></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-checkbox',
+
+ created() {
+ this.needsInit_ = true;
+ this.defaultCheckedValue_ = undefined;
+ this.settingsKey_ = undefined;
+ this.label_ = undefined;
+ this.checked_ = false;
+ this.is_ready_ = false;
+ },
+
+ ready() {
+ this.is_ready_ = true;
+ this.$.checkbox.addEventListener('click', function() {
+ this.checked = this.$.checkbox.checked;
+ }.bind(this));
+ this.maybeUpdateElements_();
+ },
+
+ maybeUpdateElements_() {
+ if (!this.is_ready_) return;
+ this.$.label.innerText = this.label_;
+ this.$.checkbox.checked = this.checked_;
+ },
+
+ get defaultCheckedValue() {
+ return this.defaultCheckedValue_;
+ },
+
+ set defaultCheckedValue(defaultCheckedValue) {
+ if (!this.needsInit_) {
+ throw new Error('Already initialized.');
+ }
+ this.defaultCheckedValue_ = defaultCheckedValue;
+ this.maybeInit_();
+ },
+
+ get settingsKey() {
+ return this.settingsKey_;
+ },
+
+ set settingsKey(settingsKey) {
+ if (!this.needsInit_) {
+ throw new Error('Already initialized.');
+ }
+ this.settingsKey_ = settingsKey;
+ this.maybeInit_();
+ },
+
+ maybeInit_() {
+ if (!this.needsInit_) return;
+ if (this.settingsKey_ === undefined) return;
+ if (this.defaultCheckedValue_ === undefined) return;
+ this.needsInit_ = false;
+ this.checked = tr.b.Settings.get(
+ this.settingsKey_, this.defaultCheckedValue_);
+ },
+
+ get label() {
+ return this.label_;
+ },
+
+ set label(label) {
+ this.label_ = label;
+ this.maybeUpdateElements_();
+ },
+
+ get checked() {
+ return this.checked_;
+ },
+
+ set checked(checked) {
+ this.checked_ = checked;
+ this.maybeUpdateElements_();
+ tr.b.Settings.set(this.settingsKey_, this.checked_);
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_picker.html b/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_picker.html
new file mode 100644
index 00000000000..63073255379
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_picker.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/checkbox.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<dom-module id='tr-ui-b-checkbox-picker'>
+ <template>
+ <style>
+ #container {
+ display: flex;
+ flex-direction: column;
+ }
+ </style>
+
+ <div id="container">
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-checkbox-picker',
+ created() {
+ this.needsInit_ = true;
+ this.settingsKey_ = undefined;
+ this.is_ready_ = false;
+ this.checkboxes_ = undefined;
+ },
+
+ ready() {
+ this.is_ready_ = true;
+ this.maybeInit_();
+ this.maybeRenderCheckboxes_();
+ },
+
+ get settingsKey() {
+ return this.settingsKey_;
+ },
+
+ set settingsKey(settingsKey) {
+ if (!this.needsInit_) {
+ throw new Error('Already initialized.');
+ }
+ this.settingsKey_ = settingsKey;
+ this.maybeInit_();
+ },
+
+ maybeInit_() {
+ if (!this.needsInit_) return;
+ if (this.settingsKey_ === undefined) return;
+ if (this.checkboxes_ === undefined) return;
+
+ this.needsInit_ = false;
+
+ for (const key in this.checkboxes_) {
+ this.checkboxes_[key].defaultCheckedValue = false;
+ this.checkboxes_[key].settingsKey = this.settingsKey_ + key;
+ }
+ },
+
+ set items(items) {
+ this.checkboxes_ = {};
+ items.forEach(function(e) {
+ if (e.key in this.checkboxes_) {
+ throw new Error(e.key + ' already exists');
+ }
+ const checkboxEl = document.createElement('tr-ui-b-checkbox');
+ checkboxEl.label = e.label;
+ this.checkboxes_[e.key] = checkboxEl;
+ }.bind(this));
+ this.maybeInit_();
+ this.maybeRenderCheckboxes_();
+ },
+
+ maybeRenderCheckboxes_() {
+ if (!this.is_ready_) return;
+ if (this.checkboxes_ === undefined) return;
+ for (const key in this.checkboxes_) {
+ Polymer.dom(this.$.container).appendChild(this.checkboxes_[key]);
+ }
+ },
+
+ selectCheckbox(key) {
+ if (!(key in this.checkboxes_)) {
+ throw new Error(key + ' does not exists');
+ }
+ this.checkboxes_[key].checked = true;
+ },
+
+ unselectCheckbox(key) {
+ if (!(key in this.checkboxes_)) {
+ throw new Error(key + ' does not exists');
+ }
+ this.checkboxes_[key].checked = false;
+ },
+
+ get checkedKeys() {
+ return Object.keys(this.checkboxes_).filter(function(k) {
+ return this.checkboxes_[k].checked;
+ }.bind(this));
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_picker_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_picker_test.html
new file mode 100644
index 00000000000..ad893d6cc51
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_picker_test.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/checkbox_picker.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basicAllCheckboxUnchecked', function() {
+ const cp = document.createElement('tr-ui-b-checkbox-picker');
+ cp.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Boeing', label: 'I want to fly'}
+ ];
+ this.addHTMLOutput(cp);
+ assert.deepEqual(cp.checkedKeys, []);
+ });
+
+ test('basicSomeCheckboxChecked', function() {
+ const cp = document.createElement('tr-ui-b-checkbox-picker');
+ cp.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Honda', label: 'I want to drive Honda'},
+ {key: 'Tesla', label: 'I want to drive electric car'},
+ ];
+
+ cp.selectCheckbox('Toyota');
+ cp.selectCheckbox('Tesla');
+ this.addHTMLOutput(cp);
+ assert.deepEqual(cp.checkedKeys.sort(), ['Tesla', 'Toyota']);
+ cp.unselectCheckbox('Toyota');
+ assert.deepEqual(cp.checkedKeys, ['Tesla']);
+ });
+
+ test('duplicateKeys', function() {
+ const cp = document.createElement('tr-ui-b-checkbox-picker');
+ assert.throws(function() {
+ cp.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Honda', label: 'I want to drive Honda'},
+ {key: 'Toyota', label: 'I want to drive electric car'},
+ ];
+ });
+ });
+
+ test('selectAndUnselectNonExistingKey', function() {
+ const cp = document.createElement('tr-ui-b-checkbox-picker');
+ cp.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Honda', label: 'I want to drive Honda'},
+ ];
+ assert.throws(function() {
+ cp.selectCheckbox('Lamborghini');
+ });
+ assert.throws(function() {
+ cp.unselectCheckbox('Roll Royce');
+ });
+ });
+
+ test('testPersistentStateOneSetSettingsKeyBeforeSettingItems', function() {
+ const container1 = tr.ui.b.createDiv({textContent: 'Checkbox Picker One'});
+ container1.style.border = 'solid';
+ const cp = document.createElement('tr-ui-b-checkbox-picker');
+ cp.settingsKey = 'checkbox-picker-test-one';
+ cp.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Honda', label: 'I want to drive Honda'},
+ {key: 'Tesla', label: 'I want to drive electric car'},
+ ];
+ cp.selectCheckbox('Toyota');
+ cp.selectCheckbox('Tesla');
+ Polymer.dom(container1).appendChild(cp);
+ this.addHTMLOutput(container1);
+ cp.unselectCheckbox('Tesla');
+ assert.deepEqual(cp.checkedKeys, ['Toyota']);
+
+ this.addHTMLOutput(document.createElement('br'));
+
+ const container2 = tr.ui.b.createDiv(
+ {textContent:
+ 'Checkbox Picker Two (Same settingsKey as Checkbox Picker One)'});
+ container2.style.border = 'solid #0000FF';
+ const cp2 = document.createElement('tr-ui-b-checkbox-picker');
+ cp2.settingsKey = 'checkbox-picker-test-one';
+ cp2.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Honda', label: 'I want to drive Honda'},
+ {key: 'Tesla', label: 'I want to drive electric car'},
+ ];
+ Polymer.dom(container2).appendChild(cp2);
+ this.addHTMLOutput(container2);
+ assert.deepEqual(cp2.checkedKeys, ['Toyota']);
+ });
+
+ test('testPersistentStateTwoSetSettingsKeyAfterSettingItems', function() {
+ const container1 = tr.ui.b.createDiv({textContent: 'Checkbox Picker One'});
+ container1.style.border = 'solid';
+ const cp = document.createElement('tr-ui-b-checkbox-picker');
+ cp.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Honda', label: 'I want to drive Honda'},
+ {key: 'Tesla', label: 'I want to drive electric car'},
+ ];
+ cp.settingsKey = 'checkbox-picker-test-one';
+ cp.selectCheckbox('Toyota');
+ cp.selectCheckbox('Tesla');
+ Polymer.dom(container1).appendChild(cp);
+ this.addHTMLOutput(container1);
+ assert.deepEqual(cp.checkedKeys.sort(), ['Tesla', 'Toyota']);
+
+ this.addHTMLOutput(document.createElement('br'));
+
+ const container2 = tr.ui.b.createDiv(
+ {textContent:
+ 'Checkbox Picker Two (Same settingsKey as Checkbox Picker One)'});
+ container2.style.border = 'solid #0000FF';
+ const cp2 = document.createElement('tr-ui-b-checkbox-picker');
+ cp2.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Honda', label: 'I want to drive Honda'},
+ {key: 'Tesla', label: 'I want to drive electric car'},
+ ];
+ Polymer.dom(container2).appendChild(cp2);
+ this.addHTMLOutput(container2);
+ cp2.settingsKey = 'checkbox-picker-test-one';
+ assert.deepEqual(cp2.checkedKeys.sort(), ['Tesla', 'Toyota']);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_test.html
new file mode 100644
index 00000000000..47ac3492ef5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/checkbox_test.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/checkbox.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basicUnchecked', function() {
+ const checkbox = document.createElement('tr-ui-b-checkbox');
+ checkbox.label = 'Yo like pizza?';
+ this.addHTMLOutput(checkbox);
+ assert.strictEqual(checkbox.label, 'Yo like pizza?');
+ assert.isFalse(checkbox.checked);
+ });
+
+ test('basicChecked', function() {
+ const checkbox = document.createElement('tr-ui-b-checkbox');
+ checkbox.label = 'Yo like cookie?';
+ checkbox.checked = true;
+ this.addHTMLOutput(checkbox);
+ assert.strictEqual(checkbox.label, 'Yo like cookie?');
+ assert.isTrue(checkbox.checked);
+ });
+
+ test('testPersistentStateOneSetSettingsKeyBeforeAddToDom', function() {
+ const checkbox = document.createElement('tr-ui-b-checkbox');
+ checkbox.settingsKey = 'checkbox-basic-test-one';
+ checkbox.label = 'I like sushi';
+ checkbox.defaultCheckedValue = false;
+ this.addHTMLOutput(checkbox);
+ assert.isFalse(checkbox.checked);
+ checkbox.checked = true;
+
+ const checkbox2 = document.createElement('tr-ui-b-checkbox');
+ checkbox2.label = 'I like sushi';
+ checkbox2.defaultCheckedValue = false;
+ checkbox2.settingsKey = 'checkbox-basic-test-one';
+ this.addHTMLOutput(checkbox2);
+ assert.isTrue(checkbox2.checked);
+ });
+
+ test('testPersistentStateTwoSetSettingsKeyAfterAddToDom', function() {
+ const checkbox = document.createElement('tr-ui-b-checkbox');
+ this.addHTMLOutput(checkbox);
+ checkbox.label = 'I like Ramen';
+ checkbox.settingsKey = 'checkbox-basic-test-two';
+ checkbox.defaultCheckedValue = false;
+ assert.isFalse(checkbox.checked);
+ checkbox.checked = true;
+
+ const checkbox2 = document.createElement('tr-ui-b-checkbox');
+ this.addHTMLOutput(checkbox2);
+ checkbox2.label = 'I like Ramen';
+ checkbox2.defaultCheckedValue = false;
+ checkbox2.settingsKey = 'checkbox-basic-test-two';
+ assert.isTrue(checkbox2.checked);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/color_legend.html b/chromium/third_party/catapult/tracing/tracing/ui/base/color_legend.html
new file mode 100644
index 00000000000..c082f12f834
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/color_legend.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/model/compound_event_selection_state.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+
+<!--
+@fileoverview A component used to display a label and a color square.
+
+The colored square is typically filled with the color associated with
+that label, using the getColorId* methods from base/color_scheme.
+-->
+<dom-module id='tr-ui-b-color-legend'>
+ <template>
+ <style>
+ :host {
+ display: inline-block;
+ }
+
+ #square {
+ font-size: 150%; /* Make the square bigger. */
+ line-height: 0%; /* Prevent the square from increasing legend height. */
+ }
+ </style>
+ <span id="square"></span>
+ <span id="label"></span>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-color-legend',
+
+ ready() {
+ const blackSquareCharCode = 9632;
+ this.$.square.innerText = String.fromCharCode(blackSquareCharCode);
+ this.label_ = undefined;
+
+ this.compoundEventSelectionState_ =
+ tr.model.CompoundEventSelectionState.NOT_SELECTED;
+ },
+
+ set compoundEventSelectionState(compoundEventSelectionState) {
+ this.compoundEventSelectionState_ = compoundEventSelectionState;
+ // TODO(nduca): Adjust appearance based on associated state.
+ },
+
+ get label() {
+ return this.label_;
+ },
+
+ set label(label) {
+ if (label === undefined) {
+ this.setLabelAndColorId(undefined, undefined);
+ return;
+ }
+
+ const colorId = tr.b.ColorScheme.getColorIdForGeneralPurposeString(
+ label);
+ this.setLabelAndColorId(label, colorId);
+ },
+
+ setLabelAndColorId(label, colorId) {
+ this.label_ = label;
+
+ Polymer.dom(this.$.label).textContent = '';
+ Polymer.dom(this.$.label).appendChild(tr.ui.b.asHTMLOrTextNode(label));
+
+ if (colorId === undefined) {
+ this.$.square.style.color = 'initial';
+ } else {
+ this.$.square.style.color = tr.b.ColorScheme.colorsAsStrings[colorId];
+ }
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/color_legend_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/color_legend_test.html
new file mode 100644
index 00000000000..b19b3a4b7e5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/color_legend_test.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/color_legend.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const CompoundEventSelectionState = tr.model.CompoundEventSelectionState;
+
+ function checkSquareColor(colorLegend, expectedColor) {
+ assert.strictEqual(
+ getComputedStyle(colorLegend.$.square).color, expectedColor);
+ }
+
+ test('noLabelSet', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(0, 0, 0)');
+ });
+
+ test('undefinedLabel', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = undefined;
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(0, 0, 0)');
+ });
+
+ test('emptyLabel', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = '';
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(255, 161, 161)');
+ });
+
+ test('nonEmptyLabel', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = 'Frequency';
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(255, 133, 236)');
+ });
+
+ test('longLabel', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = 'Total memory usage';
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(150, 193, 255)');
+ });
+
+ test('directlySetColorId', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.setLabelAndColorId('hello_world', 7 /* colorId */);
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(152, 220, 149)');
+ });
+
+ test('directlyProvidedLabelElement', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.setLabelAndColorId(
+ tr.ui.b.createSpan({textContent: 'hello',
+ className: 'hello-span'}),
+ 7 /* colorId */);
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(152, 220, 149)');
+ });
+
+ test('cessObjectSelected', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = 'Object selected';
+ colorLegend.compoundEventSelectionState =
+ CompoundEventSelectionState.EVENT_SELECTED;
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(228, 184, 134)');
+ });
+
+ test('cessSomeAssociatedObjectsSelected', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = 'Some associated objects selected';
+ colorLegend.compoundEventSelectionState =
+ CompoundEventSelectionState.SOME_ASSOCIATED_EVENTS_SELECTED;
+
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(255, 155, 172)');
+ });
+
+ test('cessAllAssociatedObjectsSelected', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = 'All associated objects selected';
+ colorLegend.compoundEventSelectionState =
+ CompoundEventSelectionState.ALL_ASSOCIATED_EVENTS_SELECTED;
+
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(150, 193, 255)');
+ });
+
+ test('cessObjectAndSomeAssociatedObjectsSelected', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = 'Object and some associated objects selected';
+ colorLegend.compoundEventSelectionState =
+ CompoundEventSelectionState.EVENT_AND_SOME_ASSOCIATED_SELECTED;
+
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(204, 158, 255)');
+ });
+
+ test('cessObjectAndAllAssociatedObjectsSelected', function() {
+ const colorLegend = document.createElement('tr-ui-b-color-legend');
+ colorLegend.label = 'Object and all associated objects selected';
+ colorLegend.compoundEventSelectionState =
+ CompoundEventSelectionState.EVENT_AND_ALL_ASSOCIATED_SELECTED;
+
+ this.addHTMLOutput(colorLegend);
+ checkSquareColor(colorLegend, 'rgb(255, 146, 193)');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/column_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/base/column_chart.html
new file mode 100644
index 00000000000..9d14ce92974
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/column_chart.html
@@ -0,0 +1,427 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/chart_base_2d_brushable_x.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const ColumnChart = tr.ui.b.define('column-chart', tr.ui.b.ChartBase2DBrushX);
+
+ ColumnChart.prototype = {
+ __proto__: tr.ui.b.ChartBase2DBrushX.prototype,
+
+ decorate() {
+ super.decorate();
+
+ // ColumnChart allows bars to have arbitrary, non-uniform widths. Bars
+ // need not all be the same width. The width of each bar is automatically
+ // computed from the bar's x-coordinate and that of the next bar, which
+ // can not define the width of the last bar. This is the width (in the
+ // xScale's domain (as opposed to the xScale's range (which is measured in
+ // pixels))) of the last bar. When there are at least 2 bars, this is
+ // computed as the average width of the bars. When there is a single bar,
+ // this must default to a non-zero number so that the width of the only
+ // bar will not be zero.
+ this.xCushion_ = 1;
+
+ this.isStacked_ = false;
+ this.isGrouped_ = false;
+
+ this.enableHoverBox = true;
+ this.displayXInHover = false;
+ this.enableToolTip = false;
+
+ this.toolTipCallBack_ = () => {};
+ },
+
+ set toolTipCallBack(callback) {
+ this.toolTipCallBack_ = callback;
+ },
+
+ get toolTipCallBack() {
+ return this.toolTipCallBack_;
+ },
+
+ set isGrouped(grouped) {
+ this.isGrouped_ = grouped;
+ if (grouped) {
+ this.getDataSeries('group').color = 'transparent';
+ }
+ this.updateContents_();
+ },
+
+ get isGrouped() {
+ return this.isGrouped_;
+ },
+
+ set isStacked(stacked) {
+ this.isStacked_ = true;
+ this.updateContents_();
+ },
+
+ get isStacked() {
+ return this.isStacked_;
+ },
+
+ get defaultGraphHeight() {
+ return 100;
+ },
+
+ get defaultGraphWidth() {
+ return 10 * this.data_.length;
+ },
+
+ updateScales_() {
+ if (this.data_.length === 0) return;
+
+ let xDifferences = 0;
+ let currentX = undefined;
+ let previousX = undefined;
+ this.data_.forEach(function(datum, index) {
+ previousX = currentX;
+ currentX = this.getXForDatum_(datum, index);
+ if (previousX !== undefined) {
+ xDifferences += currentX - previousX;
+ }
+ }, this);
+
+ // X.
+ // Leave a cushion on the right so that the last rect doesn't
+ // exceed the chart boundaries. The last rect's width is set to the
+ // average width of the rects, which is chart.width / data.length.
+ this.xScale_.range([0, this.graphWidth]);
+ const domain = d3.extent(this.data_, this.getXForDatum_.bind(this));
+ if (this.data_.length > 1) {
+ this.xCushion_ = xDifferences / (this.data_.length - 1);
+ }
+ this.xScale_.domain([domain[0], domain[1] + this.xCushion_]);
+
+ // Y.
+ this.yScale_.range([this.graphHeight, 0]);
+ this.yScale_.domain(this.getYScaleDomain_(
+ this.dataRange.min, this.dataRange.max));
+ },
+
+ updateDataRange_() {
+ if (!this.isStacked) {
+ super.updateDataRange_();
+ return;
+ }
+
+ this.autoDataRange_.reset();
+ this.autoDataRange_.addValue(0);
+ for (const datum of this.data_) {
+ let sum = 0;
+ for (const [key, series] of this.seriesByKey_) {
+ if (datum[key] === undefined) {
+ continue;
+ } else if (this.isGrouped && key === 'group') {
+ continue;
+ }
+ sum += datum[key];
+ }
+ this.autoDataRange_.addValue(sum);
+ }
+ },
+
+ getStackedRectsForDatum_(datum, index) {
+ const stacks = [];
+ let bottom = this.yScale_.range()[0];
+ let sum = 0;
+ for (const [key, series] of this.seriesByKey_) {
+ if (datum[key] === undefined || !this.isSeriesEnabled(key)) {
+ continue;
+ } else if (this.isGrouped && key === 'group') {
+ continue;
+ }
+
+ sum += this.dataRange.clamp(datum[key]);
+ const heightPx = bottom - this.yScale_(sum);
+ bottom -= heightPx;
+ stacks.push({
+ key,
+ value: datum[key],
+ color: this.getDataSeries(key).color,
+ heightPx,
+ topPx: bottom,
+ underflow: sum < this.dataRange.min,
+ overflow: sum > this.dataRange.max,
+ });
+ }
+ return stacks;
+ },
+
+ getRectsForDatum_(datum, index) {
+ if (this.isStacked) {
+ return this.getStackedRectsForDatum_(datum, index);
+ }
+
+ const stacks = [];
+ for (const [key, series] of this.seriesByKey_) {
+ if (datum[key] === undefined || !this.isSeriesEnabled(key)) {
+ continue;
+ }
+
+ const clampedValue = this.dataRange.clamp(datum[key]);
+ const topPx = this.yScale_(Math.max(
+ clampedValue, this.getYScaleMin_()));
+ stacks.push({
+ key,
+ value: datum[key],
+ topPx,
+ heightPx: this.yScale_.range()[0] - topPx,
+ color: this.getDataSeries(key).color,
+ underflow: datum[key] < this.dataRange.min,
+ overflow: datum[key] > this.dataRange.max,
+ });
+ }
+ stacks.sort(function(a, b) {
+ return b.topPx - a.topPx;
+ });
+ return stacks;
+ },
+
+ drawToolTip_(rect) {
+ if (!this.enableToolTip) return;
+
+ const chartAreaSel = d3.select(this.chartAreaElement);
+ chartAreaSel.selectAll('.tooltip').remove();
+
+ const labelText = 'View Breakdown';
+ const labelWidth = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, labelText).width + 5;
+ const labelHeight = this.textHeightPx_;
+
+ const toolTipLeftPx = rect.leftPx + (rect.widthPx / 2);
+ const toolTipTopPx = rect.topPx;
+
+ chartAreaSel
+ .append('rect')
+ .attr('class', 'tooltip')
+ .attr('fill', 'white')
+ .attr('opacity', 0.8)
+ .attr('stroke', 'black')
+ .attr('x', toolTipLeftPx)
+ .attr('y', toolTipTopPx)
+ .attr('width', labelWidth + 5)
+ .attr('height', labelHeight + 10);
+
+ chartAreaSel
+ .append('text')
+ .style('cursor', 'pointer')
+ .attr('class', 'tooltip')
+ .on('mousedown', () => this.toolTipCallBack_(rect))
+ .attr('fill', 'blue')
+ .attr('x', toolTipLeftPx + 4)
+ .attr('y', toolTipTopPx + labelHeight)
+ .attr('text-decoration', 'underline')
+ .text(labelText);
+ },
+
+ drawHoverValueBox_(rect) {
+ const rectHoverEvent = new tr.b.Event('rect-mouseenter');
+ rectHoverEvent.rect = rect;
+ this.dispatchEvent(rectHoverEvent);
+
+ if (!this.enableHoverBox) return;
+
+ const seriesKeys = [...this.seriesByKey_.keys()];
+ const chartAreaSel = d3.select(this.chartAreaElement);
+ chartAreaSel.selectAll('.hover').remove();
+ let keyWidthPx = 0;
+ let keyHeightPx = 0;
+ if (seriesKeys.length > 1 && !this.isGrouped) {
+ keyWidthPx = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, rect.key).width + 5;
+ keyHeightPx = this.textHeightPx_;
+ }
+
+ let xLabelWidthPx = 0;
+ let xLabelHeightPx = 0;
+ if (this.displayXInHover) {
+ xLabelWidthPx = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, rect.datum.x).width + 5;
+ xLabelHeightPx = this.textHeightPx_;
+ }
+
+ let groupWidthPx = 0;
+ let groupHeightPx = 0;
+ if (this.isGrouped && rect.datum.group !== undefined) {
+ groupWidthPx = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, rect.datum.group).width + 5;
+ groupHeightPx = this.textHeightPx_;
+ }
+
+ let value = rect.value;
+ if (this.unit) value = this.unit.format(value);
+ const valueWidthPx = tr.ui.b.getSVGTextSize(
+ this.chartAreaElement, value).width + 5;
+ const valueHeightPx = this.textHeightPx_;
+
+ const hoverWidthPx = Math.max(keyWidthPx, valueWidthPx,
+ xLabelWidthPx, groupWidthPx);
+
+ let hoverLeftPx = rect.leftPx + (rect.widthPx / 2);
+ hoverLeftPx = Math.max(hoverLeftPx - hoverWidthPx, -this.margin.left);
+
+ const hoverHeightPx = keyHeightPx + valueHeightPx +
+ xLabelHeightPx + groupHeightPx + 2;
+
+ const topOffSetPx = this.isGrouped ? 36 : 12;
+ let hoverTopPx = rect.topPx;
+ hoverTopPx = Math.min(
+ hoverTopPx, this.getBoundingClientRect().height -
+ hoverHeightPx - topOffSetPx);
+
+ chartAreaSel
+ .append('rect')
+ .attr('class', 'hover')
+ .on('mouseleave', () => this.clearHoverValueBox_(rect))
+ .on('mousedown', this.drawToolTip_.bind(this, rect))
+ .attr('fill', 'white')
+ .attr('stroke', 'black')
+ .attr('x', hoverLeftPx)
+ .attr('y', hoverTopPx)
+ .attr('width', hoverWidthPx)
+ .attr('height', hoverHeightPx);
+
+ if (seriesKeys.length > 1 && !this.isGrouped) {
+ chartAreaSel
+ .append('text')
+ .attr('class', 'hover')
+ .on('mouseleave', () => this.clearHoverValueBox_(rect))
+ .on('mousedown', this.drawToolTip_.bind(this, rect))
+ .attr('fill', rect.color)
+ .attr('x', hoverLeftPx + 2)
+ .attr('y', hoverTopPx + keyHeightPx - 2)
+ .text(rect.key);
+ }
+
+ if (this.displayXInHover) {
+ chartAreaSel.append('text')
+ .attr('class', 'hover')
+ .on('mouseleave', () => this.clearHoverValueBox_(rect))
+ .on('mousedown', this.drawToolTip_.bind(this, rect))
+ .attr('fill', rect.color)
+ .attr('x', hoverLeftPx + 2)
+ .attr('y', hoverTopPx + keyHeightPx + xLabelHeightPx - 2)
+ .text(rect.datum.x);
+ }
+
+ if (this.isGrouped && rect.datum.group !== undefined) {
+ chartAreaSel.append('text')
+ .attr('class', 'hover')
+ .on('mouseleave', () => this.clearHoverValueBox_(rect))
+ .on('mousedown', this.drawToolTip_.bind(this, rect))
+ .attr('fill', rect.color)
+ .attr('x', hoverLeftPx + 2)
+ .attr('y', hoverTopPx + keyHeightPx +
+ xLabelHeightPx + groupHeightPx - 2)
+ .text(rect.datum.group);
+ }
+
+ chartAreaSel
+ .append('text')
+ .attr('class', 'hover')
+ .on('mouseleave', () => this.clearHoverValueBox_(rect))
+ .on('mousedown', this.drawToolTip_.bind(this, rect))
+ .attr('fill', rect.color)
+ .attr('x', hoverLeftPx + 2)
+ .attr('y', hoverTopPx + hoverHeightPx - 2)
+ .text(value);
+ },
+
+ clearHoverValueBox_(rect) {
+ const event = window.event;
+ if (event.relatedTarget &&
+ Array.from(event.relatedTarget.classList).includes('hover')) {
+ return;
+ }
+
+ const rectHoverEvent = new tr.b.Event('rect-mouseleave');
+ rectHoverEvent.rect = rect;
+ this.dispatchEvent(rectHoverEvent);
+
+ d3.select(this.chartAreaElement).selectAll('.hover').remove();
+ },
+
+ drawRect_(rect, sel) {
+ sel = sel.data([rect]);
+ sel.enter().append('rect')
+ .attr('fill', rect.color)
+ .attr('x', rect.leftPx)
+ .attr('y', rect.topPx)
+ .attr('width', rect.widthPx)
+ .attr('height', rect.heightPx)
+ .on('mousedown', this.drawToolTip_.bind(this, rect))
+ .on('mouseenter', this.drawHoverValueBox_.bind(this, rect))
+ .on('mouseleave', this.clearHoverValueBox_.bind(this, rect));
+ sel.exit().remove();
+ },
+
+ drawUnderflow_(rect, sel) {
+ sel = sel.data([rect]);
+ sel.enter().append('text')
+ .text('*')
+ .attr('fill', rect.color)
+ .attr('x', rect.leftPx + (rect.widthPx / 2))
+ .attr('y', this.graphHeight)
+ .on('mousedown', this.drawToolTip_.bind(this, rect))
+ .on('mouseenter', this.drawHoverValueBox_.bind(this, rect))
+ .on('mouseleave', this.clearHoverValueBox_.bind(this, rect));
+ sel.exit().remove();
+ },
+
+ drawOverflow_(rect, sel) {
+ sel = sel.data([rect]);
+ sel.enter().append('text')
+ .text('*')
+ .attr('fill', rect.color)
+ .attr('x', rect.leftPx + (rect.widthPx / 2))
+ .attr('y', 0);
+ sel.exit().remove();
+ },
+
+ updateDataContents_(dataSel) {
+ dataSel.selectAll('*').remove();
+ const chartAreaSel = d3.select(this.chartAreaElement);
+ const seriesKeys = [...this.seriesByKey_.keys()];
+ const rectsSel = dataSel.selectAll('path');
+ this.data_.forEach(function(datum, index) {
+ const currentX = this.getXForDatum_(datum, index);
+ let width = undefined;
+ if (index < (this.data_.length - 1)) {
+ const nextX = this.getXForDatum_(this.data_[index + 1], index + 1);
+ width = nextX - currentX;
+ } else {
+ width = this.xCushion_;
+ }
+ for (const rect of this.getRectsForDatum_(datum, index)) {
+ rect.datum = datum;
+ rect.index = index;
+ rect.leftPx = this.xScale_(currentX);
+ rect.rightPx = this.xScale_(currentX + width);
+ rect.widthPx = rect.rightPx - rect.leftPx;
+ this.drawRect_(rect, rectsSel);
+ if (rect.underflow) {
+ this.drawUnderflow_(rect, rectsSel);
+ }
+ if (rect.overflow) {
+ this.drawOverflow_(rect, rectsSel);
+ }
+ }
+ }, this);
+ }
+ };
+
+ return {
+ ColumnChart,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/column_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/column_chart_test.html
new file mode 100644
index 00000000000..4771b9f60fa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/column_chart_test.html
@@ -0,0 +1,276 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/column_chart.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('chartLegendKey', function() {
+ let key = document.createElement('tr-ui-b-chart-legend-key');
+ key.textContent = 'Lorem ipsum dolor sit amet';
+ key.color = 'red';
+ this.addHTMLOutput(key);
+
+ key = document.createElement('tr-ui-b-chart-legend-key');
+ key.textContent = 'ipsum dolor sit amet';
+ key.target = 'orange ipsum';
+ key.color = 'orange';
+ this.addHTMLOutput(key);
+
+ key = document.createElement('tr-ui-b-chart-legend-key');
+ key.target = 'brown dolor';
+ key.color = 'brown';
+ key.textContent = 'dolor sit amet';
+ this.addHTMLOutput(key);
+ });
+
+ test('instantiation_legendTargets', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ chart.getDataSeries('lorem_ipsum').target = 'lorem_ipsumTarget';
+ chart.getDataSeries('lorem_ipsum').title = 'lorem ipsum';
+ chart.getDataSeries('qux').target = 'quxTarget';
+ chart.getDataSeries('lorem_ipsum').optional = true;
+ chart.getDataSeries('bar').optional = true;
+ chart.isStacked = true;
+ chart.hideXAxis = true;
+ this.addHTMLOutput(chart);
+ chart.data = [{x: 0, foo: 3, lorem_ipsum: 5, bar: 1, qux: 2}];
+
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(
+ chart, function(element) {
+ return element.tagName === 'TR-UI-B-CHART-LEGEND-KEY' &&
+ element.textContent === 'lorem_ipsum' &&
+ element.target === 'lorem_ipsumTarget';
+ }));
+ });
+
+ test('instantiation_singleSeries', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ chart.xAxisLabel = 'ms';
+ chart.yAxisLabel = '#';
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, value: 100},
+ {x: 20, value: 110},
+ {x: 30, value: 100},
+ {x: 40, value: 50}
+ ];
+ });
+
+ test('instantiation_singleDatum', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, value: 100},
+ ];
+ });
+
+ test('instantiation_stacked', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ chart.isStacked = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, foo: 10, bar: 5, qux: 7},
+ {x: 20, foo: 11, bar: 6, qux: 3},
+ {x: 30, foo: 10, bar: 4, qux: 8},
+ {x: 40, foo: 5, bar: 1, qux: 2}
+ ];
+ });
+
+ test('instantiation_singleSeries_yLogScale', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ chart.isYLogScale = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, value: 100},
+ {x: 20, value: 10},
+ {x: 30, value: 1},
+ {x: 40, value: 0.1},
+ {x: 50, value: 0.01},
+ {x: 60, value: 0.001}
+ ];
+ });
+
+ test('undefined', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ assert.throws(function() {
+ chart.data = undefined;
+ });
+ });
+
+ test('instantiation_twoSeries', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 100, beta: 50},
+ {x: 20, alpha: 110, beta: 75},
+ {x: 30, alpha: 100, beta: 125},
+ {x: 40, alpha: 50, beta: 125}
+ ];
+
+ const r = new tr.b.math.Range();
+ r.addValue(20);
+ r.addValue(40);
+ chart.brushedRange = r;
+ });
+
+ test('instantiation_twoSeries_yLogScale', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ chart.isYLogScale = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 100, beta: 50},
+ {x: 20, alpha: 110, beta: 75},
+ {x: 30, alpha: 100, beta: 125},
+ {x: 40, alpha: 50, beta: 125}
+ ];
+
+ const r = new tr.b.math.Range();
+ r.addValue(20);
+ r.addValue(40);
+ chart.brushedRange = r;
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueSparse', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 20, beta: undefined},
+ {x: 20, alpha: undefined, beta: 10},
+ {x: 30, alpha: 10, beta: undefined},
+ {x: 45, alpha: undefined, beta: 20},
+ {x: 50, alpha: 25, beta: 30}
+ ];
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueNotSparse', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 20, beta: 40},
+ {x: 20, alpha: undefined, beta: 10},
+ {x: 30, alpha: 10, beta: undefined},
+ {x: 45, alpha: undefined, beta: 20},
+ {x: 50, alpha: 30, beta: undefined}
+ ];
+ });
+
+ test('brushRangeFromIndices', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ const data = [
+ {x: 10, value: 50},
+ {x: 30, value: 60},
+ {x: 70, value: 70},
+ {x: 80, value: 80},
+ {x: 120, value: 90}
+ ];
+ chart.data = data;
+ let r = new tr.b.math.Range();
+
+ // Range min should be 10.
+ r = chart.computeBrushRangeFromIndices(-2, 1);
+ assert.strictEqual(r.min, 10);
+
+ // Range max should be 120.
+ r = chart.computeBrushRangeFromIndices(3, 10);
+ assert.strictEqual(r.max, 120);
+
+ // Range should be [10, 120]
+ r = chart.computeBrushRangeFromIndices(-2, 10);
+ assert.strictEqual(r.min, 10);
+ assert.strictEqual(r.max, 120);
+
+ // Range should be [20, 100]
+ r = chart.computeBrushRangeFromIndices(1, 3);
+ assert.strictEqual(r.min, 20);
+ assert.strictEqual(r.max, 100);
+ });
+
+ test('instantiation_interactiveBrushing', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, value: 50},
+ {x: 20, value: 60},
+ {x: 30, value: 80},
+ {x: 40, value: 20},
+ {x: 50, value: 30},
+ {x: 60, value: 20},
+ {x: 70, value: 15},
+ {x: 80, value: 20}
+ ];
+
+ let mouseDownX = undefined;
+ let curMouseX = undefined;
+
+ function updateBrushedRange() {
+ if (mouseDownX === undefined || (mouseDownX === curMouseX)) {
+ chart.brushedRange = new tr.b.math.Range();
+ return;
+ }
+ const r = new tr.b.math.Range();
+ r.min = Math.min(mouseDownX, curMouseX);
+ r.max = Math.max(mouseDownX, curMouseX);
+ chart.brushedRange = r;
+ }
+
+ chart.addEventListener('item-mousedown', function(e) {
+ mouseDownX = e.x;
+ curMouseX = e.x;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mousemove', function(e) {
+ if (e.button === undefined) return;
+ curMouseX = e.x;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mouseup', function(e) {
+ curMouseX = e.x;
+ updateBrushedRange();
+ });
+ });
+
+ test('overrideDataRange', function() {
+ let chart = new tr.ui.b.ColumnChart();
+ chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(10, 90);
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, value: 0},
+ {x: 1, value: 100},
+ ];
+
+ chart = new tr.ui.b.ColumnChart();
+ chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(-10, 100);
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, value: 0},
+ {x: 1, value: 50},
+ ];
+ });
+
+ test('instantiationGrouped', function() {
+ const chart = new tr.ui.b.ColumnChart();
+ chart.graphWidth = 300;
+ chart.graphHeight = 200;
+ chart.isStacked = true;
+ chart.isGrouped = true;
+ chart.displayXInHover = true;
+ chart.enableToolTip = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 100, beta: 50, group: 'group1' },
+ {x: 20, alpha: 110, beta: 75, group: 'group2' },
+ {x: 30 },
+ {x: 40, alpha: 100, beta: 125, group: 'group1' },
+ {x: 50, alpha: 50, beta: 125, group: 'group2' }
+ ];
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/constants.html b/chromium/third_party/catapult/tracing/tracing/ui/base/constants.html
new file mode 100644
index 00000000000..8c38d0bb1b4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/constants.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const constants = {
+ HEADING_WIDTH: 250
+ };
+
+ return {
+ constants,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children.html b/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children.html
new file mode 100644
index 00000000000..3ce0d3908b1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Container that decorates its children.
+ */
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * @constructor
+ */
+ const ContainerThatDecoratesItsChildren = tr.ui.b.define('div');
+
+ ContainerThatDecoratesItsChildren.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.observer_ = new WebKitMutationObserver(this.didMutate_.bind(this));
+ this.observer_.observe(this, { childList: true });
+
+ // textContent is a variable on regular HTMLElements. However, we want to
+ // hook and prevent writes to it.
+ Object.defineProperty(
+ this, 'textContent',
+ { get: undefined, set: this.onSetTextContent_});
+ },
+
+ appendChild(x) {
+ HTMLDivElement.prototype.appendChild.call(this, x);
+ this.didMutate_(this.observer_.takeRecords());
+ },
+
+ insertBefore(x, y) {
+ HTMLDivElement.prototype.insertBefore.call(this, x, y);
+ this.didMutate_(this.observer_.takeRecords());
+ },
+
+ removeChild(x) {
+ HTMLDivElement.prototype.removeChild.call(this, x);
+ this.didMutate_(this.observer_.takeRecords());
+ },
+
+ replaceChild(x, y) {
+ HTMLDivElement.prototype.replaceChild.call(this, x, y);
+ this.didMutate_(this.observer_.takeRecords());
+ },
+
+ onSetTextContent_(textContent) {
+ if (textContent !== '') {
+ throw new Error('textContent can only be set to \'\'.');
+ }
+ this.clear();
+ },
+
+ clear() {
+ while (Polymer.dom(this).lastChild) {
+ HTMLDivElement.prototype.removeChild.call(
+ this, Polymer.dom(this).lastChild);
+ }
+ this.didMutate_(this.observer_.takeRecords());
+ },
+
+ didMutate_(records) {
+ this.beginDecorating_();
+ for (let i = 0; i < records.length; i++) {
+ const addedNodes = records[i].addedNodes;
+ if (addedNodes) {
+ for (let j = 0; j < addedNodes.length; j++) {
+ this.decorateChild_(addedNodes[j]);
+ }
+ }
+ const removedNodes = records[i].removedNodes;
+ if (removedNodes) {
+ for (let j = 0; j < removedNodes.length; j++) {
+ this.undecorateChild_(removedNodes[j]);
+ }
+ }
+ }
+ this.doneDecoratingForNow_();
+ },
+
+ decorateChild_(child) {
+ throw new Error('Not implemented');
+ },
+
+ undecorateChild_(child) {
+ throw new Error('Not implemented');
+ },
+
+ beginDecorating_() {
+ },
+
+ doneDecoratingForNow_() {
+ }
+ };
+
+ return {
+ ContainerThatDecoratesItsChildren,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html
new file mode 100644
index 00000000000..54417b3ded6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/container_that_decorates_its_children_test.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/container_that_decorates_its_children.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createChild() {
+ const span = document.createElement('span');
+ span.decorated = false;
+ return span;
+ }
+
+ /**
+ * @constructor
+ */
+ const SimpleContainer = tr.ui.b.define(
+ 'simple-container', tr.ui.b.ContainerThatDecoratesItsChildren);
+
+ SimpleContainer.prototype = {
+ __proto__: tr.ui.b.ContainerThatDecoratesItsChildren.prototype,
+
+ decorateChild_(child) {
+ assert.isFalse(child.decorated);
+ child.decorated = true;
+ },
+
+ undecorateChild_(child) {
+ assert.isTrue(child.decorated);
+ child.decorated = false;
+ }
+ };
+
+ test('add', function() {
+ const container = new SimpleContainer();
+ Polymer.dom(container).appendChild(createChild());
+ Polymer.dom(container).appendChild(createChild());
+ Polymer.dom(container).appendChild(createChild());
+ assert.isTrue(container.children[0].decorated);
+ assert.isTrue(container.children[1].decorated);
+ assert.isTrue(container.children[2].decorated);
+ });
+
+ test('clearUsingTextContent', function() {
+ const c0 = createChild();
+ const container = new SimpleContainer();
+ Polymer.dom(container).appendChild(c0);
+ Polymer.dom(container).textContent = '';
+ assert.isFalse(c0.decorated);
+ });
+
+ test('clear', function() {
+ const c0 = createChild();
+ const container = new SimpleContainer();
+ Polymer.dom(container).appendChild(c0);
+ container.clear();
+ assert.isFalse(c0.decorated);
+ });
+
+ test('insertNewBefore', function() {
+ const c0 = createChild();
+ const c1 = createChild();
+ const container = new SimpleContainer();
+ Polymer.dom(container).appendChild(c1);
+ Polymer.dom(container).insertBefore(c0, c1);
+ assert.isTrue(c0.decorated);
+ assert.isTrue(c1.decorated);
+ });
+
+ test('insertExistingBefore', function() {
+ const c0 = createChild();
+ const c1 = createChild();
+ const container = new SimpleContainer();
+ Polymer.dom(container).appendChild(c1);
+ Polymer.dom(container).appendChild(c0);
+ Polymer.dom(container).insertBefore(c0, c1);
+ assert.isTrue(c0.decorated);
+ assert.isTrue(c1.decorated);
+ });
+
+ test('testReplace', function() {
+ const c0 = createChild();
+ const c1 = createChild();
+ const container = new SimpleContainer();
+ Polymer.dom(container).appendChild(c0);
+ Polymer.dom(container).replaceChild(c1, c0);
+ assert.isFalse(c0.decorated);
+ assert.isTrue(c1.decorated);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/d3.html b/chromium/third_party/catapult/tracing/tracing/ui/base/d3.html
new file mode 100644
index 00000000000..bce0554c512
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/d3.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<script src="/tracing/ui/base/d3_preload.js"></script>
+<script src="/d3.min.js"></script>
+<script src="/tracing/ui/base/d3_postload.js"></script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/d3_postload.js b/chromium/third_party/catapult/tracing/tracing/ui/base/d3_postload.js
new file mode 100644
index 00000000000..94cefdb15f9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/d3_postload.js
@@ -0,0 +1,8 @@
+/* Copyright (c) 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+'use strict';
+
+(function(window) {
+ window.define = undefined;
+}).call(this, this);
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/d3_preload.js b/chromium/third_party/catapult/tracing/tracing/ui/base/d3_preload.js
new file mode 100644
index 00000000000..57548f1d175
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/d3_preload.js
@@ -0,0 +1,11 @@
+/* Copyright (c) 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+'use strict';
+
+(function(window) {
+ window.define = function(x) {
+ window.d3 = x;
+ };
+ window.define.amd = true;
+})(this);
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/deep_utils.html b/chromium/third_party/catapult/tracing/tracing/ui/base/deep_utils.html
new file mode 100644
index 00000000000..2a1ad88d6cc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/deep_utils.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ function iterateElementDeeplyImpl(element, cb, thisArg, includeElement) {
+ if (includeElement && cb.call(thisArg, element)) return true;
+
+ if (element.root &&
+ element.root !== element &&
+ iterateElementDeeplyImpl(element.root, cb, thisArg, false)) {
+ // Some elements, most notably Polymer template dom-repeat='...'
+ // elements, are their own shadow root. Make sure that we avoid infinite
+ // recursion by avoiding these elements.
+ return true;
+ }
+ const children = Polymer.dom(element).children;
+ for (let i = 0; i < children.length; i++) {
+ if (iterateElementDeeplyImpl(children[i], cb, thisArg, true)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ function iterateElementDeeply(element, cb, thisArg) {
+ iterateElementDeeplyImpl(element, cb, thisArg, false);
+ }
+
+ function findDeepElementMatchingPredicate(element, predicate) {
+ let foundElement = undefined;
+ function matches(element) {
+ const match = predicate(element);
+ if (!match) {
+ return false;
+ }
+ foundElement = element;
+ return true;
+ }
+ iterateElementDeeply(element, matches);
+ return foundElement;
+ }
+
+ function findDeepElementsMatchingPredicate(element, predicate) {
+ const foundElements = [];
+ function matches(element) {
+ const match = predicate(element);
+ if (match) {
+ foundElements.push(element);
+ }
+ return false;
+ }
+ iterateElementDeeply(element, matches);
+ return foundElements;
+ }
+
+ function findDeepElementMatching(element, selector) {
+ return findDeepElementMatchingPredicate(element, function(element) {
+ return element.matches(selector);
+ });
+ }
+ function findDeepElementsMatching(element, selector) {
+ return findDeepElementsMatchingPredicate(element, function(element) {
+ return element.matches(selector);
+ });
+ }
+ function findDeepElementWithTextContent(element, re) {
+ return findDeepElementMatchingPredicate(element, function(element) {
+ if (element.children.length !== 0) return false;
+ return re.test(Polymer.dom(element).textContent);
+ });
+ }
+
+ return {
+ findDeepElementMatching,
+ findDeepElementsMatching,
+ findDeepElementMatchingPredicate,
+ findDeepElementsMatchingPredicate,
+ findDeepElementWithTextContent,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/deep_utils_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/deep_utils_test.html
new file mode 100644
index 00000000000..d9e1d49f556
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/deep_utils_test.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+
+<dom-module id='tr-ui-b-deep-utils-test-a'>
+ <template>
+ <div></div>
+ </template>
+</dom-module>
+<dom-module id='tr-ui-b-deep-utils-test-b'>
+ <template>
+ <div></div>
+ </template>
+</dom-module>
+<dom-module id='tr-ui-b-deep-utils-test-c'>
+ <template>
+ <tr-ui-b-deep-utils-test-b class='x'></tr-ui-b-deep-utils-test-b>
+ <tr-ui-b-deep-utils-test-a class='x'></tr-ui-b-deep-utils-test-a>
+ <tr-ui-b-deep-utils-test-a class='x'></tr-ui-b-deep-utils-test-a>
+ </template>
+</dom-module>
+<dom-module id='tr-ui-b-deep-utils-test-d'>
+ <template>
+ <tr-ui-b-deep-utils-test-c></tr-ui-b-deep-utils-test-c>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-deep-utils-test-a'
+});
+
+Polymer({
+ is: 'tr-ui-b-deep-utils-test-b'
+});
+
+Polymer({
+ is: 'tr-ui-b-deep-utils-test-c'
+});
+
+Polymer({
+ is: 'tr-ui-b-deep-utils-test-d'
+});
+
+tr.b.unittest.testSuite(function() {
+ test('testFindDeepElementMatching', function() {
+ const d = document.createElement('tr-ui-b-deep-utils-test-d');
+
+ const b = tr.ui.b.findDeepElementMatching(d, 'tr-ui-b-deep-utils-test-b.x');
+ assert.isDefined(b);
+ assert.strictEqual(b.tagName, 'TR-UI-B-DEEP-UTILS-TEST-B');
+ });
+
+ test('testFindDeepElementsMatching', function() {
+ const d = document.createElement('tr-ui-b-deep-utils-test-d');
+
+ const a = tr.ui.b.findDeepElementsMatching(
+ d, 'tr-ui-b-deep-utils-test-a.x');
+ assert.isDefined(a);
+ assert.strictEqual(a[0].tagName, 'TR-UI-B-DEEP-UTILS-TEST-A');
+ assert.strictEqual(a[1].tagName, 'TR-UI-B-DEEP-UTILS-TEST-A');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers.html b/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers.html
new file mode 100644
index 00000000000..adf7f10b34d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers.html
@@ -0,0 +1,390 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ function createSpan(opt_dictionary) {
+ let ownerDocument = document;
+ if (opt_dictionary && opt_dictionary.ownerDocument) {
+ ownerDocument = opt_dictionary.ownerDocument;
+ }
+ const spanEl = ownerDocument.createElement('span');
+ if (opt_dictionary) {
+ if (opt_dictionary.className) {
+ spanEl.className = opt_dictionary.className;
+ }
+ if (opt_dictionary.textContent) {
+ Polymer.dom(spanEl).textContent =
+ opt_dictionary.textContent;
+ }
+ if (opt_dictionary.tooltip) {
+ spanEl.title = opt_dictionary.tooltip;
+ }
+ if (opt_dictionary.parent) {
+ Polymer.dom(opt_dictionary.parent).appendChild(spanEl);
+ }
+ if (opt_dictionary.bold) {
+ spanEl.style.fontWeight = 'bold';
+ }
+ if (opt_dictionary.italic) {
+ spanEl.style.fontStyle = 'italic';
+ }
+ if (opt_dictionary.marginLeft) {
+ spanEl.style.marginLeft = opt_dictionary.marginLeft;
+ }
+ if (opt_dictionary.marginRight) {
+ spanEl.style.marginRight = opt_dictionary.marginRight;
+ }
+ if (opt_dictionary.backgroundColor) {
+ spanEl.style.backgroundColor = opt_dictionary.backgroundColor;
+ }
+ if (opt_dictionary.color) {
+ spanEl.style.color = opt_dictionary.color;
+ }
+ }
+ return spanEl;
+ }
+
+ function createLink(opt_args) {
+ let ownerDocument = document;
+ if (opt_args && opt_args.ownerDocument) {
+ ownerDocument = opt_args.ownerDocument;
+ }
+ const linkEl = ownerDocument.createElement('a');
+ if (opt_args) {
+ if (opt_args.href) linkEl.href = opt_args.href;
+ if (opt_args.tooltip) linkEl.title = opt_args.tooltip;
+ if (opt_args.color) linkEl.style.color = opt_args.color;
+ if (opt_args.bold) linkEl.style.fontWeight = 'bold';
+ if (opt_args.italic) linkEl.style.fontStyle = 'italic';
+ if (opt_args.className) linkEl.className = opt_args.className;
+ if (opt_args.parent) Polymer.dom(opt_args.parent).appendChild(linkEl);
+ if (opt_args.marginLeft) linkEl.style.marginLeft = opt_args.marginLeft;
+ if (opt_args.marginRight) linkEl.style.marginRight = opt_args.marginRight;
+ if (opt_args.backgroundColor) {
+ linkEl.style.backgroundColor = opt_args.backgroundColor;
+ }
+ if (opt_args.textContent) {
+ Polymer.dom(linkEl).textContent = opt_args.textContent;
+ }
+ }
+ return linkEl;
+ }
+
+ function createDiv(opt_dictionary) {
+ const divEl = document.createElement('div');
+ if (opt_dictionary) {
+ if (opt_dictionary.className) {
+ divEl.className = opt_dictionary.className;
+ }
+ if (opt_dictionary.parent) {
+ Polymer.dom(opt_dictionary.parent).appendChild(divEl);
+ }
+ if (opt_dictionary.textContent) {
+ Polymer.dom(divEl).textContent =
+ opt_dictionary.textContent;
+ }
+ if (opt_dictionary.maxWidth) {
+ divEl.style.maxWidth = opt_dictionary.maxWidth;
+ }
+ }
+ return divEl;
+ }
+
+ function createScopedStyle(styleContent) {
+ const styleEl = document.createElement('style');
+ styleEl.scoped = true;
+ Polymer.dom(styleEl).innerHTML = styleContent;
+ return styleEl;
+ }
+
+ function valuesEqual(a, b) {
+ if (a instanceof Array && b instanceof Array) {
+ return a.length === b.length && JSON.stringify(a) === JSON.stringify(b);
+ }
+ return a === b;
+ }
+
+ function createSelector(
+ targetEl, targetElProperty,
+ settingsKey, defaultValue,
+ items, opt_namespace) {
+ let defaultValueIndex;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ if (valuesEqual(item.value, defaultValue)) {
+ defaultValueIndex = i;
+ break;
+ }
+ }
+ if (defaultValueIndex === undefined) {
+ throw new Error('defaultValue must be in the items list');
+ }
+
+ const selectorEl = document.createElement('select');
+ selectorEl.addEventListener('change', onChange);
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ const optionEl = document.createElement('option');
+ Polymer.dom(optionEl).textContent = item.label;
+ optionEl.targetPropertyValue = item.value;
+ optionEl.item = item;
+ Polymer.dom(selectorEl).appendChild(optionEl);
+ }
+ function onChange(e) {
+ const value = selectorEl.selectedOptions[0].targetPropertyValue;
+ tr.b.Settings.set(settingsKey, value, opt_namespace);
+ targetEl[targetElProperty] = value;
+ }
+ const oldSetter = targetEl.__lookupSetter__('selectedIndex');
+ selectorEl.__defineGetter__('selectedValue', function(v) {
+ return selectorEl.children[selectorEl.selectedIndex].targetPropertyValue;
+ });
+ selectorEl.__defineGetter__('selectedItem', function(v) {
+ return selectorEl.children[selectorEl.selectedIndex].item;
+ });
+ selectorEl.__defineSetter__('selectedValue', function(v) {
+ for (let i = 0; i < selectorEl.children.length; i++) {
+ const value = selectorEl.children[i].targetPropertyValue;
+ if (valuesEqual(value, v)) {
+ const changed = selectorEl.selectedIndex !== i;
+ if (changed) {
+ selectorEl.selectedIndex = i;
+ onChange();
+ }
+ return;
+ }
+ }
+ throw new Error('Not a valid value');
+ });
+
+ const initialValue = tr.b.Settings.get(
+ settingsKey, defaultValue, opt_namespace);
+ let didSet = false;
+ for (let i = 0; i < selectorEl.children.length; i++) {
+ if (valuesEqual(selectorEl.children[i].targetPropertyValue,
+ initialValue)) {
+ didSet = true;
+ targetEl[targetElProperty] = initialValue;
+ selectorEl.selectedIndex = i;
+ break;
+ }
+ }
+ if (!didSet) {
+ selectorEl.selectedIndex = defaultValueIndex;
+ targetEl[targetElProperty] = defaultValue;
+ }
+
+ return selectorEl;
+ }
+
+ function createEditCategorySpan(optionGroupEl, targetEl) {
+ const spanEl = createSpan({className: 'edit-categories'});
+ Polymer.dom(spanEl).textContent = 'Edit categories';
+ Polymer.dom(spanEl).classList.add('labeled-option');
+
+ spanEl.addEventListener('click', function() {
+ targetEl.onClickEditCategories();
+ });
+ return spanEl;
+ }
+
+ function createOptionGroup(targetEl, targetElProperty,
+ settingsKey, defaultValue,
+ items) {
+ function onChange() {
+ let value = [];
+ if (this.value.length) {
+ value = this.value.split(',');
+ }
+ tr.b.Settings.set(settingsKey, value);
+ targetEl[targetElProperty] = value;
+ }
+
+ const optionGroupEl = createSpan({className: 'labeled-option-group'});
+ const initialValue = tr.b.Settings.get(settingsKey, defaultValue);
+ for (let i = 0; i < items.length; ++i) {
+ const item = items[i];
+ const id = 'category-preset-' + item.label.replace(/ /g, '-');
+
+ const radioEl = document.createElement('input');
+ radioEl.type = 'radio';
+ Polymer.dom(radioEl).setAttribute('id', id);
+ Polymer.dom(radioEl).setAttribute('name', 'category-presets-group');
+ Polymer.dom(radioEl).setAttribute('value', item.value);
+ radioEl.addEventListener('change', onChange.bind(radioEl, targetEl,
+ targetElProperty,
+ settingsKey));
+ if (valuesEqual(initialValue, item.value)) {
+ radioEl.checked = true;
+ }
+
+ const labelEl = document.createElement('label');
+ Polymer.dom(labelEl).textContent = item.label;
+ Polymer.dom(labelEl).setAttribute('for', id);
+
+ const spanEl = createSpan({className: 'labeled-option'});
+ Polymer.dom(spanEl).appendChild(radioEl);
+ Polymer.dom(spanEl).appendChild(labelEl);
+
+ spanEl.__defineSetter__('checked', function(opt_bool) {
+ const changed = radioEl.checked !== (!!opt_bool);
+ if (!changed) return;
+
+ radioEl.checked = !!opt_bool;
+ onChange();
+ });
+ spanEl.__defineGetter__('checked', function() {
+ return radioEl.checked;
+ });
+
+ Polymer.dom(optionGroupEl).appendChild(spanEl);
+ }
+ Polymer.dom(optionGroupEl).appendChild(
+ createEditCategorySpan(optionGroupEl, targetEl));
+ // Since this option group element is not yet added to the tree,
+ // querySelector will fail during updateEditCategoriesStatus_ call.
+ // Hence, creating the element with the 'expanded' classlist category
+ // added, if last selected value was 'Manual' selection.
+ if (!initialValue.length) {
+ Polymer.dom(optionGroupEl).classList.add('categories-expanded');
+ }
+ targetEl[targetElProperty] = initialValue;
+
+ return optionGroupEl;
+ }
+
+ let nextCheckboxId = 1;
+ function createCheckBox(targetEl, targetElProperty,
+ settingsKey, defaultValue,
+ label, opt_changeCb) {
+ const buttonEl = document.createElement('input');
+ buttonEl.type = 'checkbox';
+
+ let initialValue = defaultValue;
+ if (settingsKey !== undefined) {
+ initialValue = tr.b.Settings.get(settingsKey, defaultValue);
+ buttonEl.checked = !!initialValue;
+ }
+ if (targetEl) {
+ targetEl[targetElProperty] = initialValue;
+ }
+
+ function onChange() {
+ if (settingsKey !== undefined) {
+ tr.b.Settings.set(settingsKey, buttonEl.checked);
+ }
+ if (targetEl) {
+ targetEl[targetElProperty] = buttonEl.checked;
+ }
+ if (opt_changeCb) {
+ opt_changeCb.call();
+ }
+ }
+
+ buttonEl.addEventListener('change', onChange);
+
+ const id = '#checkbox-' + nextCheckboxId++;
+
+ const spanEl = createSpan();
+ spanEl.style.display = 'flex';
+ spanEl.style.whiteSpace = 'nowrap';
+ Polymer.dom(buttonEl).setAttribute('id', id);
+
+ const labelEl = document.createElement('label');
+ Polymer.dom(labelEl).textContent = label;
+ Polymer.dom(labelEl).setAttribute('for', id);
+ Polymer.dom(spanEl).appendChild(buttonEl);
+ Polymer.dom(spanEl).appendChild(labelEl);
+
+ spanEl.__defineSetter__('checked', function(opt_bool) {
+ const changed = buttonEl.checked !== (!!opt_bool);
+ if (!changed) return;
+
+ buttonEl.checked = !!opt_bool;
+ onChange();
+ });
+ spanEl.__defineGetter__('checked', function() {
+ return buttonEl.checked;
+ });
+
+ return spanEl;
+ }
+
+ /**
+ * @param {!string} label
+ * @param {function()=} opt_callback
+ * @param {*=} opt_this
+ */
+ function createButton(label, opt_callback, opt_this) {
+ const buttonEl = document.createElement('input');
+ buttonEl.type = 'button';
+ buttonEl.value = label;
+
+ function onClick() {
+ opt_callback.call(opt_this || buttonEl);
+ }
+
+ if (opt_callback) {
+ buttonEl.addEventListener('click', onClick);
+ }
+
+ return buttonEl;
+ }
+
+ function createTextInput(
+ targetEl, targetElProperty, settingsKey, defaultValue) {
+ const initialValue = tr.b.Settings.get(settingsKey, defaultValue);
+ const el = document.createElement('input');
+ el.type = 'text';
+ function onChange(e) {
+ tr.b.Settings.set(settingsKey, el.value);
+ targetEl[targetElProperty] = el.value;
+ }
+ el.addEventListener('input', onChange);
+ el.value = initialValue;
+ targetEl[targetElProperty] = initialValue;
+
+ return el;
+ }
+
+ function isElementAttachedToDocument(el) {
+ let cur = el;
+ while (Polymer.dom(cur).parentNode) {
+ cur = Polymer.dom(cur).parentNode;
+ }
+ return (cur === el.ownerDocument || cur.nodeName === '#document-fragment');
+ }
+
+ function asHTMLOrTextNode(value, opt_ownerDocument) {
+ if (value instanceof Node) {
+ return value;
+ }
+ const ownerDocument = opt_ownerDocument || document;
+ return ownerDocument.createTextNode(value);
+ }
+
+ return {
+ createSpan,
+ createLink,
+ createDiv,
+ createScopedStyle,
+ createSelector,
+ createOptionGroup,
+ createCheckBox,
+ createButton,
+ createTextInput,
+ isElementAttachedToDocument,
+ asHTMLOrTextNode,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html
new file mode 100644
index 00000000000..46313143710
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/dom_helpers_test.html
@@ -0,0 +1,169 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ test('simpleSpanAndDiv', function() {
+ const divEl = tr.ui.b.createDiv({
+ className: 'a-div-class', parent: document.body
+ });
+ const testText = 'some span text';
+ const spanEl = tr.ui.b.createSpan({
+ className: 'a-span-class',
+ textContent: testText,
+ parent: divEl
+ });
+ const eltInDocument = Polymer.dom(document)
+ .querySelector('.a-div-class>.a-span-class');
+ assert.strictEqual(Polymer.dom(eltInDocument).textContent, testText);
+ Polymer.dom(eltInDocument.parentElement).removeChild(eltInDocument);
+ });
+
+ test('createSpan_ownerDocument', function() {
+ const spanEl = tr.ui.b.createSpan({
+ className: 'a-span-class',
+ bold: true,
+ ownerDocument: THIS_DOC
+ });
+ assert.strictEqual(spanEl.ownerDocument, THIS_DOC);
+ });
+
+ test('createLink', function() {
+ const linkEl = tr.ui.b.createLink({
+ parent: document.body,
+ className: 'a-link-class',
+ textContent: 'Google',
+ href: 'http://www.google.com/'
+ });
+ const eltInDocument = Polymer.dom(document)
+ .querySelector('.a-link-class');
+ assert.strictEqual(Polymer.dom(eltInDocument).textContent, 'Google');
+ assert.strictEqual(eltInDocument.href, 'http://www.google.com/');
+ Polymer.dom(eltInDocument.parentElement).removeChild(eltInDocument);
+ });
+
+ test('checkboxFromDefaults', function() {
+ const target = {foo: undefined};
+ const cb = tr.ui.b.createCheckBox(
+ target, 'foo', 'myCheckBox', false, 'Foo');
+ assert.isFalse(target.foo);
+ });
+
+ test('checkboxFromSettings', function() {
+ tr.b.Settings.set('myCheckBox', true);
+ const target = {foo: undefined};
+ const cb = tr.ui.b.createCheckBox(
+ target, 'foo', 'myCheckBox', false, 'Foo');
+ assert.isTrue(target.foo);
+ });
+
+ test('checkboxChanged', function() {
+ const target = {foo: undefined};
+ const cb = tr.ui.b.createCheckBox(
+ target, 'foo', 'myCheckBox', false, 'Foo');
+ cb.checked = true;
+
+ assert.isTrue(tr.b.Settings.get('myCheckBox', undefined));
+ assert.isTrue(target.foo);
+ });
+
+ test('selectorSettingsAlreaySet', function() {
+ tr.b.Settings.set('myScale', 0.25);
+
+ const target = {
+ scale: 314
+ };
+ const sel = tr.ui.b.createSelector(
+ target, 'scale',
+ 'myScale', 0.375,
+ [{label: '6.25%', value: 0.0625},
+ {label: '12.5%', value: 0.125},
+ {label: '25%', value: 0.25},
+ {label: '37.5%', value: 0.375},
+ {label: '50%', value: 0.5},
+ {label: '75%', value: 0.75},
+ {label: '100%', value: 1},
+ {label: '200%', value: 2}
+ ]);
+ assert.strictEqual(target.scale, 0.25);
+ assert.strictEqual(sel.selectedIndex, 2);
+ });
+
+ test('selectorSettingsDefault', function() {
+ const target = {
+ scale: 314
+ };
+ const sel = tr.ui.b.createSelector(
+ target, 'scale',
+ 'myScale', 0.375,
+ [{label: '6.25%', value: 0.0625},
+ {label: '12.5%', value: 0.125},
+ {label: '25%', value: 0.25},
+ {label: '37.5%', value: 0.375},
+ {label: '50%', value: 0.5},
+ {label: '75%', value: 0.75},
+ {label: '100%', value: 1},
+ {label: '200%', value: 2}
+ ]);
+ assert.strictEqual(target.scale, 0.375);
+ assert.strictEqual(sel.selectedIndex, 3);
+ });
+
+ test('selectorSettingsChanged', function() {
+ const target = {
+ scale: 314
+ };
+ const sel = tr.ui.b.createSelector(
+ target, 'scale',
+ 'myScale', 0.375,
+ [{label: '6.25%', value: 0.0625},
+ {label: '12.5%', value: 0.125},
+ {label: '25%', value: 0.25},
+ {label: '37.5%', value: 0.375},
+ {label: '50%', value: 0.5},
+ {label: '75%', value: 0.75},
+ {label: '100%', value: 1},
+ {label: '200%', value: 2}
+ ]);
+ assert.strictEqual(sel.selectedValue, 0.375);
+ sel.selectedValue = 0.75;
+ assert.strictEqual(target.scale, 0.75);
+ assert.strictEqual(sel.selectedValue, 0.75);
+ assert.strictEqual(undefined), 0.75, tr.b.Settings.get('myScale');
+ });
+
+ test('asHTMLOrTextNode_string', function() {
+ // Default owner document.
+ let node = tr.ui.b.asHTMLOrTextNode('Hello, World!');
+ assert.instanceOf(node, Node);
+ assert.strictEqual(Polymer.dom(node).textContent, 'Hello, World!');
+ assert.strictEqual(node.ownerDocument, document);
+
+ // Custom owner document.
+ node = tr.ui.b.asHTMLOrTextNode('Bye, World!', THIS_DOC);
+ assert.instanceOf(node, Node);
+ assert.strictEqual(Polymer.dom(node).textContent, 'Bye, World!');
+ assert.strictEqual(node.ownerDocument, THIS_DOC);
+ });
+
+ test('asHTMLOrTextNode_node', function() {
+ // Node object. Owner document should NOT be modified.
+ let node = document.createTextNode('Hi', THIS_DOC);
+ assert.strictEqual(tr.ui.b.asHTMLOrTextNode(node), node);
+ assert.strictEqual(node.ownerDocument, document);
+
+ // HTMLElement object. Owner document should NOT be modified.
+ node = THIS_DOC.createElement('div');
+ assert.strictEqual(tr.ui.b.asHTMLOrTextNode(node), node);
+ assert.strictEqual(node.ownerDocument, THIS_DOC);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/drag_handle.html b/chromium/third_party/catapult/tracing/tracing/ui/base/drag_handle.html
new file mode 100644
index 00000000000..614c3c2fb8f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/drag_handle.html
@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<dom-module id="tr-ui-b-drag-handle">
+ <template>
+ <style>
+ :host {
+ -webkit-user-select: none;
+ box-sizing: border-box;
+ display: block;
+ }
+
+ :host(.horizontal-drag-handle) {
+ background-image: -webkit-gradient(linear,
+ 0 0, 0 100%,
+ from(#E5E5E5),
+ to(#D1D1D1));
+ border-bottom: 1px solid #8e8e8e;
+ border-top: 1px solid white;
+ cursor: ns-resize;
+ flex: 0 0 auto;
+ height: 7px;
+ position: relative;
+ }
+
+ :host(.vertical-drag-handle) {
+ background-image: -webkit-gradient(linear,
+ 0 0, 100% 0,
+ from(#E5E5E5),
+ to(#D1D1D1));
+ border-left: 1px solid white;
+ border-right: 1px solid #8e8e8e;
+ cursor: ew-resize;
+ flex: 0 0 auto;
+ position: relative;
+ width: 7px;
+ }
+ </style>
+ <div></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-drag-handle',
+
+ created() {
+ this.lastMousePos_ = 0;
+ this.onMouseMove_ = this.onMouseMove_.bind(this);
+ this.onMouseUp_ = this.onMouseUp_.bind(this);
+ this.addEventListener('mousedown', this.onMouseDown_);
+ this.target_ = undefined;
+ this.horizontal = true;
+ this.observer_ = new WebKitMutationObserver(
+ this.didTargetMutate_.bind(this));
+ this.targetSizesByModeKey_ = {};
+ this.currentDraggingSize_ = undefined;
+ },
+
+ get modeKey_() {
+ return this.target_.className === '' ? '.' : this.target_.className;
+ },
+
+ get target() {
+ return this.target_;
+ },
+
+ set target(target) {
+ this.observer_.disconnect();
+ this.target_ = target;
+ if (!this.target_) return;
+ this.observer_.observe(this.target_, {
+ attributes: true,
+ attributeFilter: ['class']
+ });
+ },
+
+ get horizontal() {
+ return this.horizontal_;
+ },
+
+ set horizontal(h) {
+ this.horizontal_ = h;
+ if (this.horizontal_) {
+ this.className = 'horizontal-drag-handle';
+ } else {
+ this.className = 'vertical-drag-handle';
+ }
+ },
+
+ get vertical() {
+ return !this.horizontal_;
+ },
+
+ set vertical(v) {
+ this.horizontal = !v;
+ },
+
+ forceMutationObserverFlush_() {
+ const records = this.observer_.takeRecords();
+ if (records.length) {
+ this.didTargetMutate_(records);
+ }
+ },
+
+ didTargetMutate_(e) {
+ const modeSize = this.targetSizesByModeKey_[this.modeKey_];
+ if (modeSize !== undefined) {
+ this.setTargetSize_(modeSize);
+ return;
+ }
+
+ // If we hadn't previously sized the target, then just remove any manual
+ // sizing that we applied.
+ this.target_.style[this.targetStyleKey_] = '';
+ },
+
+ get targetStyleKey_() {
+ return this.horizontal_ ? 'height' : 'width';
+ },
+
+ getTargetSize_() {
+ // Get the actual size, which may be different from the expected size
+ // because of size constraints (e.g. min-width) etc.
+ const size =
+ parseInt(window.getComputedStyle(this.target_)[this.targetStyleKey_]);
+ this.targetSizesByModeKey_[this.modeKey_] = size;
+ return size;
+ },
+
+ setTargetSize_(s) {
+ this.target_.style[this.targetStyleKey_] = s + 'px';
+ this.targetSizesByModeKey_[this.modeKey_] = this.getTargetSize_();
+ tr.b.dispatchSimpleEvent(this, 'drag-handle-resize', true, false);
+ },
+
+ applyDelta_(delta) {
+ // Apply new size to the target.
+ if (this.target_ === this.nextElementSibling) {
+ this.currentDraggingSize_ += delta;
+ } else {
+ this.currentDraggingSize_ -= delta;
+ }
+ this.setTargetSize_(this.currentDraggingSize_);
+ },
+
+ onMouseMove_(e) {
+ // Compute the difference in height position.
+ const curMousePos = this.horizontal_ ? e.clientY : e.clientX;
+ const delta = this.lastMousePos_ - curMousePos;
+
+ this.applyDelta_(delta);
+
+ this.lastMousePos_ = curMousePos;
+ e.preventDefault();
+ return true;
+ },
+
+ onMouseDown_(e) {
+ if (!this.target_) return;
+ this.forceMutationObserverFlush_();
+ // Start with the current actual size.
+ this.currentDraggingSize_ = this.getTargetSize_();
+ this.lastMousePos_ = this.horizontal_ ? e.clientY : e.clientX;
+ document.addEventListener('mousemove', this.onMouseMove_);
+ document.addEventListener('mouseup', this.onMouseUp_);
+ e.preventDefault();
+ return true;
+ },
+
+ onMouseUp_(e) {
+ document.removeEventListener('mousemove', this.onMouseMove_);
+ document.removeEventListener('mouseup', this.onMouseUp_);
+ e.preventDefault();
+ this.currentDraggingSize_ = undefined;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/drag_handle_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/drag_handle_test.html
new file mode 100644
index 00000000000..9faa91fce81
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/drag_handle_test.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const createDragHandle = function() {
+ const el = document.createElement('div');
+ el.style.border = '1px solid black';
+ el.style.width = '200px';
+ el.style.height = '200px';
+ el.style.display = 'flex';
+ el.style.flexDirection = 'column';
+
+ const upperEl = document.createElement('div');
+ upperEl.style.flex = '1 1 auto';
+ upperEl.style.minHeight = '0';
+
+ const lowerEl = document.createElement('div');
+ lowerEl.style.height = '100px';
+ lowerEl.style.minHeight = '50px';
+
+ const dragHandle = document.createElement('tr-ui-b-drag-handle');
+ dragHandle.target = lowerEl;
+
+ Polymer.dom(el).appendChild(upperEl);
+ Polymer.dom(el).appendChild(dragHandle);
+ Polymer.dom(el).appendChild(lowerEl);
+ el.upperEl = upperEl;
+ el.dragHandle = dragHandle;
+ el.lowerEl = lowerEl;
+
+ el.getLowerElHeight = function() {
+ return parseInt(getComputedStyle(this.lowerEl).height);
+ };
+ return el;
+ };
+
+ test('instantiate', function() {
+ this.addHTMLOutput(createDragHandle());
+ });
+
+ test('dragWithoutConstraint', function() {
+ const el = createDragHandle();
+ this.addHTMLOutput(el);
+
+ const dragHandle = el.dragHandle;
+ assert.strictEqual(el.getLowerElHeight(), 100);
+ dragHandle.onMouseDown_({clientX: 0, clientY: 0, preventDefault() {}});
+ dragHandle.onMouseMove_({clientX: 0, clientY: -10, preventDefault() {}});
+ assert.strictEqual(el.getLowerElHeight(), 110);
+ dragHandle.onMouseUp_({preventDefault() {}});
+ });
+
+ test('dragWithConstraint', function() {
+ const el = createDragHandle();
+ this.addHTMLOutput(el);
+
+ const dragHandle = el.dragHandle;
+ assert.strictEqual(el.getLowerElHeight(), 100);
+ dragHandle.onMouseDown_({clientX: 0, clientY: 0, preventDefault() {}});
+ dragHandle.onMouseMove_({clientX: 0, clientY: 60, preventDefault() {}});
+ // The actual size is constrained by minHeight.
+ assert.strictEqual(el.getLowerElHeight(), 50);
+ dragHandle.onMouseUp_({preventDefault() {}});
+
+ // Drag again. Should based on the actual size.
+ dragHandle.onMouseDown_({clientX: 0, clientY: 0, preventDefault() {}});
+ dragHandle.onMouseMove_({clientX: 0, clientY: -10, preventDefault() {}});
+ assert.strictEqual(el.getLowerElHeight(), 60);
+ dragHandle.onMouseUp_({preventDefault() {}});
+ });
+
+ test('classNameMutation', function() {
+ const el = createDragHandle();
+
+ const styleEl = document.createElement('style');
+ Polymer.dom(styleEl).textContent =
+ '.mode-a { height: 100px; } .mode-b { height: 50px; }';
+ Polymer.dom(document.head).appendChild(styleEl);
+
+ this.addHTMLOutput(el);
+
+ try {
+ const dragHandle = el.dragHandle;
+ const mouseDown = {clientX: 0, clientY: 0, preventDefault() {}};
+ const mouseMove = {clientX: 0, clientY: -10, preventDefault() {}};
+ const mouseUp = {preventDefault() {}};
+
+ el.lowerEl.className = 'mode-a';
+ assert.strictEqual(el.getLowerElHeight(), 100);
+ dragHandle.onMouseDown_(mouseDown);
+ dragHandle.onMouseMove_(mouseMove);
+ assert.strictEqual(el.getLowerElHeight(), 110);
+ dragHandle.onMouseUp_(mouseUp);
+
+ // Change the class, which should restore the layout
+ // to the default sizing for mode-b
+ el.lowerEl.className = 'mode-b';
+ dragHandle.forceMutationObserverFlush_();
+ assert.strictEqual(el.getLowerElHeight(), 50);
+
+ dragHandle.onMouseDown_(mouseDown);
+ dragHandle.onMouseMove_(mouseMove);
+ assert.strictEqual(el.getLowerElHeight(), 60);
+ dragHandle.onMouseUp_(mouseUp);
+
+ // Restore the class-a, which should restore the layout
+ // to sizing when we were changed.
+ el.lowerEl.className = 'mode-a';
+ dragHandle.forceMutationObserverFlush_();
+ assert.strictEqual(el.getLowerElHeight(), 110);
+
+ dragHandle.onMouseDown_(mouseDown);
+ dragHandle.onMouseMove_(mouseMove);
+ assert.strictEqual(el.getLowerElHeight(), 120);
+ dragHandle.onMouseUp_(mouseUp);
+ } finally {
+ Polymer.dom(document.head).removeChild(styleEl);
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/draw_helpers.html b/chromium/third_party/catapult/tracing/tracing/ui/base/draw_helpers.html
new file mode 100644
index 00000000000..449f3576274
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/draw_helpers.html
@@ -0,0 +1,415 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/elided_cache.html">
+<link rel="import" href="/tracing/ui/base/event_presenter.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides various helper methods for drawing to a provided
+ * canvas.
+ */
+tr.exportTo('tr.ui.b', function() {
+ const elidedTitleCache = new tr.ui.b.ElidedTitleCache();
+ const ColorScheme = tr.b.ColorScheme;
+ const colorsAsStrings = ColorScheme.colorsAsStrings;
+
+ const EventPresenter = tr.ui.b.EventPresenter;
+ const blackColorId = ColorScheme.getColorIdForReservedName('black');
+
+ /**
+ * This value is used to allow for consistent style UI elements.
+ * Thread time visualisation uses a smaller rectangle that has this height.
+ * @const
+ */
+ const THIN_SLICE_HEIGHT = 4;
+
+ /**
+ * This value is used to for performance considerations when drawing large
+ * zoomed out traces that feature cpu time in the slices. If the waiting
+ * width is less than the threshold, we only draw the rectangle as a solid.
+ * @const
+ */
+ const SLICE_WAITING_WIDTH_DRAW_THRESHOLD = 3;
+
+ /**
+ * If the slice has mostly been waiting to be scheduled on the cpu, the
+ * wall clock will be far greater than the cpu clock. Draw the slice
+ * only as an idle slice, if the active width is not thicker than the
+ * threshold.
+ * @const
+ */
+ const SLICE_ACTIVE_WIDTH_DRAW_THRESHOLD = 1;
+
+ /**
+ * Should we elide text on trace labels?
+ * Without eliding, text that is too wide isn't drawn at all.
+ * Disable if you feel this causes a performance problem.
+ * This is a default value that can be overridden in tracks for testing.
+ * @const
+ */
+ const SHOULD_ELIDE_TEXT = true;
+
+ /**
+ * Draw the define line into |ctx|.
+ *
+ * @param {Context} ctx The context to draw into.
+ * @param {float} x1 The start x position of the line.
+ * @param {float} y1 The start y position of the line.
+ * @param {float} x2 The end x position of the line.
+ * @param {float} y2 The end y position of the line.
+ */
+ function drawLine(ctx, x1, y1, x2, y2) {
+ ctx.moveTo(x1, y1);
+ ctx.lineTo(x2, y2);
+ }
+
+ /**
+ * Draw the defined triangle into |ctx|.
+ *
+ * @param {Context} ctx The context to draw into.
+ * @param {float} x1 The first corner x.
+ * @param {float} y1 The first corner y.
+ * @param {float} x2 The second corner x.
+ * @param {float} y2 The second corner y.
+ * @param {float} x3 The third corner x.
+ * @param {float} y3 The third corner y.
+ */
+ function drawTriangle(ctx, x1, y1, x2, y2, x3, y3) {
+ ctx.beginPath();
+ ctx.moveTo(x1, y1);
+ ctx.lineTo(x2, y2);
+ ctx.lineTo(x3, y3);
+ ctx.closePath();
+ }
+
+ /**
+ * Draw an arrow into |ctx|.
+ *
+ * @param {Context} ctx The context to draw into.
+ * @param {float} x1 The shaft x.
+ * @param {float} y1 The shaft y.
+ * @param {float} x2 The head x.
+ * @param {float} y2 The head y.
+ * @param {float} arrowLength The length of the head.
+ * @param {float} arrowWidth The width of the head.
+ */
+ function drawArrow(ctx, x1, y1, x2, y2, arrowLength, arrowWidth) {
+ const dx = x2 - x1;
+ const dy = y2 - y1;
+ const len = Math.sqrt(dx * dx + dy * dy);
+ const perc = (len - arrowLength) / len;
+ const bx = x1 + perc * dx;
+ const by = y1 + perc * dy;
+ const ux = dx / len;
+ const uy = dy / len;
+ const ax = uy * arrowWidth;
+ const ay = -ux * arrowWidth;
+
+ ctx.beginPath();
+ drawLine(ctx, x1, y1, x2, y2);
+ ctx.stroke();
+
+ drawTriangle(ctx,
+ bx + ax, by + ay,
+ x2, y2,
+ bx - ax, by - ay);
+ ctx.fill();
+ }
+
+ /**
+ * Draw the provided slices to the screen.
+ *
+ * Each of the elements in |slices| must provide the follow methods:
+ * * start
+ * * duration
+ * * colorId
+ * * selected
+ *
+ * @param {Context} ctx The canvas context.
+ * @param {TimelineDrawTransform} dt The draw transform.
+ * @param {float} viewLWorld The left most point of the world viewport.
+ * @param {float} viewRWorld The right most point of the world viewport.
+ * @param {float} viewHeight The height of the viewport.
+ * @param {Array} slices The slices to draw.
+ * @param {bool} async Whether the slices are drawn with async style.
+ */
+ function drawSlices(ctx, dt, viewLWorld, viewRWorld, viewHeight, slices,
+ async) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ const height = viewHeight * pixelRatio;
+ const viewL = dt.xWorldToView(viewLWorld);
+ const viewR = dt.xWorldToView(viewRWorld);
+
+ let darkRectHeight = THIN_SLICE_HEIGHT * pixelRatio;
+
+ // Not enough space for both colors, use light color only.
+ if (height < darkRectHeight) {
+ darkRectHeight = 0;
+ }
+
+ const lightRectHeight = height - darkRectHeight;
+
+ ctx.save();
+ const rect = new tr.ui.b.FastRectRenderer(
+ ctx, viewL, viewR, 2, 2, colorsAsStrings);
+ rect.setYandH(0, height);
+
+ const lowSlice = tr.b.findLowIndexInSortedArray(
+ slices,
+ function(slice) { return slice.start + slice.duration; },
+ viewLWorld);
+
+ let hadTopLevel = false;
+
+ for (let i = lowSlice; i < slices.length; ++i) {
+ const slice = slices[i];
+ const x = slice.start;
+ if (x > viewRWorld) break;
+
+ const xView = dt.xWorldToView(x);
+ let wView = 1;
+ if (slice.duration > 0) {
+ const w = Math.max(slice.duration, 0.000001);
+ wView = Math.max(dt.xWorldVectorToView(w), 1);
+ }
+
+ const colorId = EventPresenter.getSliceColorId(slice);
+ const alpha = EventPresenter.getSliceAlpha(slice, async);
+ const lightAlpha = alpha * 0.70;
+
+ if (async && slice.isTopLevel) {
+ rect.setYandH(3, height - 3);
+ hadTopLevel = true;
+ } else {
+ rect.setYandH(0, height);
+ }
+
+ // If cpuDuration is available, draw rectangles proportional to the
+ // amount of cpu time taken.
+ if (!slice.cpuDuration) {
+ // No cpuDuration available, draw using only one alpha.
+ rect.fillRect(xView, wView, colorId, alpha);
+ continue;
+ }
+
+ let activeWidth = wView * (slice.cpuDuration / slice.duration);
+ let waitingWidth = wView - activeWidth;
+
+ // Check if we have enough screen space to draw the whole slice, with
+ // both color tones.
+ //
+ // Truncate the activeWidth to 0 if it is less than 'threshold' pixels.
+ if (activeWidth < SLICE_ACTIVE_WIDTH_DRAW_THRESHOLD) {
+ activeWidth = 0;
+ waitingWidth = wView;
+ }
+
+ // Truncate the waitingWidth to 0 if it is less than 'threshold' pixels.
+ if (waitingWidth < SLICE_WAITING_WIDTH_DRAW_THRESHOLD) {
+ activeWidth = wView;
+ waitingWidth = 0;
+ }
+
+ // We now draw the two rectangles making up the event slice.
+ // NOTE: The if statements are necessary for performance considerations.
+ // We do not want to force draws, if the width of the rectangle is 0.
+ //
+ // First draw the solid color, representing the 'active' part.
+ if (activeWidth > 0) {
+ rect.fillRect(xView, activeWidth, colorId, alpha);
+ }
+
+ // Next draw the two toned 'idle' part.
+ // NOTE: We subtract 1 from the left-hand edge and draw one extra pixel to
+ // prevent drawing artifacts. Without this, the two parts of the slice
+ // ('active' and 'idle') may appear split apart.
+ if (waitingWidth > 0) {
+ // First draw the light toned top part.
+ rect.setYandH(0, lightRectHeight);
+ rect.fillRect(xView + activeWidth - 1,
+ waitingWidth + 1, colorId, lightAlpha);
+ // Then the solid bottom half.
+ rect.setYandH(lightRectHeight, darkRectHeight);
+ rect.fillRect(xView + activeWidth - 1,
+ waitingWidth + 1, colorId, alpha);
+ // Reset for the next slice.
+ rect.setYandH(0, height);
+ }
+ }
+ rect.flush();
+
+ if (async && hadTopLevel) {
+ // Draw a top border over async slices in order to visually separate
+ // them from events above it.
+ // See https://github.com/google/trace-viewer/issues/725.
+ rect.setYandH(2, 1);
+ for (let i = lowSlice; i < slices.length; ++i) {
+ const slice = slices[i];
+ const x = slice.start;
+ if (x > viewRWorld) break;
+
+ if (!slice.isTopLevel) continue;
+
+ const xView = dt.xWorldToView(x);
+ let wView = 1;
+ if (slice.duration > 0) {
+ const w = Math.max(slice.duration, 0.000001);
+ wView = Math.max(dt.xWorldVectorToView(w), 1);
+ }
+
+ rect.fillRect(xView, wView, blackColorId, 0.7);
+ }
+ rect.flush();
+ }
+
+ ctx.restore();
+ }
+
+ /**
+ * Draw the provided instant slices as lines to the screen.
+ *
+ * Each of the elements in |slices| must provide the follow methods:
+ * * start
+ * * duration with value of 0.
+ * * colorId
+ * * selected
+ *
+ * @param {Context} ctx The canvas context.
+ * @param {TimelineDrawTransform} dt The draw transform.
+ * @param {float} viewLWorld The left most point of the world viewport.
+ * @param {float} viewRWorld The right most point of the world viewport.
+ * @param {float} viewHeight The height of the viewport.
+ * @param {Array} slices The slices to draw.
+ * @param {Numer} lineWidthInPixels The width of the lines.
+ */
+ function drawInstantSlicesAsLines(
+ ctx, dt, viewLWorld, viewRWorld, viewHeight, slices, lineWidthInPixels) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ const height = viewHeight * pixelRatio;
+
+ ctx.save();
+ ctx.lineWidth = lineWidthInPixels * pixelRatio;
+
+ const lowSlice = tr.b.findLowIndexInSortedArray(
+ slices,
+ function(slice) { return slice.start; },
+ viewLWorld);
+
+ for (let i = lowSlice; i < slices.length; ++i) {
+ const slice = slices[i];
+ const x = slice.start;
+ if (x > viewRWorld) break;
+
+ ctx.strokeStyle = EventPresenter.getInstantSliceColor(slice);
+
+ const xView = dt.xWorldToView(x);
+
+ ctx.beginPath();
+ ctx.moveTo(xView, 0);
+ ctx.lineTo(xView, height);
+ ctx.stroke();
+ }
+ ctx.restore();
+ }
+
+ /**
+ * Draws the labels for the given slices.
+ *
+ * The |slices| array must contain objects with the following API:
+ * * start
+ * * duration
+ * * title
+ * * didNotFinish (optional)
+ *
+ * @param {Context} ctx The graphics context.
+ * @param {TimelineDrawTransform} dt The draw transform.
+ * @param {float} viewLWorld The left most point of the world viewport.
+ * @param {float} viewRWorld The right most point of the world viewport.
+ * @param {Array} slices The slices to label.
+ * @param {bool} async Whether the slice labels are drawn with async style.
+ * @param {float} fontSize The font size.
+ * @param {float} yOffset The font offset.
+ */
+ function drawLabels(ctx, dt, viewLWorld, viewRWorld, slices, async,
+ fontSize, yOffset) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ const pixWidth = dt.xViewVectorToWorld(1);
+
+ ctx.save();
+
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'top';
+ ctx.font = (fontSize * pixelRatio) + 'px sans-serif';
+
+ if (async) {
+ ctx.font = 'italic ' + ctx.font;
+ }
+
+ const cY = yOffset * pixelRatio;
+
+ const lowSlice = tr.b.findLowIndexInSortedArray(
+ slices,
+ function(slice) { return slice.start + slice.duration; },
+ viewLWorld);
+
+ // Don't render text until it is 20px wide
+ const quickDiscardThreshold = pixWidth * 20;
+ for (let i = lowSlice; i < slices.length; ++i) {
+ const slice = slices[i];
+ if (slice.start > viewRWorld) break;
+
+ if (slice.duration <= quickDiscardThreshold) continue;
+
+ // Clip slice boundaries to viewport.
+ const xLeftClipped = Math.max(slice.start, viewLWorld);
+ const xRightClipped = Math.min(slice.start + slice.duration, viewRWorld);
+ const visibleWidth = xRightClipped - xLeftClipped;
+
+ const title = slice.title +
+ (slice.didNotFinish ? ' (Did Not Finish)' : '');
+
+ let drawnTitle = title;
+ let drawnWidth = elidedTitleCache.labelWidth(ctx, drawnTitle);
+ const fullLabelWidth = elidedTitleCache.labelWidthWorld(
+ ctx, drawnTitle, pixWidth);
+ if (SHOULD_ELIDE_TEXT && fullLabelWidth > visibleWidth) {
+ const elidedValues = elidedTitleCache.get(
+ ctx, pixWidth,
+ drawnTitle, drawnWidth,
+ visibleWidth);
+ drawnTitle = elidedValues.string;
+ drawnWidth = elidedValues.width;
+ }
+
+ if (drawnWidth * pixWidth < visibleWidth) {
+ ctx.fillStyle = EventPresenter.getTextColor(slice);
+ const cX = dt.xWorldToView((xLeftClipped + xRightClipped) / 2);
+ ctx.fillText(drawnTitle, cX, cY, drawnWidth);
+ }
+ }
+ ctx.restore();
+ }
+
+ return {
+ drawSlices,
+ drawInstantSlicesAsLines,
+ drawLabels,
+
+ drawLine,
+ drawTriangle,
+ drawArrow,
+
+ elidedTitleCache_: elidedTitleCache,
+
+ THIN_SLICE_HEIGHT,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown.html b/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown.html
new file mode 100644
index 00000000000..0c37e9910b7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<dom-module id='tr-ui-b-dropdown'>
+ <template>
+ <style>
+ button {
+ @apply --dropdown-button;
+ }
+ button.open {
+ @apply --dropdown-button-open;
+ }
+ dialog {
+ position: absolute;
+ margin: 0;
+ padding: 1em;
+ border: 1px solid darkgrey;
+ @apply --dropdown-dialog;
+ }
+ </style>
+
+ <button id="button" on-tap="open">[[label]]</button>
+
+ <dialog id="dialog" on-tap="onDialogTap_" on-cancel="close">
+ <slot></slot>
+ </dialog>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.ui.b', function() {
+ Polymer({
+ is: 'tr-ui-b-dropdown',
+
+ properties: {
+ label: {
+ type: String,
+ value: '',
+ },
+ },
+
+ open() {
+ if (this.isOpen) return;
+
+ Polymer.dom(this.$.button).classList.add('open');
+ const buttonRect = this.$.button.getBoundingClientRect();
+ this.$.dialog.style.top = buttonRect.bottom - 1 + 'px';
+ this.$.dialog.style.left = buttonRect.left + 'px';
+ this.$.dialog.showModal();
+
+ const dialogRect = this.$.dialog.getBoundingClientRect();
+ if (dialogRect.right > window.innerWidth) {
+ // If the dialog's right edge falls past the right edge of the window,
+ // then move the dialog to the left so that its right edge lines up with
+ // the button's right edge, but not so far left that its left edge falls
+ // past the left edge of the window.
+ this.$.dialog.style.left = Math.max(0, buttonRect.right -
+ dialogRect.width) + 'px';
+ }
+ },
+
+ onDialogTap_(event) {
+ // Clicking on elements inside the dialog should never close it.
+ if (event.detail.sourceEvent.srcElement !== this.$.dialog) return;
+
+ // Close the dialog when the user clicks on the backdrop outside the
+ // dialog, which sends click events to the dialog even though the
+ // coordinates are outside the dialog.
+ const dialogRect = this.$.dialog.getBoundingClientRect();
+ let inside = true;
+ inside &= event.detail.x >= dialogRect.left;
+ inside &= event.detail.x < dialogRect.right;
+ inside &= event.detail.y >= dialogRect.top;
+ inside &= event.detail.y < dialogRect.bottom;
+ if (inside) return;
+
+ event.preventDefault();
+ this.close();
+ },
+
+ close() {
+ if (!this.isOpen) return;
+ this.$.dialog.close();
+ Polymer.dom(this.$.button).classList.remove('open');
+ this.$.button.focus();
+ },
+
+ get isOpen() {
+ return this.$.button.classList.contains('open');
+ }
+ });
+
+ return {
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html
new file mode 100644
index 00000000000..bdc118a4d09
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/dropdown_test.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/dropdown.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function dispatchClick(elem, x, y) {
+ const clickEvent = document.createEvent('MouseEvents');
+ const bubbles = true;
+ const cancelable = false;
+ const button = 0;
+ const ctrlKey = false;
+ const altKey = false;
+ const shiftKey = false;
+ const metaKey = false;
+ clickEvent.initMouseEvent(
+ 'click', bubbles, cancelable, document.defaultView, button, x, y, x,
+ y, ctrlKey, altKey, shiftKey, metaKey, button, elem);
+ elem.dispatchEvent(clickEvent);
+ }
+
+ test('basic', function() {
+ const dd = document.createElement('tr-ui-b-dropdown');
+ dd.style.marginLeft = '50px';
+ dd.style.width = '50px';
+ dd.label = 'Settings';
+
+ const textDiv = tr.ui.b.createDiv({textContent: 'text'});
+ Polymer.dom(dd).appendChild(textDiv);
+ const target = {};
+ const checkbox = tr.ui.b.createCheckBox(
+ target, 'enabled', undefined, true, 'checkbox');
+ const actualCheckbox = checkbox.querySelector('input');
+ Polymer.dom(dd).appendChild(checkbox);
+
+ const container = tr.ui.b.createDiv();
+ container.style.height = '100px';
+ Polymer.dom(container).appendChild(dd);
+ Polymer.dom(container).appendChild(
+ tr.ui.b.createDiv({textContent: 'some text'}));
+ this.addHTMLOutput(container);
+
+ dd.open();
+ assert.isTrue(dd.isOpen);
+
+ dd.close();
+ assert.isFalse(dd.isOpen);
+
+ dd.open();
+ assert.isTrue(dd.isOpen);
+
+ // Dispatching a click event at contents of the dropdown should never close
+ // it, even if it is outside of the dropdown, which can happen if the user
+ // presses the spacebar while the checkbox is focused.
+ const actualCheckboxRect = actualCheckbox.getBoundingClientRect();
+ dispatchClick(
+ actualCheckbox, actualCheckboxRect.left, actualCheckboxRect.top);
+ assert.isTrue(dd.isOpen);
+ dispatchClick(actualCheckbox, 0, 0);
+ assert.isTrue(dd.isOpen);
+
+ const textDivRect = textDiv.getBoundingClientRect();
+ dispatchClick(textDiv, textDivRect.left, textDivRect.top);
+ assert.isTrue(dd.isOpen);
+ dispatchClick(textDiv, 0, 0);
+ assert.isTrue(dd.isOpen);
+
+ // Clicking outside the dropdown should close it.
+ dispatchClick(dd.$.dialog, 0, 0);
+ assert.isFalse(dd.isOpen);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/elided_cache.html b/chromium/third_party/catapult/tracing/tracing/ui/base/elided_cache.html
new file mode 100644
index 00000000000..85e6cf681f6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/elided_cache.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides a caching layer for elided text values.
+ */
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * Cache for elided strings.
+ * Moved from the ElidedTitleCache protoype to a "global" for speed
+ * (variable reference is 100x faster).
+ * key: String we wish to elide.
+ * value: Another dict whose key is width
+ * and value is an ElidedStringWidthPair.
+ */
+ const elidedTitleCacheDict = new Map();
+ const elidedTitleCache = new ElidedTitleCache();
+
+ /**
+ * A cache for elided strings.
+ * @constructor
+ */
+ function ElidedTitleCache() {
+ // TODO(jrg): possibly obsoleted with the elided string cache.
+ // Consider removing.
+ this.textWidthMap = new Map();
+ }
+
+ ElidedTitleCache.prototype = {
+ /**
+ * Return elided text.
+ *
+ * @param {ctx} Context The graphics context.
+ * @param {pixWidth} Pixel width.
+ * @param {title} Original title text.
+ * @param {width} Drawn width in world coords.
+ * @param {sliceDuration} Where the title must fit (in world coords).
+ * @return {ElidedStringWidthPair} Elided string and width.
+ */
+ get(ctx, pixWidth, title, width, sliceDuration) {
+ let elidedDict = elidedTitleCacheDict.get(title);
+ if (!elidedDict) {
+ elidedDict = new Map();
+ elidedTitleCacheDict.set(title, elidedDict);
+ }
+
+ let elidedDictForPixWidth = elidedDict.get(pixWidth);
+ if (!elidedDictForPixWidth) {
+ elidedDict.set(pixWidth, new Map());
+ elidedDictForPixWidth = elidedDict.get(pixWidth);
+ }
+
+ let stringWidthPair = elidedDictForPixWidth.get(sliceDuration);
+ if (stringWidthPair === undefined) {
+ let newtitle = title;
+ let elided = false;
+ while (this.labelWidthWorld(ctx, newtitle, pixWidth) > sliceDuration) {
+ if (newtitle.length * 0.75 < 1) break;
+ newtitle = newtitle.substring(0, newtitle.length * 0.75);
+ elided = true;
+ }
+
+ if (elided && newtitle.length > 3) {
+ newtitle = newtitle.substring(0, newtitle.length - 3) + '...';
+ }
+
+ stringWidthPair = new ElidedStringWidthPair(
+ newtitle, this.labelWidth(ctx, newtitle));
+ elidedDictForPixWidth.set(sliceDuration, stringWidthPair);
+ }
+ return stringWidthPair;
+ },
+
+ quickMeasureText_(ctx, text) {
+ let w = this.textWidthMap.get(text);
+ if (!w) {
+ w = ctx.measureText(text).width;
+ this.textWidthMap.set(text, w);
+ }
+ return w;
+ },
+
+ labelWidth(ctx, title) {
+ return this.quickMeasureText_(ctx, title) + 2;
+ },
+
+ labelWidthWorld(ctx, title, pixWidth) {
+ return this.labelWidth(ctx, title) * pixWidth;
+ }
+ };
+
+ /**
+ * A pair representing an elided string and world-coordinate width
+ * to draw it.
+ * @constructor
+ */
+ function ElidedStringWidthPair(string, width) {
+ this.string = string;
+ this.width = width;
+ }
+
+ return {
+ ElidedTitleCache,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/event_presenter.html b/chromium/third_party/catapult/tracing/tracing/ui/base/event_presenter.html
new file mode 100644
index 00000000000..977561e2787
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/event_presenter.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides color scheme related functions.
+ */
+tr.exportTo('tr.ui.b', function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ const colors = ColorScheme.colors;
+ const colorsAsStrings = ColorScheme.colorsAsStrings;
+
+ const SelectionState = tr.model.SelectionState;
+
+ /**
+ * Provides methods to get view values for events.
+ */
+ const EventPresenter = {
+ getSelectableItemColorAsString(item) {
+ const offset = this.getColorIdOffset_(item);
+ const colorId = ColorScheme.getVariantColorId(item.colorId, offset);
+ return colorsAsStrings[colorId];
+ },
+
+ getColorIdOffset_(event) {
+ return event.selectionState;
+ },
+
+ getTextColor(event) {
+ if (event.selectionState === SelectionState.DIMMED) {
+ return 'rgb(60,60,60)';
+ }
+ return 'rgb(0,0,0)';
+ },
+
+ getSliceColorId(slice) {
+ const offset = this.getColorIdOffset_(slice);
+ return ColorScheme.getVariantColorId(slice.colorId, offset);
+ },
+
+ getSliceAlpha(slice, async) {
+ let alpha = 1;
+ if (async) {
+ alpha *= 0.3;
+ }
+ return alpha;
+ },
+
+ getInstantSliceColor(instant) {
+ const offset = this.getColorIdOffset_(instant);
+ const colorId = ColorScheme.getVariantColorId(instant.colorId, offset);
+ return colors[colorId].toStringWithAlphaOverride(1.0);
+ },
+
+ getObjectInstanceColor(instance) {
+ const offset = this.getColorIdOffset_(instance);
+ const colorId = ColorScheme.getVariantColorId(instance.colorId, offset);
+ return colors[colorId].toStringWithAlphaOverride(0.25);
+ },
+
+ getObjectSnapshotColor(snapshot) {
+ const offset = this.getColorIdOffset_(snapshot);
+ let colorId = snapshot.objectInstance.colorId;
+ colorId = ColorScheme.getVariantColorId(colorId, offset);
+ return colors[colorId];
+ },
+
+ getCounterSeriesColor(colorId, selectionState,
+ opt_alphaMultiplier) {
+ const event = {selectionState};
+ const offset = this.getColorIdOffset_(event);
+ const c = colors[ColorScheme.getVariantColorId(colorId, offset)];
+ return c.toStringWithAlphaOverride(
+ opt_alphaMultiplier !== undefined ? opt_alphaMultiplier : 1.0);
+ },
+
+ getBarSnapshotColor(snapshot, offset) {
+ const snapshotOffset = this.getColorIdOffset_(snapshot);
+ let colorId = snapshot.objectInstance.colorId;
+ colorId = ColorScheme.getAnotherColorId(colorId, offset);
+ colorId = ColorScheme.getVariantColorId(colorId, snapshotOffset);
+ return colors[colorId].toStringWithAlphaOverride(1.0);
+ }
+ };
+
+ return {
+ EventPresenter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/event_presenter_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/event_presenter_test.html
new file mode 100644
index 00000000000..f9531aa9cdf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/event_presenter_test.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/event_presenter.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventPresenter = tr.ui.b.EventPresenter;
+
+ function mockEvent(colorId, selectionState) {
+ return { colorId, selectionState };
+ }
+
+ function mockSnapshot(colorId, selectionState) {
+ return { objectInstance: { colorId }, selectionState };
+ }
+
+ function isColor(color) {
+ return color.toString().startsWith('rgb');
+ }
+
+ test('instantSliceColor', function() {
+ const color = EventPresenter.getInstantSliceColor(mockEvent(1, 0));
+ const variant = EventPresenter.getInstantSliceColor(mockEvent(1, 1));
+ assert.isTrue(isColor(color));
+ assert.notStrictEqual(color, variant);
+ });
+
+ test('objectInstanceColor', function() {
+ const color = EventPresenter.getObjectInstanceColor(mockEvent(2, 0));
+ const variant = EventPresenter.getInstantSliceColor(mockEvent(2, 2));
+ assert.isTrue(isColor(color));
+ assert.notStrictEqual(color, variant);
+ });
+
+ test('objectSnapshotColor', function() {
+ const color = EventPresenter.getObjectSnapshotColor(mockSnapshot(3, 0));
+ const variant = EventPresenter.getObjectSnapshotColor(mockSnapshot(3, 3));
+ assert.isTrue(isColor(color));
+ assert.notStrictEqual(color, variant);
+ });
+
+ test('counterSeriesColor', function() {
+ const color = EventPresenter.getCounterSeriesColor(1, 0);
+ const variant = EventPresenter.getCounterSeriesColor(1, 1);
+ const transparent = EventPresenter.getCounterSeriesColor(1, 0, 0.0);
+ assert.isTrue(isColor(color));
+ assert.isTrue(isColor(transparent));
+ assert.notStrictEqual(color, variant);
+ assert.notStrictEqual(variant, transparent);
+ assert.notStrictEqual(transparent, color);
+ });
+
+ test('barSnapshotColor', function() {
+ const color = EventPresenter.getBarSnapshotColor(mockSnapshot(1, 2), 1000);
+ assert.isTrue(isColor(color));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/fast_rect_renderer.html b/chromium/third_party/catapult/tracing/tracing/ui/base/fast_rect_renderer.html
new file mode 100644
index 00000000000..750140bc8f9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/fast_rect_renderer.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides a mechanism for drawing massive numbers of
+ * colored rectangles into a canvas in an efficient manner, provided
+ * they are drawn left to right with fixed y and height throughout.
+ *
+ * The basic idea used here is to fuse subpixel rectangles together so that
+ * we never issue a canvas fillRect for them. It turns out Javascript can
+ * do this quite efficiently, compared to asking Canvas2D to do the same.
+ *
+ * Rather than expending compute cycles trying to figure out an average
+ * color for fused rectangles from css strings, you instead draw using
+ * palettized colors. The fused rect color is chosen from the rectangle with
+ * the higher alpha value, if equal the max palette index encountered.
+ *
+ * Make sure to flush the trackRenderer before finishing drawing in order
+ * to commit any queued drawing operations.
+ */
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * Creates a fast rect renderer with a specific set of culling rules
+ * and color palette.
+ *
+ * Rectangles that are drawn will be clipped horizontally to the range
+ * [xMin, xMax]; this is done because CanvasRenderingContext2D does not draw
+ * rectangles with coordinates of very large magnitude correctly.
+ *
+ * @param {GraphicsContext2D} ctx Canvas2D drawing context.
+ * @param {number} xMin Left border of the viewport (pre-transformation).
+ * @param {number} xMax Right border of the viewport (pre-transformation).
+ * @param {number} minRectSize Only rectangles with width < minRectSize are
+ * considered for merging.
+ * @param {number} maxMergeDist Only rectangles that are at most this far
+ apart are considered for merging.
+ * @param {Array} palette The color palette for drawing. Palette slots
+ * should map to valid Canvas fillStyle strings.
+ *
+ * @constructor
+ */
+ function FastRectRenderer(
+ ctx, xMin, xMax, minRectSize, maxMergeDist, palette) {
+ this.ctx_ = ctx;
+ this.xMin_ = xMin;
+ this.xMax_ = xMax;
+ this.minRectSize_ = minRectSize;
+ this.maxMergeDist_ = maxMergeDist;
+ this.palette_ = palette;
+ }
+
+ FastRectRenderer.prototype = {
+ y_: 0,
+ h_: 0,
+ merging_: false,
+ mergeStartX_: 0,
+ mergeCurRight_: 0,
+ mergedColorId_: 0,
+ mergedAlpha_: 0,
+
+ /**
+ * Changes the y position and height for subsequent fillRect
+ * calls. x and width are specified on the fillRect calls.
+ */
+ setYandH(y, h) {
+ if (this.y_ === y &&
+ this.h_ === h) {
+ return;
+ }
+ this.flush();
+ this.y_ = y;
+ this.h_ = h;
+ },
+
+ /**
+ * Fills rectangle at the specified location, if visible. If the
+ * rectangle is subpixel, it will be merged with adjacent rectangles.
+ * The drawing operation may not take effect until flush is called.
+ * @param {number} colorId The color of this rectangle, as an index
+ * in the renderer's color palette.
+ * @param {number} alpha The opacity of the rectangle as 0.0-1.0 number.
+ */
+ fillRect(x, w, colorId, alpha) {
+ const r = x + w;
+ if (w < this.minRectSize_) {
+ if (r - this.mergeStartX_ > this.maxMergeDist_) {
+ this.flush();
+ }
+ if (!this.merging_) {
+ this.merging_ = true;
+ this.mergeStartX_ = x;
+ this.mergeCurRight_ = r;
+ this.mergedColorId_ = colorId;
+ this.mergedAlpha_ = alpha;
+ } else {
+ this.mergeCurRight_ = r;
+
+ if (this.mergedAlpha_ < alpha ||
+ (this.mergedAlpha_ === alpha && this.mergedColorId_ < colorId)) {
+ this.mergedAlpha_ = alpha;
+ this.mergedColorId_ = colorId;
+ }
+ }
+ } else {
+ if (this.merging_) {
+ this.flush();
+ }
+ this.ctx_.fillStyle = this.palette_[colorId];
+ this.ctx_.globalAlpha = alpha;
+ const xLeft = Math.max(x, this.xMin_);
+ const xRight = Math.min(r, this.xMax_);
+ if (xLeft < xRight) {
+ this.ctx_.fillRect(xLeft, this.y_, xRight - xLeft, this.h_);
+ }
+ }
+ },
+
+ /**
+ * Commits any pending fillRect operations to the underlying graphics
+ * context.
+ */
+ flush() {
+ if (this.merging_) {
+ this.ctx_.fillStyle = this.palette_[this.mergedColorId_];
+ this.ctx_.globalAlpha = this.mergedAlpha_;
+ const xLeft = Math.max(this.mergeStartX_, this.xMin_);
+ const xRight = Math.min(this.mergeCurRight_, this.xMax_);
+ if (xLeft < xRight) {
+ this.ctx_.fillRect(xLeft, this.y_, xRight - xLeft, this.h_);
+ }
+ this.merging_ = false;
+ }
+ }
+ };
+
+ return {
+ FastRectRenderer,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/favicons.html b/chromium/third_party/catapult/tracing/tracing/ui/base/favicons.html
new file mode 100644
index 00000000000..0182602631d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/favicons.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.ui.b', function() {
+ const FaviconsByHue = {
+ blue: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALgAAAC4CAYAAABQMybHAAAlrklEQVR4Ae2dCXwdVb3H5265yc3SpEk3ukEXCqVUBLT4Wm19oFKtaN0fKijy9CMguPBarIJsIiA8qsjTh7SllAoFeVBaEARkLV1ooXtL0yRdkqZp9u3uy/v/5uY/OZm75y659+acdnLOnP385zv/+58zZ2YMinTplIAhzsoDceaT2RKUQLwHIMFqh0V2ll0kn4XA6byv9/Vw834kX19e7keRQCzhRyk6bJJYRvD1YTXuhRdeqDj77LPPtNls400mU7HRaCzFFggEVJ/iSqhsicFgKIXUKL6bvB6fz9fj9/u7Kb4bPjaK67Xb7Q0HDhw49IUvfKEd2XUb7WpxHIYvXRgJ8AELkzRso1gmKrwkBfjG7373u5Zly5ZNKS8vn2G1Ws80m83YphPI0wnQUemQFp0IzQR9tdfrxXbI5XId6ujo+PCuu+6qXbNmjYfa9NMmngDoBmt+hIe944M53AUhwqwCvXTp0qJrr732opKSkk8XFhZ+imC+gIAryAZB0QnlJuB3OJ3Ot3p6el5/6KGHttxzzz0O6pse+GEP+3AGnKE2EhgG0tAFt99++4WkoT9tsVgW0DaH4guzAeg4+uD0eDxbaXuDNPzrt9xyy3bS8G4qB8BF6OOoKr+yDDfAB0B91VVXFf72t7+9lLT05QUFBZfQoYWtnA+ux+12v0ra/W+/+tWvXlq5cqWTBjUsYR8OgDPU8KGtjR9++OHHx4wZ8+2ioqKv0X4lbfnsWh0Ox9+bmprWzpgxYxsNFBpd1Op5bcbkM+AMtgr11q1bTz/zzDP/gy4Qv02zGtPzmehIY6MZmmq6UF176NChJ+bMmXOkD3QR9khFczY+HwEXwTbV1NTMI229FCYIXSTm43gTho8uUgMwYUir3zN16tR3qAIfbXkJej4dcIxF1dbkm44ePfqZqqqqpTT7MZf2pYsgAZqN2dTS0nLP5MmTX6EsDDrDHqFU7kTnA+Aa2BMmTDBv2bLliyNHjlxCZsgFuXMYhr6nZL7saGtru/eiiy7aUF9f76UeAfKcBz2XAUffVbgJbAuB/Y3KysoldONl5tDjkrs9oBtL+1tbWwH6UwS6/mZSzg0sVwHXTJG9e/deOGXKlOWksS/MOelncYdJo2+vra396axZs7ZTN0XTJYt7Hdq1XANc1dg0DNOqVatGLl68+DZa/3E1XTwCeOn6JLCly6ncU9+mNLnBZRLOYPAHHI5H2l5/8TdHbl3SRjUx6DkztZgrgKOfDLf5xIkT36moqLiLzJG0rAFJAomsKDp1W51S74IZnSIX8DcrXV3LlK/Oe5xqZPsckGc96LkAOPpowrZ79+5ZNK31BzkzQtKI4qxvV0dJTSLJ592kHKu7QfnPxXupFmhzbFkNeTb/tGsae/bs2Va6wr/lrLPO2izhTgLQZIuaaMp1yvTNyvNbb1HomFB1ZtrAUNYqymztGMNt2rhx44T58+evohs1n0r2+AyX8mnT4KIAvZ63lA82f1/55TX1FJ21tnk2As4zJObq6urP0BTgCmlri2TFDmcEcHQDtnlz4w+Uyz+Hm0Rsm2PuPGtcNpkomtZesGBBYXNz8210d+05CXfWsBLaEQNd5I+e8JyyYettCh0zyoBrpawyWbJFg2twv/jiixPnzZu3mhZFzQ2VqIyJRwIZ0+BiZzyeTcqebVcqS350nKKzxmTJBsDRB3WWZN++fXPpps060tpVouxkODEJDAng6GIg0KI0Hv+mcsXnN9FeVsyyDLWJwnCbadXfomnTpm2UcCcGc1blNhiqlNMmblT+9soi6hdmWKC4hlSJDiXgaBsCsNDKvysnTpz4JIWLaJMupyVgKFLGjHtSefrNK2kYFtpwjIeMs6FqWIOb7kr+Yty4cX+m2+0446XLBwkESHuPrPqz8uymX9BwhhTyoQBchZseQiigdcj30grAO+SDCPlAtW4MeLikdMQdyvqt9yp0rCl1SDR5pgFX4V64cGERvdhmRWlp6XU6scjdfJNAcfF1ysqNK5Q5C2F+ZhzyTF4AqHCPGjXKSjdwHqUHfr+ab8cyW8YzZLMo0QTgcj2jfO/S7ynNzS7KxtOI0UqkJC1TGlyFm3pccPDgwfsk3Ck5drlVidX6VWXFxvvAAG0Z0+SZAJzhtjQ2Ni6ld5D8KLeOjOxtyiRgK/6R8uy7S6m+jF14phtwmEBow3L8+PGr6FnJm1MmLFlRbkqgtOxm5am3rgITtIGNtJrJ6QQcHcdPkYUuKL9MsybLKSydlICijKxcrjz+0pdJFKzJ0wZ5ugBnuM27du2aT7ffV9JUIGCXTkqAJEAsjJ2wQlm1fj7tpPWOZzoAB9yo1/zSSy/NoLdJraMwFsdLJyUgSqBQGX/GOuX+FTMoEpCDmZRr8nQBbqIHgovnzp27mtaWlImjkmEpAU0CYGPmR1crF19cTHH4hU854KmuECcMOmo9derUAyNGjLiawtJlWAJZOQ8eTQb27keUyz7xM8qS8jnyVGpwNk0s+/fv/4qEO9oRlWkDJGArvVpZ89JXKC7lMyupApzhNm/YsGH6GWec8eCAAcgdKYFYEhhz2oPK3X+ZTtlSao+nEnDzxWRL0eNmj0q7O9bRlOkhEoA9ft6cR5WPq/Y4IE+J+ZyKSjS7m56jvK+srEzeqQw5epmNyDkbXBRPT8//Kl++6EaKSok9nqwG10yTHTt2fJpWB0q4xYMlw4lLoJhu5z/y3KepYEpMlWQBV7U3mSXFNN99H71YPfEByRJSAqIEwND4yfcpFyzgqcOkGE2mMGtvy2OPPXY9vZjnTLGfMiwlMGgJWCxnKktv/QmVT3pWZbCAM9zmxx9//IzRo0fj0STppARSJ4HykTcqN//3GVRhUqZKMoCrC6no6Zy7yTSxpW5ksiYpAZKA0WhTPj73dxRKakHWYABn7W3Zs2cPvjH5eXlApATSIoGi4i8oK56/tA9ysAr2EnKDARxlzJdddlkJ3dC5N6HWZGYpgUQlMH7SvbRWpYSKsamSUA2JAs7a2/ynP/3pOvrc9eSEWpOZpQQSlYDZPFn54a/xcDoDnpAWTxRw5DfRJ7DL6HUPP060rzK/lMCgJFA+8sfKZd/CqlRc9yXEbCKZWXtbli1b9gN6EX3loDorC0kJJCoBk6lS+ebVP6BiCU8bJgI48ppxU2fs2LHXJNpHmV9KICkJVFZdo3zsY7j5w6ZKXNXFCzhrb/PDDz/8HbK9x8ZVu8wkJZAqCZjNY5Wf3vkdqo4Bj8sWjxdw5DPRt3KKTjvtNNxhkk5KIPMSqBz1E2Xq7ITekBUP4Ky9LevWrfsGae9JmR+ZbFFKgCRgLpik3HL3NygUty0eD+Cq9h4/fnwBbTdIQUsJDKkERo+9QSkr47ubMfmNlQHaG5v56aef/ndaUDVtSAcnG5cSMFumKXc/fDGYpI35jCiXeADH3KOZ7lp+Sy6HjShHmZApCWA57dgJ3wKTtIFNQB7RxQIc6abLL7+cniEesTBiLTJBSiCTEiguWah8/isjqEkAHpXhaIk4M5BuXrp06ZfoOUtcvUonJTD0EjCaipSvff9L1JGYU4bRAEeaCjh9P+fr0jwZ+uMqe9AnAZgpo0Z/nfYY8IgcR0qA9sZmeuCBBybZbLZ/66taelIC2SEBKzF5zTJMWbMdDl5DXDTAVe29aNGib5D2jpQvpEIZISWQEQkYicm5C0QtnjDg6uwJPY72tYx0WDYiJZCoBMorGXDW4iE1hNPMOBMQb1qzZs0MmvueHlJKRmS1BCZYYZoOA2exTFd+dT/eTsuzKSFaPJwkNMDPO++8+fLiMvdA+Z8JJcqPN+9RGnocoZ0PBELjFF2cbjdYIEykvq4wWehd4APb05dBari4gaWCe/p8AT+uFOdT4j7aoJTB7oAGowFurqqqmicBV5QPmgLKX3b7lVbHANmRLLPVVSjnGT6hzFRa44dHHEqIHhQThXC8+YQiqQ66K9rnvakoD1O9DPiAJvSAo8vYjMXFxWZ6U9VFA3IP052fv+5VGntzBW4+SCYl4KtQ/L3tpCBJ0+WpC/hKLgKrvb29DDj41Q4WIvUOcaZHH310lslkGqlPHI77uQd38CgZTBbSVBVKXk+CGYwjS758/ywwS1sIz/oI1uCmmTNnflKaJ7l/OmuQG3migQ9xnvg0W2gaN/2TfYDzoLQDFw5wVYOT/T1XAq7JKacDKuS2csVg1B/unB6W2nkwaiiumEs7rMEBueZEG5zpN9Gt+QKyv+douWQg5yXAkPvtHYO78MxiCZisJXNsVRML7C3HndRN5li1w/WnNPaNDz744Ll0ZpRm8Zhk1wYhAYacjPJBlM7eIgHFUFryxZvPpR6q/Io9DavBJ0yYcJY0T0Qx5U84CDnNrtjb82dQZHqZysefRQPaRltEDc4JRlr7PS1/Ri9HopeAwWRWjLYKQiF/NLnBWgpmocGZY3XYoomCBOybaPXgNKnBVfnk7R8V8qLyvIAcrBoLiqaCXdoYcvXYMeB8KmPfSIBPUVPln7yWQD/kjEEOD7fABsBVfvtGoTIdYoOPHDnSXFhYODmHhyq7noAEgpCPUPyOTiql3QBMoIbsyGo0F04uInYdbW3RTZRbb711AnXZmh3dlr3IhAQYcpooz0RzaWmDTk1r0YLrwS4GwRaJuoMGmXrjOeecI5fHQiLDzKmQF9ILXFXIGYfc8q2jZ4JdBlyFnE9ZHolx1KhR8gJzmMHNw9Ugz8U7nrijWToyZCZFtMEBu7GoqGgiD1j6w08CKuTWUsXv6s65O56GApVdlWM+cnoNbqB3D+JzEdINYwkw5DlnkxvNYJetEdVEETU4Ioy0RLZEzoEPY7r7hh6EvIQ0eQ/FZP/sCpilPgNwKG0VbgyFdzTqCXC8ZFw6KQEAoxgLS3NoPbkR7GosIyxqcBxSgwQcYpCOJWDAOnIrKUbS5AH9M5GcKUt8OiEZcK1HbIMjQiVfAq7JRgb6JADIDQR5tpuuAaMGuGaisAbXIiTgkutwEujX5L2UnJ02uSEIOHdfZVpqcBaH9GNKIKjJQ6yAmOUylYHsa+6cprBZg3MfpA3OkpB+WAkENXmxEnDbs2+e3KABrvU9RINTih56LbMMSAlAAqomL7BRQFOU2SGYgMouOqV1jGHWIrxer50+8iofV8uOQ5a1vVA1OUEecOPtWdlhkxsUH/2saE5lmufBtVifz4erCOmkBGJKIKjJ8V0ETT/GLJPODAG/X8+uOg+O0087BaHB09kJWXd+SSCoyYuUgIceaB/qeXL/AA2uci3a4JB8QGrw/AIwE6NRNbmlcMht8oBftT40ZY2xsw2OsJogAYcopEtUAqomt5Am9w6dJg8ENPNagzysBs/2W7KJCl/mz4wE8OYsg3loNLnKbNAG1+DGqFmDI1LdpA2eGRjytRX19XAEecDr6kMqcyM1BNTrR41ltCxqcAYc6yOlkxIYtASCmhyP9WZ2doVmUXhtL1hWHWtw3lccDkcb1H22L6zROiwDWSmBoCa39mnyDHSRmPV7nG36lliDs1r3t7e31+kzyX0pgcFIQNPkGbrj6be3gV287Z95Vk0U7MCpkdXV1bXyIjMoEPk3eQmokJsKglOIAD1tm6J4Wo7UMsd9PQ+wBse+CvgzzzwjAe+TjvRSIwGGnB4qS02F4WohE8W58zk94CGzKP6XX3652+VyNdN6lFHh6pFxUgKDkQAgDygWxeDzDKZ47DJeV3PvvtfpVQChJgoKs80C+8Xf09NzRJopEIt0qZQAIFfou0GpXoUIVv0uxxHqq8ov+cxzyDShmsFut9elcmCyLikBloAKuZEm71Jsi/vdKrMi4GqTbIMz8cjgw0yK1OB8SKSfagkMgDwVlZMGDzg6oJR9tIFh5lmzwdEMR/pPnjxZiwjppATSJQHVJg/QRaffm3wT9Gvg624GswPgRsXhNLh//fr1u2nRFYCXTkogbRJQbybCXEl2diXgCzh2bthNFQHwAZAz4BgEgEaijz4C29zZ2VkjzRSIRbp0SiAIOT7MgCnExDeyThS/s7uma+vaZqpANFHUbusBZ8i9ra2tWyXgqozknzRLQIMcF56JOiLc19O6lYrB1hmgvVGVCDj2VQ1Ovq+mpmaLBBwikS4TElAhx7vJE55dIWhb6rZQH6G9WYNrXRYBh/ZmDe5buXLlVj85LacMSAmkWQIa5Im0Q4x2bXkUGpzhZo7VWsIBrp4JGzZsaCc7/KDU4olIW+ZNVgL9kMe2x4P2d+dB+86X8NFP1uARAUffWIPDnvHSdOE2CTjEIl0mJRCEPA57nAj3dzXj468qr+SzDa51V9TgiGTAcTZ4yQ7fLAHXZCUDGZSABnlUm5wgba3dDFZpE00Uraf6Bx5YveNM8C5fvnzbJZdc4iwuLqYH7Yavq+ytURq70rRIKIvEGlmZAYswDjZCRBchLUJ0ULeGqYzaQL8AfEj/PA5nz8u/Zw3O2ntAC+EAR0bVnnn33Xe7Gxsb35gyZcqlxhR9mGj/oU7liWfrlPZOd5jRZGfUbK9bmUnPGIYIeEB3B8i1PyUKBHTo+vPFEYrcfpR6orYfR6NZmiUQ8Cs9XU1vbDiyEysI2f5myLVe6wFHAqSlanDyPTt37nz+9NNPTxngv/3DHqW5lV4tkGPO67ErPi+9pgw/mYAGfjyO8zJo+vL6dH2dmc6vb1/fP31/9Pn1+7HK69P15fXt9eUP+LxKR/OB5yk7flrFOfABNehtcCSKgHuvu+66t2n5bGtk7TGgvpg7uQg3BmW22BSTGa8pIwehx+s4L3wxzOXFOM4j+sjHecSwmEcMi3nEsJhHDIt5ENY75IXjMhxWI+P4E6u8Pp3bYV/fHsWDRb/f1Vq3b9XblBzxAhNFowEOte+hlYWO+vr6f6QKcDSaq06F3FQYdeUEow9fDGfLmMU+ieFI/RPziOFU5Y9UT/T4gOJ2tP/D7e7Bmz+hwcNeYKKOcIAjHiaKZqa8+uqr6+l9KYgf9g6QG/sgxwHXbxAQgyCG9fmGal/skxiO1B8xjxhOVf5I9USLV8j+7mjd/Rz1RzRPwGuIiwQ4zBScFaDas3Tp0r0dHR2HpRYPyo8hD+7Jv5mUABj0eeyHjx58Yh+1y4CDVTAb4qIBzpCjEjfNiW+Qd+775dcPeTRdI9NCf+OSlQl98M3RvAFM0sbmCVhNCHAcSah8TYuvXr16PT2MjAql65OAapPjXXzRnP4iCnk5Llw5ToMvhsPlzYU4cQxiOFLfxTxiuC+/3+/xNB9/cz3tito7rHmCIpE0ONJwRrAd7l61alXjkSNHXpBaHKLpd5hZMfELJ3FA9Buy8oESw/p8vC/mEcOcnmu+OAYxHGkcYh4xTPlx38DtaHnhZP3rjZQEDR5xehBF4eIFXDVT1q5d+whp8YhnS7DK4fdXhdyEd/FJl04J+ANef3PDpkeoDTZPkgIcfR2gxe+7776aY8eO/VNq8dDD2A95sjamLE8/eSTggRsuLj2Otn821D5fQ4lxaW8cpWgaHOnQ1pqZQmHXU0899VePxxPWoEeB4ewYchwadhzmw4V4jhPDnJ6oL9YhhuOtRywjhuMtr88n1iGGOZ8YJ4Y5PZKv+H2BthOb/0pl8F5mEfCoFkUswNEHVICLTdVMufPOOw+QFn9TanGIJtTBHjeSucIHCjkQZsfhSOmcL14/2fqSLa/vZ6z6YqXr68M+1p24nK1vHq3++wHaZfMETEaFG2XjARzaWgOcwq4XX3zxYdLiKC9dGAkw5Pqf2czso0OMkRhGXG5u9N5vpb3p/YdpAKy9AR+YjGlJxAs4a3GcPa4lS5bsOnHixGapxUkaEVwQcnqrasYdw80wowMcl/HOJN0gtLfb1bH5yMHHd1FlDDhr75QAjk6yFsdVKyB3bty48UE5owLRRHYa5JgSY8dhniZDPMeJYU5P1BfrEMOR6hHzIBzLcV8j1aePR31cRgxzPjFODPel+xWvv6N5x4OUhCWoYA8MxqW9KV9cJgryAXBocQbcdeONN+6kd4k/J9eoQDyRnQq5se+Fk3yg2UcxDvcdULUmjotcbeQULhtvffr8XC6Sj5a5TORe9KdwXq5PXz5KOn0WUHH2nnyudt/qnVSMtXfMqcH+xuMHHGVYi6sXm2jwpptuWk4PJrfLNSqiSEPDGuShSTImggTUNSdee/uxA2uXUxaGO27bm6uNxwbnvKzF8fOABp2vvfZa89atW/8oLzhZRJF9zVyJnEWmCBKgb14qPZ01f2xv3o03VsE8AXNx295cVSKAo4yoxVXIFy9e/Aw91rZLXnCySCP7Jpo+NNLnPMQvHXAYfjz/UDuXEcNcVowTw5yeal9sQwxHakfMI4bF/HhiyuPq2LV/293PUB6GO2HtjfoHA7g4o4LGnWvWrLnL6XT6pKkCkUZ3gNxAL4HnA4rcCMfrOG+k8rHS420n3nyJthcrPxgK+D2+5oa37qI+qHyRj4vLhLU3xpAo4CjDgOOMUrX4HXfcse/AgQPr6I20SJcuhgQYcvVijS++pN938RpQHD0n1h378Cms99Zrb7CXkBsM4GiAIVenDGnfccMNNzzU0tLSKE2V+OSvmiuYXZFOkwDmvD2e7saa/X99iCLxOBoAF7W3ljfewGABZ1ucpw2d7733XusTTzxxE33+xCNNlfjED3vcqELON2WGr0+WCS03cXtaTmy6qbutppUkyHAnNO+tl/xgAUc9DLmmxWnacAeB/hDdANK3I/cjSCAIebi3d0QokKfRZHcrvZ01D9XtW72DhqjX3mBtUC5ZwGGqaFqcws5LL7109dGjR9+WN4DiPx7DHXLc0HE5Wt7es/m21WCob4PiTOimTjiJJwM46gPg2PiCE2ee/Wc/+9lvyB5vkvY4SSNO12+uxFkgT7LB7vZ6uptq9678DQ3JThsYggkAppgvCg7OJQs4WkUnMH2CMw6dc9ANoJNPPvnkL8ke90p7nCQSpzPS9CFscryHbzhsEEvA7/a2NLzzy46WXSdpV+WH/KQuLFEvu1QAzrY4mypqJ+lVE9u3bdv2Z9jjEnIWd2wfkBsM+W+T9813093K6j/X7l+9nSQjwp3UhaUo5VQAjvoY8gGmysKFC1fSgqxX3G6ckNLFKwEVcu3rY/k5swK729Hb9Mqed29fSXLRmyawCAZ9YSnKOVWAo06GHDTjQgGdti9atOjXdNH5noScpJGAU00VI74+ln+OXv2gOJ0t7x3cduevaXQqJ+TztGDK4IbkUg24aI+rkNNXIrquuOKKG+kBiYNyURZEHr/LR8j99OFXt6v94KH377/R4WjtImkAcBFuMJQS7Q1Jp0NFoHNiBw0Eube2tnbT/PnzFzz3UtMIA76mJV1cEjAYcIhInLgTkuMOZonH3XW8dvdff9zZur+JhtNLGwMO8zal2hviSgfgqBduAOhki7u6u7u3NHWO+yxNidkk5EEhxfM3CHmfSHN0zQq98Fjxunta6w+v+9GphneO0Wj0cKdUc7Nc0wW4qG608AcffNBrMlvfLx0x5XMGo7lAQs6HIbbfLytNnLELZUkOrO2mF2b2nDz64rX1hzccpG7p4YbmBuApd+kCHB3lI8G+2vnOlr0dBYVV+4tKxl1MswWW/gOX8rHlXYUsq+C8ChaeZv8/vOqYvo5hb2l48+d1+9fiNrwId8rmuyMd7HQCLrYJyDXQ20/tOGUxF+6wlU1aYDQWFPGBEwvIcHgJ9MtKE2f4jFkQq9rcnu72xrp//OTIgccx181wY8477XBDBJkGXAO9o2VPm+JzbioZMXWewVRQ2n/g0C3poklgoKyyc57cTxeUXnfHCVrXfU1D7fr9NJ4e2gA4w530OpNoMuK0TAGO9ljlaJB3tVd3u1yNb5ZVzPy40Wyt7L+Y4u5JP5IE+iFnsUbKmfl4zHN7nG3VdXtWXNvU8GYd9QBgZxxujDyTgKM9OAZc9e1dDY6ejoOvl1fNnm0yFY1TaApR/QhoMK/8G0UCGuQGEmUWKHK83jhA89z0gvoPDu1cfn1b864T1H29WZIRzc1iyzTgA+CmTqj7Lkeru6156xsVoy+cQk+fn44DJyHnQxTd1yBXRRk9bzpTsSrQ7/MoLvvJN/a/d9uSno5jLdQew40bOVghmFG4Md5MA4424UJA97rtvub6f71VPupcq9lSNttgNBLj8oZQUFzR/w6UU+ZVOeD2eV2B3u7ax/a9e/PvXI7OTuqxCDcuKDMON6Q2VICjbYacJ/jpHYte/8mjr35gtVUdLCwaPYfmyunDlFKbQ1ixXBByiDRzTl0RGPBiPXd7S8Pbyw68d+/TdAz5YlK8QzkkcEMSQwk42mfI4Wugt53c3uB0nHyttHz6THo4dywOnjRZIK7ojiHPxOw4lg4EYJI4mnfW7V95ff3h9bupd9DarLlhkohTgZk9+/pElS2AA27eVOjt3fW9p4699kr5qFkmc0HZR6TJ0nfEYngDzZUYmQeZrN6ZhEnSeXj1nk2/vr2nsw5vn4LGZrj1i6cG2VLyxYYacIyAz2zW4hro9HPnO3nstZ2FhZX7Cm1j5tCDAEWkyqU2j3HctV+7FJvjWE+CWRKvt6utpeGtX+7f/vv/6zNJGG7McfPFZNpuv8cY/oDkbAAcHRIhF0FXw21N2084HfWv2UonjaHPhEwJaikJ+oAjqdvRINfFD2ZXfSILF5I+Fz2kUP/akT0rlhyv2bCX6mKNDcD1N3CgqIbc4RzPJof+YOoEJx7eioNPl+FDlHSxqdgQnj77h5+oGPeJXxQUlE3Cg7qZ+EmmdnPWYYYjGRec/nMrbnfnsbaT2+6v2f3wZqoPJghDzVOAvNwVDbLCSqbplJTNNsAxKP5hBeR4OBGfSQDkDHpRYWFFyYzzf/Gd4oqpV5JGt+IZxlRqLGorr1zwmdjEmOMZEp/X4erpqFld/f4Djzud7ZghgabGBrDZ1sYsCa/lTqwhKphOly0min6MLCT42KAV2Kbzeb1Ob9Pxf+32utteLSqZOJ4++jRJmi16Efbv95/8rDsi++pzFX3mCM1kvXPkw7X/Vbd31eskc3H6D9pbhBvHJ7mfiv7upjSUjRpcHCD6xyYLa3PW6DBbVM0+4/yffKq88iPXmq0jJuOdf/J2vyjC/nBQk/fviyHRzva6u462N+96qHrng29RHtbUrLUx9cc3bljpsEISq8yKcLYDzkIC5Aw6bHNAzva5CrnZbC6c/pHrLykbefYVZmv5NAk6iy66PwBsV8fhrrYDj1Xv+uOr9GYyBpt9ntcWbe2s1NriiHMFcPSZtTlAhzZn0AE4ww7fOuP86z45ovLcKyzWkecEL0RN0kYnwYguaGP78MJLetl8277O1j2Pffj+n96mPAAZG8BmHxobYPMdSYCdtVqb+qa5XAKcO40+49qBQYc2Z42uAk77qj919tUfqxh1wZXWosrz6cEKslxQbPhOLwZNFKz4I7D9broL2fp+e/OO1TW7H3mPBMNgi75ojgBqvpCkYG64XAQckkW/sYlmCzQ6Ty2KoBeccc53Z5eP/uiXrIWjFpjNRTaD+no0FM1/2DWo6cIRb3D1eh12l7P5jY5TH6yv27cGt9cBsQg1wtDWvIl2dk5obeq75nIVcB4AQ86gs+nCoLNmV7V8YcnY4ikzvr3ANuKMz1mLqi4k0E3q+7nVu6OoIn+cOv9NUyJ4+ACfBKG3t263d9a9XPvh2jecPSdxg4a1M4BmyBlqnvaD1s4ZcyTc0ct1wHlMetBhi7CNziYM+6qmrzrtwtHjJi/6rK1k/OfoiblpAJ1hz0XNzpoai6AANTafu/uwvafh5cajG//ZcmL7KZIJA8xwiz7SoK1ZY+c02DQO1eUL4OJ4grZH0E6HRmetDsAZetE3T5q6eHr5mPPmWQurzjcXls8i0K20VFcx4iWYeA9JFpoyA4CmJatYI0JQu7zOjr0uZ8v7HU073zlW82w1dR7aGPAC5nA+0llj8z2HnDNFaAxhXb4BzoMMUtlvo0Ojs1bXA69qdEqHby4sLLeOm7p4Vln5tAsshRXnFxSMOJseirbgAhXPjAZvmrDYgn7/jRRuPjV+EGLUxbzRBSKWqdJ7RnChGKBPftAt9AMeZ/v7XR2HdzTWPLvX6eyAycFQA2jeGHBOY23NGhuNcEMUzA/HRyo/RhM6ChF0aHbRVhe1O0POceybiovH28ZNW/SR4pJJ55oLiieZzLZJJottPFY2BoHHWnWAT1Wr0owkUn18JJYoHv9xUQiQNd/roJfnNPi89mNed++x3p5jexoPb9zV29uAu4qAlDUx+ww2fI6Dz0CL9nWkzlD23HZ6qef2aKL3HmNl84VBZ83OQEfyOR98lDWOnjB3dFnFOZOttjGTLIWlk81m20RaMlBpUEw2Ay2QoRPARg1SffQXF7F9vtpFaOEgxbSrhuhDAV57gBZ+BBSf3e9ztXq99uMeZ/dRl73pWFf7vqOn6jfBhmYoRe0rwhsuLOZlu5p9tTv5/Gc4Ac7HEWMWN4ZW9AE6Q83Q8z6fHKKvQq+r10DmjrmoZEKx1Ta6yGItK7aYy7AiUvF4u+weV1evy37K4eip7yWzAmBCi4obwwyfta7oI8xAM8TYF/NwWbHevNXWNPYQNxwBF4Uggo4wg8q+CL0IuAg350Ec18H1oi0xjH3RMXiI4zBrVwZcDyxDy1DzPudnn+tjX2x32IQhfOmCEmBZMJDwGXQxLMYBbqSxz5AjDg4+b7wPH9DBMXz6fUCKOEAs+gwv+0gTw9jHBsd+cG+Y/uUDMUyHH3XYLBsGNJIvQq3PgwbEesQGGUDRR1i/Mez6eHEf9WJfOp0EWPi6aLkbQQIsLwYZ2aLFiekRqhwAJkPK8KJMtLhIdcr4PgnwwZECSU4Cejnq91G7Po7BFVvWx+n3xbwyHIcE/h9VLWRYHWXC/QAAAABJRU5ErkJggg==', // @suppress longLineCheck
+
+ green: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALgAAAC4CAYAAABQMybHAAAltklEQVR4Ae2dCXQcxZnHR3NoNDp8SD7kU7bxFXCchBhMYoLNmhCcOBBykGw2gYTkPV6AhGXD2sTZJQcJG3jsgw3hscuCsTEsOAQW1sbY+MAHxpYtHzI+5EOy5UMStnWPZkZzab9/j75WTWt6NKO5Z6r82lVdXV1d9e/ffPq6uro7zyBDIhXIi7DyngjLyWJRKhDpCYiy2pwoztrpxSwCb+d1bayFm9f1Yu3+cj2MAgOJH2bXnNnEGiHWppW8d999d/inPvWp6YWFheNMJlOR0WgswdLT06PElFdM+xbn5eWVQDXK76TI7vP57H6/v5PyOxFjobwuh8Nx4dixYye+9rWvtaK4ZqFVNY/TiGUIoQCfsBCbcjaLNVHgJRUQG3/4wx9ali1bNmXYsGEzrFbrdLPZjGUagTyNAB2ZCLXoh3CJoD/p9XqxnOju7j7R1tZ2/LHHHqtbtWqVh47pp0X8AaAZbPmRzvnAJzPXhRBhVoBeunSp7b777ruuuLj4xoKCghsI5s8TcPnpIBT9oNwE/D6Xy7Xdbrd/8Oyzz+5+/PHHndQ2LfA5D3suA85QGwmMPLLQ+b///e/nkIW+0WKxLKBlLuUXpAPQEbTB5fF4KmnZShb+g0ceeaSKLLyb9gPgIvQRVJVdRXIN8CCo77777oI//vGPt5CV/n5+fv5NdGrhK2dDsLvd7k1k3f/n17/+9frly5e7qFM5CXsuAM5QI4a1Nh4/fvza0aNH/4PNZvs2rZfRks2h2el0/u2TTz55dcaMGXuoo7DoolXPajcmmwFnsBWoKysrJ02fPv3v6QLxH2hUY1o2E63XNxqhOUkXqq+eOHHitblz557pBV2EXW/XjM3PRsBFsE21tbXXk7VeCheELhKzsb9Rw0cXqT1wYciqP37FFVd8SBX4aMlK0LPphKMvirWm2FRfX//lESNGLKXRj3m0LoOOAjQas/Py5cuPV1RUbKQiDDrDrrNX5mRnA+Aq2OPHjzfv3r3766WlpUvIDfl85pyG1LeU3Jd9LS0tT1x33XVrzp8/76UWAfKMBz2TAUfbFbgJbAuBfUdZWdkSuvFyZepxydwW0I2lo83NzQD9rwS69mZSxnUsUwFXXZHDhw/PmTJlytNksedknPpp3GCy6FV1dXX/OGvWrCpqpui6pHGr+zct0wBXLDZ1w/TSSy+V3n777b+j+R8/pYtHAC9DrwIO9xHD5c5XDF5fS0ya0MWo3+nwvrBx47nfLLlvKypj0DNmaDFTAEc7GW5zQ0PDD4YPH/4YuSMJmQMSExVpsPPxhjsMHt/FuLWkp8dwqb3dt2zhnD2vUKXsnwPytAc9EwBHG01YDh06NIuGtf5DjoyQGmHC4XMLwmwd/Caft2fnmXr3A3d8Zf9hqgXWHEtaQ57Of9pViz179mwrXeE/MnPmzF0S7sEDGuueJnPevCuusO76sPq6R2bPHm2l+sy0gKG0NZTp2jCG27R27drx8+fPf4lu1NwQ6wnKlf0TZcFF/bwe//Z9uxw/vvfuj89Tftr65ukIOI+QmE+ePPllGgJ8UfraIloDp5MBOFoB37zxQvdPvr5gP24SsW+OsfO0CenkoqhWe8GCBQWXLl36Hd1de1vCnTas9GtIXp5h5LgJ1re3H7z2dwsWjMTUYlwrpZXLki4WXIV73bp1E66//vqVNClK3mLvh1RkGcmy4GJr3B7/zkOVXXfd86PD5yg/bVyWdAAcbVBGSY4cOTKPbtqsJqs9QhRPpqNTIBWAo4U0l+1yw1nXd29duH8nrabFKEuqXRSG20yz/hZPnTp1rYQ7OpjTqTRNUhwxtsK69t3tcxZTuzDCAsOVUiOaSsBxbAhgoZl/d02YMOF1SttokSGDFSCabeVj819/v3LOXdQNCy04xynjLFUHVuGmu5K/HDNmzHN0ux2/eBmyQoEe84gRluc2V13zS+pOSiFPBeAK3PQQQj7NQ36CZgA+Kh9EyAqqgzpBQ4h5w4aZH6URlidwrmljSix5sgFX4F60aJGNXmzzYklJyf1BqsiVrFOgqNh0/5ubJr24aFEp3M+kQ57MCwAF7pEjR1rpBs4KeuD3W1l3NtOkQ6kaRQnXfZfL/+Y3bqz7Ed3f6KZyPIwYbpe4bEuWBVfgphbn19TUPCnhjsu5y6hKCgqM33pr4+QnwQAtSbPkyQCc4bY0NjYupXeQ3JNRZ0Y2Nm4KFBab7tlSdc1SqjBpF56JBhwuEI5hOXfu3N30rOS/xk0tWVFGKjB0mPlfN1bOuRtM0AI2EuomJxJwNBx/iix0QfkNupJ+mtIySAUMpSPyn16z5fPfICnYkicM8kQBznCbq6ur59Pt9+U0FAjYZZAK4J6+aczE/BffWn/1fJIjoXc8EwE44Ea95vXr18+gt0mtpjQmx8sgFVAVIEgKJkzJX/2fq66aQZmAHMzE3ZInCnATPRBcNG/evJU0t2SI2iuZkAoIChiNeUM+O6d45cLbxxVRNv7Cxx3weFeIHwwaar148eJTQ4cO/SmlZUiyAuk4Dh5Ogs5O3wsLPrfnQSoT9zHyeFpw/FhQn+Xo0aPflHCHO6Vym6hASYnpp29v+dw3wQ4tYChuhjdegDPc5jVr1kybPHnyM2IHZFoqMJAC48Zbn/nzi1dNo3Jx9cfjCbh54cKFRfS42Qrpdw90OuV2rQLwx6/9QvGKhQsVfxyQx8WKx6MS/EgUv5vmGTw5ZMgQeadSe/aSvJ5pPrgoj73D91/zr97zEOXFxR+P1YKrrsm+fftupNmBEm7xbMl01AoUlRjvWb1u9o20Y1xclVgBV6w3uSVFNN79JL3LLuoOyR2kAqICYKhisu3JBQvG8tBhTIzGsjNbb8vLL7/8C3oxz3SxoTItFRisAhaLcfqyP435Oe0f86jKYAFnuM2vvPLK5FGjRuHRJBmkAnFToLTM8tCfnpk5mSqMyVWJBXBcWFro6Zw/0Z+Vwrj1TFYkFSAFwNQX5w/5N0rGNCFrMICz9bZ8/PHH+MbkV+UZkQokQoGiQtPX/rb+M7f0Qg5WwV5UYTCAYx/zrbfeWkw3dJ6I6miysFQgSgXGV9ieWHjrqGLajV2VqGqIFnC23ua//OUv99PnriuiOposLBWIUgGLJa9iya8q8HA6Ax6VFY8WcJQ30Sewh9DrHn4WZVtlcanAoBQYXmr62fe+NwGzUnHdFxWz0RRm621ZtmzZT+hF9GWDaq3cSSoQpQImU17ZnfeO+gntFvWwYTSAo6wZN3XKy8vvjbKNsrhUICYFykZa7r1mwUjc/GFXJaL6IgWcrbf5+eef/wH53uUR1S4LSQXipIDZklf+m99N/AFVx4BH5ItHCjjKmehbObaxY8fiDpMMUoGkK0BW/OezZxdH9YasSABn621ZvXr1HWS9Jya9Z/KAUgFSID8/b+KjT02/g5IR++KRAK5Y73HjxuXT8oBUWiqQSgVGlVseoCnZfHdzQH4HKgDrjcX8xhtv/B1NqJqays7JY0sFLPl5U59bVbEQTNLCfOoKEwngGHs0013L78npsLo6yg1JUgAMjhlb8D0wSQvYBOS6YSDAsd30/e9/n54hHrpItxa5QSqQRAWKh5gWffWbY4bSIQF4WIbDbcQvA9vNS5cuvY2es8TVqwxSgZQrYDQabHffU34bNWTAIcNwgGObAjh9P+c70j1J+XmVDehVACyOLs//Dq0y4Loc621g59301FNPTSwsLPyiVFcqkE4K2ArzvvjPv52GIWv2w0P64uEAV6z34sWL76BfjF65dOqzbEsOKQAm5/9diWjFowZcGT2hx9G+nUO6ya5mkAL0WBsDzla8X+tDWWa+uDStWrVqBo19T+u3l8xIawUsplFp3b54NY7mik/703/MxNtpeTSlnxWHk64NKuCf/exn58uLS6086b8+3Pqg4WDNHw0O5yf9Gkuf9+sX6N3twXmaVWwMkUWv+Q7eLVShHk1mv310Kg9Vrt/h/PStQoN/PlVxhBYYa7AbVCwc4PQxzxHXS8ANhkZ7jaGq8W8Gh6ed9MuM4C2ebrD7Jhp6CIJsDr481/UGw4nnqY8MeFB3tYDjF6BY8KKiIjO9qeq6oNI5urL+1L8bOt2XM673PrPf4OjwZDXk/p6e68BqV1cXAx5kxUP54MgzrVixYpbJZCrNuLOagAZnItyQwWQ2GgppXlKeEec8OwON75V+/YErZlHv2A8P6qieBTddeeWVX5LuSZBWGbnCkDs7PQa/PyO7EL7RZI5HTCj+EhXaTwt7IKpfprXgintCBU3kf8+TgIfXNlO2AnJbicVAt7izLoBR2xDLPOoYW/CgP1eiBWf6TXRrPp/877lZp0YOd4ghhyUPNUKRydJYbaa5IyYU5l8+53BRP5hjxYprf9NYNz7zzDOfpl9GSSZ3Wra9vwIMORm9rArUn5Kbfzzt09QphV+xcyEt+Pjx42dK90SUKXvSDDksedYEwnrYyIKZ1J89tOhacN5gpLnfU7Om87Ij/RRgyLPJiFlsZjALC84cK/1GBgdswLqJZg9OzabOcwdl3KcAIC8oNuMtrn2ZGZpCHyxW0xXU/H4Xmgw49xLrRgJ8Sob2VTY7CgVUyLNgnLwXcIXfXgkUpvv54KWlpeaCgoKKKHSSRTNYAQXyIrPB1eXVzOLIrE5ZrcaK0lKbuaXFCbDZYCsuCfcEmcbf/va34ym2cqaMs18BhjyTZ/3TmKB17ncngV1Y8X6AM/XGq65SPsaZ/WdV9jBIAUBuLSSfnPFgIjIoHj2pCFO7xR6oFpy7YRw5cqS8wAw69bmz0gc5cMiwQE0uKrH0G0kRfXDFQbfZbBMyrGuyuXFUQIGc3p/Q7fSRT65O6YjjERJXVX6hCewqHPNRsILAFjyP3j2Iz0XIkMMKBCA3ZdwQosloBLsqyziFogXHBiNNkS3OhrFRdE6GwSsAyPPJkrvJkmeCHVeYNeUBcPbBlc7ziko9AY6XjMsgFVDmkysXnqAjAwIN54NdlWWkRQuOLuRJwCGDDKyA0ZRnsNrM5JOn/zi5yZzHgHPz1VEUZCjkS8BVbWSiVwGGXCEkjVUxGlXA1b85bMHVDAl4Gp/BFDaNIXe7vGk7uEL+iOheK0zzKAqkkxY8hQBlwqEBeX4BJmilZ2uNRuX6UeGYW8gWnNelD85KyDikAgy5uzv9xslNRvUiU217PwtOW7TQq4VlQioABRTIrTQzNc1MeU9eD9gNacHVPzper9dBH3mVj6tJlsMqwJB7yJKnyzg5vTXAITRaYZrHwdV8n8/Xpa7IhFQgjAKAnOZhp83gSo/foGVXGQfHD1D9EcKCh+mT3CQVCFKAIfe6yZKrFAUVSdqK39cjsqtwLfrgaEiPtOBJOx9ZcyBAbs7H3JUUd8mnWPCgn5l4QalskICn+CRl6OEVyMld8brp9VkpMuU9fj+7KCrkIS14v9fpZqjostnJVYDuJJIlJ6RSYMrBrK9HAVyFG71nC45MZZE+eHKhyLajMeQ+jz/phtzvy4MPrrIMbUULzoDbs0102Z/kKgDITRZj0g253+8Huwy40mm24KoCTqezBeZezglXJZGJQSgAyA0EOSx5MgLcfp+7p0V7LLbgTL2/tbX1tLaQXJcKDEYBtuSD2Xcw+zg6u8EuflHMs+KiYAVByTx58mSdvMgMCCL/j12BpEFO9Laed9Yxx70t72ELjnUF8DfffFMC3quOjOKjAEOeyMEVfOyqevtFLeD9RlH8GzZs6Ozu7r5E81FGxqd7shapAI1mwCen5zz93sT45H5Pz6UTey52ktb9XBTor1jv3o1+u91+RropkEWGeCoAyI0EebyHV8Bqt8t7htoKuEMCjn4AcqWAw+E4jQwZpALxVkCBnG7tK5DDZ4nT4nb5wawIuNJ09sFFC+7DSIq04PE+tbI+VoAhj5dPjiHCbrsXgNNTGMEWXBwHVyFvamqq48bIWCqQCAUAeQ8ZcJoBGHP1+KF0NHvALCw4c6zUG8qC+995551DNOkq9iPH3HRZQTYrgJuJmKQVa6CvOffUfNhwiOoRXRSFXwYcx0AGCvjoI7CX2tvba6WbAllkSKQCsUKuXGB2eWsr37twidopuihKs7WAM+Te5ubmSgl4Ik+trJsVYMgHMz0E/ndXm6eS6qI3E+m7KHwsxYLTiq+2tna3BJxlkXGiFQDceDe5EiMd6UIPzLU0OneD2d4FDKtBz4L7li9fXkmzs4IKq3vJhFQgAQow5NFUTYT696w5DwsuuieK/416QgGu/BLWrFnTSn54jbTi0cgty8aqgAo5rj0HWHB7vtvhqTnyUVMrlWYLDrhDAo62YQOsNvwZLw0X7pGAkxIyJFWBgHsy8CHhf9tb3Pj4q8IrxWBXhRs1iBYc6ww4fg1e8sN3ScAhiwzJVoAhJ1dc/2YnNaq5oWsXRQBcdFHU5oo3epAJwBly79NPP73npptuchUVFRWoe+RgwnXRZmh3YBQqu4OuMQuyiX0a6GQHCuhs1D1GX7VBKVhp7APgtfvSS4dcm1bUsQVn6x105FCAo6Diz3z00UedjY2NW6dMmXKL0ag19kHtiHil9nyj4b2dVYaOLvEVFhHvnpKCXs9XDUa3m44dpF1QW7TiB23UWdHdR+cw8DlDBlCgE/S30A5h9tOpLubsaG/r6JWnJ+gNrtbmrRdO7sYMQva/GXK1nVrAsQGaoCDMvufgwYP/N2nSpLgB/sJb6w0tHWhTZgV3t4teidBNjYbkkEhPem2/uCyjpt1fu127f7LLa4+vbZ+2Pdry2vWB9tdu1+6vPV6gvN/vMzTUHv8/Ku2hBaz2gxs1hTLLqIEB995///07aPpss661QS1RhEyEG93LtxbQKxH4+7gQPdLAZRGLad5fzOMyYoxyXEZMi2XEtFhGTItlxLRYBmltQFkE3ofTSmYE/w20v3Y7H4dj7fECrorP42mu2rZhB23VvcDEnuEAh9n30MxC5/nz59+LF+A4aKaGAOT5wbxpO6M9X9jOedqyqVjntujxo21Tostrjxfheldnx3tuu91JxWHBQ15goqpQgCMfFpytuGfTpk3v0PtSkJ/zAZBbLL2QMyRiDIUYCjEtlkllWmyTmNZrk1hGTMervF49YfL99JbNpvrat6k5onsCXvsFPcDhpuBXofjhS5cuPdzW1nZKWvGAfhaGvJ+cMiPRCoBBj8t16tCOTUfoWAw4WAWz/UKoi0wUQmGGHJW4aUx8TVlZ2YP0DR9sz/kAyBG8HsgjQ7IUAOD2jvY1dDwMa0F8hjsk4HoWHO2FyVet+MqVK9+hh5Hl2YQyvQGQm/PJXQkXcKcCge9YcFrJDPFftOVDVJFWWdH2Z4Dy9PpjT92R/e9QH8EiPAwwGtI9oXxdHxzb8ItgP9z90ksvNZ45c+ZdOf8K0vQFC42sKJAzwNoYRfmkiWltOV4Xy4hp3p5psdgHMa3XD7GMmKbyALKrs/3dMx8faKQkLDgAB6MhrTflRww4fi3uV1999QWy4rq/FlSYi0GB3GLJxa4ntc9+r9d/5tjHL9BB2T2JCXA0PsiKP/nkk7Vnz559X1rx/ueVIQ9z8a+OJMsygYGmaHTAXVdnZ+f7x/bsqO0FfEC4cZbC+eDYDmutuimU7v7rX//63x6PR/dPAnbK1QDITcoQYq/fDSHwp5hjMR3I7b9d70+3Xj7XPdj6Yt1f266B6htou7a+3nW6c9lTf/Lwf9PuuJ0suidhPYqBAEdzUAEcecVN+cMf/nCMrPg2acUhTf9goYtOk5ncFT5RKII0B07rbedykcax1hfr/tp2DlTfQNu19dE6Rk4c9o5th3d+cIxW2T0Je3HJ1UQCOKy1Cjilu9etW/c8WXGuQ8YaBVTINflydXAK+H007+TUyedpb7begA9MDuhJRAo4W3H8erqXLFlS3dDQsEtacVJDJ0jIdYSJMhvW29nVuevAtvXVtCsDztY7LoCjSWzF4dgDctfatWufkSMqkEY/AHIzja5gLjMHTgcm9AfyOQ9lOM3bo43FOsS0Xj1iGaQHCtG2D/XxPmKa2yPmiWne3uP3+Zvqjj9D21y0gD0wGJH1pnIDXmSiDAIAD7rYfOihhw7Su8TflnNUFH10/zPTRafJbFZOMp9ojrETp/mEinm6lYbZEG192vLcDr042vZp69fuH247psR2tDS/XbVl/UHaj613RKMnLFEkLgqXZSuuXGzigA8//PDT9GByK/6MyKCvAEOuX0Ju0SoAprzd3a3VO9Y/TdsY7oh9b64vWsDZF8cBXZs3b75UWVn5Z3nByXLqxwHI5c0gfYWCt8B6Nzde+HPj6dN4VhDuCZiL2Pfm2qIBHPuIVlyB/Pbbb3+THmurlhecLKl+DH9cHULkYuyfI45kwX68j5jmfcU8Mc3b4x2LxxDTescRy4hpoTwezXN1dVVvfeuVN6kIwx219Ub1gwGcrbhysYkGrFq16jGXy+WTrgokDR8UyE00iZNPKIojHWngsnr7D7Q90uNEWi7a4w1QHgz5vF5f3ZEDj1ETADdfXEZtvdGFaAHHPgw4flGKFX/00UePHDt2bDW9kRbbZRhAAYYcWMslWAMDPcxgb768mm7qYL631nqDvajCYADHARhytuLOBx544NnLly83SlclMv0BuZFGV2ToU6CH4HY7nI37Nr/3LOXicTSt9e4rHGFqsICzL66Oi+/du7f5tddee5g+f+KRrkpk6pvplr4CObsbORwDKBpy9pyuqX74YkN9M60y3FGNe2uVHyzgqIchV604DRvuI9CfpRtA2uPIdR0FFMjlU1L0pQcvjZo0PHvggw37SCqt9QZrgwqxAg5XRbXilHbdcsstK+vr63fIG0CRnw+GPFf9cbpbaejqaNuxZfXylWCod+G7lmAsJYDjDOLgWPiCE788x4MPPvgb8sc/kf44qRFhCECeez45/O5up/OTqo3v/oakwuvOwBBcADDFfFFycCEWC85HRCMwfIJfHBrnpBtATa+//vqvyB/3Sn+cFIkw4Ja+URxCzHKfHGaZ/tJ76SmdX9FrIJpoVeGHYrDEw4KUHHyIB+BoJxrDrorSSHrVRNWePXuegz8uIY/8BCmQG7P/zQVgAn735aYLz+3fsq6KFBLhjunCUlQ7HoCjPoY8yFVZtGjRcpqQtdGtvLhSPKxMh1MgYMkBefZ65TRJ0NDZ1rpxy2vLl1NHta4JDCaYijnEC3A0hCHnURU02rF48eJ/oYvOvRLy6M6ViVwVoymepye64yeytI8sd1dH+94tb6z4FzDSu/CwYNzgRh/iqSAAF/1xNNhBX4nouPPOOx+iByRq5KQsSB55YMizyRXHiEm3vbNm99o3HnJ2dHSQGgBchBsMxcV6Q+lEOHtonNjAPILcW1dXt3P+/PkLPth/eGgePqclQ0QK4L3synvBs2BKMmYIuhz2c/s2rf1ZY33tJyRAFy0MONzbuFpvCJwIwFEvQhDo5It3d3Z27naYCm6mGXWFPNE9UFT+H04B/vhAgPHM9Mv9fvpglNPZfGjnpntOHzl0lvqrhTuulpv1TBTgogVX0wcOHOiix7j2Dx899is0HJYvIefTMHCc1/uFjUwckcL9EHphpv34gY/uq9nzUU0IuGG5AXjcQ6IAR0MZbI6VxjfV17UVlQw5OqR0xEKah2GRkEd+TlXIIW2GGHK86tjtcjnqjx74pwNb38dteNFyx228W0/FRAIuHhOQq6BfqD1+0WIp2Dds1KgFNCRmkz65KFX4tAp5Bvjk8LndDkfriQN7fn5g6waMdTPcGPNOONxQMtmAq6DTnasWn8e1s7R8wvVkyEv4xKFRMoRXQDUIiiGnz16n4b8eGud2d9kbqnd+cC+9bu0o9chOCwBnuHEzJyF+N9WrhmQBjgOyBVchv9xwobOro3XbqPGTrjVZLGV8MaW2TiZ0FQhATlKyqrolk78B49z0HsGT+zatua/uyMHT1AKAnXS40fNkAo7jITDgStx++aKz+cLZD8onTZ1NryEeA59c+uUBoQb6X4UcBdPAJ8dwJt5CRTMDD+xY88YvGs+caqCWad2SpFhu1i7ZgAfBTY1Q1umdz+7zp45uHXfFjCn0AstJeUYJOZ+ggWLVXUmxKcesQHqWkm6/t2zd+saKJW0Xmy5T2xlu3MjBDMGkwg3tkg04jonQD3S60vbVVh/cPmbyFGu+rXA2+eRkyGGWZBhIAdYpYMST75H30Bg3fcqlp62p4eWNry7/N3rVWju1WYQbF5RJhxu6pQpwHJsh5wsN+nit13+quupA4ZChNSVDh881mkw0wiKtOcQaKEAnCJrMoMwIpJESj6Orlaa8Ltv2v6++QeeQLybFO5QpgRtapBJwHJ8hR6yCfuFUzQX6U7d5RPn4K8kvL5cuC6QaOKiQJ8EfJ2/bgItJR3vbwb1b1v3iaOX2Q9RCWG223HBJxKHAZP/+FMHSBXDAzYsCPV18dp06eGBjecVkk7Ww6DPSZVHO14D/sbsyYMEYCuDOpNfj7mlpOL9yw6oXf996sQFvn4LFZri1k6diOFpsu6YacLSef9lsxVXQ6c+d79ShqoN05/NI0TByWYxwWWjAQPrmYc96nz7xNeWBhxRofNvpbDl7rPpX2/73f97qdUkYboxx88Vkwm6/h+28ZmM6AI4miZCLoCvp86eON9ibWzYPHVk+mlyWKXBZMC7WdyI1vZKrvdqwrLEJArAxSoJvgna0XNpctXntkqOVHx6mWtliA3DtDRwYqpQHkJJOAe3BXFr88PCmSist+OKqjZZCpK+55bYvVEy78pcFRcUT8eRL3zAZbZWhnwIAM5bAw3/dXfaz9SeO/vve99fsovrggjDUPATI011xwPj8smJpeO++6QY4mhUwzwHI8Zg5vrQKyBl0W0FJSfENt/39D0pHj73LYrVayXWR1pwE0guBGYjRMaeOkNBDtc1NDSs/XLP6FVdnJ0ZIYKmxAGz2tTFKwnO5ozsQ7ZjIkC4uiraPLBJiLLAK7NP5vG63t/bQvkMOR8emoWWjx9Fr0CZKt0UrYd96nyvHtkM/xhwudkfsra0fHtz6/j/v2/zuB6S5OPwH6y3CjfMT25+KvubGNZWOFlzsINrHLgtbc7bocFsUyz7vq9+6oXzK9PsKCgsraE6L4rb0nVSxutxOByx5aA3Yz/aRn+1yOOobT598dte6N7dTabbUbLUx9Mc3btjosEEKXXkKc9MdcJYGkDPo8M0BOfvnCuRms7lg7uJv31Q+ruJOa1HxVLzcEv65BJ0lDB0z2LiAJD/7VNOF+pcr1/5tE72uhMHmmMe1RV87La222NNMARxtZmsO0GHNGXQAzrAjtn5x0Te/VD556p0FxSVX4Y1RmIorQSdlhKCAjfFsL1lse+eRptOnXv7ovbd2UBGAjAVgcwyLDbD5jiTATlurTW1TQyYBzo1Gm3HtwKDDmrNFVwCndSW+5uavXzNu8oy7CocMuRpfVgi8hiF3hxcDLgpm/GFilMfg6OjYf+H08ZU0MrKXNGOwxVh0RwA1X0hSMjNCJgIOZdFuLKLbAovOQ4si6PlXz7959tipM28rKhm2wGzNL8TrGHLlopShxoQo3Fr3drsdXZ1tWxtO1byzf9v7uL0OiEWokYa15kX0szPCalPb1ZCpgHMHGHIGnV0XBp0tu2Lli4eNKPrc/C8vKC0v/0phybA5NI5uogldivuSbePpGAkB3JifjU+CODrbqlqamjYc2LZxq73tMm7QsHUG0Aw5Q83DfrDaGeOOMBRinOmAc1+0oPONInZfxFix9BOmXjVq+py5Nw8rG/kVmp47lV+XFvDVM8+NUS11H9R0S91xqq350oYTVZXvnzt15CKJxQAz3GKMbbDWbLEzGmwRDE5nQ8ygIwbksOhs1QE54NbG5qu+cMO0cZOmXW8bMvTqgsLiWQS7FW95hc+ersAHA+1XXmRJlrqbXqxz2NnRvv/CmZMfHtm1/ST1F9YY8ALmUDG2s8WGC5IVYFM/lJAtFpz7wzH6xbADdF4AuBZ4xaJTvrKtoLjYOuvaL80qGzPx8wVDSq622Yo/ZTSbLLhbqjwzqsxPp9JKCMiXqBGaAMQ4UMD1xU0Y8jsMmM2HJ9ZpLprH6bQfc3V07m9uPLvv8J4dh112O1wOhhpA88KA8za21myxldqpfFaFbAWcT5IIOvx00VcXrTtDznkcm4aWlRXOuGbeZ4aXjfm0xVYwMT/fOtFsLRhnwsMYyvCjUQG/76KVD62NtVIHoNWWUiAmoHFRCJAVX5pi+oKdk+zzBbe7+6zH6Trb2tz48fG9O6vbm5txVxGQsiXmmMFGzHmIGWjRvw7dGCqc6UGreqb3J1z70VcAzjFbddGVYbC1sVhW+aFUzPzMqNETJ1YUDyubaLUVVeRbrRNMFnOZyWguzAvAj9fToZ6AmwPLjxUKCk1EMltoir30OJOjhyD2+b0On8fb7O7uPtft7Kq3tzWf/eTs2fr6mmr40AylaH1FeEOlxbLsfnCstCeb/2PNs7mP2r6hz+ICeNmycwwwGWqGnde5jBgjjUWsN4/cHfPQ0lFF9PidzVpUWFRgK8KMSIPL2eXo7qLRuvZWZ3vLxS5yKwAmuwgcM8yI2eqKMdIMNEOMdbEM78t1ckzFciPkIuDimQ0CkjYwqByL8IuAY7u4jcujPqS5XkoGpbEuBhE4TrN1ZcC1wDK0DDWvc3mOuT6OxePmTDrXARdPNGvBcCLWgsvrDDEgRzmOOT9UXTgW5wM6BIZPuw5IkQeIxZjh5RjbxDTWsSBwHFjL0f9Z8BztfthuszaIwy0i1NpyOIBYj3hABlCMkdYuDLs2X1xHvViXQaMAi6/Jlqs6CrBeDDKKhcsTt+tUGQQmQ8rwYp9weXp1yvxeBfjkSEFiU0Cro3YdtWvzGFzxyNo87bpYVqYjUOD/AZrbm7Ts1rpFAAAAAElFTkSuQmCC', // @suppress longLineCheck
+
+ red: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALgAAAC4CAYAAABQMybHAAAk/0lEQVR4Ae2dCZxUxZ3Hq8/pnhkGmOEQuQS5VCTxWHEDBlyNkciakMMkxujGuOvHO24IKCae0UQlKwmyroocoqtozGpA4oFiVAQU5IaRcchwDsPczNF39/5/b+bfVL/p7ume6bur+DyqXt31r2//5//q1XvPIJRLpgQMMVYeiDGfyhanBGKdgDirzYvsLLtIPguB0/lc7+vh5vNIvr68Oo8ige6EH6Vo3iSxjODrw1rcm2++2f+MM84YV1hYONRkMhUZjcY+OAKBgOZTXDGVLTYYDH0gNYpvIa/V5/O1+v3+FopvgY+D4tra29uP7N27d98VV1zRiOy6g06DcRyGr1wYCfCEhUnK2yiWiQYvSQG+8ac//all3rx5o/v16ze+oKBgnNlsxjGWQB5LgA5MhrToh1BL0Fd4vV4c+1wu176mpqYvHnnkkf0rVqzwUJt+OuQfALrBmh/hvHc8mfkuCBlmDei5c+fab7nllguLi4svttlsXyeYzyPgrJkgKPpBuQn4LU6n88PW1tZ1ixYt2vjoo486qG964PMe9nwGnKE2EhgG0tDWBx988HzS0BdbLJbpdEymeFsmAB1DH5wej2cTHR+Qhl937733biYN76ZyAFyGPoaqcitLvgEeAvX1119ve/jhhy8nLX211Wq9lKYWtnIuuFa3272WtPv/3nPPPW8tWbLESYPKS9jzAXCGGj60tfGLL764YPDgwT+x2+3fp/MyOnLZ1Tscjj/X1NS8OH78+E9poNDoslbPaTMmlwFnsDWoN23adNq4ceN+TBeIP6FVjbG5THSksdEKTQVdqL64b9++lyZPnlzVCboMe6SiWRufi4DLYJsqKyunkraeCxOELhJzcbxxw0cXqQGYMKTVHz399NM/pgp8dOQk6Lk04RiLpq3JNx04cOAbAwYMmEurH1PoXLkIEqDVmPV1dXWPjhw58l3KwqAz7BFKZU90LgAeBHvYsGHmjRs3/mtpaekcMkPOy55pSH9PyXzZ0tDQ8NiFF1646vDhw17qESDPetCzGXD0XYObwLYQ2FeVlZXNoRsvZ6Yfl+ztAd1Y2lNfXw/QXyHQ9TeTsm5g2Qp40BTZtWvX+aNHj15AGvv8rJN+BneYNPrm/fv3/2LixImbqZuy6ZLBve7atWwDXNPYNAzT0qVLS2fNmvUA7f+4gS4eAbxynRIwHN8ozDseFQZHTW9l4m/3BBa/8nnDfT97vKqBKmPQs2ZpMVsARz8ZbvPRo0ev6d+//yNkjiRlD0hvqUh3ecsrpwtD2+GEdcMfELUNbWLewNniBaqU7XNAnvGgZwPg6KMJx44dOybSstYf1coISSOKsy4tiJLa8ySPX6wvrxN3TLpX7KJaoM1xZDTkmfynPaixJ02aVEBX+PdOmDBhg4K754D2tqTFKKacPVhsOPEnce+kSQK/IjMdYChjFWWmdozhNq1evXrYtGnTltKNmq/3doLypXyyNLgsP49XfPhOpfjZzCcEbKGMtc0zEXBeITFXVFR8g5YAn1O2toxW9+FUAI5ewDY/UC9+PvrXAjeJ2DbH2nnGuEwyUYJae/r06bba2toH6O7a6wrujGGlS0eMBjFw1ADxetMT4oHpZ2lbi3GtlFEmS6Zo8CDca9asGT516tTltClK3WLvglRsEanS4HJvXF6x/v0vxHXfWigOUXzGmCyZADj6oK2S7N69ewrdtFlJWnuALDwVjk8C6QAcPSSTpa6iTvxwwm/EejrNiFWWdJsoDLeZdv3NHDNmzGoFd3wwZ1JuMlkGjBsoVlf9TsykfmGFBYorrUo0nYCjbQjAQjv/rhs+fPjLFLbToVwWS4Boto/sL14++ri4joZhoQNznDbO0tVwEG66K/nLIUOGPEW32/GLVy43JGAeUiKeqvsv8UsaTlohTwfgGtz0EIKV9iE/RjsAH1IPIuQG1SGjCAhDWaF4qHmBeGzwYIG3EaRFk6cacA3uGTNm2OnFNs/16dPn1hChqJOck0CJTdxaeY94bsZkzfxMOeSpvADQ4B44cGAB3cBZRg/8fi/nZjNDBpSuVZRow3d4xGsjHxT/VlsrXJSPlxGjFUlIWqo0uAY39dhaXl4+X8GdkLnLqkrsFvE90uTzwQAdKdPkqQCc4bZUV1fPpXeQ3JhVM6M6mzAJ9LGJG+v/IOZShSm78Ew24DCB0Ibl0KFD19Ozkr9JmLRURVkpgdIi8Zvqx8X1YIIOsJFUMzmZgKPj+FNkoQvK79CqyQIKK6ckIE4pEQsqHxbfIVGwJk8a5MkCnOE2b9++fRrdfl9CS4GAXTklATwiYRpVJp7bfb+YRuJI6h3PZAAOuFGv+a233hpPb5NaSeHkPGJCFSuXnRIgSGwTBomVb/2nGE8jAORgJuGaPFmAm+iB4KIpU6Ysp70lJdk5BarXyZaA0ShKLh4tls+6QBRRW/gLn3DAE10hfjDoaMHx48ef6Nu37w0UVi7FEsjEdfBoImh2iMX97hR3Up6Er5EnUoPjx4L6LHv27PmugjvalKo0WQJ97eKGLx8U3wU7dIChhCneRAHOcJtXrVo1dtSoUQvlAaiwkkB3EqAngxauuk2MpXwJtccTCbj5kksuKaLHzZYpu7u76VTpegnAHr9svFh2yQTNHgfkCdHiiagEPxLN7qbnKOeXlJSoO5X62UvxebbZ4LJ4yB5/muzx2RSXEHu8txo8aJps2bLlYtodqOCWZ0uF45YA7T68cfu94mIqmBBTpbeAa9qbzJIiWu+eTy9Wj3tAqoCSgCwBIETr4/OnjwsuHfaK0d4UZu1tef7552+nF/OMkzuqwkoCPZWA1SzGvXS9uI3K93pVpaeAM9zmF154YdSgQYPwaJJySgIJk8DgvmL2C/8hRlGFvTJVegM4Liwt9HTO78k0KUzYyFRFSgIkATJVCq88S/yOgr3akNUTwFl7W3bu3IlvTH5LzYiSQDIk0KdAXEEbsi7vhBysgr24XE8ARxnzlVdeWUw3dB6LqzWVWUkgTgmMHSgeu3Ky9oFeNlXiqiFewFl7m5988slb6XPXI+NqTWVWEohTAhaTGPnMLIGH0xnwuLR4vIAjv4k+gV1Cr3u4Kc6+quxKAj2SwIA+4qbrpwjsSsV1X1zMxpOZtbdl3rx5P6cX0Zf1qLeqkJJAnBIwmUTZ/TPFz6lY3MuG8QCOvGbc1DnllFNujrOPKruSQK8kQG/Kuple0Yx942yqxFRfrICz9jY/88wz15DtfUpMtatMSgIJkoDZJE5Z9mNxDVXHgMdki8cKOPKZ6Fs59lNPPRV3mJRTEki5BIb0FbdNOj2+N2TFAjhrb8vKlSuvIu09IuUjUw0qCZAErBYx4i/XiasoGLMtHgvgmvYeOnSolY47lKSVBNIpgWH9xR0lJcG7m93y210GaG8c5ldfffVfaEPVmHQOTrWtJEAbsca8f7O4BEzSwXxGFEwsgGPt0Ux3LX+ktsNGlKNKSJEEsJ121CDxIzBJB9gE5BFdd4Aj3XT11VfTM8R9Z0SsRSUoCaRQAn0LxIyrvyb6UpMAPCrD0RLxy0C6ee7cud+m5yzV50VIGMqlXwL0/Kb9nsvEt6kn3S4ZRgMcaRrg9P2cHyjzJP0Tq3rQIQGYKSP6iR/QGQMekeNICdDeOExPPPHEiMLCwq91VK3+VxLIDAkUWcXXnrhaYMma7XDw2sVFA1zT3jNnzryKtHekfF0qVBFKAqmQABFpnDUxRIvHDbi2ekKPo30/FR1WbSgJxCuBwcVBwFmLd6kinGbGLwHxphUrVoynte+xXUqpiIyWQKBoWEb3L1GdozXxsS/9u/Z2Wl5N6aLFYaTrXRDwr371q9PUxaVePJl/3nzef4uaN28S7hNHunQ2EOgSRa/r1rkuEXild1enr6unecJVHktd9OlwaOJp1LPddEApg92QotEANw8YMGCqApwktmen8K9cIURTI8kv810BdXGI72JR73LR9+ND5jvzOx9nD80u11QhVj1DxRjwkBr0gOMXoGnwoqIiM72p6sKQ3Hl64nv0fhGoPZ5Vo8ff7P5+v2jw+Eil5S7kfQKBC8FqW1sbAx6ixRGpd4gzLVu2bKLJZCrVJ+bjebbBzXNkoTsipfRQo0HTWRybWz7BWvqHkYMn0qjYDg8ZoB5w1uCmM8888yJlnoTIKitPGHIj3R3hyc0lHwCPLbRdRB4A56EF5yoc4Igzkf09RQEelFNWBwB5f3okJhfnE2MqNZumgFk6wC4gDzoZcKbfRLfmrWR/Tw7mUoGsl0Ao5DzVueEXmUyThxcW8heUeVDanMmAIwLnxoULF55Nv4w+Wg71X85IgCE3AoEccjScPr8ZderZNCSNX3lo8ioKk28aNmzYhFz8cyYPPF/DHZAbRKPXmzNrK6B6qM0ygbxP6WCOtaUjWYNzgpH2fo/JVwDyYdxmUuH9zWZN3eXKePuYjGAWPDPH2tD0GhwZTLR7cIzS4Jp8cvY/QN6PIG/KAU0OVouMxtPBLh0MuTZ3rMFBPRzOjQT4aO1M/ZfTEmDIc8Emt5s0wDV+OydNY5oBR5ym2ktLS802m21kTs+sGlxQAoC8r4nMFZp9DQAGIct8m9EwstRuh0XCw9DGqAfceP/992MrGrYzKJcnEjgJOdjIUhcQBbcPHQx2wXRwIGyDM/XGs846S22PzdI57k23AXkJmbAnfNm5dwUAn1mkbe3+ohNwRAVYgwcBHzhwoLrA7A0pWVxWg5xe5Wo8qQCzZjQAuNRs7rKSwhocAwHsRrvdPhwnyuWnBAB5H9LkLZomzy4ZFJmNYFfjmHuu1+AGevdgMScqPz8loEGuafLsGr/ZYAC7bI3A1x6751EgwkhbZIvVGjiLJH99QF5Mmrw1SzQ5mKVFcAAOpa3BjdnjkyD1BDheMq6ckoDQNDntQsQSYjY4ghzsBllGWLbBMQaDAhxiUI4lYCLNWEzmiqbJM/zBIKvByIBz9zUNzica+QpwFofyWQIMObGe0c4kAgx4sKeswYMRCvCMnsO0dY4hb/P5M/YZT7NJ0+AsI41pXkVBJCKUicLiUX4XCQDyIhNWyYP6sEuedEZE0+DcLwU4S0L5YSXAkLdrmjxslrRFGmOxwal3bLakraOq4cyWACAv1DR5ZvWTVlHArmaJcM/YRAn+zfF6ve2cqHwlgUgSYMi7rDNTASYs1b7PH5DZ1Zjm/gXH4fP52oInKqAkEEUCgJz2YWeMRU6Xv3p2NZWO1c3gCqfS4FFmVCV1kQBD7qS3aKX7LXE+v1/W4BrXbKJwxwNKg7MolB+rBAC5jd69Ql5anS8goMGDyhqdkS8otQQFeFrnKGsb1zQ5Qa5p8jSNwm8ImihByMNq8EC6/9akSUCq2d5JAK+H0zR576rpUWkwSyuXETW4Zq9QzQFlg/dIvqpQpwQYche9vDvVb7X1BgRs8CDL6JKswbUEAry1s6/KUxLokQQAeQFtQUz1HU96FzrYZcC1vss2uBbhcDgaoO7VnvAeza0q1CmBDsiFcPlTIxJQ7aTXoetbYw3O1PsbGxv/oc+kzpUEeiKBk5q8J6XjL9Pk9YBd/KSYZ81EwQmcFllRUbFfXWR2CET933sJAHKrZq4k9w4nelrldOwnLwg3wqzBka4lvPbaawpwSEO5hEkgCHkS18kB72v1zXrAg+vgTL3/7bffbnG5XLVms3lgwkaoKsp7CQByC0nBo+nRxIvD7ffXrjve1EI1dzFR0FoQcGRobW2tUmYKxKJcIiWgQU6gJ1qRg9U2X6CK+gq4wwKOcQByLUN7e/s/EKGckkCiJQDI6fUOCd9x2O7zgVkZcK3rbIPLGtyHlRSlwRM9tao+loAMOcf1xge8TT4vAPfREaLB5XXwIOTHjh3b35sGVVklge4kAMhhqngTsC0E9dR6fGA2BG70IZwG97/xxhs7aNMVgFdOSSBpEsDNxA5zpXdWuY/MjVW1zTuoowA8BHIGHIMA0Ej00Udga5ubmyuVmQKxKJdMCQByE/ENfd6Tf6C2xR+ofPFITS31UzZRtG7rAWfIvfX19ZsU4MmcWlU3SyAIeQ8UOYCt93g3keelI0R7o34ZcJxrGpx8X2Vl5UYFOESiXCokAMgBI3lxHTDkqxyujVQU2ps1eLDLMuD4MbAG9y1ZsmSTn1wwpwooCSRZAgx5PM3Qg3L+JTX10OAMN3OsVRMOcO2XsGrVqkayw8uVFo9H3CpvbyXAkMNa6e7AQ6DNXl/5W8fqGyk7a/CIgKNvrMFhz3hpufBTBTjEolwqJQDIAXd3DrDWuj34+KvGK/lsgweLyhockQw4fg1essM3KMCDslKBFEqAIY+mxdGdynbPBvIAuGyiIElz8o0eRLB6xy/Bu2DBgk8vvfRSZ1FRkU3Lnaf/VRaVCM/xmpwffSRlBijCuUjxyBsxLUJCpMfbkB39AvD6/jn8fufjh46wBmftHdJCOMCRUbNnPvnkk5bq6uoPRo8efbmRnphOhGvbWiGO/c9fhaeuORHVpaQOt+8rwlmCb7uHyC6k7UgpUctEKBStTEijnSf6iZfzRGhCyxJvO3K96Q7T42mi2nnig21N5dhByPY3Qx7snh5wJEAmmgYn37Nt27a/nnbaaQkDfP+dTwp3dT3aySrn9HtEu9+r2YYQUCw2IgbIeRk0lOO4cOmIk12q88ttI8x9jdR/fX79eXfl9en68pHG7w34xW5nzV8pv4cOeQ08pIpwahltMuDeW2+99SPaPlsfTUuE1NjNSTbCjSEVGS2i0NihD2KFG+U4L3w5jDQ4OY7zyL6cRw7LeeSwnEcOy3nksJwHYb1DXjguw2EtMob/uiuvT+d22Ne3h3iw6Az46he37PyITiNeYKJsNMCh9j20s9Bx+PDhvyUKcDSarQ6Q2wnyaNf4nMa3nTFWjsuEcXNfYu1fsvP3RCbQwLU+598a3W4HBaHBw15gou5wgCMeGpy1uGft2rVv0OskEJ/3DpDbjCYNWoZE9iEghkIOy3nSGZb7JIcj9UnOI4cTlT9SPdHiAeZ2Z93r5MnmCaK7uEiA40eCXwWo9sydO3dXU1PTl0qLd8iPIe84U/+nUgJgsC3g+XJJ8+7d1C4DDlbBbBcX7iITmZCZIUclbloTX1VWVnYnfcMH6XnvADmcKwDZKpcqCUBN13jbVpHnpoPNE+a1SzciaXBkRF1BLb58+fI36GFkVKhcpwQ0Td7lS4xKPMmUgFv4PG+3HXmD2pC1d1jzBP2IBjh+FSgIM8W9dOnS6qqqqjfV/iuShuSwsmJTkEsSSV4Qa9+1Pseb77ZWVVMr0OBgE4yC1bAuVsA1M+XFF19cTFo84q8lbAt5EKkgT80kuwMB/7q2I4upNTZPegU4eh2ixefPn1958ODBd5QW7zqhDHm0q3+V1nMJkPIW9f72d149UVHZCXi3cGOWomlwpENbB80UCrteeeWVZz0eT8Q/CSiUr64DciwhnnQcjnbjArk5PV6fy3KL+va6q6+35fX1d1dfd+n6+vjcL/yBjx3Vz1J5Fx2yeRLVougOcPQHFeBiUzNTfvvb3+4lLf53pcUhmq4ON4IKDB2QY3Lg2JfDPHFyHMLxOq67p/X1try+v93V1126vj6cd9jezr+vaCrfS6dsnoDJqHCjbCyAQ1sHAaewa82aNc+QFkd55cJIQA85w5cKH91hiORwKtpOVhs+4nij89gzNB7W3oAPTHZrScQKOGtx/Hpcc+bM2X706NENSouTNCI4QG4lTZ5qx3AzbGif41Ldl0S0B+1d73dtWNy4ezvVx4Cz9k4I4Ogna3EY9oDcuXr16oVqRQWiiexOavKTiOEyC44vtzisRXbGcxznicfnsrHWp8/P5SL5+v531zd9/fry3aV7aOVkk+P4QsrnpAPsgcGYtDfli8lEQT4ADi3OgLtmz569jd4l/rraowLxRHY2TZPjY6kd/5CTJ1kOR0qPXHP4FK471vr0+blcJF/uc/gehMbq69eXj5buoy2xR31trz/duGMblWPtHdPqCfciFhOF87IW1y420eBdd921gB5MblR7VFhE4X2GPHyqig0ngY49J97GxU27FlA6wx2z7c11xgs42+Jo0Pnee+/Vbtq06U/qgpPFGdkH5FhdUS42CeD5qb2exj997qzFG6tgnoC5mG1vbiUewFFG1uIa5LNmzXqNHmvbri44WaSR/QLaZstLiJyLrXP4sRwox2XkMJeV4+Qwpyfal9uQw5HakfPIYTk/tHej37X9vuMbX6M8DHfc2hv19wRw1uLaxSY6sGLFikecTifegYg6lYsiAUCO1RWeUGRFOFbHeSOV7y491nZizRdve93lB0Nu+qD8O22HH6E+AG6+uIxbe2MM8QKOMgw4flGaFn/ooYd27927dyW9kRbpynUjgSDkeP+HOkJkEKBfwCF/68oXmvdgv7dee4O9uFxPAEcDDDlrcccdd9yxqK6urlqZKrHJH5BbeqRfYqs/G3NhzftEwF39ZNPORdR/PI6m195xD6ungLMtzsuGzs8++6z+pZdeuos+f0JLl8pUiWUmGHL82c73A69hcwm/5/3WQ3eVOxrw2gWGO651b73cewo46mHIg1qclg23EOiL6AaQvh11HkECgNysNDltdPKLfe6GRU837d5CotJr7x5rzN4CDlMlqMUp7Lz88suXHzhw4CN1AygC0WGi8x1y3NCp8To++lXN+uVgqPPgu5ZgLC2AY6rQOA6+4MQvr/3OO++8j+zxGmWPkzRidJq5YuiNvomxoQzLBru72e+pWdS46z7qWjsdYAgmAJhivijYM5cIiaITWD7BLw6dc9ANoGMvv/zy3WSP0zeGevzjo6ryy2H50EKQR7pNnmvx0MvugN/7vuPw3Vucx47RbGv8kA+WeFmwVxAkAnAQjM6wqaJ1kl41sfnTTz99Cva4gjz2OQLk+DBTrjswAbt7r6fhqacbdm6m8cpw9+rCUpZdIgBHfQx5iKkyY8aMJbQh6123Gz9I5WKVwElNnrurK16C+4i39d05NeuXkFz0pgkUZkL+9CcKcMwdQw6acaGATrfPnDnz13TR+ZmCnKQRh4OpYs5Rm9yjXVS2f3ZX3YZfk0g0TsjnZcGEwQ1xJxpw2R7XIKevRJy49tprZ9MDEuVqUxZEHrtjyHNpjRwrJvU+R/nDjZtn13scJ0gaAFyGGwwlRHtD0snY3obOyR00EOTe/fv3r582bdr0pmXv9MVXbpWLTQImklWHQGWRxlY203IB7kaf69CC5p037XDU4osCbXQw4DBvE6q9Mf5kAI564UJAJ1vc1dLSsnFUZctltKOuUEHeIaRY/gfkcBBotq6k+KnzJwKe+mUnym9c13roIA1FD3dCNTfkBZcswGV1Ewxv3bq1rcBk+Xycpd836c+vVUHeMQmx/M+yCgozlkIZkoe2mYrWgKf19ROVt/y55cty6pYebmhuAJ5wlyzA0VGeC/a1zm9z1jaVme17hluKL6HVAgtPXMJHloMVsqxCBJrh4+yA292+tv3Ifz7btAu34WW4E7beHUkMyQRcbhNzEpyXTY5jx+kJly2jrSXTSZPbeeLkAiocXgIsq6Aww2fLiFjY3Cf8nsbX2/bf9mzjLqx1M9xY80463BBCqgEPgr7VWdvQbvCuH28tnUo2eR+eOHRKuegSCMqKTHOY55l44F0mDQHn0eXNX9z8yomKPTSiVjoAOMONmzlJsbup3qBLFeBokJVOEPJyV2PLUW/738+2DbjAZjCV8cVUsHcqEFECgDwoyIi50pOAde46n6NiYePuW9a2HfgH9QJgpxxujD6VgKM9OJ4XzT/gOeHY7W5Yd65t0CS70TRE24nRuWrQkV39H0kCDHmmrK1gZnH7/ZjXsfWRhs23b3HUHKW+682SlGhullmqAQ+Bmzqhndd6He5PHDUfTC48ZXShwXyagpynp3ufzRUIMp0OuwLpWUq6/d72wd21G+fsdzfVUX8YbtzIwQ7BlMINeaQacLQJ1wX0Fr/b9zfnwQ/PKxhUUGKyTjIJo4Enr6OI+j+SBGQ5YcU81Qfgdga8gQpP0/O/qP/4d41eB77yK8ONC8qUww15pQtwtM2Q84VGwEsbyN9srdo60FRYPsRin2wxmOzYS4AHc5WLLoGT5kr0fIlMxY5AvL+k2e9ufK/98Lz7aje9SnPIF5PyHcq0wI2xphNwtM+Qww+CvsFRfaTa2/beuILSM+0G0ynKZIGounephJxNkhpf+7aFjTtvp5WSHdRDaG3W3DBJ5KVAzHHKXaYADrj50KCv8rS0rXFUvXtOwSBTX5P1K8pkiY0NNleSSRNu3sAkKfc0L7+j9sMH97ua8fYpaGyGW795KrbOJyFXugHHkHgu4DPkmjanP3e+Na1V2waa7buHmAsn0/ZRu7YXQ5ksUVE4adIlducKcU0mCW7euBvWOo7c/UDtxr90miQMN9a4+WIyabffow5el5gJgKNLMuQy6Fp4g+PY0cNksoyylgymz4SM7nioS9nmurkMOT0JeUh0j05ga/toiuj78OKQr/W9RY3b57x64stdVBlrbACuv4EDJZV2l2lXb+gPrivxw8OXVgvosNFhp6MQ4TvKzvnni+yn/rLUaB2BJ1/4TzKlKRdGArCVe+PY1m70uw9+7Kz+wx/rt26g+mCCMNS8BMjbXbW/vr1pM5FlMw1wjA19wgHI8SVmKx2AnEG39zfbiu8vu+CasdZ+19HHWAvM2ESqzBYSUXgHDRwv5rxC0ub3uCrI1n6w/tMXGr1OrJBAU+MA2GxrY5WE93LH2xQVTZ7LFBNFP0IWEnwc0Aps0/mcfq/3rbYDO+r9zrUjLMVDaePWCGW26EV48px//Kw5ovl4wxSbI/Ty+Y+fa97zq0WNO9aRzOXlP2hvGW7MT0aYJCdH3RHCWDPZoX9ssrA2Z40Os0XT7HMGnP/1C2yDbulrtI7E64nx7lae1EweXKr7Bq0cybGd7SI7m9a1D3zmqln0WN3nH1J+1tSstbH0xzduWOlErjhSgymKz3TAWQyAnEGHbQ7I2T7XIDebzba7+p1z6STbgGv7GwvGKNBZdNF9GWx6J/eXO5x1z/++aetaejMZg80+r2vLtnZGam15xNkCOPrM2hygQ5sz6ACcYYdf8Kuy8y86zz7g2jKj7SwFOkkkjJPBJlNv9xZH3fOP12/+iLICZBwAm31obIDNdyQBdsZqbepb0GUT4Nxp9BnXDgw6tDlrdA1wOtf828rO+afJtkHXDTLZz7XiNQxUBIXz1XwB1KASa9n0Rilx3Of4fJPz+PKF9Vs/o2gGW/ZlcwRQ84UkBbPDZSPgkKzGKfmy2QKNzkuLMujWG0rPmnRhwZBvDzbbp9sN5kLAni8XpQy1n9AG1I6At51edPnBRlf1G4sbduP2OiCWoUYY2poP2c7OCq1NfQ+6bAWcB4D+A3IGnU0XBp01u6blh5qLi27od8b0Mdb+3xxosp9PoJvwch3Anmvr6Vi/BtRegprA9tX6HJu/dDe+vbhp7wf0RincoGHtDKAZcoaal/2gtbPGHKG+dnHZDjgPSA86TBi20dmEYV/T9FMKTx00q3j0ZSOsfb5ZYrCO0UyYLNbssqbuhBpfS/jyoLvl7f9r3f/O+vajx0kmDDDDLftIg7ZmjZ3VYNM4NJcrgMvjgTbHuAA5NDprdQDO0Mu++Yf9xo2dXDB4Kmn1c/uZCibShWkBPi+CR+gy1ZSRgcbmJzxJQ0t8riafaxdp6883uWo+Xtm0r4LGDG0MeAFzOB/prLFhguQE2DQOzeUa4PK4WKsDdD4Ath54TaNTvJbWz2wr+FHfsRMnWErPG2iyndvfVHAGwW7BBSqA7/jX0QwLL1kXrYAYjg1f+LhMBNC4UCSoPfSmqL21Pufn5Z6GLS83V+xq8jphcjDUAJoPBpzTWFuzxu6ongrkkuM5yqUxyWPB+Bh0va0ua3eGnOPYNw21FRX+oHDcV06zlpxdQvtfCg2mEYVGy1CrMNpZw7Mvwy93AmG9oBlafT6GGPYzQGbfLfyOdr/nSHvAd5B28x2scp/Y+Wr7vu1HnG24qwhIWROzz2DD5zj4DLRsX0fqDmXPbqeXe3aPJnrvGXT2WavLpgyDrfflvNoP5eLiYYMmWctGDjEVj+hrtowsMliG01cayugppEK6k2qnbWCFlNGMxhh81vRsXkAbgywizUuvWWinW+QOT8DX7vL76tsCnkPNXs+Bal/rwR3u+gPrWg/DhmYoZe0rwxsuLOdl84P96BLLgdR8Apynq4O5DqWKMOAFtLIPwBlqhp3P9Xk14DvrCKmbzB3zSGtx0RBjob2fuaCoj8GKHZGiJeBub/K62qr97Y4D7tY2MisAZofyPukzzPBZ68o+wgw0Q4xzOQ+X1ddN2fLD5SPg8syGAEkJMqx6kGXA9WlcDvUhzPWiLTmMc9kxeIjjMGtXBlwPLEPLUPM552ef62NfbjdvwhC+ch0SYFkwkPD14PI5QwzokY99jg9XF1rheEAHx/DpzwEp4gCx7DO87CNNDuMcBxz7HWd5+j8LPE+HH3XYLBv40Q4Zan0+NCDXIzfIAMo+wvqDYdfHy+eoF+fK6STAwtdFq9MIEmB5McjIFi1OTo9QZQiYDCnDizLR4iLVqeI7JcCTowTSOwno5ag/R+36OAZXblkfpz+X86pwDBL4fwN/IZwMBwH5AAAAAElFTkSuQmCC', // @suppress longLineCheck
+
+ yellow: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALcAAAC4CAYAAAChOH1KAAAlaElEQVR4Ae2dCZhUxbXHTy+zL8ywDDsSVhEVJQoCkoSIIr4kvohLxO2ZfC8an0mQrCQm+uJ7qHkv5hE/xSQaNokBogkxigaUuLDIpsiOMA4MOwyz7zPd7/yLOZfqnu7p7umeXut83+2qW7du3apTv3v63Lr31rWRkUhowOZViPc6Nutpbq/8WPVO8173sYtJ6kgDusI7yme2nYdTdIZQj0NH1vrgwYNtc+bMyb344otzCgsL87KysnLT0tKym5ub6+rr62vKy8urd+7cWfv444/XlJSUAGSB2VfoKw3HM9KBBqQzOsiSspsEXgmhCMTtDGT2TTfdNDwvL28kQzvC6XSOcDgcQ2w2Wzfenme323M5nuN2uwPql/O5OF+dy+Wq4X2rOV7Z2tpa3NLSsp9Pgv3V1dX7XnnllU/4RKnj7S5edNARl4WjRnQNBFS+njnJ4wKxHtp37NgxpG/fvlPY6l7CAI/kZTgv/YMBN1L64hPAzcAf5eUTXvax9d9x/PjxtZdcckkxH0OAF8gljNThE7acVIdbQLZzDyJuX7du3YChQ4dOycnJ+QJb5M+zFR4Qr73L1v4IW/h3amtr/3nw4MG1kyZNOsJ1FdglBOwpKakItwfQTz31VN4dd9wxnd2LL7J1/hzDPCxRSWDYD7BVf5fdmbeXLl26avbs2dXcFsCdkqCnCtwCNEL7gAEDnBs2bPh8QUHBnenp6TdyWi4vySY1TU1NKysqKl6cMGHCO0eOHGnhBuqQJ71FT3a4FczcqQgdu3btGtWvX787MzMzv8YWun+y0eyvPWzRjzY0NPzp2LFjL44ePXoP52vlRbfo/nZN6PRkhdvyoX/7299245GNe9iHvoMvBC9P6N6KQOX5gvRD9tGX8gjMovvuu6+SixRrjjCpJJngRluwAGz78uXLu0+dOvXbDPW3eL2QFyOeGihnyOevWbPm6VtvvfUsbwLcAnpSuCzJALcH1KtXr+4zduzYWbm5uf/OnZWMvrQnouGv1bD8ftu2bf937bXXnmgDPCkgT3S4lZXmDrGvX79+0EUXXTSbRz3u5fXM8Ps85Upo4FGWBbt3735q4sSJh7n1YskRJqQkKtyoN8B2vPzyyz2uueaaX2RnZ9/NN1bSE7IX4qjSfMOoqa6ubvFbb7318xkzZpRx1XDxKZY8jmoauCqJBjfqi8WB4bzNmzf/W/fu3R/j9R6Bm5o6OWyuErK1fMiKwuhfJ8VNZWUVtT/77MTHFrYNI8oIS8L444kEt7ggju3bt182bNiweXwHcXwnuy5pdwPYzrofMdiR8SaaW9wffFLc+N3RE/7xEStNrHhkCu/iXkgEuFFHBfb8+fMLb7vttkf4YvGb7II4u1g3CVm8vXEpORtfiGzdbbaWmpqW3724ou4/v/WDj8u5cMAd965KvMMt1tp56NCh24qKip7gmy99IttzyVWao3ERYekKcbnpxKmy5h/3HbVpGZcvdzzj1ooDnngUnHQOLI8++mhBZWXlC3369FlowI5tV9lt1KdPz7SFdaUTXnj00REF0kccxqWRjMdKWWBv2rTpUn7YfwnfWRwZ225NnKN3peXWtdDion0799TedfkXPvqY0+GLywWnni2m8Xiz3KgPLLbz6NGj3xgzZsw7BuyY8uH34E47jRxzUc47J/eN/wb6ixf0W1zxFC+VEWvtnDt3biE/ybagZ8+ez7CysngxEqcasNkoq6i785m6w1ctmDt3GB5xEMjjwiOIh0qgDjjJMG49hp9ae5Gt9fA47c+4r1a03BJvRbS43J/s3FN3R5ubIhebMR0Tj7XlFoudtm/fvmsuvfTSNQZsb2wSY91ptw0fMzrnrYObr7iGa5zGC9yUmBrPWMItYGOY7xZ+W/wvrIw8XowkqAa4Q/M+MzjjL0d2jL+FmxBzFyVWcOO4OLPT+AH6b/ELuAs5bp4LYSUkujDg6f37Ohee3ncVHjUWCx4TzmJxUAE7/eTJk4/06NHjKb7bGIt6JDpH8Vt/N9l7dnc8dfaTcY9wJWG0YjKSEm2oFNh80ZhRVlb2NL/D+KP47SFTs3A1UFiQ9qOakglPjx7dKyMWgEcTbgX2+PHjs3j6hCX8fMjXw1We2T/+NZCTY//65jeGLRk/vjuGdaNqwaN1NavA5salnz179jl+9evO+O+WxKxhrIYCA2mrtq71xdwLNt7P+Zp4kacLA+0W1vZoWG4BO4197McM2GH1V8LunJPtuLP84FWPcQOidpHZ1XCjfCxppaWl32Ef+6GE7R1T8bA1UJDveOjUnvHfAQ+8CBthl+uvgK6EGy6PAru4uPj23r17z/VXCZOeOhro1cs5t3T7uNu5xQJ4l7nGXQU3KqzGsfmF0+v79+8/P5oTR6YOKgnYUjfZ+vdLm7/vg7HXtwEOTroE8K6AWyy2kx9ZHTdkyJAlbY1IwJ4wVe4KDTAgacMHZy3Z9vbl47h83MkEhxEHvCvgRpnOefPmFfF49lLMU83rRowGPDRgs1POpRdlLZ33xJAi3iCAe+QJdyXSZ4sCmyuVwY+truA5RKaFW0Gzf2gaiNehQH+tqKt3vZkzaAOeRWnkRZ4m9Jc9pPRIWm6cKMrPPnz48HcN2CH1Q8pmzs6yTzux+8rvsgJkiDBiBjdScAvY8LOv4hd58UyBEaOBoDRQ1DPtEfa/r+LMEX2SMFJwoxzHE0880Yv97AXsZ6OSRowGgtIAeLl0VNaCJx4d0ot3wL9/RLiMxF8AKgKY4WcvY3dkOseNxEgDieZz62qqq29dlTNo422cFhH/O9wzBCeHgptfOHjAgK13lYmHqoHsLMf0ozvHPcD7yehJWMY3HLgtsBcvXnwB34F8ONTGmPxGA94a6FuU9vDiZy6+gNPDBjxcuNXoyA033PA4+01mLmzvnjLrIWuA36jP/dcb8h7nHcMePeks3JbV3rp167X8sVF8NMmI0UBENJCXa7/xo3fGXsuFhWW9Ows39nNed911uRdeeOEvI9IiU4jRgKaBi0Zk/vK663rDGxDAta3BRTsDt2W1n3/++Vk8jfDQ4A5lchkNBK+BNKdt6OJfD5rFewjcIV9chgq3BTZ/UGkY36wxz2cH318mZ4ga4Js7Dy1fMHpYZwHvDNzqIpI/1fEkX0Sab8+E2GEme/AasNltmdO/kP8k79Gpi8tQ4Las9rvvvjuBXxe7LvhqmpxGA53TQE6O7bp1r4+RW/PgNWj3JFS4ldXmW+zfY6vdudqavYwGQtAAOONb89/nXUK23sHCbVnt119//TKelmFqCPUzWY0GwtJAbq596j9eueQyLiSki8tQ4IbVdl555ZWzOTRmO6zuMjuHpgGbbfxlOeAOcIPDoPgLBm7LavM3H0fl5+d/KbSKmdxGA+FrID/P/qWXXxw1iksK2noHC7ey2pMnT8bQXzD7hN8aU4LRgIcGbPYpV3UDf0Fb70CgitV2LFq0aAhb7RkexzMrRgNR1ADPezJj0fyLhvAhYWzBbofuSbBwO6dOnfogX7miUCNGAzHRAA+cOP5lSt6DfPCgXJNg4HawO5LDs0XdFJMWmYMaDWgaKChw3DR5ck/MqBDwwrIjuMUlwTQN0/lzHvjuoBGjgZhqwG6ngmfnDsTbXgGtd0dwY5u6kBwwYMCt5qZNTPvUHLxNA+BwYP/0W3lVLiz9MuxvA6w2FsecOXN68fPaX2wr2wRGAzHXQF6O44tzZlsvEwur7erVEdzY5rz77rtv5s9S49anEaOBuNCA3W5L+/rt3W/mynTomnQEt3JJ+JvrmA3IiNFAXGmgX1FawC+m+YJbzLxjyZIlI/mNdtzTN2I0EFcayMqyXfbS7y4cyZWSURNw6yH+4MYOjokTJ95iLiQ99BX3K271Tx331Qy7guBy0vg8WG/FKoft4IbP4i3IpPztwsLCz3tvNOvxrYEW23iqKPs9VxKfnUlc4fncPSrvtUpYb2lygU+/frc33JZLcs899xSwS3KpxxFSdMVWv4dsle+Qzd0c9xqAGevm/AJVVBSTy+ViCDwhQQN8JLVLc1P7/bz39VXOuTye+/rK5zvNcz+U1ZG4XO5Lb5teWbBs1QHMUCXsWoV4w42yYLUd99133yQ2/dBVSoutbhc5997MmkscS4hOK2hxU1mlb7h9daj3f7r3uq99Yp3GJ67jnqktk5atopVcF3Dr0UnecKNNCu5+/fpNNv42m4PyN8jWdDTW/Rjy8TF22yPLTWeriFyWLQu5mLjeAbD26eaezMHfeQG3SLJaiwRdsK7g5icAJ+kbUjVuc+OziYkpPD0Cdc/nDk0EM9xJFedn2ybyrvizEnatknS4oQIsjlmzZvXMzs6+0MplIgmrAQHcwT0tHZxMYXaGe9QDX03vCW55kaap/vIFt33mzJlXt2VUmcxPYmsAgBfmsWkD4Nz9SbbYvnq1G7yC5Q7hRgYH35W82vjbiQ20d+11wL23JfI6OO1TSIBbXBMArsTbciu4eU4Sc1dSNJREoQKcZ9+DBY+U4F8AIv8GEleJUfrJyiTw2g5uGS0R2hXcPL79mSjVyxwmyhpwwkXJdVNFTeRGUQRwNEXiEkajedkZBF4FblUN/nHr5zDi9p/85Cd92NSzh2YkWTUAwAtgwcWkJXhD+UTKm3VLWh9uhmJYmiNwo5lY7Pw8yXDZaMLk1YAArkZRuOdhaRN5mXSxDdyCZ2FZrUgPKrj55s1QczEpKknuEIB347cRYcGFiEQMUf++3V1DubcEbtVx7Sw3v3UzLLm71LRO14AADqudyJKbaQO3ArdqjQ434naeB3CIsdyJ3M2h110Aj+QoSui16Pwe4DUnm4ZwCYphDhXcGC2Rcxahg0dKkMlIimkAgOdnu6mqzvdTg/Gujqx0G7jFiInFM0iHIME+atSo9MzMzAEqxfyknAbOAc4gMBWJdnGZke4eMOozmengmBcFuA63bdq0aYV4jDDletU02NIAAM/LOge3lZgYEceUMa2FXFWAbcEtKzaen4RHP42kugYE8M6Mg8uFqVh+6FLSfOlVtnU2v+yHcFCRG/xaPOt3KG29evUyN2989UAKpgHwXH4evKZee0A6SD0IsMgucQl9FaFvk7iEgfLr27vnucGvwK38E9lu42FAY7lFGyYkZcGz2YkFLgkg+TkOsdyqtjJaomjnZ7gN3AnQidGsosOhWXDrHZdo1iC4YwHgzEzfbglKsBm4g1NkquUSwGsb4neYEG5MTjp5WG6P0RIeBswxN3BSDd3g2gvAc/irox35wsGV1DW5UK/0DDemNlZeCI5ijQkikT91jY1GjAZ8asAX4AI7Qj3us4BOJOpl6nFfRaU77AI3Ntv00RK+gDBw+1KaSTuvgXOAu6mOZwqRuUcEOuSSuITn9+x8TC9L4hLqpTqdynIjCdbbc+6t1tbWFiQaMRroSAMAnF/MpXoA3lHGKG9rddk8+BWfG9WwNTU11fqaoSjKdTSHSwANAPCsjDYTGQf1xb9IYzPVclWU1UaVdLipoaEBG40YDQSlAR1wuYrzDlGQRZuPUmWb937+1r3L0/fnuQM9+NXhdhu4fWjfJHWoAQtwocwrtyQHC6vX7u1WvctDBkmrb7YBbstTErhVQl1dHb82asRoIDQNAHA8j+frIi+0ksLLzRe5wq/iGaMlQrq7oqLCw6yHdyizdypp4JwFd1MDzz4noyjRbD9OrMpaD8vtlqFAAO4uLy8X8qNZL3OsJNEAf6uGLfg5wKPdJMBdXuMCv4plHF/cElWX06dPV5vREqUK89NJDZwDPPouCv4tTpVTtV5tgVvRvnv37hoDt64eE++MBgB4Bs+hDGvqvaA8pIlIXPIhXdIkjx7KNskvIa4q9xyyA24Py40ViHvlypXVPNbNMzobMRoITwMW4F7FeMOJzZKmxwVa71DPg7hIczNVvba+SdwSJFszTgntbh4xKTHWW1RmwnA0AMDTYcG5kK5ccAXLIyUlfBiLY9Rb3BLEscFVW1tbghUjRgOR0IAFuOaKRKJc7zJqG2wlnObiRTwRBbfQjg0uHg781Fhu1oSRiGkAgKfxuJy3ixGpdVS0qtb9KQeKYQ4V02K5BXA3j5gUI7MRo4FIakAAj2SZelmnKuggr1scYxvg1hNaecTkoLHcUI2RSGtAAI+UxZZyUM89h1wwyviamcWzWG5sVyZ94cKFn/L3CxE3YjQQcQ0AcCfPjAMwIyVMq2vhasenXJ5iWMoVuIV2165duxp4xOSYZDCh0UCkNaADLtY3nLC+yXZs14EmfsPTuqAEz9ZoiQU3p7XW1NQY1wTaMdJlGsC7urDg4Qpc6JoGN/xtuCSw3MKyB9xi0l0nTpzYbPzucNVu9g+kAQE8lDFwlOnh0TDKJ8tsmznZ4pfjHpYb+yABGVq3bNmywbjdUImRrtYAAHeE4IML2HJC4OvIW/e3buB66pZbVbudz41MP/3pT3fziwvmNnxX96wpX2kAgHd2ZtnGFqr68QuO3eCWF59uCQ5iWe7q6uqms2fPbjWuCdRiJBoaEMBDORb4LKugLYwrvmGuw62KEcuNFQtujrccO3bsAwO30pH5iZIGBPBgR05QrWNltk0c4K33gHADcGRq2bBhw3rjd7MmjERVAwAccAcj8LfX7Wxdz3kFbvCLRYleDOIYnOEX9tWca93OnDmznmd+7aFypuiP48jjhMVIdDUQjNdQVecuK7iheSLXrJIXPO7KM6ko46wAl9fMOE0Rj0Q1YsJhC8O9mT+Vfb09Ub8EhFaFKc2taVReYRmDMEszu4eigY4Ad7HZPnyKMAQoVtvjYhLH0eHGusCNHVr27du3euDAgRGF21axm2zH1pLN3Yzjxb3YG89Qel02PzIM3bUXf9jjtSdf4i8def3s4veFW39l+StHHaODjaGW5zd/R8fw08pQy2ppddOuva2rGVPFKrdN4EYzlehuCRKwDuB5Pk/KGzlyZM/169e/z5/vi8gXFwC28x9fZrDh1ieOVNW7cBcscSqcAjWtbXRXf/l/K6/ed6rpDDcXr5fh9jtAtzrKl+XGRtDXzJa77siRI6tHjBhxUyRcE9vhV8lWe4SLTizJR3XZLtRiwMlIzDWAx/qOn6HV+04Rf1iQ4AKAV3Brgc1x6/Y74iIw71hwFjTxqMlKniBTtoUV2lyJS0c+f+GLJzc3EgcaYI+EthyilVwVAAVOhVmP2unj3LJBLLfyZe6///5NVVVVRzty7mXHZA8BeC6PJcF3M0tsdADbzF94OPq9P5OMb4NTsdweCPqDWwCHyW8uKSl5zcB9Tm95fDWSg8FSIzHRAC48SyvoNT64YpNDARvMeogvuJEBZh474axo5ikf/trM784bOacBATzYO2kmH1t5/quLxNLCCK/aSX8Fl7yI1Qav7cQf3DgLLL/7ySefLC4rK9turPd5/QHwbOODn1dIFGKw2uW1tP3/3qZiPpzub7ez2qhOMHDj7GjasWPHSy1qSBG7GYEGlAVnwI3/HR0dtLK53XWCXmLVC9hgE0Y4JLg5v9oBO8L8N82cOfM1nvah1FhvqOa85BoLfl4ZXRiD1a6sp9L7lil/G3CDS79goyr+LDe24Wyw/G5+9axh+/btf4jUsCAOkCwigEfCpzRl+PbN8ZDUzhP0h5oadbNG97d9Wm2wFQhuAVxZ729+85t/raysPGmsd/vTEoBn8dRhRiKvAWW1G+jk7OXqQlKstt9REqlBR3AjD8w+CgHcjUePHq3duXPnImO9WRs+xFhw31Y33H8jWO29J2jR0Qr1QSc8+QcewSX49CuB4IblRgHqopLDxm9/+9sr+E2dMmO9fesUY+DGgvvWTWdSYbVrmqjsxytpBfjjRS4mO/S3caxAcCOPWG8FOD9vUrVnz54XjfWGanyLAG5GUcIfRcFzJPtP0ov7jhPe6RWwA1pt9EwwcIv1Vn4379M4Z86cl9h6VxrrDRX6FgW4GQf3rZwgU2G1qxup8ud/V8N/YrXBYUCrjUMEAzfyifVWvvfGjRvLN2/e/LS5awnV+Bfc5MnCOHiE7s6lWjktTN22Unp6awmVs5aD9rWlR4KF29t6N8yYMWMFT96z07xnKar0HQLwTDOK4ls5HaTCHTlVTTvvWqR8bTyrLaMkQVltFB0s3MjrYb358yL1y5Ytm8vzm7iMewL1+BcB3PjgwfnguMPC85G4Xt5Gc3nShnrWbMhWG70RCtztrPfDDz/88f79+/9sLi79gy1bBHBZN6F/DeA2+4Ez9OdfvE4fc65OWW2UHgrcyC/WG38ROJsavv/97/+Gb8ufNdYb6ulY4H/DRUk13zmU9kKDlY109sd/pd9wFGDLhWRQIyTYXyRUuGG9cRAMC+Kg9e+9914ZX2D+mt0UXjUSSAMAPMP75b5AO6XQ9iama0sJ/XrjQSrjZotLAt7AHfgLWkKFGwUL4GrkhNfr+eJyJd+93Gbck+D0LoCHYtFSIS/uRJ6oom23v6BeIROwwVnIYKMnOgs33BPrriXHG+bNm/cIv45WY0ZPoNbAIoAHznk+By5IIXJhKnGV2JYuaXpe2R4o1PfR4/720/PocX/5O0rH6EhlA9U88096hPPp7gg4A28hWW0cqzNwYz/xvS3r/dxzzx1cvXr1L3j0hOfZCLkeKDPlBP43XBSAEcwCBQlEelz21dP0uGwPFOr76HF/++l59Li//P7S20ZHaO0++sXv31cfbvK22uAtZOks3DgQDijWG2da/V133fXm3r17l5ubO1BPcALA01PcB29mp4OnaVj+jcX0JmsNYMsIiVjt4JTplSscuGGeAbhYb1So7pZbbvnV8ePH9xr/20vTHaxaFpxNWyr41nob4WefrKG9dy6kX4EfXsQlAVfgq9NuQAS+SsKHPy829rt5gquWDydMmPCVjIyMdMzaKWI/8S5hMdJeA+r7MNyN6GwR0Zy/v/NIp+O4ckw9LsfR0/S4bA81xAx1VQ1U+8s19K1/7qVjXGYtL7Dc8oCUpg0cMTQJx3LjSDi4t3tSN3/+fPjfjxn/O7TOyGAXJQ2f0ODdsEAkPLfWtb9yLH/HD7Q9lNrhsqyBnY639tJjv39X+dlitQXssKw26hIu3ChDABf3BGdeHfvfq/jR2BVm/BsqCl4E8OD3SMycGM/ec4JW3LuYVnELADa4wb2TsN0RLkNJJOBGQTjLMBbpAfj06dOfLC4uft8ADhUFLwAcF5m6b5pMcVxAlpyl9298jp5krXiDDY7AU9gSKbhREVhwffSkjt+3rLn55pt/WFpa+rEZQQmtrwA3XJRkE4B9pJw+/trz9MPKOjVhvLc7Ao4iIpGGW/xv/L2o0ZMDBw5U8HyDD/HjscUteEDXSNAaEMCTxWrjgaiT1VT84Ev00IFTVMGKELDBiwz7RQzurrYNqqKHDh1q4tvzGyZfmHVNbsUHufz5byNBasDRZn7kvpiuOokj9LXgEJJHj/vKK/kk7Ex+7KOLlIUQdyBP19CJOa/Q/W/soSOchJERwB1RP5vLs6Qr4PZ55vHFZb2r1b1lXNHRa/muXKYB3OqDgBFfgOvg+CtAz6PHuyo/jqEvOA7WYbF5GrSKX71NDyzaQAc4SYb88O+O67SI+dlcliVdATcKB+CyyMFsH+w6WsnTAO+8pD9dx4CnGcBFNYFDAVwfBw+8V+xzAGyeKar+D+vpu798k7ZzjWCtxR3Rh/0iXtmugluvqECO0MbPD5zpmUs7RvamKQx4Rgp/S0rXUVBxAVwpkk1ivPviAPtsPVUv2Uizfvaq+jgToBarDbBhsdGcLpFowo0GqIas3kOnud0fjBlAk/nWc450Wpe0MMkKFV3BB9ddgHiLtzC27GOfmvcWPTj3DfqIuwFQY4ErolvshIab22KdnWiIasyGYqrkZwreu/ICmsivYBVIpyGzkY41IP92cpHZce7ob23icY/jVXToZ3+jB55fR59wDfCNSN1iR3xkxFcro2G55bhyhlqAf3yEanccp7WfG05j+XszRQAcf7VGAmsgHgHHyQawedqzXQ8up/949WNrVEQHO2J3IANpKZpwS10EbhV+eoYaV++lt68dRaPyM2mAAVzUFDgUwJEz1v436oBb6p+W0cZbX6CHNn1KpzkJUMPP1h+GYo/U+ifnaNdJtOHWwZZGus/UUMufPqS114+mfvkZNNxpLHjQPS6Ax9JFwRh2Hdtjnqzy9WnP0k9Ky9QNmpiCDQVGG27pNB1yxF31jeT63Xu07ooLqLx3N7oy3UFO6TjZyYS+NaAPqUbbgquhvkZq5FGwX13/ND3L/YgPnsLH9jXch76OmsQKbjRQQd0WWrAv30r7bXbaOLIPXZHppG7GTQmOBQ/AeZeuHj1B7/HEOXSikg4/vZZmzV5Ba/mwsNbiX8uoiNygQR9HVWIJtzQUjYaLYrkp6w5QOfvhb04aSn3YDx9m3BRRVcehAN7VFCk3hAfz9p6kN29fQD9Y+REd4poJ2GKx9TuPXV0ln4qJNdxotPeiQD9dTc3sprw39gI60zufxsFNkb9cny0xiUoDMtrUFTTBr1e30huo8e399D/TfkPPcj9V8oF1/1qeFRGLHbOeiTXcaLj0g1hvPXSv2EqfuG20bngRXc43fAod/H8rHRgzrcX5gS39tOlKjEI4IcDGmzPHKql43ts0i7/g+y6rQe44yoiIgC19GFNNwTWLF0FdcLJh4cf1Cd/p5Q9SqyW7ex7lLL2X7vjsILq3WyZ/vIBzWZ3ImYy01wDch3AFUOMZbJ5TpH7rYVrAs64uPVvtYan1N2hgrbGIwQr38GHtHw+WW28AlCKLnP0IW+ubyLX0A9pxqIzWXNib+vLk7oPlYtNArqvwfDwcvYgLUsu2eP9pemfOSvrBwyvpHe4HuCAyGgKwvZ/siwuwoYV4styojwieYsaCGT14dj1lxfl7YZYlz3j2drr6Xy6m2T3zqD+PqpAZNmTt+BGAiiVYgcWHC8L3H46+toOeenAZvc/7wuUAzAI01vVnRCLwP8ElRlDiFW40EXUTwAVyAG4tA3tR3oI76J4xA+mOvHTKgKtiIIfq2kswcANquCDVTdTIj0YsvXcpLSo9rcatYZ31RaDmU8Aa5Wp/0BinxDPcUA3qhwXuEwCHLw5LbgGO+MyraNCDk+nuEb1pOrsr6TyyYiBnxXiLP8ABNW6dswvStP8UrXrmPVr8x410mPfXgUYcUGOID1CLbx3CfwLvFUWJd7hFFagnrLhALq4KLjoF9IyvXkb9Zk+lmSOK6Cv8XfZMfl7cQC4a9BECatyIqW6gBob6b0+toT/+5SM1OQ5cDgEbcd0FAdRwQeIWaq6bkkSBG5VFXQVyWHFxVQC4QK7iU4ZTr4e/RLeN7kdfzcugXAU57xnOBRYfIykE1htv8yioG6lm1zH6y3/9nZat/UQ96CQgA2yJ+3JB4h5sdFYiwS1wCeDe/jjAFosOa57+2c9Q4X9/mW4Z3Zdm8J3OQszJJ3c7Uwl0AI0Fkw80sFPBU5iV7zpOL//0VVqx9VP1pTAALEAjrltq8asTwlpz3S1JRLil8gI5XBUs8MdlfFwgV8AX5lHW4zfSxCsG0vUDu9NEfnY8Xax5Ml+Awu0QK13bRE2lZ2n9llJ6g4f11pdXW4+h6hYacfjUcus8YVwQrnM7SWS40RjUXyAXn1wgB+ACucTTxw2mbj+cRlNH9aZp/QroYobcpmZ3QkFcUiJbdLHQ8Bnw0gC7Hu5jFbRzDz8Dwi/nrtlUom6VwzLLIhYa6zrUsNJiqRPCBeH6tpNEh1sa5AtyfXQFcAN6gVydAHdNoAF3j6PpQ3rQlIIcGoxRFoCubg5x5niHXYcZz3wAaIx6VNRSSXEZrV28iVYt2UBHuCkCrkCNdT0O10OsdMJDzW1Rkixw6+0R0MVd0V0WuQgV0MXKO798CRV9bRxdMbQHje3TjS7n0Za+cF0wdq7DjgPFwroDZIgCmkPAjDHpttGO4/zo6YcHy2jbnzbRlld30CnOAmB1qAVoPR1Ay4IjyMLRxJdkg1vvEbQNroq4KwI7ABeovUNsQz7nzHHU78YxdMWQnjSWn0q8LDuNemIObVyQAnbrwpQzQ3Tg9fi5rYF/BV7klLgijX9wIQiYEeKtcn7r5czJKvqo+AxtW7mdtvxxkxq+E+urwytwSyh5BGgu0XI/AlcywXIkM9zSFWLJBXSEFsQcB+BYF+glriBvS7dPGU6FUy+iwcOKaFBRPg3qlkUD89NpIFv4fmzdnQAez1OLK6POLK91bBPLq0IGFxd8AjHSsN5mlVt4/PlYVROV8qQ2paeq6DDPr3d4zW4q4WE7fAsdYAJWAVbiANk7DpiRJjAjVIflMGkFfZAqgrbqC+AF6Ahl8QU20mS7vo86WXIzyfm1K6jfZQNpQEEm5fP0w1lZaZTNw47Z7L9ns4XPZl8+i61+NsOdwQA3svWtY9+4ni1xHfvJdTw8V1fPS2Mz1Vc0UNVHpXTkT1voWE2DB5AAFFCK1RVgBWR9Xc8j+wjMEnJRyS2pBLfekzrkiCtQOdThFaB9wS0nhYRShne5so5jIy4CwCACmncolhWQCpwIJS7wAmyJ+8rrXS5nTx3RFZ46rfZsqQCohwK7Hgr4HaXpZUgcR9PjWBfo9LikIRSQBWZ93V8a0vUyJI5jpKRA6UY8NSAgeoeAGmmBQu/9UDrSvAXwQQRCPRRQA4X6PhI/V6r59al0oxZPDQisSPUVlzQ9lLx6iLi3AEiIHgqk3qHk886rCjA/7TWADjESugZ0vUncO5RSJV3W9VBAlTRZ9w6xXdIkrwkDaKAjxQfY1WwOoIFQdGvADaDMzmz+f6SMYEX4z7hMAAAAAElFTkSuQmCC' // @suppress longLineCheck
+ };
+
+ return {
+ FaviconsByHue,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/file.html b/chromium/third_party/catapult/tracing/tracing/ui/base/file.html
new file mode 100644
index 00000000000..0c4945933f1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/file.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ function readFile(fileBlob) {
+ return new Promise(function(resolve, reject) {
+ const reader = new FileReader();
+ const filename = fileBlob.name;
+ reader.onload = function(data) {
+ resolve(data.target.result);
+ };
+ reader.onerror = function(err) {
+ reject(err);
+ };
+
+ const isBinary = filename.endsWith('.gz') || filename.endsWith('.zip');
+ if (isBinary) {
+ reader.readAsArrayBuffer(fileBlob);
+ } else {
+ reader.readAsText(fileBlob);
+ }
+ });
+ }
+ return {
+ readFile,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table.html b/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table.html
new file mode 100644
index 00000000000..942d83f9542
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table.html
@@ -0,0 +1,229 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-b-grouping-table'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ }
+ #table {
+ flex: 1 1 auto;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ function Row(title, data, groupingKeyFuncs, rowStatsConstructor) {
+ this.title = title;
+ this.data_ = data;
+ if (groupingKeyFuncs === undefined) {
+ groupingKeyFuncs = [];
+ }
+ this.groupingKeyFuncs_ = groupingKeyFuncs;
+ this.rowStatsConstructor_ = rowStatsConstructor;
+
+ this.subRowsBuilt_ = false;
+ this.subRows_ = undefined;
+
+ this.rowStats_ = undefined;
+ }
+
+ Row.prototype = {
+ getCurrentGroupingKeyFunc_() {
+ if (this.groupingKeyFuncs_.length === 0) return undefined;
+ return this.groupingKeyFuncs_[0];
+ },
+
+ get data() {
+ return this.data_;
+ },
+
+ get rowStats() {
+ if (this.rowStats_ === undefined) {
+ this.rowStats_ = new this.rowStatsConstructor_(this);
+ }
+ return this.rowStats_;
+ },
+
+ rebuildSubRowsIfNeeded_() {
+ if (this.subRowsBuilt_) return;
+ this.subRowsBuilt_ = true;
+
+ const groupingKeyFunc = this.getCurrentGroupingKeyFunc_();
+ if (groupingKeyFunc === undefined) {
+ this.subRows_ = undefined;
+ return;
+ }
+
+ const dataByKey = {};
+ let hasValues = false;
+ this.data_.forEach(function(datum) {
+ const key = groupingKeyFunc(datum);
+ hasValues = hasValues || (key !== undefined);
+ if (dataByKey[key] === undefined) {
+ dataByKey[key] = [];
+ }
+ dataByKey[key].push(datum);
+ });
+ if (!hasValues) {
+ this.subRows_ = undefined;
+ return;
+ }
+
+ this.subRows_ = [];
+ for (const key in dataByKey) {
+ const row = new Row(key,
+ dataByKey[key],
+ this.groupingKeyFuncs_.slice(1),
+ this.rowStatsConstructor_);
+ this.subRows_.push(row);
+ }
+ },
+
+ get isExpanded() {
+ return (this.subRows &&
+ (this.subRows.length > 0) &&
+ (this.subRows.length < 5));
+ },
+
+ get subRows() {
+ this.rebuildSubRowsIfNeeded_();
+ return this.subRows_;
+ }
+ };
+
+ Polymer({
+ is: 'tr-ui-b-grouping-table',
+
+ created() {
+ this.dataToGroup_ = undefined;
+ this.groupBy_ = undefined;
+ this.rowStatsConstructor_ = undefined;
+ },
+
+ get tableColumns() {
+ return this.$.table.tableColumns;
+ },
+
+ set tableColumns(tableColumns) {
+ this.$.table.tableColumns = tableColumns;
+ },
+
+ get tableRows() {
+ return this.$.table.tableRows;
+ },
+
+ get sortColumnIndex() {
+ return this.$.table.sortColumnIndex;
+ },
+
+ set sortColumnIndex(sortColumnIndex) {
+ this.$.table.sortColumnIndex = sortColumnIndex;
+ },
+
+ get sortDescending() {
+ return this.$.table.sortDescending;
+ },
+
+ set sortDescending(sortDescending) {
+ this.$.table.sortDescending = sortDescending;
+ },
+
+ get selectionMode() {
+ return this.$.table.selectionMode;
+ },
+
+ set selectionMode(selectionMode) {
+ this.$.table.selectionMode = selectionMode;
+ },
+
+ get rowHighlightStyle() {
+ return this.$.table.rowHighlightStyle;
+ },
+
+ set rowHighlightStyle(rowHighlightStyle) {
+ this.$.table.rowHighlightStyle = rowHighlightStyle;
+ },
+
+ get cellHighlightStyle() {
+ return this.$.table.cellHighlightStyle;
+ },
+
+ set cellHighlightStyle(cellHighlightStyle) {
+ this.$.table.cellHighlightStyle = cellHighlightStyle;
+ },
+
+ get selectedColumnIndex() {
+ return this.$.table.selectedColumnIndex;
+ },
+
+ set selectedColumnIndex(selectedColumnIndex) {
+ this.$.table.selectedColumnIndex = selectedColumnIndex;
+ },
+
+ get selectedTableRow() {
+ return this.$.table.selectedTableRow;
+ },
+
+ set selectedTableRow(selectedTableRow) {
+ this.$.table.selectedTableRow = selectedTableRow;
+ },
+
+ get groupBy() {
+ return this.groupBy_;
+ },
+
+ set groupBy(groupBy) {
+ this.groupBy_ = groupBy;
+ this.updateContents_();
+ },
+
+ get dataToGroup() {
+ return this.dataToGroup_;
+ },
+
+ set dataToGroup(dataToGroup) {
+ this.dataToGroup_ = dataToGroup;
+ this.updateContents_();
+ },
+
+ get rowStatsConstructor() {
+ return this.rowStatsConstructor_;
+ },
+
+ set rowStatsConstructor(rowStatsConstructor) {
+ this.rowStatsConstructor_ = rowStatsConstructor;
+ this.updateContents_();
+ },
+
+ rebuild() {
+ this.$.table.rebuild();
+ },
+
+ updateContents_() {
+ const groupBy = this.groupBy_ || [];
+ const dataToGroup = this.dataToGroup_ || [];
+ const rowStatsConstructor = this.rowStatsConstructor_ || function() {};
+
+ const superRow = new Row('', dataToGroup, groupBy,
+ rowStatsConstructor);
+ this.$.table.tableRows = superRow.subRows || [];
+ }
+ });
+
+ return {
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table_groupby_picker.html b/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table_groupby_picker.html
new file mode 100644
index 00000000000..6d2f1b917e6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table_groupby_picker.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/dropdown.html">
+
+<dom-module id='tr-ui-b-grouping-table-groupby-picker'>
+ <template>
+ <style>
+ #container {
+ display: flex;
+ }
+ #container *:not(:first-child) {
+ padding-left: 3px;
+ border-left: 1px solid black;
+ margin-left: 3px;
+ }
+ </style>
+
+ <div id="container"></div>
+ </template>
+</dom-module>
+
+<dom-module id="tr-ui-b-grouping-table-groupby-picker-group">
+ <template>
+ <style>
+ :host {
+ white-space: nowrap;
+ }
+ #left, #right {
+ user-select: none;
+ cursor: pointer;
+ }
+ </style>
+
+ <span id="left" on-click="moveLeft_">&#9664;</span>
+ <input type="checkbox" id="enabled" on-change="onEnableChanged_">
+ <label for="enabled" id="label"></label>
+ <span id="right" on-click="moveRight_">&#9654;</span>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ Polymer({
+ is: 'tr-ui-b-grouping-table-groupby-picker-group',
+
+ created() {
+ this.picker_ = undefined;
+ this.group_ = undefined;
+ },
+
+ get picker() {
+ return this.picker_;
+ },
+
+ set picker(picker) {
+ this.picker_ = picker;
+ },
+
+ get group() {
+ return this.group_;
+ },
+
+ set group(g) {
+ this.group_ = g;
+ this.$.label.textContent = g.label;
+ },
+
+ get enabled() {
+ return this.$.enabled.checked;
+ },
+
+ set enabled(enabled) {
+ this.$.enabled.checked = enabled;
+ if (!this.enabled) {
+ this.$.left.style.display = 'none';
+ this.$.right.style.display = 'none';
+ }
+ },
+
+ set isFirst(isFirst) {
+ this.$.left.style.display = (!this.enabled || isFirst) ? 'none' :
+ 'inline';
+ },
+
+ set isLast(isLast) {
+ this.$.right.style.display = (!this.enabled || isLast) ? 'none' :
+ 'inline';
+ },
+
+ moveLeft_() {
+ this.picker.moveLeft_(this);
+ },
+
+ moveRight_() {
+ this.picker.moveRight_(this);
+ },
+
+ onEnableChanged_() {
+ if (!this.enabled) {
+ this.$.left.style.display = 'none';
+ this.$.right.style.display = 'none';
+ }
+ this.picker.onEnableChanged_(this);
+ }
+ });
+
+ Polymer({
+ is: 'tr-ui-b-grouping-table-groupby-picker',
+
+ created() {
+ this.settingsKey_ = undefined;
+ },
+
+ get settingsKey() {
+ return this.settingsKey_;
+ },
+
+ set settingsKey(settingsKey) {
+ this.settingsKey_ = settingsKey;
+ if (this.$.container.children.length) {
+ this.restoreSetting_();
+ }
+ },
+
+ restoreSetting_() {
+ if (this.settingsKey_ === undefined) return;
+ this.currentGroupKeys = tr.b.Settings.get(this.settingsKey_,
+ this.currentGroupKeys);
+ },
+
+ get possibleGroups() {
+ return [...this.$.container.children].map(groupEl => groupEl.group);
+ },
+
+ set possibleGroups(possibleGroups) {
+ Polymer.dom(this.$.container).textContent = '';
+ for (let i = 0; i < possibleGroups.length; ++i) {
+ const groupEl = document.createElement(
+ 'tr-ui-b-grouping-table-groupby-picker-group');
+ groupEl.picker = this;
+ groupEl.group = possibleGroups[i];
+ Polymer.dom(this.$.container).appendChild(groupEl);
+ }
+ this.restoreSetting_();
+ this.updateFirstLast_();
+ },
+
+ updateFirstLast_() {
+ const groupEls = this.$.container.children;
+ const enabledGroupEls = [...groupEls].filter(el => el.enabled);
+ for (let i = 0; i < enabledGroupEls.length; ++i) {
+ enabledGroupEls[i].isFirst = i === 0;
+ enabledGroupEls[i].isLast = i === enabledGroupEls.length - 1;
+ }
+ },
+
+ get currentGroupKeys() {
+ return this.currentGroups.map(group => group.key);
+ },
+
+ get currentGroups() {
+ const groups = [];
+ for (const groupEl of this.$.container.children) {
+ if (groupEl.enabled) {
+ groups.push(groupEl.group);
+ }
+ }
+ return groups;
+ },
+
+ set currentGroupKeys(newKeys) {
+ if (!tr.b.compareArrays(this.currentGroupKeys, newKeys,
+ (x, y) => x.localeCompare(y))) {
+ return;
+ }
+
+ const possibleGroups = new Map();
+ for (const group of this.possibleGroups) {
+ possibleGroups.set(group.key, group);
+ }
+
+ const groupEls = this.$.container.children;
+
+ let i = 0;
+ for (i = 0; i < newKeys.length; ++i) {
+ const group = possibleGroups.get(newKeys[i]);
+ if (group === undefined) {
+ newKeys.splice(i, 1);
+ --i;
+ continue;
+ }
+ groupEls[i].group = group;
+ groupEls[i].enabled = true;
+ possibleGroups.delete(newKeys[i]);
+ }
+
+ for (const group of possibleGroups.values()) {
+ groupEls[i].group = group;
+ groupEls[i].enabled = false;
+ ++i;
+ }
+
+ this.updateFirstLast_();
+ this.onCurrentGroupsChanged_();
+ },
+
+ moveLeft_(groupEl) {
+ const reference = groupEl.previousSibling;
+ Polymer.dom(this.$.container).removeChild(groupEl);
+ Polymer.dom(this.$.container).insertBefore(groupEl, reference);
+ this.updateFirstLast_();
+
+ if (groupEl.enabled) {
+ this.onCurrentGroupsChanged_();
+ }
+ },
+
+ moveRight_(groupEl) {
+ const reference = groupEl.nextSibling.nextSibling;
+ Polymer.dom(this.$.container).removeChild(groupEl);
+ if (reference) {
+ Polymer.dom(this.$.container).insertBefore(groupEl, reference);
+ } else {
+ Polymer.dom(this.$.container).appendChild(groupEl);
+ }
+ this.updateFirstLast_();
+
+ if (groupEl.enabled) {
+ this.onCurrentGroupsChanged_();
+ }
+ },
+
+ onCurrentGroupsChanged_() {
+ this.dispatchEvent(new tr.b.Event('current-groups-changed'));
+ tr.b.Settings.set(this.settingsKey_, this.currentGroupKeys);
+ },
+
+ onEnableChanged_(groupEl) {
+ this.updateFirstLast_();
+ this.onCurrentGroupsChanged_();
+ }
+ });
+
+ return {
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table_groupby_picker_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table_groupby_picker_test.html
new file mode 100644
index 00000000000..727d430224f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/grouping_table_groupby_picker_test.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/grouping_table_groupby_picker.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('groupby-picker', function() {
+ const settingsKey = 'tr-ui-b-grouping-table-groupby-picker-test';
+ const picker = document.createElement(
+ 'tr-ui-b-grouping-table-groupby-picker');
+ tr.b.Settings.set(settingsKey, []);
+ picker.settingsKey = settingsKey;
+ picker.possibleGroups = [
+ {key: 'a', label: 'A'},
+ {key: 'b', label: 'B'},
+ {key: 'c', label: 'C'},
+ {key: 'd', label: 'D'},
+ {key: 'e', label: 'E'}
+ ];
+ assert.deepEqual([], picker.currentGroupKeys);
+ this.addHTMLOutput(picker);
+
+ let keys = ['a', 'b', 'c', 'd', 'e'];
+ picker.currentGroupKeys = keys;
+ assert.deepEqual(keys, picker.currentGroupKeys);
+
+ keys = ['e', 'd', 'c', 'b', 'a'];
+ picker.currentGroupKeys = keys;
+ assert.deepEqual(keys, picker.currentGroupKeys);
+
+ keys = [];
+ picker.currentGroupKeys = keys;
+ assert.deepEqual(keys, picker.currentGroupKeys);
+
+ keys = ['a', 'b', 'd'];
+ picker.currentGroupKeys = keys;
+ assert.deepEqual(keys, picker.currentGroupKeys);
+
+ tr.b.Settings.set(settingsKey, ['foo']);
+ picker.settingsKey = settingsKey;
+ assert.deepEqual([], picker.currentGroupKeys);
+
+ tr.b.Settings.set(settingsKey, ['e']);
+ picker.settingsKey = settingsKey;
+ assert.deepEqual(['e'], picker.currentGroupKeys);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/heading.html b/chromium/third_party/catapult/tracing/tracing/ui/base/heading.html
new file mode 100644
index 00000000000..9b625c61b03
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/heading.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel='import' href='/tracing/ui/base/constants.html'>
+
+<dom-module id='tr-ui-b-heading'>
+ <template>
+ <style>
+ :host {
+ background-color: rgb(243, 245, 247);
+ border-right: 1px solid #8e8e8e;
+ display: block;
+ height: 100%;
+ margin: 0;
+ padding: 0 5px 0 0;
+ }
+
+ heading {
+ display: block;
+ overflow-x: hidden;
+ text-align: left;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ #arrow {
+ flex: 0 0 auto;
+ font-family: sans-serif;
+ margin-left: 5px;
+ margin-right: 5px;
+ width: 8px;
+ }
+
+ #link, #heading_content {
+ display: none;
+ }
+ </style>
+ <heading id='heading' on-click='onHeadingDivClicked_'>
+ <span id='arrow'></span>
+ <span id='heading_content'></span>
+ <tr-ui-a-analysis-link id='link'></tr-ui-a-analysis-link>
+ </heading>
+ </template>
+</dom-module>
+<script>
+'use strict';
+Polymer({
+ is: 'tr-ui-b-heading',
+
+ DOWN_ARROW: String.fromCharCode(0x25BE),
+ RIGHT_ARROW: String.fromCharCode(0x25B8),
+
+ ready(viewport) {
+ // Minus 6 === 1px border + 5px padding right.
+ this.style.width = (tr.ui.b.constants.HEADING_WIDTH - 6) + 'px';
+
+ this.heading_ = '';
+ this.expanded_ = true;
+ this.arrowVisible_ = false;
+ this.selectionGenerator_ = undefined;
+
+ this.updateContents_();
+ },
+
+ get heading() {
+ return this.heading_;
+ },
+
+ set heading(text) {
+ if (this.heading_ === text) return;
+
+ this.heading_ = text;
+ this.updateContents_();
+ },
+
+ set arrowVisible(val) {
+ if (this.arrowVisible_ === val) return;
+
+ this.arrowVisible_ = !!val;
+ this.updateContents_();
+ },
+
+ set tooltip(text) {
+ this.$.heading.title = text;
+ },
+
+ set selectionGenerator(generator) {
+ if (this.selectionGenerator_ === generator) return;
+
+ this.selectionGenerator_ = generator;
+ this.updateContents_();
+ },
+
+ get expanded() {
+ return this.expanded_;
+ },
+
+ set expanded(expanded) {
+ if (this.expanded_ === expanded) return;
+
+ this.expanded_ = !!expanded;
+ this.updateContents_();
+ },
+
+ onHeadingDivClicked_() {
+ this.dispatchEvent(new tr.b.Event('heading-clicked', true));
+ },
+
+ updateContents_() {
+ if (this.arrowVisible_) {
+ this.$.arrow.style.display = '';
+ } else {
+ this.$.arrow.style.display = 'none';
+ this.$.heading.style.display = this.expanded_ ? '' : 'none';
+ }
+
+ if (this.arrowVisible_) {
+ Polymer.dom(this.$.arrow).textContent =
+ this.expanded_ ? this.DOWN_ARROW : this.RIGHT_ARROW;
+ }
+
+ this.$.link.style.display = 'none';
+ this.$.heading_content.style.display = 'none';
+
+ if (this.selectionGenerator_) {
+ this.$.link.style.display = 'inline-block';
+ this.$.link.selection = this.selectionGenerator_;
+ Polymer.dom(this.$.link).textContent = this.heading_;
+ } else {
+ this.$.heading_content.style.display = 'inline-block';
+ Polymer.dom(this.$.heading_content).textContent = this.heading_;
+ }
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/hot_key.html b/chromium/third_party/catapult/tracing/tracing/ui/base/hot_key.html
new file mode 100644
index 00000000000..3ffd96bfbe3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/hot_key.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/guid.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ function HotKey(dict) {
+ if (dict.eventType === undefined) {
+ throw new Error('eventType must be given');
+ }
+ if (dict.keyCode === undefined && dict.keyCodes === undefined) {
+ throw new Error('keyCode or keyCodes must be given');
+ }
+ if (dict.keyCode !== undefined && dict.keyCodes !== undefined) {
+ throw new Error('Only keyCode or keyCodes can be given');
+ }
+ if (dict.callback === undefined) {
+ throw new Error('callback must be given');
+ }
+
+ this.eventType_ = dict.eventType;
+ this.keyCodes_ = [];
+
+ if (dict.keyCode) {
+ this.pushKeyCode_(dict.keyCode);
+ } else if (dict.keyCodes) {
+ dict.keyCodes.forEach(this.pushKeyCode_, this);
+ }
+
+ this.useCapture_ = !!dict.useCapture;
+ this.callback_ = dict.callback;
+ this.thisArg_ = dict.thisArg !== undefined ? dict.thisArg : undefined;
+
+ this.helpText_ = dict.helpText !== undefined ? dict.helpText : undefined;
+ }
+
+ HotKey.prototype = {
+ get eventType() {
+ return this.eventType_;
+ },
+
+ get keyCodes() {
+ return this.keyCodes_;
+ },
+
+ get helpText() {
+ return this.helpText_;
+ },
+
+ call(e) {
+ this.callback_.call(this.thisArg_, e);
+ },
+
+ pushKeyCode_(keyCode) {
+ this.keyCodes_.push(keyCode);
+ }
+ };
+
+ return {
+ HotKey,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller.html b/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller.html
new file mode 100644
index 00000000000..f56631dc350
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller.html
@@ -0,0 +1,310 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/ui/base/hot_key.html">
+
+<dom-module id='tv-ui-b-hotkey-controller'>
+ <template>
+ <div></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+Polymer({
+ is: 'tv-ui-b-hotkey-controller',
+
+ created() {
+ this.isAttached_ = false;
+ this.globalMode_ = false;
+ this.slavedToParentController_ = undefined;
+ this.curHost_ = undefined;
+ this.childControllers_ = [];
+
+ this.bubblingKeyDownHotKeys_ = {};
+ this.capturingKeyDownHotKeys_ = {};
+ this.bubblingKeyPressHotKeys_ = {};
+ this.capturingKeyPressHotKeys_ = {};
+
+ this.onBubblingKeyDown_ = this.onKey_.bind(this, false);
+ this.onCapturingKeyDown_ = this.onKey_.bind(this, true);
+ this.onBubblingKeyPress_ = this.onKey_.bind(this, false);
+ this.onCapturingKeyPress_ = this.onKey_.bind(this, true);
+ },
+
+ attached() {
+ this.isAttached_ = true;
+
+ const host = this.findHost_();
+ if (host.__hotkeyController) {
+ throw new Error('Multiple hotkey controllers attached to this host');
+ }
+
+ host.__hotkeyController = this;
+ this.curHost_ = host;
+
+ let parentElement;
+ if (host.parentElement) {
+ parentElement = host.parentElement;
+ } else {
+ parentElement = Polymer.dom(host).parentNode.host;
+ }
+ const parentController = tr.b.getHotkeyControllerForElement(
+ parentElement);
+
+ if (parentController) {
+ this.slavedToParentController_ = parentController;
+ parentController.addChildController_(this);
+ return;
+ }
+
+ host.addEventListener('keydown', this.onBubblingKeyDown_, false);
+ host.addEventListener('keydown', this.onCapturingKeyDown_, true);
+ host.addEventListener('keypress', this.onBubblingKeyPress_, false);
+ host.addEventListener('keypress', this.onCapturingKeyPress_, true);
+ },
+
+ detached() {
+ this.isAttached_ = false;
+
+ const host = this.curHost_;
+ if (!host) return;
+
+ delete host.__hotkeyController;
+ this.curHost_ = undefined;
+
+ if (this.slavedToParentController_) {
+ this.slavedToParentController_.removeChildController_(this);
+ this.slavedToParentController_ = undefined;
+ return;
+ }
+
+ host.removeEventListener('keydown', this.onBubblingKeyDown_, false);
+ host.removeEventListener('keydown', this.onCapturingKeyDown_, true);
+ host.removeEventListener('keypress', this.onBubblingKeyPress_, false);
+ host.removeEventListener('keypress', this.onCapturingKeyPress_, true);
+ },
+
+ addChildController_(controller) {
+ const i = this.childControllers_.indexOf(controller);
+ if (i !== -1) {
+ throw new Error('Controller already registered');
+ }
+ this.childControllers_.push(controller);
+ },
+
+ removeChildController_(controller) {
+ const i = this.childControllers_.indexOf(controller);
+ if (i === -1) {
+ throw new Error('Controller not registered');
+ }
+ this.childControllers_.splice(i, 1);
+ return controller;
+ },
+
+ getKeyMapForEventType_(eventType, useCapture) {
+ if (eventType === 'keydown') {
+ if (!useCapture) {
+ return this.bubblingKeyDownHotKeys_;
+ }
+ return this.capturingKeyDownHotKeys_;
+ }
+ if (eventType === 'keypress') {
+ if (!useCapture) {
+ return this.bubblingKeyPressHotKeys_;
+ }
+ return this.capturingKeyPressHotKeys_;
+ }
+
+ throw new Error('Unsupported key event');
+ },
+
+ addHotKey(hotKey) {
+ if (!(hotKey instanceof tr.ui.b.HotKey)) {
+ throw new Error('hotKey must be a tr.ui.b.HotKey');
+ }
+
+ const keyMap = this.getKeyMapForEventType_(
+ hotKey.eventType, hotKey.useCapture);
+
+ for (let i = 0; i < hotKey.keyCodes.length; i++) {
+ const keyCode = hotKey.keyCodes[i];
+ if (keyMap[keyCode]) {
+ throw new Error('Key is already bound for keyCode=' + keyCode);
+ }
+ }
+
+ for (let i = 0; i < hotKey.keyCodes.length; i++) {
+ const keyCode = hotKey.keyCodes[i];
+ keyMap[keyCode] = hotKey;
+ }
+ return hotKey;
+ },
+
+ removeHotKey(hotKey) {
+ if (!(hotKey instanceof tr.ui.b.HotKey)) {
+ throw new Error('hotKey must be a tr.ui.b.HotKey');
+ }
+
+ const keyMap = this.getKeyMapForEventType_(
+ hotKey.eventType, hotKey.useCapture);
+
+ for (let i = 0; i < hotKey.keyCodes.length; i++) {
+ const keyCode = hotKey.keyCodes[i];
+ if (!keyMap[keyCode]) {
+ throw new Error('Key is not bound for keyCode=' + keyCode);
+ }
+ keyMap[keyCode] = hotKey;
+ }
+ for (let i = 0; i < hotKey.keyCodes.length; i++) {
+ const keyCode = hotKey.keyCodes[i];
+ delete keyMap[keyCode];
+ }
+ return hotKey;
+ },
+
+ get globalMode() {
+ return this.globalMode_;
+ },
+
+ set globalMode(globalMode) {
+ const wasAttached = this.isAttached_;
+ if (wasAttached) {
+ this.detached();
+ }
+ this.globalMode_ = !!globalMode;
+ if (wasAttached) {
+ this.attached();
+ }
+ },
+
+ get topmostConroller_() {
+ if (this.slavedToParentController_) {
+ return this.slavedToParentController_.topmostConroller_;
+ }
+ return this;
+ },
+
+ childRequestsGeneralFocus(child) {
+ const topmost = this.topmostConroller_;
+ if (topmost.curHost_) {
+ if (topmost.curHost_.hasAttribute('tabIndex')) {
+ topmost.curHost_.focus();
+ } else {
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ }
+ } else {
+ if (document.activeElement) {
+ document.activeElement.blur();
+ }
+ }
+ },
+
+ childRequestsBlur(child) {
+ child.blur();
+
+ const topmost = this.topmostConroller_;
+ if (topmost.curHost_) {
+ topmost.curHost_.focus();
+ }
+ },
+
+ findHost_() {
+ if (this.globalMode_) return document.body;
+ if (this.parentElement) return this.parentElement;
+ if (!Polymer.dom(this).parentNode) return this.host;
+
+ let node = this.parentNode;
+ while (Polymer.dom(node).parentNode) node = Polymer.dom(node).parentNode;
+ return node.host;
+ },
+
+ appendMatchingHotKeysTo_(matchedHotKeys,
+ useCapture, e) {
+ const localKeyMap = this.getKeyMapForEventType_(e.type, useCapture);
+ const localHotKey = localKeyMap[e.keyCode];
+ if (localHotKey) {
+ matchedHotKeys.push(localHotKey);
+ }
+
+ for (let i = 0; i < this.childControllers_.length; i++) {
+ const controller = this.childControllers_[i];
+ controller.appendMatchingHotKeysTo_(matchedHotKeys,
+ useCapture, e);
+ }
+ },
+
+ onKey_(useCapture, e) {
+ // Keys dispatched to INPUT elements still bubble, even when they're
+ // handled. So, skip any events that targeted the input element.
+ if (!useCapture && e.path[0].tagName === 'INPUT') return;
+
+ let sortedControllers;
+
+ const matchedHotKeys = [];
+ this.appendMatchingHotKeysTo_(matchedHotKeys, useCapture, e);
+
+ if (matchedHotKeys.length === 0) return false;
+
+ if (matchedHotKeys.length > 1) {
+ // TODO(nduca): To do support for coddling hotKeys, we need to
+ // sort the listeners by their capturing/bubbling order and then pick
+ // the one that would topologically win the tie, per DOM dispatch rules.
+ throw new Error('More than one hotKey is currently unsupported');
+ }
+
+
+ const hotKey = matchedHotKeys[0];
+
+ let prevented = 0;
+ prevented |= hotKey.call(e);
+
+ // We want to return false if preventDefaulted, or one of the handlers
+ // return false. But otherwise, we want to return undefiend.
+ return !prevented && e.defaultPrevented;
+ }
+});
+</script>
+<script>
+'use strict';
+tr.exportTo('tr.b', function() {
+ function getHotkeyControllerForElement(refElement) {
+ let curElement = refElement;
+ while (curElement) {
+ if (curElement.tagName === 'tv-ui-b-hotkey-controller') {
+ return curElement;
+ }
+
+ if (curElement.__hotkeyController) {
+ return curElement.__hotkeyController;
+ }
+
+ if (curElement.parentElement) {
+ curElement = curElement.parentElement;
+ continue;
+ }
+
+ // Probably inside a shadow
+ curElement = findHost(curElement);
+ }
+ return undefined;
+ }
+
+ function findHost(initialNode) {
+ let node = initialNode;
+ while (Polymer.dom(node).parentNode) {
+ node = Polymer.dom(node).parentNode;
+ }
+ return node.host;
+ }
+
+ return {
+ getHotkeyControllerForElement,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html
new file mode 100644
index 00000000000..cff10cb775c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/hotkey_controller_test.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/ui/base/hotkey_controller.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const KeyEventManager = tr.b.KeyEventManager;
+
+ function newKeyEvent(eventType, dict) {
+ const e = new tr.b.Event(eventType, true, true);
+ if (dict.keyCode === undefined) {
+ throw new Error('keyCode required');
+ }
+ e.keyCode = dict.keyCode;
+ return e;
+ }
+
+ test('simpleHotkeyManager', function() {
+ const rootElement = document.createElement('div');
+ Polymer.dom(document.body).appendChild(rootElement);
+ try {
+ const elementShadow = rootElement.createShadowRoot();
+
+ const hkc = document.createElement('tv-ui-b-hotkey-controller');
+ Polymer.dom(elementShadow).appendChild(hkc);
+
+ const subElement = document.createElement('div');
+ Polymer.dom(elementShadow).appendChild(subElement);
+
+ assert.strictEqual(tr.b.getHotkeyControllerForElement(subElement), hkc);
+
+ let didGetCalled = false;
+ hkc.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keydown',
+ keyCode: 73, useCapture: true,
+ callback() {
+ didGetCalled = true;
+ }
+ }));
+
+ // Ensure it is called when events target the root element.
+ let e = newKeyEvent('keydown', {keyCode: 73});
+ rootElement.dispatchEvent(e);
+ assert.isTrue(didGetCalled);
+
+ // Ensure it is still called when we target the sub element.
+ didGetCalled = false;
+ e = newKeyEvent('keydown', {keyCode: 73});
+ subElement.dispatchEvent(e);
+ assert.isTrue(didGetCalled);
+ } finally {
+ Polymer.dom(document.body).removeChild(rootElement);
+ }
+ });
+
+ test('nestedHotkeyController', function() {
+ const rootElement = document.createElement('div');
+ Polymer.dom(document.body).appendChild(rootElement);
+ try {
+ const elementShadow = rootElement.createShadowRoot();
+
+ const hkc = document.createElement('tv-ui-b-hotkey-controller');
+ Polymer.dom(elementShadow).appendChild(hkc);
+
+ const subElement = document.createElement('div');
+ Polymer.dom(elementShadow).appendChild(subElement);
+ assert.strictEqual(
+ tr.b.getHotkeyControllerForElement(elementShadow), hkc);
+
+ const subHKC = document.createElement('tv-ui-b-hotkey-controller');
+ Polymer.dom(subElement).appendChild(subHKC);
+
+ assert.strictEqual(
+ tr.b.getHotkeyControllerForElement(subElement), subHKC);
+
+ let didGetCalled = false;
+ subHKC.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keydown',
+ keyCode: 73, useCapture: true,
+ callback() {
+ didGetCalled = true;
+ }
+ }));
+
+ // Ensure it is called when events target the root element.
+ const e = newKeyEvent('keydown', {keyCode: 73});
+ rootElement.dispatchEvent(e);
+ assert.isTrue(didGetCalled);
+ } finally {
+ Polymer.dom(document.body).removeChild(rootElement);
+ }
+ });
+
+ test('inputInsideHKC', function() {
+ const rootElement = document.createElement('div');
+ Polymer.dom(document.body).appendChild(rootElement);
+ try {
+ const elementShadow = rootElement.createShadowRoot();
+
+ const hkc = document.createElement('tv-ui-b-hotkey-controller');
+ Polymer.dom(elementShadow).appendChild(hkc);
+
+ const inputEl = document.createElement('input');
+ Polymer.dom(elementShadow).appendChild(inputEl);
+
+ let didGetCalled = false;
+ hkc.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keypress',
+ keyCode: 'a'.charCodeAt(0), useCapture: false,
+ callback() {
+ didGetCalled = true;
+ }
+ }));
+
+ // Ensure it is called when events target the root element.
+ didGetCalled = false;
+ let e = newKeyEvent('keypress', {keyCode: 'a'.charCodeAt(0)});
+ rootElement.dispatchEvent(e);
+ assert.isTrue(didGetCalled);
+
+ // Handler should NOT be called when events target the input element.
+ didGetCalled = false;
+ e = newKeyEvent('keypress', {keyCode: 'a'.charCodeAt(0)});
+ inputEl.dispatchEvent(e);
+ assert.isFalse(didGetCalled);
+ } finally {
+ Polymer.dom(document.body).removeChild(rootElement);
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar.html b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar.html
new file mode 100644
index 00000000000..3a4894278be
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<dom-module id='tr-ui-b-info-bar'>
+ <template>
+ <style>
+ :host {
+ align-items: center;
+ flex: 0 0 auto;
+ background-color: rgb(252, 235, 162);
+ border-bottom: 1px solid #A3A3A3;
+ border-left: 1px solid white;
+ border-right: 1px solid #A3A3A3;
+ border-top: 1px solid white;
+ display: flex;
+ height: 26px;
+ padding: 0 3px 0 3px;
+ }
+
+ :host([hidden]) {
+ display: none !important;
+ }
+
+ #message { flex: 1 1 auto; }
+ </style>
+
+ <span id='message'></span>
+ <span id='buttons'></span>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-info-bar',
+
+ ready() {
+ this.messageEl_ = this.$.message;
+ this.buttonsEl_ = this.$.buttons;
+
+ this.message = '';
+ },
+
+ get message() {
+ return Polymer.dom(this.messageEl_).textContent;
+ },
+
+ set message(message) {
+ Polymer.dom(this.messageEl_).textContent = message;
+ },
+
+ get visible() {
+ return !this.hidden;
+ },
+
+ set visible(visible) {
+ this.hidden = !visible;
+ },
+
+ removeAllButtons() {
+ Polymer.dom(this.buttonsEl_).textContent = '';
+ },
+
+ addButton(text, clickCallback) {
+ const button = document.createElement('button');
+ Polymer.dom(button).textContent = text;
+ button.addEventListener('click', event => clickCallback(event, this));
+ Polymer.dom(this.buttonsEl_).appendChild(button);
+ return button;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group.html b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group.html
new file mode 100644
index 00000000000..d095e4d99f9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel='import' href='/tracing/ui/base/info_bar.html'>
+
+<dom-module id='tr-ui-b-info-bar-group'>
+ <template>
+ <style>
+ :host {
+ flex: 0 0 auto;
+ flex-direction: column;
+ display: flex;
+ }
+ </style>
+ <div id='messages'></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+Polymer({
+ is: 'tr-ui-b-info-bar-group',
+
+ ready() {
+ this.messages_ = [];
+ },
+
+ clearMessages() {
+ this.messages_ = [];
+ this.updateContents_();
+ },
+
+ addMessage(text, opt_buttons) {
+ opt_buttons = opt_buttons || [];
+ for (let i = 0; i < opt_buttons.length; i++) {
+ if (opt_buttons[i].buttonText === undefined) {
+ throw new Error('buttonText must be provided');
+ }
+ if (opt_buttons[i].onClick === undefined) {
+ throw new Error('onClick must be provided');
+ }
+ }
+
+ this.messages_.push({
+ text,
+ buttons: opt_buttons || []
+ });
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ Polymer.dom(this.$.messages).textContent = '';
+ this.messages_.forEach(function(message) {
+ const bar = document.createElement('tr-ui-b-info-bar');
+ bar.message = message.text;
+ bar.visible = true;
+
+ message.buttons.forEach(function(button) {
+ bar.addButton(button.buttonText, button.onClick);
+ }, this);
+
+ Polymer.dom(this.$.messages).appendChild(bar);
+ }, this);
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html
new file mode 100644
index 00000000000..304d48ede37
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_group_test.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/info_bar_group.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('group-instantiate', function() {
+ const infoBarGroup = document.createElement('tr-ui-b-info-bar-group');
+ infoBarGroup.addMessage(
+ 'Message 1',
+ [{buttonText: 'ok', onClick() {}}]);
+ infoBarGroup.addMessage(
+ 'Message 2',
+ [{buttonText: 'button 2', onClick() {}}]);
+ this.addHTMLOutput(infoBarGroup);
+ });
+
+ test('group-populate-then-clear', function() {
+ const infoBarGroup = document.createElement('tr-ui-b-info-bar-group');
+ infoBarGroup.addMessage(
+ 'Message 1',
+ [{buttonText: 'ok', onClick() {}}]);
+ infoBarGroup.addMessage(
+ 'Message 2',
+ [{buttonText: 'button 2', onClick() {}}]);
+ infoBarGroup.clearMessages();
+ assert.strictEqual(infoBarGroup.children.length, 0);
+ });
+
+ test('group-populate-clear-repopulate', function() {
+ const infoBarGroup = document.createElement('tr-ui-b-info-bar-group');
+ infoBarGroup.addMessage(
+ 'Message 1',
+ [{buttonText: 'ok', onClick() {}}]);
+ infoBarGroup.addMessage(
+ 'Message 2',
+ [{buttonText: 'button 2', onClick() {}}]);
+ infoBarGroup.clearMessages();
+ infoBarGroup.addMessage(
+ 'Message 1',
+ [{buttonText: 'ok', onClick() {}}]);
+ this.addHTMLOutput(infoBarGroup);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_test.html
new file mode 100644
index 00000000000..94b19482ec8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/info_bar_test.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/info_bar.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const infoBar = document.createElement('tr-ui-b-info-bar');
+ infoBar.message = 'This is an info';
+ infoBar.visible = true;
+ this.addHTMLOutput(infoBar);
+ });
+
+ test('buttons', function() {
+ const infoBar = document.createElement('tr-ui-b-info-bar');
+ infoBar.visible = true;
+ infoBar.message = 'This is an info bar with buttons';
+ let didClick = false;
+ const button = infoBar.addButton('More info...', function() {
+ didClick = true;
+ });
+ button.click();
+ assert.isTrue(didClick);
+ this.addHTMLOutput(infoBar);
+ });
+
+ test('hiding', function() {
+ const infoBar = document.createElement('tr-ui-b-info-bar');
+ infoBar.message = 'This is an info bar';
+ infoBar.visible = true;
+ this.addHTMLOutput(infoBar);
+
+ assert.strictEqual(getComputedStyle(infoBar).display, 'flex');
+
+ infoBar.visible = false;
+ assert.strictEqual(getComputedStyle(infoBar).display, 'none');
+
+ infoBar.visible = true;
+ assert.strictEqual(getComputedStyle(infoBar).display, 'flex');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/line_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/base/line_chart.html
new file mode 100644
index 00000000000..e02f4413bb1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/line_chart.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/chart_base_2d_brushable_x.html">
+<link rel="import" href="/tracing/ui/base/column_chart.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const LineChart = tr.ui.b.define('line-chart', tr.ui.b.ChartBase2DBrushX);
+
+ LineChart.prototype = {
+ __proto__: tr.ui.b.ChartBase2DBrushX.prototype,
+
+ decorate() {
+ super.decorate();
+ this.enableHoverBox = true;
+ this.displayXInHover = false;
+ },
+
+ get defaultGraphWidth() {
+ return 20 * this.data_.length;
+ },
+
+ get defaultGraphHeight() {
+ return 100;
+ },
+
+ drawHoverValueBox_(circle) {
+ tr.ui.b.ColumnChart.prototype.drawHoverValueBox_.call(this, circle);
+ },
+
+ clearHoverValueBox_(circle) {
+ tr.ui.b.ColumnChart.prototype.clearHoverValueBox_.call(this, circle);
+ },
+
+ updateDataContents_(dataSel) {
+ dataSel.selectAll('*').remove();
+ const dataBySeriesKey = this.getDataBySeriesKey_();
+ const seriesKeys = [...this.seriesByKey_.keys()];
+ const pathsSel = dataSel.selectAll('path').data(seriesKeys);
+ pathsSel.enter()
+ .append('path')
+ .style('fill', 'none')
+ .style('stroke-width', '1.5px')
+ .style('stroke', key => this.getDataSeries(key).color)
+ .attr('d', key => {
+ const line = d3.svg.line()
+ .x(d => this.xScale_(d.x))
+ .y(d => this.yScale_(this.dataRange.clamp(d[key])));
+ return line(dataBySeriesKey[key]);
+ });
+ pathsSel.exit().remove();
+
+ if (this.enableHoverBox) {
+ for (let index = 0; index < this.data_.length; ++index) {
+ const datum = this.data_[index];
+ const x = this.getXForDatum_(datum, index);
+ for (const [key, value] of Object.entries(datum)) {
+ if (key === 'x') continue;
+ if (value === undefined) continue;
+ const color = this.getDataSeries(key).color;
+ const circle = document.createElementNS(
+ 'http://www.w3.org/2000/svg', 'circle');
+ circle.setAttribute('cx', this.xScale_(x));
+ circle.setAttribute('cy',
+ this.yScale_(this.dataRange.clamp(value)));
+ circle.setAttribute('r', 5);
+ circle.style.fill = color;
+ circle.datum = datum;
+ circle.key = key;
+ circle.value = datum[key];
+ circle.leftPx = this.xScale_(x);
+ circle.widthPx = 0;
+ circle.color = color;
+ circle.topPx = this.yScale_(this.dataRange.clamp(value));
+ circle.heightPx = 0;
+ circle.addEventListener(
+ 'mouseenter', () => this.drawHoverValueBox_(circle));
+ circle.addEventListener(
+ 'mouseleave', () => this.clearHoverValueBox_(circle));
+ dataSel[0][0].appendChild(circle);
+ }
+ }
+ }
+ }
+ };
+
+ return {
+ LineChart,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/line_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/line_chart_test.html
new file mode 100644
index 00000000000..411e46fb5dc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/line_chart_test.html
@@ -0,0 +1,180 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/base/line_chart.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ test('instantiation_singleSeries', function() {
+ const chart = new tr.ui.b.LineChart();
+ chart.displayXInHover = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, y: 100},
+ {x: 20, y: 110},
+ {x: 30, y: 100},
+ {x: 40, y: 50}
+ ];
+ });
+
+ test('instantiation_twoSeries', function() {
+ const chart = new tr.ui.b.LineChart();
+ chart.displayXInHover = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 100, beta: 50},
+ {x: 20, alpha: 110, beta: 75},
+ {x: 30, alpha: 100, beta: 125},
+ {x: 40, alpha: 50, beta: 125}
+ ];
+
+ const r = new tr.b.math.Range();
+ r.addValue(20);
+ r.addValue(40);
+ chart.brushedRange = r;
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueSparse', function() {
+ const chart = new tr.ui.b.LineChart();
+ chart.displayXInHover = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 20, beta: undefined},
+ {x: 20, alpha: undefined, beta: 10},
+ {x: 30, alpha: 10, beta: undefined},
+ {x: 45, alpha: undefined, beta: 20},
+ {x: 50, alpha: 30, beta: 30}
+ ];
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueNotSparse', function() {
+ const chart = new tr.ui.b.LineChart();
+ chart.displayXInHover = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, alpha: 20, beta: 40},
+ {x: 20, alpha: undefined, beta: 10},
+ {x: 30, alpha: 10, beta: undefined},
+ {x: 45, alpha: undefined, beta: 20},
+ {x: 50, alpha: 30, beta: undefined}
+ ];
+ });
+
+ test('brushRangeFromIndices', function() {
+ const chart = new tr.ui.b.LineChart();
+ chart.displayXInHover = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, value: 50},
+ {x: 30, value: 60},
+ {x: 70, value: 70},
+ {x: 80, value: 80},
+ {x: 120, value: 90}
+ ];
+ let r = new tr.b.math.Range();
+
+ // Range min should be 10.
+ r = chart.computeBrushRangeFromIndices(-2, 1);
+ assert.strictEqual(r.min, 10);
+
+ // Range max should be 120.
+ r = chart.computeBrushRangeFromIndices(3, 10);
+ assert.strictEqual(r.max, 120);
+
+ // Range should be [10, 120]
+ r = chart.computeBrushRangeFromIndices(-2, 10);
+ assert.strictEqual(r.min, 10);
+ assert.strictEqual(r.max, 120);
+
+ // Range should be [20, 100]
+ r = chart.computeBrushRangeFromIndices(1, 3);
+ assert.strictEqual(r.min, 20);
+ assert.strictEqual(r.max, 100);
+ });
+
+ test('instantiation_interactiveBrushing', function() {
+ const chart = new tr.ui.b.LineChart();
+ chart.displayXInHover = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, value: 50},
+ {x: 20, value: 60},
+ {x: 30, value: 80},
+ {x: 40, value: 20},
+ {x: 50, value: 30},
+ {x: 60, value: 20},
+ {x: 70, value: 15},
+ {x: 80, value: 20}
+ ];
+
+ let mouseDownIndex = undefined;
+ let curMouseIndex = undefined;
+
+ function updateBrushedRange() {
+ if (mouseDownIndex === undefined) {
+ chart.brushedRange = new tr.b.math.Range();
+ return;
+ }
+ chart.brushedRange = chart.computeBrushRangeFromIndices(
+ mouseDownIndex, curMouseIndex);
+ }
+
+ chart.addEventListener('item-mousedown', function(e) {
+ mouseDownIndex = e.index;
+ curMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mousemove', function(e) {
+ if (e.button === undefined) return;
+ curMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mouseup', function(e) {
+ curMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ });
+
+ test('overrideDataRange', function() {
+ let chart = new tr.ui.b.LineChart();
+ chart.displayXInHover = true;
+ this.addHTMLOutput(chart);
+ chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(10, 90);
+ chart.data = [
+ {x: 0, value: 0},
+ {x: 1, value: 100},
+ ];
+
+ chart = new tr.ui.b.LineChart();
+ chart.displayXInHover = true;
+ this.addHTMLOutput(chart);
+ chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(-10, 100);
+ chart.data = [
+ {x: 0, value: 0},
+ {x: 1, value: 50},
+ ];
+ });
+
+ test('sizeInBytes', function() {
+ const chart = new tr.ui.b.LineChart();
+ chart.unit = tr.b.Unit.byName.sizeInBytes;
+ chart.yLogScaleBase = 2;
+ chart.graphHeight = 400;
+ chart.isYLogScale = true;
+ chart.hideLegend = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 0, value: 1},
+ {x: 1, value: 1 << 10},
+ {x: 2, value: 1 << 20},
+ {x: 3, value: 1 << 30},
+ ];
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/list_view.html b/chromium/third_party/catapult/tracing/tracing/ui/base/list_view.html
new file mode 100644
index 00000000000..6e2d1652016
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/list_view.html
@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/ui/base/container_that_decorates_its_children.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Simple list view.
+ */
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * @constructor
+ */
+ const ListView = tr.ui.b.define(
+ 'x-list-view', tr.ui.b.ContainerThatDecoratesItsChildren);
+
+ ListView.prototype = {
+ __proto__: tr.ui.b.ContainerThatDecoratesItsChildren.prototype,
+
+ decorate() {
+ tr.ui.b.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);
+
+ Polymer.dom(this).classList.add('x-list-view');
+ this.style.display = 'block';
+ this.style.userSelect = 'none';
+ this.style.outline = 'none';
+ this.onItemClicked_ = this.onItemClicked_.bind(this);
+ this.onKeyDown_ = this.onKeyDown_.bind(this);
+ this.tabIndex = 0;
+ this.addEventListener('keydown', this.onKeyDown_);
+
+ this.selectionChanged_ = false;
+ },
+
+ decorateChild_(item) {
+ Polymer.dom(item).classList.add('list-item');
+ item.style.paddingTop = '2px';
+ item.style.paddingRight = '4px';
+ item.style.paddingBottom = '2px';
+ item.style.paddingLeft = '4px';
+ item.addEventListener('click', this.onItemClicked_, true);
+
+ Object.defineProperty(
+ item,
+ 'selected', {
+ configurable: true,
+ get: () => item.hasAttribute('selected'),
+ set: value => {
+ // |this| is the ListView.
+ const oldSelection = this.selectedElement;
+ if (oldSelection && oldSelection !== item && value) {
+ Polymer.dom(this.selectedElement).removeAttribute('selected');
+ }
+ if (value) {
+ Polymer.dom(item).setAttribute('selected', 'selected');
+ item.style.backgroundColor = 'rgb(171, 217, 202)';
+ item.style.outline = '1px dotted rgba(0,0,0,0.1)';
+ item.style.outlineOffset = 0;
+ } else {
+ Polymer.dom(item).removeAttribute('selected');
+ item.style.backgroundColor = '';
+ }
+ const newSelection = this.selectedElement;
+ if (newSelection !== oldSelection) {
+ tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
+ }
+ },
+ });
+ },
+
+ undecorateChild_(item) {
+ this.selectionChanged_ |= item.selected;
+
+ Polymer.dom(item).classList.remove('list-item');
+ item.removeEventListener('click', this.onItemClicked_);
+ delete item.selected;
+ },
+
+ beginDecorating_() {
+ this.selectionChanged_ = false;
+ },
+
+ doneDecoratingForNow_() {
+ if (this.selectionChanged_) {
+ tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
+ }
+ },
+
+ get selectedElement() {
+ const el = Polymer.dom(this).querySelector('.list-item[selected]');
+ if (!el) return undefined;
+ return el;
+ },
+
+ set selectedElement(el) {
+ if (!el) {
+ if (this.selectedElement) {
+ this.selectedElement.selected = false;
+ }
+ return;
+ }
+
+ if (el.parentElement !== this) {
+ throw new Error(
+ 'Can only select elements that are children of this list view');
+ }
+ el.selected = true;
+ },
+
+ getElementByIndex(index) {
+ return Polymer.dom(this)
+ .querySelector('.list-item:nth-child(' + index + ')');
+ },
+
+ clear() {
+ const changed = this.selectedElement !== undefined;
+ tr.ui.b.ContainerThatDecoratesItsChildren.prototype.clear.call(this);
+ if (changed) {
+ tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
+ }
+ },
+
+ onItemClicked_(e) {
+ const currentSelectedElement = this.selectedElement;
+ if (currentSelectedElement) {
+ Polymer.dom(currentSelectedElement).removeAttribute('selected');
+ }
+ let element = e.target;
+ while (element.parentElement !== this) {
+ element = element.parentElement;
+ }
+ if (element !== currentSelectedElement) {
+ Polymer.dom(element).setAttribute('selected', 'selected');
+ }
+ tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
+ },
+
+ onKeyDown_(e) {
+ if (this.selectedElement === undefined) return;
+
+ if (e.keyCode === 38) { // Up arrow.
+ const prev = Polymer.dom(this.selectedElement).previousSibling;
+ if (prev) {
+ prev.selected = true;
+ tr.ui.b.scrollIntoViewIfNeeded(prev);
+ e.preventDefault();
+ return true;
+ }
+ } else if (e.keyCode === 40) { // Down arrow.
+ const next = Polymer.dom(this.selectedElement).nextSibling;
+ if (next) {
+ next.selected = true;
+ tr.ui.b.scrollIntoViewIfNeeded(next);
+ e.preventDefault();
+ return true;
+ }
+ }
+ },
+
+ addItem(textContent) {
+ const item = document.createElement('div');
+ Polymer.dom(item).textContent = textContent;
+ Polymer.dom(this).appendChild(item);
+ item.style.userSelect = 'none';
+ return item;
+ }
+
+ };
+
+ return {
+ ListView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/list_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/list_view_test.html
new file mode 100644
index 00000000000..685eefc9472
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/list_view_test.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/list_view.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ListView = tr.ui.b.ListView;
+
+ test('instantiate', function() {
+ const view = new ListView();
+ const i1 = view.addItem('item 1');
+ const i2 = view.addItem('item 2');
+ const i3 = view.addItem('item 3');
+ this.addHTMLOutput(view);
+ });
+
+ test('programmaticSelection', function() {
+ const view = new ListView();
+ const i1 = view.addItem('item 1');
+ const i2 = view.addItem('item 2');
+ const i3 = view.addItem('item 3');
+
+ i2.selected = true;
+ assert.isTrue(i2.hasAttribute('selected'));
+ i3.selected = true;
+ assert.isFalse(i2.hasAttribute('selected'));
+ assert.isTrue(i3.hasAttribute('selected'));
+ });
+
+ test('clickSelection', function() {
+ const view = new ListView();
+ let didFireSelectionChange = false;
+ view.addEventListener('selection-changed', function() {
+ didFireSelectionChange = true;
+ });
+ const i1 = view.addItem('item 1');
+ const i2 = view.addItem('item 2');
+ const i3 = view.addItem('item 3');
+
+ didFireSelectionChange = false;
+ i2.click();
+ assert.isTrue(didFireSelectionChange);
+ assert.strictEqual(view.selectedElement, i2);
+
+ didFireSelectionChange = false;
+ i3.click();
+ assert.isTrue(didFireSelectionChange);
+ assert.strictEqual(view.selectedElement, i3);
+
+ // Click the same target again.
+ didFireSelectionChange = false;
+ i3.click();
+ assert.isTrue(didFireSelectionChange);
+ assert.isUndefined(view.selectedElement);
+
+ didFireSelectionChange = false;
+ i1.click();
+ assert.isTrue(didFireSelectionChange);
+ assert.strictEqual(view.selectedElement, i1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_icon.html b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_icon.html
new file mode 100644
index 00000000000..bf32a7f25fe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_icon.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/mouse_modes.html">
+
+<dom-module id='tr-ui-b-mouse-mode-icon'>
+ <template>
+ <style>
+ :host {
+ display: block;
+ background-image: url(../images/ui-states.png);
+ width: 27px;
+ height: 30px;
+ }
+ :host.active {
+ cursor: auto;
+ }
+ </style>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-mouse-mode-icon',
+
+ properties: {
+ modeName: {
+ type: String,
+ reflectToAttribute: true,
+ observer: 'modeNameChanged'
+ },
+ },
+
+ created() {
+ this.active_ = false;
+ this.acceleratorKey_ = undefined;
+ },
+
+ ready() {
+ this.updateContents_();
+ },
+
+ get mode() {
+ return tr.ui.b.MOUSE_SELECTOR_MODE[this.modeName];
+ },
+
+ set mode(mode) {
+ const modeInfo = tr.ui.b.MOUSE_SELECTOR_MODE_INFOS[mode];
+ if (modeInfo === undefined) {
+ throw new Error('Unknown mode');
+ }
+ this.modeName = modeInfo.name;
+ },
+
+ modeNameChanged() {
+ this.updateContents_();
+ },
+
+ get active() {
+ return this.active_;
+ },
+
+ set active(active) {
+ this.active_ = !!active;
+ if (this.active_) {
+ Polymer.dom(this).classList.add('active');
+ } else {
+ Polymer.dom(this).classList.remove('active');
+ }
+ this.updateContents_();
+ },
+
+ get acceleratorKey() {
+ return this.acceleratorKey_;
+ },
+
+ set acceleratorKey(acceleratorKey) {
+ this.acceleratorKey_ = acceleratorKey;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ if (this.modeName === undefined) return;
+
+ const mode = this.mode;
+ if (mode === undefined) {
+ throw new Error('Invalid mode');
+ }
+
+ const modeInfo = tr.ui.b.MOUSE_SELECTOR_MODE_INFOS[mode];
+ if (!modeInfo) {
+ throw new Error('Invalid mode');
+ }
+
+ let title = modeInfo.title;
+ if (this.acceleratorKey_) {
+ title = title + ' (' + this.acceleratorKey_ + ')';
+ }
+ this.title = title;
+
+ let bp;
+ if (this.active_) {
+ bp = modeInfo.activeBackgroundPosition;
+ } else {
+ bp = modeInfo.defaultBackgroundPosition;
+ }
+ this.style.backgroundPosition = bp;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_icon_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_icon_test.html
new file mode 100644
index 00000000000..047d5af22b9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_icon_test.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_icon.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const MOUSE_SELECTOR_MODE = tr.ui.b.MOUSE_SELECTOR_MODE;
+
+ test('inactive', function() {
+ const icon = document.createElement('tr-ui-b-mouse-mode-icon');
+ icon.mode = MOUSE_SELECTOR_MODE.SELECTION;
+ assert.strictEqual(icon.modeName, 'SELECTION');
+ icon.acceleratorKey = 'a';
+ this.addHTMLOutput(icon);
+ });
+
+ test('active', function() {
+ const icon = document.createElement('tr-ui-b-mouse-mode-icon');
+ icon.mode = MOUSE_SELECTOR_MODE.SELECTION;
+ assert.strictEqual(icon.modeName, 'SELECTION');
+ icon.active = true;
+ this.addHTMLOutput(icon);
+ });
+
+ test('modeNameSetter', function() {
+ const icon = document.createElement('tr-ui-b-mouse-mode-icon');
+ Polymer.dom(icon).setAttribute('mode-name', 'SELECTION');
+ this.addHTMLOutput(icon);
+
+ return Promise.resolve().then(function() {
+ assert.strictEqual(icon.mode, 1);
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_selector.html b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_selector.html
new file mode 100644
index 00000000000..4ee7348833f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_selector.html
@@ -0,0 +1,577 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/hotkey_controller.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_icon.html">
+<link rel="import" href="/tracing/ui/base/mouse_modes.html">
+<link rel="import" href="/tracing/ui/base/mouse_tracker.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<dom-module id='tr-ui-b-mouse-mode-selector'>
+ <template>
+ <style>
+ :host {
+
+ -webkit-user-drag: element;
+ -webkit-user-select: none;
+
+ background: #DDD;
+ border: 1px solid #BBB;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px rgba(0,0,0,0.2);
+ left: calc(100% - 120px);
+ position: absolute;
+ top: 100px;
+ user-select: none;
+ width: 29px;
+ z-index: 20;
+ }
+
+ .drag-handle {
+ background: url(../images/ui-states.png) 2px 3px no-repeat;
+ background-repeat: no-repeat;
+ border-bottom: 1px solid #BCBCBC;
+ cursor: move;
+ display: block;
+ height: 13px;
+ width: 27px;
+ }
+
+ .tool-button {
+ background-position: center center;
+ background-repeat: no-repeat;
+ border-bottom: 1px solid #BCBCBC;
+ border-top: 1px solid #F1F1F1;
+ cursor: pointer;
+ }
+
+ .buttons > .tool-button:last-child {
+ border-bottom: none;
+ }
+
+ </style>
+ <div class="drag-handle"></div>
+ <div class="buttons">
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const MOUSE_SELECTOR_MODE = tr.ui.b.MOUSE_SELECTOR_MODE;
+ const MOUSE_SELECTOR_MODE_INFOS = tr.ui.b.MOUSE_SELECTOR_MODE_INFOS;
+
+
+ const MIN_MOUSE_SELECTION_DISTANCE = 4;
+
+ const MODIFIER = {
+ SHIFT: 0x1,
+ SPACE: 0x2,
+ CMD_OR_CTRL: 0x4
+ };
+
+ function isCmdOrCtrlPressed(event) {
+ if (tr.isMac) return event.metaKey;
+ return event.ctrlKey;
+ }
+
+ /**
+ * Provides a panel for switching the interaction mode of the mouse.
+ * It handles the user interaction and dispatches events for the various
+ * modes.
+ */
+ Polymer({
+ is: 'tr-ui-b-mouse-mode-selector',
+
+ created() {
+ this.supportedModeMask_ = MOUSE_SELECTOR_MODE.ALL_MODES;
+
+ this.initialRelativeMouseDownPos_ = {x: 0, y: 0};
+
+ this.defaultMode_ = MOUSE_SELECTOR_MODE.PANSCAN;
+ this.settingsKey_ = undefined;
+ this.mousePos_ = {x: 0, y: 0};
+ this.mouseDownPos_ = {x: 0, y: 0};
+
+ this.onMouseDown_ = this.onMouseDown_.bind(this);
+ this.onMouseMove_ = this.onMouseMove_.bind(this);
+ this.onMouseUp_ = this.onMouseUp_.bind(this);
+
+ this.onKeyDown_ = this.onKeyDown_.bind(this);
+ this.onKeyUp_ = this.onKeyUp_.bind(this);
+
+ this.mode_ = undefined;
+ this.modeToKeyCodeMap_ = {};
+ this.modifierToModeMap_ = {};
+
+ this.targetElement_ = undefined;
+ this.modeBeforeAlternativeModeActivated_ = null;
+
+ this.isInteracting_ = false;
+ this.isClick_ = false;
+ },
+
+ ready() {
+ this.buttonsEl_ = Polymer.dom(this.root).querySelector('.buttons');
+ this.dragHandleEl_ = Polymer.dom(this.root).querySelector(
+ '.drag-handle');
+ this.supportedModeMask = MOUSE_SELECTOR_MODE.ALL_MODES;
+
+ this.dragHandleEl_.addEventListener('mousedown',
+ this.onDragHandleMouseDown_.bind(this));
+
+ this.buttonsEl_.addEventListener('mouseup', this.onButtonMouseUp_);
+ this.buttonsEl_.addEventListener('mousedown', this.onButtonMouseDown_);
+ this.buttonsEl_.addEventListener('click', this.onButtonPress_.bind(this));
+ },
+
+ attached() {
+ document.addEventListener('keydown', this.onKeyDown_);
+ document.addEventListener('keyup', this.onKeyUp_);
+ },
+
+ detached() {
+ document.removeEventListener('keydown', this.onKeyDown_);
+ document.removeEventListener('keyup', this.onKeyUp_);
+ },
+
+ get targetElement() {
+ return this.targetElement_;
+ },
+
+ set targetElement(target) {
+ if (this.targetElement_) {
+ this.targetElement_.removeEventListener('mousedown', this.onMouseDown_);
+ }
+ this.targetElement_ = target;
+ if (this.targetElement_) {
+ this.targetElement_.addEventListener('mousedown', this.onMouseDown_);
+ }
+ },
+
+ get defaultMode() {
+ return this.defaultMode_;
+ },
+
+ set defaultMode(defaultMode) {
+ this.defaultMode_ = defaultMode;
+ },
+
+ get settingsKey() {
+ return this.settingsKey_;
+ },
+
+ set settingsKey(settingsKey) {
+ this.settingsKey_ = settingsKey;
+ if (!this.settingsKey_) return;
+
+ let mode = tr.b.Settings.get(this.settingsKey_ + '.mode', undefined);
+ // Modes changed from 1,2,3,4 to 0x1, 0x2, 0x4, 0x8. Fix any stray
+ // settings to the best of our abilities.
+ if (MOUSE_SELECTOR_MODE_INFOS[mode] === undefined) {
+ mode = undefined;
+ }
+
+ // Restoring settings against unsupported modes should just go back to the
+ // default mode.
+ if ((mode & this.supportedModeMask_) === 0) {
+ mode = undefined;
+ }
+
+ if (!mode) mode = this.defaultMode_;
+ this.mode = mode;
+
+ const pos = tr.b.Settings.get(this.settingsKey_ + '.pos', undefined);
+ if (pos) this.pos = pos;
+ },
+
+ get supportedModeMask() {
+ return this.supportedModeMask_;
+ },
+
+ /**
+ * Sets the supported modes. Should be an OR-ing of MOUSE_SELECTOR_MODE
+ * values.
+ */
+ set supportedModeMask(supportedModeMask) {
+ if (this.mode && (supportedModeMask & this.mode) === 0) {
+ throw new Error('supportedModeMask must include current mode.');
+ }
+
+ function createButtonForMode(mode) {
+ return button;
+ }
+
+ this.supportedModeMask_ = supportedModeMask;
+ Polymer.dom(this.buttonsEl_).textContent = '';
+ for (const modeName in MOUSE_SELECTOR_MODE) {
+ if (modeName === 'ALL_MODES') continue;
+
+ const mode = MOUSE_SELECTOR_MODE[modeName];
+ if ((this.supportedModeMask_ & mode) === 0) continue;
+
+ const button = document.createElement('tr-ui-b-mouse-mode-icon');
+ button.mode = mode;
+ Polymer.dom(button).classList.add('tool-button');
+
+ Polymer.dom(this.buttonsEl_).appendChild(button);
+ }
+ },
+
+ getButtonForMode_(mode) {
+ for (let i = 0; i < this.buttonsEl_.children.length; i++) {
+ const buttonEl = this.buttonsEl_.children[i];
+ if (buttonEl.mode === mode) {
+ return buttonEl;
+ }
+ }
+ return undefined;
+ },
+
+ get mode() {
+ return this.currentMode_;
+ },
+
+ set mode(newMode) {
+ if (newMode !== undefined) {
+ if (typeof newMode !== 'number') {
+ throw new Error('Mode must be a number');
+ }
+ if ((newMode & this.supportedModeMask_) === 0) {
+ throw new Error('Cannot switch to this mode, it is not supported');
+ }
+ if (MOUSE_SELECTOR_MODE_INFOS[newMode] === undefined) {
+ throw new Error('Unrecognized mode');
+ }
+ }
+
+ let modeInfo;
+
+ if (this.currentMode_ === newMode) return;
+
+ if (this.currentMode_) {
+ const buttonEl = this.getButtonForMode_(this.currentMode_);
+ if (buttonEl) buttonEl.active = false;
+
+ // End event.
+ if (this.isInteracting_) {
+ const mouseEvent = this.createEvent_(
+ MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.end);
+ this.dispatchEvent(mouseEvent);
+ }
+
+ // Exit event.
+ modeInfo = MOUSE_SELECTOR_MODE_INFOS[this.currentMode_];
+ tr.b.dispatchSimpleEvent(this, modeInfo.eventNames.exit, true);
+ }
+
+ this.currentMode_ = newMode;
+
+ if (this.currentMode_) {
+ const buttonEl = this.getButtonForMode_(this.currentMode_);
+ if (buttonEl) buttonEl.active = true;
+
+ // Entering a new mode resets mouse down pos.
+ this.mouseDownPos_.x = this.mousePos_.x;
+ this.mouseDownPos_.y = this.mousePos_.y;
+
+ // Enter event.
+ modeInfo = MOUSE_SELECTOR_MODE_INFOS[this.currentMode_];
+ if (!this.isInAlternativeMode_) {
+ tr.b.dispatchSimpleEvent(this, modeInfo.eventNames.enter, true);
+ }
+
+ // Begin event.
+ if (this.isInteracting_) {
+ const mouseEvent = this.createEvent_(
+ MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.begin);
+ this.dispatchEvent(mouseEvent);
+ }
+ }
+
+ if (this.settingsKey_ && !this.isInAlternativeMode_) {
+ tr.b.Settings.set(this.settingsKey_ + '.mode', this.mode);
+ }
+ },
+
+ setKeyCodeForMode(mode, keyCode) {
+ if ((mode & this.supportedModeMask_) === 0) {
+ throw new Error('Mode not supported');
+ }
+ this.modeToKeyCodeMap_[mode] = keyCode;
+
+ if (!this.buttonsEl_) return;
+
+ const buttonEl = this.getButtonForMode_(mode);
+ if (buttonEl) {
+ buttonEl.acceleratorKey = String.fromCharCode(keyCode);
+ }
+ },
+
+ setCurrentMousePosFromEvent_(e) {
+ this.mousePos_.x = e.clientX;
+ this.mousePos_.y = e.clientY;
+ },
+
+ createEvent_(eventName, sourceEvent) {
+ const event = new tr.b.Event(eventName, true);
+ event.clientX = this.mousePos_.x;
+ event.clientY = this.mousePos_.y;
+ event.deltaX = this.mousePos_.x - this.mouseDownPos_.x;
+ event.deltaY = this.mousePos_.y - this.mouseDownPos_.y;
+ event.mouseDownX = this.mouseDownPos_.x;
+ event.mouseDownY = this.mouseDownPos_.y;
+ event.didPreventDefault = false;
+ event.preventDefault = function() {
+ event.didPreventDefault = true;
+ if (sourceEvent) {
+ sourceEvent.preventDefault();
+ }
+ };
+ event.stopPropagation = function() {
+ sourceEvent.stopPropagation();
+ };
+ event.stopImmediatePropagation = function() {
+ throw new Error('Not implemented');
+ };
+ return event;
+ },
+
+ onMouseDown_(e) {
+ if (e.button !== 0) return;
+ this.setCurrentMousePosFromEvent_(e);
+ const mouseEvent = this.createEvent_(
+ MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.begin, e);
+ if (this.mode === MOUSE_SELECTOR_MODE.SELECTION) {
+ mouseEvent.appendSelection = isCmdOrCtrlPressed(e);
+ }
+ this.dispatchEvent(mouseEvent);
+ this.isInteracting_ = true;
+ this.isClick_ = true;
+ tr.ui.b.trackMouseMovesUntilMouseUp(this.onMouseMove_, this.onMouseUp_);
+ },
+
+ onMouseMove_(e) {
+ this.setCurrentMousePosFromEvent_(e);
+
+ const mouseEvent = this.createEvent_(
+ MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.update, e);
+ this.dispatchEvent(mouseEvent);
+
+ if (this.isInteracting_) {
+ this.checkIsClick_(e);
+ }
+ },
+
+ onMouseUp_(e) {
+ if (e.button !== 0) return;
+
+ const mouseEvent = this.createEvent_(
+ MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.end, e);
+ mouseEvent.isClick = this.isClick_;
+ this.dispatchEvent(mouseEvent);
+
+ if (this.isClick_ && !mouseEvent.didPreventDefault) {
+ this.dispatchClickEvents_(e);
+ }
+
+ this.isInteracting_ = false;
+ this.updateAlternativeModeState_(e);
+ },
+
+ onButtonMouseDown_(e) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ },
+
+ onButtonMouseUp_(e) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ },
+
+ onButtonPress_(e) {
+ this.modeBeforeAlternativeModeActivated_ = undefined;
+ this.mode = e.target.mode;
+ e.preventDefault();
+ },
+
+ onKeyDown_(e) {
+ // Keys dispatched to INPUT elements still bubble, even when they're
+ // handled. So, skip any events that targeted the input element.
+ if (e.path[0].tagName === 'INPUT') return;
+
+ if (e.keyCode === ' '.charCodeAt(0)) {
+ this.spacePressed_ = true;
+ }
+ this.updateAlternativeModeState_(e);
+ },
+
+ onKeyUp_(e) {
+ // Keys dispatched to INPUT elements still bubble, even when they're
+ // handled. So, skip any events that targeted the input element.
+ if (e.path[0].tagName === 'INPUT') return;
+
+ if (e.keyCode === ' '.charCodeAt(0)) {
+ this.spacePressed_ = false;
+ }
+
+ let didHandleKey = false;
+ for (const [modeStr, keyCode] of Object.entries(this.modeToKeyCodeMap_)) {
+ if (e.keyCode === keyCode) {
+ this.modeBeforeAlternativeModeActivated_ = undefined;
+ const mode = parseInt(modeStr);
+ this.mode = mode;
+ didHandleKey = true;
+ }
+ }
+
+ if (didHandleKey) {
+ e.preventDefault();
+ e.stopPropagation();
+ return;
+ }
+ this.updateAlternativeModeState_(e);
+ },
+
+ updateAlternativeModeState_(e) {
+ const shiftPressed = e.shiftKey;
+ const spacePressed = this.spacePressed_;
+ const cmdOrCtrlPressed = isCmdOrCtrlPressed(e);
+
+ // Figure out the new mode
+ const smm = this.supportedModeMask_;
+ let newMode;
+ let isNewModeAnAlternativeMode = false;
+ if (shiftPressed &&
+ (this.modifierToModeMap_[MODIFIER.SHIFT] & smm) !== 0) {
+ newMode = this.modifierToModeMap_[MODIFIER.SHIFT];
+ isNewModeAnAlternativeMode = true;
+ } else if (spacePressed &&
+ (this.modifierToModeMap_[MODIFIER.SPACE] & smm) !== 0) {
+ newMode = this.modifierToModeMap_[MODIFIER.SPACE];
+ isNewModeAnAlternativeMode = true;
+ } else if (cmdOrCtrlPressed &&
+ (this.modifierToModeMap_[MODIFIER.CMD_OR_CTRL] & smm) !== 0) {
+ newMode = this.modifierToModeMap_[MODIFIER.CMD_OR_CTRL];
+ isNewModeAnAlternativeMode = true;
+ } else {
+ // Go to the old mode, if there is one.
+ if (this.isInAlternativeMode_) {
+ newMode = this.modeBeforeAlternativeModeActivated_;
+ isNewModeAnAlternativeMode = false;
+ } else {
+ newMode = undefined;
+ }
+ }
+
+ // Maybe a mode change isn't needed.
+ if (this.mode === newMode || newMode === undefined) return;
+
+ // Okay, we're changing.
+ if (isNewModeAnAlternativeMode) {
+ this.modeBeforeAlternativeModeActivated_ = this.mode;
+ }
+ this.mode = newMode;
+ },
+
+ get isInAlternativeMode_() {
+ return !!this.modeBeforeAlternativeModeActivated_;
+ },
+
+ setModifierForAlternateMode(mode, modifier) {
+ this.modifierToModeMap_[modifier] = mode;
+ },
+
+ get pos() {
+ return {
+ x: parseInt(this.style.left),
+ y: parseInt(this.style.top)
+ };
+ },
+
+ set pos(pos) {
+ pos = this.constrainPositionToBounds_(pos);
+
+ this.style.left = pos.x + 'px';
+ this.style.top = pos.y + 'px';
+
+ if (this.settingsKey_) {
+ tr.b.Settings.set(this.settingsKey_ + '.pos', this.pos);
+ }
+ },
+
+ constrainPositionToBounds_(pos) {
+ const parent = this.offsetParent || document.body;
+ const parentRect = tr.ui.b.windowRectForElement(parent);
+
+ const top = 0;
+ const bottom = parentRect.height - this.offsetHeight;
+ const left = 0;
+ const right = parentRect.width - this.offsetWidth;
+
+ const res = {};
+ res.x = Math.max(pos.x, left);
+ res.x = Math.min(res.x, right);
+
+ res.y = Math.max(pos.y, top);
+ res.y = Math.min(res.y, bottom);
+ return res;
+ },
+
+ onDragHandleMouseDown_(e) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+
+ const mouseDownPos = {
+ x: e.clientX - this.offsetLeft,
+ y: e.clientY - this.offsetTop
+ };
+ tr.ui.b.trackMouseMovesUntilMouseUp(function(e) {
+ const pos = {};
+ pos.x = e.clientX - mouseDownPos.x;
+ pos.y = e.clientY - mouseDownPos.y;
+ this.pos = pos;
+ }.bind(this));
+ },
+
+ checkIsClick_(e) {
+ if (!this.isInteracting_ || !this.isClick_) return;
+
+ const deltaX = this.mousePos_.x - this.mouseDownPos_.x;
+ const deltaY = this.mousePos_.y - this.mouseDownPos_.y;
+ const minDist = MIN_MOUSE_SELECTION_DISTANCE;
+
+ if (deltaX * deltaX + deltaY * deltaY > minDist * minDist) {
+ this.isClick_ = false;
+ }
+ },
+
+ dispatchClickEvents_(e) {
+ if (!this.isClick_) return;
+
+ const modeInfo = MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.SELECTION];
+ const eventNames = modeInfo.eventNames;
+
+ let mouseEvent = this.createEvent_(eventNames.begin);
+ mouseEvent.appendSelection = isCmdOrCtrlPressed(e);
+ this.dispatchEvent(mouseEvent);
+
+ mouseEvent = this.createEvent_(eventNames.end);
+ this.dispatchEvent(mouseEvent);
+ }
+ });
+
+ return {
+ MIN_MOUSE_SELECTION_DISTANCE,
+ MODIFIER,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_selector_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_selector_test.html
new file mode 100644
index 00000000000..577d40dbae3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_mode_selector_test.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_selector.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const MOUSE_SELECTOR_MODE = tr.ui.b.MOUSE_SELECTOR_MODE;
+ test('instantiate', function() {
+ const sel = document.createElement('tr-ui-b-mouse-mode-selector');
+ sel.supportedModeMask =
+ MOUSE_SELECTOR_MODE.SELECTION |
+ MOUSE_SELECTOR_MODE.PANSCAN;
+ this.addHTMLOutput(sel);
+ });
+
+ test('changeMaskWithUnsupportedMode', function() {
+ const sel = document.createElement('tr-ui-b-mouse-mode-selector');
+ sel.mode = MOUSE_SELECTOR_MODE.SELECTION;
+ assert.throw(function() {
+ sel.supportedModeMask = MOUSE_SELECTOR_MODE.ZOOM;
+ });
+ });
+
+ test('modePersists', function() {
+ const sel1 = document.createElement('tr-ui-b-mouse-mode-selector');
+ sel1.defaultMode_ = MOUSE_SELECTOR_MODE.ZOOM;
+ sel1.settingsKey = 'foo';
+ assert.strictEqual(sel1.mode, MOUSE_SELECTOR_MODE.ZOOM);
+
+ sel1.mode = MOUSE_SELECTOR_MODE.PANSCAN;
+
+ const sel2 = document.createElement('tr-ui-b-mouse-mode-selector');
+ sel2.settingsKey = 'foo';
+ assert.strictEqual(sel2.mode, MOUSE_SELECTOR_MODE.PANSCAN);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_modes.html b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_modes.html
new file mode 100644
index 00000000000..8d68f0279cc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_modes.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const MOUSE_SELECTOR_MODE = {};
+ MOUSE_SELECTOR_MODE.SELECTION = 0x1;
+ MOUSE_SELECTOR_MODE.PANSCAN = 0x2;
+ MOUSE_SELECTOR_MODE.ZOOM = 0x4;
+ MOUSE_SELECTOR_MODE.TIMING = 0x8;
+ MOUSE_SELECTOR_MODE.ROTATE = 0x10;
+ MOUSE_SELECTOR_MODE.ALL_MODES = 0x1F;
+
+ const MOUSE_SELECTOR_MODE_INFOS = {};
+ MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.PANSCAN] = {
+ name: 'PANSCAN',
+ mode: MOUSE_SELECTOR_MODE.PANSCAN,
+ title: 'pan',
+ eventNames: {
+ enter: 'enterpan',
+ begin: 'beginpan',
+ update: 'updatepan',
+ end: 'endpan',
+ exit: 'exitpan'
+ },
+ activeBackgroundPosition: '-30px -10px',
+ defaultBackgroundPosition: '0 -10px'
+ };
+ MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.SELECTION] = {
+ name: 'SELECTION',
+ mode: MOUSE_SELECTOR_MODE.SELECTION,
+ title: 'selection',
+ eventNames: {
+ enter: 'enterselection',
+ begin: 'beginselection',
+ update: 'updateselection',
+ end: 'endselection',
+ exit: 'exitselection'
+ },
+ activeBackgroundPosition: '-30px -40px',
+ defaultBackgroundPosition: '0 -40px'
+ };
+
+ MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.ZOOM] = {
+ name: 'ZOOM',
+ mode: MOUSE_SELECTOR_MODE.ZOOM,
+ title: 'zoom',
+ eventNames: {
+ enter: 'enterzoom',
+ begin: 'beginzoom',
+ update: 'updatezoom',
+ end: 'endzoom',
+ exit: 'exitzoom'
+ },
+ activeBackgroundPosition: '-30px -70px',
+ defaultBackgroundPosition: '0 -70px'
+ };
+ MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.TIMING] = {
+ name: 'TIMING',
+ mode: MOUSE_SELECTOR_MODE.TIMING,
+ title: 'timing',
+ eventNames: {
+ enter: 'entertiming',
+ begin: 'begintiming',
+ update: 'updatetiming',
+ end: 'endtiming',
+ exit: 'exittiming'
+ },
+ activeBackgroundPosition: '-30px -100px',
+ defaultBackgroundPosition: '0 -100px'
+ };
+ MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.ROTATE] = {
+ name: 'ROTATE',
+ mode: MOUSE_SELECTOR_MODE.ROTATE,
+ title: 'rotate',
+ eventNames: {
+ enter: 'enterrotate',
+ begin: 'beginrotate',
+ update: 'updaterotate',
+ end: 'endrotate',
+ exit: 'exitrotate'
+ },
+ activeBackgroundPosition: '-30px -130px',
+ defaultBackgroundPosition: '0 -130px'
+ };
+
+ return {
+ MOUSE_SELECTOR_MODE_INFOS,
+ MOUSE_SELECTOR_MODE,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_tracker.html b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_tracker.html
new file mode 100644
index 00000000000..f71e0ba2dea
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/mouse_tracker.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+/**
+ * @fileoverview A Mouse-event abtraction that waits for
+ * mousedown, then watches for subsequent mousemove events
+ * until the next mouseup event, then waits again.
+ * State changes are signaled with
+ * 'mouse-tracker-start' : mousedown and tracking
+ * 'mouse-tracker-move' : mouse move
+ * 'mouse-tracker-end' : mouseup and not tracking.
+ */
+
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * @constructor
+ * @param {HTMLElement} targetElement will recv events 'mouse-tracker-start',
+ * 'mouse-tracker-move', 'mouse-tracker-end'.
+ */
+ function MouseTracker(opt_targetElement) {
+ this.onMouseDown_ = this.onMouseDown_.bind(this);
+ this.onMouseMove_ = this.onMouseMove_.bind(this);
+ this.onMouseUp_ = this.onMouseUp_.bind(this);
+
+ this.targetElement = opt_targetElement;
+ }
+
+ MouseTracker.prototype = {
+
+ get targetElement() {
+ return this.targetElement_;
+ },
+
+ set targetElement(targetElement) {
+ if (this.targetElement_) {
+ this.targetElement_.removeEventListener('mousedown', this.onMouseDown_);
+ }
+ this.targetElement_ = targetElement;
+ if (this.targetElement_) {
+ this.targetElement_.addEventListener('mousedown', this.onMouseDown_);
+ }
+ },
+
+ onMouseDown_(e) {
+ if (e.button !== 0) return true;
+
+ e = this.remakeEvent_(e, 'mouse-tracker-start');
+ this.targetElement_.dispatchEvent(e);
+ document.addEventListener('mousemove', this.onMouseMove_);
+ document.addEventListener('mouseup', this.onMouseUp_);
+ this.targetElement_.addEventListener('blur', this.onMouseUp_);
+ this.savePreviousUserSelect_ = document.body.style['-webkit-user-select'];
+ document.body.style['-webkit-user-select'] = 'none';
+ e.preventDefault();
+ return true;
+ },
+
+ onMouseMove_(e) {
+ e = this.remakeEvent_(e, 'mouse-tracker-move');
+ this.targetElement_.dispatchEvent(e);
+ },
+
+ onMouseUp_(e) {
+ document.removeEventListener('mousemove', this.onMouseMove_);
+ document.removeEventListener('mouseup', this.onMouseUp_);
+ this.targetElement_.removeEventListener('blur', this.onMouseUp_);
+ document.body.style['-webkit-user-select'] =
+ this.savePreviousUserSelect_;
+ e = this.remakeEvent_(e, 'mouse-tracker-end');
+ this.targetElement_.dispatchEvent(e);
+ },
+
+ remakeEvent_(e, newType) {
+ const remade = new tr.b.Event(newType, true, true);
+ remade.x = e.x;
+ remade.y = e.y;
+ remade.offsetX = e.offsetX;
+ remade.offsetY = e.offsetY;
+ remade.clientX = e.clientX;
+ remade.clientY = e.clientY;
+ return remade;
+ }
+
+ };
+
+ function trackMouseMovesUntilMouseUp(mouseMoveHandler,
+ opt_mouseUpHandler, opt_keyUpHandler) {
+ function cleanupAndDispatchToMouseUp(e) {
+ document.removeEventListener('mousemove', mouseMoveHandler);
+ if (opt_keyUpHandler) {
+ document.removeEventListener('keyup', opt_keyUpHandler);
+ }
+ document.removeEventListener('mouseup', cleanupAndDispatchToMouseUp);
+ if (opt_mouseUpHandler) {
+ opt_mouseUpHandler(e);
+ }
+ }
+ document.addEventListener('mousemove', mouseMoveHandler);
+ if (opt_keyUpHandler) {
+ document.addEventListener('keyup', opt_keyUpHandler);
+ }
+ document.addEventListener('mouseup', cleanupAndDispatchToMouseUp);
+ }
+
+ return {
+ MouseTracker,
+ trackMouseMovesUntilMouseUp,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/name_bar_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/base/name_bar_chart.html
new file mode 100644
index 00000000000..19bda4bcec8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/name_bar_chart.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/ui/base/bar_chart.html">
+<link rel="import" href="/tracing/ui/base/d3.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const NameBarChart = tr.ui.b.define('name-bar-chart', tr.ui.b.BarChart);
+
+ const Y_AXIS_PADDING = 2;
+
+ NameBarChart.prototype = {
+ __proto__: tr.ui.b.BarChart.prototype,
+
+ getDataPointAtChartPoint_(chartPoint) {
+ return {
+ x: tr.ui.b.BarChart.prototype.getDataPointAtChartPoint_.call(
+ this, chartPoint).x,
+ y: parseInt(Math.floor(
+ (this.graphHeight - chartPoint.y) / this.barHeight))
+ };
+ },
+
+ getXForDatum_(datum, index) {
+ return index;
+ },
+
+ get yAxisWidth() {
+ if (this.data.length === 0) return 0;
+ return Y_AXIS_PADDING + tr.b.math.Statistics.max(
+ this.data_, d => tr.ui.b.getSVGTextSize(this, d.x).width);
+ },
+
+ get defaultGraphHeight() {
+ return (3 + this.textHeightPx_) * this.data.length;
+ },
+
+ updateYAxis_(yAxis) {
+ // Building the y-axis requires measuring text.
+ // If necessary, wait for this element to be displayed.
+ if (tr.ui.b.getSVGTextSize(this, 'test').width === 0) {
+ tr.b.requestAnimationFrame(() => this.updateYAxis_(yAxis));
+ return;
+ }
+
+ // When we can measure text, we're ready to build the y-axis.
+ yAxis.selectAll('*').remove();
+ if (this.hideYAxis) return;
+ const nameTexts = yAxis.selectAll('text').data(this.data_);
+ nameTexts
+ .enter()
+ .append('text')
+ .attr('x', d => -(
+ tr.ui.b.getSVGTextSize(this, d.x).width + Y_AXIS_PADDING))
+ .attr('y', (d, index) => this.verticalScale_(index))
+ .text(d => d.x);
+ nameTexts.exit().remove();
+
+ let previousTop = undefined;
+ for (const text of nameTexts[0]) {
+ const bbox = text.getBBox();
+ if ((previousTop === undefined) ||
+ (previousTop > (bbox.y + bbox.height))) {
+ previousTop = bbox.y;
+ } else {
+ text.style.opacity = 0;
+ }
+ }
+ }
+ };
+
+ return {
+ NameBarChart,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/name_bar_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/name_bar_chart_test.html
new file mode 100644
index 00000000000..771022a86d9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/name_bar_chart_test.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/name_bar_chart.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiation_singleSeries', function() {
+ const chart = new tr.ui.b.NameBarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', value: 100},
+ {x: 'ball', value: 110},
+ {x: 'cat', value: 100},
+ {x: 'dog', value: 50}
+ ];
+ });
+
+ test('undefined', function() {
+ const chart = new tr.ui.b.NameBarChart();
+ assert.throws(function() {
+ chart.data = undefined;
+ });
+ });
+
+ test('instantiation_twoSeries', function() {
+ const chart = new tr.ui.b.NameBarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 100, beta: 50},
+ {x: 'ball', alpha: 110, beta: 75},
+ {x: 'cat', alpha: 100, beta: 125},
+ {x: 'dog', alpha: 50, beta: 125}
+ ];
+
+ const r = new tr.b.math.Range();
+ r.addValue(20);
+ r.addValue(40);
+ chart.brushedRange = r;
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueSparse', function() {
+ const chart = new tr.ui.b.NameBarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 20, beta: undefined},
+ {x: 'ball', alpha: undefined, beta: 10},
+ {x: 'cat', alpha: 10, beta: undefined},
+ {x: 'dog', alpha: undefined, beta: 20},
+ {x: 'echo', alpha: 30, beta: 30}
+ ];
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueNotSparse', function() {
+ const chart = new tr.ui.b.NameBarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 20, beta: 40},
+ {x: 'ball', alpha: undefined, beta: 10},
+ {x: 'cat', alpha: 10, beta: undefined},
+ {x: 'dog', alpha: undefined, beta: 20},
+ {x: 'echo', alpha: 30, beta: undefined}
+ ];
+ });
+
+ test('instantiation_interactiveBrushing', function() {
+ const chart = new tr.ui.b.NameBarChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', value: 50},
+ {x: 'ball', value: 60},
+ {x: 'cat', value: 80},
+ {x: 'dog', value: 20},
+ {x: 'echo', value: 30},
+ {x: 'fortune', value: 20},
+ {x: 'gpu', value: 15},
+ {x: 'happy', value: 20}
+ ];
+
+ let mouseDownIndex = undefined;
+ let currentMouseIndex = undefined;
+
+ function updateBrushedRange() {
+ const r = new tr.b.math.Range();
+ r.min = Math.max(0, Math.min(mouseDownIndex, currentMouseIndex));
+ r.max = Math.min(chart.data.length, Math.max(mouseDownIndex,
+ currentMouseIndex) + 1);
+ chart.brushedRange = r;
+ }
+
+ chart.addEventListener('item-mousedown', function(e) {
+ mouseDownIndex = e.index;
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mousemove', function(e) {
+ if (e.button === undefined) return;
+
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mouseup', function(e) {
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ });
+
+ test('instantiation_hideXandYAxis', function() {
+ const chart = new tr.ui.b.NameBarChart();
+ chart.hideXAxis = true;
+ chart.hideYAxis = true;
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', value: 100},
+ {x: 'ball', value: 110},
+ {x: 'cat', value: 100},
+ {x: 'dog', value: 50}
+ ];
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/name_column_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/base/name_column_chart.html
new file mode 100644
index 00000000000..6c0144da7ce
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/name_column_chart.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/column_chart.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const MIN_GUIDELINE_HEIGHT_PX = 3;
+
+ const CHECKBOX_WIDTH_PX = 18;
+
+ const NameColumnChart = tr.ui.b.define(
+ 'name-column-chart', tr.ui.b.ColumnChart);
+
+ NameColumnChart.prototype = {
+ __proto__: tr.ui.b.ColumnChart.prototype,
+
+ get xAxisHeight() {
+ // Add 5px for descenders because SVG draws text baselines at the
+ // specified y-coordinate.
+ return 5 + (this.textHeightPx_ * this.data_.length);
+ },
+
+ updateMargins_() {
+ super.updateMargins_();
+ let xAxisTickOverhangPx = 0;
+ for (let i = 0; i < this.data_.length; ++i) {
+ const datum = this.data_[i];
+ xAxisTickOverhangPx = Math.max(xAxisTickOverhangPx,
+ this.xScale_(i) + tr.ui.b.getSVGTextSize(this, datum.x).width -
+ this.graphWidth);
+ }
+ this.margin.right = Math.max(this.margin.right, xAxisTickOverhangPx);
+ },
+
+ getXForDatum_(datum, index) {
+ return index;
+ },
+
+ get xAxisTickOffset() {
+ return 0.5;
+ },
+
+ updateXAxis_(xAxis) {
+ xAxis.selectAll('*').remove();
+ if (this.hideXAxis) return;
+
+ // Draw the tick labels from |this.data_[*].x|.
+ // Lay them out so that the text doesn't overlap.
+ // They may overhang into |this.margin.right|.
+ const nameTexts = xAxis.selectAll('text')
+ .data(this.data_);
+ nameTexts
+ .enter()
+ .append('text')
+ .attr('transform', (d, index) => 'translate(0, ' +
+ this.textHeightPx_ * (this.data_.length - index) + ')')
+ .attr('x', (d, index) => this.xScale_(index))
+ .attr('y', d => this.graphHeight)
+ .text(d => d.x);
+ nameTexts.exit().remove();
+
+ // Draw lines to guide the eye from bottom center of the column to the
+ // tick label.
+ const guideLines = xAxis.selectAll('line.guide').data(this.data_);
+ guideLines.enter()
+ .append('line')
+ .attr('x1', (d, index) => this.xScale_(index + this.xAxisTickOffset))
+ .attr('x2', (d, index) => this.xScale_(index + this.xAxisTickOffset))
+ .attr('y1', () => this.graphHeight)
+ .attr('y2', (d, index) => this.graphHeight + Math.max(
+ MIN_GUIDELINE_HEIGHT_PX,
+ (this.textHeightPx_ * (this.data_.length - index - 1))));
+ }
+ };
+
+ return {
+ NameColumnChart,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/name_column_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/name_column_chart_test.html
new file mode 100644
index 00000000000..5e78dd6aa76
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/name_column_chart_test.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/name_column_chart.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiation_singleSeries', function() {
+ this.addHTMLOutput(document.createTextNode(
+ 'There should be a capital "A" at the end of the string of "a"s.'));
+ const chart = new tr.ui.b.NameColumnChart();
+ this.addHTMLOutput(chart);
+ // Make a x-axis tick label long enough that it would overhang past the
+ // right edge of the legend in order to test that updateMargins_ extends the
+ // right margin.
+ chart.data = [
+ {x: 'a'.repeat(20) + 'A', value: 100},
+ {x: 'b', value: 110},
+ {x: 'c', value: 100},
+ {x: 'd', value: 50}
+ ];
+ });
+
+ test('undefined', function() {
+ const chart = new tr.ui.b.NameColumnChart();
+ assert.throws(function() {
+ chart.data = undefined;
+ });
+ });
+
+ test('instantiation_twoSeries', function() {
+ const chart = new tr.ui.b.NameColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 100, beta: 50},
+ {x: 'ball', alpha: 110, beta: 75},
+ {x: 'cat', alpha: 100, beta: 125},
+ {x: 'dog', alpha: 50, beta: 125}
+ ];
+
+ const r = new tr.b.math.Range();
+ r.addValue(20);
+ r.addValue(40);
+ chart.brushedRange = r;
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueSparse', function() {
+ const chart = new tr.ui.b.NameColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 20, beta: undefined},
+ {x: 'ball', alpha: undefined, beta: 10},
+ {x: 'cat', alpha: 10, beta: undefined},
+ {x: 'dog', alpha: undefined, beta: 20},
+ {x: 'echo', alpha: 30, beta: 30}
+ ];
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueNotSparse', function() {
+ const chart = new tr.ui.b.NameColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 20, beta: 40},
+ {x: 'ball', alpha: undefined, beta: 10},
+ {x: 'cat', alpha: 10, beta: undefined},
+ {x: 'dog', alpha: undefined, beta: 20},
+ {x: 'echo', alpha: 30, beta: undefined}
+ ];
+ });
+
+ test('instantiation_interactiveBrushing', function() {
+ const chart = new tr.ui.b.NameColumnChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', value: 50},
+ {x: 'ball', value: 60},
+ {x: 'cat', value: 80},
+ {x: 'dog', value: 20},
+ {x: 'echo', value: 30},
+ {x: 'fortune', value: 20},
+ {x: 'gpu', value: 15},
+ {x: 'happy', value: 20}
+ ];
+
+ let mouseDownIndex = undefined;
+ let currentMouseIndex = undefined;
+
+ function updateBrushedRange() {
+ const r = new tr.b.math.Range();
+ r.min = Math.max(0, Math.min(mouseDownIndex, currentMouseIndex));
+ r.max = Math.min(chart.data.length,
+ Math.max(mouseDownIndex, currentMouseIndex) + 1);
+ chart.brushedRange = r;
+ }
+
+ chart.addEventListener('item-mousedown', function(e) {
+ mouseDownIndex = e.index;
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mousemove', function(e) {
+ if (e.button === undefined) return;
+
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mouseup', function(e) {
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/name_line_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/base/name_line_chart.html
new file mode 100644
index 00000000000..572ba36e533
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/name_line_chart.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/ui/base/line_chart.html">
+<link rel="import" href="/tracing/ui/base/name_column_chart.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const LineChart = tr.ui.b.LineChart;
+
+ // @constructor
+ const NameLineChart = tr.ui.b.define('name-line-chart', LineChart);
+
+ NameLineChart.prototype = {
+ __proto__: LineChart.prototype,
+
+ getXForDatum_(datum, index) {
+ return index;
+ },
+
+ get xAxisHeight() {
+ // Add 5px for descenders because SVG draws text baselines at the
+ // specified y-coordinate.
+ return 5 + (this.textHeightPx_ * this.data_.length);
+ },
+
+ get xAxisTickOffset() {
+ return 0;
+ },
+
+ updateMargins_() {
+ tr.ui.b.NameColumnChart.prototype.updateMargins_.call(this);
+ },
+
+ updateXAxis_(xAxis) {
+ xAxis.selectAll('*').remove();
+ if (this.hideXAxis) return;
+
+ tr.ui.b.NameColumnChart.prototype.updateXAxis_.call(this, xAxis);
+
+ const baseline = xAxis.selectAll('path').data([this]);
+ baseline.enter().append('line')
+ .attr('stroke', 'black')
+ .attr('x1', this.xScale_(0))
+ .attr('x2', this.xScale_(this.data_.length - 1))
+ .attr('y1', this.graphHeight)
+ .attr('y2', this.graphHeight);
+ baseline.exit().remove();
+ }
+ };
+
+ return {
+ NameLineChart,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/name_line_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/name_line_chart_test.html
new file mode 100644
index 00000000000..fa7388103ae
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/name_line_chart_test.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/name_line_chart.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiation_singleSeries', function() {
+ const chart = new tr.ui.b.NameLineChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', value: 100},
+ {x: 'ball', value: 110},
+ {x: 'cat', value: 100},
+ {x: 'dog', value: 50}
+ ];
+ });
+
+ test('undefined', function() {
+ const chart = new tr.ui.b.NameLineChart();
+ assert.throws(function() {
+ chart.data = undefined;
+ });
+ });
+
+ test('instantiation_twoSeries', function() {
+ const chart = new tr.ui.b.NameLineChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 100, beta: 50},
+ {x: 'ball', alpha: 110, beta: 75},
+ {x: 'cat', alpha: 100, beta: 125},
+ {x: 'dog', alpha: 50, beta: 125}
+ ];
+
+ const r = new tr.b.math.Range();
+ r.addValue(20);
+ r.addValue(40);
+ chart.brushedRange = r;
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueSparse', function() {
+ const chart = new tr.ui.b.NameLineChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 20, beta: undefined},
+ {x: 'ball', alpha: undefined, beta: 10},
+ {x: 'cat', alpha: 10, beta: undefined},
+ {x: 'dog', alpha: undefined, beta: 20},
+ {x: 'echo', alpha: 30, beta: 30}
+ ];
+ });
+
+ test('instantiation_twoSparseSeriesWithFirstValueNotSparse', function() {
+ const chart = new tr.ui.b.NameLineChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', alpha: 20, beta: 40},
+ {x: 'ball', alpha: undefined, beta: 10},
+ {x: 'cat', alpha: 10, beta: undefined},
+ {x: 'dog', alpha: undefined, beta: 20},
+ {x: 'echo', alpha: 30, beta: undefined}
+ ];
+ });
+
+ test('instantiation_interactiveBrushing', function() {
+ const chart = new tr.ui.b.NameLineChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 'apple', value: 50},
+ {x: 'ball', value: 60},
+ {x: 'cat', value: 80},
+ {x: 'dog', value: 20},
+ {x: 'echo', value: 30},
+ {x: 'fortune', value: 20},
+ {x: 'gpu', value: 15},
+ {x: 'happy', value: 20}
+ ];
+
+ let mouseDownIndex = undefined;
+ let currentMouseIndex = undefined;
+
+ function updateBrushedRange() {
+ const r = new tr.b.math.Range();
+ r.min = Math.max(0, Math.min(mouseDownIndex, currentMouseIndex));
+ r.max = Math.min(chart.data.length, Math.max(mouseDownIndex,
+ currentMouseIndex) + 1);
+ chart.brushedRange = r;
+ }
+
+ chart.addEventListener('item-mousedown', function(e) {
+ mouseDownIndex = e.index;
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mousemove', function(e) {
+ if (e.button === undefined) return;
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ chart.addEventListener('item-mouseup', function(e) {
+ currentMouseIndex = e.index;
+ updateBrushedRange();
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/overlay.html b/chromium/third_party/catapult/tracing/tracing/ui/base/overlay.html
new file mode 100644
index 00000000000..9b1014d63b4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/overlay.html
@@ -0,0 +1,351 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<template id="overlay-template">
+ <style>
+ overlay-mask {
+ left: 0;
+ padding: 8px;
+ position: absolute;
+ top: 0;
+ z-index: 1000;
+ font-family: sans-serif;
+ -webkit-justify-content: center;
+ background: rgba(0, 0, 0, 0.8);
+ display: flex;
+ height: 100%;
+ left: 0;
+ position: fixed;
+ top: 0;
+ width: 100%;
+ }
+ overlay-mask:focus {
+ outline: none;
+ }
+ overlay-vertical-centering-container {
+ -webkit-justify-content: center;
+ flex-direction: column;
+ display: flex;
+ }
+ overlay-frame {
+ z-index: 1100;
+ background: rgb(255, 255, 255);
+ border: 1px solid #ccc;
+ margin: 75px;
+ display: flex;
+ flex-direction: column;
+ min-height: 0;
+ }
+ title-bar {
+ -webkit-align-items: center;
+ flex-direction: row;
+ border-bottom: 1px solid #ccc;
+ background-color: #ddd;
+ display: flex;
+ padding: 5px;
+ flex: 0 0 auto;
+ }
+ title {
+ display: inline;
+ font-weight: bold;
+ flex: 1 1 auto;
+ }
+ close-button {
+ -webkit-align-self: flex-end;
+ border: 1px solid #eee;
+ background-color: #999;
+ font-size: 10pt;
+ font-weight: bold;
+ padding: 2px;
+ text-align: center;
+ width: 16px;
+ }
+ close-button:hover {
+ background-color: #ddd;
+ border-color: black;
+ cursor: pointer;
+ }
+ overlay-content {
+ display: flex;
+ flex: 1 1 auto;
+ flex-direction: column;
+ overflow-y: auto;
+ padding: 10px;
+ min-width: 300px;
+ min-height: 0;
+ }
+ button-bar {
+ -webkit-align-items: baseline;
+ border-top: 1px solid #ccc;
+ display: flex;
+ flex: 0 0 auto;
+ flex-direction: row-reverse;
+ padding: 4px;
+ }
+ </style>
+
+ <overlay-mask>
+ <overlay-vertical-centering-container>
+ <overlay-frame>
+ <title-bar>
+ <title></title>
+ <close-button>&#x2715</close-button>
+ </title-bar>
+ <overlay-content>
+ <content></content>
+ </overlay-content>
+ <button-bar></button-bar>
+ </overlay-frame>
+ </overlay-vertical-centering-container>
+ </overlay-mask>
+</template>
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Implements an element that is hidden by default, but
+ * when shown, dims and (attempts to) disable the main document.
+ *
+ * You can turn any div into an overlay. Note that while an
+ * overlay element is shown, its parent is changed. Hiding the overlay
+ * restores its original parentage.
+ *
+ */
+tr.exportTo('tr.ui.b', function() {
+ if (tr.isHeadless) return {};
+
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ /**
+ * Creates a new overlay element. It will not be visible until shown.
+ * @constructor
+ * @extends {HTMLDivElement}
+ */
+ const Overlay = tr.ui.b.define('overlay');
+
+ Overlay.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ /**
+ * Initializes the overlay element.
+ */
+ decorate() {
+ Polymer.dom(this).classList.add('overlay');
+
+ this.parentEl_ = this.ownerDocument.body;
+
+ this.visible_ = false;
+ this.userCanClose_ = true;
+
+ this.onKeyDown_ = this.onKeyDown_.bind(this);
+ this.onClick_ = this.onClick_.bind(this);
+ this.onFocusIn_ = this.onFocusIn_.bind(this);
+ this.onDocumentClick_ = this.onDocumentClick_.bind(this);
+ this.onClose_ = this.onClose_.bind(this);
+
+ this.addEventListener('visible-change',
+ tr.ui.b.Overlay.prototype.onVisibleChange_.bind(this), true);
+
+ // Setup the shadow root
+ const createShadowRoot = this.createShadowRoot ||
+ this.webkitCreateShadowRoot;
+ this.shadow_ = createShadowRoot.call(this);
+ Polymer.dom(this.shadow_).appendChild(
+ tr.ui.b.instantiateTemplate('#overlay-template', THIS_DOC));
+
+ this.closeBtn_ = Polymer.dom(this.shadow_).querySelector('close-button');
+ this.closeBtn_.addEventListener('click', this.onClose_);
+
+ Polymer.dom(this.shadow_)
+ .querySelector('overlay-frame')
+ .addEventListener('click', this.onClick_);
+
+ this.observer_ = new WebKitMutationObserver(
+ this.didButtonBarMutate_.bind(this));
+ this.observer_.observe(
+ Polymer.dom(this.shadow_).querySelector('button-bar'),
+ { childList: true });
+
+ // title is a variable on regular HTMLElements. However, we want to
+ // use it for something more useful.
+ Object.defineProperty(
+ this, 'title', {
+ get() {
+ return Polymer.dom(Polymer.dom(this.shadow_)
+ .querySelector('title')).textContent;
+ },
+ set(title) {
+ Polymer.dom(Polymer.dom(this.shadow_).querySelector('title'))
+ .textContent = title;
+ }
+ });
+ },
+
+ set userCanClose(userCanClose) {
+ this.userCanClose_ = userCanClose;
+ this.closeBtn_.style.display =
+ userCanClose ? 'block' : 'none';
+ },
+
+ get buttons() {
+ return Polymer.dom(this.shadow_).querySelector('button-bar');
+ },
+
+ get visible() {
+ return this.visible_;
+ },
+
+ set visible(newValue) {
+ if (this.visible_ === newValue) return;
+
+ this.visible_ = newValue;
+ const e = new tr.b.Event('visible-change');
+ this.dispatchEvent(e);
+ },
+
+ onVisibleChange_() {
+ this.visible_ ? this.show_() : this.hide_();
+ },
+
+ show_() {
+ Polymer.dom(this.parentEl_).appendChild(this);
+
+ if (this.userCanClose_) {
+ this.addEventListener('keydown', this.onKeyDown_.bind(this));
+ this.addEventListener('click', this.onDocumentClick_.bind(this));
+ this.closeBtn_.addEventListener('click', this.onClose_);
+ }
+
+ this.parentEl_.addEventListener('focusin', this.onFocusIn_);
+ this.tabIndex = 0;
+
+ // Focus the first thing we find that makes sense. (Skip the close button
+ // as it doesn't make sense as the first thing to focus.)
+ const elList =
+ Polymer.dom(this).querySelectorAll('button, input, list, select, a');
+ if (elList.length > 0) {
+ if (elList[0] === this.closeBtn_) {
+ if (elList.length > 1) return elList[1].focus();
+ } else {
+ return elList[0].focus();
+ }
+ }
+ this.focus();
+ },
+
+ hide_() {
+ Polymer.dom(this.parentEl_).removeChild(this);
+
+ this.parentEl_.removeEventListener('focusin', this.onFocusIn_);
+
+ if (this.closeBtn_) {
+ this.closeBtn_.removeEventListener('click', this.onClose_);
+ }
+
+ document.removeEventListener('keydown', this.onKeyDown_);
+ document.removeEventListener('click', this.onDocumentClick_);
+ },
+
+ onClose_(e) {
+ this.visible = false;
+ if ((e.type !== 'keydown') ||
+ (e.type === 'keydown' && e.keyCode === 27)) {
+ e.stopPropagation();
+ }
+ e.preventDefault();
+ tr.b.dispatchSimpleEvent(this, 'closeclick');
+ },
+
+ onFocusIn_(e) {
+ // Prevent focus from leaving the overlay.
+
+ let node = e.target;
+ while (node) {
+ if (node === this) {
+ // |this| contains |e.target|, so nothing needs to be done. Allow
+ // focus to move from |this| to |e.target|.
+ return;
+ }
+ node = node.parentNode;
+ }
+
+ // |e.target| is outside of |this|, so focus |this|.
+ tr.b.timeout(0).then(() => this.focus());
+ e.preventDefault();
+ e.stopPropagation();
+ },
+
+ didButtonBarMutate_(e) {
+ const hasButtons = this.buttons.children.length > 0;
+ if (hasButtons) {
+ Polymer.dom(this.shadow_).querySelector('button-bar').style.display =
+ undefined;
+ } else {
+ Polymer.dom(this.shadow_).querySelector('button-bar').style.display =
+ 'none';
+ }
+ },
+
+ onKeyDown_(e) {
+ // Disallow shift-tab back to another element.
+ if (e.keyCode === 9 && // tab
+ e.shiftKey &&
+ e.target === this) {
+ e.preventDefault();
+ return;
+ }
+
+ if (e.keyCode !== 27) return; // escape
+
+ this.onClose_(e);
+ },
+
+ onClick_(e) {
+ e.stopPropagation();
+ },
+
+ onDocumentClick_(e) {
+ if (!this.userCanClose_) return;
+
+ this.onClose_(e);
+ }
+ };
+
+ Overlay.showError = function(msg, opt_err) {
+ const o = new Overlay();
+ o.title = 'Error';
+ Polymer.dom(o).textContent = msg;
+ if (opt_err) {
+ const e = tr.b.normalizeException(opt_err);
+
+ const stackDiv = document.createElement('pre');
+ Polymer.dom(stackDiv).textContent = e.stack;
+ stackDiv.style.paddingLeft = '8px';
+ stackDiv.style.margin = 0;
+ Polymer.dom(o).appendChild(stackDiv);
+ }
+ const b = document.createElement('button');
+ Polymer.dom(b).textContent = 'OK';
+ b.addEventListener('click', function() {
+ o.visible = false;
+ });
+ Polymer.dom(o.buttons).appendChild(b);
+ o.visible = true;
+ return o;
+ };
+
+ return {
+ Overlay,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/overlay_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/overlay_test.html
new file mode 100644
index 00000000000..ac22b08aa6b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/overlay_test.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function addShowButtonForDialog(dlg) {
+ const btn = document.createElement('button');
+ Polymer.dom(btn).textContent = 'Launch Overlay';
+ btn.addEventListener('click', function(e) {
+ dlg.visible = true;
+ e.stopPropagation();
+ });
+
+ this.addHTMLOutput(btn);
+ }
+
+ function makeButton(title) {
+ const btn = document.createElement('button');
+ Polymer.dom(btn).textContent = title;
+ return btn;
+ }
+
+ function makeCloseButton(dlg) {
+ const btn = makeButton('close');
+ btn.addEventListener('click', function(e) {
+ dlg.onClose_(e);
+ });
+ return btn;
+ }
+
+ test('instantiate', function() {
+ const dlg = new tr.ui.b.Overlay();
+ Polymer.dom(dlg).classList.add('example-overlay');
+ dlg.title = 'ExampleOverlay';
+ Polymer.dom(dlg).innerHTML = 'hello';
+ Polymer.dom(dlg.buttons).appendChild(makeButton('i am a button'));
+ Polymer.dom(dlg.buttons).appendChild(makeCloseButton(dlg));
+ Polymer.dom(dlg.buttons).appendChild(tr.ui.b.createSpan(
+ {textContent: 'i am a span'}));
+ addShowButtonForDialog.call(this, dlg);
+ });
+
+ test('instantiate_noButtons', function() {
+ const dlg = new tr.ui.b.Overlay();
+ Polymer.dom(dlg).classList.add('example-overlay');
+ dlg.title = 'ExampleOverlay';
+ Polymer.dom(dlg).innerHTML = 'hello';
+ addShowButtonForDialog.call(this, dlg);
+ });
+
+ test('instantiate_disableUserClose', function() {
+ const dlg = new tr.ui.b.Overlay();
+ Polymer.dom(dlg).classList.add('example-overlay');
+ dlg.userCanClose = false;
+ dlg.title = 'Unclosable';
+ Polymer.dom(dlg).innerHTML = 'This has no close X button.';
+ Polymer.dom(dlg.buttons).appendChild(makeCloseButton(dlg));
+ addShowButtonForDialog.call(this, dlg);
+ });
+
+ test('instantiateTall', function() {
+ const dlg = new tr.ui.b.Overlay();
+ dlg.title = 'TallContent';
+ const contentEl = document.createElement('div');
+ contentEl.style.overflowY = 'auto';
+ Polymer.dom(dlg).appendChild(contentEl);
+
+ for (let i = 0; i < 1000; i++) {
+ const el = document.createElement('div');
+ Polymer.dom(el).textContent = 'line ' + i;
+ Polymer.dom(contentEl).appendChild(el);
+ }
+
+
+ Polymer.dom(dlg.buttons).appendChild(makeButton('i am a button'));
+ addShowButtonForDialog.call(this, dlg);
+ });
+
+ test('instantiateTallWithManyDirectChildren', function() {
+ const dlg = new tr.ui.b.Overlay();
+ dlg.title = 'TallContent';
+ for (let i = 0; i < 100; i++) {
+ const el = document.createElement('div');
+ el.style.webkitFlex = '1 0 auto';
+ Polymer.dom(el).textContent = 'line ' + i;
+ Polymer.dom(dlg).appendChild(el);
+ }
+
+ Polymer.dom(dlg.buttons).appendChild(makeButton('i am a button'));
+ addShowButtonForDialog.call(this, dlg);
+ });
+
+ test('closeclickEvent', function() {
+ const dlg = new tr.ui.b.Overlay();
+ dlg.title = 'Test closeclick event';
+ const closeBtn = makeCloseButton(dlg);
+ Polymer.dom(dlg.buttons).appendChild(closeBtn);
+
+ let closeClicked = false;
+ dlg.addEventListener('closeclick', function() {
+ closeClicked = true;
+ });
+
+ dlg.visible = true;
+ return tr.b.timeout(60).then(() => {
+ closeBtn.click();
+ assert.isTrue(closeClicked);
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/polymer_postload.html b/chromium/third_party/catapult/tracing/tracing/ui/base/polymer_postload.html
new file mode 100644
index 00000000000..8a8016142ab
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/polymer_postload.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<script>
+'use strict';
+
+if (!Polymer.Settings.useNativeShadow) {
+ tr.showPanic('Polymer error', 'base only works in shadow mode');
+}
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/polymer_preload.html b/chromium/third_party/catapult/tracing/tracing/ui/base/polymer_preload.html
new file mode 100644
index 00000000000..4c21ef991ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/polymer_preload.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<script>
+'use strict';
+
+// Force Polymer into native shadowDom mode
+if (window.Polymer) {
+ throw new Error('Cannot proceed. Polymer already present.');
+}
+window.Polymer = {};
+window.Polymer.dom = 'shadow';
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/quad_stack_view.html b/chromium/third_party/catapult/tracing/tracing/ui/base/quad_stack_view.html
new file mode 100644
index 00000000000..d3d91fa6c00
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/quad_stack_view.html
@@ -0,0 +1,688 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/bbox2.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/ui/base/camera.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_selector.html">
+<link rel="import" href="/tracing/ui/base/mouse_tracker.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<template id="quad-stack-view-template">
+ <style>
+ #chrome-left {
+ background-image: url('../images/chrome-left.png');
+ display: none;
+ }
+ #chrome-mid {
+ background-image: url('../images/chrome-mid.png');
+ display: none;
+ }
+ #chrome-right {
+ background-image: url('../images/chrome-right.png');
+ display: none;
+ }
+ </style>
+
+ <div id="header"></div>
+ <input id="stacking-distance-slider" type="range" min=1 max=400 step=1>
+ </input>
+ <div id="canvas-scroller">
+ <canvas id="canvas"></canvas>
+ </div>
+ <img id="chrome-left"/>
+ <img id="chrome-mid"/>
+ <img id="chrome-right"/>
+</template>
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview QuadStackView controls the content and viewing angle a
+ * QuadStack.
+ */
+tr.exportTo('tr.ui.b', function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ const constants = {};
+ constants.IMAGE_LOAD_RETRY_TIME_MS = 500;
+ constants.SUBDIVISION_MINIMUM = 1;
+ constants.SUBDIVISION_RECURSION_DEPTH = 3;
+ constants.SUBDIVISION_DEPTH_THRESHOLD = 100;
+ constants.FAR_PLANE_DISTANCE = 10000;
+
+ // Care of bckenney@ via
+ // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
+ function drawTexturedTriangle(ctx, img, p0, p1, p2, t0, t1, t2) {
+ const tmpP0 = [p0[0], p0[1]];
+ const tmpP1 = [p1[0], p1[1]];
+ const tmpP2 = [p2[0], p2[1]];
+ const tmpT0 = [t0[0], t0[1]];
+ const tmpT1 = [t1[0], t1[1]];
+ const tmpT2 = [t2[0], t2[1]];
+
+ ctx.beginPath();
+ ctx.moveTo(tmpP0[0], tmpP0[1]);
+ ctx.lineTo(tmpP1[0], tmpP1[1]);
+ ctx.lineTo(tmpP2[0], tmpP2[1]);
+ ctx.closePath();
+
+ tmpP1[0] -= tmpP0[0];
+ tmpP1[1] -= tmpP0[1];
+ tmpP2[0] -= tmpP0[0];
+ tmpP2[1] -= tmpP0[1];
+
+ tmpT1[0] -= tmpT0[0];
+ tmpT1[1] -= tmpT0[1];
+ tmpT2[0] -= tmpT0[0];
+ tmpT2[1] -= tmpT0[1];
+
+ const det = 1 / (tmpT1[0] * tmpT2[1] - tmpT2[0] * tmpT1[1]);
+
+ // linear transformation
+ const a = (tmpT2[1] * tmpP1[0] - tmpT1[1] * tmpP2[0]) * det;
+ const b = (tmpT2[1] * tmpP1[1] - tmpT1[1] * tmpP2[1]) * det;
+ const c = (tmpT1[0] * tmpP2[0] - tmpT2[0] * tmpP1[0]) * det;
+ const d = (tmpT1[0] * tmpP2[1] - tmpT2[0] * tmpP1[1]) * det;
+
+ // translation
+ const e = tmpP0[0] - a * tmpT0[0] - c * tmpT0[1];
+ const f = tmpP0[1] - b * tmpT0[0] - d * tmpT0[1];
+
+ ctx.save();
+ ctx.transform(a, b, c, d, e, f);
+ ctx.clip();
+ ctx.drawImage(img, 0, 0);
+ ctx.restore();
+ }
+
+ function drawTriangleSub(
+ ctx, img, p0, p1, p2, t0, t1, t2, opt_recursionDepth) {
+ const depth = opt_recursionDepth || 0;
+
+ // We may subdivide if we are not at the limit of recursion.
+ let subdivisionIndex = 0;
+ if (depth < constants.SUBDIVISION_MINIMUM) {
+ subdivisionIndex = 7;
+ } else if (depth < constants.SUBDIVISION_RECURSION_DEPTH) {
+ if (Math.abs(p0[2] - p1[2]) > constants.SUBDIVISION_DEPTH_THRESHOLD) {
+ subdivisionIndex += 1;
+ }
+ if (Math.abs(p0[2] - p2[2]) > constants.SUBDIVISION_DEPTH_THRESHOLD) {
+ subdivisionIndex += 2;
+ }
+ if (Math.abs(p1[2] - p2[2]) > constants.SUBDIVISION_DEPTH_THRESHOLD) {
+ subdivisionIndex += 4;
+ }
+ }
+
+ // These need to be created every time, since temporaries
+ // outside of the scope will be rewritten in recursion.
+ const p01 = vec4.create();
+ const p02 = vec4.create();
+ const p12 = vec4.create();
+ const t01 = vec2.create();
+ const t02 = vec2.create();
+ const t12 = vec2.create();
+
+ // Calculate the position before w-divide.
+ for (let i = 0; i < 2; ++i) {
+ p0[i] *= p0[2];
+ p1[i] *= p1[2];
+ p2[i] *= p2[2];
+ }
+
+ // Interpolate the 3d position.
+ for (let i = 0; i < 4; ++i) {
+ p01[i] = (p0[i] + p1[i]) / 2;
+ p02[i] = (p0[i] + p2[i]) / 2;
+ p12[i] = (p1[i] + p2[i]) / 2;
+ }
+
+ // Re-apply w-divide to the original points and the interpolated ones.
+ for (let i = 0; i < 2; ++i) {
+ p0[i] /= p0[2];
+ p1[i] /= p1[2];
+ p2[i] /= p2[2];
+
+ p01[i] /= p01[2];
+ p02[i] /= p02[2];
+ p12[i] /= p12[2];
+ }
+
+ // Interpolate the texture coordinates.
+ for (let i = 0; i < 2; ++i) {
+ t01[i] = (t0[i] + t1[i]) / 2;
+ t02[i] = (t0[i] + t2[i]) / 2;
+ t12[i] = (t1[i] + t2[i]) / 2;
+ }
+
+ // Based on the index, we subdivide the triangle differently.
+ // Assuming the triangle is p0, p1, p2 and points between i j
+ // are represented as pij (that is, a point between p2 and p0
+ // is p02, etc), then the new triangles are defined by
+ // the 3rd 4th and 5th arguments into the function.
+ switch (subdivisionIndex) {
+ case 1:
+ drawTriangleSub(ctx, img, p0, p01, p2, t0, t01, t2, depth + 1);
+ drawTriangleSub(ctx, img, p01, p1, p2, t01, t1, t2, depth + 1);
+ break;
+ case 2:
+ drawTriangleSub(ctx, img, p0, p1, p02, t0, t1, t02, depth + 1);
+ drawTriangleSub(ctx, img, p1, p02, p2, t1, t02, t2, depth + 1);
+ break;
+ case 3:
+ drawTriangleSub(ctx, img, p0, p01, p02, t0, t01, t02, depth + 1);
+ drawTriangleSub(ctx, img, p02, p01, p2, t02, t01, t2, depth + 1);
+ drawTriangleSub(ctx, img, p01, p1, p2, t01, t1, t2, depth + 1);
+ break;
+ case 4:
+ drawTriangleSub(ctx, img, p0, p12, p2, t0, t12, t2, depth + 1);
+ drawTriangleSub(ctx, img, p0, p1, p12, t0, t1, t12, depth + 1);
+ break;
+ case 5:
+ drawTriangleSub(ctx, img, p0, p01, p2, t0, t01, t2, depth + 1);
+ drawTriangleSub(ctx, img, p2, p01, p12, t2, t01, t12, depth + 1);
+ drawTriangleSub(ctx, img, p01, p1, p12, t01, t1, t12, depth + 1);
+ break;
+ case 6:
+ drawTriangleSub(ctx, img, p0, p12, p02, t0, t12, t02, depth + 1);
+ drawTriangleSub(ctx, img, p0, p1, p12, t0, t1, t12, depth + 1);
+ drawTriangleSub(ctx, img, p02, p12, p2, t02, t12, t2, depth + 1);
+ break;
+ case 7:
+ drawTriangleSub(ctx, img, p0, p01, p02, t0, t01, t02, depth + 1);
+ drawTriangleSub(ctx, img, p01, p12, p02, t01, t12, t02, depth + 1);
+ drawTriangleSub(ctx, img, p01, p1, p12, t01, t1, t12, depth + 1);
+ drawTriangleSub(ctx, img, p02, p12, p2, t02, t12, t2, depth + 1);
+ break;
+ default:
+ // In the 0 case and all other cases, we simply draw the triangle.
+ drawTexturedTriangle(ctx, img, p0, p1, p2, t0, t1, t2);
+ break;
+ }
+ }
+
+ // Created to avoid creating garbage when doing bulk transforms.
+ const tmpVec4 = vec4.create();
+ function transform(transformed, point, matrix, viewport) {
+ vec4.set(tmpVec4, point[0], point[1], 0, 1);
+ vec4.transformMat4(tmpVec4, tmpVec4, matrix);
+
+ let w = tmpVec4[3];
+ if (w < 1e-6) w = 1e-6;
+
+ transformed[0] = ((tmpVec4[0] / w) + 1) * viewport.width / 2;
+ transformed[1] = ((tmpVec4[1] / w) + 1) * viewport.height / 2;
+ transformed[2] = w;
+ }
+
+ function drawProjectedQuadBackgroundToContext(
+ quad, p1, p2, p3, p4, ctx, quadCanvas) {
+ if (quad.imageData) {
+ quadCanvas.width = quad.imageData.width;
+ quadCanvas.height = quad.imageData.height;
+ quadCanvas.getContext('2d').putImageData(quad.imageData, 0, 0);
+ const quadBBox = new tr.b.math.BBox2();
+ quadBBox.addQuad(quad);
+ const iw = quadCanvas.width;
+ const ih = quadCanvas.height;
+ drawTriangleSub(
+ ctx, quadCanvas,
+ p1, p2, p4,
+ [0, 0], [iw, 0], [0, ih]);
+ drawTriangleSub(
+ ctx, quadCanvas,
+ p2, p3, p4,
+ [iw, 0], [iw, ih], [0, ih]);
+ }
+
+ if (quad.backgroundColor) {
+ ctx.fillStyle = quad.backgroundColor;
+ ctx.beginPath();
+ ctx.moveTo(p1[0], p1[1]);
+ ctx.lineTo(p2[0], p2[1]);
+ ctx.lineTo(p3[0], p3[1]);
+ ctx.lineTo(p4[0], p4[1]);
+ ctx.closePath();
+ ctx.fill();
+ }
+ }
+
+ function drawProjectedQuadOutlineToContext(
+ quad, p1, p2, p3, p4, ctx, quadCanvas) {
+ ctx.beginPath();
+ ctx.moveTo(p1[0], p1[1]);
+ ctx.lineTo(p2[0], p2[1]);
+ ctx.lineTo(p3[0], p3[1]);
+ ctx.lineTo(p4[0], p4[1]);
+ ctx.closePath();
+ ctx.save();
+ if (quad.borderColor) {
+ ctx.strokeStyle = quad.borderColor;
+ } else {
+ ctx.strokeStyle = 'rgb(128,128,128)';
+ }
+
+ if (quad.shadowOffset) {
+ ctx.shadowColor = 'rgb(0, 0, 0)';
+ ctx.shadowOffsetX = quad.shadowOffset[0];
+ ctx.shadowOffsetY = quad.shadowOffset[1];
+ if (quad.shadowBlur) {
+ ctx.shadowBlur = quad.shadowBlur;
+ }
+ }
+
+ if (quad.borderWidth) {
+ ctx.lineWidth = quad.borderWidth;
+ } else {
+ ctx.lineWidth = 1;
+ }
+
+ ctx.stroke();
+ ctx.restore();
+ }
+
+ function drawProjectedQuadSelectionOutlineToContext(
+ quad, p1, p2, p3, p4, ctx, quadCanvas) {
+ if (!quad.upperBorderColor) return;
+
+ ctx.lineWidth = 8;
+ ctx.strokeStyle = quad.upperBorderColor;
+
+ ctx.beginPath();
+ ctx.moveTo(p1[0], p1[1]);
+ ctx.lineTo(p2[0], p2[1]);
+ ctx.lineTo(p3[0], p3[1]);
+ ctx.lineTo(p4[0], p4[1]);
+ ctx.closePath();
+ ctx.stroke();
+ }
+
+ function drawProjectedQuadToContext(
+ passNumber, quad, p1, p2, p3, p4, ctx, quadCanvas) {
+ if (passNumber === 0) {
+ drawProjectedQuadBackgroundToContext(
+ quad, p1, p2, p3, p4, ctx, quadCanvas);
+ } else if (passNumber === 1) {
+ drawProjectedQuadOutlineToContext(
+ quad, p1, p2, p3, p4, ctx, quadCanvas);
+ } else if (passNumber === 2) {
+ drawProjectedQuadSelectionOutlineToContext(
+ quad, p1, p2, p3, p4, ctx, quadCanvas);
+ } else {
+ throw new Error('Invalid pass number');
+ }
+ }
+
+ const tmpP1 = vec3.create();
+ const tmpP2 = vec3.create();
+ const tmpP3 = vec3.create();
+ const tmpP4 = vec3.create();
+ function transformAndProcessQuads(
+ matrix, viewport, quads, numPasses, handleQuadFunc, opt_arg1, opt_arg2) {
+ for (let passNumber = 0; passNumber < numPasses; passNumber++) {
+ for (let i = 0; i < quads.length; i++) {
+ const quad = quads[i];
+ transform(tmpP1, quad.p1, matrix, viewport);
+ transform(tmpP2, quad.p2, matrix, viewport);
+ transform(tmpP3, quad.p3, matrix, viewport);
+ transform(tmpP4, quad.p4, matrix, viewport);
+ handleQuadFunc(passNumber, quad,
+ tmpP1, tmpP2, tmpP3, tmpP4,
+ opt_arg1, opt_arg2);
+ }
+ }
+ }
+
+ /**
+ * @constructor
+ */
+ const QuadStackView = tr.ui.b.define('quad-stack-view');
+
+ QuadStackView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.className = 'quad-stack-view';
+ this.style.display = 'flex';
+ this.style.position = 'relative';
+
+ const node = tr.ui.b.instantiateTemplate('#quad-stack-view-template',
+ THIS_DOC);
+ Polymer.dom(this).appendChild(node);
+ this.updateHeaderVisibility_();
+ const header = Polymer.dom(this).querySelector('#header');
+ header.style.position = 'absolute';
+ header.style.fontSize = '70%';
+ header.style.top = '10px';
+ header.style.left = '10px';
+ header.style.right = '150px';
+
+ const scroller = Polymer.dom(this).querySelector('#canvas-scroller');
+ scroller.style.flexGrow = 1;
+ scroller.style.flexShrink = 1;
+ scroller.style.flexBasis = 'auto';
+ scroller.style.minWidth = 0;
+ scroller.style.minHeight = 0;
+ scroller.style.overflow = 'auto';
+
+ this.canvas_ = Polymer.dom(this).querySelector('#canvas');
+ this.chromeImages_ = {
+ left: Polymer.dom(this).querySelector('#chrome-left'),
+ mid: Polymer.dom(this).querySelector('#chrome-mid'),
+ right: Polymer.dom(this).querySelector('#chrome-right')
+ };
+
+ const stackingDistanceSlider = Polymer.dom(this).querySelector(
+ '#stacking-distance-slider');
+ stackingDistanceSlider.style.position = 'absolute';
+ stackingDistanceSlider.style.fontSize = '70%';
+ stackingDistanceSlider.style.top = '10px';
+ stackingDistanceSlider.style.right = '10px';
+ stackingDistanceSlider.value = tr.b.Settings.get(
+ 'quadStackView.stackingDistance', 45);
+ stackingDistanceSlider.addEventListener(
+ 'change', this.onStackingDistanceChange_.bind(this));
+ stackingDistanceSlider.addEventListener(
+ 'input', this.onStackingDistanceChange_.bind(this));
+
+ this.trackMouse_();
+
+ this.camera_ = new tr.ui.b.Camera(this.mouseModeSelector_);
+ this.camera_.addEventListener('renderrequired',
+ this.onRenderRequired_.bind(this));
+ this.cameraWasReset_ = false;
+ this.camera_.canvas = this.canvas_;
+
+ this.viewportRect_ = tr.b.math.Rect.fromXYWH(0, 0, 0, 0);
+
+ this.pixelRatio_ = window.devicePixelRatio || 1;
+ },
+
+ updateHeaderVisibility_() {
+ if (this.headerText) {
+ Polymer.dom(this).querySelector('#header').style.display = '';
+ } else {
+ Polymer.dom(this).querySelector('#header').style.display = 'none';
+ }
+ },
+
+ get headerText() {
+ return Polymer.dom(this).querySelector('#header').textContent;
+ },
+
+ set headerText(headerText) {
+ Polymer.dom(this).querySelector('#header').textContent = headerText;
+ this.updateHeaderVisibility_();
+ },
+
+ onStackingDistanceChange_(e) {
+ tr.b.Settings.set('quadStackView.stackingDistance',
+ this.stackingDistance);
+ this.scheduleRender();
+ e.stopPropagation();
+ },
+
+ get stackingDistance() {
+ return Polymer.dom(this).querySelector('#stacking-distance-slider').value;
+ },
+
+ get mouseModeSelector() {
+ return this.mouseModeSelector_;
+ },
+
+ get camera() {
+ return this.camera_;
+ },
+
+ set quads(q) {
+ this.quads_ = q;
+ this.scheduleRender();
+ },
+
+ set deviceRect(rect) {
+ if (!rect || rect.equalTo(this.deviceRect_)) return;
+
+ this.deviceRect_ = rect;
+ this.camera_.deviceRect = rect;
+ this.chromeQuad_ = undefined;
+ },
+
+ resize() {
+ if (!this.offsetParent) return true;
+
+ const width = parseInt(window.getComputedStyle(this.offsetParent).width);
+ const height = parseInt(window.getComputedStyle(
+ this.offsetParent).height);
+ const rect = tr.b.math.Rect.fromXYWH(0, 0, width, height);
+
+ if (rect.equalTo(this.viewportRect_)) return false;
+
+ this.viewportRect_ = rect;
+ this.canvas_.style.width = width + 'px';
+ this.canvas_.style.height = height + 'px';
+ this.canvas_.width = this.pixelRatio_ * width;
+ this.canvas_.height = this.pixelRatio_ * height;
+ if (!this.cameraWasReset_) {
+ this.camera_.resetCamera();
+ this.cameraWasReset_ = true;
+ }
+ return true;
+ },
+
+ readyToDraw() {
+ // If src isn't set yet, set it to ensure we can use
+ // the image to draw onto a canvas.
+ if (!this.chromeImages_.left.src) {
+ let leftContent =
+ window.getComputedStyle(this.chromeImages_.left).backgroundImage;
+ leftContent = tr.ui.b.extractUrlString(leftContent);
+
+ let midContent =
+ window.getComputedStyle(this.chromeImages_.mid).backgroundImage;
+ midContent = tr.ui.b.extractUrlString(midContent);
+
+ let rightContent =
+ window.getComputedStyle(this.chromeImages_.right).backgroundImage;
+ rightContent = tr.ui.b.extractUrlString(rightContent);
+
+ this.chromeImages_.left.src = leftContent;
+ this.chromeImages_.mid.src = midContent;
+ this.chromeImages_.right.src = rightContent;
+ }
+
+ // If all of the images are loaded (height > 0), then
+ // we are ready to draw.
+ return (this.chromeImages_.left.height > 0) &&
+ (this.chromeImages_.mid.height > 0) &&
+ (this.chromeImages_.right.height > 0);
+ },
+
+ get chromeQuad() {
+ if (this.chromeQuad_) return this.chromeQuad_;
+
+ // Draw the chrome border into a separate canvas.
+ const chromeCanvas = document.createElement('canvas');
+ const offsetY = this.chromeImages_.left.height;
+
+ chromeCanvas.width = this.deviceRect_.width;
+ chromeCanvas.height = this.deviceRect_.height + offsetY;
+
+ const leftWidth = this.chromeImages_.left.width;
+ const midWidth = this.chromeImages_.mid.width;
+ const rightWidth = this.chromeImages_.right.width;
+
+ const chromeCtx = chromeCanvas.getContext('2d');
+ chromeCtx.drawImage(this.chromeImages_.left, 0, 0);
+
+ chromeCtx.save();
+ chromeCtx.translate(leftWidth, 0);
+
+ // Calculate the scale of the mid image.
+ const s = (this.deviceRect_.width - leftWidth - rightWidth) / midWidth;
+ chromeCtx.scale(s, 1);
+
+ chromeCtx.drawImage(this.chromeImages_.mid, 0, 0);
+ chromeCtx.restore();
+
+ chromeCtx.drawImage(
+ this.chromeImages_.right, leftWidth + s * midWidth, 0);
+
+ // Construct the quad.
+ const chromeRect = tr.b.math.Rect.fromXYWH(
+ this.deviceRect_.x,
+ this.deviceRect_.y - offsetY,
+ this.deviceRect_.width,
+ this.deviceRect_.height + offsetY);
+ const chromeQuad = tr.b.math.Quad.fromRect(chromeRect);
+ chromeQuad.stackingGroupId = this.maxStackingGroupId_ + 1;
+ chromeQuad.imageData = chromeCtx.getImageData(
+ 0, 0, chromeCanvas.width, chromeCanvas.height);
+ chromeQuad.shadowOffset = [0, 0];
+ chromeQuad.shadowBlur = 5;
+ chromeQuad.borderWidth = 3;
+ this.chromeQuad_ = chromeQuad;
+ return this.chromeQuad_;
+ },
+
+ scheduleRender() {
+ if (this.redrawScheduled_) return false;
+ this.redrawScheduled_ = true;
+ tr.b.requestAnimationFrame(this.render, this);
+ },
+
+ onRenderRequired_(e) {
+ this.scheduleRender();
+ },
+
+ stackTransformAndProcessQuads_(
+ numPasses, handleQuadFunc, includeChromeQuad, opt_arg1, opt_arg2) {
+ const mv = this.camera_.modelViewMatrix;
+ const p = this.camera_.projectionMatrix;
+
+ const viewport = tr.b.math.Rect.fromXYWH(
+ 0, 0, this.canvas_.width, this.canvas_.height);
+
+ // Calculate the quad stacks.
+ const quadStacks = [];
+ for (let i = 0; i < this.quads_.length; ++i) {
+ const quad = this.quads_[i];
+ const stackingId = quad.stackingGroupId || 0;
+ while (stackingId >= quadStacks.length) {
+ quadStacks.push([]);
+ }
+
+ quadStacks[stackingId].push(quad);
+ }
+
+ const mvp = mat4.create();
+ this.maxStackingGroupId_ = quadStacks.length;
+ const effectiveStackingDistance =
+ this.stackingDistance * this.camera_.stackingDistanceDampening;
+
+ // Draw the quad stacks, raising each subsequent level.
+ mat4.multiply(mvp, p, mv);
+ for (let i = 0; i < quadStacks.length; ++i) {
+ transformAndProcessQuads(mvp, viewport, quadStacks[i],
+ numPasses, handleQuadFunc,
+ opt_arg1, opt_arg2);
+
+ mat4.translate(mv, mv, [0, 0, effectiveStackingDistance]);
+ mat4.multiply(mvp, p, mv);
+ }
+
+ if (includeChromeQuad && this.deviceRect_) {
+ transformAndProcessQuads(mvp, viewport, [this.chromeQuad],
+ numPasses, drawProjectedQuadToContext,
+ opt_arg1, opt_arg2);
+ }
+ },
+
+ render() {
+ this.redrawScheduled_ = false;
+
+ if (!this.readyToDraw()) {
+ setTimeout(this.scheduleRender.bind(this),
+ constants.IMAGE_LOAD_RETRY_TIME_MS);
+ return;
+ }
+
+ if (!this.quads_) return;
+
+ const canvasCtx = this.canvas_.getContext('2d');
+ if (!this.resize()) {
+ canvasCtx.clearRect(0, 0, this.canvas_.width, this.canvas_.height);
+ }
+
+ const quadCanvas = document.createElement('canvas');
+ this.stackTransformAndProcessQuads_(
+ 3, drawProjectedQuadToContext, true,
+ canvasCtx, quadCanvas);
+ quadCanvas.width = 0; // Hack: Frees the quadCanvas' resources.
+ },
+
+ trackMouse_() {
+ this.mouseModeSelector_ = document.createElement(
+ 'tr-ui-b-mouse-mode-selector');
+ this.mouseModeSelector_.targetElement = this.canvas_;
+ this.mouseModeSelector_.supportedModeMask =
+ tr.ui.b.MOUSE_SELECTOR_MODE.SELECTION |
+ tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN |
+ tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM |
+ tr.ui.b.MOUSE_SELECTOR_MODE.ROTATE;
+ this.mouseModeSelector_.mode = tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN;
+ this.mouseModeSelector_.pos = {x: 0, y: 100};
+ Polymer.dom(this).appendChild(this.mouseModeSelector_);
+ this.mouseModeSelector_.settingsKey =
+ 'quadStackView.mouseModeSelector';
+
+ this.mouseModeSelector_.setModifierForAlternateMode(
+ tr.ui.b.MOUSE_SELECTOR_MODE.ROTATE, tr.ui.b.MODIFIER.SHIFT);
+ this.mouseModeSelector_.setModifierForAlternateMode(
+ tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN, tr.ui.b.MODIFIER.SPACE);
+ this.mouseModeSelector_.setModifierForAlternateMode(
+ tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM, tr.ui.b.MODIFIER.CMD_OR_CTRL);
+
+ this.mouseModeSelector_.addEventListener('updateselection',
+ this.onSelectionUpdate_.bind(this));
+ this.mouseModeSelector_.addEventListener('endselection',
+ this.onSelectionUpdate_.bind(this));
+ },
+
+ extractRelativeMousePosition_(e) {
+ const br = this.canvas_.getBoundingClientRect();
+ return [
+ this.pixelRatio_ * (e.clientX - this.canvas_.offsetLeft - br.left),
+ this.pixelRatio_ * (e.clientY - this.canvas_.offsetTop - br.top)
+ ];
+ },
+
+ onSelectionUpdate_(e) {
+ const mousePos = this.extractRelativeMousePosition_(e);
+ const res = [];
+ function handleQuad(passNumber, quad, p1, p2, p3, p4) {
+ if (tr.b.math.pointInImplicitQuad(mousePos, p1, p2, p3, p4)) {
+ res.push(quad);
+ }
+ }
+ this.stackTransformAndProcessQuads_(1, handleQuad, false);
+ e = new tr.b.Event('selectionchange');
+ e.quads = res;
+ this.dispatchEvent(e);
+ }
+ };
+
+ return {
+ QuadStackView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/radio_picker.html b/chromium/third_party/catapult/tracing/tracing/ui/base/radio_picker.html
new file mode 100644
index 00000000000..27edfb59152
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/radio_picker.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<dom-module id='tr-ui-b-radio-picker'>
+ <template>
+ <style>
+ :host([vertical]) #container {
+ flex-direction: column;
+ }
+ :host(:not[vertical]) #container {
+ flex-direction: row;
+ }
+ #container {
+ display: flex;
+ }
+ #container > div {
+ padding-left: 1em;
+ padding-bottom: 0.5em;
+ }
+ </style>
+ <div id="container"></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-radio-picker',
+
+ created() {
+ this.needsInit_ = true;
+ this.settingsKey_ = undefined;
+ this.isReady_ = false;
+ this.radioButtons_ = undefined;
+ // Keeping track of which key is selected. This member should only be set
+ // set inside select() method to make sure that logical state & the UI
+ // state is consistent.
+ this.selectedKey_ = undefined;
+ },
+
+ ready() {
+ this.isReady_ = true;
+ this.maybeInit_();
+ this.maybeRenderRadioButtons_();
+ },
+
+ get vertical() {
+ return this.getAttribute('vertical');
+ },
+
+ set vertical(vertical) {
+ if (vertical) {
+ this.setAttribute('vertical', true);
+ } else {
+ this.removeAttribute('vertical');
+ }
+ },
+
+ get settingsKey() {
+ return this.settingsKey_;
+ },
+
+ set settingsKey(settingsKey) {
+ if (!this.needsInit_) {
+ throw new Error('Already initialized.');
+ }
+ this.settingsKey_ = settingsKey;
+ this.maybeInit_();
+ },
+
+ maybeInit_() {
+ if (!this.needsInit_) return;
+ if (this.settingsKey_ === undefined) return;
+ this.needsInit_ = false;
+ this.select(tr.b.Settings.get(this.settingsKey_));
+ },
+
+ set items(items) {
+ this.radioButtons_ = {};
+ items.forEach(function(e) {
+ if (e.key in this.radioButtons_) {
+ throw new Error(e.key + ' already exists');
+ }
+ const radioButton = document.createElement('div');
+ const input = document.createElement('input');
+ const label = document.createElement('label');
+ input.type = 'radio';
+ input.id = e.label;
+ input.addEventListener('click', function() {
+ this.select(e.key);
+ }.bind(this));
+ Polymer.dom(label).innerHTML = e.label;
+ label.htmlFor = e.label;
+ label.style.display = 'inline';
+ Polymer.dom(radioButton).appendChild(input);
+ Polymer.dom(radioButton).appendChild(label);
+ this.radioButtons_[e.key] = input;
+ }.bind(this));
+
+ this.maybeInit_();
+ this.maybeRenderRadioButtons_();
+ },
+
+ maybeRenderRadioButtons_() {
+ if (!this.isReady_) return;
+ if (this.radioButtons_ === undefined) return;
+ for (const key in this.radioButtons_) {
+ Polymer.dom(this.$.container).appendChild(
+ this.radioButtons_[key].parentElement);
+ }
+ if (this.selectedKey_ !== undefined) {
+ this.select(this.selectedKey_);
+ }
+ },
+
+ select(key) {
+ if (key === undefined || key === this.selectedKey_) {
+ return;
+ }
+ if (this.radioButtons_ === undefined) {
+ this.selectedKey_ = key;
+ return;
+ }
+ if (!(key in this.radioButtons_)) {
+ throw new Error(key + ' does not exists');
+ }
+ // Unselect the previous radio, update the key & select the new one.
+ if (this.selectedKey_ !== undefined) {
+ this.radioButtons_[this.selectedKey_].checked = false;
+ }
+ this.selectedKey_ = key;
+ tr.b.Settings.set(this.settingsKey_, this.selectedKey_);
+ if (this.selectedKey_ !== undefined) {
+ this.radioButtons_[this.selectedKey_].checked = true;
+ }
+
+ this.dispatchEvent(new tr.b.Event('change', false));
+ },
+
+ get selectedKey() {
+ return this.selectedKey_;
+ },
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/radio_picker_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/radio_picker_test.html
new file mode 100644
index 00000000000..292cfaa4c9b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/radio_picker_test.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/radio_picker.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const rp = document.createElement('tr-ui-b-radio-picker');
+ rp.items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Boeing', label: 'I want to fly'},
+ {key: 'Submarine', label: 'I want to swim'}
+ ];
+ this.addHTMLOutput(rp);
+ assert.strictEqual(rp.selectedKey, undefined);
+ rp.select('Toyota');
+ assert.strictEqual(rp.selectedKey, 'Toyota');
+ });
+
+ test('persistentState_setSelectedKeyAfterSettingItems', function() {
+ const items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Boeing', label: 'I want to fly'},
+ {key: 'Submarine', label: 'I want to swim'}
+ ];
+ const container1 = tr.ui.b.createDiv({textContent: 'Radio Picker One'});
+ container1.style.border = 'solid';
+ const rp = document.createElement('tr-ui-b-radio-picker');
+ rp.items = items;
+ rp.settingsKey = 'radio-picker-test-one';
+ Polymer.dom(container1).appendChild(rp);
+ this.addHTMLOutput(container1);
+ assert.strictEqual(rp.selectedKey, undefined);
+ rp.select('Toyota');
+ assert.strictEqual(rp.selectedKey, 'Toyota');
+
+ const container2 = tr.ui.b.createDiv({
+ textContent: 'Radio Picker Two (same settingKey as Radio Picker One)'});
+ container2.style.border = 'solid';
+ const rp2 = document.createElement('tr-ui-b-radio-picker');
+ rp2.items = items;
+ rp2.settingsKey = 'radio-picker-test-one';
+ Polymer.dom(container2).appendChild(rp2);
+ this.addHTMLOutput(container2);
+
+ assert.strictEqual(rp2.selectedKey, 'Toyota');
+ });
+
+ test('persistentState_setSelectedKeyBeforeSettingItems', function() {
+ const items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Boeing', label: 'I want to fly'},
+ {key: 'Submarine', label: 'I want to swim'}
+ ];
+ const container1 = tr.ui.b.createDiv({textContent: 'Radio Picker One'});
+ container1.style.border = 'solid';
+ const rp = document.createElement('tr-ui-b-radio-picker');
+ rp.settingsKey = 'radio-picker-test-two';
+ rp.items = items;
+ Polymer.dom(container1).appendChild(rp);
+ this.addHTMLOutput(container1);
+ assert.strictEqual(rp.selectedKey, undefined);
+ rp.select('Boeing');
+ assert.strictEqual(rp.selectedKey, 'Boeing');
+
+ const container2 = tr.ui.b.createDiv({
+ textContent: 'Radio Picker Two (same settingKey as Radio Picker One)'});
+ container2.style.border = 'solid';
+ const rp2 = document.createElement('tr-ui-b-radio-picker');
+ rp2.settingsKey = 'radio-picker-test-two';
+ Polymer.dom(container2).appendChild(rp2);
+ this.addHTMLOutput(container2);
+ rp2.items = items;
+
+ assert.strictEqual(rp2.selectedKey, 'Boeing');
+ });
+
+ test('changeEventFired', function() {
+ const items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Boeing', label: 'I want to fly'},
+ {key: 'Submarine', label: 'I want to swim'}
+ ];
+ const rp = document.createElement('tr-ui-b-radio-picker');
+ rp.items = items;
+ this.addHTMLOutput(rp);
+ rp.select('Boeing');
+ assert.strictEqual(rp.selectedKey, 'Boeing');
+ let fired = false;
+ rp.addEventListener('change', function(e) {
+ fired = true;
+ assert.strictEqual('Toyota', e.target.selectedKey);
+ });
+ rp.select('Toyota');
+ assert.isTrue(fired);
+ });
+
+ test('verticalAttribute', function() {
+ const items = [
+ {key: 'Toyota', label: 'I want to drive Toyota'},
+ {key: 'Boeing', label: 'I want to fly'},
+ {key: 'Submarine', label: 'I want to swim'}
+ ];
+ const rp = document.createElement('tr-ui-b-radio-picker');
+ rp.items = items;
+ this.addHTMLOutput(rp);
+ assert.isNull(rp.getAttribute('vertical'));
+ rp.vertical = true;
+ assert.strictEqual(rp.getAttribute('vertical'), 'true');
+ rp.vertical = false;
+ assert.isNull(rp.getAttribute('vertical'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/scatter_chart.html b/chromium/third_party/catapult/tracing/tracing/ui/base/scatter_chart.html
new file mode 100644
index 00000000000..38b292e2360
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/scatter_chart.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/ui/base/chart_base_2d.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const ScatterChart = tr.ui.b.define('scatter-chart', tr.ui.b.ChartBase2D);
+
+ // @constructor
+ ScatterChart.Dot = function(x, y, radius, color, breadcrumb) {
+ this.x = x;
+ this.y = y;
+ this.radius = radius;
+ this.color = color;
+ this.breadcrumb = breadcrumb;
+ };
+
+ ScatterChart.prototype = {
+ __proto__: tr.ui.b.ChartBase2D.prototype,
+
+ decorate() {
+ super.decorate();
+ this.brushedXRange_ = new tr.b.math.Range();
+ this.brushedYRange_ = new tr.b.math.Range();
+ },
+
+ get hideLegend() {
+ return true;
+ },
+
+ get defaultGraphHeight() {
+ return 100;
+ },
+
+ get defaultGraphWidth() {
+ return 100;
+ },
+
+ updateMargins_() {
+ super.updateMargins_();
+ if (this.data.length === 0) return;
+
+ const rightOverhangPx = tr.b.math.Statistics.max(
+ this.data, d => this.xScale_(d.x) + d.radius - this.graphWidth);
+ this.margin.right = Math.max(this.margin.right, rightOverhangPx);
+
+ const topOverhangPx = tr.b.math.Statistics.max(
+ this.data, d => (this.graphHeight - this.yScale_(d.y)) + d.radius) -
+ this.graphHeight;
+ this.margin.top = Math.max(this.margin.top, topOverhangPx);
+ },
+
+ setBrushedRanges(xRange, yRange) {
+ this.brushedXRange_.reset();
+ this.brushedYRange_.reset();
+ this.brushedXRange_.addRange(xRange);
+ this.brushedYRange_.addRange(yRange);
+ this.updateContents_();
+ },
+
+ updateBrushContents_(brushSel) {
+ brushSel.selectAll('*').remove();
+ if (this.brushedXRange_.isEmpty || this.brushedYRange_.isEmpty) return;
+
+ const brushRectsSel = brushSel.selectAll('rect').data([undefined]);
+ brushRectsSel.enter().append('rect')
+ .attr('x', () => this.xScale_(this.brushedXRange_.min))
+ .attr('y', () => this.yScale_(this.brushedYRange_.max))
+ .attr('width', () => this.xScale_(this.brushedXRange_.max) -
+ this.xScale_(this.brushedXRange_.min))
+ .attr('height', () => this.yScale_(this.brushedYRange_.min) -
+ this.yScale_(this.brushedYRange_.max));
+ brushRectsSel.exit().remove();
+ },
+
+ setDataFromCallbacks(data, getX, getY, getRadius, getColor) {
+ this.data = data.map(d => new ScatterChart.Dot(
+ getX(d), getY(d), getRadius(d), getColor(d), d));
+ },
+
+ isDatumFieldSeries_(fieldName) {
+ return fieldName === 'y';
+ },
+
+ updateDataContents_(dataSel) {
+ dataSel.selectAll('*').remove();
+ dataSel.selectAll('circle')
+ .data(this.data_)
+ .enter()
+ .append('circle')
+ .attr('cx', d => this.xScale_(d.x))
+ .attr('cy', d => this.yScale_(d.y))
+ .attr('r', d => d.radius)
+ .attr('fill', d => d.color);
+ }
+ };
+
+ return {
+ ScatterChart,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/scatter_chart_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/scatter_chart_test.html
new file mode 100644
index 00000000000..a223589a2ac
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/scatter_chart_test.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/scatter_chart.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiation_singleSeries', function() {
+ const chart = new tr.ui.b.ScatterChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, y: 100, radius: 2, color: 'red'},
+ {x: 20, y: 110, radius: 20, color: 'blue'},
+ {x: 30, y: 100, radius: 10, color: 'red'},
+ {x: 40, y: 50, radius: 10, color: 'red'}
+ ];
+ });
+
+ test('instantiation_interactiveBrushing', function() {
+ const chart = new tr.ui.b.ScatterChart();
+ this.addHTMLOutput(chart);
+ chart.data = [
+ {x: 10, y: 50, radius: 2, color: 'blue'},
+ {x: 20, y: 60, radius: 3, color: 'red'},
+ {x: 30, y: 80, radius: 4, color: 'orange'},
+ {x: 40, y: 20, radius: 5, color: 'purple'},
+ {x: 50, y: 30, radius: 6, color: 'yellow'},
+ {x: 60, y: 20, radius: 7, color: 'green'},
+ {x: 70, y: 15, radius: 8, color: 'blue'},
+ {x: 80, y: 20, radius: 9, color: 'red'}
+ ];
+
+ let mouseDown = undefined;
+
+ function updateBrushedRange(e) {
+ const xRange = new tr.b.math.Range();
+ if (e.x !== mouseDown.x) {
+ xRange.addValue(mouseDown.x);
+ xRange.addValue(e.x);
+ }
+ const yRange = new tr.b.math.Range();
+ if (e.y !== mouseDown.y) {
+ yRange.addValue(mouseDown.y);
+ yRange.addValue(e.y);
+ }
+ chart.setBrushedRanges(xRange, yRange);
+ }
+
+ chart.addEventListener('item-mousedown', function(e) {
+ mouseDown = e;
+ });
+ chart.addEventListener('item-mousemove', function(e) {
+ updateBrushedRange(e);
+ });
+ chart.addEventListener('item-mouseup', function(e) {
+ updateBrushedRange(e);
+ mouseDown = undefined;
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view.html b/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view.html
new file mode 100644
index 00000000000..a651fc5cc3d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view.html
@@ -0,0 +1,273 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<!--
+@fileoverview A view that allows the user to control which single tab is
+displayed.
+
+We follow a fairly standard web convention of backing our tabs with hidden radio
+buttons but visible radio button labels (the tabs themselves) which toggle the
+input element when clicked. Using hidden radio buttons makes sense, as both tabs
+and radio buttons are input elements that allow user selection through clicking
+and limit users to having one option selected at a time.
+-->
+<dom-module id='tr-ui-b-tab-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+
+ #selection_description, #tabs {
+ font-size: 12px;
+ }
+
+ #selection_description {
+ display: inline-block;
+ font-weight: bold;
+ margin: 9px 0px 4px 20px;
+ }
+
+ #tabs {
+ flex: 0 0 auto;
+ border-top: 1px solid #8e8e8e;
+ border-bottom: 1px solid #8e8e8e;
+ background-color: #ececec;
+ overflow: hidden;
+ margin: 0;
+ }
+
+ #tabs input[type=radio] {
+ display: none;
+ }
+
+ #tabs tab label {
+ cursor: pointer;
+ display: inline-block;
+ border: 1px solid #ececec;
+ margin: 5px 0px 0px 15px;
+ padding: 3px 10px 3px 10px;
+ }
+
+ #tabs tab label span {
+ font-weight: bold;
+ }
+
+ #tabs:focus input[type=radio]:checked ~ label {
+ outline: dotted 1px #8e8e8e;
+ outline-offset: -2px;
+ }
+
+ #tabs input[type=radio]:checked ~ label {
+ background-color: white;
+ border: 1px solid #8e8e8e;
+ border-bottom: 1px solid white;
+ }
+
+ #subView {
+ flex: 1 1 auto;
+ min-width: 0;
+ display: flex;
+ }
+
+ #subView > * {
+ flex: 1 1 auto;
+ min-width: 0;
+ }
+ </style>
+ <div id='tabs' hidden="[[tabsHidden]]">
+ <label id=selection_description>[[label_]]</label>
+ <template is=dom-repeat items=[[subViews_]]>
+ <tab>
+ <input type=radio name=tabs id$=[[computeRadioId_(item)]]
+ on-change='onTabChanged_'
+ checked='[[isChecked_(item)]]'/>
+ <label for$=[[computeRadioId_(item)]]>
+ <template is=dom-if if=[[item.tabIcon]]>
+ <span style$='[[item.tabIcon.style]]'>[[item.tabIcon.text]]</span>
+ </template>
+ [[item.tabLabel]]
+ </label>
+ </tab>
+ </template>
+ </div>
+ <div id='subView'></div>
+ <slot>
+ </slot>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-tab-view',
+
+ properties: {
+ label_: {
+ type: String,
+ value: () => ''
+ },
+ selectedSubView_: Object,
+ subViews_: {
+ type: Array,
+ value: () => []
+ },
+ tabsHidden: {
+ type: Boolean,
+ value: false,
+ observer: 'tabsHiddenChanged_'
+ }
+ },
+
+ ready() {
+ this.$.tabs.addEventListener('keydown', this.onKeyDown_.bind(this), true);
+ this.updateFocusability_();
+ },
+
+ set label(newLabel) {
+ this.set('label_', newLabel);
+ },
+
+ get tabs() {
+ return this.get('subViews_');
+ },
+
+ get selectedSubView() {
+ return this.selectedSubView_;
+ },
+
+ set selectedSubView(subView) {
+ if (subView === this.selectedSubView_) return;
+
+ if (this.selectedSubView_) {
+ Polymer.dom(this.$.subView).removeChild(this.selectedSubView_);
+ const oldInput = this.root.getElementById(this.computeRadioId_(
+ this.selectedSubView_));
+ if (oldInput) {
+ oldInput.checked = false;
+ }
+ }
+
+ this.set('selectedSubView_', subView);
+
+ if (subView) {
+ Polymer.dom(this.$.subView).appendChild(subView);
+ const newInput = this.root.getElementById(this.computeRadioId_(subView));
+ if (newInput) {
+ newInput.checked = true;
+ }
+ }
+
+ this.fire('selected-tab-change');
+ },
+
+ clearSubViews() {
+ this.splice('subViews_', 0, this.subViews_.length);
+ this.selectedSubView = undefined;
+ this.updateFocusability_();
+ },
+
+ addSubView(subView) {
+ this.push('subViews_', subView);
+ if (!this.selectedSubView_) this.selectedSubView = subView;
+
+ this.updateFocusability_();
+ },
+
+ get subViews() {
+ return this.subViews_;
+ },
+
+ resetSubViews(subViews) {
+ this.splice('subViews_', 0, this.subViews_.length);
+ if (subViews.length) {
+ for (const subView of subViews) {
+ this.push('subViews_', subView);
+ }
+ this.selectedSubView = subViews[0];
+ } else {
+ this.selectedSubView = undefined;
+ }
+ this.updateFocusability_();
+ },
+
+ onTabChanged_(event) {
+ this.selectedSubView = event.model.item;
+ },
+
+ isChecked_(subView) {
+ return this.selectedSubView_ === subView;
+ },
+
+ tabsHiddenChanged_() {
+ this.updateFocusability_();
+ },
+
+ onKeyDown_(e) {
+ if (this.tabsHidden) return;
+
+ let keyHandled = false;
+ switch (e.keyCode) {
+ // Arrow left.
+ case 37:
+ keyHandled = this.selectPreviousTabIfPossible();
+ break;
+
+ // Arrow right.
+ case 39:
+ keyHandled = this.selectNextTabIfPossible();
+ break;
+ }
+
+ if (!keyHandled) return;
+ e.stopPropagation();
+ e.preventDefault();
+ },
+
+ selectNextTabIfPossible() {
+ return this.selectTabByOffsetIfPossible_(1);
+ },
+
+ selectPreviousTabIfPossible() {
+ return this.selectTabByOffsetIfPossible_(-1);
+ },
+
+ selectTabByOffsetIfPossible_(offset) {
+ if (!this.selectedSubView_) return false;
+ const currentIndex = this.subViews_.indexOf(this.selectedSubView_);
+ const newSubView = this.tabs[currentIndex + offset];
+ if (!newSubView) return false;
+ this.selectedSubView = newSubView;
+ return true;
+ },
+
+ shouldBeFocusable_() {
+ return !this.tabsHidden && this.subViews_.length > 0;
+ },
+
+ updateFocusability_() {
+ if (this.shouldBeFocusable_()) {
+ Polymer.dom(this.$.tabs).setAttribute('tabindex', 0);
+ } else {
+ Polymer.dom(this.$.tabs).removeAttribute('tabindex');
+ }
+ },
+
+ computeRadioId_(subView) {
+ // We can't just use the tagName as the radio's ID because there are
+ // instances where a single subview type can handle multiple event types,
+ // and thus might be present multiple times in a single tab view. In order
+ // to avoid the case where we might have two tabs with the same ID, we
+ // uniquify this ID by appending the tab's label with all spaces replaced
+ // by dashes (because spaces aren't allowed in HTML IDs).
+ return subView.tagName + '-' + subView.tabLabel.replace(/ /g, '-');
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html
new file mode 100644
index 00000000000..d5e9c19e672
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/tab_view_test.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/power_series.html">
+<link rel="import" href="/tracing/ui/analysis/alert_sub_view.html">
+<link rel="import" href="/tracing/ui/analysis/multi_power_sample_sub_view.html">
+<link rel="import" href="/tracing/ui/base/tab_view.html">
+
+<dom-module id='tr-ui-b-tab-view-test-non-sub-view'>
+ <template>
+ <div></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+const nonSubViewBehavior = {};
+
+Polymer({
+ is: 'tr-ui-b-tab-view-test-non-sub-view',
+ behaviors: [nonSubViewBehavior]
+});
+
+tr.b.unittest.testSuite(function() {
+ function createPowerSampleSubView() {
+ const model = tr.c.TestUtils.newModel(function(m) {
+ m.device.powerSeries = new tr.model.PowerSeries(m.device);
+
+ m.device.vSyncTimestamps = [0];
+ m.device.powerSeries.addPowerSample(1, 1);
+ m.device.powerSeries.addPowerSample(2, 2);
+ m.device.powerSeries.addPowerSample(3, 3);
+ m.device.powerSeries.addPowerSample(4, 2);
+ });
+
+ const subView = document.createElement(
+ 'tr-ui-a-multi-power-sample-sub-view');
+ subView.selection = new tr.model.EventSet(model.device.powerSeries.samples);
+ subView.tabLabel = 'Power samples';
+ return subView;
+ }
+
+ function createAlertSubView() {
+ const slice = tr.c.TestUtils.newSliceEx(
+ {title: 'b', start: 0, duration: 0.002});
+ const alertInfo = new tr.model.EventInfo(
+ 'Alert 1', 'Critical alert',
+ [{
+ label: 'Example',
+ textContent: 'Example page',
+ href: 'http://www.example.com'
+ }]);
+
+ const alert = new tr.model.Alert(alertInfo, 5, [slice]);
+ const subView = document.createElement('tr-ui-a-alert-sub-view');
+ subView.selection = new tr.model.EventSet(alert);
+ subView.tabLabel = 'Alerts';
+ subView.tabIcon = { text: '\u26A0', style: 'color: red;' };
+
+ return subView;
+ }
+
+ test('instantiate_noTabs', function() {
+ const tabView = document.createElement('tr-ui-b-tab-view');
+ tabView.label = 'No items selected.';
+ this.addHTMLOutput(tabView);
+ });
+
+ test('instantiate_oneTab', function() {
+ const tabView = document.createElement('tr-ui-b-tab-view');
+ tabView.label = '1 item selected.';
+ tabView.addSubView(createPowerSampleSubView());
+ this.addHTMLOutput(tabView);
+ });
+
+ test('instantiate_twoTabs', function() {
+ const tabView = document.createElement('tr-ui-b-tab-view');
+ tabView.label = '3 items selected.';
+ tabView.addSubView(createPowerSampleSubView());
+ tabView.addSubView(createAlertSubView());
+ this.addHTMLOutput(tabView);
+ });
+
+ test('clearSubViews_selectedSubViewNullAfter', function() {
+ const tabView = document.createElement('tr-ui-b-tab-view');
+ tabView.label = '3 items selected.';
+ tabView.addSubView(createPowerSampleSubView());
+ tabView.addSubView(createAlertSubView());
+
+ tabView.clearSubViews();
+
+ assert.isUndefined(tabView.selectedSubView);
+ });
+
+ test('changeSelectedSubView', function() {
+ let selectedTabChangeEventCount = 0;
+ const tabView = document.createElement('tr-ui-b-tab-view');
+ tabView.addEventListener('selected-tab-change', function() {
+ selectedTabChangeEventCount++;
+ });
+
+ assert.isUndefined(tabView.selectedSubView);
+ assert.strictEqual(selectedTabChangeEventCount, 0);
+
+ const view1 = createPowerSampleSubView();
+ tabView.addSubView(view1);
+ assert.strictEqual(tabView.selectedSubView, view1);
+ assert.strictEqual(selectedTabChangeEventCount, 1);
+
+ const view2 = createAlertSubView();
+ tabView.addSubView(view2);
+ assert.strictEqual(tabView.selectedSubView, view1);
+ assert.strictEqual(selectedTabChangeEventCount, 1);
+
+ tabView.selectedSubView = view2;
+ assert.strictEqual(tabView.selectedSubView, view2);
+ assert.strictEqual(selectedTabChangeEventCount, 2);
+ });
+
+ // Regression test: https://github.com/catapult-project/catapult/issues/2754
+ test('instantiate_twoTabsSwitch', function() {
+ const tabView = document.createElement('tr-ui-b-tab-view');
+ tabView.label = '3 items selected.';
+ tabView.addSubView(createPowerSampleSubView());
+ tabView.addSubView(createAlertSubView());
+ this.addHTMLOutput(tabView);
+ Polymer.dom.flush();
+
+ tabView.selectedSubView = tabView.tabs[1];
+ Polymer.dom.flush();
+
+ const selectedLabel = tabView.$.tabs.querySelector(':checked ~ label');
+ assert.isTrue(selectedLabel && selectedLabel.innerText.includes('Alerts'));
+ });
+
+ // Regression test: https://github.com/catapult-project/catapult/issues/2755
+ test('instantiate_twoTabsSwitchAndChange', function() {
+ const tabView = document.createElement('tr-ui-b-tab-view');
+ this.addHTMLOutput(tabView);
+ tabView.addSubView(createPowerSampleSubView());
+ tabView.addSubView(createAlertSubView());
+ Polymer.dom.flush();
+
+ tabView.$.tabs.querySelectorAll('label')[2].click();
+ tabView.$.tabs.querySelectorAll('label')[1].click();
+ tabView.clearSubViews();
+ tabView.addSubView(createPowerSampleSubView());
+ Polymer.dom.flush();
+
+ assert.isTrue(!!tabView.$.tabs.querySelector(':checked'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/table.html b/chromium/third_party/catapult/tracing/tracing/ui/base/table.html
new file mode 100644
index 00000000000..3d707fb4b87
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/table.html
@@ -0,0 +1,1808 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<!--
+@fileoverview A container that constructs a table-like container.
+-->
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const TableFormat = {};
+
+ TableFormat.SelectionMode = {
+ // Selection disabled.
+ // Default highlight: none.
+ NONE: 0,
+
+ // Row selection mode.
+ // Default highlight: dark row.
+ ROW: 1,
+
+ // Cell selection mode.
+ // Default highlight: dark cell and light row.
+ CELL: 2
+ };
+
+ TableFormat.HighlightStyle = {
+ // Highlight depends on the current selection mode.
+ DEFAULT: 0,
+
+ // No highlight.
+ NONE: 1,
+
+ // Light highlight.
+ LIGHT: 2,
+
+ // Dark highlight.
+ DARK: 3
+ };
+
+ TableFormat.ColumnAlignment = {
+ LEFT: 0 /* default */,
+ RIGHT: 1
+ };
+
+ return {
+ TableFormat,
+ };
+});
+</script>
+
+<dom-module id="tr-ui-b-table">
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+
+ table {
+ flex: 1 1 auto;
+ align-self: stretch;
+ border-collapse: separate;
+ border-spacing: 0;
+ border-width: 0;
+ -webkit-user-select: initial;
+ }
+
+ tr > td {
+ padding: 2px 4px 2px 4px;
+ vertical-align: top;
+ }
+
+ table > tbody:focus {
+ outline: none;
+ }
+ table > tbody:focus[selection-mode="row"] > tr[selected],
+ table > tbody:focus[selection-mode="cell"] > tr > td[selected],
+ table > tbody:focus > tr.empty-row > td {
+ outline: 1px dotted #666666;
+ outline-offset: -1px;
+ }
+
+ button.toggle-button {
+ height: 15px;
+ line-height: 60%;
+ vertical-align: middle;
+ width: 100%;
+ }
+
+ button > * {
+ height: 15px;
+ vertical-align: middle;
+ }
+
+ td.button-column {
+ width: 30px;
+ }
+
+ table > thead > tr > td.sensitive:hover {
+ background-color: #fcfcfc;
+ }
+
+ table > thead > tr > td {
+ font-weight: bold;
+ text-align: left;
+
+ background-color: #eee;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ border-top: 1px solid #ffffff;
+ border-bottom: 1px solid #aaa;
+ }
+
+ table > tfoot {
+ background-color: #eee;
+ font-weight: bold;
+ }
+
+ /* Light row and cell highlight. */
+ table > tbody[row-highlight-style="light"] > tr[selected],
+ table > tbody[cell-highlight-style="light"] > tr > td[selected] {
+ background-color: rgb(213, 236, 229); /* light turquoise */
+ }
+ table > tbody[row-highlight-style="light"] >
+ tr:not(.empty-row):not([selected]):hover,
+ table > tbody[cell-highlight-style="light"] >
+ tr:not(.empty-row):not([selected]) > td:hover {
+ background-color: #f6f6f6; /* light grey */
+ }
+
+ /* Dark row and cell highlight. */
+ table > tbody[row-highlight-style="dark"] > tr[selected],
+ table > tbody[cell-highlight-style="dark"] > tr > td[selected] {
+ background-color: rgb(103, 199, 165); /* turquoise */
+ }
+ table > tbody[row-highlight-style="dark"] >
+ tr:not(.empty-row):not([selected]):hover,
+ table > tbody[cell-highlight-style="dark"] >
+ tr:not(.empty-row):not([selected]) > td:hover {
+ background-color: #e6e6e6; /* grey */
+ }
+ table > tbody[row-highlight-style="dark"] > tr:hover[selected],
+ table > tbody[cell-highlight-style="dark"] > tr[selected] > td:hover {
+ background-color: rgb(171, 217, 202); /* semi-light turquoise */
+ }
+
+ table > colgroup > col[selected] {
+ background-color: #e6e6e6; /* grey */
+ }
+
+ table > tbody > tr.empty-row > td {
+ color: #666;
+ font-style: italic;
+ text-align: center;
+ }
+
+ table > tbody.has-footer > tr:last-child > td {
+ border-bottom: 1px solid #aaa;
+ }
+
+ table > tfoot > tr:first-child > td {
+ border-top: 1px solid #ffffff;
+ }
+
+ :host([zebra]) table tbody tr:nth-child(even) {
+ background-color: #f4f4f4;
+ }
+
+ expand-button {
+ -webkit-user-select: none;
+ cursor: pointer;
+ margin-right: 3px;
+ font-size: smaller;
+ height: 1rem;
+ }
+
+ expand-button.button-expanded {
+ transform: rotate(90deg);
+ }
+ </style>
+ <table>
+ <colgroup id="cols">
+ </colgroup>
+ <thead id="head">
+ </thead>
+ <tbody id="body">
+ </tbody>
+ <tfoot id="foot">
+ </tfoot>
+ </table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+(function() {
+ const RIGHT_ARROW = String.fromCharCode(0x25b6);
+ const UNSORTED_ARROW = String.fromCharCode(0x25BF);
+ const ASCENDING_ARROW = String.fromCharCode(0x25B4);
+ const DESCENDING_ARROW = String.fromCharCode(0x25BE);
+
+ const SelectionMode = tr.ui.b.TableFormat.SelectionMode;
+ const SelectionModeValues = new Set(Object.values(SelectionMode));
+ const HighlightStyle = tr.ui.b.TableFormat.HighlightStyle;
+ const HighlightStyleValues = new Set(Object.values(HighlightStyle));
+ const ColumnAlignment = tr.ui.b.TableFormat.ColumnAlignment;
+ const ColumnAlignmentValues = new Set(Object.values(ColumnAlignment));
+
+ Polymer({
+ is: 'tr-ui-b-table',
+
+ created() {
+ this.selectionMode_ = SelectionMode.NONE;
+ this.rowHighlightStyle_ = HighlightStyle.DEFAULT;
+ this.cellHighlightStyle_ = HighlightStyle.DEFAULT;
+ this.selectedTableRowInfo_ = undefined;
+ this.selectedColumnIndex_ = undefined;
+
+ this.tableColumns_ = [];
+ this.tableRows_ = [];
+ this.tableRowsInfo_ = new WeakMap();
+ this.tableFooterRows_ = [];
+ this.tableFooterRowsInfo_ = new WeakMap();
+ this.sortColumnIndex_ = undefined;
+ this.sortDescending_ = false;
+ this.columnsWithExpandButtons_ = [];
+ this.headerCells_ = [];
+ this.showHeader_ = true;
+ this.emptyValue_ = undefined;
+ this.subRowsPropertyName_ = 'subRows';
+ this.customizeTableRowCallback_ = undefined;
+ this.defaultExpansionStateCallback_ = undefined;
+ this.userCanModifySortOrder_ = true;
+ this.computedFontSizePx_ = undefined;
+ },
+
+ ready() {
+ this.$.body.addEventListener(
+ 'keydown', this.onKeyDown_.bind(this), true);
+ this.$.body.addEventListener(
+ 'focus', this.onFocus_.bind(this), true);
+ },
+
+ clear() {
+ this.selectionMode_ = SelectionMode.NONE;
+ this.rowHighlightStyle_ = HighlightStyle.DEFAULT;
+ this.cellHighlightStyle_ = HighlightStyle.DEFAULT;
+ this.selectedTableRowInfo_ = undefined;
+ this.selectedColumnIndex_ = undefined;
+
+ Polymer.dom(this).textContent = '';
+ this.tableColumns_ = [];
+ this.tableRows_ = [];
+ this.tableRowsInfo_ = new WeakMap();
+ this.tableFooterRows_ = [];
+ this.tableFooterRowsInfo_ = new WeakMap();
+ this.sortColumnIndex_ = undefined;
+ this.sortDescending_ = false;
+ this.columnsWithExpandButtons_ = [];
+ this.headerCells_ = [];
+ this.showHeader_ = true;
+ this.emptyValue_ = undefined;
+ this.subRowsPropertyName_ = 'subRows';
+ this.defaultExpansionStateCallback_ = undefined;
+ this.userCanModifySortOrder_ = true;
+ },
+
+ set zebra(zebra) {
+ if (zebra) {
+ this.setAttribute('zebra', true);
+ } else {
+ this.removeAttribute('zebra');
+ }
+ },
+
+ get zebra() {
+ return this.getAttribute('zebra');
+ },
+
+ get showHeader() {
+ return this.showHeader_;
+ },
+
+ set showHeader(showHeader) {
+ this.showHeader_ = showHeader;
+ this.scheduleRebuildHeaders_();
+ },
+
+ set subRowsPropertyName(name) {
+ this.subRowsPropertyName_ = name;
+ },
+
+ /**
+ * This callback will be called whenever a body row is built
+ * for a userRow that has subRows and does not have an explicit
+ * isExpanded field.
+ * The callback should return true if the row should be expanded,
+ * or false if the row should be collapsed.
+ * @param {function(userRow, parentUserRow): boolean} cb The callback.
+ */
+ set defaultExpansionStateCallback(cb) {
+ this.defaultExpansionStateCallback_ = cb;
+ this.scheduleRebuildBody_();
+ },
+
+ /**
+ * This callback will be called whenever a body row is built.
+ * The callback's return value is ignored.
+ * @param {function(userRow, trElement)} cb The callback.
+ */
+ set customizeTableRowCallback(cb) {
+ this.customizeTableRowCallback_ = cb;
+ this.scheduleRebuildBody_();
+ },
+
+ get emptyValue() {
+ return this.emptyValue_;
+ },
+
+ set emptyValue(emptyValue) {
+ const previousEmptyValue = this.emptyValue_;
+ this.emptyValue_ = emptyValue;
+ if (this.tableRows_.length === 0 && emptyValue !== previousEmptyValue) {
+ this.scheduleRebuildBody_();
+ }
+ },
+
+ /**
+ * Data objects should have the following fields:
+ * mandatory: title, value
+ * optional: width {string}, cmp {function}, colSpan {number},
+ * showExpandButtons {boolean},
+ * align {tr.ui.b.TableFormat.ColumnAlignment}
+ *
+ * @param {Array} columns An array of data objects.
+ */
+ set tableColumns(columns) {
+ // Figure out the columns with expand buttons...
+ let columnsWithExpandButtons = [];
+ for (let i = 0; i < columns.length; i++) {
+ if (columns[i].showExpandButtons) {
+ columnsWithExpandButtons.push(i);
+ }
+ }
+ if (columnsWithExpandButtons.length === 0) {
+ // First column if none have specified.
+ columnsWithExpandButtons = [0];
+ }
+
+ // Sanity check columns.
+ for (let i = 0; i < columns.length; i++) {
+ const colInfo = columns[i];
+ if (colInfo.width === undefined) continue;
+
+ const hasExpandButton = columnsWithExpandButtons.includes(i);
+
+ const w = colInfo.width;
+ if (w) {
+ if (/\d+px/.test(w)) {
+ continue;
+ } else if (/\d+%/.test(w)) {
+ if (hasExpandButton) {
+ throw new Error('Columns cannot be %-sized and host ' +
+ ' an expand button');
+ }
+ } else {
+ throw new Error('Unrecognized width string');
+ }
+ }
+ }
+
+ // Try to preserve the user's sort choice.
+ // This is a 'best-effort' attempt, for example we compare columns by
+ // thier titles which can be HTML nodes in which case we might consider
+ // them different even if they look the same to the user.
+ let sortIndex = undefined;
+ const currentSortColumn = this.tableColumns[this.sortColumnIndex_];
+ if (currentSortColumn) {
+ for (const [i, column] of columns.entries()) {
+ if (currentSortColumn.title === column.title) {
+ sortIndex = i;
+ break;
+ }
+ }
+ }
+
+ // Commit the change.
+ this.tableColumns_ = columns;
+ this.headerCells_ = [];
+ this.columnsWithExpandButtons_ = columnsWithExpandButtons;
+ this.scheduleRebuildHeaders_();
+ this.sortColumnIndex = sortIndex;
+
+ // Blow away the table rows, too.
+ this.tableRows = this.tableRows_;
+ },
+
+ get tableColumns() {
+ return this.tableColumns_;
+ },
+
+ /**
+ * @param {Array} rows An array of 'row' objects with the following
+ * fields:
+ * optional: subRows An array of objects that have the same 'row'
+ * structure. Set subRowsPropertyName to use an
+ * alternative field name.
+ */
+ set tableRows(rows) {
+ this.selectedTableRowInfo_ = undefined;
+ this.selectedColumnIndex_ = undefined;
+ this.tableRows_ = rows;
+ this.tableRowsInfo_ = new WeakMap();
+ this.scheduleRebuildBody_();
+ },
+
+ get tableRows() {
+ return this.tableRows_;
+ },
+
+ set footerRows(rows) {
+ this.tableFooterRows_ = rows;
+ this.tableFooterRowsInfo_ = new WeakMap();
+ this.scheduleRebuildFooter_();
+ },
+
+ get footerRows() {
+ return this.tableFooterRows_;
+ },
+
+ get userCanModifySortOrder() {
+ return this.userCanModifySortOrder_;
+ },
+
+ set userCanModifySortOrder(userCanModifySortOrder) {
+ const newUserCanModifySortOrder = !!userCanModifySortOrder;
+ if (newUserCanModifySortOrder === this.userCanModifySortOrder_) {
+ return;
+ }
+
+ this.userCanModifySortOrder_ = newUserCanModifySortOrder;
+ this.scheduleRebuildHeaders_();
+ },
+
+ set sortColumnIndex(number) {
+ if (number === this.sortColumnIndex_) return;
+
+ if (number !== undefined) {
+ if (this.tableColumns_.length <= number) {
+ throw new Error('Column number ' + number + ' is out of bounds.');
+ }
+ if (!this.tableColumns_[number].cmp) {
+ throw new Error('Column ' + number + ' does not have a comparator.');
+ }
+ }
+
+ this.sortColumnIndex_ = number;
+ this.updateHeaderArrows_();
+ this.scheduleRebuildBody_();
+ this.dispatchSortingChangedEvent_();
+ },
+
+ get sortColumnIndex() {
+ return this.sortColumnIndex_;
+ },
+
+ set sortDescending(value) {
+ const newValue = !!value;
+
+ if (newValue !== this.sortDescending_) {
+ this.sortDescending_ = newValue;
+ this.updateHeaderArrows_();
+ this.scheduleRebuildBody_();
+ this.dispatchSortingChangedEvent_();
+ }
+ },
+
+ get sortDescending() {
+ return this.sortDescending_;
+ },
+
+ updateHeaderArrows_() {
+ for (let i = 0; i < this.headerCells_.length; i++) {
+ const headerCell = this.headerCells_[i];
+ const isColumnCurrentlySorted = i === this.sortColumnIndex_;
+ if (!this.tableColumns_[i].cmp ||
+ (!this.userCanModifySortOrder_ && !isColumnCurrentlySorted)) {
+ headerCell.sideContent = '';
+ continue;
+ }
+ if (!isColumnCurrentlySorted) {
+ headerCell.sideContent = UNSORTED_ARROW;
+ headerCell.sideContentDisabled = false;
+ continue;
+ }
+ headerCell.sideContent = this.sortDescending_ ?
+ DESCENDING_ARROW : ASCENDING_ARROW;
+ headerCell.sideContentDisabled = !this.userCanModifySortOrder_;
+ }
+ },
+
+ generateHeaderColumns_() {
+ const selectedTableColumnIndex = this.selectedTableColumnIndex;
+ Polymer.dom(this.$.cols).textContent = '';
+ for (let i = 0; i < this.tableColumns_.length; ++i) {
+ const colElement = document.createElement('col');
+ if (i === selectedTableColumnIndex) {
+ colElement.setAttribute('selected', true);
+ }
+ Polymer.dom(this.$.cols).appendChild(colElement);
+ }
+
+ this.headerCells_ = [];
+ Polymer.dom(this.$.head).textContent = '';
+ if (!this.showHeader_) return;
+
+ const tr = this.appendNewElement_(this.$.head, 'tr');
+ for (let i = 0; i < this.tableColumns_.length; i++) {
+ const td = this.appendNewElement_(tr, 'td');
+
+ const headerCell = document.createElement('tr-ui-b-table-header-cell');
+ headerCell.column = this.tableColumns_[i];
+
+ // If the table can be sorted by this column and the user can modify
+ // the sort order, attach a tap callback to the column.
+ if (this.tableColumns_[i].cmp) {
+ const isColumnCurrentlySorted = i === this.sortColumnIndex_;
+ if (isColumnCurrentlySorted) {
+ headerCell.sideContent = this.sortDescending_ ?
+ DESCENDING_ARROW : ASCENDING_ARROW;
+ if (!this.userCanModifySortOrder_) {
+ headerCell.sideContentDisabled = true;
+ }
+ }
+ if (this.userCanModifySortOrder_) {
+ Polymer.dom(td).classList.add('sensitive');
+ if (!isColumnCurrentlySorted) {
+ headerCell.sideContent = UNSORTED_ARROW;
+ }
+ headerCell.tapCallback = this.createSortCallback_(i);
+ }
+ }
+
+ Polymer.dom(td).appendChild(headerCell);
+ this.headerCells_.push(headerCell);
+ }
+ },
+
+ applySizes_() {
+ if (this.tableRows_.length === 0 && !this.showHeader) return;
+
+ let rowToRemoveSizing;
+ let rowToSize;
+ if (this.showHeader) {
+ rowToSize = Polymer.dom(this.$.head).children[0];
+ rowToRemoveSizing = Polymer.dom(this.$.body).children[0];
+ } else {
+ rowToSize = Polymer.dom(this.$.body).children[0];
+ rowToRemoveSizing = Polymer.dom(this.$.head).children[0];
+ }
+ for (let i = 0; i < this.tableColumns_.length; i++) {
+ if (rowToRemoveSizing && Polymer.dom(rowToRemoveSizing).children[i]) {
+ const tdToRemoveSizing = Polymer.dom(rowToRemoveSizing).children[i];
+ tdToRemoveSizing.style.minWidth = '';
+ tdToRemoveSizing.style.width = '';
+ }
+
+ // Apply sizing.
+ const td = Polymer.dom(rowToSize).children[i];
+
+ let delta;
+ if (this.columnsWithExpandButtons_.includes(i)) {
+ td.style.paddingLeft = this.basicIndentation_ + 'px';
+ delta = this.basicIndentation_ + 'px';
+ } else {
+ delta = undefined;
+ }
+
+ function calc(base, delta) {
+ if (delta) {
+ return 'calc(' + base + ' - ' + delta + ')';
+ }
+ return base;
+ }
+
+ const w = this.tableColumns_[i].width;
+ if (w) {
+ if (/\d+px/.test(w)) {
+ td.style.minWidth = calc(w, delta);
+ } else if (/\d+%/.test(w)) {
+ td.style.width = w;
+ } else {
+ throw new Error('Unrecognized width string: ' + w);
+ }
+ }
+ }
+ },
+
+ createSortCallback_(columnNumber) {
+ return function() {
+ if (!this.userCanModifySortOrder_) return;
+
+ const previousIndex = this.sortColumnIndex;
+ this.sortColumnIndex = columnNumber;
+ if (previousIndex !== columnNumber) {
+ this.sortDescending = false;
+ } else {
+ this.sortDescending = !this.sortDescending;
+ }
+ }.bind(this);
+ },
+
+ generateTableRowNodes_(tableSection, userRows, rowInfoMap,
+ indentation, lastAddedRow,
+ parentRowInfo) {
+ if (this.sortColumnIndex_ !== undefined &&
+ tableSection === this.$.body) {
+ userRows = userRows.slice(); // Don't mess with the input data.
+ userRows.sort(function(rowA, rowB) {
+ let c = this.tableColumns_[this.sortColumnIndex_].cmp(
+ rowA, rowB);
+ if (this.sortDescending_) {
+ c = -c;
+ }
+ return c;
+ }.bind(this));
+ }
+
+ for (let i = 0; i < userRows.length; i++) {
+ const userRow = userRows[i];
+ const rowInfo = this.getOrCreateRowInfoFor_(rowInfoMap, userRow,
+ parentRowInfo);
+ const htmlNode = this.getHTMLNodeForRowInfo_(
+ tableSection, rowInfo, rowInfoMap, indentation);
+
+ if (lastAddedRow === undefined) {
+ // Put first into the table.
+ Polymer.dom(tableSection).insertBefore(
+ htmlNode, Polymer.dom(tableSection).firstChild);
+ } else {
+ // This is shorthand for insertAfter(htmlNode, lastAdded).
+ const nextSiblingOfLastAdded = Polymer.dom(lastAddedRow).nextSibling;
+ Polymer.dom(tableSection).insertBefore(
+ htmlNode, nextSiblingOfLastAdded);
+ }
+
+ lastAddedRow = htmlNode;
+ if (!rowInfo.isExpanded) continue;
+
+ // Append subrows now.
+ lastAddedRow = this.generateTableRowNodes_(
+ tableSection, userRow[this.subRowsPropertyName_], rowInfoMap,
+ indentation + 1, lastAddedRow, rowInfo);
+ }
+ return lastAddedRow;
+ },
+
+ getOrCreateRowInfoFor_(rowInfoMap, userRow, parentRowInfo) {
+ let rowInfo = undefined;
+
+ if (rowInfoMap.has(userRow)) {
+ rowInfo = rowInfoMap.get(userRow);
+ } else {
+ rowInfo = {
+ userRow,
+ htmlNode: undefined,
+ parentRowInfo
+ };
+ rowInfoMap.set(userRow, rowInfo);
+ }
+
+ // Recompute isExpanded in case defaultExpansionStateCallback_ has
+ // changed.
+ rowInfo.isExpanded = this.getExpandedForUserRow_(userRow);
+
+ return rowInfo;
+ },
+
+ customizeTableRow_(userRow, trElement) {
+ if (!this.customizeTableRowCallback_) return;
+ this.customizeTableRowCallback_(userRow, trElement);
+ },
+
+ get basicIndentation_() {
+ if (this.computedFontSizePx_ === undefined) {
+ this.computedFontSizePx_ = parseInt(
+ getComputedStyle(this).fontSize) || 16;
+ }
+ return this.computedFontSizePx_ - 2;
+ },
+
+ getHTMLNodeForRowInfo_(tableSection, rowInfo,
+ rowInfoMap, indentation) {
+ if (rowInfo.htmlNode) {
+ this.customizeTableRow_(rowInfo.userRow, rowInfo.htmlNode);
+ return rowInfo.htmlNode;
+ }
+
+ const INDENT_SPACE = indentation * 16;
+ const INDENT_SPACE_NO_BUTTON = indentation * 16 + this.basicIndentation_;
+ const trElement = this.ownerDocument.createElement('tr');
+ rowInfo.htmlNode = trElement;
+ rowInfo.indentation = indentation;
+ trElement.rowInfo = rowInfo;
+ this.customizeTableRow_(rowInfo.userRow, trElement);
+
+ const isBodyRow = tableSection === this.$.body;
+ const isExpandableRow = rowInfo.userRow[this.subRowsPropertyName_] &&
+ rowInfo.userRow[this.subRowsPropertyName_].length;
+
+ for (let i = 0; i < this.tableColumns_.length;) {
+ const td = this.appendNewElement_(trElement, 'td');
+ td.columnIndex = i;
+
+ const column = this.tableColumns_[i];
+ const value = column.value(rowInfo.userRow);
+ const colSpan = column.colSpan ? column.colSpan : 1;
+ td.style.colSpan = colSpan;
+
+ switch (column.align) {
+ case undefined:
+ case ColumnAlignment.LEFT:
+ break;
+
+ case ColumnAlignment.RIGHT:
+ td.style.textAlign = 'right';
+ break;
+
+ default:
+ throw new Error('Invalid alignment of column at index=' + i +
+ ': ' + column.align);
+ }
+
+ if (this.doesColumnIndexSupportSelection(i)) {
+ Polymer.dom(td).classList.add('supports-selection');
+ }
+
+ if (this.columnsWithExpandButtons_.includes(i)) {
+ if (rowInfo.userRow[this.subRowsPropertyName_] &&
+ rowInfo.userRow[this.subRowsPropertyName_].length > 0) {
+ td.style.paddingLeft = INDENT_SPACE + 'px';
+ td.style.display = 'flex';
+ const expandButton = this.appendNewElement_(td, 'expand-button');
+ Polymer.dom(expandButton).textContent = RIGHT_ARROW;
+ if (rowInfo.isExpanded) {
+ Polymer.dom(expandButton).classList.add('button-expanded');
+ }
+ } else {
+ td.style.paddingLeft = INDENT_SPACE_NO_BUTTON + 'px';
+ }
+ }
+
+ if (value !== undefined) {
+ Polymer.dom(td).appendChild(
+ tr.ui.b.asHTMLOrTextNode(value, this.ownerDocument));
+ }
+
+ td.addEventListener('click', function(i, clickEvent) {
+ // Prevent automatically focusing on the table upon clicking on the
+ // table. Explicitly focus on it when appropriate (upon clicking on a
+ // selectable row/cell) instead.
+ clickEvent.preventDefault();
+
+ if (!isBodyRow && !isExpandableRow) return;
+
+ clickEvent.stopPropagation();
+
+ if (clickEvent.target.tagName === 'EXPAND-BUTTON') {
+ this.setExpandedForUserRow_(
+ tableSection, rowInfoMap,
+ rowInfo.userRow, !rowInfo.isExpanded);
+ return;
+ }
+
+ // If the row/cell can be selected and it's not selected yet,
+ // select it.
+ if (isBodyRow && this.selectionMode_ !== SelectionMode.NONE) {
+ let shouldSelect = false;
+ let shouldFocus = false;
+ switch (this.selectionMode_) {
+ case SelectionMode.ROW:
+ shouldSelect = this.selectedTableRowInfo_ !== rowInfo;
+ shouldFocus = true;
+ break;
+ case SelectionMode.CELL:
+ if (this.doesColumnIndexSupportSelection(i)) {
+ shouldSelect = this.selectedTableRowInfo_ !== rowInfo ||
+ this.selectedColumnIndex_ !== i;
+ shouldFocus = true;
+ }
+ break;
+ default:
+ throw new Error('Invalid selection mode ' +
+ this.selectionMode_);
+ }
+ if (shouldFocus) {
+ this.focus();
+ }
+ if (shouldSelect) {
+ this.didTableRowInfoGetClicked_(rowInfo, i);
+ return;
+ }
+ }
+
+ // Otherwise, if the row is expandable, expand/collapse it.
+ if (isExpandableRow) {
+ this.setExpandedForUserRow_(tableSection, rowInfoMap,
+ rowInfo.userRow, !rowInfo.isExpanded);
+ }
+ }.bind(this, i));
+
+ // Add a double-click handler for stepping into a row/cell (if
+ // applicable).
+ if (isBodyRow) {
+ td.addEventListener('dblclick', function(i, e) {
+ e.stopPropagation();
+ this.dispatchStepIntoEvent_(rowInfo, i);
+ }.bind(this, i));
+ }
+
+ i += colSpan;
+ }
+
+ return rowInfo.htmlNode;
+ },
+
+ removeSubNodes_(tableSection, rowInfo, rowInfoMap) {
+ if (rowInfo.userRow[this.subRowsPropertyName_] === undefined) return;
+
+ for (let i = 0;
+ i < rowInfo.userRow[this.subRowsPropertyName_].length; i++) {
+ const subRow = rowInfo.userRow[this.subRowsPropertyName_][i];
+ const subRowInfo = rowInfoMap.get(subRow);
+ if (!subRowInfo) continue;
+
+ const subNode = subRowInfo.htmlNode;
+ if (subNode && Polymer.dom(subNode).parentNode === tableSection) {
+ Polymer.dom(tableSection).removeChild(subNode);
+ this.removeSubNodes_(tableSection, subRowInfo, rowInfoMap);
+ }
+ }
+ },
+
+ scheduleRebuildHeaders_() {
+ this.headerDirty_ = true;
+ this.scheduleRebuild_();
+ },
+
+ scheduleRebuildBody_() {
+ this.bodyDirty_ = true;
+ this.scheduleRebuild_();
+ },
+
+ scheduleRebuildFooter_() {
+ this.footerDirty_ = true;
+ this.scheduleRebuild_();
+ },
+
+ scheduleRebuild_() {
+ if (this.rebuildPending_) return;
+
+ this.rebuildPending_ = true;
+ setTimeout(function() {
+ this.rebuildPending_ = false;
+ this.rebuild();
+ }.bind(this), 0);
+ },
+
+ rebuildIfNeeded_() {
+ this.rebuild();
+ },
+
+ rebuild() {
+ const wasBodyOrHeaderDirty = this.headerDirty_ || this.bodyDirty_;
+
+ if (this.headerDirty_) {
+ this.generateHeaderColumns_();
+ this.headerDirty_ = false;
+ }
+ if (this.bodyDirty_) {
+ Polymer.dom(this.$.body).textContent = '';
+ this.generateTableRowNodes_(
+ this.$.body,
+ this.tableRows_, this.tableRowsInfo_, 0,
+ undefined, undefined);
+ if (this.tableRows_.length === 0 && this.emptyValue_ !== undefined) {
+ const trElement = this.ownerDocument.createElement('tr');
+ Polymer.dom(this.$.body).appendChild(trElement);
+ Polymer.dom(trElement).classList.add('empty-row');
+ const td = this.ownerDocument.createElement('td');
+ Polymer.dom(trElement).appendChild(td);
+ td.colSpan = this.tableColumns_.length;
+ const emptyValue = this.emptyValue_;
+ Polymer.dom(td).appendChild(
+ tr.ui.b.asHTMLOrTextNode(emptyValue, this.ownerDocument));
+ }
+ this.bodyDirty_ = false;
+ }
+
+ if (wasBodyOrHeaderDirty) this.applySizes_();
+
+ if (this.footerDirty_) {
+ Polymer.dom(this.$.foot).textContent = '';
+ this.generateTableRowNodes_(
+ this.$.foot,
+ this.tableFooterRows_, this.tableFooterRowsInfo_, 0,
+ undefined, undefined);
+ if (this.tableFooterRowsInfo_.length) {
+ Polymer.dom(this.$.body).classList.add('has-footer');
+ } else {
+ Polymer.dom(this.$.body).classList.remove('has-footer');
+ }
+ this.footerDirty_ = false;
+ }
+ },
+
+ appendNewElement_(parent, tagName) {
+ const element = parent.ownerDocument.createElement(tagName);
+ Polymer.dom(parent).appendChild(element);
+ return element;
+ },
+
+ getExpandedForTableRow(userRow) {
+ this.rebuildIfNeeded_();
+ const rowInfo = this.tableRowsInfo_.get(userRow);
+ if (rowInfo === undefined) {
+ throw new Error('Row has not been seen, must expand its parents');
+ }
+ return rowInfo.isExpanded;
+ },
+
+ getExpandedForUserRow_(userRow) {
+ if (userRow[this.subRowsPropertyName_] === undefined) {
+ return false;
+ }
+ if (userRow[this.subRowsPropertyName_].length === 0) {
+ return false;
+ }
+ if (userRow.isExpanded) {
+ return true;
+ }
+ if ((userRow.isExpanded !== undefined) &&
+ (userRow.isExpanded === false)) {
+ return false;
+ }
+
+ const rowInfo = this.tableRowsInfo_.get(userRow);
+ if (rowInfo && rowInfo.isExpanded) {
+ return true;
+ }
+
+ if (this.defaultExpansionStateCallback_ === undefined) {
+ return false;
+ }
+
+ let parentUserRow = undefined;
+ if (rowInfo && rowInfo.parentRowInfo) {
+ parentUserRow = rowInfo.parentRowInfo.userRow;
+ }
+
+ return this.defaultExpansionStateCallback_(
+ userRow, parentUserRow);
+ },
+
+ setExpandedForTableRow(userRow, expanded) {
+ this.rebuildIfNeeded_();
+ const rowInfo = this.tableRowsInfo_.get(userRow);
+ if (rowInfo === undefined) {
+ throw new Error('Row has not been seen, must expand its parents');
+ }
+ return this.setExpandedForUserRow_(this.$.body, this.tableRowsInfo_,
+ userRow, expanded);
+ },
+
+ setExpandedForUserRow_(tableSection, rowInfoMap,
+ userRow, expanded) {
+ this.rebuildIfNeeded_();
+
+ const rowInfo = rowInfoMap.get(userRow);
+ if (rowInfo === undefined) {
+ throw new Error('Row has not been seen, must expand its parents');
+ }
+
+ const wasExpanded = rowInfo.isExpanded;
+
+ rowInfo.isExpanded = !!expanded;
+ // If no node, then nothing further needs doing.
+ if (rowInfo.htmlNode === undefined) return;
+
+ // If its detached, then nothing needs doing.
+ if (rowInfo.htmlNode.parentElement !== tableSection) {
+ return;
+ }
+
+ // Otherwise, rebuild.
+ const expandButton =
+ Polymer.dom(rowInfo.htmlNode).querySelector('expand-button');
+ if (rowInfo.isExpanded) {
+ Polymer.dom(expandButton).classList.add('button-expanded');
+ const lastAddedRow = rowInfo.htmlNode;
+ if (rowInfo.userRow[this.subRowsPropertyName_]) {
+ this.generateTableRowNodes_(
+ tableSection,
+ rowInfo.userRow[this.subRowsPropertyName_], rowInfoMap,
+ rowInfo.indentation + 1,
+ lastAddedRow, rowInfo);
+ }
+ } else {
+ Polymer.dom(expandButton).classList.remove('button-expanded');
+ this.removeSubNodes_(tableSection, rowInfo, rowInfoMap);
+ }
+
+ if (wasExpanded !== rowInfo.isExpanded) {
+ const e = new tr.b.Event('row-expanded-changed');
+ e.row = rowInfo.userRow;
+ this.dispatchEvent(e);
+ }
+
+ this.maybeUpdateSelectedRow_();
+ },
+
+ get selectionMode() {
+ return this.selectionMode_;
+ },
+
+ set selectionMode(selectionMode) {
+ if (!SelectionModeValues.has(selectionMode)) {
+ throw new Error('Invalid selection mode ' + selectionMode);
+ }
+ this.rebuildIfNeeded_();
+ this.selectionMode_ = selectionMode;
+ this.didSelectionStateChange_();
+ },
+
+ get rowHighlightStyle() {
+ return this.rowHighlightStyle_;
+ },
+
+ set rowHighlightStyle(rowHighlightStyle) {
+ if (!HighlightStyleValues.has(rowHighlightStyle)) {
+ throw new Error('Invalid row highlight style ' + rowHighlightStyle);
+ }
+ this.rebuildIfNeeded_();
+ this.rowHighlightStyle_ = rowHighlightStyle;
+ this.didSelectionStateChange_();
+ },
+
+ get resolvedRowHighlightStyle() {
+ if (this.rowHighlightStyle_ !== HighlightStyle.DEFAULT) {
+ return this.rowHighlightStyle_;
+ }
+ switch (this.selectionMode_) {
+ case SelectionMode.NONE:
+ return HighlightStyle.NONE;
+ case SelectionMode.ROW:
+ return HighlightStyle.DARK;
+ case SelectionMode.CELL:
+ return HighlightStyle.LIGHT;
+ default:
+ throw new Error('Invalid selection mode ' + selectionMode);
+ }
+ },
+
+ get cellHighlightStyle() {
+ return this.cellHighlightStyle_;
+ },
+
+ set cellHighlightStyle(cellHighlightStyle) {
+ if (!HighlightStyleValues.has(cellHighlightStyle)) {
+ throw new Error('Invalid cell highlight style ' + cellHighlightStyle);
+ }
+ this.rebuildIfNeeded_();
+ this.cellHighlightStyle_ = cellHighlightStyle;
+ this.didSelectionStateChange_();
+ },
+
+ get resolvedCellHighlightStyle() {
+ if (this.cellHighlightStyle_ !== HighlightStyle.DEFAULT) {
+ return this.cellHighlightStyle_;
+ }
+ switch (this.selectionMode_) {
+ case SelectionMode.NONE:
+ case SelectionMode.ROW:
+ return HighlightStyle.NONE;
+ case SelectionMode.CELL:
+ return HighlightStyle.DARK;
+ default:
+ throw new Error('Invalid selection mode ' + selectionMode);
+ }
+ },
+
+ setHighlightStyle_(highlightAttribute, resolvedHighlightStyle) {
+ switch (resolvedHighlightStyle) {
+ case HighlightStyle.NONE:
+ Polymer.dom(this.$.body).removeAttribute(highlightAttribute);
+ break;
+ case HighlightStyle.LIGHT:
+ Polymer.dom(this.$.body).setAttribute(highlightAttribute, 'light');
+ break;
+ case HighlightStyle.DARK:
+ Polymer.dom(this.$.body).setAttribute(highlightAttribute, 'dark');
+ break;
+ default:
+ throw new Error('Invalid resolved highlight style ' +
+ resolvedHighlightStyle);
+ }
+ },
+
+ didSelectionStateChange_() {
+ this.setHighlightStyle_('row-highlight-style',
+ this.resolvedRowHighlightStyle);
+ this.setHighlightStyle_('cell-highlight-style',
+ this.resolvedCellHighlightStyle);
+
+ this.removeSelectedState_();
+
+ switch (this.selectionMode_) {
+ case SelectionMode.ROW:
+ // TODO: Replace this.selectionMode_ with a proper Polymer attribute.
+ Polymer.dom(this.$.body).setAttribute('selection-mode', 'row');
+ Polymer.dom(this.$.body).setAttribute('tabindex', 0);
+ this.selectedColumnIndex_ = undefined;
+ break;
+ case SelectionMode.CELL:
+ Polymer.dom(this.$.body).setAttribute('selection-mode', 'cell');
+ Polymer.dom(this.$.body).setAttribute('tabindex', 0);
+ if (this.selectedTableRowInfo_ &&
+ this.selectedColumnIndex_ === undefined) {
+ const i = this.getFirstSelectableColumnIndex_();
+ if (i === -1) {
+ // No column is selectable.
+ this.selectedTableRowInfo_ = undefined;
+ } else {
+ this.selectedColumnIndex_ = i;
+ }
+ }
+ break;
+ case SelectionMode.NONE:
+ Polymer.dom(this.$.body).removeAttribute('selection-mode');
+ Polymer.dom(this.$.body).removeAttribute('tabindex');
+ this.$.body.blur(); // Remove focus (if applicable).
+ this.selectedTableRowInfo_ = undefined;
+ this.selectedColumnIndex_ = undefined;
+ break;
+ default:
+ throw new Error('Invalid selection mode ' + this.selectionMode_);
+ }
+
+ this.maybeUpdateSelectedRow_();
+ },
+
+ maybeUpdateSelectedRow_() {
+ if (this.selectedTableRowInfo_ === undefined) return;
+
+ // selectedUserRow may not be visible
+ function isVisible(rowInfo) {
+ if (!rowInfo.htmlNode) return false;
+ return !!rowInfo.htmlNode.parentElement;
+ }
+ if (isVisible(this.selectedTableRowInfo_)) {
+ this.updateSelectedState_();
+ return;
+ }
+
+ this.removeSelectedState_();
+ let curRowInfo = this.selectedTableRowInfo_;
+ while (curRowInfo && !isVisible(curRowInfo)) {
+ curRowInfo = curRowInfo.parentRowInfo;
+ }
+
+ this.selectedTableRowInfo_ = curRowInfo;
+ if (this.selectedTableRowInfo_) {
+ this.updateSelectedState_();
+ } else {
+ this.selectedColumnIndex_ = undefined;
+ }
+ },
+
+ didTableRowInfoGetClicked_(rowInfo, columnIndex) {
+ switch (this.selectionMode_) {
+ case SelectionMode.NONE:
+ return;
+
+ case SelectionMode.CELL:
+ if (!this.doesColumnIndexSupportSelection(columnIndex)) {
+ return;
+ }
+ if (this.selectedColumnIndex !== columnIndex) {
+ this.selectedColumnIndex = columnIndex;
+ }
+ // Fall through.
+
+ case SelectionMode.ROW:
+ if (this.selectedTableRowInfo_ !== rowInfo) {
+ this.selectedTableRow = rowInfo.userRow;
+ }
+ }
+ },
+
+ dispatchStepIntoEvent_(rowInfo, columnIndex) {
+ const e = new tr.b.Event('step-into');
+ e.tableRow = rowInfo.userRow;
+ e.tableColumn = this.tableColumns_[columnIndex];
+ e.columnIndex = columnIndex;
+ this.dispatchEvent(e);
+ },
+
+ /**
+ * If the selectionMode is CELL and a cell is selected,
+ * return an object containing the row, column, and value of the selected
+ * cell.
+ *
+ * @return {undefined|!Object}
+ */
+ get selectedCell() {
+ const row = this.selectedTableRow;
+ const columnIndex = this.selectedColumnIndex;
+ if (row === undefined || columnIndex === undefined ||
+ this.tableColumns_.length <= columnIndex) {
+ return undefined;
+ }
+ const column = this.tableColumns_[columnIndex];
+ return {
+ row,
+ column,
+ value: column.value(row)
+ };
+ },
+
+ /**
+ * If a column is selected, return the object describing the selected
+ * column.
+ *
+ * Columns can be selected independently of rows and cells. So it is
+ * possible to select column 0 and cell [0,0], or column 1 and cell [0,0],
+ * for example. See |selectedCell| for how to access the selected cell when
+ * the selectionMode is CELL.
+ *
+ * |selectedTableColumn| is entirely independent of |selectedColumnIndex|.
+ * When the table selectionMode is CELL, use |selectedTableRow| and
+ * |selectedColumnIndex| to find the selected cell.
+ * When one or more columns have |selectable:true|, then use
+ * |selectedTableColumn| to find the selected column, which may be either
+ * the same as or different from |selectedColumnIndex|, if a cell is also
+ * selected.
+ *
+ * @return {number|undefined}
+ */
+ get selectedTableColumnIndex() {
+ const cols = Polymer.dom(this.$.cols).children;
+ for (let i = 0; i < cols.length; ++i) {
+ if (cols[i].getAttribute('selected')) {
+ return i;
+ }
+ }
+ return undefined;
+ },
+
+ /**
+ * @param {number|undefined} index
+ */
+ set selectedTableColumnIndex(selectedIndex) {
+ const cols = Polymer.dom(this.$.cols).children;
+ for (let i = 0; i < cols.length; ++i) {
+ if (i === selectedIndex) {
+ cols[i].setAttribute('selected', true);
+ } else {
+ cols[i].removeAttribute('selected');
+ }
+ }
+ },
+
+ get selectedTableRow() {
+ if (!this.selectedTableRowInfo_) return undefined;
+ return this.selectedTableRowInfo_.userRow;
+ },
+
+ set selectedTableRow(userRow) {
+ this.rebuildIfNeeded_();
+ if (this.selectionMode_ === SelectionMode.NONE) {
+ throw new Error('Selection is off.');
+ }
+
+ let rowInfo;
+ if (userRow === undefined) {
+ rowInfo = undefined;
+ } else {
+ rowInfo = this.tableRowsInfo_.get(userRow);
+ if (!rowInfo) {
+ throw new Error('Row has not been seen, must expand its parents.');
+ }
+ }
+
+ const e = this.prepareToChangeSelection_();
+
+ if (!rowInfo) {
+ this.selectedColumnIndex_ = undefined;
+ } else {
+ switch (this.selectionMode_) {
+ case SelectionMode.ROW:
+ this.selectedColumnIndex_ = undefined;
+ break;
+
+ case SelectionMode.CELL:
+ if (this.selectedColumnIndex_ === undefined) {
+ const i = this.getFirstSelectableColumnIndex_();
+ if (i === -1) {
+ throw new Error('Cannot find a selectable column.');
+ }
+ this.selectedColumnIndex_ = i;
+ }
+ break;
+
+ default:
+ throw new Error('Invalid selection mode ' + this.selectionMode_);
+ }
+ }
+
+ this.selectedTableRowInfo_ = rowInfo;
+ this.updateSelectedState_();
+ this.dispatchEvent(e);
+ },
+
+ prepareToChangeSelection_() {
+ const e = new tr.b.Event('selection-changed');
+ const previousSelectedRowInfo = this.selectedTableRowInfo_;
+ if (previousSelectedRowInfo) {
+ e.previousSelectedTableRow = previousSelectedRowInfo.userRow;
+ } else {
+ e.previousSelectedTableRow = undefined;
+ }
+
+ this.removeSelectedState_();
+
+ return e;
+ },
+
+ removeSelectedState_() {
+ this.setSelectedState_(false);
+ },
+
+ updateSelectedState_() {
+ this.setSelectedState_(true);
+ },
+
+ setSelectedState_(select) {
+ if (this.selectedTableRowInfo_ === undefined) return;
+
+ // Row selection.
+ const rowNode = this.selectedTableRowInfo_.htmlNode;
+ if (select) {
+ Polymer.dom(rowNode).setAttribute('selected', true);
+ } else {
+ Polymer.dom(rowNode).removeAttribute('selected');
+ }
+
+ // Cell selection (if applicable).
+ const cellNode = Polymer.dom(rowNode).children[this.selectedColumnIndex_];
+ if (!cellNode) return;
+ if (select) {
+ Polymer.dom(cellNode).setAttribute('selected', true);
+ } else {
+ Polymer.dom(cellNode).removeAttribute('selected');
+ }
+ },
+
+ doesColumnIndexSupportSelection(columnIndex) {
+ const columnInfo = this.tableColumns_[columnIndex];
+ const scs = columnInfo.supportsCellSelection;
+ if (scs === false) return false;
+ return true;
+ },
+
+ getFirstSelectableColumnIndex_() {
+ for (let i = 0; i < this.tableColumns_.length; i++) {
+ if (this.doesColumnIndexSupportSelection(i)) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ getSelectableNodeGivenTableRowNode_(htmlNode) {
+ switch (this.selectionMode_) {
+ case SelectionMode.ROW:
+ return htmlNode;
+
+ case SelectionMode.CELL:
+ return Polymer.dom(htmlNode).children[this.selectedColumnIndex_];
+
+ default:
+ throw new Error('Invalid selection mode ' + this.selectionMode_);
+ }
+ },
+
+ get selectedColumnIndex() {
+ if (this.selectionMode_ !== SelectionMode.CELL) {
+ return undefined;
+ }
+ return this.selectedColumnIndex_;
+ },
+
+ set selectedColumnIndex(selectedColumnIndex) {
+ this.rebuildIfNeeded_();
+ if (this.selectionMode_ === SelectionMode.NONE) {
+ throw new Error('Selection is off.');
+ }
+ if (selectedColumnIndex < 0 ||
+ selectedColumnIndex >= this.tableColumns_.length) {
+ throw new Error('Invalid index');
+ }
+ if (!this.doesColumnIndexSupportSelection(selectedColumnIndex)) {
+ throw new Error('Selection is not supported on this column');
+ }
+
+ const e = this.prepareToChangeSelection_();
+ if (this.selectedColumnIndex_ === undefined) {
+ this.selectedTableRowInfo_ = undefined;
+ } else if (!this.selectedTableRowInfo_) {
+ if (this.tableRows_.length === 0) {
+ throw new Error('No available row to be selected');
+ }
+ this.selectedTableRowInfo_ =
+ this.tableRowsInfo_.get(this.tableRows_[0]);
+ }
+ this.selectedColumnIndex_ = selectedColumnIndex;
+ this.updateSelectedState_();
+ this.dispatchEvent(e);
+ },
+
+ onKeyDown_(e) {
+ if (this.selectionMode_ === SelectionMode.NONE) return;
+
+ const CODE_TO_COMMAND_NAMES = {
+ 13: 'ENTER',
+ 32: 'SPACE',
+ 37: 'ARROW_LEFT',
+ 38: 'ARROW_UP',
+ 39: 'ARROW_RIGHT',
+ 40: 'ARROW_DOWN'
+ };
+ const cmdName = CODE_TO_COMMAND_NAMES[e.keyCode];
+ if (cmdName === undefined) return;
+
+ e.stopPropagation();
+ e.preventDefault();
+ this.performKeyCommand_(cmdName);
+ },
+
+ onFocus_(e) {
+ // This method should be idempotent. If it can't be, then focus() must be
+ // updated.
+ if (this.selectionMode_ === SelectionMode.NONE ||
+ this.selectedTableRow ||
+ this.tableRows_.length === 0) {
+ return;
+ }
+
+ if (this.selectionMode_ === SelectionMode.CELL &&
+ this.getFirstSelectableColumnIndex_() === -1) {
+ // If there are no selectable columns in cell selection mode, don't do
+ // anything.
+ return;
+ }
+
+ this.selectedTableRow = this.tableRows_[0];
+ },
+
+ focus() {
+ this.$.body.focus();
+
+ // Need to manually call onFocus_ here: if the table is invisible for any
+ // reason, then the focus event will not fire, but the table may become
+ // visible later, and should reflect the focus accurately.
+ // If the table is already visible, then this will cause onFocus_ to be
+ // called multiple times. That shouldn't be a problem since onFocus_ is
+ // idempotent.
+ this.onFocus_();
+ },
+
+ blur() {
+ this.$.body.blur();
+ },
+
+ get isFocused() {
+ return this.root.activeElement === this.$.body;
+ },
+
+ performKeyCommand_(cmdName) {
+ this.rebuildIfNeeded_();
+
+ switch (cmdName) {
+ case 'ARROW_UP':
+ this.selectPreviousOrFirstRowIfPossible_();
+ return;
+
+ case 'ARROW_DOWN':
+ this.selectNextOrFirstRowIfPossible_();
+ return;
+
+ case 'ARROW_RIGHT':
+ switch (this.selectionMode_) {
+ case SelectionMode.NONE:
+ return; // No action.
+ case SelectionMode.ROW:
+ this.expandRowAndSelectChildRowIfPossible_();
+ return;
+ case SelectionMode.CELL:
+ this.selectNextSelectableCellToTheRightIfPossible_();
+ return;
+ default:
+ throw new Error('Invalid selection mode ' + this.selectionMode_);
+ }
+
+ case 'ARROW_LEFT':
+ switch (this.selectionMode_) {
+ case SelectionMode.NONE:
+ return; // No action.
+ case SelectionMode.ROW:
+ this.collapseRowOrSelectParentRowIfPossible_();
+ return;
+ case SelectionMode.CELL:
+ this.selectNextSelectableCellToTheLeftIfPossible_();
+ return;
+ default:
+ throw new Error('Invalid selection mode ' + this.selectionMode_);
+ }
+
+ case 'SPACE':
+ this.toggleRowExpansionStateIfPossible_();
+ return;
+
+ case 'ENTER':
+ this.stepIntoSelectionIfPossible_();
+ return;
+
+ default:
+ throw new Error('Unrecognized command ' + cmdName);
+ }
+ },
+
+ selectPreviousOrFirstRowIfPossible_() {
+ const prev = this.selectedTableRowInfo_ ?
+ this.selectedTableRowInfo_.htmlNode.previousElementSibling :
+ this.$.body.firstChild;
+ if (!prev) return;
+
+ if (this.selectionMode_ === SelectionMode.CELL &&
+ this.getFirstSelectableColumnIndex_() === -1) {
+ // If there are no selectable columns in cell selection mode, don't do
+ // anything.
+ return;
+ }
+ tr.ui.b.scrollIntoViewIfNeeded(prev);
+ this.selectedTableRow = prev.rowInfo.userRow;
+ },
+
+ selectNextOrFirstRowIfPossible_() {
+ this.getFirstSelectableColumnIndex_;
+ const next = this.selectedTableRowInfo_ ?
+ this.selectedTableRowInfo_.htmlNode.nextElementSibling :
+ this.$.body.firstChild;
+ if (!next) return;
+
+ if (this.selectionMode_ === SelectionMode.CELL &&
+ this.getFirstSelectableColumnIndex_() === -1) {
+ // If there are no selectable columns in cell selection mode, don't do
+ // anything.
+ return;
+ }
+ tr.ui.b.scrollIntoViewIfNeeded(next);
+ this.selectedTableRow = next.rowInfo.userRow;
+ },
+
+ expandRowAndSelectChildRowIfPossible_() {
+ const selectedRowInfo = this.selectedTableRowInfo_;
+ if (!selectedRowInfo ||
+ selectedRowInfo.userRow[this.subRowsPropertyName_] === undefined ||
+ selectedRowInfo.userRow[this.subRowsPropertyName_].length === 0) {
+ return;
+ }
+ if (!selectedRowInfo.isExpanded) {
+ this.setExpandedForTableRow(selectedRowInfo.userRow, true);
+ }
+ this.selectedTableRow =
+ selectedRowInfo.htmlNode.nextElementSibling.rowInfo.userRow;
+ },
+
+ collapseRowOrSelectParentRowIfPossible_() {
+ const selectedRowInfo = this.selectedTableRowInfo_;
+ if (!selectedRowInfo) return;
+
+ if (selectedRowInfo.isExpanded) {
+ // If the node is expanded, collapse it.
+ this.setExpandedForTableRow(selectedRowInfo.userRow, false);
+ } else {
+ // If the node is not expanded, select its parent.
+ const parentRowInfo = selectedRowInfo.parentRowInfo;
+ if (parentRowInfo) {
+ this.selectedTableRow = parentRowInfo.userRow;
+ }
+ }
+ },
+
+ selectNextSelectableCellToTheRightIfPossible_() {
+ if (!this.selectedTableRowInfo_ ||
+ this.selectedColumnIndex_ === undefined) {
+ return;
+ }
+ for (let i = this.selectedColumnIndex_ + 1; i < this.tableColumns_.length;
+ i++) {
+ if (this.doesColumnIndexSupportSelection(i)) {
+ this.selectedColumnIndex = i;
+ return;
+ }
+ }
+ },
+
+ selectNextSelectableCellToTheLeftIfPossible_() {
+ if (!this.selectedTableRowInfo_ ||
+ this.selectedColumnIndex_ === undefined) {
+ return;
+ }
+ for (let i = this.selectedColumnIndex_ - 1; i >= 0; i--) {
+ if (this.doesColumnIndexSupportSelection(i)) {
+ this.selectedColumnIndex = i;
+ return;
+ }
+ }
+ },
+
+ toggleRowExpansionStateIfPossible_() {
+ const selectedRowInfo = this.selectedTableRowInfo_;
+ if (!selectedRowInfo ||
+ selectedRowInfo.userRow[this.subRowsPropertyName_] === undefined ||
+ selectedRowInfo.userRow[this.subRowsPropertyName_].length === 0) {
+ return;
+ }
+ this.setExpandedForTableRow(selectedRowInfo.userRow,
+ !selectedRowInfo.isExpanded);
+ },
+
+ stepIntoSelectionIfPossible_() {
+ if (!this.selectedTableRowInfo_) return;
+ this.dispatchStepIntoEvent_(this.selectedTableRowInfo_,
+ this.selectedColumnIndex_);
+ },
+
+ dispatchSortingChangedEvent_() {
+ const e = new tr.b.Event('sort-column-changed');
+ e.sortColumnIndex = this.sortColumnIndex_;
+ e.sortDescending = this.sortDescending_;
+ this.dispatchEvent(e);
+ }
+ });
+})();
+</script>
+
+<dom-module id="tr-ui-b-table-header-cell">
+ <template>
+ <style>
+ :host {
+ -webkit-user-select: none;
+ display: flex;
+ }
+
+ span {
+ flex: 0 1 auto;
+ }
+
+ #side {
+ -webkit-user-select: none;
+ flex: 0 0 auto;
+ padding-left: 2px;
+ padding-right: 2px;
+ vertical-align: top;
+ font-size: 15px;
+ font-family: sans-serif;
+ line-height: 85%;
+ margin-left: 5px;
+ }
+
+ #side.disabled {
+ color: rgb(140, 140, 140);
+ }
+
+ #title:empty, #side:empty {
+ display: none;
+ }
+ </style>
+
+ <span id="title"></span>
+ <span id="side"></span>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+const ColumnAlignment = tr.ui.b.TableFormat.ColumnAlignment;
+
+Polymer({
+ is: 'tr-ui-b-table-header-cell',
+
+ created() {
+ this.tapCallback_ = undefined;
+ this.cellTitle_ = '';
+ this.align_ = undefined;
+ this.selectable_ = false;
+ this.column_ = undefined;
+ },
+
+ ready() {
+ this.addEventListener('click', this.onTap_.bind(this));
+ },
+
+ set column(column) {
+ this.column_ = column;
+ this.align = column.align;
+ this.cellTitle = column.title;
+ },
+
+ get column() {
+ return this.column_;
+ },
+
+ set cellTitle(value) {
+ this.cellTitle_ = value;
+
+ const titleNode = tr.ui.b.asHTMLOrTextNode(
+ this.cellTitle_, this.ownerDocument);
+
+ this.$.title.innerText = '';
+
+ Polymer.dom(this.$.title).appendChild(titleNode);
+ },
+
+ get cellTitle() {
+ return this.cellTitle_;
+ },
+
+ set align(align) {
+ switch (align) {
+ case undefined:
+ case ColumnAlignment.LEFT:
+ this.style.justifyContent = '';
+ break;
+
+ case ColumnAlignment.RIGHT:
+ this.style.justifyContent = 'flex-end';
+ break;
+
+ default:
+ throw new Error('Invalid alignment of column (title=\'' +
+ this.cellTitle_ + '\'): ' + align);
+ }
+ this.align_ = align;
+ },
+
+ get align() {
+ return this.align_;
+ },
+
+ clearSideContent() {
+ Polymer.dom(this.$.side).textContent = '';
+ },
+
+ set sideContent(content) {
+ Polymer.dom(this.$.side).textContent = content;
+ this.$.side.style.display = content ? 'inline' : 'none';
+ },
+
+ get sideContent() {
+ return Polymer.dom(this.$.side).textContent;
+ },
+
+ set sideContentDisabled(sideContentDisabled) {
+ this.$.side.classList.toggle('disabled', sideContentDisabled);
+ },
+
+ get sideContentDisabled() {
+ return this.$.side.classList.contains('disabled');
+ },
+
+ set tapCallback(callback) {
+ this.style.cursor = 'pointer';
+ this.tapCallback_ = callback;
+ },
+
+ get tapCallback() {
+ return this.tapCallback_;
+ },
+
+ onTap_() {
+ if (this.tapCallback_) {
+ this.tapCallback_();
+ }
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/table_header_cell.html b/chromium/third_party/catapult/tracing/tracing/ui/base/table_header_cell.html
new file mode 100644
index 00000000000..d7e8d427cb9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/table_header_cell.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+
+<dom-module id='tr-ui-b-table-header-cell'>
+ <template>
+ <style>
+ :host {
+ -webkit-user-select: none;
+ display: flex;
+ }
+
+ span {
+ flex: 0 1 auto;
+ }
+
+ side-element {
+ -webkit-user-select: none;
+ flex: 1 0 auto;
+ padding-left: 4px;
+ vertical-align: top;
+ font-size: 15px;
+ font-family: sans-serif;
+ display: inline;
+ line-height: 85%;
+ }
+ </style>
+
+ <span id="title"></span><side-element id="side"></side-element>
+ </template>
+</dom-module>
+ <script>
+ 'use strict';
+
+ Polymer({
+ is: 'tr-ui-b-table-header-cell',
+
+ listeners: {
+ 'tap': 'onTap_'
+ },
+
+ created() {
+ this.tapCallback_ = undefined;
+ this.cellTitle_ = '';
+ },
+
+ set cellTitle(value) {
+ this.cellTitle_ = value;
+
+ const titleNode =
+ tr.ui.b.asHTMLOrTextNode(this.cellTitle_, this.ownerDocument);
+
+ this.$.title.innerText = '';
+ Polymer.dom(this.$.title).appendChild(titleNode);
+ },
+
+ get cellTitle() {
+ return this.cellTitle_;
+ },
+
+ clearSideContent() {
+ Polymer.dom(this.$.side).textContent = '';
+ },
+
+ set sideContent(content) {
+ Polymer.dom(this.$.side).textContent = content;
+ },
+
+ get sideContent() {
+ return Polymer.dom(this.$.side).textContent;
+ },
+
+ set tapCallback(callback) {
+ this.style.cursor = 'pointer';
+ this.tapCallback_ = callback;
+ },
+
+ get tapCallback() {
+ return this.tapCallback_;
+ },
+
+ onTap_() {
+ if (this.tapCallback_) {
+ this.tapCallback_();
+ }
+ }
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html
new file mode 100644
index 00000000000..73e8aca4418
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/table_test.html
@@ -0,0 +1,2115 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+ const SelectionMode = tr.ui.b.TableFormat.SelectionMode;
+ const HighlightStyle = tr.ui.b.TableFormat.HighlightStyle;
+ const ColumnAlignment = tr.ui.b.TableFormat.ColumnAlignment;
+
+ function isSelected(element) {
+ if (!element.hasAttribute('selected')) return false;
+ return element.getAttribute('selected') === 'true';
+ }
+
+ function simulateDoubleClick(element) {
+ // See https://developer.mozilla.org/en/docs/Web/API/MouseEvent#Example.
+ const event = new MouseEvent('dblclick', {
+ bubbles: true,
+ cancelable: true,
+ view: window
+ });
+ return element.dispatchEvent(event);
+ }
+
+ test('rowExpandedChanged', function() {
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = [
+ {
+ title: 'Name',
+ value: row => row.value,
+ }
+ ];
+ table.tableRows = [{value: 'a', subRows: [{value: 'b'}]}];
+ let count = 0;
+ table.addEventListener('row-expanded-changed', e => ++count);
+ this.addHTMLOutput(table);
+ table.rebuild();
+
+ assert.strictEqual(0, count);
+
+ table.setExpandedForTableRow(table.tableRows[0], true);
+ assert.strictEqual(1, count);
+
+ table.setExpandedForTableRow(table.tableRows[0], true);
+ assert.strictEqual(1, count);
+
+ table.setExpandedForTableRow(table.tableRows[0], false);
+ assert.strictEqual(2, count);
+ });
+
+ test('instantiateEmptyTable_withoutEmptyValue', function() {
+ // TODO(#4321): Switch to using skipped instead once it works
+ return; // https://github.com/catapult-project/catapult/issues/4320
+ /* eslint-disable no-unreachable */
+ const columns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; },
+ width: '300px'
+ },
+ {
+ title: 'Second Column',
+ value(row) { return row.secondData; }
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = [];
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ // Check that the width of the first column was set correctly (despite no
+ // body rows).
+ const firstColumnHeader = table.$.head.children[0].children[0];
+ assert.closeTo(firstColumnHeader.offsetWidth, 300, 20);
+
+ // Check that the first column has a non-empty header.
+ const firstColumnTitle = tr.ui.b.findDeepElementMatchingPredicate(
+ firstColumnHeader, function(element) {
+ return Polymer.dom(element).textContent === 'First Column';
+ });
+ assert.isDefined(firstColumnTitle);
+
+ // Check that empty value was not appended.
+ assert.lengthOf(table.$.body.children, 0);
+ /* eslint-enable no-unreachable */
+ });
+
+ test('instantiateEmptyTable_withEmptyValue', function() {
+ // TODO(#4321): Switch to using skipped instead once it works
+ return; // https://github.com/catapult-project/catapult/issues/4320
+ /* eslint-disable no-unreachable */
+ const columns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; },
+ width: '300px'
+ },
+ {
+ title: 'Second Column',
+ value(row) { return row.secondData; }
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = [];
+ table.emptyValue = 'This table is left intentionally empty';
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ // Check that the width of the first column was set correctly (despite no
+ // body rows).
+ const firstColumnHeader = table.$.head.children[0].children[0];
+ assert.closeTo(firstColumnHeader.offsetWidth, 300, 20);
+
+ // Check that empty value was appended.
+ assert.lengthOf(table.$.body.children, 1);
+ /* eslint-enable no-unreachable */
+ });
+
+ test('instantiateNestedTableNoNests', function() {
+ const columns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; },
+ width: '200px'
+ },
+ {
+ title: 'Second Column',
+ value(row) { return row.secondData; }
+ }
+ ];
+
+ const rows = [
+ {
+ firstData: 'A1',
+ secondData: 'A2'
+ },
+ {
+ firstData: 'B1',
+ secondData: 'B2'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.emptyValue = 'THIS SHOULD NOT BE VISIBLE!!!';
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ // Check that empty value was not appended.
+ assert.lengthOf(table.$.body.children, 2);
+ });
+
+ test('sequentialRebuildsBehaveSanely', function() {
+ const columns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; },
+ width: '200px'
+ },
+ {
+ title: 'Second Column',
+ value(row) { return row.secondData; }
+ }
+ ];
+
+ const rows = [
+ {
+ firstData: 'A1',
+ secondData: 'A2'
+ },
+ {
+ firstData: 'B1',
+ secondData: 'B2'
+ }
+ ];
+ const footerRows = [
+ {
+ firstData: 'A1',
+ secondData: 'A2'
+ },
+ {
+ firstData: 'B1',
+ secondData: 'B2'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.footerRows = footerRows;
+ table.rebuild();
+ table.rebuild();
+ assert.strictEqual(table.$.body.children.length, 2);
+ assert.strictEqual(table.$.foot.children.length, 2);
+
+ this.addHTMLOutput(table);
+ });
+
+ test('instantiateNestedTableWithNests', function() {
+ const columns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; },
+ width: '250px'
+ },
+ {
+ title: 'Second Column',
+ value(row) { return row.secondData; },
+ width: '50%'
+ }
+ ];
+
+ const rows = [
+ {
+ firstData: 'A1',
+ secondData: 'A2',
+ subRows: [
+ {
+ firstData: 'Sub1 A1',
+ secondData: 'Sub1 A2'
+ },
+ {
+ firstData: 'Sub2 A1',
+ secondData: 'Sub2 A2',
+ subRows: [
+ {
+ firstData: 'SubSub1 A1',
+ secondData: 'SubSub1 A2'
+ },
+ {
+ firstData: 'SubSub2 A1',
+ secondData: 'SubSub2 A2'
+ }
+ ]
+ },
+ {
+ firstData: 'Sub3 A1',
+ secondData: 'Sub3 A2'
+ }
+ ]
+ },
+ {
+ firstData: 'B1',
+ secondData: 'B2'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+ });
+
+ test('instantiateSortingCallbacksWithNests', function() {
+ const table = document.createElement('tr-ui-b-table');
+
+ const columns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; },
+ width: '50%'
+ },
+ {
+ title: 'Second Column',
+ value(row) { return row.secondData; },
+ width: '250px',
+ cmp(rowA, rowB) {
+ return rowA.secondData.toString().localeCompare(
+ rowB.secondData.toString());
+ },
+ showExpandButtons: true
+ }
+ ];
+
+ const rows = [
+ {
+ firstData: 'A1',
+ secondData: 'A2',
+ subRows: [
+ {
+ firstData: 'Sub1 A1',
+ secondData: 'Sub1 A2'
+ },
+ {
+ firstData: 'Sub2 A1',
+ secondData: 'Sub2 A2',
+ subRows: [
+ {
+ firstData: 'SubSub1 A1',
+ secondData: 'SubSub1 A2'
+ },
+ {
+ firstData: 'SubSub2 A1',
+ secondData: 'SubSub2 A2'
+ }
+ ]
+ },
+ {
+ firstData: 'Sub3 A1',
+ secondData: 'Sub3 A2'
+ }
+ ]
+ },
+ {
+ firstData: 'B1',
+ secondData: 'B2'
+ }
+ ];
+
+ const footerRows = [
+ {
+ firstData: 'F1',
+ secondData: 'F2',
+ subRows: [
+ {
+ firstData: 'Sub1F1',
+ secondData: 'Sub1F2'
+ },
+ {
+ firstData: 'Sub2F1',
+ secondData: 'Sub2F2',
+ subRows: [
+ {
+ firstData: 'SubSub1F1',
+ secondData: 'SubSub1F2'
+ },
+ {
+ firstData: 'SubSub2F1',
+ secondData: 'SubSub2F2'
+ }
+ ]
+ },
+ {
+ firstData: 'Sub3F1',
+ secondData: 'Sub3F2'
+ }
+ ]
+ },
+ {
+ firstData: 'F\'1',
+ secondData: 'F\'2'
+ }
+
+ ];
+
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.footerRows = footerRows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ const button = THIS_DOC.createElement('button');
+ Polymer.dom(button).textContent = 'Sort By Col 0';
+ button.addEventListener('click', function() {
+ table.sortDescending = !table.sortDescending;
+ table.sortColumnIndex = 0;
+ });
+ table.rebuild();
+
+ this.addHTMLOutput(button);
+ });
+
+
+ test('instantiateNestedTableAlreadyExpanded', function() {
+ const columns = [
+ {
+ title: 'a',
+ value(row) { return row.a; },
+ width: '150px'
+ },
+ {
+ title: 'a',
+ value(row) { return row.b; },
+ width: '50%'
+ }
+ ];
+
+ const rows = [
+ {
+ a: 'aToplevel',
+ b: 'bToplevel',
+ isExpanded: true,
+ subRows: [
+ {
+ a: 'a1',
+ b: 'b1'
+ }
+ ]
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+ this.addHTMLOutput(table);
+
+ const a1El = tr.ui.b.findDeepElementMatchingPredicate(
+ table, e => Polymer.dom(e).textContent === 'a1');
+ assert.isDefined(a1El);
+
+ const bToplevelEl = tr.ui.b.findDeepElementMatchingPredicate(
+ table,
+ function(element) {
+ return Polymer.dom(element).textContent === 'bToplevel';
+ });
+ assert.isDefined(bToplevelEl);
+ const expandButton = Polymer.dom(bToplevelEl.parentElement)
+ .querySelector('expand-button');
+ assert.isTrue(Polymer.dom(expandButton).classList.contains(
+ 'button-expanded'));
+ });
+
+
+ test('subRowsThatAreRetrievedOnDemand', function() {
+ const columns = [
+ {
+ title: 'a',
+ value(row) { return row.a; },
+ width: '150px'
+ }
+ ];
+
+ const rows = [
+ {
+ a: 'row1',
+ subRows: [
+ {
+ b: 'row1.1',
+ get subRows() {
+ throw new Error('Shold not be called');
+ }
+ }
+ ]
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+ this.addHTMLOutput(table);
+ });
+
+
+ test('instantiateTableWithHiddenHeader', function() {
+ const columns = [
+ {
+ title: 'a',
+ value(row) { return row.a; },
+ width: '150px'
+ },
+ {
+ title: 'a',
+ value(row) { return row.b; },
+ width: '50%'
+ }
+ ];
+
+ const rows = [
+ {
+ a: 'aToplevel',
+ b: 'bToplevel'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.showHeader = false;
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+ this.addHTMLOutput(table);
+
+ const tHead = table.$.head;
+ assert.strictEqual(table.$.head.children.length, 0);
+ assert.strictEqual(0, tHead.getBoundingClientRect().height);
+
+ table.showHeader = true;
+ table.rebuild();
+ table.showHeader = false;
+ table.rebuild();
+ assert.strictEqual(table.$.head.children.length, 0);
+ });
+
+
+ test('sortColumnsNotPossibleOnPercentSizedColumns', function() {
+ const columns = [
+ {
+ title: 'Title',
+ value(row) { return row.a; },
+ width: '150px'
+ },
+ {
+ title: 'Value',
+ value(row) { return row.b; },
+ width: '100%',
+ showExpandButtons: true
+ }
+ ];
+
+ const table1 = document.createElement('tr-ui-b-table');
+ table1.showHeader = true;
+
+ assert.throws(function() {
+ table1.tableColumns = columns;
+ });
+ });
+
+ test('twoTablesFirstColumnMatching', function() {
+ const columns = [
+ {
+ title: 'Title',
+ value(row) { return row.a; },
+ width: '150px'
+ },
+ {
+ title: 'Value',
+ value(row) { return row.b; },
+ width: '100%'
+ }
+ ];
+
+ const table1 = document.createElement('tr-ui-b-table');
+ table1.showHeader = true;
+ table1.tableColumns = columns;
+ table1.tableRows = [
+ {
+ a: 'first',
+ b: 'row'
+ }
+ ];
+ table1.rebuild();
+ this.addHTMLOutput(table1);
+
+ const table2 = document.createElement('tr-ui-b-table');
+ table2.showHeader = false;
+ table2.tableColumns = columns;
+ table2.tableRows = [
+ {
+ a: 'second',
+ b: 'row'
+ }
+ ];
+ table2.rebuild();
+ this.addHTMLOutput(table2);
+
+ const h1FirstCol = table1.$.head.children[0].children[0];
+ const h2FirstCol = table2.$.body.children[0].children[0];
+ assert.strictEqual(h1FirstCol.getBoundingClientRect().width,
+ h2FirstCol.getBoundingClientRect().width);
+ });
+
+ test('programmaticSorting', function() {
+ const table = document.createElement('tr-ui-b-table');
+
+ const columns = [
+ {
+ title: 'Column',
+ value(row) { return row.value; },
+ cmp(rowA, rowB) {
+ return rowA.value.toString().localeCompare(
+ rowB.value.toString());
+ }
+ }
+ ];
+
+ const rows = [
+ {
+ value: 'A1',
+ subRows: [
+ {
+ value: 'A1.1'
+ },
+ {
+ value: 'A1.2',
+ subRows: [
+ {
+ value: 'A1.2.1'
+ },
+ {
+ value: 'A1.2.2'
+ }
+ ]
+ },
+ {
+ value: 'A1.3'
+ }
+ ]
+ },
+ {
+ value: 'A2'
+ }
+ ];
+
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ table.sortDescending = true;
+ table.sortColumnIndex = 0;
+ table.rebuild();
+ const r0 = table.$.body.children[0];
+ assert.strictEqual(r0.rowInfo.userRow, rows[1]);
+
+ const r1 = table.$.body.children[1];
+ assert.strictEqual(r1.rowInfo.userRow, rows[0]);
+ });
+
+ test('sortDispatchesEvent', function() {
+ const table = document.createElement('tr-ui-b-table');
+ const columns = [
+ {
+ title: 'Column 0',
+ value(row) { return row.value0; },
+ cmp(rowA, rowB) { return rowA.value0 - rowB.value0; }
+ },
+ {
+ title: 'Column 1',
+ value(row) { return row.value1; },
+ cmp(rowA, rowB) { return rowA.value1 - rowB.value1; }
+ }
+ ];
+
+ let sortColumnIndex = undefined;
+ let sortDescending = undefined;
+ let numListenerCalls = 0;
+ table.tableColumns = columns;
+ table.addEventListener('sort-column-changed', function(e) {
+ sortColumnIndex = e.sortColumnIndex;
+ sortDescending = e.sortDescending;
+ numListenerCalls++;
+ });
+ table.rebuild();
+
+ table.sortColumnIndex = 0;
+ assert.strictEqual(sortColumnIndex, 0);
+ assert.strictEqual(numListenerCalls, 1);
+
+ table.sortDescending = true;
+ assert.strictEqual(sortColumnIndex, 0);
+ assert.isTrue(sortDescending);
+ assert.strictEqual(numListenerCalls, 2);
+
+ table.sortColumnIndex = 1;
+ table.sortDescending = false;
+ assert.strictEqual(sortColumnIndex, 1);
+ assert.isFalse(sortDescending);
+ assert.strictEqual(numListenerCalls, 4);
+
+ table.sortColumnIndex = undefined;
+ assert.strictEqual(sortColumnIndex, undefined);
+ assert.strictEqual(numListenerCalls, 5);
+ });
+
+ test('sortingAfterExpand', function() {
+ const table = document.createElement('tr-ui-b-table');
+
+ const columns = [
+ {
+ title: 'Column',
+ value(row) { return row.value; },
+ cmp(rowA, rowB) {
+ return rowA.value.toString().localeCompare(
+ rowB.value.toString());
+ }
+ }
+ ];
+
+ const rows = [
+ {
+ value: 'A1',
+ isExpanded: true,
+ subRows: [
+ {
+ value: 'A1.1'
+ },
+ {
+ value: 'A1.2',
+ subRows: [
+ {
+ value: 'A1.2.1'
+ },
+ {
+ value: 'A1.2.2'
+ }
+ ]
+ },
+ {
+ value: 'A1.3'
+ }
+ ]
+ },
+ {
+ value: 'A2'
+ }
+ ];
+
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ table.sortDescending = true;
+ table.sortColumnIndex = 0;
+ table.rebuild();
+ const r0 = table.$.body.children[0];
+ assert.strictEqual(r0.rowInfo.userRow, rows[1]);
+
+ const r1 = table.$.body.children[1];
+ assert.strictEqual(r1.rowInfo.userRow, rows[0]);
+
+ const r2 = table.$.body.children[2];
+ assert.strictEqual(r2.rowInfo.userRow, rows[0].subRows[2]);
+
+ assert.isFalse(table.$.body.hasAttribute('tabindex'));
+ });
+
+ function createSimpleOneColumnNestedTable() {
+ const table = document.createElement('tr-ui-b-table');
+
+ const columns = [
+ {
+ title: 'Column',
+ value(row) { return row.value; },
+ cmp(rowA, rowB) {
+ return rowA.value.toString().localeCompare(
+ rowB.value.toString());
+ }
+ }
+ ];
+
+ const rows = [
+ {
+ value: 'A1',
+ subRows: [
+ {
+ value: 'A1.1'
+ },
+ {
+ value: 'A1.2',
+ subRows: [
+ {
+ value: 'A1.2.1'
+ },
+ {
+ value: 'A1.2.2'
+ }
+ ]
+ },
+ {
+ value: 'A1.3'
+ }
+ ]
+ },
+ {
+ value: 'A2'
+ }
+ ];
+
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ return table;
+ }
+
+ function createMultiColumnNestedTable() {
+ const table = document.createElement('tr-ui-b-table');
+
+ const columns = [
+ {
+ title: 'Title',
+ value(row) { return row.value; },
+ cmp(rowA, rowB) {
+ return rowA.value.toString().localeCompare(
+ rowB.value.toString());
+ },
+ width: '150px',
+ supportsCellSelection: false
+ },
+ {
+ title: 'A',
+ value(row) { return row.a; },
+ width: '25%'
+ },
+ {
+ title: 'B',
+ value(row) { return row.b; },
+ width: '25%'
+ },
+ {
+ title: 'C',
+ value(row) { return row.c; },
+ width: '25%',
+ supportsCellSelection: false
+ },
+ {
+ title: 'D',
+ value(row) { return row.d; },
+ width: '25%'
+ }
+ ];
+
+ const rows = [
+ {
+ value: 'R1',
+ a: 1, b: 2, c: 3, d: 4,
+ subRows: [
+ {
+ value: 'R1.1',
+ a: 2, b: 3, c: 4, d: 1,
+ },
+ {
+ value: 'R1.2',
+ a: 3, b: 4, c: 1, d: 2,
+ }
+ ]
+ },
+ {
+ value: 'R2',
+ a: 3, b: 4, c: 1, d: 2
+ }
+ ];
+
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ return table;
+ }
+
+ test('expandAfterRebuild', function() {
+ const table = createSimpleOneColumnNestedTable();
+ table.rebuild();
+ const rows = table.tableRows;
+
+ this.addHTMLOutput(table);
+
+ table.rebuild();
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+ table.setExpandedForTableRow(rows[0], true);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ const r1 = table.$.body.children[1];
+ assert.strictEqual(r1.rowInfo.userRow, rows[0].subRows[0]);
+ });
+
+ test('tableSelection', function() {
+ const table = createMultiColumnNestedTable();
+ const rows = table.tableRows;
+
+ table.selectionMode = SelectionMode.ROW;
+ table.selectedTableRow = rows[0];
+ assert.isUndefined(table.selectedColumnIndex);
+
+ table.setExpandedForTableRow(rows[0], true);
+ table.selectedTableRow = rows[0].subRows[1];
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[1]);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ table.selectionMode = SelectionMode.CELL;
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[1]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ table.setExpandedForTableRow(rows[0], false);
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ table.selectionMode = SelectionMode.NONE;
+ assert.strictEqual(table.selectedTableRow, undefined);
+
+ table.selectionMode = SelectionMode.ROW;
+ table.setExpandedForTableRow(rows[0].subRows[1], true);
+ this.addHTMLOutput(table);
+
+ assert.isTrue(table.$.body.hasAttribute('tabindex'));
+ });
+
+
+ test('keyMovement_rows', function() {
+ const table = createSimpleOneColumnNestedTable();
+ table.selectionMode = SelectionMode.ROW;
+ this.addHTMLOutput(table);
+
+ const rows = table.tableRows;
+ table.selectedTableRow = rows[0];
+
+ table.performKeyCommand_('ARROW_DOWN');
+ assert.strictEqual(table.selectedTableRow, rows[1]);
+
+ table.performKeyCommand_('ARROW_UP');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+
+ // Enter on collapsed row should expand.
+ table.selectedTableRow = rows[0];
+ table.performKeyCommand_('SPACE');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('SPACE');
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+
+ // Arrow right on collapsed row should expand.
+ table.selectedTableRow = rows[0];
+ table.performKeyCommand_('ARROW_RIGHT');
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[0]);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_DOWN');
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[1]);
+
+ // Arrow left on collapsed item should select parent.
+ table.performKeyCommand_('ARROW_LEFT');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+ // Arrow left on parent should collapse its children.
+ table.performKeyCommand_('ARROW_LEFT');
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+
+ // Arrow right on expanded row should select first child.
+ table.selectedTableRow = rows[0];
+ table.setExpandedForTableRow(rows[0], true);
+ table.performKeyCommand_('ARROW_RIGHT');
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[0]);
+
+ // Arrow right on a non-expandable row should do nothing.
+ table.selectedTableRow = rows[1];
+ assert.strictEqual(table.selectedTableRow, rows[1]);
+ table.performKeyCommand_('ARROW_RIGHT');
+ assert.strictEqual(table.selectedTableRow, rows[1]);
+ assert.isFalse(table.getExpandedForTableRow(rows[1]));
+ });
+
+ test('keyMovement_cells', function() {
+ const table = createMultiColumnNestedTable();
+ table.selectionMode = SelectionMode.CELL;
+ this.addHTMLOutput(table);
+
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ const rows = table.tableRows;
+ table.selectedTableRow = rows[1];
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ table.performKeyCommand_('ARROW_LEFT');
+ assert.strictEqual(table.selectedTableRow, rows[1]);
+ // No-op (leftmost selectable cell already selected).
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ table.performKeyCommand_('ARROW_UP');
+ // No-op (top row already selected).
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ table.performKeyCommand_('ARROW_UP');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ table.performKeyCommand_('ARROW_RIGHT');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 2);
+ // Right arrow should NOT expand nested rows in cell selection mode.
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_RIGHT');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 4);
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_RIGHT');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ // No-op (rightmost selectable cell already selected).
+ assert.strictEqual(table.selectedColumnIndex, 4);
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('SPACE');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 4);
+ // Space on collapsed row should expand it.
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_DOWN');
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 4);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_LEFT');
+ // Left arrow should NOT move to parent row.
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 2);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_LEFT');
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_LEFT');
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[0]);
+ // No-op (leftmost selectable cell already selected).
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_UP');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_LEFT');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ // No-op (leftmost selectable cell already selected).
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ // Left arrow should NOT collapse nested rows in cell selection mode.
+ assert.isTrue(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('SPACE');
+ assert.strictEqual(table.selectedTableRow, rows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ // Space on expanded row should collapse it.
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_DOWN');
+ assert.strictEqual(table.selectedTableRow, rows[1]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+
+ table.performKeyCommand_('ARROW_DOWN');
+ // No-op (bottom row already selected).
+ assert.strictEqual(table.selectedTableRow, rows[1]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ assert.isFalse(table.getExpandedForTableRow(rows[0]));
+ });
+
+ test('focus_empty', function() {
+ const table = createSimpleOneColumnNestedTable();
+ table.tableRows = [];
+ table.emptyValue = 'This table is left intentionally empty';
+ this.addHTMLOutput(table);
+
+ assert.isFalse(table.$.body.hasAttribute('tabindex'));
+ assert.isFalse(table.isFocused);
+
+ for (const selectionMode of [SelectionMode.ROW, SelectionMode.CELL]) {
+ table.selectionMode = selectionMode;
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Manually focus.
+ table.focus();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Manually unfocus.
+ table.blur();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Manually focus again.
+ table.focus();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Unfocus via removing selection mode.
+ table.selectionMode = SelectionMode.NONE;
+ assert.isFalse(table.$.body.hasAttribute('tabindex'));
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+ }
+
+ // Re-enable selection mode (for interactive testing).
+ table.selectionMode = SelectionMode.ROW;
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+ });
+
+ test('focus_rows', function() {
+ const table = createSimpleOneColumnNestedTable();
+ table.selectionMode = SelectionMode.ROW;
+ this.addHTMLOutput(table);
+
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Manually focus.
+ table.focus();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[0]);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Manually unfocus.
+ table.blur();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[0]);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Trigger focus via clicking.
+ table.$.body.children[1].children[0].click();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[1]);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Unfocus via removing selection mode.
+ table.selectionMode = SelectionMode.NONE;
+ assert.isFalse(table.$.body.hasAttribute('tabindex'));
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Re-enable selection mode.
+ table.selectionMode = SelectionMode.ROW;
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Programatically select row (should NOT steal focus).
+ table.selectedTableRow = table.tableRows[0];
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[0]);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Trigger focus on the already selected row by clicking.
+ table.$.body.children[0].children[0].click();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[0]);
+ assert.isUndefined(table.selectedColumnIndex);
+ });
+
+ test('focus_cells', function() {
+ const table = createMultiColumnNestedTable();
+ table.selectionMode = SelectionMode.CELL;
+ this.addHTMLOutput(table);
+
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Manually focus.
+ table.focus();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ // Manually unfocus.
+ table.blur();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ // Trigger focus via clicking.
+ table.$.body.children[1].children[4].click();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[1]);
+ assert.strictEqual(table.selectedColumnIndex, 4);
+
+ // Unfocus via removing selection mode.
+ table.selectionMode = SelectionMode.NONE;
+ assert.isFalse(table.$.body.hasAttribute('tabindex'));
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Re-enable selection mode.
+ table.selectionMode = SelectionMode.CELL;
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Clicking on an unselectable cell should NOT trigger focus.
+ table.$.body.children[1].children[0].click();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Programatically select cell (should NOT steal focus).
+ table.selectedTableRow = table.tableRows[0];
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+
+ // Trigger focus on the already selected cell by clicking.
+ table.$.body.children[0].children[1].click();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.strictEqual(table.selectedTableRow, table.tableRows[0]);
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ });
+
+ test('focus_allCellsUnselectable', function() {
+ const table = createMultiColumnNestedTable();
+ table.selectionMode = SelectionMode.CELL;
+ for (const c of table.tableColumns) {
+ c.supportsCellSelection = false;
+ }
+ table.tableColumns = table.tableColumns;
+ this.addHTMLOutput(table);
+
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isFalse(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Manually focus (no automatic selection).
+ table.focus();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+
+ // Trigger focus via clicking (no selection).
+ table.$.body.children[1].children[2].click();
+ assert.strictEqual(table.$.body.getAttribute('tabindex'), '0');
+ assert.isTrue(table.isFocused);
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+ });
+
+ test('RightArrowKeyWhenTableSorted', function() {
+ const table = createSimpleOneColumnNestedTable();
+ table.selectionMode = SelectionMode.ROW;
+ this.addHTMLOutput(table);
+ table.sortDescending = true;
+ table.sortColumnIndex = 0;
+ table.rebuild();
+ const rows = table.tableRows;
+
+ // Arrow right should select the first child showing up on the viewer,
+ // rather than first child in sub rows since sorted.
+ table.selectedTableRow = rows[0];
+ table.performKeyCommand_('ARROW_RIGHT');
+ assert.strictEqual(table.selectedTableRow, rows[0].subRows[2]);
+ });
+
+ test('reduceNumberOfColumnsAfterRebuild', function() {
+ // Create a table with two columns.
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; },
+ width: '100px'
+ },
+ {
+ title: 'Second Column',
+ value(row) { return row.secondData; },
+ width: '100px'
+ }
+ ];
+
+ // Build the table.
+ table.rebuild();
+
+ // Check that reducing the number of columns doesn't throw an exception.
+ table.tableColumns = [
+ {
+ title: 'First Column',
+ value(row) { return row.firstData; },
+ width: '200px'
+ }
+ ];
+ });
+
+ test('rowHighlightDark', function() {
+ const columns = [
+ {
+ title: 'Title',
+ value(row) { return row.a; },
+ width: '150px',
+ supportsCellSelection: false
+ },
+ {
+ title: 'Col1',
+ value(row) { return row.b; },
+ width: '33%'
+ },
+ {
+ title: 'Col2',
+ value(row) { return row.b * 2; },
+ width: '33%'
+ },
+ {
+ title: 'Col3',
+ value(row) { return row.b * 3; },
+ width: '33%'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.showHeader = true;
+ table.rowHighlightStyle = HighlightStyle.DARK;
+ table.tableColumns = columns;
+ table.tableRows = [
+ {
+ a: 'first',
+ b: '1'
+ },
+ {
+ a: 'second',
+ b: '2'
+ }
+ ];
+ table.rebuild();
+ this.addHTMLOutput(table);
+ });
+
+ test('cellHighlightLight', function() {
+ const columns = [
+ {
+ title: 'Title',
+ value(row) { return row.a; },
+ width: '150px',
+ supportsCellSelection: false
+ },
+ {
+ title: 'Col1',
+ value(row) { return row.b; },
+ width: '33%'
+ },
+ {
+ title: 'Col2',
+ value(row) { return row.b * 2; },
+ width: '33%'
+ },
+ {
+ title: 'Col3',
+ value(row) { return row.b * 3; },
+ width: '33%'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.showHeader = true;
+ table.cellHighlightStyle = HighlightStyle.LIGHT;
+ table.tableColumns = columns;
+ table.tableRows = [
+ {
+ a: 'first',
+ b: '1'
+ },
+ {
+ a: 'second',
+ b: '2'
+ }
+ ];
+ table.rebuild();
+ this.addHTMLOutput(table);
+ });
+
+ test('cellSelectionBasic', function() {
+ const columns = [
+ {
+ title: 'Title',
+ value(row) { return row.a; },
+ width: '150px',
+ supportsCellSelection: false
+ },
+ {
+ title: 'Col1',
+ value(row) { return row.b; },
+ width: '33%'
+ },
+ {
+ title: 'Col2',
+ value(row) { return row.b * 2; },
+ width: '33%'
+ },
+ {
+ title: 'Col3',
+ value(row) { return row.b * 3; },
+ width: '33%'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.showHeader = true;
+ table.selectionMode = SelectionMode.CELL;
+ table.rowHighlightStyle = HighlightStyle.NONE;
+ table.tableColumns = columns;
+ table.tableRows = [
+ {
+ a: 'first',
+ b: '1'
+ },
+ {
+ a: 'second',
+ b: '2'
+ }
+ ];
+ table.rebuild();
+ this.addHTMLOutput(table);
+
+ table.selectedTableRow = table.tableRows[0];
+ assert.strictEqual(table.selectedColumnIndex, 1);
+ let selectedCell = table.selectedCell;
+ assert.strictEqual(selectedCell.row, table.tableRows[0]);
+ assert.strictEqual(selectedCell.column, columns[1]);
+ assert.strictEqual(selectedCell.value, '1');
+
+ table.performKeyCommand_('ARROW_DOWN');
+ table.performKeyCommand_('ARROW_RIGHT');
+ table.performKeyCommand_('ARROW_RIGHT');
+ table.performKeyCommand_('ARROW_LEFT');
+ assert.strictEqual(table.selectedTableRow, table.tableRows[1]);
+ assert.strictEqual(table.selectedColumnIndex, 2);
+ selectedCell = table.selectedCell;
+ assert.strictEqual(selectedCell.row, table.tableRows[1]);
+ assert.strictEqual(selectedCell.column, columns[2]);
+ assert.strictEqual(selectedCell.value, 4);
+
+ table.selectedTableRow = undefined;
+ assert.isUndefined(table.selectedTableRow);
+ assert.isUndefined(table.selectedColumnIndex);
+ assert.isUndefined(table.selectedColumnIndex);
+ assert.isUndefined(table.selectedCell);
+ });
+
+ test('cellSelectionNested', function() {
+ const columns = [
+ {
+ title: 'Title',
+ value(row) { return row.a; },
+ width: '150px',
+ supportsCellSelection: false
+ },
+ {
+ title: 'Value',
+ value(row) { return row.b; },
+ width: '150px'
+ }
+ ];
+
+ const rows = [
+ {
+ a: 'parent',
+ b: '1',
+ subRows: [
+ {
+ a: 'child',
+ b: '2'
+ }
+ ]
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.showHeader = true;
+ table.selectionMode = SelectionMode.CELL;
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+ this.addHTMLOutput(table);
+
+ // Expand the parent row.
+ table.setExpandedForTableRow(rows[0], true);
+
+ // Select the second cell in the child row.
+ table.selectedTableRow = rows[0].subRows[0];
+ assert.isFalse(isSelected(table.$.body.children[0]));
+ assert.isFalse(isSelected(table.$.body.children[0].children[1]));
+ assert.isTrue(isSelected(table.$.body.children[1]));
+ assert.isTrue(isSelected(table.$.body.children[1].children[1]));
+
+ // Fold the parent row. The second cell in the parent row should be
+ // automatically selected.
+ table.setExpandedForTableRow(rows[0], false);
+ assert.isTrue(isSelected(table.$.body.children[0]));
+ assert.isTrue(isSelected(table.$.body.children[0].children[1]));
+
+ // Expand the parent row again. Only the second cell of the parent row
+ // should still be selected.
+ table.setExpandedForTableRow(rows[0], true);
+ assert.isTrue(isSelected(table.$.body.children[0]));
+ assert.isTrue(isSelected(table.$.body.children[0].children[1]));
+ assert.isFalse(isSelected(table.$.body.children[1]));
+ assert.isFalse(isSelected(table.$.body.children[1].children[1]));
+ });
+
+ test('resolvedHighlightStyle', function() {
+ const table = document.createElement('tr-ui-b-table');
+
+ // Undefined selection mode.
+ assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.NONE);
+ assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.NONE);
+
+ // Row selection mode.
+ table.selectionMode = SelectionMode.ROW;
+ assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.DARK);
+ assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.NONE);
+
+ // Cell selection mode.
+ table.selectionMode = SelectionMode.CELL;
+ assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.LIGHT);
+ assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.DARK);
+
+ // Explicit row highlight style.
+ table.rowHighlightStyle = HighlightStyle.NONE;
+ assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.NONE);
+ assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.DARK);
+
+ // Explicit row and cell highlight styles.
+ table.cellHighlightStyle = HighlightStyle.LIGHT;
+ assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.NONE);
+ assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.LIGHT);
+
+ // Back to default highlight styles.
+ table.cellHighlightStyle = HighlightStyle.DEFAULT;
+ table.rowHighlightStyle = HighlightStyle.DEFAULT;
+ assert.strictEqual(table.resolvedRowHighlightStyle, HighlightStyle.LIGHT);
+ assert.strictEqual(table.resolvedCellHighlightStyle, HighlightStyle.DARK);
+ });
+
+ test('headersWithHtmlElements', function() {
+ const firstColumnTitle = document.createTextNode('First Column');
+ const secondColumnTitle = document.createElement('span');
+ secondColumnTitle.innerText = 'Second Column';
+ secondColumnTitle.style.color = 'blue';
+
+ const columns = [
+ {
+ title: firstColumnTitle,
+ value(row) { return row.firstData; },
+ width: '200px'
+ },
+ {
+ title: secondColumnTitle,
+ value(row) { return row.secondData; }
+ }
+ ];
+
+ const rows = [
+ {
+ firstData: 'A1',
+ secondData: 'A2'
+ },
+ {
+ firstData: 'B1',
+ secondData: 'B2'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ const firstColumnHeader = table.$.head.children[0].children[0].children[0];
+ const secondColumnHeader = table.$.head.children[0].children[1].children[0];
+ assert.strictEqual(Polymer.dom(firstColumnHeader.cellTitle).textContent,
+ 'First Column');
+ assert.strictEqual(Polymer.dom(secondColumnHeader.cellTitle).textContent,
+ 'Second Column');
+ });
+
+ test('align', function() {
+ const columns = [
+ {
+ title: 'a',
+ align: ColumnAlignment.RIGHT,
+ value(row) {
+ return row.a;
+ }
+ }
+ ];
+ const rows = [{a: 1}, {a: 'long-row-so-that-alignment-would-be-visible'}];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ assert.strictEqual(
+ table.$.body.children[0].children[0].style.textAlign, 'right');
+ });
+
+ test('subRowsPropertyName', function() {
+ const columns = [
+ {
+ title: 'a',
+ value(row) {
+ return row.a;
+ }
+ }
+ ];
+ const rows = [
+ {
+ a: 1,
+ isExpanded: true,
+ children: [
+ {a: 2}
+ ]
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.subRowsPropertyName = 'children';
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ assert.strictEqual(
+ '2', Polymer.dom(table.$.body.children[1].children[0]).textContent);
+ });
+
+ test('shouldNotRenderUndefined', function() {
+ const columns = [
+ {
+ title: 'Column',
+ value(row) { return row.firstData; }
+ }
+ ];
+
+ const rows = [
+ {
+ firstData: undefined,
+ secondData: 'A2'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ // check that we don't have 'undefined' anywhere
+ assert.isTrue(Polymer.dom(table.$.body).innerHTML.indexOf('undefined') < 0);
+ });
+
+ test('customizeTableRowCallback', function() {
+ const columns = [
+ {
+ title: 'Column',
+ value(row) { return row.data; }
+ }
+ ];
+
+ const rows = [
+ {
+ data: 'data'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ let callbackCalled = false;
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.customizeTableRowCallback = function(userRow, trElement) {
+ callbackCalled = (userRow === rows[0]);
+ };
+ table.rebuild();
+ assert.isTrue(callbackCalled);
+
+ this.addHTMLOutput(table);
+
+ // The callback can also be set after the table is first built.
+ table.customizeTableRowCallback = function(userRow, trElement) {
+ callbackCalled = (userRow === rows[0]);
+ };
+
+ // Setting the customize callback should set the body dirty.
+ assert.isTrue(table.bodyDirty_);
+
+ callbackCalled = false;
+
+ // Don't bother waiting for the timeout.
+ table.rebuild();
+
+ assert.isTrue(callbackCalled);
+ });
+
+ test('selectionEdgeCases', function() {
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = [
+ {
+ title: 'Column',
+ value(row) { return row.data; },
+ supportsCellSelection: false
+ }
+ ];
+ table.tableRows = [{ data: 'body row' }];
+ table.footerRows = [{ data: 'footer row' }];
+ table.selectionMode = SelectionMode.ROW;
+ this.addHTMLOutput(table);
+
+ // Clicking on the body row should *not* throw an exception (despite the
+ // column not supporting cell selection).
+ table.$.body.children[0].children[0].click();
+
+ // Clicking on the footer row should *not* throw an exception (despite
+ // footer rows not being selectable in general).
+ table.$.foot.children[0].children[0].click();
+ });
+
+ test('defaultExpansionStateCallback', function() {
+ const columns = [
+ {
+ title: 'Name',
+ value(row) { return row.name; }
+ },
+ {
+ title: 'Value',
+ value(row) { return row.value; }
+ }
+ ];
+
+ const rows = [
+ {
+ name: 'A',
+ value: 10,
+ subRows: [
+ {
+ name: 'B',
+ value: 8,
+ subRows: [
+ {
+ name: 'C',
+ value: 4
+ },
+ {
+ name: 'D',
+ value: 4
+ }
+ ]
+ },
+ {
+ name: 'E',
+ value: 2,
+ subRows: [
+ {
+ name: 'F',
+ value: 1
+ },
+ {
+ name: 'G',
+ value: 1
+ }
+ ]
+ }
+ ]
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ let cRow = tr.ui.b.findDeepElementMatchingPredicate(
+ table, function(element) {
+ return Polymer.dom(element).textContent === 'C';
+ });
+ assert.strictEqual(cRow, undefined);
+
+ let callbackCalled = false;
+ table.defaultExpansionStateCallback = function(row, parentRow) {
+ callbackCalled = true;
+
+ if (parentRow === undefined) return true;
+
+ if (row.value >= (parentRow.value * 0.8)) return true;
+
+ return false;
+ };
+
+ // Setting the callback should set the body dirty.
+ assert.isTrue(table.bodyDirty_);
+ assert.isFalse(callbackCalled);
+
+ table.rebuild();
+
+ assert.isTrue(callbackCalled);
+ cRow = tr.ui.b.findDeepElementMatchingPredicate(table, function(element) {
+ return Polymer.dom(element).textContent === 'C';
+ });
+ assert.isDefined(cRow);
+ });
+
+ test('sortExpanded', function() {
+ const columns = [
+ {
+ title: 'Name',
+ value(row) { return row.name; }
+ },
+ {
+ title: 'Value',
+ value(row) { return row.value; },
+ cmp(x, y) { return x.value - y.value; }
+ }
+ ];
+
+ const rows = [
+ {
+ name: 'A',
+ value: 10,
+ subRows: [
+ {
+ name: 'B',
+ value: 8
+ },
+ {
+ name: 'C',
+ value: 4
+ },
+ ]
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ function isB(row) {
+ return row.textContent === 'B';
+ }
+
+ // Check that 'A' row is not expanded.
+ assert.isUndefined(tr.ui.b.findDeepElementMatchingPredicate(table, isB));
+
+ // Expand 'A' row.
+ table.setExpandedForTableRow(rows[0], true);
+
+ // Check that 'A' is expanded.
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(table, isB));
+
+ // Sort by value.
+ table.sortColumnIndex = 1;
+
+ // Rebuild the table synchronously instead of waiting for scheduleRebuild_'s
+ // setTimeout(0).
+ table.rebuild();
+
+ // Check that 'A' is still expanded.
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(table, isB));
+ });
+
+ test('shouldPreserveSortWhenColumnsChange', function() {
+ const name = {
+ title: 'Name',
+ value(row) { return row.name; },
+ };
+
+ const count = {
+ title: 'Count',
+ value(row) { return row.count; },
+ cmp: (rowA, rowB) => rowA.a - rowB.a,
+ };
+
+ const otherCount = {
+ title: 'Count',
+ value(row) { return row.count; },
+ cmp: (rowA, rowB) => rowA.a - rowB.a,
+ };
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = [count];
+ table.sortColumnIndex = 0;
+ table.sortDescending = true;
+ table.rebuild();
+
+ this.addHTMLOutput(table);
+
+ table.tableColumns = [name, count];
+ table.rebuild();
+ assert.strictEqual(1, table.sortColumnIndex);
+ assert.isTrue(table.sortDescending);
+
+ table.sortDescending = false;
+ table.tableColumns = [otherCount, name];
+ table.rebuild();
+ assert.strictEqual(0, table.sortColumnIndex);
+ assert.isFalse(table.sortDescending);
+
+ table.tableColumns = [name];
+ table.rebuild();
+ assert.isUndefined(table.sortColumnIndex);
+ });
+
+ test('userCanModifySortOrder', function() {
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = [
+ {
+ title: 'Name',
+ value: row => row.name
+ },
+ {
+ title: 'colA',
+ value: row => row.a,
+ cmp: (rowA, rowB) => rowA.a - rowB.a
+ },
+ {
+ title: 'colB',
+ value: row => row.b,
+ cmp: (rowA, rowB) => rowA.b - rowB.b
+ }
+ ];
+ table.tableRows = [
+ {name: 'A', a: 42, b: 0},
+ {name: 'B', a: 89, b: 100},
+ {name: 'C', a: 65, b: -273.15}
+ ];
+ table.userCanModifySortOrder = false;
+ table.sortColumnIndex = 2;
+ table.sortDescending = true;
+ table.rebuild();
+ this.addHTMLOutput(table);
+
+ const toggleButton = document.createElement('button');
+ Polymer.dom(toggleButton).textContent =
+ 'Toggle table.userCanModifySortOrder';
+ toggleButton.addEventListener('click', function() {
+ table.userCanModifySortOrder = !table.userCanModifySortOrder;
+ });
+ this.addHTMLOutput(toggleButton);
+
+ const unsetButton = document.createElement('button');
+ Polymer.dom(unsetButton).textContent = 'Unset sort order';
+ unsetButton.addEventListener('click', function() {
+ table.sortColumnIndex = undefined;
+ });
+ this.addHTMLOutput(unsetButton);
+ });
+
+ test('columnSelection', function() {
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = [
+ {
+ title: 'Name',
+ value: (row) => row.name
+ },
+ {
+ title: 'colA',
+ selectable: true,
+ value: (row) => row.a,
+ cmp: (rowA, rowB) => rowA.a - rowB.a
+ },
+ {
+ title: 'colB',
+ selectable: true,
+ value: (row) => row.b,
+ cmp: (rowA, rowB) => rowA.b - rowB.b
+ }
+ ];
+ table.tableRows = [
+ {name: 'foo', a: 42, b: -42},
+ {name: 'bar', a: 57, b: 133}
+ ];
+ table.rebuild();
+ table.selectionMode = SelectionMode.CELL;
+ this.addHTMLOutput(table);
+
+ table.selectedTableColumnIndex = 1;
+ let cols = tr.ui.b.findDeepElementMatchingPredicate(table,
+ e => e.tagName === 'COLGROUP').children;
+ assert.isNull(cols[0].getAttribute('selected'));
+ assert.strictEqual(cols[1].getAttribute('selected'), 'true');
+ assert.isNull(cols[2].getAttribute('selected'));
+ assert.strictEqual(1, table.selectedTableColumnIndex);
+
+ table.selectedTableColumnIndex = undefined;
+ cols = tr.ui.b.findDeepElementMatchingPredicate(table,
+ e => e.tagName === 'COLGROUP').children;
+ assert.isNull(cols[0].getAttribute('selected'));
+ assert.isNull(cols[1].getAttribute('selected'));
+ assert.isNull(cols[2].getAttribute('selected'));
+ assert.isUndefined(table.selectedTableColumnIndex);
+
+ table.selectedTableColumnIndex = 2;
+ cols = tr.ui.b.findDeepElementMatchingPredicate(table,
+ e => e.tagName === 'COLGROUP').children;
+ assert.isNull(cols[0].getAttribute('selected'));
+ assert.isNull(cols[1].getAttribute('selected'));
+ assert.strictEqual(cols[2].getAttribute('selected'), 'true');
+ assert.strictEqual(2, table.selectedTableColumnIndex);
+ });
+
+ test('stepInto', function() {
+ const columns = [
+ {
+ title: 'Title',
+ value(row) { return row.a; },
+ width: '150px',
+ supportsCellSelection: false
+ },
+ {
+ title: 'Col1',
+ value(row) { return row.b; },
+ width: '33%'
+ },
+ {
+ title: 'Col2',
+ value(row) { return row.b * 2; },
+ width: '33%'
+ },
+ {
+ title: 'Col3',
+ value(row) { return row.b * 3; },
+ width: '33%'
+ }
+ ];
+ const rows = [
+ {
+ a: 'first',
+ b: '1'
+ },
+ {
+ a: 'second',
+ b: '2'
+ }
+ ];
+
+ const table = document.createElement('tr-ui-b-table');
+
+ const firedStepIntoEvents = [];
+ table.addEventListener('step-into', e => firedStepIntoEvents.push(e));
+
+ table.cellHighlightStyle = HighlightStyle.DARK;
+ table.tableColumns = columns;
+ table.tableRows = rows;
+ table.rebuild();
+ this.addHTMLOutput(table);
+
+ assert.lengthOf(firedStepIntoEvents, 0);
+
+ // Double click.
+ simulateDoubleClick(table.$.body.children[0].children[1]);
+ assert.lengthOf(firedStepIntoEvents, 1);
+ assert.strictEqual(firedStepIntoEvents[0].tableRow, rows[0]);
+ assert.strictEqual(firedStepIntoEvents[0].tableColumn, columns[1]);
+ assert.strictEqual(firedStepIntoEvents[0].columnIndex, 1);
+
+ simulateDoubleClick(table.$.body.children[1].children[3]);
+ assert.lengthOf(firedStepIntoEvents, 2);
+ assert.strictEqual(firedStepIntoEvents[1].tableRow, rows[1]);
+ assert.strictEqual(firedStepIntoEvents[1].tableColumn, columns[3]);
+ assert.strictEqual(firedStepIntoEvents[1].columnIndex, 3);
+
+ // Shift+Enter in cell selection mode.
+ table.selectionMode = SelectionMode.CELL;
+ table.selectedTableRow = rows[0];
+ table.selectedColumnIndex = 2;
+ table.performKeyCommand_('ENTER');
+ assert.lengthOf(firedStepIntoEvents, 3);
+ assert.strictEqual(firedStepIntoEvents[2].tableRow, rows[0]);
+ assert.strictEqual(firedStepIntoEvents[2].tableColumn, columns[2]);
+ assert.strictEqual(firedStepIntoEvents[2].columnIndex, 2);
+
+ // Shift+Enter in row selection mode.
+ table.selectionMode = SelectionMode.ROW;
+ table.selectedTableRow = rows[1];
+ table.performKeyCommand_('ENTER');
+ assert.lengthOf(firedStepIntoEvents, 4);
+ assert.strictEqual(firedStepIntoEvents[3].tableRow, rows[1]);
+ assert.isUndefined(firedStepIntoEvents[3].tableColumn);
+ assert.isUndefined(firedStepIntoEvents[3].columnIndex);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/timing_tool.html b/chromium/third_party/catapult/tracing/tracing/ui/base/timing_tool.html
new file mode 100644
index 00000000000..e142afd50f1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/timing_tool.html
@@ -0,0 +1,327 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/slice.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Provides the TimingTool class.
+ */
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * Tool for taking time measurements in the TimelineTrackView using
+ * Viewportmarkers.
+ * @constructor
+ */
+ function TimingTool(viewport, targetElement) {
+ this.viewport_ = viewport;
+
+ // Prepare the event handlers to be added and removed repeatedly.
+ this.onMouseMove_ = this.onMouseMove_.bind(this);
+ this.onDblClick_ = this.onDblClick_.bind(this);
+ this.targetElement_ = targetElement;
+
+ // Valid only during mousedown.
+ this.isMovingLeftEdge_ = false;
+ }
+
+ TimingTool.prototype = {
+
+ onEnterTiming(e) {
+ this.targetElement_.addEventListener('mousemove', this.onMouseMove_);
+ this.targetElement_.addEventListener('dblclick', this.onDblClick_);
+ },
+
+ onBeginTiming(e) {
+ if (!this.isTouchPointInsideTrackBounds_(e.clientX, e.clientY)) {
+ return;
+ }
+
+ const pt = this.getSnappedToEventPosition_(e);
+ this.mouseDownAt_(pt.x, pt.y);
+
+ this.updateSnapIndicators_(pt);
+ },
+
+ updateSnapIndicators_(pt) {
+ if (!pt.snapped) return;
+
+ const ir = this.viewport_.interestRange;
+ if (ir.min === pt.x) {
+ ir.leftSnapIndicator = new tr.ui.SnapIndicator(pt.y, pt.height);
+ }
+ if (ir.max === pt.x) {
+ ir.rightSnapIndicator = new tr.ui.SnapIndicator(pt.y, pt.height);
+ }
+ },
+
+ onUpdateTiming(e) {
+ const pt = this.getSnappedToEventPosition_(e);
+ this.mouseMoveAt_(pt.x, pt.y, true);
+ this.updateSnapIndicators_(pt);
+ },
+
+ onEndTiming(e) {
+ this.mouseUp_();
+ },
+
+ onExitTiming(e) {
+ this.targetElement_.removeEventListener('mousemove', this.onMouseMove_);
+ this.targetElement_.removeEventListener('dblclick', this.onDblClick_);
+ },
+
+ onMouseMove_(e) {
+ if (e.button) return;
+
+ const worldX = this.getWorldXFromEvent_(e);
+ this.mouseMoveAt_(worldX, e.clientY, false);
+ },
+
+ onDblClick_(e) {
+ // TODO(nduca): Implement dobuleclicking.
+ },
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ isTouchPointInsideTrackBounds_(clientX, clientY) {
+ if (!this.viewport_ ||
+ !this.viewport_.modelTrackContainer ||
+ !this.viewport_.modelTrackContainer.canvas) {
+ return false;
+ }
+
+ const canvas = this.viewport_.modelTrackContainer.canvas;
+ const canvasRect = canvas.getBoundingClientRect();
+ if (clientX >= canvasRect.left && clientX <= canvasRect.right &&
+ clientY >= canvasRect.top && clientY <= canvasRect.bottom) {
+ return true;
+ }
+
+ return false;
+ },
+
+ mouseDownAt_(worldX, y) {
+ const ir = this.viewport_.interestRange;
+ const dt = this.viewport_.currentDisplayTransform;
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const nearnessThresholdWorld = dt.xViewVectorToWorld(6 * pixelRatio);
+
+ if (ir.isEmpty) {
+ ir.setMinAndMax(worldX, worldX);
+ ir.rightSelected = true;
+ this.isMovingLeftEdge_ = false;
+ return;
+ }
+
+
+ // Left edge test.
+ if (Math.abs(worldX - ir.min) < nearnessThresholdWorld) {
+ ir.leftSelected = true;
+ ir.min = worldX;
+ this.isMovingLeftEdge_ = true;
+ return;
+ }
+
+ // Right edge test.
+ if (Math.abs(worldX - ir.max) < nearnessThresholdWorld) {
+ ir.rightSelected = true;
+ ir.max = worldX;
+ this.isMovingLeftEdge_ = false;
+ return;
+ }
+
+ ir.setMinAndMax(worldX, worldX);
+ ir.rightSelected = true;
+ this.isMovingLeftEdge_ = false;
+ },
+
+ mouseMoveAt_(worldX, y, mouseDown) {
+ if (mouseDown) {
+ this.updateMovingEdge_(worldX);
+ return;
+ }
+
+ const ir = this.viewport_.interestRange;
+ const dt = this.viewport_.currentDisplayTransform;
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const nearnessThresholdWorld = dt.xViewVectorToWorld(6 * pixelRatio);
+
+ // Left edge test.
+ if (Math.abs(worldX - ir.min) < nearnessThresholdWorld) {
+ ir.leftSelected = true;
+ ir.rightSelected = false;
+ return;
+ }
+
+ // Right edge test.
+ if (Math.abs(worldX - ir.max) < nearnessThresholdWorld) {
+ ir.leftSelected = false;
+ ir.rightSelected = true;
+ return;
+ }
+
+ ir.leftSelected = false;
+ ir.rightSelected = false;
+ return;
+ },
+
+ updateMovingEdge_(newWorldX) {
+ const ir = this.viewport_.interestRange;
+ let a = ir.min;
+ let b = ir.max;
+ if (this.isMovingLeftEdge_) {
+ a = newWorldX;
+ } else {
+ b = newWorldX;
+ }
+
+ if (a <= b) {
+ ir.setMinAndMax(a, b);
+ } else {
+ ir.setMinAndMax(b, a);
+ }
+
+ if (ir.min === newWorldX) {
+ this.isMovingLeftEdge_ = true;
+ ir.leftSelected = true;
+ ir.rightSelected = false;
+ } else {
+ this.isMovingLeftEdge_ = false;
+ ir.leftSelected = false;
+ ir.rightSelected = true;
+ }
+ },
+
+ mouseUp_() {
+ const dt = this.viewport_.currentDisplayTransform;
+ const ir = this.viewport_.interestRange;
+
+ ir.leftSelected = false;
+ ir.rightSelected = false;
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const minWidthValue = dt.xViewVectorToWorld(2 * pixelRatio);
+ if (ir.range < minWidthValue) {
+ ir.reset();
+ }
+ },
+
+ getWorldXFromEvent_(e) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ const canvas = this.viewport_.modelTrackContainer.canvas;
+ const worldOffset = canvas.getBoundingClientRect().left;
+ const viewX = (e.clientX - worldOffset) * pixelRatio;
+ return this.viewport_.currentDisplayTransform.xViewToWorld(viewX);
+ },
+
+
+ /**
+ * Get the closest position of an event within a vertical range of the mouse
+ * position if possible, otherwise use the position of the mouse pointer.
+ * @param {MouseEvent} e Mouse event with the current mouse coordinates.
+ * @return {
+ * {Number} x, The x coordinate in world space.
+ * {Number} y, The y coordinate in world space.
+ * {Number} height, The height of the event.
+ * {boolean} snapped Whether the coordinates are from a snapped event or
+ * the mouse position.
+ * }
+ */
+ getSnappedToEventPosition_(e) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ const EVENT_SNAP_RANGE = 16 * pixelRatio;
+
+ const modelTrackContainer = this.viewport_.modelTrackContainer;
+ const modelTrackContainerRect =
+ modelTrackContainer.getBoundingClientRect();
+
+ const viewport = this.viewport_;
+ const dt = viewport.currentDisplayTransform;
+ const worldMaxDist = dt.xViewVectorToWorld(EVENT_SNAP_RANGE);
+
+ const worldX = this.getWorldXFromEvent_(e);
+ const mouseY = e.clientY;
+
+ const selection = new tr.model.EventSet();
+
+ // Look at the track under mouse position first for better performance.
+ modelTrackContainer.addClosestEventToSelection(
+ worldX, worldMaxDist, mouseY, mouseY, selection);
+
+ // Look at all tracks visible on screen.
+ if (!selection.length) {
+ modelTrackContainer.addClosestEventToSelection(
+ worldX, worldMaxDist,
+ modelTrackContainerRect.top, modelTrackContainerRect.bottom,
+ selection);
+ }
+
+ let minDistX = worldMaxDist;
+ let minDistY = Infinity;
+ const pixWidth = dt.xViewVectorToWorld(1);
+
+ // Create result object with the mouse coordinates.
+ const result = {
+ x: worldX,
+ y: mouseY - modelTrackContainerRect.top,
+ height: 0,
+ snapped: false
+ };
+
+ const eventBounds = new tr.b.math.Range();
+ for (const event of selection) {
+ const track = viewport.trackForEvent(event);
+ const trackRect = track.getBoundingClientRect();
+
+ eventBounds.reset();
+ event.addBoundsToRange(eventBounds);
+ let eventX;
+ if (Math.abs(eventBounds.min - worldX) <
+ Math.abs(eventBounds.max - worldX)) {
+ eventX = eventBounds.min;
+ } else {
+ eventX = eventBounds.max;
+ }
+
+ const distX = eventX - worldX;
+
+ const eventY = trackRect.top;
+ const eventHeight = trackRect.height;
+ const distY = Math.abs(eventY + eventHeight / 2 - mouseY);
+
+ // Prefer events with a closer y position if their x difference is below
+ // the width of a pixel.
+ if ((distX <= minDistX || Math.abs(distX - minDistX) < pixWidth) &&
+ distY < minDistY) {
+ minDistX = distX;
+ minDistY = distY;
+
+ // Retrieve the event position from the hit.
+ result.x = eventX;
+ result.y = eventY +
+ modelTrackContainer.scrollTop - modelTrackContainerRect.top;
+ result.height = eventHeight;
+ result.snapped = true;
+ }
+ }
+
+ return result;
+ }
+ };
+
+ return {
+ TimingTool,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/timing_tool_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/timing_tool_test.html
new file mode 100644
index 00000000000..c07319d3e97
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/timing_tool_test.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/timing_tool.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function create100PxWideViewportInto10WideWorld() {
+ const vp = new tr.ui.TimelineViewport(document.createElement('div'));
+ const tempDisplayTransform = new tr.ui.TimelineDisplayTransform();
+ tempDisplayTransform.xSetWorldBounds(0, 10, 100);
+ vp.setDisplayTransformImmediately(tempDisplayTransform);
+
+ assert.strictEqual(vp.currentDisplayTransform.xViewToWorld(0), 0);
+ assert.strictEqual(vp.currentDisplayTransform.xViewToWorld(100), 10);
+
+ return vp;
+ }
+
+ test('dragLeftInterestRegion', function() {
+ const vp = create100PxWideViewportInto10WideWorld();
+ vp.interestRange.min = 1;
+ vp.interestRange.max = 9;
+ const tool = new tr.ui.b.TimingTool(vp);
+
+ tool.mouseDownAt_(1.1, 0);
+ assert.isTrue(vp.interestRange.leftSelected);
+ tool.mouseMoveAt_(1.5, 0, true);
+ assert.strictEqual(vp.interestRange.min, 1.5);
+ tool.mouseUp_();
+ assert.strictEqual(vp.interestRange.min, 1.5);
+ assert.isFalse(vp.interestRange.leftSelected);
+ });
+
+ test('dragRightInterestRegion', function() {
+ const vp = create100PxWideViewportInto10WideWorld();
+ vp.interestRange.min = 1;
+ vp.interestRange.max = 9;
+ const tool = new tr.ui.b.TimingTool(vp);
+
+ tool.mouseDownAt_(9.1, 0);
+ assert.isTrue(vp.interestRange.rightSelected);
+ tool.mouseMoveAt_(8, 0, true);
+ assert.strictEqual(vp.interestRange.max, 8);
+ tool.mouseUp_();
+ assert.strictEqual(vp.interestRange.max, 8);
+ assert.isFalse(vp.interestRange.leftSelected);
+ });
+
+ test('dragInNewSpace', function() {
+ const vp = create100PxWideViewportInto10WideWorld();
+ vp.interestRange.min = 1;
+ vp.interestRange.max = 9;
+ const tool = new tr.ui.b.TimingTool(vp);
+
+ tool.mouseDownAt_(5, 0);
+ assert.isTrue(vp.interestRange.rightSelected);
+ assert.strictEqual(vp.interestRange.min, 5);
+ assert.strictEqual(vp.interestRange.max, 5);
+ tool.mouseMoveAt_(4, 0, true);
+ assert.strictEqual(vp.interestRange.min, 4);
+ assert.strictEqual(vp.interestRange.max, 5);
+ assert.isTrue(vp.interestRange.leftSelected);
+ tool.mouseUp_();
+ assert.strictEqual(vp.interestRange.min, 4);
+ assert.isFalse(vp.interestRange.leftSelected);
+ assert.isFalse(vp.interestRange.rightSelected);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/toolbar_button.html b/chromium/third_party/catapult/tracing/tracing/ui/base/toolbar_button.html
new file mode 100644
index 00000000000..51108abd247
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/toolbar_button.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+</script>
+<dom-module id='tr-ui-b-toolbar-button'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ background-color: #f8f8f8;
+ border: 1px solid rgba(0, 0, 0, 0.5);
+ color: rgba(0,0,0,0.8);
+ justify-content: center;
+ align-self: stretch;
+ min-width: 23px;
+ }
+
+ :host(:hover) {
+ background-color: rgba(255, 255, 255, 1.0);
+ border-color: rgba(0, 0, 0, 0.8);
+ box-shadow: 0 0 .05em rgba(0, 0, 0, 0.4);
+ color: rgba(0, 0, 0, 1);
+ }
+
+ #aligner {
+ display: flex;
+ flex: 0 0 auto;
+ align-self: center;
+ }
+ </style>
+ <div id="aligner">
+ <slot></slot>
+ </div>
+ </template>
+</dom-module>
+<script>
+ 'use strict';
+ Polymer({ is: 'tr-ui-b-toolbar-button' });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/toolbar_button_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/toolbar_button_test.html
new file mode 100644
index 00000000000..d111fb637d8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/toolbar_button_test.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/toolbar_button.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('tallWithTextContent', function() {
+ const el = document.createElement('tr-ui-b-toolbar-button');
+ el.style.width = '100px';
+ el.style.height = '40px';
+
+ Polymer.dom(el).textContent = 'blahblah';
+
+ this.addHTMLOutput(el);
+ });
+
+ test('tallWithInnerSpan', function() {
+ const el = document.createElement('tr-ui-b-toolbar-button');
+ el.style.width = '100px';
+ el.style.height = '40px';
+
+ Polymer.dom(el).appendChild(tr.ui.b.createSpan({textContent: 'blahblah'}));
+
+ this.addHTMLOutput(el);
+ });
+
+ test('puny', function() {
+ const el = document.createElement('tr-ui-b-toolbar-button');
+ Polymer.dom(el).textContent = 'M';
+ this.addHTMLOutput(el);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/ui.html b/chromium/third_party/catapult/tracing/tracing/ui/base/ui.html
new file mode 100644
index 00000000000..a1e647e78b9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/ui.html
@@ -0,0 +1,172 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ /**
+ * Decorates elements as an instance of a class.
+ * @param {string|!Element} source The way to find the element(s) to decorate.
+ * If this is a string then {@code querySeletorAll} is used to find the
+ * elements to decorate.
+ * @param {!Function} constr The constructor to decorate with. The constr
+ * needs to have a {@code decorate} function.
+ */
+ function decorate(source, constr) {
+ let elements;
+ if (typeof source === 'string') {
+ elements = Polymer.dom(tr.doc).querySelectorAll(source);
+ } else {
+ elements = [source];
+ }
+
+ for (let i = 0, el; el = elements[i]; i++) {
+ if (!(el instanceof constr)) {
+ constr.decorate(el);
+ }
+ }
+ }
+
+ /**
+ * Defines a tracing UI component, a function that can be called to construct
+ * the component.
+ *
+ * tr class:
+ * const List = tr.ui.b.define('list');
+ * List.prototype = {
+ * __proto__: HTMLUListElement.prototype,
+ * decorate: function() {
+ * ...
+ * },
+ * ...
+ * };
+ *
+ * Derived class:
+ * const CustomList = tr.ui.b.define('custom-list', List);
+ * CustomList.prototype = {
+ * __proto__: List.prototype,
+ * decorate: function() {
+ * ...
+ * },
+ * ...
+ * };
+ *
+ * @param {string} className The className of the newly created subtype. If
+ * subclassing by passing in opt_parentConstructor, this is used for
+ * debugging. If not subclassing, then it is the tag name that will be
+ * created by the component.
+
+ * @param {function=} opt_parentConstructor The parent class for this new
+ * element, if subclassing is desired. If provided, the parent class must
+ * be also a function created by tr.ui.b.define.
+ *
+ * @param {string=} opt_tagNS The namespace in which to create the base
+ * element. Has no meaning when opt_parentConstructor is passed and must
+ * either be undefined or the same namespace as the parent class.
+ *
+ * @return {function(Object=):Element} The newly created component
+ * constructor.
+ */
+ function define(className, opt_parentConstructor, opt_tagNS) {
+ if (typeof className === 'function') {
+ throw new Error('Passing functions as className is deprecated. Please ' +
+ 'use (className, opt_parentConstructor) to subclass');
+ }
+
+ className = className.toLowerCase();
+ if (opt_parentConstructor && !opt_parentConstructor.tagName) {
+ throw new Error('opt_parentConstructor was not ' +
+ 'created by tr.ui.b.define');
+ }
+
+ // Walk up the parent constructors until we can find the type of tag
+ // to create.
+ let tagName = className;
+ let tagNS = undefined;
+ if (opt_parentConstructor) {
+ if (opt_tagNS) {
+ throw new Error('Must not specify tagNS if parentConstructor is given');
+ }
+ let parent = opt_parentConstructor;
+ while (parent && parent.tagName) {
+ tagName = parent.tagName;
+ tagNS = parent.tagNS;
+ parent = parent.parentConstructor;
+ }
+ } else {
+ tagNS = opt_tagNS;
+ }
+
+ /**
+ * Creates a new UI element constructor.
+ * Arguments passed to the constuctor are provided to the decorate method.
+ * You will need to call the parent elements decorate method from within
+ * your decorate method and pass any required parameters.
+ * @constructor
+ */
+ function f() {
+ if (opt_parentConstructor &&
+ f.prototype.__proto__ !== opt_parentConstructor.prototype) {
+ throw new Error(
+ className + ' prototye\'s __proto__ field is messed up. ' +
+ 'It MUST be the prototype of ' + opt_parentConstructor.tagName);
+ }
+
+ let el;
+ if (tagNS === undefined) {
+ el = tr.doc.createElement(tagName);
+ } else {
+ el = tr.doc.createElementNS(tagNS, tagName);
+ }
+ f.decorate.call(this, el, arguments);
+ return el;
+ }
+
+ /**
+ * Decorates an element as a UI element class.
+ * @param {!Element} el The element to decorate.
+ */
+ f.decorate = function(el) {
+ el.__proto__ = f.prototype;
+ el.decorate.apply(el, arguments[1]);
+ el.constructor = f;
+ };
+
+ f.className = className;
+ f.tagName = tagName;
+ f.tagNS = tagNS;
+ f.parentConstructor = (opt_parentConstructor ? opt_parentConstructor :
+ undefined);
+ f.toString = function() {
+ if (!f.parentConstructor) {
+ return f.tagName;
+ }
+ return f.parentConstructor.toString() + '::' + f.className;
+ };
+
+ return f;
+ }
+
+ function elementIsChildOf(el, potentialParent) {
+ if (el === potentialParent) return false;
+
+ let cur = el;
+ while (Polymer.dom(cur).parentNode) {
+ if (cur === potentialParent) return true;
+ cur = Polymer.dom(cur).parentNode;
+ }
+ return false;
+ }
+
+ return {
+ decorate,
+ define,
+ elementIsChildOf,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/ui_state.html b/chromium/third_party/catapult/tracing/tracing/ui/base/ui_state.html
new file mode 100644
index 00000000000..c87041eeb45
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/ui_state.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/location.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const Location = tr.model.Location;
+
+ /**
+ * UIState is a class that represents the current state of the timeline by
+ * the Location of the point of interest and the current scaleX of the
+ * timeline.
+ *
+ * @constructor
+ */
+ function UIState(location, scaleX) {
+ this.location_ = location;
+ this.scaleX_ = scaleX;
+ }
+
+ /**
+ * Accepts a UIState string in the format of (timestamp)@(stableID)x(scaleX)
+ * Returns undefined if string is not in this format, or throws an Error if
+ * variables in a syntactically-correct stateString does not produce a valid
+ * UIState. Otherwise returns a constructed UIState instance.
+ */
+ UIState.fromUserFriendlyString = function(model, viewport, stateString) {
+ const navByFinderPattern = /^(-?\d+(\.\d+)?)@(.+)x(\d+(\.\d+)?)$/g;
+ const match = navByFinderPattern.exec(stateString);
+ if (!match) return;
+
+ const timestamp = parseFloat(match[1]);
+ const stableId = match[3];
+ const scaleX = parseFloat(match[4]);
+
+ if (scaleX <= 0) {
+ throw new Error('Invalid ScaleX value in UI State string.');
+ }
+
+ if (!viewport.containerToTrackMap.getTrackByStableId(stableId)) {
+ throw new Error('Invalid StableID given in UI State String.');
+ }
+
+ const loc = tr.model.Location.fromStableIdAndTimestamp(
+ viewport, stableId, timestamp);
+ return new UIState(loc, scaleX);
+ };
+
+ UIState.prototype = {
+
+ get location() {
+ return this.location_;
+ },
+
+ get scaleX() {
+ return this.scaleX_;
+ },
+
+ toUserFriendlyString(viewport) {
+ const timestamp = this.location_.xWorld;
+ const stableId =
+ this.location_.getContainingTrack(viewport).eventContainer.stableId;
+ const scaleX = this.scaleX_;
+ return timestamp.toFixed(5) + '@' + stableId + 'x' + scaleX.toFixed(5);
+ },
+
+ toDict() {
+ return {
+ location: this.location_.toDict(),
+ scaleX: this.scaleX_
+ };
+ }
+ };
+
+ return {
+ UIState,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/ui_state_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/ui_state_test.html
new file mode 100644
index 00000000000..de9c6ba6090
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/ui_state_test.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/base/ui_state.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const UIState = tr.ui.b.UIState;
+
+ function FakeModel() {
+ this.processes = { 1: { threads: { 2: { stableId: '1.2' } } } };
+ }
+
+ // FakeTrack needs to be an instance of tr.ui.tracks.Track because a
+ // location is constructed in terms of Track instances.
+ function FakeTrack() { }
+ FakeTrack.prototype = {
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ get eventContainer() {
+ return { stableId: '1.2' };
+ },
+
+ getBoundingClientRect() {
+ return { top: 5, height: 2 };
+ },
+
+ get parentElement() {
+ return null;
+ }
+ };
+
+ function FakeViewPort() {
+ this.containerToTrackMap = {
+ // "1.2" is the only valid stableId this test function accepts.
+ getTrackByStableId(stableId) {
+ if (stableId === '1.2') {
+ return new FakeTrack;
+ }
+ return undefined;
+ }
+ };
+ }
+
+ test('invalidStableId', function() {
+ const model = new FakeModel;
+ const vp = new FakeViewPort;
+ assert.throws(function() {
+ UIState.fromUserFriendlyString(model, vp, '15@1.3x6');
+ });
+ assert.throws(function() {
+ UIState.fromUserFriendlyString(model, vp, '15@2.2x6');
+ });
+ assert.throws(function() {
+ UIState.fromUserFriendlyString(model, vp, '505@1.x5');
+ });
+ });
+
+ test('invalidScaleX', function() {
+ const model = new FakeModel;
+ const vp = new FakeViewPort;
+ assert.isUndefined(UIState.fromUserFriendlyString(model, vp, '1@1.2x-1'));
+ assert.throws(function() {
+ UIState.fromUserFriendlyString(model, vp, '1@1.2x0');
+ });
+ });
+
+ test('invalidSyntax', function() {
+ const model = new FakeModel;
+ const vp = new FakeViewPort;
+ assert.isUndefined(UIState.fromUserFriendlyString(model, vp, '5'));
+ assert.isUndefined(UIState.fromUserFriendlyString(model, vp, '5@x5'));
+ assert.isUndefined(UIState.fromUserFriendlyString(model, vp, 'ab@1.2x5'));
+ });
+
+ test('validString', function() {
+ const model = new FakeModel;
+ const vp = new FakeViewPort;
+ const str = '-50125.51231@1.2x1.12345';
+ const uiState = UIState.fromUserFriendlyString(model, vp, str);
+
+ assert.isDefined(uiState);
+ assert.strictEqual(uiState.location.xWorld, -50125.51231);
+ assert.strictEqual(
+ uiState.location.getContainingTrack(vp).eventContainer.stableId,
+ '1.2');
+ assert.strictEqual(uiState.scaleX, 1.12345);
+
+ assert.strictEqual(uiState.toUserFriendlyString(vp), str);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/ui_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/ui_test.html
new file mode 100644
index 00000000000..486c1019c62
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/ui_test.html
@@ -0,0 +1,246 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TestElement = tr.ui.b.define('div');
+ TestElement.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ if (!this.decorateCallCount) {
+ this.decorateCallCount = 0;
+ }
+ this.decorateCallCount++;
+ }
+ };
+
+ const Base = tr.ui.b.define('div');
+ Base.prototype = {
+ __proto__: HTMLDivElement.prototype,
+ decorate() {
+ this.decoratedAsBase = true;
+ },
+ set baseProperty(v) {
+ this.basePropertySet = v;
+ }
+ };
+
+ test('decorateOnceViaNew', function() {
+ const testElement = new TestElement();
+ assert.strictEqual(testElement.decorateCallCount, 1);
+ });
+
+ test('decorateOnceDirectly', function() {
+ const testElement = document.createElement('div');
+ tr.ui.b.decorate(testElement, TestElement);
+ assert.strictEqual(testElement.decorateCallCount, 1);
+ });
+
+ test('componentToString', function() {
+ assert.strictEqual(Base.toString(), 'div');
+
+ const Sub = tr.ui.b.define('Sub', Base);
+ assert.strictEqual(Sub.toString(), 'div::sub');
+
+ const SubSub = tr.ui.b.define('Marine', Sub);
+ assert.strictEqual(SubSub.toString(), 'div::sub::marine');
+ });
+
+ test('basicDefines', function() {
+ const baseInstance = new Base();
+ assert.instanceOf(baseInstance, Base);
+ assert.isTrue(baseInstance.decoratedAsBase);
+
+ assert.strictEqual(baseInstance.constructor, Base);
+ assert.strictEqual(baseInstance.constructor.toString(), 'div');
+
+ baseInstance.basePropertySet = 7;
+ assert.strictEqual(baseInstance.basePropertySet, 7);
+ });
+
+ test('subclassing', function() {
+ const Sub = tr.ui.b.define('sub', Base);
+ Sub.prototype = {
+ __proto__: Base.prototype,
+ decorate() {
+ this.decoratedAsSub = true;
+ }
+ };
+
+ const subInstance = new Sub();
+ assert.instanceOf(subInstance, Sub);
+ assert.isTrue(subInstance.decoratedAsSub);
+
+ assert.instanceOf(subInstance, Base);
+ assert.isUndefined(subInstance.decoratedAsBase);
+
+ assert.strictEqual(subInstance.constructor, Sub);
+ assert.strictEqual(subInstance.constructor.toString(), 'div::sub');
+
+ subInstance.baseProperty = true;
+ assert.isTrue(subInstance.basePropertySet);
+ });
+
+ const NoArgs = tr.ui.b.define('div');
+ NoArgs.prototype = {
+ __proto__: HTMLDivElement.prototype,
+ decorate() {
+ this.noArgsDecorated_ = true;
+ },
+ get noArgsDecorated() {
+ return this.noArgsDecorated_;
+ }
+ };
+
+ const Args = tr.ui.b.define('args', NoArgs);
+ Args.prototype = {
+ __proto__: NoArgs.prototype,
+ decorate(first) {
+ this.first_ = first;
+ this.argsDecorated_ = true;
+ },
+ get first() {
+ return this.first_;
+ },
+ get argsDecorated() {
+ return this.argsDecorated_;
+ }
+ };
+
+ const ArgsChild = tr.ui.b.define('args-child', Args);
+ ArgsChild.prototype = {
+ __proto__: Args.prototype,
+ decorate(_, second) {
+ this.second_ = second;
+ this.argsChildDecorated_ = true;
+ },
+ get second() {
+ return this.second_;
+ },
+ get decorated() {
+ return this.decorated_;
+ },
+ get argsChildDecorated() {
+ return this.argsChildDecorated_ = true;
+ }
+ };
+
+ const ArgsDecoratingChild = tr.ui.b.define('args-decorating-child', Args);
+ ArgsDecoratingChild.prototype = {
+ __proto__: Args.prototype,
+ decorate(first, second) {
+ Args.prototype.decorate.call(this, first);
+ this.second_ = second;
+ this.argsDecoratingChildDecorated_ = true;
+ },
+ get second() {
+ return this.second_;
+ },
+ get decorated() {
+ return this.decorated_;
+ },
+ get argsDecoratingChildDecorated() {
+ return this.argsChildDecorated_ = true;
+ }
+ };
+
+ test('decorate_noArguments', function() {
+ let noArgs;
+ assert.doesNotThrow(function() {
+ noArgs = new NoArgs();
+ });
+ assert.isTrue(noArgs.noArgsDecorated);
+ });
+
+ test('decorate_arguments', function() {
+ const args = new Args('this is first');
+ assert.strictEqual(args.first, 'this is first');
+ assert.isTrue(args.argsDecorated);
+ assert.isUndefined(args.noArgsDecorated);
+ });
+
+ test('decorate_subclassArguments', function() {
+ const argsChild = new ArgsChild('this is first', 'and second');
+ assert.isUndefined(argsChild.first);
+ assert.strictEqual(argsChild.second, 'and second');
+
+ assert.isTrue(argsChild.argsChildDecorated);
+ assert.isUndefined(argsChild.argsDecorated);
+ assert.isUndefined(argsChild.noArgsDecorated);
+ });
+
+ test('decorate_subClassCallsParentDecorate', function() {
+ const argsDecoratingChild = new ArgsDecoratingChild(
+ 'this is first', 'and second');
+ assert.strictEqual(argsDecoratingChild.first, 'this is first');
+ assert.strictEqual(argsDecoratingChild.second, 'and second');
+ assert.isTrue(argsDecoratingChild.argsDecoratingChildDecorated);
+ assert.isTrue(argsDecoratingChild.argsDecorated);
+ assert.isUndefined(argsDecoratingChild.noArgsDecorated);
+ });
+
+ test('defineWithNamespace', function() {
+ const svgNS = 'http://www.w3.org/2000/svg';
+ const cls = tr.ui.b.define('svg', undefined, svgNS);
+ cls.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ Polymer.dom(this).setAttribute('width', 200);
+ Polymer.dom(this).setAttribute('height', 200);
+ Polymer.dom(this).setAttribute('viewPort', '0 0 200 200');
+ const rectEl = document.createElementNS(svgNS, 'rect');
+ Polymer.dom(rectEl).setAttribute('x', 10);
+ Polymer.dom(rectEl).setAttribute('y', 10);
+ Polymer.dom(rectEl).setAttribute('width', 180);
+ Polymer.dom(rectEl).setAttribute('height', 180);
+ Polymer.dom(this).appendChild(rectEl);
+ }
+ };
+ const el = new cls();
+ assert.strictEqual(el.tagName, 'svg');
+ assert.strictEqual(el.namespaceURI, svgNS);
+ this.addHTMLOutput(el);
+ });
+
+ test('defineSubclassWithNamespace', function() {
+ const svgNS = 'http://www.w3.org/2000/svg';
+ const cls = tr.ui.b.define('svg', undefined, svgNS);
+ cls.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ Polymer.dom(this).setAttribute('width', 200);
+ Polymer.dom(this).setAttribute('height', 200);
+ Polymer.dom(this).setAttribute('viewPort', '0 0 200 200');
+ const rectEl = document.createElementNS(svgNS, 'rect');
+ Polymer.dom(rectEl).setAttribute('x', 10);
+ Polymer.dom(rectEl).setAttribute('y', 10);
+ Polymer.dom(rectEl).setAttribute('width', 180);
+ Polymer.dom(rectEl).setAttribute('height', 180);
+ Polymer.dom(this).appendChild(rectEl);
+ }
+ };
+
+ const subCls = tr.ui.b.define('sub', cls);
+ subCls.prototype = {
+ __proto__: cls.prototype
+ };
+ assert.strictEqual(subCls.toString(), 'svg::sub');
+
+ const el = new subCls();
+ this.addHTMLOutput(el);
+ assert.strictEqual(el.tagName, 'svg');
+ assert.strictEqual(el.namespaceURI, svgNS);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/utils.html b/chromium/third_party/catapult/tracing/tracing/ui/base/utils.html
new file mode 100644
index 00000000000..cca1003cc06
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/utils.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ function instantiateTemplate(selector, doc) {
+ doc = doc || document;
+ const el = Polymer.dom(doc).querySelector(selector);
+ if (!el) {
+ throw new Error('Element not found: ' + selector);
+ }
+ return doc.importNode(el.content, true);
+ // return el.createInstance();
+ }
+
+ function windowRectForElement(element) {
+ const position = [element.offsetLeft, element.offsetTop];
+ const size = [element.offsetWidth, element.offsetHeight];
+ let node = element.offsetParent;
+ while (node) {
+ position[0] += node.offsetLeft;
+ position[1] += node.offsetTop;
+ node = node.offsetParent;
+ }
+ return tr.b.math.Rect.fromXYWH(position[0], position[1], size[0], size[1]);
+ }
+
+ function scrollIntoViewIfNeeded(el) {
+ const pr = el.parentElement.getBoundingClientRect();
+ const cr = el.getBoundingClientRect();
+ if (cr.top < pr.top) {
+ el.scrollIntoView(true);
+ } else if (cr.bottom > pr.bottom) {
+ el.scrollIntoView(false);
+ }
+ }
+
+ function extractUrlString(url) {
+ let extracted = url.replace(/url\((.*)\)/, '$1');
+
+ // In newer versions of chrome, the contents of url() will be quoted. Remove
+ // these quotes as well. If quotes are not present, match will fail and this
+ // becomes a no-op.
+ extracted = extracted.replace(/\"(.*)\"/, '$1');
+
+ return extracted;
+ }
+
+ function toThreeDigitLocaleString(value) {
+ return value.toLocaleString(
+ undefined, {minimumFractionDigits: 3, maximumFractionDigits: 3});
+ }
+
+ /**
+ * Returns true if |name| is the name of an unknown HTML element. Registered
+ * polymer elements are known, so this returns false. Typos of registered
+ * polymer element names are unknown, so this returns true for typos.
+ *
+ * @return {boolean}
+ */
+ function isUnknownElementName(name) {
+ return document.createElement(name) instanceof HTMLUnknownElement;
+ }
+
+ return {
+ isUnknownElementName,
+ toThreeDigitLocaleString,
+ instantiateTemplate,
+ windowRectForElement,
+ scrollIntoViewIfNeeded,
+ extractUrlString,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html b/chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html
new file mode 100644
index 00000000000..4ab76e1d221
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/base/utils_test.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<dom-module id='instantiate-template-polymer-element-test'>
+ <template></template>
+</dom-module>
+<script>
+'use strict';
+Polymer({
+ is: 'instantiate-template-polymer-element-test',
+ testProperty: 'Test'
+});
+</script>
+<template id="instantiate-template-polymer-test">
+ <instantiate-template-polymer-element-test>
+ </instantiate-template-polymer-element-test>
+</template>
+
+<template id="multiple-template-test">
+ <template>
+ <instantiate-template-polymer-element-test>
+ </instantiate-template-polymer-element-test>
+ <span test-attribute='TestAttribute'>Foo</span>
+ </template>
+ <instantiate-template-polymer-element-test>
+ </instantiate-template-polymer-element-test>
+</template>
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ test('instantiateTemplatePolymer', function() {
+ const e = tr.ui.b.instantiateTemplate(
+ '#instantiate-template-polymer-test',
+ THIS_DOC);
+ assert.strictEqual(e.children.length, 1);
+ assert.strictEqual(e.children[0].testProperty, 'Test');
+ });
+
+ test('instantiateTemplateMultipleTemplates', function() {
+ const outerElement = tr.ui.b.instantiateTemplate(
+ '#multiple-template-test',
+ THIS_DOC);
+ assert.strictEqual(outerElement.children.length, 2);
+ assert.strictEqual(outerElement.children[1].testProperty, 'Test');
+
+ // Make sure we can still instantiate inner templates, if we need them.
+ const innerElement = THIS_DOC.importNode(
+ outerElement.children[0].content, true);
+ assert.strictEqual(innerElement.children.length, 2);
+ assert.strictEqual(innerElement.children[0].testProperty, 'Test');
+ assert.strictEqual(
+ innerElement.children[1].getAttribute('test-attribute'),
+ 'TestAttribute');
+ assert.strictEqual(
+ Polymer.dom(innerElement.children[1]).textContent, 'Foo');
+ });
+
+ test('extractUrlStringAcceptsBothVersions', function() {
+ const oldStyleUrl = 'url(content)';
+ const newStyleUrl = 'url("content")';
+ const expectedResult = 'content';
+
+ assert.strictEqual(tr.ui.b.extractUrlString(oldStyleUrl), expectedResult);
+ assert.strictEqual(tr.ui.b.extractUrlString(newStyleUrl), expectedResult);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/brushing_state.html b/chromium/third_party/catapult/tracing/tracing/ui/brushing_state.html
new file mode 100644
index 00000000000..f88e7a9bca3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/brushing_state.html
@@ -0,0 +1,280 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.b', function() {
+ const EventSet = tr.model.EventSet;
+ const SelectionState = tr.model.SelectionState;
+
+ function BrushingState() {
+ this.guid_ = tr.b.GUID.allocateSimple();
+ this.selection_ = new EventSet();
+ this.findMatches_ = new EventSet();
+ this.analysisViewRelatedEvents_ = new EventSet();
+ this.analysisLinkHoveredEvents_ = new EventSet();
+ this.appliedToModel_ = undefined;
+ this.viewSpecificBrushingStates_ = {};
+ }
+ BrushingState.prototype = {
+ get guid() {
+ return this.guid_;
+ },
+
+ clone() {
+ const that = new BrushingState();
+ that.selection_ = this.selection_;
+ that.findMatches_ = this.findMatches_;
+ that.analysisViewRelatedEvents_ = this.analysisViewRelatedEvents_;
+ that.analysisLinkHoveredEvents_ = this.analysisLinkHoveredEvents_;
+ that.viewSpecificBrushingStates_ = this.viewSpecificBrushingStates_;
+
+ return that;
+ },
+
+ equals(that) {
+ if (!this.selection_.equals(that.selection_)) {
+ return false;
+ }
+ if (!this.findMatches_.equals(that.findMatches_)) {
+ return false;
+ }
+ if (!this.analysisViewRelatedEvents_.equals(
+ that.analysisViewRelatedEvents_)) {
+ return false;
+ }
+ if (!this.analysisLinkHoveredEvents_.equals(
+ that.analysisLinkHoveredEvents_)) {
+ return false;
+ }
+ // We currently do not take the view-specific brushing states into
+ // account. If we did, every change of the view-specific brushing state
+ // of any view would cause a redraw of the whole UI (see the
+ // BrushingStateController.currentBrushingState setter).
+ return true;
+ },
+
+ get selectionOfInterest() {
+ if (this.selection_.length) {
+ return this.selection_;
+ }
+
+ if (this.highlight_.length) {
+ return this.highlight_;
+ }
+
+ if (this.analysisViewRelatedEvents_.length) {
+ return this.analysisViewRelatedEvents_;
+ }
+
+ if (this.analysisLinkHoveredEvents_.length) {
+ return this.analysisLinkHoveredEvents_;
+ }
+
+ return this.selection_;
+ },
+
+ get selection() {
+ return this.selection_;
+ },
+
+ set selection(selection) {
+ if (this.appliedToModel_) {
+ throw new Error('Cannot mutate this state right now');
+ }
+ if (selection === undefined) {
+ selection = new EventSet();
+ }
+ this.selection_ = selection;
+ },
+
+ get findMatches() {
+ return this.findMatches_;
+ },
+
+ set findMatches(findMatches) {
+ if (this.appliedToModel_) {
+ throw new Error('Cannot mutate this state right now');
+ }
+ if (findMatches === undefined) {
+ findMatches = new EventSet();
+ }
+ this.findMatches_ = findMatches;
+ },
+
+ get analysisViewRelatedEvents() {
+ return this.analysisViewRelatedEvents_;
+ },
+
+ set analysisViewRelatedEvents(analysisViewRelatedEvents) {
+ if (this.appliedToModel_) {
+ throw new Error('Cannot mutate this state right now');
+ }
+ if (!(analysisViewRelatedEvents instanceof EventSet)) {
+ analysisViewRelatedEvents = new EventSet();
+ }
+ this.analysisViewRelatedEvents_ = analysisViewRelatedEvents;
+ },
+
+ get analysisLinkHoveredEvents() {
+ return this.analysisLinkHoveredEvents_;
+ },
+
+ set analysisLinkHoveredEvents(analysisLinkHoveredEvents) {
+ if (this.appliedToModel_) {
+ throw new Error('Cannot mutate this state right now');
+ }
+ if (!(analysisLinkHoveredEvents instanceof EventSet)) {
+ analysisLinkHoveredEvents = new EventSet();
+ }
+ this.analysisLinkHoveredEvents_ = analysisLinkHoveredEvents;
+ },
+
+ get isAppliedToModel() {
+ return this.appliedToModel_ !== undefined;
+ },
+
+ get viewSpecificBrushingStates() {
+ return this.viewSpecificBrushingStates_;
+ },
+
+ set viewSpecificBrushingStates(viewSpecificBrushingStates) {
+ this.viewSpecificBrushingStates_ = viewSpecificBrushingStates;
+ },
+
+ get dimmedEvents_() {
+ const dimmedEvents = new EventSet();
+ dimmedEvents.addEventSet(this.findMatches);
+ dimmedEvents.addEventSet(this.analysisViewRelatedEvents_);
+ return dimmedEvents;
+ },
+
+ get brightenedEvents_() {
+ const brightenedEvents = new EventSet();
+ brightenedEvents.addEventSet(this.selection_);
+ brightenedEvents.addEventSet(this.analysisLinkHoveredEvents_);
+ return brightenedEvents;
+ },
+
+ /**
+ * This function sets the SelectionStates according to these rules:
+ *
+ * - Events in ONE of findMatches or analysisViewRelatedEvents
+ * are set to SelectionState.BRIGHTENED0.
+ * - Events in BOTH of findMatches and analysisViewRelatedEvents
+ * are set to SelectionState.BRIGHTENED1.
+ * - Events in ONE of selection or analysisLinkHoveredEvents
+ * are set to SelectionState.DIMMED1.
+ * - Events in BOTH selection and analysisLinkHoveredEvents
+ * are set to SelectionState.DIMMED2.
+ * - Events not in any of the above are set to SelectionState.NONE
+ * if there are no events in selection or analysisLinkHoveredEvents
+ * (i.e. model is "default bright") or SelectionState.DIMMED0 (i.e.
+ * model is "default dimmed").
+ *
+ * It is up to the caller to assure that all of the SelectionStates
+ * are the same before calling this function. Normally,
+ * this is done by calling unapplyFromModelSelectionState on the
+ * old brushing state first.
+ */
+ applyToEventSelectionStates(model) {
+ this.appliedToModel_ = model;
+
+ const dimmedEvents = this.dimmedEvents_;
+
+ // It's possible for this to get called with an undefined model pointer.
+ // If so, skip adjusting the defaults.
+ if (model) {
+ const newDefaultState = (
+ dimmedEvents.length ? SelectionState.DIMMED0 : SelectionState.NONE);
+
+ // Since all the states are the same, we can get the current default
+ // state by looking at the first element.
+ const currentDefaultState = tr.b.getFirstElement(
+ model.getDescendantEvents()).selectionState;
+
+ // If the default state was changed, then we have to iterate through
+ // and reset all the events to the new default state.
+ if (currentDefaultState !== newDefaultState) {
+ for (const e of model.getDescendantEvents()) {
+ e.selectionState = newDefaultState;
+ }
+ }
+ }
+
+ // Now we apply the other rules above.
+ let score;
+ for (const e of dimmedEvents) {
+ score = 0;
+ if (this.findMatches_.contains(e)) {
+ score++;
+ }
+ if (this.analysisViewRelatedEvents_.contains(e)) {
+ score++;
+ }
+ e.selectionState = SelectionState.getFromDimmingLevel(score);
+ }
+
+ for (const e of this.brightenedEvents_) {
+ score = 0;
+ if (this.selection_.contains(e)) {
+ score++;
+ }
+ if (this.analysisLinkHoveredEvents_.contains(e)) {
+ score++;
+ }
+ e.selectionState = SelectionState.getFromBrighteningLevel(score);
+ }
+ },
+
+ transferModelOwnershipToClone(that) {
+ if (!this.appliedToModel_) {
+ throw new Error('Not applied');
+ }
+ // Assumes this.equals(that).
+ that.appliedToModel_ = this.appliedToModel_;
+ this.appliedToModel_ = undefined;
+ },
+
+ /**
+ * Unapplies this brushing state from the model selection state.
+ * Resets all the SelectionStates to their default value (DIMMED0 or NONE)
+ * and returns the default selection states. The caller should store this
+ * value and pass it into applyFromModelSelectionStat when that is called.
+ */
+ unapplyFromEventSelectionStates() {
+ if (!this.appliedToModel_) {
+ throw new Error('Not applied');
+ }
+ const model = this.appliedToModel_;
+ this.appliedToModel_ = undefined;
+
+ const dimmedEvents = this.dimmedEvents_;
+ const defaultState = (
+ dimmedEvents.length ? SelectionState.DIMMED0 : SelectionState.NONE);
+
+ for (const e of this.brightenedEvents_) {
+ e.selectionState = defaultState;
+ }
+ for (const e of dimmedEvents) {
+ e.selectionState = defaultState;
+ }
+ return defaultState;
+ }
+ };
+
+ return {
+ BrushingState,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_controller.html b/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_controller.html
new file mode 100644
index 00000000000..6a547c339c3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_controller.html
@@ -0,0 +1,317 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/base/ui_state.html">
+<link rel="import" href="/tracing/ui/brushing_state.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.c', function() {
+ const BrushingState = tr.ui.b.BrushingState;
+ const EventSet = tr.model.EventSet;
+ const SelectionState = tr.model.SelectionState;
+ const Viewport = tr.ui.TimelineViewport;
+
+ function BrushingStateController(timelineView) {
+ tr.b.EventTarget.call(this);
+
+ this.timelineView_ = timelineView;
+ this.currentBrushingState_ = new BrushingState();
+
+ this.onPopState_ = this.onPopState_.bind(this);
+ this.historyEnabled_ = false;
+ this.selections_ = {};
+ }
+
+ BrushingStateController.prototype = {
+ __proto__: tr.b.EventTarget.prototype,
+
+ dispatchChangeEvent_() {
+ const e = new tr.b.Event('change', false, false);
+ this.dispatchEvent(e);
+ },
+
+ get model() {
+ if (!this.timelineView_) {
+ return undefined;
+ }
+ return this.timelineView_.model;
+ },
+
+ get trackView() {
+ if (!this.timelineView_) {
+ return undefined;
+ }
+ return this.timelineView_.trackView;
+ },
+
+ get viewport() {
+ if (!this.timelineView_) {
+ return undefined;
+ }
+ if (!this.timelineView_.trackView) {
+ return undefined;
+ }
+ return this.timelineView_.trackView.viewport;
+ },
+
+ /* History system */
+ get historyEnabled() {
+ return this.historyEnabled_;
+ },
+
+ set historyEnabled(historyEnabled) {
+ this.historyEnabled_ = !!historyEnabled;
+ if (historyEnabled) {
+ window.addEventListener('popstate', this.onPopState_);
+ } else {
+ window.removeEventListener('popstate', this.onPopState_);
+ }
+ },
+
+ modelWillChange() {
+ if (this.currentBrushingState_.isAppliedToModel) {
+ this.currentBrushingState_.unapplyFromEventSelectionStates();
+ }
+ },
+
+ modelDidChange() {
+ this.selections_ = {};
+
+ this.currentBrushingState_ = new BrushingState();
+ this.currentBrushingState_.applyToEventSelectionStates(this.model);
+
+ const e = new tr.b.Event('model-changed', false, false);
+ this.dispatchEvent(e);
+
+ this.dispatchChangeEvent_();
+ },
+
+ onUserInitiatedSelectionChange_() {
+ const selection = this.selection;
+ if (this.historyEnabled) {
+ // Save the selection so that when back button is pressed,
+ // it could be retrieved.
+ this.selections_[selection.guid] = selection;
+ const state = {
+ selection_guid: selection.guid
+ };
+
+ window.history.pushState(state, document.title);
+ }
+ },
+
+ onPopState_(e) {
+ if (e.state === null) return;
+
+ const selection = this.selections_[e.state.selection_guid];
+ if (selection) {
+ const newState = this.currentBrushingState_.clone();
+ newState.selection = selection;
+ this.currentBrushingState = newState;
+ }
+ e.stopPropagation();
+ },
+
+ get selection() {
+ return this.currentBrushingState_.selection;
+ },
+ get findMatches() {
+ return this.currentBrushingState_.findMatches;
+ },
+
+ get selectionOfInterest() {
+ return this.currentBrushingState_.selectionOfInterest;
+ },
+
+ get currentBrushingState() {
+ return this.currentBrushingState_;
+ },
+
+ set currentBrushingState(newBrushingState) {
+ if (newBrushingState.isAppliedToModel) {
+ throw new Error('Cannot apply this state, it is applied');
+ }
+
+ // This function uses value-equality on the states so that state can
+ // changed to a clone of itself without causing a change event, while
+ // still having the actual state object change to the new clone.
+ const hasValueChanged = !this.currentBrushingState_.equals(
+ newBrushingState);
+
+ if (newBrushingState !== this.currentBrushingState_ && !hasValueChanged) {
+ if (this.currentBrushingState_.isAppliedToModel) {
+ this.currentBrushingState_.transferModelOwnershipToClone(
+ newBrushingState);
+ }
+ this.currentBrushingState_ = newBrushingState;
+ return;
+ }
+
+ if (this.currentBrushingState_.isAppliedToModel) {
+ this.currentBrushingState_.unapplyFromEventSelectionStates();
+ }
+
+ this.currentBrushingState_ = newBrushingState;
+
+ this.currentBrushingState_.applyToEventSelectionStates(this.model);
+
+ this.dispatchChangeEvent_();
+ },
+
+ /**
+ * @param {Filter} filter The filter to use for finding matches.
+ * @param {Selection} selection The selection to add matches to.
+ * @return {Task} which performs the filtering.
+ */
+ addAllEventsMatchingFilterToSelectionAsTask(filter, selection) {
+ const timelineView = this.timelineView_.trackView;
+ if (!timelineView) {
+ return new tr.b.Task();
+ }
+ return timelineView.addAllEventsMatchingFilterToSelectionAsTask(
+ filter, selection);
+ },
+
+ findTextChangedTo(allPossibleMatches) {
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.findMatches = allPossibleMatches;
+ this.currentBrushingState = newBrushingState;
+ },
+
+ findFocusChangedTo(currentFocus) {
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.selection = currentFocus;
+ this.currentBrushingState = newBrushingState;
+
+ this.onUserInitiatedSelectionChange_();
+ },
+
+ findTextCleared() {
+ if (this.xNavStringMarker_ !== undefined) {
+ this.model.removeAnnotation(this.xNavStringMarker_);
+ this.xNavStringMarker_ = undefined;
+ }
+
+ if (this.guideLineAnnotation_ !== undefined) {
+ this.model.removeAnnotation(this.guideLineAnnotation_);
+ this.guideLineAnnotation_ = undefined;
+ }
+
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.selection = new EventSet();
+ newBrushingState.findMatches = new EventSet();
+ this.currentBrushingState = newBrushingState;
+
+ this.onUserInitiatedSelectionChange_();
+ },
+
+ uiStateFromString(string) {
+ return tr.ui.b.UIState.fromUserFriendlyString(
+ this.model, this.viewport, string);
+ },
+
+ navToPosition(uiState, showNavLine) {
+ this.trackView.navToPosition(uiState, showNavLine);
+ },
+
+ changeSelectionFromTimeline(selection) {
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.selection = selection;
+ newBrushingState.findMatches = new EventSet();
+ this.currentBrushingState = newBrushingState;
+
+ this.onUserInitiatedSelectionChange_();
+ },
+
+ showScriptControlSelection(selection) {
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.selection = selection;
+ newBrushingState.findMatches = new EventSet();
+ this.currentBrushingState = newBrushingState;
+ },
+
+ changeSelectionFromRequestSelectionChangeEvent(selection) {
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.selection = selection;
+ newBrushingState.findMatches = new EventSet();
+ this.currentBrushingState = newBrushingState;
+
+ this.onUserInitiatedSelectionChange_();
+ },
+
+ changeAnalysisViewRelatedEvents(eventSet) {
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.analysisViewRelatedEvents = eventSet;
+ this.currentBrushingState = newBrushingState;
+ },
+
+ changeAnalysisLinkHoveredEvents(eventSet) {
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.analysisLinkHoveredEvents = eventSet;
+ this.currentBrushingState = newBrushingState;
+ },
+
+ getViewSpecificBrushingState(viewId) {
+ return this.currentBrushingState.viewSpecificBrushingStates[viewId];
+ },
+
+ changeViewSpecificBrushingState(viewId, newState) {
+ const oldStates = this.currentBrushingState_.viewSpecificBrushingStates;
+ const newStates = {};
+ for (const id in oldStates) {
+ newStates[id] = oldStates[id];
+ }
+ if (newState === undefined) {
+ delete newStates[viewId];
+ } else {
+ newStates[viewId] = newState;
+ }
+
+ const newBrushingState = this.currentBrushingState_.clone();
+ newBrushingState.viewSpecificBrushingStates = newStates;
+ this.currentBrushingState = newBrushingState;
+ }
+ };
+
+ BrushingStateController.getControllerForElement = function(element) {
+ if (tr.isHeadless) {
+ throw new Error('Unsupported');
+ }
+ let currentElement = element;
+ while (currentElement) {
+ if (currentElement.brushingStateController) {
+ return currentElement.brushingStateController;
+ }
+
+ // Walk up the DOM.
+ if (currentElement.parentElement) {
+ currentElement = currentElement.parentElement;
+ continue;
+ }
+
+ // Possibly inside a shadow DOM.
+ let currentNode = currentElement;
+ while (Polymer.dom(currentNode).parentNode) {
+ currentNode = Polymer.dom(currentNode).parentNode;
+ }
+ currentElement = currentNode.host;
+ }
+ return undefined;
+ };
+
+ return {
+ BrushingStateController,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_controller_test.html b/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_controller_test.html
new file mode 100644
index 00000000000..b72aeccf16a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_controller_test.html
@@ -0,0 +1,204 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ const EventSet = tr.model.EventSet;
+ const SelectionState = tr.model.SelectionState;
+ const Task = tr.b.Task;
+
+ function newSimpleFakeTimelineView() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+
+ m.sA = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'a', start: 0, end: 5}));
+ m.sB = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'b', start: 10, end: 15}));
+ m.sC = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'c', start: 20, end: 20}));
+ });
+
+ // Fake timeline view. So fake its ... just wow.
+ const timelineView = {
+ model: m
+ };
+ return timelineView;
+ }
+
+ function doesCauseChangeToFire(brushingStateController, cb, opt_this) {
+ let didFire = false;
+ function didFireCb() {
+ didFire = true;
+ }
+ brushingStateController.addEventListener('change', didFireCb);
+ cb.call(opt_this);
+ brushingStateController.removeEventListener('change', didFireCb);
+ return didFire;
+ }
+
+ test('simpleStateChanges', function() {
+ const timelineView = newSimpleFakeTimelineView();
+ const brushingStateController =
+ new tr.c.BrushingStateController(timelineView);
+ const m = timelineView.model;
+
+ // Setting empty brushing state doesn't cause change event. This behavior
+ // is triggered when the user tries to search for something when no trace
+ // has been loaded yet in chrome://tracing.
+ const bs0 = new tr.ui.b.BrushingState();
+ assert.isFalse(doesCauseChangeToFire(
+ brushingStateController,
+ function() {
+ brushingStateController.currentBrushingState = bs0;
+ }));
+ assert.isFalse(bs0.isAppliedToModel);
+ assert.strictEqual(brushingStateController.currentBrushingState, bs0);
+
+ // Setting causes change.
+ const bs1 = new tr.ui.b.BrushingState();
+ bs1.selection = new EventSet([m.sA]);
+ assert.isTrue(doesCauseChangeToFire(
+ brushingStateController,
+ function() {
+ brushingStateController.currentBrushingState = bs1;
+ }));
+ assert.isTrue(bs1.isAppliedToModel);
+
+ // Setting value equivalent doesn't cause change event.
+ const bs2 = bs1.clone();
+ assert.isFalse(doesCauseChangeToFire(
+ brushingStateController,
+ function() {
+ brushingStateController.currentBrushingState = bs2;
+ }));
+ assert.strictEqual(brushingStateController.currentBrushingState, bs2);
+ assert.isTrue(
+ brushingStateController.currentBrushingState.isAppliedToModel);
+
+ // Setting to something different unapplies the old bs.
+ const bs3 = new tr.ui.b.BrushingState();
+ bs3.findMatches = new EventSet([m.sA, m.sB]);
+ brushingStateController.currentBrushingState = bs3;
+ assert.isTrue(bs3.isAppliedToModel);
+ assert.isFalse(bs2.isAppliedToModel);
+ });
+
+ test('modelCausesStateChange', function() {
+ const timelineView = newSimpleFakeTimelineView();
+ const brushingStateController =
+ new tr.c.BrushingStateController(timelineView);
+
+ const m1 = timelineView.model;
+
+ const bs1 = new tr.ui.b.BrushingState();
+ bs1.selection = new EventSet([m1.sA]);
+
+ // Change the model.
+ const m2 = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+
+ m.sA = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'a', start: 0, end: 5}));
+ });
+ assert.isTrue(doesCauseChangeToFire(
+ brushingStateController,
+ function() {
+ brushingStateController.modelWillChange();
+ timelineView.model = m2;
+ brushingStateController.modelDidChange();
+ }));
+ assert.strictEqual(
+ brushingStateController.currentBrushingState.selection.length, 0);
+ });
+
+ function addChildDiv(element) {
+ const child = element.ownerDocument.createElement('div');
+ Polymer.dom(element).appendChild(child);
+ return child;
+ }
+
+ function addShadowChildDiv(element) {
+ const shadowRoot = element.createShadowRoot();
+ return addChildDiv(shadowRoot);
+ }
+
+ if (!tr.isHeadless) {
+ test('getControllerForElement_none', function() {
+ const element = document.createElement('div');
+
+ assert.isUndefined(
+ tr.c.BrushingStateController.getControllerForElement(element));
+ });
+
+ test('getControllerForElement_self', function() {
+ const controller = new tr.c.BrushingStateController(undefined);
+ const element = document.createElement('div');
+ element.brushingStateController = controller;
+
+ assert.strictEqual(
+ tr.c.BrushingStateController.getControllerForElement(element),
+ controller);
+ });
+
+ test('getControllerForElement_ancestor', function() {
+ const controller = new tr.c.BrushingStateController(undefined);
+ const ancestor = document.createElement('div');
+ ancestor.brushingStateController = controller;
+
+ const element = addChildDiv(addChildDiv(addChildDiv(ancestor)));
+ assert.strictEqual(
+ tr.c.BrushingStateController.getControllerForElement(element),
+ controller);
+ });
+
+ test('getControllerForElement_host', function() {
+ const controller = new tr.c.BrushingStateController(undefined);
+ const host = document.createElement('div');
+ host.brushingStateController = controller;
+
+ const element = addShadowChildDiv(host);
+ assert.strictEqual(
+ tr.c.BrushingStateController.getControllerForElement(element),
+ controller);
+ });
+
+ test('getControllerForElement_hierarchy', function() {
+ const controller1 = new tr.c.BrushingStateController(undefined);
+ const root = document.createElement('div');
+ root.brushingStateController = controller1;
+
+ const controller2 = new tr.c.BrushingStateController(undefined);
+ const child = addChildDiv(root);
+ child.brushingStateController = controller2;
+
+ const controller3 = new tr.c.BrushingStateController(undefined);
+ const shadowChild = addShadowChildDiv(child);
+ shadowChild.brushingStateController = controller3;
+
+ const element = addChildDiv(addChildDiv(addShadowChildDiv(
+ addChildDiv(addChildDiv(addShadowChildDiv(
+ addChildDiv(shadowChild)))))));
+ assert.strictEqual(
+ tr.c.BrushingStateController.getControllerForElement(element),
+ controller3);
+ });
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_test.html b/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_test.html
new file mode 100644
index 00000000000..aa33b12d116
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/brushing_state_test.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ const EventSet = tr.model.EventSet;
+ const SelectionState = tr.model.SelectionState;
+
+ function newSimpleModel() {
+ return tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+
+ m.sA = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'a', start: 0, end: 5}));
+ m.sB = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'b', start: 10, end: 15}));
+ m.sC = m.t2.sliceGroup.pushSlice(
+ newSliceEx({title: 'c', start: 20, end: 20}));
+ });
+ }
+
+ test('brushingStateSimple', function() {
+ const m = newSimpleModel();
+
+ const bs = new tr.ui.b.BrushingState();
+ bs.selection = new EventSet([m.sA]);
+
+ bs.applyToEventSelectionStates(m);
+ assert.strictEqual(m.sA.selectionState, SelectionState.SELECTED);
+ bs.unapplyFromEventSelectionStates();
+ assert.strictEqual(m.sA.selectionState, SelectionState.NONE);
+ });
+
+
+ test('selectionAndAnalysisHover', function() {
+ const m = newSimpleModel();
+
+ const bs = new tr.ui.b.BrushingState();
+ bs.selection = new EventSet([m.sA]);
+ bs.analysisLinkHoveredEvents = new EventSet([m.sA, m.sB]);
+
+ bs.applyToEventSelectionStates(m);
+ assert.strictEqual(m.sA.selectionState, SelectionState.BRIGHTENED1);
+ assert.strictEqual(m.sB.selectionState, SelectionState.BRIGHTENED0);
+ bs.unapplyFromEventSelectionStates();
+ assert.strictEqual(m.sA.selectionState, SelectionState.NONE);
+ });
+
+ test('brushingStateWithFindMatches', function() {
+ const m = newSimpleModel();
+
+ const bs = new tr.ui.b.BrushingState();
+ bs.selection = new EventSet([m.sA]);
+ bs.findMatches = new EventSet([m.sA, m.sB]);
+
+ bs.applyToEventSelectionStates(m);
+ assert.strictEqual(m.sA.selectionState, SelectionState.BRIGHTENED0);
+ assert.strictEqual(m.sB.selectionState, SelectionState.DIMMED1);
+ assert.strictEqual(m.sC.selectionState, SelectionState.DIMMED0);
+ bs.unapplyFromEventSelectionStates();
+ assert.strictEqual(m.sA.selectionState, SelectionState.DIMMED0);
+ assert.strictEqual(m.sB.selectionState, SelectionState.DIMMED0);
+ assert.strictEqual(m.sC.selectionState, SelectionState.DIMMED0);
+ });
+
+ test('brushingTransfer', function() {
+ const m = newSimpleModel();
+
+ const bs = new tr.ui.b.BrushingState();
+ bs.selection = new EventSet([m.sA]);
+
+ const bs2 = bs.clone();
+
+ bs.applyToEventSelectionStates(m);
+ assert.strictEqual(m.sA.selectionState, SelectionState.SELECTED);
+ bs.transferModelOwnershipToClone(bs2);
+ assert.isFalse(bs.isAppliedToModel);
+ assert.isTrue(bs2.isAppliedToModel);
+
+ bs2.unapplyFromEventSelectionStates();
+ assert.strictEqual(m.sA.selectionState, SelectionState.NONE);
+ assert.strictEqual(m.sB.selectionState, SelectionState.NONE);
+ assert.strictEqual(m.sC.selectionState, SelectionState.NONE);
+ });
+
+ test('equality', function() {
+ const m = newSimpleModel();
+
+ const bs = new tr.ui.b.BrushingState();
+ bs.selection = new EventSet([m.sA]);
+ bs.findMatches = new EventSet([m.sB]);
+ bs.applyToEventSelectionStates = new EventSet([m.sC]);
+
+ // Clone equality, but with shared refs.
+ const bs2 = bs.clone();
+ assert.isTrue(bs.equals(bs2));
+
+ // Same value, different refs.
+ bs2.selection = new EventSet([m.sA]);
+ assert.isTrue(bs.equals(bs2));
+
+ // Different actual values.
+ bs2.selection = new EventSet([m.sB]);
+ assert.isFalse(bs.equals(bs2));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/about_tracing.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/about_tracing.html
new file mode 100644
index 00000000000..8e579d90921
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/about_tracing.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/base/base.html" data-suppress-import-order>
+
+<link rel="stylesheet" href="/tracing/ui/extras/about_tracing/common.css">
+<link rel="import" href="/tracing/ui/extras/about_tracing/profiling_view.html">
+<link rel="import" href="/tracing/ui/extras/full_config.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ window.profilingView = undefined; // Made global for debugging purposes only.
+
+ document.addEventListener('DOMContentLoaded', function() {
+ window.profilingView = new tr.ui.e.about_tracing.ProfilingView();
+ profilingView.timelineView.globalMode = true;
+ Polymer.dom(document.body).appendChild(profilingView);
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/common.css b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/common.css
new file mode 100644
index 00000000000..3db21b67ffa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/common.css
@@ -0,0 +1,25 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+html,
+body {
+ height: 100%;
+}
+
+body {
+ flex-direction: column;
+ display: flex;
+ margin: 0;
+ padding: 0;
+}
+
+body > x-profiling-view {
+ flex: 1 1 auto;
+ min-height: 0;
+}
+
+body > x-profiling-view > x-timeline-view:focus {
+ outline: 0
+}
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/devtools_stream.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/devtools_stream.html
new file mode 100644
index 00000000000..fa348a7b661
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/devtools_stream.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/base64.html">
+<script>
+
+'use strict';
+
+/**
+ * A devtools protocol stream object.
+ *
+ * This reads a stream of data over the remote debugging connection.
+ */
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ class DevtoolsStream {
+ constructor(connection, streamHandle) {
+ this.connection_ = connection;
+ this.streamHandle_ = streamHandle;
+ this.closed_ = false;
+ }
+
+ async read() {
+ if (this.closed_) {
+ throw new Error('stream is closed');
+ }
+
+ const pendingRequests = [];
+
+ const READ_REQUEST_BYTES = 32768;
+ const makeRequest = () => {
+ pendingRequests.push(this.connection_.req(
+ 'IO.read',
+ {
+ handle: this.streamHandle_,
+ size: READ_REQUEST_BYTES,
+ }));
+ };
+
+ const MAX_CONCURRENT_REQUESTS = 2;
+ for (let i = 0; i < MAX_CONCURRENT_REQUESTS; ++i) {
+ makeRequest();
+ }
+
+ const chunks = [];
+ let base64 = false;
+ while (true) {
+ const request = pendingRequests.shift();
+ const response = await request;
+
+ chunks.push(response.data);
+ if (response.base64Encoded) {
+ base64 = true;
+ }
+ if (response.eof) {
+ break;
+ }
+
+ makeRequest();
+ }
+
+ if (base64) {
+ let totalSize = 0;
+ for (const chunk of chunks) {
+ totalSize += tr.b.Base64.getDecodedBufferLength(chunk);
+ }
+ const buffer = new ArrayBuffer(totalSize);
+ let offset = 0;
+ for (const chunk of chunks) {
+ offset += tr.b.Base64.DecodeToTypedArray(
+ chunk,
+ new DataView(buffer, offset));
+ }
+ return buffer;
+ }
+
+ return chunks.join('');
+ }
+
+ close() {
+ this.closed_ = true;
+ return this.connection_.req('IO.close', { handle: this.streamHandle_ });
+ }
+
+ async readAndClose() {
+ const data = await this.read();
+ this.close();
+ return data;
+ }
+ }
+
+ return {
+ DevtoolsStream,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_connection.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_connection.html
new file mode 100644
index 00000000000..791f5e77705
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_connection.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<script>
+
+'use strict';
+
+/**
+ * Contains connection code that inspector's embedding framework calls on
+ * tracing, and that tracing can use to talk to inspector.
+ */
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ class InspectorConnection {
+ constructor(windowGlobal) {
+ if (!windowGlobal.DevToolsHost) {
+ throw new Error('Requires window.DevToolsHost');
+ }
+ this.devToolsHost_ = windowGlobal.DevToolsHost;
+ this.installDevToolsAPI_(windowGlobal);
+
+ this.nextRequestId_ = 1;
+ this.pendingRequestResolversId_ = {};
+
+ this.notificationListenersByMethodName_ = {};
+ }
+
+ req(method, params) {
+ const id = this.nextRequestId_++;
+ const msg = JSON.stringify({
+ id,
+ method,
+ params
+ });
+ const devtoolsMessageStr = JSON.stringify(
+ {id, 'method': 'dispatchProtocolMessage', 'params': [msg]});
+ this.devToolsHost_.sendMessageToEmbedder(devtoolsMessageStr);
+
+ return new Promise(function(resolve, reject) {
+ this.pendingRequestResolversId_[id] = {
+ resolve,
+ reject
+ };
+ }.bind(this));
+ }
+
+ setNotificationListener(method, listener) {
+ this.notificationListenersByMethodName_[method] = listener;
+ }
+
+ dispatchMessage_(payload) {
+ const isStringPayload = typeof payload === 'string';
+ // Special handling for Tracing.dataCollected because it is high
+ // bandwidth.
+ const isDataCollectedMessage = isStringPayload ?
+ payload.includes('"method": "Tracing.dataCollected"') :
+ payload.method === 'Tracing.dataCollected';
+ if (isDataCollectedMessage) {
+ const listener = this.notificationListenersByMethodName_[
+ 'Tracing.dataCollected'];
+ if (listener) {
+ // FIXME(loislo): trace viewer should be able to process
+ // raw message object because string based version a few times
+ // slower on the browser side.
+ // see https://codereview.chromium.org/784513002.
+ listener(isStringPayload ? payload : JSON.stringify(payload));
+ return;
+ }
+ }
+
+ const message = isStringPayload ? JSON.parse(payload) : payload;
+ if (message.id) {
+ const resolver = this.pendingRequestResolversId_[message.id];
+ if (resolver === undefined) {
+ return;
+ }
+ if (message.error) {
+ resolver.reject(message.error);
+ return;
+ }
+ resolver.resolve(message.result);
+ return;
+ }
+
+ if (message.method) {
+ const listener = this.notificationListenersByMethodName_[
+ message.method];
+ if (listener === undefined) return;
+ listener(message.params);
+ return;
+ }
+ }
+
+ installDevToolsAPI_(windowGlobal) {
+ // Interface used by inspector when it hands data to us from the backend.
+ windowGlobal.DevToolsAPI = {
+ setToolbarColors() { },
+ addExtensions() { },
+ setInspectedPageId() { },
+ dispatchMessage: this.dispatchMessage_.bind(this),
+ };
+
+ // Temporary until inspector backend switches to DevToolsAPI.
+ windowGlobal.InspectorFrontendAPI = windowGlobal.DevToolsAPI;
+ }
+ }
+
+ return {
+ InspectorConnection,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_tracing_controller_client.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_tracing_controller_client.html
new file mode 100644
index 00000000000..ac5afabae12
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_tracing_controller_client.html
@@ -0,0 +1,216 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/extras/about_tracing/devtools_stream.html">
+<link rel="import" href="/tracing/ui/extras/about_tracing/inspector_connection.html">
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/tracing_controller_client.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ function createResolvedPromise(data) {
+ const promise = new Promise(function(resolve, reject) {
+ if (data) {
+ resolve(data);
+ } else {
+ resolve();
+ }
+ });
+ return promise;
+ }
+
+ function appendTraceChunksTo(chunks, messageString) {
+ if (typeof messageString !== 'string') {
+ throw new Error('Invalid data');
+ }
+ const re = /"params":\s*\{\s*"value":\s*\[([^]+)\]\s*\}\s*\}/;
+ const m = re.exec(messageString);
+ if (!m) {
+ throw new Error('Malformed response');
+ }
+
+ if (chunks.length > 1) {
+ chunks.push(',');
+ }
+ chunks.push(m[1]);
+ }
+
+ /**
+ * Controls tracing using the inspector's FrontendAgentHost APIs.
+ */
+ class InspectorTracingControllerClient extends
+ tr.ui.e.about_tracing.TracingControllerClient {
+ constructor(connection) {
+ super();
+ this.recording_ = false;
+ this.bufferUsage_ = 0;
+ this.conn_ = connection;
+ this.currentTraceTextChunks_ = undefined;
+ }
+
+ beginMonitoring(monitoringOptions) {
+ throw new Error('Not implemented');
+ }
+
+ endMonitoring() {
+ throw new Error('Not implemented');
+ }
+
+ captureMonitoring() {
+ throw new Error('Not implemented');
+ }
+
+ getMonitoringStatus() {
+ return createResolvedPromise({
+ isMonitoring: false,
+ categoryFilter: '',
+ useSystemTracing: false,
+ useContinuousTracing: false,
+ useSampling: false
+ });
+ }
+
+ getCategories() {
+ const res = this.conn_.req('Tracing.getCategories', {});
+ return res.then(function(result) {
+ return result.categories;
+ }, function(err) {
+ return [];
+ });
+ }
+
+ beginRecording(recordingOptions) {
+ if (this.recording_) {
+ throw new Error('Already recording');
+ }
+ this.recording_ = 'starting';
+
+ // The devtools and tracing endpoints have slightly different parameter
+ // configurations. Noteably, recordMode has different spelling
+ // requirements.
+ function RewriteRecordMode(recordMode) {
+ if (recordMode === 'record-until-full') {
+ return 'recordUntilFull';
+ }
+ if (recordMode === 'record-continuously') {
+ return 'recordContinuously';
+ }
+ if (recordMode === 'record-as-much-as-possible') {
+ return 'recordAsMuchAsPossible';
+ }
+ return 'unsupported record mode';
+ }
+
+ const traceConfigStr = {
+ includedCategories: recordingOptions.included_categories,
+ excludedCategories: recordingOptions.excluded_categories,
+ recordMode: RewriteRecordMode(recordingOptions.record_mode),
+ enableSystrace: recordingOptions.enable_systrace
+ };
+ if ('memory_dump_config' in recordingOptions) {
+ traceConfigStr.memoryDumpConfig = recordingOptions.memory_dump_config;
+ }
+ let res = this.conn_.req(
+ 'Tracing.start',
+ {
+ traceConfig: traceConfigStr,
+ transferMode: 'ReturnAsStream',
+ streamCompression: 'gzip',
+ bufferUsageReportingInterval: 1000
+ });
+ res = res.then(
+ function ok() {
+ this.conn_.setNotificationListener(
+ 'Tracing.bufferUsage',
+ this.onBufferUsageUpdateFromInspector_.bind(this));
+ this.recording_ = true;
+ }.bind(this),
+ function error() {
+ this.recording_ = false;
+ }.bind(this));
+ return res;
+ }
+
+ onBufferUsageUpdateFromInspector_(params) {
+ this.bufferUsage_ = params.value || params.percentFull;
+ }
+
+ beginGetBufferPercentFull() {
+ return tr.b.timeout(100).then(() => this.bufferUsage_);
+ }
+
+ onDataCollected_(messageString) {
+ appendTraceChunksTo(this.currentTraceTextChunks_, messageString);
+ }
+
+ async endRecording() {
+ if (this.recording_ === false) {
+ return createResolvedPromise();
+ }
+
+ if (this.recording_ !== true) {
+ throw new Error('Cannot end');
+ }
+
+ this.currentTraceTextChunks_ = ['['];
+ const clearListeners = () => {
+ this.conn_.setNotificationListener(
+ 'Tracing.bufferUsage', undefined);
+ this.conn_.setNotificationListener(
+ 'Tracing.tracingComplete', undefined);
+ this.conn_.setNotificationListener(
+ 'Tracing.dataCollected', undefined);
+ };
+
+ try {
+ this.conn_.setNotificationListener(
+ 'Tracing.dataCollected', this.onDataCollected_.bind(this));
+
+ const tracingComplete = new Promise((resolve, reject) => {
+ this.conn_.setNotificationListener(
+ 'Tracing.tracingComplete', resolve);
+ });
+
+ this.recording_ = 'stopping';
+ await this.conn_.req('Tracing.end', {});
+ const params = await tracingComplete;
+
+ this.traceName_ = 'trace.json';
+ if ('stream' in params) {
+ const stream = new tr.ui.e.about_tracing.DevtoolsStream(
+ this.conn_, params.stream);
+ const streamCompression = params.streamCompression || 'none';
+ if (streamCompression === 'gzip') {
+ this.traceName_ = 'trace.json.gz';
+ }
+
+ return await stream.readAndClose();
+ }
+
+ this.currentTraceTextChunks_.push(']');
+ const traceText = this.currentTraceTextChunks_.join('');
+ this.currentTraceTextChunks_ = undefined;
+ return traceText;
+ } finally {
+ clearListeners();
+ this.recording_ = false;
+ }
+ }
+
+ defaultTraceName() {
+ return this.traceName_;
+ }
+ }
+
+ return {
+ InspectorTracingControllerClient,
+ appendTraceChunksTo,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_tracing_controller_client_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_tracing_controller_client_test.html
new file mode 100644
index 00000000000..4a6585ac9e8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/inspector_tracing_controller_client_test.html
@@ -0,0 +1,396 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/inspector_connection.html">
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/inspector_tracing_controller_client.html">
+
+<script>
+'use strict';
+
+function makeController() {
+ const controller =
+ new tr.ui.e.about_tracing.InspectorTracingControllerClient();
+ controller.conn_ = new (function() {
+ this.req = function(method, params) {
+ const msg = JSON.stringify({
+ id: 1,
+ method,
+ params
+ });
+ return new (function() {
+ this.msg = msg;
+ this.then = function(m1, m2) {
+ return this;
+ };
+ })();
+ };
+ this.setNotificationListener = function(method, listener) {
+ };
+ })();
+ return controller;
+}
+
+tr.b.unittest.testSuite(function() {
+ test('beginRecording_sendCategoriesAndOptions', function() {
+ const controller = makeController();
+
+ const recordingOptions = {
+ included_categories: ['a', 'b', 'c'],
+ excluded_categories: ['e'],
+ enable_systrace: false,
+ record_mode: 'record-until-full',
+ };
+
+ const result = JSON.parse(controller.beginRecording(recordingOptions).msg);
+ assert.deepEqual(
+ result.params.traceConfig.includedCategories, ['a', 'b', 'c']);
+ assert.deepEqual(
+ result.params.traceConfig.excludedCategories, ['e']);
+ assert.strictEqual(
+ result.params.traceConfig.recordMode, 'recordUntilFull');
+ assert.isFalse(
+ result.params.traceConfig.enableSystrace);
+ assert.isFalse('memoryDumpConfig' in result.params.traceConfig);
+ });
+
+ test('beginRecording_sendCategoriesAndOptionsWithMemoryInfra', function() {
+ const controller = makeController();
+
+ const memoryConfig = { triggers: [] };
+ memoryConfig.triggers.push(
+ {'mode': 'detailed', 'periodic_interval_ms': 10000});
+ const recordingOptions = {
+ included_categories: ['c', 'disabled-by-default-memory-infra', 'a'],
+ excluded_categories: ['e'],
+ enable_systrace: false,
+ record_mode: 'test-mode',
+ memory_dump_config: memoryConfig,
+ };
+
+ const result = JSON.parse(controller.beginRecording(recordingOptions).msg);
+ assert.isTrue(
+ result.params.traceConfig.memoryDumpConfig.triggers.length === 1);
+ assert.strictEqual(result.params.traceConfig.memoryDumpConfig.
+ triggers[0].mode, 'detailed');
+ assert.strictEqual(result.params.traceConfig.memoryDumpConfig.
+ triggers[0].periodic_interval_ms, 10000);
+ });
+
+ test('oldFormat', function() {
+ const chunks = [];
+ tr.ui.e.about_tracing.appendTraceChunksTo(chunks, '"{ "method": "Tracing.dataCollected", "params": { "value": [ {"cat":"__metadata","pid":28871,"tid":0,"ts":0,"ph":"M","name":"num_cpus","args":{"number":4}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_sort_index","args":{"sort_index":-5}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_name","args":{"name":"Renderer"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_labels","args":{"labels":"JS Bin"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_sort_index","args":{"sort_index":-1}},{"cat":"__metadata","pid":28871,"tid":28917,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Compositor"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Chrome_ChildIOThread"}},{"cat":"__metadata","pid":28871,"tid":28919,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CompositorRasterWorker1/28919"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CrRendererMain"}},{"cat":"ipc,toplevel","pid":28871,"tid":28911,"ts":22000084746,"ph":"X","name":"ChannelReader::DispatchInputData","args":{"class":64,"line":25},"tdur":0,"tts":1853064},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"overhead","args":{"average_overhead":0.015}} ] } }"'); // @suppress longLineCheck
+ assert.strictEqual(chunks.length, 1);
+ JSON.parse('[' + chunks.join('') + ']');
+ });
+
+ test('newFormat', function() {
+ const chunks = [];
+ tr.ui.e.about_tracing.appendTraceChunksTo(chunks, '"{ "method": "Tracing.dataCollected", "params": { "value": [{"cat":"__metadata","pid":28871,"tid":0,"ts":0,"ph":"M","name":"num_cpus","args":{"number":4}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_sort_index","args":{"sort_index":-5}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_name","args":{"name":"Renderer"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"process_labels","args":{"labels":"JS Bin"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_sort_index","args":{"sort_index":-1}},{"cat":"__metadata","pid":28871,"tid":28917,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Compositor"}},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"thread_name","args":{"name":"Chrome_ChildIOThread"}},{"cat":"__metadata","pid":28871,"tid":28919,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CompositorRasterWorker1/28919"}},{"cat":"__metadata","pid":28871,"tid":28908,"ts":0,"ph":"M","name":"thread_name","args":{"name":"CrRendererMain"}},{"cat":"ipc,toplevel","pid":28871,"tid":28911,"ts":22000084746,"ph":"X","name":"ChannelReader::DispatchInputData","args":{"class":64,"line":25},"tdur":0,"tts":1853064},{"cat":"__metadata","pid":28871,"tid":28911,"ts":0,"ph":"M","name":"overhead","args":{"average_overhead":0.015}}] } }"'); // @suppress longLineCheck
+ assert.strictEqual(chunks.length, 1);
+ JSON.parse('[' + chunks.join('') + ']');
+ });
+
+ test('stringAndObjectPayload', function() {
+ const connection =
+ new tr.ui.e.about_tracing.InspectorConnection({DevToolsHost: {}});
+ connection.setNotificationListener('Tracing.dataCollected',
+ function(message) {
+ assert.typeOf(message, 'string');
+ JSON.parse(message);
+ }
+ );
+ connection.dispatchMessage_('{ "method": "Tracing.dataCollected", "params": { "value": [] } }'); // @suppress longLineCheck
+ connection.dispatchMessage_({'method': 'Tracing.dataCollected', 'params': {'value': [] } }); // @suppress longLineCheck
+ });
+
+ // Makes a fake version of DevToolsHost, which is the object injected
+ // by the chrome inspector to allow tracing a remote instance of chrome.
+ //
+ // The fake host doesn't do much by itself - you have to install
+ // callbacks for incoming messages via handleMessage().
+ function makeFakeDevToolsHost() {
+ return new (function() {
+ this.pendingMethods_ = [];
+ this.messageHandlers_ = [];
+
+ // Sends a message to DevTools host. This is used by
+ // InspectorTracingControllerClient to communicate with the remote
+ // debugging tracing backend.
+ this.sendMessageToEmbedder = function(devtoolsMessageStr) {
+ this.pendingMethods_.push(JSON.parse(devtoolsMessageStr));
+ this.tryMessageHandlers_();
+ };
+
+ // Runs remote debugging message handlers. Handlers are installed
+ // by test code via handleMessage().
+ this.tryMessageHandlers_ = function() {
+ while (this.pendingMethods_.length !== 0) {
+ const message = this.pendingMethods_[0];
+ const params = JSON.parse(message.params);
+ let handled = false;
+ const handlersToRemove = [];
+
+ // Try to find a handler for this method.
+ for (const handler of this.messageHandlers_) {
+ if (handler(params, () => handlersToRemove.push(handler))) {
+ handled = true;
+ break;
+ }
+ }
+
+ // Remove any handlers that requested removal.
+ this.messageHandlers_ = this.messageHandlers_.filter(
+ (handler) => !handlersToRemove.includes(handler));
+
+ // Remove any handled messages.
+ if (handled) {
+ this.pendingMethods_.shift();
+ } else {
+ return; // Methods must be handled in order.
+ }
+ }
+ };
+
+ // Installs a message handler that will be invoked for each
+ // incoming message from InspectorTracingControllerClient.
+ //
+ // handleMessage((message, removeSelf) => {
+ // // Try to handle |message|.
+ // // Call |removeSelf| to remove this handler for future messages.
+ // // Return whether |message| was handled. Otherwise other handlers
+ // // will be run until one of them succeeds.
+ // }
+ this.handleMessage = function(handler) {
+ this.messageHandlers_.push(handler);
+ this.tryMessageHandlers_();
+ };
+
+ // Installs a message handler that will handle the first call to the named
+ // method. Returns a promise for the parameters passed to the method.
+ this.handleMethod = function(method) {
+ const result = new Promise((resolve, reject) => {
+ this.handleMessage(
+ (requestParams, removeHandler) => {
+ if (requestParams.method === method) {
+ removeHandler();
+ resolve(requestParams);
+ return true;
+ }
+ return false;
+ });
+ });
+ return result;
+ };
+
+ // Sends a response to a remote debugging method call (i.e.,
+ // "return") to InspectorTracingControllerClient.
+ this.respondToMethod = function(id, params) {
+ this.devToolsAPI_.dispatchMessage(JSON.stringify({
+ id,
+ result: params,
+ }));
+ };
+
+ // Sets the object used to send messages back to
+ // InspectorTracingControllerClient.
+ this.setDevToolsAPI = function(api) {
+ this.devToolsAPI_ = api;
+ };
+
+ // Sends a notification to InspectorTracingControllerClient.
+ this.sendNotification = function(method, params) {
+ this.devToolsAPI_.dispatchMessage(JSON.stringify({ method, params }));
+ };
+ })();
+ }
+
+ test('shouldUseLegacyTraceFormatIfNoStreamId', async function() {
+ const fakeDevToolsHost = makeFakeDevToolsHost();
+ const fakeWindow = {
+ DevToolsHost: fakeDevToolsHost,
+ };
+ const controller =
+ new tr.ui.e.about_tracing.InspectorTracingControllerClient(
+ new tr.ui.e.about_tracing.InspectorConnection(fakeWindow));
+ fakeDevToolsHost.setDevToolsAPI(fakeWindow.DevToolsAPI);
+
+ const runHost = (async() => {
+ const startParams = await fakeDevToolsHost.handleMethod('Tracing.start');
+ fakeDevToolsHost.respondToMethod(startParams.id, {});
+ const endParams = await fakeDevToolsHost.handleMethod('Tracing.end');
+ fakeDevToolsHost.respondToMethod(endParams.id, {});
+ fakeDevToolsHost.sendNotification('Tracing.tracingComplete', {});
+ })();
+
+ await controller.beginRecording({});
+ const traceData = await controller.endRecording();
+ await runHost;
+
+ assert.strictEqual('[]', traceData);
+ });
+
+ test('shouldReassembleTextDataChunks', async function() {
+ const fakeDevToolsHost = makeFakeDevToolsHost();
+ const fakeWindow = {
+ DevToolsHost: fakeDevToolsHost,
+ };
+ const controller =
+ new tr.ui.e.about_tracing.InspectorTracingControllerClient(
+ new tr.ui.e.about_tracing.InspectorConnection(fakeWindow));
+ fakeDevToolsHost.setDevToolsAPI(fakeWindow.DevToolsAPI);
+
+ const STREAM_HANDLE = 7;
+
+ const streamChunks = [
+ '[',
+ ']',
+ '\n',
+ ];
+
+ let streamClosed = false;
+
+ const handleIoRead = (index, params) => {
+ if (params.params.handle !== STREAM_HANDLE) {
+ throw new Error('Invalid stream handle');
+ }
+ if (streamClosed) {
+ throw new Error('stream is closed');
+ }
+ let data = '';
+ if (index < streamChunks.length) {
+ data = streamChunks[index];
+ }
+ const eof = (index >= streamChunks.length - 1);
+ fakeDevToolsHost.respondToMethod(params.id, {
+ eof,
+ base64Encoded: false,
+ data,
+ });
+ const nextIndex = eof ? streamChunks.length : index + 1;
+ return (async() =>
+ handleIoRead(nextIndex, await fakeDevToolsHost.handleMethod('IO.read'))
+ )();
+ };
+
+ const runHost = (async() => {
+ const startParams = await fakeDevToolsHost.handleMethod('Tracing.start');
+ fakeDevToolsHost.respondToMethod(startParams.id, {});
+ const endParams = await fakeDevToolsHost.handleMethod('Tracing.end');
+ fakeDevToolsHost.respondToMethod(endParams.id, {});
+ fakeDevToolsHost.sendNotification('Tracing.tracingComplete', {
+ 'stream': STREAM_HANDLE,
+ });
+
+ const closePromise = (async() => {
+ const closeParams = await fakeDevToolsHost.handleMethod('IO.close');
+ assert.strictEqual(closeParams.params.handle, STREAM_HANDLE);
+ streamClosed = true;
+ })();
+
+ const readPromise = (async() =>
+ handleIoRead(0, await fakeDevToolsHost.handleMethod('IO.read'))
+ )();
+
+ await Promise.race([closePromise, readPromise]);
+ await closePromise;
+ })();
+
+ await controller.beginRecording({});
+ const traceData = await controller.endRecording();
+ await runHost;
+
+ assert.strictEqual(traceData, '[]\n');
+ });
+
+ test('shouldReassembleBase64TraceDataChunks', async function() {
+ const fakeDevToolsHost = makeFakeDevToolsHost();
+ const fakeWindow = {
+ DevToolsHost: fakeDevToolsHost,
+ };
+ const controller =
+ new tr.ui.e.about_tracing.InspectorTracingControllerClient(
+ new tr.ui.e.about_tracing.InspectorConnection(fakeWindow));
+ fakeDevToolsHost.setDevToolsAPI(fakeWindow.DevToolsAPI);
+
+ const STREAM_HANDLE = 7;
+
+ // This is the empty trace ('[]') gzip compressed and chunked to make
+ // sure reassembling base64 strings works properly.
+ const streamChunks = [
+ 'Hw==',
+ 'iwg=',
+ 'ALg4',
+ 'L1oAA4uOBQApu0wNAgAAAA==',
+ ];
+
+ let streamClosed = false;
+
+ const handleIoRead = (index, params) => {
+ if (params.params.handle !== STREAM_HANDLE) {
+ throw new Error('Invalid stream handle');
+ }
+ if (streamClosed) {
+ throw new Error('stream is closed');
+ }
+ let data = '';
+ if (index < streamChunks.length) {
+ data = streamChunks[index];
+ }
+ const eof = (index >= streamChunks.length - 1);
+ fakeDevToolsHost.respondToMethod(params.id, {
+ eof,
+ base64Encoded: true,
+ data,
+ });
+ const nextIndex = eof ? streamChunks.length : index + 1;
+ return (async() => {
+ handleIoRead(nextIndex, await fakeDevToolsHost.handleMethod('IO.read'));
+ })();
+ };
+
+ const runHost = (async() => {
+ const startParams = await fakeDevToolsHost.handleMethod('Tracing.start');
+ fakeDevToolsHost.respondToMethod(startParams.id, {});
+ const endParams = await fakeDevToolsHost.handleMethod('Tracing.end');
+ fakeDevToolsHost.respondToMethod(endParams.id, {});
+ fakeDevToolsHost.sendNotification('Tracing.tracingComplete', {
+ 'stream': STREAM_HANDLE,
+ 'streamCompression': 'gzip'
+ });
+ const closePromise = (async() => {
+ const closeParams = await fakeDevToolsHost.handleMethod('IO.close');
+ assert.strictEqual(closeParams.params.handle, STREAM_HANDLE);
+ streamClosed = true;
+ })();
+
+ const readPromise = (async() => {
+ handleIoRead(0, await fakeDevToolsHost.handleMethod('IO.read'));
+ })();
+
+ await Promise.race([closePromise, readPromise]);
+ await closePromise;
+ })();
+
+ await controller.beginRecording({});
+ const traceData = await controller.endRecording();
+ await runHost;
+
+ const dataArray = new Uint8Array(traceData);
+ const expectedArray = new Uint8Array([
+ 0x1f, 0x8b, 0x8, 0x0, 0xb8, 0x38, 0x2f, 0x5a, 0x0, 0x3, 0x8b, 0x8e,
+ 0x5, 0x0, 0x29, 0xbb, 0x4c, 0xd, 0x2, 0x0, 0x0, 0x0]);
+
+ assert.strictEqual(dataArray.length, expectedArray.length);
+
+ for (let i = 0; i < dataArray.length; ++i) {
+ assert.strictEqual(dataArray[i], expectedArray[i]);
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/mock_tracing_controller_client.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/mock_tracing_controller_client.html
new file mode 100644
index 00000000000..cfefdc05cc7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/mock_tracing_controller_client.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/tracing_controller_client.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ function MockTracingControllerClient() {
+ this.requests = [];
+ this.nextRequestIndex = 0;
+ this.allowLooping = false;
+ }
+
+ MockTracingControllerClient.prototype = {
+ __proto__: tr.ui.e.about_tracing.TracingControllerClient.prototype,
+
+ expectRequest(method, generateResponse) {
+ let generateResponseCb;
+ if (typeof generateResponse === 'function') {
+ generateResponseCb = generateResponse;
+ } else {
+ generateResponseCb = function() {
+ return generateResponse;
+ };
+ }
+
+ this.requests.push({
+ method,
+ generateResponseCb});
+ },
+
+ _request(method, args) {
+ return new Promise(function(resolve) {
+ const requestIndex = this.nextRequestIndex;
+ if (requestIndex >= this.requests.length) {
+ throw new Error('Unhandled request');
+ }
+ if (!this.allowLooping) {
+ this.nextRequestIndex++;
+ } else {
+ this.nextRequestIndex = (this.nextRequestIndex + 1) %
+ this.requests.length;
+ }
+
+ const req = this.requests[requestIndex];
+ assert.strictEqual(method, req.method);
+ const resp = req.generateResponseCb(args);
+ resolve(resp);
+ }.bind(this));
+ },
+
+ assertAllRequestsHandled() {
+ if (this.allowLooping) {
+ throw new Error('Incompatible with allowLooping');
+ }
+ assert.strictEqual(this.requests.length, this.nextRequestIndex);
+ },
+
+ getCategories() {
+ return this._request('getCategories');
+ },
+
+ beginRecording(recordingOptions) {
+ return this._request('beginRecording', recordingOptions);
+ },
+
+ beginGetBufferPercentFull() {
+ return this._request('beginGetBufferPercentFull');
+ },
+
+ endRecording() {
+ return this._request('endRecording');
+ }
+ };
+
+ return {
+ MockTracingControllerClient,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html
new file mode 100644
index 00000000000..77c0e80af12
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view.html
@@ -0,0 +1,372 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/ui/base/file.html">
+<link rel="import" href="/tracing/ui/base/hotkey_controller.html">
+<link rel="import" href="/tracing/ui/base/info_bar_group.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/inspector_tracing_controller_client.html">
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/record_controller.html">
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/xhr_based_tracing_controller_client.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
+
+<style>
+x-profiling-view {
+ flex-direction: column;
+ display: flex;
+ padding: 0;
+}
+
+x-profiling-view .controls #save-button {
+ margin-left: 64px !important;
+}
+
+x-profiling-view > tr-ui-timeline-view {
+ flex: 1 1 auto;
+ min-height: 0;
+}
+
+.report-id-message {
+ -webkit-user-select: text;
+}
+
+x-timeline-view-buttons {
+ display: flex;
+ align-items: center;
+}
+</style>
+
+<template id="profiling-view-template">
+ <tr-ui-b-info-bar-group></tr-ui-b-info-bar-group>
+ <x-timeline-view-buttons>
+ <button id="record-button">Record</button>
+ <button id="save-button">Save</button>
+ <button id="load-button">Load</button>
+ </x-timeline-view-buttons>
+ <tr-ui-timeline-view>
+ <track-view-container id='track_view_container'></track-view-container>
+ </tr-ui-timeline-view>
+</template>
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview ProfilingView glues the View control to
+ * TracingController.
+ */
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ /**
+ * ProfilingView
+ * @constructor
+ * @extends {HTMLDivElement}
+ */
+ const ProfilingView = tr.ui.b.define('x-profiling-view');
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ ProfilingView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate(tracingControllerClient) {
+ Polymer.dom(this).appendChild(
+ tr.ui.b.instantiateTemplate('#profiling-view-template', THIS_DOC));
+
+ this.timelineView_ =
+ Polymer.dom(this).querySelector('tr-ui-timeline-view');
+ this.infoBarGroup_ =
+ Polymer.dom(this).querySelector('tr-ui-b-info-bar-group');
+
+ // Detach the buttons. We will reattach them to the timeline view.
+ // TODO(nduca): Make timeline-view have a content select="x-buttons"
+ // that pulls in any buttons.
+ this.recordButton_ = Polymer.dom(this).querySelector('#record-button');
+ this.loadButton_ = Polymer.dom(this).querySelector('#load-button');
+ this.saveButton_ = Polymer.dom(this).querySelector('#save-button');
+
+ const buttons = Polymer.dom(this).querySelector(
+ 'x-timeline-view-buttons');
+ Polymer.dom(buttons.parentElement).removeChild(buttons);
+ Polymer.dom(this.timelineView_.leftControls).appendChild(buttons);
+ this.initButtons_();
+
+ this.timelineView_.hotkeyController.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keypress',
+ keyCode: 'r'.charCodeAt(0),
+ callback(e) {
+ this.beginRecording();
+ event.stopPropagation();
+ },
+ thisArg: this
+ }));
+
+ this.initDragAndDrop_();
+
+ if (tracingControllerClient) {
+ this.tracingControllerClient_ = tracingControllerClient;
+ } else if (window.DevToolsHost !== undefined) {
+ this.tracingControllerClient_ =
+ new tr.ui.e.about_tracing.InspectorTracingControllerClient(
+ new tr.ui.e.about_tracing.InspectorConnection(window));
+ } else {
+ this.tracingControllerClient_ =
+ new tr.ui.e.about_tracing.XhrBasedTracingControllerClient();
+ }
+
+ this.isRecording_ = false;
+ this.activeTrace_ = undefined;
+
+ this.updateTracingControllerSpecificState_();
+ },
+
+ // Detach all document event listeners. Without this the tests can get
+ // confused as the element may still be listening when the next test runs.
+ detach_() {
+ this.detachDragAndDrop_();
+ },
+
+ get isRecording() {
+ return this.isRecording_;
+ },
+
+ set tracingControllerClient(tracingControllerClient) {
+ this.tracingControllerClient_ = tracingControllerClient;
+ this.updateTracingControllerSpecificState_();
+ },
+
+ updateTracingControllerSpecificState_() {
+ const isInspector = this.tracingControllerClient_ instanceof
+ tr.ui.e.about_tracing.InspectorTracingControllerClient;
+
+ if (isInspector) {
+ this.infoBarGroup_.addMessage(
+ 'This about:tracing is connected to a remote device...',
+ [{buttonText: 'Wow!', onClick() {}}]);
+ }
+ },
+
+ beginRecording() {
+ if (this.isRecording_) {
+ throw new Error('Already recording');
+ }
+ this.isRecording_ = true;
+ const resultPromise = tr.ui.e.about_tracing.beginRecording(
+ this.tracingControllerClient_);
+ resultPromise.then(
+ function(data) {
+ this.isRecording_ = false;
+ const traceName = tr.ui.e.about_tracing.defaultTraceName(
+ this.tracingControllerClient_);
+ this.setActiveTrace(traceName, data, false);
+ }.bind(this),
+ function(err) {
+ this.isRecording_ = false;
+ if (err instanceof tr.ui.e.about_tracing.UserCancelledError) {
+ return;
+ }
+ tr.ui.b.Overlay.showError('Error while recording', err);
+ }.bind(this));
+ return resultPromise;
+ },
+
+ get timelineView() {
+ return this.timelineView_;
+ },
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ clearActiveTrace() {
+ this.saveButton_.disabled = true;
+ this.activeTrace_ = undefined;
+ },
+
+ setActiveTrace(filename, data) {
+ this.activeTrace_ = {
+ filename,
+ data
+ };
+
+ this.infoBarGroup_.clearMessages();
+ this.updateTracingControllerSpecificState_();
+ this.saveButton_.disabled = false;
+ this.timelineView_.viewTitle = filename;
+
+ const m = new tr.Model();
+ const i = new tr.importer.Import(m);
+ const p = i.importTracesWithProgressDialog([data]);
+ p.then(
+ function() {
+ this.timelineView_.model = m;
+ this.timelineView_.updateDocumentFavicon();
+ }.bind(this),
+ function(err) {
+ tr.ui.b.Overlay.showError('While importing: ', err);
+ }.bind(this));
+ },
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ initButtons_() {
+ this.recordButton_.addEventListener(
+ 'click', function(event) {
+ event.stopPropagation();
+ this.beginRecording();
+ }.bind(this));
+
+ this.loadButton_.addEventListener(
+ 'click', function(event) {
+ event.stopPropagation();
+ this.onLoadClicked_();
+ }.bind(this));
+
+ this.saveButton_.addEventListener('click',
+ this.onSaveClicked_.bind(this));
+ this.saveButton_.disabled = true;
+ },
+
+ requestFilename_() {
+ // unsafe filename patterns:
+ const illegalRe = /[\/\?<>\\:\*\|":]/g;
+ const controlRe = /[\x00-\x1f\x80-\x9f]/g;
+ const reservedRe = /^\.+$/;
+
+ const defaultName = this.activeTrace_.filename;
+ let fileExtension = '.json';
+ let fileRegex = /\.json$/;
+ if (/[.]gz$/.test(defaultName)) {
+ fileExtension += '.gz';
+ fileRegex = /\.json\.gz$/;
+ } else if (/[.]zip$/.test(defaultName)) {
+ fileExtension = '.zip';
+ fileRegex = /\.zip$/;
+ }
+
+ const custom = prompt('Filename? (' + fileExtension +
+ ' appended) Or leave blank:');
+ if (custom === null) {
+ return undefined;
+ }
+
+ let name;
+ if (custom) {
+ name = ' ' + custom;
+ } else {
+ const date = new Date();
+ const dateText = ' ' + date.toDateString() +
+ ' ' + date.toLocaleTimeString();
+ name = dateText;
+ }
+
+ const filename = defaultName.replace(fileRegex, name) + fileExtension;
+
+ return filename
+ .replace(illegalRe, '.')
+ .replace(controlRe, '\u2022')
+ .replace(reservedRe, '')
+ .replace(/\s+/g, '_');
+ },
+
+ onSaveClicked_() {
+ // Create a blob URL from the binary array.
+ const blob = new Blob([this.activeTrace_.data],
+ {type: 'application/octet-binary'});
+ const blobUrl = window.webkitURL.createObjectURL(blob);
+
+ // Create a link and click on it. BEST API EVAR!
+ const link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
+ link.href = blobUrl;
+ const filename = this.requestFilename_();
+ if (filename) {
+ link.download = filename;
+ link.click();
+ }
+ },
+
+ onLoadClicked_() {
+ const inputElement = document.createElement('input');
+ inputElement.type = 'file';
+ inputElement.multiple = false;
+
+ let changeFired = false;
+ inputElement.addEventListener(
+ 'change',
+ function(e) {
+ if (changeFired) return;
+ changeFired = true;
+
+ const file = inputElement.files[0];
+ tr.ui.b.readFile(file).then(
+ function(data) {
+ this.setActiveTrace(file.name, data);
+ }.bind(this),
+ function(err) {
+ tr.ui.b.Overlay.showError('Error while loading file: ' + err);
+ });
+ }.bind(this), false);
+ inputElement.click();
+ },
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ initDragAndDrop_() {
+ this.dropHandler_ = this.dropHandler_.bind(this);
+ this.ignoreDragEvent_ = this.ignoreDragEvent_.bind(this);
+ document.addEventListener('dragstart', this.ignoreDragEvent_, false);
+ document.addEventListener('dragend', this.ignoreDragEvent_, false);
+ document.addEventListener('dragenter', this.ignoreDragEvent_, false);
+ document.addEventListener('dragleave', this.ignoreDragEvent_, false);
+ document.addEventListener('dragover', this.ignoreDragEvent_, false);
+ document.addEventListener('drop', this.dropHandler_, false);
+ },
+
+ detachDragAndDrop_() {
+ document.removeEventListener('dragstart', this.ignoreDragEvent_);
+ document.removeEventListener('dragend', this.ignoreDragEvent_);
+ document.removeEventListener('dragenter', this.ignoreDragEvent_);
+ document.removeEventListener('dragleave', this.ignoreDragEvent_);
+ document.removeEventListener('dragover', this.ignoreDragEvent_);
+ document.removeEventListener('drop', this.dropHandler_);
+ },
+
+ ignoreDragEvent_(e) {
+ e.preventDefault();
+ return false;
+ },
+
+ dropHandler_(e) {
+ if (this.isAnyDialogUp_) return;
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ const files = e.dataTransfer.files;
+ if (files.length !== 1) {
+ tr.ui.b.Overlay.showError('1 file supported at a time.');
+ return;
+ }
+
+ tr.ui.b.readFile(files[0]).then(
+ function(data) {
+ this.setActiveTrace(files[0].name, data);
+ }.bind(this),
+ function(err) {
+ tr.ui.b.Overlay.showError('Error while loading file: ' + err);
+ });
+ return false;
+ }
+ };
+
+ return {
+ ProfilingView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html
new file mode 100644
index 00000000000..f52c491207f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/profiling_view_test.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/mock_tracing_controller_client.html">
+<link rel="import" href="/tracing/ui/extras/about_tracing/profiling_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Base64 = tr.b.Base64;
+ const testData = [
+ {name: 'a', args: {}, pid: 52, ts: 15000, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 19000, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'b', args: {}, pid: 52, ts: 32000, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'b', args: {}, pid: 52, ts: 54000, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+
+ const monitoringOptions = {
+ isMonitoring: false,
+ categoryFilter: '*',
+ useSystemTracing: false,
+ useContinuousTracing: false,
+ useSampling: false
+ };
+
+ const ProfilingView = tr.ui.e.about_tracing.ProfilingView;
+
+ test('recording', function() {
+ const mock = new tr.ui.e.about_tracing.MockTracingControllerClient();
+ mock.allowLooping = true;
+ mock.expectRequest('endRecording', function() {
+ return '';
+ });
+ mock.expectRequest('getCategories', function() {
+ return ['a', 'b', 'c'];
+ });
+ mock.expectRequest('beginRecording', function(data) {
+ return '';
+ });
+ mock.expectRequest('endRecording', function(data) {
+ return JSON.stringify(testData);
+ });
+
+ const view = new ProfilingView(mock);
+ view.style.height = '400px';
+ view.style.border = '1px solid black';
+ this.addHTMLOutput(view);
+
+ const recordingPromise = view.beginRecording();
+
+ let didAbort = false;
+
+ tr.b.timeout(60).then(() => {
+ if (didAbort) return;
+ recordingPromise.selectionDlg.clickRecordButton();
+ }).then(() => tr.b.timeout(60)).then(() => {
+ recordingPromise.progressDlg.clickStopButton();
+ });
+
+ return recordingPromise.then(null, err => {
+ didAbort = true;
+ assert.fail(err);
+ });
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller.html
new file mode 100644
index 00000000000..a9b42b589d8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller.html
@@ -0,0 +1,187 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/extras/about_tracing/record_selection_dialog.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ function beginRecording(tracingControllerClient) {
+ let finalPromiseResolver;
+ const finalPromise = new Promise(function(resolve, reject) {
+ finalPromiseResolver = {
+ resolve,
+ reject
+ };
+ });
+ finalPromise.selectionDlg = undefined;
+ finalPromise.progressDlg = undefined;
+
+ function beginRecordingError(err) {
+ finalPromiseResolver.reject(err);
+ }
+
+ // Step 0: End recording. This is necessary when the user reloads the
+ // about:tracing page when we are recording. Window.onbeforeunload is not
+ // reliable to end recording on reload.
+ endRecording(tracingControllerClient).then(
+ getCategories,
+ getCategories); // Ignore error.
+
+ // But just in case, bind onbeforeunload anyway.
+ window.onbeforeunload = function(e) {
+ endRecording(tracingControllerClient);
+ };
+
+ // Step 1: Get categories.
+ function getCategories() {
+ const p = tracingControllerClient.getCategories().then(
+ showTracingDialog,
+ beginRecordingError);
+ p.catch(function(err) {
+ beginRecordingError(err);
+ });
+ }
+
+ // Step 2: Show tracing dialog.
+ let selectionDlg;
+ function showTracingDialog(categories) {
+ selectionDlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ selectionDlg.categories = categories;
+ selectionDlg.settings_key =
+ 'tr.ui.e.about_tracing.record_selection_dialog';
+ selectionDlg.addEventListener('recordclick', startTracing);
+ selectionDlg.addEventListener('closeclick', cancelRecording);
+ selectionDlg.visible = true;
+
+ finalPromise.selectionDlg = selectionDlg;
+ }
+
+ function cancelRecording() {
+ finalPromise.selectionDlg = undefined;
+ finalPromiseResolver.reject(new UserCancelledError());
+ }
+
+ // Step 2: Do the actual tracing dialog.
+ let progressDlg;
+ let bufferPercentFullDiv;
+ function startTracing() {
+ progressDlg = new tr.ui.b.Overlay();
+ Polymer.dom(progressDlg).textContent = 'Recording...';
+ progressDlg.userCanClose = false;
+
+ bufferPercentFullDiv = document.createElement('div');
+ Polymer.dom(progressDlg).appendChild(bufferPercentFullDiv);
+
+ const stopButton = document.createElement('button');
+ Polymer.dom(stopButton).textContent = 'Stop';
+ progressDlg.clickStopButton = function() {
+ stopButton.click();
+ };
+ Polymer.dom(progressDlg).appendChild(stopButton);
+
+ const categories = selectionDlg.includedAndExcludedCategories();
+ const recordingOptions = {
+ included_categories: categories.included,
+ excluded_categories: categories.excluded,
+ enable_systrace: selectionDlg.useSystemTracing,
+ record_mode: selectionDlg.tracingRecordMode,
+ };
+ if (categories.included.indexOf(
+ 'disabled-by-default-memory-infra') !== -1) {
+ const memoryConfig = { triggers: [] };
+ memoryConfig.triggers.push(
+ {'mode': 'detailed', 'periodic_interval_ms': 10000});
+ recordingOptions.memory_dump_config = memoryConfig;
+ }
+
+ const requestPromise = tracingControllerClient.beginRecording(
+ recordingOptions);
+ requestPromise.then(
+ function() {
+ progressDlg.visible = true;
+ stopButton.focus();
+ updateBufferPercentFull('0');
+ },
+ recordFailed);
+
+ stopButton.addEventListener('click', function() {
+ // TODO(chrishenry): Currently, this only dismiss the progress
+ // dialog when tracingComplete event is received. When performing
+ // remote debugging, the tracingComplete event may be delayed
+ // considerable. We should indicate to user that we are waiting
+ // for tracingComplete event instead of being unresponsive. (For
+ // now, I disable the "stop" button, since clicking on the button
+ // again now cause exception.)
+ const recordingPromise = endRecording(tracingControllerClient);
+ recordingPromise.then(
+ recordFinished,
+ recordFailed);
+ stopButton.disabled = true;
+ bufferPercentFullDiv = undefined;
+ });
+ finalPromise.progressDlg = progressDlg;
+ }
+
+ function recordFinished(tracedData) {
+ progressDlg.visible = false;
+ finalPromise.progressDlg = undefined;
+ finalPromiseResolver.resolve(tracedData);
+ }
+
+ function recordFailed(err) {
+ progressDlg.visible = false;
+ finalPromise.progressDlg = undefined;
+ finalPromiseResolver.reject(err);
+ }
+
+ function getBufferPercentFull() {
+ if (!bufferPercentFullDiv) return;
+
+ tracingControllerClient.beginGetBufferPercentFull().then(
+ updateBufferPercentFull);
+ }
+
+ function updateBufferPercentFull(percentFull) {
+ if (!bufferPercentFullDiv) return;
+
+ percentFull = Math.round(100 * parseFloat(percentFull));
+ const newText = 'Buffer usage: ' + percentFull + '%';
+ if (Polymer.dom(bufferPercentFullDiv).textContent !== newText) {
+ Polymer.dom(bufferPercentFullDiv).textContent = newText;
+ }
+
+ window.setTimeout(getBufferPercentFull, 500);
+ }
+
+ // Thats it! We're done.
+ return finalPromise;
+ }
+
+ function endRecording(tracingControllerClient) {
+ return tracingControllerClient.endRecording();
+ }
+
+ function defaultTraceName(tracingControllerClient) {
+ return tracingControllerClient.defaultTraceName();
+ }
+
+ function UserCancelledError() {
+ Error.apply(this, arguments);
+ }
+ UserCancelledError.prototype = {
+ __proto__: Error.prototype
+ };
+
+ return {
+ beginRecording,
+ UserCancelledError,
+ defaultTraceName,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html
new file mode 100644
index 00000000000..e3e0438f3a2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_controller_test.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/mock_tracing_controller_client.html">
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/record_controller.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const testData = [
+ {name: 'a', args: {}, pid: 52, ts: 15000, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'a', args: {}, pid: 52, ts: 19000, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'b', args: {}, pid: 52, ts: 32000, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'b', args: {}, pid: 52, ts: 54000, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+
+ test('fullRecording', function() {
+ const mock = new tr.ui.e.about_tracing.MockTracingControllerClient();
+ mock.expectRequest('endRecording', function() {
+ return '';
+ });
+ mock.expectRequest('getCategories', function() {
+ tr.b.timeout(20).then(() =>
+ recordingPromise.selectionDlg.clickRecordButton());
+ return ['a', 'b', 'c'];
+ });
+ mock.expectRequest('beginRecording', function(recordingOptions) {
+ assert.typeOf(recordingOptions.included_categories, 'array');
+ assert.typeOf(recordingOptions.excluded_categories, 'array');
+ assert.typeOf(recordingOptions.enable_systrace, 'boolean');
+ assert.typeOf(recordingOptions.record_mode, 'string');
+ tr.b.timeout(10).then(() =>
+ recordingPromise.progressDlg.clickStopButton());
+ return '';
+ });
+ mock.expectRequest('endRecording', function(data) {
+ return JSON.stringify(testData);
+ });
+
+ const recordingPromise = tr.ui.e.about_tracing.beginRecording(mock);
+
+ return recordingPromise.then(function(data) {
+ mock.assertAllRequestsHandled();
+ assert.strictEqual(data, JSON.stringify(testData));
+ }, function(error) {
+ assert.fail(error);
+ });
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog.html
new file mode 100644
index 00000000000..a5383973a80
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog.html
@@ -0,0 +1,689 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/info_bar_group.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<template id="record-selection-dialog-template">
+ <style>
+ .categories-column-view {
+ display: flex;
+ flex-direction: column;
+ font-family: sans-serif;
+ max-width: 640px;
+ min-height: 0;
+ min-width: 0;
+ opacity: 1;
+ transition: max-height 1s ease, max-width 1s ease, opacity 1s ease;
+ will-change: opacity;
+ }
+
+ .categories-column-view-hidden {
+ max-height: 0;
+ max-width: 0;
+ opacity: 0;
+ overflow: hidden;
+ display: none;
+ }
+
+ .categories-selection {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .category-presets {
+ padding: 4px;
+ }
+
+ .category-description {
+ color: #aaa;
+ font-size: small;
+ max-height: 1em;
+ opacity: 1;
+ padding-left: 4px;
+ padding-right: 4px;
+ text-align: right;
+ transition: max-height 1s ease, opacity 1s ease;
+ will-change: opacity;
+ }
+
+ .category-description-hidden {
+ max-height: 0;
+ opacity: 0;
+ }
+
+ .default-enabled-categories,
+ .default-disabled-categories {
+ flex: 1 1 auto;
+ display: flex;
+ flex-direction: column;
+ padding: 4px;
+ width: 300px;
+ }
+
+ .default-enabled-categories > div,
+ .default-disabled-categories > div {
+ padding: 4px;
+ }
+
+ .tracing-modes {
+ flex: 1 0 auto;
+ display: flex;
+ flex-direction: reverse;
+ padding: 4px;
+ border-bottom: 2px solid #ddd;
+ border-top: 2px solid #ddd;
+ }
+
+ .default-disabled-categories {
+ border-left: 2px solid #ddd;
+ }
+
+ .warning-default-disabled-categories {
+ display: inline-block;
+ font-weight: bold;
+ text-align: center;
+ color: #BD2E2E;
+ width: 2.0ex;
+ height: 2.0ex;
+ border-radius: 2.0ex;
+ border: 1px solid #BD2E2E;
+ }
+
+ .categories {
+ font-size: 80%;
+ padding: 10px;
+ flex: 1 1 auto;
+ }
+
+ .group-selectors {
+ font-size: 80%;
+ border-bottom: 1px solid #ddd;
+ padding-bottom: 6px;
+ flex: 0 0 auto;
+ }
+
+ .group-selectors button {
+ padding: 1px;
+ }
+
+ .record-selection-dialog .labeled-option-group {
+ flex: 0 0 auto;
+ flex-direction: column;
+ display: flex;
+ }
+
+ .record-selection-dialog .labeled-option {
+ border-top: 5px solid white;
+ border-bottom: 5px solid white;
+ }
+
+ .record-selection-dialog .edit-categories {
+ padding-left: 6px;
+ }
+
+ .record-selection-dialog .edit-categories:after {
+ padding-left: 15px;
+ font-size: 125%;
+ }
+
+ .record-selection-dialog .labeled-option-group:not(.categories-expanded)
+ .edit-categories:after {
+ content: '\25B8'; /* Right triangle */
+ }
+
+ .record-selection-dialog .labeled-option-group.categories-expanded
+ .edit-categories:after {
+ content: '\25BE'; /* Down triangle */
+ }
+
+ </style>
+
+ <div class="record-selection-dialog">
+ <tr-ui-b-info-bar-group></tr-ui-b-info-bar-group>
+ <div class="category-presets">
+ </div>
+ <div class="category-description"></div>
+ <div class="categories-column-view">
+ <div class="tracing-modes"></div>
+ <div class="categories-selection">
+ <div class="default-enabled-categories">
+ <div>Record&nbsp;Categories</div>
+ <div class="group-selectors">
+ Select
+ <button class="all-btn">All</button>
+ <button class="none-btn">None</button>
+ </div>
+ <div class="categories"></div>
+ </div>
+ <div class="default-disabled-categories">
+ <div>Disabled&nbsp;by&nbsp;Default&nbsp;Categories
+ <a class="warning-default-disabled-categories">!</a>
+ </div>
+ <div class="group-selectors">
+ Select
+ <button class="all-btn">All</button>
+ <button class="none-btn">None</button>
+ </div>
+ <div class="categories"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview RecordSelectionDialog presents the available categories
+ * to be enabled/disabled during tr.c.
+ */
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+ const RecordSelectionDialog = tr.ui.b.define('div');
+
+ const DEFAULT_PRESETS = [
+ {title: 'Web developer',
+ categoryFilter: ['blink', 'cc', 'netlog', 'renderer.scheduler',
+ 'sequence_manager', 'toplevel', 'v8']},
+ {title: 'Input latency',
+ categoryFilter: ['benchmark', 'input', 'evdev', 'renderer.scheduler',
+ 'sequence_manager', 'toplevel']},
+ {title: 'Rendering',
+ categoryFilter: ['blink', 'cc', 'gpu', 'toplevel', 'viz']},
+ {title: 'Javascript and rendering',
+ categoryFilter: ['blink', 'cc', 'gpu', 'renderer.scheduler',
+ 'sequence_manager', 'v8', 'toplevel', 'viz']},
+ {title: 'Frame Viewer',
+ categoryFilter: ['blink', 'cc', 'gpu', 'renderer.scheduler',
+ 'sequence_manager', 'v8', 'toplevel',
+ 'disabled-by-default-blink.invalidation',
+ 'disabled-by-default-cc.debug',
+ 'disabled-by-default-cc.debug.picture',
+ 'disabled-by-default-cc.debug.display_items']},
+ {title: 'Manually select settings',
+ categoryFilter: []}
+ ];
+ const RECORDING_MODES = [
+ {'label': 'Record until full',
+ 'value': 'record-until-full'},
+ {'label': 'Record continuously',
+ 'value': 'record-continuously'},
+ {'label': 'Record as much as possible',
+ 'value': 'record-as-much-as-possible'}];
+ const DEFAULT_RECORD_MODE = 'record-until-full';
+ const DEFAULT_CONTINUOUS_TRACING = true;
+ const DEFAULT_SYSTEM_TRACING = true;
+ const DEFAULT_SAMPLING_TRACING = false;
+
+ RecordSelectionDialog.prototype = {
+ __proto__: tr.ui.b.Overlay.prototype,
+
+ decorate() {
+ tr.ui.b.Overlay.prototype.decorate.call(this);
+ this.title = 'Record a new trace...';
+
+ Polymer.dom(this).classList.add('record-dialog-overlay');
+
+ const node =
+ tr.ui.b.instantiateTemplate('#record-selection-dialog-template',
+ THIS_DOC);
+ Polymer.dom(this).appendChild(node);
+
+ this.recordButtonEl_ = document.createElement('button');
+ Polymer.dom(this.recordButtonEl_).textContent = 'Record';
+ this.recordButtonEl_.addEventListener(
+ 'click',
+ this.onRecordButtonClicked_.bind(this));
+ this.recordButtonEl_.style.fontSize = '110%';
+ Polymer.dom(this.buttons).appendChild(this.recordButtonEl_);
+
+ this.categoriesView_ = Polymer.dom(this).querySelector(
+ '.categories-column-view');
+ this.presetsEl_ = Polymer.dom(this).querySelector('.category-presets');
+ Polymer.dom(this.presetsEl_).appendChild(tr.ui.b.createOptionGroup(
+ this, 'currentlyChosenPreset',
+ 'about_tracing.record_selection_dialog_preset',
+ DEFAULT_PRESETS[0].categoryFilter,
+ DEFAULT_PRESETS.map(function(p) {
+ return { label: p.title, value: p.categoryFilter };
+ })));
+
+ this.tracingRecordModeSltr_ = tr.ui.b.createSelector(
+ this, 'tracingRecordMode',
+ 'recordSelectionDialog.tracingRecordMode',
+ DEFAULT_RECORD_MODE, RECORDING_MODES);
+
+ this.systemTracingBn_ = tr.ui.b.createCheckBox(
+ undefined, undefined,
+ 'recordSelectionDialog.useSystemTracing', DEFAULT_SYSTEM_TRACING,
+ 'System tracing');
+ this.samplingTracingBn_ = tr.ui.b.createCheckBox(
+ undefined, undefined,
+ 'recordSelectionDialog.useSampling', DEFAULT_SAMPLING_TRACING,
+ 'State sampling');
+ this.tracingModesContainerEl_ = Polymer.dom(this).querySelector(
+ '.tracing-modes');
+ Polymer.dom(this.tracingModesContainerEl_).appendChild(
+ this.tracingRecordModeSltr_);
+ Polymer.dom(this.tracingModesContainerEl_).appendChild(
+ this.systemTracingBn_);
+ Polymer.dom(this.tracingModesContainerEl_).appendChild(
+ this.samplingTracingBn_);
+
+ this.enabledCategoriesContainerEl_ =
+ Polymer.dom(this).querySelector(
+ '.default-enabled-categories .categories');
+
+ this.disabledCategoriesContainerEl_ =
+ Polymer.dom(this).querySelector(
+ '.default-disabled-categories .categories');
+
+ this.createGroupSelectButtons_(
+ Polymer.dom(this).querySelector('.default-enabled-categories'));
+ this.createGroupSelectButtons_(
+ Polymer.dom(this).querySelector('.default-disabled-categories'));
+ this.createDefaultDisabledWarningDialog_(
+ Polymer.dom(this).querySelector(
+ '.warning-default-disabled-categories'));
+ this.editCategoriesOpened_ = false;
+
+ // TODO(chrishenry): When used with tr.ui.b.Overlay (such as in
+ // chrome://tracing, this does not yet look quite right due to
+ // the 10px overlay content padding (but it's good enough).
+ this.infoBarGroup_ = Polymer.dom(this).querySelector(
+ 'tr-ui-b-info-bar-group');
+
+ this.addEventListener('visible-change', this.onVisibleChange_.bind(this));
+ },
+
+ set supportsSystemTracing(s) {
+ if (s) {
+ this.systemTracingBn_.style.display = undefined;
+ } else {
+ this.systemTracingBn_.style.display = 'none';
+ this.useSystemTracing = false;
+ }
+ },
+
+ get tracingRecordMode() {
+ return this.tracingRecordModeSltr_.selectedValue;
+ },
+ set tracingRecordMode(value) {
+ this.tracingRecordMode_ = value;
+ },
+
+ get useSystemTracing() {
+ return this.systemTracingBn_.checked;
+ },
+ set useSystemTracing(value) {
+ this.systemTracingBn_.checked = !!value;
+ },
+
+ get useSampling() {
+ return this.samplingTracingBn_.checked;
+ },
+ set useSampling(value) {
+ this.samplingTracingBn_.checked = !!value;
+ },
+
+ set categories(c) {
+ if (!(c instanceof Array)) {
+ throw new Error('categories must be an array');
+ }
+ this.categories_ = c;
+
+ for (let i = 0; i < this.categories_.length; i++) {
+ const split = this.categories_[i].split(',');
+ this.categories_[i] = split.shift();
+ if (split.length > 0) {
+ this.categories_ = this.categories_.concat(split);
+ }
+ }
+ },
+
+ set settings_key(k) {
+ this.settings_key_ = k;
+ },
+
+ set settings(s) {
+ throw new Error('Dont use this!');
+ },
+
+ usingPreset_() {
+ return this.currentlyChosenPreset_.length > 0;
+ },
+
+ get currentlyChosenPreset() {
+ return this.currentlyChosenPreset_;
+ },
+
+ set currentlyChosenPreset(preset) {
+ if (!(preset instanceof Array)) {
+ throw new Error('RecordSelectionDialog.currentlyChosenPreset:' +
+ ' preset must be an array.');
+ }
+ this.currentlyChosenPreset_ = preset;
+
+ if (this.usingPreset_()) {
+ this.changeEditCategoriesState_(false);
+ } else {
+ this.updateCategoryColumnView_(true);
+ this.changeEditCategoriesState_(true);
+ }
+ this.updateManualSelectionView_();
+ this.updatePresetDescription_();
+ },
+
+ updateManualSelectionView_() {
+ const classList = Polymer.dom(this.categoriesView_).classList;
+ if (!this.usingPreset_()) {
+ classList.remove('categories-column-view-hidden');
+ } else {
+ if (this.editCategoriesOpened_) {
+ classList.remove('categories-column-view-hidden');
+ } else {
+ classList.add('categories-column-view-hidden');
+ }
+ }
+ },
+
+ updateCategoryColumnView_(shouldReadFromSettings) {
+ const categorySet = Polymer.dom(this).querySelectorAll('.categories');
+ for (let i = 0; i < categorySet.length; ++i) {
+ const categoryGroup = categorySet[i].children;
+ for (let j = 0; j < categoryGroup.length; ++j) {
+ const categoryEl = categoryGroup[j].children[0];
+ categoryEl.checked = shouldReadFromSettings ?
+ tr.b.Settings.get(categoryEl.value, false, this.settings_key_) :
+ false;
+ }
+ }
+ },
+
+ onClickEditCategories() {
+ if (!this.usingPreset_()) return;
+
+ if (!this.editCategoriesOpened_) {
+ this.updateCategoryColumnView_(false);
+ for (let i = 0; i < this.currentlyChosenPreset_.length; ++i) {
+ const categoryEl = this.querySelector('#' +
+ this.currentlyChosenPreset_[i]);
+ if (!categoryEl) continue;
+ categoryEl.checked = true;
+ }
+ }
+
+ this.changeEditCategoriesState_(!this.editCategoriesOpened_);
+ this.updateManualSelectionView_();
+ this.recordButtonEl_.focus();
+ },
+
+ changeEditCategoriesState_(editCategoriesState) {
+ const presetOptionsGroup = Polymer.dom(this).querySelector(
+ '.labeled-option-group');
+ if (!presetOptionsGroup) return;
+
+ this.editCategoriesOpened_ = editCategoriesState;
+ if (this.editCategoriesOpened_) {
+ Polymer.dom(presetOptionsGroup).classList.add('categories-expanded');
+ } else {
+ Polymer.dom(presetOptionsGroup).classList.remove(
+ 'categories-expanded');
+ }
+ },
+
+ updatePresetDescription_() {
+ const description = Polymer.dom(this).querySelector(
+ '.category-description');
+ if (this.usingPreset_()) {
+ description.innerText = this.currentlyChosenPreset_;
+ Polymer.dom(description).classList.remove(
+ 'category-description-hidden');
+ } else {
+ description.innerText = '';
+ if (!Polymer.dom(description).classList.contains(
+ 'category-description-hidden')) {
+ Polymer.dom(description).classList.add('category-description-hidden');
+ }
+ }
+ },
+
+ includedAndExcludedCategories() {
+ let includedCategories = [];
+ let excludedCategories = [];
+ if (this.usingPreset_()) {
+ const allCategories = this.allCategories_();
+ for (const category in allCategories) {
+ const disabledByDefault =
+ category.indexOf('disabled-by-default-') === 0;
+ if (this.currentlyChosenPreset_.indexOf(category) >= 0) {
+ if (disabledByDefault) {
+ includedCategories.push(category);
+ }
+ } else {
+ if (!disabledByDefault) {
+ excludedCategories.push(category);
+ }
+ }
+ }
+ return {
+ included: includedCategories,
+ excluded: excludedCategories
+ };
+ }
+
+ excludedCategories = this.unselectedCategories_();
+ includedCategories = this.enabledDisabledByDefaultCategories_();
+ return {
+ included: includedCategories,
+ excluded: excludedCategories
+ };
+ },
+
+ clickRecordButton() {
+ this.recordButtonEl_.click();
+ },
+
+ onRecordButtonClicked_() {
+ this.visible = false;
+ tr.b.dispatchSimpleEvent(this, 'recordclick');
+ return false;
+ },
+
+ collectInputs_(inputs, isChecked) {
+ const inputsLength = inputs.length;
+ const categories = [];
+ for (let i = 0; i < inputsLength; ++i) {
+ const input = inputs[i];
+ if (input.checked === isChecked) {
+ categories.push(input.value);
+ }
+ }
+ return categories;
+ },
+
+ unselectedCategories_() {
+ const inputs =
+ Polymer.dom(this.enabledCategoriesContainerEl_).querySelectorAll(
+ 'input');
+ return this.collectInputs_(inputs, false);
+ },
+
+ enabledDisabledByDefaultCategories_() {
+ const inputs =
+ Polymer.dom(this.disabledCategoriesContainerEl_).querySelectorAll(
+ 'input');
+ return this.collectInputs_(inputs, true);
+ },
+
+ onVisibleChange_() {
+ if (this.visible) {
+ this.updateForm_();
+ }
+ },
+
+ buildInputs_(inputs, checkedDefault, parent) {
+ const inputsLength = inputs.length;
+ for (let i = 0; i < inputsLength; i++) {
+ const category = inputs[i];
+
+ const inputEl = document.createElement('input');
+ inputEl.type = 'checkbox';
+ inputEl.id = category;
+ inputEl.value = category;
+
+ inputEl.checked = tr.b.Settings.get(
+ category, checkedDefault, this.settings_key_);
+ inputEl.onclick = this.updateSetting_.bind(this);
+
+ const labelEl = document.createElement('label');
+ Polymer.dom(labelEl).textContent =
+ category.replace('disabled-by-default-', '');
+ Polymer.dom(labelEl).setAttribute('for', category);
+
+ const divEl = document.createElement('div');
+ Polymer.dom(divEl).appendChild(inputEl);
+ Polymer.dom(divEl).appendChild(labelEl);
+
+ Polymer.dom(parent).appendChild(divEl);
+ }
+ },
+
+ allCategories_() {
+ // Dedup the categories. We may have things in settings that are also
+ // returned when we query the category list.
+ const categorySet = {};
+ const allCategories =
+ this.categories_.concat(tr.b.Settings.keys(this.settings_key_));
+ const allCategoriesLength = allCategories.length;
+ for (let i = 0; i < allCategoriesLength; ++i) {
+ categorySet[allCategories[i]] = true;
+ }
+ return categorySet;
+ },
+
+ updateForm_() {
+ function ignoreCaseCompare(a, b) {
+ return a.toLowerCase().localeCompare(b.toLowerCase());
+ }
+
+ // Clear old categories
+ Polymer.dom(this.enabledCategoriesContainerEl_).innerHTML = '';
+ Polymer.dom(this.disabledCategoriesContainerEl_).innerHTML = '';
+
+ this.recordButtonEl_.focus();
+
+ const allCategories = this.allCategories_();
+ let categories = [];
+ let disabledCategories = [];
+ for (const category in allCategories) {
+ if (category.indexOf('disabled-by-default-') === 0) {
+ disabledCategories.push(category);
+ } else {
+ categories.push(category);
+ }
+ }
+ disabledCategories = disabledCategories.sort(ignoreCaseCompare);
+ categories = categories.sort(ignoreCaseCompare);
+
+ if (this.categories_.length === 0) {
+ this.infoBarGroup_.addMessage(
+ 'No categories found; recording will use default categories.');
+ }
+
+ this.buildInputs_(categories, true, this.enabledCategoriesContainerEl_);
+
+ if (disabledCategories.length > 0) {
+ this.disabledCategoriesContainerEl_.hidden = false;
+ this.buildInputs_(disabledCategories, false,
+ this.disabledCategoriesContainerEl_);
+ }
+ },
+
+ updateSetting_(e) {
+ const checkbox = e.target;
+ tr.b.Settings.set(checkbox.value, checkbox.checked, this.settings_key_);
+
+ // Change the current record mode to 'Manually select settings' from
+ // preset mode if and only if currently user is in preset record mode
+ // and user selects/deselects any category in 'Edit Categories' mode.
+ if (this.usingPreset_()) {
+ this.currentlyChosenPreset_ = []; /* manually select settings */
+ const categoryEl = this.querySelector(
+ '#category-preset-Manually-select-settings');
+ categoryEl.checked = true;
+ const description = Polymer.dom(this).querySelector(
+ '.category-description');
+ description.innerText = '';
+ Polymer.dom(description).classList.add('category-description-hidden');
+ }
+ },
+
+ createGroupSelectButtons_(parent) {
+ const flipInputs = function(dir) {
+ const inputs = Polymer.dom(parent).querySelectorAll('input');
+ for (let i = 0; i < inputs.length; i++) {
+ if (inputs[i].checked === dir) continue;
+ // click() is used so the settings will be correclty stored. Setting
+ // checked does not trigger the onclick (or onchange) callback.
+ inputs[i].click();
+ }
+ };
+
+ const allBtn = Polymer.dom(parent).querySelector('.all-btn');
+ allBtn.onclick = function(evt) {
+ flipInputs(true);
+ evt.preventDefault();
+ };
+
+ const noneBtn = Polymer.dom(parent).querySelector('.none-btn');
+ noneBtn.onclick = function(evt) {
+ flipInputs(false);
+ evt.preventDefault();
+ };
+ },
+
+ setWarningDialogOverlayText_(messages) {
+ const contentDiv = document.createElement('div');
+
+ for (let i = 0; i < messages.length; ++i) {
+ const messageDiv = document.createElement('div');
+ Polymer.dom(messageDiv).textContent = messages[i];
+ Polymer.dom(contentDiv).appendChild(messageDiv);
+ }
+ Polymer.dom(this.warningOverlay_).textContent = '';
+ Polymer.dom(this.warningOverlay_).appendChild(contentDiv);
+ },
+
+ createDefaultDisabledWarningDialog_(warningLink) {
+ function onClickHandler(evt) {
+ this.warningOverlay_ = tr.ui.b.Overlay();
+ this.warningOverlay_.parentEl_ = this;
+ this.warningOverlay_.title = 'Warning...';
+ this.warningOverlay_.userCanClose = true;
+ this.warningOverlay_.visible = true;
+
+ this.setWarningDialogOverlayText_([
+ 'Enabling the default disabled categories may have',
+ 'performance and memory impact while tr.c.'
+ ]);
+
+ evt.preventDefault();
+ }
+ warningLink.onclick = onClickHandler.bind(this);
+ }
+ };
+
+ return {
+ RecordSelectionDialog,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html
new file mode 100644
index 00000000000..7c62b487305
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/record_selection_dialog_test.html
@@ -0,0 +1,426 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/extras/about_tracing/record_selection_dialog.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantitate', function() {
+ const showButton = document.createElement('button');
+ Polymer.dom(showButton).textContent = 'Show record selection dialog';
+ this.addHTMLOutput(showButton);
+
+ showButton.addEventListener('click', function(e) {
+ e.stopPropagation();
+
+ const categories = [];
+ for (let i = 0; i < 30; i++) {
+ categories.push('cat-' + i);
+ }
+ for (let i = 0; i < 20; i++) {
+ categories.push('disabled-by-default-cat-' + i);
+ }
+ categories.push(
+ 'really-really-really-really-really-really-very-loong-cat');
+ categories.push('first,second,third');
+ categories.push('cc,disabled-by-default-cc.debug');
+
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = categories;
+ dlg.settings_key = 'key';
+ dlg.visible = true;
+ });
+ });
+
+ test('recordSelectionDialog_splitCategories', function() {
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories =
+ ['cc,disabled-by-default-one,cc.debug', 'two,three', 'three'];
+ dlg.settings_key = 'key';
+ dlg.currentlyChosenPreset = [];
+ dlg.updateForm_();
+
+ const expected =
+ ['"cc"', '"cc.debug"', '"disabled-by-default-one"', '"three"', '"two"'];
+
+ const labels = Polymer.dom(dlg).querySelectorAll('.categories input');
+ let results = [];
+ for (let i = 0; i < labels.length; i++) {
+ results.push('"' + labels[i].value + '"');
+ }
+ results = results.sort();
+
+ assert.deepEqual(results, expected);
+ });
+
+ test('recordSelectionDialog_UpdateForm_NoSettings', function() {
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['disabled-by-default-one', 'two', 'three'];
+ dlg.settings_key = 'key';
+ dlg.currentlyChosenPreset = [];
+ dlg.updateForm_();
+
+ const checkboxes = Polymer.dom(dlg).querySelectorAll('.categories input');
+ assert.strictEqual(checkboxes.length, 3);
+ assert.strictEqual(checkboxes[0].id, 'three');
+ assert.strictEqual(checkboxes[0].value, 'three');
+ assert.isTrue(checkboxes[0].checked);
+ assert.strictEqual(checkboxes[1].id, 'two');
+ assert.strictEqual(checkboxes[1].value, 'two');
+ assert.isTrue(checkboxes[1].checked);
+ assert.strictEqual(checkboxes[2].id, 'disabled-by-default-one');
+ assert.strictEqual(checkboxes[2].value, 'disabled-by-default-one');
+ assert.isFalse(checkboxes[2].checked);
+
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, []);
+
+ const labels = Polymer.dom(dlg).querySelectorAll('.categories label');
+ assert.strictEqual(labels.length, 3);
+ assert.strictEqual(Polymer.dom(labels[0]).textContent, 'three');
+ assert.strictEqual(Polymer.dom(labels[1]).textContent, 'two');
+ assert.strictEqual(Polymer.dom(labels[2]).textContent, 'one');
+ });
+
+ test('recordSelectionDialog_UpdateForm_Settings', function() {
+ tr.b.Settings.set('two', true, 'categories');
+ tr.b.Settings.set('three', false, 'categories');
+
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['disabled-by-default-one'];
+ dlg.settings_key = 'categories';
+ dlg.currentlyChosenPreset = [];
+ dlg.updateForm_();
+
+ const checkboxes = Polymer.dom(dlg).querySelectorAll('.categories input');
+ assert.strictEqual(checkboxes.length, 3);
+ assert.strictEqual(checkboxes[0].id, 'three');
+ assert.strictEqual(checkboxes[0].value, 'three');
+ assert.isFalse(checkboxes[0].checked);
+ assert.strictEqual(checkboxes[1].id, 'two');
+ assert.strictEqual(checkboxes[1].value, 'two');
+ assert.isTrue(checkboxes[1].checked);
+ assert.strictEqual(checkboxes[2].id, 'disabled-by-default-one');
+ assert.strictEqual(checkboxes[2].value, 'disabled-by-default-one');
+ assert.isFalse(checkboxes[2].checked);
+
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, ['three']);
+
+ const labels = Polymer.dom(dlg).querySelectorAll('.categories label');
+ assert.strictEqual(labels.length, 3);
+ assert.strictEqual(Polymer.dom(labels[0]).textContent, 'three');
+ assert.strictEqual(Polymer.dom(labels[1]).textContent, 'two');
+ assert.strictEqual(Polymer.dom(labels[2]).textContent, 'one');
+ });
+
+ test('recordSelectionDialog_UpdateForm_DisabledByDefault', function() {
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['disabled-by-default-bar', 'baz'];
+ dlg.settings_key = 'categories';
+ dlg.currentlyChosenPreset = [];
+ dlg.updateForm_();
+
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, []);
+
+ const inputs =
+ Polymer.dom(dlg).querySelector('input#disabled-by-default-bar').click();
+
+ assert.deepEqual(dlg.includedAndExcludedCategories().included,
+ ['disabled-by-default-bar']);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, []);
+
+ assert.isFalse(
+ tr.b.Settings.get('disabled-by-default-foo', false, 'categories'));
+ });
+
+ test('selectAll', function() {
+ tr.b.Settings.set('two', true, 'categories');
+ tr.b.Settings.set('three', false, 'categories');
+
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['disabled-by-default-one'];
+ dlg.settings_key = 'categories';
+ dlg.currentlyChosenPreset = [];
+ dlg.updateForm_();
+ });
+
+ test('selectNone', function() {
+ tr.b.Settings.set('two', true, 'categories');
+ tr.b.Settings.set('three', false, 'categories');
+
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['disabled-by-default-one'];
+ dlg.settings_key = 'categories';
+ dlg.currentlyChosenPreset = [];
+ dlg.updateForm_();
+
+ // Enables the three option, two already enabled.
+ Polymer.dom(dlg).querySelector('.default-enabled-categories .all-btn')
+ .click();
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, []);
+ assert.isTrue(tr.b.Settings.get('three', false, 'categories'));
+
+ // Disables three and two.
+ Polymer.dom(dlg).querySelector('.default-enabled-categories .none-btn')
+ .click();
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['three', 'two']);
+ assert.isFalse(tr.b.Settings.get('two', false, 'categories'));
+ assert.isFalse(tr.b.Settings.get('three', false, 'categories'));
+
+ // Turn categories back on so they can be ignored.
+ Polymer.dom(dlg).querySelector('.default-enabled-categories .all-btn')
+ .click();
+
+ // Enables disabled category.
+ Polymer.dom(dlg).querySelector('.default-disabled-categories .all-btn')
+ .click();
+ assert.deepEqual(dlg.includedAndExcludedCategories().included,
+ ['disabled-by-default-one']);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, []);
+ assert.isTrue(
+ tr.b.Settings.get('disabled-by-default-one', false, 'categories'));
+
+ // Turn disabled by default back off.
+ Polymer.dom(dlg).querySelector('.default-disabled-categories .none-btn')
+ .click();
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, []);
+ assert.isFalse(
+ tr.b.Settings.get('disabled-by-default-one', false, 'categories'));
+ });
+
+ test('recordSelectionDialog_noPreset', function() {
+ tr.b.Settings.set('about_tracing.record_selection_dialog_preset', []);
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ assert.isFalse(dlg.usingPreset_());
+ });
+
+ test('recordSelectionDialog_defaultPreset', function() {
+ tr.b.Settings.set('two', true, 'categories');
+ tr.b.Settings.set('three', false, 'categories');
+
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['disabled-by-default-one'];
+ dlg.settings_key = 'categories';
+ // Note: currentlyChosenPreset is not set here, so the default is used.
+ dlg.updateForm_();
+
+ // Make sure the default filter is returned.
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['three', 'two']);
+
+ // Make sure the default tracing types are returned.
+ assert.strictEqual(dlg.tracingRecordMode, 'record-until-full');
+ assert.isTrue(dlg.useSystemTracing);
+ assert.isFalse(dlg.useSampling);
+
+ // Make sure the manual settings are not visible.
+ const classList = Polymer.dom(dlg.categoriesView_).classList;
+ assert.isTrue(classList.contains('categories-column-view-hidden'));
+
+ // Verify manual settings do not modify the checkboxes.
+ const checkboxes = Polymer.dom(dlg).querySelectorAll('.categories input');
+ assert.strictEqual(checkboxes.length, 3);
+ assert.strictEqual(checkboxes[0].id, 'three');
+ assert.strictEqual(checkboxes[0].value, 'three');
+ assert.isFalse(checkboxes[0].checked);
+ assert.strictEqual(checkboxes[1].id, 'two');
+ assert.strictEqual(checkboxes[1].value, 'two');
+ assert.isTrue(checkboxes[1].checked);
+ assert.strictEqual(checkboxes[2].id, 'disabled-by-default-one');
+ assert.strictEqual(checkboxes[2].value, 'disabled-by-default-one');
+ assert.isFalse(checkboxes[2].checked);
+ });
+
+ test('recordSelectionDialog_editPreset', function() {
+ function createDialog() {
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['one', 'two', 'disabled-by-default-three'];
+ dlg.settings_key = 'categories';
+ // Note: currentlyChosenPreset is not set here, so the default is used.
+ dlg.updateForm_();
+ return dlg;
+ }
+
+ // After the dialog is created, it should be using the default preset.
+ let dlg = createDialog();
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['one', 'two']);
+ assert.isTrue(dlg.usingPreset_());
+ assert.isFalse(
+ dlg.querySelector('#category-preset-Manually-select-settings').checked);
+
+ // After clicking on "Edit Categories", the default preset should still be
+ // used.
+ dlg.onClickEditCategories();
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['one', 'two']);
+ assert.isTrue(dlg.usingPreset_());
+ assert.isFalse(
+ dlg.querySelector('#category-preset-Manually-select-settings').checked);
+
+ // After clicking on category checkbox(es), the mode should be changed to
+ // "Manually select settings".
+ Array.prototype.forEach.call(dlg.querySelectorAll('.categories input'),
+ checkbox => checkbox.click());
+ assert.deepEqual(dlg.includedAndExcludedCategories().included,
+ ['disabled-by-default-three']);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, []);
+ assert.isFalse(dlg.usingPreset_());
+ assert.isTrue(
+ dlg.querySelector('#category-preset-Manually-select-settings').checked);
+
+ // After the dialog is opened again, it should be using the default preset.
+ // More importantly, the default preset should NOT be modified.
+ dlg = createDialog();
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['one', 'two']);
+ assert.isTrue(dlg.usingPreset_());
+ assert.isFalse(
+ dlg.querySelector('#category-preset-Manually-select-settings').checked);
+ });
+
+ test('recordSelectionDialog_changePresets', function() {
+ tr.b.Settings.set('two', true, 'categories');
+ tr.b.Settings.set('three', false, 'categories');
+ tr.b.Settings.set('disabled-by-default-cc.debug', true, 'categories');
+ tr.b.Settings.set('recordSelectionDialog.tracingRecordMode',
+ 'record-as-much-as-possible');
+ tr.b.Settings.set('recordSelectionDialog.useSystemTracing', true);
+ tr.b.Settings.set('recordSelectionDialog.useSampling', false);
+
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['disabled-by-default-one'];
+ dlg.settings_key = 'categories';
+ // Note: currentlyChosenPreset is not set here, so the default is used.
+ dlg.updateForm_();
+
+ // Preset mode is on.
+ assert.isTrue(dlg.usingPreset_());
+
+ // Make sure the default filter is returned.
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['three', 'two']);
+
+ // Make sure the default tracing types are returned.
+ assert.strictEqual(dlg.tracingRecordMode, 'record-as-much-as-possible');
+ assert.isTrue(dlg.useSystemTracing);
+ assert.isFalse(dlg.useSampling);
+
+ // Make sure the manual settings are not visible.
+ const classList = Polymer.dom(dlg.categoriesView_).classList;
+ assert.isTrue(classList.contains('categories-column-view-hidden'));
+
+ // Switch to manual settings and verify the default values are not returned.
+ dlg.currentlyChosenPreset = [];
+
+ // Preset mode is off.
+ assert.isFalse(dlg.usingPreset_());
+
+ // Make sure the default filter is returned.
+ assert.deepEqual(dlg.includedAndExcludedCategories().included,
+ ['disabled-by-default-cc.debug']);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, ['three']);
+
+ // Make sure the tracing types set by catalog are returned.
+ assert.strictEqual(dlg.tracingRecordMode, 'record-as-much-as-possible');
+ assert.isTrue(dlg.useSystemTracing);
+ assert.isFalse(dlg.useSampling);
+ assert.isFalse(classList.contains('categories-column-view-hidden'));
+
+ // Switch to the graphics, rendering, and rasterization preset.
+ dlg.currentlyChosenPreset = ['blink', 'cc', 'renderer',
+ 'disabled-by-default-cc.debug'];
+ assert.deepEqual(dlg.includedAndExcludedCategories().included,
+ ['disabled-by-default-cc.debug']);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['three', 'two']);
+ });
+
+ test('recordSelectionDialog_savedPreset', function() {
+ tr.b.Settings.set('two', true, 'categories');
+ tr.b.Settings.set('three', false, 'categories');
+ tr.b.Settings.set('recordSelectionDialog.tracingRecordMode',
+ 'record-continuously');
+ tr.b.Settings.set('recordSelectionDialog.useSystemTracing', true);
+ tr.b.Settings.set('recordSelectionDialog.useSampling', true);
+ tr.b.Settings.set('tr.ui.e.about_tracing.record_selection_dialog_preset',
+ ['blink', 'cc', 'renderer', 'cc.debug']);
+
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.categories = ['disabled-by-default-one'];
+ dlg.settings_key = 'categories';
+ dlg.updateForm_();
+
+ // Make sure the correct filter is returned.
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['three', 'two']);
+
+ // Make sure the correct tracing types are returned.
+ assert.strictEqual(dlg.tracingRecordMode, 'record-continuously');
+ assert.isTrue(dlg.useSystemTracing);
+ assert.isTrue(dlg.useSampling);
+
+ // Make sure the manual settings are not visible.
+ const classList = Polymer.dom(dlg.categoriesView_).classList;
+ assert.isTrue(classList.contains('categories-column-view-hidden'));
+
+ // Switch to manual settings and verify the default values are not returned.
+ dlg.currentlyChosenPreset = [];
+ assert.deepEqual(dlg.includedAndExcludedCategories().included, []);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded, ['three']);
+ assert.strictEqual(dlg.tracingRecordMode, 'record-continuously');
+ assert.isTrue(dlg.useSystemTracing);
+ assert.isTrue(dlg.useSampling);
+ assert.isFalse(classList.contains('categories-column-view-hidden'));
+ });
+
+ test('recordSelectionDialog_categoryFilters', function() {
+ tr.b.Settings.set('default1', true, 'categories');
+ tr.b.Settings.set('disabled1', false, 'categories');
+ tr.b.Settings.set('disabled-by-default-cc.disabled2', false, 'categories');
+ tr.b.Settings.set('input', true, 'categories');
+ tr.b.Settings.set('blink', true, 'categories');
+ tr.b.Settings.set('cc', false, 'categories');
+ tr.b.Settings.set('disabled-by-default-cc.debug', true, 'categories');
+
+ const dlg = new tr.ui.e.about_tracing.RecordSelectionDialog();
+ dlg.settings_key = 'categories';
+ dlg.categories = [];
+ dlg.currentlyChosenPreset = [];
+ dlg.updateForm_();
+
+ assert.deepEqual(dlg.includedAndExcludedCategories().included,
+ ['disabled-by-default-cc.debug']);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['cc', 'disabled1']);
+
+ // Switch to the graphics, rendering, and rasterization preset.
+ dlg.currentlyChosenPreset = ['blink', 'cc', 'renderer',
+ 'disabled-by-default-cc.debug'];
+ assert.deepEqual(dlg.includedAndExcludedCategories().included,
+ ['disabled-by-default-cc.debug']);
+ assert.deepEqual(dlg.includedAndExcludedCategories().excluded,
+ ['default1', 'disabled1', 'input']);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/tracing_controller_client.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/tracing_controller_client.html
new file mode 100644
index 00000000000..c00bbe915e4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/tracing_controller_client.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ /**
+ * Communicates with content/browser/tracing_controller_impl.cc
+ *
+ * @constructor
+ */
+ class TracingControllerClient {
+ beginMonitoring(monitoringOptions) { }
+ endMonitoring() { }
+ captureMonitoring() { }
+ getMonitoringStatus() { }
+ getCategories() { }
+ beginRecording(recordingOptions) { }
+ beginGetBufferPercentFull() { }
+ endRecording() { }
+ defaultTraceName() { }
+ }
+
+ return {
+ TracingControllerClient,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/xhr_based_tracing_controller_client.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/xhr_based_tracing_controller_client.html
new file mode 100644
index 00000000000..d2c6adcac2a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/about_tracing/xhr_based_tracing_controller_client.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import"
+ href="/tracing/ui/extras/about_tracing/tracing_controller_client.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.about_tracing', function() {
+ const Base64 = tr.b.Base64;
+
+ function beginXhr(method, path, data) {
+ if (data === undefined) data = null;
+
+ return new Promise(function(resolve, reject) {
+ const req = new XMLHttpRequest();
+ if (method !== 'POST' && data !== null) {
+ throw new Error('Non-POST should have data==null');
+ }
+ req.open(method, path, true);
+ req.onreadystatechange = function(e) {
+ if (req.readyState === 4) {
+ window.setTimeout(function() {
+ if (req.status === 200 && req.responseText !== '##ERROR##') {
+ resolve(req.responseText);
+ } else {
+ reject(new Error('Error occured at ' + path));
+ }
+ }, 0);
+ }
+ };
+ req.send(data);
+ });
+ }
+
+ /**
+ * @constructor
+ */
+ function XhrBasedTracingControllerClient() { }
+
+ XhrBasedTracingControllerClient.prototype = {
+ __proto__: tr.ui.e.about_tracing.TracingControllerClient.prototype,
+
+ beginMonitoring(monitoringOptions) {
+ const monitoringOptionsB64 = Base64.btoa(JSON.stringify(
+ monitoringOptions));
+ return beginXhr('GET', '/json/begin_monitoring?' + monitoringOptionsB64);
+ },
+
+ endMonitoring() {
+ return beginXhr('GET', '/json/end_monitoring');
+ },
+
+ captureMonitoring() {
+ return beginXhr('GET', '/json/capture_monitoring_compressed').then(
+ function(data) {
+ const decodedSize = Base64.getDecodedBufferLength(data);
+ const buffer = new ArrayBuffer(decodedSize);
+ Base64.DecodeToTypedArray(data, new DataView(buffer));
+ return buffer;
+ }
+ );
+ },
+
+ getMonitoringStatus() {
+ return beginXhr('GET', '/json/get_monitoring_status').then(
+ function(monitoringOptionsB64) {
+ return JSON.parse(Base64.atob(monitoringOptionsB64));
+ });
+ },
+
+ getCategories() {
+ return beginXhr('GET', '/json/categories').then(
+ function(json) {
+ return JSON.parse(json);
+ });
+ },
+
+ beginRecording(recordingOptions) {
+ const recordingOptionsB64 = Base64.btoa(JSON.stringify(recordingOptions));
+ return beginXhr('GET', '/json/begin_recording?' +
+ recordingOptionsB64);
+ },
+
+ beginGetBufferPercentFull() {
+ return beginXhr('GET', '/json/get_buffer_percent_full');
+ },
+
+ endRecording() {
+ return beginXhr('GET', '/json/end_recording_compressed').then(
+ function(data) {
+ const decodedSize = Base64.getDecodedBufferLength(data);
+ const buffer = new ArrayBuffer(decodedSize);
+ Base64.DecodeToTypedArray(data, new DataView(buffer));
+ return buffer;
+ }
+ );
+ },
+
+ defaultTraceName() {
+ return 'trace.json.gz';
+ }
+ };
+
+ return {
+ XhrBasedTracingControllerClient,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/cc.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/cc.html
new file mode 100644
index 00000000000..79ba7e593c0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/cc.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/cc.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/display_item_list_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/picture_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/raster_task_selection.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/raster_task_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/tile_view.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger.html
new file mode 100644
index 00000000000..f8bfd671355
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger.html
@@ -0,0 +1,451 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<link rel="import" href="/tracing/ui/base/hotkey_controller.html">
+<link rel="import" href="/tracing/ui/base/info_bar.html">
+<link rel="import" href="/tracing/ui/base/list_view.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_selector.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/display_item_list_item.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/picture_ops_list_view.html">
+
+<template id="tr-ui-e-chrome-cc-display-item-debugger-template">
+ <left-panel>
+ <display-item-info>
+ <header>
+ <span class='title'>Display Item List</span>
+ <span class='size'></span>
+ <div class='export'>
+ <input class='dlfilename' type='text' value='displayitemlist.json' />
+ <button class='dlexport'>Export display item list</button>
+ </div>
+ <div class='export'>
+ <input class='skpfilename' type='text' value='skpicture.skp' />
+ <button class='skpexport'>Export list as SkPicture</button>
+ </div>
+ </header>
+ </display-item-info>
+ </left-panel>
+ <right-panel>
+ <raster-area>
+ <canvas-scroller>
+ <canvas></canvas>
+ </canvas-scroller>
+ </raster-area>
+ </right-panel>
+</template>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ /**
+ * DisplayItemDebugger is a view of a DisplayItemListSnapshot for inspecting
+ * a display item list and the pictures within it.
+ *
+ * @constructor
+ */
+ const DisplayItemDebugger = tr.ui.b.define(
+ 'tr-ui-e-chrome-cc-display-item-debugger');
+
+ DisplayItemDebugger.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ const node = tr.ui.b.instantiateTemplate(
+ '#tr-ui-e-chrome-cc-display-item-debugger-template', THIS_DOC);
+
+ Polymer.dom(this).appendChild(node);
+ this.style.flexGrow = 1;
+ this.style.flexShrink = 1;
+ this.style.flexBasis = 'auto';
+ this.style.display = 'flex';
+ this.style.minWidth = 0;
+
+ this.pictureAsImageData_ = undefined;
+ this.zoomScaleValue_ = 1;
+
+ this.sizeInfo_ = Polymer.dom(this).querySelector('.size');
+ this.rasterArea_ = Polymer.dom(this).querySelector('raster-area');
+ this.rasterArea_.style.flexGrow = 1;
+ this.rasterArea_.style.flexShrink = 1;
+ this.rasterArea_.style.flexBasis = 'auto';
+ this.rasterArea_.style.backgroundColor = '#ddd';
+ this.rasterArea_.style.minHeight = '200px';
+ this.rasterArea_.style.minWidth = '200px';
+ this.rasterArea_.style.paddingLeft = '5px';
+ this.rasterArea_.style.display = 'flex';
+ this.rasterArea_.style.flexDirection = 'column';
+ this.rasterCanvas_ =
+ Polymer.dom(this.rasterArea_).querySelector('canvas');
+ this.rasterCtx_ = this.rasterCanvas_.getContext('2d');
+
+ const canvasScroller = Polymer.dom(this).querySelector('canvas-scroller');
+ canvasScroller.style.flexGrow = 1;
+ canvasScroller.style.flexShrink = 1;
+ canvasScroller.style.flexBasis = 'auto';
+ canvasScroller.style.minWidth = 0;
+ canvasScroller.style.minHeight = 0;
+ canvasScroller.style.overflow = 'auto';
+
+ this.trackMouse_();
+
+ this.displayItemInfo_ =
+ Polymer.dom(this).querySelector('display-item-info');
+ this.displayItemInfo_.addEventListener(
+ 'click', this.onDisplayItemInfoClick_.bind(this), false);
+
+ this.displayItemListView_ = new tr.ui.b.ListView();
+ this.displayItemListView_.addEventListener('selection-changed',
+ this.onDisplayItemListSelection_.bind(this));
+ Polymer.dom(this.displayItemInfo_).appendChild(this.displayItemListView_);
+
+ this.displayListFilename_ =
+ Polymer.dom(this).querySelector('.dlfilename');
+ this.displayListExportButton_ =
+ Polymer.dom(this).querySelector('.dlexport');
+ this.displayListExportButton_.addEventListener(
+ 'click', this.onExportDisplayListClicked_.bind(this));
+
+ this.skpFilename_ = Polymer.dom(this).querySelector('.skpfilename');
+ this.skpExportButton_ = Polymer.dom(this).querySelector('.skpexport');
+ this.skpExportButton_.addEventListener(
+ 'click', this.onExportSkPictureClicked_.bind(this));
+
+ const leftPanel = Polymer.dom(this).querySelector('left-panel');
+ leftPanel.style.flexGrow = 0;
+ leftPanel.style.flexShrink = 0;
+ leftPanel.style.flexBasis = 'auto';
+ leftPanel.style.minWidth = '200px';
+ leftPanel.style.overflow = 'auto';
+
+ leftPanel.children[0].paddingTop = '2px';
+ leftPanel.children[0].children[0].style.borderBottom = '1px solid #555';
+
+ const leftPanelTitle = leftPanel.querySelector('.title');
+ leftPanelTitle.style.fontWeight = 'bold';
+ leftPanelTitle.style.marginLeft = '5px';
+ leftPanelTitle.style.marginright = '5px';
+
+ for (const div of leftPanel.querySelectorAll('.export')) {
+ div.style.margin = '5px';
+ }
+
+ const middleDragHandle = document.createElement('tr-ui-b-drag-handle');
+ middleDragHandle.style.flexGrow = 0;
+ middleDragHandle.style.flexShrink = 0;
+ middleDragHandle.style.flexBasis = 'auto';
+ middleDragHandle.horizontal = false;
+ middleDragHandle.target = leftPanel;
+
+ const rightPanel = Polymer.dom(this).querySelector('right-panel');
+ rightPanel.style.display = 'flex';
+ rightPanel.style.flexGrow = 1;
+ rightPanel.style.flexShrink = 1;
+ rightPanel.style.flexBasis = 'auto';
+ rightPanel.style.minWidth = 0;
+
+ this.infoBar_ = document.createElement('tr-ui-b-info-bar');
+ Polymer.dom(this.rasterArea_).insertBefore(this.infoBar_, canvasScroller);
+
+ Polymer.dom(this).insertBefore(middleDragHandle, rightPanel);
+
+ this.picture_ = undefined;
+
+ this.pictureOpsListView_ = new tr.ui.e.chrome.cc.PictureOpsListView();
+ this.pictureOpsListView_.style.flexGrow = 0;
+ this.pictureOpsListView_.style.flexShrink = 0;
+ this.pictureOpsListView_.style.flexBasis = 'auto';
+ this.pictureOpsListView_.style.overflow = 'auto';
+ this.pictureOpsListView_.style.minWidth = '100px';
+ Polymer.dom(rightPanel).insertBefore(
+ this.pictureOpsListView_, this.rasterArea_);
+
+ this.pictureOpsListDragHandle_ =
+ document.createElement('tr-ui-b-drag-handle');
+ this.pictureOpsListDragHandle_.horizontal = false;
+ this.pictureOpsListDragHandle_.target = this.pictureOpsListView_;
+ Polymer.dom(rightPanel).insertBefore(
+ this.pictureOpsListDragHandle_, this.rasterArea_);
+ },
+
+ get picture() {
+ return this.picture_;
+ },
+
+ set displayItemList(displayItemList) {
+ this.displayItemList_ = displayItemList;
+ this.picture = this.displayItemList_;
+
+ this.displayItemListView_.clear();
+ this.displayItemList_.items.forEach(function(item) {
+ const listItem = document.createElement(
+ 'tr-ui-e-chrome-cc-display-item-list-item');
+ listItem.data = item;
+ Polymer.dom(this.displayItemListView_).appendChild(listItem);
+ }.bind(this));
+ },
+
+ set picture(picture) {
+ this.picture_ = picture;
+
+ // Hide the ops list if we are showing the "main" display item list.
+ const showOpsList = picture && picture !== this.displayItemList_;
+ this.updateDrawOpsList_(showOpsList);
+
+ if (picture) {
+ const size = this.getRasterCanvasSize_();
+ this.rasterCanvas_.width = size.width;
+ this.rasterCanvas_.height = size.height;
+ }
+
+ const bounds = this.rasterArea_.getBoundingClientRect();
+ const selectorBounds = this.mouseModeSelector_.getBoundingClientRect();
+ this.mouseModeSelector_.pos = {
+ x: (bounds.right - selectorBounds.width - 10),
+ y: bounds.top
+ };
+
+ this.rasterize_();
+
+ this.scheduleUpdateContents_();
+ },
+
+ getRasterCanvasSize_() {
+ const style = window.getComputedStyle(this.rasterArea_);
+ let width = parseInt(style.width);
+ let height = parseInt(style.height);
+ if (this.picture_) {
+ width = Math.max(width, this.picture_.layerRect.width);
+ height = Math.max(height, this.picture_.layerRect.height);
+ }
+
+ return {
+ width,
+ height
+ };
+ },
+
+ scheduleUpdateContents_() {
+ if (this.updateContentsPending_) return;
+
+ this.updateContentsPending_ = true;
+ tr.b.requestAnimationFrameInThisFrameIfPossible(
+ this.updateContents_.bind(this)
+ );
+ },
+
+ updateContents_() {
+ this.updateContentsPending_ = false;
+
+ if (this.picture_) {
+ Polymer.dom(this.sizeInfo_).textContent = '(' +
+ this.picture_.layerRect.width + ' x ' +
+ this.picture_.layerRect.height + ')';
+ }
+
+ // Return if picture hasn't finished rasterizing.
+ if (!this.pictureAsImageData_) return;
+
+ this.infoBar_.visible = false;
+ this.infoBar_.removeAllButtons();
+ if (this.pictureAsImageData_.error) {
+ this.infoBar_.message = 'Cannot rasterize...';
+ this.infoBar_.addButton('More info...', function(e) {
+ const overlay = new tr.ui.b.Overlay();
+ Polymer.dom(overlay).textContent = this.pictureAsImageData_.error;
+ overlay.visible = true;
+ e.stopPropagation();
+ return false;
+ }.bind(this));
+ this.infoBar_.visible = true;
+ }
+
+ this.drawPicture_();
+ },
+
+ drawPicture_() {
+ const size = this.getRasterCanvasSize_();
+ if (size.width !== this.rasterCanvas_.width) {
+ this.rasterCanvas_.width = size.width;
+ }
+ if (size.height !== this.rasterCanvas_.height) {
+ this.rasterCanvas_.height = size.height;
+ }
+
+ this.rasterCtx_.clearRect(0, 0, size.width, size.height);
+
+ if (!this.picture_ || !this.pictureAsImageData_.imageData) return;
+
+ const imgCanvas = this.pictureAsImageData_.asCanvas();
+ const w = imgCanvas.width;
+ const h = imgCanvas.height;
+ this.rasterCtx_.drawImage(imgCanvas, 0, 0, w, h,
+ 0, 0, w * this.zoomScaleValue_,
+ h * this.zoomScaleValue_);
+ },
+
+ rasterize_() {
+ if (this.picture_) {
+ this.picture_.rasterize(
+ {
+ showOverdraw: false
+ },
+ this.onRasterComplete_.bind(this));
+ }
+ },
+
+ onRasterComplete_(pictureAsImageData) {
+ this.pictureAsImageData_ = pictureAsImageData;
+ this.scheduleUpdateContents_();
+ },
+
+ onDisplayItemListSelection_(e) {
+ const selected = this.displayItemListView_.selectedElement;
+
+ if (!selected) {
+ this.picture = this.displayItemList_;
+ return;
+ }
+
+ const index = Array.prototype.indexOf.call(
+ this.displayItemListView_.children, selected);
+ const displayItem = this.displayItemList_.items[index];
+ if (displayItem && displayItem.skp64) {
+ this.picture = new tr.e.cc.Picture(
+ displayItem.skp64, this.displayItemList_.layerRect);
+ } else {
+ this.picture = undefined;
+ }
+ },
+
+ onDisplayItemInfoClick_(e) {
+ if (e && e.target === this.displayItemInfo_) {
+ this.displayItemListView_.selectedElement = undefined;
+ }
+ },
+
+ updateDrawOpsList_(showOpsList) {
+ if (showOpsList) {
+ this.pictureOpsListView_.picture = this.picture_;
+ if (this.pictureOpsListView_.numOps > 0) {
+ this.pictureOpsListView_.style.display = 'block';
+ this.pictureOpsListDragHandle_.style.display = 'block';
+ }
+ } else {
+ this.pictureOpsListView_.style.display = 'none';
+ this.pictureOpsListDragHandle_.style.display = 'none';
+ }
+ },
+
+ trackMouse_() {
+ this.mouseModeSelector_ = document.createElement(
+ 'tr-ui-b-mouse-mode-selector');
+ this.mouseModeSelector_.targetElement = this.rasterArea_;
+ Polymer.dom(this.rasterArea_).appendChild(this.mouseModeSelector_);
+
+ this.mouseModeSelector_.supportedModeMask =
+ tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;
+ this.mouseModeSelector_.mode = tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;
+ this.mouseModeSelector_.defaultMode = tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;
+ this.mouseModeSelector_.settingsKey = 'pictureDebugger.mouseModeSelector';
+
+ this.mouseModeSelector_.addEventListener('beginzoom',
+ this.onBeginZoom_.bind(this));
+ this.mouseModeSelector_.addEventListener('updatezoom',
+ this.onUpdateZoom_.bind(this));
+ this.mouseModeSelector_.addEventListener('endzoom',
+ this.onEndZoom_.bind(this));
+ },
+
+ onBeginZoom_(e) {
+ this.isZooming_ = true;
+
+ this.lastMouseViewPos_ = this.extractRelativeMousePosition_(e);
+
+ e.preventDefault();
+ },
+
+ onUpdateZoom_(e) {
+ if (!this.isZooming_) return;
+
+ const currentMouseViewPos = this.extractRelativeMousePosition_(e);
+
+ // Take the distance the mouse has moved and we want to zoom at about
+ // 1/1000th of that speed. 0.01 feels jumpy. This could possibly be tuned
+ // more if people feel it's too slow.
+ this.zoomScaleValue_ +=
+ ((this.lastMouseViewPos_.y - currentMouseViewPos.y) * 0.001);
+ this.zoomScaleValue_ = Math.max(this.zoomScaleValue_, 0.1);
+
+ this.drawPicture_();
+
+ this.lastMouseViewPos_ = currentMouseViewPos;
+ },
+
+ onEndZoom_(e) {
+ this.lastMouseViewPos_ = undefined;
+ this.isZooming_ = false;
+ e.preventDefault();
+ },
+
+ extractRelativeMousePosition_(e) {
+ return {
+ x: e.clientX - this.rasterArea_.offsetLeft,
+ y: e.clientY - this.rasterArea_.offsetTop
+ };
+ },
+
+ saveFile_(filename, rawData) {
+ if (!rawData) return;
+
+ // Convert this String into an Uint8Array
+ const length = rawData.length;
+ const arrayBuffer = new ArrayBuffer(length);
+ const uint8Array = new Uint8Array(arrayBuffer);
+ for (let c = 0; c < length; c++) {
+ uint8Array[c] = rawData.charCodeAt(c);
+ }
+
+ // Create a blob URL from the binary array.
+ const blob = new Blob([uint8Array], {type: 'application/octet-binary'});
+ const blobUrl = window.URL.createObjectURL(blob);
+
+ // Create a link and click on it.
+ const link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
+ link.href = blobUrl;
+ link.download = filename;
+ const event = document.createEvent('MouseEvents');
+ event.initMouseEvent(
+ 'click', true, false, window, 0, 0, 0, 0, 0,
+ false, false, false, false, 0, null);
+ link.dispatchEvent(event);
+ },
+
+ onExportDisplayListClicked_() {
+ const rawData = JSON.stringify(this.displayItemList_.items);
+ this.saveFile_(this.displayListFilename_.value, rawData);
+ },
+
+ onExportSkPictureClicked_() {
+ const rawData = tr.b.Base64.atob(this.picture_.getBase64SkpData());
+ this.saveFile_(this.skpFilename_.value, rawData);
+ }
+ };
+
+ return {
+ DisplayItemDebugger,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html
new file mode 100644
index 00000000000..c10d6995db3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_debugger_test.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/display_item_list.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/display_item_debugger.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const displayItemList = new tr.e.cc.DisplayItemListSnapshot(
+ {id: '31415'},
+ 10,
+ {
+ 'params': {
+ 'layer_rect': [-15, -15, 46, 833],
+ 'items': [
+ 'BeginClipDisplayItem',
+ 'EndClipDisplayItem'
+ ]
+ },
+ 'skp64': '[another skia picture in base64]'});
+ displayItemList.preInitialize();
+ displayItemList.initialize();
+
+ const dbg = new tr.ui.e.chrome.cc.DisplayItemDebugger();
+ this.addHTMLOutput(dbg);
+ assert.isUndefined(dbg.displayItemList_);
+ assert.isUndefined(dbg.picture_);
+ dbg.displayItemList = displayItemList;
+ assert.isDefined(dbg.displayItemList_);
+ assert.isDefined(dbg.picture_);
+ assert.strictEqual(dbg.displayItemList_.items.length, 2);
+ dbg.style.border = '1px solid black';
+ });
+
+ test('selections', function() {
+ const displayItemList = new tr.e.cc.DisplayItemListSnapshot(
+ {id: '31415'},
+ 10,
+ {
+ 'params': {
+ 'layer_rect': [-15, -15, 46, 833],
+ 'items': [
+ 'BeginClipDisplayItem',
+ 'TransformDisplayItem',
+ {
+ 'name': 'DrawingDisplayItem',
+ 'skp64': '[skia picture in base64]',
+ },
+ 'EndTransformDisplayItem',
+ 'EndClipDisplayItem'
+ ]
+ },
+ 'skp64': '[another skia picture in base64]'});
+ displayItemList.preInitialize();
+ displayItemList.initialize();
+
+ const dbg = new tr.ui.e.chrome.cc.DisplayItemDebugger();
+ this.addHTMLOutput(dbg);
+ dbg.displayItemList = displayItemList;
+ assert.isDefined(dbg.displayItemList_);
+ assert.isDefined(dbg.picture_);
+ assert.strictEqual(dbg.displayItemList_.items.length, 5);
+
+ const initialPicture = dbg.picture_;
+ assert.isAbove(initialPicture.guid, 0);
+
+ // Select the drawing display item and make sure the picture updates.
+ const listView = dbg.displayItemListView_;
+ listView.selectedElement = listView.getElementByIndex(3);
+ let updatedPicture = dbg.picture_;
+ assert.isAbove(updatedPicture.guid, 0);
+ assert.notEqual(initialPicture.guid, updatedPicture.guid);
+
+ // Select the TransformDisplayItem and make sure the picture is blank.
+ listView.selectedElement = listView.getElementByIndex(2);
+ assert.isUndefined(dbg.picture_);
+
+ // Deselect a list item and make sure the picture is reset to the original.
+ listView.selectedElement = undefined;
+ updatedPicture = dbg.picture_;
+ assert.isAbove(updatedPicture.guid, 0);
+ assert.strictEqual(initialPicture.guid, updatedPicture.guid);
+
+ dbg.style.border = '1px solid black';
+ });
+
+ test('export', function() {
+ const displayItemList = new tr.e.cc.DisplayItemListSnapshot(
+ {id: '31415'},
+ 10,
+ {
+ 'params': {
+ 'layer_rect': [-15, -15, 46, 833],
+ 'items': [
+ 'BeginClipDisplayItem',
+ 'EndClipDisplayItem'
+ ]
+ },
+ 'skp64': 'c2twaWN0dXJl'});
+ displayItemList.preInitialize();
+ displayItemList.initialize();
+
+ const dbg = new tr.ui.e.chrome.cc.DisplayItemDebugger();
+ this.addHTMLOutput(dbg);
+ dbg.displayItemList = displayItemList;
+
+ let onSaveDisplayListCalled = false;
+ dbg.saveFile_ = function(filename, rawData) {
+ onSaveDisplayListCalled = true;
+ assert.strictEqual(filename, 'displayitemlist.json');
+ assert.strictEqual(
+ rawData, '["BeginClipDisplayItem","EndClipDisplayItem"]');
+ };
+ dbg.onExportDisplayListClicked_();
+ assert(onSaveDisplayListCalled);
+
+ let onSaveSkPictureCalled = false;
+ dbg.saveFile_ = function(filename, rawData) {
+ onSaveSkPictureCalled = true;
+ assert.strictEqual(filename, 'skpicture.skp');
+ assert.strictEqual(rawData, 'skpicture');
+ };
+ dbg.onExportSkPictureClicked_();
+ assert(onSaveSkPictureCalled);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_list_item.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_list_item.html
new file mode 100644
index 00000000000..3024e8d2d22
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_list_item.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+An element displaying basic information about a display item in a list view.
+-->
+<dom-module id='tr-ui-e-chrome-cc-display-item-list-item'>
+ <template>
+ <style>
+ :host {
+ border-bottom: 1px solid #555;
+ display: block;
+ font-size: 12px;
+ padding: 3px 5px;
+ }
+
+ :host(:hover) {
+ background-color: #f0f0f0;
+ cursor: pointer;
+ }
+
+ .header {
+ font-weight: bold;
+ margin: 2px 0;
+ }
+
+ .header > .extra {
+ background-color: #777;
+ border-radius: 4px;
+ color: white;
+ margin: 0 6px;
+ text-decoration: none;
+ padding: 2px 4px;
+ }
+
+ .raw-details {
+ white-space: pre-wrap;
+ }
+
+ .details > dl {
+ margin: 0;
+ }
+
+ :host(:not([selected])) .details {
+ display: none;
+ }
+ </style>
+ <div class="header">
+ {{name}}
+ <template is="dom-if" if="{{_computeIfSKP(richDetails)}}">
+ <a class="extra" href$="{{_computeHref(richDetails)}}"
+ download="drawing.skp" on-click="{{stopPropagation}}">SKP</a>
+ </template>
+ </div>
+ <div class="details">
+ <template is="dom-if" if="{{rawDetails}}">
+ <div class="raw-details">{{rawDetails}}</div>
+ </template>
+ <template is="dom-if" if="{{richDetails}}">
+ <dl>
+ <template is="dom-if" if="{{richDetails.visualRect}}">
+ <dt>Visual rect</dt>
+ <dd>{{richDetails.visualRect.x}},{{richDetails.visualRect.y}}
+ {{richDetails.visualRect.width}}&times;{{richDetails.visualRect.height}}
+ </dd>
+ </template>
+ </dl>
+ </template>
+ </div>
+ </template>
+<script>
+'use strict';
+(function() {
+ // Extracts the "type" and "details" parts of the unstructured (plaintext)
+ // display item format, even if the details span multiple lines.
+ // For example, given "FooDisplayItem type=hello\nworld", produces
+ // "FooDisplayItem" as the first capture and "type=hello\nworld" as the
+ // second. Either capture could be the empty string, but this regex will
+ // still successfully match.
+ const DETAILS_SPLIT_REGEX = /^(\S*)\s*([\S\s]*)$/;
+
+ Polymer({
+ is: 'tr-ui-e-chrome-cc-display-item-list-item',
+
+ created() {
+ // TODO(charliea): Why is setAttribute necessary here but not below? We
+ // should reach out to the Polymer team to figure out.
+ Polymer.dom(this).setAttribute('name', '');
+ Polymer.dom(this).setAttribute('rawDetails', '');
+ Polymer.dom(this).setAttribute('richDetails', undefined);
+ Polymer.dom(this).setAttribute('data_', undefined);
+ },
+
+ get data() {
+ return this.data_;
+ },
+
+ set data(data) {
+ this.data_ = data;
+
+ if (!data) {
+ this.name = 'DATA MISSING';
+ this.rawDetails = '';
+ this.richDetails = undefined;
+ } else if (typeof data === 'string') {
+ const match = data.match(DETAILS_SPLIT_REGEX);
+ this.name = match[1];
+ this.rawDetails = match[2];
+ this.richDetails = undefined;
+ } else {
+ this.name = data.name;
+ this.rawDetails = '';
+ this.richDetails = data;
+ }
+ },
+
+ stopPropagation(e) {
+ e.stopPropagation();
+ },
+
+ _computeIfSKP(richDetails) {
+ return richDetails && richDetails.skp64;
+ },
+
+ _computeHref(richDetails) {
+ return 'data:application/octet-stream;base64,' + richDetails.skp64;
+ }
+ });
+})();
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_list_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_list_view.html
new file mode 100644
index 00000000000..97598aaf3a7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/display_item_list_view.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/display_item_list.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/display_item_debugger.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ /*
+ * Displays a display item snapshot in a human readable form.
+ * @constructor
+ */
+ const DisplayItemSnapshotView = tr.ui.b.define(
+ 'tr-ui-e-chrome-cc-display-item-list-view',
+ tr.ui.analysis.ObjectSnapshotView);
+
+ DisplayItemSnapshotView.prototype = {
+ __proto__: tr.ui.analysis.ObjectSnapshotView.prototype,
+
+ decorate() {
+ this.style.display = 'flex';
+ this.style.flexGrow = 1;
+ this.style.flexShrink = 1;
+ this.style.flexBasis = 'auto';
+ this.style.minWidth = 0;
+ this.displayItemDebugger_ = new tr.ui.e.chrome.cc.DisplayItemDebugger();
+ this.displayItemDebugger_.style.flexGrow = 1;
+ this.displayItemDebugger_.style.flexShrink = 1;
+ this.displayItemDebugger_.style.flexBasis = 'auto';
+ this.displayItemDebugger_.style.minWidth = 0;
+ Polymer.dom(this).appendChild(this.displayItemDebugger_);
+ },
+
+ updateContents() {
+ if (this.objectSnapshot_ && this.displayItemDebugger_) {
+ this.displayItemDebugger_.displayItemList = this.objectSnapshot_;
+ }
+ }
+ };
+
+ tr.ui.analysis.ObjectSnapshotView.register(
+ DisplayItemSnapshotView,
+ {
+ typeNames: ['cc::DisplayItemList'],
+ showInstances: false
+ });
+
+ return {
+ DisplayItemSnapshotView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/images/input-event.png b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/images/input-event.png
new file mode 100644
index 00000000000..a2b7710d3c4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/images/input-event.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/images/input-event.svg b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/images/input-event.svg
new file mode 100644
index 00000000000..00531ac68d7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/images/input-event.svg
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="New document 1">
+ <defs
+ id="defs4">
+ <filter
+ inkscape:collect="always"
+ id="filter3791">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.7246316"
+ id="feGaussianBlur3793" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="195.13782"
+ inkscape:cy="982.30556"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1215"
+ inkscape:window-height="860"
+ inkscape:window-x="2219"
+ inkscape:window-y="113"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <g
+ id="g3882"
+ style="opacity:0.5"
+ inkscape:export-filename="/tmp/input-event.png"
+ inkscape:export-xdpi="82.07"
+ inkscape:export-ydpi="82.07">
+ <path
+ transform="matrix(1.0152631,0,0,1.0152631,-0.71357503,0.46150497)"
+ sodipodi:type="arc"
+ style="opacity:0.50934604000000006;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter3791);enable-background:accumulate"
+ id="path3755"
+ sodipodi:cx="177.78685"
+ sodipodi:cy="100.79848"
+ sodipodi:rx="42.426407"
+ sodipodi:ry="42.426407"
+ d="m 220.21326,100.79848 a 42.426407,42.426407 0 1 1 -84.85282,0 42.426407,42.426407 0 1 1 84.85282,0 z" />
+ <path
+ transform="translate(-2,-2)"
+ d="m 220.21326,100.79848 a 42.426407,42.426407 0 1 1 -84.85282,0 42.426407,42.426407 0 1 1 84.85282,0 z"
+ sodipodi:ry="42.426407"
+ sodipodi:rx="42.426407"
+ sodipodi:cy="100.79848"
+ sodipodi:cx="177.78685"
+ id="path2985"
+ style="color:#000000;fill:#d4d4d4;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path3853"
+ d="m 175.28125,96.03125 0,8.46875 1,0 0,-8.46875 -1,0 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path3859"
+ d="m 171.53125,99.75 0,1 8.46875,0 0,-1 -8.46875,0 z"
+ style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" />
+ </g>
+ <path
+ transform="matrix(1.2923213,0,0,1.2923213,-53.970887,-31.465544)"
+ d="m 220.21326,100.79848 a 42.426407,42.426407 0 1 1 -84.85282,0 42.426407,42.426407 0 1 1 84.85282,0 z"
+ sodipodi:ry="42.426407"
+ sodipodi:rx="42.426407"
+ sodipodi:cy="100.79848"
+ sodipodi:cx="177.78685"
+ id="path3867"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc"
+ inkscape:export-filename="/tmp/input-event.png"
+ inkscape:export-xdpi="82.07"
+ inkscape:export-ydpi="82.07" />
+ </g>
+</svg>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_picker.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_picker.html
new file mode 100644
index 00000000000..9f81199e358
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_picker.html
@@ -0,0 +1,336 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/extras/chrome/cc/constants.html">
+<link rel="import" href="/tracing/extras/chrome/cc/layer_tree_host_impl.html">
+<link rel="import" href="/tracing/extras/chrome/cc/util.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<link rel="import" href="/tracing/ui/base/list_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/selection.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ const constants = tr.e.cc.constants;
+ const RENDER_PASS_QUADS =
+ Math.max(constants.ACTIVE_TREE, constants.PENDING_TREE) + 1;
+
+ /**
+ * @constructor
+ */
+ const LayerPicker = tr.ui.b.define('tr-ui-e-chrome-cc-layer-picker');
+
+ LayerPicker.prototype = {
+ __proto__: HTMLUnknownElement.prototype,
+
+ decorate() {
+ this.lthi_ = undefined;
+ this.controls_ = document.createElement('top-controls');
+ this.renderPassQuads_ = false;
+
+ this.style.display = 'flex';
+ this.style.flexDirection = 'column';
+ this.controls_.style.flexGrow = 0;
+ this.controls_.style.flexShrink = 0;
+ this.controls_.style.flexBasis = 'auto';
+ this.controls_.style.backgroundImage =
+ '-webkit-gradient(linear, 0 0, 100% 0, from(#E5E5E5), to(#D1D1D1))';
+ this.controls_.style.borderBottom = '1px solid #8e8e8e';
+ this.controls_.style.borderTop = '1px solid white';
+ this.controls_.style.display = 'inline';
+ this.controls_.style.fontSize = '14px';
+ this.controls_.style.paddingLeft = '2px';
+
+ this.itemList_ = new tr.ui.b.ListView();
+ this.itemList_.style.flexGrow = 1;
+ this.itemList_.style.flexShrink = 1;
+ this.itemList_.style.flexBasis = 'auto';
+ this.itemList_.style.fontFamily = 'monospace';
+ this.itemList_.style.overflow = 'auto';
+ Polymer.dom(this).appendChild(this.controls_);
+
+ Polymer.dom(this).appendChild(this.itemList_);
+
+ this.itemList_.addEventListener(
+ 'selection-changed', this.onItemSelectionChanged_.bind(this));
+
+ Polymer.dom(this.controls_).appendChild(tr.ui.b.createSelector(
+ this, 'whichTree',
+ 'layerPicker.whichTree', constants.ACTIVE_TREE,
+ [{label: 'Active tree', value: constants.ACTIVE_TREE},
+ {label: 'Pending tree', value: constants.PENDING_TREE},
+ {label: 'Render pass quads', value: RENDER_PASS_QUADS}]));
+
+ this.showPureTransformLayers_ = false;
+ const showPureTransformLayers = tr.ui.b.createCheckBox(
+ this, 'showPureTransformLayers',
+ 'layerPicker.showPureTransformLayers', false,
+ 'Transform layers');
+ Polymer.dom(showPureTransformLayers).classList.add(
+ 'show-transform-layers');
+ showPureTransformLayers.title =
+ 'When checked, pure transform layers are shown';
+ Polymer.dom(this.controls_).appendChild(showPureTransformLayers);
+ },
+
+ get lthiSnapshot() {
+ return this.lthiSnapshot_;
+ },
+
+ set lthiSnapshot(lthiSnapshot) {
+ this.lthiSnapshot_ = lthiSnapshot;
+ this.updateContents_();
+ },
+
+ get whichTree() {
+ return this.renderPassQuads_ ? constants.ACTIVE_TREE : this.whichTree_;
+ },
+
+ set whichTree(whichTree) {
+ this.whichTree_ = whichTree;
+ this.renderPassQuads_ = (whichTree === RENDER_PASS_QUADS);
+ this.updateContents_();
+ tr.b.dispatchSimpleEvent(this, 'selection-change', false);
+ },
+
+ get layerTreeImpl() {
+ if (this.lthiSnapshot === undefined) return undefined;
+
+ return this.lthiSnapshot.getTree(this.whichTree);
+ },
+
+ get isRenderPassQuads() {
+ return this.renderPassQuads_;
+ },
+
+ get showPureTransformLayers() {
+ return this.showPureTransformLayers_;
+ },
+
+ set showPureTransformLayers(show) {
+ if (this.showPureTransformLayers_ === show) return;
+
+ this.showPureTransformLayers_ = show;
+ this.updateContents_();
+ },
+
+ getRenderPassInfos_() {
+ if (!this.lthiSnapshot_) return [];
+
+ const renderPassInfo = [];
+ if (!this.lthiSnapshot_.args.frame ||
+ !this.lthiSnapshot_.args.frame.renderPasses) {
+ return renderPassInfo;
+ }
+
+ const renderPasses = this.lthiSnapshot_.args.frame.renderPasses;
+ for (let i = 0; i < renderPasses.length; ++i) {
+ const info = {renderPass: renderPasses[i],
+ depth: 0,
+ id: i,
+ name: 'cc::RenderPass'};
+ renderPassInfo.push(info);
+ }
+ return renderPassInfo;
+ },
+
+ getLayerInfos_() {
+ if (!this.lthiSnapshot_) return [];
+
+ const tree = this.lthiSnapshot_.getTree(this.whichTree_);
+ if (!tree) return [];
+
+ const layerInfos = [];
+
+ const showPureTransformLayers = this.showPureTransformLayers_;
+
+ const visitedLayers = {};
+ function visitLayer(layer, depth, isMask, isReplica) {
+ if (visitedLayers[layer.layerId]) return;
+
+ visitedLayers[layer.layerId] = true;
+ const info = {layer,
+ depth};
+
+ if (layer.args.drawsContent) {
+ info.name = layer.objectInstance.name;
+ } else {
+ info.name = 'cc::LayerImpl';
+ }
+
+ if (layer.usingGpuRasterization) {
+ info.name += ' (G)';
+ }
+
+ info.isMaskLayer = isMask;
+ info.replicaLayer = isReplica;
+
+ if (showPureTransformLayers || layer.args.drawsContent) {
+ layerInfos.push(info);
+ }
+ }
+ tree.iterLayers(visitLayer);
+ return layerInfos;
+ },
+
+ updateContents_() {
+ if (this.renderPassQuads_) {
+ this.updateRenderPassContents_();
+ } else {
+ this.updateLayerContents_();
+ }
+ },
+
+ updateRenderPassContents_() {
+ this.itemList_.clear();
+
+ let selectedRenderPassId;
+ if (this.selection_ && this.selection_.associatedRenderPassId) {
+ selectedRenderPassId = this.selection_.associatedRenderPassId;
+ }
+
+ const renderPassInfos = this.getRenderPassInfos_();
+ renderPassInfos.forEach(function(renderPassInfo) {
+ const renderPass = renderPassInfo.renderPass;
+ const id = renderPassInfo.id;
+
+ const item = this.createElementWithDepth_(renderPassInfo.depth);
+ const labelEl = Polymer.dom(item).appendChild(tr.ui.b.createSpan());
+
+ Polymer.dom(labelEl).textContent = renderPassInfo.name + ' ' + id;
+ item.renderPass = renderPass;
+ item.renderPassId = id;
+ Polymer.dom(this.itemList_).appendChild(item);
+
+ if (id === selectedRenderPassId) {
+ renderPass.selectionState =
+ tr.model.SelectionState.SELECTED;
+ }
+ }, this);
+ },
+
+ updateLayerContents_() {
+ this.changingItemSelection_ = true;
+ try {
+ this.itemList_.clear();
+
+ let selectedLayerId;
+ if (this.selection_ && this.selection_.associatedLayerId) {
+ selectedLayerId = this.selection_.associatedLayerId;
+ }
+
+ const layerInfos = this.getLayerInfos_();
+ layerInfos.forEach(function(layerInfo) {
+ const layer = layerInfo.layer;
+ const id = layer.layerId;
+
+ const item = this.createElementWithDepth_(layerInfo.depth);
+ const labelEl = Polymer.dom(item).appendChild(tr.ui.b.createSpan());
+
+ Polymer.dom(labelEl).textContent = layerInfo.name + ' ' + id;
+
+ const notesEl = Polymer.dom(item).appendChild(tr.ui.b.createSpan());
+ if (layerInfo.isMaskLayer) {
+ Polymer.dom(notesEl).textContent += '(mask)';
+ }
+ if (layerInfo.isReplicaLayer) {
+ Polymer.dom(notesEl).textContent += '(replica)';
+ }
+
+ if ((layer.gpuMemoryUsageInBytes !== undefined) &&
+ (layer.gpuMemoryUsageInBytes > 0)) {
+ const gpuUsageStr = tr.b.Unit.byName.sizeInBytes.format(
+ layer.gpuMemoryUsageInBytes);
+ Polymer.dom(notesEl).textContent += ' (' + gpuUsageStr + ' MiB)';
+ }
+
+ item.layer = layer;
+ Polymer.dom(this.itemList_).appendChild(item);
+
+ if (layer.layerId === selectedLayerId) {
+ layer.selectionState = tr.model.SelectionState.SELECTED;
+ item.selected = true;
+ }
+ }, this);
+ } finally {
+ this.changingItemSelection_ = false;
+ }
+ },
+
+ createElementWithDepth_(depth) {
+ const item = document.createElement('div');
+
+ const indentEl = Polymer.dom(item).appendChild(tr.ui.b.createSpan());
+ indentEl.style.whiteSpace = 'pre';
+ for (let i = 0; i < depth; i++) {
+ Polymer.dom(indentEl).textContent =
+ Polymer.dom(indentEl).textContent + ' ';
+ }
+ return item;
+ },
+
+ onItemSelectionChanged_(e) {
+ if (this.changingItemSelection_) return;
+ if (this.renderPassQuads_) {
+ this.onRenderPassSelected_(e);
+ } else {
+ this.onLayerSelected_(e);
+ }
+ tr.b.dispatchSimpleEvent(this, 'selection-change', false);
+ },
+
+ onRenderPassSelected_(e) {
+ let selectedRenderPass;
+ let selectedRenderPassId;
+ if (this.itemList_.selectedElement) {
+ selectedRenderPass = this.itemList_.selectedElement.renderPass;
+ selectedRenderPassId =
+ this.itemList_.selectedElement.renderPassId;
+ }
+
+ if (selectedRenderPass) {
+ this.selection_ = new tr.ui.e.chrome.cc.RenderPassSelection(
+ selectedRenderPass, selectedRenderPassId);
+ } else {
+ this.selection_ = undefined;
+ }
+ },
+
+ onLayerSelected_(e) {
+ let selectedLayer;
+ if (this.itemList_.selectedElement) {
+ selectedLayer = this.itemList_.selectedElement.layer;
+ }
+
+ if (selectedLayer) {
+ this.selection_ = new tr.ui.e.chrome.cc.LayerSelection(selectedLayer);
+ } else {
+ this.selection_ = undefined;
+ }
+ },
+
+ get selection() {
+ return this.selection_;
+ },
+
+ set selection(selection) {
+ if (this.selection_ === selection) return;
+ this.selection_ = selection;
+ this.updateContents_();
+ }
+ };
+
+ return {
+ LayerPicker,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view.html
new file mode 100644
index 00000000000..1aaee9d7fbc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/layer_tree_host_impl.html">
+<link rel="import" href="/tracing/extras/chrome/cc/tile.html">
+<link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/layer_picker.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/layer_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ /*
+ * Displays a LayerTreeHostImpl snapshot in a human readable form.
+ * @constructor
+ */
+ const LayerTreeHostImplSnapshotView = tr.ui.b.define(
+ 'tr-ui-e-chrome-cc-layer-tree-host-impl-snapshot-view',
+ tr.ui.analysis.ObjectSnapshotView);
+
+ LayerTreeHostImplSnapshotView.prototype = {
+ __proto__: tr.ui.analysis.ObjectSnapshotView.prototype,
+
+ decorate() {
+ Polymer.dom(this).classList.add('tr-ui-e-chrome-cc-lthi-s-view');
+ this.style.display = 'flex';
+ this.style.flexDirection = 'row';
+ this.style.flexGrow = 1;
+ this.style.flexShrink = 1;
+ this.style.flexBasis = 'auto';
+ this.style.minWidth = 0;
+
+ this.selection_ = undefined;
+
+ this.layerPicker_ = new tr.ui.e.chrome.cc.LayerPicker();
+ this.layerPicker_.style.flexGrow = 0;
+ this.layerPicker_.style.flexShrink = 0;
+ this.layerPicker_.style.flexBasis = 'auto';
+ this.layerPicker_.style.minWidth = '200px';
+ this.layerPicker_.addEventListener(
+ 'selection-change',
+ this.onLayerPickerSelectionChanged_.bind(this));
+
+ this.layerView_ = new tr.ui.e.chrome.cc.LayerView();
+ this.layerView_.addEventListener(
+ 'selection-change',
+ this.onLayerViewSelectionChanged_.bind(this));
+ this.layerView_.style.flexGrow = 1;
+ this.layerView_.style.flexShrink = 1;
+ this.layerView_.style.flexBasis = 'auto';
+ this.layerView_.style.minWidth = 0;
+
+ this.dragHandle_ = document.createElement('tr-ui-b-drag-handle');
+ this.dragHandle_.style.flexGrow = 0;
+ this.dragHandle_.style.flexShrink = 0;
+ this.dragHandle_.style.flexBasis = 'auto';
+ this.dragHandle_.horizontal = false;
+ this.dragHandle_.target = this.layerPicker_;
+
+ Polymer.dom(this).appendChild(this.layerPicker_);
+ Polymer.dom(this).appendChild(this.dragHandle_);
+ Polymer.dom(this).appendChild(this.layerView_);
+
+ // Make sure we have the current values from layerView_ and layerPicker_,
+ // since those might have been created before we added the listener.
+ this.onLayerViewSelectionChanged_();
+ this.onLayerPickerSelectionChanged_();
+ },
+
+ get objectSnapshot() {
+ return this.objectSnapshot_;
+ },
+
+ set objectSnapshot(objectSnapshot) {
+ this.objectSnapshot_ = objectSnapshot;
+
+ const lthi = this.objectSnapshot;
+ let layerTreeImpl;
+ if (lthi) {
+ layerTreeImpl = lthi.getTree(this.layerPicker_.whichTree);
+ }
+
+ this.layerPicker_.lthiSnapshot = lthi;
+ this.layerView_.layerTreeImpl = layerTreeImpl;
+ this.layerView_.regenerateContent();
+
+ if (!this.selection_) return;
+
+ this.selection = this.selection_.findEquivalent(lthi);
+ },
+
+ get selection() {
+ return this.selection_;
+ },
+
+ set selection(selection) {
+ if (this.selection_ === selection) return;
+
+ this.selection_ = selection;
+ this.layerPicker_.selection = selection;
+ this.layerView_.selection = selection;
+ tr.b.dispatchSimpleEvent(this, 'cc-selection-change');
+ },
+
+ onLayerPickerSelectionChanged_() {
+ this.selection_ = this.layerPicker_.selection;
+ this.layerView_.selection = this.selection;
+ this.layerView_.layerTreeImpl = this.layerPicker_.layerTreeImpl;
+ this.layerView_.isRenderPassQuads = this.layerPicker_.isRenderPassQuads;
+ this.layerView_.regenerateContent();
+ tr.b.dispatchSimpleEvent(this, 'cc-selection-change');
+ },
+
+ onLayerViewSelectionChanged_() {
+ this.selection_ = this.layerView_.selection;
+ this.layerPicker_.selection = this.selection;
+ tr.b.dispatchSimpleEvent(this, 'cc-selection-change');
+ },
+
+ get extraHighlightsByLayerId() {
+ return this.layerView_.extraHighlightsByLayerId;
+ },
+
+ set extraHighlightsByLayerId(extraHighlightsByLayerId) {
+ this.layerView_.extraHighlightsByLayerId = extraHighlightsByLayerId;
+ }
+ };
+
+ tr.ui.analysis.ObjectSnapshotView.register(
+ LayerTreeHostImplSnapshotView, {typeName: 'cc::LayerTreeHostImpl'});
+
+ return {
+ LayerTreeHostImplSnapshotView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html
new file mode 100644
index 00000000000..1831be24618
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view_test.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/layer_tree_host_impl.html">
+<link rel="import" href="/tracing/extras/chrome/cc/raster_task.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
+ const snapshot = instance.snapshots[0];
+
+ const view = new tr.ui.e.chrome.cc.LayerTreeHostImplSnapshotView();
+ view.style.width = '900px';
+ view.style.height = '400px';
+ view.objectSnapshot = snapshot;
+
+ this.addHTMLOutput(view);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html
new file mode 100644
index 00000000000..2a7e5666f8b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html
@@ -0,0 +1,1200 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/extras/chrome/cc/debug_colors.html">
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/extras/chrome/cc/render_pass.html">
+<link rel="import" href="/tracing/extras/chrome/cc/tile.html">
+<link rel="import" href="/tracing/extras/chrome/cc/util.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/ui/base/info_bar.html">
+<link rel="import" href="/tracing/ui/base/quad_stack_view.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+
+<template id='tr-ui-e-chrome-cc-layer-tree-quad-stack-view-template'>
+ <style>
+ #input-event {
+ background-image: url('./images/input-event.png');
+ display: none;
+ }
+ </style>
+ <img id='input-event'/>
+</template>
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Graphical view of LayerTreeImpl, with controls for
+ * type of layer content shown and info bar for content-loading warnings.
+ */
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ const THIS_DOC = document.currentScript.ownerDocument;
+ const TILE_HEATMAP_TYPE = {};
+ TILE_HEATMAP_TYPE.NONE = 'none';
+ TILE_HEATMAP_TYPE.SCHEDULED_PRIORITY = 'scheduledPriority';
+ TILE_HEATMAP_TYPE.USING_GPU_MEMORY = 'usingGpuMemory';
+
+ const cc = tr.ui.e.chrome.cc;
+
+ function createTileRectsSelectorBaseOptions() {
+ return [{label: 'None', value: 'none'},
+ {label: 'Coverage Rects', value: 'coverage'}];
+ }
+
+
+ /**
+ * @constructor
+ */
+ const LayerTreeQuadStackView =
+ tr.ui.b.define('tr-ui-e-chrome-cc-layer-tree-quad-stack-view');
+
+ LayerTreeQuadStackView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.style.flexGrow = 1;
+ this.style.flexShrink = 1;
+ this.style.flexBasis = 'auto';
+ this.style.flexDirection = 'column';
+ this.style.minHeight = 0;
+ this.style.display = 'flex';
+
+ this.isRenderPassQuads_ = false;
+ this.pictureAsImageData_ = {}; // Maps picture.guid to PictureAsImageData.
+ this.messages_ = [];
+ this.controls_ = document.createElement('top-controls');
+ this.controls_.style.flexGrow = 0;
+ this.controls_.style.flexShrink = 0;
+ this.controls_.style.flexBasis = 'auto';
+ this.controls_.style.backgroundImage =
+ '-webkit-gradient(linear, 0 0, 100% 0, from(#E5E5E5), to(#D1D1D1))';
+ this.controls_.style.borderBottom = '1px solid #8e8e8e';
+ this.controls_.style.borderTop = '1px solid white';
+ this.controls_.style.display = 'flex';
+ this.controls_.style.flexDirection = 'row';
+ this.controls_.style.flexWrap = 'wrap';
+ this.controls_.style.fontSize = '14px';
+ this.controls_.style.paddingLeft = '2px';
+ this.controls_.style.overflow = 'hidden';
+ this.infoBar_ = document.createElement('tr-ui-b-info-bar');
+ this.quadStackView_ = new tr.ui.b.QuadStackView();
+ this.quadStackView_.addEventListener(
+ 'selectionchange', this.onQuadStackViewSelectionChange_.bind(this));
+ this.quadStackView_.style.flexGrow = 1;
+ this.quadStackView_.style.flexShrink = 1;
+ this.quadStackView_.style.flexBasis = 'auto';
+ this.quadStackView_.style.minWidth = '200px';
+
+ this.extraHighlightsByLayerId_ = undefined;
+ this.inputEventImageData_ = undefined;
+
+ const m = tr.ui.b.MOUSE_SELECTOR_MODE;
+ const mms = this.quadStackView_.mouseModeSelector;
+ mms.settingsKey = 'tr.e.cc.layerTreeQuadStackView.mouseModeSelector';
+ mms.setKeyCodeForMode(m.SELECTION, 'Z'.charCodeAt(0));
+ mms.setKeyCodeForMode(m.PANSCAN, 'X'.charCodeAt(0));
+ mms.setKeyCodeForMode(m.ZOOM, 'C'.charCodeAt(0));
+ mms.setKeyCodeForMode(m.ROTATE, 'V'.charCodeAt(0));
+
+ const node = tr.ui.b.instantiateTemplate(
+ '#tr-ui-e-chrome-cc-layer-tree-quad-stack-view-template', THIS_DOC);
+ Polymer.dom(this).appendChild(node);
+ Polymer.dom(this).appendChild(this.controls_);
+ Polymer.dom(this).appendChild(this.infoBar_);
+ Polymer.dom(this).appendChild(this.quadStackView_);
+
+ this.tileRectsSelector_ = tr.ui.b.createSelector(
+ this, 'howToShowTiles',
+ 'layerView.howToShowTiles', 'none',
+ createTileRectsSelectorBaseOptions());
+ Polymer.dom(this.controls_).appendChild(this.tileRectsSelector_);
+
+ const tileHeatmapText = tr.ui.b.createSpan({
+ textContent: 'Tile heatmap:'
+ });
+ Polymer.dom(this.controls_).appendChild(tileHeatmapText);
+
+ const tileHeatmapSelector = tr.ui.b.createSelector(
+ this, 'tileHeatmapType',
+ 'layerView.tileHeatmapType', TILE_HEATMAP_TYPE.NONE,
+ [{label: 'None',
+ value: TILE_HEATMAP_TYPE.NONE},
+ {label: 'Scheduled Priority',
+ value: TILE_HEATMAP_TYPE.SCHEDULED_PRIORITY},
+ {label: 'Is using GPU memory',
+ value: TILE_HEATMAP_TYPE.USING_GPU_MEMORY}
+ ]);
+ Polymer.dom(this.controls_).appendChild(tileHeatmapSelector);
+
+ const showOtherLayersCheckbox = tr.ui.b.createCheckBox(
+ this, 'showOtherLayers',
+ 'layerView.showOtherLayers', true,
+ 'Other layers/passes');
+ showOtherLayersCheckbox.title =
+ 'When checked, show all layers, selected or not.';
+ Polymer.dom(this.controls_).appendChild(showOtherLayersCheckbox);
+
+ const showInvalidationsCheckbox = tr.ui.b.createCheckBox(
+ this, 'showInvalidations',
+ 'layerView.showInvalidations', true,
+ 'Invalidations');
+ showInvalidationsCheckbox.title =
+ 'When checked, compositing invalidations are highlighted in red';
+ Polymer.dom(this.controls_).appendChild(showInvalidationsCheckbox);
+
+ const showUnrecordedRegionCheckbox = tr.ui.b.createCheckBox(
+ this, 'showUnrecordedRegion',
+ 'layerView.showUnrecordedRegion', true,
+ 'Unrecorded area');
+ showUnrecordedRegionCheckbox.title =
+ 'When checked, unrecorded areas are highlighted in yellow';
+ Polymer.dom(this.controls_).appendChild(showUnrecordedRegionCheckbox);
+
+ const showBottlenecksCheckbox = tr.ui.b.createCheckBox(
+ this, 'showBottlenecks',
+ 'layerView.showBottlenecks', true,
+ 'Bottlenecks');
+ showBottlenecksCheckbox.title =
+ 'When checked, scroll bottlenecks are highlighted';
+ Polymer.dom(this.controls_).appendChild(showBottlenecksCheckbox);
+
+ const showLayoutRectsCheckbox = tr.ui.b.createCheckBox(
+ this, 'showLayoutRects',
+ 'layerView.showLayoutRects', false,
+ 'Layout rects');
+ showLayoutRectsCheckbox.title =
+ 'When checked, shows rects for regions where layout happened';
+ Polymer.dom(this.controls_).appendChild(showLayoutRectsCheckbox);
+
+ const showContentsCheckbox = tr.ui.b.createCheckBox(
+ this, 'showContents',
+ 'layerView.showContents', true,
+ 'Contents');
+ showContentsCheckbox.title =
+ 'When checked, show the rendered contents inside the layer outlines';
+ Polymer.dom(this.controls_).appendChild(showContentsCheckbox);
+
+ const showAnimationBoundsCheckbox = tr.ui.b.createCheckBox(
+ this, 'showAnimationBounds',
+ 'layerView.showAnimationBounds', false,
+ 'Animation Bounds');
+ showAnimationBoundsCheckbox.title = 'When checked, show a border around' +
+ ' a layer showing the extent of its animation.';
+ Polymer.dom(this.controls_).appendChild(showAnimationBoundsCheckbox);
+
+ const showInputEventsCheckbox = tr.ui.b.createCheckBox(
+ this, 'showInputEvents',
+ 'layerView.showInputEvents', true,
+ 'Input events');
+ showInputEventsCheckbox.title = 'When checked, input events are ' +
+ 'displayed as circles.';
+ Polymer.dom(this.controls_).appendChild(showInputEventsCheckbox);
+
+ this.whatRasterizedLink_ = document.createElement(
+ 'tr-ui-a-analysis-link');
+ this.whatRasterizedLink_.style.position = 'absolute';
+ this.whatRasterizedLink_.style.bottom = '15px';
+ this.whatRasterizedLink_.style.left = '10px';
+ this.whatRasterizedLink_.selection =
+ this.getWhatRasterizedEventSet_.bind(this);
+ Polymer.dom(this.quadStackView_).appendChild(this.whatRasterizedLink_);
+ },
+
+ get layerTreeImpl() {
+ return this.layerTreeImpl_;
+ },
+
+ set isRenderPassQuads(newValue) {
+ this.isRenderPassQuads_ = newValue;
+ },
+
+ set layerTreeImpl(layerTreeImpl) {
+ if (this.layerTreeImpl_ === layerTreeImpl) return;
+
+ // FIXME(pdr): We may want to clear pictureAsImageData_ here to save
+ // memory at the cost of performance. Note that
+ // pictureAsImageData_ will be cleared when this is
+ // destructed, but this view might live for several
+ // layerTreeImpls.
+ this.layerTreeImpl_ = layerTreeImpl;
+ this.selection = undefined;
+ },
+
+ get extraHighlightsByLayerId() {
+ return this.extraHighlightsByLayerId_;
+ },
+
+ set extraHighlightsByLayerId(extraHighlightsByLayerId) {
+ this.extraHighlightsByLayerId_ = extraHighlightsByLayerId;
+ this.scheduleUpdateContents_();
+ },
+
+ get showOtherLayers() {
+ return this.showOtherLayers_;
+ },
+
+ set showOtherLayers(show) {
+ this.showOtherLayers_ = show;
+ this.updateContents_();
+ },
+
+ get showAnimationBounds() {
+ return this.showAnimationBounds_;
+ },
+
+ set showAnimationBounds(show) {
+ this.showAnimationBounds_ = show;
+ this.updateContents_();
+ },
+
+ get showInputEvents() {
+ return this.showInputEvents_;
+ },
+
+ set showInputEvents(show) {
+ this.showInputEvents_ = show;
+ this.updateContents_();
+ },
+
+ get showContents() {
+ return this.showContents_;
+ },
+
+ set showContents(show) {
+ this.showContents_ = show;
+ this.updateContents_();
+ },
+
+ get showInvalidations() {
+ return this.showInvalidations_;
+ },
+
+ set showInvalidations(show) {
+ this.showInvalidations_ = show;
+ this.updateContents_();
+ },
+
+ get showUnrecordedRegion() {
+ return this.showUnrecordedRegion_;
+ },
+
+ set showUnrecordedRegion(show) {
+ this.showUnrecordedRegion_ = show;
+ this.updateContents_();
+ },
+
+ get showBottlenecks() {
+ return this.showBottlenecks_;
+ },
+
+ set showBottlenecks(show) {
+ this.showBottlenecks_ = show;
+ this.updateContents_();
+ },
+
+ get showLayoutRects() {
+ return this.showLayoutRects_;
+ },
+
+ set showLayoutRects(show) {
+ this.showLayoutRects_ = show;
+ this.updateContents_();
+ },
+
+ get howToShowTiles() {
+ return this.howToShowTiles_;
+ },
+
+ set howToShowTiles(val) {
+ // Make sure val is something we expect.
+ if (val !== 'none' && val !== 'coverage' && isNaN(parseFloat(val))) {
+ throw new Error(
+ 'howToShowTiles requires "none" or "coverage" or a number');
+ }
+
+ this.howToShowTiles_ = val;
+ this.updateContents_();
+ },
+
+ get tileHeatmapType() {
+ return this.tileHeatmapType_;
+ },
+
+ set tileHeatmapType(val) {
+ this.tileHeatmapType_ = val;
+ this.updateContents_();
+ },
+
+ get selection() {
+ return this.selection_;
+ },
+
+ set selection(selection) {
+ if (this.selection === selection) return;
+
+ this.selection_ = selection;
+ tr.b.dispatchSimpleEvent(this, 'selection-change');
+ this.updateContents_();
+ },
+
+ regenerateContent() {
+ this.updateTilesSelector_();
+ this.updateContents_();
+ },
+
+ loadDataForImageElement_(image, callback) {
+ const imageContent = window.getComputedStyle(image).backgroundImage;
+ if (!imageContent) {
+ // The style has not been applied because the view has not been added
+ // into the DOM tree yet. Try again in another cycle.
+ this.scheduleUpdateContents_();
+ return;
+ }
+ image.src = tr.ui.b.extractUrlString(imageContent);
+ image.onload = function() {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+ canvas.width = image.width;
+ canvas.height = image.height;
+ ctx.drawImage(image, 0, 0);
+ const imageData = ctx.getImageData(
+ 0, 0, canvas.width, canvas.height);
+ callback(imageData);
+ };
+ },
+
+ onQuadStackViewSelectionChange_(e) {
+ const selectableQuads = e.quads.filter(function(q) {
+ return q.selectionToSetIfClicked !== undefined;
+ });
+ if (selectableQuads.length === 0) {
+ this.selection = undefined;
+ return;
+ }
+
+ // Sort the quads low to high on stackingGroupId.
+ selectableQuads.sort(function(x, y) {
+ const z = x.stackingGroupId - y.stackingGroupId;
+ if (z !== 0) return z;
+
+ return x.selectionToSetIfClicked.specicifity -
+ y.selectionToSetIfClicked.specicifity;
+ });
+
+ // TODO(nduca): Support selecting N things at once.
+ const quadToSelect = selectableQuads[selectableQuads.length - 1];
+ this.selection = quadToSelect.selectionToSetIfClicked;
+ },
+
+ scheduleUpdateContents_() {
+ if (this.updateContentsPending_) return;
+
+ this.updateContentsPending_ = true;
+ tr.b.requestAnimationFrameInThisFrameIfPossible(
+ this.updateContents_, this);
+ },
+
+ updateContents_() {
+ if (!this.layerTreeImpl_) {
+ this.quadStackView_.headerText = 'No tree';
+ this.quadStackView_.quads = [];
+ return;
+ }
+
+
+ const status = this.computePictureLoadingStatus_();
+ if (!status.picturesComplete) return;
+
+ const lthi = this.layerTreeImpl_.layerTreeHostImpl;
+ const lthiInstance = lthi.objectInstance;
+ const worldViewportRect = tr.b.math.Rect.fromXYWH(
+ 0, 0,
+ lthi.deviceViewportSize.width, lthi.deviceViewportSize.height);
+ this.quadStackView_.deviceRect = worldViewportRect;
+ if (this.isRenderPassQuads_) {
+ this.quadStackView_.quads = this.generateRenderPassQuads();
+ } else {
+ this.quadStackView_.quads = this.generateLayerQuads();
+ }
+
+ this.updateWhatRasterizedLinkState_();
+
+ let message = '';
+ if (lthi.tilesHaveGpuMemoryUsageInfo) {
+ const thisTreeUsageInBytes = this.layerTreeImpl_.gpuMemoryUsageInBytes;
+ const otherTreeUsageInBytes = lthi.gpuMemoryUsageInBytes -
+ thisTreeUsageInBytes;
+ message +=
+ tr.b.convertUnit(thisTreeUsageInBytes,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1) +
+ ' MiB on this tree';
+ if (otherTreeUsageInBytes) {
+ message += ', ' +
+ tr.b.convertUnit(otherTreeUsageInBytes,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1) +
+ ' MiB on the other tree';
+ }
+ } else {
+ if (this.layerTreeImpl_) {
+ const thisTreeUsageInBytes =
+ this.layerTreeImpl_.gpuMemoryUsageInBytes;
+ message +=
+ tr.b.convertUnit(thisTreeUsageInBytes,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1) +
+ ' MiB on this tree';
+
+ if (this.layerTreeImpl_.otherTree) {
+ // Older Chromes don't report enough data to know how much memory is
+ // being used across both trees. We know the memory consumed by each
+ // tree, but there is resource sharing *between the trees* so we
+ // can't simply sum up the per-tree costs. We need either the total
+ // plus one tree, to guess the unique on the other tree, etc. Newer
+ // chromes report memory per tile, which allows LTHI to compute the
+ // total tile memory usage, letting us figure things out properly.
+ message += ', ??? MiB on other tree. ';
+ }
+ }
+ }
+
+ if (lthi.args.tileManagerBasicState) {
+ const tmgs = lthi.args.tileManagerBasicState.globalState;
+ message += ' (softMax=' +
+ tr.b.convertUnit(tmgs.softMemoryLimitInBytes,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1) +
+ ' MiB, hardMax=' +
+ tr.b.convertUnit(tmgs.hardMemoryLimitInBytes,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1) + ' MiB, ' +
+ tmgs.memoryLimitPolicy + ')';
+ } else {
+ // Old Chromes do not have a globalState on the LTHI dump.
+ // But they do issue a DidManage event wiht the globalstate. Find that
+ // event so that we show some global state.
+ const thread = lthi.snapshottedOnThread;
+ const didManageTilesSlices = thread.sliceGroup.slices.filter(s => {
+ if (s.category !== 'tr.e.cc') return false;
+
+ if (s.title !== 'DidManage') return false;
+
+ if (s.end > lthi.ts) return false;
+
+ return true;
+ });
+ didManageTilesSlices.sort(function(x, y) {
+ return x.end - y.end;
+ });
+ if (didManageTilesSlices.length > 0) {
+ const newest = didManageTilesSlices[didManageTilesSlices.length - 1];
+ const tmgs = newest.args.state.global_state;
+ message += ' (softMax=' +
+ tr.b.convertUnit(tmgs.softMemoryLimitInBytes,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1) +
+ ' MiB, hardMax=' +
+ tr.b.convertUnit(tmgs.hardMemoryLimitInBytes,
+ tr.b.UnitPrefixScale.BINARY.NONE,
+ tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1) + ' MiB, ' +
+ tmgs.memoryLimitPolicy + ')';
+ }
+ }
+
+ if (this.layerTreeImpl_.otherTree) {
+ message += ' (Another tree exists)';
+ }
+
+ if (message.length) {
+ this.quadStackView_.headerText = message;
+ } else {
+ this.quadStackView_.headerText = undefined;
+ }
+
+ this.updateInfoBar_(status.messages);
+ },
+
+ updateTilesSelector_() {
+ const data = createTileRectsSelectorBaseOptions();
+
+ if (this.layerTreeImpl_) {
+ // First get all of the scales information from LTHI.
+ const lthi = this.layerTreeImpl_.layerTreeHostImpl;
+ const scaleNames = lthi.getContentsScaleNames();
+ for (const scale in scaleNames) {
+ data.push({
+ label: 'Scale ' + scale + ' (' + scaleNames[scale] + ')',
+ value: scale
+ });
+ }
+ }
+
+ // Then create a new selector and replace the old one.
+ const newSelector = tr.ui.b.createSelector(
+ this, 'howToShowTiles',
+ 'layerView.howToShowTiles', 'none',
+ data);
+ this.controls_.replaceChild(newSelector, this.tileRectsSelector_);
+ this.tileRectsSelector_ = newSelector;
+ },
+
+ computePictureLoadingStatus_() {
+ // Figure out if we can draw the quads yet. While we're at it, figure out
+ // if we have any warnings we need to show.
+ const layers = this.layers;
+ const status = {
+ messages: [],
+ picturesComplete: true
+ };
+ if (this.showContents) {
+ let hasPendingRasterizeImage = false;
+ let firstPictureError = undefined;
+ let hasMissingLayerRect = false;
+ let hasUnresolvedPictureRef = false;
+ for (let i = 0; i < layers.length; i++) {
+ const layer = layers[i];
+ for (let ir = 0; ir < layer.pictures.length; ++ir) {
+ const picture = layer.pictures[ir];
+
+ if (picture.idRef) {
+ hasUnresolvedPictureRef = true;
+ continue;
+ }
+ if (!picture.layerRect) {
+ hasMissingLayerRect = true;
+ continue;
+ }
+
+ const pictureAsImageData = this.pictureAsImageData_[picture.guid];
+ if (!pictureAsImageData) {
+ hasPendingRasterizeImage = true;
+ this.pictureAsImageData_[picture.guid] =
+ tr.e.cc.PictureAsImageData.Pending(this);
+ picture.rasterize(
+ {stopIndex: undefined},
+ function(pictureImageData) {
+ const picture_ = pictureImageData.picture;
+ this.pictureAsImageData_[picture_.guid] = pictureImageData;
+ this.scheduleUpdateContents_();
+ }.bind(this));
+ continue;
+ }
+ if (pictureAsImageData.isPending()) {
+ hasPendingRasterizeImage = true;
+ continue;
+ }
+ if (pictureAsImageData.error) {
+ if (!firstPictureError) {
+ firstPictureError = pictureAsImageData.error;
+ }
+ break;
+ }
+ }
+ }
+ if (hasPendingRasterizeImage) {
+ status.picturesComplete = false;
+ } else {
+ if (hasUnresolvedPictureRef) {
+ status.messages.push({
+ header: 'Missing picture',
+ details: 'Your trace didn\'t have pictures for every layer. ' +
+ 'Old chrome versions had this problem'});
+ }
+ if (hasMissingLayerRect) {
+ status.messages.push({
+ header: 'Missing layer rect',
+ details: 'Your trace may be corrupt or from a very old ' +
+ 'Chrome revision.'});
+ }
+ if (firstPictureError) {
+ status.messages.push({
+ header: 'Cannot rasterize',
+ details: firstPictureError});
+ }
+ }
+ }
+ if (this.showInputEvents && this.layerTreeImpl.tracedInputLatencies &&
+ this.inputEventImageData_ === undefined) {
+ const image = Polymer.dom(this).querySelector('#input-event');
+ if (!image.src) {
+ this.loadDataForImageElement_(image, function(imageData) {
+ this.inputEventImageData_ = imageData;
+ this.updateContentsPending_ = false;
+ this.scheduleUpdateContents_();
+ }.bind(this));
+ }
+ status.picturesComplete = false;
+ }
+ return status;
+ },
+
+ get selectedRenderPass() {
+ if (this.selection) {
+ return this.selection.renderPass_;
+ }
+ },
+
+ get selectedLayer() {
+ if (this.selection) {
+ const selectedLayerId = this.selection.associatedLayerId;
+ return this.layerTreeImpl_.findLayerWithId(selectedLayerId);
+ }
+ },
+
+ get renderPasses() {
+ let renderPasses =
+ this.layerTreeImpl.layerTreeHostImpl.args.frame.renderPasses;
+ if (!this.showOtherLayers) {
+ const selectedRenderPass = this.selectedRenderPass;
+ if (selectedRenderPass) {
+ renderPasses = [selectedRenderPass];
+ }
+ }
+ return renderPasses;
+ },
+
+ get layers() {
+ let layers = this.layerTreeImpl.renderSurfaceLayerList;
+ if (!this.showOtherLayers) {
+ const selectedLayer = this.selectedLayer;
+ if (selectedLayer) {
+ layers = [selectedLayer];
+ }
+ }
+ return layers;
+ },
+
+ appendImageQuads_(quads, layer, layerQuad) {
+ // Generate image quads for the layer
+ for (let ir = 0; ir < layer.pictures.length; ++ir) {
+ const picture = layer.pictures[ir];
+ if (!picture.layerRect) continue;
+
+ const unitRect = picture.layerRect.asUVRectInside(layer.bounds);
+ const iq = layerQuad.projectUnitRect(unitRect);
+
+ const pictureData = this.pictureAsImageData_[picture.guid];
+ if (this.showContents && pictureData && pictureData.imageData) {
+ iq.imageData = pictureData.imageData;
+ iq.borderColor = 'rgba(0,0,0,0)';
+ } else {
+ iq.imageData = undefined;
+ }
+
+ iq.stackingGroupId = layerQuad.stackingGroupId;
+ quads.push(iq);
+ }
+ },
+
+ appendAnimationQuads_(quads, layer, layerQuad) {
+ if (!layer.animationBoundsRect) return;
+
+ const rect = layer.animationBoundsRect;
+ const abq = tr.b.math.Quad.fromRect(rect);
+
+ abq.backgroundColor = 'rgba(164,191,48,0.5)';
+ abq.borderColor = 'rgba(205,255,0,0.75)';
+ abq.borderWidth = 3.0;
+ abq.stackingGroupId = layerQuad.stackingGroupId;
+ abq.selectionToSetIfClicked = new cc.AnimationRectSelection(
+ layer, rect);
+ quads.push(abq);
+ },
+
+ appendInvalidationQuads_(quads, layer, layerQuad) {
+ if (layer.layerTreeImpl.hasSourceFrameBeenDrawnBefore) return;
+
+ // Generate the invalidation rect quads.
+ for (const rect of layer.invalidation.rects) {
+ const unitRect = rect.asUVRectInside(layer.bounds);
+ const iq = layerQuad.projectUnitRect(unitRect);
+ iq.backgroundColor = 'rgba(0, 255, 0, 0.1)';
+ if (rect.reason === 'appeared') {
+ iq.backgroundColor = 'rgba(0, 255, 128, 0.1)';
+ }
+ iq.borderColor = 'rgba(0, 255, 0, 1)';
+ iq.stackingGroupId = layerQuad.stackingGroupId;
+
+ let message = 'Invalidation rect';
+ if (rect.reason) {
+ message += ' (' + rect.reason + ')';
+ }
+ if (rect.client) {
+ message += ' for ' + rect.client;
+ }
+
+ iq.selectionToSetIfClicked = new cc.LayerRectSelection(
+ layer, message, rect, rect);
+ quads.push(iq);
+ }
+ },
+
+ appendUnrecordedRegionQuads_(quads, layer, layerQuad) {
+ // Generate the unrecorded region quads.
+ for (let ir = 0; ir < layer.unrecordedRegion.rects.length; ir++) {
+ const rect = layer.unrecordedRegion.rects[ir];
+ const unitRect = rect.asUVRectInside(layer.bounds);
+ const iq = layerQuad.projectUnitRect(unitRect);
+ iq.backgroundColor = 'rgba(240, 230, 140, 0.3)';
+ iq.borderColor = 'rgba(240, 230, 140, 1)';
+ iq.stackingGroupId = layerQuad.stackingGroupId;
+ iq.selectionToSetIfClicked = new cc.LayerRectSelection(
+ layer, 'Unrecorded area', rect, rect);
+ quads.push(iq);
+ }
+ },
+
+ appendBottleneckQuads_(quads, layer, layerQuad, stackingGroupId) {
+ function processRegion(region, label, borderColor) {
+ const backgroundColor = borderColor.clone();
+ backgroundColor.a = 0.4 * (borderColor.a || 1.0);
+
+ if (!region || !region.rects) return;
+
+ for (let ir = 0; ir < region.rects.length; ir++) {
+ const rect = region.rects[ir];
+ const unitRect = rect.asUVRectInside(layer.bounds);
+ const iq = layerQuad.projectUnitRect(unitRect);
+ iq.backgroundColor = backgroundColor.toString();
+ iq.borderColor = borderColor.toString();
+ iq.borderWidth = 4.0;
+ iq.stackingGroupId = stackingGroupId;
+ iq.selectionToSetIfClicked = new cc.LayerRectSelection(
+ layer, label, rect, rect);
+ quads.push(iq);
+ }
+ }
+
+ processRegion(layer.touchEventHandlerRegion, 'Touch listener',
+ tr.b.Color.fromString('rgb(228, 226, 27)'));
+ processRegion(layer.wheelEventHandlerRegion, 'Wheel listener',
+ tr.b.Color.fromString('rgb(176, 205, 29)'));
+ processRegion(layer.nonFastScrollableRegion, 'Repaints on scroll',
+ tr.b.Color.fromString('rgb(213, 134, 32)'));
+ },
+
+ appendTileCoverageRectQuads_(
+ quads, layer, layerQuad, heatmapType) {
+ if (!layer.tileCoverageRects) return;
+
+ const tiles = [];
+ for (let ct = 0; ct < layer.tileCoverageRects.length; ++ct) {
+ const tile = layer.tileCoverageRects[ct].tile;
+ if (tile !== undefined) tiles.push(tile);
+ }
+
+ const lthi = this.layerTreeImpl_.layerTreeHostImpl;
+ const minMax =
+ this.getMinMaxForHeatmap_(lthi.activeTiles, heatmapType);
+ const heatmapResult =
+ this.computeHeatmapColors_(tiles, minMax, heatmapType);
+ let heatIndex = 0;
+
+ for (let ct = 0; ct < layer.tileCoverageRects.length; ++ct) {
+ let rect = layer.tileCoverageRects[ct].geometryRect;
+ rect = rect.scale(1.0 / layer.geometryContentsScale);
+
+ const tile = layer.tileCoverageRects[ct].tile;
+
+ const unitRect = rect.asUVRectInside(layer.bounds);
+ const quad = layerQuad.projectUnitRect(unitRect);
+
+ quad.backgroundColor = 'rgba(0, 0, 0, 0)';
+ quad.stackingGroupId = layerQuad.stackingGroupId;
+ let type = tr.e.cc.tileTypes.missing;
+ if (tile) {
+ type = tile.getTypeForLayer(layer);
+ quad.backgroundColor = heatmapResult[heatIndex].color;
+ ++heatIndex;
+ }
+
+ quad.borderColor = tr.e.cc.tileBorder[type].color;
+ quad.borderWidth = tr.e.cc.tileBorder[type].width;
+ let label;
+ if (tile) {
+ label = 'coverageRect';
+ } else {
+ label = 'checkerboard coverageRect';
+ }
+ quad.selectionToSetIfClicked = new cc.LayerRectSelection(
+ layer, label, rect, layer.tileCoverageRects[ct]);
+
+ quads.push(quad);
+ }
+ },
+
+ appendLayoutRectQuads_(quads, layer, layerQuad) {
+ if (!layer.layoutRects) {
+ return;
+ }
+
+ for (let ct = 0; ct < layer.layoutRects.length; ++ct) {
+ let rect = layer.layoutRects[ct].geometryRect;
+ rect = rect.scale(1.0 / layer.geometryContentsScale);
+
+ const unitRect = rect.asUVRectInside(layer.bounds);
+ const quad = layerQuad.projectUnitRect(unitRect);
+
+ quad.backgroundColor = 'rgba(0, 0, 0, 0)';
+ quad.stackingGroupId = layerQuad.stackingGroupId;
+
+ quad.borderColor = 'rgba(0, 0, 200, 0.7)';
+ quad.borderWidth = 2;
+ const label = 'Layout rect';
+ quad.selectionToSetIfClicked = new cc.LayerRectSelection(
+ layer, label, rect);
+
+ quads.push(quad);
+ }
+ },
+
+ getValueForHeatmap_(tile, heatmapType) {
+ if (heatmapType === TILE_HEATMAP_TYPE.SCHEDULED_PRIORITY) {
+ return tile.scheduledPriority === 0 ?
+ undefined :
+ tile.scheduledPriority;
+ } else if (heatmapType === TILE_HEATMAP_TYPE.USING_GPU_MEMORY) {
+ if (tile.isSolidColor) return 0.5;
+ return tile.isUsingGpuMemory ? 0 : 1;
+ }
+ },
+
+ getMinMaxForHeatmap_(tiles, heatmapType) {
+ const range = new tr.b.math.Range();
+ if (heatmapType === TILE_HEATMAP_TYPE.USING_GPU_MEMORY) {
+ range.addValue(0);
+ range.addValue(1);
+ return range;
+ }
+
+ for (let i = 0; i < tiles.length; ++i) {
+ const value = this.getValueForHeatmap_(tiles[i], heatmapType);
+ if (value === undefined) continue;
+ range.addValue(value);
+ }
+ if (range.range === 0) {
+ range.addValue(1);
+ }
+ return range;
+ },
+
+ computeHeatmapColors_(tiles, minMax, heatmapType) {
+ const min = minMax.min;
+ const max = minMax.max;
+
+ const color = function(value) {
+ let hue = 120 * (1 - (value - min) / (max - min));
+ if (hue < 0) hue = 0;
+ return 'hsla(' + hue + ', 100%, 50%, 0.5)';
+ };
+
+ const values = [];
+ for (let i = 0; i < tiles.length; ++i) {
+ const tile = tiles[i];
+ const value = this.getValueForHeatmap_(tile, heatmapType);
+ const res = {
+ value,
+ color: value !== undefined ? color(value) : undefined
+ };
+ values.push(res);
+ }
+
+ return values;
+ },
+
+ appendTilesWithScaleQuads_(
+ quads, layer, layerQuad, scale, heatmapType) {
+ const lthi = this.layerTreeImpl_.layerTreeHostImpl;
+
+ const tiles = [];
+ for (let i = 0; i < lthi.activeTiles.length; ++i) {
+ const tile = lthi.activeTiles[i];
+
+ if (Math.abs(tile.contentsScale - scale) > 1e-6) {
+ continue;
+ }
+
+ // TODO(vmpstr): Make the stiching of tiles and layers a part of
+ // tile construction (issue 346)
+ if (layer.layerId !== tile.layerId) continue;
+
+ tiles.push(tile);
+ }
+
+ const minMax =
+ this.getMinMaxForHeatmap_(lthi.activeTiles, heatmapType);
+ const heatmapResult =
+ this.computeHeatmapColors_(tiles, minMax, heatmapType);
+
+ for (let i = 0; i < tiles.length; ++i) {
+ const tile = tiles[i];
+ const rect = tile.layerRect;
+ if (!tile.layerRect) continue;
+
+ const unitRect = rect.asUVRectInside(layer.bounds);
+ const quad = layerQuad.projectUnitRect(unitRect);
+
+ quad.backgroundColor = 'rgba(0, 0, 0, 0)';
+ quad.stackingGroupId = layerQuad.stackingGroupId;
+
+ const type = tile.getTypeForLayer(layer);
+ quad.borderColor = tr.e.cc.tileBorder[type].color;
+ quad.borderWidth = tr.e.cc.tileBorder[type].width;
+
+ quad.backgroundColor = heatmapResult[i].color;
+ const data = {
+ tileType: type
+ };
+ if (heatmapType !== TILE_HEATMAP_TYPE.NONE) {
+ data[heatmapType] = heatmapResult[i].value;
+ }
+ quad.selectionToSetIfClicked = new cc.TileSelection(tile, data);
+ quads.push(quad);
+ }
+ },
+
+ appendHighlightQuadsForLayer_(
+ quads, layer, layerQuad, highlights) {
+ highlights.forEach(function(highlight) {
+ const rect = highlight.rect;
+
+ const unitRect = rect.asUVRectInside(layer.bounds);
+ const quad = layerQuad.projectUnitRect(unitRect);
+
+ let colorId = ColorScheme.getColorIdForGeneralPurposeString(
+ highlight.colorKey);
+ const offset = ColorScheme.properties.brightenedOffsets[0];
+ colorId = ColorScheme.getVariantColorId(colorId, offset);
+
+ const color = ColorScheme.colors[colorId];
+
+ const quadForDrawing = quad.clone();
+ quadForDrawing.backgroundColor = color.withAlpha(0.5).toString();
+ quadForDrawing.borderColor = color.withAlpha(1.0).darken().toString();
+ quadForDrawing.stackingGroupId = layerQuad.stackingGroupId;
+ quads.push(quadForDrawing);
+ }, this);
+ },
+
+ generateRenderPassQuads() {
+ if (!this.layerTreeImpl.layerTreeHostImpl.args.frame) return [];
+ const renderPasses = this.renderPasses;
+ if (!renderPasses) return [];
+
+ const quads = [];
+ for (let i = 0; i < renderPasses.length; ++i) {
+ const quadList = renderPasses[i].quadList;
+ for (let j = 0; j < quadList.length; ++j) {
+ const drawQuad = quadList[j];
+ const quad = drawQuad.rectAsTargetSpaceQuad.clone();
+ quad.borderColor = 'rgb(170, 204, 238)';
+ quad.borderWidth = 2;
+ quad.stackingGroupId = i;
+ quads.push(quad);
+ }
+ }
+ return quads;
+ },
+
+ generateLayerQuads() {
+ this.updateContentsPending_ = false;
+
+ // Generate the quads for the view.
+ const layers = this.layers;
+ const quads = [];
+ let nextStackingGroupId = 0;
+ const alreadyVisitedLayerIds = {};
+
+
+ let selectionHighlightsByLayerId;
+ if (this.selection) {
+ selectionHighlightsByLayerId = this.selection.highlightsByLayerId;
+ } else {
+ selectionHighlightsByLayerId = {};
+ }
+
+ const extraHighlightsByLayerId = this.extraHighlightsByLayerId || {};
+
+ for (let i = 1; i <= layers.length; i++) {
+ // Generate quads back-to-front.
+ const layer = layers[layers.length - i];
+ alreadyVisitedLayerIds[layer.layerId] = true;
+ if (layer.objectInstance.name === 'cc::NinePatchLayerImpl') {
+ continue;
+ }
+
+ const layerQuad = layer.layerQuad.clone();
+ if (layer.usingGpuRasterization) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ layerQuad.borderWidth = 2.0 * pixelRatio;
+ layerQuad.borderColor = 'rgba(154,205,50,0.75)';
+ } else {
+ layerQuad.borderColor = 'rgba(0,0,0,0.75)';
+ }
+ layerQuad.stackingGroupId = nextStackingGroupId++;
+ layerQuad.selectionToSetIfClicked = new cc.LayerSelection(layer);
+ layerQuad.layer = layer;
+ if (this.showOtherLayers && this.selectedLayer === layer) {
+ layerQuad.upperBorderColor = 'rgb(156,189,45)';
+ }
+
+ if (this.showAnimationBounds) {
+ this.appendAnimationQuads_(quads, layer, layerQuad);
+ }
+
+ this.appendImageQuads_(quads, layer, layerQuad);
+ quads.push(layerQuad);
+
+
+ if (this.showInvalidations) {
+ this.appendInvalidationQuads_(quads, layer, layerQuad);
+ }
+ if (this.showUnrecordedRegion) {
+ this.appendUnrecordedRegionQuads_(quads, layer, layerQuad);
+ }
+ if (this.showBottlenecks) {
+ this.appendBottleneckQuads_(quads, layer, layerQuad,
+ layerQuad.stackingGroupId);
+ }
+ if (this.showLayoutRects) {
+ this.appendLayoutRectQuads_(quads, layer, layerQuad);
+ }
+
+ if (this.howToShowTiles === 'coverage') {
+ this.appendTileCoverageRectQuads_(
+ quads, layer, layerQuad, this.tileHeatmapType);
+ } else if (this.howToShowTiles !== 'none') {
+ this.appendTilesWithScaleQuads_(
+ quads, layer, layerQuad,
+ this.howToShowTiles, this.tileHeatmapType);
+ }
+
+ let highlights;
+ highlights = extraHighlightsByLayerId[layer.layerId];
+ if (highlights) {
+ this.appendHighlightQuadsForLayer_(
+ quads, layer, layerQuad, highlights);
+ }
+
+ highlights = selectionHighlightsByLayerId[layer.layerId];
+ if (highlights) {
+ this.appendHighlightQuadsForLayer_(
+ quads, layer, layerQuad, highlights);
+ }
+ }
+
+ this.layerTreeImpl.iterLayers(function(layer, depth, isMask, isReplica) {
+ if (!this.showOtherLayers && this.selectedLayer !== layer) return;
+ if (alreadyVisitedLayerIds[layer.layerId]) return;
+
+ const layerQuad = layer.layerQuad;
+ const stackingGroupId = nextStackingGroupId++;
+ if (this.showBottlenecks) {
+ this.appendBottleneckQuads_(quads, layer, layerQuad, stackingGroupId);
+ }
+ }, this);
+
+ const tracedInputLatencies = this.layerTreeImpl.tracedInputLatencies;
+ if (this.showInputEvents && tracedInputLatencies) {
+ for (let i = 0; i < tracedInputLatencies.length; i++) {
+ const coordinatesArray =
+ tracedInputLatencies[i].args.data.coordinates;
+ for (let j = 0; j < coordinatesArray.length; j++) {
+ const inputQuad = tr.b.math.Quad.fromXYWH(
+ coordinatesArray[j].x - 25,
+ coordinatesArray[j].y - 25,
+ 50,
+ 50);
+ inputQuad.borderColor = 'rgba(0, 0, 0, 0)';
+ inputQuad.imageData = this.inputEventImageData_;
+ quads.push(inputQuad);
+ }
+ }
+ }
+
+ return quads;
+ },
+
+ updateInfoBar_(infoBarMessages) {
+ if (infoBarMessages.length) {
+ this.infoBar_.removeAllButtons();
+ this.infoBar_.message = 'Some problems were encountered...';
+ this.infoBar_.addButton('More info...', function(e) {
+ const overlay = new tr.ui.b.Overlay();
+ Polymer.dom(overlay).textContent = '';
+ infoBarMessages.forEach(function(message) {
+ const title = document.createElement('h3');
+ Polymer.dom(title).textContent = message.header;
+
+ const details = document.createElement('div');
+ Polymer.dom(details).textContent = message.details;
+
+ Polymer.dom(overlay).appendChild(title);
+ Polymer.dom(overlay).appendChild(details);
+ });
+ overlay.visible = true;
+
+ e.stopPropagation();
+ return false;
+ });
+ this.infoBar_.visible = true;
+ } else {
+ this.infoBar_.removeAllButtons();
+ this.infoBar_.message = '';
+ this.infoBar_.visible = false;
+ }
+ },
+
+ getWhatRasterized_() {
+ const lthi = this.layerTreeImpl_.layerTreeHostImpl;
+ const renderProcess = lthi.objectInstance.parent;
+ const tasks = [];
+ for (const event of renderProcess.getDescendantEvents()) {
+ if (!(event instanceof tr.model.Slice)) continue;
+
+ const tile = tr.e.cc.getTileFromRasterTaskSlice(event);
+ if (tile === undefined) continue;
+
+ if (tile.containingSnapshot === lthi) {
+ tasks.push(event);
+ }
+ }
+ return tasks;
+ },
+
+ updateWhatRasterizedLinkState_() {
+ const tasks = this.getWhatRasterized_();
+ if (tasks.length) {
+ Polymer.dom(this.whatRasterizedLink_).textContent =
+ tasks.length + ' raster tasks';
+ this.whatRasterizedLink_.style.display = '';
+ } else {
+ Polymer.dom(this.whatRasterizedLink_).textContent = '';
+ this.whatRasterizedLink_.style.display = 'none';
+ }
+ },
+
+ getWhatRasterizedEventSet_() {
+ return new tr.model.EventSet(this.getWhatRasterized_());
+ }
+ };
+
+ return {
+ LayerTreeQuadStackView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html
new file mode 100644
index 00000000000..66932ae785f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view_test.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/cc.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('tileCoverageRectCount', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = m.processes[1];
+
+ const instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
+ const lthi = instance.snapshots[0];
+
+ const view = new tr.ui.e.chrome.cc.LayerTreeQuadStackView();
+ view.layerTreeImpl = lthi.activeTree;
+ view.howToShowTiles = 'none';
+ view.showInvalidations = false;
+ view.showContents = false;
+
+ // There should be some quads drawn with all "show" checkboxes off,
+ // but that number can change with new features added.
+ const aQuads = view.generateLayerQuads();
+ view.howToShowTiles = 'coverage';
+ const bQuads = view.generateLayerQuads();
+ const numCoverageRects = bQuads.length - aQuads.length;
+
+ // We know we have 5 coverage rects in lthi cats.
+ assert.strictEqual(numCoverageRects, 5);
+ });
+
+ test('inputEvent', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = m.processes[1];
+
+ const instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
+ const lthi = instance.snapshots[0];
+ lthi.activeTree.tracedInputLatencies =
+ [{args: {data: {coordinates: [{x: 10, y: 20}, {x: 30, y: 40}]}}}];
+
+ const view = new tr.ui.e.chrome.cc.LayerTreeQuadStackView();
+ view.layerTreeImpl = lthi.activeTree;
+ view.showInputEvents = false;
+
+ const aQuads = view.generateLayerQuads();
+ view.showInputEvents = true;
+ const bQuads = view.generateLayerQuads();
+ const numInputEventRects = bQuads.length - aQuads.length;
+
+ assert.strictEqual(numInputEventRects, 2);
+
+ // We should not start loading the image until the view is added into the
+ // DOM tree.
+ const image = Polymer.dom(view).querySelector('#input-event');
+ assert.strictEqual(getComputedStyle(image).backgroundImage, '');
+ assert.strictEqual(image.src, '');
+
+ document.body.appendChild(view);
+ view.updateContents_();
+ assert.notEqual(getComputedStyle(image).backgroundImage, '');
+ assert.notEqual(image.src, '');
+ view.remove();
+ });
+
+ test('invalidation', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = m.processes[1];
+
+ const instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
+ const lthi = instance.snapshots[0];
+
+ const view = new tr.ui.e.chrome.cc.LayerTreeQuadStackView();
+ view.layerTreeImpl = lthi.activeTree;
+ view.showInvalidations = false;
+
+ const aQuads = view.generateLayerQuads();
+ view.showInvalidations = true;
+ const bQuads = view.generateLayerQuads();
+ const numInvalidationRects = bQuads.length - aQuads.length;
+
+ // We know we have 3 invalidation rects.
+ assert.strictEqual(numInvalidationRects, 3);
+
+ const expectedRectTypes = [
+ 'Invalidation rect (appeared) for client1',
+ 'Invalidation rect (disappeared) for client2',
+ 'Invalidation rect' // The non-annotated rect.
+ ];
+ const found = [];
+ for (const quad of bQuads) {
+ const i = expectedRectTypes.indexOf(quad.selectionToSetIfClicked &&
+ quad.selectionToSetIfClicked.rectType_);
+ if (i !== -1) {
+ found[i] = true;
+ }
+ }
+ assert.deepEqual(found, [true, true, true]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view.html
new file mode 100644
index 00000000000..56ecf770ec1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/extras/chrome/cc/constants.html">
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview LayerView coordinates graphical and analysis views of layers.
+ */
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ const constants = tr.e.cc.constants;
+
+ /**
+ * @constructor
+ */
+ const LayerView = tr.ui.b.define('tr-ui-e-chrome-cc-layer-view');
+
+ LayerView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.style.flexDirection = 'column';
+ this.style.display = 'flex';
+
+ this.layerTreeQuadStackView_ =
+ new tr.ui.e.chrome.cc.LayerTreeQuadStackView();
+ this.dragBar_ = document.createElement('tr-ui-b-drag-handle');
+ this.analysisEl_ =
+ document.createElement('tr-ui-e-chrome-cc-layer-view-analysis');
+ this.analysisEl_.style.flexGrow = 0;
+ this.analysisEl_.style.flexShrink = 0;
+ this.analysisEl_.style.flexBasis = 'auto';
+ this.analysisEl_.style.height = '150px';
+ this.analysisEl_.style.overflow = 'auto';
+ this.analysisEl_.addEventListener('requestSelectionChange',
+ this.onRequestSelectionChangeFromAnalysisEl_.bind(this));
+
+ this.dragBar_.target = this.analysisEl_;
+
+ Polymer.dom(this).appendChild(this.layerTreeQuadStackView_);
+ Polymer.dom(this).appendChild(this.dragBar_);
+ Polymer.dom(this).appendChild(this.analysisEl_);
+
+ this.layerTreeQuadStackView_.addEventListener('selection-change',
+ function() {
+ this.layerTreeQuadStackViewSelectionChanged_();
+ }.bind(this));
+ this.layerTreeQuadStackViewSelectionChanged_();
+ },
+
+ get layerTreeImpl() {
+ return this.layerTreeQuadStackView_.layerTreeImpl;
+ },
+
+ set layerTreeImpl(newValue) {
+ return this.layerTreeQuadStackView_.layerTreeImpl = newValue;
+ },
+
+ set isRenderPassQuads(newValue) {
+ return this.layerTreeQuadStackView_.isRenderPassQuads = newValue;
+ },
+
+ get selection() {
+ return this.layerTreeQuadStackView_.selection;
+ },
+
+ set selection(newValue) {
+ this.layerTreeQuadStackView_.selection = newValue;
+ },
+
+ regenerateContent() {
+ this.layerTreeQuadStackView_.regenerateContent();
+ },
+
+ layerTreeQuadStackViewSelectionChanged_() {
+ const selection = this.layerTreeQuadStackView_.selection;
+ if (selection) {
+ this.dragBar_.style.display = '';
+ this.analysisEl_.style.display = '';
+ Polymer.dom(this.analysisEl_).textContent = '';
+
+ const layer = selection.layer;
+ if (tr.e.cc.PictureSnapshot.CanDebugPicture() &&
+ layer &&
+ layer.args &&
+ layer.args.pictures &&
+ layer.args.pictures.length) {
+ Polymer.dom(this.analysisEl_).appendChild(
+ this.createPictureBtn_(layer.args.pictures));
+ }
+
+ const analysis = selection.createAnalysis();
+ Polymer.dom(this.analysisEl_).appendChild(analysis);
+ for (const child of this.analysisEl_.children) {
+ child.style.userSelect = 'text';
+ }
+ } else {
+ this.dragBar_.style.display = 'none';
+ this.analysisEl_.style.display = 'none';
+ const analysis = Polymer.dom(this.analysisEl_).firstChild;
+ if (analysis) {
+ Polymer.dom(this.analysisEl_).removeChild(analysis);
+ }
+ this.layerTreeQuadStackView_.style.height =
+ window.getComputedStyle(this).height;
+ }
+ tr.b.dispatchSimpleEvent(this, 'selection-change');
+ },
+
+ createPictureBtn_(pictures) {
+ if (!(pictures instanceof Array)) {
+ pictures = [pictures];
+ }
+
+ const link = document.createElement('tr-ui-a-analysis-link');
+ link.selection = function() {
+ const layeredPicture = new tr.e.cc.LayeredPicture(pictures);
+ const snapshot = new tr.e.cc.PictureSnapshot(layeredPicture);
+ snapshot.picture = layeredPicture;
+
+ const selection = new tr.model.EventSet();
+ selection.push(snapshot);
+ return selection;
+ };
+ Polymer.dom(link).textContent = 'View in Picture Debugger';
+ return link;
+ },
+
+ onRequestSelectionChangeFromAnalysisEl_(e) {
+ if (!(e.selection instanceof tr.ui.e.chrome.cc.Selection)) {
+ return;
+ }
+
+ e.stopPropagation();
+ this.selection = e.selection;
+ },
+
+ get extraHighlightsByLayerId() {
+ return this.layerTreeQuadStackView_.extraHighlightsByLayerId;
+ },
+
+ set extraHighlightsByLayerId(extraHighlightsByLayerId) {
+ this.layerTreeQuadStackView_.extraHighlightsByLayerId =
+ extraHighlightsByLayerId;
+ }
+ };
+
+ return {
+ LayerView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html
new file mode 100644
index 00000000000..ed3de7b87e1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/layer_view_test.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/cc.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/layer_view.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = m.processes[1];
+
+ const instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
+ const lthi = instance.snapshots[0];
+ const numLayers = lthi.activeTree.renderSurfaceLayerList.length;
+ const layer = lthi.activeTree.renderSurfaceLayerList[numLayers - 1];
+
+ const view = new tr.ui.e.chrome.cc.LayerView();
+ view.style.height = '500px';
+ view.layerTreeImpl = lthi.activeTree;
+ view.selection = new tr.ui.e.chrome.cc.LayerSelection(layer);
+
+ this.addHTMLOutput(view);
+ });
+
+ test('instantiate_withTileHighlight', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = m.processes[1];
+
+ const instance = p.objects.getAllInstancesNamed('cc::LayerTreeHostImpl')[0];
+ const lthi = instance.snapshots[0];
+ const numLayers = lthi.activeTree.renderSurfaceLayerList.length;
+ const layer = lthi.activeTree.renderSurfaceLayerList[numLayers - 1];
+ const tile = lthi.activeTiles[0];
+
+ const view = new tr.ui.e.chrome.cc.LayerView();
+ view.style.height = '500px';
+ view.layerTreeImpl = lthi.activeTree;
+ view.selection = new tr.ui.e.chrome.cc.TileSelection(tile);
+ this.addHTMLOutput(view);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_debugger.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_debugger.html
new file mode 100644
index 00000000000..5dc62b1b4f6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_debugger.html
@@ -0,0 +1,455 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<link rel="import" href="/tracing/ui/base/hotkey_controller.html">
+<link rel="import" href="/tracing/ui/base/info_bar.html">
+<link rel="import" href="/tracing/ui/base/list_view.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_selector.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+<link rel="import"
+ href="/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/picture_ops_list_view.html">
+
+<template id="tr-ui-e-chrome-cc-picture-debugger-template">
+ <left-panel>
+ <picture-info>
+ <div>
+ <span class='title'>Skia Picture</span>
+ <span class='size'></span>
+ </div>
+ <div>
+ <input class='filename' type='text' value='skpicture.skp' />
+ <button class='export'>Export</button>
+ </div>
+ </picture-info>
+ </left-panel>
+ <right-panel>
+ <tr-ui-e-chrome-cc-picture-ops-chart-view>
+ </tr-ui-e-chrome-cc-picture-ops-chart-view>
+ <raster-area><canvas></canvas></raster-area>
+ </right-panel>
+</template>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ /**
+ * PictureDebugger is a view of a PictureSnapshot for inspecting
+ * the picture in detail. (e.g., timing information, etc.)
+ *
+ * @constructor
+ */
+ const PictureDebugger = tr.ui.b.define('tr-ui-e-chrome-cc-picture-debugger');
+
+ PictureDebugger.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ const node = tr.ui.b.instantiateTemplate(
+ '#tr-ui-e-chrome-cc-picture-debugger-template', THIS_DOC);
+
+ Polymer.dom(this).appendChild(node);
+
+ this.style.display = 'flex';
+ this.style.flexDirection = 'row';
+
+ const title = this.querySelector('.title');
+ title.style.fontWeight = 'bold';
+ title.style.marginLeft = '5px';
+ title.style.marginRight = '5px';
+
+ this.pictureAsImageData_ = undefined;
+ this.showOverdraw_ = false;
+ this.zoomScaleValue_ = 1;
+
+ this.sizeInfo_ = Polymer.dom(this).querySelector('.size');
+ this.rasterArea_ = Polymer.dom(this).querySelector('raster-area');
+ this.rasterArea_.style.backgroundColor = '#ddd';
+ this.rasterArea_.style.minHeight = '100px';
+ this.rasterArea_.style.minWidth = '200px';
+ this.rasterArea_.style.overflow = 'auto';
+ this.rasterArea_.style.paddingLeft = '5px';
+ this.rasterCanvas_ = Polymer.dom(this.rasterArea_)
+ .querySelector('canvas');
+ this.rasterCtx_ = this.rasterCanvas_.getContext('2d');
+
+ this.filename_ = Polymer.dom(this).querySelector('.filename');
+ this.filename_.style.userSelect = 'text';
+ this.filename_.style.marginLeft = '5px';
+
+ this.drawOpsChartSummaryView_ =
+ new tr.ui.e.chrome.cc.PictureOpsChartSummaryView();
+ this.drawOpsChartView_ = new tr.ui.e.chrome.cc.PictureOpsChartView();
+ this.drawOpsChartView_.addEventListener(
+ 'selection-changed', this.onChartBarClicked_.bind(this));
+
+ this.exportButton_ = Polymer.dom(this).querySelector('.export');
+ this.exportButton_.addEventListener(
+ 'click', this.onSaveAsSkPictureClicked_.bind(this));
+
+ this.trackMouse_();
+
+ const overdrawCheckbox = tr.ui.b.createCheckBox(
+ this, 'showOverdraw',
+ 'pictureView.showOverdraw', false,
+ 'Show overdraw');
+
+ const chartCheckbox = tr.ui.b.createCheckBox(
+ this, 'showSummaryChart',
+ 'pictureView.showSummaryChart', false,
+ 'Show timing summary');
+
+ const pictureInfo = Polymer.dom(this).querySelector('picture-info');
+ pictureInfo.style.flexGrow = 0;
+ pictureInfo.style.flexShrink = 0;
+ pictureInfo.style.flexBasis = 'auto';
+ pictureInfo.style.paddingTop = '2px';
+ Polymer.dom(pictureInfo).appendChild(overdrawCheckbox);
+ Polymer.dom(pictureInfo).appendChild(chartCheckbox);
+
+ this.drawOpsView_ = new tr.ui.e.chrome.cc.PictureOpsListView();
+ this.drawOpsView_.flexGrow = 1;
+ this.drawOpsView_.flexShrink = 1;
+ this.drawOpsView_.flexBasis = 'auto';
+ this.drawOpsView_.addEventListener(
+ 'selection-changed', this.onChangeDrawOps_.bind(this));
+
+ const leftPanel = Polymer.dom(this).querySelector('left-panel');
+ leftPanel.style.flexDirection = 'column';
+ leftPanel.style.display = 'flex';
+ leftPanel.style.flexGrow = 0;
+ leftPanel.style.flexShrink = 0;
+ leftPanel.style.flexBasis = 'auto';
+ leftPanel.style.minWidth = '200px';
+ leftPanel.style.overflow = 'auto';
+ Polymer.dom(leftPanel).appendChild(this.drawOpsChartSummaryView_);
+ Polymer.dom(leftPanel).appendChild(this.drawOpsView_);
+
+ const middleDragHandle = document.createElement('tr-ui-b-drag-handle');
+ middleDragHandle.style.flexGrow = 0;
+ middleDragHandle.style.flexShrink = 0;
+ middleDragHandle.style.flexBasis = 'auto';
+ middleDragHandle.horizontal = false;
+ middleDragHandle.target = leftPanel;
+
+ const rightPanel = Polymer.dom(this).querySelector('right-panel');
+ rightPanel.style.flexGrow = 1;
+ rightPanel.style.flexShrink = 1;
+ rightPanel.style.flexBasis = 'auto';
+ rightPanel.style.minWidth = 0;
+ rightPanel.style.flexDirection = 'column';
+ rightPanel.style.display = 'flex';
+
+ const chartView = Polymer.dom(rightPanel).querySelector(
+ 'tr-ui-e-chrome-cc-picture-ops-chart-view');
+ this.drawOpsChartView_.style.flexGrow = 0;
+ this.drawOpsChartView_.style.flexShrink = 0;
+ this.drawOpsChartView_.style.flexBasis = 'auto';
+ this.drawOpsChartView_.style.minWidth = 0;
+ this.drawOpsChartView_.style.overflowX = 'auto';
+ this.drawOpsChartView_.style.overflowY = 'hidden';
+ rightPanel.replaceChild(this.drawOpsChartView_, chartView);
+
+ this.infoBar_ = document.createElement('tr-ui-b-info-bar');
+ Polymer.dom(this.rasterArea_).appendChild(this.infoBar_);
+
+ Polymer.dom(this).insertBefore(middleDragHandle, rightPanel);
+
+ this.picture_ = undefined;
+
+ const hkc = document.createElement('tv-ui-b-hotkey-controller');
+ hkc.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keypress',
+ thisArg: this,
+ keyCode: 'h'.charCodeAt(0),
+ callback(e) {
+ this.moveSelectedOpBy(-1);
+ e.stopPropagation();
+ }
+ }));
+ hkc.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keypress',
+ thisArg: this,
+ keyCode: 'l'.charCodeAt(0),
+ callback(e) {
+ this.moveSelectedOpBy(1);
+ e.stopPropagation();
+ }
+ }));
+ Polymer.dom(this).appendChild(hkc);
+ },
+
+ onSaveAsSkPictureClicked_() {
+ // Decode base64 data into a String
+ const rawData = tr.b.Base64.atob(this.picture_.getBase64SkpData());
+
+ // Convert this String into an Uint8Array
+ const length = rawData.length;
+ const arrayBuffer = new ArrayBuffer(length);
+ const uint8Array = new Uint8Array(arrayBuffer);
+ for (let c = 0; c < length; c++) {
+ uint8Array[c] = rawData.charCodeAt(c);
+ }
+
+ // Create a blob URL from the binary array.
+ const blob = new Blob([uint8Array], {type: 'application/octet-binary'});
+ const blobUrl = window.webkitURL.createObjectURL(blob);
+
+ // Create a link and click on it. BEST API EVAR!
+ const link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
+ link.href = blobUrl;
+ link.download = this.filename_.value;
+ const event = document.createEvent('MouseEvents');
+ event.initMouseEvent(
+ 'click', true, false, window, 0, 0, 0, 0, 0,
+ false, false, false, false, 0, null);
+ link.dispatchEvent(event);
+ },
+
+ get picture() {
+ return this.picture_;
+ },
+
+ set picture(picture) {
+ this.drawOpsView_.picture = picture;
+ this.drawOpsChartView_.picture = picture;
+ this.drawOpsChartSummaryView_.picture = picture;
+ this.picture_ = picture;
+
+ this.exportButton_.disabled = !this.picture_.canSave;
+
+ if (picture) {
+ const size = this.getRasterCanvasSize_();
+ this.rasterCanvas_.width = size.width;
+ this.rasterCanvas_.height = size.height;
+ }
+
+ const bounds = this.rasterArea_.getBoundingClientRect();
+ const selectorBounds = this.mouseModeSelector_.getBoundingClientRect();
+ this.mouseModeSelector_.pos = {
+ x: (bounds.right - selectorBounds.width - 10),
+ y: bounds.top
+ };
+
+ this.rasterize_();
+
+ this.scheduleUpdateContents_();
+ },
+
+ getRasterCanvasSize_() {
+ const style = window.getComputedStyle(this.rasterArea_);
+ const width =
+ Math.max(parseInt(style.width), this.picture_.layerRect.width);
+ const height =
+ Math.max(parseInt(style.height), this.picture_.layerRect.height);
+
+ return {
+ width,
+ height
+ };
+ },
+
+ scheduleUpdateContents_() {
+ if (this.updateContentsPending_) return;
+
+ this.updateContentsPending_ = true;
+ tr.b.requestAnimationFrameInThisFrameIfPossible(
+ this.updateContents_.bind(this)
+ );
+ },
+
+ updateContents_() {
+ this.updateContentsPending_ = false;
+
+ if (this.picture_) {
+ Polymer.dom(this.sizeInfo_).textContent = '(' +
+ this.picture_.layerRect.width + ' x ' +
+ this.picture_.layerRect.height + ')';
+ }
+
+ this.drawOpsChartView_.updateChartContents();
+ this.drawOpsChartView_.scrollSelectedItemIntoViewIfNecessary();
+
+ // Return if picture hasn't finished rasterizing.
+ if (!this.pictureAsImageData_) return;
+
+ this.infoBar_.visible = false;
+ this.infoBar_.removeAllButtons();
+ if (this.pictureAsImageData_.error) {
+ this.infoBar_.message = 'Cannot rasterize...';
+ this.infoBar_.addButton('More info...', function(e) {
+ const overlay = new tr.ui.b.Overlay();
+ Polymer.dom(overlay).textContent = this.pictureAsImageData_.error;
+ overlay.visible = true;
+ e.stopPropagation();
+ return false;
+ }.bind(this));
+ this.infoBar_.visible = true;
+ }
+
+ this.drawPicture_();
+ },
+
+ drawPicture_() {
+ const size = this.getRasterCanvasSize_();
+ if (size.width !== this.rasterCanvas_.width) {
+ this.rasterCanvas_.width = size.width;
+ }
+ if (size.height !== this.rasterCanvas_.height) {
+ this.rasterCanvas_.height = size.height;
+ }
+
+ this.rasterCtx_.clearRect(0, 0, size.width, size.height);
+
+ if (!this.pictureAsImageData_.imageData) return;
+
+ const imgCanvas = this.pictureAsImageData_.asCanvas();
+ const w = imgCanvas.width;
+ const h = imgCanvas.height;
+ this.rasterCtx_.drawImage(imgCanvas, 0, 0, w, h,
+ 0, 0, w * this.zoomScaleValue_,
+ h * this.zoomScaleValue_);
+ },
+
+ rasterize_() {
+ if (this.picture_) {
+ this.picture_.rasterize(
+ {
+ stopIndex: this.drawOpsView_.selectedOpIndex,
+ showOverdraw: this.showOverdraw_
+ },
+ this.onRasterComplete_.bind(this));
+ }
+ },
+
+ onRasterComplete_(pictureAsImageData) {
+ this.pictureAsImageData_ = pictureAsImageData;
+ this.scheduleUpdateContents_();
+ },
+
+ moveSelectedOpBy(increment) {
+ if (this.selectedOpIndex === undefined) {
+ this.selectedOpIndex = 0;
+ return;
+ }
+ this.selectedOpIndex = tr.b.math.clamp(
+ this.selectedOpIndex + increment,
+ 0, this.numOps);
+ },
+
+ get numOps() {
+ return this.drawOpsView_.numOps;
+ },
+
+ get selectedOpIndex() {
+ return this.drawOpsView_.selectedOpIndex;
+ },
+
+ set selectedOpIndex(index) {
+ this.drawOpsView_.selectedOpIndex = index;
+ this.drawOpsChartView_.selectedOpIndex = index;
+ },
+
+ onChartBarClicked_(e) {
+ this.drawOpsView_.selectedOpIndex =
+ this.drawOpsChartView_.selectedOpIndex;
+ },
+
+ onChangeDrawOps_(e) {
+ this.rasterize_();
+ this.scheduleUpdateContents_();
+
+ this.drawOpsChartView_.selectedOpIndex =
+ this.drawOpsView_.selectedOpIndex;
+ },
+
+ set showOverdraw(v) {
+ this.showOverdraw_ = v;
+ this.rasterize_();
+ },
+
+ set showSummaryChart(chartShouldBeVisible) {
+ if (chartShouldBeVisible) {
+ this.drawOpsChartSummaryView_.show();
+ } else {
+ this.drawOpsChartSummaryView_.hide();
+ }
+ },
+
+ trackMouse_() {
+ this.mouseModeSelector_ = document.createElement(
+ 'tr-ui-b-mouse-mode-selector');
+ this.mouseModeSelector_.targetElement = this.rasterArea_;
+ Polymer.dom(this.rasterArea_).appendChild(this.mouseModeSelector_);
+
+ this.mouseModeSelector_.supportedModeMask =
+ tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;
+ this.mouseModeSelector_.mode = tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;
+ this.mouseModeSelector_.defaultMode = tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;
+ this.mouseModeSelector_.settingsKey = 'pictureDebugger.mouseModeSelector';
+
+ this.mouseModeSelector_.addEventListener('beginzoom',
+ this.onBeginZoom_.bind(this));
+ this.mouseModeSelector_.addEventListener('updatezoom',
+ this.onUpdateZoom_.bind(this));
+ this.mouseModeSelector_.addEventListener('endzoom',
+ this.onEndZoom_.bind(this));
+ },
+
+ onBeginZoom_(e) {
+ this.isZooming_ = true;
+
+ this.lastMouseViewPos_ = this.extractRelativeMousePosition_(e);
+
+ e.preventDefault();
+ },
+
+ onUpdateZoom_(e) {
+ if (!this.isZooming_) return;
+
+ const currentMouseViewPos = this.extractRelativeMousePosition_(e);
+
+ // Take the distance the mouse has moved and we want to zoom at about
+ // 1/1000th of that speed. 0.01 feels jumpy. This could possibly be tuned
+ // more if people feel it's too slow.
+ this.zoomScaleValue_ +=
+ ((this.lastMouseViewPos_.y - currentMouseViewPos.y) * 0.001);
+ this.zoomScaleValue_ = Math.max(this.zoomScaleValue_, 0.1);
+
+ this.drawPicture_();
+
+ this.lastMouseViewPos_ = currentMouseViewPos;
+ },
+
+ onEndZoom_(e) {
+ this.lastMouseViewPos_ = undefined;
+ this.isZooming_ = false;
+ e.preventDefault();
+ },
+
+ extractRelativeMousePosition_(e) {
+ return {
+ x: e.clientX - this.rasterArea_.offsetLeft,
+ y: e.clientY - this.rasterArea_.offsetTop
+ };
+ }
+ };
+
+ return {
+ PictureDebugger,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_debugger_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_debugger_test.html
new file mode 100644
index 00000000000..e89e6b355e1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_debugger_test.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/picture_debugger.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const picture = new tr.e.cc.PictureSnapshot({id: '31415'}, 10, {
+ 'params': {
+ 'opaque_rect': [-15, -15, 0, 0],
+ 'layer_rect': [-15, -15, 46, 833]
+ },
+ 'skp64': 'DAAAAHYEAADzAQAABwAAAAFkYWVy8AAAAAgAAB4DAAAADAAAIAAAgD8AAIA/CAAAHgMAAAAcAAADAAAAAAAAAAAAwI5EAID5QwEAAADoAAAACAAAHgMAAAAMAAAjAAAAAAAAAAAMAAAjAAAAAAAAAAAcAAADAAAAAAAAAAAAwI5EAID5QwEAAADkAAAAGAAAFQEAAAAAAAAAAAAAAADAjkQAgPlDGAAAFQIAAAAAAAAAAAAAAADAjkQAgPlDCAAAHgMAAAAcAAADAAAAAAAAAAAAwI5EAID5QwEAAADgAAAAGAAAFQMAAAAAAKBAAACgQAAAgEIAAIBCBAAAHAQAABwEAAAcBAAAHHRjYWYBAAAADVNrU3JjWGZlcm1vZGVjZnB0AAAAAHlhcmGgAAAAIHRucAMAAAAAAEBBAACAPwAAAAAAAIA/AAAAAAAAgEAAAP//ADABAAAAAAAAAEBBAACAPwAAAAAAAIA/AAAAAAAAgED/////AjABAAAAAAAAAAAAAAAAAAEAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEEAAIA/AAAAAAAAgD8AAAAAAACAQP8AAP8AMAEAAAAAACBmb2U=' // @suppress longLineCheck
+ });
+ picture.preInitialize();
+ picture.initialize();
+
+ const dbg = new tr.ui.e.chrome.cc.PictureDebugger();
+ this.addHTMLOutput(dbg);
+ dbg.picture = picture;
+ dbg.style.border = '1px solid black';
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html
new file mode 100644
index 00000000000..55a8685aee0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html
@@ -0,0 +1,458 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ const OPS_TIMING_ITERATIONS = 3;
+ const CHART_PADDING_LEFT = 65;
+ const CHART_PADDING_RIGHT = 40;
+ const AXIS_PADDING_LEFT = 60;
+ const AXIS_PADDING_RIGHT = 35;
+ const AXIS_PADDING_TOP = 25;
+ const AXIS_PADDING_BOTTOM = 45;
+ const AXIS_LABEL_PADDING = 5;
+ const AXIS_TICK_SIZE = 10;
+ const LABEL_PADDING = 5;
+ const LABEL_INTERLEAVE_OFFSET = 15;
+ const BAR_PADDING = 5;
+ const VERTICAL_TICKS = 5;
+ const HUE_CHAR_CODE_ADJUSTMENT = 5.7;
+
+ /**
+ * Provides a chart showing the cumulative time spent in Skia operations
+ * during picture rasterization.
+ *
+ * @constructor
+ */
+ const PictureOpsChartSummaryView = tr.ui.b.define(
+ 'tr-ui-e-chrome-cc-picture-ops-chart-summary-view');
+
+ PictureOpsChartSummaryView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.style.flexGrow = 0;
+ this.style.flexShrink = 0;
+ this.style.flexBasis = 'auto';
+ this.style.fontSize = 0;
+ this.style.margin = 0;
+ this.style.minHeight = '200px';
+ this.style.minWidth = '200px';
+ this.style.overflow = 'hidden';
+ this.style.padding = 0;
+
+ this.picture_ = undefined;
+ this.pictureDataProcessed_ = false;
+
+ this.chartScale_ = window.devicePixelRatio;
+
+ this.chart_ = document.createElement('canvas');
+ this.chartCtx_ = this.chart_.getContext('2d');
+ Polymer.dom(this).appendChild(this.chart_);
+
+ this.opsTimingData_ = [];
+
+ this.chartWidth_ = 0;
+ this.chartHeight_ = 0;
+ this.requiresRedraw_ = true;
+
+ this.currentBarMouseOverTarget_ = null;
+
+ this.chart_.addEventListener('mousemove', this.onMouseMove_.bind(this));
+ new ResizeObserver(this.onResize_.bind(this)).observe(this);
+ },
+
+ get requiresRedraw() {
+ return this.requiresRedraw_;
+ },
+
+ set requiresRedraw(requiresRedraw) {
+ this.requiresRedraw_ = requiresRedraw;
+ },
+
+ get picture() {
+ return this.picture_;
+ },
+
+ set picture(picture) {
+ this.picture_ = picture;
+ this.pictureDataProcessed_ = false;
+
+ if (Polymer.dom(this).classList.contains('hidden')) return;
+
+ this.processPictureData_();
+ this.requiresRedraw = true;
+ this.updateChartContents();
+ },
+
+ hide() {
+ Polymer.dom(this).classList.add('hidden');
+ this.style.display = 'none';
+ },
+
+ show() {
+ Polymer.dom(this).classList.remove('hidden');
+ this.style.display = '';
+
+ if (!this.pictureDataProcessed_) {
+ this.processPictureData_();
+ }
+ this.requiresRedraw = true;
+ this.updateChartContents();
+ },
+
+ onMouseMove_(e) {
+ const lastBarMouseOverTarget = this.currentBarMouseOverTarget_;
+ this.currentBarMouseOverTarget_ = null;
+
+ const x = e.offsetX;
+ const y = e.offsetY;
+
+ const chartLeft = CHART_PADDING_LEFT;
+ const chartRight = this.chartWidth_ - CHART_PADDING_RIGHT;
+ const chartTop = AXIS_PADDING_TOP;
+ const chartBottom = this.chartHeight_ - AXIS_PADDING_BOTTOM;
+ const chartInnerWidth = chartRight - chartLeft;
+
+ if (x > chartLeft && x < chartRight && y > chartTop && y < chartBottom) {
+ this.currentBarMouseOverTarget_ = Math.floor(
+ (x - chartLeft) / chartInnerWidth * this.opsTimingData_.length);
+
+ this.currentBarMouseOverTarget_ = tr.b.math.clamp(
+ this.currentBarMouseOverTarget_, 0, this.opsTimingData_.length - 1);
+ }
+
+ if (this.currentBarMouseOverTarget_ === lastBarMouseOverTarget) return;
+
+ this.drawChartContents_();
+ },
+
+ onResize_() {
+ this.requiresRedraw = true;
+ this.updateChartContents();
+ },
+
+ updateChartContents() {
+ if (this.requiresRedraw) {
+ this.updateChartDimensions_();
+ }
+
+ this.drawChartContents_();
+ },
+
+ updateChartDimensions_() {
+ this.chartWidth_ = this.offsetWidth;
+ this.chartHeight_ = this.offsetHeight;
+
+ // Scale up the canvas according to the devicePixelRatio, then reduce it
+ // down again via CSS. Finally we apply a scale to the canvas so that
+ // things are drawn at the correct size.
+ this.chart_.width = this.chartWidth_ * this.chartScale_;
+ this.chart_.height = this.chartHeight_ * this.chartScale_;
+
+ this.chart_.style.width = this.chartWidth_ + 'px';
+ this.chart_.style.height = this.chartHeight_ + 'px';
+
+ this.chartCtx_.scale(this.chartScale_, this.chartScale_);
+ },
+
+ processPictureData_() {
+ this.resetOpsTimingData_();
+ this.pictureDataProcessed_ = true;
+
+ if (!this.picture_) return;
+
+ let ops = this.picture_.getOps();
+ if (!ops) return;
+
+ ops = this.picture_.tagOpsWithTimings(ops);
+
+ // Check that there are valid times.
+ if (ops[0].cmd_time === undefined) return;
+
+ this.collapseOpsToTimingBuckets_(ops);
+ },
+
+ drawChartContents_() {
+ this.clearChartContents_();
+
+ if (this.opsTimingData_.length === 0) {
+ this.showNoTimingDataMessage_();
+ return;
+ }
+
+ this.drawChartAxes_();
+ this.drawBars_();
+ this.drawLineAtBottomOfChart_();
+
+ if (this.currentBarMouseOverTarget_ === null) return;
+
+ this.drawTooltip_();
+ },
+
+ drawLineAtBottomOfChart_() {
+ this.chartCtx_.strokeStyle = '#AAA';
+ this.chartCtx_.moveTo(0, this.chartHeight_ - 0.5);
+ this.chartCtx_.lineTo(this.chartWidth_, this.chartHeight_ - 0.5);
+ this.chartCtx_.stroke();
+ },
+
+ drawTooltip_() {
+ const tooltipData = this.opsTimingData_[this.currentBarMouseOverTarget_];
+ const tooltipTitle = tooltipData.cmd_string;
+ const tooltipTime = tooltipData.cmd_time.toFixed(4);
+
+ const tooltipWidth = 110;
+ const tooltipHeight = 40;
+ const chartInnerWidth = this.chartWidth_ - CHART_PADDING_RIGHT -
+ CHART_PADDING_LEFT;
+ const barWidth = chartInnerWidth / this.opsTimingData_.length;
+ const tooltipOffset = Math.round((tooltipWidth - barWidth) * 0.5);
+
+ const left = CHART_PADDING_LEFT + this.currentBarMouseOverTarget_ *
+ barWidth - tooltipOffset;
+ const top = Math.round((this.chartHeight_ - tooltipHeight) * 0.5);
+
+ this.chartCtx_.save();
+
+ this.chartCtx_.shadowOffsetX = 0;
+ this.chartCtx_.shadowOffsetY = 5;
+ this.chartCtx_.shadowBlur = 4;
+ this.chartCtx_.shadowColor = 'rgba(0,0,0,0.4)';
+
+ this.chartCtx_.strokeStyle = '#888';
+ this.chartCtx_.fillStyle = '#EEE';
+ this.chartCtx_.fillRect(left, top, tooltipWidth, tooltipHeight);
+
+ this.chartCtx_.shadowColor = 'transparent';
+ this.chartCtx_.translate(0.5, 0.5);
+ this.chartCtx_.strokeRect(left, top, tooltipWidth, tooltipHeight);
+
+ this.chartCtx_.restore();
+
+ this.chartCtx_.fillStyle = '#222';
+ this.chartCtx_.textBaseline = 'top';
+ this.chartCtx_.font = '800 12px Arial';
+ this.chartCtx_.fillText(tooltipTitle, left + 8, top + 8);
+
+ this.chartCtx_.fillStyle = '#555';
+ this.chartCtx_.textBaseline = 'top';
+ this.chartCtx_.font = '400 italic 10px Arial';
+ this.chartCtx_.fillText('Total: ' + tooltipTime + 'ms',
+ left + 8, top + 22);
+ },
+
+ drawBars_() {
+ const len = this.opsTimingData_.length;
+ const max = this.opsTimingData_[0].cmd_time;
+ const min = this.opsTimingData_[len - 1].cmd_time;
+
+ const width = this.chartWidth_ - CHART_PADDING_LEFT - CHART_PADDING_RIGHT;
+ const height = this.chartHeight_ - AXIS_PADDING_TOP - AXIS_PADDING_BOTTOM;
+ const barWidth = Math.floor(width / len);
+
+ let opData;
+ let opTiming;
+ let opHeight;
+ let opLabel;
+ let barLeft;
+
+ for (let b = 0; b < len; b++) {
+ opData = this.opsTimingData_[b];
+ opTiming = opData.cmd_time / max;
+
+ opHeight = Math.round(Math.max(1, opTiming * height));
+ opLabel = opData.cmd_string;
+ barLeft = CHART_PADDING_LEFT + b * barWidth;
+
+ this.chartCtx_.fillStyle = this.getOpColor_(opLabel);
+
+ this.chartCtx_.fillRect(barLeft + BAR_PADDING, AXIS_PADDING_TOP +
+ height - opHeight, barWidth - 2 * BAR_PADDING, opHeight);
+ }
+ },
+
+ getOpColor_(opName) {
+ const characters = opName.split('');
+ const hue = characters.reduce(this.reduceNameToHue, 0) % 360;
+
+ return 'hsl(' + hue + ', 30%, 50%)';
+ },
+
+ reduceNameToHue(previousValue, currentValue, index, array) {
+ // Get the char code and apply a magic adjustment value so we get
+ // pretty colors from around the rainbow.
+ return Math.round(previousValue + currentValue.charCodeAt(0) *
+ HUE_CHAR_CODE_ADJUSTMENT);
+ },
+
+ drawChartAxes_() {
+ const len = this.opsTimingData_.length;
+ const max = this.opsTimingData_[0].cmd_time;
+ const min = this.opsTimingData_[len - 1].cmd_time;
+
+ const width = this.chartWidth_ - AXIS_PADDING_LEFT - AXIS_PADDING_RIGHT;
+ const height = this.chartHeight_ - AXIS_PADDING_TOP - AXIS_PADDING_BOTTOM;
+
+ const totalBarWidth = this.chartWidth_ - CHART_PADDING_LEFT -
+ CHART_PADDING_RIGHT;
+ const barWidth = Math.floor(totalBarWidth / len);
+ const tickYInterval = height / (VERTICAL_TICKS - 1);
+ let tickYPosition = 0;
+ const tickValInterval = (max - min) / (VERTICAL_TICKS - 1);
+ let tickVal = 0;
+
+ this.chartCtx_.fillStyle = '#333';
+ this.chartCtx_.strokeStyle = '#777';
+ this.chartCtx_.save();
+
+ // Translate half a pixel to avoid blurry lines.
+ this.chartCtx_.translate(0.5, 0.5);
+
+ // Sides.
+
+ this.chartCtx_.save();
+
+ this.chartCtx_.translate(AXIS_PADDING_LEFT, AXIS_PADDING_TOP);
+ this.chartCtx_.moveTo(0, 0);
+ this.chartCtx_.lineTo(0, height);
+ this.chartCtx_.lineTo(width, height);
+
+ // Y-axis ticks.
+ this.chartCtx_.font = '10px Arial';
+ this.chartCtx_.textAlign = 'right';
+ this.chartCtx_.textBaseline = 'middle';
+
+ for (let t = 0; t < VERTICAL_TICKS; t++) {
+ tickYPosition = Math.round(t * tickYInterval);
+ tickVal = (max - t * tickValInterval).toFixed(4);
+
+ this.chartCtx_.moveTo(0, tickYPosition);
+ this.chartCtx_.lineTo(-AXIS_TICK_SIZE, tickYPosition);
+ this.chartCtx_.fillText(tickVal,
+ -AXIS_TICK_SIZE - AXIS_LABEL_PADDING, tickYPosition);
+ }
+
+ this.chartCtx_.stroke();
+
+ this.chartCtx_.restore();
+
+
+ // Labels.
+
+ this.chartCtx_.save();
+
+ this.chartCtx_.translate(CHART_PADDING_LEFT + Math.round(barWidth * 0.5),
+ AXIS_PADDING_TOP + height + LABEL_PADDING);
+
+ this.chartCtx_.font = '10px Arial';
+ this.chartCtx_.textAlign = 'center';
+ this.chartCtx_.textBaseline = 'top';
+
+ let labelTickLeft;
+ let labelTickBottom;
+ for (let l = 0; l < len; l++) {
+ labelTickLeft = Math.round(l * barWidth);
+ labelTickBottom = l % 2 * LABEL_INTERLEAVE_OFFSET;
+
+ this.chartCtx_.save();
+ this.chartCtx_.moveTo(labelTickLeft, -LABEL_PADDING);
+ this.chartCtx_.lineTo(labelTickLeft, labelTickBottom);
+ this.chartCtx_.stroke();
+ this.chartCtx_.restore();
+
+ this.chartCtx_.fillText(this.opsTimingData_[l].cmd_string,
+ labelTickLeft, labelTickBottom);
+ }
+
+ this.chartCtx_.restore();
+
+ this.chartCtx_.restore();
+ },
+
+ clearChartContents_() {
+ this.chartCtx_.clearRect(0, 0, this.chartWidth_, this.chartHeight_);
+ },
+
+ showNoTimingDataMessage_() {
+ this.chartCtx_.font = '800 italic 14px Arial';
+ this.chartCtx_.fillStyle = '#333';
+ this.chartCtx_.textAlign = 'center';
+ this.chartCtx_.textBaseline = 'middle';
+ this.chartCtx_.fillText('No timing data available.',
+ this.chartWidth_ * 0.5, this.chartHeight_ * 0.5);
+ },
+
+ collapseOpsToTimingBuckets_(ops) {
+ const opsTimingDataIndexHash_ = {};
+ const timingData = this.opsTimingData_;
+ let op;
+ let opIndex;
+
+ for (let i = 0; i < ops.length; i++) {
+ op = ops[i];
+
+ if (op.cmd_time === undefined) continue;
+
+ // Try to locate the entry for the current operation
+ // based on its name. If that fails, then create one for it.
+ opIndex = opsTimingDataIndexHash_[op.cmd_string] || null;
+
+ if (opIndex === null) {
+ timingData.push({
+ cmd_time: 0,
+ cmd_string: op.cmd_string
+ });
+
+ opIndex = timingData.length - 1;
+ opsTimingDataIndexHash_[op.cmd_string] = opIndex;
+ }
+
+ timingData[opIndex].cmd_time += op.cmd_time;
+ }
+
+ timingData.sort(this.sortTimingBucketsByOpTimeDescending_);
+
+ this.collapseTimingBucketsToOther_(4);
+ },
+
+ collapseTimingBucketsToOther_(count) {
+ const timingData = this.opsTimingData_;
+ const otherSource = timingData.splice(count, timingData.length - count);
+ let otherDestination = null;
+
+ if (!otherSource.length) return;
+
+ timingData.push({
+ cmd_time: 0,
+ cmd_string: 'Other'
+ });
+
+ otherDestination = timingData[timingData.length - 1];
+ for (let i = 0; i < otherSource.length; i++) {
+ otherDestination.cmd_time += otherSource[i].cmd_time;
+ }
+ },
+
+ sortTimingBucketsByOpTimeDescending_(a, b) {
+ return b.cmd_time - a.cmd_time;
+ },
+
+ resetOpsTimingData_() {
+ this.opsTimingData_.length = 0;
+ }
+ };
+
+ return {
+ PictureOpsChartSummaryView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html
new file mode 100644
index 00000000000..413998847aa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html
@@ -0,0 +1,505 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ const BAR_PADDING = 1;
+ const BAR_WIDTH = 5;
+ const CHART_PADDING_LEFT = 65;
+ const CHART_PADDING_RIGHT = 30;
+ const CHART_PADDING_BOTTOM = 35;
+ const CHART_PADDING_TOP = 20;
+ const AXIS_PADDING_LEFT = 55;
+ const AXIS_PADDING_RIGHT = 30;
+ const AXIS_PADDING_BOTTOM = 35;
+ const AXIS_PADDING_TOP = 20;
+ const AXIS_TICK_SIZE = 5;
+ const AXIS_LABEL_PADDING = 5;
+ const VERTICAL_TICKS = 5;
+ const HUE_CHAR_CODE_ADJUSTMENT = 5.7;
+
+ /**
+ * Provides a chart showing the cumulative time spent in Skia operations
+ * during picture rasterization.
+ *
+ * @constructor
+ */
+ const PictureOpsChartView =
+ tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-chart-view');
+
+ PictureOpsChartView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.style.display = 'block';
+ this.style.height = '180px';
+ this.style.margin = 0;
+ this.style.padding = 0;
+ this.style.position = 'relative';
+
+ this.picture_ = undefined;
+ this.pictureOps_ = undefined;
+ this.opCosts_ = undefined;
+
+ this.chartScale_ = window.devicePixelRatio;
+
+ this.chart_ = document.createElement('canvas');
+ this.chartCtx_ = this.chart_.getContext('2d');
+ Polymer.dom(this).appendChild(this.chart_);
+
+ this.selectedOpIndex_ = undefined;
+ this.chartWidth_ = 0;
+ this.chartHeight_ = 0;
+ this.dimensionsHaveChanged_ = true;
+
+ this.currentBarMouseOverTarget_ = undefined;
+
+ this.ninetyFifthPercentileCost_ = 0;
+ this.totalOpCost_ = 0;
+
+ this.chart_.addEventListener('click', this.onClick_.bind(this));
+ this.chart_.addEventListener('mousemove', this.onMouseMove_.bind(this));
+ new ResizeObserver(this.onResize_.bind(this)).observe(this);
+
+ this.usePercentileScale_ = false;
+ this.usePercentileScaleCheckbox_ = tr.ui.b.createCheckBox(
+ this, 'usePercentileScale',
+ 'PictureOpsChartView.usePercentileScale', false,
+ 'Limit to 95%-ile');
+ Polymer.dom(this.usePercentileScaleCheckbox_).classList.add(
+ 'use-percentile-scale');
+ this.usePercentileScaleCheckbox_.style.position = 'absolute';
+ this.usePercentileScaleCheckbox_.style.left = 0;
+ this.usePercentileScaleCheckbox_.style.top = 0;
+ Polymer.dom(this).appendChild(this.usePercentileScaleCheckbox_);
+ },
+
+ get dimensionsHaveChanged() {
+ return this.dimensionsHaveChanged_;
+ },
+
+ set dimensionsHaveChanged(dimensionsHaveChanged) {
+ this.dimensionsHaveChanged_ = dimensionsHaveChanged;
+ },
+
+ get usePercentileScale() {
+ return this.usePercentileScale_;
+ },
+
+ set usePercentileScale(usePercentileScale) {
+ this.usePercentileScale_ = usePercentileScale;
+ this.drawChartContents_();
+ },
+
+ get numOps() {
+ return this.opCosts_.length;
+ },
+
+ get selectedOpIndex() {
+ return this.selectedOpIndex_;
+ },
+
+ set selectedOpIndex(selectedOpIndex) {
+ if (selectedOpIndex < 0) throw new Error('Invalid index');
+ if (selectedOpIndex >= this.numOps) throw new Error('Invalid index');
+
+ this.selectedOpIndex_ = selectedOpIndex;
+ },
+
+ get picture() {
+ return this.picture_;
+ },
+
+ set picture(picture) {
+ this.picture_ = picture;
+ this.pictureOps_ = picture.tagOpsWithTimings(picture.getOps());
+ this.currentBarMouseOverTarget_ = undefined;
+ this.processPictureData_();
+ this.dimensionsHaveChanged = true;
+ },
+
+ processPictureData_() {
+ if (this.pictureOps_ === undefined) return;
+
+ let totalOpCost = 0;
+
+ // Take a copy of the picture ops data for sorting.
+ this.opCosts_ = this.pictureOps_.map(function(op) {
+ totalOpCost += op.cmd_time;
+ return op.cmd_time;
+ });
+ this.opCosts_.sort();
+
+ const ninetyFifthPercentileCostIndex = Math.floor(
+ this.opCosts_.length * 0.95);
+ this.ninetyFifthPercentileCost_ =
+ this.opCosts_[ninetyFifthPercentileCostIndex];
+ this.maxCost_ = this.opCosts_[this.opCosts_.length - 1];
+
+ this.totalOpCost_ = totalOpCost;
+ },
+
+ extractBarIndex_(e) {
+ let index = undefined;
+
+ if (this.pictureOps_ === undefined ||
+ this.pictureOps_.length === 0) {
+ return index;
+ }
+
+ const x = e.offsetX;
+ const y = e.offsetY;
+
+ const totalBarWidth = (BAR_WIDTH + BAR_PADDING) * this.pictureOps_.length;
+
+ const chartLeft = CHART_PADDING_LEFT;
+ const chartTop = 0;
+ const chartBottom = this.chartHeight_ - CHART_PADDING_BOTTOM;
+ const chartRight = chartLeft + totalBarWidth;
+
+ if (x < chartLeft || x > chartRight || y < chartTop || y > chartBottom) {
+ return index;
+ }
+
+ index = Math.floor((x - chartLeft) / totalBarWidth *
+ this.pictureOps_.length);
+
+ index = tr.b.math.clamp(index, 0, this.pictureOps_.length - 1);
+
+ return index;
+ },
+
+ onClick_(e) {
+ const barClicked = this.extractBarIndex_(e);
+
+ if (barClicked === undefined) return;
+
+ // If we click on the already selected item we should deselect.
+ if (barClicked === this.selectedOpIndex) {
+ this.selectedOpIndex = undefined;
+ } else {
+ this.selectedOpIndex = barClicked;
+ }
+
+ e.preventDefault();
+
+ tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
+ },
+
+ onMouseMove_(e) {
+ const lastBarMouseOverTarget = this.currentBarMouseOverTarget_;
+ this.currentBarMouseOverTarget_ = this.extractBarIndex_(e);
+
+ if (this.currentBarMouseOverTarget_ === lastBarMouseOverTarget) {
+ return;
+ }
+
+ this.drawChartContents_();
+ },
+
+ onResize_() {
+ this.dimensionsHaveChanged = true;
+ this.updateChartContents();
+ },
+
+ scrollSelectedItemIntoViewIfNecessary() {
+ if (this.selectedOpIndex === undefined) {
+ return;
+ }
+
+ const width = this.offsetWidth;
+ const left = this.scrollLeft;
+ const right = left + width;
+ const targetLeft = CHART_PADDING_LEFT +
+ (BAR_WIDTH + BAR_PADDING) * this.selectedOpIndex;
+
+ if (targetLeft > left && targetLeft < right) {
+ return;
+ }
+
+ this.scrollLeft = (targetLeft - width * 0.5);
+ },
+
+ updateChartContents() {
+ if (this.dimensionsHaveChanged) {
+ this.updateChartDimensions_();
+ }
+
+ this.drawChartContents_();
+ },
+
+ updateChartDimensions_() {
+ if (!this.pictureOps_) return;
+
+ let width = CHART_PADDING_LEFT + CHART_PADDING_RIGHT +
+ ((BAR_WIDTH + BAR_PADDING) * this.pictureOps_.length);
+
+ if (width < this.offsetWidth) {
+ width = this.offsetWidth;
+ }
+
+ // Allow the element to be its natural size as set by flexbox, then lock
+ // the width in before we set the width of the canvas.
+ this.chartWidth_ = width;
+ this.chartHeight_ = this.getBoundingClientRect().height;
+
+ // Scale up the canvas according to the devicePixelRatio, then reduce it
+ // down again via CSS. Finally we apply a scale to the canvas so that
+ // things are drawn at the correct size.
+ this.chart_.width = this.chartWidth_ * this.chartScale_;
+ this.chart_.height = this.chartHeight_ * this.chartScale_;
+
+ this.chart_.style.width = this.chartWidth_ + 'px';
+ this.chart_.style.height = this.chartHeight_ + 'px';
+
+ this.chartCtx_.scale(this.chartScale_, this.chartScale_);
+
+ this.dimensionsHaveChanged = false;
+ },
+
+ drawChartContents_() {
+ this.clearChartContents_();
+
+ if (this.pictureOps_ === undefined ||
+ this.pictureOps_.length === 0 ||
+ this.pictureOps_[0].cmd_time === undefined) {
+ this.showNoTimingDataMessage_();
+ return;
+ }
+
+ this.drawSelection_();
+ this.drawBars_();
+ this.drawChartAxes_();
+ this.drawLinesAtTickMarks_();
+ this.drawLineAtBottomOfChart_();
+
+ if (this.currentBarMouseOverTarget_ === undefined) {
+ return;
+ }
+
+ this.drawTooltip_();
+ },
+
+ drawSelection_() {
+ if (this.selectedOpIndex === undefined) {
+ return;
+ }
+
+ const width = (BAR_WIDTH + BAR_PADDING) * this.selectedOpIndex;
+ this.chartCtx_.fillStyle = 'rgb(223, 235, 230)';
+ this.chartCtx_.fillRect(CHART_PADDING_LEFT, CHART_PADDING_TOP,
+ width, this.chartHeight_ - CHART_PADDING_TOP - CHART_PADDING_BOTTOM);
+ },
+
+ drawChartAxes_() {
+ const min = this.opCosts_[0];
+ const max = this.opCosts_[this.opCosts_.length - 1];
+ const height = this.chartHeight_ - AXIS_PADDING_TOP - AXIS_PADDING_BOTTOM;
+
+ const tickYInterval = height / (VERTICAL_TICKS - 1);
+ let tickYPosition = 0;
+ const tickValInterval = (max - min) / (VERTICAL_TICKS - 1);
+ let tickVal = 0;
+
+ this.chartCtx_.fillStyle = '#333';
+ this.chartCtx_.strokeStyle = '#777';
+ this.chartCtx_.save();
+
+ // Translate half a pixel to avoid blurry lines.
+ this.chartCtx_.translate(0.5, 0.5);
+
+ // Sides.
+ this.chartCtx_.beginPath();
+ this.chartCtx_.moveTo(AXIS_PADDING_LEFT, AXIS_PADDING_TOP);
+ this.chartCtx_.lineTo(AXIS_PADDING_LEFT, this.chartHeight_ -
+ AXIS_PADDING_BOTTOM);
+ this.chartCtx_.lineTo(this.chartWidth_ - AXIS_PADDING_RIGHT,
+ this.chartHeight_ - AXIS_PADDING_BOTTOM);
+ this.chartCtx_.stroke();
+ this.chartCtx_.closePath();
+
+ // Y-axis ticks.
+ this.chartCtx_.translate(AXIS_PADDING_LEFT, AXIS_PADDING_TOP);
+
+ this.chartCtx_.font = '10px Arial';
+ this.chartCtx_.textAlign = 'right';
+ this.chartCtx_.textBaseline = 'middle';
+
+ this.chartCtx_.beginPath();
+ for (let t = 0; t < VERTICAL_TICKS; t++) {
+ tickYPosition = Math.round(t * tickYInterval);
+ tickVal = (max - t * tickValInterval).toFixed(4);
+
+ this.chartCtx_.moveTo(0, tickYPosition);
+ this.chartCtx_.lineTo(-AXIS_TICK_SIZE, tickYPosition);
+ this.chartCtx_.fillText(tickVal,
+ -AXIS_TICK_SIZE - AXIS_LABEL_PADDING, tickYPosition);
+ }
+
+ this.chartCtx_.stroke();
+ this.chartCtx_.closePath();
+
+ this.chartCtx_.restore();
+ },
+
+ drawLinesAtTickMarks_() {
+ const height = this.chartHeight_ - AXIS_PADDING_TOP - AXIS_PADDING_BOTTOM;
+ const width = this.chartWidth_ - AXIS_PADDING_LEFT - AXIS_PADDING_RIGHT;
+ const tickYInterval = height / (VERTICAL_TICKS - 1);
+ let tickYPosition = 0;
+
+ this.chartCtx_.save();
+
+ this.chartCtx_.translate(AXIS_PADDING_LEFT + 0.5, AXIS_PADDING_TOP + 0.5);
+ this.chartCtx_.beginPath();
+ this.chartCtx_.strokeStyle = 'rgba(0,0,0,0.05)';
+
+ for (let t = 0; t < VERTICAL_TICKS; t++) {
+ tickYPosition = Math.round(t * tickYInterval);
+
+ this.chartCtx_.moveTo(0, tickYPosition);
+ this.chartCtx_.lineTo(width, tickYPosition);
+ this.chartCtx_.stroke();
+ }
+
+ this.chartCtx_.restore();
+ this.chartCtx_.closePath();
+ },
+
+ drawLineAtBottomOfChart_() {
+ this.chartCtx_.strokeStyle = '#AAA';
+ this.chartCtx_.beginPath();
+ this.chartCtx_.moveTo(0, this.chartHeight_ - 0.5);
+ this.chartCtx_.lineTo(this.chartWidth_, this.chartHeight_ - 0.5);
+ this.chartCtx_.stroke();
+ this.chartCtx_.closePath();
+ },
+
+ drawTooltip_() {
+ const tooltipData = this.pictureOps_[this.currentBarMouseOverTarget_];
+ const tooltipTitle = tooltipData.cmd_string;
+ const tooltipTime = tooltipData.cmd_time.toFixed(4);
+ const toolTipTimePercentage =
+ ((tooltipData.cmd_time / this.totalOpCost_) * 100).toFixed(2);
+
+ const tooltipWidth = 120;
+ const tooltipHeight = 40;
+ const chartInnerWidth = this.chartWidth_ - CHART_PADDING_RIGHT -
+ CHART_PADDING_LEFT;
+ const barWidth = BAR_WIDTH + BAR_PADDING;
+ const tooltipOffset = Math.round((tooltipWidth - barWidth) * 0.5);
+
+ const left = CHART_PADDING_LEFT + this.currentBarMouseOverTarget_ *
+ barWidth - tooltipOffset;
+ const top = Math.round((this.chartHeight_ - tooltipHeight) * 0.5);
+
+ this.chartCtx_.save();
+
+ this.chartCtx_.shadowOffsetX = 0;
+ this.chartCtx_.shadowOffsetY = 5;
+ this.chartCtx_.shadowBlur = 4;
+ this.chartCtx_.shadowColor = 'rgba(0,0,0,0.4)';
+
+ this.chartCtx_.strokeStyle = '#888';
+ this.chartCtx_.fillStyle = '#EEE';
+ this.chartCtx_.fillRect(left, top, tooltipWidth, tooltipHeight);
+
+ this.chartCtx_.shadowColor = 'transparent';
+ this.chartCtx_.translate(0.5, 0.5);
+ this.chartCtx_.strokeRect(left, top, tooltipWidth, tooltipHeight);
+
+ this.chartCtx_.restore();
+
+ this.chartCtx_.fillStyle = '#222';
+ this.chartCtx_.textAlign = 'left';
+ this.chartCtx_.textBaseline = 'top';
+ this.chartCtx_.font = '800 12px Arial';
+ this.chartCtx_.fillText(tooltipTitle, left + 8, top + 8);
+
+ this.chartCtx_.fillStyle = '#555';
+ this.chartCtx_.font = '400 italic 10px Arial';
+ this.chartCtx_.fillText(tooltipTime + 'ms (' +
+ toolTipTimePercentage + '%)', left + 8, top + 22);
+ },
+
+ drawBars_() {
+ let op;
+ let opColor = 0;
+ let opHeight = 0;
+ const opWidth = BAR_WIDTH + BAR_PADDING;
+ let opHover = false;
+
+ const bottom = this.chartHeight_ - CHART_PADDING_BOTTOM;
+ const maxHeight = this.chartHeight_ - CHART_PADDING_BOTTOM -
+ CHART_PADDING_TOP;
+
+ let maxValue;
+ if (this.usePercentileScale) {
+ maxValue = this.ninetyFifthPercentileCost_;
+ } else {
+ maxValue = this.maxCost_;
+ }
+
+ for (let b = 0; b < this.pictureOps_.length; b++) {
+ op = this.pictureOps_[b];
+ opHeight = Math.round(
+ (op.cmd_time / maxValue) * maxHeight);
+ opHeight = Math.max(opHeight, 1);
+ opHover = (b === this.currentBarMouseOverTarget_);
+ opColor = this.getOpColor_(op.cmd_string, opHover);
+
+ if (b === this.selectedOpIndex) {
+ this.chartCtx_.fillStyle = '#FFFF00';
+ } else {
+ this.chartCtx_.fillStyle = opColor;
+ }
+
+ this.chartCtx_.fillRect(CHART_PADDING_LEFT + b * opWidth,
+ bottom - opHeight, BAR_WIDTH, opHeight);
+ }
+ },
+
+ getOpColor_(opName, hover) {
+ const characters = opName.split('');
+
+ const hue = characters.reduce(this.reduceNameToHue, 0) % 360;
+ const saturation = 30;
+ const lightness = hover ? '75%' : '50%';
+
+ return 'hsl(' + hue + ', ' + saturation + '%, ' + lightness + '%)';
+ },
+
+ reduceNameToHue(previousValue, currentValue, index, array) {
+ // Get the char code and apply a magic adjustment value so we get
+ // pretty colors from around the rainbow.
+ return Math.round(previousValue + currentValue.charCodeAt(0) *
+ HUE_CHAR_CODE_ADJUSTMENT);
+ },
+
+ clearChartContents_() {
+ this.chartCtx_.clearRect(0, 0, this.chartWidth_, this.chartHeight_);
+ },
+
+ showNoTimingDataMessage_() {
+ this.chartCtx_.font = '800 italic 14px Arial';
+ this.chartCtx_.fillStyle = '#333';
+ this.chartCtx_.textAlign = 'center';
+ this.chartCtx_.textBaseline = 'middle';
+ this.chartCtx_.fillText('No timing data available.',
+ this.chartWidth_ * 0.5, this.chartHeight_ * 0.5);
+ }
+ };
+
+ return {
+ PictureOpsChartView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_list_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_list_view.html
new file mode 100644
index 00000000000..2e45be58c33
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_list_view.html
@@ -0,0 +1,261 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/constants.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/list_view.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/selection.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ const OPS_TIMING_ITERATIONS = 3; // Iterations to average op timing info over.
+ const ANNOTATION = 'Comment';
+ const BEGIN_ANNOTATION = 'BeginCommentGroup';
+ const END_ANNOTATION = 'EndCommentGroup';
+ const ANNOTATION_ID = 'ID: ';
+ const ANNOTATION_CLASS = 'CLASS: ';
+ const ANNOTATION_TAG = 'TAG: ';
+
+ const constants = tr.e.cc.constants;
+
+ /**
+ * @constructor
+ */
+ const PictureOpsListView =
+ tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-list-view');
+
+ PictureOpsListView.prototype = {
+ __proto__: HTMLDivElement.prototype,
+
+ decorate() {
+ this.style.borderTop = '1px solid grey';
+ this.style.overflow = 'auto';
+ this.opsList_ = new tr.ui.b.ListView();
+ Polymer.dom(this).appendChild(this.opsList_);
+
+ this.selectedOp_ = undefined;
+ this.selectedOpIndex_ = undefined;
+ this.opsList_.addEventListener(
+ 'selection-changed', this.onSelectionChanged_.bind(this));
+
+ this.picture_ = undefined;
+ },
+
+ get picture() {
+ return this.picture_;
+ },
+
+ set picture(picture) {
+ this.picture_ = picture;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ this.opsList_.clear();
+
+ if (!this.picture_) return;
+
+ let ops = this.picture_.getOps();
+ if (!ops) return;
+
+ ops = this.picture_.tagOpsWithTimings(ops);
+
+ ops = this.opsTaggedWithAnnotations_(ops);
+
+ for (let i = 0; i < ops.length; i++) {
+ const op = ops[i];
+ const item = document.createElement('div');
+ item.opIndex = op.opIndex;
+ Polymer.dom(item).textContent = i + ') ' + op.cmd_string;
+
+ // Display the element info associated with the op, if available.
+ if (op.elementInfo.tag || op.elementInfo.id || op.elementInfo.class) {
+ const elementInfo = document.createElement('span');
+ Polymer.dom(elementInfo).classList.add('elementInfo');
+ elementInfo.style.color = 'purple';
+ elementInfo.style.fontSize = 'small';
+ elementInfo.style.fontWeight = 'bold';
+ elementInfo.style.color = '#777';
+ const tag = op.elementInfo.tag ? op.elementInfo.tag : 'unknown';
+ const id = op.elementInfo.id ? 'id=' + op.elementInfo.id : undefined;
+ const className = op.elementInfo.class ? 'class=' +
+ op.elementInfo.class : undefined;
+ Polymer.dom(elementInfo).textContent =
+ '<' + tag + (id ? ' ' : '') +
+ (id ? id : '') + (className ? ' ' : '') +
+ (className ? className : '') + '>';
+ Polymer.dom(item).appendChild(elementInfo);
+ }
+
+ // Display the Skia params.
+ // FIXME: now that we have structured data, we should format it.
+ // (https://github.com/google/trace-viewer/issues/782)
+ if (op.info.length > 0) {
+ const infoItem = document.createElement('div');
+ Polymer.dom(infoItem).textContent = JSON.stringify(op.info);
+ infoItem.style.fontSize = 'x-small';
+ infoItem.style.color = '#777';
+ Polymer.dom(item).appendChild(infoItem);
+ }
+
+ // Display the op timing, if available.
+ if (op.cmd_time && op.cmd_time >= 0.0001) {
+ const time = document.createElement('span');
+ Polymer.dom(time).classList.add('time');
+ const rounded = op.cmd_time.toFixed(4);
+ Polymer.dom(time).textContent = '(' + rounded + 'ms)';
+ time.style.fontSize = 'x-small';
+ time.style.color = 'rgb(136, 0, 0)';
+ Polymer.dom(item).appendChild(time);
+ }
+
+ item.style.borderBottom = '1px solid #555';
+ item.style.fontSize = 'small';
+ item.style.fontWeight = 'bold';
+ item.style.paddingBottom = '5px';
+ item.style.paddingLeft = '5px';
+ item.style.cursor = 'pointer';
+
+ for (const child of item.children) {
+ child.style.fontWeight = 'normal';
+ child.style.marginLeft = '1em';
+ child.style.maxWidth = '300px';
+ }
+
+ Polymer.dom(this.opsList_).appendChild(item);
+ }
+ },
+
+ onSelectionChanged_(e) {
+ let beforeSelectedOp = true;
+
+ // Deselect on re-selection.
+ if (this.opsList_.selectedElement === this.selectedOp_) {
+ this.opsList_.selectedElement = undefined;
+ beforeSelectedOp = false;
+ this.selectedOpIndex_ = undefined;
+ }
+
+ this.selectedOp_ = this.opsList_.selectedElement;
+
+ // Set selection on all previous ops.
+ const ops = this.opsList_.children;
+ for (let i = 0; i < ops.length; i++) {
+ const op = ops[i];
+ if (op === this.selectedOp_) {
+ beforeSelectedOp = false;
+ this.selectedOpIndex_ = op.opIndex;
+ } else if (beforeSelectedOp) {
+ Polymer.dom(op).setAttribute('beforeSelection', 'beforeSelection');
+ op.style.backgroundColor = 'rgb(103, 199, 165)';
+ } else {
+ Polymer.dom(op).removeAttribute('beforeSelection');
+ op.style.backgroundColor = '';
+ }
+ }
+
+ tr.b.dispatchSimpleEvent(this, 'selection-changed', false);
+ },
+
+ get numOps() {
+ return this.opsList_.children.length;
+ },
+
+ get selectedOpIndex() {
+ return this.selectedOpIndex_;
+ },
+
+ set selectedOpIndex(s) {
+ this.selectedOpIndex_ = s;
+
+ if (s === undefined) {
+ this.opsList_.selectedElement = this.selectedOp_;
+ this.onSelectionChanged_();
+ } else {
+ if (s < 0) throw new Error('Invalid index');
+ if (s >= this.numOps) throw new Error('Invalid index');
+ this.opsList_.selectedElement = this.opsList_.getElementByIndex(s + 1);
+ tr.ui.b.scrollIntoViewIfNeeded(this.opsList_.selectedElement);
+ }
+ },
+
+ /**
+ * Return Skia operations tagged by annotation.
+ *
+ * The ops returned from Picture.getOps() contain both Skia ops and
+ * annotations threaded together. This function removes all annotations
+ * from the list and tags each op with the associated annotations.
+ * Additionally, the last {tag, id, class} is stored as elementInfo on
+ * each op.
+ *
+ * @param {Array} ops Array of Skia operations and annotations.
+ * @return {Array} Skia ops where op.annotations contains the associated
+ * annotations for a given op.
+ */
+ opsTaggedWithAnnotations_(ops) {
+ // This algorithm works by walking all the ops and pushing any
+ // annotations onto a stack. When a non-annotation op is found, the
+ // annotations stack is traversed and stored with the op.
+ const annotationGroups = [];
+ const opsWithoutAnnotations = [];
+ for (let opIndex = 0; opIndex < ops.length; opIndex++) {
+ const op = ops[opIndex];
+ op.opIndex = opIndex;
+ switch (op.cmd_string) {
+ case BEGIN_ANNOTATION:
+ annotationGroups.push([]);
+ break;
+ case END_ANNOTATION:
+ annotationGroups.pop();
+ break;
+ case ANNOTATION:
+ annotationGroups[annotationGroups.length - 1].push(op);
+ break;
+ default: {
+ const annotations = [];
+ let elementInfo = {};
+ annotationGroups.forEach(function(annotationGroup) {
+ elementInfo = {};
+ annotationGroup.forEach(function(annotation) {
+ annotation.info.forEach(function(info) {
+ if (info.includes(ANNOTATION_TAG)) {
+ elementInfo.tag = info.substring(
+ info.indexOf(ANNOTATION_TAG) +
+ ANNOTATION_TAG.length).toLowerCase();
+ } else if (info.includes(ANNOTATION_ID)) {
+ elementInfo.id = info.substring(
+ info.indexOf(ANNOTATION_ID) +
+ ANNOTATION_ID.length);
+ } else if (info.includes(ANNOTATION_CLASS)) {
+ elementInfo.class = info.substring(
+ info.indexOf(ANNOTATION_CLASS) +
+ ANNOTATION_CLASS.length);
+ }
+
+ annotations.push(info);
+ });
+ });
+ });
+ op.annotations = annotations;
+ op.elementInfo = elementInfo;
+ opsWithoutAnnotations.push(op);
+ }
+ }
+ }
+
+ return opsWithoutAnnotations;
+ }
+ };
+
+ return {
+ PictureOpsListView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_list_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_list_view_test.html
new file mode 100644
index 00000000000..b58c1568f4f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_ops_list_view_test.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/picture_ops_list_view.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const PictureOpsListView = tr.ui.e.chrome.cc.PictureOpsListView;
+
+ test('instantiate', function() {
+ if (!tr.e.cc.PictureSnapshot.CanRasterize()) return;
+
+ const m = new tr.Model(g_catLTHIEvents);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('cc::Picture')[0];
+ const snapshot = instance.snapshots[0];
+
+ const view = new PictureOpsListView();
+ view.picture = snapshot;
+ assert.strictEqual(view.opsList_.children.length, 142);
+ });
+
+ test('selection', function() {
+ if (!tr.e.cc.PictureSnapshot.CanRasterize()) return;
+
+ const m = new tr.Model(g_catLTHIEvents);
+ const p = Object.values(m.processes)[0];
+
+ const instance = p.objects.getAllInstancesNamed('cc::Picture')[0];
+ const snapshot = instance.snapshots[0];
+
+ const view = new PictureOpsListView();
+ view.picture = snapshot;
+ let didSelectionChange = 0;
+ view.addEventListener('selection-changed', function() {
+ didSelectionChange = true;
+ });
+ assert.isFalse(didSelectionChange);
+ view.opsList_.selectedElement = view.opsList_.children[3];
+ assert.isTrue(didSelectionChange);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_view.html
new file mode 100644
index 00000000000..a9db575773f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/picture_view.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/picture_debugger.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ /*
+ * Displays a picture snapshot in a human readable form.
+ * @constructor
+ */
+ const PictureSnapshotView = tr.ui.b.define(
+ 'tr-ui-e-chrome-cc-picture-snapshot-view',
+ tr.ui.analysis.ObjectSnapshotView);
+
+ PictureSnapshotView.prototype = {
+ __proto__: tr.ui.analysis.ObjectSnapshotView.prototype,
+
+ decorate() {
+ Polymer.dom(this).classList.add(
+ 'tr-ui-e-chrome-cc-picture-snapshot-view');
+ this.style.display = 'flex';
+ this.style.flexGrow = 1;
+ this.style.flexShrink = 1;
+ this.style.flexBasis = 'auto';
+ this.style.minWidth = 0;
+ this.pictureDebugger_ = new tr.ui.e.chrome.cc.PictureDebugger();
+ this.pictureDebugger_.style.flexGrow = 1;
+ this.pictureDebugger_.style.flexShrink = 1;
+ this.pictureDebugger_.style.flexBasis = 'auto';
+ this.pictureDebugger_.style.minWidth = 0;
+ Polymer.dom(this).appendChild(this.pictureDebugger_);
+ },
+
+ updateContents() {
+ if (this.objectSnapshot_ && this.pictureDebugger_) {
+ this.pictureDebugger_.picture = this.objectSnapshot_;
+ }
+ }
+ };
+
+ tr.ui.analysis.ObjectSnapshotView.register(
+ PictureSnapshotView,
+ {
+ typeNames: ['cc::Picture', 'cc::LayeredPicture'],
+ showInstances: false
+ });
+
+ return {
+ PictureSnapshotView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection.html
new file mode 100644
index 00000000000..6b1a7cb7df0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/extras/chrome/cc/raster_task.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/single_event_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/raster_task_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/selection.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ /**
+ * @constructor
+ */
+ function RasterTaskSelection(selection) {
+ tr.ui.e.chrome.cc.Selection.call(this);
+ const whySupported = RasterTaskSelection.whySuported(selection);
+ if (!whySupported.ok) {
+ throw new Error('Fail: ' + whySupported.why);
+ }
+ this.slices_ = Array.from(selection);
+ this.tiles_ = this.slices_.map(function(slice) {
+ const tile = tr.e.cc.getTileFromRasterTaskSlice(slice);
+ if (tile === undefined) {
+ throw new Error('This should never happen due to .supports check.');
+ }
+ return tile;
+ });
+ }
+
+ RasterTaskSelection.whySuported = function(selection) {
+ if (!(selection instanceof tr.model.EventSet)) {
+ return {ok: false, why: 'Must be selection'};
+ }
+
+ if (selection.length === 0) {
+ return {ok: false, why: 'Selection must be non empty'};
+ }
+
+ let referenceSnapshot = undefined;
+ for (const event of selection) {
+ if (!(event instanceof tr.model.Slice)) {
+ return {ok: false, why: 'Not a slice'};
+ }
+
+ const tile = tr.e.cc.getTileFromRasterTaskSlice(event);
+ if (tile === undefined) {
+ return {ok: false, why: 'No tile found'};
+ }
+
+ if (!referenceSnapshot) {
+ referenceSnapshot = tile.containingSnapshot;
+ } else {
+ if (tile.containingSnapshot !== referenceSnapshot) {
+ return {
+ ok: false,
+ why: 'Raster tasks are from different compositor instances'
+ };
+ }
+ }
+ }
+ return {ok: true};
+ };
+
+ RasterTaskSelection.supports = function(selection) {
+ return RasterTaskSelection.whySuported(selection).ok;
+ };
+
+ RasterTaskSelection.prototype = {
+ __proto__: tr.ui.e.chrome.cc.Selection.prototype,
+
+ get specicifity() {
+ return 3;
+ },
+
+ get associatedLayerId() {
+ const tile0 = this.tiles_[0];
+ const allSameLayer = this.tiles_.every(function(tile) {
+ tile.layerId === tile0.layerId;
+ });
+ if (allSameLayer) {
+ return tile0.layerId;
+ }
+ return undefined;
+ },
+
+ get extraHighlightsByLayerId() {
+ const highlights = {};
+ this.tiles_.forEach(function(tile, i) {
+ if (highlights[tile.layerId] === undefined) {
+ highlights[tile.layerId] = [];
+ }
+ const slice = this.slices_[i];
+ highlights[tile.layerId].push({
+ colorKey: slice.title,
+ rect: tile.layerRect
+ });
+ }, this);
+ return highlights;
+ },
+
+ createAnalysis() {
+ const sel = new tr.model.EventSet();
+ this.slices_.forEach(function(slice) {
+ sel.push(slice);
+ });
+
+ let analysis;
+ if (sel.length === 1) {
+ analysis = document.createElement('tr-ui-a-single-event-sub-view');
+ } else {
+ analysis = document.createElement('tr-ui-e-chrome-cc-raster-task-view');
+ }
+ analysis.selection = sel;
+ return analysis;
+ },
+
+ findEquivalent(lthi) {
+ // Raster tasks are only valid in one LTHI.
+ return undefined;
+ },
+
+ // RasterTaskSelection specific stuff follows.
+ get containingSnapshot() {
+ return this.tiles_[0].containingSnapshot;
+ }
+ };
+
+ return {
+ RasterTaskSelection,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection_test.html
new file mode 100644
index 00000000000..d95a7135d37
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_selection_test.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/raster_task_selection.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = m.processes[1];
+ const rasterTasks = p.threads[1].sliceGroup.slices.filter(function(slice) {
+ return slice.title === 'RasterTask';
+ });
+
+ let selection = new tr.model.EventSet();
+ selection.push(rasterTasks[0]);
+ selection.push(rasterTasks[1]);
+
+ assert.isTrue(tr.ui.e.chrome.cc.RasterTaskSelection.supports(selection));
+ selection = new tr.ui.e.chrome.cc.RasterTaskSelection(selection);
+ const highlights = selection.extraHighlightsByLayerId;
+ assert.lengthOf(Object.keys(highlights), 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view.html
new file mode 100644
index 00000000000..a5f7f5d806c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view.html
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/extras/chrome/cc/raster_task.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/selection.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-e-chrome-cc-raster-task-view'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ #heading {
+ flex: 0 0 auto;
+ }
+ tr-ui-b-table {
+ font-size: 12px;
+ }
+ </style>
+
+ <div id="heading">
+ Rasterization costs in
+ <tr-ui-a-analysis-link id="link"></tr-ui-a-analysis-link>
+ </div>
+ <tr-ui-b-table id="content"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+Polymer({
+ is: 'tr-ui-e-chrome-cc-raster-task-view',
+
+ created() {
+ this.selection_ = undefined;
+ },
+
+ set selection(selection) {
+ this.selection_ = selection;
+
+ this.updateContents_();
+ },
+
+ updateColumns_(hadCpuDurations) {
+ const timeSpanConfig = {
+ unit: tr.b.Unit.byName.timeDurationInMs,
+ ownerDocument: this.ownerDocument
+ };
+
+ const columns = [
+ {
+ title: 'Layer',
+ value(row) {
+ if (row.isTotals) return 'Totals';
+ if (row.layer) {
+ const linkEl = document.createElement('tr-ui-a-analysis-link');
+ linkEl.setSelectionAndContent(
+ function() {
+ return new tr.ui.e.chrome.cc.LayerSelection(row.layer);
+ },
+ 'Layer ' + row.layerId);
+ return linkEl;
+ }
+ return 'Layer ' + row.layerId;
+ },
+ width: '250px'
+ },
+ {
+ title: 'Num Tiles',
+ value(row) { return row.numTiles; },
+ cmp(a, b) { return a.numTiles - b.numTiles; }
+ },
+ {
+ title: 'Num Analysis Tasks',
+ value(row) { return row.numAnalysisTasks; },
+ cmp(a, b) {
+ return a.numAnalysisTasks - b.numAnalysisTasks;
+ }
+ },
+ {
+ title: 'Num Raster Tasks',
+ value(row) { return row.numRasterTasks; },
+ cmp(a, b) { return a.numRasterTasks - b.numRasterTasks; }
+ },
+ {
+ title: 'Wall Duration (ms)',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.duration, timeSpanConfig);
+ },
+ cmp(a, b) { return a.duration - b.duration; }
+ }
+ ];
+
+ if (hadCpuDurations) {
+ columns.push({
+ title: 'CPU Duration (ms)',
+ value(row) {
+ return tr.v.ui.createScalarSpan(row.cpuDuration, timeSpanConfig);
+ },
+ cmp(a, b) { return a.cpuDuration - b.cpuDuration; }
+ });
+ }
+
+ let colWidthPercentage;
+ if (columns.length === 1) {
+ colWidthPercentage = '100%';
+ } else {
+ colWidthPercentage = (100 / (columns.length - 1)).toFixed(3) + '%';
+ }
+
+ for (let i = 1; i < columns.length; i++) {
+ columns[i].width = colWidthPercentage;
+ }
+
+ this.$.content.tableColumns = columns;
+ this.$.content.sortColumnIndex = columns.length - 1;
+ },
+
+ updateContents_() {
+ const table = this.$.content;
+
+ if (this.selection_.length === 0) {
+ this.$.link.setSelectionAndContent(undefined, '');
+ table.tableRows = [];
+ table.footerRows = [];
+ table.rebuild();
+ return;
+ }
+ // LTHI link.
+ const lthi = tr.e.cc.getTileFromRasterTaskSlice(
+ tr.b.getFirstElement(this.selection_)).containingSnapshot;
+ this.$.link.setSelectionAndContent(function() {
+ return new tr.model.EventSet(lthi);
+ }, lthi.userFriendlyName);
+
+ // Get costs by layer.
+ const costsByLayerId = {};
+ function getCurrentCostsForLayerId(tile) {
+ const layerId = tile.layerId;
+ const lthi = tile.containingSnapshot;
+ let layer;
+ if (lthi.activeTree) {
+ layer = lthi.activeTree.findLayerWithId(layerId);
+ }
+ if (layer === undefined && lthi.pendingTree) {
+ layer = lthi.pendingTree.findLayerWithId(layerId);
+ }
+ if (costsByLayerId[layerId] === undefined) {
+ costsByLayerId[layerId] = {
+ layerId,
+ layer,
+ numTiles: 0,
+ numAnalysisTasks: 0,
+ numRasterTasks: 0,
+ duration: 0,
+ cpuDuration: 0
+ };
+ }
+ return costsByLayerId[layerId];
+ }
+
+ let totalDuration = 0;
+ let totalCpuDuration = 0;
+ let totalNumAnalyzeTasks = 0;
+ let totalNumRasterizeTasks = 0;
+ let hadCpuDurations = false;
+
+ const tilesThatWeHaveSeen = {};
+
+ this.selection_.forEach(function(slice) {
+ const tile = tr.e.cc.getTileFromRasterTaskSlice(slice);
+ const curCosts = getCurrentCostsForLayerId(tile);
+
+ if (!tilesThatWeHaveSeen[tile.objectInstance.id]) {
+ tilesThatWeHaveSeen[tile.objectInstance.id] = true;
+ curCosts.numTiles += 1;
+ }
+
+ if (tr.e.cc.isSliceDoingAnalysis(slice)) {
+ curCosts.numAnalysisTasks += 1;
+ totalNumAnalyzeTasks += 1;
+ } else {
+ curCosts.numRasterTasks += 1;
+ totalNumRasterizeTasks += 1;
+ }
+ curCosts.duration += slice.duration;
+ totalDuration += slice.duration;
+ if (slice.cpuDuration !== undefined) {
+ curCosts.cpuDuration += slice.cpuDuration;
+ totalCpuDuration += slice.cpuDuration;
+ hadCpuDurations = true;
+ }
+ });
+
+ // Apply to the table.
+ this.updateColumns_(hadCpuDurations);
+ table.tableRows = Object.values(costsByLayerId);
+ table.rebuild();
+
+ // Footer.
+ table.footerRows = [
+ {
+ isTotals: true,
+ numTiles: Object.keys(tilesThatWeHaveSeen).length,
+ numAnalysisTasks: totalNumAnalyzeTasks,
+ numRasterTasks: totalNumRasterizeTasks,
+ duration: totalDuration,
+ cpuDuration: totalCpuDuration
+ }
+ ];
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html
new file mode 100644
index 00000000000..56767cfcc89
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/raster_task_view_test.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/layer_tree_host_impl_view.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/raster_task_selection.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/raster_task_view.html">
+
+<script src="/tracing/extras/chrome/cc/layer_tree_host_impl_test_data.js">
+</script>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createSelection() {
+ const m = tr.c.TestUtils.newModelWithEvents([g_catLTHIEvents]);
+ const p = m.processes[1];
+ const rasterTasks = p.threads[1].sliceGroup.slices.filter(function(slice) {
+ return slice.title === 'RasterTask' || slice.title === 'AnalyzeTask';
+ });
+
+ const selection = new tr.model.EventSet();
+ selection.model = m;
+
+ selection.push(rasterTasks[0]);
+ selection.push(rasterTasks[1]);
+ return selection;
+ }
+
+ test('basic', function() {
+ const selection = createSelection();
+ const view = document.createElement('tr-ui-e-chrome-cc-raster-task-view');
+ view.selection = selection;
+ this.addHTMLOutput(view);
+ });
+
+ test('analysisViewIntegration', function() {
+ const selection = createSelection();
+
+ const timelineView = {model: selection.model};
+ const brushingStateController =
+ new tr.c.BrushingStateController(timelineView);
+
+ const analysisEl = document.createElement('tr-ui-a-analysis-view');
+ analysisEl.brushingStateController = brushingStateController;
+ brushingStateController.changeSelectionFromTimeline(selection);
+
+ assert.isDefined(Polymer.dom(analysisEl).querySelector(
+ 'tr-ui-e-chrome-cc-raster-task-view'));
+
+ const sv = tr.ui.b.findDeepElementMatching(
+ analysisEl, 'tr-ui-a-multi-thread-slice-sub-view');
+ assert.isTrue(sv.requiresTallView);
+ this.addHTMLOutput(analysisEl);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/selection.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/selection.html
new file mode 100644
index 00000000000..2794540e115
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/selection.html
@@ -0,0 +1,304 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ function Selection() {
+ this.selectionToSetIfClicked = undefined;
+ }
+ Selection.prototype = {
+ /**
+ * When two things are picked in the UI, one must occasionally tie-break
+ * between them to decide what was really clicked. Things with higher
+ * specicifity will win.
+ */
+ get specicifity() {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * If a selection is related to a specific layer, then this returns the
+ * layerId of that layer. If the selection is not related to a layer, for
+ * example if the device viewport is selected, then this returns undefined.
+ */
+ get associatedLayerId() {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * If a selection is related to a specific render pass, then this returns
+ * the layerId of that layer. If the selection is not related to a layer,
+ * for example if the device viewport is selected, then this returns
+ * undefined.
+ */
+ get associatedRenderPassId() {
+ throw new Error('Not implemented');
+ },
+
+
+ get highlightsByLayerId() {
+ return {};
+ },
+
+ /**
+ * Called when the selection is made active in the layer view. Must return
+ * an HTMLElement that explains this selection in detail.
+ */
+ createAnalysis() {
+ throw new Error('Not implemented');
+ },
+
+ /**
+ * Should try to create the equivalent selection in the provided LTHI,
+ * or undefined if it can't be done.
+ */
+ findEquivalent(lthi) {
+ throw new Error('Not implemented');
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function RenderPassSelection(renderPass, renderPassId) {
+ if (!renderPass || (renderPassId === undefined)) {
+ throw new Error('Render pass (with id) is required');
+ }
+ this.renderPass_ = renderPass;
+ this.renderPassId_ = renderPassId;
+ }
+
+ RenderPassSelection.prototype = {
+ __proto__: Selection.prototype,
+
+ get specicifity() {
+ return 1;
+ },
+
+ get associatedLayerId() {
+ return undefined;
+ },
+
+ get associatedRenderPassId() {
+ return this.renderPassId_;
+ },
+
+ get renderPass() {
+ return this.renderPass_;
+ },
+
+ createAnalysis() {
+ const dataView = document.createElement(
+ 'tr-ui-a-generic-object-view-with-label');
+ dataView.label = 'RenderPass ' + this.renderPassId_;
+ dataView.object = this.renderPass_.args;
+ return dataView;
+ },
+
+ get title() {
+ return this.renderPass_.objectInstance.typeName;
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function LayerSelection(layer) {
+ if (!layer) {
+ throw new Error('Layer is required');
+ }
+ this.layer_ = layer;
+ }
+
+ LayerSelection.prototype = {
+ __proto__: Selection.prototype,
+
+ get specicifity() {
+ return 1;
+ },
+
+ get associatedLayerId() {
+ return this.layer_.layerId;
+ },
+
+ get associatedRenderPassId() {
+ return undefined;
+ },
+
+ get layer() {
+ return this.layer_;
+ },
+
+ createAnalysis() {
+ const dataView = document.createElement(
+ 'tr-ui-a-generic-object-view-with-label');
+ dataView.label = 'Layer ' + this.layer_.layerId;
+ if (this.layer_.usingGpuRasterization) {
+ dataView.label += ' (GPU-rasterized)';
+ }
+ dataView.object = this.layer_.args;
+ return dataView;
+ },
+
+ get title() {
+ return this.layer_.objectInstance.typeName;
+ },
+
+ findEquivalent(lthi) {
+ const layer = lthi.activeTree.findLayerWithId(this.layer_.layerId) ||
+ lthi.pendingTree.findLayerWithId(this.layer_.layerId);
+ if (!layer) return undefined;
+ return new LayerSelection(layer);
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function TileSelection(tile, opt_data) {
+ this.tile_ = tile;
+ this.data_ = opt_data || {};
+ }
+
+ TileSelection.prototype = {
+ __proto__: Selection.prototype,
+
+ get specicifity() {
+ return 2;
+ },
+
+ get associatedLayerId() {
+ return this.tile_.layerId;
+ },
+
+ get highlightsByLayerId() {
+ const highlights = {};
+ highlights[this.tile_.layerId] = [
+ {
+ colorKey: this.tile_.objectInstance.typeName,
+ rect: this.tile_.layerRect
+ }
+ ];
+ return highlights;
+ },
+
+ createAnalysis() {
+ const analysis = document.createElement(
+ 'tr-ui-a-generic-object-view-with-label');
+ analysis.label = 'Tile ' + this.tile_.objectInstance.id + ' on layer ' +
+ this.tile_.layerId;
+ if (this.data_) {
+ analysis.object = {
+ moreInfo: this.data_,
+ tileArgs: this.tile_.args
+ };
+ } else {
+ analysis.object = this.tile_.args;
+ }
+ return analysis;
+ },
+
+ findEquivalent(lthi) {
+ const tileInstance = this.tile_.tileInstance;
+ if (lthi.ts < tileInstance.creationTs ||
+ lthi.ts >= tileInstance.deletionTs) {
+ return undefined;
+ }
+ const tileSnapshot = tileInstance.getSnapshotAt(lthi.ts);
+ if (!tileSnapshot) return undefined;
+ return new TileSelection(tileSnapshot);
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function LayerRectSelection(layer, rectType, rect, opt_data) {
+ this.layer_ = layer;
+ this.rectType_ = rectType;
+ this.rect_ = rect;
+ this.data_ = opt_data !== undefined ? opt_data : rect;
+ }
+
+ LayerRectSelection.prototype = {
+ __proto__: Selection.prototype,
+
+ get specicifity() {
+ return 2;
+ },
+
+ get associatedLayerId() {
+ return this.layer_.layerId;
+ },
+
+
+ get highlightsByLayerId() {
+ const highlights = {};
+ highlights[this.layer_.layerId] = [
+ {
+ colorKey: this.rectType_,
+ rect: this.rect_
+ }
+ ];
+ return highlights;
+ },
+
+ createAnalysis() {
+ const analysis = document.createElement(
+ 'tr-ui-a-generic-object-view-with-label');
+ analysis.label = this.rectType_ + ' on layer ' + this.layer_.layerId;
+ analysis.object = this.data_;
+ return analysis;
+ },
+
+ findEquivalent(lthi) {
+ return undefined;
+ }
+ };
+
+ /**
+ * @constructor
+ */
+ function AnimationRectSelection(layer, rect) {
+ this.layer_ = layer;
+ this.rect_ = rect;
+ }
+
+ AnimationRectSelection.prototype = {
+ __proto__: Selection.prototype,
+
+ get specicifity() {
+ return 0;
+ },
+
+ get associatedLayerId() {
+ return this.layer_.layerId;
+ },
+
+ createAnalysis() {
+ const analysis = document.createElement(
+ 'tr-ui-a-generic-object-view-with-label');
+ analysis.label = 'Animation Bounds of layer ' + this.layer_.layerId;
+ analysis.object = this.rect_;
+ return analysis;
+ }
+ };
+
+ return {
+ Selection,
+ RenderPassSelection,
+ LayerSelection,
+ TileSelection,
+ LayerRectSelection,
+ AnimationRectSelection,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/tile_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/tile_view.html
new file mode 100644
index 00000000000..ad1f633f334
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/cc/tile_view.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/cc/tile.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
+
+<script>
+
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.cc', function() {
+ /*
+ * Displays a tile in a human readable form.
+ * @constructor
+ */
+ const TileSnapshotView = tr.ui.b.define(
+ 'tr-ui-e-chrome-cc-tile-snapshot-view',
+ tr.ui.analysis.ObjectSnapshotView);
+
+ TileSnapshotView.prototype = {
+ __proto__: tr.ui.analysis.ObjectSnapshotView.prototype,
+
+ decorate() {
+ Polymer.dom(this).classList.add('tr-ui-e-chrome-cc-tile-snapshot-view');
+ this.layerTreeView_ =
+ new tr.ui.e.chrome.cc.LayerTreeHostImplSnapshotView();
+ Polymer.dom(this).appendChild(this.layerTreeView_);
+ },
+
+ updateContents() {
+ const tile = this.objectSnapshot_;
+ const layerTreeHostImpl = tile.containingSnapshot;
+ if (!layerTreeHostImpl) return;
+
+ this.layerTreeView_.objectSnapshot = layerTreeHostImpl;
+ this.layerTreeView_.selection = new tr.ui.e.chrome.cc.TileSelection(tile);
+ }
+ };
+
+ tr.ui.analysis.ObjectSnapshotView.register(
+ TileSnapshotView,
+ {
+ typeName: 'cc::Tile',
+ showInTrackView: false
+ });
+
+ return {
+ TileSnapshotView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/codesearch.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/codesearch.html
new file mode 100644
index 00000000000..af6c79447bc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/codesearch.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Copyright 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<dom-module id='tr-ui-e-chrome-codesearch'>
+ <template>
+ <style>
+ :host {
+ white-space: nowrap;
+ }
+ #codesearchLink {
+ font-size: x-small;
+ margin-left: 20px;
+ text-decoration: none;
+ }
+ </style>
+ <a id="codesearchLink" target=_blank on-click="onClick">&#x1F50D;</a>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome', function() {
+ Polymer({
+ is: 'tr-ui-e-chrome-codesearch',
+
+ set searchPhrase(phrase) {
+ const link = Polymer.dom(this.$.codesearchLink);
+ const codeSearchURL =
+ 'https://cs.chromium.org/search/?sq=package:chromium&type=cs&q=';
+ link.setAttribute('href', codeSearchURL + encodeURIComponent(phrase));
+ },
+
+ onClick(clickEvent) {
+ // Let the event trigger the default action of following the link. Stop
+ // the propagation of the event here, so that subsequent handlers do not
+ // intercept the clicks.
+ clickEvent.stopPropagation();
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/gpu.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/gpu.html
new file mode 100644
index 00000000000..ec7991b6640
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/gpu.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/gpu/gpu_async_slice.html">
+<link rel="import" href="/tracing/extras/chrome/gpu/state.html">
+<link rel="import" href="/tracing/ui/extras/chrome/gpu/state_view.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/images/checkerboard.png b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/images/checkerboard.png
new file mode 100644
index 00000000000..8ea9bc726bb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/images/checkerboard.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/state_view.css b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/state_view.css
new file mode 100644
index 00000000000..7c2c34787dc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/state_view.css
@@ -0,0 +1,15 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.tr-ui-e-chrome-gpu-state-snapshot-view {
+ background: url('./images/checkerboard.png');
+ display: flex;
+ overflow: auto;
+}
+
+.tr-ui-e-chrome-gpu-state-snapshot-view img {
+ display: block;
+ margin: 16px auto 16px auto;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/state_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/state_view.html
new file mode 100644
index 00000000000..ba6c345be5f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/gpu/state_view.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet" href="/tracing/ui/extras/chrome/gpu/state_view.css">
+
+<link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.chrome.gpu', function() {
+ /*
+ * Displays a GPU state snapshot in a human readable form.
+ * @constructor
+ */
+ const StateSnapshotView = tr.ui.b.define(
+ 'tr-ui-e-chrome-gpu-state-snapshot-view',
+ tr.ui.analysis.ObjectSnapshotView);
+
+ StateSnapshotView.prototype = {
+ __proto__: tr.ui.analysis.ObjectSnapshotView.prototype,
+
+ decorate() {
+ Polymer.dom(this).classList.add('tr-ui-e-chrome-gpu-state-snapshot-view');
+ this.screenshotImage_ = document.createElement('img');
+ Polymer.dom(this).appendChild(this.screenshotImage_);
+ },
+
+ updateContents() {
+ if (this.objectSnapshot_ && this.objectSnapshot_.screenshot) {
+ this.screenshotImage_.src = 'data:image/png;base64,' +
+ this.objectSnapshot_.screenshot;
+ }
+ }
+ };
+ tr.ui.analysis.ObjectSnapshotView.register(
+ StateSnapshotView,
+ {typeName: 'gpu::State'});
+
+ return {
+ StateSnapshotView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/layout_tree_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/layout_tree_sub_view.html
new file mode 100644
index 00000000000..db80ef75afa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome/layout_tree_sub_view.html
@@ -0,0 +1,229 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/chrome/layout_tree.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+
+<dom-module id='tr-ui-a-layout-tree-sub-view'>
+ <template>
+ <style>
+ tr-ui-b-table {
+ font-size: 12px;
+ }
+ </style>
+ <div id="content"></div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.analysis', function() {
+ Polymer({
+ is: 'tr-ui-a-layout-tree-sub-view',
+ behaviors: ['tr-ui-a-sub-view'],
+
+ set selection(selection) {
+ this.currentSelection_ = selection;
+ this.updateContents_();
+ },
+
+ get selection() {
+ return this.currentSelection_;
+ },
+
+ updateContents_() {
+ this.set('$.content.textContent', '');
+ if (!this.currentSelection_) return;
+
+ const columns = [
+ {
+ title: 'Tag/Name',
+ value(layoutObject) {
+ return layoutObject.tag || ':' + layoutObject.name;
+ }
+ },
+
+ {
+ title: 'htmlId',
+ value(layoutObject) {
+ return layoutObject.htmlId || '';
+ }
+ },
+
+ {
+ title: 'classNames',
+ value(layoutObject) {
+ return layoutObject.classNames || '';
+ }
+ },
+
+ {
+ title: 'reasons',
+ value(layoutObject) {
+ return layoutObject.needsLayoutReasons.join(', ');
+ }
+ },
+
+ {
+ title: 'width',
+ value(layoutObject) {
+ return layoutObject.absoluteRect.width;
+ }
+ },
+
+ {
+ title: 'height',
+ value(layoutObject) {
+ return layoutObject.absoluteRect.height;
+ }
+ },
+
+ {
+ title: 'absX',
+ value(layoutObject) {
+ return layoutObject.absoluteRect.left;
+ }
+ },
+
+ {
+ title: 'absY',
+ value(layoutObject) {
+ return layoutObject.absoluteRect.top;
+ }
+ },
+
+ {
+ title: 'relX',
+ value(layoutObject) {
+ return layoutObject.relativeRect.left;
+ }
+ },
+
+ {
+ title: 'relY',
+ value(layoutObject) {
+ return layoutObject.relativeRect.top;
+ }
+ },
+
+ {
+ title: 'float',
+ value(layoutObject) {
+ return layoutObject.isFloat ? 'float' : '';
+ }
+ },
+
+ {
+ title: 'positioned',
+ value(layoutObject) {
+ return layoutObject.isPositioned ? 'positioned' : '';
+ }
+ },
+
+ {
+ title: 'relative',
+ value(layoutObject) {
+ return layoutObject.isRelativePositioned ? 'relative' : '';
+ }
+ },
+
+ {
+ title: 'sticky',
+ value(layoutObject) {
+ return layoutObject.isStickyPositioned ? 'sticky' : '';
+ }
+ },
+
+ {
+ title: 'anonymous',
+ value(layoutObject) {
+ return layoutObject.isAnonymous ? 'anonymous' : '';
+ }
+ },
+
+ {
+ title: 'row',
+ value(layoutObject) {
+ if (layoutObject.tableRow === undefined) {
+ return '';
+ }
+ return layoutObject.tableRow;
+ }
+ },
+
+ {
+ title: 'col',
+ value(layoutObject) {
+ if (layoutObject.tableCol === undefined) {
+ return '';
+ }
+ return layoutObject.tableCol;
+ }
+ },
+
+ {
+ title: 'rowSpan',
+ value(layoutObject) {
+ if (layoutObject.tableRowSpan === undefined) {
+ return '';
+ }
+ return layoutObject.tableRowSpan;
+ }
+ },
+
+ {
+ title: 'colSpan',
+ value(layoutObject) {
+ if (layoutObject.tableColSpan === undefined) {
+ return '';
+ }
+ return layoutObject.tableColSpan;
+ }
+ },
+
+ {
+ title: 'address',
+ value(layoutObject) {
+ return layoutObject.id.toString(16);
+ }
+ }
+ ];
+
+ const table = this.ownerDocument.createElement('tr-ui-b-table');
+ table.defaultExpansionStateCallback = function(
+ layoutObject, parentLayoutObject) {
+ return true;
+ };
+ table.subRowsPropertyName = 'childLayoutObjects';
+ table.tableColumns = columns;
+ table.tableRows = this.currentSelection_.map(function(snapshot) {
+ return snapshot.rootLayoutObject;
+ });
+ table.rebuild();
+ Polymer.dom(this.$.content).appendChild(table);
+ },
+ });
+
+ return {};
+});
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-layout-tree-sub-view',
+ tr.e.chrome.LayoutTreeSnapshot,
+ {
+ multi: false,
+ title: 'Layout Tree',
+ });
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-a-layout-tree-sub-view',
+ tr.e.chrome.LayoutTreeSnapshot,
+ {
+ multi: true,
+ title: 'Layout Trees',
+ });
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome_config.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome_config.html
new file mode 100644
index 00000000000..cea42a2d78c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/chrome_config.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+The chrome config is heavily used:
+ - chrome://tracing,
+ - trace2html, which in turn implies
+ - adb_profile_chrome
+ - telemetry
+-->
+
+<!--
+TODO(charliea): Make all UI files depend on tracing/ui/base/base.html in the
+same way that all non-UI files depend on tracing/base/base.html. Enforce this
+dependency with a presubmit.
+-->
+<link rel="import" href="/tracing/ui/base/base.html" data-suppress-import-order>
+
+<link rel="import" href="/tracing/extras/chrome_config.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/cc.html">
+<link rel="import" href="/tracing/ui/extras/chrome/codesearch.html">
+<link rel="import" href="/tracing/ui/extras/chrome/gpu/gpu.html">
+<link rel="import" href="/tracing/ui/extras/chrome/layout_tree_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/side_panel/frame_data_side_panel.html">
+<link rel="import" href="/tracing/ui/extras/side_panel/input_latency_side_panel.html">
+<link rel="import" href="/tracing/ui/extras/system_stats/system_stats.html">
+<link rel="import" href="/tracing/ui/extras/v8_config.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/html_results.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/html_results.html
new file mode 100644
index 00000000000..cb3d41a88a0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/html_results.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<!--
+This class tries to (simply) copy the telemetry Results object, but outputs
+directly to an HTML table. It takes things that look like Telemetry values,
+and updates the table internally.
+-->
+<dom-module id='tr-ui-e-deep-reports-html-results'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ font-size: 12px;
+ }
+ </style>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-e-deep-reports-html-results',
+
+ created() {
+ this.hasColumnNamed_ = {};
+ this.pageToRowMap_ = new WeakMap();
+ },
+
+ ready() {
+ const table = this.$.table;
+ table.tableColumns = [
+ {
+ title: 'Label',
+ value(row) { return row.label; },
+ width: '350px'
+ }
+ ];
+ this.clear();
+ },
+
+ clear() {
+ this.$.table.tableRows = [];
+ },
+
+ addColumnIfNeeded_(columnName) {
+ if (this.hasColumnNamed_[columnName]) return;
+
+ this.hasColumnNamed_[columnName] = true;
+
+ const column = {
+ title: columnName,
+ value(row) {
+ if (row[columnName] === undefined) return '';
+ return row[columnName];
+ }
+ };
+
+ const columns = this.$.table.tableColumns;
+ columns.push(column);
+
+ // Update widths.
+ let colWidthPercentage;
+ if (columns.length === 1) {
+ colWidthPercentage = '100%';
+ } else {
+ colWidthPercentage = (100 / (columns.length - 1)).toFixed(3) + '%';
+ }
+
+ for (let i = 1; i < columns.length; i++) {
+ columns[i].width = colWidthPercentage;
+ }
+
+ this.$.table.tableColumns = columns;
+ },
+
+ getRowForPage_(page) {
+ if (!this.pageToRowMap_.has(page)) {
+ const i = page.url.lastIndexOf('/');
+ const baseName = page.url.substring(i + 1);
+
+ const link = document.createElement('a');
+ link.href = 'trace_viewer.html#' + page.url;
+ Polymer.dom(link).textContent = baseName;
+
+ const row = {
+ label: link,
+ value: '',
+ subRows: [],
+ isExpanded: true
+ };
+ this.$.table.tableRows.push(row);
+ this.pageToRowMap_.set(page, row);
+
+ // Kick table rebuild.
+ this.$.table.tableRows = this.$.table.tableRows;
+ }
+ return this.pageToRowMap_.get(page);
+ },
+
+ addValue(value) {
+ /* Value is expected to be a scalar telemetry-style Value. */
+ if (value.type !== 'scalar') {
+ throw new Error('wat');
+ }
+
+ this.addColumnIfNeeded_(value.name);
+ const rowForPage = this.getRowForPage_(value.page);
+ rowForPage[value.name] = value.value;
+
+ // Kick table rebuild.
+ this.$.table.tableRows = this.$.table.tableRows;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/main.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/main.html
new file mode 100644
index 00000000000..9cf2d7f6c79
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/main.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/ui/extras/deep_reports/scalar_value.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.deep_reports', function() {
+ /**
+ * Runs deep reports on the provided files, and pushes telemetry-style
+ * values to the results object.
+ */
+ function main(results, filesInDir) {
+ let lastP = new Promise(function(resolve) { resolve(); });
+
+ filesInDir.forEach(function(filename) {
+ // TODO(nduca): Make this like telemetry page.
+ const page = {
+ url: filename
+ };
+ lastP = lastP.then(function() {
+ return loadModelFromFileAsync(filename);
+ });
+ lastP = lastP.then(function(model) {
+ processModel(results, page, model);
+ });
+ });
+ return lastP;
+ }
+
+ function loadModelFromFileAsync(filename) {
+ return tr.b.getAsync(filename).then(function(trace) {
+ const io = new tr.ImportOptions();
+ io.shiftWorldToZero = true;
+ io.pruneEmptyContainers = false;
+
+ const m = new tr.Model();
+ try {
+ m.importTraces([trace], io);
+ } catch (e) {
+ throw new Error('While loading ' + filename + ' got: ' + e.toString());
+ }
+ return m;
+ });
+ }
+
+ function processModel(results, page, model) {
+ results.addValue(
+ new tr.ui.e.deep_reports.ScalarValue(
+ page, 'numRailIRs', 'ms', model.userModel.expectations.length));
+ }
+
+ return {
+ main
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/scalar_value.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/scalar_value.html
new file mode 100644
index 00000000000..cb550c35b4b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/deep_reports/scalar_value.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.deep_reports', function() {
+ function ScalarValue(page, name, units, value,
+ opt_important, opt_description) {
+ this.type = 'scalar';
+ this.page = page;
+ this.name = name;
+ this.units = units;
+ this.value = value;
+ this.important = opt_important !== undefined ? opt_important : false;
+ this.description = opt_description || '';
+ }
+ ScalarValue.fromDict = function(page, dict) {
+ if (dict.type !== 'scalar') {
+ throw new Error('wat');
+ }
+ const v = new ScalarValue(page, dict.name, dict.units, dict.value);
+ v.important = dict.important;
+ v.description = dict.description;
+ v.value = dict.value;
+ return v;
+ };
+
+ ScalarValue.prototype = {
+
+ };
+
+ return {
+ ScalarValue,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comment_element.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comment_element.html
new file mode 100644
index 00000000000..1748dd12b88
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comment_element.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<dom-module id='tr-ui-e-drive-comment-element'>
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+ #comment-area {
+ display: flex;
+ flex-direction: column;
+ border-top: 1px solid #e8e8e8;
+ background-color: white;
+ padding: 6px;
+ margin-bottom: 4px;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.3);
+ border-radius: 2px;
+ font-size: small;
+ }
+ #comment-header {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ margin-bottom: 8px;
+ }
+ #comment-header-text {
+ display: flex;
+ flex-direction: column;
+ padding-left: 10px;
+ }
+ #comment-img {
+ width: 32px;
+ height: 32px;
+ }
+ #comment-text-author {
+ padding-bottom: 2px;
+ }
+ #comment-date {
+ color: #777;
+ font-size: 11px;
+ }
+ #comment-content {
+ word-wrap: break-word;
+ }
+ </style>
+ <div id="comment-area">
+ <div id="comment-header">
+ <img id="comment-img" src="{{ comment.author.picture.url }}" />
+ <div id="comment-header-text">
+ <div id="comment-text-author">{{ comment.author.displayName }}</div>
+ <div id="comment-date">{{ createdDate }}</div>
+ </div>
+ </div>
+ <div id="comment-content">{{_computeCommentContentPrefix( comment)}}
+ {{ comment.content }}</div>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+Polymer({
+ is: 'tr-ui-e-drive-comment-element',
+
+ properties: {
+ comment: {
+ type: String,
+ observer: '_commentChanged'
+ }
+ },
+
+ _commentChanged() {
+ this.createdDate = new Date(this.comment.createdDate).toLocaleString();
+ },
+
+ _computeCommentContentPrefix(comment) {
+ return comment.anchor ? '&#9875;&nbsp;' : '';
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comments_side_panel.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comments_side_panel.html
new file mode 100644
index 00000000000..8f52839029d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comments_side_panel.html
@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/extras/drive/comment_element.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
+
+<dom-module id='tr-ui-e-drive-comments-side-panel'>
+ <template>
+ <style>
+ :host {
+ flex-direction: column;
+ display: flex;
+ width: 290px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ background-color: #eee;
+ }
+ toolbar {
+ flex: 0 0 auto;
+ border-bottom: 1px solid black;
+ display: flex;
+ }
+ result-area {
+ flex: 1 1 auto;
+ display: block;
+ min-height: 0;
+ padding: 4px;
+ }
+ #comments-textarea-container {
+ display: flex;
+ }
+ #commentinput {
+ width: 100%;
+ }
+ </style>
+
+ <toolbar id='toolbar'></toolbar>
+ <result-area id='result_area'>
+ <template is="dom-repeat" items="{{comments_}}" repeat="{{ comment in comments_ }}">
+ <tr-ui-e-drive-comment-element comment="{{comment}}"
+ on-click="commentClick">
+ </tr-ui-e-drive-comment-element>
+ </template>
+ <div id="comments-textarea-container">
+ <textarea id="commentinput" on-focus='textAreaFocus'
+ on-blur='textAreaBlur'
+ on-keypress="textareaKeypress"></textarea>
+ </div>
+ </result-area>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-e-drive-comments-side-panel',
+ behaviors: [tr.ui.behaviors.SidePanel],
+
+ ready() {
+ this.rangeOfInterest_ = new tr.b.math.Range();
+ this.selection_ = undefined;
+ this.comments_ = [];
+ this.annotationFromComment_ = undefined;
+ this.textAreaFocused = false;
+ },
+
+ setCommentProvider(commentProvider) {
+ this.commentProvider_ = commentProvider;
+ },
+
+ attached() {
+ if (this.commentProvider_ === undefined) {
+ this.commentProvider_ =
+ new tr.ui.e.drive.analysis.DefaultCommentProvider();
+ }
+ this.commentProvider_.attachToElement(this);
+ },
+
+ detached() {
+ this.commentProvider_.detachFromElement();
+ },
+
+ commentClick(event) {
+ const anchor = event.currentTarget.comment.anchor;
+ if (!anchor) return;
+
+ const uiState =
+ JSON.parse(anchor).a[0][tr.ui.e.drive.constants.ANCHOR_NAME];
+
+ const myEvent = new CustomEvent('navigateToUIState', { detail:
+ new tr.ui.b.UIState(new tr.model.Location(uiState.location.xWorld,
+ uiState.location.yComponents),
+ uiState.scaleX)
+ });
+ document.dispatchEvent(myEvent);
+
+ if (this.annotationFromComment_) {
+ this.model.removeAnnotation(this.annotationFromComment_);
+ }
+ const loc = new tr.model.Location(uiState.location.xWorld,
+ uiState.location.yComponents);
+
+ const text = sender.comment.author.displayName + ': ' +
+ sender.comment.content;
+ this.annotationFromComment_ =
+ new tr.model.CommentBoxAnnotation(loc, text);
+ this.model.addAnnotation(this.annotationFromComment_);
+ },
+
+ textareaKeypress(event) {
+ // Check for return key.
+ if (event.keyCode === 13 && !event.ctrlKey) {
+ this.commentProvider_.addComment(this.$.commentinput.value);
+ this.$.commentinput.value = '';
+ }
+ event.stopPropagation();
+ return true;
+ },
+
+ textAreaFocus(event) {
+ this.textAreaFocused = true;
+ },
+
+ textAreaBlur(event) {
+ this.textAreaFocused = false;
+ },
+
+ get rangeOfInterest() {
+ return this.rangeOfInterest_;
+ },
+
+ set rangeOfInterest(rangeOfInterest) {
+ this.rangeOfInterest_ = rangeOfInterest;
+ this.updateContents_();
+ },
+
+ get currentRangeOfInterest() {
+ if (this.rangeOfInterest_.isEmpty) {
+ return this.model_.bounds;
+ }
+ return this.rangeOfInterest_;
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ set model(model) {
+ this.model_ = model;
+ this.updateContents_();
+ },
+
+ set selection(selection) {
+ this.selection_ = selection;
+ },
+
+ updateContents_() {
+ this.commentProvider_.updateComments();
+ },
+
+ supportsModel(m) {
+ if (m === undefined) {
+ return {
+ supported: false,
+ reason: 'Unknown tracing model'
+ };
+ }
+ return {
+ supported: true
+ };
+ },
+
+ get textLabel() {
+ return 'Comments';
+ }
+});
+
+tr.ui.side_panel.SidePanelRegistry.register(function() {
+ return document.createElement('tr-ui-e-drive-comments-side-panel');
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comments_side_panel_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comments_side_panel_test.html
new file mode 100644
index 00000000000..639c1b9b597
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/comments_side_panel_test.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/extras/drive/comments_side_panel.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function StubCommentProvider() {
+ this.addDummyComment('Lorem ipsum dolor sit amet');
+ this.addDummyComment('consectetur adipiscing elit');
+ this.addDummyComment('sed do eiusmod tempor incididunt ut labore et ' +
+ 'dolore magna aliqua. Ut enim ad minim veniam, quis nostrud ' +
+ 'exercitation ullamco laboris nisi ut aliquip ex ea commodo ' +
+ 'consequat. Duis aute irure dolor in reprehenderit in voluptate ' +
+ 'velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint ' +
+ 'occaecat cupidatat non proident, sunt in culpa qui officia deserunt ' +
+ 'mollit anim id est laborum.');
+ }
+
+ StubCommentProvider.prototype = {
+ comments_: [],
+
+ attachToElement(attachedElement) {
+ this.attachedElement_ = attachedElement;
+ this.updateComments();
+ },
+
+ detachFromElement() {
+ },
+
+ updateComments() {
+ this.attachedElement_.comments_ = this.comments_;
+ },
+
+ addDummyComment(content) {
+ const newComment = {
+ author: {
+ displayName: 'Casper the Friendly Ghost',
+ picture: {
+ url: 'https://lh3.googleusercontent.com/-XdUIqdMkCWA/' +
+ 'AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/s128/photo.jpg'
+ }
+ },
+ createdDate: Date.now(),
+ anchor: (this.comments_.length) % 2 ? 1 : 0,
+ content
+ };
+
+ this.comments_.push(newComment);
+ },
+
+ addComment(body) {
+ this.addDummyComment(body);
+ this.updateComments();
+ }
+ };
+
+ test('instantiate', function() {
+ const panel = document.createElement('tr-ui-e-drive-comments-side-panel');
+ panel.setCommentProvider(new StubCommentProvider);
+ this.addHTMLOutput(panel);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/drive_comment_provider.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/drive_comment_provider.html
new file mode 100644
index 00000000000..42d3706f854
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/drive_comment_provider.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/comment_box_annotation.html">
+
+<link rel="import" href="/tracing/ui/extras/drive/comments_side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
+
+<script>
+'use strict';
+
+(function() {
+ function addDriveCommentWithUIState_(text, uiState) {
+ gapi.client.load('drive', 'v2', function() {
+ const request = gapi.client.drive.revisions.get({
+ 'fileId': tr.ui.e.drive.getDriveFileId(),
+ 'revisionId': 'head'
+ });
+ request.execute(function(resp) {
+ const anchorObject = {};
+ anchorObject[tr.ui.e.drive.constants.ANCHOR_NAME] = uiState;
+ let anchor = {
+ 'r': resp.id,
+ 'a': [anchorObject]
+ };
+ anchor = JSON.stringify(anchor);
+ gapi.client.load('drive', 'v2', function() {
+ const request = gapi.client.drive.comments.insert({
+ 'fileId': tr.ui.e.drive.getDriveFileId(),
+ 'resource': {'content': text, anchor}
+ });
+ request.execute();
+ });
+ });
+ });
+ }
+
+ function onCommentWithUIState(e) {
+ addDriveCommentWithUIState_(e.detail.name, e.detail.location);
+ }
+
+ document.addEventListener('commentWithUIState',
+ onCommentWithUIState.bind(this));
+}());
+
+tr.exportTo('tr.ui.e.drive.analysis', function() {
+ function DefaultCommentProvider() { }
+
+ DefaultCommentProvider.prototype = {
+ attachToElement(attachedElement) {
+ this.attachedElement_ = attachedElement;
+ this.commentsCheckTimer_ = setTimeout(this.checkForComments_.bind(this),
+ 5000);
+ },
+
+ detachFromElement() {
+ clearTimeout(this.commentsCheckTimer_);
+ },
+
+ checkForComments_() {
+ this.updateComments();
+ this.commentsCheckTimer_ = setTimeout(this.checkForComments_.bind(this),
+ 5000);
+ },
+
+ updateComments() {
+ gapi.client.load('drive', 'v2', () => {
+ const request = gapi.client.drive.comments.list({
+ 'fileId': tr.ui.e.drive.getDriveFileId()
+ });
+ request.execute(results => {
+ this.attachedElement_.comments_ = results.items;
+ });
+ });
+ },
+
+ addComment(body) {
+ gapi.client.load('drive', 'v2', () => {
+ const request = gapi.client.drive.comments.insert({
+ 'fileId': tr.ui.e.drive.getDriveFileId(),
+ 'resource': {'content': body}
+ });
+ request.execute(resp => {
+ this.updateComments();
+ });
+ });
+ }
+ };
+
+ return {
+ DefaultCommentProvider,
+ };
+});
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/index.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/index.html
new file mode 100644
index 00000000000..270dcccf2fc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/drive/index.html
@@ -0,0 +1,463 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <script type="text/javascript" src="https://apis.google.com/js/api.js"></script>
+
+ <link rel="import" href="/components/polymer/polymer.html">
+ <link rel="import" href="/tracing/ui/extras/drive/drive_comment_provider.html">
+ <link rel="import" href="/tracing/ui/extras/full_config.html">
+ <link rel="import" href="/tracing/ui/timeline_view.html">
+
+ <style>
+ body {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ }
+ body > x-timeline-view {
+ flex: 1 1 auto;
+ overflow: hidden;
+ position: absolute;
+ top: 0px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ }
+ body > x-timeline-view:focus {
+ outline: none;
+ }
+ nav {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ }
+ #navbar button {
+ height: 24px;
+ padding-bottom: 3px;
+ vertical-align: middle;
+ box-shadow: none;
+ background-color: #4d90fe;
+ background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);
+ border: 1px solid #3079ed;
+ color: #fff;
+ border-radius: 2px;
+ cursor: default;
+ font-size: 11px;
+ font-weight: bold;
+ text-align: center;
+ white-space: nowrap;
+ line-height: 27px;
+ min-width: 54px;
+ outline: 0px;
+ padding: 0 8px;
+ font: normal 13px arial,sans-serif;
+ margin: 5px;
+ }
+ #collabs {
+ display: flex;
+ flex-direction: row;
+ }
+ .collaborator-div {
+ display: inline-block;
+ vertical-align: middle;
+ min-height: 0;
+ width: 100px;
+ font-size: 11px;
+ font-weight: bold;
+ font: normal 13px arial,sans-serif;
+ margin: 10px;
+ }
+ .collaborator-img {
+ margin: 2px;
+ }
+ .collaborator-tooltip {
+ z-index: 10000;
+ transition: visibility 0,opacity .13s ease-in;
+ background-color: #2a2a2a;
+ border: 1px solid #fff;
+ color: #fff;
+ cursor: default;
+ display: block;
+ font-family: arial, sans-serif;
+ font-size: 11px;
+ font-weight: bold;
+ margin-left: -1px;
+ opacity: 1;
+ padding: 7px 9px;
+ word-break: break-word;
+ position: absolute;
+ }
+ .collaborator-tooltip-content {
+ color: #fff;
+ }
+ .collaborator-tooltip-arrow {
+ position: absolute;
+ top: -6px;
+ }
+ .collaborator-tooltip-arrow-before {
+ border-color: #fff transparent !important;
+ left: -6px;
+ border: 6px solid;
+ border-top-width: 0;
+ content: '';
+ display: block;
+ height: 0;
+ position: absolute;
+ width: 0;
+ }
+ .collaborator-tooltip-arrow-after {
+ top: 1px;
+ border-color: #2a2a2a transparent !important;
+ left: -5px;
+ border: 5px solid;
+ border-top-width: 0;
+ content: '';
+ display: block;
+ height: 0;
+ position: absolute;
+ width: 0;
+ }
+
+ </style>
+ <title>Trace Viewer</title>
+</head>
+<body>
+ <nav id="navbar">
+ <div id="collabs"></div>
+ <button id="x-drive-save-to-disk">Save to disk</button>
+ <button id="x-drive-save-to-drive">Save to Drive</button>
+ <button id="x-drive-load-from-drive">Load from Drive</button>
+ <button id="x-drive-share">Share</button>
+ </nav>
+ <x-timeline-view>
+ </x-timeline-view>
+
+ <script>
+ 'use strict';
+
+ // Needs to be global as it's passed through the Google API as a
+ // GET parameter.
+ let onAPIClientLoaded_ = null;
+
+ (function() {
+ tr.exportTo('tr.ui.e.drive', function() {
+ const appId = '239864068844';
+ const constants = {
+ APP_ID: appId,
+ ANCHOR_NAME: appId + '.trace_viewer',
+ DEVELOPER_KEY: 'AIzaSyDR-6_wL9vHg1_oz4JHk8IQAkv2_Y0Y8-M',
+ CLIENT_ID: '239864068844-c7gefbfdcp0j6grltulh2r88tsvl18c1.apps.' +
+ 'googleusercontent.com',
+ SCOPE: [
+ 'https://www.googleapis.com/auth/drive',
+ 'https://www.googleapis.com/auth/drive.install',
+ 'https://www.googleapis.com/auth/drive.file',
+ 'profile'
+ ]
+ };
+
+ return {
+ getDriveFileId() { return driveFileId_; },
+ constants
+ };
+ });
+
+
+ let pickerApiLoaded_ = false;
+ let oauthToken_ = null;
+
+ let timelineViewEl_ = null;
+ let driveDocument_ = null;
+ let shareClient_ = null;
+ let fileIdToLoad_ = null;
+ let driveFileId_ = null;
+
+ function parseGETParameter(val) {
+ let result = null;
+ let tmp = [];
+ location.search.substr(1).split('&').forEach(function(item) {
+ tmp = item.split('=');
+ if (tmp[0] === val) {
+ result = decodeURIComponent(tmp[1]);
+ }
+ });
+ return result;
+ }
+
+ // Use the Google API Loader script to load the google.picker script.
+ onAPIClientLoaded_ = function() {
+ const driveState = parseGETParameter('state');
+ if (driveState !== null) {
+ const driveStateJson = JSON.parse(driveState);
+ fileIdToLoad_ = String(driveStateJson.ids);
+ }
+
+ gapi.load('picker', {'callback': onPickerApiLoad});
+ gapi.load('auth', {'callback'() {
+ onAuthApiLoad(true, onAuthResultSuccess);
+ return tr.b.timeout(30e3)
+ .then(() => onAuthApiLoad(true, function() {}))
+ .then(() => tr.b.timeout(30e3))
+ .then(() => onRepeatAuthApiLoad);
+ }});
+ };
+
+ function onAuthApiLoad(tryImmediate, resultCallback) {
+ window.gapi.auth.authorize(
+ {'client_id': tr.ui.e.drive.constants.CLIENT_ID,
+ 'scope': tr.ui.e.drive.constants.SCOPE, 'immediate': tryImmediate},
+ function(authResult) {
+ handleAuthResult(authResult, tryImmediate, resultCallback);
+ });
+ }
+
+ function onPickerApiLoad() {
+ pickerApiLoaded_ = true;
+ if (fileIdToLoad_ === null) {
+ createPicker();
+ }
+ }
+
+ function onAuthResultSuccess() {
+ if (fileIdToLoad_ === null) {
+ createPicker();
+ } else {
+ loadFileFromDrive(fileIdToLoad_);
+ }
+ }
+
+ function handleAuthResult(authResult, wasImmediate, resultCallback) {
+ if (authResult && !authResult.error) {
+ oauthToken_ = authResult.access_token;
+ resultCallback();
+ } else if (wasImmediate) {
+ onAuthApiLoad(false);
+ }
+ }
+
+ function createPicker() {
+ if (pickerApiLoaded_ && oauthToken_) {
+ const view = new google.picker.View(google.picker.ViewId.DOCS);
+ view.setMimeTypes('application/json,application/octet-stream');
+ const picker = new google.picker.PickerBuilder()
+ .enableFeature(google.picker.Feature.NAV_HIDDEN)
+ .enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
+ .setAppId(tr.ui.e.drive.constants.APP_ID)
+ .setOAuthToken(oauthToken_)
+ .addView(view)
+ .addView(new google.picker.DocsUploadView())
+ .setDeveloperKey(tr.ui.e.drive.constants.DEVELOPER_KEY)
+ .setCallback(pickerCallback)
+ .build();
+ picker.setVisible(true);
+ }
+ }
+
+ function pickerCallback(data) {
+ if (data.action === google.picker.Action.PICKED) {
+ loadFileFromDrive(data.docs[0].id);
+ }
+ }
+
+ function initShareButton() {
+ shareClient_ = new gapi.drive.share.ShareClient(
+ tr.ui.e.drive.constants.APP_ID);
+ shareClient_.setItemIds([driveFileId_]);
+ }
+
+ function loadFileFromDrive(fileId) {
+ gapi.client.load('drive', 'v2', function() {
+ const request = gapi.client.drive.files.get({fileId});
+ request.execute(function(resp) { downloadFile(resp); });
+ driveFileId_ = fileId;
+ gapi.load('drive-share', initShareButton);
+ });
+ }
+
+ function downloadFile(file) {
+ if (file.downloadUrl) {
+ const downloadingOverlay = tr.ui.b.Overlay();
+ downloadingOverlay.title = 'Downloading...';
+ downloadingOverlay.userCanClose = false;
+ downloadingOverlay.msgEl = document.createElement('div');
+ Polymer.dom(downloadingOverlay).appendChild(downloadingOverlay.msgEl);
+ downloadingOverlay.msgEl.style.margin = '20px';
+ downloadingOverlay.update = function(msg) {
+ Polymer.dom(this.msgEl).textContent = msg;
+ };
+ downloadingOverlay.visible = true;
+
+ const accessToken = gapi.auth.getToken().access_token;
+ const xhr = new XMLHttpRequest();
+ xhr.open('GET', file.downloadUrl);
+ xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
+ xhr.onload = function() {
+ downloadingOverlay.visible = false;
+ onDownloaded(file.title, xhr.responseText);
+ };
+ xhr.onprogress = function(evt) {
+ downloadingOverlay.update(
+ Math.floor(evt.position * 100 / file.fileSize) + '% complete');
+ };
+ xhr.onerror = function() { alert('Failed downloading!'); };
+ xhr.send();
+ } else {
+ alert('No URL!');
+ }
+ }
+
+ function displayAllCollaborators() {
+ const allCollaborators = driveDocument_.getCollaborators();
+ const collaboratorCount = allCollaborators.length;
+ const collabspan = document.getElementById('collabs');
+ Polymer.dom(collabspan).innerHTML = '';
+ const imageList = [];
+ for (let i = 0; i < collaboratorCount; i++) {
+ const user = allCollaborators[i];
+
+ const img = document.createElement('img');
+ img.src = user.photoUrl;
+ img.alt = user.displayName;
+ img.height = 30;
+ img.width = 30;
+ img.className = 'collaborator-img';
+ Polymer.dom(collabspan).appendChild(img);
+ imageList.push({'image': img, 'name': user.displayName});
+ }
+ for (i = 0; i < imageList.length; i++) {
+ const collabTooltip = tr.ui.b.createDiv({
+ className: 'collaborator-tooltip'
+ });
+ const collabTooltipContent = tr.ui.b.createDiv({
+ className: 'collaborator-tooltip-content'
+ });
+ Polymer.dom(collabTooltipContent).textContent = imageList[i].name;
+ Polymer.dom(collabTooltip).appendChild(collabTooltipContent);
+ Polymer.dom(collabspan).appendChild(collabTooltip);
+ const collabTooltipArrow = tr.ui.b.createDiv({
+ className: 'collaborator-tooltip-arrow'});
+ Polymer.dom(collabTooltip).appendChild(collabTooltipArrow);
+ const collabTooltipArrowBefore = tr.ui.b.createDiv({
+ className: 'collaborator-tooltip-arrow-before'});
+ Polymer.dom(collabTooltipArrow).appendChild(collabTooltipArrowBefore);
+ const collabTooltipArrowAfter = tr.ui.b.createDiv({
+ className: 'collaborator-tooltip-arrow-after'});
+ Polymer.dom(collabTooltipArrow).appendChild(collabTooltipArrowAfter);
+
+ const rect = imageList[i].image.getBoundingClientRect();
+ collabTooltip.style.top = (rect.bottom - 6) + 'px';
+ collabTooltip.style.left =
+ (rect.left + 16 - (collabTooltip.offsetWidth / 2)) + 'px';
+ collabTooltipArrow.style.left = (collabTooltip.offsetWidth / 2) + 'px';
+ collabTooltip.style.visibility = 'hidden';
+ function visibilityDelegate(element, visibility) {
+ return function() {
+ element.style.visibility = visibility;
+ };
+ }
+ imageList[i].image.addEventListener(
+ 'mouseover', visibilityDelegate(collabTooltip, 'visible'));
+ imageList[i].image.addEventListener(
+ 'mouseout', visibilityDelegate(collabTooltip, 'hidden'));
+ }
+ }
+
+ function onRealtimeFileLoaded(doc) {
+ if (driveDocument_) {
+ driveDocument_.close();
+ }
+ driveDocument_ = doc;
+ doc.addEventListener(gapi.drive.realtime.EventType.COLLABORATOR_JOINED,
+ displayAllCollaborators);
+ doc.addEventListener(gapi.drive.realtime.EventType.COLLABORATOR_LEFT,
+ displayAllCollaborators);
+
+ displayAllCollaborators(doc);
+ }
+
+ function onRealtimeError(e) {
+ alert('Error loading realtime: ' + e);
+ }
+
+ function onDownloaded(filename, content) {
+ gapi.load('auth:client,drive-realtime,drive-share', function() {
+ gapi.drive.realtime.load(driveFileId_,
+ onRealtimeFileLoaded,
+ null,
+ onRealtimeError);
+ });
+
+ const traces = [];
+ const filenames = [];
+ filenames.push(filename);
+ traces.push(content);
+ createViewFromTraces(filenames, traces);
+ }
+
+ function createViewFromTraces(filenames, traces) {
+ const m = new tr.Model();
+ const i = new tr.importer.Import(m);
+ const p = i.importTracesWithProgressDialog(traces);
+ p.then(
+ function() {
+ timelineViewEl_.model = m;
+ timelineViewEl_.updateDocumentFavicon();
+ timelineViewEl_.globalMode = true;
+ timelineViewEl_.viewTitle = '';
+ },
+ function(err) {
+ const downloadingOverlay = new tr.ui.b.Overlay();
+ Polymer.dom(downloadingOverlay).textContent =
+ tr.b.normalizeException(err).message;
+ downloadingOverlay.title = 'Import error';
+ downloadingOverlay.visible = true;
+ });
+ }
+
+ function onSaveToDiskClicked() {
+ throw new Error('Not implemented');
+ }
+
+ function onSaveToDriveClicked() {
+ throw new Error('Not implemented');
+ }
+
+ function onLoadFromDriveClicked() {
+ createPicker();
+ }
+
+ function onLoad() {
+ timelineViewEl_ = Polymer.dom(document).querySelector('x-timeline-view');
+ timelineViewEl_.globalMode = true;
+ const navbar = document.getElementById('navbar');
+ timelineViewEl_.style.top = navbar.offsetHeight + 'px';
+ tr.ui.b.decorate(timelineViewEl_, tr.ui.TimelineView);
+ }
+
+ window.addEventListener('load', onLoad);
+
+ document.getElementById('x-drive-save-to-disk').onclick =
+ onSaveToDiskClicked;
+ document.getElementById('x-drive-save-to-drive').onclick =
+ onSaveToDriveClicked;
+ document.getElementById('x-drive-load-from-drive').onclick =
+ onLoadFromDriveClicked;
+ document.getElementById('x-drive-share').onclick = function() {
+ shareClient_.showSettingsDialog();
+ };
+ }());
+
+ </script>
+ <script type="text/javascript"
+ src="https://apis.google.com/js/client.js?onload=onAPIClientLoaded_">
+ </script>
+</body>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/full_config.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/full_config.html
new file mode 100644
index 00000000000..6d1e29d4e20
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/full_config.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+TODO(charliea): Make all UI files depend on tracing/ui/base/base.html in the
+same way that all non-UI files depend on tracing/base/base.html. Enforce this
+dependency with a presubmit.
+-->
+<link rel="import" href="/tracing/ui/base/base.html" data-suppress-import-order>
+
+<!-- The full config is all the configs slammed together. -->
+<link rel="import" href="/tracing/extras/importer/gcloud_trace/gcloud_trace_importer.html">
+<link rel="import" href="/tracing/ui/extras/chrome_config.html">
+<link rel="import" href="/tracing/ui/extras/lean_config.html">
+<link rel="import" href="/tracing/ui/extras/systrace_config.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/lean_config.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/lean_config.html
new file mode 100644
index 00000000000..8d66352f140
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/lean_config.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+TODO(charliea): Make all UI files depend on tracing/ui/base/base.html in the same way that
+all non-UI files depend on tracing/base/base.html. Enforce this dependency with a presubmit.
+-->
+<link rel="import" href="/tracing/ui/base/base.html" data-suppress-import-order>
+
+<link rel="import" href="/tracing/extras/lean_config.html" data-suppress-import-order>
+
+<!--
+The lean config is just enough to import uncompressed, trace-event-formatted
+json blobs.
+-->
+<link rel="import" href="/tracing/ui/side_panel/file_size_stats_side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/metrics_side_panel.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/alerts_side_panel.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/alerts_side_panel.html
new file mode 100644
index 00000000000..0971d7f5409
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/alerts_side_panel.html
@@ -0,0 +1,172 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/line_chart.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
+
+<dom-module id='tr-ui-e-s-alerts-side-panel'>
+ <template>
+ <style>
+ :host {
+ display: block;
+ width: 250px;
+ }
+ #content {
+ flex-direction: column;
+ display: flex;
+ }
+ tr-ui-b-table {
+ font-size: 12px;
+ }
+ </style>
+
+ <div id='content'>
+ <toolbar id='toolbar'></toolbar>
+ <result-area id='result_area'></result-area>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-e-s-alerts-side-panel',
+ behaviors: [tr.ui.behaviors.SidePanel],
+
+
+ ready() {
+ this.rangeOfInterest_ = new tr.b.math.Range();
+ this.selection_ = undefined;
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ set model(model) {
+ this.model_ = model;
+ this.updateContents_();
+ },
+
+ set selection(selection) {
+ },
+
+ set rangeOfInterest(rangeOfInterest) {
+ },
+
+ /**
+ * Fires a selection event selecting all alerts of the specified
+ * type.
+ */
+ selectAlertsOfType(alertTypeString) {
+ const alertsOfType = this.model_.alerts.filter(function(alert) {
+ return alert.title === alertTypeString;
+ });
+
+ const event = new tr.model.RequestSelectionChangeEvent();
+ event.selection = new tr.model.EventSet(alertsOfType);
+ this.dispatchEvent(event);
+ },
+
+ /**
+ * Returns a map for the specified alerts where each key is the
+ * alert type string and each value is a list of alerts with that
+ * type.
+ */
+ alertsByType_(alerts) {
+ const alertsByType = {};
+ alerts.forEach(function(alert) {
+ if (!alertsByType[alert.title]) {
+ alertsByType[alert.title] = [];
+ }
+
+ alertsByType[alert.title].push(alert);
+ });
+ return alertsByType;
+ },
+
+ alertsTableRows_(alertsByType) {
+ return Object.keys(alertsByType).map(function(key) {
+ return {
+ alertType: key,
+ count: alertsByType[key].length
+ };
+ });
+ },
+
+ alertsTableColumns_() {
+ return [
+ {
+ title: 'Alert type',
+ value(row) { return row.alertType; },
+ width: '180px'
+ },
+ {
+ title: 'Count',
+ width: '100%',
+ value(row) { return row.count; }
+ }
+ ];
+ },
+
+ createAlertsTable_(alerts) {
+ const alertsByType = this.alertsByType_(alerts);
+
+ const table = document.createElement('tr-ui-b-table');
+ table.tableColumns = this.alertsTableColumns_();
+ table.tableRows = this.alertsTableRows_(alertsByType);
+ table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ table.addEventListener('selection-changed', function(e) {
+ const row = table.selectedTableRow;
+ if (row) {
+ this.selectAlertsOfType(row.alertType);
+ }
+ }.bind(this));
+
+ return table;
+ },
+
+ updateContents_() {
+ Polymer.dom(this.$.result_area).textContent = '';
+ if (this.model_ === undefined) return;
+
+ const panel = this.createAlertsTable_(this.model_.alerts);
+ Polymer.dom(this.$.result_area).appendChild(panel);
+ },
+
+ supportsModel(m) {
+ if (m === undefined) {
+ return {
+ supported: false,
+ reason: 'Unknown tracing model'
+ };
+ } else if (m.alerts.length === 0) {
+ return {
+ supported: false,
+ reason: 'No alerts in tracing model'
+ };
+ }
+
+ return {
+ supported: true
+ };
+ },
+
+ get textLabel() {
+ return 'Alerts';
+ }
+});
+
+tr.ui.side_panel.SidePanelRegistry.register(function() {
+ return document.createElement('tr-ui-e-s-alerts-side-panel');
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/alerts_side_panel_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/alerts_side_panel_test.html
new file mode 100644
index 00000000000..c4cb9825d1e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/alerts_side_panel_test.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/side_panel/alerts_side_panel.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ALERT_INFO_1 = new tr.model.EventInfo(
+ 'Alert 1', 'Critical alert');
+ const ALERT_INFO_2 = new tr.model.EventInfo(
+ 'Alert 2', 'Warning alert');
+
+ test('instantiate', function() {
+ const panel = document.createElement('tr-ui-e-s-alerts-side-panel');
+ panel.model = createModelWithAlerts([
+ new tr.model.Alert(ALERT_INFO_1, 5),
+ new tr.model.Alert(ALERT_INFO_2, 35)
+ ]);
+ panel.style.height = '100px';
+
+ this.addHTMLOutput(panel);
+ });
+
+ test('selectAlertsOfType', function() {
+ const panel = document.createElement('tr-ui-e-s-alerts-side-panel');
+ const alerts = [
+ new tr.model.Alert(ALERT_INFO_1, 1),
+ new tr.model.Alert(ALERT_INFO_1, 2),
+ new tr.model.Alert(ALERT_INFO_2, 3)
+ ];
+
+ const predictedAlerts = new tr.model.EventSet([alerts[0], alerts[1]]);
+ panel.model = createModelWithAlerts(alerts);
+ panel.style.height = '100px';
+ this.addHTMLOutput(panel);
+
+ let selectionChanged = false;
+ panel.addEventListener('requestSelectionChange', function(e) {
+ selectionChanged = true;
+ assert.isTrue(e.selection.equals(predictedAlerts));
+ });
+ panel.selectAlertsOfType(ALERT_INFO_1.title);
+
+ assert.isTrue(selectionChanged);
+ });
+
+ function createModelWithAlerts(alerts) {
+ const m = new tr.Model();
+ m.alerts = alerts;
+ return m;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/frame_data_side_panel.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/frame_data_side_panel.html
new file mode 100644
index 00000000000..e5fd7689479
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/frame_data_side_panel.html
@@ -0,0 +1,347 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/frame_tree_node.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/render_frame.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/top_level.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-e-s-frame-data-side-panel'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ width: 600px;
+ flex-direction: column;
+ }
+ table-container {
+ display: flex;
+ overflow: auto;
+ font-size: 12px;
+ }
+ </style>
+ <div>
+ Organize by:
+ <select id="select">
+ <option value="none">None</option>
+ <option value="tree">Frame Tree</option>
+ </select>
+ </div>
+ <table-container>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </table-container>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.ui.e.s', function() {
+ const BlameContextSnapshot = tr.e.chrome.BlameContextSnapshot;
+ const FrameTreeNodeSnapshot = tr.e.chrome.FrameTreeNodeSnapshot;
+ const RenderFrameSnapshot = tr.e.chrome.RenderFrameSnapshot;
+ const TopLevelSnapshot = tr.e.chrome.TopLevelSnapshot;
+
+ const BlameContextInstance = tr.e.chrome.BlameContextInstance;
+ const FrameTreeNodeInstance = tr.e.chrome.FrameTreeNodeInstance;
+ const RenderFrameInstance = tr.e.chrome.RenderFrameInstance;
+ const TopLevelInstance = tr.e.chrome.TopLevelInstance;
+
+ /**
+ * @constructor
+ * If |context| is provided, creates a row for the given context.
+ * Otherwise, creates an empty Row template which can be used for aggregating
+ * data from a group of subrows.
+ */
+ function Row(context) {
+ this.subRows = undefined;
+ this.contexts = [];
+ this.type = undefined;
+ this.renderer = 'N/A';
+ this.url = undefined;
+ this.time = 0;
+ this.eventsOfInterest = new tr.model.EventSet();
+
+ if (context === undefined) return;
+
+ this.type = context.objectInstance.blameContextType;
+ this.contexts.push(context);
+ if (context instanceof FrameTreeNodeSnapshot) {
+ if (context.renderFrame) {
+ this.contexts.push(context.renderFrame);
+ this.renderer = context.renderFrame.objectInstance.parent.pid;
+ }
+ } else if (context instanceof RenderFrameSnapshot) {
+ if (context.frameTreeNode) {
+ this.contexts.push(context.frameTreeNode);
+ }
+ this.renderer = context.objectInstance.parent.pid;
+ } else if (context instanceof TopLevelSnapshot) {
+ this.renderer = context.objectInstance.parent.pid;
+ } else {
+ throw new Error('Unknown context type');
+ }
+ this.eventsOfInterest.addEventSet(this.contexts);
+
+ // TODO(xiaochengh): Handle the case where a subframe has a trivial url
+ // (e.g., about:blank), but inherits the origin of its parent. This is not
+ // needed now, but will be required if we want to group rows by origin.
+ this.url = context.url;
+ }
+
+ const groupFunctions = {
+ none: rows => rows,
+
+ // Group the rows according to the frame tree structure.
+ // Example: consider frame tree a(b, c(d)), where each frame has 1ms time
+ // attributed to it. The resulting table should look like:
+ // Type | Time | URL
+ // --------------+------+-----
+ // Frame Tree | 4 | a
+ // +- Frame | 1 | a
+ // +- Subframe | 1 | b
+ // +- Frame Tree | 2 | c
+ // +- Frame | 1 | c
+ // +- Subframe | 1 | d
+ tree(rows, rowMap) {
+ // Finds the parent of a specific row. When there is conflict between the
+ // browser's dump of the frame tree and the renderers', use the browser's.
+ const getParentRow = function(row) {
+ let pivot;
+ row.contexts.forEach(function(context) {
+ if (context instanceof tr.e.chrome.FrameTreeNodeSnapshot) {
+ pivot = context;
+ }
+ });
+ if (pivot && pivot.parentContext) {
+ return rowMap[pivot.parentContext.guid];
+ }
+ return undefined;
+ };
+
+ const rootRows = [];
+ rows.forEach(function(row) {
+ const parentRow = getParentRow(row);
+ if (parentRow === undefined) {
+ rootRows.push(row);
+ return;
+ }
+ if (parentRow.subRows === undefined) {
+ parentRow.subRows = [];
+ }
+ parentRow.subRows.push(row);
+ });
+
+ const aggregateAllDescendants = function(row) {
+ if (!row.subRows) {
+ if (getParentRow(row)) {
+ row.type = 'Subframe';
+ }
+ return row;
+ }
+ const result = new Row();
+ result.type = 'Frame Tree';
+ result.renderer = row.renderer;
+ result.url = row.url;
+ result.subRows = [row];
+ row.subRows.forEach(
+ subRow => result.subRows.push(aggregateAllDescendants(subRow)));
+ result.subRows.forEach(function(subRow) {
+ result.time += subRow.time;
+ result.eventsOfInterest.addEventSet(subRow.eventsOfInterest);
+ });
+ row.subRows = undefined;
+ return result;
+ };
+
+ return rootRows.map(rootRow => aggregateAllDescendants(rootRow));
+ }
+
+ // TODO(xiaochengh): Add grouping by site and probably more...
+ };
+
+ Polymer({
+ is: 'tr-ui-e-s-frame-data-side-panel',
+ behaviors: [tr.ui.behaviors.SidePanel],
+
+ ready() {
+ this.model_ = undefined;
+ this.rangeOfInterest_ = new tr.b.math.Range();
+
+ this.$.table.showHeader = true;
+ this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ this.$.table.tableColumns = this.createFrameDataTableColumns_();
+
+ this.$.table.addEventListener('selection-changed', function(e) {
+ this.selectEventSet_(this.$.table.selectedTableRow.eventsOfInterest);
+ }.bind(this));
+
+ this.$.select.addEventListener('change', function(e) {
+ this.updateContents_();
+ }.bind(this));
+ },
+
+ selectEventSet_(eventSet) {
+ const event = new tr.model.RequestSelectionChangeEvent();
+ event.selection = eventSet;
+ this.dispatchEvent(event);
+ },
+
+ createFrameDataTableColumns_() {
+ return [
+ {
+ title: 'Renderer',
+ value: row => row.renderer,
+ cmp: (a, b) => a.renderer - b.renderer
+ },
+ {
+ title: 'Type',
+ value: row => row.type
+ },
+ // TODO(xiaochengh): Decide what details to show in the table:
+ // - URL seems necessary, but we may also want origin instead/both.
+ // - Distinguish between browser time and renderer time?
+ // - Distinguish between CPU time and wall clock time?
+ // - Memory? Network? ...
+ {
+ title: 'Time',
+ value: row => tr.v.ui.createScalarSpan(row.time, {
+ unit: tr.b.Unit.byName.timeStampInMs,
+ ownerDocument: this.ownerDocument
+ }),
+ cmp: (a, b) => a.time - b.time
+ },
+ {
+ title: 'URL',
+ value: row => row.url,
+ cmp: (a, b) => (a.url || '').localeCompare(b.url || '')
+ }
+ ];
+ },
+
+ createFrameDataTableRows_() {
+ if (!this.model_) return [];
+
+ // Gather contexts into skeletons of rows.
+ const rows = [];
+ const rowMap = {};
+ for (const proc of Object.values(this.model_.processes)) {
+ proc.objects.iterObjectInstances(function(objectInstance) {
+ if (!(objectInstance instanceof BlameContextInstance)) {
+ return;
+ }
+ objectInstance.snapshots.forEach(function(snapshot) {
+ if (rowMap[snapshot.guid]) return;
+
+ const row = new Row(snapshot);
+ row.contexts.forEach(context => rowMap[context.guid] = row);
+ rows.push(row);
+ }, this);
+ }, this);
+ }
+
+ // Find slices attributed to each row.
+ // TODO(xiaochengh): We should implement a getter
+ // BlameContextSnapshot.attributedEvents, instead of process the model in
+ // a UI component.
+ for (const proc of Object.values(this.model_.processes)) {
+ for (const thread of Object.values(proc.threads)) {
+ thread.sliceGroup.iterSlicesInTimeRange(function(topLevelSlice) {
+ topLevelSlice.contexts.forEach(function(context) {
+ if (!context.snapshot.guid || !rowMap[context.snapshot.guid]) {
+ return;
+ }
+ const row = rowMap[context.snapshot.guid];
+ row.eventsOfInterest.push(topLevelSlice);
+ row.time += topLevelSlice.selfTime || 0;
+ });
+ }, this.currentRangeOfInterest.min, this.currentRangeOfInterest.max);
+ }
+ }
+
+ // Apply grouping to rows.
+ const select = this.$.select;
+ const groupOption = select.options[select.selectedIndex].value;
+ const groupFunction = groupFunctions[groupOption];
+ return groupFunction(rows, rowMap);
+ },
+
+ updateContents_() {
+ this.$.table.tableRows = this.createFrameDataTableRows_();
+ this.$.table.rebuild();
+ },
+
+ supportsModel(m) {
+ if (!m) {
+ return {
+ supported: false,
+ reason: 'No model available.'
+ };
+ }
+
+ const ans = {supported: false};
+ for (const proc of Object.values(m.processes)) {
+ proc.objects.iterObjectInstances(function(instance) {
+ if (instance instanceof BlameContextInstance) {
+ ans.supported = true;
+ }
+ });
+ }
+
+ if (!ans.supported) {
+ ans.reason = 'No frame data available';
+ }
+ return ans;
+ },
+
+ get currentRangeOfInterest() {
+ if (this.rangeOfInterest_.isEmpty) {
+ return this.model_.bounds;
+ }
+ return this.rangeOfInterest_;
+ },
+
+ get rangeOfInterest() {
+ return this.rangeOfInterest_;
+ },
+
+ set rangeOfInterest(rangeOfInterest) {
+ this.rangeOfInterest_ = rangeOfInterest;
+ this.updateContents_();
+ },
+
+ get selection() {
+ // Not applicable.
+ },
+
+ set selection(_) {
+ // Not applicable.
+ },
+
+ get textLabel() {
+ return 'Frame Data';
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ set model(model) {
+ this.model_ = model;
+ this.updateContents_();
+ }
+ });
+
+ tr.ui.side_panel.SidePanelRegistry.register(function() {
+ return document.createElement('tr-ui-e-s-frame-data-side-panel');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/frame_data_side_panel_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/frame_data_side_panel_test.html
new file mode 100644
index 00000000000..298afe05d42
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/frame_data_side_panel_test.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/frame_tree_node.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/render_frame.html">
+<link rel="import" href="/tracing/extras/chrome/blame_context/top_level.html">
+<link rel="import" href="/tracing/ui/extras/side_panel/frame_data_side_panel.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TestUtils = tr.c.TestUtils;
+
+ function topLevelOptions(pid, id) {
+ return {
+ pid,
+ id,
+ cat: 'blink',
+ scope: 'PlatformThread',
+ name: 'TopLevel'
+ };
+ }
+
+ function renderFrameOptions(pid, id, parent) {
+ return {
+ pid,
+ id,
+ cat: 'blink',
+ scope: 'RenderFrame',
+ name: 'RenderFrame',
+ args: {parent: {
+ id_ref: parent.id,
+ scope: parent.scope
+ }}
+ };
+ }
+
+ function frameTreeNodeOptions(pid, id, opt_renderFrame, opt_parentId) {
+ const ans = {
+ pid,
+ id,
+ cat: 'navigation',
+ scope: 'FrameTreeNode',
+ name: 'FrameTreeNode',
+ args: {}
+ };
+ if (opt_renderFrame) {
+ ans.args.renderFrame = {
+ id_ref: opt_renderFrame.id,
+ pid_ref: opt_renderFrame.pid,
+ scope: 'RenderFrame'
+ };
+ }
+ if (opt_parentId) {
+ ans.args.parent = {
+ id_ref: opt_parentId,
+ scope: 'FrameTreeNode'
+ };
+ }
+ return ans;
+ }
+
+ /**
+ * Creates some independent contexts. Checks if all are present in the panel.
+ */
+ test('basic', function() {
+ const panel = document.createElement('tr-ui-e-s-frame-data-side-panel');
+ panel.model = TestUtils.newModel(function(model) {
+ TestUtils.newSnapshot(model, topLevelOptions(1, '0x1'));
+ TestUtils.newSnapshot(model, renderFrameOptions(
+ 1, '0x2', {id: '0x1', scope: 'PlatformThread'}));
+ TestUtils.newSnapshot(model, frameTreeNodeOptions(
+ 2, '0x3'));
+ });
+ assert.lengthOf(panel.$.table.tableRows, 3);
+
+ this.addHTMLOutput(panel);
+ });
+
+ /**
+ * Creates a FrameTreeNode in the browser process and a RenderFrame in a
+ * renderer process that are the same frame. Checks if they are merged into
+ * one row in the panel.
+ */
+ test('mergeCrossProcessFrameBlameContexts', function() {
+ const panel = document.createElement('tr-ui-e-s-frame-data-side-panel');
+ panel.model = TestUtils.newModel(function(model) {
+ TestUtils.newSnapshot(model, topLevelOptions(1, '0x1'));
+ TestUtils.newSnapshot(model, renderFrameOptions(
+ 1, '0x2', {id: '0x1', scope: 'PlatformThread'}));
+ TestUtils.newSnapshot(model, frameTreeNodeOptions(
+ 2, '0x3', {id: '0x2', pid: 1}));
+ });
+ assert.lengthOf(panel.$.table.tableRows, 2);
+
+ this.addHTMLOutput(panel);
+ });
+
+ function newAttributedSlice(model, pid, start, duration, context) {
+ const slice = TestUtils.newSliceEx({start, duration});
+ slice.contexts = [{type: 'FrameBlameContext', snapshot: context}];
+ model.getOrCreateProcess(pid).getOrCreateThread(1).sliceGroup.pushSlice(
+ slice);
+ return slice;
+ }
+
+ /**
+ * Changes the range of interest. Checks if the panel updates correspondingly.
+ */
+ test('respondToRangeOfInterest', function() {
+ let topLevel;
+ let slice1;
+ let slice2;
+ const panel = document.createElement('tr-ui-e-s-frame-data-side-panel');
+ panel.model = TestUtils.newModel(function(model) {
+ topLevel = TestUtils.newSnapshot(model, topLevelOptions(1, '0x1'));
+ slice1 = newAttributedSlice(model, 1, 1500, 500, topLevel);
+ slice2 = newAttributedSlice(model, 1, 2500, 500, topLevel);
+ });
+
+ // The default range of interest contains both slices.
+ assert.isTrue(panel.$.table.tableRows[0].eventsOfInterest.equals(
+ new tr.model.EventSet([topLevel, slice1, slice2])));
+
+ // The new range of interest contains only slice2.
+ panel.rangeOfInterest = tr.b.math.Range.fromExplicitRange(slice2.start,
+ slice2.end);
+ assert.isTrue(panel.$.table.tableRows[0].eventsOfInterest.equals(
+ new tr.model.EventSet([topLevel, slice2])));
+
+ this.addHTMLOutput(panel);
+ });
+
+ /**
+ * Selects a row in the panel. Checks if the context(s) of the row and the
+ * slices attributed to the row are selected.
+ */
+ test('selectAttributedEvents', function() {
+ let topLevel;
+ let slice;
+ const panel = document.createElement('tr-ui-e-s-frame-data-side-panel');
+ panel.model = TestUtils.newModel(function(model) {
+ topLevel = TestUtils.newSnapshot(model, topLevelOptions(1, '0x1'));
+ slice = newAttributedSlice(model, 1, 1500, 500, topLevel);
+ });
+
+ let selectionChanged = false;
+ panel.addEventListener('requestSelectionChange', function(e) {
+ selectionChanged = true;
+ assert.isTrue(
+ e.selection.equals(new tr.model.EventSet([topLevel, slice])));
+ });
+ panel.$.table.selectedTableRow = panel.$.table.tableRows[0];
+ assert.isTrue(selectionChanged);
+
+ this.addHTMLOutput(panel);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel.html
new file mode 100644
index 00000000000..14e33919922
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel.html
@@ -0,0 +1,334 @@
+<!DOCTYPE html>
+<!--
+Copyright 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/line_chart.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
+
+<dom-module id='tr-ui-e-s-input-latency-side-panel'>
+ <template>
+ <style>
+ :host {
+ flex-direction: column;
+ display: flex;
+ }
+ toolbar {
+ flex: 0 0 auto;
+ border-bottom: 1px solid black;
+ display: flex;
+ }
+ result-area {
+ flex: 1 1 auto;
+ display: block;
+ min-height: 0;
+ overflow-y: auto;
+ }
+ </style>
+
+ <toolbar id='toolbar'></toolbar>
+ <result-area id='result_area'></result-area>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-e-s-input-latency-side-panel',
+ behaviors: [tr.ui.behaviors.SidePanel],
+
+
+ ready() {
+ this.rangeOfInterest_ = new tr.b.math.Range();
+ this.frametimeType_ = tr.model.helpers.IMPL_FRAMETIME_TYPE;
+ this.latencyChart_ = undefined;
+ this.frametimeChart_ = undefined;
+ this.selectedProcessId_ = undefined;
+ this.mouseDownIndex_ = undefined;
+ this.curMouseIndex_ = undefined;
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ set model(model) {
+ this.model_ = model;
+ if (this.model_) {
+ this.modelHelper_ = this.model_.getOrCreateHelper(
+ tr.model.helpers.ChromeModelHelper);
+ } else {
+ this.modelHelper_ = undefined;
+ }
+
+ this.updateToolbar_();
+ this.updateContents_();
+ },
+
+ get frametimeType() {
+ return this.frametimeType_;
+ },
+
+ set frametimeType(type) {
+ if (this.frametimeType_ === type) return;
+
+ this.frametimeType_ = type;
+ this.updateContents_();
+ },
+
+ get selectedProcessId() {
+ return this.selectedProcessId_;
+ },
+
+ set selectedProcessId(process) {
+ if (this.selectedProcessId_ === process) return;
+
+ this.selectedProcessId_ = process;
+ this.updateContents_();
+ },
+
+ set selection(selection) {
+ if (this.latencyChart_ === undefined) return;
+
+ this.latencyChart_.brushedRange = selection.bounds;
+ },
+
+ // This function is for testing purpose.
+ setBrushedIndices(mouseDownIndex, curIndex) {
+ this.mouseDownIndex_ = mouseDownIndex;
+ this.curMouseIndex_ = curIndex;
+ this.updateBrushedRange_();
+ },
+
+ updateBrushedRange_() {
+ if (this.latencyChart_ === undefined) return;
+
+ let r = new tr.b.math.Range();
+ if (this.mouseDownIndex_ === undefined) {
+ this.latencyChart_.brushedRange = r;
+ return;
+ }
+ r = this.latencyChart_.computeBrushRangeFromIndices(
+ this.mouseDownIndex_, this.curMouseIndex_);
+ this.latencyChart_.brushedRange = r;
+
+ // Based on the brushed range, update the selection of LatencyInfo in
+ // the timeline view by sending a selectionChange event.
+ let latencySlices = [];
+ for (const thread of this.model_.getAllThreads()) {
+ for (const event of thread.getDescendantEvents()) {
+ if (event.title.indexOf('InputLatency:') === 0) {
+ latencySlices.push(event);
+ }
+ }
+ }
+ latencySlices = tr.model.helpers.getSlicesIntersectingRange(
+ r, latencySlices);
+
+ const event = new tr.model.RequestSelectionChangeEvent();
+ event.selection = new tr.model.EventSet(latencySlices);
+ this.latencyChart_.dispatchEvent(event);
+ },
+
+ registerMouseEventForLatencyChart_() {
+ this.latencyChart_.addEventListener('item-mousedown', function(e) {
+ this.mouseDownIndex_ = e.index;
+ this.curMouseIndex_ = e.index;
+ this.updateBrushedRange_();
+ }.bind(this));
+
+ this.latencyChart_.addEventListener('item-mousemove', function(e) {
+ if (e.button === undefined) return;
+
+ this.curMouseIndex_ = e.index;
+ this.updateBrushedRange_();
+ }.bind(this));
+
+ this.latencyChart_.addEventListener('item-mouseup', function(e) {
+ this.curMouseIndex = e.index;
+ this.updateBrushedRange_();
+ }.bind(this));
+ },
+
+ updateToolbar_() {
+ const browserProcess = this.modelHelper_.browserProcess;
+ const labels = [];
+
+ if (browserProcess !== undefined) {
+ const labelStr = 'Browser: ' + browserProcess.pid;
+ labels.push({label: labelStr, value: browserProcess.pid});
+ }
+
+ for (const rendererHelper of
+ Object.values(this.modelHelper_.rendererHelpers)) {
+ const rendererProcess = rendererHelper.process;
+ const labelStr = 'Renderer: ' + rendererProcess.userFriendlyName;
+ labels.push({label: labelStr, value: rendererProcess.userFriendlyName});
+ }
+
+ if (labels.length === 0) return;
+
+ this.selectedProcessId_ = labels[0].value;
+ const toolbarEl = this.$.toolbar;
+ Polymer.dom(toolbarEl).appendChild(tr.ui.b.createSelector(
+ this, 'frametimeType',
+ 'inputLatencySidePanel.frametimeType', this.frametimeType_,
+ [{label: 'Main Thread Frame Times',
+ value: tr.model.helpers.MAIN_FRAMETIME_TYPE},
+ {label: 'Impl Thread Frame Times',
+ value: tr.model.helpers.IMPL_FRAMETIME_TYPE}
+ ]));
+ Polymer.dom(toolbarEl).appendChild(tr.ui.b.createSelector(
+ this, 'selectedProcessId',
+ 'inputLatencySidePanel.selectedProcessId',
+ this.selectedProcessId_,
+ labels));
+ },
+
+ // TODO(charliea): Delete this function in favor of rangeOfInterest.
+ get currentRangeOfInterest() {
+ if (this.rangeOfInterest_.isEmpty) {
+ return this.model_.bounds;
+ }
+ return this.rangeOfInterest_;
+ },
+
+ createLatencyLineChart(data, title, parentNode) {
+ const chart = new tr.ui.b.LineChart();
+ Polymer.dom(parentNode).appendChild(chart);
+ let width = 600;
+ if (document.body.clientWidth !== undefined) {
+ width = document.body.clientWidth * 0.5;
+ }
+ chart.graphWidth = width;
+ chart.chartTitle = title;
+ chart.data = data;
+ return chart;
+ },
+
+ updateContents_() {
+ const resultArea = this.$.result_area;
+ this.latencyChart_ = undefined;
+ this.frametimeChart_ = undefined;
+ Polymer.dom(resultArea).textContent = '';
+
+ if (this.modelHelper_ === undefined) return;
+
+ const rangeOfInterest = this.currentRangeOfInterest;
+
+ let chromeProcess;
+ if (this.modelHelper_.rendererHelpers[this.selectedProcessId_]) {
+ chromeProcess = this.modelHelper_.rendererHelpers[
+ this.selectedProcessId_
+ ];
+ } else {
+ chromeProcess = this.modelHelper_.browserHelper;
+ }
+
+ const frameEvents = chromeProcess.getFrameEventsInRange(
+ this.frametimeType, rangeOfInterest);
+
+ const frametimeData = tr.model.helpers.getFrametimeDataFromEvents(
+ frameEvents);
+ const averageFrametime = tr.b.math.Statistics.mean(frametimeData, d =>
+ d.frametime
+ );
+
+ const latencyEvents = this.modelHelper_.browserHelper.
+ getLatencyEventsInRange(
+ rangeOfInterest);
+
+ const latencyData = [];
+ latencyEvents.forEach(function(event) {
+ if (event.inputLatency === undefined) return;
+
+ latencyData.push({
+ x: event.start,
+ latency: event.inputLatency / 1000
+ });
+ });
+
+ const averageLatency = tr.b.math.Statistics.mean(latencyData, function(d) {
+ return d.latency;
+ });
+
+ // Create summary.
+ const latencySummaryText = document.createElement('div');
+ Polymer.dom(latencySummaryText).appendChild(tr.ui.b.createSpan({
+ textContent: 'Average Latency ' + averageLatency + ' ms',
+ bold: true}));
+ Polymer.dom(resultArea).appendChild(latencySummaryText);
+
+ const frametimeSummaryText = document.createElement('div');
+ Polymer.dom(frametimeSummaryText).appendChild(tr.ui.b.createSpan({
+ textContent: 'Average Frame Time ' + averageFrametime + ' ms',
+ bold: true}));
+ Polymer.dom(resultArea).appendChild(frametimeSummaryText);
+
+ if (latencyData.length !== 0) {
+ this.latencyChart_ = this.createLatencyLineChart(
+ latencyData, 'Latency Over Time', resultArea);
+ this.registerMouseEventForLatencyChart_();
+ }
+
+ if (frametimeData.length !== 0) {
+ this.frametimeChart_ = this.createLatencyLineChart(
+ frametimeData, 'Frame Times', resultArea);
+ }
+ },
+
+ get rangeOfInterest() {
+ return this.rangeOfInterest_;
+ },
+
+ set rangeOfInterest(rangeOfInterest) {
+ this.rangeOfInterest_ = rangeOfInterest;
+ this.updateContents_();
+ },
+
+ supportsModel(m) {
+ if (m === undefined) {
+ return {
+ supported: false,
+ reason: 'Unknown tracing model'
+ };
+ }
+
+ if (!tr.model.helpers.ChromeModelHelper.supportsModel(m)) {
+ return {
+ supported: false,
+ reason: 'No Chrome browser or renderer process found'
+ };
+ }
+
+ const modelHelper = m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);
+ if (modelHelper.browserHelper &&
+ modelHelper.browserHelper.hasLatencyEvents) {
+ return {
+ supported: true
+ };
+ }
+
+ return {
+ supported: false,
+ reason: 'No InputLatency events trace. Consider enabling ' +
+ 'benchmark" and "input" category when recording the trace'
+ };
+ },
+
+ get textLabel() {
+ return 'Input Latency';
+ }
+});
+
+tr.ui.side_panel.SidePanelRegistry.register(function() {
+ return document.createElement('tr-ui-e-s-input-latency-side-panel');
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel_test.html
new file mode 100644
index 00000000000..de225416faa
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/side_panel/input_latency_side_panel_test.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/side_panel/input_latency_side_panel.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const latencyData = [
+ {
+ x: 1000,
+ latency: 16
+ },
+ {
+ x: 2000,
+ latency: 17
+ },
+ {
+ x: 3000,
+ latency: 14
+ },
+ {
+ x: 4000,
+ latency: 23
+ }
+ ];
+ let lc = document.createElement('tr-ui-e-s-input-latency-side-panel');
+ let container = document.createElement('div');
+ this.addHTMLOutput(container);
+ const latencyChart = lc.createLatencyLineChart(
+ latencyData, 'latency', container);
+
+ const frametimeData = [
+ {
+ x: 1000,
+ frametime: 16
+ },
+ {
+ x: 2000,
+ frametime: 17
+ },
+ {
+ x: 3000,
+ frametime: 14
+ },
+ {
+ x: 4000,
+ frametime: 23
+ }
+ ];
+ lc = document.createElement('tr-ui-e-s-input-latency-side-panel');
+ container = document.createElement('div');
+ this.addHTMLOutput(container);
+ const frametimeChart = lc.createLatencyLineChart(
+ frametimeData, 'frametime', container);
+ });
+
+ test('brushedRangeChange', function() {
+ const events = [];
+ for (let i = 0; i < 10; i++) {
+ const startTs = i * 10000;
+ const endTs = startTs + 1000 * (i % 2);
+ events.push(
+ {
+ 'cat': 'benchmark',
+ 'pid': 3507,
+ 'tid': 3507,
+ 'ts': startTs,
+ 'ph': 'S',
+ 'name': 'InputLatency',
+ 'id': i
+ });
+ events.push(
+ {
+ 'cat': 'benchmark',
+ 'pid': 3507,
+ 'tid': 3507,
+ 'ts': endTs,
+ 'ph': 'T',
+ 'name': 'InputLatency',
+ 'args': {'step': 'GestureScrollUpdate'},
+ 'id': i
+ });
+ events.push(
+ {
+ 'cat': 'benchmark',
+ 'pid': 3507,
+ 'tid': 3507,
+ 'ts': endTs,
+ 'ph': 'F',
+ 'name': 'InputLatency',
+ 'args': {
+ 'data': {
+ 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT': {
+ 'time': startTs
+ },
+ 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT': {
+ 'time': endTs
+ }
+ }
+ },
+ 'id': i
+ });
+ }
+ events.push({'cat': '__metadata',
+ 'pid': 3507,
+ 'tid': 3507,
+ 'ts': 0,
+ 'ph': 'M',
+ 'name': 'thread_name',
+ 'args': {'name': 'CrBrowserMain'}});
+
+ const panel = document.createElement('tr-ui-e-s-input-latency-side-panel');
+ this.addHTMLOutput(panel);
+
+ let selectionChanged = false;
+
+ panel.model = tr.c.TestUtils.newModelWithEvents([events]);
+ function listener(e) {
+ selectionChanged = true;
+ assert.strictEqual(e.selection.length, 3);
+ const predictedStarts = [20, 31, 40];
+ let i = 0;
+ for (const event of e.selection) {
+ assert.strictEqual(event.start, predictedStarts[i++]);
+ }
+ }
+ panel.ownerDocument.addEventListener('requestSelectionChange', listener);
+ try {
+ panel.setBrushedIndices(2, 4);
+ } finally {
+ panel.ownerDocument.removeEventListener(
+ 'requestSelectionChange', listener);
+ }
+ assert.isTrue(selectionChanged);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats.html
new file mode 100644
index 00000000000..31bc1dbd997
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/system_stats/system_stats_snapshot.html">
+<link rel="import"
+ href="/tracing/ui/extras/system_stats/system_stats_instance_track.html">
+<link rel="import"
+ href="/tracing/ui/extras/system_stats/system_stats_snapshot_view.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.css b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.css
new file mode 100644
index 00000000000..40096f5497c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.css
@@ -0,0 +1,15 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.tr-ui-e-system-stats-instance-track {
+ height: 500px;
+}
+
+.tr-ui-e-system-stats-instance-track ul {
+ list-style: none;
+ list-style-position: outside;
+ margin: 0;
+ overflow: hidden;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html
new file mode 100644
index 00000000000..7695086660c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html
@@ -0,0 +1,451 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet"
+ href="/tracing/ui/extras/system_stats/system_stats_instance_track.css">
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/event_presenter.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/object_instance_track.html">
+<link rel="import" href="/tracing/ui/tracks/stacked_bars_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.system_stats', function() {
+ const EventPresenter = tr.ui.b.EventPresenter;
+
+ let statCount;
+
+ const excludedStats = {'meminfo': {
+ 'pswpin': 0,
+ 'pswpout': 0,
+ 'pgmajfault': 0},
+ 'diskinfo': {
+ 'io': 0,
+ 'io_time': 0,
+ 'read_time': 0,
+ 'reads': 0,
+ 'reads_merged': 0,
+ 'sectors_read': 0,
+ 'sectors_written': 0,
+ 'weighted_io_time': 0,
+ 'write_time': 0,
+ 'writes': 0,
+ 'writes_merged': 0},
+ 'swapinfo': {},
+ 'perfinfo': {
+ 'idle_time': 0,
+ 'read_transfer_count': 0,
+ 'write_transfer_count': 0,
+ 'other_transfer_count': 0,
+ 'read_operation_count': 0,
+ 'write_operation_count': 0,
+ 'other_operation_count': 0,
+ 'pagefile_pages_written': 0,
+ 'pagefile_pages_write_ios': 0,
+ 'available_pages': 0,
+ 'pages_read': 0,
+ 'page_read_ios': 0}
+ };
+
+ /**
+ * Tracks that display system stats data.
+ *
+ * @constructor
+ * @extends {StackedBarsTrack}
+ */
+
+ const SystemStatsInstanceTrack = tr.ui.b.define(
+ 'tr-ui-e-system-stats-instance-track', tr.ui.tracks.StackedBarsTrack);
+
+ const kPageSizeWindows = 4096;
+
+ SystemStatsInstanceTrack.prototype = {
+
+ __proto__: tr.ui.tracks.StackedBarsTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.StackedBarsTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('tr-ui-e-system-stats-instance-track');
+ this.objectInstance_ = null;
+ },
+
+ set objectInstances(objectInstances) {
+ if (!objectInstances) {
+ this.objectInstance_ = [];
+ return;
+ }
+ if (objectInstances.length !== 1) {
+ throw new Error('Bad object instance count.');
+ }
+ this.objectInstance_ = objectInstances[0];
+ if (this.objectInstance_ !== null) {
+ this.computeRates_(this.objectInstance_.snapshots);
+ this.maxStats_ = this.computeMaxStats_(
+ this.objectInstance_.snapshots);
+ }
+ },
+
+ computeRates_(snapshots) {
+ for (let i = 0; i < snapshots.length; i++) {
+ const snapshot = snapshots[i];
+ const stats = snapshot.getStats();
+ let prevSnapshot;
+
+ if (i === 0) {
+ // Deltas will be zero.
+ prevSnapshot = snapshots[0];
+ } else {
+ prevSnapshot = snapshots[i - 1];
+ }
+ const prevStats = prevSnapshot.getStats();
+ let timeIntervalSeconds = (snapshot.ts - prevSnapshot.ts) / 1000;
+ // Prevent divide by zero.
+ if (timeIntervalSeconds === 0) {
+ timeIntervalSeconds = 1;
+ }
+
+ this.computeRatesRecursive_(prevStats, stats,
+ timeIntervalSeconds);
+ }
+ },
+
+ computeRatesRecursive_(prevStats, stats,
+ timeIntervalSeconds) {
+ for (const statName in stats) {
+ if (stats[statName] instanceof Object) {
+ this.computeRatesRecursive_(prevStats[statName],
+ stats[statName],
+ timeIntervalSeconds);
+ } else {
+ if (statName === 'sectors_read') {
+ stats.bytes_read_per_sec = (stats.sectors_read -
+ prevStats.sectors_read) *
+ 512 / timeIntervalSeconds;
+ }
+ if (statName === 'sectors_written') {
+ stats.bytes_written_per_sec =
+ (stats.sectors_written -
+ prevStats.sectors_written) *
+ 512 / timeIntervalSeconds;
+ }
+ if (statName === 'pgmajfault') {
+ stats.pgmajfault_per_sec = (stats.pgmajfault -
+ prevStats.pgmajfault) /
+ timeIntervalSeconds;
+ }
+ if (statName === 'pswpin') {
+ stats.bytes_swpin_per_sec = (stats.pswpin -
+ prevStats.pswpin) *
+ 1000 / timeIntervalSeconds;
+ }
+ if (statName === 'pswpout') {
+ stats.bytes_swpout_per_sec = (stats.pswpout -
+ prevStats.pswpout) *
+ 1000 / timeIntervalSeconds;
+ }
+
+ // All the stats below are available only on Windows:
+
+ if (statName === 'idle_time') {
+ // Total amount of idle_time, in unit of 100 nanoseconds.
+ const units = tr.b.convertUnit(100.,
+ tr.b.UnitScale.TIME.NANO_SEC, tr.b.UnitScale.TIME.SEC);
+ const idleTile = (stats.idle_time - prevStats.idle_time) * units;
+ stats.idle_time_per_sec = idleTile / timeIntervalSeconds;
+ }
+ if (statName === 'read_transfer_count') {
+ const bytesRead = stats.read_transfer_count -
+ prevStats.read_transfer_count;
+ stats.bytes_read_per_sec = bytesRead / timeIntervalSeconds;
+ }
+ if (statName === 'write_transfer_count') {
+ const bytesWritten = stats.write_transfer_count -
+ prevStats.write_transfer_count;
+ stats.bytes_written_per_sec = bytesWritten / timeIntervalSeconds;
+ }
+ if (statName === 'other_transfer_count') {
+ const bytesTransfer = stats.other_transfer_count -
+ prevStats.other_transfer_count;
+ stats.bytes_other_per_sec = bytesTransfer / timeIntervalSeconds;
+ }
+ if (statName === 'read_operation_count') {
+ const readOperation = stats.read_operation_count -
+ prevStats.read_operation_count;
+ stats.read_operation_per_sec = readOperation / timeIntervalSeconds;
+ }
+ if (statName === 'write_operation_count') {
+ const writeOperation = stats.write_operation_count -
+ prevStats.write_operation_count;
+ stats.write_operation_per_sec =
+ writeOperation / timeIntervalSeconds;
+ }
+ if (statName === 'other_operation_count') {
+ const otherOperation = stats.other_operation_count -
+ prevStats.other_operation_count;
+ stats.other_operation_per_sec =
+ otherOperation / timeIntervalSeconds;
+ }
+ if (statName === 'pagefile_pages_written') {
+ const pageFileBytesWritten =
+ (stats.pagefile_pages_written -
+ prevStats.pagefile_pages_written) * kPageSizeWindows;
+ stats.pagefile_bytes_written_per_sec =
+ pageFileBytesWritten / timeIntervalSeconds;
+ }
+ if (statName === 'pagefile_pages_write_ios') {
+ const pagefileWriteOperation =
+ stats.pagefile_pages_write_ios -
+ prevStats.pagefile_pages_write_ios;
+ stats.pagefile_write_operation_per_sec =
+ pagefileWriteOperation / timeIntervalSeconds;
+ }
+ if (statName === 'available_pages') {
+ // Nothing to do here for now.
+ stats.available_pages_in_bytes =
+ stats.available_pages * kPageSizeWindows;
+ // TODO(sebmarchand): Add a available_pages_field that tracks the
+ // variation of this metric?
+ }
+ if (statName === 'pages_read') {
+ const pagesBytesRead =
+ (stats.pages_read - prevStats.pages_read) * kPageSizeWindows;
+ stats.bytes_read_per_sec = pagesBytesRead / timeIntervalSeconds;
+ }
+ if (statName === 'page_read_ios') {
+ const pagesBytesReadOperations =
+ stats.page_read_ios - prevStats.page_read_ios;
+ stats.pagefile_write_operation_per_sec =
+ pagesBytesReadOperations / timeIntervalSeconds;
+ }
+ }
+ }
+ },
+
+ computeMaxStats_(snapshots) {
+ const maxStats = {};
+ statCount = 0;
+
+ for (let i = 0; i < snapshots.length; i++) {
+ const snapshot = snapshots[i];
+ const stats = snapshot.getStats();
+
+ this.computeMaxStatsRecursive_(stats, maxStats,
+ excludedStats);
+ }
+
+ return maxStats;
+ },
+
+ computeMaxStatsRecursive_(stats, maxStats, excludedStats) {
+ for (const statName in stats) {
+ if (stats[statName] instanceof Object) {
+ if (!(statName in maxStats)) {
+ maxStats[statName] = {};
+ }
+
+ let excludedNested;
+ if (excludedStats && statName in excludedStats) {
+ excludedNested = excludedStats[statName];
+ } else {
+ excludedNested = null;
+ }
+
+ this.computeMaxStatsRecursive_(stats[statName],
+ maxStats[statName],
+ excludedNested);
+ } else {
+ if (excludedStats && statName in excludedStats) {
+ continue;
+ }
+ if (!(statName in maxStats)) {
+ maxStats[statName] = 0;
+ statCount++;
+ }
+ if (stats[statName] > maxStats[statName]) {
+ maxStats[statName] = stats[statName];
+ }
+ }
+ }
+ },
+
+ get height() {
+ return window.getComputedStyle(this).height;
+ },
+
+ set height(height) {
+ this.style.height = height;
+ },
+
+ draw(type, viewLWorld, viewRWorld, viewHeight) {
+ switch (type) {
+ case tr.ui.tracks.DrawType.GENERAL_EVENT:
+ this.drawStatBars_(viewLWorld, viewRWorld);
+ break;
+ }
+ },
+
+ drawStatBars_(viewLWorld, viewRWorld) {
+ const ctx = this.context();
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ const bounds = this.getBoundingClientRect();
+ const width = bounds.width * pixelRatio;
+ const height = (bounds.height * pixelRatio) / statCount;
+
+ // Culling parameters.
+ const vp = this.viewport.currentDisplayTransform;
+
+ // Scale by the size of the largest snapshot.
+ const maxStats = this.maxStats_;
+
+ const objectSnapshots = this.objectInstance_.snapshots;
+ let lowIndex = tr.b.findLowIndexInSortedArray(
+ objectSnapshots,
+ function(snapshot) {
+ return snapshot.ts;
+ },
+ viewLWorld);
+
+ // Assure that the stack with the left edge off screen still gets drawn
+ if (lowIndex > 0) lowIndex -= 1;
+
+ for (let i = lowIndex; i < objectSnapshots.length; ++i) {
+ const snapshot = objectSnapshots[i];
+ const trace = snapshot.getStats();
+ const currentY = height;
+
+ const left = snapshot.ts;
+ if (left > viewRWorld) break;
+
+ let leftView = vp.xWorldToView(left);
+ if (leftView < 0) leftView = 0;
+
+ // Compute the edges for the column graph bar.
+ let right;
+ if (i !== objectSnapshots.length - 1) {
+ right = objectSnapshots[i + 1].ts;
+ } else {
+ // If this is the last snapshot of multiple snapshots, use the width
+ // of the previous snapshot for the width.
+ if (objectSnapshots.length > 1) {
+ right = objectSnapshots[i].ts + (objectSnapshots[i].ts -
+ objectSnapshots[i - 1].ts);
+ } else {
+ // If there's only one snapshot, use max bounds as the width.
+ right = this.objectInstance_.parent.model.bounds.max;
+ }
+ }
+
+ let rightView = vp.xWorldToView(right);
+ if (rightView > width) {
+ rightView = width;
+ }
+
+ // Floor the bounds to avoid a small gap between stacks.
+ leftView = Math.floor(leftView);
+ rightView = Math.floor(rightView);
+
+ // Descend into nested stats.
+ this.drawStatBarsRecursive_(snapshot,
+ leftView,
+ rightView,
+ height,
+ trace,
+ maxStats,
+ currentY);
+
+ if (i === lowIndex) {
+ this.drawStatNames_(leftView, height, currentY, '', maxStats);
+ }
+ }
+ ctx.lineWidth = 1;
+ },
+
+ drawStatBarsRecursive_(snapshot,
+ leftView,
+ rightView,
+ height,
+ stats,
+ maxStats,
+ currentY) {
+ const ctx = this.context();
+
+ for (const statName in maxStats) {
+ if (stats[statName] instanceof Object) {
+ // Use the y-position returned from the recursive call.
+ currentY = this.drawStatBarsRecursive_(snapshot,
+ leftView,
+ rightView,
+ height,
+ stats[statName],
+ maxStats[statName],
+ currentY);
+ } else {
+ const maxStat = maxStats[statName];
+
+ // Draw a bar for the stat. The height of the bar is scaled
+ // against the largest value of the stat across all snapshots.
+ ctx.fillStyle = EventPresenter.getBarSnapshotColor(
+ snapshot, Math.round(currentY / height));
+
+ let barHeight;
+ if (maxStat > 0) {
+ barHeight = height * Math.max(stats[statName], 0) / maxStat;
+ } else {
+ barHeight = 0;
+ }
+
+ ctx.fillRect(leftView, currentY - barHeight,
+ Math.max(rightView - leftView, 1), barHeight);
+
+ currentY += height;
+ }
+ }
+
+ // Return the updated y-position.
+ return currentY;
+ },
+
+ drawStatNames_(leftView, height, currentY, prefix, maxStats) {
+ const ctx = this.context();
+
+ ctx.textAlign = 'end';
+ ctx.font = '12px Arial';
+ ctx.fillStyle = '#000000';
+ for (const statName in maxStats) {
+ if (maxStats[statName] instanceof Object) {
+ currentY = this.drawStatNames_(leftView, height, currentY,
+ statName, maxStats[statName]);
+ } else {
+ let fullname = statName;
+
+ if (prefix !== '') {
+ fullname = prefix + ' :: ' + statName;
+ }
+
+ ctx.fillText(fullname, leftView - 10, currentY - height / 4);
+ currentY += height;
+ }
+ }
+
+ return currentY;
+ }
+ };
+
+ tr.ui.tracks.ObjectInstanceTrack.register(
+ SystemStatsInstanceTrack,
+ {typeName: 'base::TraceEventSystemStatsMonitor::SystemStats'});
+
+ return {
+ SystemStatsInstanceTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track_test.html
new file mode 100644
index 00000000000..8dc4bc28264
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_instance_track_test.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/extras/system_stats/system_stats.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const SystemStatsInstanceTrack =
+ tr.ui.e.system_stats.SystemStatsInstanceTrack;
+ const Viewport = tr.ui.TimelineViewport;
+
+ const createObjects = function() {
+ const objectInstance = new tr.model.ObjectInstance({});
+ const snapshots = [];
+
+ const stats1 = {};
+ const stats2 = {};
+
+ stats1.committed_memory = 2000000;
+ stats2.committed_memory = 3000000;
+
+ stats1.meminfo = {};
+ stats1.meminfo.free = 10000;
+ stats2.meminfo = {};
+ stats2.meminfo.free = 20000;
+
+ stats1.perfinfo = {};
+ stats1.perfinfo.idle_time = 10;
+ stats1.perfinfo.read_transfer_count = 20;
+ stats1.perfinfo.write_transfer_count = 30;
+ stats1.perfinfo.other_transfer_count = 40;
+ stats1.perfinfo.read_operation_count = 2;
+ stats1.perfinfo.write_operation_count = 3;
+ stats1.perfinfo.other_operation_count = 4;
+ stats1.perfinfo.pagefile_pages_written = 5;
+ stats1.perfinfo.pagefile_pages_write_ios = 6;
+
+ stats2.perfinfo = {};
+ stats2.perfinfo.idle_time = 110;
+ stats2.perfinfo.read_transfer_count = 120;
+ stats2.perfinfo.write_transfer_count = 130;
+ stats2.perfinfo.other_transfer_count = 140;
+ stats2.perfinfo.read_operation_count = 102;
+ stats2.perfinfo.write_operation_count = 103;
+ stats2.perfinfo.other_operation_count = 104;
+ stats2.perfinfo.pagefile_pages_written = 105;
+ stats2.perfinfo.pagefile_pages_write_ios = 106;
+
+ snapshots.push(new tr.e.system_stats.SystemStatsSnapshot(objectInstance,
+ 10, stats1));
+ snapshots.push(new tr.e.system_stats.SystemStatsSnapshot(objectInstance,
+ 20, stats2));
+
+ objectInstance.snapshots = snapshots;
+
+ return objectInstance;
+ };
+
+ test('instantiate', function() {
+ const objectInstances = [];
+ objectInstances.push(createObjects());
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = new SystemStatsInstanceTrack(viewport);
+ track.objectInstances = objectInstances;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ const snapshot1 = track.objectInstance_.snapshots[1];
+ const stats1 = snapshot1.getStats();
+
+ // Raw counters should not move.
+ assert.strictEqual(stats1.perfinfo.idle_time, 110);
+ assert.strictEqual(stats1.perfinfo.read_operation_count, 102);
+ assert.strictEqual(stats1.perfinfo.write_operation_count, 103);
+ assert.strictEqual(stats1.perfinfo.other_operation_count, 104);
+ assert.strictEqual(stats1.perfinfo.read_transfer_count, 120);
+ assert.strictEqual(stats1.perfinfo.write_transfer_count, 130);
+ assert.strictEqual(stats1.perfinfo.other_transfer_count, 140);
+ assert.strictEqual(stats1.perfinfo.pagefile_pages_written, 105);
+ assert.strictEqual(stats1.perfinfo.pagefile_pages_write_ios, 106);
+
+ // Rates should be computed.
+ assert.strictEqual(stats1.perfinfo.idle_time_per_sec, 0.001);
+ assert.strictEqual(stats1.perfinfo.bytes_read_per_sec, 10000);
+ assert.strictEqual(stats1.perfinfo.bytes_written_per_sec, 10000);
+ assert.strictEqual(stats1.perfinfo.bytes_other_per_sec, 10000);
+ assert.strictEqual(stats1.perfinfo.read_operation_per_sec, 10000);
+ assert.strictEqual(stats1.perfinfo.write_operation_per_sec, 10000);
+ assert.strictEqual(stats1.perfinfo.other_operation_per_sec, 10000);
+ assert.strictEqual(stats1.perfinfo.pagefile_bytes_written_per_sec,
+ 40960000);
+ assert.strictEqual(stats1.perfinfo.pagefile_write_operation_per_sec, 10000);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.heading = 'testBasic';
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 50, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_snapshot_view.css b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_snapshot_view.css
new file mode 100644
index 00000000000..e698b15aa70
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_snapshot_view.css
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.tr-ui-e-system-stats-snapshot-view .subhead {
+ font-size: small;
+ padding-bottom: 10px;
+}
+
+.tr-ui-e-system-stats-snapshot-view ul {
+ background-position: 0 5px;
+ background-repeat: no-repeat;
+ cursor: pointer;
+ font-family: monospace;
+ list-style: none;
+ margin: 0;
+ padding-left: 15px;
+}
+
+.tr-ui-e-system-stats-snapshot-view li {
+ background-position: 0 5px;
+ background-repeat: no-repeat;
+ cursor: pointer;
+ list-style: none;
+ margin: 0;
+ padding-left: 15px;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_snapshot_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_snapshot_view.html
new file mode 100644
index 00000000000..54f4b869f4a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/system_stats/system_stats_snapshot_view.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet"
+ href="/tracing/ui/extras/system_stats/system_stats_snapshot_view.css">
+
+<link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.system_stats', function() {
+ /*
+ * Displays a system stats snapshot in a human readable form. @constructor
+ */
+ const SystemStatsSnapshotView = tr.ui.b.define(
+ 'tr-ui-e-system-stats-snapshot-view', tr.ui.analysis.ObjectSnapshotView);
+
+ SystemStatsSnapshotView.prototype = {
+ __proto__: tr.ui.analysis.ObjectSnapshotView.prototype,
+
+ decorate() {
+ Polymer.dom(this).classList.add('tr-ui-e-system-stats-snapshot-view');
+ },
+
+ updateContents() {
+ const snapshot = this.objectSnapshot_;
+ if (!snapshot || !snapshot.getStats()) {
+ Polymer.dom(this).textContent = 'No system stats snapshot found.';
+ return;
+ }
+ // Clear old snapshot view.
+ Polymer.dom(this).textContent = '';
+
+ const stats = snapshot.getStats();
+ Polymer.dom(this).appendChild(this.buildList_(stats));
+ },
+
+ isFloat(n) {
+ return typeof n === 'number' && n % 1 !== 0;
+ },
+
+ /**
+ * Creates nested lists.
+ *
+ * @param {Object} stats The current trace system stats entry.
+ * @return {Element} A ul list element.
+ */
+ buildList_(stats) {
+ const statList = document.createElement('ul');
+
+ for (const statName in stats) {
+ const statText = document.createElement('li');
+ Polymer.dom(statText).textContent = '' + statName + ': ';
+ Polymer.dom(statList).appendChild(statText);
+
+ if (stats[statName] instanceof Object) {
+ Polymer.dom(statList).appendChild(this.buildList_(stats[statName]));
+ } else {
+ if (this.isFloat(stats[statName])) {
+ Polymer.dom(statText).textContent += stats[statName].toFixed(2);
+ } else {
+ Polymer.dom(statText).textContent += stats[statName];
+ }
+ }
+ }
+
+ return statList;
+ }
+ };
+
+ tr.ui.analysis.ObjectSnapshotView.register(
+ SystemStatsSnapshotView,
+ {typeName: 'base::TraceEventSystemStatsMonitor::SystemStats'});
+
+ return {
+ SystemStatsSnapshotView,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/systrace_config.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/systrace_config.html
new file mode 100644
index 00000000000..fcc410b754a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/systrace_config.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+TODO(charliea): Make all UI files depend on tracing/ui/base/base.html in the
+same way that all non-UI files depend on tracing/base/base.html. Enforce this
+dependency with a presubmit.
+-->
+<link rel="import" href="/tracing/ui/base/base.html" data-suppress-import-order>
+
+<link rel="import" href="/tracing/extras/systrace_config.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/extras/side_panel/alerts_side_panel.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html
new file mode 100644
index 00000000000..bc3247d9289
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table.html
@@ -0,0 +1,728 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/v8/v8_gc_stats_thread_slice.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-e-v8-gc-objects-stats-table'>
+ <template>
+ <style>
+ tr-ui-b-table {
+ flex: 0 0 auto;
+ align-self: stretch;
+ margin-top: 1em;
+ font-size: 12px;
+ }
+ .diff {
+ display: inline-block;
+ margin-top: 1em;
+ margin-left: 0.8em;
+ }
+ </style>
+ <div class="diff" id="diffOption">
+ Diff
+ </div>
+ <tr-ui-b-table id="diffTable"></tr-ui-b-table>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.v8', function() {
+ // Instance types that should not be part of the overview as they are either
+ // double-attributed (e.g. also part of some other instance type) or do not
+ // make any sense in memory profiling.
+ const IGNORED_ENTRIES = {
+ // Ignore code aging entries as they are already accounted in their
+ // respective code instance types.
+ match: full => full.startsWith('*CODE_AGE_')
+ };
+
+ // Groups are matched on a first-matched basis, i.e., once a group matches we
+ // are done with an entry.
+ // Requires properties:
+ // - match(full): Return true iff |full| should be part of the group and
+ // false otherwise.
+ // - keyToName(key): Returns the human readable name for |key|.
+ // - nameToKey(name): Returns the key for |name|.
+ // Optional properties:
+ // - realEntry: A string representing the actual entry in the trace. If this
+ // entry is present an additional entry UNKNOWN will be created holding all
+ // the unaccounted data.
+ const INSTANCE_TYPE_GROUPS = {
+ FIXED_ARRAY_TYPE: {
+ match: full => full.startsWith('*FIXED_ARRAY_'),
+ realEntry: 'FIXED_ARRAY_TYPE',
+ keyToName: key => key.slice('*FIXED_ARRAY_'.length)
+ .slice(0, -('_SUB_TYPE'.length)),
+ nameToKey: name => '*FIXED_ARRAY_' + name + '_SUB_TYPE'
+ },
+ CODE_TYPE: {
+ match: full => full.startsWith('*CODE_'),
+ realEntry: 'CODE_TYPE',
+ keyToName: key => key.slice('*CODE_'.length),
+ nameToKey: name => '*CODE_' + name
+ },
+ JS_OBJECTS: {
+ match: full => full.startsWith('JS_'),
+ keyToName: key => key,
+ nameToKey: name => name
+ },
+ Strings: {
+ match: full => full.endsWith('STRING_TYPE'),
+ keyToName: key => key,
+ nameToKey: name => name
+ }
+ };
+
+ const DIFF_COLOR = {
+ GREEN: '#64DD17',
+ RED: '#D50000'
+ };
+
+ function computePercentage(valueA, valueB) {
+ if (valueA === 0) return 0;
+ return valueA / valueB * 100;
+ }
+
+ class DiffEntry {
+ constructor(originalEntry, diffEntry) {
+ this.originalEntry_ = originalEntry;
+ this.diffEntry_ = diffEntry;
+ }
+ get title() {
+ return this.diffEntry_.title;
+ }
+ get overall() {
+ return this.diffEntry_.overall;
+ }
+ get overAllocated() {
+ return this.diffEntry_.overAllocated;
+ }
+ get count() {
+ return this.diffEntry_.count;
+ }
+ get overallPercent() {
+ return this.diffEntry_.overallPercent;
+ }
+ get overAllocatedPercent() {
+ return this.diffEntry_.overAllocatedPercent;
+ }
+ get origin() {
+ return this.originalEntry_;
+ }
+ get diff() {
+ return this.diffEntry_;
+ }
+ get subRows() {
+ return this.diffEntry_.subRows;
+ }
+ }
+
+ class Entry {
+ constructor(title, count, overall, overAllocated, histogram,
+ overAllocatedHistogram) {
+ this.title_ = title;
+ this.overall_ = overall;
+ this.count_ = count;
+ this.overAllocated_ = overAllocated;
+ this.histogram_ = histogram;
+ this.overAllocatedHistogram_ = overAllocatedHistogram;
+ this.bucketSize_ = this.histogram_.length;
+ this.overallPercent_ = 100;
+ this.overAllocatedPercent_ = 100;
+ }
+
+ get title() {
+ return this.title_;
+ }
+
+ get overall() {
+ return this.overall_;
+ }
+
+ get count() {
+ return this.count_;
+ }
+
+ get overAllocated() {
+ return this.overAllocated_;
+ }
+
+ get histogram() {
+ return this.histogram_;
+ }
+
+ get overAllocatedHistogram() {
+ return this.overAllocatedHistogram_;
+ }
+
+ get bucketSize() {
+ return this.bucketSize_;
+ }
+
+ get overallPercent() {
+ return this.overallPercent_;
+ }
+
+ set overallPercent(value) {
+ this.overallPercent_ = value;
+ }
+
+ get overAllocatedPercent() {
+ return this.overAllocatedPercent_;
+ }
+
+ set overAllocatedPercent(value) {
+ this.overAllocatedPercent_ = value;
+ }
+
+ setFromObject(obj) {
+ this.count_ = obj.count;
+ // Calculate memory in KB.
+ this.overall_ = obj.overall / 1024;
+ this.overAllocated_ = obj.over_allocated / 1024;
+ this.histogram_ = obj.histogram;
+ this.overAllocatedHistogram_ = obj.over_allocated_histogram;
+ }
+
+ diff(other) {
+ const entry = new Entry(this.title_, other.count_ - this.count,
+ other.overall_ - this.overall,
+ other.overAllocated_ - this.overAllocated, [], []);
+ entry.overallPercent = computePercentage(entry.overall, this.overall);
+ entry.overAllocatedPercent = computePercentage(entry.overAllocated,
+ this.overAllocated);
+ return new DiffEntry(this, entry);
+ }
+ }
+
+ class GroupedEntry extends Entry {
+ constructor(title, count, overall, overAllocated, histogram,
+ overAllocatedHistogram) {
+ super(title, count, overall, overAllocated, histogram,
+ overAllocatedHistogram);
+ this.histogram_.fill(0);
+ this.overAllocatedHistogram_.fill(0);
+ this.entries_ = new Map();
+ }
+
+ get title() {
+ return this.title_;
+ }
+
+ set title(value) {
+ this.title_ = value;
+ }
+
+ get subRows() {
+ return Array.from(this.entries_.values());
+ }
+
+ getEntryFromTitle(title) {
+ return this.entries_.get(title);
+ }
+
+ add(entry) {
+ this.count_ += entry.count;
+ this.overall_ += entry.overall;
+ this.overAllocated_ += entry.overAllocated;
+ if (this.bucketSize_ === entry.bucketSize) {
+ for (let i = 0; i < this.bucketSize_; ++i) {
+ this.histogram_[i] += entry.histogram[i];
+ this.overAllocatedHistogram_[i] += entry.overAllocatedHistogram[i];
+ }
+ }
+ this.entries_.set(entry.title, entry);
+ }
+
+ accumulateUnknown(title) {
+ let unknownCount = this.count_;
+ let unknownOverall = this.overall_;
+ let unknownOverAllocated = this.overAllocated_;
+ const unknownHistogram = tr.b.deepCopy(this.histogram_);
+ const unknownOverAllocatedHistogram =
+ tr.b.deepCopy(this.overAllocatedHistogram_);
+ for (const entry of this.entries_.values()) {
+ unknownCount -= entry.count;
+ unknownOverall -= entry.overall;
+ unknownOverAllocated -= entry.overAllocated;
+ for (let i = 0; i < this.bucketSize_; ++i) {
+ unknownHistogram[i] -= entry.histogram[i];
+ unknownOverAllocatedHistogram[i] -= entry.overAllocatedHistogram[i];
+ }
+ }
+ unknownOverAllocated =
+ unknownOverAllocated < 0 ? 0 : unknownOverAllocated;
+ this.entries_.set(title, new Entry(title, unknownCount, unknownOverall,
+ unknownOverAllocated, unknownHistogram,
+ unknownOverAllocatedHistogram));
+ }
+
+ calculatePercentage() {
+ for (const entry of this.entries_.values()) {
+ entry.overallPercent = computePercentage(entry.overall, this.overall_);
+ entry.overAllocatedPercent =
+ computePercentage(entry.overAllocated, this.overAllocated_);
+
+ if (entry instanceof GroupedEntry) entry.calculatePercentage();
+ }
+ }
+
+ diff(other) {
+ let newTitle = '';
+ if (this.title_.startsWith('Isolate')) {
+ newTitle = 'Total';
+ } else {
+ newTitle = this.title_;
+ }
+ const result = new GroupedEntry(newTitle, 0, 0, 0, [], []);
+ for (const entry of this.entries_) {
+ const otherEntry = other.getEntryFromTitle(entry[0]);
+ if (otherEntry === undefined) continue;
+ result.add(entry[1].diff(otherEntry));
+ }
+ result.overallPercent = computePercentage(result.overall, this.overall);
+ result.overAllocatedPercent = computePercentage(result.overAllocated,
+ this.overAllocated);
+ return new DiffEntry(this, result);
+ }
+ }
+
+ function createSelector(targetEl, defaultValue, items, callback) {
+ const selectorEl = document.createElement('select');
+ selectorEl.addEventListener('change', callback.bind(targetEl));
+ const defaultOptionEl = document.createElement('option');
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ const optionEl = document.createElement('option');
+ Polymer.dom(optionEl).textContent = item.label;
+ optionEl.targetPropertyValue = item.value;
+ optionEl.item = item;
+ Polymer.dom(selectorEl).appendChild(optionEl);
+ }
+ selectorEl.__defineGetter__('selectedValue', function(v) {
+ if (selectorEl.children[selectorEl.selectedIndex] === undefined) {
+ return undefined;
+ }
+ return selectorEl.children[selectorEl.selectedIndex].targetPropertyValue;
+ });
+ selectorEl.__defineGetter__('selectedItem', function(v) {
+ if (selectorEl.children[selectorEl.selectedIndex] === undefined) {
+ return undefined;
+ }
+ return selectorEl.children[selectorEl.selectedIndex].item;
+ });
+ selectorEl.__defineSetter__('selectedValue', function(v) {
+ for (let i = 0; i < selectorEl.children.length; i++) {
+ const value = selectorEl.children[i].targetPropertyValue;
+ if (value === v) {
+ const changed = selectorEl.selectedIndex !== i;
+ if (changed) {
+ selectorEl.selectedIndex = i;
+ callback();
+ }
+ return;
+ }
+ }
+ throw new Error('Not a valid value');
+ });
+ selectorEl.selectedIndex = -1;
+
+ return selectorEl;
+ }
+
+ function plusMinus(value, toFixed = 3) {
+ return (value > 0 ? '+' : '') + value.toFixed(toFixed);
+ }
+
+ function addArrow(value) {
+ if (value === 0) return value;
+ if (value === Number.NEGATIVE_INFINITY) return '\u2193\u221E';
+ if (value === Number.POSITIVE_INFINITY) return '\u2191\u221E';
+ return (value > 0 ? '\u2191' : '\u2193') + Math.abs(value.toFixed(3));
+ }
+
+ Polymer({
+ is: 'tr-ui-e-v8-gc-objects-stats-table',
+
+ ready() {
+ this.$.diffOption.style.display = 'none';
+ this.isolateEntries_ = [];
+ this.selector1_ = undefined;
+ this.selector2_ = undefined;
+ },
+
+ constructDiffTable_(table) {
+ this.$.diffTable.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ this.$.diffTable.tableColumns = [
+ {
+ title: 'Component',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.title;
+ return typeEl;
+ },
+ showExpandButtons: true
+ },
+ {
+ title: 'Overall Memory(KB)',
+ value(row) {
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = row.origin.overall.toFixed(3);
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.origin.overall - b.origin.overall;
+ }
+ },
+ {
+ title: 'diff(KB)',
+ value(row) {
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = plusMinus(row.overall);
+ if (row.overall > 0) {
+ spanEl.style.color = DIFF_COLOR.RED;
+ } else if (row.overall < 0) {
+ spanEl.style.color = DIFF_COLOR.GREEN;
+ }
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.overall - b.overall;
+ }
+ },
+ {
+ title: 'diff(%)',
+ value(row) {
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = addArrow(row.overallPercent);
+ if (row.overall > 0) {
+ spanEl.style.color = DIFF_COLOR.RED;
+ } else if (row.overall < 0) {
+ spanEl.style.color = DIFF_COLOR.GREEN;
+ }
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.overall - b.overall;
+ }
+ },
+ {
+ title: 'Over Allocated Memory(KB)',
+ value(row) {
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = row.origin.overAllocated.toFixed(3);
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.origin.overAllocated - b.origin.overAllocated;
+ }
+ },
+ {
+ title: 'diff(KB)',
+ value(row) {
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = plusMinus(row.overAllocated);
+ if (row.overAllocated > 0) {
+ spanEl.style.color = DIFF_COLOR.RED;
+ } else if (row.overAllocated < 0) {
+ spanEl.style.color = DIFF_COLOR.GREEN;
+ }
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.overAllocated - b.overAllocated;
+ }
+ },
+ {
+ title: 'diff(%)',
+ value(row) {
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = addArrow(row.overAllocatedPercent);
+ if (row.overAllocated > 0) {
+ spanEl.style.color = DIFF_COLOR.RED;
+ } else if (row.overAllocated < 0) {
+ spanEl.style.color = DIFF_COLOR.GREEN;
+ }
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.overAllocated - b.overAllocated;
+ }
+ },
+ {
+ title: 'Count',
+ value(row) {
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = row.origin.count;
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.origin.count - b.origin.count;
+ }
+ },
+ {
+ title: 'diff',
+ value(row) {
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = plusMinus(row.count, 0);
+ if (row.count > 0) {
+ spanEl.style.color = DIFF_COLOR.RED;
+ } else if (row.count < 0) {
+ spanEl.style.color = DIFF_COLOR.GREEN;
+ }
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.count - b.count;
+ }
+ },
+ ];
+ },
+
+ buildOptions_() {
+ const items = [];
+ for (const isolateEntry of this.isolateEntries_) {
+ items.push({
+ label: isolateEntry.title,
+ value: isolateEntry
+ });
+ }
+ this.$.diffOption.style.display = 'inline-block';
+ this.selector1_ = createSelector(
+ this, '', items, this.diffOptionChanged_);
+ Polymer.dom(this.$.diffOption).appendChild(this.selector1_);
+ const spanEl = tr.ui.b.createSpan();
+ spanEl.innerText = ' VS ';
+ Polymer.dom(this.$.diffOption).appendChild(spanEl);
+ this.selector2_ = createSelector(
+ this, '', items, this.diffOptionChanged_);
+ Polymer.dom(this.$.diffOption).appendChild(this.selector2_);
+ },
+
+ diffOptionChanged_() {
+ const isolateEntry1 = this.selector1_.selectedValue;
+ const isolateEntry2 = this.selector2_.selectedValue;
+ if (isolateEntry1 === undefined || isolateEntry2 === undefined) {
+ return;
+ }
+ if (isolateEntry1 === isolateEntry2) {
+ this.$.diffTable.tableRows = [];
+ this.$.diffTable.rebuild();
+ return;
+ }
+ this.$.diffTable.tableRows = [isolateEntry1.diff(isolateEntry2)];
+ this.$.diffTable.rebuild();
+ },
+
+ constructTable_() {
+ this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ this.$.table.tableColumns = [
+ {
+ title: 'Component',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.title;
+ return typeEl;
+ },
+ showExpandButtons: true
+ },
+ {
+ title: 'Overall Memory (KB)',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.overall.toFixed(3);
+ return typeEl;
+ },
+ cmp(a, b) {
+ return a.overall - b.overall;
+ }
+ },
+ {
+ title: 'Over Allocated Memory (KB)',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.overAllocated.toFixed(3);
+ return typeEl;
+ },
+ cmp(a, b) {
+ return a.overAllocated - b.overAllocated;
+ }
+ },
+ {
+ title: 'Overall Count',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.count;
+ return typeEl;
+ },
+ cmp(a, b) {
+ return a.count - b.count;
+ }
+ },
+ {
+ title: 'Overall Memory Percent',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.overallPercent.toFixed(3) + '%';
+ return typeEl;
+ },
+ cmp(a, b) {
+ return a.overall - b.overall;
+ }
+ },
+ {
+ title: 'Overall Allocated Memory Percent',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.overAllocatedPercent.toFixed(3) + '%';
+ return typeEl;
+ },
+ cmp(a, b) {
+ return a.overAllocated - b.overAllocated;
+ }
+ }
+ ];
+
+ this.$.table.sortColumnIndex = 1;
+ this.$.table.sortDescending = true;
+ },
+
+ buildSubEntry_(objects, groupEntry, keyToName) {
+ const typeGroup = INSTANCE_TYPE_GROUPS[groupEntry.title];
+ for (const instanceType of typeGroup) {
+ const e = objects[instanceType];
+ if (e === undefined) continue;
+ delete objects[instanceType];
+ let title = instanceType;
+ if (keyToName !== undefined) title = keyToName(title);
+ // Represent memery in KB unit.
+ groupEntry.add(new Entry(title, e.count, e.overall / 1024,
+ e.over_allocated / 1024, e.histogram,
+ e.over_allocated_histogram));
+ }
+ },
+
+ buildUnGroupedEntries_(objects, objectEntry, bucketSize) {
+ for (const title of Object.getOwnPropertyNames(objects)) {
+ const obj = objects[title];
+ const groupedEntry = new GroupedEntry(title, 0, 0, 0,
+ new Array(bucketSize),
+ new Array(bucketSize));
+ groupedEntry.setFromObject(obj);
+ objectEntry.add(groupedEntry);
+ }
+ },
+
+ createGroupEntries_(groupEntries, objects, bucketSize) {
+ for (const groupName of Object.getOwnPropertyNames(
+ INSTANCE_TYPE_GROUPS)) {
+ const groupEntry = new GroupedEntry(groupName, 0, 0, 0,
+ new Array(bucketSize),
+ new Array(bucketSize));
+ if (INSTANCE_TYPE_GROUPS[groupName].realEntry !== undefined) {
+ groupEntry.savedRealEntry =
+ objects[INSTANCE_TYPE_GROUPS[groupName].realEntry];
+ delete objects[INSTANCE_TYPE_GROUPS[groupName].realEntry];
+ }
+ groupEntries[groupName] = groupEntry;
+ }
+ },
+
+ buildGroupEntries_(groupEntries, objectEntry) {
+ for (const groupName of Object.getOwnPropertyNames(groupEntries)) {
+ const groupEntry = groupEntries[groupName];
+ if (groupEntry.savedRealEntry !== undefined) {
+ groupEntry.setFromObject(groupEntry.savedRealEntry);
+ groupEntry.accumulateUnknown('UNKNOWN');
+ delete groupEntry.savedRealEntry;
+ }
+ objectEntry.add(groupEntry);
+ }
+ },
+
+ buildSubEntriesForGroups_(groupEntries, objects) {
+ for (const instanceType of Object.getOwnPropertyNames(objects)) {
+ if (IGNORED_ENTRIES.match(instanceType)) {
+ delete objects[instanceType];
+ continue;
+ }
+ const e = objects[instanceType];
+ for (const name of Object.getOwnPropertyNames(INSTANCE_TYPE_GROUPS)) {
+ const group = INSTANCE_TYPE_GROUPS[name];
+ if (group.match(instanceType)) {
+ groupEntries[name].add(new Entry(
+ group.keyToName(instanceType), e.count, e.overall / 1024,
+ e.over_allocated / 1024, e.histogram,
+ e.over_allocated_histogram));
+ delete objects[instanceType];
+ }
+ }
+ }
+ },
+
+ build_(objects, objectEntry, bucketSize) {
+ delete objects.END;
+ const groupEntries = {};
+ this.createGroupEntries_(groupEntries, objects, bucketSize);
+ this.buildSubEntriesForGroups_(groupEntries, objects);
+ this.buildGroupEntries_(groupEntries, objectEntry);
+ this.buildUnGroupedEntries_(objects, objectEntry, bucketSize);
+ },
+
+ set selection(slices) {
+ slices.sortEvents(function(a, b) {
+ return b.start - a.start;
+ });
+ const previous = undefined;
+ for (const slice of slices) {
+ if (!slice instanceof tr.e.v8.V8GCStatsThreadSlice) continue;
+ const liveObjects = slice.liveObjects;
+ const deadObjects = slice.deadObjects;
+ const isolate = liveObjects.isolate;
+
+ const isolateEntry =
+ new GroupedEntry(
+ 'Isolate_' + isolate + ' at ' + slice.start.toFixed(3) + ' ms',
+ 0, 0, 0, [], []);
+ const liveEntry = new GroupedEntry('live objects', 0, 0, 0, [], []);
+ const deadEntry = new GroupedEntry('dead objects', 0, 0, 0, [], []);
+
+ const liveBucketSize = liveObjects.bucket_sizes.length;
+ const deadBucketSize = deadObjects.bucket_sizes.length;
+
+ this.build_(tr.b.deepCopy(liveObjects.type_data), liveEntry,
+ liveBucketSize);
+ isolateEntry.add(liveEntry);
+
+ this.build_(tr.b.deepCopy(deadObjects.type_data), deadEntry,
+ deadBucketSize);
+ isolateEntry.add(deadEntry);
+
+ isolateEntry.calculatePercentage();
+ this.isolateEntries_.push(isolateEntry);
+ }
+ this.updateTable_();
+
+ if (slices.length > 1) {
+ this.buildOptions_();
+ this.constructDiffTable_();
+ }
+ },
+
+ updateTable_() {
+ this.constructTable_();
+ this.$.table.tableRows = this.isolateEntries_;
+ this.$.table.rebuild();
+ },
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table_test.html
new file mode 100644
index 00000000000..42d904d94c8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/gc_objects_stats_table_test.html
@@ -0,0 +1,198 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/v8/v8_gc_stats_thread_slice.html">
+<link rel="import" href="/tracing/ui/extras/v8/gc_objects_stats_table.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ function createModel() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+
+ m.s1 = m.t2.sliceGroup.pushSlice(
+ newSliceEx({
+ title: 'V8.GC_Objects_Stats',
+ start: 1,
+ end: 1,
+ type: tr.e.v8.V8GCStatsThreadSlice,
+ cat: 'disabled-by-default-v8.gc_stats',
+ args: {
+ // eslint-disable-next-line
+ live:'{"isolate":"0x00000000001","id":1,"time":111,"bucket_sizes":[32,64,128,256],"type_data":{"STRING_TYPE":{"type":1,"overall":2,"count":3,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"FIXED_ARRAY_TYPE":{"type":2,"overall":5,"count":6,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"*FIXED_ARRAY_CONTEXT_SUB_TYPE":{"type":3,"overall":1,"count":1,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"JS_OBJECT_TYPE":{"type":4,"overall":5,"count":1,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"JS_TYPED_ARRAY_TYPE":{"type":5,"overall":5,"count":1,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"CODE_TYPE":{"type":4,"overall":6,"count":6,"over_allocated":0,"histogram":[6,0,0,0],"over_allocated_histogram":[0,0,0,0]},"*CODE_BYTECODE_HANDLER":{"type":7,"overall":5,"count":6,"over_allocated":0,"histogram":[6,0,0,0],"over_allocated_histogram":[0,0,0,0]},"*CODE_AGE_Quadragenarian":{"type":8,"overall":1,"count":1,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]}}}',
+ // eslint-disable-next-line
+ dead:'{"isolate":"0x00000000001","id":2,"time":112,"bucket_sizes":[32,64,128,256],"type_data":{"STRING_TYPE":{"type":1,"overall":1,"count":1,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"FIXED_ARRAY_TYPE":{"type":2,"overall":3,"count":3,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"*FIXED_ARRAY_CONTEXT_SUB_TYPE":{"type":3,"overall":1,"count":1,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]}}}'
+ }
+ })
+ );
+ m.s2 = m.t2.sliceGroup.pushSlice(
+ newSliceEx({
+ title: 'V8.GC_Objects_Stats',
+ start: 2,
+ end: 2,
+ type: tr.e.v8.V8GCStatsThreadSlice,
+ cat: 'disabled-by-default-v8.gc_stats',
+ args: {
+ // eslint-disable-next-line
+ live:'{"isolate":"0x00000000001","id":1,"time":113,"bucket_sizes":[32,64,128,256],"type_data":{"STRING_TYPE":{"type":1,"overall":3,"count":4,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"FIXED_ARRAY_TYPE":{"type":2,"overall":6,"count":7,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"*FIXED_ARRAY_CONTEXT_SUB_TYPE":{"type":3,"overall":2,"count":2,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]}}}',
+ // eslint-disable-next-line
+ dead:'{"isolate":"0x00000000001","id":2,"time":114,"bucket_sizes":[32,64,128,256],"type_data":{"STRING_TYPE":{"type":1,"overall":2,"count":2,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"FIXED_ARRAY_TYPE":{"type":2,"overall":4,"count":4,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]},"*FIXED_ARRAY_CONTEXT_SUB_TYPE":{"type":3,"overall":2,"count":2,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]}}}'
+ }
+ })
+ );
+ m.s3 = m.t2.sliceGroup.pushSlice(
+ newSliceEx({
+ title: 'V8.GC_Objects_Stats',
+ start: 3,
+ end: 3,
+ type: tr.e.v8.V8GCStatsThreadSlice,
+ cat: 'disabled-by-default-v8.gc_stats',
+ args: {
+ // eslint-disable-next-line
+ live:'{"isolate":"0x00000000001","id":1,"time":115,"bucket_sizes":[32,64,128,256],"type_data":{"FIXED_ARRAY_TYPE":{"type":2,"overall":5,"count":6,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]}, "TYPE_DONT_HAVE_GROUP1":{"type":1,"overall":2,"count":3,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]}, "TYPE_DONT_HAVE_GROUP2":{"type":1,"overall":2,"count":3,"over_allocated":0,"histogram":[0,1,0,0],"over_allocated_histogram":[0,0,0,0]}}}',
+ // eslint-disable-next-line
+ dead:'{"isolate":"0x00000000001","id":2,"time":116,"bucket_sizes":[32,64,128,256],"type_data":{"FIXED_ARRAY_TYPE":{"type":2,"overall":5,"count":6,"over_allocated":0,"histogram":[1,0,0,0],"over_allocated_histogram":[0,0,0,0]}}}'
+ }
+ })
+ );
+ });
+ return m;
+ }
+
+ test('GCObjectTableSingleSelection', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement('tr-ui-e-v8-gc-objects-stats-table');
+ const eventSet = new tr.model.EventSet();
+ eventSet.push(m.s1);
+ viewEl.selection = eventSet;
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+ const rows = viewEl.$.table.tableRows;
+ assert.lengthOf(rows, 1);
+ const row = rows[0];
+ assert.strictEqual(row.overall, 0.0263671875);
+ assert.strictEqual(row.count, 21);
+ assert.strictEqual(row.overAllocated, 0);
+ const subRows = row.subRows;
+ const live = subRows[0];
+ assert.strictEqual(live.overall, 0.0224609375);
+ assert.strictEqual(live.count, 17);
+ assert.strictEqual(live.overAllocated, 0);
+ const dead = subRows[1];
+ assert.strictEqual(dead.overall, 0.00390625);
+ assert.strictEqual(dead.count, 4);
+ assert.strictEqual(dead.overAllocated, 0);
+ });
+
+ test('GCObjectTableMultiSelection', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement('tr-ui-e-v8-gc-objects-stats-table');
+ const eventSet = new tr.model.EventSet();
+ eventSet.push(m.s1);
+ eventSet.push(m.s2);
+ viewEl.selection = eventSet;
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+ const rows = viewEl.$.table.tableRows;
+ assert.lengthOf(rows, 2);
+
+ let row = rows[0];
+ assert.strictEqual(row.overall, 0.0146484375);
+ assert.strictEqual(row.count, 17);
+ assert.strictEqual(row.overAllocated, 0);
+ let subRows = row.subRows;
+ let live = subRows[0];
+ assert.strictEqual(live.overall, 0.0087890625);
+ assert.strictEqual(live.count, 11);
+ assert.strictEqual(live.overAllocated, 0);
+ let dead = subRows[1];
+ assert.strictEqual(dead.overall, 0.005859375);
+ assert.strictEqual(dead.count, 6);
+ assert.strictEqual(dead.overAllocated, 0);
+
+ row = rows[1];
+ assert.strictEqual(row.overall, 0.0263671875);
+ assert.strictEqual(row.count, 21);
+ assert.strictEqual(row.overAllocated, 0);
+ subRows = row.subRows;
+ live = subRows[0];
+ assert.strictEqual(live.overall, 0.0224609375);
+ assert.strictEqual(live.count, 17);
+ assert.strictEqual(live.overAllocated, 0);
+ dead = subRows[1];
+ assert.strictEqual(dead.overall, 0.00390625);
+ assert.strictEqual(dead.count, 4);
+ assert.strictEqual(dead.overAllocated, 0);
+ });
+
+ test('GCObjectTableDiff', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement('tr-ui-e-v8-gc-objects-stats-table');
+ const eventSet = new tr.model.EventSet();
+ eventSet.push(m.s1);
+ eventSet.push(m.s2);
+ viewEl.selection = eventSet;
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+ const rows = viewEl.$.table.tableRows;
+ assert.lengthOf(rows, 2);
+ const diffEntry = rows[0].diff(rows[1]);
+
+ assert.strictEqual(diffEntry.origin.overall.toFixed(3), '0.015');
+ assert.strictEqual(diffEntry.origin.overAllocated, 0);
+ assert.strictEqual(diffEntry.overall.toFixed(3), '-0.004');
+ assert.strictEqual(diffEntry.overAllocated, 0);
+ assert.strictEqual(diffEntry.overallPercent.toFixed(3), '-26.667');
+ assert.strictEqual(diffEntry.overAllocatedPercent, 0);
+ });
+
+ test('GCObjectTableGroupEntryWithoutGroupDefined', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement('tr-ui-e-v8-gc-objects-stats-table');
+ const eventSet = new tr.model.EventSet();
+ eventSet.push(m.s3);
+ viewEl.selection = eventSet;
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+ const rows = viewEl.$.table.tableRows;
+ assert.lengthOf(rows, 1);
+ const row = rows[0];
+ assert.strictEqual(row.overall, 0.013671875);
+ assert.strictEqual(row.count, 18);
+ assert.strictEqual(row.overAllocated, 0);
+ const subRows = row.subRows;
+
+ const live = subRows[0];
+ assert.strictEqual(live.overall, 0.0087890625);
+ assert.strictEqual(live.count, 12);
+ assert.strictEqual(live.overAllocated, 0);
+
+ // ungrouped entry should be top level entry.
+ const unGrouped1 = live.getEntryFromTitle('TYPE_DONT_HAVE_GROUP1');
+ assert.isDefined(unGrouped1);
+ assert.strictEqual(unGrouped1.overall, 0.001953125);
+ assert.strictEqual(unGrouped1.count, 3);
+ assert.strictEqual(unGrouped1.overAllocated, 0);
+
+ const unGrouped2 = live.getEntryFromTitle('TYPE_DONT_HAVE_GROUP2');
+ assert.isDefined(unGrouped2);
+ assert.strictEqual(unGrouped2.overall, 0.001953125);
+ assert.strictEqual(unGrouped2.count, 3);
+ assert.strictEqual(unGrouped2.overAllocated, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/ic_stats_table.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/ic_stats_table.html
new file mode 100644
index 00000000000..e19a367cfca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/ic_stats_table.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/v8/ic_stats_entry.html">
+<link rel="import" href="/tracing/extras/v8/v8_ic_stats_thread_slice.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-e-v8-ic-stats-table'>
+ <template>
+ <style>
+ tr-ui-b-table {
+ flex: 0 0 auto;
+ align-self: stretch;
+ margin-top: 1em;
+ font-size: 12px;
+ }
+ #total {
+ margin-top: 1em;
+ margin-left: 0.8em;
+ }
+ #groupOption {
+ display: inline-block;
+ margin-top: 1em;
+ margin-left: 0.8em;
+ }
+ </style>
+ <div style="padding-right: 200px">
+ <div style="float:right; border-style: solid; border-width: 1px; padding:20px">
+ 0 uninitialized<br>
+ . premonomorphic<br>
+ 1 monomorphic<br>
+ ^ recompute handler<br>
+ P polymorphic<br>
+ N megamorphic<br>
+ G generic
+ </div>
+ </div>
+ <div id="total">
+ </div>
+ <div id="groupOption">
+ Group Key
+ </div>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.v8', function() {
+ const PROPERTIES = tr.e.v8.IC_STATS_PROPERTIES.map(
+ x => {return {label: x, value: x};});
+ const ICStatsEntry = tr.e.v8.ICStatsEntry;
+ const ICStatsEntryGroup = tr.e.v8.ICStatsEntryGroup;
+ const ICStatsCollection = tr.e.v8.ICStatsCollection;
+
+ Polymer({
+ is: 'tr-ui-e-v8-ic-stats-table',
+
+ ready() {
+ this.icStatsCollection_ = new ICStatsCollection();
+ this.groupKey_ = PROPERTIES[0].value;
+ this.selector_ = tr.ui.b.createSelector(this, 'groupKey',
+ 'v8ICStatsGroupKey',
+ this.groupKey_, PROPERTIES);
+ Polymer.dom(this.$.groupOption).appendChild(this.selector_);
+ },
+
+ get groupKey() {
+ return this.groupKey_;
+ },
+
+ set groupKey(key) {
+ this.groupKey_ = key;
+ if (this.icStatsCollection_.length === 0) return;
+ this.updateTable_(this.groupKey_);
+ },
+
+ constructTable_(table, groupKey) {
+ table.tableColumns = [
+ {
+ title: '',
+ value: row => {
+ let expanded = false;
+ const buttonEl = tr.ui.b.createButton('details', function() {
+ const previousSibling = Polymer.dom(this).parentNode.parentNode;
+ const parentNode = previousSibling.parentNode;
+ if (expanded) {
+ const trEls = parentNode.getElementsByClassName('subTable');
+ Array.from(trEls).map(x => x.parentNode.removeChild(x));
+ expanded = false;
+ return;
+ }
+ expanded = true;
+ const subGroups = row.createSubGroup();
+ const tr = document.createElement('tr');
+ tr.classList.add('subTable');
+ tr.appendChild(document.createElement('td'));
+ const td = document.createElement('td');
+ td.colSpan = 3;
+ for (const subGroup of subGroups) {
+ const property = subGroup[0];
+ const all = Array.from(subGroup[1].values());
+ const group = all.slice(0, 20);
+ const divEl = document.createElement('div');
+ const spanEl = document.createElement('span');
+ const subTableEl = document.createElement('tr-ui-b-table');
+
+ spanEl.innerText = `Top 20 out of ${all.length}`;
+ spanEl.style.fontWeight = 'bold';
+ spanEl.style.fontSize = '14px';
+ divEl.appendChild(spanEl);
+
+ this.constructTable_(subTableEl, property);
+ subTableEl.tableRows = group;
+ subTableEl.rebuild();
+ divEl.appendChild(subTableEl);
+ td.appendChild(divEl);
+ }
+ tr.appendChild(td);
+ parentNode.insertBefore(tr, previousSibling.nextSibling);
+ });
+ return buttonEl;
+ }
+ },
+ {
+ title: 'Percentage',
+ value(row) {
+ const spanEl = document.createElement('span');
+ spanEl.innerText = (row.percentage * 100).toFixed(3) + '%';
+ return spanEl;
+ },
+ cmp: (a, b) => a.percentage - b.percentage
+ },
+ {
+ title: 'Count',
+ value(row) {
+ const spanEl = document.createElement('span');
+ spanEl.innerText = row.length;
+ return spanEl;
+ },
+ cmp: (a, b) => a.length - b.length
+ },
+ {
+ title: groupKey,
+ value(row) {
+ const spanEl = document.createElement('span');
+ spanEl.innerText = row.key ? row.key : '';
+ return spanEl;
+ }
+ }
+ ];
+
+ table.sortColumnIndex = 1;
+ table.sortDescending = true;
+ },
+
+ updateTable_(groupKey) {
+ this.constructTable_(this.$.table, groupKey);
+ this.$.table.tableRows = this.icStatsCollection_.groupBy(groupKey);
+ this.$.table.rebuild();
+ },
+
+ set selection(slices) {
+ for (const slice of slices) {
+ for (const icStatsObj of slice.icStats) {
+ const entry = new ICStatsEntry(icStatsObj);
+ this.icStatsCollection_.add(entry);
+ }
+ }
+ this.$.total.innerText = 'Total items: ' + this.icStatsCollection_.length;
+ this.updateTable_(this.selector_.selectedValue);
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_gc_stats_thread_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_gc_stats_thread_slice_sub_view.html
new file mode 100644
index 00000000000..eded2c44a66
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_gc_stats_thread_slice_sub_view.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/gc_objects_stats_table.html">
+
+<dom-module id='tr-ui-e-multi-v8-gc-stats-thread-slice-sub-view'>
+ <template>
+ <style>
+ </style>
+ <tr-ui-e-v8-gc-objects-stats-table id="gcObjectsStats">
+ </tr-ui-e-v8-gc-objects-stats-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-e-multi-v8-gc-stats-thread-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.gcObjectsStats.selection = selection;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-e-multi-v8-gc-stats-thread-slice-sub-view',
+ tr.e.v8.V8GCStatsThreadSlice,
+ {
+ multi: true,
+ title: 'V8 GC Stats slices'
+ }
+);
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_ic_stats_thread_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_ic_stats_thread_slice_sub_view.html
new file mode 100644
index 00000000000..36b14cb7be0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_ic_stats_thread_slice_sub_view.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/ic_stats_table.html">
+
+<dom-module id='tr-ui-e-multi-v8-ic-stats-thread-slice-sub-view'>
+ <template>
+ <tr-ui-e-v8-ic-stats-table id="table">
+ </tr-ui-e-v8-ic-stats-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-e-multi-v8-ic-stats-thread-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.table.selection = selection;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-e-multi-v8-ic-stats-thread-slice-sub-view',
+ tr.e.v8.V8ICStatsThreadSlice,
+ {
+ multi: true,
+ title: 'V8 IC stats slices'
+ }
+);
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view.html
new file mode 100644
index 00000000000..48c1f05b274
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/runtime_call_stats_table.html">
+
+<dom-module id='tr-ui-e-multi-v8-thread-slice-sub-view'>
+ <template>
+ <tr-ui-a-multi-thread-slice-sub-view id="content"></tr-ui-a-multi-thread-slice-sub-view>
+ <tr-ui-e-v8-runtime-call-stats-table id="runtimeCallStats"></tr-ui-e-v8-runtime-call-stats-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-e-multi-v8-thread-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.runtimeCallStats.slices = selection;
+ this.$.content.selection = selection;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-e-multi-v8-thread-slice-sub-view',
+ tr.e.v8.V8ThreadSlice,
+ {
+ multi: true,
+ title: 'V8 slices'
+ }
+);
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view_test.html
new file mode 100644
index 00000000000..d0d62bed87d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view_test.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
+<link rel="import" href="/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ function createModel() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+
+ m.s1 = m.t2.sliceGroup.pushSlice(
+ newSliceEx(
+ {title: 'V8.Execute',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {'runtime-call-stats':
+ {
+ CompileFullCode: [3, 345],
+ LoadIC_Miss: [5, 567],
+ ParseLazy: [8, 890]
+ }}}));
+ m.s2 = m.t2.sliceGroup.pushSlice(
+ newSliceEx(
+ {title: 'V8.Execute',
+ start: 11,
+ end: 15,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {'runtime-call-stats':
+ {
+ HandleApiCall: [1, 123],
+ OptimizeCode: [7, 789]
+ }}}));
+ });
+ return m;
+ }
+
+ test('selectMultiV8ThreadSlices', function() {
+ const m = createModel();
+
+ const viewEl =
+ document.createElement('tr-ui-e-multi-v8-thread-slice-sub-view');
+ const selection = new tr.model.EventSet();
+ selection.push(m.s1);
+ selection.push(m.s2);
+ viewEl.selection = selection;
+ this.addHTMLOutput(viewEl);
+ const rows = viewEl.$.runtimeCallStats.$.table.tableRows;
+ assert.lengthOf(rows, 19);
+ assert.deepEqual(rows.map(r => r.time), [
+ 2714,
+ 567,
+ 0,
+ 789,
+ 0,
+ 345,
+ 0,
+ 890,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 123
+ ]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/runtime_call_stats_table.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/runtime_call_stats_table.html
new file mode 100644
index 00000000000..27bf0f5ef72
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/runtime_call_stats_table.html
@@ -0,0 +1,197 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/v8/runtime_stats_entry.html">
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-e-v8-runtime-call-stats-table'>
+ <template>
+ <style>
+ #table, #blink_rcs_table {
+ flex: 0 0 auto;
+ align-self: stretch;
+ margin-top: 1em;
+ font-size: 12px;
+ }
+
+ #v8_rcs_heading, #blink_rcs_heading {
+ padding-top: 1em;
+ font-size: 18px;
+ }
+ </style>
+ <h1 id="v8_rcs_heading"></h1>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ <h1 id="blink_rcs_heading"></h1>
+ <tr-ui-b-table id="blink_rcs_table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.e.v8', function() {
+ const codeSearchURL_ = 'https://cs.chromium.org/search/?sq=package:chromium&type=cs&q=';
+
+ function removeBlinkPrefix_(name) {
+ if (name.startsWith('Blink_')) name = name.substring(6);
+ return name;
+ }
+
+ function handleCodeSearchForV8_(event) {
+ if (event.target.parentNode === undefined) return;
+ let name = event.target.parentNode.entryName;
+ if (name.startsWith('API_')) name = name.substring(4);
+ const url = codeSearchURL_ + encodeURIComponent(name) + '+file:src/v8/src';
+ window.open(url, '_blank');
+ }
+
+ function handleCodeSearchForBlink_(event) {
+ if (event.target.parentNode === undefined) return;
+ const name = event.target.parentNode.entryName;
+ const url = codeSearchURL_ +
+ encodeURIComponent('RuntimeCallStats::CounterId::k' + name) +
+ '+file:src/third_party/WebKit/|src/out/Debug/';
+ window.open(url, '_blank');
+ }
+
+ function createCodeSearchEl_(handleCodeSearch) {
+ const codeSearchEl = document.createElement('span');
+ codeSearchEl.innerText = '?';
+ codeSearchEl.style.float = 'right';
+ codeSearchEl.style.borderRadius = '5px';
+ codeSearchEl.style.backgroundColor = '#EEE';
+ codeSearchEl.addEventListener('click',
+ handleCodeSearch.bind(this));
+ return codeSearchEl;
+ }
+
+ const timeColumn_ = {
+ title: 'Time',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = (row.time / 1000.0).toFixed(3) + ' ms';
+ return typeEl;
+ },
+ width: '100px',
+ cmp(a, b) {
+ return a.time - b.time;
+ }
+ };
+
+ const countColumn_ = {
+ title: 'Count',
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = row.count;
+ return typeEl;
+ },
+ width: '100px',
+ cmp(a, b) {
+ return a.count - b.count;
+ }
+ };
+
+ function percentColumn_(title, totalTime) {
+ return {
+ title,
+ value(row) {
+ const typeEl = document.createElement('span');
+ typeEl.innerText = (row.time / totalTime * 100).toFixed(3) + '%';
+ return typeEl;
+ },
+ width: '100px',
+ cmp(a, b) {
+ return a.time - b.time;
+ }
+ };
+ }
+
+ function nameColumn_(handleCodeSearch, modifyName) {
+ return {
+ title: 'Name',
+ value(row) {
+ const typeEl = document.createElement('span');
+ let name = row.name;
+ if (modifyName) name = modifyName(name);
+ typeEl.innerText = name;
+ if (!(row instanceof tr.e.v8.RuntimeStatsGroup)) {
+ typeEl.title = 'click ? for code search';
+ typeEl.entryName = name;
+ const codeSearchEl = createCodeSearchEl_(handleCodeSearch);
+ typeEl.appendChild(codeSearchEl);
+ }
+ return typeEl;
+ },
+ width: '200px',
+ showExpandButtons: true
+ };
+ }
+
+ function initializeCommonOptions_(table) {
+ table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+ table.sortColumnIndex = 1;
+ table.sortDescending = true;
+ table.subRowsPropertyName = 'values';
+ }
+
+ Polymer({
+ is: 'tr-ui-e-v8-runtime-call-stats-table',
+
+ ready() {
+ this.table_ = this.$.table;
+ this.blink_rcs_table_ = this.$.blink_rcs_table;
+ this.totalTime_ = 0;
+ },
+
+ constructV8RCSTable_(totalTime) {
+ this.table_.tableColumns = [
+ nameColumn_(handleCodeSearchForV8_),
+ timeColumn_,
+ countColumn_,
+ percentColumn_('Percent', totalTime)
+ ];
+
+ initializeCommonOptions_(this.table_);
+ },
+
+ constructBlinkRCSTable_(blinkCppTotalTime) {
+ this.blink_rcs_table_.tableColumns = [
+ nameColumn_(handleCodeSearchForBlink_, removeBlinkPrefix_),
+ timeColumn_,
+ countColumn_,
+ percentColumn_('Percent (of \'Blink C++\' + \'API\')',
+ blinkCppTotalTime)
+ ];
+
+ initializeCommonOptions_(this.blink_rcs_table_);
+ },
+
+ set slices(slices) {
+ const runtimeGroupCollection = new tr.e.v8.RuntimeStatsGroupCollection();
+ runtimeGroupCollection.addSlices(slices);
+ if (runtimeGroupCollection.totalTime > 0) {
+ this.$.v8_rcs_heading.textContent = 'V8 Runtime Call Stats';
+ this.constructV8RCSTable_(runtimeGroupCollection.totalTime);
+ this.table_.tableRows = runtimeGroupCollection.runtimeGroups;
+ this.table_.rebuild();
+ }
+
+ const blinkRCSGroupCollection =
+ runtimeGroupCollection.blinkRCSGroupCollection;
+ if (runtimeGroupCollection.blinkCppTotalTime > 0 &&
+ blinkRCSGroupCollection.totalTime > 0) {
+ this.$.blink_rcs_heading.textContent = 'Blink Runtime Call Stats';
+ this.constructBlinkRCSTable_(runtimeGroupCollection.blinkCppTotalTime);
+ this.blink_rcs_table_.tableRows = blinkRCSGroupCollection.runtimeGroups;
+ this.blink_rcs_table_.rebuild();
+ }
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/runtime_call_stats_table_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/runtime_call_stats_table_test.html
new file mode 100644
index 00000000000..06698d03c4a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/runtime_call_stats_table_test.html
@@ -0,0 +1,236 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
+<link rel="import" href="/tracing/ui/extras/v8/runtime_call_stats_table.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+ const apiObjectGet = [1, 123];
+ const functionCallback = [2, 234];
+ const compileFullCode = [3, 345];
+ const allocateInTargetSpace = [4, 456];
+ const loadIcMiss = [5, 567];
+ const jsExecution = [6, 678];
+ const optimizeCode = [7, 789];
+ const parseLazy = [8, 890];
+ const handleApiCall = [9, 901];
+ const compileBackground = [1, 101];
+ const parseBackground = [2, 202];
+ const optimizeCodeBackground = [3, 303];
+
+ function createModel() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+
+ m.s1 = m.t2.sliceGroup.pushSlice(
+ newSliceEx(
+ {title: 'V8.Execute',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {'runtime-call-stats':
+ {
+ JS_Execution: jsExecution,
+ HandleApiCall: handleApiCall,
+ CompileFullCode: compileFullCode,
+ LoadIC_Miss: loadIcMiss,
+ ParseLazy: parseLazy,
+ RecompileConcurrent: optimizeCode,
+ OptimizeCode: optimizeCode,
+ FunctionCallback: functionCallback,
+ AllocateInTargetSpace: allocateInTargetSpace,
+ API_Object_Get: apiObjectGet,
+ CompileBackgroundIgnition: compileBackground,
+ ParseBackgroundFunctionLiteral: parseBackground,
+ RecompileConcurrent: optimizeCodeBackground
+ }}}));
+ m.s2 = m.t2.sliceGroup.pushSlice(
+ newSliceEx(
+ {title: 'V8.Execute',
+ start: 11,
+ end: 15,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {'runtime-call-stats':
+ {
+ JS_Execution: jsExecution,
+ HandleApiCall: handleApiCall,
+ CompileFullCode: compileFullCode,
+ LoadIC_Miss: loadIcMiss,
+ ParseLazy: parseLazy,
+ OptimizeCode: optimizeCode,
+ FunctionCallback: functionCallback,
+ AllocateInTargetSpace: allocateInTargetSpace,
+ API_Object_Get: apiObjectGet
+ }}}));
+ m.s3 = m.t2.sliceGroup.pushSlice(
+ newSliceEx(
+ {title: 'V8.Execute',
+ start: 11,
+ end: 15,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {'runtime-call-stats':
+ {
+ LoadIC_LoadCallback: [1, 111],
+ StoreIC_StoreCallback: [2, 222],
+ }}}));
+ });
+ return m;
+ }
+
+ test('SingleSliceSelection', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement(
+ 'tr-ui-e-v8-runtime-call-stats-table');
+ viewEl.slices = [m.s1];
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+ const rows = viewEl.$.table.tableRows;
+ assert.lengthOf(rows, 19);
+ assert.deepEqual(rows.map(r => r.time), [
+ 5589,
+ loadIcMiss[1],
+ optimizeCodeBackground[1],
+ optimizeCode[1],
+ compileBackground[1],
+ compileFullCode[1],
+ parseBackground[1],
+ parseLazy[1],
+ functionCallback[1],
+ apiObjectGet[1],
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ allocateInTargetSpace[1],
+ jsExecution[1],
+ handleApiCall[1]
+ ]);
+ });
+
+ test('MultiSliceSelection', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement(
+ 'tr-ui-e-v8-runtime-call-stats-table');
+ viewEl.slices = [m.s1, m.s2];
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+ const rows = viewEl.$.table.tableRows;
+ assert.lengthOf(rows, 19);
+ assert.deepEqual(rows.map(r => r.time), [
+ 10572,
+ loadIcMiss[1] * 2,
+ optimizeCodeBackground[1],
+ optimizeCode[1] * 2,
+ compileBackground[1],
+ compileFullCode[1] * 2,
+ parseBackground[1],
+ parseLazy[1] * 2,
+ functionCallback[1] * 2,
+ apiObjectGet[1] * 2,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ allocateInTargetSpace[1] * 2,
+ jsExecution[1] * 2,
+ handleApiCall[1] * 2
+ ]);
+
+ assert.deepEqual(rows.map(r => r.entries_.size), [
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 1,
+ 1
+ ]);
+ });
+
+ test('groupCorrectly', function() {
+ const m = createModel();
+
+ const viewEl = document.createElement(
+ 'tr-ui-e-v8-runtime-call-stats-table');
+ viewEl.slices = [m.s3];
+ this.addHTMLOutput(viewEl);
+ tr.b.forceAllPendingTasksToRunForTest();
+ const rows = viewEl.$.table.tableRows;
+ assert.lengthOf(rows, 19);
+ assert.deepEqual(rows.map(r => r.time), [
+ 333,
+ 333,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]);
+
+ assert.deepEqual(rows.map(r => r.entries_.size), [
+ 0,
+ 2,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_gc_stats_thread_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_gc_stats_thread_slice_sub_view.html
new file mode 100644
index 00000000000..6a8d5f15b73
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_gc_stats_thread_slice_sub_view.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/gc_objects_stats_table.html">
+
+<dom-module id='tr-ui-e-single-v8-gc-stats-thread-slice-sub-view'>
+ <template>
+ <tr-ui-a-single-event-sub-view id="content"></tr-ui-a-single-event-sub-view>
+ <tr-ui-e-v8-gc-objects-stats-table id="gcObjectsStats"></tr-ui-e-v8-gc-objects-stats-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+Polymer({
+ is: 'tr-ui-e-single-v8-gc-stats-thread-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.content.selection = selection;
+ this.$.gcObjectsStats.selection = selection;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-e-single-v8-gc-stats-thread-slice-sub-view',
+ tr.e.v8.V8GCStatsThreadSlice,
+ {
+ multi: false,
+ title: 'V8 GC stats slice'
+ }
+);
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_ic_stats_thread_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_ic_stats_thread_slice_sub_view.html
new file mode 100644
index 00000000000..eeaf407eab1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_ic_stats_thread_slice_sub_view.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/ic_stats_table.html">
+
+<dom-module id='tr-ui-e-single-v8-ic-stats-thread-slice-sub-view'>
+ <template>
+ <tr-ui-e-v8-ic-stats-table id="table">
+ </tr-ui-e-v8-ic-stats-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+Polymer({
+ is: 'tr-ui-e-single-v8-ic-stats-thread-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.table.selection = selection;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-e-single-v8-ic-stats-thread-slice-sub-view',
+ tr.e.v8.V8ICStatsThreadSlice,
+ {
+ multi: false,
+ title: 'V8 IC stats slice'
+ }
+);
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_thread_slice_sub_view.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_thread_slice_sub_view.html
new file mode 100644
index 00000000000..a9b1189fc76
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_thread_slice_sub_view.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/runtime_call_stats_table.html">
+
+<dom-module id='tr-ui-e-single-v8-thread-slice-sub-view'>
+ <template>
+ <tr-ui-a-single-thread-slice-sub-view id="content"></tr-ui-a-single-thread-slice-sub-view>
+ <tr-ui-e-v8-runtime-call-stats-table id="runtimeCallStats"></tr-ui-e-v8-runtime-call-stats-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+Polymer({
+ is: 'tr-ui-e-single-v8-thread-slice-sub-view',
+ behaviors: [tr.ui.analysis.AnalysisSubView],
+
+ get selection() {
+ return this.$.content.selection;
+ },
+
+ set selection(selection) {
+ this.$.runtimeCallStats.slices = selection;
+ this.$.content.selection = selection;
+ }
+});
+
+tr.ui.analysis.AnalysisSubView.register(
+ 'tr-ui-e-single-v8-thread-slice-sub-view',
+ tr.e.v8.V8ThreadSlice,
+ {
+ multi: false,
+ title: 'V8 slice'
+ }
+);
+
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_thread_slice_sub_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_thread_slice_sub_view_test.html
new file mode 100644
index 00000000000..9e12aa6e044
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8/single_v8_thread_slice_sub_view_test.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/v8/v8_thread_slice.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/extras/v8/single_v8_thread_slice_sub_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ function createModel() {
+ const m = tr.c.TestUtils.newModel(function(m) {
+ m.p1 = m.getOrCreateProcess(1);
+ m.t2 = m.p1.getOrCreateThread(2);
+
+ m.s1 = m.t2.sliceGroup.pushSlice(
+ newSliceEx(
+ {title: 'V8.Execute',
+ start: 0,
+ end: 10,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {'runtime-call-stats':
+ {
+ CompileFullCode: [3, 345],
+ LoadIC_Miss: [5, 567],
+ ParseLazy: [8, 890]
+ }}}));
+ m.s2 = m.t2.sliceGroup.pushSlice(
+ newSliceEx(
+ {title: 'V8.Execute',
+ start: 11,
+ end: 15,
+ type: tr.e.v8.V8ThreadSlice,
+ cat: 'v8',
+ args: {'runtime-call-stats':
+ {
+ HandleApiCall: [1, 123],
+ OptimizeCode: [7, 789]
+ }}}));
+ });
+ return m;
+ }
+
+ test('selectV8ThreadSlice', function() {
+ const m = createModel();
+
+ const viewEl =
+ document.createElement('tr-ui-e-single-v8-thread-slice-sub-view');
+ const selection1 = new tr.model.EventSet();
+ selection1.push(m.s1);
+ viewEl.selection = selection1;
+ this.addHTMLOutput(viewEl);
+ let rows = viewEl.$.runtimeCallStats.$.table.tableRows;
+ assert.lengthOf(rows, 19);
+ assert.deepEqual(rows.map(r => r.time), [
+ 1802,
+ 567,
+ 0,
+ 0,
+ 0,
+ 345,
+ 0,
+ 890,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]);
+
+ const selection2 = new tr.model.EventSet();
+ selection2.push(m.s2);
+ viewEl.selection = selection2;
+ rows = viewEl.$.runtimeCallStats.$.table.tableRows;
+ assert.lengthOf(rows, 19);
+ assert.deepEqual(rows.map(r => r.time), [
+ 912,
+ 0,
+ 0,
+ 789,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 123
+ ]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/extras/v8_config.html b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8_config.html
new file mode 100644
index 00000000000..f78005c2b54
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/extras/v8_config.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+
+<link rel="import" href="/tracing/extras/v8_config.html">
+<link rel="import" href="/tracing/ui/extras/v8/gc_objects_stats_table.html">
+<link rel="import" href="/tracing/ui/extras/v8/multi_v8_gc_stats_thread_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/multi_v8_ic_stats_thread_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/multi_v8_thread_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/runtime_call_stats_table.html">
+<link rel="import" href="/tracing/ui/extras/v8/single_v8_gc_stats_thread_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/single_v8_ic_stats_thread_slice_sub_view.html">
+<link rel="import" href="/tracing/ui/extras/v8/single_v8_thread_slice_sub_view.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/find_control.html b/chromium/third_party/catapult/tracing/tracing/ui/find_control.html
new file mode 100644
index 00000000000..daaa0f59777
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/find_control.html
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/hotkey_controller.html">
+<link rel="import" href="/tracing/ui/find_controller.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+
+<dom-module id='tr-ui-find-control'>
+ <template>
+ <style>
+ :host {
+ -webkit-user-select: none;
+ display: flex;
+ position: relative;
+ }
+ input {
+ -webkit-user-select: auto;
+ background-color: #f8f8f8;
+ border: 1px solid rgba(0, 0, 0, 0.5);
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ width: 170px;
+ }
+ input:focus {
+ background-color: white;
+ }
+ tr-ui-b-toolbar-button {
+ border-left: none;
+ margin: 0;
+ }
+ #hitCount {
+ left: 0;
+ opacity: 0.25;
+ pointer-events: none;
+ position: absolute;
+ text-align: right;
+ top: 2px;
+ width: 167px;
+ z-index: 1;
+ }
+ #spinner {
+ visibility: hidden;
+ width: 8px;
+ height: 8px;
+ left: 154px;
+ pointer-events: none;
+ position: absolute;
+ top: 4px;
+ z-index: 1;
+
+ border: 2px solid transparent;
+ border-bottom: 2px solid rgba(0, 0, 0, 0.5);
+ border-right: 2px solid rgba(0, 0, 0, 0.5);
+ border-radius: 50%;
+ }
+ @keyframes spin { 100% { transform: rotate(360deg); } }
+ </style>
+
+ <input type='text' id='filter'
+ on-input="filterTextChanged"
+ on-keydown="filterKeyDown"
+ on-blur="filterBlur"
+ on-focus="filterFocus"
+ on-mouseup="filterMouseUp" />
+ <div id="spinner"></div>
+ <tr-ui-b-toolbar-button on-click="findPrevious">
+ &larr;
+ </tr-ui-b-toolbar-button>
+ <tr-ui-b-toolbar-button on-click="findNext">
+ &rarr;
+ </tr-ui-b-toolbar-button>
+ <div id="hitCount">0 of 0</div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-find-control',
+
+ filterKeyDown(e) {
+ if (e.keyCode === 27) {
+ const hkc = tr.b.getHotkeyControllerForElement(this);
+ if (hkc) {
+ hkc.childRequestsBlur(this);
+ } else {
+ this.blur();
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ return;
+ } else if (e.keyCode === 13) {
+ if (e.shiftKey) {
+ this.findPrevious();
+ } else {
+ this.findNext();
+ }
+ }
+ },
+
+ filterBlur(e) {
+ this.updateHitCountEl();
+ },
+
+ filterFocus(e) {
+ this.$.filter.select();
+ },
+
+ // Prevent that the input text is deselected after focusing the find
+ // control with the mouse.
+ filterMouseUp(e) {
+ e.preventDefault();
+ },
+
+ get controller() {
+ return this.controller_;
+ },
+
+ set controller(c) {
+ this.controller_ = c;
+ this.updateHitCountEl();
+ },
+
+ focus() {
+ this.$.filter.focus();
+ },
+
+ get hasFocus() {
+ return this === document.activeElement;
+ },
+
+ filterTextChanged() {
+ Polymer.dom(this.$.hitCount).textContent = '';
+ this.$.spinner.style.visibility = 'visible';
+ this.$.spinner.style.animation = 'spin 1s linear infinite';
+ this.controller.startFiltering(this.$.filter.value).then(function() {
+ this.$.spinner.style.visibility = 'hidden';
+ this.$.spinner.style.animation = '';
+ this.updateHitCountEl();
+ }.bind(this));
+ },
+
+ findNext() {
+ if (this.controller) {
+ this.controller.findNext();
+ }
+ this.updateHitCountEl();
+ },
+
+ findPrevious() {
+ if (this.controller) {
+ this.controller.findPrevious();
+ }
+ this.updateHitCountEl();
+ },
+
+ updateHitCountEl() {
+ if (!this.controller || this.$.filter.value.length === 0) {
+ Polymer.dom(this.$.hitCount).textContent = '';
+ return;
+ }
+
+ const n = this.controller.filterHits.length;
+ const i = n === 0 ? -1 : this.controller.currentHitIndex;
+ Polymer.dom(this.$.hitCount).textContent = (i + 1) + ' of ' + n;
+ },
+
+ setText(string) {
+ this.$.filter.value = string;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/find_control_test.html b/chromium/third_party/catapult/tracing/tracing/ui/find_control_test.html
new file mode 100644
index 00000000000..e3af0ec9c6f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/find_control_test.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/find_control.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const ctl = document.createElement('tr-ui-find-control');
+ ctl.controller = {
+ findNext() { },
+ findPrevious() { },
+ reset() {},
+
+ filterHits: ['a', 'b'],
+
+ currentHitIndex: 0
+ };
+
+ this.addHTMLOutput(ctl);
+ });
+
+ test('updateHitCountEl_twoResults', function() {
+ const ctl = document.createElement('tr-ui-find-control');
+ ctl.controller = {
+ findNext() { },
+ findPrevious() { },
+ reset() {},
+
+ filterHits: ['a', 'b'],
+
+ currentHitIndex: 0
+ };
+
+ this.addHTMLOutput(ctl);
+ ctl.$.filter.value = 'test';
+ ctl.updateHitCountEl();
+ assert.strictEqual(ctl.$.hitCount.textContent, '1 of 2');
+ });
+
+ test('updateHitCountEl_emptyFilter', function() {
+ const ctl = document.createElement('tr-ui-find-control');
+ ctl.controller = {
+ findNext() { },
+ findPrevious() { },
+ reset() {},
+
+ filterHits: ['a', 'b'],
+
+ currentHitIndex: 0
+ };
+
+ this.addHTMLOutput(ctl);
+ ctl.$.filter.value = '';
+ ctl.updateHitCountEl();
+ assert.strictEqual(ctl.$.hitCount.textContent, '');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/find_controller.html b/chromium/third_party/catapult/tracing/tracing/ui/find_controller.html
new file mode 100644
index 00000000000..926915b19fb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/find_controller.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/model/event_set.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview FindController.
+ */
+tr.exportTo('tr.ui', function() {
+ const Task = tr.b.Task;
+
+ function FindController(brushingStateController) {
+ this.brushingStateController_ = brushingStateController;
+ this.filterHits_ = [];
+ this.currentHitIndex_ = -1;
+ this.activePromise_ = Promise.resolve();
+ this.activeTask_ = undefined;
+ }
+
+ FindController.prototype = {
+ __proto__: Object.prototype,
+
+ get model() {
+ return this.brushingStateController_.model;
+ },
+
+ get brushingStateController() {
+ return this.brushingStateController_;
+ },
+
+ enqueueOperation_(operation) {
+ let task;
+ if (operation instanceof tr.b.Task) {
+ task = operation;
+ } else {
+ task = new tr.b.Task(operation, this);
+ }
+ if (this.activeTask_) {
+ this.activeTask_ = this.activeTask_.enqueue(task);
+ } else {
+ // We're enqueuing the first task, schedule it.
+ this.activeTask_ = task;
+ this.activePromise_ = Task.RunWhenIdle(this.activeTask_);
+ this.activePromise_.then(function() {
+ this.activePromise_ = undefined;
+ this.activeTask_ = undefined;
+ }.bind(this));
+ }
+ },
+
+ /**
+ * Updates the filter hits based on the provided |filterText|. Returns a
+ * promise which resolves when |filterHits| has been refreshed.
+ */
+ startFiltering(filterText) {
+ const sc = this.brushingStateController_;
+ if (!sc) return;
+
+ // TODO(beaudoin): Cancel anything left in the task queue, without
+ // invalidating the promise.
+ this.enqueueOperation_(function() {
+ this.filterHits_ = [];
+ this.currentHitIndex_ = -1;
+ }.bind(this));
+
+ // Try constructing a UIState from the filterText.
+ // UIState.fromUserFriendlyString will throw an error only if the string
+ // is syntactically correct to a UI state string but with invalid values.
+ // It will return undefined if there is no syntactic match.
+ let stateFromString;
+ try {
+ stateFromString = sc.uiStateFromString(filterText);
+ } catch (e) {
+ this.enqueueOperation_(function() {
+ const overlay = new tr.ui.b.Overlay();
+ Polymer.dom(overlay).textContent = e.message;
+ overlay.title = 'UI State Navigation Error';
+ overlay.visible = true;
+ });
+ return this.activePromise_;
+ }
+
+ if (stateFromString !== undefined) {
+ this.enqueueOperation_(
+ sc.navToPosition.bind(this, stateFromString, true));
+ } else {
+ // filterText is not a navString here -- proceed with find and filter.
+ if (filterText.length === 0) {
+ this.enqueueOperation_(sc.findTextCleared.bind(sc));
+ } else {
+ const filter = new tr.c.FullTextFilter(filterText);
+ const filterHitSet = new tr.model.EventSet();
+ this.enqueueOperation_(sc.addAllEventsMatchingFilterToSelectionAsTask(
+ filter, filterHitSet));
+ this.enqueueOperation_(function() {
+ this.filterHits_ = filterHitSet.toArray();
+ sc.findTextChangedTo(filterHitSet);
+ }.bind(this));
+ }
+ }
+ return this.activePromise_;
+ },
+
+ /**
+ * Returns the most recent filter hits as an array. Call
+ * |startFiltering| to ensure this is up to date after the filter settings
+ * have been changed.
+ */
+ get filterHits() {
+ return this.filterHits_;
+ },
+
+ get currentHitIndex() {
+ return this.currentHitIndex_;
+ },
+
+ find_(dir) {
+ const firstHit = this.currentHitIndex_ === -1;
+ if (firstHit && dir < 0) {
+ this.currentHitIndex_ = 0;
+ }
+
+ const N = this.filterHits.length;
+ this.currentHitIndex_ = (this.currentHitIndex_ + dir + N) % N;
+
+ if (!this.brushingStateController_) return;
+
+ this.brushingStateController_.findFocusChangedTo(
+ new tr.model.EventSet(this.filterHits[this.currentHitIndex]));
+ },
+
+ findNext() {
+ this.find_(1);
+ },
+
+ findPrevious() {
+ this.find_(-1);
+ }
+ };
+
+ return {
+ FindController,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/find_controller_test.html b/chromium/third_party/catapult/tracing/tracing/ui/find_controller_test.html
new file mode 100644
index 00000000000..76f3362899b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/find_controller_test.html
@@ -0,0 +1,366 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/find_controller.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Task = tr.b.Task;
+
+ /*
+ * Just enough of the BrushingStateController to support the tests below.
+ */
+ function FakeBrushingStateController() {
+ this.addAllEventsMatchingFilterToSelectionReturnValue = [];
+
+ this.viewport = undefined;
+ this.model = undefined;
+ this.selection = new tr.model.EventSet();
+ this.findMatches = new tr.model.EventSet();
+ }
+
+ FakeBrushingStateController.prototype = {
+ addAllEventsMatchingFilterToSelectionAsTask(filter, selection) {
+ return new Task(function() {
+ const n = this.addAllEventsMatchingFilterToSelectionReturnValue.length;
+ for (let i = 0; i < n; i++) {
+ selection.push(
+ this.addAllEventsMatchingFilterToSelectionReturnValue[i]);
+ }
+ }, this);
+ },
+
+ uiStateFromString(string) {
+ return undefined;
+ },
+
+ findTextChangedTo(selection) {
+ this.findMatches = selection;
+ this.selection = new tr.model.EventSet();
+ },
+
+ findFocusChangedTo(selection) {
+ this.selection = selection;
+ },
+
+ findTextCleared(selection) {
+ this.selection = new tr.model.EventSet();
+ this.findMatches = new tr.model.EventSet();
+ }
+ };
+
+ test('findControllerNoModel', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.ui.FindController(brushingStateController);
+ controller.findNext();
+ controller.findPrevious();
+ });
+
+ test('findControllerEmptyHit', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.ui.FindController(brushingStateController);
+
+ brushingStateController.selection = new tr.model.EventSet();
+ brushingStateController.findMatches = new tr.model.EventSet();
+ controller.findNext();
+ assert.lengthOf(brushingStateController.selection, 0);
+ assert.lengthOf(brushingStateController.findMatches, 0);
+ controller.findPrevious();
+ assert.lengthOf(brushingStateController.selection, 0);
+ assert.lengthOf(brushingStateController.findMatches, 0);
+ });
+
+ test('findControllerOneHit', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.ui.FindController(brushingStateController);
+
+ const s1 = {guid: 1};
+ brushingStateController.addAllEventsMatchingFilterToSelectionReturnValue = [
+ s1
+ ];
+ return new Promise(function(resolve, reject) {
+ controller.startFiltering('asdf').then(function() {
+ try {
+ assert.lengthOf(brushingStateController.selection, 0);
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.findMatches), s1);
+
+ controller.findNext();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s1);
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.findMatches), s1);
+
+ controller.findNext();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s1);
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.findMatches), s1);
+
+ controller.findPrevious();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s1);
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.findMatches), s1);
+ resolve();
+ } catch (err) {
+ reject(err);
+ }
+ });
+ });
+ });
+
+ test('findControllerMultipleHits', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.ui.FindController(brushingStateController);
+
+ const s1 = {guid: 1};
+ const s2 = {guid: 2};
+ const s3 = {guid: 3};
+
+ brushingStateController.addAllEventsMatchingFilterToSelectionReturnValue = [
+ s1, s2, s3
+ ];
+ return new Promise(function(resolve, reject) {
+ controller.startFiltering('asdf').then(function() {
+ try {
+ // Loop through hits then when we wrap, try moving backward.
+ assert.lengthOf(brushingStateController.selection, 0);
+ assert.lengthOf(brushingStateController.findMatches, 3);
+ let matches = Array.from(brushingStateController.findMatches);
+ assert.strictEqual(matches[0], s1);
+ assert.strictEqual(matches[1], s2);
+ assert.strictEqual(matches[2], s3);
+
+ controller.findNext();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s1);
+
+ controller.findNext();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s2);
+
+ controller.findNext();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s3);
+
+ controller.findNext();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s1);
+
+ controller.findPrevious();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s3);
+
+ controller.findPrevious();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s2);
+ assert.lengthOf(brushingStateController.findMatches, 3);
+ matches = Array.from(brushingStateController.findMatches);
+ assert.strictEqual(matches[0], s1);
+ assert.strictEqual(matches[1], s2);
+ assert.strictEqual(matches[2], s3);
+ resolve();
+ } catch (err) {
+ reject(err);
+ }
+ });
+ });
+ });
+
+ test('findControllerChangeFilterAfterNext', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.ui.FindController(brushingStateController);
+
+ const s1 = {guid: 1};
+ const s2 = {guid: 2};
+ const s3 = {guid: 3};
+ const s4 = {guid: 4};
+
+ brushingStateController.addAllEventsMatchingFilterToSelectionReturnValue = [
+ s1, s2, s3
+ ];
+ return new Promise(function(resolve, reject) {
+ controller.startFiltering('asdf').then(function() {
+ // Loop through hits then when we wrap, try moving backward.
+ controller.findNext();
+ brushingStateController.
+ addAllEventsMatchingFilterToSelectionReturnValue = [s4];
+
+ controller.startFiltering('asdfsf').then(function() {
+ controller.findNext();
+ try {
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s4);
+ resolve();
+ } catch (err) {
+ reject(err);
+ }
+ });
+ });
+ });
+ });
+
+ test('findControllerSelectsAllItemsFirst', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.ui.FindController(brushingStateController);
+
+ const s1 = {guid: 1};
+ const s2 = {guid: 2};
+ const s3 = {guid: 3};
+ brushingStateController.addAllEventsMatchingFilterToSelectionReturnValue = [
+ s1, s2, s3
+ ];
+ return new Promise(function(resolve, reject) {
+ controller.startFiltering('asdfsf').then(function() {
+ try {
+ assert.lengthOf(brushingStateController.selection, 0);
+ assert.lengthOf(brushingStateController.findMatches, 3);
+ let matches = Array.from(brushingStateController.findMatches);
+ assert.strictEqual(matches[0], s1);
+ assert.strictEqual(matches[1], s2);
+ assert.strictEqual(matches[2], s3);
+
+ controller.findNext();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s1);
+
+ controller.findNext();
+ assert.strictEqual(
+ tr.b.getOnlyElement(brushingStateController.selection), s2);
+ assert.lengthOf(brushingStateController.findMatches, 3);
+ matches = Array.from(brushingStateController.findMatches);
+ assert.strictEqual(matches[0], s1);
+ assert.strictEqual(matches[1], s2);
+ assert.strictEqual(matches[2], s3);
+ resolve();
+ } catch (err) {
+ reject(err);
+ }
+ });
+ });
+ });
+
+ test('findControllerWithRealTimeline', function() {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(new tr.model.ThreadSlice(
+ '', 'a', 0, 1, {}, 3));
+ model.t1 = t1;
+ });
+
+ const container = document.createElement('track-view-container');
+ container.id = 'track_view_container';
+
+ const timeline = document.createElement('tr-ui-timeline-view');
+ Polymer.dom(timeline).appendChild(container);
+
+ // This is for testing only, have to make sure things link up right.
+ timeline.trackViewContainer_ = container;
+
+ timeline.model = model;
+
+ const brushingStateController = timeline.brushingStateController;
+ const controller = timeline.findCtl_.controller;
+
+ // Test find with no filterText.
+ controller.findNext();
+
+ // Test find with filter txt.
+ return new Promise(function(resolve, reject) {
+ controller.startFiltering('a').then(function() {
+ try {
+ assert.strictEqual(brushingStateController.selection.length, 0);
+ assert.deepEqual(Array.from(brushingStateController.findMatches),
+ model.t1.sliceGroup.slices);
+
+ controller.findNext();
+ assert.isTrue(brushingStateController.selection.equals(
+ new tr.model.EventSet(model.t1.sliceGroup.slices[0])));
+
+ controller.startFiltering('xxx').then(function() {
+ try {
+ assert.strictEqual(brushingStateController.findMatches.length, 0);
+ assert.strictEqual(brushingStateController.selection.length, 1);
+
+ controller.findNext();
+ assert.strictEqual(brushingStateController.selection.length, 0);
+
+ controller.findNext();
+ assert.strictEqual(brushingStateController.selection.length, 0);
+ resolve();
+ } catch (err) {
+ reject(err);
+ }
+ });
+ } catch (err) {
+ reject(err);
+ }
+ });
+ });
+ });
+
+ test('findControllerNavigation', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.ui.FindController(brushingStateController);
+
+ let navToPositionCallCount = 0;
+ let findTextClearedCallCount = 0;
+ const fakeUIState = {};
+ brushingStateController.uiStateFromString = function(string) {
+ if (string === '') return undefined;
+
+ assert.strictEqual(string, '2000@1.2x7');
+ return fakeUIState;
+ };
+ brushingStateController.navToPosition = function(uiState) {
+ assert.strictEqual(uiState, fakeUIState);
+ navToPositionCallCount++;
+ };
+ brushingStateController.findTextCleared = function() {
+ findTextClearedCallCount++;
+ };
+
+ return new Promise(function(resolve, reject) {
+ controller.startFiltering('2000@1.2x7').then(function() {
+ assert.strictEqual(navToPositionCallCount, 1);
+ }).then(function() {
+ controller.startFiltering('').then(function() {
+ try {
+ assert.strictEqual(findTextClearedCallCount, 1);
+ resolve();
+ } catch (err) {
+ reject(err);
+ }
+ });
+ });
+ });
+ });
+
+ test('findControllerClearAfterSet', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ const controller = new tr.ui.FindController(brushingStateController);
+ let findTextChangedToCalled = false;
+ brushingStateController.findTextChangedTo = function(selection) {
+ findTextChangedToCalled = true;
+ };
+ brushingStateController.findTextCleared = function() {
+ assert.strictEqual(findTextChangedToCalled, true);
+ };
+ controller.startFiltering('1');
+ controller.startFiltering('');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-left.png b/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-left.png
new file mode 100644
index 00000000000..8eef2bf7ecc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-left.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-mid.png b/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-mid.png
new file mode 100644
index 00000000000..c67e697de5f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-mid.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-right.png b/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-right.png
new file mode 100644
index 00000000000..834004a0f74
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/images/chrome-right.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/images/ui-states.png b/chromium/third_party/catapult/tracing/tracing/ui/images/ui-states.png
new file mode 100644
index 00000000000..83d09179817
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/images/ui-states.png
Binary files differ
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/metrics_debugger_app.html b/chromium/third_party/catapult/tracing/tracing/ui/metrics_debugger_app.html
new file mode 100644
index 00000000000..2f21d5156f8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/metrics_debugger_app.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/extras/full_config.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/metrics/all_metrics.html">
+<link rel="import" href="/tracing/metrics/metric_map_function.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/mre/mre_result.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/file.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<dom-module id='tracing-ui-metrics-debugger-app'>
+ <style>
+ pre {
+ overflow: auto;
+ }
+ #bar {
+ display: flex;
+ flex-direction: row;
+ padding: 1px 6px;
+ }
+ </style>
+
+ <template>
+ <top-left-controls id="top_left_controls"></top-left-controls>
+ <input id="load_trace" type="file"/>
+ <button id="run_metric">Run metric</button>
+ <div id="trace_info"></div>
+ <pre id="map_results">
+ </pre>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui', function() {
+ Polymer({
+ is: 'tracing-ui-metrics-debugger-app',
+ created() {
+ this.metrics_ = [];
+ tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(
+ function(m) {
+ this.metrics_.push({
+ label: m.constructor.name,
+ value: m.constructor.name
+ });
+ }, this);
+ this.activeTrace_ = undefined;
+ this.settingsKey_ = undefined;
+ this.currentMetricName_ = undefined;
+ this.settingsKey_ = 'metrics-debugger-app-metric-name';
+ },
+
+ ready() {
+ const metricSelector = tr.ui.b.createSelector(
+ this, 'currentMetricName_',
+ this.settingsKey_,
+ this.metrics_[0].value,
+ this.metrics_);
+ Polymer.dom(this.$.top_left_controls).appendChild(
+ metricSelector);
+
+ this.$.load_trace.addEventListener('change', function(event) {
+ const file = event.target.files[0];
+ this.onTraceFileSelected_(file);
+ }.bind(this));
+ this.$.run_metric.addEventListener(
+ 'click', function(event) {
+ event.stopPropagation();
+ this.onRunMetricClicked_();
+ }.bind(this));
+ },
+
+ onRunMetricClicked_() {
+ if (this.activeTrace_ === undefined) {
+ tr.ui.b.Overlay.showError('You must load a trace first!');
+ return;
+ }
+ const result = new tr.mre.MreResult();
+ const model = this.activeTrace_.model;
+ const options = {metrics: [this.currentMetricName_]};
+ try {
+ tr.metrics.metricMapFunction(result, model, options);
+ this.set(
+ '$.map_results.textContent',
+ 'Metric result:\n' + JSON.stringify(result.asDict(), undefined, 2));
+ } catch (err) {
+ tr.ui.b.Overlay.showError('Error running metric:\n' + err.stack);
+ }
+ },
+
+ onTraceFileSelected_(file) {
+ tr.ui.b.readFile(file).then(
+ function(data) {
+ this.setActiveTrace(file.name, data);
+ }.bind(this),
+ function(err) {
+ tr.ui.b.Overlay.showError('Error while loading file: ' + err);
+ });
+ },
+
+ setActiveTrace(filename, data) {
+ const model = new tr.Model();
+ const importOptions = new tr.importer.ImportOptions();
+ importOptions.pruneEmptyContainers = false;
+ importOptions.showImportWarnings = true;
+ importOptions.trackDetailedModelStats = true;
+
+ const i = new tr.importer.Import(model, importOptions);
+ i.importTracesWithProgressDialog([data]).then(
+ function() {
+ this.activeTrace_ = {
+ filename,
+ model,
+ };
+ Polymer.dom(this.$.trace_info).textContent = 'Trace file ' +
+ filename + ' is loaded.';
+ }.bind(this),
+ function(err) {
+ tr.ui.b.Overlay.showError('Trace import error: ' + err);
+ });
+ },
+ });
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/null_brushing_state_controller.html b/chromium/third_party/catapult/tracing/tracing/ui/null_brushing_state_controller.html
new file mode 100644
index 00000000000..2ab621151db
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/null_brushing_state_controller.html
@@ -0,0 +1,196 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event_target.html">
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/base/ui_state.html">
+<link rel="import" href="/tracing/ui/brushing_state.html">
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui', function() {
+ /*
+ * Some elements such as analysis-links require at least one of their
+ * ancestors to have a BrushingStateController.
+ * Some clients of such elements, such as histogram-set-view, do not have a
+ * timeline-view, which is required by the BrushingStateController.
+ * This class provides the API of BrushingStateController but not the
+ * implementation, unless there is a real BrushingStateController in the
+ * owning element's ancestor chain, in which case the implementation is
+ * delegated to the real BrushingStateController.
+ */
+ class NullBrushingStateController extends tr.c.BrushingStateController {
+ constructor() {
+ super(undefined);
+ this.parentController = undefined;
+ }
+
+ dispatchChangeEvent_() {
+ if (this.parentController) this.parentController.dispatchChangeEvent_();
+ }
+
+ get model() {
+ if (!this.parentController) return undefined;
+ return this.parentController.model;
+ }
+
+ get trackView() {
+ if (!this.parentController) return undefined;
+ return this.parentController.trackView;
+ }
+
+ get viewport() {
+ if (!this.parentController) return undefined;
+ return this.parentController.viewport;
+ }
+
+ get historyEnabled() {
+ if (!this.parentController) return undefined;
+ return this.parentController.historyEnabled;
+ }
+
+ set historyEnabled(historyEnabled) {
+ if (this.parentController) {
+ this.parentController.historyEnabled = historyEnabled;
+ }
+ }
+
+ modelWillChange() {
+ if (this.parentController) this.parentController.modelWillChange();
+ }
+
+ modelDidChange() {
+ if (this.parentController) this.parentController.modelDidChange();
+ }
+
+ onUserInitiatedSelectionChange_() {
+ if (this.parentController) {
+ this.parentController.onUserInitiatedSelectionChange_();
+ }
+ }
+
+ onPopState_(e) {
+ if (this.parentController) this.parentController.onPopState_(e);
+ }
+
+ get selection() {
+ if (!this.parentController) return undefined;
+ return this.parentController.selection;
+ }
+
+ get findMatches() {
+ if (!this.parentController) return undefined;
+ return this.parentController.findMatches;
+ }
+
+ get selectionOfInterest() {
+ if (!this.parentController) return undefined;
+ return this.parentController.selectionOfInterest;
+ }
+
+ get currentBrushingState() {
+ if (!this.parentController) return undefined;
+ return this.parentController.currentBrushingState;
+ }
+
+ set currentBrushingState(newBrushingState) {
+ if (this.parentController) {
+ this.parentController.currentBrushingState = newBrushingState;
+ }
+ }
+
+ addAllEventsMatchingFilterToSelectionAsTask(filter, selection) {
+ if (this.parentController) {
+ this.parentController.addAllEventsMatchingFilterToSelectionAsTask(
+ filter, selection);
+ }
+ }
+
+ findTextChangedTo(allPossibleMatches) {
+ if (this.parentController) {
+ this.parentController.findTextChangedTo(allPossibleMatches);
+ }
+ }
+
+ findFocusChangedTo(currentFocus) {
+ if (this.parentController) {
+ this.parentController.findFocusChangedTo(currentFocus);
+ }
+ }
+
+ findTextCleared() {
+ if (this.parentController) {
+ this.parentController.findTextCleared();
+ }
+ }
+
+ uiStateFromString(string) {
+ if (this.parentController) {
+ this.parentController.uiStateFromString(string);
+ }
+ }
+
+ navToPosition(uiState, showNavLine) {
+ if (this.parentController) {
+ this.parentController.navToPosition(uiState, showNavLine);
+ }
+ }
+
+ changeSelectionFromTimeline(selection) {
+ if (this.parentController) {
+ this.parentController.changeSelectionFromTimeline(selection);
+ }
+ }
+
+ showScriptControlSelection(selection) {
+ if (this.parentController) {
+ this.parentController.showScriptControlSelection(selection);
+ }
+ }
+
+ changeSelectionFromRequestSelectionChangeEvent(selection) {
+ if (this.parentController) {
+ this.parentController.changeSelectionFromRequestSelectionChangeEvent(
+ selection);
+ }
+ }
+
+ changeAnalysisViewRelatedEvents(eventSet) {
+ if (this.parentController && (eventSet instanceof tr.model.EventSet)) {
+ this.parentController.changeAnalysisViewRelatedEvents(eventSet);
+ }
+ }
+
+ changeAnalysisLinkHoveredEvents(eventSet) {
+ if (this.parentController && (eventSet instanceof tr.model.EventSet)) {
+ this.parentController.changeAnalysisLinkHoveredEvents(eventSet);
+ }
+ }
+
+ getViewSpecificBrushingState(viewId) {
+ if (this.parentController) {
+ this.parentController.getViewSpecificBrushingState(viewId);
+ }
+ }
+
+ changeViewSpecificBrushingState(viewId, newState) {
+ if (this.parentController) {
+ this.parentController.changeViewSpecificBrushingState(viewId, newState);
+ }
+ }
+ }
+
+ return {
+ NullBrushingStateController,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/scripting_control.html b/chromium/third_party/catapult/tracing/tracing/ui/scripting_control.html
new file mode 100644
index 00000000000..a91a81e05ec
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/scripting_control.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/extras/tquery/tquery.html">
+
+<dom-module id='tr-ui-scripting-control'>
+ <template>
+ <style>
+ :host {
+ flex: 1 1 auto;
+ }
+ .root {
+ font-family: monospace;
+ cursor: text;
+
+ padding: 2px;
+ margin: 2px;
+ border: 1px solid rgba(0, 0, 0, 0.5);
+ background: white;
+
+ height: 100px;
+ overflow-y: auto;
+
+ transition-property: opacity, height, padding, margin;
+ transition-duration: .2s;
+ transition-timing-function: ease-out;
+ }
+ .hidden {
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ height: 0px;
+ opacity: 0;
+ }
+ .focused {
+ outline: auto 5px -webkit-focus-ring-color;
+ }
+ #history {
+ -webkit-user-select: text;
+ color: #777;
+ }
+ #promptContainer {
+ display: flex;
+ }
+ #promptMark {
+ width: 1em;
+ color: #468;
+ }
+ #prompt {
+ flex: 1;
+ width: 100%;
+ border: none !important;
+ background-color: inherit !important;
+ font: inherit !important;
+ text-overflow: clip !important;
+ text-decoration: none !important;
+ }
+ #prompt:focus {
+ outline: none;
+ }
+ </style>
+
+ <div id="root" class="root hidden" tabindex="0"
+ on-focus="onConsoleFocus">
+ <div id='history'></div>
+ <div id='promptContainer'>
+ <span id='promptMark'>&gt;</span>
+ <input id='prompt' type='text'
+ on-keypress="promptKeyPress"
+ on-keydown="promptKeyDown"
+ on-blur="onConsoleBlur">
+ </div>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-scripting-control',
+
+ isEnterKey_(event) {
+ // Check if in IME.
+ // Remove keyIdentifier after reference build rolls past M51 when
+ // KeyboardEvent.key was added.
+ return event.keyCode !== 229 &&
+ (event.key === 'Enter' || event.keyIdentifier === 'Enter');
+ },
+
+ setFocus_(focused) {
+ const promptEl = this.$.prompt;
+ if (focused) {
+ promptEl.focus();
+ Polymer.dom(this.$.root).classList.add('focused');
+ // Move cursor to the end of any existing text.
+ if (promptEl.value.length > 0) {
+ const sel = window.getSelection();
+ sel.collapse(
+ Polymer.dom(promptEl).firstChild, promptEl.value.length);
+ }
+ } else {
+ promptEl.blur();
+ Polymer.dom(this.$.root).classList.remove('focused');
+ // Workaround for crbug.com/89026 to ensure the prompt doesn't retain
+ // keyboard focus.
+ const parent = promptEl.parentElement;
+ const nextEl = Polymer.dom(promptEl).nextSibling;
+ promptEl.remove();
+ Polymer.dom(parent).insertBefore(promptEl, nextEl);
+ }
+ },
+
+ onConsoleFocus(e) {
+ e.stopPropagation();
+ this.setFocus_(true);
+ },
+
+ onConsoleBlur(e) {
+ e.stopPropagation();
+ this.setFocus_(false);
+ },
+
+ promptKeyDown(e) {
+ e.stopPropagation();
+ if (!this.isEnterKey_(e)) return;
+
+ e.preventDefault();
+ const promptEl = this.$.prompt;
+ const command = promptEl.value;
+ if (command.length === 0) return;
+
+ promptEl.value = '';
+ this.addLine_(String.fromCharCode(187) + ' ' + command);
+
+ let result;
+ try {
+ result = this.controller_.executeCommand(command);
+ } catch (e) {
+ result = e.stack || e.stackTrace;
+ }
+
+ if (result instanceof tr.e.tquery.TQuery) {
+ // TODO(skyostil): Show a cool spinner.
+ result.ready().then(function(selection) {
+ this.addLine_(selection.length + ' matches');
+ this.controller_.brushingStateController.
+ showScriptControlSelection(selection);
+ }.bind(this));
+ } else {
+ this.addLine_(result);
+ }
+ promptEl.scrollIntoView();
+ },
+
+ addLine_(line) {
+ const historyEl = this.$.history;
+ if (historyEl.innerText.length !== 0) {
+ historyEl.innerText += '\n';
+ }
+ historyEl.innerText += line;
+ },
+
+ promptKeyPress(e) {
+ e.stopPropagation();
+ },
+
+ toggleVisibility() {
+ const root = this.$.root;
+ if (!this.visible) {
+ Polymer.dom(root).classList.remove('hidden');
+ this.setFocus_(true);
+ } else {
+ Polymer.dom(root).classList.add('hidden');
+ this.setFocus_(false);
+ }
+ },
+
+ get hasFocus() {
+ return this === document.activeElement;
+ },
+
+ get visible() {
+ const root = this.$.root;
+ return !Polymer.dom(root).classList.contains('hidden');
+ },
+
+ get controller() {
+ return this.controller_;
+ },
+
+ set controller(c) {
+ this.controller_ = c;
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/scripting_control_test.html b/chromium/third_party/catapult/tracing/tracing/ui/scripting_control_test.html
new file mode 100644
index 00000000000..69e8b2b9de7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/scripting_control_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/scripting_control.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const ctl = document.createElement('tr-ui-scripting-control');
+ this.addHTMLOutput(ctl);
+ ctl.toggleVisibility();
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/file_size_stats_side_panel.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/file_size_stats_side_panel.html
new file mode 100644
index 00000000000..b2611f4ac3a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/file_size_stats_side_panel.html
@@ -0,0 +1,221 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/base/grouping_table.html">
+<link rel="import" href="/tracing/ui/base/grouping_table_groupby_picker.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id='tr-ui-sp-file-size-stats-side-panel'>
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ toolbar {
+ align-items: center;
+ background-color: rgb(236, 236, 236);
+ border-bottom: 1px solid #8e8e8e;
+ display: flex;
+ flex-direction: row;
+ flex-direction: row;
+ flex: 0 0 auto;
+ font-size: 12px;
+ padding: 0 10px 0 10px;
+ }
+ table-container {
+ display: flex;
+ min-height: 0px;
+ overflow-y: auto;
+ }
+ </style>
+
+ <toolbar>
+ <span><b>Group by:</b></span>
+ <tr-ui-b-grouping-table-groupby-picker id="picker">
+ </tr-ui-b-grouping-table-groupby-picker>
+ </toolbar>
+ <table-container>
+ <tr-ui-b-grouping-table id="table"></tr-ui-b-grouping-table>
+ </table-container>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+(function() {
+ Polymer({
+ is: 'tr-ui-sp-file-size-stats-side-panel',
+ behaviors: [tr.ui.behaviors.SidePanel],
+
+ ready() {
+ this.model_ = undefined;
+ this.selection_ = new tr.model.EventSet();
+ this.$.picker.settingsKey = 'tr-ui-sp-file-size-stats-side-panel-picker';
+ this.$.picker.possibleGroups = [
+ {
+ key: 'phase', label: 'Event Type',
+ dataFn(eventStat) { return eventStat.phase; }
+ },
+ {
+ key: 'category', label: 'Category',
+ dataFn(eventStat) { return eventStat.category; }
+ },
+ {
+ key: 'title', label: 'Title',
+ dataFn(eventStat) { return eventStat.title; }
+ }
+ ];
+ // If the picker did not restore currentGroupKeys from Settings,
+ // then set default currentGroupKeys.
+ if (this.$.picker.currentGroupKeys.length === 0) {
+ this.$.picker.currentGroupKeys = ['phase', 'title'];
+ }
+ this.$.picker.addEventListener('current-groups-changed',
+ this.updateContents_.bind(this));
+ },
+
+ get textLabel() {
+ return 'File Size Stats';
+ },
+
+ supportsModel(m) {
+ if (!m) {
+ return {
+ supported: false,
+ reason: 'No stats were collected for this file.'
+ };
+ }
+
+ if (m.stats.allTraceEventStats.length === 0) {
+ return {
+ supported: false,
+ reason: 'No stats were collected for this file.'
+ };
+ }
+ return {
+ supported: true
+ };
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ set model(model) {
+ this.model_ = model;
+ this.updateContents_();
+ },
+
+ get rangeOfInterest() {
+ return this.rangeOfInterest_;
+ },
+
+ set rangeOfInterest(rangeOfInterest) {
+ this.rangeOfInterest_ = rangeOfInterest;
+ },
+
+ get selection() {
+ return this.selection_;
+ },
+
+ set selection(selection) {
+ this.selection_ = selection;
+ },
+
+ createColumns_(stats) {
+ const columns = [
+ {
+ title: 'Title',
+ value(row) {
+ const titleEl = document.createElement('span');
+ Polymer.dom(titleEl).textContent = row.title;
+ titleEl.style.textOverflow = 'ellipsis';
+ return titleEl;
+ },
+ cmp(a, b) {
+ return a.title.localeCompare(b.title);
+ },
+ width: '400px'
+ },
+ {
+ title: 'Num Events',
+ align: tr.ui.b.TableFormat.ColumnAlignment.RIGHT,
+ value(row) {
+ return row.rowStats.numEvents;
+ },
+ cmp(a, b) {
+ return a.rowStats.numEvents - b.rowStats.numEvents;
+ },
+ width: '80px'
+ }
+ ];
+
+ if (stats && stats.hasEventSizesinBytes) {
+ columns.push({
+ title: 'Bytes',
+ value(row) {
+ const value = new tr.b.Scalar(tr.b.Unit.byName.sizeInBytes,
+ row.rowStats.totalEventSizeinBytes);
+ const spanEl = tr.v.ui.createScalarSpan(value);
+ return spanEl;
+ },
+ cmp(a, b) {
+ return a.rowStats.totalEventSizeinBytes -
+ b.rowStats.totalEventSizeinBytes;
+ },
+ width: '80px'
+ });
+ }
+ return columns;
+ },
+
+ updateContents_() {
+ const table = this.$.table;
+
+ const columns = this.createColumns_(this.model.stats);
+ table.rowStatsConstructor = function ModelStatsRowStats(row) {
+ const sum = tr.b.math.Statistics.sum(row.data, function(x) {
+ return x.numEvents;
+ });
+ const totalEventSizeinBytes = tr.b.math.Statistics.sum(row.data, x =>
+ x.totalEventSizeinBytes
+ );
+ return {
+ numEvents: sum,
+ totalEventSizeinBytes
+ };
+ };
+ table.tableColumns = columns;
+ table.sortColumnIndex = 1;
+ table.sortDescending = true;
+ table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
+
+ table.groupBy = this.$.picker.currentGroups.map(function(group) {
+ return group.dataFn;
+ });
+
+ if (!this.model) {
+ table.dataToGroup = [];
+ } else {
+ table.dataToGroup = this.model.stats.allTraceEventStats;
+ }
+ this.$.table.rebuild();
+ }
+ });
+
+ tr.ui.side_panel.SidePanelRegistry.register(function() {
+ return document.createElement('tr-ui-sp-file-size-stats-side-panel');
+ });
+})();
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/file_size_stats_side_panel_test.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/file_size_stats_side_panel_test.html
new file mode 100644
index 00000000000..a764387427a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/file_size_stats_side_panel_test.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/side_panel/file_size_stats_side_panel.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TestUtils = tr.c.TestUtils;
+
+ function createModel(opt_customizeModelCallback) {
+ return TestUtils.newModel(function(model) {
+ const modelStats = model.stats;
+ modelStats.willProcessBasicTraceEvent('X', 'cat1', 'title1');
+ modelStats.willProcessBasicTraceEvent('X', 'cat1', 'title1');
+ modelStats.willProcessBasicTraceEvent('X', 'cat2', 'title1');
+ modelStats.willProcessBasicTraceEvent('X', 'cat2', 'title3');
+ modelStats.willProcessBasicTraceEvent('Y', 'cat3', 'title3');
+ });
+ }
+
+ test('instantiate', function() {
+ const panel = document.createElement('tr-ui-sp-file-size-stats-side-panel');
+ panel.model = createModel();
+ panel.style.height = '200px';
+ this.addHTMLOutput(panel);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/metrics_side_panel.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/metrics_side_panel.html
new file mode 100644
index 00000000000..4508a4347a9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/metrics_side_panel.html
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/metrics/metric_map_function.html">
+<link rel="import" href="/tracing/metrics/metric_registry.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/mre/mre_result.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view.html">
+
+<dom-module id="tr-ui-sp-metrics-side-panel">
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ div#error {
+ color: red;
+ }
+ #results {
+ font-size: 12px;
+ }
+ </style>
+
+ <top-left-controls id="top_left_controls"></top-left-controls>
+
+ <tr-v-ui-histogram-set-view id="results"></tr-v-ui-histogram-set-view>
+
+ <div id="error"></div>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.ui', function() {
+ Polymer({
+ is: 'tr-ui-sp-metrics-side-panel',
+ behaviors: [tr.ui.behaviors.SidePanel],
+
+ ready() {
+ this.model_ = undefined;
+
+ this.rangeOfInterest_ = undefined;
+ this.metricLatenciesMs_ = [];
+
+ this.metrics_ = [];
+ tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(
+ function(m) {
+ if (m.constructor.name === 'sampleMetric') return;
+
+ this.metrics_.push({
+ label: m.constructor.name,
+ value: m.constructor.name
+ });
+ }, this);
+
+ this.metrics_.sort((x, y) => x.label.localeCompare(y.label));
+
+ this.settingsKey_ = 'metrics-side-panel-metric-name';
+ this.currentMetricName_ = 'responsivenessMetric';
+ const metricSelector = tr.ui.b.createSelector(
+ this, 'currentMetricName_',
+ this.settingsKey_,
+ this.currentMetricName_,
+ this.metrics_);
+ Polymer.dom(this.$.top_left_controls).appendChild(metricSelector);
+ metricSelector.addEventListener('change',
+ this.onMetricChange_.bind(this));
+ this.currentMetricTypeInfo_ =
+ tr.metrics.MetricRegistry.findTypeInfoWithName(
+ this.currentMetricName_);
+
+ this.recomputeButton_ = tr.ui.b.createButton(
+ 'Recompute', this.onRecompute_, this);
+ Polymer.dom(this.$.top_left_controls).appendChild(this.recomputeButton_);
+
+ this.$.results.addEventListener('display-ready', () => {
+ this.$.results.style.display = '';
+ });
+ },
+
+ async build(model) {
+ this.model_ = model;
+ await this.updateContents_();
+ },
+
+ /**
+ * Return an estimate of how many milliseconds it would take to re-run the
+ * metric. If the metric has not been run, return undefined.
+ *
+ * @return {undefined|number}
+ */
+ get metricLatencyMs() {
+ return tr.b.math.Statistics.mean(this.metricLatenciesMs_);
+ },
+
+ onMetricChange_() {
+ this.currentMetricTypeInfo_ =
+ tr.metrics.MetricRegistry.findTypeInfoWithName(
+ this.currentMetricName_);
+ this.metricLatenciesMs_ = [];
+ this.updateContents_();
+ },
+
+ onRecompute_() {
+ this.updateContents_();
+ },
+
+ get textLabel() {
+ return 'Metrics';
+ },
+
+ supportsModel(m) {
+ if (!m) {
+ return {
+ supported: false,
+ reason: 'No model available'
+ };
+ }
+
+ return {
+ supported: true
+ };
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ set model(model) {
+ this.build(model);
+ },
+
+ get selection() {
+ // Not applicable to metrics.
+ },
+
+ set selection(_) {
+ // Not applicable to metrics.
+ },
+
+ /**
+ * @return {undefined|!tr.b.math.Range}
+ */
+ get rangeOfInterest() {
+ return this.rangeOfInterest_;
+ },
+
+ /**
+ * This may be called rapidly as the mouse is moved.
+ * If the metric supportsRangeOfInterest and takes less than 100ms, then it
+ * will be re-run immediately; otherwise, the Recompute button will be
+ * enabled.
+ *
+ * @param {!tr.b.math.Range} range
+ */
+ set rangeOfInterest(range) {
+ this.rangeOfInterest_ = range;
+
+ if (this.currentMetricTypeInfo_ &&
+ this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest) {
+ if ((this.metricLatencyMs === undefined) ||
+ (this.metricLatencyMs < 100)) {
+ this.updateContents_();
+ } else {
+ this.recomputeButton_.style.background = 'red';
+ }
+ }
+ },
+
+ async updateContents_() {
+ Polymer.dom(this.$.error).textContent = '';
+ this.$.results.style.display = 'none';
+
+ if (!this.model_) {
+ Polymer.dom(this.$.error).textContent = 'Missing model';
+ return;
+ }
+
+ const options = {metrics: [this.currentMetricName_]};
+
+ if (this.currentMetricTypeInfo_ &&
+ this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest &&
+ this.rangeOfInterest &&
+ !this.rangeOfInterest.isEmpty) {
+ options.rangeOfInterest = this.rangeOfInterest;
+ }
+
+ const startDate = new Date();
+ const addFailureCb = failure => {
+ Polymer.dom(this.$.error).textContent = failure.description;
+ };
+ const histograms = tr.metrics.runMetrics(
+ this.model_, options, addFailureCb);
+
+ this.metricLatenciesMs_.push(new Date() - startDate);
+ while (this.metricLatenciesMs_.length > 20) {
+ this.metricLatenciesMs_.shift();
+ }
+
+ this.recomputeButton_.style.background = '';
+
+ await this.$.results.build(histograms);
+ }
+ });
+
+ tr.ui.side_panel.SidePanelRegistry.register(function() {
+ return document.createElement('tr-ui-sp-metrics-side-panel');
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/metrics_side_panel_test.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/metrics_side_panel_test.html
new file mode 100644
index 00000000000..dc90ab54930
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/metrics_side_panel_test.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/ui/side_panel/metrics_side_panel.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function createModel() {
+ const m = tr.c.TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback(m) {
+ const browserProcess = m.getOrCreateProcess(1);
+ const browserMain = browserProcess.getOrCreateThread(2);
+ browserMain.sliceGroup.beginSlice('cat', 'Task', 0);
+ browserMain.sliceGroup.endSlice(10);
+ browserMain.sliceGroup.beginSlice('cat', 'Task', 20);
+ browserMain.sliceGroup.endSlice(30);
+ }
+ });
+ return m;
+ }
+
+ function testMetric(values, model) {
+ const hist = new tr.v.Histogram('test histogram', tr.b.Unit.byName.count);
+ hist.addSample(1);
+ values.addHistogram(hist);
+ }
+
+ tr.metrics.MetricRegistry.register(testMetric);
+
+ test('instantiateCollapsed', async function() {
+ const metricsPanel = document.createElement('tr-ui-sp-metrics-side-panel');
+ this.addHTMLOutput(metricsPanel);
+ metricsPanel.currentMetricName_ = 'testMetric';
+ await metricsPanel.build(createModel());
+
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(
+ metricsPanel, elem => elem.textContent === 'test histogram'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel.html
new file mode 100644
index 00000000000..8b8e2f52b14
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Copyright 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.behaviors', function() {
+ const SidePanel = {
+
+ get rangeOfInterest() {
+ throw new Error('Not implemented');
+ },
+
+ set rangeOfInterest(rangeOfInterest) {
+ throw new Error('Not implemented');
+ },
+
+ get selection() {
+ throw new Error('Not implemented');
+ },
+
+ set selection(selection) {
+ throw new Error('Not implemented');
+ },
+
+ get model() {
+ throw new Error('Not implemented');
+ },
+
+ set model(model) {
+ throw new Error('Not implemented');
+ },
+
+ supportsModel(m) {
+ throw new Error('Not implemented');
+ }
+ };
+
+ return {
+ SidePanel,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_container.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_container.html
new file mode 100644
index 00000000000..95be3103873
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_container.html
@@ -0,0 +1,284 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
+
+<dom-module id='tr-ui-side-panel-container'>
+ <template>
+ <style>
+ :host {
+ align-items: stretch;
+ display: flex;
+ background-color: white;
+ }
+
+ :host([expanded]) > #side_panel_drag_handle,
+ :host([expanded]) > active-panel-container {
+ flex: 1 1 auto;
+ border-left: 1px solid black;
+ display: flex;
+ }
+
+ :host(:not([expanded])) > #side_panel_drag_handle,
+ :host(:not([expanded])) > active-panel-container {
+ display: none;
+ }
+
+ active-panel-container {
+ display: flex;
+ }
+
+ tab-strip {
+ flex: 0 0 auto;
+ flex-direction: column;
+ -webkit-user-select: none;
+ background-color: rgb(236, 236, 236);
+ border-left: 1px solid black;
+ cursor: default;
+ display: flex;
+ min-width: 18px; /* workaround for flexbox and writing-mode mixing bug */
+ padding: 10px 0 10px 0;
+ font-size: 12px;
+ }
+
+ tab-strip > tab-strip-label {
+ flex-shrink: 0;
+ -webkit-writing-mode: vertical-rl;
+ white-space: nowrap;
+ display: inline;
+ margin-right: 1px;
+ min-height: 20px;
+ padding: 15px 3px 15px 1px;
+ }
+
+ tab-strip >
+ tab-strip-label:not([enabled]) {
+ color: rgb(128, 128, 128);
+ }
+
+ tab-strip > tab-strip-label[selected] {
+ background-color: white;
+ border: 1px solid rgb(163, 163, 163);
+ border-left: none;
+ padding: 14px 2px 14px 1px;
+ }
+
+ #active_panel_container {
+ overflow: auto;
+ }
+ </style>
+
+ <tr-ui-b-drag-handle id="side_panel_drag_handle"></tr-ui-b-drag-handle>
+ <active-panel-container id='active_panel_container'>
+ </active-panel-container>
+ <tab-strip id='tab_strip'></tab-strip>
+ </template>
+</dom-module>
+<script>
+'use strict';
+Polymer({
+ is: 'tr-ui-side-panel-container',
+
+ ready() {
+ this.activePanelContainer_ = this.$.active_panel_container;
+ this.tabStrip_ = this.$.tab_strip;
+
+ this.dragHandle_ = this.$.side_panel_drag_handle;
+ this.dragHandle_.horizontal = false;
+ this.dragHandle_.target = this.activePanelContainer_;
+ this.rangeOfInterest_ = new tr.b.math.Range();
+ this.brushingStateController_ = undefined;
+ this.onSelectionChanged_ = this.onSelectionChanged_.bind(this);
+ this.onModelChanged_ = this.onModelChanged_.bind(this);
+ },
+
+ get brushingStateController() {
+ return this.brushingStateController_;
+ },
+
+ set brushingStateController(brushingStateController) {
+ if (this.brushingStateController) {
+ this.brushingStateController_.removeEventListener(
+ 'change', this.onSelectionChanged_);
+ this.brushingStateController_.removeEventListener(
+ 'model-changed', this.onModelChanged_);
+ }
+ this.brushingStateController_ = brushingStateController;
+ if (this.brushingStateController) {
+ this.brushingStateController_.addEventListener(
+ 'change', this.onSelectionChanged_);
+ this.brushingStateController_.addEventListener(
+ 'model-changed', this.onModelChanged_);
+ if (this.model) {
+ this.onModelChanged_();
+ }
+ }
+ },
+
+ onSelectionChanged_() {
+ if (this.activePanel) {
+ this.activePanel.selection = this.selection;
+ }
+ },
+
+ get model() {
+ return this.brushingStateController_.model;
+ },
+
+ onModelChanged_() {
+ this.activePanelType_ = undefined;
+ this.updateContents_();
+ },
+
+ get expanded() {
+ this.hasAttribute('expanded');
+ },
+
+ get activePanel() {
+ return this.activePanelContainer_.children[0];
+ },
+
+ get activePanelType() {
+ return this.activePanelType_;
+ },
+
+ set activePanelType(panelType) {
+ if (this.model === undefined) {
+ throw new Error('Cannot activate panel without a model');
+ }
+
+ let panel = undefined;
+ if (panelType) {
+ panel = document.createElement(panelType);
+ }
+
+ if (panel !== undefined && !panel.supportsModel(this.model)) {
+ throw new Error('Cannot activate panel: does not support this model');
+ }
+
+ if (this.activePanelType) {
+ Polymer.dom(this.getLabelElementForPanelType_(
+ this.activePanelType)).removeAttribute('selected');
+ }
+
+ if (this.activePanelType) {
+ this.getLabelElementForPanelType_(
+ this.activePanelType).removeAttribute('selected');
+ }
+
+ if (this.activePanel) {
+ this.activePanelContainer_.removeChild(this.activePanel);
+ }
+
+ if (panelType === undefined) {
+ Polymer.dom(this).removeAttribute('expanded');
+ this.activePanelType_ = undefined;
+ return;
+ }
+
+ Polymer.dom(this.getLabelElementForPanelType_(panelType)).
+ setAttribute('selected', true);
+ Polymer.dom(this).setAttribute('expanded', true);
+
+ Polymer.dom(this.activePanelContainer_).appendChild(panel);
+ panel.rangeOfInterest = this.rangeOfInterest_;
+ panel.selection = this.selection_;
+ panel.model = this.model;
+
+ this.activePanelType_ = panelType;
+ },
+
+ getPanelTypeForConstructor_(constructor) {
+ for (let i = 0; i < this.tabStrip_.children.length; i++) {
+ if (this.tabStrip_.children[i].panelType.constructor === constructor) {
+ return this.tabStrip_.children[i].panelType;
+ }
+ }
+ },
+
+ getLabelElementForPanelType_(panelType) {
+ for (let i = 0; i < this.tabStrip_.children.length; i++) {
+ if (this.tabStrip_.children[i].panelType === panelType) {
+ return this.tabStrip_.children[i];
+ }
+ }
+ return undefined;
+ },
+
+ updateContents_() {
+ const previouslyActivePanelType = this.activePanelType;
+
+ Polymer.dom(this.tabStrip_).textContent = '';
+ const supportedPanelTypes = [];
+ const panelTypeInfos =
+ tr.ui.side_panel.SidePanelRegistry.getAllRegisteredTypeInfos();
+ const unsupportedLabelEls = [];
+
+ for (const panelTypeInfo of panelTypeInfos) {
+ const labelEl = document.createElement('tab-strip-label');
+ const panel = panelTypeInfo.constructor();
+ const panelType = panel.tagName;
+
+ Polymer.dom(labelEl).textContent = panel.textLabel;
+ labelEl.panelType = panelType;
+
+ const supported = panel.supportsModel(this.model);
+ if (this.model && supported.supported) {
+ supportedPanelTypes.push(panelType);
+ Polymer.dom(labelEl).setAttribute('enabled', true);
+ labelEl.addEventListener('click', function(panelType) {
+ this.activePanelType =
+ this.activePanelType === panelType ? undefined : panelType;
+ }.bind(this, panelType));
+ Polymer.dom(this.tabStrip_).appendChild(labelEl);
+ } else {
+ if (this.activePanel) {
+ this.activePanelContainer_.removeChild(this.activePanel);
+ }
+ this.removeAttribute('expanded');
+ unsupportedLabelEls.push(labelEl);
+ }
+ }
+
+ // Labels do not shrink, so when the user drags the analysis-view up, the
+ // bottom labels are obscured first.
+ // Append all unsupported panel labels after all supported panel labels so
+ // that unsupported panel labels are obscured first.
+ for (const labelEl of unsupportedLabelEls) {
+ Polymer.dom(this.tabStrip_).appendChild(labelEl);
+ }
+
+ // Restore the active panel, or collapse
+ if (previouslyActivePanelType &&
+ supportedPanelTypes.includes(previouslyActivePanelType)) {
+ this.activePanelType = previouslyActivePanelType;
+ Polymer.dom(this).setAttribute('expanded', true);
+ } else {
+ if (this.activePanel) {
+ Polymer.dom(this.activePanelContainer_).removeChild(this.activePanel);
+ }
+ Polymer.dom(this).removeAttribute('expanded');
+ }
+ },
+
+ get rangeOfInterest() {
+ return this.rangeOfInterest_;
+ },
+
+ set rangeOfInterest(range) {
+ if (range === undefined) {
+ throw new Error('Must not be undefined');
+ }
+ this.rangeOfInterest_ = range;
+ if (this.activePanel) {
+ this.activePanel.rangeOfInterest = range;
+ }
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_container_test.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_container_test.html
new file mode 100644
index 00000000000..a51be620426
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_container_test.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_container.html">
+
+<dom-module id="tr-ui-sp-disabled-side-panel"></dom-module>
+<dom-module id="tr-ui-sp-enabled-side-panel"></dom-module>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function FakeBrushingStateController() {
+ this.addAllEventsMatchingFilterToSelectionReturnValue = [];
+
+ this.viewport = undefined;
+ this.model = undefined;
+ this.selection = new tr.model.EventSet();
+ this.highlight = new tr.model.EventSet();
+ }
+
+ FakeBrushingStateController.prototype = {
+ addEventListener(name, cb) {
+ }
+ };
+
+ function createModel() {
+ const m = tr.c.TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback(m) {
+ const browserProcess = m.getOrCreateProcess(1);
+ const browserMain = browserProcess.getOrCreateThread(2);
+ browserMain.sliceGroup.beginSlice('cat', 'Task', 0);
+ browserMain.sliceGroup.endSlice(10);
+ browserMain.sliceGroup.beginSlice('cat', 'Task', 20);
+ browserMain.sliceGroup.endSlice(30);
+ }
+ });
+ return m;
+ }
+
+ Polymer({
+ is: 'tr-ui-sp-disabled-test-panel',
+ behaviors: [tr.ui.behaviors.SidePanel],
+ supportsModel(m) {
+ return {supported: false};
+ },
+ get textLabel() {
+ return 'Disabled';
+ }
+ });
+
+ tr.ui.side_panel.SidePanelRegistry.register(function disabled() {
+ return document.createElement('tr-ui-sp-disabled-test-panel');
+ });
+
+ Polymer({
+ is: 'tr-ui-sp-enabled-test-panel',
+ behaviors: [tr.ui.behaviors.SidePanel],
+ supportsModel(m) {
+ return {supported: true};
+ },
+ get textLabel() {
+ return 'Enabled';
+ },
+ });
+
+ tr.ui.side_panel.SidePanelRegistry.register(function enabled() {
+ return document.createElement('tr-ui-sp-enabled-test-panel');
+ });
+
+ test('instantiateCollapsed', function() {
+ const brushingStateController = new FakeBrushingStateController();
+ brushingStateController.model = createModel();
+
+ const container = document.createElement('tr-ui-side-panel-container');
+ container.brushingStateController = brushingStateController;
+ this.addHTMLOutput(container);
+
+ // The Enabled tab should appear first in the tab strip even though the
+ // disabled side panel was registered first.
+ // There may be other side panels.
+ const labels = tr.ui.b.findDeepElementsMatching(container,
+ 'TAB-STRIP-LABEL').map(e => e.textContent);
+ assert.isBelow(labels.indexOf('Enabled'), labels.indexOf('Disabled'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_registry.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_registry.html
new file mode 100644
index 00000000000..0ec139f2225
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_registry.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+
+<script>
+'use strict';
+
+// TODO(charliea): This can probably be cleaned up so that we don't have to
+// manually wrap the Polymer element names with a function and
+// `document.createElement` at each of the registration sites by creating a
+// new "Polymer" registration mode.
+tr.exportTo('tr.ui.side_panel', function() {
+ /**
+ * SidePanelRegistry is an entity for side panel Polymer elements to register
+ * on so that they'll render a side panel if the model has the correct data.
+ *
+ * Example usage:
+ *
+ * SidePanelRegistry.register(function() {
+ * return document.createElement('my-side-panel');
+ * });
+ *
+ * @constructor
+ */
+ function SidePanelRegistry() {}
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ tr.b.decorateExtensionRegistry(SidePanelRegistry, options);
+
+ return {
+ SidePanelRegistry,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_registry_test.html b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_registry_test.html
new file mode 100644
index 00000000000..c174d5eb005
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/side_panel/side_panel_registry_test.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const SidePanelRegistry = tr.ui.side_panel.SidePanelRegistry;
+
+ const testOptions = {
+ setUp() {
+ SidePanelRegistry.pushCleanStateBeforeTest();
+ },
+
+ tearDown() {
+ SidePanelRegistry.popCleanStateAfterTest();
+ },
+ };
+
+ test('register', function() {
+ SidePanelRegistry.register(function() {
+ return document.createElement('div');
+ });
+ SidePanelRegistry.register(function() {
+ return document.createElement('span');
+ });
+
+ const typeInfos = SidePanelRegistry.getAllRegisteredTypeInfos();
+ assert.strictEqual(typeInfos[0].constructor().tagName, 'DIV');
+ assert.strictEqual(typeInfos[1].constructor().tagName, 'SPAN');
+ assert.lengthOf(typeInfos, 2);
+ }, testOptions);
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform.html
new file mode 100644
index 00000000000..2aefa6d6de4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui', function() {
+ function TimelineDisplayTransform(opt_that) {
+ if (opt_that) {
+ this.set(opt_that);
+ return;
+ }
+ this.scaleX = 1;
+ this.panX = 0;
+ this.panY = 0;
+ }
+
+ TimelineDisplayTransform.prototype = {
+ set(that) {
+ this.scaleX = that.scaleX;
+ this.panX = that.panX;
+ this.panY = that.panY;
+ },
+
+ clone() {
+ return new TimelineDisplayTransform(this);
+ },
+
+ equals(that) {
+ let eq = true;
+ if (that === undefined || that === null) {
+ return false;
+ }
+ eq &= this.panX === that.panX;
+ eq &= this.panY === that.panY;
+ eq &= this.scaleX === that.scaleX;
+ return !!eq;
+ },
+
+ almostEquals(that) {
+ let eq = true;
+ if (that === undefined || that === null) {
+ return false;
+ }
+ eq &= Math.abs(this.panX - that.panX) < 0.001;
+ eq &= Math.abs(this.panY - that.panY) < 0.001;
+ eq &= Math.abs(this.scaleX - that.scaleX) < 0.001;
+ return !!eq;
+ },
+
+ incrementPanXInViewUnits(xDeltaView) {
+ this.panX += this.xViewVectorToWorld(xDeltaView);
+ },
+
+ xPanWorldPosToViewPos(worldX, viewX, viewWidth) {
+ if (typeof viewX === 'string') {
+ if (viewX === 'left') {
+ viewX = 0;
+ } else if (viewX === 'center') {
+ viewX = viewWidth / 2;
+ } else if (viewX === 'right') {
+ viewX = viewWidth - 1;
+ } else {
+ throw new Error('viewX must be left|center|right or number.');
+ }
+ }
+ this.panX = (viewX / this.scaleX) - worldX;
+ },
+
+ xPanWorldBoundsIntoView(worldMin, worldMax, viewWidth) {
+ if (this.xWorldToView(worldMin) < 0) {
+ this.xPanWorldPosToViewPos(worldMin, 'left', viewWidth);
+ } else if (this.xWorldToView(worldMax) > viewWidth) {
+ this.xPanWorldPosToViewPos(worldMax, 'right', viewWidth);
+ }
+ },
+
+ xSetWorldBounds(worldMin, worldMax, viewWidth) {
+ const worldWidth = worldMax - worldMin;
+ const scaleX = viewWidth / worldWidth;
+ const panX = -worldMin;
+ this.setPanAndScale(panX, scaleX);
+ },
+
+ setPanAndScale(p, s) {
+ this.scaleX = s;
+ this.panX = p;
+ },
+
+ xWorldToView(x) {
+ return (x + this.panX) * this.scaleX;
+ },
+
+ xWorldVectorToView(x) {
+ return x * this.scaleX;
+ },
+
+ xViewToWorld(x) {
+ return (x / this.scaleX) - this.panX;
+ },
+
+ xViewVectorToWorld(x) {
+ return x / this.scaleX;
+ }
+ };
+
+ return {
+ TimelineDisplayTransform,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_animations.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_animations.html
new file mode 100644
index 00000000000..a632a6dc4fd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_animations.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/animation.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui', function() {
+ const kDefaultPanAnimationDurationMs = 100.0;
+ const lerp = tr.b.math.lerp;
+
+ /**
+ * Pans a TimelineDisplayTransform by a given amount.
+ * @constructor
+ * @extends {tr.ui.b.Animation}
+ * @param {Number} deltaX The total amount of change to the transform's panX.
+ * @param {Number} deltaY The total amount of change to the transform's panY.
+ * @param {Number=} opt_durationMs How long the pan animation should run.
+ * Defaults to kDefaultPanAnimationDurationMs.
+ */
+ function TimelineDisplayTransformPanAnimation(
+ deltaX, deltaY, opt_durationMs) {
+ this.deltaX = deltaX;
+ this.deltaY = deltaY;
+ if (opt_durationMs === undefined) {
+ this.durationMs = kDefaultPanAnimationDurationMs;
+ } else {
+ this.durationMs = opt_durationMs;
+ }
+
+ this.startPanX = undefined;
+ this.startPanY = undefined;
+ this.startTimeMs = undefined;
+ }
+
+ TimelineDisplayTransformPanAnimation.prototype = {
+ __proto__: tr.ui.b.Animation.prototype,
+
+ get affectsPanY() {
+ return this.deltaY !== 0;
+ },
+
+ canTakeOverFor(existingAnimation) {
+ return existingAnimation instanceof TimelineDisplayTransformPanAnimation;
+ },
+
+ takeOverFor(existing, timestamp, target) {
+ const remainingDeltaXOnExisting = existing.goalPanX - target.panX;
+ const remainingDeltaYOnExisting = existing.goalPanY - target.panY;
+ let remainingTimeOnExisting = timestamp - (
+ existing.startTimeMs + existing.durationMs);
+ remainingTimeOnExisting = Math.max(remainingTimeOnExisting, 0);
+
+ this.deltaX += remainingDeltaXOnExisting;
+ this.deltaY += remainingDeltaYOnExisting;
+ this.durationMs += remainingTimeOnExisting;
+ },
+
+ start(timestamp, target) {
+ this.startTimeMs = timestamp;
+ this.startPanX = target.panX;
+ this.startPanY = target.panY;
+ },
+
+ tick(timestamp, target) {
+ let percentDone = (timestamp - this.startTimeMs) / this.durationMs;
+ percentDone = tr.b.math.clamp(percentDone, 0, 1);
+
+ target.panX = lerp(percentDone, this.startPanX, this.goalPanX);
+ if (this.affectsPanY) {
+ target.panY = lerp(percentDone, this.startPanY, this.goalPanY);
+ }
+ return timestamp >= this.startTimeMs + this.durationMs;
+ },
+
+ get goalPanX() {
+ return this.startPanX + this.deltaX;
+ },
+
+ get goalPanY() {
+ return this.startPanY + this.deltaY;
+ }
+ };
+
+ /**
+ * Zooms in/out on a specified location in the world.
+ *
+ * Zooming in and out is all about keeping the area under the mouse cursor,
+ * here called the "focal point" in the same place under the zoom. If one
+ * simply changes the scale, the area under the mouse cursor will change. To
+ * keep the focal point from moving during the zoom, the pan needs to change
+ * in order to compensate. Thus, a ZoomTo animation is given both a focal
+ * point in addition to the amount by which to zoom.
+ *
+ * @constructor
+ * @extends {tr.ui.b.Animation}
+ * @param {Number} goalFocalPointXWorld The X coordinate in the world which is
+ * of interest.
+ * @param {Number} goalFocalPointXView Where on the screen the
+ * goalFocalPointXWorld should stay centered during the zoom.
+ * @param {Number} goalFocalPointY Where the panY should be when the zoom
+ * completes.
+ * @param {Number} zoomInRatioX The ratio of the current scaleX to the goal
+ * scaleX.
+ */
+ function TimelineDisplayTransformZoomToAnimation(
+ goalFocalPointXWorld,
+ goalFocalPointXView,
+ goalFocalPointY,
+ zoomInRatioX,
+ opt_durationMs) {
+ this.goalFocalPointXWorld = goalFocalPointXWorld;
+ this.goalFocalPointXView = goalFocalPointXView;
+ this.goalFocalPointY = goalFocalPointY;
+ this.zoomInRatioX = zoomInRatioX;
+ if (opt_durationMs === undefined) {
+ this.durationMs = kDefaultPanAnimationDurationMs;
+ } else {
+ this.durationMs = opt_durationMs;
+ }
+
+ this.startTimeMs = undefined;
+ this.startScaleX = undefined;
+ this.goalScaleX = undefined;
+ this.startPanY = undefined;
+ }
+
+ TimelineDisplayTransformZoomToAnimation.prototype = {
+ __proto__: tr.ui.b.Animation.prototype,
+
+ get affectsPanY() {
+ return this.startPanY !== this.goalFocalPointY;
+ },
+
+ canTakeOverFor(existingAnimation) {
+ return false;
+ },
+
+ takeOverFor(existingAnimation, timestamp, target) {
+ this.goalScaleX = target.scaleX * this.zoomInRatioX;
+ },
+
+ start(timestamp, target) {
+ this.startTimeMs = timestamp;
+ this.startScaleX = target.scaleX;
+ this.goalScaleX = this.zoomInRatioX * target.scaleX;
+ this.startPanY = target.panY;
+ },
+
+ tick(timestamp, target) {
+ let percentDone = (timestamp - this.startTimeMs) / this.durationMs;
+ percentDone = tr.b.math.clamp(percentDone, 0, 1);
+
+ target.scaleX = lerp(percentDone, this.startScaleX, this.goalScaleX);
+ if (this.affectsPanY) {
+ target.panY = lerp(percentDone, this.startPanY, this.goalFocalPointY);
+ }
+
+ target.xPanWorldPosToViewPos(
+ this.goalFocalPointXWorld, this.goalFocalPointXView);
+ return timestamp >= this.startTimeMs + this.durationMs;
+ }
+ };
+
+ return {
+ TimelineDisplayTransformPanAnimation,
+ TimelineDisplayTransformZoomToAnimation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_animations_test.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_animations_test.html
new file mode 100644
index 00000000000..215a8863885
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_animations_test.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/animation_controller.html">
+<link rel="import" href="/tracing/ui/timeline_display_transform.html">
+<link rel="import" href="/tracing/ui/timeline_display_transform_animations.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TimelineDisplayTransform = tr.ui.TimelineDisplayTransform;
+ const TimelineDisplayTransformPanAnimation =
+ tr.ui.TimelineDisplayTransformPanAnimation;
+ const TimelineDisplayTransformZoomToAnimation =
+ tr.ui.TimelineDisplayTransformZoomToAnimation;
+
+ test('panBasic', function() {
+ const target = new TimelineDisplayTransform();
+ target.cloneAnimationState = function() {
+ return this.clone();
+ };
+
+ const a = new TimelineDisplayTransformPanAnimation(10, 20, 100);
+
+ const controller = new tr.ui.b.AnimationController();
+ controller.target = target;
+ controller.queueAnimation(a, 0);
+
+ assert.isTrue(a.affectsPanY);
+ tr.b.forcePendingRAFTasksToRun(50);
+ assert.isAbove(target.panX, 0);
+ tr.b.forcePendingRAFTasksToRun(100);
+ assert.isFalse(controller.hasActiveAnimation);
+ assert.strictEqual(target.panX, 10);
+ assert.strictEqual(target.panY, 20);
+ });
+
+ test('zoomBasic', function() {
+ const target = new TimelineDisplayTransform();
+ target.panY = 30;
+ target.cloneAnimationState = function() {
+ return this.clone();
+ };
+
+ const a = new TimelineDisplayTransformZoomToAnimation(10, 20, 30, 5, 100);
+
+ const controller = new tr.ui.b.AnimationController();
+ controller.target = target;
+ controller.queueAnimation(a, 0);
+
+ assert.isFalse(a.affectsPanY);
+ tr.b.forcePendingRAFTasksToRun(100);
+ assert.strictEqual(target.scaleX, 5);
+ });
+
+ test('panTakeover', function() {
+ const target = new TimelineDisplayTransform();
+ target.cloneAnimationState = function() {
+ return this.clone();
+ };
+
+ const b = new TimelineDisplayTransformPanAnimation(10, 0, 100);
+ const a = new TimelineDisplayTransformPanAnimation(10, 0, 100);
+
+ const controller = new tr.ui.b.AnimationController();
+ controller.target = target;
+ controller.queueAnimation(a, 0);
+
+ tr.b.forcePendingRAFTasksToRun(50);
+ controller.queueAnimation(b, 50);
+
+ tr.b.forcePendingRAFTasksToRun(100);
+ assert.isTrue(controller.hasActiveAnimation);
+
+ tr.b.forcePendingRAFTasksToRun(150);
+ assert.isFalse(controller.hasActiveAnimation);
+ assert.strictEqual(target.panX, 20);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_test.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_test.html
new file mode 100644
index 00000000000..d0df289c34e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_display_transform_test.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/timeline_display_transform.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TimelineDisplayTransform = tr.ui.TimelineDisplayTransform;
+
+ test('basics', function() {
+ const a = new TimelineDisplayTransform();
+ a.panX = 0;
+ a.panY = 0;
+ a.scaleX = 1;
+
+ const b = new TimelineDisplayTransform();
+ b.panX = 10;
+ b.panY = 0;
+ b.scaleX = 1;
+
+ assert.isFalse(a.equals(b));
+ assert.isFalse(a.almostEquals(b));
+
+ const c = b.clone();
+ assert.isTrue(b.equals(c));
+ assert.isTrue(b.almostEquals(c));
+
+ c.set(a);
+ assert.isTrue(a.equals(c));
+ assert.isTrue(a.almostEquals(c));
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_interest_range.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_interest_range.html
new file mode 100644
index 00000000000..36126f898db
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_interest_range.html
@@ -0,0 +1,249 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui', function() {
+ /**
+ * @constructor
+ */
+ function SnapIndicator(y, height) {
+ this.y = y;
+ this.height = height;
+ }
+
+ /**
+ * The interesting part of the world.
+ *
+ * @constructor
+ */
+ function TimelineInterestRange(vp) {
+ this.viewport_ = vp;
+
+ this.range_ = new tr.b.math.Range();
+
+ this.leftSelected_ = false;
+ this.rightSelected_ = false;
+
+ this.leftSnapIndicator_ = undefined;
+ this.rightSnapIndicator_ = undefined;
+ }
+
+ TimelineInterestRange.prototype = {
+ get isEmpty() {
+ return this.range_.isEmpty;
+ },
+
+ reset() {
+ this.range_.reset();
+ this.leftSelected_ = false;
+ this.rightSelected_ = false;
+ this.leftSnapIndicator_ = undefined;
+ this.rightSnapIndicator_ = undefined;
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ get min() {
+ return this.range_.min;
+ },
+
+ set min(min) {
+ this.range_.min = min;
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ get max() {
+ return this.range_.max;
+ },
+
+ set max(max) {
+ this.range_.max = max;
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ set(range) {
+ this.range_.reset();
+ this.range_.addRange(range);
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ setMinAndMax(min, max) {
+ this.range_.min = min;
+ this.range_.max = max;
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ get range() {
+ return this.range_.range;
+ },
+
+ asRangeObject() {
+ const range = new tr.b.math.Range();
+ range.addRange(this.range_);
+ return range;
+ },
+
+ get leftSelected() {
+ return this.leftSelected_;
+ },
+
+ set leftSelected(leftSelected) {
+ if (this.leftSelected_ === leftSelected) return;
+
+ this.leftSelected_ = leftSelected;
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ get rightSelected() {
+ return this.rightSelected_;
+ },
+
+ set rightSelected(rightSelected) {
+ if (this.rightSelected_ === rightSelected) return;
+
+ this.rightSelected_ = rightSelected;
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ get leftSnapIndicator() {
+ return this.leftSnapIndicator_;
+ },
+
+ set leftSnapIndicator(leftSnapIndicator) {
+ this.leftSnapIndicator_ = leftSnapIndicator;
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ get rightSnapIndicator() {
+ return this.rightSnapIndicator_;
+ },
+
+ set rightSnapIndicator(rightSnapIndicator) {
+ this.rightSnapIndicator_ = rightSnapIndicator;
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ draw(ctx, viewLWorld, viewRWorld, viewHeight) {
+ if (this.range_.isEmpty) return;
+
+ const dt = this.viewport_.currentDisplayTransform;
+
+ const markerLWorld = this.min;
+ const markerRWorld = this.max;
+
+ const markerLView = Math.round(dt.xWorldToView(markerLWorld));
+ const markerRView = Math.round(dt.xWorldToView(markerRWorld));
+
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
+ if (markerLWorld > viewLWorld) {
+ ctx.fillRect(dt.xWorldToView(viewLWorld), 0,
+ markerLView, viewHeight);
+ }
+
+ if (markerRWorld < viewRWorld) {
+ ctx.fillRect(markerRView, 0,
+ dt.xWorldToView(viewRWorld), viewHeight);
+ }
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ ctx.lineWidth = Math.round(pixelRatio);
+ if (this.range_.range > 0) {
+ this.drawLine_(ctx, viewLWorld, viewRWorld,
+ viewHeight, this.min, this.leftSelected_);
+ this.drawLine_(ctx, viewLWorld, viewRWorld,
+ viewHeight, this.max, this.rightSelected_);
+ } else {
+ this.drawLine_(ctx, viewLWorld, viewRWorld,
+ viewHeight, this.min,
+ this.leftSelected_ || this.rightSelected_);
+ }
+ ctx.lineWidth = 1;
+ },
+
+ drawLine_(ctx, viewLWorld, viewRWorld, height, ts, selected) {
+ if (ts < viewLWorld || ts >= viewRWorld) return;
+
+ const dt = this.viewport_.currentDisplayTransform;
+ const viewX = Math.round(dt.xWorldToView(ts));
+
+ // Apply subpixel translate to get crisp lines.
+ // http://www.mobtowers.com/html5-canvas-crisp-lines-every-time/
+ ctx.save();
+ ctx.translate((Math.round(ctx.lineWidth) % 2) / 2, 0);
+
+ ctx.beginPath();
+ tr.ui.b.drawLine(ctx, viewX, 0, viewX, height);
+ if (selected) {
+ ctx.strokeStyle = 'rgb(255, 0, 0)';
+ } else {
+ ctx.strokeStyle = 'rgb(0, 0, 0)';
+ }
+ ctx.stroke();
+
+ ctx.restore();
+ },
+
+ drawIndicators(ctx, viewLWorld, viewRWorld) {
+ if (this.leftSnapIndicator_) {
+ this.drawIndicator_(ctx, viewLWorld, viewRWorld,
+ this.range_.min,
+ this.leftSnapIndicator_,
+ this.leftSelected_);
+ }
+ if (this.rightSnapIndicator_) {
+ this.drawIndicator_(ctx, viewLWorld, viewRWorld,
+ this.range_.max,
+ this.rightSnapIndicator_,
+ this.rightSelected_);
+ }
+ },
+
+ drawIndicator_(ctx, viewLWorld, viewRWorld,
+ xWorld, si, selected) {
+ const dt = this.viewport_.currentDisplayTransform;
+
+ const viewX = Math.round(dt.xWorldToView(xWorld));
+
+ // Apply subpixel translate to get crisp lines.
+ // http://www.mobtowers.com/html5-canvas-crisp-lines-every-time/
+ ctx.save();
+ ctx.translate((Math.round(ctx.lineWidth) % 2) / 2, 0);
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const viewY = si.y * devicePixelRatio;
+ const viewHeight = si.height * devicePixelRatio;
+ const arrowSize = 4 * pixelRatio;
+
+ if (selected) {
+ ctx.fillStyle = 'rgb(255, 0, 0)';
+ } else {
+ ctx.fillStyle = 'rgb(0, 0, 0)';
+ }
+ tr.ui.b.drawTriangle(ctx,
+ viewX - arrowSize * 0.75, viewY,
+ viewX + arrowSize * 0.75, viewY,
+ viewX, viewY + arrowSize);
+ ctx.fill();
+ tr.ui.b.drawTriangle(ctx,
+ viewX - arrowSize * 0.75, viewY + viewHeight,
+ viewX + arrowSize * 0.75, viewY + viewHeight,
+ viewX, viewY + viewHeight - arrowSize);
+ ctx.fill();
+
+ ctx.restore();
+ }
+ };
+
+ return {
+ SnapIndicator,
+ TimelineInterestRange,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_track_view.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_track_view.html
new file mode 100644
index 00000000000..f6087abf74c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_track_view.html
@@ -0,0 +1,1179 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/x_marker_annotation.html">
+<link rel="import" href="/tracing/ui/base/hotkey_controller.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_selector.html">
+<link rel="import" href="/tracing/ui/base/timing_tool.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/timeline_display_transform_animations.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/model_track.html">
+<link rel="import" href="/tracing/ui/tracks/x_axis_track.html">
+
+<!--
+ Interactive visualizaiton of Model objects based loosely on gantt charts.
+ Each thread in the Model is given a set of Tracks, one per subrow in the
+ thread. The TimelineTrackView class acts as a controller, creating the
+ individual tracks, while Tracks do actual drawing.
+
+ Visually, the TimelineTrackView produces (prettier) visualizations like the
+ following:
+ Thread1: AAAAAAAAAA AAAAA
+ BBBB BB
+ Thread2: CCCCCC CCCCC
+-->
+<dom-module id='tr-ui-timeline-track-view'>
+ <template>
+ <style>
+ :host {
+ flex-direction: column;
+ display: flex;
+ position: relative;
+ }
+
+ :host ::content * {
+ -webkit-user-select: none;
+ cursor: default;
+ }
+
+ #drag_box {
+ background-color: rgba(0, 0, 255, 0.25);
+ border: 1px solid rgb(0, 0, 96);
+ font-size: 75%;
+ position: fixed;
+ }
+
+ #hint_text {
+ position: absolute;
+ bottom: 6px;
+ right: 6px;
+ font-size: 8pt;
+ }
+ </style>
+ <slot></slot>
+
+ <div id='drag_box'></div>
+ <div id='hint_text'></div>
+
+ <tv-ui-b-hotkey-controller id='hotkey_controller'>
+ </tv-ui-b-hotkey-controller>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-timeline-track-view',
+
+ ready() {
+ this.displayTransform_ = new tr.ui.TimelineDisplayTransform();
+ this.model_ = undefined;
+
+ this.timelineView_ = undefined;
+ this.pollIfViewportAttachedInterval_ = undefined;
+
+ this.viewport_ = new tr.ui.TimelineViewport(this);
+ this.viewportDisplayTransformAtMouseDown_ = undefined;
+ this.brushingStateController_ = undefined;
+
+ this.rulerTrackContainer_ =
+ new tr.ui.tracks.DrawingContainer(this.viewport_);
+ Polymer.dom(this).appendChild(this.rulerTrackContainer_);
+ this.rulerTrackContainer_.invalidate();
+ this.rulerTrackContainer_.style.overflowY = 'hidden';
+ this.rulerTrackContainer_.style.flexShrink = '0';
+
+ this.rulerTrack_ = new tr.ui.tracks.XAxisTrack(this.viewport_);
+ Polymer.dom(this.rulerTrackContainer_).appendChild(this.rulerTrack_);
+
+ this.upperModelTrack_ = new tr.ui.tracks.ModelTrack(this.viewport_);
+ this.upperModelTrack_.upperMode = true;
+ Polymer.dom(this.rulerTrackContainer_).appendChild(this.upperModelTrack_);
+
+ this.modelTrackContainer_ =
+ new tr.ui.tracks.DrawingContainer(this.viewport_);
+ Polymer.dom(this).appendChild(this.modelTrackContainer_);
+ this.modelTrackContainer_.style.display = 'block';
+ this.modelTrackContainer_.style.flexGrow = '1';
+ this.modelTrackContainer_.invalidate();
+
+ this.viewport_.modelTrackContainer = this.modelTrackContainer_;
+
+ this.modelTrack_ = new tr.ui.tracks.ModelTrack(this.viewport_);
+ Polymer.dom(this.modelTrackContainer_).appendChild(this.modelTrack_);
+
+ this.timingTool_ = new tr.ui.b.TimingTool(this.viewport_, this);
+
+ this.initMouseModeSelector();
+
+ this.hideDragBox_();
+
+ this.initHintText_();
+
+ this.onSelectionChanged_ = this.onSelectionChanged_.bind(this);
+
+ this.onDblClick_ = this.onDblClick_.bind(this);
+ this.addEventListener('dblclick', this.onDblClick_);
+
+ this.onMouseWheel_ = this.onMouseWheel_.bind(this);
+ this.addEventListener('mousewheel', this.onMouseWheel_);
+
+ this.onMouseDown_ = this.onMouseDown_.bind(this);
+ this.addEventListener('mousedown', this.onMouseDown_);
+
+ this.onMouseMove_ = this.onMouseMove_.bind(this);
+ this.addEventListener('mousemove', this.onMouseMove_);
+
+ this.onTouchStart_ = this.onTouchStart_.bind(this);
+ this.addEventListener('touchstart', this.onTouchStart_);
+
+ this.onTouchMove_ = this.onTouchMove_.bind(this);
+ this.addEventListener('touchmove', this.onTouchMove_);
+
+ this.onTouchEnd_ = this.onTouchEnd_.bind(this);
+ this.addEventListener('touchend', this.onTouchEnd_);
+
+
+ this.addHotKeys_();
+
+ this.mouseViewPosAtMouseDown_ = {x: 0, y: 0};
+ this.lastMouseViewPos_ = {x: 0, y: 0};
+
+ this.lastTouchViewPositions_ = [];
+
+ this.alert_ = undefined;
+
+ this.isPanningAndScanning_ = false;
+ this.isZooming_ = false;
+ },
+
+ initMouseModeSelector() {
+ this.mouseModeSelector_ = document.createElement(
+ 'tr-ui-b-mouse-mode-selector');
+ this.mouseModeSelector_.targetElement = this;
+ Polymer.dom(this).appendChild(this.mouseModeSelector_);
+
+ this.mouseModeSelector_.addEventListener('beginpan',
+ this.onBeginPanScan_.bind(this));
+ this.mouseModeSelector_.addEventListener('updatepan',
+ this.onUpdatePanScan_.bind(this));
+ this.mouseModeSelector_.addEventListener('endpan',
+ this.onEndPanScan_.bind(this));
+
+ this.mouseModeSelector_.addEventListener('beginselection',
+ this.onBeginSelection_.bind(this));
+ this.mouseModeSelector_.addEventListener('updateselection',
+ this.onUpdateSelection_.bind(this));
+ this.mouseModeSelector_.addEventListener('endselection',
+ this.onEndSelection_.bind(this));
+
+ this.mouseModeSelector_.addEventListener('beginzoom',
+ this.onBeginZoom_.bind(this));
+ this.mouseModeSelector_.addEventListener('updatezoom',
+ this.onUpdateZoom_.bind(this));
+ this.mouseModeSelector_.addEventListener('endzoom',
+ this.onEndZoom_.bind(this));
+
+ this.mouseModeSelector_.addEventListener('entertiming',
+ this.timingTool_.onEnterTiming.bind(this.timingTool_));
+ this.mouseModeSelector_.addEventListener('begintiming',
+ this.timingTool_.onBeginTiming.bind(this.timingTool_));
+ this.mouseModeSelector_.addEventListener('updatetiming',
+ this.timingTool_.onUpdateTiming.bind(this.timingTool_));
+ this.mouseModeSelector_.addEventListener('endtiming',
+ this.timingTool_.onEndTiming.bind(this.timingTool_));
+ this.mouseModeSelector_.addEventListener('exittiming',
+ this.timingTool_.onExitTiming.bind(this.timingTool_));
+
+ const m = tr.ui.b.MOUSE_SELECTOR_MODE;
+ this.mouseModeSelector_.supportedModeMask =
+ m.SELECTION | m.PANSCAN | m.ZOOM | m.TIMING;
+ this.mouseModeSelector_.settingsKey =
+ 'timelineTrackView.mouseModeSelector';
+ this.mouseModeSelector_.setKeyCodeForMode(m.PANSCAN, '2'.charCodeAt(0));
+ this.mouseModeSelector_.setKeyCodeForMode(m.SELECTION, '1'.charCodeAt(0));
+ this.mouseModeSelector_.setKeyCodeForMode(m.ZOOM, '3'.charCodeAt(0));
+ this.mouseModeSelector_.setKeyCodeForMode(m.TIMING, '4'.charCodeAt(0));
+
+ this.mouseModeSelector_.setModifierForAlternateMode(
+ m.SELECTION, tr.ui.b.MODIFIER.SHIFT);
+ this.mouseModeSelector_.setModifierForAlternateMode(
+ m.PANSCAN, tr.ui.b.MODIFIER.SPACE);
+ },
+
+ get brushingStateController() {
+ return this.brushingStateController_;
+ },
+
+ set brushingStateController(brushingStateController) {
+ if (this.brushingStateController_) {
+ this.brushingStateController_.removeEventListener('change',
+ this.onSelectionChanged_);
+ }
+ this.brushingStateController_ = brushingStateController;
+ if (this.brushingStateController_) {
+ this.brushingStateController_.addEventListener('change',
+ this.onSelectionChanged_);
+ }
+ },
+
+ set timelineView(view) {
+ this.timelineView_ = view;
+ },
+
+ get processViews() {
+ return this.modelTrack_.processViews;
+ },
+
+ onSelectionChanged_() {
+ this.showHintText_('Press \'m\' to mark current selection');
+ this.viewport_.dispatchChangeEvent();
+ },
+
+ set selection(selection) {
+ throw new Error('DO NOT CALL THIS');
+ },
+
+ set highlight(highlight) {
+ throw new Error('DO NOT CALL THIS');
+ },
+
+ detach() {
+ this.modelTrack_.detach();
+ this.upperModelTrack_.detach();
+
+ if (this.pollIfViewportAttachedInterval_) {
+ window.clearInterval(this.pollIfViewportAttachedInterval_);
+ this.pollIfViewportAttachedInterval_ = undefined;
+ }
+ this.viewport_.detach();
+ },
+
+ get viewport() {
+ return this.viewport_;
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ set model(model) {
+ if (!model) {
+ throw new Error('Model cannot be undefined');
+ }
+
+ const modelInstanceChanged = this.model_ !== model;
+ this.model_ = model;
+ this.modelTrack_.model = model;
+ this.upperModelTrack_.model = model;
+
+ // Set up a reasonable viewport.
+ if (modelInstanceChanged) {
+ // The following code uses an interval to detect when the parent element
+ // is attached to the document. That is a trigger to run the setup
+ // function and install a resize listener.
+ this.pollIfViewportAttachedInterval_ = window.setInterval(
+ this.pollIfViewportAttached_.bind(this), 250);
+ }
+ },
+
+ get hasVisibleContent() {
+ return this.modelTrack_.hasVisibleContent ||
+ this.upperModelTrack_.hasVisibleContent;
+ },
+
+ /**
+ * Checks whether the parentNode is attached to the document.
+ * When it is, the method installs the iframe-based resize detection hook
+ * and then runs setInitialViewport_, if present.
+ */
+ pollIfViewportAttached_() {
+ if (!this.viewport_.isAttachedToDocumentOrInTestMode ||
+ this.viewport_.clientWidth === 0) {
+ return;
+ }
+ window.addEventListener(
+ 'resize', this.viewport_.dispatchChangeEvent);
+ window.clearInterval(this.pollIfViewportAttachedInterval_);
+ this.pollIfViewportAttachedInterval_ = undefined;
+
+ this.setInitialViewport_();
+ },
+
+ setInitialViewport_() {
+ // We need the canvas size to be up-to-date at this point. We maybe in
+ // here before the raf fires, so the size may have not been updated since
+ // the canvas was resized.
+ this.modelTrackContainer_.updateCanvasSizeIfNeeded_();
+ const w = this.modelTrackContainer_.canvas.width;
+
+ let min;
+ let range;
+
+ if (this.model_.bounds.isEmpty) {
+ min = 0;
+ range = 1000;
+ } else if (this.model_.bounds.range === 0) {
+ min = this.model_.bounds.min;
+ range = 1000;
+ } else {
+ min = this.model_.bounds.min;
+ range = this.model_.bounds.range;
+ }
+
+ const boost = range * 0.15;
+ this.displayTransform_.set(this.viewport_.currentDisplayTransform);
+ this.displayTransform_.xSetWorldBounds(
+ min - boost, min + range + boost, w);
+ this.viewport_.setDisplayTransformImmediately(this.displayTransform_);
+ },
+
+ /**
+ * @param {Filter} filter The filter to use for finding matches.
+ * @param {Selection} selection The selection to add matches to.
+ * @return {Task} which performs the filtering.
+ */
+ addAllEventsMatchingFilterToSelectionAsTask(filter, selection) {
+ const modelTrack = this.modelTrack_;
+ const firstT = modelTrack.addAllEventsMatchingFilterToSelectionAsTask(
+ filter, selection);
+ const lastT = firstT.after(function() {
+ this.upperModelTrack_.addAllEventsMatchingFilterToSelection(
+ filter, selection);
+ }, this);
+ return firstT;
+ },
+
+ onMouseMove_(e) {
+ // Zooming requires the delta since the last mousemove so we need to avoid
+ // tracking it when the zoom interaction is active.
+ if (this.isZooming_) return;
+
+ this.storeLastMousePos_(e);
+ },
+
+ onTouchStart_(e) {
+ this.storeLastTouchPositions_(e);
+ this.focusElements_();
+ },
+
+ onTouchMove_(e) {
+ e.preventDefault();
+ this.onUpdateTransformForTouch_(e);
+ },
+
+ onTouchEnd_(e) {
+ this.storeLastTouchPositions_(e);
+ this.focusElements_();
+ },
+
+ addHotKeys_() {
+ this.addKeyDownHotKeys_();
+ this.addKeyPressHotKeys_();
+ },
+
+ addKeyPressHotKey(dict) {
+ dict.eventType = 'keypress';
+ dict.useCapture = false;
+ dict.thisArg = this;
+ const binding = new tr.ui.b.HotKey(dict);
+ this.$.hotkey_controller.addHotKey(binding);
+ },
+
+ addKeyPressHotKeys_() {
+ this.addKeyPressHotKey({
+ keyCodes: ['w'.charCodeAt(0), ','.charCodeAt(0)],
+ callback(e) {
+ this.zoomBy_(1.5, true);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCodes: ['s'.charCodeAt(0), 'o'.charCodeAt(0)],
+ callback(e) {
+ this.zoomBy_(1 / 1.5, true);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'g'.charCodeAt(0),
+ callback(e) {
+ this.onGridToggle_(true);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'G'.charCodeAt(0),
+ callback(e) {
+ this.onGridToggle_(false);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCodes: ['W'.charCodeAt(0), '<'.charCodeAt(0)],
+ callback(e) {
+ this.zoomBy_(10, true);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCodes: ['S'.charCodeAt(0), 'O'.charCodeAt(0)],
+ callback(e) {
+ this.zoomBy_(1 / 10, true);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'a'.charCodeAt(0),
+ callback(e) {
+ this.queueSmoothPan_(this.viewWidth_ * 0.3, 0);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCodes: ['d'.charCodeAt(0), 'e'.charCodeAt(0)],
+ callback(e) {
+ this.queueSmoothPan_(this.viewWidth_ * -0.3, 0);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'A'.charCodeAt(0),
+ callback(e) {
+ this.queueSmoothPan_(viewWidth * 0.5, 0);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'D'.charCodeAt(0),
+ callback(e) {
+ this.queueSmoothPan_(viewWidth * -0.5, 0);
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: '0'.charCodeAt(0),
+ callback(e) {
+ this.setInitialViewport_();
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'f'.charCodeAt(0),
+ callback(e) {
+ this.zoomToSelection();
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'm'.charCodeAt(0),
+ callback(e) {
+ this.setCurrentSelectionAsInterestRange_();
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'p'.charCodeAt(0),
+ callback(e) {
+ this.selectPowerSamplesInCurrentTimeRange_();
+ e.stopPropagation();
+ }
+ });
+
+ this.addKeyPressHotKey({
+ keyCode: 'h'.charCodeAt(0),
+ callback(e) {
+ this.toggleHighDetails_();
+ e.stopPropagation();
+ }
+ });
+ },
+
+ get viewWidth_() {
+ return this.modelTrackContainer_.canvas.clientWidth;
+ },
+
+ addKeyDownHotKeys_() {
+ const addBinding = function(dict) {
+ dict.eventType = 'keydown';
+ dict.useCapture = false;
+ dict.thisArg = this;
+ const binding = new tr.ui.b.HotKey(dict);
+ this.$.hotkey_controller.addHotKey(binding);
+ }.bind(this);
+
+ addBinding({
+ keyCode: 37, // Left arrow.
+ callback(e) {
+ const curSel = this.brushingStateController_.selection;
+ const sel = this.viewport.getShiftedSelection(curSel, -1);
+
+ if (sel) {
+ this.brushingStateController.changeSelectionFromTimeline(sel);
+ this.panToSelection();
+ } else {
+ this.queueSmoothPan_(this.viewWidth_ * 0.3, 0);
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+
+ addBinding({
+ keyCode: 39, // Right arrow.
+ callback(e) {
+ const curSel = this.brushingStateController_.selection;
+ const sel = this.viewport.getShiftedSelection(curSel, 1);
+ if (sel) {
+ this.brushingStateController.changeSelectionFromTimeline(sel);
+ this.panToSelection();
+ } else {
+ this.queueSmoothPan_(-this.viewWidth_ * 0.3, 0);
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+ },
+
+ onDblClick_(e) {
+ if (this.mouseModeSelector_.mode !==
+ tr.ui.b.MOUSE_SELECTOR_MODE.SELECTION) {
+ return;
+ }
+
+ const curSelection = this.brushingStateController_.selection;
+ if (!curSelection.length || !tr.b.getOnlyElement(curSelection).title) {
+ return;
+ }
+
+ const selection = new tr.model.EventSet();
+ const filter = new tr.c.ExactTitleFilter(
+ tr.b.getOnlyElement(curSelection).title);
+ this.modelTrack_.addAllEventsMatchingFilterToSelection(filter,
+ selection);
+
+ this.brushingStateController.changeSelectionFromTimeline(selection);
+ },
+
+ onMouseWheel_(e) {
+ if (!e.altKey) return;
+
+ const delta = e.wheelDelta / 120;
+ const zoomScale = Math.pow(1.5, delta);
+ this.zoomBy_(zoomScale);
+ e.preventDefault();
+ },
+
+ onMouseDown_(e) {
+ if (this.mouseModeSelector_.mode !==
+ tr.ui.b.MOUSE_SELECTOR_MODE.SELECTION) {
+ return;
+ }
+
+ // Mouse down must start on ruler track for crosshair guide lines to draw.
+ if (e.target !== this.rulerTrack_) return;
+
+ // Make sure we don't start a selection drag event here.
+ this.dragBeginEvent_ = undefined;
+
+ // Remove nav string marker if it exists, since we're clearing the
+ // find control box.
+ if (this.xNavStringMarker_) {
+ this.model.removeAnnotation(this.xNavStringMarker_);
+ this.xNavStringMarker_ = undefined;
+ }
+
+ const dt = this.viewport_.currentDisplayTransform;
+ tr.ui.b.trackMouseMovesUntilMouseUp(function(e) { // Mouse move handler.
+ // If mouse event is on ruler, don't do anything.
+ if (e.target === this.rulerTrack_) return;
+
+ const relativePosition = this.extractRelativeMousePosition_(e);
+ const loc = tr.model.Location.fromViewCoordinates(
+ this.viewport_, relativePosition.x, relativePosition.y);
+ // Not all points on the timeline represents a valid location.
+ // ex. process header tracks, letter dot tracks.
+ if (!loc) return;
+
+ if (this.guideLineAnnotation_ === undefined) {
+ this.guideLineAnnotation_ =
+ new tr.model.XMarkerAnnotation(loc.xWorld);
+ this.model.addAnnotation(this.guideLineAnnotation_);
+ } else {
+ this.guideLineAnnotation_.timestamp = loc.xWorld;
+ this.modelTrackContainer_.invalidate();
+ }
+
+ // Set the findcontrol's text to nav string of current state.
+ const state = new tr.ui.b.UIState(loc,
+ this.viewport_.currentDisplayTransform.scaleX);
+ this.timelineView_.setFindCtlText(
+ state.toUserFriendlyString(this.viewport_));
+ }.bind(this),
+ undefined, // Mouse up handler.
+ function onKeyUpDuringDrag() {
+ if (this.dragBeginEvent_) {
+ this.setDragBoxPosition_(this.dragBoxXStart_, this.dragBoxYStart_,
+ this.dragBoxXEnd_, this.dragBoxYEnd_);
+ }
+ }.bind(this));
+ },
+
+ queueSmoothPan_(viewDeltaX, deltaY) {
+ const deltaX = this.viewport_.currentDisplayTransform.xViewVectorToWorld(
+ viewDeltaX);
+ const animation = new tr.ui.TimelineDisplayTransformPanAnimation(
+ deltaX, deltaY);
+ this.viewport_.queueDisplayTransformAnimation(animation);
+ },
+
+ /**
+ * Zoom in or out on the timeline by the given scale factor.
+ * @param {Number} scale The scale factor to apply. If <1, zooms out.
+ * @param {boolean} Whether to change the zoom level smoothly.
+ */
+ zoomBy_(scale, smooth) {
+ if (scale <= 0) {
+ return;
+ }
+
+ smooth = !!smooth;
+ const vp = this.viewport_;
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ const goalFocalPointXView = this.lastMouseViewPos_.x * pixelRatio;
+ const goalFocalPointXWorld = vp.currentDisplayTransform.xViewToWorld(
+ goalFocalPointXView);
+ if (smooth) {
+ const animation = new tr.ui.TimelineDisplayTransformZoomToAnimation(
+ goalFocalPointXWorld, goalFocalPointXView,
+ vp.currentDisplayTransform.panY,
+ scale);
+ vp.queueDisplayTransformAnimation(animation);
+ } else {
+ this.displayTransform_.set(vp.currentDisplayTransform);
+ this.displayTransform_.scaleX *= scale;
+ this.displayTransform_.xPanWorldPosToViewPos(
+ goalFocalPointXWorld, goalFocalPointXView, this.viewWidth_);
+ vp.setDisplayTransformImmediately(this.displayTransform_);
+ }
+ },
+
+ /**
+ * Zoom into the current selection.
+ */
+ zoomToSelection() {
+ if (!this.brushingStateController.selectionOfInterest.length) return;
+
+ const bounds = this.brushingStateController.selectionOfInterest.bounds;
+ if (!bounds.range) return;
+
+ const worldCenter = bounds.center;
+ const viewCenter = this.modelTrackContainer_.canvas.width / 2;
+ const adjustedWorldRange = bounds.range * 1.25;
+ const newScale = this.modelTrackContainer_.canvas.width /
+ adjustedWorldRange;
+ const zoomInRatio = newScale /
+ this.viewport_.currentDisplayTransform.scaleX;
+
+ const animation = new tr.ui.TimelineDisplayTransformZoomToAnimation(
+ worldCenter, viewCenter,
+ this.viewport_.currentDisplayTransform.panY,
+ zoomInRatio);
+ this.viewport_.queueDisplayTransformAnimation(animation);
+ },
+
+ /**
+ * Pan the view so the current selection becomes visible.
+ */
+ panToSelection() {
+ if (!this.brushingStateController.selectionOfInterest.length) return;
+
+ const bounds = this.brushingStateController.selectionOfInterest.bounds;
+ const worldCenter = bounds.center;
+ const viewWidth = this.viewWidth_;
+
+ const dt = this.viewport_.currentDisplayTransform;
+ if (false && !bounds.range) {
+ if (dt.xWorldToView(bounds.center) < 0 ||
+ dt.xWorldToView(bounds.center) > viewWidth) {
+ this.displayTransform_.set(dt);
+ this.displayTransform_.xPanWorldPosToViewPos(
+ worldCenter, 'center', viewWidth);
+ const deltaX = this.displayTransform_.panX - dt.panX;
+ const animation = new tr.ui.TimelineDisplayTransformPanAnimation(
+ deltaX, 0);
+ this.viewport_.queueDisplayTransformAnimation(animation);
+ }
+ return;
+ }
+
+ this.displayTransform_.set(dt);
+ this.displayTransform_.xPanWorldBoundsIntoView(
+ bounds.min,
+ bounds.max,
+ viewWidth);
+ const deltaX = this.displayTransform_.panX - dt.panX;
+ const animation = new tr.ui.TimelineDisplayTransformPanAnimation(
+ deltaX, 0);
+ this.viewport_.queueDisplayTransformAnimation(animation);
+ },
+
+ navToPosition(uiState, showNavLine) {
+ const location = uiState.location;
+ const scaleX = uiState.scaleX;
+ const track = location.getContainingTrack(this.viewport_);
+
+ const worldCenter = location.xWorld;
+ const viewCenter = this.modelTrackContainer_.canvas.width / 5;
+ const zoomInRatio = scaleX /
+ this.viewport_.currentDisplayTransform.scaleX;
+
+ // Vertically scroll so track is in view.
+ track.scrollIntoViewIfNeeded();
+
+ // Perform zoom and panX animation.
+ const animation = new tr.ui.TimelineDisplayTransformZoomToAnimation(
+ worldCenter, viewCenter,
+ this.viewport_.currentDisplayTransform.panY,
+ zoomInRatio);
+ this.viewport_.queueDisplayTransformAnimation(animation);
+
+ if (!showNavLine) return;
+ // Add an X Marker Annotation at the specified timestamp.
+ if (this.xNavStringMarker_) {
+ this.model.removeAnnotation(this.xNavStringMarker_);
+ }
+ this.xNavStringMarker_ =
+ new tr.model.XMarkerAnnotation(worldCenter);
+ this.model.addAnnotation(this.xNavStringMarker_);
+ },
+
+ selectPowerSamplesInCurrentTimeRange_() {
+ const selectionBounds = this.brushingStateController_.selection.bounds;
+ if (this.model.device.powerSeries && !selectionBounds.empty) {
+ const events = this.model.device.powerSeries.getSamplesWithinRange(
+ selectionBounds.min, selectionBounds.max);
+ const selection = new tr.model.EventSet(events);
+ this.brushingStateController_.changeSelectionFromTimeline(selection);
+ }
+ },
+
+ setCurrentSelectionAsInterestRange_() {
+ const selectionBounds = this.brushingStateController_.selection.bounds;
+ if (selectionBounds.empty) {
+ this.viewport_.interestRange.reset();
+ return;
+ }
+
+ if (this.viewport_.interestRange.min === selectionBounds.min &&
+ this.viewport_.interestRange.max === selectionBounds.max) {
+ this.viewport_.interestRange.reset();
+ } else {
+ this.viewport_.interestRange.set(selectionBounds);
+ }
+ },
+
+ toggleHighDetails_() {
+ this.viewport_.highDetails = !this.viewport_.highDetails;
+ },
+
+ hideDragBox_() {
+ this.$.drag_box.style.left = '-1000px';
+ this.$.drag_box.style.top = '-1000px';
+ this.$.drag_box.style.width = 0;
+ this.$.drag_box.style.height = 0;
+ },
+
+ setDragBoxPosition_(xStart, yStart, xEnd, yEnd) {
+ const loY = Math.min(yStart, yEnd);
+ const hiY = Math.max(yStart, yEnd);
+ const loX = Math.min(xStart, xEnd);
+ const hiX = Math.max(xStart, xEnd);
+ const modelTrackRect = this.modelTrack_.getBoundingClientRect();
+ const dragRect = {left: loX, top: loY, width: hiX - loX, height: hiY - loY};
+
+ dragRect.right = dragRect.left + dragRect.width;
+ dragRect.bottom = dragRect.top + dragRect.height;
+
+ const modelTrackContainerRect =
+ this.modelTrackContainer_.getBoundingClientRect();
+ const clipRect = {
+ left: modelTrackContainerRect.left,
+ top: modelTrackContainerRect.top,
+ right: modelTrackContainerRect.right,
+ bottom: modelTrackContainerRect.bottom
+ };
+
+ const headingWidth = window.getComputedStyle(
+ Polymer.dom(this).querySelector('tr-ui-b-heading')).width;
+ const trackTitleWidth = parseInt(headingWidth);
+ clipRect.left = clipRect.left + trackTitleWidth;
+
+ const intersectRect_ = function(r1, r2) {
+ if (r2.left > r1.right || r2.right < r1.left ||
+ r2.top > r1.bottom || r2.bottom < r1.top) {
+ return false;
+ }
+
+ const results = {};
+ results.left = Math.max(r1.left, r2.left);
+ results.top = Math.max(r1.top, r2.top);
+ results.right = Math.min(r1.right, r2.right);
+ results.bottom = Math.min(r1.bottom, r2.bottom);
+ results.width = results.right - results.left;
+ results.height = results.bottom - results.top;
+ return results;
+ };
+
+ // TODO(dsinclair): intersectRect_ can return false (which should actually
+ // be undefined) but we use finalDragBox without checking the return value
+ // which could potentially blowup. Fix this .....
+ const finalDragBox = intersectRect_(clipRect, dragRect);
+
+ this.$.drag_box.style.left = finalDragBox.left + 'px';
+ this.$.drag_box.style.width = finalDragBox.width + 'px';
+ this.$.drag_box.style.top = finalDragBox.top + 'px';
+ this.$.drag_box.style.height = finalDragBox.height + 'px';
+ this.$.drag_box.style.whiteSpace = 'nowrap';
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const canv = this.modelTrackContainer_.canvas;
+ const dt = this.viewport_.currentDisplayTransform;
+ const loWX = dt.xViewToWorld(
+ (loX - canv.offsetLeft) * pixelRatio);
+ const hiWX = dt.xViewToWorld(
+ (hiX - canv.offsetLeft) * pixelRatio);
+
+ Polymer.dom(this.$.drag_box).textContent =
+ tr.b.Unit.byName.timeDurationInMs.format(hiWX - loWX);
+
+ const e = new tr.b.Event('selectionChanging');
+ e.loWX = loWX;
+ e.hiWX = hiWX;
+ this.dispatchEvent(e);
+ },
+
+ onGridToggle_(left) {
+ const selection = this.brushingStateController_.selection;
+ const tb = left ? selection.bounds.min : selection.bounds.max;
+
+ // Toggle the grid off if the grid is on, the marker position is the same
+ // and the same element is selected (same timebase).
+ if (this.viewport_.gridEnabled &&
+ this.viewport_.gridSide === left &&
+ this.viewport_.gridInitialTimebase === tb) {
+ this.viewport_.gridside = undefined;
+ this.viewport_.gridEnabled = false;
+ this.viewport_.gridInitialTimebase = undefined;
+ return;
+ }
+
+ // Shift the timebase left until its just left of model_.bounds.min.
+ const numIntervalsSinceStart = Math.ceil((tb - this.model_.bounds.min) /
+ this.viewport_.gridStep_);
+
+ this.viewport_.gridEnabled = true;
+ this.viewport_.gridSide = left;
+ this.viewport_.gridInitialTimebase = tb;
+ this.viewport_.gridTimebase = tb -
+ (numIntervalsSinceStart + 1) * this.viewport_.gridStep_;
+ },
+
+ storeLastMousePos_(e) {
+ this.lastMouseViewPos_ = this.extractRelativeMousePosition_(e);
+ },
+
+ storeLastTouchPositions_(e) {
+ this.lastTouchViewPositions_ = this.extractRelativeTouchPositions_(e);
+ },
+
+ extractRelativeMousePosition_(e) {
+ const canv = this.modelTrackContainer_.canvas;
+ return {
+ x: e.clientX - canv.offsetLeft,
+ y: e.clientY - canv.offsetTop
+ };
+ },
+
+ extractRelativeTouchPositions_(e) {
+ const canv = this.modelTrackContainer_.canvas;
+
+ const touches = [];
+ for (let i = 0; i < e.touches.length; ++i) {
+ touches.push({
+ x: e.touches[i].clientX - canv.offsetLeft,
+ y: e.touches[i].clientY - canv.offsetTop
+ });
+ }
+ return touches;
+ },
+
+ storeInitialMouseDownPos_(e) {
+ const position = this.extractRelativeMousePosition_(e);
+
+ this.mouseViewPosAtMouseDown_.x = position.x;
+ this.mouseViewPosAtMouseDown_.y = position.y;
+ },
+
+ focusElements_() {
+ this.$.hotkey_controller.childRequestsGeneralFocus(this);
+ },
+
+ storeInitialInteractionPositionsAndFocus_(e) {
+ this.storeInitialMouseDownPos_(e);
+ this.storeLastMousePos_(e);
+
+ this.focusElements_();
+ },
+
+ onBeginPanScan_(e) {
+ const vp = this.viewport_;
+ this.viewportDisplayTransformAtMouseDown_ =
+ vp.currentDisplayTransform.clone();
+ this.isPanningAndScanning_ = true;
+
+ this.storeInitialInteractionPositionsAndFocus_(e);
+ e.preventDefault();
+ },
+
+ onUpdatePanScan_(e) {
+ if (!this.isPanningAndScanning_) return;
+
+ const viewWidth = this.viewWidth_;
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const xDeltaView = pixelRatio * (this.lastMouseViewPos_.x -
+ this.mouseViewPosAtMouseDown_.x);
+
+ const yDelta = this.lastMouseViewPos_.y -
+ this.mouseViewPosAtMouseDown_.y;
+
+ this.displayTransform_.set(this.viewportDisplayTransformAtMouseDown_);
+ this.displayTransform_.incrementPanXInViewUnits(xDeltaView);
+ this.displayTransform_.panY -= yDelta;
+ this.viewport_.setDisplayTransformImmediately(this.displayTransform_);
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ this.storeLastMousePos_(e);
+ },
+
+ onEndPanScan_(e) {
+ this.isPanningAndScanning_ = false;
+
+ this.storeLastMousePos_(e);
+
+ if (!e.isClick) {
+ e.preventDefault();
+ }
+ },
+
+ onBeginSelection_(e) {
+ const canv = this.modelTrackContainer_.canvas;
+ const rect = this.modelTrack_.getBoundingClientRect();
+ const canvRect = canv.getBoundingClientRect();
+
+ const inside = rect &&
+ e.clientX >= rect.left &&
+ e.clientX < rect.right &&
+ e.clientY >= rect.top &&
+ e.clientY < rect.bottom &&
+ e.clientX >= canvRect.left &&
+ e.clientX < canvRect.right;
+
+ if (!inside) return;
+
+ this.dragBeginEvent_ = e;
+
+ this.storeInitialInteractionPositionsAndFocus_(e);
+ e.preventDefault();
+ },
+
+ onUpdateSelection_(e) {
+ if (!this.dragBeginEvent_) return;
+
+ // Update the drag box
+ this.dragBoxXStart_ = this.dragBeginEvent_.clientX;
+ this.dragBoxXEnd_ = e.clientX;
+ this.dragBoxYStart_ = this.dragBeginEvent_.clientY;
+ this.dragBoxYEnd_ = e.clientY;
+ this.setDragBoxPosition_(this.dragBoxXStart_, this.dragBoxYStart_,
+ this.dragBoxXEnd_, this.dragBoxYEnd_);
+ },
+
+ onEndSelection_(e) {
+ e.preventDefault();
+
+ if (!this.dragBeginEvent_) return;
+
+ // Stop the dragging.
+ this.hideDragBox_();
+ const eDown = this.dragBeginEvent_;
+ this.dragBeginEvent_ = undefined;
+
+ // Figure out extents of the drag.
+ const loY = Math.min(eDown.clientY, e.clientY);
+ const hiY = Math.max(eDown.clientY, e.clientY);
+ const loX = Math.min(eDown.clientX, e.clientX);
+ const hiX = Math.max(eDown.clientX, e.clientX);
+
+ // Convert to worldspace.
+ const canv = this.modelTrackContainer_.canvas;
+ const worldOffset = canv.getBoundingClientRect().left;
+ const loVX = loX - worldOffset;
+ const hiVX = hiX - worldOffset;
+
+ // Figure out what has been selected.
+ const selection = new tr.model.EventSet();
+ if (eDown.appendSelection) {
+ const previousSelection = this.brushingStateController_.selection;
+ if (previousSelection !== undefined) {
+ selection.addEventSet(previousSelection);
+ }
+ }
+ this.modelTrack_.addIntersectingEventsInRangeToSelection(
+ loVX, hiVX, loY, hiY, selection);
+
+ // Activate the new selection.
+ this.brushingStateController_.changeSelectionFromTimeline(selection);
+ },
+
+ onBeginZoom_(e) {
+ this.isZooming_ = true;
+
+ this.storeInitialInteractionPositionsAndFocus_(e);
+ e.preventDefault();
+ },
+
+ onUpdateZoom_(e) {
+ if (!this.isZooming_) return;
+
+ const newPosition = this.extractRelativeMousePosition_(e);
+
+ const zoomScaleValue = 1 + (this.lastMouseViewPos_.y -
+ newPosition.y) * 0.01;
+
+ this.zoomBy_(zoomScaleValue, false);
+ this.storeLastMousePos_(e);
+ },
+
+ onEndZoom_(e) {
+ this.isZooming_ = false;
+
+ if (!e.isClick) {
+ e.preventDefault();
+ }
+ },
+
+ computeTouchCenter_(positions) {
+ let xSum = 0;
+ let ySum = 0;
+ for (let i = 0; i < positions.length; ++i) {
+ xSum += positions[i].x;
+ ySum += positions[i].y;
+ }
+ return {
+ x: xSum / positions.length,
+ y: ySum / positions.length
+ };
+ },
+
+ computeTouchSpan_(positions) {
+ let xMin = Number.MAX_VALUE;
+ let yMin = Number.MAX_VALUE;
+ let xMax = Number.MIN_VALUE;
+ let yMax = Number.MIN_VALUE;
+ for (let i = 0; i < positions.length; ++i) {
+ xMin = Math.min(xMin, positions[i].x);
+ yMin = Math.min(yMin, positions[i].y);
+ xMax = Math.max(xMax, positions[i].x);
+ yMax = Math.max(yMax, positions[i].y);
+ }
+ return Math.sqrt((xMin - xMax) * (xMin - xMax) +
+ (yMin - yMax) * (yMin - yMax));
+ },
+
+ onUpdateTransformForTouch_(e) {
+ const newPositions = this.extractRelativeTouchPositions_(e);
+ const currentPositions = this.lastTouchViewPositions_;
+
+ const newCenter = this.computeTouchCenter_(newPositions);
+ const currentCenter = this.computeTouchCenter_(currentPositions);
+
+ const newSpan = this.computeTouchSpan_(newPositions);
+ const currentSpan = this.computeTouchSpan_(currentPositions);
+
+ const vp = this.viewport_;
+ const viewWidth = this.viewWidth_;
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ const xDelta = pixelRatio * (newCenter.x - currentCenter.x);
+ const yDelta = newCenter.y - currentCenter.y;
+ const zoomScaleValue = currentSpan > 10 ? newSpan / currentSpan : 1;
+
+ const viewFocus = pixelRatio * newCenter.x;
+ const worldFocus = vp.currentDisplayTransform.xViewToWorld(viewFocus);
+
+ this.displayTransform_.set(vp.currentDisplayTransform);
+ this.displayTransform_.scaleX *= zoomScaleValue;
+ this.displayTransform_.xPanWorldPosToViewPos(
+ worldFocus, viewFocus, viewWidth);
+ this.displayTransform_.incrementPanXInViewUnits(xDelta);
+ this.displayTransform_.panY -= yDelta;
+ vp.setDisplayTransformImmediately(this.displayTransform_);
+ this.storeLastTouchPositions_(e);
+ },
+
+ initHintText_() {
+ this.$.hint_text.style.display = 'none';
+
+ this.pendingHintTextClearTimeout_ = undefined;
+ },
+
+ showHintText_(text) {
+ if (this.pendingHintTextClearTimeout_) {
+ window.clearTimeout(this.pendingHintTextClearTimeout_);
+ this.pendingHintTextClearTimeout_ = undefined;
+ }
+ this.pendingHintTextClearTimeout_ = setTimeout(
+ this.hideHintText_.bind(this), 1000);
+ Polymer.dom(this.$.hint_text).textContent = text;
+ this.$.hint_text.style.display = '';
+ },
+
+ hideHintText_() {
+ this.pendingHintTextClearTimeout_ = undefined;
+ this.$.hint_text.style.display = 'none';
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_track_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_track_view_test.html
new file mode 100644
index 00000000000..a84addbe9bc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_track_view_test.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventSet = tr.model.EventSet;
+ const SelectionState = tr.model.SelectionState;
+ const Task = tr.b.Task;
+
+ test('instantiate', function() {
+ const numThreads = 500;
+ const model = tr.c.TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback(model) {
+ const p100 = model.getOrCreateProcess(100);
+ for (let i = 0; i < numThreads; i++) {
+ const t = p100.getOrCreateThread(101 + i);
+ if (i % 2 === 0) {
+ t.sliceGroup.beginSlice('cat', 'a', 100);
+ t.sliceGroup.endSlice(110);
+ } else {
+ t.sliceGroup.beginSlice('cat', 'b', 50);
+ t.sliceGroup.endSlice(120);
+ }
+ }
+ }
+ });
+
+ const timeline = document.createElement('tr-ui-timeline-track-view');
+ timeline.model = model;
+ timeline.style.maxHeight = '600px';
+ this.addHTMLOutput(timeline);
+ });
+
+ test('addAllEventsMatchingFilterToSelectionAsTask', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'b', 0, 1.1, {}, 2.8));
+
+ const t1asg = t1.asyncSliceGroup;
+ t1asg.slices.push(
+ tr.c.TestUtils.newAsyncSliceNamed('a', 0, 1, t1, t1));
+ t1asg.slices.push(
+ tr.c.TestUtils.newAsyncSliceNamed('b', 1, 2, t1, t1));
+
+ const timeline = document.createElement('tr-ui-timeline-track-view');
+ timeline.model = model;
+
+ let expected = new tr.model.EventSet(
+ [t1asg.slices[0], t1.sliceGroup.slices[0]]);
+ let result = new tr.model.EventSet;
+ let filterTask = timeline.addAllEventsMatchingFilterToSelectionAsTask(
+ new tr.c.TitleOrCategoryFilter('a'), result);
+ Task.RunSynchronously(filterTask);
+ assert.isTrue(result.equals(expected));
+
+ expected = new tr.model.EventSet(
+ [t1asg.slices[1], t1.sliceGroup.slices[1]]);
+ result = new tr.model.EventSet();
+ filterTask = timeline.addAllEventsMatchingFilterToSelectionAsTask(
+ new tr.c.TitleOrCategoryFilter('b'), result);
+ Task.RunSynchronously(filterTask);
+ assert.isTrue(result.equals(expected));
+ });
+
+ test('emptyThreadsDeleted', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+
+ const timeline = document.createElement('tr-ui-timeline-track-view');
+ timeline.model = model;
+
+ assert.isFalse(timeline.hasVisibleContent);
+ });
+
+ test('filteredCounters', function() {
+ const model = new tr.Model();
+ const c1 = model.kernel.getOrCreateCpu(0);
+ c1.getOrCreateCounter('', 'b');
+
+ const p1 = model.getOrCreateProcess(1);
+ const ctr = p1.getOrCreateCounter('', 'a');
+ const series = new tr.model.CounterSeries('a', 0);
+ series.addCounterSample(0, 1);
+ ctr.addSeries(series);
+
+ const timeline = document.createElement('tr-ui-timeline-track-view');
+ timeline.model = model;
+
+ assert.isTrue(timeline.hasVisibleContent);
+ });
+
+ test('filteredCpus', function() {
+ const model = new tr.Model();
+ const c1 = model.kernel.getOrCreateCpu(1);
+ c1.getOrCreateCounter('', 'a');
+
+ const timeline = document.createElement('tr-ui-timeline-track-view');
+ timeline.model = model;
+
+ assert.isTrue(timeline.hasVisibleContent);
+ });
+
+ test('filteredProcesses', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ p1.getOrCreateCounter('', 'a');
+
+ const timeline = document.createElement('tr-ui-timeline-track-view');
+ timeline.model = model;
+
+ assert.isTrue(timeline.hasVisibleContent);
+ });
+
+ test('filteredThreads', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(2);
+ t1.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({start: 0, duration: 1}));
+
+ const timeline = document.createElement('tr-ui-timeline-track-view');
+ timeline.model = model;
+
+ assert.isTrue(timeline.hasVisibleContent);
+ });
+
+ test('interestRange', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'b', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'c', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'c', args: {}, pid: 52, ts: 629, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+ const model = tr.c.TestUtils.newModelWithEvents([events]);
+ const trackView = document.createElement('tr-ui-timeline-track-view');
+ trackView.model = model;
+ this.addHTMLOutput(trackView);
+
+ const slice = model.processes[52].threads[53].sliceGroup.slices[2];
+ trackView.viewport.interestRange.setMinAndMax(slice.start, slice.end);
+ });
+
+ test('emptyInterestRange', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'b', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'c', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'c', args: {}, pid: 52, ts: 629, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+ const model = tr.c.TestUtils.newModelWithEvents([events]);
+ const trackView = document.createElement('tr-ui-timeline-track-view');
+ trackView.model = model;
+ this.addHTMLOutput(trackView);
+ trackView.viewport.interestRange.reset();
+ });
+
+
+ test('thinnestInterestRange', function() {
+ const events = [
+ {name: 'a', args: {}, pid: 52, ts: 520, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'b', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'c', args: {}, pid: 52, ts: 560, cat: 'foo', tid: 53, ph: 'B'},
+ {name: 'c', args: {}, pid: 52, ts: 629, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'b', args: {}, pid: 52, ts: 631, cat: 'foo', tid: 53, ph: 'E'},
+ {name: 'a', args: {}, pid: 52, ts: 634, cat: 'foo', tid: 53, ph: 'E'}
+ ];
+ const model = tr.c.TestUtils.newModelWithEvents([events]);
+ const trackView = document.createElement('tr-ui-timeline-track-view');
+ trackView.model = model;
+ this.addHTMLOutput(trackView);
+ trackView.viewport.interestRange.reset();
+
+ const slice = model.processes[52].threads[53].sliceGroup.slices[2];
+ trackView.viewport.interestRange.setMinAndMax(slice.start, slice.start);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html
new file mode 100644
index 00000000000..9a7a83f4a7b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view.html
@@ -0,0 +1,641 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/settings.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/scripting_controller.html">
+<link rel="import" href="/tracing/metrics/all_metrics.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_view.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<link rel="import" href="/tracing/ui/base/dropdown.html">
+<link rel="import" href="/tracing/ui/base/favicons.html">
+<link rel="import" href="/tracing/ui/base/hotkey_controller.html">
+<link rel="import" href="/tracing/ui/base/info_bar_group.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+<link rel="import" href="/tracing/ui/base/toolbar_button.html">
+<link rel="import" href="/tracing/ui/base/utils.html">
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+<link rel="import" href="/tracing/ui/find_control.html">
+<link rel="import" href="/tracing/ui/find_controller.html">
+<link rel="import" href="/tracing/ui/scripting_control.html">
+<link rel="import" href="/tracing/ui/side_panel/side_panel_container.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+<link rel="import" href="/tracing/ui/timeline_view_help_overlay.html">
+<link rel="import" href="/tracing/ui/timeline_view_metadata_overlay.html">
+<link rel="import" href="/tracing/value/ui/preferred_display_unit.html">
+
+<dom-module id='tr-ui-timeline-view'>
+ <template>
+ <style>
+ :host {
+ flex-direction: column;
+ cursor: default;
+ display: flex;
+ font-family: sans-serif;
+ padding: 0;
+ }
+
+ #control {
+ background-color: #e6e6e6;
+ background-image: -webkit-gradient(linear, 0 0, 0 100%,
+ from(#E5E5E5), to(#D1D1D1));
+ flex: 0 0 auto;
+ overflow-x: auto;
+ }
+
+ #control::-webkit-scrollbar { height: 0px; }
+
+ #control > #bar {
+ font-size: 12px;
+ display: flex;
+ flex-direction: row;
+ margin: 1px;
+ }
+
+ #control > #bar > #title {
+ display: flex;
+ align-items: center;
+ padding-left: 8px;
+ padding-right: 8px;
+ flex: 1 1 auto;
+ }
+
+ #control > #bar > #left_controls,
+ #control > #bar > #right_controls {
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+ }
+
+ #control > #bar > #left_controls > * { margin-right: 2px; }
+ #control > #bar > #right_controls > * { margin-left: 2px; }
+ #control > #collapsing_controls { display: flex; }
+
+ middle-container {
+ flex: 1 1 auto;
+ flex-direction: row;
+ border-bottom: 1px solid #8e8e8e;
+ display: flex;
+ min-height: 0;
+ }
+
+ middle-container ::content track-view-container {
+ flex: 1 1 auto;
+ display: flex;
+ min-height: 0;
+ min-width: 0;
+ overflow-x: hidden;
+ }
+
+ middle-container ::content track-view-container > * { flex: 1 1 auto; }
+ middle-container > x-timeline-view-side-panel-container { flex: 0 0 auto; }
+ tr-ui-b-drag-handle { flex: 0 0 auto; }
+ tr-ui-a-analysis-view { flex: 0 0 auto; }
+
+ #view_options_dropdown, #process_filter_dropdown {
+ --dropdown-button: {
+ -webkit-appearance: none;
+ align-items: normal;
+ background-color: rgb(248, 248, 248);
+ border: 1px solid rgba(0, 0, 0, 0.5);
+ box-sizing: content-box;
+ color: rgba(0, 0, 0, 0.8);
+ font-family: sans-serif;
+ font-size: 12px;
+ padding: 2px 5px;
+ }
+ }
+ </style>
+
+ <tv-ui-b-hotkey-controller id="hkc"></tv-ui-b-hotkey-controller>
+ <div id="control">
+ <div id="bar">
+ <div id="left_controls"></div>
+ <div id="title">^_^</div>
+ <div id="right_controls">
+ <tr-ui-b-dropdown id="process_filter_dropdown" label="Processes"></tr-ui-b-dropdown>
+ <tr-ui-b-toolbar-button id="view_metadata_button">
+ M
+ </tr-ui-b-toolbar-button>
+ <tr-ui-b-dropdown id="view_options_dropdown" label="View Options"></tr-ui-b-dropdown>
+ <tr-ui-find-control id="view_find_control"></tr-ui-find-control>
+ <tr-ui-b-toolbar-button id="view_console_button">
+ &#187;
+ </tr-ui-b-toolbar-button>
+ <tr-ui-b-toolbar-button id="view_help_button">
+ ?
+ </tr-ui-b-toolbar-button>
+ </div>
+ </div>
+ <div id="collapsing_controls"></div>
+ <tr-ui-b-info-bar-group id="import-warnings">
+ </tr-ui-b-info-bar-group>
+ </div>
+ <middle-container>
+ <slot></slot>
+
+ <tr-ui-side-panel-container id="side_panel_container">
+ </tr-ui-side-panel-container>
+ </middle-container>
+ <tr-ui-b-drag-handle id="drag_handle"></tr-ui-b-drag-handle>
+ <tr-ui-a-analysis-view id="analysis"></tr-ui-a-analysis-view>
+
+ <tr-v-ui-preferred-display-unit id="display_unit">
+ </tr-v-ui-preferred-display-unit>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-timeline-view',
+
+ created() {
+ this.trackViewContainer_ = undefined;
+
+ this.queuedModel_ = undefined;
+
+ this.builtPromise_ = undefined;
+ this.doneBuilding_ = undefined;
+ },
+
+ attached() {
+ this.async(function() {
+ this.trackViewContainer_ = Polymer.dom(this).querySelector(
+ '#track_view_container');
+ if (!this.trackViewContainer_) {
+ throw new Error('missing trackviewContainer');
+ }
+
+ if (this.queuedModel_) this.updateContents_();
+ });
+ },
+
+ ready() {
+ this.tabIndex = 0; // Let the timeline able to receive key events.
+
+ this.titleEl_ = this.$.title;
+ this.leftControlsEl_ = this.$.left_controls;
+ this.rightControlsEl_ = this.$.right_controls;
+ this.collapsingControlsEl_ = this.$.collapsing_controls;
+ this.sidePanelContainer_ = this.$.side_panel_container;
+
+ this.brushingStateController_ = new tr.c.BrushingStateController(this);
+
+ this.findCtl_ = this.$.view_find_control;
+ this.findCtl_.controller = new tr.ui.FindController(
+ this.brushingStateController_);
+
+ this.scriptingCtl_ = document.createElement('tr-ui-scripting-control');
+ this.scriptingCtl_.controller = new tr.c.ScriptingController(
+ this.brushingStateController_);
+
+ this.sidePanelContainer_.brushingStateController =
+ this.brushingStateController_;
+
+ if (window.tr.metrics && window.tr.metrics.sh &&
+ window.tr.metrics.sh.SystemHealthMetric) {
+ this.railScoreSpan_ = document.createElement(
+ 'tr-metrics-ui-sh-system-health-span');
+ Polymer.dom(this.rightControls).appendChild(this.railScoreSpan_);
+ } else {
+ this.railScoreSpan_ = undefined;
+ }
+
+ this.processFilter_ = this.$.process_filter_dropdown;
+
+ this.optionsDropdown_ = this.$.view_options_dropdown;
+ Polymer.dom(this.optionsDropdown_.iconElement).textContent = 'View Options';
+
+ this.showFlowEvents_ = false;
+ Polymer.dom(this.optionsDropdown_).appendChild(tr.ui.b.createCheckBox(
+ this, 'showFlowEvents',
+ 'tr.ui.TimelineView.showFlowEvents', false,
+ 'Flow events'));
+ this.highlightVSync_ = false;
+ this.highlightVSyncCheckbox_ = tr.ui.b.createCheckBox(
+ this, 'highlightVSync',
+ 'tr.ui.TimelineView.highlightVSync', false,
+ 'Highlight VSync');
+ Polymer.dom(this.optionsDropdown_).appendChild(
+ this.highlightVSyncCheckbox_);
+
+ this.initMetadataButton_();
+ this.initConsoleButton_();
+ this.initHelpButton_();
+
+ Polymer.dom(this.collapsingControls).appendChild(this.scriptingCtl_);
+
+ this.dragEl_ = this.$.drag_handle;
+
+ this.analysisEl_ = this.$.analysis;
+ this.analysisEl_.brushingStateController = this.brushingStateController_;
+
+ this.addEventListener(
+ 'requestSelectionChange',
+ function(e) {
+ const sc = this.brushingStateController_;
+ sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);
+ }.bind(this));
+
+ // Bookkeeping.
+ this.onViewportChanged_ = this.onViewportChanged_.bind(this);
+ this.bindKeyListeners_();
+
+ this.dragEl_.target = this.analysisEl_;
+ },
+
+ get globalMode() {
+ return this.hotkeyController.globalMode;
+ },
+
+ set globalMode(globalMode) {
+ globalMode = !!globalMode;
+ this.brushingStateController_.historyEnabled = globalMode;
+ this.hotkeyController.globalMode = globalMode;
+ },
+
+ get hotkeyController() {
+ return this.$.hkc;
+ },
+
+ updateDocumentFavicon() {
+ let hue;
+ if (!this.model) {
+ hue = 'blue';
+ } else {
+ hue = this.model.faviconHue;
+ }
+
+ let faviconData = tr.ui.b.FaviconsByHue[hue];
+ if (faviconData === undefined) {
+ faviconData = tr.ui.b.FaviconsByHue.blue;
+ }
+
+ // Find link if its there
+ let link = Polymer.dom(document.head).querySelector(
+ 'link[rel="shortcut icon"]');
+ if (!link) {
+ link = document.createElement('link');
+ link.rel = 'shortcut icon';
+ Polymer.dom(document.head).appendChild(link);
+ }
+ link.href = faviconData;
+ },
+
+ get showFlowEvents() {
+ return this.showFlowEvents_;
+ },
+
+ set showFlowEvents(showFlowEvents) {
+ this.showFlowEvents_ = showFlowEvents;
+ if (!this.trackView_) return;
+
+ this.trackView_.viewport.showFlowEvents = showFlowEvents;
+ },
+
+ get highlightVSync() {
+ return this.highlightVSync_;
+ },
+
+ set highlightVSync(highlightVSync) {
+ this.highlightVSync_ = highlightVSync;
+ if (!this.trackView_) return;
+
+ this.trackView_.viewport.highlightVSync = highlightVSync;
+ },
+
+ initHelpButton_() {
+ const helpButtonEl = this.$.view_help_button;
+
+ const dlg = new tr.ui.b.Overlay();
+ dlg.title = 'Chrome Tracing Help';
+ dlg.visible = false;
+ dlg.appendChild(
+ document.createElement('tr-ui-timeline-view-help-overlay'));
+
+ function onClick(e) {
+ dlg.visible = !dlg.visible;
+ // Stop event so it doesn't trigger new click listener on document.
+ e.stopPropagation();
+ }
+
+ helpButtonEl.addEventListener('click', onClick.bind(this));
+ },
+
+ initConsoleButton_() {
+ const toggleEl = this.$.view_console_button;
+
+ function onClick(e) {
+ this.scriptingCtl_.toggleVisibility();
+ e.stopPropagation();
+ return false;
+ }
+ toggleEl.addEventListener('click', onClick.bind(this));
+ },
+
+ initMetadataButton_() {
+ const showEl = this.$.view_metadata_button;
+
+ function onClick(e) {
+ const dlg = new tr.ui.b.Overlay();
+ dlg.title = 'Metadata for trace';
+
+ const metadataOverlay = document.createElement(
+ 'tr-ui-timeline-view-metadata-overlay');
+ metadataOverlay.metadata = this.model.metadata;
+
+ Polymer.dom(dlg).appendChild(metadataOverlay);
+ dlg.visible = true;
+
+ e.stopPropagation();
+ return false;
+ }
+ showEl.addEventListener('click', onClick.bind(this));
+
+ this.updateMetadataButtonVisibility_();
+ },
+
+ updateMetadataButtonVisibility_() {
+ const showEl = this.$.view_metadata_button;
+ showEl.style.display =
+ (this.model && this.model.metadata.length) ? '' : 'none';
+ },
+
+ updateProcessList_() {
+ const dropdown = Polymer.dom(this.processFilter_);
+ while (dropdown.firstChild) {
+ dropdown.removeChild(dropdown.firstChild);
+ }
+ if (!this.model) return;
+
+ const trackView =
+ this.trackViewContainer_.querySelector('tr-ui-timeline-track-view');
+ const processViews = trackView.processViews;
+ const cboxes = [];
+ const updateAll = (checked) => {
+ for (const cbox of cboxes) {
+ cbox.checked = checked;
+ }
+ };
+
+ dropdown.appendChild(tr.ui.b.createButton('All', () => updateAll(true)));
+ dropdown.appendChild(tr.ui.b.createButton('None', () => updateAll(false)));
+
+ for (const view of processViews) {
+ const cbox = tr.ui.b.createCheckBox(undefined, undefined, undefined,
+ true, view.processBase.userFriendlyName,
+ () => view.visible = cbox.checked);
+ cbox.checked = view.visible;
+ cboxes.push(cbox);
+ view.addEventListener('visibility', () => cbox.checked = view.visible);
+ dropdown.appendChild(cbox);
+ }
+ },
+
+ get leftControls() {
+ return this.leftControlsEl_;
+ },
+
+ get rightControls() {
+ return this.rightControlsEl_;
+ },
+
+ get collapsingControls() {
+ return this.collapsingControlsEl_;
+ },
+
+ get viewTitle() {
+ return Polymer.dom(this.titleEl_).textContent.substring(
+ Polymer.dom(this.titleEl_).textContent.length - 2);
+ },
+
+ set viewTitle(text) {
+ if (text === undefined) {
+ Polymer.dom(this.titleEl_).textContent = '';
+ this.titleEl_.hidden = true;
+ return;
+ }
+ this.titleEl_.hidden = false;
+ Polymer.dom(this.titleEl_).textContent = text;
+ },
+
+ get model() {
+ if (this.trackView_) {
+ return this.trackView_.model;
+ }
+ return undefined;
+ },
+
+ set model(model) {
+ this.build(model);
+ },
+
+ async build(model) {
+ this.queuedModel_ = model;
+ this.builtPromise_ = new Promise((resolve, reject) => {
+ this.doneBuilding_ = resolve;
+ });
+ if (this.trackViewContainer_) await this.updateContents_();
+ },
+
+ get builtPromise() {
+ return this.builtPromise_;
+ },
+
+ async updateContents_() {
+ if (this.trackViewContainer_ === undefined) {
+ throw new Error(
+ 'timeline-view.updateContents_ requires trackViewContainer_');
+ }
+
+ const model = this.queuedModel_;
+ this.queuedModel_ = undefined;
+
+ const modelInstanceChanged = model !== this.model;
+ const modelValid = model && !model.bounds.isEmpty;
+
+ const importWarningsEl = Polymer.dom(this.root).querySelector(
+ '#import-warnings');
+ Polymer.dom(importWarningsEl).textContent = '';
+
+ // Remove old trackView if the model has completely changed.
+ if (modelInstanceChanged) {
+ if (this.railScoreSpan_) {
+ this.railScoreSpan_.model = undefined;
+ }
+ Polymer.dom(this.trackViewContainer_).textContent = '';
+ if (this.trackView_) {
+ this.trackView_.viewport.removeEventListener(
+ 'change', this.onViewportChanged_);
+ this.trackView_.brushingStateController = undefined;
+ this.trackView_.detach();
+ this.trackView_ = undefined;
+ }
+ this.brushingStateController_.modelWillChange();
+ }
+
+ // Create new trackView if needed.
+ if (modelValid && !this.trackView_) {
+ this.trackView_ = document.createElement('tr-ui-timeline-track-view');
+ this.trackView_.timelineView = this;
+
+ this.trackView.brushingStateController = this.brushingStateController_;
+
+ Polymer.dom(this.trackViewContainer_).appendChild(this.trackView_);
+ this.trackView_.viewport.addEventListener(
+ 'change', this.onViewportChanged_);
+ }
+
+ // Set the model.
+ if (modelValid) {
+ this.trackView_.model = model;
+ this.trackView_.viewport.showFlowEvents = this.showFlowEvents;
+ this.trackView_.viewport.highlightVSync = this.highlightVSync;
+ if (this.railScoreSpan_) {
+ this.railScoreSpan_.model = model;
+ }
+
+ this.$.display_unit.preferredTimeDisplayMode = model.intrinsicTimeUnit;
+ }
+
+ if (model) {
+ for (const warning of model.importWarningsThatShouldBeShownToUser) {
+ importWarningsEl.addMessage(
+ `Import Warning: ${warning.type}: ${warning.message}`, [{
+ buttonText: 'Dismiss',
+ onClick(event, infobar) {
+ infobar.visible = false;
+ }
+ }]);
+ }
+ }
+
+ // Do things that are selection specific
+ if (modelInstanceChanged) {
+ this.updateProcessList_();
+ this.updateMetadataButtonVisibility_();
+ this.brushingStateController_.modelDidChange();
+ this.onViewportChanged_();
+ }
+
+ this.doneBuilding_();
+ },
+
+ get brushingStateController() {
+ return this.brushingStateController_;
+ },
+
+ get trackView() {
+ return this.trackView_;
+ },
+
+ get settings() {
+ if (!this.settings_) {
+ this.settings_ = new tr.b.Settings();
+ }
+ return this.settings_;
+ },
+
+ /**
+ * Deprecated. Kept around because third_party code occasionally calls
+ * this to set up embedding.
+ */
+ set focusElement(value) {
+ throw new Error('This is deprecated. Please set globalMode to true.');
+ },
+
+ bindKeyListeners_() {
+ const hkc = this.hotkeyController;
+
+ // Shortcuts that *can* steal focus from the console and the filter text
+ // box.
+ hkc.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keypress',
+ keyCode: '`'.charCodeAt(0),
+ useCapture: true,
+ thisArg: this,
+ callback(e) {
+ this.scriptingCtl_.toggleVisibility();
+ if (!this.scriptingCtl_.hasFocus) {
+ this.focus();
+ }
+ e.stopPropagation();
+ }
+ }));
+
+ // Shortcuts that *can* steal focus from the filter text box.
+ hkc.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keypress',
+ keyCode: '/'.charCodeAt(0),
+ useCapture: true,
+ thisArg: this,
+ callback(e) {
+ if (this.scriptingCtl_.hasFocus) return;
+
+ if (this.findCtl_.hasFocus) {
+ this.focus();
+ } else {
+ this.findCtl_.focus();
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }));
+
+ // Shortcuts that *can't* steal focus.
+ hkc.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keypress',
+ keyCode: '?'.charCodeAt(0),
+ useCapture: false,
+ thisArg: this,
+ callback(e) {
+ this.$.view_help_button.click();
+ e.stopPropagation();
+ }
+ }));
+
+ hkc.addHotKey(new tr.ui.b.HotKey({
+ eventType: 'keypress',
+ keyCode: 'v'.charCodeAt(0),
+ useCapture: false,
+ thisArg: this,
+ callback(e) {
+ this.toggleHighlightVSync_();
+ e.stopPropagation();
+ }
+ }));
+ },
+
+ onViewportChanged_(e) {
+ const spc = this.sidePanelContainer_;
+ if (!this.trackView_) {
+ spc.rangeOfInterest.reset();
+ return;
+ }
+
+ const vr = this.trackView_.viewport.interestRange.asRangeObject();
+ if (!spc.rangeOfInterest.equals(vr)) {
+ spc.rangeOfInterest = vr;
+ }
+
+ if (this.railScoreSpan_ && this.model) {
+ this.railScoreSpan_.model = this.model;
+ }
+ },
+
+ toggleHighlightVSync_() {
+ this.highlightVSyncCheckbox_.checked =
+ !this.highlightVSyncCheckbox_.checked;
+ },
+
+ setFindCtlText(string) {
+ this.findCtl_.setText(string);
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_help_overlay.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_help_overlay.html
new file mode 100644
index 00000000000..48c2e72df76
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_help_overlay.html
@@ -0,0 +1,245 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_icon.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+
+<dom-module id='tr-ui-timeline-view-help-overlay'>
+ <template>
+ <style>
+ :host {
+ flex: 1 1 auto;
+ flex-direction: row;
+ display: flex;
+ width: 700px;
+ }
+ .column {
+ width: 50%;
+ }
+ h2 {
+ font-size: 1.2em;
+ margin: 0;
+ margin-top: 5px;
+ text-align: center;
+ }
+ h3 {
+ margin: 0;
+ margin-left: 126px;
+ margin-top: 10px;
+ }
+ .pair {
+ flex: 1 1 auto;
+ flex-direction: row;
+ display: flex;
+ }
+ .command {
+ font-family: monospace;
+ margin-right: 5px;
+ text-align: right;
+ width: 150px;
+ }
+ .action {
+ font-size: 0.9em;
+ text-align: left;
+ width: 200px;
+ }
+ tr-ui-b-mouse-mode-icon {
+ border: 1px solid #888;
+ border-radius: 3px;
+ box-shadow: inset 0 0 2px rgba(0,0,0,0.3);
+ display: inline-block;
+ margin-right: 1px;
+ position: relative;
+ top: 4px;
+ }
+ .mouse-mode-icon.pan-mode {
+ background-position: -1px -11px;
+ }
+ .mouse-mode-icon.select-mode {
+ background-position: -1px -41px;
+ }
+ .mouse-mode-icon.zoom-mode {
+ background-position: -1px -71px;
+ }
+ .mouse-mode-icon.timing-mode {
+ background-position: -1px -101px;
+ }
+ </style>
+ <div class="column left">
+ <h2>Navigation</h2>
+ <div class='pair'>
+ <div class='command'>w/s</div>
+ <div class='action'>Zoom in/out (+shift: faster)</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>a/d</div>
+ <div class='action'>Pan left/right (+shift: faster)</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>&rarr;/shift-TAB</div>
+ <div class='action'>Select previous event</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>&larr;/TAB</div>
+ <div class='action'>Select next event</div>
+ </div>
+
+ <h2>Mouse Controls</h2>
+ <div class='pair'>
+ <div class='command'>click</div>
+ <div class='action'>Select event</div>
+ </div>
+ <div class='pair'>
+ <div class='command'>alt-mousewheel</div>
+ <div class='action'>Zoom in/out</div>
+ </div>
+
+ <h3>
+ <tr-ui-b-mouse-mode-icon mode-name="SELECTION"></tr-ui-b-mouse-mode-icon>
+ Select mode
+ </h3>
+ <div class='pair'>
+ <div class='command'>drag</div>
+ <div class='action'>Box select</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'><span class='mod'></span>-click/drag</div>
+ <div class='action'>Add events to the current selection</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>double click</div>
+ <div class='action'>Select all events with same title</div>
+ </div>
+
+ <h3>
+ <tr-ui-b-mouse-mode-icon mode-name="PANSCAN"></tr-ui-b-mouse-mode-icon>
+ Pan mode
+ </h3>
+ <div class='pair'>
+ <div class='command'>drag</div>
+ <div class='action'>Pan the view</div>
+ </div>
+
+ <h3>
+ <tr-ui-b-mouse-mode-icon mode-name="ZOOM"></tr-ui-b-mouse-mode-icon>
+ Zoom mode
+ </h3>
+ <div class='pair'>
+ <div class='command'>drag</div>
+ <div class='action'>Zoom in/out by dragging up/down</div>
+ </div>
+
+ <h3>
+ <tr-ui-b-mouse-mode-icon mode-name="TIMING"></tr-ui-b-mouse-mode-icon>
+ Timing mode
+ </h3>
+ <div class='pair'>
+ <div class='command'>drag</div>
+ <div class='action'>Create or move markers</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>double click</div>
+ <div class='action'>Set marker range to slice</div>
+ </div>
+ </div>
+
+ <div class="column right">
+ <h2>General</h2>
+ <div class='pair'>
+ <div class='command'>1-4</div>
+ <div class='action'>Switch mouse mode</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>shift</div>
+ <div class='action'>Hold for temporary select</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>space</div>
+ <div class='action'>Hold for temporary pan</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>/</div>
+ <div class='action'>Search</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>enter</div>
+ <div class='action'>Step through search results</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>f</div>
+ <div class='action'>Zoom into selection</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>z/0</div>
+ <div class='action'>Reset zoom and pan</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>g/G</div>
+ <div class='action'>Toggle 60hz grid</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>v</div>
+ <div class='action'>Highlight VSync</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>h</div>
+ <div class='action'>Toggle low/high details</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>m</div>
+ <div class='action'>Mark current selection</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>p</div>
+ <div class='action'>Select power samples over current selection interval</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>`</div>
+ <div class='action'>Show or hide the scripting console</div>
+ </div>
+
+ <div class='pair'>
+ <div class='command'>?</div>
+ <div class='action'>Show help</div>
+ </div>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-timeline-view-help-overlay',
+
+ ready() {
+ const mod = tr.isMac ? 'cmd ' : 'ctrl';
+ const spans = Polymer.dom(this.root).querySelectorAll(
+ 'span.mod');
+ for (let i = 0; i < spans.length; i++) {
+ Polymer.dom(spans[i]).textContent = mod;
+ }
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_help_overlay_test.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_help_overlay_test.html
new file mode 100644
index 00000000000..1b705eea28c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_help_overlay_test.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/timeline_view_help_overlay.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('inactive', function() {
+ const el = document.createElement('tr-ui-timeline-view-help-overlay');
+ this.addHTMLOutput(el);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_metadata_overlay.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_metadata_overlay.html
new file mode 100644
index 00000000000..45f0efa1a2a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_metadata_overlay.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/ui/base/mouse_mode_icon.html">
+<link rel="import" href="/tracing/ui/base/overlay.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+
+<dom-module id='tr-ui-timeline-view-metadata-overlay'>
+ <template>
+ <style>
+ :host {
+ width: 700px;
+
+ overflow: auto;
+ }
+ </style>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-timeline-view-metadata-overlay',
+
+ created() {
+ this.metadata_ = undefined;
+ },
+
+ ready() {
+ this.$.table.tableColumns = [
+ {
+ title: 'name',
+ value: d => d.name,
+ },
+ {
+ title: 'value',
+ value: d => {
+ const gov = document.createElement('tr-ui-a-generic-object-view');
+ gov.object = d.value;
+ return gov;
+ },
+ }
+ ];
+ },
+
+ get metadata() {
+ return this.metadata_;
+ },
+
+ set metadata(metadata) {
+ this.metadata_ = metadata;
+ this.$.table.tableRows = this.metadata_;
+ this.$.table.rebuild();
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_metadata_overlay_test.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_metadata_overlay_test.html
new file mode 100644
index 00000000000..82f974ac7e9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_metadata_overlay_test.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/ui/timeline_view_metadata_overlay.html">
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('inactive', function() {
+ const el = document.createElement('tr-ui-timeline-view-metadata-overlay');
+ el.metadata = [
+ {
+ name: 'clientInfo',
+ value: {
+ command_line: './out/Release/Chromium.app/Contents/MacOS/Chromium --enable-threaded-compositing --force-compositing-mode --enable-impl-side-painting --enable-skia-benchmarking --allow-webui-compositing --flag-switches-begin --force-compositing-mode --disable-threaded-compositing --flag-switches-end', // @suppress longLineCheck
+ version: 'Chrome/29.0.1521.0'
+ }
+ },
+ {
+ name: 'somethingElse',
+ value: 'fascinating!'
+ }
+ ];
+
+ this.addHTMLOutput(el);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_test.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_test.html
new file mode 100644
index 00000000000..7591f82df77
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_view_test.html
@@ -0,0 +1,217 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Task = tr.b.Task;
+
+ function setupTimeline() {
+ const container = document.createElement('track-view-container');
+ container.id = 'track_view_container';
+
+ const view = document.createElement('tr-ui-timeline-view');
+ Polymer.dom(view).appendChild(container);
+ view.trackViewContainer_ = container;
+ return view;
+ }
+
+ const createFullyPopulatedModel = function(opt_withError, opt_withMetadata) {
+ const withError = opt_withError !== undefined ? opt_withError : true;
+ const withMetadata = opt_withMetadata !== undefined ?
+ opt_withMetadata : true;
+
+ const numTests = 50;
+ let testIndex = 0;
+ const startTime = 0;
+
+ const model = new tr.Model();
+ const io = new tr.importer.ImportOptions();
+ model.importOptions = io;
+
+ const cpu = model.kernel.getOrCreateCpu(0);
+ cpu.getOrCreateCounter('Category Name', 'Counter Name Here');
+ cpu.createSubSlices();
+
+ for (testIndex = 0; testIndex < numTests; ++testIndex) {
+ const process = model.getOrCreateProcess(10000 + testIndex);
+ if (testIndex % 2 === 0) {
+ const thread = process.getOrCreateThread('Thread Name Here');
+ thread.sliceGroup.pushSlice(new tr.model.ThreadSlice(
+ 'foo', 'a', 0, startTime, {}, 1));
+ thread.sliceGroup.pushSlice(new tr.model.ThreadSlice(
+ 'bar', 'b', 0, startTime + 23, {}, 10));
+ } else {
+ const thread = process.getOrCreateThread('Name');
+ thread.sliceGroup.pushSlice(new tr.model.ThreadSlice(
+ 'foo', 'a', 0, startTime + 4, {}, 11));
+ thread.sliceGroup.pushSlice(new tr.model.ThreadSlice(
+ 'bar', 'b', 0, startTime + 22, {}, 14));
+ }
+ }
+ const p1000 = model.getOrCreateProcess(1000);
+ const objects = p1000.objects;
+ objects.idWasCreated('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 10);
+ objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 10,
+ 'snapshot-1');
+ objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 25,
+ 'snapshot-2');
+ objects.addSnapshot('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 40,
+ 'snapshot-3');
+ objects.idWasDeleted('0x1000', 'tr.e.cc', 'LayerTreeHostImpl', 45);
+ model.updateCategories_();
+
+ // Add a known problematic piece of data to test the import errors UI.
+ model.importWarning({
+ type: 'test_error',
+ message: 'Synthetic Import Error',
+ showToUser: true,
+ });
+ model.updateBounds();
+
+ // Add data with metadata information stored
+ model.metadata.push({name: 'a', value: 'testA'});
+ model.metadata.push({name: 'b', value: 'testB'});
+ model.metadata.push({name: 'c', value: 'testC'});
+
+ return model;
+ };
+
+ const visibleTracks = function(trackButtons) {
+ return trackButtons.reduce(function(numVisible, button) {
+ const style = button.parentElement.style;
+ const visible = (style.display.indexOf('none') === -1);
+ return visible ? numVisible + 1 : numVisible;
+ }, 0);
+ };
+
+ const modelsEquivalent = function(lhs, rhs) {
+ if (lhs.length !== rhs.length) return false;
+
+ return lhs.every(function(lhsItem, index) {
+ const rhsItem = rhs[index];
+ return rhsItem.regexpText === lhsItem.regexpText &&
+ rhsItem.isOn === lhsItem.isOn;
+ });
+ };
+
+ test('instantiate', async function() {
+ const model11 = createFullyPopulatedModel(true, true);
+
+ const view = setupTimeline();
+ view.style.height = '400px';
+ view.style.border = '1px solid black';
+ view.model = model11;
+
+ const simpleButton1 = document.createElement('tr-ui-b-toolbar-button');
+ Polymer.dom(simpleButton1).textContent = 'M';
+ Polymer.dom(view.leftControls).appendChild(simpleButton1);
+
+ const simpleButton2 = document.createElement('tr-ui-b-toolbar-button');
+ Polymer.dom(simpleButton2).textContent = 'am button';
+ Polymer.dom(view.leftControls).appendChild(simpleButton2);
+
+ this.addHTMLOutput(view);
+ await view.builtPromise;
+ });
+
+ test('changeModelToSomethingDifferent', async function() {
+ const model00 = createFullyPopulatedModel(false, false);
+ const model11 = createFullyPopulatedModel(true, true);
+
+ const view = setupTimeline();
+ view.style.height = '400px';
+ view.model = model00;
+ view.model = undefined;
+ view.model = model11;
+ view.model = model00;
+
+ this.addHTMLOutput(view);
+ await view.builtPromise;
+ });
+
+ test('setModelToSameThingAgain', async function() {
+ const model = createFullyPopulatedModel(false, false);
+
+ // Create a view with a model.
+ const view = setupTimeline();
+ this.addHTMLOutput(view);
+ view.style.height = '400px';
+ view.model = model;
+ const sc = view.brushingStateController;
+
+ // Mutate the model and update the view.
+ const t123 = model.getOrCreateProcess(123).getOrCreateThread(123);
+ t123.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {title: 'somethingUnusual', start: 0, duration: 5}));
+ view.model = model;
+
+ await view.builtPromise;
+
+ // Verify that the new bits of the model show up in the view.
+ const selection = new tr.model.EventSet();
+ const filter = new tr.c.TitleOrCategoryFilter('somethingUnusual');
+ const filterTask = sc.addAllEventsMatchingFilterToSelectionAsTask(
+ filter, selection);
+ Task.RunSynchronously(filterTask);
+ assert.strictEqual(selection.length, 1);
+ });
+
+ test('setModelBeforeAttached', async function() {
+ const view = document.createElement('tr-ui-timeline-view');
+ view.style.height = '400px';
+ view.model = createFullyPopulatedModel(false, false);
+
+ const container = document.createElement('track-view-container');
+ container.id = 'track_view_container';
+ Polymer.dom(view).appendChild(container);
+ this.addHTMLOutput(view);
+ await view.builtPromise;
+ });
+
+ test('filterProcessesUI', async function() {
+ const view = document.createElement('tr-ui-timeline-view');
+ view.style.height = '400px';
+ view.model = createFullyPopulatedModel(false, false);
+
+ const container = document.createElement('track-view-container');
+ container.id = 'track_view_container';
+ Polymer.dom(view).appendChild(container);
+ this.addHTMLOutput(view);
+ await view.builtPromise;
+
+ const procFilter = Polymer.dom(view.processFilter_);
+ const checkboxes = procFilter.querySelectorAll('input[type=checkbox]');
+ assert.lengthOf(checkboxes, 52);
+
+ const trackView =
+ view.trackViewContainer_.querySelector('tr-ui-timeline-track-view');
+ const countVisibleTracks = () => trackView.processViews.filter(
+ view => view.visible).length;
+ assert.strictEqual(checkboxes.length, trackView.processViews.length);
+ assert.strictEqual(countVisibleTracks(), 52);
+ assert.isTrue(trackView.processViews[0].visible);
+
+ checkboxes[0].click();
+ assert.strictEqual(countVisibleTracks(), 51);
+ assert.isFalse(trackView.processViews[0].visible);
+ assert.isTrue(trackView.processViews[1].visible);
+
+ // Hide a track. Validate that the checkbox updated state correctly.
+ trackView.processViews[1].visible = false;
+ assert.isFalse(trackView.processViews[1].visible);
+ assert.isFalse(checkboxes[1].checked);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_viewport.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_viewport.html
new file mode 100644
index 00000000000..58dafb55aff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_viewport.html
@@ -0,0 +1,442 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/base/animation.html">
+<link rel="import" href="/tracing/ui/base/animation_controller.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/draw_helpers.html">
+<link rel="import" href="/tracing/ui/timeline_display_transform.html">
+<link rel="import" href="/tracing/ui/timeline_interest_range.html">
+<link rel="import" href="/tracing/ui/tracks/container_to_track_map.html">
+<link rel="import" href="/tracing/ui/tracks/event_to_track_map.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Code for the viewport.
+ */
+tr.exportTo('tr.ui', function() {
+ const TimelineDisplayTransform = tr.ui.TimelineDisplayTransform;
+ const TimelineInterestRange = tr.ui.TimelineInterestRange;
+
+ const IDEAL_MAJOR_MARK_DISTANCE_PX = 150;
+ // Keep 5 digits of precision when rounding the major mark distances.
+ const MAJOR_MARK_ROUNDING_FACTOR = 100000;
+
+ class AnimationControllerProxy {
+ constructor(target) {
+ this.target_ = target;
+ }
+
+ get panX() {
+ return this.target_.currentDisplayTransform_.panX;
+ }
+
+ set panX(panX) {
+ this.target_.currentDisplayTransform_.panX = panX;
+ }
+
+ get panY() {
+ return this.target_.currentDisplayTransform_.panY;
+ }
+
+ set panY(panY) {
+ this.target_.currentDisplayTransform_.panY = panY;
+ }
+
+ get scaleX() {
+ return this.target_.currentDisplayTransform_.scaleX;
+ }
+
+ set scaleX(scaleX) {
+ this.target_.currentDisplayTransform_.scaleX = scaleX;
+ }
+
+ cloneAnimationState() {
+ return this.target_.currentDisplayTransform_.clone();
+ }
+
+ xPanWorldPosToViewPos(xWorld, xView) {
+ this.target_.currentDisplayTransform_.xPanWorldPosToViewPos(
+ xWorld, xView, this.target_.modelTrackContainer_.canvas.clientWidth);
+ }
+ }
+
+ /**
+ * The TimelineViewport manages the transform used for navigating
+ * within the timeline. It is a simple transform:
+ * x' = (x+pan) * scale
+ *
+ * The timeline code tries to avoid directly accessing this transform,
+ * instead using this class to do conversion between world and viewspace,
+ * as well as the math for centering the viewport in various interesting
+ * ways.
+ *
+ * @constructor
+ * @extends {tr.b.EventTarget}
+ */
+ function TimelineViewport(parentEl) {
+ this.parentEl_ = parentEl;
+ this.modelTrackContainer_ = undefined;
+ this.currentDisplayTransform_ = new TimelineDisplayTransform();
+ this.initAnimationController_();
+
+ // Flow events
+ this.showFlowEvents_ = false;
+
+ // Highlights.
+ this.highlightVSync_ = false;
+
+ // High details.
+ this.highDetails_ = false;
+
+ // Grid system.
+ this.gridTimebase_ = 0;
+ this.gridStep_ = 1000 / 60;
+ this.gridEnabled_ = false;
+
+ // Init logic.
+ this.hasCalledSetupFunction_ = false;
+
+ this.onResize_ = this.onResize_.bind(this);
+ this.onModelTrackControllerScroll_ =
+ this.onModelTrackControllerScroll_.bind(this);
+
+ this.timeMode_ = TimelineViewport.TimeMode.TIME_IN_MS;
+ // Major mark positions are where the gridlines/ruler marks are placed along
+ // the x-axis.
+ this.majorMarkWorldPositions_ = [];
+ this.majorMarkUnit_ = undefined;
+ this.interestRange_ = new TimelineInterestRange(this);
+
+ this.eventToTrackMap_ = new tr.ui.tracks.EventToTrackMap();
+ this.containerToTrackMap = new tr.ui.tracks.ContainerToTrackMap();
+
+ this.dispatchChangeEvent = this.dispatchChangeEvent.bind(this);
+ }
+
+ TimelineViewport.TimeMode = {
+ TIME_IN_MS: 0,
+ REVISIONS: 1
+ };
+
+ TimelineViewport.prototype = {
+ __proto__: tr.b.EventTarget.prototype,
+
+ /**
+ * @return {boolean} Whether the current timeline is attached to the
+ * document.
+ */
+ get isAttachedToDocumentOrInTestMode() {
+ // Allow not providing a parent element, used by tests.
+ if (this.parentEl_ === undefined) return;
+ return tr.ui.b.isElementAttachedToDocument(this.parentEl_);
+ },
+
+ onResize_() {
+ this.dispatchChangeEvent();
+ },
+
+ /**
+ * Fires the change event on this viewport. Used to notify listeners
+ * to redraw when the underlying model has been mutated.
+ */
+ dispatchChangeEvent() {
+ tr.b.dispatchSimpleEvent(this, 'change');
+ },
+
+ detach() {
+ window.removeEventListener('resize', this.dispatchChangeEvent);
+ },
+
+ initAnimationController_() {
+ this.dtAnimationController_ = new tr.ui.b.AnimationController();
+ this.dtAnimationController_.addEventListener(
+ 'didtick', function(e) {
+ this.onCurentDisplayTransformChange_(e.oldTargetState);
+ }.bind(this));
+
+ this.dtAnimationController_.target = new AnimationControllerProxy(this);
+ },
+
+ get currentDisplayTransform() {
+ return this.currentDisplayTransform_;
+ },
+
+ setDisplayTransformImmediately(displayTransform) {
+ this.dtAnimationController_.cancelActiveAnimation();
+
+ const oldDisplayTransform =
+ this.dtAnimationController_.target.cloneAnimationState();
+ this.currentDisplayTransform_.set(displayTransform);
+ this.onCurentDisplayTransformChange_(oldDisplayTransform);
+ },
+
+ queueDisplayTransformAnimation(animation) {
+ if (!(animation instanceof tr.ui.b.Animation)) {
+ throw new Error('animation must be instanceof tr.ui.b.Animation');
+ }
+ this.dtAnimationController_.queueAnimation(animation);
+ },
+
+ onCurentDisplayTransformChange_(oldDisplayTransform) {
+ // Ensure panY stays clamped in the track container's scroll range.
+ if (this.modelTrackContainer_) {
+ this.currentDisplayTransform.panY = tr.b.math.clamp(
+ this.currentDisplayTransform.panY,
+ 0,
+ this.modelTrackContainer_.scrollHeight -
+ this.modelTrackContainer_.clientHeight);
+ }
+
+ const changed = !this.currentDisplayTransform.equals(oldDisplayTransform);
+ const yChanged = this.currentDisplayTransform.panY !==
+ oldDisplayTransform.panY;
+ if (yChanged) {
+ this.modelTrackContainer_.scrollTop = this.currentDisplayTransform.panY;
+ }
+ if (changed) {
+ this.dispatchChangeEvent();
+ }
+ },
+
+ onModelTrackControllerScroll_(e) {
+ if (this.dtAnimationController_.activeAnimation &&
+ this.dtAnimationController_.activeAnimation.affectsPanY) {
+ this.dtAnimationController_.cancelActiveAnimation();
+ }
+ const panY = this.modelTrackContainer_.scrollTop;
+ this.currentDisplayTransform_.panY = panY;
+ },
+
+ get modelTrackContainer() {
+ return this.modelTrackContainer_;
+ },
+
+ set modelTrackContainer(m) {
+ if (this.modelTrackContainer_) {
+ this.modelTrackContainer_.removeEventListener('scroll',
+ this.onModelTrackControllerScroll_);
+ }
+
+ this.modelTrackContainer_ = m;
+ this.modelTrackContainer_.addEventListener('scroll',
+ this.onModelTrackControllerScroll_);
+ },
+
+ get showFlowEvents() {
+ return this.showFlowEvents_;
+ },
+
+ set showFlowEvents(showFlowEvents) {
+ this.showFlowEvents_ = showFlowEvents;
+ this.dispatchChangeEvent();
+ },
+
+ get highlightVSync() {
+ return this.highlightVSync_;
+ },
+
+ set highlightVSync(highlightVSync) {
+ this.highlightVSync_ = highlightVSync;
+ this.dispatchChangeEvent();
+ },
+
+ get highDetails() {
+ return this.highDetails_;
+ },
+
+ set highDetails(highDetails) {
+ this.highDetails_ = highDetails;
+ this.dispatchChangeEvent();
+ },
+
+ get gridEnabled() {
+ return this.gridEnabled_;
+ },
+
+ set gridEnabled(enabled) {
+ if (this.gridEnabled_ === enabled) return;
+
+ this.gridEnabled_ = enabled && true;
+ this.dispatchChangeEvent();
+ },
+
+ get gridTimebase() {
+ return this.gridTimebase_;
+ },
+
+ set gridTimebase(timebase) {
+ if (this.gridTimebase_ === timebase) return;
+
+ this.gridTimebase_ = timebase;
+ this.dispatchChangeEvent();
+ },
+
+ get gridStep() {
+ return this.gridStep_;
+ },
+
+ get interestRange() {
+ return this.interestRange_;
+ },
+
+ get majorMarkWorldPositions() {
+ return this.majorMarkWorldPositions_;
+ },
+
+ get majorMarkUnit() {
+ switch (this.timeMode_) {
+ case TimelineViewport.TimeMode.TIME_IN_MS:
+ return tr.b.Unit.byName.timeInMsAutoFormat;
+ case TimelineViewport.TimeMode.REVISIONS:
+ return tr.b.Unit.byName.count;
+ default:
+ throw new Error(
+ 'Cannot get Unit for unsupported time mode ' + this.timeMode_);
+ }
+ },
+
+ get timeMode() {
+ return this.timeMode_;
+ },
+
+ set timeMode(mode) {
+ this.timeMode_ = mode;
+ this.dispatchChangeEvent();
+ },
+
+ updateMajorMarkData(viewLWorld, viewRWorld) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ const dt = this.currentDisplayTransform;
+
+ const idealMajorMarkDistancePix =
+ IDEAL_MAJOR_MARK_DISTANCE_PX * pixelRatio;
+ const idealMajorMarkDistanceWorld =
+ dt.xViewVectorToWorld(idealMajorMarkDistancePix);
+
+ const majorMarkDistanceWorld = tr.b.math.preferredNumberLargerThanMin(
+ idealMajorMarkDistanceWorld);
+
+ const firstMajorMark = Math.floor(
+ viewLWorld / majorMarkDistanceWorld) * majorMarkDistanceWorld;
+
+ this.majorMarkWorldPositions_ = [];
+ for (let curX = firstMajorMark;
+ curX < viewRWorld;
+ curX += majorMarkDistanceWorld) {
+ this.majorMarkWorldPositions_.push(
+ Math.floor(MAJOR_MARK_ROUNDING_FACTOR * curX) /
+ MAJOR_MARK_ROUNDING_FACTOR);
+ }
+ },
+
+ drawMajorMarkLines(ctx, viewHeight) {
+ // Apply subpixel translate to get crisp lines.
+ // http://www.mobtowers.com/html5-canvas-crisp-lines-every-time/
+ ctx.save();
+ ctx.translate((Math.round(ctx.lineWidth) % 2) / 2, 0);
+
+ ctx.beginPath();
+ for (const majorMark of this.majorMarkWorldPositions_) {
+ const x = this.currentDisplayTransform.xWorldToView(majorMark);
+ tr.ui.b.drawLine(ctx, x, 0, x, viewHeight);
+ }
+ ctx.strokeStyle = '#ddd';
+ ctx.stroke();
+
+ ctx.restore();
+ },
+
+ drawGridLines(ctx, viewLWorld, viewRWorld, viewHeight) {
+ if (!this.gridEnabled) return;
+
+ const dt = this.currentDisplayTransform;
+ let x = this.gridTimebase;
+
+ // Apply subpixel translate to get crisp lines.
+ // http://www.mobtowers.com/html5-canvas-crisp-lines-every-time/
+ ctx.save();
+ ctx.translate((Math.round(ctx.lineWidth) % 2) / 2, 0);
+
+ ctx.beginPath();
+ while (x < viewRWorld) {
+ if (x >= viewLWorld) {
+ // Do conversion to viewspace here rather than on
+ // x to avoid precision issues.
+ const vx = Math.floor(dt.xWorldToView(x));
+ tr.ui.b.drawLine(ctx, vx, 0, vx, viewHeight);
+ }
+
+ x += this.gridStep;
+ }
+ ctx.strokeStyle = 'rgba(255, 0, 0, 0.25)';
+ ctx.stroke();
+
+ ctx.restore();
+ },
+
+ /**
+ * Helper for selection previous or next.
+ * @param {boolean} offset If positive, select one forward (next).
+ * Else, select previous.
+ *
+ * @return {boolean} true if current selection changed.
+ */
+ getShiftedSelection(selection, offset) {
+ const newSelection = new tr.model.EventSet();
+ for (const event of selection) {
+ // If this is a flow event, then move to its slice based on the
+ // offset direction.
+ if (event instanceof tr.model.FlowEvent) {
+ if (offset > 0) {
+ newSelection.push(event.endSlice);
+ } else if (offset < 0) {
+ newSelection.push(event.startSlice);
+ } else {
+ /* Do nothing. Zero offsets don't do anything. */
+ }
+ continue;
+ }
+
+ const track = this.trackForEvent(event);
+ track.addEventNearToProvidedEventToSelection(
+ event, offset, newSelection);
+ }
+
+ if (newSelection.length === 0) return undefined;
+
+ return newSelection;
+ },
+
+ rebuildEventToTrackMap() {
+ // TODO(charliea): Make the event to track map have a similar interface
+ // to the container to track map so that we can just clear() here.
+ this.eventToTrackMap_ = new tr.ui.tracks.EventToTrackMap();
+ this.modelTrackContainer_.addEventsToTrackMap(this.eventToTrackMap_);
+ },
+
+ rebuildContainerToTrackMap() {
+ this.containerToTrackMap.clear();
+ this.modelTrackContainer_.addContainersToTrackMap(
+ this.containerToTrackMap);
+ },
+
+ trackForEvent(event) {
+ return this.eventToTrackMap_[event.guid];
+ }
+ };
+
+ return {
+ TimelineViewport,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/timeline_viewport_test.html b/chromium/third_party/catapult/tracing/tracing/ui/timeline_viewport_test.html
new file mode 100644
index 00000000000..5715182e720
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/timeline_viewport_test.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/location.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/base/constants.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/slice_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Location = tr.model.Location;
+ const Model = tr.Model;
+
+ test('memoization', function() {
+ const vp = new tr.ui.TimelineViewport(document.createElement('div'));
+
+ const slice = { guid: 1 };
+
+ vp.modelTrackContainer = {
+ addEventsToTrackMap(eventToTrackMap) {
+ eventToTrackMap.addEvent(slice, 'track');
+ },
+ addEventListener() {}
+ };
+
+ assert.isUndefined(vp.trackForEvent(slice));
+ vp.rebuildEventToTrackMap();
+
+ assert.strictEqual(vp.trackForEvent(slice), 'track');
+ });
+
+ test('shiftedSelection', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 1, {}, 3));
+ t1.sliceGroup.pushSlice(
+ new tr.model.ThreadSlice('', 'a', 0, 5, {}, 1));
+
+ const viewport = new tr.ui.TimelineViewport();
+ const track = new tr.ui.tracks.SliceTrack(viewport);
+ viewport.modelTrackContainer = track;
+ track.slices = t1.sliceGroup.slices;
+
+ viewport.rebuildEventToTrackMap();
+
+ const sel = new tr.model.EventSet();
+ sel.push(t1.sliceGroup.slices[0]);
+
+ const shifted = track.viewport.getShiftedSelection(sel, 1);
+ assert.isTrue(shifted.equals(
+ new tr.model.EventSet(t1.sliceGroup.slices[1])));
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/alert_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/alert_track.html
new file mode 100644
index 00000000000..571b0543bb9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/alert_track.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/tracks/letter_dot_track.html">
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays an array of alert objects.
+ * @constructor
+ * @extends {LetterDotTrack}
+ */
+ const AlertTrack = tr.ui.b.define(
+ 'alert-track', tr.ui.tracks.LetterDotTrack);
+
+ AlertTrack.prototype = {
+ __proto__: tr.ui.tracks.LetterDotTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.LetterDotTrack.prototype.decorate.call(this, viewport);
+ this.heading = 'Alerts';
+ this.alerts_ = undefined;
+ },
+
+ get alerts() {
+ return this.alerts_;
+ },
+
+ set alerts(alerts) {
+ this.alerts_ = alerts;
+ if (alerts === undefined) {
+ this.items = undefined;
+ return;
+ }
+ this.items = this.alerts_.map(function(alert) {
+ return new tr.ui.tracks.LetterDot(
+ alert, String.fromCharCode(9888), alert.colorId, alert.start);
+ });
+ }
+ };
+
+ return {
+ AlertTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/alert_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/alert_track_test.html
new file mode 100644
index 00000000000..4e60180b00e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/alert_track_test.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/alert_track.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AlertTrack = tr.ui.tracks.AlertTrack;
+ const SelectionState = tr.model.SelectionState;
+ const Viewport = tr.ui.TimelineViewport;
+
+ const ALERT_INFO_1 = new tr.model.EventInfo(
+ 'Alert 1', 'One alert');
+ const ALERT_INFO_2 = new tr.model.EventInfo(
+ 'Alert 2', 'Another alert');
+
+ const createAlerts = function() {
+ const alerts = [
+ new tr.model.Alert(ALERT_INFO_1, 5),
+ new tr.model.Alert(ALERT_INFO_1, 20),
+ new tr.model.Alert(ALERT_INFO_2, 35),
+ new tr.model.Alert(ALERT_INFO_2, 50)
+ ];
+ return alerts;
+ };
+
+ test('instantiate', function() {
+ const alerts = createAlerts();
+ alerts[1].selectionState = SelectionState.SELECTED;
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = AlertTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.alerts = alerts;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 50, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+
+ assert.strictEqual(5, track.items[0].start);
+ });
+
+ test('modelMapping', function() {
+ const alerts = createAlerts();
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const track = AlertTrack(viewport);
+ track.alerts = alerts;
+
+ const a0 = track.items[0].modelItem;
+ assert.strictEqual(a0, alerts[0]);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html
new file mode 100644
index 00000000000..d922030ce70
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/multi_row_track.html">
+<link rel="import" href="/tracing/ui/tracks/slice_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays a AsyncSliceGroup.
+ * @constructor
+ * @extends {MultiRowTrack}
+ */
+ const AsyncSliceGroupTrack = tr.ui.b.define(
+ 'async-slice-group-track',
+ tr.ui.tracks.MultiRowTrack);
+
+ AsyncSliceGroupTrack.prototype = {
+
+ __proto__: tr.ui.tracks.MultiRowTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('async-slice-group-track');
+ this.group_ = undefined;
+ },
+
+ addSubTrack_(slices) {
+ const track = new tr.ui.tracks.SliceTrack(this.viewport);
+ track.slices = slices;
+ Polymer.dom(this).appendChild(track);
+ track.asyncStyle = true;
+ return track;
+ },
+
+ get group() {
+ return this.group_;
+ },
+
+ set group(group) {
+ this.group_ = group;
+ this.buildAndSetSubRows_();
+ },
+
+ get eventContainer() {
+ return this.group;
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ tr.ui.tracks.MultiRowTrack.prototype.addContainersToTrackMap.apply(
+ this, arguments);
+ containerToTrackMap.addContainer(this.group, this);
+ },
+
+ buildAndSetSubRows_() {
+ if (this.group_.viewSubGroups.length <= 1) {
+ // No nested groups or just only one, the most common case.
+ const rows = groupAsyncSlicesIntoSubRows(this.group_.slices);
+ const rowsWithHeadings = rows.map(row => {
+ return {row, heading: undefined};
+ });
+ this.setPrebuiltSubRows(this.group_, rowsWithHeadings);
+ return;
+ }
+
+ // We have nested grouping level (no further levels supported),
+ // so process sub-groups separately and preserve their titles.
+ const rowsWithHeadings = [];
+ for (const subGroup of this.group_.viewSubGroups) {
+ const subGroupRows = groupAsyncSlicesIntoSubRows(subGroup.slices);
+ if (subGroupRows.length === 0) {
+ continue;
+ }
+ for (let i = 0; i < subGroupRows.length; i++) {
+ rowsWithHeadings.push({
+ row: subGroupRows[i],
+ heading: (i === 0 ? subGroup.title : '')
+ });
+ }
+ }
+ this.setPrebuiltSubRows(this.group_, rowsWithHeadings);
+ }
+ };
+
+ /**
+ * Strip away wrapper slice which are used to group slices into
+ * a single track but provide no information themselves.
+ */
+ function stripSlice_(slice) {
+ if (slice.subSlices !== undefined && slice.subSlices.length === 1) {
+ const subSlice = slice.subSlices[0];
+ if (tr.b.math.approximately(subSlice.start, slice.start, 1) &&
+ tr.b.math.approximately(subSlice.duration, slice.duration, 1)) {
+ return subSlice;
+ }
+ }
+ return slice;
+ }
+
+ /**
+ * Unwrap the list of non-overlapping slices into a number of rows where
+ * the top row holds original slices and additional rows hold nested slices
+ * of ones from the row above them.
+ */
+ function makeLevelSubRows_(slices) {
+ const rows = [];
+ const putSlice = (slice, level) => {
+ while (rows.length <= level) {
+ rows.push([]);
+ }
+ rows[level].push(slice);
+ };
+ const putSliceRecursively = (slice, level) => {
+ putSlice(slice, level);
+ if (slice.subSlices !== undefined) {
+ for (const subSlice of slice.subSlices) {
+ putSliceRecursively(subSlice, level + 1);
+ }
+ }
+ };
+
+ for (const slice of slices) {
+ putSliceRecursively(stripSlice_(slice), 0);
+ }
+ return rows;
+ }
+
+ /**
+ * Breaks up the list of slices into a number of rows:
+ * - Which contain non-overlapping slices.
+ * - If slice has nested slices, they're placed onto the row below.
+ * Sorting may be skipped if slices are already sorted by start timestamp.
+ */
+ function groupAsyncSlicesIntoSubRows(slices, opt_skipSort) {
+ if (!opt_skipSort) {
+ slices.sort((x, y) => x.start - y.start);
+ }
+
+ // The algorithm is fairly simple:
+ // - Level is a group of rows, where the top row holds original slices and
+ // additional rows hold nested slices of ones from the row above them.
+ // - Make a level by putting sorted slices, skipping if one's overlapping.
+ // - Repeat and make more levels while we're having residual slices left.
+ const rows = [];
+ let slicesLeft = slices;
+ while (slicesLeft.length !== 0) {
+ // Make a level.
+ const fit = [];
+ const unfit = [];
+ let levelEndTime = -1;
+
+ for (const slice of slicesLeft) {
+ if (slice.start >= levelEndTime) {
+ // Assuming nested slices lie within parent's boundaries.
+ levelEndTime = slice.end;
+ fit.push(slice);
+ } else {
+ unfit.push(slice);
+ }
+ }
+ rows.push(...makeLevelSubRows_(fit));
+ slicesLeft = unfit;
+ }
+ return rows;
+ }
+
+ return {
+ AsyncSliceGroupTrack,
+ groupAsyncSlicesIntoSubRows,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track_test.html
new file mode 100644
index 00000000000..96003e1b5f2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/async_slice_group_track_test.html
@@ -0,0 +1,328 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const AsyncSliceGroup = tr.model.AsyncSliceGroup;
+ const AsyncSliceGroupTrack = tr.ui.tracks.AsyncSliceGroupTrack;
+ const Process = tr.model.Process;
+ const ProcessTrack = tr.ui.tracks.ProcessTrack;
+ const Thread = tr.model.Thread;
+ const ThreadTrack = tr.ui.tracks.ThreadTrack;
+ const newAsyncSlice = tr.c.TestUtils.newAsyncSlice;
+ const newAsyncSliceNamed = tr.c.TestUtils.newAsyncSliceNamed;
+ const groupAsyncSlicesIntoSubRows = tr.ui.tracks.groupAsyncSlicesIntoSubRows;
+
+ test('filterSubRows', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const g = new AsyncSliceGroup(t1);
+ g.push(newAsyncSlice(0, 1, t1, t1));
+ const track = new AsyncSliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = g;
+
+ assert.strictEqual(track.children.length, 1);
+ assert.isTrue(track.hasVisibleContent);
+ });
+
+ test('groupAsyncSlicesIntoSubRows_empty', function() {
+ const rows = groupAsyncSlicesIntoSubRows([]);
+ assert.strictEqual(rows.length, 0);
+ });
+
+ test('groupAsyncSlicesIntoSubRows_trivial', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+
+ const s1 = newAsyncSlice(10, 200, t1, t1);
+ const s2 = newAsyncSlice(300, 30, t1, t1);
+
+ const slices = [s2, s1];
+ const rows = groupAsyncSlicesIntoSubRows(slices);
+
+ assert.strictEqual(rows.length, 1);
+ assert.sameMembers(rows[0], [s1, s2]);
+ });
+
+ test('groupAsyncSlicesIntoSubRows_nonTrivial', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+
+ const s1 = newAsyncSlice(10, 200, t1, t1); // Should be stripped.
+ const s1s1 = newAsyncSlice(10, 200, t1, t1);
+ s1.subSlices = [s1s1];
+
+ const s2 = newAsyncSlice(300, 30, t1, t1);
+ const s2s1 = newAsyncSlice(300, 10, t1, t1);
+ const s2s2 = newAsyncSlice(310, 20, t1, t1); // Should not be stripped.
+ const s2s2s1 = newAsyncSlice(310, 20, t1, t1);
+ s2s2.subSlices = [s2s2s1];
+ s2.subSlices = [s2s2, s2s1];
+
+ const s3 = newAsyncSlice(200, 50, t1, t1); // Overlaps with s1.
+ const s3s1 = newAsyncSlice(220, 5, t1, t1);
+ s3.subSlices = [s3s1];
+
+ const slices = [s2, s3, s1];
+ const rows = groupAsyncSlicesIntoSubRows(slices);
+
+ assert.strictEqual(rows.length, 5);
+ assert.sameMembers(rows[0], [s1s1, s2]);
+ assert.sameMembers(rows[1], [s2s1, s2s2]);
+ assert.sameMembers(rows[2], [s2s2s1]);
+ assert.sameMembers(rows[3], [s3]);
+ assert.sameMembers(rows[4], [s3s1]);
+ });
+
+ test('rebuildSubRows_twoNonOverlappingSlices', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const g = new AsyncSliceGroup(t1);
+ const s1 = newAsyncSlice(0, 1, t1, t1);
+ const subs1 = newAsyncSliceNamed('b', 0, 1, t1, t1);
+ s1.subSlices = [subs1];
+ g.push(s1);
+ g.push(newAsyncSlice(1, 1, t1, t1));
+ const track = new AsyncSliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = g;
+ const subRows = track.subRows;
+ assert.strictEqual(subRows.length, 1);
+ assert.strictEqual(subRows[0].length, 2);
+ assert.sameMembers(g.slices[1].subSlices, []);
+ });
+
+ test('rebuildSubRows_twoOverlappingSlices', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const g = new AsyncSliceGroup(t1);
+
+ const s1 = newAsyncSlice(0, 1, t1, t1);
+ const subs1 = newAsyncSliceNamed('b', 0, 1, t1, t1);
+ s1.subSlices = [subs1];
+ const s2 = newAsyncSlice(0, 1.5, t1, t1);
+ const subs2 = newAsyncSliceNamed('b', 0, 1, t1, t1);
+ s2.subSlices = [subs2];
+ g.push(s1);
+ g.push(s2);
+
+ g.updateBounds();
+
+ const track = new AsyncSliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = g;
+
+ const subRows = track.subRows;
+
+ assert.strictEqual(subRows.length, 2);
+ assert.strictEqual(subRows[0].length, 1);
+ assert.strictEqual(subRows[1].length, 1);
+ assert.strictEqual(subRows[1][0], g.slices[1].subSlices[0]);
+ });
+
+ test('rebuildSubRows_threePartlyOverlappingSlices', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const g = new AsyncSliceGroup(t1);
+ g.push(newAsyncSlice(0, 1, t1, t1));
+ g.push(newAsyncSlice(0, 1.5, t1, t1));
+ g.push(newAsyncSlice(1, 1.5, t1, t1));
+ g.updateBounds();
+ const track = new AsyncSliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = g;
+ const subRows = track.subRows;
+
+ assert.strictEqual(subRows.length, 2);
+ assert.strictEqual(subRows[0].length, 2);
+ assert.strictEqual(subRows[0][0], g.slices[0]);
+ assert.strictEqual(subRows[0][1], g.slices[2]);
+ assert.strictEqual(subRows[1][0], g.slices[1]);
+ assert.strictEqual(subRows[1].length, 1);
+ assert.sameMembers(g.slices[0].subSlices, []);
+ assert.sameMembers(g.slices[1].subSlices, []);
+ assert.sameMembers(g.slices[2].subSlices, []);
+ });
+
+ test('rebuildSubRows_threeOverlappingSlices', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const g = new AsyncSliceGroup(t1);
+
+ g.push(newAsyncSlice(0, 1, t1, t1));
+ g.push(newAsyncSlice(0, 1.5, t1, t1));
+ g.push(newAsyncSlice(2, 1, t1, t1));
+ g.updateBounds();
+
+ const track = new AsyncSliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = g;
+
+ const subRows = track.subRows;
+ assert.strictEqual(subRows.length, 2);
+ assert.strictEqual(subRows[0].length, 2);
+ assert.strictEqual(subRows[1].length, 1);
+ assert.strictEqual(subRows[0][0], g.slices[0]);
+ assert.strictEqual(subRows[1][0], g.slices[1]);
+ assert.strictEqual(subRows[0][1], g.slices[2]);
+ });
+
+ test('rebuildSubRows_twoViewSubGroups', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const g = new AsyncSliceGroup(t1);
+ g.push(newAsyncSliceNamed('foo', 0, 1, t1, t1));
+ g.push(newAsyncSliceNamed('foo', 2, 1, t1, t1));
+ g.push(newAsyncSliceNamed('bar', 1, 2, t1, t1));
+ g.push(newAsyncSliceNamed('bar', 3, 2, t1, t1));
+ g.updateBounds();
+
+ const track = new AsyncSliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = g;
+ track.heading = 'sup';
+
+ assert.strictEqual(track.subRows.length, 2);
+ const subTracks = Polymer.dom(track).children;
+ assert.strictEqual(subTracks.length, 3);
+ assert.strictEqual(subTracks[0].slices.length, 0);
+ assert.strictEqual(subTracks[1].slices.length, 2);
+ assert.strictEqual(subTracks[2].slices.length, 2);
+ const headings =
+ [subTracks[0].heading, subTracks[1].heading, subTracks[2].heading];
+ assert.sameMembers(headings, ['foo', 'bar', 'sup']);
+ });
+
+ // Tests that no slices and their sub slices overlap.
+ test('rebuildSubRows_NonOverlappingSubSlices', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const g = new AsyncSliceGroup(t1);
+
+ const slice1 = newAsyncSlice(0, 5, t1, t1);
+ const slice1Child = newAsyncSlice(1, 2, t1, t1);
+ slice1.subSlices = [slice1Child];
+ const slice2 = newAsyncSlice(3, 5, t1, t1);
+ const slice3 = newAsyncSlice(5, 4, t1, t1);
+ const slice3Child = newAsyncSlice(6, 2, t1, t1);
+ slice3.subSlices = [slice3Child];
+ g.push(slice1);
+ g.push(slice2);
+ g.push(slice3);
+ g.updateBounds();
+
+ const track = new AsyncSliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = g;
+
+ const subRows = track.subRows;
+ // Checks each sub row to see that we don't have any overlapping slices.
+ for (let i = 0; i < subRows.length; i++) {
+ const row = subRows[i];
+ for (let j = 0; j < row.length; j++) {
+ for (let k = j + 1; k < row.length; k++) {
+ assert.isTrue(row[j].end <= row[k].start);
+ }
+ }
+ }
+ });
+
+ test('rebuildSubRows_NonOverlappingSubSlicesThreeNestedLevels', function() {
+ const model = new tr.Model();
+ const p1 = new Process(model, 1);
+ const t1 = new Thread(p1, 1);
+ const g = new AsyncSliceGroup(t1);
+
+ const slice1 = newAsyncSlice(0, 4, t1, t1);
+ const slice1Child = newAsyncSlice(1, 2, t1, t1);
+ slice1.subSlices = [slice1Child];
+ const slice2 = newAsyncSlice(2, 7, t1, t1);
+ const slice3 = newAsyncSlice(5, 5, t1, t1);
+ const slice3Child = newAsyncSlice(6, 3, t1, t1);
+ const slice3Child2 = newAsyncSlice(7, 1, t1, t1);
+ slice3.subSlices = [slice3Child];
+ slice3Child.subSlices = [slice3Child2];
+ g.push(slice1);
+ g.push(slice2);
+ g.push(slice3);
+ g.updateBounds();
+
+ const track = new AsyncSliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = g;
+
+ const subRows = track.subRows;
+ // Checks each sub row to see that we don't have any overlapping slices.
+ for (let i = 0; i < subRows.length; i++) {
+ const row = subRows[i];
+ for (let j = 0; j < row.length; j++) {
+ for (let k = j + 1; k < row.length; k++) {
+ assert.isTrue(row[j].end <= row[k].start);
+ }
+ }
+ }
+ });
+
+ test('asyncSliceGroupContainerMap', function() {
+ const vp = new tr.ui.TimelineViewport();
+ const containerToTrack = vp.containerToTrackMap;
+ const model = new tr.Model();
+ const process = model.getOrCreateProcess(123);
+ const thread = process.getOrCreateThread(456);
+ const group = new AsyncSliceGroup(thread);
+
+ const processTrack = new ProcessTrack(vp);
+ const threadTrack = new ThreadTrack(vp);
+ const groupTrack = new AsyncSliceGroupTrack(vp);
+ processTrack.process = process;
+ threadTrack.thread = thread;
+ groupTrack.group = group;
+ Polymer.dom(processTrack).appendChild(threadTrack);
+ Polymer.dom(threadTrack).appendChild(groupTrack);
+
+ assert.strictEqual(processTrack.eventContainer, process);
+ assert.strictEqual(threadTrack.eventContainer, thread);
+ assert.strictEqual(groupTrack.eventContainer, group);
+
+ assert.isUndefined(containerToTrack.getTrackByStableId('123'));
+ assert.isUndefined(containerToTrack.getTrackByStableId('123.456'));
+ assert.isUndefined(
+ containerToTrack.getTrackByStableId('123.456.AsyncSliceGroup'));
+
+ vp.modelTrackContainer = {
+ addContainersToTrackMap(containerToTrackMap) {
+ processTrack.addContainersToTrackMap(containerToTrackMap);
+ },
+ addEventListener() {}
+ };
+ vp.rebuildContainerToTrackMap();
+
+ // Check that all tracks call childs' addContainersToTrackMap()
+ // by checking the resulting map.
+ assert.strictEqual(
+ containerToTrack.getTrackByStableId('123'), processTrack);
+ assert.strictEqual(
+ containerToTrack.getTrackByStableId('123.456'), threadTrack);
+ assert.strictEqual(
+ containerToTrack.getTrackByStableId('123.456.AsyncSliceGroup'),
+ groupTrack);
+
+ // Check the track's eventContainer getter.
+ assert.strictEqual(processTrack.eventContainer, process);
+ assert.strictEqual(threadTrack.eventContainer, thread);
+ assert.strictEqual(groupTrack.eventContainer, group);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_point.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_point.html
new file mode 100644
index 00000000000..1b73f367636
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_point.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/proxy_selectable_item.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A point in a chart series with x (timestamp) and y (value) coordinates
+ * and an associated model item. The point can optionally also have a base
+ * y coordinate (which for example corresponds to the bottom edge of the
+ * associated bar in a bar chart).
+ *
+ * @constructor
+ * @extends {ProxySelectableItem}
+ */
+ function ChartPoint(modelItem, x, y, opt_yBase) {
+ tr.model.ProxySelectableItem.call(this, modelItem);
+ this.x = x;
+ this.y = y;
+ this.dotLetter = undefined;
+
+ // If the base y-coordinate is undefined, the bottom edge of the associated
+ // bar in a bar chart will start at the outer bottom edge (which is most
+ // likely slightly below zero).
+ this.yBase = opt_yBase;
+ }
+
+ ChartPoint.prototype = {
+ __proto__: tr.model.ProxySelectableItem.prototype,
+ };
+
+ return {
+ ChartPoint,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_point_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_point_test.html
new file mode 100644
index 00000000000..e2d8bc3e11c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_point_test.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/tracks/chart_point.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ChartPoint = tr.ui.tracks.ChartPoint;
+
+ test('checkFields_withoutYBase', function() {
+ const event = {};
+ const point = new ChartPoint(event, 42, -7);
+
+ assert.strictEqual(point.modelItem, event);
+ assert.strictEqual(point.x, 42);
+ assert.strictEqual(point.y, -7);
+ assert.isUndefined(point.yBase);
+ });
+
+ test('checkFields_withYBase', function() {
+ const event = {};
+ const point = new ChartPoint(event, 111, 222, 333);
+
+ assert.strictEqual(point.modelItem, event);
+ assert.strictEqual(point.x, 111);
+ assert.strictEqual(point.y, 222);
+ assert.strictEqual(point.yBase, 333);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series.html
new file mode 100644
index 00000000000..45025d13e0d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series.html
@@ -0,0 +1,566 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/proxy_selectable_item.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/base/event_presenter.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const EventPresenter = tr.ui.b.EventPresenter;
+ const SelectionState = tr.model.SelectionState;
+
+ /**
+ * The type of a chart series.
+ * @enum
+ */
+ const ChartSeriesType = {
+ LINE: 0,
+ AREA: 1
+ };
+
+ // The default rendering configuration for ChartSeries.
+ const DEFAULT_RENDERING_CONFIG = {
+ // The type of the chart series.
+ chartType: ChartSeriesType.LINE,
+
+ // The size of a selected point dot in device-independent pixels (circle
+ // diameter).
+ selectedPointSize: 4,
+
+ // The size of an unselected point dot in device-independent pixels (square
+ // width/height).
+ unselectedPointSize: 3,
+
+ // Whether the selected dots should be solid circles of the line color, or
+ // filled with the background's selection color.
+ solidSelectedDots: false,
+
+ // The color of the chart.
+ colorId: 0,
+
+ // The width of the top line in device-independent pixels.
+ lineWidth: 1,
+
+ // Minimum distance between points in physical pixels. Points which are
+ // closer than this distance will be skipped.
+ skipDistance: 1,
+
+ // Density in points per physical pixel at which unselected point dots
+ // become transparent.
+ unselectedPointDensityTransparent: 0.10,
+
+ // Density in points per physical pixel at which unselected point dots
+ // become fully opaque.
+ unselectedPointDensityOpaque: 0.05,
+
+ // Opacity of area chart background.
+ backgroundOpacity: 0.5,
+
+ // Whether to graph steps between points. Set to false for lines instead.
+ stepGraph: true
+ };
+
+ // The virtual width of the last point in a series (whose rectangle has zero
+ // width) in world timestamps difference for the purposes of selection.
+ const LAST_POINT_WIDTH = 16;
+
+ // Constants for sizing and font of points with dot letters.
+ const DOT_LETTER_RADIUS_PX = 7;
+ const DOT_LETTER_RADIUS_PADDING_PX = 0.5;
+ const DOT_LETTER_SELECTED_OUTLINE_WIDTH_PX = 3;
+ const DOT_LETTER_SELECTED_OUTLINE_DETAIL_WIDTH_PX = 1.5;
+ const DOT_LETTER_UNSELECTED_OUTLINE_WIDTH_PX = 1;
+ const DOT_LETTER_FONT_WEIGHT = 400;
+ const DOT_LETTER_FONT_SIZE_PX = 9;
+ const DOT_LETTER_FONT = 'Arial';
+
+ /**
+ * Visual components of a ChartSeries.
+ * @enum
+ */
+ const ChartSeriesComponent = {
+ BACKGROUND: 0,
+ LINE: 1,
+ DOTS: 2
+ };
+
+ /**
+ * A series of points corresponding to a single chart on a chart track.
+ * This class is responsible for drawing the actual chart onto canvas.
+ *
+ * @constructor
+ */
+ function ChartSeries(points, seriesYAxis, opt_renderingConfig) {
+ this.points = points;
+ this.seriesYAxis = seriesYAxis;
+
+ this.useRenderingConfig_(opt_renderingConfig);
+ }
+
+ ChartSeries.prototype = {
+ useRenderingConfig_(opt_renderingConfig) {
+ const config = opt_renderingConfig || {};
+
+ // Store all configuration flags as private properties.
+ for (const [key, defaultValue] of
+ Object.entries(DEFAULT_RENDERING_CONFIG)) {
+ let value = config[key];
+ if (value === undefined) {
+ value = defaultValue;
+ }
+ this[key + '_'] = value;
+ }
+
+ // Avoid unnecessary recomputation in getters.
+ this.topPadding = this.bottomPadding = Math.max(
+ this.selectedPointSize_, this.unselectedPointSize_) / 2;
+ },
+
+ get range() {
+ const range = new tr.b.math.Range();
+ this.points.forEach(function(point) {
+ range.addValue(point.y);
+ }, this);
+ return range;
+ },
+
+ draw(ctx, transform, highDetails) {
+ if (this.points === undefined || this.points.length === 0) {
+ return;
+ }
+
+ // Draw the background.
+ if (this.chartType_ === ChartSeriesType.AREA) {
+ this.drawComponent_(ctx, transform, ChartSeriesComponent.BACKGROUND,
+ highDetails);
+ }
+
+ // Draw the line at the top.
+ if (this.chartType_ === ChartSeriesType.LINE || highDetails) {
+ this.drawComponent_(ctx, transform, ChartSeriesComponent.LINE,
+ highDetails);
+ }
+
+ // Draw the points.
+ this.drawComponent_(ctx, transform, ChartSeriesComponent.DOTS,
+ highDetails);
+ },
+
+ drawComponent_(ctx, transform, component, highDetails) {
+ // We need to consider extra pixels outside the visible area to avoid
+ // visual glitches due to non-zero width of dots.
+ let extraPixels = 0;
+ if (component === ChartSeriesComponent.DOTS) {
+ extraPixels = Math.max(
+ this.selectedPointSize_, this.unselectedPointSize_);
+ }
+ const pixelRatio = transform.pixelRatio;
+ const leftViewX = transform.leftViewX - extraPixels * pixelRatio;
+ const rightViewX = transform.rightViewX + extraPixels * pixelRatio;
+ const leftTimestamp = transform.leftTimestamp - extraPixels;
+ const rightTimestamp = transform.rightTimestamp + extraPixels;
+
+ // Find the index of the first and last (partially) visible points.
+ const firstVisibleIndex = tr.b.findLowIndexInSortedArray(
+ this.points,
+ function(point) { return point.x; },
+ leftTimestamp);
+ let lastVisibleIndex = tr.b.findLowIndexInSortedArray(
+ this.points,
+ function(point) { return point.x; },
+ rightTimestamp);
+ if (lastVisibleIndex >= this.points.length ||
+ this.points[lastVisibleIndex].x > rightTimestamp) {
+ lastVisibleIndex--;
+ }
+
+ // Pre-calculate component style which does not depend on individual
+ // points:
+ // * Skip distance between points,
+ // * Selected (circle) and unselected (square) dot size,
+ // * Unselected dot opacity,
+ // * Selected dot edge color and width, and
+ // * Line component color and width.
+ const viewSkipDistance = this.skipDistance_ * pixelRatio;
+ let selectedCircleRadius;
+ let letterDotRadius;
+ let squareSize;
+ let squareHalfSize;
+ let squareOpacity;
+ let unselectedSeriesColor;
+ let currentStateSeriesColor;
+
+ ctx.save();
+ ctx.font =
+ DOT_LETTER_FONT_WEIGHT + ' ' +
+ Math.floor(DOT_LETTER_FONT_SIZE_PX * pixelRatio) + 'px ' +
+ DOT_LETTER_FONT;
+ ctx.textBaseline = 'middle';
+ ctx.textAlign = 'center';
+
+ switch (component) {
+ case ChartSeriesComponent.DOTS: {
+ // Selected (circle) and unselected (square) dot size.
+ selectedCircleRadius =
+ (this.selectedPointSize_ / 2) * pixelRatio;
+ letterDotRadius =
+ Math.max(selectedCircleRadius, DOT_LETTER_RADIUS_PX * pixelRatio);
+ squareSize = this.unselectedPointSize_ * pixelRatio;
+ squareHalfSize = squareSize / 2;
+ unselectedSeriesColor = EventPresenter.getCounterSeriesColor(
+ this.colorId_, SelectionState.NONE);
+
+ // Unselected dot opacity.
+ if (!highDetails) {
+ // Unselected dots are not displayed in 'low details' mode.
+ squareOpacity = 0;
+ break;
+ }
+ const visibleIndexRange = lastVisibleIndex - firstVisibleIndex;
+ if (visibleIndexRange <= 0) {
+ // There is at most one visible point.
+ squareOpacity = 1;
+ break;
+ }
+ const visibleViewXRange =
+ transform.worldXToViewX(this.points[lastVisibleIndex].x) -
+ transform.worldXToViewX(this.points[firstVisibleIndex].x);
+ if (visibleViewXRange === 0) {
+ // Multiple visible points which all have the same timestamp.
+ squareOpacity = 1;
+ break;
+ }
+ const density = visibleIndexRange / visibleViewXRange;
+ const clampedDensity = tr.b.math.clamp(density,
+ this.unselectedPointDensityOpaque_,
+ this.unselectedPointDensityTransparent_);
+ const densityRange = this.unselectedPointDensityTransparent_ -
+ this.unselectedPointDensityOpaque_;
+ squareOpacity =
+ (this.unselectedPointDensityTransparent_ - clampedDensity) /
+ densityRange;
+ break;
+ }
+
+ case ChartSeriesComponent.LINE:
+ // Line component color and width.
+ ctx.strokeStyle = EventPresenter.getCounterSeriesColor(
+ this.colorId_, SelectionState.NONE);
+ ctx.lineWidth = this.lineWidth_ * pixelRatio;
+ break;
+
+ case ChartSeriesComponent.BACKGROUND:
+ // Style depends on the selection state of individual points.
+ break;
+
+ default:
+ throw new Error('Invalid component: ' + component);
+ }
+
+ // The main loop which draws the given component of visible points from
+ // left to right. Given the potentially large number of points to draw,
+ // it should be considered performance-critical and function calls should
+ // be avoided when possible.
+ //
+ // Note that the background and line components are drawn in a delayed
+ // fashion: the rectangle/line that we draw in an iteration corresponds
+ // to the *previous* point. This does not apply to the dots, whose
+ // position is independent of the surrounding dots.
+ let previousViewX = undefined;
+ let previousViewY = undefined;
+ let previousViewYBase = undefined;
+ let lastSelectionState = undefined;
+ let baseSteps = undefined;
+ const startIndex = Math.max(firstVisibleIndex - 1, 0);
+ let currentViewX;
+
+ for (let i = startIndex; i < this.points.length; i++) {
+ const currentPoint = this.points[i];
+ currentViewX = transform.worldXToViewX(currentPoint.x);
+
+ // Stop drawing the points once we are to the right of the visible area.
+ if (currentViewX > rightViewX) {
+ if (previousViewX !== undefined) {
+ previousViewX = currentViewX = rightViewX;
+ if (component === ChartSeriesComponent.BACKGROUND ||
+ component === ChartSeriesComponent.LINE) {
+ ctx.lineTo(currentViewX, previousViewY);
+ }
+ }
+ break;
+ }
+
+ if (i + 1 < this.points.length) {
+ const nextPoint = this.points[i + 1];
+ const nextViewX = transform.worldXToViewX(nextPoint.x);
+
+ // Skip points that are too close to each other.
+ if (previousViewX !== undefined &&
+ nextViewX - previousViewX <= viewSkipDistance &&
+ nextViewX < rightViewX) {
+ continue;
+ }
+
+ // Start drawing right at the left side of the visible are (instead
+ // of potentially very far to the left).
+ if (currentViewX < leftViewX) {
+ currentViewX = leftViewX;
+ }
+ }
+
+ if (previousViewX !== undefined &&
+ currentViewX - previousViewX < viewSkipDistance) {
+ // We know that nextViewX > previousViewX + viewSkipDistance, so we
+ // can safely move this points's x over that much without passing
+ // nextViewX. This ensures that the previous point is visible when
+ // zoomed out very far.
+ currentViewX = previousViewX + viewSkipDistance;
+ }
+
+ const currentViewY = Math.round(transform.worldYToViewY(
+ currentPoint.y));
+ let currentViewYBase;
+ if (currentPoint.yBase === undefined) {
+ currentViewYBase = transform.outerBottomViewY;
+ } else {
+ currentViewYBase = Math.round(
+ transform.worldYToViewY(currentPoint.yBase));
+ }
+ const currentSelectionState = currentPoint.selectionState;
+ if (currentSelectionState !== lastSelectionState) {
+ const opacity = currentSelectionState === SelectionState.SELECTED ?
+ 1 : squareOpacity;
+ currentStateSeriesColor = EventPresenter.getCounterSeriesColor(
+ this.colorId_, currentSelectionState, opacity);
+ }
+
+ // Actually draw the given component of the point.
+ switch (component) {
+ case ChartSeriesComponent.DOTS:
+ // Draw the dot for the current point.
+ if (currentPoint.dotLetter) {
+ ctx.fillStyle = unselectedSeriesColor;
+ ctx.strokeStyle =
+ ColorScheme.getColorForReservedNameAsString('black');
+ ctx.beginPath();
+ ctx.arc(currentViewX, currentViewY,
+ letterDotRadius + DOT_LETTER_RADIUS_PADDING_PX, 0,
+ 2 * Math.PI);
+ ctx.fill();
+ if (currentSelectionState === SelectionState.SELECTED) {
+ ctx.lineWidth = DOT_LETTER_SELECTED_OUTLINE_WIDTH_PX;
+ ctx.strokeStyle =
+ ColorScheme.getColorForReservedNameAsString('olive');
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.arc(currentViewX, currentViewY, letterDotRadius, 0,
+ 2 * Math.PI);
+ ctx.lineWidth = DOT_LETTER_SELECTED_OUTLINE_DETAIL_WIDTH_PX;
+ ctx.strokeStyle =
+ ColorScheme.getColorForReservedNameAsString('yellow');
+ ctx.stroke();
+ } else {
+ ctx.lineWidth = DOT_LETTER_UNSELECTED_OUTLINE_WIDTH_PX;
+ ctx.strokeStyle =
+ ColorScheme.getColorForReservedNameAsString('black');
+ ctx.stroke();
+ }
+ ctx.fillStyle =
+ ColorScheme.getColorForReservedNameAsString('white');
+ ctx.fillText(currentPoint.dotLetter, currentViewX, currentViewY);
+ } else {
+ ctx.strokeStyle = unselectedSeriesColor;
+ ctx.lineWidth = pixelRatio;
+ if (currentSelectionState === SelectionState.SELECTED) {
+ if (this.solidSelectedDots_) {
+ ctx.fillStyle = ctx.strokeStyle;
+ } else {
+ ctx.fillStyle = currentStateSeriesColor;
+ }
+
+ ctx.beginPath();
+ ctx.arc(currentViewX, currentViewY, selectedCircleRadius, 0,
+ 2 * Math.PI);
+ ctx.fill();
+ ctx.stroke();
+ } else if (squareOpacity > 0) {
+ ctx.fillStyle = currentStateSeriesColor;
+ ctx.fillRect(currentViewX - squareHalfSize,
+ currentViewY - squareHalfSize, squareSize, squareSize);
+ }
+ }
+ break;
+
+ case ChartSeriesComponent.LINE:
+ // Draw the top line for the previous point (if applicable), or
+ // prepare for drawing the top line of the current point in the next
+ // iteration.
+ if (previousViewX === undefined) {
+ ctx.beginPath();
+ ctx.moveTo(currentViewX, currentViewY);
+ } else if (this.stepGraph_) {
+ ctx.lineTo(currentViewX, previousViewY);
+ }
+
+ // Move to the current point coordinate.
+ ctx.lineTo(currentViewX, currentViewY);
+ break;
+
+ case ChartSeriesComponent.BACKGROUND:
+ // Draw the background for the previous point (if applicable).
+ if (previousViewX !== undefined && this.stepGraph_) {
+ ctx.lineTo(currentViewX, previousViewY);
+ } else {
+ ctx.lineTo(currentViewX, currentViewY);
+ }
+
+ // Finish the bottom part of the backgound polygon, change
+ // background color and start a new polygon when the selection state
+ // changes (and at the beginning).
+ if (currentSelectionState !== lastSelectionState) {
+ if (previousViewX !== undefined) {
+ let previousBaseStepViewX = currentViewX;
+ for (let j = baseSteps.length - 1; j >= 0; j--) {
+ const baseStep = baseSteps[j];
+ const baseStepViewX = baseStep.viewX;
+ const baseStepViewY = baseStep.viewY;
+ ctx.lineTo(previousBaseStepViewX, baseStepViewY);
+ ctx.lineTo(baseStepViewX, baseStepViewY);
+ previousBaseStepViewX = baseStepViewX;
+ }
+ ctx.closePath();
+ ctx.fill();
+ }
+ ctx.beginPath();
+ ctx.fillStyle = EventPresenter.getCounterSeriesColor(
+ this.colorId_, currentSelectionState,
+ this.backgroundOpacity_);
+ ctx.moveTo(currentViewX, currentViewYBase);
+ baseSteps = [];
+ }
+
+ if (currentViewYBase !== previousViewYBase ||
+ currentSelectionState !== lastSelectionState) {
+ baseSteps.push({viewX: currentViewX, viewY: currentViewYBase});
+ }
+
+ // Move to the current point coordinate.
+ ctx.lineTo(currentViewX, currentViewY);
+ break;
+
+ default:
+ throw new Error('Not reachable');
+ }
+
+ previousViewX = currentViewX;
+ previousViewY = currentViewY;
+ previousViewYBase = currentViewYBase;
+ lastSelectionState = currentSelectionState;
+ }
+
+ // If we still have an open background or top line polygon (which is
+ // always the case once we have started drawing due to the delayed fashion
+ // of drawing), we must close it.
+ if (previousViewX !== undefined) {
+ switch (component) {
+ case ChartSeriesComponent.DOTS:
+ // All dots were drawn in the main loop.
+ break;
+
+ case ChartSeriesComponent.LINE:
+ ctx.stroke();
+ break;
+
+ case ChartSeriesComponent.BACKGROUND: {
+ let previousBaseStepViewX = currentViewX;
+ for (let j = baseSteps.length - 1; j >= 0; j--) {
+ const baseStep = baseSteps[j];
+ const baseStepViewX = baseStep.viewX;
+ const baseStepViewY = baseStep.viewY;
+ ctx.lineTo(previousBaseStepViewX, baseStepViewY);
+ ctx.lineTo(baseStepViewX, baseStepViewY);
+ previousBaseStepViewX = baseStepViewX;
+ }
+ ctx.closePath();
+ ctx.fill();
+ break;
+ }
+
+ default:
+ throw new Error('Not reachable');
+ }
+ }
+ ctx.restore();
+ },
+
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ const points = this.points;
+
+ function getPointWidth(point, i) {
+ if (i === points.length - 1) {
+ return LAST_POINT_WIDTH * viewPixWidthWorld;
+ }
+ const nextPoint = points[i + 1];
+ return nextPoint.x - point.x;
+ }
+
+ function selectPoint(point) {
+ point.addToSelection(selection);
+ }
+
+ tr.b.iterateOverIntersectingIntervals(
+ this.points,
+ function(point) { return point.x; },
+ getPointWidth,
+ loWX,
+ hiWX,
+ selectPoint);
+ },
+
+ addEventNearToProvidedEventToSelection(event, offset, selection) {
+ if (this.points === undefined) return false;
+
+ const index = this.points.findIndex(point => point.modelItem === event);
+ if (index === -1) return false;
+
+ const newIndex = index + offset;
+ if (newIndex < 0 || newIndex >= this.points.length) return false;
+
+ this.points[newIndex].addToSelection(selection);
+ return true;
+ },
+
+ addClosestEventToSelection(worldX, worldMaxDist, loY, hiY,
+ selection) {
+ if (this.points === undefined) return;
+
+ const item = tr.b.findClosestElementInSortedArray(
+ this.points,
+ function(point) { return point.x; },
+ worldX,
+ worldMaxDist);
+
+ if (!item) return;
+
+ item.addToSelection(selection);
+ }
+ };
+
+ return {
+ ChartSeries,
+ ChartSeriesType,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_test.html
new file mode 100644
index 00000000000..b07e4276e26
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_test.html
@@ -0,0 +1,331 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/timeline_display_transform.html">
+<link rel="import" href="/tracing/ui/tracks/chart_point.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series_y_axis.html">
+<link rel="import" href="/tracing/ui/tracks/chart_transform.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventSet = tr.model.EventSet;
+ const TimelineDisplayTransform = tr.ui.TimelineDisplayTransform;
+ const Event = tr.model.Event;
+ const SelectionState = tr.model.SelectionState;
+ const ChartSeriesYAxis = tr.ui.tracks.ChartSeriesYAxis;
+ const ChartPoint = tr.ui.tracks.ChartPoint;
+ const ChartSeries = tr.ui.tracks.ChartSeries;
+ const ChartTransform = tr.ui.tracks.ChartTransform;
+ const ChartSeriesType = tr.ui.tracks.ChartSeriesType;
+
+ const CANVAS_WIDTH = 800;
+ const CANVAS_HEIGHT = 80;
+
+ function getSelectionStateForTesting(index) {
+ index = index % 7;
+ if (index < 5) {
+ return SelectionState.getFromBrighteningLevel(index % 4);
+ }
+ return SelectionState.getFromDimmingLevel(index % 3);
+ }
+
+ function buildSeries(renderingConfig) {
+ const points = [];
+ for (let i = 0; i < 60; i++) {
+ const event = new Event();
+ event.index = i;
+ const phase = i * Math.PI / 15;
+ const value = Math.sin(phase);
+ const peakIndex = Math.floor((phase + Math.PI / 2) / (2 * Math.PI));
+ const base = peakIndex % 2 === 0 ? undefined : -1 + value / 1.5;
+ const point = new ChartPoint(event, i - 30, value, base);
+ points.push(point);
+ }
+ const seriesYAxis = new ChartSeriesYAxis(-1, 1);
+ return new ChartSeries(points, seriesYAxis, renderingConfig);
+ }
+
+ function drawSeriesWithDetails(test, series, highDetails) {
+ const div = document.createElement('div');
+ const canvas = document.createElement('canvas');
+ Polymer.dom(div).appendChild(canvas);
+
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ canvas.width = CANVAS_WIDTH * pixelRatio;
+ canvas.style.width = CANVAS_WIDTH + 'px';
+ canvas.height = CANVAS_HEIGHT * pixelRatio;
+ canvas.style.height = CANVAS_HEIGHT + 'px';
+
+ const displayTransform = new TimelineDisplayTransform();
+ displayTransform.scaleX = CANVAS_WIDTH * pixelRatio / 60;
+ displayTransform.panX = 30;
+
+ const transform = new ChartTransform(
+ displayTransform,
+ series.seriesYAxis,
+ CANVAS_WIDTH * pixelRatio,
+ CANVAS_HEIGHT * pixelRatio,
+ 10 * pixelRatio,
+ 10 * pixelRatio,
+ pixelRatio);
+
+ series.draw(canvas.getContext('2d'), transform, highDetails);
+
+ test.addHTMLOutput(div);
+ }
+
+ function drawSeries(test, series) {
+ drawSeriesWithDetails(test, series, false);
+ drawSeriesWithDetails(test, series, true);
+ series.stepGraph_ = !series.stepGraph_;
+ drawSeriesWithDetails(test, series, false);
+ drawSeriesWithDetails(test, series, true);
+ }
+
+ test('instantiate_defaultConfig', function() {
+ const series = buildSeries(undefined);
+ drawSeries(this, series);
+ });
+
+ test('instantiate_lineChart', function() {
+ const series = buildSeries({
+ chartType: ChartSeriesType.LINE,
+ colorId: 4,
+ unselectedPointSize: 6,
+ lineWidth: 2,
+ unselectedPointDensityOpaque: 0.08
+ });
+ drawSeries(this, series);
+ });
+
+ test('instantiate_areaChart', function() {
+ const series = buildSeries({
+ chartType: ChartSeriesType.AREA,
+ colorId: 2,
+ backgroundOpacity: 0.2
+ });
+ drawSeries(this, series);
+ });
+
+ test('instantiate_largeSkipDistance', function() {
+ const series = buildSeries({
+ chartType: ChartSeriesType.AREA,
+ colorId: 1,
+ skipDistance: 40,
+ unselectedPointDensityTransparent: 0.07
+ });
+ drawSeries(this, series);
+ });
+
+ test('instantiate_selection', function() {
+ const series = buildSeries({
+ chartType: ChartSeriesType.AREA,
+ colorId: 10
+ });
+ series.points.forEach(function(point, index) {
+ point.modelItem.selectionState = getSelectionStateForTesting(index);
+ });
+ drawSeries(this, series);
+ });
+
+ test('instantiate_selectionWithSolidDots', function() {
+ const series = buildSeries({
+ chartType: ChartSeriesType.AREA,
+ selectedPointSize: 10,
+ unselectedPointSize: 6,
+ solidSelectedDots: true,
+ colorId: 10
+ });
+ series.points.forEach(function(point, index) {
+ point.modelItem.selectionState = getSelectionStateForTesting(index);
+ });
+ drawSeries(this, series);
+ });
+
+ test('instantiate_selectionWithAllConfigFlags', function() {
+ const series = buildSeries({
+ chartType: ChartSeriesType.AREA,
+ selectedPointSize: 10,
+ unselectedPointSize: 6,
+ colorId: 15,
+ lineWidth: 2,
+ skipDistance: 25,
+ unselectedPointDensityOpaque: 0.07,
+ unselectedPointDensityTransparent: 0.09,
+ backgroundOpacity: 0.8
+ });
+ series.points.forEach(function(point, index) {
+ point.modelItem.selectionState = getSelectionStateForTesting(index);
+ });
+ drawSeries(this, series);
+ });
+
+ test('instantiate_selectionWithDotLetters', function() {
+ const series = buildSeries({
+ chartType: ChartSeriesType.AREA,
+ selectedPointSize: 10,
+ unselectedPointSize: 6,
+ solidSelectedDots: true,
+ colorId: 10
+ });
+ series.points.forEach(function(point, index) {
+ point.modelItem.selectionState = getSelectionStateForTesting(index);
+ if (index % 10 === 3) {
+ point.dotLetter = 'P';
+ } else if (index % 10 === 7) {
+ point.dotLetter = '\u26A0';
+ }
+ });
+ drawSeries(this, series);
+ });
+
+ test('checkRange', function() {
+ const series = buildSeries();
+ const range = series.range;
+ assert.isFalse(range.isEmpty);
+ assert.closeTo(range.min, -1, 0.05);
+ assert.closeTo(range.max, 1, 0.05);
+ });
+
+ test('checkaddIntersectingEventsInRangeToSelectionInWorldSpace', function() {
+ const series = buildSeries();
+
+ // Too far left.
+ let sel = new EventSet();
+ series.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ -1000, -30.5, 40, sel);
+ assert.lengthOf(sel, 0);
+
+ // Select first point.
+ sel = new EventSet();
+ series.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ -30.5, -29.5, 40, sel);
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 0);
+
+ // Select second point.
+ sel = new EventSet();
+ series.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ -28.8, -28.2, 40, sel);
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 1);
+
+ // Select points in the middle.
+ sel = new EventSet();
+ series.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ -0.99, 1.01, 40, sel);
+ assert.lengthOf(sel, 3);
+ const iterator = sel[Symbol.iterator]();
+ assert.strictEqual(iterator.next().value.index, 29);
+ assert.strictEqual(iterator.next().value.index, 30);
+ assert.strictEqual(iterator.next().value.index, 31);
+
+ // Select the last point.
+ sel = new EventSet();
+ series.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ 668.99, 668.99, 40, sel);
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 59);
+
+ // Too far right.
+ sel = new EventSet();
+ series.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ 669.01, 2000, 40, sel);
+ assert.lengthOf(sel, 0);
+
+ // Select everything.
+ sel = new EventSet();
+ series.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ -29.01, 669.01, 40, sel);
+ assert.lengthOf(sel, 60);
+ });
+
+ test('checkaddEventNearToProvidedEventToSelection', function() {
+ const series = buildSeries();
+
+ // Invalid event.
+ let sel = new EventSet();
+ assert.isFalse(series.addEventNearToProvidedEventToSelection(
+ new Event(), 1, sel));
+ assert.lengthOf(sel, 0);
+
+ sel = new EventSet();
+ assert.isFalse(series.addEventNearToProvidedEventToSelection(
+ new Event(), -1, sel));
+ assert.lengthOf(sel, 0);
+
+ // First point.
+ sel = new EventSet();
+ assert.isTrue(series.addEventNearToProvidedEventToSelection(
+ series.points[0].modelItem, 1, sel));
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 1);
+
+ sel = new EventSet();
+ assert.isFalse(series.addEventNearToProvidedEventToSelection(
+ series.points[0].modelItem, -1, sel));
+ assert.lengthOf(sel, 0);
+
+ // Middle point.
+ sel = new EventSet();
+ assert.isTrue(series.addEventNearToProvidedEventToSelection(
+ series.points[30].modelItem, 1, sel));
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 31);
+
+ sel = new EventSet();
+ assert.isTrue(series.addEventNearToProvidedEventToSelection(
+ series.points[30].modelItem, -1, sel));
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 29);
+
+ // Last point.
+ sel = new EventSet();
+ assert.isFalse(series.addEventNearToProvidedEventToSelection(
+ series.points[59].modelItem, 1, sel));
+ assert.lengthOf(sel, 0);
+
+ sel = new EventSet();
+ assert.isTrue(series.addEventNearToProvidedEventToSelection(
+ series.points[59].modelItem, -1, sel));
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 58);
+ });
+
+ test('checkAddClosestEventToSelection', function() {
+ const series = buildSeries();
+
+ // Left of first point.
+ let sel = new EventSet();
+ series.addClosestEventToSelection(-40, 9, -0.5, 0.5, sel);
+ assert.lengthOf(sel, 0);
+
+ sel = new EventSet();
+ series.addClosestEventToSelection(-40, 11, -0.5, 0.5, sel);
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 0);
+
+ // Between two points.
+ sel = new EventSet();
+ series.addClosestEventToSelection(0.4, 0.3, -0.5, 0.5, sel);
+ assert.lengthOf(sel, 0);
+
+ sel = new EventSet();
+ series.addClosestEventToSelection(0.4, 0.4, -0.5, 0.5, sel);
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 30);
+
+ // Right of last point.
+ sel = new EventSet();
+ series.addClosestEventToSelection(40, 10, -0.5, 0.5, sel);
+ assert.lengthOf(sel, 0);
+
+ sel = new EventSet();
+ series.addClosestEventToSelection(40, 12, -0.5, 0.5, sel);
+ assert.strictEqual(tr.b.getOnlyElement(sel).index, 59);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_y_axis.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_y_axis.html
new file mode 100644
index 00000000000..f34b4c68579
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_y_axis.html
@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const IDEAL_MAJOR_MARK_HEIGHT_PX = 30;
+ const AXIS_LABLE_MARGIN_PX = 10;
+ const AXIS_LABLE_FONT_SIZE_PX = 9;
+ const AXIS_LABLE_FONT = 'Arial';
+
+ /**
+ * A vertical axis for a (set of) chart series which maps an arbitrary range
+ * of values [min, max] to the unit range [0, 1].
+ *
+ * @constructor
+ */
+ function ChartSeriesYAxis(opt_min, opt_max) {
+ this.guid_ = tr.b.GUID.allocateSimple();
+ this.bounds = new tr.b.math.Range();
+ if (opt_min !== undefined) this.bounds.addValue(opt_min);
+ if (opt_max !== undefined) this.bounds.addValue(opt_max);
+ }
+
+ ChartSeriesYAxis.prototype = {
+ get guid() {
+ return this.guid_;
+ },
+
+ valueToUnitRange(value) {
+ if (this.bounds.isEmpty) {
+ throw new Error('Chart series y-axis bounds are empty');
+ }
+ const bounds = this.bounds;
+ if (bounds.range === 0) return 0;
+ return (value - bounds.min) / bounds.range;
+ },
+
+ unitRangeToValue(unitRange) {
+ if (this.bounds.isEmpty) {
+ throw new Error('Chart series y-axis bounds are empty');
+ }
+ return unitRange * this.bounds.range + this.bounds.min;
+ },
+
+ /**
+ * Automatically set the y-axis bounds from the range of values of all
+ * series in a list.
+ *
+ * See the description of autoSetFromRange for the optional configuration
+ * argument flags.
+ */
+ autoSetFromSeries(series, opt_config) {
+ const range = new tr.b.math.Range();
+ series.forEach(function(s) {
+ range.addRange(s.range);
+ }, this);
+ this.autoSetFromRange(range, opt_config);
+ },
+
+ /**
+ * Automatically set the y-axis bound from a range of values.
+ *
+ * The following four flags, which affect the behavior of this method with
+ * respect to already defined bounds, can be present in the optional
+ * configuration (a flag is assumed to be false if it is not provided or if
+ * the configuration is not provided):
+ *
+ * - expandMin: allow decreasing the min bound (if range.min < this.min)
+ * - shrinkMin: allow increasing the min bound (if range.min > this.min)
+ * - expandMax: allow increasing the max bound (if range.max > this.max)
+ * - shrinkMax: allow decreasing the max bound (if range.max < this.max)
+ *
+ * This method will ensure that the resulting bounds are defined and valid
+ * (i.e. min <= max) provided that they were valid or empty before and the
+ * value range is non-empty and valid.
+ *
+ * Note that unless expanding/shrinking a bound is explicitly enabled in
+ * the configuration, non-empty bounds will not be changed under any
+ * circumstances.
+ *
+ * Observe that if no configuration is provided (or all flags are set to
+ * false), this method will only modify the y-axis bounds if they are empty.
+ */
+ autoSetFromRange(range, opt_config) {
+ if (range.isEmpty) return;
+
+ const bounds = this.bounds;
+ if (bounds.isEmpty) {
+ bounds.addRange(range);
+ return;
+ }
+
+ if (!opt_config) return;
+
+ const useRangeMin = (opt_config.expandMin && range.min < bounds.min ||
+ opt_config.shrinkMin && range.min > bounds.min);
+ const useRangeMax = (opt_config.expandMax && range.max > bounds.max ||
+ opt_config.shrinkMax && range.max < bounds.max);
+
+ // Neither bound is modified.
+ if (!useRangeMin && !useRangeMax) return;
+
+ // Both bounds are modified. Assuming the range argument is a valid
+ // range, no extra checks are necessary.
+ if (useRangeMin && useRangeMax) {
+ bounds.min = range.min;
+ bounds.max = range.max;
+ return;
+ }
+
+ // Only one bound is modified. We must ensure that it doesn't go
+ // over/under the other (unmodified) bound.
+ if (useRangeMin) {
+ bounds.min = Math.min(range.min, bounds.max);
+ } else {
+ bounds.max = Math.max(range.max, bounds.min);
+ }
+ },
+
+
+ majorMarkHeightWorld_(transform, pixelRatio) {
+ const idealMajorMarkHeightPx = IDEAL_MAJOR_MARK_HEIGHT_PX * pixelRatio;
+ const idealMajorMarkHeightWorld =
+ transform.vectorToWorldDistance(idealMajorMarkHeightPx);
+
+ return tr.b.math.preferredNumberLargerThanMin(idealMajorMarkHeightWorld);
+ },
+
+ draw(ctx, transform, showYAxisLabels, showYGridLines) {
+ if (!showYAxisLabels && !showYGridLines) return;
+
+ const pixelRatio = transform.pixelRatio;
+ const viewTop = transform.outerTopViewY;
+ const worldTop = transform.viewYToWorldY(viewTop);
+ const viewBottom = transform.outerBottomViewY;
+ const viewHeight = viewBottom - viewTop;
+ const viewLeft = transform.leftViewX;
+ const viewRight = transform.rightViewX;
+ const labelLeft = transform.leftYLabel;
+
+ ctx.save();
+ ctx.lineWidth = pixelRatio;
+ ctx.fillStyle = ColorScheme.getColorForReservedNameAsString('black');
+ ctx.textAlign = 'left';
+ ctx.textBaseline = 'center';
+
+ ctx.font =
+ (AXIS_LABLE_FONT_SIZE_PX * pixelRatio) + 'px ' + AXIS_LABLE_FONT;
+
+ // Draw left edge of chart series.
+ ctx.beginPath();
+ ctx.strokeStyle = ColorScheme.getColorForReservedNameAsString('black');
+ tr.ui.b.drawLine(
+ ctx, viewLeft, viewTop, viewLeft, viewBottom, viewLeft);
+ ctx.stroke();
+ ctx.closePath();
+
+ // Draw y-axis ticks and gridlines.
+ ctx.beginPath();
+ ctx.strokeStyle = ColorScheme.getColorForReservedNameAsString('grey');
+
+ const majorMarkHeight = this.majorMarkHeightWorld_(transform, pixelRatio);
+ const maxMajorMark = Math.max(transform.viewYToWorldY(viewTop),
+ Math.abs(transform.viewYToWorldY(viewBottom)));
+ for (let curWorldY = 0;
+ curWorldY <= maxMajorMark;
+ curWorldY += majorMarkHeight) {
+ const roundedUnitValue = Math.floor(curWorldY * 1000000) / 1000000;
+ const curViewYPositive = transform.worldYToViewY(curWorldY);
+ if (curViewYPositive >= viewTop) {
+ if (showYAxisLabels) {
+ ctx.fillText(roundedUnitValue, viewLeft + AXIS_LABLE_MARGIN_PX,
+ curViewYPositive - AXIS_LABLE_MARGIN_PX);
+ }
+ if (showYGridLines) {
+ tr.ui.b.drawLine(
+ ctx, viewLeft, curViewYPositive, viewRight, curViewYPositive);
+ }
+ }
+
+ const curViewYNegative = transform.worldYToViewY(-1 * curWorldY);
+ if (curViewYNegative <= viewBottom) {
+ if (showYAxisLabels) {
+ ctx.fillText(roundedUnitValue, viewLeft + AXIS_LABLE_MARGIN_PX,
+ curViewYNegative - AXIS_LABLE_MARGIN_PX);
+ }
+ if (showYGridLines) {
+ tr.ui.b.drawLine(
+ ctx, viewLeft, curViewYNegative, viewRight, curViewYNegative);
+ }
+ }
+ }
+ ctx.stroke();
+ ctx.restore();
+ }
+ };
+
+ return {
+ ChartSeriesYAxis,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_y_axis_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_y_axis_test.html
new file mode 100644
index 00000000000..4a759e040d4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_series_y_axis_test.html
@@ -0,0 +1,313 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/tracks/chart_point.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series_y_axis.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ChartSeriesYAxis = tr.ui.tracks.ChartSeriesYAxis;
+ const ChartPoint = tr.ui.tracks.ChartPoint;
+ const ChartSeries = tr.ui.tracks.ChartSeries;
+ const Range = tr.b.math.Range;
+
+ function buildRange() {
+ const range = new Range();
+ for (let i = 0; i < arguments.length; i++) {
+ range.addValue(arguments[i]);
+ }
+ return range;
+ }
+
+ function buildSeries() {
+ const points = [];
+ for (let i = 0; i < arguments.length; i++) {
+ points.push(new ChartPoint(undefined, i, arguments[i]));
+ }
+ return new ChartSeries(points, new ChartSeriesYAxis());
+ }
+
+ test('instantiate_emptyBounds', function() {
+ const seriesYAxis = new ChartSeriesYAxis();
+ assert.isTrue(seriesYAxis.bounds.isEmpty);
+ });
+
+ test('instantiate_nonEmptyBounds', function() {
+ const seriesYAxis = new ChartSeriesYAxis(-2, 12);
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, -2);
+ assert.strictEqual(seriesYAxis.bounds.max, 12);
+ });
+
+ test('instantiate_equalBounds', function() {
+ const seriesYAxis = new ChartSeriesYAxis(2.72);
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 2.72);
+ assert.strictEqual(seriesYAxis.bounds.max, 2.72);
+ });
+
+ test('checkValueToUnitRange_emptyBounds', function() {
+ const seriesYAxis = new ChartSeriesYAxis();
+ assert.throws(function() { seriesYAxis.valueToUnitRange(42); });
+ });
+
+ test('checkValueToUnitRange_nonEmptyBounds', function() {
+ const seriesYAxis = new ChartSeriesYAxis(10, 20);
+
+ assert.strictEqual(seriesYAxis.valueToUnitRange(0), -1);
+ assert.strictEqual(seriesYAxis.valueToUnitRange(10), 0);
+ assert.strictEqual(seriesYAxis.valueToUnitRange(15), 0.5);
+ assert.strictEqual(seriesYAxis.valueToUnitRange(20), 1);
+ assert.strictEqual(seriesYAxis.valueToUnitRange(30), 2);
+ });
+
+ test('checkValueToUnitRange_equalBounds', function() {
+ const seriesYAxis = new ChartSeriesYAxis(3.14);
+
+ assert.strictEqual(seriesYAxis.valueToUnitRange(0), 0);
+ assert.strictEqual(seriesYAxis.valueToUnitRange(3.14), 0);
+ assert.strictEqual(seriesYAxis.valueToUnitRange(6.28), 0);
+ });
+
+ test('checkAutoSetFromRange_emptyBounds', function() {
+ // Empty range.
+ let seriesYAxis = new ChartSeriesYAxis();
+ seriesYAxis.autoSetFromRange(buildRange());
+ assert.isTrue(seriesYAxis.bounds.isEmpty);
+
+ // Non-empty range.
+ seriesYAxis = new ChartSeriesYAxis();
+ seriesYAxis.autoSetFromRange(buildRange(-1, 3));
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, -1);
+ assert.strictEqual(seriesYAxis.bounds.max, 3);
+ });
+
+ test('checkAutoSetFromRange_nonEmptyBounds', function() {
+ // Empty range.
+ let seriesYAxis = new ChartSeriesYAxis(0, 1);
+ seriesYAxis.autoSetFromRange(buildRange());
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 0);
+ assert.strictEqual(seriesYAxis.bounds.max, 1);
+
+ // No configuration.
+ seriesYAxis = new ChartSeriesYAxis(2, 3);
+ seriesYAxis.autoSetFromRange(buildRange(1, 4));
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 2);
+ assert.strictEqual(seriesYAxis.bounds.max, 3);
+
+ // Allow expanding min.
+ seriesYAxis = new ChartSeriesYAxis(-2, -1);
+ seriesYAxis.autoSetFromRange(buildRange(-3, 0), {expandMin: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, -3);
+ assert.strictEqual(seriesYAxis.bounds.max, -1);
+
+ // Allow shrinking min.
+ seriesYAxis = new ChartSeriesYAxis(-2, -1);
+ seriesYAxis.autoSetFromRange(buildRange(-1.5, 0.5), {shrinkMin: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, -1.5);
+ assert.strictEqual(seriesYAxis.bounds.max, -1);
+
+ seriesYAxis = new ChartSeriesYAxis(7, 8);
+ seriesYAxis.autoSetFromRange(buildRange(9, 10), {shrinkMin: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 8);
+ assert.strictEqual(seriesYAxis.bounds.max, 8);
+
+ // Allow expanding max.
+ seriesYAxis = new ChartSeriesYAxis(19, 20);
+ seriesYAxis.autoSetFromRange(buildRange(18, 21), {expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 19);
+ assert.strictEqual(seriesYAxis.bounds.max, 21);
+
+ // Allow shrinking max.
+ seriesYAxis = new ChartSeriesYAxis(30, 32);
+ seriesYAxis.autoSetFromRange(buildRange(29, 31), {shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 30);
+ assert.strictEqual(seriesYAxis.bounds.max, 31);
+
+ seriesYAxis = new ChartSeriesYAxis(41, 42);
+ seriesYAxis.autoSetFromRange(buildRange(39, 40), {shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 41);
+ assert.strictEqual(seriesYAxis.bounds.max, 41);
+
+ // Allow shrinking both bounds.
+ seriesYAxis = new ChartSeriesYAxis(50, 53);
+ seriesYAxis.autoSetFromRange(buildRange(51, 52),
+ {shrinkMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 51);
+ assert.strictEqual(seriesYAxis.bounds.max, 52);
+
+ seriesYAxis = new ChartSeriesYAxis(50, 53);
+ seriesYAxis.autoSetFromRange(buildRange(49, 52),
+ {shrinkMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 50);
+ assert.strictEqual(seriesYAxis.bounds.max, 52);
+
+ seriesYAxis = new ChartSeriesYAxis(50, 53);
+ seriesYAxis.autoSetFromRange(buildRange(51, 54),
+ {shrinkMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 51);
+ assert.strictEqual(seriesYAxis.bounds.max, 53);
+
+ seriesYAxis = new ChartSeriesYAxis(50, 53);
+ seriesYAxis.autoSetFromRange(buildRange(49, 54),
+ {shrinkMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 50);
+ assert.strictEqual(seriesYAxis.bounds.max, 53);
+
+ // Allow expanding both bounds.
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(0, 100),
+ {expandMin: true, expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 0);
+ assert.strictEqual(seriesYAxis.bounds.max, 100);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(60.5, 100),
+ {expandMin: true, expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 60);
+ assert.strictEqual(seriesYAxis.bounds.max, 100);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(0, 60.5),
+ {expandMin: true, expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 0);
+ assert.strictEqual(seriesYAxis.bounds.max, 61);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(60.2, 60.8),
+ {expandMin: true, expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 60);
+ assert.strictEqual(seriesYAxis.bounds.max, 61);
+
+ // Allow shrinking min and expanding max.
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(62, 63),
+ {shrinkMin: true, expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 62);
+ assert.strictEqual(seriesYAxis.bounds.max, 63);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(59, 63),
+ {shrinkMin: true, expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 60);
+ assert.strictEqual(seriesYAxis.bounds.max, 63);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(60.2, 60.8),
+ {shrinkMin: true, expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 60.2);
+ assert.strictEqual(seriesYAxis.bounds.max, 61);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(59, 60.5),
+ {shrinkMin: true, expandMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 60);
+ assert.strictEqual(seriesYAxis.bounds.max, 61);
+
+ // Allow expanding min and shrinking max.
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(62, 63),
+ {expandMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 60);
+ assert.strictEqual(seriesYAxis.bounds.max, 61);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(59, 63),
+ {expandMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 59);
+ assert.strictEqual(seriesYAxis.bounds.max, 61);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(60.2, 60.8),
+ {expandMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 60);
+ assert.strictEqual(seriesYAxis.bounds.max, 60.8);
+
+ seriesYAxis = new ChartSeriesYAxis(60, 61);
+ seriesYAxis.autoSetFromRange(buildRange(59, 60.5),
+ {expandMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 59);
+ assert.strictEqual(seriesYAxis.bounds.max, 60.5);
+
+ // Allow everything.
+ seriesYAxis = new ChartSeriesYAxis(200, 250);
+ seriesYAxis.autoSetFromRange(buildRange(150, 175),
+ {expandMin: true, expandMax: true, shrinkMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 150);
+ assert.strictEqual(seriesYAxis.bounds.max, 175);
+
+ seriesYAxis = new ChartSeriesYAxis(0, 0.1);
+ seriesYAxis.autoSetFromRange(buildRange(0.2, 0.3),
+ {expandMin: true, expandMax: true, shrinkMin: true, shrinkMax: true});
+ assert.isFalse(seriesYAxis.bounds.isEmpty);
+ assert.strictEqual(seriesYAxis.bounds.min, 0.2);
+ assert.strictEqual(seriesYAxis.bounds.max, 0.3);
+ });
+
+ test('checkAutoSetFromSeries_noSeries', function() {
+ const seriesYAxis = new ChartSeriesYAxis(-100, 100);
+ const series = [];
+
+ seriesYAxis.autoSetFromSeries(series);
+ assert.strictEqual(seriesYAxis.bounds.min, -100);
+ assert.strictEqual(seriesYAxis.bounds.max, 100);
+ });
+
+ test('checkAutoSetFromSeries_oneSeries', function() {
+ const seriesYAxis = new ChartSeriesYAxis(-100, 100);
+ const series = [buildSeries(-80, 100, -40, 200)];
+
+ seriesYAxis.autoSetFromSeries(series, {shrinkMin: true, expandMax: true});
+ assert.strictEqual(seriesYAxis.bounds.min, -80);
+ assert.strictEqual(seriesYAxis.bounds.max, 200);
+ });
+
+ test('checkAutoSetFromSeries_multipleSeries', function() {
+ const seriesYAxis = new ChartSeriesYAxis(-100, 100);
+ const series = [
+ buildSeries(0, 20, 10, 30),
+ buildSeries(),
+ buildSeries(-500)
+ ];
+
+ seriesYAxis.autoSetFromSeries(series, {expandMin: true, shrinkMax: true});
+ assert.strictEqual(seriesYAxis.bounds.min, -500);
+ assert.strictEqual(seriesYAxis.bounds.max, 30);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_track.html
new file mode 100644
index 00000000000..58ef08d651c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_track.html
@@ -0,0 +1,281 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/heading.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/chart_transform.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<style>
+.chart-track {
+ height: 30px;
+ position: relative;
+}
+</style>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays a chart.
+ *
+ * @constructor
+ * @extends {Track}
+ */
+ const ChartTrack =
+ tr.ui.b.define('chart-track', tr.ui.tracks.Track);
+
+ ChartTrack.prototype = {
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('chart-track');
+ this.series_ = undefined;
+ this.axes_ = undefined;
+
+ // GUID -> {axis: ChartSeriesYAxis, series: [ChartSeries]}.
+ this.axisGuidToAxisData_ = undefined;
+
+ // The maximum top and bottom padding of all series.
+ this.topPadding_ = undefined;
+ this.bottomPadding_ = undefined;
+
+ this.showYAxisLabels_ = undefined;
+ this.showGridLines_ = undefined;
+
+ this.heading_ = document.createElement('tr-ui-b-heading');
+ Polymer.dom(this).appendChild(this.heading_);
+ },
+
+ set heading(heading) {
+ this.heading_.heading = heading;
+ },
+
+ get heading() {
+ return this.heading_.heading;
+ },
+
+ set tooltip(tooltip) {
+ this.heading_.tooltip = tooltip;
+ },
+
+ get series() {
+ return this.series_;
+ },
+
+ /**
+ * Set the list of chart series to be displayed on this track. The list
+ * is assumed to be sorted in increasing z-order (i.e. the last series in
+ * the list will be drawn at the top).
+ */
+ set series(series) {
+ this.series_ = series;
+ this.calculateAxisDataAndPadding_();
+ this.invalidateDrawingContainer();
+ },
+
+ get height() {
+ return window.getComputedStyle(this).height;
+ },
+
+ set height(height) {
+ this.style.height = height;
+ this.invalidateDrawingContainer();
+ },
+
+ get showYAxisLabels() {
+ return this.showYAxisLabels_;
+ },
+
+ set showYAxisLabels(showYAxisLabels) {
+ this.showYAxisLabels_ = showYAxisLabels;
+ this.invalidateDrawingContainer();
+ },
+
+ get showGridLines() {
+ return this.showGridLines_;
+ },
+
+ set showGridLines(showGridLines) {
+ this.showGridLines_ = showGridLines;
+ this.invalidateDrawingContainer();
+ },
+
+ get hasVisibleContent() {
+ return !!this.series && this.series.length > 0;
+ },
+
+ calculateAxisDataAndPadding_() {
+ if (!this.series_) {
+ this.axes_ = undefined;
+ this.axisGuidToAxisData_ = undefined;
+ this.topPadding_ = undefined;
+ this.bottomPadding_ = undefined;
+ return;
+ }
+
+ const axisGuidToAxisData = {};
+ let topPadding = 0;
+ let bottomPadding = 0;
+
+ this.series_.forEach(function(series) {
+ const seriesYAxis = series.seriesYAxis;
+ const axisGuid = seriesYAxis.guid;
+ if (!(axisGuid in axisGuidToAxisData)) {
+ axisGuidToAxisData[axisGuid] = {
+ axis: seriesYAxis,
+ series: []
+ };
+ if (!this.axes_) this.axes_ = [];
+ this.axes_.push(seriesYAxis);
+ }
+ axisGuidToAxisData[axisGuid].series.push(series);
+ topPadding = Math.max(topPadding, series.topPadding);
+ bottomPadding = Math.max(bottomPadding, series.bottomPadding);
+ }, this);
+
+ this.axisGuidToAxisData_ = axisGuidToAxisData;
+ this.topPadding_ = topPadding;
+ this.bottomPadding_ = bottomPadding;
+ },
+
+ draw(type, viewLWorld, viewRWorld, viewHeight) {
+ switch (type) {
+ case tr.ui.tracks.DrawType.GENERAL_EVENT:
+ this.drawChart_(viewLWorld, viewRWorld);
+ break;
+ }
+ },
+
+ drawChart_(viewLWorld, viewRWorld) {
+ if (!this.series_) return;
+
+ const ctx = this.context();
+
+ // Get track drawing parameters.
+ const displayTransform = this.viewport.currentDisplayTransform;
+ const pixelRatio = window.devicePixelRatio || 1;
+ const bounds = this.getBoundingClientRect();
+ const highDetails = this.viewport.highDetails;
+
+ // Pre-multiply all device-independent pixel parameters with the pixel
+ // ratio to avoid unnecessary recomputation in the performance-critical
+ // drawing code.
+ const width = bounds.width * pixelRatio;
+ const height = bounds.height * pixelRatio;
+ const topPadding = this.topPadding_ * pixelRatio;
+ const bottomPadding = this.bottomPadding_ * pixelRatio;
+
+ // Set up clipping.
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(0, 0, width, height);
+ ctx.clip();
+
+ // TODO(aiolos): Add support for secondary y-axis on right side of chart.
+ // https://github.com/catapult-project/catapult/issues/3008
+ // Draw y-axis grid lines.
+ if (this.axes_) {
+ if ((this.showGridLines_ || this.showYAxisLabels_) &&
+ this.axes_.length > 1) {
+ throw new Error('Only one axis allowed when showing grid lines.');
+ }
+ for (const yAxis of this.axes_) {
+ const chartTransform = new tr.ui.tracks.ChartTransform(
+ displayTransform, yAxis, width, height,
+ topPadding, bottomPadding, pixelRatio);
+ yAxis.draw(
+ ctx, chartTransform, this.showYAxisLabels_, this.showGridLines_);
+ }
+ }
+
+ // Draw all series in the increasing z-order.
+ for (const series of this.series) {
+ const chartTransform = new tr.ui.tracks.ChartTransform(
+ displayTransform, series.seriesYAxis, width, height, topPadding,
+ bottomPadding, pixelRatio);
+ series.draw(ctx, chartTransform, highDetails);
+ }
+
+ // Stop clipping.
+ ctx.restore();
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ // TODO(petrcermak): Consider adding the series to the track map instead
+ // of the track (a potential performance optimization).
+ this.series_.forEach(function(series) {
+ series.points.forEach(function(point) {
+ point.addToTrackMap(eventToTrackMap, this);
+ }, this);
+ }, this);
+ },
+
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ this.series_.forEach(function(series) {
+ series.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection);
+ }, this);
+ },
+
+ addEventNearToProvidedEventToSelection(event, offset, selection) {
+ let foundItem = false;
+ this.series_.forEach(function(series) {
+ foundItem = foundItem || series.addEventNearToProvidedEventToSelection(
+ event, offset, selection);
+ }, this);
+ return foundItem;
+ },
+
+ addAllEventsMatchingFilterToSelection(filter, selection) {
+ // Do nothing.
+ },
+
+ addClosestEventToSelection(worldX, worldMaxDist, loY, hiY,
+ selection) {
+ this.series_.forEach(function(series) {
+ series.addClosestEventToSelection(
+ worldX, worldMaxDist, loY, hiY, selection);
+ }, this);
+ },
+
+ /**
+ * Automatically set the bounds of all axes on this track from the range of
+ * values of all series (in this track) associated with each of them.
+ *
+ * See the description of ChartSeriesYAxis.autoSetFromRange for the optional
+ * configuration argument flags.
+ */
+ autoSetAllAxes(opt_config) {
+ for (const axisData of Object.values(this.axisGuidToAxisData_)) {
+ const seriesYAxis = axisData.axis;
+ const series = axisData.series;
+ seriesYAxis.autoSetFromSeries(series, opt_config);
+ }
+ },
+
+ /**
+ * Automatically set the bounds of the provided axis from the range of
+ * values of all series (in this track) associated with it.
+ *
+ * See the description of ChartSeriesYAxis.autoSetFromRange for the optional
+ * configuration argument flags.
+ */
+ autoSetAxis(seriesYAxis, opt_config) {
+ const series = this.axisGuidToAxisData_[seriesYAxis.guid].series;
+ seriesYAxis.autoSetFromSeries(series, opt_config);
+ }
+ };
+
+ return {
+ ChartTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_track_test.html
new file mode 100644
index 00000000000..405640a9b2c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_track_test.html
@@ -0,0 +1,454 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+<link rel="import" href="/tracing/ui/tracks/chart_point.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series_y_axis.html">
+<link rel="import" href="/tracing/ui/tracks/chart_track.html">
+<link rel="import" href="/tracing/ui/tracks/event_to_track_map.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ChartSeriesYAxis = tr.ui.tracks.ChartSeriesYAxis;
+ const ChartPoint = tr.ui.tracks.ChartPoint;
+ const ChartSeries = tr.ui.tracks.ChartSeries;
+ const ChartSeriesType = tr.ui.tracks.ChartSeriesType;
+ const ChartTrack = tr.ui.tracks.ChartTrack;
+ const Event = tr.model.Event;
+ const EventSet = tr.model.EventSet;
+ const EventToTrackMap = tr.ui.tracks.EventToTrackMap;
+ const SelectionState = tr.model.SelectionState;
+ const Viewport = tr.ui.TimelineViewport;
+
+ function buildPoint(x, y) {
+ const event = new Event();
+ return new ChartPoint(event, x, y);
+ }
+
+ function buildTrack(opt_args) {
+ const viewport = (opt_args && opt_args.viewport) ?
+ opt_args.viewport : new Viewport(document.createElement('div'));
+
+ const seriesYAxis1 = new ChartSeriesYAxis(0, 2.5);
+
+ const points1 = [
+ buildPoint(-2.5, 2),
+ buildPoint(-1.5, 1),
+ buildPoint(-0.5, 0),
+ buildPoint(0.5, 1),
+ buildPoint(1.5, 2),
+ buildPoint(2.5, 0)
+ ];
+ const renderingConfig1 = {
+ chartType: ChartSeriesType.AREA,
+ colorId: 6,
+ selectedPointSize: 7
+ };
+ if (opt_args && opt_args.stepGraph !== undefined) {
+ renderingConfig1.stepGraph = opt_args.stepGraph;
+ }
+ const series1 = new ChartSeries(points1, seriesYAxis1, renderingConfig1);
+
+ const points2 = [
+ buildPoint(-2.3, 0.2),
+ buildPoint(-1.3, 1.2),
+ buildPoint(-0.3, 2.2),
+ buildPoint(0.3, 1.2),
+ buildPoint(1.3, 0.2),
+ buildPoint(2.3, 0)
+ ];
+ const renderingConfig2 = {
+ chartType: ChartSeriesType.AREA,
+ colorId: 4,
+ selectedPointSize: 10
+ };
+ if (opt_args && opt_args.stepGraph !== undefined) {
+ renderingConfig2.stepGraph = opt_args.stepGraph;
+ }
+ const series2 = new ChartSeries(points2, seriesYAxis1, renderingConfig2);
+
+ const seriesList = [series1, series2];
+
+ if (!opt_args || !opt_args.singleAxis) {
+ const seriesYAxis2 = new ChartSeriesYAxis(-100, 100);
+ const points3 = [
+ buildPoint(-3, -50),
+ buildPoint(-2.4, -40),
+ buildPoint(-1.8, -30),
+ buildPoint(-1.2, -20),
+ buildPoint(-0.6, -10),
+ buildPoint(0, 0),
+ buildPoint(0.6, 10),
+ buildPoint(1.2, 20),
+ buildPoint(1.8, 30),
+ buildPoint(2.4, 40),
+ buildPoint(3, 50)
+ ];
+ const renderingConfig3 = {
+ chartType: ChartSeriesType.LINE,
+ lineWidth: 2
+ };
+ if (opt_args && opt_args.stepGraph !== undefined) {
+ renderingConfig3.stepGraph = opt_args.stepGraph;
+ }
+ const series3 = new ChartSeries(points3, seriesYAxis2, renderingConfig3);
+ seriesList.push(series3);
+ }
+
+ const track = new ChartTrack(viewport);
+ track.series = seriesList;
+
+ return track;
+ }
+
+ function buildDashboardTrack(opt_viewport) {
+ const viewport = opt_viewport || new Viewport(
+ document.createElement('div'));
+
+ const seriesYAxis = new ChartSeriesYAxis(0, 1.1);
+ const fileUrl = '/test_data/dashboard_test_points.json';
+ const pointsArray = JSON.parse(tr.b.getSync(fileUrl));
+ const points = [];
+ for (let i = 0; i < pointsArray.length; i++) {
+ points.push(buildPoint(pointsArray[i][0], pointsArray[i][1]));
+ }
+ const renderingConfig = {
+ chartType: ChartSeriesType.LINE,
+ lineWidth: 1,
+ stepGraph: false,
+ selectedPointSize: 10,
+ solidSelectedDots: true,
+ highDetail: false,
+ skipDistance: 0.4
+ };
+ const series = new ChartSeries(points, seriesYAxis, renderingConfig);
+
+ const track = new ChartTrack(viewport);
+ track.series = [series];
+
+ return track;
+ }
+
+ test('instantiate_lowDetailsWithoutSelection', function() {
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = buildTrack({viewport});
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ track.height = '100px';
+ });
+
+ test('instantiate_highDetailsWithSelection', function() {
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ viewport.highDetails = true;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = buildTrack({viewport});
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ track.series[0].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+ track.series[1].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+ track.series[2].points[3].modelItem.selectionState =
+ SelectionState.SELECTED;
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ track.height = '100px';
+ });
+
+ test('instantiate_lowDetailsNoStepGraphWithoutSelection', function() {
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = buildTrack({viewport, stepGraph: false});
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ track.height = '100px';
+ });
+
+ test('instantiate_highDetailsNoStepGraphWithSelection', function() {
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ viewport.highDetails = true;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = buildTrack({viewport, stepGraph: false});
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ track.series[0].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+ track.series[1].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+ track.series[2].points[3].modelItem.selectionState =
+ SelectionState.SELECTED;
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ track.height = '100px';
+ });
+
+ test('instantiate_highDetailsNoStepGraphWithSelectionAndYAxisLabels',
+ function() {
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ viewport.highDetails = true;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = buildTrack({
+ viewport,
+ stepGraph: false,
+ singleAxis: true,
+ });
+ track.showYAxisLabels = true;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ track.series[0].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+ track.series[1].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ track.height = '200px';
+ });
+
+ test('instantiate_highDetailsNoStepGraphWithSelectionAndGridLines',
+ function() {
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ viewport.highDetails = true;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = buildTrack({
+ viewport,
+ stepGraph: false,
+ singleAxis: true,
+ });
+ track.showGridLines = true;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ track.series[0].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+ track.series[1].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ track.height = '200px';
+ });
+
+ test('instantiate_highDetailsNoStepGraphWithSelectionYAxisLabelsAndGridLines',
+ function() {
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ viewport.highDetails = true;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = buildTrack({
+ viewport,
+ stepGraph: false,
+ singleAxis: true,
+ });
+ track.showYAxisLabels = true;
+ track.showGridLines = true;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ track.series[0].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+ track.series[1].points[1].modelItem.selectionState =
+ SelectionState.SELECTED;
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ dt.xSetWorldBounds(-3, 3, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ track.height = '200px';
+ });
+
+ test('instantiate_dashboardChartStyleWithSelection', function() {
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ viewport.highDetails = true;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = buildDashboardTrack(viewport);
+ track.showYAxisLabels = true;
+ track.showGridLines = true;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ track.series[0].points[40].modelItem.selectionState =
+ SelectionState.SELECTED;
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ dt.xSetWorldBounds(
+ 26610390797802200, 28950000891700000, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ track.height = '100px';
+ });
+
+ test('checkPadding', function() {
+ const track = buildTrack();
+
+ // Padding should be equal to half maximum point size.
+ assert.strictEqual(track.topPadding_, 5);
+ assert.strictEqual(track.bottomPadding_, 5);
+ });
+
+ test('checkAddEventsToTrackMap', function() {
+ const track = buildTrack();
+ const eventToTrackMap = new EventToTrackMap();
+ track.addEventsToTrackMap(eventToTrackMap);
+ assert.lengthOf(Object.keys(eventToTrackMap), 23);
+ });
+
+ test('checkaddIntersectingEventsInRangeToSelectionInWorldSpace', function() {
+ const track = buildTrack();
+
+ const sel = new EventSet();
+ track.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ -1.1, -0.7, 0.01, sel);
+ assert.lengthOf(sel, 3);
+ const iter = sel[Symbol.iterator]();
+ assert.strictEqual(iter.next().value, track.series[0].points[1].modelItem);
+ assert.strictEqual(iter.next().value, track.series[1].points[1].modelItem);
+ assert.strictEqual(iter.next().value, track.series[2].points[3].modelItem);
+ });
+
+ test('checkaddEventNearToProvidedEventToSelection', function() {
+ const track = buildTrack();
+
+ // Fail to find a near item to the left in any series.
+ let sel = new EventSet();
+ assert.isFalse(track.addEventNearToProvidedEventToSelection(
+ track.series[0].points[0].modelItem, -1, sel));
+ assert.lengthOf(sel, 0);
+
+ // Succeed at finding a near item to the right of one series.
+ sel = new EventSet();
+ assert.isTrue(track.addEventNearToProvidedEventToSelection(
+ track.series[1].points[1].modelItem, 1, sel));
+ assert.strictEqual(
+ tr.b.getOnlyElement(sel), track.series[1].points[2].modelItem);
+ });
+
+ test('checkAddClosestEventToSelection', function() {
+ const track = buildTrack();
+
+ const sel = new EventSet();
+ track.addClosestEventToSelection(-0.8, 0.4, 0.5, 1.5, sel);
+ assert.lengthOf(sel, 2);
+ const iter = sel[Symbol.iterator]();
+ assert.strictEqual(iter.next().value, track.series[0].points[2].modelItem);
+ assert.strictEqual(iter.next().value, track.series[2].points[4].modelItem);
+ });
+
+ test('checkAutoSetAllAxes', function() {
+ const track = buildTrack();
+ const seriesYAxis1 = track.series[0].seriesYAxis;
+ const seriesYAxis2 = track.series[2].seriesYAxis;
+
+ track.autoSetAllAxes({expandMax: true, shrinkMax: true});
+
+ // Min bounds of both axes should not have been modified.
+ assert.strictEqual(seriesYAxis1.bounds.min, 0);
+ assert.strictEqual(seriesYAxis2.bounds.min, -100);
+
+ // Max bounds of both axes should have been modified.
+ assert.strictEqual(seriesYAxis1.bounds.max, 2.2);
+ assert.strictEqual(seriesYAxis2.bounds.max, 50);
+ });
+
+ test('checkAutoSetAxis', function() {
+ const track = buildTrack();
+ const seriesYAxis1 = track.series[0].seriesYAxis;
+ const seriesYAxis2 = track.series[2].seriesYAxis;
+
+ track.autoSetAxis(seriesYAxis2,
+ {expandMin: true, shrinkMin: true, expandMax: true, shrinkMax: true});
+
+ // First axis should not have been modified.
+ assert.strictEqual(seriesYAxis1.bounds.min, 0);
+ assert.strictEqual(seriesYAxis1.bounds.max, 2.5);
+
+ // Second axis should have been modified.
+ assert.strictEqual(seriesYAxis2.bounds.min, -50);
+ assert.strictEqual(seriesYAxis2.bounds.max, 50);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_transform.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_transform.html
new file mode 100644
index 00000000000..f6bf6310116
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_transform.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A helper object encapsulating all parameters necessary to draw a chart
+ * series and provides conversion between world coordinates and physical
+ * pixels.
+ *
+ * All parameters (except for pixelRatio) are assumed to be in physical pixels
+ * (i.e. already pre-multiplied with pixelRatio).
+ *
+ * The diagram below explains the meaning of the resulting fields with
+ * respect to a chart track:
+ *
+ * outerTopViewY -> +--------------------/-\------+ <- Top padding
+ * innerTopViewY -> + - - - - - - - - - -| |- - - + <- Axis max
+ * | .. ==\-/== |
+ * | === Series === |
+ * | ==/-\== .. |
+ * innerBottomViewY -> + - - -Point- - - - - - - - - + <- Axis min
+ * outerBottomViewY -> +-------\-/-------------------+ <- Bottom padding
+ * ^ ^
+ * leftViewX rightViewX
+ * leftTimeStamp rightTimestamp
+ *
+ * Labels starting with a lower case letter are the resulting fields of the
+ * transform object. Labels starting with an upper case letter correspond
+ * to the relevant chart track concepts.
+ *
+ * @constructor
+ */
+ function ChartTransform(displayTransform, axis, trackWidth,
+ trackHeight, topPadding, bottomPadding, pixelRatio) {
+ this.pixelRatio = pixelRatio;
+
+ // X axis.
+ this.leftViewX = 0;
+ this.rightViewX = trackWidth;
+ this.leftTimestamp = displayTransform.xViewToWorld(this.leftViewX);
+ this.rightTimestamp = displayTransform.xViewToWorld(this.rightViewX);
+
+ this.displayTransform_ = displayTransform;
+
+ // Y axis.
+ this.outerTopViewY = 0;
+ this.innerTopViewY = topPadding;
+ this.innerBottomViewY = trackHeight - bottomPadding;
+ this.outerBottomViewY = trackHeight;
+
+ this.axis_ = axis;
+ this.innerHeight_ = this.innerBottomViewY - this.innerTopViewY;
+ }
+
+ ChartTransform.prototype = {
+ worldXToViewX(worldX) {
+ return this.displayTransform_.xWorldToView(worldX);
+ },
+
+ viewXToWorldX(viewX) {
+ return this.displayTransform_.xViewToWorld(viewX);
+ },
+
+ vectorToWorldDistance(viewY) {
+ return this.axis_.bounds.range * Math.abs(viewY / this.innerHeight_);
+ },
+
+ viewYToWorldY(viewY) {
+ return this.axis_.unitRangeToValue(
+ 1 - (viewY - this.innerTopViewY) / this.innerHeight_);
+ },
+
+ worldYToViewY(worldY) {
+ const innerHeightCoefficient = 1 - this.axis_.valueToUnitRange(worldY);
+ return innerHeightCoefficient * this.innerHeight_ + this.innerTopViewY;
+ }
+ };
+
+ return {
+ ChartTransform,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_transform_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_transform_test.html
new file mode 100644
index 00000000000..8d46e08aace
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/chart_transform_test.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/timeline_display_transform.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series_y_axis.html">
+<link rel="import" href="/tracing/ui/tracks/chart_transform.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const TimelineDisplayTransform = tr.ui.TimelineDisplayTransform;
+ const ChartTransform = tr.ui.tracks.ChartTransform;
+ const ChartSeriesYAxis = tr.ui.tracks.ChartSeriesYAxis;
+
+ function buildChartTransform() {
+ const displayTransform = new TimelineDisplayTransform();
+ displayTransform.panX = -20;
+ displayTransform.scaleX = 0.5;
+
+ const seriesYAxis = new ChartSeriesYAxis(-100, 100);
+
+ const chartTransform = new ChartTransform(
+ displayTransform,
+ seriesYAxis,
+ 500, /* trackWidth */
+ 80, /* trackHeight */
+ 15, /* topPadding */
+ 5, /* bottomPadding */
+ 3 /* pixelRatio */);
+
+ return chartTransform;
+ }
+
+ test('checkFields', function() {
+ const t = buildChartTransform();
+
+ assert.strictEqual(t.pixelRatio, 3);
+
+ assert.strictEqual(t.leftViewX, 0);
+ assert.strictEqual(t.rightViewX, 500);
+ assert.strictEqual(t.leftTimestamp, 20);
+ assert.strictEqual(t.rightTimestamp, 1020);
+
+ assert.strictEqual(t.outerTopViewY, 0);
+ assert.strictEqual(t.innerTopViewY, 15);
+ assert.strictEqual(t.innerBottomViewY, 75);
+ assert.strictEqual(t.outerBottomViewY, 80);
+ });
+
+ test('checkWorldXToViewX', function() {
+ const t = buildChartTransform();
+
+ assert.strictEqual(t.worldXToViewX(-100), -60);
+ assert.strictEqual(t.worldXToViewX(0), -10);
+ assert.strictEqual(t.worldXToViewX(520), 250);
+ assert.strictEqual(t.worldXToViewX(1020), 500);
+ assert.strictEqual(t.worldXToViewX(1200), 590);
+ });
+
+ test('checkViewXToWorldX', function() {
+ const t = buildChartTransform();
+
+ assert.strictEqual(t.viewXToWorldX(-60), -100);
+ assert.strictEqual(t.viewXToWorldX(-10), 0);
+ assert.strictEqual(t.viewXToWorldX(250), 520);
+ assert.strictEqual(t.viewXToWorldX(500), 1020);
+ assert.strictEqual(t.viewXToWorldX(590), 1200);
+ });
+
+ test('checkWorldYToViewY', function() {
+ const t = buildChartTransform();
+
+ assert.strictEqual(t.worldYToViewY(-200), 105);
+ assert.strictEqual(t.worldYToViewY(-100), 75);
+ assert.strictEqual(t.worldYToViewY(0), 45);
+ assert.strictEqual(t.worldYToViewY(100), 15);
+ assert.strictEqual(t.worldYToViewY(200), -15);
+ });
+
+ test('checkViewYToWorldY', function() {
+ const t = buildChartTransform();
+
+ assert.strictEqual(t.viewYToWorldY(105), -200);
+ assert.strictEqual(t.viewYToWorldY(75), -100);
+ assert.strictEqual(t.viewYToWorldY(45), 0);
+ assert.strictEqual(t.viewYToWorldY(15), 100);
+ assert.strictEqual(t.viewYToWorldY(-15), 200);
+ });
+
+ test('checkVectorToWorldDistance', function() {
+ const t = buildChartTransform();
+
+ assert.strictEqual(t.vectorToWorldDistance(105), 350);
+ assert.strictEqual(t.vectorToWorldDistance(75), 250);
+ assert.strictEqual(t.vectorToWorldDistance(45), 150);
+ assert.strictEqual(t.vectorToWorldDistance(15), 50);
+ assert.strictEqual(t.vectorToWorldDistance(-15), 50);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/container_to_track_map.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/container_to_track_map.html
new file mode 100644
index 00000000000..ecaac0dd3b1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/container_to_track_map.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * ContainerToTrackMap is a class to handle building and accessing a map
+ * between an EventContainer's stableId and its handling track.
+ *
+ * @constructor
+ */
+ function ContainerToTrackMap() {
+ this.stableIdToTrackMap_ = {};
+ }
+
+ ContainerToTrackMap.prototype = {
+ addContainer(container, track) {
+ if (!track) {
+ throw new Error('Must provide a track.');
+ }
+ this.stableIdToTrackMap_[container.stableId] = track;
+ },
+
+ clear() {
+ this.stableIdToTrackMap_ = {};
+ },
+
+ getTrackByStableId(stableId) {
+ return this.stableIdToTrackMap_[stableId];
+ }
+ };
+
+ return {
+ ContainerToTrackMap,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/container_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/container_track.html
new file mode 100644
index 00000000000..454c1df585c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/container_track.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/task.html">
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const Task = tr.b.Task;
+
+ /**
+ * A generic track that contains other tracks as its children.
+ * @constructor
+ */
+ const ContainerTrack = tr.ui.b.define('container-track', tr.ui.tracks.Track);
+ ContainerTrack.prototype = {
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ },
+
+ detach() {
+ Polymer.dom(this).textContent = '';
+ },
+
+ get tracks_() {
+ const tracks = [];
+ for (let i = 0; i < this.children.length; i++) {
+ if (this.children[i] instanceof tr.ui.tracks.Track) {
+ tracks.push(this.children[i]);
+ }
+ }
+ return tracks;
+ },
+
+ drawTrack(type) {
+ this.tracks_.forEach(function(track) {
+ track.drawTrack(type);
+ });
+ },
+
+ /**
+ * Adds items intersecting the given range to a selection.
+ * @param {number} loVX Lower X bound of the interval to search, in
+ * viewspace.
+ * @param {number} hiVX Upper X bound of the interval to search, in
+ * viewspace.
+ * @param {number} loY Lower Y bound of the interval to search, in
+ * viewspace space.
+ * @param {number} hiY Upper Y bound of the interval to search, in
+ * viewspace space.
+ * @param {Selection} selection Selection to which to add results.
+ */
+ addIntersectingEventsInRangeToSelection(
+ loVX, hiVX, loY, hiY, selection) {
+ for (let i = 0; i < this.tracks_.length; i++) {
+ const trackClientRect = this.tracks_[i].getBoundingClientRect();
+ const a = Math.max(loY, trackClientRect.top);
+ const b = Math.min(hiY, trackClientRect.bottom);
+ if (a <= b) {
+ this.tracks_[i].addIntersectingEventsInRangeToSelection(
+ loVX, hiVX, loY, hiY, selection);
+ }
+ }
+
+ tr.ui.tracks.Track.prototype.addIntersectingEventsInRangeToSelection.
+ apply(this, arguments);
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ for (const track of this.tracks_) {
+ track.addEventsToTrackMap(eventToTrackMap);
+ }
+ },
+
+ addAllEventsMatchingFilterToSelection(filter, selection) {
+ for (let i = 0; i < this.tracks_.length; i++) {
+ this.tracks_[i].addAllEventsMatchingFilterToSelection(
+ filter, selection);
+ }
+ },
+
+ addAllEventsMatchingFilterToSelectionAsTask(filter, selection) {
+ const task = new Task();
+ for (let i = 0; i < this.tracks_.length; i++) {
+ task.subTask(function(i) {
+ return function() {
+ this.tracks_[i].addAllEventsMatchingFilterToSelection(
+ filter, selection);
+ };
+ }(i), this);
+ }
+ return task;
+ },
+
+ addClosestEventToSelection(
+ worldX, worldMaxDist, loY, hiY, selection) {
+ for (let i = 0; i < this.tracks_.length; i++) {
+ const trackClientRect = this.tracks_[i].getBoundingClientRect();
+ const a = Math.max(loY, trackClientRect.top);
+ const b = Math.min(hiY, trackClientRect.bottom);
+ if (a <= b) {
+ this.tracks_[i].addClosestEventToSelection(
+ worldX, worldMaxDist, loY, hiY, selection);
+ }
+ }
+
+ tr.ui.tracks.Track.prototype.addClosestEventToSelection.
+ apply(this, arguments);
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ this.tracks_.forEach(function(track) {
+ track.addContainersToTrackMap(containerToTrackMap);
+ });
+ },
+
+ clearTracks_() {
+ this.tracks_.forEach(function(track) {
+ Polymer.dom(this).removeChild(track);
+ }, this);
+ }
+ };
+
+ return {
+ ContainerTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track.html
new file mode 100644
index 00000000000..7f25e41bf6a
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/chart_point.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series_y_axis.html">
+<link rel="import" href="/tracing/ui/tracks/chart_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays a Counter object.
+ * @constructor
+ * @extends {ChartTrack}
+ */
+ const CounterTrack = tr.ui.b.define('counter-track', tr.ui.tracks.ChartTrack);
+
+ CounterTrack.prototype = {
+ __proto__: tr.ui.tracks.ChartTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ChartTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('counter-track');
+ },
+
+ get counter() {
+ return this.chart;
+ },
+
+ set counter(counter) {
+ this.heading = counter.name + ': ';
+ this.series = CounterTrack.buildChartSeriesFromCounter(counter);
+ this.autoSetAllAxes({expandMax: true});
+ },
+
+ getModelEventFromItem(chartValue) {
+ return chartValue;
+ }
+ };
+
+ CounterTrack.buildChartSeriesFromCounter = function(counter) {
+ const numSeries = counter.series.length;
+ const totals = counter.totals;
+
+ // Create one common axis for all series.
+ const seriesYAxis = new tr.ui.tracks.ChartSeriesYAxis(0, undefined);
+
+ // Build one chart series for each counter series.
+ const chartSeries = counter.series.map(function(series, seriesIndex) {
+ const chartPoints = series.samples.map(function(sample, sampleIndex) {
+ const total = totals[sampleIndex * numSeries + seriesIndex];
+ return new tr.ui.tracks.ChartPoint(sample, sample.timestamp, total);
+ });
+ const renderingConfig = {
+ chartType: tr.ui.tracks.ChartSeriesType.AREA,
+ colorId: series.color
+ };
+ return new tr.ui.tracks.ChartSeries(
+ chartPoints, seriesYAxis, renderingConfig);
+ });
+
+ // Show the first series (with the smallest cumulative value) at the top.
+ chartSeries.reverse();
+
+ return chartSeries;
+ };
+
+ return {
+ CounterTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track_perf_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track_perf_test.html
new file mode 100644
index 00000000000..3a4f84a14b4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track_perf_test.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/full_config.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function getSynchronous(url) {
+ const req = new XMLHttpRequest();
+ req.open('GET', url, false);
+ // Without the mime type specified like this, the file's bytes are not
+ // retrieved correctly.
+ req.overrideMimeType('text/plain; charset=x-user-defined');
+ req.send(null);
+ return req.responseText;
+ }
+
+ const ZOOM_STEPS = 10;
+ const ZOOM_COEFFICIENT = 1.2;
+
+ let model = undefined;
+
+ let drawingContainer;
+ let viewportDiv;
+
+ let viewportWidth;
+ let worldMid;
+
+ let startScale = undefined;
+
+ function timedCounterTrackPerfTest(name, testFn, iterations) {
+ function setUpOnce() {
+ if (model !== undefined) return;
+
+ const fileUrl = '/test_data/counter_tracks.html';
+ const events = getSynchronous(fileUrl);
+ model = tr.c.TestUtils.newModelWithEvents([events]);
+ }
+
+ function setUp() {
+ setUpOnce();
+ viewportDiv = document.createElement('div');
+
+ const viewport = new tr.ui.TimelineViewport(viewportDiv);
+
+ drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ viewport.modelTrackContainer = drawingContainer;
+
+ const modelTrack = new tr.ui.tracks.ModelTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(modelTrack);
+
+ modelTrack.model = model;
+
+ Polymer.dom(viewportDiv).appendChild(drawingContainer);
+
+ this.addHTMLOutput(viewportDiv);
+
+ // Size the canvas.
+ drawingContainer.updateCanvasSizeIfNeeded_();
+
+ // Size the viewport.
+ viewportWidth = drawingContainer.canvas.width;
+ const min = model.bounds.min;
+ const range = model.bounds.range;
+ worldMid = min + range / 2;
+
+ const boost = range * 0.15;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(min - boost, min + range + boost, viewportWidth);
+ modelTrack.viewport.setDisplayTransformImmediately(dt);
+ startScale = dt.scaleX;
+
+ // Select half of the counter samples.
+ for (const pid in model.processes) {
+ const counters = model.processes[pid].counters;
+ for (const cid in counters) {
+ const series = counters[cid].series;
+ for (let i = 0; i < series.length; i++) {
+ const samples = series[i].samples;
+ for (let j = Math.floor(samples.length / 2); j < samples.length;
+ j++) {
+ samples[j].selectionState =
+ tr.model.SelectionState.SELECTED;
+ }
+ }
+ }
+ }
+ }
+
+ function tearDown() {
+ viewportDiv.innerText = '';
+ drawingContainer = undefined;
+ }
+
+ timedPerfTest(name, testFn, {
+ setUp,
+ tearDown,
+ iterations
+ });
+ }
+
+ const n110100 = [1, 10, 100];
+ n110100.forEach(function(val) {
+ timedCounterTrackPerfTest(
+ 'draw_softwareCanvas_' + val,
+ function() {
+ let scale = startScale;
+ for (let i = 0; i < ZOOM_STEPS; i++) {
+ const dt =
+ drawingContainer.viewport.currentDisplayTransform.clone();
+ scale *= ZOOM_COEFFICIENT;
+ dt.scaleX = scale;
+ dt.xPanWorldPosToViewPos(worldMid, 'center', viewportWidth);
+ drawingContainer.viewport.setDisplayTransformImmediately(dt);
+ drawingContainer.draw_();
+ }
+ }, val);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track_test.html
new file mode 100644
index 00000000000..dd0286b6b67
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/counter_track_test.html
@@ -0,0 +1,205 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const Counter = tr.model.Counter;
+ const Viewport = tr.ui.TimelineViewport;
+ const CounterTrack = tr.ui.tracks.CounterTrack;
+
+ const runTest = function(timestamps, samples, testFn) {
+ const testEl = document.createElement('div');
+
+ const ctr = new Counter(undefined, 'foo', '', 'foo');
+ const n = samples.length;
+
+ for (let i = 0; i < n; ++i) {
+ ctr.addSeries(new tr.model.CounterSeries('value' + i,
+ ColorScheme.getColorIdForGeneralPurposeString('value' + i)));
+ }
+
+ for (let i = 0; i < samples.length; ++i) {
+ for (let k = 0; k < timestamps.length; ++k) {
+ ctr.series[i].addCounterSample(timestamps[k], samples[i][k]);
+ }
+ }
+
+ ctr.updateBounds();
+
+ const viewport = new Viewport(testEl);
+
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(testEl).appendChild(drawingContainer);
+
+ const track = new CounterTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ this.addHTMLOutput(testEl);
+
+ // Force the container to update sizes so the test can use coordinates that
+ // make sense. This has to be after the adding of the track as we need to
+ // use the track header to figure out our positioning.
+ drawingContainer.updateCanvasSizeIfNeeded_();
+
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ track.heading = ctr.name;
+ track.counter = ctr;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 10, track.clientWidth * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ testFn(ctr, drawingContainer, track);
+ };
+
+ test('instantiate', function() {
+ const ctr = new Counter(undefined, 'testBasicCounter', '',
+ 'testBasicCounter');
+ ctr.addSeries(new tr.model.CounterSeries('value1',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ 'testBasicCounter.value1')));
+ ctr.addSeries(new tr.model.CounterSeries('value2',
+ ColorScheme.getColorIdForGeneralPurposeString(
+ 'testBasicCounter.value2')));
+
+ const timestamps = [0, 1, 2, 3, 4, 5, 6, 7];
+ const samples = [[0, 3, 1, 2, 3, 1, 3, 3.1],
+ [5, 3, 1, 1.1, 0, 7, 0, 0.5]];
+ for (let i = 0; i < samples.length; ++i) {
+ for (let k = 0; k < timestamps.length; ++k) {
+ ctr.series[i].addCounterSample(timestamps[k], samples[i][k]);
+ }
+ }
+
+ ctr.updateBounds();
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = new CounterTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.heading = ctr.name;
+ track.counter = ctr;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 7.7, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ test('basicCounterXPointPicking', function() {
+ const timestamps = [0, 1, 2, 3, 4, 5, 6, 7];
+ const samples = [[0, 3, 1, 2, 3, 1, 3, 3.1],
+ [5, 3, 1, 1.1, 0, 7, 0, 0.5]];
+
+ runTest.call(this, timestamps, samples, function(ctr, container, track) {
+ const clientRect = track.getBoundingClientRect();
+ const y75 = clientRect.top + (0.75 * clientRect.height);
+
+ // In bounds.
+ let sel = new tr.model.EventSet();
+ let x = 0.15 * clientRect.width;
+ track.addIntersectingEventsInRangeToSelection(
+ x, x + 1, y75, y75 + 1, sel);
+
+ let nextSeriesIndex = 1;
+ assert.strictEqual(sel.length, 2);
+ for (const event of sel) {
+ assert.strictEqual(event.series.counter, ctr);
+ assert.strictEqual(event.getSampleIndex(), 1);
+ assert.strictEqual(event.series.seriesIndex, nextSeriesIndex--);
+ }
+
+ // Outside bounds.
+ sel = new tr.model.EventSet();
+ x = -0.5 * clientRect.width;
+ track.addIntersectingEventsInRangeToSelection(
+ x, x + 1, y75, y75 + 1, sel);
+ assert.strictEqual(sel.length, 0);
+
+ sel = new tr.model.EventSet();
+ x = 0.8 * clientRect.width;
+ track.addIntersectingEventsInRangeToSelection(
+ x, x + 1, y75, y75 + 1, sel);
+ assert.strictEqual(sel.length, 0);
+ });
+ });
+
+ test('counterTrackAddClosestEventToSelection', function() {
+ const timestamps = [0, 1, 2, 3, 4, 5, 6, 7];
+ const samples = [[0, 4, 1, 2, 3, 1, 3, 3.1],
+ [5, 3, 1, 1.1, 0, 7, 0, 0.5]];
+
+ runTest.call(this, timestamps, samples, function(ctr, container, track) {
+ // Before with not range.
+ let sel = new tr.model.EventSet();
+ track.addClosestEventToSelection(-1, 0, 0, 0, sel);
+ assert.strictEqual(sel.length, 0);
+
+ // Before with negative range.
+ sel = new tr.model.EventSet();
+ track.addClosestEventToSelection(-1, -10, 0, 0, sel);
+ assert.strictEqual(sel.length, 0);
+
+ // Before first sample.
+ sel = new tr.model.EventSet();
+ track.addClosestEventToSelection(-1, 1, 0, 0, sel);
+ assert.strictEqual(sel.length, 2);
+ for (const event of sel) {
+ assert.strictEqual(event.getSampleIndex(), 0);
+ }
+
+ // Between and closer to sample before.
+ sel = new tr.model.EventSet();
+ track.addClosestEventToSelection(1.3, 1, 0, 0, sel);
+ assert.strictEqual(sel.length, 2);
+ for (const event of sel) {
+ assert.strictEqual(event.getSampleIndex(), 1);
+ }
+
+ // Between samples with bad range.
+ sel = new tr.model.EventSet();
+ track.addClosestEventToSelection(1.45, 0.25, 0, 0, sel);
+ assert.strictEqual(sel.length, 0);
+
+ // Between and closer to next sample.
+ sel = new tr.model.EventSet();
+ track.addClosestEventToSelection(4.7, 6, 0, 0, sel);
+ assert.strictEqual(sel.length, 2);
+ for (const event of sel) {
+ assert.strictEqual(event.getSampleIndex(), 5);
+ }
+
+ // After last sample with good range.
+ sel = new tr.model.EventSet();
+ track.addClosestEventToSelection(8.5, 2, 0, 0, sel);
+ assert.strictEqual(sel.length, 2);
+ for (const event of sel) {
+ assert.strictEqual(event.getSampleIndex(), 7);
+ }
+
+ // After last sample with bad range.
+ sel = new tr.model.EventSet();
+ track.addClosestEventToSelection(10, 1, 0, 0, sel);
+ assert.strictEqual(sel.length, 0);
+ });
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_track.html
new file mode 100644
index 00000000000..3a6c627fb38
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_track.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/slice_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * Visualizes a Cpu using a series of SliceTracks.
+ * @constructor
+ */
+ const CpuTrack =
+ tr.ui.b.define('cpu-track', tr.ui.tracks.ContainerTrack);
+ CpuTrack.prototype = {
+ __proto__: tr.ui.tracks.ContainerTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('cpu-track');
+ this.detailedMode_ = true;
+ },
+
+ get cpu() {
+ return this.cpu_;
+ },
+
+ set cpu(cpu) {
+ this.cpu_ = cpu;
+ this.updateContents_();
+ },
+
+ get detailedMode() {
+ return this.detailedMode_;
+ },
+
+ set detailedMode(detailedMode) {
+ this.detailedMode_ = detailedMode;
+ this.updateContents_();
+ },
+
+ get tooltip() {
+ return this.tooltip_;
+ },
+
+ set tooltip(value) {
+ this.tooltip_ = value;
+ this.updateContents_();
+ },
+
+ get hasVisibleContent() {
+ if (this.cpu_ === undefined) return false;
+
+ const cpu = this.cpu_;
+ if (cpu.slices.length) return true;
+
+ if (cpu.samples && cpu.samples.length) return true;
+
+ if (Object.keys(cpu.counters).length > 0) return true;
+
+ return false;
+ },
+
+ updateContents_() {
+ this.detach();
+ if (!this.cpu_) return;
+
+ const slices = this.cpu_.slices;
+ if (slices.length) {
+ const track = new tr.ui.tracks.SliceTrack(this.viewport);
+ track.slices = slices;
+ track.heading = this.cpu_.userFriendlyName + ':';
+ Polymer.dom(this).appendChild(track);
+ }
+
+ if (this.detailedMode_) {
+ this.appendSamplesTracks_();
+
+ for (const counterName in this.cpu_.counters) {
+ const counter = this.cpu_.counters[counterName];
+ const track = new tr.ui.tracks.CounterTrack(this.viewport);
+ track.heading = this.cpu_.userFriendlyName + ' ' +
+ counter.name + ':';
+ track.counter = counter;
+ Polymer.dom(this).appendChild(track);
+ }
+ }
+ },
+
+ appendSamplesTracks_() {
+ const samples = this.cpu_.samples;
+ if (samples === undefined || samples.length === 0) {
+ return;
+ }
+ const samplesByTitle = {};
+ samples.forEach(function(sample) {
+ if (samplesByTitle[sample.title] === undefined) {
+ samplesByTitle[sample.title] = [];
+ }
+ samplesByTitle[sample.title].push(sample);
+ });
+
+ const sampleTitles = Object.keys(samplesByTitle);
+ sampleTitles.sort();
+
+ sampleTitles.forEach(function(sampleTitle) {
+ const samples = samplesByTitle[sampleTitle];
+ const samplesTrack = new tr.ui.tracks.SliceTrack(this.viewport);
+ samplesTrack.group = this.cpu_;
+ samplesTrack.slices = samples;
+ samplesTrack.heading = this.cpu_.userFriendlyName + ': ' +
+ sampleTitle;
+ samplesTrack.tooltip = this.cpu_.userFriendlyDetails;
+ samplesTrack.selectionGenerator = function() {
+ const selection = new tr.model.EventSet();
+ for (let i = 0; i < samplesTrack.slices.length; i++) {
+ selection.push(samplesTrack.slices[i]);
+ }
+ return selection;
+ };
+ Polymer.dom(this).appendChild(samplesTrack);
+ }, this);
+ }
+ };
+
+ return {
+ CpuTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_track_test.html
new file mode 100644
index 00000000000..442992522f5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_track_test.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Cpu = tr.model.Cpu;
+ const CpuTrack = tr.ui.tracks.CpuTrack;
+ const ThreadSlice = tr.model.ThreadSlice;
+ const StackFrame = tr.model.StackFrame;
+ const Sample = tr.model.Sample;
+ const Thread = tr.model.Thread;
+ const Viewport = tr.ui.TimelineViewport;
+
+ test('basicCpu', function() {
+ const cpu = new Cpu({}, 7);
+ cpu.slices = [
+ new ThreadSlice('', 'a', 0, 1, {}, 1),
+ new ThreadSlice('', 'b', 1, 2.1, {}, 4.8)
+ ];
+ cpu.updateBounds();
+
+ const testEl = document.createElement('div');
+ const viewport = new Viewport(testEl);
+
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+
+ const track = new CpuTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ track.heading = 'CPU ' + cpu.cpuNumber;
+ track.cpu = cpu;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 11.1, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+
+ test('withSamples', function() {
+ let thread;
+ let cpu;
+ const model = tr.c.TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback(model) {
+ cpu = model.kernel.getOrCreateCpu(1);
+ thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+
+ const nodeA = tr.c.TestUtils.newProfileNode(model, 'a');
+ const nodeB = tr.c.TestUtils.newProfileNode(model, 'b', nodeA);
+ const nodeC = tr.c.TestUtils.newProfileNode(model, 'c', nodeB);
+ const nodeD = tr.c.TestUtils.newProfileNode(model, 'd', nodeA);
+
+ model.samples.push(new Sample(10, 'instructions_retired', nodeC, thread,
+ undefined, 10));
+ model.samples.push(new Sample(20, 'instructions_retired', nodeB, thread,
+ undefined, 10));
+ model.samples.push(new Sample(30, 'instructions_retired', nodeB, thread,
+ undefined, 10));
+ model.samples.push(new Sample(40, 'instructions_retired', nodeD, thread,
+ undefined, 10));
+
+ model.samples.push(new Sample(25, 'page_fault', nodeB, thread,
+ undefined, 10));
+ model.samples.push(new Sample(35, 'page_fault', nodeD, thread,
+ undefined, 10));
+ }
+ });
+
+ const testEl = document.createElement('div');
+ const viewport = new Viewport(testEl);
+
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+
+ const track = new CpuTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ track.heading = 'CPU ' + cpu.cpuNumber;
+ track.cpu = cpu;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 11.1, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_usage_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_usage_track.html
new file mode 100644
index 00000000000..912220b8236
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_usage_track.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/chart_point.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series_y_axis.html">
+<link rel="import" href="/tracing/ui/tracks/chart_track.html">
+
+<style>
+.cpu-usage-track {
+ height: 90px;
+}
+</style>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const ChartTrack = tr.ui.tracks.ChartTrack;
+
+ /**
+ * A track that displays the cpu usage of a process.
+ *
+ * @constructor
+ * @extends {tr.ui.tracks.ChartTrack}
+ */
+ const CpuUsageTrack = tr.ui.b.define('cpu-usage-track', ChartTrack);
+
+ CpuUsageTrack.prototype = {
+ __proto__: ChartTrack.prototype,
+
+ decorate(viewport) {
+ ChartTrack.prototype.decorate.call(this, viewport);
+ this.classList.add('cpu-usage-track');
+ this.heading = 'CPU usage';
+ this.cpuUsageSeries_ = undefined;
+ },
+
+ // Given a tr.Model, it creates a cpu usage series and a graph.
+ initialize(model) {
+ if (model !== undefined) {
+ this.cpuUsageSeries_ = model.device.cpuUsageSeries;
+ } else {
+ this.cpuUsageSeries_ = undefined;
+ }
+ this.series = this.buildChartSeries_();
+ this.autoSetAllAxes({expandMax: true});
+ },
+
+ get hasVisibleContent() {
+ return !!this.cpuUsageSeries_ &&
+ this.cpuUsageSeries_.samples.length > 0;
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ containerToTrackMap.addContainer(this.series_, this);
+ },
+
+ buildChartSeries_(yAxis, color) {
+ if (!this.hasVisibleContent) return [];
+
+ yAxis = new tr.ui.tracks.ChartSeriesYAxis(0, undefined);
+ const usageSamples = this.cpuUsageSeries_.samples;
+ const pts = new Array(usageSamples.length + 1);
+ for (let i = 0; i < usageSamples.length; i++) {
+ pts[i] = new tr.ui.tracks.ChartPoint(undefined,
+ usageSamples[i].start, usageSamples[i].usage);
+ }
+ pts[usageSamples.length] = new tr.ui.tracks.ChartPoint(undefined,
+ usageSamples[usageSamples.length - 1].start, 0);
+ const renderingConfig = {
+ chartType: tr.ui.tracks.ChartSeriesType.AREA,
+ colorId: color
+ };
+
+ return [new tr.ui.tracks.ChartSeries(pts, yAxis, renderingConfig)];
+ },
+ };
+
+ return {
+ CpuUsageTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_usage_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_usage_track_test.html
new file mode 100644
index 00000000000..2970e81eaf8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/cpu_usage_track_test.html
@@ -0,0 +1,215 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/cpu/cpu_usage_auditor.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+<link rel='import' href='/tracing/ui/base/constants.html'>
+<link rel='import' href='/tracing/ui/timeline_viewport.html'>
+<link rel="import" href="/tracing/ui/tracks/cpu_usage_track.html">
+<link rel='import' href='/tracing/ui/tracks/drawing_container.html'>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const ThreadSlice = tr.model.ThreadSlice;
+ const DIFF_EPSILON = 0.0001;
+
+ // Input : slices is an array-of-array-of slices. Each top level array
+ // represents a process. So, each slice in one of the top level array
+ // will be placed in the same process.
+ function buildModel(slices) {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ for (let i = 0; i < slices.length; i++) {
+ const thread = process.getOrCreateThread(i);
+ slices[i].forEach(s => thread.sliceGroup.pushSlice(s));
+ }
+ });
+ const auditor = new tr.e.audits.CpuUsageAuditor(model);
+ auditor.runAnnotate();
+ return model;
+ }
+
+ // Compare float arrays based on an epsilon since floating point arithmetic
+ // is not always 100% accurate.
+ function assertArrayValuesCloseTo(actualValue, expectedValue) {
+ assert.lengthOf(actualValue, expectedValue.length);
+ for (let i = 0; i < expectedValue.length; i++) {
+ assert.closeTo(actualValue[i], expectedValue[i], DIFF_EPSILON);
+ }
+ }
+
+ function createCpuUsageTrack(model, interval) {
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ div.appendChild(drawingContainer);
+ const track = new tr.ui.tracks.CpuUsageTrack(drawingContainer.viewport);
+ if (model !== undefined) {
+ setDisplayTransformFromBounds(viewport, model.bounds);
+ }
+ track.initialize(model, interval);
+ drawingContainer.appendChild(track);
+ this.addHTMLOutput(drawingContainer);
+ return track;
+ }
+
+ /**
+ * Sets the mapping between the input range of timestamps and the output range
+ * of horizontal pixels.
+ */
+ function setDisplayTransformFromBounds(viewport, bounds) {
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ const chartPixelWidth =
+ (window.innerWidth - tr.ui.b.constants.HEADING_WIDTH) * pixelRatio;
+ dt.xSetWorldBounds(bounds.min, bounds.max, chartPixelWidth);
+ viewport.setDisplayTransformImmediately(dt);
+ }
+
+ test('computeCpuUsage_simple', function() {
+ // Set the boundaries, from 0-15 ms. This slice will not
+ // contain any CPU usage data, it's just to make the boundaries
+ // of the bins go as 0-1, 1-2, 2-3, etc. This also tests whether
+ // this function works properly in the presence of slices that
+ // don't include CPU usage data.
+ const bigSlice = new tr.model.ThreadSlice('', title, 0, 0, {}, 15);
+ // First thread.
+ // 0 5 10 15
+ // [ sliceA ]
+ // [ sliceB ] [C ]
+ const sliceA = new tr.model.ThreadSlice('', title, 0, 0.5, {}, 5);
+ sliceA.cpuDuration = 5;
+ const sliceB = new tr.model.ThreadSlice('', title, 0, 2.5, {}, 8);
+ sliceB.cpuDuration = 6;
+ // The slice completely fits into an interval and is the last.
+ const sliceC = new tr.model.ThreadSlice('', title, 0, 12.5, {}, 2);
+ sliceC.cpuDuration = 1;
+
+ // Second thread.
+ // 0 5 10 15
+ // [ sliceD ][ sliceE ]
+ const sliceD = new tr.model.ThreadSlice('', title, 0, 3.5, {}, 3);
+ sliceD.cpuDuration = 3;
+ const sliceE = new tr.model.ThreadSlice('', title, 0, 6.5, {}, 6);
+ sliceE.cpuDuration = 3;
+
+ const model = buildModel([
+ [bigSlice, sliceA, sliceB, sliceC],
+ [sliceD, sliceE]
+ ]);
+
+ // Compute average CPU usage over A (but not over B and C).
+ const avgCpuUsageA = sliceA.cpuSelfTime / sliceA.selfTime;
+ // Compute average CPU usage over B, C, D, E. They don't have subslices.
+ const avgCpuUsageB = sliceB.cpuDuration / sliceB.duration;
+ const avgCpuUsageC = sliceC.cpuDuration / sliceC.duration;
+ const avgCpuUsageD = sliceD.cpuDuration / sliceD.duration;
+ const avgCpuUsageE = sliceE.cpuDuration / sliceE.duration;
+
+ const expectedValue = [
+ 0,
+ avgCpuUsageA,
+ avgCpuUsageA,
+ avgCpuUsageA + avgCpuUsageB,
+ avgCpuUsageA + avgCpuUsageB + avgCpuUsageD,
+ avgCpuUsageA + avgCpuUsageB + avgCpuUsageD,
+ avgCpuUsageB + avgCpuUsageD,
+ avgCpuUsageB + avgCpuUsageE,
+ avgCpuUsageB + avgCpuUsageE,
+ avgCpuUsageB + avgCpuUsageE,
+ avgCpuUsageB + avgCpuUsageE,
+ avgCpuUsageE,
+ avgCpuUsageE,
+ avgCpuUsageC,
+ avgCpuUsageC,
+ 0
+ ];
+ const track = createCpuUsageTrack.call(this, model);
+ const actualValue = track.series[0].points.map(point => point.y);
+ assertArrayValuesCloseTo(actualValue, expectedValue);
+ });
+
+ test('computeCpuUsage_longDurationThreadSlice', function() {
+ // Create a slice covering 24 hours.
+ const sliceA = new tr.model.ThreadSlice(
+ '', title, 0, 0, {}, 24 * 60 * 60 * 1000);
+ sliceA.cpuDuration = sliceA.duration * 0.25;
+
+ const model = buildModel([[sliceA]]);
+
+ const track = createCpuUsageTrack.call(this, model);
+ const cpuSamples = track.series[0].points.map(point => point.y);
+
+ // All except the last sample is 0.25, since sliceA.cpuDuration was set to
+ // 0.25 of the total.
+ for (const cpuSample of cpuSamples.slice(0, cpuSamples.length - 1)) {
+ assert.closeTo(cpuSample, 0.25, DIFF_EPSILON);
+ }
+ // The last sample is 0.
+ assert.closeTo(cpuSamples[cpuSamples.length - 1], 0, DIFF_EPSILON);
+ });
+
+ test('instantiate', function() {
+ const sliceA = new tr.model.ThreadSlice('', title, 0, 5.5111, {}, 47.1023);
+ sliceA.cpuDuration = 25;
+ const sliceB = new tr.model.ThreadSlice('', title, 0, 11.2384, {}, 1.8769);
+ sliceB.cpuDuration = 1.5;
+ const sliceC = new tr.model.ThreadSlice('', title, 0, 11.239, {}, 5.8769);
+ sliceC.cpuDuration = 5;
+ const sliceD = new tr.model.ThreadSlice('', title, 0, 48.012, {}, 5.01);
+ sliceD.cpuDuration = 4;
+
+ const model = buildModel([[sliceA, sliceB, sliceC, sliceD]]);
+ createCpuUsageTrack.call(this, model);
+ });
+
+ test('hasVisibleContent_trueWithThreadSlicePresent', function() {
+ const sliceA = new tr.model.ThreadSlice('', title, 0, 48.012, {}, 5.01);
+ sliceA.cpuDuration = 4;
+ const model = buildModel([[sliceA]]);
+ const track = createCpuUsageTrack.call(this, model);
+
+ assert.isTrue(track.hasVisibleContent);
+ });
+
+ test('hasVisibleContent_falseWithUndefinedProcessModel', function() {
+ const track = createCpuUsageTrack.call(this, undefined);
+
+ assert.isFalse(track.hasVisibleContent);
+ });
+
+ test('hasVisibleContent_falseWithNoThreadSlice', function() {
+ // model with a CPU and a thread but no ThreadSlice.
+ const model = buildModel([]);
+ const track = createCpuUsageTrack.call(this, model);
+
+ assert.isFalse(track.hasVisibleContent);
+ });
+
+ test('hasVisibleContent_trueWithSubSlices', function() {
+ const sliceA = new tr.model.ThreadSlice('', title, 0, 5.5111, {}, 47.1023);
+ sliceA.cpuDuration = 25;
+ const sliceB = new tr.model.ThreadSlice('', title, 0, 11.2384, {}, 1.8769);
+ sliceB.cpuDuration = 1.5;
+
+ const model = buildModel([[sliceA, sliceB]]);
+ const process = model.getProcess(1);
+ // B will become lowest level slices of A.
+ process.getThread(0).sliceGroup.createSubSlices();
+ assert.strictEqual(
+ sliceA.cpuSelfTime, (sliceA.cpuDuration - sliceB.cpuDuration));
+ const track = createCpuUsageTrack.call(this, model);
+
+ assert.isTrue(track.hasVisibleContent);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/device_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/device_track.html
new file mode 100644
index 00000000000..a068a7ebebb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/device_track.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/power_series_track.html">
+<link rel="import" href="/tracing/ui/tracks/spacing_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ContainerTrack = tr.ui.tracks.ContainerTrack;
+
+ // TODO(charliea): Make this track collapsible.
+ /**
+ * Track to visualize the device model.
+ *
+ * @constructor
+ * @extends {ContainerTrack}
+ */
+ const DeviceTrack = tr.ui.b.define('device-track', ContainerTrack);
+
+ DeviceTrack.prototype = {
+
+ __proto__: ContainerTrack.prototype,
+
+ decorate(viewport) {
+ ContainerTrack.prototype.decorate.call(this, viewport);
+
+ Polymer.dom(this).classList.add('device-track');
+ this.device_ = undefined;
+ this.powerSeriesTrack_ = undefined;
+ },
+
+ get device() {
+ return this.device_;
+ },
+
+ set device(device) {
+ this.device_ = device;
+ this.updateContents_();
+ },
+
+ get powerSeriesTrack() {
+ return this.powerSeriesTrack_;
+ },
+
+ get hasVisibleContent() {
+ return (this.powerSeriesTrack_ &&
+ this.powerSeriesTrack_.hasVisibleContent);
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ tr.ui.tracks.ContainerTrack.prototype.addContainersToTrackMap.call(
+ this, containerToTrackMap);
+ containerToTrackMap.addContainer(this.device, this);
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ this.tracks_.forEach(function(track) {
+ track.addEventsToTrackMap(eventToTrackMap);
+ });
+ },
+
+ appendPowerSeriesTrack_() {
+ this.powerSeriesTrack_ = new tr.ui.tracks.PowerSeriesTrack(this.viewport);
+ this.powerSeriesTrack_.powerSeries = this.device.powerSeries;
+
+ if (this.powerSeriesTrack_.hasVisibleContent) {
+ Polymer.dom(this).appendChild(this.powerSeriesTrack_);
+ Polymer.dom(this).appendChild(
+ new tr.ui.tracks.SpacingTrack(this.viewport));
+ }
+ },
+
+ updateContents_() {
+ this.clearTracks_();
+ this.appendPowerSeriesTrack_();
+ }
+ };
+
+ return {
+ DeviceTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/device_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/device_track_test.html
new file mode 100644
index 00000000000..fdd3b392993
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/device_track_test.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel='import' href='/tracing/model/device.html'>
+<link rel='import' href='/tracing/model/model.html'>
+<link rel="import" href="/tracing/ui/base/constants.html">
+<link rel='import' href='/tracing/ui/timeline_display_transform.html'>
+<link rel='import' href='/tracing/ui/timeline_viewport.html'>
+<link rel='import' href='/tracing/ui/tracks/device_track.html'>
+<link rel='import' href='/tracing/ui/tracks/drawing_container.html'>
+<link rel='import' href='/tracing/ui/tracks/event_to_track_map.html'>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Device = tr.model.Device;
+ const DeviceTrack = tr.ui.tracks.DeviceTrack;
+ const Model = tr.Model;
+ const PowerSeries = tr.model.PowerSeries;
+
+ const createDrawingContainer = function(series) {
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ if (series) {
+ series.updateBounds();
+ setDisplayTransformFromBounds(viewport, series.bounds);
+ }
+
+ return drawingContainer;
+ };
+
+ /**
+ * Sets the mapping between the input range of timestamps and the output range
+ * of horizontal pixels.
+ */
+ const setDisplayTransformFromBounds = function(viewport, bounds) {
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ const chartPixelWidth =
+ (window.innerWidth - tr.ui.b.constants.HEADING_WIDTH) * pixelRatio;
+ dt.xSetWorldBounds(bounds.min, bounds.max, chartPixelWidth);
+ viewport.setDisplayTransformImmediately(dt);
+ };
+
+ test('instantiate', function() {
+ const device = new Device(new Model());
+ device.powerSeries = new PowerSeries(device);
+ device.powerSeries.addPowerSample(0, 1);
+ device.powerSeries.addPowerSample(0.5, 2);
+ device.powerSeries.addPowerSample(1, 3);
+ device.powerSeries.addPowerSample(1.5, 4);
+
+ const drawingContainer = createDrawingContainer(device.powerSeries);
+ const track = new DeviceTrack(drawingContainer.viewport);
+ track.device = device;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(drawingContainer);
+ });
+
+ test('instantiate_noPowerSeries', function() {
+ const device = new Device(new Model());
+
+ const drawingContainer = createDrawingContainer(device.powerSeries);
+ const track = new DeviceTrack(drawingContainer.viewport);
+ track.device = device;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ // Adding output should throw due to no visible content.
+ assert.throw(function() { this.addHTMLOutput(drawingContainer); });
+ });
+
+ test('setDevice_clearsTrackBeforeUpdating', function() {
+ const device = new Device(new Model());
+ device.powerSeries = new PowerSeries(device);
+ device.powerSeries.addPowerSample(0, 1);
+ device.powerSeries.addPowerSample(0.5, 2);
+ device.powerSeries.addPowerSample(1, 3);
+ device.powerSeries.addPowerSample(1.5, 4);
+
+ const drawingContainer = createDrawingContainer(device.powerSeries);
+
+ // Set the device twice and make sure that this doesn't result in
+ // the track appearing twice.
+ const track = new DeviceTrack(drawingContainer.viewport);
+ track.device = device;
+ track.device = device;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(drawingContainer);
+
+ // The device track should still have two subtracks: one counter track and
+ // one spacing track.
+ assert.strictEqual(track.tracks_.length, 2);
+ });
+
+ test('addContainersToTrackMap', function() {
+ const device = new Device(new Model());
+ device.powerSeries = new PowerSeries(device);
+ device.powerSeries.addPowerSample(0, 1);
+
+ const drawingContainer = createDrawingContainer(device.series);
+ const track = new DeviceTrack(drawingContainer.viewport);
+ track.device = device;
+
+ const containerToTrackMap = new tr.ui.tracks.ContainerToTrackMap();
+ track.addContainersToTrackMap(containerToTrackMap);
+
+ assert.strictEqual(containerToTrackMap.getTrackByStableId('Device'), track);
+ assert.strictEqual(
+ containerToTrackMap.getTrackByStableId('Device.PowerSeries'),
+ track.powerSeriesTrack);
+ });
+
+ test('addEventsToTrackMap', function() {
+ const device = new Device(new Model());
+ device.powerSeries = new PowerSeries(device);
+ device.powerSeries.addPowerSample(0, 1);
+ device.powerSeries.addPowerSample(0.5, 2);
+
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+
+ const track = new DeviceTrack(viewport);
+ track.device = device;
+
+ const eventToTrackMap = new tr.ui.tracks.EventToTrackMap();
+ track.addEventsToTrackMap(eventToTrackMap);
+
+ const expected = new tr.ui.tracks.EventToTrackMap();
+ expected[device.powerSeries.samples[0].guid] = track.powerSeriesTrack;
+ expected[device.powerSeries.samples[1].guid] = track.powerSeriesTrack;
+
+ assert.deepEqual(eventToTrackMap, expected);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container.css b/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container.css
new file mode 100644
index 00000000000..a8f4d17c91c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container.css
@@ -0,0 +1,18 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.drawing-container {
+ display: inline;
+ overflow: auto;
+ overflow-x: hidden;
+ position: relative;
+}
+
+.drawing-container-canvas {
+ display: block;
+ pointer-events: none;
+ position: absolute;
+ top: 0;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container.html
new file mode 100644
index 00000000000..d13a3a5383c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container.html
@@ -0,0 +1,236 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet" href="/tracing/ui/tracks/drawing_container.css">
+
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/ui/base/constants.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const DrawType = {
+ GENERAL_EVENT: 1,
+ INSTANT_EVENT: 2,
+ BACKGROUND: 3,
+ GRID: 4,
+ FLOW_ARROWS: 5,
+ MARKERS: 6,
+ HIGHLIGHTS: 7,
+ ANNOTATIONS: 8
+ };
+
+ // Must be > 1.0. This is the maximum multiple by which the size
+ // of the canvas can exceed the window dimensions. For example
+ // if window.innerHeight is 1000 and this is 1.4, then the
+ // largest the canvas height can be set to is 1400px assuming a
+ // window.devicePixelRatio of 1.
+ // Currently this value is set rather large to mostly match
+ // previous behavior & performance. This should be reduced to
+ // be as small as possible once raw drawing performance is improved
+ // such that a repaint doesn't incur a large jank
+ const MAX_OVERSIZE_MULTIPLE = 3.0;
+ const REDRAW_SLOP = (MAX_OVERSIZE_MULTIPLE - 1) / 2;
+
+ const DrawingContainer = tr.ui.b.define('drawing-container',
+ tr.ui.tracks.Track);
+
+ DrawingContainer.prototype = {
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('drawing-container');
+
+ this.canvas_ = document.createElement('canvas');
+ this.canvas_.className = 'drawing-container-canvas';
+ this.canvas_.style.left = tr.ui.b.constants.HEADING_WIDTH + 'px';
+ Polymer.dom(this).appendChild(this.canvas_);
+
+ this.ctx_ = this.canvas_.getContext('2d');
+ this.offsetY_ = 0;
+
+ this.viewportChange_ = this.viewportChange_.bind(this);
+ this.viewport.addEventListener('change', this.viewportChange_);
+
+ window.addEventListener('resize', this.windowResized_.bind(this));
+ this.addEventListener('scroll', this.scrollChanged_.bind(this));
+ },
+
+ // Needed to support the calls in TimelineTrackView.
+ get canvas() {
+ return this.canvas_;
+ },
+
+ context() {
+ return this.ctx_;
+ },
+
+ viewportChange_() {
+ this.invalidate();
+ },
+
+ windowResized_() {
+ this.invalidate();
+ },
+
+ scrollChanged_() {
+ if (this.updateOffsetY_()) {
+ this.invalidate();
+ }
+ },
+
+ invalidate() {
+ if (this.rafPending_) return;
+
+ this.rafPending_ = true;
+
+ tr.b.requestPreAnimationFrame(this.preDraw_, this);
+ },
+
+ preDraw_() {
+ this.rafPending_ = false;
+ this.updateCanvasSizeIfNeeded_();
+
+ tr.b.requestAnimationFrameInThisFrameIfPossible(this.draw_, this);
+ },
+
+ draw_() {
+ this.ctx_.clearRect(0, 0, this.canvas_.width, this.canvas_.height);
+
+ const typesToDraw = [
+ DrawType.BACKGROUND,
+ DrawType.HIGHLIGHTS,
+ DrawType.GRID,
+ DrawType.INSTANT_EVENT,
+ DrawType.GENERAL_EVENT,
+ DrawType.MARKERS,
+ DrawType.ANNOTATIONS,
+ DrawType.FLOW_ARROWS
+ ];
+
+ for (const idx in typesToDraw) {
+ for (let i = 0; i < this.children.length; ++i) {
+ if (!(this.children[i] instanceof tr.ui.tracks.Track)) {
+ continue;
+ }
+ this.children[i].drawTrack(typesToDraw[idx]);
+ }
+ }
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const bounds = this.canvas_.getBoundingClientRect();
+ const dt = this.viewport.currentDisplayTransform;
+ const viewLWorld = dt.xViewToWorld(0);
+ const viewRWorld = dt.xViewToWorld(
+ bounds.width * pixelRatio);
+ const viewHeight = bounds.height * pixelRatio;
+
+ this.viewport.drawGridLines(
+ this.ctx_, viewLWorld, viewRWorld, viewHeight);
+ },
+
+ // Update's this.offsetY_, returning true if the value has changed
+ // and thus a redraw is needed, or false if it did not change.
+ updateOffsetY_() {
+ const maxYDelta = window.innerHeight * REDRAW_SLOP;
+ let newOffset = this.scrollTop - maxYDelta;
+ if (Math.abs(newOffset - this.offsetY_) <= maxYDelta) return false;
+ // Now clamp to the valid range.
+ const maxOffset = this.scrollHeight -
+ this.canvas_.getBoundingClientRect().height;
+ newOffset = Math.max(0, Math.min(newOffset, maxOffset));
+ if (newOffset !== this.offsetY_) {
+ this.offsetY_ = newOffset;
+ return true;
+ }
+ return false;
+ },
+
+ updateCanvasSizeIfNeeded_() {
+ const visibleChildTracks =
+ Array.from(this.children).filter(this.visibleFilter_);
+
+ if (visibleChildTracks.length === 0) {
+ return;
+ }
+
+ const thisBounds = this.getBoundingClientRect();
+
+ const firstChildTrackBounds =
+ visibleChildTracks[0].getBoundingClientRect();
+ const lastChildTrackBounds =
+ visibleChildTracks[visibleChildTracks.length - 1].
+ getBoundingClientRect();
+
+ const innerWidth = firstChildTrackBounds.width -
+ tr.ui.b.constants.HEADING_WIDTH;
+ const innerHeight = Math.min(
+ lastChildTrackBounds.bottom - firstChildTrackBounds.top,
+ Math.floor(window.innerHeight * MAX_OVERSIZE_MULTIPLE));
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ if (this.canvas_.width !== innerWidth * pixelRatio) {
+ this.canvas_.width = innerWidth * pixelRatio;
+ this.canvas_.style.width = innerWidth + 'px';
+ }
+
+ if (this.canvas_.height !== innerHeight * pixelRatio) {
+ this.canvas_.height = innerHeight * pixelRatio;
+ this.canvas_.style.height = innerHeight + 'px';
+ }
+
+ if (this.canvas_.top !== this.offsetY_) {
+ this.canvas_.top = this.offsetY_;
+ this.canvas_.style.top = this.offsetY_ + 'px';
+ }
+ },
+
+ visibleFilter_(element) {
+ if (!(element instanceof tr.ui.tracks.Track)) return false;
+
+ return window.getComputedStyle(element).display !== 'none';
+ },
+
+ addClosestEventToSelection(
+ worldX, worldMaxDist, loY, hiY, selection) {
+ for (let i = 0; i < this.children.length; ++i) {
+ if (!(this.children[i] instanceof tr.ui.tracks.Track)) {
+ continue;
+ }
+ const trackClientRect = this.children[i].getBoundingClientRect();
+ const a = Math.max(loY, trackClientRect.top);
+ const b = Math.min(hiY, trackClientRect.bottom);
+ if (a <= b) {
+ this.children[i].addClosestEventToSelection(
+ worldX, worldMaxDist, loY, hiY, selection);
+ }
+ }
+
+ tr.ui.tracks.Track.prototype.addClosestEventToSelection.
+ apply(this, arguments);
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ for (let i = 0; i < this.children.length; ++i) {
+ if (!(this.children[i] instanceof tr.ui.tracks.Track)) {
+ continue;
+ }
+ this.children[i].addEventsToTrackMap(eventToTrackMap);
+ }
+ }
+ };
+
+ return {
+ DrawingContainer,
+ DrawType,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container_perf_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container_perf_test.html
new file mode 100644
index 00000000000..7b778b1c332
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/drawing_container_perf_test.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/ui/extras/full_config.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ let generalModel;
+ function getOrCreateGeneralModel() {
+ if (generalModel !== undefined) {
+ generalModel;
+ }
+ const fileUrl = '/test_data/thread_time_visualisation.json.gz';
+ const events = tr.b.getSync(fileUrl);
+ generalModel = tr.c.TestUtils.newModelWithEvents([events]);
+ return generalModel;
+ }
+
+ function DCPerfTestCase(testName, opt_options) {
+ tr.b.unittest.PerfTestCase.call(this, testName, undefined, opt_options);
+ this.viewportDiv = undefined;
+ this.drawingContainer = undefined;
+ this.viewport = undefined;
+ }
+ DCPerfTestCase.prototype = {
+ __proto__: tr.b.unittest.PerfTestCase.prototype,
+
+ setUp(model) {
+ this.viewportDiv = document.createElement('div');
+
+ this.viewport = new tr.ui.TimelineViewport(this.viewportDiv);
+
+ this.drawingContainer = new tr.ui.tracks.DrawingContainer(this.viewport);
+ this.viewport.modelTrackContainer = this.drawingContainer;
+
+ const modelTrack = new tr.ui.tracks.ModelTrack(this.viewport);
+ Polymer.dom(this.drawingContainer).appendChild(modelTrack);
+
+ modelTrack.model = model;
+
+ Polymer.dom(this.viewportDiv).appendChild(this.drawingContainer);
+
+ this.addHTMLOutput(this.viewportDiv);
+
+ // Size the canvas.
+ this.drawingContainer.updateCanvasSizeIfNeeded_();
+
+ // Size the viewport.
+ const w = this.drawingContainer.canvas.width;
+ const min = model.bounds.min;
+ const range = model.bounds.range;
+
+ const boost = range * 0.15;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(min - boost, min + range + boost, w);
+ this.viewport.setDisplayTransformImmediately(dt);
+ },
+
+ runOneIteration() {
+ this.drawingContainer.draw_();
+ }
+ };
+
+
+ function GeneralDCPerfTestCase(testName, opt_options) {
+ DCPerfTestCase.call(this, testName, opt_options);
+ }
+
+ GeneralDCPerfTestCase.prototype = {
+ __proto__: DCPerfTestCase.prototype,
+
+ setUp() {
+ const model = getOrCreateGeneralModel();
+ DCPerfTestCase.prototype.setUp.call(this, model);
+ }
+ };
+
+ // Failing on Chrome canary, see
+ // https://github.com/catapult-project/catapult/issues/1826
+ flakyTest(new GeneralDCPerfTestCase('draw_softwareCanvas_One',
+ {iterations: 1}));
+ // Failing on Chrome stable on Windows, see
+ // https://github.com/catapult-project/catapult/issues/1908
+ flakyTest(new GeneralDCPerfTestCase('draw_softwareCanvas_Ten',
+ {iterations: 10}));
+ test(new GeneralDCPerfTestCase('draw_softwareCanvas_AHundred',
+ {iterations: 100}));
+
+ function AsyncDCPerfTestCase(testName, opt_options) {
+ DCPerfTestCase.call(this, testName, opt_options);
+ }
+
+ AsyncDCPerfTestCase.prototype = {
+ __proto__: DCPerfTestCase.prototype,
+
+ setUp() {
+ const model = tr.c.TestUtils.newModel(function(m) {
+ const proc = m.getOrCreateProcess(1);
+ for (let tid = 1; tid <= 5; tid++) {
+ const thread = proc.getOrCreateThread(tid);
+ for (let i = 0; i < 5000; i++) {
+ const mod = Math.floor(i / 100) % 4;
+ const slice = tr.c.TestUtils.newAsyncSliceEx({
+ name: 'Test' + i,
+ colorId: tid + mod,
+ id: tr.b.GUID.allocateSimple(),
+ start: i * 10,
+ duration: 9,
+ isTopLevel: true
+ });
+ thread.asyncSliceGroup.push(slice);
+ }
+ }
+ });
+ DCPerfTestCase.prototype.setUp.call(this, model);
+
+ const w = this.drawingContainer.canvas.width;
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(-2000, 54000, w);
+ this.viewport.setDisplayTransformImmediately(dt);
+ }
+ };
+ test(new AsyncDCPerfTestCase('draw_asyncSliceHeavy_Twenty',
+ {iterations: 20}));
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/event_to_track_map.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/event_to_track_map.html
new file mode 100644
index 00000000000..f8ba209d01b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/event_to_track_map.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * EventToTrackMap provides a mapping mechanism between events and the
+ * tracks those events belong on.
+ * @constructor
+ */
+ function EventToTrackMap() {}
+
+ EventToTrackMap.prototype = {
+ addEvent(event, track) {
+ if (!track) {
+ throw new Error('Must provide a track.');
+ }
+ this[event.guid] = track;
+ }
+ };
+
+ return {
+ EventToTrackMap,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/frame_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/frame_track.html
new file mode 100644
index 00000000000..3e8de1d9831
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/frame_track.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/ui/base/event_presenter.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/letter_dot_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const startCompare = function(x, y) { return x.start - y.start; };
+
+ /**
+ * Track enabling quick selection of frame slices/events.
+ * @constructor
+ */
+ const FrameTrack = tr.ui.b.define(
+ 'frame-track', tr.ui.tracks.LetterDotTrack);
+
+ FrameTrack.prototype = {
+ __proto__: tr.ui.tracks.LetterDotTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.LetterDotTrack.prototype.decorate.call(this, viewport);
+ this.heading = 'Frames';
+
+ this.frames_ = undefined;
+ this.items = undefined;
+ },
+
+ get frames() {
+ return this.frames_;
+ },
+
+ set frames(frames) {
+ this.frames_ = frames;
+ if (frames === undefined) return;
+
+ this.frames_ = this.frames_.slice();
+ this.frames_.sort(startCompare);
+
+ // letter dots
+ this.items = this.frames_.map(function(frame) {
+ return new FrameDot(frame);
+ });
+ }
+ };
+
+ /**
+ * @constructor
+ * @extends {LetterDot}
+ */
+ function FrameDot(frame) {
+ tr.ui.tracks.LetterDot.call(this, frame, 'F', frame.colorId, frame.start);
+ }
+
+ FrameDot.prototype = {
+ __proto__: tr.ui.tracks.LetterDot.prototype
+ };
+
+ return {
+ FrameTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/frame_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/frame_track_test.html
new file mode 100644
index 00000000000..94189d0fecb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/frame_track_test.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/frame.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/frame_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Frame = tr.model.Frame;
+ const FrameTrack = tr.ui.tracks.FrameTrack;
+ const EventSet = tr.model.EventSet;
+ const SelectionState = tr.model.SelectionState;
+ const Viewport = tr.ui.TimelineViewport;
+
+ const createFrames = function() {
+ let frames = undefined;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ const thread = process.getOrCreateThread(1);
+ for (let i = 1; i < 5; i++) {
+ const slice = tr.c.TestUtils.newSliceEx(
+ {title: 'work for frame', start: i * 20, duration: 10});
+ thread.sliceGroup.pushSlice(slice);
+ const events = [slice];
+ const threadTimeRanges =
+ [{thread, start: slice.start, end: slice.end}];
+ process.frames.push(new Frame(events, threadTimeRanges));
+ }
+ frames = process.frames;
+ });
+ return frames;
+ };
+
+ test('instantiate', function() {
+ const frames = createFrames();
+ frames[1].selectionState = SelectionState.SELECTED;
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = FrameTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.frames = frames;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 50, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ assert.strictEqual(track.items[0].start, 20);
+ });
+
+ test('modelMapping', function() {
+ const frames = createFrames();
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const track = FrameTrack(viewport);
+ track.frames = frames;
+
+ const a0 = track.items[0].modelItem;
+ assert.strictEqual(a0, frames[0]);
+ });
+
+ test('selectionMapping', function() {
+ const frames = createFrames();
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const track = FrameTrack(viewport);
+ track.frames = frames;
+
+ const selection = new EventSet();
+ track.items[0].addToSelection(selection);
+
+ // select both frame, but not its component slice
+ assert.strictEqual(selection.length, 1);
+
+ let frameCount = 0;
+ let eventCount = 0;
+ selection.forEach(function(event) {
+ if (event instanceof Frame) {
+ assert.strictEqual(event, frames[0]);
+ frameCount++;
+ } else {
+ eventCount++;
+ }
+ });
+ assert.strictEqual(frameCount, 1);
+ assert.strictEqual(eventCount, 0);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/global_memory_dump_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/global_memory_dump_track.html
new file mode 100644
index 00000000000..aaf9bc0a80d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/global_memory_dump_track.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/tracks/chart_track.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/letter_dot_track.html">
+<link rel="import" href="/tracing/ui/tracks/memory_dump_track_util.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const USED_MEMORY_TRACK_HEIGHT = 50;
+ const ALLOCATED_MEMORY_TRACK_HEIGHT = 50;
+
+ /**
+ * A track that displays an array of GlobalMemoryDump objects.
+ * @constructor
+ * @extends {ContainerTrack}
+ */
+ const GlobalMemoryDumpTrack = tr.ui.b.define(
+ 'global-memory-dump-track', tr.ui.tracks.ContainerTrack);
+
+ GlobalMemoryDumpTrack.prototype = {
+ __proto__: tr.ui.tracks.ContainerTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+ this.memoryDumps_ = undefined;
+ },
+
+ get memoryDumps() {
+ return this.memoryDumps_;
+ },
+
+ set memoryDumps(memoryDumps) {
+ this.memoryDumps_ = memoryDumps;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ this.clearTracks_();
+
+ // Show no tracks if there are no dumps.
+ if (!this.memoryDumps_ || !this.memoryDumps_.length) return;
+
+ this.appendDumpDotsTrack_();
+ this.appendUsedMemoryTrack_();
+ this.appendAllocatedMemoryTrack_();
+ },
+
+ appendDumpDotsTrack_() {
+ const items = tr.ui.tracks.buildMemoryLetterDots(this.memoryDumps_);
+ if (!items) return;
+
+ const track = new tr.ui.tracks.LetterDotTrack(this.viewport);
+ track.heading = 'Memory Dumps';
+ track.items = items;
+ Polymer.dom(this).appendChild(track);
+ },
+
+ appendUsedMemoryTrack_() {
+ const tracks = [];
+ const perProcessSeries =
+ tr.ui.tracks.buildGlobalUsedMemoryChartSeries(this.memoryDumps_);
+ if (perProcessSeries !== undefined) {
+ tracks.push({name: 'Memory per process', series: perProcessSeries});
+ } else {
+ tracks.push.apply(tracks, tr.ui.tracks.buildSystemMemoryChartSeries(
+ this.memoryDumps_[0].model));
+ }
+
+ for (const {name, series} of tracks) {
+ const track = new tr.ui.tracks.ChartTrack(this.viewport);
+ track.heading = name;
+ track.height = USED_MEMORY_TRACK_HEIGHT + 'px';
+ track.series = series;
+ track.autoSetAllAxes({expandMax: true});
+ Polymer.dom(this).appendChild(track);
+ }
+ },
+
+ appendAllocatedMemoryTrack_() {
+ const series = tr.ui.tracks.buildGlobalAllocatedMemoryChartSeries(
+ this.memoryDumps_);
+ if (!series) return;
+
+ const track = new tr.ui.tracks.ChartTrack(this.viewport);
+ track.heading = 'Memory per component';
+ track.height = ALLOCATED_MEMORY_TRACK_HEIGHT + 'px';
+ track.series = series;
+ track.autoSetAllAxes({expandMax: true});
+ Polymer.dom(this).appendChild(track);
+ }
+ };
+
+ return {
+ GlobalMemoryDumpTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/global_memory_dump_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/global_memory_dump_track_test.html
new file mode 100644
index 00000000000..20fa869bbf0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/global_memory_dump_track_test.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/global_memory_dump_track.html">
+<link rel="import" href="/tracing/ui/tracks/memory_dump_track_test_utils.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Viewport = tr.ui.TimelineViewport;
+ const GlobalMemoryDumpTrack = tr.ui.tracks.GlobalMemoryDumpTrack;
+ const createTestGlobalMemoryDumps = tr.ui.tracks.createTestGlobalMemoryDumps;
+
+ function instantiateTrack(withVMRegions, withAllocatorDumps,
+ expectedTrackCount) {
+ const dumps = createTestGlobalMemoryDumps(
+ withVMRegions, withAllocatorDumps);
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = new GlobalMemoryDumpTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ drawingContainer.invalidate();
+
+ track.memoryDumps = dumps;
+ this.addHTMLOutput(div);
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 50, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ assert.lengthOf(track.tracks_, expectedTrackCount);
+ }
+
+ test('instantiate_dotsOnly', function() {
+ instantiateTrack.call(this, false, false, 1);
+ });
+
+ test('instantiate_withVMRegions', function() {
+ instantiateTrack.call(this, true, false, 2);
+ });
+
+ test('instantiate_withMemoryAllocatorDumps', function() {
+ instantiateTrack.call(this, false, true, 2);
+ });
+
+ test('instantiate_withBoth', function() {
+ instantiateTrack.call(this, true, true, 3);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/interaction_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/interaction_track.html
new file mode 100644
index 00000000000..7ae139672d2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/interaction_track.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/draw_helpers.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/alert_track.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/kernel_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays an array of interaction records.
+ * @constructor
+ * @extends {MultiRowTrack}
+ */
+ const InteractionTrack = tr.ui.b.define(
+ 'interaction-track', tr.ui.tracks.MultiRowTrack);
+
+ InteractionTrack.prototype = {
+ __proto__: tr.ui.tracks.MultiRowTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
+ this.heading = 'Interactions';
+ this.subRows_ = [];
+ },
+
+ set model(model) {
+ this.setItemsToGroup(model.userModel.expectations, {
+ guid: tr.b.GUID.allocateSimple(),
+ model,
+ getSettingsKey() {
+ return undefined;
+ }
+ });
+ },
+
+ buildSubRows_(slices) {
+ if (this.subRows_.length) {
+ return this.subRows_;
+ }
+ this.subRows_.push(
+ ...tr.ui.tracks.groupAsyncSlicesIntoSubRows(slices, true));
+ return this.subRows_;
+ },
+
+ addSubTrack_(slices) {
+ const track = new tr.ui.tracks.SliceTrack(this.viewport);
+ track.slices = slices;
+ Polymer.dom(this).appendChild(track);
+ return track;
+ }
+ };
+
+ return {
+ InteractionTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/interaction_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/interaction_track_test.html
new file mode 100644
index 00000000000..ac0d5692c4d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/interaction_track_test.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/user_model/stub_expectation.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/interaction_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ // UserExpectations should be sorted by start time, not title, so that
+ // AsyncSliceGroupTrack.buildSubRows_ can lay them out in as few tracks as
+ // possible, so that they mesh instead of stacking unnecessarily.
+ test('instantiate', function() {
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+ const track = new tr.ui.tracks.InteractionTrack(viewport);
+ track.model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ const thread = process.getOrCreateThread(1);
+ thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 0, duration: 200}));
+ model.userModel.expectations.push(new tr.model.um.StubExpectation(
+ {parentModel: model, start: 100, duration: 100}));
+ model.userModel.expectations.push(new tr.model.um.StubExpectation(
+ {parentModel: model, start: 0, duration: 100}));
+ model.userModel.expectations.push(new tr.model.um.StubExpectation(
+ {parentModel: model, start: 150, duration: 50}));
+ model.userModel.expectations.push(new tr.model.um.StubExpectation(
+ {parentModel: model, start: 50, duration: 100}));
+ model.userModel.expectations.push(new tr.model.um.StubExpectation(
+ {parentModel: model, start: 0, duration: 50}));
+ // Model.createImportTracesTask() automatically sorts UEs by start time.
+ });
+ assert.strictEqual(2, track.subRows_.length);
+ assert.strictEqual(2, track.subRows_[0].length);
+ assert.strictEqual(3, track.subRows_[1].length);
+ Polymer.dom(drawingContainer).appendChild(track);
+ this.addHTMLOutput(div);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/kernel_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/kernel_track.html
new file mode 100644
index 00000000000..b10547bc2e9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/kernel_track.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/tracks/cpu_track.html">
+<link rel="import" href="/tracing/ui/tracks/process_track_base.html">
+<link rel="import" href="/tracing/ui/tracks/spacing_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const Cpu = tr.model.Cpu;
+ const CpuTrack = tr.ui.tracks.cpu_track;
+ const ProcessTrackBase = tr.ui.tracks.ProcessTrackBase;
+ const SpacingTrack = tr.ui.tracks.SpacingTrack;
+
+ /**
+ * @constructor
+ */
+ const KernelTrack = tr.ui.b.define('kernel-track', ProcessTrackBase);
+
+ KernelTrack.prototype = {
+ __proto__: ProcessTrackBase.prototype,
+
+ decorate(viewport) {
+ ProcessTrackBase.prototype.decorate.call(this, viewport);
+ },
+
+
+ // Kernel maps to processBase because we derive from ProcessTrackBase.
+ set kernel(kernel) {
+ this.processBase = kernel;
+ },
+
+ get kernel() {
+ return this.processBase;
+ },
+
+ get eventContainer() {
+ return this.kernel;
+ },
+
+ get hasVisibleContent() {
+ return this.children.length > 1;
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ tr.ui.tracks.ProcessTrackBase.prototype.addContainersToTrackMap.call(
+ this, containerToTrackMap);
+ containerToTrackMap.addContainer(this.kernel, this);
+ },
+
+ willAppendTracks_() {
+ const cpus = Object.values(this.kernel.cpus);
+ cpus.sort(tr.model.Cpu.compare);
+
+ let didAppendAtLeastOneTrack = false;
+ for (let i = 0; i < cpus.length; ++i) {
+ const cpu = cpus[i];
+ const track = new tr.ui.tracks.CpuTrack(this.viewport);
+ track.detailedMode = this.expanded;
+ track.cpu = cpu;
+ if (!track.hasVisibleContent) continue;
+ Polymer.dom(this).appendChild(track);
+ didAppendAtLeastOneTrack = true;
+ }
+ if (didAppendAtLeastOneTrack) {
+ Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));
+ }
+ }
+ };
+
+
+ return {
+ KernelTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/letter_dot_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/letter_dot_track.html
new file mode 100644
index 00000000000..6a642e52ff9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/letter_dot_track.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/proxy_selectable_item.html">
+<link rel="import" href="/tracing/ui/base/event_presenter.html">
+<link rel="import" href="/tracing/ui/base/heading.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<style>
+.letter-dot-track {
+ height: 18px;
+}
+</style>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const EventPresenter = tr.ui.b.EventPresenter;
+ const SelectionState = tr.model.SelectionState;
+
+ /**
+ * A track that displays an array of dots with filled letters inside them.
+ * @constructor
+ * @extends {Track}
+ */
+ const LetterDotTrack = tr.ui.b.define(
+ 'letter-dot-track', tr.ui.tracks.Track);
+
+ LetterDotTrack.prototype = {
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('letter-dot-track');
+ this.items_ = undefined;
+
+ this.heading_ = document.createElement('tr-ui-b-heading');
+ Polymer.dom(this).appendChild(this.heading_);
+ },
+
+ set heading(heading) {
+ this.heading_.heading = heading;
+ },
+
+ get heading() {
+ return this.heading_.heading;
+ },
+
+ set tooltip(tooltip) {
+ this.heading_.tooltip = tooltip;
+ },
+
+ get items() {
+ return this.items_;
+ },
+
+ set items(items) {
+ this.items_ = items;
+ this.invalidateDrawingContainer();
+ },
+
+ get height() {
+ return window.getComputedStyle(this).height;
+ },
+
+ set height(height) {
+ this.style.height = height;
+ },
+
+ get dumpRadiusView() {
+ return 7 * (window.devicePixelRatio || 1);
+ },
+
+ draw(type, viewLWorld, viewRWorld, viewHeight) {
+ if (this.items_ === undefined) return;
+
+ switch (type) {
+ case tr.ui.tracks.DrawType.GENERAL_EVENT:
+ this.drawLetterDots_(viewLWorld, viewRWorld);
+ break;
+ }
+ },
+
+ drawLetterDots_(viewLWorld, viewRWorld) {
+ const ctx = this.context();
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ const bounds = this.getBoundingClientRect();
+ const height = bounds.height * pixelRatio;
+ const halfHeight = height * 0.5;
+ const twoPi = Math.PI * 2;
+
+ // Culling parameters.
+ const dt = this.viewport.currentDisplayTransform;
+ const dumpRadiusView = this.dumpRadiusView;
+ const itemRadiusWorld = dt.xViewVectorToWorld(height);
+
+ // Draw the memory dumps.
+ const items = this.items_;
+ const loI = tr.b.findLowIndexInSortedArray(
+ items,
+ function(item) { return item.start; },
+ viewLWorld);
+
+ const oldFont = ctx.font;
+ ctx.font = '400 ' + Math.floor(9 * pixelRatio) + 'px Arial';
+ ctx.strokeStyle = 'rgb(0,0,0)';
+ ctx.textBaseline = 'middle';
+ ctx.textAlign = 'center';
+
+ const drawItems = function(selected) {
+ for (let i = loI; i < items.length; ++i) {
+ const item = items[i];
+ const x = item.start;
+ if (x - itemRadiusWorld > viewRWorld) break;
+
+ if (item.selected !== selected) continue;
+
+ const xView = dt.xWorldToView(x);
+
+ ctx.fillStyle = EventPresenter.getSelectableItemColorAsString(item);
+ ctx.beginPath();
+ ctx.arc(xView, halfHeight, dumpRadiusView + 0.5, 0, twoPi);
+ ctx.fill();
+ if (item.selected) {
+ ctx.lineWidth = 3;
+ ctx.strokeStyle = 'rgb(100,100,0)';
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.arc(xView, halfHeight, dumpRadiusView, 0, twoPi);
+ ctx.lineWidth = 1.5;
+ ctx.strokeStyle = 'rgb(255,255,0)';
+ ctx.stroke();
+ } else {
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = 'rgb(0,0,0)';
+ ctx.stroke();
+ }
+
+ ctx.fillStyle = 'rgb(255, 255, 255)';
+ ctx.fillText(item.dotLetter, xView, halfHeight);
+ }
+ };
+
+ // Draw unselected items first to make sure they don't occlude selected
+ // items.
+ drawItems(false);
+ drawItems(true);
+
+ ctx.lineWidth = 1;
+ ctx.font = oldFont;
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ if (this.items_ === undefined) return;
+
+ this.items_.forEach(function(item) {
+ item.addToTrackMap(eventToTrackMap, this);
+ }, this);
+ },
+
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ if (this.items_ === undefined) return;
+
+ const itemRadiusWorld = viewPixWidthWorld * this.dumpRadiusView;
+ tr.b.iterateOverIntersectingIntervals(
+ this.items_,
+ function(x) { return x.start - itemRadiusWorld; },
+ function(x) { return 2 * itemRadiusWorld; },
+ loWX, hiWX,
+ function(item) {
+ item.addToSelection(selection);
+ }.bind(this));
+ },
+
+ /**
+ * Add the item to the left or right of the provided event, if any, to the
+ * selection.
+ * @param {event} The current event item.
+ * @param {Number} offset Number of slices away from the event to look.
+ * @param {Selection} selection The selection to add an event to,
+ * if found.
+ * @return {boolean} Whether an event was found.
+ * @private
+ */
+ addEventNearToProvidedEventToSelection(event, offset, selection) {
+ if (this.items_ === undefined) return;
+
+ const index = this.items_.findIndex(item => item.modelItem === event);
+ if (index === -1) return false;
+
+ const newIndex = index + offset;
+ if (newIndex >= 0 && newIndex < this.items_.length) {
+ this.items_[newIndex].addToSelection(selection);
+ return true;
+ }
+ return false;
+ },
+
+ addAllEventsMatchingFilterToSelection(filter, selection) {
+ },
+
+ addClosestEventToSelection(worldX, worldMaxDist, loY, hiY,
+ selection) {
+ if (this.items_ === undefined) return;
+
+ const item = tr.b.findClosestElementInSortedArray(
+ this.items_,
+ function(x) { return x.start; },
+ worldX,
+ worldMaxDist);
+
+ if (!item) return;
+
+ item.addToSelection(selection);
+ }
+ };
+
+ /**
+ * A filled dot with a letter inside it.
+ *
+ * @constructor
+ * @extends {ProxySelectableItem}
+ */
+ function LetterDot(modelItem, dotLetter, colorId, start) {
+ tr.model.ProxySelectableItem.call(this, modelItem);
+ this.dotLetter = dotLetter;
+ this.colorId = colorId;
+ this.start = start;
+ }
+
+ LetterDot.prototype = {
+ __proto__: tr.model.ProxySelectableItem.prototype
+ };
+
+ return {
+ LetterDotTrack,
+ LetterDot,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/letter_dot_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/letter_dot_track_test.html
new file mode 100644
index 00000000000..b37034afab2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/letter_dot_track_test.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/letter_dot_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const LetterDotTrack = tr.ui.tracks.LetterDotTrack;
+ const LetterDot = tr.ui.tracks.LetterDot;
+ const SelectionState = tr.model.SelectionState;
+ const Viewport = tr.ui.TimelineViewport;
+
+ const createItems = function() {
+ const items = [
+ new LetterDot({selectionState: SelectionState.SELECTED}, 'a', 7, 5),
+ new LetterDot({selectionState: SelectionState.SELECTED}, 'b', 2, 20),
+ new LetterDot({selectionState: SelectionState.NONE}, 'c', 4, 35),
+ new LetterDot({selectionState: SelectionState.NONE}, 'd', 4, 50)
+ ];
+ return items;
+ };
+
+ test('instantiate', function() {
+ const items = createItems();
+
+ const div = document.createElement('div');
+
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = LetterDotTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.items = items;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 60, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ test('selectionHitTesting', function() {
+ const items = createItems();
+
+ const track = new LetterDotTrack(new Viewport());
+ track.items = items;
+
+ // Fake a view pixel size.
+ const devicePixelRatio = window.devicePixelRatio || 1;
+ const viewPixWidthWorld = 0.1 / devicePixelRatio;
+
+ // Hit outside range
+ let selection = [];
+ track.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ 3, 4, viewPixWidthWorld, selection);
+ assert.strictEqual(selection.length, 0);
+
+ // Hit the first item, via pixel-nearness.
+ selection = [];
+ track.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ 19.98, 19.99, viewPixWidthWorld, selection);
+ assert.strictEqual(selection.length, 1);
+ assert.strictEqual(selection[0], items[1].modelItem);
+
+ // Hit the instance, between the 1st and 2nd snapshots
+ selection = [];
+ track.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ 30, 50, viewPixWidthWorld, selection);
+ assert.strictEqual(selection.length, 2);
+ assert.strictEqual(selection[0], items[2].modelItem);
+ assert.strictEqual(selection[1], items[3].modelItem);
+ });
+
+ test('addEventNearToProvidedEventToSelection', function() {
+ const items = createItems();
+
+ const track = new LetterDotTrack(new Viewport());
+ track.items = items;
+
+ // Right from the middle of items.
+ const selection1 = [];
+ assert.isTrue(track.addEventNearToProvidedEventToSelection(
+ items[2].modelItem, 1, selection1));
+ assert.strictEqual(selection1.length, 1);
+ assert.strictEqual(selection1[0], items[3].modelItem);
+
+ // Left from the middle of items.
+ const selection2 = [];
+ assert.isTrue(track.addEventNearToProvidedEventToSelection(
+ items[2].modelItem, -1, selection2));
+ assert.strictEqual(selection2.length, 1);
+ assert.strictEqual(selection2[0], items[1].modelItem);
+
+ // Right from the right edge of items.
+ const selection3 = [];
+ assert.isFalse(track.addEventNearToProvidedEventToSelection(
+ items[3].modelItem, 1, selection3));
+ assert.strictEqual(selection3.length, 0);
+
+ // Left from the left edge of items.
+ const selection4 = [];
+ assert.isFalse(track.addEventNearToProvidedEventToSelection(
+ items[0].modelItem, -1, selection4));
+ assert.strictEqual(selection4.length, 0);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_test_utils.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_test_utils.html
new file mode 100644
index 00000000000..611bd8664f8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_test_utils.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/global_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_dump_test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/process_memory_dump.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/model/vm_region.html">
+
+<script>
+'use strict';
+
+/**
+ * @fileoverview Helper functions for memory dump track tests.
+ */
+tr.exportTo('tr.ui.tracks', function() {
+ const ProcessMemoryDump = tr.model.ProcessMemoryDump;
+ const GlobalMemoryDump = tr.model.GlobalMemoryDump;
+ const VMRegion = tr.model.VMRegion;
+ const VMRegionClassificationNode = tr.model.VMRegionClassificationNode;
+ const SelectionState = tr.model.SelectionState;
+ const addGlobalMemoryDump = tr.model.MemoryDumpTestUtils.addGlobalMemoryDump;
+ const addProcessMemoryDump =
+ tr.model.MemoryDumpTestUtils.addProcessMemoryDump;
+ const newAllocatorDump = tr.model.MemoryDumpTestUtils.newAllocatorDump;
+ const addOwnershipLink = tr.model.MemoryDumpTestUtils.addOwnershipLink;
+ const BACKGROUND = tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;
+ const LIGHT = tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;
+ const DETAILED = tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;
+
+ function createVMRegions(pssValues) {
+ return VMRegionClassificationNode.fromRegions(
+ pssValues.map(function(pssValue, i) {
+ return VMRegion.fromDict({
+ startAddress: 1000 * i,
+ sizeInBytes: 1000,
+ protectionFlags: VMRegion.PROTECTION_FLAG_READ,
+ mappedFile: '[stack' + i + ']',
+ byteStats: {
+ privateDirtyResident: pssValue / 3,
+ swapped: pssValue * 3,
+ proportionalResident: pssValue
+ }
+ });
+ }));
+ }
+
+ function createAllocatorDumps(memoryDump, dumpData) {
+ // Create the individual allocator dumps.
+ const allocatorDumps = {};
+ for (const [allocatorName, data] of Object.entries(dumpData)) {
+ const size = data.size;
+ assert.typeOf(size, 'number'); // Sanity check.
+ allocatorDumps[allocatorName] = newAllocatorDump(
+ memoryDump, allocatorName, {numerics: {size}});
+ }
+
+ // Add ownership links between them.
+ for (const [allocatorName, data] of Object.entries(dumpData)) {
+ const owns = data.owns;
+ if (owns === undefined) continue;
+
+ const ownerDump = allocatorDumps[allocatorName];
+ assert.isDefined(ownerDump); // Sanity check.
+ const ownedDump = allocatorDumps[owns];
+ assert.isDefined(ownedDump); // Sanity check.
+
+ addOwnershipLink(ownerDump, ownedDump);
+ }
+
+ return Object.values(allocatorDumps);
+ }
+
+ function addProcessMemoryDumpWithFields(globalMemoryDump, process, start,
+ opt_pssValues, opt_dumpData) {
+ const pmd = addProcessMemoryDump(globalMemoryDump, process, {ts: start});
+ if (opt_pssValues !== undefined) {
+ pmd.vmRegions = createVMRegions(opt_pssValues);
+ }
+ if (opt_dumpData !== undefined) {
+ pmd.memoryAllocatorDumps = createAllocatorDumps(pmd, opt_dumpData);
+ }
+ }
+
+ function createModelWithDumps(withVMRegions, withAllocatorDumps) {
+ const maybePssValues = function(pssValues) {
+ return withVMRegions ? pssValues : undefined;
+ };
+ const maybeDumpData = function(dumpData) {
+ return withAllocatorDumps ? dumpData : undefined;
+ };
+ return tr.c.TestUtils.newModel(function(model) {
+ // Construct a model with three processes.
+ const pa = model.getOrCreateProcess(3);
+ const pb = model.getOrCreateProcess(6);
+ const pc = model.getOrCreateProcess(9);
+
+ const gmd1 = addGlobalMemoryDump(model, {ts: 0, levelOfDetail: LIGHT});
+ addProcessMemoryDumpWithFields(gmd1, pa, 0, maybePssValues([111]));
+ addProcessMemoryDumpWithFields(gmd1, pb, 0.2, undefined,
+ maybeDumpData({oilpan: {size: 1024}}));
+
+ const gmd2 = addGlobalMemoryDump(model, {ts: 5, levelOfDetail: DETAILED});
+ addProcessMemoryDumpWithFields(gmd2, pa, 0);
+ addProcessMemoryDumpWithFields(gmd2, pb, 4.99, maybePssValues([100, 50]),
+ maybeDumpData({v8: {size: 512}}));
+ addProcessMemoryDumpWithFields(gmd2, pc, 5.12, undefined,
+ maybeDumpData({oilpan: {size: 128, owns: 'v8'},
+ v8: {size: 384, owns: 'tracing'}, tracing: {size: 65920}}));
+
+ const gmd3 = addGlobalMemoryDump(
+ model, {ts: 15, levelOfDetail: DETAILED});
+ addProcessMemoryDumpWithFields(gmd3, pa, 15.5, maybePssValues([]),
+ maybeDumpData({v8: {size: 768}}));
+ addProcessMemoryDumpWithFields(gmd3, pc, 14.5,
+ maybePssValues([70, 70, 70]), maybeDumpData({oilpan: {size: 512}}));
+
+ const gmd4 = addGlobalMemoryDump(model, {ts: 18, levelOfDetail: LIGHT});
+
+ const gmd5 = addGlobalMemoryDump(model,
+ {ts: 20, levelOfDetail: BACKGROUND});
+ addProcessMemoryDumpWithFields(gmd5, pa, 0, maybePssValues([105]));
+ addProcessMemoryDumpWithFields(gmd5, pb, 0.2, undefined,
+ maybeDumpData({oilpan: {size: 100}}));
+ });
+ }
+
+ function createTestGlobalMemoryDumps(withVMRegions, withAllocatorDumps) {
+ const model = createModelWithDumps(withVMRegions, withAllocatorDumps);
+ const dumps = model.globalMemoryDumps;
+ dumps[1].selectionState = SelectionState.HIGHLIGHTED;
+ dumps[2].selectionState = SelectionState.SELECTED;
+ return dumps;
+ }
+
+ function createTestProcessMemoryDumps(withVMRegions, withAllocatorDumps) {
+ const model = createModelWithDumps(withVMRegions, withAllocatorDumps);
+ const dumps = model.getProcess(9).memoryDumps;
+ dumps[0].selectionState = SelectionState.SELECTED;
+ dumps[1].selectionState = SelectionState.HIGHLIGHTED;
+ return dumps;
+ }
+
+ return {
+ createTestGlobalMemoryDumps,
+ createTestProcessMemoryDumps,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_util.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_util.html
new file mode 100644
index 00000000000..a483d545880
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_util.html
@@ -0,0 +1,253 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/container_memory_dump.html">
+<link rel="import" href="/tracing/model/memory_allocator_dump.html">
+<link rel="import" href="/tracing/ui/tracks/chart_point.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series_y_axis.html">
+<link rel="import" href="/tracing/ui/tracks/chart_track.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/letter_dot_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ const DISPLAYED_SIZE_NUMERIC_NAME =
+ tr.model.MemoryAllocatorDump.DISPLAYED_SIZE_NUMERIC_NAME;
+ const BACKGROUND = tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;
+ const LIGHT = tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;
+ const DETAILED = tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;
+
+ const SYSTEM_MEMORY_CHART_RENDERING_CONFIG = {
+ chartType: tr.ui.tracks.ChartSeriesType.AREA,
+ colorId: ColorScheme.getColorIdForGeneralPurposeString('systemMemory'),
+ backgroundOpacity: 0.8
+ };
+ const SYSTEM_MEMORY_SERIES_NAMES = ['Used (KB)', 'Swapped (KB)'];
+
+ /** Extract PSS values of processes in a global memory dump. */
+ function extractGlobalMemoryDumpUsedSizes(globalMemoryDump, addSize) {
+ for (const [pid, pmd] of
+ Object.entries(globalMemoryDump.processMemoryDumps)) {
+ const mostRecentVmRegions = pmd.mostRecentVmRegions;
+ if (mostRecentVmRegions === undefined) continue;
+ addSize(pid, mostRecentVmRegions.byteStats.proportionalResident || 0,
+ pmd.process.userFriendlyName);
+ }
+ }
+
+ /** Extract sizes of root allocators in a process memory dump. */
+ function extractProcessMemoryDumpAllocatorSizes(processMemoryDump, addSize) {
+ const allocatorDumps = processMemoryDump.memoryAllocatorDumps;
+ if (allocatorDumps === undefined) return;
+
+ allocatorDumps.forEach(function(allocatorDump) {
+ // Don't show tracing overhead in the charts.
+ // TODO(petrcermak): Find a less hacky way to do this.
+ if (allocatorDump.fullName === 'tracing') return;
+
+ const allocatorSize = allocatorDump.numerics[DISPLAYED_SIZE_NUMERIC_NAME];
+ if (allocatorSize === undefined) return;
+
+ const allocatorSizeValue = allocatorSize.value;
+ if (allocatorSizeValue === undefined) return;
+
+ addSize(allocatorDump.fullName, allocatorSizeValue);
+ });
+ }
+
+ /** Extract sizes of root allocators in a global memory dump. */
+ function extractGlobalMemoryDumpAllocatorSizes(globalMemoryDump, addSize) {
+ for (const pmd of Object.values(globalMemoryDump.processMemoryDumps)) {
+ extractProcessMemoryDumpAllocatorSizes(pmd, addSize);
+ }
+ }
+
+ /**
+ * A generic function which converts a list of memory dumps to a list of
+ * chart series.
+ *
+ * @param {!Array<!tr.model.ContainerMemoryDump>} memoryDumps List of
+ * container memory dumps.
+ * @param {!function(
+ * !tr.model.ContainerMemoryDump,
+ * !function(string, number, string=))} dumpSizeExtractor Callback for
+ * extracting sizes from a container memory dump.
+ * @return {(!Array<!tr.ui.tracks.ChartSeries>|undefined)} List of chart
+ * series (or undefined if no size is extracted from any container memory
+ * dump).
+ */
+ function buildMemoryChartSeries(memoryDumps, dumpSizeExtractor) {
+ const dumpCount = memoryDumps.length;
+ const idToTimestampToPoint = {};
+ const idToName = {};
+
+ // Extract the sizes of all components from each memory dump.
+ memoryDumps.forEach(function(dump, index) {
+ dumpSizeExtractor(dump, function addSize(id, size, opt_name) {
+ let timestampToPoint = idToTimestampToPoint[id];
+ if (timestampToPoint === undefined) {
+ idToTimestampToPoint[id] = timestampToPoint = new Array(dumpCount);
+ for (let i = 0; i < dumpCount; i++) {
+ const modelItem = memoryDumps[i];
+ timestampToPoint[i] = new tr.ui.tracks.ChartPoint(
+ modelItem, modelItem.start, 0);
+ }
+ }
+ timestampToPoint[index].y += size;
+ if (opt_name !== undefined) idToName[id] = opt_name;
+ });
+ });
+
+ // Do not generate any chart series if no sizes were extracted.
+ const ids = Object.keys(idToTimestampToPoint);
+ if (ids.length === 0) return undefined;
+
+ ids.sort();
+ for (let i = 0; i < dumpCount; i++) {
+ let baseSize = 0;
+ // Traverse |ids| in reverse (alphabetical) order so that the first id is
+ // at the top of the chart.
+ for (let j = ids.length - 1; j >= 0; j--) {
+ const point = idToTimestampToPoint[ids[j]][i];
+ point.yBase = baseSize;
+ point.y += baseSize;
+ baseSize = point.y;
+ }
+ }
+
+ // Create one common axis for all memory chart series.
+ const seriesYAxis = new tr.ui.tracks.ChartSeriesYAxis(0);
+
+ // Build a chart series for each id.
+ const series = ids.map(function(id) {
+ const colorId = ColorScheme.getColorIdForGeneralPurposeString(
+ idToName[id] || id);
+ const renderingConfig = {
+ chartType: tr.ui.tracks.ChartSeriesType.AREA,
+ colorId,
+ backgroundOpacity: 0.8
+ };
+ return new tr.ui.tracks.ChartSeries(idToTimestampToPoint[id],
+ seriesYAxis, renderingConfig);
+ });
+
+ // Ensure that the series at the top of the chart are drawn last.
+ series.reverse();
+
+ return series;
+ }
+
+ /**
+ * Transform a list of memory dumps to a list of letter dots (with letter 'M'
+ * inside).
+ */
+ function buildMemoryLetterDots(memoryDumps) {
+ const backgroundMemoryColorId =
+ ColorScheme.getColorIdForReservedName('background_memory_dump');
+ const lightMemoryColorId =
+ ColorScheme.getColorIdForReservedName('light_memory_dump');
+ const detailedMemoryColorId =
+ ColorScheme.getColorIdForReservedName('detailed_memory_dump');
+ return memoryDumps.map(function(memoryDump) {
+ let memoryColorId;
+ switch (memoryDump.levelOfDetail) {
+ case BACKGROUND:
+ memoryColorId = backgroundMemoryColorId;
+ break;
+ case DETAILED:
+ memoryColorId = detailedMemoryColorId;
+ break;
+ case LIGHT:
+ default:
+ memoryColorId = lightMemoryColorId;
+ }
+ return new tr.ui.tracks.LetterDot(
+ memoryDump, 'M', memoryColorId, memoryDump.start);
+ });
+ }
+
+ /**
+ * Convert a list of global memory dumps to a list of chart series (one per
+ * process). Each series represents the evolution of the memory used by the
+ * process over time.
+ */
+ function buildGlobalUsedMemoryChartSeries(globalMemoryDumps) {
+ return buildMemoryChartSeries(globalMemoryDumps,
+ extractGlobalMemoryDumpUsedSizes);
+ }
+
+ /**
+ * Convert a list of process memory dumps to a list of chart series (one per
+ * root allocator). Each series represents the evolution of the size of a the
+ * corresponding root allocator (e.g. 'v8') over time.
+ */
+ function buildProcessAllocatedMemoryChartSeries(processMemoryDumps) {
+ return buildMemoryChartSeries(processMemoryDumps,
+ extractProcessMemoryDumpAllocatorSizes);
+ }
+
+ /**
+ * Convert a list of global memory dumps to a list of chart series (one per
+ * root allocator). Each series represents the evolution of the size of a the
+ * corresponding root allocator (e.g. 'v8') over time.
+ */
+ function buildGlobalAllocatedMemoryChartSeries(globalMemoryDumps) {
+ return buildMemoryChartSeries(globalMemoryDumps,
+ extractGlobalMemoryDumpAllocatorSizes);
+ }
+
+ /**
+ * Converts system memory counters in the model to a list of
+ * {'name': trackName, 'series': ChartSeries}.
+ */
+ function buildSystemMemoryChartSeries(model) {
+ if (model.kernel.counters === undefined) return;
+ const memoryCounter = model.kernel.counters['global.SystemMemory'];
+ if (memoryCounter === undefined) return;
+
+ const tracks = [];
+ for (const name of SYSTEM_MEMORY_SERIES_NAMES) {
+ const series = memoryCounter.series.find(series => series.name === name);
+ if (series === undefined || series.samples.length === 0) return;
+
+ const chartPoints = [];
+ const valueRange = new tr.b.math.Range();
+ for (const sample of series.samples) {
+ chartPoints.push(new tr.ui.tracks.ChartPoint(
+ sample, sample.timestamp, sample.value, 0));
+ valueRange.addValue(sample.value);
+ }
+ // Stretch min to max range over the top half of a chart for readability.
+ const baseLine = Math.max(0, valueRange.min - valueRange.range);
+ const axisY = new tr.ui.tracks.ChartSeriesYAxis(baseLine, valueRange.max);
+ const chartSeries =
+ [new tr.ui.tracks.ChartSeries(chartPoints, axisY,
+ SYSTEM_MEMORY_CHART_RENDERING_CONFIG)];
+ tracks.push({
+ name: 'System Memory ' + name,
+ series: chartSeries
+ });
+ }
+ return tracks;
+ }
+
+ return {
+ buildMemoryLetterDots,
+ buildGlobalUsedMemoryChartSeries,
+ buildProcessAllocatedMemoryChartSeries,
+ buildGlobalAllocatedMemoryChartSeries,
+ buildSystemMemoryChartSeries,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_util_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_util_test.html
new file mode 100644
index 00000000000..f4f9451b4b9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_dump_track_util_test.html
@@ -0,0 +1,270 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/tracks/memory_dump_track_test_utils.html">
+<link rel="import" href="/tracing/ui/tracks/memory_dump_track_util.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const SelectionState = tr.model.SelectionState;
+ const createTestGlobalMemoryDumps = tr.ui.tracks.createTestGlobalMemoryDumps;
+ const createTestProcessMemoryDumps =
+ tr.ui.tracks.createTestProcessMemoryDumps;
+
+ test('buildMemoryLetterDots_withoutVMRegions', function() {
+ const dumps = createTestGlobalMemoryDumps(false, false);
+ const items = tr.ui.tracks.buildMemoryLetterDots(dumps);
+
+ assert.lengthOf(items, 5);
+ assert.strictEqual(items[0].start, 0);
+ assert.strictEqual(items[1].start, 5);
+ assert.strictEqual(items[2].start, 15);
+ assert.strictEqual(items[3].start, 18);
+ assert.strictEqual(items[4].start, 20);
+
+ // Check model mapping.
+ assert.strictEqual(items[1].selectionState, SelectionState.HIGHLIGHTED);
+ assert.isTrue(items[2].selected);
+ assert.strictEqual(items[3].modelItem, dumps[3]);
+ });
+
+ test('buildMemoryLetterDots_withVMRegions', function() {
+ const dumps = createTestGlobalMemoryDumps(false, false);
+ const items = tr.ui.tracks.buildMemoryLetterDots(dumps);
+
+ assert.lengthOf(items, 5);
+ assert.strictEqual(items[0].start, 0);
+ assert.strictEqual(items[1].start, 5);
+ assert.strictEqual(items[2].start, 15);
+ assert.strictEqual(items[3].start, 18);
+ assert.strictEqual(items[4].start, 20);
+
+ // Check model mapping.
+ assert.strictEqual(items[1].selectionState, SelectionState.HIGHLIGHTED);
+ assert.isTrue(items[2].selected);
+ assert.strictEqual(items[3].modelItem, dumps[3]);
+ });
+
+ test('buildGlobalUsedMemoryChartSeries_withoutVMRegions', function() {
+ const dumps = createTestGlobalMemoryDumps(false, false);
+ const series = tr.ui.tracks.buildGlobalUsedMemoryChartSeries(dumps);
+
+ assert.isUndefined(series);
+ });
+
+ test('buildGlobalUsedMemoryChartSeries_withVMRegions', function() {
+ const dumps = createTestGlobalMemoryDumps(true, false);
+ const series = tr.ui.tracks.buildGlobalUsedMemoryChartSeries(dumps);
+
+ assert.lengthOf(series, 3);
+
+ const sa = series[2];
+ const sb = series[1];
+ const sc = series[0];
+
+ assert.lengthOf(sa.points, 5);
+ assert.lengthOf(sb.points, 5);
+ assert.lengthOf(sc.points, 5);
+
+ // Process A: VM regions defined -> sum their PSS values (111).
+ // Process B: VM regions undefined and no previous value -> assume zero.
+ // Process C: Memory dump not present -> assume process not alive (0).
+ assert.strictEqual(sa.points[0].x, 0);
+ assert.strictEqual(sb.points[0].x, 0);
+ assert.strictEqual(sc.points[0].x, 0);
+ assert.strictEqual(sa.points[0].y, 111);
+ assert.strictEqual(sb.points[0].y, 0);
+ assert.strictEqual(sc.points[0].y, 0);
+ assert.strictEqual(sa.points[0].yBase, 0);
+ assert.strictEqual(sb.points[0].yBase, 0);
+ assert.strictEqual(sc.points[0].yBase, 0);
+
+ // Process A: VM regions undefined -> assume previous value (111).
+ // Process B: VM regions defined -> sum their PSS values (100 + 50).
+ // Process C: VM regions undefined -> assume previous value (0).
+ assert.strictEqual(sa.points[1].x, 5);
+ assert.strictEqual(sb.points[1].x, 5);
+ assert.strictEqual(sc.points[1].x, 5);
+ assert.strictEqual(sa.points[1].y, 150 + 111);
+ assert.strictEqual(sb.points[1].y, 150);
+ assert.strictEqual(sc.points[1].y, 0);
+ assert.strictEqual(sa.points[1].yBase, 150);
+ assert.strictEqual(sb.points[1].yBase, 0);
+ assert.strictEqual(sc.points[1].yBase, 0);
+
+ // Process A: VM regions defined -> sum their PSS values (0).
+ // Process B: Memory dump not present -> assume process not alive (0).
+ // Process C: VM regions defined -> sum their PSS values (70 + 70 + 70).
+ assert.strictEqual(sa.points[2].x, 15);
+ assert.strictEqual(sb.points[2].x, 15);
+ assert.strictEqual(sc.points[2].x, 15);
+ assert.strictEqual(sa.points[2].y, 210);
+ assert.strictEqual(sb.points[2].y, 210);
+ assert.strictEqual(sc.points[2].y, 210);
+ assert.strictEqual(sa.points[2].yBase, 210);
+ assert.strictEqual(sb.points[2].yBase, 210);
+ assert.strictEqual(sc.points[2].yBase, 0);
+
+ // All processes: Memory dump not present -> assume process not alive (0).
+ assert.strictEqual(sa.points[3].x, 18);
+ assert.strictEqual(sb.points[3].x, 18);
+ assert.strictEqual(sc.points[3].x, 18);
+ assert.strictEqual(sa.points[3].y, 0);
+ assert.strictEqual(sb.points[3].y, 0);
+ assert.strictEqual(sc.points[3].y, 0);
+ assert.strictEqual(sa.points[3].yBase, 0);
+ assert.strictEqual(sb.points[3].yBase, 0);
+ assert.strictEqual(sc.points[3].yBase, 0);
+
+ // Process A: VM regions defined -> sum their PSS values (105).
+ // Process B: VM regions undefined and no previous value -> assume zero.
+ // Process C: Memory dump not present -> assume process not alive (0).
+ assert.strictEqual(sa.points[4].x, 20);
+ assert.strictEqual(sb.points[4].x, 20);
+ assert.strictEqual(sc.points[4].x, 20);
+ assert.strictEqual(sa.points[4].y, 105);
+ assert.strictEqual(sb.points[4].y, 0);
+ assert.strictEqual(sc.points[4].y, 0);
+ assert.strictEqual(sa.points[4].yBase, 0);
+ assert.strictEqual(sb.points[4].yBase, 0);
+ assert.strictEqual(sc.points[4].yBase, 0);
+
+ // Check model mapping.
+ assert.strictEqual(sa.points[1].selectionState, SelectionState.HIGHLIGHTED);
+ assert.isTrue(sb.points[2].selected);
+ assert.strictEqual(sc.points[3].modelItem, dumps[3]);
+ });
+
+ test('buildGlobalAllocatedMemoryChartSeries_withoutMemoryAllocatorDumps',
+ function() {
+ const dumps = createTestGlobalMemoryDumps(false, false);
+ const series = tr.ui.tracks.buildGlobalAllocatedMemoryChartSeries(
+ dumps);
+
+ assert.isUndefined(series);
+ });
+
+ test('buildGlobalAllocatedMemoryChartSeries_withMemoryAllocatorDumps',
+ function() {
+ const dumps = createTestGlobalMemoryDumps(false, true);
+ const series = tr.ui.tracks.buildGlobalAllocatedMemoryChartSeries(
+ dumps);
+
+ assert.lengthOf(series, 2);
+
+ const so = series[1];
+ const sv = series[0];
+
+ assert.lengthOf(so.points, 5);
+ assert.lengthOf(sv.points, 5);
+
+ // Oilpan: Only process B dumps allocated objects size (1024).
+ // V8: No process dumps allocated objects size (0).
+ assert.strictEqual(so.points[0].x, 0);
+ assert.strictEqual(sv.points[0].x, 0);
+ assert.strictEqual(so.points[0].y, 1024);
+ assert.strictEqual(sv.points[0].y, 0);
+ assert.strictEqual(so.points[0].yBase, 0);
+ assert.strictEqual(sv.points[0].yBase, 0);
+
+ // Oilpan: Process B did not provide a value and process C dumps (128).
+ // V8: Processes B and C dump (512 + 256).
+ assert.strictEqual(so.points[1].x, 5);
+ assert.strictEqual(sv.points[1].x, 5);
+ assert.strictEqual(so.points[1].y, 768 + 128);
+ assert.strictEqual(sv.points[1].y, 768);
+ assert.strictEqual(so.points[1].yBase, 768);
+ assert.strictEqual(sv.points[1].yBase, 0);
+
+ // Oilpan: Process B assumed not alive and process C dumps (512)
+ // V8: Process A dumps now, process B assumed not alive, process C did
+ // not provide a value (768).
+ assert.strictEqual(so.points[2].x, 15);
+ assert.strictEqual(sv.points[2].x, 15);
+ assert.strictEqual(so.points[2].y, 768 + 512);
+ assert.strictEqual(sv.points[2].y, 768);
+ assert.strictEqual(so.points[2].yBase, 768);
+ assert.strictEqual(sv.points[2].yBase, 0);
+
+ // All processes: Memory dump not present -> assume process not alive
+ // (0).
+ assert.strictEqual(so.points[3].x, 18);
+ assert.strictEqual(sv.points[3].x, 18);
+ assert.strictEqual(so.points[3].y, 0);
+ assert.strictEqual(sv.points[3].y, 0);
+ assert.strictEqual(so.points[3].yBase, 0);
+ assert.strictEqual(sv.points[3].yBase, 0);
+
+ // Oilpan: Only process B dumps allocated objects size (100).
+ // V8: No process dumps allocated objects size (0).
+ assert.strictEqual(so.points[4].x, 20);
+ assert.strictEqual(sv.points[4].x, 20);
+ assert.strictEqual(so.points[4].y, 100);
+ assert.strictEqual(sv.points[4].y, 0);
+
+ // Check model mapping.
+ assert.strictEqual(
+ so.points[1].selectionState, SelectionState.HIGHLIGHTED);
+ assert.isTrue(sv.points[2].selected);
+ assert.strictEqual(so.points[3].modelItem, dumps[3]);
+ });
+
+ test('buildProcessAllocatedMemoryChartSeries_withoutMemoryAllocatorDumps',
+ function() {
+ const dumps = createTestProcessMemoryDumps(false, false);
+ const series = tr.ui.tracks.buildProcessAllocatedMemoryChartSeries(
+ dumps);
+
+ assert.isUndefined(series);
+ });
+
+ test('buildProcessAllocatedMemoryChartSeries_withMemoryAllocatorDumps',
+ function() {
+ const dumps = createTestProcessMemoryDumps(false, true);
+ const series = tr.ui.tracks.buildProcessAllocatedMemoryChartSeries(
+ dumps);
+
+ // There should be only 2 series (because 'tracing' is not shown in the
+ // charts).
+ assert.lengthOf(series, 2);
+
+ const so = series[1];
+ const sv = series[0];
+
+ assert.lengthOf(so.points, 2);
+ assert.lengthOf(sv.points, 2);
+
+ // Oilpan: Process dumps (128).
+ // V8: Process dumps (256).
+ assert.strictEqual(so.points[0].x, 5.12);
+ assert.strictEqual(sv.points[0].x, 5.12);
+ assert.strictEqual(so.points[0].y, 256 + 128);
+ assert.strictEqual(sv.points[0].y, 256);
+ assert.strictEqual(so.points[0].yBase, 256);
+ assert.strictEqual(sv.points[0].yBase, 0);
+
+ // Oilpan: Process dumps (512).
+ // V8: Process did not provide a value (0).
+ assert.strictEqual(so.points[1].x, 14.5);
+ assert.strictEqual(sv.points[1].x, 14.5);
+ assert.strictEqual(so.points[1].y, 512);
+ assert.strictEqual(sv.points[1].y, 0);
+ assert.strictEqual(so.points[1].yBase, 0);
+ assert.strictEqual(sv.points[1].yBase, 0);
+
+ // Check model mapping.
+ assert.strictEqual(
+ so.points[1].selectionState, SelectionState.HIGHLIGHTED);
+ assert.isTrue(sv.points[0].selected);
+ assert.strictEqual(so.points[1].modelItem, dumps[1]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_track.html
new file mode 100644
index 00000000000..bf59f11349e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_track.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/tracks/letter_dot_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const LetterDotTrack = tr.ui.tracks.LetterDotTrack;
+
+ /**
+ * A track that displays global memory events.
+ *
+ * @constructor
+ * @extends {tr.ui.tracks.LetterDotTrack}
+ */
+ const MemoryTrack = tr.ui.b.define('memory-track', LetterDotTrack);
+
+ MemoryTrack.prototype = {
+ __proto__: LetterDotTrack.prototype,
+
+ decorate(viewport) {
+ LetterDotTrack.prototype.decorate.call(this, viewport);
+ this.classList.add('memory-track');
+ this.heading = 'Memory Events';
+ this.lowMemoryEvents_ = undefined;
+ },
+
+ initialize(model) {
+ if (model !== undefined) {
+ this.lowMemoryEvents_ = model.device.lowMemoryEvents;
+ } else {
+ this.lowMemoryEvents_ = undefined;
+ }
+
+ if (this.hasVisibleContent) {
+ this.items = this.buildMemoryLetterDots_(this.lowMemoryEvents_);
+ }
+ },
+
+ get hasVisibleContent() {
+ return !!this.lowMemoryEvents_ && this.lowMemoryEvents_.length !== 0;
+ },
+
+ buildMemoryLetterDots_(memoryEvents) {
+ return memoryEvents.map(
+ memoryEvent => new tr.ui.tracks.LetterDot(
+ memoryEvent,
+ 'K',
+ ColorScheme.getColorIdForReservedName('background_memory_dump'),
+ memoryEvent.start
+ )
+ );
+ },
+ };
+
+ return {
+ MemoryTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_track_test.html
new file mode 100644
index 00000000000..60f1c8ccd2c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/memory_track_test.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<!--
+ Copyright 2017 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/extras/memory/lowmemory_auditor.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/thread_slice.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/memory_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Model = tr.Model;
+ const ThreadSlice = tr.model.ThreadSlice;
+
+ // Input : slices is an array-of-array-of slices. Each top level array
+ // represents a process. So, each slice in one of the top level array
+ // will be placed in the same process.
+ function buildModel(slices) {
+ const model = tr.c.TestUtils.newModel(function(model) {
+ const process = model.getOrCreateProcess(1);
+ for (let i = 0; i < slices.length; i++) {
+ const thread = process.getOrCreateThread(i);
+ slices[i].forEach(s => thread.sliceGroup.pushSlice(s));
+ }
+ });
+
+ const auditor = new tr.e.audits.LowMemoryAuditor(model);
+ auditor.runAnnotate();
+ return model;
+ }
+
+ function createMemoryTrack(model, interval) {
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ div.appendChild(drawingContainer);
+ const track = new tr.ui.tracks.MemoryTrack(drawingContainer.viewport);
+ if (model !== undefined) {
+ setDisplayTransformFromBounds(viewport, model.bounds);
+ }
+ track.initialize(model, interval);
+ drawingContainer.appendChild(track);
+ this.addHTMLOutput(drawingContainer);
+ return track;
+ }
+
+ /**
+ * Sets the mapping between the input range of timestamps and the output range
+ * of horizontal pixels.
+ */
+ function setDisplayTransformFromBounds(viewport, bounds) {
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ const chartPixelWidth =
+ (window.innerWidth - tr.ui.b.constants.HEADING_WIDTH) * pixelRatio;
+ dt.xSetWorldBounds(bounds.min, bounds.max, chartPixelWidth);
+ viewport.setDisplayTransformImmediately(dt);
+ }
+
+ test('instantiate', function() {
+ const sliceA = new tr.model.ThreadSlice('lowmemory', title, 0, 5.5111, {});
+ const sliceB = new tr.model.ThreadSlice('lowmemory', title, 0, 11.2384, {});
+
+ const model = buildModel([[sliceA, sliceB]]);
+ createMemoryTrack.call(this, model);
+ });
+
+ test('hasVisibleContent_trueWithThreadSlicePresent', function() {
+ const sliceA = new tr.model.ThreadSlice('lowmemory', title, 0, 5.5111, {});
+ const sliceB = new tr.model.ThreadSlice('lowmemory', title, 0, 11.2384, {});
+ const model = buildModel([[sliceA, sliceB]]);
+ const track = createMemoryTrack.call(this, model);
+
+ assert.isTrue(track.hasVisibleContent);
+ });
+
+ test('hasVisibleContent_falseWithUndefinedProcessModel', function() {
+ const track = createMemoryTrack.call(this, undefined);
+
+ assert.isFalse(track.hasVisibleContent);
+ });
+
+ test('hasVisibleContent_falseWithNoThreadSlice', function() {
+ const sliceA = new tr.model.ThreadSlice('', title, 0, 7.6211, {});
+ const model = buildModel([[sliceA]]);
+ const track = createMemoryTrack.call(this, model);
+
+ assert.isFalse(track.hasVisibleContent);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/model_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/model_track.html
new file mode 100644
index 00000000000..45404899b7c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/model_track.html
@@ -0,0 +1,534 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/ui/base/draw_helpers.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/alert_track.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/cpu_usage_track.html">
+<link rel="import" href="/tracing/ui/tracks/device_track.html">
+<link rel="import" href="/tracing/ui/tracks/global_memory_dump_track.html">
+<link rel="import" href="/tracing/ui/tracks/interaction_track.html">
+<link rel="import" href="/tracing/ui/tracks/kernel_track.html">
+<link rel="import" href="/tracing/ui/tracks/memory_track.html">
+<link rel="import" href="/tracing/ui/tracks/process_track.html">
+
+<style>
+.model-track {
+ flex-grow: 1;
+}
+</style>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const SelectionState = tr.model.SelectionState;
+ const ColorScheme = tr.b.ColorScheme;
+ const EventPresenter = tr.ui.b.EventPresenter;
+
+ /**
+ * Visualizes a Model by building ProcessTracks and CpuTracks.
+ * @constructor
+ */
+ const ModelTrack = tr.ui.b.define('model-track', tr.ui.tracks.ContainerTrack);
+
+ ModelTrack.VSYNC_HIGHLIGHT_ALPHA = 0.1;
+ ModelTrack.VSYNC_DENSITY_TRANSPARENT = 0.20;
+ ModelTrack.VSYNC_DENSITY_OPAQUE = 0.10;
+ ModelTrack.VSYNC_DENSITY_RANGE =
+ ModelTrack.VSYNC_DENSITY_TRANSPARENT - ModelTrack.VSYNC_DENSITY_OPAQUE;
+
+ /**
+ * Generate a zebra striping from a list of times.
+ *
+ * @param {!Array.<number>} times A sorted array of timestamps.
+ * @param {number} minTime the lower bound of time to start striping at.
+ * @param {number} maxTime the upper bound of time to stop striping at.
+ * of |times|.
+ *
+ * @returns {!Array.<tr.b.math.Range>} An array of ranges where each element
+ * represents the time range that a stripe covers. Each range is a subset
+ * of the interval [minTime, maxTime].
+ */
+ ModelTrack.generateStripes_ = function(times, minTime, maxTime) {
+ if (times.length === 0) return [];
+
+ // Find the lowest and highest index within the viewport.
+ const lowIndex = tr.b.findLowIndexInSortedArray(
+ times, (x => x), minTime);
+ let highIndex = lowIndex - 1;
+ while (times[highIndex + 1] <= maxTime) {
+ highIndex++;
+ }
+
+ const stripes = [];
+ // Must start at an even index and end at an odd index.
+ for (let i = lowIndex - (lowIndex % 2); i <= highIndex; i += 2) {
+ const left = i < lowIndex ? minTime : times[i];
+ const right = i + 1 > highIndex ? maxTime : times[i + 1];
+ stripes.push(tr.b.math.Range.fromExplicitRange(left, right));
+ }
+
+ return stripes;
+ };
+
+
+ ModelTrack.prototype = {
+
+ __proto__: tr.ui.tracks.ContainerTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('model-track');
+
+ this.upperMode_ = false;
+ this.annotationViews_ = [];
+ this.vSyncTimes_ = [];
+ },
+
+ get processViews() {
+ return Polymer.dom(this).querySelectorAll('.process-track-base');
+ },
+
+ // upperMode is true if the track is being used on the ruler.
+ get upperMode() {
+ return this.upperMode_;
+ },
+
+ set upperMode(upperMode) {
+ this.upperMode_ = upperMode;
+ this.updateContents_();
+ },
+
+ detach() {
+ tr.ui.tracks.ContainerTrack.prototype.detach.call(this);
+ },
+
+ get model() {
+ return this.model_;
+ },
+
+ set model(model) {
+ this.model_ = model;
+ this.updateContents_();
+
+ this.model_.addEventListener('annotationChange',
+ this.updateAnnotations_.bind(this));
+ },
+
+ get hasVisibleContent() {
+ return this.children.length > 0;
+ },
+
+ updateContents_() {
+ Polymer.dom(this).textContent = '';
+ if (!this.model_) return;
+
+ if (this.upperMode_) {
+ this.updateContentsForUpperMode_();
+ } else {
+ this.updateContentsForLowerMode_();
+ }
+ },
+
+ updateContentsForUpperMode_() {
+ },
+
+ updateContentsForLowerMode_() {
+ if (this.model_.userModel.expectations.length > 1) {
+ const mrt = new tr.ui.tracks.InteractionTrack(this.viewport_);
+ mrt.model = this.model_;
+ Polymer.dom(this).appendChild(mrt);
+ }
+
+ if (this.model_.alerts.length) {
+ const at = new tr.ui.tracks.AlertTrack(this.viewport_);
+ at.alerts = this.model_.alerts;
+ Polymer.dom(this).appendChild(at);
+ }
+
+ if (this.model_.globalMemoryDumps.length) {
+ const gmdt = new tr.ui.tracks.GlobalMemoryDumpTrack(this.viewport_);
+ gmdt.memoryDumps = this.model_.globalMemoryDumps;
+ Polymer.dom(this).appendChild(gmdt);
+ }
+
+ this.appendDeviceTrack_();
+ this.appendCpuUsageTrack_();
+ this.appendMemoryTrack_();
+ this.appendKernelTrack_();
+
+ // Get a sorted list of processes.
+ const processes = this.model_.getAllProcesses();
+ processes.sort(tr.model.Process.compare);
+
+ for (let i = 0; i < processes.length; ++i) {
+ const process = processes[i];
+
+ const track = new tr.ui.tracks.ProcessTrack(this.viewport);
+ track.process = process;
+ if (!track.hasVisibleContent) continue;
+
+ Polymer.dom(this).appendChild(track);
+ }
+ this.viewport_.rebuildEventToTrackMap();
+ this.viewport_.rebuildContainerToTrackMap();
+ this.vSyncTimes_ = this.model_.device.vSyncTimestamps;
+
+ this.updateAnnotations_();
+ },
+
+ getContentBounds() { return this.model.bounds; },
+
+ addAnnotation(annotation) {
+ this.model.addAnnotation(annotation);
+ },
+
+ removeAnnotation(annotation) {
+ this.model.removeAnnotation(annotation);
+ },
+
+ updateAnnotations_() {
+ this.annotationViews_ = [];
+ const annotations = this.model_.getAllAnnotations();
+ for (let i = 0; i < annotations.length; i++) {
+ this.annotationViews_.push(
+ annotations[i].getOrCreateView(this.viewport_));
+ }
+ this.invalidateDrawingContainer();
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ if (!this.model_) return;
+
+ const tracks = this.children;
+ for (let i = 0; i < tracks.length; ++i) {
+ tracks[i].addEventsToTrackMap(eventToTrackMap);
+ }
+
+ if (this.instantEvents === undefined) return;
+
+ const vp = this.viewport_;
+ this.instantEvents.forEach(function(ev) {
+ eventToTrackMap.addEvent(ev, this);
+ }.bind(this));
+ },
+
+ appendDeviceTrack_() {
+ const device = this.model.device;
+ const track = new tr.ui.tracks.DeviceTrack(this.viewport);
+ track.device = this.model.device;
+ if (!track.hasVisibleContent) return;
+ Polymer.dom(this).appendChild(track);
+ },
+
+ appendKernelTrack_() {
+ const kernel = this.model.kernel;
+ const track = new tr.ui.tracks.KernelTrack(this.viewport);
+ track.kernel = this.model.kernel;
+ if (!track.hasVisibleContent) return;
+ Polymer.dom(this).appendChild(track);
+ },
+
+ appendCpuUsageTrack_() {
+ const track = new tr.ui.tracks.CpuUsageTrack(this.viewport);
+ track.initialize(this.model);
+ if (!track.hasVisibleContent) return;
+
+ this.appendChild(track);
+ },
+
+ appendMemoryTrack_() {
+ const track = new tr.ui.tracks.MemoryTrack(this.viewport);
+ track.initialize(this.model);
+ if (!track.hasVisibleContent) return;
+
+ Polymer.dom(this).appendChild(track);
+ },
+
+ drawTrack(type) {
+ const ctx = this.context();
+ if (!this.model_) return;
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const bounds = this.getBoundingClientRect();
+ const canvasBounds = ctx.canvas.getBoundingClientRect();
+
+ ctx.save();
+ ctx.translate(0, pixelRatio * (bounds.top - canvasBounds.top));
+
+ const dt = this.viewport.currentDisplayTransform;
+ const viewLWorld = dt.xViewToWorld(0);
+ const viewRWorld = dt.xViewToWorld(canvasBounds.width * pixelRatio);
+ const viewHeight = bounds.height * pixelRatio;
+
+ switch (type) {
+ case tr.ui.tracks.DrawType.GRID:
+ this.viewport.drawMajorMarkLines(ctx, viewHeight);
+ // The model is the only thing that draws grid lines.
+ ctx.restore();
+ return;
+
+ case tr.ui.tracks.DrawType.FLOW_ARROWS:
+ if (this.model_.flowIntervalTree.size === 0) {
+ ctx.restore();
+ return;
+ }
+
+ this.drawFlowArrows_(viewLWorld, viewRWorld);
+ ctx.restore();
+ return;
+
+ case tr.ui.tracks.DrawType.INSTANT_EVENT:
+ if (!this.model_.instantEvents ||
+ this.model_.instantEvents.length === 0) {
+ break;
+ }
+
+ tr.ui.b.drawInstantSlicesAsLines(
+ ctx,
+ this.viewport.currentDisplayTransform,
+ viewLWorld,
+ viewRWorld,
+ bounds.height,
+ this.model_.instantEvents,
+ 4);
+
+ break;
+
+ case tr.ui.tracks.DrawType.MARKERS:
+ if (!this.viewport.interestRange.isEmpty) {
+ this.viewport.interestRange.draw(
+ ctx, viewLWorld, viewRWorld, viewHeight);
+ this.viewport.interestRange.drawIndicators(
+ ctx, viewLWorld, viewRWorld);
+ }
+ ctx.restore();
+ return;
+
+ case tr.ui.tracks.DrawType.HIGHLIGHTS:
+ this.drawVSyncHighlight(
+ ctx, dt, viewLWorld, viewRWorld, viewHeight);
+ ctx.restore();
+ return;
+
+ case tr.ui.tracks.DrawType.ANNOTATIONS:
+ for (let i = 0; i < this.annotationViews_.length; i++) {
+ this.annotationViews_[i].draw(ctx);
+ }
+ ctx.restore();
+ return;
+ }
+ ctx.restore();
+
+ tr.ui.tracks.ContainerTrack.prototype.drawTrack.call(this, type);
+ },
+
+ drawFlowArrows_(viewLWorld, viewRWorld) {
+ const ctx = this.context();
+
+ ctx.strokeStyle = 'rgba(0, 0, 0, 0.4)';
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
+ ctx.lineWidth = 1;
+
+ const events =
+ this.model_.flowIntervalTree.findIntersection(viewLWorld, viewRWorld);
+
+ // When not showing flow events, show only highlighted/selected ones.
+ const onlyHighlighted = !this.viewport.showFlowEvents;
+ const canvasBounds = ctx.canvas.getBoundingClientRect();
+ for (let i = 0; i < events.length; ++i) {
+ if (onlyHighlighted &&
+ events[i].selectionState !== SelectionState.SELECTED &&
+ events[i].selectionState !== SelectionState.HIGHLIGHTED) {
+ continue;
+ }
+ this.drawFlowArrow_(ctx, events[i], canvasBounds);
+ }
+ },
+
+ drawFlowArrow_(ctx, flowEvent, canvasBounds) {
+ const dt = this.viewport.currentDisplayTransform;
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ const startTrack = this.viewport.trackForEvent(flowEvent.startSlice);
+ const endTrack = this.viewport.trackForEvent(flowEvent.endSlice);
+
+ // TODO(nduca): Figure out how to draw flow arrows even when
+ // processes are collapsed, bug #931.
+ if (startTrack === undefined || endTrack === undefined) return;
+
+ const startBounds = startTrack.getBoundingClientRect();
+ const endBounds = endTrack.getBoundingClientRect();
+
+ if (flowEvent.selectionState === SelectionState.SELECTED) {
+ ctx.shadowBlur = 1;
+ ctx.shadowColor = 'red';
+ ctx.shadowOffsety = 2;
+ ctx.strokeStyle = tr.b.ColorScheme.colorsAsStrings[
+ tr.b.ColorScheme.getVariantColorId(
+ flowEvent.colorId,
+ tr.b.ColorScheme.properties.brightenedOffsets[0])];
+ } else if (flowEvent.selectionState === SelectionState.HIGHLIGHTED) {
+ ctx.shadowBlur = 1;
+ ctx.shadowColor = 'red';
+ ctx.shadowOffsety = 2;
+ ctx.strokeStyle = tr.b.ColorScheme.colorsAsStrings[
+ tr.b.ColorScheme.getVariantColorId(
+ flowEvent.colorId,
+ tr.b.ColorScheme.properties.brightenedOffsets[0])];
+ } else if (flowEvent.selectionState === SelectionState.DIMMED) {
+ ctx.shadowBlur = 0;
+ ctx.shadowOffsetX = 0;
+ ctx.strokeStyle = tr.b.ColorScheme.colorsAsStrings[flowEvent.colorId];
+ } else {
+ let hasBoost = false;
+ const startSlice = flowEvent.startSlice;
+ hasBoost |= startSlice.selectionState === SelectionState.SELECTED;
+ hasBoost |= startSlice.selectionState === SelectionState.HIGHLIGHTED;
+ const endSlice = flowEvent.endSlice;
+ hasBoost |= endSlice.selectionState === SelectionState.SELECTED;
+ hasBoost |= endSlice.selectionState === SelectionState.HIGHLIGHTED;
+ if (hasBoost) {
+ ctx.shadowBlur = 1;
+ ctx.shadowColor = 'rgba(255, 0, 0, 0.4)';
+ ctx.shadowOffsety = 2;
+ ctx.strokeStyle = tr.b.ColorScheme.colorsAsStrings[
+ tr.b.ColorScheme.getVariantColorId(
+ flowEvent.colorId,
+ tr.b.ColorScheme.properties.brightenedOffsets[0])];
+ } else {
+ ctx.shadowBlur = 0;
+ ctx.shadowOffsetX = 0;
+ ctx.strokeStyle = tr.b.ColorScheme.colorsAsStrings[flowEvent.colorId];
+ }
+ }
+
+ const startSize = startBounds.left + startBounds.top +
+ startBounds.bottom + startBounds.right;
+ const endSize = endBounds.left + endBounds.top +
+ endBounds.bottom + endBounds.right;
+ // Nothing to do if both ends of the track are collapsed.
+ if (startSize === 0 && endSize === 0) return;
+
+ const startY = this.calculateTrackY_(startTrack, canvasBounds);
+ const endY = this.calculateTrackY_(endTrack, canvasBounds);
+
+ const pixelStartY = pixelRatio * startY;
+ const pixelEndY = pixelRatio * endY;
+
+ const startXView = dt.xWorldToView(flowEvent.start);
+ const endXView = dt.xWorldToView(flowEvent.end);
+ const midXView = (startXView + endXView) / 2;
+
+ ctx.beginPath();
+ ctx.moveTo(startXView, pixelStartY);
+ ctx.bezierCurveTo(
+ midXView, pixelStartY,
+ midXView, pixelEndY,
+ endXView, pixelEndY);
+ ctx.stroke();
+
+ const arrowWidth = 5 * pixelRatio;
+ const distance = endXView - startXView;
+ if (distance <= (2 * arrowWidth)) return;
+
+ const tipX = endXView;
+ const tipY = pixelEndY;
+ const arrowHeight = (endBounds.height / 4) * pixelRatio;
+ tr.ui.b.drawTriangle(ctx,
+ tipX, tipY,
+ tipX - arrowWidth, tipY - arrowHeight,
+ tipX - arrowWidth, tipY + arrowHeight);
+ ctx.fill();
+ },
+
+ /**
+ * Highlights VSync events on the model track (using "zebra" striping).
+ */
+ drawVSyncHighlight(ctx, dt, viewLWorld, viewRWorld, viewHeight) {
+ if (!this.viewport_.highlightVSync) {
+ return;
+ }
+
+ const stripes = ModelTrack.generateStripes_(
+ this.vSyncTimes_, viewLWorld, viewRWorld);
+ if (stripes.length === 0) {
+ return;
+ }
+
+ const vSyncHighlightColor =
+ new tr.b.Color(ColorScheme.getColorForReservedNameAsString(
+ 'vsync_highlight_color'));
+
+ const stripeRange = stripes[stripes.length - 1].max - stripes[0].min;
+ const stripeDensity =
+ stripeRange ? stripes.length / (dt.scaleX * stripeRange) : 0;
+ const clampedStripeDensity =
+ tr.b.math.clamp(stripeDensity, ModelTrack.VSYNC_DENSITY_OPAQUE,
+ ModelTrack.VSYNC_DENSITY_TRANSPARENT);
+ const opacity =
+ (ModelTrack.VSYNC_DENSITY_TRANSPARENT - clampedStripeDensity) /
+ ModelTrack.VSYNC_DENSITY_RANGE;
+ if (opacity === 0) {
+ return;
+ }
+
+ ctx.fillStyle = vSyncHighlightColor.toStringWithAlphaOverride(
+ ModelTrack.VSYNC_HIGHLIGHT_ALPHA * opacity);
+
+ for (let i = 0; i < stripes.length; i++) {
+ const xLeftView = dt.xWorldToView(stripes[i].min);
+ const xRightView = dt.xWorldToView(stripes[i].max);
+ ctx.fillRect(xLeftView, 0, xRightView - xLeftView, viewHeight);
+ }
+ },
+
+ calculateTrackY_(track, canvasBounds) {
+ const bounds = track.getBoundingClientRect();
+ const size = bounds.left + bounds.top + bounds.bottom + bounds.right;
+ if (size === 0) {
+ return this.calculateTrackY_(
+ Polymer.dom(track).parentNode, canvasBounds);
+ }
+
+ return bounds.top - canvasBounds.top + (bounds.height / 2);
+ },
+
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ function onPickHit(instantEvent) {
+ selection.push(instantEvent);
+ }
+ const instantEventWidth = 3 * viewPixWidthWorld;
+ tr.b.iterateOverIntersectingIntervals(this.model_.instantEvents,
+ function(x) { return x.start; },
+ function(x) { return x.duration + instantEventWidth; },
+ loWX, hiWX,
+ onPickHit.bind(this));
+
+ tr.ui.tracks.ContainerTrack.prototype.
+ addIntersectingEventsInRangeToSelectionInWorldSpace.
+ apply(this, arguments);
+ },
+
+ addClosestEventToSelection(worldX, worldMaxDist, loY, hiY,
+ selection) {
+ this.addClosestInstantEventToSelection(this.model_.instantEvents,
+ worldX, worldMaxDist, selection);
+ tr.ui.tracks.ContainerTrack.prototype.addClosestEventToSelection.
+ apply(this, arguments);
+ }
+ };
+
+ return {
+ ModelTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/model_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/model_track_test.html
new file mode 100644
index 00000000000..53e19146ae2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/model_track_test.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/thread.html">
+<link rel="import" href="/tracing/ui/tracks/model_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Range = tr.b.math.Range;
+ const VIEW_L_WORLD = 100;
+ const VIEW_R_WORLD = 1000;
+
+ function testGenerateStripes(times, expectedRanges) {
+ const ranges = tr.ui.tracks.ModelTrack.generateStripes_(
+ times, VIEW_L_WORLD, VIEW_R_WORLD);
+
+ assert.sameDeepMembers(ranges, expectedRanges);
+ }
+
+ test('generateStripesInside', function() {
+ const range200To500 = Range.fromExplicitRange(200, 500);
+ const range800To900 = Range.fromExplicitRange(800, 900);
+ const range998To999 = Range.fromExplicitRange(998, 999);
+ testGenerateStripes([], []);
+ testGenerateStripes([200, 500], [range200To500]);
+ testGenerateStripes([200, 500, 800, 900], [range200To500, range800To900]);
+ testGenerateStripes(
+ [200, 500, 800, 900, 998, 999],
+ [range200To500, range800To900, range998To999]);
+ });
+
+ test('generateStripesOutside', function() {
+ const range101To999 = Range.fromExplicitRange(101, 999);
+ // Far left.
+ testGenerateStripes([0, 99], []);
+ testGenerateStripes([0, 10, 50, 99], []);
+ testGenerateStripes([0, 99, 101, 999], [range101To999]);
+ testGenerateStripes([0, 10, 50, 99, 101, 999], [range101To999]);
+
+ // Far right.
+ testGenerateStripes([1001, 2000], []);
+ testGenerateStripes([1001, 2000, 3000, 4000], []);
+ testGenerateStripes([101, 999, 1001, 2000], [range101To999]);
+ testGenerateStripes([101, 999, 1001, 2000, 3000, 4000], [range101To999]);
+
+ // Far both.
+ testGenerateStripes([0, 99, 1001, 2000], []);
+ testGenerateStripes([0, 10, 50, 99, 1001, 2000], []);
+ testGenerateStripes([0, 10, 50, 99, 1001, 2000, 3000, 4000], []);
+ testGenerateStripes([0, 99, 101, 999, 1001, 2000], [range101To999]);
+ });
+
+ test('generateStripesOverlap', function() {
+ const rangeLeftWorldTo101 = Range.fromExplicitRange(VIEW_L_WORLD, 101);
+ const range102To103 = Range.fromExplicitRange(102, 103);
+ const range200To900 = Range.fromExplicitRange(200, 900);
+ const range997To998 = Range.fromExplicitRange(997, 998);
+ const range999ToRightWorld = Range.fromExplicitRange(999, VIEW_R_WORLD);
+ const rangeLeftWorldToRightWorld =
+ Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
+
+
+ // Left overlap.
+ testGenerateStripes([0, 101], [rangeLeftWorldTo101]);
+ testGenerateStripes([0, 1, 2, 101], [rangeLeftWorldTo101]);
+ testGenerateStripes(
+ [2, 101, 102, 103],
+ [rangeLeftWorldTo101, range102To103]);
+ testGenerateStripes(
+ [0, 1, 2, 101, 102, 103],
+ [rangeLeftWorldTo101, range102To103]);
+ testGenerateStripes(
+ [0, 1, 2, 101, 102, 103, 1001, 3000],
+ [rangeLeftWorldTo101, range102To103]);
+
+ // Right overlap.
+ testGenerateStripes([999, 2000], [range999ToRightWorld]);
+ testGenerateStripes([999, 2000, 3000, 4000], [range999ToRightWorld]);
+ testGenerateStripes(
+ [997, 998, 999, 2000],
+ [range997To998, range999ToRightWorld]);
+ testGenerateStripes(
+ [997, 998, 999, 2000, 3000, 4000],
+ [range997To998, range999ToRightWorld]);
+ testGenerateStripes(
+ [0, 10, 997, 998, 999, 2000, 3000, 4000],
+ [range997To998, range999ToRightWorld]);
+
+ // Both overlap.
+ testGenerateStripes([0, 2000], [rangeLeftWorldToRightWorld]);
+ testGenerateStripes(
+ [0, 101, 999, 2000],
+ [rangeLeftWorldTo101, range999ToRightWorld]);
+ testGenerateStripes(
+ [0, 101, 200, 900, 999, 2000],
+ [rangeLeftWorldTo101, range200To900, range999ToRightWorld]);
+ testGenerateStripes(
+ [0, 10, 90, 101, 999, 2000, 3000, 4000],
+ [rangeLeftWorldTo101, range999ToRightWorld]);
+ testGenerateStripes(
+ [0, 10, 90, 101, 200, 900, 999, 2000, 3000, 4000],
+ [rangeLeftWorldTo101, range200To900, range999ToRightWorld]);
+ });
+
+ test('generateStripesOdd', function() {
+ const range500To900 = Range.fromExplicitRange(500, 900);
+ const rangeLeftWorldTo200 = Range.fromExplicitRange(VIEW_L_WORLD, 200);
+ const rangeLeftWorldTo500 = Range.fromExplicitRange(VIEW_L_WORLD, 500);
+ const range500ToRightWorld = Range.fromExplicitRange(500, VIEW_R_WORLD);
+ const rangeLeftWorldToRightWorld =
+ Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
+
+ // One VSync.
+ testGenerateStripes([0], [rangeLeftWorldToRightWorld]);
+ testGenerateStripes([500], [range500ToRightWorld]);
+ testGenerateStripes([1500], []);
+
+ // Multiple VSyncs.
+ testGenerateStripes([0, 10, 20], [rangeLeftWorldToRightWorld]);
+ testGenerateStripes([0, 500, 2000], [rangeLeftWorldTo500]);
+ testGenerateStripes([0, 10, 500], [range500ToRightWorld]);
+ testGenerateStripes([0, 10, 2000], []);
+ testGenerateStripes(
+ [0, 200, 500],
+ [rangeLeftWorldTo200, range500ToRightWorld]);
+ testGenerateStripes(
+ [0, 200, 500, 900],
+ [rangeLeftWorldTo200, range500To900]);
+ });
+
+ test('generateStripesBorder', function() {
+ const rangeLeftWorldToLeftWorld =
+ Range.fromExplicitRange(VIEW_L_WORLD, VIEW_L_WORLD);
+ const rangeRightWorldToRightWorld =
+ Range.fromExplicitRange(VIEW_R_WORLD, VIEW_R_WORLD);
+ const rangeLeftWorldToRightWorld =
+ Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
+ const rangeLeftWorldTo200 = Range.fromExplicitRange(VIEW_L_WORLD, 200);
+ const range200To500 = Range.fromExplicitRange(200, 500);
+ const range500ToRightWorld = Range.fromExplicitRange(500, VIEW_R_WORLD);
+ testGenerateStripes([0, VIEW_L_WORLD], [rangeLeftWorldToLeftWorld]);
+ testGenerateStripes(
+ [VIEW_L_WORLD, VIEW_L_WORLD],
+ [rangeLeftWorldToLeftWorld]);
+ testGenerateStripes(
+ [VIEW_R_WORLD, 2000],
+ [rangeRightWorldToRightWorld]);
+ testGenerateStripes(
+ [VIEW_R_WORLD, VIEW_R_WORLD],
+ [rangeRightWorldToRightWorld]);
+ testGenerateStripes(
+ [VIEW_L_WORLD, VIEW_R_WORLD],
+ [rangeLeftWorldToRightWorld]);
+ testGenerateStripes(
+ [VIEW_L_WORLD, 200, 500, VIEW_R_WORLD],
+ [rangeLeftWorldTo200, range500ToRightWorld]);
+ testGenerateStripes(
+ [0, VIEW_L_WORLD, VIEW_R_WORLD, 2000],
+ [rangeLeftWorldToLeftWorld, rangeRightWorldToRightWorld]);
+ testGenerateStripes(
+ [0, VIEW_L_WORLD, VIEW_R_WORLD, 2000],
+ [rangeLeftWorldToLeftWorld, rangeRightWorldToRightWorld]);
+ testGenerateStripes(
+ [0, VIEW_L_WORLD, 200, 500, VIEW_R_WORLD, 2000],
+ [rangeLeftWorldToLeftWorld, range200To500,
+ rangeRightWorldToRightWorld]);
+ testGenerateStripes(
+ [0, 10, VIEW_L_WORLD, VIEW_R_WORLD, 2000, 3000],
+ [rangeLeftWorldToRightWorld]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/multi_row_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/multi_row_track.html
new file mode 100644
index 00000000000..8b5fd837f0d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/multi_row_track.html
@@ -0,0 +1,240 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/model_settings.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays a group of objects in multiple rows.
+ * @constructor
+ * @extends {ContainerTrack}
+ */
+ const MultiRowTrack = tr.ui.b.define(
+ 'multi-row-track', tr.ui.tracks.ContainerTrack);
+
+ MultiRowTrack.prototype = {
+
+ __proto__: tr.ui.tracks.ContainerTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+ this.tooltip_ = '';
+ this.heading_ = '';
+
+ this.groupingSource_ = undefined;
+ this.itemsToGroup_ = undefined;
+
+ this.defaultToCollapsedWhenSubRowCountMoreThan = 1;
+
+ this.currentSubRowsWithHeadings_ = undefined;
+ this.expanded_ = true;
+ },
+
+ get itemsToGroup() {
+ return this.itemsToGroup_;
+ },
+
+ setItemsToGroup(itemsToGroup, opt_groupingSource) {
+ this.itemsToGroup_ = itemsToGroup;
+ this.groupingSource_ = opt_groupingSource;
+ this.currentSubRowsWithHeadings_ = undefined;
+ this.updateContents_();
+ this.updateExpandedStateFromGroupingSource_();
+ },
+
+ /**
+ * Opt-out from using buildSubRows_() and provide prebuilt rows.
+ * Array of {row: [rowItems...], heading} dicts is expected as an argument.
+ */
+ setPrebuiltSubRows(groupingSource, subRowsWithHeadings) {
+ this.itemsToGroup_ = undefined;
+ this.groupingSource_ = groupingSource;
+ this.currentSubRowsWithHeadings_ = subRowsWithHeadings;
+ this.updateContents_();
+ this.updateExpandedStateFromGroupingSource_();
+ },
+
+ get heading() {
+ return this.heading_;
+ },
+
+ set heading(h) {
+ this.heading_ = h;
+ this.updateHeadingAndTooltip_();
+ },
+
+ get tooltip() {
+ return this.tooltip_;
+ },
+
+ set tooltip(t) {
+ this.tooltip_ = t;
+ this.updateHeadingAndTooltip_();
+ },
+
+ get subRows() {
+ return this.currentSubRowsWithHeadings_.map(elem => elem.row);
+ },
+
+ get hasVisibleContent() {
+ return this.children.length > 0;
+ },
+
+ get expanded() {
+ return this.expanded_;
+ },
+
+ set expanded(expanded) {
+ if (this.expanded_ === expanded) return;
+
+ this.expanded_ = expanded;
+ this.expandedStateChanged_();
+ },
+
+ onHeadingClicked_(e) {
+ if (this.subRows.length <= 1) return;
+
+ this.expanded = !this.expanded;
+
+ if (this.groupingSource_) {
+ const modelSettings = new tr.model.ModelSettings(
+ this.groupingSource_.model);
+ modelSettings.setSettingFor(this.groupingSource_, 'expanded',
+ this.expanded);
+ }
+
+ e.stopPropagation();
+ },
+
+ updateExpandedStateFromGroupingSource_() {
+ if (this.groupingSource_) {
+ const numSubRows = this.subRows.length;
+ const modelSettings = new tr.model.ModelSettings(
+ this.groupingSource_.model);
+ if (numSubRows > 1) {
+ let defaultExpanded;
+ if (numSubRows > this.defaultToCollapsedWhenSubRowCountMoreThan) {
+ defaultExpanded = false;
+ } else {
+ defaultExpanded = true;
+ }
+ this.expanded = modelSettings.getSettingFor(
+ this.groupingSource_, 'expanded', defaultExpanded);
+ } else {
+ this.expanded = undefined;
+ }
+ }
+ },
+
+ expandedStateChanged_() {
+ const minH = Math.max(2, Math.ceil(18 / this.children.length));
+ const h = (this.expanded_ ? 18 : minH) + 'px';
+
+ for (let i = 0; i < this.children.length; i++) {
+ this.children[i].height = h;
+ if (i === 0) {
+ this.children[i].arrowVisible = true;
+ }
+ this.children[i].expanded = this.expanded;
+ }
+
+ if (this.children.length === 1) {
+ this.children[0].expanded = true;
+ this.children[0].arrowVisible = false;
+ }
+ },
+
+ updateContents_() {
+ tr.ui.tracks.ContainerTrack.prototype.updateContents_.call(this);
+ this.detach(); // Clear sub-tracks.
+
+ if (this.currentSubRowsWithHeadings_ === undefined) {
+ // No prebuilt rows, build it.
+ if (this.itemsToGroup_ === undefined) {
+ return;
+ }
+ const subRows = this.buildSubRows_(this.itemsToGroup_);
+ this.currentSubRowsWithHeadings_ = subRows.map(row => {
+ return {row, heading: undefined};
+ });
+ }
+ if (this.currentSubRowsWithHeadings_ === undefined ||
+ this.currentSubRowsWithHeadings_.length === 0) {
+ return;
+ }
+
+ const addSubTrackEx = (items, opt_heading) => {
+ const track = this.addSubTrack_(items);
+ if (opt_heading !== undefined) {
+ track.heading = opt_heading;
+ }
+ track.addEventListener(
+ 'heading-clicked', this.onHeadingClicked_.bind(this));
+ };
+
+ if (this.currentSubRowsWithHeadings_[0].heading !== undefined &&
+ this.currentSubRowsWithHeadings_[0].heading !== this.heading_) {
+ // Create an empty row to render the group's title there.
+ addSubTrackEx([]);
+ }
+
+ for (const subRowWithHeading of this.currentSubRowsWithHeadings_) {
+ const subRow = subRowWithHeading.row;
+ if (subRow.length === 0) {
+ continue;
+ }
+ addSubTrackEx(subRow, subRowWithHeading.heading);
+ }
+
+ this.updateHeadingAndTooltip_();
+ this.expandedStateChanged_();
+ },
+
+ updateHeadingAndTooltip_() {
+ if (!Polymer.dom(this).firstChild) return;
+
+ Polymer.dom(this).firstChild.heading = this.heading_;
+ Polymer.dom(this).firstChild.tooltip = this.tooltip_;
+ },
+
+ /**
+ * Breaks up the list of slices into N rows, each of which is a list of
+ * slices that are non overlapping.
+ */
+ buildSubRows_(itemsToGroup) {
+ throw new Error('Not implemented');
+ },
+
+ addSubTrack_(subRowItems) {
+ throw new Error('Not implemented');
+ },
+
+ areArrayContentsSame_(a, b) {
+ if (!a || !b) return false;
+
+ if (!a.length || !b.length) return false;
+
+ if (a.length !== b.length) return false;
+
+ for (let i = 0; i < a.length; ++i) {
+ if (a[i] !== b[i]) return false;
+ }
+ return true;
+ }
+ };
+
+ return {
+ MultiRowTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_group_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_group_track.html
new file mode 100644
index 00000000000..b97b48c3ef0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_group_track.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/object_instance_view.html">
+<link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/multi_row_track.html">
+<link rel="import" href="/tracing/ui/tracks/object_instance_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays a ObjectInstanceGroup.
+ * @constructor
+ * @extends {ContainerTrack}
+ */
+ const ObjectInstanceGroupTrack = tr.ui.b.define(
+ 'object-instance-group-track', tr.ui.tracks.MultiRowTrack);
+
+ ObjectInstanceGroupTrack.prototype = {
+
+ __proto__: tr.ui.tracks.MultiRowTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('object-instance-group-track');
+ this.objectInstances_ = undefined;
+ },
+
+ get objectInstances() {
+ return this.itemsToGroup;
+ },
+
+ set objectInstances(objectInstances) {
+ this.setItemsToGroup(objectInstances);
+ },
+
+ addSubTrack_(objectInstances) {
+ const hasMultipleRows = this.subRows.length > 1;
+ const track = new tr.ui.tracks.ObjectInstanceTrack(this.viewport);
+ track.objectInstances = objectInstances;
+ Polymer.dom(this).appendChild(track);
+ return track;
+ },
+
+ buildSubRows_(objectInstances) {
+ objectInstances.sort(function(x, y) {
+ return x.creationTs - y.creationTs;
+ });
+
+ const subRows = [];
+ for (let i = 0; i < objectInstances.length; i++) {
+ const objectInstance = objectInstances[i];
+
+ let found = false;
+ for (let j = 0; j < subRows.length; j++) {
+ const subRow = subRows[j];
+ const lastItemInSubRow = subRow[subRow.length - 1];
+ if (objectInstance.creationTs >= lastItemInSubRow.deletionTs) {
+ found = true;
+ subRow.push(objectInstance);
+ break;
+ }
+ }
+ if (!found) {
+ subRows.push([objectInstance]);
+ }
+ }
+ return subRows;
+ },
+ updateHeadingAndTooltip_() {
+ }
+ };
+
+ return {
+ ObjectInstanceGroupTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track.css b/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track.css
new file mode 100644
index 00000000000..0919e85524e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track.css
@@ -0,0 +1,8 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.object-instance-track {
+ height: 18px;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track.html
new file mode 100644
index 00000000000..f21a87d04db
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track.html
@@ -0,0 +1,294 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet" href="/tracing/ui/tracks/object_instance_track.css">
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/event.html">
+<link rel="import" href="/tracing/ui/base/event_presenter.html">
+<link rel="import" href="/tracing/ui/base/heading.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const SelectionState = tr.model.SelectionState;
+ const EventPresenter = tr.ui.b.EventPresenter;
+
+ /**
+ * A track that displays an array of Slice objects.
+ * @constructor
+ * @extends {Track}
+ */
+ const ObjectInstanceTrack = tr.ui.b.define(
+ 'object-instance-track', tr.ui.tracks.Track);
+
+ ObjectInstanceTrack.prototype = {
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('object-instance-track');
+ this.objectInstances_ = [];
+ this.objectSnapshots_ = [];
+
+ this.heading_ = document.createElement('tr-ui-b-heading');
+ Polymer.dom(this).appendChild(this.heading_);
+ },
+
+ set heading(heading) {
+ this.heading_.heading = heading;
+ },
+
+ get heading() {
+ return this.heading_.heading;
+ },
+
+ set tooltip(tooltip) {
+ this.heading_.tooltip = tooltip;
+ },
+
+ get objectInstances() {
+ return this.objectInstances_;
+ },
+
+ set objectInstances(objectInstances) {
+ if (!objectInstances || objectInstances.length === 0) {
+ this.heading = '';
+ this.objectInstances_ = [];
+ this.objectSnapshots_ = [];
+ return;
+ }
+ this.heading = objectInstances[0].baseTypeName;
+ this.objectInstances_ = objectInstances;
+ this.objectSnapshots_ = [];
+ this.objectInstances_.forEach(function(instance) {
+ this.objectSnapshots_.push.apply(
+ this.objectSnapshots_, instance.snapshots);
+ }, this);
+ this.objectSnapshots_.sort(function(a, b) {
+ return a.ts - b.ts;
+ });
+ },
+
+ get height() {
+ return window.getComputedStyle(this).height;
+ },
+
+ set height(height) {
+ this.style.height = height;
+ },
+
+ get snapshotRadiusView() {
+ return 7 * (window.devicePixelRatio || 1);
+ },
+
+ draw(type, viewLWorld, viewRWorld, viewHeight) {
+ switch (type) {
+ case tr.ui.tracks.DrawType.GENERAL_EVENT:
+ this.drawObjectInstances_(viewLWorld, viewRWorld);
+ break;
+ }
+ },
+
+ drawObjectInstances_(viewLWorld, viewRWorld) {
+ const ctx = this.context();
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ const bounds = this.getBoundingClientRect();
+ const height = bounds.height * pixelRatio;
+ const halfHeight = height * 0.5;
+ const twoPi = Math.PI * 2;
+
+ // Culling parameters.
+ const dt = this.viewport.currentDisplayTransform;
+ const snapshotRadiusView = this.snapshotRadiusView;
+ const snapshotRadiusWorld = dt.xViewVectorToWorld(height);
+
+ // Instances
+ const objectInstances = this.objectInstances_;
+ let loI = tr.b.findLowIndexInSortedArray(
+ objectInstances,
+ function(instance) {
+ return instance.deletionTs;
+ },
+ viewLWorld);
+ ctx.save();
+ ctx.strokeStyle = 'rgb(0,0,0)';
+ for (let i = loI; i < objectInstances.length; ++i) {
+ const instance = objectInstances[i];
+ const x = instance.creationTs;
+ if (x > viewRWorld) break;
+
+ const right = instance.deletionTs === Number.MAX_VALUE ?
+ viewRWorld : instance.deletionTs;
+ const xView = dt.xWorldToView(x);
+ const widthView = dt.xWorldVectorToView(right - x);
+ ctx.fillStyle = EventPresenter.getObjectInstanceColor(instance);
+ ctx.fillRect(xView, pixelRatio, widthView, height - 2 * pixelRatio);
+ }
+ ctx.restore();
+
+ // Snapshots. Has to run in worldspace because ctx.arc gets transformed.
+ const objectSnapshots = this.objectSnapshots_;
+ loI = tr.b.findLowIndexInSortedArray(
+ objectSnapshots,
+ function(snapshot) {
+ return snapshot.ts + snapshotRadiusWorld;
+ },
+ viewLWorld);
+ for (let i = loI; i < objectSnapshots.length; ++i) {
+ const snapshot = objectSnapshots[i];
+ const x = snapshot.ts;
+ if (x - snapshotRadiusWorld > viewRWorld) break;
+
+ const xView = dt.xWorldToView(x);
+
+ ctx.fillStyle = EventPresenter.getObjectSnapshotColor(snapshot);
+ ctx.beginPath();
+ ctx.arc(xView, halfHeight, snapshotRadiusView, 0, twoPi);
+ ctx.fill();
+ if (snapshot.selected) {
+ ctx.lineWidth = 5;
+ ctx.strokeStyle = 'rgb(100,100,0)';
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.arc(xView, halfHeight, snapshotRadiusView - 1, 0, twoPi);
+ ctx.lineWidth = 2;
+ ctx.strokeStyle = 'rgb(255,255,0)';
+ ctx.stroke();
+ } else {
+ ctx.lineWidth = 1;
+ ctx.strokeStyle = 'rgb(0,0,0)';
+ ctx.stroke();
+ }
+ }
+ ctx.lineWidth = 1;
+
+ // For performance reasons we only check the SelectionState of the first
+ // instance. If it's DIMMED we assume that all are DIMMED.
+ // TODO(egraether): Allow partial highlight.
+ let selectionState = SelectionState.NONE;
+ if (objectInstances.length &&
+ objectInstances[0].selectionState === SelectionState.DIMMED) {
+ selectionState = SelectionState.DIMMED;
+ }
+
+ // Dim the track when there is an active highlight.
+ if (selectionState === SelectionState.DIMMED) {
+ const width = bounds.width * pixelRatio;
+ ctx.fillStyle = 'rgba(255,255,255,0.5)';
+ ctx.fillRect(0, 0, width, height);
+ ctx.restore();
+ }
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ if (this.objectInstance_ !== undefined) {
+ this.objectInstance_.forEach(function(obj) {
+ eventToTrackMap.addEvent(obj, this);
+ }, this);
+ }
+
+ if (this.objectSnapshots_ !== undefined) {
+ this.objectSnapshots_.forEach(function(obj) {
+ eventToTrackMap.addEvent(obj, this);
+ }, this);
+ }
+ },
+
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ // Pick snapshots first.
+ let foundSnapshot = false;
+ function onSnapshot(snapshot) {
+ selection.push(snapshot);
+ foundSnapshot = true;
+ }
+ const snapshotRadiusView = this.snapshotRadiusView;
+ const snapshotRadiusWorld = viewPixWidthWorld * snapshotRadiusView;
+ tr.b.iterateOverIntersectingIntervals(
+ this.objectSnapshots_,
+ function(x) { return x.ts - snapshotRadiusWorld; },
+ function(x) { return 2 * snapshotRadiusWorld; },
+ loWX, hiWX,
+ onSnapshot);
+ if (foundSnapshot) return;
+
+ // Try picking instances.
+ tr.b.iterateOverIntersectingIntervals(
+ this.objectInstances_,
+ function(x) { return x.creationTs; },
+ function(x) { return x.deletionTs - x.creationTs; },
+ loWX, hiWX,
+ (value) => { selection.push(value); });
+ },
+
+ /**
+ * Add the item to the left or right of the provided event, if any, to the
+ * selection.
+ * @param {event} The current event item.
+ * @param {Number} offset Number of slices away from the event to look.
+ * @param {Selection} selection The selection to add an event to,
+ * if found.
+ * @return {boolean} Whether an event was found.
+ * @private
+ */
+ addEventNearToProvidedEventToSelection(event, offset, selection) {
+ let events;
+ if (event instanceof tr.model.ObjectSnapshot) {
+ events = this.objectSnapshots_;
+ } else if (event instanceof tr.model.ObjectInstance) {
+ events = this.objectInstances_;
+ } else {
+ throw new Error('Unrecognized event');
+ }
+
+ const index = events.indexOf(event);
+ const newIndex = index + offset;
+ if (newIndex >= 0 && newIndex < events.length) {
+ selection.push(events[newIndex]);
+ return true;
+ }
+ return false;
+ },
+
+ addAllEventsMatchingFilterToSelection(filter, selection) {
+ },
+
+ addClosestEventToSelection(worldX, worldMaxDist, loY, hiY,
+ selection) {
+ const snapshot = tr.b.findClosestElementInSortedArray(
+ this.objectSnapshots_,
+ function(x) { return x.ts; },
+ worldX,
+ worldMaxDist);
+
+ if (!snapshot) return;
+
+ selection.push(snapshot);
+
+ // TODO(egraether): Search for object instances as well, which was not
+ // implemented because it makes little sense with the current visual and
+ // needs to take care of overlapping intervals.
+ }
+ };
+
+
+ const options = new tr.b.ExtensionRegistryOptions(
+ tr.b.TYPE_BASED_REGISTRY_MODE);
+ tr.b.decorateExtensionRegistry(ObjectInstanceTrack, options);
+
+ return {
+ ObjectInstanceTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track_test.html
new file mode 100644
index 00000000000..8312d0ba7e5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/object_instance_track_test.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/object_collection.html">
+<link rel="import" href="/tracing/model/scoped_id.html">
+<link rel="import" href="/tracing/model/selection_state.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/object_instance_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventSet = tr.model.EventSet;
+ const ObjectInstanceTrack = tr.ui.tracks.ObjectInstanceTrack;
+ const Viewport = tr.ui.TimelineViewport;
+
+ const createObjects = function() {
+ const objects = new tr.model.ObjectCollection({});
+ const scopedId1 = new tr.model.ScopedId('ptr', '0x1000');
+ objects.idWasCreated(scopedId1, 'tr.e.cc', 'Frame', 10);
+ objects.addSnapshot(scopedId1, 'tr.e.cc', 'Frame', 10, 'snapshot-1');
+ objects.addSnapshot(scopedId1, 'tr.e.cc', 'Frame', 25, 'snapshot-2');
+ objects.addSnapshot(scopedId1, 'tr.e.cc', 'Frame', 40, 'snapshot-3');
+ objects.idWasDeleted(scopedId1, 'tr.e.cc', 'Frame', 45);
+
+ const scopedId2 = new tr.model.ScopedId('ptr', '0x1001');
+ objects.idWasCreated(scopedId2, 'skia', 'Picture', 20);
+ objects.addSnapshot(scopedId2, 'skia', 'Picture', 20, 'snapshot-1');
+ objects.idWasDeleted(scopedId2, 'skia', 'Picture', 25);
+ return objects;
+ };
+
+ test('instantiate', function() {
+ const objects = createObjects();
+ const frames = objects.getAllInstancesByTypeName().Frame;
+ frames[0].snapshots[1].selectionState =
+ tr.model.SelectionState.SELECTED;
+
+ const div = document.createElement('div');
+
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = ObjectInstanceTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.heading = 'testBasic';
+ track.objectInstances = frames;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 50, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ test('selectionHitTestingWithThreadTrack', function() {
+ const objects = createObjects();
+ const frames = objects.getAllInstancesByTypeName().Frame;
+
+ const track = ObjectInstanceTrack(new Viewport());
+ track.objectInstances = frames;
+
+ // Hit outside range
+ let selection = new EventSet();
+ track.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ 8, 8.1, 0.1, selection);
+ assert.strictEqual(selection.length, 0);
+
+ // Hit the first snapshot, via pixel-nearness.
+ selection = new EventSet();
+ track.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ 9.98, 9.99, 0.1, selection);
+ assert.strictEqual(selection.length, 1);
+ assert.instanceOf(tr.b.getOnlyElement(selection), tr.model.ObjectSnapshot);
+
+ // Hit the instance, between the 1st and 2nd snapshots
+ selection = new EventSet();
+ track.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ 20, 20.1, 0.1, selection);
+ assert.strictEqual(selection.length, 1);
+ assert.instanceOf(tr.b.getOnlyElement(selection), tr.model.ObjectInstance);
+ });
+
+ test('addEventNearToProvidedEventToSelection', function() {
+ const objects = createObjects();
+ const frames = objects.getAllInstancesByTypeName().Frame;
+
+ const track = ObjectInstanceTrack(new Viewport());
+ track.objectInstances = frames;
+
+ const instance = new tr.model.ObjectInstance(
+ {}, new tr.model.ScopedId('ptr', '0x1000'), 'cat', 'n', 10);
+
+ assert.doesNotThrow(function() {
+ track.addEventNearToProvidedEventToSelection(instance, 0, undefined);
+ });
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/other_threads_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/other_threads_track.html
new file mode 100644
index 00000000000..e43bce0cec2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/other_threads_track.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/spacing_track.html">
+<link rel="import" href="/tracing/ui/tracks/thread_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays threads with only scheduling information but no
+ * slices. By default it's collapsed to minimize initial visual difference
+ * while allowing the user to drill-down into whatever process is
+ * interesting to them.
+ * @constructor
+ * @extends {ContainerTrack}
+ */
+ const OtherThreadsTrack = tr.ui.b.define(
+ 'other-threads-track', tr.ui.tracks.OtherThreadsTrack);
+
+ const SpacingTrack = tr.ui.tracks.SpacingTrack;
+
+ OtherThreadsTrack.prototype = {
+
+ __proto__: tr.ui.tracks.ContainerTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+
+ this.header_ = document.createElement('tr-ui-b-heading');
+ this.header_.addEventListener('click', this.onHeaderClick_.bind(this));
+ this.header_.heading = 'Other Threads';
+ this.header_.tooltip = 'Threads with only scheduling information';
+ this.header_.arrowVisible = true;
+
+ this.threads_ = [];
+ this.expanded = false;
+ this.collapsible_ = true;
+ },
+
+ set threads(threads) {
+ this.threads_ = threads;
+ this.updateContents_();
+ },
+
+ set collapsible(collapsible) {
+ this.collapsible_ = collapsible;
+ this.updateContents_();
+ },
+
+ onHeaderClick_(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ this.expanded = !this.expanded;
+ },
+
+ get expanded() {
+ return this.header_.expanded;
+ },
+
+ set expanded(expanded) {
+ expanded = !!expanded;
+
+ if (this.expanded === expanded) return;
+
+ this.header_.expanded = expanded;
+
+ // Expanding and collapsing tracks is, essentially, growing and shrinking
+ // the viewport. We dispatch a change event to trigger any processing
+ // to happen.
+ this.viewport_.dispatchChangeEvent();
+
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ this.detach();
+ if (this.collapsible_) {
+ Polymer.dom(this).appendChild(this.header_);
+ }
+ if (this.expanded || !this.collapsible_) {
+ for (const thread of this.threads_) {
+ const track = new tr.ui.tracks.ThreadTrack(this.viewport);
+ track.thread = thread;
+ if (!track.hasVisibleContent) return;
+
+ Polymer.dom(this).appendChild(track);
+ Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));
+ }
+ }
+ }
+ };
+
+ return {
+ OtherThreadsTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/power_series_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/power_series_track.html
new file mode 100644
index 00000000000..d32cd21e9a3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/power_series_track.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/chart_point.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series.html">
+<link rel="import" href="/tracing/ui/tracks/chart_series_y_axis.html">
+<link rel="import" href="/tracing/ui/tracks/chart_track.html">
+
+<style>
+.power-series-track {
+ height: 90px;
+}
+</style>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ColorScheme = tr.b.ColorScheme;
+ const ChartTrack = tr.ui.tracks.ChartTrack;
+
+ /**
+ * A track that displays a PowerSeries.
+ *
+ * @constructor
+ * @extends {ChartTrack}
+ */
+ const PowerSeriesTrack = tr.ui.b.define('power-series-track', ChartTrack);
+
+ PowerSeriesTrack.prototype = {
+ __proto__: ChartTrack.prototype,
+
+ decorate(viewport) {
+ ChartTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('power-series-track');
+ this.heading = 'Power';
+ this.powerSeries_ = undefined;
+ },
+
+ set powerSeries(powerSeries) {
+ this.powerSeries_ = powerSeries;
+
+ this.series = this.buildChartSeries_();
+ this.autoSetAllAxes({expandMax: true});
+ },
+
+ get hasVisibleContent() {
+ return (this.powerSeries_ && this.powerSeries_.samples.length > 0);
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ containerToTrackMap.addContainer(this.powerSeries_, this);
+ },
+
+ buildChartSeries_() {
+ if (!this.hasVisibleContent) return [];
+
+ const seriesYAxis = new tr.ui.tracks.ChartSeriesYAxis(0, undefined);
+ const pts = this.powerSeries_.samples.map(function(smpl) {
+ return new tr.ui.tracks.ChartPoint(smpl, smpl.start, smpl.powerInW);
+ });
+ const renderingConfig = {
+ chartType: tr.ui.tracks.ChartSeriesType.AREA,
+ colorId: ColorScheme.getColorIdForGeneralPurposeString(this.heading)
+ };
+
+ return [new tr.ui.tracks.ChartSeries(pts, seriesYAxis, renderingConfig)];
+ }
+ };
+
+ return {
+ PowerSeriesTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/power_series_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/power_series_track_test.html
new file mode 100644
index 00000000000..9e8b03aa168
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/power_series_track_test.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel='import' href='/tracing/model/device.html'>
+<link rel='import' href='/tracing/model/model.html'>
+<link rel='import' href='/tracing/model/power_series.html'>
+<link rel='import' href='/tracing/ui/base/constants.html'>
+<link rel='import' href='/tracing/ui/timeline_viewport.html'>
+<link rel='import' href='/tracing/ui/tracks/container_to_track_map.html'>
+<link rel='import' href='/tracing/ui/tracks/drawing_container.html'>
+<link rel="import" href="/tracing/ui/tracks/power_series_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Device = tr.model.Device;
+ const Model = tr.Model;
+ const PowerSeries = tr.model.PowerSeries;
+ const PowerSeriesTrack = tr.ui.tracks.PowerSeriesTrack;
+
+ const createDrawingContainer = function(series) {
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ if (series) {
+ series.updateBounds();
+ setDisplayTransformFromBounds(viewport, series.bounds);
+ }
+
+ return drawingContainer;
+ };
+
+ /**
+ * Sets the mapping between the input range of timestamps and the output range
+ * of horizontal pixels.
+ */
+ const setDisplayTransformFromBounds = function(viewport, bounds) {
+ const dt = new tr.ui.TimelineDisplayTransform();
+ const pixelRatio = window.devicePixelRatio || 1;
+ const chartPixelWidth =
+ (window.innerWidth - tr.ui.b.constants.HEADING_WIDTH) * pixelRatio;
+ dt.xSetWorldBounds(bounds.min, bounds.max, chartPixelWidth);
+ viewport.setDisplayTransformImmediately(dt);
+ };
+
+ test('instantiate', function() {
+ const series = new PowerSeries(new Model().device);
+ series.addPowerSample(0, 1);
+ series.addPowerSample(0.5, 2);
+ series.addPowerSample(1, 3);
+ series.addPowerSample(1.5, 4);
+
+ const drawingContainer = createDrawingContainer(series);
+ const track = new PowerSeriesTrack(drawingContainer.viewport);
+ track.powerSeries = series;
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(drawingContainer);
+ });
+
+ test('hasVisibleContent_trueWithPowerSamplesPresent', function() {
+ const series = new PowerSeries(new Model().device);
+ series.addPowerSample(0, 1);
+ series.addPowerSample(0.5, 2);
+ series.addPowerSample(1, 3);
+ series.addPowerSample(1.5, 4);
+
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+
+ const track = new PowerSeriesTrack(viewport);
+ track.powerSeries = series;
+
+ assert.isTrue(track.hasVisibleContent);
+ });
+
+ test('hasVisibleContent_falseWithUndefinedPowerSeries', function() {
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+
+ const track = new PowerSeriesTrack(viewport);
+ track.powerSeries = undefined;
+
+ assert.notOk(track.hasVisibleContent);
+ });
+
+ test('hasVisibleContent_falseWithEmptyPowerSeries', function() {
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+
+ const track = new PowerSeriesTrack(viewport);
+ const series = new PowerSeries(new Model().device);
+ track.powerSeries = series;
+
+ assert.notOk(track.hasVisibleContent);
+ });
+
+ test('addContainersToTrackMap', function() {
+ const div = document.createElement('div');
+ const viewport = new tr.ui.TimelineViewport(div);
+
+ const powerSeriesTrack = new PowerSeriesTrack(viewport);
+ const series = new PowerSeries(new Model().device);
+ powerSeriesTrack.powerSeries = series;
+
+ const containerToTrackMap = new tr.ui.tracks.ContainerToTrackMap();
+ powerSeriesTrack.addContainersToTrackMap(containerToTrackMap);
+
+ assert.strictEqual(
+ containerToTrackMap.getTrackByStableId('Device.PowerSeries'),
+ powerSeriesTrack);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_memory_dump_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_memory_dump_track.html
new file mode 100644
index 00000000000..247d707f58f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_memory_dump_track.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/tracks/chart_track.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/memory_dump_track_util.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ALLOCATED_MEMORY_TRACK_HEIGHT = 50;
+
+ /**
+ * A track that displays an array of ProcessMemoryDump objects.
+ * @constructor
+ * @extends {ContainerTrack}
+ */
+ const ProcessMemoryDumpTrack = tr.ui.b.define(
+ 'process-memory-dump-track', tr.ui.tracks.ContainerTrack);
+
+ ProcessMemoryDumpTrack.prototype = {
+ __proto__: tr.ui.tracks.ContainerTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+ this.memoryDumps_ = undefined;
+ },
+
+ get memoryDumps() {
+ return this.memoryDumps_;
+ },
+
+ set memoryDumps(memoryDumps) {
+ this.memoryDumps_ = memoryDumps;
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ this.clearTracks_();
+
+ // Show no tracks if there are no dumps.
+ if (!this.memoryDumps_ || !this.memoryDumps_.length) return;
+
+ this.appendAllocatedMemoryTrack_();
+ },
+
+ appendAllocatedMemoryTrack_() {
+ const series = tr.ui.tracks.buildProcessAllocatedMemoryChartSeries(
+ this.memoryDumps_);
+ if (!series) return;
+
+ const track = new tr.ui.tracks.ChartTrack(this.viewport);
+ track.heading = 'Memory per component';
+ track.height = ALLOCATED_MEMORY_TRACK_HEIGHT + 'px';
+ track.series = series;
+ track.autoSetAllAxes({expandMax: true});
+ Polymer.dom(this).appendChild(track);
+ }
+ };
+
+ return {
+ ProcessMemoryDumpTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_memory_dump_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_memory_dump_track_test.html
new file mode 100644
index 00000000000..897d2883c62
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_memory_dump_track_test.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/memory_dump_track_test_utils.html">
+<link rel="import" href="/tracing/ui/tracks/process_memory_dump_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Viewport = tr.ui.TimelineViewport;
+ const ProcessMemoryDumpTrack = tr.ui.tracks.ProcessMemoryDumpTrack;
+ const createTestProcessMemoryDumps =
+ tr.ui.tracks.createTestProcessMemoryDumps;
+
+ function instantiateTrack(withVMRegions, withAllocatorDumps,
+ expectedTrackCount) {
+ const dumps = createTestProcessMemoryDumps(
+ withVMRegions, withAllocatorDumps);
+
+ const div = document.createElement('div');
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = new ProcessMemoryDumpTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ drawingContainer.invalidate();
+
+ track.memoryDumps = dumps;
+
+ // TODO(petrcermak): Check that the div has indeed zero size.
+ if (expectedTrackCount > 0) {
+ this.addHTMLOutput(div);
+ }
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 50, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ assert.lengthOf(track.tracks_, expectedTrackCount);
+ }
+
+ test('instantiate_withoutMemoryAllocatorDumps', function() {
+ instantiateTrack.call(this, false, false, 0);
+ });
+ test('instantiate_withMemoryAllocatorDumps', function() {
+ instantiateTrack.call(this, false, true, 1);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_summary_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_summary_track.html
new file mode 100644
index 00000000000..c6560f40118
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_summary_track.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/color_scheme.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/rect_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ColorScheme = tr.b.ColorScheme;
+
+ /**
+ * Visualizes a Process's state using a series of rects to represent activity.
+ * @constructor
+ */
+ const ProcessSummaryTrack = tr.ui.b.define('process-summary-track',
+ tr.ui.tracks.RectTrack);
+
+ ProcessSummaryTrack.buildRectsFromProcess = function(process) {
+ if (!process) return [];
+
+ const ops = [];
+ // build list of start/end ops for each top level or important slice
+ const pushOp = function(isStart, time, slice) {
+ ops.push({
+ isStart,
+ time,
+ slice
+ });
+ };
+ for (const tid in process.threads) {
+ const sliceGroup = process.threads[tid].sliceGroup;
+
+ sliceGroup.topLevelSlices.forEach(function(slice) {
+ pushOp(true, slice.start, undefined);
+ pushOp(false, slice.end, undefined);
+ });
+ sliceGroup.slices.forEach(function(slice) {
+ if (slice.important) {
+ pushOp(true, slice.start, slice);
+ pushOp(false, slice.end, slice);
+ }
+ });
+ }
+ ops.sort(function(a, b) { return a.time - b.time; });
+
+ const rects = [];
+ /**
+ * Build a row of rects which display one way for unimportant activity,
+ * and during important slices, show up as those important slices.
+ *
+ * If an important slice starts in the middle of another,
+ * just drop it on the floor.
+ */
+ const genericColorId = ColorScheme.getColorIdForReservedName(
+ 'generic_work');
+ const pushRect = function(start, end, slice) {
+ rects.push(new tr.ui.tracks.Rect(
+ slice, /* modelItem: show selection state of slice if present */
+ slice ? slice.title : '', /* title */
+ slice ? slice.colorId : genericColorId, /* colorId */
+ start, /* start */
+ end - start /* duration */));
+ };
+ let depth = 0;
+ let currentSlice = undefined;
+ let lastStart = undefined;
+ ops.forEach(function(op) {
+ depth += op.isStart ? 1 : -1;
+
+ if (currentSlice) {
+ // simply find end of current important slice
+ if (!op.isStart && op.slice === currentSlice) {
+ // important slice has ended
+ pushRect(lastStart, op.time, currentSlice);
+ lastStart = depth >= 1 ? op.time : undefined;
+ currentSlice = undefined;
+ }
+ } else {
+ if (op.isStart) {
+ if (depth === 1) {
+ lastStart = op.time;
+ currentSlice = op.slice;
+ } else if (op.slice) {
+ // switch to slice
+ if (op.time !== lastStart) {
+ pushRect(lastStart, op.time, undefined);
+ lastStart = op.time;
+ }
+ currentSlice = op.slice;
+ }
+ } else {
+ if (depth === 0) {
+ pushRect(lastStart, op.time, undefined);
+ lastStart = undefined;
+ }
+ }
+ }
+ });
+ return rects;
+ };
+
+ ProcessSummaryTrack.prototype = {
+ __proto__: tr.ui.tracks.RectTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.RectTrack.prototype.decorate.call(this, viewport);
+ },
+
+ get process() {
+ return this.process_;
+ },
+
+ set process(process) {
+ this.process_ = process;
+ this.rects = ProcessSummaryTrack.buildRectsFromProcess(process);
+ }
+ };
+
+ return {
+ ProcessSummaryTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_summary_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_summary_track_test.html
new file mode 100644
index 00000000000..1d071f9d0ce
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_summary_track_test.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/model.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/ui/tracks/process_summary_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ProcessSummaryTrack = tr.ui.tracks.ProcessSummaryTrack;
+
+ test('buildRectSimple', function() {
+ let process;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ process = model.getOrCreateProcess(1);
+ // XXXX
+ // XXXX
+ const thread1 = process.getOrCreateThread(1);
+ thread1.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 1, duration: 4}));
+ const thread2 = process.getOrCreateThread(2);
+ thread2.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 4, duration: 4}));
+ });
+
+ const rects = ProcessSummaryTrack.buildRectsFromProcess(process);
+
+ assert.strictEqual(rects.length, 1);
+ const rect = rects[0];
+ assert.closeTo(rect.start, 1, 1e-5);
+ assert.closeTo(rect.end, 8, 1e-5);
+ });
+
+ test('buildRectComplex', function() {
+ let process;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ process = model.getOrCreateProcess(1);
+ // XXXX X X XX
+ // XXXX XXX X
+ const thread1 = process.getOrCreateThread(1);
+ thread1.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 1, duration: 4}));
+ thread1.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 9, duration: 1}));
+ thread1.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 11, duration: 1}));
+ thread1.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 13, duration: 2}));
+ const thread2 = process.getOrCreateThread(2);
+ thread2.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 4, duration: 4}));
+ thread2.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 9, duration: 3}));
+ thread2.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx(
+ {start: 16, duration: 1}));
+ });
+
+ const rects = ProcessSummaryTrack.buildRectsFromProcess(process);
+
+ assert.strictEqual(4, rects.length);
+ assert.closeTo(rects[0].start, 1, 1e-5);
+ assert.closeTo(rects[0].end, 8, 1e-5);
+ assert.closeTo(rects[1].start, 9, 1e-5);
+ assert.closeTo(rects[1].end, 12, 1e-5);
+ assert.closeTo(rects[2].start, 13, 1e-5);
+ assert.closeTo(rects[2].end, 15, 1e-5);
+ assert.closeTo(rects[3].start, 16, 1e-5);
+ assert.closeTo(rects[3].end, 17, 1e-5);
+ });
+
+ test('buildRectImportantSlice', function() {
+ let process;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ // [ unimportant ]
+ // [important]
+ const a = tr.c.TestUtils.newSliceEx(
+ {title: 'unimportant', start: 4, duration: 21});
+ const b = tr.c.TestUtils.newSliceEx(
+ {title: 'important', start: 9, duration: 11});
+ b.important = true;
+ process = model.getOrCreateProcess(1);
+ process.getOrCreateThread(1).sliceGroup.pushSlices([a, b]);
+
+ model.importantSlice = b;
+ });
+
+ const rects = ProcessSummaryTrack.buildRectsFromProcess(process);
+
+ assert.strictEqual(3, rects.length);
+ assert.closeTo(rects[0].start, 4, 1e-5);
+ assert.closeTo(rects[0].end, 9, 1e-5);
+ assert.closeTo(rects[1].start, 9, 1e-5);
+ assert.closeTo(rects[1].end, 20, 1e-5);
+ assert.closeTo(rects[2].start, 20, 1e-5);
+ assert.closeTo(rects[2].end, 25, 1e-5);
+
+ // middle rect represents important slice, so colorId & title are preserved
+ assert.strictEqual(rects[1].title, model.importantSlice.title);
+ assert.strictEqual(rects[1].colorId, model.importantSlice.colorId);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track.html
new file mode 100644
index 00000000000..1be51cbf4cb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/draw_helpers.html">
+<link rel="import" href="/tracing/ui/tracks/process_memory_dump_track.html">
+<link rel="import" href="/tracing/ui/tracks/process_track_base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ProcessTrackBase = tr.ui.tracks.ProcessTrackBase;
+
+ /**
+ * @constructor
+ */
+ const ProcessTrack = tr.ui.b.define('process-track', ProcessTrackBase);
+
+ ProcessTrack.prototype = {
+ __proto__: ProcessTrackBase.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ProcessTrackBase.prototype.decorate.call(this, viewport);
+ },
+
+ drawTrack(type) {
+ switch (type) {
+ case tr.ui.tracks.DrawType.INSTANT_EVENT: {
+ if (!this.processBase.instantEvents ||
+ this.processBase.instantEvents.length === 0) {
+ break;
+ }
+
+ const ctx = this.context();
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const bounds = this.getBoundingClientRect();
+ const canvasBounds = ctx.canvas.getBoundingClientRect();
+
+ ctx.save();
+ ctx.translate(0, pixelRatio * (bounds.top - canvasBounds.top));
+
+ const dt = this.viewport.currentDisplayTransform;
+ const viewLWorld = dt.xViewToWorld(0);
+ const viewRWorld = dt.xViewToWorld(canvasBounds.width * pixelRatio);
+
+ tr.ui.b.drawInstantSlicesAsLines(
+ ctx,
+ this.viewport.currentDisplayTransform,
+ viewLWorld,
+ viewRWorld,
+ bounds.height,
+ this.processBase.instantEvents,
+ 2);
+
+ ctx.restore();
+
+ break;
+ }
+
+ case tr.ui.tracks.DrawType.BACKGROUND:
+ this.drawBackground_();
+ // Don't bother recursing further, Process is the only level that
+ // draws backgrounds.
+ return;
+ }
+
+ tr.ui.tracks.ContainerTrack.prototype.drawTrack.call(this, type);
+ },
+
+ drawBackground_() {
+ const ctx = this.context();
+ const canvasBounds = ctx.canvas.getBoundingClientRect();
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ let draw = false;
+ ctx.fillStyle = '#eee';
+ for (let i = 0; i < this.children.length; ++i) {
+ if (!(this.children[i] instanceof tr.ui.tracks.Track) ||
+ (this.children[i] instanceof tr.ui.tracks.SpacingTrack)) {
+ continue;
+ }
+
+ draw = !draw;
+ if (!draw) continue;
+
+ const bounds = this.children[i].getBoundingClientRect();
+ ctx.fillRect(0, pixelRatio * (bounds.top - canvasBounds.top),
+ ctx.canvas.width, pixelRatio * bounds.height);
+ }
+ },
+
+ // Process maps to processBase because we derive from ProcessTrackBase.
+ set process(process) {
+ this.processBase = process;
+ },
+
+ get process() {
+ return this.processBase;
+ },
+
+ get eventContainer() {
+ return this.process;
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ tr.ui.tracks.ProcessTrackBase.prototype.addContainersToTrackMap.apply(
+ this, arguments);
+ containerToTrackMap.addContainer(this.process, this);
+ },
+
+ appendMemoryDumpTrack_() {
+ const processMemoryDumps = this.process.memoryDumps;
+ if (processMemoryDumps.length) {
+ const pmdt = new tr.ui.tracks.ProcessMemoryDumpTrack(this.viewport_);
+ pmdt.memoryDumps = processMemoryDumps;
+ Polymer.dom(this).appendChild(pmdt);
+ }
+ },
+
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ function onPickHit(instantEvent) {
+ selection.push(instantEvent);
+ }
+ const instantEventWidth = 2 * viewPixWidthWorld;
+ tr.b.iterateOverIntersectingIntervals(this.processBase.instantEvents,
+ function(x) { return x.start; },
+ function(x) { return x.duration + instantEventWidth; },
+ loWX, hiWX,
+ onPickHit.bind(this));
+
+ tr.ui.tracks.ContainerTrack.prototype.
+ addIntersectingEventsInRangeToSelectionInWorldSpace.
+ apply(this, arguments);
+ },
+
+ addClosestEventToSelection(worldX, worldMaxDist, loY, hiY,
+ selection) {
+ this.addClosestInstantEventToSelection(this.processBase.instantEvents,
+ worldX, worldMaxDist, selection);
+ tr.ui.tracks.ContainerTrack.prototype.addClosestEventToSelection.
+ apply(this, arguments);
+ }
+ };
+
+ return {
+ ProcessTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track_base.css b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track_base.css
new file mode 100644
index 00000000000..25fa5f015b7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track_base.css
@@ -0,0 +1,39 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.process-track-header {
+ display: flex;
+ flex: 0 0 auto;
+ background-image: -webkit-gradient(linear,
+ 0 0, 100% 0,
+ from(#E5E5E5),
+ to(#D1D1D1));
+ border-bottom: 1px solid #8e8e8e;
+ border-top: 1px solid white;
+ font-size: 75%;
+}
+
+.process-track-name {
+ flex-grow: 1;
+}
+
+.process-track-name:before {
+ content: '\25B8'; /* Right triangle */
+ padding: 0 5px;
+}
+
+.process-track-base.expanded .process-track-name:before {
+ content: '\25BE'; /* Down triangle */
+}
+
+.process-track-close {
+ color: black;
+ border: 1px solid transparent;
+ padding: 0px 2px;
+}
+
+.process-track-close:hover {
+ border: 1px solid grey;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track_base.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track_base.html
new file mode 100644
index 00000000000..89358b8411e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/process_track_base.html
@@ -0,0 +1,313 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet" href="/tracing/ui/tracks/process_track_base.css">
+
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/model/model_settings.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/counter_track.html">
+<link rel="import" href="/tracing/ui/tracks/frame_track.html">
+<link rel="import" href="/tracing/ui/tracks/object_instance_group_track.html">
+<link rel="import" href="/tracing/ui/tracks/other_threads_track.html">
+<link rel="import" href="/tracing/ui/tracks/process_summary_track.html">
+<link rel="import" href="/tracing/ui/tracks/spacing_track.html">
+<link rel="import" href="/tracing/ui/tracks/thread_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ const ObjectSnapshotView = tr.ui.analysis.ObjectSnapshotView;
+ const ObjectInstanceView = tr.ui.analysis.ObjectInstanceView;
+ const SpacingTrack = tr.ui.tracks.SpacingTrack;
+
+ /**
+ * Visualizes a Process by building ThreadTracks and CounterTracks.
+ * @constructor
+ */
+ const ProcessTrackBase =
+ tr.ui.b.define('process-track-base', tr.ui.tracks.ContainerTrack);
+
+ ProcessTrackBase.prototype = {
+
+ __proto__: tr.ui.tracks.ContainerTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+
+ this.processBase_ = undefined;
+
+ Polymer.dom(this).classList.add('process-track-base');
+ Polymer.dom(this).classList.add('expanded');
+
+ this.processNameEl_ = tr.ui.b.createSpan();
+ Polymer.dom(this.processNameEl_).classList.add('process-track-name');
+
+ this.closeEl_ = tr.ui.b.createSpan();
+ Polymer.dom(this.closeEl_).classList.add('process-track-close');
+ this.closeEl_.textContent = 'X';
+
+ this.headerEl_ = tr.ui.b.createDiv({className: 'process-track-header'});
+ Polymer.dom(this.headerEl_).appendChild(this.processNameEl_);
+ Polymer.dom(this.headerEl_).appendChild(this.closeEl_);
+ this.headerEl_.addEventListener('click', this.onHeaderClick_.bind(this));
+
+ Polymer.dom(this).appendChild(this.headerEl_);
+ },
+
+ get processBase() {
+ return this.processBase_;
+ },
+
+ set processBase(processBase) {
+ this.processBase_ = processBase;
+
+ if (this.processBase_) {
+ const modelSettings = new tr.model.ModelSettings(
+ this.processBase_.model);
+ const defaultValue = this.processBase_.important;
+ this.expanded = modelSettings.getSettingFor(
+ this.processBase_, 'expanded', defaultValue);
+ }
+
+ this.updateContents_();
+ },
+
+ get expanded() {
+ return Polymer.dom(this).classList.contains('expanded');
+ },
+
+ set expanded(expanded) {
+ expanded = !!expanded;
+
+ if (this.expanded === expanded) return;
+
+ Polymer.dom(this).classList.toggle('expanded');
+
+ // Expanding and collapsing tracks is, essentially, growing and shrinking
+ // the viewport. We dispatch a change event to trigger any processing
+ // to happen.
+ this.viewport_.dispatchChangeEvent();
+
+ if (!this.processBase_) return;
+
+ const modelSettings = new tr.model.ModelSettings(this.processBase_.model);
+ modelSettings.setSettingFor(this.processBase_, 'expanded', expanded);
+ this.updateContents_();
+ this.viewport.rebuildEventToTrackMap();
+ this.viewport.rebuildContainerToTrackMap();
+ },
+
+ set visible(visible) {
+ if (visible === this.visible) return;
+ this.hidden = !visible;
+
+ tr.b.dispatchSimpleEvent(this, 'visibility');
+ // Changing the visibility of the tracks can grow and shrink the viewport.
+ // We dispatch a change event to trigger any processing to happen.
+ this.viewport_.dispatchChangeEvent();
+
+ if (!this.processBase_) return;
+
+ this.updateContents_();
+ this.viewport.rebuildEventToTrackMap();
+ this.viewport.rebuildContainerToTrackMap();
+ },
+
+ get visible() {
+ return !this.hidden;
+ },
+
+ get hasVisibleContent() {
+ if (this.expanded) {
+ return this.children.length > 1;
+ }
+ return true;
+ },
+
+ onHeaderClick_(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ if (e.target === this.closeEl_) {
+ this.visible = false;
+ } else {
+ this.expanded = !this.expanded;
+ }
+ },
+
+ updateContents_() {
+ this.clearTracks_();
+
+ if (!this.processBase_) return;
+
+ Polymer.dom(this.processNameEl_).textContent =
+ this.processBase_.userFriendlyName;
+ this.headerEl_.title = this.processBase_.userFriendlyDetails;
+
+ // Create the object instance tracks for this process.
+ this.willAppendTracks_();
+ if (this.expanded) {
+ this.appendMemoryDumpTrack_();
+ this.appendObjectInstanceTracks_();
+ this.appendCounterTracks_();
+ this.appendFrameTrack_();
+ this.appendThreadTracks_();
+ } else {
+ this.appendSummaryTrack_();
+ }
+ this.didAppendTracks_();
+ },
+
+ willAppendTracks_() {
+ },
+
+ didAppendTracks_() {
+ },
+
+ appendMemoryDumpTrack_() {
+ },
+
+ appendSummaryTrack_() {
+ const track = new tr.ui.tracks.ProcessSummaryTrack(this.viewport);
+ track.process = this.process;
+ if (!track.hasVisibleContent) return;
+ Polymer.dom(this).appendChild(track);
+ // no spacing track, since this track only shown in collapsed state
+ },
+
+ appendFrameTrack_() {
+ const frames = this.process ? this.process.frames : undefined;
+ if (!frames || !frames.length) return;
+
+ const track = new tr.ui.tracks.FrameTrack(this.viewport);
+ track.frames = frames;
+ Polymer.dom(this).appendChild(track);
+ },
+
+ appendObjectInstanceTracks_() {
+ const instancesByTypeName =
+ this.processBase_.objects.getAllInstancesByTypeName();
+ const instanceTypeNames = Object.keys(instancesByTypeName);
+ instanceTypeNames.sort();
+
+ let didAppendAtLeastOneTrack = false;
+ instanceTypeNames.forEach(function(typeName) {
+ const allInstances = instancesByTypeName[typeName];
+
+ // If a object snapshot has a view it will be shown,
+ // unless the view asked for it to not be shown.
+ let instanceViewInfo = ObjectInstanceView.getTypeInfo(
+ undefined, typeName);
+ let snapshotViewInfo = ObjectSnapshotView.getTypeInfo(
+ undefined, typeName);
+ if (instanceViewInfo && !instanceViewInfo.metadata.showInTrackView) {
+ instanceViewInfo = undefined;
+ }
+ if (snapshotViewInfo && !snapshotViewInfo.metadata.showInTrackView) {
+ snapshotViewInfo = undefined;
+ }
+ const hasViewInfo = instanceViewInfo || snapshotViewInfo;
+
+ // There are some instances that don't merit their own track in
+ // the UI. Filter them out.
+ const visibleInstances = [];
+ for (let i = 0; i < allInstances.length; i++) {
+ const instance = allInstances[i];
+
+ // Do not create tracks for instances that have no snapshots.
+ if (instance.snapshots.length === 0) continue;
+
+ // Do not create tracks for instances that have implicit snapshots
+ // and don't have a view.
+ if (instance.hasImplicitSnapshots && !hasViewInfo) continue;
+
+ visibleInstances.push(instance);
+ }
+ if (visibleInstances.length === 0) return;
+
+ // Look up the constructor for this track, or use the default
+ // constructor if none exists.
+ let trackConstructor =
+ tr.ui.tracks.ObjectInstanceTrack.getConstructor(
+ undefined, typeName);
+ if (!trackConstructor) {
+ snapshotViewInfo = ObjectSnapshotView.getTypeInfo(
+ undefined, typeName);
+ if (snapshotViewInfo && snapshotViewInfo.metadata.showInstances) {
+ trackConstructor = tr.ui.tracks.ObjectInstanceGroupTrack;
+ } else {
+ trackConstructor = tr.ui.tracks.ObjectInstanceTrack;
+ }
+ }
+ const track = new trackConstructor(this.viewport);
+ track.objectInstances = visibleInstances;
+ Polymer.dom(this).appendChild(track);
+ didAppendAtLeastOneTrack = true;
+ }, this);
+ if (didAppendAtLeastOneTrack) {
+ Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));
+ }
+ },
+
+ appendCounterTracks_() {
+ // Add counter tracks for this process.
+ const counters = Object.values(this.processBase.counters);
+ counters.sort(tr.model.Counter.compare);
+
+ // Create the counters for this process.
+ counters.forEach(function(counter) {
+ const track = new tr.ui.tracks.CounterTrack(this.viewport);
+ track.counter = counter;
+ Polymer.dom(this).appendChild(track);
+ Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));
+ }.bind(this));
+ },
+
+ appendThreadTracks_() {
+ // Get a sorted list of threads.
+ const threads = Object.values(this.processBase.threads);
+ threads.sort(tr.model.Thread.compare);
+
+ // Create the threads.
+ const otherThreads = [];
+ let hasVisibleThreads = false;
+ threads.forEach(function(thread) {
+ const track = new tr.ui.tracks.ThreadTrack(this.viewport);
+ track.thread = thread;
+ if (!track.hasVisibleContent) return;
+
+ if (track.hasSlices) {
+ hasVisibleThreads = true;
+ Polymer.dom(this).appendChild(track);
+ Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));
+ } else if (track.hasTimeSlices) {
+ otherThreads.push(thread);
+ }
+ }.bind(this));
+
+ if (otherThreads.length > 0) {
+ // If there's only 1 thread with scheduling-only information don't
+ // bother making a group, just display it directly
+ // Similarly if we are a process with only scheduling-only threads
+ // don't bother making a group as the process itself serves
+ // as the collapsable group
+ const track = new tr.ui.tracks.OtherThreadsTrack(this.viewport);
+ track.threads = otherThreads;
+ track.collapsible = otherThreads.length > 1 && hasVisibleThreads;
+ Polymer.dom(this).appendChild(track);
+ }
+ }
+ };
+
+ return {
+ ProcessTrackBase,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track.css b/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track.css
new file mode 100644
index 00000000000..0467c91562c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track.css
@@ -0,0 +1,8 @@
+/* Copyright (c) 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.rect-track {
+ height: 18px;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track.html
new file mode 100644
index 00000000000..65e073d32ee
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track.html
@@ -0,0 +1,249 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet" href="/tracing/ui/tracks/rect_track.css">
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/model/proxy_selectable_item.html">
+<link rel="import" href="/tracing/ui/base/draw_helpers.html">
+<link rel="import" href="/tracing/ui/base/fast_rect_renderer.html">
+<link rel="import" href="/tracing/ui/base/heading.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays an array of Rect objects.
+ * @constructor
+ * @extends {Track}
+ */
+ const RectTrack = tr.ui.b.define(
+ 'rect-track', tr.ui.tracks.Track);
+
+ RectTrack.prototype = {
+
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('rect-track');
+ this.asyncStyle_ = false;
+ this.rects_ = null;
+
+ this.heading_ = document.createElement('tr-ui-b-heading');
+ Polymer.dom(this).appendChild(this.heading_);
+ },
+
+ set heading(heading) {
+ this.heading_.heading = heading;
+ },
+
+ get heading() {
+ return this.heading_.heading;
+ },
+
+ set tooltip(tooltip) {
+ this.heading_.tooltip = tooltip;
+ },
+
+ set selectionGenerator(generator) {
+ this.heading_.selectionGenerator = generator;
+ },
+
+ set expanded(expanded) {
+ this.heading_.expanded = !!expanded;
+ },
+
+ set arrowVisible(arrowVisible) {
+ this.heading_.arrowVisible = !!arrowVisible;
+ },
+
+ get expanded() {
+ return this.heading_.expanded;
+ },
+
+ get asyncStyle() {
+ return this.asyncStyle_;
+ },
+
+ set asyncStyle(v) {
+ this.asyncStyle_ = !!v;
+ },
+
+ get rects() {
+ return this.rects_;
+ },
+
+ set rects(rects) {
+ this.rects_ = rects || [];
+ this.invalidateDrawingContainer();
+ },
+
+ get height() {
+ return window.getComputedStyle(this).height;
+ },
+
+ set height(height) {
+ this.style.height = height;
+ this.invalidateDrawingContainer();
+ },
+
+ get hasVisibleContent() {
+ return this.rects_.length > 0;
+ },
+
+ draw(type, viewLWorld, viewRWorld, viewHeight) {
+ switch (type) {
+ case tr.ui.tracks.DrawType.GENERAL_EVENT:
+ this.drawRects_(viewLWorld, viewRWorld);
+ break;
+ }
+ },
+
+ drawRects_(viewLWorld, viewRWorld) {
+ const ctx = this.context();
+
+ ctx.save();
+ const bounds = this.getBoundingClientRect();
+ tr.ui.b.drawSlices(
+ ctx,
+ this.viewport.currentDisplayTransform,
+ viewLWorld,
+ viewRWorld,
+ bounds.height,
+ this.rects_,
+ this.asyncStyle_);
+ ctx.restore();
+
+ if (bounds.height <= 6) return;
+
+ let fontSize;
+ let yOffset;
+ if (bounds.height < 15) {
+ fontSize = 6;
+ yOffset = 1.0;
+ } else {
+ fontSize = 10;
+ yOffset = 2.5;
+ }
+ tr.ui.b.drawLabels(
+ ctx,
+ this.viewport.currentDisplayTransform,
+ viewLWorld,
+ viewRWorld,
+ this.rects_,
+ this.asyncStyle_,
+ fontSize,
+ yOffset);
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ if (this.rects_ === undefined || this.rects_ === null) {
+ return;
+ }
+
+ this.rects_.forEach(function(rect) {
+ rect.addToTrackMap(eventToTrackMap, this);
+ }, this);
+ },
+
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ function onRect(rect) {
+ rect.addToSelection(selection);
+ }
+ onRect = onRect.bind(this);
+ const instantEventWidth = 2 * viewPixWidthWorld;
+ tr.b.iterateOverIntersectingIntervals(this.rects_,
+ function(x) { return x.start; },
+ function(x) {
+ return x.duration === 0 ?
+ x.duration + instantEventWidth :
+ x.duration;
+ },
+ loWX, hiWX,
+ onRect);
+ },
+
+ /**
+ * Add the item to the left or right of the provided event, if any, to the
+ * selection.
+ * @param {rect} The current rect.
+ * @param {Number} offset Number of rects away from the event to look.
+ * @param {Selection} selection The selection to add an event to,
+ * if found.
+ * @return {boolean} Whether an event was found.
+ * @private
+ */
+ addEventNearToProvidedEventToSelection(event, offset, selection) {
+ const index = this.rects_.findIndex(rect => rect.modelItem === event);
+ if (index === -1) return false;
+
+ const newIndex = index + offset;
+ if (newIndex < 0 || newIndex >= this.rects_.length) return false;
+
+ this.rects_[newIndex].addToSelection(selection);
+ return true;
+ },
+
+ addAllEventsMatchingFilterToSelection(filter, selection) {
+ for (let i = 0; i < this.rects_.length; ++i) {
+ // TODO(petrcermak): Rather than unpacking the proxy item here,
+ // we should probably add an addToSelectionIfMatching(selection, filter)
+ // method to SelectableItem (#900).
+ const modelItem = this.rects_[i].modelItem;
+ if (!modelItem) continue;
+
+ if (filter.matchSlice(modelItem)) {
+ selection.push(modelItem);
+ }
+ }
+ },
+
+ addClosestEventToSelection(worldX, worldMaxDist, loY, hiY,
+ selection) {
+ const rect = tr.b.findClosestIntervalInSortedIntervals(
+ this.rects_,
+ function(x) { return x.start; },
+ function(x) { return x.end; },
+ worldX,
+ worldMaxDist);
+
+ if (!rect) return;
+
+ rect.addToSelection(selection);
+ }
+ };
+
+ /**
+ * A filled rectangle with a title.
+ *
+ * @constructor
+ * @extends {ProxySelectableItem}
+ */
+ function Rect(modelItem, title, colorId, start, duration) {
+ tr.model.ProxySelectableItem.call(this, modelItem);
+ this.title = title;
+ this.colorId = colorId;
+ this.start = start;
+ this.duration = duration;
+ this.end = start + duration;
+ }
+
+ Rect.prototype = {
+ __proto__: tr.model.ProxySelectableItem.prototype
+ };
+
+ return {
+ RectTrack,
+ Rect,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track_test.html
new file mode 100644
index 00000000000..ec81a8835d7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/rect_track_test.html
@@ -0,0 +1,412 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/slice.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/draw_helpers.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const EventSet = tr.model.EventSet;
+ const RectTrack = tr.ui.tracks.RectTrack;
+ const Rect = tr.ui.tracks.Rect;
+ const ThreadSlice = tr.model.ThreadSlice;
+ const Viewport = tr.ui.TimelineViewport;
+
+ test('instantiate_withRects', function() {
+ const div = document.createElement('div');
+
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = RectTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.heading = 'testBasicRects';
+ track.rects = [
+ new Rect(undefined, 'a', 0, 1, 1),
+ new Rect(undefined, 'b', 1, 2.1, 4.8),
+ new Rect(undefined, 'b', 1, 7, 0.5),
+ new Rect(undefined, 'c', 2, 7.6, 0.4)
+ ];
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 8.8, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ test('instantiate_withSlices', function() {
+ const div = document.createElement('div');
+
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = RectTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.heading = 'testBasicSlices';
+ track.rects = [
+ new ThreadSlice('', 'a', 0, 1, {}, 1),
+ new ThreadSlice('', 'b', 1, 2.1, {}, 4.8),
+ new ThreadSlice('', 'b', 1, 7, {}, 0.5),
+ new ThreadSlice('', 'c', 2, 7.6, {}, 0.4)
+ ];
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 8.8, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ test('instantiate_shrinkingRectSize', function() {
+ const div = document.createElement('div');
+
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = RectTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.heading = 'testShrinkingRectSizes';
+ let x = 0;
+ const widths = [10, 5, 4, 3, 2, 1, 0.5, 0.4, 0.3, 0.2, 0.1, 0.05];
+ const slices = [];
+ for (let i = 0; i < widths.length; i++) {
+ const s = new Rect(undefined, 'a', 1, x, widths[i]);
+ x += s.duration + 0.5;
+ slices.push(s);
+ }
+ track.rects = slices;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 1.1 * x, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ test('instantiate_elide', function() {
+ const optDicts = [{ trackName: 'elideOff', elide: false },
+ { trackName: 'elideOn', elide: true }];
+
+ const tooLongTitle = 'Unless eliding this SHOULD NOT BE DISPLAYED. ';
+ const bigTitle = 'Very big title name that goes on longer ' +
+ 'than you may expect';
+
+ for (const dictIndex in optDicts) {
+ const dict = optDicts[dictIndex];
+
+ const div = document.createElement('div');
+ Polymer.dom(div).appendChild(document.createTextNode(dict.trackName));
+
+ const viewport = new Viewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = new RectTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+
+ this.addHTMLOutput(div);
+ drawingContainer.invalidate();
+
+ track.SHOULD_ELIDE_TEXT = dict.elide;
+ track.heading = 'Visual: ' + dict.trackName;
+ track.rects = [
+ // title, colorId, start, args, opt_duration
+ new Rect(undefined, 'a ' + tooLongTitle + bigTitle, 0, 1, 1),
+ new Rect(undefined, bigTitle, 1, 2.1, 4.8),
+ new Rect(undefined, 'cccc cccc cccc', 1, 7, 0.5),
+ new Rect(undefined, 'd', 2, 7.6, 1.0)
+ ];
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 9.5, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+ }
+ });
+
+ test('findAllObjectsMatchingInRectTrack', function() {
+ const track = new RectTrack(new tr.ui.TimelineViewport());
+ track.rects = [
+ new ThreadSlice('', 'a', 0, 1, {}, 1),
+ new ThreadSlice('', 'b', 1, 2.1, {}, 4.8),
+ new ThreadSlice('', 'b', 1, 7, {}, 0.5),
+ new ThreadSlice('', 'c', 2, 7.6, {}, 0.4)
+ ];
+ const selection = new EventSet();
+ track.addAllEventsMatchingFilterToSelection(
+ new tr.c.TitleOrCategoryFilter('b'), selection);
+
+ const predictedSelection = new EventSet(
+ [track.rects[1].modelItem, track.rects[2].modelItem]);
+ assert.isTrue(selection.equals(predictedSelection));
+ });
+
+ test('selectionHitTesting', function() {
+ const testEl = document.createElement('div');
+ Polymer.dom(testEl).appendChild(
+ tr.ui.b.createScopedStyle('heading { width: 100px; }'));
+ testEl.style.width = '600px';
+
+ const viewport = new Viewport(testEl);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(testEl).appendChild(drawingContainer);
+
+ const track = new RectTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ this.addHTMLOutput(testEl);
+
+ drawingContainer.updateCanvasSizeIfNeeded_();
+
+ track.heading = 'testSelectionHitTesting';
+ track.rects = [
+ new ThreadSlice('', 'a', 0, 1, {}, 1),
+ new ThreadSlice('', 'b', 1, 5, {}, 4.8)
+ ];
+ const y = track.getBoundingClientRect().top + 5;
+ const pixelRatio = window.devicePixelRatio || 1;
+ const wW = 10;
+ const vW = drawingContainer.canvas.getBoundingClientRect().width;
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, wW, vW * pixelRatio);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ let selection = new EventSet();
+ let x = (1.5 / wW) * vW;
+ track.addIntersectingEventsInRangeToSelection(
+ x, x + 1, y, y + 1, selection);
+ assert.isTrue(selection.equals(new EventSet(track.rects[0].modelItem)));
+
+ selection = new EventSet();
+ x = (2.1 / wW) * vW;
+ track.addIntersectingEventsInRangeToSelection(
+ x, x + 1, y, y + 1, selection);
+ assert.strictEqual(0, selection.length);
+
+ selection = new EventSet();
+ x = (6.8 / wW) * vW;
+ track.addIntersectingEventsInRangeToSelection(
+ x, x + 1, y, y + 1, selection);
+ assert.isTrue(selection.equals(new EventSet(track.rects[1].modelItem)));
+
+ selection = new EventSet();
+ x = (9.9 / wW) * vW;
+ track.addIntersectingEventsInRangeToSelection(
+ x, x + 1, y, y + 1, selection);
+ assert.strictEqual(0, selection.length);
+ });
+
+ test('elide', function() {
+ const testEl = document.createElement('div');
+
+ const viewport = new Viewport(testEl);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(testEl).appendChild(drawingContainer);
+
+ const track = new RectTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ this.addHTMLOutput(testEl);
+
+ drawingContainer.updateCanvasSizeIfNeeded_();
+
+ const bigtitle = 'Super duper long long title ' +
+ 'holy moly when did you get so verbose?';
+ const smalltitle = 'small';
+ track.heading = 'testElide';
+ track.rects = [
+ // title, colorId, start, args, opt_duration
+ new ThreadSlice('', bigtitle, 0, 1, {}, 1),
+ new ThreadSlice('', smalltitle, 1, 2, {}, 1)
+ ];
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, 3.3, track.clientWidth);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ let stringWidthPair = undefined;
+ const pixWidth = dt.xViewVectorToWorld(1);
+
+ // Small titles on big slices are not elided.
+ stringWidthPair =
+ tr.ui.b.elidedTitleCache_.get(
+ track.context(),
+ pixWidth,
+ smalltitle,
+ tr.ui.b.elidedTitleCache_.labelWidth(
+ track.context(),
+ smalltitle),
+ 1);
+ assert.strictEqual(smalltitle, stringWidthPair.string);
+
+ // Keep shrinking the slice until eliding starts.
+ let elidedWhenSmallEnough = false;
+ for (let sliceLength = 1; sliceLength >= 0.00001; sliceLength /= 2.0) {
+ stringWidthPair =
+ tr.ui.b.elidedTitleCache_.get(
+ track.context(),
+ pixWidth,
+ smalltitle,
+ tr.ui.b.elidedTitleCache_.labelWidth(
+ track.context(),
+ smalltitle),
+ sliceLength);
+ if (stringWidthPair.string.length < smalltitle.length) {
+ elidedWhenSmallEnough = true;
+ break;
+ }
+ }
+ assert.isTrue(elidedWhenSmallEnough);
+
+ // Big titles are elided immediately.
+ let superBigTitle = '';
+ for (let x = 0; x < 10; x++) {
+ superBigTitle += bigtitle;
+ }
+ stringWidthPair =
+ tr.ui.b.elidedTitleCache_.get(
+ track.context(),
+ pixWidth,
+ superBigTitle,
+ tr.ui.b.elidedTitleCache_.labelWidth(
+ track.context(),
+ superBigTitle),
+ 1);
+ assert.isTrue(stringWidthPair.string.length < superBigTitle.length);
+
+ // And elided text ends with ...
+ const len = stringWidthPair.string.length;
+ assert.strictEqual('...', stringWidthPair.string.substring(len - 3, len));
+ });
+
+ test('rectTrackAddItemNearToProvidedEvent', function() {
+ const track = new RectTrack(new tr.ui.TimelineViewport());
+ track.rects = [
+ new ThreadSlice('', 'a', 0, 1, {}, 1),
+ new ThreadSlice('', 'b', 1, 2.1, {}, 4.8),
+ new ThreadSlice('', 'b', 1, 7, {}, 0.5),
+ new ThreadSlice('', 'c', 2, 7.6, {}, 0.4)
+ ];
+ let sel = new EventSet();
+ track.addAllEventsMatchingFilterToSelection(
+ new tr.c.TitleOrCategoryFilter('b'), sel);
+
+ // Select to the right of B.
+ const selRight = new EventSet();
+ let ret = track.addEventNearToProvidedEventToSelection(
+ tr.b.getFirstElement(sel), 1, selRight);
+ assert.isTrue(ret);
+ assert.strictEqual(
+ track.rects[2].modelItem, tr.b.getFirstElement(selRight));
+
+ // Select to the right of the 2nd b.
+ const selRight2 = new EventSet();
+ ret = track.addEventNearToProvidedEventToSelection(
+ tr.b.getFirstElement(sel), 2, selRight2);
+ assert.isTrue(ret);
+ assert.strictEqual(
+ track.rects[3].modelItem, tr.b.getFirstElement(selRight2));
+
+ // Select to 2 to the right of the 2nd b.
+ const selRightOfRight = new EventSet();
+ ret = track.addEventNearToProvidedEventToSelection(
+ tr.b.getFirstElement(selRight), 1, selRightOfRight);
+ assert.isTrue(ret);
+ assert.strictEqual(track.rects[3].modelItem,
+ tr.b.getFirstElement(selRightOfRight));
+
+ // Select to the right of the rightmost slice.
+ let selNone = new EventSet();
+ ret = track.addEventNearToProvidedEventToSelection(
+ tr.b.getFirstElement(selRightOfRight), 1, selNone);
+ assert.isFalse(ret);
+ assert.strictEqual(0, selNone.length);
+
+ // Select A and then select left.
+ sel = new EventSet();
+ track.addAllEventsMatchingFilterToSelection(
+ new tr.c.TitleOrCategoryFilter('a'), sel);
+
+ selNone = new EventSet();
+ ret = track.addEventNearToProvidedEventToSelection(
+ tr.b.getFirstElement(sel), -1, selNone);
+ assert.isFalse(ret);
+ assert.strictEqual(0, selNone.length);
+ });
+
+ test('rectTrackAddClosestEventToSelection', function() {
+ const track = new RectTrack(new tr.ui.TimelineViewport());
+ track.rects = [
+ new ThreadSlice('', 'a', 0, 1, {}, 1),
+ new ThreadSlice('', 'b', 1, 2.1, {}, 4.8),
+ new ThreadSlice('', 'b', 1, 7, {}, 0.5),
+ new ThreadSlice('', 'c', 2, 7.6, {}, 0.4)
+ ];
+
+ // Before with not range.
+ let sel = new EventSet();
+ track.addClosestEventToSelection(0, 0, 0, 0, sel);
+ assert.strictEqual(0, sel.length);
+
+ // Before with negative range.
+ sel = new EventSet();
+ track.addClosestEventToSelection(1.5, -10, 0, 0, sel);
+ assert.strictEqual(0, sel.length);
+
+ // Before first slice.
+ sel = new EventSet();
+ track.addClosestEventToSelection(0.5, 1, 0, 0, sel);
+ assert.isTrue(sel.equals(new EventSet(track.rects[0].modelItem)));
+
+ // Within first slice closer to start.
+ sel = new EventSet();
+ track.addClosestEventToSelection(1.3, 1, 0, 0, sel);
+ assert.isTrue(sel.equals(new EventSet(track.rects[0].modelItem)));
+
+ // Between slices with good range.
+ sel = new EventSet();
+ track.addClosestEventToSelection(2.08, 3, 0, 0, sel);
+ assert.isTrue(sel.equals(new EventSet(track.rects[1].modelItem)));
+
+ // Between slices with bad range.
+ sel = new EventSet();
+ track.addClosestEventToSelection(2.05, 0.03, 0, 0, sel);
+ assert.strictEqual(0, sel.length);
+
+ // Within slice closer to end.
+ sel = new EventSet();
+ track.addClosestEventToSelection(6, 100, 0, 0, sel);
+ assert.isTrue(sel.equals(new EventSet(track.rects[1].modelItem)));
+
+ // Within slice with bad range.
+ sel = new EventSet();
+ track.addClosestEventToSelection(1.8, 0.1, 0, 0, sel);
+ assert.strictEqual(0, sel.length);
+
+ // After last slice with good range.
+ sel = new EventSet();
+ track.addClosestEventToSelection(8.5, 1, 0, 0, sel);
+ assert.isTrue(sel.equals(new EventSet(track.rects[3].modelItem)));
+
+ // After last slice with bad range.
+ sel = new EventSet();
+ track.addClosestEventToSelection(10, 1, 0, 0, sel);
+ assert.strictEqual(0, sel.length);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/sample_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/sample_track.html
new file mode 100644
index 00000000000..1f764019cfc
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/sample_track.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/tracks/rect_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays an array of Sample objects.
+ * @constructor
+ * @extends {RectTrack}
+ */
+ const SampleTrack = tr.ui.b.define(
+ 'sample-track', tr.ui.tracks.RectTrack);
+
+ SampleTrack.prototype = {
+
+ __proto__: tr.ui.tracks.RectTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.RectTrack.prototype.decorate.call(this, viewport);
+ },
+
+ get samples() {
+ return this.rects;
+ },
+
+ set samples(samples) {
+ this.rects = samples;
+ }
+ };
+
+ return {
+ SampleTrack,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/sample_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/sample_track_test.html
new file mode 100644
index 00000000000..0fb17df65f1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/sample_track_test.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/profile_node.html">
+<link rel="import" href="/tracing/model/sample.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+<link rel="import" href="/tracing/ui/tracks/sample_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const SampleTrack = tr.ui.tracks.SampleTrack;
+ const Sample = tr.model.Sample;
+ const ProfileNode = tr.model.ProfileNode;
+
+ test('modelMapping', function() {
+ const track = new SampleTrack(new tr.ui.TimelineViewport());
+ const node = new ProfileNode(1, {
+ functionName: 'a'
+ }, undefined);
+ const sample = new Sample(10, 'instructions_retired', node);
+ track.samples = [sample];
+ const me0 = track.rects[0].modelItem;
+ assert.strictEqual(me0, sample);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_group_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_group_track.html
new file mode 100644
index 00000000000..36f09566b07
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_group_track.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/multi_row_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays a SliceGroup.
+ * @constructor
+ * @extends {MultiRowTrack}
+ */
+ const SliceGroupTrack = tr.ui.b.define(
+ 'slice-group-track', tr.ui.tracks.MultiRowTrack);
+
+ SliceGroupTrack.prototype = {
+
+ __proto__: tr.ui.tracks.MultiRowTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('slice-group-track');
+ this.group_ = undefined;
+ // Set the collapse threshold so we don't collapse by default, but the
+ // user can explicitly collapse if they want it.
+ this.defaultToCollapsedWhenSubRowCountMoreThan = 100;
+ },
+
+ addSubTrack_(slices) {
+ const track = new tr.ui.tracks.SliceTrack(this.viewport);
+ track.slices = slices;
+ Polymer.dom(this).appendChild(track);
+ return track;
+ },
+
+ get group() {
+ return this.group_;
+ },
+
+ set group(group) {
+ this.group_ = group;
+ this.setItemsToGroup(this.group_.slices, this.group_);
+ },
+
+ get eventContainer() {
+ return this.group;
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ tr.ui.tracks.MultiRowTrack.prototype.addContainersToTrackMap.apply(
+ this, arguments);
+ containerToTrackMap.addContainer(this.group, this);
+ },
+
+ /**
+ * Breaks up the list of slices into N rows, each of which is a list of
+ * slices that are non overlapping.
+ */
+ buildSubRows_(slices) {
+ const precisionUnit = this.group.model.intrinsicTimeUnit;
+
+ // This function works by walking through slices by start time.
+ //
+ // The basic idea here is to insert each slice as deep into the subrow
+ // list as it can go such that every subSlice is fully contained by its
+ // parent slice.
+ //
+ // Visually, if we start with this:
+ // 0: [ a ]
+ // 1: [ b ]
+ // 2: [c][d]
+ //
+ // To place this slice:
+ // [e]
+ // We first check row 2's last item, [d]. [e] wont fit into [d] (they dont
+ // even intersect). So we go to row 1. That gives us [b], and [d] wont fit
+ // into that either. So, we go to row 0 and its last slice, [a]. That can
+ // completely contain [e], so that means we should add [e] as a subchild
+ // of [a]. That puts it on row 1, yielding:
+ // 0: [ a ]
+ // 1: [ b ][e]
+ // 2: [c][d]
+ //
+ // If we then get this slice:
+ // [f]
+ // We do the same deepest-to-shallowest walk of the subrows trying to fit
+ // it. This time, it doesn't fit in any open slice. So, we simply append
+ // it to row 0:
+ // 0: [ a ] [f]
+ // 1: [ b ][e]
+ // 2: [c][d]
+ if (!slices.length) return [];
+
+ const ops = [];
+ for (let i = 0; i < slices.length; i++) {
+ if (slices[i].subSlices) {
+ slices[i].subSlices.splice(0,
+ slices[i].subSlices.length);
+ }
+ ops.push(i);
+ }
+
+ ops.sort(function(ix, iy) {
+ const x = slices[ix];
+ const y = slices[iy];
+ if (x.start !== y.start) return x.start - y.start;
+
+ // Elements get inserted into the slices array in order of when the
+ // slices start. Because slices must be properly nested, we break
+ // start-time ties by assuming that the elements appearing earlier in
+ // the slices array (and thus ending earlier) start earlier.
+ return ix - iy;
+ });
+
+ const subRows = [[]];
+ this.badSlices_ = []; // TODO(simonjam): Connect this again.
+
+ for (let i = 0; i < ops.length; i++) {
+ const op = ops[i];
+ const slice = slices[op];
+
+ // Try to fit the slice into the existing subrows.
+ let inserted = false;
+ for (let j = subRows.length - 1; j >= 0; j--) {
+ if (subRows[j].length === 0) continue;
+
+ const insertedSlice = subRows[j][subRows[j].length - 1];
+ if (slice.start < insertedSlice.start) {
+ this.badSlices_.push(slice);
+ inserted = true;
+ }
+ if (insertedSlice.bounds(slice, precisionUnit)) {
+ // Insert it into subRow j + 1.
+ while (subRows.length <= j + 1) {
+ subRows.push([]);
+ }
+ subRows[j + 1].push(slice);
+ if (insertedSlice.subSlices) {
+ insertedSlice.subSlices.push(slice);
+ }
+ inserted = true;
+ break;
+ }
+ }
+ if (inserted) continue;
+
+ // Append it to subRow[0] as a root.
+ subRows[0].push(slice);
+ }
+
+ return subRows;
+ }
+ };
+
+ return {
+ SliceGroupTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_group_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_group_track_test.html
new file mode 100644
index 00000000000..a8b5842f945
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_group_track_test.html
@@ -0,0 +1,299 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/slice_group.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const ProcessTrack = tr.ui.tracks.ProcessTrack;
+ const ThreadTrack = tr.ui.tracks.ThreadTrack;
+ const SliceGroup = tr.model.SliceGroup;
+ const SliceGroupTrack = tr.ui.tracks.SliceGroupTrack;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ test('subRowBuilderBasic', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 2}));
+ const sB = group.pushSlice(newSliceEx({title: 'a', start: 3, duration: 1}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 1);
+ assert.strictEqual(subRows[0].length, 2);
+ assert.deepEqual(subRows[0], [sA, sB]);
+ });
+
+ test('subRowBuilderBasic2', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 4}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 3, duration: 1}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 2);
+ assert.strictEqual(subRows[0].length, 1);
+ assert.strictEqual(subRows[1].length, 1);
+ assert.deepEqual(subRows[0], [sA]);
+ assert.deepEqual(subRows[1], [sB]);
+ });
+
+ test('subRowBuilderNestedExactly', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 1, duration: 4}));
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 4}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 2);
+ assert.strictEqual(subRows[0].length, 1);
+ assert.strictEqual(subRows[1].length, 1);
+ assert.deepEqual(subRows[0], [sB]);
+ assert.deepEqual(subRows[1], [sA]);
+ });
+
+ test('subRowBuilderInstantEvents', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 0}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 2, duration: 0}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 1);
+ assert.strictEqual(subRows[0].length, 2);
+ assert.deepEqual(subRows[0], [sA, sB]);
+ });
+
+ test('subRowBuilderTwoInstantEvents', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 0}));
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 1, duration: 0}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 2);
+ assert.deepEqual(subRows[0], [sA]);
+ assert.deepEqual(subRows[1], [sB]);
+ });
+
+ test('subRowBuilderOutOfOrderAddition', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ // Pattern being tested:
+ // [ a ][ b ]
+ // Where insertion is done backward.
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 3, duration: 1}));
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 2}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 1);
+ assert.strictEqual(subRows[0].length, 2);
+ assert.deepEqual(subRows[0], [sA, sB]);
+ });
+
+ test('subRowBuilderOutOfOrderAddition2', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ // Pattern being tested:
+ // [ a ]
+ // [ b ]
+ // Where insertion is done backward.
+ const sB = group.pushSlice(newSliceEx({title: 'b', start: 3, duration: 1}));
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 5}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 2);
+ assert.strictEqual(subRows[0].length, 1);
+ assert.strictEqual(subRows[1].length, 1);
+ assert.deepEqual(subRows[0], [sA]);
+ assert.deepEqual(subRows[1], [sB]);
+ });
+
+ test('subRowBuilderOnNestedZeroLength', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ // Pattern being tested:
+ // [ a ]
+ // [ b1 ] []<- b2 where b2.duration = 0 and b2.end === a.end.
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 3}));
+ const sB1 = group.pushSlice(newSliceEx(
+ {title: 'b1', start: 1, duration: 2}));
+ const sB2 = group.pushSlice(newSliceEx(
+ {title: 'b2', start: 4, duration: 0}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 2);
+ assert.deepEqual(subRows[0], [sA]);
+ assert.deepEqual(subRows[1], [sB1, sB2]);
+ });
+
+ test('subRowBuilderOnGroup1', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ // Pattern being tested:
+ // [ a ] [ c ]
+ // [ b ]
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 3}));
+ const sB = group.pushSlice(newSliceEx(
+ {title: 'b', start: 1.5, duration: 1}));
+ const sC = group.pushSlice(newSliceEx({title: 'c', start: 5, duration: 0}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+ const subRows = track.subRows;
+
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 2);
+ assert.deepEqual(subRows[0], [sA, sC]);
+ assert.deepEqual(subRows[1], [sB]);
+ });
+
+ test('subRowBuilderOnGroup2', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ // Pattern being tested:
+ // [ a ] [ d ]
+ // [ b ]
+ // [ c ]
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 3}));
+ const sB = group.pushSlice(newSliceEx(
+ {title: 'b', start: 1.5, duration: 1}));
+ const sC = group.pushSlice(newSliceEx(
+ {title: 'c', start: 1.75, duration: 0.5}));
+ const sD = group.pushSlice(newSliceEx(
+ {title: 'c', start: 5, duration: 0.25}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+
+ const subRows = track.subRows;
+ assert.strictEqual(track.badSlices_.length, 0);
+ assert.strictEqual(subRows.length, 3);
+ assert.deepEqual(subRows[0], [sA, sD]);
+ assert.deepEqual(subRows[1], [sB]);
+ assert.deepEqual(subRows[2], [sC]);
+ });
+
+ test('trackFiltering', function() {
+ const m = new tr.Model();
+ const t1 = m.getOrCreateProcess(1).getOrCreateThread(2);
+ const group = t1.sliceGroup;
+
+ const sA = group.pushSlice(newSliceEx({title: 'a', start: 1, duration: 3}));
+ const sB = group.pushSlice(newSliceEx(
+ {title: 'b', start: 1.5, duration: 1}));
+
+ const track = new SliceGroupTrack(new tr.ui.TimelineViewport());
+ track.group = group;
+
+ assert.strictEqual(track.subRows.length, 2);
+ assert.isTrue(track.hasVisibleContent);
+ });
+
+ test('sliceGroupContainerMap', function() {
+ const vp = new tr.ui.TimelineViewport();
+ const containerToTrack = vp.containerToTrackMap;
+ const model = new tr.Model();
+ const process = model.getOrCreateProcess(123);
+ const thread = process.getOrCreateThread(456);
+ const group = new SliceGroup(thread);
+
+ const processTrack = new ProcessTrack(vp);
+ const threadTrack = new ThreadTrack(vp);
+ const groupTrack = new SliceGroupTrack(vp);
+ processTrack.process = process;
+ threadTrack.thread = thread;
+ groupTrack.group = group;
+ Polymer.dom(processTrack).appendChild(threadTrack);
+ Polymer.dom(threadTrack).appendChild(groupTrack);
+
+ assert.strictEqual(processTrack.eventContainer, process);
+ assert.strictEqual(threadTrack.eventContainer, thread);
+ assert.strictEqual(groupTrack.eventContainer, group);
+
+ assert.isUndefined(containerToTrack.getTrackByStableId('123'));
+ assert.isUndefined(containerToTrack.getTrackByStableId('123.456'));
+ assert.isUndefined(
+ containerToTrack.getTrackByStableId('123.456.SliceGroup'));
+
+ vp.modelTrackContainer = {
+ addContainersToTrackMap(containerToTrackMap) {
+ processTrack.addContainersToTrackMap(containerToTrackMap);
+ },
+ addEventListener() {}
+ };
+ vp.rebuildContainerToTrackMap();
+
+ // Check that all tracks call childs' addContainersToTrackMap()
+ // by checking the resulting map.
+ assert.strictEqual(
+ containerToTrack.getTrackByStableId('123'), processTrack);
+ assert.strictEqual(
+ containerToTrack.getTrackByStableId('123.456'), threadTrack);
+ assert.strictEqual(
+ containerToTrack.getTrackByStableId('123.456.SliceGroup'), groupTrack);
+
+ // Check the track's eventContainer getter.
+ assert.strictEqual(processTrack.eventContainer, process);
+ assert.strictEqual(threadTrack.eventContainer, thread);
+ assert.strictEqual(groupTrack.eventContainer, group);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_track.html
new file mode 100644
index 00000000000..1e1386bff66
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_track.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/tracks/rect_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays an array of Slice objects.
+ * @constructor
+ * @extends {RectTrack}
+ */
+ const SliceTrack = tr.ui.b.define(
+ 'slice-track', tr.ui.tracks.RectTrack);
+
+ SliceTrack.prototype = {
+
+ __proto__: tr.ui.tracks.RectTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.RectTrack.prototype.decorate.call(this, viewport);
+ },
+
+ get slices() {
+ return this.rects;
+ },
+
+ set slices(slices) {
+ this.rects = slices;
+ }
+ };
+
+ return {
+ SliceTrack,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_track_test.html
new file mode 100644
index 00000000000..7ba42d3dc79
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/slice_track_test.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/slice.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+<link rel="import" href="/tracing/ui/tracks/slice_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const SliceTrack = tr.ui.tracks.SliceTrack;
+ const ThreadSlice = tr.model.ThreadSlice;
+
+ test('modelMapping', function() {
+ const track = new SliceTrack(new tr.ui.TimelineViewport());
+ const slice = new ThreadSlice('', 'a', 0, 1, {}, 1);
+ track.slices = [slice];
+ const me0 = track.rects[0].modelItem;
+ assert.strictEqual(slice, me0);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/spacing_track.css b/chromium/third_party/catapult/tracing/tracing/ui/tracks/spacing_track.css
new file mode 100644
index 00000000000..094eee0862d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/spacing_track.css
@@ -0,0 +1,7 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+.spacing-track {
+ height: 4px;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/spacing_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/spacing_track.html
new file mode 100644
index 00000000000..a321066daa2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/spacing_track.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet" href="/tracing/ui/tracks/spacing_track.css">
+
+<link rel="import" href="/tracing/ui/base/heading.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track used to provide whitespace between the tracks above and below it.
+ *
+ * @constructor
+ * @extends {tr.ui.tracks.Track}
+ */
+ const SpacingTrack = tr.ui.b.define('spacing-track', tr.ui.tracks.Track);
+
+ SpacingTrack.prototype = {
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('spacing-track');
+
+ this.heading_ = document.createElement('tr-ui-b-heading');
+ Polymer.dom(this).appendChild(this.heading_);
+ },
+
+ addAllEventsMatchingFilterToSelection(filter, selection) {
+ }
+ };
+
+ return {
+ SpacingTrack,
+ };
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/stacked_bars_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/stacked_bars_track.html
new file mode 100644
index 00000000000..7a292c04113
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/stacked_bars_track.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/heading.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays traces as stacked bars.
+ * @constructor
+ * @extends {Track}
+ */
+ const StackedBarsTrack = tr.ui.b.define(
+ 'stacked-bars-track', tr.ui.tracks.Track);
+
+ StackedBarsTrack.prototype = {
+
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('stacked-bars-track');
+ this.objectInstance_ = null;
+
+ this.heading_ = document.createElement('tr-ui-b-heading');
+ Polymer.dom(this).appendChild(this.heading_);
+ },
+
+ set heading(heading) {
+ this.heading_.heading = heading;
+ },
+
+ get heading() {
+ return this.heading_.heading;
+ },
+
+ set tooltip(tooltip) {
+ this.heading_.tooltip = tooltip;
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ const objectSnapshots = this.objectInstance_.snapshots;
+ objectSnapshots.forEach(function(obj) {
+ eventToTrackMap.addEvent(obj, this);
+ }, this);
+ },
+
+ /**
+ * Used to hit-test clicks in the graph.
+ */
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ function onSnapshot(snapshot) {
+ selection.push(snapshot);
+ }
+
+ const snapshots = this.objectInstance_.snapshots;
+ const maxBounds = this.objectInstance_.parent.model.bounds.max;
+
+ tr.b.iterateOverIntersectingIntervals(
+ snapshots,
+ function(x) { return x.ts; },
+ function(x, i) {
+ if (i === snapshots.length - 1) {
+ if (snapshots.length === 1) {
+ return maxBounds;
+ }
+
+ return snapshots[i].ts - snapshots[i - 1].ts;
+ }
+
+ return snapshots[i + 1].ts - snapshots[i].ts;
+ },
+ loWX, hiWX,
+ onSnapshot);
+ },
+
+ /**
+ * Add the item to the left or right of the provided item, if any, to the
+ * selection.
+ * @param {slice} The current slice.
+ * @param {Number} offset Number of slices away from the object to look.
+ * @param {Selection} selection The selection to add an event to,
+ * if found.
+ * @return {boolean} Whether an event was found.
+ * @private
+ */
+ addEventNearToProvidedEventToSelection(event, offset, selection) {
+ if (!(event instanceof tr.model.ObjectSnapshot)) {
+ throw new Error('Unrecognized event');
+ }
+ const objectSnapshots = this.objectInstance_.snapshots;
+ const index = objectSnapshots.indexOf(event);
+ const newIndex = index + offset;
+ if (newIndex >= 0 && newIndex < objectSnapshots.length) {
+ selection.push(objectSnapshots[newIndex]);
+ return true;
+ }
+ return false;
+ },
+
+ addAllEventsMatchingFilterToSelection(filter, selection) {
+ },
+
+ addClosestEventToSelection(worldX, worldMaxDist, loY, hiY,
+ selection) {
+ const snapshot = tr.b.findClosestElementInSortedArray(
+ this.objectInstance_.snapshots,
+ function(x) { return x.ts; },
+ worldX,
+ worldMaxDist);
+
+ if (!snapshot) return;
+
+ selection.push(snapshot);
+ }
+ };
+
+ return {
+ StackedBarsTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track.css b/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track.css
new file mode 100644
index 00000000000..4e063bbad48
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track.css
@@ -0,0 +1,10 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.thread-track {
+ flex-direction: column;
+ display: flex;
+ position: relative;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track.html
new file mode 100644
index 00000000000..c6ea8fa576c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track.html
@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="stylesheet" href="/tracing/ui/tracks/thread_track.css">
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/filter.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/async_slice_group_track.html">
+<link rel="import" href="/tracing/ui/tracks/container_track.html">
+<link rel="import" href="/tracing/ui/tracks/sample_track.html">
+<link rel="import" href="/tracing/ui/tracks/slice_group_track.html">
+<link rel="import" href="/tracing/ui/tracks/slice_track.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * Visualizes a Thread using a series of SliceTracks.
+ * @constructor
+ */
+ const ThreadTrack = tr.ui.b.define('thread-track',
+ tr.ui.tracks.ContainerTrack);
+ ThreadTrack.prototype = {
+ __proto__: tr.ui.tracks.ContainerTrack.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('thread-track');
+ this.heading_ = document.createElement('tr-ui-b-heading');
+ },
+
+ get thread() {
+ return this.thread_;
+ },
+
+ set thread(thread) {
+ this.thread_ = thread;
+ this.updateContents_();
+ },
+
+ get hasVisibleContent() {
+ return this.tracks_.length > 0;
+ },
+
+ get hasSlices() {
+ return this.thread_.asyncSliceGroup.length > 0 ||
+ this.thread_.sliceGroup.length > 0;
+ },
+
+ get hasTimeSlices() {
+ return this.thread_.timeSlices;
+ },
+
+ get eventContainer() {
+ return this.thread;
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ tr.ui.tracks.ContainerTrack.prototype.addContainersToTrackMap.apply(
+ this, arguments);
+ containerToTrackMap.addContainer(this.thread, this);
+ },
+
+ updateContents_() {
+ this.detach();
+
+ if (!this.thread_) return;
+
+ this.heading_.heading = this.thread_.userFriendlyName;
+ this.heading_.tooltip = this.thread_.userFriendlyDetails;
+
+ if (this.thread_.asyncSliceGroup.length) {
+ this.appendAsyncSliceTracks_();
+ }
+
+ this.appendThreadSamplesTracks_();
+
+ let needsHeading = false;
+ if (this.thread_.timeSlices) {
+ const timeSlicesTrack = new tr.ui.tracks.SliceTrack(this.viewport);
+ timeSlicesTrack.heading = '';
+ timeSlicesTrack.height = tr.ui.b.THIN_SLICE_HEIGHT + 'px';
+ timeSlicesTrack.slices = this.thread_.timeSlices;
+ if (timeSlicesTrack.hasVisibleContent) {
+ needsHeading = true;
+ Polymer.dom(this).appendChild(timeSlicesTrack);
+ }
+ }
+
+ if (this.thread_.sliceGroup.length) {
+ const track = new tr.ui.tracks.SliceGroupTrack(this.viewport);
+ track.heading = this.thread_.userFriendlyName;
+ track.tooltip = this.thread_.userFriendlyDetails;
+ track.group = this.thread_.sliceGroup;
+ if (track.hasVisibleContent) {
+ needsHeading = false;
+ Polymer.dom(this).appendChild(track);
+ }
+ }
+
+ if (needsHeading) {
+ Polymer.dom(this).appendChild(this.heading_);
+ }
+ },
+
+ appendAsyncSliceTracks_() {
+ const subGroups = this.thread_.asyncSliceGroup.viewSubGroups;
+ // TODO(kraynov): Support nested sub-groups.
+ subGroups.forEach(function(subGroup) {
+ const asyncTrack = new tr.ui.tracks.AsyncSliceGroupTrack(this.viewport);
+ asyncTrack.group = subGroup;
+ asyncTrack.heading = subGroup.title;
+ if (asyncTrack.hasVisibleContent) {
+ Polymer.dom(this).appendChild(asyncTrack);
+ }
+ }, this);
+ },
+
+ appendThreadSamplesTracks_() {
+ const threadSamples = this.thread_.samples;
+ if (threadSamples === undefined || threadSamples.length === 0) {
+ return;
+ }
+ const samplesByTitle = {};
+ threadSamples.forEach(function(sample) {
+ if (samplesByTitle[sample.title] === undefined) {
+ samplesByTitle[sample.title] = [];
+ }
+ samplesByTitle[sample.title].push(sample);
+ });
+
+ const sampleTitles = Object.keys(samplesByTitle);
+ sampleTitles.sort();
+
+ sampleTitles.forEach(function(sampleTitle) {
+ const samples = samplesByTitle[sampleTitle];
+ const samplesTrack = new tr.ui.tracks.SampleTrack(this.viewport);
+ samplesTrack.group = this.thread_;
+ samplesTrack.samples = samples;
+ samplesTrack.heading = this.thread_.userFriendlyName + ': ' +
+ sampleTitle;
+ samplesTrack.tooltip = this.thread_.userFriendlyDetails;
+ samplesTrack.selectionGenerator = function() {
+ const selection = new tr.model.EventSet();
+ for (let i = 0; i < samplesTrack.samples.length; i++) {
+ selection.push(samplesTrack.samples[i]);
+ }
+ return selection;
+ };
+ Polymer.dom(this).appendChild(samplesTrack);
+ }, this);
+ },
+
+ collapsedDidChange(collapsed) {
+ if (collapsed) {
+ let h = parseInt(this.tracks[0].height);
+ for (let i = 0; i < this.tracks.length; ++i) {
+ if (h > 2) {
+ this.tracks[i].height = Math.floor(h) + 'px';
+ } else {
+ this.tracks[i].style.display = 'none';
+ }
+ h = h * 0.5;
+ }
+ } else {
+ for (let i = 0; i < this.tracks.length; ++i) {
+ this.tracks[i].height = this.tracks[0].height;
+ this.tracks[i].style.display = '';
+ }
+ }
+ }
+ };
+
+ return {
+ ThreadTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track_test.html
new file mode 100644
index 00000000000..1ece1aa3f93
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/thread_track_test.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/model/instant_event.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/timeline_track_view.html">
+<link rel="import" href="/tracing/ui/tracks/thread_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const HighlightInstantEvent = tr.model.ThreadHighlightInstantEvent;
+ const Process = tr.model.Process;
+ const EventSet = tr.model.EventSet;
+ const StackFrame = tr.model.StackFrame;
+ const Sample = tr.model.Sample;
+ const Thread = tr.model.Thread;
+ const ThreadSlice = tr.model.ThreadSlice;
+ const ThreadTrack = tr.ui.tracks.ThreadTrack;
+ const Viewport = tr.ui.TimelineViewport;
+ const newAsyncSlice = tr.c.TestUtils.newAsyncSlice;
+ const newAsyncSliceNamed = tr.c.TestUtils.newAsyncSliceNamed;
+ const newSliceEx = tr.c.TestUtils.newSliceEx;
+
+ test('selectionHitTestingWithThreadTrack', function() {
+ const model = new tr.Model();
+ const p1 = model.getOrCreateProcess(1);
+ const t1 = p1.getOrCreateThread(1);
+ t1.sliceGroup.pushSlice(new ThreadSlice('', 'a', 0, 1, {}, 4));
+ t1.sliceGroup.pushSlice(new ThreadSlice('', 'b', 0, 5.1, {}, 4));
+
+ const testEl = document.createElement('div');
+ Polymer.dom(testEl).appendChild(
+ tr.ui.b.createScopedStyle('heading { width: 100px; }'));
+ testEl.style.width = '600px';
+
+ const viewport = new Viewport(testEl);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(testEl).appendChild(drawingContainer);
+
+ const track = new ThreadTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ drawingContainer.updateCanvasSizeIfNeeded_();
+ track.thread = t1;
+
+ const y = track.getBoundingClientRect().top;
+ const h = track.getBoundingClientRect().height;
+ const wW = 10;
+ const vW = drawingContainer.canvas.getBoundingClientRect().width;
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.xSetWorldBounds(0, wW, vW);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ let selection = new EventSet();
+ const x = (1.5 / wW) * vW;
+ track.addIntersectingEventsInRangeToSelection(
+ x, x + 1, y, y + 1, selection);
+ assert.isTrue(selection.equals(
+ new EventSet([t1.sliceGroup.slices[0], t1.sliceGroup.slices[1]])));
+
+ selection = new EventSet();
+ track.addIntersectingEventsInRangeToSelection(
+ (1.5 / wW) * vW, (1.8 / wW) * vW,
+ y, y + h, selection);
+ assert.isTrue(selection.equals(
+ new EventSet([t1.sliceGroup.slices[0], t1.sliceGroup.slices[1]])));
+ });
+
+ test('filterThreadSlices', function() {
+ const model = new tr.Model();
+ const thread = new Thread(new Process(model, 7), 1);
+ thread.sliceGroup.pushSlice(newSliceEx(
+ {title: 'a', start: 0, duration: 0}));
+ thread.asyncSliceGroup.push(newAsyncSliceNamed('a', 0, 5, thread, thread));
+ const t = new ThreadTrack(new tr.ui.TimelineViewport());
+ t.thread = thread;
+
+ assert.strictEqual(t.tracks_.length, 2);
+ assert.instanceOf(t.tracks_[0], tr.ui.tracks.AsyncSliceGroupTrack);
+ assert.instanceOf(t.tracks_[1], tr.ui.tracks.SliceGroupTrack);
+ });
+
+ test('sampleThreadSlices', function() {
+ let thread;
+ let cpu;
+ const model = tr.c.TestUtils.newModelWithEvents([], {
+ shiftWorldToZero: false,
+ pruneContainers: false,
+ customizeModelCallback(model) {
+ cpu = model.kernel.getOrCreateCpu(1);
+ thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+
+ const nodeA = tr.c.TestUtils.newProfileNode(model, 'a');
+ const nodeB = tr.c.TestUtils.newProfileNode(model, 'b', nodeA);
+ const nodeC = tr.c.TestUtils.newProfileNode(model, 'c', nodeB);
+ const nodeD = tr.c.TestUtils.newProfileNode(model, 'd', nodeA);
+
+ model.samples.push(new Sample(10, 'instructions_retired', nodeC, thread,
+ undefined, 10));
+ model.samples.push(new Sample(20, 'instructions_retired', nodeB, thread,
+ undefined, 10));
+ model.samples.push(new Sample(30, 'instructions_retired', nodeB, thread,
+ undefined, 10));
+ model.samples.push(new Sample(40, 'instructions_retired', nodeD, thread,
+ undefined, 10));
+
+ model.samples.push(new Sample(25, 'page_fault', nodeB, thread,
+ undefined, 10));
+ model.samples.push(new Sample(35, 'page_fault', nodeD, thread,
+ undefined, 10));
+ }
+ });
+
+ const t = new ThreadTrack(new tr.ui.TimelineViewport());
+ t.thread = thread;
+ assert.strictEqual(t.tracks_.length, 2);
+
+ // Instructions retired
+ const t0 = t.tracks_[0];
+ assert.notEqual(t0.heading.indexOf('instructions_retired'), -1);
+ assert.instanceOf(t0, tr.ui.tracks.SampleTrack);
+ assert.strictEqual(t0.samples.length, 4);
+ t0.samples.forEach(function(s) {
+ assert.instanceOf(s, tr.model.Sample);
+ });
+
+ // page_fault
+ const t1 = t.tracks_[1];
+ assert.notEqual(t1.heading.indexOf('page_fault'), -1);
+ assert.instanceOf(t1, tr.ui.tracks.SampleTrack);
+ assert.strictEqual(t1.samples.length, 2);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/track.css b/chromium/third_party/catapult/tracing/tracing/ui/tracks/track.css
new file mode 100644
index 00000000000..3d56eef5b8d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/track.css
@@ -0,0 +1,33 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.track-button {
+ background-color: rgba(255, 255, 255, 0.5);
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ color: rgba(0,0,0,0.2);
+ font-size: 10px;
+ height: 12px;
+ text-align: center;
+ width: 12px;
+}
+
+.track-button:hover {
+ background-color: rgba(255, 255, 255, 1.0);
+ border: 1px solid rgba(0, 0, 0, 0.5);
+ box-shadow: 0 0 .05em rgba(0, 0, 0, 0.4);
+ color: rgba(0, 0, 0, 1);
+}
+
+.track-close-button {
+ left: 2px;
+ position: absolute;
+ top: 2px;
+}
+
+.track-collapse-button {
+ left: 3px;
+ position: absolute;
+ top: 2px;
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/track.html
new file mode 100644
index 00000000000..fccad427740
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/track.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="stylesheet" href="/tracing/ui/tracks/track.css">
+
+<link rel="import" href="/tracing/ui/base/container_that_decorates_its_children.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * The base class for all tracks, which render data into a provided div.
+ * @constructor
+ */
+ const Track = tr.ui.b.define('track',
+ tr.ui.b.ContainerThatDecoratesItsChildren);
+ Track.prototype = {
+ __proto__: tr.ui.b.ContainerThatDecoratesItsChildren.prototype,
+
+ decorate(viewport) {
+ tr.ui.b.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);
+ if (viewport === undefined) {
+ throw new Error('viewport is required when creating a Track.');
+ }
+
+ this.viewport_ = viewport;
+ Polymer.dom(this).classList.add('track');
+ },
+
+ get viewport() {
+ return this.viewport_;
+ },
+
+ get drawingContainer() {
+ if (this instanceof tr.ui.tracks.DrawingContainer) return this;
+ let cur = this.parentElement;
+ while (cur) {
+ if (cur instanceof tr.ui.tracks.DrawingContainer) return cur;
+ cur = cur.parentElement;
+ }
+ return undefined;
+ },
+
+ get eventContainer() {
+ },
+
+ invalidateDrawingContainer() {
+ const dc = this.drawingContainer;
+ if (dc) dc.invalidate();
+ },
+
+ context() {
+ // This is a little weird here, but we have to be able to walk up the
+ // parent tree to get the context.
+ if (!Polymer.dom(this).parentNode) return undefined;
+
+ if (!Polymer.dom(this).parentNode.context) {
+ throw new Error('Parent container does not support context() method.');
+ }
+ return Polymer.dom(this).parentNode.context();
+ },
+
+ decorateChild_(childTrack) {
+ },
+
+ undecorateChild_(childTrack) {
+ if (childTrack.detach) {
+ childTrack.detach();
+ }
+ },
+
+ updateContents_() {
+ },
+
+ /**
+ * Wrapper function around draw() that performs transformations on the
+ * context necessary for the track's contents to be drawn in the right place
+ * given the current pan and zoom.
+ */
+ drawTrack(type) {
+ const ctx = this.context();
+
+ const pixelRatio = window.devicePixelRatio || 1;
+ const bounds = this.getBoundingClientRect();
+ const canvasBounds = ctx.canvas.getBoundingClientRect();
+
+ ctx.save();
+ ctx.translate(0, pixelRatio * (bounds.top - canvasBounds.top));
+
+ const dt = this.viewport.currentDisplayTransform;
+ const viewLWorld = dt.xViewToWorld(0);
+ const viewRWorld = dt.xViewToWorld(canvasBounds.width * pixelRatio);
+ const viewHeight = bounds.height * pixelRatio;
+
+ this.draw(type, viewLWorld, viewRWorld, viewHeight);
+ ctx.restore();
+ },
+
+ draw(type, viewLWorld, viewRWorld, viewHeight) {
+ },
+
+ addEventsToTrackMap(eventToTrackMap) {
+ },
+
+ addContainersToTrackMap(containerToTrackMap) {
+ },
+
+ addIntersectingEventsInRangeToSelection(
+ loVX, hiVX, loVY, hiVY, selection) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ const dt = this.viewport.currentDisplayTransform;
+ const viewPixWidthWorld = dt.xViewVectorToWorld(1);
+ const loWX = dt.xViewToWorld(loVX * pixelRatio);
+ const hiWX = dt.xViewToWorld(hiVX * pixelRatio);
+
+ const clientRect = this.getBoundingClientRect();
+ const a = Math.max(loVY, clientRect.top);
+ const b = Math.min(hiVY, clientRect.bottom);
+ if (a > b) return;
+
+ this.addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection);
+ },
+
+ addIntersectingEventsInRangeToSelectionInWorldSpace(
+ loWX, hiWX, viewPixWidthWorld, selection) {
+ },
+
+ /**
+ * Gets implemented by supporting track types. The method adds the event
+ * closest to worldX to the selection.
+ *
+ * @param {number} worldX The position that is looked for.
+ * @param {number} worldMaxDist The maximum distance allowed from worldX to
+ * the event.
+ * @param {number} loY Lower Y bound of the search interval in view space.
+ * @param {number} hiY Upper Y bound of the search interval in view space.
+ * @param {Selection} selection Selection to which to add hits.
+ */
+ addClosestEventToSelection(
+ worldX, worldMaxDist, loY, hiY, selection) {
+ },
+
+ addClosestInstantEventToSelection(instantEvents, worldX,
+ worldMaxDist, selection) {
+ const instantEvent = tr.b.findClosestElementInSortedArray(
+ instantEvents,
+ function(x) { return x.start; },
+ worldX,
+ worldMaxDist);
+
+ if (!instantEvent) return;
+
+ selection.push(instantEvent);
+ }
+ };
+
+ return {
+ Track,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/x_axis_track.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/x_axis_track.html
new file mode 100644
index 00000000000..620a35c8040
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/x_axis_track.html
@@ -0,0 +1,309 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/draw_helpers.html">
+<link rel="import" href="/tracing/ui/base/heading.html">
+<link rel="import" href="/tracing/ui/base/ui.html">
+<link rel="import" href="/tracing/ui/tracks/track.html">
+
+<style>
+.x-axis-track {
+ height: 12px;
+}
+
+.x-axis-track.tall-mode {
+ height: 30px;
+}
+</style>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.ui.tracks', function() {
+ /**
+ * A track that displays the x-axis.
+ * @constructor
+ * @extends {Track}
+ */
+ const XAxisTrack = tr.ui.b.define('x-axis-track', tr.ui.tracks.Track);
+
+ XAxisTrack.prototype = {
+ __proto__: tr.ui.tracks.Track.prototype,
+
+ decorate(viewport) {
+ tr.ui.tracks.Track.prototype.decorate.call(this, viewport);
+ Polymer.dom(this).classList.add('x-axis-track');
+ this.strings_secs_ = [];
+ this.strings_msecs_ = [];
+ this.strings_usecs_ = [];
+ this.strings_nsecs_ = [];
+
+ this.viewportChange_ = this.viewportChange_.bind(this);
+ viewport.addEventListener('change', this.viewportChange_);
+
+ const heading = document.createElement('tr-ui-b-heading');
+ heading.arrowVisible = false;
+ Polymer.dom(this).appendChild(heading);
+ },
+
+ detach() {
+ tr.ui.tracks.Track.prototype.detach.call(this);
+ this.viewport.removeEventListener('change',
+ this.viewportChange_);
+ },
+
+ viewportChange_() {
+ if (this.viewport.interestRange.isEmpty) {
+ Polymer.dom(this).classList.remove('tall-mode');
+ } else {
+ Polymer.dom(this).classList.add('tall-mode');
+ }
+ },
+
+ draw(type, viewLWorld, viewRWorld, viewHeight) {
+ switch (type) {
+ case tr.ui.tracks.DrawType.GRID:
+ this.drawGrid_(viewLWorld, viewRWorld);
+ break;
+ case tr.ui.tracks.DrawType.MARKERS:
+ this.drawMarkers_(viewLWorld, viewRWorld);
+ break;
+ }
+ },
+
+ drawGrid_(viewLWorld, viewRWorld) {
+ const ctx = this.context();
+ const pixelRatio = window.devicePixelRatio || 1;
+
+ const canvasBounds = ctx.canvas.getBoundingClientRect();
+ const trackBounds = this.getBoundingClientRect();
+ const width = canvasBounds.width * pixelRatio;
+ const height = trackBounds.height * pixelRatio;
+
+ const hasInterestRange = !this.viewport.interestRange.isEmpty;
+
+ const xAxisHeightPx = hasInterestRange ? (height * 2) / 5 : height;
+
+ const vp = this.viewport;
+ const dt = vp.currentDisplayTransform;
+
+ vp.updateMajorMarkData(viewLWorld, viewRWorld);
+ const majorMarkDistanceWorld = vp.majorMarkWorldPositions.length > 1 ?
+ vp.majorMarkWorldPositions[1] - vp.majorMarkWorldPositions[0] : 0;
+
+ const numTicksPerMajor = 5;
+ const minorMarkDistanceWorld = majorMarkDistanceWorld / numTicksPerMajor;
+ const minorMarkDistancePx = dt.xWorldVectorToView(minorMarkDistanceWorld);
+
+ const minorTickHeight = Math.floor(xAxisHeightPx * 0.25);
+
+ ctx.save();
+
+ ctx.lineWidth = Math.round(pixelRatio);
+
+ // Apply subpixel translate to get crisp lines.
+ // http://www.mobtowers.com/html5-canvas-crisp-lines-every-time/
+ const crispLineCorrection = (ctx.lineWidth % 2) / 2;
+ ctx.translate(crispLineCorrection, -crispLineCorrection);
+
+ ctx.fillStyle = 'rgb(0, 0, 0)';
+ ctx.strokeStyle = 'rgb(0, 0, 0)';
+ ctx.textAlign = 'left';
+ ctx.textBaseline = 'top';
+
+ ctx.font = (9 * pixelRatio) + 'px sans-serif';
+
+ const tickLabels = [];
+ ctx.beginPath();
+ for (let i = 0; i < vp.majorMarkWorldPositions.length; i++) {
+ const curXWorld = vp.majorMarkWorldPositions[i];
+ const curXView = dt.xWorldToView(curXWorld);
+ const displayText = vp.majorMarkUnit.format(
+ curXWorld, {deltaValue: majorMarkDistanceWorld});
+ ctx.fillText(displayText, curXView + (2 * pixelRatio), 0);
+
+ // Draw major mark.
+ tr.ui.b.drawLine(ctx, curXView, 0, curXView, xAxisHeightPx);
+
+ // Draw minor marks.
+ if (minorMarkDistancePx) {
+ for (let j = 1; j < numTicksPerMajor; ++j) {
+ const xView = Math.floor(curXView + minorMarkDistancePx * j);
+ tr.ui.b.drawLine(ctx,
+ xView, xAxisHeightPx - minorTickHeight,
+ xView, xAxisHeightPx);
+ }
+ }
+ }
+
+ // Draw bottom bar.
+ ctx.strokeStyle = 'rgb(0, 0, 0)';
+ tr.ui.b.drawLine(ctx, 0, height, width, height);
+ ctx.stroke();
+
+ // Give distance between directly adjacent markers.
+ if (!hasInterestRange) return;
+
+ // Draw middle bar.
+ tr.ui.b.drawLine(ctx, 0, xAxisHeightPx, width, xAxisHeightPx);
+ ctx.stroke();
+
+ // Distance Variables.
+ let displayDistance;
+ const displayTextColor = 'rgb(0,0,0)';
+
+ // Arrow Variables.
+ const arrowSpacing = 10 * pixelRatio;
+ const arrowColor = 'rgb(128,121,121)';
+ const arrowPosY = xAxisHeightPx * 1.75;
+ const arrowWidthView = 3 * pixelRatio;
+ const arrowLengthView = 10 * pixelRatio;
+ const spaceForArrowsView = 2 * (arrowWidthView + arrowSpacing);
+
+ ctx.textBaseline = 'middle';
+ ctx.font = (14 * pixelRatio) + 'px sans-serif';
+ const textPosY = arrowPosY;
+
+ const interestRange = vp.interestRange;
+
+ // If the range is zero, draw it's min timestamp next to the line.
+ if (interestRange.range === 0) {
+ const markerWorld = interestRange.min;
+ const markerView = dt.xWorldToView(markerWorld);
+
+ const textToDraw = vp.majorMarkUnit.format(markerWorld);
+ let textLeftView = markerView + 4 * pixelRatio;
+ const textWidthView = ctx.measureText(textToDraw).width;
+
+ // Put text to the left in case it gets cut off.
+ if (textLeftView + textWidthView > width) {
+ textLeftView = markerView - 4 * pixelRatio - textWidthView;
+ }
+
+ ctx.fillStyle = displayTextColor;
+ ctx.fillText(textToDraw, textLeftView, textPosY);
+ return;
+ }
+
+ const leftMarker = interestRange.min;
+ const rightMarker = interestRange.max;
+
+ const leftMarkerView = dt.xWorldToView(leftMarker);
+ const rightMarkerView = dt.xWorldToView(rightMarker);
+
+ const distanceBetweenMarkers = interestRange.range;
+ const distanceBetweenMarkersView =
+ dt.xWorldVectorToView(distanceBetweenMarkers);
+ const positionInMiddleOfMarkersView =
+ leftMarkerView + (distanceBetweenMarkersView / 2);
+
+ const textToDraw = vp.majorMarkUnit.format(distanceBetweenMarkers);
+ const textWidthView = ctx.measureText(textToDraw).width;
+ const spaceForArrowsAndTextView =
+ textWidthView + spaceForArrowsView + arrowSpacing;
+
+ // Set text positions.
+ let textLeftView = positionInMiddleOfMarkersView - textWidthView / 2;
+ const textRightView = textLeftView + textWidthView;
+
+ if (spaceForArrowsAndTextView > distanceBetweenMarkersView) {
+ // Print the display distance text right of the 2 markers.
+ textLeftView = rightMarkerView + 2 * arrowSpacing;
+
+ // Put text to the left in case it gets cut off.
+ if (textLeftView + textWidthView > width) {
+ textLeftView = leftMarkerView - 2 * arrowSpacing - textWidthView;
+ }
+
+ ctx.fillStyle = displayTextColor;
+ ctx.fillText(textToDraw, textLeftView, textPosY);
+
+ // Draw the arrows pointing from outside in and a line in between.
+ ctx.strokeStyle = arrowColor;
+ ctx.beginPath();
+ tr.ui.b.drawLine(ctx, leftMarkerView, arrowPosY, rightMarkerView,
+ arrowPosY);
+ ctx.stroke();
+
+ ctx.fillStyle = arrowColor;
+ tr.ui.b.drawArrow(ctx,
+ leftMarkerView - 1.5 * arrowSpacing, arrowPosY,
+ leftMarkerView, arrowPosY,
+ arrowLengthView, arrowWidthView);
+ tr.ui.b.drawArrow(ctx,
+ rightMarkerView + 1.5 * arrowSpacing, arrowPosY,
+ rightMarkerView, arrowPosY,
+ arrowLengthView, arrowWidthView);
+ } else if (spaceForArrowsView <= distanceBetweenMarkersView) {
+ let leftArrowStart;
+ let rightArrowStart;
+ if (spaceForArrowsAndTextView <= distanceBetweenMarkersView) {
+ // Print the display distance text.
+ ctx.fillStyle = displayTextColor;
+ ctx.fillText(textToDraw, textLeftView, textPosY);
+
+ leftArrowStart = textLeftView - arrowSpacing;
+ rightArrowStart = textRightView + arrowSpacing;
+ } else {
+ leftArrowStart = positionInMiddleOfMarkersView;
+ rightArrowStart = positionInMiddleOfMarkersView;
+ }
+
+ // Draw the arrows pointing inside out.
+ ctx.strokeStyle = arrowColor;
+ ctx.fillStyle = arrowColor;
+ tr.ui.b.drawArrow(ctx,
+ leftArrowStart, arrowPosY,
+ leftMarkerView, arrowPosY,
+ arrowLengthView, arrowWidthView);
+ tr.ui.b.drawArrow(ctx,
+ rightArrowStart, arrowPosY,
+ rightMarkerView, arrowPosY,
+ arrowLengthView, arrowWidthView);
+ }
+
+ ctx.restore();
+ },
+
+ drawMarkers_(viewLWorld, viewRWorld) {
+ const pixelRatio = window.devicePixelRatio || 1;
+ const trackBounds = this.getBoundingClientRect();
+ const viewHeight = trackBounds.height * pixelRatio;
+
+ if (!this.viewport.interestRange.isEmpty) {
+ this.viewport.interestRange.draw(this.context(),
+ viewLWorld, viewRWorld, viewHeight);
+ }
+ },
+
+ /**
+ * Adds items intersecting the given range to a selection.
+ * @param {number} loVX Lower X bound of the interval to search, in
+ * viewspace.
+ * @param {number} hiVX Upper X bound of the interval to search, in
+ * viewspace.
+ * @param {number} loVY Lower Y bound of the interval to search, in
+ * viewspace.
+ * @param {number} hiVY Upper Y bound of the interval to search, in
+ * viewspace.
+ * @param {Selection} selection Selection to which to add results.
+ */
+ addIntersectingEventsInRangeToSelection(
+ loVX, hiVX, loY, hiY, selection) {
+ // Does nothing. There's nothing interesting to pick on the xAxis
+ // track.
+ },
+
+ addAllEventsMatchingFilterToSelection(filter, selection) {
+ }
+ };
+
+ return {
+ XAxisTrack,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/tracks/x_axis_track_test.html b/chromium/third_party/catapult/tracing/tracing/ui/tracks/x_axis_track_test.html
new file mode 100644
index 00000000000..459c05cd122
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/tracks/x_axis_track_test.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/ui/timeline_viewport.html">
+<link rel="import" href="/tracing/ui/tracks/drawing_container.html">
+<link rel="import" href="/tracing/ui/tracks/x_axis_track.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const div = document.createElement('div');
+
+ const viewport = new tr.ui.TimelineViewport(div);
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = tr.ui.tracks.XAxisTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ this.addHTMLOutput(div);
+
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.setPanAndScale(0, track.clientWidth / 1000);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ test('instantiate_interestRange', function() {
+ const div = document.createElement('div');
+
+ const viewport = new tr.ui.TimelineViewport(div);
+ viewport.interestRange.min = 300;
+ viewport.interestRange.max = 300;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = tr.ui.tracks.XAxisTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ this.addHTMLOutput(div);
+
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.setPanAndScale(0, track.clientWidth / 1000);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ test('instantiate_singlePointInterestRange', function() {
+ const div = document.createElement('div');
+
+ const viewport = new tr.ui.TimelineViewport(div);
+ viewport.interestRange.min = 300;
+ viewport.interestRange.max = 400;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const track = tr.ui.tracks.XAxisTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ this.addHTMLOutput(div);
+
+ drawingContainer.invalidate();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.setPanAndScale(0, track.clientWidth / 1000);
+ track.viewport.setDisplayTransformImmediately(dt);
+ });
+
+ function testTimeMode(mode, testInstance, numDigits, opt_unit) {
+ const div = document.createElement('div');
+
+ const viewport = new tr.ui.TimelineViewport(div);
+ viewport.timeMode = mode;
+ const drawingContainer = new tr.ui.tracks.DrawingContainer(viewport);
+ Polymer.dom(div).appendChild(drawingContainer);
+
+ const trackContext = drawingContainer.ctx_;
+ const oldFillText = trackContext.fillText;
+ const fillTextText = [];
+ const fillTextThis = [];
+ trackContext.fillText = function(text, xPos, yPos) {
+ fillTextText.push(text);
+ fillTextThis.push(this);
+ return oldFillText.call(this, text, xPos, yPos);
+ };
+
+ const track = tr.ui.tracks.XAxisTrack(viewport);
+ Polymer.dom(drawingContainer).appendChild(track);
+ testInstance.addHTMLOutput(div);
+
+ drawingContainer.invalidate();
+ tr.b.forceAllPendingTasksToRunForTest();
+
+ const dt = new tr.ui.TimelineDisplayTransform();
+ dt.setPanAndScale(0, track.clientWidth / 1000);
+ track.viewport.setDisplayTransformImmediately(dt);
+
+ const formatter =
+ new Intl.NumberFormat(undefined, { numDigits, numDigits });
+ const formatFunction = function(value) {
+ let valueString = value.toLocaleString(undefined, {
+ minimumFractionDigits: 0,
+ maximumFractionDigits: numDigits
+ });
+ if (opt_unit) valueString += opt_unit;
+ return valueString;
+ };
+ const expectedText = viewport.majorMarkWorldPositions.map(
+ formatFunction);
+ assert.strictEqual(fillTextText.length, fillTextThis.length);
+ for (let i = 0; i < fillTextText.length; i++) {
+ assert.deepEqual(fillTextText[i], expectedText[i]);
+ assert.strictEqual(fillTextThis[i], trackContext);
+ }
+ }
+
+ test('instantiate_timeModeMs', function() {
+ testTimeMode(tr.ui.TimelineViewport.TimeMode.TIME_IN_MS,
+ this, 3, ' ms');
+ });
+
+ test('instantiate_timeModeRevisions', function() {
+ testTimeMode(tr.ui.TimelineViewport.TimeMode.REVISIONS, this, 0);
+ });
+});
+</script>
+
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/view_specific_brushing_state.html b/chromium/third_party/catapult/tracing/tracing/ui/view_specific_brushing_state.html
new file mode 100644
index 00000000000..75b616332c2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/view_specific_brushing_state.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+
+<!--
+This element handles storing and retrieving the brushing state of arbitrary
+views (e.g. analysis sub-views). An element can use it by instantiating it and
+appending it to itself:
+
+ <div id="some-view-with-specific-brushing-state">
+ <tr-ui-b-view-specific-brushing-state view-id="unique-view-identifier">
+ </tr-ui-b-view-specific-brushing-state>
+ ... other child elements ...
+ </div>
+
+The state can then be retrieved from and pushed to the state element as
+follows:
+
+ newStateElement.set(state);
+ state = newStateElement.get();
+
+Under the hood, the state element searches the DOM tree for an ancestor element
+with a brushingStateController field to persist the state (see the
+tr.c.BrushingStateController and tr.ui.b.BrushingState classes for more
+details).
+-->
+<dom-module id='tr-ui-b-view-specific-brushing-state'>
+ <template></template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-ui-b-view-specific-brushing-state',
+
+ /** Compulsory unique identifier of the associated view. */
+ get viewId() {
+ return this.getAttribute('view-id');
+ },
+
+ set viewId(viewId) {
+ Polymer.dom(this).setAttribute('view-id', viewId);
+ },
+
+ /**
+ * Retrieve the persisted state of the associated view. The returned object
+ * (or any of its fields) must not be modified by the caller (unless the
+ * object/field is treated as a reference).
+ *
+ * If no state has been persisted yet or there is no ancestor element with
+ * a brushingStateController field, this method returns undefined.
+ */
+ get() {
+ const viewId = this.viewId;
+ if (!viewId) {
+ throw new Error('Element must have a view-id attribute!');
+ }
+
+ const brushingStateController =
+ tr.c.BrushingStateController.getControllerForElement(this);
+ if (!brushingStateController) return undefined;
+
+ return brushingStateController.getViewSpecificBrushingState(viewId);
+ },
+
+ /**
+ * Persist the provided state of the associated view. The provided object
+ * (or any of its fields) must not be modified afterwards (unless the
+ * object/field is treated as a reference).
+ *
+ * If there is no ancestor element with a brushingStateController field,
+ * this method does nothing.
+ */
+ set(state) {
+ const viewId = this.viewId;
+ if (!viewId) {
+ throw new Error('Element must have a view-id attribute!');
+ }
+
+ const brushingStateController =
+ tr.c.BrushingStateController.getControllerForElement(this);
+ if (!brushingStateController) return;
+
+ brushingStateController.changeViewSpecificBrushingState(viewId, state);
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/ui/view_specific_brushing_state_test.html b/chromium/third_party/catapult/tracing/tracing/ui/view_specific_brushing_state_test.html
new file mode 100644
index 00000000000..ee920cb1100
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/ui/view_specific_brushing_state_test.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/brushing_state_controller.html">
+<link rel="import" href="/tracing/ui/view_specific_brushing_state.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const BrushingStateController = tr.c.BrushingStateController;
+
+ function setStateElement(containerEl, viewId) {
+ const stateElement = document.createElement(
+ 'tr-ui-b-view-specific-brushing-state');
+ stateElement.viewId = viewId;
+ Polymer.dom(containerEl).appendChild(stateElement);
+ return stateElement;
+ }
+
+ function addChildDiv(element) {
+ const child = element.ownerDocument.createElement('div');
+ Polymer.dom(element).appendChild(child);
+ return child;
+ }
+
+ function addShadowChildDiv(element) {
+ const shadowRoot = element.createShadowRoot();
+ return addChildDiv(shadowRoot);
+ }
+
+ test('instantiate_withoutBrushingStateController', function() {
+ const containerEl = document.createElement('div');
+
+ const stateElement1 = setStateElement(containerEl, 'test-view');
+ assert.isUndefined(stateElement1.get());
+ stateElement1.set({e: 2.71828});
+ assert.isUndefined(stateElement1.get());
+ });
+
+ test('instantiate_withBrushingStateController', function() {
+ const rootEl = document.createElement('div');
+ const containerEl = addChildDiv(addShadowChildDiv(addChildDiv(rootEl)));
+ rootEl.brushingStateController = new BrushingStateController(undefined);
+
+ const stateElement1 = setStateElement(containerEl, 'test-view');
+ assert.isUndefined(stateElement1.get());
+ stateElement1.set({e: 2.71828});
+ assert.deepEqual(stateElement1.get(), {e: 2.71828});
+
+ const stateElement2 = setStateElement(containerEl, 'test-view-2');
+ assert.isUndefined(stateElement2.get());
+ stateElement2.set({pi: 3.14159});
+ assert.deepEqual(stateElement2.get(), {pi: 3.14159});
+
+ const stateElement3 = setStateElement(containerEl, 'test-view');
+ assert.deepEqual(stateElement3.get(), {e: 2.71828});
+
+ const stateElement4 = setStateElement(containerEl, 'test-view-2');
+ assert.deepEqual(stateElement4.get(), {pi: 3.14159});
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/__init__.py b/chromium/third_party/catapult/tracing/tracing/value/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/__init__.py
diff --git a/chromium/third_party/catapult/tracing/tracing/value/chart_json_converter.html b/chromium/third_party/catapult/tracing/tracing/value/chart_json_converter.html
new file mode 100644
index 00000000000..fb30056f60b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/chart_json_converter.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/legacy_unit_info.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v', function() {
+ class ChartJsonConverter {
+ /**
+ * Parses Values from |charts|, converts them to Histograms, and adds those
+ * to |histograms|.
+ *
+ * @param {!Array.<!Object>} charts
+ * @param {!tr.v.HistogramSet} histograms
+ */
+ static convertChartJson(charts, histograms) {
+ const traceValues = charts.charts.trace;
+
+ // The chromeperf dashboard requires some Diagnostics to be shared, even
+ // if there is only a single Histogram in the HistogramSet.
+ const diagnosticCaches = new Map();
+ function addSharedDiagnostic(hist, name, diagnostic) {
+ if (!diagnosticCaches.has(name)) {
+ diagnosticCaches.set(name, new Map());
+ }
+ const cache = diagnosticCaches.get(name);
+ const cacheKey = diagnostic instanceof tr.v.d.GenericSet ?
+ [...diagnostic].sort().join(',') : diagnostic.minDate;
+ if (!cache.has(cacheKey)) {
+ cache.set(cacheKey, diagnostic);
+ histograms.addSharedDiagnostic(diagnostic);
+ }
+ hist.diagnostics.set(name, cache.get(cacheKey));
+ }
+
+ for (const [name, pageValues] of Object.entries(charts.charts)) {
+ if (name === 'trace') continue;
+
+ const pageValuesCount = Object.keys(pageValues).length;
+ for (const [storyName, value] of Object.entries(pageValues)) {
+ if (pageValuesCount > 1 && storyName === 'summary') continue;
+
+ const unitInfo = tr.v.LEGACY_UNIT_INFO.get(value.units) || {};
+ const unitName = unitInfo.name || 'unitlessNumber';
+ const conversionFactor = unitInfo.conversionFactor || 1;
+
+ let improvementDirection = tr.b.ImprovementDirection.DONT_CARE;
+ if (unitInfo.defaultImprovementDirection !== undefined) {
+ improvementDirection = unitInfo.defaultImprovementDirection;
+ }
+ // Metrics have the final say.
+ if (value.improvement_direction !== undefined) {
+ improvementDirection =
+ ChartJsonConverter.convertImprovementDirection(
+ value.improvement_direction);
+ }
+ const unitNameSuffix = tr.b.Unit.nameSuffixForImprovementDirection(
+ improvementDirection);
+
+ const hist = histograms.createHistogram(
+ value.name || name,
+ tr.b.Unit.byName[unitName + unitNameSuffix], [], {
+ binBoundaries: tr.v.HistogramBinBoundaries.SINGULAR,
+ description: value.description || '',
+ });
+
+ if (traceValues) {
+ const traceValue = traceValues[storyName] || {};
+ let traceUrl = traceValue.cloud_url;
+ if (!traceUrl && traceValue.file_path) {
+ traceUrl = 'file://' + traceValue.file_path;
+ }
+ if (traceUrl) {
+ addSharedDiagnostic(hist, tr.v.d.RESERVED_NAMES.TRACE_URLS,
+ new tr.v.d.GenericSet([traceUrl]));
+ }
+ }
+
+ if (pageValuesCount > 1) {
+ addSharedDiagnostic(hist, tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet([storyName]));
+ }
+
+ const storyTags = [];
+ if (value.tir_label) {
+ storyTags.push(`tir_label:${value.tir_label}`);
+ }
+ if (value.story_tags) {
+ storyTags.push(...value.story_tags);
+ }
+ if (storyTags.length) {
+ addSharedDiagnostic(hist, tr.v.d.RESERVED_NAMES.STORY_TAGS,
+ new tr.v.d.GenericSet(storyTags));
+ }
+
+ if (charts.benchmark_name) {
+ addSharedDiagnostic(hist, tr.v.d.RESERVED_NAMES.BENCHMARKS,
+ new tr.v.d.GenericSet([charts.benchmark_name]));
+ }
+
+ if (charts.label) {
+ addSharedDiagnostic(hist, tr.v.d.RESERVED_NAMES.LABELS,
+ new tr.v.d.GenericSet([charts.label]));
+ }
+
+ if (charts.benchmarkStartMs) {
+ addSharedDiagnostic(hist, tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(charts.benchmarkStartMs));
+ }
+
+ if (value.type === 'histogram' || value.buckets) {
+ for (const bucket of value.buckets) {
+ // Take the center of the bin. This coarse granularity can amplify
+ // noise when a measurement moves from one bin to the next.
+ const sample = conversionFactor * (bucket.high + bucket.low) / 2;
+ for (let i = 0; i < bucket.count; ++i) {
+ hist.addSample(sample);
+ }
+ }
+ } else if (value.type === 'list_of_scalar_values' || value.values) {
+ // |value.values| is undefined if the list_of_scalar_values is
+ // empty.
+ if (value.values) {
+ for (const sample of value.values) {
+ hist.addSample(sample * conversionFactor);
+ }
+ }
+ } else if (value.type === 'scalar' || value.value !== undefined) {
+ hist.addSample(value.value * conversionFactor);
+ }
+ }
+ }
+ }
+
+ static convertImprovementDirection(improvementDirection) {
+ switch (improvementDirection) {
+ case 'down': return tr.b.ImprovementDirection.SMALLER_IS_BETTER;
+ case 'up': return tr.b.ImprovementDirection.BIGGER_IS_BETTER;
+ default: return tr.b.ImprovementDirection.DONT_CARE;
+ }
+ }
+ }
+
+ return {
+ ChartJsonConverter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/chart_json_converter_test.html b/chromium/third_party/catapult/tracing/tracing/value/chart_json_converter_test.html
new file mode 100644
index 00000000000..6b0bb9e49ec
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/chart_json_converter_test.html
@@ -0,0 +1,401 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/chart_json_converter.html">
+<link rel="import" href="/tracing/value/histogram_grouping.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('emptyListOfScalarValues', function() {
+ const charts = {
+ benchmark_name: 'the.benchmark',
+ label: 'the_label',
+ charts: {
+ mean_frame_time: {
+ 'http://games.yahoo.com': {
+ std: 0.0,
+ name: 'mean_frame_time',
+ type: 'list_of_scalar_values',
+ improvement_direction: 'down',
+ units: 'ms',
+ page_id: 16,
+ description: 'Arithmetic mean of frame times.'
+ },
+ 'summary': {
+ std: 0.0,
+ name: 'mean_frame_time',
+ improvement_direction: 'down',
+ units: 'ms',
+ type: 'list_of_scalar_values',
+ description: 'Arithmetic mean of frame times.'
+ },
+ }
+ }
+ };
+ const histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ assert.lengthOf(histograms, 1);
+ const hist = [...histograms][0];
+ assert.strictEqual('mean_frame_time', hist.name);
+ assert.strictEqual('http://games.yahoo.com',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(hist));
+ assert.strictEqual('the.benchmark',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.BENCHMARKS).callback(hist));
+ assert.strictEqual('the_label',
+ tr.v.HistogramGrouping.DISPLAY_LABEL.callback(hist));
+ assert.strictEqual(0, hist.numValues);
+ assert.strictEqual(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ hist.unit);
+
+ const stories = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.STORIES);
+ assert.isTrue(stories.hasGuid);
+ assert.strictEqual(stories, histograms.lookupDiagnostic(stories.guid));
+
+ const benchmarks = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARKS);
+ assert.isTrue(benchmarks.hasGuid);
+ assert.strictEqual(benchmarks, histograms.lookupDiagnostic(
+ benchmarks.guid));
+
+ const labels = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.LABELS);
+ assert.isTrue(labels.hasGuid);
+ assert.strictEqual(labels, histograms.lookupDiagnostic(labels.guid));
+ });
+
+ test('convertWithoutName', function() {
+ const charts = {
+ benchmark_name: 'the.benchmark',
+ label: 'the_label',
+ charts: {
+ mean_frame_time: {
+ 'http://games.yahoo.com': {
+ std: 0.0,
+ type: 'list_of_scalar_values',
+ improvement_direction: 'down',
+ units: 'ms',
+ page_id: 16,
+ description: 'Arithmetic mean of frame times.'
+ },
+ 'summary': {
+ std: 0.0,
+ improvement_direction: 'down',
+ units: 'ms',
+ type: 'list_of_scalar_values',
+ description: 'Arithmetic mean of frame times.'
+ },
+ }
+ }
+ };
+ const histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ assert.lengthOf(histograms, 1);
+ const hist = [...histograms][0];
+ assert.strictEqual('mean_frame_time', hist.name);
+ assert.strictEqual('http://games.yahoo.com',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(hist));
+ assert.strictEqual('the.benchmark',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.BENCHMARKS).callback(hist));
+ assert.strictEqual('the_label',
+ tr.v.HistogramGrouping.DISPLAY_LABEL.callback(hist));
+ assert.strictEqual(0, hist.numValues);
+ assert.strictEqual(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ hist.unit);
+
+ const stories = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.STORIES);
+ assert.isTrue(stories.hasGuid);
+ assert.strictEqual(stories, histograms.lookupDiagnostic(stories.guid));
+
+ const benchmarks = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARKS);
+ assert.isTrue(benchmarks.hasGuid);
+ assert.strictEqual(benchmarks, histograms.lookupDiagnostic(
+ benchmarks.guid));
+
+ const labels = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.LABELS);
+ assert.isTrue(labels.hasGuid);
+ assert.strictEqual(labels, histograms.lookupDiagnostic(labels.guid));
+ });
+ test('convertWithoutTIRLabel', function() {
+ const charts = {
+ charts: {
+ mean_frame_time: {
+ 'http://games.yahoo.com': {
+ std: 0.0,
+ name: 'mean_frame_time',
+ type: 'list_of_scalar_values',
+ improvement_direction: 'down',
+ values: [42],
+ units: 'ms',
+ page_id: 16,
+ description: 'Arithmetic mean of frame times.'
+ },
+ 'summary': {
+ std: 0.0,
+ name: 'mean_frame_time',
+ improvement_direction: 'down',
+ values: [
+ 16.693,
+ 16.646,
+ 16.918,
+ 16.681
+ ],
+ units: 'ms',
+ type: 'list_of_scalar_values',
+ description: 'Arithmetic mean of frame times.'
+ },
+ }
+ }
+ };
+ const histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ assert.lengthOf(histograms, 1);
+ const hist = [...histograms][0];
+ assert.strictEqual('mean_frame_time', hist.name);
+ assert.strictEqual('http://games.yahoo.com',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(hist));
+ assert.strictEqual(42, hist.average);
+ assert.strictEqual(1, hist.numValues);
+ assert.strictEqual(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ hist.unit);
+
+ const stories = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.STORIES);
+ assert.isTrue(stories.hasGuid);
+ assert.strictEqual(stories, histograms.lookupDiagnostic(stories.guid));
+ });
+
+ test('convertWithoutType', function() {
+ const charts = {
+ charts: {
+ mean_frame_time: {
+ 'http://games.yahoo.com': {
+ std: 0.0,
+ name: 'mean_frame_time',
+ improvement_direction: 'down',
+ value: 42,
+ units: 'ms',
+ page_id: 16,
+ description: 'Arithmetic mean of frame times.'
+ },
+ 'summary': {
+ std: 0.0,
+ name: 'mean_frame_time',
+ improvement_direction: 'down',
+ values: [
+ 16.693,
+ 16.646,
+ 16.918,
+ 16.681
+ ],
+ units: 'ms',
+ type: 'list_of_scalar_values',
+ description: 'Arithmetic mean of frame times.'
+ },
+ }
+ }
+ };
+ const histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ assert.lengthOf(histograms, 1);
+ const hist = [...histograms][0];
+ assert.strictEqual('mean_frame_time', hist.name);
+ assert.strictEqual('http://games.yahoo.com',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(hist));
+ assert.strictEqual(42, hist.average);
+ assert.strictEqual(1, hist.numValues);
+ assert.strictEqual(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ hist.unit);
+
+ const stories = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.STORIES);
+ assert.isTrue(stories.hasGuid);
+ assert.strictEqual(stories, histograms.lookupDiagnostic(stories.guid));
+ });
+
+ test('convertWithTIRLabel', function() {
+ const charts = {
+ charts: {
+ 'TIR-A@@value-name': {
+ 'story-name': {
+ name: 'value-name',
+ page_id: 7,
+ improvement_direction: 'down',
+ values: [42],
+ units: 'ms',
+ tir_label: 'TIR-A',
+ type: 'list_of_scalar_values',
+ },
+ 'summary': {
+ name: 'value-name',
+ improvement_direction: 'down',
+ values: [42],
+ units: 'ms',
+ tir_label: 'TIR-A',
+ type: 'list_of_scalar_values',
+ },
+ },
+ },
+ };
+ const histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ const hist = tr.b.getOnlyElement(histograms);
+ assert.strictEqual('value-name', hist.name);
+ assert.strictEqual(tr.b.getOnlyElement(hist.diagnostics.get(
+ tr.v.d.RESERVED_NAMES.STORY_TAGS)), 'tir_label:TIR-A');
+ assert.strictEqual('story-name',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(hist));
+ assert.strictEqual(42, hist.average);
+ assert.strictEqual(1, hist.numValues);
+ assert.strictEqual(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ hist.unit);
+ assert.isTrue(hist.diagnostics.get(tr.v.d.RESERVED_NAMES.STORIES).hasGuid);
+ assert.isTrue(hist.diagnostics.get(
+ tr.v.d.RESERVED_NAMES.STORY_TAGS).hasGuid);
+ });
+
+ test('convertWithStoryTags', function() {
+ const charts = {
+ charts: {
+ 'TIR-A@@value-name': {
+ 'story-name': {
+ name: 'value-name',
+ page_id: 7,
+ improvement_direction: 'down',
+ values: [42],
+ units: 'ms',
+ story_tags: ['foo', 'bar'],
+ type: 'list_of_scalar_values',
+ },
+ 'summary': {
+ name: 'value-name',
+ improvement_direction: 'down',
+ values: [42],
+ units: 'ms',
+ story_tags: ['foo', 'bar'],
+ type: 'list_of_scalar_values',
+ },
+ },
+ },
+ };
+ const histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ const hist = tr.b.getOnlyElement(histograms);
+ assert.strictEqual('value-name', hist.name);
+ const tags = [...hist.diagnostics.get(
+ tr.v.d.RESERVED_NAMES.STORY_TAGS)];
+ assert.lengthOf(tags, 2);
+ assert.strictEqual(tags[0], 'foo');
+ assert.strictEqual(tags[1], 'bar');
+ assert.strictEqual('story-name',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(hist));
+ assert.strictEqual(42, hist.average);
+ assert.strictEqual(1, hist.numValues);
+ assert.strictEqual(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ hist.unit);
+ assert.isTrue(hist.diagnostics.get(tr.v.d.RESERVED_NAMES.STORIES).hasGuid);
+ assert.isTrue(hist.diagnostics.get(
+ tr.v.d.RESERVED_NAMES.STORY_TAGS).hasGuid);
+ });
+
+ test('convertHistogram', function() {
+ const charts = {
+ charts: {
+ MPArch_RWH_TabSwitchPaintDuration: {
+ summary: {
+ units: 'ms',
+ buckets: [
+ {
+ high: 20,
+ count: 2,
+ low: 16,
+ },
+ {
+ high: 24,
+ count: 2,
+ low: 20,
+ }
+ ],
+ important: false,
+ type: 'histogram',
+ name: 'MPArch_RWH_TabSwitchPaintDuration',
+ }
+ }
+ }
+ };
+ const histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ assert.lengthOf(histograms, 1);
+ const hist = [...histograms][0];
+ assert.strictEqual('MPArch_RWH_TabSwitchPaintDuration', hist.name);
+ assert.strictEqual('',
+ tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(hist));
+ assert.strictEqual(20, hist.average);
+ assert.strictEqual(4, hist.numValues);
+ assert.strictEqual(tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ hist.unit);
+ });
+
+ test('traceUrls', function() {
+ const charts = {
+ charts: {
+ measurementA: {
+ storyA: {
+ units: 'ms',
+ type: 'list_of_scalar_values',
+ values: [100],
+ name: 'measurementA',
+ },
+ storyB: {
+ units: 'ms',
+ type: 'list_of_scalar_values',
+ values: [200],
+ name: 'measurementA',
+ },
+ },
+ trace: {
+ storyA: {
+ name: 'trace',
+ type: 'trace',
+ file_path: '/home/user/storyA_1900-01-01_00-00-00.html',
+ },
+ storyB: {
+ name: 'trace',
+ type: 'trace',
+ cloud_url: 'https://console.developers.google.com/m/cloudstorage/chromium-telemetry/o/storyB_1900-01-01_00-00-00.html',
+ },
+ },
+ },
+ };
+ let histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ histograms = [...histograms];
+ assert.lengthOf(histograms, 2);
+ assert.strictEqual(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(histograms[0]), 'storyA');
+ assert.strictEqual(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES).callback(histograms[1]), 'storyB');
+ assert.strictEqual(tr.b.getOnlyElement(histograms[0].diagnostics.get(
+ tr.v.d.RESERVED_NAMES.TRACE_URLS)),
+ 'file:///home/user/storyA_1900-01-01_00-00-00.html');
+ assert.strictEqual(tr.b.getOnlyElement(histograms[1].diagnostics.get(
+ tr.v.d.RESERVED_NAMES.TRACE_URLS)),
+ 'https://console.developers.google.com/m/cloudstorage/chromium-telemetry/o/storyB_1900-01-01_00-00-00.html');
+ assert.isTrue(histograms[0].diagnostics.get(
+ tr.v.d.RESERVED_NAMES.TRACE_URLS).hasGuid);
+ assert.isTrue(histograms[1].diagnostics.get(
+ tr.v.d.RESERVED_NAMES.TRACE_URLS).hasGuid);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/convert_chart_json.py b/chromium/third_party/catapult/tracing/tracing/value/convert_chart_json.py
new file mode 100755
index 00000000000..10dabee5ccf
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/convert_chart_json.py
@@ -0,0 +1,24 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import tracing_project
+import vinn
+
+
+def ConvertChartJson(chart_json):
+ """Convert chart_json to Histograms.
+
+ Args:
+ chart_json: path to a file containing chart-json
+
+ Returns:
+ a Vinn result object whose 'returncode' indicates whether there was an
+ exception, and whose 'stdout' contains HistogramSet json.
+ """
+ return vinn.RunFile(
+ os.path.join(os.path.dirname(__file__),
+ 'convert_chart_json_cmdline.html'),
+ source_paths=tracing_project.TracingProject().source_paths,
+ js_args=[os.path.abspath(chart_json)])
diff --git a/chromium/third_party/catapult/tracing/tracing/value/convert_chart_json_cmdline.html b/chromium/third_party/catapult/tracing/tracing/value/convert_chart_json_cmdline.html
new file mode 100644
index 00000000000..3503b1db685
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/convert_chart_json_cmdline.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/value/chart_json_converter.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+if (tr.isHeadless) {
+ const charts = JSON.parse(tr.b.getSync('file://' + sys.argv[1]));
+ const histograms = new tr.v.HistogramSet();
+ tr.v.ChartJsonConverter.convertChartJson(charts, histograms);
+ console.log(JSON.stringify(histograms.asDicts()));
+}
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/csv_builder.html b/chromium/third_party/catapult/tracing/tracing/value/csv_builder.html
new file mode 100644
index 00000000000..1627c592669
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/csv_builder.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram_grouping.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v', function() {
+ const IGNORE_GROUPING_KEYS = [
+ 'name',
+ 'storyTags',
+ 'testPath',
+ ];
+
+ class CSVBuilder {
+ /**
+ * @param {!tr.v.HistogramSet} histograms
+ */
+ constructor(histograms) {
+ this.histograms_ = histograms;
+ this.table_ = [];
+ this.statisticsNames_ = new Set();
+ this.groupings_ = [];
+ }
+
+ build() {
+ this.prepare_();
+ this.buildHeader_();
+ this.buildTable_();
+ }
+
+ prepare_() {
+ for (const [key, grouping] of tr.v.HistogramGrouping.BY_KEY) {
+ if (IGNORE_GROUPING_KEYS.includes(key)) continue;
+ this.groupings_.push(grouping);
+ }
+ this.groupings_.push(new tr.v.GenericSetGrouping(
+ tr.v.d.RESERVED_NAMES.TRACE_URLS));
+
+ this.groupings_.sort((a, b) => a.key.localeCompare(b.key));
+
+ for (const hist of this.histograms_) {
+ for (const name of hist.statisticsNames) {
+ this.statisticsNames_.add(name);
+ }
+ }
+ this.statisticsNames_ = Array.from(this.statisticsNames_);
+ this.statisticsNames_.sort();
+ }
+
+ buildHeader_() {
+ const header = ['name', 'unit'];
+ for (const name of this.statisticsNames_) {
+ header.push(name);
+ }
+ for (const grouping of this.groupings_) {
+ header.push(grouping.key);
+ }
+ this.table_.push(header);
+ }
+
+ buildTable_() {
+ for (const hist of this.histograms_) {
+ const row = [hist.name, hist.unit.unitString];
+ this.table_.push(row);
+
+ for (const name of this.statisticsNames_) {
+ const stat = hist.getStatisticScalar(name);
+ if (stat) {
+ row.push(stat.value);
+ } else {
+ row.push('');
+ }
+ }
+
+ for (const grouping of this.groupings_) {
+ row.push(grouping.callback(hist));
+ }
+ }
+ }
+
+ toString() {
+ let str = '';
+ for (const row of this.table_) {
+ for (let i = 0; i < row.length; ++i) {
+ if (i > 0) {
+ str += ',';
+ }
+ let cell = '' + row[i];
+ cell = cell.replace(/\n/g, ' ');
+ if (cell.indexOf(',') >= 0 || cell.indexOf('"') >= 0) {
+ cell = '"' + cell.replace(/"/g, '""') + '"';
+ }
+ str += cell;
+ }
+ str += '\n';
+ }
+ return str;
+ }
+ }
+
+ return {
+ CSVBuilder,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/csv_builder_test.html b/chromium/third_party/catapult/tracing/tracing/value/csv_builder_test.html
new file mode 100644
index 00000000000..b34faf35c7d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/csv_builder_test.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/csv_builder.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('csvBuilder', function() {
+ const hist0 = new tr.v.Histogram('hist0', tr.b.Unit.byName.sizeInBytes,
+ tr.v.HistogramBinBoundaries.createLinear(0, 1e3, 10));
+ hist0.customizeSummaryOptions({
+ nans: true,
+ percentile: [0.1, 0.9],
+ });
+ hist0.diagnostics.set(tr.v.d.RESERVED_NAMES.BENCHMARKS,
+ new tr.v.d.GenericSet(['benchmark A']));
+ hist0.diagnostics.set(tr.v.d.RESERVED_NAMES.LABELS,
+ new tr.v.d.GenericSet(['label A']));
+ hist0.diagnostics.set(tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet(['story A']));
+ hist0.diagnostics.set(tr.v.d.RESERVED_NAMES.TRACE_URLS,
+ new tr.v.d.GenericSet(['file://a/b.html']));
+ hist0.diagnostics.set(tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(0));
+ hist0.diagnostics.set(tr.v.d.RESERVED_NAMES.STORYSET_REPEATS,
+ new tr.v.d.GenericSet([0]));
+ for (let i = 0; i <= 1e3; i += 10) {
+ hist0.addSample(i);
+ }
+ hist0.addSample(NaN);
+
+ const hist1 = new tr.v.Histogram('hist1', tr.b.Unit.byName.sigma);
+ hist0.customizeSummaryOptions({
+ std: false,
+ count: false,
+ sum: false,
+ min: false,
+ max: false,
+ });
+
+ const hist2 = new tr.v.Histogram('hist2', tr.b.Unit.byName.count);
+ hist2.diagnostics.set(tr.v.d.RESERVED_NAMES.BENCHMARKS,
+ new tr.v.d.GenericSet(['benchmark A']));
+ hist0.diagnostics.set(tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(1499726648646));
+
+ const histograms = new tr.v.HistogramSet([hist0, hist1, hist2]);
+ let csv = new tr.v.CSVBuilder(histograms);
+ csv.build();
+ csv = csv.toString().split('\n');
+ assert.lengthOf(csv, histograms.length + 2);
+ assert.strictEqual(csv[0],
+ 'name,unit,avg,count,max,min,nans,pct_010,pct_090,std,sum,' +
+ 'architectures,benchmarks,benchmarkStart,bots,builds,deviceIds,' +
+ 'displayLabel,masters,memoryAmounts,osNames,osVersions,' +
+ 'productVersions,stories,storysetRepeats,traceStart,traceUrls');
+ assert.strictEqual(csv[1],
+ 'hist0,B,500,101,1000,0,1,150,950,293.00170647967224,50500,,' +
+ 'benchmark A,2017-07-10 22:44:08,,,,label A,,,,,,story A,0,,' +
+ 'file://a/b.html');
+ assert.strictEqual(csv[2],
+ 'hist1,σ,,0,-Infinity,Infinity,0,,,,0,,,,,,,Value,,,,,,,,,');
+ assert.strictEqual(csv[3],
+ 'hist2,,,0,-Infinity,Infinity,0,,,,0,,benchmark A,,,,,' +
+ 'benchmark A,,,,,,,,,');
+ assert.strictEqual(csv[4], '');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/__init__.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/__init__.py
new file mode 100644
index 00000000000..a22a6ee39a9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/add_reserved_diagnostics.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/add_reserved_diagnostics.py
new file mode 100644
index 00000000000..e947e4d45cd
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/add_reserved_diagnostics.py
@@ -0,0 +1,180 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import contextlib
+import json
+import os
+import tempfile
+
+from tracing.value import histogram_set
+from tracing.value import merge_histograms
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import reserved_infos
+
+
+ALL_NAMES = list(reserved_infos.AllNames())
+
+
+def _LoadHistogramSet(dicts):
+ hs = histogram_set.HistogramSet()
+ hs.ImportDicts(dicts)
+ return hs
+
+
+@contextlib.contextmanager
+def TempFile():
+ try:
+ temp = tempfile.NamedTemporaryFile(delete=False)
+ yield temp
+ finally:
+ os.unlink(temp.name)
+
+
+def GetTIRLabelFromHistogram(hist):
+ tags = hist.diagnostics.get(reserved_infos.STORY_TAGS.name) or []
+
+ tags_to_use = [t.split(':') for t in tags if ':' in t]
+
+ return '_'.join(v for _, v in sorted(tags_to_use))
+
+
+def ComputeTestPath(hist):
+ path = hist.name
+
+ # If a Histogram represents a summary across multiple stories, then its
+ # 'stories' diagnostic will contain the names of all of the stories.
+ # If a Histogram is not a summary, then its 'stories' diagnostic will contain
+ # the singular name of its story.
+ is_summary = list(
+ hist.diagnostics.get(reserved_infos.SUMMARY_KEYS.name, []))
+
+ tir_label = GetTIRLabelFromHistogram(hist)
+ if tir_label and (
+ not is_summary or reserved_infos.STORY_TAGS.name in is_summary):
+ path += '/' + tir_label
+
+ is_ref = hist.diagnostics.get(reserved_infos.IS_REFERENCE_BUILD.name)
+ if is_ref and len(is_ref) == 1:
+ is_ref = is_ref.GetOnlyElement()
+
+ story_name = hist.diagnostics.get(reserved_infos.STORIES.name)
+ if story_name and len(story_name) == 1 and not is_summary:
+ escaped_story_name = story_name.GetOnlyElement()
+ path += '/' + escaped_story_name
+ if is_ref:
+ path += '_ref'
+ elif is_ref:
+ path += '/ref'
+
+ return path
+
+
+def _MergeHistogramSetByPath(hs):
+ with TempFile() as temp:
+ temp.write(json.dumps(hs.AsDicts()).encode('utf-8'))
+ temp.close()
+
+ return merge_histograms.MergeHistograms(temp.name, (
+ reserved_infos.TEST_PATH.name,))
+
+
+def _GetAndDeleteHadFailures(hs):
+ had_failures = False
+ for h in hs:
+ had_failures_diag = h.diagnostics.get(reserved_infos.HAD_FAILURES.name)
+ if had_failures_diag:
+ del h.diagnostics[reserved_infos.HAD_FAILURES.name]
+ had_failures = True
+ return had_failures
+
+
+def _MergeAndReplaceSharedDiagnostics(diagnostic_name, hs):
+ merged = None
+ for h in hs:
+ d = h.diagnostics.get(diagnostic_name)
+ if not d:
+ continue
+
+ if not merged:
+ merged = d
+ else:
+ merged.AddDiagnostic(d)
+ h.diagnostics[diagnostic_name] = merged
+
+
+def AddReservedDiagnostics(histogram_dicts, names_to_values):
+ # We need to generate summary statistics for anything that had a story, so
+ # filter out every histogram with no stories, then merge. If you keep the
+ # histograms with no story, you end up with duplicates.
+ hs_with_stories = _LoadHistogramSet(histogram_dicts)
+ hs_with_stories.FilterHistograms(
+ lambda h: not h.diagnostics.get(reserved_infos.STORIES.name, []))
+
+ hs_with_no_stories = _LoadHistogramSet(histogram_dicts)
+ hs_with_no_stories.FilterHistograms(
+ lambda h: h.diagnostics.get(reserved_infos.STORIES.name, []))
+
+ # TODO(#3987): Refactor recipes to call merge_histograms separately.
+ # This call combines all repetitions of a metric for a given story into a
+ # single histogram.
+ hs = histogram_set.HistogramSet()
+ hs.ImportDicts(hs_with_stories.AsDicts())
+
+ for h in hs:
+ h.diagnostics[reserved_infos.TEST_PATH.name] = (
+ generic_set.GenericSet([ComputeTestPath(h)]))
+
+ _GetAndDeleteHadFailures(hs)
+ dicts_across_repeats = _MergeHistogramSetByPath(hs)
+
+ had_failures = _GetAndDeleteHadFailures(hs_with_stories)
+
+ if not had_failures:
+ # This call creates summary metrics across each tag set of stories.
+ hs = histogram_set.HistogramSet()
+ hs.ImportDicts(hs_with_stories.AsDicts())
+ hs.FilterHistograms(lambda h: not GetTIRLabelFromHistogram(h))
+
+ for h in hs:
+ h.diagnostics[reserved_infos.SUMMARY_KEYS.name] = (
+ generic_set.GenericSet(['name', 'storyTags']))
+ h.diagnostics[reserved_infos.TEST_PATH.name] = (
+ generic_set.GenericSet([ComputeTestPath(h)]))
+
+ dicts_across_stories = _MergeHistogramSetByPath(hs)
+
+ # This call creates summary metrics across the entire story set.
+ hs = histogram_set.HistogramSet()
+ hs.ImportDicts(hs_with_stories.AsDicts())
+
+ for h in hs:
+ h.diagnostics[reserved_infos.SUMMARY_KEYS.name] = (
+ generic_set.GenericSet(['name']))
+ h.diagnostics[reserved_infos.TEST_PATH.name] = (
+ generic_set.GenericSet([ComputeTestPath(h)]))
+
+ dicts_across_names = _MergeHistogramSetByPath(hs)
+ else:
+ dicts_across_stories = []
+ dicts_across_names = []
+
+ # Now load everything into one histogram set. First we load the summary
+ # histograms, since we need to mark them with SUMMARY_KEYS.
+ # After that we load the rest, and then apply all the diagnostics specified
+ # on the command line. Finally, since we end up with a lot of diagnostics
+ # that no histograms refer to, we make sure to prune those.
+ histograms = histogram_set.HistogramSet()
+ histograms.ImportDicts(dicts_across_names)
+ histograms.ImportDicts(dicts_across_stories)
+ histograms.ImportDicts(dicts_across_repeats)
+ histograms.ImportDicts(hs_with_no_stories.AsDicts())
+
+ histograms.DeduplicateDiagnostics()
+ for name, value in names_to_values.items():
+ assert name in ALL_NAMES
+ histograms.AddSharedDiagnosticToAllHistograms(
+ name, generic_set.GenericSet([value]))
+ histograms.RemoveOrphanedDiagnostics()
+
+ return json.dumps(histograms.AsDicts())
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/add_reserved_diagnostics_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/add_reserved_diagnostics_unittest.py
new file mode 100644
index 00000000000..e94589c2cb9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/add_reserved_diagnostics_unittest.py
@@ -0,0 +1,237 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import unittest
+
+from tracing.value import histogram
+from tracing.value import histogram_set
+from tracing.value.diagnostics import add_reserved_diagnostics
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import reserved_infos
+
+class AddReservedDiagnosticsUnittest(unittest.TestCase):
+
+ def _CreateHistogram(self, name, stories=None, tags=None, had_failures=False):
+ h = histogram.Histogram(name, 'count')
+ if stories:
+ h.diagnostics[reserved_infos.STORIES.name] = generic_set.GenericSet(
+ stories)
+ if tags:
+ h.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ tags)
+ if had_failures:
+ h.diagnostics[reserved_infos.HAD_FAILURES.name] = generic_set.GenericSet(
+ [True])
+ return h
+
+ def testAddReservedDiagnostics_InvalidDiagnostic_Raises(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram('foo')])
+
+ with self.assertRaises(AssertionError):
+ add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'SOME INVALID DIAGNOSTIC': 'bar'})
+
+ def testAddReservedDiagnostics_DiagnosticsAdded(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram('foo1', stories=['foo1']),
+ self._CreateHistogram('foo1', stories=['foo1']),
+ self._CreateHistogram('bar', stories=['bar1']),
+ self._CreateHistogram('bar', stories=['bar2']),
+ self._CreateHistogram('blah')])
+
+ new_hs_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'benchmarks': 'bar'})
+
+ new_hs = histogram_set.HistogramSet()
+ new_hs.ImportDicts(json.loads(new_hs_json))
+
+ for h in new_hs:
+ self.assertIn('benchmarks', h.diagnostics)
+ benchmarks = list(h.diagnostics['benchmarks'])
+ self.assertEqual(['bar'], benchmarks)
+
+ def testAddReservedDiagnostics_SummaryAddedToMerged(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram('foo1', stories=['foo1']),
+ self._CreateHistogram('foo1', stories=['foo1']),
+ self._CreateHistogram('bar', stories=['bar1']),
+ self._CreateHistogram('bar', stories=['bar2']),
+ self._CreateHistogram('blah')])
+
+ new_hs_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'benchmarks': 'bar'})
+
+ new_hs = histogram_set.HistogramSet()
+ new_hs.ImportDicts(json.loads(new_hs_json))
+
+ expected = [
+ [u'foo1', [], [u'foo1']],
+ [u'bar', [], [u'bar1']],
+ [u'blah', [], []],
+ [u'bar', [u'name'], [u'bar1', u'bar2']],
+ [u'foo1', [u'name'], [u'foo1']],
+ [u'bar', [], [u'bar2']],
+ ]
+
+ for h in new_hs:
+ is_summary = sorted(
+ list(h.diagnostics.get(reserved_infos.SUMMARY_KEYS.name, [])))
+ stories = sorted(list(h.diagnostics.get(reserved_infos.STORIES.name, [])))
+ self.assertIn([h.name, is_summary, stories], expected)
+ expected.remove([h.name, is_summary, stories])
+
+ self.assertEqual(0, len(expected))
+
+ def testAddReservedDiagnostics_Repeats_Merged(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram('foo1', stories=['foo1']),
+ self._CreateHistogram('foo1', stories=['foo1']),
+ self._CreateHistogram('foo2', stories=['foo2'])])
+
+ new_hs_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'benchmarks': 'bar'})
+
+ new_hs = histogram_set.HistogramSet()
+ new_hs.ImportDicts(json.loads(new_hs_json))
+
+ expected = [
+ [u'foo2', [u'name']],
+ [u'foo1', [u'name']],
+ [u'foo2', []],
+ [u'foo1', []],
+ ]
+
+ for h in new_hs:
+ is_summary = sorted(
+ list(h.diagnostics.get(reserved_infos.SUMMARY_KEYS.name, [])))
+ self.assertIn([h.name, is_summary], expected)
+ expected.remove([h.name, is_summary])
+
+ self.assertEqual(0, len(expected))
+
+ def testAddReservedDiagnostics_Stories_Merged(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram('foo', stories=['foo1']),
+ self._CreateHistogram('foo', stories=['foo2']),
+ self._CreateHistogram('bar', stories=['bar'])])
+
+ new_hs_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'benchmarks': 'bar'})
+
+ new_hs = histogram_set.HistogramSet()
+ new_hs.ImportDicts(json.loads(new_hs_json))
+
+ expected = [
+ [u'foo', [], [u'foo2']],
+ [u'foo', [u'name'], [u'foo1', u'foo2']],
+ [u'bar', [u'name'], [u'bar']],
+ [u'foo', [], [u'foo1']],
+ [u'bar', [], [u'bar']],
+ ]
+
+ for h in new_hs:
+ is_summary = sorted(
+ list(h.diagnostics.get(reserved_infos.SUMMARY_KEYS.name, [])))
+ stories = sorted(list(h.diagnostics[reserved_infos.STORIES.name]))
+ self.assertIn([h.name, is_summary, stories], expected)
+ expected.remove([h.name, is_summary, stories])
+
+ self.assertEqual(0, len(expected))
+
+ def testAddReservedDiagnostics_NoStories_Unmerged(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram('foo'),
+ self._CreateHistogram('foo'),
+ self._CreateHistogram('bar')])
+
+ new_hs_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'benchmarks': 'bar'})
+
+ new_hs = histogram_set.HistogramSet()
+ new_hs.ImportDicts(json.loads(new_hs_json))
+
+ for h in new_hs:
+ self.assertNotIn(reserved_infos.SUMMARY_KEYS.name, h.diagnostics)
+
+ self.assertEqual(2, len(new_hs.GetHistogramsNamed('foo')))
+ self.assertEqual(1, len(new_hs.GetHistogramsNamed('bar')))
+
+ def testAddReservedDiagnostics_WithTags(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram('foo', ['bar'], ['t:1']),
+ self._CreateHistogram('foo', ['bar'], ['t:2'])
+ ])
+
+ new_hs_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'benchmarks': 'bar'})
+
+ new_hs = histogram_set.HistogramSet()
+ new_hs.ImportDicts(json.loads(new_hs_json))
+
+ expected = [
+ [u'foo', [u'name'], [u'bar'], [u't:1', u't:2']],
+ [u'foo', [], [u'bar'], [u't:1']],
+ [u'foo', [], [u'bar'], [u't:2']],
+ [u'foo', [u'name', u'storyTags'], [u'bar'], [u't:1']],
+ [u'foo', [u'name', u'storyTags'], [u'bar'], [u't:2']],
+ ]
+
+ for h in new_hs:
+ is_summary = sorted(
+ list(h.diagnostics.get(reserved_infos.SUMMARY_KEYS.name, [])))
+ stories = sorted(list(h.diagnostics[reserved_infos.STORIES.name]))
+ tags = sorted(list(h.diagnostics[reserved_infos.STORY_TAGS.name]))
+ self.assertIn([h.name, is_summary, stories, tags], expected)
+ expected.remove([h.name, is_summary, stories, tags])
+
+ self.assertEqual(0, len(expected))
+
+ def testAddReservedDiagnostics_WithTags_SomeIgnored(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram(
+ 'foo', stories=['story1'], tags=['t:1', 'ignored']),
+ self._CreateHistogram(
+ 'foo', stories=['story1'], tags=['t:1']),
+ ])
+
+ new_hs_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'benchmarks': 'bar'})
+
+ new_hs = histogram_set.HistogramSet()
+ new_hs.ImportDicts(json.loads(new_hs_json))
+
+ expected = [
+ [u'foo', [u'name', u'storyTags'], [u'story1'], [u'ignored', u't:1']],
+ [u'foo', [], [u'story1'], [u'ignored', u't:1']],
+ [u'foo', [u'name'], [u'story1'], [u'ignored', u't:1']],
+ ]
+
+ for h in new_hs:
+ is_summary = sorted(
+ list(h.diagnostics.get(reserved_infos.SUMMARY_KEYS.name, [])))
+ stories = sorted(list(h.diagnostics[reserved_infos.STORIES.name]))
+ tags = sorted(list(h.diagnostics[reserved_infos.STORY_TAGS.name]))
+ self.assertIn([h.name, is_summary, stories, tags], expected)
+ expected.remove([h.name, is_summary, stories, tags])
+
+ self.assertEqual(0, len(expected))
+
+ def testAddReservedDiagnostics_OmitsSummariesIfHadFailures(self):
+ hs = histogram_set.HistogramSet([
+ self._CreateHistogram('foo', ['bar'], had_failures=True)])
+
+ new_hs_json = add_reserved_diagnostics.AddReservedDiagnostics(
+ hs.AsDicts(), {'benchmarks': 'bar'})
+
+ new_hs = histogram_set.HistogramSet()
+ new_hs.ImportDicts(json.loads(new_hs_json))
+
+ self.assertEqual(len(new_hs), 1)
+
+ h = new_hs.GetFirstHistogram()
+ self.assertEqual(h.name, 'foo')
+ self.assertNotIn(reserved_infos.SUMMARY_KEYS.name, h.diagnostics)
+ self.assertNotIn(reserved_infos.HAD_FAILURES.name, h.diagnostics)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics.html
new file mode 100644
index 00000000000..48ec199d6ca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/breakdown.html">
+<link rel="import" href="/tracing/value/diagnostics/collected_related_event_set.html">
+<link rel="import" href="/tracing/value/diagnostics/date_range.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic_ref.html">
+<link rel="import" href="/tracing/value/diagnostics/generic_set.html">
+<link rel="import" href="/tracing/value/diagnostics/related_event_set.html">
+<link rel="import" href="/tracing/value/diagnostics/related_name_map.html">
+<link rel="import" href="/tracing/value/diagnostics/scalar.html">
+<link rel="import" href="/tracing/value/diagnostics/unmergeable_diagnostic_set.html">
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics.py
new file mode 100644
index 00000000000..95b18c65e7c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics.py
@@ -0,0 +1,42 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import importlib
+import sys
+
+
+# TODO(#3613): Flatten this to a list once diagnostics are in their own modules.
+_MODULES_BY_DIAGNOSTIC_NAME = {
+ 'Breakdown': 'diagnostics.breakdown',
+ 'GenericSet': 'diagnostics.generic_set',
+ 'UnmergeableDiagnosticSet': 'diagnostics.unmergeable_diagnostic_set',
+ 'RelatedEventSet': 'diagnostics.related_event_set',
+ 'DateRange': 'diagnostics.date_range',
+ 'RelatedNameMap': 'diagnostics.related_name_map',
+}
+
+
+_CLASSES_BY_NAME = {}
+
+
+def IsDiagnosticTypename(name):
+ return name in _MODULES_BY_DIAGNOSTIC_NAME
+
+
+def GetDiagnosticTypenames():
+ return _MODULES_BY_DIAGNOSTIC_NAME.keys()
+
+
+def GetDiagnosticClassForName(name):
+ assert IsDiagnosticTypename(name)
+
+ if name in _CLASSES_BY_NAME:
+ return _CLASSES_BY_NAME[name]
+
+ module_name = 'tracing.value.%s' % _MODULES_BY_DIAGNOSTIC_NAME[name]
+ importlib.import_module(module_name)
+
+ cls = getattr(sys.modules[module_name], name)
+ _CLASSES_BY_NAME[name] = cls
+ return cls
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics_unittest.py
new file mode 100644
index 00000000000..9004114c3d9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/all_diagnostics_unittest.py
@@ -0,0 +1,27 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value.diagnostics import all_diagnostics
+
+
+class AllDiagnosticsUnittest(unittest.TestCase):
+
+ def testGetDiagnosticClassForName(self):
+ cls0 = all_diagnostics.GetDiagnosticClassForName('GenericSet')
+ gs0 = cls0(['foo'])
+ gs0_dict = gs0.AsDict()
+
+ # Run twice to ensure that the memoization isn't broken.
+ cls1 = all_diagnostics.GetDiagnosticClassForName('GenericSet')
+ gs1 = cls1(['foo'])
+ gs1_dict = gs1.AsDict()
+
+ self.assertEqual(gs0_dict['type'], 'GenericSet')
+ self.assertEqual(gs1_dict['type'], 'GenericSet')
+
+ def testGetDiagnosticClassForName_Bogus(self):
+ self.assertRaises(
+ AssertionError, all_diagnostics.GetDiagnosticClassForName, 'BogusDiag')
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.html
new file mode 100644
index 00000000000..bf19b381170
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ class Breakdown extends tr.v.d.Diagnostic {
+ constructor() {
+ super();
+ this.values_ = new Map();
+ this.colorScheme = undefined;
+ }
+
+ truncate(unit) {
+ for (const [name, value] of this) {
+ this.values_.set(name, unit.truncate(value));
+ }
+ }
+
+ clone() {
+ const clone = new Breakdown();
+ clone.colorScheme = this.colorScheme;
+ clone.addDiagnostic(this);
+ return clone;
+ }
+
+ canAddDiagnostic(otherDiagnostic) {
+ return ((otherDiagnostic instanceof Breakdown) &&
+ (otherDiagnostic.colorScheme === this.colorScheme));
+ }
+
+ addDiagnostic(otherDiagnostic) {
+ for (const [name, value] of otherDiagnostic) {
+ this.set(name, this.get(name) + value);
+ }
+ return this;
+ }
+
+ /**
+ * Add a Value by an explicit name to this map.
+ *
+ * @param {string} name
+ * @param {number} value
+ */
+ set(name, value) {
+ if (typeof name !== 'string' ||
+ typeof value !== 'number') {
+ throw new Error('Breakdown maps from strings to numbers');
+ }
+ this.values_.set(name, value);
+ }
+
+ /**
+ * @param {string} name
+ * @return {number}
+ */
+ get(name) {
+ return this.values_.get(name) || 0;
+ }
+
+ * [Symbol.iterator]() {
+ for (const pair of this.values_) {
+ yield pair;
+ }
+ }
+
+ get size() {
+ return this.values_.size;
+ }
+
+ asDictInto_(d) {
+ d.values = {};
+ for (const [name, value] of this) {
+ d.values[name] = tr.b.numberToJson(value);
+ }
+ if (this.colorScheme) {
+ d.colorScheme = this.colorScheme;
+ }
+ }
+
+ static fromEntries(entries) {
+ const breakdown = new Breakdown();
+ for (const [name, value] of entries) {
+ breakdown.set(name, value);
+ }
+ return breakdown;
+ }
+
+ static fromDict(d) {
+ const breakdown = new Breakdown();
+ for (const [name, value] of Object.entries(d.values)) {
+ breakdown.set(name, tr.b.numberFromJson(value));
+ }
+ if (d.colorScheme) {
+ breakdown.colorScheme = d.colorScheme;
+ }
+ return breakdown;
+ }
+ }
+
+ tr.v.d.Diagnostic.register(Breakdown, {
+ elementName: 'tr-v-ui-breakdown-span'
+ });
+
+ return {
+ Breakdown,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py
new file mode 100644
index 00000000000..5272734f469
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown.py
@@ -0,0 +1,73 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import math
+import numbers
+
+from tracing.value.diagnostics import diagnostic
+
+
+try:
+ StringTypes = basestring
+except NameError:
+ StringTypes = str
+
+
+class Breakdown(diagnostic.Diagnostic):
+ __slots__ = '_values', '_color_scheme'
+
+ def __init__(self):
+ super(Breakdown, self).__init__()
+ self._values = {}
+ self._color_scheme = None
+
+ @property
+ def color_scheme(self):
+ return self._color_scheme
+
+ @staticmethod
+ def FromDict(d):
+ result = Breakdown()
+ result._color_scheme = d.get('colorScheme')
+ for name, value in d['values'].items():
+ if value in ['NaN', 'Infinity', '-Infinity']:
+ value = float(value)
+ result.Set(name, value)
+ return result
+
+ def _AsDictInto(self, d):
+ d['values'] = {}
+ for name, value in self:
+ # JSON serializes NaN and the infinities as 'null', preventing
+ # distinguishing between them. Override that behavior by serializing them
+ # as their Javascript string names, not their python string names since
+ # the reference implementation is in Javascript.
+ if math.isnan(value):
+ value = 'NaN'
+ elif math.isinf(value):
+ if value > 0:
+ value = 'Infinity'
+ else:
+ value = '-Infinity'
+ d['values'][name] = value
+ if self._color_scheme:
+ d['colorScheme'] = self._color_scheme
+
+ def Set(self, name, value):
+ assert isinstance(name, StringTypes), (
+ 'Expected basestring, found %s: "%r"' % (type(name).__name__, name))
+ assert isinstance(value, numbers.Number), (
+ 'Expected number, found %s: "%r"', (type(value).__name__, value))
+ self._values[name] = value
+
+ def Get(self, name):
+ return self._values.get(name, 0)
+
+ def __iter__(self):
+ for name, value in self._values.items():
+ yield name, value
+
+ def __len__(self):
+ return len(self._values)
+
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown_test.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown_test.html
new file mode 100644
index 00000000000..23b4e54359d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown_test.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/breakdown.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('merge', function() {
+ const a = new tr.v.d.Breakdown();
+ a.set('x', 1);
+ a.set('y', 2);
+
+ const b = new tr.v.d.Breakdown();
+ b.set('y', 3);
+ b.set('z', 4);
+
+ assert.isTrue(a.canAddDiagnostic(b));
+ assert.isTrue(b.canAddDiagnostic(a));
+
+ a.addDiagnostic(b);
+ assert.strictEqual(a.get('x'), 1);
+ assert.strictEqual(a.get('y'), 5);
+ assert.strictEqual(a.get('z'), 4);
+
+ a.colorScheme = 'fake color scheme';
+ assert.isFalse(a.canAddDiagnostic(b));
+ assert.isFalse(b.canAddDiagnostic(a));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown_unittest.py
new file mode 100644
index 00000000000..ab9c6733771
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/breakdown_unittest.py
@@ -0,0 +1,31 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import math
+import unittest
+
+from tracing.value.diagnostics import breakdown
+from tracing.value.diagnostics import diagnostic
+
+
+class BreakdownUnittest(unittest.TestCase):
+
+ def testRoundtrip(self):
+ bd = breakdown.Breakdown()
+ bd.Set('one', 1)
+ bd.Set('m1', -1)
+ bd.Set('inf', float('inf'))
+ bd.Set('nun', float('nan'))
+ bd.Set('ninf', float('-inf'))
+ bd.Set('long', 2**65)
+ d = bd.AsDict()
+ clone = diagnostic.Diagnostic.FromDict(d)
+ self.assertEqual(json.dumps(d), json.dumps(clone.AsDict()))
+ self.assertEqual(clone.Get('one'), 1)
+ self.assertEqual(clone.Get('m1'), -1)
+ self.assertEqual(clone.Get('inf'), float('inf'))
+ self.assertTrue(math.isnan(clone.Get('nun')))
+ self.assertEqual(clone.Get('ninf'), float('-inf'))
+ self.assertEqual(clone.Get('long'), 2**65)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/collected_related_event_set.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/collected_related_event_set.html
new file mode 100644
index 00000000000..b88a8bf3349
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/collected_related_event_set.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ class CollectedRelatedEventSet extends tr.v.d.Diagnostic {
+ constructor() {
+ super();
+ this.eventSetsByCanonicalUrl_ = new Map();
+ }
+
+ asDictInto_(d) {
+ d.events = {};
+ for (const [canonicalUrl, eventSet] of this) {
+ d.events[canonicalUrl] = [];
+ for (const event of eventSet) {
+ d.events[canonicalUrl].push({
+ stableId: event.stableId,
+ title: event.title,
+ start: event.start,
+ duration: event.duration
+ });
+ }
+ }
+ }
+
+ static fromDict(d) {
+ const result = new CollectedRelatedEventSet();
+ for (const [canonicalUrl, events] of Object.entries(d.events)) {
+ result.eventSetsByCanonicalUrl_.set(canonicalUrl, events.map(
+ e => new tr.v.d.EventRef(e)));
+ }
+ return result;
+ }
+
+ get size() {
+ return this.eventSetsByCanonicalUrl_.size;
+ }
+
+ get(canonicalUrl) {
+ return this.eventSetsByCanonicalUrl_.get(canonicalUrl);
+ }
+
+ * [Symbol.iterator]() {
+ for (const [canonicalUrl, eventSet] of this.eventSetsByCanonicalUrl_) {
+ yield [canonicalUrl, eventSet];
+ }
+ }
+
+ canAddDiagnostic(otherDiagnostic) {
+ return otherDiagnostic instanceof tr.v.d.RelatedEventSet ||
+ otherDiagnostic instanceof tr.v.d.CollectedRelatedEventSet;
+ }
+
+ addEventSetForCanonicalUrl(canonicalUrl, events) {
+ let myEventSet = this.eventSetsByCanonicalUrl_.get(canonicalUrl);
+ if (myEventSet === undefined) {
+ myEventSet = new Set();
+ this.eventSetsByCanonicalUrl_.set(canonicalUrl, myEventSet);
+ }
+ for (const event of events) {
+ myEventSet.add(event);
+ }
+ }
+
+ addDiagnostic(otherDiagnostic) {
+ if (otherDiagnostic instanceof tr.v.d.CollectedRelatedEventSet) {
+ // Merge Maps of Sets.
+ for (const [canonicalUrl, otherEventSet] of otherDiagnostic) {
+ this.addEventSetForCanonicalUrl(canonicalUrl, otherEventSet);
+ }
+ return;
+ }
+
+ if (!otherDiagnostic.canonicalUrl) return;
+ this.addEventSetForCanonicalUrl(
+ otherDiagnostic.canonicalUrl, otherDiagnostic);
+ }
+ }
+
+ tr.v.d.Diagnostic.register(CollectedRelatedEventSet, {
+ elementName: 'tr-v-ui-collected-related-event-set-span'
+ });
+
+ return {
+ CollectedRelatedEventSet,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.html
new file mode 100644
index 00000000000..f519326b553
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ /**
+ * This class represents a mergeable range of Date objects.
+ * This range can contain 1 or 2 Dates.
+ */
+ class DateRange extends tr.v.d.Diagnostic {
+ /**
+ * @param {number} ms
+ */
+ constructor(ms) {
+ super();
+ this.range_ = new tr.b.math.Range();
+ this.range_.addValue(ms);
+ }
+
+ get minDate() {
+ return new Date(this.range_.min);
+ }
+
+ get maxDate() {
+ return new Date(this.range_.max);
+ }
+
+ get durationMs() {
+ return this.range_.duration;
+ }
+
+ clone() {
+ const clone = new tr.v.d.DateRange(this.range_.min);
+ clone.addDiagnostic(this);
+ return clone;
+ }
+
+ equals(other) {
+ if (!(other instanceof DateRange)) return false;
+ return this.range_.equals(other.range_);
+ }
+
+ canAddDiagnostic(otherDiagnostic) {
+ return otherDiagnostic instanceof DateRange;
+ }
+
+ addDiagnostic(other) {
+ this.range_.addRange(other.range_);
+ }
+
+ toString() {
+ const minDate = tr.b.formatDate(this.minDate);
+ if (this.durationMs === 0) return minDate;
+ const maxDate = tr.b.formatDate(this.maxDate);
+ return `${minDate} - ${maxDate}`;
+ }
+
+ asDictInto_(d) {
+ d.min = this.range_.min;
+ if (this.durationMs === 0) return;
+ d.max = this.range_.max;
+ }
+
+ static fromDict(d) {
+ const dateRange = new DateRange(d.min);
+ if (d.max !== undefined) dateRange.range_.addValue(d.max);
+ return dateRange;
+ }
+ }
+
+ tr.v.d.Diagnostic.register(DateRange, {
+ elementName: 'tr-v-ui-date-range-span'
+ });
+
+ return {
+ DateRange,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py
new file mode 100644
index 00000000000..3cdce45d49c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range.py
@@ -0,0 +1,71 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import datetime
+
+from tracing.value.diagnostics import diagnostic
+
+
+class DateRange(diagnostic.Diagnostic):
+ __slots__ = '_range',
+
+ def __init__(self, ms):
+ from tracing.value import histogram
+ super(DateRange, self).__init__()
+ self._range = histogram.Range()
+ self._range.AddValue(ms)
+
+ def __eq__(self, other):
+ if not isinstance(other, DateRange):
+ return False
+ return self._range == other._range
+
+ def __hash__(self):
+ return id(self)
+
+ @property
+ def min_date(self):
+ return datetime.datetime.utcfromtimestamp(self._range.min / 1000)
+
+ @property
+ def max_date(self):
+ return datetime.datetime.utcfromtimestamp(self._range.max / 1000)
+
+ @property
+ def min_timestamp(self):
+ return self._range.min
+
+ @property
+ def max_timestamp(self):
+ return self._range.max
+
+ @property
+ def duration_ms(self):
+ return self._range.duration
+
+ def __str__(self):
+ min_date = self.min_date.isoformat().replace('T', ' ')[:19]
+ if self.duration_ms == 0:
+ return min_date
+ max_date = self.max_date.isoformat().replace('T', ' ')[:19]
+ return min_date + ' - ' + max_date
+
+ def _AsDictInto(self, dct):
+ dct['min'] = self._range.min
+ if self.duration_ms == 0:
+ return
+ dct['max'] = self._range.max
+
+ @staticmethod
+ def FromDict(dct):
+ dr = DateRange(dct['min'])
+ if 'max' in dct:
+ dr._range.AddValue(dct['max'])
+ return dr
+
+ def CanAddDiagnostic(self, other_diagnostic):
+ return isinstance(other_diagnostic, DateRange)
+
+ def AddDiagnostic(self, other_diagnostic):
+ self._range.AddRange(other_diagnostic._range)
+
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range_unittest.py
new file mode 100644
index 00000000000..4636045da1c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/date_range_unittest.py
@@ -0,0 +1,31 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import calendar
+import unittest
+
+from tracing.value.diagnostics import date_range
+from tracing.value.diagnostics import diagnostic
+
+
+class DateRangeUnittest(unittest.TestCase):
+
+ def testRoundtrip(self):
+ dr = date_range.DateRange(1496693745000)
+ dr.AddDiagnostic(date_range.DateRange(1496693746000))
+ self.assertEqual(calendar.timegm(dr.min_date.timetuple()), 1496693745)
+ self.assertEqual(calendar.timegm(dr.max_date.timetuple()), 1496693746)
+ clone = diagnostic.Diagnostic.FromDict(dr.AsDict())
+ self.assertEqual(clone.min_date, dr.min_date)
+ self.assertEqual(clone.max_date, dr.max_date)
+
+ def testMinTimestamp(self):
+ dr = date_range.DateRange(1496693745123)
+ dr.AddDiagnostic(date_range.DateRange(1496693746123))
+ self.assertEqual(dr.min_timestamp, 1496693745123)
+
+ def testMaxTimestamp(self):
+ dr = date_range.DateRange(1496693745123)
+ dr.AddDiagnostic(date_range.DateRange(1496693746123))
+ self.assertEqual(dr.max_timestamp, 1496693746123)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.html
new file mode 100644
index 00000000000..cb3b4907563
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/extension_registry.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ class Diagnostic {
+ constructor() {
+ this.guid_ = undefined;
+ }
+
+ /**
+ * Returns a new Diagnostic that is like this one but distinct.
+ * This is useful when merging Diagnostics.
+ * @return {!tr.v.d.Diagnostic}
+ */
+ clone() {
+ return new this.constructor();
+ }
+
+ /**
+ * Return true if |this| can be merged with |otherDiagnostic|.
+ *
+ * @param {!tr.v.d.Diagnostic} otherDiagnostic
+ * @return {!boolean}
+ */
+ canAddDiagnostic(otherDiagnostic) {
+ return false;
+ }
+
+ /**
+ * If subclasses override canAddDiagnostic() then they must also override
+ * this method to modify |this| to include information from
+ * |otherDiagnostic|.
+ *
+ * @param {!tr.v.d.Diagnostic} otherDiagnostic
+ */
+ addDiagnostic(otherDiagnostic) {
+ throw new Error('Abstract virtual method: subclasses must override ' +
+ 'this method if they override canAddDiagnostic');
+ }
+
+ get guid() {
+ if (this.guid_ === undefined) {
+ this.guid_ = tr.b.GUID.allocateUUID4();
+ }
+
+ return this.guid_;
+ }
+
+ set guid(guid) {
+ if (this.guid_ !== undefined) {
+ throw new Error('Cannot reset guid');
+ }
+
+ this.guid_ = guid;
+ }
+
+ get hasGuid() {
+ return this.guid_ !== undefined;
+ }
+
+ /**
+ * If this Diagnostic is shared between multiple Histograms, then return its
+ * |guid|. Otherwise, serialize this Diagnostic to a dictionary.
+ *
+ * @return {string|!Object}
+ */
+ asDictOrReference() {
+ if (this.guid_ !== undefined) {
+ return this.guid_;
+ }
+ return this.asDict();
+ }
+
+ /**
+ * Serialize all of the information in this Diagnostic to a dictionary,
+ * regardless of whether it is shared between multiple Histograms.
+ *
+ * @return {!Object}
+ */
+ asDict() {
+ const result = {type: this.constructor.name};
+ if (this.guid_ !== undefined) {
+ result.guid = this.guid_;
+ }
+ this.asDictInto_(result);
+ return result;
+ }
+
+ asDictInto_(d) {
+ throw new Error('Abstract virtual method: subclasses must override ' +
+ 'this method if they override canAddDiagnostic');
+ }
+
+ static fromDict(d) {
+ const typeInfo = Diagnostic.findTypeInfoWithName(d.type);
+ if (!typeInfo) {
+ throw new Error('Unrecognized diagnostic type: ' + d.type);
+ }
+
+ const diagnostic = typeInfo.constructor.fromDict(d);
+ if (d.guid !== undefined) diagnostic.guid = d.guid;
+ return diagnostic;
+ }
+ }
+
+ const options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);
+ options.defaultMetadata = {};
+ options.mandatoryBaseClass = Diagnostic;
+ tr.b.decorateExtensionRegistry(Diagnostic, options);
+
+ Diagnostic.addEventListener('will-register', function(e) {
+ const constructor = e.typeInfo.constructor;
+ if (!(constructor.fromDict instanceof Function) ||
+ (constructor.fromDict === Diagnostic.fromDict) ||
+ (constructor.fromDict.length !== 1)) {
+ throw new Error('Diagnostics must define fromDict(d)');
+ }
+ });
+
+ return {
+ Diagnostic,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py
new file mode 100644
index 00000000000..d2decda8f12
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic.py
@@ -0,0 +1,95 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import uuid
+
+try:
+ from py_utils import slots_metaclass
+ SlotsMetaclass = slots_metaclass.SlotsMetaclass # pylint: disable=invalid-name
+except ImportError:
+ # TODO(benjhayden): Figure out why py_utils doesn't work in dev_appserver.py
+ SlotsMetaclass = None # pylint: disable=invalid-name
+
+from tracing.value.diagnostics import all_diagnostics
+
+
+class Diagnostic(object):
+ __slots__ = '_guid',
+
+ # Ensure that new subclasses remember to specify __slots__ in order to prevent
+ # regressing memory consumption:
+ if SlotsMetaclass:
+ __metaclass__ = SlotsMetaclass
+
+ def __init__(self):
+ self._guid = None
+
+ def __ne__(self, other):
+ return not self == other
+
+ @property
+ def guid(self):
+ if self._guid is None:
+ self._guid = str(uuid.uuid4())
+ return self._guid
+
+ @guid.setter
+ def guid(self, g):
+ assert self._guid is None
+ self._guid = g
+
+ @property
+ def has_guid(self):
+ return self._guid is not None
+
+ def AsDictOrReference(self):
+ if self._guid:
+ return self._guid
+ return self.AsDict()
+
+ def AsDict(self):
+ dct = {'type': self.__class__.__name__}
+ if self._guid:
+ dct['guid'] = self._guid
+ self._AsDictInto(dct)
+ return dct
+
+ def _AsDictInto(self, unused_dct):
+ raise NotImplementedError
+
+ @staticmethod
+ def FromDict(dct):
+ cls = all_diagnostics.GetDiagnosticClassForName(dct['type'])
+ if not cls:
+ raise ValueError('Unrecognized diagnostic type: ' + dct['type'])
+ diagnostic = cls.FromDict(dct)
+ if 'guid' in dct:
+ diagnostic.guid = dct['guid']
+ return diagnostic
+
+ def ResetGuid(self, guid=None):
+ if guid:
+ self._guid = guid
+ else:
+ self._guid = str(uuid.uuid4())
+
+ def Inline(self):
+ """Inlines a shared diagnostic.
+
+ Any diagnostic that has a guid will be serialized as a reference, because it
+ is assumed that diagnostics with guids are shared. This method removes the
+ guid so that the diagnostic will be serialized by value.
+
+ Inling is used for example in the dashboard, where certain types of shared
+ diagnostics that vary on a per-upload basis are inlined for efficiency
+ reasons.
+ """
+ self._guid = None
+
+ def CanAddDiagnostic(self, unused_other_diagnostic):
+ return False
+
+ def AddDiagnostic(self, unused_other_diagnostic):
+ raise Exception('Abstract virtual method: subclasses must override '
+ 'this method if they override canAddDiagnostic')
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_map.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_map.html
new file mode 100644
index 00000000000..79af5824b7e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_map.html
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+ Include all Diagnostic subclasses here so that DiagnosticMap.addDicts() and
+ DiagnosticMap.fromDict() always have access to all subclasses in the
+ Diagnostic registry.
+-->
+<link rel="import" href="/tracing/value/diagnostics/all_diagnostics.html">
+<link rel="import" href="/tracing/value/diagnostics/reserved_names.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ class DiagnosticMap extends Map {
+ /**
+ * @param {boolean=} opt_allowReservedNames defaults to true
+ */
+ constructor(opt_allowReservedNames) {
+ super();
+ if (opt_allowReservedNames === undefined) {
+ opt_allowReservedNames = true;
+ }
+ this.allowReservedNames_ = opt_allowReservedNames;
+ }
+
+ /**
+ * Add a new Diagnostic to this map.
+ *
+ * @param {string} name
+ * @param {!tr.v.d.Diagnostic} diagnostic
+ */
+ set(name, diagnostic) {
+ if (typeof(name) !== 'string') {
+ throw new Error(`name must be string, not ${name}`);
+ }
+
+ if (!(diagnostic instanceof tr.v.d.Diagnostic) &&
+ !(diagnostic instanceof tr.v.d.DiagnosticRef)) {
+ throw new Error(`Must be instanceof Diagnostic: ${diagnostic}`);
+ }
+
+ // TODO(#3507): Reserved names should never be UnmergeableDiagnosticSet.
+ if (!this.allowReservedNames_ &&
+ tr.v.d.RESERVED_NAMES_SET.has(name) &&
+ !(diagnostic instanceof tr.v.d.UnmergeableDiagnosticSet) &&
+ !(diagnostic instanceof tr.v.d.DiagnosticRef)) {
+ const type = tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);
+ if (type && !(diagnostic instanceof type)) {
+ throw new Error(
+ `Diagnostics named "${name}" must be ${type.name}, ` +
+ `not ${diagnostic.constructor.name}`);
+ }
+ }
+
+ Map.prototype.set.call(this, name, diagnostic);
+ }
+
+ delete(name) {
+ if (name === undefined) throw new Error('missing name');
+ Map.prototype.delete.call(this, name);
+ }
+
+ /**
+ * Add Diagnostics from a dictionary of dictionaries.
+ *
+ * @param {Object} dict
+ */
+ addDicts(dict) {
+ for (const [name, diagnosticDict] of Object.entries(dict)) {
+ if (name === 'tagmap') continue;
+ if (typeof diagnosticDict === 'string') {
+ this.set(name, new tr.v.d.DiagnosticRef(diagnosticDict));
+ } else if (diagnosticDict.type !== 'RelatedHistogramMap' &&
+ diagnosticDict.type !== 'RelatedHistogramBreakdown' &&
+ diagnosticDict.type !== 'TagMap') {
+ // Ignore RelatedHistograms and TagMaps.
+ // TODO(benjhayden): Forget about them in 2019 Q2.
+ this.set(name, tr.v.d.Diagnostic.fromDict(diagnosticDict));
+ }
+ }
+ }
+
+ resolveSharedDiagnostics(histograms, opt_required) {
+ for (const [name, value] of this) {
+ if (!(value instanceof tr.v.d.DiagnosticRef)) {
+ continue;
+ }
+
+ const guid = value.guid;
+ const diagnostic = histograms.lookupDiagnostic(guid);
+ if (diagnostic instanceof tr.v.d.Diagnostic) {
+ this.set(name, diagnostic);
+ } else if (opt_required) {
+ throw new Error('Unable to find shared Diagnostic ' + guid);
+ }
+ }
+ }
+
+ asDict() {
+ const dict = {};
+ for (const [name, diagnostic] of this) {
+ dict[name] = diagnostic.asDictOrReference();
+ }
+ return dict;
+ }
+
+ static fromDict(d) {
+ const diagnostics = new DiagnosticMap();
+ diagnostics.addDicts(d);
+ return diagnostics;
+ }
+
+ /**
+ * Convert dictionary or ES6 Map to DiagnosticMap.
+ * @param {!Object|!Map.<string, !tr.v.d.Diagnostic>} obj
+ * @return {tr.v.d.DiagnosticMap}
+ */
+ static fromObject(obj) {
+ const diagnostics = new DiagnosticMap();
+ if (!(obj instanceof Map)) obj = Object.entries(obj);
+ for (const [name, diagnostic] of obj) {
+ if (!diagnostic) continue;
+ diagnostics.set(name, diagnostic);
+ }
+ return diagnostics;
+ }
+
+ addDiagnostics(other) {
+ for (const [name, otherDiagnostic] of other) {
+ const myDiagnostic = this.get(name);
+
+ if (myDiagnostic !== undefined &&
+ myDiagnostic.canAddDiagnostic(otherDiagnostic)) {
+ myDiagnostic.addDiagnostic(otherDiagnostic);
+ continue;
+ }
+
+ // We need to avoid storing references to |otherDiagnostic| in both
+ // |this| and |other| because future merge()s may add yet other
+ // Diagnostics to |this|, and they shouldn't accidentally modify
+ // anything in |other|.
+ // Now, either |this| doesn't already have a Diagnostic named |name|
+ // (myDiagnostic is undefined), or
+ // |this| already has a Diagnostic named |name| that can't be merged
+ // with |otherDiagnostic|.
+ // Either way, we need to clone |otherDiagnostic|.
+ // However, clones produced via fromDict/toDict cannot necessarily be
+ // merged with yet other Diagnostics, either because of semantics (as in
+ // the case of TelemtryInfo and the like) or because guids must not be
+ // shared by distinct Diagnostics. Therefore, Diagnostics support
+ // another way of cloning that is specifically targeted at supporting
+ // merging: clone().
+
+ const clone = otherDiagnostic.clone();
+
+ if (myDiagnostic === undefined) {
+ this.set(name, clone);
+ continue;
+ }
+
+ // Now, |myDiagnostic| exists and it is unmergeable with |clone|, which
+ // is safe to store in |this|.
+ this.set(name, new tr.v.d.UnmergeableDiagnosticSet(
+ [myDiagnostic, clone]));
+ }
+ }
+ }
+
+ return {DiagnosticMap};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_map_test.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_map_test.html
new file mode 100644
index 00000000000..8d0781fb22d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_map_test.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('clone', function() {
+ const diagnostics = new tr.v.d.DiagnosticMap();
+ diagnostics.set('generic', new tr.v.d.GenericSet([{a: ['b', 3]}]));
+ diagnostics.set('breakdown', new tr.v.d.Breakdown());
+ diagnostics.set('events', new tr.v.d.RelatedEventSet());
+
+ const clone = tr.v.d.DiagnosticMap.fromDict(diagnostics.asDict());
+ assert.instanceOf(clone.get('generic'), tr.v.d.GenericSet);
+ assert.deepEqual(tr.b.getOnlyElement(clone.get('generic')),
+ tr.b.getOnlyElement(diagnostics.get('generic')));
+ assert.instanceOf(clone.get('breakdown'), tr.v.d.Breakdown);
+ assert.instanceOf(clone.get('events'), tr.v.d.RelatedEventSet);
+ });
+
+ test('fromObject', function() {
+ assert.strictEqual(tr.v.d.DiagnosticMap.fromObject(
+ {a: new tr.v.d.GenericSet([])}).size, 1);
+ assert.strictEqual(tr.v.d.DiagnosticMap.fromObject(
+ new Map([['a', new tr.v.d.GenericSet([])]])).size, 1);
+ });
+
+ test('cloneWithRef', function() {
+ const diagnostics = new tr.v.d.DiagnosticMap();
+ diagnostics.set('ref', new tr.v.d.DiagnosticRef('abc'));
+
+ const clone = tr.v.d.DiagnosticMap.fromDict(diagnostics.asDict());
+ assert.instanceOf(clone.get('ref'), tr.v.d.DiagnosticRef);
+ assert.strictEqual(clone.get('ref').guid, 'abc');
+ });
+
+ test('requireFromDict', function() {
+ class MissingFromDict extends tr.v.d.Diagnostic { }
+ assert.throws(() => tr.v.d.Diagnostic.register(MissingFromDict));
+
+ class InvalidFromDict extends tr.v.d.Diagnostic {
+ static fromDict() {
+ }
+ }
+ assert.throws(() => tr.v.d.Diagnostic.register(InvalidFromDict));
+ });
+
+ test('merge', function() {
+ const event = tr.c.TestUtils.newSliceEx({
+ title: 'event',
+ start: 0,
+ duration: 1,
+ });
+ event.parentContainer = {
+ sliceGroup: {
+ stableId: 'fake_thread',
+ slices: [event],
+ },
+ };
+ const generic = new tr.v.d.GenericSet(['generic diagnostic']);
+ const generic2 = new tr.v.d.GenericSet(['generic diagnostic 2']);
+ const events = new tr.v.d.RelatedEventSet([event]);
+
+ // When Histograms are merged, first an empty clone is created with an empty
+ // DiagnosticMap.
+ const hist = new tr.v.Histogram('', tr.b.Unit.byName.count);
+
+ const hist2 = new tr.v.Histogram('', tr.b.Unit.byName.count);
+ hist2.diagnostics.set('a', generic);
+ hist.diagnostics.addDiagnostics(hist2.diagnostics);
+ assert.strictEqual(tr.b.getOnlyElement(generic),
+ tr.b.getOnlyElement(hist.diagnostics.get('a')));
+
+ // Separate keys are not merged.
+ const hist3 = new tr.v.Histogram('', tr.b.Unit.byName.count);
+ hist3.diagnostics.set('b', generic2);
+ hist.diagnostics.addDiagnostics(hist3.diagnostics);
+ assert.strictEqual(
+ tr.b.getOnlyElement(generic),
+ tr.b.getOnlyElement(hist.diagnostics.get('a')));
+ assert.strictEqual(
+ tr.b.getOnlyElement(generic2),
+ tr.b.getOnlyElement(hist.diagnostics.get('b')));
+
+ // Merging unmergeable diagnostics should produce an
+ // UnmergeableDiagnosticSet.
+ const hist4 = new tr.v.Histogram('', tr.b.Unit.byName.count);
+ hist4.diagnostics.set('a', new tr.v.d.RelatedNameMap());
+ hist.diagnostics.addDiagnostics(hist4.diagnostics);
+ assert.instanceOf(hist.diagnostics.get('a'),
+ tr.v.d.UnmergeableDiagnosticSet);
+ let diagnostics = Array.from(hist.diagnostics.get('a'));
+ assert.strictEqual(
+ tr.b.getOnlyElement(generic), tr.b.getOnlyElement(diagnostics[0]));
+
+ // UnmergeableDiagnosticSets are mergeable.
+ const hist5 = new tr.v.Histogram('', tr.b.Unit.byName.count);
+ hist5.diagnostics.set('a', new tr.v.d.UnmergeableDiagnosticSet([
+ events, generic2]));
+ hist.diagnostics.addDiagnostics(hist5.diagnostics);
+ assert.instanceOf(hist.diagnostics.get('a'),
+ tr.v.d.UnmergeableDiagnosticSet);
+ diagnostics = Array.from(hist.diagnostics.get('a'));
+ assert.lengthOf(diagnostics, 3);
+ assert.instanceOf(diagnostics[0], tr.v.d.GenericSet);
+ assert.deepEqual(Array.from(diagnostics[0]), [...generic, ...generic2]);
+ assert.instanceOf(diagnostics[2], tr.v.d.CollectedRelatedEventSet);
+ });
+
+ test('validateDiagnosticTypes', function() {
+ const hist = new tr.v.Histogram('', tr.b.Unit.byName.count);
+ function addInvalidDiagnosticType() {
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.TRACE_START, new tr.v.d.GenericSet(['foo']));
+ }
+ assert.throw(addInvalidDiagnosticType, Error,
+ `Diagnostics named "${tr.v.d.RESERVED_NAMES.TRACE_START}" must be ` +
+ 'DateRange, not GenericSet');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_ref.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_ref.html
new file mode 100644
index 00000000000..ac30d88cd65
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_ref.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ /**
+ * This is a placeholder to allow many DiagnosticMaps to contain references to
+ * the same Diagnostic.
+ */
+ class DiagnosticRef {
+ /**
+ * @param {string} guid
+ */
+ constructor(guid) {
+ this.guid = guid;
+ }
+
+ asDict() {
+ return this.guid;
+ }
+
+ asDictOrReference() {
+ return this.asDict();
+ }
+ }
+
+ return {
+ DiagnosticRef,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_ref.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_ref.py
new file mode 100644
index 00000000000..fe86099af13
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_ref.py
@@ -0,0 +1,22 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class DiagnosticRef(object):
+ def __init__(self, guid):
+ self._guid = guid
+
+ @property
+ def guid(self):
+ return self._guid
+
+ @property
+ def has_guid(self):
+ return True
+
+ def AsDict(self):
+ return self.guid
+
+ def AsDictOrReference(self):
+ return self.AsDict()
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_test.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_test.html
new file mode 100644
index 00000000000..55a49aa65b6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_test.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/all_diagnostics.html">
+<link rel="import" href="/tracing/value/diagnostics/generic_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('roundtripPreservesGuid', function() {
+ const diagnostic = new tr.v.d.GenericSet(['generic']);
+ diagnostic.guid = 'foo';
+ const clone = tr.v.d.Diagnostic.fromDict(diagnostic.asDict());
+ assert.strictEqual('foo', clone.guid);
+ });
+
+ test('equalitySmokeTest', function() {
+ const infos = tr.v.d.Diagnostic.getAllRegisteredTypeInfos();
+
+ for (const info of infos) {
+ assert.hasOwnProperty(info, 'equals');
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_unittest.py
new file mode 100644
index 00000000000..f3c1a1f9b64
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/diagnostic_unittest.py
@@ -0,0 +1,15 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value.diagnostics import all_diagnostics
+
+
+class DiagnosticUnittest(unittest.TestCase):
+
+ def testEqualityForSmoke(self):
+ for name in all_diagnostics.GetDiagnosticTypenames():
+ ctor = all_diagnostics.GetDiagnosticClassForName(name)
+ self.assertTrue(hasattr(ctor, '__eq__'))
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/discover_cmdline.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/discover_cmdline.html
new file mode 100644
index 00000000000..293a5086508
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/discover_cmdline.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+function isDiagnosticSubclass(cls) {
+ cls = cls.__proto__;
+ while (cls) {
+ if (cls === tr.v.d.Diagnostic) return true;
+ cls = cls.__proto__;
+ }
+ return false;
+}
+
+function discoverDiagnostics(args) {
+ const discoveryMode = args.shift();
+ for (const arg of args) HTMLImportsLoader.loadHTML(arg);
+
+ const results = [];
+ if (discoveryMode === 'registry') {
+ for (const typeInfo of tr.v.d.Diagnostic.getAllRegisteredTypeInfos()) {
+ results.push(typeInfo.constructor.name);
+ }
+ } else if (discoveryMode === 'namespace') {
+ for (const cls of Object.values(tr.v.d)) {
+ if (isDiagnosticSubclass(cls)) results.push(cls.name);
+ }
+ } else {
+ console.log('First argument must be either "registry" or "namespace".');
+ return 1;
+ }
+ console.log(JSON.stringify(results));
+ return 0;
+}
+
+if (tr.isHeadless) {
+ quit(discoverDiagnostics(sys.argv.slice(1)));
+}
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/event_ref.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/event_ref.html
new file mode 100644
index 00000000000..d582272f0e6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/event_ref.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/guid.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ /**
+ * This is a placeholder in case the referenced Event isn't available in
+ * memory to point to directly.
+ */
+ class EventRef {
+ /**
+ * @param {!Object} event
+ * @param {string} event.stableId
+ * @param {string} event.title
+ * @param {number} event.start
+ * @param {number} event.duration
+ */
+ constructor(event) {
+ this.stableId = event.stableId;
+ this.title = event.title;
+ this.start = event.start;
+ this.duration = event.duration;
+ this.end = this.start + this.duration;
+
+ // tr.v.d.RelatedEventSet identifies events using stableId, but
+ // tr.model.EventSet uses guid.
+ this.guid = tr.b.GUID.allocateSimple();
+ }
+ }
+
+ return {
+ EventRef,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.html
new file mode 100644
index 00000000000..e0c0664b958
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ /**
+ * Stringify Arrays or dictionaries. Sorts dictionaries keys. Non-recursive.
+ *
+ * @param {!Object} obj
+ * @return {string}
+ */
+ function stableStringify(obj) {
+ let replacer;
+ if (!(obj instanceof Array) && obj !== null) {
+ replacer = Object.keys(obj).sort();
+ }
+ return JSON.stringify(obj, replacer);
+ }
+
+ /**
+ * @typedef {(null|number|string|boolean|Array.<!PlainOldData>|!Object)}
+ * PlainOldData
+ */
+
+ class GenericSet extends tr.v.d.Diagnostic {
+ /**
+ * @param {!Iterable.<!PlainOldData>} values
+ */
+ constructor(values) {
+ super();
+
+ if (typeof values[Symbol.iterator] !== 'function') {
+ throw new Error('GenericSet must be constructed from an interable.');
+ }
+
+ this.values_ = new Set(values);
+ this.has_objects_ = false;
+
+ for (const value of values) {
+ if (typeof value === 'object') {
+ this.has_objects_ = true;
+ }
+ }
+ }
+
+ get size() {
+ return this.values_.size;
+ }
+
+ get length() {
+ return this.values_.size;
+ }
+
+ * [Symbol.iterator]() {
+ for (const value of this.values_) {
+ yield value;
+ }
+ }
+
+ has(value) {
+ if (typeof value !== 'object') return this.values_.has(value);
+ const json = JSON.stringify(value);
+ for (const x of this) {
+ if (typeof x !== 'object') continue;
+ if (json === JSON.stringify(x)) return true;
+ }
+ return false;
+ }
+
+ equals(other) {
+ if (!(other instanceof GenericSet)) return false;
+ if (this.size !== other.size) return false;
+ for (const value of this) {
+ if (!other.has(value)) return false;
+ }
+ return true;
+ }
+
+ get hashKey() {
+ if (this.has_objects_) return undefined;
+
+ if (this.hash_key_ !== undefined) {
+ return this.hash_key_;
+ }
+
+ let key = '';
+ for (const value of Array.from(this.values_.values()).sort()) {
+ key += value;
+ }
+ this.hash_key_ = key;
+ return key;
+ }
+
+ asDictInto_(d) {
+ d.values = Array.from(this);
+ }
+
+ static fromDict(d) {
+ return new GenericSet(d.values);
+ }
+
+ clone() {
+ return new GenericSet(this.values_);
+ }
+
+ canAddDiagnostic(otherDiagnostic) {
+ return otherDiagnostic instanceof GenericSet;
+ }
+
+ addDiagnostic(otherDiagnostic) {
+ const jsons = new Set();
+ for (const value of this) {
+ if (typeof value !== 'object') continue;
+ jsons.add(stableStringify(value));
+ }
+
+ for (const value of otherDiagnostic) {
+ if (typeof value === 'object') {
+ if (jsons.has(stableStringify(value))) {
+ continue;
+ }
+ this.has_objects_ = true;
+ }
+ this.values_.add(value);
+ }
+ }
+ }
+
+ tr.v.d.Diagnostic.register(GenericSet, {
+ elementName: 'tr-v-ui-generic-set-span'
+ });
+
+ return {
+ GenericSet,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py
new file mode 100644
index 00000000000..e4a2b19f4c7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set.py
@@ -0,0 +1,82 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+
+from tracing.value.diagnostics import diagnostic
+
+
+class GenericSet(diagnostic.Diagnostic):
+ """Contains any Plain-Ol'-Data objects.
+
+ Contents are serialized using json.dumps(): None, boolean, number, string,
+ list, dict. Dicts, lists, and booleans are deduplicated by their JSON
+ representation. Dicts and lists are not hashable. (1 == True) and (0 ==
+ False) in Python, but not in JSON.
+ """
+ __slots__ = '_values', '_comparable_set'
+
+ def __init__(self, values):
+ super(GenericSet, self).__init__()
+
+ self._values = list(values)
+ self._comparable_set = None
+
+ def __iter__(self):
+ for value in self._values:
+ yield value
+
+ def __len__(self):
+ return len(self._values)
+
+ def __eq__(self, other):
+ return self._GetComparableSet() == other._GetComparableSet()
+
+ def __hash__(self):
+ return id(self)
+
+ def SetValues(self, values):
+ # Use a list because Python sets cannot store dicts or lists because they
+ # are not hashable.
+ self._values = list(values)
+
+ # Cache a set to facilitate comparing and merging GenericSets.
+ # Dicts, lists, and booleans are serialized; other types are not.
+ self._comparable_set = None
+
+ def _GetComparableSet(self):
+ if self._comparable_set is None:
+ self._comparable_set = set()
+ for value in self:
+ if isinstance(value, (dict, list, bool)):
+ self._comparable_set.add(json.dumps(value, sort_keys=True))
+ else:
+ self._comparable_set.add(value)
+ return self._comparable_set
+
+ def CanAddDiagnostic(self, other_diagnostic):
+ return isinstance(other_diagnostic, GenericSet)
+
+ def AddDiagnostic(self, other_diagnostic):
+ comparable_set = self._GetComparableSet()
+ for value in other_diagnostic:
+ if isinstance(value, (dict, list, bool)):
+ json_value = json.dumps(value, sort_keys=True)
+ if json_value not in comparable_set:
+ self._values.append(value)
+ self._comparable_set.add(json_value)
+ elif value not in comparable_set:
+ self._values.append(value)
+ self._comparable_set.add(value)
+
+ def _AsDictInto(self, dct):
+ dct['values'] = list(self)
+
+ @staticmethod
+ def FromDict(dct):
+ return GenericSet(dct['values'])
+
+ def GetOnlyElement(self):
+ assert len(self) == 1
+ return self._values[0]
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set_test.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set_test.html
new file mode 100644
index 00000000000..8ce850e220b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set_test.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/generic_set.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('merge', function() {
+ const a = new tr.v.d.GenericSet(['a']);
+ const b = new tr.v.d.GenericSet(['b']);
+
+ assert.isTrue(a.canAddDiagnostic(b));
+ assert.isTrue(b.canAddDiagnostic(a));
+
+ const ab = a.clone();
+ ab.addDiagnostic(b);
+ assert.deepEqual(Array.from(ab), ['a', 'b']);
+
+ const bab = b.clone();
+ bab.addDiagnostic(ab);
+ assert.deepEqual(Array.from(bab), ['b', 'a']);
+ });
+
+ test('mergeDictionaries', function() {
+ const a = new tr.v.d.GenericSet([{a: 1, b: 2}]);
+ const b = new tr.v.d.GenericSet([{b: 2, a: 1}]);
+ const ab = a.clone();
+ assert.strictEqual(tr.b.getOnlyElement(a), tr.b.getOnlyElement(ab));
+ ab.addDiagnostic(b);
+ assert.lengthOf(ab, 1);
+ assert.strictEqual(tr.b.getOnlyElement(a), tr.b.getOnlyElement(ab));
+ });
+
+ test('addDiagnosticWithNull', function() {
+ const a = new tr.v.d.GenericSet([]);
+ const b = new tr.v.d.GenericSet([null]);
+ a.addDiagnostic(b);
+ assert.lengthOf(a, 1);
+ assert.isTrue(a.has(null));
+ });
+
+ test('hashKey', function() {
+ const a = new tr.v.d.GenericSet(['a', 'b']);
+ assert.strictEqual(a.hashKey, 'ab');
+ });
+
+ test('setsWithoutObjectsSupportFastPath', function() {
+ const a = new tr.v.d.GenericSet(['a', 'b']);
+ assert.isDefined(a.hashKey);
+ });
+
+ test('setsWithObjectsDoNotSupportFastPath', function() {
+ const a = new tr.v.d.GenericSet([{foo: 'bar'}]);
+ assert.isUndefined(a.hashKey);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set_unittest.py
new file mode 100644
index 00000000000..00ba42e10a0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/generic_set_unittest.py
@@ -0,0 +1,100 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value.diagnostics import diagnostic
+from tracing.value.diagnostics import generic_set
+
+
+class GenericSetUnittest(unittest.TestCase):
+
+ def testRoundtrip(self):
+ a_set = generic_set.GenericSet([
+ None,
+ True,
+ False,
+ 0,
+ 1,
+ 42,
+ [],
+ {},
+ [0, False],
+ {'a': 1, 'b': True},
+ ])
+ self.assertEqual(a_set, diagnostic.Diagnostic.FromDict(a_set.AsDict()))
+
+ def testEq(self):
+ a_set = generic_set.GenericSet([
+ None,
+ True,
+ False,
+ 0,
+ 1,
+ 42,
+ [],
+ {},
+ [0, False],
+ {'a': 1, 'b': True},
+ ])
+ b_set = generic_set.GenericSet([
+ {'b': True, 'a': 1},
+ [0, False],
+ {},
+ [],
+ 42,
+ 1,
+ 0,
+ False,
+ True,
+ None,
+ ])
+ self.assertEqual(a_set, b_set)
+
+ def testMerge(self):
+ a_set = generic_set.GenericSet([
+ None,
+ True,
+ False,
+ 0,
+ 1,
+ 42,
+ [],
+ {},
+ [0, False],
+ {'a': 1, 'b': True},
+ ])
+ b_set = generic_set.GenericSet([
+ {'b': True, 'a': 1},
+ [0, False],
+ {},
+ [],
+ 42,
+ 1,
+ 0,
+ False,
+ True,
+ None,
+ ])
+ self.assertTrue(a_set.CanAddDiagnostic(b_set))
+ self.assertTrue(b_set.CanAddDiagnostic(a_set))
+ a_set.AddDiagnostic(b_set)
+ self.assertEqual(a_set, b_set)
+ b_set.AddDiagnostic(a_set)
+ self.assertEqual(a_set, b_set)
+
+ c_dict = {'a': 1, 'b': 1}
+ c_set = generic_set.GenericSet([c_dict])
+ a_set.AddDiagnostic(c_set)
+ self.assertEqual(len(a_set), 1 + len(b_set))
+ self.assertIn(c_dict, a_set)
+
+ def testGetOnlyElement(self):
+ gs = generic_set.GenericSet(['foo'])
+ self.assertEqual(gs.GetOnlyElement(), 'foo')
+
+ def testGetOnlyElementRaises(self):
+ gs = generic_set.GenericSet([])
+ with self.assertRaises(AssertionError):
+ gs.GetOnlyElement()
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.html
new file mode 100644
index 00000000000..8021e661159
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/model/event_set.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+<link rel="import" href="/tracing/value/diagnostics/event_ref.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ /**
+ * @typedef {!(tr.v.d.EventRef|tr.model.Event)} EventLike
+ */
+
+ /**
+ * A RelatedEventSet diagnostic contains references to Events
+ */
+ class RelatedEventSet extends tr.v.d.Diagnostic {
+ /**
+ * @param {!(tr.model.EventSet|Array.<EventLike>|EventLike)=} opt_events
+ */
+ constructor(opt_events) {
+ super();
+ this.eventsByStableId_ = new Map();
+ // TODO(#2431) Plumb canonicalUrl from event.model.
+ this.canonicalUrl_ = undefined;
+
+ if (opt_events) {
+ if (opt_events instanceof tr.model.EventSet ||
+ opt_events instanceof Array) {
+ for (const event of opt_events) {
+ this.add(event);
+ }
+ } else {
+ this.add(opt_events);
+ }
+ }
+ }
+
+ clone() {
+ const clone = new tr.v.d.CollectedRelatedEventSet();
+ clone.addDiagnostic(this);
+ return clone;
+ }
+
+ /**
+ * @param {!(tr.v.d.EventRef|tr.model.Event)} event
+ */
+ add(event) {
+ this.eventsByStableId_.set(event.stableId, event);
+ }
+
+ /**
+ * @param {!(tr.v.d.EventRef|tr.model.Event)} event
+ * @return {boolean}
+ */
+ has(event) {
+ return this.eventsByStableId_.has(event.stableId);
+ }
+
+ get length() {
+ return this.eventsByStableId_.size;
+ }
+
+ * [Symbol.iterator]() {
+ for (const event of this.eventsByStableId_.values()) {
+ yield event;
+ }
+ }
+
+ get canonicalUrl() {
+ return this.canonicalUrl_;
+ }
+
+ /**
+ * Resolve all EventRefs into Events by finding their stableIds in |model|.
+ * If a stableId cannot be found and |opt_required| is true, then throw an
+ * Error.
+ * If a stableId cannot be found and |opt_required| is false, then the
+ * EventRef will remain an EventRef.
+ *
+ * @param {!tr.model.Model} model
+ * @param {boolean=} opt_required
+ */
+ resolve(model, opt_required) {
+ for (const [stableId, value] of this.eventsByStableId_) {
+ if (!(value instanceof tr.v.d.EventRef)) continue;
+
+ const event = model.getEventByStableId(stableId);
+ if (event instanceof tr.model.Event) {
+ this.eventsByStableId_.set(stableId, event);
+ } else if (opt_required) {
+ throw new Error('Unable to find Event ' + stableId);
+ }
+ }
+ }
+
+ asDictInto_(d) {
+ d.events = [];
+ for (const event of this) {
+ d.events.push({
+ stableId: event.stableId,
+ title: event.title,
+ start: tr.b.Unit.byName.timeStampInMs.truncate(event.start),
+ duration: tr.b.Unit.byName.timeDurationInMs.truncate(event.duration),
+ });
+ }
+ }
+
+ static fromDict(d) {
+ return new RelatedEventSet(d.events.map(
+ event => new tr.v.d.EventRef(event)));
+ }
+ }
+
+ tr.v.d.Diagnostic.register(RelatedEventSet, {
+ elementName: 'tr-v-ui-related-event-set-span'
+ });
+
+ return {
+ RelatedEventSet,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py
new file mode 100644
index 00000000000..f4bbad3c596
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set.py
@@ -0,0 +1,34 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from tracing.value.diagnostics import diagnostic
+
+
+class RelatedEventSet(diagnostic.Diagnostic):
+ __slots__ = '_events_by_stable_id',
+
+ def __init__(self):
+ super(RelatedEventSet, self).__init__()
+ self._events_by_stable_id = {}
+
+ def Add(self, event):
+ self._events_by_stable_id[event['stableId']] = event
+
+ def __len__(self):
+ return len(self._events_by_stable_id)
+
+ def __iter__(self):
+ for event in self._events_by_stable_id.values():
+ yield event
+
+ @staticmethod
+ def FromDict(d):
+ result = RelatedEventSet()
+ for event in d['events']:
+ result.Add(event)
+ return result
+
+ def _AsDictInto(self, d):
+ d['events'] = [event for event in self]
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set_test.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set_test.html
new file mode 100644
index 00000000000..8019f67172f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set_test.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('eventSet', function() {
+ let slice = undefined;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ slice = tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ title: 'foo',
+ start: 0,
+ duration: 10
+ });
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ thread.sliceGroup.pushSlice(slice);
+ });
+
+ let d = new tr.v.d.RelatedEventSet(slice);
+ assert.strictEqual(tr.b.getOnlyElement([...d]), slice);
+
+ d = new tr.v.d.RelatedEventSet([slice]);
+ assert.strictEqual(tr.b.getOnlyElement([...d]), slice);
+
+ d = new tr.v.d.RelatedEventSet(new tr.model.EventSet([slice]));
+ assert.strictEqual(tr.b.getOnlyElement([...d]), slice);
+
+ const d2 = tr.v.d.Diagnostic.fromDict(d.asDict());
+ assert.instanceOf(d2, tr.v.d.RelatedEventSet);
+
+ assert.instanceOf(tr.b.getOnlyElement([...d2]), tr.v.d.EventRef);
+
+ d2.resolve(model, true);
+
+ assert.strictEqual(tr.b.getOnlyElement([...d2]), slice);
+ });
+
+ test('merge', function() {
+ let aSlice;
+ let bSlice;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ aSlice = tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ title: 'a',
+ start: 0,
+ duration: 10
+ });
+ bSlice = tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ title: 'b',
+ start: 1,
+ duration: 10
+ });
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ thread.sliceGroup.pushSlice(aSlice);
+ thread.sliceGroup.pushSlice(bSlice);
+ });
+ assert.notEqual(aSlice.stableId, bSlice.stableId);
+
+ const aHist = new tr.v.Histogram('a', tr.b.Unit.byName.count);
+ const bHist = new tr.v.Histogram('b', tr.b.Unit.byName.count);
+
+ const aEvents = new tr.v.d.RelatedEventSet(aSlice);
+ const bEvents = new tr.v.d.RelatedEventSet(bSlice);
+ aEvents.canonicalUrl_ = 'http://a';
+ bEvents.canonicalUrl_ = 'http://b';
+
+ aHist.diagnostics.set('events', aEvents);
+ bHist.diagnostics.set('events', bEvents);
+
+ let mergedHist = aHist.clone();
+ mergedHist.addHistogram(bHist);
+ mergedHist = tr.v.Histogram.fromDict(mergedHist.asDict());
+
+ const mergedEvents = mergedHist.diagnostics.get('events');
+ const aSlice2 = tr.b.getOnlyElement(mergedEvents.get('http://a'));
+ assert.strictEqual(aSlice.stableId, aSlice2.stableId);
+ const bSlice2 = tr.b.getOnlyElement(mergedEvents.get('http://b'));
+ assert.strictEqual(bSlice.stableId, bSlice2.stableId);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set_unittest.py
new file mode 100644
index 00000000000..b0a55e090a0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_event_set_unittest.py
@@ -0,0 +1,29 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from tracing.value import histogram_unittest
+from tracing.value.diagnostics import related_event_set
+from tracing.value.diagnostics import diagnostic
+
+
+class RelatedEventSetUnittest(unittest.TestCase):
+ def testRoundtrip(self):
+ events = related_event_set.RelatedEventSet()
+ events.Add({
+ 'stableId': '0.0',
+ 'title': 'foo',
+ 'start': 0,
+ 'duration': 1,
+ })
+ d = events.AsDict()
+ clone = diagnostic.Diagnostic.FromDict(d)
+ self.assertEqual(
+ histogram_unittest.ToJSON(d), histogram_unittest.ToJSON(clone.AsDict()))
+ self.assertEqual(len(events), 1)
+ event = list(events)[0]
+ self.assertEqual(event['stableId'], '0.0')
+ self.assertEqual(event['title'], 'foo')
+ self.assertEqual(event['start'], 0)
+ self.assertEqual(event['duration'], 1)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.html
new file mode 100644
index 00000000000..3004d6bf3e5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ class RelatedNameMap extends tr.v.d.Diagnostic {
+ constructor(opt_info) {
+ super();
+ this.map_ = new Map();
+ }
+
+ clone() {
+ const clone = new RelatedNameMap();
+ clone.addDiagnostic(this);
+ return clone;
+ }
+
+ equals(other) {
+ if (!(other instanceof RelatedNameMap)) return false;
+
+ const keys1 = new Set(this.map_.keys());
+ const keys2 = new Set(other.map_.keys());
+ if (!tr.b.setsEqual(keys1, keys2)) return false;
+
+ for (const [key, name] of this) {
+ if (name !== other.get(key)) return false;
+ }
+
+ return true;
+ }
+
+ canAddDiagnostic(otherDiagnostic) {
+ return otherDiagnostic instanceof RelatedNameMap;
+ }
+
+ addDiagnostic(otherDiagnostic) {
+ for (const [key, name] of otherDiagnostic) {
+ const existing = this.get(key);
+ if (existing === undefined) {
+ this.set(key, name);
+ } else if (existing !== name) {
+ throw new Error('Histogram names differ: ' +
+ `"${existing}" != "${name}"`);
+ }
+ }
+ }
+
+ asDictInto_(d) {
+ d.names = {};
+ for (const [key, name] of this) d.names[key] = name;
+ }
+
+ set(key, name) {
+ this.map_.set(key, name);
+ }
+
+ get(key) {
+ return this.map_.get(key);
+ }
+
+ * [Symbol.iterator]() {
+ for (const pair of this.map_) yield pair;
+ }
+
+ * values() {
+ for (const value of this.map_.values()) yield value;
+ }
+
+ static fromEntries(entries) {
+ const names = new RelatedNameMap();
+ for (const [key, name] of entries) {
+ names.set(key, name);
+ }
+ return names;
+ }
+
+ static fromDict(d) {
+ return RelatedNameMap.fromEntries(Object.entries(d.names || {}));
+ }
+ }
+
+ tr.v.d.Diagnostic.register(RelatedNameMap, {
+ elementName: 'tr-v-ui-related-name-map-span',
+ });
+
+ return {
+ RelatedNameMap,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py
new file mode 100644
index 00000000000..c2584fa1b60
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map.py
@@ -0,0 +1,64 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from tracing.value.diagnostics import diagnostic
+
+
+class RelatedNameMap(diagnostic.Diagnostic):
+ __slots__ = '_map',
+
+ def __init__(self):
+ super(RelatedNameMap, self).__init__()
+ self._map = {}
+
+ def __len__(self):
+ return len(self._map)
+
+ def __eq__(self, other):
+ if not isinstance(other, RelatedNameMap):
+ return False
+ if set(self._map) != set(other._map):
+ return False
+ for key, name in self._map.items():
+ if name != other.Get(key):
+ return False
+ return True
+
+ def __hash__(self):
+ return id(self)
+
+ def CanAddDiagnostic(self, other):
+ return isinstance(other, RelatedNameMap)
+
+ def AddDiagnostic(self, other):
+ for key, name in other._map.items():
+ existing = self.Get(key)
+ if existing is None:
+ self.Set(key, name)
+ elif existing != name:
+ raise ValueError('Histogram names differ: "%s" != "%s"' % (
+ existing, name))
+
+ def Get(self, key):
+ return self._map.get(key)
+
+ def Set(self, key, name):
+ self._map[key] = name
+
+ def __iter__(self):
+ for key, name in self._map.items():
+ yield key, name
+
+ def Values(self):
+ return self._map.values()
+
+ def _AsDictInto(self, dct):
+ dct['names'] = dict(self._map)
+
+ @staticmethod
+ def FromDict(dct):
+ names = RelatedNameMap()
+ for key, name in dct['names'].items():
+ names.Set(key, name)
+ return names
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map_unittest.py
new file mode 100644
index 00000000000..13fae26d20e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/related_name_map_unittest.py
@@ -0,0 +1,50 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value import histogram_unittest
+from tracing.value.diagnostics import diagnostic
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import related_name_map
+
+
+class RelatedNameMapUnittest(unittest.TestCase):
+ def testRoundtrip(self):
+ names = related_name_map.RelatedNameMap()
+ names.Set('a', 'A')
+ d = names.AsDict()
+ clone = diagnostic.Diagnostic.FromDict(d)
+ self.assertEqual(
+ histogram_unittest.ToJSON(d), histogram_unittest.ToJSON(clone.AsDict()))
+ self.assertEqual(clone.Get('a'), 'A')
+
+ def testMerge(self):
+ a_names = related_name_map.RelatedNameMap()
+ a_names.Set('a', 'A')
+ b_names = related_name_map.RelatedNameMap()
+ b_names.Set('b', 'B')
+ self.assertTrue(a_names.CanAddDiagnostic(b_names))
+ self.assertTrue(b_names.CanAddDiagnostic(a_names))
+ self.assertFalse(a_names.CanAddDiagnostic(generic_set.GenericSet([])))
+
+ a_names.AddDiagnostic(b_names)
+ self.assertEqual(a_names.Get('b'), 'B')
+ a_names.AddDiagnostic(b_names)
+ self.assertEqual(a_names.Get('b'), 'B')
+
+ b_names.Set('a', 'C')
+ with self.assertRaises(ValueError):
+ a_names.AddDiagnostic(b_names)
+
+ def testEquals(self):
+ a_names = related_name_map.RelatedNameMap()
+ a_names.Set('a', 'A')
+ self.assertNotEqual(a_names, generic_set.GenericSet([]))
+ b_names = related_name_map.RelatedNameMap()
+ self.assertNotEqual(a_names, b_names)
+ b_names.Set('a', 'B')
+ self.assertNotEqual(a_names, b_names)
+ b_names.Set('a', 'A')
+ self.assertEqual(a_names, b_names)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py
new file mode 100644
index 00000000000..54615b7a6fb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_infos.py
@@ -0,0 +1,92 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class _Info(object):
+
+ def __init__(self, name, _type=None, entry_type=None):
+ self._name = name
+ self._type = _type
+ if entry_type is not None and self._type != 'GenericSet':
+ raise ValueError(
+ 'entry_type should only be specified if _type is GenericSet')
+ self._entry_type = entry_type
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def type(self):
+ return self._type
+
+ @property
+ def entry_type(self):
+ return self._entry_type
+
+
+ANGLE_REVISIONS = _Info('angleRevisions', 'GenericSet', str)
+ARCHITECTURES = _Info('architectures', 'GenericSet', str)
+BENCHMARKS = _Info('benchmarks', 'GenericSet', str)
+BENCHMARK_START = _Info('benchmarkStart', 'DateRange')
+BENCHMARK_DESCRIPTIONS = _Info('benchmarkDescriptions', 'GenericSet', str)
+BOTS = _Info('bots', 'GenericSet', str)
+BUG_COMPONENTS = _Info('bugComponents', 'GenericSet', str)
+BUILD_URLS = _Info('buildUrls', 'GenericSet', str)
+BUILDS = _Info('builds', 'GenericSet', int)
+CATAPULT_REVISIONS = _Info('catapultRevisions', 'GenericSet', str)
+CHROMIUM_COMMIT_POSITIONS = _Info('chromiumCommitPositions', 'GenericSet', int)
+CHROMIUM_REVISIONS = _Info('chromiumRevisions', 'GenericSet', str)
+DEVICE_IDS = _Info('deviceIds', 'GenericSet', str)
+DOCUMENTATION_URLS = _Info('documentationLinks', 'GenericSet', str)
+FUCHSIA_GARNET_REVISIONS = _Info('fuchsiaGarnetRevisions', 'GenericSet', str)
+FUCHSIA_PERIDOT_REVISIONS = _Info('fuchsiaPeridotRevisions', 'GenericSet', str)
+FUCHSIA_TOPAZ_REVISIONS = _Info('fuchsiaTopazRevisions', 'GenericSet', str)
+FUCHSIA_ZIRCON_REVISIONS = _Info('fuchsiaZirconRevisions', 'GenericSet', str)
+GPUS = _Info('gpus', 'GenericSet', str)
+HAD_FAILURES = _Info('hadFailures', 'GenericSet', bool)
+IS_REFERENCE_BUILD = _Info('isReferenceBuild', 'GenericSet', bool)
+LABELS = _Info('labels', 'GenericSet', str)
+LOG_URLS = _Info('logUrls', 'GenericSet', str)
+MASTERS = _Info('masters', 'GenericSet', str)
+MEMORY_AMOUNTS = _Info('memoryAmounts', 'GenericSet', int)
+OS_NAMES = _Info('osNames', 'GenericSet', str)
+OS_VERSIONS = _Info('osVersions', 'GenericSet', str)
+OWNERS = _Info('owners', 'GenericSet', str)
+POINT_ID = _Info('pointId', 'GenericSet', int)
+PRODUCT_VERSIONS = _Info('productVersions', 'GenericSet', str)
+REVISION_TIMESTAMPS = _Info('revisionTimestamps', 'DateRange')
+SKIA_REVISIONS = _Info('skiaRevisions', 'GenericSet', str)
+STORIES = _Info('stories', 'GenericSet', str)
+STORYSET_REPEATS = _Info('storysetRepeats', 'GenericSet', int)
+STORY_TAGS = _Info('storyTags', 'GenericSet', str)
+SUMMARY_KEYS = _Info('summaryKeys', 'GenericSet', str)
+TEST_PATH = _Info('testPath', 'GenericSet', str)
+TRACE_START = _Info('traceStart', 'DateRange')
+TRACE_URLS = _Info('traceUrls', 'GenericSet', str)
+V8_COMMIT_POSITIONS = _Info('v8CommitPositions', 'DateRange')
+V8_REVISIONS = _Info('v8Revisions', 'GenericSet', str)
+WEBRTC_REVISIONS = _Info('webrtcRevisions', 'GenericSet', str)
+
+
+def _CreateCachedInfoTypes():
+ info_types = {}
+ for info in globals().values():
+ if isinstance(info, _Info):
+ info_types[info.name] = info
+ return info_types
+
+_CACHED_INFO_TYPES = _CreateCachedInfoTypes()
+
+def GetTypeForName(name):
+ info = _CACHED_INFO_TYPES.get(name)
+ if info:
+ return info.type
+
+def AllInfos():
+ for info in _CACHED_INFO_TYPES.values():
+ yield info
+
+def AllNames():
+ for info in AllInfos():
+ yield info.name
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html
new file mode 100644
index 00000000000..1321815f0c5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/reserved_names.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+ Include all Diagnostic subclasses here so that RESERVED_INFOS always has
+ access to all subclasses.
+-->
+<link rel="import" href="/tracing/value/diagnostics/all_diagnostics.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v.d', function() {
+ // Diagnostics that are produced outside of metrics (e.g. by telemetry) use
+ // reserved names.
+ const RESERVED_INFOS = {
+ ANGLE_REVISIONS: {name: 'angleRevisions', type: tr.v.d.GenericSet},
+ ARCHITECTURES: {name: 'architectures', type: tr.v.d.GenericSet},
+ BENCHMARKS: {name: 'benchmarks', type: tr.v.d.GenericSet},
+ BENCHMARK_START: {name: 'benchmarkStart', type: tr.v.d.DateRange},
+ BENCHMARK_DESCRIPTIONS: {name: 'benchmarkDescriptions',
+ type: tr.v.d.GenericSet},
+ BOTS: {name: 'bots', type: tr.v.d.GenericSet},
+ BUG_COMPONENTS: {name: 'bugComponents', type: tr.v.d.GenericSet},
+ BUILDS: {name: 'builds', type: tr.v.d.GenericSet},
+ CATAPULT_REVISIONS: {name: 'catapultRevisions', type: tr.v.d.GenericSet},
+ CHROMIUM_COMMIT_POSITIONS: {
+ name: 'chromiumCommitPositions', type: tr.v.d.GenericSet},
+ CHROMIUM_REVISIONS: {name: 'chromiumRevisions', type: tr.v.d.GenericSet},
+ DEVICE_IDS: {name: 'deviceIds', type: tr.v.d.GenericSet},
+ DOCUMENTATION_URLS: {name: 'documentationUrls', type: tr.v.d.GenericSet},
+ FUCHSIA_GARNET_REVISIONS: {
+ name: 'fuchsiaGarnetRevisions', type: tr.v.d.GenericSet},
+ FUCHSIA_PERIDOT_REVISIONS: {
+ name: 'fuchsiaPeridotRevisions', type: tr.v.d.GenericSet},
+ FUCHSIA_TOPAZ_REVISIONS: {
+ name: 'fuchsiaTopazRevisions', type: tr.v.d.GenericSet},
+ FUCHSIA_ZIRCON_REVISIONS: {
+ name: 'fuchsiaZirconRevisions', type: tr.v.d.GenericSet},
+ GPUS: {name: 'gpus', type: tr.v.d.GenericSet},
+ IS_REFERENCE_BUILD: {name: 'isReferenceBuild', type: tr.v.d.GenericSet},
+ LABELS: {name: 'labels', type: tr.v.d.GenericSet},
+ LOG_URLS: {name: 'logUrls', type: tr.v.d.GenericSet},
+ MASTERS: {name: 'masters', type: tr.v.d.GenericSet},
+ MEMORY_AMOUNTS: {name: 'memoryAmounts', type: tr.v.d.GenericSet},
+ OS_NAMES: {name: 'osNames', type: tr.v.d.GenericSet},
+ OS_VERSIONS: {name: 'osVersions', type: tr.v.d.GenericSet},
+ OWNERS: {name: 'owners', type: tr.v.d.GenericSet},
+ POINT_ID: {name: 'pointId', type: tr.v.d.GenericSet},
+ PRODUCT_VERSIONS: {name: 'productVersions', type: tr.v.d.GenericSet},
+ REVISION_TIMESTAMPS: {name: 'revisionTimestamps', type: tr.v.d.DateRange},
+ SKIA_REVISIONS: {name: 'skiaRevisions', type: tr.v.d.GenericSet},
+ STORIES: {name: 'stories', type: tr.v.d.GenericSet},
+ STORYSET_REPEATS: {name: 'storysetRepeats', type: tr.v.d.GenericSet},
+ STORY_TAGS: {name: 'storyTags', type: tr.v.d.GenericSet},
+ SUMMARY_KEYS: {name: 'summaryKeys', type: tr.v.d.GenericSet},
+ TEST_PATH: {name: 'testPath', type: tr.v.d.GenericSet},
+ TRACE_START: {name: 'traceStart', type: tr.v.d.DateRange},
+ TRACE_URLS: {name: 'traceUrls', type: tr.v.d.GenericSet},
+ V8_COMMIT_POSITIONS: {name: 'v8CommitPositions', type: tr.v.d.DateRange},
+ V8_REVISIONS: {name: 'v8Revisions', type: tr.v.d.GenericSet},
+ WEBRTC_REVISIONS: {name: 'webrtcRevisions', type: tr.v.d.GenericSet},
+ };
+
+ const RESERVED_NAMES = {};
+
+ const RESERVED_NAMES_TO_TYPES = new Map();
+
+ for (const [codename, info] of Object.entries(RESERVED_INFOS)) {
+ RESERVED_NAMES[codename] = info.name;
+ if (RESERVED_NAMES_TO_TYPES.has(info.name)) {
+ throw new Error(`Duplicate reserved name "${info.name}"`);
+ }
+ RESERVED_NAMES_TO_TYPES.set(info.name, info.type);
+ }
+
+ const RESERVED_NAMES_SET = new Set(Object.values(RESERVED_NAMES));
+
+ return {
+ RESERVED_INFOS,
+ RESERVED_NAMES,
+ RESERVED_NAMES_SET,
+ RESERVED_NAMES_TO_TYPES,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/scalar.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/scalar.html
new file mode 100644
index 00000000000..397ec7d31b5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/scalar.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ class Scalar extends tr.v.d.Diagnostic {
+ /**
+ * @param {!tr.b.Scalar} value
+ */
+ constructor(value) {
+ super();
+ if (!(value instanceof tr.b.Scalar)) {
+ throw new Error('expected Scalar');
+ }
+ this.value = value;
+ }
+
+ clone() {
+ return new Scalar(this.value);
+ }
+
+ asDictInto_(d) {
+ d.value = this.value.asDict();
+ }
+
+ static fromDict(d) {
+ return new Scalar(tr.b.Scalar.fromDict(d.value));
+ }
+ }
+
+ tr.v.d.Diagnostic.register(Scalar, {
+ elementName: 'tr-v-ui-scalar-diagnostic-span'
+ });
+
+ return {
+ Scalar,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.html b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.html
new file mode 100644
index 00000000000..3bffc75caf0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.d', function() {
+ class UnmergeableDiagnosticSet extends tr.v.d.Diagnostic {
+ /**
+ * @param {!Array.<!tr.v.d.Diagnostic>} diagnostics
+ */
+ constructor(diagnostics) {
+ super();
+ this._diagnostics = diagnostics;
+ }
+
+ clone() {
+ const clone = new tr.v.d.UnmergeableDiagnosticSet();
+ clone.addDiagnostic(this);
+ return clone;
+ }
+
+ canAddDiagnostic(otherDiagnostic) {
+ return true;
+ }
+
+ /**
+ * If |otherDiagnostic| is an UnmergeableDiagnosticSet, then add clones of
+ * its diagnostics to |this|. Otherwise, try to add |otherDiagnostic| to one
+ * of the diagnostics already in this set. If that fails, add a clone of
+ * |otherDiagnostic| to this set.
+ *
+ * @param {!tr.v.d.Diagnostic} otherDiagnostic
+ * @return {!tr.v.d.UnmergeableDiagnostic} this
+ */
+ addDiagnostic(otherDiagnostic) {
+ if (otherDiagnostic instanceof UnmergeableDiagnosticSet) {
+ for (const subOtherDiagnostic of otherDiagnostic) {
+ const clone = subOtherDiagnostic.clone();
+ this.addDiagnostic(clone);
+ }
+ return;
+ }
+
+ for (let i = 0; i < this._diagnostics.length; ++i) {
+ if (this._diagnostics[i].canAddDiagnostic(otherDiagnostic)) {
+ this._diagnostics[i].addDiagnostic(otherDiagnostic);
+ return;
+ }
+ }
+
+ const clone = otherDiagnostic.clone();
+ this._diagnostics.push(clone);
+ }
+
+ get length() {
+ return this._diagnostics.length;
+ }
+
+ * [Symbol.iterator]() {
+ for (const diagnostic of this._diagnostics) yield diagnostic;
+ }
+
+ asDictInto_(d) {
+ d.diagnostics = this._diagnostics.map(d => d.asDictOrReference());
+ }
+
+ static fromDict(d) {
+ return new UnmergeableDiagnosticSet(d.diagnostics.map(
+ d => ((typeof d === 'string') ?
+ new tr.v.d.DiagnosticRef(d) : tr.v.d.Diagnostic.fromDict(d))));
+ }
+ }
+
+ tr.v.d.Diagnostic.register(UnmergeableDiagnosticSet, {
+ elementName: 'tr-v-ui-unmergeable-diagnostic-set-span'
+ });
+
+ return {
+ UnmergeableDiagnosticSet,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py
new file mode 100644
index 00000000000..5387c3b9614
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/diagnostics/unmergeable_diagnostic_set.py
@@ -0,0 +1,52 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from tracing.value.diagnostics import diagnostic
+from tracing.value.diagnostics import diagnostic_ref
+
+try:
+ StringTypes = basestring
+except NameError:
+ StringTypes = str
+
+
+class UnmergeableDiagnosticSet(diagnostic.Diagnostic):
+ __slots__ = '_diagnostics',
+
+ def __init__(self, diagnostics):
+ super(UnmergeableDiagnosticSet, self).__init__()
+ self._diagnostics = diagnostics
+
+ def __len__(self):
+ return len(self._diagnostics)
+
+ def __iter__(self):
+ for diag in self._diagnostics:
+ yield diag
+
+ def CanAddDiagnostic(self, unused_other_diagnostic):
+ return True
+
+ def AddDiagnostic(self, other_diagnostic):
+ if isinstance(other_diagnostic, UnmergeableDiagnosticSet):
+ self._diagnostics.extend(other_diagnostic._diagnostics)
+ return
+ for diag in self:
+ if diag.CanAddDiagnostic(other_diagnostic):
+ diag.AddDiagnostic(other_diagnostic)
+ return
+ self._diagnostics.append(other_diagnostic)
+
+ def _AsDictInto(self, d):
+ d['diagnostics'] = [d.AsDictOrReference() for d in self]
+
+ @staticmethod
+ def FromDict(dct):
+ def RefOrDiagnostic(d):
+ if isinstance(d, StringTypes):
+ return diagnostic_ref.DiagnosticRef(d)
+ return diagnostic.Diagnostic.FromDict(d)
+
+ return UnmergeableDiagnosticSet(
+ [RefOrDiagnostic(d) for d in dct['diagnostics']])
diff --git a/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py b/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py
new file mode 100644
index 00000000000..82b0ce3ceb8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter.py
@@ -0,0 +1,112 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+
+from tracing.value import histogram
+from tracing.value import histogram_set
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import reserved_infos
+
+
+def ConvertGtestJson(gtest_json):
+ """Convert JSON from a gtest perf test to Histograms.
+
+ Incoming data is in the following format:
+ {
+ 'metric1': {
+ 'units': 'unit1',
+ 'traces': {
+ 'story1': ['mean', 'std_dev'],
+ 'story2': ['mean', 'std_dev'],
+ },
+ 'important': ['testcase1', 'testcase2'],
+ },
+ 'metric2': {
+ 'units': 'unit2',
+ 'traces': {
+ 'story1': ['mean', 'std_dev'],
+ 'story2': ['mean', 'std_dev'],
+ },
+ 'important': ['testcase1', 'testcase2'],
+ },
+ ...
+ }
+ We ignore the 'important' fields and just assume everything should be
+ considered important.
+
+ We also don't bother adding any reserved diagnostics like mastername in this
+ script since that should be handled by the upload script.
+
+ Args:
+ gtest_json: A JSON dict containing perf output from a gtest
+
+ Returns:
+ A HistogramSet containing equivalent histograms and diagnostics
+ """
+
+ hs = histogram_set.HistogramSet()
+
+ for metric, metric_data in gtest_json.iteritems():
+ # Maintain the same unit if we're able to find an exact match, converting
+ # time units if possible. Otherwise use 'unitless'.
+ unit, multiplier = _ConvertUnit(metric_data.get('units'))
+
+ for story, story_data in metric_data['traces'].iteritems():
+ # We should only ever have the mean and standard deviation here.
+ assert len(story_data) == 2
+ h = histogram.Histogram(metric, unit)
+ h.diagnostics[reserved_infos.STORIES.name] = generic_set.GenericSet(
+ [story])
+ mean = float(story_data[0]) * multiplier
+ std_dev = float(story_data[1]) * multiplier
+ h.AddSample(mean)
+
+ # Synthesize the running statistics since we only have the mean + standard
+ # deviation instead of the actual data points.
+ h._running = histogram.RunningStatistics.FromDict([
+ 2, # count, we need this to be >1 in order for variance to work
+ mean, # max
+ 0, # meanlogs
+ mean, # mean
+ mean, # min
+ 2 * mean, # sum, this must be count * mean otherwise the reported mean
+ # is incorrect after merging statistics when reserved
+ # diagnostics are added.
+ std_dev * std_dev, # variance
+ ])
+
+ hs.AddHistogram(h)
+
+ return hs
+
+def ConvertGtestJsonFile(filepath):
+ """Convert JSON in a file from a gtest perf test to Histograms.
+
+ Contents of the given file will be overwritten with the new Histograms data.
+
+ Args:
+ filepath: The filepath to the JSON file to read/write from/to.
+ """
+ with open(filepath, 'r') as f:
+ data = json.load(f)
+ histograms = ConvertGtestJson(data)
+ with open(filepath, 'w') as f:
+ json.dump(histograms.AsDicts(), f)
+
+
+def _ConvertUnit(unit):
+ # We assume that smaller is better since we don't have an actual way to
+ # determine what the improvement direction is and most or all metrics from
+ # gtest perf tests have a downward improvement direction.
+ if unit in histogram.UNIT_NAMES:
+ return unit + '_smallerIsBetter', 1
+ # A number of existing gtest perf tests report time in units like
+ # microseconds, but histograms only support milliseconds. So, convert here if
+ # we can.
+ if unit == 'us':
+ return 'msBestFitFormat_smallerIsBetter', 0.001
+ if unit == 'ns':
+ return 'msBestFitFormat_smallerIsBetter', 0.000001
+ return 'unitless_smallerIsBetter', 1
diff --git a/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter_unittest.py
new file mode 100644
index 00000000000..b784143ee97
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/gtest_json_converter_unittest.py
@@ -0,0 +1,114 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value import gtest_json_converter
+from tracing.value.diagnostics import reserved_infos
+
+
+NANO_TO_MILLISECONDS = 0.000001
+
+
+class GtestJsonConverterUnittest(unittest.TestCase):
+
+ def testConvertBasic(self):
+ data = {
+ 'metric1': {
+ 'units': 'ms',
+ 'traces': {
+ 'story1': ['10.12345', '0.54321'],
+ 'story2': ['30', '0'],
+ }
+ },
+ 'metric2': {
+ 'units': 'ns',
+ 'traces': {
+ 'story1': ['100000.0', '2543.543'],
+ 'story2': ['12345.6789', '301.2'],
+ },
+ }
+ }
+ histograms = gtest_json_converter.ConvertGtestJson(data)
+ self.assertEqual(len(histograms), 4)
+
+ metric_histograms = histograms.GetHistogramsNamed('metric1')
+ self.assertEqual(len(metric_histograms), 2)
+ story1 = None
+ story2 = None
+ if metric_histograms[0].diagnostics[
+ reserved_infos.STORIES.name].GetOnlyElement() == 'story1':
+ story1 = metric_histograms[0]
+ story2 = metric_histograms[1]
+ else:
+ story2 = metric_histograms[0]
+ story1 = metric_histograms[1]
+
+ # assertAlmostEqual necessary to avoid floating point precision issues.
+ self.assertAlmostEqual(story1.average, 10.12345)
+ self.assertAlmostEqual(story1.standard_deviation, 0.54321)
+ self.assertAlmostEqual(story1.sum, story1.num_values * story1.average)
+ self.assertEqual(story2.average, 30)
+ self.assertEqual(story2.standard_deviation, 0)
+ self.assertEqual(story2.sum, story2.num_values * story2.average)
+ self.assertEqual(story1.unit, story2.unit)
+ self.assertEqual(story1.unit, 'ms_smallerIsBetter')
+
+ metric_histograms = histograms.GetHistogramsNamed('metric2')
+ self.assertEqual(len(metric_histograms), 2)
+ if metric_histograms[0].diagnostics[
+ reserved_infos.STORIES.name].GetOnlyElement() == 'story1':
+ story1 = metric_histograms[0]
+ story2 = metric_histograms[1]
+ else:
+ story2 = metric_histograms[0]
+ story1 = metric_histograms[1]
+
+ # assertAlmostEqual necessary to avoid floating point precision issues.
+ # We expect the numbers to be different than what was initially provided
+ # since this should be converted to milliseconds.
+ self.assertAlmostEqual(story1.average, 100000 * NANO_TO_MILLISECONDS)
+ self.assertAlmostEqual(story1.standard_deviation,
+ 2543.543 * NANO_TO_MILLISECONDS)
+ self.assertAlmostEqual(story1.sum, story1.num_values * story1.average)
+ self.assertAlmostEqual(story2.average, 12345.6789 * NANO_TO_MILLISECONDS)
+ self.assertAlmostEqual(story2.standard_deviation,
+ 301.2 * NANO_TO_MILLISECONDS)
+ self.assertAlmostEqual(story2.sum, story2.num_values * story2.average)
+ self.assertEqual(story1.unit, story2.unit)
+ self.assertEqual(story1.unit, 'msBestFitFormat_smallerIsBetter')
+
+ def testConvertUnknownUnit(self):
+ data = {
+ 'metric1': {
+ 'units': 'SomeUnknownUnit',
+ 'traces': {
+ 'story1': ['10', '1'],
+ 'story2': ['123.4', '7.89'],
+ }
+ }
+ }
+ histograms = gtest_json_converter.ConvertGtestJson(data)
+ self.assertEqual(len(histograms), 2)
+
+ metric_histograms = histograms.GetHistogramsNamed('metric1')
+ self.assertEqual(len(metric_histograms), 2)
+ story1 = None
+ story2 = None
+ if metric_histograms[0].diagnostics[
+ reserved_infos.STORIES.name].GetOnlyElement() == 'story1':
+ story1 = metric_histograms[0]
+ story2 = metric_histograms[1]
+ else:
+ story2 = metric_histograms[0]
+ story1 = metric_histograms[1]
+
+ self.assertEqual(story1.average, 10)
+ self.assertEqual(story1.standard_deviation, 1)
+ self.assertEqual(story1.sum, story1.num_values * story1.average)
+ self.assertAlmostEqual(story2.average, 123.4)
+ self.assertAlmostEqual(story2.standard_deviation, 7.89)
+ self.assertAlmostEqual(story2.sum, story2.num_values * story2.average)
+ self.assertEqual(story1.unit, story2.unit)
+ self.assertEqual(story1.unit, 'unitless_smallerIsBetter')
diff --git a/chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py b/chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py
new file mode 100644
index 00000000000..9ca47d2a709
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/heap_profiler.py
@@ -0,0 +1,201 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import codecs
+import collections
+import sys
+import time
+
+from tracing.value import histogram
+from tracing.value import histogram_set
+from tracing.value.diagnostics import breakdown
+from tracing.value.diagnostics import date_range
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import related_name_map
+from tracing.value.diagnostics import reserved_infos
+from tracing_build import render_histograms_viewer
+
+
+def _IsUserDefinedInstance(obj):
+ return str(type(obj)).startswith('<class ')
+
+
+class _HeapProfiler(object):
+ __slots__ = '_diagnostics_callback', '_histograms', '_seen'
+
+ def __init__(self, diagnostics_callback=None):
+ self._diagnostics_callback = diagnostics_callback
+ self._histograms = None
+ self._seen = set()
+
+ def Profile(self, root):
+ self._histograms = histogram_set.HistogramSet()
+ total_hist = self._GetOrCreateHistogram('heap')
+ total_hist.diagnostics['types'] = related_name_map.RelatedNameMap()
+ total_breakdown = breakdown.Breakdown()
+ total_size = self._Recurse(
+ root, total_hist.diagnostics['types'], total_breakdown)
+ builtins_size = total_size - sum(subsize for _, subsize in total_breakdown)
+
+ if builtins_size:
+ total_breakdown.Set('(builtin types)', builtins_size)
+ total_hist.AddSample(total_size, dict(types=total_breakdown))
+
+ self._histograms.AddSharedDiagnosticToAllHistograms(
+ reserved_infos.TRACE_START.name,
+ date_range.DateRange(time.time() * 1000))
+
+ return self._histograms
+
+ def _GetOrCreateHistogram(self, name):
+ hs = self._histograms.GetHistogramsNamed(name)
+ if len(hs) > 1:
+ raise Exception('Too many Histograms named %s' % name)
+
+ if len(hs) == 1:
+ return hs[0]
+
+ hist = histogram.Histogram(name, 'sizeInBytes_smallerIsBetter')
+ hist.CustomizeSummaryOptions(dict(std=False, min=False, max=False))
+ self._histograms.AddHistogram(hist)
+ return hist
+
+ def _Recurse(self, obj, parent_related_names, parent_breakdown):
+ if id(obj) in self._seen:
+ return 0
+ self._seen.add(id(obj))
+
+ size = sys.getsizeof(obj)
+
+ related_names = parent_related_names
+ types_breakdown = parent_breakdown
+
+ hist = None
+ if _IsUserDefinedInstance(obj):
+ type_name = type(obj).__name__
+ hist = self._GetOrCreateHistogram('heap:' + type_name)
+
+ related_names = hist.diagnostics.get('types')
+ if related_names is None:
+ related_names = related_name_map.RelatedNameMap()
+ types_breakdown = breakdown.Breakdown()
+
+ if isinstance(obj, dict):
+ for objkey, objvalue in obj.iteritems():
+ size += self._Recurse(objkey, related_names, types_breakdown)
+ size += self._Recurse(objvalue, related_names, types_breakdown)
+ elif isinstance(obj, (tuple, list, set, frozenset, collections.deque)):
+ # Can't use collections.Iterable because strings are iterable, but
+ # sys.getsizeof() already handles strings, we don't need to iterate over
+ # them.
+ for elem in obj:
+ size += self._Recurse(elem, related_names, types_breakdown)
+
+ # It is possible to subclass builtin types like dict and add properties to
+ # them, so handle __dict__ and __slots__ even if obj is a dict/list/etc.
+
+ properties_breakdown = breakdown.Breakdown()
+ if hasattr(obj, '__dict__'):
+ size += sys.getsizeof(obj.__dict__)
+ for dkey, dvalue in obj.__dict__.iteritems():
+ size += self._Recurse(dkey, related_names, types_breakdown)
+ dsize = self._Recurse(dvalue, related_names, types_breakdown)
+ properties_breakdown.Set(dkey, dsize)
+ size += dsize
+ size += self._Recurse(obj.__dict__, related_names, types_breakdown)
+
+ # It is possible for a class to use both __slots__ and __dict__ by listing
+ # __dict__ as a slot.
+
+ if hasattr(obj.__class__, '__slots__'):
+ for slot in obj.__class__.__slots__:
+ if slot == '__dict__':
+ # obj.__dict__ was already handled
+ continue
+ if not hasattr(obj, slot):
+ continue
+ slot_size = self._Recurse(
+ getattr(obj, slot), related_names, types_breakdown)
+ properties_breakdown.Set(slot, slot_size)
+ size += slot_size
+
+ if hist:
+ if len(related_names):
+ hist.diagnostics['types'] = related_names
+
+ parent_related_names.Set(type_name, hist.name)
+ parent_breakdown.Set(type_name, parent_breakdown.Get(type_name) + size)
+
+ builtins_size = size - sum(subsize for _, subsize in types_breakdown)
+ if builtins_size:
+ types_breakdown.Set('(builtin types)', builtins_size)
+
+ sample_diagnostics = {'types': types_breakdown}
+ if len(properties_breakdown):
+ sample_diagnostics['properties'] = properties_breakdown
+ if self._diagnostics_callback:
+ sample_diagnostics.update(self._diagnostics_callback(obj))
+
+ hist.AddSample(size, sample_diagnostics)
+
+ return size
+
+
+def Profile(root, label=None, html_filename=None, html_stream=None,
+ vulcanized_viewer=None, reset_results=False,
+ diagnostics_callback=None):
+ """Profiles memory consumed by the root object.
+
+ Produces a HistogramSet containing 1 Histogram for each user-defined class
+ encountered when recursing through the root object's properties.
+ Each Histogram contains 1 sample for each instance of the class.
+ Each sample contains 2 Breakdowns:
+ - 'types' allows drilling down into memory profiles for other classes, and
+ - 'properties' breaks down the size of an instance by its properties.
+
+ Args:
+ label: string label to distinguish these results from those produced by
+ other Profile() calls.
+ html_filename: string filename to write HTML results.
+ html_stream: file-like string to write HTML results.
+ vulcanized_viewer: HTML string
+ reset_results: whether to delete pre-existing results in
+ html_filename/html_stream
+ diagnostics_callback: function that takes an instance of a class, and
+ returns a dictionary from strings to Diagnostic objects.
+
+ Returns:
+ HistogramSet
+ """
+ # TODO(4068): Package this and its dependencies and a vulcanized viewer in
+ # order to remove the vulcanized_viewer parameter and simplify rendering the
+ # viewer.
+
+ profiler = _HeapProfiler(diagnostics_callback)
+ histograms = profiler.Profile(root)
+
+ if label:
+ histograms.AddSharedDiagnosticToAllHistograms(
+ reserved_infos.LABELS.name, generic_set.GenericSet([label]))
+
+ if html_filename and not html_stream:
+ open(html_filename, 'a').close() # Create file if it doesn't exist.
+ html_stream = codecs.open(html_filename, mode='r+', encoding='utf-8')
+
+ if html_stream:
+ # Vulcanizing the viewer requires a full catapult checkout, which is not
+ # available in some contexts such as appengine.
+ # Merely rendering the viewer requires a pre-vulcanized viewer HTML string.
+ # render_histograms_viewer does not require a full checkout, so it can run
+ # in restricted contexts such as appengine as long as a pre-vulcanized
+ # viewer is provided.
+ if vulcanized_viewer:
+ render_histograms_viewer.RenderHistogramsViewer(
+ histograms.AsDicts(), html_stream, reset_results, vulcanized_viewer)
+ else:
+ from tracing_build import vulcanize_histograms_viewer
+ vulcanize_histograms_viewer.VulcanizeAndRenderHistogramsViewer(
+ histograms.AsDicts(), html_stream)
+
+ return histograms
diff --git a/chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py
new file mode 100644
index 00000000000..d2904c8a151
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/heap_profiler_unittest.py
@@ -0,0 +1,58 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value import heap_profiler
+from tracing.value import histogram
+from tracing.value import histogram_set
+
+
+class HeapProfilerUnitTest(unittest.TestCase):
+
+ def testHeapProfiler(self):
+ test_data = histogram_set.HistogramSet()
+ for i in xrange(10):
+ test_hist = histogram.Histogram('test', 'n%')
+ test_hist.AddSample(i / 10.0)
+ test_data.AddHistogram(test_hist)
+
+ histograms = heap_profiler.Profile(test_data)
+
+ set_size_hist = histograms.GetHistogramNamed('heap:HistogramSet')
+ self.assertEquals(set_size_hist.num_values, 1)
+ # The exact sizes of python objects can vary between platforms and versions.
+ self.assertGreater(set_size_hist.sum, 10000)
+
+ hist_size_hist = histograms.GetHistogramNamed('heap:Histogram')
+ self.assertEquals(hist_size_hist.num_values, 10)
+ self.assertGreater(hist_size_hist.sum, 10000)
+
+ related_names = hist_size_hist.diagnostics['types']
+ self.assertEquals(related_names.Get('HistogramBin'), 'heap:HistogramBin')
+ self.assertEquals(related_names.Get('DiagnosticMap'), 'heap:DiagnosticMap')
+
+ properties = hist_size_hist.bins[33].diagnostic_maps[0]['properties']
+ types = hist_size_hist.bins[33].diagnostic_maps[0]['types']
+ self.assertGreater(len(properties), 3)
+ self.assertGreater(properties.Get('_bins'), 1000)
+ self.assertEquals(len(types), 4)
+ self.assertGreater(types.Get('HistogramBin'), 1000)
+ self.assertGreater(types.Get('(builtin types)'), 1000)
+
+ bin_size_hist = histograms.GetHistogramNamed('heap:HistogramBin')
+ self.assertEquals(bin_size_hist.num_values, 32)
+ self.assertGreater(bin_size_hist.sum, 1000)
+
+ diag_map_size_hist = histograms.GetHistogramNamed('heap:DiagnosticMap')
+ self.assertEquals(diag_map_size_hist.num_values, 10)
+ self.assertGreater(diag_map_size_hist.sum, 1000)
+
+ range_size_hist = histograms.GetHistogramNamed('heap:Range')
+ self.assertEquals(range_size_hist.num_values, 22)
+ self.assertGreater(range_size_hist.sum, 1000)
+
+ stats_size_hist = histograms.GetHistogramNamed('heap:RunningStatistics')
+ self.assertEquals(stats_size_hist.num_values, 10)
+ self.assertGreater(stats_size_hist.sum, 1000)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram.html b/chromium/third_party/catapult/tracing/tracing/value/histogram.html
new file mode 100644
index 00000000000..effc879666d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram.html
@@ -0,0 +1,1478 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/running_statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/scalar.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v', function() {
+ const MAX_DIAGNOSTIC_MAPS = 16;
+
+ const DEFAULT_SAMPLE_VALUES_PER_BIN = 10;
+
+ const DEFAULT_REBINNED_COUNT = 40;
+
+ const DEFAULT_BOUNDARIES_FOR_UNIT = new Map();
+
+ const DELTA = String.fromCharCode(916);
+ const Z_SCORE_NAME = 'z-score';
+ const P_VALUE_NAME = 'p-value';
+ const U_STATISTIC_NAME = 'U';
+
+ /**
+ * Converts the given percent to a string in the format specified above.
+ * @param {number} percent The percent must be between 0.0 and 1.0.
+ * @param {boolean=} opt_force3 Whether to force the result to be 3 chars long
+ * @return {string}
+ */
+ function percentToString(percent, opt_force3) {
+ if (percent < 0 || percent > 1) {
+ throw new Error('percent must be in [0,1]');
+ }
+ if (percent === 0) return '000';
+ if (percent === 1) return '100';
+ let str = percent.toString();
+ if (str[1] !== '.') {
+ throw new Error('Unexpected percent');
+ }
+ // Pad short strings with zeros.
+ str = str + '0'.repeat(Math.max(4 - str.length, 0));
+
+ if (str.length > 4) {
+ if (opt_force3) {
+ str = str.slice(0, 4);
+ } else {
+ str = str.slice(0, 4) + '_' + str.slice(4);
+ }
+ }
+ return '0' + str.slice(2);
+ }
+
+ /**
+ * Converts the given string to a percent between 0 and 1.
+ * @param {string}
+ * @return {number}
+ */
+ function percentFromString(s) {
+ return parseFloat(s[0] + '.' + s.substr(1).replace(/_/g, ''));
+ }
+
+ class HistogramBin {
+ /**
+ * @param {!tr.b.math.Range} range
+ */
+ constructor(range) {
+ this.range = range;
+ this.count = 0;
+ this.diagnosticMaps = [];
+ }
+
+ /**
+ * @param {*} value
+ */
+ addSample(value) {
+ this.count += 1;
+ }
+
+ /**
+ * @param {!tr.v.d.DiagnosticMap} diagnostics
+ */
+ addDiagnosticMap(diagnostics) {
+ tr.b.math.Statistics.uniformlySampleStream(
+ this.diagnosticMaps, this.count, diagnostics, MAX_DIAGNOSTIC_MAPS);
+ }
+
+ addBin(other) {
+ if (!this.range.equals(other.range)) {
+ throw new Error('Merging incompatible Histogram bins.');
+ }
+ tr.b.math.Statistics.mergeSampledStreams(this.diagnosticMaps, this.count,
+ other.diagnosticMaps, other.count, MAX_DIAGNOSTIC_MAPS);
+ this.count += other.count;
+ }
+
+ fromDict(dict) {
+ this.count = dict[0];
+ if (dict.length > 1) {
+ for (const map of dict[1]) {
+ this.diagnosticMaps.push(tr.v.d.DiagnosticMap.fromDict(map));
+ }
+ }
+ }
+
+ asDict() {
+ if (!this.diagnosticMaps.length) {
+ return [this.count];
+ }
+ // It's more efficient to serialize these 2 fields in an array. If you
+ // add any other fields, you should re-evaluate whether it would be more
+ // efficient to serialize as a dict.
+ return [this.count, this.diagnosticMaps.map(d => d.asDict())];
+ }
+ }
+
+ const DEFAULT_SUMMARY_OPTIONS = new Map([
+ ['avg', true],
+ ['count', true],
+ ['geometricMean', false],
+ ['max', true],
+ ['min', true],
+ ['nans', false],
+ ['std', true],
+ ['sum', true],
+ // Don't include 'percentile' or 'iprs' here. Their default values are [],
+ // which is mutable. Callers may push to it, so there must be a different
+ // Array instance for each Histogram instance.
+ ]);
+
+ /**
+ * This is basically a histogram, but so much more.
+ * Histogram is serializable using asDict/fromDict.
+ * Histogram computes several statistics of its contents.
+ * Histograms can be merged.
+ * getDifferenceSignificance() test whether one Histogram is statistically
+ * significantly different from another Histogram.
+ * Histogram stores a random sample of the exact number values added to it.
+ * Histogram stores a random sample of optional per-sample DiagnosticMaps.
+ * Histogram is visualized by <tr-v-ui-histogram-span>, which supports
+ * selecting bins, and visualizing the DiagnosticMaps of selected bins.
+ *
+ * @param {!tr.b.Unit} unit
+ * @param {!tr.v.HistogramBinBoundaries=} opt_binBoundaries
+ */
+ class Histogram {
+ constructor(name, unit, opt_binBoundaries) {
+ if (!(unit instanceof tr.b.Unit)) {
+ throw new Error('unit must be a Unit: ' + unit);
+ }
+ let binBoundaries = opt_binBoundaries;
+ if (!binBoundaries) {
+ const baseUnit = unit.baseUnit ? unit.baseUnit : unit;
+ binBoundaries = DEFAULT_BOUNDARIES_FOR_UNIT.get(baseUnit.unitName);
+ }
+
+ // Serialize binBoundaries here instead of holding a reference to it in
+ // case it is modified.
+ this.binBoundariesDict_ = binBoundaries.asDict();
+
+ // HistogramBinBoundaries create empty HistogramBins. Save memory by
+ // sharing those empty HistogramBin instances with other Histograms. Wait
+ // to copy HistogramBins until we need to modify it (copy-on-write).
+ this.allBins = binBoundaries.bins.slice();
+ this.description = '';
+ const allowReservedNames = false;
+ this.diagnostics_ = new tr.v.d.DiagnosticMap(allowReservedNames);
+ this.maxNumSampleValues_ = this.defaultMaxNumSampleValues_;
+ this.name_ = name;
+ this.nanDiagnosticMaps = [];
+ this.numNans = 0;
+ this.running_ = undefined;
+ this.sampleValues_ = [];
+ this.summaryOptions = new Map(DEFAULT_SUMMARY_OPTIONS);
+ this.summaryOptions.set('percentile', []);
+ this.summaryOptions.set('iprs', []);
+ this.unit = unit;
+ }
+
+ /**
+ * Create a Histogram, configure it, and add samples to it.
+ *
+ * |samples| can be either
+ * 0. a number, or
+ * 1. a dictionary {value: number, diagnostics: dictionary}, or
+ * 2. an array of
+ * 2a. number, or
+ * 2b. dictionaries {value, diagnostics}.
+ *
+ * @param {string} name
+ * @param {!tr.b.Unit} unit
+ * @param {number|!Object|!Array.<(number|!Object)>} samples
+ * @param {!Object=} opt_options
+ * @param {!tr.v.HistogramBinBoundaries} opt_options.binBoundaries
+ * @param {!Object|!Map} opt_options.summaryOptions
+ * @param {!Object|!Map} opt_options.diagnostics
+ * @param {string} opt_options.description
+ * @return {!tr.v.Histogram}
+ */
+ static create(name, unit, samples, opt_options) {
+ const options = opt_options || {};
+ const hist = new Histogram(name, unit, options.binBoundaries);
+
+ if (options.description) hist.description = options.description;
+
+ if (options.summaryOptions) {
+ let summaryOptions = options.summaryOptions;
+ if (!(summaryOptions instanceof Map)) {
+ summaryOptions = Object.entries(summaryOptions);
+ }
+ for (const [name, value] of summaryOptions) {
+ hist.summaryOptions.set(name, value);
+ }
+ }
+
+ if (options.diagnostics !== undefined) {
+ let diagnostics = options.diagnostics;
+ if (!(diagnostics instanceof Map)) {
+ diagnostics = Object.entries(diagnostics);
+ }
+ for (const [name, diagnostic] of diagnostics) {
+ if (!diagnostic) continue;
+ hist.diagnostics.set(name, diagnostic);
+ }
+ }
+
+ if (!(samples instanceof Array)) samples = [samples];
+
+ for (const sample of samples) {
+ if (typeof sample === 'object') {
+ hist.addSample(sample.value, sample.diagnostics);
+ } else {
+ hist.addSample(sample);
+ }
+ }
+
+ return hist;
+ }
+
+ get diagnostics() {
+ return this.diagnostics_;
+ }
+
+ get running() {
+ return this.running_;
+ }
+
+ get maxNumSampleValues() {
+ return this.maxNumSampleValues_;
+ }
+
+ set maxNumSampleValues(n) {
+ this.maxNumSampleValues_ = n;
+ tr.b.math.Statistics.uniformlySampleArray(
+ this.sampleValues_, this.maxNumSampleValues_);
+ }
+
+ get name() {
+ return this.name_;
+ }
+
+ static fromDict(dict) {
+ const hist = new Histogram(dict.name, tr.b.Unit.fromJSON(dict.unit),
+ HistogramBinBoundaries.fromDict(dict.binBoundaries));
+ if (dict.description) {
+ hist.description = dict.description;
+ }
+ if (dict.diagnostics) {
+ hist.diagnostics.addDicts(dict.diagnostics);
+ }
+ if (dict.allBins) {
+ if (dict.allBins.length !== undefined) {
+ for (let i = 0; i < dict.allBins.length; ++i) {
+ // Copy HistogramBin on write, share the rest with the other
+ // Histograms that use the same HistogramBinBoundaries.
+ hist.allBins[i] = new HistogramBin(hist.allBins[i].range);
+ hist.allBins[i].fromDict(dict.allBins[i]);
+ }
+ } else {
+ for (const [i, binDict] of Object.entries(dict.allBins)) {
+ hist.allBins[i] = new HistogramBin(hist.allBins[i].range);
+ hist.allBins[i].fromDict(binDict);
+ }
+ }
+ }
+ if (dict.running) {
+ hist.running_ = tr.b.math.RunningStatistics.fromDict(dict.running);
+ }
+ if (dict.summaryOptions) {
+ if (dict.summaryOptions.iprs) {
+ // Range.fromDict() requires isEmpty, which is unnecessarily verbose
+ // for this use case.
+ dict.summaryOptions.iprs = dict.summaryOptions.iprs.map(
+ r => tr.b.math.Range.fromExplicitRange(r[0], r[1]));
+ }
+ hist.customizeSummaryOptions(dict.summaryOptions);
+ }
+ if (dict.maxNumSampleValues !== undefined) {
+ hist.maxNumSampleValues = dict.maxNumSampleValues;
+ }
+ if (dict.sampleValues) {
+ hist.sampleValues_ = dict.sampleValues;
+ }
+ if (dict.numNans) {
+ hist.numNans = dict.numNans;
+ }
+ if (dict.nanDiagnostics) {
+ for (const map of dict.nanDiagnostics) {
+ hist.nanDiagnosticMaps.push(tr.v.d.DiagnosticMap.fromDict(map));
+ }
+ }
+ return hist;
+ }
+
+ get numValues() {
+ return this.running_ ? this.running_.count : 0;
+ }
+
+ get average() {
+ return this.running_ ? this.running_.mean : undefined;
+ }
+
+ get standardDeviation() {
+ return this.running_ ? this.running_.stddev : undefined;
+ }
+
+ get geometricMean() {
+ return this.running_ ? this.running_.geometricMean : 0;
+ }
+
+ get sum() {
+ return this.running_ ? this.running_.sum : 0;
+ }
+
+ get min() {
+ return this.running_ ? this.running_.min : Infinity;
+ }
+
+ get max() {
+ return this.running_ ? this.running_.max : -Infinity;
+ }
+
+ /**
+ * Requires that units agree.
+ * Returns DONT_CARE if that is the units' improvementDirection.
+ * Returns SIGNIFICANT if the Mann-Whitney U test returns a
+ * p-value less than opt_alpha or DEFAULT_ALPHA. Returns INSIGNIFICANT if
+ * the p-value is greater than alpha.
+ *
+ * @param {!tr.v.Histogram} other
+ * @param {number=} opt_alpha
+ * @return {!tr.b.math.Statistics.Significance}
+ */
+ getDifferenceSignificance(other, opt_alpha) {
+ if (this.unit !== other.unit) {
+ throw new Error('Cannot compare Histograms with different units');
+ }
+
+ if (this.unit.improvementDirection ===
+ tr.b.ImprovementDirection.DONT_CARE) {
+ return tr.b.math.Statistics.Significance.DONT_CARE;
+ }
+
+ if (!(other instanceof Histogram)) {
+ throw new Error('Unable to compute a p-value');
+ }
+
+ const testResult = tr.b.math.Statistics.mwu(
+ this.sampleValues, other.sampleValues, opt_alpha);
+ return testResult.significance;
+ }
+
+ /*
+ * Compute an approximation of percentile based on the counts in the bins.
+ * If the real percentile lies within |this.range| then the result of
+ * the function will deviate from the real percentile by at most
+ * the maximum width of the bin(s) within which the point(s)
+ * from which the real percentile would be calculated lie.
+ * If the real percentile is outside |this.range| then the function
+ * returns the closest range limit: |this.range.min| or |this.range.max|.
+ *
+ * @param {number} percent The percent must be between 0.0 and 1.0.
+ */
+ getApproximatePercentile(percent) {
+ if (percent < 0 || percent > 1) {
+ throw new Error('percent must be in [0,1]');
+ }
+ if (this.numValues === 0) return undefined;
+ if (this.allBins.length === 1) {
+ // Copy sampleValues, don't sort them in place, in order to preserve
+ // insertion order.
+ const sortedSampleValues = this.sampleValues.slice().sort(
+ (x, y) => x - y);
+ return sortedSampleValues[Math.floor((sortedSampleValues.length - 1) *
+ percent)];
+ }
+ let valuesToSkip = Math.floor((this.numValues - 1) * percent);
+ for (const bin of this.allBins) {
+ valuesToSkip -= bin.count;
+ if (valuesToSkip >= 0) continue;
+ if (bin.range.min === -Number.MAX_VALUE) {
+ return bin.range.max;
+ }
+ if (bin.range.max === Number.MAX_VALUE) {
+ return bin.range.min;
+ }
+ return bin.range.center;
+ }
+ return this.allBins[this.allBins.length - 1].range.min;
+ }
+
+ getBinIndexForValue(value) {
+ // Don't use subtraction to avoid arithmetic overflow.
+ const i = tr.b.findFirstTrueIndexInSortedArray(
+ this.allBins, b => value < b.range.max);
+ if (0 <= i && i < this.allBins.length) return i;
+ return this.allBins.length - 1;
+ }
+
+ getBinForValue(value) {
+ return this.allBins[this.getBinIndexForValue(value)];
+ }
+
+ /**
+ * @param {number|*} value
+ * @param {(!Object|!tr.v.d.DiagnosticMap)=} opt_diagnostics
+ */
+ addSample(value, opt_diagnostics) {
+ if (opt_diagnostics) {
+ if (!(opt_diagnostics instanceof tr.v.d.DiagnosticMap)) {
+ opt_diagnostics = tr.v.d.DiagnosticMap.fromObject(opt_diagnostics);
+ }
+ for (const [name, diag] of opt_diagnostics) {
+ if (diag instanceof tr.v.d.Breakdown) {
+ diag.truncate(this.unit);
+ }
+ }
+ }
+
+ if (typeof(value) !== 'number' || isNaN(value)) {
+ this.numNans++;
+ if (opt_diagnostics) {
+ tr.b.math.Statistics.uniformlySampleStream(this.nanDiagnosticMaps,
+ this.numNans, opt_diagnostics, MAX_DIAGNOSTIC_MAPS);
+ }
+ } else {
+ if (this.running_ === undefined) {
+ this.running_ = new tr.b.math.RunningStatistics();
+ }
+ this.running_.add(value);
+
+ value = this.unit.truncate(value);
+
+ const binIndex = this.getBinIndexForValue(value);
+ let bin = this.allBins[binIndex];
+ if (bin.count === 0) {
+ // Copy HistogramBin on write, share the rest with the other
+ // Histograms that use the same HistogramBinBoundaries.
+ bin = new HistogramBin(bin.range);
+ this.allBins[binIndex] = bin;
+ }
+ bin.addSample(value);
+ if (opt_diagnostics) {
+ bin.addDiagnosticMap(opt_diagnostics);
+ }
+ }
+
+ tr.b.math.Statistics.uniformlySampleStream(this.sampleValues_,
+ this.numValues + this.numNans, value, this.maxNumSampleValues);
+ }
+
+ sampleValuesInto(samples) {
+ for (const sampleValue of this.sampleValues) {
+ samples.push(sampleValue);
+ }
+ }
+
+ /**
+ * Return true if this Histogram can be added to |other|.
+ *
+ * @param {!tr.v.Histogram} other
+ * @return {boolean}
+ */
+ canAddHistogram(other) {
+ if (this.unit !== other.unit) {
+ return false;
+ }
+ if (this.binBoundariesDict_ === other.binBoundariesDict_) {
+ return true;
+ }
+ if (!this.binBoundariesDict_ || !other.binBoundariesDict_) {
+ return true;
+ }
+ // |binBoundariesDict_| may be equal even if they are not the same object.
+ if (this.binBoundariesDict_.length !== other.binBoundariesDict_.length) {
+ return false;
+ }
+ for (let i = 0; i < this.binBoundariesDict_.length; ++i) {
+ const slice = this.binBoundariesDict_[i];
+ const otherSlice = other.binBoundariesDict_[i];
+ if (slice instanceof Array) {
+ if (!(otherSlice instanceof Array)) {
+ return false;
+ }
+ if (slice[0] !== otherSlice[0] ||
+ !tr.b.math.approximately(slice[1], otherSlice[1]) ||
+ slice[2] !== otherSlice[2]) {
+ return false;
+ }
+ } else {
+ if (otherSlice instanceof Array) {
+ return false;
+ }
+ if (!tr.b.math.approximately(slice, otherSlice)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Add |other| to this Histogram in-place if they can be added.
+ *
+ * @param {!tr.v.Histogram} other
+ */
+ addHistogram(other) {
+ if (!this.canAddHistogram(other)) {
+ throw new Error('Merging incompatible Histograms');
+ }
+
+ if (!!this.binBoundariesDict_ === !!other.binBoundariesDict_) {
+ for (let i = 0; i < this.allBins.length; ++i) {
+ let bin = this.allBins[i];
+ if (bin.count === 0) {
+ bin = new HistogramBin(bin.range);
+ this.allBins[i] = bin;
+ }
+ bin.addBin(other.allBins[i]);
+ }
+ } else {
+ const [multiBin, singleBin] = this.binBoundariesDict_ ?
+ [this, other] : [other, this];
+ // TODO(benjhayden) This can't propagate sample diagnostics until
+ // sampleValues are merged into bins alongside their diagnostics.
+ for (const value of singleBin.sampleValues) {
+ if (typeof(value) !== 'number' || isNaN(value)) {
+ continue;
+ }
+ const binIndex = multiBin.getBinIndexForValue(value);
+ let bin = multiBin.allBins[binIndex];
+ if (bin.count === 0) {
+ // Copy HistogramBin on write, share the rest with the other
+ // Histograms that use the same HistogramBinBoundaries.
+ bin = new HistogramBin(bin.range);
+ multiBin.allBins[binIndex] = bin;
+ }
+ bin.addSample(value);
+ }
+ }
+
+ tr.b.math.Statistics.mergeSampledStreams(this.nanDiagnosticMaps,
+ this.numNans, other.nanDiagnosticMaps, other.numNans,
+ MAX_DIAGNOSTIC_MAPS);
+ tr.b.math.Statistics.mergeSampledStreams(
+ this.sampleValues, this.numValues + this.numNans,
+ other.sampleValues, other.numValues + other.numNans,
+ (this.maxNumSampleValues + other.maxNumSampleValues) / 2);
+ this.numNans += other.numNans;
+
+ if (other.running_ !== undefined) {
+ if (this.running_ === undefined) {
+ this.running_ = new tr.b.math.RunningStatistics();
+ }
+ this.running_ = this.running_.merge(other.running_);
+ }
+
+ this.diagnostics.addDiagnostics(other.diagnostics);
+
+ for (const [stat, option] of other.summaryOptions) {
+ if (stat === 'percentile') {
+ const percentiles = this.summaryOptions.get(stat);
+ for (const percent of option) {
+ if (!percentiles.includes(percent)) percentiles.push(percent);
+ }
+ } else if (stat === 'iprs') {
+ const thisIprs = this.summaryOptions.get(stat);
+ for (const ipr of option) {
+ let found = false;
+ for (const thisIpr of thisIprs) {
+ found = ipr.equals(thisIpr);
+ if (found) break;
+ }
+ if (!found) thisIprs.push(ipr);
+ }
+ } else if (option && !this.summaryOptions.get(stat)) {
+ this.summaryOptions.set(stat, true);
+ }
+ }
+ }
+
+ /**
+ * Controls which statistics are exported to dashboard for this Histogram.
+ * The options not included in the |summaryOptions| will not change.
+ *
+ * @param {!Object} summaryOptions
+ * @param {boolean=} summaryOptions.avg
+ * @param {boolean=} summaryOptions.count
+ * @param {boolean=} summaryOptions.geometricMean
+ * @param {boolean=} summaryOptions.max
+ * @param {boolean=} summaryOptions.min
+ * @param {boolean=} summaryOptions.nans
+ * @param {boolean=} summaryOptions.std
+ * @param {boolean=} summaryOptions.sum
+ * @param {!Array.<number>=} summaryOptions.percentile Numbers in (0,1)
+ * @param {!Array.<!tr.b.Range>=} summaryOptions.iprs Ranges of numbers in
+ * (0,1).
+ */
+ customizeSummaryOptions(summaryOptions) {
+ for (const [key, value] of Object.entries(summaryOptions)) {
+ this.summaryOptions.set(key, value);
+ }
+ }
+
+ /**
+ * @param {string} statName
+ * @param {!tr.v.Histogram=} opt_referenceHistogram
+ * @param {!HypothesisTestResult=} opt_mwu
+ * @return {!tr.b.Scalar}
+ * @throws {Error} When statName is not recognized, such as delta statistics
+ * when !this.canCompare(opt_referenceHistograms).
+ */
+ getStatisticScalar(statName, opt_referenceHistogram, opt_mwu) {
+ if (statName === 'avg') {
+ if (typeof(this.average) !== 'number') return undefined;
+ return new tr.b.Scalar(this.unit, this.average);
+ }
+ if (statName === 'std') {
+ if (typeof(this.standardDeviation) !== 'number') return undefined;
+ return new tr.b.Scalar(this.unit, this.standardDeviation);
+ }
+ if (statName === 'geometricMean') {
+ if (typeof(this.geometricMean) !== 'number') return undefined;
+ return new tr.b.Scalar(this.unit, this.geometricMean);
+ }
+ if (statName === 'min' || statName === 'max' || statName === 'sum') {
+ if (this.running_ === undefined) {
+ this.running_ = new tr.b.math.RunningStatistics();
+ }
+ if (typeof(this.running_[statName]) !== 'number') return undefined;
+ return new tr.b.Scalar(this.unit, this.running_[statName]);
+ }
+ if (statName === 'nans') {
+ return new tr.b.Scalar(
+ tr.b.Unit.byName.count_smallerIsBetter, this.numNans);
+ }
+ if (statName === 'count') {
+ return new tr.b.Scalar(
+ tr.b.Unit.byName.count_smallerIsBetter, this.numValues);
+ }
+ if (statName.substr(0, 4) === 'pct_') {
+ const percent = percentFromString(statName.substr(4));
+ if (this.numValues === 0) return undefined;
+ const percentile = this.getApproximatePercentile(percent);
+ if (typeof(percentile) !== 'number') return undefined;
+ return new tr.b.Scalar(this.unit, percentile);
+ }
+ if (statName.substr(0, 4) === 'ipr_') {
+ let lower = percentFromString(statName.substr(4, 3));
+ let upper = percentFromString(statName.substr(8));
+ if (lower >= upper) {
+ throw new Error('Invalid inter-percentile range: ' + statName);
+ }
+ lower = this.getApproximatePercentile(lower);
+ upper = this.getApproximatePercentile(upper);
+ const ipr = upper - lower;
+ if (typeof(ipr) !== 'number') return undefined;
+ return new tr.b.Scalar(this.unit, ipr);
+ }
+
+ if (!this.canCompare(opt_referenceHistogram)) {
+ throw new Error(
+ 'Cannot compute ' + statName +
+ ' when histograms are not comparable');
+ }
+
+ const suffix = tr.b.Unit.nameSuffixForImprovementDirection(
+ this.unit.improvementDirection);
+
+ const deltaIndex = statName.indexOf(DELTA);
+ if (deltaIndex >= 0) {
+ const baseStatName = statName.substr(deltaIndex + 1);
+ const thisStat = this.getStatisticScalar(baseStatName);
+ const otherStat = opt_referenceHistogram.getStatisticScalar(
+ baseStatName);
+ const deltaValue = thisStat.value - otherStat.value;
+
+ if (statName[0] === '%') {
+ return new tr.b.Scalar(
+ tr.b.Unit.byName['normalizedPercentageDelta' + suffix],
+ deltaValue / otherStat.value);
+ }
+ return new tr.b.Scalar(
+ thisStat.unit.correspondingDeltaUnit, deltaValue);
+ }
+
+ if (statName === Z_SCORE_NAME) {
+ return new tr.b.Scalar(
+ tr.b.Unit.byName['sigmaDelta' + suffix],
+ (this.average - opt_referenceHistogram.average) /
+ opt_referenceHistogram.standardDeviation);
+ }
+
+ const mwu = opt_mwu || tr.b.math.Statistics.mwu(
+ this.sampleValues, opt_referenceHistogram.sampleValues);
+ if (statName === P_VALUE_NAME) {
+ return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.p);
+ }
+ if (statName === U_STATISTIC_NAME) {
+ return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.U);
+ }
+
+ throw new Error('Unrecognized statistic name: ' + statName);
+ }
+
+ /**
+ * @return {!Array.<string>} names of enabled summary statistics
+ */
+ get statisticsNames() {
+ const statisticsNames = new Set();
+ for (const [statName, option] of this.summaryOptions) {
+ if (statName === 'percentile') {
+ for (const pctile of option) {
+ statisticsNames.add('pct_' + tr.v.percentToString(pctile));
+ }
+ } else if (statName === 'iprs') {
+ for (const range of option) {
+ statisticsNames.add(
+ 'ipr_' + tr.v.percentToString(range.min, true) +
+ '_' + tr.v.percentToString(range.max, true));
+ }
+ } else if (option) {
+ statisticsNames.add(statName);
+ }
+ }
+ return statisticsNames;
+ }
+
+ /**
+ * Returns true if delta statistics can be computed between |this| and
+ * |other|.
+ *
+ * @param {!tr.v.Histogram=} other
+ * @return {boolean}
+ */
+ canCompare(other) {
+ return other instanceof Histogram &&
+ this.unit === other.unit &&
+ this.numValues > 0 &&
+ other.numValues > 0;
+ }
+
+ /**
+ * Returns |statName| if it can be computed, or the related non-delta
+ * statistic if |statName| is a delta statistic and
+ * !this.canCompare(opt_referenceHist).
+ *
+ * @param {string} statName
+ * @param {!tr.v.Histogram=} opt_referenceHist
+ * @return {string}
+ */
+ getAvailableStatisticName(statName, opt_referenceHist) {
+ if (this.canCompare(opt_referenceHist)) return statName;
+ if (statName === Z_SCORE_NAME ||
+ statName === P_VALUE_NAME ||
+ statName === U_STATISTIC_NAME) {
+ return 'avg';
+ }
+ const deltaIndex = statName.indexOf(DELTA);
+ if (deltaIndex < 0) return statName;
+ return statName.substr(deltaIndex + 1);
+ }
+
+ /**
+ * Returns names of delta statistics versions of given non-delta statistics
+ * names.
+ *
+ * @param {!Array.<string>} statNames
+ * @return {!Array.<string>}
+ */
+ static getDeltaStatisticsNames(statNames) {
+ const deltaNames = [];
+ for (const statName of statNames) {
+ deltaNames.push(`${DELTA}${statName}`);
+ deltaNames.push(`%${DELTA}${statName}`);
+ }
+ return deltaNames.concat([Z_SCORE_NAME, P_VALUE_NAME, U_STATISTIC_NAME]);
+ }
+
+ /**
+ * Returns a Map {statisticName: Scalar}.
+ *
+ * Each enabled summary option produces the corresponding value:
+ * min, max, count, sum, avg, or std.
+ * Each percentile 0.x produces pct_0x0.
+ * Each percentile 0.xx produces pct_0xx.
+ * Each percentile 0.xxy produces pct_0xx_y.
+ * Percentile 1.0 produces pct_100.
+ *
+ * @return {!Map.<string, Scalar>}
+ */
+ get statisticsScalars() {
+ const results = new Map();
+ for (const statName of this.statisticsNames) {
+ const scalar = this.getStatisticScalar(statName);
+ if (scalar === undefined) continue;
+ results.set(statName, scalar);
+ }
+ return results;
+ }
+
+ get sampleValues() {
+ return this.sampleValues_;
+ }
+
+ /**
+ * Create a new Histogram instance that is just like |this|. This is useful
+ * when merging Histograms.
+ * @return {!tr.v.Histogram}
+ */
+ clone() {
+ const binBoundaries = HistogramBinBoundaries.fromDict(
+ this.binBoundariesDict_);
+ const hist = new Histogram(this.name, this.unit, binBoundaries);
+ for (const [stat, option] of this.summaryOptions) {
+ // Copy arrays, but not ipr Ranges.
+ if (stat === 'percentile' || stat === 'iprs') {
+ hist.summaryOptions.set(stat, Array.from(option));
+ } else {
+ hist.summaryOptions.set(stat, option);
+ }
+ }
+ hist.addHistogram(this);
+ return hist;
+ }
+
+ /**
+ * Produce a Histogram with |this| Histogram's name, unit, description,
+ * statistics, summaryOptions, sampleValues, and diagnostics, but with
+ * |newBoundaries|.
+ * sample diagnostics are not copied. In-bound Relationship
+ * diagnostics are broken.
+ *
+ * @param {!tr.v.HistogramBinBoundaries} newBoundaries
+ * @return {!tr.v.Histogram}
+ */
+ rebin(newBoundaries) {
+ const rebinned = new tr.v.Histogram(this.name, this.unit, newBoundaries);
+ rebinned.description = this.description;
+ for (const sample of this.sampleValues) {
+ rebinned.addSample(sample);
+ }
+ rebinned.running_ = this.running_;
+ for (const [name, diagnostic] of this.diagnostics) {
+ rebinned.diagnostics.set(name, diagnostic);
+ }
+ for (const [stat, option] of this.summaryOptions) {
+ // Copy the array of percentiles.
+ if (stat === 'percentile') {
+ rebinned.summaryOptions.set(stat, Array.from(option));
+ } else {
+ rebinned.summaryOptions.set(stat, option);
+ }
+ }
+ return rebinned;
+ }
+
+ asDict() {
+ const dict = {};
+ dict.name = this.name;
+ dict.unit = this.unit.asJSON();
+ if (this.binBoundariesDict_ !== undefined) {
+ dict.binBoundaries = this.binBoundariesDict_;
+ }
+ if (this.description) {
+ dict.description = this.description;
+ }
+ if (this.diagnostics.size) {
+ dict.diagnostics = this.diagnostics.asDict();
+ }
+ if (this.maxNumSampleValues !== this.defaultMaxNumSampleValues_) {
+ dict.maxNumSampleValues = this.maxNumSampleValues;
+ }
+ if (this.numNans) {
+ dict.numNans = this.numNans;
+ }
+ if (this.nanDiagnosticMaps.length) {
+ dict.nanDiagnostics = this.nanDiagnosticMaps.map(
+ dm => dm.asDict());
+ }
+
+ if (this.numValues) {
+ dict.sampleValues = this.sampleValues.slice();
+ this.running.truncate(this.unit);
+ dict.running = this.running_.asDict();
+ dict.allBins = this.allBinsAsDict_();
+ }
+
+ const summaryOptions = {};
+ let anyOverriddenSummaryOptions = false;
+ for (const [name, value] of this.summaryOptions) {
+ let option;
+ if (name === 'percentile') {
+ if (value.length === 0) continue;
+ option = Array.from(value);
+ } else if (name === 'iprs') {
+ // Use a more compact JSON format than Range supports.
+ if (value.length === 0) continue;
+ option = value.map(r => [r.min, r.max]);
+ } else if (value === DEFAULT_SUMMARY_OPTIONS.get(name)) {
+ continue;
+ } else {
+ option = value;
+ }
+ summaryOptions[name] = option;
+ anyOverriddenSummaryOptions = true;
+ }
+ if (anyOverriddenSummaryOptions) {
+ dict.summaryOptions = summaryOptions;
+ }
+
+ return dict;
+ }
+
+ allBinsAsDict_() {
+ // dict.allBins may be either an array or a dict, whichever is more
+ // efficient.
+ // The overhead of the array form is significant when the histogram is
+ // sparse, and the overhead of the dict form is significant when the
+ // histogram is dense.
+ // The dict form is more efficient when more than half of allBins are
+ // empty. The array form is more efficient when fewer than half of
+ // allBins are empty.
+
+ const numBins = this.allBins.length;
+
+ // If allBins are empty, then don't serialize anything for them.
+ let emptyBins = 0;
+
+ for (let i = 0; i < numBins; ++i) {
+ if (this.allBins[i].count === 0) {
+ ++emptyBins;
+ }
+ }
+
+ if (emptyBins === numBins) {
+ return undefined;
+ }
+
+ if (emptyBins > (numBins / 2)) {
+ const allBinsDict = {};
+ for (let i = 0; i < numBins; ++i) {
+ const bin = this.allBins[i];
+ if (bin.count > 0) {
+ allBinsDict[i] = bin.asDict();
+ }
+ }
+ return allBinsDict;
+ }
+
+ const allBinsArray = [];
+ for (let i = 0; i < numBins; ++i) {
+ allBinsArray.push(this.allBins[i].asDict());
+ }
+ return allBinsArray;
+ }
+
+ get defaultMaxNumSampleValues_() {
+ // Single-bin histograms might be rebin()ned, so they should retain enough
+ // samples that the rebinned histogram looks close enough.
+ return DEFAULT_SAMPLE_VALUES_PER_BIN * Math.max(
+ this.allBins.length, DEFAULT_REBINNED_COUNT);
+ }
+ }
+
+ // Some metrics only want to report average. This dictionary is provided to
+ // facilitate disabling all other statistics.
+ Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS = {
+ count: false,
+ max: false,
+ min: false,
+ std: false,
+ sum: false,
+ };
+
+ const HISTOGRAM_BIN_BOUNDARIES_CACHE = new Map();
+
+ /*
+ * Reusable builder for tr.v.Histogram objects.
+ *
+ * The bins of the Histogram are specified by adding the desired boundaries
+ * between bins. Initially, the builder has only a single boundary:
+ *
+ * range.min=range.max
+ * |
+ * |
+ * -MAX_VALUE <-----|-----------> +MAX_VALUE
+ * : resulting : resulting :
+ * : underflow : overflow :
+ * : bin : bin :
+ *
+ * If the single boundary is set to either -Number.MAX_VALUE or
+ * +Number.MAX_VALUE, then the builder will construct only a single bin:
+ *
+ * range.min=range.max
+ * |
+ * |
+ * -MAX_VALUE <-> +MAX_VALUE
+ * : resulting :
+ * : bin :
+ *
+ * More boundaries can be added (in increasing order) using addBinBoundary,
+ * addLinearBins and addExponentialBins:
+ *
+ * range.min range.max
+ * | | | | |
+ * | | | | |
+ * -MAX_VALUE <------|---------|---------|-----|---------|------> +MAX_VALUE
+ * : resulting : result. : result. : : result. : resulting :
+ * : underflow : central : central : ... : central : overflow :
+ * : bin : bin 0 : bin 1 : : bin N-1 : bin :
+ *
+ * An important feature of the builder is that it's reusable, i.e. it can be
+ * used to build multiple Histograms with the same bin structure.
+ */
+ class HistogramBinBoundaries {
+ /**
+ * Create a linearly scaled tr.v.HistogramBinBoundaries with |numBins| bins
+ * ranging from |min| to |max|.
+ *
+ * @param {number} min
+ * @param {number} max
+ * @param {number} numBins
+ * @return {tr.v.HistogramBinBoundaries}
+ */
+ static createLinear(min, max, numBins) {
+ return new HistogramBinBoundaries(min).addLinearBins(max, numBins);
+ }
+
+ /**
+ * Create an exponentially scaled tr.v.HistogramBinBoundaries with |numBins|
+ * bins ranging from |min| to |max|.
+ *
+ * @param {number} min
+ * @param {number} max
+ * @param {number} numBins
+ * @return {tr.v.HistogramBinBoundaries}
+ */
+ static createExponential(min, max, numBins) {
+ return new HistogramBinBoundaries(min).addExponentialBins(max, numBins);
+ }
+
+ /**
+ * @param {Array.<number>} binBoundaries
+ */
+ static createWithBoundaries(binBoundaries) {
+ const builder = new HistogramBinBoundaries(binBoundaries[0]);
+ for (const boundary of binBoundaries.slice(1)) {
+ builder.addBinBoundary(boundary);
+ }
+ return builder;
+ }
+
+ /**
+ * |minBinBoundary| will be the boundary between the underflow bin and the
+ * first central bin if other bin boundaries are added.
+ * If no other bin boundaries are added, then |minBinBoundary| will be the
+ * boundary between the underflow bin and the overflow bin.
+ * If no other bin boundaries are added and |minBinBoundary| is either
+ * -Number.MAX_VALUE or +Number.MAX_VALUE, then only a single binRange will
+ * be built.
+ *
+ * @param {number} minBinBoundary The minimum boundary between bins.
+ */
+ constructor(minBinBoundary) {
+ this.builder_ = [minBinBoundary];
+ this.range_ = new tr.b.math.Range();
+ this.range_.addValue(minBinBoundary);
+ this.binRanges_ = undefined;
+ this.bins_ = undefined;
+ }
+
+ get range() {
+ return this.range_;
+ }
+
+ asDict() {
+ if (this.builder_.length === 1 && this.builder_[0] === Number.MAX_VALUE) {
+ return undefined;
+ }
+
+ // Don't copy builder_ here so that Histogram.canAddHistogram() can test
+ // for object identity.
+ return this.builder_;
+ }
+
+ pushBuilderSlice_(slice) {
+ this.builder_.push(slice);
+ // Copy builder_ when it's modified so that Histogram.canAddHistogram()
+ // can test for object identity.
+ this.builder_ = this.builder_.slice();
+ }
+
+ static fromDict(dict) {
+ if (dict === undefined) {
+ return HistogramBinBoundaries.SINGULAR;
+ }
+
+ // When loading a results.html with many Histograms with the same bin
+ // boundaries, caching the HistogramBinBoundaries not only speeds up
+ // loading, but also prevents a bug where buildBinRanges_ is occasionally
+ // non-deterministic, which causes similar Histograms to be unmergeable.
+ const cacheKey = JSON.stringify(dict);
+ if (HISTOGRAM_BIN_BOUNDARIES_CACHE.has(cacheKey)) {
+ return HISTOGRAM_BIN_BOUNDARIES_CACHE.get(cacheKey);
+ }
+
+ const binBoundaries = new HistogramBinBoundaries(dict[0]);
+ for (const slice of dict.slice(1)) {
+ if (!(slice instanceof Array)) {
+ binBoundaries.addBinBoundary(slice);
+ continue;
+ }
+ switch (slice[0]) {
+ case HistogramBinBoundaries.SLICE_TYPE.LINEAR:
+ binBoundaries.addLinearBins(slice[1], slice[2]);
+ break;
+
+ case HistogramBinBoundaries.SLICE_TYPE.EXPONENTIAL:
+ binBoundaries.addExponentialBins(slice[1], slice[2]);
+ break;
+
+ default:
+ throw new Error('Unrecognized HistogramBinBoundaries slice type');
+ }
+ }
+ HISTOGRAM_BIN_BOUNDARIES_CACHE.set(cacheKey, binBoundaries);
+ return binBoundaries;
+ }
+
+ get bins() {
+ if (this.bins_ === undefined) {
+ this.buildBins_();
+ }
+ return this.bins_;
+ }
+
+ buildBins_() {
+ this.bins_ = this.binRanges.map(r => new HistogramBin(r));
+ // It would be nice to Object.freeze() the bins in order to catch bugs
+ // when we forget to copy a bin before writing to it, but that would slow
+ // down buildBins_ by 55%: https://jsperf.com/new-vs-new-freeze/1
+ }
+
+ /**
+ * @return {!Array.<!tr.b.math.Range>}
+ */
+ get binRanges() {
+ if (this.binRanges_ === undefined) {
+ this.buildBinRanges_();
+ }
+ return this.binRanges_;
+ }
+
+ buildBinRanges_() {
+ if (typeof this.builder_[0] !== 'number') {
+ throw new Error('Invalid start of builder_');
+ }
+ this.binRanges_ = [];
+ let prevBoundary = this.builder_[0];
+
+ if (prevBoundary > -Number.MAX_VALUE) {
+ // underflow bin
+ this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
+ -Number.MAX_VALUE, prevBoundary));
+ }
+
+ for (const slice of this.builder_.slice(1)) {
+ if (!(slice instanceof Array)) {
+ this.binRanges_.push(
+ tr.b.math.Range.fromExplicitRange(prevBoundary, slice));
+ prevBoundary = slice;
+ continue;
+ }
+ const nextMaxBinBoundary = slice[1];
+ const binCount = slice[2];
+ const sliceMinBinBoundary = prevBoundary;
+
+ switch (slice[0]) {
+ case HistogramBinBoundaries.SLICE_TYPE.LINEAR:
+ {
+ const binWidth = (nextMaxBinBoundary - prevBoundary) / binCount;
+ for (let i = 1; i < binCount; i++) {
+ const boundary = sliceMinBinBoundary + i * binWidth;
+ this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
+ prevBoundary, boundary));
+ prevBoundary = boundary;
+ }
+ break;
+ }
+
+ case HistogramBinBoundaries.SLICE_TYPE.EXPONENTIAL:
+ {
+ const binExponentWidth =
+ Math.log(nextMaxBinBoundary / prevBoundary) / binCount;
+ for (let i = 1; i < binCount; i++) {
+ const boundary = sliceMinBinBoundary * Math.exp(
+ i * binExponentWidth);
+ this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
+ prevBoundary, boundary));
+ prevBoundary = boundary;
+ }
+ break;
+ }
+
+ default:
+ throw new Error('Unrecognized HistogramBinBoundaries slice type');
+ }
+ this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
+ prevBoundary, nextMaxBinBoundary));
+ prevBoundary = nextMaxBinBoundary;
+ }
+ if (prevBoundary < Number.MAX_VALUE) {
+ // overflow bin
+ this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
+ prevBoundary, Number.MAX_VALUE));
+ }
+ }
+
+ /**
+ * Add a bin boundary |nextMaxBinBoundary| to the builder.
+ *
+ * This operation effectively corresponds to appending a new central bin
+ * with the range [this.range.max, nextMaxBinBoundary].
+ *
+ * @param {number} nextMaxBinBoundary The added bin boundary (must be
+ * greater than |this.maxMinBoundary|).
+ */
+ addBinBoundary(nextMaxBinBoundary) {
+ if (nextMaxBinBoundary <= this.range.max) {
+ throw new Error('The added max bin boundary must be larger than ' +
+ 'the current max boundary');
+ }
+
+ // If binRanges_ had been built, then clear them.
+ this.binRanges_ = undefined;
+ this.bins_ = undefined;
+
+ this.pushBuilderSlice_(nextMaxBinBoundary);
+ this.range.addValue(nextMaxBinBoundary);
+ return this;
+ }
+
+ /**
+ * Add |binCount| linearly scaled bin boundaries up to |nextMaxBinBoundary|
+ * to the builder.
+ *
+ * This operation corresponds to appending |binCount| central bins of
+ * constant range width
+ * W = ((|nextMaxBinBoundary| - |this.range.max|) / |binCount|)
+ * with the following ranges:
+ *
+ * [|this.maxMinBoundary|, |this.maxMinBoundary| + W]
+ * [|this.maxMinBoundary| + W, |this.maxMinBoundary| + 2W]
+ * [|this.maxMinBoundary| + 2W, |this.maxMinBoundary| + 3W]
+ * ...
+ * [|this.maxMinBoundary| + (|binCount| - 2) * W,
+ * |this.maxMinBoundary| + (|binCount| - 2) * W]
+ * [|this.maxMinBoundary| + (|binCount| - 1) * W,
+ * |nextMaxBinBoundary|]
+ *
+ * @param {number} nextBinBoundary The last added bin boundary (must be
+ * greater than |this.maxMinBoundary|).
+ * @param {number} binCount Number of bins to be added (must be positive).
+ */
+ addLinearBins(nextMaxBinBoundary, binCount) {
+ if (binCount <= 0) {
+ throw new Error('Bin count must be positive');
+ }
+
+ if (nextMaxBinBoundary <= this.range.max) {
+ throw new Error('The new max bin boundary must be greater than ' +
+ 'the previous max bin boundary');
+ }
+
+ // If binRanges_ had been built, then clear them.
+ this.binRanges_ = undefined;
+ this.bins_ = undefined;
+
+ this.pushBuilderSlice_([
+ HistogramBinBoundaries.SLICE_TYPE.LINEAR,
+ nextMaxBinBoundary, binCount]);
+ this.range.addValue(nextMaxBinBoundary);
+ return this;
+ }
+
+ /**
+ * Add |binCount| exponentially scaled bin boundaries up to
+ * |nextMaxBinBoundary| to the builder.
+ *
+ * This operation corresponds to appending |binCount| central bins with
+ * a constant difference between the logarithms of their range min and max
+ * D = ((ln(|nextMaxBinBoundary|) - ln(|this.range.max|)) / |binCount|)
+ * with the following ranges:
+ *
+ * [|this.maxMinBoundary|, |this.maxMinBoundary| * exp(D)]
+ * [|this.maxMinBoundary| * exp(D), |this.maxMinBoundary| * exp(2D)]
+ * [|this.maxMinBoundary| * exp(2D), |this.maxMinBoundary| * exp(3D)]
+ * ...
+ * [|this.maxMinBoundary| * exp((|binCount| - 2) * D),
+ * |this.maxMinBoundary| * exp((|binCount| - 2) * D)]
+ * [|this.maxMinBoundary| * exp((|binCount| - 1) * D),
+ * |nextMaxBinBoundary|]
+ *
+ * This method requires that the current max bin boundary is positive.
+ *
+ * @param {number} nextBinBoundary The last added bin boundary (must be
+ * greater than |this.maxMinBoundary|).
+ * @param {number} binCount Number of bins to be added (must be positive).
+ */
+ addExponentialBins(nextMaxBinBoundary, binCount) {
+ if (binCount <= 0) {
+ throw new Error('Bin count must be positive');
+ }
+ if (this.range.max <= 0) {
+ throw new Error('Current max bin boundary must be positive');
+ }
+ if (this.range.max >= nextMaxBinBoundary) {
+ throw new Error('The last added max boundary must be greater than ' +
+ 'the current max boundary boundary');
+ }
+
+ // If binRanges_ had been built, then clear them.
+ this.binRanges_ = undefined;
+ this.bins_ = undefined;
+
+ this.pushBuilderSlice_([
+ HistogramBinBoundaries.SLICE_TYPE.EXPONENTIAL,
+ nextMaxBinBoundary, binCount]);
+ this.range.addValue(nextMaxBinBoundary);
+ return this;
+ }
+ }
+
+ HistogramBinBoundaries.SLICE_TYPE = {
+ LINEAR: 0,
+ EXPONENTIAL: 1,
+ };
+
+ // This special HistogramBinBoundaries instance produces a singe binRange,
+ // allowing Histograms to have a single bin.
+ // This is the only way for Histograms to have fewer than 2 bins, since
+ // HistogramBinBoundaries.buildBinRanges_() ensures that there is always a bin
+ // whose min is -Number.MAX_VALUE, and a bin whose max is Number.MAX_VALUE.
+ // SINGULAR is the only HistogramBinBoundaries in which those bins are one and
+ // the same.
+ HistogramBinBoundaries.SINGULAR = new HistogramBinBoundaries(
+ Number.MAX_VALUE);
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.timeDurationInMs.unitName,
+ HistogramBinBoundaries.createExponential(1e-3, 1e6, 1e2));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.timeInMsAutoFormat.unitName,
+ new HistogramBinBoundaries(0)
+ .addBinBoundary(1).addExponentialBins(1e3, 3)
+ .addBinBoundary(tr.b.convertUnit(
+ 2, tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ 5, tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ 10, tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ 30, tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ tr.b.UnitScale.TIME.MINUTE.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(2 * tr.b.convertUnit(
+ tr.b.UnitScale.TIME.MINUTE.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(5 * tr.b.convertUnit(
+ tr.b.UnitScale.TIME.MINUTE.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(10 * tr.b.convertUnit(
+ tr.b.UnitScale.TIME.MINUTE.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(30 * tr.b.convertUnit(
+ tr.b.UnitScale.TIME.MINUTE.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ tr.b.UnitScale.TIME.HOUR.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(2 * tr.b.convertUnit(
+ tr.b.UnitScale.TIME.HOUR.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(6 * tr.b.convertUnit(
+ tr.b.UnitScale.TIME.HOUR.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(12 * tr.b.convertUnit(
+ tr.b.UnitScale.TIME.HOUR.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ tr.b.UnitScale.TIME.DAY.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ tr.b.UnitScale.TIME.WEEK.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ tr.b.UnitScale.TIME.MONTH.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC))
+ .addBinBoundary(tr.b.convertUnit(
+ tr.b.UnitScale.TIME.YEAR.value,
+ tr.b.UnitScale.TIME.SEC, tr.b.UnitScale.TIME.MILLI_SEC)));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.timeStampInMs.unitName,
+ HistogramBinBoundaries.createLinear(0, 1e10, 1e3));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.normalizedPercentage.unitName,
+ HistogramBinBoundaries.createLinear(0, 1.0, 20));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.sizeInBytes.unitName,
+ HistogramBinBoundaries.createExponential(1, 1e12, 1e2));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.energyInJoules.unitName,
+ HistogramBinBoundaries.createExponential(1e-3, 1e3, 50));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.powerInWatts.unitName,
+ HistogramBinBoundaries.createExponential(1e-3, 1, 50));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.unitlessNumber.unitName,
+ HistogramBinBoundaries.createExponential(1e-3, 1e3, 50));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.count.unitName,
+ HistogramBinBoundaries.createExponential(1, 1e3, 20));
+
+ DEFAULT_BOUNDARIES_FOR_UNIT.set(
+ tr.b.Unit.byName.sigma.unitName,
+ HistogramBinBoundaries.createLinear(-5, 5, 50));
+
+ return {
+ DEFAULT_REBINNED_COUNT,
+ DELTA,
+ Histogram,
+ HistogramBinBoundaries,
+ P_VALUE_NAME,
+ U_STATISTIC_NAME,
+ Z_SCORE_NAME,
+ percentFromString,
+ percentToString,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram.py b/chromium/third_party/catapult/tracing/tracing/value/histogram.py
new file mode 100644
index 00000000000..272468f6430
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram.py
@@ -0,0 +1,1111 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import math
+import numbers
+import random
+
+from tracing.value.diagnostics import diagnostic
+from tracing.value.diagnostics import diagnostic_ref
+from tracing.value.diagnostics import reserved_infos
+from tracing.value.diagnostics import unmergeable_diagnostic_set
+
+
+try:
+ StringTypes = basestring
+except NameError:
+ StringTypes = str
+
+
+# pylint: disable=too-many-lines
+# TODO(#3613) Split this file.
+
+
+# This should be equal to sys.float_info.max, but that value might differ
+# between platforms, whereas ECMA Script specifies this value for all platforms.
+# The specific value should not matter in normal practice.
+JS_MAX_VALUE = 1.7976931348623157e+308
+
+
+# Converts the given percent to a string in the following format:
+# 0.x produces '0x0',
+# 0.xx produces '0xx',
+# 0.xxy produces '0xx_y',
+# 1.0 produces '100'.
+def PercentToString(percent):
+ if percent < 0 or percent > 1:
+ raise ValueError('percent must be in [0,1]')
+ if percent == 0:
+ return '000'
+ if percent == 1:
+ return '100'
+ s = str(percent)
+ if s[1] != '.':
+ raise ValueError('Unexpected percent')
+ s += '0' * max(4 - len(s), 0)
+ if len(s) > 4:
+ s = s[:4] + '_' + s[4:]
+ return '0' + s[2:]
+
+
+# This variation of binary search returns the index |hi| into |ary| for which
+# callback(ary[hi]) < 0 and callback(ary[hi-1]) >= 0
+# This function assumes that map(callback, ary) is sorted descending.
+def FindHighIndexInSortedArray(ary, callback):
+ lo = 0
+ hi = len(ary)
+ while lo < hi:
+ mid = (lo + hi) >> 1
+ if callback(ary[mid]) >= 0:
+ lo = mid + 1
+ else:
+ hi = mid
+ return hi
+
+
+# Modifies |samples| in-place to reduce its length to |count|, discarding random
+# elements.
+def UniformlySampleArray(samples, count):
+ while len(samples) > count:
+ samples.pop(int(random.uniform(0, len(samples))))
+ return samples
+
+
+# When processing a stream of samples, call this method for each new sample in
+# order to decide whether to keep it in |samples|.
+# Modifies |samples| in-place such that its length never exceeds |num_samples|.
+# After |stream_length| samples have been processed, each sample has equal
+# probability of being retained in |samples|.
+# The order of samples is not preserved after |stream_length| exceeds
+# |num_samples|.
+def UniformlySampleStream(samples, stream_length, new_element, num_samples):
+ if stream_length <= num_samples:
+ if len(samples) >= stream_length:
+ samples[stream_length - 1] = new_element
+ else:
+ samples.append(new_element)
+ return
+
+ prob_keep = num_samples / stream_length
+ if random.random() > prob_keep:
+ # reject new_sample
+ return
+
+ # replace a random element
+ samples[math.floor(random.random() * num_samples)] = new_element
+
+
+# Merge two sets of samples that were assembled using UniformlySampleStream().
+# Modify |a_samples| in-place such that all of the samples in |a_samples| and
+# |b_samples| have equal probability of being retained in |a_samples|.
+def MergeSampledStreams(a_samples, a_stream_length,
+ b_samples, b_stream_length, num_samples):
+ if b_stream_length < num_samples:
+ for i in range(min(b_stream_length, len(b_samples))):
+ UniformlySampleStream(
+ a_samples, a_stream_length + i + 1, b_samples[i], num_samples)
+ return
+
+ if a_stream_length < num_samples:
+ temp_samples = list(b_samples)
+ for i in range(min(a_stream_length, len(a_samples))):
+ UniformlySampleStream(
+ temp_samples, b_stream_length + i + 1, a_samples[i], num_samples)
+ for i, temp_sample in enumerate(temp_samples):
+ a_samples[i] = temp_sample
+ return
+
+ prob_swap = b_stream_length / (a_stream_length + b_stream_length)
+ for i in range(min(num_samples, len(b_samples))):
+ if random.random() < prob_swap:
+ a_samples[i] = b_samples[i]
+
+
+def Percentile(ary, percent):
+ if percent < 0 or percent > 1:
+ raise ValueError('percent must be in [0,1]')
+ ary = list(ary)
+ ary.sort()
+ return ary[int((len(ary) - 1) * percent)]
+
+
+class Range(object):
+ __slots__ = '_empty', '_min', '_max'
+
+ def __init__(self):
+ self._empty = True
+ self._min = None
+ self._max = None
+
+ def __eq__(self, other):
+ if not isinstance(other, Range):
+ return False
+ if self.empty and other.empty:
+ return True
+ if self.empty != other.empty:
+ return False
+ return (self.min == other.min) and (self.max == other.max)
+
+ def __hash__(self):
+ return id(self)
+
+ @staticmethod
+ def FromExplicitRange(lower, upper):
+ r = Range()
+ r._min = lower
+ r._max = upper
+ r._empty = False
+ return r
+
+ @property
+ def empty(self):
+ return self._empty
+
+ @property
+ def min(self):
+ return self._min
+
+ @property
+ def max(self):
+ return self._max
+
+ @property
+ def center(self):
+ return (self._min + self._max) * 0.5
+
+ @property
+ def duration(self):
+ if self.empty:
+ return 0
+ return self._max - self._min
+
+ def AddValue(self, x):
+ if self._empty:
+ self._empty = False
+ self._min = x
+ self._max = x
+ return
+
+ self._max = max(x, self._max)
+ self._min = min(x, self._min)
+
+ def AddRange(self, other):
+ if other.empty:
+ return
+ self.AddValue(other.min)
+ self.AddValue(other.max)
+
+
+# This class computes statistics online in O(1).
+class RunningStatistics(object):
+ __slots__ = (
+ '_count', '_mean', '_max', '_min', '_sum', '_variance', '_meanlogs')
+
+ def __init__(self):
+ self._count = 0
+ self._mean = 0.0
+ self._max = -JS_MAX_VALUE
+ self._min = JS_MAX_VALUE
+ self._sum = 0.0
+ self._variance = 0.0
+ # Mean of logarithms of samples, or None if any samples were <= 0.
+ self._meanlogs = 0.0
+
+ @property
+ def count(self):
+ return self._count
+
+ @property
+ def geometric_mean(self):
+ if self._meanlogs is None:
+ return None
+ return math.exp(self._meanlogs)
+
+ @property
+ def mean(self):
+ if self._count == 0:
+ return None
+ return self._mean
+
+ @property
+ def max(self):
+ return self._max
+
+ @property
+ def min(self):
+ return self._min
+
+ @property
+ def sum(self):
+ return self._sum
+
+ # This returns the variance of the samples after Bessel's correction has
+ # been applied.
+ @property
+ def variance(self):
+ if self.count == 0:
+ return None
+ if self.count == 1:
+ return 0
+ return self._variance / (self.count - 1)
+
+ # This returns the standard deviation of the samples after Bessel's
+ # correction has been applied.
+ @property
+ def stddev(self):
+ if self.count == 0:
+ return None
+ return math.sqrt(self.variance)
+
+ def Add(self, x):
+ self._count += 1
+ x = float(x)
+ self._max = max(self._max, x)
+ self._min = min(self._min, x)
+ self._sum += x
+
+ if x <= 0.0:
+ self._meanlogs = None
+ elif self._meanlogs is not None:
+ self._meanlogs += (math.log(abs(x)) - self._meanlogs) / self.count
+
+ # The following uses Welford's algorithm for computing running mean and
+ # variance. See http://www.johndcook.com/blog/standard_deviation.
+ if self.count == 1:
+ self._mean = x
+ self._variance = 0.0
+ else:
+ old_mean = self._mean
+ old_variance = self._variance
+
+ # Using the 2nd formula for updating the mean yields better precision but
+ # it doesn't work for the case oldMean is Infinity. Hence we handle that
+ # case separately.
+ if abs(old_mean) == float('inf'):
+ self._mean = self._sum / self.count
+ else:
+ self._mean = old_mean + float(x - old_mean) / self.count
+ self._variance = old_variance + (x - old_mean) * (x - self._mean)
+
+ def Merge(self, other):
+ result = RunningStatistics()
+ result._count = self._count + other._count
+ result._sum = self._sum + other._sum
+ result._min = min(self._min, other._min)
+ result._max = max(self._max, other._max)
+ if result._count == 0:
+ result._mean = 0.0
+ result._variance = 0.0
+ result._meanlogs = 0.0
+ else:
+ # Combine the mean and the variance using the formulas from
+ # https://goo.gl/ddcAep.
+ result._mean = float(result._sum) / result._count
+ delta_mean = (self._mean or 0.0) - (other._mean or 0.0)
+ result._variance = self._variance + other._variance + (
+ self._count * other._count * delta_mean * delta_mean / result._count)
+
+ # Merge the arithmetic means of logarithms of absolute values of samples,
+ # weighted by counts.
+ if self._meanlogs is None or other._meanlogs is None:
+ result._meanlogs = None
+ else:
+ result._meanlogs = (self._count * self._meanlogs +
+ other._count * other._meanlogs) / result._count
+ return result
+
+ def AsDict(self):
+ if self._count == 0:
+ return []
+
+ # Javascript automatically converts between ints and floats.
+ # It's more efficient to serialize integers as ints than floats.
+ def FloatAsFloatOrInt(x):
+ if x is not None and x.is_integer():
+ return int(x)
+ return x
+
+ # It's more efficient to serialize these fields in an array. If you add any
+ # other fields, you should re-evaluate whether it would be more efficient to
+ # serialize as a dict.
+ return [
+ self._count,
+ FloatAsFloatOrInt(self._max),
+ FloatAsFloatOrInt(self._meanlogs),
+ FloatAsFloatOrInt(self._mean),
+ FloatAsFloatOrInt(self._min),
+ FloatAsFloatOrInt(self._sum),
+ FloatAsFloatOrInt(self._variance),
+ ]
+
+ @staticmethod
+ def FromDict(dct):
+ result = RunningStatistics()
+ if len(dct) != 7:
+ return result
+
+ def AsFloatOrNone(x):
+ if x is None:
+ return x
+ return float(x)
+ [result._count, result._max, result._meanlogs, result._mean, result._min,
+ result._sum, result._variance] = [int(dct[0])] + [
+ AsFloatOrNone(x) for x in dct[1:]]
+ return result
+
+
+class DiagnosticMap(dict):
+ __slots__ = '_allow_reserved_names',
+
+ def __init__(self, *args, **kwargs):
+ self._allow_reserved_names = True
+ dict.__init__(self, *args, **kwargs)
+
+ def DisallowReservedNames(self):
+ self._allow_reserved_names = False
+
+ def __setitem__(self, name, diag):
+ if not isinstance(name, StringTypes):
+ raise TypeError('name must be string')
+ if not isinstance(diag, (diagnostic.Diagnostic,
+ diagnostic_ref.DiagnosticRef)):
+ raise TypeError('diag must be Diagnostic or DiagnosticRef')
+ if (not self._allow_reserved_names and
+ not isinstance(diag,
+ unmergeable_diagnostic_set.UnmergeableDiagnosticSet) and
+ not isinstance(diag, diagnostic_ref.DiagnosticRef)):
+ expected_type = reserved_infos.GetTypeForName(name)
+ if expected_type and diag.__class__.__name__ != expected_type:
+ raise TypeError('Diagnostics names "%s" must be %s, not %s' %
+ (name, expected_type, diag.__class__.__name__))
+ dict.__setitem__(self, name, diag)
+
+ @staticmethod
+ def FromDict(dct):
+ dm = DiagnosticMap()
+ dm.AddDicts(dct)
+ return dm
+
+ def AddDicts(self, dct):
+ for name, diagnostic_dict in dct.items():
+ if name == 'tagmap':
+ continue
+ if isinstance(diagnostic_dict, StringTypes):
+ self[name] = diagnostic_ref.DiagnosticRef(diagnostic_dict)
+ elif diagnostic_dict['type'] not in [
+ 'RelatedHistogramMap', 'RelatedHistogramBreakdown', 'TagMap']:
+ # Ignore RelatedHistograms and TagMaps.
+ # TODO(benjhayden): Forget about them in 2019 Q2.
+ self[name] = diagnostic.Diagnostic.FromDict(diagnostic_dict)
+
+ def ResolveSharedDiagnostics(self, histograms, required=False):
+ for name, diag in self.items():
+ if not isinstance(diag, diagnostic_ref.DiagnosticRef):
+ continue
+ guid = diag.guid
+ diag = histograms.LookupDiagnostic(guid)
+ if isinstance(diag, diagnostic.Diagnostic):
+ self[name] = diag
+ elif required:
+ raise ValueError('Unable to find shared Diagnostic ' + guid)
+
+ def AsDict(self):
+ dct = {}
+ for name, diag in self.items():
+ dct[name] = diag.AsDictOrReference()
+ return dct
+
+ def Merge(self, other):
+ for name, other_diagnostic in other.items():
+ if name not in self:
+ self[name] = other_diagnostic
+ continue
+ my_diagnostic = self[name]
+ if my_diagnostic.CanAddDiagnostic(other_diagnostic):
+ my_diagnostic.AddDiagnostic(other_diagnostic)
+ continue
+ self[name] = unmergeable_diagnostic_set.UnmergeableDiagnosticSet([
+ my_diagnostic, other_diagnostic])
+
+
+MAX_DIAGNOSTIC_MAPS = 16
+
+
+class HistogramBin(object):
+ __slots__ = '_range', '_count', '_diagnostic_maps'
+
+ def __init__(self, rang):
+ self._range = rang
+ self._count = 0
+ self._diagnostic_maps = []
+
+ def AddSample(self, unused_x):
+ self._count += 1
+
+ @property
+ def count(self):
+ return self._count
+
+ @property
+ def range(self):
+ return self._range
+
+ def AddBin(self, other):
+ self._count += other.count
+
+ @property
+ def diagnostic_maps(self):
+ return self._diagnostic_maps
+
+ def AddDiagnosticMap(self, diagnostics):
+ UniformlySampleStream(
+ self._diagnostic_maps, self.count, diagnostics, MAX_DIAGNOSTIC_MAPS)
+
+ def FromDict(self, dct):
+ self._count = dct[0]
+ if len(dct) > 1:
+ for diagnostic_map_dict in dct[1]:
+ self._diagnostic_maps.append(DiagnosticMap.FromDict(
+ diagnostic_map_dict))
+
+ def AsDict(self):
+ if len(self._diagnostic_maps) == 0:
+ return [self.count]
+ return [self.count, [d.AsDict() for d in self._diagnostic_maps]]
+
+
+# TODO(#3814) Presubmit to compare with unit.html.
+UNIT_NAMES = [
+ 'ms',
+ 'msBestFitFormat',
+ 'tsMs',
+ 'n%',
+ 'sizeInBytes',
+ 'bytesPerSecond',
+ 'J', # Joule
+ 'W', # Watt
+ 'A', # Ampere
+ 'V', # Volt
+ 'Hz', # Hertz
+ 'unitless',
+ 'count',
+ 'sigma',
+]
+
+def ExtendUnitNames():
+ # Use a function in order to avoid cluttering the global namespace with a loop
+ # variable.
+ for name in list(UNIT_NAMES):
+ UNIT_NAMES.append(name + '_biggerIsBetter')
+ UNIT_NAMES.append(name + '_smallerIsBetter')
+
+ExtendUnitNames()
+
+
+class Scalar(object):
+ __slots__ = '_unit', '_value'
+
+ def __init__(self, unit, value):
+ assert unit in UNIT_NAMES, (
+ 'Unrecognized unit "%r"' % unit)
+ self._unit = unit
+ self._value = value
+
+ @property
+ def unit(self):
+ return self._unit
+
+ @property
+ def value(self):
+ return self._value
+
+ def AsDict(self):
+ return {'type': 'scalar', 'unit': self.unit, 'value': self.value}
+
+ @staticmethod
+ def FromDict(dct):
+ return Scalar(dct['unit'], dct['value'])
+
+
+DEFAULT_SUMMARY_OPTIONS = {
+ 'avg': True,
+ 'geometricMean': False,
+ 'std': True,
+ 'count': True,
+ 'sum': True,
+ 'min': True,
+ 'max': True,
+ 'nans': False,
+ # Don't include 'percentile' here. Its default value is [], which is
+ # modifiable. Callers may push to it, so there must be a different Array
+ # instance for each Histogram instance.
+}
+
+
+class Histogram(object):
+ __slots__ = (
+ '_bin_boundaries_dict',
+ '_description',
+ '_name',
+ '_diagnostics',
+ '_nan_diagnostic_maps',
+ '_num_nans',
+ '_running',
+ '_sample_values',
+ '_summary_options',
+ '_unit',
+ '_bins',
+ '_max_num_sample_values')
+
+ def __init__(self, name, unit, bin_boundaries=None):
+ assert unit in UNIT_NAMES, (
+ 'Unrecognized unit "%r"' % unit)
+
+ if bin_boundaries is None:
+ base_unit = unit.split('_')[0]
+ bin_boundaries = DEFAULT_BOUNDARIES_FOR_UNIT[base_unit]
+
+ # Serialize bin boundaries here instead of holding a reference to it in case
+ # it is modified.
+ self._bin_boundaries_dict = bin_boundaries.AsDict()
+
+ # HistogramBinBoundaries creates empty HistogramBins. Save memory by sharing
+ # those empty HistogramBin instances with other Histograms. Wait to copy
+ # HistogramBins until we need to modify it (copy-on-write).
+ self._bins = list(bin_boundaries.bins)
+ self._description = ''
+ self._name = name
+ self._diagnostics = DiagnosticMap()
+ self._diagnostics.DisallowReservedNames()
+ self._nan_diagnostic_maps = []
+ self._num_nans = 0
+ self._running = None
+ self._sample_values = []
+ self._summary_options = dict(DEFAULT_SUMMARY_OPTIONS)
+ self._summary_options['percentile'] = []
+ self._unit = unit
+
+ self._max_num_sample_values = self._GetDefaultMaxNumSampleValues()
+
+ @property
+ def nan_diagnostic_maps(self):
+ return self._nan_diagnostic_maps
+
+ @property
+ def unit(self):
+ return self._unit
+
+ @property
+ def running(self):
+ return self._running
+
+ @property
+ def max_num_sample_values(self):
+ return self._max_num_sample_values
+
+ @max_num_sample_values.setter
+ def max_num_sample_values(self, n):
+ self._max_num_sample_values = n
+ UniformlySampleArray(self._sample_values, self._max_num_sample_values)
+
+ @property
+ def sample_values(self):
+ return self._sample_values
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def bins(self):
+ return self._bins
+
+ @property
+ def diagnostics(self):
+ return self._diagnostics
+
+ @staticmethod
+ def FromDict(dct):
+ boundaries = HistogramBinBoundaries.FromDict(dct.get('binBoundaries'))
+ hist = Histogram(dct['name'], dct['unit'], boundaries)
+ if 'description' in dct:
+ hist._description = dct['description']
+ if 'diagnostics' in dct:
+ hist._diagnostics.AddDicts(dct['diagnostics'])
+ if 'allBins' in dct:
+ if isinstance(dct['allBins'], list):
+ for i, bin_dct in enumerate(dct['allBins']):
+ # Copy HistogramBin on write, share the rest with the other
+ # Histograms that use the same HistogramBinBoundaries.
+ hist._bins[i] = HistogramBin(hist._bins[i].range)
+ hist._bins[i].FromDict(bin_dct)
+ else:
+ for i, bin_dct in dct['allBins'].items():
+ i = int(i)
+ hist._bins[i] = HistogramBin(hist._bins[i].range)
+ hist._bins[i].FromDict(bin_dct)
+ if 'running' in dct:
+ hist._running = RunningStatistics.FromDict(dct['running'])
+ if 'summaryOptions' in dct:
+ hist.CustomizeSummaryOptions(dct['summaryOptions'])
+ if 'maxNumSampleValues' in dct:
+ hist._max_num_sample_values = dct['maxNumSampleValues']
+ if 'sampleValues' in dct:
+ hist._sample_values = dct['sampleValues']
+ if 'numNans' in dct:
+ hist._num_nans = dct['numNans']
+ if 'nanDiagnostics' in dct:
+ for map_dct in dct['nanDiagnostics']:
+ hist._nan_diagnostic_maps.append(DiagnosticMap.FromDict(map_dct))
+ return hist
+
+ @property
+ def num_values(self):
+ if self._running is None:
+ return 0
+ return self._running.count
+
+ @property
+ def num_nans(self):
+ return self._num_nans
+
+ @property
+ def average(self):
+ if self._running is None:
+ return None
+ return self._running.mean
+
+ @property
+ def standard_deviation(self):
+ if self._running is None:
+ return None
+ return self._running.stddev
+
+ @property
+ def geometric_mean(self):
+ if self._running is None:
+ return 0
+ return self._running.geometric_mean
+
+ @property
+ def sum(self):
+ if self._running is None:
+ return 0
+ return self._running.sum
+
+ def GetApproximatePercentile(self, percent):
+ if percent < 0 or percent > 1:
+ raise ValueError('percent must be in [0,1]')
+ if self.num_values == 0:
+ return 0
+
+ if len(self._bins) == 1:
+ sorted_sample_values = list(self._sample_values)
+ sorted_sample_values.sort()
+ return sorted_sample_values[
+ int((len(sorted_sample_values) - 1) * percent)]
+
+ values_to_skip = math.floor((self.num_values - 1) * percent)
+ for hbin in self._bins:
+ values_to_skip -= hbin.count
+ if values_to_skip >= 0:
+ continue
+ if hbin.range.min == -JS_MAX_VALUE:
+ return hbin.range.max
+ elif hbin.range.max == JS_MAX_VALUE:
+ return hbin.range.min
+ else:
+ return hbin.range.center
+ return self._bins[len(self._bins) - 1].range.min
+
+ def GetBinIndexForValue(self, value):
+ index = FindHighIndexInSortedArray(
+ self._bins, lambda b: (-1 if (value < b.range.max) else 1))
+ if 0 <= index < len(self._bins):
+ return index
+ return len(self._bins) - 1
+
+ def GetBinForValue(self, value):
+ return self._bins[self.GetBinIndexForValue(value)]
+
+ def AddSample(self, value, diagnostic_map=None):
+ if (diagnostic_map is not None and
+ not isinstance(diagnostic_map, DiagnosticMap)):
+ diagnostic_map = DiagnosticMap(diagnostic_map)
+
+ if not isinstance(value, numbers.Number) or math.isnan(value):
+ self._num_nans += 1
+ if diagnostic_map:
+ UniformlySampleStream(self._nan_diagnostic_maps, self.num_nans,
+ diagnostic_map, MAX_DIAGNOSTIC_MAPS)
+ else:
+ if self._running is None:
+ self._running = RunningStatistics()
+ self._running.Add(value)
+
+ bin_index = self.GetBinIndexForValue(value)
+ hbin = self._bins[bin_index]
+ if hbin.count == 0:
+ hbin = HistogramBin(hbin.range)
+ self._bins[bin_index] = hbin
+ hbin.AddSample(value)
+ if diagnostic_map:
+ hbin.AddDiagnosticMap(diagnostic_map)
+
+ UniformlySampleStream(self._sample_values, self.num_values + self.num_nans,
+ value, self.max_num_sample_values)
+
+ def CanAddHistogram(self, other):
+ if self.unit != other.unit:
+ return False
+ return self._bin_boundaries_dict == other._bin_boundaries_dict
+
+ def AddHistogram(self, other):
+ if not self.CanAddHistogram(other):
+ raise ValueError('Merging incompatible Histograms')
+
+ MergeSampledStreams(
+ self.sample_values, self.num_values,
+ other.sample_values, other.num_values,
+ (self.max_num_sample_values + other.max_num_sample_values) / 2)
+ self._num_nans += other._num_nans
+
+ if other.running is not None:
+ if self.running is None:
+ self._running = RunningStatistics()
+ self._running = self._running.Merge(other.running)
+
+ for i, hbin in enumerate(other.bins):
+ mybin = self._bins[i]
+ if mybin.count == 0:
+ self._bins[i] = mybin = HistogramBin(mybin.range)
+ mybin.AddBin(hbin)
+
+ self.diagnostics.Merge(other.diagnostics)
+
+ def CustomizeSummaryOptions(self, options):
+ for key, value in options.items():
+ self._summary_options[key] = value
+
+ def Clone(self):
+ return Histogram.FromDict(self.AsDict())
+
+ def CloneEmpty(self):
+ return Histogram(self.name, self.unit, HistogramBinBoundaries.FromDict(
+ self._bin_boundaries_dict))
+
+ @property
+ def statistics_scalars(self):
+ results = {}
+ for stat_name, option in self._summary_options.items():
+ if not option:
+ continue
+ if stat_name == 'percentile':
+ for percent in option:
+ percentile = self.GetApproximatePercentile(percent)
+ results['pct_' + PercentToString(percent)] = Scalar(
+ self.unit, percentile)
+ elif stat_name == 'nans':
+ results['nans'] = Scalar('count', self.num_nans)
+ else:
+ if stat_name == 'count':
+ stat_unit = 'count'
+ else:
+ stat_unit = self.unit
+ if stat_name == 'std':
+ key = 'stddev'
+ elif stat_name == 'avg':
+ key = 'mean'
+ elif stat_name == 'geometricMean':
+ key = 'geometric_mean'
+ else:
+ key = stat_name
+ if self._running is None:
+ self._running = RunningStatistics()
+ stat_value = getattr(self._running, key)
+ if isinstance(stat_value, numbers.Number):
+ results[stat_name] = Scalar(stat_unit, stat_value)
+ return results
+
+ def AsDict(self):
+ dct = {'name': self.name, 'unit': self.unit}
+ if self._bin_boundaries_dict is not None:
+ dct['binBoundaries'] = self._bin_boundaries_dict
+ if self._description:
+ dct['description'] = self._description
+ if len(self.diagnostics):
+ dct['diagnostics'] = self.diagnostics.AsDict()
+ if self.max_num_sample_values != self._GetDefaultMaxNumSampleValues():
+ dct['maxNumSampleValues'] = self.max_num_sample_values
+ if self.num_nans:
+ dct['numNans'] = self.num_nans
+ if len(self.nan_diagnostic_maps):
+ dct['nanDiagnostics'] = [m.AsDict() for m in self.nan_diagnostic_maps]
+ if self.num_values:
+ dct['sampleValues'] = list(self.sample_values)
+ dct['running'] = self._running.AsDict()
+ dct['allBins'] = self._GetAllBinsAsDict()
+ if dct['allBins'] is None:
+ del dct['allBins']
+
+ summary_options = {}
+ any_overridden_summary_options = False
+ for name, option in self._summary_options.items():
+ if name == 'percentile':
+ if len(option) == 0:
+ continue
+ elif option == DEFAULT_SUMMARY_OPTIONS[name]:
+ continue
+ summary_options[name] = option
+ any_overridden_summary_options = True
+ if any_overridden_summary_options:
+ dct['summaryOptions'] = summary_options
+ return dct
+
+ def _GetAllBinsAsDict(self):
+ num_bins = len(self._bins)
+ empty_bins = 0
+ for hbin in self._bins:
+ if hbin.count == 0:
+ empty_bins += 1
+ if empty_bins == num_bins:
+ return None
+
+ if empty_bins > (num_bins / 2):
+ all_bins_dict = {}
+ for i, hbin in enumerate(self._bins):
+ if hbin.count > 0:
+ all_bins_dict[i] = hbin.AsDict()
+ return all_bins_dict
+
+ all_bins_list = []
+ for hbin in self._bins:
+ all_bins_list.append(hbin.AsDict())
+ return all_bins_list
+
+ def _GetDefaultMaxNumSampleValues(self):
+ return len(self._bins) * 10
+
+
+class HistogramBinBoundaries(object):
+ __slots__ = '_builder', '_range', '_bin_ranges', '_bins'
+
+ CACHE = {}
+ SLICE_TYPE_LINEAR = 0
+ SLICE_TYPE_EXPONENTIAL = 1
+
+ def __init__(self, min_bin_boundary):
+ self._builder = [min_bin_boundary]
+ self._range = Range()
+ self._range.AddValue(min_bin_boundary)
+ self._bin_ranges = None
+ self._bins = None
+
+ @property
+ def range(self):
+ return self._range
+
+ @staticmethod
+ def FromDict(dct):
+ if dct is None:
+ return HistogramBinBoundaries.SINGULAR
+
+ cache_key = json.dumps(dct)
+ if cache_key in HistogramBinBoundaries.CACHE:
+ return HistogramBinBoundaries.CACHE[cache_key]
+
+ bin_boundaries = HistogramBinBoundaries(dct[0])
+ for slic in dct[1:]:
+ if not isinstance(slic, list):
+ bin_boundaries.AddBinBoundary(slic)
+ continue
+ if slic[0] == HistogramBinBoundaries.SLICE_TYPE_LINEAR:
+ bin_boundaries.AddLinearBins(slic[1], slic[2])
+ elif slic[0] == HistogramBinBoundaries.SLICE_TYPE_EXPONENTIAL:
+ bin_boundaries.AddExponentialBins(slic[1], slic[2])
+ else:
+ raise ValueError('Unrecognized HistogramBinBoundaries slice type')
+
+ HistogramBinBoundaries.CACHE[cache_key] = bin_boundaries
+ return bin_boundaries
+
+ def AsDict(self):
+ if len(self._builder) == 1 and self._builder[0] == JS_MAX_VALUE:
+ return None
+ return self._builder
+
+ @staticmethod
+ def CreateExponential(lower, upper, num_bins):
+ return HistogramBinBoundaries(lower).AddExponentialBins(upper, num_bins)
+
+ @staticmethod
+ def CreateLinear(lower, upper, num_bins):
+ return HistogramBinBoundaries(lower).AddLinearBins(upper, num_bins)
+
+ def _PushBuilderSlice(self, slic):
+ self._builder += [slic]
+
+ def AddBinBoundary(self, next_max_bin_boundary):
+ if next_max_bin_boundary <= self.range.max:
+ raise ValueError('The added max bin boundary must be larger than ' +
+ 'the current max boundary')
+
+ self._bin_ranges = None
+ self._bins = None
+
+ self._PushBuilderSlice(next_max_bin_boundary)
+ self.range.AddValue(next_max_bin_boundary)
+ return self
+
+ def AddLinearBins(self, next_max_bin_boundary, bin_count):
+ if bin_count <= 0:
+ raise ValueError('Bin count must be positive')
+ if next_max_bin_boundary <= self.range.max:
+ raise ValueError('The new max bin boundary must be greater than ' +
+ 'the previous max bin boundary')
+
+ self._bin_ranges = None
+ self._bins = None
+
+ self._PushBuilderSlice([
+ HistogramBinBoundaries.SLICE_TYPE_LINEAR,
+ next_max_bin_boundary, bin_count])
+ self.range.AddValue(next_max_bin_boundary)
+ return self
+
+ def AddExponentialBins(self, next_max_bin_boundary, bin_count):
+ if bin_count <= 0:
+ raise ValueError('Bin count must be positive')
+ if self.range.max <= 0:
+ raise ValueError('Current max bin boundary must be positive')
+ if self.range.max >= next_max_bin_boundary:
+ raise ValueError('The last added max boundary must be greater than ' +
+ 'the current max boundary boundary')
+
+ self._bin_ranges = None
+ self._bins = None
+
+ self._PushBuilderSlice([
+ HistogramBinBoundaries.SLICE_TYPE_EXPONENTIAL,
+ next_max_bin_boundary, bin_count])
+ self.range.AddValue(next_max_bin_boundary)
+ return self
+
+ @property
+ def bins(self):
+ if self._bins is None:
+ self._BuildBins()
+ return self._bins
+
+ def _BuildBins(self):
+ self._bins = [HistogramBin(r) for r in self.bin_ranges]
+
+ @property
+ def bin_ranges(self):
+ if self._bin_ranges is None:
+ self._BuildBinRanges()
+ return self._bin_ranges
+
+ def _BuildBinRanges(self):
+ if not isinstance(self._builder[0], numbers.Number):
+ raise ValueError('Invalid start of builder_')
+
+ self._bin_ranges = []
+ prev_boundary = self._builder[0]
+ if prev_boundary > -JS_MAX_VALUE:
+ # underflow bin
+ self._bin_ranges.append(Range.FromExplicitRange(
+ -JS_MAX_VALUE, prev_boundary))
+
+ for slic in self._builder[1:]:
+ if not isinstance(slic, list):
+ self._bin_ranges.append(Range.FromExplicitRange(
+ prev_boundary, slic))
+ prev_boundary = slic
+ continue
+
+ next_max_bin_boundary = float(slic[1])
+ bin_count = slic[2]
+ slice_min_bin_boundary = float(prev_boundary)
+
+ if slic[0] == self.SLICE_TYPE_LINEAR:
+ bin_width = (next_max_bin_boundary - prev_boundary) / bin_count
+ for i in range(1, bin_count):
+ boundary = slice_min_bin_boundary + (i * bin_width)
+ self._bin_ranges.append(Range.FromExplicitRange(
+ prev_boundary, boundary))
+ prev_boundary = boundary
+ elif slic[0] == self.SLICE_TYPE_EXPONENTIAL:
+ bin_exponent_width = (
+ math.log(next_max_bin_boundary / prev_boundary) / bin_count)
+ for i in range(1, bin_count):
+ boundary = slice_min_bin_boundary * math.exp(i * bin_exponent_width)
+ self._bin_ranges.append(Range.FromExplicitRange(
+ prev_boundary, boundary))
+ prev_boundary = boundary
+ else:
+ raise ValueError('Unrecognized HistogramBinBoundaries slice type')
+
+ self._bin_ranges.append(Range.FromExplicitRange(
+ prev_boundary, next_max_bin_boundary))
+ prev_boundary = next_max_bin_boundary
+
+ if prev_boundary < JS_MAX_VALUE:
+ # overflow bin
+ self._bin_ranges.append(Range.FromExplicitRange(
+ prev_boundary, JS_MAX_VALUE))
+
+
+HistogramBinBoundaries.SINGULAR = HistogramBinBoundaries(JS_MAX_VALUE)
+
+
+# The JS version computes these values using tr.b.convertUnit, which is
+# not implemented in Python, so we write them out here.
+def _CreateMsAutoFormatBins():
+ bins = [
+ 2000,
+ 5000,
+ 10000,
+ 30000,
+ 60000,
+ 120000,
+ 300000,
+ 600000,
+ 1800000,
+ 3600000,
+ 7200000,
+ 21600000,
+ 43200000,
+ 86400000,
+ 604800000,
+ 2629743840,
+ 31556926080
+ ]
+
+ boundaries = HistogramBinBoundaries(0).AddBinBoundary(1).AddExponentialBins(
+ 1e3, 3)
+
+ for b in bins:
+ boundaries.AddBinBoundary(b)
+
+ return boundaries
+
+
+DEFAULT_BOUNDARIES_FOR_UNIT = {
+ 'ms': HistogramBinBoundaries.CreateExponential(1e-3, 1e6, 100),
+ 'tsMs': HistogramBinBoundaries.CreateLinear(0, 1e10, 1000),
+ 'msBestFitFormat': _CreateMsAutoFormatBins(),
+ 'n%': HistogramBinBoundaries.CreateLinear(0, 1.0, 20),
+ 'sizeInBytes': HistogramBinBoundaries.CreateExponential(1, 1e12, 100),
+ 'bytesPerSecond': HistogramBinBoundaries.CreateExponential(1, 1e12, 100),
+ 'J': HistogramBinBoundaries.CreateExponential(1e-3, 1e3, 50),
+ 'W': HistogramBinBoundaries.CreateExponential(1e-3, 1, 50),
+ 'A': HistogramBinBoundaries.CreateExponential(1e-3, 1, 50),
+ 'V': HistogramBinBoundaries.CreateExponential(1e-3, 1, 50),
+ 'Hz': HistogramBinBoundaries.CreateExponential(1e-3, 1, 50),
+ 'unitless': HistogramBinBoundaries.CreateExponential(1e-3, 1e3, 50),
+ 'count': HistogramBinBoundaries.CreateExponential(1, 1e3, 20),
+ 'sigma': HistogramBinBoundaries.CreateLinear(-5, 5, 50),
+}
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping.html
new file mode 100644
index 00000000000..9a61aa19510
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping.html
@@ -0,0 +1,204 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v', function() {
+ /*
+ * HistogramGrouping objects are registered named functions that map from
+ * Histogram objects to strings.
+ *
+ * They are used to group Histograms by
+ * tr.v.HistogramSet.groupHistogramsRecursively()
+ *
+ * The tr-ui-b-grouping-table-groupby-picker module within the
+ * tr-v-ui-histogram-set-controls module allows users to select and reorder
+ * groupings.
+ */
+ class HistogramGrouping {
+ /**
+ * @param {string} key
+ * @param {!function(!tr.v.Histogram):string} callback
+ */
+ constructor(key, callback) {
+ this.key_ = key;
+ this.callback_ = callback;
+
+ HistogramGrouping.BY_KEY.set(key, this);
+ }
+
+ get key() {
+ return this.key_;
+ }
+
+ get callback() {
+ return this.callback_;
+ }
+
+ get label() {
+ return this.key;
+ }
+
+ /**
+ * @param {!Set.<string>} tags
+ * @param {string} diagnosticName
+ * @return {!Array.<!HistogramGrouping>}
+ */
+ static buildFromTags(tags, diagnosticName) {
+ const booleanTags = new Set();
+ const keyValueTags = new Set();
+ for (const tag of tags) {
+ if (tag.includes(':')) {
+ const key = tag.split(':')[0];
+ if (booleanTags.has(key)) {
+ throw new Error(
+ `Tag "${key}" cannot be both boolean and key-value`);
+ }
+ keyValueTags.add(key);
+ } else {
+ if (keyValueTags.has(tag)) {
+ throw new Error(
+ `Tag "${tag}" cannot be both boolean and key-value`);
+ }
+ booleanTags.add(tag);
+ }
+ }
+
+ const groupings = [];
+ for (const tag of booleanTags) {
+ groupings.push(HistogramGrouping.buildBooleanTagGrouping_(
+ tag, diagnosticName));
+ }
+ for (const tag of keyValueTags) {
+ groupings.push(HistogramGrouping.buildKeyValueTagGrouping_(
+ tag, diagnosticName));
+ }
+ return groupings;
+ }
+
+ static buildBooleanTagGrouping_(tag, diagnosticName) {
+ return new HistogramGrouping(`${tag}Tag`, h => {
+ const tags = h.diagnostics.get(diagnosticName);
+ if (tags === undefined || !tags.has(tag)) return `~${tag}`;
+ return tag;
+ });
+ }
+
+ static buildKeyValueTagGrouping_(tag, diagnosticName) {
+ return new HistogramGrouping(`${tag}Tag`, h => {
+ const tags = h.diagnostics.get(diagnosticName);
+ if (tags === undefined) return `~${tag}`;
+ const values = new Set();
+ for (const value of tags) {
+ const kvp = value.split(':');
+ if (kvp.length < 2 || kvp[0] !== tag) continue;
+ values.add(kvp[1]);
+ }
+ if (values.size === 0) return `~${tag}`;
+ const sortedValues = Array.from(values);
+ sortedValues.sort();
+ return sortedValues.join(',');
+ }, `${tag} tag`);
+ }
+ }
+
+ HistogramGrouping.BY_KEY = new Map();
+
+ HistogramGrouping.HISTOGRAM_NAME = new HistogramGrouping('name', h => h.name);
+
+ HistogramGrouping.DISPLAY_LABEL = new HistogramGrouping(
+ 'displayLabel', hist => {
+ const labels = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.LABELS);
+ if (labels !== undefined && labels.size > 0) {
+ return Array.from(labels).join(',');
+ }
+
+ const benchmarks = hist.diagnostics.get(
+ tr.v.d.RESERVED_NAMES.BENCHMARKS);
+ const start = hist.diagnostics.get(
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START);
+ if (benchmarks === undefined) {
+ if (start === undefined) return 'Value';
+
+ return start.toString();
+ }
+ const benchmarksStr = Array.from(benchmarks).join('\n');
+
+ if (start === undefined) return benchmarksStr;
+
+ return benchmarksStr + '\n' + start.toString();
+ });
+
+ class GenericSetGrouping extends HistogramGrouping {
+ constructor(name) {
+ super(name, undefined);
+ this.callback_ = this.compute_.bind(this);
+ }
+
+ compute_(hist) {
+ const diag = hist.diagnostics.get(this.key);
+ if (diag === undefined) return '';
+ const parts = Array.from(diag);
+ parts.sort();
+ return parts.join(',');
+ }
+ }
+
+ GenericSetGrouping.NAMES = [
+ tr.v.d.RESERVED_NAMES.ARCHITECTURES,
+ tr.v.d.RESERVED_NAMES.BENCHMARKS,
+ tr.v.d.RESERVED_NAMES.BOTS,
+ tr.v.d.RESERVED_NAMES.BUILDS,
+ tr.v.d.RESERVED_NAMES.DEVICE_IDS,
+ tr.v.d.RESERVED_NAMES.MASTERS,
+ tr.v.d.RESERVED_NAMES.MEMORY_AMOUNTS,
+ tr.v.d.RESERVED_NAMES.OS_NAMES,
+ tr.v.d.RESERVED_NAMES.OS_VERSIONS,
+ tr.v.d.RESERVED_NAMES.PRODUCT_VERSIONS,
+ tr.v.d.RESERVED_NAMES.STORIES,
+ tr.v.d.RESERVED_NAMES.STORYSET_REPEATS,
+ tr.v.d.RESERVED_NAMES.STORY_TAGS,
+ tr.v.d.RESERVED_NAMES.TEST_PATH,
+ ];
+
+ for (const name of GenericSetGrouping.NAMES) {
+ // Instantiating a HistogramGrouping adds it to BY_KEY.
+ new GenericSetGrouping(name);
+ }
+
+ class DateRangeGrouping extends HistogramGrouping {
+ constructor(name) {
+ super(name, undefined);
+ this.callback_ = this.compute_.bind(this);
+ }
+
+ compute_(hist) {
+ const diag = hist.diagnostics.get(this.key);
+ if (diag === undefined) return '';
+ return diag.toString();
+ }
+ }
+
+ DateRangeGrouping.NAMES = [
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ tr.v.d.RESERVED_NAMES.TRACE_START,
+ ];
+
+ for (const name of DateRangeGrouping.NAMES) {
+ new DateRangeGrouping(name);
+ }
+
+ return {
+ HistogramGrouping,
+ GenericSetGrouping,
+ DateRangeGrouping,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping.py
new file mode 100644
index 00000000000..49eab313d49
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping.py
@@ -0,0 +1,161 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from tracing.value.diagnostics import reserved_infos
+
+
+GROUPINGS_BY_KEY = {}
+
+
+class HistogramGrouping(object):
+ """This class wraps a registered function that maps from a Histogram to a
+ string or number in order to allow grouping together Histograms that produce
+ the same string or number. HistogramGroupings may be looked up by key in
+ GROUPINGS_BY_KEY.
+ """
+
+ def __init__(self, key, callback):
+ self._key = key
+ self._callback = callback
+ GROUPINGS_BY_KEY[key] = self
+
+ @property
+ def key(self):
+ return self._key
+
+ @property
+ def callback(self):
+ return self._callback
+
+
+def BuildFromTags(tags, diagnostic_name):
+ """Builds HistogramGroupings from a set of tags.
+
+ Builds one HistogramGrouping for each tag in tags. The HistogramGroupings wrap
+ functions (callback) that get the named diagnostic from the given Histogram.
+ If the named diagnostic is found, it is assumed to be a GenericSet containing
+ strings. The HistogramGrouping callback returns a string indicating whether
+ the tag is in the GenericSet, and, if it is a key-value tag, what its values
+ are.
+
+ Args:
+ tags: set of strings
+ diagnostic_name: string, e.g. reserved_infos.STORY_TAGS.name
+
+ Returns:
+ list of HistogramGrouping
+ """
+ boolean_tags = set()
+ key_value_tags = set()
+ for tag in tags:
+ if ':' in tag:
+ key = tag.split(':')[0]
+ assert key not in boolean_tags, key
+ key_value_tags.add(key)
+ else:
+ assert tag not in key_value_tags, tag
+ boolean_tags.add(tag)
+ groupings = [
+ _BuildBooleanTagGrouping(tag, diagnostic_name) for tag in boolean_tags]
+ groupings += [
+ _BuildKeyValueTagGrouping(key, diagnostic_name) for key in key_value_tags]
+ return groupings
+
+
+def _BuildBooleanTagGrouping(tag, diagnostic_name):
+ def Closure(hist):
+ tags = hist.diagnostics.get(diagnostic_name)
+ if not tags or tag not in tags:
+ return '~' + tag
+ return tag
+ return HistogramGrouping(tag + 'Tag', Closure)
+
+
+def _BuildKeyValueTagGrouping(key, diagnostic_name):
+ def Closure(hist):
+ tags = hist.diagnostics.get(diagnostic_name)
+ if not tags:
+ return '~' + key
+ values = set()
+ for tag in tags:
+ kvp = tag.split(':')
+ if len(kvp) < 2 or kvp[0] != key:
+ continue
+ values.add(kvp[1])
+ if len(values) == 0:
+ return '~' + key
+ return ','.join(sorted(values))
+ return HistogramGrouping(key + 'Tag', Closure)
+
+
+HISTOGRAM_NAME = HistogramGrouping('name', lambda h: h.name)
+
+
+def _DisplayLabel(hist):
+ labels = hist.diagnostics.get(reserved_infos.LABELS.name)
+ if labels and len(labels):
+ return ','.join(sorted(labels))
+
+ benchmarks = hist.diagnostics.get(reserved_infos.BENCHMARKS.name)
+ start = hist.diagnostics.get(reserved_infos.BENCHMARK_START.name)
+ if not benchmarks:
+ if not start:
+ return 'Value'
+ return str(start)
+ benchmarks = '\n'.join(benchmarks)
+ if not start:
+ return benchmarks
+ return benchmarks + '\n' + str(start)
+
+
+DISPLAY_LABEL = HistogramGrouping('displayLabel', _DisplayLabel)
+
+
+class GenericSetGrouping(HistogramGrouping):
+ """Wraps a function that looks up and formats a GenericSet by name from a
+ Histogram.
+ """
+
+ def __init__(self, name):
+ super(GenericSetGrouping, self).__init__(name, self._Compute)
+
+ def _Compute(self, hist):
+ diag = hist.diagnostics.get(self.key)
+ if not diag:
+ return ''
+ return ','.join(str(elem) for elem in sorted(diag))
+
+
+GenericSetGrouping(reserved_infos.ARCHITECTURES.name)
+GenericSetGrouping(reserved_infos.BENCHMARKS.name)
+GenericSetGrouping(reserved_infos.BOTS.name)
+GenericSetGrouping(reserved_infos.BUILDS.name)
+GenericSetGrouping(reserved_infos.DEVICE_IDS.name)
+GenericSetGrouping(reserved_infos.MASTERS.name)
+GenericSetGrouping(reserved_infos.MEMORY_AMOUNTS.name)
+GenericSetGrouping(reserved_infos.OS_NAMES.name)
+GenericSetGrouping(reserved_infos.OS_VERSIONS.name)
+GenericSetGrouping(reserved_infos.PRODUCT_VERSIONS.name)
+GenericSetGrouping(reserved_infos.STORIES.name)
+GenericSetGrouping(reserved_infos.STORYSET_REPEATS.name)
+GenericSetGrouping(reserved_infos.STORY_TAGS.name)
+
+
+class DateRangeGrouping(HistogramGrouping):
+ """Wraps a function that looks up and formats a DateRange by name from a
+ Histogram.
+ """
+
+ def __init__(self, name):
+ super(DateRangeGrouping, self).__init__(name, self._Compute)
+
+ def _Compute(self, hist):
+ diag = hist.diagnostics.get(self.key)
+ if not diag:
+ return ''
+ return str(diag)
+
+
+DateRangeGrouping(reserved_infos.BENCHMARK_START.name)
+DateRangeGrouping(reserved_infos.TRACE_START.name)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping_test.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping_test.html
new file mode 100644
index 00000000000..622313b54b0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping_test.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram_grouping.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('booleanTags', function() {
+ const aHist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(
+ ['video', 'audio']),
+ ]]),
+ });
+ const bHist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(['audio']),
+ ]]),
+ });
+ const cHist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(['video']),
+ ]]),
+ });
+ const dHist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet([]),
+ ]]),
+ });
+
+ const groupings = tr.v.HistogramGrouping.buildFromTags(
+ ['video', 'audio'], tr.v.d.RESERVED_NAMES.STORY_TAGS);
+ assert.lengthOf(groupings, 2);
+ assert.strictEqual(groupings[0].key, 'videoTag');
+ assert.strictEqual(groupings[1].key, 'audioTag');
+ assert.strictEqual(groupings[0].callback(aHist), 'video');
+ assert.strictEqual(groupings[0].callback(bHist), '~video');
+ assert.strictEqual(groupings[0].callback(cHist), 'video');
+ assert.strictEqual(groupings[0].callback(dHist), '~video');
+ assert.strictEqual(groupings[1].callback(aHist), 'audio');
+ assert.strictEqual(groupings[1].callback(bHist), 'audio');
+ assert.strictEqual(groupings[1].callback(cHist), '~audio');
+ assert.strictEqual(groupings[1].callback(dHist), '~audio');
+ });
+
+ test('keyValueTags', function() {
+ const aHist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(['case:load']),
+ ]]),
+ });
+ const bHist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(
+ ['case:browse']),
+ ]]),
+ });
+ const cHist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet([]),
+ ]]),
+ });
+ const dHist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(
+ ['case:load', 'case:browse']),
+ ]]),
+ });
+
+ const groupings = tr.v.HistogramGrouping.buildFromTags(
+ ['case:load', 'case:browse'], tr.v.d.RESERVED_NAMES.STORY_TAGS);
+ assert.lengthOf(groupings, 1);
+ assert.strictEqual(groupings[0].key, 'caseTag');
+ assert.strictEqual(groupings[0].callback(aHist), 'load');
+ assert.strictEqual(groupings[0].callback(bHist), 'browse');
+ assert.strictEqual(groupings[0].callback(cHist), '~case');
+ assert.strictEqual(groupings[0].callback(dHist), 'browse,load');
+ });
+
+ test('histogramNameGrouping', function() {
+ const hist = tr.v.Histogram.create('name', tr.b.Unit.byName.count, []);
+ assert.strictEqual(tr.v.HistogramGrouping.HISTOGRAM_NAME.callback(hist),
+ 'name');
+ });
+
+ test('labelGrouping', function() {
+ const hist = tr.v.Histogram.create('name', tr.b.Unit.byName.count, []);
+ assert.strictEqual(tr.v.HistogramGrouping.DISPLAY_LABEL.callback(hist),
+ 'Value');
+ hist.diagnostics.set(tr.v.d.RESERVED_NAMES.LABELS,
+ new tr.v.d.GenericSet(['H']));
+ assert.strictEqual(tr.v.HistogramGrouping.DISPLAY_LABEL.callback(hist),
+ 'H');
+ });
+
+ test('genericSetGrouping', function() {
+ const grouping = new tr.v.GenericSetGrouping('foo');
+
+ const empty = tr.v.Histogram.create('', tr.b.Unit.byName.count, []);
+ assert.strictEqual(grouping.callback(empty), '');
+
+ const hist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([
+ ['foo', new tr.v.d.GenericSet(['baz', 'bar'])],
+ ]),
+ });
+ assert.strictEqual(grouping.callback(hist), 'bar,baz');
+ });
+
+ test('reservedGenericSetGroupings', function() {
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.ARCHITECTURES), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.BENCHMARKS), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.BOTS), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.BUILDS), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.MASTERS), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.MEMORY_AMOUNTS), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.OS_NAMES), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.OS_VERSIONS), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.PRODUCT_VERSIONS), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORIES), tr.v.GenericSetGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.STORYSET_REPEATS), tr.v.GenericSetGrouping);
+ });
+
+ test('dateRangeGrouping', function() {
+ const grouping = new tr.v.DateRangeGrouping('foo');
+
+ const empty = tr.v.Histogram.create('', tr.b.Unit.byName.count, []);
+ assert.strictEqual(grouping.callback(empty), '');
+
+ const hist = tr.v.Histogram.create('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([
+ ['foo', new tr.v.d.DateRange(15e11)],
+ ]),
+ });
+ assert.strictEqual(grouping.callback(hist),
+ tr.b.formatDate(new Date(15e11)));
+ });
+
+ test('reservedDateRangeGroupings', function() {
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START), tr.v.DateRangeGrouping);
+ assert.instanceOf(tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.TRACE_START), tr.v.DateRangeGrouping);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping_unittest.py
new file mode 100644
index 00000000000..3050121e970
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_grouping_unittest.py
@@ -0,0 +1,127 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value import histogram
+from tracing.value import histogram_grouping
+from tracing.value.diagnostics import date_range
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import reserved_infos
+
+class HistogramGroupingUnittest(unittest.TestCase):
+
+ def testBooleanTags(self):
+ a_hist = histogram.Histogram('', 'count')
+ a_hist.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ ['video', 'audio'])
+ b_hist = histogram.Histogram('', 'count')
+ b_hist.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ ['audio'])
+ c_hist = histogram.Histogram('', 'count')
+ c_hist.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ ['video'])
+ d_hist = histogram.Histogram('', 'count')
+ d_hist.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ [])
+ groupings = histogram_grouping.BuildFromTags(
+ ['audio', 'video'], reserved_infos.STORY_TAGS.name)
+ self.assertEqual(len(groupings), 2)
+ groupings.sort(key=lambda g: g.key)
+ self.assertEqual(groupings[0].key, 'audioTag')
+ self.assertEqual(groupings[1].key, 'videoTag')
+ self.assertEqual(groupings[0].callback(a_hist), 'audio')
+ self.assertEqual(groupings[0].callback(b_hist), 'audio')
+ self.assertEqual(groupings[0].callback(c_hist), '~audio')
+ self.assertEqual(groupings[0].callback(d_hist), '~audio')
+ self.assertEqual(groupings[1].callback(a_hist), 'video')
+ self.assertEqual(groupings[1].callback(b_hist), '~video')
+ self.assertEqual(groupings[1].callback(c_hist), 'video')
+ self.assertEqual(groupings[1].callback(d_hist), '~video')
+
+ def testKeyValueTags(self):
+ a_hist = histogram.Histogram('', 'count')
+ a_hist.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ ['case:load'])
+ b_hist = histogram.Histogram('', 'count')
+ b_hist.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ ['case:browse'])
+ c_hist = histogram.Histogram('', 'count')
+ c_hist.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ [])
+ d_hist = histogram.Histogram('', 'count')
+ d_hist.diagnostics[reserved_infos.STORY_TAGS.name] = generic_set.GenericSet(
+ ['case:load', 'case:browse'])
+ groupings = histogram_grouping.BuildFromTags(
+ ['case:load', 'case:browse'], reserved_infos.STORY_TAGS.name)
+ self.assertEqual(len(groupings), 1)
+ self.assertEqual(groupings[0].key, 'caseTag')
+ self.assertEqual(groupings[0].callback(a_hist), 'load')
+ self.assertEqual(groupings[0].callback(b_hist), 'browse')
+ self.assertEqual(groupings[0].callback(c_hist), '~case')
+ self.assertEqual(groupings[0].callback(d_hist), 'browse,load')
+
+ def testName(self):
+ self.assertEqual(histogram_grouping.HISTOGRAM_NAME.callback(
+ histogram.Histogram('test', 'count')), 'test')
+
+ def testDisplayLabel(self):
+ hist = histogram.Histogram('test', 'count')
+ self.assertEqual(histogram_grouping.DISPLAY_LABEL.callback(hist), 'Value')
+ hist.diagnostics[reserved_infos.LABELS.name] = generic_set.GenericSet(['H'])
+ self.assertEqual(histogram_grouping.DISPLAY_LABEL.callback(hist), 'H')
+
+ def testGenericSet(self):
+ grouping = histogram_grouping.GenericSetGrouping('foo')
+ hist = histogram.Histogram('', 'count')
+ self.assertEqual(grouping.callback(hist), '')
+ hist.diagnostics['foo'] = generic_set.GenericSet(['baz'])
+ self.assertEqual(grouping.callback(hist), 'baz')
+ hist.diagnostics['foo'] = generic_set.GenericSet(['baz', 'bar'])
+ self.assertEqual(grouping.callback(hist), 'bar,baz')
+
+ def testReservedGenericSetGroupings(self):
+ self.assertIsInstance(
+ histogram_grouping.GROUPINGS_BY_KEY[reserved_infos.ARCHITECTURES.name],
+ histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.BENCHMARKS.name], histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.BOTS.name], histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.BUILDS.name], histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.MASTERS.name], histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(
+ histogram_grouping.GROUPINGS_BY_KEY[reserved_infos.MEMORY_AMOUNTS.name],
+ histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.OS_NAMES.name], histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.OS_VERSIONS.name], histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(
+ histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.PRODUCT_VERSIONS.name],
+ histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.STORIES.name], histogram_grouping.GenericSetGrouping)
+ self.assertIsInstance(
+ histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.STORYSET_REPEATS.name],
+ histogram_grouping.GenericSetGrouping)
+
+ def testDateRange(self):
+ grouping = histogram_grouping.DateRangeGrouping('foo')
+ hist = histogram.Histogram('', 'count')
+ self.assertEqual(grouping.callback(hist), '')
+ hist.diagnostics['foo'] = date_range.DateRange(15e11)
+ self.assertEqual(grouping.callback(hist), str(hist.diagnostics['foo']))
+
+ def testReservedDateRangeGroupings(self):
+ self.assertIsInstance(
+ histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.BENCHMARK_START.name],
+ histogram_grouping.DateRangeGrouping)
+ self.assertIsInstance(histogram_grouping.GROUPINGS_BY_KEY[
+ reserved_infos.TRACE_START.name], histogram_grouping.DateRangeGrouping)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html
new file mode 100644
index 00000000000..3a8c3356914
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_importer.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v', function() {
+ class HistogramImporter {
+ /**
+ * @param {!Element} loadingEl
+ */
+ constructor(loadingEl) {
+ this.loadingEl_ = loadingEl;
+ this.histograms_ = undefined;
+ this.string_ = '';
+ this.dataOffset_ = 0;
+ this.view_ = undefined;
+ this.fmpMark_ = tr.b.Timing.mark('HistogramImporter', 'fmp');
+
+ this.loadingEl_.textContent = 'Parsing HTML...';
+ // The json comment appears after this script tag in results.html, so the
+ // browser will parse them into DOM now.
+ }
+
+ /**
+ * @param {string} message
+ * @return {Promise} resolves when |message| is displayed.
+ */
+ async update_(message) {
+ this.loadingEl_.textContent = message;
+ // Use rAF callbacks only if the document is visible. If the document is
+ // hidden, then the user-agent can stop triggering the rAF callbacks. So
+ // avoid rAF callbacks when hidden.
+ if (window.document.visibilityState === 'visible') {
+ await tr.b.animationFrame();
+ }
+ }
+
+ /**
+ * The string contains a list of histograms of the following form:
+ * JSON\n
+ * JSON\n
+ * ...
+ * The |view| should have 'display:none' so that it doesn't obnoxiously
+ * display "zero Histograms" while they are being imported.
+ *
+ * @param {!String} string
+ * @param {!Element} view A histogram-set-view.
+ * @return {Promise} resolves when |view| is displayed.
+ */
+ async importHistograms(string, view) {
+ this.histograms_ = new tr.v.HistogramSet();
+ this.string_ = string;
+ this.view_ = view;
+ tr.b.Timing.instant('HistogramImporter', 'string', this.string_.length);
+
+ if (this.string_.length > 0) {
+ await this.update_('Loading Histogram 0');
+ const loadMark = tr.b.Timing.mark(
+ 'HistogramImporter', 'loadHistograms');
+ if (!this.findDataStart_()) return;
+ await this.loadSomeHistograms_();
+ loadMark.end();
+ tr.b.Timing.instant('HistogramImporter', 'nsPerJson',
+ parseInt(1e3 * loadMark.durationMs / this.histograms_.length));
+ }
+
+ await this.update_('Displaying Histogram table...');
+ await this.displayHistograms_();
+ }
+
+ findDataStart_() {
+ // Find the initial data start.
+ this.dataOffset_ = this.string_.indexOf('\n', this.dataOffset_);
+ if (this.dataOffset_ < 0) return false;
+ // Skip over newline character.
+ this.dataOffset_++;
+ return true;
+ }
+
+ async loadSomeHistograms_() {
+ // Don't spend so long on this chunk of Histograms that the user gets
+ // frustrated, but also don't call requestAnimationFrame faster than every
+ // 16ms, so that the browser doesn't have to wait for the next vsync.
+ // Powerful computers can load several hundred Histograms in 32ms.
+ // Also don't call performance.now() more often than necessary.
+ const startTime = performance.now();
+ do {
+ for (let i = 0; i < 100; i++) {
+ const endIndex = this.string_.indexOf('\n', this.dataOffset_);
+ if (endIndex < 0) return;
+ const json = this.string_.substring(this.dataOffset_, endIndex);
+ const dict = JSON.parse(json);
+ this.histograms_.importDict(dict);
+ // Continue after last found newline character.
+ this.dataOffset_ = endIndex + 1;
+ }
+ } while (performance.now() - startTime < 50);
+
+ await this.update_(`Loading Histogram ${this.histograms_.length}`);
+ await this.loadSomeHistograms_();
+ }
+
+ async displayHistograms_() {
+ this.view_.addEventListener('display-ready', async() => {
+ this.loadingEl_.style.display = 'none';
+ this.view_.style.display = 'block';
+ await tr.b.animationFrame();
+ this.fmpMark_.end();
+ });
+
+ await this.view_.build(this.histograms_, {
+ progress: message => this.update_(message),
+ helpHref: 'https://github.com/catapult-project/catapult/blob/master/docs/metrics-results-ui.md',
+ feedbackHref: 'https://docs.google.com/a/google.com/forms/d/e/1FAIpQLSfXvMvm_z2F9-khFaKyH_LHVZ6caPPkxI27BZqMnEt4XjyJ3g/viewform',
+ });
+ }
+ }
+
+ return {
+ HistogramImporter,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_parameter_collector.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_parameter_collector.html
new file mode 100644
index 00000000000..19213f74ba4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_parameter_collector.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/value/histogram_grouping.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v', function() {
+ const getDisplayLabel =
+ tr.v.HistogramGrouping.DISPLAY_LABEL.callback;
+
+ const DEFAULT_POSSIBLE_GROUPS = [];
+
+ const EXCLUDED_GROUPING_KEYS = [
+ tr.v.HistogramGrouping.DISPLAY_LABEL.key,
+ ];
+ // HISTOGRAM_NAME is overridden.
+ // DISPLAY_LABEL is used to define the columns, so don't allow grouping rows
+ // by it.
+ for (const group of tr.v.HistogramGrouping.BY_KEY.values()) {
+ if (EXCLUDED_GROUPING_KEYS.includes(group.key)) continue;
+ DEFAULT_POSSIBLE_GROUPS.push(group);
+ }
+
+ // This Processor collects various parameters from a set of Histograms such as
+ // their statistics, displayLabels, and grouping keys in a single pass.
+ class HistogramParameterCollector {
+ constructor() {
+ this.statisticNames_ = new Set(['avg']);
+
+ this.labelsToStartTimes_ = new Map();
+
+ // @typedef {!Map.<string,!tr.v.HistogramGrouping>}
+ this.keysToGroupings_ = new Map(DEFAULT_POSSIBLE_GROUPS.map(
+ g => [g.key, g]));
+
+ // Map from HistogramGrouping keys to Sets of return values from the
+ // HistogramGroupings' callbacks.
+ this.keysToValues_ = new Map(DEFAULT_POSSIBLE_GROUPS.map(
+ g => [g.key, new Set()]));
+
+ // Never remove 'name' from keysToGroupings.
+ this.keysToValues_.delete(
+ tr.v.HistogramGrouping.HISTOGRAM_NAME.key);
+ }
+
+ process(histograms) {
+ const allStoryTags = new Set();
+ let maxSampleCount = 0;
+ for (const hist of histograms) {
+ maxSampleCount = Math.max(maxSampleCount, hist.numValues);
+
+ for (const statName of hist.statisticsNames) {
+ this.statisticNames_.add(statName);
+ }
+
+ let startTime = hist.diagnostics.get(
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START);
+ if (startTime !== undefined) startTime = startTime.minDate.getTime();
+
+ const displayLabel = getDisplayLabel(hist);
+
+ if (this.labelsToStartTimes_.has(displayLabel)) {
+ startTime = Math.min(startTime,
+ this.labelsToStartTimes_.get(displayLabel));
+ }
+ this.labelsToStartTimes_.set(displayLabel, startTime);
+
+ for (const [groupingKey, values] of this.keysToValues_) {
+ const grouping = this.keysToGroupings_.get(groupingKey);
+ const value = grouping.callback(hist);
+ if (!value) continue;
+ values.add(value);
+ if (values.size > 1) {
+ // This grouping will definitely stay in keysToGroupings_. We don't
+ // need to see any more values in the rest of histograms. Remove
+ // this groupingKey from this.keysToValues_ so that we don't compute
+ // it for any more histograms and so that we don't delete it from
+ // keysToGroupings_.
+ this.keysToValues_.delete(groupingKey);
+ }
+ }
+
+ const storyTags = hist.diagnostics.get(
+ tr.v.d.RESERVED_NAMES.STORY_TAGS);
+ for (const tag of (storyTags || [])) {
+ allStoryTags.add(tag);
+ }
+ }
+ tr.b.Timing.instant(
+ 'HistogramParameterCollector', 'maxSampleCount', maxSampleCount);
+
+ for (const tagGrouping of tr.v.HistogramGrouping.buildFromTags(
+ allStoryTags, tr.v.d.RESERVED_NAMES.STORY_TAGS)) {
+ const values = new Set();
+ for (const hist of histograms) {
+ values.add(tagGrouping.callback(hist));
+ }
+ if (values.size > 1) {
+ this.keysToGroupings_.set(tagGrouping.key, tagGrouping);
+ this.keysToValues_.set(tagGrouping.key, values);
+ }
+ }
+
+ this.statisticNames_.add('pct_090');
+ }
+
+ get statisticNames() {
+ return Array.from(this.statisticNames_);
+ }
+
+ get labels() {
+ const displayLabels = Array.from(this.labelsToStartTimes_.keys());
+ displayLabels.sort((x, y) =>
+ this.labelsToStartTimes_.get(x) - this.labelsToStartTimes_.get(y));
+ return displayLabels;
+ }
+
+ get possibleGroupings() {
+ for (const [key, values] of this.keysToValues_) {
+ if (values.size >= 2) continue;
+ // Remove this grouping from keysToGroupings_ if there is fewer than
+ // 2 possible values.
+ this.keysToGroupings_.delete(key);
+ }
+
+ return Array.from(this.keysToGroupings_.values());
+ }
+ }
+
+ return {
+ HistogramParameterCollector,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_parameter_collector_test.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_parameter_collector_test.html
new file mode 100644
index 00000000000..2e508d21c92
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_parameter_collector_test.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram_parameter_collector.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ test('empty', function() {
+ const collector = new tr.v.HistogramParameterCollector();
+ collector.process([]);
+ assert.lengthOf(collector.statisticNames, 2);
+ assert.strictEqual('avg', collector.statisticNames[0]);
+ assert.strictEqual('pct_090', collector.statisticNames[1]);
+ assert.strictEqual('name',
+ tr.b.getOnlyElement(collector.possibleGroupings).key);
+ assert.lengthOf(collector.labels, 0);
+ });
+
+ test('sortLabels', function() {
+ const collector = new tr.v.HistogramParameterCollector();
+ collector.process([
+ tr.v.Histogram.create('', tr.b.Unit.byName.count, 0, {
+ diagnostics: new Map([
+ [
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A']),
+ ], [
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(1000),
+ ],
+ ]),
+ }),
+ tr.v.Histogram.create('', tr.b.Unit.byName.count, 0, {
+ diagnostics: new Map([
+ [
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B']),
+ ], [
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(3000),
+ ],
+ ]),
+ }),
+ tr.v.Histogram.create('', tr.b.Unit.byName.count, 0, {
+ diagnostics: new Map([
+ [
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['C']),
+ ], [
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(2000),
+ ],
+ ]),
+ }),
+ ]);
+ const labels = collector.labels;
+ assert.lengthOf(labels, 3);
+ assert.strictEqual(labels[0], 'A');
+ assert.strictEqual(labels[1], 'C');
+ assert.strictEqual(labels[2], 'B');
+ });
+
+ test('possibleGroupings', function() {
+ const collector = new tr.v.HistogramParameterCollector();
+ collector.process([
+ tr.v.Histogram.create('a', tr.b.Unit.byName.count, 0, {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(['F'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(1000)],
+ [tr.v.d.RESERVED_NAMES.STORYSET_REPEATS, new tr.v.d.GenericSet([0])],
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['R'])],
+ ]),
+ }),
+ tr.v.Histogram.create('b', tr.b.Unit.byName.count, 0, {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(['F'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(3000)],
+ [tr.v.d.RESERVED_NAMES.STORYSET_REPEATS, new tr.v.d.GenericSet([1])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARKS, new tr.v.d.GenericSet(['N'])],
+ ]),
+ }),
+ tr.v.Histogram.create('c', tr.b.Unit.byName.count, 0, {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(['E', 'F'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['C'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(2000)],
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['P'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARKS, new tr.v.d.GenericSet(['M'])],
+ ]),
+ }),
+ ]);
+
+ const possibleGroupingKeys = new Set(
+ collector.possibleGroupings.map(g => g.key));
+ assert.isTrue(possibleGroupingKeys.has(
+ tr.v.HistogramGrouping.HISTOGRAM_NAME.key));
+ assert.isTrue(possibleGroupingKeys.has(
+ tr.v.d.RESERVED_NAMES.BENCHMARKS));
+ assert.isTrue(possibleGroupingKeys.has(
+ tr.v.d.RESERVED_NAMES.STORYSET_REPEATS));
+ assert.isTrue(possibleGroupingKeys.has(
+ tr.v.d.RESERVED_NAMES.STORIES));
+ assert.isFalse(possibleGroupingKeys.has(
+ tr.v.HistogramGrouping.DISPLAY_LABEL.key));
+ assert.isFalse(possibleGroupingKeys.has(
+ tr.v.d.RESERVED_NAMES.TRACE_START));
+ assert.isTrue(possibleGroupingKeys.has('ETag'));
+ assert.isFalse(possibleGroupingKeys.has('FTag'));
+ assert.strictEqual(possibleGroupingKeys.size, 7);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_set.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_set.html
new file mode 100644
index 00000000000..1171233ebb1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_set.html
@@ -0,0 +1,374 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/histogram_grouping.html">
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v', function() {
+ class HistogramSet {
+ constructor(opt_histograms) {
+ this.histograms_ = new Set();
+ this.sharedDiagnosticsByGuid_ = new Map();
+
+ if (opt_histograms !== undefined) {
+ for (const hist of opt_histograms) {
+ this.addHistogram(hist);
+ }
+ }
+ }
+
+ has(hist) {
+ return this.histograms_.has(hist);
+ }
+
+ /**
+ * Create a Histogram, configure it, add samples to it, and add it to this
+ * HistogramSet.
+ *
+ * |samples| can be either
+ * 0. a number, or
+ * 1. a dictionary {value: number, diagnostics: dictionary}, or
+ * 2. an array of
+ * 2a. number, or
+ * 2b. dictionaries {value, diagnostics}.
+ *
+ * @param {string} name
+ * @param {!tr.b.Unit} unit
+ * @param {number|!Object|!Array.<(number|!Object)>} samples
+ * @param {!Object=} opt_options
+ * @param {!tr.v.HistogramBinBoundaries} opt_options.binBoundaries
+ * @param {!Object|!Map} opt_options.summaryOptions
+ * @param {!Object|!Map} opt_options.diagnostics
+ * @param {string} opt_options.description
+ * @return {!tr.v.Histogram}
+ */
+ createHistogram(name, unit, samples, opt_options) {
+ const hist = tr.v.Histogram.create(name, unit, samples, opt_options);
+ this.addHistogram(hist);
+ return hist;
+ }
+
+ /**
+ * @param {!tr.v.Histogram} hist
+ * @param {(!Object|!tr.v.d.DiagnosticMap)=} opt_diagnostics
+ */
+ addHistogram(hist, opt_diagnostics) {
+ if (this.has(hist)) {
+ throw new Error('Cannot add same Histogram twice');
+ }
+
+ if (opt_diagnostics !== undefined) {
+ if (!(opt_diagnostics instanceof Map)) {
+ opt_diagnostics = Object.entries(opt_diagnostics);
+ }
+ for (const [name, diagnostic] of opt_diagnostics) {
+ hist.diagnostics.set(name, diagnostic);
+ }
+ }
+
+ this.histograms_.add(hist);
+ }
+
+ /**
+ * Add a Diagnostic to all Histograms so that it will only be serialized
+ * once per HistogramSet rather than once per Histogram that contains it.
+ *
+ * @param {string} name
+ * @param {!tr.v.d.Diagnostic} diagnostic
+ */
+ addSharedDiagnosticToAllHistograms(name, diagnostic) {
+ this.addSharedDiagnostic(diagnostic);
+ for (const hist of this) {
+ hist.diagnostics.set(name, diagnostic);
+ }
+ }
+
+ /**
+ * Add a Diagnostic to this HistogramSet so that it will only be serialized
+ * once per HistogramSet rather than once per Histogram that contains it.
+ *
+ * @param {!tr.v.d.Diagnostic} diagnostic
+ */
+ addSharedDiagnostic(diagnostic) {
+ this.sharedDiagnosticsByGuid_.set(diagnostic.guid, diagnostic);
+ }
+
+ get length() {
+ return this.histograms_.size;
+ }
+
+ * [Symbol.iterator]() {
+ for (const hist of this.histograms_) {
+ yield hist;
+ }
+ }
+
+ /**
+ * Filters Histograms by matching their name exactly.
+ *
+ * @param {string} name Histogram name.
+ * @return {!Array.<!tr.v.Histogram>}
+ */
+ getHistogramsNamed(name) {
+ return [...this].filter(h => h.name === name);
+ }
+
+ /**
+ * Filters to find the Histogram that matches the specified name exactly.
+ * If no Histogram with that name exists, undefined is returned. If multiple
+ * Histograms with the name exist, an error is thrown.
+ *
+ * @param {string} name Histogram name.
+ * @return {tr.v.Histogram}
+ */
+ getHistogramNamed(name) {
+ const histograms = this.getHistogramsNamed(name);
+ if (histograms.length === 0) return undefined;
+ if (histograms.length > 1) {
+ throw new Error(
+ `Unexpectedly found multiple histograms named "${name}"`);
+ }
+
+ return histograms[0];
+ }
+
+ /**
+ * Lookup a Diagnostic by its guid.
+ *
+ * @param {string} guid
+ * @return {!tr.v.d.Diagnostic|undefined}
+ */
+ lookupDiagnostic(guid) {
+ return this.sharedDiagnosticsByGuid_.get(guid);
+ }
+
+ /**
+ * Convert dicts to either Histograms or shared Diagnostics.
+ *
+ * @param {!Object} dicts
+ */
+ importDicts(dicts) {
+ for (const dict of dicts) {
+ this.importDict(dict);
+ }
+ }
+
+ /**
+ * Convert dict to either a Histogram or a shared Diagnostic.
+ *
+ * @param {!Object} dict
+ */
+ importDict(dict) {
+ if (dict.type !== undefined) {
+ // TODO(benjhayden): Forget about TagMaps in 2019Q2.
+ if (dict.type === 'TagMap') return;
+
+ if (!tr.v.d.Diagnostic.findTypeInfoWithName(dict.type)) {
+ throw new Error('Unrecognized shared diagnostic type ' + dict.type);
+ }
+ this.sharedDiagnosticsByGuid_.set(dict.guid,
+ tr.v.d.Diagnostic.fromDict(dict));
+ } else {
+ const hist = tr.v.Histogram.fromDict(dict);
+ this.addHistogram(hist);
+ hist.diagnostics.resolveSharedDiagnostics(this, true);
+ }
+ }
+
+ /**
+ * Serialize all of the Histograms and shared Diagnostics to an Array of
+ * dictionaries.
+ *
+ * @return {!Array.<!Object>}
+ */
+ asDicts() {
+ const dicts = [];
+ for (const diagnostic of this.sharedDiagnosticsByGuid_.values()) {
+ dicts.push(diagnostic.asDict());
+ }
+ for (const hist of this) {
+ dicts.push(hist.asDict());
+ }
+ return dicts;
+ }
+
+ /**
+ * Find the Histograms whose names are not contained in any other
+ * Histograms' RelatedNameMap diagnostics.
+ *
+ * @return {!Array.<!tr.v.Histogram>}
+ */
+ get sourceHistograms() {
+ const diagnosticNames = new Set();
+ for (const hist of this) {
+ for (const diagnostic of hist.diagnostics.values()) {
+ if (!(diagnostic instanceof tr.v.d.RelatedNameMap)) continue;
+ for (const name of diagnostic.values()) {
+ diagnosticNames.add(name);
+ }
+ }
+ }
+
+ const sourceHistograms = new HistogramSet;
+ for (const hist of this) {
+ if (!diagnosticNames.has(hist.name)) {
+ sourceHistograms.addHistogram(hist);
+ }
+ }
+ return sourceHistograms;
+ }
+
+ /**
+ * Return a nested Map, whose keys are strings and leaf values are Arrays of
+ * Histograms.
+ * See GROUPINGS for example |groupings|.
+ * Groupings are skipped when |opt_skipGroupingCallback| is specified and
+ * returns true.
+ *
+ * @typedef {!Array.<tr.v.Histogram>} HistogramArray
+ * @typedef {!Map.<string,!(HistogramArray|HistogramArrayMap)>}
+ * HistogramArrayMap
+ * @typedef {!Map.<string,!HistogramArray>} LeafHistogramArrayMap
+ *
+ * @param {!Array.<!tr.v.HistogramGrouping>} groupings
+ * @param {!function(!Grouping, !LeafHistogramArrayMap):boolean=}
+ * opt_skipGroupingCallback
+ *
+ * @return {!(HistogramArray|HistogramArrayMap)}
+ */
+ groupHistogramsRecursively(groupings, opt_skipGroupingCallback) {
+ function recurse(histograms, level) {
+ if (level === groupings.length) {
+ return histograms; // recursion base case
+ }
+
+ const grouping = groupings[level];
+ const groupedHistograms = tr.b.groupIntoMap(
+ histograms, grouping.callback);
+
+ if (opt_skipGroupingCallback && opt_skipGroupingCallback(
+ grouping, groupedHistograms)) {
+ return recurse(histograms, level + 1);
+ }
+
+ for (const [key, group] of groupedHistograms) {
+ groupedHistograms.set(key, recurse(group, level + 1));
+ }
+
+ return groupedHistograms;
+ }
+
+ return recurse([...this], 0);
+ }
+
+ /*
+ * Histograms and Diagnostics are merged two at a time, without considering
+ * any others, so it is possible for two merged Diagnostics to be equivalent
+ * but not identical, which is inefficient. This method replaces equivalent
+ * Diagnostics with shared Diagnostics so that the HistogramSet can be
+ * serialized more efficiently and so that these Diagnostics can be compared
+ * quickly when merging relationship Diagnostics.
+ */
+ deduplicateDiagnostics() {
+ const namesToCandidates = new Map(); // string: Set<Diagnostic>
+ const diagnosticsToHistograms = new Map(); // Diagnostic: [Histogram]
+ const keysToDiagnostics = new Map(); // string: Diagnostic
+
+ for (const hist of this) {
+ for (const [name, candidate] of hist.diagnostics) {
+ // TODO(#3695): Remove this check once equality is smoke-tested.
+ if (candidate.equals === undefined) {
+ this.sharedDiagnosticsByGuid_.set(candidate.guid, candidate);
+ continue;
+ }
+
+ const hashKey = candidate.hashKey;
+ if (candidate.hashKey !== undefined) {
+ // TODO(857283): Fall back to slow path if same name but diff type
+ if (keysToDiagnostics.has(hashKey)) {
+ hist.diagnostics.set(name, keysToDiagnostics.get(hashKey));
+ } else {
+ keysToDiagnostics.set(hashKey, candidate);
+ this.sharedDiagnosticsByGuid_.set(candidate.guid, candidate);
+ }
+
+ continue;
+ }
+
+ if (diagnosticsToHistograms.get(candidate) === undefined) {
+ diagnosticsToHistograms.set(candidate, [hist]);
+ } else {
+ diagnosticsToHistograms.get(candidate).push(hist);
+ }
+
+ if (!namesToCandidates.has(name)) {
+ namesToCandidates.set(name, new Set());
+ }
+ namesToCandidates.get(name).add(candidate);
+ }
+ }
+
+ for (const [name, candidates] of namesToCandidates) {
+ const deduplicatedDiagnostics = new Set();
+
+ for (const candidate of candidates) {
+ let found = false;
+ for (const test of deduplicatedDiagnostics) {
+ if (candidate.equals(test)) {
+ const hists = diagnosticsToHistograms.get(candidate);
+ for (const hist of hists) {
+ hist.diagnostics.set(name, test);
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ deduplicatedDiagnostics.add(candidate);
+ }
+
+ for (const diagnostic of deduplicatedDiagnostics) {
+ this.sharedDiagnosticsByGuid_.set(diagnostic.guid, diagnostic);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param {!Iterable.<string>} names of GenericSet diagnostics
+ * @return {!Array.<!tr.v.HistogramGrouping>}
+ */
+ buildGroupingsFromTags(names) {
+ const tags = new Map(); // name: Set<string>
+ for (const hist of this) {
+ for (const name of names) {
+ if (!hist.diagnostics.has(name)) continue;
+ if (!tags.has(name)) tags.set(name, new Set());
+ for (const tag of hist.diagnostics.get(name)) {
+ tags.get(name).add(tag);
+ }
+ }
+ }
+
+ const groupings = [];
+ for (const [name, values] of tags) {
+ const built = tr.v.HistogramGrouping.buildFromTags(values, name);
+ for (const grouping of built) {
+ groupings.push(grouping);
+ }
+ }
+ return groupings;
+ }
+ }
+
+ return {HistogramSet};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_set.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_set.py
new file mode 100644
index 00000000000..b9a5d795c37
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_set.py
@@ -0,0 +1,155 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+
+from tracing.value import histogram as histogram_module
+from tracing.value.diagnostics import all_diagnostics
+from tracing.value.diagnostics import diagnostic
+from tracing.value.diagnostics import diagnostic_ref
+from tracing.value.diagnostics import generic_set
+
+class HistogramSet(object):
+ def __init__(self, histograms=()):
+ self._histograms = set()
+ self._shared_diagnostics_by_guid = {}
+ for hist in histograms:
+ self.AddHistogram(hist)
+
+ @property
+ def shared_diagnostics(self):
+ return self._shared_diagnostics_by_guid.values()
+
+ def RemoveOrphanedDiagnostics(self):
+ orphans = set(self._shared_diagnostics_by_guid.keys())
+ for h in self._histograms:
+ for d in h.diagnostics.values():
+ if d.guid in orphans:
+ orphans.remove(d.guid)
+ for guid in orphans:
+ del self._shared_diagnostics_by_guid[guid]
+
+ def FilterHistograms(self, discard):
+ self._histograms = set(
+ hist
+ for hist in self._histograms
+ if not discard(hist))
+
+ def AddHistogram(self, hist, diagnostics=None):
+ if diagnostics:
+ for name, diag in diagnostics.items():
+ hist.diagnostics[name] = diag
+
+ self._histograms.add(hist)
+
+ def AddSharedDiagnostic(self, diag):
+ self._shared_diagnostics_by_guid[diag.guid] = diag
+
+ def AddSharedDiagnosticToAllHistograms(self, name, diag):
+ self._shared_diagnostics_by_guid[diag.guid] = diag
+
+ for hist in self:
+ hist.diagnostics[name] = diag
+
+ def GetFirstHistogram(self):
+ for histogram in self._histograms:
+ return histogram
+
+ def GetHistogramsNamed(self, name):
+ return [h for h in self if h.name == name]
+
+ def GetHistogramNamed(self, name):
+ hs = self.GetHistogramsNamed(name)
+ assert len(hs) == 1, 'Found %d Histograms names "%s"' % (len(hs), name)
+ return hs[0]
+
+ def GetSharedDiagnosticsOfType(self, typ):
+ return [d for d in self.shared_diagnostics if isinstance(d, typ)]
+
+ def LookupDiagnostic(self, guid):
+ return self._shared_diagnostics_by_guid.get(guid)
+
+ def __len__(self):
+ return len(self._histograms)
+
+ def __iter__(self):
+ for hist in self._histograms:
+ yield hist
+
+ def ImportDicts(self, dicts):
+ for d in dicts:
+ if 'type' in d:
+ # TODO(benjhayden): Forget about TagMaps in 2019Q2.
+ if d['type'] == 'TagMap':
+ continue
+
+ assert d['type'] in all_diagnostics.GetDiagnosticTypenames(), (
+ 'Unrecognized shared diagnostic type ' + d['type'])
+ diag = diagnostic.Diagnostic.FromDict(d)
+ self._shared_diagnostics_by_guid[d['guid']] = diag
+ else:
+ hist = histogram_module.Histogram.FromDict(d)
+ hist.diagnostics.ResolveSharedDiagnostics(self)
+ self.AddHistogram(hist)
+
+ def AsDicts(self):
+ dcts = []
+ for d in self._shared_diagnostics_by_guid.values():
+ dcts.append(d.AsDict())
+ for h in self:
+ dcts.append(h.AsDict())
+ return dcts
+
+ def ReplaceSharedDiagnostic(self, old_guid, new_diagnostic):
+ if not isinstance(new_diagnostic, diagnostic_ref.DiagnosticRef):
+ self._shared_diagnostics_by_guid[new_diagnostic.guid] = new_diagnostic
+
+ old_diagnostic = self._shared_diagnostics_by_guid.get(old_guid)
+
+ # Fast path, if they're both generic_sets, we overwrite the contents of the
+ # old diagnostic.
+ if isinstance(new_diagnostic, generic_set.GenericSet) and (
+ isinstance(old_diagnostic, generic_set.GenericSet)):
+ old_diagnostic.SetValues(list(new_diagnostic))
+ old_diagnostic.ResetGuid(new_diagnostic.guid)
+
+ self._shared_diagnostics_by_guid[new_diagnostic.guid] = old_diagnostic
+ del self._shared_diagnostics_by_guid[old_guid]
+
+ return
+
+ for hist in self:
+ for name, diag in hist.diagnostics.items():
+ if diag.has_guid and diag.guid == old_guid:
+ hist.diagnostics[name] = new_diagnostic
+
+ def DeduplicateDiagnostics(self):
+ names_to_candidates = {}
+ diagnostics_to_histograms = collections.defaultdict(list)
+
+ for hist in self:
+ for name, candidate in hist.diagnostics.items():
+ diagnostics_to_histograms[candidate].append(hist)
+
+ if name not in names_to_candidates:
+ names_to_candidates[name] = set()
+ names_to_candidates[name].add(candidate)
+
+ for name, candidates in names_to_candidates.items():
+ deduplicated_diagnostics = set()
+
+ for candidate in candidates:
+ found = False
+ for test in deduplicated_diagnostics:
+ if candidate == test:
+ hists = diagnostics_to_histograms.get(candidate)
+ for h in hists:
+ h.diagnostics[name] = test
+ found = True
+ break
+ if not found:
+ deduplicated_diagnostics.add(candidate)
+
+ for diag in deduplicated_diagnostics:
+ self._shared_diagnostics_by_guid[diag.guid] = diag
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_set_hierarchy.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_set_hierarchy.html
new file mode 100644
index 00000000000..86a3765fbfe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_set_hierarchy.html
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v', function() {
+ /*
+ * See also HistogramSet.groupHistogramsRecursively().
+ * See also tr.v.ui.HistogramSetTableRow.
+ */
+ class HistogramSetHierarchy {
+ /**
+ * @param {string} name
+ */
+ constructor(name) {
+ this.name = name;
+ this.description = '';
+ this.depth = 0;
+ this.subRows = [];
+ this.columns = new Map();
+ }
+
+ * walk() {
+ yield this;
+ for (const row of this.subRows) yield* row.walk();
+ }
+
+ static* walkAll(rootRows) {
+ for (const rootRow of rootRows) yield* rootRow.walk();
+ }
+
+ /**
+ * Build table rows recursively from grouped Histograms.
+ *
+ * @param {!(HistogramArray|HistogramArrayMap)}
+ * @returns {!Array.<!HistogramSetHierarchy>}
+ */
+ static build(histogramArrayMap) {
+ const rootRows = [];
+ HistogramSetHierarchy.buildInternal_(histogramArrayMap, [], rootRows);
+
+ const histograms = new tr.v.HistogramSet();
+
+ for (const row of HistogramSetHierarchy.walkAll(rootRows)) {
+ for (const hist of row.columns.values()) {
+ if (!(hist instanceof tr.v.Histogram)) continue;
+ histograms.addHistogram(hist);
+ }
+ }
+
+ histograms.deduplicateDiagnostics();
+
+ for (const row of HistogramSetHierarchy.walkAll(rootRows)) {
+ row.maybeRebin_();
+ }
+
+ return rootRows;
+ }
+
+ maybeRebin_() {
+ // if all of |this| row's columns are single-bin, then re-bin all of them.
+ const dataRange = new tr.b.math.Range();
+ for (const hist of this.columns.values()) {
+ if (!(hist instanceof tr.v.Histogram)) continue;
+ if (hist.allBins.length > 1) return; // don't re-bin
+ if (hist.numValues === 0) continue; // ignore hist
+ dataRange.addValue(hist.min);
+ dataRange.addValue(hist.max);
+ }
+
+ dataRange.addValue(tr.b.math.lesserWholeNumber(dataRange.min));
+ dataRange.addValue(tr.b.math.greaterWholeNumber(dataRange.max));
+
+ if (dataRange.min === dataRange.max) return; // don't rebin
+
+ const boundaries = tr.v.HistogramBinBoundaries.createLinear(
+ dataRange.min, dataRange.max, tr.v.DEFAULT_REBINNED_COUNT);
+
+ for (const [name, hist] of this.columns) {
+ if (!(hist instanceof tr.v.Histogram)) continue;
+ this.columns.set(name, hist.rebin(boundaries));
+ }
+ }
+
+ static mergeHistogramDownHierarchy_(histogram, hierarchy, columnName) {
+ // Track the path down the grouping tree to each Histogram,
+ // but only start tracking the path at the grouping level that
+ // corresponds to the Histogram NAME Grouping.
+ for (const row of hierarchy) {
+ if (!row.description) {
+ row.description = histogram.description;
+ }
+
+ const existing = row.columns.get(columnName);
+
+ if (existing === undefined) {
+ row.columns.set(columnName, histogram.clone());
+ continue;
+ }
+
+ if (existing instanceof tr.v.HistogramSet) {
+ // There have already been unmergeable histograms.
+ existing.addHistogram(histogram);
+ continue;
+ }
+
+ if (!existing.canAddHistogram(histogram)) {
+ // TODO(benjhayden) Remove?
+ const unmergeableHistograms = new tr.v.HistogramSet([histogram]);
+ row.columns.set(columnName, unmergeableHistograms);
+ continue;
+ }
+
+ existing.addHistogram(histogram);
+ }
+ }
+
+ static buildInternal_(
+ histogramArrayMap, hierarchy, rootRows) {
+ for (const [name, histograms] of histogramArrayMap) {
+ if (histograms instanceof Array) {
+ // This recursion base case corresponds to the recursion base case of
+ // groupHistogramsRecursively(). The last groupingCallback is always
+ // getDisplayLabel, which defines the columns of the table and is
+ // unskippable.
+ for (const histogram of histograms) {
+ HistogramSetHierarchy.mergeHistogramDownHierarchy_(
+ histogram, hierarchy, name);
+ }
+ } else if (histograms instanceof Map) {
+ // |histograms| is actually a nested histogramArrayMap.
+ const row = new HistogramSetHierarchy(name);
+ row.depth = hierarchy.length;
+ hierarchy.push(row);
+ HistogramSetHierarchy.buildInternal_(histograms, hierarchy, rootRows);
+ hierarchy.pop();
+
+ if (hierarchy.length === 0) {
+ rootRows.push(row);
+ } else {
+ const parentRow = hierarchy[hierarchy.length - 1];
+ parentRow.subRows.push(row);
+ }
+ }
+ }
+ }
+ }
+
+ return {HistogramSetHierarchy};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_set_test.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_set_test.html
new file mode 100644
index 00000000000..2db75bfba45
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_set_test.html
@@ -0,0 +1,221 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
+<link rel="import" href="/tracing/value/diagnostics/generic_set.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ // TODO(#3812) Test groupHistogramsRecursively.
+
+ test('assertType', function() {
+ const hs = new tr.v.HistogramSet();
+ assert.throws(() => hs.importDict({type: ''}),
+ Error, 'Unrecognized shared diagnostic type ');
+ });
+
+ test('ignoreTagMap', function() {
+ const hs = new tr.v.HistogramSet();
+ hs.importDict({type: 'TagMap'});
+ });
+
+ test('importDicts', function() {
+ const n = new tr.v.Histogram('foo', tr.b.Unit.byName.unitlessNumber);
+ const histograms = new tr.v.HistogramSet([n]);
+ const histograms2 = new tr.v.HistogramSet();
+ histograms2.importDicts(histograms.asDicts());
+ assert.isDefined(histograms2.getHistogramNamed('foo'));
+ });
+
+ test('importDictsWithSampleDiagnostic', function() {
+ const n = new tr.v.Histogram('foo', tr.b.Unit.byName.count);
+ n.addSample(10, {bar: new tr.v.d.GenericSet(['baz'])});
+
+ const histograms = new tr.v.HistogramSet([n]);
+ const histograms2 = new tr.v.HistogramSet();
+ histograms2.importDicts(histograms.asDicts());
+ assert.isDefined(histograms2.getHistogramNamed('foo'));
+ const v = histograms2.getHistogramNamed('foo');
+ assert.lengthOf(v.getBinForValue(10).diagnosticMaps, 1);
+ const dm = v.getBinForValue(10).diagnosticMaps[0];
+ assert.strictEqual(dm.size, 1);
+ assert.instanceOf(dm.get('bar'), tr.v.d.GenericSet);
+ assert.strictEqual(tr.b.getOnlyElement(dm.get('bar')), 'baz');
+ });
+
+ test('sourceHistogramsWithSampleDiagnostic', function() {
+ const unit = tr.b.Unit.byName.unitlessNumber;
+ const aHist = new tr.v.Histogram('a', unit);
+ aHist.addSample(1);
+
+ const bHist = new tr.v.Histogram('b', tr.b.Unit.byName.unitlessNumber);
+ const related = new tr.v.d.RelatedNameMap();
+ related.set('0', aHist.name);
+ bHist.diagnostics.set('related', related);
+ bHist.addSample(1);
+
+ const histograms = new tr.v.HistogramSet([aHist, bHist]);
+ assert.strictEqual(tr.b.getOnlyElement(histograms.sourceHistograms), bHist);
+ });
+
+ test('sourceHistogramsWithNameMap', function() {
+ const unit = tr.b.Unit.byName.unitlessNumber;
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('A', unit, []);
+ const bHist = histograms.createHistogram('B', unit, [], {diagnostics: {
+ related: tr.v.d.RelatedNameMap.fromEntries([['a', 'A']]),
+ }});
+ assert.strictEqual(tr.b.getOnlyElement(histograms.sourceHistograms), bHist);
+ });
+
+ test('sharedDiagnostic', function() {
+ // Make a single Histogram, add a shared Diagnostic.
+ const aHist = new tr.v.Histogram('aHist', tr.b.Unit.byName.count);
+ const histograms = new tr.v.HistogramSet([aHist]);
+ const diagnostic = new tr.v.d.GenericSet(['shared']);
+ histograms.addSharedDiagnosticToAllHistograms('generic', diagnostic);
+
+ // Serializing a single Histogram with a single shared diagnostic should
+ // produce 2 dicts.
+ const dicts = histograms.asDicts();
+ assert.lengthOf(dicts, 2);
+ assert.deepEqual(diagnostic.asDict(), dicts[0]);
+
+ // The serialized Histogram should refer to the shared diagnostic by its
+ // guid.
+ assert.strictEqual(dicts[1].diagnostics.generic, diagnostic.guid);
+
+ // Deserialize the dicts.
+ const histograms2 = new tr.v.HistogramSet();
+ histograms2.importDicts(dicts);
+ assert.lengthOf(histograms2, 1);
+ const aHist2 = histograms2.getHistogramNamed(aHist.name);
+
+ assert.instanceOf(aHist2.diagnostics.get('generic'), tr.v.d.GenericSet);
+ assert.strictEqual(tr.b.getOnlyElement(diagnostic),
+ tr.b.getOnlyElement(aHist2.diagnostics.get('generic')));
+ });
+
+ test('getHistogramNamed_noHistogramFound', function() {
+ const aHist = new tr.v.Histogram('aHist', tr.b.Unit.byName.count);
+ const histograms = new tr.v.HistogramSet([aHist]);
+
+ assert.isUndefined(histograms.getHistogramNamed('bHist'));
+ });
+
+ test('getHistogramNamed_oneHistogramFound', function() {
+ const aHist = new tr.v.Histogram('aHist', tr.b.Unit.byName.count);
+ const histograms = new tr.v.HistogramSet([aHist]);
+
+ assert.strictEqual(histograms.getHistogramNamed('aHist'), aHist);
+ });
+
+ test('getHistogramNamed_multipleHistogramsFound', function() {
+ const aHist1 = new tr.v.Histogram('aHist', tr.b.Unit.byName.count);
+ const aHist2 = new tr.v.Histogram('aHist', tr.b.Unit.byName.count);
+ const histograms = new tr.v.HistogramSet([aHist1, aHist2]);
+
+ assert.throws(() => histograms.getHistogramNamed('aHist'),
+ Error, 'Unexpectedly found multiple histograms named "aHist"');
+ });
+
+ test('deduplicateDiagnostics', function() {
+ const genericA = new tr.v.d.GenericSet(['A']);
+ const genericB = new tr.v.d.GenericSet(['B']);
+ const dateA = new tr.v.d.DateRange(42);
+ const dateB = new tr.v.d.DateRange(57);
+
+ const aHist = new tr.v.Histogram('a', tr.b.Unit.byName.count);
+ const generic0 = genericA.clone();
+ generic0.addDiagnostic(genericB);
+ aHist.diagnostics.set('generic', generic0);
+ const date0 = dateA.clone();
+ date0.addDiagnostic(dateB);
+ aHist.diagnostics.set('date', date0);
+
+ const bHist = new tr.v.Histogram('b', tr.b.Unit.byName.count);
+ const generic1 = genericA.clone();
+ generic1.addDiagnostic(genericB);
+ bHist.diagnostics.set('generic', generic1);
+ const date1 = dateA.clone();
+ date1.addDiagnostic(dateB);
+ bHist.diagnostics.set('date', date1);
+
+ const cHist = new tr.v.Histogram('c', tr.b.Unit.byName.count);
+ cHist.diagnostics.set('generic', generic1);
+
+ const histograms = new tr.v.HistogramSet([aHist, bHist, cHist]);
+ assert.notStrictEqual(
+ aHist.diagnostics.get('generic'), bHist.diagnostics.get('generic'));
+ assert.strictEqual(
+ bHist.diagnostics.get('generic'), cHist.diagnostics.get('generic'));
+ assert.isTrue(
+ aHist.diagnostics.get('generic').equals(
+ bHist.diagnostics.get('generic')));
+ assert.notStrictEqual(
+ aHist.diagnostics.get('date'), bHist.diagnostics.get('date'));
+ assert.isTrue(
+ aHist.diagnostics.get('date').equals(bHist.diagnostics.get('date')));
+
+ histograms.deduplicateDiagnostics();
+
+ assert.strictEqual(
+ aHist.diagnostics.get('generic'), bHist.diagnostics.get('generic'));
+ assert.strictEqual(
+ bHist.diagnostics.get('generic'), cHist.diagnostics.get('generic'));
+ assert.strictEqual(
+ aHist.diagnostics.get('date'), bHist.diagnostics.get('date'));
+
+ const histogramDicts = histograms.asDicts();
+
+ // All diagnostics should have been serialized as DiagnosticRefs.
+ for (const dict of histogramDicts) {
+ if (!('type' in dict)) {
+ for (const diagnosticDict of Object.values(dict.diagnostics)) {
+ assert.strictEqual(typeof(diagnosticDict), 'string');
+ }
+ }
+ }
+
+ const histograms2 = new tr.v.HistogramSet();
+ histograms2.importDicts(histogramDicts);
+ const aHist2 = histograms2.getHistogramNamed('a');
+ const bHist2 = histograms2.getHistogramNamed('b');
+
+ assert.strictEqual(
+ aHist2.diagnostics.get('generic'), bHist2.diagnostics.get('generic'));
+ assert.strictEqual(
+ aHist2.diagnostics.get('date'), bHist2.diagnostics.get('date'));
+ });
+
+ test('buildGroupingsFromTags', function() {
+ const histograms = new tr.v.HistogramSet();
+ const aHist = histograms.createHistogram('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(['a'])],
+ ]),
+ });
+ const bHist = histograms.createHistogram('', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORY_TAGS, new tr.v.d.GenericSet(['b'])],
+ ]),
+ });
+ const groupings = histograms.buildGroupingsFromTags([
+ tr.v.d.RESERVED_NAMES.STORY_TAGS]);
+ assert.lengthOf(groupings, 2);
+ assert.strictEqual(groupings[0].callback(aHist), 'a');
+ assert.strictEqual(groupings[0].callback(bHist), '~a');
+ assert.strictEqual(groupings[1].callback(aHist), '~b');
+ assert.strictEqual(groupings[1].callback(bHist), 'b');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py
new file mode 100644
index 00000000000..39f6e45a3ec
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_set_unittest.py
@@ -0,0 +1,236 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value import histogram
+from tracing.value import histogram_set
+from tracing.value.diagnostics import date_range
+from tracing.value.diagnostics import diagnostic_ref
+from tracing.value.diagnostics import generic_set
+
+class HistogramSetUnittest(unittest.TestCase):
+
+ def testGetSharedDiagnosticsOfType(self):
+ d0 = generic_set.GenericSet(['foo'])
+ d1 = date_range.DateRange(0)
+ hs = histogram_set.HistogramSet()
+ hs.AddSharedDiagnosticToAllHistograms('generic', d0)
+ hs.AddSharedDiagnosticToAllHistograms('generic', d1)
+ diagnostics = hs.GetSharedDiagnosticsOfType(generic_set.GenericSet)
+ self.assertEqual(len(diagnostics), 1)
+ self.assertIsInstance(diagnostics[0], generic_set.GenericSet)
+
+ def testImportDicts(self):
+ hist = histogram.Histogram('', 'unitless')
+ hists = histogram_set.HistogramSet([hist])
+ hists2 = histogram_set.HistogramSet()
+ hists2.ImportDicts(hists.AsDicts())
+ self.assertEqual(len(hists), len(hists2))
+
+ def testAssertType(self):
+ hs = histogram_set.HistogramSet()
+ with self.assertRaises(AssertionError):
+ hs.ImportDicts([{'type': ''}])
+
+ def testIgnoreTagMap(self):
+ histogram_set.HistogramSet().ImportDicts([{'type': 'TagMap'}])
+
+ def testFilterHistogram(self):
+ a = histogram.Histogram('a', 'unitless')
+ b = histogram.Histogram('b', 'unitless')
+ c = histogram.Histogram('c', 'unitless')
+ hs = histogram_set.HistogramSet([a, b, c])
+ hs.FilterHistograms(lambda h: h.name == 'b')
+
+ names = set(['a', 'c'])
+ for h in hs:
+ self.assertIn(h.name, names)
+ names.remove(h.name)
+ self.assertEqual(0, len(names))
+
+ def testRemoveOrphanedDiagnostics(self):
+ da = generic_set.GenericSet(['a'])
+ db = generic_set.GenericSet(['b'])
+ a = histogram.Histogram('a', 'unitless')
+ b = histogram.Histogram('b', 'unitless')
+ hs = histogram_set.HistogramSet([a])
+ hs.AddSharedDiagnosticToAllHistograms('a', da)
+ hs.AddHistogram(b)
+ hs.AddSharedDiagnosticToAllHistograms('b', db)
+ hs.FilterHistograms(lambda h: h.name == 'a')
+
+ dicts = hs.AsDicts()
+ self.assertEqual(3, len(dicts))
+
+ hs.RemoveOrphanedDiagnostics()
+ dicts = hs.AsDicts()
+ self.assertEqual(2, len(dicts))
+
+ def testAddSharedDiagnostic(self):
+ diags = {}
+ da = generic_set.GenericSet(['a'])
+ db = generic_set.GenericSet(['b'])
+ diags['da'] = da
+ diags['db'] = db
+ a = histogram.Histogram('a', 'unitless')
+ b = histogram.Histogram('b', 'unitless')
+ hs = histogram_set.HistogramSet()
+ hs.AddSharedDiagnostic(da)
+ hs.AddHistogram(a, {'da': da})
+ hs.AddHistogram(b, {'db': db})
+
+ # This should produce one shared diagnostic and 2 histograms.
+ dicts = hs.AsDicts()
+ self.assertEqual(3, len(dicts))
+ self.assertEqual(da.AsDict(), dicts[0])
+
+
+ # Assert that you only see the shared diagnostic once.
+ seen_once = False
+ for idx, val in enumerate(dicts):
+ if idx == 0:
+ continue
+ if 'da' in val['diagnostics']:
+ self.assertFalse(seen_once)
+ self.assertEqual(val['diagnostics']['da'], da.guid)
+ seen_once = True
+
+
+ def testSharedDiagnostic(self):
+ hist = histogram.Histogram('', 'unitless')
+ hists = histogram_set.HistogramSet([hist])
+ diag = generic_set.GenericSet(['shared'])
+ hists.AddSharedDiagnosticToAllHistograms('generic', diag)
+
+ # Serializing a single Histogram with a single shared diagnostic should
+ # produce 2 dicts.
+ ds = hists.AsDicts()
+ self.assertEqual(len(ds), 2)
+ self.assertEqual(diag.AsDict(), ds[0])
+
+ # The serialized Histogram should refer to the shared diagnostic by its
+ # guid.
+ self.assertEqual(ds[1]['diagnostics']['generic'], diag.guid)
+
+ # Deserialize ds.
+ hists2 = histogram_set.HistogramSet()
+ hists2.ImportDicts(ds)
+ self.assertEqual(len(hists2), 1)
+ hist2 = [h for h in hists2][0]
+
+ self.assertIsInstance(
+ hist2.diagnostics.get('generic'), generic_set.GenericSet)
+ self.assertEqual(list(diag), list(hist2.diagnostics.get('generic')))
+
+ def testReplaceSharedDiagnostic(self):
+ hist = histogram.Histogram('', 'unitless')
+ hists = histogram_set.HistogramSet([hist])
+ diag0 = generic_set.GenericSet(['shared0'])
+ diag1 = generic_set.GenericSet(['shared1'])
+ hists.AddSharedDiagnosticToAllHistograms('generic0', diag0)
+ hists.AddSharedDiagnosticToAllHistograms('generic1', diag1)
+
+ guid0 = diag0.guid
+ guid1 = diag1.guid
+
+ hists.ReplaceSharedDiagnostic(
+ guid0, diagnostic_ref.DiagnosticRef('fakeGuid'))
+
+ self.assertEqual(hist.diagnostics['generic0'].guid, 'fakeGuid')
+ self.assertEqual(hist.diagnostics['generic1'].guid, guid1)
+
+ def testReplaceSharedDiagnostic_NonRefAddsToMap(self):
+ hist = histogram.Histogram('', 'unitless')
+ hists = histogram_set.HistogramSet([hist])
+ diag0 = generic_set.GenericSet(['shared0'])
+ diag1 = generic_set.GenericSet(['shared1'])
+ hists.AddSharedDiagnosticToAllHistograms('generic0', diag0)
+
+ guid0 = diag0.guid
+ guid1 = diag1.guid
+
+ hists.ReplaceSharedDiagnostic(guid0, diag1)
+
+ self.assertIsNotNone(hists.LookupDiagnostic(guid1))
+
+ def testDeduplicateDiagnostics(self):
+ generic_a = generic_set.GenericSet(['A'])
+ generic_b = generic_set.GenericSet(['B'])
+ date_a = date_range.DateRange(42)
+ date_b = date_range.DateRange(57)
+
+ a_hist = histogram.Histogram('a', 'unitless')
+ generic0 = generic_set.GenericSet.FromDict(generic_a.AsDict())
+ generic0.AddDiagnostic(generic_b)
+ a_hist.diagnostics['generic'] = generic0
+ date0 = date_range.DateRange.FromDict(date_a.AsDict())
+ date0.AddDiagnostic(date_b)
+ a_hist.diagnostics['date'] = date0
+
+ b_hist = histogram.Histogram('b', 'unitless')
+ generic1 = generic_set.GenericSet.FromDict(generic_a.AsDict())
+ generic1.AddDiagnostic(generic_b)
+ b_hist.diagnostics['generic'] = generic1
+ date1 = date_range.DateRange.FromDict(date_a.AsDict())
+ date1.AddDiagnostic(date_b)
+ b_hist.diagnostics['date'] = date1
+
+ c_hist = histogram.Histogram('c', 'unitless')
+ c_hist.diagnostics['generic'] = generic1
+
+ histograms = histogram_set.HistogramSet([a_hist, b_hist, c_hist])
+ self.assertNotEqual(
+ a_hist.diagnostics['generic'].guid, b_hist.diagnostics['generic'].guid)
+ self.assertEqual(
+ b_hist.diagnostics['generic'].guid, c_hist.diagnostics['generic'].guid)
+ self.assertEqual(
+ a_hist.diagnostics['generic'], b_hist.diagnostics['generic'])
+ self.assertNotEqual(
+ a_hist.diagnostics['date'].guid, b_hist.diagnostics['date'].guid)
+ self.assertEqual(
+ a_hist.diagnostics['date'], b_hist.diagnostics['date'])
+
+ histograms.DeduplicateDiagnostics()
+
+ self.assertEqual(
+ a_hist.diagnostics['generic'].guid, b_hist.diagnostics['generic'].guid)
+ self.assertEqual(
+ b_hist.diagnostics['generic'].guid, c_hist.diagnostics['generic'].guid)
+ self.assertEqual(
+ a_hist.diagnostics['generic'], b_hist.diagnostics['generic'])
+ self.assertEqual(
+ a_hist.diagnostics['date'].guid, b_hist.diagnostics['date'].guid)
+ self.assertEqual(
+ a_hist.diagnostics['date'], b_hist.diagnostics['date'])
+
+ histogram_dicts = histograms.AsDicts()
+
+ # All diagnostics should have been serialized as DiagnosticRefs.
+ for d in histogram_dicts:
+ if 'type' not in d:
+ for diagnostic_dict in d['diagnostics'].values():
+ self.assertIsInstance(diagnostic_dict, str)
+
+ histograms2 = histogram_set.HistogramSet()
+ histograms2.ImportDicts(histograms.AsDicts())
+ a_hists = histograms2.GetHistogramsNamed('a')
+ self.assertEqual(len(a_hists), 1)
+ a_hist2 = a_hists[0]
+ b_hists = histograms2.GetHistogramsNamed('b')
+ self.assertEqual(len(b_hists), 1)
+ b_hist2 = b_hists[0]
+
+ self.assertEqual(
+ a_hist2.diagnostics['generic'].guid,
+ b_hist2.diagnostics['generic'].guid)
+ self.assertEqual(
+ a_hist2.diagnostics['generic'],
+ b_hist2.diagnostics['generic'])
+ self.assertEqual(
+ a_hist2.diagnostics['date'].guid,
+ b_hist2.diagnostics['date'].guid)
+ self.assertEqual(
+ a_hist2.diagnostics['date'],
+ b_hist2.diagnostics['date'])
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_test.html b/chromium/third_party/catapult/tracing/tracing/value/histogram_test.html
new file mode 100644
index 00000000000..16f7b948272
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_test.html
@@ -0,0 +1,809 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/assert_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/generic_set.html">
+<link rel="import" href="/tracing/value/histogram.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const unitlessNumber = tr.b.Unit.byName.unitlessNumber;
+ const unitlessNumber_smallerIsBetter =
+ tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
+
+ const TEST_BOUNDARIES = tr.v.HistogramBinBoundaries.createLinear(0, 1000, 10);
+
+ function checkBoundaries(boundaries, expectedMinBoundary, expectedMaxBoundary,
+ expectedUnit, expectedBinRanges) {
+ assert.strictEqual(boundaries.range.min, expectedMinBoundary);
+ assert.strictEqual(boundaries.range.max, expectedMaxBoundary);
+
+ // Check that the boundaries can be used multiple times.
+ for (let i = 0; i < 3; i++) {
+ const hist = new tr.v.Histogram('', expectedUnit, boundaries);
+ assert.instanceOf(hist, tr.v.Histogram);
+ assert.strictEqual(hist.unit, expectedUnit);
+ assert.strictEqual(hist.numValues, 0);
+
+ assert.lengthOf(hist.allBins, expectedBinRanges.length);
+ for (let j = 0; j < expectedBinRanges.length; j++) {
+ const bin = hist.allBins[j];
+ assert.strictEqual(bin.count, 0);
+ assert.isTrue(bin.range.equals(expectedBinRanges[j]));
+ }
+ }
+ }
+
+ test('truncateBreakdowns', function() {
+ const hist = tr.v.Histogram.create('a', unitlessNumber, {
+ value: 1,
+ diagnostics: {b: tr.v.d.Breakdown.fromEntries([
+ ['c', 1 / 3],
+ ])},
+ }, {
+ binBoundaries: tr.v.HistogramBinBoundaries.SINGULAR,
+ });
+ assert.strictEqual(0.3333, hist.allBins[0].diagnosticMaps[0].get(
+ 'b').get('c'));
+ });
+
+ test('createWithNameUnitNumber', function() {
+ const hist = tr.v.Histogram.create('a', unitlessNumber, 1);
+ assert.strictEqual(hist.name, 'a');
+ assert.strictEqual(hist.unit, unitlessNumber);
+ assert.lengthOf(hist.sampleValues, 1);
+ assert.strictEqual(hist.average, 1);
+ });
+
+ test('createWithSamples', function() {
+ const hist = tr.v.Histogram.create('', unitlessNumber, [
+ 1,
+ {value: 3, diagnostics: {a: new tr.v.d.GenericSet(['b'])}},
+ ]);
+ assert.lengthOf(hist.sampleValues, 2);
+ assert.strictEqual(hist.average, 2);
+
+ const bin = hist.getBinForValue(3);
+ assert.lengthOf(bin.diagnosticMaps, 1);
+ const sampleDiagnostics = tr.b.getOnlyElement(bin.diagnosticMaps);
+ assert.strictEqual(tr.b.getOnlyElement(sampleDiagnostics.get('a')), 'b');
+ });
+
+ test('createWithOptions', function() {
+ const hist = tr.v.Histogram.create('', unitlessNumber, [], {
+ binBoundaries: tr.v.HistogramBinBoundaries.SINGULAR,
+ description: 'foo',
+ diagnostics: {
+ generic: new tr.v.d.GenericSet(['occam']),
+ },
+ summaryOptions: {
+ count: false,
+ percentile: [0.5],
+ }
+ });
+ assert.strictEqual(hist.description, 'foo');
+ assert.strictEqual(tr.b.getOnlyElement(
+ hist.diagnostics.get('generic')), 'occam');
+ assert.isFalse(hist.summaryOptions.get('count'));
+ assert.strictEqual(tr.b.getOnlyElement(
+ hist.summaryOptions.get('percentile')), 0.5);
+ });
+
+ test('getStatisticScalar', function() {
+ const hist = new tr.v.Histogram('', unitlessNumber);
+ // getStatisticScalar should work even when the statistics are disabled.
+ hist.customizeSummaryOptions({
+ avg: false,
+ count: false,
+ max: false,
+ min: false,
+ std: false,
+ sum: false,
+ });
+
+ assert.isUndefined(hist.getStatisticScalar('avg'));
+ assert.isUndefined(hist.getStatisticScalar('std'));
+ assert.strictEqual(0, hist.getStatisticScalar('geometricMean').value);
+ assert.strictEqual(Infinity, hist.getStatisticScalar('min').value);
+ assert.strictEqual(-Infinity, hist.getStatisticScalar('max').value);
+ assert.strictEqual(0, hist.getStatisticScalar('sum').value);
+ assert.strictEqual(0, hist.getStatisticScalar('nans').value);
+ assert.strictEqual(0, hist.getStatisticScalar('count').value);
+ assert.isUndefined(hist.getStatisticScalar('pct_000'));
+ assert.isUndefined(hist.getStatisticScalar('pct_050'));
+ assert.isUndefined(hist.getStatisticScalar('pct_100'));
+
+ assert.isFalse(hist.canCompare());
+ assert.throws(() => hist.getStatisticScalar(tr.v.DELTA + 'avg'));
+
+ const ref = new tr.v.Histogram('', unitlessNumber);
+ for (let i = 0; i < 10; ++i) {
+ hist.addSample(i * 10);
+ ref.addSample(i);
+ }
+
+ assert.strictEqual(45, hist.getStatisticScalar('avg').value);
+ assert.closeTo(30.277, hist.getStatisticScalar('std').value, 1e-3);
+ assert.closeTo(0, hist.getStatisticScalar('geometricMean').value, 1e-4);
+ assert.strictEqual(0, hist.getStatisticScalar('min').value);
+ assert.strictEqual(90, hist.getStatisticScalar('max').value);
+ assert.strictEqual(450, hist.getStatisticScalar('sum').value);
+ assert.strictEqual(0, hist.getStatisticScalar('nans').value);
+ assert.strictEqual(10, hist.getStatisticScalar('count').value);
+ assert.closeTo(18.371, hist.getStatisticScalar('pct_025').value, 1e-3);
+ assert.closeTo(55.48, hist.getStatisticScalar('pct_075').value, 1e-3);
+ assert.closeTo(37.108, hist.getStatisticScalar('ipr_025_075').value, 1e-3);
+
+ assert.strictEqual(40.5, hist.getStatisticScalar(
+ tr.v.DELTA + 'avg', ref).value);
+ assert.closeTo(27.249, hist.getStatisticScalar(
+ tr.v.DELTA + 'std', ref).value, 1e-3);
+ assert.closeTo(0, hist.getStatisticScalar(
+ tr.v.DELTA + 'geometricMean', ref).value, 1e-4);
+ assert.strictEqual(0, hist.getStatisticScalar(
+ tr.v.DELTA + 'min', ref).value);
+ assert.strictEqual(81, hist.getStatisticScalar(
+ tr.v.DELTA + 'max', ref).value);
+ assert.strictEqual(405, hist.getStatisticScalar(
+ tr.v.DELTA + 'sum', ref).value);
+ assert.strictEqual(0, hist.getStatisticScalar(
+ tr.v.DELTA + 'nans', ref).value);
+ assert.strictEqual(0, hist.getStatisticScalar(
+ tr.v.DELTA + 'count', ref).value);
+ assert.closeTo(16.357, hist.getStatisticScalar(
+ tr.v.DELTA + 'pct_025', ref).value, 1e-3);
+ assert.closeTo(49.396, hist.getStatisticScalar(
+ tr.v.DELTA + 'pct_075', ref).value, 1e-3);
+ assert.closeTo(33.04, hist.getStatisticScalar(
+ tr.v.DELTA + 'ipr_025_075', ref).value, 1e-3);
+
+ assert.strictEqual(9, hist.getStatisticScalar(
+ `%${tr.v.DELTA}avg`, ref).value);
+ assert.closeTo(9, hist.getStatisticScalar(
+ `%${tr.v.DELTA}std`, ref).value, 1e-3);
+ assert.isTrue(isNaN(hist.getStatisticScalar(
+ `%${tr.v.DELTA}geometricMean`, ref).value));
+ assert.isTrue(isNaN(hist.getStatisticScalar(
+ `%${tr.v.DELTA}min`, ref).value));
+ assert.strictEqual(9, hist.getStatisticScalar(
+ `%${tr.v.DELTA}max`, ref).value);
+ assert.strictEqual(9, hist.getStatisticScalar(
+ `%${tr.v.DELTA}sum`, ref).value);
+ assert.isTrue(isNaN(hist.getStatisticScalar(
+ `%${tr.v.DELTA}nans`, ref).value));
+ assert.strictEqual(0, hist.getStatisticScalar(
+ `%${tr.v.DELTA}count`, ref).value);
+ assert.closeTo(8.12, hist.getStatisticScalar(
+ `%${tr.v.DELTA}pct_025`, ref).value, 1e-3);
+ assert.closeTo(8.12, hist.getStatisticScalar(
+ `%${tr.v.DELTA}pct_075`, ref).value, 1e-3);
+ assert.closeTo(8.12, hist.getStatisticScalar(
+ `%${tr.v.DELTA}ipr_025_075`, ref).value, 1e-3);
+ });
+
+ test('rebin', function() {
+ const hist = new tr.v.Histogram('foo', unitlessNumber_smallerIsBetter,
+ tr.v.HistogramBinBoundaries.SINGULAR);
+ assert.strictEqual(400, hist.maxNumSampleValues);
+ for (let i = 0; i < 100; ++i) {
+ hist.addSample(i);
+ }
+
+ let rebinned = hist.rebin(TEST_BOUNDARIES);
+ assert.strictEqual(12, rebinned.allBins.length);
+ assert.strictEqual(100, rebinned.allBins[1].count);
+ assert.strictEqual(hist.numValues, rebinned.numValues);
+ assert.strictEqual(hist.average, rebinned.average);
+ assert.strictEqual(hist.standardDeviation, rebinned.standardDeviation);
+ assert.strictEqual(hist.geometricMean, rebinned.geometricMean);
+ assert.strictEqual(hist.sum, rebinned.sum);
+ assert.strictEqual(hist.min, rebinned.min);
+ assert.strictEqual(hist.max, rebinned.max);
+
+ for (let i = 100; i < 1000; ++i) {
+ hist.addSample(i);
+ }
+
+ rebinned = hist.rebin(TEST_BOUNDARIES);
+ assert.strictEqual(12, rebinned.allBins.length);
+ let binCountSum = 0;
+ for (let i = 1; i < 11; ++i) {
+ binCountSum += rebinned.allBins[i].count;
+ assert.isAbove(100, rebinned.allBins[i].count, i);
+ }
+ assert.strictEqual(400, binCountSum);
+ assert.strictEqual(hist.numValues, rebinned.numValues);
+ assert.strictEqual(hist.average, rebinned.average);
+ assert.strictEqual(hist.standardDeviation, rebinned.standardDeviation);
+ assert.strictEqual(hist.geometricMean, rebinned.geometricMean);
+ assert.strictEqual(hist.sum, rebinned.sum);
+ assert.strictEqual(hist.min, rebinned.min);
+ assert.strictEqual(hist.max, rebinned.max);
+ });
+
+ test('serializationSize', function() {
+ // Ensure that serialized Histograms don't take up too much more space than
+ // necessary.
+ const hist = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
+
+ // You can change these numbers, but when you do, please explain in your CL
+ // description why they changed.
+ let dict = hist.asDict();
+ assert.strictEqual(61, JSON.stringify(dict).length);
+ assert.isUndefined(dict.allBins);
+ assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
+
+ hist.addSample(100);
+ dict = hist.asDict();
+ assert.strictEqual(142, JSON.stringify(dict).length);
+ assert.isUndefined(dict.allBins.length);
+ assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
+
+ hist.addSample(100);
+ dict = hist.asDict();
+ // SAMPLE_VALUES grew by "100,"
+ assert.strictEqual(146, JSON.stringify(dict).length);
+ assert.isUndefined(dict.allBins.length);
+ assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
+
+ hist.addSample(271, {foo: new tr.v.d.GenericSet(['bar'])});
+ dict = hist.asDict();
+ assert.strictEqual(212, JSON.stringify(dict).length);
+ assert.isUndefined(dict.allBins.length);
+ assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
+
+ // Add samples to most bins so that allBinsArray is more efficient than
+ // allBinsDict.
+ for (let i = 10; i < 100; ++i) {
+ hist.addSample(10 * i);
+ }
+ dict = hist.asDict();
+ assert.strictEqual(628, JSON.stringify(hist.asDict()).length);
+ assert.lengthOf(dict.allBins, 12);
+ assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
+
+ // Lowering maxNumSampleValues takes a random sub-sample of the existing
+ // sampleValues. We have deliberately set all samples to 3-digit numbers so
+ // that the serialized size is constant regardless of which samples are
+ // retained.
+ hist.maxNumSampleValues = 10;
+ dict = hist.asDict();
+ assert.strictEqual(320, JSON.stringify(dict).length);
+ assert.lengthOf(dict.allBins, 12);
+ assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
+ });
+
+ test('significance', function() {
+ const boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 10);
+ const histA = new tr.v.Histogram(
+ '', unitlessNumber_smallerIsBetter, boundaries);
+ const histB = new tr.v.Histogram(
+ '', unitlessNumber_smallerIsBetter, boundaries);
+
+ const dontCare = new tr.v.Histogram('', unitlessNumber, boundaries);
+ assert.strictEqual(dontCare.getDifferenceSignificance(dontCare),
+ tr.b.math.Statistics.Significance.DONT_CARE);
+
+ for (let i = 0; i < 100; ++i) {
+ histA.addSample(i);
+ histB.addSample(i * 0.85);
+ }
+
+ assert.strictEqual(histA.getDifferenceSignificance(histB),
+ tr.b.math.Statistics.Significance.INSIGNIFICANT);
+ assert.strictEqual(histB.getDifferenceSignificance(histA),
+ tr.b.math.Statistics.Significance.INSIGNIFICANT);
+ assert.strictEqual(histA.getDifferenceSignificance(histB, 0.1),
+ tr.b.math.Statistics.Significance.SIGNIFICANT);
+ assert.strictEqual(histB.getDifferenceSignificance(histA, 0.1),
+ tr.b.math.Statistics.Significance.SIGNIFICANT);
+ });
+
+ test('basic', function() {
+ const hist = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
+ assert.strictEqual(hist.getBinForValue(250).range.min, 200);
+ assert.strictEqual(hist.getBinForValue(250).range.max, 300);
+
+ hist.addSample(-1, {foo: new tr.v.d.GenericSet(['a'])});
+ hist.addSample(0, {foo: new tr.v.d.GenericSet(['b'])});
+ hist.addSample(0, {foo: new tr.v.d.GenericSet(['c'])});
+ hist.addSample(500, {foo: new tr.v.d.GenericSet(['c'])});
+ hist.addSample(999, {foo: new tr.v.d.GenericSet(['d'])});
+ hist.addSample(1000, {foo: new tr.v.d.GenericSet(['d'])});
+ assert.strictEqual(hist.allBins[0].count, 1);
+
+ assert.strictEqual(hist.getBinForValue(0).count, 2);
+ assert.deepEqual(
+ hist.getBinForValue(0).diagnosticMaps.map(dm =>
+ tr.b.getOnlyElement(dm.get('foo'))), ['b', 'c']);
+
+ assert.strictEqual(hist.getBinForValue(500).count, 1);
+ assert.strictEqual(hist.getBinForValue(999).count, 1);
+
+ assert.strictEqual(hist.allBins[hist.allBins.length - 1].count, 1);
+ assert.strictEqual(hist.numValues, 6);
+ assert.closeTo(hist.average, 416.3, 0.1);
+ });
+
+ test('nans', function() {
+ const hist = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
+
+ hist.addSample(undefined, {foo: new tr.v.d.GenericSet(['b'])});
+ hist.addSample(NaN, {'foo': new tr.v.d.GenericSet(['c'])});
+ hist.addSample(undefined);
+ hist.addSample(NaN);
+
+ assert.strictEqual(hist.numNans, 4);
+ assert.deepEqual(hist.nanDiagnosticMaps.map(dm =>
+ tr.b.getOnlyElement(dm.get('foo'))), ['b', 'c']);
+
+ const hist2 = tr.v.Histogram.fromDict(hist.asDict());
+ assert.instanceOf(hist2.nanDiagnosticMaps[0], tr.v.d.DiagnosticMap);
+ assert.instanceOf(hist2.nanDiagnosticMaps[0].get('foo'), tr.v.d.GenericSet);
+ });
+
+ test('addHistogramsValid', function() {
+ const hist0 = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
+ const hist1 = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
+
+ hist0.addSample(-1, {foo: new tr.v.d.GenericSet(['a0'])});
+ hist0.addSample(0, {foo: new tr.v.d.GenericSet(['b0'])});
+ hist0.addSample(0, {foo: new tr.v.d.GenericSet(['c0'])});
+ hist0.addSample(500, {foo: new tr.v.d.GenericSet(['c0'])});
+ hist0.addSample(1000, {foo: new tr.v.d.GenericSet(['d0'])});
+ hist0.addSample(NaN, {foo: new tr.v.d.GenericSet(['e0'])});
+
+ hist1.addSample(-1, {foo: new tr.v.d.GenericSet(['a1'])});
+ hist1.addSample(0, {foo: new tr.v.d.GenericSet(['b1'])});
+ hist1.addSample(0, {foo: new tr.v.d.GenericSet(['c1'])});
+ hist1.addSample(999, {foo: new tr.v.d.GenericSet(['d1'])});
+ hist1.addSample(1000, {foo: new tr.v.d.GenericSet(['d1'])});
+ hist1.addSample(NaN, {foo: new tr.v.d.GenericSet(['e1'])});
+
+ hist0.addHistogram(hist1);
+
+ assert.strictEqual(hist0.numNans, 2);
+ assert.deepEqual(hist0.nanDiagnosticMaps.map(dmd =>
+ tr.b.getOnlyElement(dmd.get('foo'))), ['e0', 'e1']);
+
+ assert.strictEqual(hist0.allBins[0].count, 2);
+ assert.deepEqual(
+ hist0.allBins[0].diagnosticMaps.map(dmd =>
+ tr.b.getOnlyElement(dmd.get('foo'))), ['a0', 'a1']);
+
+ assert.strictEqual(hist0.getBinForValue(0).count, 4);
+ assert.deepEqual(
+ hist0.getBinForValue(0).diagnosticMaps.map(dmd =>
+ tr.b.getOnlyElement(dmd.get('foo'))), ['b0', 'c0', 'b1', 'c1']);
+
+ assert.strictEqual(hist0.getBinForValue(500).count, 1);
+ assert.deepEqual(
+ hist0.getBinForValue(500).diagnosticMaps.map(dmd =>
+ tr.b.getOnlyElement(dmd.get('foo'))), ['c0']);
+
+ assert.strictEqual(hist0.getBinForValue(999).count, 1);
+ assert.deepEqual(
+ hist0.getBinForValue(999).diagnosticMaps.map(dmd =>
+ tr.b.getOnlyElement(dmd.get('foo'))), ['d1']);
+
+ assert.strictEqual(hist0.allBins[hist0.allBins.length - 1].count, 2);
+ assert.deepEqual(hist0.allBins[hist0.allBins.length - 1].diagnosticMaps.map(
+ dmd => tr.b.getOnlyElement(dmd.get('foo'))), ['d0', 'd1']);
+
+ assert.strictEqual(hist0.numValues, 10);
+ assert.closeTo(hist0.average, 349.7, 0.1);
+
+ const hist02 = tr.v.Histogram.fromDict(hist0.asDict());
+ assert.instanceOf(hist02.allBins[0].diagnosticMaps[0],
+ tr.v.d.DiagnosticMap);
+ assert.instanceOf(hist02.allBins[0].diagnosticMaps[0].get('foo'),
+ tr.v.d.GenericSet);
+ });
+
+ test('addHistogramsInvalid', function() {
+ const hist0 = new tr.v.Histogram('', tr.b.Unit.byName.timeDurationInMs,
+ tr.v.HistogramBinBoundaries.createLinear(0, 1000, 10));
+ const hist1 = new tr.v.Histogram('', tr.b.Unit.byName.timeDurationInMs,
+ tr.v.HistogramBinBoundaries.createLinear(0, 1001, 10));
+ const hist2 = new tr.v.Histogram('', tr.b.Unit.byName.timeDurationInMs,
+ tr.v.HistogramBinBoundaries.createLinear(0, 1000, 11));
+
+ assert.isFalse(hist0.canAddHistogram(hist1));
+ assert.isFalse(hist0.canAddHistogram(hist2));
+ assert.isFalse(hist1.canAddHistogram(hist0));
+ assert.isFalse(hist1.canAddHistogram(hist2));
+ assert.isFalse(hist2.canAddHistogram(hist0));
+ assert.isFalse(hist2.canAddHistogram(hist1));
+
+ assert.throws(hist0.addHistogram.bind(hist0, hist1), Error);
+ assert.throws(hist0.addHistogram.bind(hist0, hist2), Error);
+ });
+
+ test('addHistogramWithNonDiagnosticMapThrows', function() {
+ const hist = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
+ assert.throws(hist.addSample.bind(42, 'foo'), Error);
+ });
+
+ test('getApproximatePercentile', function() {
+ function check(array, min, max, bins, precision) {
+ const boundaries = tr.v.HistogramBinBoundaries.createLinear(
+ min, max, bins);
+ const hist = new tr.v.Histogram(
+ '', tr.b.Unit.byName.timeDurationInMs, boundaries);
+ array.forEach(x => hist.addSample(
+ x, {foo: new tr.v.d.GenericSet(['x'])}));
+ [0.25, 0.5, 0.75, 0.8, 0.95, 0.99].forEach(function(percent) {
+ const expected = tr.b.math.Statistics.percentile(array, percent);
+ const actual = hist.getApproximatePercentile(percent);
+ assert.closeTo(expected, actual, precision);
+ });
+ }
+ check([1, 2, 5, 7], 0.5, 10.5, 10, 1e-3);
+ check([3, 3, 4, 4], 0.5, 10.5, 10, 1e-3);
+ check([1, 10], 0.5, 10.5, 10, 1e-3);
+ check([1, 2, 3, 4, 5], 0.5, 10.5, 10, 1e-3);
+ check([3, 3, 3, 3, 3], 0.5, 10.5, 10, 1e-3);
+ check([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0.5, 10.5, 10, 1e-3);
+ check([1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10], 0.5, 10.5, 10, 1e-3);
+ check([0, 11], 0.5, 10.5, 10, 1);
+ check([0, 6, 11], 0.5, 10.5, 10, 1);
+ const array = [];
+ for (let i = 0; i < 1000; i++) {
+ array.push((i * i) % 10 + 1);
+ }
+ check(array, 0.5, 10.5, 10, 1e-3);
+ // If the real percentile is outside the bin range then the approximation
+ // error can be high.
+ check([-10000], 0, 10, 10, 10000);
+ check([10000], 0, 10, 10, 10000 - 10);
+ // The result is no more than the bin width away from the real percentile.
+ check([1, 1], 0, 10, 1, 10);
+ });
+
+ test('histogramBinBoundaries_addBinBoundary', function() {
+ const b = new tr.v.HistogramBinBoundaries(-100);
+ b.addBinBoundary(50);
+
+ checkBoundaries(b, -100, 50, tr.b.Unit.byName.timeDurationInMs, [
+ tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -100),
+ tr.b.math.Range.fromExplicitRange(-100, 50),
+ tr.b.math.Range.fromExplicitRange(50, Number.MAX_VALUE)
+ ]);
+
+ b.addBinBoundary(60);
+ b.addBinBoundary(75);
+
+ checkBoundaries(b, -100, 75, tr.b.Unit.byName.timeDurationInMs, [
+ tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -100),
+ tr.b.math.Range.fromExplicitRange(-100, 50),
+ tr.b.math.Range.fromExplicitRange(50, 60),
+ tr.b.math.Range.fromExplicitRange(60, 75),
+ tr.b.math.Range.fromExplicitRange(75, Number.MAX_VALUE)
+ ]);
+ });
+
+ test('histogramBinBoundaries_addLinearBins', function() {
+ const b = new tr.v.HistogramBinBoundaries(1000);
+ b.addLinearBins(1200, 5);
+
+ checkBoundaries(b, 1000, 1200, tr.b.Unit.byName.powerInWatts, [
+ tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, 1000),
+ tr.b.math.Range.fromExplicitRange(1000, 1040),
+ tr.b.math.Range.fromExplicitRange(1040, 1080),
+ tr.b.math.Range.fromExplicitRange(1080, 1120),
+ tr.b.math.Range.fromExplicitRange(1120, 1160),
+ tr.b.math.Range.fromExplicitRange(1160, 1200),
+ tr.b.math.Range.fromExplicitRange(1200, Number.MAX_VALUE)
+ ]);
+ });
+
+ test('histogramBinBoundaries_addExponentialBins', function() {
+ const b = new tr.v.HistogramBinBoundaries(0.5);
+ b.addExponentialBins(8, 4);
+
+ checkBoundaries(b, 0.5, 8, tr.b.Unit.byName.energyInJoules, [
+ tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, 0.5),
+ tr.b.math.Range.fromExplicitRange(0.5, 1),
+ tr.b.math.Range.fromExplicitRange(1, 2),
+ tr.b.math.Range.fromExplicitRange(2, 4),
+ tr.b.math.Range.fromExplicitRange(4, 8),
+ tr.b.math.Range.fromExplicitRange(8, Number.MAX_VALUE)
+ ]);
+ });
+
+ test('histogramBinBoundaries_combined', function() {
+ const b = new tr.v.HistogramBinBoundaries(-273.15);
+ b.addBinBoundary(-50);
+ b.addLinearBins(4, 3);
+ b.addExponentialBins(16, 2);
+ b.addLinearBins(17, 4);
+ b.addBinBoundary(100);
+
+ checkBoundaries(b, -273.15, 100, tr.b.Unit.byName.unitlessNumber, [
+ tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -273.15),
+ tr.b.math.Range.fromExplicitRange(-273.15, -50),
+ tr.b.math.Range.fromExplicitRange(-50, -32),
+ tr.b.math.Range.fromExplicitRange(-32, -14),
+ tr.b.math.Range.fromExplicitRange(-14, 4),
+ tr.b.math.Range.fromExplicitRange(4, 8),
+ tr.b.math.Range.fromExplicitRange(8, 16),
+ tr.b.math.Range.fromExplicitRange(16, 16.25),
+ tr.b.math.Range.fromExplicitRange(16.25, 16.5),
+ tr.b.math.Range.fromExplicitRange(16.5, 16.75),
+ tr.b.math.Range.fromExplicitRange(16.75, 17),
+ tr.b.math.Range.fromExplicitRange(17, 100),
+ tr.b.math.Range.fromExplicitRange(100, Number.MAX_VALUE)
+ ]);
+ });
+
+ test('histogramBinBoundaries_throws', function() {
+ const b0 = new tr.v.HistogramBinBoundaries(-7);
+ assert.throws(function() { b0.addBinBoundary(-10 /* must be > -7 */); });
+ assert.throws(function() { b0.addBinBoundary(-7 /* must be > -7 */); });
+ assert.throws(function() { b0.addLinearBins(-10 /* must be > -7 */, 10); });
+ assert.throws(function() { b0.addLinearBins(-7 /* must be > -7 */, 100); });
+ assert.throws(function() { b0.addLinearBins(10, 0 /* must be > 0 */); });
+ assert.throws(function() {
+ // Current max bin boundary (-7) must be positive.
+ b0.addExponentialBins(16, 4);
+ });
+
+ const b1 = new tr.v.HistogramBinBoundaries(8);
+ assert.throws(() => b1.addExponentialBins(20, 0 /* must be > 0 */));
+ assert.throws(() => b1.addExponentialBins(5 /* must be > 8 */, 3));
+ assert.throws(() => b1.addExponentialBins(8 /* must be > 8 */, 3));
+ });
+
+ test('statisticsScalars', function() {
+ const boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 100);
+ let hist = new tr.v.Histogram('', unitlessNumber, boundaries);
+
+ hist.addSample(50);
+ hist.addSample(60);
+ hist.addSample(70);
+ hist.addSample('i am not a number');
+
+ hist.customizeSummaryOptions({
+ count: true,
+ min: true,
+ max: true,
+ sum: true,
+ avg: true,
+ std: true,
+ nans: true,
+ geometricMean: true,
+ percentile: [0.5, 1]
+ });
+
+ // Test round-tripping summaryOptions.
+ hist = tr.v.Histogram.fromDict(hist.asDict());
+
+ const stats = hist.statisticsScalars;
+ assert.strictEqual(stats.get('nans').unit,
+ tr.b.Unit.byName.count_smallerIsBetter);
+ assert.strictEqual(stats.get('nans').value, 1);
+ assert.strictEqual(stats.get('count').unit,
+ tr.b.Unit.byName.count_smallerIsBetter);
+ assert.strictEqual(stats.get('count').value, 3);
+ assert.strictEqual(stats.get('min').unit, hist.unit);
+ assert.strictEqual(stats.get('min').value, 50);
+ assert.strictEqual(stats.get('max').unit, hist.unit);
+ assert.strictEqual(stats.get('max').value, 70);
+ assert.strictEqual(stats.get('sum').unit, hist.unit);
+ assert.strictEqual(stats.get('sum').value, 180);
+ assert.strictEqual(stats.get('avg').unit, hist.unit);
+ assert.strictEqual(stats.get('avg').value, 60);
+ assert.strictEqual(stats.get('std').value, 10);
+ assert.strictEqual(stats.get('pct_050').unit, hist.unit);
+ assert.closeTo(stats.get('pct_050').value, 60, 1);
+ assert.strictEqual(stats.get('pct_100').unit, hist.unit);
+ assert.closeTo(stats.get('pct_100').value, 70, 1);
+ assert.strictEqual(stats.get('geometricMean').unit, hist.unit);
+ assert.closeTo(stats.get('geometricMean').value, 59.439, 1e-3);
+ });
+
+ test('statisticsScalarsNoSummaryOptions', function() {
+ const boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 100);
+ const hist = new tr.v.Histogram('', unitlessNumber, boundaries);
+
+ hist.addSample(50);
+ hist.addSample(60);
+ hist.addSample(70);
+
+ hist.customizeSummaryOptions({
+ count: false,
+ min: false,
+ max: false,
+ sum: false,
+ avg: false,
+ std: false,
+ percentile: []
+ });
+
+ assert.strictEqual(hist.statisticsScalars.size, 0);
+ });
+
+ test('statisticsScalarsEmptyHistogram', function() {
+ const boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 100);
+ const hist = new tr.v.Histogram('', unitlessNumber, boundaries);
+ hist.customizeSummaryOptions({
+ count: true,
+ min: true,
+ max: true,
+ sum: true,
+ avg: true,
+ std: true,
+ percentile: [0, 0.01, 0.1, 0.5, 0.995, 1]
+ });
+
+ const stats = hist.statisticsScalars;
+ assert.strictEqual(stats.get('count').value, 0);
+ assert.strictEqual(stats.get('min').value, Infinity);
+ assert.strictEqual(stats.get('max').value, -Infinity);
+ assert.strictEqual(stats.get('sum').value, 0);
+ assert.strictEqual(stats.get('avg'), undefined);
+ assert.strictEqual(stats.get('std'), undefined);
+ assert.isUndefined(stats.get('pct_000'));
+ assert.isUndefined(stats.get('pct_001'));
+ assert.isUndefined(stats.get('pct_010'));
+ assert.isUndefined(stats.get('pct_050'));
+ assert.isUndefined(stats.get('pct_099_5'));
+ assert.isUndefined(stats.get('pct_100'));
+ });
+
+ test('sampleValues', function() {
+ const boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 1000, 50);
+ const hist0 = new tr.v.Histogram('', unitlessNumber, boundaries);
+ const hist1 = new tr.v.Histogram('', unitlessNumber, boundaries);
+ // maxNumSampleValues defaults to numBins * 10, which, including the
+ // underflow bin and overflow bin plus this builder's 10 central bins,
+ // is 52 * 10.
+ assert.strictEqual(hist0.maxNumSampleValues, 520);
+ assert.strictEqual(hist1.maxNumSampleValues, 520);
+ const values0 = [];
+ const values1 = [];
+ for (let i = 0; i < 10; ++i) {
+ values0.push(i);
+ hist0.addSample(i);
+ }
+ for (let i = 10; i < 20; ++i) {
+ values1.push(i);
+ hist1.addSample(i);
+ }
+ assert.deepEqual(hist0.sampleValues, values0);
+ assert.deepEqual(hist1.sampleValues, values1);
+ hist0.addHistogram(hist1);
+ assert.deepEqual(hist0.sampleValues, values0.concat(values1));
+ const hist2 = tr.v.Histogram.fromDict(hist0.asDict());
+ assert.deepEqual(hist2.sampleValues, values0.concat(values1));
+
+ for (let i = 0; i < 500; ++i) {
+ hist0.addSample(i);
+ }
+ assert.strictEqual(hist0.sampleValues.length, hist0.maxNumSampleValues);
+
+ const hist3 = new tr.v.Histogram('', unitlessNumber, boundaries);
+ hist3.maxNumSampleValues = 10;
+ for (let i = 0; i < 100; ++i) {
+ hist3.addSample(i);
+ }
+ assert.strictEqual(hist3.sampleValues.length, 10);
+ });
+
+ test('singularBin', function() {
+ const hist = new tr.v.Histogram('', unitlessNumber,
+ tr.v.HistogramBinBoundaries.SINGULAR);
+ assert.lengthOf(hist.allBins, 1);
+
+ const dict = hist.asDict();
+ assert.isUndefined(dict.binBoundaries);
+ const clone = tr.v.Histogram.fromDict(dict);
+ assert.lengthOf(clone.allBins, 1);
+ assert.deepEqual(dict, clone.asDict());
+
+ assert.isUndefined(hist.getApproximatePercentile(0));
+ assert.isUndefined(hist.getApproximatePercentile(1));
+ hist.addSample(0);
+ assert.strictEqual(0, hist.getApproximatePercentile(0));
+ assert.strictEqual(0, hist.getApproximatePercentile(1));
+ hist.addSample(1);
+ assert.strictEqual(0, hist.getApproximatePercentile(0));
+ assert.strictEqual(1, hist.getApproximatePercentile(1));
+ hist.addSample(2);
+ assert.strictEqual(0, hist.getApproximatePercentile(0));
+ assert.strictEqual(1, hist.getApproximatePercentile(0.5));
+ assert.strictEqual(2, hist.getApproximatePercentile(1));
+ hist.addSample(3);
+ assert.strictEqual(0, hist.getApproximatePercentile(0));
+ assert.strictEqual(1, hist.getApproximatePercentile(0.5));
+ assert.strictEqual(2, hist.getApproximatePercentile(0.9));
+ assert.strictEqual(3, hist.getApproximatePercentile(1));
+ hist.addSample(4);
+ assert.strictEqual(0, hist.getApproximatePercentile(0));
+ assert.strictEqual(1, hist.getApproximatePercentile(0.4));
+ assert.strictEqual(2, hist.getApproximatePercentile(0.7));
+ assert.strictEqual(3, hist.getApproximatePercentile(0.9));
+ assert.strictEqual(4, hist.getApproximatePercentile(1));
+ });
+
+ test('singularBin_with_multiBin', function() {
+ const multiBin = new tr.v.Histogram('', unitlessNumber);
+ const singleBin = new tr.v.Histogram('', unitlessNumber,
+ tr.v.HistogramBinBoundaries.SINGULAR);
+ multiBin.addSample(1);
+ singleBin.addSample(3);
+ assert.strictEqual(1, multiBin.average);
+ assert.strictEqual(3, singleBin.average);
+ multiBin.addHistogram(singleBin);
+ assert.strictEqual(2, multiBin.average);
+ multiBin.addSample(1);
+ singleBin.addHistogram(multiBin);
+ assert.strictEqual(2, singleBin.average);
+ });
+
+ test('mergeSummaryOptions', function() {
+ const hist0 = new tr.v.Histogram('', unitlessNumber);
+ const hist1 = new tr.v.Histogram('', unitlessNumber);
+
+ hist0.customizeSummaryOptions({
+ sum: false,
+ percentile: [0.1, 0.9],
+ iprs: [
+ tr.b.math.Range.fromExplicitRange(0.1, 0.9),
+ tr.b.math.Range.fromExplicitRange(0.25, 0.75),
+ ],
+ });
+ hist1.customizeSummaryOptions({
+ min: false,
+ percentile: [0.1, 0.95],
+ iprs: [
+ tr.b.math.Range.fromExplicitRange(0.1, 0.9),
+ tr.b.math.Range.fromExplicitRange(0.2, 0.8),
+ ],
+ });
+
+ let merged = tr.v.Histogram.fromDict(hist0.asDict());
+ let mergedIprs = merged.summaryOptions.get('iprs');
+ assert.isTrue(merged.summaryOptions.get('min'));
+ assert.isFalse(merged.summaryOptions.get('sum'));
+ assert.deepEqual(merged.summaryOptions.get('percentile'), [0.1, 0.9]);
+ assert.lengthOf(merged.summaryOptions.get('iprs'), 2);
+ tr.b.assertRangeEquals(
+ mergedIprs[0], tr.b.math.Range.fromExplicitRange(0.1, 0.9));
+ tr.b.assertRangeEquals(
+ mergedIprs[1], tr.b.math.Range.fromExplicitRange(0.25, 0.75));
+
+ merged = tr.v.Histogram.fromDict(hist1.asDict());
+ mergedIprs = merged.summaryOptions.get('iprs');
+ assert.isFalse(merged.summaryOptions.get('min'));
+ assert.isTrue(merged.summaryOptions.get('sum'));
+ assert.deepEqual(merged.summaryOptions.get('percentile'), [0.1, 0.95]);
+ assert.lengthOf(merged.summaryOptions.get('iprs'), 2);
+ tr.b.assertRangeEquals(
+ mergedIprs[0], tr.b.math.Range.fromExplicitRange(0.1, 0.9));
+ tr.b.assertRangeEquals(
+ mergedIprs[1], tr.b.math.Range.fromExplicitRange(0.2, 0.8));
+
+ merged = hist0.clone();
+ merged.addHistogram(hist1);
+
+ assert.isTrue(merged.summaryOptions.get('min'));
+ assert.isTrue(merged.summaryOptions.get('sum'));
+ assert.deepEqual(merged.summaryOptions.get('percentile'), [0.1, 0.9, 0.95]);
+ mergedIprs = merged.summaryOptions.get('iprs');
+ assert.lengthOf(mergedIprs, 3);
+ tr.b.assertRangeEquals(
+ mergedIprs[0], tr.b.math.Range.fromExplicitRange(0.1, 0.9));
+ tr.b.assertRangeEquals(
+ mergedIprs[1], tr.b.math.Range.fromExplicitRange(0.25, 0.75));
+ tr.b.assertRangeEquals(
+ mergedIprs[2], tr.b.math.Range.fromExplicitRange(0.2, 0.8));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py
new file mode 100644
index 00000000000..ab9b473e21c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histogram_unittest.py
@@ -0,0 +1,674 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import math
+import unittest
+
+from tracing.value import histogram
+from tracing.value.diagnostics import date_range
+from tracing.value.diagnostics import diagnostic
+from tracing.value.diagnostics import diagnostic_ref
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import related_event_set
+from tracing.value.diagnostics import related_name_map
+from tracing.value.diagnostics import reserved_infos
+from tracing.value.diagnostics import unmergeable_diagnostic_set as ums
+
+# pylint: disable=too-many-lines
+
+class PercentToStringUnittest(unittest.TestCase):
+ def testPercentToString(self):
+ with self.assertRaises(Exception) as ex:
+ histogram.PercentToString(-1)
+ self.assertEqual(str(ex.exception), 'percent must be in [0,1]')
+
+ with self.assertRaises(Exception) as ex:
+ histogram.PercentToString(2)
+ self.assertEqual(str(ex.exception), 'percent must be in [0,1]')
+
+ self.assertEqual(histogram.PercentToString(0), '000')
+ self.assertEqual(histogram.PercentToString(1), '100')
+
+ with self.assertRaises(Exception) as ex:
+ histogram.PercentToString(float('nan'))
+ self.assertEqual(str(ex.exception), 'Unexpected percent')
+
+ self.assertEqual(histogram.PercentToString(0.50), '050')
+ self.assertEqual(histogram.PercentToString(0.95), '095')
+
+
+class StatisticsUnittest(unittest.TestCase):
+ def testFindHighIndexInSortedArray(self):
+ self.assertEqual(histogram.FindHighIndexInSortedArray(
+ list(range(0, -10, -1)), lambda x: x + 5), 6)
+
+ def testUniformlySampleArray(self):
+ self.assertEqual(len(histogram.UniformlySampleArray(
+ list(range(10)), 5)), 5)
+
+ def testUniformlySampleStream(self):
+ samples = []
+ histogram.UniformlySampleStream(samples, 1, 'A', 5)
+ self.assertEqual(samples, ['A'])
+ histogram.UniformlySampleStream(samples, 2, 'B', 5)
+ histogram.UniformlySampleStream(samples, 3, 'C', 5)
+ histogram.UniformlySampleStream(samples, 4, 'D', 5)
+ histogram.UniformlySampleStream(samples, 5, 'E', 5)
+ self.assertEqual(samples, ['A', 'B', 'C', 'D', 'E'])
+ histogram.UniformlySampleStream(samples, 6, 'F', 5)
+ self.assertEqual(len(samples), 5)
+
+ samples = [0, 0, 0]
+ histogram.UniformlySampleStream(samples, 1, 'G', 5)
+ self.assertEqual(samples, ['G', 0, 0])
+
+ def testMergeSampledStreams(self):
+ samples = []
+ histogram.MergeSampledStreams(samples, 0, ['A'], 1, 5)
+ self.assertEqual(samples, ['A'])
+ histogram.MergeSampledStreams(samples, 1, ['B', 'C', 'D', 'E'], 4, 5)
+ self.assertEqual(samples, ['A', 'B', 'C', 'D', 'E'])
+ histogram.MergeSampledStreams(samples, 9, ['F', 'G', 'H', 'I', 'J'], 7, 5)
+ self.assertEqual(len(samples), 5)
+
+
+class RangeUnittest(unittest.TestCase):
+ def testAddValue(self):
+ r = histogram.Range()
+ self.assertEqual(r.empty, True)
+ r.AddValue(1)
+ self.assertEqual(r.empty, False)
+ self.assertEqual(r.min, 1)
+ self.assertEqual(r.max, 1)
+ self.assertEqual(r.center, 1)
+ r.AddValue(2)
+ self.assertEqual(r.empty, False)
+ self.assertEqual(r.min, 1)
+ self.assertEqual(r.max, 2)
+ self.assertEqual(r.center, 1.5)
+
+
+class RunningStatisticsUnittest(unittest.TestCase):
+ def _Run(self, data):
+ running = histogram.RunningStatistics()
+ for datum in data:
+ running.Add(datum)
+ return running
+
+ def testStatistics(self):
+ running = self._Run([1, 2, 3])
+ self.assertEqual(running.sum, 6)
+ self.assertEqual(running.mean, 2)
+ self.assertEqual(running.min, 1)
+ self.assertEqual(running.max, 3)
+ self.assertEqual(running.variance, 1)
+ self.assertEqual(running.stddev, 1)
+ self.assertEqual(running.geometric_mean, math.pow(6, 1./3))
+ self.assertEqual(running.count, 3)
+
+ running = self._Run([2, 4, 4, 2])
+ self.assertEqual(running.sum, 12)
+ self.assertEqual(running.mean, 3)
+ self.assertEqual(running.min, 2)
+ self.assertEqual(running.max, 4)
+ self.assertEqual(running.variance, 4./3)
+ self.assertEqual(running.stddev, math.sqrt(4./3))
+ self.assertAlmostEqual(running.geometric_mean, math.pow(64, 1./4))
+ self.assertEqual(running.count, 4)
+
+ def testMerge(self):
+ def Compare(data1, data2):
+ a_running = self._Run(data1 + data2)
+ b_running = self._Run(data1).Merge(self._Run(data2))
+ CompareRunningStatistics(a_running, b_running)
+ a_running = histogram.RunningStatistics.FromDict(a_running.AsDict())
+ CompareRunningStatistics(a_running, b_running)
+ b_running = histogram.RunningStatistics.FromDict(b_running.AsDict())
+ CompareRunningStatistics(a_running, b_running)
+
+ def CompareRunningStatistics(a_running, b_running):
+ self.assertEqual(a_running.sum, b_running.sum)
+ self.assertEqual(a_running.mean, b_running.mean)
+ self.assertEqual(a_running.min, b_running.min)
+ self.assertEqual(a_running.max, b_running.max)
+ self.assertAlmostEqual(a_running.variance, b_running.variance)
+ self.assertAlmostEqual(a_running.stddev, b_running.stddev)
+ self.assertAlmostEqual(a_running.geometric_mean, b_running.geometric_mean)
+ self.assertEqual(a_running.count, b_running.count)
+
+ Compare([], [])
+ Compare([], [1, 2, 3])
+ Compare([1, 2, 3], [])
+ Compare([1, 2, 3], [10, 20, 100])
+ Compare([1, 1, 1, 1, 1], [10, 20, 10, 40])
+
+
+def ToJSON(x):
+ return json.dumps(x, separators=(',', ':'), sort_keys=True)
+
+
+class HistogramUnittest(unittest.TestCase):
+ TEST_BOUNDARIES = histogram.HistogramBinBoundaries.CreateLinear(0, 1000, 10)
+
+ def assertDeepEqual(self, a, b):
+ self.assertEqual(ToJSON(a), ToJSON(b))
+
+ def testDefaultBoundaries(self):
+ hist = histogram.Histogram('', 'ms')
+ self.assertEqual(len(hist.bins), 102)
+
+ hist = histogram.Histogram('', 'tsMs')
+ self.assertEqual(len(hist.bins), 1002)
+
+ hist = histogram.Histogram('', 'n%')
+ self.assertEqual(len(hist.bins), 22)
+
+ hist = histogram.Histogram('', 'sizeInBytes')
+ self.assertEqual(len(hist.bins), 102)
+
+ hist = histogram.Histogram('', 'J')
+ self.assertEqual(len(hist.bins), 52)
+
+ hist = histogram.Histogram('', 'W')
+ self.assertEqual(len(hist.bins), 52)
+
+ hist = histogram.Histogram('', 'unitless')
+ self.assertEqual(len(hist.bins), 52)
+
+ hist = histogram.Histogram('', 'count')
+ self.assertEqual(len(hist.bins), 22)
+
+ hist = histogram.Histogram('', 'sigma')
+ self.assertEqual(len(hist.bins), 52)
+
+ hist = histogram.Histogram('', 'sigma_smallerIsBetter')
+ self.assertEqual(len(hist.bins), 52)
+
+ hist = histogram.Histogram('', 'sigma_biggerIsBetter')
+ self.assertEqual(len(hist.bins), 52)
+
+ def testSerializationSize(self):
+ hist = histogram.Histogram('', 'unitless', self.TEST_BOUNDARIES)
+ d = hist.AsDict()
+ self.assertEqual(61, len(ToJSON(d)))
+ self.assertIsNone(d.get('allBins'))
+ self.assertDeepEqual(d, histogram.Histogram.FromDict(d).AsDict())
+
+ hist.AddSample(100)
+ d = hist.AsDict()
+ self.assertEqual(152, len(ToJSON(d)))
+ self.assertIsInstance(d['allBins'], dict)
+ self.assertDeepEqual(d, histogram.Histogram.FromDict(d).AsDict())
+
+ hist.AddSample(100)
+ d = hist.AsDict()
+ # SAMPLE_VALUES grew by "100,"
+ self.assertEqual(156, len(ToJSON(d)))
+ self.assertIsInstance(d['allBins'], dict)
+ self.assertDeepEqual(d, histogram.Histogram.FromDict(d).AsDict())
+
+ hist.AddSample(271, {'foo': generic_set.GenericSet(['bar'])})
+ d = hist.AsDict()
+ self.assertEqual(222, len(ToJSON(d)))
+ self.assertIsInstance(d['allBins'], dict)
+ self.assertDeepEqual(d, histogram.Histogram.FromDict(d).AsDict())
+
+ # Add samples to most bins so that allBinsArray is more efficient than
+ # allBinsDict.
+ for i in range(10, 100):
+ hist.AddSample(10 * i)
+ d = hist.AsDict()
+ self.assertEqual(651, len(ToJSON(d)))
+ self.assertIsInstance(d['allBins'], list)
+ self.assertDeepEqual(d, histogram.Histogram.FromDict(d).AsDict())
+
+ # Lowering maxNumSampleValues takes a random sub-sample of the existing
+ # sampleValues. We have deliberately set all samples to 3-digit numbers so
+ # that the serialized size is constant regardless of which samples are
+ # retained.
+ hist.max_num_sample_values = 10
+ d = hist.AsDict()
+ self.assertEqual(343, len(ToJSON(d)))
+ self.assertIsInstance(d['allBins'], list)
+ self.assertDeepEqual(d, histogram.Histogram.FromDict(d).AsDict())
+
+ def testBasic(self):
+ hist = histogram.Histogram('', 'unitless', self.TEST_BOUNDARIES)
+ self.assertEqual(hist.GetBinForValue(250).range.min, 200)
+ self.assertEqual(hist.GetBinForValue(250).range.max, 300)
+
+ hist.AddSample(-1)
+ hist.AddSample(0)
+ hist.AddSample(0)
+ hist.AddSample(500)
+ hist.AddSample(999)
+ hist.AddSample(1000)
+ self.assertEqual(hist.bins[0].count, 1)
+
+ self.assertEqual(hist.GetBinForValue(0).count, 2)
+ self.assertEqual(hist.GetBinForValue(500).count, 1)
+ self.assertEqual(hist.GetBinForValue(999).count, 1)
+ self.assertEqual(hist.bins[-1].count, 1)
+ self.assertEqual(hist.num_values, 6)
+ self.assertAlmostEqual(hist.average, 416.3333333)
+
+ def testNans(self):
+ hist = histogram.Histogram('', 'unitless', self.TEST_BOUNDARIES)
+ hist.AddSample(None)
+ hist.AddSample(float('nan'))
+ self.assertEqual(hist.num_nans, 2)
+
+ def testAddHistogramValid(self):
+ hist0 = histogram.Histogram('', 'unitless', self.TEST_BOUNDARIES)
+ hist1 = histogram.Histogram('', 'unitless', self.TEST_BOUNDARIES)
+ hist0.AddSample(0)
+ hist0.AddSample(None)
+ hist1.AddSample(1)
+ hist1.AddSample(float('nan'))
+ hist0.AddHistogram(hist1)
+ self.assertEqual(hist0.num_nans, 2)
+ self.assertEqual(hist0.GetBinForValue(0).count, 2)
+
+ def testAddHistogramInvalid(self):
+ hist0 = histogram.Histogram(
+ '', 'ms', histogram.HistogramBinBoundaries.CreateLinear(0, 1000, 10))
+ hist1 = histogram.Histogram(
+ '', 'unitless', histogram.HistogramBinBoundaries.CreateLinear(
+ 0, 1000, 10))
+ hist2 = histogram.Histogram(
+ '', 'ms', histogram.HistogramBinBoundaries.CreateLinear(0, 1001, 10))
+ hist3 = histogram.Histogram(
+ '', 'ms', histogram.HistogramBinBoundaries.CreateLinear(0, 1000, 11))
+ hists = [hist0, hist1, hist2, hist3]
+ for hista in hists:
+ for histb in hists:
+ if hista is histb:
+ continue
+ self.assertFalse(hista.CanAddHistogram(histb))
+ with self.assertRaises(Exception):
+ hista.AddHistogram(histb)
+
+ def testPercentile(self):
+ def Check(ary, mn, mx, bins, precision):
+ boundaries = histogram.HistogramBinBoundaries.CreateLinear(mn, mx, bins)
+ hist = histogram.Histogram('', 'ms', boundaries)
+ for x in ary:
+ hist.AddSample(x)
+ for percent in [0.25, 0.5, 0.75, 0.8, 0.95, 0.99]:
+ self.assertLessEqual(
+ abs(histogram.Percentile(ary, percent) -
+ hist.GetApproximatePercentile(percent)), precision)
+ Check([1, 2, 5, 7], 0.5, 10.5, 10, 1e-3)
+ Check([3, 3, 4, 4], 0.5, 10.5, 10, 1e-3)
+ Check([1, 10], 0.5, 10.5, 10, 1e-3)
+ Check([1, 2, 3, 4, 5], 0.5, 10.5, 10, 1e-3)
+ Check([3, 3, 3, 3, 3], 0.5, 10.5, 10, 1e-3)
+ Check([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0.5, 10.5, 10, 1e-3)
+ Check([1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10], 0.5, 10.5, 10, 1e-3)
+ Check([0, 11], 0.5, 10.5, 10, 1)
+ Check([0, 6, 11], 0.5, 10.5, 10, 1)
+ array = []
+ for i in range(1000):
+ array.append((i * i) % 10 + 1)
+ Check(array, 0.5, 10.5, 10, 1e-3)
+ # If the real percentile is outside the bin range then the approximation
+ # error can be high.
+ Check([-10000], 0, 10, 10, 10000)
+ Check([10000], 0, 10, 10, 10000 - 10)
+ # The result is no more than the bin width away from the real percentile.
+ Check([1, 1], 0, 10, 1, 10)
+
+ def _CheckBoundaries(self, boundaries, expected_min_boundary,
+ expected_max_boundary, expected_bin_ranges):
+ self.assertEqual(boundaries.range.min, expected_min_boundary)
+ self.assertEqual(boundaries.range.max, expected_max_boundary)
+
+ # Check that the boundaries can be used multiple times.
+ for _ in range(3):
+ hist = histogram.Histogram('', 'unitless', boundaries)
+ self.assertEqual(len(expected_bin_ranges), len(hist.bins))
+ for j, hbin in enumerate(hist.bins):
+ self.assertAlmostEqual(hbin.range.min, expected_bin_ranges[j].min)
+ self.assertAlmostEqual(hbin.range.max, expected_bin_ranges[j].max)
+
+ def testAddBinBoundary(self):
+ b = histogram.HistogramBinBoundaries(-100)
+ b.AddBinBoundary(50)
+ self._CheckBoundaries(b, -100, 50, [
+ histogram.Range.FromExplicitRange(-histogram.JS_MAX_VALUE, -100),
+ histogram.Range.FromExplicitRange(-100, 50),
+ histogram.Range.FromExplicitRange(50, histogram.JS_MAX_VALUE),
+ ])
+
+ b.AddBinBoundary(60)
+ b.AddBinBoundary(75)
+ self._CheckBoundaries(b, -100, 75, [
+ histogram.Range.FromExplicitRange(-histogram.JS_MAX_VALUE, -100),
+ histogram.Range.FromExplicitRange(-100, 50),
+ histogram.Range.FromExplicitRange(50, 60),
+ histogram.Range.FromExplicitRange(60, 75),
+ histogram.Range.FromExplicitRange(75, histogram.JS_MAX_VALUE),
+ ])
+
+ def testAddLinearBins(self):
+ b = histogram.HistogramBinBoundaries(1000)
+ b.AddLinearBins(1200, 5)
+ self._CheckBoundaries(b, 1000, 1200, [
+ histogram.Range.FromExplicitRange(-histogram.JS_MAX_VALUE, 1000),
+ histogram.Range.FromExplicitRange(1000, 1040),
+ histogram.Range.FromExplicitRange(1040, 1080),
+ histogram.Range.FromExplicitRange(1080, 1120),
+ histogram.Range.FromExplicitRange(1120, 1160),
+ histogram.Range.FromExplicitRange(1160, 1200),
+ histogram.Range.FromExplicitRange(1200, histogram.JS_MAX_VALUE),
+ ])
+
+ def testAddExponentialBins(self):
+ b = histogram.HistogramBinBoundaries(0.5)
+ b.AddExponentialBins(8, 4)
+ self._CheckBoundaries(b, 0.5, 8, [
+ histogram.Range.FromExplicitRange(-histogram.JS_MAX_VALUE, 0.5),
+ histogram.Range.FromExplicitRange(0.5, 1),
+ histogram.Range.FromExplicitRange(1, 2),
+ histogram.Range.FromExplicitRange(2, 4),
+ histogram.Range.FromExplicitRange(4, 8),
+ histogram.Range.FromExplicitRange(8, histogram.JS_MAX_VALUE),
+ ])
+
+ def testBinBoundariesCombined(self):
+ b = histogram.HistogramBinBoundaries(-273.15)
+ b.AddBinBoundary(-50)
+ b.AddLinearBins(4, 3)
+ b.AddExponentialBins(16, 2)
+ b.AddLinearBins(17, 4)
+ b.AddBinBoundary(100)
+
+ self._CheckBoundaries(b, -273.15, 100, [
+ histogram.Range.FromExplicitRange(-histogram.JS_MAX_VALUE, -273.15),
+ histogram.Range.FromExplicitRange(-273.15, -50),
+ histogram.Range.FromExplicitRange(-50, -32),
+ histogram.Range.FromExplicitRange(-32, -14),
+ histogram.Range.FromExplicitRange(-14, 4),
+ histogram.Range.FromExplicitRange(4, 8),
+ histogram.Range.FromExplicitRange(8, 16),
+ histogram.Range.FromExplicitRange(16, 16.25),
+ histogram.Range.FromExplicitRange(16.25, 16.5),
+ histogram.Range.FromExplicitRange(16.5, 16.75),
+ histogram.Range.FromExplicitRange(16.75, 17),
+ histogram.Range.FromExplicitRange(17, 100),
+ histogram.Range.FromExplicitRange(100, histogram.JS_MAX_VALUE)
+ ])
+
+ def testBinBoundariesRaises(self):
+ b = histogram.HistogramBinBoundaries(-7)
+ with self.assertRaises(Exception):
+ b.AddBinBoundary(-10)
+ with self.assertRaises(Exception):
+ b.AddBinBoundary(-7)
+ with self.assertRaises(Exception):
+ b.AddLinearBins(-10, 10)
+ with self.assertRaises(Exception):
+ b.AddLinearBins(-7, 10)
+ with self.assertRaises(Exception):
+ b.AddLinearBins(10, 0)
+ with self.assertRaises(Exception):
+ b.AddExponentialBins(16, 4)
+ b = histogram.HistogramBinBoundaries(8)
+ with self.assertRaises(Exception):
+ b.AddExponentialBins(20, 0)
+ with self.assertRaises(Exception):
+ b.AddExponentialBins(5, 3)
+ with self.assertRaises(Exception):
+ b.AddExponentialBins(8, 3)
+
+ def testStatisticsScalars(self):
+ b = histogram.HistogramBinBoundaries.CreateLinear(0, 100, 100)
+ hist = histogram.Histogram('', 'unitless', b)
+ hist.AddSample(50)
+ hist.AddSample(60)
+ hist.AddSample(70)
+ hist.AddSample('i am not a number')
+ hist.CustomizeSummaryOptions({
+ 'count': True,
+ 'min': True,
+ 'max': True,
+ 'sum': True,
+ 'avg': True,
+ 'std': True,
+ 'nans': True,
+ 'geometricMean': True,
+ 'percentile': [0.5, 1],
+ })
+
+ # Test round-tripping summaryOptions
+ hist = hist.Clone()
+ stats = hist.statistics_scalars
+ self.assertEqual(stats['nans'].unit, 'count')
+ self.assertEqual(stats['nans'].value, 1)
+ self.assertEqual(stats['count'].unit, 'count')
+ self.assertEqual(stats['count'].value, 3)
+ self.assertEqual(stats['min'].unit, hist.unit)
+ self.assertEqual(stats['min'].value, 50)
+ self.assertEqual(stats['max'].unit, hist.unit)
+ self.assertEqual(stats['max'].value, 70)
+ self.assertEqual(stats['sum'].unit, hist.unit)
+ self.assertEqual(stats['sum'].value, 180)
+ self.assertEqual(stats['avg'].unit, hist.unit)
+ self.assertEqual(stats['avg'].value, 60)
+ self.assertEqual(stats['std'].unit, hist.unit)
+ self.assertEqual(stats['std'].value, 10)
+ self.assertEqual(stats['pct_050'].unit, hist.unit)
+ self.assertEqual(stats['pct_050'].value, 60.5)
+ self.assertEqual(stats['pct_100'].unit, hist.unit)
+ self.assertEqual(stats['pct_100'].value, 70.5)
+ self.assertEqual(stats['geometricMean'].unit, hist.unit)
+ self.assertLess(abs(stats['geometricMean'].value - 59.439), 1e-3)
+
+ hist.CustomizeSummaryOptions({
+ 'count': False,
+ 'min': False,
+ 'max': False,
+ 'sum': False,
+ 'avg': False,
+ 'std': False,
+ 'nans': False,
+ 'geometricMean': False,
+ 'percentile': [],
+ })
+ self.assertEqual(0, len(hist.statistics_scalars))
+
+ def testStatisticsScalarsEmpty(self):
+ b = histogram.HistogramBinBoundaries.CreateLinear(0, 100, 100)
+ hist = histogram.Histogram('', 'unitless', b)
+ hist.CustomizeSummaryOptions({
+ 'count': True,
+ 'min': True,
+ 'max': True,
+ 'sum': True,
+ 'avg': True,
+ 'std': True,
+ 'nans': True,
+ 'geometricMean': True,
+ 'percentile': [0, 0.01, 0.1, 0.5, 0.995, 1],
+ })
+ stats = hist.statistics_scalars
+ self.assertEqual(stats['nans'].value, 0)
+ self.assertEqual(stats['count'].value, 0)
+ self.assertEqual(stats['min'].value, histogram.JS_MAX_VALUE)
+ self.assertEqual(stats['max'].value, -histogram.JS_MAX_VALUE)
+ self.assertEqual(stats['sum'].value, 0)
+ self.assertNotIn('avg', stats)
+ self.assertNotIn('stddev', stats)
+ self.assertEqual(stats['pct_000'].value, 0)
+ self.assertEqual(stats['pct_001'].value, 0)
+ self.assertEqual(stats['pct_010'].value, 0)
+ self.assertEqual(stats['pct_050'].value, 0)
+ self.assertEqual(stats['pct_099_5'].value, 0)
+ self.assertEqual(stats['pct_100'].value, 0)
+
+ def testSampleValues(self):
+ hist0 = histogram.Histogram('', 'unitless', self.TEST_BOUNDARIES)
+ hist1 = histogram.Histogram('', 'unitless', self.TEST_BOUNDARIES)
+ self.assertEqual(hist0.max_num_sample_values, 120)
+ self.assertEqual(hist1.max_num_sample_values, 120)
+ values0 = []
+ values1 = []
+ for i in range(10):
+ values0.append(i)
+ hist0.AddSample(i)
+ values1.append(10 + i)
+ hist1.AddSample(10 + i)
+ self.assertDeepEqual(hist0.sample_values, values0)
+ self.assertDeepEqual(hist1.sample_values, values1)
+ hist0.AddHistogram(hist1)
+ self.assertDeepEqual(hist0.sample_values, values0 + values1)
+ hist2 = hist0.Clone()
+ self.assertDeepEqual(hist2.sample_values, values0 + values1)
+
+ for i in range(200):
+ hist0.AddSample(i)
+ self.assertEqual(len(hist0.sample_values), hist0.max_num_sample_values)
+
+ hist3 = histogram.Histogram('', 'unitless', self.TEST_BOUNDARIES)
+ hist3.max_num_sample_values = 10
+ for i in range(100):
+ hist3.AddSample(i)
+ self.assertEqual(len(hist3.sample_values), 10)
+
+ def testSingularBin(self):
+ hist = histogram.Histogram(
+ '', 'unitless', histogram.HistogramBinBoundaries.SINGULAR)
+ self.assertEqual(1, len(hist.bins))
+ d = hist.AsDict()
+ self.assertNotIn('binBoundaries', d)
+ clone = histogram.Histogram.FromDict(d)
+ self.assertEqual(1, len(clone.bins))
+ self.assertDeepEqual(d, clone.AsDict())
+
+ self.assertEqual(0, hist.GetApproximatePercentile(0))
+ self.assertEqual(0, hist.GetApproximatePercentile(1))
+ hist.AddSample(0)
+ self.assertEqual(0, hist.GetApproximatePercentile(0))
+ self.assertEqual(0, hist.GetApproximatePercentile(1))
+ hist.AddSample(1)
+ self.assertEqual(0, hist.GetApproximatePercentile(0))
+ self.assertEqual(1, hist.GetApproximatePercentile(1))
+ hist.AddSample(2)
+ self.assertEqual(0, hist.GetApproximatePercentile(0))
+ self.assertEqual(1, hist.GetApproximatePercentile(0.5))
+ self.assertEqual(2, hist.GetApproximatePercentile(1))
+ hist.AddSample(3)
+ self.assertEqual(0, hist.GetApproximatePercentile(0))
+ self.assertEqual(1, hist.GetApproximatePercentile(0.5))
+ self.assertEqual(2, hist.GetApproximatePercentile(0.9))
+ self.assertEqual(3, hist.GetApproximatePercentile(1))
+ hist.AddSample(4)
+ self.assertEqual(0, hist.GetApproximatePercentile(0))
+ self.assertEqual(1, hist.GetApproximatePercentile(0.4))
+ self.assertEqual(2, hist.GetApproximatePercentile(0.7))
+ self.assertEqual(3, hist.GetApproximatePercentile(0.9))
+ self.assertEqual(4, hist.GetApproximatePercentile(1))
+
+
+class DiagnosticMapUnittest(unittest.TestCase):
+ def testDisallowReservedNames(self):
+ diagnostics = histogram.DiagnosticMap()
+ with self.assertRaises(TypeError):
+ diagnostics[None] = generic_set.GenericSet(())
+ with self.assertRaises(TypeError):
+ diagnostics['generic'] = None
+ diagnostics[reserved_infos.TRACE_URLS.name] = date_range.DateRange(0)
+ diagnostics.DisallowReservedNames()
+ diagnostics[reserved_infos.TRACE_URLS.name] = generic_set.GenericSet(())
+ with self.assertRaises(TypeError):
+ diagnostics[reserved_infos.TRACE_URLS.name] = date_range.DateRange(0)
+
+ def testResetGuid(self):
+ generic = generic_set.GenericSet(['generic diagnostic'])
+ guid1 = generic.guid
+ generic.ResetGuid()
+ guid2 = generic.guid
+ self.assertNotEqual(guid1, guid2)
+
+ # TODO(eakuefner): Find a better place for these non-map tests once we
+ # break up the Python implementation more.
+ def testInlineSharedDiagnostic(self):
+ generic = generic_set.GenericSet(['generic diagnostic'])
+ hist = histogram.Histogram('', 'count')
+ _ = generic.guid # First access sets guid
+ hist.diagnostics['foo'] = generic
+ generic.Inline()
+ self.assertFalse(generic.has_guid)
+ hist_dict = hist.AsDict()
+ diag_dict = hist_dict['diagnostics']['foo']
+ self.assertIsInstance(diag_dict, dict)
+ self.assertEqual(diag_dict['type'], 'GenericSet')
+
+ def testCloneWithRef(self):
+ diagnostics = histogram.DiagnosticMap()
+ diagnostics['ref'] = diagnostic_ref.DiagnosticRef('abc')
+
+ clone = histogram.DiagnosticMap.FromDict(diagnostics.AsDict())
+ self.assertIsInstance(clone.get('ref'), diagnostic_ref.DiagnosticRef)
+ self.assertEqual(clone.get('ref').guid, 'abc')
+
+ def testDiagnosticGuidDeserialized(self):
+ d = {
+ 'type': 'GenericSet',
+ 'values': [],
+ 'guid': 'bar'
+ }
+ g = diagnostic.Diagnostic.FromDict(d)
+ self.assertEqual('bar', g.guid)
+
+ def testMerge(self):
+ events = related_event_set.RelatedEventSet()
+ events.Add({
+ 'stableId': '0.0',
+ 'title': 'foo',
+ 'start': 0,
+ 'duration': 1,
+ })
+ generic = generic_set.GenericSet(['generic diagnostic'])
+ generic2 = generic_set.GenericSet(['generic diagnostic 2'])
+ related_map = related_name_map.RelatedNameMap()
+ related_map.Set('a', 'histogram')
+
+ hist = histogram.Histogram('', 'count')
+
+ # When Histograms are merged, first an empty clone is created with an empty
+ # DiagnosticMap.
+ hist2 = histogram.Histogram('', 'count')
+ hist2.diagnostics['a'] = generic
+ hist.diagnostics.Merge(hist2.diagnostics)
+ self.assertIs(generic, hist.diagnostics['a'])
+
+ # Separate keys are not merged.
+ hist3 = histogram.Histogram('', 'count')
+ hist3.diagnostics['b'] = generic2
+ hist.diagnostics.Merge(hist3.diagnostics)
+ self.assertIs(generic, hist.diagnostics['a'])
+ self.assertIs(generic2, hist.diagnostics['b'])
+
+ # Merging unmergeable diagnostics should produce an
+ # UnmergeableDiagnosticSet.
+ hist4 = histogram.Histogram('', 'count')
+ hist4.diagnostics['a'] = related_map
+ hist.diagnostics.Merge(hist4.diagnostics)
+ self.assertIsInstance(hist.diagnostics['a'], ums.UnmergeableDiagnosticSet)
+ diagnostics = list(hist.diagnostics['a'])
+ self.assertIs(generic, diagnostics[0])
+ self.assertIs(related_map, diagnostics[1])
+
+ # UnmergeableDiagnosticSets are mergeable.
+ hist5 = histogram.Histogram('', 'count')
+ hist5.diagnostics['a'] = ums.UnmergeableDiagnosticSet([events, generic2])
+ hist.diagnostics.Merge(hist5.diagnostics)
+ self.assertIsInstance(hist.diagnostics['a'], ums.UnmergeableDiagnosticSet)
+ diagnostics = list(hist.diagnostics['a'])
+ self.assertIs(generic, diagnostics[0])
+ self.assertIs(related_map, diagnostics[1])
+ self.assertIs(events, diagnostics[2])
+ self.assertIs(generic2, diagnostics[3])
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histograms_to_csv.py b/chromium/third_party/catapult/tracing/tracing/value/histograms_to_csv.py
new file mode 100644
index 00000000000..ce1b90f55b1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histograms_to_csv.py
@@ -0,0 +1,22 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import vinn
+import tracing_project
+
+def HistogramsToCsv(json_path):
+ """Convert HistogramSet JSON to CSV.
+
+ Args:
+ json_path: path to a file containing HistogramSet JSON
+
+ Returns:
+ a Vinn result object whose 'returncode' indicates whether there was an
+ exception, and whose 'stdout' contains CSV.
+ """
+ return vinn.RunFile(
+ os.path.join(os.path.dirname(__file__), 'histograms_to_csv_cmdline.html'),
+ source_paths=list(tracing_project.TracingProject().source_paths),
+ js_args=[os.path.abspath(json_path)])
diff --git a/chromium/third_party/catapult/tracing/tracing/value/histograms_to_csv_cmdline.html b/chromium/third_party/catapult/tracing/tracing/value/histograms_to_csv_cmdline.html
new file mode 100644
index 00000000000..c3b5163544e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/histograms_to_csv_cmdline.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/value/csv_builder.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+if (tr.isHeadless) {
+ const histograms = new tr.v.HistogramSet();
+ histograms.importDicts(JSON.parse(tr.b.getSync('file://' + sys.argv[1])));
+ const csv = new tr.v.CSVBuilder(histograms);
+ csv.build();
+ console.log(csv.toString());
+}
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/legacy_json_converter.py b/chromium/third_party/catapult/tracing/tracing/value/legacy_json_converter.py
new file mode 100755
index 00000000000..a940f3dde5c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/legacy_json_converter.py
@@ -0,0 +1,68 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from tracing.value import histogram
+from tracing.value import histogram_set
+from tracing.value.diagnostics import generic_set
+from tracing.value.diagnostics import reserved_infos
+
+
+def ConvertLegacyDicts(dicts):
+ """Convert legacy JSON dicts to Histograms.
+
+ Args:
+ dicts: A list of v0 JSON dicts
+
+ Returns:
+ A HistogramSet containing equivalent histograms and diagnostics
+ """
+ if len(dicts) < 1:
+ return histogram_set.HistogramSet()
+
+ first_dict = dicts[0]
+ master = first_dict['master']
+ bot = first_dict['bot']
+ suite = first_dict['test'].split('/')[0]
+
+ hs = histogram_set.HistogramSet()
+
+ for d in dicts:
+ assert d['master'] == master
+ assert d['bot'] == bot
+
+ test_parts = d['test'].split('/')
+ assert test_parts[0] == suite
+ name = test_parts[1]
+
+ # TODO(843643): Generalize this
+ assert 'units' not in d
+ # TODO(861822): Port this to CreateHistogram
+ h = histogram.Histogram(name, 'unitless')
+ h.AddSample(d['value'])
+ # TODO(876379): Support more than three components
+ if len(test_parts) == 3:
+ h.diagnostics[reserved_infos.STORIES.name] = generic_set.GenericSet(
+ [test_parts[2]])
+
+ hs.AddHistogram(h)
+
+ hs.AddSharedDiagnosticToAllHistograms(
+ reserved_infos.MASTERS.name, generic_set.GenericSet([master]))
+ hs.AddSharedDiagnosticToAllHistograms(
+ reserved_infos.BOTS.name, generic_set.GenericSet([bot]))
+ hs.AddSharedDiagnosticToAllHistograms(
+ reserved_infos.BENCHMARKS.name, generic_set.GenericSet([suite]))
+ _AddRevision(first_dict, hs)
+
+ return hs
+
+
+def _AddRevision(d, hs):
+ r_commit_pos = d.get('supplemental_columns', {}).get('r_commit_pos')
+ rev = d['revision']
+ if r_commit_pos == rev:
+ name = reserved_infos.CHROMIUM_COMMIT_POSITIONS.name
+ else:
+ name = reserved_infos.POINT_ID.name
+ hs.AddSharedDiagnosticToAllHistograms(name, generic_set.GenericSet([rev]))
diff --git a/chromium/third_party/catapult/tracing/tracing/value/legacy_json_converter_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/legacy_json_converter_unittest.py
new file mode 100644
index 00000000000..84b173fd04b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/legacy_json_converter_unittest.py
@@ -0,0 +1,116 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing.value import legacy_json_converter
+from tracing.value.diagnostics import reserved_infos
+
+
+class LegacyJsonConverterUnittest(unittest.TestCase):
+
+ def testConvertBasic(self):
+ dicts = [{
+ 'master': 'Master',
+ 'bot': 'Bot',
+ 'test': 'Suite/Metric',
+ 'revision': 1234,
+ 'value': 42.0
+ }]
+
+ histograms = legacy_json_converter.ConvertLegacyDicts(dicts)
+
+ self.assertEqual(len(histograms), 1)
+
+ h = histograms.GetFirstHistogram()
+
+ self.assertEqual(h.name, 'Metric')
+ self.assertEqual(len(h.diagnostics), 4)
+
+ masters = h.diagnostics[reserved_infos.MASTERS.name]
+ self.assertEqual(masters.GetOnlyElement(), 'Master')
+
+ bots = h.diagnostics[reserved_infos.BOTS.name]
+ self.assertEqual(bots.GetOnlyElement(), 'Bot')
+
+ benchmarks = h.diagnostics[reserved_infos.BENCHMARKS.name]
+ self.assertEqual(benchmarks.GetOnlyElement(), 'Suite')
+
+ point_id = h.diagnostics[reserved_infos.POINT_ID.name].GetOnlyElement()
+ self.assertEqual(point_id, 1234)
+
+ self.assertEqual(h.num_values, 1)
+ self.assertEqual(h.average, 42.0)
+
+ def testConvertWithStory(self):
+ dicts = [{
+ 'master': 'Master',
+ 'bot': 'Bot',
+ 'test': 'Suite/Metric/Case',
+ 'revision': 1234,
+ 'value': 42.0
+ }]
+
+ histograms = legacy_json_converter.ConvertLegacyDicts(dicts)
+ h = histograms.GetFirstHistogram()
+
+ stories = h.diagnostics[reserved_infos.STORIES.name]
+ self.assertEqual(stories.GetOnlyElement(), 'Case')
+
+ def testConvertWithRCommitPos(self):
+ dicts = [{
+ 'master': 'Master',
+ 'bot': 'Bot',
+ 'test': 'Suite/Metric/Case',
+ 'revision': 1234,
+ 'value': 42.0,
+ 'supplemental_columns': {
+ 'r_commit_pos': 1234
+ }
+ }]
+
+ histograms = legacy_json_converter.ConvertLegacyDicts(dicts)
+ h = histograms.GetFirstHistogram()
+
+ commit_pos = h.diagnostics[reserved_infos.CHROMIUM_COMMIT_POSITIONS.name]
+ self.assertEqual(commit_pos.GetOnlyElement(), 1234)
+ self.assertNotIn(reserved_infos.POINT_ID.name, h.diagnostics)
+
+ def testConvertWithDifferentRCommitPos(self):
+ dicts = [{
+ 'master': 'Master',
+ 'bot': 'Bot',
+ 'test': 'Suite/Metric/Case',
+ 'revision': 1234,
+ 'value': 42.0,
+ 'supplemental_columns': {
+ 'r_commit_pos': 2435
+ }
+ }]
+
+ histograms = legacy_json_converter.ConvertLegacyDicts(dicts)
+ h = histograms.GetFirstHistogram()
+
+ point_id = h.diagnostics[reserved_infos.POINT_ID.name].GetOnlyElement()
+ self.assertEqual(point_id, 1234)
+ self.assertNotIn(reserved_infos.CHROMIUM_COMMIT_POSITIONS.name,
+ h.diagnostics)
+
+ def testConvertUsesPointIdIfSupplementalColumnsButNoRCommitPos(self):
+ dicts = [{
+ 'master': 'Master',
+ 'bot': 'Bot',
+ 'test': 'Suite/Metric/Case',
+ 'revision': 1234,
+ 'value': 42.0,
+ 'supplemental_columns': {
+ 'r_v8_rev': 1234
+ }
+ }]
+
+ histograms = legacy_json_converter.ConvertLegacyDicts(dicts)
+ h = histograms.GetFirstHistogram()
+
+ point_id = h.diagnostics[reserved_infos.POINT_ID.name].GetOnlyElement()
+ self.assertEqual(point_id, 1234)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/legacy_unit_info.html b/chromium/third_party/catapult/tracing/tracing/value/legacy_unit_info.html
new file mode 100644
index 00000000000..801ae4d6533
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/legacy_unit_info.html
@@ -0,0 +1,271 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v', function() {
+ // This information is used to convert results from chart-json format to
+ // Histograms.
+ // Improvement directions are copied from
+ // telemetry/telemetry/value/unit-info.json
+ // but can be overridden by 'improvement_direction' in chart-json.
+ const LEGACY_UNIT_INFO = new Map();
+ LEGACY_UNIT_INFO.set('%', {
+ name: 'normalizedPercentage',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.DONT_CARE,
+ });
+ LEGACY_UNIT_INFO.set('Celsius', {
+ name: 'unitlessNumber',
+ // Colder machines are faster.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('Hz', {
+ name: 'unitlessNumber',
+ // Higher frequencies are faster.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('KB', {
+ name: 'sizeInBytes',
+ conversionFactor: 1024,
+ // Less memory usage is better.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('MB', {
+ name: 'sizeInBytes',
+ conversionFactor: 1024 * 1024,
+ // Less memory usage is better.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('ObjectsAt30FPS', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('available_kB', {
+ name: 'sizeInBytes',
+ conversionFactor: 1024,
+ // More memory available is better.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('bit/s', {
+ name: 'unitlessNumber',
+ // TODO(#3815) Reconcile with char/s.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('bytes', {
+ name: 'sizeInBytes',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('chars/s', {
+ name: 'unitlessNumber',
+ // TODO(#3815) Reconcile with bit/s.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('commit_count', {
+ name: 'count',
+ // layer_tree_host_perftest
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('count', {
+ name: 'count',
+ // Processes
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('coverage%', {
+ name: 'normalizedPercentage',
+ // Used in alloy-perf-test/cts%/passed.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('dB', {
+ name: 'unitlessNumber',
+ // Decibels peak signal-to-noise ratio. Used by WebRTC quality tests.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('files', {
+ name: 'count',
+ // Static initializers
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('fps', {
+ name: 'unitlessNumber',
+ // Used by scirra benchmark.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('frame_count', {
+ name: 'count',
+ // layer_tree_host_perftest
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('frame_time', {
+ name: 'timeDurationInMs',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('frames', {
+ name: 'count',
+ // Dropped frames.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('frames-per-second', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('garbage_collections', {
+ name: 'count',
+ // Number of GCs needed to collect an object. Less is better.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('idle%', {
+ name: 'normalizedPercentage',
+ // Percentage of work done in idle time.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('janks', {
+ name: 'count',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('kb', {
+ name: 'sizeInBytes',
+ conversionFactor: 1024,
+ // Less memory usage is better.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('lines', {
+ name: 'count',
+ // More test coverage is better.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('mWh', {
+ name: 'energyInJoules',
+ conversionFactor: 3.6,
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('milliseconds', {
+ name: 'timeDurationInMs',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('milliseconds-per-frame', {
+ name: 'timeDurationInMs',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('minutes', {
+ name: 'timeInMsAutoFormat',
+ conversionFactor: 60e3,
+ // Used for NaCl build time.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('mips', {
+ name: 'unitlessNumber',
+ // More instructions processed per time unit.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('mpixels_sec', {
+ name: 'unitlessNumber',
+ // More pixels processed per time unit.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('ms', {
+ name: 'timeDurationInMs',
+ // Used in many Telemetry measurements. Fewer ms of time means faster.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('mtri_sec', {
+ name: 'unitlessNumber',
+ // More triangles processed per time unit.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('mvtx_sec', {
+ name: 'unitlessNumber',
+ // More vertices processed per time unit.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('objects (bigger is better)', {
+ name: 'count',
+ // Used in spaceport benchmark.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('packets', {
+ name: 'count',
+ // Monitors how many packets we use to accomplish something.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('percent', {
+ name: 'normalizedPercentage',
+ // Synonym for %, used in memory metric for percent fragmentation.
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('points', {
+ name: 'unitlessNumber',
+ // Synonym for score, used in ChromeOS touchpad tests.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('ports', {
+ name: 'count',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('reduction%', {
+ name: 'normalizedPercentage',
+ // Used in draw_property measurement to indicate relative improvement.
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('relocs', {
+ name: 'count',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('runs/s', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('runs_per_s', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('runs_per_second', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('score (bigger is better)', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('score', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('score_(bigger_is_better)', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('seconds', {
+ name: 'timeDurationInMs',
+ conversionFactor: 1e3,
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('tokens/s', {
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.BIGGER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('tasks', {
+ // Used by thread_times but actually indicates tasks/s, so not count.
+ name: 'unitlessNumber',
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+ LEGACY_UNIT_INFO.set('us', {
+ name: 'timeDurationInMs',
+ conversionFactor: 1e-3,
+ defaultImprovementDirection: tr.b.ImprovementDirection.SMALLER_IS_BETTER,
+ });
+
+ return {
+ LEGACY_UNIT_INFO,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/merge_histograms.py b/chromium/third_party/catapult/tracing/tracing/value/merge_histograms.py
new file mode 100644
index 00000000000..c7e4c9a95b1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/merge_histograms.py
@@ -0,0 +1,34 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import sys
+
+import tracing_project
+import vinn
+
+_MERGE_HISTOGRAMS_CMD_LINE = os.path.join(
+ os.path.dirname(__file__), 'merge_histograms_cmdline.html')
+
+
+def MergeHistograms(json_path, groupby=()):
+ """Merge Histograms.
+
+ Args:
+ json_path: Path to a HistogramSet JSON file.
+ groupby: Array of grouping keys (name, benchmark, time, storyset_repeat,
+ story_repeat, story, tir, label)
+ Returns:
+ HistogramSet dicts of the merged Histograms.
+ """
+ result = vinn.RunFile(
+ _MERGE_HISTOGRAMS_CMD_LINE,
+ source_paths=list(tracing_project.TracingProject().source_paths),
+ js_args=[os.path.abspath(json_path)] + list(groupby))
+ if result.returncode != 0:
+ sys.stderr.write(result.stdout)
+ raise Exception('vinn merge_histograms_cmdline.html returned ' +
+ str(result.returncode))
+ return json.loads(result.stdout)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/merge_histograms_cmdline.html b/chromium/third_party/catapult/tracing/tracing/value/merge_histograms_cmdline.html
new file mode 100644
index 00000000000..090390e81e8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/merge_histograms_cmdline.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+
+<script>
+'use strict';
+/* eslint-disable no-console */
+
+function findGrouping(key) {
+ const grouping = tr.v.HistogramGrouping.BY_KEY.get(key);
+ if (grouping === undefined) {
+ throw new Error(`Could not find grouping "${key}"`);
+ }
+ return grouping;
+}
+
+function findMergeable(hist, candidates) {
+ for (const candidate of candidates) {
+ if (candidate.canAddHistogram(hist)) return candidate;
+ }
+ return undefined;
+}
+
+function mergeLeafHistograms(groupedHistograms, mergedHistograms) {
+ for (const [name, histograms] of groupedHistograms) {
+ if (histograms instanceof Map) {
+ mergeLeafHistograms(histograms, mergedHistograms);
+ continue;
+ }
+
+ if (histograms.length === 1) {
+ mergedHistograms.addHistogram(histograms[0].clone());
+ continue;
+ }
+
+ // Merge Histograms in this leaf array and return the merged Histograms to
+ // mergedHistograms.
+ // If it isn't possible to merge all Histograms in |histograms| together,
+ // then merge them into as few merged Histograms as possible.
+ const merged = [histograms.shift().clone()];
+ for (const hist of histograms) {
+ const candidate = findMergeable(hist, merged);
+ if (candidate !== undefined) {
+ candidate.addHistogram(hist);
+ continue;
+ }
+ merged.push(hist.clone());
+ }
+ for (const hist of merged) {
+ mergedHistograms.addHistogram(hist);
+ }
+ }
+}
+
+function stripInternalDiagnostics(mergedHistograms) {
+ for (const hist of mergedHistograms) {
+ hist.diagnostics.delete(tr.v.d.RESERVED_NAMES.TEST_PATH);
+ }
+}
+
+function mergeHistograms(histogramsPath, groupingKeys) {
+ const histograms = new tr.v.HistogramSet();
+ histograms.importDicts(JSON.parse(tr.b.getSync('file://' + histogramsPath)));
+ histograms.buildGroupingsFromTags([tr.v.d.RESERVED_NAMES.STORY_TAGS]);
+ const groupings = groupingKeys.map(findGrouping);
+ const groupedHistograms = histograms.groupHistogramsRecursively(groupings);
+ const mergedHistograms = new tr.v.HistogramSet();
+ mergeLeafHistograms(groupedHistograms, mergedHistograms);
+ mergedHistograms.deduplicateDiagnostics();
+ stripInternalDiagnostics(mergedHistograms);
+ return mergedHistograms;
+}
+
+if (tr.isHeadless) {
+ const mergedHistograms = mergeHistograms(sys.argv[1], sys.argv.slice(2));
+ console.log(JSON.stringify(mergedHistograms.asDicts()));
+}
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/merge_histograms_unittest.py b/chromium/third_party/catapult/tracing/tracing/value/merge_histograms_unittest.py
new file mode 100644
index 00000000000..376f3ac59d8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/merge_histograms_unittest.py
@@ -0,0 +1,31 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import tempfile
+import unittest
+
+from tracing.value import histogram
+from tracing.value import histogram_set
+from tracing.value import merge_histograms
+
+
+class MergeHistogramsUnittest(unittest.TestCase):
+
+ def testSingularHistogramsGetMergedFrom(self):
+ hist0 = histogram.Histogram('foo', 'count')
+ hist1 = histogram.Histogram('bar', 'count')
+ histograms = histogram_set.HistogramSet([hist0, hist1])
+ histograms_file = tempfile.NamedTemporaryFile(delete=False)
+ histograms_file.write(json.dumps(histograms.AsDicts()).encode('utf-8'))
+ histograms_file.close()
+
+ merged_dicts = merge_histograms.MergeHistograms(histograms_file.name,
+ ('name',))
+ merged_histograms = histogram_set.HistogramSet()
+ merged_histograms.ImportDicts(merged_dicts)
+ self.assertEqual(len(list(merged_histograms.shared_diagnostics)), 0)
+ self.assertEqual(len(merged_histograms), 2)
+ os.remove(histograms_file.name)
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span.html
new file mode 100644
index 00000000000..228afbd2891
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span.html
@@ -0,0 +1,350 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/fixed_color_scheme.html">
+<link rel="import" href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
+<link rel="import" href="/tracing/metrics/all_fixed_color_schemes.html">
+<link rel="import" href="/tracing/ui/base/column_chart.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span_behavior.html">
+
+<dom-module id="tr-v-ui-breakdown-span">
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: column;
+ }
+ #table_container {
+ display: flex;
+ flex: 0 0 auto;
+ }
+ #table {
+ max-height: 150px;
+ overflow-y: auto;
+ }
+ </style>
+
+ <div id="empty">(empty)</div>
+ <div id="table_container">
+ <div id="container"></div>
+ <span>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </span>
+ </div>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.ui', function() {
+ const DEFAULT_COLOR_SCHEME = new tr.b.SinebowColorGenerator();
+
+ function getHistogramName(histogram, diagnosticName, key) {
+ if (histogram === undefined) return undefined;
+ const nameMap = histogram.diagnostics.get(diagnosticName);
+ if (nameMap === undefined) return undefined;
+ return nameMap.get(key);
+ }
+
+ class BreakdownTableSummaryRow {
+ constructor(displayElement, histogramNames) {
+ this.displayElement_ = displayElement;
+ this.histogramNames_ = histogramNames;
+ this.keySpan_ = undefined;
+ }
+
+ get numberValue() {
+ // Prevent this row from appearing in the ColumnChart.
+ return undefined;
+ }
+
+ get keySpan() {
+ if (this.keySpan_ === undefined) {
+ if (this.histogramNames_.length) {
+ this.keySpan_ = document.createElement('tr-ui-a-analysis-link');
+ this.keySpan_.setSelectionAndContent(
+ this.histogramNames_, 'Select All');
+ } else {
+ this.keySpan_ = 'Sum';
+ }
+ }
+ return this.keySpan_;
+ }
+
+ get name() {
+ return 'Sum';
+ }
+
+ get displayElement() {
+ return this.displayElement_;
+ }
+
+ get stringPercent() {
+ return '100%';
+ }
+ }
+
+ class BreakdownTableRow {
+ constructor(name, value, histogramName, unit, color) {
+ this.name_ = name;
+ this.value_ = value;
+ this.histogramName_ = histogramName;
+ this.unit_ = unit;
+
+ if (typeof value !== 'number') {
+ throw new Error('unsupported value ' + value);
+ }
+
+ this.tableSum_ = undefined;
+ this.keySpan_ = undefined;
+
+ this.color_ = color;
+ const hsl = this.color.toHSL();
+ hsl.l *= 0.85;
+ this.highlightedColor_ = tr.b.Color.fromHSL(hsl);
+
+ if (this.unit_) {
+ this.displayElement_ = tr.v.ui.createScalarSpan(this.numberValue, {
+ unit: this.unit_,
+ });
+ } else {
+ this.displayElement_ = tr.ui.b.createSpan({
+ textContent: this.stringValue,
+ });
+ }
+ }
+
+ get name() {
+ return this.name_;
+ }
+
+ get color() {
+ return this.color_;
+ }
+
+ get highlightedColor() {
+ return this.highlightedColor_;
+ }
+
+ get keySpan() {
+ if (this.keySpan_ === undefined) {
+ if (this.histogramName_) {
+ this.keySpan_ = document.createElement('tr-ui-a-analysis-link');
+ this.keySpan_.setSelectionAndContent(
+ [this.histogramName_], this.name);
+ this.keySpan_.color = this.color;
+ this.keySpan_.title = this.histogramName_;
+ } else {
+ this.keySpan_ = document.createElement('span');
+ this.keySpan_.innerText = this.name;
+ this.keySpan_.style.color = this.color;
+ }
+ }
+ return this.keySpan_;
+ }
+
+ /**
+ * @return {number|undefined}
+ */
+ get numberValue() {
+ if (!isNaN(this.value_) &&
+ (this.value_ !== Infinity) &&
+ (this.value_ !== -Infinity) &&
+ (this.value_ > 0)) return this.value_;
+ // Prevent this row from appearing in the ColumnChart.
+ return undefined;
+ }
+
+ get stringValue() {
+ if ((this.unit_ !== undefined) &&
+ !isNaN(this.value_) &&
+ (this.value_ !== Infinity) &&
+ (this.value_ !== -Infinity)) {
+ return this.unit_.format(this.value_);
+ }
+ return this.value_.toString();
+ }
+
+ set tableSum(s) {
+ this.tableSum_ = s;
+ }
+
+ get stringPercent() {
+ if (this.tableSum_ === undefined) return '';
+ const num = this.numberValue;
+ if (num === undefined) return '';
+ return Math.floor(num * 100.0 / this.tableSum_) + '%';
+ }
+
+ get displayElement() {
+ return this.displayElement_;
+ }
+
+ compare(other) {
+ if (this.numberValue === undefined) {
+ if (other.numberValue === undefined) {
+ return this.name.localeCompare(other.name);
+ }
+ return 1;
+ }
+ if (other.numberValue === undefined) {
+ return -1;
+ }
+ if (this.numberValue === other.numberValue) {
+ return this.name.localeCompare(other.name);
+ }
+ return other.numberValue - this.numberValue;
+ }
+ }
+
+ Polymer({
+ is: 'tr-v-ui-breakdown-span',
+ behaviors: [tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],
+
+ created() {
+ this.chart_ = new tr.ui.b.ColumnChart();
+ this.chart_.graphHeight = 130;
+ this.chart_.isStacked = true;
+ this.chart_.hideXAxis = true;
+ this.chart_.hideLegend = true;
+ this.chart_.enableHoverBox = false;
+ this.chart_.addEventListener('rect-mouseenter',
+ event => this.onRectMouseEnter_(event));
+ this.chart_.addEventListener('rect-mouseleave',
+ event => this.onRectMouseLeave_(event));
+ },
+
+ onRectMouseEnter_(event) {
+ for (const row of this.$.table.tableRows) {
+ if (row.name === event.rect.key) {
+ row.displayElement.style.background = event.rect.color;
+ row.keySpan.scrollIntoViewIfNeeded();
+ } else {
+ row.displayElement.style.background = '';
+ }
+ }
+ },
+
+ onRectMouseLeave_(event) {
+ for (const row of this.$.table.tableRows) {
+ row.displayElement.style.background = '';
+ }
+ },
+
+ ready() {
+ Polymer.dom(this.$.container).appendChild(this.chart_);
+
+ this.$.table.zebra = true;
+ this.$.table.showHeader = false;
+ this.$.table.tableColumns = [
+ {
+ value: row => row.keySpan,
+ },
+ {
+ value: row => row.displayElement,
+ align: tr.ui.b.TableFormat.ColumnAlignment.RIGHT,
+ },
+ {
+ value: row => row.stringPercent,
+ align: tr.ui.b.TableFormat.ColumnAlignment.RIGHT,
+ },
+ ];
+ },
+
+ updateContents_() {
+ this.$.container.style.display = 'none';
+ this.$.table.style.display = 'none';
+ this.$.empty.style.display = 'block';
+
+ if (!this.diagnostic_) {
+ this.chart_.data = [];
+ return;
+ }
+
+ if (this.histogram_) this.chart_.unit = this.histogram_.unit;
+
+ let colorScheme = undefined;
+ // https://github.com/catapult-project/catapult/issues/2970
+ if (this.diagnostic.colorScheme ===
+ tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER) {
+ colorScheme = (name) => {
+ let cat = name.split(' ');
+ cat = cat[cat.length - 1];
+ return tr.e.chrome.ChromeUserFriendlyCategoryDriver.getColor(cat);
+ };
+ } else if (this.diagnostic.colorScheme !== undefined) {
+ colorScheme = (name) => tr.b.FixedColorSchemeRegistry.lookUp(
+ this.diagnostic.colorScheme).getColor(name);
+ } else {
+ colorScheme = (name) => DEFAULT_COLOR_SCHEME.colorForKey(name);
+ }
+
+ const tableRows = [];
+ let tableSum = 0;
+ const histogramNames = [];
+ for (const [key, value] of this.diagnostic) {
+ const histogramName = getHistogramName(
+ this.histogram_, this.name_, key);
+ const row = new BreakdownTableRow(
+ key, value, histogramName, this.chart_.unit, colorScheme(key));
+ tableRows.push(row);
+ if (row.numberValue !== undefined) tableSum += row.numberValue;
+ if (histogramName) {
+ histogramNames.push(histogramName);
+ }
+ }
+ tableRows.sort((x, y) => x.compare(y));
+
+ if (tableSum > 0) {
+ let summaryDisplayElement = tableSum;
+ if (this.chart_.unit !== undefined) {
+ summaryDisplayElement = this.chart_.unit.format(tableSum);
+ }
+ summaryDisplayElement = tr.ui.b.createSpan({
+ textContent: summaryDisplayElement,
+ });
+ tableRows.unshift(new BreakdownTableSummaryRow(
+ summaryDisplayElement, histogramNames));
+ }
+
+ const chartData = {x: 0};
+ for (const row of tableRows) {
+ if (row.numberValue === undefined) continue;
+
+ // Let the row compute its percentage.
+ row.tableSum = tableSum;
+
+ // Add it to the chart.
+ chartData[row.name] = row.numberValue;
+
+ // Configure the colors.
+ const dataSeries = this.chart_.getDataSeries(row.name);
+ dataSeries.color = row.color;
+ dataSeries.highlightedColor = row.highlightedColor;
+ }
+
+ if (tableRows.length > 0) {
+ this.$.table.style.display = 'block';
+ this.$.empty.style.display = 'none';
+ this.$.table.tableRows = tableRows;
+ this.$.table.rebuild();
+ }
+
+ if (Object.keys(chartData).length > 1) {
+ this.$.container.style.display = 'block';
+ this.$.empty.style.display = 'none';
+ this.chart_.data = [chartData];
+ }
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html
new file mode 100644
index 00000000000..71079cdc856
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/breakdown_span_test.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/fixed_color_scheme.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/breakdown.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+<link rel="import" href="/tracing/value/ui/breakdown_span.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate_Breakdown', function() {
+ let breakdown = new tr.v.d.Breakdown();
+ breakdown.colorScheme =
+ tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;
+ breakdown.set('script', 42);
+ breakdown.set('style', 57);
+
+ // Test weird numbers.
+ breakdown.set('ba---a', NaN);
+ breakdown.set('inf', Infinity);
+ breakdown.set('-inf', -Infinity);
+ breakdown.set('goose egg', 0);
+ breakdown.set('<0', -1);
+
+ // Test lots of categories
+ for (let i = 0; i < 10; ++i) {
+ breakdown.set('cat ' + i, i);
+ }
+
+ // Test round-tripping.
+ breakdown = tr.v.d.Diagnostic.fromDict(breakdown.asDict());
+
+ const span = tr.v.ui.createDiagnosticSpan(breakdown);
+ assert.strictEqual('TR-V-UI-BREAKDOWN-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+
+ test('instantiate_BreakdownWithFixedColorScheme', function() {
+ const colorScheme = tr.b.FixedColorScheme.fromNames([
+ 'foo',
+ 'bar',
+ ]);
+ tr.b.FixedColorSchemeRegistry.register(() => colorScheme, {
+ 'name': 'myColorScheme',
+ });
+
+ let breakdown = new tr.v.d.Breakdown();
+ breakdown.colorScheme = 'myColorScheme';
+ breakdown.set('foo', 42);
+ breakdown.set('bar', 57);
+
+ // Test round-tripping.
+ breakdown = tr.v.d.Diagnostic.fromDict(breakdown.asDict());
+
+ const span = tr.v.ui.createDiagnosticSpan(breakdown);
+ span.updateContents_();
+ assert.strictEqual(
+ span.chart_.getDataSeries('foo').color, colorScheme.getColor('foo'));
+ this.addHTMLOutput(span);
+ });
+
+ test('empty', function() {
+ const breakdown = new tr.v.d.Breakdown();
+ const span = tr.v.ui.createDiagnosticSpan(breakdown);
+ assert.strictEqual('TR-V-UI-BREAKDOWN-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+
+ test('emptyExceptForWeirdNumbers', function() {
+ const breakdown = new tr.v.d.Breakdown();
+ breakdown.set('ba---a', NaN);
+ breakdown.set('inf', Infinity);
+ breakdown.set('-inf', -Infinity);
+ breakdown.set('goose egg', 0);
+ breakdown.set('<0', -1);
+
+ const span = tr.v.ui.createDiagnosticSpan(breakdown);
+ assert.strictEqual('TR-V-UI-BREAKDOWN-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+
+ test('correlate', function() {
+ const histograms = new tr.v.HistogramSet();
+ const sample0Breakdown = new tr.v.d.Breakdown();
+ sample0Breakdown.set('a', 5);
+ sample0Breakdown.set('b', 3);
+ sample0Breakdown.set('c', 2);
+ const sample1Breakdown = new tr.v.d.Breakdown();
+ sample1Breakdown.set('a', 50);
+ sample1Breakdown.set('b', 30);
+ sample1Breakdown.set('c', 20);
+ const related = new tr.v.d.RelatedNameMap();
+ related.set('a', histograms.createHistogram('root:a',
+ tr.b.Unit.byName.timeDurationInMs, [5, 50]).name);
+ related.set('b', tr.v.Histogram.create('root:b',
+ tr.b.Unit.byName.timeDurationInMs, [3, 30]).name);
+ related.set('c', tr.v.Histogram.create('root:c',
+ tr.b.Unit.byName.timeDurationInMs, [2, 20]).name);
+ const hist = histograms.createHistogram('root',
+ tr.b.Unit.byName.timeDurationInMs, [
+ {
+ value: 10,
+ diagnostics: new Map([['breakdown', sample0Breakdown]]),
+ },
+ {
+ value: 100,
+ diagnostics: new Map([['breakdown', sample1Breakdown]]),
+ },
+ ], {
+ diagnostics: new Map([
+ ['breakdown', related],
+ ]),
+ });
+ const span = tr.v.ui.createDiagnosticSpan(sample0Breakdown, 'breakdown',
+ hist);
+ this.addHTMLOutput(span);
+ const links = tr.ui.b.findDeepElementsMatching(span,
+ 'tr-ui-a-analysis-link');
+ assert.lengthOf(links, 4);
+ assert.strictEqual(links[0].title, '');
+ assert.strictEqual(links[1].title, 'root:a');
+ assert.strictEqual(links[2].title, 'root:b');
+ assert.strictEqual(links[3].title, 'root:c');
+ assert.strictEqual(links[0].textContent, 'Select All');
+ assert.strictEqual(links[1].textContent, 'a');
+ assert.strictEqual(links[2].textContent, 'b');
+ assert.strictEqual(links[3].textContent, 'c');
+ assert.lengthOf(links[0].selection, 3);
+ assert.strictEqual(links[0].selection[0], 'root:a');
+ assert.strictEqual(links[0].selection[1], 'root:b');
+ assert.strictEqual(links[0].selection[2], 'root:c');
+ assert.lengthOf(links[1].selection, 1);
+ assert.strictEqual(links[1].selection[0], 'root:a');
+ assert.lengthOf(links[2].selection, 1);
+ assert.strictEqual(links[2].selection[0], 'root:b');
+ assert.lengthOf(links[3].selection, 1);
+ assert.strictEqual(links[3].selection[0], 'root:c');
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/collected_related_event_set_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/collected_related_event_set_span.html
new file mode 100644
index 00000000000..08e0cc91dca
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/collected_related_event_set_span.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/ui/diagnostic_span_behavior.html">
+
+<dom-module id="tr-v-ui-collected-related-event-set-span">
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-collected-related-event-set-span',
+ behaviors: [tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],
+
+ updateContents_() {
+ Polymer.dom(this).textContent = '';
+ for (const [canonicalUrl, events] of this.diagnostic) {
+ const link = document.createElement('a');
+ if (events.length === 1) {
+ const event = tr.b.getOnlyElement(events);
+ link.textContent = event.title + ' ' +
+ tr.b.Unit.byName.timeDurationInMs.format(event.duration);
+ } else {
+ link.textContent = events.length + ' events';
+ }
+ link.href = canonicalUrl;
+ Polymer.dom(this).appendChild(link);
+ Polymer.dom(this).appendChild(document.createElement('br'));
+ }
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/collected_related_event_set_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/collected_related_event_set_span_test.html
new file mode 100644
index 00000000000..c14f75a9826
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/collected_related_event_set_span_test.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('merge', function() {
+ let aSlice;
+ let bSlice;
+ const model = tr.c.TestUtils.newModel(function(model) {
+ aSlice = tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ title: 'a',
+ start: 0,
+ duration: 10
+ });
+ bSlice = tr.c.TestUtils.newSliceEx({
+ type: tr.model.ThreadSlice,
+ title: 'b',
+ start: 1,
+ duration: 10
+ });
+ const thread = model.getOrCreateProcess(1).getOrCreateThread(2);
+ thread.sliceGroup.pushSlice(aSlice);
+ thread.sliceGroup.pushSlice(bSlice);
+ });
+ assert.notEqual(aSlice.stableId, bSlice.stableId);
+
+ const aHist = new tr.v.Histogram('a', tr.b.Unit.byName.count);
+ const bHist = new tr.v.Histogram('b', tr.b.Unit.byName.count);
+
+ aHist.diagnostics.set('events', new tr.v.d.RelatedEventSet(aSlice));
+ bHist.diagnostics.set('events', new tr.v.d.RelatedEventSet(bSlice));
+
+ let mergedHist = aHist.clone();
+ mergedHist.addHistogram(bHist);
+ mergedHist = tr.v.Histogram.fromDict(mergedHist.asDict());
+
+ const mergedEvents = mergedHist.diagnostics.get('events');
+ const span = tr.v.ui.createDiagnosticSpan(mergedEvents);
+ assert.strictEqual(
+ 'TR-V-UI-COLLECTED-RELATED-EVENT-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/date_range_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/date_range_span.html
new file mode 100644
index 00000000000..29773057810
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/date_range_span.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/ui/diagnostic_span_behavior.html">
+
+<dom-module id="tr-v-ui-date-range-span">
+ <template>
+ <content></content>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-date-range-span',
+ behaviors: [tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],
+
+ updateContents_() {
+ if (this.diagnostic === undefined) {
+ Polymer.dom(this).textContent = '';
+ return;
+ }
+
+ Polymer.dom(this).textContent = this.diagnostic.toString();
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/date_range_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/date_range_span_test.html
new file mode 100644
index 00000000000..3e7f02f0727
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/date_range_span_test.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/date_range.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate_one', function() {
+ const diagnostic = new tr.v.d.DateRange(1496693745398);
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-DATE-RANGE-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+
+ test('instantiate_merged', function() {
+ const diagnostic = new tr.v.d.DateRange(1496693745398);
+ diagnostic.addDiagnostic(new tr.v.d.DateRange(1496693745399));
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-DATE-RANGE-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_map_table.html b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_map_table.html
new file mode 100644
index 00000000000..3a600c00925
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_map_table.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+
+<dom-module id="tr-v-ui-diagnostic-map-table">
+ <template>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+tr.exportTo('tr.v.ui', function() {
+ function makeColumn(title, histogram) {
+ return {
+ title,
+ value(map) {
+ const diagnostic = map.get(title);
+ if (!diagnostic) return '';
+ return tr.v.ui.createDiagnosticSpan(diagnostic, title, histogram);
+ }
+ };
+ }
+
+ Polymer({
+ is: 'tr-v-ui-diagnostic-map-table',
+
+ created() {
+ this.diagnosticMaps_ = undefined;
+ this.histogram_ = undefined;
+ this.isMetadata_ = false;
+ },
+
+ set histogram(h) {
+ this.histogram_ = h;
+ },
+
+ set isMetadata(m) {
+ this.isMetadata_ = m;
+ this.$.table.showHeader = !this.isMetadata_;
+ },
+
+ /**
+ * The |title| will be used as the heading for the column containing
+ * diagnostic-spans for |diagnosticMap|'s Diagnostics.
+ *
+ * @param {!Array.<!Object>} maps
+ * @param {!string} maps[].title
+ * @param {!tr.v.d.DiagnosticMap} maps[].diagnosticMap
+ */
+ set diagnosticMaps(maps) {
+ this.diagnosticMaps_ = maps;
+ this.updateContents_();
+ },
+
+ get diagnosticMaps() {
+ return this.diagnosticMaps_;
+ },
+
+ updateContents_() {
+ if (this.isMetadata_ && this.diagnosticMaps_.length !== 1) {
+ throw new Error(
+ 'Metadata diagnostic-map-tables require exactly 1 DiagnosticMap');
+ }
+ if (this.diagnosticMaps_ === undefined ||
+ this.diagnosticMaps_.length === 0) {
+ this.$.table.tableRows = [];
+ this.$.table.tableColumns = [];
+ return;
+ }
+
+ let names = new Set();
+ for (const map of this.diagnosticMaps_) {
+ for (const [name, diagnostic] of map) {
+ // https://github.com/catapult-project/catapult/issues/2842
+ if (diagnostic instanceof tr.v.d.UnmergeableDiagnosticSet) continue;
+ if (diagnostic instanceof tr.v.d.CollectedRelatedEventSet) continue;
+
+ names.add(name);
+ }
+ }
+ names = Array.from(names).sort();
+
+ const histogram = this.histogram_;
+ if (this.isMetadata_) {
+ const diagnosticMap = this.diagnosticMaps_[0];
+ this.$.table.tableColumns = [
+ {
+ value(name) {
+ return name.name;
+ }
+ },
+ {
+ value(name) {
+ const diagnostic = diagnosticMap.get(name.name);
+ if (!diagnostic) return '';
+ return tr.v.ui.createDiagnosticSpan(
+ diagnostic, name.name, histogram);
+ }
+ },
+ ];
+ this.$.table.tableRows = names.map(name => {
+ // tr-ui-b-table requires rows to be objects.
+ return {name};
+ });
+ } else {
+ this.$.table.tableColumns = names.map(
+ name => makeColumn(name, histogram));
+ this.$.table.tableRows = this.diagnosticMaps_;
+ }
+
+ this.$.table.rebuild();
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_map_table_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_map_table_test.html
new file mode 100644
index 00000000000..d5d4ac02761
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_map_table_test.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_map_table.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const map0 = new tr.v.d.DiagnosticMap();
+ map0.set('genericA', new tr.v.d.GenericSet([{a: 0}]));
+ map0.set('genericB', new tr.v.d.GenericSet([{b: 0}]));
+ const map1 = new tr.v.d.DiagnosticMap();
+ map1.set('genericA', new tr.v.d.GenericSet([{a: 1}]));
+ map1.set('genericB', new tr.v.d.GenericSet([{b: 1}]));
+ const table = document.createElement('tr-v-ui-diagnostic-map-table');
+ table.diagnosticMaps = [map0, map1];
+ this.addHTMLOutput(table);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html
new file mode 100644
index 00000000000..741fc07f58e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic.html">
+<link rel="import" href="/tracing/value/ui/breakdown_span.html">
+<link rel="import" href="/tracing/value/ui/collected_related_event_set_span.html">
+<link rel="import" href="/tracing/value/ui/date_range_span.html">
+<link rel="import" href="/tracing/value/ui/generic_set_span.html">
+<link rel="import" href="/tracing/value/ui/related_event_set_span.html">
+<link rel="import" href="/tracing/value/ui/scalar_diagnostic_span.html">
+<link rel="import" href="/tracing/value/ui/unmergeable_diagnostic_set_span.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ /**
+ * Find the name of a polymer element registered to display |diagnostic|
+ * or one of its base classes.
+ *
+ * @param {!tr.v.d.Diagnostic} diagnostic
+ * @return {string}
+ */
+ function findElementNameForDiagnostic(diagnostic) {
+ let typeInfo = undefined;
+ let curProto = diagnostic.constructor.prototype;
+ while (curProto) {
+ typeInfo = tr.v.d.Diagnostic.findTypeInfo(curProto.constructor);
+ if (typeInfo && typeInfo.metadata.elementName) break;
+ typeInfo = undefined;
+ curProto = curProto.__proto__;
+ }
+
+ if (typeInfo === undefined) {
+ throw new Error(
+ diagnostic.constructor.name +
+ ' or a base class must have a registered elementName');
+ }
+
+ const tagName = typeInfo.metadata.elementName;
+
+ if (tr.ui.b.isUnknownElementName(tagName)) {
+ throw new Error('Element not registered: ' + tagName);
+ }
+
+ return tagName;
+ }
+
+ /**
+ * Create a visualization for |diagnostic|.
+ *
+ * @param {!tr.v.d.Diagnostic} diagnostic
+ * @param {string} name
+ * @param {!tr.v.Histogram} histogram
+ * @return {Element}
+ */
+ function createDiagnosticSpan(diagnostic, name, histogram) {
+ const tagName = findElementNameForDiagnostic(diagnostic);
+ const span = document.createElement(tagName);
+ if (span.build === undefined) throw new Error(tagName);
+ span.build(diagnostic, name, histogram);
+ return span;
+ }
+
+ return {
+ createDiagnosticSpan,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span_behavior.html b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span_behavior.html
new file mode 100644
index 00000000000..a40c15cb1c8
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/diagnostic_span_behavior.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/base.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ const DIAGNOSTIC_SPAN_BEHAVIOR = {
+ created() {
+ this.diagnostic_ = undefined;
+ this.name_ = undefined;
+ this.histogram_ = undefined;
+ },
+
+ attached() {
+ if (this.diagnostic_) this.updateContents_();
+ },
+
+ get diagnostic() {
+ return this.diagnostic_;
+ },
+
+ build(diagnostic, name, histogram) {
+ this.diagnostic_ = diagnostic;
+ this.name_ = name;
+ this.histogram_ = histogram;
+ if (this.isAttached) this.updateContents_();
+ },
+
+ updateContents_() {
+ throw new Error('dom-modules must override updateContents_()');
+ }
+ };
+
+ return {
+ DIAGNOSTIC_SPAN_BEHAVIOR,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span.html
new file mode 100644
index 00000000000..6f355e44478
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/analysis/generic_object_view.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span_behavior.html">
+
+<dom-module id="tr-v-ui-generic-set-span">
+ <template>
+ <style>
+ a {
+ display: block;
+ }
+ </style>
+
+ <tr-ui-a-generic-object-view id="generic"></tr-ui-a-generic-object-view>
+
+ <div id="links"></div>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ function isLinkTuple(value) {
+ return ((value instanceof Array) &&
+ (value.length === 2) &&
+ (typeof value[0] === 'string') &&
+ tr.b.isUrl(value[1]));
+ }
+
+ Polymer({
+ is: 'tr-v-ui-generic-set-span',
+ behaviors: [tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],
+
+ updateContents_() {
+ this.$.generic.style.display = 'none';
+ this.$.links.textContent = '';
+ if (this.diagnostic === undefined) return;
+ const values = Array.from(this.diagnostic);
+
+ let areAllStrings = true;
+ let areAllNumbers = true;
+ for (const value of values) {
+ if (typeof value !== 'number') {
+ areAllNumbers = false;
+ if (typeof value !== 'string' && !isLinkTuple(value)) {
+ areAllStrings = false;
+ break;
+ }
+ }
+ }
+
+ if (!areAllStrings) {
+ this.$.generic.style.display = '';
+ this.$.generic.object = values;
+ return;
+ }
+
+ if (areAllNumbers) {
+ values.sort((x, y) => x - y);
+ } else {
+ values.sort();
+ }
+
+ for (const value of values) {
+ const link = {textContent: '' + value};
+ if (isLinkTuple(value)) {
+ link.textContent = value[0];
+ link.href = value[1];
+ } else if (tr.b.isUrl(value)) {
+ link.href = value;
+ }
+ if (this.name_ === tr.v.d.RESERVED_NAMES.TRACE_URLS) {
+ link.textContent = value.substr(1 + value.lastIndexOf('/'));
+ }
+ const linkEl = tr.ui.b.createLink(link);
+ if (link.href) {
+ linkEl.target = '_blank';
+ // In case there's a listener in the hierarchy that calls
+ // preventDefault(), stop the event from propagating to it so that
+ // clicking the link always opens it in a new tab.
+ linkEl.addEventListener('click', e => e.stopPropagation());
+ }
+ this.$.links.appendChild(linkEl);
+ }
+ }
+ });
+
+ return {
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html
new file mode 100644
index 00000000000..6bddec81aa6
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/generic_set_span_test.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/generic_set.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('link_tuple', function() {
+ const diagnostic = new tr.v.d.GenericSet([
+ ['label', 'http://example.com/'],
+ ]);
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-GENERIC-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ const links = tr.ui.b.findDeepElementsMatching(span, 'a');
+ assert.lengthOf(links, diagnostic.size);
+ assert.strictEqual('label', links[0].textContent);
+ assert.strictEqual('http://example.com/', links[0].href);
+ });
+
+ test('instantiate', function() {
+ const diagnostic = new tr.v.d.GenericSet([{foo: 'bar', baz: [42]}]);
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-GENERIC-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+
+ test('strings', function() {
+ const diagnostic = new tr.v.d.GenericSet([
+ 'foo', 'bar', 1, 0, Infinity, NaN,
+ ]);
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-GENERIC-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ const links = tr.ui.b.findDeepElementsMatching(span, 'a');
+ assert.lengthOf(links, diagnostic.size);
+ assert.strictEqual(links[0].textContent, '0');
+ assert.strictEqual(links[0].href, '');
+ assert.strictEqual(links[1].textContent, '1');
+ assert.strictEqual(links[1].href, '');
+ assert.strictEqual(links[2].textContent, 'Infinity');
+ assert.strictEqual(links[2].href, '');
+ assert.strictEqual(links[3].textContent, 'NaN');
+ assert.strictEqual(links[3].href, '');
+ assert.strictEqual(links[4].textContent, 'bar');
+ assert.strictEqual(links[4].href, '');
+ assert.strictEqual(links[5].textContent, 'foo');
+ assert.strictEqual(links[5].href, '');
+ });
+
+ test('numbers', function() {
+ const diagnostic = new tr.v.d.GenericSet([10, 1, 0, 2, 11]);
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-GENERIC-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ const links = tr.ui.b.findDeepElementsMatching(span, 'a');
+ assert.lengthOf(links, diagnostic.size);
+ assert.strictEqual(links[0].textContent, '0');
+ assert.strictEqual(links[0].href, '');
+ assert.strictEqual(links[1].textContent, '1');
+ assert.strictEqual(links[1].href, '');
+ assert.strictEqual(links[2].textContent, '2');
+ assert.strictEqual(links[2].href, '');
+ assert.strictEqual(links[3].textContent, '10');
+ assert.strictEqual(links[3].href, '');
+ assert.strictEqual(links[4].textContent, '11');
+ assert.strictEqual(links[4].href, '');
+ });
+
+ test('urls', function() {
+ const urls = [
+ 'http://google.com/',
+ 'http://cnn.com/',
+ ];
+ const span = tr.v.ui.createDiagnosticSpan(new tr.v.d.GenericSet(urls));
+ assert.strictEqual('TR-V-UI-GENERIC-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ const links = tr.ui.b.findDeepElementsMatching(span, 'a');
+ assert.lengthOf(links, urls.length);
+ assert.strictEqual(links[0].textContent, urls[1]);
+ assert.strictEqual(links[0].href, urls[1]);
+ assert.strictEqual(links[1].textContent, urls[0]);
+ assert.strictEqual(links[1].href, urls[0]);
+ });
+
+ test('traceUrls', function() {
+ const urls = [
+ 'https://console.developers.google.com/m/cloudstorage/b/chromium-telemetry/o/c.html',
+ 'file://d/e/f.html',
+ ];
+ const span = tr.v.ui.createDiagnosticSpan(
+ new tr.v.d.GenericSet(urls), tr.v.d.RESERVED_NAMES.TRACE_URLS);
+ assert.strictEqual('TR-V-UI-GENERIC-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ const links = tr.ui.b.findDeepElementsMatching(span, 'a');
+ assert.lengthOf(links, urls.length);
+ assert.strictEqual(links[0].textContent, 'f.html');
+ assert.strictEqual(links[0].href, urls[1]);
+ assert.strictEqual(links[1].textContent, 'c.html');
+ assert.strictEqual(links[1].href, urls[0]);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram-set-view.md b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram-set-view.md
new file mode 100644
index 00000000000..951e4a9918c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram-set-view.md
@@ -0,0 +1,71 @@
+<!-- Copyright 2017 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+# HistogramSet UI Architecture
+
+Documentation for users of this UI is in [metrics-results-ui](/docs/metrics-results-ui.md).
+
+This document outlines the MVC architecture of the implementation of the UI.
+ * Model: [HistogramSetViewState](/tracing/tracing/value/ui/histogram_set_view_state.html)
+ * searchQuery: regex filters Histogram names
+ * referenceDisplayLabel selects the reference column in the table
+ * showAll: when false, only sourceHistograms are shown in the table
+ * groupings: array of HistogramGroupings configures how the hierarchy is constructed
+ * sortColumnIndex
+ * sortDescending
+ * constrainNameColumn: whether the Name column in the table is constrained to 300px
+ * tableRowStates: Map from row name to HistogramSetTableRowState
+ * subRows: Map from row name to HistogramSetTableRowState
+ * isExpanded: whether the row is expanded to show its subRows
+ * isOverviewed: whether the overview charts are displayed
+ * cells: map from column names to HistogramSetTableCellState:
+ * isOpen: whether the cell's histogram-span is open and displaying the BarChart and Diagnostics
+ * brushedBinRange: which bins are brushed in the BarChart
+ * mergeSampleDiagnostics: whether sample diagnostics are merged
+ * Setters delegate to the main entry point, update(delta), which dispatches an update event to listeners
+ * View-Controllers:
+ * [histogram-set-view](/tracing/tracing/value/ui/histogram_set_view.html):
+ * Main entry point: build(HistogramSet, progressIndicator):Promise
+ * Displays "zero Histograms"
+ * Listens for download-csv event from [histogram-set-controls](/tracing/tracing/value/ui/histogram_set_controls.html)
+ * gets leafHistograms from the [histogram-set-table](/tracing/tracing/value/ui/histogram_set_table.html)
+ * builds a CSV using [CSVBuilder](/tracing/tracing/value/csv_builder.html)
+ * Collects possible configurations of the HistogramSet and passes them to the child elements directly (not through the HistogramSetViewState!):
+ * Possible groupings
+ * displayLabels
+ * baseStatisticNames
+ * Contains child elements:
+ * [histogram-set-controls](/tracing/tracing/value/ui/histogram_set_controls.html)
+ * visualizes and controls the top half of HistogramSetViewState:
+ * searchQuery
+ * toggle display of all isOvervieweds
+ * referenceDisplayLabel
+ * showAll
+ * groupings
+ * Displays a button to download a CSV of the leafHistograms
+ * Displays a "Help" link to [metrics-results-ui](/docs/metrics-results-ui.md)
+ * [histogram-set-table](/tracing/tracing/value/ui/histogram_set_table.html)
+ * Visualizes and controls the bottom half of HistogramSetViewState:
+ * sortColumnIndex
+ * sortDescending
+ * constrainNameColumn
+ * HistogramSetTableRowStates
+ * Builds [HistogramSetTableRow](/tracing/tracing/value/ui/histogram_set_table_row.html)s containing
+ * [histogram-set-table-name-cell](/tracing/tracing/value/ui/histogram_set_table_name_cell.html)
+ * Toggles HistogramSetTableRowState.isOverviewed
+ * Overview [NameLineChart](/tracing/tracing/ui/base/name_line_chart.html)
+ * [histogram-set-table-cell](/tracing/tracing/value/ui/histogram_set_table_cell.html)
+ * (missing) / (empty) / (unmergeable)
+ * when closed, [scalar-span](/tracing/tracing/value/ui/scalar_span.html) displays a single summary statistic
+ * when open, [histogram-span](/tracing/tracing/value/ui/histogram_span.html) contains:
+ * [NameBarChart](/tracing/tracing/ui/base/name_bar_chart.html) visualizes and controls HistogramSetTableCellState.brushedBinRange
+ * [scalar-map-table](/tracing/tracing/value/ui/scalar_map_table.html) of statistics
+ * Two [diagnostic-map-tables](/tracing/tracing/value/ui/diagnostic_map_table.html): one for Histogram.diagnostics and another for the sample diagnostics
+ * A checkbox to visualize and control HistogramSetTableCellState.mergeSampleDiagnostics
+ * Overview [NameLineChart](/tracing/tracing/ui/base/name_line_chart.html)
+ * Main entry points:
+ * build(allHistograms, sourceHistograms, displayLabels, progressIndicator):Promise
+ * onViewStateUpdate_(delta)
+ * The [HistogramSetLocation](/tracing/tracing/value/ui/histogram_set_location.html) synchronizes the HistogramSetViewState with the URL using the HTML5 history API.
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html
new file mode 100644
index 00000000000..bb4e1e11ed0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_importer_test.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram_importer.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(() => {
+ const kHtmlString = '<script>throw new Error("oops");<' + '/script>';
+
+ function createHistogram(id) {
+ const histogram =
+ new tr.v.Histogram('name<' + id + '>', tr.b.Unit.byName.count);
+ histogram.addSample(id);
+ histogram.customizeSummaryOptions({
+ count: false,
+ max: false,
+ min: false,
+ std: false,
+ sum: false,
+ });
+ histogram.diagnostics.set('html', new tr.v.d.GenericSet([kHtmlString]));
+ return histogram;
+ }
+
+ test('importZeroHistograms', async function() {
+ const loadingEl = document.createElement('div');
+ this.addHTMLOutput(loadingEl);
+ const importer = new tr.v.HistogramImporter(loadingEl);
+ const histogramData = '\n';
+
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ view.style.display = 'none';
+ this.addHTMLOutput(view);
+
+ await importer.importHistograms(histogramData, view);
+
+ assert.strictEqual('block', view.style.display);
+ assert.strictEqual(undefined, view.histograms);
+ });
+
+ test('importOneHistogram', async function() {
+ const loadingEl = document.createElement('div');
+ this.addHTMLOutput(loadingEl);
+ const importer = new tr.v.HistogramImporter(loadingEl);
+
+ const hist = createHistogram(42);
+ const histogramData = '\n' + JSON.stringify(hist.asDict()) + '\n';
+
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ view.style.display = 'none';
+ this.addHTMLOutput(view);
+
+ await importer.importHistograms(histogramData, view);
+
+ assert.strictEqual('none', loadingEl.style.display);
+ assert.strictEqual('block', view.style.display);
+ assert.lengthOf(view.histograms, 1);
+ const histogram = view.histograms.getHistogramNamed('name<42>');
+ assert.strictEqual(kHtmlString, tr.b.getOnlyElement(
+ histogram.diagnostics.get('html')));
+ assert.deepEqual([42], histogram.sampleValues);
+ });
+
+ test('importNHistogram', async function() {
+ const loadingEl = document.createElement('div');
+ this.addHTMLOutput(loadingEl);
+ const importer = new tr.v.HistogramImporter(loadingEl);
+
+ const kNofHistograms = 1000;
+ let histogramData = '\n';
+ for (let i = 0; i < kNofHistograms; i++) {
+ const id = kNofHistograms * 100 + i;
+ const histogram = createHistogram(id);
+ histogramData += JSON.stringify(histogram.asDict()) + '\n';
+ }
+
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ view.style.display = 'none';
+ this.addHTMLOutput(view);
+
+ await importer.importHistograms(histogramData, view);
+
+ assert.strictEqual('none', loadingEl.style.display);
+ assert.strictEqual('block', view.style.display);
+ assert.lengthOf(view.histograms, kNofHistograms);
+ for (let i = 0; i < kNofHistograms; i++) {
+ const id = kNofHistograms * 100 + i;
+ const histogram = view.histograms.getHistogramNamed('name<' + id + '>');
+ assert.strictEqual(kHtmlString, tr.b.getOnlyElement(
+ histogram.diagnostics.get('html')));
+ assert.deepEqual([id], histogram.sampleValues);
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls.html
new file mode 100644
index 00000000000..c55093a90ec
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls.html
@@ -0,0 +1,557 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/ui/base/dom_helpers.html">
+<link rel="import" href="/tracing/ui/base/dropdown.html">
+<link rel="import" href="/tracing/ui/base/grouping_table_groupby_picker.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_controls_export.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view_state.html">
+
+<dom-module id="tr-v-ui-histogram-set-controls">
+ <template>
+ <style>
+ :host {
+ display: block;
+ }
+
+ #help, #feedback {
+ display: none;
+ margin-left: 20px;
+ }
+
+ #search_container {
+ display: inline-flex;
+ margin-right: 20px;
+ padding-bottom: 1px;
+ border-bottom: 1px solid darkgrey;
+ }
+
+ #search {
+ border: 0;
+ max-width: 20em;
+ outline: none;
+ }
+
+ #clear_search {
+ visibility: hidden;
+ height: 1em;
+ stroke: black;
+ stroke-width: 16;
+ }
+
+ #controls {
+ white-space: nowrap;
+ }
+
+ #show_overview, #hide_overview {
+ height: 1em;
+ margin-right: 20px;
+ }
+
+ #show_overview {
+ stroke: blue;
+ stroke-width: 16;
+ }
+
+ #show_overview:hover {
+ background: blue;
+ stroke: white;
+ }
+
+ #hide_overview {
+ display: none;
+ stroke-width: 18;
+ stroke: black;
+ }
+
+ #hide_overview:hover {
+ background: black;
+ stroke: white;
+ }
+
+ #reference_display_label {
+ display: none;
+ margin-right: 20px;
+ }
+
+ #alpha, #alpha_slider_container {
+ display: none;
+ }
+
+ #alpha {
+ margin-right: 20px;
+ }
+
+ #alpha_slider_container {
+ background: white;
+ border: 1px solid black;
+ flex-direction: column;
+ padding: 0.5em;
+ position: absolute;
+ z-index: 10; /* scalar-span uses z-index :-( */
+ }
+
+ #alpha_slider {
+ -webkit-appearance: slider-vertical;
+ align-self: center;
+ height: 200px;
+ width: 30px;
+ }
+
+ #statistic {
+ display: none;
+ margin-right: 20px;
+ }
+
+ #show_visualization {
+ margin-right: 20px;
+ }
+
+ #export {
+ margin-right: 20px;
+ }
+ </style>
+
+ <div id="controls">
+ <span id="search_container">
+ <input id="search" value="{{searchQuery::keyup}}" placeholder="Find Histogram name">
+ <svg viewbox="0 0 128 128" id="clear_search" on-tap="clearSearch_">
+ <g>
+ <title>Clear search</title>
+ <line x1="28" y1="28" x2="100" y2="100"/>
+ <line x1="28" y1="100" x2="100" y2="28"/>
+ </g>
+ </svg>
+ </span>
+
+ <svg viewbox="0 0 128 128" id="show_overview"
+ on-tap="toggleOverviewLineCharts_">
+ <g>
+ <title>Show overview charts</title>
+ <line x1="19" y1="109" x2="49" y2="49"/>
+ <line x1="49" y1="49" x2="79" y2="79"/>
+ <line x1="79" y1="79" x2="109" y2="19"/>
+ </g>
+ </svg>
+ <svg viewbox="0 0 128 128" id="hide_overview"
+ on-tap="toggleOverviewLineCharts_">
+ <g>
+ <title>Hide overview charts</title>
+ <line x1="28" y1="28" x2="100" y2="100"/>
+ <line x1="28" y1="100" x2="100" y2="28"/>
+ </g>
+ </svg>
+
+ <select id="reference_display_label" value="{{referenceDisplayLabel::change}}">
+ <option value="">Select a reference column</option>
+ </select>
+
+ <button id="alpha" on-tap="openAlphaSlider_">&#945;=[[alphaString]]</button>
+ <div id="alpha_slider_container">
+ <input type="range" id="alpha_slider" value="{{alphaIndex::change}}" min="0" max="18" on-blur="closeAlphaSlider_" on-input="updateAlpha_">
+ </div>
+
+ <select id="statistic" value="{{displayStatisticName::change}}">
+ </select>
+
+ <button id="show_visualization" on-tap="loadVisualization_">Visualize</button>
+
+ <tr-ui-b-dropdown label="Export">
+ <tr-v-ui-histogram-set-controls-export>
+ </tr-v-ui-histogram-set-controls-export>
+ </tr-ui-b-dropdown>
+
+ <input type="checkbox" id="show_all" checked="{{showAll::change}}" title="When unchecked, less important histograms are hidden.">
+ <label for="show_all" title="When unchecked, less important histograms are hidden.">Show all</label>
+
+ <a id="help">Help</a>
+ <a id="feedback">Feedback</a>
+ </div>
+
+ <tr-ui-b-grouping-table-groupby-picker id="picker">
+ </tr-ui-b-grouping-table-groupby-picker>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ const ALPHA_OPTIONS = [];
+ for (let i = 1; i < 10; ++i) ALPHA_OPTIONS.push(i * 1e-3);
+ for (let i = 1; i < 10; ++i) ALPHA_OPTIONS.push(i * 1e-2);
+ ALPHA_OPTIONS.push(0.1);
+
+ Polymer({
+ is: 'tr-v-ui-histogram-set-controls',
+
+ properties: {
+ searchQuery: {
+ type: String,
+ value: '',
+ observer: 'onSearchQueryChange_',
+ },
+ showAll: {
+ type: Boolean,
+ value: true,
+ observer: 'onUserChange_',
+ },
+ referenceDisplayLabel: {
+ type: String,
+ value: '',
+ observer: 'onUserChange_',
+ },
+ displayStatisticName: {
+ type: String,
+ value: '',
+ observer: 'onUserChange_',
+ },
+ alphaString: {
+ type: String,
+ computed: 'getAlphaString_(alphaIndex)',
+ },
+ alphaIndex: {
+ type: Number,
+ value: 9,
+ observer: 'onUserChange_',
+ },
+ },
+
+ created() {
+ this.viewState_ = undefined;
+ this.rowListener_ = this.onRowViewStateUpdate_.bind(this);
+ this.baseStatisticNames_ = [];
+
+ // When onViewStateUpdate_() copies multiple properties from the viewState
+ // to polymer properties, disable onUserChange_ until all properties are
+ // copied in order to prevent nested mutations to the ViewState.
+ this.isInOnViewStateUpdate_ = false;
+ this.searchQueryDebounceMs = 200;
+ },
+
+ ready() {
+ this.$.picker.addEventListener('current-groups-changed',
+ this.onGroupsChanged_.bind(this));
+ },
+
+ get viewState() {
+ return this.viewState_;
+ },
+
+ set viewState(vs) {
+ if (this.viewState_) {
+ throw new Error('viewState must be set exactly once.');
+ }
+ this.viewState_ = vs;
+ this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));
+ // It would be arduous to construct a delta and call viewStateListener_
+ // here in case vs contains non-default values, so callers must set
+ // viewState first and then update it.
+ },
+
+ async onSearchQueryChange_() {
+ // Bypass debouncing for testing purpose:
+ if (this.searchQueryDebounceMs === 0) return this.onUserChange_();
+ // Limit the update rate for instance caused by typing in a search.
+ this.debounce('onSearchQueryDebounce', this.onUserChange_,
+ this.searchQueryDebounceMs);
+ },
+
+ async onUserChange_() {
+ if (!this.viewState) return;
+ if (this.isInOnViewStateUpdate_) return;
+
+ const marks = [];
+ if (this.searchQuery !== this.viewState.searchQuery) {
+ marks.push(tr.b.Timing.mark('histogram-set-controls', 'search'));
+ }
+ if (this.showAll !== this.viewState.showAll) {
+ marks.push(tr.b.Timing.mark('histogram-set-controls', 'showAll'));
+ }
+ if (this.referenceDisplayLabel !== this.viewState.referenceDisplayLabel) {
+ marks.push(tr.b.Timing.mark(
+ 'histogram-set-controls', 'referenceColumn'));
+ }
+ if (this.displayStatisticName !== this.viewState.displayStatisticName) {
+ marks.push(tr.b.Timing.mark('histogram-set-controls', 'statistic'));
+ }
+ if (parseInt(this.alphaIndex) !== this.getAlphaIndexFromViewState_()) {
+ marks.push(tr.b.Timing.mark('histogram-set-controls', 'alpha'));
+ }
+
+ this.$.clear_search.style.visibility =
+ this.searchQuery ? 'visible' : 'hidden';
+
+ let displayStatisticName = this.displayStatisticName;
+ if (this.viewState.referenceDisplayLabel === '' &&
+ this.referenceDisplayLabel !== '' &&
+ this.baseStatisticNames.length) {
+ // The user selected a reference display label.
+ displayStatisticName = `%${tr.v.DELTA}${this.displayStatisticName}`;
+ // Can't set this.displayStatisticName before updating viewState -- that
+ // would cause an infinite loop of onUserChange_().
+ }
+ if (this.referenceDisplayLabel === '' &&
+ this.viewState.referenceDisplayLabel !== '' &&
+ this.baseStatisticNames.length) {
+ // The user unset the reference display label.
+ // Ensure that displayStatisticName is not a delta statistic.
+ const deltaIndex = displayStatisticName.indexOf(tr.v.DELTA);
+ if (deltaIndex >= 0) {
+ displayStatisticName = displayStatisticName.slice(deltaIndex + 1);
+ } else if (!this.baseStatisticNames.includes(displayStatisticName)) {
+ displayStatisticName = 'avg';
+ }
+ }
+
+ // Propagate updates from the user to the view state.
+ await this.viewState.update({
+ searchQuery: this.searchQuery,
+ showAll: this.showAll,
+ referenceDisplayLabel: this.referenceDisplayLabel,
+ displayStatisticName,
+ alpha: ALPHA_OPTIONS[this.alphaIndex],
+ });
+
+ if (this.referenceDisplayLabel &&
+ this.statisticNames.length === this.baseStatisticNames.length) {
+ // When a reference column is selected, delta statistics should be
+ // available.
+ this.statisticNames = this.baseStatisticNames.concat(
+ tr.v.Histogram.getDeltaStatisticsNames(this.baseStatisticNames));
+ } else if (!this.referenceDisplayLabel &&
+ this.statisticNames.length > this.baseStatisticNames.length) {
+ // When a reference column is not selected, delta statistics should not
+ // be available.
+ this.statisticNames = this.baseStatisticNames;
+ }
+
+ for (const mark of marks) mark.end();
+ },
+
+ onViewStateUpdate_(event) {
+ this.isInOnViewStateUpdate_ = true;
+
+ if (event.delta.searchQuery) {
+ this.searchQuery = this.viewState.searchQuery;
+ }
+
+ if (event.delta.showAll) this.showAll = this.viewState.showAll;
+
+ if (event.delta.displayStatisticName) {
+ this.displayStatisticName = this.viewState.displayStatisticName;
+ }
+
+ if (event.delta.referenceDisplayLabel) {
+ this.referenceDisplayLabel = this.viewState.referenceDisplayLabel;
+ this.$.alpha.style.display = this.referenceDisplayLabel ? 'inline' : '';
+ }
+
+ if (event.delta.groupings) {
+ this.$.picker.currentGroupKeys = this.viewState.groupings.map(
+ g => g.key);
+ }
+
+ if (event.delta.tableRowStates) {
+ for (const row of tr.v.ui.HistogramSetTableRowState.walkAll(
+ this.viewState.tableRowStates.values())) {
+ row.addUpdateListener(this.rowListener_);
+ }
+
+ const anyShowing = this.anyOverviewCharts_;
+ this.$.hide_overview.style.display = anyShowing ? 'inline' : 'none';
+ this.$.show_overview.style.display = anyShowing ? 'none' : 'inline';
+ }
+
+ if (event.delta.alpha) {
+ this.alphaIndex = this.getAlphaIndexFromViewState_();
+ }
+
+ this.isInOnViewStateUpdate_ = false;
+ this.onUserChange_();
+ },
+
+ onRowViewStateUpdate_(event) {
+ if (event.delta.isOverviewed) {
+ const anyShowing = event.delta.isOverviewed.current ||
+ this.anyOverviewCharts_;
+ this.$.hide_overview.style.display = anyShowing ? 'inline' : 'none';
+ this.$.show_overview.style.display = anyShowing ? 'none' : 'inline';
+ }
+
+ if (event.delta.subRows) {
+ for (const subRow of event.delta.subRows.previous) {
+ subRow.removeUpdateListener(this.rowListener_);
+ }
+ for (const subRow of event.delta.subRows.current) {
+ subRow.addUpdateListener(this.rowListener_);
+ }
+ }
+ },
+
+ onGroupsChanged_() {
+ if (this.$.picker.currentGroups.length === 0 &&
+ this.$.picker.possibleGroups.length > 0) {
+ // If the current groupings are now empty but there are possible
+ // groupings, then force there to be at least one grouping.
+ // The histogram-set-table requires there to be at least one grouping.
+ this.$.picker.currentGroupKeys = [this.$.picker.possibleGroups[0].key];
+ }
+ this.viewState.groupings = this.$.picker.currentGroups;
+ },
+
+ set showAllEnabled(enable) {
+ if (!enable) this.$.show_all.checked = true;
+ this.$.show_all.disabled = !enable;
+ },
+
+ set possibleGroupings(groupings) {
+ this.$.picker.possibleGroups = groupings;
+ this.$.picker.style.display = (groupings.length < 2) ? 'none' : 'block';
+ this.onGroupsChanged_();
+ },
+
+ set displayLabels(labels) {
+ this.$.reference_display_label.style.display =
+ (labels.length < 2) ? 'none' : 'inline';
+
+ while (this.$.reference_display_label.children.length > 1) {
+ this.$.reference_display_label.removeChild(
+ this.$.reference_display_label.lastChild);
+ }
+
+ for (const displayLabel of labels) {
+ const option = document.createElement('option');
+ option.textContent = displayLabel;
+ option.value = displayLabel;
+ this.$.reference_display_label.appendChild(option);
+ }
+
+ if (labels.includes(this.viewState.referenceDisplayLabel)) {
+ this.referenceDisplayLabel = this.viewState.referenceDisplayLabel;
+ } else {
+ this.viewState.referenceDisplayLabel = '';
+ }
+ },
+
+ get baseStatisticNames() {
+ return this.baseStatisticNames_;
+ },
+
+ set baseStatisticNames(names) {
+ this.baseStatisticNames_ = names;
+ this.statisticNames = names;
+ },
+
+ get statisticNames() {
+ return Array.from(this.$.statistic.options).map(o => o.value);
+ },
+
+ set statisticNames(names) {
+ this.$.statistic.style.display = (names.length < 2) ? 'none' : 'inline';
+
+ while (this.$.statistic.children.length) {
+ this.$.statistic.removeChild(this.$.statistic.lastChild);
+ }
+
+ for (const name of names) {
+ const option = document.createElement('option');
+ option.textContent = name;
+ this.$.statistic.appendChild(option);
+ }
+
+ if (names.includes(this.viewState.displayStatisticName)) {
+ this.displayStatisticName = this.viewState.displayStatisticName;
+ // Polymer doesn't reset the value when the options change, so do that
+ // manually.
+ this.$.statistic.value = this.displayStatisticName;
+ } else {
+ this.viewState.displayStatisticName = names[0] || '';
+ }
+ },
+
+ get anyOverviewCharts_() {
+ for (const row of tr.v.ui.HistogramSetTableRowState.walkAll(
+ this.viewState.tableRowStates.values())) {
+ if (row.isOverviewed) return true;
+ }
+ return false;
+ },
+
+ async toggleOverviewLineCharts_() {
+ const showOverviews = !this.anyOverviewCharts_;
+ const mark = tr.b.Timing.mark('histogram-set-controls',
+ (showOverviews ? 'show' : 'hide') + 'OverviewCharts');
+
+ for (const row of tr.v.ui.HistogramSetTableRowState.walkAll(
+ this.viewState.tableRowStates.values())) {
+ await row.update({isOverviewed: showOverviews});
+ }
+
+ this.$.hide_overview.style.display = showOverviews ? 'inline' : 'none';
+ this.$.show_overview.style.display = showOverviews ? 'none' : 'inline';
+
+ await tr.b.animationFrame();
+ mark.end();
+ },
+
+ set helpHref(href) {
+ this.$.help.href = href;
+ this.$.help.style.display = 'inline';
+ },
+
+ set feedbackHref(href) {
+ this.$.feedback.href = href;
+ this.$.feedback.style.display = 'inline';
+ },
+
+ clearSearch_() {
+ this.set('searchQuery', '');
+ this.$.search.focus();
+ },
+
+ getAlphaString_(alphaIndex) {
+ // (9 * 1e-3).toString() is "0.009000000000000001", so truncate.
+ return ('' + ALPHA_OPTIONS[alphaIndex]).substr(0, 5);
+ },
+
+ openAlphaSlider_() {
+ const alphaButtonRect = this.$.alpha.getBoundingClientRect();
+ this.$.alpha_slider_container.style.display = 'flex';
+ this.$.alpha_slider_container.style.top = alphaButtonRect.bottom + 'px';
+ this.$.alpha_slider_container.style.left = alphaButtonRect.left + 'px';
+ this.$.alpha_slider.focus();
+ },
+
+ closeAlphaSlider_() {
+ this.$.alpha_slider_container.style.display = '';
+ },
+
+ updateAlpha_() {
+ this.alphaIndex = this.$.alpha_slider.value;
+ },
+
+ getAlphaIndexFromViewState_() {
+ for (let i = 0; i < ALPHA_OPTIONS.length; ++i) {
+ if (ALPHA_OPTIONS[i] >= this.viewState.alpha) return i;
+ }
+ return ALPHA_OPTIONS.length - 1;
+ },
+
+ set enableVisualization(enable) {
+ this.$.show_visualization.style.display = enable ? 'inline' : 'none';
+ },
+
+ loadVisualization_() {
+ tr.b.dispatchSimpleEvent(this, 'loadVisualization', true, true, {});
+ },
+ });
+
+ return {
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_export.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_export.html
new file mode 100644
index 00000000000..98936f24bba
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_export.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/timing.html">
+
+<dom-module id="tr-v-ui-histogram-set-controls-export">
+ <template>
+ <style>
+ :host {
+ display: grid;
+ grid-gap: 1em;
+ grid-template-rows: auto auto;
+ grid-template-columns: auto auto;
+ }
+ button {
+ -webkit-appearance: none;
+ border: 0;
+ font-size: initial;
+ padding: 5px;
+ }
+ </style>
+
+ <button on-tap="exportRawCsv_">raw CSV</button>
+ <button on-tap="exportRawJson_">raw JSON</button>
+ <button on-tap="exportMergedCsv_">merged CSV</button>
+ <button on-tap="exportMergedJson_">merged JSON</button>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-histogram-set-controls-export',
+
+ exportRawCsv_() {
+ this.export_(false, 'csv');
+ },
+
+ exportRawJson_() {
+ this.export_(false, 'json');
+ },
+
+ exportMergedCsv_() {
+ this.export_(true, 'csv');
+ },
+
+ exportMergedJson_() {
+ this.export_(true, 'json');
+ },
+
+ export_(merged, format) {
+ tr.b.dispatchSimpleEvent(this, 'export', true, true, {merged, format});
+ },
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html
new file mode 100644
index 00000000000..9783059ccbe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_controls_test.html
@@ -0,0 +1,300 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/value/histogram_grouping.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_controls.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ function buildControls(test) {
+ const controls = document.createElement('tr-v-ui-histogram-set-controls');
+ controls.viewState = new tr.v.ui.HistogramSetViewState();
+ test.addHTMLOutput(controls);
+ return controls;
+ }
+
+ test('helpHref', function() {
+ const controls = buildControls(this);
+ controls.helpHref = 'data:text/html,hello';
+ const help = tr.ui.b.findDeepElementMatchingPredicate(
+ controls, e => e.id === 'help');
+ assert.strictEqual(help.style.display, 'inline');
+ assert.strictEqual(help.href, 'data:text/html,hello');
+ });
+
+ test('feedbackHref', function() {
+ const controls = buildControls(this);
+ controls.feedbackHref = 'data:text/html,hello';
+ const feedback = tr.ui.b.findDeepElementMatchingPredicate(
+ controls, e => e.id === 'feedback');
+ assert.strictEqual(feedback.style.display, 'inline');
+ assert.strictEqual(feedback.href, 'data:text/html,hello');
+ });
+
+ test('displayLabels', function() {
+ const controls = buildControls(this);
+ const selector = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'reference_display_label');
+ assert.strictEqual('none', getComputedStyle(selector).display);
+
+ controls.displayLabels = [];
+ assert.strictEqual('none', getComputedStyle(selector).display);
+
+ controls.displayLabels = ['Value'];
+ assert.strictEqual('none', getComputedStyle(selector).display);
+
+ controls.displayLabels = ['a', 'b\nc'];
+ assert.strictEqual('inline-block', getComputedStyle(selector).display);
+ assert.strictEqual('', selector.children[0].value);
+ assert.strictEqual('a', selector.children[1].value);
+ assert.strictEqual('a', selector.children[1].textContent);
+
+ // displayLabels can contain newlines, which <option> replace with spaces.
+ // histogram-set-controls must set option.value in order for selector.value
+ // to contain the newlines.
+ assert.strictEqual('b\nc', selector.children[2].value);
+ assert.strictEqual('b\nc', selector.children[2].textContent);
+ selector.selectedIndex = 2;
+ assert.strictEqual('b\nc', selector.value);
+
+ controls.displayLabels = ['Value'];
+ assert.strictEqual('none', getComputedStyle(selector).display);
+ });
+
+ test('baseStatisticNames', function() {
+ const controls = buildControls(this);
+ controls.baseStatisticNames = ['avg', 'std'];
+ const selector = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'statistic');
+ assert.strictEqual('inline-block', getComputedStyle(selector).display);
+ assert.lengthOf(selector.children, 2);
+ assert.strictEqual('avg', selector.children[0].value);
+ assert.strictEqual('avg', selector.children[0].textContent);
+ assert.strictEqual('std', selector.children[1].value);
+ assert.strictEqual('std', selector.children[1].textContent);
+ assert.strictEqual('avg', selector.value);
+ });
+
+ test('viewDisplayStatisticName', function() {
+ const controls = buildControls(this);
+ controls.baseStatisticNames = ['avg', 'std'];
+ const selector = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'statistic');
+ controls.viewState.displayStatisticName = 'std';
+ assert.strictEqual('std', selector.value);
+ });
+
+ test('controlDisplayStatisticName', function() {
+ const controls = buildControls(this);
+ controls.baseStatisticNames = ['avg', 'std'];
+ const selector = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'statistic');
+ selector.value = 'std';
+ const changeEvent = document.createEvent('HTMLEvents');
+ changeEvent.initEvent('change', false, true);
+ selector.dispatchEvent(changeEvent);
+ assert.strictEqual('std', controls.viewState.displayStatisticName);
+ });
+
+ test('viewSearchQuery', function() {
+ const controls = buildControls(this);
+ controls.viewState.searchQuery = 'foo';
+ const search = tr.ui.b.findDeepElementMatchingPredicate(
+ controls, e => e.id === 'search');
+ assert.strictEqual(search.value, 'foo');
+ });
+
+ test('controlSearchQuery', function() {
+ const controls = buildControls(this);
+ controls.searchQueryDebounceMs = 0;
+ const search = tr.ui.b.findDeepElementMatching(controls, '#search');
+ search.value = 'x';
+ const keyupEvent = document.createEvent('KeyboardEvent');
+ keyupEvent.initEvent('keyup');
+ search.dispatchEvent(keyupEvent);
+ assert.strictEqual(controls.viewState.searchQuery, 'x');
+ controls.clearSearch_();
+ assert.strictEqual(controls.viewState.searchQuery, '');
+ });
+
+ test('viewShowAll', function() {
+ const controls = buildControls(this);
+ const showAll = tr.ui.b.findDeepElementMatchingPredicate(
+ controls, e => e.id === 'show_all');
+ assert.strictEqual(controls.viewState.showAll, true);
+ assert.strictEqual(showAll.checked, true);
+ controls.viewState.showAll = false;
+ assert.strictEqual(showAll.checked, false);
+ });
+
+ test('controlShowAll', function() {
+ const controls = buildControls(this);
+ const showAll = tr.ui.b.findDeepElementMatchingPredicate(
+ controls, e => e.id === 'show_all');
+ assert.strictEqual(controls.viewState.showAll, true);
+ assert.strictEqual(showAll.checked, true);
+ showAll.click();
+ assert.strictEqual(showAll.checked, false);
+ assert.strictEqual(controls.viewState.showAll, false);
+ const showAllLabel = tr.ui.b.findDeepElementMatchingPredicate(
+ controls, e => e.tagName === 'LABEL' && e.htmlFor === 'show_all');
+ showAllLabel.click();
+ assert.strictEqual(showAll.checked, true);
+ assert.strictEqual(controls.viewState.showAll, true);
+ });
+
+ test('viewReferenceDisplayLabel', function() {
+ const controls = buildControls(this);
+ controls.displayLabels = ['a', 'b'];
+ const selector = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'reference_display_label');
+
+ assert.strictEqual('', selector.value);
+ assert.strictEqual('', controls.viewState.referenceDisplayLabel);
+
+ controls.viewState.referenceDisplayLabel = 'a';
+ assert.strictEqual('a', selector.value);
+
+ controls.viewState.referenceDisplayLabel = 'b';
+ assert.strictEqual('b', selector.value);
+
+ controls.viewState.referenceDisplayLabel = '';
+ assert.strictEqual('', selector.value);
+ });
+
+ test('controlReferenceDisplayLabel', function() {
+ const controls = buildControls(this);
+ controls.displayLabels = ['a', 'b'];
+ const selector = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'reference_display_label');
+ assert.strictEqual('', selector.value);
+ assert.strictEqual('', controls.viewState.referenceDisplayLabel);
+
+ selector.value = 'a';
+ const changeEvent = document.createEvent('HTMLEvents');
+ changeEvent.initEvent('change', false, true);
+ selector.dispatchEvent(changeEvent);
+ assert.strictEqual('a', controls.viewState.referenceDisplayLabel);
+
+ selector.value = 'b';
+ selector.dispatchEvent(changeEvent);
+ assert.strictEqual('b', controls.viewState.referenceDisplayLabel);
+
+ selector.value = '';
+ selector.dispatchEvent(changeEvent);
+ assert.strictEqual('', controls.viewState.referenceDisplayLabel);
+ });
+
+ test('viewGroupings', function() {
+ const controls = buildControls(this);
+ const fooGrouping = new tr.v.HistogramGrouping('foo', h => 'foo');
+ const groupings = Array.from(tr.v.HistogramGrouping.BY_KEY.values());
+ groupings.push(fooGrouping);
+ controls.possibleGroupings = groupings;
+ const picker = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.tagName === 'TR-UI-B-GROUPING-TABLE-GROUPBY-PICKER');
+ assert.lengthOf(picker.currentGroupKeys, 1);
+ assert.strictEqual(picker.currentGroupKeys[0],
+ tr.v.HistogramGrouping.HISTOGRAM_NAME.key);
+
+ controls.viewState.groupings = [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ ];
+ assert.lengthOf(picker.currentGroupKeys, 1);
+ assert.strictEqual(picker.currentGroupKeys[0],
+ tr.v.HistogramGrouping.HISTOGRAM_NAME.key);
+ assert.strictEqual('block', picker.style.display);
+
+ controls.viewState.groupings = [
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ fooGrouping,
+ ];
+ assert.lengthOf(picker.currentGroupKeys, 2);
+ assert.strictEqual(picker.currentGroupKeys[0],
+ tr.v.d.RESERVED_NAMES.STORIES);
+ assert.strictEqual(picker.currentGroupKeys[1], 'foo');
+ });
+
+ test('controlGroupings', function() {
+ const controls = buildControls(this);
+ const fooGrouping = new tr.v.HistogramGrouping('foo', h => 'foo');
+ const groupings = Array.from(tr.v.HistogramGrouping.BY_KEY.values());
+ groupings.push(fooGrouping);
+ controls.possibleGroupings = groupings;
+ const picker = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.tagName === 'TR-UI-B-GROUPING-TABLE-GROUPBY-PICKER');
+ assert.lengthOf(picker.currentGroupKeys, 1);
+ assert.strictEqual(controls.viewState.groupings[0].key,
+ tr.v.HistogramGrouping.HISTOGRAM_NAME.key);
+
+ picker.currentGroupKeys = ['name'];
+ assert.lengthOf(controls.viewState.groupings, 1);
+ assert.strictEqual(controls.viewState.groupings[0].key,
+ tr.v.HistogramGrouping.HISTOGRAM_NAME.key);
+
+ picker.currentGroupKeys = [tr.v.d.RESERVED_NAMES.STORIES, 'foo'];
+ assert.lengthOf(controls.viewState.groupings, 2);
+ assert.strictEqual(controls.viewState.groupings[0],
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES));
+ assert.strictEqual(controls.viewState.groupings[1],
+ fooGrouping);
+ });
+
+ test('viewIsOverviewed', function() {
+ const controls = buildControls(this);
+ const showOverview = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'show_overview');
+ const hideOverview = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'hide_overview');
+ controls.viewState.tableRowStates = new Map([
+ ['a', new tr.v.ui.HistogramSetTableRowState()],
+ ['b', new tr.v.ui.HistogramSetTableRowState()],
+ ]);
+ assert.strictEqual('inline', showOverview.style.display);
+ assert.strictEqual('none', hideOverview.style.display);
+
+ controls.viewState.tableRowStates.get('a').isOverviewed = true;
+ assert.strictEqual('none', showOverview.style.display);
+ assert.strictEqual('inline', hideOverview.style.display);
+
+ controls.viewState.tableRowStates.get('a').isOverviewed = false;
+ assert.strictEqual('inline', showOverview.style.display);
+ assert.strictEqual('none', hideOverview.style.display);
+ });
+
+ test('controlIsOverviewed', async function() {
+ const controls = buildControls(this);
+ const showOverview = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'show_overview');
+ const hideOverview = tr.ui.b.findDeepElementMatchingPredicate(controls, e =>
+ e.id === 'hide_overview');
+ controls.viewState.tableRowStates = new Map([
+ ['a', new tr.v.ui.HistogramSetTableRowState()],
+ ['b', new tr.v.ui.HistogramSetTableRowState()],
+ ]);
+ assert.isFalse(controls.viewState.tableRowStates.get('a').isOverviewed);
+ assert.isFalse(controls.viewState.tableRowStates.get('b').isOverviewed);
+ assert.strictEqual('inline', showOverview.style.display);
+ assert.strictEqual('none', hideOverview.style.display);
+
+ await controls.toggleOverviewLineCharts_();
+ assert.strictEqual('none', showOverview.style.display);
+ assert.strictEqual('inline', hideOverview.style.display);
+ assert.isTrue(controls.viewState.tableRowStates.get('a').isOverviewed);
+ assert.isTrue(controls.viewState.tableRowStates.get('b').isOverviewed);
+
+ await controls.toggleOverviewLineCharts_();
+ assert.strictEqual('inline', showOverview.style.display);
+ assert.strictEqual('none', hideOverview.style.display);
+ assert.isFalse(controls.viewState.tableRowStates.get('a').isOverviewed);
+ assert.isFalse(controls.viewState.tableRowStates.get('b').isOverviewed);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_location.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_location.html
new file mode 100644
index 00000000000..882806ba32b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_location.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/base/url_json.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view_state.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ // This number is used to decide whether the tableStates can fit in the URL,
+ // and omit them if not.
+ // There is no specification for maximum URL length, so it is typically
+ // limited by hosts, not browsers.
+ // TODO(#3816) Tune this number.
+ const MAX_URL_LENGTH = 2048;
+
+ // This class wraps |window.location| and |window.history| to allow tests to
+ // mock it.
+ class Locus {
+ get origin() {
+ return window.location.origin;
+ }
+
+ get pathname() {
+ return window.location.pathname;
+ }
+
+ get search() {
+ return window.location.search;
+ }
+
+ get hash() {
+ return window.location.hash;
+ }
+
+ get state() {
+ if (this.stateMode === '#') return this.hash.substr(1);
+ return this.search.substr(1);
+ }
+
+ get stateMode() {
+ if (this.hash) return '#';
+ return '?';
+ }
+
+ buildUrlFromState(state) {
+ let url = this.origin + this.pathname;
+ if (this.stateMode === '#') url += this.search;
+ url += this.stateMode + state;
+ return url;
+ }
+
+ pushState(state) {
+ if (state === this.state) return;
+
+ // TODO(#3837) When should this actually call pushState()?
+ window.history.replaceState(null, null, this.buildUrlFromState(state));
+ }
+
+ addPopStateListener(listener) {
+ window.addEventListener('popstate', listener);
+ }
+ }
+
+ class HistogramSetLocation {
+ constructor(opt_location) {
+ // Optional dependency injection for testing.
+ this.location_ = opt_location || new Locus();
+ this.location_.addPopStateListener(this.onPopState_.bind(this));
+
+ this.viewState_ = undefined;
+ this.rowListener_ = this.onRowStateUpdate_.bind(this);
+ this.cellListener_ = this.onCellStateUpdate_.bind(this);
+
+ // pushState_ is disabled while handling onPopState_.
+ this.poppingState_ = false;
+ }
+
+ /**
+ * @return {!tr.v.ui.HistogramSetViewState}
+ */
+ get viewState() {
+ return this.viewState_;
+ }
+
+ /**
+ * @param {!tr.v.ui.HistogramSetViewState} vs
+ */
+ async build(vs) {
+ if (this.viewState !== undefined) {
+ throw new Error('viewState must be set exactly once.');
+ }
+ this.viewState_ = vs;
+ this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));
+
+ await this.onPopState_();
+ }
+
+ onViewStateUpdate_(event) {
+ if (event.delta.tableRowStates) {
+ for (const row of tr.v.ui.HistogramSetTableRowState.walkAll(
+ event.delta.tableRowStates.previous.values())) {
+ row.removeUpdateListener(this.rowListener_);
+ for (const cell of row.cells.values()) {
+ cell.removeUpdateListener(this.cellListener_);
+ }
+ }
+ for (const row of tr.v.ui.HistogramSetTableRowState.walkAll(
+ event.delta.tableRowStates.current.values())) {
+ row.addUpdateListener(this.rowListener_);
+ for (const cell of row.cells.values()) {
+ cell.addUpdateListener(this.cellListener_);
+ }
+ }
+ }
+
+ this.pushState_();
+ }
+
+ onRowStateUpdate_(event) {
+ // This assumes that subRows and cells are not updated.
+ this.pushState_();
+ }
+
+ onCellStateUpdate_(event) {
+ this.pushState_();
+ }
+
+ pushState_() {
+ if (this.poppingState_) return;
+ const mark = tr.b.Timing.mark('HistogramSetLocation', 'pushState');
+
+ const params = new Map();
+ if (this.viewState.searchQuery) {
+ params.set('q', this.viewState.searchQuery);
+ }
+ if (this.viewState.referenceDisplayLabel) {
+ params.set('r', this.viewState.referenceDisplayLabel);
+ }
+ params.set('s', this.viewState.displayStatisticName);
+ if (!this.viewState.showAll) params.set('m', '');
+ params.set('g', this.viewState.groupings.map(g => g.key).join('.'));
+ if (this.viewState.sortColumnIndex !== undefined) {
+ params.set('c', '' + this.viewState.sortColumnIndex);
+ }
+ if (this.viewState.sortDescending) params.set('d', '');
+ if (!this.viewState.constrainNameColumn) params.set('n', '0');
+ if (!tr.b.math.approximately(this.viewState.alpha, 0.01)) {
+ params.set('p', ('' + this.viewState.alpha).substr(0, 5));
+ }
+
+ let urlState = '';
+ for (const [key, value] of params) {
+ if (urlState) urlState += '&';
+ urlState += key + '=' + window.encodeURIComponent(value);
+ }
+
+ const rowDicts = {};
+ for (const [name, rowState] of this.viewState.tableRowStates) {
+ const dict = rowState.asCompactDict();
+ if (dict === undefined) continue;
+ rowDicts[name] = dict;
+ }
+
+ if (Object.keys(rowDicts).length > 0) {
+ const rowsParam = '&t=' + tr.b.UrlJson.stringify(rowDicts);
+
+ if (this.location_.buildUrlFromState(urlState + rowsParam).length <
+ MAX_URL_LENGTH) {
+ urlState += rowsParam;
+ }
+ }
+
+ this.location_.pushState(urlState);
+ mark.end();
+ }
+
+ async onPopState_() {
+ const mark = tr.b.Timing.mark('HistogramSetLocation', 'onPopState');
+ this.poppingState_ = true;
+
+ const params = new Map();
+ for (const kvp of this.location_.state.split('&')) {
+ const [key, value] = kvp.split('=');
+ try {
+ params.set(key, window.decodeURIComponent(value));
+ } catch (e) {
+ // If the user tampers with the params so that a value cannot be
+ // decoded, ignore it.
+ }
+ }
+
+ const delta = new Map();
+ if (params.has('q')) delta.set('searchQuery', params.get('q'));
+ if (params.has('r')) delta.set('referenceDisplayLabel', params.get('r'));
+ if (params.has('s')) delta.set('displayStatisticName', params.get('s'));
+ delta.set('showAll', !params.has('m'));
+ if (params.has('g')) {
+ delta.set('groupings', params.get('g').split('.').map(
+ k => tr.v.HistogramGrouping.BY_KEY.get(k)));
+ }
+ if (params.has('c')) {
+ delta.set('sortColumnIndex', parseInt(params.get('c')));
+ } else {
+ delta.set('sortColumnIndex', 0);
+ }
+ delta.set('sortDescending', params.has('d'));
+ delta.set('constrainNameColumn', params.get('n') !== '0');
+ if (params.has('p')) {
+ delta.set('alpha', parseFloat(params.get('p')));
+ }
+
+ await this.viewState.update(delta);
+
+ if (params.has('t')) {
+ let rowDicts;
+ try {
+ rowDicts = tr.b.UrlJson.parse(params.get('t'));
+ } catch (e) {
+ // If the user tampers with the params so that rowDicts cannot be
+ // parsed, ignore it.
+ }
+
+ if (rowDicts) {
+ for (const [name, rowDict] of Object.entries(rowDicts)) {
+ const rowState = this.viewState.tableRowStates.get(name);
+ if (rowState === undefined) continue;
+ await rowState.updateFromCompactDict(rowDict);
+ }
+ }
+ }
+
+ this.poppingState_ = false;
+ mark.end();
+ }
+ }
+
+ HistogramSetLocation.Locus = Locus;
+
+ return {
+ HistogramSetLocation,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_location_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_location_test.html
new file mode 100644
index 00000000000..d9987e7b097
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_location_test.html
@@ -0,0 +1,290 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/ui/histogram_set_location.html">
+
+<script>
+'use strict';
+/* eslint-disable max-len */
+tr.b.unittest.testSuite(function() {
+ class TestLocus extends tr.v.ui.HistogramSetLocation.Locus {
+ constructor() {
+ super();
+ this.search_ = '';
+ this.hash_ = '';
+ this.listener_ = undefined;
+ }
+
+ get origin() {
+ return 'http://example.com';
+ }
+
+ get pathname() {
+ return '/pathname';
+ }
+
+ get search() {
+ return this.search_;
+ }
+
+ set search(s) {
+ this.search_ = s;
+ }
+
+ get hash() {
+ return this.hash_;
+ }
+
+ set hash(h) {
+ this.hash_ = h;
+ }
+
+ pushState(state) {
+ if (this.hash) {
+ this.hash = '#' + state;
+ } else {
+ this.search = '?' + state;
+ }
+ }
+
+ get stateMode() {
+ if (this.hash) return '#';
+ return '?';
+ }
+
+ addPopStateListener(listener) {
+ this.listener_ = listener;
+ }
+
+ async popState(state) {
+ if (state[0] === '?') {
+ this.search = state;
+ } else if (state[0] === '#') {
+ this.hash = state;
+ }
+ await this.listener_();
+ }
+ }
+
+ test('viewStateUpdateHashAndSearch', async function() {
+ const locus = new TestLocus();
+ locus.search = '?';
+ locus.hash = '#';
+ const hsl = new tr.v.ui.HistogramSetLocation(locus);
+ await hsl.build(new tr.v.ui.HistogramSetViewState());
+
+ await hsl.viewState.update({
+ displayStatisticName: 'avg',
+ groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ],
+ sortColumnIndex: undefined,
+ });
+ assert.strictEqual(locus.hash, '#s=avg&g=name.stories');
+ });
+
+ test('viewStateUpdateHash', async function() {
+ const locus = new TestLocus();
+ locus.hash = '#';
+ const hsl = new tr.v.ui.HistogramSetLocation(locus);
+ await hsl.build(new tr.v.ui.HistogramSetViewState());
+
+ await hsl.viewState.update({
+ displayStatisticName: 'avg',
+ groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ],
+ sortColumnIndex: undefined,
+ });
+ assert.strictEqual(locus.hash, '#s=avg&g=name.stories');
+
+ await hsl.viewState.update({searchQuery: 'foo'});
+ assert.strictEqual(locus.hash, '#q=foo&s=avg&g=name.stories');
+
+ await hsl.viewState.update({referenceDisplayLabel: 'bar'});
+ assert.strictEqual(locus.hash, '#q=foo&r=bar&s=avg&g=name.stories');
+
+ await hsl.viewState.update({showAll: false});
+ assert.strictEqual(locus.hash, '#q=foo&r=bar&s=avg&m=&g=name.stories');
+
+ await hsl.viewState.update({sortColumnIndex: 2});
+ assert.strictEqual(locus.hash, '#q=foo&r=bar&s=avg&m=&g=name.stories&c=2');
+
+ await hsl.viewState.update({sortDescending: true});
+ assert.strictEqual(locus.hash, '#q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=');
+
+ await hsl.viewState.update({constrainNameColumn: false});
+ assert.strictEqual(locus.hash,
+ '#q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=&n=0');
+
+ const rowState = new tr.v.ui.HistogramSetTableRowState();
+ rowState.cells.set('Value', new tr.v.ui.HistogramSetTableCellState());
+ await hsl.viewState.update({tableRowStates: new Map([['fmp', rowState]])});
+ assert.strictEqual(locus.hash,
+ '#q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=&n=0');
+
+ await hsl.viewState.tableRowStates.get('fmp').update({isExpanded: true});
+ assert.strictEqual(locus.hash,
+ '#q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=&n=0&t=fmp-(e-1)');
+
+ await hsl.viewState.tableRowStates.get('fmp').cells.get('Value').update({
+ isOpen: true,
+ });
+ assert.strictEqual(locus.hash,
+ '#q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=&n=0&t=fmp-(e-1.c-(Value-(o-1)))');
+ });
+
+ test('viewStateUpdateSearch', async function() {
+ const locus = new TestLocus();
+ const hsl = new tr.v.ui.HistogramSetLocation(locus);
+ await hsl.build(new tr.v.ui.HistogramSetViewState());
+
+ await hsl.viewState.update({
+ displayStatisticName: 'avg',
+ groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ],
+ sortColumnIndex: undefined,
+ });
+ assert.strictEqual(locus.search, '?s=avg&g=name.stories');
+
+ await hsl.viewState.update({searchQuery: 'foo'});
+ assert.strictEqual(locus.search, '?q=foo&s=avg&g=name.stories');
+
+ await hsl.viewState.update({referenceDisplayLabel: 'bar'});
+ assert.strictEqual(locus.search, '?q=foo&r=bar&s=avg&g=name.stories');
+
+ await hsl.viewState.update({showAll: false});
+ assert.strictEqual(locus.search, '?q=foo&r=bar&s=avg&m=&g=name.stories');
+
+ await hsl.viewState.update({sortColumnIndex: 2});
+ assert.strictEqual(locus.search, '?q=foo&r=bar&s=avg&m=&g=name.stories&c=2');
+
+ await hsl.viewState.update({sortDescending: true});
+ assert.strictEqual(locus.search, '?q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=');
+
+ await hsl.viewState.update({constrainNameColumn: false});
+ assert.strictEqual(locus.search,
+ '?q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=&n=0');
+
+ const rowState = new tr.v.ui.HistogramSetTableRowState();
+ rowState.cells.set('Value', new tr.v.ui.HistogramSetTableCellState());
+ await hsl.viewState.update({tableRowStates: new Map([['fmp', rowState]])});
+ assert.strictEqual(locus.search,
+ '?q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=&n=0');
+
+ await hsl.viewState.tableRowStates.get('fmp').update({isExpanded: true});
+ assert.strictEqual(locus.search,
+ '?q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=&n=0&t=fmp-(e-1)');
+
+ await hsl.viewState.tableRowStates.get('fmp').cells.get('Value').update({
+ isOpen: true,
+ });
+ assert.strictEqual(locus.search,
+ '?q=foo&r=bar&s=avg&m=&g=name.stories&c=2&d=&n=0&t=fmp-(e-1.c-(Value-(o-1)))');
+ });
+
+ test('popStateSearch', async function() {
+ const locus = new TestLocus();
+ const hsl = new tr.v.ui.HistogramSetLocation(locus);
+ await hsl.build(new tr.v.ui.HistogramSetViewState());
+
+ await locus.popState('?q=foo&r=bar&s=qux&m=&c=2&d=&g=name.stories');
+ assert.strictEqual('foo', hsl.viewState.searchQuery);
+ assert.strictEqual('bar', hsl.viewState.referenceDisplayLabel);
+ assert.strictEqual('qux', hsl.viewState.displayStatisticName);
+ assert.isFalse(hsl.viewState.showAll);
+ assert.lengthOf(hsl.viewState.groupings, 2);
+ assert.strictEqual('name', hsl.viewState.groupings[0].key);
+ assert.strictEqual('stories', hsl.viewState.groupings[1].key);
+ assert.strictEqual(2, hsl.viewState.sortColumnIndex);
+ assert.isTrue(hsl.viewState.sortDescending);
+
+ // onPopState_ should ignore missing rows and cells
+ await locus.popState('?t=f%3Am_p-(o-1)');
+ assert.strictEqual(0, hsl.viewState.tableRowStates.size);
+
+ await hsl.viewState.update({tableRowStates: new Map([
+ ['f:m_p', new tr.v.ui.HistogramSetTableRowState()],
+ ])});
+ assert.isFalse(hsl.viewState.tableRowStates.get('f:m_p').isExpanded);
+
+ await locus.popState('?t=f%3Am_p-(e-1)');
+ assert.strictEqual(0, hsl.viewState.tableRowStates.get('f:m_p').cells.size);
+ assert.isTrue(hsl.viewState.tableRowStates.get('f:m_p').isExpanded);
+
+ await hsl.viewState.tableRowStates.get('f:m_p').update({cells: new Map([
+ ['Value', new tr.v.ui.HistogramSetTableCellState()],
+ ])});
+ assert.isFalse(hsl.viewState.tableRowStates.get('f:m_p').cells.get('Value').isOpen);
+
+ await locus.popState('?t=f%3Am_p-(c-(Value-(o-1)))');
+ assert.isTrue(hsl.viewState.tableRowStates.get('f:m_p').cells.get('Value').isOpen);
+ });
+
+ test('popStateHashAndSearch', async function() {
+ const locus = new TestLocus();
+ const hsl = new tr.v.ui.HistogramSetLocation(locus);
+ await hsl.build(new tr.v.ui.HistogramSetViewState());
+
+ await locus.popState('?q=foo&r=bar&s=qux&a=&c=2&d=&g=name.stories');
+ assert.strictEqual('foo', hsl.viewState.searchQuery);
+ assert.strictEqual('bar', hsl.viewState.referenceDisplayLabel);
+ assert.strictEqual('qux', hsl.viewState.displayStatisticName);
+ assert.isTrue(hsl.viewState.showAll);
+ assert.lengthOf(hsl.viewState.groupings, 2);
+ assert.strictEqual('name', hsl.viewState.groupings[0].key);
+ assert.strictEqual('stories', hsl.viewState.groupings[1].key);
+ assert.strictEqual(2, hsl.viewState.sortColumnIndex);
+ assert.isTrue(hsl.viewState.sortDescending);
+
+ await locus.popState('#q=q');
+ assert.strictEqual('q', hsl.viewState.searchQuery);
+ });
+
+ test('popStateHash', async function() {
+ const locus = new TestLocus();
+ const hsl = new tr.v.ui.HistogramSetLocation(locus);
+ await hsl.build(new tr.v.ui.HistogramSetViewState());
+
+ await locus.popState('#q=foo&r=bar&s=qux&a=&c=2&d=&g=name.stories');
+ assert.strictEqual('foo', hsl.viewState.searchQuery);
+ assert.strictEqual('bar', hsl.viewState.referenceDisplayLabel);
+ assert.strictEqual('qux', hsl.viewState.displayStatisticName);
+ assert.isTrue(hsl.viewState.showAll);
+ assert.lengthOf(hsl.viewState.groupings, 2);
+ assert.strictEqual('name', hsl.viewState.groupings[0].key);
+ assert.strictEqual('stories', hsl.viewState.groupings[1].key);
+ assert.strictEqual(2, hsl.viewState.sortColumnIndex);
+ assert.isTrue(hsl.viewState.sortDescending);
+
+ // onPopState_ should ignore missing rows and cells
+ await locus.popState('#t=f%3Am_p-(o-1)');
+ assert.strictEqual(0, hsl.viewState.tableRowStates.size);
+
+ await hsl.viewState.update({tableRowStates: new Map([
+ ['f:m_p', new tr.v.ui.HistogramSetTableRowState()],
+ ])});
+ assert.isFalse(hsl.viewState.tableRowStates.get('f:m_p').isExpanded);
+
+ await locus.popState('#t=f%3Am_p-(e-1)');
+ assert.strictEqual(0, hsl.viewState.tableRowStates.get('f:m_p').cells.size);
+ assert.isTrue(hsl.viewState.tableRowStates.get('f:m_p').isExpanded);
+
+ await hsl.viewState.tableRowStates.get('f:m_p').update({cells: new Map([
+ ['Value', new tr.v.ui.HistogramSetTableCellState()],
+ ])});
+ assert.isFalse(hsl.viewState.tableRowStates.get('f:m_p').cells.get('Value').isOpen);
+
+ await locus.popState('#t=f%3Am_p-(c-(Value-(o-1)))');
+ assert.isTrue(hsl.viewState.tableRowStates.get('f:m_p').cells.get('Value').isOpen);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table.html
new file mode 100644
index 00000000000..9ac3046c5d3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table.html
@@ -0,0 +1,459 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+<link rel="import" href="/tracing/value/histogram_set_hierarchy.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_table_row.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view_state.html">
+
+<dom-module id="tr-v-ui-histogram-set-table">
+ <template>
+ <style>
+ :host {
+ min-height: 0px;
+ overflow: auto;
+ }
+ #table {
+ margin-top: 5px;
+ }
+ </style>
+
+ <tr-ui-b-table id="table"/>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ const MIDLINE_HORIZONTAL_ELLIPSIS = String.fromCharCode(0x22ef);
+
+ // http://stackoverflow.com/questions/3446170
+ function escapeRegExp(str) {
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
+ }
+
+ Polymer({
+ is: 'tr-v-ui-histogram-set-table',
+
+ created() {
+ this.viewState_ = undefined;
+ this.progress_ = () => Promise.resolve();
+ this.nameColumnTitle_ = undefined;
+ this.displayLabels_ = [];
+ this.histograms_ = undefined;
+ this.sourceHistograms_ = undefined;
+ this.filteredHistograms_ = undefined;
+ this.groupedHistograms_ = undefined;
+ this.hierarchies_ = undefined;
+ this.tableRows_ = undefined;
+
+ // Store this listener so it can be removed while updateContents_ modifies
+ // sortColumnIndex and sortDescending, then re-added.
+ this.sortColumnChangedListener_ = e => this.onSortColumnChanged_(e);
+ },
+
+ ready() {
+ this.$.table.zebra = true;
+ this.addEventListener('sort-column-changed',
+ this.sortColumnChangedListener_);
+ this.addEventListener('requestSelectionChange',
+ this.onRequestSelectionChange_.bind(this));
+ this.addEventListener('row-expanded-changed',
+ this.onRowExpandedChanged_.bind(this));
+ },
+
+ get viewState() {
+ return this.viewState_;
+ },
+
+ set viewState(vs) {
+ if (this.viewState_) {
+ throw new Error('viewState must be set exactly once.');
+ }
+ this.viewState_ = vs;
+ this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));
+ // It would be arduous to construct a delta and call onViewStateUpdate_
+ // here in case vs contains non-default values, so callers must set
+ // viewState first and then update it.
+ },
+
+ get histograms() {
+ return this.histograms_;
+ },
+
+ /**
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!tr.v.HistogramSet} sourceHistograms
+ * @param {!Array.<string>} displayLabels
+ * @param {function(string, function())=} opt_progress
+ */
+ async build(histograms, sourceHistograms, displayLabels, opt_progress) {
+ this.histograms_ = histograms;
+ this.sourceHistograms_ = sourceHistograms;
+ this.filteredHistograms_ = undefined;
+ this.groupedHistograms_ = undefined;
+ this.displayLabels_ = displayLabels;
+
+ if (opt_progress !== undefined) this.progress_ = opt_progress;
+
+ if (histograms.length === 0) {
+ throw new Error('histogram-set-table requires non-empty HistogramSet.');
+ }
+
+ await this.progress_('Building columns...');
+ this.$.table.tableColumns = [
+ {
+ title: this.buildNameColumnTitle_(),
+ value: row => row.nameCell,
+ cmp: (a, b) => a.compareNames(b),
+ }
+ ].concat(displayLabels.map(l => this.buildColumn_(l)));
+
+ tr.b.Timing.instant('histogram-set-table', 'columnCount',
+ this.$.table.tableColumns.length);
+
+ // updateContents_() displays its own progress.
+ await this.updateContents_();
+
+ // Building some elements requires being able to measure them, which is
+ // impossible until they are displayed. If clients hide this table while
+ // it is being built, then they must display it when this event fires.
+ this.fire('display-ready');
+
+ this.progress_ = () => Promise.resolve();
+
+ this.checkNameColumnOverflow_(
+ tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows));
+ },
+
+ buildNameColumnTitle_() {
+ this.nameColumnTitle_ = document.createElement('span');
+ this.nameColumnTitle_.style.display = 'inline-flex';
+
+ // Wrap the string in a span instead of using createTextNode() so that the
+ // span can be styled later.
+ const nameEl = document.createElement('span');
+ nameEl.textContent = 'Name';
+ this.nameColumnTitle_.appendChild(nameEl);
+
+ const toggleWidthEl = document.createElement('span');
+ toggleWidthEl.style.fontWeight = 'bold';
+ toggleWidthEl.style.background = '#bbb';
+ toggleWidthEl.style.color = '#333';
+ toggleWidthEl.style.padding = '0px 3px';
+ toggleWidthEl.style.marginRight = '8px';
+ toggleWidthEl.style.display = 'none';
+ toggleWidthEl.textContent = MIDLINE_HORIZONTAL_ELLIPSIS;
+ toggleWidthEl.addEventListener('click',
+ this.toggleNameColumnWidth_.bind(this));
+ this.nameColumnTitle_.appendChild(toggleWidthEl);
+ return this.nameColumnTitle_;
+ },
+
+ toggleNameColumnWidth_(opt_event) {
+ this.viewState.update({
+ constrainNameColumn: !this.viewState.constrainNameColumn,
+ });
+
+ if (opt_event !== undefined) {
+ opt_event.stopPropagation();
+ opt_event.preventDefault();
+ tr.b.Timing.instant('histogram-set-table', 'nameColumn' +
+ (this.viewState.constrainNameColumn ? 'Constrained' :
+ 'Unconstrained'));
+ }
+ },
+
+ buildColumn_(displayLabel) {
+ const title = document.createElement('span');
+ title.textContent = displayLabel;
+ title.style.whiteSpace = 'pre';
+
+ return {
+ displayLabel,
+ title,
+ value: row => row.getCell(displayLabel),
+ cmp: (rowA, rowB) => rowA.compareCells(rowB, displayLabel),
+ };
+ },
+
+ async updateContents_() {
+ const previousRowStates = this.viewState.tableRowStates;
+
+ if (!this.filteredHistograms_) {
+ await this.progress_('Filtering rows...');
+ this.filteredHistograms_ = this.viewState.showAll ?
+ this.histograms : this.sourceHistograms_;
+
+ if (this.viewState.searchQuery) {
+ let query;
+ try {
+ query = new RegExp(this.viewState.searchQuery);
+ } catch (e) {
+ }
+ if (query !== undefined) {
+ this.filteredHistograms_ = new tr.v.HistogramSet(
+ [...this.filteredHistograms_].filter(
+ hist => hist.name.match(query)));
+ if (this.filteredHistograms_.length === 0 &&
+ !this.viewState.showAll) {
+ await this.viewState.update({showAll: true});
+ return;
+ }
+ }
+ }
+ this.groupedHistograms_ = undefined;
+ }
+
+ if (!this.groupedHistograms_) {
+ await this.progress_('Grouping Histograms...');
+ this.groupHistograms_();
+ }
+
+ if (!this.hierarchies_) {
+ await this.progress_('Merging Histograms...');
+ this.hierarchies_ = tr.v.HistogramSetHierarchy.build(
+ this.groupedHistograms_);
+ this.tableRows_ = undefined;
+ }
+
+ const tableRowsDirty = this.tableRows_ === undefined;
+ if (tableRowsDirty) {
+ // Wait to set this.$.table.tableRows until we're ready for it to build
+ // DOM. When tableRows are set on it, tr-ui-b-table calls
+ // setTimeout(..., 0) to schedule rebuild for the next interpreter tick,
+ // but that can happen in between the next await, which is too early.
+ this.tableRows_ = this.hierarchies_.map(hierarchy =>
+ new tr.v.ui.HistogramSetTableRow(
+ hierarchy, this.$.table, this.viewState));
+
+ tr.b.Timing.instant('histogram-set-table', 'rootRowCount',
+ this.tableRows_.length);
+
+ const namesToRowStates = new Map();
+ for (const row of this.tableRows_) {
+ namesToRowStates.set(row.name, row.viewState);
+ }
+ await this.viewState.update({tableRowStates: namesToRowStates});
+ }
+
+ await this.progress_('Configuring table...');
+ this.nameColumnTitle_.children[1].style.filter =
+ this.viewState.constrainNameColumn ? 'invert(100%)' : '';
+
+ const referenceDisplayLabelIndex = this.displayLabels_.indexOf(
+ this.viewState.referenceDisplayLabel);
+ this.$.table.selectedTableColumnIndex = (referenceDisplayLabelIndex < 0) ?
+ undefined : (1 + referenceDisplayLabelIndex);
+
+ // Temporarily stop listening for this event in order to prevent the
+ // listener from updating viewState unnecessarily.
+ this.removeEventListener('sort-column-changed',
+ this.sortColumnChangedListener_);
+ this.$.table.sortColumnIndex = this.viewState.sortColumnIndex;
+ this.$.table.sortDescending = this.viewState.sortDescending;
+ this.addEventListener('sort-column-changed',
+ this.sortColumnChangedListener_);
+
+ // Each name-cell listens to this.viewState for updates to
+ // constrainNameColumn.
+ // Each table-cell listens to this.viewState for updates to
+ // displayStatisticName and referenceDisplayLabel.
+
+ if (tableRowsDirty) {
+ await this.progress_('Building DOM...');
+ this.$.table.tableRows = this.tableRows_;
+
+ // Try to restore previous row state.
+ // Wait to do this until after the base table has the new rows so that
+ // setExpandedForTableRow doesn't get confused.
+ for (const row of this.tableRows_) {
+ const previousState = previousRowStates.get(row.name);
+ if (!previousState) continue;
+ await row.restoreState(previousState);
+ }
+ }
+
+ // It's always safe to call this, it will only recompute what is dirty.
+ // We want to make sure that the table is up to date when this async
+ // function resolves.
+ this.$.table.rebuild();
+ },
+
+ async onRowExpandedChanged_(event) {
+ event.row.viewState.isExpanded =
+ this.$.table.getExpandedForTableRow(event.row);
+ tr.b.Timing.instant('histogram-set-table',
+ 'row' + (event.row.viewState.isExpanded ? 'Expanded' : 'Collapsed'));
+
+ // When the user expands a row, the table builds subRows' name-cells.
+ // If a subRow's name isOverflowing even though none of the top-level rows
+ // are constrained, show the dots to allow the user to unconstrain the
+ // name column.
+ // Each name-cell.isOverflowing would force layout if we don't await
+ // animationFrame here, which would be inefficient.
+ if (this.nameColumnTitle_.children[1].style.display === 'block') return;
+ await tr.b.animationFrame();
+ this.checkNameColumnOverflow_(event.row.subRows);
+ },
+
+ checkNameColumnOverflow_(rows) {
+ for (const row of rows) {
+ if (!row.nameCell.isOverflowing) continue;
+
+ const [nameSpan, dots] = this.nameColumnTitle_.children;
+ dots.style.display = 'block';
+
+ // Size the span containing 'Name' so that the dots align with the
+ // ellipses in the name-cells.
+ const labelWidthPx = tr.v.ui.NAME_COLUMN_WIDTH_PX -
+ dots.getBoundingClientRect().width;
+ nameSpan.style.width = labelWidthPx + 'px';
+
+ return;
+ }
+ },
+
+ groupHistograms_() {
+ const groupings = this.viewState.groupings.slice();
+ groupings.push(tr.v.HistogramGrouping.DISPLAY_LABEL);
+
+ function canSkipGrouping(grouping, groupedHistograms) {
+ // Never skip meaningful groupings.
+ if (groupedHistograms.size > 1) return false;
+
+ // Never skip the zero-th grouping.
+ if (grouping.key === groupings[0].key) return false;
+
+ // Never skip the grouping that defines the table columns.
+ if (grouping.key === tr.v.HistogramGrouping.DISPLAY_LABEL.key) {
+ return false;
+ }
+
+ // Skip meaningless groupings.
+ return true;
+ }
+
+ this.groupedHistograms_ =
+ this.filteredHistograms_.groupHistogramsRecursively(
+ groupings, canSkipGrouping);
+
+ this.hierarchies_ = undefined;
+ },
+
+ /**
+ * @param {!tr.b.Event} event
+ * @param {!Object} event.delta
+ * @param {!Object} event.delta.searchQuery
+ * @param {!Object} event.delta.referenceDisplayLabel
+ * @param {!Object} event.delta.displayStatisticName
+ * @param {!Object} event.delta.showAll
+ * @param {!Object} event.delta.groupings
+ * @param {!Object} event.delta.sortColumnIndex
+ * @param {!Object} event.delta.sortDescending
+ * @param {!Object} event.delta.constrainNameColumn
+ * @param {!Object} event.delta.tableRowStates
+ */
+ async onViewStateUpdate_(event) {
+ if (this.histograms_ === undefined) return;
+
+ if (event.delta.searchQuery !== undefined ||
+ event.delta.showAll !== undefined) {
+ this.filteredHistograms_ = undefined;
+ }
+
+ if (event.delta.groupings !== undefined) {
+ this.groupedHistograms_ = undefined;
+ }
+
+ if (event.delta.displayStatistic !== undefined &&
+ this.$.table.sortColumnIndex > 0) {
+ // Force re-sort.
+ this.$.table.sortColumnIndex = undefined;
+ }
+
+ if (event.delta.referenceDisplayLabel !== undefined ||
+ event.delta.displayStatisticName !== undefined) {
+ // Force this.$.table.bodyDirty_ = true;
+ this.$.table.tableRows = this.$.table.tableRows;
+ }
+
+ // updateContents_() always copies sortColumnIndex and sortDescending
+ // from the viewState to the table. The table will only re-sort if
+ // they change.
+
+ // Name-cells listen to this.viewState to handle updates to
+ // constrainNameColumn.
+
+ if (event.delta.tableRowStates) {
+ if (this.tableRows_.length !==
+ this.viewState.tableRowStates.size) {
+ throw new Error(
+ 'Only histogram-set-table may update tableRowStates');
+ }
+ for (const row of this.tableRows_) {
+ if (this.viewState.tableRowStates.get(row.name) !== row.viewState) {
+ throw new Error(
+ 'Only histogram-set-table may update tableRowStates');
+ }
+ }
+ return; // No need to re-enter updateContents_().
+ }
+
+ await this.updateContents_();
+ },
+
+ onSortColumnChanged_(event) {
+ tr.b.Timing.instant('histogram-set-table', 'sortColumn');
+ this.viewState.update({
+ sortColumnIndex: event.sortColumnIndex,
+ sortDescending: event.sortDescending,
+ });
+ },
+
+ onRequestSelectionChange_(event) {
+ // This event may reference an EventSet or an array of Histogram names.
+ // If EventSet, let the BrushingStateController handle it.
+ if (event.selection instanceof tr.model.EventSet) return;
+
+ event.stopPropagation();
+ tr.b.Timing.instant('histogram-set-table', 'selectHistogramNames');
+
+ let histogramNames = event.selection;
+ histogramNames.sort();
+ histogramNames = histogramNames.map(escapeRegExp).join('|');
+ this.viewState.update({
+ showAll: true,
+ searchQuery: `^(${histogramNames})$`,
+ });
+ },
+
+ /**
+ * @return {!tr.v.HistogramSet}
+ */
+ get leafHistograms() {
+ const histograms = new tr.v.HistogramSet();
+ for (const row of
+ tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows)) {
+ if (row.subRows.length) continue;
+ for (const hist of row.columns.values()) {
+ if (!(hist instanceof tr.v.Histogram)) continue;
+
+ histograms.addHistogram(hist);
+ }
+ }
+ return histograms;
+ }
+ });
+
+ return {
+ MIDLINE_HORIZONTAL_ELLIPSIS,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_cell.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_cell.html
new file mode 100644
index 00000000000..8a1d158d021
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_cell.html
@@ -0,0 +1,396 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/base/name_line_chart.html">
+<link rel="import" href="/tracing/value/ui/histogram_span.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id="tr-v-ui-histogram-set-table-cell">
+ <template>
+ <style>
+ #histogram_container {
+ display: flex;
+ flex-direction: row;
+ }
+
+ #missing, #empty, #unmergeable, #scalar {
+ flex-grow: 1;
+ }
+
+ #open_histogram, #close_histogram, #open_histogram svg, #close_histogram svg {
+ height: 1em;
+ }
+
+ #open_histogram svg {
+ margin-left: 4px;
+ stroke-width: 0;
+ stroke: blue;
+ fill: blue;
+ }
+ :host(:hover) #open_histogram svg {
+ background: blue;
+ stroke: white;
+ fill: white;
+ }
+
+ #scalar {
+ flex-grow: 1;
+ white-space: nowrap;
+ }
+
+ #histogram {
+ flex-grow: 1;
+ }
+
+ #close_histogram svg line {
+ stroke-width: 18;
+ stroke: black;
+ }
+ #close_histogram:hover svg {
+ background: black;
+ }
+ #close_histogram:hover svg line {
+ stroke: white;
+ }
+
+ #overview_container {
+ display: none;
+ }
+ </style>
+
+ <div id="histogram_container">
+ <span id="missing">(missing)</span>
+ <span id="empty">(empty)</span>
+ <span id="unmergeable">(unmergeable)</span>
+
+ <tr-v-ui-scalar-span id="scalar" on-click="openHistogram_"></tr-v-ui-scalar-span>
+
+ <span id="open_histogram" on-click="openHistogram_">
+ <svg viewbox="0 0 128 128">
+ <rect x="16" y="24" width="32" height="16"/>
+ <rect x="16" y="56" width="96" height="16"/>
+ <rect x="16" y="88" width="64" height="16"/>
+ </svg>
+ </span>
+
+ <span id="histogram"></span>
+
+ <span id="close_histogram" on-click="closeHistogram_">
+ <svg viewbox="0 0 128 128">
+ <line x1="28" y1="28" x2="100" y2="100"/>
+ <line x1="28" y1="100" x2="100" y2="28"/>
+ </svg>
+ </span>
+ </div>
+
+ <div id="overview_container">
+ </div>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-histogram-set-table-cell',
+
+ created() {
+ this.viewState_ = undefined;
+ this.rootListener_ = this.onRootStateUpdate_.bind(this);
+ this.row_ = undefined;
+ this.displayLabel_ = '';
+ this.histogram_ = undefined;
+ this.histogramSpan_ = undefined;
+ this.overviewChart_ = undefined;
+ this.mwuResult_ = undefined;
+ },
+
+ ready() {
+ this.addEventListener('click', this.onClick_.bind(this));
+ },
+
+ attached() {
+ if (this.row) {
+ this.row.rootViewState.addUpdateListener(this.rootListener_);
+ }
+ },
+
+ detached() {
+ this.row.rootViewState.removeUpdateListener(this.rootListener_);
+ // Don't need to removeUpdateListener for the row and cells; their
+ // lifetimes are the same as |this|.
+ },
+
+ updateMwu_() {
+ const referenceHistogram = this.referenceHistogram;
+ this.mwuResult_ = undefined;
+ if (!(this.histogram instanceof tr.v.Histogram)) return;
+ if (!this.histogram.canCompare(referenceHistogram)) return;
+ this.mwuResult_ = tr.b.math.Statistics.mwu(
+ this.histogram.sampleValues,
+ referenceHistogram.sampleValues,
+ this.row.rootViewState.alpha);
+ },
+
+ build(row, displayLabel, viewState) {
+ this.row_ = row;
+ this.displayLabel_ = displayLabel;
+ this.viewState_ = viewState;
+ this.histogram_ = this.row.columns.get(displayLabel);
+
+ if (this.viewState) {
+ // this.viewState is undefined when this.histogram_ is undefined.
+ // In that case, onViewStateUpdate_ wouldn't be able to do anything
+ // anyway.
+ this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));
+ }
+ this.row.viewState.addUpdateListener(this.onRowStateUpdate_.bind(this));
+ if (this.isAttached) {
+ this.row.rootViewState.addUpdateListener(this.rootListener_);
+ }
+
+ this.updateMwu_();
+
+ // this.histogram_ and this.referenceHistogram might be undefined,
+ // a HistogramSet of unmergeable Histograms, or a Histogram.
+ this.updateContents_();
+ },
+
+ updateSignificance_() {
+ if (!this.mwuResult_) return;
+ this.$.scalar.significance = this.mwuResult_.significance;
+ },
+
+ get viewState() {
+ return this.viewState_;
+ },
+
+ get row() {
+ return this.row_;
+ },
+
+ get histogram() {
+ return this.histogram_;
+ },
+
+ get referenceHistogram() {
+ const referenceDisplayLabel =
+ this.row.rootViewState.referenceDisplayLabel;
+ if (!referenceDisplayLabel) return undefined;
+ if (referenceDisplayLabel === this.displayLabel_) return undefined;
+ return this.row.columns.get(referenceDisplayLabel);
+ },
+
+ get isHistogramOpen() {
+ return (this.histogramSpan_ !== undefined) &&
+ (this.$.histogram.style.display === 'block');
+ },
+
+ set isHistogramOpen(open) {
+ if (!(this.histogram instanceof tr.v.Histogram) ||
+ (this.histogram.numValues === 0)) {
+ return;
+ }
+
+ // Unfortunately, we can't use a css attribute for this since this stuff
+ // is tied up in all the possible states of this.histogram. See
+ // updateContents_().
+
+ this.$.scalar.style.display = open ? 'none' : 'flex';
+ this.$.open_histogram.style.display = open ? 'none' : 'block';
+
+ this.$.close_histogram.style.display = open ? 'block' : 'none';
+ this.$.histogram.style.display = open ? 'block' : 'none';
+
+ // Wait to create the histogram-span until the user wants to display it
+ // in order to speed up creating lots of histogram-set-table-cells when
+ // building the table.
+ if (open && this.histogramSpan_ === undefined) {
+ this.histogramSpan_ = document.createElement('tr-v-ui-histogram-span');
+ this.histogramSpan_.viewState = this.viewState;
+ this.histogramSpan_.rowState = this.row.viewState;
+ this.histogramSpan_.rootState = this.row.rootViewState;
+ this.histogramSpan_.build(this.histogram, this.referenceHistogram);
+ this.$.histogram.appendChild(this.histogramSpan_);
+ }
+
+ this.viewState.isOpen = open;
+ },
+
+ onViewStateUpdate_(event) {
+ if (event.delta.isOpen) {
+ this.isHistogramOpen = this.viewState.isOpen;
+ }
+ },
+
+ onRowStateUpdate_(event) {
+ if (event.delta.isOverviewed === undefined) return;
+ if (this.row.viewState.isOverviewed) {
+ this.showOverview();
+ } else {
+ this.hideOverview();
+ }
+ },
+
+ onRootStateUpdate_(event) {
+ if (event.delta.referenceDisplayLabel &&
+ this.histogramSpan_) {
+ this.histogramSpan_.build(this.histogram, this.referenceHistogram);
+ }
+
+ if (event.delta.displayStatisticName ||
+ event.delta.referenceDisplayLabel) {
+ this.updateMwu_();
+ this.updateContents_();
+ } else if (event.delta.alpha && this.mwuResult_) {
+ this.mwuResult_.compare(this.row.rootViewState.alpha);
+ this.updateSignificance_();
+ }
+
+ if (this.row.viewState.isOverviewed &&
+ (event.delta.sortColumnIndex ||
+ event.delta.sortDescending ||
+ event.delta.displayStatisticName ||
+ event.delta.referenceDisplayLabel)) {
+ if (this.overviewChart_ !== undefined) {
+ this.$.overview_container.removeChild(this.overviewChart_);
+ this.overviewChart_ = undefined;
+ }
+ this.showOverview();
+ }
+ },
+
+ onClick_(event) {
+ // Since the histogram-set-table's table doesn't support any kind of
+ // selection, clicking anywhere within a row that has subRows will
+ // expand/collapse that row, which can relayout the table and move things
+ // around. Prevent table relayout by preventing the tr-ui-b-table from
+ // receiving the click event.
+ event.stopPropagation();
+ },
+
+ openHistogram_() {
+ this.isHistogramOpen = true;
+ tr.b.Timing.instant('histogram-set-table-cell', 'open');
+ },
+
+ closeHistogram_() {
+ this.isHistogramOpen = false;
+ tr.b.Timing.instant('histogram-set-table-cell', 'close');
+ },
+
+ updateContents_() {
+ const isOpen = this.isHistogramOpen;
+
+ this.$.empty.style.display = 'none';
+ this.$.unmergeable.style.display = 'none';
+ this.$.scalar.style.display = 'none';
+ this.$.histogram.style.display = 'none';
+ this.$.close_histogram.style.display = 'none';
+ this.$.open_histogram.style.visibility = 'hidden';
+
+ if (!this.histogram) {
+ this.$.missing.style.display = 'block';
+ return;
+ }
+
+ this.$.missing.style.display = 'none';
+
+ if (this.histogram instanceof tr.v.HistogramSet) {
+ this.$.unmergeable.style.display = 'block';
+ return;
+ }
+
+ if (!(this.histogram instanceof tr.v.Histogram)) {
+ throw new Error('Invalid Histogram: ' + this.histogram);
+ }
+
+ if (this.histogram.numValues === 0) {
+ this.$.empty.style.display = 'block';
+ return;
+ }
+
+ this.$.open_histogram.style.display = 'block';
+ this.$.open_histogram.style.visibility = 'visible';
+ this.$.scalar.style.display = 'flex';
+
+ this.updateSignificance_();
+
+ const referenceHistogram = this.referenceHistogram;
+ const statName = this.histogram.getAvailableStatisticName(
+ this.row.rootViewState.displayStatisticName, referenceHistogram);
+ const statisticScalar = this.histogram.getStatisticScalar(
+ statName, referenceHistogram);
+ this.$.scalar.setValueAndUnit(
+ statisticScalar.value, statisticScalar.unit);
+
+ this.isHistogramOpen = isOpen;
+ },
+
+ showOverview() {
+ this.$.overview_container.style.display = 'block';
+ if (this.overviewChart_ !== undefined) return;
+
+ this.row.sortSubRows();
+ let referenceDisplayLabel =
+ this.row.rootViewState.referenceDisplayLabel;
+ if (referenceDisplayLabel === this.displayLabel_) {
+ referenceDisplayLabel = undefined;
+ }
+ const displayStatisticName = this.row.rootViewState.displayStatisticName;
+ const data = [];
+ let unit;
+
+ for (const subRow of this.row.subRows) {
+ const subHist = subRow.columns.get(this.displayLabel_);
+ if (!(subHist instanceof tr.v.Histogram)) continue;
+
+ if (unit === undefined) {
+ unit = subHist.unit;
+ } else if (unit !== subHist.unit) {
+ // The subrows have different units, so the overview chart cannot
+ // use a single unit to format all of the values, so don't display
+ // an overview chart at all.
+ data.splice(0);
+ break;
+ }
+
+ const refHist = subRow.columns.get(referenceDisplayLabel);
+ const statName = subHist.getAvailableStatisticName(
+ displayStatisticName, refHist);
+ const statScalar = subHist.getStatisticScalar(
+ statName, refHist);
+
+ if (statScalar !== undefined) {
+ data.push({
+ x: subRow.name,
+ y: statScalar.value,
+ });
+ }
+ }
+ if (data.length < 2) return;
+
+ this.overviewChart_ = new tr.ui.b.NameLineChart();
+ this.$.overview_container.appendChild(this.overviewChart_);
+ this.overviewChart_.displayXInHover = true;
+ this.overviewChart_.hideLegend = true;
+ this.overviewChart_.unit = unit;
+ this.overviewChart_.overrideDataRange = this.row.overviewDataRange;
+ this.overviewChart_.data = data;
+ },
+
+ hideOverview() {
+ this.$.overview_container.style.display = 'none';
+ }
+ });
+
+ return {
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_name_cell.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_name_cell.html
new file mode 100644
index 00000000000..f0dec062018
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_name_cell.html
@@ -0,0 +1,361 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/ui/base/name_line_chart.html">
+
+<dom-module id="tr-v-ui-histogram-set-table-name-cell">
+ <template>
+ <style>
+ #name_container {
+ display: flex;
+ }
+
+ #name {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+
+ #show_overview, #hide_overview, #show_overview svg, #hide_overview svg {
+ height: 1em;
+ margin-left: 5px;
+ }
+
+ #show_overview svg {
+ stroke: blue;
+ stroke-width: 16;
+ }
+
+ #show_overview:hover svg {
+ background: blue;
+ stroke: white;
+ }
+
+ #hide_overview {
+ display: none;
+ }
+
+ #hide_overview svg {
+ stroke-width: 18;
+ stroke: black;
+ }
+
+ #hide_overview:hover svg {
+ background: black;
+ stroke: white;
+ }
+
+ #open_histograms, #close_histograms, #open_histograms svg, #close_histograms svg {
+ height: 1em;
+ }
+
+ #close_histograms {
+ display: none;
+ }
+
+ #open_histograms svg {
+ margin-left: 4px;
+ stroke-width: 0;
+ stroke: blue;
+ fill: blue;
+ }
+ #open_histograms:hover svg {
+ background: blue;
+ stroke: white;
+ fill: white;
+ }
+
+ #close_histograms line {
+ stroke-width: 18;
+ stroke: black;
+ }
+ #close_histograms:hover {
+ background: black;
+ }
+ #close_histograms:hover line {
+ stroke: white;
+ }
+
+ #overview_container {
+ display: none;
+ }
+ </style>
+
+ <div id="name_container">
+ <span id="name"></span>
+
+ <span id="show_overview" on-click="showOverview_">
+ <svg viewbox="0 0 128 128">
+ <line x1="19" y1="109" x2="49" y2="49"/>
+ <line x1="49" y1="49" x2="79" y2="79"/>
+ <line x1="79" y1="79" x2="109" y2="19"/>
+ </svg>
+ </span>
+
+ <span id="hide_overview" on-click="hideOverview_">
+ <svg viewbox="0 0 128 128">
+ <line x1="28" y1="28" x2="100" y2="100"/>
+ <line x1="28" y1="100" x2="100" y2="28"/>
+ </svg>
+ </span>
+
+ <span id="open_histograms" on-click="openHistograms_">
+ <svg viewbox="0 0 128 128">
+ <rect x="16" y="24" width="32" height="16"/>
+ <rect x="16" y="56" width="96" height="16"/>
+ <rect x="16" y="88" width="64" height="16"/>
+ </svg>
+ </span>
+
+ <span id="close_histograms" on-click="closeHistograms_">
+ <svg viewbox="0 0 128 128">
+ <line x1="28" y1="28" x2="100" y2="100"/>
+ <line x1="28" y1="100" x2="100" y2="28"/>
+ </svg>
+ </span>
+ </div>
+
+ <div id="overview_container">
+ </div>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ const NAME_COLUMN_WIDTH_PX = 300;
+
+ Polymer({
+ is: 'tr-v-ui-histogram-set-table-name-cell',
+
+ created() {
+ this.row_ = undefined;
+ this.overviewChart_ = undefined;
+ this.cellListener_ = this.onCellStateUpdate_.bind(this);
+ this.rootListener_ = this.onRootStateUpdate_.bind(this);
+ },
+
+ attached() {
+ if (this.row) {
+ this.row.rootViewState.addUpdateListener(this.rootListener_);
+ }
+ },
+
+ detached() {
+ this.row.rootViewState.removeUpdateListener(this.rootListener_);
+ // Don't need to removeUpdateListener for the row and cells; their
+ // lifetimes are the same as |this|.
+ },
+
+ get row() {
+ return this.row_;
+ },
+
+ build(row) {
+ if (this.row_ !== undefined) {
+ throw new Error('row must be set exactly once.');
+ }
+ this.row_ = row;
+ this.row.viewState.addUpdateListener(this.onRowStateUpdate_.bind(this));
+ this.constrainWidth = this.row.rootViewState.constrainNameColumn;
+ if (this.isAttached) {
+ this.row.rootViewState.addUpdateListener(this.rootListener_);
+ }
+
+ for (const cellState of this.row.viewState.cells.values()) {
+ cellState.addUpdateListener(this.cellListener_);
+ }
+
+ Polymer.dom(this.$.name).textContent = this.row.name;
+
+ this.title = this.row.name;
+ if (this.row.description) {
+ this.title += '\n' + this.row.description;
+ }
+
+ if (this.row.overviewDataRange.isEmpty ||
+ this.row.overviewDataRange.min === this.row.overviewDataRange.max) {
+ // TODO(#3744) Also hide this button when column or subrow units don't
+ // match.
+ this.$.show_overview.style.display = 'none';
+ }
+
+ let histogramCount = 0;
+ for (const cell of this.row.columns.values()) {
+ if (cell instanceof tr.v.Histogram &&
+ cell.numValues > 0) {
+ ++histogramCount;
+ }
+ }
+ if (histogramCount <= 1) {
+ this.$.open_histograms.style.display = 'none';
+ }
+ },
+
+ set constrainWidth(constrain) {
+ this.$.name.style.maxWidth = constrain ?
+ (this.nameWidthPx + 'px') : 'none';
+ },
+
+ get nameWidthPx() {
+ // tr-ui-b-table adds 16px of padding for each additional level of subRows
+ // nesting, so outer nameDivs can be wider than inner nameDivs.
+ return NAME_COLUMN_WIDTH_PX - (16 * this.row.depth);
+ },
+
+ get isOverflowing() {
+ return this.$.name.style.maxWidth !== 'none' &&
+ this.$.name.getBoundingClientRect().width === this.nameWidthPx;
+ },
+
+ get isOverviewed() {
+ return this.$.overview_container.style.display === 'block';
+ },
+
+ set isOverviewed(isOverviewed) {
+ if (isOverviewed === this.isOverviewed) return;
+ if (isOverviewed) {
+ this.showOverview_();
+ } else {
+ this.hideOverview_();
+ }
+ },
+
+ hideOverview_(opt_event) {
+ this.$.overview_container.style.display = 'none';
+ this.$.hide_overview.style.display = 'none';
+ this.$.show_overview.style.display = 'block';
+
+ if (opt_event !== undefined) {
+ opt_event.stopPropagation();
+ tr.b.Timing.instant('histogram-set-table-name-cell', 'hideOverview');
+ this.row.viewState.isOverviewed = this.isOverviewed;
+ }
+ },
+
+ showOverview_(opt_event) {
+ if (opt_event !== undefined) {
+ opt_event.stopPropagation();
+ tr.b.Timing.instant('histogram-set-table-name-cell', 'showOverview');
+ this.row.viewState.isOverviewed = true;
+ }
+
+ this.$.overview_container.style.display = 'block';
+ this.$.hide_overview.style.display = 'block';
+ this.$.show_overview.style.display = 'none';
+
+ if (this.overviewChart_ === undefined) {
+ const displayStatisticName =
+ this.row.rootViewState.displayStatisticName;
+ const data = [];
+ let unit;
+
+ for (const [displayLabel, hist] of this.row.sortedColumns()) {
+ if (!(hist instanceof tr.v.Histogram)) continue;
+
+ if (unit === undefined) {
+ unit = hist.unit;
+ } else if (unit !== hist.unit) {
+ // The columns have different units, so the overview chart cannot
+ // use a single unit to format all of the values, so don't display
+ // an overview chart at all.
+ data.splice(0);
+ break;
+ }
+
+ const statName = hist.getAvailableStatisticName(displayStatisticName);
+ const statScalar = hist.getStatisticScalar(statName);
+
+ if (statScalar !== undefined) {
+ data.push({
+ x: displayLabel,
+ y: statScalar.value,
+ });
+ }
+ }
+ if (data.length < 2) {
+ return;
+ }
+
+ this.overviewChart_ = new tr.ui.b.NameLineChart();
+ this.$.overview_container.appendChild(this.overviewChart_);
+ this.overviewChart_.displayXInHover = true;
+ this.overviewChart_.hideLegend = true;
+ this.overviewChart_.unit = unit;
+ this.overviewChart_.overrideDataRange = this.row.overviewDataRange;
+ this.overviewChart_.data = data;
+ }
+ },
+
+ openHistograms_(event) {
+ event.stopPropagation();
+ tr.b.Timing.instant('histogram-set-table-name-cell', 'openHistograms');
+ for (const cell of this.row.cells.values()) {
+ cell.isHistogramOpen = true;
+ }
+ this.$.close_histograms.style.display = 'block';
+ this.$.open_histograms.style.display = 'none';
+ },
+
+ closeHistograms_(event) {
+ event.stopPropagation();
+ tr.b.Timing.instant('histogram-set-table-name-cell', 'closeHistograms');
+ for (const cell of this.row.cells.values()) {
+ cell.isHistogramOpen = false;
+ }
+ this.$.open_histograms.style.display = 'block';
+ this.$.close_histograms.style.display = 'none';
+ },
+
+ onRootStateUpdate_(event) {
+ if (event.delta.constrainNameColumn) {
+ this.constrainWidth = this.row.rootViewState.constrainNameColumn;
+ }
+ if (this.row.viewState.isOverviewed &&
+ event.delta.displayStatisticName) {
+ this.row.resetOverviewDataRange();
+ if (this.overviewChart_ !== undefined) {
+ this.$.overview_container.removeChild(this.overviewChart_);
+ this.overviewChart_ = undefined;
+ }
+ this.showOverview_();
+ }
+ },
+
+ onRowStateUpdate_(event) {
+ if (event.delta.isOverviewed) {
+ this.isOverviewed = this.row.viewState.isOverviewed;
+ }
+ // This assumes that cell states are not updated.
+ },
+
+ onCellStateUpdate_(event) {
+ if (!event.delta.isOpen) return;
+
+ let cellCount = 0;
+ let openCellCount = 0;
+ for (const cell of this.row.cells.values()) {
+ if (!(cell.histogram instanceof tr.v.Histogram) ||
+ (cell.histogram.numValues === 0)) {
+ continue;
+ }
+ ++cellCount;
+ if (cell.isHistogramOpen) ++openCellCount;
+ }
+ if (cellCount <= 1) return;
+ const mostlyOpen = openCellCount > (cellCount / 2);
+ this.$.open_histograms.style.display = mostlyOpen ? 'none' : 'block';
+ this.$.close_histograms.style.display = mostlyOpen ? 'block' : 'none';
+ }
+ });
+
+ return {
+ NAME_COLUMN_WIDTH_PX,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html
new file mode 100644
index 00000000000..b4cb1a54020
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_row.html
@@ -0,0 +1,299 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/ui/histogram_set_table_cell.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_table_name_cell.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ class HistogramSetTableRow {
+ /**
+ * @param {!tr.v.HistogramSetHierarchy} hierarchy
+ * @param {!Element} baseTable tr-ui-b-table
+ * @param {!tr.v.ui.HistogramSetViewState} rootViewState
+ */
+ constructor(hierarchy, baseTable, rootViewState) {
+ this.hierarchy_ = hierarchy;
+ this.baseTable_ = baseTable;
+ this.rootViewState_ = rootViewState;
+ this.viewState_ = new tr.v.ui.HistogramSetTableRowState();
+ this.viewState_.addUpdateListener(this.onViewStateUpdate_.bind(this));
+ this.overviewDataRange_ = undefined;
+ this.nameCell_ = undefined;
+ this.cells_ = new Map();
+ this.subRows_ = [];
+
+ // Don't assign viewState.subRows or cells. There can't be anything
+ // listening to viewState, so avoid the overhead of dispatching an event.
+ for (const subHierarchy of hierarchy.subRows) {
+ const subRow = new HistogramSetTableRow(
+ subHierarchy, baseTable, rootViewState);
+ this.subRows_.push(subRow);
+ this.viewState.subRows.set(subRow.name, subRow.viewState);
+ }
+ for (const columnName of this.columns.keys()) {
+ this.viewState.cells.set(
+ columnName, new tr.v.ui.HistogramSetTableCellState());
+ }
+ }
+
+ /**
+ * @return {string}
+ */
+ get name() {
+ return this.hierarchy_.name;
+ }
+
+ /**
+ * @return {number}
+ */
+ get depth() {
+ return this.hierarchy_.depth;
+ }
+
+ /**
+ * @return {string}
+ */
+ get description() {
+ return this.hierarchy_.description;
+ }
+
+ /**
+ * @return {!Map.<string, !(undefined|tr.v.Histogram|tr.v.HistogramSet)>}
+ */
+ get columns() {
+ return this.hierarchy_.columns;
+ }
+
+ * sortedColumns() {
+ for (const col of this.baseTable_.tableColumns) {
+ yield [
+ col.displayLabel,
+ this.hierarchy_.columns.get(col.displayLabel),
+ ];
+ }
+ }
+
+ /**
+ * @return {!tr.b.Range}
+ */
+ get overviewDataRange() {
+ if (this.overviewDataRange_ === undefined) {
+ this.overviewDataRange_ = new tr.b.math.Range();
+
+ const displayStatisticName =
+ this.rootViewState.displayStatisticName;
+ const referenceDisplayLabel =
+ this.rootViewState.referenceDisplayLabel;
+
+ for (const [displayLabel, hist] of this.columns) {
+ if (hist instanceof tr.v.Histogram) {
+ const statName = hist.getAvailableStatisticName(
+ displayStatisticName);
+ const statScalar = hist.getStatisticScalar(statName);
+ if (statScalar !== undefined) {
+ this.overviewDataRange_.addValue(statScalar.value);
+ }
+ }
+
+ for (const subRow of this.subRows) {
+ const subHist = subRow.columns.get(displayLabel);
+ if (!(subHist instanceof tr.v.Histogram)) continue;
+
+ const refHist = subRow.columns.get(referenceDisplayLabel);
+ const statName = subHist.getAvailableStatisticName(
+ displayStatisticName, refHist);
+ const statScalar = subHist.getStatisticScalar(
+ statName, refHist);
+
+ if (statScalar !== undefined) {
+ this.overviewDataRange_.addValue(statScalar.value);
+ }
+ }
+ }
+ }
+ return this.overviewDataRange_;
+ }
+
+ /**
+ * overviewDataRange is used by histogram-set-table-cell (hstc) and
+ * histogram-set-table-name-cell (hstnc) to display overview line charts
+ * with consistent y-axes.
+ * overviewDataRange depends on HistogramSetViewState.displayStatisticName
+ * and referenceDisplayLabel, so it must be recomputed when either of those
+ * changes.
+ * overviewDataRange should not be recomputed for each hstc in the row; it
+ * should only be computed once when necessary, and cached.
+ * HistogramSetTableRow (HSTR) cannot listen to HistogramSetViewState
+ * (HSVS) updates because there is no way for it to remove the listener.
+ * However, Polymer has detached callbacks, so dom-modules can listen to
+ * HSVS updates without leaking memory.
+ * overviewDataRange should be recomputed only once whenever
+ * displayStatisticName or referenceDisplayLabel changes.
+ * There is exactly one hstnc per row.
+ * histogram-set-table-name-cell resets overviewDataRange when
+ * displayStatisticName or referenceDisplayLabel changes.
+ */
+ resetOverviewDataRange() {
+ this.overviewDataRange_ = undefined;
+ }
+
+ /**
+ * @return {!tr.v.ui.HistogramSetViewState}
+ */
+ get rootViewState() {
+ return this.rootViewState_;
+ }
+
+ /**
+ * @return {!Map.<string, !Element>} tr-v-ui-histogram-set-table-cell
+ */
+ get cells() {
+ return this.cells_;
+ }
+
+ /**
+ * @return {!Array.<tr.v.ui.HistogramSetTableRow>}
+ */
+ get subRows() {
+ return this.subRows_;
+ }
+
+ /**
+ * @return {!Array.<tr.v.ui.HistogramSetTableRowState>}
+ */
+ get viewState() {
+ return this.viewState_;
+ }
+
+ * walk() {
+ yield this;
+ for (const row of this.subRows) yield* row.walk();
+ }
+
+ static* walkAll(rootRows) {
+ for (const rootRow of rootRows) yield* rootRow.walk();
+ }
+
+ get nameCell() {
+ if (this.nameCell_ === undefined) {
+ this.nameCell_ = document.createElement(
+ 'tr-v-ui-histogram-set-table-name-cell');
+ this.nameCell_.build(this);
+ }
+ return this.nameCell_;
+ }
+
+ getCell(columnName) {
+ if (this.cells.has(columnName)) return this.cells.get(columnName);
+ const cell = document.createElement('tr-v-ui-histogram-set-table-cell');
+ cell.build(this, columnName, this.viewState.cells.get(columnName));
+ this.cells.set(columnName, cell);
+ return cell;
+ }
+
+ compareNames(other) {
+ return this.name.localeCompare(other.name);
+ }
+
+ compareCells(other, displayLabel) {
+ // If a reference column is selected, compare the absolute deltas
+ // between the two cells and their references.
+ const referenceDisplayLabel = this.rootViewState.referenceDisplayLabel;
+ let referenceCellA;
+ let referenceCellB;
+ if (referenceDisplayLabel &&
+ referenceDisplayLabel !== displayLabel) {
+ referenceCellA = this.columns.get(referenceDisplayLabel);
+ referenceCellB = other.columns.get(referenceDisplayLabel);
+ }
+
+ const cellA = this.columns.get(displayLabel);
+ let valueA = 0;
+ if (cellA instanceof tr.v.Histogram) {
+ const statisticA = cellA.getAvailableStatisticName(
+ this.rootViewState.displayStatisticName, referenceCellA);
+ const scalarA = cellA.getStatisticScalar(statisticA, referenceCellA);
+ if (scalarA) {
+ valueA = scalarA.value;
+ }
+ }
+
+ const cellB = other.columns.get(displayLabel);
+ let valueB = 0;
+ if (cellB instanceof tr.v.Histogram) {
+ const statisticB = cellB.getAvailableStatisticName(
+ this.rootViewState.displayStatisticName, referenceCellB);
+ const scalarB = cellB.getStatisticScalar(statisticB, referenceCellB);
+ if (scalarB) {
+ valueB = scalarB.value;
+ }
+ }
+
+ return valueA - valueB;
+ }
+
+ onViewStateUpdate_(event) {
+ if (event.delta.isExpanded) {
+ this.baseTable_.setExpandedForTableRow(this, this.viewState.isExpanded);
+ }
+
+ if (event.delta.subRows) {
+ throw new Error('HistogramSetTableRow.subRows must not be reassigned.');
+ }
+
+ if (event.delta.cells) {
+ // Only validate the cells that have already been built.
+ // Cells may not have been built yet, so only validate the cells that
+ // have been built.
+ for (const [displayLabel, cell] of this.cells) {
+ if (cell.viewState !== this.viewState.cells.get(displayLabel)) {
+ throw new Error('Only HistogramSetTableRow may update cells');
+ }
+ }
+ }
+ }
+
+ async restoreState(vs) {
+ // Don't use updateFromViewState() because it would overwrite cells and
+ // subRows, but we just want to restore them.
+ await this.viewState.update({
+ isExpanded: vs.isExpanded,
+ isOverviewed: vs.isOverviewed,
+ });
+
+ // If cells haven't been built yet, then their state will be restored when
+ // they are built.
+ for (const [displayLabel, cell] of this.cells) {
+ const previousState = vs.cells.get(displayLabel);
+ if (!previousState) continue;
+ await cell.viewState.updateFromViewState(previousState);
+ }
+ for (const row of this.subRows) {
+ const previousState = vs.subRows.get(row.name);
+ if (!previousState) continue;
+ await row.restoreState(previousState);
+ }
+ }
+
+ sortSubRows() {
+ const sortColumn = this.baseTable_.tableColumns[
+ this.rootViewState_.sortColumnIndex];
+ if (sortColumn === undefined) return;
+ this.subRows_.sort(sortColumn.cmp);
+ if (this.rootViewState_.sortDescending) {
+ this.subRows_.reverse();
+ }
+ }
+ }
+
+ return {
+ HistogramSetTableRow,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html
new file mode 100644
index 00000000000..f8d76afc72b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_table_test.html
@@ -0,0 +1,1679 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/assert_utils.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ // TODO(#3811) Clean up these tests.
+
+ const TEST_BOUNDARIES = tr.v.HistogramBinBoundaries.createLinear(0, 1e3, 20);
+
+ async function buildTable(test, histograms) {
+ // This should mirror HistogramImporter in order to be as similar to
+ // results.html as possible.
+ const table = document.createElement('tr-v-ui-histogram-set-table');
+
+ table.viewState = new tr.v.ui.HistogramSetViewState();
+ await table.viewState.update({
+ displayStatisticName: 'avg',
+ groupings: [tr.v.HistogramGrouping.HISTOGRAM_NAME],
+ });
+
+ table.style.display = 'none';
+ test.addHTMLOutput(table);
+
+ table.addEventListener('display-ready', () => {
+ table.style.display = '';
+ });
+
+ const collector = new tr.v.HistogramParameterCollector();
+ collector.process(histograms);
+
+ await table.build(
+ histograms,
+ histograms.sourceHistograms,
+ collector.labels,
+ async message => {
+ await tr.b.animationFrame();
+ });
+ return table;
+ }
+
+ function range(start, end) {
+ const result = [];
+ for (let i = start; i < end; ++i) result.push(i);
+ return result;
+ }
+
+ function getBaseTable(table) {
+ return tr.ui.b.findDeepElementMatchingPredicate(table, e =>
+ e.tagName === 'TR-UI-B-TABLE');
+ }
+
+ function getNameCells(table) {
+ return tr.ui.b.findDeepElementsMatchingPredicate(table, e =>
+ e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL');
+ }
+
+ function getTableCells(table) {
+ return tr.ui.b.findDeepElementsMatchingPredicate(table, e =>
+ e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL');
+ }
+
+ test('viewSearchQuery', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ histograms.createHistogram('b', tr.b.Unit.byName.count, [2]);
+ const table = await buildTable(this, histograms);
+
+ await table.viewState.update({searchQuery: 'a'});
+ let cells = getTableCells(table);
+ assert.lengthOf(cells, 1);
+
+ await table.viewState.update({searchQuery: '[z-'});
+ cells = getTableCells(table);
+ assert.lengthOf(cells, 2);
+
+ await table.viewState.update({searchQuery: 'x'});
+ cells = getTableCells(table);
+ assert.lengthOf(cells, 0);
+
+ await table.viewState.update({searchQuery: ''});
+ cells = getTableCells(table);
+ assert.lengthOf(cells, 2);
+ });
+
+ test('controlSearchQuery', async function() {
+ const histograms = new tr.v.HistogramSet();
+ const aHist = histograms.createHistogram('a', tr.b.Unit.byName.count,
+ {value: 1, diagnostics: {r: tr.v.d.Breakdown.fromEntries([['0', 1]])}});
+ const bHist = histograms.createHistogram('b', tr.b.Unit.byName.count, []);
+ const related = new tr.v.d.RelatedNameMap();
+ related.set('0', bHist.name);
+ aHist.diagnostics.set('r', related);
+ const table = await buildTable(this, histograms);
+ await table.viewState.tableRowStates.get('a').cells.get('Value').update(
+ {isOpen: true});
+ const link = tr.ui.b.findDeepElementMatchingPredicate(
+ table, e => e.tagName === 'TR-UI-A-ANALYSIS-LINK');
+ link.click();
+ assert.strictEqual('^(b)$', table.viewState.searchQuery);
+ });
+
+ test('viewReferenceDisplayLabel', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])
+ ]]),
+ });
+ histograms.createHistogram('b', tr.b.Unit.byName.count, [2], {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])
+ ]]),
+ });
+ const table = await buildTable(this, histograms);
+ const baseTable = getBaseTable(table);
+ assert.isUndefined(baseTable.selectedTableColumnIndex);
+
+ await table.viewState.update({referenceDisplayLabel: 'A'});
+ assert.strictEqual(1, baseTable.selectedTableColumnIndex);
+
+ await table.viewState.update({referenceDisplayLabel: 'B'});
+ assert.strictEqual(2, baseTable.selectedTableColumnIndex);
+ });
+
+ test('viewDisplayStatisticName', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, range(0, 10), {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])
+ ]]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, range(10, 20), {
+ diagnostics: new Map([[
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])
+ ]]),
+ });
+ const table = await buildTable(this, histograms);
+ let scalarSpans = tr.ui.b.findDeepElementsMatchingPredicate(table, e =>
+ e.tagName === 'TR-V-UI-SCALAR-SPAN');
+ assert.lengthOf(scalarSpans, 2);
+ assert.strictEqual('5', scalarSpans[0].unit.format(scalarSpans[0].value));
+ assert.strictEqual('15', scalarSpans[1].unit.format(scalarSpans[1].value));
+
+ await table.viewState.update({displayStatisticName: 'std'});
+ scalarSpans = tr.ui.b.findDeepElementsMatchingPredicate(table, e =>
+ e.tagName === 'TR-V-UI-SCALAR-SPAN');
+ assert.lengthOf(scalarSpans, 2);
+ assert.strictEqual('3', scalarSpans[0].unit.format(scalarSpans[0].value));
+ assert.strictEqual('3', scalarSpans[1].unit.format(scalarSpans[1].value));
+ });
+
+ test('autoShowAll', async function() {
+ const histograms = new tr.v.HistogramSet();
+ const aHist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ const bHist = histograms.createHistogram('b', tr.b.Unit.byName.count, []);
+ const related = new tr.v.d.RelatedNameMap();
+ related.set('0', bHist.name);
+ aHist.diagnostics.set('r', related);
+ const table = await buildTable(this, histograms);
+
+ let cells = getNameCells(table);
+ assert.lengthOf(cells, 2);
+ assert.strictEqual('a', cells[0].row.name);
+
+ await table.viewState.update({searchQuery: 'b'});
+ assert.isTrue(table.viewState.showAll);
+ cells = getNameCells(table);
+ assert.lengthOf(cells, 1);
+ assert.strictEqual('b', cells[0].row.name);
+ });
+
+ test('viewShowAll', async function() {
+ const histograms = new tr.v.HistogramSet();
+ const aHist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ const bHist = histograms.createHistogram('b', tr.b.Unit.byName.count, []);
+ const related = new tr.v.d.RelatedNameMap();
+ related.set('0', bHist.name);
+ aHist.diagnostics.set('r', related);
+ const table = await buildTable(this, histograms);
+
+ let cells = getNameCells(table);
+ assert.lengthOf(cells, 2);
+ assert.strictEqual('a', cells[0].row.name);
+ assert.strictEqual('b', cells[1].row.name);
+
+ await table.viewState.update({showAll: false});
+ cells = getNameCells(table);
+ assert.lengthOf(cells, 1);
+ assert.strictEqual('a', cells[0].row.name);
+ });
+
+ test('viewSortColumnIndex', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ histograms.createHistogram('b', tr.b.Unit.byName.count, [2]);
+ const table = await buildTable(this, histograms);
+ const baseTable = getBaseTable(table);
+ assert.strictEqual(baseTable.sortColumnIndex, 0);
+ assert.isFalse(baseTable.sortDescending);
+
+ await table.viewState.update({sortColumnIndex: 1, sortDescending: true});
+ assert.isTrue(baseTable.sortDescending);
+ assert.strictEqual(baseTable.sortColumnIndex, 1);
+ });
+
+ test('controlSortColumnIndex', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ histograms.createHistogram('b', tr.b.Unit.byName.count, [2]);
+ const table = await buildTable(this, histograms);
+
+ assert.strictEqual(0, table.viewState.sortColumnIndex);
+
+ tr.ui.b.findDeepElementsMatchingPredicate(
+ table, e => e.tagName === 'TR-UI-B-TABLE-HEADER-CELL')[0].click();
+ assert.strictEqual(0, table.viewState.sortColumnIndex);
+
+ tr.ui.b.findDeepElementsMatchingPredicate(
+ table, e => e.tagName === 'TR-UI-B-TABLE-HEADER-CELL')[1].click();
+ assert.strictEqual(1, table.viewState.sortColumnIndex);
+ });
+
+ test('viewSortDescending', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ histograms.createHistogram('b', tr.b.Unit.byName.count, [2]);
+ const table = await buildTable(this, histograms);
+
+ await table.viewState.update({sortColumnIndex: 0});
+
+ await table.viewState.update({sortDescending: true});
+
+ await table.viewState.update({sortDescending: false});
+ });
+
+ test('controlSortDescending', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ histograms.createHistogram('b', tr.b.Unit.byName.count, [2]);
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({sortColumnIndex: 0});
+
+ assert.isFalse(table.viewState.sortDescending);
+
+ tr.ui.b.findDeepElementsMatchingPredicate(
+ table, e => e.tagName === 'TR-UI-B-TABLE-HEADER-CELL')[0].click();
+ assert.isTrue(table.viewState.sortDescending);
+
+ tr.ui.b.findDeepElementsMatchingPredicate(
+ table, e => e.tagName === 'TR-UI-B-TABLE-HEADER-CELL')[0].click();
+ assert.isFalse(table.viewState.sortDescending);
+ });
+
+ test('sortUndefinedStatistics', async function() {
+ // The 'avg' statistic Scalar of an empty histogram is undefined, so
+ // HistogramSetTableRow.compareCells must not throw when it encounters
+ // undefined Scalars.
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ histograms.createHistogram('b', tr.b.Unit.byName.count, []);
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({sortColumnIndex: 1});
+ });
+
+ test('sortByDeltaStatistic', async function() {
+ const histograms0 = new tr.v.HistogramSet();
+ const histograms1 = new tr.v.HistogramSet();
+ const a0Hist = histograms0.createHistogram(
+ 'a', tr.b.Unit.byName.count, [0]);
+ const b0Hist = histograms0.createHistogram(
+ 'b', tr.b.Unit.byName.count, [0]);
+ const c0Hist = histograms0.createHistogram(
+ 'c', tr.b.Unit.byName.count, [3]);
+ const a1Hist = histograms1.createHistogram(
+ 'a', tr.b.Unit.byName.count, [1]);
+ const b1Hist = histograms1.createHistogram(
+ 'b', tr.b.Unit.byName.count, [2]);
+ const c1Hist = histograms1.createHistogram(
+ 'c', tr.b.Unit.byName.count, [3]);
+ histograms0.addSharedDiagnosticToAllHistograms(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['L0']));
+ histograms0.addSharedDiagnosticToAllHistograms(
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(0));
+ histograms1.addSharedDiagnosticToAllHistograms(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['L1']));
+ histograms1.addSharedDiagnosticToAllHistograms(
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(1));
+
+ const table = await buildTable(this, new tr.v.HistogramSet(
+ Array.from(histograms0).concat(Array.from(histograms1))));
+ await table.viewState.update({
+ displayStatisticName: tr.v.DELTA + 'avg',
+ referenceDisplayLabel: 'L0',
+ sortColumnIndex: 2,
+ });
+ const nameCells = getNameCells(table);
+ assert.strictEqual('c', nameCells[0].row.name);
+ assert.strictEqual('a', nameCells[1].row.name);
+ assert.strictEqual('b', nameCells[2].row.name);
+ });
+
+ test('sortMissing', async function() {
+ // Missing cells should be treated as zero for sorting purposes. The
+ // comparator must not return undefined or NaN.
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['x'])],
+ ]),
+ });
+ histograms.createHistogram('b', tr.b.Unit.byName.count, [2], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['x'])],
+ ]),
+ });
+ // 'c','x' intentionally missing
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['y'])],
+ ]),
+ });
+ // 'b','y' intentionally missing
+ histograms.createHistogram('c', tr.b.Unit.byName.count, [-1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['y'])],
+ ]),
+ });
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({sortColumnIndex: 2});
+ let cells = getNameCells(table);
+ assert.lengthOf(cells, 3);
+ assert.strictEqual('c', cells[0].row.name);
+ assert.strictEqual('b', cells[1].row.name);
+ assert.strictEqual('a', cells[2].row.name);
+ await table.viewState.update({sortDescending: true});
+ cells = getNameCells(table);
+ assert.lengthOf(cells, 3);
+ assert.strictEqual('a', cells[0].row.name);
+ assert.strictEqual('b', cells[1].row.name);
+ assert.strictEqual('c', cells[2].row.name);
+ await table.viewState.update({sortColumnIndex: 1});
+ cells = getNameCells(table);
+ assert.lengthOf(cells, 3);
+ assert.strictEqual('b', cells[0].row.name);
+ assert.strictEqual('a', cells[1].row.name);
+ assert.strictEqual('c', cells[2].row.name);
+ await table.viewState.update({sortDescending: false});
+ cells = getNameCells(table);
+ assert.lengthOf(cells, 3);
+ assert.strictEqual('c', cells[0].row.name);
+ assert.strictEqual('a', cells[1].row.name);
+ assert.strictEqual('b', cells[2].row.name);
+ });
+
+ test('viewConstrainNameColumn', async function() {
+ // TODO(#4321): Switch to using skipped instead once it works
+ return; // https://github.com/catapult-project/catapult/issues/4320
+ /* eslint-disable no-unreachable */
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a'.repeat(100), tr.b.Unit.byName.count, []);
+ const table = await buildTable(this, histograms);
+ const nameCell = tr.b.getOnlyElement(getNameCells(table));
+ assert.isTrue(nameCell.isOverflowing);
+ assert.isAbove(350, nameCell.getBoundingClientRect().width);
+ assert.isTrue(table.viewState.constrainNameColumn);
+ const dots = tr.ui.b.findDeepElementMatchingPredicate(
+ table, e => e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS);
+ assert.strictEqual('block', dots.style.display);
+
+ await table.viewState.update({constrainNameColumn: false});
+ assert.isFalse(nameCell.isOverflowing);
+ assert.isBelow(350, nameCell.getBoundingClientRect().width);
+
+ await table.viewState.update({constrainNameColumn: true});
+ assert.isTrue(nameCell.isOverflowing);
+ assert.isAbove(350, nameCell.getBoundingClientRect().width);
+ /* eslint-enable no-unreachable */
+ });
+
+ test('controlConstrainNameColumn', async function() {
+ // TODO(#4321): Switch to using skipped instead once it works
+ return; // https://github.com/catapult-project/catapult/issues/4320
+ /* eslint-disable no-unreachable */
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a'.repeat(100), tr.b.Unit.byName.count, []);
+ const table = await buildTable(this, histograms);
+ const nameCell = tr.b.getOnlyElement(getNameCells(table));
+ assert.isTrue(nameCell.isOverflowing);
+ assert.isAbove(350, nameCell.getBoundingClientRect().width);
+ assert.isTrue(table.viewState.constrainNameColumn);
+ const dots = tr.ui.b.findDeepElementMatchingPredicate(
+ table, e => e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS);
+ assert.strictEqual('block', dots.style.display);
+
+ tr.ui.b.findDeepElementMatchingPredicate(table, e =>
+ e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS).click();
+ assert.isFalse(table.viewState.constrainNameColumn);
+ await tr.b.animationFrame();
+ assert.isFalse(nameCell.isOverflowing);
+ assert.isBelow(350, nameCell.getBoundingClientRect().width);
+
+ tr.ui.b.findDeepElementMatchingPredicate(table, e =>
+ e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS).click();
+ assert.isTrue(table.viewState.constrainNameColumn);
+ await tr.b.animationFrame();
+ assert.isTrue(nameCell.isOverflowing);
+ assert.isAbove(350, nameCell.getBoundingClientRect().width);
+ /* eslint-enable no-unreachable */
+ });
+
+ test('viewRowExpanded', async function() {
+ const histograms = new tr.v.HistogramSet();
+ const aHist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ aHist.diagnostics.set(tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet(['A']));
+ const bHist = histograms.createHistogram('a', tr.b.Unit.byName.count, [2]);
+ bHist.diagnostics.set(tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet(['B']));
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ]});
+ assert.lengthOf(getTableCells(table), 1);
+
+ await table.viewState.tableRowStates.get('a').update({isExpanded: true});
+ assert.lengthOf(getTableCells(table), 3);
+
+ await table.viewState.tableRowStates.get('a').update({isExpanded: false});
+ assert.lengthOf(getTableCells(table), 1);
+ });
+
+ test('controlRowExpanded', async function() {
+ const histograms = new tr.v.HistogramSet();
+ const aHist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ aHist.diagnostics.set(tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet(['A']));
+ const bHist = histograms.createHistogram('a', tr.b.Unit.byName.count, [2]);
+ bHist.diagnostics.set(tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet(['B']));
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ]});
+ assert.isFalse(table.viewState.tableRowStates.get('a').isExpanded);
+
+ const nameCell = tr.b.getOnlyElement(getNameCells(table));
+ nameCell.click();
+ assert.isTrue(table.viewState.tableRowStates.get('a').isExpanded);
+
+ nameCell.click();
+ assert.isFalse(table.viewState.tableRowStates.get('a').isExpanded);
+ });
+
+ test('viewIsOverviewed', async function() {
+ const histograms = new tr.v.HistogramSet();
+ let hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A']));
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['A']));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [2]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A']));
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['B']));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B']));
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['A']));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [2]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B']));
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['B']));
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ]});
+
+ const nameCells = getNameCells(table);
+ const cells = getTableCells(table);
+ assert.isFalse(nameCells[0].isOverviewed);
+
+ await table.viewState.tableRowStates.get('a').update({isOverviewed: true});
+ assert.isTrue(nameCells[0].isOverviewed);
+
+ await table.viewState.tableRowStates.get('a').update({isOverviewed: false});
+ assert.isFalse(nameCells[0].isOverviewed);
+ });
+
+ test('overviewSorted', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [4], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['D'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [2], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['B'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [3], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['C'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['A'])],
+ ]),
+ });
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({
+ groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ],
+ sortColumnIndex: 0,
+ sortDescending: true,
+ });
+ await table.viewState.tableRowStates.get('a').update({isOverviewed: true});
+
+ let cells = getTableCells(table);
+ let chart = tr.ui.b.findDeepElementMatchingPredicate(cells[0], e =>
+ e.tagName === 'svg' && e.parentNode.id === 'overview_container');
+ assert.strictEqual('D', chart.data[0].x);
+ assert.strictEqual('C', chart.data[1].x);
+ assert.strictEqual('B', chart.data[2].x);
+ assert.strictEqual('A', chart.data[3].x);
+
+ await table.viewState.update({
+ sortDescending: false,
+ });
+ cells = getTableCells(table);
+ chart = tr.ui.b.findDeepElementMatchingPredicate(cells[0], e =>
+ e.tagName === 'svg' && e.parentNode.id === 'overview_container');
+ assert.strictEqual('A', chart.data[0].x);
+ assert.strictEqual('B', chart.data[1].x);
+ assert.strictEqual('C', chart.data[2].x);
+ assert.strictEqual('D', chart.data[3].x);
+ });
+
+ test('controlIsOverviewed', async function() {
+ const histograms = new tr.v.HistogramSet();
+ let hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['A']));
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A']));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [2]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['B']));
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A']));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['A']));
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B']));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [2]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['B']));
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B']));
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ]});
+
+ assert.isFalse(table.viewState.tableRowStates.get('a').isOverviewed);
+
+ const nameCells = getNameCells(table);
+ tr.ui.b.findDeepElementMatchingPredicate(nameCells[0], e =>
+ e.id === 'show_overview').click();
+ assert.isTrue(table.viewState.tableRowStates.get('a').isOverviewed);
+
+ tr.ui.b.findDeepElementMatchingPredicate(nameCells[0], e =>
+ e.id === 'hide_overview').click();
+ assert.isFalse(table.viewState.tableRowStates.get('a').isOverviewed);
+ });
+
+ test('overviewStatistic', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['X'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1, 1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['Y'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1, 1, 1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['X'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1, 1, 1, 1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['Y'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])],
+ ]),
+ });
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({
+ displayStatisticName: 'count',
+ groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ],
+ });
+ await table.viewState.tableRowStates.get('a').update({isOverviewed: true});
+
+ let charts = tr.ui.b.findDeepElementsMatchingPredicate(table, e =>
+ e.tagName === 'svg' && e.parentNode.id === 'overview_container');
+ assert.lengthOf(charts, 3);
+ assert.lengthOf(charts[0].data, 2);
+ assert.lengthOf(charts[1].data, 2);
+ assert.lengthOf(charts[2].data, 2);
+ assert.strictEqual(charts[0].data[0].y, 3);
+ assert.strictEqual(charts[0].data[1].y, 7);
+ assert.strictEqual(charts[1].data[0].y, 1);
+ assert.strictEqual(charts[1].data[1].y, 2);
+ assert.strictEqual(charts[2].data[0].y, 3);
+ assert.strictEqual(charts[2].data[1].y, 4);
+
+ await table.viewState.update({
+ displayStatisticName: tr.v.DELTA + 'count',
+ referenceDisplayLabel: 'A',
+ });
+ charts = tr.ui.b.findDeepElementsMatchingPredicate(table, e =>
+ e.tagName === 'svg' && e.parentNode.id === 'overview_container');
+ assert.lengthOf(charts, 3);
+ assert.lengthOf(charts[0].data, 2);
+ assert.lengthOf(charts[1].data, 2);
+ assert.lengthOf(charts[2].data, 2);
+ assert.strictEqual(charts[0].data[0].y, 3);
+ assert.strictEqual(charts[0].data[1].y, 7);
+ assert.strictEqual(charts[1].data[0].y, 1);
+ assert.strictEqual(charts[1].data[1].y, 2);
+ assert.strictEqual(charts[2].data[0].y, 2);
+ assert.strictEqual(charts[2].data[1].y, 2);
+ });
+
+ test('overviewUnits', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['X'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1, 1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['Y'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1, 1, 1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['X'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])],
+ ]),
+ });
+ histograms.createHistogram(
+ 'a', tr.b.Unit.byName.unitlessNumber, [1, 1, 1, 1], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['Y'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])],
+ ]),
+ });
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({
+ displayStatisticName: 'count',
+ groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ],
+ });
+ await table.viewState.tableRowStates.get('a').update({
+ isExpanded: true,
+ isOverviewed: true,
+ });
+ await table.viewState.tableRowStates.get('a').subRows.get('X').update({
+ isOverviewed: true,
+ });
+
+ const nameCells = getNameCells(table);
+
+ // Check there is no overviewChart in name-cell when column units mismatch.
+ assert.isUndefined(tr.ui.b.findDeepElementMatching(nameCells[0],
+ '#overview_container svg'));
+ assert.isUndefined(tr.ui.b.findDeepElementMatching(nameCells[2],
+ '#overview_container svg'));
+
+ // When column units match, the overview chart should exist and have the
+ // correct unit.
+ const nameOverviewChart = tr.ui.b.findDeepElementMatching(nameCells[1],
+ '#overview_container svg');
+ assert.isDefined(nameOverviewChart);
+ assert.strictEqual(nameOverviewChart.unit, tr.b.Unit.byName.count);
+
+ const cells = getTableCells(table);
+
+ // When subrow units match, the overview chart should exist and have the
+ // correct unit.
+ const overviewChart = tr.ui.b.findDeepElementMatching(cells[0],
+ '#overview_container svg');
+ assert.isDefined(overviewChart);
+ assert.strictEqual(overviewChart.unit, tr.b.Unit.byName.count);
+
+ // Check there is no overviewChart in table-cell when subrow units mismatch.
+ assert.isUndefined(tr.ui.b.findDeepElementMatching(cells[1],
+ '#overview_container svg'));
+
+ // Check there is no overviewChart in table-cell when there are no subrows.
+ assert.isUndefined(tr.ui.b.findDeepElementMatching(cells[2],
+ '#overview_container svg'));
+ assert.isUndefined(tr.ui.b.findDeepElementMatching(cells[3],
+ '#overview_container svg'));
+ assert.isUndefined(tr.ui.b.findDeepElementMatching(cells[4],
+ '#overview_container svg'));
+ assert.isUndefined(tr.ui.b.findDeepElementMatching(cells[5],
+ '#overview_container svg'));
+ });
+
+ test('viewCellOpen', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ const table = await buildTable(this, histograms);
+ const cell = tr.b.getOnlyElement(getTableCells(table));
+ assert.isFalse(cell.isHistogramOpen);
+
+ await table.viewState.tableRowStates.get('a').cells.get('Value').update(
+ {isOpen: true});
+ assert.isTrue(cell.isHistogramOpen);
+
+ await table.viewState.tableRowStates.get('a').cells.get('Value').update(
+ {isOpen: false});
+ assert.isFalse(cell.isHistogramOpen);
+ });
+
+ test('controlCellOpen', async function() {
+ const histograms = new tr.v.HistogramSet();
+ let hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A']));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, [1]);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B']));
+ const table = await buildTable(this, histograms);
+
+ assert.isFalse(table.viewState.tableRowStates.get('a').cells.get('A')
+ .isOpen);
+ const cells = getTableCells(table);
+
+ tr.ui.b.findDeepElementMatchingPredicate(cells[0], e =>
+ e.tagName === 'TR-V-UI-SCALAR-SPAN').click();
+ assert.isTrue(table.viewState.tableRowStates.get('a').cells.get('A')
+ .isOpen);
+
+ tr.ui.b.findDeepElementMatchingPredicate(cells[0], e =>
+ e.id === 'close_histogram').click();
+ assert.isFalse(table.viewState.tableRowStates.get('a').cells.get('A')
+ .isOpen);
+
+ tr.ui.b.findDeepElementMatchingPredicate(table, e =>
+ e.id === 'open_histograms').click();
+ assert.isTrue(table.viewState.tableRowStates.get('a').cells.get('A')
+ .isOpen);
+ assert.isTrue(table.viewState.tableRowStates.get('a').cells.get('B')
+ .isOpen);
+
+ tr.ui.b.findDeepElementMatchingPredicate(table, e =>
+ e.id === 'close_histograms').click();
+ assert.isFalse(table.viewState.tableRowStates.get('a').cells.get('A')
+ .isOpen);
+ assert.isFalse(table.viewState.tableRowStates.get('a').cells.get('B')
+ .isOpen);
+ });
+
+ test('rebin', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a', tr.b.Unit.byName.count, range(0, 100), {
+ binBoundaries: tr.v.HistogramBinBoundaries.SINGULAR,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])],
+ ]),
+ });
+ histograms.createHistogram('a', tr.b.Unit.byName.count, range(50, 150), {
+ binBoundaries: tr.v.HistogramBinBoundaries.SINGULAR,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])],
+ ]),
+ });
+ const table = await buildTable(this, histograms);
+
+ const cells = getTableCells(table);
+ assert.lengthOf(cells, 2);
+ assert.lengthOf(cells[0].histogram.allBins,
+ 2 + tr.v.DEFAULT_REBINNED_COUNT);
+ assert.lengthOf(cells[1].histogram.allBins,
+ 2 + tr.v.DEFAULT_REBINNED_COUNT);
+ assert.strictEqual(cells[0].histogram.allBins[0].range.max, 0);
+ assert.strictEqual(cells[1].histogram.allBins[0].range.max, 0);
+ assert.strictEqual(cells[0].histogram.allBins[41].range.min, 200);
+ assert.strictEqual(cells[1].histogram.allBins[41].range.min, 200);
+ });
+
+ test('leafHistograms', async function() {
+ const histograms = new tr.v.HistogramSet();
+ let hist = histograms.createHistogram('a', tr.b.Unit.byName.count, []);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['A']));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, []);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['B']));
+ const table = await buildTable(this, histograms);
+ assert.lengthOf(table.leafHistograms, 1);
+ await table.viewState.update({groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ]});
+ assert.lengthOf(table.leafHistograms, 2);
+ });
+
+ test('nameCellOverflow', async function() {
+ // TODO(#4321): Switch to using skipped instead once it works
+ return; // https://github.com/catapult-project/catapult/issues/4320
+ /* eslint-disable no-unreachable */
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('a'.repeat(100), tr.b.Unit.byName.count, []);
+ const table = await buildTable(this, histograms);
+ const nameCell = tr.b.getOnlyElement(getNameCells(table));
+ assert.isTrue(nameCell.isOverflowing);
+ assert.isAbove(350, nameCell.getBoundingClientRect().width);
+
+ const dots = tr.ui.b.findDeepElementMatchingPredicate(
+ table, e => e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS);
+ assert.strictEqual('block', dots.style.display);
+ dots.click();
+
+ await tr.b.animationFrame();
+ assert.isFalse(nameCell.isOverflowing);
+ assert.isBelow(350, nameCell.getBoundingClientRect().width);
+ /* eslint-enable no-unreachable */
+ });
+
+ test('nameCellOverflowOnExpand', async function() {
+ // TODO(#4321): Switch to using skipped instead once it works
+ return; // https://github.com/catapult-project/catapult/issues/4320
+ /* eslint-disable no-unreachable */
+ const histograms = new tr.v.HistogramSet();
+ let hist = histograms.createHistogram('a', tr.b.Unit.byName.count, []);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet(['0'.repeat(100)]));
+ hist = histograms.createHistogram('a', tr.b.Unit.byName.count, []);
+ hist.diagnostics.set(
+ tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet(['1'.repeat(100)]));
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ]});
+
+ const dots = tr.ui.b.findDeepElementMatchingPredicate(
+ table, e => e.textContent === tr.v.ui.MIDLINE_HORIZONTAL_ELLIPSIS);
+ assert.strictEqual('none', dots.style.display);
+
+ const baseTable = getBaseTable(table);
+ await table.viewState.tableRowStates.get('a').update({isExpanded: true});
+
+ const nameCell = tr.ui.b.findDeepElementMatchingPredicate(table, e =>
+ e.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-NAME-CELL' &&
+ e.row.name === '0'.repeat(100));
+ await tr.b.animationFrame();
+ assert.isTrue(nameCell.isOverflowing);
+ assert.isAbove(350, nameCell.getBoundingClientRect().width);
+
+ assert.strictEqual('block', dots.style.display);
+ dots.click();
+
+ await tr.b.animationFrame();
+ assert.isFalse(nameCell.isOverflowing);
+ assert.isBelow(350, nameCell.getBoundingClientRect().width);
+ /* eslint-enable no-unreachable */
+ });
+
+ test('overviewCharts', async function() {
+ const binBoundaries = tr.v.HistogramBinBoundaries.createLinear(0, 150, 10);
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('foo', tr.b.Unit.byName.count, [0], {
+ binBoundaries,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['story0'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['0'])],
+ ]),
+ });
+ histograms.createHistogram('foo', tr.b.Unit.byName.count, [10], {
+ binBoundaries,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['story0'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['1'])],
+ ]),
+ });
+ histograms.createHistogram('foo', tr.b.Unit.byName.count, [100], {
+ binBoundaries,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['story1'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['0'])],
+ ]),
+ });
+ histograms.createHistogram('foo', tr.b.Unit.byName.count, [110], {
+ binBoundaries,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['story1'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['1'])],
+ ]),
+ });
+ histograms.createHistogram('bar', tr.b.Unit.byName.count, [0], {
+ binBoundaries,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['story0'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['0'])],
+ ]),
+ });
+ histograms.createHistogram('bar', tr.b.Unit.byName.count, [9], {
+ binBoundaries,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['story0'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['1'])],
+ ]),
+ });
+ histograms.createHistogram('bar', tr.b.Unit.byName.count, [90], {
+ binBoundaries,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['story1'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['0'])],
+ ]),
+ });
+ histograms.createHistogram('bar', tr.b.Unit.byName.count, [99], {
+ binBoundaries,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['story1'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['1'])],
+ ]),
+ });
+ const now = new Date().getTime();
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ ]});
+
+ for (const row of tr.v.ui.HistogramSetTableRowState.walkAll(
+ table.viewState.tableRowStates.values())) {
+ await row.update({isOverviewed: true});
+ }
+
+ let charts = tr.ui.b.findDeepElementsMatchingPredicate(
+ table, e => ((e.id === 'overview_container') &&
+ (e.style.display !== 'none')));
+ charts = charts.map(div => div.children[0]);
+ assert.lengthOf(charts, 6);
+
+ assert.deepEqual(JSON.stringify(charts[0].data),
+ JSON.stringify([{x: '0', y: 45}, {x: '1', y: 54}]));
+ tr.b.assertRangeEquals(
+ charts[0].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
+
+ assert.deepEqual(
+ charts[1].data, [{x: 'story0', y: 0}, {x: 'story1', y: 90}]);
+ tr.b.assertRangeEquals(
+ charts[1].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
+
+ assert.deepEqual(
+ charts[2].data, [{x: 'story0', y: 9}, {x: 'story1', y: 99}]);
+ tr.b.assertRangeEquals(
+ charts[2].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
+
+ assert.deepEqual(charts[3].data, [{x: '0', y: 50}, {x: '1', y: 60}]);
+ tr.b.assertRangeEquals(
+ charts[3].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
+
+ assert.deepEqual(
+ charts[4].data, [{x: 'story0', y: 0}, {x: 'story1', y: 100}]);
+ tr.b.assertRangeEquals(
+ charts[4].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
+
+ assert.deepEqual(
+ charts[5].data, [{x: 'story0', y: 10}, {x: 'story1', y: 110}]);
+ tr.b.assertRangeEquals(
+ charts[5].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
+
+ for (const row of tr.v.ui.HistogramSetTableRowState.walkAll(
+ table.viewState.tableRowStates.values())) {
+ await row.update({isOverviewed: false});
+ }
+
+ charts = tr.ui.b.findDeepElementsMatchingPredicate(
+ table, e => ((e.id === 'overview_container') &&
+ (e.style.display !== 'none')));
+ assert.lengthOf(charts, 0);
+ });
+
+ test('sortByDisplayStatistic', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram(
+ 'bar', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [0, 10], {
+ binBoundaries: TEST_BOUNDARIES,
+ });
+ histograms.createHistogram(
+ 'foo', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [5], {
+ binBoundaries: TEST_BOUNDARIES,
+ });
+
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({
+ sortColumnIndex: 1,
+ sortDescending: false,
+ displayStatisticName: 'min',
+ });
+
+ let nameCells = getNameCells(table);
+ assert.strictEqual(nameCells[0].row.name, 'bar');
+ assert.strictEqual(nameCells[1].row.name, 'foo');
+
+ await table.viewState.update({sortDescending: true});
+
+ nameCells = getNameCells(table);
+ assert.strictEqual(nameCells[0].row.name, 'foo');
+ assert.strictEqual(nameCells[1].row.name, 'bar');
+
+ await table.viewState.update({displayStatisticName: 'max'});
+
+ nameCells = getNameCells(table);
+ assert.strictEqual(nameCells[0].row.name, 'bar');
+ assert.strictEqual(nameCells[1].row.name, 'foo');
+
+ await table.viewState.update({sortDescending: false});
+
+ nameCells = getNameCells(table);
+ assert.strictEqual(nameCells[0].row.name, 'foo');
+ assert.strictEqual(nameCells[1].row.name, 'bar');
+ });
+
+ test('displayStatistic', async function() {
+ const histograms = new tr.v.HistogramSet();
+ const now = new Date().getTime();
+ const barHist = histograms.createHistogram(
+ 'a', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [1, 2, 3], {
+ binBoundaries: TEST_BOUNDARIES,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['bar'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(now)],
+ ]),
+ });
+ const fooHist = histograms.createHistogram(
+ 'a', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [10, 20, 30], {
+ binBoundaries: TEST_BOUNDARIES,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['foo'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(now)],
+ ]),
+ });
+
+ // Add a Histogram with another name so that the table displays the scalars.
+ const quxHist = histograms.createHistogram(
+ 'qux', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: TEST_BOUNDARIES,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['foo'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(now)],
+ ]),
+ });
+
+ const table = await buildTable(this, histograms);
+
+ function histogramsEqual(a, b) {
+ // This is not an exhaustive equality check. This only tests the fields
+ // that are distinguishing for this test().
+ if (a.name !== b.name) return false;
+ return tr.v.HistogramGrouping.DISPLAY_LABEL.callback(a) ===
+ tr.v.HistogramGrouping.DISPLAY_LABEL.callback(b);
+ }
+
+ let fooCell = tr.ui.b.findDeepElementMatchingPredicate(table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ elem.histogram &&
+ histogramsEqual(elem.histogram, fooHist)));
+ assert.isDefined(fooCell);
+
+ let fooContent = tr.ui.b.findDeepElementMatchingPredicate(
+ fooCell, elem => elem.id === 'content');
+ assert.isDefined(fooContent);
+
+ let barCell = tr.ui.b.findDeepElementMatchingPredicate(table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ elem.histogram &&
+ histogramsEqual(elem.histogram, barHist)));
+ assert.isDefined(barCell);
+
+ let barContent = tr.ui.b.findDeepElementMatchingPredicate(
+ barCell, elem => elem.id === 'content');
+ assert.isDefined(barContent);
+
+ assert.strictEqual(table.viewState.displayStatisticName, 'avg');
+ assert.strictEqual('20.000 ms', fooContent.textContent);
+ assert.strictEqual('2.000 ms', barContent.textContent);
+
+ await table.viewState.update({referenceDisplayLabel: 'foo'});
+
+ fooCell = tr.ui.b.findDeepElementMatchingPredicate(table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ elem.histogram &&
+ histogramsEqual(elem.histogram, fooHist)));
+ assert.isDefined(fooCell);
+
+ fooContent = tr.ui.b.findDeepElementMatchingPredicate(
+ fooCell, elem => elem.id === 'content');
+ assert.isDefined(fooContent);
+
+ barCell = tr.ui.b.findDeepElementMatchingPredicate(table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ elem.histogram &&
+ histogramsEqual(elem.histogram, barHist)));
+ assert.isDefined(barCell);
+
+ barContent = tr.ui.b.findDeepElementMatchingPredicate(
+ barCell, elem => elem.id === 'content');
+ assert.isDefined(barContent);
+
+ await table.viewState.update({displayStatisticName: `${tr.v.DELTA}avg`});
+ assert.strictEqual('20.000 ms', fooContent.textContent);
+ assert.strictEqual('-18.000 ms', barContent.textContent);
+
+ await table.viewState.update({displayStatisticName: `%${tr.v.DELTA}avg`});
+
+ fooCell = tr.ui.b.findDeepElementMatchingPredicate(table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ elem.histogram &&
+ histogramsEqual(elem.histogram, fooHist)));
+ assert.isDefined(fooCell);
+
+ fooContent = tr.ui.b.findDeepElementMatchingPredicate(
+ fooCell, elem => elem.id === 'content');
+ assert.isDefined(fooContent);
+
+ barCell = tr.ui.b.findDeepElementMatchingPredicate(table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ elem.histogram &&
+ histogramsEqual(elem.histogram, barHist)));
+ assert.isDefined(barCell);
+
+ barContent = tr.ui.b.findDeepElementMatchingPredicate(
+ barCell, elem => elem.id === 'content');
+ assert.isDefined(barContent);
+
+ assert.strictEqual(table.viewState.displayStatisticName,
+ `%${tr.v.DELTA}avg`);
+ assert.strictEqual('20.000 ms', fooContent.textContent);
+ assert.strictEqual('-90.0%', barContent.textContent);
+ });
+
+ test('requestSelectionChange', async function() {
+ const histograms = new tr.v.HistogramSet();
+ const barHist = histograms.createHistogram(
+ 'bar', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [1], {
+ binBoundaries: TEST_BOUNDARIES,
+ });
+
+ const fooHist = histograms.createHistogram(
+ 'foo', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, {
+ value: 1,
+ diagnostics: {
+ breakdown: tr.v.d.Breakdown.fromEntries([
+ ['bar', 1],
+ ['qux', 0],
+ ]),
+ },
+ }, {
+ binBoundaries: TEST_BOUNDARIES,
+ });
+
+ const quxHist = histograms.createHistogram(
+ 'qux', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: TEST_BOUNDARIES,
+ });
+ const breakdown = new tr.v.d.RelatedNameMap();
+ breakdown.set('bar', barHist.name);
+ breakdown.set('qux', quxHist.name);
+ fooHist.diagnostics.set('breakdown', breakdown);
+
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({showAll: false});
+
+ let fooCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'foo')));
+ assert.isDefined(fooCell);
+
+ let barCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'bar')));
+ assert.isUndefined(barCell);
+
+ fooCell.isHistogramOpen = true;
+
+ const barLink = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => elem.tagName === 'TR-UI-A-ANALYSIS-LINK');
+ assert.isDefined(barLink);
+ barLink.click();
+
+ await tr.b.animationFrame();
+ barCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'bar')));
+ assert.isDefined(barCell);
+
+ await table.viewState.update({searchQuery: ''});
+
+ fooCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'foo')));
+ assert.isDefined(fooCell);
+
+ fooCell.isHistogramOpen = true;
+
+ const selectAllLink = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-UI-A-ANALYSIS-LINK') &&
+ (elem.textContent === 'Select All')));
+ assert.isDefined(selectAllLink);
+ selectAllLink.click();
+
+ assert.strictEqual(table.viewState.searchQuery, '^(bar|qux)$');
+
+ await tr.b.animationFrame();
+ fooCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'foo')));
+ assert.isUndefined(fooCell);
+
+ barCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'bar')));
+ assert.isDefined(barCell);
+
+ const quxCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'qux')));
+ assert.isDefined(quxCell);
+ });
+
+ test('search', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram(
+ 'bar', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [1], {
+ binBoundaries: TEST_BOUNDARIES,
+ });
+ histograms.createHistogram(
+ 'foo', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [1], {
+ binBoundaries: TEST_BOUNDARIES,
+ });
+
+ const table = await buildTable(this, histograms);
+
+ let fooCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'foo')));
+ assert.isDefined(fooCell);
+
+ let barCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'bar')));
+ assert.isDefined(barCell);
+
+ await table.viewState.update({searchQuery: 'bar'});
+
+ fooCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'foo')));
+ assert.isUndefined(fooCell);
+
+ barCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'bar')));
+ assert.isDefined(barCell);
+
+ await table.viewState.update({searchQuery: 'foo'});
+
+ fooCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'foo')));
+ assert.isDefined(fooCell);
+
+ barCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'bar')));
+ assert.isUndefined(barCell);
+
+ // As users type in regexes, some intermediate forms may be invalid regexes.
+ // When the search is an invalid regex, just ignore it.
+ await table.viewState.update({searchQuery: '[a-'});
+
+ fooCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'foo')));
+ assert.isDefined(fooCell);
+
+ barCell = tr.ui.b.findDeepElementMatchingPredicate(
+ table, elem => (
+ (elem.tagName === 'TR-V-UI-HISTOGRAM-SET-TABLE-CELL') &&
+ (elem.histogram.name === 'bar')));
+ assert.isDefined(barCell);
+ });
+
+ test('emptyAndMissing', async function() {
+ const now = new Date().getTime();
+ const histograms = new tr.v.HistogramSet();
+
+ const histA = histograms.createHistogram(
+ 'histogram A', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ range(0, 100).map(i => Math.random() * 1e3), {
+ binBoundaries: TEST_BOUNDARIES,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS,
+ new tr.v.d.GenericSet(['iteration A'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(now)],
+ ]),
+ });
+
+ const histB = histograms.createHistogram(
+ 'histogram B', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ range(0, 100).map(i => Math.random() * 1e3), {
+ binBoundaries: TEST_BOUNDARIES,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS,
+ new tr.v.d.GenericSet(['iteration B'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(now)],
+ ]),
+ });
+
+ const histC = histograms.createHistogram(
+ 'histogram A', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, [], {
+ binBoundaries: TEST_BOUNDARIES,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS,
+ new tr.v.d.GenericSet(['iteration B'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START, new tr.v.d.DateRange(now)],
+ ]),
+ });
+
+ const table = await buildTable(this, histograms);
+
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(
+ table, e => e.textContent === '(empty)'));
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(
+ table, e => e.textContent === '(missing)'));
+ });
+
+ test('instantiate_1x1', async function() {
+ const histograms = new tr.v.HistogramSet();
+ const hist = histograms.createHistogram(
+ 'foo', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ range(0, 100).map(i => Math.random() * 1e3), {
+ binBoundaries: TEST_BOUNDARIES,
+ });
+ const table = await buildTable(this, histograms);
+
+ const baseTable = getBaseTable(table);
+ assert.strictEqual(baseTable.tableRows.length, 1);
+
+ const cell = tr.ui.b.findDeepElementMatchingPredicate(table, elem =>
+ elem.tagName === 'TR-V-UI-SCALAR-SPAN');
+ cell.click();
+
+ const yAxisText = tr.ui.b.findDeepElementMatchingPredicate(table, e =>
+ e.tagName === 'text' && e.textContent === '<0.000 ms');
+ assert.isBelow(0, yAxisText.getBBox().width);
+ });
+
+ test('merge_unmergeable', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('foo', tr.b.Unit.byName.count, [], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['A'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['Value'])],
+ ]),
+ });
+ histograms.createHistogram('foo', tr.b.Unit.byName.count, [], {
+ binBoundaries: tr.v.HistogramBinBoundaries.createLinear(0, 1e3, 21),
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet(['B'])],
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['Value'])],
+ ]),
+ });
+ const table = await buildTable(this, histograms);
+ assert.strictEqual(table.viewState.tableRowStates.size, 1);
+ assert.instanceOf(tr.b.getOnlyElement(getTableCells(table)).histogram,
+ tr.v.HistogramSet);
+ });
+
+ test('instantiate_1x5', async function() {
+ const histograms = new tr.v.HistogramSet();
+
+ for (let i = 0; i < 5; ++i) {
+ histograms.createHistogram(
+ 'foo', tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
+ range(0, 100).map(i => Math.random() * 1e3), {
+ binBoundaries: TEST_BOUNDARIES,
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['' + i])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(new Date().getTime())],
+ ]),
+ });
+ }
+ const table = await buildTable(this, histograms);
+ });
+
+ test('instantiate_2x2', async function() {
+ const histograms = new tr.v.HistogramSet();
+ histograms.createHistogram('foo', tr.b.Unit.byName.count,
+ range(0, 100).map(i => Math.random() * 1e3), {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(new Date().getTime())],
+ ]),
+ });
+ histograms.createHistogram('bar', tr.b.Unit.byName.count,
+ range(0, 100).map(i => Math.random() * 1e3), {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['A'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(new Date().getTime())],
+ ]),
+ });
+ histograms.createHistogram('foo', tr.b.Unit.byName.count,
+ range(0, 100).map(i => Math.random() * 1e3), {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(new Date().getTime())],
+ ]),
+ });
+ histograms.createHistogram('bar', tr.b.Unit.byName.count,
+ range(0, 100).map(i => Math.random() * 1e3), {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet(['B'])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(new Date().getTime())],
+ ]),
+ });
+ const table = await buildTable(this, histograms);
+ const baseTable = getBaseTable(table);
+
+ assert.lengthOf(baseTable.tableColumns, 3);
+ assert.strictEqual('Name',
+ baseTable.tableColumns[0].title.children[0].textContent);
+ assert.strictEqual('A',
+ baseTable.tableColumns[1].title.textContent);
+ assert.strictEqual('B',
+ baseTable.tableColumns[2].title.textContent);
+
+ await table.viewState.update({referenceDisplayLabel: 'A'});
+ baseTable.rebuild();
+ assert.strictEqual(1, baseTable.selectedTableColumnIndex);
+ let cells = getTableCells(table);
+ assert.strictEqual(cells[1].referenceHistogram, cells[0].histogram);
+ assert.strictEqual(cells[3].referenceHistogram, cells[2].histogram);
+
+ await table.viewState.update({referenceDisplayLabel: 'B'});
+ cells = getTableCells(table);
+ assert.strictEqual(2, baseTable.selectedTableColumnIndex);
+ assert.strictEqual(cells[0].referenceHistogram, cells[1].histogram);
+ assert.strictEqual(cells[2].referenceHistogram, cells[3].histogram);
+
+ // Test sorting by the reference column when the displayStatistic is a delta
+ // statistic.
+ await table.viewState.update({sortColumnIndex: 2});
+ let nameCell = getNameCells(table)[0];
+ const originalFirstRow = nameCell.row.name;
+ // This is either 'foo' or 'bar' depending on Math.random() above.
+
+ await table.viewState.update({
+ sortDescending: !table.viewState.sortDescending,
+ });
+ baseTable.rebuild();
+ nameCell = getNameCells(table)[0];
+ assert.notEqual(originalFirstRow, nameCell.row.name);
+ });
+
+ test('merged', async function() {
+ const histograms = new tr.v.HistogramSet();
+ // Add 2^8=256 Histograms, all with the same name, with different metadata.
+ const benchmarkNames = ['bm A', 'bm B'];
+ const storyGroupingKeys0 = ['A', 'B'];
+ const storyGroupingKeys1 = ['C', 'D'];
+ const storyNames = ['story A', 'story B'];
+ const starts = [1439708400000, 1439794800000];
+ const labels = ['label A', 'label B'];
+ const name = 'name '.repeat(20);
+ const unit = tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;
+
+ for (const benchmarkName of benchmarkNames) {
+ for (const storyGroupingKey0 of storyGroupingKeys0) {
+ for (const storyGroupingKey1 of storyGroupingKeys1) {
+ for (const storyName of storyNames) {
+ for (const startMs of starts) {
+ for (let storysetCounter = 0; storysetCounter < 2;
+ ++storysetCounter) {
+ for (const label of labels) {
+ const samples = range(0, 100).map(i => {
+ return {
+ value: Math.random() * 1e3,
+ diagnostics: {i: new tr.v.d.GenericSet([i])},
+ };
+ });
+ histograms.createHistogram(name, unit, samples, {
+ description: 'The best description.',
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.LABELS,
+ new tr.v.d.GenericSet([label])],
+ [tr.v.d.RESERVED_NAMES.STORYSET_REPEATS,
+ new tr.v.d.GenericSet([storysetCounter])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARKS,
+ new tr.v.d.GenericSet([benchmarkName])],
+ [tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(startMs)],
+ [tr.v.d.RESERVED_NAMES.STORIES,
+ new tr.v.d.GenericSet([storyName])],
+ [tr.v.d.RESERVED_NAMES.STORY_TAGS,
+ new tr.v.d.GenericSet([
+ `storyGroupingKey0:${storyGroupingKey0}`,
+ `storyGroupingKey1:${storyGroupingKey1}`,
+ ])],
+ ]),
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ histograms.buildGroupingsFromTags([tr.v.d.RESERVED_NAMES.STORY_TAGS]);
+
+ const table = await buildTable(this, histograms);
+ await table.viewState.update({groupings: [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.BENCHMARKS),
+ tr.v.HistogramGrouping.BY_KEY.get('storyGroupingKey0Tag'),
+ tr.v.HistogramGrouping.BY_KEY.get('storyGroupingKey1Tag'),
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES),
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START),
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORYSET_REPEATS),
+ ]});
+ const baseTable = getBaseTable(table);
+
+ assert.lengthOf(baseTable.tableColumns, 3);
+ const nameHeaderCell = baseTable.tableColumns[0].title;
+ assert.strictEqual('Name', nameHeaderCell.children[0].textContent);
+ assert.strictEqual('label A', baseTable.tableColumns[1].title.textContent);
+ assert.strictEqual('label B', baseTable.tableColumns[2].title.textContent);
+
+ const nameCell = tr.b.getOnlyElement(getNameCells(table));
+ assert.closeTo(346, nameCell.getBoundingClientRect().width, 1);
+
+ nameHeaderCell.children[1].click();
+ // toggleNameColumnWidth_ does not await viewState.update()
+ await tr.b.animationFrame();
+ assert.isBelow(322, nameCell.getBoundingClientRect().width);
+
+ nameHeaderCell.children[1].click();
+ await tr.b.animationFrame();
+ assert.closeTo(346, nameCell.getBoundingClientRect().width, 1);
+
+ assert.lengthOf(baseTable.tableRows, 1);
+ assert.strictEqual(name, baseTable.tableRows[0].name);
+ assert.lengthOf(baseTable.tableRows[0].subRows, 2);
+
+ // assertions only report their arguments, which is not enough information
+ // to diagnose problems with nested structures like tableRows -- the path to
+ // the particular row is needed. This code would be a bit simpler if each
+ // row were given a named variable, but the path to each subRow would still
+ // need to be tracked in order to provide for diagnosing.
+ const subRowPath = [];
+ function getSubRow() {
+ let row = baseTable.tableRows[0];
+ for (const index of subRowPath) {
+ row = row.subRows[index];
+ }
+ return row;
+ }
+
+ for (let i = 0; i < benchmarkNames.length; ++i) {
+ subRowPath.push(i);
+ assert.lengthOf(getSubRow().subRows, 2, subRowPath);
+ assert.strictEqual(benchmarkNames[i], getSubRow().name, subRowPath);
+
+ for (let s = 0; s < storyGroupingKeys0.length; ++s) {
+ subRowPath.push(s);
+ assert.lengthOf(getSubRow().subRows, 2, subRowPath);
+ assert.strictEqual(storyGroupingKeys0[s], getSubRow().name, subRowPath);
+
+ for (let t = 0; t < storyGroupingKeys1.length; ++t) {
+ subRowPath.push(t);
+ assert.lengthOf(getSubRow().subRows, 2, subRowPath);
+ assert.strictEqual(storyGroupingKeys1[t], getSubRow().name,
+ subRowPath);
+
+ for (let j = 0; j < storyNames.length; ++j) {
+ subRowPath.push(j);
+ assert.lengthOf(getSubRow().subRows, 2, subRowPath);
+ assert.strictEqual(storyNames[j], getSubRow().name, subRowPath);
+
+ for (let k = 0; k < starts.length; ++k) {
+ subRowPath.push(k);
+ assert.lengthOf(getSubRow().subRows, 2, subRowPath);
+ assert.strictEqual(tr.b.formatDate(new Date(starts[k])),
+ getSubRow().name, subRowPath);
+
+ for (let l = 0; l < 2; ++l) {
+ subRowPath.push(l);
+ assert.lengthOf(getSubRow().subRows, 0, subRowPath);
+ assert.strictEqual('' + l, getSubRow().name, subRowPath);
+ subRowPath.pop();
+ }
+ subRowPath.pop();
+ }
+ subRowPath.pop();
+ }
+ subRowPath.pop();
+ }
+ subRowPath.pop();
+ }
+ subRowPath.pop();
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view.html
new file mode 100644
index 00000000000..18ba824811f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/ui/null_brushing_state_controller.html">
+<link rel="import" href="/tracing/value/csv_builder.html">
+<link rel="import" href="/tracing/value/histogram_parameter_collector.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_controls.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_table.html">
+<link rel="import" href="/tracing/value/ui/visualizations_data_container.html">
+
+<dom-module id="tr-v-ui-histogram-set-view">
+ <template>
+ <style>
+ :host {
+ font-family: sans-serif;
+ }
+
+ #zero {
+ color: red;
+ /* histogram-set-table is used by both metrics-side-panel and results.html.
+ * This font-size rule has no effect in results.html, but improves
+ * legibility in the metrics-side-panel, which sets font-size in order to
+ * make this table denser.
+ */
+ font-size: initial;
+ }
+
+ #container {
+ display: none;
+ }
+
+ #visualizations{
+ display: none;
+ }
+ </style>
+
+ <div id="zero">zero Histograms</div>
+
+ <div id="container">
+ <tr-v-ui-histogram-set-controls id="controls">
+ </tr-v-ui-histogram-set-controls>
+
+ <tr-v-ui-visualizations-data-container id="visualizations">
+ </tr-v-ui-visualizations-data-container>
+
+ <tr-v-ui-histogram-set-table id="table"></tr-v-ui-histogram-set-table>
+ </div>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-histogram-set-view',
+
+ listeners: {
+ export: 'onExport_',
+ loadVisualization: 'onLoadVisualization_'
+ },
+
+ created() {
+ this.brushingStateController_ = new tr.ui.NullBrushingStateController();
+ this.viewState_ = new tr.v.ui.HistogramSetViewState();
+ this.visualizationLoaded_ = false;
+ },
+
+ ready() {
+ this.$.table.viewState = this.viewState;
+ this.$.controls.viewState = this.viewState;
+ },
+
+ attached() {
+ this.brushingStateController.parentController =
+ tr.c.BrushingStateController.getControllerForElement(this.parentNode);
+ },
+
+ get brushingStateController() {
+ return this.brushingStateController_;
+ },
+
+ get viewState() {
+ return this.viewState_;
+ },
+
+ get histograms() {
+ return this.$.table.histograms;
+ },
+
+ /**
+ * @param {!tr.v.HistogramSet} histograms
+ * @param {!Object=} opt_options
+ * @param {function(string):!Promise=} opt_options.progressconst
+ * @param {string=} opt_options.helpHref
+ * @param {string=} opt_options.feedbackHref
+ */
+ async build(histograms, opt_options) {
+ const options = opt_options || {};
+ const progress = options.progress || (() => Promise.resolve());
+
+ if (options.helpHref) this.$.controls.helpHref = options.helpHref;
+ if (options.feedbackHref) {
+ this.$.controls.feedbackHref = options.feedbackHref;
+ }
+
+ if (histograms === undefined || histograms.length === 0) {
+ this.$.container.style.display = 'none';
+ this.$.zero.style.display = 'block';
+ this.style.display = 'block';
+ return;
+ }
+ this.$.zero.style.display = 'none';
+ this.$.container.style.display = 'block';
+ this.$.container.style.maxHeight = (window.innerHeight - 16) + 'px';
+
+ const buildMark = tr.b.Timing.mark('histogram-set-view', 'build');
+ await progress('Finding important Histograms...');
+ const sourceHistogramsMark = tr.b.Timing.mark(
+ 'histogram-set-view', 'sourceHistograms');
+ const sourceHistograms = histograms.sourceHistograms;
+ sourceHistogramsMark.end();
+ // Disable show_all if all values are sourceHistograms.
+ this.$.controls.showAllEnabled = (
+ sourceHistograms.length !== histograms.length);
+
+ await progress('Collecting parameters...');
+ const collectParametersMark = tr.b.Timing.mark(
+ 'histogram-set-view', 'collectParameters');
+ const parameterCollector = new tr.v.HistogramParameterCollector();
+ parameterCollector.process(histograms);
+ this.$.controls.baseStatisticNames = parameterCollector.statisticNames;
+ this.$.controls.possibleGroupings = parameterCollector.possibleGroupings;
+ const displayLabels = parameterCollector.labels;
+ this.$.controls.displayLabels = displayLabels;
+ collectParametersMark.end();
+
+ // Only show visualizer button if values are from rendering benchmarks
+ const hist = [...histograms][0];
+ const benchmarks = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARKS);
+ let enable = false;
+ if (benchmarks !== undefined && benchmarks.length > 0) {
+ for (const benchmark of benchmarks) {
+ if (benchmark.includes('rendering')) {
+ enable = true;
+ break;
+ }
+ }
+ }
+ this.$.controls.enableVisualization = enable;
+
+ // Table.build() displays its own progress.
+ await this.$.table.build(
+ histograms, sourceHistograms, displayLabels, progress);
+
+ buildMark.end();
+ },
+
+ onExport_(event) {
+ const mark = tr.b.Timing.mark('histogram-set-view', 'export' +
+ (event.merged ? 'Merged' : 'Raw') + event.format.toUpperCase());
+
+ const histograms = event.merged ? this.$.table.leafHistograms :
+ this.histograms;
+
+ let blob;
+ if (event.format === 'csv') {
+ const csv = new tr.v.CSVBuilder(histograms);
+ csv.build();
+ blob = new window.Blob([csv.toString()], {type: 'text/csv'});
+ } else if (event.format === 'json') {
+ blob = new window.Blob([JSON.stringify(histograms.asDicts())],
+ {type: 'text/json'});
+ } else {
+ throw new Error(`Unable to export format "${event.format}"`);
+ }
+
+ const path = window.location.pathname.split('/');
+ const basename = path[path.length - 1].split('.')[0] || 'histograms';
+
+ const anchor = document.createElement('a');
+ anchor.download = `${basename}.${event.format}`;
+ anchor.href = window.URL.createObjectURL(blob);
+ anchor.click();
+ mark.end();
+ },
+
+ onLoadVisualization_(event) {
+ if (!this.visualizationLoaded_) { // Initial loading
+ this.$.visualizations.style.display = 'block';
+ this.$.visualizations.build(this.$.table.leafHistograms,
+ this.histograms);
+ this.visualizationLoaded_ = true;
+ } else if (this.$.visualizations.style.display === 'none') {
+ // Toggle to hide
+ this.$.visualizations.style.display = 'block';
+ } else {
+ this.$.visualizations.style.display = 'none';
+ }
+ },
+ });
+
+ return {
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view_state.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view_state.html
new file mode 100644
index 00000000000..ade4ef2a9c4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view_state.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/view_state.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ class HistogramSetViewState extends tr.b.ViewState {
+ constructor() {
+ super();
+ this.define('searchQuery', '');
+ this.define('referenceDisplayLabel', '');
+ this.define('displayStatisticName', '');
+ this.define('showAll', true);
+ this.define('groupings', []);
+ this.define('sortColumnIndex', 0);
+ this.define('sortDescending', false);
+ this.define('constrainNameColumn', true);
+ this.define('tableRowStates', new Map());
+ this.define('alpha', 0.01);
+ }
+ }
+
+ tr.b.ViewState.register(HistogramSetViewState);
+
+ class HistogramSetTableRowState extends tr.b.ViewState {
+ constructor() {
+ super();
+ this.define('isExpanded', false);
+ this.define('isOverviewed', false);
+ this.define('cells', new Map());
+ this.define('subRows', new Map());
+ this.define('diagnosticsTab', '');
+ }
+
+ asCompactDict() {
+ const result = {};
+ if (this.isExpanded) result.e = '1';
+ if (this.isOverviewed) result.o = '1';
+ if (this.diagnosticsTab) result.d = this.diagnosticsTab;
+ const cells = {};
+ for (const [name, cell] of this.cells) {
+ const cellDict = cell.asCompactDict();
+ if (cellDict === undefined) continue;
+ cells[name] = cellDict;
+ }
+ if (Object.keys(cells).length > 0) result.c = cells;
+
+ const subRows = {};
+ for (const [name, row] of this.subRows) {
+ const rowDict = row.asCompactDict();
+ if (rowDict === undefined) continue;
+ subRows[name] = rowDict;
+ }
+ if (Object.keys(subRows).length > 0) result.r = subRows;
+
+ if (Object.keys(result).length === 0) return undefined;
+
+ return result;
+ }
+
+ async updateFromCompactDict(dict) {
+ await this.update({
+ isExpanded: dict.e === '1',
+ isOverviewed: dict.o === '1',
+ diagnosticsTab: dict.d || '',
+ });
+
+ for (const [name, cellDict] of Object.entries(dict.c || {})) {
+ const cell = this.cells.get(name);
+ if (cell === undefined) continue;
+ await cell.updateFromCompactDict(cellDict);
+ }
+
+ for (const [name, subRowDict] of Object.entries(dict.r || {})) {
+ const subRow = this.subRows.get(name);
+ if (subRow === undefined) continue;
+ await subRow.updateFromCompactDict(subRowDict);
+ }
+ }
+
+ * walk() {
+ yield this;
+ for (const row of this.subRows.values()) yield* row.walk();
+ }
+
+ static* walkAll(rootRows) {
+ for (const rootRow of rootRows) yield* rootRow.walk();
+ }
+ }
+
+ tr.b.ViewState.register(HistogramSetTableRowState);
+
+ class HistogramSetTableCellState extends tr.b.ViewState {
+ constructor() {
+ super();
+ this.define('isOpen', false);
+ this.define('brushedBinRange', new tr.b.math.Range());
+ this.define('mergeSampleDiagnostics', true);
+ }
+
+ asCompactDict() {
+ const result = {};
+ if (this.isOpen) result.o = '1';
+ if (!this.mergeSampleDiagnostics) result.m = '0';
+ if (!this.brushedBinRange.isEmpty) {
+ result.b = this.brushedBinRange.min + '_' + this.brushedBinRange.max;
+ }
+ if (Object.keys(result).length === 0) return undefined;
+ return result;
+ }
+
+ async updateFromCompactDict(dict) {
+ let binRange = this.brushedBinRange;
+ if (dict.b) {
+ let [bMin, bMax] = dict.b.split('_');
+ bMin = parseInt(bMin);
+ bMax = parseInt(bMax);
+ if (bMin !== binRange.min || bMax !== binRange.max) {
+ binRange = tr.b.math.Range.fromExplicitRange(bMin, bMax);
+ }
+ }
+ await this.update({
+ isOpen: dict.o === '1',
+ brushedBinRange: binRange,
+ mergeSampleDiagnostics: dict.m !== '0',
+ });
+ }
+ }
+
+ tr.b.ViewState.register(HistogramSetTableCellState);
+
+ return {
+ HistogramSetTableCellState,
+ HistogramSetTableRowState,
+ HistogramSetViewState,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view_test.html
new file mode 100644
index 00000000000..ede486c98d5
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_set_view_test.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate0', async function() {
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ const histograms = new tr.v.HistogramSet();
+
+ const hist = new tr.v.Histogram('a', tr.b.Unit.byName.normalizedPercentage);
+ for (let i = 0; i < 1e2; ++i) {
+ hist.addSample(Math.random());
+ }
+ histograms.addHistogram(hist);
+
+ this.addHTMLOutput(view);
+ await view.build(histograms);
+
+ assert.strictEqual('none', getComputedStyle(
+ tr.ui.b.findDeepElementMatchingPredicate(
+ view, e => e.textContent === 'zero Histograms')).display);
+ assert.strictEqual('block', getComputedStyle(
+ tr.ui.b.findDeepElementMatchingPredicate(
+ view, e => e.id === 'container')).display);
+ });
+
+ test('implicitUndefinedHistogramSet', async function() {
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ this.addHTMLOutput(view);
+ assert.strictEqual('block', getComputedStyle(
+ tr.ui.b.findDeepElementMatchingPredicate(
+ view, e => e.textContent === 'zero Histograms')).display);
+ assert.strictEqual('none', getComputedStyle(
+ tr.ui.b.findDeepElementMatchingPredicate(
+ view, e => e.id === 'container')).display);
+ });
+
+ test('explicitUndefinedHistogramSet', async function() {
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ this.addHTMLOutput(view);
+ view.build(undefined);
+ assert.strictEqual('block', getComputedStyle(
+ tr.ui.b.findDeepElementMatchingPredicate(
+ view, e => e.textContent === 'zero Histograms')).display);
+ assert.strictEqual('none', getComputedStyle(
+ tr.ui.b.findDeepElementMatchingPredicate(
+ view, e => e.id === 'container')).display);
+ });
+
+ test('emptyHistogramSet', async function() {
+ const view = document.createElement('tr-v-ui-histogram-set-view');
+ this.addHTMLOutput(view);
+ view.build(new tr.v.HistogramSet());
+ assert.strictEqual('block', getComputedStyle(
+ tr.ui.b.findDeepElementMatchingPredicate(
+ view, e => e.textContent === 'zero Histograms')).display);
+ assert.strictEqual('none', getComputedStyle(
+ tr.ui.b.findDeepElementMatchingPredicate(
+ view, e => e.id === 'container')).display);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span.html
new file mode 100644
index 00000000000..c0382f66b93
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span.html
@@ -0,0 +1,599 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/statistics.html">
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/ui/base/box_chart.html">
+<link rel="import" href="/tracing/ui/base/drag_handle.html">
+<link rel="import" href="/tracing/ui/base/name_bar_chart.html">
+<link rel="import" href="/tracing/ui/base/tab_view.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_map_table.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view_state.html">
+<link rel="import" href="/tracing/value/ui/scalar_map_table.html">
+
+<dom-module id="tr-v-ui-histogram-span">
+ <template>
+ <style>
+ #container {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ }
+ #chart {
+ flex-grow: 1;
+ display: none;
+ }
+ #drag_handle, #diagnostics_tab_templates {
+ display: none;
+ }
+ #chart svg {
+ display: block;
+ }
+ #stats_container {
+ overflow-y: auto;
+ }
+ </style>
+
+ <div id="container">
+ <div id="chart"></div>
+ <div id="stats_container">
+ <tr-v-ui-scalar-map-table id="stats"></tr-v-ui-scalar-map-table>
+ </div>
+ </div>
+ <tr-ui-b-drag-handle id="drag_handle"></tr-ui-b-drag-handle>
+
+ <tr-ui-b-tab-view id="diagnostics"></tr-ui-b-tab-view>
+
+ <div id="diagnostics_tab_templates">
+ <tr-v-ui-diagnostic-map-table id="metric_diagnostics"></tr-v-ui-diagnostic-map-table>
+
+ <tr-v-ui-diagnostic-map-table id="metadata_diagnostics"></tr-v-ui-diagnostic-map-table>
+
+ <div id="sample_diagnostics_container">
+ <div id="merge_sample_diagnostics_container">
+ <input type="checkbox" id="merge_sample_diagnostics" checked on-change="updateDiagnostics_">
+ <label for="merge_sample_diagnostics">Merge Sample Diagnostics</label>
+ </div>
+ <tr-v-ui-diagnostic-map-table id="sample_diagnostics"></tr-v-ui-diagnostic-map-table>
+ </div>
+ </div>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ const DEFAULT_BAR_HEIGHT_PX = 5;
+ const TRUNCATE_BIN_MARGIN = 0.15;
+ const IGNORE_DELTA_STATISTICS_NAMES = [
+ `${tr.v.DELTA}min`,
+ `%${tr.v.DELTA}min`,
+ `${tr.v.DELTA}max`,
+ `%${tr.v.DELTA}max`,
+ `${tr.v.DELTA}sum`,
+ `%${tr.v.DELTA}sum`,
+ `${tr.v.DELTA}count`,
+ `%${tr.v.DELTA}count`,
+ ];
+
+ Polymer({
+ is: 'tr-v-ui-histogram-span',
+
+ created() {
+ this.viewStateListener_ = this.onViewStateUpdate_.bind(this);
+ this.viewState = new tr.v.ui.HistogramSetTableCellState();
+ this.rowStateListener_ = this.onRowStateUpdate_.bind(this);
+ this.rowState = new tr.v.ui.HistogramSetTableRowState();
+ this.rootStateListener_ = this.onRootStateUpdate_.bind(this);
+ this.rootState = new tr.v.ui.HistogramSetViewState();
+
+ this.histogram_ = undefined;
+ this.referenceHistogram_ = undefined;
+ this.graphWidth_ = undefined;
+ this.graphHeight_ = undefined;
+ this.mouseDownBin_ = undefined;
+ this.prevBrushedBinRange_ = new tr.b.math.Range();
+ this.anySampleDiagnostics_ = false;
+ this.canMergeSampleDiagnostics_ = true;
+ this.mwuResult_ = undefined;
+ },
+
+ get rowState() {
+ return this.rowState_;
+ },
+
+ set rowState(rs) {
+ if (this.rowState) {
+ this.rowState.removeUpdateListener(this.rowStateListener_);
+ }
+ this.rowState_ = rs;
+ this.rowState.addUpdateListener(this.rowStateListener_);
+ if (this.isAttached) this.updateContents_();
+ },
+
+ get viewState() {
+ return this.viewState_;
+ },
+
+ set viewState(vs) {
+ if (this.viewState) {
+ this.viewState.removeUpdateListener(this.viewStateListener_);
+ }
+ this.viewState_ = vs;
+ this.viewState.addUpdateListener(this.viewStateListener_);
+ if (this.isAttached) this.updateContents_();
+ },
+
+ get rootState() {
+ return this.rootState_;
+ },
+
+ set rootState(vs) {
+ if (this.rootState) {
+ this.rootState.removeUpdateListener(this.rootStateListener_);
+ }
+ this.rootState_ = vs;
+ this.rootState.addUpdateListener(this.rootStateListener_);
+ if (this.isAttached) this.updateContents_();
+ },
+
+ build(histogram, opt_referenceHistogram) {
+ this.histogram_ = histogram;
+ this.$.metric_diagnostics.histogram = histogram;
+ this.$.sample_diagnostics.histogram = histogram;
+ this.referenceHistogram_ = opt_referenceHistogram;
+
+ if (this.histogram.canCompare(this.referenceHistogram)) {
+ this.mwuResult_ = tr.b.math.Statistics.mwu(
+ this.histogram.sampleValues,
+ this.referenceHistogram.sampleValues,
+ this.rootState.alpha);
+ }
+
+ this.anySampleDiagnostics_ = false;
+ for (const bin of this.histogram.allBins) {
+ if (bin.diagnosticMaps.length > 0) {
+ this.anySampleDiagnostics_ = true;
+ break;
+ }
+ }
+
+ if (this.isAttached) this.updateContents_();
+ },
+
+ onViewStateUpdate_(event) {
+ if (event.delta.brushedBinRange) {
+ if (this.chart_ !== undefined) {
+ this.chart_.brushedRange = this.viewState.brushedBinRange;
+ }
+ this.updateDiagnostics_();
+ }
+
+ if (event.delta.mergeSampleDiagnostics &&
+ (this.viewState.mergeSampleDiagnostics !==
+ this.$.merge_sample_diagnostics.checked)) {
+ this.$.merge_sample_diagnostics.checked =
+ this.canMergeSampleDiagnostics &&
+ this.viewState.mergeSampleDiagnostics;
+ this.updateDiagnostics_();
+ }
+ },
+
+ updateSignificance_() {
+ if (!this.mwuResult_) return;
+ this.$.stats.setSignificanceForKey(
+ `${tr.v.DELTA}avg`, this.mwuResult_.significance);
+ },
+
+ onRootStateUpdate_(event) {
+ if (event.delta.alpha && this.mwuResult_) {
+ this.mwuResult_.compare(this.rootState.alpha);
+ this.updateSignificance_();
+ }
+ },
+
+ onRowStateUpdate_(event) {
+ if (event.delta.diagnosticsTab) {
+ if (this.rowState.diagnosticsTab ===
+ this.$.sample_diagnostics_container.tabLabel) {
+ this.updateDiagnostics_();
+ } else {
+ for (const tab of this.$.diagnostics.subViews) {
+ if (this.rowState.diagnosticsTab === tab.tabLabel) {
+ this.$.diagnostics.selectedSubView = tab;
+ break;
+ }
+ }
+ }
+ }
+ },
+
+ ready() {
+ this.$.metric_diagnostics.tabLabel = 'histogram diagnostics';
+ this.$.sample_diagnostics_container.tabLabel = 'sample diagnostics';
+ this.$.metadata_diagnostics.tabLabel = 'metadata';
+ this.$.metadata_diagnostics.isMetadata = true;
+ this.$.diagnostics.addEventListener(
+ 'selected-tab-change', this.onSelectedDiagnosticsChanged_.bind(this));
+ this.$.drag_handle.target = this.$.container;
+ this.$.drag_handle.addEventListener(
+ 'drag-handle-resize', this.onResize_.bind(this));
+ },
+
+ attached() {
+ if (this.histogram_ !== undefined) this.updateContents_();
+ },
+
+ get canMergeSampleDiagnostics() {
+ return this.canMergeSampleDiagnostics_;
+ },
+
+ set canMergeSampleDiagnostics(merge) {
+ this.canMergeSampleDiagnostics_ = merge;
+ if (!merge) this.viewState.mergeSampleDiagnostics = false;
+ this.$.merge_sample_diagnostics_container.style.display = (
+ merge ? '' : 'none');
+ },
+
+ onResize_(event) {
+ event.stopPropagation();
+ let heightPx = parseInt(this.$.container.style.height);
+ if (heightPx < this.defaultGraphHeight) {
+ heightPx = this.defaultGraphHeight;
+ this.$.container.style.height = this.defaultGraphHeight + 'px';
+ }
+ this.chart_.graphHeight = heightPx - (this.chart_.margin.top +
+ this.chart_.margin.bottom);
+ this.$.stats_container.style.maxHeight =
+ this.chart_.getBoundingClientRect().height + 'px';
+ },
+
+ /**
+ * Get the width in pixels of the widest bar in the bar chart, not the total
+ * bar chart svg tag, which includes margins containing axes and legend.
+ *
+ * @return {number}
+ */
+ get graphWidth() {
+ return this.graphWidth_ || this.defaultGraphWidth;
+ },
+
+ /**
+ * Set the width in pixels of the widest bar in the bar chart, not the total
+ * bar chart svg tag, which includes margins containing axes and legend.
+ *
+ * @param {number} width
+ */
+ set graphWidth(width) {
+ this.graphWidth_ = width;
+ },
+
+ /**
+ * Get the height in pixels of the bars in the bar chart, not the total
+ * bar chart svg tag, which includes margins containing axes and legend.
+ *
+ * @return {number}
+ */
+ get graphHeight() {
+ return this.graphHeight_ || this.defaultGraphHeight;
+ },
+
+ /**
+ * Set the height in pixels of the bars in the bar chart, not the total
+ * bar chart svg tag, which includes margins containing axes and legend.
+ *
+ * @param {number} height
+ */
+ set graphHeight(height) {
+ this.graphHeight_ = height;
+ },
+
+ /**
+ * Get the height in pixels of one bar in the bar chart.
+ *
+ * @return {number}
+ */
+ get barHeight() {
+ return this.chart_.barHeight;
+ },
+
+ /**
+ * Set the height in pixels of one bar in the bar chart.
+ *
+ * @param {number} px
+ */
+ set barHeight(px) {
+ this.graphHeight = this.computeChartHeight_(px);
+ },
+
+ computeChartHeight_(barHeightPx) {
+ return (this.chart_.margin.top +
+ this.chart_.margin.bottom +
+ (barHeightPx * this.histogram.allBins.length));
+ },
+
+ get defaultGraphHeight() {
+ if (this.histogram && this.histogram.allBins.length === 1) {
+ return 150;
+ }
+ return this.computeChartHeight_(DEFAULT_BAR_HEIGHT_PX);
+ },
+
+ get defaultGraphWidth() {
+ if (this.histogram.allBins.length === 1) {
+ return 100;
+ }
+ return 300;
+ },
+
+ get brushedBins() {
+ const bins = [];
+ if (this.histogram && !this.viewState.brushedBinRange.isEmpty) {
+ for (let i = this.viewState.brushedBinRange.min;
+ i < this.viewState.brushedBinRange.max; ++i) {
+ bins.push(this.histogram.allBins[i]);
+ }
+ }
+ return bins;
+ },
+
+ async updateBrushedRange_(binIndex) {
+ const brushedBinRange = new tr.b.math.Range();
+ brushedBinRange.addValue(tr.b.math.clamp(
+ this.mouseDownBinIndex_, 0, this.histogram.allBins.length - 1));
+ brushedBinRange.addValue(tr.b.math.clamp(
+ binIndex, 0, this.histogram.allBins.length - 1));
+ brushedBinRange.max += 1;
+ await this.viewState.update({brushedBinRange});
+ },
+
+ onMouseDown_(chartEvent) {
+ chartEvent.stopPropagation();
+ if (!this.histogram) return;
+ this.prevBrushedBinRange_ = this.viewState.brushedBinRange;
+ this.mouseDownBinIndex_ = chartEvent.y;
+ this.updateBrushedRange_(chartEvent.y);
+ },
+
+ onMouseMove_(chartEvent) {
+ chartEvent.stopPropagation();
+ if (!this.histogram) return;
+ this.updateBrushedRange_(chartEvent.y);
+ },
+
+ onMouseUp_(chartEvent) {
+ chartEvent.stopPropagation();
+ if (!this.histogram) return;
+ this.updateBrushedRange_(chartEvent.y);
+ if (this.prevBrushedBinRange_.range === 1 &&
+ this.viewState.brushedBinRange.range === 1 &&
+ (this.prevBrushedBinRange_.min ===
+ this.viewState.brushedBinRange.min)) {
+ tr.b.Timing.instant('histogram-span', 'clearBrushedBins');
+ this.viewState.update({brushedBinRange: new tr.b.math.Range()});
+ } else {
+ tr.b.Timing.instant('histogram-span', 'brushBins');
+ }
+ this.mouseDownBinIndex_ = undefined;
+ },
+
+ async onSelectedDiagnosticsChanged_() {
+ await this.rowState.update({
+ diagnosticsTab: this.$.diagnostics.selectedSubView.tabLabel,
+ });
+ if ((this.$.diagnostics.selectedSubView ===
+ this.$.sample_diagnostics_container) &&
+ this.histogram &&
+ this.viewState.brushedBinRange.isEmpty) {
+ // When the user selects the sample diagnostics tab, if they haven't
+ // already brushed any bins, then automatically brush all bins.
+ const brushedBinRange = tr.b.math.Range.fromExplicitRange(
+ 0, this.histogram.allBins.length);
+ await this.viewState.update({brushedBinRange});
+ this.updateDiagnostics_();
+ }
+ },
+
+ updateDiagnostics_() {
+ let maps = [];
+ for (const bin of this.brushedBins) {
+ for (const map of bin.diagnosticMaps) {
+ maps.push(map);
+ }
+ }
+
+ if (this.$.merge_sample_diagnostics.checked !==
+ this.viewState.mergeSampleDiagnostics) {
+ this.viewState.update({
+ mergeSampleDiagnostics: this.$.merge_sample_diagnostics.checked});
+ }
+
+ if (this.viewState.mergeSampleDiagnostics) {
+ const merged = new tr.v.d.DiagnosticMap();
+ for (const map of maps) {
+ merged.addDiagnostics(map);
+ }
+ maps = [merged];
+ }
+
+ const mark = tr.b.Timing.mark('histogram-span',
+ (this.viewState.mergeSampleDiagnostics ? 'merge' : 'split') +
+ 'SampleDiagnostics');
+ this.$.sample_diagnostics.diagnosticMaps = maps;
+ mark.end();
+
+ if (this.anySampleDiagnostics_) {
+ this.$.diagnostics.selectedSubView =
+ this.$.sample_diagnostics_container;
+ }
+ },
+
+ get histogram() {
+ return this.histogram_;
+ },
+
+ get referenceHistogram() {
+ return this.referenceHistogram_;
+ },
+
+ getDeltaScalars_(statNames, scalarMap) {
+ if (!this.histogram.canCompare(this.referenceHistogram)) return;
+
+ for (const deltaStatName of tr.v.Histogram.getDeltaStatisticsNames(
+ statNames)) {
+ if (IGNORE_DELTA_STATISTICS_NAMES.includes(deltaStatName)) continue;
+ const scalar = this.histogram.getStatisticScalar(
+ deltaStatName, this.referenceHistogram, this.mwuResult_);
+ if (scalar === undefined) continue;
+ scalarMap.set(deltaStatName, scalar);
+ }
+ },
+
+ set isYLogScale(logScale) {
+ this.chart_.isYLogScale = logScale;
+ },
+
+ async updateContents_() {
+ this.$.chart.style.display = 'none';
+ this.$.drag_handle.style.display = 'none';
+ this.$.container.style.justifyContent = '';
+
+ while (Polymer.dom(this.$.chart).lastChild) {
+ Polymer.dom(this.$.chart).removeChild(
+ Polymer.dom(this.$.chart).lastChild);
+ }
+
+ if (!this.histogram) return;
+ this.$.container.style.display = '';
+
+ const scalarMap = new Map();
+ this.getDeltaScalars_(this.histogram.statisticsNames, scalarMap);
+ for (const [name, scalar] of this.histogram.statisticsScalars) {
+ scalarMap.set(name, scalar);
+ }
+ this.$.stats.scalarMap = scalarMap;
+ this.updateSignificance_();
+
+ const metricDiagnosticMap = new tr.v.d.DiagnosticMap();
+ const metadataDiagnosticMap = new tr.v.d.DiagnosticMap();
+ for (const [key, diagnostic] of this.histogram.diagnostics) {
+ // Hide implementation details.
+ if (diagnostic instanceof tr.v.d.RelatedNameMap) continue;
+
+ if (tr.v.d.RESERVED_NAMES_SET.has(key)) {
+ metadataDiagnosticMap.set(key, diagnostic);
+ } else {
+ metricDiagnosticMap.set(key, diagnostic);
+ }
+ }
+
+ const diagnosticTabs = [];
+ if (metricDiagnosticMap.size) {
+ this.$.metric_diagnostics.diagnosticMaps = [metricDiagnosticMap];
+ diagnosticTabs.push(this.$.metric_diagnostics);
+ }
+ if (this.anySampleDiagnostics_) {
+ diagnosticTabs.push(this.$.sample_diagnostics_container);
+ }
+ if (metadataDiagnosticMap.size) {
+ this.$.metadata_diagnostics.diagnosticMaps = [metadataDiagnosticMap];
+ diagnosticTabs.push(this.$.metadata_diagnostics);
+ }
+ this.$.diagnostics.resetSubViews(diagnosticTabs);
+ this.$.diagnostics.set('tabsHidden', diagnosticTabs.length < 2);
+
+ if (this.histogram.numValues <= 1) {
+ await this.viewState.update({
+ brushedBinRange: tr.b.math.Range.fromExplicitRange(
+ 0, this.histogram.allBins.length)});
+ this.$.container.style.justifyContent = 'flex-end';
+ return;
+ }
+
+ this.$.chart.style.display = 'block';
+ this.$.drag_handle.style.display = 'block';
+
+ if (this.histogram.allBins.length === 1) {
+ if (this.histogram.min !== this.histogram.max) {
+ this.chart_ = new tr.ui.b.BoxChart();
+ Polymer.dom(this.$.chart).appendChild(this.chart_);
+ this.chart_.graphWidth = this.graphWidth;
+ this.chart_.graphHeight = this.graphHeight;
+ this.chart_.hideXAxis = true;
+ this.chart_.data = [
+ {
+ x: '',
+ color: 'blue',
+ percentile_0: this.histogram.running.min,
+ percentile_25: this.histogram.getApproximatePercentile(0.25),
+ percentile_50: this.histogram.getApproximatePercentile(0.5),
+ percentile_75: this.histogram.getApproximatePercentile(0.75),
+ percentile_100: this.histogram.running.max,
+ }
+ ];
+ }
+ this.$.stats_container.style.maxHeight =
+ this.chart_.getBoundingClientRect().height + 'px';
+ await this.viewState.update({
+ brushedBinRange: tr.b.math.Range.fromExplicitRange(
+ 0, this.histogram.allBins.length)});
+ return;
+ }
+
+ this.chart_ = new tr.ui.b.NameBarChart();
+ Polymer.dom(this.$.chart).appendChild(this.chart_);
+ this.chart_.graphWidth = this.graphWidth;
+ this.chart_.graphHeight = this.graphHeight;
+ this.chart_.addEventListener('item-mousedown',
+ this.onMouseDown_.bind(this));
+ this.chart_.addEventListener('item-mousemove',
+ this.onMouseMove_.bind(this));
+ this.chart_.addEventListener('item-mouseup',
+ this.onMouseUp_.bind(this));
+ this.chart_.hideLegend = true;
+ this.chart_.getDataSeries('y').color = 'blue';
+ this.chart_.xAxisLabel = '#';
+ this.chart_.brushedRange = this.viewState.brushedBinRange;
+ if (!this.viewState.brushedBinRange.isEmpty) {
+ this.updateDiagnostics_();
+ }
+
+ const chartData = [];
+ const binCounts = [];
+ for (const bin of this.histogram.allBins) {
+ let x = bin.range.min;
+ if (x === -Number.MAX_VALUE) {
+ x = '<' + new tr.b.Scalar(
+ this.histogram.unit, bin.range.max).toString();
+ } else {
+ x = new tr.b.Scalar(this.histogram.unit, x).toString();
+ }
+ chartData.push({x, y: bin.count});
+ binCounts.push(bin.count);
+ }
+
+ // If the largest 1 or 2 bins are more than twice as large as the next
+ // largest bin, then set the dataRange max to TRUNCATE_BIN_MARGIN% more
+ // than that next largest bin.
+ binCounts.sort((x, y) => y - x);
+ const dataRange = tr.b.math.Range.fromExplicitRange(0, binCounts[0]);
+ if (binCounts[1] > 0 && binCounts[0] > (binCounts[1] * 2)) {
+ dataRange.max = binCounts[1] * (1 + TRUNCATE_BIN_MARGIN);
+ }
+ if (binCounts[2] > 0 && binCounts[1] > (binCounts[2] * 2)) {
+ dataRange.max = binCounts[2] * (1 + TRUNCATE_BIN_MARGIN);
+ }
+ this.chart_.overrideDataRange = dataRange;
+
+ this.chart_.data = chartData;
+ this.$.stats_container.style.maxHeight =
+ this.chart_.getBoundingClientRect().height + 'px';
+ }
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html
new file mode 100644
index 00000000000..2ca360b3348
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/histogram_span_test.html
@@ -0,0 +1,300 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/assert_utils.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/ui/histogram_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('basic', function() {
+ const h = new tr.v.Histogram('', tr.b.Unit.byName.unitlessNumber);
+ h.addSample(-1, {foo: new tr.v.d.GenericSet(['a'])});
+ h.addSample(0, {foo: new tr.v.d.GenericSet(['b'])});
+ h.addSample(0, {foo: new tr.v.d.GenericSet(['b'])});
+ h.addSample(0, {foo: new tr.v.d.GenericSet(['b'])});
+ h.addSample(0, {foo: new tr.v.d.GenericSet(['b'])});
+ h.addSample(0, {foo: new tr.v.d.GenericSet(['b'])});
+ h.addSample(0, {foo: new tr.v.d.GenericSet(['b'])});
+ h.addSample(0, {foo: new tr.v.d.GenericSet(['c'])});
+ h.addSample(500, {foo: new tr.v.d.GenericSet(['c'])});
+ h.addSample(999, {foo: new tr.v.d.GenericSet(['d'])});
+ h.addSample(1000, {foo: new tr.v.d.GenericSet(['d'])});
+
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(h);
+ });
+
+ test('emptyHistogram', function() {
+ const h = new tr.v.Histogram('', tr.b.Unit.byName.unitlessNumber);
+
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(h);
+ });
+
+ test('viewBrushedBinRange', async function() {
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(tr.v.Histogram.create('a', tr.b.Unit.byName.count,
+ [0, 1, 2, 3, 4].map(value => {
+ return {value, diagnostics: new Map([
+ ['i', new tr.v.d.GenericSet([value])]])};
+ })));
+ assert.isTrue(span.viewState.brushedBinRange.isEmpty);
+
+ await span.viewState.update({
+ brushedBinRange: tr.b.math.Range.fromExplicitRange(5, 10),
+ });
+ const chart = tr.ui.b.findDeepElementMatchingPredicate(
+ span, e => e.tagName === 'svg');
+ assert.strictEqual(5, chart.brushedRange.min);
+ assert.strictEqual(10, chart.brushedRange.max);
+ });
+
+ test('controlBrushedBinRange', async function() {
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(tr.v.Histogram.create('a', tr.b.Unit.byName.count,
+ [0, 1, 2, 3, 4]));
+ assert.isTrue(span.viewState.brushedBinRange.isEmpty);
+
+ span.onMouseDown_({
+ stopPropagation: () => undefined,
+ y: 21,
+ });
+ span.onMouseUp_({
+ stopPropagation: () => undefined,
+ y: 0,
+ });
+ tr.b.assertRangeEquals(span.viewState.brushedBinRange,
+ tr.b.math.Range.fromExplicitRange(0, 22));
+ });
+
+ test('viewMergeSampleDiagnostics', async function() {
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ const samples = [];
+ for (let i = 0; i < 5; ++i) {
+ samples.push({
+ value: i,
+ diagnostics: {
+ breakdown: tr.v.d.Breakdown.fromDict({
+ values: {
+ a: 5 - i,
+ b: i + 5,
+ c: i,
+ },
+ }),
+ },
+ });
+ }
+ span.build(tr.v.Histogram.create('', tr.b.Unit.byName.count, samples));
+ await span.viewState.update({brushedBinRange:
+ tr.b.math.Range.fromExplicitRange(0, 10)});
+ const merge = tr.ui.b.findDeepElementMatchingPredicate(span, e =>
+ e.id === 'merge_sample_diagnostics');
+ assert.isTrue(merge.checked);
+
+ await span.viewState.update({mergeSampleDiagnostics: false});
+ assert.isFalse(merge.checked);
+
+ await span.viewState.update({mergeSampleDiagnostics: true});
+ assert.isTrue(merge.checked);
+ });
+
+ test('controlMergeSampleDiagnostics', async function() {
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ const samples = [];
+ for (let i = 0; i < 5; ++i) {
+ samples.push({
+ value: i,
+ diagnostics: {
+ breakdown: tr.v.d.Breakdown.fromDict({
+ values: {
+ a: 5 - i,
+ b: i + 5,
+ c: i,
+ },
+ }),
+ },
+ });
+ }
+ span.build(tr.v.Histogram.create('', tr.b.Unit.byName.count, samples));
+ await span.viewState.update({brushedBinRange:
+ tr.b.math.Range.fromExplicitRange(0, 10)});
+ const merge = tr.ui.b.findDeepElementMatchingPredicate(span, e =>
+ e.id === 'merge_sample_diagnostics');
+ assert.isTrue(merge.checked);
+
+ merge.click();
+ assert.isFalse(span.viewState.mergeSampleDiagnostics);
+
+ merge.click();
+ assert.isTrue(span.viewState.mergeSampleDiagnostics);
+ });
+
+ test('mergeSampleDiagnostics', async function() {
+ // Add several samples with sample diagnostics to a Histogram, brush all of
+ // the bins, test that the sample diagnostics are merged.
+ const h = new tr.v.Histogram('', tr.b.Unit.byName.normalizedPercentage);
+ h.addSample(0.1, {foo: tr.v.d.Breakdown.fromDict({values: {a: 1, b: 2}})});
+ h.addSample(0.3, {foo: tr.v.d.Breakdown.fromDict({values: {a: 3, b: 4}})});
+ h.addSample(0.5, {foo: tr.v.d.Breakdown.fromDict({values: {a: 5, b: 6}})});
+ h.addSample(0.7, {foo: tr.v.d.Breakdown.fromDict({values: {a: 7, b: 8}})});
+ h.addSample(0.9, {foo: tr.v.d.Breakdown.fromDict({values: {a: 9, b: 10}})});
+
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(h);
+ await span.viewState.update({
+ brushedBinRange: tr.b.math.Range.fromExplicitRange(0, h.allBins.length)});
+ let breakdowns = tr.ui.b.findDeepElementsMatchingPredicate(
+ span, e => e.tagName === 'TR-V-UI-BREAKDOWN-SPAN');
+ assert.lengthOf(breakdowns, 1);
+
+ const merge = tr.ui.b.findDeepElementMatchingPredicate(
+ span, e => e.id === 'merge_sample_diagnostics');
+ merge.click();
+ breakdowns = tr.ui.b.findDeepElementsMatchingPredicate(
+ span, e => e.tagName === 'TR-V-UI-BREAKDOWN-SPAN');
+ assert.lengthOf(breakdowns, 5);
+ });
+
+ test('cannotMergeSampleDiagnostics', async function() {
+ // Add several samples with sample diagnostics to a Histogram, brush all of
+ // the bins, test that the sample diagnostics are not merged.
+ const h = new tr.v.Histogram('', tr.b.Unit.byName.normalizedPercentage);
+ h.addSample(0.1, {foo: tr.v.d.Breakdown.fromDict({values: {a: 1, b: 2}})});
+ h.addSample(0.3, {foo: tr.v.d.Breakdown.fromDict({values: {a: 3, b: 4}})});
+ h.addSample(0.5, {foo: tr.v.d.Breakdown.fromDict({values: {a: 5, b: 6}})});
+ h.addSample(0.7, {foo: tr.v.d.Breakdown.fromDict({values: {a: 7, b: 8}})});
+ h.addSample(0.9, {foo: tr.v.d.Breakdown.fromDict({values: {a: 9, b: 10}})});
+
+ const span = document.createElement('tr-v-ui-histogram-span');
+ span.canMergeSampleDiagnostics = false;
+ this.addHTMLOutput(span);
+ span.build(h);
+ await span.viewState.update({
+ brushedBinRange: tr.b.math.Range.fromExplicitRange(0, h.allBins.length)});
+ const breakdowns = tr.ui.b.findDeepElementsMatchingPredicate(
+ span, e => e.tagName === 'TR-V-UI-BREAKDOWN-SPAN');
+ assert.lengthOf(breakdowns, 5);
+ });
+
+ test('singleSample', function() {
+ const h = new tr.v.Histogram('', tr.b.Unit.byName.unitlessNumber);
+ h.addSample(100, {
+ sample_diagnostic_0: new tr.v.d.GenericSet(['foo']),
+ sample_diagnostic_1: new tr.v.d.GenericSet(['bar']),
+ });
+ h.diagnostics.set('histogram diagnostic 0', new tr.v.d.GenericSet(['baz']));
+ h.diagnostics.set('histogram diagnostic 1', new tr.v.d.GenericSet(['qux']));
+
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(h);
+ });
+
+ test('nans', function() {
+ const h = new tr.v.Histogram('', tr.b.Unit.byName.unitlessNumber);
+ h.addSample(undefined, {foo: new tr.v.d.GenericSet(['b'])});
+ h.addSample(NaN, {foo: new tr.v.d.GenericSet(['c'])});
+ h.customizeSummaryOptions({nans: true});
+
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(h);
+ });
+
+ test('singleBin', function() {
+ const h = new tr.v.Histogram('', tr.b.Unit.byName.unitlessNumber,
+ tr.v.HistogramBinBoundaries.SINGULAR);
+ h.addSample(0);
+ h.addSample(25);
+ h.addSample(100);
+ h.addSample(100);
+ h.addSample(25);
+ h.addSample(50);
+ h.addSample(75);
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(h);
+ });
+
+ test('referenceHistogram', function() {
+ const span = document.createElement('tr-v-ui-histogram-span');
+ span.build(tr.v.Histogram.create('', tr.b.Unit.byName.count, [1, 10, 100], {
+ binBoundaries: tr.v.HistogramBinBoundaries.SINGULAR,
+ }), tr.v.Histogram.create('', tr.b.Unit.byName.count, [2, 20, 200], {
+ binBoundaries: tr.v.HistogramBinBoundaries.SINGULAR,
+ }));
+ this.addHTMLOutput(span);
+ });
+
+ test('breakdownUnit', async function() {
+ const root = new tr.v.Histogram('root', tr.b.Unit.byName.sizeInBytes);
+ const sampleBreakdown = new tr.v.d.Breakdown();
+ sampleBreakdown.set('x', 30 << 20);
+ sampleBreakdown.set('y', 70 << 20);
+ root.addSample(100 << 20, {sampleBreakdown});
+ const rhb = new tr.v.d.RelatedNameMap();
+ root.diagnostics.set('rhb', rhb);
+ const aHist = new tr.v.Histogram('a', tr.b.Unit.byName.sizeInBytes);
+ rhb.set('a', aHist.name);
+ aHist.addSample(10 << 20);
+ const bHist = new tr.v.Histogram('b', tr.b.Unit.byName.sizeInBytes);
+ rhb.set('b', bHist.name);
+ bHist.addSample(90 << 20);
+ const span = document.createElement('tr-v-ui-histogram-span');
+ this.addHTMLOutput(span);
+ span.build(root);
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(
+ span, e => e.textContent === '100.0 MiB'));
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(
+ span, e => e.textContent === '30.0 MiB'));
+ assert.isDefined(tr.ui.b.findDeepElementMatchingPredicate(
+ span, e => e.textContent === '70.0 MiB'));
+ });
+
+ test('diagnosticsTabs', async function() {
+ const span = document.createElement('tr-v-ui-histogram-span');
+ span.build(tr.v.Histogram.create(
+ '', tr.b.Unit.byName.count, [
+ {value: 1, diagnostics: new Map([
+ ['sample diagnostic', new tr.v.d.GenericSet(['value1'])],
+ ])},
+ {value: 10, diagnostics: new Map([
+ ['sample diagnostic', new tr.v.d.GenericSet(['value10'])],
+ ])},
+ ], {
+ diagnostics: new Map([
+ [tr.v.d.RESERVED_NAMES.BENCHMARKS, new tr.v.d.GenericSet([
+ 'system_health.common_desktop'])],
+ ]),
+ }));
+ this.addHTMLOutput(span);
+
+ const sample = tr.ui.b.findDeepElementMatching(
+ span, '#sample_diagnostics_container');
+ assert.strictEqual(span.rowState.diagnosticsTab, sample.tabLabel);
+ const tabs = tr.ui.b.findDeepElementMatching(
+ span, 'TR-UI-B-TAB-VIEW');
+ assert.strictEqual(tabs.selectedSubView, sample);
+
+ const metadata = tr.ui.b.findDeepElementMatching(
+ span, '#metadata_diagnostics');
+ await span.rowState.update({diagnosticsTab: metadata.tabLabel});
+ assert.strictEqual(tabs.selectedSubView, metadata);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/metrics_visualization.html b/chromium/third_party/catapult/tracing/tracing/value/ui/metrics_visualization.html
new file mode 100644
index 00000000000..1bc6ea696b3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/metrics_visualization.html
@@ -0,0 +1,353 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/running_statistics.html">
+<link rel="import" href="/tracing/ui/base/name_bar_chart.html">
+<link rel="import" href="/tracing/ui/base/name_column_chart.html">
+<dom-module id='tr-v-ui-metrics-visualization'>
+ <template>
+ <style>
+ button {
+ padding: 5px;
+ font-size: 14px;
+ }
+
+ .text_input {
+ width: 50px;
+ padding: 4px;
+ font-size: 14px;
+ }
+
+ .error {
+ color: red;
+ display: none;
+ }
+
+ .container {
+ position: relative;
+ display: inline-block;
+ margin-left: 15px;
+ }
+
+ #title {
+ font-size: 20px;
+ font-weight: bold;
+ padding-bottom: 5px;
+ }
+
+ #selectors {
+ display: block;
+ padding-bottom: 10px;
+ }
+
+ #search_page {
+ width: 200px;
+ margin-left: 30px;
+ }
+
+ #close {
+ display: none;
+ vertical-align: top;
+ }
+
+ #close svg{
+ height: 1em;
+ }
+
+ #close svg line {
+ stroke-width: 18;
+ stroke: black;
+ }
+
+ #close:hover svg {
+ background: black;
+ }
+
+ #close:hover svg line {
+ stroke: white;
+ }
+ </style>
+ <span id="aggregateContainer" class="container">
+ </span>
+ <span id="pageByPageContainer" class="container">
+ <span id="selectors">
+ <span id="percentile_label">Percentile Range:</span>
+ <input id="start" class="text_input" placeholder="0">
+ <input id="end" class="text_input" placeholder="100">
+ <button id="filter" on-tap="filterByPercentile_">Filter</button>
+ <input id="search_page" class="text_input" placeholder="Page Name">
+ <button id="search" on-tap="searchByPage_">Search</button>
+ <span id="search_error" class="error">Sorry, could not find that page!</span>
+ </span>
+ </span>
+ <div id="submetricsContainer" display="block">
+ <span id="close">
+ <svg viewbox="0 0 128 128">
+ <line x1="28" y1="28" x2="100" y2="100"/>
+ <line x1="28" y1="100" x2="100" y2="28"/>
+ </svg>
+ </span>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.v.ui', function() {
+ const PAGE_BREAKDOWN_KEY = 'pageBreakdown';
+
+ Polymer({
+ is: 'tr-v-ui-metrics-visualization',
+
+ created() {
+ this.charts_ = new Map();
+ },
+
+ ready() {
+ this.$.start.addEventListener ('keydown', (e) => {
+ if (e.key === 'Enter') this.filterByPercentile_();
+ });
+
+ this.$.end.addEventListener ('keydown', (e) => {
+ if (e.key === 'Enter') this.filterByPercentile_();
+ });
+
+ this.$.search_page.addEventListener ('keydown', (e) => {
+ if (e.key === 'Enter') this.searchByPage_();
+ });
+ },
+
+ build(chartData) {
+ this.title_ = chartData.title;
+ this.aggregateData_ = chartData.aggregate;
+ this.data_ = chartData.page;
+ this.submetricsData_ = chartData.submetrics;
+ this.benchmarkCount_ = chartData.aggregate.length;
+
+ // build aggregate chart
+ const aggregateChart = this.initializeColumnChart(this.title_);
+ Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);
+ this.charts_.set(tr.v.ui.AGGREGATE_KEY, aggregateChart);
+ this.setChartColors_(tr.v.ui.AGGREGATE_KEY);
+ aggregateChart.data = chartData.aggregate;
+ this.setChartSize_(tr.v.ui.AGGREGATE_KEY);
+
+ // build page by page
+ const newChart = this.initializeColumnChart(this.title_ + ' Breakdown');
+ newChart.enableToolTip = true;
+ newChart.toolTipCallBack = (rect) =>
+ this.openChildChart_(rect);
+ Polymer.dom(this.$.pageByPageContainer).appendChild(newChart);
+ this.charts_.set(PAGE_BREAKDOWN_KEY, newChart);
+ this.setChartColors_(PAGE_BREAKDOWN_KEY);
+ newChart.data = this.data_;
+ this.setChartSize_(PAGE_BREAKDOWN_KEY);
+ },
+
+ setChartSize_(page) {
+ const chart = this.charts_.get(page);
+ const pageCount = chart.data.length;
+ chart.graphHeight = tr.b.math.clamp(pageCount * 20, 400, 600);
+ chart.graphWidth = tr.b.math.clamp(pageCount * 30, 200, 1000);
+ },
+
+ // Assign color gradient to series in chart
+ setChartColors_(page) {
+ const chart = this.charts_.get(page);
+ const metrics = tr.v.ui.METRICS.get(this.title_);
+ for (let i = 0; i < this.benchmarkCount_; ++i) {
+ for (let j = 0; j < metrics.length; ++j) {
+ const mainColorIndex = j % tr.v.ui.COLORS.length;
+ const subColorIndex = i % tr.v.ui.COLORS[mainColorIndex].length;
+ const color = tr.v.ui.COLORS[mainColorIndex][subColorIndex];
+ const series = metrics[j] + '-' + this.aggregateData_[i].x;
+ chart.getDataSeries(series).color = color;
+ if (i === 0) {
+ chart.getDataSeries(series).title = metrics[j];
+ } else {
+ chart.getDataSeries(series).title = '';
+ }
+ }
+ }
+ },
+
+ // Element creation
+ initializeColumnChart(title) {
+ const newChart = new tr.ui.b.NameColumnChart();
+ newChart.hideLegend = false;
+ newChart.isStacked = true;
+ newChart.yAxisLabel = 'ms';
+ newChart.hideXAxis = true;
+ newChart.displayXInHover = true;
+ newChart.isGrouped = true;
+ newChart.showTitleInLegend = true;
+ newChart.chartTitle = title;
+ newChart.titleHeight = '14pt';
+ return newChart;
+ },
+
+ initializeChildChart_(title, height, width) {
+ const div = document.createElement('div');
+ div.classList.add('container');
+ Polymer.dom(this.$.submetricsContainer).
+ insertBefore(div, this.$.submetricsContainer.firstChild);
+
+ const childChart = new tr.ui.b.NameBarChart();
+ childChart.xAxisLabel = 'ms';
+ childChart.chartTitle = title;
+ childChart.graphHeight = height;
+ childChart.graphWidth = width;
+ childChart.titleHeight = '14pt';
+ childChart.isStacked = true;
+ childChart.hideLegend = true;
+ childChart.isGrouped = true;
+ childChart.isWaterfall = true;
+
+ div.appendChild(childChart);
+
+ const button = this.initializeCloseButton_(div,
+ this.$.submetricsContainer);
+ div.appendChild(button);
+ return childChart;
+ },
+
+ initializeCloseButton_(div, parent) {
+ const button = this.$.close.cloneNode(true);
+ button.style.display = 'inline-block';
+ button.addEventListener ('click', () => {
+ Polymer.dom(parent).removeChild(div);
+ });
+ return button;
+ },
+
+ // Create child chart and populate it
+ openChildChart_(rect) {
+ // Find main metric and corresponding sub-metrics
+ const metrics = tr.v.ui.METRICS.get(this.title_);
+ let metric;
+ let metricIndex;
+ for (let i = 0; i < metrics.length; ++i) {
+ if (rect.key.startsWith(metrics[i])) {
+ metric = metrics[i];
+ metricIndex = i;
+ break;
+ }
+ }
+
+ // Create child chart
+ const page = rect.datum.group;
+ const title = this.title_ + ' ' + metric + ': ' + page;
+ const submetrics = this.submetricsData_.get(page).get(metric);
+ const width = tr.b.math.clamp(submetrics.size * 150, 300, 700);
+ const height = tr.b.math.clamp(submetrics.size *
+ this.benchmarkCount_ * 50, 300, 700);
+
+ const childChart = this.initializeChildChart_(title, height, width);
+
+ // Get breakdown data for main step
+ childChart.data = this.processSubmetrics_(childChart,
+ submetrics, 0, metricIndex).data;
+ },
+
+ processSubmetrics_(chart, submetrics, hideValue, metricIndex) {
+ const finalData = [];
+ let submetricIndex = 0;
+ for (const submetric of submetrics.values()) {
+ let benchmarkIndex = 0;
+ for (const benchmark of submetric.values()) {
+ benchmark.hide = !hideValue ? 0 : hideValue;
+ const series = benchmark.x + '-' + benchmark.group;
+ const mainColorIndex = metricIndex % tr.v.ui.COLORS.length;
+ const subColorIndex = benchmarkIndex %
+ tr.v.ui.COLORS[mainColorIndex].length;
+ chart.getDataSeries(series).color =
+ tr.v.ui.COLORS[mainColorIndex][subColorIndex];
+ if (benchmarkIndex === (this.benchmarkCount_ - 1)) {
+ hideValue += benchmark[series];
+ }
+ finalData.push(benchmark);
+ benchmarkIndex++;
+ }
+ submetricIndex++;
+ }
+ return {data: finalData, hide: hideValue};
+ },
+
+ // Handle filtering by start and end percentiles
+ filterByPercentile_() {
+ const startPercentile = this.$.start.value;
+ const endPercentile = this.$.end.value;
+
+ if (startPercentile === '' || endPercentile === '') return;
+
+ const length = this.data_.length / (this.benchmarkCount_ + 1);
+ const startIndex = this.getPercentileIndex_(startPercentile, length);
+ const endIndex = this.getPercentileIndex_(endPercentile, length);
+ this.charts_.get(PAGE_BREAKDOWN_KEY).data =
+ this.data_.slice(startIndex, endIndex);
+ },
+
+ // Get index of x percentile value
+ getPercentileIndex_(percentile, arrayLength) {
+ const index = Math.ceil(arrayLength * (percentile / 100.0));
+ if (index === -1) return 0;
+ if (index >= arrayLength) return arrayLength;
+ return index * this.benchmarkCount_;
+ },
+
+ // Handle searching by page name
+ searchByPage_() {
+ const criteria = this.$.search_page.value;
+ if (criteria === '') return;
+
+ const query = new RegExp(criteria);
+
+ const filteredData = [...this.data_]
+ .filter(group => {
+ if (group.group) return group.group.match(query);
+ return false;
+ });
+
+ if (filteredData.length < 1) {
+ this.$.search_error.style.display = 'block';
+ return;
+ }
+
+ // Create child chart with breakdown data
+ const page = filteredData[0].group;
+ const title = this.title_ + ' Breakdown: ' + page;
+ const metricToSubmetricMap = this.submetricsData_.get(page);
+
+ let totalSubmetrics = 0;
+ for (const submetrics of metricToSubmetricMap.values()) {
+ for (const benchmark of submetrics.values()) {
+ totalSubmetrics += benchmark.length;
+ }
+ }
+ const width = tr.b.math.clamp(totalSubmetrics * 150, 300, 700);
+ const height = tr.b.math.clamp(totalSubmetrics *
+ this.benchmarkCount_ * 30, 300, 700);
+
+ const childChart = this.initializeChildChart_(title, height, width);
+
+ const childData = [];
+ let hide = 0;
+ let metricIndex = 0;
+ for (const submetrics of metricToSubmetricMap.values()) {
+ const submetricsData = this.processSubmetrics_(childChart, submetrics,
+ hide, metricIndex);
+ childData.push(...submetricsData.data);
+ hide = submetricsData.hide;
+ metricIndex++;
+ }
+ childChart.data = childData;
+ },
+
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/metrics_visualization_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/metrics_visualization_test.html
new file mode 100644
index 00000000000..0d062557f63
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/metrics_visualization_test.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/ui/metrics_visualization.html">
+<link rel="import" href="/tracing/value/ui/visualizations_data_container.html">
+
+<script>
+'use strict';
+tr.b.unittest.testSuite(function() {
+ function generateChartBar(metrics, benchmark, page) {
+ const data = {x: benchmark, group: page};
+ for (const metric of metrics) {
+ const key = metric + '-' + benchmark;
+ const mean = Math.random() * 100;
+ data[key] = Math.round(mean * 100) / 100;
+ }
+ return data;
+ }
+
+ function generateSubmetricBar(submetric, benchmark, page,
+ metricToSubmetricMap) {
+ let submetricToBenchmarkMap = metricToSubmetricMap.get(submetric);
+ if (!submetricToBenchmarkMap) {
+ submetricToBenchmarkMap = [];
+ metricToSubmetricMap.set(submetric, submetricToBenchmarkMap);
+ }
+ const data = {x: submetric, hide: 0, group: benchmark};
+ const mean = Math.random() * 100;
+ data[submetric + '-' + benchmark] = Math.round(mean * 100) / 100;
+ submetricToBenchmarkMap.push(data);
+ }
+
+ test('instantiate', function() {
+ const mv = document.createElement('tr-v-ui-metrics-visualization');
+ this.addHTMLOutput(mv);
+
+ const testMetrics = tr.v.ui.METRICS.get('Thread');
+
+ // generate aggregate chart
+ const aggregateChart = [];
+ for (let i = 1; i <= 5; i++) {
+ aggregateChart.push(generateChartBar(testMetrics,
+ 'Run ' + i, 'aggregate'));
+ }
+
+ // generate chart with individual page metrics
+ const chartData = [];
+ for (let i = 1; i <= 5; i++) {
+ for (let j = 1; j <= 5; j++) {
+ chartData.push(generateChartBar(testMetrics,
+ 'Run ' + i, 'Page ' + j));
+ }
+ }
+
+ // generate submetrics
+ const submetricsData = new Map();
+ for (const metric in testMetrics) {
+ const testSubmetrics = [metric + 'a', metric + 'b', metric + 'c'];
+ for (let i = 1; i <= 5; i++) {
+ const page = 'Page ' + i;
+ const pageToMetricMap = tr.v.ui.getValueFromMap(page,
+ submetricsData);
+ const metricToSubmetricMap = tr.v.ui.getValueFromMap(metric,
+ pageToMetricMap);
+ for (let j = 1; j <= 5; j++) {
+ for (const submetric in testSubmetrics) {
+ generateSubmetricBar(submetric, 'Run ' + j, page,
+ metricToSubmetricMap);
+ }
+ }
+ }
+ }
+
+ mv.build({
+ title: 'Thread',
+ aggregate: aggregateChart,
+ page: chartData,
+ submetrics: submetricsData
+ });
+ });
+});
+</script> \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/preferred_display_unit.html b/chromium/third_party/catapult/tracing/tracing/value/ui/preferred_display_unit.html
new file mode 100644
index 00000000000..b546041de50
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/preferred_display_unit.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+
+<script>
+ 'use strict';
+ Polymer({
+ is: 'tr-v-ui-preferred-display-unit',
+
+ ready() {
+ this.preferredTimeDisplayMode_ = undefined;
+ },
+
+ attached() {
+ tr.b.Unit.didPreferredTimeDisplayUnitChange();
+ },
+
+ detached() {
+ tr.b.Unit.didPreferredTimeDisplayUnitChange();
+ },
+
+ // null means no-preference
+ get preferredTimeDisplayMode() {
+ return this.preferredTimeDisplayMode_;
+ },
+
+ set preferredTimeDisplayMode(v) {
+ if (this.preferredTimeDisplayMode_ === v) return;
+ this.preferredTimeDisplayMode_ = v;
+ tr.b.Unit.didPreferredTimeDisplayUnitChange();
+ }
+
+ });
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/preferred_display_unit_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/preferred_display_unit_test.html
new file mode 100644
index 00000000000..382dc5963fe
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/preferred_display_unit_test.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/time_display_modes.html">
+<link rel="import" href="/tracing/value/ui/preferred_display_unit.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const unit = document.createElement('tr-v-ui-preferred-display-unit');
+ const ms = tr.b.TimeDisplayModes.ms;
+ unit.preferredDisplayUnit = ms;
+ assert.strictEqual(unit.preferredDisplayUnit, ms);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/raster_visualization.html b/chromium/third_party/catapult/tracing/tracing/value/ui/raster_visualization.html
new file mode 100644
index 00000000000..d3253d8eff9
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/raster_visualization.html
@@ -0,0 +1,274 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<dom-module id='tr-v-ui-raster-visualization'>
+ <template>
+ <style>
+ button {
+ padding: 5px;
+ font-size: 14px;
+ }
+ .error {
+ color: red;
+ display: none;
+ }
+
+ .text_input {
+ width: 200px;
+ padding: 4px;
+ font-size: 14px;
+ }
+
+ .selector_container{
+ padding: 5px;
+ }
+
+ #search {
+ display: inline-block;
+ padding-bottom: 10px;
+ }
+
+ #search_page {
+ width: 200px;
+ }
+
+ #pageSelector {
+ display: inline-block;
+ font-size: 12pt;
+ }
+
+ #close {
+ display: none;
+ vertical-align: top;
+ }
+
+ #close svg{
+ height: 1em;
+ }
+
+ #close svg line {
+ stroke-width: 18;
+ stroke: black;
+ }
+
+ #close:hover svg {
+ background: black;
+ }
+
+ #close:hover svg line {
+ stroke: white;
+ }
+ </style>
+ <span id="aggregateContainer">
+ <div>
+ <div class="selector_container">
+ <span id="select_page_label">Individual Page Results:</span>
+ <select id="pageSelector">
+ <option id="select_page" value="">Select a page</option>
+ </select>
+ </div>
+ <div class="selector_container">
+ <div id="search_page_label">Search for a page:</div>
+ <input id="search_page" class="text_input" placeholder="Page Name">
+ <button id="search_button">Search</button>
+ <div id="search_error" class="error">Sorry, could not find that page!</div>
+ </div>
+ </div>
+ </span>
+ <span id="pageContainer">
+ <span id="close">
+ <svg viewbox="0 0 128 128">
+ <line x1="28" y1="28" x2="100" y2="100"/>
+ <line x1="28" y1="100" x2="100" y2="28"/>
+ </svg>
+ </span>
+ </span>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-v-ui-raster-visualization',
+
+ ready() {
+ this.$.pageSelector.addEventListener ('click', () => {
+ this.selectPage_();
+ });
+
+ this.$.search_page.addEventListener ('keydown', (e) => {
+ if (e.key === 'Enter') this.searchByPage_();
+ });
+
+ this.$.search_button.addEventListener ('click', () => {
+ this.searchByPage_();
+ });
+ },
+
+
+ build(chartData) {
+ this.data_ = chartData;
+ const aggregateChart = this.createChart_('Aggregate Data by Run');
+ Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);
+ aggregateChart.enableToolTip = true;
+ aggregateChart.toolTipCallBack = (rect) =>
+ this.openBenchmarkChart_(rect);
+ this.setChartColors_(aggregateChart, this.data_.get(tr.v.ui.AGGREGATE_KEY));
+ aggregateChart.data = this.data_.get(tr.v.ui.AGGREGATE_KEY);
+ this.setChartSize_(aggregateChart,
+ this.data_.get(tr.v.ui.AGGREGATE_KEY).length);
+
+ for (const page of this.data_.keys()) {
+ if (page === tr.v.ui.AGGREGATE_KEY) continue;
+ const option = document.createElement('option');
+ option.textContent = page;
+ option.value = page;
+ this.$.pageSelector.appendChild(option);
+ }
+ },
+
+ setChartSize_(chart, pageCount, dataLength) {
+ chart.graphHeight = tr.b.math.clamp(pageCount * 25, 175, 1000);
+ chart.graphWidth = tr.b.math.clamp(pageCount * 25, 500, 1000);
+ },
+
+ setChartColors_(chart, data) {
+ const metrics = new Map();
+ let count = 0;
+ for (const thread of tr.v.ui.FRAME.values()) {
+ for (const metric of thread.keys()) {
+ metrics.set(metric, count);
+ count++;
+ }
+ }
+ for (let i = 0; i < Math.floor(data.length / tr.v.ui.FRAME.length); ++i) {
+ let j = 0;
+ for (const [threadName, thread] of tr.v.ui.FRAME.entries()) {
+ for (const metric of thread.keys()) {
+ let color = 'transparent';
+ if (thread.get(metric)) {
+ const mainColorIndex = metrics.get(metric) % tr.v.ui.COLORS.length;
+ const subColorIndex = i % tr.v.ui.COLORS[mainColorIndex].length;
+ color = tr.v.ui.COLORS[mainColorIndex][subColorIndex];
+ }
+ const series = metric + '-' + data[i * 2 + j].x + '-' + threadName;
+ chart.getDataSeries(series).color = color;
+ chart.getDataSeries(series).title = !i ? metric : '';
+ }
+ j++;
+ }
+ }
+ },
+
+ createChart_(title) {
+ const newChart = new tr.ui.b.NameBarChart();
+ newChart.chartTitle = title;
+ newChart.xAxisLabel = 'ms';
+ newChart.hideLegend = false;
+ newChart.showTitleInLegend = true;
+ newChart.hideYAxis = true;
+ newChart.isStacked = true;
+ newChart.displayXInHover = true;
+ newChart.isGrouped = true;
+ return newChart;
+ },
+
+ openBenchmarkChart_(rect) {
+ // Find main metric and corresponding sub-metrics
+ const benchmarkIndex = Math.floor(rect.index / tr.v.ui.FRAME.length);
+ const title = rect.datum.x;
+
+ // Create child chart with breakdown data
+ const div = document.createElement('div');
+ Polymer.dom(this.$.pageContainer).
+ insertBefore(div, this.$.pageContainer.firstChild);
+
+ const chart = this.createChart_(title);
+
+ div.appendChild(chart);
+ const button = this.initializeCloseButton_(div, this.$.pageContainer);
+ div.appendChild(button);
+
+ const newDataSet = [];
+
+ for (const page of this.data_.keys()) {
+ if (page === tr.v.ui.AGGREGATE_KEY) continue;
+ for (let i = 0; i < tr.v.ui.FRAME.length; i++) {
+ newDataSet.push(this.data_
+ .get(page)[benchmarkIndex * tr.v.ui.FRAME.length + i]);
+ }
+ }
+
+ this.setChartColors_(chart, newDataSet);
+ chart.data = newDataSet;
+ this.setChartSize_(chart, newDataSet.length);
+ },
+
+ selectPage_() {
+ // Create child chart with breakdown data
+ const div = document.createElement('div');
+ const page = this.$.pageSelector.value;
+ if (page === '') return;
+ Polymer.dom(this.$.pageContainer).
+ insertBefore(div, this.$.pageContainer.firstChild);
+
+ const pageChart = this.createChart_(page);
+
+ div.appendChild(pageChart);
+ const button = this.initializeCloseButton_(div, this.$.pageContainer);
+ div.appendChild(button);
+
+ const pageData = this.data_.get(page);
+
+ this.setChartColors_(pageChart, pageData);
+ pageChart.data = pageData;
+ this.setChartSize_(pageChart, pageData.length);
+ },
+
+ searchByPage_() {
+ const criteria = this.$.search_page.value;
+ if (criteria === '') return;
+
+ const query = new RegExp(criteria);
+
+ const filteredData = [...this.data_.keys()]
+ .filter(page => page.match(query));
+
+ if (filteredData.length < 1) {
+ this.$.search_error.style.display = 'block';
+ return;
+ }
+
+ // Create child chart with breakdown data
+ const page = filteredData[0];
+
+ const div = document.createElement('div');
+ Polymer.dom(this.$.pageContainer).
+ insertBefore(div, this.$.pageContainer.firstChild);
+
+ const pageChart = this.createChart_(page);
+
+ div.appendChild(pageChart);
+ const button = this.initializeCloseButton_(div, this.$.pageContainer);
+ div.appendChild(button);
+
+ const pageData = this.data_.get(page);
+
+ this.setChartColors_(pageChart, pageData);
+ pageChart.data = pageData;
+ this.setChartSize_(pageChart, pageData.length);
+ },
+
+ initializeCloseButton_(div, parent) {
+ const button = this.$.close.cloneNode(true);
+ button.style.display = 'inline-block';
+ button.addEventListener('click', () => {
+ Polymer.dom(parent).removeChild(div);
+ });
+ return button;
+ },
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/raster_visualization_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/raster_visualization_test.html
new file mode 100644
index 00000000000..eaf3ee61842
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/raster_visualization_test.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/ui/raster_visualization.html">
+<link rel="import" href="/tracing/value/ui/visualizations_data_container.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function generateBars(page, benchmark) {
+ const benchmarkData = [];
+ for (const [threadName, thread] of tr.v.ui.FRAME.entries()) {
+ const data = {x: benchmark, hide: 0};
+ if (page !== tr.v.ui.AGGREGATE_KEY) data.group = page;
+ for (const metric of thread.keys()) {
+ const key = metric + '-' + data.x + '-' + threadName;
+ const mean = Math.random() * 100;
+ data[key] = Math.round(mean * 100) / 100;
+ }
+ benchmarkData.push(data);
+ }
+ return benchmarkData;
+ }
+
+ test('instantiate', function() {
+ const rv = document.createElement('tr-v-ui-raster-visualization');
+ this.addHTMLOutput(rv);
+
+ const allChartData = new Map();
+
+ // generate aggregate data
+ let aggregateData = [];
+ for (let i = 1; i <= 5; i++) {
+ aggregateData = aggregateData.concat(generateBars(tr.v.ui.AGGREGATE_KEY,
+ 'Run ' + i));
+ }
+ allChartData.set(tr.v.ui.AGGREGATE_KEY, aggregateData);
+
+ // generate data per page
+ for (let i = 1; i <= 5; i++) {
+ const page = 'Page ' + i;
+ let chartData = [];
+ for (let j = 1; j <= 5; j++) {
+ chartData = chartData.concat(generateBars(page, 'Run ' + j));
+ }
+ allChartData.set(page, chartData);
+ }
+
+ rv.build(allChartData);
+ });
+});
+</script> \ No newline at end of file
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span.html
new file mode 100644
index 00000000000..ac52e51aba2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span_behavior.html">
+
+<dom-module id="tr-v-ui-related-event-set-span">
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-related-event-set-span',
+ behaviors: [tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],
+
+ updateContents_() {
+ Polymer.dom(this).textContent = '';
+ const events = new tr.model.EventSet([...this.diagnostic]);
+ const link = document.createElement('tr-ui-a-analysis-link');
+ let label = events.length + ' events';
+ if (events.length === 1) {
+ const event = tr.b.getOnlyElement(events);
+ label = event.title + ' ';
+ label += tr.b.Unit.byName.timeDurationInMs.format(
+ event.duration);
+ }
+ link.setSelectionAndContent(events, label);
+ Polymer.dom(this).appendChild(link);
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html
new file mode 100644
index 00000000000..b0058a3c97b
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/related_event_set_span_test.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/related_event_set.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate_RelatedEventSet0', function() {
+ const diagnostic = new tr.v.d.RelatedEventSet();
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-RELATED-EVENT-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ assert.strictEqual('0 events', span.textContent);
+ });
+
+ test('instantiate_RelatedEventSet1', function() {
+ const diagnostic = new tr.v.d.RelatedEventSet();
+ tr.c.TestUtils.newModel(function(model) {
+ const proc = model.getOrCreateProcess(1);
+ const thread = proc.getOrCreateThread(2);
+ const event = tr.c.TestUtils.newSliceEx(
+ {title: 'a', start: 0, duration: 1});
+ thread.sliceGroup.pushSlice(event);
+ diagnostic.add(event);
+ });
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-RELATED-EVENT-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ assert.strictEqual('a 1.000 ms', span.textContent);
+ });
+
+ test('instantiate_RelatedEventSet2', function() {
+ const diagnostic = new tr.v.d.RelatedEventSet();
+ tr.c.TestUtils.newModel(function(model) {
+ const proc = model.getOrCreateProcess(1);
+ const thread = proc.getOrCreateThread(2);
+ let event = tr.c.TestUtils.newSliceEx({start: 0, duration: 1});
+ thread.sliceGroup.pushSlice(event);
+ diagnostic.add(event);
+ event = tr.c.TestUtils.newSliceEx({start: 1, duration: 1});
+ thread.sliceGroup.pushSlice(event);
+ diagnostic.add(event);
+ });
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-RELATED-EVENT-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ assert.strictEqual('2 events', span.textContent);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller.html
new file mode 100644
index 00000000000..ac71cd7a1d7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller.html
@@ -0,0 +1,204 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/raf.html">
+
+<dom-module id="tr-v-ui-scalar-context-controller">
+ <template></template>
+</dom-module>
+
+<!--
+@fileoverview Polymer element for controlling common context across scalar
+spans. To facilitate multiple separate contexts (e.g. a separate context for
+each table column), each scalar span has to specify which "context group"
+it belongs to:
+
+ +============ some container element (e.g. <div>) ============+
+ | |
+ | <tr-v-ui-scalar-context-controller> |
+ | ^ ^ |
+ | | | |
+ | v v |
+ | .... Context group 1 .... .... Context group 2 .... |
+ | : <tr-v-ui-scalar-span> : : <tr-v-ui-scalar-span> : |
+ | : <tr-v-ui-scalar-span> : : <tr-v-ui-scalar-span> : . . . |
+ | : . . . : : . . . : |
+ | :.......................: :.......................: |
+ +=============================================================+
+
+An element can find its enclosing context controller using the
+getScalarContextControllerForElement(node) defined in this file. Scalar spans
+can push their state to the controller using the following three methods:
+
+ 1. onScalarSpanAdded(contextGroup, span)
+ This method should be called when a span is attached to the DOM tree (or
+ afterwards when added to a context group).
+
+ 2. onScalarSpanRemoved(contextGroup, span)
+ This method should be called when a span is detached from the DOM tree (or
+ beforehand when removed from a context group).
+
+ 3. onScalarSpanUpdated(contextGroup, span)
+ This method should be called when the value of a span changes.
+
+Note: If a span wants to change its context group, it should first call
+onScalarSpanRemoved with the old group and then onScalarSpanAdded with the new
+group.
+
+If one or more group contexts are modified (due to one of the three methods
+above), the controller will asynchronously (at the next RAF) update them and
+fire a 'context-updated' event. Scalar spans can listen for this event and
+update their UI accordingly.
+
+The context currently consists of the range of values of the associated spans.
+This allows automatic display of relative sizes using sparklines.
+
+The controller design is based on:
+https://docs.google.com/document/d/16ih8yYK8kF8MMlPnB-5KlyfS_AjjtbyAfi3pkxoZ8xs/edit?usp=sharing
+-->
+<script>
+'use strict';
+
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-scalar-context-controller',
+
+ created() {
+ this.host_ = undefined;
+ this.groupToContext_ = new Map();
+ this.dirtyGroups_ = new Set();
+ },
+
+ attached() {
+ if (this.host_) {
+ throw new Error(
+ 'Scalar context controller is already attached to a host');
+ }
+
+ const host = findParentOrHost(this);
+ if (host.__scalarContextController) {
+ throw new Error(
+ 'Multiple scalar context controllers attached to this host');
+ }
+
+ host.__scalarContextController = this;
+ this.host_ = host;
+ },
+
+ detached() {
+ if (!this.host_) {
+ throw new Error('Scalar context controller is not attached to a host');
+ }
+ if (this.host_.__scalarContextController !== this) {
+ throw new Error(
+ 'Scalar context controller is not attached to its host');
+ }
+
+ delete this.host_.__scalarContextController;
+ this.host_ = undefined;
+ },
+
+ getContext(group) {
+ return this.groupToContext_.get(group);
+ },
+
+ onScalarSpanAdded(group, span) {
+ let context = this.groupToContext_.get(group);
+ if (context === undefined) {
+ context = {
+ spans: new Set(),
+ range: new tr.b.math.Range()
+ };
+ this.groupToContext_.set(group, context);
+ }
+ if (context.spans.has(span)) {
+ throw new Error('Scalar span already registered with group: ' + group);
+ }
+ context.spans.add(span);
+ this.markGroupDirtyAndScheduleUpdate_(group);
+ },
+
+ onScalarSpanRemoved(group, span) {
+ const context = this.groupToContext_.get(group);
+ if (!context.spans.has(span)) {
+ throw new Error('Scalar span not registered with group: ' + group);
+ }
+ context.spans.delete(span);
+ this.markGroupDirtyAndScheduleUpdate_(group);
+ },
+
+ onScalarSpanUpdated(group, span) {
+ const context = this.groupToContext_.get(group);
+ if (!context.spans.has(span)) {
+ throw new Error('Scalar span not registered with group: ' + group);
+ }
+ this.markGroupDirtyAndScheduleUpdate_(group);
+ },
+
+ markGroupDirtyAndScheduleUpdate_(group) {
+ const alreadyDirty = this.dirtyGroups_.size > 0;
+ this.dirtyGroups_.add(group);
+ if (!alreadyDirty) {
+ tr.b.requestAnimationFrameInThisFrameIfPossible(
+ this.updateContext, this);
+ }
+ },
+
+ updateContext() {
+ const groups = this.dirtyGroups_;
+ if (groups.size === 0) return;
+ this.dirtyGroups_ = new Set();
+
+ for (const group of groups) {
+ this.updateGroup_(group);
+ }
+
+ const event = new tr.b.Event('context-updated');
+ event.groups = groups;
+ this.dispatchEvent(event);
+ },
+
+ updateGroup_(group) {
+ const context = this.groupToContext_.get(group);
+ if (context.spans.size === 0) {
+ this.groupToContext_.delete(group);
+ return;
+ }
+ context.range.reset();
+ for (const span of context.spans) {
+ context.range.addValue(span.value);
+ }
+ }
+ });
+
+ function getScalarContextControllerForElement(element) {
+ while (element) {
+ if (element.__scalarContextController) {
+ return element.__scalarContextController;
+ }
+ element = findParentOrHost(element);
+ }
+ return undefined;
+ }
+
+ function findParentOrHost(node) {
+ if (node.parentElement) {
+ return node.parentElement;
+ }
+ while (Polymer.dom(node).parentNode) {
+ node = Polymer.dom(node).parentNode;
+ }
+ return node.host;
+ }
+
+ return {
+ getScalarContextControllerForElement,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html
new file mode 100644
index 00000000000..ccb3f61d6f4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_context_controller_test.html
@@ -0,0 +1,312 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/utils.html">
+<link rel="import" href="/tracing/value/ui/scalar_context_controller.html">
+
+<dom-module id="tr-v-ui-scalar-context-controller-mock-host">
+ <template>
+ <tr-v-ui-scalar-context-controller id="controller">
+ </tr-v-ui-scalar-context-controller>
+ <content></content>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const getScalarContextControllerForElement =
+ tr.v.ui.getScalarContextControllerForElement;
+
+ Polymer({
+ is: 'tr-v-ui-scalar-context-controller-mock-host'
+ });
+
+ test('getScalarContextControllerForElement', function() {
+ const root = document.createElement('div');
+ Polymer.dom(document.body).appendChild(root);
+ try {
+ assert.isUndefined(getScalarContextControllerForElement(root));
+
+ // <div> root
+ // |__<div> host1
+ // |__<tr-v-ui-scalar-context-controller> c1
+ const host1 = document.createElement('div');
+ Polymer.dom(root).appendChild(host1);
+ assert.isUndefined(getScalarContextControllerForElement(root));
+ assert.strictEqual(getScalarContextControllerForElement(host1));
+ const c1 = document.createElement('tr-v-ui-scalar-context-controller');
+ Polymer.dom(host1).appendChild(c1);
+ assert.isUndefined(getScalarContextControllerForElement(root));
+ assert.strictEqual(getScalarContextControllerForElement(host1), c1);
+
+ // <div> root
+ // |__<div> host1
+ // | |__<tr-v-ui-scalar-context-controller> c1
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host2
+ // :..<tr-v-ui-scalar-context-controller> c2
+ const host2 = document.createElement(
+ 'tr-v-ui-scalar-context-controller-mock-host');
+ const c2 = host2.$.controller;
+ Polymer.dom(root).appendChild(host2);
+ assert.isUndefined(getScalarContextControllerForElement(root));
+ assert.strictEqual(getScalarContextControllerForElement(host1), c1);
+ assert.strictEqual(getScalarContextControllerForElement(host2), c2);
+
+ // <div> root
+ // |__<div> host1
+ // | |__<tr-v-ui-scalar-context-controller> c1
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host2
+ // | :..<tr-v-ui-scalar-context-controller> c2
+ // |__<div> divA
+ // |__<div> divB
+ const divA = document.createElement('div');
+ Polymer.dom(host2).appendChild(divA);
+ assert.strictEqual(getScalarContextControllerForElement(divA), c2);
+ const divB = document.createElement('div');
+ Polymer.dom(divA).appendChild(divB);
+ assert.strictEqual(getScalarContextControllerForElement(divB), c2);
+
+ // <div> root
+ // |__<div> host1
+ // | |_<tr-v-ui-scalar-context-controller> c1
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host2
+ // | :.-<tr-v-ui-scalar-context-controller> c2
+ // |__<div> divA
+ // |__<div> divB
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host3
+ // :..<tr-v-ui-scalar-context-controller> c3
+ const host3 = document.createElement(
+ 'tr-v-ui-scalar-context-controller-mock-host');
+ Polymer.dom(divB).appendChild(host3);
+ const c3 = host3.$.controller;
+ assert.isUndefined(getScalarContextControllerForElement(root));
+ assert.strictEqual(getScalarContextControllerForElement(host1), c1);
+ assert.strictEqual(getScalarContextControllerForElement(host2), c2);
+ assert.strictEqual(getScalarContextControllerForElement(divA), c2);
+ assert.strictEqual(getScalarContextControllerForElement(divB), c2);
+ assert.strictEqual(getScalarContextControllerForElement(host3), c3);
+
+ // <div> root
+ // |__<div> host1
+ // | |_<tr-v-ui-scalar-context-controller> c1
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host2
+ // | :.-<tr-v-ui-scalar-context-controller> c2
+ // |__<div> divA
+ // | :.<tr-v-ui-scalar-context-controller> c4
+ // |__<div> divB
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host3
+ // :..<tr-v-ui-scalar-context-controller> c3
+ const c4 = document.createElement('tr-v-ui-scalar-context-controller');
+ Polymer.dom(divA).appendChild(c4);
+ assert.isUndefined(getScalarContextControllerForElement(root));
+ assert.strictEqual(getScalarContextControllerForElement(host1), c1);
+ assert.strictEqual(getScalarContextControllerForElement(host2), c2);
+ assert.strictEqual(getScalarContextControllerForElement(divA), c4);
+ assert.strictEqual(getScalarContextControllerForElement(divB), c4);
+ assert.strictEqual(getScalarContextControllerForElement(host3), c3);
+
+ // <div> root
+ // |__<div> host1
+ // | |_<tr-v-ui-scalar-context-controller> c1
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host2
+ // | :.-<tr-v-ui-scalar-context-controller> c2
+ // |__<div> divA
+ // | :.<tr-v-ui-scalar-context-controller> c4
+ // |__<div> divB
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host3
+ Polymer.dom(host3.root).removeChild(c3);
+ assert.isUndefined(getScalarContextControllerForElement(root));
+ assert.strictEqual(getScalarContextControllerForElement(host1), c1);
+ assert.strictEqual(getScalarContextControllerForElement(host2), c2);
+ assert.strictEqual(getScalarContextControllerForElement(divA), c4);
+ assert.strictEqual(getScalarContextControllerForElement(divB), c4);
+ assert.strictEqual(getScalarContextControllerForElement(host3), c4);
+
+ // <div> root
+ // |__<div> host1
+ // | |_<tr-v-ui-scalar-context-controller> c1
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host2
+ // |__<div> divA
+ // | :.<tr-v-ui-scalar-context-controller> c4
+ // |__<div> divB
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host3
+ Polymer.dom(host2.root).removeChild(c2);
+ assert.isUndefined(getScalarContextControllerForElement(root));
+ assert.strictEqual(getScalarContextControllerForElement(host1), c1);
+ assert.isUndefined(getScalarContextControllerForElement(host2));
+ assert.strictEqual(getScalarContextControllerForElement(divA), c4);
+ assert.strictEqual(getScalarContextControllerForElement(divB), c4);
+ assert.strictEqual(getScalarContextControllerForElement(host3), c4);
+
+ // <div> root
+ // | :.<tr-v-ui-scalar-context-controller> c3
+ // |__<div> host1
+ // | |_<tr-v-ui-scalar-context-controller> c1
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host2
+ // |__<div> divA
+ // | :.<tr-v-ui-scalar-context-controller> c4
+ // |__<div> divB
+ // |__<tr-v-ui-scalar-context-controller-mock-host> host3
+ Polymer.dom(root).appendChild(c3);
+ assert.strictEqual(getScalarContextControllerForElement(root), c3);
+ assert.strictEqual(getScalarContextControllerForElement(host1), c1);
+ assert.strictEqual(getScalarContextControllerForElement(host2), c3);
+ assert.strictEqual(getScalarContextControllerForElement(divA), c4);
+ assert.strictEqual(getScalarContextControllerForElement(divB), c4);
+ assert.strictEqual(getScalarContextControllerForElement(host3), c4);
+ } finally {
+ Polymer.dom(document.body).removeChild(root);
+ }
+ });
+
+ function contextTest(name, testCallback) {
+ test('context_' + name, function() {
+ const root = document.createElement('div');
+ Polymer.dom(document.body).appendChild(root);
+ try {
+ const c = document.createElement('tr-v-ui-scalar-context-controller');
+ Polymer.dom(root).appendChild(c);
+
+ let updatedGroups = []; // Fail if event fires unexpectedly.
+ c.addEventListener('context-updated', function(e) {
+ if (updatedGroups) {
+ assert.fail('Unexpected context-updated event fired.');
+ }
+ updatedGroups = Array.from(e.groups);
+ });
+
+ c.expectContextUpdatedEventForTesting =
+ function(expectedUpdatedGroups) {
+ updatedGroups = undefined;
+ tr.b.forceAllPendingTasksToRunForTest();
+ assert.sameMembers(updatedGroups, expectedUpdatedGroups);
+ };
+
+ testCallback.call(this, c);
+ } finally {
+ Polymer.dom(document.body).removeChild(root);
+ }
+ });
+ }
+
+ contextTest('singleGroup', function(c) {
+ assert.isUndefined(c.getContext('G'));
+
+ const s1 = {value: 10};
+ c.onScalarSpanAdded('G', s1);
+ c.expectContextUpdatedEventForTesting(['G']);
+ assert.isTrue(c.getContext('G').range.equals(
+ tr.b.math.Range.fromExplicitRange(10, 10)));
+ assert.sameMembers(Array.from(c.getContext('G').spans), [s1]);
+
+ const s2 = {value: 15};
+ c.onScalarSpanAdded('G', s2);
+ c.expectContextUpdatedEventForTesting(['G']);
+ assert.isTrue(c.getContext('G').range.equals(
+ tr.b.math.Range.fromExplicitRange(10, 15)));
+ assert.sameMembers(Array.from(c.getContext('G').spans), [s1, s2]);
+
+ s1.value = 5;
+ c.onScalarSpanUpdated('G', s1);
+ c.expectContextUpdatedEventForTesting(['G']);
+ assert.isTrue(c.getContext('G').range.equals(
+ tr.b.math.Range.fromExplicitRange(5, 15)));
+ assert.sameMembers(Array.from(c.getContext('G').spans), [s1, s2]);
+
+ c.onScalarSpanRemoved('G', s2);
+ c.expectContextUpdatedEventForTesting(['G']);
+ assert.isTrue(c.getContext('G').range.equals(
+ tr.b.math.Range.fromExplicitRange(5, 5)));
+ assert.sameMembers(Array.from(c.getContext('G').spans), [s1]);
+
+ const s3 = {value: 0};
+ c.onScalarSpanAdded('G', s3);
+ s2.value = 14;
+ c.onScalarSpanAdded('G', s2);
+ c.expectContextUpdatedEventForTesting(['G']);
+ assert.isTrue(c.getContext('G').range.equals(
+ tr.b.math.Range.fromExplicitRange(0, 14)));
+ assert.sameMembers(Array.from(c.getContext('G').spans), [s1, s2, s3]);
+
+ c.onScalarSpanRemoved('G', s1);
+ c.onScalarSpanRemoved('G', s2);
+ c.onScalarSpanRemoved('G', s3);
+ c.expectContextUpdatedEventForTesting(['G']);
+ assert.isUndefined(c.getContext('G'));
+
+ c.onScalarSpanAdded('G', s2);
+ c.expectContextUpdatedEventForTesting(['G']);
+ assert.isTrue(c.getContext('G').range.equals(
+ tr.b.math.Range.fromExplicitRange(14, 14)));
+ assert.sameMembers(Array.from(c.getContext('G').spans), [s2]);
+ });
+
+ contextTest('multipleGroups', function(c) {
+ assert.isUndefined(c.getContext('G1'));
+ assert.isUndefined(c.getContext('G2'));
+
+ const s1 = {value: 0};
+ c.onScalarSpanAdded('G1', s1);
+ c.expectContextUpdatedEventForTesting(['G1']);
+ assert.isTrue(c.getContext('G1').range.equals(
+ tr.b.math.Range.fromExplicitRange(0, 0)));
+ assert.sameMembers(Array.from(c.getContext('G1').spans), [s1]);
+
+ const s2 = {value: 1};
+ c.onScalarSpanAdded('G2', s2);
+ c.expectContextUpdatedEventForTesting(['G2']);
+ assert.isTrue(c.getContext('G2').range.equals(
+ tr.b.math.Range.fromExplicitRange(1, 1)));
+ assert.sameMembers(Array.from(c.getContext('G2').spans), [s2]);
+
+ const s3 = {value: 2};
+ const s4 = {value: -1};
+ c.onScalarSpanAdded('G2', s3);
+ c.onScalarSpanAdded('G1', s4);
+ c.expectContextUpdatedEventForTesting(['G1', 'G2']);
+ assert.isTrue(c.getContext('G1').range.equals(
+ tr.b.math.Range.fromExplicitRange(-1, 0)));
+ assert.sameMembers(Array.from(c.getContext('G1').spans), [s1, s4]);
+ assert.isTrue(c.getContext('G2').range.equals(
+ tr.b.math.Range.fromExplicitRange(1, 2)));
+ assert.sameMembers(Array.from(c.getContext('G2').spans), [s2, s3]);
+
+ c.onScalarSpanRemoved('G2', s3);
+ c.onScalarSpanAdded('G1', s3);
+ c.expectContextUpdatedEventForTesting(['G1', 'G2']);
+ assert.isTrue(c.getContext('G1').range.equals(
+ tr.b.math.Range.fromExplicitRange(-1, 2)));
+ assert.sameMembers(Array.from(c.getContext('G1').spans), [s1, s3, s4]);
+ assert.isTrue(c.getContext('G2').range.equals(
+ tr.b.math.Range.fromExplicitRange(1, 1)));
+ assert.sameMembers(Array.from(c.getContext('G2').spans), [s2]);
+
+ s4.value = 3;
+ c.onScalarSpanUpdated('G1', s4);
+ s1.value = 1;
+ c.onScalarSpanUpdated('G1', s1);
+ c.expectContextUpdatedEventForTesting(['G1']);
+ assert.isTrue(c.getContext('G1').range.equals(
+ tr.b.math.Range.fromExplicitRange(1, 3)));
+ assert.sameMembers(Array.from(c.getContext('G1').spans), [s1, s3, s4]);
+ assert.isTrue(c.getContext('G2').range.equals(
+ tr.b.math.Range.fromExplicitRange(1, 1)));
+ assert.sameMembers(Array.from(c.getContext('G2').spans), [s2]);
+
+ c.onScalarSpanRemoved('G2', s2);
+ c.expectContextUpdatedEventForTesting(['G2']);
+ assert.isTrue(c.getContext('G1').range.equals(
+ tr.b.math.Range.fromExplicitRange(1, 3)));
+ assert.sameMembers(Array.from(c.getContext('G1').spans), [s1, s3, s4]);
+ assert.isUndefined(c.getContext('G2'));
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_diagnostic_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_diagnostic_span.html
new file mode 100644
index 00000000000..631c3696f8c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_diagnostic_span.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/ui/diagnostic_span_behavior.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id="tr-v-ui-scalar-diagnostic-span">
+ <template>
+ <tr-v-ui-scalar-span id="scalar"></tr-v-ui-scalar-span>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-scalar-diagnostic-span',
+ behaviors: [tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],
+
+ updateContents_() {
+ this.$.scalar.setValueAndUnit(this.diagnostic.value.value,
+ this.diagnostic.value.unit);
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_diagnostic_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_diagnostic_span_test.html
new file mode 100644
index 00000000000..9f6167f1acb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_diagnostic_span_test.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/diagnostics/scalar.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const diagnostic = new tr.v.d.Scalar(new tr.b.Scalar(
+ tr.b.Unit.byName.timeDurationInMs, 123.456));
+ const span = tr.v.ui.createDiagnosticSpan(diagnostic);
+ assert.strictEqual('TR-V-UI-SCALAR-DIAGNOSTIC-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_map_table.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_map_table.html
new file mode 100644
index 00000000000..24a5cf3ac0f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_map_table.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/ui/base/table.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<dom-module id="tr-v-ui-scalar-map-table">
+ <template>
+ <tr-ui-b-table id="table"></tr-ui-b-table>
+ </template>
+</dom-module>
+
+<script>
+'use strict';
+Polymer({
+ is: 'tr-v-ui-scalar-map-table',
+
+ created() {
+ /** @type {!Map.<string, !tr.b.Scalar>} */
+ this.scalarMap_ = new Map();
+
+ /** @type {!Map.<string, !tr.b.math.Statistics.Significance>} */
+ this.significance_ = new Map();
+ },
+
+ ready() {
+ this.$.table.showHeader = false;
+ this.$.table.tableColumns = [
+ {
+ value(row) {
+ return row.name;
+ }
+ },
+ {
+ value(row) {
+ const span = tr.v.ui.createScalarSpan(row.value);
+ if (row.significance !== undefined) {
+ span.significance = row.significance;
+ } else if (row.anyRowsHaveSignificance) {
+ // Ensure vertical alignment.
+ span.style.marginRight = '18px';
+ }
+ span.style.whiteSpace = 'nowrap';
+ return span;
+ }
+ }
+ ];
+ },
+
+ get scalarMap() {
+ return this.scalarMap_;
+ },
+
+ /**
+ * @param {!Map.<string,!tr.b.Scalar>} map
+ */
+ set scalarMap(map) {
+ this.scalarMap_ = map;
+ this.updateContents_();
+ },
+
+ /**
+ * @param {string} key
+ * @param {!tr.b.math.Statistics.Significance} significance
+ */
+ setSignificanceForKey(key, significance) {
+ this.significance_.set(key, significance);
+ this.updateContents_();
+ },
+
+ updateContents_() {
+ const rows = [];
+ for (const [key, scalar] of this.scalarMap) {
+ rows.push({
+ name: key,
+ value: scalar,
+ significance: this.significance_.get(key),
+ anyRowsHaveSignificance: (this.significance_.size > 0)
+ });
+ }
+ this.$.table.tableRows = rows;
+ this.$.table.rebuild();
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_map_table_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_map_table_test.html
new file mode 100644
index 00000000000..4c9a50c2314
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_map_table_test.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/ui/scalar_map_table.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const span = document.createElement('tr-v-ui-scalar-map-table');
+
+ const histogram = new tr.v.Histogram('', tr.b.Unit.byName.energyInJoules);
+ for (let i = 0; i < 1e2; ++i) {
+ histogram.addSample(Math.random() * 1000);
+ }
+
+ histogram.addSample('foo');
+ histogram.customizeSummaryOptions({nans: true});
+
+ span.scalarMap = histogram.statisticsScalars;
+ this.addHTMLOutput(span);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span.html
new file mode 100644
index 00000000000..50d89653ed1
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span.html
@@ -0,0 +1,626 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/ui/base/deep_utils.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/ui/scalar_context_controller.html">
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ /**
+ * One common simple way to use this function is
+ * createScalarSpan(number, {unit: tr.b.Unit.byName.whatever})
+ *
+ * This function can also take a Scalar, undefined, or a Histogram plus
+ * significance, contextGroup, customContextRange, leftAlign and/or inline.
+ *
+ * @param {undefined|tr.b.Scalar|tr.v.Histogram} value
+ * @param {Object=} opt_config
+ * @param {!tr.b.math.Range=} opt_config.customContextRange
+ * @param {boolean=} opt_config.leftAlign
+ * @param {boolean=} opt_config.inline
+ * @param {!tr.b.Unit=} opt_config.unit
+ * @param {tr.b.math.Statistics.Significance=} opt_config.significance
+ * @param {string=} opt_config.contextGroup
+ * @return {(string|!HTMLElement)}
+ */
+ function createScalarSpan(value, opt_config) {
+ if (value === undefined) return '';
+
+ const config = opt_config || {};
+ const ownerDocument = config.ownerDocument || document;
+
+ const span = ownerDocument.createElement('tr-v-ui-scalar-span');
+
+ let numericValue;
+ if (value instanceof tr.b.Scalar) {
+ span.value = value;
+ numericValue = value.value;
+ } else if (value instanceof tr.v.Histogram) {
+ numericValue = value.average;
+ if (numericValue === undefined) return '';
+ span.setValueAndUnit(numericValue, value.unit);
+ } else {
+ const unit = config.unit;
+ if (unit === undefined) {
+ throw new Error(
+ 'Unit must be provided in config when value is a number');
+ }
+ span.setValueAndUnit(value, unit);
+ numericValue = value;
+ }
+
+ if (config.context) {
+ span.context = config.context;
+ }
+
+ if (config.customContextRange) {
+ span.customContextRange = config.customContextRange;
+ }
+
+ if (config.leftAlign) {
+ span.leftAlign = true;
+ }
+
+ if (config.inline) {
+ span.inline = true;
+ }
+
+ if (config.significance !== undefined) {
+ span.significance = config.significance;
+ }
+
+ if (config.contextGroup !== undefined) {
+ span.contextGroup = config.contextGroup;
+ }
+
+ return span;
+ }
+
+ return {
+ createScalarSpan,
+ };
+});
+</script>
+
+<dom-module id="tr-v-ui-scalar-span">
+ <template>
+ <style>
+ :host {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ position: relative;
+ /* Limit the sparkline's negative z-index to the span only. */
+ isolation: isolate;
+ }
+
+ :host(.left-align) {
+ justify-content: flex-start;
+ }
+
+ :host(.inline) {
+ display: inline-flex;
+ }
+
+ #sparkline {
+ width: 0%;
+ position: absolute;
+ bottom: 0;
+ display: none;
+ height: 100%;
+ background-color: hsla(216, 100%, 94.5%, .75);
+ border-color: hsl(216, 100%, 89%);
+ box-sizing: border-box;
+ z-index: -1;
+ }
+ #sparkline.positive {
+ border-right-style: solid;
+ /* The border width must be kept in sync with buildSparklineStyle_(). */
+ border-right-width: 1px;
+ }
+ #sparkline:not(.positive) {
+ border-left-style: solid;
+ /* The border width must be kept in sync with buildSparklineStyle_(). */
+ border-left-width: 1px;
+ }
+ #sparkline.better {
+ background-color: hsla(115, 100%, 93%, .75);
+ border-color: hsl(118, 60%, 80%);
+ }
+ #sparkline.worse {
+ background-color: hsla(0, 100%, 88%, .75);
+ border-color: hsl(0, 100%, 80%);
+ }
+
+ #content {
+ white-space: nowrap;
+ }
+ #content, #significance, #warning {
+ flex-grow: 0;
+ }
+ #content.better {
+ color: green;
+ }
+ #content.worse {
+ color: red;
+ }
+
+ #significance svg {
+ margin-left: 4px;
+ display: none;
+ height: 1em;
+ vertical-align: text-top;
+ stroke-width: 4;
+ fill: rgba(0, 0, 0, 0);
+ }
+ #significance #insignificant {
+ stroke: black;
+ }
+ #significance #significantly_better {
+ stroke: green;
+ }
+ #significance #significantly_worse {
+ stroke: red;
+ }
+
+ #warning {
+ display: none;
+ margin-left: 4px;
+ height: 1em;
+ vertical-align: text-top;
+ stroke-width: 0;
+ }
+ #warning path {
+ fill: rgb(255, 185, 185);
+ }
+ #warning rect {
+ fill: red;
+ }
+ </style>
+
+ <span id="sparkline"></span>
+
+ <span id="content"></span>
+
+ <span id="significance">
+ <!-- Neutral face -->
+ <svg viewbox="0 0 128 128" id="insignificant">
+ <circle r="60" cx="64" cy="64"/>
+ <circle r="4" cx="44" cy="44"/>
+ <circle r="4" cx="84" cy="44"/>
+ <line x1="36" x2="92" y1="80" y2="80"/>
+ </svg>
+
+ <!-- Smiling face -->
+ <svg viewbox="0 0 128 128" id="significantly_better">
+ <circle r="60" cx="64" cy="64"/>
+ <circle r="4" cx="44" cy="44"/>
+ <circle r="4" cx="84" cy="44"/>
+ <path d="M 28 64 Q 64 128 100 64"/>
+ </svg>
+
+ <!-- Frowning face -->
+ <svg viewbox="0 0 128 128" id="significantly_worse">
+ <circle r="60" cx="64" cy="64"/>
+ <circle r="4" cx="44" cy="44"/>
+ <circle r="4" cx="84" cy="44"/>
+ <path d="M 36 96 Q 64 48 92 96"/>
+ </svg>
+ </span>
+
+ <svg viewbox="0 0 128 128" id="warning">
+ <path d="M 64 0 L 128 128 L 0 128 L 64 0"/>
+ <rect x="60" width="8" y="0" height="84"/>
+ <rect x="60" width="8" y="100" height="24"/>
+ </svg>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+Polymer({
+ is: 'tr-v-ui-scalar-span',
+
+ properties: {
+ /**
+ * String identifier for grouping scalar spans with common context (e.g.
+ * all scalar spans in a single table column would typically share a common
+ * context and, thus, have the same context group identifier). If falsy,
+ * the scalar span will NOT be associated with any context.
+ */
+ contextGroup: {
+ type: String,
+ reflectToAttribute: true,
+ observer: 'contextGroupChanged_'
+ }
+ },
+
+ created() {
+ this.value_ = undefined;
+ this.unit_ = undefined;
+
+ // TODO(petrcermak): Merge this into the context controller.
+ this.context_ = undefined;
+
+ this.warning_ = undefined;
+ this.significance_ = tr.b.math.Statistics.Significance.DONT_CARE;
+
+ // To avoid unnecessary DOM traversal, search for the context controller
+ // only when necessary (when the span is attached and has a context group).
+ this.shouldSearchForContextController_ = false;
+ this.lazyContextController_ = undefined;
+ this.onContextUpdated_ = this.onContextUpdated_.bind(this);
+ this.updateContents_ = this.updateContents_.bind(this);
+
+ // The span can specify a custom context range, which will override the
+ // values from the context controller.
+ this.customContextRange_ = undefined;
+ },
+
+ get significance() {
+ return this.significance_;
+ },
+
+ set significance(s) {
+ this.significance_ = s;
+ this.updateContents_();
+ },
+
+ set contentTextDecoration(deco) {
+ this.$.content.style.textDecoration = deco;
+ },
+
+ get value() {
+ return this.value_;
+ },
+
+ set value(value) {
+ if (value instanceof tr.b.Scalar) {
+ this.value_ = value.value;
+ this.unit_ = value.unit;
+ } else {
+ this.value_ = value;
+ }
+ this.updateContents_();
+ if (this.hasContext_(this.contextGroup)) {
+ this.contextController_.onScalarSpanUpdated(this.contextGroup, this);
+ } else {
+ this.updateSparkline_();
+ }
+ },
+
+ get contextController_() {
+ if (this.shouldSearchForContextController_) {
+ this.lazyContextController_ =
+ tr.v.ui.getScalarContextControllerForElement(this);
+ this.shouldSearchForContextController_ = false;
+ }
+ return this.lazyContextController_;
+ },
+
+ hasContext_(contextGroup) {
+ // The ordering here is important. It ensures that we avoid a DOM traversal
+ // when the span doesn't have a context group.
+ return !!(contextGroup && this.contextController_);
+ },
+
+ contextGroupChanged_(newContextGroup, oldContextGroup) {
+ this.detachFromContextControllerIfPossible_(oldContextGroup);
+ if (!this.attachToContextControllerIfPossible_(newContextGroup)) {
+ // If the span failed to attach to a controller, it won't receive a
+ // context-updated event, so we trigger it manually.
+ this.onContextUpdated_();
+ }
+ },
+
+ attachToContextControllerIfPossible_(contextGroup) {
+ if (!this.hasContext_(contextGroup)) return false;
+
+ this.contextController_.addEventListener(
+ 'context-updated', this.onContextUpdated_);
+ this.contextController_.onScalarSpanAdded(contextGroup, this);
+ return true;
+ },
+
+ detachFromContextControllerIfPossible_(contextGroup) {
+ if (!this.hasContext_(contextGroup)) return;
+
+ this.contextController_.removeEventListener(
+ 'context-updated', this.onContextUpdated_);
+ this.contextController_.onScalarSpanRemoved(contextGroup, this);
+ },
+
+ attached() {
+ tr.b.Unit.addEventListener(
+ 'display-mode-changed', this.updateContents_);
+ this.shouldSearchForContextController_ = true;
+ this.attachToContextControllerIfPossible_(this.contextGroup);
+ },
+
+ detached() {
+ tr.b.Unit.removeEventListener(
+ 'display-mode-changed', this.updateContents_);
+ this.detachFromContextControllerIfPossible_(this.contextGroup);
+ this.shouldSearchForContextController_ = false;
+ this.lazyContextController_ = undefined;
+ },
+
+ onContextUpdated_() {
+ this.updateSparkline_();
+ },
+
+ get context() {
+ return this.context_;
+ },
+
+ set context(context) {
+ this.context_ = context;
+ this.updateContents_();
+ },
+
+ get unit() {
+ return this.unit_;
+ },
+
+ set unit(unit) {
+ this.unit_ = unit;
+ this.updateContents_();
+ this.updateSparkline_();
+ },
+
+ setValueAndUnit(value, unit) {
+ this.value_ = value;
+ this.unit_ = unit;
+ this.updateContents_();
+ },
+
+ get customContextRange() {
+ return this.customContextRange_;
+ },
+
+ set customContextRange(customContextRange) {
+ this.customContextRange_ = customContextRange;
+ this.updateSparkline_();
+ },
+
+ get inline() {
+ return Polymer.dom(this).classList.contains('inline');
+ },
+
+ set inline(inline) {
+ if (inline) {
+ Polymer.dom(this).classList.add('inline');
+ } else {
+ Polymer.dom(this).classList.remove('inline');
+ }
+ },
+
+ get leftAlign() {
+ return Polymer.dom(this).classList.contains('left-align');
+ },
+
+ set leftAlign(leftAlign) {
+ if (leftAlign) {
+ Polymer.dom(this).classList.add('left-align');
+ } else {
+ Polymer.dom(this).classList.remove('left-align');
+ }
+ },
+
+ updateSparkline_() {
+ Polymer.dom(this.$.sparkline).classList.remove('positive');
+ Polymer.dom(this.$.sparkline).classList.remove('better');
+ Polymer.dom(this.$.sparkline).classList.remove('worse');
+ Polymer.dom(this.$.sparkline).classList.remove('same');
+ this.$.sparkline.style.display = 'none';
+ this.$.sparkline.style.left = '0';
+ this.$.sparkline.style.width = '0';
+
+ // Custom context range takes precedence over controller context range.
+ let range = this.customContextRange_;
+ if (!range && this.hasContext_(this.contextGroup)) {
+ const context = this.contextController_.getContext(this.contextGroup);
+ if (context) {
+ range = context.range;
+ }
+ }
+ if (!range || range.isEmpty) return;
+
+ const leftPoint = Math.min(range.min, 0);
+ const rightPoint = Math.max(range.max, 0);
+ const pointDistance = rightPoint - leftPoint;
+ if (pointDistance === 0) {
+ // This can happen, for example, when all spans within the context have
+ // zero values (so |range| is [0, 0]).
+ return;
+ }
+
+ // Draw the sparkline.
+ this.$.sparkline.style.display = 'block';
+ let left;
+ let width;
+ if (this.value > 0) {
+ width = Math.min(this.value, rightPoint);
+ left = -leftPoint;
+ Polymer.dom(this.$.sparkline).classList.add('positive');
+ } else if (this.value <= 0) {
+ width = -Math.max(this.value, leftPoint);
+ left = (-leftPoint) - width;
+ }
+ this.$.sparkline.style.left = this.buildSparklineStyle_(
+ left / pointDistance, false);
+ this.$.sparkline.style.width = this.buildSparklineStyle_(
+ width / pointDistance, true);
+
+ // Set the sparkline color (if applicable).
+ const changeClass = this.changeClassName_;
+ if (changeClass) {
+ Polymer.dom(this.$.sparkline).classList.add(changeClass);
+ }
+ },
+
+ buildSparklineStyle_(ratio, isWidth) {
+ // To avoid visual glitches around the zero value bar, we subtract 1 pixel
+ // from the width of the element and multiply the remainder (100% - 1px) by
+ // |ratio|. The extra pixel is used for the sparkline border. This allows
+ // us to align zero sparklines with both positive and negative values:
+ //
+ // ::::::::::| +10 MiB
+ // :::::| +5 MiB
+ // | 0 MiB
+ // |::::: -5 MiB
+ // |:::::::::: -10 MiB
+ //
+ let position = 'calc(' + ratio + ' * (100% - 1px)';
+ if (isWidth) {
+ position += ' + 1px'; // Extra pixel for sparkline border.
+ }
+ position += ')';
+ return position;
+ },
+
+ updateContents_() {
+ Polymer.dom(this.$.content).textContent = '';
+ Polymer.dom(this.$.content).classList.remove('better');
+ Polymer.dom(this.$.content).classList.remove('worse');
+ Polymer.dom(this.$.content).classList.remove('same');
+ this.$.insignificant.style.display = '';
+ this.$.significantly_better.style.display = '';
+ this.$.significantly_worse.style.display = '';
+
+ if (this.unit_ === undefined) return;
+
+ this.$.content.title = '';
+ Polymer.dom(this.$.content).textContent =
+ this.unit_.format(this.value, this.context);
+ this.updateDelta_();
+ },
+
+ updateDelta_() {
+ let changeClass = this.changeClassName_;
+ if (!changeClass) {
+ this.$.significance.style.display = 'none';
+ return; // Not a delta or we don't care.
+ }
+
+ this.$.significance.style.display = 'inline';
+
+ let title;
+ switch (changeClass) {
+ case 'better':
+ title = 'improvement';
+ break;
+
+ case 'worse':
+ title = 'regression';
+ break;
+
+ case 'same':
+ title = 'no change';
+ break;
+
+ default:
+ throw new Error('Unknown change class: ' + changeClass);
+ }
+
+ // Set the content class separately from the significance class so that
+ // the Neutral face is always a neutral color.
+ Polymer.dom(this.$.content).classList.add(changeClass);
+
+ switch (this.significance) {
+ case tr.b.math.Statistics.Significance.DONT_CARE:
+ break;
+
+ case tr.b.math.Statistics.Significance.INSIGNIFICANT:
+ if (changeClass !== 'same') title = 'insignificant ' + title;
+ this.$.insignificant.style.display = 'inline';
+ changeClass = 'same';
+ break;
+
+ case tr.b.math.Statistics.Significance.SIGNIFICANT:
+ if (changeClass === 'same') {
+ throw new Error('How can no change be significant?');
+ }
+ this.$['significantly_' + changeClass].style.display = 'inline';
+ title = 'significant ' + title;
+ break;
+
+ default:
+ throw new Error('Unknown significance ' + this.significance);
+ }
+
+ this.$.significance.title = title;
+ this.$.content.title = title;
+ },
+
+ get changeClassName_() {
+ if (!this.unit_ || !this.unit_.isDelta) return undefined;
+
+ switch (this.unit_.improvementDirection) {
+ case tr.b.ImprovementDirection.DONT_CARE:
+ return undefined;
+
+ case tr.b.ImprovementDirection.BIGGER_IS_BETTER:
+ if (this.value === 0) return 'same';
+ return this.value > 0 ? 'better' : 'worse';
+
+ case tr.b.ImprovementDirection.SMALLER_IS_BETTER:
+ if (this.value === 0) return 'same';
+ return this.value < 0 ? 'better' : 'worse';
+
+ default:
+ throw new Error('Unknown improvement direction: ' +
+ this.unit_.improvementDirection);
+ }
+ },
+
+ get warning() {
+ return this.warning_;
+ },
+
+ set warning(warning) {
+ this.warning_ = warning;
+ const warningEl = this.$.warning;
+ if (this.warning_) {
+ warningEl.title = warning;
+ warningEl.style.display = 'inline';
+ } else {
+ warningEl.title = '';
+ warningEl.style.display = '';
+ }
+ },
+
+ // tr-v-ui-time-stamp-span property
+ get timestamp() {
+ return this.value;
+ },
+
+ set timestamp(timestamp) {
+ if (timestamp instanceof tr.b.u.TimeStamp) {
+ this.value = timestamp;
+ return;
+ }
+ this.setValueAndUnit(timestamp, tr.b.u.Units.timeStampInMs);
+ },
+
+ // tr-v-ui-time-duration-span property
+ get duration() {
+ return this.value;
+ },
+
+ set duration(duration) {
+ if (duration instanceof tr.b.u.TimeDuration) {
+ this.value = duration;
+ return;
+ }
+ this.setValueAndUnit(duration, tr.b.u.Units.timeDurationInMs);
+ }
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html
new file mode 100644
index 00000000000..56ca6917d71
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/scalar_span_test.html
@@ -0,0 +1,1027 @@
+<!DOCTYPE html>
+<!--
+Copyright 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/raf.html">
+<link rel="import" href="/tracing/base/time_display_modes.html">
+<link rel="import" href="/tracing/base/unit.html">
+<link rel="import" href="/tracing/base/unit_scale.html">
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/ui/scalar_context_controller.html">
+<link rel="import" href="/tracing/value/ui/scalar_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ const Scalar = tr.b.Scalar;
+ const Unit = tr.b.Unit;
+ const THIS_DOC = document.currentScript.ownerDocument;
+
+ const EXAMPLE_MEMORY_FORMATTING_CONTEXT = {
+ unitPrefix: tr.b.UnitPrefixScale.BINARY.KIBI,
+ };
+ const EXAMPLE_MEMORY_NUMERIC = new Scalar(
+ Unit.byName.sizeInBytesDelta_smallerIsBetter, 256 * 1024 * 1024);
+
+ function checkSignificance(span, expectedSignificance) {
+ assert.strictEqual(span.$.insignificant.style.display,
+ expectedSignificance === 'insignificant' ? 'inline' : '');
+ assert.strictEqual(span.$.significantly_better.style.display,
+ expectedSignificance === 'significantly_better' ? 'inline' : '');
+ assert.strictEqual(span.$.significantly_worse.style.display,
+ expectedSignificance === 'significantly_worse' ? 'inline' : '');
+ }
+
+ function checkScalarSpan(test, value, unit, expectedContent, opt_options) {
+ const options = opt_options || {};
+ const span = tr.v.ui.createScalarSpan(new tr.b.Scalar(unit, value),
+ {significance: options.significance});
+
+ test.addHTMLOutput(span);
+ assert.strictEqual(
+ Polymer.dom(span.$.content).textContent, expectedContent);
+ assert.strictEqual(window.getComputedStyle(span.$.content).color,
+ options.expectedColor || 'rgb(0, 0, 0)');
+
+ if (options.expectedTitle) {
+ assert.strictEqual(span.$.content.title, options.expectedTitle);
+ }
+
+ if (options.significance !== undefined) {
+ checkSignificance(span, options.expectedEmoji);
+ if (options.expectedTitle) {
+ assert.strictEqual(span.$.significance.title, options.expectedTitle);
+ }
+ }
+ }
+
+ test('instantiate_significance', function() {
+ const countD = Unit.byName.count.correspondingDeltaUnit;
+ const countSIBD = Unit.byName.count_smallerIsBetter.correspondingDeltaUnit;
+ const countBIBD = Unit.byName.count_biggerIsBetter.correspondingDeltaUnit;
+
+ const zero = String.fromCharCode(177) + '0';
+
+ checkScalarSpan(this, 0, countSIBD, zero, {
+ significance: tr.b.math.Statistics.Significance.DONT_CARE,
+ expectedTitle: 'no change',
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, 0, countSIBD, zero, {
+ expectedEmoji: 'insignificant',
+ significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
+ expectedEmojiColor: 'rgb(0, 0, 0)',
+ expectedTitle: 'no change'
+ });
+
+ assert.throws(() => checkScalarSpan(this, 0, countSIBD, zero,
+ {significance: tr.b.math.Statistics.Significance.SIGNIFICANT}));
+
+ checkScalarSpan(this, 0, countBIBD, zero, {
+ significance: tr.b.math.Statistics.Significance.DONT_CARE,
+ expectedTitle: 'no change',
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, 0, countBIBD, zero, {
+ expectedEmoji: 'insignificant',
+ significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
+ expectedEmojiColor: 'rgb(0, 0, 0)',
+ expectedTitle: 'no change'
+ });
+
+ assert.throws(() => checkScalarSpan(this, 0, countSIBD, zero,
+ {significance: tr.b.math.Statistics.Significance.SIGNIFICANT}));
+
+ checkScalarSpan(this, 1, countSIBD, '+1', {
+ significance: tr.b.math.Statistics.Significance.DONT_CARE,
+ expectedColor: 'rgb(255, 0, 0)',
+ expectedTitle: 'regression',
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, 1, countSIBD, '+1', {
+ significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
+ expectedColor: 'rgb(255, 0, 0)',
+ expectedEmoji: 'insignificant',
+ expectedEmojiColor: 'rgb(0, 0, 0)',
+ expectedTitle: 'insignificant regression'
+ });
+
+ checkScalarSpan(this, 1, countSIBD, '+1', {
+ significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
+ expectedColor: 'rgb(255, 0, 0)',
+ expectedEmoji: 'significantly_worse',
+ expectedEmojiColor: 'rgb(255, 0, 0)',
+ expectedTitle: 'significant regression'
+ });
+
+ checkScalarSpan(this, 1, countBIBD, '+1', {
+ significance: tr.b.math.Statistics.Significance.DONT_CARE,
+ expectedColor: 'rgb(0, 128, 0)',
+ expectedTitle: 'improvement',
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, 1, countBIBD, '+1', {
+ significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
+ expectedColor: 'rgb(0, 128, 0)',
+ expectedEmoji: 'insignificant',
+ expectedEmojiColor: 'rgb(0, 0, 0)',
+ expectedTitle: 'insignificant improvement'
+ });
+
+ checkScalarSpan(this, 1, countBIBD, '+1', {
+ significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
+ expectedColor: 'rgb(0, 128, 0)',
+ expectedEmoji: 'significantly_better',
+ expectedEmojiColor: 'rgb(0, 128, 0)',
+ expectedTitle: 'significant improvement'
+ });
+
+ checkScalarSpan(this, -1, countSIBD, '-1', {
+ significance: tr.b.math.Statistics.Significance.DONT_CARE,
+ expectedColor: 'rgb(0, 128, 0)',
+ expectedEmoji: '',
+ expectedEmojiColor: '',
+ expectedTitle: 'improvement'
+ });
+
+ checkScalarSpan(this, -1, countSIBD, '-1', {
+ significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
+ expectedColor: 'rgb(0, 128, 0)',
+ expectedEmoji: 'insignificant',
+ expectedEmojiColor: 'rgb(0, 0, 0)',
+ expectedTitle: 'insignificant improvement'
+ });
+
+ checkScalarSpan(this, -1, countSIBD, '-1', {
+ significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
+ expectedColor: 'rgb(0, 128, 0)',
+ expectedEmoji: 'significantly_better',
+ expectedEmojiColor: 'rgb(0, 128, 0)',
+ expectedTitle: 'significant improvement'
+ });
+
+ checkScalarSpan(this, -1, countBIBD, '-1', {
+ expectedColor: 'rgb(255, 0, 0)',
+ significance: tr.b.math.Statistics.Significance.DONT_CARE,
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, -1, countBIBD, '-1', {
+ significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
+ expectedColor: 'rgb(255, 0, 0)',
+ expectedEmoji: 'insignificant',
+ expectedEmojiColor: 'rgb(0, 0, 0)',
+ expectedTitle: 'insignificant regression'
+ });
+
+ checkScalarSpan(this, -1, countBIBD, '-1', {
+ significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
+ expectedColor: 'rgb(255, 0, 0)',
+ expectedEmoji: 'significantly_worse',
+ expectedEmojiColor: 'rgb(255, 0, 0)',
+ expectedTitle: 'significant regression'
+ });
+
+ checkScalarSpan(this, 1, countD, '+1', {
+ expectedColor: 'rgb(0, 0, 0)',
+ significance: tr.b.math.Statistics.Significance.DONT_CARE,
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, 1, countD, '+1', {
+ expectedColor: 'rgb(0, 0, 0)',
+ significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, 1, countD, '+1', {
+ expectedColor: 'rgb(0, 0, 0)',
+ significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, -1, countD, '-1', {
+ expectedColor: 'rgb(0, 0, 0)',
+ significance: tr.b.math.Statistics.Significance.DONT_CARE,
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, -1, countD, '-1', {
+ expectedColor: 'rgb(0, 0, 0)',
+ significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
+ expectedEmoji: ''
+ });
+
+ checkScalarSpan(this, -1, countD, '-1', {
+ expectedColor: 'rgb(0, 0, 0)',
+ significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
+ expectedEmoji: ''
+ });
+ });
+
+ test('instantiate', function() {
+ checkScalarSpan(this, 123.456789, Unit.byName.timeDurationInMs,
+ '123.457 ms');
+ checkScalarSpan(this, 0, Unit.byName.normalizedPercentage, '0.0%');
+ checkScalarSpan(this, 1, Unit.byName.normalizedPercentage, '100.0%');
+ checkScalarSpan(this, -2560, Unit.byName.sizeInBytes, '-2.5 KiB');
+ });
+
+ test('instantiate_smallerIsBetter', function() {
+ checkScalarSpan(this, 45097156608, Unit.byName.sizeInBytes_smallerIsBetter,
+ '42.0 GiB');
+ checkScalarSpan(this, 0, Unit.byName.energyInJoules_smallerIsBetter,
+ '0.000 J');
+ checkScalarSpan(this, -0.25, Unit.byName.unitlessNumber_smallerIsBetter,
+ '-0.250');
+ });
+
+ test('instantiate_biggerIsBetter', function() {
+ checkScalarSpan(this, 0.07, Unit.byName.powerInWatts_smallerIsBetter,
+ '70.000 mW');
+ checkScalarSpan(this, 0, Unit.byName.timeStampInMs_biggerIsBetter,
+ '0.000 ms');
+ checkScalarSpan(this, -0.003,
+ Unit.byName.normalizedPercentage_biggerIsBetter, '-0.3%');
+ });
+
+ test('instantiate_delta', function() {
+ checkScalarSpan(this, 123.456789, Unit.byName.timeDurationInMsDelta,
+ '+123.457 ms');
+ checkScalarSpan(this, 0, Unit.byName.normalizedPercentageDelta,
+ '\u00B10.0%');
+ checkScalarSpan(this, -2560, Unit.byName.sizeInBytesDelta,
+ '-2.5 KiB');
+ });
+
+ test('instantiate_delta_smallerIsBetter', function() {
+ checkScalarSpan(this, 45097156608,
+ Unit.byName.sizeInBytesDelta_smallerIsBetter, '+42.0 GiB',
+ {expectedColor: 'rgb(255, 0, 0)'});
+ checkScalarSpan(this, 0, Unit.byName.energyInJoulesDelta_smallerIsBetter,
+ '\u00B10.000 J');
+ checkScalarSpan(this, -0.25,
+ Unit.byName.unitlessNumberDelta_smallerIsBetter, '-0.250',
+ {expectedColor: 'rgb(0, 128, 0)'});
+ });
+
+ test('instantiate_delta_biggerIsBetter', function() {
+ checkScalarSpan(this, 0.07, Unit.byName.powerInWattsDelta_biggerIsBetter,
+ '+70.000 mW', {expectedColor: 'rgb(0, 128, 0)'});
+ checkScalarSpan(this, 0, Unit.byName.timeStampInMsDelta_biggerIsBetter,
+ '\u00B10.000 ms');
+ checkScalarSpan(this, -0.003,
+ Unit.byName.normalizedPercentageDelta_biggerIsBetter, '-0.3%',
+ {expectedColor: 'rgb(255, 0, 0)'});
+ });
+
+ test('createScalarSpan', function() {
+ // No config.
+ let span = tr.v.ui.createScalarSpan(
+ new Scalar(Unit.byName.powerInWatts, 3.14));
+ assert.strictEqual(Polymer.dom(span.$.content).textContent, '3.140 W');
+ assert.strictEqual(span.ownerDocument, document);
+ assert.strictEqual(span.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(span.value, 3.14);
+ assert.strictEqual(span.unit, Unit.byName.powerInWatts);
+ assert.isUndefined(span.context);
+ assert.isUndefined(span.customContextRange);
+ assert.isUndefined(span.warning);
+ assert.isFalse(span.leftAlign);
+ this.addHTMLOutput(span);
+
+ // Inline.
+ const div = document.createElement('div');
+ this.addHTMLOutput(div);
+ const inlineSpan = tr.v.ui.createScalarSpan(
+ new Scalar(Unit.byName.powerInWatts, 3.14),
+ {inline: true});
+ assert.strictEqual(Polymer.dom(inlineSpan.$.content).textContent,
+ '3.140 W');
+ assert.strictEqual(inlineSpan.ownerDocument, document);
+ assert.strictEqual(inlineSpan.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(inlineSpan.value, 3.14);
+ assert.strictEqual(inlineSpan.unit, Unit.byName.powerInWatts);
+ assert.isUndefined(inlineSpan.context);
+ assert.isUndefined(inlineSpan.customContextRange);
+ assert.isUndefined(inlineSpan.warning);
+ assert.isFalse(inlineSpan.leftAlign);
+ div.appendChild(document.createTextNode('prefix '));
+ div.appendChild(inlineSpan);
+ div.appendChild(document.createTextNode(' suffix'));
+ assert.isBelow(inlineSpan.getBoundingClientRect().width,
+ span.getBoundingClientRect().width);
+
+ // Custom owner document and right align.
+ span = tr.v.ui.createScalarSpan(
+ new Scalar(Unit.byName.energyInJoules, 2.72),
+ { ownerDocument: THIS_DOC, leftAlign: true});
+ assert.strictEqual(Polymer.dom(span.$.content).textContent, '2.720 J');
+ assert.strictEqual(span.ownerDocument, THIS_DOC);
+ assert.strictEqual(span.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(span.value, 2.72);
+ assert.strictEqual(span.unit, Unit.byName.energyInJoules);
+ assert.isUndefined(span.context);
+ assert.isUndefined(span.customContextRange);
+ assert.isUndefined(span.warning);
+ assert.isTrue(span.leftAlign);
+ this.addHTMLOutput(span);
+
+ // Unit and sparkline set via config.
+ span = tr.v.ui.createScalarSpan(1.62, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: tr.b.math.Range.fromExplicitRange(0, 3.24)
+ });
+ assert.strictEqual(Polymer.dom(span.$.content).textContent, '1.620 ms');
+ assert.strictEqual(span.ownerDocument, document);
+ assert.strictEqual(span.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(span.value, 1.62);
+ assert.strictEqual(span.unit, Unit.byName.timeStampInMs);
+ assert.isUndefined(span.context);
+ assert.isTrue(tr.b.math.Range.fromExplicitRange(0, 3.24).equals(
+ span.customContextRange));
+ assert.isUndefined(span.warning);
+ assert.isFalse(span.leftAlign);
+ this.addHTMLOutput(span);
+
+ // Custom context.
+ span = tr.v.ui.createScalarSpan(
+ new Scalar(Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ 256 * 1024 * 1024), { context: {
+ unitPrefix: tr.b.UnitPrefixScale.BINARY.KIBI,
+ minimumFractionDigits: 2
+ } });
+ assert.strictEqual(
+ Polymer.dom(span.$.content).textContent, '+262,144.00 KiB');
+ assert.strictEqual(span.ownerDocument, document);
+ assert.strictEqual(span.tagName, 'TR-V-UI-SCALAR-SPAN');
+ assert.strictEqual(span.value, 256 * 1024 * 1024);
+ assert.strictEqual(span.unit, Unit.byName.sizeInBytesDelta_smallerIsBetter);
+ assert.deepEqual(span.context, {
+ unitPrefix: tr.b.UnitPrefixScale.BINARY.KIBI,
+ minimumFractionDigits: 2
+ });
+ assert.isUndefined(span.customContextRange);
+ assert.isUndefined(span.warning);
+ assert.isFalse(span.leftAlign);
+ this.addHTMLOutput(span);
+ });
+
+ test('instantiate_withWarning', function() {
+ const span = document.createElement('tr-v-ui-scalar-span');
+ span.value = 400000000;
+ span.unit = Unit.byName.sizeInBytes;
+ span.warning = 'There is a problem with this size';
+ this.addHTMLOutput(span);
+ });
+
+ test('instantiate_withCustomContextRange', function() {
+ const span = document.createElement('tr-v-ui-scalar-span');
+ span.value = new Scalar(Unit.byName.unitlessNumber, 0.99);
+ span.customContextRange = tr.b.math.Range.fromExplicitRange(0, 3);
+ this.addHTMLOutput(span);
+ });
+
+ test('instantiate_withRightAlign', function() {
+ const span = document.createElement('tr-v-ui-scalar-span');
+ span.value = new Scalar(Unit.byName.timeStampInMs, 5.777);
+ span.leftAlign = true;
+ this.addHTMLOutput(span);
+ });
+
+ test('instantiate_withContext', function() {
+ const span = document.createElement('tr-v-ui-scalar-span');
+ span.value = new Scalar(
+ Unit.byName.unitlessNumberDelta_smallerIsBetter, 42);
+ span.context = { maximumFractionDigits: 2 };
+ assert.strictEqual(Polymer.dom(span.$.content).textContent, '+42.00');
+ this.addHTMLOutput(span);
+ });
+
+ test('deltaAndNonDeltaHaveSimilarHeights', function() {
+ const spanA = document.createElement('tr-v-ui-scalar-span');
+ spanA.setValueAndUnit(400, Unit.byName.timeDurationInMs);
+ checkSignificance(spanA, '');
+
+ const spanB = document.createElement('tr-v-ui-scalar-span');
+ spanB.setValueAndUnit(400, Unit.byName.timeDurationInMsDelta);
+ checkSignificance(spanB, '');
+
+ const spanC = document.createElement('tr-v-ui-scalar-span');
+ spanC.setValueAndUnit(
+ 400, Unit.byName.timeDurationInMsDelta_smallerIsBetter);
+ spanC.significance = tr.b.math.Statistics.Significance.SIGNIFICANT;
+ checkSignificance(spanC, 'significantly_worse');
+
+ const spanD = document.createElement('tr-v-ui-scalar-span');
+ spanD.setValueAndUnit(
+ 400, Unit.byName.timeDurationInMsDelta_biggerIsBetter);
+ spanD.significance = tr.b.math.Statistics.Significance.SIGNIFICANT;
+ checkSignificance(spanD, 'significantly_better');
+
+ const spanE = document.createElement('tr-v-ui-scalar-span');
+ spanE.setValueAndUnit(
+ 400, Unit.byName.timeDurationInMsDelta_smallerIsBetter);
+ spanE.significance = tr.b.math.Statistics.Significance.INSIGNIFICANT;
+ checkSignificance(spanE, 'insignificant');
+
+ const overall = document.createElement('div');
+ overall.style.display = 'flex';
+ // These spans must be on separate lines so that Chrome has the option of
+ // making their heights different. The point of the test is that Chrome
+ // shouldn't have to make their heights different even when it could.
+ overall.style.flexDirection = 'column';
+ Polymer.dom(overall).appendChild(spanA);
+ Polymer.dom(overall).appendChild(spanB);
+ Polymer.dom(overall).appendChild(spanC);
+ Polymer.dom(overall).appendChild(spanD);
+ Polymer.dom(overall).appendChild(spanE);
+ this.addHTMLOutput(overall);
+
+ const expectedHeight = spanA.getBoundingClientRect().height;
+ assert.strictEqual(expectedHeight, spanB.getBoundingClientRect().height);
+ assert.strictEqual(expectedHeight, spanC.getBoundingClientRect().height);
+ assert.strictEqual(expectedHeight, spanD.getBoundingClientRect().height);
+ assert.strictEqual(expectedHeight, spanE.getBoundingClientRect().height);
+ });
+
+ test('warningAndNonWarningHaveSimilarHeights', function() {
+ const spanA = document.createElement('tr-v-ui-scalar-span');
+ spanA.setValueAndUnit(400, Unit.byName.timeDurationInMs);
+
+ const spanB = document.createElement('tr-v-ui-scalar-span');
+ spanB.setValueAndUnit(400, Unit.byName.timeDurationInMs);
+ spanB.warning = 'There is a problem with this time';
+
+ const overall = document.createElement('div');
+ overall.style.display = 'flex';
+ // These spans must be on separate lines so that Chrome has the option of
+ // making their heights different. The point of the test is that Chrome
+ // shouldn't have to make their heights different even when it could.
+ overall.style.flexDirection = 'column';
+ Polymer.dom(overall).appendChild(spanA);
+ Polymer.dom(overall).appendChild(spanB);
+ this.addHTMLOutput(overall);
+
+ const rectA = spanA.getBoundingClientRect();
+ const rectB = spanB.getBoundingClientRect();
+ assert.strictEqual(rectA.height, rectB.height);
+ });
+
+ test('respectCurrentDisplayUnit', function() {
+ try {
+ Unit.currentTimeDisplayMode = tr.b.TimeDisplayModes.ns;
+
+ const span = document.createElement('tr-v-ui-scalar-span');
+ span.setValueAndUnit(73, Unit.byName.timeStampInMs);
+ this.addHTMLOutput(span);
+
+ assert.isTrue(Polymer.dom(span.$.content).textContent.indexOf('ns') > 0);
+ Unit.currentTimeDisplayMode = tr.b.TimeDisplayModes.ms;
+ assert.isTrue(Polymer.dom(span.$.content).textContent.indexOf('ms') > 0);
+ } finally {
+ Unit.reset();
+ }
+ });
+
+ function checkSparkline(span, expectation) {
+ tr.b.forceAllPendingTasksToRunForTest();
+ const sparklineEl = span.$.sparkline;
+ const computedStyle = getComputedStyle(sparklineEl);
+
+ const expectedDisplay = expectation.display || 'block';
+ assert.strictEqual(computedStyle.display, expectedDisplay);
+ if (expectedDisplay === 'none') {
+ // Test expectation sanity check.
+ assert.notProperty(expectation, 'left');
+ assert.notProperty(expectation, 'width');
+ assert.notProperty(expectation, 'classList');
+ return;
+ }
+
+ assert.closeTo(parseFloat(computedStyle.left), expectation.left, 0.1);
+ assert.closeTo(parseFloat(computedStyle.width), expectation.width, 0.1);
+ assert.sameMembers(Array.from(sparklineEl.classList),
+ expectation.classList || []);
+ }
+
+ test('customContextRange', function() {
+ const div = document.createElement('div');
+ div.style.width = '101px'; // One extra pixel for sparkline border.
+ this.addHTMLOutput(div);
+
+ // No custom context range.
+ const span1 = tr.v.ui.createScalarSpan(0, {
+ unit: Unit.byName.timeStampInMs
+ });
+ Polymer.dom(div).appendChild(span1);
+ checkSparkline(span1, {display: 'none'});
+ const span2 = tr.v.ui.createScalarSpan(0, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: undefined
+ });
+ Polymer.dom(div).appendChild(span2);
+ checkSparkline(span2, {display: 'none'});
+ const span3 = tr.v.ui.createScalarSpan(0, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: new tr.b.math.Range() // Empty range.
+ });
+ Polymer.dom(div).appendChild(span3);
+ checkSparkline(span3, {display: 'none'});
+
+ const range = tr.b.math.Range.fromExplicitRange(-15, 15);
+
+ // Values inside custom context range.
+ const span4 = tr.v.ui.createScalarSpan(-15, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span4);
+ checkSparkline(span4, {left: 0, width: 51});
+ const span5 = tr.v.ui.createScalarSpan(-14, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span5);
+ checkSparkline(span5, {left: 3.33, width: 47.67});
+ const span6 = tr.v.ui.createScalarSpan(-10, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span6);
+ checkSparkline(span6, {left: 16.67, width: 34.33});
+ const span7 = tr.v.ui.createScalarSpan(0, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span7);
+ checkSparkline(span7, {left: 50, width: 1});
+ const span8 = tr.v.ui.createScalarSpan(10, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span8);
+ checkSparkline(span8, {left: 50, width: 34.33, classList: ['positive']});
+ const span9 = tr.v.ui.createScalarSpan(14, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span9);
+ checkSparkline(span9, {left: 50, width: 47.67, classList: ['positive']});
+ const span10 = tr.v.ui.createScalarSpan(15, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span10);
+ checkSparkline(span10, {left: 50, width: 51, classList: ['positive']});
+
+ // Values outside custom context range.
+ const span11 = tr.v.ui.createScalarSpan(-20, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span11);
+ checkSparkline(span11, {left: 0, width: 51});
+ const span12 = tr.v.ui.createScalarSpan(20, {
+ unit: Unit.byName.timeStampInMs,
+ customContextRange: range
+ });
+ Polymer.dom(div).appendChild(span12);
+ checkSparkline(span12, {left: 50, width: 51, classList: ['positive']});
+ });
+
+ test('emptyNumeric', function() {
+ assert.strictEqual(tr.v.ui.createScalarSpan(), '');
+ });
+
+ test('contextControllerChanges', function() {
+ const div = document.createElement('div');
+ div.style.width = '101px'; // One extra pixel for sparkline border.
+ this.addHTMLOutput(div);
+
+ div.appendChild(
+ document.createElement('tr-v-ui-scalar-context-controller'));
+
+ const s1 = tr.v.ui.createScalarSpan(10, {
+ unit: Unit.byName.powerInWatts
+ });
+ Polymer.dom(div).appendChild(s1);
+ checkSparkline(s1, {display: 'none'});
+
+ const s2 = tr.v.ui.createScalarSpan(20, {
+ unit: Unit.byName.powerInWatts,
+ contextGroup: 'A'
+ });
+ Polymer.dom(div).appendChild(s2);
+ checkSparkline(s1, {display: 'none'});
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+
+ const s3 = tr.v.ui.createScalarSpan(30, {
+ unit: Unit.byName.powerInWatts,
+ contextGroup: 'A'
+ });
+ Polymer.dom(div).appendChild(s3);
+ checkSparkline(s1, {display: 'none'});
+ checkSparkline(s2, {left: 0, width: 67.67, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+
+ const s4 = tr.v.ui.createScalarSpan(40, {
+ unit: Unit.byName.powerInWatts,
+ contextGroup: 'B'
+ });
+ Polymer.dom(div).appendChild(s4);
+ checkSparkline(s1, {display: 'none'});
+ checkSparkline(s2, {left: 0, width: 67.67, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s4, {left: 0, width: 101, classList: ['positive']});
+
+ s3.contextGroup = 'B';
+ checkSparkline(s1, {display: 'none'});
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 76, classList: ['positive']});
+ checkSparkline(s4, {left: 0, width: 101, classList: ['positive']});
+
+ s1.setAttribute('context-group', 'A');
+ checkSparkline(s1, {left: 0, width: 51, classList: ['positive']});
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 76, classList: ['positive']});
+ checkSparkline(s4, {left: 0, width: 101, classList: ['positive']});
+
+ s1.value = 50;
+ checkSparkline(s1, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s2, {left: 0, width: 41, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 76, classList: ['positive']});
+ checkSparkline(s4, {left: 0, width: 101, classList: ['positive']});
+
+ s1.customContextRange = tr.b.math.Range.fromExplicitRange(0, 150);
+ checkSparkline(s1, {left: 0, width: 34.33, classList: ['positive']});
+ checkSparkline(s2, {left: 0, width: 41, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 76, classList: ['positive']});
+ checkSparkline(s4, {left: 0, width: 101, classList: ['positive']});
+
+ s4.contextGroup = null;
+ checkSparkline(s1, {left: 0, width: 34.33, classList: ['positive']});
+ checkSparkline(s2, {left: 0, width: 41, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s4, {display: 'none'});
+
+ s1.customContextRange = undefined;
+ checkSparkline(s1, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s2, {left: 0, width: 41, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s4, {display: 'none'});
+
+ s4.value = 0;
+ checkSparkline(s1, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s2, {left: 0, width: 41, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s4, {display: 'none'});
+
+ div.removeChild(s1);
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s4, {display: 'none'});
+
+ s1.contextGroup = 'B';
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s4, {display: 'none'});
+
+ div.appendChild(s1);
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 61, classList: ['positive']});
+ checkSparkline(s4, {display: 'none'});
+ checkSparkline(s1, {left: 0, width: 101, classList: ['positive']});
+
+ s1.removeAttribute('context-group');
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s4, {display: 'none'});
+ checkSparkline(s1, {display: 'none'});
+
+ s1.customContextRange = tr.b.math.Range.fromExplicitRange(0, 100);
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s4, {display: 'none'});
+ checkSparkline(s1, {left: 0, width: 51, classList: ['positive']});
+
+ s3.value = 0;
+ checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(s3, {display: 'none'});
+ checkSparkline(s4, {display: 'none'});
+ checkSparkline(s1, {left: 0, width: 51, classList: ['positive']});
+ });
+
+ test('deltaSparkline_noImprovementDirection', function() {
+ const div = document.createElement('div');
+ div.style.width = '101px'; // One extra pixel for sparkline border.
+ this.addHTMLOutput(div);
+ div.appendChild(
+ document.createElement('tr-v-ui-scalar-context-controller'));
+
+ const span1 = tr.v.ui.createScalarSpan(20971520, {
+ unit: Unit.byName.sizeInBytesDelta,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span1);
+ const span2 = tr.v.ui.createScalarSpan(15728640, {
+ unit: Unit.byName.sizeInBytesDelta,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span2);
+ const span3 = tr.v.ui.createScalarSpan(12582912, {
+ unit: Unit.byName.sizeInBytesDelta,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span3);
+ const span4 = tr.v.ui.createScalarSpan(11534336, {
+ unit: Unit.byName.sizeInBytesDelta,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span4);
+ const span5 = tr.v.ui.createScalarSpan(10485760, {
+ unit: Unit.byName.sizeInBytesDelta,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span5);
+ const span6 = tr.v.ui.createScalarSpan(9437184, {
+ unit: Unit.byName.sizeInBytesDelta,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span6);
+ const span7 = tr.v.ui.createScalarSpan(8388608, {
+ unit: Unit.byName.sizeInBytesDelta,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span7);
+ const span8 = tr.v.ui.createScalarSpan(5242880, {
+ unit: Unit.byName.sizeInBytesDelta,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span8);
+
+ // We must check the sparklines *after* all spans are appended because new
+ // values can change the context range.
+ checkSparkline(span1, {left: 0, width: 101, classList: ['positive']});
+ checkSparkline(span2, {left: 0, width: 76, classList: ['positive']});
+ checkSparkline(span3, {left: 0, width: 61, classList: ['positive']});
+ checkSparkline(span4, {left: 0, width: 56, classList: ['positive']});
+ checkSparkline(span5, {left: 0, width: 51, classList: ['positive']});
+ checkSparkline(span6, {left: 0, width: 46, classList: ['positive']});
+ checkSparkline(span7, {left: 0, width: 41, classList: ['positive']});
+ checkSparkline(span8, {left: 0, width: 26, classList: ['positive']});
+ });
+
+ test('deltaSparkline_smallerIsBetter', function() {
+ const div = document.createElement('div');
+ div.style.width = '101px'; // One extra pixel for sparkline border.
+ this.addHTMLOutput(div);
+ div.appendChild(
+ document.createElement('tr-v-ui-scalar-context-controller'));
+
+ const span1 = tr.v.ui.createScalarSpan(5242880, {
+ unit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span1);
+ const span2 = tr.v.ui.createScalarSpan(0, {
+ unit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span2);
+ const span3 = tr.v.ui.createScalarSpan(-3145728, {
+ unit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span3);
+ const span4 = tr.v.ui.createScalarSpan(-4194304, {
+ unit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span4);
+ const span5 = tr.v.ui.createScalarSpan(-5242880, {
+ unit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span5);
+ const span6 = tr.v.ui.createScalarSpan(-6291456, {
+ unit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span6);
+ const span7 = tr.v.ui.createScalarSpan(-7340032, {
+ unit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span7);
+ const span8 = tr.v.ui.createScalarSpan(-15728640, {
+ unit: Unit.byName.sizeInBytesDelta_smallerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span8);
+
+ // We must check the sparklines *after* all spans are appended because new
+ // values can change the context range.
+ checkSparkline(span1,
+ {left: 75, width: 26, classList: ['positive', 'worse']});
+ checkSparkline(span2, {left: 75, width: 1, classList: ['same']});
+ checkSparkline(span3, {left: 60, width: 16, classList: ['better']});
+ checkSparkline(span4, {left: 55, width: 21, classList: ['better']});
+ checkSparkline(span5, {left: 50, width: 26, classList: ['better']});
+ checkSparkline(span6, {left: 45, width: 31, classList: ['better']});
+ checkSparkline(span7, {left: 40, width: 36, classList: ['better']});
+ checkSparkline(span8, {left: 0, width: 76, classList: ['better']});
+ });
+
+ test('deltaSparkline_biggerIsBetter', function() {
+ const div = document.createElement('div');
+ div.style.width = '101px'; // One extra pixel for sparkline border.
+ this.addHTMLOutput(div);
+ div.appendChild(
+ document.createElement('tr-v-ui-scalar-context-controller'));
+
+ const span1 = tr.v.ui.createScalarSpan(0, {
+ unit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span1);
+ const span2 = tr.v.ui.createScalarSpan(-5242880, {
+ unit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span2);
+ const span3 = tr.v.ui.createScalarSpan(-8388608, {
+ unit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span3);
+ const span4 = tr.v.ui.createScalarSpan(-9437184, {
+ unit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span4);
+ const span5 = tr.v.ui.createScalarSpan(-10485760, {
+ unit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span5);
+ const span6 = tr.v.ui.createScalarSpan(-11534336, {
+ unit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span6);
+ const span7 = tr.v.ui.createScalarSpan(-12582912, {
+ unit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span7);
+ const span8 = tr.v.ui.createScalarSpan(-20971520, {
+ unit: Unit.byName.sizeInBytesDelta_biggerIsBetter,
+ contextGroup: 'test'
+ });
+ Polymer.dom(div).appendChild(span8);
+
+ // We must check the sparklines *after* all spans are appended because new
+ // values can change the context range.
+ checkSparkline(span1, {left: 100, width: 1, classList: ['same']});
+ checkSparkline(span2, {left: 75, width: 26, classList: ['worse']});
+ checkSparkline(span3, {left: 60, width: 41, classList: ['worse']});
+ checkSparkline(span4, {left: 55, width: 46, classList: ['worse']});
+ checkSparkline(span5, {left: 50, width: 51, classList: ['worse']});
+ checkSparkline(span6, {left: 45, width: 56, classList: ['worse']});
+ checkSparkline(span7, {left: 40, width: 61, classList: ['worse']});
+ checkSparkline(span8, {left: 0, width: 101, classList: ['worse']});
+ });
+
+ test('classListChanges', function() {
+ const div = document.createElement('div');
+ div.style.width = '200px';
+ this.addHTMLOutput(div);
+
+ const span = tr.v.ui.createScalarSpan(10, {
+ unit: Unit.byName.energyInJoulesDelta_smallerIsBetter,
+ significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
+ customContextRange: tr.b.math.Range.fromExplicitRange(-20, 20)
+ });
+ Polymer.dom(div).appendChild(span);
+
+ assert.sameMembers(Array.from(span.$.content.classList), ['worse']);
+ checkSignificance(span, 'significantly_worse');
+
+ span.significance = tr.b.math.Statistics.Significance.DONT_CARE;
+ assert.sameMembers(Array.from(span.$.sparkline.classList),
+ ['positive', 'worse']);
+ assert.sameMembers(Array.from(span.$.content.classList), ['worse']);
+ checkSignificance(span, '');
+
+ span.value = -5;
+ assert.sameMembers(Array.from(span.$.sparkline.classList), ['better']);
+ assert.sameMembers(Array.from(span.$.content.classList), ['better']);
+ checkSignificance(span, '');
+
+ span.unit = Unit.byName.energyInJoules;
+ assert.sameMembers(Array.from(span.$.sparkline.classList), []);
+ assert.sameMembers(Array.from(span.$.content.classList), []);
+ checkSignificance(span, '');
+
+ span.value = 20;
+ assert.sameMembers(Array.from(span.$.sparkline.classList), ['positive']);
+ assert.sameMembers(Array.from(span.$.content.classList), []);
+ checkSignificance(span, '');
+
+ span.unit = Unit.byName.energyInJoulesDelta_biggerIsBetter;
+ assert.sameMembers(Array.from(span.$.sparkline.classList),
+ ['positive', 'better']);
+ assert.sameMembers(Array.from(span.$.content.classList), ['better']);
+ checkSignificance(span, '');
+
+ span.significance = tr.b.math.Statistics.Significance.INSIGNIFICANT;
+ assert.sameMembers(Array.from(span.$.sparkline.classList),
+ ['positive', 'better']);
+ assert.sameMembers(Array.from(span.$.content.classList), ['better']);
+ checkSignificance(span, 'insignificant');
+
+ span.unit = Unit.byName.energyInJoulesDelta_smallerIsBetter;
+ assert.sameMembers(Array.from(span.$.sparkline.classList),
+ ['positive', 'worse']);
+ assert.sameMembers(Array.from(span.$.content.classList), ['worse']);
+ checkSignificance(span, 'insignificant');
+
+ span.unit = Unit.byName.energyInJoulesDelta;
+ assert.sameMembers(Array.from(span.$.sparkline.classList), ['positive']);
+ assert.sameMembers(Array.from(span.$.content.classList), []);
+ checkSignificance(span, '');
+
+ span.value = 0;
+ assert.sameMembers(Array.from(span.$.sparkline.classList), []);
+ assert.sameMembers(Array.from(span.$.content.classList), []);
+ checkSignificance(span, '');
+ });
+
+ test('sparkline_uncentered', function() {
+ const div = document.createElement('div');
+ this.addHTMLOutput(div);
+ div.appendChild(
+ document.createElement('tr-v-ui-scalar-context-controller'));
+
+ Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(-1, {
+ unit: Unit.byName.powerInWattsDelta,
+ contextGroup: 'test'
+ }));
+ Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(100, {
+ unit: Unit.byName.powerInWattsDelta,
+ contextGroup: 'test'
+ }));
+ Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(80, {
+ unit: Unit.byName.powerInWattsDelta,
+ contextGroup: 'test'
+ }));
+ Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(60, {
+ unit: Unit.byName.powerInWattsDelta,
+ contextGroup: 'test'
+ }));
+ });
+
+ test('sparkline_centered', function() {
+ const div = document.createElement('div');
+ this.addHTMLOutput(div);
+ div.appendChild(
+ document.createElement('tr-v-ui-scalar-context-controller'));
+
+ Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(-1, {
+ unit: Unit.byName.powerInWattsDelta,
+ customContextRange: tr.b.math.Range.fromExplicitRange(-100, 100)
+ }));
+ Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(100, {
+ unit: Unit.byName.powerInWattsDelta,
+ customContextRange: tr.b.math.Range.fromExplicitRange(-100, 100)
+ }));
+ Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(80, {
+ unit: Unit.byName.powerInWattsDelta,
+ customContextRange: tr.b.math.Range.fromExplicitRange(-100, 100)
+ }));
+ Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(60, {
+ unit: Unit.byName.powerInWattsDelta,
+ customContextRange: tr.b.math.Range.fromExplicitRange(-100, 100)
+ }));
+ });
+
+ timedPerfTest('memory_scalar_spans', function() {
+ tr.v.ui.createScalarSpan(EXAMPLE_MEMORY_NUMERIC, {
+ context: EXAMPLE_MEMORY_FORMATTING_CONTEXT,
+ inline: true,
+ });
+ }, {
+ iterations: 1000,
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/timings.md b/chromium/third_party/catapult/tracing/tracing/value/ui/timings.md
new file mode 100644
index 00000000000..3846af6ee0d
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/timings.md
@@ -0,0 +1,78 @@
+This document describes the Google Analytics metrics reported by results.html.
+
+Measures are recorded by the performance web API, and are visible in the User
+Timing track in the devtools Performance timeline.
+
+Instant events are recorded using console.timestamp(), and are visible as orange
+ticks at the top of the devtools Performance timeline.
+
+Both measures and instant events are recorded as Events in Google Analytics.
+[Access these metrics here](https://analytics.google.com/analytics/web/#embed/report-home/a98760012w145165698p149871853/) if you have been granted access.
+
+ * histogram-set-controls
+ * `alpha` measures response latency of changing the statistical significance
+ threshold, alpha.
+ * `hideOverviewCharts` measures response latency of hiding all overview
+ charts.
+ * `referenceColumn` measures response latency of changing the reference
+ column.
+ * `search` measures response latency of changing the search query to filter
+ rows.
+ * `showAll` measures response latency of toggling showing all rows versus
+ source Histograms only.
+ * `showOverviewCharts` measures response latency of showing all overview
+ charts.
+ * `statistic` measures response latency of changing the statistic that is
+ displayed in histogram-set-table-cells.
+ * HistogramSetLocation
+ * `onPopState` measures response latency of the browser back button.
+ * `pushState` measures latency of serializing the view state and pushing it
+ to the HTML5 history API. This happens automatically whenever any part of
+ the ViewState is updated.
+ * histogram-set-table
+ * `columnCount` instant event contains the number of columns, recorded when the
+ table is built.
+ * `nameColumnConstrained` instant event recorded when the name column width
+ is constrained.
+ * `nameColumnUnconstrained` instant event recorded when the name column width
+ is unconstrained.
+ * `rootRowCount` instant event contains the number of root rows, recorded
+ whenever it changes or the table is built.
+ * `rowCollapsed` instant event recorded whenever a row is collapsed.
+ * `rowExpanded` instant event recorded whenever a row is expanded.
+ * `selectHistogramNames` instant event recorded whenever a breakdown related
+ histogram name link is clicked.
+ * `sortColumn` instant event recorded whenever the user changes the sort
+ column.
+ * histogram-set-table-cell
+ * `close` instant event recorded when the cell is closed.
+ * `open` instant event recorded when the cell is opened.
+ * histogram-set-table-name-cell
+ * `closeHistograms` instant event recorded when the user clicks the button to
+ close all histogram-set-table-cells in the row.
+ * `hideOverview` instant event recorded when the user clicks the button to
+ hide the overview line charts for the row.
+ * `openHistograms` instant event recorded when the user clicks the button to
+ open all histogram-set-table-cells in the row.
+ * `showOverview` instant event recorded when the user clicks the button to
+ show the overview line charts for the row.
+ * histogram-set-view
+ * `build` measures latency to find source Histograms, collect parameters,
+ configure the controls and build the table. Does not include parsing
+ Histograms from json.
+ * `sourceHistograms` measures latency to find source Histograms in the
+ relationship graphical model.
+ * `collectParameters` measures latency to collect display labels, statistic
+ names, and possible groupings.
+ * `export{Raw,Merged}{CSV,JSON}` measures latency to download a CSV/JSON file
+ of raw/merged Histograms.
+ * histogram-span
+ * `brushBins` instant event recorded when the user finishes brushing bins.
+ * `clearBrushedBins` instant event recorded when the user clears brushed
+ bins.
+ * `mergeSampleDiagnostics` measures latency of displaying the table of merged
+ sample diagnostics.
+ * `splitSampleDiagnostics` measures latency of displaying the table of
+ unmerged sample diagnostics.
+ * HistogramParameterCollector
+ * `maxSampleCount` instant event records maximum Histogram.numValues
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/unmergeable_diagnostic_set_span.html b/chromium/third_party/catapult/tracing/tracing/value/ui/unmergeable_diagnostic_set_span.html
new file mode 100644
index 00000000000..de68e0cfa57
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/unmergeable_diagnostic_set_span.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!--
+Copyright 2017 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+ This file only depends on diagnostic_span.html, but it must be imported from
+ diagnostic_span.html.
+ Fortunately, this file is only imported from diagnostic_span.html, so it can
+ just not import anything.
+-->
+
+<link rel="import" href="/tracing/value/ui/diagnostic_span_behavior.html">
+
+<dom-module id="tr-v-ui-unmergeable-diagnostic-set-span">
+</dom-module>
+
+<script>
+'use strict';
+tr.exportTo('tr.v.ui', function() {
+ Polymer({
+ is: 'tr-v-ui-unmergeable-diagnostic-set-span',
+ behaviors: [tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],
+
+ updateContents_() {
+ Polymer.dom(this).textContent = '';
+ for (const diagnostic of this.diagnostic) {
+ if (diagnostic instanceof tr.v.d.RelatedNameMap) continue;
+ const div = document.createElement('div');
+ div.appendChild(tr.v.ui.createDiagnosticSpan(
+ diagnostic, this.name_, this.histogram_));
+ Polymer.dom(this).appendChild(div);
+ }
+ }
+ });
+
+ return {};
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/unmergeable_diagnostic_set_span_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/unmergeable_diagnostic_set_span_test.html
new file mode 100644
index 00000000000..29e48966fc0
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/unmergeable_diagnostic_set_span_test.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/core/test_utils.html">
+<link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
+<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ test('instantiate', function() {
+ const event = tr.c.TestUtils.newSliceEx({
+ title: 'event',
+ start: 0,
+ duration: 1,
+ });
+ event.parentContainer = {
+ sliceGroup: {
+ stableId: 'fake_thread',
+ slices: [event],
+ },
+ };
+ const diagnostics = new tr.v.d.UnmergeableDiagnosticSet([
+ new tr.v.d.GenericSet(['generic diagnostic']),
+ new tr.v.d.RelatedNameMap(),
+ new tr.v.d.RelatedEventSet([
+ event,
+ ]),
+ ]);
+ const span = tr.v.ui.createDiagnosticSpan(diagnostics);
+ assert.strictEqual('TR-V-UI-UNMERGEABLE-DIAGNOSTIC-SET-SPAN', span.tagName);
+ this.addHTMLOutput(span);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/visualizations_data_container.html b/chromium/third_party/catapult/tracing/tracing/value/ui/visualizations_data_container.html
new file mode 100644
index 00000000000..0adeaf55e3c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/visualizations_data_container.html
@@ -0,0 +1,410 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/value/ui/metrics_visualization.html">
+<link rel="import" href="/tracing/value/ui/raster_visualization.html">
+<meta charset="utf-8">
+<dom-module id='tr-v-ui-visualizations-data-container'>
+ <template>
+ <style>
+ .error {
+ color: red;
+ display: none;
+ }
+
+ .sample{
+ display: none;
+ }
+
+ .subtitle{
+ font-size: 20px;
+ font-weight: bold;
+ padding-bottom: 5px;
+ }
+
+ .description{
+ font-size: 15px;
+ padding-bottom: 5px;
+ }
+
+ #title {
+ font-size: 30px;
+ font-weight: bold;
+ padding-bottom: 5px;
+ }
+ </style>
+ <div id="title">Visualizations</div>
+ <div id="data_error" class="error">Invalid data provided.</div>
+ <div id="pipeline_per_frame_container">
+ <div class="subtitle">Graphics Pipeline and Raster Tasks</div>
+ <div class="description">
+ When raster tasks are completed in comparison to the rest of the graphics pipeline.<br>
+ Only pages where raster tasks are completed after beginFrame is issued are included.
+ </div>
+ <tr-v-ui-raster-visualization id="rasterVisualization">
+ </tr-v-ui-raster-visualization>
+ </div>
+ <div id=metrics_container>
+ <div class="subtitle">Metrics</div>
+ <div class="description">Total amount of time taken for the indicated metrics.</div>
+ <tr-v-ui-metrics-visualization id="metricsVisualization" class="sample">
+ </tr-v-ui-metrics-visualization>
+ </div>
+ </template>
+</dom-module>
+<script>
+'use strict';
+
+tr.exportTo('tr.v.ui', function() {
+ const STATISTICS_KEY = 'statistics';
+ const SUBMETRICS_KEY = 'submetrics';
+ const AGGREGATE_KEY = 'aggregate';
+ const RASTER_START_METRIC_KEY = 'pipeline:begin_frame_to_raster_start';
+
+ const COLORS = [
+ ['#FFD740', '#FFC400', '#FFAB00', '#E29800'],
+ ['#FF6E40', '#FF3D00', '#DD2C00', '#A32000'],
+ ['#40C4FF', '#00B0FF', '#0091EA', '#006DAF'],
+ ['#89C641', '#54B503', '#4AA510', '#377A0D'],
+ ['#B388FF', '#7C4DFF', '#651FFF', '#6200EA'],
+ ['#FF80AB', '#FF4081', '#F50057', '#C51162'],
+ ['#FFAB40', '#FF9100', '#FF6D00', '#D65C02'],
+ ['#8C9EFF', '#536DFE', '#3D5AFE', '#304FFE']];
+
+ const FRAME = [new Map([
+ ['pipeline:begin_frame_to_raster_start', false],
+ ['pipeline:begin_frame_to_raster_end', true]]), new Map([
+ ['pipeline:begin_frame_transport', true],
+ ['pipeline:begin_frame_to_frame_submission', true],
+ ['pipeline:frame_submission_to_display', true],
+ ['pipeline:draw', true]])];
+
+ const METRICS = new Map([
+ ['Pipeline', [
+ 'pipeline:begin_frame_transport',
+ 'pipeline:begin_frame_to_frame_submission',
+ 'pipeline:frame_submission_to_display',
+ 'pipeline:draw']],
+ ['Thread', [
+ 'thread_browser_cpu_time_per_frame',
+ 'thread_display_compositor_cpu_time_per_frame',
+ 'thread_GPU_cpu_time_per_frame',
+ 'thread_IO_cpu_time_per_frame',
+ 'thread_other_cpu_time_per_frame',
+ 'thread_raster_cpu_time_per_frame',
+ 'thread_renderer_compositor_cpu_time_per_frame',
+ 'thread_renderer_main_cpu_time_per_frame']]]);
+
+ function getValueFromMap(key, map) {
+ let retrievedValue = map.get(key);
+ if (!retrievedValue) {
+ retrievedValue = new Map();
+ map.set(key, retrievedValue);
+ }
+ return retrievedValue;
+ }
+
+ Polymer({
+ is: 'tr-v-ui-visualizations-data-container',
+
+ created() {
+ // from earliest to latest
+ this.orderedBenchmarks_ = [];
+ // aggregate/page -> benchmark -> metric -> statistics/submetrics
+ this.groupedData_ = new Map();
+ },
+
+ build(leafHistograms, histograms) {
+ if (!leafHistograms || leafHistograms.length < 1 ||
+ !histograms || histograms.length < 1) {
+ this.$.data_error.style.display = 'block';
+ return;
+ }
+
+ this.processHistograms_(this.groupHistograms_(histograms),
+ this.groupHistograms_(leafHistograms));
+ this.buildCharts_();
+ },
+
+ processHistograms_(histograms, leafHistograms) {
+ const benchmarkStartGrouping = tr.v.HistogramGrouping.BY_KEY.get(
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START);
+
+ const benchmarkToStartTime = new Map();
+ for (const [metric, benchmarks] of histograms.entries()) {
+ // process aggregate data
+ for (const [benchmark, pages] of leafHistograms.get(metric).entries()) {
+ for (const [page, histograms] of pages.entries()) {
+ for (const histogram of histograms) {
+ const aggregateToBenchmarkMap = getValueFromMap(AGGREGATE_KEY,
+ this.groupedData_);
+ const benchmarkToMetricMap = getValueFromMap(benchmark,
+ aggregateToBenchmarkMap);
+
+ benchmarkToMetricMap.set(metric, new Map([
+ [STATISTICS_KEY, histogram.running]]));
+ }
+ }
+ }
+
+ // process data per page
+ for (const [benchmark, pages] of benchmarks.entries()) {
+ for (const [page, histograms] of pages.entries()) {
+ for (const histogram of histograms) {
+ if (!benchmarkToStartTime.get(benchmark)) {
+ benchmarkToStartTime.set(benchmark,
+ benchmarkStartGrouping.callback(histogram));
+ }
+
+ const pageToBenchmarkMap = getValueFromMap(page,
+ this.groupedData_);
+ const benchmarkToMetricMap = getValueFromMap(benchmark,
+ pageToBenchmarkMap);
+
+ // retrieving submetric _ta
+ const mergedSubmetrics = new tr.v.d.DiagnosticMap();
+ for (const bin of histogram.allBins) {
+ for (const map of bin.diagnosticMaps) {
+ mergedSubmetrics.addDiagnostics(map);
+ }
+ }
+
+ if (benchmarkToMetricMap.get(metric)) continue;
+ benchmarkToMetricMap.set(metric, new Map([
+ [STATISTICS_KEY, histogram.running],
+ [SUBMETRICS_KEY, mergedSubmetrics.get('breakdown')]]));
+ }
+ }
+ }
+ }
+ this.orderedBenchmarks_ = this.sortBenchmarks_(benchmarkToStartTime);
+ },
+
+ groupHistograms_(histograms) {
+ const groupings = [
+ tr.v.HistogramGrouping.HISTOGRAM_NAME,
+ tr.v.HistogramGrouping.DISPLAY_LABEL,
+ tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES)];
+
+ return histograms.groupHistogramsRecursively(groupings);
+ },
+
+ sortBenchmarks_(benchmarks) {
+ return Array.from(benchmarks.keys()).sort((a, b) => {
+ Date.parse(benchmarks.get(a)) - Date.parse(benchmarks.get(b));
+ });
+ },
+
+ getSeriesKey_(metric, benchmark) {
+ return metric + '-' + benchmark;
+ },
+
+ buildCharts_() {
+ const rasterDataToBePassed = this.buildRasterChart_();
+ this.$.rasterVisualization.build(rasterDataToBePassed);
+
+ for (const chartName of METRICS.keys()) {
+ const metricsDataToBePassed = this.buildMetricsData_(chartName);
+ const newChart = this.$.metricsVisualization.cloneNode(true);
+ newChart.style.display = 'block';
+ Polymer.dom(this.$.metrics_container).appendChild(newChart);
+ newChart.build(metricsDataToBePassed);
+ }
+ },
+
+ buildRasterChart_() {
+ const orderedPages = [...this.groupedData_.keys()]
+ .filter((page) => this.filterPagesWithoutRasterMetric_(page))
+ .sort((a, b) => this.sortByRasterStart_(a, b));
+ const allChartData = new Map();
+ for (const page of orderedPages) {
+ const pageMap = this.groupedData_.get(page);
+ let chartData = [];
+ for (const benchmark of this.orderedBenchmarks_) {
+ if (!pageMap.has(benchmark)) continue;
+ const benchmarkMap = pageMap.get(benchmark);
+ const benchmarkData = [];
+ if (benchmarkMap.get(RASTER_START_METRIC_KEY) === undefined) {
+ continue;
+ }
+ for (const [threadName, thread] of FRAME.entries()) {
+ const data = {x: benchmark, hide: 0};
+ if (page !== AGGREGATE_KEY) data.group = page;
+ let rasterBegin = 0;
+ for (const metric of thread.keys()) {
+ const metricMap = benchmarkMap.get(metric);
+ const key = this.getSeriesKey_(metric,
+ data.x + '-' + threadName);
+ const stats = metricMap.get(STATISTICS_KEY);
+ const mean = stats ? stats.mean : 0;
+ let roundedMean = Math.round(mean * 100) / 100;
+ if (metric === RASTER_START_METRIC_KEY) {
+ rasterBegin = roundedMean;
+ } else if (metric === 'pipeline:begin_frame_to_raster_end') {
+ roundedMean -= rasterBegin;
+ }
+ data[key] = roundedMean;
+ }
+ benchmarkData.push(data);
+ }
+ chartData = chartData.concat(benchmarkData);
+ }
+ allChartData.set(page, chartData);
+ }
+ return allChartData;
+ },
+
+ buildMetricsData_(chartName) {
+ // pages are ordered from smallest to largest by their total
+ // values for the first benchmark
+ const orderedPages = [...this.groupedData_.keys()].sort((a, b) =>
+ this.sortByTotal_(a, b, chartName));
+ const chartData = [];
+ const aggregateChart = [];
+ for (const page of orderedPages) {
+ const pageMap = this.groupedData_.get(page);
+ for (const benchmark of this.orderedBenchmarks_) {
+ if (!pageMap.has(benchmark)) continue;
+ const data = {x: benchmark, group: page};
+ const benchmarkMap = pageMap.get(benchmark);
+ for (const metric of METRICS.get(chartName)) {
+ const metricMap = benchmarkMap.get(metric);
+ const key = this.getSeriesKey_(metric, benchmark);
+ const stats = metricMap.get(STATISTICS_KEY);
+ const mean = stats ? stats.mean : 0;
+ data[key] = Math.round(mean * 100) / 100;
+ }
+ if (page === AGGREGATE_KEY) {
+ aggregateChart.push(data);
+ } else {
+ chartData.push(data);
+ }
+ }
+ chartData.push({});
+ }
+ chartData.shift();
+ return {
+ title: chartName,
+ aggregate: aggregateChart,
+ page: chartData,
+ submetrics: this.processSubmetricsData_(chartName)
+ };
+ },
+
+ submetricsHelper_(submetric, value, benchmark, metricToSubmetricMap) {
+ let submetricToBenchmarkMap = metricToSubmetricMap.get(submetric);
+ if (!submetricToBenchmarkMap) {
+ submetricToBenchmarkMap = [];
+ metricToSubmetricMap.set(submetric, submetricToBenchmarkMap);
+ }
+ const data = {x: submetric, hide: 0, group: benchmark};
+ const mean = value;
+ const roundedMean = Math.round(mean * 100) / 100;
+ if (!roundedMean) return;
+ data[this.getSeriesKey_(submetric, benchmark)] = roundedMean;
+ submetricToBenchmarkMap.push(data);
+ },
+
+ // Get data for breakdown of a main step
+ processSubmetricsData_(chartName) {
+ // page -> metric -> submetric ->
+ // array of submetrics across all benchmarks
+ const submetrics = new Map();
+ for (const [page, pageMap] of this.groupedData_.entries()) {
+ if (page === AGGREGATE_KEY) continue;
+ const pageToMetricMap = getValueFromMap(page, submetrics);
+ for (const benchmark of this.orderedBenchmarks_) {
+ const benchmarkMap = pageMap.get(benchmark);
+ if (!benchmarkMap) continue;
+ for (const metric of METRICS.get(chartName)) {
+ const metricMap = benchmarkMap.get(metric);
+ const metricToSubmetricMap = getValueFromMap(metric,
+ pageToMetricMap);
+ const submetrics = metricMap.get(SUBMETRICS_KEY);
+ if (!submetrics) {
+ this.submetricsHelper_(metric, metricMap.get(STATISTICS_KEY),
+ benchmark, metricToSubmetricMap);
+ continue;
+ }
+ for (const [submetric, value] of [...submetrics]) {
+ this.submetricsHelper_(submetric, value, benchmark,
+ metricToSubmetricMap);
+ }
+ }
+ }
+ }
+ return submetrics;
+ },
+
+ sortByTotal_(a, b, chartName) {
+ if (a === AGGREGATE_KEY) return -1;
+ if (b === AGGREGATE_KEY) return 1;
+ let aValue = 0;
+ const aMap = this.groupedData_.get(a);
+ if (aMap.get(this.orderedBenchmarks_[0]) !== undefined) {
+ for (const metric of METRICS.get(chartName)) {
+ const aMetricMap = aMap.get(this.orderedBenchmarks_[0]).get(metric);
+ const aStats = aMetricMap.get(STATISTICS_KEY);
+ aValue += aStats ? aStats.mean : 0;
+ }
+ }
+ let bValue = 0;
+ const bMap = this.groupedData_.get(b);
+ if (bMap.get(this.orderedBenchmarks_[0]) !== undefined) {
+ for (const metric of METRICS.get(chartName)) {
+ const bMetricMap = bMap.get(this.orderedBenchmarks_[0]).get(metric);
+ const bStats = bMetricMap.get(STATISTICS_KEY);
+ bValue += bStats ? bStats.mean : 0;
+ }
+ }
+ return aValue - bValue;
+ },
+
+ filterPagesWithoutRasterMetric_(page) {
+ const pageMap = this.groupedData_.get(page);
+ for (const benchmark of this.orderedBenchmarks_) {
+ const pageMetricMap = pageMap.get(benchmark);
+ if (!pageMetricMap) continue;
+ const wantedMetric = pageMetricMap.get(RASTER_START_METRIC_KEY);
+ if (wantedMetric !== undefined) return true;
+ }
+ return false;
+ },
+
+ sortByRasterStart_(a, b) {
+ if (a === AGGREGATE_KEY) return 1;
+ if (b === AGGREGATE_KEY) return -1;
+ let aValue = 0;
+ const aMap = this.groupedData_.get(a);
+ if (aMap.get(this.orderedBenchmarks_[0]) !== undefined) {
+ const aMetricMap = aMap.get(this.orderedBenchmarks_[0])
+ .get(RASTER_START_METRIC_KEY);
+ const aStats = aMetricMap.get(STATISTICS_KEY);
+ aValue = aStats ? aStats.mean : 0;
+ }
+ let bValue = 0;
+ const bMap = this.groupedData_.get(b);
+ if (bMap.get(this.orderedBenchmarks_[0]) !== undefined) {
+ const bMetricMap = bMap.get(this.orderedBenchmarks_[0])
+ .get(RASTER_START_METRIC_KEY);
+ const bStats = bMetricMap.get(STATISTICS_KEY);
+ bValue = bStats ? bStats.mean : 0;
+ }
+ return bValue - aValue;
+ },
+ });
+
+ return {
+ STATISTICS_KEY,
+ SUBMETRICS_KEY,
+ AGGREGATE_KEY,
+ COLORS,
+ FRAME,
+ METRICS,
+ getValueFromMap,
+ };
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing/value/ui/visualizations_data_container_test.html b/chromium/third_party/catapult/tracing/tracing/value/ui/visualizations_data_container_test.html
new file mode 100644
index 00000000000..1199d8ed731
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing/value/ui/visualizations_data_container_test.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2018 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<link rel="import" href="/tracing/value/histogram.html">
+<link rel="import" href="/tracing/value/histogram_set.html">
+<link rel="import" href="/tracing/value/ui/visualizations_data_container.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+ function getHistogram(name) {
+ const samples = [];
+ for (let i = 0; i < 5; ++i) {
+ const total = Math.random();
+ const values = {};
+ values[name + 'a'] = total / 2.0;
+ values[name + 'b'] = total / 4.0;
+ values[name + 'c'] = total / 4.0;
+ samples.push({
+ value: total,
+ diagnostics: new Map([
+ [
+ tr.v.d.RESERVED_NAMES.BENCHMARK_START,
+ new tr.v.d.DateRange(Date.now()),
+ ], [
+ 'breakdown', tr.v.d.Breakdown.fromDict({values}),
+ ],
+ ]),
+ });
+ }
+ return tr.v.Histogram.create(name, tr.b.Unit.byName.count, samples);
+ }
+
+ function getHistogramSet(displayLabel, story, containsRasterStart = true) {
+ const histograms = new tr.v.HistogramSet();
+ let metrics = [];
+ for (const category of tr.v.ui.METRICS.values()) {
+ metrics = metrics.concat(category);
+ }
+ for (const metric of metrics) {
+ histograms.addHistogram(getHistogram(metric));
+ }
+
+ if (containsRasterStart) {
+ histograms.addHistogram(
+ getHistogram('pipeline:begin_frame_to_raster_start'));
+ histograms.addHistogram(
+ getHistogram('pipeline:begin_frame_to_raster_end'));
+ }
+ histograms.addSharedDiagnosticToAllHistograms(
+ tr.v.d.RESERVED_NAMES.LABELS, new tr.v.d.GenericSet([displayLabel]));
+ histograms.addSharedDiagnosticToAllHistograms(
+ tr.v.d.RESERVED_NAMES.STORIES, new tr.v.d.GenericSet([story]));
+ return histograms;
+ }
+
+ test('instantiate', function() {
+ const cp = document.createElement('tr-v-ui-visualizations-data-container');
+ this.addHTMLOutput(cp);
+
+ const histograms = getHistogramSet('Run 1', 'test.com');
+
+ const histograms2 = getHistogramSet('Run 2', 'test.com');
+ histograms.importDicts(histograms2.asDicts());
+
+ const histograms3 = getHistogramSet('Run 1', 'abc.com');
+ histograms.importDicts(histograms3.asDicts());
+
+ const histograms4 = getHistogramSet('Run 2', 'abc.com');
+ histograms.importDicts(histograms4.asDicts());
+
+ cp.build(histograms, histograms);
+ });
+
+ test('instantiateWithRepeat', function() {
+ const cp = document.createElement('tr-v-ui-visualizations-data-container');
+ this.addHTMLOutput(cp);
+
+ const histograms = getHistogramSet('Run 1', 'repeat.com');
+ const histograms2 = getHistogramSet('Run 1', 'repeat.com');
+ histograms.importDicts(histograms2.asDicts());
+
+ cp.build(histograms, histograms);
+ });
+
+ test('instantiateWithoutRasterTasks', function() {
+ const cp = document.createElement('tr-v-ui-visualizations-data-container');
+ this.addHTMLOutput(cp);
+
+ const histograms = getHistogramSet('Run 1', 'test.com', false);
+
+ const histograms2 = getHistogramSet('Run 2', 'test.com', false);
+ histograms.importDicts(histograms2.asDicts());
+
+ const histograms3 = getHistogramSet('Run 1', 'abc.com');
+ histograms.importDicts(histograms3.asDicts());
+
+ const histograms4 = getHistogramSet('Run 2', 'abc.com');
+ histograms.importDicts(histograms4.asDicts());
+
+ cp.build(histograms, histograms);
+ });
+
+ test('instantiateWithDifferentStorySets', function() {
+ const cp = document.createElement('tr-v-ui-visualizations-data-container');
+ this.addHTMLOutput(cp);
+
+ const histograms = getHistogramSet('Run 1', 'test.com');
+
+ const histograms2 = getHistogramSet('Run 1', 'abc.com');
+ histograms.importDicts(histograms2.asDicts());
+
+ const histograms3 = getHistogramSet('Run 2', 'abc.com');
+ histograms.importDicts(histograms3.asDicts());
+
+ cp.build(histograms, histograms);
+ });
+});
+</script>
diff --git a/chromium/third_party/catapult/tracing/tracing_build/__init__.py b/chromium/third_party/catapult/tracing/tracing_build/__init__.py
new file mode 100644
index 00000000000..22060c5dca2
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/__init__.py
@@ -0,0 +1,7 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+import tracing_project
+tracing_project.UpdateSysPathIfNeeded()
diff --git a/chromium/third_party/catapult/tracing/tracing_build/check_common.py b/chromium/third_party/catapult/tracing/tracing_build/check_common.py
new file mode 100644
index 00000000000..28dd49edc2c
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/check_common.py
@@ -0,0 +1,90 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+import tracing_project
+
+
+FILE_GROUPS = ["tracing_css_files",
+ "tracing_js_html_files",
+ "tracing_img_files"]
+
+
+def GetFileGroupFromFileName(filename):
+ extension = os.path.splitext(filename)[1]
+ return {
+ '.css': 'tracing_css_files',
+ '.html': 'tracing_js_html_files',
+ '.js': 'tracing_js_html_files',
+ '.png': 'tracing_img_files'
+ }[extension]
+
+
+def CheckListedFilesSorted(src_file, group_name, listed_files):
+ sorted_files = sorted(listed_files)
+ if sorted_files != listed_files:
+ mismatch = ''
+ for i, f in enumerate(listed_files):
+ if f != sorted_files[i]:
+ mismatch = f
+ break
+ what_is = ' ' + '\n '.join(listed_files)
+ what_should_be = ' ' + '\n '.join(sorted_files)
+ return '''In group {0} from file {1}, filenames aren't sorted.
+
+First mismatch:
+ {2}
+
+Current listing:
+{3}
+
+Correct listing:
+{4}\n\n'''.format(group_name, src_file, mismatch, what_is, what_should_be)
+ else:
+ return ''
+
+
+def GetKnownFiles():
+ project = tracing_project.TracingProject()
+
+ vulcanizer = project.CreateVulcanizer()
+ m = vulcanizer.loader.LoadModule(
+ module_name='tracing.ui.extras.about_tracing.about_tracing')
+ absolute_filenames = m.GetAllDependentFilenamesRecursive(
+ include_raw_scripts=False)
+
+ return list(set([os.path.relpath(f, project.tracing_root_path)
+ for f in absolute_filenames]))
+
+
+def CheckCommon(file_name, listed_files):
+ known_files = GetKnownFiles()
+ u = set(listed_files).union(set(known_files))
+ i = set(listed_files).intersection(set(known_files))
+ diff = list(u - i)
+
+ if len(diff) == 0:
+ return ''
+
+ error = 'Entries in ' + file_name + ' do not match files on disk:\n'
+ in_file_only = list(set(listed_files) - set(known_files))
+ in_known_only = list(set(known_files) - set(listed_files))
+
+ if len(in_file_only) > 0:
+ error += ' In file only:\n ' + '\n '.join(sorted(in_file_only))
+ if len(in_known_only) > 0:
+ if len(in_file_only) > 0:
+ error += '\n\n'
+ error += ' On disk only:\n ' + '\n '.join(sorted(in_known_only))
+
+ if in_file_only:
+ error += (
+ '\n\n'
+ ' Note: only files actually used in about:tracing should\n'
+ ' be listed in the build files. Try running \n'
+ ' tracing/bin/update_gni\n'
+ ' to update the files automatically.')
+
+ return error
diff --git a/chromium/third_party/catapult/tracing/tracing_build/check_common_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/check_common_unittest.py
new file mode 100644
index 00000000000..b3af7b6fb68
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/check_common_unittest.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing_build import check_common
+
+
+class CheckCommonUnitTest(unittest.TestCase):
+
+ def testFilesSorted(self):
+ error = check_common.CheckListedFilesSorted('foo.gyp', 'tracing_pdf_files',
+ ['/dir/file.pdf',
+ '/dir/another_file.pdf'])
+ expected_error = '''In group tracing_pdf_files from file foo.gyp,\
+ filenames aren't sorted.
+
+First mismatch:
+ /dir/file.pdf
+
+Current listing:
+ /dir/file.pdf
+ /dir/another_file.pdf
+
+Correct listing:
+ /dir/another_file.pdf
+ /dir/file.pdf\n\n'''
+ assert error == expected_error
diff --git a/chromium/third_party/catapult/tracing/tracing_build/check_gni.py b/chromium/third_party/catapult/tracing/tracing_build/check_gni.py
new file mode 100644
index 00000000000..af68ca4e667
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/check_gni.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import os
+
+from tracing_build import check_common
+
+_TRACING_BUILD = os.path.abspath(os.path.dirname(__file__))
+GNI_FILE = os.path.join(_TRACING_BUILD, '..', 'trace_viewer.gni')
+
+
+def GniCheck():
+ gni = open(GNI_FILE).read()
+ listed_files = []
+ error = ''
+ for group in check_common.FILE_GROUPS:
+ filenames = re.search(r'\n%s = \[([^\]]+)\]' % group, gni).groups(1)[0]
+ filenames = re.findall(r'"([^"]+)"', filenames)
+ filenames = [os.path.normpath(filename) for filename in filenames]
+ error += check_common.CheckListedFilesSorted(GNI_FILE, group, filenames)
+ listed_files.extend(filenames)
+
+ return error + check_common.CheckCommon(GNI_FILE, listed_files)
+
+
+if __name__ == '__main__':
+ print GniCheck()
diff --git a/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents.py b/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents.py
new file mode 100644
index 00000000000..e5aece0871f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents.py
@@ -0,0 +1,66 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import codecs
+import argparse
+import os
+import sys
+
+import py_vulcanize
+
+import tracing_project
+
+
+def Main(args):
+ parser = argparse.ArgumentParser(usage='%(prog)s --outdir=<directory>')
+ parser.add_argument('--outdir', dest='out_dir',
+ help='Where to place generated content')
+ parser.add_argument('--no-min', default=False, action='store_true',
+ help='Skip minification')
+ args = parser.parse_args(args)
+
+ if not args.out_dir:
+ sys.stderr.write('ERROR: Must specify --outdir=<directory>')
+ parser.print_help()
+ return 1
+
+ names = ['tracing.ui.extras.about_tracing.about_tracing']
+ project = tracing_project.TracingProject()
+
+ vulcanizer = project.CreateVulcanizer()
+ load_sequence = vulcanizer.CalcLoadSequenceForModuleNames(names)
+
+ olddir = os.getcwd()
+ try:
+ if not os.path.exists(args.out_dir):
+ os.makedirs(args.out_dir)
+ o = codecs.open(os.path.join(args.out_dir, 'about_tracing.html'), 'w',
+ encoding='utf-8')
+ try:
+ py_vulcanize.GenerateStandaloneHTMLToFile(
+ o,
+ load_sequence,
+ title='chrome://tracing',
+ flattened_js_url='tracing.js',
+ minify=not args.no_min)
+ except py_vulcanize.module.DepsException as ex:
+ sys.stderr.write('Error: %s\n\n' % str(ex))
+ return 255
+ o.close()
+
+ o = codecs.open(os.path.join(args.out_dir, 'about_tracing.js'), 'w',
+ encoding='utf-8')
+ assert o.encoding == 'utf-8'
+ py_vulcanize.GenerateJSToFile(
+ o,
+ load_sequence,
+ use_include_tags_for_scripts=False,
+ dir_for_include_tag_root=args.out_dir,
+ minify=not args.no_min)
+ o.close()
+
+ finally:
+ os.chdir(olddir)
+
+ return 0
diff --git a/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py
new file mode 100644
index 00000000000..7ebe3ddc861
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/generate_about_tracing_contents_unittest.py
@@ -0,0 +1,24 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+import shutil
+import sys
+import tempfile
+
+if sys.version_info < (3,):
+ from tracing_build import generate_about_tracing_contents
+
+
+@unittest.skipIf(sys.version_info >= (3,),
+ 'py_vulcanize is not ported to python3')
+class GenerateAboutTracingContentsUnittTest(unittest.TestCase):
+
+ def testSmoke(self):
+ try:
+ tmpdir = tempfile.mkdtemp()
+ res = generate_about_tracing_contents.Main(['--outdir', tmpdir])
+ assert res == 0
+ finally:
+ shutil.rmtree(tmpdir)
diff --git a/chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html b/chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html
new file mode 100644
index 00000000000..8e86bdc695e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/histograms_viewer.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<script>
+'use strict';
+window.ga = window.ga || function() {
+ ga.q = ga.q || [];
+ ga.q.push(arguments);
+};
+ga.l = new Date();
+ga('create', 'UA-98760012-1', 'auto');
+
+// Supporting file: URIs requires disabling protocol checking, cookie storage
+// checking, and history checking.
+ga('set', 'checkProtocolTask', null);
+ga('set', 'checkStorageTask', null);
+ga('set', 'historyImportTask', null);
+
+(function() {
+ // Write this script tag at runtime instead of in HTML in order to bypass the
+ // vulcanizer.
+ const script = document.createElement('script');
+ script.src = 'https://www.google-analytics.com/analytics.js';
+ script.type = 'text/javascript';
+ script.async = true;
+ document.head.appendChild(script);
+})();
+</script>
+
+<link rel="import" href="/tracing/ui/base/base.html" data-suppress-import-order>
+
+<div id="loading">Loading framework...</div>
+
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/value/histogram_importer.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_location.html">
+<link rel="import" href="/tracing/value/ui/histogram_set_view.html">
+
+<script>
+'use strict';
+(function() {
+ ga('send', {
+ hitType: 'pageview',
+ page: '/results.html',
+ });
+
+ const domContentLoadedMark = tr.b.Timing.mark('results2', 'domContentLoaded');
+ let importer = new tr.v.HistogramImporter(document.getElementById('loading'));
+
+ document.addEventListener('DOMContentLoaded', async() => {
+ domContentLoadedMark.end();
+
+ const jsonData = document.getElementById('histogram-json-data');
+ const view = document.getElementById('histograms');
+ const locus = new tr.v.ui.HistogramSetLocation();
+
+ const data = jsonData.childNodes[0].textContent;
+ await importer.importHistograms(data, view);
+ await locus.build(view.viewState);
+
+ // Free the objects and DOM referenced by the importer.
+ document.body.removeChild(jsonData);
+ importer = undefined;
+ });
+})();
+</script>
+
+<tr-v-ui-histogram-set-view id="histograms" style="display: none;"></tr-v-ui-histogram-set-view>
diff --git a/chromium/third_party/catapult/tracing/tracing_build/html2trace.py b/chromium/third_party/catapult/tracing/tracing_build/html2trace.py
new file mode 100644
index 00000000000..0dfa63fa2c4
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/html2trace.py
@@ -0,0 +1,106 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import base64
+import gzip
+import io
+import json
+import re
+
+
+GZIP_HEADER_BYTES = b'\x1f\x8b'
+
+
+# Regular expressions for matching the beginning and end of trace data in HTML
+# traces. See tracing/extras/importer/trace2html_importer.html.
+TRACE_DATA_START_LINE_RE = re.compile(
+ r'^<\s*script id="viewer-data" type="(application\/json|text\/plain)">\r?$')
+TRACE_DATA_END_LINE_RE = re.compile(r'^<\/\s*script>\r?$')
+
+
+def IsHTMLTrace(trace_file_handle):
+ trace_file_handle.seek(0)
+ for line in trace_file_handle:
+ line = line.strip()
+ if not line:
+ continue
+ return line == '<!DOCTYPE html>'
+
+
+def CopyTraceDataFromHTMLFilePath(html_file_handle, trace_path,
+ gzipped_output=False):
+ """Copies trace data from an existing HTML file into new trace file(s).
+
+ If |html_file_handle| doesn't contain any trace data blocks, this function
+ throws an exception. If |html_file_handle| contains more than one trace data
+ block, the first block will be extracted into |trace_path| and the rest will
+ be extracted into separate files |trace_path|.1, |trace_path|.2, etc.
+
+ The contents of each trace data block is decoded and, if |gzipped_output| is
+ false, inflated before it's stored in a trace file.
+
+ This function returns a list of paths of the saved trace files ([|trace_path|,
+ |trace_path|.1, |trace_path|.2, ...]).
+ """
+ trace_data_list = _ExtractTraceDataFromHTMLFile(html_file_handle,
+ unzip_data=not gzipped_output)
+ saved_paths = []
+ for i, trace_data in enumerate(trace_data_list):
+ saved_path = trace_path if i == 0 else '%s.%d' % (trace_path, i)
+ saved_paths.append(saved_path)
+ with open(saved_path, 'wb' if gzipped_output else 'w') as trace_file:
+ trace_file.write(trace_data.read())
+ return saved_paths
+
+
+def ReadTracesFromHTMLFile(file_handle):
+ """Returns a list of inflated JSON traces extracted from an HTML file."""
+ return [json.load(t) for t in _ExtractTraceDataFromHTMLFile(file_handle)]
+
+
+def _ExtractTraceDataFromHTMLFile(html_file_handle, unzip_data=True):
+ assert IsHTMLTrace(html_file_handle)
+ html_file_handle.seek(0)
+ lines = html_file_handle.readlines()
+
+ start_indices = [i for i in range(len(lines))
+ if TRACE_DATA_START_LINE_RE.match(lines[i])]
+ if not start_indices:
+ raise Exception('File %r does not contain trace data')
+
+ decoded_data_list = []
+ for start_index in start_indices:
+ end_index = next(i for i in range(start_index + 1, len(lines))
+ if TRACE_DATA_END_LINE_RE.match(lines[i]))
+ encoded_data = '\n'.join(lines[start_index + 1:end_index]).strip()
+ decoded_data_list.append(io.BytesIO(base64.b64decode(encoded_data)))
+
+ if unzip_data:
+ return map(_UnzipFileIfNecessary, decoded_data_list)
+ else:
+ return map(_ZipFileIfNecessary, decoded_data_list)
+
+
+def _UnzipFileIfNecessary(original_file):
+ if _IsFileZipped(original_file):
+ return gzip.GzipFile(fileobj=original_file)
+ else:
+ return original_file
+
+
+def _ZipFileIfNecessary(original_file):
+ if _IsFileZipped(original_file):
+ return original_file
+ else:
+ zipped_file = io.BytesIO()
+ with gzip.GzipFile(fileobj=zipped_file, mode='wb') as gzip_wrapper:
+ gzip_wrapper.write(original_file.read())
+ zipped_file.seek(0)
+ return zipped_file
+
+
+def _IsFileZipped(f):
+ is_gzipped = f.read(len(GZIP_HEADER_BYTES)) == GZIP_HEADER_BYTES
+ f.seek(0)
+ return is_gzipped
diff --git a/chromium/third_party/catapult/tracing/tracing_build/merge_traces.py b/chromium/third_party/catapult/tracing/tracing_build/merge_traces.py
new file mode 100644
index 00000000000..127e4db7ebb
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/merge_traces.py
@@ -0,0 +1,687 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import argparse
+import codecs
+import collections
+import gzip
+import itertools
+import json
+import logging
+import os
+import sys
+
+# Add tracing/ to the path.
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
+from tracing_build import html2trace, trace2html
+
+
+try:
+ StringTypes = basestring
+except NameError:
+ StringTypes = str
+
+
+GZIP_FILENAME_SUFFIX = '.gz'
+HTML_FILENAME_SUFFIX = '.html'
+
+
+# Relevant trace event phases. See
+# https://code.google.com/p/chromium/codesearch#chromium/src/base/trace_event/common/trace_event_common.h.
+METADATA_PHASE = 'M'
+MEMORY_DUMP_PHASE = 'v'
+BEGIN_PHASE = 'B'
+END_PHASE = 'E'
+CLOCK_SYNC_EVENT_PHASE = 'c'
+
+
+# Minimum gap between two consecutive merged traces in microseconds.
+MIN_TRACE_GAP_IN_US = 1000000
+
+
+# Rule for matching IDs in an IdMap. For a given level, |match| should be a
+# named tuple class where its fields determine the importance of |entry._items|
+# for the purposes of matching pairs of IdMap entries.
+IdMapLevel = collections.namedtuple('IdMapLevel', ['name', 'match'])
+
+
+class IdMap(object):
+ """Abstract class for merging and mapping IDs from multiple sources."""
+
+ # Sub-classes must provide a tuple of |IdMapLevel| objects.
+ LEVELS = NotImplemented
+
+ def __init__(self, depth=0):
+ assert 0 <= depth <= len(self.LEVELS)
+ self._depth = depth
+
+ if depth > 0:
+ # Non-root node.
+ self._canonical_id = None
+ self._items = collections.defaultdict(set)
+ self._sources = set()
+
+ if depth < len(self.LEVELS):
+ # Non-leaf node.
+ self._entry_map = {} # (Source, Entry ID) -> Entry.
+
+ @property
+ def max_mapped_id(self):
+ """The maximum mapped ID of this map's entries."""
+ if not self._entry_map:
+ return 0
+ return max(e._canonical_id for e in self._entry_map.values())
+
+ def AddEntry(self, source, path, **items):
+ """Add a source-specific entry path to the map.
+
+ Args:
+ source: The source of the entry (e.g. trace filename).
+ path: A path of source-specific entry IDs in the map (e.g. [PID, TID]).
+ **items: Dictionary of items (or sets of items) to be appended to the
+ target entry's |_items|.
+ """
+ if path:
+ return self._GetSubMapEntry(source, path[0]).AddEntry(source, path[1:],
+ **items)
+ assert 'id' not in items # ID is set according to the path.
+ for key, value in items.items():
+ value_set = self._items[key]
+ if (isinstance(value, collections.Iterable) and
+ not isinstance(value, StringTypes)):
+ value_set.update(value)
+ else:
+ value_set.add(value)
+
+ def MapEntry(self, source, path):
+ """Map an source-specific entry ID path to a canonical entry ID path.
+
+ Args:
+ source: The source of the entry (e.g. trace filename).
+ path: A path of source-specific entry IDs in the map (e.g. [PID, TID]).
+
+ Returns:
+ A path of canonical entry IDs in the map to which the provided path of
+ source-specific entry IDs is mapped.
+ """
+ if not path:
+ return ()
+ entry = self._entry_map[(source, path[0])]
+ return (entry._canonical_id,) + entry.MapEntry(source, path[1:])
+
+ def MergeEntries(self):
+ """Recursively merge the entries in this map.
+
+ Example: Suppose that the following entries were added to the map:
+
+ map.AddEntry(source='trace_A.json', path=[10], name='Browser')
+ map.AddEntry(source='trace_A.json', path=[20], name='Renderer')
+ map.AddEntry(source='trace_B.json', path=[30], name='Browser')
+
+ Before merging, |map._entry_map| will contain three separate items:
+
+ ('trace_A.json', 10) -> IdMap(_items={id: {10}, name: {'Browser'}},
+ _sources={'trace_A.json'})
+ ('trace_A.json', 20) -> IdMap(_items={id: {20}, name: {'Renderer'}},
+ _sources={'trace_A.json'})
+ ('trace_B.json', 30) -> IdMap(_items={id: {30}, name: {'Browser'}},
+ _sources={'trace_B.json'})
+
+ Since the first two entries come from the same source, they cannot be
+ merged. On the other hand, the third entry could be merged with either of
+ the first two. Since it has a common name with the first entry, it will be
+ merged with it in this method:
+
+ ('trace_A.json', 10) -> IdMap(_items={id: {10, 30}, name: {'Browser'}},
+ _sources={'trace_A.json', 'trace_B.json'})
+ ('trace_A.json', 20) -> IdMap(_items={id: {20}, name: {Renderer}},
+ _sources={'trace_A.json'})
+ ('trace_B.json', 30) -> <same IdMap as ('trace_A.json', 10)>
+
+ Pairs of entries will be merged in a descending order of sizes of
+ pair-wise intersections of |entry._items| until there are no two entries
+ such that (1) they have at least one value in |entry._items| in common and
+ (2) they are mergeable (i.e. have no common source). Afterwards, unique IDs
+ are assigned to the resulting "canonical" entries and their sub-entries are
+ merged recursively.
+ """
+ # pylint: disable=unsubscriptable-object
+ if self._depth == len(self.LEVELS):
+ return
+
+ logging.debug('Merging %r entries in %s...', self.LEVELS[self._depth].name,
+ self)
+
+ canonical_entries = self._CanonicalizeEntries()
+ self._AssignIdsToCanonicalEntries(canonical_entries)
+
+ for entry in canonical_entries:
+ entry.MergeEntries()
+
+ def _GetSubMapEntry(self, source, entry_id):
+ full_id = (source, entry_id)
+ entry = self._entry_map.get(full_id)
+ if entry is None:
+ entry = type(self)(self._depth + 1)
+ entry._sources.add(source)
+ entry._items['id'].add(entry_id)
+ self._entry_map[full_id] = entry
+ return entry
+
+ def _CalculateUnmergeableMapFromEntrySources(self):
+ entry_ids_by_source = collections.defaultdict(set)
+ for entry_id, entry in self._entry_map.items():
+ for source in entry._sources:
+ entry_ids_by_source[source].add(entry_id)
+
+ unmergeable_map = collections.defaultdict(set)
+ for unmergeable_set in entry_ids_by_source.values():
+ for entry_id in unmergeable_set:
+ unmergeable_map[entry_id].update(unmergeable_set - {entry_id})
+
+ return unmergeable_map
+
+ def _IsMergeableWith(self, other):
+ return self._sources.isdisjoint(other._sources)
+
+ def _GetMatch(self, other):
+ # pylint: disable=unsubscriptable-object
+ match_cls = self.LEVELS[self._depth - 1].match
+ return match_cls(*(self._items[f] & other._items[f]
+ for f in match_cls._fields))
+
+ def _MergeFrom(self, source):
+ if self._depth > 0:
+ # This is NOT a ROOT node, so we need to merge fields and sources from
+ # the source node.
+ for key, values in source._items.items():
+ self._items[key].update(values)
+ self._sources.update(source._sources)
+
+ if self._depth < len(self.LEVELS):
+ # This is NOT a LEAF node, so we need to copy over entries from the
+ # source node's entry map.
+ assert not set(self._entry_map) & set(source._entry_map)
+ self._entry_map.update(source._entry_map)
+
+ def _CanonicalizeEntries(self):
+ canonical_entries = self._entry_map.copy()
+
+ # {ID1, ID2} -> Match between the two entries.
+ matches = {frozenset([full_id1, full_id2]): entry1._GetMatch(entry2)
+ for full_id1, entry1 in canonical_entries.items()
+ for full_id2, entry2 in canonical_entries.items()
+ if entry1._IsMergeableWith(entry2)}
+
+ while matches:
+ # Pop the maximum match from the dictionary.
+ max_match_set, max_match = max(
+ matches.items(), key=lambda pair: [len(v) for v in pair[1]])
+ del matches[max_match_set]
+ canonical_full_id, merged_full_id = max_match_set
+
+ # Skip pairs of entries that have nothing in common.
+ if not any(max_match):
+ continue
+
+ # Merge the entries and update the map to reflect this.
+ canonical_entry = canonical_entries[canonical_full_id]
+ merged_entry = canonical_entries.pop(merged_full_id)
+ logging.debug('Merging %s into %s [match=%s]...', merged_entry,
+ canonical_entry, max_match)
+ canonical_entry._MergeFrom(merged_entry)
+ del merged_entry
+ self._entry_map[merged_full_id] = canonical_entry
+
+ for match_set in matches.keys():
+ if merged_full_id in match_set:
+ # Remove other matches with the merged entry.
+ del matches[match_set]
+ elif canonical_full_id in match_set:
+ [other_full_id] = match_set - {canonical_full_id}
+ other_entry = canonical_entries[other_full_id]
+ if canonical_entry._IsMergeableWith(other_entry):
+ # Update other matches with the canonical entry which are still
+ # mergeable.
+ matches[match_set] = canonical_entry._GetMatch(other_entry)
+ else:
+ # Remove other matches with the canonical entry which have become
+ # unmergeable.
+ del matches[match_set]
+
+ return canonical_entries.values()
+
+ def _AssignIdsToCanonicalEntries(self, canonical_entries):
+ assigned_ids = set()
+ canonical_entries_without_assigned_ids = set()
+
+ # Try to assign each canonical entry to one of the IDs from which it was
+ # merged.
+ for canonical_entry in canonical_entries:
+ candidate_ids = canonical_entry._items['id']
+ try:
+ assigned_id = next(candidate_id for candidate_id in candidate_ids
+ if candidate_id not in assigned_ids)
+ except StopIteration:
+ canonical_entries_without_assigned_ids.add(canonical_entry)
+ continue
+ assigned_ids.add(assigned_id)
+ canonical_entry._canonical_id = assigned_id
+
+ # For canonical entries where this cannot be done (highly unlikely), scan
+ # from the minimal merged ID upwards for the first unassigned ID.
+ for canonical_entry in canonical_entries_without_assigned_ids:
+ assigned_id = next(candidate_id for candidate_id in
+ itertools.count(min(canonical_entry._items['id']))
+ if candidate_id not in assigned_ids)
+ assigned_ids.add(assigned_id)
+ canonical_entry._canonical_id = assigned_id
+
+ def __repr__(self):
+ # pylint: disable=unsubscriptable-object
+ cls_name = type(self).__name__
+ if self._depth == 0:
+ return '%s root' % cls_name
+ else:
+ return '%s %s entry(%s)' % (cls_name, self.LEVELS[self._depth - 1].name,
+ self._items)
+
+
+class ProcessIdMap(IdMap):
+ """Class for merging and mapping PIDs and TIDs from multiple sources."""
+
+ LEVELS = (
+ IdMapLevel(name='process',
+ match=collections.namedtuple('ProcessMatch',
+ ['name', 'id', 'label'])),
+ IdMapLevel(name='thread',
+ match=collections.namedtuple('ThreadMatch', ['name', 'id']))
+ )
+
+
+def LoadTrace(filename):
+ """Load a trace from a (possibly gzipped) file and return its parsed JSON."""
+ logging.info('Loading trace %r...', filename)
+ if filename.endswith(HTML_FILENAME_SUFFIX):
+ return LoadHTMLTrace(filename)
+ elif filename.endswith(GZIP_FILENAME_SUFFIX):
+ with gzip.open(filename, 'rb') as f:
+ return json.load(f)
+ else:
+ with open(filename, 'r') as f:
+ return json.load(f)
+
+
+def LoadHTMLTrace(filename):
+ """Load a trace from a vulcanized HTML trace file."""
+ trace_components = collections.defaultdict(list)
+
+ with open(filename) as file_handle:
+ for sub_trace in html2trace.ReadTracesFromHTMLFile(file_handle):
+ for name, component in TraceAsDict(sub_trace).items():
+ trace_components[name].append(component)
+
+ trace = {}
+ for name, components in trace_components.items():
+ if len(components) == 1:
+ trace[name] = components[0]
+ elif all(isinstance(component, list) for component in components):
+ trace[name] = [e for component in components for e in component]
+ else:
+ trace[name] = components[0]
+ logging.warning(
+ 'Values of repeated trace component %r in HTML trace %r are not '
+ 'lists. The first defined value of the component will be used.',
+ filename, name)
+
+ return trace
+
+
+def SaveTrace(trace, filename):
+ """Save a JSON trace to a (possibly gzipped) file."""
+ if filename is None:
+ logging.info('Dumping trace to standard output...')
+ print(json.dumps(trace))
+ else:
+ logging.info('Saving trace %r...', filename)
+ if filename.endswith(HTML_FILENAME_SUFFIX):
+ with codecs.open(filename, mode='w', encoding='utf-8') as f:
+ trace2html.WriteHTMLForTraceDataToFile([trace], 'Merged trace', f)
+ elif filename.endswith(GZIP_FILENAME_SUFFIX):
+ with gzip.open(filename, 'wb') as f:
+ json.dump(trace, f)
+ else:
+ with open(filename, 'w') as f:
+ json.dump(trace, f)
+
+
+def TraceAsDict(trace):
+ """Ensure that a trace is a dictionary."""
+ if isinstance(trace, list):
+ return {'traceEvents': trace}
+ return trace
+
+
+def MergeTraceFiles(input_trace_filenames, output_trace_filename):
+ """Merge a collection of input trace files into an output trace file."""
+ logging.info('Loading %d input traces...', len(input_trace_filenames))
+ input_traces = collections.OrderedDict()
+ for input_trace_filename in input_trace_filenames:
+ input_traces[input_trace_filename] = LoadTrace(input_trace_filename)
+
+ logging.info('Merging traces...')
+ output_trace = MergeTraces(input_traces)
+
+ logging.info('Saving output trace...')
+ SaveTrace(output_trace, output_trace_filename)
+
+ logging.info('Finished.')
+
+
+def MergeTraces(traces):
+ """Merge a collection of JSON traces into a single JSON trace."""
+ trace_components = collections.defaultdict(collections.OrderedDict)
+
+ for filename, trace in traces.items():
+ for name, component in TraceAsDict(trace).items():
+ trace_components[name][filename] = component
+
+ merged_trace = {}
+ for component_name, components_by_filename in trace_components.items():
+ logging.info('Merging %d %r components...', len(components_by_filename),
+ component_name)
+ merged_trace[component_name] = MergeComponents(component_name,
+ components_by_filename)
+
+ return merged_trace
+
+
+def MergeComponents(component_name, components_by_filename):
+ """Merge a component of multiple JSON traces into a single component."""
+ if component_name == 'traceEvents':
+ return MergeTraceEvents(components_by_filename)
+ else:
+ return MergeGenericTraceComponents(component_name, components_by_filename)
+
+
+def MergeTraceEvents(events_by_filename):
+ """Merge trace events from multiple traces into a single list of events."""
+ # Remove strings from the list of trace events
+ # (https://github.com/catapult-project/catapult/issues/2497).
+ events_by_filename = collections.OrderedDict(
+ (filename, [e for e in events if not isinstance(e, StringTypes)])
+ for filename, events in events_by_filename.items())
+
+ timestamp_range_by_filename = _AdjustTimestampRanges(events_by_filename)
+ process_map = _CreateProcessMapFromTraceEvents(events_by_filename)
+ merged_events = _CombineTraceEvents(events_by_filename, process_map)
+ _RemoveSurplusClockSyncEvents(merged_events)
+ merged_events.extend(
+ _BuildInjectedTraceMarkerEvents(timestamp_range_by_filename, process_map))
+ return merged_events
+
+
+def _RemoveSurplusClockSyncEvents(events):
+ """Remove all clock sync events except for the first one."""
+ # TODO(petrcermak): Figure out how to handle merging multiple clock sync
+ # events.
+ clock_sync_event_indices = [i for i, e in enumerate(events)
+ if e['ph'] == CLOCK_SYNC_EVENT_PHASE]
+ # The indices need to be traversed from largest to smallest (hence the -1).
+ for i in clock_sync_event_indices[:0:-1]:
+ del events[i]
+
+
+def _AdjustTimestampRanges(events_by_filename):
+ logging.info('Adjusting timestamp ranges of traces...')
+
+ previous_trace_max_timestamp = 0
+ timestamp_range_by_filename = collections.OrderedDict()
+
+ for index, (filename, events) in enumerate(events_by_filename.items(), 1):
+ # Skip metadata events, the timestamps of which are always zero.
+ non_metadata_events = [e for e in events if e['ph'] != METADATA_PHASE]
+ if not non_metadata_events:
+ logging.warning('Trace %r (%d/%d) only contains metadata events.',
+ filename, index, len(events_by_filename))
+ timestamp_range_by_filename[filename] = None
+ continue
+
+ min_timestamp = min(e['ts'] for e in non_metadata_events)
+ max_timestamp = max(e['ts'] for e in non_metadata_events)
+
+ # Determine by how much the timestamps should be shifted.
+ injected_timestamp_shift = max(
+ previous_trace_max_timestamp + MIN_TRACE_GAP_IN_US - min_timestamp, 0)
+ logging.info('Injected timestamp shift in trace %r (%d/%d): %d ms '
+ '[min=%d, max=%d, duration=%d].', filename, index,
+ len(events_by_filename), injected_timestamp_shift,
+ min_timestamp, max_timestamp, max_timestamp - min_timestamp)
+
+ if injected_timestamp_shift > 0:
+ # Shift the timestamps.
+ for event in non_metadata_events:
+ event['ts'] += injected_timestamp_shift
+
+ # Adjust the range.
+ min_timestamp += injected_timestamp_shift
+ max_timestamp += injected_timestamp_shift
+
+ previous_trace_max_timestamp = max_timestamp
+
+ timestamp_range_by_filename[filename] = min_timestamp, max_timestamp
+
+ return timestamp_range_by_filename
+
+
+def _CreateProcessMapFromTraceEvents(events_by_filename):
+ logging.info('Creating process map from trace events...')
+
+ process_map = ProcessIdMap()
+ for filename, events in events_by_filename.items():
+ for event in events:
+ pid, tid = event['pid'], event['tid']
+ process_map.AddEntry(source=filename, path=(pid, tid))
+ if event['ph'] == METADATA_PHASE:
+ if event['name'] == 'process_name':
+ process_map.AddEntry(source=filename, path=(pid,),
+ name=event['args']['name'])
+ elif event['name'] == 'process_labels':
+ process_map.AddEntry(source=filename, path=(pid,),
+ label=event['args']['labels'].split(','))
+ elif event['name'] == 'thread_name':
+ process_map.AddEntry(source=filename, path=(pid, tid),
+ name=event['args']['name'])
+
+ process_map.MergeEntries()
+ return process_map
+
+
+def _CombineTraceEvents(events_by_filename, process_map):
+ logging.info('Combining trace events from all traces...')
+
+ type_name_event_by_pid = {}
+ combined_events = []
+
+ for index, (filename, events) in enumerate(events_by_filename.items(), 1):
+ for event in events:
+ if _UpdateTraceEventForMerge(event, process_map, filename, index,
+ type_name_event_by_pid):
+ combined_events.append(event)
+
+ return combined_events
+
+
+def _UpdateTraceEventForMerge(event, process_map, filename, index,
+ type_name_event_by_pid):
+ pid, tid = process_map.MapEntry(source=filename,
+ path=(event['pid'], event['tid']))
+ event['pid'], event['tid'] = pid, tid
+
+ if event['ph'] == METADATA_PHASE:
+ # Update IDs in 'stackFrames' and 'typeNames' metadata events.
+ if event['name'] == 'stackFrames':
+ _UpdateDictIds(index, event['args'], 'stackFrames')
+ for frame in event['args']['stackFrames'].values():
+ _UpdateFieldId(index, frame, 'parent')
+ elif event['name'] == 'typeNames':
+ _UpdateDictIds(index, event['args'], 'typeNames')
+ existing_type_name_event = type_name_event_by_pid.get(pid)
+ if existing_type_name_event is None:
+ type_name_event_by_pid[pid] = event
+ else:
+ existing_type_name_event['args']['typeNames'].update(
+ event['args']['typeNames'])
+ # Don't add the event to the merged trace because it has been merged
+ # into an existing 'typeNames' metadata event for the given process.
+ return False
+
+ elif event['ph'] == MEMORY_DUMP_PHASE:
+ # Update stack frame and type name IDs in heap dump entries in process
+ # memory dumps.
+ for heap_dump in event['args']['dumps'].get('heaps', {}).values():
+ for heap_entry in heap_dump['entries']:
+ _UpdateFieldId(index, heap_entry, 'bt', ignored_values=[''])
+ _UpdateFieldId(index, heap_entry, 'type')
+
+ return True # Events should be added to the merged trace by default.
+
+
+def _ConvertId(index, original_id):
+ return '%d#%s' % (index, original_id)
+
+
+def _UpdateDictIds(index, parent_dict, key):
+ parent_dict[key] = {
+ _ConvertId(index, original_id): value
+ for original_id, value in parent_dict[key].items()}
+
+
+def _UpdateFieldId(index, parent_dict, key, ignored_values=()):
+ original_value = parent_dict.get(key)
+ if original_value is not None and original_value not in ignored_values:
+ parent_dict[key] = _ConvertId(index, original_value)
+
+
+def _BuildInjectedTraceMarkerEvents(timestamp_range_by_filename, process_map):
+ logging.info('Building injected trace marker events...')
+
+ injected_pid = process_map.max_mapped_id + 1
+
+ # Inject a mock process with a thread.
+ injected_events = [
+ {
+ 'pid': injected_pid,
+ 'tid': 0,
+ 'ph': METADATA_PHASE,
+ 'ts': 0,
+ 'name': 'process_sort_index',
+ 'args': {'sort_index': -1000} # Show the process at the top.
+ },
+ {
+ 'pid': injected_pid,
+ 'tid': 0,
+ 'ph': METADATA_PHASE,
+ 'ts': 0,
+ 'name': 'process_name',
+ 'args': {'name': 'Merged traces'}
+ },
+ {
+ 'pid': injected_pid,
+ 'tid': 0,
+ 'ph': METADATA_PHASE,
+ 'ts': 0,
+ 'name': 'thread_name',
+ 'args': {'name': 'Trace'}
+ }
+ ]
+
+ # Inject slices for each sub-trace denoting its beginning and end.
+ for index, (filename, timestamp_range) in enumerate(
+ timestamp_range_by_filename.items(), 1):
+ if timestamp_range is None:
+ continue
+ min_timestamp, max_timestamp = timestamp_range
+ name = 'Trace %r (%d/%d)' % (filename, index,
+ len(timestamp_range_by_filename))
+ slice_id = 'INJECTED_TRACE_MARKER_%d' % index
+ injected_events.extend([
+ {
+ 'pid': injected_pid,
+ 'tid': 0,
+ 'ph': BEGIN_PHASE,
+ 'cat': 'injected',
+ 'name': name,
+ 'id': slice_id,
+ 'ts': min_timestamp
+ },
+ {
+ 'pid': injected_pid,
+ 'tid': 0,
+ 'ph': END_PHASE,
+ 'cat': 'injected',
+ 'name': name,
+ 'id': slice_id,
+ 'ts': max_timestamp
+ }
+ ])
+
+ return injected_events
+
+
+def MergeGenericTraceComponents(component_name, components_by_filename):
+ """Merge a generic component of multiple JSON traces into a single component.
+
+ This function is only used for components that don't have a component-specific
+ merging function (see MergeTraceEvents). It just returns the component's first
+ provided value (in some trace).
+ """
+ components = components_by_filename.values()
+ first_component = next(components)
+ if not all(c == first_component for c in components):
+ logging.warning(
+ 'Values of trace component %r differ across the provided traces. '
+ 'The first defined value of the component will be used.',
+ component_name)
+ return first_component
+
+
+def Main(argv):
+ parser = argparse.ArgumentParser(description='Merge multiple traces.',
+ add_help=False)
+ parser.add_argument('input_traces', metavar='INPUT_TRACE', nargs='+',
+ help='Input trace filename.')
+ parser.add_argument('-h', '--help', action='help',
+ help='Show this help message and exit.')
+ parser.add_argument('-o', '--output_trace', help='Output trace filename. If '
+ 'not provided, the merged trace will be written to '
+ 'the standard output.')
+ parser.add_argument('-v', '--verbose', action='count', dest='verbosity',
+ help='Increase verbosity level.')
+ args = parser.parse_args(argv[1:])
+
+ # Set verbosity level.
+ if args.verbosity >= 2:
+ logging_level = logging.DEBUG
+ elif args.verbosity == 1:
+ logging_level = logging.INFO
+ else:
+ logging_level = logging.WARNING
+ logging.getLogger().setLevel(logging_level)
+
+ try:
+ MergeTraceFiles(args.input_traces, args.output_trace)
+ return 0
+ except Exception: # pylint: disable=broad-except
+ logging.exception('Something went wrong:')
+ return 1
+ finally:
+ logging.warning('This is an EXPERIMENTAL TOOL! If you encounter any '
+ 'issues, please file a Catapult bug '
+ '(https://github.com/catapult-project/catapult/issues/new) '
+ 'with your current Catapult commit hash, a description of '
+ 'the problem and any error messages, attach the input '
+ 'traces and notify petrcermak@chromium.org. Thank you!')
diff --git a/chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py
new file mode 100644
index 00000000000..f036fcd718e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/merge_traces_unittest.py
@@ -0,0 +1,48 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+from tracing.trace_data import trace_data
+if sys.version_info < (3,):
+ from tracing_build import merge_traces
+
+
+def _FakeDumpEvent(pid, tid):
+ return {'ph': 'v', 'ts': 100, 'pid': pid, 'tid': tid, 'args': {'dumps': {}}}
+
+
+@unittest.skipIf(sys.version_info >= (3,),
+ 'py_vulcanize is not ported to python3')
+class MergeTracesTest(unittest.TestCase):
+ def setUp(self):
+ self.test_dir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self.test_dir)
+
+ def _SerializeTrace(self, filename, trace):
+ filepath = os.path.join(self.test_dir, filename)
+ ri = trace_data.CreateTraceDataFromRawData(trace)
+ ri.Serialize(filepath)
+ return filepath
+
+ def testSimple(self):
+ """Simple integration test for the main MergeTraceFiles function."""
+ trace1 = self._SerializeTrace(
+ 'trace1.html', {'traceEvents': [_FakeDumpEvent(pid=1, tid=3)]})
+ trace2 = self._SerializeTrace(
+ 'trace2.html', {'traceEvents': [_FakeDumpEvent(pid=2, tid=4)]})
+ merged = os.path.join(self.test_dir, 'merged.json')
+ merge_traces.MergeTraceFiles([trace1, trace2], merged)
+ with open(merged) as f:
+ events = json.load(f)['traceEvents']
+ # Check that both dumps are found in the merged trace.
+ dump_pids = [e['pid'] for e in events if e['ph'] == 'v']
+ self.assertEquals([1, 2], dump_pids)
diff --git a/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py b/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py
new file mode 100644
index 00000000000..a5ad91a4e20
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer.py
@@ -0,0 +1,81 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import logging
+import re
+
+_DATA_START = '<div id="histogram-json-data" style="display:none;"><!--'
+_DATA_END = '--!></div>'
+
+
+def ExtractJSON(results_html):
+ results = []
+ flags = re.MULTILINE | re.DOTALL
+ start = re.search("^%s" % re.escape(_DATA_START), results_html, flags)
+ if start is None:
+ logging.warn('Could not find histogram data start: %s', _DATA_START)
+ return []
+ pattern = '^((%s)|(.*?))$' % re.escape(_DATA_END)
+ # Find newlines and parse each line as separate JSON data.
+ for match in re.compile(pattern, flags).finditer(results_html, start.end()+1):
+ try:
+ # Check if the end tag in group(2) got a match.
+ if match.group(2):
+ return results
+ results.append(json.loads(match.group(3)))
+ except ValueError:
+ logging.warn(
+ 'Found existing results json, but failed to parse it: %s',
+ match.group(1))
+ return []
+ return results
+
+
+def ReadExistingResults(results_html):
+ if not results_html:
+ return []
+
+ histogram_dicts = ExtractJSON(results_html)
+
+ if not histogram_dicts:
+ logging.warn('Failed to extract previous results from HTML output')
+ return histogram_dicts
+
+
+def RenderHistogramsViewer(histogram_dicts, output_stream, reset_results=False,
+ vulcanized_html=''):
+ """Renders a Histograms viewer to output_stream containing histogram_dicts.
+
+ Requires a Histograms viewer to have already been vulcanized.
+ The vulcanized viewer can be provided either as a string or a file.
+
+ Args:
+ histogram_dicts: list of dictionaries containing Histograms.
+ output_stream: file-like stream to read existing results and write HTML.
+ reset_results: whether to drop existing results.
+ vulcanized_html: HTML string of vulcanized histograms viewer.
+ """
+ output_stream.seek(0)
+
+ if not reset_results:
+ results_html = output_stream.read()
+ output_stream.seek(0)
+ histogram_dicts += ReadExistingResults(results_html)
+
+ output_stream.write(vulcanized_html)
+ # Put all the serialized histograms nodes inside an html comment to avoid
+ # unecessary stress on html parsing and avoid creating throw-away dom nodes.
+ output_stream.write(_DATA_START)
+ for histogram in histogram_dicts:
+ hist_json = json.dumps(histogram, separators=(',', ':'))
+ output_stream.write('\n')
+ # No escaping is necessary since the data is stored inside an html comment.
+ # This assumes that {hist_json} doesn't contain an html comment itself.
+ output_stream.write(hist_json)
+ output_stream.write('\n%s\n' % _DATA_END)
+
+ # If the output file already existed and was longer than the new contents,
+ # discard the old contents after this point.
+ output_stream.truncate()
diff --git a/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py
new file mode 100644
index 00000000000..48c8dcbe33e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/render_histograms_viewer_unittest.py
@@ -0,0 +1,95 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import codecs
+import json
+import unittest
+import os
+import tempfile
+
+from tracing_build import render_histograms_viewer
+
+
+class ResultsRendererTest(unittest.TestCase):
+
+ # Renamed between Python 2 and Python 3.
+ try:
+ assertCountEqual = unittest.TestCase.assertItemsEqual
+ except AttributeError:
+ pass
+
+ def setUp(self):
+ tmp = tempfile.NamedTemporaryFile(delete=False)
+ tmp.close()
+ self.output_file = tmp.name
+ self.output_stream = codecs.open(self.output_file,
+ mode='r+',
+ encoding='utf-8')
+
+ def GetOutputFileContent(self):
+ self.output_stream.seek(0)
+ return self.output_stream.read()
+
+ def tearDown(self):
+ self.output_stream.close()
+ os.remove(self.output_file)
+
+ def testBasic(self):
+ value0 = {'foo': 0}
+ value0_json = json.dumps(value0, separators=(',', ':'))
+
+ render_histograms_viewer.RenderHistogramsViewer(
+ [], self.output_stream, False)
+ self.output_stream.seek(0)
+ self.assertCountEqual([], render_histograms_viewer.ReadExistingResults(
+ self.output_stream.read()))
+ render_histograms_viewer.RenderHistogramsViewer(
+ [value0], self.output_stream, False)
+ self.output_stream.seek(0)
+ self.assertCountEqual(
+ [value0],
+ render_histograms_viewer.ReadExistingResults(self.output_stream.read()))
+ self.assertIn(value0_json, self.GetOutputFileContent())
+
+ def testExistingResults(self):
+ value0 = {'foo': 0}
+ value0_json = json.dumps(value0, separators=(',', ':'))
+
+ value1 = {'bar': 1}
+ value1_json = json.dumps(value1, separators=(',', ':'))
+
+ render_histograms_viewer.RenderHistogramsViewer(
+ [value0], self.output_stream, False)
+ render_histograms_viewer.RenderHistogramsViewer(
+ [value1], self.output_stream, False)
+ self.output_stream.seek(0)
+ self.assertCountEqual(
+ [value0, value1],
+ render_histograms_viewer.ReadExistingResults(self.output_stream.read()))
+ self.assertIn(value0_json, self.GetOutputFileContent())
+ self.assertIn(value1_json, self.GetOutputFileContent())
+
+ def testExistingResultsReset(self):
+ value0 = {'foo': 0}
+ value0_json = json.dumps(value0, separators=(',', ':'))
+
+ value1 = {'bar': 1}
+ value1_json = json.dumps(value1, separators=(',', ':'))
+
+ render_histograms_viewer.RenderHistogramsViewer(
+ [value0], self.output_stream, False)
+ render_histograms_viewer.RenderHistogramsViewer(
+ [value1], self.output_stream, True)
+ self.output_stream.seek(0)
+ self.assertCountEqual(
+ [value1],
+ render_histograms_viewer.ReadExistingResults(self.output_stream.read()))
+ self.assertNotIn(value0_json, self.GetOutputFileContent())
+ self.assertIn(value1_json, self.GetOutputFileContent())
+
+ def testHtmlEscape(self):
+ # No escaping is needed since data is stored in an html comment.
+ render_histograms_viewer.RenderHistogramsViewer(
+ [{'name': '<a><b>'}], self.output_stream, False)
+ self.assertIn('<a><b>', self.GetOutputFileContent())
diff --git a/chromium/third_party/catapult/tracing/tracing_build/run_profile.py b/chromium/third_party/catapult/tracing/tracing_build/run_profile.py
new file mode 100644
index 00000000000..458f8f5f453
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/run_profile.py
@@ -0,0 +1,67 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import argparse
+import cProfile
+import pstats
+import inspect
+import sys
+
+try:
+ from StringIO import StringIO
+except ImportError:
+ from io import StringIO
+
+
+class Bench(object):
+
+ def SetUp(self):
+ pass
+
+ def Run(self):
+ pass
+
+ def TearDown(self):
+ pass
+
+
+def Main(args):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--repeat-count', type=int, default=10)
+ parser.add_argument('bench_name')
+ args = parser.parse_args(args)
+
+ benches = [g for g in globals().values()
+ if g != Bench and inspect.isclass(g) and
+ Bench in inspect.getmro(g)]
+
+ # pylint: disable=undefined-loop-variable
+ b = [b for b in benches if b.__name__ == args.bench_name]
+ if len(b) != 1:
+ sys.stderr.write('Bench %r not found.' % args.bench_name)
+ return 1
+
+ bench = b[0]()
+ bench.SetUp()
+ try:
+ pr = cProfile.Profile()
+ pr.enable(builtins=False)
+ for _ in range(args.repeat_count):
+ bench.Run()
+ pr.disable()
+ s = StringIO()
+
+ sortby = 'cumulative'
+ ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
+ ps.print_stats()
+ print(s.getvalue())
+ return 0
+ finally:
+ bench.TearDown()
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
diff --git a/chromium/third_party/catapult/tracing/tracing_build/run_vinn_tests.py b/chromium/third_party/catapult/tracing/tracing_build/run_vinn_tests.py
new file mode 100644
index 00000000000..f8c79e0de35
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/run_vinn_tests.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import sys
+
+from hooks import install
+import tracing_project
+import vinn
+
+
+def _RelPathToUnixPath(p):
+ return p.replace(os.sep, '/')
+
+
+def RunTests():
+ project = tracing_project.TracingProject()
+ headless_test_module_filenames = [
+ '/' + _RelPathToUnixPath(x)
+ for x in project.FindAllD8TestModuleRelPaths()]
+ headless_test_module_filenames.sort()
+
+ cmd = """
+ HTMLImportsLoader.loadHTML('/tracing/base/headless_tests.html');
+ tr.b.unittest.loadAndRunTests(sys.argv.slice(1));
+ """
+ res = vinn.RunJsString(
+ cmd, source_paths=list(project.source_paths),
+ js_args=headless_test_module_filenames,
+ stdout=sys.stdout, stdin=sys.stdin)
+ return res.returncode
+
+
+def Main(argv):
+ parser = argparse.ArgumentParser(
+ description='Run d8 tests.')
+ parser.add_argument(
+ '--no-install-hooks', dest='install_hooks', action='store_false')
+ parser.set_defaults(install_hooks=True)
+ args = parser.parse_args(argv[1:])
+ if args.install_hooks:
+ install.InstallHooks()
+
+ sys.exit(RunTests())
diff --git a/chromium/third_party/catapult/tracing/tracing_build/slim_trace.py b/chromium/third_party/catapult/tracing/tracing_build/slim_trace.py
new file mode 100644
index 00000000000..44c2737ea91
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/slim_trace.py
@@ -0,0 +1,112 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import codecs
+import json
+import os
+import logging
+
+
+from tracing_build import html2trace
+from tracing_build import trace2html
+
+
+def GetFileSizeInMb(path):
+ return os.path.getsize(path) >> 20
+
+
+def Main(argv):
+ parser = argparse.ArgumentParser(
+ description='Slim a trace to a more managable size')
+ parser.add_argument('trace_path', metavar='TRACE_PATH', type=str,
+ help='trace file path (input).')
+ options = parser.parse_args(argv[1:])
+
+ trace_path = os.path.abspath(options.trace_path)
+
+ orignal_trace_name = os.path.splitext(os.path.basename(trace_path))[0]
+ slimmed_trace_path = os.path.join(
+ os.path.dirname(trace_path), 'slimmed_%s.html' % orignal_trace_name)
+
+ with codecs.open(trace_path, mode='r', encoding='utf-8') as f:
+ SlimTrace(f, slimmed_trace_path)
+
+ print('Original trace %s (%s Mb)' % (
+ trace_path, GetFileSizeInMb(trace_path)))
+ print('Slimmed trace file://%s (%s Mb)' % (
+ slimmed_trace_path, GetFileSizeInMb(slimmed_trace_path)))
+
+def SlimTraceEventsList(events_list):
+ filtered_events = []
+ # Filter out all events of phase complete that takes less than 20
+ # microseconds.
+ for e in events_list:
+ dur = e.get('dur', 0)
+ if e['ph'] != 'X' or dur >= 20:
+ filtered_events.append(e)
+ return filtered_events
+
+
+def SlimSingleTrace(trace_data):
+ if isinstance(trace_data, dict):
+ trace_data['traceEvents'] = SlimTraceEventsList(trace_data['traceEvents'])
+ elif isinstance(trace_data, list) and isinstance(trace_data[0], dict):
+ trace_data = SlimTraceEventsList(trace_data)
+ else:
+ logging.warning('Cannot slim trace %s...', trace_data[:10])
+ return trace_data
+
+
+class TraceExtractor(object):
+ def CanExtractFile(self, trace_file_handle):
+ raise NotImplementedError
+
+ def ExtractTracesFromFile(self, trace_file_handle):
+ raise NotImplementedError
+
+
+class HTMLTraceExtractor(TraceExtractor):
+ def CanExtractFile(self, trace_file_handle):
+ return html2trace.IsHTMLTrace(trace_file_handle)
+
+ def ExtractTracesFromFile(self, trace_file_handle):
+ return html2trace.ReadTracesFromHTMLFile(trace_file_handle)
+
+
+class JsonTraceExtractor(TraceExtractor):
+ def CanExtractFile(self, trace_file_handle):
+ trace_file_handle.seek(0)
+ begin_char = trace_file_handle.read(1)
+ trace_file_handle.seek(-1, 2)
+ end_char = trace_file_handle.read(1)
+ return ((begin_char == '{' and end_char == '}') or
+ (begin_char == '[' and end_char == ']'))
+
+ def ExtractTracesFromFile(self, trace_file_handle):
+ trace_file_handle.seek(0)
+ return [json.load(trace_file_handle)]
+
+
+ALL_TRACE_EXTRACTORS = [
+ HTMLTraceExtractor(),
+ JsonTraceExtractor()
+]
+
+
+def SlimTrace(trace_file_handle, slimmed_trace_path):
+ traces = None
+ for extractor in ALL_TRACE_EXTRACTORS:
+ if extractor.CanExtractFile(trace_file_handle):
+ traces = extractor.ExtractTracesFromFile(trace_file_handle)
+ break
+
+ if traces is None:
+ raise Exception('Cannot extrac trace from %s' % trace_file_handle.name)
+
+ slimmed_traces = map(SlimSingleTrace, traces)
+
+ with codecs.open(slimmed_trace_path, mode='w', encoding='utf-8') as f:
+ trace2html.WriteHTMLForTraceDataToFile(
+ slimmed_traces, title='', output_file=f)
diff --git a/chromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py b/chromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py
new file mode 100755
index 00000000000..4e897727f3e
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/strip_memory_infra_trace.py
@@ -0,0 +1,102 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Filters a big trace keeping only the last memory-infra dumps."""
+
+from __future__ import print_function
+
+import collections
+import gzip
+import json
+
+
+def FormatBytes(value):
+ units = ['B', 'KiB', 'MiB', 'GiB']
+ while abs(value) >= 1024 and len(units) > 1:
+ value /= 1024
+ units = units.pop(0)
+ return '%3.1f %s' % (value, units[0])
+
+
+def Main(argv):
+ if len(argv) < 2:
+ print('Usage: %s trace.json[.gz]' % argv[0])
+ return 1
+
+ in_path = argv[1]
+ if in_path.lower().endswith('.gz'):
+ fin = gzip.open(in_path, 'rb')
+ else:
+ fin = open(in_path, 'r')
+ with fin:
+ print('Loading trace (can take 1 min on a z620 for a 1GB trace)...')
+ trace = json.load(fin)
+ print('Done. Read ' + FormatBytes(fin.tell()))
+
+ print('Filtering events')
+ phase_count = collections.defaultdict(int)
+ out_events = []
+ global_dumps = collections.OrderedDict()
+ if isinstance(trace, dict):
+ in_events = trace.get('traceEvents', [])
+ elif isinstance(trace, list) and isinstance(trace[0], dict):
+ in_events = trace
+
+ for evt in in_events:
+ phase = evt.get('ph', '?')
+ phase_count[phase] += 1
+
+ # Drop all diagnostic events for memory-infra debugging.
+ if phase not in ('v', 'V') and evt.get('cat', '').endswith('memory-infra'):
+ continue
+
+ # pass-through all the other non-memory-infra events
+ if phase != 'v':
+ out_events.append(evt)
+ continue
+
+ # Recreate the global dump groups
+ event_id = evt['id']
+ global_dumps.setdefault(event_id, [])
+ global_dumps[event_id].append(evt)
+
+
+ print('Detected %d memory-infra global dumps' % len(global_dumps))
+ if global_dumps:
+ max_procs = max(len(x) for x in global_dumps.values())
+ print('Max number of processes seen: %d' % max_procs)
+
+ ndumps = 2
+ print('Preserving the last %d memory-infra dumps' % ndumps)
+ detailed_dumps = []
+ non_detailed_dumps = []
+ for global_dump in global_dumps.values():
+ try:
+ level_of_detail = global_dump[0]['args']['dumps']['level_of_detail']
+ except KeyError:
+ level_of_detail = None
+ if level_of_detail == 'detailed':
+ detailed_dumps.append(global_dump)
+ else:
+ non_detailed_dumps.append(global_dump)
+
+ dumps_to_preserve = detailed_dumps[-ndumps:]
+ ndumps -= len(dumps_to_preserve)
+ if ndumps:
+ dumps_to_preserve += non_detailed_dumps[-ndumps:]
+
+ for global_dump in dumps_to_preserve:
+ out_events += global_dump
+
+ print('\nEvents histogram for the original trace (count by phase)')
+ print('--------------------------------------------------------')
+ for phase, count in sorted(phase_count.items(), key=lambda x: x[1]):
+ print('%s %d' % (phase, count))
+
+ out_path = in_path.split('.json')[0] + '-filtered.json'
+ print('\nWriting filtered trace to ' + out_path, end='')
+ with open(out_path, 'w') as fout:
+ json.dump({'traceEvents': out_events}, fout)
+ num_bytes_written = fout.tell()
+ print(' (%s written)' % FormatBytes(num_bytes_written))
diff --git a/chromium/third_party/catapult/tracing/tracing_build/trace2html.py b/chromium/third_party/catapult/tracing/tracing_build/trace2html.py
new file mode 100644
index 00000000000..b26cc2ea0ff
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/trace2html.py
@@ -0,0 +1,128 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import argparse
+import codecs
+import base64
+import gzip
+import io
+import json
+import os
+
+import tracing_project
+
+from py_vulcanize import generate
+
+
+try:
+ StringTypes = basestring
+except NameError:
+ StringTypes = str
+
+
+def Main(argv):
+
+ parser = argparse.ArgumentParser(
+ usage='%(prog)s <options> trace_file1 [trace_file2 ...]',
+ epilog='Takes the provided trace file and produces a standalone HTML\n'
+ 'file that contains both the trace and the trace viewer.')
+
+ project = tracing_project.TracingProject()
+ project.AddConfigNameOptionToParser(parser)
+
+ parser.add_argument(
+ '--output', dest='output',
+ help='Where to put the generated result. If not '
+ 'given, the trace filename is used, with an html suffix.')
+ parser.add_argument(
+ '--quiet', action='store_true',
+ help='Dont print the output file name')
+ parser.add_argument(
+ '--title', type=str,
+ help='The title to put in trace viewer top panel.')
+ parser.add_argument('trace_files', nargs='+')
+ args = parser.parse_args(argv[1:])
+
+ if args.output:
+ output_filename = args.output
+ elif len(args.trace_files) > 1:
+ parser.error('Must specify --output if there are multiple trace files.')
+ else:
+ name_part = os.path.splitext(args.trace_files[0])[0]
+ output_filename = name_part + '.html'
+
+ with codecs.open(output_filename, mode='w', encoding='utf-8') as f:
+ WriteHTMLForTracesToFile(args.trace_files, f, args.title,
+ config_name=args.config_name)
+
+ if not args.quiet:
+ print(output_filename)
+ return 0
+
+
+class ViewerDataScript(generate.ExtraScript):
+
+ def __init__(self, trace_data_string, mime_type):
+ super(ViewerDataScript, self).__init__()
+ self._trace_data_string = trace_data_string
+ self._mime_type = mime_type
+
+ def WriteToFile(self, output_file):
+ output_file.write('<script id="viewer-data" type="%s">\n' % self._mime_type)
+ compressed_trace = io.BytesIO()
+ with gzip.GzipFile(fileobj=compressed_trace, mode='w', mtime=0) as f:
+ f.write(self._trace_data_string)
+ b64_content = base64.b64encode(compressed_trace.getvalue())
+ output_file.write(b64_content)
+ output_file.write('\n</script>\n')
+
+
+def WriteHTMLForTraceDataToFile(trace_data_list,
+ title, output_file,
+ config_name=None):
+ project = tracing_project.TracingProject()
+
+ if config_name is None:
+ config_name = project.GetDefaultConfigName()
+
+ modules = [
+ 'tracing.trace2html',
+ project.GetModuleNameForConfigName(config_name),
+ ]
+ vulcanizer = project.CreateVulcanizer()
+ load_sequence = vulcanizer.CalcLoadSequenceForModuleNames(modules)
+
+ scripts = []
+ for trace_data in trace_data_list:
+ # If the object was previously decoded from valid JSON data (e.g., in
+ # WriteHTMLForTracesToFile), it will be a JSON object at this point and we
+ # should re-serialize it into a string. Other types of data will be already
+ # be strings.
+ if not isinstance(trace_data, StringTypes):
+ trace_data = json.dumps(trace_data)
+ mime_type = 'application/json'
+ else:
+ mime_type = 'text/plain'
+ scripts.append(ViewerDataScript(trace_data, mime_type))
+ generate.GenerateStandaloneHTMLToFile(
+ output_file, load_sequence, title, extra_scripts=scripts)
+
+
+def WriteHTMLForTracesToFile(trace_filenames, output_file, title='',
+ config_name=None):
+ trace_data_list = []
+ for filename in trace_filenames:
+ try:
+ with gzip.GzipFile(filename, 'r') as f:
+ # If filename is not gzipped, then read() will raise IOError.
+ trace_data = f.read()
+ except IOError:
+ with open(filename, 'r') as f:
+ trace_data = f.read()
+ trace_data_list.append(trace_data)
+ if not title:
+ title = "Trace from %s" % ','.join(trace_filenames)
+ WriteHTMLForTraceDataToFile(trace_data_list, title, output_file, config_name)
diff --git a/chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py
new file mode 100644
index 00000000000..b0d07b02801
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/trace2html_unittest.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import codecs
+import gzip
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+if sys.version_info < (3,):
+ from tracing_build import trace2html
+
+
+@unittest.skipIf(sys.version_info >= (3,),
+ 'py_vulcanize is not ported to python3')
+class Trace2HTMLTests(unittest.TestCase):
+ SIMPLE_TRACE_PATH = os.path.join(
+ os.path.dirname(__file__),
+ '..', 'test_data', 'simple_trace.json')
+ BIG_TRACE_PATH = os.path.join(
+ os.path.dirname(__file__),
+ '..', 'test_data', 'big_trace.json')
+ NON_JSON_TRACE_PATH = os.path.join(
+ os.path.dirname(__file__),
+ '..', 'test_data', 'android_systrace.txt')
+
+ def setUp(self):
+ self._tmpdir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self._tmpdir, ignore_errors=True)
+
+ def testGzippedTraceIsntDoubleGzipped(self):
+ # |input_filename| will contain plain JSON data at one point, then gzipped
+ # JSON data at another point for reasons that will be explained below.
+ input_filename = os.path.join(self._tmpdir, 'GzippedTraceIsntDoubleGzipped')
+
+ output_filename = os.path.join(
+ self._tmpdir, 'GzippedTraceIsntDoubleGzipped.html')
+
+ # trace2html-ify SIMPLE_TRACE, but from a controlled input filename so
+ # that when ViewerDataScript gzips it, it uses the same filename for both
+ # the unzipped SIMPLE_TRACE here and the gzipped SIMPLE_TRACE below.
+ file(input_filename, 'w').write(file(self.SIMPLE_TRACE_PATH).read())
+ with codecs.open(output_filename, 'w', encoding='utf-8') as output_file:
+ trace2html.WriteHTMLForTracesToFile([input_filename], output_file)
+
+ # Hash the contents of the output file that was generated from an unzipped
+ # json input file.
+ unzipped_hash = hash(file(output_filename).read())
+
+ os.unlink(output_filename)
+
+ # Gzip SIMPLE_TRACE into |input_filename|.
+ # trace2html should automatically gunzip it and start building the html from
+ # the same input as if the input weren't gzipped.
+ with gzip.GzipFile(input_filename, mode='w') as input_gzipfile:
+ input_gzipfile.write(file(self.SIMPLE_TRACE_PATH).read())
+
+ # trace2html-ify the zipped version of SIMPLE_TRACE from the same input
+ # filename as the unzipped version so that the gzipping process is stable.
+ with codecs.open(output_filename, 'w', encoding='utf-8') as output_file:
+ trace2html.WriteHTMLForTracesToFile([input_filename], output_file)
+
+ # Hash the contents of the output file that was generated from the zipped
+ # json input file.
+ zipped_hash = hash(file(output_filename).read())
+
+ # Compare the hashes, not the file contents directly so that, if they are
+ # different, python shouldn't try to print megabytes of html.
+ self.assertEqual(unzipped_hash, zipped_hash)
+
+ def testWriteHTMLForTracesToFile(self):
+ output_filename = os.path.join(
+ self._tmpdir, 'WriteHTMLForTracesToFile.html')
+ with codecs.open(output_filename, 'w', encoding='utf-8') as output_file:
+ trace2html.WriteHTMLForTracesToFile([
+ self.BIG_TRACE_PATH,
+ self.SIMPLE_TRACE_PATH,
+ self.NON_JSON_TRACE_PATH
+ ], output_file)
diff --git a/chromium/third_party/catapult/tracing/tracing_build/tracing_dev_server_config.py b/chromium/third_party/catapult/tracing/tracing_build/tracing_dev_server_config.py
new file mode 100644
index 00000000000..fcd0a1a9f1f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/tracing_dev_server_config.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+
+import tracing_project
+
+
+import webapp2
+from webapp2 import Route
+
+
+def _RelPathToUnixPath(p):
+ return p.replace(os.sep, '/')
+
+
+class TestListHandler(webapp2.RequestHandler):
+
+ def get(self, *args, **kwargs): # pylint: disable=unused-argument
+ project = tracing_project.TracingProject()
+ test_relpaths = ['/' + _RelPathToUnixPath(x)
+ for x in project.FindAllTestModuleRelPaths()]
+
+ tests = {'test_relpaths': test_relpaths}
+ tests_as_json = json.dumps(tests)
+ self.response.content_type = 'application/json'
+ return self.response.write(tests_as_json)
+
+
+class TracingDevServerConfig(object):
+
+ def __init__(self):
+ self.project = tracing_project.TracingProject()
+
+ def GetName(self):
+ return 'tracing'
+
+ def GetRunUnitTestsUrl(self):
+ return '/tracing/tests.html'
+
+ def AddOptionstToArgParseGroup(self, g):
+ g.add_argument('-d', '--data-dir', default=self.project.test_data_path)
+ g.add_argument('-s', '--skp-data-dir', default=self.project.skp_data_path)
+
+ def GetRoutes(self, args): # pylint: disable=unused-argument
+ return [Route('/tracing/tests', TestListHandler)]
+
+ def GetSourcePaths(self, args): # pylint: disable=unused-argument
+ return list(self.project.source_paths)
+
+ def GetTestDataPaths(self, args): # pylint: disable=unused-argument
+ return [
+ ('/tracing/test_data/', os.path.expanduser(args.data_dir)),
+ ('/tracing/skp_data/', os.path.expanduser(args.skp_data_dir)),
+ ]
diff --git a/chromium/third_party/catapult/tracing/tracing_build/update_gni.py b/chromium/third_party/catapult/tracing/tracing_build/update_gni.py
new file mode 100644
index 00000000000..e31487831c7
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/update_gni.py
@@ -0,0 +1,123 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import os
+import re
+
+import tracing_project
+from tracing_build import check_common
+
+
+class _Token(object):
+
+ def __init__(self, data, token_id=None):
+ self.data = data
+ if token_id:
+ self.token_id = token_id
+ else:
+ self.token_id = 'plain'
+
+
+class BuildFile(object):
+
+ def __init__(self, text, file_groups):
+ self._file_groups = file_groups
+ self._tokens = [token for token in self._Tokenize(text)]
+
+ def _Tokenize(self, text):
+ rest = text
+ token_regex = self._TokenRegex()
+ while len(rest):
+ m = token_regex.search(rest)
+ if not m:
+ # In `rest', we couldn't find a match.
+ # So, lump the entire `rest' into a token
+ # and stop producing any more tokens.
+ yield _Token(rest)
+ return
+ min_index, end_index, matched_token = self._ProcessMatch(m)
+
+ if min_index > 0:
+ yield _Token(rest[:min_index])
+
+ yield matched_token
+ rest = rest[end_index:]
+
+ def Update(self, files_by_group):
+ for token in self._tokens:
+ if token.token_id in files_by_group:
+ token.data = self._GetReplacementListAsString(
+ token.data,
+ files_by_group[token.token_id])
+
+ def Write(self, f):
+ for token in self._tokens:
+ f.write(token.data)
+
+ def _ProcessMatch(self, match):
+ raise NotImplementedError
+
+ def _TokenRegex(self):
+ raise NotImplementedError
+
+ def _GetReplacementListAsString(self, existing_list_as_string, filelist):
+ raise NotImplementedError
+
+
+class GniFile(BuildFile):
+
+ def _ProcessMatch(self, match):
+ min_index = match.start(2)
+ end_index = match.end(2)
+ token = _Token(match.string[min_index:end_index],
+ token_id=match.groups()[0])
+ return min_index, end_index, token
+
+ def _TokenRegex(self):
+ # regexp to match the following:
+ # file_group_name = [
+ # "path/to/one/file.extension",
+ # "another/file.ex",
+ # ]
+ # In the match,
+ # group 1 is : 'file_group_name'
+ # group 2 is : ' "path/to/one/file.extension",\n "another/file.ex",\n'
+ regexp_str = r'(%s) = \[\n(.+?) +\],?\n' % '|'.join(self._file_groups)
+ return re.compile(regexp_str, re.MULTILINE | re.DOTALL)
+
+ def _GetReplacementListAsString(self, existing_list_as_string, filelist):
+ list_entry = existing_list_as_string.splitlines()[0]
+ prefix, _, suffix = list_entry.split('"')
+ return ''.join(['"'.join([prefix, filename, suffix + '\n'])
+ for filename in filelist])
+
+
+def _GroupFiles(file_name_to_group_name_func, filenames):
+ file_groups = collections.defaultdict(lambda: [])
+ for filename in filenames:
+ file_groups[file_name_to_group_name_func(filename)].append(filename)
+ for group in file_groups:
+ file_groups[group].sort()
+ return file_groups
+
+
+def _UpdateBuildFile(filename, build_file_class):
+ with open(filename, 'r') as f:
+ build_file = build_file_class(f.read(), check_common.FILE_GROUPS)
+ files_by_group = _GroupFiles(check_common.GetFileGroupFromFileName,
+ check_common.GetKnownFiles())
+ build_file.Update(files_by_group)
+ with open(filename, 'w') as f:
+ build_file.Write(f)
+
+
+def UpdateGni():
+ tvp = tracing_project.TracingProject()
+ _UpdateBuildFile(
+ os.path.join(tvp.tracing_root_path, 'trace_viewer.gni'), GniFile)
+
+
+def Update():
+ UpdateGni()
diff --git a/chromium/third_party/catapult/tracing/tracing_build/update_gni_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/update_gni_unittest.py
new file mode 100644
index 00000000000..049e9749442
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/update_gni_unittest.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from tracing_build.update_gni import GniFile
+
+
+class UpdateGniTests(unittest.TestCase):
+
+ def setUp(self):
+ self.file_groups = ['group1', 'group2']
+
+ def testGniTokenizer(self):
+ content = ("useless data\ngroup1 = [\n <file list goes here>\n"
+ " ]\nNote the four spaces before the ] above")
+ gni_files = GniFile(content, self.file_groups)
+ self.assertEqual(3, len(gni_files._tokens))
+ self.assertEqual('plain', gni_files._tokens[0].token_id)
+ self.assertEqual(
+ "useless data\ngroup1 = [\n", gni_files._tokens[0].data)
+ self.assertEqual('group1', gni_files._tokens[1].token_id)
+ self.assertEqual(" <file list goes here>\n", gni_files._tokens[1].data)
+ self.assertEqual('plain', gni_files._tokens[2].token_id)
+ self.assertEqual(
+ " ]\nNote the four spaces before the ] above",
+ gni_files._tokens[2].data)
+
+ def testGniFileListBuilder(self):
+ gni_file = GniFile('', self.file_groups)
+ existing_list = (' "/four/spaces/indent",\n"'
+ ' "/five/spaces/but/only/first/line/matters",\n')
+ new_list = ['item1', 'item2', 'item3']
+ self.assertEqual(
+ ' "item1",\n "item2",\n "item3",\n',
+ gni_file._GetReplacementListAsString(existing_list, new_list))
diff --git a/chromium/third_party/catapult/tracing/tracing_build/vulcanize_histograms_viewer.py b/chromium/third_party/catapult/tracing/tracing_build/vulcanize_histograms_viewer.py
new file mode 100644
index 00000000000..c9d4122c444
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/vulcanize_histograms_viewer.py
@@ -0,0 +1,27 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import tracing_project
+from py_vulcanize import generate
+
+from tracing_build import render_histograms_viewer
+
+
+def VulcanizeHistogramsViewer():
+ """Vulcanizes Histograms viewer with its dependencies.
+
+ Args:
+ path: destination to write the vulcanized viewer HTML.
+ """
+ vulcanizer = tracing_project.TracingProject().CreateVulcanizer()
+ load_sequence = vulcanizer.CalcLoadSequenceForModuleNames(
+ ['tracing_build.histograms_viewer'])
+ return generate.GenerateStandaloneHTMLAsString(load_sequence)
+
+
+def VulcanizeAndRenderHistogramsViewer(
+ histogram_dicts, output_stream, reset_results=False):
+ render_histograms_viewer.RenderHistogramsViewer(
+ histogram_dicts, output_stream, reset_results,
+ VulcanizeHistogramsViewer())
diff --git a/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer.py b/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer.py
new file mode 100644
index 00000000000..ee3404bba80
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer.py
@@ -0,0 +1,114 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import codecs
+import argparse
+import os
+import sys
+
+import tracing_project
+from py_vulcanize import generate
+
+
+def Main(argv):
+
+ parser = argparse.ArgumentParser(
+ usage='%(prog)s <options>',
+ epilog=('Produces a standalone HTML import that contains the\n'
+ 'trace viewer.'))
+
+ project = tracing_project.TracingProject()
+ project.AddConfigNameOptionToParser(parser)
+
+ parser.add_argument('--no-min', default=False, action='store_true',
+ help='skip minification')
+ parser.add_argument('--report-sizes', default=False, action='store_true',
+ help='Explain what makes tracing big.')
+ parser.add_argument('--report-deps', default=False, action='store_true',
+ help='Print a dot-formatted deps graph.')
+ parser.add_argument('--output',
+ help='Where to put the generated result. If not given, '
+ '$TRACING/tracing/bin/trace_viewer.html is used.')
+ parser.add_argument('--generate-js', default=False, action='store_true',
+ help='Produce a js file instead of html.')
+ parser.add_argument('--fully-qualified-config',
+ help='Fully qualified config name.'
+ 'For example: tracing.extras.lean_config_import. '
+ 'Overrides --config-name.')
+ parser.add_argument('--extra-search-paths', nargs='+',
+ help='Extra search paths for script imports.')
+
+ args = parser.parse_args(argv[1:])
+
+ tracing_dir = os.path.relpath(
+ os.path.join(os.path.dirname(__file__), '..', '..'))
+ if args.output:
+ output_filename = args.output
+ else:
+ if args.generate_js:
+ output_suffix = '.js'
+ else:
+ output_suffix = '.html'
+ output_filename = os.path.join(
+ tracing_dir,
+ 'tracing/bin/trace_viewer_%s%s' % (args.config_name, output_suffix))
+
+ print('Writing output to %s' % output_filename)
+ with codecs.open(output_filename, 'w', encoding='utf-8') as f:
+ WriteTraceViewer(
+ f,
+ config_name=args.config_name,
+ minify=not args.no_min,
+ report_sizes=args.report_sizes,
+ report_deps=args.report_deps,
+ generate_js=args.generate_js,
+ fully_qualified_config_name=args.fully_qualified_config,
+ extra_search_paths=args.extra_search_paths)
+
+ return 0
+
+
+def WriteTraceViewer(output_file,
+ config_name=None,
+ minify=False,
+ report_sizes=False,
+ report_deps=False,
+ output_html_head_and_body=True,
+ extra_search_paths=None,
+ extra_module_names_to_load=None,
+ generate_js=False,
+ fully_qualified_config_name=None):
+ project = tracing_project.TracingProject()
+ if extra_search_paths:
+ for p in extra_search_paths:
+ project.source_paths.append(p)
+ if config_name is None:
+ config_name = project.GetDefaultConfigName()
+
+ if fully_qualified_config_name is not None:
+ module_names = [fully_qualified_config_name]
+ else:
+ module_names = [project.GetModuleNameForConfigName(config_name)]
+
+ if extra_module_names_to_load:
+ module_names += extra_module_names_to_load
+
+ vulcanizer = project.CreateVulcanizer()
+ load_sequence = vulcanizer.CalcLoadSequenceForModuleNames(
+ module_names)
+
+ if report_deps:
+ sys.stdout.write(vulcanizer.GetDepsGraphFromModuleNames(module_names))
+
+ if generate_js:
+ generate.GenerateJSToFile(
+ output_file, load_sequence,
+ minify=minify, report_sizes=report_sizes)
+ else:
+ generate.GenerateStandaloneHTMLToFile(
+ output_file, load_sequence,
+ minify=minify, report_sizes=report_sizes,
+ output_html_head_and_body=output_html_head_and_body)
diff --git a/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py b/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py
new file mode 100644
index 00000000000..9d57ed06b96
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_build/vulcanize_trace_viewer_unittest.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import codecs
+import os
+import sys
+import unittest
+import tempfile
+
+if sys.version_info < (3,):
+ from tracing_build import vulcanize_trace_viewer
+
+
+@unittest.skipIf(sys.version_info >= (3,),
+ 'py_vulcanize is not ported to python3')
+class Trace2HTMLTests(unittest.TestCase):
+
+ def testWriteHTMLForTracesToFile(self):
+ try:
+ # Note: We can't use "with" when working with tempfile.NamedTemporaryFile
+ # as that does not work on Windows. We use the longer, more clunky version
+ # instead. See https://bugs.python.org/issue14243 for detials.
+ raw_tmpfile = tempfile.NamedTemporaryFile(
+ mode='w', suffix='.html', delete=False)
+ raw_tmpfile.close()
+ with codecs.open(raw_tmpfile.name, 'w', encoding='utf-8') as tmpfile:
+ vulcanize_trace_viewer.WriteTraceViewer(tmpfile)
+ finally:
+ os.remove(raw_tmpfile.name)
diff --git a/chromium/third_party/catapult/tracing/tracing_examples/chrome_inspect_test_shell.html b/chromium/third_party/catapult/tracing/tracing_examples/chrome_inspect_test_shell.html
new file mode 100644
index 00000000000..3e74a195068
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_examples/chrome_inspect_test_shell.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2011 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+<title>chrome://inspect test shell</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+<link rel="import" href="/tracing/ui/base/base.html">
+<link rel="import" href="/tracing/ui/extras/about_tracing/profiling_view.html">
+<link rel="import" href="/tracing/ui/extras/full_config.html">
+
+<style>
+ body {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ }
+
+ body > x-profiling-view {
+ flex: 1 1 auto;
+ overflow: hidden;
+ position: absolute;
+ top: 0px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ }
+
+</style>
+</head>
+<body>
+ <script>
+ 'use strict';
+
+ let profilingViewEl;
+
+ function onLoad() {
+ if (window.DevToolsHost === undefined) {
+ tr.showPanic(
+ 'This page only works when launched from chrome://inspect',
+ 'Try going to ' +
+ 'chrome://inspect/?browser-inspector=' +
+ 'http://localhost:8003/examples/chrome_inspect_test_shell.html' +
+ '#devices ' +
+ 'and then clicking the inspect link on a browser');
+
+ return;
+ }
+
+ const tracingControllerClient =
+ new tr.ui.e.about_tracing.InspectorTracingControllerClient(
+ new tr.ui.e.about_tracing.InspectorConnection(window));
+ profilingViewEl = new tr.ui.e.about_tracing.ProfilingView(tracingControllerClient); // @suppress longLineCheck
+ document.body.appendChild(profilingViewEl);
+ }
+ window.addEventListener('load', onLoad);
+ </script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/tracing/tracing_examples/deep_reports.html b/chromium/third_party/catapult/tracing/tracing_examples/deep_reports.html
new file mode 100644
index 00000000000..0937ce8b1ab
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_examples/deep_reports.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2015 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+<title>Deep insights via Bulk Trace Analysis</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+<link rel="import" href="/tracing/ui/base/base.html" data-suppress-import-order>
+
+<link rel="import" href="/tracing/ui/extras/deep_reports/html_results.html">
+<link rel="import" href="/tracing/ui/extras/deep_reports/main.html">
+<link rel="import" href="/tracing/ui/extras/full_config.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
+
+<style>
+ body {
+ font-family: sans-serif;
+ }
+</style>
+</head>
+<body>
+ <select id="trace-dir"></select>
+ <tr-ui-e-deep-reports-html-results id="results">
+ </tr-ui-e-deep-reports-html-results>
+
+ <script>
+ 'use strict';
+
+ function onLoad() {
+ tr.b.getAsync('/test_data/__file_list__').then(function(data) {
+ var select = document.querySelector('#trace-file');
+ var allFiles = JSON.parse(data);
+ var filenames = allFiles.filter(function(file) {
+ if (!file.startsWith('measurmt-traces/'))
+ return false;
+ if (file === 'measurmt-traces/README.md')
+ return false;
+ return true;
+ });
+
+ initUI(filenames);
+ });
+ }
+ window.addEventListener('load', onLoad);
+
+ function initUI(files) {
+ // Groups.
+ var filesByDirName = {};
+ files.forEach(function(file) {
+ var rest = /measurmt-traces\/(.+)/.exec(file)[1];
+
+ // Find subdirectories.
+ var m = /(.+?)\/(.*)/.exec(rest);
+ var dirName = m[1];
+ var baseName = m[2];
+ if (baseName === 'rail_expectations.json') {
+ // TODO(nduca): Stash this somewhere else.
+ return;
+ }
+ if (baseName.endsWith('.mp4')) {
+ // TODO(nduca): Stash this somewhere else.
+ return;
+ }
+ if (filesByDirName[dirName] === undefined)
+ filesByDirName[dirName] = [];
+ filesByDirName[dirName].push(file);
+ });
+
+ var selectEl = document.body.querySelector('#trace-dir');
+ selectEl.filesByDirName = filesByDirName;
+
+ for (var [dirName, filesInDir] of Object.entries(filesByDirName)) {
+ var runEl = document.createElement('option');
+ runEl.textContent = dirName + ': ' + filesInDir.length + ' traces';
+ runEl.value = dirName;
+ selectEl.appendChild(runEl);
+ }
+
+ selectEl.selectedIndex = 0;
+ selectEl.addEventListener('change', onSelectionChange);
+ if (!window.location.hash) {
+ // This will trigger an onHashChange so no need to reload directly.
+ window.location.hash = '#' + selectEl[selectEl.selectedIndex].value;
+ } else {
+ onHashChange();
+ }
+ }
+
+ function onSelectionChange() {
+ var selectEl = document.body.querySelector('#trace-dir');
+ window.location.hash = '#' + selectEl[selectEl.selectedIndex].value;
+ }
+
+ function onHashChange() {
+ var file = window.location.hash.substr(1);
+ var selectEl = document.querySelector('#trace-dir');
+ if (selectEl[selectEl.selectedIndex].value !== file) {
+ for (var i = 0; i < selectEl.children.length; i++) {
+ if (selectEl.children[i].value === file) {
+ selectEl.selectedIndex = i;
+ break;
+ }
+ }
+ }
+ reload();
+ }
+ window.addEventListener('hashchange', onHashChange);
+
+ function reload() {
+ var dirName = window.location.hash.substr(1);
+ var selectEl = document.body.querySelector('#trace-dir');
+ var filesInDir = selectEl.filesByDirName[dirName];
+ var results = document.querySelector('#results');
+ results.clear();
+ tr.ui.e.deep_reports.main(results, filesInDir).then(
+ function success() {
+ },
+ function error(err) {
+ tr.showPanic('Error', err);
+ });
+ }
+ </script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/tracing/tracing_examples/metrics_debugger.html b/chromium/third_party/catapult/tracing/tracing_examples/metrics_debugger.html
new file mode 100644
index 00000000000..9cc365fb982
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_examples/metrics_debugger.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Copyright 2016 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+<title>Metrics debugger</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+<link rel="import" href="/components/polymer/polymer.html">
+<link rel="import" href="/tracing/ui/metrics_debugger_app.html">
+
+<style>
+ html,
+ body {
+ box-sizing: border-box;
+ margin: 0px;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+ font-family: sans-serif;
+ }
+</style>
+
+</head>
+<body>
+ <tracing-ui-metrics-debugger-app>
+ </tracing-ui-metrics-debugger-app>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/tracing/tracing_examples/skia_debugger.html b/chromium/third_party/catapult/tracing/tracing_examples/skia_debugger.html
new file mode 100644
index 00000000000..4868ccaffe3
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_examples/skia_debugger.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+<title>Skia Debugger</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+<link rel="import" href="/tracing/base/base64.html">
+<link rel="import" href="/tracing/extras/chrome/cc/picture.html">
+<link rel="import" href="/tracing/ui/base/base.html">
+<link rel="import" href="/tracing/ui/extras/chrome/cc/picture_debugger.html">
+
+<script src="string_convert.js"></script>
+<style>
+ picture-ops-list-view {
+ height: 500px;
+ overflow-y: auto;
+ }
+</style>
+</head>
+<body>
+ <div class="header">
+ <select id="skp_file"></select>
+ </div>
+
+ <div class="view"></div>
+ <script>
+ 'use strict';
+ /* eslint-disable no-console */
+
+ var debuggerEl;
+
+ function getPicture(skp64) {
+ if (!tr.e.cc.PictureSnapshot.CanGetInfo()) {
+ console.error(tr.e.cc.PictureSnapshot.HowToEnablePictureDebugging());
+
+ var infoBar = document.createElement('tr-ui-b-info-bar');
+ var view = document.querySelector('.view');
+
+ view.removeChild(debuggerEl);
+ debuggerEl = undefined;
+
+ view.appendChild(infoBar);
+
+ infoBar.message = tr.e.cc.PictureSnapshot.HowToEnablePictureDebugging();
+ infoBar.visible = true;
+ return undefined;
+ }
+
+ var size = chrome.skiaBenchmarking.getInfo(skp64);
+ if (size === undefined)
+ throw new Error('Unable to get picture information');
+
+ return new tr.e.cc.Picture(skp64,
+ tr.Rect.fromXYWH(0, 0, size.width, size.height),
+ tr.Rect.fromXYWH(0, 0, size.width, size.height));
+ }
+
+ function utf8ToB64(str) {
+ return tr.b.Base64.btoa(unescape(encodeURIComponent(str)));
+ }
+
+ function loadSkp(filename, onSkpLoaded) {
+ getAsync(filename, function(arr) {
+ var view = new Uint8Array(arr);
+ var data = base64EncArr(view, 1);
+ onSkpLoaded(filename, data);
+ }, 'arraybuffer');
+ }
+ function YloadSkp(filename, onSkpLoaded) {
+ getAsync(filename, function(data) {
+ var data64 = utf8ToB64(data);
+ onSkpLoaded(filename, data64);
+ });
+ }
+
+ function getAsync(url, callback, opt_responseType) {
+ var req = new XMLHttpRequest();
+ if (opt_responseType)
+ req.responseType = opt_responseType;
+ req.open('GET', url, true);
+ req.onreadystatechange = function(aEvt) {
+ if (req.readyState === 4) {
+ window.setTimeout(function() {
+ if (req.status === 200) {
+ if (opt_responseType === undefined)
+ callback(req.responseText);
+ else
+ callback(req.response);
+ } else {
+ console.log('Failed to load ' + url);
+ }
+ }, 0);
+ }
+ };
+ req.send(null);
+ }
+
+ function createViewFromSkp(filename, skp) {
+ var p = getPicture(skp);
+ if (p === undefined)
+ return;
+ debuggerEl.picture = p;
+ }
+
+ function onSelectionChange() {
+ var select = document.querySelector('#skp_file');
+ window.location.hash = '#' + select[select.selectedIndex].value;
+ }
+
+ function onHashChange() {
+ var file = window.location.hash.substr(1);
+ var select = document.querySelector('#skp_file');
+ if (select[select.selectedIndex].value !== file) {
+ for (var i = 0; i < select.children.length; i++) {
+ if (select.children[i].value === file) {
+ select.selectedIndex = i;
+ break;
+ }
+ }
+ }
+ reload();
+ }
+
+ function cleanFilename(file) {
+ function upcase(letter) {
+ return ' ' + letter.toUpperCase();
+ }
+ return file.replace(/_/g, ' ')
+ .replace(/\.[^\.]*$/, '')
+ .replace(/ ([a-z])/g, upcase)
+ .replace(/^[a-z]/, upcase);
+ }
+
+ function reload() {
+ var filename = window.location.hash.substr(1);
+ loadSkp(filename, createViewFromSkp);
+ }
+
+ function onLoad() {
+ debuggerEl = new tr.ui.e.chrome.cc.PictureDebugger();
+ document.querySelector('.view').appendChild(debuggerEl);
+
+ getAsync('/skp_data/__file_list__', function(data) {
+ var select = document.querySelector('#skp_file');
+ var files = JSON.parse(data);
+
+ for (var i = 0; i < files.length; ++i) {
+ var opt = document.createElement('option');
+ opt.value = files[i];
+ opt.textContent = cleanFilename(files[i]);
+ select.appendChild(opt);
+ }
+ select.selectedIndex = 0;
+ select.onchange = onSelectionChange;
+
+ if (!window.location.hash) {
+ // This will trigger an onHashChange so no need to reload directly.
+ window.location.hash = '#' + select[select.selectedIndex].value;
+ } else {
+ onHashChange();
+ }
+ });
+ }
+
+ window.addEventListener('hashchange', onHashChange);
+ window.addEventListener('load', onLoad);
+ </script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/tracing/tracing_examples/string_convert.js b/chromium/third_party/catapult/tracing/tracing_examples/string_convert.js
new file mode 100644
index 00000000000..8f532388f1f
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_examples/string_convert.js
@@ -0,0 +1,171 @@
+"use strict";
+
+/*\
+|*|
+|*| Base64 / binary data / UTF-8 strings utilities
+|*|
+|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
+|*|
+\*/
+
+/* Array of bytes to base64 string decoding */
+
+function b64ToUint6 (nChr) {
+
+ return nChr > 64 && nChr < 91 ?
+ nChr - 65
+ : nChr > 96 && nChr < 123 ?
+ nChr - 71
+ : nChr > 47 && nChr < 58 ?
+ nChr + 4
+ : nChr === 43 ?
+ 62
+ : nChr === 47 ?
+ 63
+ :
+ 0;
+
+}
+
+function base64DecToArr (sBase64, nBlocksSize) {
+
+ var
+ sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
+ nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen);
+
+ for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
+ nMod4 = nInIdx & 3;
+ nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
+ if (nMod4 === 3 || nInLen - nInIdx === 1) {
+ for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
+ taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
+ }
+ nUint24 = 0;
+
+ }
+ }
+
+ return taBytes;
+}
+
+/* Base64 string to array encoding */
+
+function uint6ToB64 (nUint6) {
+
+ return nUint6 < 26 ?
+ nUint6 + 65
+ : nUint6 < 52 ?
+ nUint6 + 71
+ : nUint6 < 62 ?
+ nUint6 - 4
+ : nUint6 === 62 ?
+ 43
+ : nUint6 === 63 ?
+ 47
+ :
+ 65;
+
+}
+
+function base64EncArr (aBytes) {
+
+ var nMod3, sB64Enc = "";
+
+ for (var nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
+ nMod3 = nIdx % 3;
+ nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
+ if (nMod3 === 2 || aBytes.length - nIdx === 1) {
+ sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));
+ nUint24 = 0;
+ }
+ }
+
+ return sB64Enc.replace(/A(?=A$|$)/g, "=");
+
+}
+
+/* UTF-8 array to DOMString and vice versa */
+
+function UTF8ArrToStr (aBytes) {
+
+ var sView = "";
+
+ for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
+ nPart = aBytes[nIdx];
+ sView += String.fromCharCode(
+ nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
+ /* (nPart - 252 << 32) is not possible in ECMAScript! So...: */
+ (nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
+ : nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
+ (nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
+ : nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
+ (nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
+ : nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
+ (nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
+ : nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
+ (nPart - 192 << 6) + aBytes[++nIdx] - 128
+ : /* nPart < 127 ? */ /* one byte */
+ nPart
+ );
+ }
+
+ return sView;
+
+}
+
+function strToUTF8Arr (sDOMStr) {
+
+ var aBytes, nChr, nStrLen = sDOMStr.length, nArrLen = 0;
+
+ /* mapping... */
+
+ for (var nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) {
+ nChr = sDOMStr.charCodeAt(nMapIdx);
+ nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6;
+ }
+
+ aBytes = new Uint8Array(nArrLen);
+
+ /* transcription... */
+
+ for (var nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) {
+ nChr = sDOMStr.charCodeAt(nChrIdx);
+ if (nChr < 128) {
+ /* one byte */
+ aBytes[nIdx++] = nChr;
+ } else if (nChr < 0x800) {
+ /* two bytes */
+ aBytes[nIdx++] = 192 + (nChr >>> 6);
+ aBytes[nIdx++] = 128 + (nChr & 63);
+ } else if (nChr < 0x10000) {
+ /* three bytes */
+ aBytes[nIdx++] = 224 + (nChr >>> 12);
+ aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
+ aBytes[nIdx++] = 128 + (nChr & 63);
+ } else if (nChr < 0x200000) {
+ /* four bytes */
+ aBytes[nIdx++] = 240 + (nChr >>> 18);
+ aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
+ aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
+ aBytes[nIdx++] = 128 + (nChr & 63);
+ } else if (nChr < 0x4000000) {
+ /* five bytes */
+ aBytes[nIdx++] = 248 + (nChr >>> 24);
+ aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
+ aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
+ aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
+ aBytes[nIdx++] = 128 + (nChr & 63);
+ } else /* if (nChr <= 0x7fffffff) */ {
+ /* six bytes */
+ aBytes[nIdx++] = 252 + /* (nChr >>> 32) is not possible in ECMAScript! So...: */ (nChr / 1073741824);
+ aBytes[nIdx++] = 128 + (nChr >>> 24 & 63);
+ aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
+ aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
+ aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
+ aBytes[nIdx++] = 128 + (nChr & 63);
+ }
+ }
+
+ return aBytes;
+
+}
diff --git a/chromium/third_party/catapult/tracing/tracing_examples/trace_viewer.html b/chromium/third_party/catapult/tracing/tracing_examples/trace_viewer.html
new file mode 100644
index 00000000000..1749bc126ec
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_examples/trace_viewer.html
@@ -0,0 +1,184 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright (c) 2011 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+<title>Simple Embedded Viewer</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<script src="/components/webcomponentsjs/HTMLImports.js"></script>
+
+<link rel="import" href="/tracing/base/timing.html">
+<link rel="import" href="/tracing/base/xhr.html">
+<link rel="import" href="/tracing/importer/import.html">
+<link rel="import" href="/tracing/ui/extras/full_config.html">
+<link rel="import" href="/tracing/ui/timeline_view.html">
+
+<style>
+ html,
+ body {
+ height: 100%;
+ }
+
+ body {
+ flex-direction: column;
+ display: flex;
+ margin: 0;
+ padding: 0;
+ }
+
+ body > tr-ui-timeline-view {
+ flex: 1 1 auto;
+ min-height: 0;
+ }
+ body > tr-ui-timeline-view:focus {
+ outline: none;
+ }
+</style>
+</head>
+<body>
+ <tr-ui-timeline-view>
+ <track-view-container id='track_view_container'></track-view-container>
+ </tr-ui-timeline-view>
+
+ <script>
+ 'use strict';
+
+ let timelineViewEl;
+ let selectEl;
+
+ function loadTraces(filenames, onTracesLoaded) {
+ const loadTracesMark = tr.b.Timing.mark('TraceImport', 'loadTraces');
+ const traces = [];
+ for (let i = 0; i < filenames.length; i++) {
+ traces.push(undefined);
+ }
+ let numTracesPending = filenames.length;
+
+ filenames.forEach(function(filename, i) {
+ getAsync(filename, function(trace) {
+ traces[i] = trace;
+ numTracesPending--;
+ if (numTracesPending === 0) {
+ loadTracesMark.end();
+ onTracesLoaded(filenames, traces);
+ }
+ });
+ });
+ }
+
+
+ function getAsync(url, cb) {
+ return tr.b.getAsync(url).then(cb);
+ }
+
+ function createViewFromTraces(filenames, traces) {
+ const createViewFromTracesTimer = tr.b.Timing.mark(
+ 'TraceImport', 'createViewFromTraces');
+ const m = new tr.Model();
+
+ const trackDetailedModelStatsEl = tr.ui.b.findDeepElementMatching(
+ document.body, '#track-detailed-model-stats');
+ const importOptions = new tr.importer.ImportOptions();
+ importOptions.trackDetailedModelStats = trackDetailedModelStatsEl.checked;
+ const i = new tr.importer.Import(m, importOptions);
+ const p = i.importTracesWithProgressDialog(traces);
+
+ p.then(
+ function() {
+ timelineViewEl.model = m;
+ timelineViewEl.updateDocumentFavicon();
+ timelineViewEl.globalMode = true;
+ timelineViewEl.viewTitle = '';
+ createViewFromTracesTimer.end();
+ },
+ function(err) {
+ const overlay = new tr.ui.b.Overlay();
+ overlay.textContent = tr.b.normalizeException(err).message;
+ overlay.title = 'Import error';
+ overlay.visible = true;
+ createViewFromTracesTimer.end();
+ });
+ }
+
+ function onSelectionChange() {
+ window.location.hash = '#' + selectEl[selectEl.selectedIndex].value;
+ }
+
+ function onHashChange() {
+ const file = window.location.hash.substr(1);
+ if (selectEl[selectEl.selectedIndex].value !== file) {
+ for (let i = 0; i < selectEl.children.length; i++) {
+ if (selectEl.children[i].value === file) {
+ selectEl.selectedIndex = i;
+ break;
+ }
+ }
+ }
+ reload();
+ }
+
+ function cleanFilename(file) {
+ const m = /\/tracing\/test_data\/(.+)/.exec(file);
+ const rest = m[1];
+
+ function upcase(letter) {
+ return ' ' + letter.toUpperCase();
+ }
+
+ return rest.replace(/_/g, ' ')
+ .replace(/\.[^\.]*$/, '')
+ .replace(/ ([a-z])/g, upcase)
+ .replace(/^[a-z]/, upcase);
+ }
+
+ function reload() {
+ loadTraces([window.location.hash.substr(1)], createViewFromTraces);
+ }
+
+ window.addEventListener('hashchange', onHashChange);
+
+ function onLoad() {
+ const onLoadTimer = tr.b.Timing.mark('TraceImport', 'onLoad');
+ timelineViewEl = document.querySelector('tr-ui-timeline-view');
+ timelineViewEl.globalMode = true;
+
+
+ selectEl = document.createElement('select');
+ timelineViewEl.leftControls.appendChild(selectEl);
+
+ getAsync('/tracing/test_data/__file_list__', function(data) {
+ const files = JSON.parse(data);
+ for (let i = 0; i < files.length; ++i) {
+ const opt = document.createElement('option');
+ opt.value = files[i];
+ opt.textContent = cleanFilename(files[i]);
+ selectEl.appendChild(opt);
+ }
+ selectEl.selectedIndex = 0;
+ selectEl.onchange = onSelectionChange;
+
+ if (!window.location.hash) {
+ // This will trigger an onHashChange so no need to reload directly.
+ window.location.hash = '#' + selectEl[selectEl.selectedIndex].value;
+ } else {
+ onHashChange();
+ }
+ }).then(onLoadTimer.end.call(this));
+
+ const trackDetailedModelStatsEl = tr.ui.b.createCheckBox(
+ this, 'trackDetailedModelStats',
+ 'traceViewer.trackDetailedModelStats', false,
+ 'Detailed file size stats',
+ onHashChange);
+ trackDetailedModelStatsEl.id = 'track-detailed-model-stats';
+ timelineViewEl.leftControls.appendChild(trackDetailedModelStatsEl);
+ }
+
+ window.addEventListener('load', onLoad);
+ window.addEventListener('HTMLImportsLoaded', onLoad);
+ </script>
+</body>
+</html>
diff --git a/chromium/third_party/catapult/tracing/tracing_project.py b/chromium/third_party/catapult/tracing/tracing_project.py
new file mode 100644
index 00000000000..633b98bde92
--- /dev/null
+++ b/chromium/third_party/catapult/tracing/tracing_project.py
@@ -0,0 +1,209 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import os
+import re
+
+
+def _AddToPathIfNeeded(path):
+ if path not in sys.path:
+ sys.path.insert(0, path)
+
+
+def UpdateSysPathIfNeeded():
+ for path in GetDependencyPaths():
+ _AddToPathIfNeeded(path)
+
+
+def GetDependencyPaths():
+ # TODO(#3703): Separate the paths that are only used by the dev server into
+ # another call.
+ p = TracingProject()
+ return [
+ p.catapult_path,
+ p.py_vulcanize_path,
+ p.vinn_path,
+ os.path.join(p.catapult_third_party_path, 'WebOb'),
+ os.path.join(p.catapult_third_party_path, 'Paste'),
+ os.path.join(p.catapult_third_party_path, 'six'),
+ os.path.join(p.catapult_third_party_path, 'webapp2'),
+ os.path.join(p.catapult_path, 'common', 'py_utils'),
+ os.path.join(p.tracing_third_party_path, 'symbols')
+ ]
+
+
+def _FindAllFilesRecursive(source_paths):
+ assert isinstance(source_paths, list)
+ all_filenames = set()
+ for source_path in source_paths:
+ for dirpath, _, filenames in os.walk(source_path):
+ for f in filenames:
+ if f.startswith('.'):
+ continue
+ x = os.path.abspath(os.path.join(dirpath, f))
+ all_filenames.add(x)
+ return all_filenames
+
+def _IsFilenameATest(x):
+ if x.endswith('_test.js'):
+ return True
+
+ if x.endswith('_test.html'):
+ return True
+
+ if x.endswith('_unittest.js'):
+ return True
+
+ if x.endswith('_unittest.html'):
+ return True
+
+ # TODO(nduca): Add content test?
+ return False
+
+
+class TracingProject(object):
+ catapult_path = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), os.path.pardir))
+
+ tracing_root_path = os.path.join(catapult_path, 'tracing')
+ trace_processor_root_path = os.path.join(catapult_path, 'trace_processor')
+ common_root_path = os.path.join(catapult_path, 'common')
+ tracing_src_path = os.path.join(tracing_root_path, 'tracing')
+ extras_path = os.path.join(tracing_src_path, 'extras')
+ ui_extras_path = os.path.join(tracing_src_path, 'ui', 'extras')
+
+ catapult_third_party_path = os.path.join(catapult_path, 'third_party')
+ polymer_path = os.path.join(catapult_third_party_path, 'polymer')
+
+ tracing_third_party_path = os.path.join(tracing_root_path, 'third_party')
+ py_vulcanize_path = os.path.join(common_root_path, 'py_vulcanize')
+ vinn_path = os.path.join(catapult_third_party_path, 'vinn')
+
+ jszip_path = os.path.join(tracing_third_party_path, 'jszip')
+ pako_path = os.path.join(tracing_third_party_path, 'pako')
+
+ glmatrix_path = os.path.join(
+ tracing_third_party_path, 'gl-matrix', 'dist')
+
+ mannwhitneyu_path = os.path.join(
+ tracing_third_party_path, 'mannwhitneyu')
+
+ ui_path = os.path.join(tracing_src_path, 'ui')
+ d3_path = os.path.join(tracing_third_party_path, 'd3')
+ chai_path = os.path.join(tracing_third_party_path, 'chai')
+ mocha_path = os.path.join(tracing_third_party_path, 'mocha')
+ oboe_path = os.path.join(tracing_third_party_path, 'oboe')
+
+ mre_path = os.path.join(tracing_src_path, 'mre')
+
+ metrics_path = os.path.join(tracing_src_path, 'metrics')
+ diagnostics_path = os.path.join(tracing_src_path, 'value', 'diagnostics')
+
+ value_ui_path = os.path.join(tracing_src_path, 'value', 'ui')
+ metrics_ui_path = os.path.join(tracing_src_path, 'metrics', 'ui')
+
+ test_data_path = os.path.join(tracing_root_path, 'test_data')
+ skp_data_path = os.path.join(tracing_root_path, 'skp_data')
+
+ rjsmin_path = os.path.join(
+ tracing_third_party_path, 'tvcm', 'third_party', 'rjsmin')
+ rcssmin_path = os.path.join(
+ tracing_third_party_path, 'tvcm', 'third_party', 'rcssmin')
+
+ def __init__(self):
+ self.source_paths = []
+ self.source_paths.append(self.tracing_root_path)
+ self.source_paths.append(self.polymer_path)
+ self.source_paths.append(self.tracing_third_party_path)
+ self.source_paths.append(self.mre_path)
+ self.source_paths.append(self.jszip_path)
+ self.source_paths.append(self.pako_path)
+ self.source_paths.append(self.glmatrix_path)
+ self.source_paths.append(self.mannwhitneyu_path)
+ self.source_paths.append(self.d3_path)
+ self.source_paths.append(self.chai_path)
+ self.source_paths.append(self.mocha_path)
+ self.source_paths.append(self.oboe_path)
+
+ def CreateVulcanizer(self):
+ from py_vulcanize import project as project_module
+ return project_module.Project(self.source_paths)
+
+ def IsD8CompatibleFile(self, filename):
+ if filename.startswith(self.ui_path):
+ return False
+
+ if filename.startswith(self.value_ui_path):
+ return False
+
+ if filename.startswith(self.metrics_ui_path):
+ return False
+
+ return True
+
+ def FindAllTestModuleRelPaths(self, pred=None):
+ if pred is None:
+ pred = lambda x: True
+
+ all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
+ test_module_filenames = [x for x in all_filenames if
+ _IsFilenameATest(x) and pred(x)]
+ test_module_filenames.sort()
+
+ return [os.path.relpath(x, self.tracing_root_path)
+ for x in test_module_filenames]
+
+ def FindAllMetricsModuleRelPaths(self):
+ all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
+ all_metrics_module_filenames = []
+ for x in all_filenames:
+ if x.startswith(self.metrics_path) and not _IsFilenameATest(x):
+ all_metrics_module_filenames.append(x)
+ all_metrics_module_filenames.sort()
+ return [os.path.relpath(x, self.tracing_root_path)
+ for x in all_metrics_module_filenames]
+
+ def FindAllDiagnosticsModuleRelPaths(self):
+ all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
+ all_diagnostics_module_filenames = []
+ for x in all_filenames:
+ if x.startswith(self.diagnostics_path) and not _IsFilenameATest(x):
+ all_diagnostics_module_filenames.append(x)
+ all_diagnostics_module_filenames.sort()
+ return [os.path.relpath(x, self.tracing_root_path)
+ for x in all_diagnostics_module_filenames]
+
+ def FindAllD8TestModuleRelPaths(self):
+ return self.FindAllTestModuleRelPaths(pred=self.IsD8CompatibleFile)
+
+ def GetConfigNames(self):
+ config_files = [
+ os.path.join(self.ui_extras_path, x)
+ for x in os.listdir(self.ui_extras_path)
+ if x.endswith('_config.html')
+ ]
+
+ config_files = [x for x in config_files if os.path.isfile(x)]
+
+ config_basenames = [os.path.basename(x) for x in config_files]
+ config_names = [re.match('(.+)_config.html$', x).group(1)
+ for x in config_basenames]
+ return config_names
+
+ def GetDefaultConfigName(self):
+ assert 'full' in self.GetConfigNames()
+ return 'full'
+
+ def AddConfigNameOptionToParser(self, parser):
+ choices = self.GetConfigNames()
+ parser.add_argument(
+ '--config', dest='config_name',
+ choices=choices, default=self.GetDefaultConfigName(),
+ help='Picks a browser config. Valid choices: %s' % ', '.join(choices))
+ return choices
+
+ def GetModuleNameForConfigName(self, config_name):
+ return 'tracing.ui.extras.%s_config' % config_name
+
diff --git a/chromium/third_party/chromevox/LICENSE b/chromium/third_party/chromevox/LICENSE
deleted file mode 100644
index 6766c3fe34b..00000000000
--- a/chromium/third_party/chromevox/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
diff --git a/chromium/third_party/chromevox/OWNERS b/chromium/third_party/chromevox/OWNERS
deleted file mode 100644
index 7d496ba2840..00000000000
--- a/chromium/third_party/chromevox/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-aboxhall@chromium.org
-dmazzoni@chromium.org
-dtseng@chromium.org
-plundblad@chromium.org
-
-# TEAM: chromium-accessibility@chromium.org
-# COMPONENT: UI>Accessibility
diff --git a/chromium/third_party/chromevox/README.chromium b/chromium/third_party/chromevox/README.chromium
deleted file mode 100644
index 8702dc1afd3..00000000000
--- a/chromium/third_party/chromevox/README.chromium
+++ /dev/null
@@ -1,16 +0,0 @@
-Name: ChromeVox
-URL: http://code.google.com/p/google-axs-chrome/
-InfoURL: http://www.chromevox.com/
-Version: 1.31.4
-License: Apache 2.0
-Security Critical: Yes
-
-Description:
-ChromeVox is the screen reader for Chrome OS. This directory contains pars of
-ChromeVox that haven't been migrated to
-chrome/browser/resources/chromeos/chromevox.
-
-Local Modifications: ChromeVox lives under trunk/chromevox/ in the upstream
-Google Code repository. The only modification is Chrome uses a different
-manifest. The one checked into the upstream repository should be deleted when
-merging.
diff --git a/chromium/third_party/chromevox/chromevox/background/chrome_shared2.css b/chromium/third_party/chromevox/chromevox/background/chrome_shared2.css
deleted file mode 100644
index 701921a2a3c..00000000000
--- a/chromium/third_party/chromevox/chromevox/background/chrome_shared2.css
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-/* This file holds CSS that should be shared, in theory, by all user-visible
- * chrome:// pages. This contrasts chrome_shared.css, which it is meant to
- * replace, but has CSS specific to options and options-like pages. */
-
-/* Prevent CSS from overriding the hidden property. */
-[hidden] {
- display: none !important;
-}
-
-html.loading * {
- -webkit-transition-delay: 0ms !important;
- -webkit-transition-duration: 0ms !important;
-}
-
-body {
- cursor: default;
- margin: 0;
-}
-
-p {
- line-height: 1.8em;
-}
-
-h1,
-h2,
-h3 {
- -webkit-user-select: none;
- font-weight: normal;
- /* Makes the vertical size of the text the same for all fonts. */
- line-height: 1;
-}
-
-h1 {
- font-size: 1.5em;
-}
-
-h2 {
- font-size: 1.3em;
- margin-bottom: 0.4em;
-}
-
-h3 {
- color: black;
- font-size: 1.2em;
- margin-bottom: 0.5em;
-}
-
-a {
- color: rgb(17, 85, 204);
- text-decoration: underline;
-}
-
-a:active {
- color: rgb(5, 37, 119);
-}
-
-/* Elements that need to be LTR even in an RTL context, but should align
- * right. (Namely, URLs, search engine names, etc.)
- */
-html[dir='rtl'] .weakrtl {
- direction: ltr;
- text-align: right;
-}
-
-/* Input fields in search engine table need to be weak-rtl. Since those input
- * fields are generated for all cr.ListItem elements (and we only want weakrtl
- * on some), the class needs to be on the enclosing div.
- */
-html[dir='rtl'] div.weakrtl input {
- direction: ltr;
- text-align: right;
-}
-
-html[dir='rtl'] .favicon-cell.weakrtl {
- -webkit-padding-end: 22px;
- -webkit-padding-start: 0;
-}
-
-/* weakrtl for selection drop downs needs to account for the fact that
- * Webkit does not honor the text-align attribute for the select element.
- * (See Webkit bug #40216)
- */
-html[dir='rtl'] select.weakrtl {
- direction: rtl;
-}
-
-html[dir='rtl'] select.weakrtl option {
- direction: ltr;
-}
-
-/* WebKit does not honor alignment for text specified via placeholder attribute.
- * This CSS is a workaround. Please remove once WebKit bug is fixed.
- * https://bugs.webkit.org/show_bug.cgi?id=63367
- */
-html[dir='rtl'] input.weakrtl::-webkit-input-placeholder,
-html[dir='rtl'] .weakrtl input::-webkit-input-placeholder {
- direction: rtl;
-}
diff --git a/chromium/third_party/chromevox/chromevox/background/options.css b/chromium/third_party/chromevox/chromevox/background/options.css
deleted file mode 100644
index 9036b084cf2..00000000000
--- a/chromium/third_party/chromevox/chromevox/background/options.css
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-.hidden {
- position: absolute;
- left: -10000px;
- top: auto;
- width: 1px;
- height: 1px;
- overflow: hidden;
-}
-
-body {
- font-size: 14px;
- font-family: 'Lucida Grande', sans-serif;
- color: #282828;
-}
-
-div {
- padding-left: 30px;
- padding-top: 10px;
-}
-
-.option {
- padding-left: 0px;
- padding-top: 0px;
- padding-bottom:10px;
-}
-
-p {
- padding-top:0px;
- margin-top:0px;
- margin-bottom:25px;
-}
-
-h1 {
- font-size: 1.5em;
- font-weight: bold;
- margin-bottom:0px;
- padding-bottom:0px;
-}
-
-h2 {
- font-size: 16px;
- font-weight: bold;
- padding-bottom: 5px;
- margin-bottom: 0px;
-}
-
-h3 {
- padding-bottom: 0px;
- margin-bottom: 10px;
-}
-
-a {
- color: #337ef1
-}
-
-input {
- font-size: 12pt;
- color: #787878;
-}
-
-.description {
- margin-bottom: 0px;
-}
-
-.key {
- padding-left: 0px;
- padding-top: 0px;
- padding-bottom:10px;
- padding-right: 5px;
- margin-right: 5px;
-}
-
-.key-container {
- padding-left: 0px;
-}
diff --git a/chromium/third_party/chromevox/chromevox/background/options_widgets.css b/chromium/third_party/chromevox/chromevox/background/options_widgets.css
deleted file mode 100644
index 745b2326615..00000000000
--- a/chromium/third_party/chromevox/chromevox/background/options_widgets.css
+++ /dev/null
@@ -1,298 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* This file defines styles for form controls. The order of rule blocks is
- * important as there are some rules with equal specificity that rely on order
- * as a tiebreaker. These are marked with OVERRIDE.
- */
-
-/* Default state **************************************************************/
-
-button:not(.custom-appearance):not(.link-button),
-input[type='button']:not(.custom-appearance):not(.link-button),
-input[type='submit']:not(.custom-appearance):not(.link-button),
-select,
-input[type='checkbox'],
-input[type='radio'] {
- -webkit-appearance: none;
- -webkit-user-select: none;
- background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
- border: 1px solid rgba(0, 0, 0, 0.25);
- border-radius: 2px;
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),
- inset 0 1px 2px rgba(255, 255, 255, 0.75);
- color: #444;
- font: inherit;
- margin: 0 1px 0 0;
- text-shadow: 0 1px 0 rgb(240, 240, 240);
-}
-
-button:not(.custom-appearance):not(.link-button),
-input[type='button']:not(.custom-appearance):not(.link-button),
-input[type='submit']:not(.custom-appearance):not(.link-button),
-select {
- min-height: 2em;
- min-width: 4em;
-
-/* The following platform-specific rule is necessary to get adjacent
- * buttons, text inputs, and so forth to align on their borders while also
- * aligning on the text's baselines. */
- padding-bottom: 1px;
-}
-
-button:not(.custom-appearance):not(.link-button),
-input[type='button']:not(.custom-appearance):not(.link-button),
-input[type='submit']:not(.custom-appearance):not(.link-button) {
- -webkit-padding-end: 10px;
- -webkit-padding-start: 10px;
-}
-
-select {
- -webkit-appearance: none;
- -webkit-padding-end: 20px;
- -webkit-padding-start: 6px;
- /* OVERRIDE */
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAWklEQVQokWNgoAOIAuI0PDiKaJMSgYCZmfkbkPkfHYPEQfJEG/b//3+FBQsWLGRjY/uJbBCIDxIHyRNtGDYDyTYI3UA+Pr4vFBmEbODbt2+bKDYIyUBWYtQBAIRzRP/XKJ//AAAAAElFTkSuQmCC"),
- -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
- background-position: right center;
- background-repeat: no-repeat;
-}
-
-html[dir='rtl'] select {
- background-position: center left;
-}
-
-input[type='checkbox'] {
- bottom: 2px;
- height: 13px;
- position: relative;
- vertical-align: middle;
- width: 13px;
-}
-
-input[type='radio'] {
- /* OVERRIDE */
- border-radius: 100%;
- bottom: 3px;
- height: 15px;
- position: relative;
- vertical-align: middle;
- width: 15px;
-}
-
-/* TODO(estade): add more types here? */
-input[type='password'],
-input[type='search'],
-input[type='text'],
-input[type='url'],
-input:not([type]) {
- border: 1px solid #bfbfbf;
- border-radius: 2px;
- box-sizing: border-box;
- color: #444;
- font: inherit;
- height: 2em;
- padding: 3px;
-
-
-}
-
-input[type='search'] {
- -webkit-appearance: textfield;
- /* NOTE: Keep a relatively high min-width for this so we don't obscure the end
- * of the default text in relatively spacious languages (i.e. German). */
- min-width: 160px;
-}
-
-/* Checked ********************************************************************/
-
-input[type='checkbox']:checked::before {
- -webkit-user-select: none;
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wDBhYcG79aGIsAAACbSURBVBjTjdFBCkFhFAXgj4fp24PBy0SZ2ICRXRgYGb2xlKzBSEo2YgsiKWVoZgFKMjD5X/2Ux6lb99bpnNO5lKMR5i8MsEQHkhJiEzlS9HCqfiFWMUIt3AfsC3KKLCL30Qr7HfM4Ro4h6rhiEqmusIMKuphGqo+ogSPGcbYLzh91vdkXSHDDBk+0gxussS3rNcMCs+D6E18/9gLPPhbDshfzLgAAAABJRU5ErkJggg==");
- background-size: 100% 100%;
- content: '';
- display: block;
- height: 100%;
- width: 100%;
-}
-
-html[dir='rtl'] input[type='checkbox']:checked::before {
- -webkit-transform: scaleX(-1);
-}
-
-input[type='radio']:checked::before {
- background-color: #666;
- border-radius: 100%;
- bottom: 25%;
- content: '';
- display: block;
- left: 25%;
- position: absolute;
- right: 25%;
- top: 25%;
-}
-
-/* Hover **********************************************************************/
-
-button:not(.custom-appearance):not(.link-button):enabled:hover,
-input[type='button']:not(.custom-appearance):not(.link-button):enabled:hover,
-input[type='submit']:not(.custom-appearance):not(.link-button):enabled:hover,
-select:enabled:hover,
-input[type='checkbox']:enabled:hover,
-input[type='radio']:enabled:hover {
- background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
- border-color: rgba(0, 0, 0, 0.3);
- box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12),
- inset 0 1px 2px rgba(255, 255, 255, 0.95);
- color: black;
-}
-
-select:enabled:hover {
- /* OVERRIDE */
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAWklEQVQokWNgoAOIAuI0PDiKaJMSgYCZmfkbkPkfHYPEQfJEG/b//3+FBQsWLGRjY/uJbBCIDxIHyRNtGDYDyTYI3UA+Pr4vFBmEbODbt2+bKDYIyUBWYtQBAIRzRP/XKJ//AAAAAElFTkSuQmCC"),
- -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
-}
-
-/* Active *********************************************************************/
-
-button:not(.custom-appearance):not(.link-button):enabled:active,
-input[type='button']:not(.custom-appearance):not(.link-button):enabled:active,
-input[type='submit']:not(.custom-appearance):not(.link-button):enabled:active,
-select:enabled:active,
-input[type='checkbox']:enabled:active,
-input[type='radio']:enabled:active {
- background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
- box-shadow: none;
- text-shadow: none;
-}
-
-select:enabled:active {
- /* OVERRIDE */
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAWklEQVQokWNgoAOIAuI0PDiKaJMSgYCZmfkbkPkfHYPEQfJEG/b//3+FBQsWLGRjY/uJbBCIDxIHyRNtGDYDyTYI3UA+Pr4vFBmEbODbt2+bKDYIyUBWYtQBAIRzRP/XKJ//AAAAAElFTkSuQmCC"),
- -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);
-}
-
-/* Disabled *******************************************************************/
-
-button:not(.custom-appearance):not(.link-button):disabled,
-input[type='button']:not(.custom-appearance):not(.link-button):disabled,
-input[type='submit']:not(.custom-appearance):not(.link-button):disabled,
-select:disabled {
- background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);
- border-color: rgba(80, 80, 80, 0.2);
- box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08),
- inset 0 1px 2px rgba(255, 255, 255, 0.75);
- color: #aaa;
-}
-
-select:disabled {
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAYAAAAbQcSUAAAAAXNSR0IArs4c6QAAAAd0SU1FB9sLAxYEBKriBmwAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAABLSURBVCiRY2CgA4gC4jQ8OIpokxKBoKGh4T8uDJIn2rD///8rLFiwYCE2g0DiIHkSfIndQLIMwmYgRQYhG/j27dsmig1CMpCVGHUAo8FcsHfxfXQAAAAASUVORK5CYII="),
- -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);
-}
-
-input[type='checkbox']:disabled,
-input[type='radio']:disabled {
- opacity: .75;
-}
-
-input[type='password']:disabled,
-input[type='search']:disabled,
-input[type='text']:disabled,
-input[type='url']:disabled,
-input:not([type]):disabled {
- color: #999;
-}
-
-/* Focus **********************************************************************/
-
-button:not(.custom-appearance):not(.link-button):enabled:focus,
-input[type='button']:not(.custom-appearance):enabled:focus,
-input[type='checkbox']:enabled:focus,
-input[type='password']:enabled:focus,
-input[type='radio']:enabled:focus,
-input[type='search']:enabled:focus,
-input[type='submit']:not(.custom-appearance):enabled:focus,
-input[type='text']:enabled:focus,
-input[type='url']:enabled:focus,
-input:not([type]):enabled:focus,
-select:enabled:focus {
- /* OVERRIDE */
- -webkit-transition: border-color 200ms;
- /* We use border color because it follows the border radius (unlike outline).
- * This is particularly noticeable on mac. */
- border-color: rgb(77, 144, 254);
- outline: none;
-}
-
-/* Link buttons ***************************************************************/
-
-.link-button {
- -webkit-box-shadow: none;
- background: transparent none;
- border: none;
- color: rgb(17, 85, 204);
- cursor: pointer;
- /* Input elements have -webkit-small-control which can override the body font.
- * Resolve this by using 'inherit'. */
- font: inherit;
- margin: 0;
- padding: 0 4px;
-}
-
-.link-button:hover {
- text-decoration: underline;
-}
-
-.link-button:active {
- color: rgb(5, 37, 119);
- text-decoration: underline;
-}
-
-.link-button[disabled] {
- color: #999;
- cursor: default;
- text-decoration: none;
-}
-
-/* Checkbox/radio helpers ******************************************************
- *
- * .checkbox and .radio classes wrap labels. Checkboxes and radios should use
- * these classes with the markup structure:
- *
- * <div class="checkbox">
- * <label>
- * <input type="checkbox"></input>
- * <span>
- * </label>
- * </div>
- */
-
-.checkbox,
-.radio {
- margin: 0.65em 0;
-}
-
-.checkbox label,
-.radio label {
- /* Don't expand horizontally: <http://crbug.com/112091>. */
- display: -webkit-inline-box;
-}
-
-.checkbox label input ~ span,
-.radio label input ~ span {
- -webkit-margin-start: 0.6em;
- /* Make sure long spans wrap at the same horizontal position they start. */
- display: block;
-}
-
-.checkbox label:hover,
-.radio label:hover {
- color: black;
-}
-
-label > input[type=checkbox]:disabled ~ span,
-label > input[type=radio]:disabled ~ span {
- color: #999;
-}
diff --git a/chromium/third_party/chromevox/chromevox/injected/mathjax.js b/chromium/third_party/chromevox/chromevox/injected/mathjax.js
deleted file mode 100644
index 1b926721519..00000000000
--- a/chromium/third_party/chromevox/chromevox/injected/mathjax.js
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Bridge to MathJax functions from the ChromeVox content script.
- *
- */
-
-if (typeof(goog) != 'undefined' && goog.provide) {
- goog.provide('cvox.MathJax');
-}
-
-if (typeof(goog) != 'undefined' && goog.require) {
- goog.require('cvox.Api');
- goog.require('cvox.MathJaxExternalUtil');
-}
-
-(function() {
- /**
- * The channel between the page and content script.
- * @type {MessageChannel}
- */
- var channel_ = new MessageChannel();
-
-
- /**
- * @constructor
- */
- cvox.MathJax = function() {
- };
-
-
- /**
- * Initializes message channel in Chromevox.
- */
- cvox.MathJax.initMessage = function() {
- channel_.port1.onmessage = function(evt) {
- cvox.MathJax.execMessage(evt.data);
- };
- window.postMessage('cvox.MathJaxPortSetup', '*', [channel_.port2]);
- };
-
-
- /**
- * Post a message to Chromevox.
- * @param {string} cmd The command to be executed in Chromevox.
- * @param {string} callbackId A string representing the callback id.
- * @param {Object<string, *>} args Dictionary of arguments.
- */
- cvox.MathJax.postMessage = function(cmd, callbackId, args) {
- channel_.port1.postMessage({'cmd': cmd, 'id': callbackId, 'args': args});
- };
-
-
- /**
- * Executes a command for an incoming message.
- * @param {{cmd: string, id: string, args: string}} msg A
- * serializable message.
- */
- cvox.MathJax.execMessage = function(msg) {
- var args = msg.args;
- switch (msg.cmd) {
- case 'Active':
- cvox.MathJax.isActive(msg.id);
- break;
- case 'AllJax':
- cvox.MathJax.getAllJax(msg.id);
- break;
- case 'AsciiMathToMml':
- cvox.MathJax.asciiMathToMml(msg.id, args.alt, args.id);
- break;
- case 'InjectScripts':
- cvox.MathJax.injectScripts();
- break;
- case 'ConfWikipedia':
- cvox.MathJax.configMediaWiki();
- break;
- case 'RegSig':
- cvox.MathJax.registerSignal(msg.id, args.sig);
- break;
- case 'TexToMml':
- cvox.MathJax.texToMml(msg.id, args.alt, args.id);
- break;
- }
- };
-
-
- /**
- * Compute the MathML representation for all currently available MathJax
- * nodes.
- * @param {string} callbackId A string representing the callback id.
- */
- cvox.MathJax.getAllJax = function(callbackId) {
- cvox.MathJaxExternalUtil.getAllJax(
- cvox.MathJax.getMathmlCallback_(callbackId));
- };
-
-
- /**
- * Registers a callback for a particular Mathjax signal.
- * @param {string} callbackId A string representing the callback id.
- * @param {string} signal The Mathjax signal on which to fire the callback.
- */
- cvox.MathJax.registerSignal = function(callbackId, signal) {
- cvox.MathJaxExternalUtil.registerSignal(
- cvox.MathJax.getMathmlCallback_(callbackId), signal);
- };
-
-
- /**
- * Constructs a callback that posts a string with the MathML representation of
- * a MathJax element to ChromeVox.
- * @param {string} callbackId A string representing the callback id.
- * @return {function(Node, string)} A function taking a Mathml node and an id
- * string.
- * @private
- */
- cvox.MathJax.getMathmlCallback_ = function(callbackId) {
- return function(mml, id) {
- cvox.MathJax.postMessage('NodeMml', callbackId,
- {'mathml': mml, 'elementId': id});
- };
- };
-
-
- /**
- * Inject a minimalistic MathJax script into a page for LaTeX translation.
- */
- cvox.MathJax.injectScripts = function() {
- cvox.MathJaxExternalUtil.injectConfigScript();
- cvox.MathJaxExternalUtil.injectLoadScript();
- };
-
-
- /**
- * Loads configurations for MediaWiki pages (e.g., Wikipedia).
- */
- cvox.MathJax.configMediaWiki = function() {
- cvox.MathJaxExternalUtil.configMediaWiki();
- };
-
-
- /**
- * Translates a LaTeX expressions into a MathML element.
- * @param {string} callbackId A string representing the callback id.
- * @param {string} tex The LaTeX expression.
- * @param {string} cvoxId A string representing the cvox id for the node.
- */
- cvox.MathJax.texToMml = function(callbackId, tex, cvoxId) {
- cvox.MathJaxExternalUtil.texToMml(
- function(mml) {
- cvox.MathJax.getMathmlCallback_(callbackId)(mml, cvoxId);
- },
- tex);
- };
-
-
- /**
- * Translates an AsciiMath expression into a MathML element.
- * @param {string} callbackId A string representing the callback id.
- * @param {string} asciiMath The AsciiMath expression.
- * @param {string} cvoxId A string representing the cvox id for the node.
- */
- cvox.MathJax.asciiMathToMml = function(callbackId, asciiMath, cvoxId) {
- cvox.MathJaxExternalUtil.asciiMathToMml(
- function(mml) {
- cvox.MathJax.getMathmlCallback_(callbackId)(mml, cvoxId);
- },
- asciiMath);
- };
-
-
- /**
- * Check if MathJax is injected in the page.
- * @param {string} callbackId A string representing the callback id.
- */
- cvox.MathJax.isActive = function(callbackId) {
- cvox.MathJax.postMessage(
- 'Active', callbackId,
- {'status': cvox.MathJaxExternalUtil.isActive()});
- };
-
-
- // Initializing the bridge.
- cvox.MathJax.initMessage();
-
-})();
diff --git a/chromium/third_party/chromevox/chromevox/injected/mathjax_external_util.js b/chromium/third_party/chromevox/chromevox/injected/mathjax_external_util.js
deleted file mode 100644
index 051789b5633..00000000000
--- a/chromium/third_party/chromevox/chromevox/injected/mathjax_external_util.js
+++ /dev/null
@@ -1,481 +0,0 @@
-// Copyright 2013 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Utility functions for the MathJax bridge. It contains
- * functionality that changes the normal behaviour of MathJax contributed by
- * Davide Cervone (dpvc@union.edu) and adapted by Volker Sorge
- * (sorge@google.com).
- * This is the only file that should contain actual MathJax code!
- *
- */
-
-if (typeof(goog) != 'undefined' && goog.provide) {
- goog.provide('cvox.MathJaxExternalUtil');
-}
-
-
-if (!window['cvox']) {
- window['cvox'] = {};
-}
-
-/**
- * @constructor
- */
-cvox.MathJaxExternalUtil = function() {
-};
-
-
-/**
- * Returns a string with Mathml attributes for a MathJax object. This serves as
- * intermediate store for the original function when we temporarily change
- * MathJax's output behaviour.
- * @return {string}
- */
-cvox.MathJaxExternalUtil.mmlAttr = function() {
- return '';
-};
-
-
-/**
- * Rewrites an mfenced expression internally in MathJax to a corresponding mrow.
- * @param {?string} space The separator expression.
- * @return {string} The new mrow expression as a string.
- * @this {MathJax.RootElement}
- */
-cvox.MathJaxExternalUtil.mfenced = function(space) {
- if (space == null) {
- space = '';
- }
- var mml = [space + '<mrow mfenced="true"' +
- this.toMathMLattributes() + '>'];
- var mspace = space + ' ';
- if (this.data.open) {
- mml.push(this.data.open.toMathML(mspace));
- }
- if (this.data[0] != null) {
- mml.push(this.data[0].toMathML(mspace));
- }
- for (var i = 1, m = this.data.length; i < m; i++) {
- if (this.data[i]) {
- if (this.data['sep' + i]) {
- mml.push(this.data['sep' + i].toMathML(mspace));
- }
- mml.push(this.data[i].toMathML(mspace));
- }
- }
- if (this.data.close) {
- mml.push(this.data.close.toMathML(mspace));
- }
- mml.push(space + '</mrow>');
- return mml.join('\n');
-};
-
-
-/**
- * Compute the MathML representation of a MathJax element.
- * @param {MathJax.Jax} jax MathJax object.
- * @param {function(string)} callback Callback function.
- * @return {Function} Callback function for restart.
- * @this {cvox.MathJaxExternalUtil}
- */
-cvox.MathJaxExternalUtil.getMathml = function(jax, callback) {
- var mbaseProt = MathJax.ElementJax.mml.mbase.prototype;
- var mfencedProt = MathJax.ElementJax.mml.mfenced.prototype;
- this.mmlAttr = mbaseProt.toMathMLattributes;
- var mfenced = mfencedProt.toMathML;
- try {
- mbaseProt.toMathMLattributes = cvox.MathJaxExternalUtil.mbase;
- mfencedProt.toMathML = cvox.MathJaxExternalUtil.mfenced;
- var mml = jax.root.toMathML('');
- mbaseProt.toMathMLattributes = this.mmlAttr;
- mfencedProt.toMathML = mfenced;
- MathJax.Callback(callback)(mml);
- } catch (err) {
- mbaseProt.toMathMLattributes = this.mmlAttr;
- mfencedProt.toMathML = mfenced;
- if (!err['restart']) {
- throw err;
- }
- return MathJax.Callback.After(
- [cvox.MathJaxExternalUtil.getMathml, jax, callback], err['restart']);
- }
-};
-
-
-/**
- * Compute the special span ID attribute.
- * @return {string} The MathJax spanID attribute string.
- * @this {MathJax.RootElement}
- */
-cvox.MathJaxExternalUtil.mbase = function() {
- var attr = cvox.MathJaxExternalUtil.mmlAttr.call(this);
- if (this.spanID != null) {
- var id = (this.id || 'MathJax-Span-' + this.spanID) +
- MathJax.OutputJax['HTML-CSS']['idPostfix'];
- attr += ' spanID="' + id + '"';
- }
- if (this.texClass != null) {
- attr += ' texClass="' + this.texClass + '"';
- }
- return attr;
-};
-
-
-/**
- * Test that ensures that all important parts of MathJax have been initialized
- * at startup.
- * @return {boolean} True if MathJax is sufficiently initialised.
- */
-cvox.MathJaxExternalUtil.isActive = function() {
- return typeof(MathJax) != 'undefined' &&
- typeof(MathJax.Hub) != 'undefined' &&
- typeof(MathJax.ElementJax) != 'undefined' &&
- typeof(MathJax.InputJax) != 'undefined';
-};
-
-
-/**
- * Constructs a callback for a MathJax object with the purpose of returning the
- * MathML representation of a particular jax given by its node id. The callback
- * can be used by functions passing it to MathJax functions and is invoked by
- * MathJax.
- * @param {function(string, string)} callback A function taking a MathML
- * expression and an id string.
- * @param {MathJax.Jax} jax The MathJax object.
- * @private
- */
-cvox.MathJaxExternalUtil.getMathjaxCallback_ = function(callback, jax) {
- cvox.MathJaxExternalUtil.getMathml(
- jax,
- function(mml) {
- if (jax.root.inputID) {
- callback(mml, jax.root.inputID);
- }
- });
-};
-
-
-/**
- * Registers a callback for a particular Mathjax signal.
- * @param {function(string, string)} callback A function taking an MathML
- * expression and an id string.
- * @param {string} signal The Mathjax signal on which to fire the callback.
- */
-cvox.MathJaxExternalUtil.registerSignal = function(callback, signal) {
- MathJax.Hub.Register.MessageHook(
- signal,
- function(signalAndIdPair) {
- var jax = MathJax.Hub.getJaxFor(signalAndIdPair[1]);
- cvox.MathJaxExternalUtil.getMathjaxCallback_(callback, jax);
- });
-};
-
-
-/**
- * Compute the MathML representation for all currently available MathJax
- * nodes.
- * @param {function(string, string)} callback A function taking a MathML
- * expression and an id string.
- */
-cvox.MathJaxExternalUtil.getAllJax = function(callback) {
- var jaxs = MathJax.Hub.getAllJax();
- if (jaxs) {
- jaxs.forEach(function(jax) {
- if (jax.root.spanID) {
- cvox.MathJaxExternalUtil.getMathjaxCallback_(callback, jax);
- }
- });
- }
-};
-
-
-// Functionality for direct translation from LaTeX to MathML without rendering.
-/**
- * Injects a MathJax config script into the page.
- * This script is picked up by MathJax at load time. It only runs in the page,
- * thus in case it causes an exception it will not crash ChromeVox. The worst
- * thing that can happen is that we do not get a MathML object for some
- * LaTeX alternative text, i.e., we default to the usual behaviour of simply
- * reading out the alt text directly.
- */
-cvox.MathJaxExternalUtil.injectConfigScript = function() {
- var script = document.createElement('script');
- script.setAttribute('type', 'text/x-mathjax-config');
- script.textContent =
- 'MathJax.Hub.Config({\n' +
- // No output needed.
- ' jax: ["input/AsciiMath", "input/TeX"],\n' +
- // Load functionality for MathML translation.
- ' extensions: ["toMathML.js"],\n' +
- // Do not change any rendering in the page.
- ' skipStartupTypeset: true,\n' +
- // Do not display any MathJax status message.
- ' messageStyle: "none",\n' +
- // Load AMS math extensions.
- ' TeX: {extensions: ["AMSmath.js","AMSsymbols.js"]}\n' +
- '});\n' +
- 'MathJax.Hub.Queue(\n' +
- // Force InputJax to load.
- ' function() {MathJax.Hub.inputJax["math/asciimath"].Process();\n' +
- ' MathJax.Hub.inputJax["math/tex"].Process()}\n' +
- ');\n' +
- '//\n' +
- '// Prevent these from being loaded\n' +
- '//\n' +
- // Make sure that no pop up menu is created for the jax.
- 'if (!MathJax.Extension.MathMenu) {MathJax.Extension.MathMenu = {}};\n' +
- // Make sure that jax is created unzoomed.
- 'if (!MathJax.Extension.MathZoom) {MathJax.Extension.MathZoom = {}};';
- document.activeElement.appendChild(script);
-};
-
-
-/**
- * Injects a MathJax load script into the page. This should only be injected
- * after the config script. While the config script can adapted for different
- * pages, the load script is generic.
- *
- */
-cvox.MathJaxExternalUtil.injectLoadScript = function() {
- var script = document.createElement('script');
- script.setAttribute('type', 'text/javascript');
- var protocol = location.protocol == 'https:' ? 'https' : 'http';
- script.setAttribute(
- 'src', protocol + '://cdn.mathjax.org/mathjax/latest/MathJax.js');
- document.activeElement.appendChild(script);
-};
-
-
-/**
- * Configures MathJax for MediaWiki pages (e.g., Wikipedia) by adding
- * some special mappings to MathJax's symbol definitions. The function
- * can only be successfully executed, once MathJax is injected and
- * configured in the page.
- */
-// Adapted from
-// https://en.wikipedia.org/wiki/User:Nageh/mathJax/config/TeX-AMS-texvc_HTML.js
-cvox.MathJaxExternalUtil.configMediaWiki = function() {
- if (mediaWiki) {
- MathJax.Hub.Register.StartupHook(
- 'TeX Jax Ready', function() {
- var MML = MathJax.ElementJax.mml;
- MathJax.Hub.Insert(
- MathJax.InputJax.TeX.Definitions,
- {
- mathchar0mi: {
- thetasym: '03B8',
- koppa: '03DF',
- stigma: '03DB',
- varstigma: '03DB',
- coppa: '03D9',
- varcoppa: '03D9',
- sampi: '03E1',
- C: ['0043', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- cnums: ['0043', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- Complex: ['0043', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- H: ['210D', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- N: ['004E', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- natnums: ['004E', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- Q: ['0051', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- R: ['0052', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- reals: ['0052', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- Reals: ['0052', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- Z: ['005A', {mathvariant: MML.VARIANT.DOUBLESTRUCK}],
- sect: '00A7',
- P: '00B6',
- AA: ['00C5', {mathvariant: MML.VARIANT.NORMAL}],
- alef: ['2135', {mathvariant: MML.VARIANT.NORMAL}],
- alefsym: ['2135', {mathvariant: MML.VARIANT.NORMAL}],
- weierp: ['2118', {mathvariant: MML.VARIANT.NORMAL}],
- real: ['211C', {mathvariant: MML.VARIANT.NORMAL}],
- part: ['2202', {mathvariant: MML.VARIANT.NORMAL}],
- infin: ['221E', {mathvariant: MML.VARIANT.NORMAL}],
- empty: ['2205', {mathvariant: MML.VARIANT.NORMAL}],
- O: ['2205', {mathvariant: MML.VARIANT.NORMAL}],
- ang: ['2220', {mathvariant: MML.VARIANT.NORMAL}],
- exist: ['2203', {mathvariant: MML.VARIANT.NORMAL}],
- clubs: ['2663', {mathvariant: MML.VARIANT.NORMAL}],
- diamonds: ['2662', {mathvariant: MML.VARIANT.NORMAL}],
- hearts: ['2661', {mathvariant: MML.VARIANT.NORMAL}],
- spades: ['2660', {mathvariant: MML.VARIANT.NORMAL}],
- textvisiblespace: '2423',
- geneuro: '20AC',
- euro: '20AC'
- },
- mathchar0mo: {
- and: '2227',
- or: '2228',
- bull: '2219',
- plusmn: '00B1',
- sdot: '22C5',
- Dagger: '2021',
- sup: '2283',
- sub: '2282',
- supe: '2287',
- sube: '2286',
- isin: '2208',
- hAar: '21D4',
- hArr: '21D4',
- Harr: '21D4',
- Lrarr: '21D4',
- lrArr: '21D4',
- lArr: '21D0',
- Larr: '21D0',
- rArr: '21D2',
- Rarr: '21D2',
- harr: '2194',
- lrarr: '2194',
- larr: '2190',
- gets: '2190',
- rarr: '2192',
- oiint: ['222F', {texClass: MML.TEXCLASS.OP}],
- oiiint: ['2230', {texClass: MML.TEXCLASS.OP}]
- },
- mathchar7: {
- Alpha: '0391',
- Beta: '0392',
- Epsilon: '0395',
- Zeta: '0396',
- Eta: '0397',
- Iota: '0399',
- Kappa: '039A',
- Mu: '039C',
- Nu: '039D',
- Omicron: '039F',
- Rho: '03A1',
- Tau: '03A4',
- Chi: '03A7',
- Koppa: '03DE',
- Stigma: '03DA',
- Digamma: '03DC',
- Coppa: '03D8',
- Sampi: '03E0'
- },
- delimiter: {
- '\\uarr': '2191',
- '\\darr': '2193',
- '\\Uarr': '21D1',
- '\\uArr': '21D1',
- '\\Darr': '21D3',
- '\\dArr': '21D3',
- '\\rang': '27E9',
- '\\lang': '27E8'
- },
- macros: {
- sgn: 'NamedFn',
- arccot: 'NamedFn',
- arcsec: 'NamedFn',
- arccsc: 'NamedFn',
- sen: 'NamedFn',
- image: ['Macro', '\\Im'],
- bold: ['Macro', '\\mathbf{#1}', 1],
- pagecolor: ['Macro', '', 1],
- emph: ['Macro', '\\textit{#1}', 1],
- textsf: ['Macro', '\\mathord{\\sf{\\text{#1}}}', 1],
- texttt: ['Macro', '\\mathord{\\tt{\\text{#1}}}', 1],
- vline: ['Macro', '\\smash{\\large\\lvert}', 0]
- }
- });
- });
- }
-};
-
-
-/**
- * Converts an expression into MathML string.
- * @param {function(string)} callback Callback function called with the MathML
- * string after it is produced.
- * @param {string} math The math Expression.
- * @param {string} typeString Type of the expression to be converted (e.g.,
- * "math/tex", "math/asciimath")
- * @param {string} filterString Name of object specifying the filters to be used
- * by MathJax (e.g., TeX, AsciiMath)
- * @param {string} errorString Name of the error object used by MathJax (e.g.,
- * texError, asciimathError).
- * @param {!function(string)} parseFunction The MathJax function used for
- * parsing the particular expression. This depends on the kind of expression we
- * have.
- * @return {Function} If a restart occurs, the callback for it is
- * returned, so this can be used in MathJax.Hub.Queue() calls reliably.
- */
-cvox.MathJaxExternalUtil.convertToMml = function(
- callback, math, typeString, filterString, errorString, parseFunction) {
- // Make a fake script and pass it to the pre-filters.
- var script = MathJax.HTML.Element('script', {type: typeString}, [math]);
- var data = {math: math, script: script};
- MathJax.InputJax[filterString].prefilterHooks.Execute(data);
-
- // Attempt to parse the code, processing any errors.
- var mml;
- try {
- mml = parseFunction(data.math);
- } catch (err) {
- if (err[errorString]) {
- // Put errors into <merror> tags.
- mml = MathJax.ElementJax.mml.merror(err.message.replace(/\n.*/, ''));
- } else if (err['restart']) {
- // Wait for file to load, then do this routine again.
- return MathJax.Callback.After(
- [cvox.MathJaxExternalUtil.convertToMml, callback, math,
- typeString, filterString, errorString, parseFunction],
- err['restart']);
- } else {
- // It's an actual error, so pass it on.
- throw err;
- }
- }
-
- // Make an ElementJax from the tree, call the post-filters, and get the
- // MathML.
- if (mml.inferred) {
- mml = MathJax.ElementJax.mml.apply(MathJax.ElementJax, mml.data);
- } else {
- mml = MathJax.ElementJax.mml(mml);
- }
- mml.root.display = 'block';
- data.math = mml;
- // This is necessary to make this function work even if MathJax is already
- // properly injected into the page, as this object is used in MathJax's
- // AMSmath.js file.
- data.script['MathJax'] = {};
- MathJax.InputJax[filterString].postfilterHooks.Execute(data);
- return cvox.MathJaxExternalUtil.getMathml(data.math, callback);
-};
-
-
-/**
- * Converts a LaTeX expression into MathML string.
- * @param {function(string)} callback Callback function called with the MathML
- * string after it is produced.
- * @param {string} math Expression latex.
- */
-cvox.MathJaxExternalUtil.texToMml = function(callback, math) {
- cvox.MathJaxExternalUtil.convertToMml(
- callback, math, 'math/tex;mode=display', 'TeX', 'texError',
- function(data) {return MathJax.InputJax.TeX.Parse(data).mml();});
-};
-
-
-/**
- * Converts an AsciiMath expression into MathML string.
- * @param {function(string)} callback Callback function called with the MathML
- * string after it is produced.
- * @param {string} math Expression in AsciiMath.
- */
-cvox.MathJaxExternalUtil.asciiMathToMml = function(callback, math) {
- cvox.MathJaxExternalUtil.convertToMml(
- callback, math, 'math/asciimath', 'AsciiMath', 'asciimathError',
- MathJax.InputJax.AsciiMath.AM.parseMath);
-};
diff --git a/chromium/third_party/chromevox/third_party/closure-library/LICENSE b/chromium/third_party/chromevox/third_party/closure-library/LICENSE
deleted file mode 100644
index d9a10c0d8e8..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/LICENSE
+++ /dev/null
@@ -1,176 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
diff --git a/chromium/third_party/chromevox/third_party/closure-library/README.chromium b/chromium/third_party/chromevox/third_party/closure-library/README.chromium
deleted file mode 100644
index aa37cc52fb5..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/README.chromium
+++ /dev/null
@@ -1,20 +0,0 @@
-Name: Closure Library
-URL: https://github.com/google/closure-library
-Version: 5a4878ece3dd35230a21d745411ab0985cf99e15
-InfoURL: http://developers.google.com/closure/library
-License: Apache 2.0
-Security Critical: Yes
-
-Description:
-Closure Library is a powerful, low level JavaScript library designed
-for building complex and scalable web applications.
-
-Local Modifications:
-Only the files actually used by ChromeVox are kept. This includes a small
-number of javaScript source files and a few python modules to scan sources for
-closure dependencies. In addition:
-- closure/goog/i18n/messageformat.js was changed to use
- Number.prototype.toLocaleString and not depend on the number format classes
- in the Closure library.
-- Most of closure/goog/string/string.js was deleted. The only function
- left is goog.string.subs as it is needed by goog.asserts.
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/depstree.py b/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/depstree.py
deleted file mode 100644
index f288dd3aa61..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/depstree.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# Copyright 2009 The Closure Library Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS-IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-"""Class to represent a full Closure Library dependency tree.
-
-Offers a queryable tree of dependencies of a given set of sources. The tree
-will also do logical validation to prevent duplicate provides and circular
-dependencies.
-"""
-
-__author__ = 'nnaze@google.com (Nathan Naze)'
-
-
-class DepsTree(object):
- """Represents the set of dependencies between source files."""
-
- def __init__(self, sources):
- """Initializes the tree with a set of sources.
-
- Args:
- sources: A set of JavaScript sources.
-
- Raises:
- MultipleProvideError: A namespace is provided by muplitple sources.
- NamespaceNotFoundError: A namespace is required but never provided.
- """
-
- self._sources = sources
- self._provides_map = dict()
-
- # Ensure nothing was provided twice.
- for source in sources:
- for provide in source.provides:
- if provide in self._provides_map:
- raise MultipleProvideError(
- provide, [self._provides_map[provide], source])
-
- self._provides_map[provide] = source
-
- # Check that all required namespaces are provided.
- for source in sources:
- for require in source.requires:
- if require not in self._provides_map:
- raise NamespaceNotFoundError(require, source)
-
- def GetDependencies(self, required_namespaces):
- """Get source dependencies, in order, for the given namespaces.
-
- Args:
- required_namespaces: A string (for one) or list (for one or more) of
- namespaces.
-
- Returns:
- A list of source objects that provide those namespaces and all
- requirements, in dependency order.
-
- Raises:
- NamespaceNotFoundError: A namespace is requested but doesn't exist.
- CircularDependencyError: A cycle is detected in the dependency tree.
- """
- if isinstance(required_namespaces, str):
- required_namespaces = [required_namespaces]
-
- deps_sources = []
-
- for namespace in required_namespaces:
- for source in DepsTree._ResolveDependencies(
- namespace, [], self._provides_map, []):
- if source not in deps_sources:
- deps_sources.append(source)
-
- return deps_sources
-
- @staticmethod
- def _ResolveDependencies(required_namespace, deps_list, provides_map,
- traversal_path):
- """Resolve dependencies for Closure source files.
-
- Follows the dependency tree down and builds a list of sources in dependency
- order. This function will recursively call itself to fill all dependencies
- below the requested namespaces, and then append its sources at the end of
- the list.
-
- Args:
- required_namespace: String of required namespace.
- deps_list: List of sources in dependency order. This function will append
- the required source once all of its dependencies are satisfied.
- provides_map: Map from namespace to source that provides it.
- traversal_path: List of namespaces of our path from the root down the
- dependency/recursion tree. Used to identify cyclical dependencies.
- This is a list used as a stack -- when the function is entered, the
- current namespace is pushed and popped right before returning.
- Each recursive call will check that the current namespace does not
- appear in the list, throwing a CircularDependencyError if it does.
-
- Returns:
- The given deps_list object filled with sources in dependency order.
-
- Raises:
- NamespaceNotFoundError: A namespace is requested but doesn't exist.
- CircularDependencyError: A cycle is detected in the dependency tree.
- """
-
- source = provides_map.get(required_namespace)
- if not source:
- raise NamespaceNotFoundError(required_namespace)
-
- if required_namespace in traversal_path:
- traversal_path.append(required_namespace) # do this *after* the test
-
- # This must be a cycle.
- raise CircularDependencyError(traversal_path)
-
- # If we don't have the source yet, we'll have to visit this namespace and
- # add the required dependencies to deps_list.
- if source not in deps_list:
- traversal_path.append(required_namespace)
-
- for require in source.requires:
-
- # Append all other dependencies before we append our own.
- DepsTree._ResolveDependencies(require, deps_list, provides_map,
- traversal_path)
- deps_list.append(source)
-
- traversal_path.pop()
-
- return deps_list
-
-
-class BaseDepsTreeError(Exception):
- """Base DepsTree error."""
-
- def __init__(self):
- Exception.__init__(self)
-
-
-class CircularDependencyError(BaseDepsTreeError):
- """Raised when a dependency cycle is encountered."""
-
- def __init__(self, dependency_list):
- BaseDepsTreeError.__init__(self)
- self._dependency_list = dependency_list
-
- def __str__(self):
- return ('Encountered circular dependency:\n%s\n' %
- '\n'.join(self._dependency_list))
-
-
-class MultipleProvideError(BaseDepsTreeError):
- """Raised when a namespace is provided more than once."""
-
- def __init__(self, namespace, sources):
- BaseDepsTreeError.__init__(self)
- self._namespace = namespace
- self._sources = sources
-
- def __str__(self):
- source_strs = map(str, self._sources)
-
- return ('Namespace "%s" provided more than once in sources:\n%s\n' %
- (self._namespace, '\n'.join(source_strs)))
-
-
-class NamespaceNotFoundError(BaseDepsTreeError):
- """Raised when a namespace is requested but not provided."""
-
- def __init__(self, namespace, source=None):
- BaseDepsTreeError.__init__(self)
- self._namespace = namespace
- self._source = source
-
- def __str__(self):
- msg = 'Namespace "%s" never provided.' % self._namespace
- if self._source:
- msg += ' Required in %s' % self._source
- return msg
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/source.py b/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/source.py
deleted file mode 100644
index 64e748587d4..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/source.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright 2009 The Closure Library Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS-IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-"""Scans a source JS file for its provided and required namespaces.
-
-Simple class to scan a JavaScript file and express its dependencies.
-"""
-
-__author__ = 'nnaze@google.com'
-
-
-import re
-
-_BASE_REGEX_STRING = '^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s*\)'
-_PROVIDE_REGEX = re.compile(_BASE_REGEX_STRING % 'provide')
-_REQUIRES_REGEX = re.compile(_BASE_REGEX_STRING % 'require')
-
-
-class Source(object):
- """Scans a JavaScript source for its provided and required namespaces."""
-
- # Matches a "/* ... */" comment.
- # Note: We can't definitively distinguish a "/*" in a string literal without a
- # state machine tokenizer. We'll assume that a line starting with whitespace
- # and "/*" is a comment.
- _COMMENT_REGEX = re.compile(
- r"""
- ^\s* # Start of a new line and whitespace
- /\* # Opening "/*"
- .*? # Non greedy match of any characters (including newlines)
- \*/ # Closing "*/""",
- re.MULTILINE | re.DOTALL | re.VERBOSE)
-
- def __init__(self, source):
- """Initialize a source.
-
- Args:
- source: str, The JavaScript source.
- """
-
- self.provides = set()
- self.requires = set()
-
- self._source = source
- self._ScanSource()
-
- def GetSource(self):
- """Get the source as a string."""
- return self._source
-
- @classmethod
- def _StripComments(cls, source):
- return cls._COMMENT_REGEX.sub('', source)
-
- @classmethod
- def _HasProvideGoogFlag(cls, source):
- """Determines whether the @provideGoog flag is in a comment."""
- for comment_content in cls._COMMENT_REGEX.findall(source):
- if '@provideGoog' in comment_content:
- return True
-
- return False
-
- def _ScanSource(self):
- """Fill in provides and requires by scanning the source."""
-
- stripped_source = self._StripComments(self.GetSource())
-
- source_lines = stripped_source.splitlines()
- for line in source_lines:
- match = _PROVIDE_REGEX.match(line)
- if match:
- self.provides.add(match.group(1))
- match = _REQUIRES_REGEX.match(line)
- if match:
- self.requires.add(match.group(1))
-
- # Closure's base file implicitly provides 'goog'.
- # This is indicated with the @provideGoog flag.
- if self._HasProvideGoogFlag(self.GetSource()):
-
- if len(self.provides) or len(self.requires):
- raise Exception(
- 'Base file should not provide or require namespaces.')
-
- self.provides.add('goog')
-
-
-def GetFileContents(path):
- """Get a file's contents as a string.
-
- Args:
- path: str, Path to file.
-
- Returns:
- str, Contents of file.
-
- Raises:
- IOError: An error occurred opening or reading the file.
-
- """
- fileobj = open(path)
- try:
- return fileobj.read()
- finally:
- fileobj.close()
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/treescan.py b/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/treescan.py
deleted file mode 100755
index 6694593aab0..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/bin/build/treescan.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2010 The Closure Library Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS-IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-"""Shared utility functions for scanning directory trees."""
-
-import os
-import re
-
-
-__author__ = 'nnaze@google.com (Nathan Naze)'
-
-
-# Matches a .js file path.
-_JS_FILE_REGEX = re.compile(r'^.+\.js$')
-
-
-def ScanTreeForJsFiles(root):
- """Scans a directory tree for JavaScript files.
-
- Args:
- root: str, Path to a root directory.
-
- Returns:
- An iterable of paths to JS files, relative to cwd.
- """
- return ScanTree(root, path_filter=_JS_FILE_REGEX)
-
-
-def ScanTree(root, path_filter=None, ignore_hidden=True):
- """Scans a directory tree for files.
-
- Args:
- root: str, Path to a root directory.
- path_filter: A regular expression filter. If set, only paths matching
- the path_filter are returned.
- ignore_hidden: If True, do not follow or return hidden directories or files
- (those starting with a '.' character).
-
- Yields:
- A string path to files, relative to cwd.
- """
-
- def OnError(os_error):
- raise os_error
-
- for dirpath, dirnames, filenames in os.walk(root, onerror=OnError):
- # os.walk allows us to modify dirnames to prevent decent into particular
- # directories. Avoid hidden directories.
- for dirname in dirnames:
- if ignore_hidden and dirname.startswith('.'):
- dirnames.remove(dirname)
-
- for filename in filenames:
-
- # nothing that starts with '.'
- if ignore_hidden and filename.startswith('.'):
- continue
-
- fullpath = os.path.join(dirpath, filename)
-
- if path_filter and not path_filter.match(fullpath):
- continue
-
- yield os.path.normpath(fullpath)
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/asserts/asserts.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/asserts/asserts.js
deleted file mode 100644
index af9fac0664d..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/asserts/asserts.js
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2008 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Utilities to check the preconditions, postconditions and
- * invariants runtime.
- *
- * Methods in this package should be given special treatment by the compiler
- * for type-inference. For example, <code>goog.asserts.assert(foo)</code>
- * will restrict <code>foo</code> to a truthy value.
- *
- * The compiler has an option to disable asserts. So code like:
- * <code>
- * var x = goog.asserts.assert(foo()); goog.asserts.assert(bar());
- * </code>
- * will be transformed into:
- * <code>
- * var x = foo();
- * </code>
- * The compiler will leave in foo() (because its return value is used),
- * but it will remove bar() because it assumes it does not have side-effects.
- *
- */
-
-goog.provide('goog.asserts');
-goog.provide('goog.asserts.AssertionError');
-
-goog.require('goog.debug.Error');
-goog.require('goog.dom.NodeType');
-goog.require('goog.string');
-
-
-/**
- * @define {boolean} Whether to strip out asserts or to leave them in.
- */
-goog.define('goog.asserts.ENABLE_ASSERTS', goog.DEBUG);
-
-
-
-/**
- * Error object for failed assertions.
- * @param {string} messagePattern The pattern that was used to form message.
- * @param {!Array<*>} messageArgs The items to substitute into the pattern.
- * @constructor
- * @extends {goog.debug.Error}
- * @final
- */
-goog.asserts.AssertionError = function(messagePattern, messageArgs) {
- messageArgs.unshift(messagePattern);
- goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs));
- // Remove the messagePattern afterwards to avoid permenantly modifying the
- // passed in array.
- messageArgs.shift();
-
- /**
- * The message pattern used to format the error message. Error handlers can
- * use this to uniquely identify the assertion.
- * @type {string}
- */
- this.messagePattern = messagePattern;
-};
-goog.inherits(goog.asserts.AssertionError, goog.debug.Error);
-
-
-/** @override */
-goog.asserts.AssertionError.prototype.name = 'AssertionError';
-
-
-/**
- * Throws an exception with the given message and "Assertion failed" prefixed
- * onto it.
- * @param {string} defaultMessage The message to use if givenMessage is empty.
- * @param {Array<*>} defaultArgs The substitution arguments for defaultMessage.
- * @param {string|undefined} givenMessage Message supplied by the caller.
- * @param {Array<*>} givenArgs The substitution arguments for givenMessage.
- * @throws {goog.asserts.AssertionError} When the value is not a number.
- * @private
- */
-goog.asserts.doAssertFailure_ =
- function(defaultMessage, defaultArgs, givenMessage, givenArgs) {
- var message = 'Assertion failed';
- if (givenMessage) {
- message += ': ' + givenMessage;
- var args = givenArgs;
- } else if (defaultMessage) {
- message += ': ' + defaultMessage;
- args = defaultArgs;
- }
- // The '' + works around an Opera 10 bug in the unit tests. Without it,
- // a stack trace is added to var message above. With this, a stack trace is
- // not added until this line (it causes the extra garbage to be added after
- // the assertion message instead of in the middle of it).
- throw new goog.asserts.AssertionError('' + message, args || []);
-};
-
-
-/**
- * Checks if the condition evaluates to true if goog.asserts.ENABLE_ASSERTS is
- * true.
- * @template T
- * @param {T} condition The condition to check.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @return {T} The value of the condition.
- * @throws {goog.asserts.AssertionError} When the condition evaluates to false.
- */
-goog.asserts.assert = function(condition, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && !condition) {
- goog.asserts.doAssertFailure_('', null, opt_message,
- Array.prototype.slice.call(arguments, 2));
- }
- return condition;
-};
-
-
-/**
- * Fails if goog.asserts.ENABLE_ASSERTS is true. This function is useful in case
- * when we want to add a check in the unreachable area like switch-case
- * statement:
- *
- * <pre>
- * switch(type) {
- * case FOO: doSomething(); break;
- * case BAR: doSomethingElse(); break;
- * default: goog.assert.fail('Unrecognized type: ' + type);
- * // We have only 2 types - "default:" section is unreachable code.
- * }
- * </pre>
- *
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @throws {goog.asserts.AssertionError} Failure.
- */
-goog.asserts.fail = function(opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS) {
- throw new goog.asserts.AssertionError(
- 'Failure' + (opt_message ? ': ' + opt_message : ''),
- Array.prototype.slice.call(arguments, 1));
- }
-};
-
-
-/**
- * Checks if the value is a number if goog.asserts.ENABLE_ASSERTS is true.
- * @param {*} value The value to check.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @return {number} The value, guaranteed to be a number when asserts enabled.
- * @throws {goog.asserts.AssertionError} When the value is not a number.
- */
-goog.asserts.assertNumber = function(value, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && !goog.isNumber(value)) {
- goog.asserts.doAssertFailure_('Expected number but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
- }
- return /** @type {number} */ (value);
-};
-
-
-/**
- * Checks if the value is a string if goog.asserts.ENABLE_ASSERTS is true.
- * @param {*} value The value to check.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @return {string} The value, guaranteed to be a string when asserts enabled.
- * @throws {goog.asserts.AssertionError} When the value is not a string.
- */
-goog.asserts.assertString = function(value, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && !goog.isString(value)) {
- goog.asserts.doAssertFailure_('Expected string but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
- }
- return /** @type {string} */ (value);
-};
-
-
-/**
- * Checks if the value is a function if goog.asserts.ENABLE_ASSERTS is true.
- * @param {*} value The value to check.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @return {!Function} The value, guaranteed to be a function when asserts
- * enabled.
- * @throws {goog.asserts.AssertionError} When the value is not a function.
- */
-goog.asserts.assertFunction = function(value, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && !goog.isFunction(value)) {
- goog.asserts.doAssertFailure_('Expected function but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
- }
- return /** @type {!Function} */ (value);
-};
-
-
-/**
- * Checks if the value is an Object if goog.asserts.ENABLE_ASSERTS is true.
- * @param {*} value The value to check.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @return {!Object} The value, guaranteed to be a non-null object.
- * @throws {goog.asserts.AssertionError} When the value is not an object.
- */
-goog.asserts.assertObject = function(value, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && !goog.isObject(value)) {
- goog.asserts.doAssertFailure_('Expected object but got %s: %s.',
- [goog.typeOf(value), value],
- opt_message, Array.prototype.slice.call(arguments, 2));
- }
- return /** @type {!Object} */ (value);
-};
-
-
-/**
- * Checks if the value is an Array if goog.asserts.ENABLE_ASSERTS is true.
- * @param {*} value The value to check.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @return {!Array} The value, guaranteed to be a non-null array.
- * @throws {goog.asserts.AssertionError} When the value is not an array.
- */
-goog.asserts.assertArray = function(value, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && !goog.isArray(value)) {
- goog.asserts.doAssertFailure_('Expected array but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
- }
- return /** @type {!Array} */ (value);
-};
-
-
-/**
- * Checks if the value is a boolean if goog.asserts.ENABLE_ASSERTS is true.
- * @param {*} value The value to check.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @return {boolean} The value, guaranteed to be a boolean when asserts are
- * enabled.
- * @throws {goog.asserts.AssertionError} When the value is not a boolean.
- */
-goog.asserts.assertBoolean = function(value, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && !goog.isBoolean(value)) {
- goog.asserts.doAssertFailure_('Expected boolean but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
- }
- return /** @type {boolean} */ (value);
-};
-
-
-/**
- * Checks if the value is a DOM Element if goog.asserts.ENABLE_ASSERTS is true.
- * @param {*} value The value to check.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @return {!Element} The value, likely to be a DOM Element when asserts are
- * enabled.
- * @throws {goog.asserts.AssertionError} When the value is not a boolean.
- */
-goog.asserts.assertElement = function(value, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && (!goog.isObject(value) ||
- value.nodeType != goog.dom.NodeType.ELEMENT)) {
- goog.asserts.doAssertFailure_('Expected Element but got %s: %s.',
- [goog.typeOf(value), value], opt_message,
- Array.prototype.slice.call(arguments, 2));
- }
- return /** @type {!Element} */ (value);
-};
-
-
-/**
- * Checks if the value is an instance of the user-defined type if
- * goog.asserts.ENABLE_ASSERTS is true.
- *
- * The compiler may tighten the type returned by this function.
- *
- * @param {*} value The value to check.
- * @param {function(new: T, ...)} type A user-defined constructor.
- * @param {string=} opt_message Error message in case of failure.
- * @param {...*} var_args The items to substitute into the failure message.
- * @throws {goog.asserts.AssertionError} When the value is not an instance of
- * type.
- * @return {!T}
- * @template T
- */
-goog.asserts.assertInstanceof = function(value, type, opt_message, var_args) {
- if (goog.asserts.ENABLE_ASSERTS && !(value instanceof type)) {
- goog.asserts.doAssertFailure_('instanceof check failed.', null,
- opt_message, Array.prototype.slice.call(arguments, 3));
- }
- return value;
-};
-
-
-/**
- * Checks that no enumerable keys are present in Object.prototype. Such keys
- * would break most code that use {@code for (var ... in ...)} loops.
- */
-goog.asserts.assertObjectPrototypeIsIntact = function() {
- for (var key in Object.prototype) {
- goog.asserts.fail(key + ' should not be enumerable in Object.prototype.');
- }
-};
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/base.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/base.js
deleted file mode 100644
index d358a28847c..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/base.js
+++ /dev/null
@@ -1,1706 +0,0 @@
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Bootstrap for the Google JS Library (Closure).
- *
- * In uncompiled mode base.js will write out Closure's deps file, unless the
- * global <code>CLOSURE_NO_DEPS</code> is set to true. This allows projects to
- * include their own deps file(s) from different locations.
- *
- *
- * @provideGoog
- */
-
-
-/**
- * @define {boolean} Overridden to true by the compiler when --closure_pass
- * or --mark_as_compiled is specified.
- */
-var COMPILED = false;
-
-
-/**
- * Base namespace for the Closure library. Checks to see goog is already
- * defined in the current scope before assigning to prevent clobbering if
- * base.js is loaded more than once.
- *
- * @const
- */
-var goog = goog || {};
-
-
-/**
- * Reference to the global context. In most cases this will be 'window'.
- */
-goog.global = this;
-
-
-/**
- * A hook for overriding the define values in uncompiled mode.
- *
- * In uncompiled mode, {@code CLOSURE_UNCOMPILED_DEFINES} may be defined before
- * loading base.js. If a key is defined in {@code CLOSURE_UNCOMPILED_DEFINES},
- * {@code goog.define} will use the value instead of the default value. This
- * allows flags to be overwritten without compilation (this is normally
- * accomplished with the compiler's "define" flag).
- *
- * Example:
- * <pre>
- * var CLOSURE_UNCOMPILED_DEFINES = {'goog.DEBUG': false};
- * </pre>
- *
- * @type {Object<string, (string|number|boolean)>|undefined}
- */
-goog.global.CLOSURE_UNCOMPILED_DEFINES;
-
-
-/**
- * A hook for overriding the define values in uncompiled or compiled mode,
- * like CLOSURE_UNCOMPILED_DEFINES but effective in compiled code. In
- * uncompiled code CLOSURE_UNCOMPILED_DEFINES takes precedence.
- *
- * Also unlike CLOSURE_UNCOMPILED_DEFINES the values must be number, boolean or
- * string literals or the compiler will emit an error.
- *
- * While any @define value may be set, only those set with goog.define will be
- * effective for uncompiled code.
- *
- * Example:
- * <pre>
- * var CLOSURE_DEFINES = {'goog.DEBUG': false};
- * </pre>
- *
- * @type {Object<string, (string|number|boolean)>|undefined}
- */
-goog.global.CLOSURE_DEFINES;
-
-
-/**
- * Returns true if the specified value is not undefined.
- * WARNING: Do not use this to test if an object has a property. Use the in
- * operator instead.
- *
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is defined.
- */
-goog.isDef = function(val) {
- // void 0 always evaluates to undefined and hence we do not need to depend on
- // the definition of the global variable named 'undefined'.
- return val !== void 0;
-};
-
-
-/**
- * Builds an object structure for the provided namespace path, ensuring that
- * names that already exist are not overwritten. For example:
- * "a.b.c" -> a = {};a.b={};a.b.c={};
- * Used by goog.provide and goog.exportSymbol.
- * @param {string} name name of the object that this file defines.
- * @param {*=} opt_object the object to expose at the end of the path.
- * @param {Object=} opt_objectToExportTo The object to add the path to; default
- * is |goog.global|.
- * @private
- */
-goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
- var parts = name.split('.');
- var cur = opt_objectToExportTo || goog.global;
-
- // Internet Explorer exhibits strange behavior when throwing errors from
- // methods externed in this manner. See the testExportSymbolExceptions in
- // base_test.html for an example.
- if (!(parts[0] in cur) && cur.execScript) {
- cur.execScript('var ' + parts[0]);
- }
-
- // Certain browsers cannot parse code in the form for((a in b); c;);
- // This pattern is produced by the JSCompiler when it collapses the
- // statement above into the conditional loop below. To prevent this from
- // happening, use a for-loop and reserve the init logic as below.
-
- // Parentheses added to eliminate strict JS warning in Firefox.
- for (var part; parts.length && (part = parts.shift());) {
- if (!parts.length && goog.isDef(opt_object)) {
- // last part and we have an object; use it
- cur[part] = opt_object;
- } else if (cur[part]) {
- cur = cur[part];
- } else {
- cur = cur[part] = {};
- }
- }
-};
-
-
-/**
- * Defines a named value. In uncompiled mode, the value is retreived from
- * CLOSURE_DEFINES or CLOSURE_UNCOMPILED_DEFINES if the object is defined and
- * has the property specified, and otherwise used the defined defaultValue.
- * When compiled, the default can be overridden using compiler command-line
- * options.
- *
- * @param {string} name The distinguished name to provide.
- * @param {string|number|boolean} defaultValue
- */
-goog.define = function(name, defaultValue) {
- var value = defaultValue;
- if (!COMPILED) {
- if (goog.global.CLOSURE_UNCOMPILED_DEFINES &&
- Object.prototype.hasOwnProperty.call(
- goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {
- value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];
- } else if (goog.global.CLOSURE_DEFINES &&
- Object.prototype.hasOwnProperty.call(
- goog.global.CLOSURE_DEFINES, name)) {
- value = goog.global.CLOSURE_DEFINES[name];
- }
- }
- goog.exportPath_(name, value);
-};
-
-
-/**
- * @define {boolean} DEBUG is provided as a convenience so that debugging code
- * that should not be included in a production js_binary can be easily stripped
- * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most
- * toString() methods should be declared inside an "if (goog.DEBUG)" conditional
- * because they are generally used for debugging purposes and it is difficult
- * for the JSCompiler to statically determine whether they are used.
- */
-goog.DEBUG = true;
-
-
-/**
- * @define {string} LOCALE defines the locale being used for compilation. It is
- * used to select locale specific data to be compiled in js binary. BUILD rule
- * can specify this value by "--define goog.LOCALE=<locale_name>" as JSCompiler
- * option.
- *
- * Take into account that the locale code format is important. You should use
- * the canonical Unicode format with hyphen as a delimiter. Language must be
- * lowercase, Language Script - Capitalized, Region - UPPERCASE.
- * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
- *
- * See more info about locale codes here:
- * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
- *
- * For language codes you should use values defined by ISO 693-1. See it here
- * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
- * this rule: the Hebrew language. For legacy reasons the old code (iw) should
- * be used instead of the new code (he), see http://wiki/Main/IIISynonyms.
- */
-goog.define('goog.LOCALE', 'en'); // default to en
-
-
-/**
- * @define {boolean} Whether this code is running on trusted sites.
- *
- * On untrusted sites, several native functions can be defined or overridden by
- * external libraries like Prototype, Datejs, and JQuery and setting this flag
- * to false forces closure to use its own implementations when possible.
- *
- * If your JavaScript can be loaded by a third party site and you are wary about
- * relying on non-standard implementations, specify
- * "--define goog.TRUSTED_SITE=false" to the JSCompiler.
- */
-goog.define('goog.TRUSTED_SITE', true);
-
-
-/**
- * @define {boolean} Whether a project is expected to be running in strict mode.
- *
- * This define can be used to trigger alternate implementations compatible with
- * running in EcmaScript Strict mode or warn about unavailable functionality.
- * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
- */
-goog.define('goog.STRICT_MODE_COMPATIBLE', false);
-
-
-/**
- * Creates object stubs for a namespace. The presence of one or more
- * goog.provide() calls indicate that the file defines the given
- * objects/namespaces. Provided objects must not be null or undefined.
- * Build tools also scan for provide/require statements
- * to discern dependencies, build dependency files (see deps.js), etc.
- * @see goog.require
- * @param {string} name Namespace provided by this file in the form
- * "goog.package.part".
- */
-goog.provide = function(name) {
- if (!COMPILED) {
- // Ensure that the same namespace isn't provided twice. This is intended
- // to teach new developers that 'goog.provide' is effectively a variable
- // declaration. And when JSCompiler transforms goog.provide into a real
- // variable declaration, the compiled JS should work the same as the raw
- // JS--even when the raw JS uses goog.provide incorrectly.
- if (goog.isProvided_(name)) {
- throw Error('Namespace "' + name + '" already declared.');
- }
- delete goog.implicitNamespaces_[name];
-
- var namespace = name;
- while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
- if (goog.getObjectByName(namespace)) {
- break;
- }
- goog.implicitNamespaces_[namespace] = true;
- }
- }
-
- goog.exportPath_(name);
-};
-
-
-/**
- * Marks that the current file should only be used for testing, and never for
- * live code in production.
- *
- * In the case of unit tests, the message may optionally be an exact namespace
- * for the test (e.g. 'goog.stringTest'). The linter will then ignore the extra
- * provide (if not explicitly defined in the code).
- *
- * @param {string=} opt_message Optional message to add to the error that's
- * raised when used in production code.
- */
-goog.setTestOnly = function(opt_message) {
- if (COMPILED && !goog.DEBUG) {
- opt_message = opt_message || '';
- throw Error('Importing test-only code into non-debug environment' +
- opt_message ? ': ' + opt_message : '.');
- }
-};
-
-
-/**
- * Forward declares a symbol. This is an indication to the compiler that the
- * symbol may be used in the source yet is not required and may not be provided
- * in compilation.
- *
- * The most common usage of forward declaration is code that takes a type as a
- * function parameter but does not need to require it. By forward declaring
- * instead of requiring, no hard dependency is made, and (if not required
- * elsewhere) the namespace may never be required and thus, not be pulled
- * into the JavaScript binary. If it is required elsewhere, it will be type
- * checked as normal.
- *
- *
- * @param {string} name The namespace to forward declare in the form of
- * "goog.package.part".
- */
-goog.forwardDeclare = function(name) {};
-
-
-if (!COMPILED) {
-
- /**
- * Check if the given name has been goog.provided. This will return false for
- * names that are available only as implicit namespaces.
- * @param {string} name name of the object to look for.
- * @return {boolean} Whether the name has been provided.
- * @private
- */
- goog.isProvided_ = function(name) {
- return !goog.implicitNamespaces_[name] &&
- goog.isDefAndNotNull(goog.getObjectByName(name));
- };
-
- /**
- * Namespaces implicitly defined by goog.provide. For example,
- * goog.provide('goog.events.Event') implicitly declares that 'goog' and
- * 'goog.events' must be namespaces.
- *
- * @type {Object}
- * @private
- */
- goog.implicitNamespaces_ = {};
-}
-
-
-/**
- * Returns an object based on its fully qualified external name. The object
- * is not found if null or undefined. If you are using a compilation pass that
- * renames property names beware that using this function will not find renamed
- * properties.
- *
- * @param {string} name The fully qualified name.
- * @param {Object=} opt_obj The object within which to look; default is
- * |goog.global|.
- * @return {?} The value (object or primitive) or, if not found, null.
- */
-goog.getObjectByName = function(name, opt_obj) {
- var parts = name.split('.');
- var cur = opt_obj || goog.global;
- for (var part; part = parts.shift(); ) {
- if (goog.isDefAndNotNull(cur[part])) {
- cur = cur[part];
- } else {
- return null;
- }
- }
- return cur;
-};
-
-
-/**
- * Globalizes a whole namespace, such as goog or goog.lang.
- *
- * @param {Object} obj The namespace to globalize.
- * @param {Object=} opt_global The object to add the properties to.
- * @deprecated Properties may be explicitly exported to the global scope, but
- * this should no longer be done in bulk.
- */
-goog.globalize = function(obj, opt_global) {
- var global = opt_global || goog.global;
- for (var x in obj) {
- global[x] = obj[x];
- }
-};
-
-
-/**
- * Adds a dependency from a file to the files it requires.
- * @param {string} relPath The path to the js file.
- * @param {Array} provides An array of strings with the names of the objects
- * this file provides.
- * @param {Array} requires An array of strings with the names of the objects
- * this file requires.
- */
-goog.addDependency = function(relPath, provides, requires) {
- if (goog.DEPENDENCIES_ENABLED) {
- var provide, require;
- var path = relPath.replace(/\\/g, '/');
- var deps = goog.dependencies_;
- for (var i = 0; provide = provides[i]; i++) {
- deps.nameToPath[provide] = path;
- if (!(path in deps.pathToNames)) {
- deps.pathToNames[path] = {};
- }
- deps.pathToNames[path][provide] = true;
- }
- for (var j = 0; require = requires[j]; j++) {
- if (!(path in deps.requires)) {
- deps.requires[path] = {};
- }
- deps.requires[path][require] = true;
- }
- }
-};
-
-
-
-
-// NOTE(nnaze): The debug DOM loader was included in base.js as an original way
-// to do "debug-mode" development. The dependency system can sometimes be
-// confusing, as can the debug DOM loader's asynchronous nature.
-//
-// With the DOM loader, a call to goog.require() is not blocking -- the script
-// will not load until some point after the current script. If a namespace is
-// needed at runtime, it needs to be defined in a previous script, or loaded via
-// require() with its registered dependencies.
-// User-defined namespaces may need their own deps file. See http://go/js_deps,
-// http://go/genjsdeps, or, externally, DepsWriter.
-// http://code.google.com/closure/library/docs/depswriter.html
-//
-// Because of legacy clients, the DOM loader can't be easily removed from
-// base.js. Work is being done to make it disableable or replaceable for
-// different environments (DOM-less JavaScript interpreters like Rhino or V8,
-// for example). See bootstrap/ for more information.
-
-
-/**
- * @define {boolean} Whether to enable the debug loader.
- *
- * If enabled, a call to goog.require() will attempt to load the namespace by
- * appending a script tag to the DOM (if the namespace has been registered).
- *
- * If disabled, goog.require() will simply assert that the namespace has been
- * provided (and depend on the fact that some outside tool correctly ordered
- * the script).
- */
-goog.define('goog.ENABLE_DEBUG_LOADER', true);
-
-
-/**
- * Implements a system for the dynamic resolution of dependencies that works in
- * parallel with the BUILD system. Note that all calls to goog.require will be
- * stripped by the JSCompiler when the --closure_pass option is used.
- * @see goog.provide
- * @param {string} name Namespace to include (as was given in goog.provide()) in
- * the form "goog.package.part".
- */
-goog.require = function(name) {
-
- // If the object already exists we do not need do do anything.
- // TODO(arv): If we start to support require based on file name this has to
- // change.
- // TODO(arv): If we allow goog.foo.* this has to change.
- // TODO(arv): If we implement dynamic load after page load we should probably
- // not remove this code for the compiled output.
- if (!COMPILED) {
- if (goog.isProvided_(name)) {
- return;
- }
-
- if (goog.ENABLE_DEBUG_LOADER) {
- var path = goog.getPathFromDeps_(name);
- if (path) {
- goog.included_[path] = true;
- goog.writeScripts_();
- return;
- }
- }
-
- var errorMessage = 'goog.require could not find: ' + name;
- if (goog.global.console) {
- goog.global.console['error'](errorMessage);
- }
-
-
- throw Error(errorMessage);
-
- }
-};
-
-
-/**
- * Path for included scripts.
- * @type {string}
- */
-goog.basePath = '';
-
-
-/**
- * A hook for overriding the base path.
- * @type {string|undefined}
- */
-goog.global.CLOSURE_BASE_PATH;
-
-
-/**
- * Whether to write out Closure's deps file. By default, the deps are written.
- * @type {boolean|undefined}
- */
-goog.global.CLOSURE_NO_DEPS = true;
-
-
-/**
- * A function to import a single script. This is meant to be overridden when
- * Closure is being run in non-HTML contexts, such as web workers. It's defined
- * in the global scope so that it can be set before base.js is loaded, which
- * allows deps.js to be imported properly.
- *
- * The function is passed the script source, which is a relative URI. It should
- * return true if the script was imported, false otherwise.
- * @type {(function(string): boolean)|undefined}
- */
-goog.global.CLOSURE_IMPORT_SCRIPT;
-
-
-/**
- * Null function used for default values of callbacks, etc.
- * @return {void} Nothing.
- */
-goog.nullFunction = function() {};
-
-
-/**
- * The identity function. Returns its first argument.
- *
- * @param {*=} opt_returnValue The single value that will be returned.
- * @param {...*} var_args Optional trailing arguments. These are ignored.
- * @return {?} The first argument. We can't know the type -- just pass it along
- * without type.
- * @deprecated Use goog.functions.identity instead.
- */
-goog.identityFunction = function(opt_returnValue, var_args) {
- return opt_returnValue;
-};
-
-
-/**
- * When defining a class Foo with an abstract method bar(), you can do:
- * Foo.prototype.bar = goog.abstractMethod
- *
- * Now if a subclass of Foo fails to override bar(), an error will be thrown
- * when bar() is invoked.
- *
- * Note: This does not take the name of the function to override as an argument
- * because that would make it more difficult to obfuscate our JavaScript code.
- *
- * @type {!Function}
- * @throws {Error} when invoked to indicate the method should be overridden.
- */
-goog.abstractMethod = function() {
- throw Error('unimplemented abstract method');
-};
-
-
-/**
- * Adds a {@code getInstance} static method that always returns the same
- * instance object.
- * @param {!Function} ctor The constructor for the class to add the static
- * method to.
- */
-goog.addSingletonGetter = function(ctor) {
- ctor.getInstance = function() {
- if (ctor.instance_) {
- return ctor.instance_;
- }
- if (goog.DEBUG) {
- // NOTE: JSCompiler can't optimize away Array#push.
- goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;
- }
- return ctor.instance_ = new ctor;
- };
-};
-
-
-/**
- * All singleton classes that have been instantiated, for testing. Don't read
- * it directly, use the {@code goog.testing.singleton} module. The compiler
- * removes this variable if unused.
- * @type {!Array<!Function>}
- * @private
- */
-goog.instantiatedSingletons_ = [];
-
-
-/**
- * True if goog.dependencies_ is available.
- * @const {boolean}
- */
-goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
-
-
-if (goog.DEPENDENCIES_ENABLED) {
- /**
- * Object used to keep track of urls that have already been added. This record
- * allows the prevention of circular dependencies.
- * @type {Object}
- * @private
- */
- goog.included_ = {};
-
-
- /**
- * This object is used to keep track of dependencies and other data that is
- * used for loading scripts.
- * @private
- * @type {Object}
- */
- goog.dependencies_ = {
- pathToNames: {}, // 1 to many
- nameToPath: {}, // 1 to 1
- requires: {}, // 1 to many
- // Used when resolving dependencies to prevent us from visiting file twice.
- visited: {},
- written: {} // Used to keep track of script files we have written.
- };
-
-
- /**
- * Tries to detect whether is in the context of an HTML document.
- * @return {boolean} True if it looks like HTML document.
- * @private
- */
- goog.inHtmlDocument_ = function() {
- var doc = goog.global.document;
- return typeof doc != 'undefined' &&
- 'write' in doc; // XULDocument misses write.
- };
-
-
- /**
- * Tries to detect the base path of base.js script that bootstraps Closure.
- * @private
- */
- goog.findBasePath_ = function() {
- if (goog.global.CLOSURE_BASE_PATH) {
- goog.basePath = goog.global.CLOSURE_BASE_PATH;
- return;
- } else if (!goog.inHtmlDocument_()) {
- return;
- }
- var doc = goog.global.document;
- var scripts = doc.getElementsByTagName('script');
- // Search backwards since the current script is in almost all cases the one
- // that has base.js.
- for (var i = scripts.length - 1; i >= 0; --i) {
- var src = scripts[i].src;
- var qmark = src.lastIndexOf('?');
- var l = qmark == -1 ? src.length : qmark;
- if (src.substr(l - 7, 7) == 'base.js') {
- goog.basePath = src.substr(0, l - 7);
- return;
- }
- }
- };
-
-
- /**
- * Imports a script if, and only if, that script hasn't already been imported.
- * (Must be called at execution time)
- * @param {string} src Script source.
- * @private
- */
- goog.importScript_ = function(src) {
- var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
- goog.writeScriptTag_;
- if (!goog.dependencies_.written[src] && importScript(src)) {
- goog.dependencies_.written[src] = true;
- }
- };
-
-
- /**
- * The default implementation of the import function. Writes a script tag to
- * import the script.
- *
- * @param {string} src The script source.
- * @return {boolean} True if the script was imported, false otherwise.
- * @private
- */
- goog.writeScriptTag_ = function(src) {
- if (goog.inHtmlDocument_()) {
- var doc = goog.global.document;
-
- // If the user tries to require a new symbol after document load,
- // something has gone terribly wrong. Doing a document.write would
- // wipe out the page.
- if (doc.readyState == 'complete') {
- // Certain test frameworks load base.js multiple times, which tries
- // to write deps.js each time. If that happens, just fail silently.
- // These frameworks wipe the page between each load of base.js, so this
- // is OK.
- var isDeps = /\bdeps.js$/.test(src);
- if (isDeps) {
- return false;
- } else {
- throw Error('Cannot write "' + src + '" after document load');
- }
- }
-
- doc.write(
- '<script type="text/javascript" src="' + src + '"></' + 'script>');
- return true;
- } else {
- return false;
- }
- };
-
-
- /**
- * Resolves dependencies based on the dependencies added using addDependency
- * and calls importScript_ in the correct order.
- * @private
- */
- goog.writeScripts_ = function() {
- // The scripts we need to write this time.
- var scripts = [];
- var seenScript = {};
- var deps = goog.dependencies_;
-
- function visitNode(path) {
- if (path in deps.written) {
- return;
- }
-
- // We have already visited this one. We can get here if we have cyclic
- // dependencies.
- if (path in deps.visited) {
- if (!(path in seenScript)) {
- seenScript[path] = true;
- scripts.push(path);
- }
- return;
- }
-
- deps.visited[path] = true;
-
- if (path in deps.requires) {
- for (var requireName in deps.requires[path]) {
- // If the required name is defined, we assume that it was already
- // bootstrapped by other means.
- if (!goog.isProvided_(requireName)) {
- if (requireName in deps.nameToPath) {
- visitNode(deps.nameToPath[requireName]);
- } else {
- throw Error('Undefined nameToPath for ' + requireName);
- }
- }
- }
- }
-
- if (!(path in seenScript)) {
- seenScript[path] = true;
- scripts.push(path);
- }
- }
-
- for (var path in goog.included_) {
- if (!deps.written[path]) {
- visitNode(path);
- }
- }
-
- for (var i = 0; i < scripts.length; i++) {
- if (scripts[i]) {
- goog.importScript_(goog.basePath + scripts[i]);
- } else {
- throw Error('Undefined script input');
- }
- }
- };
-
-
- /**
- * Looks at the dependency rules and tries to determine the script file that
- * fulfills a particular rule.
- * @param {string} rule In the form goog.namespace.Class or project.script.
- * @return {?string} Url corresponding to the rule, or null.
- * @private
- */
- goog.getPathFromDeps_ = function(rule) {
- if (rule in goog.dependencies_.nameToPath) {
- return goog.dependencies_.nameToPath[rule];
- } else {
- return null;
- }
- };
-
- goog.findBasePath_();
-
- // Allow projects to manage the deps files themselves.
- if (!goog.global.CLOSURE_NO_DEPS) {
- goog.importScript_(goog.basePath + 'deps.js');
- }
-}
-
-
-
-//==============================================================================
-// Language Enhancements
-//==============================================================================
-
-
-/**
- * This is a "fixed" version of the typeof operator. It differs from the typeof
- * operator in such a way that null returns 'null' and arrays return 'array'.
- * @param {*} value The value to get the type of.
- * @return {string} The name of the type.
- */
-goog.typeOf = function(value) {
- var s = typeof value;
- if (s == 'object') {
- if (value) {
- // Check these first, so we can avoid calling Object.prototype.toString if
- // possible.
- //
- // IE improperly marshals tyepof across execution contexts, but a
- // cross-context object will still return false for "instanceof Object".
- if (value instanceof Array) {
- return 'array';
- } else if (value instanceof Object) {
- return s;
- }
-
- // HACK: In order to use an Object prototype method on the arbitrary
- // value, the compiler requires the value be cast to type Object,
- // even though the ECMA spec explicitly allows it.
- var className = Object.prototype.toString.call(
- /** @type {Object} */ (value));
- // In Firefox 3.6, attempting to access iframe window objects' length
- // property throws an NS_ERROR_FAILURE, so we need to special-case it
- // here.
- if (className == '[object Window]') {
- return 'object';
- }
-
- // We cannot always use constructor == Array or instanceof Array because
- // different frames have different Array objects. In IE6, if the iframe
- // where the array was created is destroyed, the array loses its
- // prototype. Then dereferencing val.splice here throws an exception, so
- // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
- // so that will work. In this case, this function will return false and
- // most array functions will still work because the array is still
- // array-like (supports length and []) even though it has lost its
- // prototype.
- // Mark Miller noticed that Object.prototype.toString
- // allows access to the unforgeable [[Class]] property.
- // 15.2.4.2 Object.prototype.toString ( )
- // When the toString method is called, the following steps are taken:
- // 1. Get the [[Class]] property of this object.
- // 2. Compute a string value by concatenating the three strings
- // "[object ", Result(1), and "]".
- // 3. Return Result(2).
- // and this behavior survives the destruction of the execution context.
- if ((className == '[object Array]' ||
- // In IE all non value types are wrapped as objects across window
- // boundaries (not iframe though) so we have to do object detection
- // for this edge case.
- typeof value.length == 'number' &&
- typeof value.splice != 'undefined' &&
- typeof value.propertyIsEnumerable != 'undefined' &&
- !value.propertyIsEnumerable('splice')
-
- )) {
- return 'array';
- }
- // HACK: There is still an array case that fails.
- // function ArrayImpostor() {}
- // ArrayImpostor.prototype = [];
- // var impostor = new ArrayImpostor;
- // this can be fixed by getting rid of the fast path
- // (value instanceof Array) and solely relying on
- // (value && Object.prototype.toString.vall(value) === '[object Array]')
- // but that would require many more function calls and is not warranted
- // unless closure code is receiving objects from untrusted sources.
-
- // IE in cross-window calls does not correctly marshal the function type
- // (it appears just as an object) so we cannot use just typeof val ==
- // 'function'. However, if the object has a call property, it is a
- // function.
- if ((className == '[object Function]' ||
- typeof value.call != 'undefined' &&
- typeof value.propertyIsEnumerable != 'undefined' &&
- !value.propertyIsEnumerable('call'))) {
- return 'function';
- }
-
- } else {
- return 'null';
- }
-
- } else if (s == 'function' && typeof value.call == 'undefined') {
- // In Safari typeof nodeList returns 'function', and on Firefox typeof
- // behaves similarly for HTML{Applet,Embed,Object}, Elements and RegExps. We
- // would like to return object for those and we can detect an invalid
- // function by making sure that the function object has a call method.
- return 'object';
- }
- return s;
-};
-
-
-/**
- * Returns true if the specified value is null.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is null.
- */
-goog.isNull = function(val) {
- return val === null;
-};
-
-
-/**
- * Returns true if the specified value is defined and not null.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is defined and not null.
- */
-goog.isDefAndNotNull = function(val) {
- // Note that undefined == null.
- return val != null;
-};
-
-
-/**
- * Returns true if the specified value is an array.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is an array.
- */
-goog.isArray = function(val) {
- return goog.typeOf(val) == 'array';
-};
-
-
-/**
- * Returns true if the object looks like an array. To qualify as array like
- * the value needs to be either a NodeList or an object with a Number length
- * property.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is an array.
- */
-goog.isArrayLike = function(val) {
- var type = goog.typeOf(val);
- return type == 'array' || type == 'object' && typeof val.length == 'number';
-};
-
-
-/**
- * Returns true if the object looks like a Date. To qualify as Date-like the
- * value needs to be an object and have a getFullYear() function.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is a like a Date.
- */
-goog.isDateLike = function(val) {
- return goog.isObject(val) && typeof val.getFullYear == 'function';
-};
-
-
-/**
- * Returns true if the specified value is a string.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is a string.
- */
-goog.isString = function(val) {
- return typeof val == 'string';
-};
-
-
-/**
- * Returns true if the specified value is a boolean.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is boolean.
- */
-goog.isBoolean = function(val) {
- return typeof val == 'boolean';
-};
-
-
-/**
- * Returns true if the specified value is a number.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is a number.
- */
-goog.isNumber = function(val) {
- return typeof val == 'number';
-};
-
-
-/**
- * Returns true if the specified value is a function.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is a function.
- */
-goog.isFunction = function(val) {
- return goog.typeOf(val) == 'function';
-};
-
-
-/**
- * Returns true if the specified value is an object. This includes arrays and
- * functions.
- * @param {?} val Variable to test.
- * @return {boolean} Whether variable is an object.
- */
-goog.isObject = function(val) {
- var type = typeof val;
- return type == 'object' && val != null || type == 'function';
- // return Object(val) === val also works, but is slower, especially if val is
- // not an object.
-};
-
-
-/**
- * Gets a unique ID for an object. This mutates the object so that further calls
- * with the same object as a parameter returns the same value. The unique ID is
- * guaranteed to be unique across the current session amongst objects that are
- * passed into {@code getUid}. There is no guarantee that the ID is unique or
- * consistent across sessions. It is unsafe to generate unique ID for function
- * prototypes.
- *
- * @param {Object} obj The object to get the unique ID for.
- * @return {number} The unique ID for the object.
- */
-goog.getUid = function(obj) {
- // TODO(arv): Make the type stricter, do not accept null.
-
- // In Opera window.hasOwnProperty exists but always returns false so we avoid
- // using it. As a consequence the unique ID generated for BaseClass.prototype
- // and SubClass.prototype will be the same.
- return obj[goog.UID_PROPERTY_] ||
- (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
-};
-
-
-/**
- * Whether the given object is alreay assigned a unique ID.
- *
- * This does not modify the object.
- *
- * @param {Object} obj The object to check.
- * @return {boolean} Whether there an assigned unique id for the object.
- */
-goog.hasUid = function(obj) {
- return !!obj[goog.UID_PROPERTY_];
-};
-
-
-/**
- * Removes the unique ID from an object. This is useful if the object was
- * previously mutated using {@code goog.getUid} in which case the mutation is
- * undone.
- * @param {Object} obj The object to remove the unique ID field from.
- */
-goog.removeUid = function(obj) {
- // TODO(arv): Make the type stricter, do not accept null.
-
- // In IE, DOM nodes are not instances of Object and throw an exception if we
- // try to delete. Instead we try to use removeAttribute.
- if ('removeAttribute' in obj) {
- obj.removeAttribute(goog.UID_PROPERTY_);
- }
- /** @preserveTry */
- try {
- delete obj[goog.UID_PROPERTY_];
- } catch (ex) {
- }
-};
-
-
-/**
- * Name for unique ID property. Initialized in a way to help avoid collisions
- * with other closure JavaScript on the same page.
- * @type {string}
- * @private
- */
-goog.UID_PROPERTY_ = 'closure_uid_' + ((Math.random() * 1e9) >>> 0);
-
-
-/**
- * Counter for UID.
- * @type {number}
- * @private
- */
-goog.uidCounter_ = 0;
-
-
-/**
- * Adds a hash code field to an object. The hash code is unique for the
- * given object.
- * @param {Object} obj The object to get the hash code for.
- * @return {number} The hash code for the object.
- * @deprecated Use goog.getUid instead.
- */
-goog.getHashCode = goog.getUid;
-
-
-/**
- * Removes the hash code field from an object.
- * @param {Object} obj The object to remove the field from.
- * @deprecated Use goog.removeUid instead.
- */
-goog.removeHashCode = goog.removeUid;
-
-
-/**
- * Clones a value. The input may be an Object, Array, or basic type. Objects and
- * arrays will be cloned recursively.
- *
- * WARNINGS:
- * <code>goog.cloneObject</code> does not detect reference loops. Objects that
- * refer to themselves will cause infinite recursion.
- *
- * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies
- * UIDs created by <code>getUid</code> into cloned results.
- *
- * @param {*} obj The value to clone.
- * @return {*} A clone of the input value.
- * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
- */
-goog.cloneObject = function(obj) {
- var type = goog.typeOf(obj);
- if (type == 'object' || type == 'array') {
- if (obj.clone) {
- return obj.clone();
- }
- var clone = type == 'array' ? [] : {};
- for (var key in obj) {
- clone[key] = goog.cloneObject(obj[key]);
- }
- return clone;
- }
-
- return obj;
-};
-
-
-/**
- * A native implementation of goog.bind.
- * @param {Function} fn A function to partially apply.
- * @param {Object|undefined} selfObj Specifies the object which this should
- * point to when the function is run.
- * @param {...*} var_args Additional arguments that are partially applied to the
- * function.
- * @return {!Function} A partially-applied form of the function bind() was
- * invoked as a method of.
- * @private
- * @suppress {deprecated} The compiler thinks that Function.prototype.bind is
- * deprecated because some people have declared a pure-JS version.
- * Only the pure-JS version is truly deprecated.
- */
-goog.bindNative_ = function(fn, selfObj, var_args) {
- return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
-};
-
-
-/**
- * A pure-JS implementation of goog.bind.
- * @param {Function} fn A function to partially apply.
- * @param {Object|undefined} selfObj Specifies the object which this should
- * point to when the function is run.
- * @param {...*} var_args Additional arguments that are partially applied to the
- * function.
- * @return {!Function} A partially-applied form of the function bind() was
- * invoked as a method of.
- * @private
- */
-goog.bindJs_ = function(fn, selfObj, var_args) {
- if (!fn) {
- throw new Error();
- }
-
- if (arguments.length > 2) {
- var boundArgs = Array.prototype.slice.call(arguments, 2);
- return function() {
- // Prepend the bound arguments to the current arguments.
- var newArgs = Array.prototype.slice.call(arguments);
- Array.prototype.unshift.apply(newArgs, boundArgs);
- return fn.apply(selfObj, newArgs);
- };
-
- } else {
- return function() {
- return fn.apply(selfObj, arguments);
- };
- }
-};
-
-
-/**
- * Partially applies this function to a particular 'this object' and zero or
- * more arguments. The result is a new function with some arguments of the first
- * function pre-filled and the value of this 'pre-specified'.
- *
- * Remaining arguments specified at call-time are appended to the pre-specified
- * ones.
- *
- * Also see: {@link #partial}.
- *
- * Usage:
- * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
- * barMethBound('arg3', 'arg4');</pre>
- *
- * @param {?function(this:T, ...)} fn A function to partially apply.
- * @param {T} selfObj Specifies the object which this should point to when the
- * function is run.
- * @param {...*} var_args Additional arguments that are partially applied to the
- * function.
- * @return {!Function} A partially-applied form of the function bind() was
- * invoked as a method of.
- * @template T
- * @suppress {deprecated} See above.
- */
-goog.bind = function(fn, selfObj, var_args) {
- // TODO(nicksantos): narrow the type signature.
- if (Function.prototype.bind &&
- // NOTE(nicksantos): Somebody pulled base.js into the default Chrome
- // extension environment. This means that for Chrome extensions, they get
- // the implementation of Function.prototype.bind that calls goog.bind
- // instead of the native one. Even worse, we don't want to introduce a
- // circular dependency between goog.bind and Function.prototype.bind, so
- // we have to hack this to make sure it works correctly.
- Function.prototype.bind.toString().indexOf('native code') != -1) {
- goog.bind = goog.bindNative_;
- } else {
- goog.bind = goog.bindJs_;
- }
- return goog.bind.apply(null, arguments);
-};
-
-
-/**
- * Like bind(), except that a 'this object' is not required. Useful when the
- * target function is already bound.
- *
- * Usage:
- * var g = partial(f, arg1, arg2);
- * g(arg3, arg4);
- *
- * @param {Function} fn A function to partially apply.
- * @param {...*} var_args Additional arguments that are partially applied to fn.
- * @return {!Function} A partially-applied form of the function bind() was
- * invoked as a method of.
- */
-goog.partial = function(fn, var_args) {
- var args = Array.prototype.slice.call(arguments, 1);
- return function() {
- // Clone the array (with slice()) and append additional arguments
- // to the existing arguments.
- var newArgs = args.slice();
- newArgs.push.apply(newArgs, arguments);
- return fn.apply(this, newArgs);
- };
-};
-
-
-/**
- * Copies all the members of a source object to a target object. This method
- * does not work on all browsers for all objects that contain keys such as
- * toString or hasOwnProperty. Use goog.object.extend for this purpose.
- * @param {Object} target Target.
- * @param {Object} source Source.
- */
-goog.mixin = function(target, source) {
- for (var x in source) {
- target[x] = source[x];
- }
-
- // For IE7 or lower, the for-in-loop does not contain any properties that are
- // not enumerable on the prototype object (for example, isPrototypeOf from
- // Object.prototype) but also it will not include 'replace' on objects that
- // extend String and change 'replace' (not that it is common for anyone to
- // extend anything except Object).
-};
-
-
-/**
- * @return {number} An integer value representing the number of milliseconds
- * between midnight, January 1, 1970 and the current time.
- */
-goog.now = (goog.TRUSTED_SITE && Date.now) || (function() {
- // Unary plus operator converts its operand to a number which in the case of
- // a date is done by calling getTime().
- return +new Date();
-});
-
-
-/**
- * Evals JavaScript in the global scope. In IE this uses execScript, other
- * browsers use goog.global.eval. If goog.global.eval does not evaluate in the
- * global scope (for example, in Safari), appends a script tag instead.
- * Throws an exception if neither execScript or eval is defined.
- * @param {string} script JavaScript string.
- */
-goog.globalEval = function(script) {
- if (goog.global.execScript) {
- goog.global.execScript(script, 'JavaScript');
- } else if (goog.global.eval) {
- // Test to see if eval works
- if (goog.evalWorksForGlobals_ == null) {
- goog.global.eval('var _et_ = 1;');
- if (typeof goog.global['_et_'] != 'undefined') {
- delete goog.global['_et_'];
- goog.evalWorksForGlobals_ = true;
- } else {
- goog.evalWorksForGlobals_ = false;
- }
- }
-
- if (goog.evalWorksForGlobals_) {
- goog.global.eval(script);
- } else {
- var doc = goog.global.document;
- var scriptElt = doc.createElement('script');
- scriptElt.type = 'text/javascript';
- scriptElt.defer = false;
- // Note(user): can't use .innerHTML since "t('<test>')" will fail and
- // .text doesn't work in Safari 2. Therefore we append a text node.
- scriptElt.appendChild(doc.createTextNode(script));
- doc.body.appendChild(scriptElt);
- doc.body.removeChild(scriptElt);
- }
- } else {
- throw Error('goog.globalEval not available');
- }
-};
-
-
-/**
- * Indicates whether or not we can call 'eval' directly to eval code in the
- * global scope. Set to a Boolean by the first call to goog.globalEval (which
- * empirically tests whether eval works for globals). @see goog.globalEval
- * @type {?boolean}
- * @private
- */
-goog.evalWorksForGlobals_ = null;
-
-
-/**
- * Optional map of CSS class names to obfuscated names used with
- * goog.getCssName().
- * @type {Object|undefined}
- * @private
- * @see goog.setCssNameMapping
- */
-goog.cssNameMapping_;
-
-
-/**
- * Optional obfuscation style for CSS class names. Should be set to either
- * 'BY_WHOLE' or 'BY_PART' if defined.
- * @type {string|undefined}
- * @private
- * @see goog.setCssNameMapping
- */
-goog.cssNameMappingStyle_;
-
-
-/**
- * Handles strings that are intended to be used as CSS class names.
- *
- * This function works in tandem with @see goog.setCssNameMapping.
- *
- * Without any mapping set, the arguments are simple joined with a hyphen and
- * passed through unaltered.
- *
- * When there is a mapping, there are two possible styles in which these
- * mappings are used. In the BY_PART style, each part (i.e. in between hyphens)
- * of the passed in css name is rewritten according to the map. In the BY_WHOLE
- * style, the full css name is looked up in the map directly. If a rewrite is
- * not specified by the map, the compiler will output a warning.
- *
- * When the mapping is passed to the compiler, it will replace calls to
- * goog.getCssName with the strings from the mapping, e.g.
- * var x = goog.getCssName('foo');
- * var y = goog.getCssName(this.baseClass, 'active');
- * becomes:
- * var x= 'foo';
- * var y = this.baseClass + '-active';
- *
- * If one argument is passed it will be processed, if two are passed only the
- * modifier will be processed, as it is assumed the first argument was generated
- * as a result of calling goog.getCssName.
- *
- * @param {string} className The class name.
- * @param {string=} opt_modifier A modifier to be appended to the class name.
- * @return {string} The class name or the concatenation of the class name and
- * the modifier.
- */
-goog.getCssName = function(className, opt_modifier) {
- var getMapping = function(cssName) {
- return goog.cssNameMapping_[cssName] || cssName;
- };
-
- var renameByParts = function(cssName) {
- // Remap all the parts individually.
- var parts = cssName.split('-');
- var mapped = [];
- for (var i = 0; i < parts.length; i++) {
- mapped.push(getMapping(parts[i]));
- }
- return mapped.join('-');
- };
-
- var rename;
- if (goog.cssNameMapping_) {
- rename = goog.cssNameMappingStyle_ == 'BY_WHOLE' ?
- getMapping : renameByParts;
- } else {
- rename = function(a) {
- return a;
- };
- }
-
- if (opt_modifier) {
- return className + '-' + rename(opt_modifier);
- } else {
- return rename(className);
- }
-};
-
-
-/**
- * Sets the map to check when returning a value from goog.getCssName(). Example:
- * <pre>
- * goog.setCssNameMapping({
- * "goog": "a",
- * "disabled": "b",
- * });
- *
- * var x = goog.getCssName('goog');
- * // The following evaluates to: "a a-b".
- * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
- * </pre>
- * When declared as a map of string literals to string literals, the JSCompiler
- * will replace all calls to goog.getCssName() using the supplied map if the
- * --closure_pass flag is set.
- *
- * @param {!Object} mapping A map of strings to strings where keys are possible
- * arguments to goog.getCssName() and values are the corresponding values
- * that should be returned.
- * @param {string=} opt_style The style of css name mapping. There are two valid
- * options: 'BY_PART', and 'BY_WHOLE'.
- * @see goog.getCssName for a description.
- */
-goog.setCssNameMapping = function(mapping, opt_style) {
- goog.cssNameMapping_ = mapping;
- goog.cssNameMappingStyle_ = opt_style;
-};
-
-
-/**
- * To use CSS renaming in compiled mode, one of the input files should have a
- * call to goog.setCssNameMapping() with an object literal that the JSCompiler
- * can extract and use to replace all calls to goog.getCssName(). In uncompiled
- * mode, JavaScript code should be loaded before this base.js file that declares
- * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is
- * to ensure that the mapping is loaded before any calls to goog.getCssName()
- * are made in uncompiled mode.
- *
- * A hook for overriding the CSS name mapping.
- * @type {Object|undefined}
- */
-goog.global.CLOSURE_CSS_NAME_MAPPING;
-
-
-if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
- // This does not call goog.setCssNameMapping() because the JSCompiler
- // requires that goog.setCssNameMapping() be called with an object literal.
- goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;
-}
-
-
-/**
- * Gets a localized message.
- *
- * This function is a compiler primitive. If you give the compiler a localized
- * message bundle, it will replace the string at compile-time with a localized
- * version, and expand goog.getMsg call to a concatenated string.
- *
- * Messages must be initialized in the form:
- * <code>
- * var MSG_NAME = goog.getMsg('Hello {$placeholder}', {'placeholder': 'world'});
- * </code>
- *
- * @param {string} str Translatable string, places holders in the form {$foo}.
- * @param {Object=} opt_values Map of place holder name to value.
- * @return {string} message with placeholders filled.
- */
-goog.getMsg = function(str, opt_values) {
- var values = opt_values || {};
- for (var key in values) {
- var value = ('' + values[key]).replace(/\$/g, '$$$$');
- str = str.replace(new RegExp('\\{\\$' + key + '\\}', 'gi'), value);
- }
- return str;
-};
-
-
-/**
- * Gets a localized message. If the message does not have a translation, gives a
- * fallback message.
- *
- * This is useful when introducing a new message that has not yet been
- * translated into all languages.
- *
- * This function is a compiler primitive. Must be used in the form:
- * <code>var x = goog.getMsgWithFallback(MSG_A, MSG_B);</code>
- * where MSG_A and MSG_B were initialized with goog.getMsg.
- *
- * @param {string} a The preferred message.
- * @param {string} b The fallback message.
- * @return {string} The best translated message.
- */
-goog.getMsgWithFallback = function(a, b) {
- return a;
-};
-
-
-/**
- * Exposes an unobfuscated global namespace path for the given object.
- * Note that fields of the exported object *will* be obfuscated, unless they are
- * exported in turn via this function or goog.exportProperty.
- *
- * Also handy for making public items that are defined in anonymous closures.
- *
- * ex. goog.exportSymbol('public.path.Foo', Foo);
- *
- * ex. goog.exportSymbol('public.path.Foo.staticFunction', Foo.staticFunction);
- * public.path.Foo.staticFunction();
- *
- * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
- * Foo.prototype.myMethod);
- * new public.path.Foo().myMethod();
- *
- * @param {string} publicPath Unobfuscated name to export.
- * @param {*} object Object the name should point to.
- * @param {Object=} opt_objectToExportTo The object to add the path to; default
- * is goog.global.
- */
-goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
- goog.exportPath_(publicPath, object, opt_objectToExportTo);
-};
-
-
-/**
- * Exports a property unobfuscated into the object's namespace.
- * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
- * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
- * @param {Object} object Object whose static property is being exported.
- * @param {string} publicName Unobfuscated name to export.
- * @param {*} symbol Object the name should point to.
- */
-goog.exportProperty = function(object, publicName, symbol) {
- object[publicName] = symbol;
-};
-
-
-/**
- * Inherit the prototype methods from one constructor into another.
- *
- * Usage:
- * <pre>
- * function ParentClass(a, b) { }
- * ParentClass.prototype.foo = function(a) { }
- *
- * function ChildClass(a, b, c) {
- * goog.base(this, a, b);
- * }
- * goog.inherits(ChildClass, ParentClass);
- *
- * var child = new ChildClass('a', 'b', 'see');
- * child.foo(); // This works.
- * </pre>
- *
- * In addition, a superclass' implementation of a method can be invoked as
- * follows:
- *
- * <pre>
- * ChildClass.prototype.foo = function(a) {
- * ChildClass.superClass_.foo.call(this, a);
- * // Other code here.
- * };
- * </pre>
- *
- * @param {Function} childCtor Child class.
- * @param {Function} parentCtor Parent class.
- */
-goog.inherits = function(childCtor, parentCtor) {
- /** @constructor */
- function tempCtor() {};
- tempCtor.prototype = parentCtor.prototype;
- childCtor.superClass_ = parentCtor.prototype;
- childCtor.prototype = new tempCtor();
- /** @override */
- childCtor.prototype.constructor = childCtor;
-
- /**
- * Calls superclass constructor/method.
- *
- * This function is only available if you use goog.inherits to
- * express inheritance relationships between classes.
- *
- * NOTE: This is a replacement for goog.base and for superClass_
- * property defined in childCtor.
- *
- * @param {!Object} me Should always be "this".
- * @param {string} methodName The method name to call. Calling
- * superclass constructor can be done with the special string
- * 'constructor'.
- * @param {...*} var_args The arguments to pass to superclass
- * method/constructor.
- * @return {*} The return value of the superclass method/constructor.
- */
- childCtor.base = function(me, methodName, var_args) {
- var args = Array.prototype.slice.call(arguments, 2);
- return parentCtor.prototype[methodName].apply(me, args);
- };
-};
-
-
-/**
- * Call up to the superclass.
- *
- * If this is called from a constructor, then this calls the superclass
- * constructor with arguments 1-N.
- *
- * If this is called from a prototype method, then you must pass the name of the
- * method as the second argument to this function. If you do not, you will get a
- * runtime error. This calls the superclass' method with arguments 2-N.
- *
- * This function only works if you use goog.inherits to express inheritance
- * relationships between your classes.
- *
- * This function is a compiler primitive. At compile-time, the compiler will do
- * macro expansion to remove a lot of the extra overhead that this function
- * introduces. The compiler will also enforce a lot of the assumptions that this
- * function makes, and treat it as a compiler error if you break them.
- *
- * @param {!Object} me Should always be "this".
- * @param {*=} opt_methodName The method name if calling a super method.
- * @param {...*} var_args The rest of the arguments.
- * @return {*} The return value of the superclass method.
- * @suppress {es5Strict} This method can not be used in strict mode, but
- * all Closure Library consumers must depend on this file.
- */
-goog.base = function(me, opt_methodName, var_args) {
- var caller = arguments.callee.caller;
-
- if (goog.STRICT_MODE_COMPATIBLE || (goog.DEBUG && !caller)) {
- throw Error('arguments.caller not defined. goog.base() cannot be used ' +
- 'with strict mode code. See ' +
- 'http://www.ecma-international.org/ecma-262/5.1/#sec-C');
- }
-
- if (caller.superClass_) {
- // This is a constructor. Call the superclass constructor.
- return caller.superClass_.constructor.apply(
- me, Array.prototype.slice.call(arguments, 1));
- }
-
- var args = Array.prototype.slice.call(arguments, 2);
- var foundCaller = false;
- for (var ctor = me.constructor;
- ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
- if (ctor.prototype[opt_methodName] === caller) {
- foundCaller = true;
- } else if (foundCaller) {
- return ctor.prototype[opt_methodName].apply(me, args);
- }
- }
-
- // If we did not find the caller in the prototype chain, then one of two
- // things happened:
- // 1) The caller is an instance method.
- // 2) This method was not called by the right caller.
- if (me[opt_methodName] === caller) {
- return me.constructor.prototype[opt_methodName].apply(me, args);
- } else {
- throw Error(
- 'goog.base called from a method of one name ' +
- 'to a method of a different name');
- }
-};
-
-
-/**
- * Allow for aliasing within scope functions. This function exists for
- * uncompiled code - in compiled code the calls will be inlined and the aliases
- * applied. In uncompiled code the function is simply run since the aliases as
- * written are valid JavaScript.
- * @param {function()} fn Function to call. This function can contain aliases
- * to namespaces (e.g. "var dom = goog.dom") or classes
- * (e.g. "var Timer = goog.Timer").
- */
-goog.scope = function(fn) {
- fn.call(goog.global);
-};
-
-
-/*
- * To support uncompiled, strict mode bundles that use eval to divide source
- * like so:
- * eval('someSource;//# sourceUrl sourcefile.js');
- * We need to export the globally defined symbols "goog" and "COMPILED".
- * Exporting "goog" breaks the compiler optimizations, so we required that
- * be defined externally.
- * NOTE: We don't use goog.exportSymbol here because we don't want to trigger
- * extern generation when that compiler option is enabled.
- */
-if (!COMPILED) {
- goog.global['COMPILED'] = COMPILED;
-}
-
-
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/debug/error.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/debug/error.js
deleted file mode 100644
index 6fed470018e..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/debug/error.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2009 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Provides a base class for custom Error objects such that the
- * stack is correctly maintained.
- *
- * You should never need to throw goog.debug.Error(msg) directly, Error(msg) is
- * sufficient.
- *
- */
-
-goog.provide('goog.debug.Error');
-
-
-
-/**
- * Base class for custom error objects.
- * @param {*=} opt_msg The message associated with the error.
- * @constructor
- * @extends {Error}
- */
-goog.debug.Error = function(opt_msg) {
-
- // Attempt to ensure there is a stack trace.
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, goog.debug.Error);
- } else {
- var stack = new Error().stack;
- if (stack) {
- this.stack = stack;
- }
- }
-
- if (opt_msg) {
- this.message = String(opt_msg);
- }
-};
-goog.inherits(goog.debug.Error, Error);
-
-
-/** @override */
-goog.debug.Error.prototype.name = 'CustomError';
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/dom/nodetype.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/dom/nodetype.js
deleted file mode 100644
index cccb4706eca..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/dom/nodetype.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Definition of goog.dom.NodeType.
- */
-
-goog.provide('goog.dom.NodeType');
-
-
-/**
- * Constants for the nodeType attribute in the Node interface.
- *
- * These constants match those specified in the Node interface. These are
- * usually present on the Node object in recent browsers, but not in older
- * browsers (specifically, early IEs) and thus are given here.
- *
- * In some browsers (early IEs), these are not defined on the Node object,
- * so they are provided here.
- *
- * See http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247
- * @enum {number}
- */
-goog.dom.NodeType = {
- ELEMENT: 1,
- ATTRIBUTE: 2,
- TEXT: 3,
- CDATA_SECTION: 4,
- ENTITY_REFERENCE: 5,
- ENTITY: 6,
- PROCESSING_INSTRUCTION: 7,
- COMMENT: 8,
- DOCUMENT: 9,
- DOCUMENT_TYPE: 10,
- DOCUMENT_FRAGMENT: 11,
- NOTATION: 12
-};
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/messageformat.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/messageformat.js
deleted file mode 100644
index f38f69c440c..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/messageformat.js
+++ /dev/null
@@ -1,764 +0,0 @@
-// Copyright 2010 The Closure Library Authors. All Rights Reserved
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Message/plural format library with locale support.
- *
- * Message format grammar:
- *
- * messageFormatPattern := string ( "{" messageFormatElement "}" string )*
- * messageFormatElement := argumentIndex [ "," elementFormat ]
- * elementFormat := "plural" "," pluralStyle
- * | "selectordinal" "," ordinalStyle
- * | "select" "," selectStyle
- * pluralStyle := pluralFormatPattern
- * ordinalStyle := selectFormatPattern
- * selectStyle := selectFormatPattern
- * pluralFormatPattern := [ "offset" ":" offsetIndex ] pluralForms*
- * selectFormatPattern := pluralForms*
- * pluralForms := stringKey "{" ( "{" messageFormatElement "}"|string )* "}"
- *
- * This is a subset of the ICU MessageFormatSyntax:
- * http://userguide.icu-project.org/formatparse/messages
- * See also http://go/plurals and http://go/ordinals for internal details.
- *
- *
- * Message example:
- *
- * I see {NUM_PEOPLE, plural, offset:1
- * =0 {no one at all}
- * =1 {{WHO}}
- * one {{WHO} and one other person}
- * other {{WHO} and # other people}}
- * in {PLACE}.
- *
- * Calling format({'NUM_PEOPLE': 2, 'WHO': 'Mark', 'PLACE': 'Athens'}) would
- * produce "I see Mark and one other person in Athens." as output.
- *
- * OR:
- *
- * {NUM_FLOOR, selectordinal,
- * one {Take the elevator to the #st floor.}
- * two {Take the elevator to the #nd floor.}
- * few {Take the elevator to the #rd floor.}
- * other {Take the elevator to the #th floor.}}
- *
- * Calling format({'NUM_FLOOR': 22}) would produce
- * "Take the elevator to the 22nd floor".
- *
- * See messageformat_test.html for more examples.
- */
-
-goog.provide('goog.i18n.MessageFormat');
-
-goog.require('goog.asserts');
-goog.require('goog.i18n.ordinalRules');
-goog.require('goog.i18n.pluralRules');
-
-
-
-/**
- * Constructor of MessageFormat.
- * @param {string} pattern The pattern we parse and apply positional parameters
- * to.
- * @constructor
- * @final
- */
-goog.i18n.MessageFormat = function(pattern) {
- /**
- * All encountered literals during parse stage. Indices tell us the order of
- * replacement.
- * @type {!Array<string>}
- * @private
- */
- this.literals_ = [];
-
- /**
- * Input pattern gets parsed into objects for faster formatting.
- * @type {!Array<!Object>}
- * @private
- */
- this.parsedPattern_ = [];
-
- this.parsePattern_(pattern);
-};
-
-
-/**
- * Literal strings, including '', are replaced with \uFDDF_x_ for
- * parsing purposes, and recovered during format phase.
- * \uFDDF is a Unicode nonprinting character, not expected to be found in the
- * typical message.
- * @type {string}
- * @private
- */
-goog.i18n.MessageFormat.LITERAL_PLACEHOLDER_ = '\uFDDF_';
-
-
-/**
- * Marks a string and block during parsing.
- * @enum {number}
- * @private
- */
-goog.i18n.MessageFormat.Element_ = {
- STRING: 0,
- BLOCK: 1
-};
-
-
-/**
- * Block type.
- * @enum {number}
- * @private
- */
-goog.i18n.MessageFormat.BlockType_ = {
- PLURAL: 0,
- ORDINAL: 1,
- SELECT: 2,
- SIMPLE: 3,
- STRING: 4,
- UNKNOWN: 5
-};
-
-
-/**
- * Mandatory option in both select and plural form.
- * @type {string}
- * @private
- */
-goog.i18n.MessageFormat.OTHER_ = 'other';
-
-
-/**
- * Regular expression for looking for string literals.
- * @type {RegExp}
- * @private
- */
-goog.i18n.MessageFormat.REGEX_LITERAL_ = new RegExp("'([{}#].*?)'", 'g');
-
-
-/**
- * Regular expression for looking for '' in the message.
- * @type {RegExp}
- * @private
- */
-goog.i18n.MessageFormat.REGEX_DOUBLE_APOSTROPHE_ = new RegExp("''", 'g');
-
-
-/**
- * Formats a message, treating '#' with special meaning representing
- * the number (plural_variable - offset).
- * @param {!Object} namedParameters Parameters that either
- * influence the formatting or are used as actual data.
- * I.e. in call to fmt.format({'NUM_PEOPLE': 5, 'NAME': 'Angela'}),
- * object {'NUM_PEOPLE': 5, 'NAME': 'Angela'} holds positional parameters.
- * 1st parameter could mean 5 people, which could influence plural format,
- * and 2nd parameter is just a data to be printed out in proper position.
- * @return {string} Formatted message.
- */
-goog.i18n.MessageFormat.prototype.format = function(namedParameters) {
- return this.format_(namedParameters, false);
-};
-
-
-/**
- * Formats a message, treating '#' as literary character.
- * @param {!Object} namedParameters Parameters that either
- * influence the formatting or are used as actual data.
- * I.e. in call to fmt.format({'NUM_PEOPLE': 5, 'NAME': 'Angela'}),
- * object {'NUM_PEOPLE': 5, 'NAME': 'Angela'} holds positional parameters.
- * 1st parameter could mean 5 people, which could influence plural format,
- * and 2nd parameter is just a data to be printed out in proper position.
- * @return {string} Formatted message.
- */
-goog.i18n.MessageFormat.prototype.formatIgnoringPound =
- function(namedParameters) {
- return this.format_(namedParameters, true);
-};
-
-
-/**
- * Formats a message.
- * @param {!Object} namedParameters Parameters that either
- * influence the formatting or are used as actual data.
- * I.e. in call to fmt.format({'NUM_PEOPLE': 5, 'NAME': 'Angela'}),
- * object {'NUM_PEOPLE': 5, 'NAME': 'Angela'} holds positional parameters.
- * 1st parameter could mean 5 people, which could influence plural format,
- * and 2nd parameter is just a data to be printed out in proper position.
- * @param {boolean} ignorePound If true, treat '#' in plural messages as a
- * literary character, else treat it as an ICU syntax character, resolving
- * to the number (plural_variable - offset).
- * @return {string} Formatted message.
- * @private
- */
-goog.i18n.MessageFormat.prototype.format_ =
- function(namedParameters, ignorePound) {
- if (this.parsedPattern_.length == 0) {
- return '';
- }
-
- var result = [];
- this.formatBlock_(this.parsedPattern_, namedParameters, ignorePound, result);
- var message = result.join('');
-
- if (!ignorePound) {
- goog.asserts.assert(message.search('#') == -1, 'Not all # were replaced.');
- }
-
- while (this.literals_.length > 0) {
- message = message.replace(this.buildPlaceholder_(this.literals_),
- this.literals_.pop());
- }
-
- return message;
-};
-
-
-/**
- * Parses generic block and returns a formatted string.
- * @param {!Array<!Object>} parsedPattern Holds parsed tree.
- * @param {!Object} namedParameters Parameters that either influence
- * the formatting or are used as actual data.
- * @param {boolean} ignorePound If true, treat '#' in plural messages as a
- * literary character, else treat it as an ICU syntax character, resolving
- * to the number (plural_variable - offset).
- * @param {!Array<!string>} result Each formatting stage appends its product
- * to the result.
- * @private
- */
-goog.i18n.MessageFormat.prototype.formatBlock_ = function(
- parsedPattern, namedParameters, ignorePound, result) {
- for (var i = 0; i < parsedPattern.length; i++) {
- switch (parsedPattern[i].type) {
- case goog.i18n.MessageFormat.BlockType_.STRING:
- result.push(parsedPattern[i].value);
- break;
- case goog.i18n.MessageFormat.BlockType_.SIMPLE:
- var pattern = parsedPattern[i].value;
- this.formatSimplePlaceholder_(pattern, namedParameters, result);
- break;
- case goog.i18n.MessageFormat.BlockType_.SELECT:
- var pattern = parsedPattern[i].value;
- this.formatSelectBlock_(pattern, namedParameters, ignorePound, result);
- break;
- case goog.i18n.MessageFormat.BlockType_.PLURAL:
- var pattern = parsedPattern[i].value;
- this.formatPluralOrdinalBlock_(pattern,
- namedParameters,
- goog.i18n.pluralRules.select,
- ignorePound,
- result);
- break;
- case goog.i18n.MessageFormat.BlockType_.ORDINAL:
- var pattern = parsedPattern[i].value;
- this.formatPluralOrdinalBlock_(pattern,
- namedParameters,
- goog.i18n.ordinalRules.select,
- ignorePound,
- result);
- break;
- default:
- goog.asserts.fail('Unrecognized block type.');
- }
- }
-};
-
-
-/**
- * Formats simple placeholder.
- * @param {!Object} parsedPattern JSON object containing placeholder info.
- * @param {!Object} namedParameters Parameters that are used as actual data.
- * @param {!Array<!string>} result Each formatting stage appends its product
- * to the result.
- * @private
- */
-goog.i18n.MessageFormat.prototype.formatSimplePlaceholder_ = function(
- parsedPattern, namedParameters, result) {
- var value = namedParameters[parsedPattern];
- if (!goog.isDef(value)) {
- result.push('Undefined parameter - ' + parsedPattern);
- return;
- }
-
- // Don't push the value yet, it may contain any of # { } in it which
- // will break formatter. Insert a placeholder and replace at the end.
- this.literals_.push(value);
- result.push(this.buildPlaceholder_(this.literals_));
-};
-
-
-/**
- * Formats select block. Only one option is selected.
- * @param {!Object} parsedPattern JSON object containing select block info.
- * @param {!Object} namedParameters Parameters that either influence
- * the formatting or are used as actual data.
- * @param {boolean} ignorePound If true, treat '#' in plural messages as a
- * literary character, else treat it as an ICU syntax character, resolving
- * to the number (plural_variable - offset).
- * @param {!Array<!string>} result Each formatting stage appends its product
- * to the result.
- * @private
- */
-goog.i18n.MessageFormat.prototype.formatSelectBlock_ = function(
- parsedPattern, namedParameters, ignorePound, result) {
- var argumentIndex = parsedPattern.argumentIndex;
- if (!goog.isDef(namedParameters[argumentIndex])) {
- result.push('Undefined parameter - ' + argumentIndex);
- return;
- }
-
- var option = parsedPattern[namedParameters[argumentIndex]];
- if (!goog.isDef(option)) {
- option = parsedPattern[goog.i18n.MessageFormat.OTHER_];
- goog.asserts.assertArray(
- option, 'Invalid option or missing other option for select block.');
- }
-
- this.formatBlock_(option, namedParameters, ignorePound, result);
-};
-
-
-/**
- * Formats plural or selectordinal block. Only one option is selected and all #
- * are replaced.
- * @param {!Object} parsedPattern JSON object containing plural block info.
- * @param {!Object} namedParameters Parameters that either influence
- * the formatting or are used as actual data.
- * @param {!function(number, number=):string} pluralSelector A select function
- * from goog.i18n.pluralRules or goog.i18n.ordinalRules which determines
- * which plural/ordinal form to use based on the input number's cardinality.
- * @param {boolean} ignorePound If true, treat '#' in plural messages as a
- * literary character, else treat it as an ICU syntax character, resolving
- * to the number (plural_variable - offset).
- * @param {!Array<!string>} result Each formatting stage appends its product
- * to the result.
- * @private
- */
-goog.i18n.MessageFormat.prototype.formatPluralOrdinalBlock_ = function(
- parsedPattern, namedParameters, pluralSelector, ignorePound, result) {
- var argumentIndex = parsedPattern.argumentIndex;
- var argumentOffset = parsedPattern.argumentOffset;
- var pluralValue = +namedParameters[argumentIndex];
- if (isNaN(pluralValue)) {
- // TODO(user): Distinguish between undefined and invalid parameters.
- result.push('Undefined or invalid parameter - ' + argumentIndex);
- return;
- }
- var diff = pluralValue - argumentOffset;
-
- // Check if there is an exact match.
- var option = parsedPattern[namedParameters[argumentIndex]];
- if (!goog.isDef(option)) {
- goog.asserts.assert(diff >= 0, 'Argument index smaller than offset.');
- var item;
- item = pluralSelector(diff);
- goog.asserts.assertString(item, 'Invalid plural key.');
-
- option = parsedPattern[item];
-
- // If option is not provided fall back to "other".
- if (!goog.isDef(option)) {
- option = parsedPattern[goog.i18n.MessageFormat.OTHER_];
- }
-
- goog.asserts.assertArray(
- option, 'Invalid option or missing other option for plural block.');
- }
-
- var pluralResult = [];
- this.formatBlock_(option, namedParameters, ignorePound, pluralResult);
- var plural = pluralResult.join('');
- goog.asserts.assertString(plural, 'Empty block in plural.');
- if (ignorePound) {
- result.push(plural);
- } else {
- // TODO(plundblad): Might want to use a more specific number formatter.
- var localeAwareDiff = diff.toLocaleString();
- result.push(plural.replace(/#/g, localeAwareDiff));
- }
-};
-
-
-/**
- * Parses input pattern into an array, for faster reformatting with
- * different input parameters.
- * Parsing is locale independent.
- * @param {string} pattern MessageFormat pattern to parse.
- * @private
- */
-goog.i18n.MessageFormat.prototype.parsePattern_ = function(pattern) {
- if (pattern) {
- pattern = this.insertPlaceholders_(pattern);
-
- this.parsedPattern_ = this.parseBlock_(pattern);
- }
-};
-
-
-/**
- * Replaces string literals with literal placeholders.
- * Literals are string of the form '}...', '{...' and '#...' where ... is
- * set of characters not containing '
- * Builds a dictionary so we can recover literals during format phase.
- * @param {string} pattern Pattern to clean up.
- * @return {string} Pattern with literals replaced with placeholders.
- * @private
- */
-goog.i18n.MessageFormat.prototype.insertPlaceholders_ = function(pattern) {
- var literals = this.literals_;
- var buildPlaceholder = goog.bind(this.buildPlaceholder_, this);
-
- // First replace '' with single quote placeholder since they can be found
- // inside other literals.
- pattern = pattern.replace(
- goog.i18n.MessageFormat.REGEX_DOUBLE_APOSTROPHE_,
- function() {
- literals.push("'");
- return buildPlaceholder(literals);
- });
-
- pattern = pattern.replace(
- goog.i18n.MessageFormat.REGEX_LITERAL_,
- function(match, text) {
- literals.push(text);
- return buildPlaceholder(literals);
- });
-
- return pattern;
-};
-
-
-/**
- * Breaks pattern into strings and top level {...} blocks.
- * @param {string} pattern (sub)Pattern to be broken.
- * @return {!Array<Object>} Each item is {type, value}.
- * @private
- */
-goog.i18n.MessageFormat.prototype.extractParts_ = function(pattern) {
- var prevPos = 0;
- var inBlock = false;
- var braceStack = [];
- var results = [];
-
- var braces = /[{}]/g;
- braces.lastIndex = 0; // lastIndex doesn't get set to 0 so we have to.
- var match;
-
- while (match = braces.exec(pattern)) {
- var pos = match.index;
- if (match[0] == '}') {
- var brace = braceStack.pop();
- goog.asserts.assert(goog.isDef(brace) && brace == '{',
- 'No matching { for }.');
-
- if (braceStack.length == 0) {
- // End of the block.
- var part = {};
- part.type = goog.i18n.MessageFormat.Element_.BLOCK;
- part.value = pattern.substring(prevPos, pos);
- results.push(part);
- prevPos = pos + 1;
- inBlock = false;
- }
- } else {
- if (braceStack.length == 0) {
- inBlock = true;
- var substring = pattern.substring(prevPos, pos);
- if (substring != '') {
- results.push({
- type: goog.i18n.MessageFormat.Element_.STRING,
- value: substring
- });
- }
- prevPos = pos + 1;
- }
- braceStack.push('{');
- }
- }
-
- // Take care of the final string, and check if the braceStack is empty.
- goog.asserts.assert(braceStack.length == 0,
- 'There are mismatched { or } in the pattern.');
-
- var substring = pattern.substring(prevPos);
- if (substring != '') {
- results.push({
- type: goog.i18n.MessageFormat.Element_.STRING,
- value: substring
- });
- }
-
- return results;
-};
-
-
-/**
- * A regular expression to parse the plural block, extracting the argument
- * index and offset (if any).
- * @type {RegExp}
- * @private
- */
-goog.i18n.MessageFormat.PLURAL_BLOCK_RE_ =
- /^\s*(\w+)\s*,\s*plural\s*,(?:\s*offset:(\d+))?/;
-
-
-/**
- * A regular expression to parse the ordinal block, extracting the argument
- * index.
- * @type {RegExp}
- * @private
- */
-goog.i18n.MessageFormat.ORDINAL_BLOCK_RE_ = /^\s*(\w+)\s*,\s*selectordinal\s*,/;
-
-
-/**
- * A regular expression to parse the select block, extracting the argument
- * index.
- * @type {RegExp}
- * @private
- */
-goog.i18n.MessageFormat.SELECT_BLOCK_RE_ = /^\s*(\w+)\s*,\s*select\s*,/;
-
-
-/**
- * Detects which type of a block is the pattern.
- * @param {string} pattern Content of the block.
- * @return {goog.i18n.MessageFormat.BlockType_} One of the block types.
- * @private
- */
-goog.i18n.MessageFormat.prototype.parseBlockType_ = function(pattern) {
- if (goog.i18n.MessageFormat.PLURAL_BLOCK_RE_.test(pattern)) {
- return goog.i18n.MessageFormat.BlockType_.PLURAL;
- }
-
- if (goog.i18n.MessageFormat.ORDINAL_BLOCK_RE_.test(pattern)) {
- return goog.i18n.MessageFormat.BlockType_.ORDINAL;
- }
-
- if (goog.i18n.MessageFormat.SELECT_BLOCK_RE_.test(pattern)) {
- return goog.i18n.MessageFormat.BlockType_.SELECT;
- }
-
- if (/^\s*\w+\s*/.test(pattern)) {
- return goog.i18n.MessageFormat.BlockType_.SIMPLE;
- }
-
- return goog.i18n.MessageFormat.BlockType_.UNKNOWN;
-};
-
-
-/**
- * Parses generic block.
- * @param {string} pattern Content of the block to parse.
- * @return {!Array<!Object>} Subblocks marked as strings, select...
- * @private
- */
-goog.i18n.MessageFormat.prototype.parseBlock_ = function(pattern) {
- var result = [];
- var parts = this.extractParts_(pattern);
- for (var i = 0; i < parts.length; i++) {
- var block = {};
- if (goog.i18n.MessageFormat.Element_.STRING == parts[i].type) {
- block.type = goog.i18n.MessageFormat.BlockType_.STRING;
- block.value = parts[i].value;
- } else if (goog.i18n.MessageFormat.Element_.BLOCK == parts[i].type) {
- var blockType = this.parseBlockType_(parts[i].value);
-
- switch (blockType) {
- case goog.i18n.MessageFormat.BlockType_.SELECT:
- block.type = goog.i18n.MessageFormat.BlockType_.SELECT;
- block.value = this.parseSelectBlock_(parts[i].value);
- break;
- case goog.i18n.MessageFormat.BlockType_.PLURAL:
- block.type = goog.i18n.MessageFormat.BlockType_.PLURAL;
- block.value = this.parsePluralBlock_(parts[i].value);
- break;
- case goog.i18n.MessageFormat.BlockType_.ORDINAL:
- block.type = goog.i18n.MessageFormat.BlockType_.ORDINAL;
- block.value = this.parseOrdinalBlock_(parts[i].value);
- break;
- case goog.i18n.MessageFormat.BlockType_.SIMPLE:
- block.type = goog.i18n.MessageFormat.BlockType_.SIMPLE;
- block.value = parts[i].value;
- break;
- default:
- goog.asserts.fail('Unknown block type.');
- }
- } else {
- goog.asserts.fail('Unknown part of the pattern.');
- }
- result.push(block);
- }
-
- return result;
-};
-
-
-/**
- * Parses a select type of a block and produces JSON object for it.
- * @param {string} pattern Subpattern that needs to be parsed as select pattern.
- * @return {!Object} Object with select block info.
- * @private
- */
-goog.i18n.MessageFormat.prototype.parseSelectBlock_ = function(pattern) {
- var argumentIndex = '';
- var replaceRegex = goog.i18n.MessageFormat.SELECT_BLOCK_RE_;
- pattern = pattern.replace(replaceRegex, function(string, name) {
- argumentIndex = name;
- return '';
- });
- var result = {};
- result.argumentIndex = argumentIndex;
-
- var parts = this.extractParts_(pattern);
- // Looking for (key block)+ sequence. One of the keys has to be "other".
- var pos = 0;
- while (pos < parts.length) {
- var key = parts[pos].value;
- goog.asserts.assertString(key, 'Missing select key element.');
-
- pos++;
- goog.asserts.assert(pos < parts.length,
- 'Missing or invalid select value element.');
-
- if (goog.i18n.MessageFormat.Element_.BLOCK == parts[pos].type) {
- var value = this.parseBlock_(parts[pos].value);
- } else {
- goog.asserts.fail('Expected block type.');
- }
- result[key.replace(/\s/g, '')] = value;
- pos++;
- }
-
- goog.asserts.assertArray(result[goog.i18n.MessageFormat.OTHER_],
- 'Missing other key in select statement.');
- return result;
-};
-
-
-/**
- * Parses a plural type of a block and produces JSON object for it.
- * @param {string} pattern Subpattern that needs to be parsed as plural pattern.
- * @return {!Object} Object with select block info.
- * @private
- */
-goog.i18n.MessageFormat.prototype.parsePluralBlock_ = function(pattern) {
- var argumentIndex = '';
- var argumentOffset = 0;
- var replaceRegex = goog.i18n.MessageFormat.PLURAL_BLOCK_RE_;
- pattern = pattern.replace(replaceRegex, function(string, name, offset) {
- argumentIndex = name;
- if (offset) {
- argumentOffset = parseInt(offset, 10);
- }
- return '';
- });
-
- var result = {};
- result.argumentIndex = argumentIndex;
- result.argumentOffset = argumentOffset;
-
- var parts = this.extractParts_(pattern);
- // Looking for (key block)+ sequence.
- var pos = 0;
- while (pos < parts.length) {
- var key = parts[pos].value;
- goog.asserts.assertString(key, 'Missing plural key element.');
-
- pos++;
- goog.asserts.assert(pos < parts.length,
- 'Missing or invalid plural value element.');
-
- if (goog.i18n.MessageFormat.Element_.BLOCK == parts[pos].type) {
- var value = this.parseBlock_(parts[pos].value);
- } else {
- goog.asserts.fail('Expected block type.');
- }
- result[key.replace(/\s*(?:=)?(\w+)\s*/, '$1')] = value;
- pos++;
- }
-
- goog.asserts.assertArray(result[goog.i18n.MessageFormat.OTHER_],
- 'Missing other key in plural statement.');
-
- return result;
-};
-
-
-/**
- * Parses an ordinal type of a block and produces JSON object for it.
- * For example the input string:
- * '{FOO, selectordinal, one {Message A}other {Message B}}'
- * Should result in the output object:
- * {
- * argumentIndex: 'FOO',
- * argumentOffest: 0,
- * one: [ { type: 4, value: 'Message A' } ],
- * other: [ { type: 4, value: 'Message B' } ]
- * }
- * @param {string} pattern Subpattern that needs to be parsed as plural pattern.
- * @return {!Object} Object with select block info.
- * @private
- */
-goog.i18n.MessageFormat.prototype.parseOrdinalBlock_ = function(pattern) {
- var argumentIndex = '';
- var replaceRegex = goog.i18n.MessageFormat.ORDINAL_BLOCK_RE_;
- pattern = pattern.replace(replaceRegex, function(string, name) {
- argumentIndex = name;
- return '';
- });
-
- var result = {};
- result.argumentIndex = argumentIndex;
- result.argumentOffset = 0;
-
- var parts = this.extractParts_(pattern);
- // Looking for (key block)+ sequence.
- var pos = 0;
- while (pos < parts.length) {
- var key = parts[pos].value;
- goog.asserts.assertString(key, 'Missing ordinal key element.');
-
- pos++;
- goog.asserts.assert(pos < parts.length,
- 'Missing or invalid ordinal value element.');
-
- if (goog.i18n.MessageFormat.Element_.BLOCK == parts[pos].type) {
- var value = this.parseBlock_(parts[pos].value);
- } else {
- goog.asserts.fail('Expected block type.');
- }
- result[key.replace(/\s*(?:=)?(\w+)\s*/, '$1')] = value;
- pos++;
- }
-
- goog.asserts.assertArray(result[goog.i18n.MessageFormat.OTHER_],
- 'Missing other key in selectordinal statement.');
-
- return result;
-};
-
-
-/**
- * Builds a placeholder from the last index of the array.
- * @param {!Array} literals All literals encountered during parse.
- * @return {string} \uFDDF_ + last index + _.
- * @private
- */
-goog.i18n.MessageFormat.prototype.buildPlaceholder_ = function(literals) {
- goog.asserts.assert(literals.length > 0, 'Literal array is empty.');
-
- var index = (literals.length - 1).toString(10);
- return goog.i18n.MessageFormat.LITERAL_PLACEHOLDER_ + index + '_';
-};
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/ordinalrules.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/ordinalrules.js
deleted file mode 100644
index 87f7bded1c6..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/ordinalrules.js
+++ /dev/null
@@ -1,733 +0,0 @@
-// Copyright 2012 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Ordinal rules.
- *
- * This file is autogenerated by script:
- * http://go/generate_pluralrules.py
- * File generated from CLDR ver. 25
- *
- * Before check in, this file could have been manually edited. This is to
- * incorporate changes before we could fix CLDR. All manual modification must be
- * documented in this section, and should be removed after those changes land to
- * CLDR.
- */
-
-goog.provide('goog.i18n.ordinalRules');
-/**
- * Ordinal pattern keyword
- * @enum {string}
- */
-goog.i18n.ordinalRules.Keyword = {
- ZERO: 'zero',
- ONE: 'one',
- TWO: 'two',
- FEW: 'few',
- MANY: 'many',
- OTHER: 'other'
-};
-
-
-/**
- * Default Ordinal select rule.
- * @param {number} n The count of items.
- * @param {number=} opt_precision optional, precision.
- * @return {goog.i18n.ordinalRules.Keyword} Default value.
- * @private
- */
-goog.i18n.ordinalRules.defaultSelect_ = function(n, opt_precision) {
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Returns the fractional part of a number (3.1416 => 1416)
- * @param {number} n The count of items.
- * @return {number} The fractional part.
- * @private
- */
-goog.i18n.ordinalRules.decimals_ = function(n) {
- var str = n + '';
- var result = str.indexOf('.');
- return (result == -1) ? 0 : str.length - result - 1;
-};
-
-/**
- * Calculates v and f as per CLDR plural rules.
- * The short names for parameters / return match the CLDR syntax and UTS #35
- * (http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax)
- * @param {number} n The count of items.
- * @param {number=} opt_precision optional, precision.
- * @return {!Object} The v and f.
- * @private
- */
-goog.i18n.ordinalRules.get_vf_ = function(n, opt_precision) {
- var DEFAULT_DIGITS = 3;
-
- if (undefined === opt_precision) {
- var v = Math.min(goog.i18n.ordinalRules.decimals_(n), DEFAULT_DIGITS);
- } else {
- var v = opt_precision;
- }
-
- var base = Math.pow(10, v);
- var f = ((n * base) | 0) % base;
-
- return {v: v, f: f};
-};
-
-/**
- * Calculates w and t as per CLDR plural rules.
- * The short names for parameters / return match the CLDR syntax and UTS #35
- * (http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax)
- * @param {number} v Calculated previously.
- * @param {number} f Calculated previously.
- * @return {!Object} The w and t.
- * @private
- */
-goog.i18n.ordinalRules.get_wt_ = function(v, f) {
- if (f === 0) {
- return {w: 0, t: 0};
- }
-
- while ((f % 10) === 0) {
- f /= 10;
- v--;
- }
-
- return {w: v, t: f};
-};
-
-/**
- * Ordinal select rules for en locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.enSelect_ = function(n, opt_precision) {
- if (n % 10 == 1 && n % 100 != 11) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (n % 10 == 2 && n % 100 != 12) {
- return goog.i18n.ordinalRules.Keyword.TWO;
- }
- if (n % 10 == 3 && n % 100 != 13) {
- return goog.i18n.ordinalRules.Keyword.FEW;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for sv locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.svSelect_ = function(n, opt_precision) {
- if ((n % 10 == 1 || n % 10 == 2) && n % 100 != 11 && n % 100 != 12) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for hu locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.huSelect_ = function(n, opt_precision) {
- if (n == 1 || n == 5) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for kk locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.kkSelect_ = function(n, opt_precision) {
- if (n % 10 == 6 || n % 10 == 9 || n % 10 == 0 && n != 0) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for mr locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.mrSelect_ = function(n, opt_precision) {
- if (n == 1) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (n == 2 || n == 3) {
- return goog.i18n.ordinalRules.Keyword.TWO;
- }
- if (n == 4) {
- return goog.i18n.ordinalRules.Keyword.FEW;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for sq locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.sqSelect_ = function(n, opt_precision) {
- if (n == 1) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (n % 10 == 4 && n % 100 != 14) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for bn locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.bnSelect_ = function(n, opt_precision) {
- if (n == 1 || n == 5 || n == 7 || n == 8 || n == 9 || n == 10) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (n == 2 || n == 3) {
- return goog.i18n.ordinalRules.Keyword.TWO;
- }
- if (n == 4) {
- return goog.i18n.ordinalRules.Keyword.FEW;
- }
- if (n == 6) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for gu locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.guSelect_ = function(n, opt_precision) {
- if (n == 1) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (n == 2 || n == 3) {
- return goog.i18n.ordinalRules.Keyword.TWO;
- }
- if (n == 4) {
- return goog.i18n.ordinalRules.Keyword.FEW;
- }
- if (n == 6) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for ka locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.kaSelect_ = function(n, opt_precision) {
- var i = n | 0;
- if (i == 1) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (i == 0 || (i % 100 >= 2 && i % 100 <= 20 || i % 100 == 40 || i % 100 == 60 || i % 100 == 80)) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for fr locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.frSelect_ = function(n, opt_precision) {
- if (n == 1) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for ne locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.neSelect_ = function(n, opt_precision) {
- if (n >= 1 && n <= 4) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for cy locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.cySelect_ = function(n, opt_precision) {
- if (n == 0 || n == 7 || n == 8 || n == 9) {
- return goog.i18n.ordinalRules.Keyword.ZERO;
- }
- if (n == 1) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (n == 2) {
- return goog.i18n.ordinalRules.Keyword.TWO;
- }
- if (n == 3 || n == 4) {
- return goog.i18n.ordinalRules.Keyword.FEW;
- }
- if (n == 5 || n == 6) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for az locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.azSelect_ = function(n, opt_precision) {
- var i = n | 0;
- if ((i % 10 == 1 || i % 10 == 2 || i % 10 == 5 || i % 10 == 7 || i % 10 == 8) || (i % 100 == 20 || i % 100 == 50 || i % 100 == 70 || i % 100 == 80)) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if ((i % 10 == 3 || i % 10 == 4) || (i % 1000 == 100 || i % 1000 == 200 || i % 1000 == 300 || i % 1000 == 400 || i % 1000 == 500 || i % 1000 == 600 || i % 1000 == 700 || i % 1000 == 800 || i % 1000 == 900)) {
- return goog.i18n.ordinalRules.Keyword.FEW;
- }
- if (i == 0 || i % 10 == 6 || (i % 100 == 40 || i % 100 == 60 || i % 100 == 90)) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for ca locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.caSelect_ = function(n, opt_precision) {
- if (n == 1 || n == 3) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (n == 2) {
- return goog.i18n.ordinalRules.Keyword.TWO;
- }
- if (n == 4) {
- return goog.i18n.ordinalRules.Keyword.FEW;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for it locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.itSelect_ = function(n, opt_precision) {
- if (n == 11 || n == 8 || n == 80 || n == 800) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Ordinal select rules for mk locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.ordinalRules.Keyword} Locale-specific ordinal value.
- * @private
- */
-goog.i18n.ordinalRules.mkSelect_ = function(n, opt_precision) {
- var i = n | 0;
- if (i % 10 == 1 && i % 100 != 11) {
- return goog.i18n.ordinalRules.Keyword.ONE;
- }
- if (i % 10 == 2 && i % 100 != 12) {
- return goog.i18n.ordinalRules.Keyword.TWO;
- }
- if ((i % 10 == 7 || i % 10 == 8) && i % 100 != 17 && i % 100 != 18) {
- return goog.i18n.ordinalRules.Keyword.MANY;
- }
- return goog.i18n.ordinalRules.Keyword.OTHER;
-};
-
-/**
- * Selected Ordinal rules by locale.
- */
-goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-if (goog.LOCALE == 'af') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'am') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ar') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'az') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.azSelect_;
-}
-if (goog.LOCALE == 'bg') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'bn') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.bnSelect_;
-}
-if (goog.LOCALE == 'br') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ca') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.caSelect_;
-}
-if (goog.LOCALE == 'chr') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'cs') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'cy') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.cySelect_;
-}
-if (goog.LOCALE == 'da') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'de') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'el') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'en') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'en_ISO' || goog.LOCALE == 'en-ISO') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.enSelect_;
-}
-if (goog.LOCALE == 'es') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'et') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'eu') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'fa') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'fi') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'fil') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'fr') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'gl') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'gsw') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'gu') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.guSelect_;
-}
-if (goog.LOCALE == 'haw') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'he') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'hi') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.guSelect_;
-}
-if (goog.LOCALE == 'hr') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'hu') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.huSelect_;
-}
-if (goog.LOCALE == 'hy') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'id') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'in') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'is') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'it') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.itSelect_;
-}
-if (goog.LOCALE == 'iw') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ja') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ka') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.kaSelect_;
-}
-if (goog.LOCALE == 'kk') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.kkSelect_;
-}
-if (goog.LOCALE == 'km') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'kn') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ko') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ky') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ln') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'lo') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'lt') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'lv') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'mk') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.mkSelect_;
-}
-if (goog.LOCALE == 'ml') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'mn') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'mo') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'mr') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.mrSelect_;
-}
-if (goog.LOCALE == 'ms') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'mt') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'my') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'nb') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ne') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.neSelect_;
-}
-if (goog.LOCALE == 'nl') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'no') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'or') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'pa') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'pl') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'pt') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ro') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'ru') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'sh') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'si') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'sk') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'sl') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'sq') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.sqSelect_;
-}
-if (goog.LOCALE == 'sr') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'sv') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.svSelect_;
-}
-if (goog.LOCALE == 'sw') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ta') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'te') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'th') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'tl') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'tr') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'uk') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ur') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'uz') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'vi') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.frSelect_;
-}
-if (goog.LOCALE == 'zh') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zu') {
- goog.i18n.ordinalRules.select = goog.i18n.ordinalRules.defaultSelect_;
-}
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/pluralrules.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/pluralrules.js
deleted file mode 100644
index 20dc9544f06..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/i18n/pluralrules.js
+++ /dev/null
@@ -1,1100 +0,0 @@
-// Copyright 2012 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Plural rules.
- *
- * This file is autogenerated by script:
- * http://go/generate_pluralrules.py
- * File generated from CLDR ver. 25
- *
- * Before check in, this file could have been manually edited. This is to
- * incorporate changes before we could fix CLDR. All manual modification must be
- * documented in this section, and should be removed after those changes land to
- * CLDR.
- */
-
-goog.provide('goog.i18n.pluralRules');
-/**
- * Plural pattern keyword
- * @enum {string}
- */
-goog.i18n.pluralRules.Keyword = {
- ZERO: 'zero',
- ONE: 'one',
- TWO: 'two',
- FEW: 'few',
- MANY: 'many',
- OTHER: 'other'
-};
-
-
-/**
- * Default Plural select rule.
- * @param {number} n The count of items.
- * @param {number=} opt_precision optional, precision.
- * @return {goog.i18n.pluralRules.Keyword} Default value.
- * @private
- */
-goog.i18n.pluralRules.defaultSelect_ = function(n, opt_precision) {
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Returns the fractional part of a number (3.1416 => 1416)
- * @param {number} n The count of items.
- * @return {number} The fractional part.
- * @private
- */
-goog.i18n.pluralRules.decimals_ = function(n) {
- var str = n + '';
- var result = str.indexOf('.');
- return (result == -1) ? 0 : str.length - result - 1;
-};
-
-/**
- * Calculates v and f as per CLDR plural rules.
- * The short names for parameters / return match the CLDR syntax and UTS #35
- * (http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax)
- * @param {number} n The count of items.
- * @param {number=} opt_precision optional, precision.
- * @return {!Object} The v and f.
- * @private
- */
-goog.i18n.pluralRules.get_vf_ = function(n, opt_precision) {
- var DEFAULT_DIGITS = 3;
-
- if (undefined === opt_precision) {
- var v = Math.min(goog.i18n.pluralRules.decimals_(n), DEFAULT_DIGITS);
- } else {
- var v = opt_precision;
- }
-
- var base = Math.pow(10, v);
- var f = ((n * base) | 0) % base;
-
- return {v: v, f: f};
-};
-
-/**
- * Calculates w and t as per CLDR plural rules.
- * The short names for parameters / return match the CLDR syntax and UTS #35
- * (http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax)
- * @param {number} v Calculated previously.
- * @param {number} f Calculated previously.
- * @return {!Object} The w and t.
- * @private
- */
-goog.i18n.pluralRules.get_wt_ = function(v, f) {
- if (f === 0) {
- return {w: 0, t: 0};
- }
-
- while ((f % 10) === 0) {
- f /= 10;
- v--;
- }
-
- return {w: v, t: f};
-};
-
-/**
- * Plural select rules for ga locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.gaSelect_ = function(n, opt_precision) {
- if (n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n == 2) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- if (n >= 3 && n <= 6) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (n >= 7 && n <= 10) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for ro locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.roSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (i == 1 && vf.v == 0) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (vf.v != 0 || n == 0 || n != 1 && n % 100 >= 1 && n % 100 <= 19) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for fil locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.filSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (vf.v == 0 && (i == 1 || i == 2 || i == 3) || vf.v == 0 && i % 10 != 4 && i % 10 != 6 && i % 10 != 9 || vf.v != 0 && vf.f % 10 != 4 && vf.f % 10 != 6 && vf.f % 10 != 9) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for fr locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.frSelect_ = function(n, opt_precision) {
- var i = n | 0;
- if (i == 0 || i == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for en locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.enSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (i == 1 && vf.v == 0) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for mt locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.mtSelect_ = function(n, opt_precision) {
- if (n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n == 0 || n % 100 >= 2 && n % 100 <= 10) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (n % 100 >= 11 && n % 100 <= 19) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for da locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.daSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- var wt = goog.i18n.pluralRules.get_wt_(vf.v, vf.f);
- if (n == 1 || wt.t != 0 && (i == 0 || i == 1)) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for gv locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.gvSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (vf.v == 0 && i % 10 == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (vf.v == 0 && i % 10 == 2) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- if (vf.v == 0 && (i % 100 == 0 || i % 100 == 20 || i % 100 == 40 || i % 100 == 60 || i % 100 == 80)) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (vf.v != 0) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for cy locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.cySelect_ = function(n, opt_precision) {
- if (n == 0) {
- return goog.i18n.pluralRules.Keyword.ZERO;
- }
- if (n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n == 2) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- if (n == 3) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (n == 6) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for br locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.brSelect_ = function(n, opt_precision) {
- if (n % 10 == 1 && n % 100 != 11 && n % 100 != 71 && n % 100 != 91) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n % 10 == 2 && n % 100 != 12 && n % 100 != 72 && n % 100 != 92) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- if ((n % 10 >= 3 && n % 10 <= 4 || n % 10 == 9) && (n % 100 < 10 || n % 100 > 19) && (n % 100 < 70 || n % 100 > 79) && (n % 100 < 90 || n % 100 > 99)) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (n != 0 && n % 1000000 == 0) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for es locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.esSelect_ = function(n, opt_precision) {
- if (n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for si locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.siSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if ((n == 0 || n == 1) || i == 0 && vf.f == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for sl locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.slSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (vf.v == 0 && i % 100 == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (vf.v == 0 && i % 100 == 2) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- if (vf.v == 0 && i % 100 >= 3 && i % 100 <= 4 || vf.v != 0) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for tzm locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.tzmSelect_ = function(n, opt_precision) {
- if (n >= 0 && n <= 1 || n >= 11 && n <= 99) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for sr locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.srSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (vf.v == 0 && i % 10 == 1 && i % 100 != 11 || vf.f % 10 == 1 && vf.f % 100 != 11) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14) || vf.f % 10 >= 2 && vf.f % 10 <= 4 && (vf.f % 100 < 12 || vf.f % 100 > 14)) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for hi locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.hiSelect_ = function(n, opt_precision) {
- var i = n | 0;
- if (i == 0 || n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for mk locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.mkSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (vf.v == 0 && i % 10 == 1 || vf.f % 10 == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for ar locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.arSelect_ = function(n, opt_precision) {
- if (n == 0) {
- return goog.i18n.pluralRules.Keyword.ZERO;
- }
- if (n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n == 2) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- if (n % 100 >= 3 && n % 100 <= 10) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (n % 100 >= 11 && n % 100 <= 99) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for iu locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.iuSelect_ = function(n, opt_precision) {
- if (n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n == 2) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for cs locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.csSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (i == 1 && vf.v == 0) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (i >= 2 && i <= 4 && vf.v == 0) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (vf.v != 0) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for pt_PT locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.pt_PTSelect_ = function(n, opt_precision) {
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (n == 1 && vf.v == 0) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for be locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.beSelect_ = function(n, opt_precision) {
- if (n % 10 == 1 && n % 100 != 11) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (n % 10 == 0 || n % 10 >= 5 && n % 10 <= 9 || n % 100 >= 11 && n % 100 <= 14) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for ak locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.akSelect_ = function(n, opt_precision) {
- if (n >= 0 && n <= 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for pt locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.ptSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- var wt = goog.i18n.pluralRules.get_wt_(vf.v, vf.f);
- if (i == 1 && vf.v == 0 || i == 0 && wt.t == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for pl locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.plSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (i == 1 && vf.v == 0) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (vf.v == 0 && i != 1 && i % 10 >= 0 && i % 10 <= 1 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 12 && i % 100 <= 14) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for ru locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.ruSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for lag locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.lagSelect_ = function(n, opt_precision) {
- var i = n | 0;
- if (n == 0) {
- return goog.i18n.pluralRules.Keyword.ZERO;
- }
- if ((i == 0 || i == 1) && n != 0) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for shi locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.shiSelect_ = function(n, opt_precision) {
- var i = n | 0;
- if (i == 0 || n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n >= 2 && n <= 10) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for he locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.heSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (i == 1 && vf.v == 0) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (i == 2 && vf.v == 0) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- if (vf.v == 0 && (n < 0 || n > 10) && n % 10 == 0) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for is locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.isSelect_ = function(n, opt_precision) {
- var i = n | 0;
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- var wt = goog.i18n.pluralRules.get_wt_(vf.v, vf.f);
- if (wt.t == 0 && i % 10 == 1 && i % 100 != 11 || wt.t != 0) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for lt locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.ltSelect_ = function(n, opt_precision) {
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- if (vf.f != 0) {
- return goog.i18n.pluralRules.Keyword.MANY;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for gd locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.gdSelect_ = function(n, opt_precision) {
- if (n == 1 || n == 11) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- if (n == 2 || n == 12) {
- return goog.i18n.pluralRules.Keyword.TWO;
- }
- if (n >= 3 && n <= 10 || n >= 13 && n <= 19) {
- return goog.i18n.pluralRules.Keyword.FEW;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for lv locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.lvSelect_ = function(n, opt_precision) {
- var vf = goog.i18n.pluralRules.get_vf_(n, opt_precision);
- if (n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19 || vf.v == 2 && vf.f % 100 >= 11 && vf.f % 100 <= 19) {
- return goog.i18n.pluralRules.Keyword.ZERO;
- }
- if (n % 10 == 1 && n % 100 != 11 || vf.v == 2 && vf.f % 10 == 1 && vf.f % 100 != 11 || vf.v != 2 && vf.f % 10 == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Plural select rules for ksh locale
- *
- * @param {number} n The count of items.
- * @param {number=} opt_precision Precision for number formatting, if not default.
- * @return {goog.i18n.pluralRules.Keyword} Locale-specific plural value.
- * @private
- */
-goog.i18n.pluralRules.kshSelect_ = function(n, opt_precision) {
- if (n == 0) {
- return goog.i18n.pluralRules.Keyword.ZERO;
- }
- if (n == 1) {
- return goog.i18n.pluralRules.Keyword.ONE;
- }
- return goog.i18n.pluralRules.Keyword.OTHER;
-};
-
-/**
- * Selected Plural rules by locale.
- */
-goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-if (goog.LOCALE == 'af') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'am') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
-}
-if (goog.LOCALE == 'ar') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.arSelect_;
-}
-if (goog.LOCALE == 'az') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'bg') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'bn') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
-}
-if (goog.LOCALE == 'br') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.brSelect_;
-}
-if (goog.LOCALE == 'ca') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'chr') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'cs') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.csSelect_;
-}
-if (goog.LOCALE == 'cy') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.cySelect_;
-}
-if (goog.LOCALE == 'da') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.daSelect_;
-}
-if (goog.LOCALE == 'de') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'de_AT' || goog.LOCALE == 'de-AT') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'de_CH' || goog.LOCALE == 'de-CH') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'el') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'en') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'en_AU' || goog.LOCALE == 'en-AU') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'en_GB' || goog.LOCALE == 'en-GB') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'en_IE' || goog.LOCALE == 'en-IE') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'en_IN' || goog.LOCALE == 'en-IN') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'en_ISO' || goog.LOCALE == 'en-ISO') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'en_SG' || goog.LOCALE == 'en-SG') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'en_US' || goog.LOCALE == 'en-US') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'en_ZA' || goog.LOCALE == 'en-ZA') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'es') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'es_419' || goog.LOCALE == 'es-419') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'es_ES' || goog.LOCALE == 'es-ES') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'et') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'eu') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'fa') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
-}
-if (goog.LOCALE == 'fi') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'fil') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.filSelect_;
-}
-if (goog.LOCALE == 'fr') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.frSelect_;
-}
-if (goog.LOCALE == 'fr_CA' || goog.LOCALE == 'fr-CA') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.frSelect_;
-}
-if (goog.LOCALE == 'gl') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'gsw') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'gu') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
-}
-if (goog.LOCALE == 'haw') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'he') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.heSelect_;
-}
-if (goog.LOCALE == 'hi') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
-}
-if (goog.LOCALE == 'hr') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
-}
-if (goog.LOCALE == 'hu') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'hy') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.frSelect_;
-}
-if (goog.LOCALE == 'id') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'in') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'is') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.isSelect_;
-}
-if (goog.LOCALE == 'it') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'iw') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.heSelect_;
-}
-if (goog.LOCALE == 'ja') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ka') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'kk') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'km') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'kn') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
-}
-if (goog.LOCALE == 'ko') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'ky') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'ln') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.akSelect_;
-}
-if (goog.LOCALE == 'lo') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'lt') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.ltSelect_;
-}
-if (goog.LOCALE == 'lv') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.lvSelect_;
-}
-if (goog.LOCALE == 'mk') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.mkSelect_;
-}
-if (goog.LOCALE == 'ml') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'mn') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'mo') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.roSelect_;
-}
-if (goog.LOCALE == 'mr') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
-}
-if (goog.LOCALE == 'ms') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'mt') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.mtSelect_;
-}
-if (goog.LOCALE == 'my') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'nb') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'ne') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'nl') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'no') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'no_NO' || goog.LOCALE == 'no-NO') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'or') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'pa') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.akSelect_;
-}
-if (goog.LOCALE == 'pl') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.plSelect_;
-}
-if (goog.LOCALE == 'pt') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.ptSelect_;
-}
-if (goog.LOCALE == 'pt_BR' || goog.LOCALE == 'pt-BR') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.ptSelect_;
-}
-if (goog.LOCALE == 'pt_PT' || goog.LOCALE == 'pt-PT') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.pt_PTSelect_;
-}
-if (goog.LOCALE == 'ro') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.roSelect_;
-}
-if (goog.LOCALE == 'ru') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.ruSelect_;
-}
-if (goog.LOCALE == 'sh') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
-}
-if (goog.LOCALE == 'si') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.siSelect_;
-}
-if (goog.LOCALE == 'sk') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.csSelect_;
-}
-if (goog.LOCALE == 'sl') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.slSelect_;
-}
-if (goog.LOCALE == 'sq') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'sr') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.srSelect_;
-}
-if (goog.LOCALE == 'sv') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'sw') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'ta') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'te') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'th') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'tl') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.filSelect_;
-}
-if (goog.LOCALE == 'tr') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'uk') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.ruSelect_;
-}
-if (goog.LOCALE == 'ur') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.enSelect_;
-}
-if (goog.LOCALE == 'uz') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.esSelect_;
-}
-if (goog.LOCALE == 'vi') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zh') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zh_CN' || goog.LOCALE == 'zh-CN') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zh_HK' || goog.LOCALE == 'zh-HK') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zh_TW' || goog.LOCALE == 'zh-TW') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.defaultSelect_;
-}
-if (goog.LOCALE == 'zu') {
- goog.i18n.pluralRules.select = goog.i18n.pluralRules.hiSelect_;
-}
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/object/object.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/object/object.js
deleted file mode 100644
index 261b8afa94f..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/object/object.js
+++ /dev/null
@@ -1,637 +0,0 @@
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Utilities for manipulating objects/maps/hashes.
- */
-
-goog.provide('goog.object');
-
-
-/**
- * Calls a function for each element in an object/map/hash.
- *
- * @param {Object<K,V>} obj The object over which to iterate.
- * @param {function(this:T,V,?,Object<K,V>):?} f The function to call
- * for every element. This function takes 3 arguments (the element, the
- * index and the object) and the return value is ignored.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @template T,K,V
- */
-goog.object.forEach = function(obj, f, opt_obj) {
- for (var key in obj) {
- f.call(opt_obj, obj[key], key, obj);
- }
-};
-
-
-/**
- * Calls a function for each element in an object/map/hash. If that call returns
- * true, adds the element to a new object.
- *
- * @param {Object<K,V>} obj The object over which to iterate.
- * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to call
- * for every element. This
- * function takes 3 arguments (the element, the index and the object)
- * and should return a boolean. If the return value is true the
- * element is added to the result object. If it is false the
- * element is not included.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @return {!Object<K,V>} a new object in which only elements that passed the
- * test are present.
- * @template T,K,V
- */
-goog.object.filter = function(obj, f, opt_obj) {
- var res = {};
- for (var key in obj) {
- if (f.call(opt_obj, obj[key], key, obj)) {
- res[key] = obj[key];
- }
- }
- return res;
-};
-
-
-/**
- * For every element in an object/map/hash calls a function and inserts the
- * result into a new object.
- *
- * @param {Object<K,V>} obj The object over which to iterate.
- * @param {function(this:T,V,?,Object<K,V>):R} f The function to call
- * for every element. This function
- * takes 3 arguments (the element, the index and the object)
- * and should return something. The result will be inserted
- * into a new object.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @return {!Object<K,R>} a new object with the results from f.
- * @template T,K,V,R
- */
-goog.object.map = function(obj, f, opt_obj) {
- var res = {};
- for (var key in obj) {
- res[key] = f.call(opt_obj, obj[key], key, obj);
- }
- return res;
-};
-
-
-/**
- * Calls a function for each element in an object/map/hash. If any
- * call returns true, returns true (without checking the rest). If
- * all calls return false, returns false.
- *
- * @param {Object<K,V>} obj The object to check.
- * @param {function(this:T,V,?,Object<K,V>):boolean} f The function to
- * call for every element. This function
- * takes 3 arguments (the element, the index and the object) and should
- * return a boolean.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @return {boolean} true if any element passes the test.
- * @template T,K,V
- */
-goog.object.some = function(obj, f, opt_obj) {
- for (var key in obj) {
- if (f.call(opt_obj, obj[key], key, obj)) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Calls a function for each element in an object/map/hash. If
- * all calls return true, returns true. If any call returns false, returns
- * false at this point and does not continue to check the remaining elements.
- *
- * @param {Object<K,V>} obj The object to check.
- * @param {?function(this:T,V,?,Object<K,V>):boolean} f The function to
- * call for every element. This function
- * takes 3 arguments (the element, the index and the object) and should
- * return a boolean.
- * @param {T=} opt_obj This is used as the 'this' object within f.
- * @return {boolean} false if any element fails the test.
- * @template T,K,V
- */
-goog.object.every = function(obj, f, opt_obj) {
- for (var key in obj) {
- if (!f.call(opt_obj, obj[key], key, obj)) {
- return false;
- }
- }
- return true;
-};
-
-
-/**
- * Returns the number of key-value pairs in the object map.
- *
- * @param {Object} obj The object for which to get the number of key-value
- * pairs.
- * @return {number} The number of key-value pairs in the object map.
- */
-goog.object.getCount = function(obj) {
- // JS1.5 has __count__ but it has been deprecated so it raises a warning...
- // in other words do not use. Also __count__ only includes the fields on the
- // actual object and not in the prototype chain.
- var rv = 0;
- for (var key in obj) {
- rv++;
- }
- return rv;
-};
-
-
-/**
- * Returns one key from the object map, if any exists.
- * For map literals the returned key will be the first one in most of the
- * browsers (a know exception is Konqueror).
- *
- * @param {Object} obj The object to pick a key from.
- * @return {string|undefined} The key or undefined if the object is empty.
- */
-goog.object.getAnyKey = function(obj) {
- for (var key in obj) {
- return key;
- }
-};
-
-
-/**
- * Returns one value from the object map, if any exists.
- * For map literals the returned value will be the first one in most of the
- * browsers (a know exception is Konqueror).
- *
- * @param {Object<K,V>} obj The object to pick a value from.
- * @return {V|undefined} The value or undefined if the object is empty.
- * @template K,V
- */
-goog.object.getAnyValue = function(obj) {
- for (var key in obj) {
- return obj[key];
- }
-};
-
-
-/**
- * Whether the object/hash/map contains the given object as a value.
- * An alias for goog.object.containsValue(obj, val).
- *
- * @param {Object<K,V>} obj The object in which to look for val.
- * @param {V} val The object for which to check.
- * @return {boolean} true if val is present.
- * @template K,V
- */
-goog.object.contains = function(obj, val) {
- return goog.object.containsValue(obj, val);
-};
-
-
-/**
- * Returns the values of the object/map/hash.
- *
- * @param {Object<K,V>} obj The object from which to get the values.
- * @return {!Array<V>} The values in the object/map/hash.
- * @template K,V
- */
-goog.object.getValues = function(obj) {
- var res = [];
- var i = 0;
- for (var key in obj) {
- res[i++] = obj[key];
- }
- return res;
-};
-
-
-/**
- * Returns the keys of the object/map/hash.
- *
- * @param {Object} obj The object from which to get the keys.
- * @return {!Array<string>} Array of property keys.
- */
-goog.object.getKeys = function(obj) {
- var res = [];
- var i = 0;
- for (var key in obj) {
- res[i++] = key;
- }
- return res;
-};
-
-
-/**
- * Get a value from an object multiple levels deep. This is useful for
- * pulling values from deeply nested objects, such as JSON responses.
- * Example usage: getValueByKeys(jsonObj, 'foo', 'entries', 3)
- *
- * @param {!Object} obj An object to get the value from. Can be array-like.
- * @param {...(string|number|!Array<number|string>)} var_args A number of keys
- * (as strings, or numbers, for array-like objects). Can also be
- * specified as a single array of keys.
- * @return {*} The resulting value. If, at any point, the value for a key
- * is undefined, returns undefined.
- */
-goog.object.getValueByKeys = function(obj, var_args) {
- var isArrayLike = goog.isArrayLike(var_args);
- var keys = isArrayLike ? var_args : arguments;
-
- // Start with the 2nd parameter for the variable parameters syntax.
- for (var i = isArrayLike ? 0 : 1; i < keys.length; i++) {
- obj = obj[keys[i]];
- if (!goog.isDef(obj)) {
- break;
- }
- }
-
- return obj;
-};
-
-
-/**
- * Whether the object/map/hash contains the given key.
- *
- * @param {Object} obj The object in which to look for key.
- * @param {*} key The key for which to check.
- * @return {boolean} true If the map contains the key.
- */
-goog.object.containsKey = function(obj, key) {
- return key in obj;
-};
-
-
-/**
- * Whether the object/map/hash contains the given value. This is O(n).
- *
- * @param {Object<K,V>} obj The object in which to look for val.
- * @param {V} val The value for which to check.
- * @return {boolean} true If the map contains the value.
- * @template K,V
- */
-goog.object.containsValue = function(obj, val) {
- for (var key in obj) {
- if (obj[key] == val) {
- return true;
- }
- }
- return false;
-};
-
-
-/**
- * Searches an object for an element that satisfies the given condition and
- * returns its key.
- * @param {Object<K,V>} obj The object to search in.
- * @param {function(this:T,V,string,Object<K,V>):boolean} f The
- * function to call for every element. Takes 3 arguments (the value,
- * the key and the object) and should return a boolean.
- * @param {T=} opt_this An optional "this" context for the function.
- * @return {string|undefined} The key of an element for which the function
- * returns true or undefined if no such element is found.
- * @template T,K,V
- */
-goog.object.findKey = function(obj, f, opt_this) {
- for (var key in obj) {
- if (f.call(opt_this, obj[key], key, obj)) {
- return key;
- }
- }
- return undefined;
-};
-
-
-/**
- * Searches an object for an element that satisfies the given condition and
- * returns its value.
- * @param {Object<K,V>} obj The object to search in.
- * @param {function(this:T,V,string,Object<K,V>):boolean} f The function
- * to call for every element. Takes 3 arguments (the value, the key
- * and the object) and should return a boolean.
- * @param {T=} opt_this An optional "this" context for the function.
- * @return {V} The value of an element for which the function returns true or
- * undefined if no such element is found.
- * @template T,K,V
- */
-goog.object.findValue = function(obj, f, opt_this) {
- var key = goog.object.findKey(obj, f, opt_this);
- return key && obj[key];
-};
-
-
-/**
- * Whether the object/map/hash is empty.
- *
- * @param {Object} obj The object to test.
- * @return {boolean} true if obj is empty.
- */
-goog.object.isEmpty = function(obj) {
- for (var key in obj) {
- return false;
- }
- return true;
-};
-
-
-/**
- * Removes all key value pairs from the object/map/hash.
- *
- * @param {Object} obj The object to clear.
- */
-goog.object.clear = function(obj) {
- for (var i in obj) {
- delete obj[i];
- }
-};
-
-
-/**
- * Removes a key-value pair based on the key.
- *
- * @param {Object} obj The object from which to remove the key.
- * @param {*} key The key to remove.
- * @return {boolean} Whether an element was removed.
- */
-goog.object.remove = function(obj, key) {
- var rv;
- if ((rv = key in obj)) {
- delete obj[key];
- }
- return rv;
-};
-
-
-/**
- * Adds a key-value pair to the object. Throws an exception if the key is
- * already in use. Use set if you want to change an existing pair.
- *
- * @param {Object<K,V>} obj The object to which to add the key-value pair.
- * @param {string} key The key to add.
- * @param {V} val The value to add.
- * @template K,V
- */
-goog.object.add = function(obj, key, val) {
- if (key in obj) {
- throw Error('The object already contains the key "' + key + '"');
- }
- goog.object.set(obj, key, val);
-};
-
-
-/**
- * Returns the value for the given key.
- *
- * @param {Object<K,V>} obj The object from which to get the value.
- * @param {string} key The key for which to get the value.
- * @param {R=} opt_val The value to return if no item is found for the given
- * key (default is undefined).
- * @return {V|R|undefined} The value for the given key.
- * @template K,V,R
- */
-goog.object.get = function(obj, key, opt_val) {
- if (key in obj) {
- return obj[key];
- }
- return opt_val;
-};
-
-
-/**
- * Adds a key-value pair to the object/map/hash.
- *
- * @param {Object<K,V>} obj The object to which to add the key-value pair.
- * @param {string} key The key to add.
- * @param {V} value The value to add.
- * @template K,V
- */
-goog.object.set = function(obj, key, value) {
- obj[key] = value;
-};
-
-
-/**
- * Adds a key-value pair to the object/map/hash if it doesn't exist yet.
- *
- * @param {Object<K,V>} obj The object to which to add the key-value pair.
- * @param {string} key The key to add.
- * @param {V} value The value to add if the key wasn't present.
- * @return {V} The value of the entry at the end of the function.
- * @template K,V
- */
-goog.object.setIfUndefined = function(obj, key, value) {
- return key in obj ? obj[key] : (obj[key] = value);
-};
-
-
-/**
- * Does a flat clone of the object.
- *
- * @param {Object<K,V>} obj Object to clone.
- * @return {!Object<K,V>} Clone of the input object.
- * @template K,V
- */
-goog.object.clone = function(obj) {
- // We cannot use the prototype trick because a lot of methods depend on where
- // the actual key is set.
-
- var res = {};
- for (var key in obj) {
- res[key] = obj[key];
- }
- return res;
- // We could also use goog.mixin but I wanted this to be independent from that.
-};
-
-
-/**
- * Clones a value. The input may be an Object, Array, or basic type. Objects and
- * arrays will be cloned recursively.
- *
- * WARNINGS:
- * <code>goog.object.unsafeClone</code> does not detect reference loops. Objects
- * that refer to themselves will cause infinite recursion.
- *
- * <code>goog.object.unsafeClone</code> is unaware of unique identifiers, and
- * copies UIDs created by <code>getUid</code> into cloned results.
- *
- * @param {*} obj The value to clone.
- * @return {*} A clone of the input value.
- */
-goog.object.unsafeClone = function(obj) {
- var type = goog.typeOf(obj);
- if (type == 'object' || type == 'array') {
- if (obj.clone) {
- return obj.clone();
- }
- var clone = type == 'array' ? [] : {};
- for (var key in obj) {
- clone[key] = goog.object.unsafeClone(obj[key]);
- }
- return clone;
- }
-
- return obj;
-};
-
-
-/**
- * Returns a new object in which all the keys and values are interchanged
- * (keys become values and values become keys). If multiple keys map to the
- * same value, the chosen transposed value is implementation-dependent.
- *
- * @param {Object} obj The object to transpose.
- * @return {!Object} The transposed object.
- */
-goog.object.transpose = function(obj) {
- var transposed = {};
- for (var key in obj) {
- transposed[obj[key]] = key;
- }
- return transposed;
-};
-
-
-/**
- * The names of the fields that are defined on Object.prototype.
- * @type {Array<string>}
- * @private
- */
-goog.object.PROTOTYPE_FIELDS_ = [
- 'constructor',
- 'hasOwnProperty',
- 'isPrototypeOf',
- 'propertyIsEnumerable',
- 'toLocaleString',
- 'toString',
- 'valueOf'
-];
-
-
-/**
- * Extends an object with another object.
- * This operates 'in-place'; it does not create a new Object.
- *
- * Example:
- * var o = {};
- * goog.object.extend(o, {a: 0, b: 1});
- * o; // {a: 0, b: 1}
- * goog.object.extend(o, {b: 2, c: 3});
- * o; // {a: 0, b: 2, c: 3}
- *
- * @param {Object} target The object to modify. Existing properties will be
- * overwritten if they are also present in one of the objects in
- * {@code var_args}.
- * @param {...Object} var_args The objects from which values will be copied.
- */
-goog.object.extend = function(target, var_args) {
- var key, source;
- for (var i = 1; i < arguments.length; i++) {
- source = arguments[i];
- for (key in source) {
- target[key] = source[key];
- }
-
- // For IE the for-in-loop does not contain any properties that are not
- // enumerable on the prototype object (for example isPrototypeOf from
- // Object.prototype) and it will also not include 'replace' on objects that
- // extend String and change 'replace' (not that it is common for anyone to
- // extend anything except Object).
-
- for (var j = 0; j < goog.object.PROTOTYPE_FIELDS_.length; j++) {
- key = goog.object.PROTOTYPE_FIELDS_[j];
- if (Object.prototype.hasOwnProperty.call(source, key)) {
- target[key] = source[key];
- }
- }
- }
-};
-
-
-/**
- * Creates a new object built from the key-value pairs provided as arguments.
- * @param {...*} var_args If only one argument is provided and it is an array
- * then this is used as the arguments, otherwise even arguments are used as
- * the property names and odd arguments are used as the property values.
- * @return {!Object} The new object.
- * @throws {Error} If there are uneven number of arguments or there is only one
- * non array argument.
- */
-goog.object.create = function(var_args) {
- var argLength = arguments.length;
- if (argLength == 1 && goog.isArray(arguments[0])) {
- return goog.object.create.apply(null, arguments[0]);
- }
-
- if (argLength % 2) {
- throw Error('Uneven number of arguments');
- }
-
- var rv = {};
- for (var i = 0; i < argLength; i += 2) {
- rv[arguments[i]] = arguments[i + 1];
- }
- return rv;
-};
-
-
-/**
- * Creates a new object where the property names come from the arguments but
- * the value is always set to true
- * @param {...*} var_args If only one argument is provided and it is an array
- * then this is used as the arguments, otherwise the arguments are used
- * as the property names.
- * @return {!Object} The new object.
- */
-goog.object.createSet = function(var_args) {
- var argLength = arguments.length;
- if (argLength == 1 && goog.isArray(arguments[0])) {
- return goog.object.createSet.apply(null, arguments[0]);
- }
-
- var rv = {};
- for (var i = 0; i < argLength; i++) {
- rv[arguments[i]] = true;
- }
- return rv;
-};
-
-
-/**
- * Creates an immutable view of the underlying object, if the browser
- * supports immutable objects.
- *
- * In default mode, writes to this view will fail silently. In strict mode,
- * they will throw an error.
- *
- * @param {!Object<K,V>} obj An object.
- * @return {!Object<K,V>} An immutable view of that object, or the
- * original object if this browser does not support immutables.
- * @template K,V
- */
-goog.object.createImmutableView = function(obj) {
- var result = obj;
- if (Object.isFrozen && !Object.isFrozen(obj)) {
- result = Object.create(obj);
- Object.freeze(result);
- }
- return result;
-};
-
-
-/**
- * @param {!Object} obj An object.
- * @return {boolean} Whether this is an immutable view of the object.
- */
-goog.object.isImmutableView = function(obj) {
- return !!Object.isFrozen && Object.isFrozen(obj);
-};
diff --git a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/string/string.js b/chromium/third_party/chromevox/third_party/closure-library/closure/goog/string/string.js
deleted file mode 100644
index af1046004e2..00000000000
--- a/chromium/third_party/chromevox/third_party/closure-library/closure/goog/string/string.js
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2006 The Closure Library Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/**
- * @fileoverview Utilities for string manipulation.
- */
-
-
-/**
- * Namespace for string utilities
- */
-goog.provide('goog.string');
-
-
-/**
- * Does simple python-style string substitution.
- * subs("foo%s hot%s", "bar", "dog") becomes "foobar hotdog".
- * @param {string} str The string containing the pattern.
- * @param {...*} var_args The items to substitute into the pattern.
- * @return {string} A copy of {@code str} in which each occurrence of
- * {@code %s} has been replaced an argument from {@code var_args}.
- */
-goog.string.subs = function(str, var_args) {
- var splitParts = str.split('%s');
- var returnString = '';
-
- var subsArguments = Array.prototype.slice.call(arguments, 1);
- while (subsArguments.length &&
- // Replace up to the last split part. We are inserting in the
- // positions between split parts.
- splitParts.length > 1) {
- returnString += splitParts.shift() + subsArguments.shift();
- }
-
- return returnString + splitParts.join('%s'); // Join unused '%s'
-};
diff --git a/chromium/third_party/chromevox/third_party/sre/LICENSE b/chromium/third_party/chromevox/third_party/sre/LICENSE
deleted file mode 100644
index f433b1a53f5..00000000000
--- a/chromium/third_party/chromevox/third_party/sre/LICENSE
+++ /dev/null
@@ -1,177 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
diff --git a/chromium/third_party/chromevox/third_party/sre/METADATA b/chromium/third_party/chromevox/third_party/sre/METADATA
deleted file mode 100644
index e5f2ca20319..00000000000
--- a/chromium/third_party/chromevox/third_party/sre/METADATA
+++ /dev/null
@@ -1,18 +0,0 @@
-Name: "Speech Rule Engine"
-Description:
- "SRE is an open source library that generates speech descriptions for XML "
- "structures."
- ""
- "It is used by ChromeVox to verbalize math."
-third_party {
- url: {
- type: GIT,
- value: "https://github.com/zorkow/speech-rule-engine"
- },
- Version: "2.3.0",
- last_upgrade_date: {year: 2018, month: 6, day: 22},
- license_type: NOTICE,
- local_modifications:
- "SRE is checked in as one compiled script as it would be presented in a "
- "node.js module."
-}
diff --git a/chromium/third_party/chromevox/third_party/sre/OWNERS b/chromium/third_party/chromevox/third_party/sre/OWNERS
deleted file mode 100644
index 3f3d042ae3a..00000000000
--- a/chromium/third_party/chromevox/third_party/sre/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-dtseng@chromium.org
-dmazzoni@chromium.org
diff --git a/chromium/third_party/chromevox/third_party/sre/sre_browser.js b/chromium/third_party/chromevox/third_party/sre/sre_browser.js
deleted file mode 100644
index bce31cc3601..00000000000
--- a/chromium/third_party/chromevox/third_party/sre/sre_browser.js
+++ /dev/null
@@ -1,1155 +0,0 @@
-var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(c.get||c.set)throw new TypeError("ES3 does not support getters and setters.");a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
-$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(a){return $jscomp.SYMBOL_PREFIX+(a||"")+$jscomp.symbolCounter_++};
-$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.iterator;a||(a=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&$jscomp.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(a){var b=0;return $jscomp.iteratorPrototype(function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}})};
-$jscomp.iteratorPrototype=function(a){$jscomp.initSymbolIterator();a={next:a};a[$jscomp.global.Symbol.iterator]=function(){return this};return a};$jscomp.array=$jscomp.array||{};$jscomp.iteratorFromArray=function(a,b){$jscomp.initSymbolIterator();a instanceof String&&(a+="");var c=0,d={next:function(){if(c<a.length){var e=c++;return{value:b(e,a[e]),done:!1}}d.next=function(){return{done:!0,value:void 0}};return d.next()}};d[Symbol.iterator]=function(){return d};return d};
-$jscomp.polyfill=function(a,b,c,d){if(b){c=$jscomp.global;a=a.split(".");for(d=0;d<a.length-1;d++){var e=a[d];e in c||(c[e]={});c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&$jscomp.defineProperty(c,a,{configurable:!0,writable:!0,value:b})}};$jscomp.findInternal=function(a,b,c){a instanceof String&&(a=String(a));for(var d=a.length,e=0;e<d;e++){var f=a[e];if(b.call(c,f,e,a))return{i:e,v:f}}return{i:-1,v:void 0}};
-$jscomp.polyfill("Array.prototype.find",function(a){return a?a:function(a,c){return $jscomp.findInternal(this,a,c).v}},"es6-impl","es3");$jscomp.checkStringArgs=function(a,b,c){if(null==a)throw new TypeError("The 'this' value for String.prototype."+c+" must not be null or undefined");if(b instanceof RegExp)throw new TypeError("First argument to String.prototype."+c+" must not be a regular expression");return a+""};var COMPILED=!0,goog=goog||{};goog.global=this;
-goog.isDef=function(a){return void 0!==a};goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&goog.isDef(b)?c[d]=b:c=c[d]&&Object.prototype.hasOwnProperty.call(c,d)?c[d]:c[d]={}};
-goog.define=function(a,b){var c=b;COMPILED||(goog.global.CLOSURE_UNCOMPILED_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES,a)?c=goog.global.CLOSURE_UNCOMPILED_DEFINES[a]:goog.global.CLOSURE_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]));goog.exportPath_(a,c)};goog.DEBUG=!0;goog.LOCALE="en";goog.TRUSTED_SITE=!0;goog.STRICT_MODE_COMPATIBLE=!1;goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG;
-goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING=!1;goog.provide=function(a){if(goog.isInModuleLoader_())throw Error("goog.provide can not be used within a goog.module.");if(!COMPILED&&goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');goog.constructNamespace_(a)};goog.constructNamespace_=function(a,b){if(!COMPILED){delete goog.implicitNamespaces_[a];for(var c=a;(c=c.substring(0,c.lastIndexOf(".")))&&!goog.getObjectByName(c);)goog.implicitNamespaces_[c]=!0}goog.exportPath_(a,b)};
-goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/;
-goog.module=function(a){if(!goog.isString(a)||!a||-1==a.search(goog.VALID_MODULE_RE_))throw Error("Invalid module identifier");if(!goog.isInModuleLoader_())throw Error("Module "+a+" has been loaded incorrectly. Note, modules cannot be loaded as normal scripts. They require some kind of pre-processing step. You're likely trying to load a module via a script tag or as a part of a concatenated bundle without rewriting the module. For more info see: https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.");if(goog.moduleLoaderState_.moduleName)throw Error("goog.module may only be called once per module.");
-goog.moduleLoaderState_.moduleName=a;if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a]}};goog.module.get=function(a){return goog.module.getInternal_(a)};goog.module.getInternal_=function(a){if(!COMPILED){if(a in goog.loadedModules_)return goog.loadedModules_[a];if(!goog.implicitNamespaces_[a])return a=goog.getObjectByName(a),null!=a?a:null}return null};goog.moduleLoaderState_=null;
-goog.isInModuleLoader_=function(){return null!=goog.moduleLoaderState_};goog.module.declareLegacyNamespace=function(){if(!COMPILED&&!goog.isInModuleLoader_())throw Error("goog.module.declareLegacyNamespace must be called from within a goog.module");if(!COMPILED&&!goog.moduleLoaderState_.moduleName)throw Error("goog.module must be called prior to goog.module.declareLegacyNamespace.");goog.moduleLoaderState_.declareLegacyNamespace=!0};
-goog.setTestOnly=function(a){if(goog.DISALLOW_TEST_ONLY_CODE)throw a=a||"",Error("Importing test-only code into non-debug environment"+(a?": "+a:"."));};goog.forwardDeclare=function(a){};COMPILED||(goog.isProvided_=function(a){return a in goog.loadedModules_||!goog.implicitNamespaces_[a]&&goog.isDefAndNotNull(goog.getObjectByName(a))},goog.implicitNamespaces_={"goog.module":!0});
-goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]};
-goog.addDependency=function(a,b,c,d){if(goog.DEPENDENCIES_ENABLED){var e;a=a.replace(/\\/g,"/");var f=goog.dependencies_;d&&"boolean"!==typeof d||(d=d?{module:"goog"}:{});for(var g=0;e=b[g];g++)f.nameToPath[e]=a,f.loadFlags[a]=d;for(d=0;b=c[d];d++)a in f.requires||(f.requires[a]={}),f.requires[a][b]=!0}};goog.ENABLE_DEBUG_LOADER=!0;goog.logToConsole_=function(a){goog.global.console&&goog.global.console.error(a)};
-goog.require=function(a){if(!COMPILED){goog.ENABLE_DEBUG_LOADER&&goog.IS_OLD_IE_&&goog.maybeProcessDeferredDep_(a);if(goog.isProvided_(a)){if(goog.isInModuleLoader_())return goog.module.getInternal_(a)}else if(goog.ENABLE_DEBUG_LOADER){var b=goog.getPathFromDeps_(a);if(b)goog.writeScripts_(b);else throw a="goog.require could not find: "+a,goog.logToConsole_(a),Error(a);}return null}};goog.basePath="";goog.nullFunction=function(){};
-goog.abstractMethod=function(){throw Error("unimplemented abstract method");};goog.addSingletonGetter=function(a){a.instance_=void 0;a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.LOAD_MODULE_USING_EVAL=!0;goog.SEAL_MODULE_EXPORTS=goog.DEBUG;goog.loadedModules_={};goog.DEPENDENCIES_ENABLED=!COMPILED&&goog.ENABLE_DEBUG_LOADER;goog.TRANSPILE="detect";
-goog.TRANSPILER="transpile.js";
-goog.DEPENDENCIES_ENABLED&&(goog.dependencies_={loadFlags:{},nameToPath:{},requires:{},visited:{},written:{},deferred:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return null!=a&&"write"in a},goog.findBasePath_=function(){if(goog.isDef(goog.global.CLOSURE_BASE_PATH))goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document.getElementsByTagName("SCRIPT"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf("?"),d=-1==d?c.length:d;if("base.js"==
-c.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a,b){(goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_)(a,b)&&(goog.dependencies_.written[a]=!0)},goog.IS_OLD_IE_=!(goog.global.atob||!goog.global.document||!goog.global.document.all),goog.importProcessedScript_=function(a,b,c){goog.importScript_("",'goog.retrieveAndExec_("'+a+'", '+b+", "+c+");")},goog.queuedModules_=[],goog.wrapModule_=function(a,b){return goog.LOAD_MODULE_USING_EVAL&&goog.isDef(goog.global.JSON)?
-"goog.loadModule("+goog.global.JSON.stringify(b+"\n//# sourceURL="+a+"\n")+");":'goog.loadModule(function(exports) {"use strict";'+b+"\n;return exports});\n//# sourceURL="+a+"\n"},goog.loadQueuedModules_=function(){var a=goog.queuedModules_.length;if(0<a){var b=goog.queuedModules_;goog.queuedModules_=[];for(var c=0;c<a;c++)goog.maybeProcessDeferredPath_(b[c])}},goog.maybeProcessDeferredDep_=function(a){goog.isDeferredModule_(a)&&goog.allDepsAreAvailable_(a)&&(a=goog.getPathFromDeps_(a),goog.maybeProcessDeferredPath_(goog.basePath+
-a))},goog.isDeferredModule_=function(a){var b=(a=goog.getPathFromDeps_(a))&&goog.dependencies_.loadFlags[a]||{},c=b.lang||"es3";return a&&("goog"==b.module||goog.needsTranspile_(c))?goog.basePath+a in goog.dependencies_.deferred:!1},goog.allDepsAreAvailable_=function(a){if((a=goog.getPathFromDeps_(a))&&a in goog.dependencies_.requires)for(var b in goog.dependencies_.requires[a])if(!goog.isProvided_(b)&&!goog.isDeferredModule_(b))return!1;return!0},goog.maybeProcessDeferredPath_=function(a){if(a in
-goog.dependencies_.deferred){var b=goog.dependencies_.deferred[a];delete goog.dependencies_.deferred[a];goog.globalEval(b)}},goog.loadModuleFromUrl=function(a){goog.retrieveAndExec_(a,!0,!1)},goog.writeScriptSrcNode_=function(a){goog.global.document.write('<script type="text/javascript" src="'+a+'">\x3c/script>')},goog.appendScriptSrcNode_=function(a){var b=goog.global.document,c=b.createElement("script");c.type="text/javascript";c.src=a;c.defer=!1;c.async=!1;b.head.appendChild(c)},goog.writeScriptTag_=
-function(a,b){if(goog.inHtmlDocument_()){var c=goog.global.document;if(!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING&&"complete"==c.readyState){if(/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}if(void 0===b)if(goog.IS_OLD_IE_){var d=" onreadystatechange='goog.onScriptLoad_(this, "+ ++goog.lastNonModuleScriptIndex_+")' ";c.write('<script type="text/javascript" src="'+a+'"'+d+">\x3c/script>")}else goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING?goog.appendScriptSrcNode_(a):
-goog.writeScriptSrcNode_(a);else c.write('<script type="text/javascript">'+goog.protectScriptTag_(b)+"\x3c/script>");return!0}return!1},goog.protectScriptTag_=function(a){return a.replace(/<\/(SCRIPT)/ig,"\\x3c\\$1")},goog.needsTranspile_=function(a){if("always"==goog.TRANSPILE)return!0;if("never"==goog.TRANSPILE)return!1;goog.requiresTranspilation_||(goog.requiresTranspilation_=goog.createRequiresTranspilation_());if(a in goog.requiresTranspilation_)return goog.requiresTranspilation_[a];throw Error("Unknown language mode: "+
-a);},goog.requiresTranspilation_=null,goog.lastNonModuleScriptIndex_=0,goog.onScriptLoad_=function(a,b){"complete"==a.readyState&&goog.lastNonModuleScriptIndex_==b&&goog.loadQueuedModules_();return!0},goog.writeScripts_=function(a){function b(a){if(!(a in e.written||a in e.visited)){e.visited[a]=!0;if(a in e.requires)for(var f in e.requires[a])if(!goog.isProvided_(f))if(f in e.nameToPath)b(e.nameToPath[f]);else throw Error("Undefined nameToPath for "+f);a in d||(d[a]=!0,c.push(a))}}var c=[],d={},
-e=goog.dependencies_;b(a);for(a=0;a<c.length;a++){var f=c[a];goog.dependencies_.written[f]=!0}var g=goog.moduleLoaderState_;goog.moduleLoaderState_=null;for(a=0;a<c.length;a++)if(f=c[a]){var h=e.loadFlags[f]||{},k=goog.needsTranspile_(h.lang||"es3");"goog"==h.module||k?goog.importProcessedScript_(goog.basePath+f,"goog"==h.module,k):goog.importScript_(goog.basePath+f)}else throw goog.moduleLoaderState_=g,Error("Undefined script input");goog.moduleLoaderState_=g},goog.getPathFromDeps_=function(a){return a in
-goog.dependencies_.nameToPath?goog.dependencies_.nameToPath[a]:null},goog.findBasePath_(),goog.global.CLOSURE_NO_DEPS||goog.importScript_(goog.basePath+"deps.js"));goog.hasBadLetScoping=null;goog.useSafari10Workaround=function(){if(null==goog.hasBadLetScoping){var a;try{a=!eval('"use strict";let x = 1; function f() { return typeof x; };f() == "number";')}catch(b){a=!1}goog.hasBadLetScoping=a}return goog.hasBadLetScoping};goog.workaroundSafari10EvalBug=function(a){return"(function(){"+a+"\n;})();\n"};
-goog.loadModule=function(a){var b=goog.moduleLoaderState_;try{goog.moduleLoaderState_={moduleName:void 0,declareLegacyNamespace:!1};var c;if(goog.isFunction(a))c=a.call(void 0,{});else if(goog.isString(a))goog.useSafari10Workaround()&&(a=goog.workaroundSafari10EvalBug(a)),c=goog.loadModuleFromSource_.call(void 0,a);else throw Error("Invalid module definition");var d=goog.moduleLoaderState_.moduleName;if(!goog.isString(d)||!d)throw Error('Invalid module name "'+d+'"');goog.moduleLoaderState_.declareLegacyNamespace?
-goog.constructNamespace_(d,c):goog.SEAL_MODULE_EXPORTS&&Object.seal&&"object"==typeof c&&null!=c&&Object.seal(c);goog.loadedModules_[d]=c}finally{goog.moduleLoaderState_=b}};goog.loadModuleFromSource_=function(a){eval(a);return{}};goog.normalizePath_=function(a){a=a.split("/");for(var b=0;b<a.length;)"."==a[b]?a.splice(b,1):b&&".."==a[b]&&a[b-1]&&".."!=a[b-1]?a.splice(--b,2):b++;return a.join("/")};
-goog.loadFileSync_=function(a){if(goog.global.CLOSURE_LOAD_FILE_SYNC)return goog.global.CLOSURE_LOAD_FILE_SYNC(a);try{var b=new goog.global.XMLHttpRequest;b.open("get",a,!1);b.send();return 0==b.status||200==b.status?b.responseText:null}catch(c){return null}};
-goog.retrieveAndExec_=function(a,b,c){if(!COMPILED){var d=a;a=goog.normalizePath_(a);var e=goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_,f=goog.loadFileSync_(a);if(null==f)throw Error('Load of "'+a+'" failed');c&&(f=goog.transpile_.call(goog.global,f,a));f=b?goog.wrapModule_(a,f):f+("\n//# sourceURL="+a);goog.IS_OLD_IE_?(goog.dependencies_.deferred[d]=f,goog.queuedModules_.push(d)):e(a,f)}};
-goog.transpile_=function(a,b){var c=goog.global.$jscomp;c||(goog.global.$jscomp=c={});var d=c.transpile;if(!d){var e=goog.basePath+goog.TRANSPILER,f=goog.loadFileSync_(e);if(f){eval(f+"\n//# sourceURL="+e);if(goog.global.$gwtExport&&goog.global.$gwtExport.$jscomp&&!goog.global.$gwtExport.$jscomp.transpile)throw Error('The transpiler did not properly export the "transpile" method. $gwtExport: '+JSON.stringify(goog.global.$gwtExport));goog.global.$jscomp.transpile=goog.global.$gwtExport.$jscomp.transpile;
-c=goog.global.$jscomp;d=c.transpile}}d||(d=c.transpile=function(a,b){goog.logToConsole_(b+" requires transpilation but no transpiler was found.");return a});return d(a,b)};
-goog.typeOf=function(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";
-else if("function"==b&&"undefined"==typeof a.call)return"object";return b};goog.isNull=function(a){return null===a};goog.isDefAndNotNull=function(a){return null!=a};goog.isArray=function(a){return"array"==goog.typeOf(a)};goog.isArrayLike=function(a){var b=goog.typeOf(a);return"array"==b||"object"==b&&"number"==typeof a.length};goog.isDateLike=function(a){return goog.isObject(a)&&"function"==typeof a.getFullYear};goog.isString=function(a){return"string"==typeof a};
-goog.isBoolean=function(a){return"boolean"==typeof a};goog.isNumber=function(a){return"number"==typeof a};goog.isFunction=function(a){return"function"==goog.typeOf(a)};goog.isObject=function(a){var b=typeof a;return"object"==b&&null!=a||"function"==b};goog.getUid=function(a){return a[goog.UID_PROPERTY_]||(a[goog.UID_PROPERTY_]=++goog.uidCounter_)};goog.hasUid=function(a){return!!a[goog.UID_PROPERTY_]};
-goog.removeUid=function(a){null!==a&&"removeAttribute"in a&&a.removeAttribute(goog.UID_PROPERTY_);try{delete a[goog.UID_PROPERTY_]}catch(b){}};goog.UID_PROPERTY_="closure_uid_"+(1E9*Math.random()>>>0);goog.uidCounter_=0;goog.getHashCode=goog.getUid;goog.removeHashCode=goog.removeUid;goog.cloneObject=function(a){var b=goog.typeOf(a);if("object"==b||"array"==b){if(a.clone)return a.clone();var b="array"==b?[]:{},c;for(c in a)b[c]=goog.cloneObject(a[c]);return b}return a};
-goog.bindNative_=function(a,b,c){return a.call.apply(a.bind,arguments)};goog.bindJs_=function(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}};
-goog.bind=function(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?goog.bind=goog.bindNative_:goog.bind=goog.bindJs_;return goog.bind.apply(null,arguments)};goog.partial=function(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var b=c.slice();b.push.apply(b,arguments);return a.apply(this,b)}};goog.mixin=function(a,b){for(var c in b)a[c]=b[c]};goog.now=goog.TRUSTED_SITE&&Date.now||function(){return+new Date};
-goog.globalEval=function(a){if(goog.global.execScript)goog.global.execScript(a,"JavaScript");else if(goog.global.eval){if(null==goog.evalWorksForGlobals_)if(goog.global.eval("var _evalTest_ = 1;"),"undefined"!=typeof goog.global._evalTest_){try{delete goog.global._evalTest_}catch(d){}goog.evalWorksForGlobals_=!0}else goog.evalWorksForGlobals_=!1;if(goog.evalWorksForGlobals_)goog.global.eval(a);else{var b=goog.global.document,c=b.createElement("SCRIPT");c.type="text/javascript";c.defer=!1;c.appendChild(b.createTextNode(a));
-b.body.appendChild(c);b.body.removeChild(c)}}else throw Error("goog.globalEval not available");};goog.evalWorksForGlobals_=null;
-goog.getCssName=function(a,b){if("."==String(a).charAt(0))throw Error('className passed in goog.getCssName must not start with ".". You passed: '+a);var c=function(a){return goog.cssNameMapping_[a]||a},d=function(a){a=a.split("-");for(var b=[],d=0;d<a.length;d++)b.push(c(a[d]));return b.join("-")},d=goog.cssNameMapping_?"BY_WHOLE"==goog.cssNameMappingStyle_?c:d:function(a){return a},d=b?a+"-"+d(b):d(a);return goog.global.CLOSURE_CSS_NAME_MAP_FN?goog.global.CLOSURE_CSS_NAME_MAP_FN(d):d};
-goog.setCssNameMapping=function(a,b){goog.cssNameMapping_=a;goog.cssNameMappingStyle_=b};!COMPILED&&goog.global.CLOSURE_CSS_NAME_MAPPING&&(goog.cssNameMapping_=goog.global.CLOSURE_CSS_NAME_MAPPING);goog.getMsg=function(a,b){b&&(a=a.replace(/\{\$([^}]+)}/g,function(a,d){return null!=b&&d in b?b[d]:a}));return a};goog.getMsgWithFallback=function(a,b){return a};goog.exportSymbol=function(a,b,c){goog.exportPath_(a,b,c)};goog.exportProperty=function(a,b,c){a[b]=c};
-goog.inherits=function(a,b){function c(){}c.prototype=b.prototype;a.superClass_=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.base=function(a,c,f){for(var d=Array(arguments.length-2),e=2;e<arguments.length;e++)d[e-2]=arguments[e];return b.prototype[c].apply(a,d)}};
-goog.base=function(a,b,c){var d=arguments.callee.caller;if(goog.STRICT_MODE_COMPATIBLE||goog.DEBUG&&!d)throw Error("arguments.caller not defined. goog.base() cannot be used with strict mode code. See http://www.ecma-international.org/ecma-262/5.1/#sec-C");if(d.superClass_){for(var e=Array(arguments.length-1),f=1;f<arguments.length;f++)e[f-1]=arguments[f];return d.superClass_.constructor.apply(a,e)}e=Array(arguments.length-2);for(f=2;f<arguments.length;f++)e[f-2]=arguments[f];for(var f=!1,g=a.constructor;g;g=
-g.superClass_&&g.superClass_.constructor)if(g.prototype[b]===d)f=!0;else if(f)return g.prototype[b].apply(a,e);if(a[b]===d)return a.constructor.prototype[b].apply(a,e);throw Error("goog.base called from a method of one name to a method of a different name");};goog.scope=function(a){if(goog.isInModuleLoader_())throw Error("goog.scope is not supported within a goog.module.");a.call(goog.global)};COMPILED||(goog.global.COMPILED=COMPILED);
-goog.defineClass=function(a,b){var c=b.constructor,d=b.statics;c&&c!=Object.prototype.constructor||(c=function(){throw Error("cannot instantiate an interface (no constructor defined).");});c=goog.defineClass.createSealingConstructor_(c,a);a&&goog.inherits(c,a);delete b.constructor;delete b.statics;goog.defineClass.applyProperties_(c.prototype,b);null!=d&&(d instanceof Function?d(c):goog.defineClass.applyProperties_(c,d));return c};goog.defineClass.SEAL_CLASS_INSTANCES=goog.DEBUG;
-goog.defineClass.createSealingConstructor_=function(a,b){if(!goog.defineClass.SEAL_CLASS_INSTANCES)return a;var c=!goog.defineClass.isUnsealable_(b),d=function(){var b=a.apply(this,arguments)||this;b[goog.UID_PROPERTY_]=b[goog.UID_PROPERTY_];this.constructor===d&&c&&Object.seal instanceof Function&&Object.seal(b);return b};return d};goog.defineClass.isUnsealable_=function(a){return a&&a.prototype&&a.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_]};goog.defineClass.OBJECT_PROTOTYPE_FIELDS_="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" ");
-goog.defineClass.applyProperties_=function(a,b){for(var c in b)Object.prototype.hasOwnProperty.call(b,c)&&(a[c]=b[c]);for(var d=0;d<goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length;d++)c=goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[d],Object.prototype.hasOwnProperty.call(b,c)&&(a[c]=b[c])};goog.tagUnsealableClass=function(a){!COMPILED&&goog.defineClass.SEAL_CLASS_INSTANCES&&(a.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_]=!0)};goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_="goog_defineClass_legacy_unsealable";
-goog.createRequiresTranspilation_=function(){function a(a,b){d?c[a]=!0:b()?c[a]=!1:d=c[a]=!0}function b(a){try{return!!eval(a)}catch(f){return!1}}var c={es3:!1},d=!1;a("es5",function(){return b("[1,].length==1")});a("es6",function(){return b('(()=>{"use strict";class X{constructor(){if(new.target!=String)throw 1;this.x=42}}let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof String))throw 1;for(const a of[2,3]){if(a==2)continue;function f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()==3}})()')});
-a("es6-impl",function(){return!0});a("es7",function(){return b("2 ** 2 == 4")});a("es8",function(){return b("async () => 1, true")});return c};var sre={SystemExternal:function(){}};sre.SystemExternal.require=function(a){return"undefined"!==typeof process&&"undefined"!==typeof require?require(a):null};sre.SystemExternal.documentSupported=function(){return"undefined"!=typeof document};sre.SystemExternal.process=sre.SystemExternal.require("process");sre.SystemExternal.xmldom=sre.SystemExternal.documentSupported()?window:sre.SystemExternal.require("xmldom-sre");
-sre.SystemExternal.document=sre.SystemExternal.documentSupported()?document:(new sre.SystemExternal.xmldom.DOMImplementation).createDocument("","",0);sre.SystemExternal.xpath=sre.SystemExternal.documentSupported()?document:function(){var a={document:{}};sre.SystemExternal.require("wicked-good-xpath").install(a);a.document.XPathResult=a.XPathResult;return a.document}();sre.SystemExternal.commander=sre.SystemExternal.documentSupported()?null:sre.SystemExternal.require("commander");
-sre.SystemExternal.fs=sre.SystemExternal.documentSupported()?null:sre.SystemExternal.require("fs");sre.SystemExternal.locationSupported=function(){return"undefined"!=typeof location};sre.SystemExternal.url=sre.SystemExternal.locationSupported()?location.protocol+"//progressiveaccess.com/content":"https://progressiveaccess.com/content";
-sre.SystemExternal.jsonPath=function(){return(sre.SystemExternal.process&&"undefined"!==typeof global?sre.SystemExternal.process.env.SRE_JSON_PATH||global.SRE_JSON_PATH||sre.SystemExternal.process.cwd():sre.SystemExternal.url+"/mathmaps")+"/"}();sre.SystemExternal.WGXpath=sre.SystemExternal.url+"/wgxpath.install.js";sre.SystemExternal.wgxpath=null;sre.BrowserUtil={};sre.BrowserUtil.detectIE=function(){if(!("undefined"!==typeof window&&"ActiveXObject"in window&&"clipboardData"in window))return!1;sre.BrowserUtil.loadMapsForIE_();sre.BrowserUtil.loadWGXpath_();return!0};sre.BrowserUtil.detectEdge=function(){if(!("undefined"!==typeof window&&"MSGestureEvent"in window&&"chrome"in window&&null==window.chrome.loadTimes))return!1;document.evaluate=null;sre.BrowserUtil.loadWGXpath_(!0);return!0};sre.BrowserUtil.mapsForIE=null;
-sre.BrowserUtil.loadWGXpath_=function(a){sre.BrowserUtil.loadScript(sre.SystemExternal.WGXpath);sre.BrowserUtil.installWGXpath_(a)};
-sre.BrowserUtil.installWGXpath_=function(a,b){var c=b||1;"undefined"===typeof wgxpath&&10>c?setTimeout(function(){sre.BrowserUtil.installWGXpath_(a,c++)},200):10<=c||(sre.SystemExternal.wgxpath=wgxpath,a?sre.SystemExternal.wgxpath.install({document:document}):sre.SystemExternal.wgxpath.install(),sre.XpathUtil.xpathEvaluate=document.evaluate,sre.XpathUtil.xpathResult=XPathResult,sre.XpathUtil.createNSResolver=document.createNSResolver)};
-sre.BrowserUtil.loadMapsForIE_=function(){sre.BrowserUtil.loadScript(sre.SystemExternal.jsonPath+"mathmaps_ie.js")};sre.BrowserUtil.loadScript=function(a){var b=sre.SystemExternal.document.createElement("script");b.type="text/javascript";b.src=a;sre.SystemExternal.document.head?sre.SystemExternal.document.head.appendChild(b):sre.SystemExternal.document.body.appendChild(b)};sre.DynamicProperties=function(a,b){this.properties_=a;this.order_=b||Object.keys(a)};sre.DynamicProperties.prototype.getProperties=function(){return this.properties_};sre.DynamicProperties.prototype.getOrder=function(){return this.order_};sre.DynamicProperties.prototype.getAxes=function(){return this.order_};sre.DynamicProperties.prototype.getProperty=function(a){return this.properties_[a]};sre.DynamicProperties.prototype.updateProperties=function(a){this.properties_=a};
-sre.DynamicProperties.prototype.allProperties=function(){var a=[];this.order_.forEach(goog.bind(function(b){a.push(this.getProperty(b))},this));return a};sre.DynamicProperties.prototype.toString=function(){var a=[];this.order_.forEach(goog.bind(function(b){a.push(b+": "+this.getProperty(b).toString())},this));return a.join("\n")};
-sre.DynamicCstr=function(a,b){this.components_=a;var c={},d;for(d in a){var e=a[d];c[d]=[e];sre.DynamicCstr.Values_.getInstance().add(d,e)}sre.DynamicProperties.call(this,c,b)};goog.inherits(sre.DynamicCstr,sre.DynamicProperties);sre.DynamicCstr.prototype.getComponents=function(){return this.components_};sre.DynamicCstr.prototype.getValue=function(a){return this.components_[a]};
-sre.DynamicCstr.prototype.getValues=function(){var a=[];this.order_.forEach(goog.bind(function(b){a.push(this.getValue(b))},this));return a};sre.DynamicCstr.prototype.toString=function(){return this.getValues().join(".")};sre.DynamicCstr.prototype.equal=function(a){var b=a.getAxes();if(this.order_.length!==b.length)return!1;for(var c=0,d;d=b[c];c++){var e=this.getValue(d);if(!e||a.getValue(d)!==e)return!1}return!0};
-sre.DynamicCstr.Axis={DOMAIN:"domain",STYLE:"style",LOCALE:"locale",TOPIC:"topic",MODALITY:"modality"};sre.DynamicCstr.Values_=function(){this.axisToValues=sre.DynamicCstr.Values_.makeAxisValueObject_()};goog.addSingletonGetter(sre.DynamicCstr.Values_);sre.DynamicCstr.Values_.prototype.add=function(a,b){this.axisToValues[a][b]=!0};sre.DynamicCstr.Values_.prototype.get=function(){var a={},b=sre.DynamicCstr.Values_.getInstance().axisToValues,c;for(c in b)a[c]=Object.keys(b[c]);return a};
-sre.DynamicCstr.Values_.makeAxisValueObject_=function(){var a={},b;for(b in sre.DynamicCstr.Axis)a[sre.DynamicCstr.Axis[b]]={};return a};sre.DynamicCstr.getAxisValues=function(){return sre.DynamicCstr.Values_.getInstance().get()};sre.DynamicCstr.DEFAULT_ORDER=[sre.DynamicCstr.Axis.LOCALE,sre.DynamicCstr.Axis.DOMAIN,sre.DynamicCstr.Axis.STYLE,sre.DynamicCstr.Axis.TOPIC,sre.DynamicCstr.Axis.MODALITY];sre.DynamicCstr.DEFAULT_VALUE="default";sre.DynamicCstr.DEFAULT_VALUES={};
-sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE]="en";sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.DOMAIN]=sre.DynamicCstr.DEFAULT_VALUE;sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.STYLE]=sre.DynamicCstr.DEFAULT_VALUE;sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.TOPIC]=sre.DynamicCstr.DEFAULT_VALUE;sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.MODALITY]=sre.DynamicCstr.DEFAULT_VALUE;sre.DynamicCstr.Parser=function(a){this.order_=a};
-sre.DynamicCstr.Parser.prototype.parse=function(a){a=a.split(".");var b={};if(a.length>this.order_.length)throw Error("Invalid dynamic constraint: "+b);for(var c=0,d;d=this.order_[c],a.length;c++){var e=a.shift();b[d]=e}return new sre.DynamicCstr(b,this.order_.slice(0,c))};sre.DynamicCstr.Comparator=function(){};sre.DynamicCstr.Comparator.prototype.getReference=function(){};sre.DynamicCstr.Comparator.prototype.setReference=function(a,b){};sre.DynamicCstr.Comparator.prototype.match=function(a){};
-sre.DynamicCstr.Comparator.prototype.compare=function(a,b){};sre.DynamicCstr.DefaultComparator=function(a,b){this.reference_=a;this.fallback_=b||new sre.DynamicProperties(a.getProperties(),a.getOrder());this.order_=this.reference_.getOrder()};sre.DynamicCstr.DefaultComparator.prototype.getReference=function(){return this.reference_};
-sre.DynamicCstr.DefaultComparator.prototype.setReference=function(a,b){this.reference_=a;this.fallback_=b||new sre.DynamicProperties(a.getProperties(),a.getOrder());this.order_=this.reference_.getOrder()};sre.DynamicCstr.DefaultComparator.prototype.match=function(a){var b=a.getAxes();return b.length===this.reference_.getAxes().length&&b.every(goog.bind(function(b){var c=a.getValue(b);return c===this.reference_.getValue(b)||-1!==this.fallback_.getProperty(b).indexOf(c)},this))};
-sre.DynamicCstr.DefaultComparator.prototype.compare=function(a,b){for(var c=!1,d=0,e;e=this.order_[d];d++){var f=a.getValue(e),g=b.getValue(e);if(!c){var h=this.reference_.getValue(e);if(h===f&&h!==g)return-1;if(h===g&&h!==f)return 1;if(h===f&&h===g)continue;h!==f&&h!==g&&(c=!0)}e=this.fallback_.getProperty(e);f=e.indexOf(f);g=e.indexOf(g);if(f<g)return-1;if(g<f)return 1}return 0};
-sre.DynamicProperties.create=function(a){for(var b=sre.DynamicCstr.DEFAULT_ORDER,c={},d=Array.prototype.slice.call(arguments,0),e=0,f=d.length,g=b.length;e<f&&e<g;e++)c[b[e]]=d[e];return new sre.DynamicProperties(c)};sre.DynamicCstr.create=function(a){for(var b=sre.DynamicCstr.DEFAULT_ORDER,c={},d=Array.prototype.slice.call(arguments,0),e=0,f=d.length,g=b.length;e<f&&e<g;e++)c[b[e]]=d[e];return new sre.DynamicCstr(c)};
-sre.DynamicCstr.defaultCstr=function(){return sre.DynamicCstr.create.apply(null,sre.DynamicCstr.DEFAULT_ORDER.map(function(a){return sre.DynamicCstr.DEFAULT_VALUES[a]}))};sre.DynamicCstr.validOrder=function(a){var b=sre.DynamicCstr.DEFAULT_ORDER.slice();return a.every(function(a){a=b.indexOf(a);return-1!==a&&b.splice(a,1)})};sre.Engine=function(){this.alternativeHost=this.activeHost=null;this.evaluator=sre.Engine.defaultEvaluator;this.parser=new sre.DynamicCstr.Parser(sre.DynamicCstr.DEFAULT_ORDER);this.dynamicCstr=sre.DynamicCstr.defaultCstr();this.comparator=null;this.comparators={};this.domain=sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.DOMAIN];this.style="short";this.locale=sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE];this.walker="Syntax";this.semantics=!0;this.mode=sre.Engine.Mode.SYNC;this.speech=
-sre.Engine.Speech.SHALLOW;this.ruleSets=[];this.cache=!0;this.markup=sre.Engine.Markup.NONE;this.isEdge=this.isIE=this.strict=!1;this.setupTests_=[]};goog.addSingletonGetter(sre.Engine);sre.Engine.personalityProps={PITCH:"pitch",RATE:"rate",VOLUME:"volume",PAUSE:"pause",JOIN:"join"};sre.Engine.Mode={SYNC:"sync",ASYNC:"async",HTTP:"http"};sre.Engine.Speech={NONE:"none",SHALLOW:"shallow",DEEP:"deep"};sre.Engine.Markup={NONE:"none",PUNCTUATION:"punctuation",SSML:"ssml",ACSS:"acss",SABLE:"sable",VOICEXML:"voicexml"};
-sre.Engine.registerTest=function(a){sre.Engine.getInstance().setupTests_.push(a)};sre.Engine.isReady=function(){return sre.Engine.getInstance().setupTests_.every(function(a){return a()})};sre.Engine.prototype.setupBrowsers=function(){this.isIE=sre.BrowserUtil.detectIE();this.isEdge=sre.BrowserUtil.detectEdge()};sre.Engine.prototype.getAxisValues=function(){return sre.DynamicCstr.getAxisValues()};sre.Engine.defaultEvaluator=function(a,b){return a};sre.Grammar=function(){this.parameters_={};this.corrections_={};this.preprocessors_={};this.stateStack_=[]};goog.addSingletonGetter(sre.Grammar);sre.Grammar.ATTRIBUTE="grammar";sre.Grammar.prototype.clear=function(){this.parameters_={};this.stateStack_=[]};sre.Grammar.prototype.setParameter=function(a,b){var c=this.parameters_[a];b?this.parameters_[a]=b:delete this.parameters_[a];return c};sre.Grammar.prototype.getParameter=function(a){return this.parameters_[a]};
-sre.Grammar.prototype.setCorrection=function(a,b){this.corrections_[a]=b};sre.Grammar.prototype.setPreprocessor=function(a,b){this.preprocessors_[a]=b};sre.Grammar.prototype.getCorrection=function(a){return this.corrections_[a]};sre.Grammar.prototype.getState=function(){var a=[],b;for(b in this.parameters_){var c=this.parameters_[b];a.push("string"===typeof c?b+":"+c:b)}return a.join(" ")};sre.Grammar.prototype.pushState=function(a){for(var b in a)a[b]=this.setParameter(b,a[b]);this.stateStack_.push(a)};
-sre.Grammar.prototype.popState=function(){var a=this.stateStack_.pop(),b;for(b in a)this.setParameter(b,a[b])};sre.Grammar.prototype.setAttribute=function(a){if(a&&a.nodeType===sre.DomUtil.NodeType.ELEMENT_NODE){var b=this.getState();b&&a.setAttribute(sre.Grammar.ATTRIBUTE,b)}};sre.Grammar.prototype.preprocess=function(a){return this.runProcessors_(a,this.preprocessors_)};sre.Grammar.prototype.correct=function(a){return this.runProcessors_(a,this.corrections_)};
-sre.Grammar.prototype.runProcessors_=function(a,b){for(var c in this.parameters_){var d=b[c];if(d){var e=this.parameters_[c];a=!0===e?d(a):d(a,e)}}return a};sre.Grammar.translateString_=function(a){var b=sre.Engine.getInstance();return b.evaluator(a,b.dynamicCstr)||a};
-sre.Grammar.prototype.apply=function(a,b){var c=b||{};a=c.adjust||c.preprocess?sre.Grammar.getInstance().preprocess(a):a;if(this.parameters_.translate||c.translate)a=sre.Grammar.translateString_(a);return a=c.adjust||c.correct?sre.Grammar.getInstance().correct(a):a};sre.Grammar.parseState=function(a){var b={};a=a.split(" ");for(var c=0,d=a.length;c<d;c++){var e=a[c].split(":"),f=e[1];b[e[0]]=f?f:!0}return b};
-sre.Grammar.parseInput=function(a){var b={};a=a.split(":");for(var c=0,d=a.length;c<d;c++){var e=a[c].split("="),f=e[0].trim();e[1]?b[f]=e[1].trim():f.match(/^!/)?b[f.slice(1)]=!1:b[f]=!0}return b};sre.Grammar.correctFont_=function(a,b){if(!b||!a)return a;b=sre.L10n.getLocale().FONT[b]||b;var c=b.split(/ |-/),c=new RegExp("^"+c.join("( |-)")+"( |-)");return a.replace(c,"")};sre.Grammar.addAnnotation_=function(a,b){return a+":"+b};sre.Grammar.getInstance().setCorrection("ignoreFont",sre.Grammar.correctFont_);
-sre.Grammar.getInstance().setPreprocessor("annotation",sre.Grammar.addAnnotation_);sre.BaseUtil={};sre.BaseUtil.removeEmpty=function(a){return a.filter(function(a){return a})};sre.BaseUtil.interleaveLists=function(a,b){for(var c=[];a.length||b.length;)a.length&&c.push(a.shift()),b.length&&c.push(b.shift());return c};sre.BaseUtil.setdifference=function(a,b){return a?b?a.filter(function(a){return 0>b.indexOf(a)}):a:[]};sre.BaseUtil.union=function(a,b){return a&&b?a.concat(sre.BaseUtil.setdifference(b,a)):a||b||[]};sre.BaseUtil.makePath=function(a){return a.match("/$")?a:a+"/"};sre.XpathUtil={};sre.XpathUtil.xpathSupported=function(){return"undefined"==typeof XPathResult?!1:!0};sre.XpathUtil.currentDocument=null;sre.XpathUtil.xpathEvaluate=sre.XpathUtil.xpathSupported()?document.evaluate:sre.SystemExternal.xpath.evaluate;sre.XpathUtil.xpathResult=sre.XpathUtil.xpathSupported()?XPathResult:sre.SystemExternal.xpath.XPathResult;sre.XpathUtil.createNSResolver=sre.XpathUtil.xpathSupported()?document.createNSResolver:sre.SystemExternal.xpath.createNSResolver;
-sre.XpathUtil.nameSpaces_={xhtml:"http://www.w3.org/1999/xhtml",mathml:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg"};sre.XpathUtil.resolveNameSpace=function(a){return sre.XpathUtil.nameSpaces_[a]||null};sre.XpathUtil.resolver_=function(){this.lookupNamespaceURI=sre.XpathUtil.resolveNameSpace};
-sre.XpathUtil.evaluateXpath_=function(a,b,c){var d=sre.Engine.getInstance();return d.mode!==sre.Engine.Mode.HTTP||d.isIE||d.isEdge?sre.XpathUtil.xpathEvaluate(a,b,new sre.XpathUtil.resolver_,c,null):sre.XpathUtil.currentDocument.evaluate(a,b,sre.XpathUtil.resolveNameSpace,c,null)};sre.XpathUtil.evalXPath=function(a,b){try{var c=sre.XpathUtil.evaluateXpath_(a,b,sre.XpathUtil.xpathResult.ORDERED_NODE_ITERATOR_TYPE)}catch(f){return[]}for(var d=[],e=c.iterateNext();e;e=c.iterateNext())d.push(e);return d};
-sre.XpathUtil.getLeafNodes=function(a){return sre.XpathUtil.evalXPath(".//*[count(*)=0]",a)};sre.XpathUtil.evaluateBoolean=function(a,b){try{var c=sre.XpathUtil.evaluateXpath_(a,b,sre.XpathUtil.xpathResult.BOOLEAN_TYPE)}catch(d){return!1}return c.booleanValue};sre.XpathUtil.evaluateString=function(a,b){try{var c=sre.XpathUtil.evaluateXpath_(a,b,sre.XpathUtil.xpathResult.STRING_TYPE)}catch(d){return""}return c.stringValue};sre.DomUtil={};sre.DomUtil.toArray=function(a){for(var b=[],c=0,d=a.length;c<d;c++)b.push(a[c]);return b};sre.DomUtil.trimInput_=function(a){a=a.replace(/&nbsp;/g," ");return a.replace(/>\s+</g,"><").trim()};sre.DomUtil.XML_ENTITIES={"&lt;":!0,"&gt;":!0,"&amp;":!0,"&quot;":!0,"&apos;":!0};
-sre.DomUtil.parseInput=function(a,b){var c=b||Error,d=new sre.SystemExternal.xmldom.DOMParser,e=sre.DomUtil.trimInput_(a),f=!!e.match(/\&(?!lt|gt|amp|quot|apos)\w+;/g);if(!e)throw new c("Empty input!");try{var g=d.parseFromString(e,f?"text/html":"text/xml");return sre.Engine.getInstance().mode===sre.Engine.Mode.HTTP?(sre.XpathUtil.currentDocument=g,f?g.body.childNodes[0]:g.documentElement):g.documentElement}catch(h){throw new c("Illegal input: "+h.message);}};
-sre.DomUtil.NodeType={ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12};sre.DomUtil.replaceNode=function(a,b){a.parentNode&&(a.parentNode.insertBefore(b,a),a.parentNode.removeChild(a))};sre.DomUtil.createElement=function(a){return sre.SystemExternal.document.createElement(a)};sre.DomUtil.createTextNode=function(a){return sre.SystemExternal.document.createTextNode(a)};
-sre.DomUtil.formatXml=function(a){var b=/(>)(<)(\/*)/g;a=a.replace(b,"$1\r\n$2$3");b=/(>)(.+)(<c)/g;a=a.replace(b,"$1\r\n$2\r\n$3");var c="",d="";a.split("\r\n").forEach(function(a){a.match(/.+<\/\w[^>]*>$/)?c+=d+a+"\r\n":a.match(/^<\/\w/)?d&&(d=d.slice(2),c+=d+a+"\r\n"):a.match(/^<\w[^>]*[^\/]>.*$/)?(c+=d+a+"\r\n",d+=" "):c+=d+a+"\r\n"});return c};sre.DomUtil.dataAttribute=function(a){a.match(/^data-/)&&(a=a.substr(5));return a.replace(/-([a-z])/g,function(a,c){return c.toUpperCase()})};
-sre.DomUtil.getDataAttribute=function(a,b){return a.dataset?a.dataset[sre.DomUtil.dataAttribute(b)]:a.getAttribute(b)};sre.DomUtil.querySelectorAllByAttr=function(a,b){return a.querySelectorAll?sre.DomUtil.toArray(a.querySelectorAll("["+b+"]")):sre.XpathUtil.evalXPath(".//*[@"+b+"]",a)};sre.DomUtil.querySelectorAllByAttrValue=function(a,b,c){return a.querySelectorAll?sre.DomUtil.toArray(a.querySelectorAll("["+b+'="'+c+'"]')):sre.XpathUtil.evalXPath(".//*[@"+b+'="'+c+'"]',a)};
-sre.DomUtil.querySelectorAll=function(a,b){return a.querySelectorAll?sre.DomUtil.toArray(a.querySelectorAll(b)):sre.XpathUtil.evalXPath(".//"+b,a)};sre.DomUtil.tagName=function(a){return a.tagName.toUpperCase()};sre.Messages={};sre.Messages.MS={START:"",FRAC_V:"",FRAC_B:"",FRAC_S:"",END:"",FRAC_OVER:"",TWICE:"",NEST_FRAC:"",ENDFRAC:"",SUPER:"",SUB:"",SUP:"",SUPERSCRIPT:"",SUBSCRIPT:"",BASELINE:"",BASE:"",NESTED:"",NEST_ROOT:"",STARTROOT:"",ENDROOT:"",ROOTINDEX:"",ROOT:"",INDEX:"",UNDER:"",UNDERSCRIPT:"",OVER:"",OVERSCRIPT:""};sre.Messages.MS_FUNC={FRAC_NEST_DEPTH:function(a){return!1},RADICAL_NEST_DEPTH:function(a){return""},COMBINE_ROOT_INDEX:function(a,b){return a}};sre.Messages.MS_ROOT_INDEX={};
-sre.Messages.FONT={bold:"","bold-fraktur":"","bold-italic":"","bold-script":"",caligraphic:"","caligraphic-bold":"","double-struck":"","double-struck-italic":"",fraktur:"",italic:"",monospace:"",normal:"",oldstyle:"","oldstyle-bold":"",script:"","sans-serif":"","sans-serif-italic":"","sans-serif-bold":"","sans-serif-bold-italic":"",unknown:""};
-sre.Messages.ROLE={addition:"",multiplication:"",subtraction:"",division:"",equality:"",inequality:"",element:"",arrow:"",determinant:"",rowvector:"",binomial:"",squarematrix:"",multiline:"",matrix:"",vector:"",cases:"",table:"",unknown:""};sre.Messages.ENCLOSE={longdiv:"",actuarial:"",radical:"",box:"",roundedbox:"",circle:"",left:"",right:"",top:"",bottom:"",updiagonalstrike:"",downdiagonalstrike:"",verticalstrike:"",horizontalstrike:"",madruwb:"",updiagonalarrow:"",phasorangle:"",unknown:""};
-sre.Messages.NAVIGATE={COLLAPSIBLE:"",EXPANDABLE:"",LEVEL:""};sre.SemanticUtil=function(){};sre.SemanticUtil.objectsToKeys=function(a){a=Array.prototype.slice.call(arguments,0);var b=[];return b.concat.apply(b,a.map(Object.keys))};sre.SemanticUtil.objectsToValues=function(a){a=Array.prototype.slice.call(arguments,0);var b=[];a.forEach(function(a){for(var c in a)b.push(a[c])});return b};
-sre.SemanticUtil.unicodeToNumber=function(a){if(!a||2<a.length)return null;if(2==a.length){var b=a.charCodeAt(0);a=a.charCodeAt(1);return 55296<=b&&56319>=b&&!isNaN(a)?1024*(b-55296)+(a-56320)+65536:null}return a.charCodeAt(0)};sre.SemanticUtil.numberToUnicode=function(a){return 65536>a?String.fromCharCode(a):String.fromCharCode((a-65536)/1024+55296,(a-65536)%1024+56320)};
-sre.SemanticUtil.splitUnicode=function(a){a=a.split("");for(var b=[],c=0,d;d=a[c];c++)"\ud800"<=d&&"\udbff">=d&&a[c+1]?b.push(d+a[++c]):b.push(d);return b};sre.SemanticUtil.LEAFTAGS=["MO","MI","MN","MTEXT","MS"];sre.SemanticUtil.IGNORETAGS="MERROR MPHANTOM MSPACE MALIGNGROUP MALIGNMARK MPRESCRIPTS ANNOTATION ANNOTATION-XML".split(" ");sre.SemanticUtil.EMPTYTAGS="MATH MROW MPADDED MACTION NONE MSTYLE SEMANTICS".split(" ");sre.SemanticUtil.hasMathTag=function(a){return!!a&&"MATH"===sre.DomUtil.tagName(a)};
-sre.SemanticUtil.hasIgnoreTag=function(a){return!!a&&-1!==sre.SemanticUtil.IGNORETAGS.indexOf(sre.DomUtil.tagName(a))};sre.SemanticUtil.hasEmptyTag=function(a){return!!a&&-1!==sre.SemanticUtil.EMPTYTAGS.indexOf(sre.DomUtil.tagName(a))};sre.SemanticUtil.purgeNodes=function(a){for(var b=[],c=0,d;d=a[c];c++){var e=sre.DomUtil.tagName(d);-1==sre.SemanticUtil.IGNORETAGS.indexOf(e)&&(-1!=sre.SemanticUtil.EMPTYTAGS.indexOf(e)&&0==d.childNodes.length||b.push(d))}return b};
-sre.SemanticUtil.isZeroLength=function(a){return a?-1!=="negativeveryverythinmathspace negativeverythinmathspace negativethinmathspace negativemediummathspace negativethickmathspace negativeverythickmathspace negativeveryverythickmathspace".split(" ").indexOf(a)?!0:(a=a.match(/[0-9\.]+/))?0===parseFloat(a)?!0:!1:!1:!1};sre.SemanticAttr=function(){this.generalPunctuations='!"#%&:;?@\\\u00a1\u00a7\u00b6\u00bf\u2017\u2020\u2021\u2022\u2023\u2024\u2025\u2027\u2030\u2031\u2038\u203b\u203c\u203d\u203e\u2041\u2042\u2043\u2047\u2048\u2049\u204b\u204c\u204d\u204e\u204f\u2050\u2051\u2053\u2055\u2056\u2058\u2059\u205a\u205b\u205c\u205d\u205e\ufe10\ufe13\ufe14\ufe15\ufe16\ufe30\ufe45\ufe46\ufe49\ufe4a\ufe4b\ufe4c\ufe50\ufe54\ufe55\ufe56\ufe57\ufe5f\ufe60\ufe61\ufe68\ufe6a\ufe6b\uff01\uff02\uff03\uff05\uff06\uff07\uff0a\uff0c\uff0f\uff1a\uff1b\uff1f\uff20\uff3c'.split("");
-this.colons=[":","\uff1a","\ufe55"];this.invisibleComma_=sre.SemanticUtil.numberToUnicode(8291);this.commas=[",",this.invisibleComma_];this.ellipses="\u2026\u22ee\u22ef\u22f0\u22f1\ufe19".split("");this.fullStops=[".","\ufe52","\uff0e"];this.dashes="\u2012\u2013\u2014\u2015\u301c\ufe31\ufe32\ufe58".split("");this.primes="'\u2032\u2033\u2034\u2035\u2036\u2037\u2057".split("");this.degrees=["\u00b0"];this.openClosePairs={"(":")","[":"]","{":"}","\u2045":"\u2046","\u2329":"\u232a","\u2768":"\u2769",
-"\u276a":"\u276b","\u276c":"\u276d","\u276e":"\u276f","\u2770":"\u2771","\u2772":"\u2773","\u2774":"\u2775","\u27c5":"\u27c6","\u27e6":"\u27e7","\u27e8":"\u27e9","\u27ea":"\u27eb","\u27ec":"\u27ed","\u27ee":"\u27ef","\u2983":"\u2984","\u2985":"\u2986","\u2987":"\u2988","\u2989":"\u298a","\u298b":"\u298c","\u298d":"\u298e","\u298f":"\u2990","\u2991":"\u2992","\u2993":"\u2994","\u2995":"\u2996","\u2997":"\u2998","\u29d8":"\u29d9","\u29da":"\u29db","\u29fc":"\u29fd","\u2e22":"\u2e23","\u2e24":"\u2e25",
-"\u2e26":"\u2e27","\u2e28":"\u2e29","\u3008":"\u3009","\u300a":"\u300b","\u300c":"\u300d","\u300e":"\u300f","\u3010":"\u3011","\u3014":"\u3015","\u3016":"\u3017","\u3018":"\u3019","\u301a":"\u301b","\u301d":"\u301e","\ufd3e":"\ufd3f","\ufe17":"\ufe18","\ufe59":"\ufe5a","\ufe5b":"\ufe5c","\ufe5d":"\ufe5e","\uff08":"\uff09","\uff3b":"\uff3d","\uff5b":"\uff5d","\uff5f":"\uff60","\uff62":"\uff63","\u2308":"\u2309","\u230a":"\u230b","\u230c":"\u230d","\u230e":"\u230f","\u231c":"\u231d","\u231e":"\u231f",
-"\u239b":"\u239e","\u239c":"\u239f","\u239d":"\u23a0","\u23a1":"\u23a4","\u23a2":"\u23a5","\u23a3":"\u23a6","\u23a7":"\u23ab","\u23a8":"\u23ac","\u23a9":"\u23ad","\u23b0":"\u23b1","\u23b8":"\u23b9"};this.topBottomPairs={"\u23b4":"\u23b5","\u23dc":"\u23dd","\u23de":"\u23df","\u23e0":"\u23e1","\ufe35":"\ufe36","\ufe37":"\ufe38","\ufe39":"\ufe3a","\ufe3b":"\ufe3c","\ufe3d":"\ufe3e","\ufe3f":"\ufe40","\ufe41":"\ufe42","\ufe43":"\ufe44","\ufe47":"\ufe48"};this.leftFences=sre.SemanticUtil.objectsToKeys(this.openClosePairs);
-this.rightFences=sre.SemanticUtil.objectsToValues(this.openClosePairs);this.rightFences.push("\u301f");this.topFences=sre.SemanticUtil.objectsToKeys(this.topBottomPairs);this.bottomFences=sre.SemanticUtil.objectsToValues(this.topBottomPairs);this.neutralFences="|\u00a6\u2016\u2758\u2980\u2af4\uffe4\uff5c".split("");this.allFences=this.neutralFences.concat(this.leftFences,this.rightFences,this.topFences,this.bottomFences);this.capitalLatin="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");this.smallLatin="abcdefghijklmnopqrstuvwxyz\u0131\u0237".split("");
-this.capitalLatinFullWidth="\uff21\uff22\uff23\uff24\uff25\uff26\uff27\uff28\uff29\uff2a\uff2b\uff2c\uff2d\uff2e\uff2f\uff30\uff31\uff32\uff33\uff34\uff35\uff36\uff37\uff38\uff39\uff3a".split("");this.smallLatinFullWidth="\uff41\uff42\uff43\uff44\uff45\uff46\uff47\uff48\uff49\uff4a\uff4b\uff4c\uff4d\uff4e\uff4f\uff50\uff51\uff52\uff53\uff54\uff55\uff56\uff57\uff58\uff59\uff5a".split("");this.capitalLatinBold="\ud835\udc00 \ud835\udc01 \ud835\udc02 \ud835\udc03 \ud835\udc04 \ud835\udc05 \ud835\udc06 \ud835\udc07 \ud835\udc08 \ud835\udc09 \ud835\udc0a \ud835\udc0b \ud835\udc0c \ud835\udc0d \ud835\udc0e \ud835\udc0f \ud835\udc10 \ud835\udc11 \ud835\udc12 \ud835\udc13 \ud835\udc14 \ud835\udc15 \ud835\udc16 \ud835\udc17 \ud835\udc18 \ud835\udc19".split(" ");
-this.smallLatinBold="\ud835\udc1a \ud835\udc1b \ud835\udc1c \ud835\udc1d \ud835\udc1e \ud835\udc1f \ud835\udc20 \ud835\udc21 \ud835\udc22 \ud835\udc23 \ud835\udc24 \ud835\udc25 \ud835\udc26 \ud835\udc27 \ud835\udc28 \ud835\udc29 \ud835\udc2a \ud835\udc2b \ud835\udc2c \ud835\udc2d \ud835\udc2e \ud835\udc2f \ud835\udc30 \ud835\udc31 \ud835\udc32 \ud835\udc33".split(" ");this.capitalLatinItalic="\ud835\udc34 \ud835\udc35 \ud835\udc36 \ud835\udc37 \ud835\udc38 \ud835\udc39 \ud835\udc3a \ud835\udc3b \ud835\udc3c \ud835\udc3d \ud835\udc3e \ud835\udc3f \ud835\udc40 \ud835\udc41 \ud835\udc42 \ud835\udc43 \ud835\udc44 \ud835\udc45 \ud835\udc46 \ud835\udc47 \ud835\udc48 \ud835\udc49 \ud835\udc4a \ud835\udc4b \ud835\udc4c \ud835\udc4d".split(" ");
-this.smallLatinItalic="\ud835\udc4e \ud835\udc4f \ud835\udc50 \ud835\udc51 \ud835\udc52 \ud835\udc53 \ud835\udc54 \u210e \ud835\udc56 \ud835\udc57 \ud835\udc58 \ud835\udc59 \ud835\udc5a \ud835\udc5b \ud835\udc5c \ud835\udc5d \ud835\udc5e \ud835\udc5f \ud835\udc60 \ud835\udc61 \ud835\udc62 \ud835\udc63 \ud835\udc64 \ud835\udc65 \ud835\udc66 \ud835\udc67 \ud835\udea4 \ud835\udea5".split(" ");this.capitalLatinScript="\ud835\udc9c \u212c \ud835\udc9e \ud835\udc9f \u2130 \u2131 \ud835\udca2 \u210b \u2110 \ud835\udca5 \ud835\udca6 \u2112 \u2133 \ud835\udca9 \ud835\udcaa \ud835\udcab \ud835\udcac \u211b \ud835\udcae \ud835\udcaf \ud835\udcb0 \ud835\udcb1 \ud835\udcb2 \ud835\udcb3 \ud835\udcb4 \ud835\udcb5 \u2118".split(" ");
-this.smallLatinScript="\ud835\udcb6 \ud835\udcb7 \ud835\udcb8 \ud835\udcb9 \u212f \ud835\udcbb \u210a \ud835\udcbd \ud835\udcbe \ud835\udcbf \ud835\udcc0 \ud835\udcc1 \ud835\udcc2 \ud835\udcc3 \u2134 \ud835\udcc5 \ud835\udcc6 \ud835\udcc7 \ud835\udcc8 \ud835\udcc9 \ud835\udcca \ud835\udccb \ud835\udccc \ud835\udccd \ud835\udcce \ud835\udccf \u2113".split(" ");this.capitalLatinBoldScript="\ud835\udcd0 \ud835\udcd1 \ud835\udcd2 \ud835\udcd3 \ud835\udcd4 \ud835\udcd5 \ud835\udcd6 \ud835\udcd7 \ud835\udcd8 \ud835\udcd9 \ud835\udcda \ud835\udcdb \ud835\udcdc \ud835\udcdd \ud835\udcde \ud835\udcdf \ud835\udce0 \ud835\udce1 \ud835\udce2 \ud835\udce3 \ud835\udce4 \ud835\udce5 \ud835\udce6 \ud835\udce7 \ud835\udce8 \ud835\udce9".split(" ");
-this.smallLatinBoldScript="\ud835\udcea \ud835\udceb \ud835\udcec \ud835\udced \ud835\udcee \ud835\udcef \ud835\udcf0 \ud835\udcf1 \ud835\udcf2 \ud835\udcf3 \ud835\udcf4 \ud835\udcf5 \ud835\udcf6 \ud835\udcf7 \ud835\udcf8 \ud835\udcf9 \ud835\udcfa \ud835\udcfb \ud835\udcfc \ud835\udcfd \ud835\udcfe \ud835\udcff \ud835\udd00 \ud835\udd01 \ud835\udd02 \ud835\udd03".split(" ");this.capitalLatinFraktur="\ud835\udd04 \ud835\udd05 \u212d \ud835\udd07 \ud835\udd08 \ud835\udd09 \ud835\udd0a \u210c \u2111 \ud835\udd0d \ud835\udd0e \ud835\udd0f \ud835\udd10 \ud835\udd11 \ud835\udd12 \ud835\udd13 \ud835\udd14 \u211c \ud835\udd16 \ud835\udd17 \ud835\udd18 \ud835\udd19 \ud835\udd1a \ud835\udd1b \ud835\udd1c \u2128".split(" ");
-this.smallLatinFraktur="\ud835\udd1e \ud835\udd1f \ud835\udd20 \ud835\udd21 \ud835\udd22 \ud835\udd23 \ud835\udd24 \ud835\udd25 \ud835\udd26 \ud835\udd27 \ud835\udd28 \ud835\udd29 \ud835\udd2a \ud835\udd2b \ud835\udd2c \ud835\udd2d \ud835\udd2e \ud835\udd2f \ud835\udd30 \ud835\udd31 \ud835\udd32 \ud835\udd33 \ud835\udd34 \ud835\udd35 \ud835\udd36 \ud835\udd37".split(" ");this.capitalLatinDoubleStruck="\ud835\udd38 \ud835\udd39 \u2102 \ud835\udd3b \ud835\udd3c \ud835\udd3d \ud835\udd3e \u210d \ud835\udd40 \ud835\udd41 \ud835\udd42 \ud835\udd43 \ud835\udd44 \u2115 \ud835\udd46 \u2119 \u211a \u211d \ud835\udd4a \ud835\udd4b \ud835\udd4c \ud835\udd4d \ud835\udd4e \ud835\udd4f \ud835\udd50 \u2124".split(" ");
-this.smallLatinDoubleStruck="\ud835\udd52 \ud835\udd53 \ud835\udd54 \ud835\udd55 \ud835\udd56 \ud835\udd57 \ud835\udd58 \ud835\udd59 \ud835\udd5a \ud835\udd5b \ud835\udd5c \ud835\udd5d \ud835\udd5e \ud835\udd5f \ud835\udd60 \ud835\udd61 \ud835\udd62 \ud835\udd63 \ud835\udd64 \ud835\udd65 \ud835\udd66 \ud835\udd67 \ud835\udd68 \ud835\udd69 \ud835\udd6a \ud835\udd6b".split(" ");this.capitalLatinBoldFraktur="\ud835\udd6c \ud835\udd6d \ud835\udd6e \ud835\udd6f \ud835\udd70 \ud835\udd71 \ud835\udd72 \ud835\udd73 \ud835\udd74 \ud835\udd75 \ud835\udd76 \ud835\udd77 \ud835\udd78 \ud835\udd79 \ud835\udd7a \ud835\udd7b \ud835\udd7c \ud835\udd7d \ud835\udd7e \ud835\udd7f \ud835\udd80 \ud835\udd81 \ud835\udd82 \ud835\udd83 \ud835\udd84 \ud835\udd85".split(" ");
-this.smallLatinBoldFraktur="\ud835\udd86 \ud835\udd87 \ud835\udd88 \ud835\udd89 \ud835\udd8a \ud835\udd8b \ud835\udd8c \ud835\udd8d \ud835\udd8e \ud835\udd8f \ud835\udd90 \ud835\udd91 \ud835\udd92 \ud835\udd93 \ud835\udd94 \ud835\udd95 \ud835\udd96 \ud835\udd97 \ud835\udd98 \ud835\udd99 \ud835\udd9a \ud835\udd9b \ud835\udd9c \ud835\udd9d \ud835\udd9e \ud835\udd9f".split(" ");this.capitalLatinSansSerif="\ud835\udda0 \ud835\udda1 \ud835\udda2 \ud835\udda3 \ud835\udda4 \ud835\udda5 \ud835\udda6 \ud835\udda7 \ud835\udda8 \ud835\udda9 \ud835\uddaa \ud835\uddab \ud835\uddac \ud835\uddad \ud835\uddae \ud835\uddaf \ud835\uddb0 \ud835\uddb1 \ud835\uddb2 \ud835\uddb3 \ud835\uddb4 \ud835\uddb5 \ud835\uddb6 \ud835\uddb7 \ud835\uddb8 \ud835\uddb9".split(" ");
-this.smallLatinSansSerif="\ud835\uddba \ud835\uddbb \ud835\uddbc \ud835\uddbd \ud835\uddbe \ud835\uddbf \ud835\uddc0 \ud835\uddc1 \ud835\uddc2 \ud835\uddc3 \ud835\uddc4 \ud835\uddc5 \ud835\uddc6 \ud835\uddc7 \ud835\uddc8 \ud835\uddc9 \ud835\uddca \ud835\uddcb \ud835\uddcc \ud835\uddcd \ud835\uddce \ud835\uddcf \ud835\uddd0 \ud835\uddd1 \ud835\uddd2 \ud835\uddd3".split(" ");this.capitalLatinSansSerifBold="\ud835\uddd4 \ud835\uddd5 \ud835\uddd6 \ud835\uddd7 \ud835\uddd8 \ud835\uddd9 \ud835\uddda \ud835\udddb \ud835\udddc \ud835\udddd \ud835\uddde \ud835\udddf \ud835\udde0 \ud835\udde1 \ud835\udde2 \ud835\udde3 \ud835\udde4 \ud835\udde5 \ud835\udde6 \ud835\udde7 \ud835\udde8 \ud835\udde9 \ud835\uddea \ud835\uddeb \ud835\uddec \ud835\udded".split(" ");
-this.smallLatinSansSerifBold="\ud835\uddee \ud835\uddef \ud835\uddf0 \ud835\uddf1 \ud835\uddf2 \ud835\uddf3 \ud835\uddf4 \ud835\uddf5 \ud835\uddf6 \ud835\uddf7 \ud835\uddf8 \ud835\uddf9 \ud835\uddfa \ud835\uddfb \ud835\uddfc \ud835\uddfd \ud835\uddfe \ud835\uddff \ud835\ude00 \ud835\ude01 \ud835\ude02 \ud835\ude03 \ud835\ude04 \ud835\ude05 \ud835\ude06 \ud835\ude07".split(" ");this.capitalLatinSansSerifItalic="\ud835\ude08 \ud835\ude09 \ud835\ude0a \ud835\ude0b \ud835\ude0c \ud835\ude0d \ud835\ude0e \ud835\ude0f \ud835\ude10 \ud835\ude11 \ud835\ude12 \ud835\ude13 \ud835\ude14 \ud835\ude15 \ud835\ude16 \ud835\ude17 \ud835\ude18 \ud835\ude19 \ud835\ude1a \ud835\ude1b \ud835\ude1c \ud835\ude1d \ud835\ude1e \ud835\ude1f \ud835\ude20 \ud835\ude21".split(" ");
-this.smallLatinSansSerifItalic="\ud835\ude22 \ud835\ude23 \ud835\ude24 \ud835\ude25 \ud835\ude26 \ud835\ude27 \ud835\ude28 \ud835\ude29 \ud835\ude2a \ud835\ude2b \ud835\ude2c \ud835\ude2d \ud835\ude2e \ud835\ude2f \ud835\ude30 \ud835\ude31 \ud835\ude32 \ud835\ude33 \ud835\ude34 \ud835\ude35 \ud835\ude36 \ud835\ude37 \ud835\ude38 \ud835\ude39 \ud835\ude3a \ud835\ude3b".split(" ");this.capitalLatinMonospace="\ud835\ude70 \ud835\ude71 \ud835\ude72 \ud835\ude73 \ud835\ude74 \ud835\ude75 \ud835\ude76 \ud835\ude77 \ud835\ude78 \ud835\ude79 \ud835\ude7a \ud835\ude7b \ud835\ude7c \ud835\ude7d \ud835\ude7e \ud835\ude7f \ud835\ude80 \ud835\ude81 \ud835\ude82 \ud835\ude83 \ud835\ude84 \ud835\ude85 \ud835\ude86 \ud835\ude87 \ud835\ude88 \ud835\ude89".split(" ");
-this.smallLatinMonospace="\ud835\ude8a \ud835\ude8b \ud835\ude8c \ud835\ude8d \ud835\ude8e \ud835\ude8f \ud835\ude90 \ud835\ude91 \ud835\ude92 \ud835\ude93 \ud835\ude94 \ud835\ude95 \ud835\ude96 \ud835\ude97 \ud835\ude98 \ud835\ude99 \ud835\ude9a \ud835\ude9b \ud835\ude9c \ud835\ude9d \ud835\ude9e \ud835\ude9f \ud835\udea0 \ud835\udea1 \ud835\udea2 \ud835\udea3".split(" ");this.latinDoubleStruckItalic=["\u2145","\u2146","\u2147","\u2148","\u2149"];this.capitalGreek="\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9".split("");
-this.smallGreek="\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9".split("");this.capitalGreekBold="\ud835\udea8 \ud835\udea9 \ud835\udeaa \ud835\udeab \ud835\udeac \ud835\udead \ud835\udeae \ud835\udeaf \ud835\udeb0 \ud835\udeb1 \ud835\udeb2 \ud835\udeb3 \ud835\udeb4 \ud835\udeb5 \ud835\udeb6 \ud835\udeb7 \ud835\udeb8 \ud835\udeba \ud835\udebb \ud835\udebc \ud835\udebd \ud835\udebe \ud835\udebf \ud835\udec0".split(" ");
-this.smallGreekBold="\ud835\udec2 \ud835\udec3 \ud835\udec4 \ud835\udec5 \ud835\udec6 \ud835\udec7 \ud835\udec8 \ud835\udec9 \ud835\udeca \ud835\udecb \ud835\udecc \ud835\udecd \ud835\udece \ud835\udecf \ud835\uded0 \ud835\uded1 \ud835\uded2 \ud835\uded3 \ud835\uded4 \ud835\uded5 \ud835\uded6 \ud835\uded7 \ud835\uded8 \ud835\uded9 \ud835\udeda".split(" ");this.capitalGreekItalic="\ud835\udee2 \ud835\udee3 \ud835\udee4 \ud835\udee5 \ud835\udee6 \ud835\udee7 \ud835\udee8 \ud835\udee9 \ud835\udeea \ud835\udeeb \ud835\udeec \ud835\udeed \ud835\udeee \ud835\udeef \ud835\udef0 \ud835\udef1 \ud835\udef2 \ud835\udef4 \ud835\udef5 \ud835\udef6 \ud835\udef7 \ud835\udef8 \ud835\udef9 \ud835\udefa".split(" ");
-this.smallGreekItalic="\ud835\udefc \ud835\udefd \ud835\udefe \ud835\udeff \ud835\udf00 \ud835\udf01 \ud835\udf02 \ud835\udf03 \ud835\udf04 \ud835\udf05 \ud835\udf06 \ud835\udf07 \ud835\udf08 \ud835\udf09 \ud835\udf0a \ud835\udf0b \ud835\udf0c \ud835\udf0d \ud835\udf0e \ud835\udf0f \ud835\udf10 \ud835\udf11 \ud835\udf12 \ud835\udf13 \ud835\udf14".split(" ");this.capitalGreekSansSerifBold="\ud835\udf56 \ud835\udf57 \ud835\udf58 \ud835\udf59 \ud835\udf5a \ud835\udf5b \ud835\udf5c \ud835\udf5d \ud835\udf5e \ud835\udf5f \ud835\udf60 \ud835\udf61 \ud835\udf62 \ud835\udf63 \ud835\udf64 \ud835\udf65 \ud835\udf66 \ud835\udf68 \ud835\udf69 \ud835\udf6a \ud835\udf6b \ud835\udf6c \ud835\udf6d \ud835\udf6e".split(" ");
-this.smallGreekSansSerifBold="\ud835\udf70 \ud835\udf71 \ud835\udf72 \ud835\udf73 \ud835\udf74 \ud835\udf75 \ud835\udf76 \ud835\udf77 \ud835\udf78 \ud835\udf79 \ud835\udf7a \ud835\udf7b \ud835\udf7c \ud835\udf7d \ud835\udf7e \ud835\udf7f \ud835\udf80 \ud835\udf81 \ud835\udf82 \ud835\udf83 \ud835\udf84 \ud835\udf85 \ud835\udf86 \ud835\udf87 \ud835\udf88".split(" ");this.greekDoubleStruck=["\u213c","\u213d","\u213e","\u213f"];this.greekSpecial="\u03d0\u03d1\u03d5\u03d6\u03d7\u03f0\u03f1\u03f5\u03f6\u03f4".split("");
-this.greekSpecialBold="\ud835\udedc \ud835\udedd \ud835\udede \ud835\udedf \ud835\udee0 \ud835\udee1".split(" ");this.greekSpecialItalic="\ud835\udf16 \ud835\udf17 \ud835\udf18 \ud835\udf19 \ud835\udf1a \ud835\udf1b".split(" ");this.greekSpecialSansSerifBold="\ud835\udf8a \ud835\udf8b \ud835\udf8c \ud835\udf8d \ud835\udf8e \ud835\udf8f".split(" ");this.hebrewLetters=["\u2135","\u2136","\u2137","\u2138"];this.allLetters=this.capitalLatin.concat(this.smallLatin,this.capitalLatinFullWidth,this.smallLatinFullWidth,
-this.capitalLatinBold,this.smallLatinBold,this.capitalLatinItalic,this.smallLatinItalic,this.capitalLatinScript,this.smallLatinScript,this.capitalLatinBoldScript,this.smallLatinBoldScript,this.capitalLatinFraktur,this.smallLatinFraktur,this.capitalLatinDoubleStruck,this.smallLatinDoubleStruck,this.capitalLatinBoldFraktur,this.smallLatinBoldFraktur,this.capitalLatinSansSerif,this.smallLatinSansSerif,this.capitalLatinSansSerifBold,this.smallLatinSansSerifBold,this.capitalLatinSansSerifItalic,this.smallLatinSansSerifItalic,
-this.capitalLatinMonospace,this.smallLatinMonospace,this.latinDoubleStruckItalic,this.capitalGreek,this.smallGreek,this.capitalGreekBold,this.smallGreekBold,this.capitalGreekItalic,this.smallGreekItalic,this.capitalGreekSansSerifBold,this.smallGreekSansSerifBold,this.greekDoubleStruck,this.greekSpecial,this.greekSpecialBold,this.greekSpecialItalic,this.greekSpecialSansSerifBold,this.hebrewLetters);this.additions="+\u00b1\u2213\u2214\u2227\u2228\u2229\u222a\u228c\u2293\u2294\u229d\u229e\u22a4\u22a5\u22ba\u22bb\u22bc\u22c4\u22ce\u22cf\u22d2\u22d3\u25b3\u25b7\u25bd\u25c1\u2a5e\u2295".split("");
-this.invisiblePlus_=sre.SemanticUtil.numberToUnicode(8292);this.additions.push(this.invisiblePlus_);this.multiplications="\u2020\u2021\u2210\u2217\u2218\u2219\u2240\u229a\u229b\u22a0\u22a1\u22c5\u22c6\u22c7\u22c9\u22ca\u22cb\u22cc\u25cb\u00b7*".split("");this.invisibleTimes_=sre.SemanticUtil.numberToUnicode(8290);this.multiplications.push(this.invisibleTimes_);this.subtractions="-\u2052\u207b\u208b\u2212\u2216\u2238\u2242\u2296\u229f\u2796\u2a29\u2a2a\u2a2b\u2a2c\u2a3a\u2a41\u2a6c\ufe63\uff0d\u2010\u2011".split("");
-this.divisions="/\u00f7\u2044\u2215\u2298\u27cc\u29bc\u2a38".split("");this.functionApplication_=sre.SemanticUtil.numberToUnicode(8289);this.equalities="=~\u207c\u208c\u223c\u223d\u2243\u2245\u2248\u224a\u224b\u224c\u224d\u224e\u2251\u2252\u2253\u2254\u2255\u2256\u2257\u2258\u2259\u225a\u225b\u225c\u225d\u225e\u225f\u2261\u2263\u29e4\u2a66\u2a6e\u2a6f\u2a70\u2a71\u2a72\u2a73\u2a74\u2a75\u2a76\u2a77\u2a78\u22d5\u2a6d\u2a6a\u2a6b\u2a6c\ufe66\uff1d".split("");this.inequalities="<>\u2241\u2242\u2244\u2246\u2247\u2249\u224f\u2250\u2260\u2262\u2264\u2265\u2266\u2267\u2268\u2269\u226a\u226b\u226c\u226d\u226e\u226f\u2270\u2271\u2272\u2273\u2274\u2275\u2276\u2277\u2278\u2279\u227a\u227b\u227c\u227d\u227e\u227f\u2280\u2281\u22d6\u22d7\u22d8\u22d9\u22da\u22db\u22dc\u22dd\u22de\u22df\u22e0\u22e1\u22e2\u22e3\u22e4\u22e5\u22e6\u22e7\u22e8\u22e9\u2a79\u2a7a\u2a7b\u2a7c\u2a7d\u2a7e\u2a7f\u2a80\u2a81\u2a82\u2a83\u2a84\u2a85\u2a86\u2a87\u2a88\u2a89\u2a8a\u2a8b\u2a8c\u2a8d\u2a8e\u2a8f\u2a90\u2a91\u2a92\u2a93\u2a94\u2a95\u2a96\u2a97\u2a98\u2a99\u2a9a\u2a9b\u2a9c\u2a9d\u2a9e\u2a9f\u2aa0\u2aa1\u2aa2\u2aa3\u2aa4\u2aa5\u2aa6\u2aa7\u2aa8\u2aa9\u2aaa\u2aab\u2aac\u2aad\u2aae\u2aaf\u2ab0\u2ab1\u2ab2\u2ab3\u2ab4\u2ab5\u2ab6\u2ab7\u2ab8\u2ab9\u2aba\u2abb\u2abc\u2af7\u2af8\u2af9\u2afa\u29c0\u29c1\ufe64\ufe65\uff1c\uff1e".split("");
-this.relations=[];this.arrows="\u2190\u2191\u2192\u2193\u2194\u2195\u2196\u2197\u2198\u2199\u219a\u219b\u219c\u219d\u219e\u219f\u21a0\u21a1\u21a2\u21a3\u21a4\u21a5\u21a6\u21a7\u21a8\u21a9\u21aa\u21ab\u21ac\u21ad\u21ae\u21af\u21b0\u21b1\u21b2\u21b3\u21b4\u21b5\u21b6\u21b7\u21b8\u21b9\u21ba\u21bb\u21c4\u21c5\u21c6\u21c7\u21c8\u21c9\u21ca\u21cd\u21ce\u21cf\u21d0\u21d1\u21d2\u21d3\u21d4\u21d5\u21d6\u21d7\u21d8\u21d9\u21da\u21db\u21dc\u21dd\u21de\u21df\u21e0\u21e1\u21e2\u21e3\u21e4\u21e5\u21e6\u21e7\u21e8\u21e9\u21ea\u21eb\u21ec\u21ed\u21ee\u21ef\u21f0\u21f1\u21f2\u21f3\u21f4\u21f5\u21f6\u21f7\u21f8\u21f9\u21fa\u21fb\u21fc\u21fd\u21fe\u21ff\u2301\u2303\u2304\u2324\u238b\u2794\u2798\u2799\u279a\u279b\u279c\u279d\u279e\u279f\u27a0\u27a1\u27a2\u27a3\u27a4\u27a5\u27a6\u27a7\u27a8\u27a9\u27aa\u27ab\u27ac\u27ad\u27ae\u27af\u27b1\u27b2\u27b3\u27b4\u27b5\u27b6\u27b7\u27b8\u27b9\u27ba\u27bb\u27bc\u27bd\u27be\u27f0\u27f1\u27f2\u27f3\u27f4\u27f5\u27f6\u27f7\u27f8\u27f9\u27fa\u27fb\u27fc\u27fd\u27fe\u27ff\u2900\u2901\u2902\u2903\u2904\u2905\u2906\u2907\u2908\u2909\u290a\u290b\u290c\u290d\u290e\u290f\u2910\u2911\u2912\u2913\u2914\u2915\u2916\u2917\u2918\u2919\u291a\u291b\u291c\u291d\u291e\u291f\u2920\u2921\u2922\u2923\u2924\u2925\u2926\u2927\u2928\u2929\u292a\u292d\u292e\u292f\u2930\u2931\u2932\u2933\u2934\u2935\u2936\u2937\u2938\u2939\u293a\u293b\u293c\u293d\u293e\u293f\u2940\u2941\u2942\u2943\u2944\u2945\u2946\u2947\u2948\u2949\u2970\u2971\u2972\u2973\u2974\u2975\u2976\u2977\u2978\u2979\u297a\u297b\u29b3\u29b4\u29bd\u29ea\u29ec\u29ed\u2a17\u2b00\u2b01\u2b02\u2b03\u2b04\u2b05\u2b06\u2b07\u2b08\u2b09\u2b0a\u2b0b\u2b0c\u2b0d\u2b0e\u2b0f\u2b10\u2b11\u2b30\u2b31\u2b32\u2b33\u2b34\u2b35\u2b36\u2b37\u2b38\u2b39\u2b3a\u2b3b\u2b3c\u2b3d\u2b3e\u2b3f\u2b40\u2b41\u2b42\u2b43\u2b44\u2b45\u2b46\u2b47\u2b48\u2b49\u2b4a\u2b4b\u2b4c\uffe9\uffea\uffeb\uffec\u21bc\u21bd\u21be\u21bf\u21c0\u21c1\u21c2\u21c3\u21cb\u21cc\u294a\u294b\u294c\u294d\u294e\u294f\u2950\u2951\u2952\u2953\u2954\u2955\u2956\u2957\u2958\u2959\u295a\u295b\u295c\u295d\u295e\u295f\u2960\u2961\u2962\u2963\u2964\u2965\u2966\u2967\u2968\u2969\u296a\u296b\u296c\u296d\u296e\u296f\u297c\u297d\u297e\u297f".split("");
-this.sumOps="\u2140\u220f\u2210\u2211\u22c0\u22c1\u22c2\u22c3\u2a00\u2a01\u2a02\u2a03\u2a04\u2a05\u2a06\u2a07\u2a08\u2a09\u2a0a\u2a0b\u2afc\u2aff".split("");this.intOps="\u222b\u222c\u222d\u222e\u222f\u2230\u2231\u2232\u2233\u2a0c\u2a0d\u2a0e\u2a0f\u2a10\u2a11\u2a12\u2a13\u2a14\u2a15\u2a16\u2a17\u2a18\u2a19\u2a1a\u2a1b\u2a1c".split("");this.prefixOps="\u2200\u2203\u2206\u2207\u2202\u2201\u2204".split("");this.prefixOpsBold=["\ud835\udec1","\ud835\udedb","\ud835\udfca","\ud835\udfcb"];this.prefixOpsItalic=
-["\ud835\udefb","\ud835\udf15"];this.prefixOpsSansSerifBold=["\ud835\udf6f","\ud835\udf89"];this.operatorBits="\u2320\u2321\u23b6\u23aa\u23ae\u23af\u23b2\u23b3\u23b7".split("");this.digitsNormal="0123456789".split("");this.digitsFullWidth="\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19".split("");this.digitsBold="\ud835\udfce \ud835\udfcf \ud835\udfd0 \ud835\udfd1 \ud835\udfd2 \ud835\udfd3 \ud835\udfd4 \ud835\udfd5 \ud835\udfd6 \ud835\udfd7".split(" ");this.digitsDoubleStruck="\ud835\udfd8 \ud835\udfd9 \ud835\udfda \ud835\udfdb \ud835\udfdc \ud835\udfdd \ud835\udfde \ud835\udfdf \ud835\udfe0 \ud835\udfe1".split(" ");
-this.digitsSansSerif="\ud835\udfe2 \ud835\udfe3 \ud835\udfe4 \ud835\udfe5 \ud835\udfe6 \ud835\udfe7 \ud835\udfe8 \ud835\udfe9 \ud835\udfea \ud835\udfeb".split(" ");this.digitsSansSerifBold="\ud835\udfec \ud835\udfed \ud835\udfee \ud835\udfef \ud835\udff0 \ud835\udff1 \ud835\udff2 \ud835\udff3 \ud835\udff4 \ud835\udff5".split(" ");this.digitsMonospace="\ud835\udff6 \ud835\udff7 \ud835\udff8 \ud835\udff9 \ud835\udffa \ud835\udffb \ud835\udffc \ud835\udffd \ud835\udffe \ud835\udfff".split(" ");this.digitsSuperscript=
-"\u00b2\u00b3\u00b9\u2070\u2074\u2075\u2076\u2077\u2078\u2079".split("");this.digitsSubscript="\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089".split("");this.fractions="\u00bc\u00bd\u00be\u2150\u2151\u2152\u2153\u2154\u2155\u2156\u2157\u2158\u2159\u215a\u215b\u215c\u215d\u215e\u215f\u2189".split("");this.enclosedNumbers="\u2460\u2461\u2462\u2463\u2464\u2465\u2466\u2467\u2468\u2469\u246a\u246b\u246c\u246d\u246e\u246f\u2470\u2471\u2472\u2473\u24ea\u24eb\u24ec\u24ed\u24ee\u24ef\u24f0\u24f1\u24f2\u24f3\u24f4\u24f5\u24f6\u24f7\u24f8\u24f9\u24fa\u24fb\u24fc\u24fd\u24fe\u24ff\u2776\u2777\u2778\u2779\u277a\u277b\u277c\u277d\u277e\u277f\u2780\u2781\u2782\u2783\u2784\u2785\u2786\u2787\u2788\u2789\u278a\u278b\u278c\u278d\u278e\u278f\u2790\u2791\u2792\u2793\u3248\u3249\u324a\u324b\u324c\u324d\u324e\u324f\u3251\u3252\u3253\u3254\u3255\u3256\u3257\u3258\u3259\u325a\u325b\u325c\u325d\u325e\u325f\u32b1\u32b2\u32b3\u32b4\u32b5\u32b6\u32b7\u32b8\u32b9\u32ba\u32bb\u32bc\u32bd\u32be\u32bf".split("");
-this.fencedNumbers="\u2474\u2475\u2476\u2477\u2478\u2479\u247a\u247b\u247c\u247d\u247e\u247f\u2480\u2481\u2482\u2483\u2484\u2485\u2486\u2487".split("");this.punctuatedNumbers="\u2488 \u2489 \u248a \u248b \u248c \u248d \u248e \u248f \u2490 \u2491 \u2492 \u2493 \u2494 \u2495 \u2496 \u2497 \u2498 \u2499 \u249a \u249b \ud83c\udd00 \ud83c\udd01 \ud83c\udd02 \ud83c\udd03 \ud83c\udd04 \ud83c\udd05 \ud83c\udd06 \ud83c\udd07 \ud83c\udd08 \ud83c\udd09 \ud83c\udd0a".split(" ");this.digits=this.digitsNormal.concat(this.digitsFullWidth,
-this.digitsBold,this.digitsDoubleStruck,this.digitsSansSerif,this.digitsSansSerifBold,this.digitsMonospace);this.numbers=this.fractions.concat(this.digitsSuperscript,this.digitsSubscript,this.enclosedNumbers,this.fencedNumbers,this.punctuatedNumbers);this.allNumbers=this.digits.concat(this.numbers);this.trigonometricFunctions="cos cot csc sec sin tan arccos arccot arccsc arcsec arcsin arctan".split(" ");this.hyperbolicFunctions="cosh coth csch sech sinh tanh arcosh arcoth arcsch arsech arsinh artanh arccosh arccoth arccsch arcsech arcsinh arctanh".split(" ");
-this.algebraicFunctions="deg det dim hom ker Tr tr".split(" ");this.elementaryFunctions="log ln lg exp expt gcd gcd arg im re Pr".split(" ");this.prefixFunctions=this.trigonometricFunctions.concat(this.hyperbolicFunctions,this.algebraicFunctions,this.elementaryFunctions);this.limitFunctions="inf lim liminf limsup max min sup injlim projlim".split(" ");this.infixFunctions=["mod","rem"];this.symbolSetToSemantic_=[{set:this.generalPunctuations,type:sre.SemanticAttr.Type.PUNCTUATION,role:sre.SemanticAttr.Role.UNKNOWN},
-{set:this.colons,type:sre.SemanticAttr.Type.PUNCTUATION,role:sre.SemanticAttr.Role.COLON},{set:this.commas,type:sre.SemanticAttr.Type.PUNCTUATION,role:sre.SemanticAttr.Role.COMMA},{set:this.ellipses,type:sre.SemanticAttr.Type.PUNCTUATION,role:sre.SemanticAttr.Role.ELLIPSIS},{set:this.fullStops,type:sre.SemanticAttr.Type.PUNCTUATION,role:sre.SemanticAttr.Role.FULLSTOP},{set:this.dashes,type:sre.SemanticAttr.Type.PUNCTUATION,role:sre.SemanticAttr.Role.DASH},{set:this.primes,type:sre.SemanticAttr.Type.PUNCTUATION,
-role:sre.SemanticAttr.Role.PRIME},{set:this.degrees,type:sre.SemanticAttr.Type.PUNCTUATION,role:sre.SemanticAttr.Role.DEGREE},{set:this.leftFences,type:sre.SemanticAttr.Type.FENCE,role:sre.SemanticAttr.Role.OPEN},{set:this.rightFences,type:sre.SemanticAttr.Type.FENCE,role:sre.SemanticAttr.Role.CLOSE},{set:this.topFences,type:sre.SemanticAttr.Type.FENCE,role:sre.SemanticAttr.Role.TOP},{set:this.bottomFences,type:sre.SemanticAttr.Type.FENCE,role:sre.SemanticAttr.Role.BOTTOM},{set:this.neutralFences,
-type:sre.SemanticAttr.Type.FENCE,role:sre.SemanticAttr.Role.NEUTRAL},{set:this.smallLatin,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.NORMAL},{set:this.capitalLatin,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.NORMAL},{set:this.smallLatinFullWidth,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.NORMAL},{set:this.capitalLatinFullWidth,
-type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.NORMAL},{set:this.smallLatinBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.BOLD},{set:this.capitalLatinBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.BOLD},{set:this.smallLatinItalic,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.ITALIC},
-{set:this.capitalLatinItalic,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.ITALIC},{set:this.smallLatinScript,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.SCRIPT},{set:this.capitalLatinScript,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.SCRIPT},{set:this.smallLatinBoldScript,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,
-font:sre.SemanticAttr.Font.BOLDSCRIPT},{set:this.capitalLatinBoldScript,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.BOLDSCRIPT},{set:this.smallLatinFraktur,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.FRAKTUR},{set:this.capitalLatinFraktur,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.FRAKTUR},{set:this.smallLatinDoubleStruck,
-type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.DOUBLESTRUCK},{set:this.capitalLatinDoubleStruck,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.DOUBLESTRUCK},{set:this.smallLatinBoldFraktur,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.BOLDFRAKTUR},{set:this.capitalLatinBoldFraktur,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,
-font:sre.SemanticAttr.Font.BOLDFRAKTUR},{set:this.smallLatinSansSerif,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.SANSSERIF},{set:this.capitalLatinSansSerif,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.SANSSERIF},{set:this.smallLatinSansSerifBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.SANSSERIFBOLD},{set:this.capitalLatinSansSerifBold,
-type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.SANSSERIFBOLD},{set:this.smallLatinSansSerifItalic,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.SANSSERIFITALIC},{set:this.capitalLatinSansSerifItalic,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.SANSSERIFITALIC},{set:this.smallLatinMonospace,type:sre.SemanticAttr.Type.IDENTIFIER,
-role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.MONOSPACE},{set:this.capitalLatinMonospace,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.MONOSPACE},{set:this.latinDoubleStruckItalic,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.LATINLETTER,font:sre.SemanticAttr.Font.DOUBLESTRUCKITALIC},{set:this.smallGreek,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.NORMAL},
-{set:this.capitalGreek,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.NORMAL},{set:this.smallGreekBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.BOLD},{set:this.capitalGreekBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.BOLD},{set:this.smallGreekItalic,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,
-font:sre.SemanticAttr.Font.ITALIC},{set:this.capitalGreekItalic,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.ITALIC},{set:this.smallGreekSansSerifBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.SANSSERIFBOLD},{set:this.capitalGreekSansSerifBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.SANSSERIFBOLD},{set:this.greekDoubleStruck,
-type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.DOUBLESTRUCK},{set:this.greekSpecial,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.NORMAL},{set:this.greekSpecialBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.BOLD},{set:this.greekSpecialItalic,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.ITALIC},
-{set:this.greekSpecialSansSerifBold,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.GREEKLETTER,font:sre.SemanticAttr.Font.SANSSERIFBOLD},{set:this.hebrewLetters,type:sre.SemanticAttr.Type.IDENTIFIER,role:sre.SemanticAttr.Role.OTHERLETTER,font:sre.SemanticAttr.Font.NORMAL},{set:this.digitsNormal,type:sre.SemanticAttr.Type.NUMBER,role:sre.SemanticAttr.Role.INTEGER,font:sre.SemanticAttr.Font.NORMAL},{set:this.digitsFullWidth,type:sre.SemanticAttr.Type.NUMBER,role:sre.SemanticAttr.Role.INTEGER,
-font:sre.SemanticAttr.Font.NORMAL},{set:this.digitsBold,type:sre.SemanticAttr.Type.NUMBER,role:sre.SemanticAttr.Role.INTEGER,font:sre.SemanticAttr.Font.BOLD},{set:this.digitsDoubleStruck,type:sre.SemanticAttr.Type.NUMBER,role:sre.SemanticAttr.Role.INTEGER,font:sre.SemanticAttr.Font.DOUBLESTRUCK},{set:this.digitsSansSerif,type:sre.SemanticAttr.Type.NUMBER,role:sre.SemanticAttr.Role.INTEGER,font:sre.SemanticAttr.Font.SANSSERIF},{set:this.digitsSansSerifBold,type:sre.SemanticAttr.Type.NUMBER,role:sre.SemanticAttr.Role.INTEGER,
-font:sre.SemanticAttr.Font.SANSSERIFBOLD},{set:this.digitsMonospace,type:sre.SemanticAttr.Type.NUMBER,role:sre.SemanticAttr.Role.INTEGER,font:sre.SemanticAttr.Font.MONOSPACE},{set:this.numbers,type:sre.SemanticAttr.Type.NUMBER,role:sre.SemanticAttr.Role.FLOAT},{set:this.additions,type:sre.SemanticAttr.Type.OPERATOR,role:sre.SemanticAttr.Role.ADDITION},{set:this.multiplications,type:sre.SemanticAttr.Type.OPERATOR,role:sre.SemanticAttr.Role.MULTIPLICATION},{set:this.subtractions,type:sre.SemanticAttr.Type.OPERATOR,
-role:sre.SemanticAttr.Role.SUBTRACTION},{set:this.divisions,type:sre.SemanticAttr.Type.OPERATOR,role:sre.SemanticAttr.Role.DIVISION},{set:this.prefixOps,type:sre.SemanticAttr.Type.PREFIXOP,role:sre.SemanticAttr.Role.PREFIXFUNC},{set:this.prefixOpsBold,type:sre.SemanticAttr.Type.PREFIXOP,role:sre.SemanticAttr.Role.PREFIXFUNC,font:sre.SemanticAttr.Font.BOLD},{set:this.prefixOpsItalic,type:sre.SemanticAttr.Type.PREFIXOP,role:sre.SemanticAttr.Role.PREFIXFUNC,font:sre.SemanticAttr.Font.ITALIC},{set:this.prefixOpsSansSerifBold,
-type:sre.SemanticAttr.Type.PREFIXOP,role:sre.SemanticAttr.Role.PREFIXFUNC,font:sre.SemanticAttr.Font.SANSSERIFBOLD},{set:this.equalities,type:sre.SemanticAttr.Type.RELATION,role:sre.SemanticAttr.Role.EQUALITY},{set:this.inequalities,type:sre.SemanticAttr.Type.RELATION,role:sre.SemanticAttr.Role.INEQUALITY},{set:this.relations,type:sre.SemanticAttr.Type.RELATION,role:sre.SemanticAttr.Role.UNKNOWN},{set:this.arrows,type:sre.SemanticAttr.Type.RELATION,role:sre.SemanticAttr.Role.ARROW},{set:this.sumOps,
-type:sre.SemanticAttr.Type.LARGEOP,role:sre.SemanticAttr.Role.SUM},{set:this.intOps,type:sre.SemanticAttr.Type.LARGEOP,role:sre.SemanticAttr.Role.INTEGRAL},{set:this.limitFunctions,type:sre.SemanticAttr.Type.FUNCTION,role:sre.SemanticAttr.Role.LIMFUNC},{set:this.prefixFunctions,type:sre.SemanticAttr.Type.FUNCTION,role:sre.SemanticAttr.Role.PREFIXFUNC},{set:this.infixFunctions,type:sre.SemanticAttr.Type.OPERATOR,role:sre.SemanticAttr.Role.MULTIPLICATION}];this.meaning_=this.initMeaning_()};goog.addSingletonGetter(sre.SemanticAttr);
-sre.SemanticAttr.Type={PUNCTUATION:"punctuation",FENCE:"fence",NUMBER:"number",IDENTIFIER:"identifier",TEXT:"text",OPERATOR:"operator",RELATION:"relation",LARGEOP:"largeop",FUNCTION:"function",ACCENT:"accent",FENCED:"fenced",FRACTION:"fraction",PUNCTUATED:"punctuated",RELSEQ:"relseq",MULTIREL:"multirel",INFIXOP:"infixop",PREFIXOP:"prefixop",POSTFIXOP:"postfixop",APPL:"appl",INTEGRAL:"integral",BIGOP:"bigop",SQRT:"sqrt",ROOT:"root",LIMUPPER:"limupper",LIMLOWER:"limlower",LIMBOTH:"limboth",SUBSCRIPT:"subscript",
-SUPERSCRIPT:"superscript",UNDERSCORE:"underscore",OVERSCORE:"overscore",TENSOR:"tensor",TABLE:"table",MULTILINE:"multiline",MATRIX:"matrix",VECTOR:"vector",CASES:"cases",ROW:"row",LINE:"line",CELL:"cell",ENCLOSE:"enclose",UNKNOWN:"unknown",EMPTY:"empty"};
-sre.SemanticAttr.Role={COMMA:"comma",ELLIPSIS:"ellipsis",FULLSTOP:"fullstop",DASH:"dash",PRIME:"prime",DEGREE:"degree",VBAR:"vbar",COLON:"colon",OPENFENCE:"openfence",CLOSEFENCE:"closefence",APPLICATION:"application",DUMMY:"dummy",UNIT:"unit",LABEL:"label",OPEN:"open",CLOSE:"close",TOP:"top",BOTTOM:"bottom",NEUTRAL:"neutral",LATINLETTER:"latinletter",GREEKLETTER:"greekletter",OTHERLETTER:"otherletter",INTEGER:"integer",FLOAT:"float",OTHERNUMBER:"othernumber",MIXED:"mixed",MULTIACCENT:"multiaccent",
-OVERACCENT:"overaccent",UNDERACCENT:"underaccent",UNDEROVER:"underover",SUBSUP:"subsup",LEFTSUB:"leftsub",LEFTSUPER:"leftsuper",RIGHTSUB:"rightsub",RIGHTSUPER:"rightsuper",LEFTRIGHT:"leftright",ABOVEBELOW:"abovebelow",SETEMPTY:"set empty",SETEXT:"set extended",SETSINGLE:"set singleton",SETCOLLECT:"set collection",STRING:"string",SEQUENCE:"sequence",ENDPUNCT:"endpunct",STARTPUNCT:"startpunct",TEXT:"text",NEGATIVE:"negative",POSITIVE:"positive",NEGATION:"negation",MULTIOP:"multiop",LIMFUNC:"limit function",
-INFIXFUNC:"infix function",PREFIXFUNC:"prefix function",POSTFIXFUNC:"postfix function",SIMPLEFUNC:"simple function",COMPFUNC:"composed function",SUM:"sum",INTEGRAL:"integral",ADDITION:"addition",MULTIPLICATION:"multiplication",SUBTRACTION:"subtraction",IMPLICIT:"implicit",DIVISION:"division",VULGAR:"vulgar",EQUALITY:"equality",INEQUALITY:"inequality",ELEMENT:"element",ARROW:"arrow",DETERMINANT:"determinant",ROWVECTOR:"rowvector",BINOMIAL:"binomial",SQUAREMATRIX:"squarematrix",MULTILINE:"multiline",
-MATRIX:"matrix",VECTOR:"vector",CASES:"cases",TABLE:"table",UNKNOWN:"unknown",PROTECTED:"protected"};
-sre.SemanticAttr.Font={BOLD:"bold",BOLDFRAKTUR:"bold-fraktur",BOLDITALIC:"bold-italic",BOLDSCRIPT:"bold-script",CALIGRAPHIC:"caligraphic",CALIGRAPHICBOLD:"caligraphic-bold",DOUBLESTRUCK:"double-struck",DOUBLESTRUCKITALIC:"double-struck-italic",FRAKTUR:"fraktur",ITALIC:"italic",MONOSPACE:"monospace",NORMAL:"normal",OLDSTYLE:"oldstyle",OLDSTYLEBOLD:"oldstyle-bold",SCRIPT:"script",SANSSERIF:"sans-serif",SANSSERIFITALIC:"sans-serif-italic",SANSSERIFBOLD:"sans-serif-bold",SANSSERIFBOLDITALIC:"sans-serif-bold-italic",
-UNKNOWN:"unknown"};sre.SemanticAttr.equal=function(a,b){return a.type===b.type&&a.role===b.role&&a.font===b.font};sre.SemanticAttr.prototype.lookupType=function(a){return sre.SemanticAttr.Type.UNKNOWN};sre.SemanticAttr.prototype.lookupRole=function(a){return sre.SemanticAttr.Role.UNKNOWN};sre.SemanticAttr.lookupMeaning=function(a){return sre.SemanticAttr.getInstance().lookupMeaning_(a)};sre.SemanticAttr.invisibleTimes=function(){return sre.SemanticAttr.getInstance().invisibleTimes_};
-sre.SemanticAttr.invisibleComma=function(){return sre.SemanticAttr.getInstance().invisibleComma_};sre.SemanticAttr.functionApplication=function(){return sre.SemanticAttr.getInstance().functionApplication_};sre.SemanticAttr.isMatchingFenceRole=function(a,b){return a==sre.SemanticAttr.Role.OPEN&&b==sre.SemanticAttr.Role.CLOSE||a==sre.SemanticAttr.Role.NEUTRAL&&b==sre.SemanticAttr.Role.NEUTRAL||a==sre.SemanticAttr.Role.TOP&&b==sre.SemanticAttr.Role.BOTTOM};
-sre.SemanticAttr.isMatchingFence=function(a,b){return sre.SemanticAttr.getInstance().isMatchingFence_(a,b)};sre.SemanticAttr.isOpeningFence=function(a){return a==sre.SemanticAttr.Role.OPEN||a==sre.SemanticAttr.Role.NEUTRAL};sre.SemanticAttr.isClosingFence=function(a){return a==sre.SemanticAttr.Role.CLOSE||a==sre.SemanticAttr.Role.NEUTRAL};
-sre.SemanticAttr.isEmbellishedType=function(a){return a===sre.SemanticAttr.Type.OPERATOR||a===sre.SemanticAttr.Type.RELATION||a===sre.SemanticAttr.Type.FENCE||a===sre.SemanticAttr.Type.PUNCTUATION};sre.SemanticAttr.isCharacterD=function(a){return-1!="d \u2146 \uff44 \ud835\udc1d \ud835\udc51 \ud835\udcb9 \ud835\udced \ud835\udd21 \ud835\udd55 \ud835\udd89 \ud835\uddbd \ud835\uddf1 \ud835\ude25 \ud835\ude8d".split(" ").indexOf(a)};
-sre.SemanticAttr.prototype.isMatchingFence_=function(a,b){return-1!=this.neutralFences.indexOf(a)?a==b:this.openClosePairs[a]==b||this.topBottomPairs[a]==b};sre.SemanticAttr.prototype.initMeaning_=function(){for(var a={},b=0,c;c=this.symbolSetToSemantic_[b];b++)c.set.forEach(function(b){a[b]={role:c.role||sre.SemanticAttr.Role.UNKNOWN,type:c.type||sre.SemanticAttr.Type.UNKNOWN,font:c.font||sre.SemanticAttr.Font.UNKNOWN}});return a};
-sre.SemanticAttr.prototype.lookupMeaning_=function(a){return this.meaning_[a]||{role:sre.SemanticAttr.Role.UNKNOWN,type:sre.SemanticAttr.Type.UNKNOWN,font:sre.SemanticAttr.Font.UNKNOWN}};sre.MathUtil={};sre.MathUtil.isMathmlNodeOfClass_=function(a,b){return-1!=b.indexOf(a.tagName.toUpperCase())};sre.MathUtil.isMathjaxNodeOfClass_=function(a,b){return"SPAN"==a.tagName?a.className.split(" ").some(function(a){return-1!=b.indexOf(a.toUpperCase())}):!1};sre.MathUtil.isMathNodeOfClass_=function(a,b){return a.nodeType==sre.DomUtil.NodeType.ELEMENT_NODE&&(sre.MathUtil.isMathmlNodeOfClass_(a,b)||sre.MathUtil.isMathjaxNodeOfClass_(a,b))};sre.MathUtil.TOKEN_LIST="MI MN MO MTEXT MSPACE MS".split(" ");
-sre.MathUtil.isToken=function(a){return sre.MathUtil.isMathNodeOfClass_(a,sre.MathUtil.TOKEN_LIST)};sre.MathUtil.LAYOUT_LIST="MROW MFRAC MSQRT MROOT MSTYLE MERROR MPADDED MPHANTOM MFENCED MENCLOSE".split(" ");sre.MathUtil.isLayout=function(a){return sre.MathUtil.isMathNodeOfClass_(a,sre.MathUtil.LAYOUT_LIST)};sre.MathUtil.SCRIPT_LIST="MSUB MSUP MSUBSUP MUNDER MOVER MUNDEROVER MMULTISCRIPTS MPRESCRIPTS".split(" ");sre.MathUtil.isScript=function(a){return sre.MathUtil.isMathNodeOfClass_(a,sre.MathUtil.SCRIPT_LIST)};
-sre.MathUtil.TABLES_LIST="MTABLE MLABELEDTR MTR MTD MALIGNGROUP MALIGNMARK".split(" ");sre.MathUtil.isTables=function(a){return sre.MathUtil.isMathNodeOfClass_(a,sre.MathUtil.TABLES_LIST)};sre.MathUtil.ELEMENTARY_LIST="MSTACK MLONGDIV MSGROUP MSROW MSCARRIES MSCARRY MSLINE".split(" ");sre.MathUtil.isElementary=function(a){return sre.MathUtil.isMathNodeOfClass_(a,sre.MathUtil.ELEMENTARY_LIST)};
-sre.MathUtil.MATHML_TAG_LIST=[sre.MathUtil.TOKEN_LIST,sre.MathUtil.LAYOUT_LIST,sre.MathUtil.SCRIPT_LIST,sre.MathUtil.TABLES_LIST,sre.MathUtil.ELEMENTARY_LIST].reduce(function(a,b){return a.concat(b)});sre.MathUtil.isMathmlTag=function(a){return sre.MathUtil.isMathNodeOfClass_(a,sre.MathUtil.MATHML_TAG_LIST)};sre.MathUtil.WHITESPACE_LIST=["MSROW","MROW","MSPACE","MPHANTOM","MPADDED"];sre.MathUtil.isWhitespace=function(a){return sre.MathUtil.isMathNodeOfClass_(a,sre.MathUtil.WHITESPACE_LIST)};
-sre.MathUtil.isNotWhitespace=function(a){return sre.MathUtil.isMathmlTag(a)&&!sre.MathUtil.isWhitespace(a)};sre.MathUtil.nextSeparatorFunction=function(a){if(a){if(a.match(/^\s+$/))return null;var b=a.replace(/\s/g,"").split("").filter(function(a){return a})}else b=[","];return function(){return 1<b.length?b.shift():b[0]}};sre.SemanticNode=function(a){this.id=a;this.mathml=[];this.parent=null;this.type=sre.SemanticAttr.Type.UNKNOWN;this.role=sre.SemanticAttr.Role.UNKNOWN;this.font=sre.SemanticAttr.Font.UNKNOWN;this.embellished=null;this.fencePointer="";this.childNodes=[];this.textContent="";this.mathmlTree=null;this.contentNodes=[];this.annotation={}};sre.SemanticNode.prototype.querySelectorAll=function(a){for(var b=[],c=0,d;d=this.childNodes[c];c++)b=b.concat(d.querySelectorAll(a));a(this)&&b.unshift(this);return b};
-sre.SemanticNode.Attribute={EMBELLISHED:"embellished",FENCEPOINTER:"fencepointer",FONT:"font",ID:"id",ANNOTATION:"annotation",ROLE:"role",TYPE:"type",CHILDREN:"children",CONTENT:"content",TEXT:"$t"};
-sre.SemanticNode.prototype.xml=function(a,b){var c=function(c,d){for(var e=d.map(function(c){return c.xml(a,b)}),f=a.createElementNS("",c),k=0,l;l=e[k];k++)f.appendChild(l);return f},d=a.createElementNS("",this.type);b||this.xmlAttributes_(d);d.textContent=this.textContent;0<this.contentNodes.length&&d.appendChild(c(sre.SemanticNode.Attribute.CONTENT,this.contentNodes));0<this.childNodes.length&&d.appendChild(c(sre.SemanticNode.Attribute.CHILDREN,this.childNodes));return d};
-sre.SemanticNode.prototype.toString=function(a){var b=new sre.SystemExternal.xmldom.XMLSerializer,c=(new sre.SystemExternal.xmldom.DOMParser).parseFromString("<snode/>","text/xml");return b.serializeToString(this.xml(c,a))};sre.SemanticNode.prototype.xmlAttributes_=function(a){for(var b=this.attributes(),c=0,d;d=b[c];c++)a.setAttribute(d[0],d[1])};
-sre.SemanticNode.prototype.attributes=function(){var a=[];a.push([sre.SemanticNode.Attribute.ROLE,this.role]);this.font!=sre.SemanticAttr.Font.UNKNOWN&&a.push([sre.SemanticNode.Attribute.FONT,this.font]);Object.keys(this.annotation).length&&a.push([sre.SemanticNode.Attribute.ANNOTATION,this.xmlAnnotation()]);this.embellished&&a.push([sre.SemanticNode.Attribute.EMBELLISHED,this.embellished]);this.fencePointer&&a.push([sre.SemanticNode.Attribute.FENCEPOINTER,this.fencePointer]);a.push([sre.SemanticNode.Attribute.ID,
-this.id]);return a};sre.SemanticNode.prototype.xmlAnnotation=function(){var a=[],b;for(b in this.annotation)this.annotation[b].forEach(function(c){a.push(b+":"+c)});return a.join(";")};
-sre.SemanticNode.prototype.toJson=function(){var a={};a[sre.SemanticNode.Attribute.TYPE]=this.type;for(var b=this.attributes(),c=0,d;d=b[c];c++)a[d[0]]=d[1].toString();this.textContent&&(a[sre.SemanticNode.Attribute.TEXT]=this.textContent);this.childNodes.length&&(a[sre.SemanticNode.Attribute.CHILDREN]=this.childNodes.map(function(a){return a.toJson()}));this.contentNodes.length&&(a[sre.SemanticNode.Attribute.CONTENT]=this.contentNodes.map(function(a){return a.toJson()}));return a};
-sre.SemanticNode.prototype.updateContent=function(a){var b=a.trim();a=a&&!b?a:b;this.textContent!=a&&(b=sre.SemanticAttr.lookupMeaning(a),this.textContent=a,this.role=b.role,this.type=b.type,this.font=b.font)};sre.SemanticNode.prototype.addMathmlNodes=function(a){for(var b=0,c;c=a[b];b++)-1==this.mathml.indexOf(c)&&this.mathml.push(c)};sre.SemanticNode.prototype.removeMathmlNodes_=function(a){for(var b=this.mathml,c=0,d;d=a[c];c++)d=b.indexOf(d),-1!=d&&b.splice(d,1);this.mathml=b};
-sre.SemanticNode.prototype.appendChild=function(a){this.childNodes.push(a);this.addMathmlNodes(a.mathml);a.parent=this};sre.SemanticNode.prototype.replaceChild=function(a,b){var c=this.childNodes.indexOf(a);if(-1!=c){a.parent=null;b.parent=this;this.childNodes[c]=b;var c=a.mathml.filter(function(a){return-1==b.mathml.indexOf(a)}),d=b.mathml.filter(function(b){return-1==a.mathml.indexOf(b)});this.removeMathmlNodes_(c);this.addMathmlNodes(d)}};
-sre.SemanticNode.prototype.appendContentNode=function(a){a&&(this.contentNodes.push(a),this.addMathmlNodes(a.mathml),a.parent=this)};sre.SemanticNode.prototype.removeContentNode=function(a){a&&(a=this.contentNodes.indexOf(a),-1!=a&&this.contentNodes.slice(a,1))};
-sre.SemanticNode.prototype.equals=function(a){if(!a||this.type!==a.type||this.role!==a.role||this.textContent!==a.textContent||this.childNodes.length!==a.childNodes.length||this.contentNodes.length!==a.contentNodes.length)return!1;for(var b=0,c,d;c=this.childNodes[b],d=a.childNodes[b];b++)if(!c.equals(d))return!1;for(b=0;c=this.contentNodes[b],d=a.contentNodes[b];b++)if(!c.equals(d))return!1;return!0};
-sre.SemanticNode.prototype.displayTree=function(a){a++;var b=Array(a).join(" ");console.log(b+this.toString());console.log(b+"MathmlTree:");console.log(b+this.mathmlTreeString_());console.log(b+"MathML:");for(var c=0,d;d=this.mathml[c];c++)console.log(b+d.toString());console.log(b+"Begin Content");this.contentNodes.forEach(function(b){b.displayTree(a)});console.log(b+"End Content");console.log(b+"Begin Children");this.childNodes.forEach(function(b){b.displayTree(a)});console.log(b+"End Children")};
-sre.SemanticNode.prototype.mathmlTreeString_=function(){return this.mathmlTree?this.mathmlTree.toString():"EMPTY"};sre.SemanticNode.prototype.addAnnotation=function(a,b){b&&this.addAnnotation_(a,b)};sre.SemanticNode.prototype.addAnnotation_=function(a,b){var c=this.annotation[a];c?c.push(b):this.annotation[a]=[b]};sre.SemanticNode.prototype.getAnnotation=function(a){return(a=this.annotation[a])?a:[]};
-sre.SemanticNode.prototype.hasAnnotation=function(a,b){var c=this.annotation[a];return c?-1!==c.indexOf(b):!1};sre.SemanticNode.prototype.parseAnnotation=function(a){a=a.split(";");for(var b=0,c=a.length;b<c;b++){var d=a[b].split(":");this.addAnnotation(d[0],d[1])}};sre.SemanticAnnotator=function(a,b){this.domain=a;this.func=b;this.name=a};sre.SemanticAnnotator.prototype.annotate=function(a){a.childNodes.forEach(goog.bind(this.annotate,this));a.addAnnotation(this.domain,this.func(a))};sre.SemanticAnnotations=function(){this.annotators={};this.counter=0};goog.addSingletonGetter(sre.SemanticAnnotations);sre.SemanticAnnotations.prototype.register=function(a){a.name=a.domain+this.counter++;this.annotators[a.name]=a};sre.SemanticAnnotations.prototype.unregister=function(a){delete this.annotators[a]};sre.SemanticAnnotations.prototype.annotate=function(a){for(var b in this.annotators)this.annotators[b].annotate(a)};sre.SemanticDefault=function(){this.map_={}};sre.SemanticDefault.prototype.add=function(a,b){this.map_[sre.SemanticDefault.key_(a,b.font)]=b};sre.SemanticDefault.prototype.addNode=function(a){this.add(a.textContent,{type:a.type,role:a.role,font:a.font})};sre.SemanticDefault.prototype.retrieve=function(a,b){return this.map_[sre.SemanticDefault.key_(a,b)]};sre.SemanticDefault.prototype.retrieveNode=function(a){return this.retrieve(a.textContent,a.font)};
-sre.SemanticDefault.key_=function(a,b){return b?a+":"+b:a};sre.SemanticCollator_=function(){this.map_={}};sre.SemanticCollator_.prototype.add=function(a,b){var c=sre.SemanticDefault.key_(a,b.font),d=this.map_[c];d?d.push(b):this.map_[c]=[b]};sre.SemanticCollator_.prototype.addNode=function(a){this.add(a.textContent,a)};sre.SemanticCollator_.prototype.retrieve=function(a,b){return this.map_[sre.SemanticDefault.key_(a,b)]};
-sre.SemanticCollator_.prototype.retrieveNode=function(a){return this.retrieve(a.textContent,a.font)};sre.SemanticCollator_.prototype.minimize=function(){for(var a in this.map_)1===this.map_[a].length&&delete this.map_[a]};sre.SemanticCollator_.prototype.isMultiValued=function(){for(var a in this.map_)if(1<this.map_[a].length)return!0;return!1};sre.SemanticCollator_.prototype.isEmpty=function(){return!Object.keys(this.map_).length};sre.SemanticNodeCollator=function(){sre.SemanticCollator_.call(this)};
-goog.inherits(sre.SemanticNodeCollator,sre.SemanticCollator_);sre.SemanticNodeCollator.prototype.toString=function(){var a=[],b;for(b in this.map_){for(var c=Array(b.length+3).join(" "),d=this.map_[b],e=[],f=0,g;g=d[f];f++)e.push(g.toString());a.push(b+": "+e.join("\n"+c))}return a.join("\n")};sre.SemanticNodeCollator.prototype.collateMeaning=function(){var a=new sre.SemanticMeaningCollator,b;for(b in this.map_)this.map_[b].forEach(goog.bind(a.addNode,a));return a};sre.SemanticMeaningCollator=function(){sre.SemanticCollator_.call(this)};
-goog.inherits(sre.SemanticMeaningCollator,sre.SemanticCollator_);sre.SemanticMeaningCollator.prototype.add=function(a,b){var c=this.retrieve(a,b.font);c&&c.find(function(a){return sre.SemanticAttr.equal(a,b)})||sre.SemanticMeaningCollator.superClass_.add.call(this,a,b)};sre.SemanticMeaningCollator.prototype.addNode=function(a){this.add(a.textContent,{type:a.type,role:a.role,font:a.font})};
-sre.SemanticMeaningCollator.prototype.toString=function(){var a=[],b;for(b in this.map_){for(var c=Array(b.length+3).join(" "),d=this.map_[b],e=[],f=0,g;g=d[f];f++)e.push("{type: "+g.type+", role: "+g.role+", font: "+g.font+"}");a.push(b+": "+e.join("\n"+c))}return a.join("\n")};sre.SemanticNodeFactory=function(){this.idCounter_=0;this.leafMap=new sre.SemanticNodeCollator};sre.SemanticNodeFactory.prototype.createNode_=function(){return new sre.SemanticNode(this.idCounter_++)};sre.SemanticNodeFactory.prototype.makeUnprocessed=function(a){var b=this.createNode_();b.mathml=[a];return b};sre.SemanticNodeFactory.prototype.makeEmptyNode=function(){var a=this.createNode_();a.type=sre.SemanticAttr.Type.EMPTY;return a};
-sre.SemanticNodeFactory.prototype.makeContentNode=function(a){var b=this.createNode_();b.updateContent(a);return b};sre.SemanticNodeFactory.prototype.makeMultipleContentNodes=function(a,b){for(var c=[],d=0;d<a;d++)c.push(this.makeContentNode(b));return c};sre.SemanticNodeFactory.prototype.makeLeafNode=function(a,b){if(!a)return this.makeEmptyNode();var c=this.makeContentNode(a);c.font=b||c.font;this.leafMap.addNode(c);return c};
-sre.SemanticNodeFactory.prototype.makeBranchNode=function(a,b,c,d){var e=this.createNode_();d&&e.updateContent(d);e.type=a;e.childNodes=b;e.contentNodes=c;b.concat(c).forEach(function(a){a.parent=e;e.addMathmlNodes(a.mathml)});return e};sre.SemanticParser=function(){};sre.SemanticParser.prototype.parse=function(a){};sre.SemanticParser.prototype.getFactory=function(){};sre.SemanticParser.prototype.setFactory=function(a){};sre.SemanticParser.prototype.getType=function(){};sre.SemanticAbstractParser=function(a){this.type_=a;this.factory_=new sre.SemanticNodeFactory};sre.SemanticAbstractParser.prototype.getFactory=function(){return this.factory_};sre.SemanticAbstractParser.prototype.setFactory=function(a){this.factory_=a};
-sre.SemanticAbstractParser.prototype.getType=function(){return this.type_};sre.SemanticAbstractParser.prototype.parse=goog.abstractMethod;sre.SemanticPred={};sre.SemanticPred.isAttribute=function(a,b){return function(c){c=c[a];var d;a:switch(a){case "role":d=sre.SemanticAttr.Role[b];break a;case "font":d=sre.SemanticAttr.Font[b];break a;default:d=sre.SemanticAttr.Type[b]}return c===d}};
-sre.SemanticPred.isAccent=function(a){return sre.SemanticPred.isAttribute("type","FENCE")(a)||sre.SemanticPred.isAttribute("type","PUNCTUATION")(a)||sre.SemanticPred.isAttribute("type","OPERATOR")(a)||sre.SemanticPred.isAttribute("type","RELATION")(a)||sre.SemanticPred.isAttribute("type","IDENTIFIER")(a)&&sre.SemanticPred.isAttribute("role","UNKNOWN")(a)&&!a.textContent.match(new RegExp(sre.SemanticAttr.getInstance().allLetters.join("|")))};
-sre.SemanticPred.isSimpleFunctionScope=function(a){a=a.childNodes;if(0===a.length)return!0;if(1<a.length)return!1;a=a[0];return a.type!==sre.SemanticAttr.Type.INFIXOP||a.role===sre.SemanticAttr.Role.IMPLICIT&&!a.childNodes.some(sre.SemanticPred.isAttribute("type","INFIXOP"))?!0:!1};sre.SemanticPred.isPrefixFunctionBoundary=function(a){return sre.SemanticPred.isOperator(a)||sre.SemanticPred.isAttribute("type","APPL")(a)||sre.SemanticPred.isGeneralFunctionBoundary(a)};
-sre.SemanticPred.isBigOpBoundary=function(a){return sre.SemanticPred.isOperator(a)||sre.SemanticPred.isGeneralFunctionBoundary(a)};sre.SemanticPred.isIntegralDxBoundary=function(a,b){return!!b&&sre.SemanticPred.isAttribute("type","IDENTIFIER")(b)&&sre.SemanticAttr.isCharacterD(a.textContent)};sre.SemanticPred.isIntegralDxBoundarySingle=function(a){if(sre.SemanticPred.isAttribute("type","IDENTIFIER")(a)){var b=a.textContent[0];return b&&a.textContent[1]&&sre.SemanticAttr.isCharacterD(b)}return!1};
-sre.SemanticPred.isGeneralFunctionBoundary=function(a){return sre.SemanticPred.isRelation(a)||sre.SemanticPred.isPunctuation(a)};sre.SemanticPred.isEmbellished=function(a){return a.embellished?a.embellished:sre.SemanticAttr.isEmbellishedType(a.type)?a.type:null};sre.SemanticPred.isOperator=function(a){return sre.SemanticPred.isAttribute("type","OPERATOR")(a)||sre.SemanticPred.isAttribute("embellished","OPERATOR")(a)};
-sre.SemanticPred.isRelation=function(a){return sre.SemanticPred.isAttribute("type","RELATION")(a)||sre.SemanticPred.isAttribute("embellished","RELATION")(a)};sre.SemanticPred.isPunctuation=function(a){return sre.SemanticPred.isAttribute("type","PUNCTUATION")(a)||sre.SemanticPred.isAttribute("embellished","PUNCTUATION")(a)};sre.SemanticPred.isFence=function(a){return sre.SemanticPred.isAttribute("type","FENCE")(a)||sre.SemanticPred.isAttribute("embellished","FENCE")(a)};
-sre.SemanticPred.isElligibleEmbellishedFence=function(a){if(!a||!sre.SemanticPred.isFence(a))return!1;if(!a.embellished)return!0;var b=function(a){return a.embellished?!(!sre.SemanticPred.isAttribute("type","TENSOR")(a)||sre.SemanticPred.isAttribute("type","EMPTY")(a.childNodes[1])&&sre.SemanticPred.isAttribute("type","EMPTY")(a.childNodes[2])||sre.SemanticPred.isAttribute("type","EMPTY")(a.childNodes[3])&&sre.SemanticPred.isAttribute("type","EMPTY")(a.childNodes[4]))||sre.SemanticPred.isAttribute("role",
-"CLOSE")(a)&&sre.SemanticPred.isAttribute("type","TENSOR")(a)||sre.SemanticPred.isAttribute("role","OPEN")(a)&&(sre.SemanticPred.isAttribute("type","SUBSCRIPT")(a)||sre.SemanticPred.isAttribute("type","SUPERSCRIPT")(a))?!1:b(a.childNodes[0]):!0};return b(a)};sre.SemanticPred.isTableOrMultiline=function(a){return!!a&&(sre.SemanticPred.isAttribute("type","TABLE")(a)||sre.SemanticPred.isAttribute("type","MULTILINE")(a))};
-sre.SemanticPred.tableIsMatrixOrVector=function(a){return!!a&&sre.SemanticPred.isFencedElement(a)&&sre.SemanticPred.isTableOrMultiline(a.childNodes[0])};sre.SemanticPred.isFencedElement=function(a){return!!a&&sre.SemanticPred.isAttribute("type","FENCED")(a)&&(sre.SemanticPred.isAttribute("role","LEFTRIGHT")(a)||sre.SemanticPred.isAttribute("role","NEUTRAL")(a))&&1===a.childNodes.length};
-sre.SemanticPred.tableIsCases=function(a,b){return 0<b.length&&sre.SemanticPred.isAttribute("role","OPENFENCE")(b[b.length-1])};sre.SemanticPred.tableIsMultiline=function(a){return a.childNodes.every(function(a){return 1>=a.childNodes.length})};sre.SemanticPred.isBinomial=function(a){return 2===a.childNodes.length};
-sre.SemanticPred.isLimitBase=function(a){return sre.SemanticPred.isAttribute("type","LARGEOP")(a)||sre.SemanticPred.isAttribute("type","LIMBOTH")(a)||sre.SemanticPred.isAttribute("type","LIMLOWER")(a)||sre.SemanticPred.isAttribute("type","LIMUPPER")(a)||sre.SemanticPred.isAttribute("type","FUNCTION")(a)&&sre.SemanticPred.isAttribute("role","LIMFUNC")(a)};
-sre.SemanticPred.isSimpleFunctionHead=function(a){return a.type===sre.SemanticAttr.Type.IDENTIFIER||a.role===sre.SemanticAttr.Role.LATINLETTER||a.role===sre.SemanticAttr.Role.GREEKLETTER||a.role===sre.SemanticAttr.Role.OTHERLETTER};sre.SemanticPred.singlePunctAtPosition=function(a,b,c){return 1===b.length&&(a[c].type===sre.SemanticAttr.Type.PUNCTUATION||a[c].embellished===sre.SemanticAttr.Type.PUNCTUATION)&&a[c]===b[0]};
-sre.SemanticPred.isSimpleFunction=function(a){return sre.SemanticPred.isAttribute("type","IDENTIFIER")(a)&&sre.SemanticPred.isAttribute("role","SIMPLEFUNC")(a)};sre.SemanticPred.isLeftBrace=function(a){var b=["{","\ufe5b","\uff5b"];return!!a&&-1!==b.indexOf(a.textContent)};sre.SemanticPred.isRightBrace=function(a){var b=["}","\ufe5c","\uff5d"];return!!a&&-1!==b.indexOf(a.textContent)};sre.SemanticPred.isSetNode=function(a){return sre.SemanticPred.isLeftBrace(a.contentNodes[0])&&sre.SemanticPred.isRightBrace(a.contentNodes[1])};sre.SemanticProcessor=function(){this.factory_=new sre.SemanticNodeFactory};goog.addSingletonGetter(sre.SemanticProcessor);sre.SemanticProcessor.prototype.setNodeFactory=function(a){this.factory_=a};
-sre.SemanticProcessor.prototype.identifierNode=function(a,b,c){a=sre.SemanticProcessor.getInstance().factory_.makeLeafNode(a,b);if("MathML-Unit"===c)a.type=sre.SemanticAttr.Type.IDENTIFIER,a.role=sre.SemanticAttr.Role.UNIT;else if(!b&&1===a.textContent.length&&(a.role===sre.SemanticAttr.Role.INTEGER||a.role===sre.SemanticAttr.Role.LATINLETTER||a.role===sre.SemanticAttr.Role.GREEKLETTER)&&a.font===sre.SemanticAttr.Font.NORMAL)return a.font=sre.SemanticAttr.Font.ITALIC,a;a.type===sre.SemanticAttr.Type.UNKNOWN&&
-(a.type=sre.SemanticAttr.Type.IDENTIFIER);sre.SemanticProcessor.exprFont_(a);return a};
-sre.SemanticProcessor.prototype.implicitNode_=function(a){a=sre.SemanticProcessor.getInstance().getMixedNumbers_(a);a=sre.SemanticProcessor.getInstance().combineUnits_(a);if(1===a.length)return a[0];var b=sre.SemanticProcessor.getInstance().factory_.makeMultipleContentNodes(a.length-1,sre.SemanticAttr.invisibleTimes()),c=sre.SemanticProcessor.getInstance().infixNode_(a,b[0]);c.role=sre.SemanticAttr.Role.IMPLICIT;b.forEach(function(a){a.parent=c});c.contentNodes=b;return c};
-sre.SemanticProcessor.prototype.infixNode_=function(a,b){var c=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.INFIXOP,a,[b],sre.SemanticProcessor.getEmbellishedInner_(b).textContent);c.role=b.role;this.propagateSimpleFunction(c);return c};
-sre.SemanticProcessor.prototype.concatNode_=function(a,b,c){if(0===b.length)return a;var d=b.map(function(a){return sre.SemanticProcessor.getEmbellishedInner_(a).textContent}).join(" ");a=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(c,[a],b,d);1<b.length&&(a.role=sre.SemanticAttr.Role.MULTIOP);return a};
-sre.SemanticProcessor.prototype.prefixNode_=function(a,b){var c=sre.SemanticProcessor.partitionNodes_(b,sre.SemanticPred.isAttribute("role","SUBTRACTION")),d=sre.SemanticProcessor.getInstance().concatNode_(a,c.comp.pop(),sre.SemanticAttr.Type.PREFIXOP);1===d.contentNodes.length&&d.contentNodes[0].role===sre.SemanticAttr.Role.ADDITION&&"+"===d.contentNodes[0].textContent&&(d.role=sre.SemanticAttr.Role.POSITIVE);for(;0<c.rel.length;)d=sre.SemanticProcessor.getInstance().concatNode_(d,[c.rel.pop()],
-sre.SemanticAttr.Type.PREFIXOP),d.role=sre.SemanticAttr.Role.NEGATIVE,d=sre.SemanticProcessor.getInstance().concatNode_(d,c.comp.pop(),sre.SemanticAttr.Type.PREFIXOP);return d};sre.SemanticProcessor.prototype.postfixNode_=function(a,b){return b.length?sre.SemanticProcessor.getInstance().concatNode_(a,b,sre.SemanticAttr.Type.POSTFIXOP):a};
-sre.SemanticProcessor.prototype.text=function(a,b,c){if(!a)return sre.SemanticProcessor.getInstance().factory_.makeEmptyNode();a=sre.SemanticProcessor.getInstance().factory_.makeLeafNode(a,b);a.type=sre.SemanticAttr.Type.TEXT;"MS"===c&&(a.role=sre.SemanticAttr.Role.STRING);sre.SemanticProcessor.exprFont_(a);return a};
-sre.SemanticProcessor.prototype.row=function(a){a=a.filter(function(a){return!sre.SemanticPred.isAttribute("type","EMPTY")(a)});if(0===a.length)return sre.SemanticProcessor.getInstance().factory_.makeEmptyNode();a=sre.SemanticProcessor.getInstance().getFencesInRow_(a);a=sre.SemanticProcessor.getInstance().tablesInRow(a);a=sre.SemanticProcessor.getInstance().getPunctuationInRow_(a);a=sre.SemanticProcessor.getInstance().getTextInRow_(a);a=sre.SemanticProcessor.getInstance().getFunctionsInRow_(a);return sre.SemanticProcessor.getInstance().relationsInRow_(a)};
-sre.SemanticProcessor.prototype.combineUnits_=function(a){var b=sre.SemanticProcessor.partitionNodes_(a,function(a){return!sre.SemanticPred.isAttribute("role","UNIT")(a)});if(a.length===b.rel.length)return b.rel;a=[];do{var c=b.comp.shift(),d=b.rel.shift();1===c.length&&(a=a.concat(c));if(1<c.length){var e=sre.SemanticProcessor.getInstance().factory_.makeContentNode(sre.SemanticAttr.invisibleTimes()),c=sre.SemanticProcessor.getInstance().infixNode_(c,e);c.role=sre.SemanticAttr.Role.UNIT;a.push(c)}d&&
-a.push(d)}while(d);return a};
-sre.SemanticProcessor.prototype.getMixedNumbers_=function(a){var b=sre.SemanticProcessor.partitionNodes_(a,function(a){return sre.SemanticPred.isAttribute("type","FRACTION")(a)&&sre.SemanticPred.isAttribute("role","VULGAR")(a)});if(!b.rel.length)return a;a=[];for(var c=0,d;d=b.rel[c];c++){var e=b.comp[c],f=e.length-1;e[f]&&sre.SemanticPred.isAttribute("type","NUMBER")(e[f])&&sre.SemanticPred.isAttribute("role","INTEGER")(e[f])?(d=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.NUMBER,[e[f],
-d],[]),d.role=sre.SemanticAttr.Role.MIXED,a=a.concat(e.slice(0,f))):a=a.concat(e);a.push(d)}return a.concat(b.comp[b.comp.length-1])};
-sre.SemanticProcessor.prototype.getTextInRow_=function(a){if(1>=a.length)return a;var b=sre.SemanticProcessor.partitionNodes_(a,sre.SemanticPred.isAttribute("type","TEXT"));if(0===b.rel.length)return a;a=[];var c=b.comp[0];0<c.length&&a.push(sre.SemanticProcessor.getInstance().row(c));for(var d=0;c=b.rel[d];d++)a.push(c),c=b.comp[d+1],0<c.length&&a.push(sre.SemanticProcessor.getInstance().row(c));return[sre.SemanticProcessor.getInstance().dummyNode_(a)]};
-sre.SemanticProcessor.prototype.relationsInRow_=function(a){var b=sre.SemanticProcessor.partitionNodes_(a,sre.SemanticPred.isRelation),c=b.rel[0];if(!c)return sre.SemanticProcessor.getInstance().operationsInRow_(a);if(1===a.length)return a[0];a=b.comp.map(goog.bind(sre.SemanticProcessor.getInstance().operationsInRow_,this));if(b.rel.some(function(a){return!a.equals(c)}))return a=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.MULTIREL,a,b.rel),b.rel.every(function(a){return a.role===
-c.role})&&(a.role=c.role),a;a=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.RELSEQ,a,b.rel,sre.SemanticProcessor.getEmbellishedInner_(c).textContent);a.role=c.role;return a};
-sre.SemanticProcessor.prototype.operationsInRow_=function(a){if(0===a.length)return sre.SemanticProcessor.getInstance().factory_.makeEmptyNode();if(1===a.length)return a[0];for(var b=[];0<a.length&&sre.SemanticPred.isOperator(a[0]);)b.push(a.shift());if(0===a.length)return sre.SemanticProcessor.getInstance().prefixNode_(b.pop(),b);if(1===a.length)return sre.SemanticProcessor.getInstance().prefixNode_(a[0],b);a=sre.SemanticProcessor.sliceNodes_(a,sre.SemanticPred.isOperator);b=sre.SemanticProcessor.getInstance().prefixNode_(sre.SemanticProcessor.getInstance().implicitNode_(a.head),
-b);return a.div?sre.SemanticProcessor.getInstance().operationsTree_(a.tail,b,a.div):b};
-sre.SemanticProcessor.prototype.operationsTree_=function(a,b,c,d){d=d||[];if(0===a.length)return d.unshift(c),b.type===sre.SemanticAttr.Type.INFIXOP?(d=sre.SemanticProcessor.getInstance().postfixNode_(b.childNodes.pop(),d),b.appendChild(d),b):sre.SemanticProcessor.getInstance().postfixNode_(b,d);a=sre.SemanticProcessor.sliceNodes_(a,sre.SemanticPred.isOperator);if(0===a.head.length)return d.push(a.div),sre.SemanticProcessor.getInstance().operationsTree_(a.tail,b,c,d);d=sre.SemanticProcessor.getInstance().prefixNode_(sre.SemanticProcessor.getInstance().implicitNode_(a.head),
-d);b=sre.SemanticProcessor.getInstance().appendOperand_(b,c,d);return a.div?sre.SemanticProcessor.getInstance().operationsTree_(a.tail,b,a.div,[]):b};
-sre.SemanticProcessor.prototype.appendOperand_=function(a,b,c){return a.type!==sre.SemanticAttr.Type.INFIXOP?sre.SemanticProcessor.getInstance().infixNode_([a,c],b):sre.SemanticProcessor.getInstance().appendExistingOperator_(a,b,c)?a:b.role===sre.SemanticAttr.Role.MULTIPLICATION?sre.SemanticProcessor.getInstance().appendMultiplicativeOp_(a,b,c):sre.SemanticProcessor.getInstance().appendAdditiveOp_(a,b,c)};
-sre.SemanticProcessor.prototype.appendMultiplicativeOp_=function(a,b,c){if(a.role===sre.SemanticAttr.Role.IMPLICIT)return sre.SemanticProcessor.getInstance().infixNode_([a,c],b);for(var d=a,e=a.childNodes[a.childNodes.length-1];e&&e.type===sre.SemanticAttr.Type.INFIXOP;)d=e,e=d.childNodes[a.childNodes.length-1];b=sre.SemanticProcessor.getInstance().infixNode_([d.childNodes.pop(),c],b);d.appendChild(b);return a};
-sre.SemanticProcessor.prototype.appendAdditiveOp_=function(a,b,c){return sre.SemanticProcessor.getInstance().infixNode_([a,c],b)};sre.SemanticProcessor.prototype.appendExistingOperator_=function(a,b,c){return a&&a.type===sre.SemanticAttr.Type.INFIXOP&&a.role!==sre.SemanticAttr.Role.IMPLICIT?a.contentNodes[0].equals(b)?(a.appendContentNode(b),a.appendChild(c),!0):sre.SemanticProcessor.getInstance().appendExistingOperator_(a.childNodes[a.childNodes.length-1],b,c):!1};
-sre.SemanticProcessor.prototype.getFencesInRow_=function(a){a=sre.SemanticProcessor.partitionNodes_(a,sre.SemanticPred.isFence);a=sre.SemanticProcessor.purgeFences_(a);var b=a.comp.shift();return sre.SemanticProcessor.getInstance().fences_(a.rel,a.comp,[],[b])};
-sre.SemanticProcessor.prototype.fences_=function(a,b,c,d){if(0===a.length&&0===c.length)return d[0];var e=sre.SemanticPred.isAttribute("role","OPEN");if(0===a.length){for(a=d.shift();0<c.length;){if(e(c[0]))b=c.shift(),sre.SemanticProcessor.fenceToPunct_(b),a.push(b);else{c=sre.SemanticProcessor.sliceNodes_(c,e);var f=c.head.length-1,g=sre.SemanticProcessor.getInstance().neutralFences_(c.head,d.slice(0,f));d=d.slice(f);a.push.apply(a,g);c.div&&c.tail.unshift(c.div);c=c.tail}a.push.apply(a,d.shift())}return a}f=
-c[c.length-1];g=a[0].role;if(g===sre.SemanticAttr.Role.OPEN||g===sre.SemanticAttr.Role.NEUTRAL&&(!f||a[0].textContent!==f.textContent))return c.push(a.shift()),(e=b.shift())&&d.push(e),sre.SemanticProcessor.getInstance().fences_(a,b,c,d);if(f&&(g===sre.SemanticAttr.Role.CLOSE&&f.role===sre.SemanticAttr.Role.OPEN||g===sre.SemanticAttr.Role.NEUTRAL&&a[0].textContent===f.textContent))return e=sre.SemanticProcessor.getInstance().horizontalFencedNode_(c.pop(),a.shift(),d.pop()),d.push(d.pop().concat([e],
-b.shift())),sre.SemanticProcessor.getInstance().fences_(a,b,c,d);if(f&&g===sre.SemanticAttr.Role.CLOSE&&f.role===sre.SemanticAttr.Role.NEUTRAL&&c.some(e))return c=sre.SemanticProcessor.sliceNodes_(c,e,!0),e=d.pop(),f=d.length-c.tail.length+1,g=sre.SemanticProcessor.getInstance().neutralFences_(c.tail,d.slice(f)),d=d.slice(0,f),e=sre.SemanticProcessor.getInstance().horizontalFencedNode_(c.div,a.shift(),d.pop().concat(g,e)),d.push(d.pop().concat([e],b.shift())),sre.SemanticProcessor.getInstance().fences_(a,
-b,c.head,d);e=a.shift();sre.SemanticProcessor.fenceToPunct_(e);d.push(d.pop().concat([e],b.shift()));return sre.SemanticProcessor.getInstance().fences_(a,b,c,d)};
-sre.SemanticProcessor.prototype.neutralFences_=function(a,b){if(0===a.length)return a;if(1===a.length)return sre.SemanticProcessor.fenceToPunct_(a[0]),a;var c=a.shift(),d=sre.SemanticProcessor.sliceNodes_(a,function(a){return sre.SemanticProcessor.getEmbellishedInner_(a).textContent==sre.SemanticProcessor.getEmbellishedInner_(c).textContent});if(!d.div){sre.SemanticProcessor.fenceToPunct_(c);var e=b.shift();e.unshift(c);return e.concat(sre.SemanticProcessor.getInstance().neutralFences_(a,b))}var f=
-sre.SemanticProcessor.getInstance().combineFencedContent_(c,d.div,d.head,b);return 0<d.tail.length?(e=f.shift(),d=sre.SemanticProcessor.getInstance().neutralFences_(d.tail,f),e.concat(d)):f[0]};
-sre.SemanticProcessor.prototype.combineFencedContent_=function(a,b,c,d){if(0===c.length)return a=sre.SemanticProcessor.getInstance().horizontalFencedNode_(a,b,d.shift()),0<d.length?d[0].unshift(a):d=[[a]],d;var e=d.shift(),f=c.length-1,g=d.slice(0,f);d=d.slice(f);f=d.shift();c=sre.SemanticProcessor.getInstance().neutralFences_(c,g);e.push.apply(e,c);e.push.apply(e,f);a=sre.SemanticProcessor.getInstance().horizontalFencedNode_(a,b,e);0<d.length?d[0].unshift(a):d=[[a]];return d};
-sre.SemanticProcessor.FENCE_TO_PUNCT_={};sre.SemanticProcessor.FENCE_TO_PUNCT_[sre.SemanticAttr.Role.NEUTRAL]=sre.SemanticAttr.Role.VBAR;sre.SemanticProcessor.FENCE_TO_PUNCT_[sre.SemanticAttr.Role.OPEN]=sre.SemanticAttr.Role.OPENFENCE;sre.SemanticProcessor.FENCE_TO_PUNCT_[sre.SemanticAttr.Role.CLOSE]=sre.SemanticAttr.Role.CLOSEFENCE;
-sre.SemanticProcessor.fenceToPunct_=function(a){var b=sre.SemanticProcessor.FENCE_TO_PUNCT_[a.role];if(b){for(;a.embellished;)a.embellished=sre.SemanticAttr.Type.PUNCTUATION,a.role=b,a=a.childNodes[0];a.type=sre.SemanticAttr.Type.PUNCTUATION;a.role=b}};
-sre.SemanticProcessor.prototype.horizontalFencedNode_=function(a,b,c){c=sre.SemanticProcessor.getInstance().row(c);b=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.FENCED,[c],[a,b]);a.role===sre.SemanticAttr.Role.OPEN?(this.classifyHorizontalFence_(b),this.propagateComposedFunction(b)):b.role=a.role;return sre.SemanticProcessor.rewriteFencedNode_(b)};
-sre.SemanticProcessor.prototype.classifyHorizontalFence_=function(a){a.role=sre.SemanticAttr.Role.LEFTRIGHT;var b=a.childNodes;if(sre.SemanticPred.isSetNode(a)&&!(1<b.length)){var c=b[0].type;if(0===b.length||b[0].type===sre.SemanticAttr.Type.EMPTY)a.role=sre.SemanticAttr.Role.SETEMPTY;else if(c===sre.SemanticAttr.Type.IDENTIFIER||c===sre.SemanticAttr.Type.NUMBER)a.role=sre.SemanticAttr.Role.SETSINGLE;else{var d=b[0].role;c===sre.SemanticAttr.Type.PUNCTUATED&&d===sre.SemanticAttr.Role.SEQUENCE&&(b[0].contentNodes[0].role===
-sre.SemanticAttr.Role.COMMA?a.role=sre.SemanticAttr.Role.SETCOLLECT:1!==b[0].contentNodes.length||b[0].contentNodes[0].role!==sre.SemanticAttr.Role.VBAR&&b[0].contentNodes[0].role!==sre.SemanticAttr.Role.COLON||(a.role=sre.SemanticAttr.Role.SETEXT,this.setExtension_(a)))}}};
-sre.SemanticProcessor.prototype.setExtension_=function(a){(a=a.childNodes[0].childNodes[0])&&a.type===sre.SemanticAttr.Type.INFIXOP&&1===a.contentNodes.length&&a.contentNodes[0].role===sre.SemanticAttr.Role.UNKNOWN&&(a.contentNodes[0].role=sre.SemanticAttr.Role.SETEXT)};
-sre.SemanticProcessor.prototype.getPunctuationInRow_=function(a){if(1>=a.length)return a;var b=sre.SemanticProcessor.partitionNodes_(a,function(a){return sre.SemanticPred.isPunctuation(a)&&!sre.SemanticPred.isAttribute("role","ELLIPSIS")(a)});if(0===b.rel.length)return a;a=[];var c=b.comp.shift();0<c.length&&a.push(sre.SemanticProcessor.getInstance().row(c));for(var d=0;0<b.comp.length;)a.push(b.rel[d++]),c=b.comp.shift(),0<c.length&&a.push(sre.SemanticProcessor.getInstance().row(c));return[sre.SemanticProcessor.getInstance().punctuatedNode_(a,
-b.rel)]};
-sre.SemanticProcessor.prototype.punctuatedNode_=function(a,b){var c=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.PUNCTUATED,a,b);if(b.length===a.length){var d=b[0].role;if(d!==sre.SemanticAttr.Role.UNKNOWN&&b.every(function(a){return a.role===d}))return c.role=d,c}sre.SemanticPred.singlePunctAtPosition(a,b,0)?c.role=sre.SemanticAttr.Role.STARTPUNCT:sre.SemanticPred.singlePunctAtPosition(a,b,a.length-1)?c.role=sre.SemanticAttr.Role.ENDPUNCT:b.every(sre.SemanticPred.isAttribute("role","DUMMY"))?
-c.role=sre.SemanticAttr.Role.TEXT:c.role=sre.SemanticAttr.Role.SEQUENCE;return c};sre.SemanticProcessor.prototype.dummyNode_=function(a){var b=sre.SemanticProcessor.getInstance().factory_.makeMultipleContentNodes(a.length-1,sre.SemanticAttr.invisibleComma());b.forEach(function(a){a.role=sre.SemanticAttr.Role.DUMMY});return sre.SemanticProcessor.getInstance().punctuatedNode_(a,b)};
-sre.SemanticProcessor.MML_TO_LIMIT_={MSUB:sre.SemanticAttr.Type.LIMLOWER,MUNDER:sre.SemanticAttr.Type.LIMLOWER,MSUP:sre.SemanticAttr.Type.LIMUPPER,MOVER:sre.SemanticAttr.Type.LIMUPPER,MSUBSUP:sre.SemanticAttr.Type.LIMBOTH,MUNDEROVER:sre.SemanticAttr.Type.LIMBOTH};
-sre.SemanticProcessor.prototype.limitNode=function(a,b){var c=b[0],d;if(sre.SemanticPred.isLimitBase(c))d=sre.SemanticProcessor.MML_TO_LIMIT_[a];else switch(a){case "MSUB":d=sre.SemanticAttr.Type.SUBSCRIPT;break;case "MSUP":d=sre.SemanticAttr.Type.SUPERSCRIPT;break;case "MSUBSUP":var e=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.SUBSCRIPT,[c,b[1]],[]);e.role=sre.SemanticAttr.Role.SUBSUP;b=[e,b[2]];d=sre.SemanticAttr.Type.SUPERSCRIPT;break;case "MOVER":d=sre.SemanticAttr.Type.OVERSCORE;
-sre.SemanticPred.isAccent(b[1])&&(b[1].role=sre.SemanticAttr.Role.OVERACCENT);break;case "MUNDER":d=sre.SemanticAttr.Type.UNDERSCORE;sre.SemanticPred.isAccent(b[1])&&(b[1].role=sre.SemanticAttr.Role.UNDERACCENT);break;default:e=sre.SemanticPred.isAccent(b[1]),d=sre.SemanticPred.isAccent(b[2]),e&&(b[1].role=sre.SemanticAttr.Role.UNDERACCENT),d&&(b[2].role=sre.SemanticAttr.Role.OVERACCENT),d&&!e?(e=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.OVERSCORE,[c,b[2]],
-[]),b=[e,b[1]],d=sre.SemanticAttr.Type.UNDERSCORE):(e=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.UNDERSCORE,[c,b[1]],[]),b=[e,b[2]],d=sre.SemanticAttr.Type.OVERSCORE),e.role=sre.SemanticAttr.Role.UNDEROVER}d=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(d,b,[]);var f=sre.SemanticPred.isEmbellished(c);e&&(e.embellished=f);d.embellished=f;d.role=c.role;return d};
-sre.SemanticProcessor.prototype.getFunctionsInRow_=function(a,b){var c=b||[];if(0===a.length)return c;var d=a.shift(),e=sre.SemanticProcessor.classifyFunction_(d,a);if(!e)return c.push(d),sre.SemanticProcessor.getInstance().getFunctionsInRow_(a,c);var f=sre.SemanticProcessor.getInstance().getFunctionsInRow_(a,[]),d=sre.SemanticProcessor.getInstance().getFunctionArgs_(d,f,e);return c.concat(d)};sre.SemanticProcessor.CLASSIFY_FUNCTION_={};
-sre.SemanticProcessor.CLASSIFY_FUNCTION_[sre.SemanticAttr.Role.INTEGRAL]="integral";sre.SemanticProcessor.CLASSIFY_FUNCTION_[sre.SemanticAttr.Role.SUM]="bigop";sre.SemanticProcessor.CLASSIFY_FUNCTION_[sre.SemanticAttr.Role.PREFIXFUNC]="prefix";sre.SemanticProcessor.CLASSIFY_FUNCTION_[sre.SemanticAttr.Role.LIMFUNC]="prefix";sre.SemanticProcessor.CLASSIFY_FUNCTION_[sre.SemanticAttr.Role.SIMPLEFUNC]="prefix";sre.SemanticProcessor.CLASSIFY_FUNCTION_[sre.SemanticAttr.Role.COMPFUNC]="prefix";
-sre.SemanticProcessor.classifyFunction_=function(a,b){if(a.type===sre.SemanticAttr.Type.APPL||a.type===sre.SemanticAttr.Type.BIGOP||a.type===sre.SemanticAttr.Type.INTEGRAL)return"";if(b[0]&&b[0].textContent===sre.SemanticAttr.functionApplication()){b.shift();var c=sre.SemanticAttr.Role.SIMPLEFUNC;if(a.role===sre.SemanticAttr.Role.PREFIXFUNC||a.role===sre.SemanticAttr.Role.LIMFUNC)c=a.role;sre.SemanticProcessor.propagateFunctionRole_(a,c);return"prefix"}return(c=sre.SemanticProcessor.CLASSIFY_FUNCTION_[a.role])?
-c:sre.SemanticPred.isSimpleFunctionHead(a)?"simple":""};sre.SemanticProcessor.propagateFunctionRole_=function(a,b){a&&(sre.SemanticPred.isAttribute("role","SUBSUP")(a)||(a.role=b),sre.SemanticProcessor.propagateFunctionRole_(a.childNodes[0],b))};
-sre.SemanticProcessor.prototype.getFunctionArgs_=function(a,b,c){switch(c){case "integral":return b=sre.SemanticProcessor.getInstance().getIntegralArgs_(b),c=sre.SemanticProcessor.getInstance().row(b.integrand),a=sre.SemanticProcessor.getInstance().integralNode_(a,c,b.intvar),b.rest.unshift(a),b.rest;case "prefix":if(b[0]&&b[0].type===sre.SemanticAttr.Type.FENCED)return a=sre.SemanticProcessor.getInstance().functionNode_(a,b.shift()),b.unshift(a),b;c=sre.SemanticProcessor.sliceNodes_(b,sre.SemanticPred.isPrefixFunctionBoundary);
-if(c.head.length)b=sre.SemanticProcessor.getInstance().row(c.head),c.div&&c.tail.unshift(c.div);else{if(!c.div||!sre.SemanticPred.isAttribute("type","APPL")(c.div))return b.unshift(a),b;b=c.div}a=sre.SemanticProcessor.getInstance().functionNode_(a,b);c.tail.unshift(a);return c.tail;case "bigop":c=sre.SemanticProcessor.sliceNodes_(b,sre.SemanticPred.isBigOpBoundary);if(!c.head.length)return b.unshift(a),b;b=sre.SemanticProcessor.getInstance().row(c.head);a=sre.SemanticProcessor.getInstance().bigOpNode_(a,
-b);c.div&&c.tail.unshift(c.div);c.tail.unshift(a);return c.tail;default:if(0===b.length)return[a];c=b[0];if(c.type===sre.SemanticAttr.Type.FENCED&&c.role!==sre.SemanticAttr.Role.NEUTRAL&&sre.SemanticPred.isSimpleFunctionScope(c))return c.role=sre.SemanticAttr.Role.LEFTRIGHT,sre.SemanticProcessor.propagateFunctionRole_(a,sre.SemanticAttr.Role.SIMPLEFUNC),a=sre.SemanticProcessor.getInstance().functionNode_(a,b.shift()),b.unshift(a),b;b.unshift(a);return b}};
-sre.SemanticProcessor.prototype.getIntegralArgs_=function(a,b){var c=b||[];if(0===a.length)return{integrand:c,intvar:null,rest:a};var d=a[0];if(sre.SemanticPred.isGeneralFunctionBoundary(d))return{integrand:c,intvar:null,rest:a};if(sre.SemanticPred.isIntegralDxBoundarySingle(d))return{integrand:c,intvar:d,rest:a.slice(1)};if(a[1]&&sre.SemanticPred.isIntegralDxBoundary(d,a[1])){var e=sre.SemanticProcessor.getInstance().factory_.makeContentNode(sre.SemanticAttr.invisibleComma()),d=sre.SemanticProcessor.getInstance().punctuatedNode_([d,
-e,a[1]],[e]);d.role=sre.SemanticAttr.Role.INTEGRAL;return{integrand:c,intvar:d,rest:a.slice(2)}}c.push(a.shift());return sre.SemanticProcessor.getInstance().getIntegralArgs_(a,c)};
-sre.SemanticProcessor.prototype.functionNode_=function(a,b){var c=sre.SemanticProcessor.getInstance().factory_.makeContentNode(sre.SemanticAttr.functionApplication());c.type=sre.SemanticAttr.Type.PUNCTUATION;c.role=sre.SemanticAttr.Role.APPLICATION;var d=sre.SemanticProcessor.getFunctionOp_(a,function(a){return sre.SemanticPred.isAttribute("type","FUNCTION")(a)||sre.SemanticPred.isAttribute("type","IDENTIFIER")(a)&&sre.SemanticPred.isAttribute("role","SIMPLEFUNC")(a)});return sre.SemanticProcessor.getInstance().functionalNode_(sre.SemanticAttr.Type.APPL,
-[a,b],d,[c])};sre.SemanticProcessor.prototype.bigOpNode_=function(a,b){var c=sre.SemanticProcessor.getFunctionOp_(a,sre.SemanticPred.isAttribute("type","LARGEOP"));return sre.SemanticProcessor.getInstance().functionalNode_(sre.SemanticAttr.Type.BIGOP,[a,b],c,[])};
-sre.SemanticProcessor.prototype.integralNode_=function(a,b,c){b=b||sre.SemanticProcessor.getInstance().factory_.makeEmptyNode();c=c||sre.SemanticProcessor.getInstance().factory_.makeEmptyNode();var d=sre.SemanticProcessor.getFunctionOp_(a,sre.SemanticPred.isAttribute("type","LARGEOP"));return sre.SemanticProcessor.getInstance().functionalNode_(sre.SemanticAttr.Type.INTEGRAL,[a,b,c],d,[])};
-sre.SemanticProcessor.prototype.functionalNode_=function(a,b,c,d){var e=b[0];if(c){var f=c.parent;d.push(c)}a=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(a,b,d);a.role=e.role;f&&(c.parent=f);return a};sre.SemanticProcessor.getFunctionOp_=function(a,b){if(b(a))return a;for(var c=0,d;d=a.childNodes[c];c++)if(d=sre.SemanticProcessor.getFunctionOp_(d,b))return d;return null};
-sre.SemanticProcessor.prototype.tablesInRow=function(a){a=sre.SemanticProcessor.partitionNodes_(a,sre.SemanticPred.tableIsMatrixOrVector);for(var b=[],c=0,d;d=a.rel[c];c++)b=b.concat(a.comp.shift()),b.push(sre.SemanticProcessor.tableToMatrixOrVector_(d));b=b.concat(a.comp.shift());a=sre.SemanticProcessor.partitionNodes_(b,sre.SemanticPred.isTableOrMultiline);b=[];for(c=0;d=a.rel[c];c++){var e=a.comp.shift();sre.SemanticPred.tableIsCases(d,e)&&sre.SemanticProcessor.tableToCases_(d,e.pop());b=b.concat(e);
-b.push(d)}return b.concat(a.comp.shift())};sre.SemanticProcessor.tableToMatrixOrVector_=function(a){var b=a.childNodes[0];sre.SemanticPred.isAttribute("type","MULTILINE")(b)?sre.SemanticProcessor.tableToVector_(a):sre.SemanticProcessor.tableToMatrix_(a);a.contentNodes.forEach(goog.bind(b.appendContentNode,b));a=0;for(var c;c=b.childNodes[a];a++)sre.SemanticProcessor.assignRoleToRow_(c,sre.SemanticProcessor.getComponentRoles_(b));b.parent=null;return b};
-sre.SemanticProcessor.tableToVector_=function(a){var b=a.childNodes[0];b.type=sre.SemanticAttr.Type.VECTOR;1===b.childNodes.length?sre.SemanticProcessor.tableToSquare_(a):sre.SemanticProcessor.binomialForm_(b)};sre.SemanticProcessor.binomialForm_=function(a){sre.SemanticPred.isBinomial(a)&&(a.role=sre.SemanticAttr.Role.BINOMIAL,a.childNodes[0].role=sre.SemanticAttr.Role.BINOMIAL,a.childNodes[1].role=sre.SemanticAttr.Role.BINOMIAL)};
-sre.SemanticProcessor.tableToMatrix_=function(a){var b=a.childNodes[0];b.type=sre.SemanticAttr.Type.MATRIX;b.childNodes&&0<b.childNodes.length&&b.childNodes[0].childNodes&&b.childNodes.length===b.childNodes[0].childNodes.length?sre.SemanticProcessor.tableToSquare_(a):b.childNodes&&1===b.childNodes.length&&(b.role=sre.SemanticAttr.Role.ROWVECTOR)};
-sre.SemanticProcessor.tableToSquare_=function(a){var b=a.childNodes[0];sre.SemanticPred.isAttribute("role","NEUTRAL")(a)?b.role=sre.SemanticAttr.Role.DETERMINANT:b.role=sre.SemanticAttr.Role.SQUAREMATRIX};sre.SemanticProcessor.getComponentRoles_=function(a){var b=a.role;return b&&b!==sre.SemanticAttr.Role.UNKNOWN?b:sre.SemanticAttr.Role[a.type.toUpperCase()]||sre.SemanticAttr.Role.UNKNOWN};
-sre.SemanticProcessor.tableToCases_=function(a,b){for(var c=0,d;d=a.childNodes[c];c++)sre.SemanticProcessor.assignRoleToRow_(d,sre.SemanticAttr.Role.CASES);a.type=sre.SemanticAttr.Type.CASES;a.appendContentNode(b);sre.SemanticPred.tableIsMultiline(a)&&sre.SemanticProcessor.binomialForm_(a);return a};
-sre.SemanticProcessor.tableToMultiline=function(a){if(sre.SemanticPred.tableIsMultiline(a)){a.type=sre.SemanticAttr.Type.MULTILINE;for(var b=0,c;c=a.childNodes[b];b++)sre.SemanticProcessor.rowToLine_(c,sre.SemanticAttr.Role.MULTILINE);1===a.childNodes.length&&sre.SemanticPred.isFencedElement(a.childNodes[0].childNodes[0])&&sre.SemanticProcessor.tableToMatrixOrVector_(sre.SemanticProcessor.rewriteFencedLine_(a));sre.SemanticProcessor.binomialForm_(a);sre.SemanticProcessor.classifyMultiline(a)}else sre.SemanticProcessor.classifyTable(a)};
-sre.SemanticProcessor.rewriteFencedLine_=function(a){var b=a.childNodes[0],c=a.childNodes[0].childNodes[0],d=a.childNodes[0].childNodes[0].childNodes[0];c.parent=a.parent;a.parent=c;d.parent=b;c.childNodes=[a];b.childNodes=[d];return c};
-sre.SemanticProcessor.rowToLine_=function(a,b){var c=b||sre.SemanticAttr.Role.UNKNOWN;sre.SemanticPred.isAttribute("type","ROW")(a)&&(a.type=sre.SemanticAttr.Type.LINE,a.role=c,1===a.childNodes.length&&sre.SemanticPred.isAttribute("type","CELL")(a.childNodes[0])&&(a.childNodes=a.childNodes[0].childNodes,a.childNodes.forEach(function(b){b.parent=a})))};
-sre.SemanticProcessor.assignRoleToRow_=function(a,b){if(sre.SemanticPred.isAttribute("type","LINE")(a))a.role=b;else if(sre.SemanticPred.isAttribute("type","ROW")(a)){a.role=b;var c=sre.SemanticPred.isAttribute("type","CELL");a.childNodes.forEach(function(a){c(a)&&(a.role=b)})}};
-sre.SemanticProcessor.sliceNodes_=function(a,b,c){c&&a.reverse();for(var d=[],e=0,f;f=a[e];e++){if(b(f))return c?{head:a.slice(e+1).reverse(),div:f,tail:d.reverse()}:{head:d,div:f,tail:a.slice(e+1)};d.push(f)}return c?{head:[],div:null,tail:d.reverse()}:{head:d,div:null,tail:[]}};sre.SemanticProcessor.partitionNodes_=function(a,b){var c=a,d=[],e=[];do{var f=sre.SemanticProcessor.sliceNodes_(c,b);e.push(f.head);d.push(f.div);c=f.tail}while(f.div);d.pop();return{rel:d,comp:e}};
-sre.SemanticProcessor.prototype.mfenced=function(a,b,c,d){if(c&&0<d.length){var e=sre.MathUtil.nextSeparatorFunction(c),f=[d.shift()];d.forEach(goog.bind(function(a){f.push(sre.SemanticProcessor.getInstance().factory_.makeContentNode(e()));f.push(a)},this));d=f}if(a&&b)return sre.SemanticProcessor.getInstance().horizontalFencedNode_(sre.SemanticProcessor.getInstance().factory_.makeContentNode(a),sre.SemanticProcessor.getInstance().factory_.makeContentNode(b),d);a&&d.unshift(sre.SemanticProcessor.getInstance().factory_.makeContentNode(a));
-b&&d.push(sre.SemanticProcessor.getInstance().factory_.makeContentNode(b));return sre.SemanticProcessor.getInstance().row(d)};sre.SemanticProcessor.number=function(a){if(a.type===sre.SemanticAttr.Type.UNKNOWN||a.type===sre.SemanticAttr.Type.IDENTIFIER)a.type=sre.SemanticAttr.Type.NUMBER;sre.SemanticProcessor.numberRole_(a);sre.SemanticProcessor.exprFont_(a)};
-sre.SemanticProcessor.numberRole_=function(a){if(a.role===sre.SemanticAttr.Role.UNKNOWN){var b=sre.SemanticUtil.splitUnicode(a.textContent).map(sre.SemanticAttr.lookupMeaning);b.every(function(a){return a.type===sre.SemanticAttr.Type.NUMBER&&a.role===sre.SemanticAttr.Role.INTEGER||a.type===sre.SemanticAttr.Type.PUNCTUATION&&a.role===sre.SemanticAttr.Role.COMMA})?a.role=sre.SemanticAttr.Role.INTEGER:b.every(function(a){return a.type===sre.SemanticAttr.Type.NUMBER&&a.role===sre.SemanticAttr.Role.INTEGER||
-a.type===sre.SemanticAttr.Type.PUNCTUATION})?a.role=sre.SemanticAttr.Role.FLOAT:a.role=sre.SemanticAttr.Role.OTHERNUMBER}};sre.SemanticProcessor.exprFont_=function(a){if(a.font===sre.SemanticAttr.Font.UNKNOWN){var b=sre.SemanticUtil.splitUnicode(a.textContent).map(sre.SemanticAttr.lookupMeaning).reduce(function(a,b){return a&&b.font&&b.font!==sre.SemanticAttr.Font.UNKNOWN&&b.font!==a?a===sre.SemanticAttr.Font.UNKNOWN?b.font:null:a},sre.SemanticAttr.Font.UNKNOWN);b&&(a.font=b)}};
-sre.SemanticProcessor.prototype.fractionLikeNode=function(a,b,c){return sre.SemanticUtil.isZeroLength(a)?(a=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.LINE,[b],[]),c=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.LINE,[c],[]),c=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.MULTILINE,[a,c],[]),sre.SemanticProcessor.binomialForm_(c),sre.SemanticProcessor.classifyMultiline(c),c):sre.SemanticProcessor.getInstance().fractionNode_(b,
-c)};
-sre.SemanticProcessor.prototype.fractionNode_=function(a,b){var c=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.FRACTION,[a,b],[]);c.role=c.childNodes.every(function(a){return sre.SemanticPred.isAttribute("type","NUMBER")(a)&&sre.SemanticPred.isAttribute("role","INTEGER")(a)})?sre.SemanticAttr.Role.VULGAR:c.childNodes.every(function(a){return sre.SemanticPred.isAttribute("role","UNIT")(a)})?sre.SemanticAttr.Role.UNIT:sre.SemanticAttr.Role.DIVISION;this.propagateSimpleFunction(c);return c};
-sre.SemanticProcessor.prototype.tensor=function(a,b,c,d,e){b=sre.SemanticProcessor.getInstance().factory_.makeBranchNode(sre.SemanticAttr.Type.TENSOR,[a,sre.SemanticProcessor.getInstance().scriptNode_(b,sre.SemanticAttr.Role.LEFTSUB),sre.SemanticProcessor.getInstance().scriptNode_(c,sre.SemanticAttr.Role.LEFTSUPER),sre.SemanticProcessor.getInstance().scriptNode_(d,sre.SemanticAttr.Role.RIGHTSUB),sre.SemanticProcessor.getInstance().scriptNode_(e,sre.SemanticAttr.Role.RIGHTSUPER)],[]);b.role=a.role;
-b.embellished=sre.SemanticPred.isEmbellished(a);return b};
-sre.SemanticProcessor.prototype.pseudoTensor=function(a,b,c){var d=function(a){return!sre.SemanticPred.isAttribute("type","EMPTY")(a)},e=b.filter(d).length,d=c.filter(d).length;if(!e&&!d)return a;var f=e?d?"MSUBSUP":"MSUB":"MSUP";a=[a];e&&a.push(sre.SemanticProcessor.getInstance().scriptNode_(b,sre.SemanticAttr.Role.RIGHTSUB,!0));d&&a.push(sre.SemanticProcessor.getInstance().scriptNode_(c,sre.SemanticAttr.Role.RIGHTSUPER,!0));return sre.SemanticProcessor.getInstance().limitNode(f,a)};
-sre.SemanticProcessor.prototype.scriptNode_=function(a,b,c){switch(a.length){case 0:a=sre.SemanticProcessor.getInstance().factory_.makeEmptyNode();break;case 1:a=a[0];if(c)return a;break;default:a=sre.SemanticProcessor.getInstance().dummyNode_(a)}a.role=b;return a};sre.SemanticProcessor.getEmbellishedInner_=function(a){return a&&a.embellished&&0<a.childNodes.length?sre.SemanticProcessor.getEmbellishedInner_(a.childNodes[0]):a};
-sre.SemanticProcessor.purgeFences_=function(a){var b=a.rel;a=a.comp;for(var c=[],d=[];0<b.length;){var e=b.shift(),f=a.shift();sre.SemanticPred.isElligibleEmbellishedFence(e)?(c.push(e),d.push(f)):(sre.SemanticProcessor.fenceToPunct_(e),f.push(e),f=f.concat(a.shift()),a.unshift(f))}d.push(a.shift());return{rel:c,comp:d}};
-sre.SemanticProcessor.rewriteFencedNode_=function(a){var b=a.contentNodes[1],c=sre.SemanticProcessor.rewriteFence_(a,a.contentNodes[0]);a.contentNodes[0]=c.fence;c=sre.SemanticProcessor.rewriteFence_(c.node,b);a.contentNodes[1]=c.fence;a.contentNodes[0].parent=a;a.contentNodes[1].parent=a;c.node.parent=null;return c.node};
-sre.SemanticProcessor.rewriteFence_=function(a,b){if(!b.embellished)return{node:a,fence:b};var c=b.childNodes[0],d=sre.SemanticProcessor.rewriteFence_(a,c);if(sre.SemanticPred.isAttribute("type","SUPERSCRIPT")(b)||sre.SemanticPred.isAttribute("type","SUBSCRIPT")(b)||sre.SemanticPred.isAttribute("type","TENSOR")(b))return sre.SemanticPred.isAttribute("role","SUBSUP")(b)||(b.role=a.role),c!==d.node&&(b.replaceChild(c,d.node),c.parent=a),sre.SemanticProcessor.propagateFencePointer_(b,c),{node:b,fence:d.fence};
-b.replaceChild(c,d.fence);b.mathmlTree&&-1===b.mathml.indexOf(b.mathmlTree)&&b.mathml.push(b.mathmlTree);return{node:d.node,fence:b}};sre.SemanticProcessor.propagateFencePointer_=function(a,b){a.fencePointer=b.fencePointer||b.id.toString();a.embellished=null};
-sre.SemanticProcessor.classifyMultiline=function(a){for(var b=0,c=a.childNodes.length,d;b<c&&(!(d=a.childNodes[b])||!d.childNodes.length);)b++;if(!(b>=c)){var e=d.childNodes[0].role;e!==sre.SemanticAttr.Role.UNKNOWN&&a.childNodes.every(function(a){a=a.childNodes[0];return!a||a.role===e&&(sre.SemanticPred.isAttribute("type","RELATION")(a)||sre.SemanticPred.isAttribute("type","RELSEQ")(a))})&&(a.role=e)}};
-sre.SemanticProcessor.classifyTable=function(a){var b=sre.SemanticProcessor.computeColumns_(a);sre.SemanticProcessor.classifyByColumns_(a,b,"EQUALITY")||sre.SemanticProcessor.classifyByColumns_(a,b,"INEQUALITY",["EQUALITY"])||sre.SemanticProcessor.classifyByColumns_(a,b,"ARROW")};
-sre.SemanticProcessor.classifyByColumns_=function(a,b,c,d){d=function(a){return sre.SemanticProcessor.isPureRelation_(a,c)};var e=function(a){return sre.SemanticProcessor.isEndRelation_(a,c)||sre.SemanticProcessor.isPureRelation_(a,c)},f=function(a){return sre.SemanticProcessor.isEndRelation_(a,c,!0)||sre.SemanticProcessor.isPureRelation_(a,c)};return 3===b.length&&sre.SemanticProcessor.testColumns_(b,1,d)||2===b.length&&(sre.SemanticProcessor.testColumns_(b,1,e)||sre.SemanticProcessor.testColumns_(b,
-0,f))?(a.role=sre.SemanticAttr.Role[c],!0):!1};sre.SemanticProcessor.isEndRelation_=function(a,b,c){c=c?a.childNodes.length-1:0;return sre.SemanticPred.isAttribute("type","RELSEQ")(a)&&sre.SemanticPred.isAttribute("role",b)(a)&&sre.SemanticPred.isAttribute("type","EMPTY")(a.childNodes[c])};sre.SemanticProcessor.isPureRelation_=function(a,b){return sre.SemanticPred.isAttribute("type","RELATION")(a)&&sre.SemanticPred.isAttribute("role",b)(a)};
-sre.SemanticProcessor.computeColumns_=function(a){for(var b=[],c=0,d;d=a.childNodes[c];c++)for(var e=0,f;f=d.childNodes[e];e++)b[e]?b[e].push(f):b[e]=[f];return b};sre.SemanticProcessor.testColumns_=function(a,b,c){return(a=a[b])?a.some(function(a){return a.childNodes.length&&c(a.childNodes[0])})&&a.every(function(a){return!a.childNodes.length||c(a.childNodes[0])}):!1};
-sre.SemanticProcessor.MATHJAX_FONTS={"-tex-caligraphic":sre.SemanticAttr.Font.CALIGRAPHIC,"-tex-caligraphic-bold":sre.SemanticAttr.Font.CALIGRAPHICBOLD,"-tex-oldstyle":sre.SemanticAttr.Font.OLDSTYLE,"-tex-oldstyle-bold":sre.SemanticAttr.Font.OLDSTYLEBOLD,"-tex-mathit":sre.SemanticAttr.Font.ITALIC};sre.SemanticProcessor.prototype.font=function(a){var b=sre.SemanticProcessor.MATHJAX_FONTS[a];return b?b:a};
-sre.SemanticProcessor.prototype.propagateSimpleFunction=function(a){"clearspeak"!==sre.Engine.getInstance().domain||a.type!==sre.SemanticAttr.Type.INFIXOP&&a.type!==sre.SemanticAttr.Type.FRACTION||!a.childNodes.every(sre.SemanticPred.isSimpleFunction)||(a.role=sre.SemanticAttr.Role.COMPFUNC)};
-sre.SemanticProcessor.prototype.propagateComposedFunction=function(a){"clearspeak"===sre.Engine.getInstance().domain&&a.type===sre.SemanticAttr.Type.FENCED&&a.childNodes[0].role===sre.SemanticAttr.Role.COMPFUNC&&(a.role=sre.SemanticAttr.Role.COMPFUNC)};sre.SemanticMathml=function(){sre.SemanticAbstractParser.call(this,"MathML");this.parseMap_={SEMANTICS:goog.bind(this.semantics_,this),MATH:goog.bind(this.rows_,this),MROW:goog.bind(this.rows_,this),MPADDED:goog.bind(this.rows_,this),MSTYLE:goog.bind(this.rows_,this),MFRAC:goog.bind(this.fraction_,this),MSUB:goog.bind(this.limits_,this),MSUP:goog.bind(this.limits_,this),MSUBSUP:goog.bind(this.limits_,this),MOVER:goog.bind(this.limits_,this),MUNDER:goog.bind(this.limits_,this),MUNDEROVER:goog.bind(this.limits_,
-this),MROOT:goog.bind(this.root_,this),MSQRT:goog.bind(this.sqrt_,this),MTABLE:goog.bind(this.table_,this),MLABELEDTR:goog.bind(this.tableLabeledRow_,this),MTR:goog.bind(this.tableRow_,this),MTD:goog.bind(this.tableCell_,this),MS:goog.bind(this.text_,this),MTEXT:goog.bind(this.text_,this),"ANNOTATION-XML":goog.bind(this.text_,this),MI:goog.bind(this.identifier_,this),MN:goog.bind(this.number_,this),MO:goog.bind(this.operator_,this),MFENCED:goog.bind(this.fenced_,this),MENCLOSE:goog.bind(this.enclosed_,
-this),MMULTISCRIPTS:goog.bind(this.multiscripts_,this),ANNOTATION:goog.bind(this.empty_,this),NONE:goog.bind(this.empty_,this),MACTION:goog.bind(this.action_,this)}};goog.inherits(sre.SemanticMathml,sre.SemanticAbstractParser);
-sre.SemanticMathml.prototype.parse=function(a){sre.SemanticProcessor.getInstance().setNodeFactory(this.getFactory());var b=sre.DomUtil.toArray(a.childNodes),c=sre.DomUtil.tagName(a),d=this.parseMap_[c],b=(d?d:goog.bind(this.dummy_,this))(a,b);if(-1!==["MATH","MROW","MPADDED","MSTYLE","SEMANTICS"].indexOf(c))return b;b.mathml.unshift(a);b.mathmlTree=a;return b};sre.SemanticMathml.prototype.parseNodes_=function(a){for(var b=[],c=0,d;d=a[c];c++)b.push(this.parse(d));return b};
-sre.SemanticMathml.prototype.semantics_=function(a,b){return b.length?this.parse(b[0]):this.getFactory().makeEmptyNode()};sre.SemanticMathml.prototype.rows_=function(a,b){b=sre.SemanticUtil.purgeNodes(b);var c=1===b.length?this.parse(b[0]):sre.SemanticProcessor.getInstance().row(this.parseNodes_(b));c.mathml.unshift(a);return c};sre.SemanticMathml.prototype.fraction_=function(a,b){return sre.SemanticProcessor.getInstance().fractionLikeNode(a.getAttribute("linethickness"),this.parse(b[0]),this.parse(b[1]))};
-sre.SemanticMathml.prototype.limits_=function(a,b){return sre.SemanticProcessor.getInstance().limitNode(sre.DomUtil.tagName(a),this.parseNodes_(b))};sre.SemanticMathml.prototype.root_=function(a,b){return this.getFactory().makeBranchNode(sre.SemanticAttr.Type.ROOT,[this.parse(b[1]),this.parse(b[0])],[])};
-sre.SemanticMathml.prototype.sqrt_=function(a,b){var c=this.parseNodes_(sre.SemanticUtil.purgeNodes(b));return this.getFactory().makeBranchNode(sre.SemanticAttr.Type.SQRT,[sre.SemanticProcessor.getInstance().row(c)],[])};sre.SemanticMathml.prototype.table_=function(a,b){var c=this.getFactory().makeBranchNode(sre.SemanticAttr.Type.TABLE,this.parseNodes_(b),[]);sre.SemanticProcessor.tableToMultiline(c);return c};
-sre.SemanticMathml.prototype.tableRow_=function(a,b){var c=this.getFactory().makeBranchNode(sre.SemanticAttr.Type.ROW,this.parseNodes_(b),[]);c.role=sre.SemanticAttr.Role.TABLE;return c};sre.SemanticMathml.prototype.tableLabeledRow_=function(a,b){if(!b.length)return this.tableRow_(a,b);var c=this.parse(b[0]);c.role=sre.SemanticAttr.Role.LABEL;c=this.getFactory().makeBranchNode(sre.SemanticAttr.Type.ROW,this.parseNodes_(b.slice(1)),[c]);c.role=sre.SemanticAttr.Role.TABLE;return c};
-sre.SemanticMathml.prototype.tableCell_=function(a,b){var c=this.parseNodes_(sre.SemanticUtil.purgeNodes(b)),c=c.length?1===c.length&&sre.SemanticPred.isAttribute("type","EMPTY")(c[0])?c:[sre.SemanticProcessor.getInstance().row(c)]:[],c=this.getFactory().makeBranchNode(sre.SemanticAttr.Type.CELL,c,[]);c.role=sre.SemanticAttr.Role.TABLE;return c};
-sre.SemanticMathml.prototype.text_=function(a,b){return sre.SemanticProcessor.getInstance().text(a.textContent,sre.SemanticProcessor.getInstance().font(a.getAttribute("mathvariant")),sre.DomUtil.tagName(a))};
-sre.SemanticMathml.prototype.identifier_=function(a,b){var c=sre.SemanticProcessor.getInstance().identifierNode(a.textContent,sre.SemanticProcessor.getInstance().font(a.getAttribute("mathvariant")),a.getAttribute("class"));if("clearspeak"!==sre.Engine.getInstance().domain)return c;-1!=="fghFGH".split("").indexOf(c.textContent)&&(c.role=sre.SemanticAttr.Role.SIMPLEFUNC);return c};sre.SemanticMathml.prototype.number_=function(a,b){var c=this.leaf_(a);sre.SemanticProcessor.number(c);return c};
-sre.SemanticMathml.prototype.operator_=function(a,b){var c=this.leaf_(a);c.type===sre.SemanticAttr.Type.UNKNOWN&&(c.type=sre.SemanticAttr.Type.OPERATOR);return c};sre.SemanticMathml.prototype.fenced_=function(a,b){var c=this.parseNodes_(sre.SemanticUtil.purgeNodes(b)),d=sre.SemanticMathml.getAttribute_(a,"separators",","),e=sre.SemanticMathml.getAttribute_(a,"open","("),f=sre.SemanticMathml.getAttribute_(a,"close",")"),c=sre.SemanticProcessor.getInstance().mfenced(e,f,d,c);return sre.SemanticProcessor.getInstance().tablesInRow([c])[0]};
-sre.SemanticMathml.prototype.enclosed_=function(a,b){var c=this.parseNodes_(sre.SemanticUtil.purgeNodes(b)),c=this.getFactory().makeBranchNode(sre.SemanticAttr.Type.ENCLOSE,[sre.SemanticProcessor.getInstance().row(c)],[]);c.role=a.getAttribute("notation")||sre.SemanticAttr.Role.UNKNOWN;return c};
-sre.SemanticMathml.prototype.multiscripts_=function(a,b){if(!b.length)return this.getFactory().makeEmptyNode();var c=this.parse(b.shift());if(!b.length)return c;for(var d=[],e=[],f=[],g=[],h=!1,k=0,l=0,m;m=b[l];l++)"MPRESCRIPTS"===sre.DomUtil.tagName(m)?(h=!0,k=0):(h?k&1?d.push(m):e.push(m):k&1?f.push(m):g.push(m),k++);return sre.SemanticUtil.purgeNodes(d).length||sre.SemanticUtil.purgeNodes(e).length?sre.SemanticProcessor.getInstance().tensor(c,this.parseNodes_(e),this.parseNodes_(d),this.parseNodes_(g),
-this.parseNodes_(f)):sre.SemanticProcessor.getInstance().pseudoTensor(c,this.parseNodes_(g),this.parseNodes_(f))};sre.SemanticMathml.prototype.empty_=function(a,b){return this.getFactory().makeEmptyNode()};sre.SemanticMathml.prototype.action_=function(a,b){return 1<b.length?this.parse(b[1]):this.getFactory().makeUnprocessed(a)};sre.SemanticMathml.prototype.dummy_=function(a,b){return this.getFactory().makeUnprocessed(a)};
-sre.SemanticMathml.prototype.leaf_=function(a){return this.getFactory().makeLeafNode(a.textContent,sre.SemanticProcessor.getInstance().font(a.getAttribute("mathvariant")))};sre.SemanticMathml.getAttribute_=function(a,b,c){if(!a.hasAttribute(b))return c;a=a.getAttribute(b);return a.match(/^\s*$/)?null:a};sre.SemanticTree=function(a){this.mathml=a;this.parser=new sre.SemanticMathml;this.root=this.parser.parse(a);sre.SemanticAnnotations.getInstance().annotate(this.root);a=this.parser.getFactory().leafMap.collateMeaning();a.minimize();a.isEmpty()||console.log(a.toString())};sre.SemanticTree.empty=function(){var a=sre.DomUtil.parseInput("<math/>"),b=new sre.SemanticTree(a);b.mathml=a;return b};sre.SemanticTree.fromNode=function(a,b){var c=sre.SemanticTree.empty();c.root=a;b&&(c.mathml=b);return c};
-sre.SemanticTree.fromRoot=function(a,b){for(var c=a;c.parent;)c=c.parent;c=sre.SemanticTree.fromNode(c);b&&(c.mathml=b);return c};sre.SemanticTree.prototype.xml=function(a){var b=sre.DomUtil.parseInput("<stree></stree>");a=this.root.xml(b.ownerDocument,a);b.appendChild(a);return b};sre.SemanticTree.prototype.toString=function(a){return(new sre.SystemExternal.xmldom.XMLSerializer).serializeToString(this.xml(a))};sre.SemanticTree.prototype.formatXml=function(a){a=this.toString(a);return sre.DomUtil.formatXml(a)};
-sre.SemanticTree.prototype.displayTree=function(){this.root.displayTree(0)};sre.SemanticTree.prototype.replaceNode=function(a,b){var c=a.parent;c?c.replaceChild(a,b):this.root=b};sre.SemanticTree.prototype.toJson=function(){var a={};a.stree=this.root.toJson();return a};sre.Semantic={};sre.Semantic.Font=sre.SemanticAttr.Font;sre.Semantic.Role=sre.SemanticAttr.Role;sre.Semantic.Type=sre.SemanticAttr.Type;sre.Semantic.xmlTree=function(a){return sre.Semantic.getTree(a).xml()};sre.Semantic.getTree=function(a){return new sre.SemanticTree(a)};sre.Semantic.getTreeFromString=function(a){a=sre.DomUtil.parseInput(a);return sre.Semantic.getTree(a)};sre.MathspeakUtil={};sre.MathspeakUtil.spaceoutText=function(a){return a.textContent.split("").join(" ")};sre.MathspeakUtil.spaceoutNumber=function(a){a=a.textContent.split("");for(var b=[],c=new sre.SystemExternal.xmldom.DOMParser,d=0,e;e=a[d];d++){var f=sre.Semantic.Type.NUMBER,g=e.match(/\W/)?sre.SemanticAttr.lookupMeaning(e).role:sre.Semantic.Role.PROTECTED;e=c.parseFromString("<"+f+' role="'+g+'">'+e+"</"+f+">","text/xml");b.push(e.documentElement)}return b};
-sre.MathspeakUtil.spaceoutIdentifier=function(a){var b=a.textContent;if(!b.match(/[a-zA-Z]+/))return a.setAttribute("role",sre.SemanticAttr.Role.PROTECTED),[a];a=b.split("");for(var b=[],c=new sre.SystemExternal.xmldom.DOMParser,d=0,e;e=a[d];d++){var f=sre.Semantic.Type.IDENTIFIER;e=c.parseFromString("<"+f+' role="'+sre.Semantic.Role.UNKNOWN+'">'+e+"</"+f+">","text/xml");b.push(e.documentElement)}return b};
-sre.MathspeakUtil.nestingBarriers=[sre.Semantic.Type.CASES,sre.Semantic.Type.CELL,sre.Semantic.Type.INTEGRAL,sre.Semantic.Type.LINE,sre.Semantic.Type.MATRIX,sre.Semantic.Type.MULTILINE,sre.Semantic.Type.OVERSCORE,sre.Semantic.Type.ROOT,sre.Semantic.Type.ROW,sre.Semantic.Type.SQRT,sre.Semantic.Type.SUBSCRIPT,sre.Semantic.Type.SUPERSCRIPT,sre.Semantic.Type.TABLE,sre.Semantic.Type.UNDERSCORE,sre.Semantic.Type.VECTOR];sre.MathspeakUtil.nestingDepth={};
-sre.MathspeakUtil.resetNestingDepth=function(a){sre.MathspeakUtil.nestingDepth={};return[a]};
-sre.MathspeakUtil.getNestingDepth=function(a,b,c,d,e,f){d=d||sre.MathspeakUtil.nestingBarriers;e=e||{};f=f||function(a){return!1};var g=(new sre.SystemExternal.xmldom.XMLSerializer).serializeToString(b);sre.MathspeakUtil.nestingDepth[a]||(sre.MathspeakUtil.nestingDepth[a]={});if(sre.MathspeakUtil.nestingDepth[a][g])return sre.MathspeakUtil.nestingDepth[a][g];if(f(b)||0>c.indexOf(b.tagName))return 0;b=sre.MathspeakUtil.computeNestingDepth_(b,c,sre.BaseUtil.setdifference(d,c),e,f,0);return sre.MathspeakUtil.nestingDepth[a][g]=
-b};sre.MathspeakUtil.containsAttr=function(a,b){if(!a.attributes)return!1;for(var c=sre.DomUtil.toArray(a.attributes),d=0,e;e=c[d];d++)if(b[e.nodeName]===e.nodeValue)return!0;return!1};
-sre.MathspeakUtil.computeNestingDepth_=function(a,b,c,d,e,f){if(e(a)||-1<c.indexOf(a.tagName)||sre.MathspeakUtil.containsAttr(a,d))return f;-1<b.indexOf(a.tagName)&&f++;if(!a.childNodes||0===a.childNodes.length)return f;a=sre.DomUtil.toArray(a.childNodes);return Math.max.apply(null,a.map(function(a){return sre.MathspeakUtil.computeNestingDepth_(a,b,c,d,e,f)}))};
-sre.MathspeakUtil.fractionNestingDepth=function(a){return sre.MathspeakUtil.getNestingDepth("fraction",a,["fraction"],sre.MathspeakUtil.nestingBarriers,{},sre.Messages.MS_FUNC.FRAC_NEST_DEPTH)};sre.MathspeakUtil.openingFractionVerbose=function(a){a=sre.MathspeakUtil.fractionNestingDepth(a);return Array(a+1).join(sre.Messages.MS.START)+sre.Messages.MS.FRAC_V};
-sre.MathspeakUtil.closingFractionVerbose=function(a){a=sre.MathspeakUtil.fractionNestingDepth(a);return Array(a+1).join(sre.Messages.MS.END)+sre.Messages.MS.FRAC_V};sre.MathspeakUtil.overFractionVerbose=function(a){a=sre.MathspeakUtil.fractionNestingDepth(a);return Array(a+1).join(sre.Messages.MS.FRAC_OVER).trim()};sre.MathspeakUtil.openingFractionBrief=function(a){a=sre.MathspeakUtil.fractionNestingDepth(a);return Array(a+1).join(sre.Messages.MS.START)+sre.Messages.MS.FRAC_B};
-sre.MathspeakUtil.closingFractionBrief=function(a){a=sre.MathspeakUtil.fractionNestingDepth(a);return Array(a+1).join(sre.Messages.MS.END)+sre.Messages.MS.FRAC_B};sre.MathspeakUtil.openingFractionSbrief=function(a){a=sre.MathspeakUtil.fractionNestingDepth(a);return 1===a?sre.Messages.MS.FRAC_S:sre.Messages.MS.NEST_FRAC+sre.Messages.MS_FUNC.RADICAL_NEST_DEPTH(a-1)+sre.Messages.MS.FRAC_S};
-sre.MathspeakUtil.closingFractionSbrief=function(a){a=sre.MathspeakUtil.fractionNestingDepth(a);return 1===a?sre.Messages.MS.ENDFRAC:sre.Messages.MS.NEST_FRAC+sre.Messages.MS_FUNC.RADICAL_NEST_DEPTH(a-1)+sre.Messages.MS.ENDFRAC};sre.MathspeakUtil.overFractionSbrief=function(a){a=sre.MathspeakUtil.fractionNestingDepth(a);return 1===a?sre.Messages.MS.FRAC_OVER:sre.Messages.MS.NEST_FRAC+sre.Messages.MS_FUNC.RADICAL_NEST_DEPTH(a-1)+sre.Messages.MS.OVER};sre.MathspeakUtil.onesNumbers=" one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen".split(" ");
-sre.MathspeakUtil.tensNumbers=" twenty thirty forty fifty sixty seventy eighty ninety".split(" ");sre.MathspeakUtil.largeNumbers=" thousand million billion trillion quadrillion quintillion sextillion septillion octillion nonillion decillion".split(" ");
-sre.MathspeakUtil.hundredsToWords=function(a){a%=1E3;var b;b=""+(sre.MathspeakUtil.onesNumbers[Math.floor(a/100)]?sre.MathspeakUtil.onesNumbers[Math.floor(a/100)]+"-hundred":"");(a%=100)&&(b=b+(b?"-":"")+(sre.MathspeakUtil.onesNumbers[a]||sre.MathspeakUtil.tensNumbers[Math.floor(a/10)]+"-"+sre.MathspeakUtil.onesNumbers[a%10]));return b};
-sre.MathspeakUtil.numberToWords=function(a){if(a>=Math.pow(10,36))return a.toString();for(var b=0,c="";0<a;)a%1E3&&(c=sre.MathspeakUtil.hundredsToWords(a%1E3)+(b?"-"+sre.MathspeakUtil.largeNumbers[b]+"-":"")+c),a=Math.floor(a/1E3),b++;return c};sre.MathspeakUtil.numberToOrdinal=function(a,b){if(2===a)return b?"halves":"half";var c=sre.MathspeakUtil.wordOrdinal(a);return b?c+"s":c};
-sre.MathspeakUtil.wordOrdinal=function(a){a=sre.MathspeakUtil.numberToWords(a);return a=a.match(/one$/)?a.slice(0,-3)+"first":a.match(/two$/)?a.slice(0,-3)+"second":a.match(/three$/)?a.slice(0,-5)+"third":a.match(/five$/)?a.slice(0,-4)+"fifth":a.match(/eight$/)?a.slice(0,-5)+"eighth":a.match(/nine$/)?a.slice(0,-4)+"ninth":a.match(/twelve$/)?a.slice(0,-5)+"twelfth":a.match(/ty$/)?a.slice(0,-2)+"tieth":a+"th"};
-sre.MathspeakUtil.simpleOrdinal=function(a){var b=a%100,c=a.toString();if(10<b&&20>b)return c+"th";switch(a%10){case 1:return c+"st";case 2:return c+"nd";case 3:return c+"rd";default:return c+"th"}};sre.MathspeakUtil.ordinalCounter=function(a,b){var c=0;return function(){return sre.MathspeakUtil.simpleOrdinal(++c)+" "+b}};
-sre.MathspeakUtil.convertVulgarFraction_=function(a){if(!a.childNodes||!a.childNodes[0]||!a.childNodes[0].childNodes||2>a.childNodes[0].childNodes.length||a.childNodes[0].childNodes[0].tagName!==sre.SemanticAttr.Type.NUMBER||a.childNodes[0].childNodes[0].getAttribute("role")!==sre.SemanticAttr.Role.INTEGER||a.childNodes[0].childNodes[1].tagName!==sre.SemanticAttr.Type.NUMBER||a.childNodes[0].childNodes[1].getAttribute("role")!==sre.SemanticAttr.Role.INTEGER)return{convertible:!1,content:a.textContent};
-var b=a.childNodes[0].childNodes[1].textContent;a=a.childNodes[0].childNodes[0].textContent;var c=Number(b),d=Number(a);return isNaN(c)||isNaN(d)?{convertible:!1,content:a+" "+sre.Messages.MS.FRAC_OVER+" "+b}:{convertible:!0,enumerator:d,denominator:c}};
-sre.MathspeakUtil.vulgarFraction=function(a,b){var c="undefined"===typeof b?"-":b,d=sre.MathspeakUtil.convertVulgarFraction_(a);return d.convertible&&d.enumerator&&d.denominator?sre.MathspeakUtil.numberToWords(d.enumerator)+c+sre.MathspeakUtil.numberToOrdinal(d.denominator,1!==d.enumerator):d.content||""};sre.MathspeakUtil.vulgarFractionSmall=function(a,b,c){var d=sre.MathspeakUtil.convertVulgarFraction_(a);return d.convertible?(a=d.enumerator,d=d.denominator,0<a&&a<b&&0<d&&d<c):!1};
-sre.MathspeakUtil.isSmallVulgarFraction=function(a){return sre.MathspeakUtil.vulgarFractionSmall(a,10,100)?[a]:[]};
-sre.MathspeakUtil.nestedSubSuper=function(a,b,c){for(;a.parentNode;){var d=a.parentNode,e=d.parentNode,f=a.getAttribute&&a.getAttribute("role");if(e.tagName===sre.Semantic.Type.SUBSCRIPT&&a===d.childNodes[1]||e.tagName===sre.Semantic.Type.TENSOR&&f&&(f===sre.Semantic.Role.LEFTSUB||f===sre.Semantic.Role.RIGHTSUB))b=c.sub+" "+b;if(e.tagName===sre.Semantic.Type.SUPERSCRIPT&&a===d.childNodes[1]||e.tagName===sre.Semantic.Type.TENSOR&&f&&(f===sre.Semantic.Role.LEFTSUPER||f===sre.Semantic.Role.RIGHTSUPER))b=
-c.sup+" "+b;a=e}return b.trim()};sre.MathspeakUtil.subscriptVerbose=function(a){return sre.MathspeakUtil.nestedSubSuper(a,sre.Messages.MS.SUBSCRIPT,{sup:sre.Messages.MS.SUPER,sub:sre.Messages.MS.SUB})};sre.MathspeakUtil.subscriptBrief=function(a){return sre.MathspeakUtil.nestedSubSuper(a,sre.Messages.MS.SUB,{sup:sre.Messages.MS.SUP,sub:sre.Messages.MS.SUB})};
-sre.MathspeakUtil.superscriptVerbose=function(a){return sre.MathspeakUtil.nestedSubSuper(a,sre.Messages.MS.SUPERSCRIPT,{sup:sre.Messages.MS.SUPER,sub:sre.Messages.MS.SUB})};sre.MathspeakUtil.superscriptBrief=function(a){return sre.MathspeakUtil.nestedSubSuper(a,sre.Messages.MS.SUP,{sup:sre.Messages.MS.SUP,sub:sre.Messages.MS.SUB})};
-sre.MathspeakUtil.baselineVerbose=function(a){return(a=sre.MathspeakUtil.nestedSubSuper(a,"",{sup:sre.Messages.MS.SUPER,sub:sre.Messages.MS.SUB}))?a.replace(new RegExp(sre.Messages.MS.SUB+"$"),sre.Messages.MS.SUBSCRIPT).replace(new RegExp(sre.Messages.MS.SUPER+"$"),sre.Messages.MS.SUPERSCRIPT):sre.Messages.MS.BASELINE};sre.MathspeakUtil.baselineBrief=function(a){return sre.MathspeakUtil.nestedSubSuper(a,"",{sup:sre.Messages.MS.SUP,sub:sre.Messages.MS.SUB})||sre.Messages.MS.BASE};
-sre.MathspeakUtil.radicalNestingDepth=function(a){return sre.MathspeakUtil.getNestingDepth("radical",a,["sqrt","root"],sre.MathspeakUtil.nestingBarriers,{})};sre.MathspeakUtil.nestedRadical=function(a,b,c){var d=sre.MathspeakUtil.radicalNestingDepth(a);c=(a=sre.MathspeakUtil.getRootIndex(a))?sre.Messages.MS_FUNC.COMBINE_ROOT_INDEX(c,a):c;return 1===d?c:b+sre.Messages.MS_FUNC.RADICAL_NEST_DEPTH(d-1)+c};
-sre.MathspeakUtil.getRootIndex=function(a){a="sqrt"===a.tagName?"2":sre.XpathUtil.evalXPath("children/*[1]",a)[0].textContent.trim();return sre.Messages.MS_ROOT_INDEX[a]||""};sre.MathspeakUtil.openingRadicalVerbose=function(a){return sre.MathspeakUtil.nestedRadical(a,sre.Messages.MS.NESTED,sre.Messages.MS.STARTROOT)};sre.MathspeakUtil.closingRadicalVerbose=function(a){return sre.MathspeakUtil.nestedRadical(a,sre.Messages.MS.NESTED,sre.Messages.MS.ENDROOT)};
-sre.MathspeakUtil.indexRadicalVerbose=function(a){return sre.MathspeakUtil.nestedRadical(a,sre.Messages.MS.NESTED,sre.Messages.MS.ROOTINDEX)};sre.MathspeakUtil.openingRadicalBrief=function(a){return sre.MathspeakUtil.nestedRadical(a,sre.Messages.MS.NEST_ROOT,sre.Messages.MS.STARTROOT)};sre.MathspeakUtil.closingRadicalBrief=function(a){return sre.MathspeakUtil.nestedRadical(a,sre.Messages.MS.NEST_ROOT,sre.Messages.MS.ENDROOT)};
-sre.MathspeakUtil.indexRadicalBrief=function(a){return sre.MathspeakUtil.nestedRadical(a,sre.Messages.MS.NEST_ROOT,sre.Messages.MS.ROOTINDEX)};sre.MathspeakUtil.openingRadicalSbrief=function(a){return sre.MathspeakUtil.nestedRadical(a,sre.Messages.MS.NEST_ROOT,sre.Messages.MS.ROOT)};sre.MathspeakUtil.indexRadicalSbrief=function(a){return sre.MathspeakUtil.nestedRadical(a,sre.Messages.MS.NEST_ROOT,sre.Messages.MS.INDEX)};
-sre.MathspeakUtil.underscoreNestingDepth=function(a){return sre.MathspeakUtil.getNestingDepth("underscore",a,["underscore"],sre.MathspeakUtil.nestingBarriers,{},function(a){return a.tagName&&a.tagName===sre.Semantic.Type.UNDERSCORE&&a.childNodes[0].childNodes[1].getAttribute("role")===sre.Semantic.Role.UNDERACCENT})};sre.MathspeakUtil.nestedUnderscore=function(a){a=sre.MathspeakUtil.underscoreNestingDepth(a);return Array(a).join(sre.Messages.MS.UNDER)+sre.Messages.MS.UNDERSCRIPT};
-sre.MathspeakUtil.overscoreNestingDepth=function(a){return sre.MathspeakUtil.getNestingDepth("overscore",a,["overscore"],sre.MathspeakUtil.nestingBarriers,{},function(a){return a.tagName&&a.tagName===sre.Semantic.Type.OVERSCORE&&a.childNodes[0].childNodes[1].getAttribute("role")===sre.Semantic.Role.OVERACCENT})};sre.MathspeakUtil.nestedOverscore=function(a){a=sre.MathspeakUtil.overscoreNestingDepth(a);return Array(a).join(sre.Messages.MS.OVER)+sre.Messages.MS.OVERSCRIPT};
-sre.MathspeakUtil.determinantIsSimple=function(a){if(a.tagName!==sre.Semantic.Type.MATRIX||a.getAttribute("role")!==sre.Semantic.Role.DETERMINANT)return[];for(var b=sre.XpathUtil.evalXPath("children/row/children/cell/children/*",a),c=0,d;d=b[c];c++)if(d.tagName!==sre.Semantic.Type.NUMBER){if(d.tagName===sre.Semantic.Type.IDENTIFIER&&(d=d.getAttribute("role"),d===sre.Semantic.Role.LATINLETTER||d===sre.Semantic.Role.GREEKLETTER||d===sre.Semantic.Role.OTHERLETTER))continue;return[]}return[a]};
-sre.MathspeakUtil.generateBaselineConstraint=function(){for(var a=function(a){return a.map(function(a){return"ancestor::"+a})},b="not("+a(["subscript","superscript","tensor"]).join(" or ")+")",c=a(["relseq","multrel"]),a=a(["fraction","punctuation","fenced","sqrt","root"]),d=[],e=0,f;f=a[e];e++)d=d.concat(c.map(function(a){return f+"/"+a}));c="not("+d.join(" | ")+")";return["ancestor::*/following-sibling::*",b,c].join(" and ")};
-sre.MathspeakUtil.removeParens=function(a){if(!a.childNodes.length||!a.childNodes[0].childNodes.length||!a.childNodes[0].childNodes[0].childNodes.length)return"";a=a.childNodes[0].childNodes[0].childNodes[0].textContent;return a.match(/^\(.+\)$/)?a.slice(1,-1):a};sre.Locale={};sre.Locale.nestingToString=function(a){switch(a){case 1:return"";case 2:return sre.Messages.MS.TWICE;default:return a.toString()}};sre.Locale.vulgarNestingDepth=function(a){return!!sre.MathspeakUtil.isSmallVulgarFraction(a).length};sre.Locale.combinePostfixIndex=function(a,b){return a===sre.Messages.MS.ROOTINDEX||a===sre.Messages.MS.INDEX?a:a+" "+b};sre.Locale.localFont=function(a){return sre.Messages.FONT[a]||a};sre.Grammar.getInstance().setCorrection("localFont",sre.Locale.localFont);
-sre.Locale.localRole=function(a){return sre.Messages.ROLE[a]||a};sre.Grammar.getInstance().setCorrection("localRole",sre.Locale.localRole);sre.Locale.localEnclose=function(a){return sre.Messages.ENCLOSE[a]||a};sre.Grammar.getInstance().setCorrection("localEnclose",sre.Locale.localEnclose);sre.Locale.en={MS:{START:"Start",FRAC_V:"Fraction",FRAC_B:"Frac",FRAC_S:"Frac",END:"End",FRAC_OVER:"Over",TWICE:"Twice",NEST_FRAC:"Nest",ENDFRAC:"EndFrac",SUPER:"Super",SUB:"Sub",SUP:"Sup",SUPERSCRIPT:"Superscript",SUBSCRIPT:"Subscript",BASELINE:"Baseline",BASE:"Base",NESTED:"Nested",NEST_ROOT:"Nest",STARTROOT:"StartRoot",ENDROOT:"EndRoot",ROOTINDEX:"RootIndex",ROOT:"Root",INDEX:"Index",UNDER:"Under",UNDERSCRIPT:"Underscript",OVER:"Over",OVERSCRIPT:"Overscript"},MS_FUNC:{FRAC_NEST_DEPTH:sre.Locale.vulgarNestingDepth,
-RADICAL_NEST_DEPTH:sre.Locale.nestingToString,COMBINE_ROOT_INDEX:function(a,b){return a}},MS_ROOT_INDEX:{},FONT:{},ROLE:{addition:"addition",multiplication:"multiplication",subtraction:"subtraction",division:"division",equality:"equality",inequality:"inequality",element:"element",arrow:"arrow",determinant:"determinant",rowvector:"row vector",binomial:"binomial",squarematrix:"square matrix",multiline:"multiple lines",matrix:"matrix",vector:"vector",cases:"case statement",table:"table",unknown:"unknown"},
-ENCLOSE:{longdiv:"long division",actuarial:"actuarial symbol",radical:"square root",box:"box",roundedbox:"rounded box",circle:"circle",left:"left vertical-line",right:"right vertical-line",top:"overbar",bottom:"underbar",updiagonalstrike:"crossout",downdiagonalstrike:"crossout",verticalstrike:"vertical strikeout",horizontalstrike:"crossout",madruwb:"Arabic factorial symbol",updiagonalarrow:"diagonal arrow",phasorangle:"phasor angle",unknown:"long division"},NAVIGATE:{COLLAPSIBLE:"collapsible",EXPANDABLE:"expandable",
-LEVEL:"Level"}};sre.Locale.es={MS:{START:"empezar ",FRAC_V:"fracci\u00f3n",FRAC_B:"frac",FRAC_S:"frac",END:"finalizar ",FRAC_OVER:"entre ",TWICE:"",NEST_FRAC:"",ENDFRAC:"",SUPER:"super",SUB:"sub",SUP:"sup",SUPERSCRIPT:"super\u00edndice",SUBSCRIPT:"sub\u00edndice",BASELINE:"l\u00ednea base",BASE:"",NESTED:"",NEST_ROOT:"",STARTROOT:"empezar ra\u00edz",ENDROOT:"finalizar ra\u00edz",ROOTINDEX:"\u00edndice de ra\u00edz",ROOT:"ra\u00edz",INDEX:"",UNDER:"bajo",UNDERSCRIPT:"bajo\u00edndice",OVER:"sobre",OVERSCRIPT:"sobre\u00edndice"},
-MS_FUNC:{FRAC_NEST_DEPTH:function(a){return!1},RADICAL_NEST_DEPTH:function(a){return""},COMBINE_ROOT_INDEX:sre.Locale.combinePostfixIndex},MS_ROOT_INDEX:{2:"cuadrada",3:"c\u00fabica",4:"a la cuarta",5:"a la quinta",6:"a la sexta",7:"a la s\u00e9ptima",8:"a la octava",9:"a la novena",10:"a la d\u00e9cima"},FONT:{bold:"negrita","bold-fraktur":"negrita Fraktur","bold-italic":"negrita cursiva","bold-script":"negrita script",caligraphic:"caligr\u00e1fica","caligraphic-bold":"caligr\u00e1fica negrita",
-"double-struck":"negrita de pizarra","double-struck-italic":"negrita de pizarra cursiva",fraktur:"Fraktur",italic:"cursiva",monospace:"monoespacio",normal:"normal",oldstyle:"estilo antiguo","oldstyle-bold":"estilo antiguo negrita",script:"script","sans-serif":"sans-serif","sans-serif-italic":"sans-serif cursiva","sans-serif-bold":"sans-serif negrita","sans-serif-bold-italic":"sans-serif negrita cursiva",unknown:"desconocida"},ROLE:{addition:"adici\u00f3n",multiplication:"multiplicaci\u00f3n",subtraction:"resta",
-division:"divisi\u00f3n",equality:"igualdad",inequality:"desigualdad",element:"elemento",arrow:"flecha",determinant:"determinante",rowvector:"fila vector",binomial:"binomial",squarematrix:"matriz cuadrada",multiline:"l\u00edneas m\u00faltiples",matrix:"matriz",vector:"vector",cases:"declaraci\u00f3n de caso",table:"mesa",unknown:"desconocida"},ENCLOSE:{longdiv:"divisi\u00f3n larga",actuarial:"s\u00edmbolo actuarial",radical:"ra\u00edz cuadrada",box:"caja",roundedbox:"caja redondeada",circle:"c\u00edrculo",
-left:"barra vertical izquierda",right:"barra vertical derecha",top:"barra",bottom:"subbarra",updiagonalstrike:"tachadura",downdiagonalstrike:"tachadura",verticalstrike:"ponchado vertical",horizontalstrike:"cruce",madruwb:"s\u00edmbolo factorial \u00e1rabe",updiagonalarrow:"flecha diagonal",phasorangle:"\u00e1ngulo de fasores",unknown:"divisi\u00f3n larga"},NAVIGATE:{COLLAPSIBLE:"plegable",EXPANDABLE:"ampliable",LEVEL:"nivel"}};sre.L10n={};sre.L10n.setLocale=function(){var a=sre.L10n.getLocale();if(a)for(var b in a)sre.Messages[b]=a[b]};sre.L10n.getLocale=function(){return sre.Locale[sre.Engine.getInstance().locale]||sre.Locale.en};sre.AudioUtil={};sre.AudioUtil.mergePause=function(a,b,c){return a?{pause:sre.AudioUtil.mergePause_(a.pause,b.pause,c)}:b};sre.AudioUtil.mergePause_=function(a,b,c){return(c||function(c,e){return"number"===typeof c||"number"===typeof e?c+e:"number"===typeof c?e:"number"===typeof e?c:[a,b].sort()[0]}).call(null,a,b)};sre.AudioUtil.mergeMarkup=function(a,b){delete a.open;b.close.forEach(function(b){delete a[b]});b.open.forEach(function(c){a[c]=b[c]});var c=Object.keys(a);a.open=c};
-sre.AudioUtil.sortClose=function(a,b){if(1>=a.length)return a;for(var c=[],d=0,e;e=b[d],a.length;d++)e.close&&e.close.length&&e.close.forEach(function(b){var d=a.indexOf(b);-1!==d&&(c.unshift(b),a.splice(d,1))});return c};sre.AudioUtil.PersonalityRanges_={};sre.AudioUtil.LastOpen_=[];
-sre.AudioUtil.personalityMarkup=function(a){sre.AudioUtil.PersonalityRanges_={};sre.AudioUtil.LastOpen_=[];for(var b=[],c={},d=0,e;e=a[d];d++){var f=null,g=e.descriptionString(),h=e.personality;e=h[sre.Engine.personalityProps.JOIN];delete h[sre.Engine.personalityProps.JOIN];"undefined"!==typeof h[sre.Engine.personalityProps.PAUSE]&&(f={},f[sre.Engine.personalityProps.PAUSE]=h[sre.Engine.personalityProps.PAUSE],delete h[sre.Engine.personalityProps.PAUSE]);h=sre.AudioUtil.personalityDiff_(h,c);sre.AudioUtil.appendMarkup_(b,
-g,h,e,f,!0)}b=b.concat(sre.AudioUtil.finaliseMarkup_());return b=sre.AudioUtil.simplifyMarkup_(b)};
-sre.AudioUtil.appendElement_=function(a,b){var c=a[a.length-1];if(c)if(sre.AudioUtil.isStringElement(b)&&sre.AudioUtil.isStringElement(c))if("undefined"===typeof c.join)c.string=c.string.concat(b.string);else{var d=c.string.pop(),e=b.string.shift();c.string.push(d+c.join+e);c.string=c.string.concat(b.string);c.join=b.join}else sre.AudioUtil.isPauseElement(b)&&sre.AudioUtil.isPauseElement(c)?c.pause=sre.AudioUtil.mergePause_(c.pause,b.pause):a.push(b);else a.push(b)};
-sre.AudioUtil.simplifyMarkup_=function(a){for(var b={},c=[],d=0,e;e=a[d];d++)if(sre.AudioUtil.isMarkupElement(e))if(!e.close||1!==e.close.length||e.open.length)sre.AudioUtil.copyValues_(e,b),c.push(e);else{var f=a[d+1];if(!f||sre.AudioUtil.isStringElement(f))sre.AudioUtil.copyValues_(e,b),c.push(e);else{var g=sre.AudioUtil.isPauseElement(f)?f:null;g&&(f=a[d+2]);f&&sre.AudioUtil.isMarkupElement(f)&&f.open[0]===e.close[0]&&!f.close.length&&f[f.open[0]]===b[f.open[0]]?g?(sre.AudioUtil.appendElement_(c,
-g),d+=2):d+=1:(sre.AudioUtil.copyValues_(e,b),c.push(e))}}else sre.AudioUtil.appendElement_(c,e);return c};sre.AudioUtil.copyValues_=function(a,b){a.rate&&(b.rate=a.rate);a.pitch&&(b.pitch=a.pitch);a.volume&&(b.volume=a.volume)};sre.AudioUtil.finaliseMarkup_=function(){for(var a=[],b=sre.AudioUtil.LastOpen_.length-1;0<=b;b--){var c=sre.AudioUtil.LastOpen_[b];if(c.length){for(var d={open:[],close:[]},e=0;e<c.length;e++){var f=c[e];d.close.push(f);d[f]=0}a.push(d)}}return a};
-sre.AudioUtil.isMarkupElement=function(a){return"object"===typeof a&&a.open};sre.AudioUtil.isPauseElement=function(a){return"object"===typeof a&&1===Object.keys(a).length&&Object.keys(a)[0]===sre.Engine.personalityProps.PAUSE};sre.AudioUtil.isStringElement=function(a){var b=Object.keys(a);return"object"===typeof a&&(1===b.length&&"string"===b[0]||2===b.length&&("string"===b[0]&&"join"===b[1]||"string"===b[1]&&"join"===b[0]))};
-sre.AudioUtil.appendMarkup_=function(a,b,c,d,e,f){if(f){if(f=a[a.length-1])var g=f[sre.Engine.personalityProps.JOIN];if(f&&!b&&e&&sre.AudioUtil.isPauseElement(f)){var h=sre.Engine.personalityProps.PAUSE;f[h]=sre.AudioUtil.mergePause_(f[h],e[h]);e=null}f&&b&&0===Object.keys(c).length&&sre.AudioUtil.isStringElement(f)&&("undefined"!==typeof g&&(b=f.string.pop()+g+b),f.string.push(b),b="",f[sre.Engine.personalityProps.JOIN]=d)}0!==Object.keys(c).length&&a.push(c);b&&a.push({string:[b],join:d});e&&a.push(e)};
-sre.AudioUtil.personalityDiff_=function(a,b){if(!b)return a;var c={},d;for(d in sre.Engine.personalityProps){var e=sre.Engine.personalityProps[d],f=a[e],g=b[e];if(!(!f&&!g||f&&g&&f===g)){var h=f||0;sre.AudioUtil.isMarkupElement(c)||(c.open=[],c.close=[]);f||c.close.push(e);g||c.open.push(e);g&&f&&(c.close.push(e),c.open.push(e));b[e]=h;c[e]=h;sre.AudioUtil.PersonalityRanges_[e]?sre.AudioUtil.PersonalityRanges_[e].push(h):sre.AudioUtil.PersonalityRanges_[e]=[h]}}if(sre.AudioUtil.isMarkupElement(c)){for(d=
-c.close.slice();0<d.length;)if(e=sre.AudioUtil.LastOpen_.pop(),f=sre.BaseUtil.setdifference(e,d),d=sre.BaseUtil.setdifference(d,e),e=f,0===d.length)0!==e.length&&sre.AudioUtil.LastOpen_.push(e);else if(0!==e.length)for(c.close=c.close.concat(e),c.open=c.open.concat(e),f=0;g=e[f];f++)c[g]=b[g];sre.AudioUtil.LastOpen_.push(c.open)}return c};sre.AudioRenderer=function(){};sre.AudioRenderer.prototype.setSeparator=function(a){};sre.AudioRenderer.prototype.getSeparator=function(){};sre.AudioRenderer.prototype.markup=function(a){};sre.AudioRenderer.prototype.error=function(a){};sre.AudioRenderer.prototype.merge=function(a){};sre.AbstractAudioRenderer=function(){this.separator_=" "};sre.AbstractAudioRenderer.prototype.setSeparator=function(a){this.separator_=a};sre.AbstractAudioRenderer.prototype.getSeparator=function(){return this.separator_};sre.AbstractAudioRenderer.prototype.markup=goog.abstractMethod;sre.AbstractAudioRenderer.prototype.error=function(a){return null};sre.AbstractAudioRenderer.prototype.merge=function(a){return a.join(" ")};sre.MarkupRenderer=function(){sre.AbstractAudioRenderer.call(this);this.scaleFunction_=null};goog.inherits(sre.MarkupRenderer,sre.AbstractAudioRenderer);sre.MarkupRenderer.prototype.setScaleFunction=function(a,b,c,d,e){var f=e||0;this.scaleFunction_=function(e){e=(e-a)/(b-a);return+(Math.round(c*(1-e)+d*e+"e+"+f)+"e-"+f)}};sre.MarkupRenderer.prototype.applyScaleFunction=function(a){return this.scaleFunction_?this.scaleFunction_(a):a};sre.MarkupRenderer.prototype.pause=goog.abstractMethod;
-sre.MarkupRenderer.prototype.prosodyElement=goog.abstractMethod;sre.AcssRenderer=function(){sre.MarkupRenderer.call(this)};goog.inherits(sre.AcssRenderer,sre.MarkupRenderer);
-sre.AcssRenderer.prototype.markup=function(a){this.setScaleFunction(-2,2,0,10,0);a=sre.AudioUtil.personalityMarkup(a);for(var b=[],c={open:[]},d=null,e=!1,f=0,g;g=a[f];f++)if(sre.AudioUtil.isMarkupElement(g))sre.AudioUtil.mergeMarkup(c,g);else if(sre.AudioUtil.isPauseElement(g))e&&(d=sre.AudioUtil.mergePause(d,g,Math.max));else{g='"'+g.string.join(this.getSeparator())+'"';e=!0;d&&(b.push(this.pause(d)),d=null);var h=this.prosody_(c);b.push(h?"(text ("+h+") "+g+")":g)}return"(exp "+b.join(" ")+")"};
-sre.AcssRenderer.prototype.merge=function(a){return"(exp "+a.map(function(a){return a.replace(/^\(exp /,"").replace(/\)$/,"")}).join(" ")+")"};sre.AcssRenderer.prototype.error=function(a){return'(error "'+a+'")'};sre.AcssRenderer.prototype.prosody_=function(a){for(var b=a.open,c=[],d=0,e;e=b[d];d++)c.push(this.prosodyElement(e,a[e]));return c.join(" ")};
-sre.AcssRenderer.prototype.prosodyElement=function(a,b){b=this.applyScaleFunction(b);switch(a){case sre.Engine.personalityProps.RATE:return"(richness . "+b+")";case sre.Engine.personalityProps.PITCH:return"(average-pitch . "+b+")";case sre.Engine.personalityProps.VOLUME:return"(stress . "+b+")"}return"(value . "+b+")"};sre.AcssRenderer.prototype.pause=function(a){return"(pause . "+a[sre.Engine.personalityProps.PAUSE]+")"};sre.PunctuationRenderer=function(){sre.AbstractAudioRenderer.call(this)};goog.inherits(sre.PunctuationRenderer,sre.AbstractAudioRenderer);
-sre.PunctuationRenderer.prototype.markup=function(a){a=sre.AudioUtil.personalityMarkup(a);for(var b="",c=null,d=!1,e=0,f;f=a[e];e++)sre.AudioUtil.isMarkupElement(f)||(sre.AudioUtil.isPauseElement(f)?d&&(c=sre.AudioUtil.mergePause(c,f,Math.max)):(c&&(b+=this.pause(c[sre.Engine.personalityProps.PAUSE]),c=null),b+=(d?this.getSeparator():"")+f.string.join(this.getSeparator()),d=!0));return b};sre.PunctuationRenderer.PAUSE_PUNCTUATION_={"short":",",medium:";","long":"."};
-sre.PunctuationRenderer.prototype.pause=function(a){return sre.PunctuationRenderer.PAUSE_PUNCTUATION_["number"===typeof a?250>=a?"short":500>=a?"medium":"long":a]||""};sre.XmlRenderer=function(){sre.MarkupRenderer.call(this)};goog.inherits(sre.XmlRenderer,sre.MarkupRenderer);
-sre.XmlRenderer.prototype.markup=function(a){this.setScaleFunction(-2,2,-100,100,2);a=sre.AudioUtil.personalityMarkup(a);for(var b=[],c=[],d=0,e;e=a[d];d++)if(e.string)b.push(e.string.join(this.getSeparator()));else if(sre.AudioUtil.isPauseElement(e))b.push(this.pause(e));else{if(e.close.length)for(var f=0;f<e.close.length;f++){var g=c.pop();if(-1===e.close.indexOf(g))throw Error("Unknown closing markup element: "+g);b.push(this.closeTag(g))}e.open.length&&sre.AudioUtil.sortClose(e.open.slice(),a.slice(d+
-1)).forEach(goog.bind(function(a){b.push(this.prosodyElement(a,e[a]));c.push(a)},this))}return b.join(" ")};sre.XmlRenderer.prototype.closeTag=goog.abstractMethod;sre.SableRenderer=function(){sre.XmlRenderer.call(this)};goog.inherits(sre.SableRenderer,sre.XmlRenderer);sre.SableRenderer.prototype.pause=function(a){return'<BREAK MSEC="'+a[sre.Engine.personalityProps.PAUSE]+'"/>'};
-sre.SableRenderer.prototype.prosodyElement=function(a,b){b=this.applyScaleFunction(b);switch(a){case sre.Engine.personalityProps.PITCH:return'<PITCH RANGE="'+b+'%">';case sre.Engine.personalityProps.RATE:return'<RATE SPEED="'+b+'%">';case sre.Engine.personalityProps.VOLUME:return'<VOLUME LEVEL="'+b+'%">';default:return"<"+a.toUpperCase()+' VALUE="'+b+'">'}};sre.SableRenderer.prototype.closeTag=function(a){return"</"+a.toUpperCase()+">"};sre.SsmlRenderer=function(){sre.XmlRenderer.call(this)};goog.inherits(sre.SsmlRenderer,sre.XmlRenderer);sre.SsmlRenderer.prototype.pause=function(a){return'<BREAK TIME="'+a[sre.Engine.personalityProps.PAUSE]+'ms"/>'};sre.SsmlRenderer.prototype.prosodyElement=function(a,b){b=this.applyScaleFunction(b);var c=0>b?b.toString():"+"+b;return"<PROSODY "+a.toUpperCase()+'="'+c+(a===sre.Engine.personalityProps.VOLUME?">":'%">')};sre.SsmlRenderer.prototype.closeTag=function(a){return"</PROSODY>"};sre.StringRenderer=function(){sre.AbstractAudioRenderer.call(this)};goog.inherits(sre.StringRenderer,sre.AbstractAudioRenderer);sre.StringRenderer.prototype.markup=function(a){var b="";a=a.filter(function(a){return a.descriptionString()});if(!a.length)return b;for(var c=0;c<a.length-1;c++)var d=a[c],e=d.personality[sre.Engine.personalityProps.JOIN],e="undefined"===typeof e?this.getSeparator():e,b=b+(d.descriptionString()+e);return b+=a[c].descriptionString()};sre.AuralRendering=function(){};goog.addSingletonGetter(sre.AuralRendering);sre.AuralRendering.prototype.setSeparator=function(a){var b=sre.AuralRendering.rendererMapping_[sre.Engine.getInstance().markup];b&&b.setSeparator(a)};sre.AuralRendering.prototype.getSeparator=function(){var a=sre.AuralRendering.rendererMapping_[sre.Engine.getInstance().markup];return a?a.getSeparator():""};
-sre.AuralRendering.prototype.markup=function(a){var b=sre.AuralRendering.rendererMapping_[sre.Engine.getInstance().markup];return b?b.markup(a):""};sre.AuralRendering.prototype.merge=function(a){var b=sre.AuralRendering.rendererMapping_[sre.Engine.getInstance().markup];return b?b.merge(a):a.join()};sre.AuralRendering.prototype.error=function(a){var b=sre.AuralRendering.rendererMapping_[sre.Engine.getInstance().markup];return b?b.error(a):""};
-sre.AuralRendering.registerRenderer=function(a,b){sre.AuralRendering.rendererMapping_[a]=b};sre.AuralRendering.rendererMapping_={};sre.AuralRendering.registerRenderer(sre.Engine.Markup.NONE,new sre.StringRenderer);sre.AuralRendering.registerRenderer(sre.Engine.Markup.PUNCTUATION,new sre.PunctuationRenderer);sre.AuralRendering.registerRenderer(sre.Engine.Markup.ACSS,new sre.AcssRenderer);sre.AuralRendering.registerRenderer(sre.Engine.Markup.SABLE,new sre.SableRenderer);
-sre.AuralRendering.xmlInstance=new sre.SsmlRenderer;sre.AuralRendering.registerRenderer(sre.Engine.Markup.VOICEXML,sre.AuralRendering.xmlInstance);sre.AuralRendering.registerRenderer(sre.Engine.Markup.SSML,sre.AuralRendering.xmlInstance);sre.Debugger=function(){this.isActive_=!1;this.outputFunction_=console.log;this.stream_=null};goog.addSingletonGetter(sre.Debugger);sre.Debugger.prototype.init=function(a){a&&this.startDebugFile_(a);this.isActive_=!0};
-sre.Debugger.prototype.startDebugFile_=function(a){this.stream_=sre.SystemExternal.fs.createWriteStream(a);this.outputFunction_=goog.bind(function(a){var b=Array.prototype.slice.call(arguments,0);this.stream_.write(b.join(" "));this.stream_.write("\n")},this);this.stream_.on("error",goog.bind(function(a){console.log("Invalid log file. Debug information sent to console.");this.outputFunction_=console.log},this));this.stream_.on("finish",function(){console.log("Finalizing debug file.")})};
-sre.Debugger.prototype.output_=function(a){this.outputFunction_.apply(console.log===this.outputFunction_?console:this.outputFunction_,["Speech Rule Engine Debugger:"].concat(a))};sre.Debugger.prototype.output=function(a){this.isActive_&&this.output_(Array.prototype.slice.call(arguments,0))};sre.Debugger.prototype.generateOutput=function(a){this.isActive_&&this.output_(a.apply(a,[]))};sre.Debugger.prototype.exit=function(a){this.isActive_&&this.stream_&&this.stream_.end("","",a||function(){})};sre.EnrichCase=function(){};sre.EnrichCase.prototype.getMathml=function(){};sre.AbstractEnrichCase=function(a){this.semantic=a};sre.AbstractEnrichCase.prototype.getMathml=goog.abstractMethod;sre.AbstractEnrichCase.test=goog.abstractMethod;sre.EnrichCaseFactory=function(){};sre.EnrichCaseFactory.getEmbellishedCase=function(a){return new sre.EnrichCaseFactory.embellishedCase(a)};sre.EnrichCaseFactory.cases=[];sre.EnrichCaseFactory.getCase=function(a){for(var b=0,c;c=sre.EnrichCaseFactory.cases[b];b++)if(c.test(a))return new c.constr(a);return null};sre.SemanticSkeleton=function(a){this.array=a=0===a?a:a||[];this.levelsMap=this.parents=null};sre.SemanticSkeleton.prototype.populate=function(){this.parents&&this.levelsMap||(this.parents={},this.levelsMap={},this.populate_(this.array,this.array,[]))};
-sre.SemanticSkeleton.prototype.populate_=function(a,b,c){if(sre.SemanticSkeleton.simpleCollapseStructure(a))this.levelsMap[a]=b,this.parents[a]=a===c[0]?c.slice(1):c;else{b=sre.SemanticSkeleton.contentCollapseStructure(a)?a.slice(1):a;c=[b[0]].concat(c);for(var d=0,e=b.length;d<e;d++)this.populate_(b[d],a,c)}};sre.SemanticSkeleton.prototype.toString=function(){return sre.SemanticSkeleton.makeSexp_(this.array)};
-sre.SemanticSkeleton.makeSexp_=function(a){return sre.SemanticSkeleton.simpleCollapseStructure(a)?a.toString():sre.SemanticSkeleton.contentCollapseStructure(a)?"(c "+a.slice(1).map(sre.SemanticSkeleton.makeSexp_).join(" ")+")":"("+a.map(sre.SemanticSkeleton.makeSexp_).join(" ")+")"};sre.SemanticSkeleton.fromTree=function(a){return sre.SemanticSkeleton.fromNode(a.root)};sre.SemanticSkeleton.fromNode=function(a){return new sre.SemanticSkeleton(sre.SemanticSkeleton.fromNode_(a))};
-sre.SemanticSkeleton.fromString=function(a){return new sre.SemanticSkeleton(sre.SemanticSkeleton.fromString_(a))};sre.SemanticSkeleton.fromString_=function(a){a=a.replace(/\(/g,"[");a=a.replace(/\)/g,"]");a=a.replace(/ /g,",");a=a.replace(/c/g,'"c"');return JSON.parse(a)};
-sre.SemanticSkeleton.fromNode_=function(a){if(!a)return[];var b=a.contentNodes;if(b.length){var c=b.map(sre.SemanticSkeleton.fromNode_);c.unshift("c")}var d=a.childNodes;if(!d.length)return b.length?[a.id,c]:a.id;d=d.map(sre.SemanticSkeleton.fromNode_);b.length&&d.unshift(c);d.unshift(a.id);return d};sre.SemanticSkeleton.simpleCollapseStructure=function(a){return"number"===typeof a};
-sre.SemanticSkeleton.contentCollapseStructure=function(a){return!!a&&!sre.SemanticSkeleton.simpleCollapseStructure(a)&&"c"===a[0]};sre.SemanticSkeleton.interleaveIds=function(a,b){return sre.BaseUtil.interleaveLists(sre.SemanticSkeleton.collapsedLeafs(a),sre.SemanticSkeleton.collapsedLeafs(b))};
-sre.SemanticSkeleton.collapsedLeafs=function(a){var b=function(a){return sre.SemanticSkeleton.simpleCollapseStructure(a)?[a]:sre.SemanticSkeleton.contentCollapseStructure(a[1])?a.slice(2):a.slice(1)};return Array.prototype.slice.call(arguments,0).reduce(function(a,d){return a.concat(b(d))},[])};sre.EnrichMathml={};sre.EnrichMathml.Error=function(a){Error.call(this);this.message=a||"";this.name="MathML Enrichment Error"};goog.inherits(sre.EnrichMathml.Error,Error);sre.EnrichMathml.SETTINGS={collapsed:!0,implicit:!0};sre.EnrichMathml.ATTRIBUTE_PREFIX_="data-semantic-";
-sre.EnrichMathml.Attribute={ADDED:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"added",ALTERNATIVE:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"alternative",CHILDREN:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"children",COLLAPSED:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"collapsed",CONTENT:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"content",EMBELLISHED:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"embellished",FENCEPOINTER:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"fencepointer",FONT:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"font",ID:sre.EnrichMathml.ATTRIBUTE_PREFIX_+
-"id",ANNOTATION:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"annotation",OPERATOR:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"operator",PARENT:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"parent",PREFIX:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"prefix",ROLE:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"role",SPEECH:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"speech",TYPE:sre.EnrichMathml.ATTRIBUTE_PREFIX_+"type"};
-sre.EnrichMathml.enrich=function(a,b){var c=a.cloneNode(!0);sre.EnrichMathml.walkTree(b.root);sre.Debugger.getInstance().generateOutput(function(){sre.EnrichMathml.formattedOutput(c,a,b,!0);return[]});return a};
-sre.EnrichMathml.walkTree=function(a){var b=sre.EnrichCaseFactory.getCase(a);if(b)return b=b.getMathml(),sre.EnrichMathml.ascendNewNode(b);if(1===a.mathml.length)return sre.Debugger.getInstance().output("Walktree Case 0"),b=a.mathml[0],sre.EnrichMathml.setAttributes(b,a),sre.EnrichMathml.ascendNewNode(b);var b=a.contentNodes.map(sre.EnrichMathml.cloneContentNode),c=a.childNodes.map(sre.EnrichMathml.walkTree),c=sre.EnrichMathml.combineContentChildren_(a,b,c),b=a.mathmlTree;if(null===b)sre.Debugger.getInstance().output("Walktree Case 1"),
-b=sre.EnrichMathml.introduceNewLayer(c);else{var d=sre.EnrichMathml.attachedElement_(c);sre.Debugger.getInstance().output("Walktree Case 2");d?(sre.Debugger.getInstance().output("Walktree Case 2.1"),b=d.parentNode):(sre.Debugger.getInstance().output("Walktree Case 2.2"),b=sre.EnrichMathml.getInnerNode(b))}b=sre.EnrichMathml.rewriteMfenced(b);sre.EnrichMathml.mergeChildren_(b,c);sre.EnrichMathml.setAttributes(b,a);return sre.EnrichMathml.ascendNewNode(b)};
-sre.EnrichMathml.introduceNewLayer=function(a){var b=sre.EnrichMathml.mathmlLca_(a),c=b.node,d=b.type;d===sre.EnrichMathml.lcaType.VALID&&sre.SemanticUtil.hasEmptyTag(c)||(sre.Debugger.getInstance().output("Walktree Case 1.1"),c=sre.DomUtil.createElement("mrow"),d===sre.EnrichMathml.lcaType.PRUNED?(sre.Debugger.getInstance().output("Walktree Case 1.1.0"),c=sre.EnrichMathml.introduceLayerAboveLca(c,b.node,a)):a[0]&&(sre.Debugger.getInstance().output("Walktree Case 1.1.1"),b=sre.EnrichMathml.attachedElement_(a),
-a=sre.EnrichMathml.childrenSubset_(b.parentNode,a),sre.DomUtil.replaceNode(b,c),a.forEach(function(a){c.appendChild(a)})));return c};
-sre.EnrichMathml.introduceLayerAboveLca=function(a,b,c){var d=sre.EnrichMathml.descendNode_(b);if(sre.SemanticUtil.hasMathTag(d)){sre.Debugger.getInstance().output("Walktree Case 1.1.0.0");sre.EnrichMathml.moveSemanticAttributes_(d,a);sre.DomUtil.toArray(d.childNodes).forEach(function(b){a.appendChild(b)});var e=a;a=d;d=e}b=c.indexOf(b);c[b]=d;sre.DomUtil.replaceNode(d,a);a.appendChild(d);c.forEach(function(b){a.appendChild(b)});return a};
-sre.EnrichMathml.moveSemanticAttributes_=function(a,b){for(var c in sre.EnrichMathml.Attribute){var d=sre.EnrichMathml.Attribute[c];a.hasAttribute(d)&&(b.setAttribute(d,a.getAttribute(d)),a.removeAttribute(d))}};sre.EnrichMathml.childrenSubset_=function(a,b){var c=sre.DomUtil.toArray(a.childNodes),d=Infinity,e=-Infinity;b.forEach(function(a){a=c.indexOf(a);-1!==a&&(d=Math.min(d,a),e=Math.max(e,a))});return c.slice(d,e+1)};
-sre.EnrichMathml.mergeChildren_=function(a,b){var c=a.childNodes;if(c.length)for(var d=0;b.length;)c[d]===b[0]||sre.EnrichMathml.functionApplication_(c[d],b[0])?(b.shift(),d++):c[d]&&-1===b.indexOf(c[d])?d++:(sre.EnrichMathml.isDescendant_(b[0],a)||a.insertBefore(b[0],c[d]||null),b.shift());else b.forEach(function(b){a.appendChild(b)})};sre.EnrichMathml.isDescendant_=function(a,b){if(!a)return!1;do if(a=a.parentNode,a===b)return!0;while(a);return!1};
-sre.EnrichMathml.functionApplication_=function(a,b){var c=sre.SemanticAttr.functionApplication();return a&&b&&a.textContent&&b.textContent&&a.textContent===c&&b.textContent===c&&"true"===b.getAttribute(sre.EnrichMathml.Attribute.ADDED)?(sre.DomUtil.replaceNode(a,b),!0):!1};sre.EnrichMathml.lcaType={VALID:"valid",INVALID:"invalid",PRUNED:"pruned"};
-sre.EnrichMathml.mathmlLca_=function(a){var b=sre.EnrichMathml.attachedElement_(a);if(!b)return{type:sre.EnrichMathml.lcaType.INVALID,node:null};var c=sre.EnrichMathml.attachedElement_(a.slice().reverse());if(b===c)return{type:sre.EnrichMathml.lcaType.VALID,node:b};var b=sre.EnrichMathml.pathToRoot_(b),d=sre.EnrichMathml.prunePath_(b,a);a=sre.EnrichMathml.pathToRoot_(c,function(a){return-1!==d.indexOf(a)});var c=a[0],e=d.indexOf(c);return-1===e?{type:sre.EnrichMathml.lcaType.INVALID,node:null}:{type:d.length!==
-b.length?sre.EnrichMathml.lcaType.PRUNED:sre.EnrichMathml.validLca_(d[e+1],a[1])?sre.EnrichMathml.lcaType.VALID:sre.EnrichMathml.lcaType.INVALID,node:c}};sre.EnrichMathml.prunePath_=function(a,b){for(var c=0;a[c]&&-1===b.indexOf(a[c]);)c++;return a.slice(0,c+1)};sre.EnrichMathml.attachedElement_=function(a){for(var b=0,c=null;!c&&b<a.length;)a[b].parentNode&&(c=a[b]),b++;return c};
-sre.EnrichMathml.pathToRoot_=function(a,b){for(var c=b||function(a){return!1},d=[a];!c(a)&&!sre.SemanticUtil.hasMathTag(a)&&a.parentNode;)a=sre.EnrichMathml.parentNode_(a),d.unshift(a);return d};sre.EnrichMathml.validLca_=function(a,b){return!(!a||!b||a.previousSibling||b.nextSibling)};sre.EnrichMathml.ascendNewNode=function(a){for(;!sre.SemanticUtil.hasMathTag(a)&&sre.EnrichMathml.unitChild_(a);)a=sre.EnrichMathml.parentNode_(a);return a};
-sre.EnrichMathml.descendNode_=function(a){var b=sre.DomUtil.toArray(a.childNodes);if(!b)return a;b=b.filter(function(a){return a.nodeType===sre.DomUtil.NodeType.ELEMENT_NODE&&!sre.SemanticUtil.hasIgnoreTag(a)});return 1===b.length&&sre.SemanticUtil.hasEmptyTag(b[0])&&!b[0].hasAttribute(sre.EnrichMathml.Attribute.TYPE)?sre.EnrichMathml.descendNode_(b[0]):a};
-sre.EnrichMathml.unitChild_=function(a){var b=sre.EnrichMathml.parentNode_(a);return b&&sre.SemanticUtil.hasEmptyTag(b)?sre.DomUtil.toArray(b.childNodes).every(function(b){return b===a||sre.EnrichMathml.isIgnorable_(b)}):!1};sre.EnrichMathml.isIgnorable_=function(a){return!a||sre.SemanticUtil.hasIgnoreTag(a)?!0:sre.SemanticUtil.hasEmptyTag(a)?sre.DomUtil.toArray(a.childNodes).every(sre.EnrichMathml.isIgnorable_):!1};sre.EnrichMathml.parentNode_=function(a){return a.parentNode};
-sre.EnrichMathml.addCollapsedAttribute=function(a,b){var c=new sre.SemanticSkeleton(b);a.setAttribute(sre.EnrichMathml.Attribute.COLLAPSED,c.toString())};sre.EnrichMathml.cloneContentNode=function(a){if(a.mathml.length)return sre.EnrichMathml.walkTree(a);var b=sre.EnrichMathml.SETTINGS.implicit?sre.EnrichMathml.createInvisibleOperator_(a):sre.DomUtil.createElement("mrow");a.mathml=[b];return b};sre.EnrichMathml.makeIdList=function(a){return a.map(function(a){return a.id}).join(",")};
-sre.EnrichMathml.setAttributes=function(a,b){a.setAttribute(sre.EnrichMathml.Attribute.TYPE,b.type);for(var c=b.attributes(),d=0,e;e=c[d];d++)a.setAttribute(sre.EnrichMathml.Attribute[e[0].toUpperCase()],e[1]);b.childNodes.length&&a.setAttribute(sre.EnrichMathml.Attribute.CHILDREN,sre.EnrichMathml.makeIdList(b.childNodes));b.contentNodes.length&&a.setAttribute(sre.EnrichMathml.Attribute.CONTENT,sre.EnrichMathml.makeIdList(b.contentNodes));b.parent&&a.setAttribute(sre.EnrichMathml.Attribute.PARENT,
-b.parent.id)};
-sre.EnrichMathml.combineContentChildren_=function(a,b,c){sre.EnrichMathml.setOperatorAttribute_(a,b);switch(a.type){case sre.Semantic.Type.RELSEQ:case sre.Semantic.Type.INFIXOP:case sre.Semantic.Type.MULTIREL:return sre.BaseUtil.interleaveLists(c,b);case sre.Semantic.Type.PREFIXOP:return b.concat(c);case sre.Semantic.Type.POSTFIXOP:return c.concat(b);case sre.Semantic.Type.FENCED:return c.unshift(b[0]),c.push(b[1]),c;case sre.Semantic.Type.PUNCTUATED:if(a.role===sre.Semantic.Role.TEXT)return sre.BaseUtil.interleaveLists(c,b);
-for(var d=[],e=0,f=0,g,h;g=c[e],h=b[f];e++)g.getAttribute(sre.EnrichMathml.Attribute.ID)==h.getAttribute(sre.EnrichMathml.Attribute.ID)&&(f++,d.push(g));sre.EnrichMathml.setOperatorAttribute_(a,d);return c;case sre.Semantic.Type.APPL:return[c[0],b[0],c[1]];case sre.Semantic.Type.ROOT:return[c[1],c[0]];case sre.Semantic.Type.ROW:case sre.Semantic.Type.LINE:return b.length&&c.unshift(b[0]),c;default:return c}};
-sre.EnrichMathml.rewriteMfenced=function(a){if("MFENCED"!==sre.DomUtil.tagName(a))return a;for(var b=sre.DomUtil.createElement("mrow"),c=0,d;d=a.attributes[c];c++)-1===["open","close","separators"].indexOf(d.name)&&b.setAttribute(d.name,d.value);sre.DomUtil.toArray(a.childNodes).forEach(function(a){b.appendChild(a)});sre.DomUtil.replaceNode(a,b);return b};
-sre.EnrichMathml.createInvisibleOperator_=function(a){var b=sre.DomUtil.createElement("mo"),c=sre.DomUtil.createTextNode(a.textContent);b.appendChild(c);sre.EnrichMathml.setAttributes(b,a);b.setAttribute(sre.EnrichMathml.Attribute.ADDED,"true");return b};sre.EnrichMathml.setOperatorAttribute_=function(a,b){var c=a.type+(a.textContent?","+a.textContent:"");b.forEach(function(a){sre.EnrichMathml.getInnerNode(a).setAttribute(sre.EnrichMathml.Attribute.OPERATOR,c)})};
-sre.EnrichMathml.getInnerNode=function(a){var b=sre.DomUtil.toArray(a.childNodes);if(!b)return a;for(var b=b.filter(function(a){return a.nodeType===sre.DomUtil.NodeType.ELEMENT_NODE&&!sre.SemanticUtil.hasIgnoreTag(a)}),c=[],d=0,e;e=b[d];d++)if(sre.SemanticUtil.hasEmptyTag(e)){var f=sre.EnrichMathml.getInnerNode(e);f&&f!==e&&c.push(f)}else c.push(e);return 1===c.length?c[0]:a};
-sre.EnrichMathml.formattedOutput=function(a,b,c,d){d=d||!1;sre.EnrichMathml.formattedOutput_(a,"Original MathML",d);sre.EnrichMathml.formattedOutput_(c,"Semantic Tree",d);sre.EnrichMathml.formattedOutput_(b,"Semantically enriched MathML",d)};sre.EnrichMathml.formattedOutput_=function(a,b,c){a=sre.DomUtil.formatXml(a.toString());c?console.log(b+":\n```html\n"+sre.EnrichMathml.removeAttributePrefix(a)+"\n```\n"):console.log(a)};
-sre.EnrichMathml.removeAttributePrefix=function(a){return a.toString().replace(new RegExp(sre.EnrichMathml.ATTRIBUTE_PREFIX_,"g"),"")};sre.EnrichMathml.printNodeList__=function(a,b){console.log(a);sre.DomUtil.toArray(b).forEach(function(a){console.log(a.toString())});console.log("<<<<<<<<<<<<<<<<<")};sre.CaseBinomial=function(a){sre.AbstractEnrichCase.call(this,a);this.mml=a.mathmlTree};goog.inherits(sre.CaseBinomial,sre.AbstractEnrichCase);sre.CaseBinomial.test=function(a){return!a.mathmlTree&&a.type===sre.SemanticAttr.Type.LINE&&a.role===sre.SemanticAttr.Role.BINOMIAL};
-sre.CaseBinomial.prototype.getMathml=function(){if(!this.semantic.childNodes.length)return this.mml;this.mml=sre.EnrichMathml.walkTree(this.semantic.childNodes[0]);if(this.mml.hasAttribute(sre.EnrichMathml.Attribute.TYPE)){var a=sre.DomUtil.createElement("mrow");a.setAttribute(sre.EnrichMathml.Attribute.ADDED,"true");sre.DomUtil.replaceNode(this.mml,a);a.appendChild(this.mml);this.mml=a}sre.EnrichMathml.setAttributes(this.mml,this.semantic);return this.mml};sre.CaseDoubleScript=function(a){sre.AbstractEnrichCase.call(this,a);this.mml=a.mathmlTree};goog.inherits(sre.CaseDoubleScript,sre.AbstractEnrichCase);sre.CaseDoubleScript.test=function(a){if(!a.mathmlTree||!a.childNodes.length)return!1;var b=sre.DomUtil.tagName(a.mathmlTree);a=a.childNodes[0].role;return"MSUBSUP"===b&&a===sre.SemanticAttr.Role.SUBSUP||"MUNDEROVER"===b&&a===sre.SemanticAttr.Role.UNDEROVER};
-sre.CaseDoubleScript.prototype.getMathml=function(){var a=this.semantic.childNodes[0],b=a.childNodes[0],c=this.semantic.childNodes[1],d=a.childNodes[1],e=sre.EnrichMathml.walkTree(c),f=sre.EnrichMathml.walkTree(b),g=sre.EnrichMathml.walkTree(d);sre.EnrichMathml.setAttributes(this.mml,this.semantic);this.mml.setAttribute(sre.EnrichMathml.Attribute.CHILDREN,sre.EnrichMathml.makeIdList([b,d,c]));[f,g,e].forEach(goog.bind(function(a){sre.EnrichMathml.getInnerNode(a).setAttribute(sre.EnrichMathml.Attribute.PARENT,
-this.mml.getAttribute(sre.EnrichMathml.Attribute.ID))},this));this.mml.setAttribute(sre.EnrichMathml.Attribute.TYPE,a.role);sre.EnrichMathml.addCollapsedAttribute(this.mml,[this.semantic.id,[a.id,b.id,d.id],c.id]);return this.mml};sre.CaseMultiindex=function(a){sre.AbstractEnrichCase.call(this,a);this.mml=a.mathmlTree};goog.inherits(sre.CaseMultiindex,sre.AbstractEnrichCase);
-sre.CaseMultiindex.prototype.completeMultiscript=function(a,b){var c=sre.DomUtil.toArray(this.mml.childNodes).slice(1),d=0,e=goog.bind(function(a){for(var b=0,e;e=a[b];b++){var f=c[d];if(f&&e==sre.EnrichMathml.getInnerNode(f).getAttribute(sre.EnrichMathml.Attribute.ID))sre.EnrichMathml.getInnerNode(f).setAttribute(sre.EnrichMathml.Attribute.PARENT,this.semantic.id),d++;else{var l=this.semantic.querySelectorAll(function(a){return a.id===e});this.mml.insertBefore(sre.CaseMultiindex.createNone_(l[0]),
-f||null)}}},this);e(a);c[d]&&"MPRESCRIPTS"!==sre.DomUtil.tagName(c[d])?this.mml.insertBefore(c[d],sre.DomUtil.createElement("mprescripts")):d++;e(b)};sre.CaseMultiindex.createNone_=function(a){var b=sre.DomUtil.createElement("none");a&&sre.EnrichMathml.setAttributes(b,a);b.setAttribute(sre.EnrichMathml.Attribute.ADDED,"true");return b};
-sre.CaseMultiindex.multiscriptIndex=function(a){if(a.type===sre.SemanticAttr.Type.PUNCTUATED&&a.contentNodes[0].role===sre.SemanticAttr.Role.DUMMY){var b=a.parent.id,c=a.contentNodes.map(function(a){return a.id});c.unshift("c");for(var c=[a.id,c],d=0,e;e=a.childNodes[d];d++){var f=sre.EnrichMathml.walkTree(e);sre.EnrichMathml.getInnerNode(f).setAttribute(sre.EnrichMathml.Attribute.PARENT,b);c.push(e.id)}return c}sre.EnrichMathml.walkTree(a);return a.id};sre.CaseMultiscripts=function(a){sre.CaseMultiindex.call(this,a)};goog.inherits(sre.CaseMultiscripts,sre.CaseMultiindex);sre.CaseMultiscripts.test=function(a){return a.mathmlTree?"MMULTISCRIPTS"===sre.DomUtil.tagName(a.mathmlTree)&&(a.type===sre.SemanticAttr.Type.SUPERSCRIPT||a.type===sre.SemanticAttr.Type.SUBSCRIPT):!1};
-sre.CaseMultiscripts.prototype.getMathml=function(){sre.EnrichMathml.setAttributes(this.mml,this.semantic);if(this.semantic.childNodes[0]&&this.semantic.childNodes[0].role===sre.SemanticAttr.Role.SUBSUP){var a=this.semantic.childNodes[0],b=a.childNodes[0],c=sre.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[1]),d=sre.CaseMultiindex.multiscriptIndex(a.childNodes[1]),e=[this.semantic.id,[a.id,b.id,d],c];sre.EnrichMathml.addCollapsedAttribute(this.mml,e);this.mml.setAttribute(sre.EnrichMathml.Attribute.TYPE,
-a.role);this.completeMultiscript(sre.SemanticSkeleton.interleaveIds(d,c),[])}else b=this.semantic.childNodes[0],c=sre.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[1]),e=[this.semantic.id,b.id,c],sre.EnrichMathml.addCollapsedAttribute(this.mml,e);a=sre.SemanticSkeleton.collapsedLeafs(d||[],c);c=sre.EnrichMathml.walkTree(b);sre.EnrichMathml.getInnerNode(c).setAttribute(sre.EnrichMathml.Attribute.PARENT,this.semantic.id);a.unshift(b.id);this.mml.setAttribute(sre.EnrichMathml.Attribute.CHILDREN,
-a.join(","));return this.mml};sre.CaseEmbellished=function(a){sre.AbstractEnrichCase.call(this,a);this.ofenceMml=this.ofence=this.fencedMml=this.fenced=null;this.ofenceMap={};this.cfenceMml=this.cfence=null;this.cfenceMap={};this.parentCleanup=[]};goog.inherits(sre.CaseEmbellished,sre.AbstractEnrichCase);sre.CaseEmbellished.test=function(a){return a.mathmlTree&&a.fencePointer};sre.CaseEmbellished.prototype.getMathml=function(){this.getFenced_();this.fencedMml=sre.EnrichMathml.walkTree(this.fenced);this.getFencesMml_();return this.rewrite_()};
-sre.CaseEmbellished.prototype.getFenced_=function(){for(var a=this.semantic;a.type!==sre.SemanticAttr.Type.FENCED;)a=a.childNodes[0];this.fenced=a.childNodes[0];this.ofence=a.contentNodes[0];this.cfence=a.contentNodes[1];sre.CaseEmbellished.fencedMap_(this.ofence,this.ofenceMap);sre.CaseEmbellished.fencedMap_(this.cfence,this.cfenceMap)};sre.CaseEmbellished.fencedMap_=function(a,b){b[a.id]=a.mathmlTree;a.embellished&&sre.CaseEmbellished.fencedMap_(a.childNodes[0],b)};
-sre.CaseEmbellished.prototype.getFencesMml_=function(){for(var a=this.semantic,b=Object.keys(this.ofenceMap),c=Object.keys(this.cfenceMap);!(this.ofenceMml&&this.cfenceMml||a===this.fenced);)-1===b.indexOf(a.fencePointer)||this.ofenceMml||(this.ofenceMml=a.mathmlTree),-1===c.indexOf(a.fencePointer)||this.cfenceMml||(this.cfenceMml=a.mathmlTree),a=a.childNodes[0];this.ofenceMml||(this.ofenceMml=this.ofence.mathmlTree);this.cfenceMml||(this.cfenceMml=this.cfence.mathmlTree);this.ofenceMml&&(this.ofenceMml=
-sre.EnrichMathml.ascendNewNode(this.ofenceMml));this.cfenceMml&&(this.cfenceMml=sre.EnrichMathml.ascendNewNode(this.cfenceMml))};
-sre.CaseEmbellished.prototype.rewrite_=function(){var a=this.semantic,b=null,c=this.introduceNewLayer_();for(sre.EnrichMathml.setAttributes(c,this.fenced.parent);a.type!==sre.SemanticAttr.Type.FENCED;){var d=a.mathmlTree,e=this.specialCase_(a,d);if(e)a=e;else{sre.EnrichMathml.setAttributes(d,a);for(var e=[],f=1,g;g=a.childNodes[f];f++)e.push(sre.EnrichMathml.walkTree(g));a=a.childNodes[0]}e=sre.DomUtil.createElement("dummy");f=c.parentNode;g=d.childNodes[0];sre.DomUtil.replaceNode(d,e);sre.DomUtil.replaceNode(c,
-d);sre.DomUtil.replaceNode(d.childNodes[0],c);sre.DomUtil.replaceNode(e,g);d.parentNode=f;c=d.childNodes[0];b||(b=d)}sre.EnrichMathml.walkTree(this.ofence);sre.EnrichMathml.walkTree(this.cfence);this.cleanupParents_();return b||c};
-sre.CaseEmbellished.prototype.specialCase_=function(a,b){var c=sre.DomUtil.tagName(b),d=null,e;"MSUBSUP"===c?(d=a.childNodes[0],e=sre.CaseDoubleScript):"MMULTISCRIPTS"===c&&(a.type===sre.SemanticAttr.Type.SUPERSCRIPT||a.type===sre.SemanticAttr.Type.SUBSCRIPT?e=sre.CaseMultiscripts:a.type===sre.SemanticAttr.Type.TENSOR&&(e=sre.CaseTensor),d=e&&a.childNodes[0]&&a.childNodes[0].role===sre.SemanticAttr.Role.SUBSUP?a.childNodes[0]:a);if(!d)return null;var c=d.childNodes[0],f=sre.CaseEmbellished.makeEmptyNode_(c.id);
-d.childNodes[0]=f;b=(new e(a)).getMathml();d.childNodes[0]=c;this.parentCleanup.push(b);return d.childNodes[0]};sre.CaseEmbellished.makeEmptyNode_=function(a){var b=sre.DomUtil.createElement("mrow");a=new sre.SemanticNode(a);a.type=sre.SemanticAttr.Type.EMPTY;a.mathmlTree=b;return a};
-sre.CaseEmbellished.prototype.introduceNewLayer_=function(){var a=this.fullFence(this.ofenceMml),b=this.fullFence(this.cfenceMml),c=sre.DomUtil.createElement("mrow");sre.DomUtil.replaceNode(this.fencedMml,c);c.appendChild(this.fencedMml);c.insertBefore(a,this.fencedMml);c.appendChild(b);if(!c.parentNode){for(a=sre.DomUtil.createElement("mrow");0<c.childNodes.length;)a.appendChild(c.childNodes[0]);c.appendChild(a);c=a}return c};
-sre.CaseEmbellished.prototype.fullFence=function(a){for(var b=this.fencedMml.parentNode;a.parentNode&&a.parentNode!==b;)a=a.parentNode;return a};sre.CaseEmbellished.prototype.cleanupParents_=function(){this.parentCleanup.forEach(function(a){var b=a.childNodes[1].getAttribute(sre.EnrichMathml.Attribute.PARENT);a.childNodes[0].setAttribute(sre.EnrichMathml.Attribute.PARENT,b)})};sre.CaseLine=function(a){sre.AbstractEnrichCase.call(this,a);this.mml=a.mathmlTree};goog.inherits(sre.CaseLine,sre.AbstractEnrichCase);sre.CaseLine.test=function(a){return a.mathmlTree&&a.type===sre.SemanticAttr.Type.LINE};
-sre.CaseLine.prototype.getMathml=function(){this.semantic.contentNodes.length&&sre.EnrichMathml.walkTree(this.semantic.contentNodes[0]);this.semantic.childNodes.length&&sre.EnrichMathml.walkTree(this.semantic.childNodes[0]);sre.EnrichMathml.setAttributes(this.mml,this.semantic);return this.mml};sre.CaseTable=function(a){sre.AbstractEnrichCase.call(this,a);this.mml=a.mathmlTree;this.inner=[]};goog.inherits(sre.CaseTable,sre.AbstractEnrichCase);sre.CaseTable.test=function(a){return a.mathmlTree&&(a.type===sre.SemanticAttr.Type.MATRIX||a.type===sre.SemanticAttr.Type.VECTOR||a.type===sre.SemanticAttr.Type.CASES)};
-sre.CaseTable.prototype.getMathml=function(){var a=sre.EnrichMathml.cloneContentNode(this.semantic.contentNodes[0]),b=this.semantic.contentNodes[1]?sre.EnrichMathml.cloneContentNode(this.semantic.contentNodes[1]):null;this.inner=this.semantic.childNodes.map(sre.EnrichMathml.walkTree);"MFENCED"===sre.DomUtil.tagName(this.mml)?(this.mml.insertBefore(a,this.mml.childNodes[0]||null),b&&this.mml.appendChild(b),this.mml=sre.EnrichMathml.rewriteMfenced(this.mml)):(a=[a,this.mml],b&&a.push(b),this.mml=sre.EnrichMathml.introduceNewLayer(a));
-sre.EnrichMathml.setAttributes(this.mml,this.semantic);return this.mml};sre.CaseTensor=function(a){sre.CaseMultiindex.call(this,a)};goog.inherits(sre.CaseTensor,sre.CaseMultiindex);sre.CaseTensor.test=function(a){return a.mathmlTree&&a.type===sre.SemanticAttr.Type.TENSOR};
-sre.CaseTensor.prototype.getMathml=function(){sre.EnrichMathml.walkTree(this.semantic.childNodes[0]);var a=sre.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[1]),b=sre.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[2]),c=sre.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[3]),d=sre.CaseMultiindex.multiscriptIndex(this.semantic.childNodes[4]);sre.EnrichMathml.setAttributes(this.mml,this.semantic);sre.EnrichMathml.addCollapsedAttribute(this.mml,[this.semantic.id,this.semantic.childNodes[0].id,
-a,b,c,d]);var e=sre.SemanticSkeleton.collapsedLeafs(a,b,c,d);e.unshift(this.semantic.childNodes[0].id);this.mml.setAttribute(sre.EnrichMathml.Attribute.CHILDREN,e.join(","));this.completeMultiscript(sre.SemanticSkeleton.interleaveIds(c,d),sre.SemanticSkeleton.interleaveIds(a,b));return this.mml};sre.EnrichCases=function(){};sre.EnrichCaseFactory.cases.push({test:sre.CaseEmbellished.test,constr:sre.CaseEmbellished},{test:sre.CaseDoubleScript.test,constr:sre.CaseDoubleScript},{test:sre.CaseTensor.test,constr:sre.CaseTensor},{test:sre.CaseMultiscripts.test,constr:sre.CaseMultiscripts},{test:sre.CaseLine.test,constr:sre.CaseLine},{test:sre.CaseBinomial.test,constr:sre.CaseBinomial},{test:sre.CaseTable.test,constr:sre.CaseTable});sre.Enrich={};sre.Enrich.semanticMathmlNode=function(a){a=a.cloneNode(!0);var b=sre.Semantic.getTree(a);return sre.EnrichMathml.enrich(a,b)};sre.Enrich.semanticMathmlSync=function(a){a=sre.DomUtil.parseInput(a);return sre.Enrich.semanticMathmlNode(a)};sre.Enrich.semanticMathml=function(a,b){if(sre.Engine.isReady()){var c=sre.DomUtil.parseInput(a);b(sre.Enrich.semanticMathmlNode(c))}else setTimeout(function(){sre.Enrich.semanticMathml(a,b)},500)};
-sre.Enrich.testTranslation__=function(a){new sre.EnrichCases;sre.Debugger.getInstance().init();a=sre.Enrich.semanticMathmlSync(sre.Enrich.prepareMmlString(a)).toString();sre.EnrichMathml.removeAttributePrefix(a);sre.Debugger.getInstance().exit();return a};sre.Enrich.prepareMmlString=function(a){a.match(/^<math/)||(a="<math>"+a);a.match(/\/math>$/)||(a+="</math>");return a};sre.ColorPicker=function(a,b){this.foreground=sre.ColorPicker.getChannelColor_(b,sre.ColorPicker.DEFAULT_FOREGROUND_);this.background=sre.ColorPicker.getChannelColor_(a,sre.ColorPicker.DEFAULT_BACKGROUND_)};sre.ColorPicker.DEFAULT_BACKGROUND_="blue";sre.ColorPicker.DEFAULT_FOREGROUND_="black";
-sre.ColorPicker.namedColors_={red:{red:255,green:0,blue:0},green:{red:0,green:255,blue:0},blue:{red:0,green:0,blue:255},yellow:{red:255,green:255,blue:0},cyan:{red:0,green:255,blue:255},magenta:{red:255,green:0,blue:255},white:{red:255,green:255,blue:255},black:{red:0,green:0,blue:0}};sre.ColorPicker.getChannelColor_=function(a,b){var c=a||{color:b},d=c.color?sre.ColorPicker.namedColors_[c.color]:c;d||(d=sre.ColorPicker.namedColors_[b]);d.alpha=c.hasOwnProperty("alpha")?c.alpha:1;return sre.ColorPicker.normalizeColor_(d)};
-sre.ColorPicker.normalizeColor_=function(a){var b=function(a){a=Math.max(a,0);a=Math.min(255,a);return Math.round(a)};a.red=b(a.red);a.green=b(a.green);a.blue=b(a.blue);a.alpha=Math.max(a.alpha,0);a.alpha=Math.min(1,a.alpha);return a};sre.ColorPicker.prototype.rgba=function(){var a=function(a){return"rgba("+a.red+","+a.green+","+a.blue+","+a.alpha+")"};return{background:a(this.background),foreground:a(this.foreground)}};
-sre.ColorPicker.prototype.rgb=function(){var a=function(a){return"rgb("+a.red+","+a.green+","+a.blue+")"};return{background:a(this.background),alphaback:this.background.alpha.toString(),foreground:a(this.foreground),alphafore:this.foreground.alpha.toString()}};
-sre.ColorPicker.prototype.hex=function(){var a=function(a){return"#"+sre.ColorPicker.toHex_(a.red)+sre.ColorPicker.toHex_(a.green)+sre.ColorPicker.toHex_(a.blue)};return{background:a(this.background),alphaback:this.background.alpha.toString(),foreground:a(this.foreground),alphafore:this.foreground.alpha.toString()}};sre.ColorPicker.toHex_=function(a){a=a.toString(16);return 1===a.length?"0"+a:a};sre.Highlighter=function(){};sre.Highlighter.prototype.highlight=function(a){};sre.Highlighter.prototype.unhighlight=function(){};sre.Highlighter.prototype.highlightAll=function(a){};sre.Highlighter.prototype.unhighlightAll=function(){};sre.Highlighter.prototype.setColor=function(a){};sre.Highlighter.prototype.addEvents=function(a,b){};sre.AbstractHighlighter=function(){this.currentHighlights_=[];this.color=null;this.mactionName="";this.state_={}};sre.AbstractHighlighter.prototype.highlight=function(a){this.currentHighlights_.push(a.map(goog.bind(function(a){return this.highlightNode(a)},this)))};sre.AbstractHighlighter.prototype.highlightNode=goog.abstractMethod;sre.AbstractHighlighter.prototype.highlightAll=function(a){a=this.getMactionNodes(a);for(var b=0,c;c=a[b];b++)this.highlight([c])};
-sre.AbstractHighlighter.prototype.unhighlight=function(){var a=this.currentHighlights_.pop();a&&a.forEach(goog.bind(function(a){return this.unhighlightNode(a)},this))};sre.AbstractHighlighter.prototype.unhighlightNode=goog.abstractMethod;sre.AbstractHighlighter.prototype.unhighlightAll=function(){for(;0<this.currentHighlights_.length;)this.unhighlight()};sre.AbstractHighlighter.prototype.setColor=function(a){this.color=a};sre.AbstractHighlighter.prototype.colorString=function(){return this.color.rgba()};
-sre.AbstractHighlighter.prototype.addEvents=function(a,b){for(var c=this.getMactionNodes(a),d=0,e;e=c[d];d++)for(var f in b)e.addEventListener(f,b[f])};sre.AbstractHighlighter.prototype.getMactionNodes=function(a){return a.getElementsByClassName(this.mactionName)};sre.AbstractHighlighter.prototype.isMactionNode=function(a){return(a=a.className||a.getAttribute("class"))?a.match(new RegExp(this.mactionName)):!1};sre.AbstractHighlighter.prototype.resetState=function(a){delete this.state_[a]};
-sre.AbstractHighlighter.prototype.setState=function(a,b){this.state_[a]=b};sre.AbstractHighlighter.prototype.getState=function(a){return this.state_[a]};sre.CssHighlighter=function(){sre.AbstractHighlighter.call(this);this.mactionName="mjx-maction"};goog.inherits(sre.CssHighlighter,sre.AbstractHighlighter);sre.CssHighlighter.prototype.highlightNode=function(a){var b={node:a,background:a.style.backgroundColor,foreground:a.style.color},c=this.colorString();a.style.backgroundColor=c.background;a.style.color=c.foreground;return b};sre.CssHighlighter.prototype.unhighlightNode=function(a){a.node.style.backgroundColor=a.background;a.node.style.color=a.foreground};sre.HtmlHighlighter=function(){sre.AbstractHighlighter.call(this);this.mactionName="maction"};goog.inherits(sre.HtmlHighlighter,sre.AbstractHighlighter);sre.HtmlHighlighter.prototype.setMode=function(a){this.mode=a};
-sre.HtmlHighlighter.prototype.highlightNode=function(a){var b={node:a,foreground:a.style.color,position:a.style.position},c=this.color.rgb();a.style.color=c.foreground;a.style.position="relative";var d=a.bbox;if(d&&d.w){var e=document.createElement("span"),f=parseFloat(a.style.paddingLeft||"0");e.style.backgroundColor=c.background;e.style.opacity=c.alphaback.toString();e.style.display="inline-block";e.style.height=d.h+d.d+.1+"em";e.style.verticalAlign=-d.d+"em";e.style.marginTop=e.style.marginBottom=
-"-0.05em";e.style.width=d.w+0+"em";e.style.marginLeft=f-0+"em";e.style.marginRight=-d.w-0-f+"em";a.parentNode.insertBefore(e,a);b.box=e}return b};sre.HtmlHighlighter.prototype.unhighlightNode=function(a){var b=a.node;b.style.color=a.foreground;b.style.position=a.position;a.box&&a.box.parentNode.removeChild(a.box)};sre.MmlCssHighlighter=function(){sre.CssHighlighter.call(this);this.mactionName="maction"};goog.inherits(sre.MmlCssHighlighter,sre.CssHighlighter);sre.MmlCssHighlighter.prototype.getMactionNodes=function(a){return a.getElementsByTagName(this.mactionName)};sre.MmlCssHighlighter.prototype.isMactionNode=function(a){return a.tagName===this.mactionName};sre.MmlHighlighter=function(){sre.AbstractHighlighter.call(this);this.mactionName="maction"};goog.inherits(sre.MmlHighlighter,sre.AbstractHighlighter);sre.MmlHighlighter.prototype.highlightNode=function(a){var b=a.getAttribute("style"),b=b+(";background-color: "+this.colorString().background),b=b+(";color: "+this.colorString().foreground);a.setAttribute("style",b);return{node:a}};
-sre.MmlHighlighter.prototype.unhighlightNode=function(a){var b=a.node.getAttribute("style"),b=b.replace(";background-color: "+this.colorString().background,""),b=b.replace(";color: "+this.colorString().foreground,"");a.node.setAttribute("style",b)};sre.MmlHighlighter.prototype.colorString=function(){return this.color.rgba()};sre.MmlHighlighter.prototype.getMactionNodes=function(a){return a.getElementsByTagName(this.mactionName)};
-sre.MmlHighlighter.prototype.isMactionNode=function(a){return a.tagName===this.mactionName};sre.SvgHighlighter=function(){sre.AbstractHighlighter.call(this);this.mactionName="mjx-svg-maction"};goog.inherits(sre.SvgHighlighter,sre.AbstractHighlighter);
-sre.SvgHighlighter.prototype.highlightNode=function(a){if("svg"===a.tagName){var b={node:a,background:a.style.backgroundColor,foreground:a.style.color};a.style.backgroundColor=this.colorString().background;a.style.color=this.colorString().foreground;return b}var b=document.createElementNS("http://www.w3.org/2000/svg","rect"),c;if("use"===a.nodeName){var d=document.createElementNS("http://www.w3.org/2000/svg","g");a.parentNode.insertBefore(d,a);d.appendChild(a);c=d.getBBox();d.parentNode.replaceChild(a,
-d)}else c=a.getBBox();b.setAttribute("x",c.x-40);b.setAttribute("y",c.y-40);b.setAttribute("width",c.width+80);b.setAttribute("height",c.height+80);(c=a.getAttribute("transform"))&&b.setAttribute("transform",c);b.setAttribute("fill",this.colorString().background);a.parentNode.insertBefore(b,a);b={node:b,foreground:a.getAttribute("fill")};a.setAttribute("fill",this.colorString().foreground);return b};
-sre.SvgHighlighter.prototype.unhighlightNode=function(a){"background"in a?(a.node.style.backgroundColor=a.background,a.node.style.color=a.foreground):(a.foreground?a.node.nextSibling.setAttribute("fill",a.foreground):a.node.nextSibling.removeAttribute("fill"),a.node.parentNode.removeChild(a.node))};sre.SvgHighlighter.prototype.isMactionNode=function(a){a=a.className||a.getAttribute("class");return(a=a.baseVal?a.baseVal:a)?a.match(new RegExp(this.mactionName)):!1};sre.HighlighterFactory={};sre.HighlighterFactory.highlighter=function(a,b,c){a=new sre.ColorPicker(a,b);c=sre.HighlighterFactory.highlighterMapping_["NativeMML"===c.renderer&&"Safari"===c.browser?"MML-CSS":c.renderer];if(!c)return null;c.setColor(a);return c};sre.HighlighterFactory.addEvents=function(a,b,c){(c=sre.HighlighterFactory.highlighterMapping_[c.renderer])&&c.addEvents(a,b)};
-sre.HighlighterFactory.highlighterMapping_={SVG:new sre.SvgHighlighter,NativeMML:new sre.MmlHighlighter,"HTML-CSS":new sre.HtmlHighlighter,"MML-CSS":new sre.MmlCssHighlighter,CommonHTML:new sre.CssHighlighter};sre.AuditoryDescription=function(a){this.context=a.context||"";this.text=a.text||"";this.userValue=a.userValue||"";this.annotation=a.annotation||"";this.personality=a.personality||{}};sre.AuditoryDescription.create=function(a,b){a.text=sre.Grammar.getInstance().apply(a.text,b||{});return new sre.AuditoryDescription(a)};sre.AuditoryDescription.prototype.isEmpty=function(){return 0==this.context.length&&0==this.text.length&&0==this.userValue.length&&0==this.annotation.length};
-sre.AuditoryDescription.prototype.clone=function(){var a;if(this.personality){a={};for(var b in this.personality)a=this.personality[b]}return new sre.AuditoryDescription({context:this.context,text:this.text,userValue:this.userValue,annotation:this.annotation,personality:a})};sre.AuditoryDescription.prototype.toString=function(){return'AuditoryDescription(context="'+this.context+'" text="'+this.text+'" userValue="'+this.userValue+'" annotation="'+this.annotation+'")'};
-sre.AuditoryDescription.prototype.descriptionString=function(){return this.context&&this.text?this.context+" "+this.text:this.context||this.text};sre.AuditoryDescription.prototype.equals=function(a){return this.context==a.context&&this.text==a.text&&this.userValue==a.userValue&&this.annotation==a.annotation};sre.SpeechRule=function(a,b,c,d){this.name=a;this.dynamicCstr=b;this.precondition=c;this.action=d};sre.SpeechRule.prototype.toString=function(){return this.name+" | "+this.dynamicCstr.toString()+" | "+this.precondition.toString()+" ==> "+this.action.toString()};sre.SpeechRule.Type={NODE:"NODE",MULTI:"MULTI",TEXT:"TEXT",PERSONALITY:"PERSONALITY"};
-sre.SpeechRule.Type.fromString=function(a){switch(a){case "[n]":return sre.SpeechRule.Type.NODE;case "[m]":return sre.SpeechRule.Type.MULTI;case "[t]":return sre.SpeechRule.Type.TEXT;case "[p]":return sre.SpeechRule.Type.PERSONALITY;default:throw"Parse error: "+a;}};
-sre.SpeechRule.Type.toString=function(a){switch(a){case sre.SpeechRule.Type.NODE:return"[n]";case sre.SpeechRule.Type.MULTI:return"[m]";case sre.SpeechRule.Type.TEXT:return"[t]";case sre.SpeechRule.Type.PERSONALITY:return"[p]";default:throw"Unknown type error: "+a;}};sre.SpeechRule.Component=function(a){this.type=a.type;this.content=a.content;this.attributes=a.attributes;this.grammar=a.grammar};
-sre.SpeechRule.Component.fromString=function(a){var b={};b.type=sre.SpeechRule.Type.fromString(a.substring(0,3));a=a.slice(3).trim();if(!a)throw new sre.SpeechRule.OutputError("Missing content.");switch(b.type){case sre.SpeechRule.Type.TEXT:if('"'==a[0]){var c=sre.SpeechRule.splitString_(a,"\\(")[0].trim();if('"'!=c.slice(-1))throw new sre.SpeechRule.OutputError("Invalid string syntax.");b.content=c;a=a.slice(c.length).trim();-1==a.indexOf("(")&&(a="");break}case sre.SpeechRule.Type.NODE:case sre.SpeechRule.Type.MULTI:c=
-a.indexOf(" ("),-1==c?(b.content=a.trim(),a=""):(b.content=a.substring(0,c).trim(),a=a.slice(c).trim())}a&&(a=sre.SpeechRule.Component.attributesFromString(a),a.grammar&&(b.grammar=a.grammar,delete a.grammar),Object.keys(a).length&&(b.attributes=a));return b=new sre.SpeechRule.Component(b)};sre.SpeechRule.Component.prototype.toString=function(){var a;a=""+sre.SpeechRule.Type.toString(this.type);a+=this.content?" "+this.content:"";var b=this.attributesToString();return a+(b?" "+b:"")};
-sre.SpeechRule.Component.grammarFromString=function(a){return sre.Grammar.parseInput(a)};sre.SpeechRule.Component.prototype.grammarToString=function(){return this.getGrammar().join(":")};sre.SpeechRule.Component.prototype.getGrammar=function(){var a=[],b;for(b in this.grammar)!0===this.grammar[b]?a.push(b):!1===this.grammar[b]?a.push("!"+b):a.push(b+"="+this.grammar[b]);return a};
-sre.SpeechRule.Component.attributesFromString=function(a){if("("!=a[0]||")"!=a.slice(-1))throw new sre.SpeechRule.OutputError("Invalid attribute expression: "+a);var b={};a=sre.SpeechRule.splitString_(a.slice(1,-1),",");for(var c=0,d=a.length;c<d;c++){var e=a[c],f=e.indexOf(":");if(-1==f)b[e.trim()]="true";else{var g=e.substring(0,f).trim(),e=e.slice(f+1).trim();b[g]="grammar"===g?sre.SpeechRule.Component.grammarFromString(e):b[g]=e}}return b};
-sre.SpeechRule.Component.prototype.attributesToString=function(){var a=this.getAttributes(),b=this.grammarToString();b&&a.push("grammar:"+b);return 0<a.length?"("+a.join(", ")+")":""};sre.SpeechRule.Component.prototype.getAttributes=function(){var a=[],b;for(b in this.attributes){var c=this.attributes[b];"true"===c?a.push(b):a.push(b+":"+c)}return a};sre.SpeechRule.Action=function(a){this.components=a};
-sre.SpeechRule.Action.fromString=function(a){a=sre.SpeechRule.splitString_(a,";").filter(function(a){return a.match(/\S/)}).map(function(a){return a.trim()});for(var b=[],c=0,d=a.length;c<d;c++){var e=sre.SpeechRule.Component.fromString(a[c]);e&&b.push(e)}return new sre.SpeechRule.Action(b)};sre.SpeechRule.Action.prototype.toString=function(){return this.components.map(function(a){return a.toString()}).join("; ")};sre.SpeechRule.Precondition=function(a,b){this.query=a;this.constraints=b||[]};
-sre.SpeechRule.Precondition.prototype.toString=function(){var a=this.constraints.join(", ");return this.query+", "+a};
-sre.SpeechRule.splitString_=function(a,b){for(var c=[],d="";""!=a;){var e=a.search(b);if(-1==e){if(0!=(a.match(/"/g)||[]).length%2)throw new sre.SpeechRule.OutputError("Invalid string in expression: "+a);c.push(d+a);a=d=""}else if(0==(a.substring(0,e).match(/"/g)||[]).length%2)c.push(d+a.substring(0,e)),d="",a=a.substring(e+1);else{var f=a.substring(e).search('"');if(-1==f)throw new sre.SpeechRule.OutputError("Invalid string in expression: "+a);d+=a.substring(0,e+f+1);a=a.substring(e+f+1)}}d&&c.push(d);
-return c};sre.SpeechRule.OutputError=function(a){Error.call(this);this.message=a||"";this.name="RuleError"};goog.inherits(sre.SpeechRule.OutputError,Error);sre.SpeechRuleEvaluator=goog.abstractMethod;sre.SpeechRuleEvaluator.prototype.evaluateDefault=goog.abstractMethod;sre.SpeechRuleFunctions=function(){};sre.SpeechRuleFunctions.Store_=function(a,b){this.prefix_=a;this.store_=b};sre.SpeechRuleFunctions.Store_.prototype.add=function(a,b){this.checkCustomFunctionSyntax_(a)&&(this.store_[a]=b)};sre.SpeechRuleFunctions.Store_.prototype.addStore=function(a){for(var b=Object.keys(a.store_),c=0,d;d=b[c];c++)this.add(d,a.store_[d])};sre.SpeechRuleFunctions.Store_.prototype.lookup=function(a){return this.store_[a]};
-sre.SpeechRuleFunctions.CustomQueries=function(){sre.SpeechRuleFunctions.Store_.call(this,"CQF",{})};goog.inherits(sre.SpeechRuleFunctions.CustomQueries,sre.SpeechRuleFunctions.Store_);sre.SpeechRuleFunctions.CustomStrings=function(){sre.SpeechRuleFunctions.Store_.call(this,"CSF",{})};goog.inherits(sre.SpeechRuleFunctions.CustomStrings,sre.SpeechRuleFunctions.Store_);sre.SpeechRuleFunctions.ContextFunctions=function(){sre.SpeechRuleFunctions.Store_.call(this,"CTXF",{})};
-goog.inherits(sre.SpeechRuleFunctions.ContextFunctions,sre.SpeechRuleFunctions.Store_);sre.SpeechRuleFunctions.Store_.prototype.checkCustomFunctionSyntax_=function(a){return a.match(new RegExp("^"+this.prefix_))?!0:(console.log("FunctionError: Invalid function name. Expected prefix "+this.prefix_),!1)};sre.SpeechRuleStore=goog.abstractMethod;sre.SpeechRuleStore.prototype.addRule=goog.abstractMethod;sre.SpeechRuleStore.prototype.deleteRule=goog.abstractMethod;sre.SpeechRuleStore.prototype.findRule=goog.abstractMethod;sre.SpeechRuleStore.prototype.findAllRules=goog.abstractMethod;sre.SpeechRuleStore.prototype.lookupRule=goog.abstractMethod;sre.SpeechRuleStore.prototype.defineRule=goog.abstractMethod;sre.TrieNode=function(){};sre.TrieNode.prototype.getConstraint=function(){};sre.TrieNode.prototype.getKind=function(){};sre.TrieNode.prototype.applyTest=function(a){};sre.TrieNode.prototype.addChild=function(a){};sre.TrieNode.prototype.getChild=function(a){};sre.TrieNode.prototype.getChildren=function(){};sre.TrieNode.prototype.findChildren=function(a){};sre.TrieNode.Kind={ROOT:"root",DYNAMIC:"dynamic",QUERY:"query",BOOLEAN:"boolean",STATIC:"static"};sre.AbstractTrieNode=function(a,b){this.constraint=a;this.test=b;this.children_={};this.kind=sre.TrieNode.Kind.ROOT};sre.AbstractTrieNode.prototype.getConstraint=function(){return this.constraint};sre.AbstractTrieNode.prototype.getKind=function(){return this.kind};sre.AbstractTrieNode.prototype.applyTest=function(a){return this.test(a)};sre.AbstractTrieNode.prototype.addChild=function(a){var b=a.getConstraint(),c=this.children_[b];this.children_[b]=a;return c};
-sre.AbstractTrieNode.prototype.getChild=function(a){return this.children_[a]};sre.AbstractTrieNode.prototype.getChildren=function(){var a=[],b;for(b in this.children_)a.push(this.children_[b]);return a};sre.AbstractTrieNode.prototype.findChildren=function(a){var b=[],c;for(c in this.children_){var d=this.children_[c];d.applyTest(a)&&b.push(d)}return b};sre.AbstractTrieNode.prototype.toString=function(){return this.constraint};
-sre.StaticTrieNode=function(a,b){sre.AbstractTrieNode.call(this,a,b);this.kind=sre.TrieNode.Kind.STATIC;this.rule_=null};goog.inherits(sre.StaticTrieNode,sre.AbstractTrieNode);sre.StaticTrieNode.prototype.getRule=function(){return this.rule_};sre.StaticTrieNode.prototype.setRule=function(a){this.rule_&&sre.Debugger.getInstance().output("Replacing rule "+this.rule_+" with "+a);this.rule_=a};
-sre.StaticTrieNode.prototype.toString=function(){return this.getRule()?this.constraint+"\n==> "+this.getRule().action:this.constraint};sre.TrieNodeFactory={};sre.TrieNodeFactory.getNode=function(a,b,c){switch(a){case sre.TrieNode.Kind.ROOT:return new sre.RootTrieNode;case sre.TrieNode.Kind.DYNAMIC:return new sre.DynamicTrieNode(b);case sre.TrieNode.Kind.QUERY:return new sre.QueryTrieNode(b,c);case sre.TrieNode.Kind.BOOLEAN:return new sre.BooleanTrieNode(b,c);default:return null}};sre.RootTrieNode=function(){sre.AbstractTrieNode.call(this,"",function(){return!0});this.kind=sre.TrieNode.Kind.ROOT};goog.inherits(sre.RootTrieNode,sre.AbstractTrieNode);
-sre.DynamicTrieNode=function(a){sre.AbstractTrieNode.call(this,a,function(b){return b===a});this.kind=sre.TrieNode.Kind.DYNAMIC};goog.inherits(sre.DynamicTrieNode,sre.AbstractTrieNode);
-sre.TrieNodeFactory.constraintTest_=function(a){if(a.match(/^self::\*$/))return function(a){return!0};if(a.match(/^self::\w+$/)){var b=a.slice(6).toUpperCase();return function(a){return a.tagName&&sre.DomUtil.tagName(a)===b}}if(a.match(/^self::\w+:\w+$/)){a=a.split(":");var c=sre.XpathUtil.resolveNameSpace(a[2]);if(!c)return null;b=a[3].toUpperCase();return function(a){return a.localName&&a.localName.toUpperCase()===b&&a.namespaceURI===c}}if(a.match(/^@\w+$/)){var d=a.slice(1);return function(a){return a.hasAttribute&&
-a.hasAttribute(d)}}if(a.match(/^@\w+="[\w\d ]+"$/)){a=a.split("=");var d=a[0].slice(1),e=a[1].slice(1,-1);return function(a){return a.hasAttribute&&a.hasAttribute(d)&&a.getAttribute(d)===e}}return a.match(/^@\w+!="[\w\d ]+"$/)?(a=a.split("!="),d=a[0].slice(1),e=a[1].slice(1,-1),function(a){return!a.hasAttribute||!a.hasAttribute(d)||a.getAttribute(d)!==e}):a.match(/^contains\(\s*@grammar\s*,\s*"[\w\d ]+"\s*\)$/)?(a=a.split('"'),e=a[1],function(a){return sre.Grammar.getInstance().getParameter(e)}):
-a.match(/^not\(\s*contains\(\s*@grammar\s*,\s*"[\w\d ]+"\s*\)\s*\)$/)?(a=a.split('"'),e=a[1],function(a){return!sre.Grammar.getInstance().getParameter(e)}):null};sre.QueryTrieNode=function(a,b){this.store_=b;sre.StaticTrieNode.call(this,a,sre.TrieNodeFactory.constraintTest_(a));this.kind=sre.TrieNode.Kind.QUERY};goog.inherits(sre.QueryTrieNode,sre.StaticTrieNode);sre.QueryTrieNode.prototype.applyTest=function(a){return this.test?this.test(a):this.store_.applyQuery(a,this.constraint)===a};
-sre.BooleanTrieNode=function(a,b){this.store_=b;sre.StaticTrieNode.call(this,a,sre.TrieNodeFactory.constraintTest_(a));this.kind=sre.TrieNode.Kind.BOOLEAN};goog.inherits(sre.BooleanTrieNode,sre.StaticTrieNode);sre.BooleanTrieNode.prototype.applyTest=function(a){return this.test?this.test(a):this.store_.applyConstraint(a,this.constraint)};sre.Trie=function(a){this.store=a;this.root=sre.TrieNodeFactory.getNode(sre.TrieNode.Kind.ROOT,"",this.store)};sre.Trie.prototype.addRule=function(a){for(var b=this.root,c=a.dynamicCstr.getValues(),d=0,e=c.length;d<e;d++)b=this.addNode_(b,c[d],sre.TrieNode.Kind.DYNAMIC);b=this.addNode_(b,a.precondition.query,sre.TrieNode.Kind.QUERY);c=a.precondition.constraints;d=0;for(e=c.length;d<e;d++)b=this.addNode_(b,c[d],sre.TrieNode.Kind.BOOLEAN);b.setRule(a)};
-sre.Trie.prototype.addNode_=function(a,b,c){var d=a.getChild(b);d||(d=sre.TrieNodeFactory.getNode(c,b,this.store),a.addChild(d));return d};
-sre.Trie.prototype.lookupRules=function(a,b){for(var c=[this.root],d=[];b.length;){for(var e=b.shift(),f=[];c.length;){var g=c.shift(),g=g.getChildren();g.forEach(function(a){a.getKind()===sre.TrieNode.Kind.DYNAMIC&&-1===e.indexOf(a.getConstraint())||f.push(a)})}c=f.slice()}for(;c.length;){g=c.shift();if(g.getRule){var h=g.getRule();h&&d.push(h)}g=g.findChildren(a);c=c.concat(g)}return d};
-sre.Trie.prototype.hasSubtrie=function(a){for(var b=this.root,c=0,d=a.length;c<d;c++)if(b=b.getChild(a[c]),!b)return!1;return!0};sre.Trie.prototype.toString=function(){return sre.Trie.printWithDepth_(this.root,0,"")};sre.Trie.prototype.collectRules=function(){return sre.Trie.collectRules_(this.root)};sre.Trie.prototype.order=function(){return sre.Trie.order_(this.root)};
-sre.Trie.printWithDepth_=function(a,b,c){var d=Array(b+2).join(b)+": ";c+=d+a.toString()+"\n";a=a.getChildren();for(var d=0,e;e=a[d];d++)c=sre.Trie.printWithDepth_(e,b+1,c);return c};sre.Trie.order_=function(a){a=a.getChildren();if(!a.length)return 0;var b=Math.max.apply(null,a.map(sre.Trie.order_));return Math.max(a.length,b)};
-sre.Trie.collectRules_=function(a){var b=[];for(a=[a];a.length;){var c=a.shift();if(c.getKind()===sre.TrieNode.Kind.QUERY||c.getKind()===sre.TrieNode.Kind.BOOLEAN){var d=c.getRule();d&&b.unshift(d)}a=a.concat(c.getChildren())}return b};sre.BaseRuleStore=function(){this.customQueries=new sre.SpeechRuleFunctions.CustomQueries;this.customStrings=new sre.SpeechRuleFunctions.CustomStrings;this.contextFunctions=new sre.SpeechRuleFunctions.ContextFunctions;this.speechRules_=[];this.trie=new sre.Trie(this);this.parseOrder=sre.DynamicCstr.DEFAULT_ORDER;this.parser=new sre.DynamicCstr.Parser(this.parseOrder);this.locale=sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE];this.initialized=!1};
-sre.BaseRuleStore.prototype.lookupRule=function(a,b){if(!a||a.nodeType!=sre.DomUtil.NodeType.ELEMENT_NODE&&a.nodeType!=sre.DomUtil.NodeType.TEXT_NODE)return null;var c=this.trie.lookupRules(a,b.allProperties());return 0<c.length?this.pickMostConstraint_(b,c):null};
-sre.BaseRuleStore.prototype.defineRule=function(a,b,c,d,e){var f;try{var g=sre.SpeechRule.Action.fromString(c),h=Array.prototype.slice.call(arguments,4),k=new sre.SpeechRule.Precondition(d,h),l=this.parseCstr(b);f=new sre.SpeechRule(a,l,k,g)}catch(m){if("RuleError"==m.name)return console.log("Rule Error ",d,"("+b+"):",m.message),null;throw m;}this.addRule(f);return f};sre.BaseRuleStore.prototype.addRule=function(a){this.trie.addRule(a);this.speechRules_.unshift(a)};
-sre.BaseRuleStore.prototype.deleteRule=function(a){a=this.speechRules_.indexOf(a);-1!=a&&this.speechRules_.splice(a,1)};sre.BaseRuleStore.prototype.findRule=function(a){for(var b=0,c;c=this.speechRules_[b];b++)if(a(c))return c;return null};sre.BaseRuleStore.prototype.findAllRules=function(a){return this.speechRules_.filter(a)};sre.BaseRuleStore.prototype.evaluateDefault=function(a){return[sre.AuditoryDescription.create({text:a.textContent})]};
-sre.BaseRuleStore.prototype.debugSpeechRule=function(a,b){var c=a.precondition,d=this.applyQuery(b,c.query);sre.Debugger.getInstance().output(c.query,d?d.toString():d);c.constraints.forEach(goog.bind(function(a){sre.Debugger.getInstance().output(a,this.applyConstraint(b,a))},this))};sre.BaseRuleStore.prototype.initialize=goog.abstractMethod;
-sre.BaseRuleStore.prototype.removeDuplicates=function(a){for(var b=this.speechRules_.length-1,c;c=this.speechRules_[b];b--)c!=a&&a.dynamicCstr.equal(c.dynamicCstr)&&sre.BaseRuleStore.comparePreconditions_(c,a)&&this.speechRules_.splice(b,1)};sre.BaseRuleStore.prototype.applyCustomQuery=function(a,b){var c=this.customQueries.lookup(b);return c?c(a):null};sre.BaseRuleStore.prototype.applySelector=function(a,b){return this.applyCustomQuery(a,b)||sre.XpathUtil.evalXPath(b,a)};
-sre.BaseRuleStore.prototype.applyQuery=function(a,b){var c=this.applySelector(a,b);return 0<c.length?c[0]:null};sre.BaseRuleStore.prototype.applyConstraint=function(a,b){return!!this.applyQuery(a,b)||sre.XpathUtil.evaluateBoolean(b,a)};
-sre.BaseRuleStore.prototype.pickMostConstraint_=function(a,b){var c=sre.Engine.getInstance().comparator;b.sort(function(a,b){return c.compare(a.dynamicCstr,b.dynamicCstr)||b.precondition.constraints.length-a.precondition.constraints.length});sre.Debugger.getInstance().generateOutput(goog.bind(function(){return b.map(function(a){return a.name+"("+a.dynamicCstr.toString()+")"})},this));return b[0]};
-sre.BaseRuleStore.compareStaticConstraints_=function(a,b){if(a.length!=b.length)return!1;for(var c=0,d;d=a[c];c++)if(-1==b.indexOf(d))return!1;return!0};sre.BaseRuleStore.comparePreconditions_=function(a,b){var c=a.precondition,d=b.precondition;return c.query!=d.query?!1:sre.BaseRuleStore.compareStaticConstraints_(c.constraints,d.constraints)};sre.BaseRuleStore.prototype.getSpeechRules=function(){return this.speechRules_};sre.BaseRuleStore.prototype.setSpeechRules=function(a){this.speechRules_=a};
-sre.BaseRuleStore.prototype.parseCstr=function(a){return this.parser.parse(this.locale+"."+a)};sre.MathStore=function(){sre.BaseRuleStore.call(this);this.initializer=[]};goog.inherits(sre.MathStore,sre.BaseRuleStore);sre.MathStore.prototype.initialize=function(){if(!this.initialized){for(var a=0,b;b=this.initializer[a];a++)b();this.setSpeechRules(this.trie.collectRules());this.initialized=!0}};
-sre.MathStore.prototype.defineUniqueRuleAlias=function(a,b,c,d){var e=this.parseCstr(b),f=this.findRule(goog.bind(function(b){return b.name==a&&e.equal(b.dynamicCstr)},this));if(!f)throw new sre.SpeechRule.OutputError("Rule named "+a+" with style "+b+" does not exist.");this.addAlias_(f,c,Array.prototype.slice.call(arguments,3))};
-sre.MathStore.prototype.defineRuleAlias=function(a,b,c){var d=this.findRule(function(b){return b.name==a});if(!d)throw new sre.SpeechRule.OutputError("Rule with named "+a+" does not exist.");this.addAlias_(d,b,Array.prototype.slice.call(arguments,2))};
-sre.MathStore.prototype.defineRulesAlias=function(a,b,c){var d=this.findAllRules(function(b){return b.name==a});if(0==d.length)throw new sre.SpeechRule.OutputError("Rule with name "+a+" does not exist.");var e=Array.prototype.slice.call(arguments,2);d.forEach(goog.bind(function(a){this.addAlias_(a,b,e)},this))};sre.MathStore.prototype.addAlias_=function(a,b,c){b=new sre.SpeechRule.Precondition(b,c);b=new sre.SpeechRule(a.name,a.dynamicCstr,b,a.action);b.name=a.name;this.addRule(b)};
-sre.MathStore.prototype.defineSpecialisedRule=function(a,b,c,d){var e=this.parseCstr(b),f=this.findRule(goog.bind(function(b){return b.name==a&&e.equal(b.dynamicCstr)},this));if(!f)throw new sre.SpeechRule.OutputError("Rule named "+a+" with style "+b+" does not exist.");b=this.parseCstr(c);d=d?sre.SpeechRule.Action.fromString(d):f.action;f=new sre.SpeechRule(f.name,b,f.precondition,d);this.addRule(f)};sre.MathStore.prototype.evaluateDefault=function(a){return this.evaluateString_(a.textContent)};
-sre.MathStore.prototype.evaluateString_=function(a){var b=[];if(a.match(/^\s+$/))return b;a=sre.BaseUtil.removeEmpty(a.replace(/\s/g," ").split(" "));for(var c=0,d;d=a[c];c++)if(1==d.length)b.push(this.evaluate_(d));else if(d.match(/^[a-zA-Z]+$/))b.push(this.evaluate_(d));else for(;d;){var e=d.match(/^((\d{1,3})(?=,)(,\d{3})*(\.\d+)?)|^\d*\.\d+|^\d+/),f=d.match(/^[a-zA-Z]+/);e?(b.push(this.evaluate_(e[0])),d=d.substring(e[0].length)):f?(b.push(this.evaluate_(f[0])),d=d.substring(f[0].length)):(e=
-d[0].charCodeAt(0),55296<=e&&56319>=e&&1<d.length&&!isNaN(d.charCodeAt(1))?(b.push(this.evaluate_(d.slice(0,2))),d=d.substring(2)):(b.push(this.evaluate_(d[0])),d=d.substring(1)))}return b};sre.MathStore.prototype.evaluate_=function(a){return sre.AuditoryDescription.create({text:a},{adjust:!0,translate:!0})};sre.WalkerUtil={};sre.WalkerUtil.splitAttribute=function(a){return a?a.split(/,/):[]};sre.WalkerUtil.getAttribute=function(a,b){return sre.DomUtil.getDataAttribute(a,b)};sre.WalkerUtil.getSemanticRoot=function(a){if(a.hasAttribute(sre.EnrichMathml.Attribute.TYPE)&&!a.hasAttribute(sre.EnrichMathml.Attribute.PARENT))return a;for(var b=sre.DomUtil.querySelectorAllByAttr(a,sre.EnrichMathml.Attribute.TYPE),c=0,d;d=b[c];c++)if(!d.hasAttribute(sre.EnrichMathml.Attribute.PARENT))return d;return a};
-sre.WalkerUtil.getBySemanticId=function(a,b){return a.getAttribute(sre.EnrichMathml.Attribute.ID)===b?a:sre.DomUtil.querySelectorAllByAttrValue(a,sre.EnrichMathml.Attribute.ID,b)[0]};sre.RebuildStree=function(a){this.nodeDict={};this.mathml=a;this.mmlRoot=sre.WalkerUtil.getSemanticRoot(a);this.streeRoot=this.assembleTree(this.mmlRoot);this.stree=sre.SemanticTree.fromNode(this.streeRoot,this.mathml);this.xml=this.stree.xml()};sre.RebuildStree.prototype.getTree=function(){return this.stree};
-sre.RebuildStree.prototype.assembleTree=function(a){var b=this.makeNode(a),c=sre.WalkerUtil.splitAttribute(sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.CHILDREN)),d=sre.WalkerUtil.splitAttribute(sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.CONTENT));if(0===d.length&&0===c.length)return b.textContent=a.textContent,b;if(0<d.length){var e=sre.WalkerUtil.getBySemanticId(a,d[0]);e&&(e=sre.WalkerUtil.splitAttribute(sre.WalkerUtil.getAttribute(e,sre.EnrichMathml.Attribute.OPERATOR)),
-1<e.length&&(b.textContent=e[1]))}e=function(c){c=sre.WalkerUtil.getBySemanticId(a,c);c=this.assembleTree(c);c.parent=b;return c};b.contentNodes=d.map(goog.bind(e,this));b.childNodes=c.map(goog.bind(e,this));return(c=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.COLLAPSED))?this.postProcess(b,c):b};
-sre.RebuildStree.prototype.makeNode=function(a){var b=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.TYPE),c=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.ROLE),d=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.FONT),e=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.ANNOTATION)||"",f=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.ID),g=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.EMBELLISHED);a=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.FENCEPOINTER);
-f=this.createNode(parseInt(f,10));f.type=b;f.role=c;f.font=d?d:sre.SemanticAttr.Font.UNKNOWN;f.parseAnnotation(e);a&&(f.fencePointer=a);g&&(f.embellished=g);return f};sre.RebuildStree.isPunctuated=function(a){return!sre.SemanticSkeleton.simpleCollapseStructure(a)&&a[1]&&sre.SemanticSkeleton.contentCollapseStructure(a[1])};sre.RebuildStree.prototype.makePunctuation=function(a){a=this.createNode(a);a.updateContent(sre.SemanticAttr.invisibleComma());a.role=sre.SemanticAttr.Role.DUMMY;return a};
-sre.RebuildStree.prototype.makePunctuated=function(a,b,c){var d=this.createNode(b[0]);d.type=sre.SemanticAttr.Type.PUNCTUATED;d.embellished=a.embellished;d.fencePointer=a.fencePointer;d.role=c;a=b.splice(1,1)[0].slice(1);d.contentNodes=a.map(goog.bind(this.makePunctuation,this));this.collapsedChildren_(b)};sre.RebuildStree.prototype.makeEmpty=function(a,b,c){b=this.createNode(b);b.type=sre.SemanticAttr.Type.EMPTY;b.embellished=a.embellished;b.fencePointer=a.fencePointer;b.role=c};
-sre.RebuildStree.prototype.makeIndex=function(a,b,c){sre.RebuildStree.isPunctuated(b)?this.makePunctuated(a,b,c):sre.SemanticSkeleton.simpleCollapseStructure(b)&&!this.nodeDict[b.toString()]&&this.makeEmpty(a,b,c)};
-sre.RebuildStree.prototype.postProcess=function(a,b){var c=sre.SemanticSkeleton.fromString(b).array;if(a.type===sre.SemanticAttr.Role.SUBSUP){var d=this.createNode(c[1][0]);d.type=sre.SemanticAttr.Type.SUBSCRIPT;d.role=sre.SemanticAttr.Role.SUBSUP;a.type=sre.SemanticAttr.Type.SUPERSCRIPT;d.embellished=a.embellished;d.fencePointer=a.fencePointer;this.makeIndex(a,c[1][2],sre.SemanticAttr.Role.RIGHTSUB);this.makeIndex(a,c[2],sre.SemanticAttr.Role.RIGHTSUPER);this.collapsedChildren_(c);return a}if(a.type===
-sre.SemanticAttr.Type.SUBSCRIPT)return this.makeIndex(a,c[2],sre.SemanticAttr.Role.RIGHTSUB),this.collapsedChildren_(c),a;if(a.type===sre.SemanticAttr.Type.SUPERSCRIPT)return this.makeIndex(a,c[2],sre.SemanticAttr.Role.RIGHTSUPER),this.collapsedChildren_(c),a;if(a.type===sre.SemanticAttr.Type.TENSOR)return this.makeIndex(a,c[2],sre.SemanticAttr.Role.LEFTSUB),this.makeIndex(a,c[3],sre.SemanticAttr.Role.LEFTSUPER),this.makeIndex(a,c[4],sre.SemanticAttr.Role.RIGHTSUB),this.makeIndex(a,c[5],sre.SemanticAttr.Role.RIGHTSUPER),
-this.collapsedChildren_(c),a;a.type===sre.SemanticAttr.Role.UNDEROVER&&(d=this.createNode(c[1][0]),a.childNodes[1].role===sre.SemanticAttr.Role.OVERACCENT?(d.type=sre.SemanticAttr.Type.OVERSCORE,a.type=sre.SemanticAttr.Type.UNDERSCORE):(d.type=sre.SemanticAttr.Type.UNDERSCORE,a.type=sre.SemanticAttr.Type.OVERSCORE),d.role=sre.SemanticAttr.Role.UNDEROVER,d.embellished=a.embellished,d.fencePointer=a.fencePointer,this.collapsedChildren_(c));return a};
-sre.RebuildStree.prototype.createNode=function(a){var b=new sre.SemanticNode(a);return this.nodeDict[a.toString()]=b};sre.RebuildStree.prototype.collapsedChildren_=function(a){var b=goog.bind(function(a){var c=this.nodeDict[a[0]];c.childNodes=[];for(var e=1,f=a.length;e<f;e++){var g=a[e];c.childNodes.push(sre.SemanticSkeleton.simpleCollapseStructure(g)?this.nodeDict[g]:b(g))}return c},this);b(a)};sre.SpeechGenerator=function(){};sre.SpeechGenerator.prototype.getSpeech=function(a,b){};sre.SpeechGenerator.prototype.getRebuilt=function(){};sre.SpeechGenerator.prototype.setRebuilt=function(a){};sre.SpeechGenerator.prototype.start=function(){};sre.SpeechGenerator.prototype.end=function(){};sre.MathSimpleStore=function(){sre.MathStore.call(this);this.category=""};goog.inherits(sre.MathSimpleStore,sre.MathStore);sre.MathSimpleStore.prototype.defineRulesFromMappings=function(a,b,c){for(var d in c)for(var e in c[d])this.defineRule(a,d+"."+e,'[t] "'+c[d][e]+'"',"self::text()",'"'===b?"self::text() = '"+b+"'":'self::text() = "'+b+'"')};
-sre.MathSimpleStore.prototype.lookupRule=function(a,b){var c=this.getSpeechRules().filter(function(a){return sre.MathSimpleStore.testDynamicConstraints_(b,a)});return c.length?c.sort(function(a,b){return sre.Engine.getInstance().comparator.compare(a.dynamicCstr,b.dynamicCstr)})[0]:null};sre.MathSimpleStore.testDynamicConstraints_=function(a,b){return sre.Engine.getInstance().strict?b.dynamicCstr.equal(a):sre.Engine.getInstance().comparator.match(b.dynamicCstr)};
-sre.MathCompoundStore=function(){this.subStores_={};this.locale=sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE]};goog.addSingletonGetter(sre.MathCompoundStore);sre.MathCompoundStore.prototype.defineRules=function(a,b,c,d){var e=this.subStores_[b];e?sre.Debugger.getInstance().output("Store exists! "+b):(e=new sre.MathSimpleStore,this.subStores_[b]=e);e.locale=this.locale;c&&(e.category=c);e.defineRulesFromMappings(a,b,d)};
-sre.MathCompoundStore.prototype.changeLocale_=function(a){if(!a.locale)return!1;this.locale=a.locale;return!0};sre.MathCompoundStore.prototype.addSymbolRules=function(a){if(!this.changeLocale_(a)){var b=sre.MathSimpleStore.parseUnicode_(a.key);this.defineRules(a.key,b,a.category,a.mappings)}};sre.MathCompoundStore.prototype.addFunctionRules=function(a){if(!this.changeLocale_(a)){var b=a.names,c=a.mappings;a=a.category;for(var d=0,e;e=b[d];d++)this.defineRules(e,e,a,c)}};
-sre.MathCompoundStore.prototype.addUnitRules=function(a){if(!this.changeLocale_(a)){var b=a.names;b&&(a.names=b.map(function(a){return a+":unit"}));this.addFunctionRules(a)}};sre.MathCompoundStore.prototype.lookupRule=function(a,b){var c=this.subStores_[a];return c?c.lookupRule(null,b):null};sre.MathCompoundStore.prototype.lookupCategory=function(a){return(a=this.subStores_[a])?a.category:""};
-sre.MathCompoundStore.prototype.lookupString=function(a,b){var c=this.lookupRule(a,b);return c?c.action.components.map(function(a){return a.content.slice(1,-1)}).join(" "):""};sre.MathSimpleStore.parseUnicode_=function(a){a=parseInt(a,16);if(65536>a)return String.fromCharCode(a);a-=65536;return String.fromCharCode((a>>10)+55296,(a&1023)+56320)};sre.MathMap=function(){this.store=sre.MathCompoundStore.getInstance();this.retrieveMaps()};goog.addSingletonGetter(sre.MathMap);sre.MathMap.toFetch_=0;sre.Engine.registerTest(function(){return sre.MathMap.getInstance()&&!sre.MathMap.toFetch_});sre.MathMap.prototype.stringify=function(){return JSON.stringify(this)};sre.MathMap.SYMBOLS_PATH_="symbols";sre.MathMap.FUNCTIONS_PATH_="functions";sre.MathMap.UNITS_PATH_="units";sre.MathMap.SYMBOLS_FILES_="greek-capital.js greek-small.js greek-scripts.js greek-mathfonts.js greek-symbols.js hebrew_letters.js latin-lower-double-accent.js latin-lower-normal.js latin-lower-phonetic.js latin-lower-single-accent.js latin-rest.js latin-upper-double-accent.js latin-upper-normal.js latin-upper-single-accent.js latin-mathfonts.js math_angles.js math_arrows.js math_characters.js math_delimiters.js math_digits.js math_geometry.js math_harpoons.js math_non_characters.js math_symbols.js math_whitespace.js other_stars.js spanish.js spanish_mathfonts.js".split(" ");
-sre.MathMap.FUNCTIONS_FILES_=["algebra.js","elementary.js","hyperbolic.js","trigonometry.js","functions_spanish.js"];sre.MathMap.UNITS_FILES_="energy.js length.js memory.js other.js speed.js temperature.js time.js volume.js weight.js units_spanish.js".split(" ");
-sre.MathMap.retrieveFiles=function(a,b,c){b=sre.BaseUtil.makePath(sre.SystemExternal.jsonPath+b);switch(sre.Engine.getInstance().mode){case sre.Engine.Mode.ASYNC:sre.MathMap.toFetch_+=a.length;for(var d=0,e;e=a[d];d++)sre.MathMap.fromFile_(b+e,function(a,b){sre.MathMap.toFetch_--;a||JSON.parse(b).forEach(function(a){c(a)})});break;case sre.Engine.Mode.HTTP:var f=sre.Engine.getInstance().isIE;sre.MathMap.toFetch_+=a.length;for(d=0;e=a[d];d++)f?sre.MathMap.getJsonIE_(e,c):sre.MathMap.getJsonAjax_(b+
-e,c);break;default:sre.MathMap.parseFiles(a.map(function(a){return b+a})).forEach(function(a){c(a)})}};
-sre.MathMap.prototype.retrieveMaps=function(){sre.MathMap.retrieveFiles(sre.MathMap.FUNCTIONS_FILES_,sre.MathMap.FUNCTIONS_PATH_,goog.bind(this.store.addFunctionRules,this.store));sre.MathMap.retrieveFiles(sre.MathMap.SYMBOLS_FILES_,sre.MathMap.SYMBOLS_PATH_,goog.bind(this.store.addSymbolRules,this.store));sre.MathMap.retrieveFiles(sre.MathMap.UNITS_FILES_,sre.MathMap.UNITS_PATH_,goog.bind(this.store.addUnitRules,this.store))};
-sre.MathMap.getJsonIE_=function(a,b,c){var d=c||1;sre.BrowserUtil.mapsForIE?((c=sre.BrowserUtil.mapsForIE[a])&&c.forEach(function(a){b(a)}),sre.MathMap.toFetch_--):5>=d?setTimeout(function(){sre.MathMap.getJsonIE_(a,b,d++)},300):sre.MathMap.toFetch_--};sre.MathMap.fromFile_=function(a,b){return sre.SystemExternal.fs.readFile(a,"utf8",b)};sre.MathMap.loadFile=function(a){try{return sre.MathMap.readJSON_(a)}catch(b){console.log("Unable to load file: "+a+", error: "+b)}};sre.MathMap.loadFiles=function(a){return a.map(sre.MathMap.loadFile)};
-sre.MathMap.parseFiles=function(a){a=sre.MathMap.loadFiles(a);return[].concat.apply([],a.map(function(a){return JSON.parse(a)}))};sre.MathMap.readJSON_=function(a){return sre.SystemExternal.fs.readFileSync(a)};sre.MathMap.getJsonAjax_=function(a,b){var c=new XMLHttpRequest;c.onreadystatechange=function(){4===c.readyState&&(sre.MathMap.toFetch_--,200===c.status&&JSON.parse(c.responseText).forEach(function(a){b(a)}))};c.open("GET",a,!0);c.send()};sre.AbstractionRules=function(){sre.MathStore.call(this)};goog.inherits(sre.AbstractionRules,sre.MathStore);goog.addSingletonGetter(sre.AbstractionRules);sre.AbstractionRules.mathStore=sre.AbstractionRules.getInstance();sre.AbstractionRules.defineRule_=goog.bind(sre.AbstractionRules.mathStore.defineRule,sre.AbstractionRules.mathStore);sre.AbstractionRules.defineRuleAlias_=goog.bind(sre.AbstractionRules.mathStore.defineRulesAlias,sre.AbstractionRules.mathStore);
-sre.AbstractionRules.defineSpecialisedRule_=goog.bind(sre.AbstractionRules.mathStore.defineSpecialisedRule,sre.AbstractionRules.mathStore);sre.AbstractionRules.defineUniqueRuleAlias_=goog.bind(sre.AbstractionRules.mathStore.defineUniqueRuleAlias,sre.AbstractionRules.mathStore);
-sre.AbstractionRules.initAbstractionRules_=function(){(0,sre.AbstractionRules.defineRule_)("abstr-collapsed","mathspeak.default",'[t] "collapsed"; [n] . (grammar:collapsed)',"self::*","@alternative",'not(@alternative="summary")','not(contains(@grammar, "collapsed"))');(0,sre.AbstractionRules.defineRule_)("abstr-identifier","mathspeak.default",'[t] "long identifier"',"self::identifier","@alternative","self::*","self::*","self::*","self::*");(0,sre.AbstractionRules.defineRule_)("abstr-identifier","mathspeak.default",
-'[t] "identifier"',"self::identifier",'@alternative="summary"',"@alternative","self::*","self::*","self::*","self::*");(0,sre.AbstractionRules.defineRule_)("abstr-identifier","mathspeak.brief",'[t] "identifier"',"self::identifier","@alternative","self::*","self::*","self::*","self::*");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-identifier","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-number","mathspeak.default",'[t] "long number"',"self::number","@alternative");
-(0,sre.AbstractionRules.defineRule_)("abstr-number","mathspeak.default",'[t] "number"',"self::number","@alternative",'@alternative="summary"');(0,sre.AbstractionRules.defineRule_)("abstr-number","mathspeak.brief",'[t] "number"',"self::number","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-number","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-mixed-number","mathspeak.default",'[t] "long mixed number"',"self::number","@alternative",'@role="mixed"');
-(0,sre.AbstractionRules.defineRule_)("abstr-mixed-number","mathspeak.brief",'[t] "mixed number"',"self::number","@alternative",'@role="mixed"');(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-mixed-number","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-text","mathspeak.default",'[t] "text"',"self::text","@alternative");(0,sre.AbstractionRules.defineRule_)("abstr-function","mathspeak.default",'[t] "functional expression"',"self::function","@alternative","self::*");
-(0,sre.AbstractionRules.defineRule_)("abstr-function","mathspeak.brief",'[t] "function"',"self::function","@alternative","self::*");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-function","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-lim","mathspeak.default",'[t] "limit function"',"self::function","@alternative",'@role="limit function"');(0,sre.AbstractionRules.defineRule_)("abstr-lim","mathspeak.brief",'[t] "lim"',"self::function","@alternative",'@role="limit function"');
-(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-lim","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-fraction","mathspeak.default",'[t] "fraction"',"self::fraction","@alternative");(0,sre.AbstractionRules.defineRule_)("abstr-fraction","mathspeak.brief",'[t] "frac"',"self::fraction","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-fraction","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-continued-fraction",
-"mathspeak.default",'[t] "continued fraction"',"self::fraction","@alternative",'children/*[2]/descendant-or-self::*[@role="ellipsis"]',"self::*","self::*");(0,sre.AbstractionRules.defineRule_)("abstr-continued-fraction","mathspeak.brief",'[t] "continued frac"',"self::fraction","@alternative",'children/*[2]/descendant-or-self::*[@role="ellipsis"]',"self::*","self::*");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-continued-fraction","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-sqrt",
-"mathspeak.default",'[t] "square root"',"self::sqrt","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-sqrt","mathspeak.default","mathspeak.brief");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-sqrt","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-sqrt-nested","mathspeak.default",'[t] "nested square root"',"self::sqrt","@alternative","children/*/descendant-or-self::sqrt or children/*/descendant-or-self::root");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-sqrt-nested",
-"mathspeak.default","mathspeak.brief");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-sqrt-nested","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-root","mathspeak.default",'[t] "root of index"; [n] children/*[1]; [t] "endindex"',"self::root","@alternative","following-sibling::* or ancestor::*/following-sibling::*");(0,sre.AbstractionRules.defineRule_)("abstr-root","mathspeak.brief",'[t] "root"',"self::root","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-root",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-root-nested","mathspeak.default",'[t] "nested root of index"; [n] children/*[1]',"self::root","@alternative","children/*/descendant-or-self::sqrt or children/*/descendant-or-self::root");(0,sre.AbstractionRules.defineRule_)("abstr-root-nested","mathspeak.default",'[t] "nested root of index"; [n] children/*[1]; [t] "endindex"',"self::root","@alternative","children/*/descendant-or-self::sqrt or children/*/descendant-or-self::root",
-"following-sibling::* or ancestor::*/following-sibling::*");(0,sre.AbstractionRules.defineRule_)("abstr-root-nested","mathspeak.brief",'[t] "nested root"',"self::root","@alternative","children/*/descendant-or-self::sqrt or children/*/descendant-or-self::root");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-root-nested","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-superscript","mathspeak.default",'[t] "power"',"self::superscript","@alternative","self::*",
-"self::*","self::*","self::*");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-superscript","mathspeak.default","mathspeak.brief");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-superscript","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-subscript","mathspeak.default",'[t] "subscript"',"self::subscript","@alternative","self::*","self::*","self::*");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-subscript","mathspeak.default","mathspeak.brief");
-(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-subscript","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-subsup","mathspeak.default",'[t] "power with subscript"',"self::superscript","@alternative",'name(children/*[1])="subscript"',"self::*","self::*","self::*");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-subsup","mathspeak.default","mathspeak.brief");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-subsup","mathspeak.brief","mathspeak.sbrief");
-(0,sre.AbstractionRules.defineRule_)("abstr-infixop","mathspeak.default",'[t] @role (grammar:localRole); [t] "with"; [t] count(./children/*); [t] "elements"',"self::infixop","@alternative");(0,sre.AbstractionRules.defineRule_)("abstr-infixop","mathspeak.default",'[t] @role (grammar:localRole); [t] "with variable number of elements"',"self::infixop","@alternative","count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-infixop","mathspeak.brief",
-"[t] @role (grammar:localRole)","self::infixop","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-infixop","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-addition","mathspeak.default",'[t] "sum with"; [t] count(./children/*); [t] "summands"',"self::infixop","@alternative",'@role="addition"');(0,sre.AbstractionRules.defineRule_)("abstr-addition","mathspeak.brief",'[t] "sum"',"self::infixop","@alternative",'@role="addition"');(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-addition",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-addition","mathspeak.default",'[t] "sum with variable number of summands"',"self::infixop","@alternative",'@role="addition"',"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-multiplication","mathspeak.default",'[t] "product with"; [t] count(./children/*); [t] "factors"',"self::infixop","@alternative",'@role="multiplication"');(0,sre.AbstractionRules.defineRule_)("abstr-multiplication",
-"mathspeak.brief",'[t] "product"',"self::infixop","@alternative",'@role="multiplication"');(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-multiplication","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRuleAlias_)("abstr-multiplication","self::infixop","@alternative",'@role="implicit"');(0,sre.AbstractionRules.defineRule_)("abstr-var-multiplication","mathspeak.default",'[t] "product with variable number of factors"',"self::infixop","@alternative",'@role="multiplication"',
-"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRuleAlias_)("abstr-var-multiplication","self::infixop","@alternative",'@role="implicit"',"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-vector","mathspeak.default",'[t] count(./children/*) ; [t] "dimensional vector"',"self::vector","@alternative");(0,sre.AbstractionRules.defineRule_)("abstr-vector","mathspeak.brief",'[t] "vector"',"self::vector",
-"@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-vector","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-vector","mathspeak.default",'[t] "n dimensional vector"',"self::vector","@alternative",'./children/*/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-binomial","mathspeak.default",'[t] "binomial"',"self::vector","@alternative",'@role="binomial"');(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-binomial",
-"mathspeak.default","mathspeak.brief");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-binomial","mathspeak.default","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-determinant","mathspeak.default",'[t] count(./children/*); [t] "dimensional determinant"',"self::matrix","@alternative",'@role="determinant"',"self::*");(0,sre.AbstractionRules.defineRule_)("abstr-determinant","mathspeak.brief",'[t] "determinant"',"self::matrix","@alternative",'@role="determinant"',"self::*");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-determinant",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-determinant","mathspeak.default",'[t] "n dimensional determinant"',"self::matrix","@alternative",'@role="determinant"','./children/*/children/*/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-squarematrix","mathspeak.default",'[t] count(./children/*); [t] "dimensional square matrix"',"self::matrix","@alternative",'@role="squarematrix"');(0,sre.AbstractionRules.defineRule_)("abstr-squarematrix",
-"mathspeak.brief",'[t] "square matrix"',"self::matrix","@alternative",'@role="squarematrix"');(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-squarematrix","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-rowvector","mathspeak.default",'[t] count(./children/row/children/*); [t] "dimensional row vector"',"self::matrix","@alternative",'@role="rowvector"');(0,sre.AbstractionRules.defineRule_)("abstr-rowvector","mathspeak.brief",'[t] "row vector"',"self::matrix",
-"@alternative",'@role="rowvector"');(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-rowvector","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-matrix","mathspeak.default",'[t] "n dimensional row vector"',"self::matrix","@alternative",'@role="rowvector"','./children/*/children/*/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-matrix","mathspeak.default",'[t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "matrix"',
-"self::matrix","@alternative");(0,sre.AbstractionRules.defineRule_)("abstr-matrix","mathspeak.brief",'[t] "matrix"',"self::matrix","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-matrix","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-matrix","mathspeak.default",'[t] "n by m dimensional matrix"',"self::matrix","@alternative",'./children/*/children/*/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-cases",
-"mathspeak.default",'[t] "case statement";[t] "with"; [t] count(children/*); [t] "cases"',"self::cases","@alternative");(0,sre.AbstractionRules.defineRule_)("abstr-cases","mathspeak.brief",'[t] "case statement"',"self::cases","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-cases","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-cases","mathspeak.default",'[t] "case statement with variable number of cases"',"self::cases","@alternative",'./children/row/children/cell/children/punctuation[@role="ellipsis"]or ./children/line/children/punctuation[@role="ellipsis"]');
-(0,sre.AbstractionRules.defineRule_)("abstr-punctuated","mathspeak.default",'[n] content/*[1]; [t] "separated list";[t] "of length"; [t] count(children/*) - count(content/*)',"self::punctuated","@alternative");(0,sre.AbstractionRules.defineRule_)("abstr-punctuated","mathspeak.brief",'[n] content/*[1]; [t] "separated list"',"self::punctuated","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-punctuated","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-punctuated",
-"mathspeak.default",'[n] content/*[1]; [t] "separated list";[t] "of variable length"',"self::punctuated","@alternative",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-bigop","mathspeak.default","[n] content/*[1]","self::bigop","@alternative","self::*");(0,sre.AbstractionRules.defineRule_)("abstr-integral","mathspeak.default",'[t] "integral"',"self::*","@alternative",'@role="integral"');(0,sre.AbstractionRules.defineRule_)("abstr-relation","mathspeak.default",
-"[t] @role (grammar:localRole);","self::relseq","@alternative","count(./children/*)=2");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-relation","mathspeak.default","mathspeak.brief");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-relation","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-relation","mathspeak.default",'[t] @role (grammar:localRole); [t] "sequence"; [t] "with"; [t] count(./children/*); [t] "elements"',"self::relseq","@alternative","count(./children/*)>2");
-(0,sre.AbstractionRules.defineRule_)("abstr-relation","mathspeak.brief",'[t] @role (grammar:localRole); [t] "sequence"',"self::relseq","@alternative","count(./children/*)>2");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-relation","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-relation","mathspeak.default",'[t] @role (grammar:localRole); [t] "sequence"; [t] "with variable number of elements"',"self::relseq","@alternative","count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');
-(0,sre.AbstractionRules.defineUniqueRuleAlias_)("abstr-relation","mathspeak.default","self::multirel","@alternative",'@role!="unknown"',"count(./children/*)>2");(0,sre.AbstractionRules.defineUniqueRuleAlias_)("abstr-relation","mathspeak.brief","self::multirel","@alternative",'@role!="unknown"',"count(./children/*)>2");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-relation","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRuleAlias_)("abstr-var-relation","self::multirel",
-"@alternative",'@role!="unknown"',"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-multirel","mathspeak.default",'[t] "relation sequence"; [t] "with"; [t] count(./children/*); [t] "elements"',"self::multirel","@alternative","count(./children/*)>2");(0,sre.AbstractionRules.defineRule_)("abstr-multirel","mathspeak.brief",'[t] "relation sequence"',"self::multirel","@alternative","count(./children/*)>2");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-multirel",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-var-multirel","mathspeak.default",'[t] "relation sequence with variable number of elements"',"self::multirel","@alternative","count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionRules.defineRule_)("abstr-table","mathspeak.default",'[t] "table with"; [t] count(children/*); [t] "rows and";[t] count(children/*[1]/children/*); [t] "columns"',"self::table","@alternative");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-table",
-"mathspeak.default","mathspeak.brief");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-table","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-line","mathspeak.default",'[t] "in"; [t] @role (grammar:localRole);',"self::line","@alternative");(0,sre.AbstractionRules.defineRule_)("abstr-row","mathspeak.default",'[t] "in"; [t] @role (grammar:localRole);[t] count(preceding-sibling::..); [t] "with";[t] count(children/*); [t] "columns"',"self::row","@alternative",
-"*");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-row","mathspeak.default","mathspeak.brief");(0,sre.AbstractionRules.defineSpecialisedRule_)("abstr-row","mathspeak.default","mathspeak.sbrief");(0,sre.AbstractionRules.defineRule_)("abstr-cell","mathspeak.default",'[t] "in"; [t] @role (grammar:localRole);',"self::cell","@alternative")};sre.AbstractionRules.getInstance().initializer=[sre.AbstractionRules.initAbstractionRules_];sre.AbstractionSpanish=function(){sre.MathStore.call(this);this.locale="es"};goog.inherits(sre.AbstractionSpanish,sre.MathStore);goog.addSingletonGetter(sre.AbstractionSpanish);sre.AbstractionSpanish.mathStore=sre.AbstractionSpanish.getInstance();sre.AbstractionSpanish.defineRule_=goog.bind(sre.AbstractionSpanish.mathStore.defineRule,sre.AbstractionSpanish.mathStore);sre.AbstractionSpanish.defineRuleAlias_=goog.bind(sre.AbstractionSpanish.mathStore.defineRulesAlias,sre.AbstractionSpanish.mathStore);
-sre.AbstractionSpanish.defineSpecialisedRule_=goog.bind(sre.AbstractionSpanish.mathStore.defineSpecialisedRule,sre.AbstractionSpanish.mathStore);sre.AbstractionSpanish.defineUniqueRuleAlias_=goog.bind(sre.AbstractionSpanish.mathStore.defineUniqueRuleAlias,sre.AbstractionSpanish.mathStore);
-sre.AbstractionSpanish.initAbstractionSpanish_=function(){(0,sre.AbstractionSpanish.defineRule_)("abstr-collapsed","mathspeak.default",'[n] . (grammar:collapsed); [t] "plegado"',"self::*","@alternative",'not(@alternative="summary")','not(contains(@grammar, "collapsed"))');(0,sre.AbstractionSpanish.defineRule_)("abstr-identifier","mathspeak.default",'[t] "identificador largo"',"self::identifier","@alternative","self::*","self::*","self::*","self::*");(0,sre.AbstractionSpanish.defineRule_)("abstr-identifier",
-"mathspeak.default",'[t] "identificador"',"self::identifier",'@alternative="summary"',"@alternative","self::*","self::*","self::*","self::*");(0,sre.AbstractionSpanish.defineRule_)("abstr-identifier","mathspeak.brief",'[t] "identificador"',"self::identifier","@alternative","self::*","self::*","self::*","self::*");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-identifier","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-number","mathspeak.default",'[t] "n\u00famero largo"',
-"self::number","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-number","mathspeak.default",'[t] "n\u00famero"',"self::number","@alternative",'@alternative="summary"');(0,sre.AbstractionSpanish.defineRule_)("abstr-number","mathspeak.brief",'[t] "n\u00famero"',"self::number","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-number","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-mixed-number","mathspeak.default",'[t] "n\u00famero largo mixto"',
-"self::number","@alternative",'@role="mixed"');(0,sre.AbstractionSpanish.defineRule_)("abstr-mixed-number","mathspeak.brief",'[t] "numero mixto"',"self::number","@alternative",'@role="mixed"');(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-mixed-number","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-text","mathspeak.default",'[t] "texto"',"self::text","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-function","mathspeak.default",'[t] "expresi\u00f3n funcional"',
-"self::function","@alternative","self::*");(0,sre.AbstractionSpanish.defineRule_)("abstr-function","mathspeak.brief",'[t] "funci\u00f3n"',"self::function","@alternative","self::*");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-function","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-lim","mathspeak.default",'[t] "funci\u00f3n de l\u00edmite"',"self::function","@alternative",'@role="limit function"');(0,sre.AbstractionSpanish.defineRule_)("abstr-lim",
-"mathspeak.brief",'[t] "l\u00edmite"',"self::function","@alternative",'@role="limit function"');(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-lim","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-fraction","mathspeak.default",'[t] "fracci\u00f3n"',"self::fraction","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-fraction","mathspeak.brief",'[t] "frac"',"self::fraction","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-fraction",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-continued-fraction","mathspeak.default",'[t] "fracci\u00f3n continua"',"self::fraction","@alternative",'children/*[2]/descendant-or-self::*[@role="ellipsis"]',"self::*","self::*");(0,sre.AbstractionSpanish.defineRule_)("abstr-continued-fraction","mathspeak.brief",'[t] "frac continua"',"self::fraction","@alternative",'children/*[2]/descendant-or-self::*[@role="ellipsis"]',"self::*","self::*");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-continued-fraction",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-sqrt","mathspeak.default",'[t] "ra\u00edz cuadrada"',"self::sqrt","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-sqrt","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-sqrt","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-sqrt-nested","mathspeak.default",'[t] "ra\u00edz cuadrada anidada"',"self::sqrt","@alternative",
-"children/*/descendant-or-self::sqrt or children/*/descendant-or-self::root");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-sqrt-nested","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-sqrt-nested","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-root","mathspeak.default",'[t] "ra\u00edz del \u00edndice"; [n] children/*[1]; [t] "finalizar de \u00edndice"',"self::root","@alternative","following-sibling::* or ancestor::*/following-sibling::*");
-(0,sre.AbstractionSpanish.defineRule_)("abstr-root","mathspeak.brief",'[t] "ra\u00edz"',"self::root","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-root","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-root-nested","mathspeak.default",'[t] "ra\u00edz anidada del \u00edndice"; [n] children/*[1]',"self::root","@alternative","children/*/descendant-or-self::sqrt or children/*/descendant-or-self::root");(0,sre.AbstractionSpanish.defineRule_)("abstr-root-nested",
-"mathspeak.default",'[t] "ra\u00edz anidada del \u00edndice"; [n] children/*[1]; [t] "finalizar de \u00edndice"',"self::root","@alternative","children/*/descendant-or-self::sqrt or children/*/descendant-or-self::root","following-sibling::* or ancestor::*/following-sibling::*");(0,sre.AbstractionSpanish.defineRule_)("abstr-root-nested","mathspeak.brief",'[t] "ra\u00edz anidada"',"self::root","@alternative","children/*/descendant-or-self::sqrt or children/*/descendant-or-self::root");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-root-nested",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-superscript","mathspeak.default",'[t] "potencia"',"self::superscript","@alternative","self::*","self::*","self::*","self::*");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-superscript","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-superscript","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-subscript","mathspeak.default",
-'[t] "sub\u00edndice"',"self::subscript","@alternative","self::*","self::*","self::*");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-subscript","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-subscript","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-subsup","mathspeak.default",'[t] "potencia con sub\u00edndice"',"self::superscript","@alternative",'name(children/*[1])="subscript"',"self::*","self::*","self::*");
-(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-subsup","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-subsup","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-infixop","mathspeak.default",'[t] @role (grammar:localRole); [t] "con"; [t] count(./children/*); [t] "elementos"',"self::infixop","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-infixop","mathspeak.default",'[t] @role (grammar:localRole); [t] "con una cantidad variable de elementos"',
-"self::infixop","@alternative","count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-infixop","mathspeak.brief","[t] @role (grammar:localRole)","self::infixop","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-infixop","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-addition","mathspeak.default",'[t] "suma con"; [t] count(./children/*); [t] "sumandos"',"self::infixop","@alternative",
-'@role="addition"');(0,sre.AbstractionSpanish.defineRule_)("abstr-addition","mathspeak.brief",'[t] "suma"',"self::infixop","@alternative",'@role="addition"');(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-addition","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-addition","mathspeak.default",'[t] "suma con n\u00famero variable de sumandos"',"self::infixop","@alternative",'@role="addition"',"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');
-(0,sre.AbstractionSpanish.defineRule_)("abstr-multiplication","mathspeak.default",'[t] "producto con"; [t] count(./children/*); [t] "factores"',"self::infixop","@alternative",'@role="multiplication"');(0,sre.AbstractionSpanish.defineRule_)("abstr-multiplication","mathspeak.brief",'[t] "producto"',"self::infixop","@alternative",'@role="multiplication"');(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-multiplication","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRuleAlias_)("abstr-multiplication",
-"self::infixop","@alternative",'@role="implicit"');(0,sre.AbstractionSpanish.defineRule_)("abstr-var-multiplication","mathspeak.default",'[t] "producto con una cantidad variable de factores"',"self::infixop","@alternative",'@role="multiplication"',"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRuleAlias_)("abstr-var-multiplication","self::infixop","@alternative",'@role="implicit"',"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');
-(0,sre.AbstractionSpanish.defineRule_)("abstr-vector","mathspeak.default",'[t] "vector de dimensi\u00f3n"; [t] count(./children/*)',"self::vector","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-vector","mathspeak.brief",'[t] "vector"',"self::vector","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-vector","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-vector","mathspeak.default",'[t] "vector de dimensi\u00f3n n"',"self::vector",
-"@alternative",'./children/*/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-binomial","mathspeak.default",'[t] "binomio"',"self::vector","@alternative",'@role="binomial"');(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-binomial","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-binomial","mathspeak.default","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-determinant","mathspeak.default",
-'[t] "determinante de dimensi\u00f3n"; [t] count(./children/*)',"self::matrix","@alternative",'@role="determinant"',"self::*");(0,sre.AbstractionSpanish.defineRule_)("abstr-determinant","mathspeak.brief",'[t] "determinante"',"self::matrix","@alternative",'@role="determinant"',"self::*");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-determinant","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-determinant","mathspeak.default",'[t] "determinante de dimensi\u00f3n n"',
-"self::matrix","@alternative",'@role="determinant"','./children/*/children/*/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-squarematrix","mathspeak.default",'[t] "matriz cuadrada de dimensi\u00f3n"; [t] count(./children/*)',"self::matrix","@alternative",'@role="squarematrix"');(0,sre.AbstractionSpanish.defineRule_)("abstr-squarematrix","mathspeak.brief",'[t] "matriz cuadrada"',"self::matrix","@alternative",'@role="squarematrix"');(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-squarematrix",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-rowvector","mathspeak.default",'[t] "vector fila de dimensi\u00f3n"; [t] count(./children/row/children/*) ',"self::matrix","@alternative",'@role="rowvector"');(0,sre.AbstractionSpanish.defineRule_)("abstr-rowvector","mathspeak.brief",'[t] "vector fila"',"self::matrix","@alternative",'@role="rowvector"');(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-rowvector","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-matrix",
-"mathspeak.default",'[t] "vector fila de dimensi\u00f3n n"',"self::matrix","@alternative",'@role="rowvector"','./children/*/children/*/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-matrix","mathspeak.default",'[t] count(children/*); [t] "por";[t] count(children/*[1]/children/*); [t] "matriz"',"self::matrix","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-matrix","mathspeak.brief",'[t] "matriz"',"self::matrix","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-matrix",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-matrix","mathspeak.default",'[t] "matriz de dimensi\u00f3n n por m"',"self::matrix","@alternative",'./children/*/children/*/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-cases","mathspeak.default",'[t] "declaraci\u00f3n de caso";[t] "con"; [t] count(children/*); [t] "casos"',"self::cases","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-cases","mathspeak.brief",
-'[t] "declaraci\u00f3n de caso"',"self::cases","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-cases","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-cases","mathspeak.default",'[t] "declaraci\u00f3n de caso con n\u00famero variable de casos"',"self::cases","@alternative",'./children/row/children/cell/children/punctuation[@role="ellipsis"]or ./children/line/children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-punctuated",
-"mathspeak.default",'[t] "lista separada por"; [n] content/*[1]; [t] "de longitud"; [t] count(children/*) - count(content/*)',"self::punctuated","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-punctuated","mathspeak.brief",'[t] "lista separada por"; [n] content/*[1]',"self::punctuated","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-punctuated","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-punctuated","mathspeak.default",
-'[t] "lista separada por"; [n] content/*[1]','[t] "de longitud variable"',"self::punctuated","@alternative",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-bigop","mathspeak.default","[n] content/*[1]","self::bigop","@alternative","self::*");(0,sre.AbstractionSpanish.defineRule_)("abstr-integral","mathspeak.default",'[t] "integral"',"self::*","@alternative",'@role="integral"');(0,sre.AbstractionSpanish.defineRule_)("abstr-relation","mathspeak.default","[t] @role (grammar:localRole);",
-"self::relseq","@alternative","count(./children/*)=2");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-relation","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-relation","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-relation","mathspeak.default",'[t] "secuencia de"; [t] @role (grammar:localRole); [t] "con"; [t] count(./children/*); [t] "elementos"',"self::relseq","@alternative","count(./children/*)>2");
-(0,sre.AbstractionSpanish.defineRule_)("abstr-relation","mathspeak.brief",'[t] "secuencia de"; [t] @role (grammar:localRole)',"self::relseq","@alternative","count(./children/*)>2");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-relation","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-relation","mathspeak.default",'[t] "secuencia de"; [t] @role (grammar:localRole); [t] "con una cantidad variable de elementos"',"self::relseq","@alternative","count(./children/*)>2",
-'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineUniqueRuleAlias_)("abstr-relation","mathspeak.default","self::multirel","@alternative",'@role!="unknown"',"count(./children/*)>2");(0,sre.AbstractionSpanish.defineUniqueRuleAlias_)("abstr-relation","mathspeak.brief","self::multirel","@alternative",'@role!="unknown"',"count(./children/*)>2");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-relation","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRuleAlias_)("abstr-var-relation",
-"self::multirel","@alternative",'@role!="unknown"',"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-multirel","mathspeak.default",'[t] "secuencia de relaci\u00f3n"; [t] "con"; [t] count(./children/*); [t] "elementos"',"self::multirel","@alternative","count(./children/*)>2");(0,sre.AbstractionSpanish.defineRule_)("abstr-multirel","mathspeak.brief",'[t] "secuencia de relaci\u00f3n"',"self::multirel","@alternative","count(./children/*)>2");
-(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-multirel","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-var-multirel","mathspeak.default",'[t] "secuencia de relaci\u00f3n con n\u00famero variable de elementos"',"self::multirel","@alternative","count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.AbstractionSpanish.defineRule_)("abstr-table","mathspeak.default",'[t] "mesa con"; [t] count(children/*); [t] "filas y";[t] count(children/*[1]/children/*); [t] "columnas"',
-"self::table","@alternative");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-table","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-table","mathspeak.brief","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-line","mathspeak.default",'[t] "en"; [t] @role (grammar:localRole);',"self::line","@alternative");(0,sre.AbstractionSpanish.defineRule_)("abstr-row","mathspeak.default",'[t] "en"; [t] @role (grammar:localRole);[t] count(preceding-sibling::..); [t] "con";[t] count(children/*); [t] "columnas"',
-"self::row","@alternative","*");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-row","mathspeak.default","mathspeak.brief");(0,sre.AbstractionSpanish.defineSpecialisedRule_)("abstr-row","mathspeak.default","mathspeak.sbrief");(0,sre.AbstractionSpanish.defineRule_)("abstr-cell","mathspeak.default",'[t] "en"; [t] @role (grammar:localRole);',"self::cell","@alternative")};sre.AbstractionSpanish.getInstance().initializer=[sre.AbstractionSpanish.initAbstractionSpanish_];sre.ClearspeakPreferences=function(a,b){sre.DynamicCstr.call(this,a);this.preference=b};goog.inherits(sre.ClearspeakPreferences,sre.DynamicCstr);sre.ClearspeakPreferences.prototype.equal=function(a){if(!sre.ClearspeakPreferences.superClass_.equal.call(this,a))return!1;var b=Object.keys(this.preference);a=a.preference;if(b.length!==Object.keys(a).length)return!1;for(var c=0,d;d=b[c];c++)if(this.preference[d]!==a[d])return!1;return!0};sre.ClearspeakPreferences.AUTO="Auto";
-sre.ClearspeakPreferences.PREFERENCES=new sre.DynamicProperties({AbsoluteValue:["Auto","AbsEnd","Cardinality","Determinant"],Bar:["Auto","Conjugate"],Caps:["Auto","SayCaps"],CombinationPermutation:["Auto","ChoosePermute"],Ellipses:["Auto","AndSoOn"],Exponent:["Auto","AfterPower","Ordinal","OrdinalPower"],Fraction:"Auto EndFrac FracOver General GeneralEndFrac Ordinal Over OverEndFrac Per".split(" "),Functions:["Auto","None"],ImpliedTimes:["Auto","MoreImpliedTimes","None"],Log:["Auto","LnAsNaturalLog"],
-Matrix:"Auto Combinatoric EndMatrix EndVector SilentColNum SpeakColNum Vector".split(" "),MultiLineLabel:"Auto Case Constraint Equation Line None Row Step".split(" "),MultiLineOverview:["Auto","None"],MultiLinePausesBetweenColumns:["Auto","Long","Short"],MultsymbolDot:["Auto","Dot"],MultsymbolX:["Auto","By","Cross"],Paren:"Auto CoordPoint Interval Silent Speak SpeakNestingLevel".split(" "),Prime:["Auto","Angle","Length"],Roots:["Auto","PosNegSqRoot","PosNegSqRootEnd","RootEnd"],SetMemberSymbol:["Auto",
-"Belongs","Element","Member"],Sets:["Auto","SilentBracket","woall","woAll"],TriangleSymbol:["Auto","Delta"],Trig:["Auto","ArcTrig","TrigInverse"],VerticalLine:["Auto","Divides","Given","SuchThat"]});sre.ClearspeakPreferences.comparator=function(){return new sre.ClearspeakPreferences.Comparator(sre.Engine.getInstance().dynamicCstr,sre.DynamicProperties.create([sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE]],["mathspeak","default"],["short","default"]))};
-sre.ClearspeakPreferences.Comparator=function(a,b){sre.DynamicCstr.DefaultComparator.call(this,a,b);this.preference=a.preference||{}};goog.inherits(sre.ClearspeakPreferences.Comparator,sre.DynamicCstr.DefaultComparator);sre.ClearspeakPreferences.Comparator.prototype.match=function(a){if(!sre.ClearspeakPreferences.Comparator.superClass_.match.call(this,a))return!1;if(!a.preference)return!0;for(var b=Object.keys(a.preference),c=0,d;d=b[c];c++)if(this.preference[d]!==a.preference[d])return!1;return!0};
-sre.ClearspeakPreferences.Comparator.prototype.compare=function(a,b){var c=sre.ClearspeakPreferences.Comparator.superClass_.compare.call(this,a,b);if(0!==c)return c;if(!a.preference&&b.preference)return 1;if(a.preference&&!b.preference)return-1;if(!a.preference&&!b.preference)return 0;var c=Object.keys(a.preference).length,d=Object.keys(b.preference).length;return c>d?-1:c<d?1:0};
-sre.ClearspeakPreferences.Parser=function(){sre.DynamicCstr.Parser.call(this,[sre.DynamicCstr.Axis.LOCALE,sre.DynamicCstr.Axis.DOMAIN,sre.DynamicCstr.Axis.STYLE])};goog.inherits(sre.ClearspeakPreferences.Parser,sre.DynamicCstr.Parser);
-sre.ClearspeakPreferences.Parser.prototype.parse=function(a){a=sre.ClearspeakPreferences.Parser.superClass_.parse.call(this,a);var b=a.getValue(sre.DynamicCstr.Axis.STYLE);a=a.getValue(sre.DynamicCstr.Axis.LOCALE);if(b===sre.DynamicCstr.DEFAULT_VALUE)return new sre.ClearspeakPreferences({locale:a,domain:"clearspeak",style:sre.DynamicCstr.DEFAULT_VALUE},{});for(var b=b.split(":"),c={},d=sre.ClearspeakPreferences.PREFERENCES.getProperties(),e=Object.keys(d),f=0,g;g=b[f];f++)if(g=g.split("_"),-1!==e.indexOf(g[0])){var h=
-g[1];h&&h!==sre.ClearspeakPreferences.AUTO&&-1!==d[g[0]].indexOf(h)&&(c[g[0]]=g[1])}return new sre.ClearspeakPreferences({locale:a,domain:"clearspeak",style:this.combine_(c)},c)};sre.ClearspeakPreferences.Parser.prototype.combine_=function(a){for(var b=Object.keys(a),c=[],d=0;d<b.length;d++)c.push(b[d]+"_"+a[b[d]]);return c.length?c.join(":"):sre.DynamicCstr.DEFAULT_VALUE};sre.StoreUtil={};sre.StoreUtil.nodeCounter=function(a,b){var c=a.length,d=0,e=b;b||(e="");return function(){d<c&&(d+=1);return e+" "+d}};sre.StoreUtil.pauseSeparator=function(a,b){var c=parseFloat(b),d=isNaN(c)?b:c;return function(){return[sre.AuditoryDescription.create({text:"",personality:{pause:d}})]}};sre.ClearspeakUtil={};sre.ClearspeakUtil.numbersToAlpha=function(a){return a.match(/\d+/)?sre.MathspeakUtil.numberToWords(parseInt(a,10)):a};sre.ClearspeakUtil.nodeCounter=function(a,b){var c=b.split("-"),d=sre.StoreUtil.nodeCounter(a,c[0]||""),e=c[1]||"",f=c[2]||"",g=!0;return function(){var a=d();return g?(g=!1,f+a+e):a+e}};
-sre.ClearspeakUtil.isSimpleExpression=function(a){return sre.ClearspeakUtil.isSimpleNumber_(a)||sre.ClearspeakUtil.isSimpleLetters_(a)||sre.ClearspeakUtil.isSimpleDegree_(a)||sre.ClearspeakUtil.isSimpleNegative_(a)||sre.ClearspeakUtil.isSimpleFunction_(a)};
-sre.ClearspeakUtil.isSimpleFunction_=function(a){return a.type===sre.SemanticAttr.Type.APPL&&(a.childNodes[0].role===sre.SemanticAttr.Role.PREFIXFUNC||a.childNodes[0].role===sre.SemanticAttr.Role.SIMPLEFUNC)&&(sre.ClearspeakUtil.isSimple_(a.childNodes[1])||a.childNodes[1].type===sre.SemanticAttr.Type.FENCED&&sre.ClearspeakUtil.isSimple_(a.childNodes[1].childNodes[0]))};
-sre.ClearspeakUtil.isSimpleNegative_=function(a){return a.type===sre.SemanticAttr.Type.PREFIXOP&&a.role===sre.SemanticAttr.Role.NEGATIVE&&sre.ClearspeakUtil.isSimple_(a.childNodes[0])&&a.childNodes[0].type!==sre.SemanticAttr.Type.PREFIXOP&&a.childNodes[0].type!==sre.SemanticAttr.Type.APPL&&a.childNodes[0].type!==sre.SemanticAttr.Type.PUNCTUATED};
-sre.ClearspeakUtil.isSimpleDegree_=function(a){return a.type===sre.SemanticAttr.Type.PUNCTUATED&&a.role===sre.SemanticAttr.Role.ENDPUNCT&&2===a.childNodes.length&&a.childNodes[1].role===sre.SemanticAttr.Role.DEGREE&&(sre.ClearspeakUtil.isLetter_(a.childNodes[0])||sre.ClearspeakUtil.isNumber_(a.childNodes[0])||a.childNodes[0].type===sre.SemanticAttr.Type.PREFIXOP&&a.childNodes[0].role===sre.SemanticAttr.Role.NEGATIVE&&(sre.ClearspeakUtil.isLetter_(a.childNodes[0].childNodes[0])||sre.ClearspeakUtil.isNumber_(a.childNodes[0].childNodes[0])))};
-sre.ClearspeakUtil.isSimpleLetters_=function(a){return sre.ClearspeakUtil.isLetter_(a)||a.type===sre.SemanticAttr.Type.INFIXOP&&a.role===sre.SemanticAttr.Role.IMPLICIT&&(2===a.childNodes.length&&(sre.ClearspeakUtil.isLetter_(a.childNodes[0])||sre.ClearspeakUtil.isSimpleNumber_(a.childNodes[0]))&&sre.ClearspeakUtil.isLetter_(a.childNodes[1])||3===a.childNodes.length&&sre.ClearspeakUtil.isSimpleNumber_(a.childNodes[0])&&sre.ClearspeakUtil.isLetter_(a.childNodes[1])&&sre.ClearspeakUtil.isLetter_(a.childNodes[2]))};
-sre.ClearspeakUtil.isSimple_=function(a){return a.hasAnnotation("clearspeak","simple")};sre.ClearspeakUtil.isLetter_=function(a){return a.type===sre.SemanticAttr.Type.IDENTIFIER&&(a.role===sre.SemanticAttr.Role.LATINLETTER||a.role===sre.SemanticAttr.Role.GREEKLETTER||a.role===sre.SemanticAttr.Role.OTHERLETTER||a.role===sre.SemanticAttr.Role.SIMPLEFUNC)};sre.ClearspeakUtil.isNumber_=function(a){return a.type===sre.SemanticAttr.Type.NUMBER&&(a.role===sre.SemanticAttr.Role.INTEGER||a.role===sre.SemanticAttr.Role.FLOAT)};
-sre.ClearspeakUtil.isSimpleNumber_=function(a){return sre.ClearspeakUtil.isNumber_(a)||sre.ClearspeakUtil.isSimpleFraction_(a)};
-sre.ClearspeakUtil.isSimpleFraction_=function(a){if(sre.ClearspeakUtil.hasPreference("Fraction_Over")||sre.ClearspeakUtil.hasPreference("Fraction_FracOver")||a.type!==sre.SemanticAttr.Type.FRACTION||a.role!==sre.SemanticAttr.Role.VULGAR)return!1;if(sre.ClearspeakUtil.hasPreference("Fraction_Ordinal"))return!0;var b=a.childNodes[0].textContent;a=a.childNodes[1].textContent;return 0<b&&20>b&&0<a&&11>a};sre.ClearspeakUtil.hasPreference=function(a){return sre.Engine.getInstance().style===a};
-sre.ClearspeakUtil.simpleExpression=function(){return new sre.SemanticAnnotator("clearspeak",function(a){return sre.ClearspeakUtil.isSimpleExpression(a)?"simple":""})};sre.ClearspeakUtil.simpleNode=function(a){if(!a.hasAttribute("annotation"))return!1;a=a.getAttribute("annotation");return!!/clearspeak:simple$|clearspeak:simple;/.exec(a)};
-sre.ClearspeakUtil.simpleCell_=function(a){if(sre.ClearspeakUtil.simpleNode(a))return!0;if(a.tagName!==sre.SemanticAttr.Type.SUBSCRIPT)return!1;a=a.childNodes[0].childNodes;var b=a[1];return a[0].tagName===sre.SemanticAttr.Type.IDENTIFIER&&(sre.ClearspeakUtil.isInteger_(b)||b.tagName===sre.SemanticAttr.Type.INFIXOP&&b.hasAttribute("role")&&b.getAttribute("role")===sre.SemanticAttr.Role.IMPLICIT&&sre.ClearspeakUtil.allIndices_(b))};
-sre.ClearspeakUtil.isInteger_=function(a){return a.tagName===sre.SemanticAttr.Type.NUMBER&&a.hasAttribute("role")&&a.getAttribute("role")===sre.SemanticAttr.Role.INTEGER};sre.ClearspeakUtil.allIndices_=function(a){return sre.XpathUtil.evalXPath("children/*",a).every(function(a){return sre.ClearspeakUtil.isInteger_(a)||a.tagName===sre.SemanticAttr.Type.IDENTIFIER})};
-sre.ClearspeakUtil.allCellsSimple=function(a){return sre.XpathUtil.evalXPath(a.tagName===sre.SemanticAttr.Type.MATRIX?"children/row/children/cell/children/*":"children/line/children/*",a).every(sre.ClearspeakUtil.simpleCell_)?[a]:[]};sre.ClearspeakUtil.vulgarFraction=function(a){return sre.MathspeakUtil.vulgarFraction(a," ")};sre.ClearspeakUtil.isSmallVulgarFraction=function(a){return sre.MathspeakUtil.vulgarFractionSmall(a,20,11)?[a]:[]};
-sre.ClearspeakUtil.isUnitExpression=function(a){return a.type===sre.SemanticAttr.Type.TEXT||a.type===sre.SemanticAttr.Type.PUNCTUATED&&a.role===sre.SemanticAttr.Role.TEXT&&sre.ClearspeakUtil.isNumber_(a.childNodes[0])&&sre.ClearspeakUtil.allTextLastContent_(a.childNodes.slice(1))||a.type===sre.SemanticAttr.Type.IDENTIFIER&&a.role===sre.SemanticAttr.Role.UNIT||a.type===sre.SemanticAttr.Type.INFIXOP&&(a.role===sre.SemanticAttr.Role.IMPLICIT||a.role===sre.SemanticAttr.Role.UNIT)};
-sre.ClearspeakUtil.allTextLastContent_=function(a){for(var b=0;b<a.length-1;b++)if(a[b].type!==sre.SemanticAttr.Type.TEXT||""!==a[b].textContent)return!1;return a[a.length-1].type===sre.SemanticAttr.Type.TEXT};sre.ClearspeakUtil.unitExpression=function(){return new sre.SemanticAnnotator("clearspeak",function(a){return sre.ClearspeakUtil.isUnitExpression(a)?"unit":""})};
-sre.ClearspeakUtil.ordinalExponent=function(a){var b=parseInt(a.textContent,10);return isNaN(b)?a.textContent:10<b?sre.MathspeakUtil.simpleOrdinal(b):sre.MathspeakUtil.numberToOrdinal(b,!1)};sre.ClearspeakUtil.isCapitalLetter=function(a){return"Lu"===sre.MathCompoundStore.getInstance().lookupCategory(a.textContent)?[a]:[]};sre.ClearspeakUtil.NESTING_DEPTH=null;
-sre.ClearspeakUtil.nestingDepth=function(a){var b=0,c=a.textContent,d="open"===a.getAttribute("role")?0:1;for(a=a.parentNode;a;)a.tagName===sre.SemanticAttr.Type.FENCED&&a.childNodes[0].childNodes[d].textContent===c&&b++,a=a.parentNode;sre.ClearspeakUtil.NESTING_DEPTH=1<b?sre.MathspeakUtil.wordOrdinal(b):"";return sre.ClearspeakUtil.NESTING_DEPTH};
-sre.ClearspeakUtil.matchingFences=function(a){var b=a.previousSibling;if(b)var c=a;else b=a,c=a.nextSibling;return c?sre.SemanticAttr.isMatchingFence(b.textContent,c.textContent)?[a]:[]:[]};sre.ClearspeakUtil.insertNesting=function(a,b){if(!b||!a)return a;var c=a.match(/^(open|close) /);return c?c[0]+b+" "+a.substring(c[0].length):b+" "+a};sre.Grammar.getInstance().setCorrection("insertNesting",sre.ClearspeakUtil.insertNesting);
-sre.ClearspeakUtil.fencedArguments=function(a){var b=sre.DomUtil.toArray(a.parentNode.childNodes),c=sre.XpathUtil.evalXPath("../../children/*",a),b=b.indexOf(a);return sre.ClearspeakUtil.fencedFactor_(c[b])||sre.ClearspeakUtil.fencedFactor_(c[b+1])?[a]:[]};
-sre.ClearspeakUtil.simpleArguments=function(a){var b=sre.DomUtil.toArray(a.parentNode.childNodes),c=sre.XpathUtil.evalXPath("../../children/*",a),b=b.indexOf(a);return!sre.ClearspeakUtil.simpleFactor_(c[b])||!sre.ClearspeakUtil.simpleFactor_(c[b+1])&&c[b+1].tagName!==sre.SemanticAttr.Type.ROOT&&c[b+1].tagName!==sre.SemanticAttr.Type.SQRT&&(c[b+1].tagName!==sre.SemanticAttr.Type.SUPERSCRIPT||c[b+1].childNodes[0].childNodes[0].tagName!==sre.SemanticAttr.Type.NUMBER&&c[b+1].childNodes[0].childNodes[0].tagName!==
-sre.SemanticAttr.Type.IDENTIFIER||"2"!==c[b+1].childNodes[0].childNodes[1].textContent&&"3"!==c[b+1].childNodes[0].childNodes[1].textContent)?[]:[a]};sre.ClearspeakUtil.simpleFactor_=function(a){return!!a&&(a.tagName===sre.SemanticAttr.Type.NUMBER||a.tagName===sre.SemanticAttr.Type.IDENTIFIER||a.tagName===sre.SemanticAttr.Type.FUNCTION||a.tagName===sre.SemanticAttr.Type.APPL||a.tagName===sre.SemanticAttr.Type.FRACTION)};
-sre.ClearspeakUtil.fencedFactor_=function(a){return a&&(a.tagName===sre.SemanticAttr.Type.FENCED||a.hasAttribute("role")&&a.getAttribute("role")===sre.SemanticAttr.Role.LEFTRIGHT||sre.ClearspeakUtil.layoutFactor_(a))};sre.ClearspeakUtil.layoutFactor_=function(a){return!!a&&(a.tagName===sre.SemanticAttr.Type.MATRIX||a.tagName===sre.SemanticAttr.Type.VECTOR)};
-sre.ClearspeakUtil.isHyperbolic=function(a){if(a.tagName===sre.SemanticAttr.Type.APPL){var b=sre.XpathUtil.evalXPath("children/*[1]",a)[0];if(b&&b.tagName===sre.SemanticAttr.Type.FUNCTION&&"Hyperbolic"===sre.MathCompoundStore.getInstance().lookupCategory(b.textContent))return[a]}return[]};
-sre.ClearspeakUtil.isLogarithmWithBase=function(a){if(a.tagName===sre.SemanticAttr.Type.SUBSCRIPT){var b=sre.XpathUtil.evalXPath("children/*[1]",a)[0];if(b&&b.tagName===sre.SemanticAttr.Type.FUNCTION&&"Logarithm"===sre.MathCompoundStore.getInstance().lookupCategory(b.textContent))return[a]}return[]};sre.ClearspeakUtil.wordOrdinal=function(a){return sre.MathspeakUtil.wordOrdinal(parseInt(a.textContent,10))};sre.ClearspeakRules=function(){sre.MathStore.call(this);this.parser=new sre.ClearspeakPreferences.Parser};goog.inherits(sre.ClearspeakRules,sre.MathStore);goog.addSingletonGetter(sre.ClearspeakRules);sre.ClearspeakRules.mathStore=sre.ClearspeakRules.getInstance();sre.ClearspeakRules.defineRule_=goog.bind(sre.ClearspeakRules.mathStore.defineRule,sre.ClearspeakRules.mathStore);sre.ClearspeakRules.defineRuleAlias_=goog.bind(sre.ClearspeakRules.mathStore.defineRulesAlias,sre.ClearspeakRules.mathStore);
-sre.ClearspeakRules.defineSpecialisedRule_=goog.bind(sre.ClearspeakRules.mathStore.defineSpecialisedRule,sre.ClearspeakRules.mathStore);sre.ClearspeakRules.addContextFunction_=goog.bind(sre.ClearspeakRules.mathStore.contextFunctions.add,sre.ClearspeakRules.mathStore.contextFunctions);sre.ClearspeakRules.addCustomQuery_=goog.bind(sre.ClearspeakRules.mathStore.customQueries.add,sre.ClearspeakRules.mathStore.customQueries);
-sre.ClearspeakRules.addCustomString_=goog.bind(sre.ClearspeakRules.mathStore.customStrings.add,sre.ClearspeakRules.mathStore.customStrings);sre.ClearspeakRules.addAnnotators_=function(){sre.SemanticAnnotations.getInstance().register(sre.ClearspeakUtil.simpleExpression());sre.SemanticAnnotations.getInstance().register(sre.ClearspeakUtil.unitExpression())};sre.ClearspeakRules.addComparator_=function(){sre.Engine.getInstance().comparators.clearspeak=sre.ClearspeakPreferences.comparator};
-sre.ClearspeakRules.initCustomFunctions_=function(){(0,sre.ClearspeakRules.addContextFunction_)("CTXFpauseSeparator",sre.StoreUtil.pauseSeparator);(0,sre.ClearspeakRules.addContextFunction_)("CTXFnodeCounter",sre.ClearspeakUtil.nodeCounter);(0,sre.ClearspeakRules.addContextFunction_)("CTXFcontentIterator",sre.MathmlStoreUtil.contentIterator);(0,sre.ClearspeakRules.addCustomString_)("CSFvulgarFraction",sre.ClearspeakUtil.vulgarFraction);(0,sre.ClearspeakRules.addCustomQuery_)("CQFvulgarFractionSmall",
-sre.ClearspeakUtil.isSmallVulgarFraction);(0,sre.ClearspeakRules.addCustomQuery_)("CQFcellsSimple",sre.ClearspeakUtil.allCellsSimple);(0,sre.ClearspeakRules.addCustomString_)("CSFordinalExponent",sre.ClearspeakUtil.ordinalExponent);(0,sre.ClearspeakRules.addCustomString_)("CSFwordOrdinal",sre.ClearspeakUtil.wordOrdinal);(0,sre.ClearspeakRules.addCustomQuery_)("CQFisCapital",sre.ClearspeakUtil.isCapitalLetter);(0,sre.ClearspeakRules.addCustomQuery_)("CQFmatchingFences",sre.ClearspeakUtil.matchingFences);
-(0,sre.ClearspeakRules.addCustomString_)("CSFnestingDepth",sre.ClearspeakUtil.nestingDepth);(0,sre.ClearspeakRules.addCustomQuery_)("CQFfencedArguments",sre.ClearspeakUtil.fencedArguments);(0,sre.ClearspeakRules.addCustomQuery_)("CQFsimpleArguments",sre.ClearspeakUtil.simpleArguments);(0,sre.ClearspeakRules.addCustomQuery_)("CQFisHyperbolic",sre.ClearspeakUtil.isHyperbolic);(0,sre.ClearspeakRules.addCustomQuery_)("CQFisLogarithm",sre.ClearspeakUtil.isLogarithmWithBase);(0,sre.ClearspeakRules.addCustomQuery_)("CQFspaceoutNumber",
-sre.MathspeakUtil.spaceoutNumber)};
-sre.ClearspeakRules.initClearspeakRules_=function(){(0,sre.ClearspeakRules.defineRule_)("stree","clearspeak.default","[n] ./*[1]","self::stree");(0,sre.ClearspeakRules.defineRule_)("omit-empty","clearspeak.default",'[p] (pause:"short")',"self::empty");(0,sre.ClearspeakRules.defineRule_)("font","clearspeak.default",'[t] @font; [n] self::* (grammar:ignoreFont=@font,pause:"short")',"self::*","@font",'not(contains(@grammar, "ignoreFont"))','@font!="normal"');(0,sre.ClearspeakRules.defineRule_)("font-identifier","clearspeak.default",
-'[t] @font; [n] self::* (grammar:ignoreFont=@font,pause:"short")',"self::identifier","string-length(text())=1","@font",'@font="normal"','not(contains(@grammar, "ignoreFont"))','@role!="unit"');(0,sre.ClearspeakRules.defineRule_)("omit-font","clearspeak.default","[n] self::* (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'not(contains(@grammar, "ignoreFont"))','@font="italic"');(0,sre.ClearspeakRules.defineRule_)("german-font","clearspeak.default",'[t] "German"; [n] self::* (grammar:ignoreFont=@font)',
-"self::*","@font",'not(contains(@grammar, "ignoreFont"))','@font="fraktur"');(0,sre.ClearspeakRules.defineRule_)("german-font","clearspeak.default",'[t] "bold German"; [n] self::* (grammar:ignoreFont=@font)',"self::*","@font",'not(contains(@grammar, "ignoreFont"))','@font="bold-fraktur"');(0,sre.ClearspeakRules.defineRule_)("text","clearspeak.default","[n] text()","self::text");(0,sre.ClearspeakRules.defineRule_)("capital","clearspeak.default",'[n] text() (pitch:0.6,grammar:ignoreFont="cap")',"self::identifier",
-'@role="latinletter" or @role="greekletter" or @role="simple function"',"CQFisCapital");(0,sre.ClearspeakRules.defineRule_)("capital","clearspeak.Caps_SayCaps","[n] text()","self::identifier",'@role="latinletter" or @role="greekletter"',"CQFisCapital");(0,sre.ClearspeakRules.defineRule_)("capital","clearspeak.Caps_SayCaps",'[p] (pause:"short"); [n] text()',"self::identifier",'@role="latinletter" or @role="greekletter"',"CQFisCapital","preceding-sibling::*[1]",'not(name(preceding-sibling::*[1])="function")',
-'not(contains(@grammar, "angle"))');(0,sre.ClearspeakRules.defineRule_)("capital","clearspeak.Caps_SayCaps",'[n] text() (pause:"short")',"self::identifier",'@role="latinletter" or @role="greekletter"',"CQFisCapital","following-sibling::*[1]");(0,sre.ClearspeakRules.defineRule_)("capital","clearspeak.Caps_SayCaps",'[p] (pause:"short"); [n] text() (pause:"short")',"self::identifier",'@role="latinletter" or @role="greekletter"',"CQFisCapital","preceding-sibling::*[1]","following-sibling::*[1]",'not(name(preceding-sibling::*[1])="function")',
-'not(contains(@grammar, "angle"))');(0,sre.ClearspeakRules.defineRule_)("punctuation-lr","clearspeak.default",'[p] (pause:"short"); [n] text() (pause:"short")',"self::punctuation",'@role="comma"');(0,sre.ClearspeakRules.defineRule_)("punctuation","clearspeak.default","[n] text()","self::punctuation",'@role="comma"',"not(preceding-sibling::*[1]/children)","not(following-sibling::*[1]/children)");(0,sre.ClearspeakRules.defineRule_)("punctuation-l","clearspeak.default",'[p] (pause:"short"); [n] text()',
-"self::punctuation",'@role="comma"',"not(following-sibling::*[1]/children)");(0,sre.ClearspeakRules.defineRule_)("punctuation-r","clearspeak.default",'[n] text() (pause:"short")',"self::punctuation",'@role="comma"',"not(preceding-sibling::*[1]/children)");(0,sre.ClearspeakRules.defineRule_)("ellipsis","clearspeak.Ellipses_AndSoOn",'[t] "and so on"',"self::punctuation",'@role="ellipsis"',"not(following-sibling::*[1])",'not(preceding-sibling::*[last()][@role="ellipsis"])');(0,sre.ClearspeakRules.defineRule_)("ellipsis",
-"clearspeak.Ellipses_AndSoOn",'[t] "and so on up to"',"self::punctuation",'@role="ellipsis"',"preceding-sibling::*[1]","following-sibling::*[1]");(0,sre.ClearspeakRules.defineRule_)("vbar-evaluated","clearspeak.default",'[n] children/*[1]; [p] (pause:"short"); [t] "evaluated at"; [n] content/*[1]/children/*[2]; [p] (pause:"short")',"self::punctuated",'@role="endpunct"','content/*[1][@role="vbar"]',"content/*[1][@embellished]",'name(content/*[1])="subscript"');(0,sre.ClearspeakRules.defineRule_)("vbar-evaluated",
-"clearspeak.default",'[n] children/*[1]; [p] (pause:"short"); [t] "evaluated at"; [n] content/*[1]/children/*[2]; [p] (pause:"short"); [t] "minus the same expression evaluated at"; [n] content/*[1]/children/*[1]/children/*[2]; [p] (pause:"short")',"self::punctuated",'@role="endpunct"','content/*[1][@role="vbar"]',"content/*[1][@embellished]",'name(content/*[1])="superscript"','name(content/*[1]/children/*[1])="subscript"');(0,sre.ClearspeakRules.defineRule_)("vbar-such-that","clearspeak.VerticalLine_SuchThat",
-'[t] "such that"',"self::punctuation",'@role="vbar"','not(parent::*/parent::*[@embellished="punctuation"])');(0,sre.ClearspeakRules.defineRule_)("vbar-such-that","clearspeak.VerticalLine_Divides",'[t] "divides"',"self::punctuation",'@role="vbar"','not(parent::*/parent::*[@embellished="punctuation"])');(0,sre.ClearspeakRules.defineRule_)("vbar-such-that","clearspeak.VerticalLine_Given",'[t] "given"',"self::punctuation",'@role="vbar"','not(parent::*/parent::*[@embellished="punctuation"])');(0,sre.ClearspeakRules.defineRule_)("set-member",
-"clearspeak.default",'[t] "in"',"self::operator",'@role="set extended"','text()="\u2208" or text()="\u220a"');(0,sre.ClearspeakRules.defineSpecialisedRule_)("set-member","clearspeak.default","clearspeak.SetMemberSymbol_Member",'[t] "member of"');(0,sre.ClearspeakRules.defineSpecialisedRule_)("set-member","clearspeak.default","clearspeak.SetMemberSymbol_Element",'[t] "element of"');(0,sre.ClearspeakRules.defineSpecialisedRule_)("set-member","clearspeak.default","clearspeak.SetMemberSymbol_Belongs",
-'[t] "belonging to"');(0,sre.ClearspeakRules.defineRule_)("set-not-member","clearspeak.default",'[t] "not in"',"self::operator",'@role="set extended"','text()="\u2209"');(0,sre.ClearspeakRules.defineSpecialisedRule_)("set-not-member","clearspeak.default","clearspeak.SetMemberSymbol_Member",'[t] "not member of"');(0,sre.ClearspeakRules.defineSpecialisedRule_)("set-not-member","clearspeak.default","clearspeak.SetMemberSymbol_Element",'[t] "not element of"');(0,sre.ClearspeakRules.defineSpecialisedRule_)("set-not-member",
-"clearspeak.default","clearspeak.SetMemberSymbol_Belongs",'[t] "not belonging to"');(0,sre.ClearspeakRules.defineRule_)("prime","clearspeak.default","[n] children/*[1]; [n] children/*[2]","self::superscript","children/*[2]",'children/*[2][@role="prime"]',"self::*");(0,sre.ClearspeakRules.defineRule_)("feet","clearspeak.default",'[n] children/*[1]; [t] "feet"',"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="number"','children/*[2][text()="\u2032"]','not(preceding-sibling::*[@role="degree"])');
-(0,sre.ClearspeakRules.defineRule_)("foot","clearspeak.default",'[n] children/*[1]; [t] "foot"',"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="number"','children/*[2][text()="\u2032"]','children/*[1][text()="1"]','not(preceding-sibling::*[@role="degree"])');(0,sre.ClearspeakRules.defineRule_)("inches","clearspeak.default",'[n] children/*[1]; [t] "inches"',"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="number"','children/*[2][text()="\u2033"]','not(preceding-sibling::*[@role="degree"])');
-(0,sre.ClearspeakRules.defineRule_)("inch","clearspeak.default",'[n] children/*[1]; [t] "inch"',"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="number"','children/*[2][text()="\u2033"]','children/*[1][text()="1"]','not(preceding-sibling::*[@role="degree"])');(0,sre.ClearspeakRules.defineRule_)("minutes","clearspeak.default",'[p] (pause:short); [n] children/*[1]; [t] "minutes"',"self::superscript",'children/*[2][@role="prime"]','preceding-sibling::*[@role="degree"]','children/*[2][text()="\u2032"]');
-(0,sre.ClearspeakRules.defineRule_)("minute","clearspeak.default",'[p] (pause:short); [n] children/*[1]; [t] "minute"',"self::superscript",'children/*[2][@role="prime"]','preceding-sibling::*[@role="degree"]','children/*[2][text()="\u2032"]','children/*[1][text()="1"]');(0,sre.ClearspeakRules.defineRule_)("seconds","clearspeak.default",'[p] (pause:short); [n] children/*[1]; [t] "seconds"',"self::superscript",'children/*[2][@role="prime"]','preceding-sibling::*[@role="degree"]','children/*[2][text()="\u2033"]');
-(0,sre.ClearspeakRules.defineRule_)("second","clearspeak.default",'[p] (pause:short); [n] children/*[1]; [t] "second"',"self::superscript",'children/*[2][@role="prime"]','preceding-sibling::*[@role="degree"]','children/*[2][text()="\u2033"]','children/*[1][text()="1"]');(0,sre.ClearspeakRules.defineRule_)("degrees-angle","clearspeak.Prime_Angle",'[n] children/*[1]; [t] "degrees"; [p] (pause:short)',"self::punctuation",'@role="degree"');(0,sre.ClearspeakRules.defineRule_)("degree-angle","clearspeak.Prime_Angle",
-'[n] children/*[1]; [t] "degree"; [p] (pause:short)',"self::punctuation",'@role="degree"','children/*[1][text()="1"]');(0,sre.ClearspeakRules.defineRule_)("minutes-angle","clearspeak.Prime_Angle",'[n] children/*[1]; [t] "minutes"; [p] (pause:short)',"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="number" or (children/*[1][@role="latinletter"] and ""=translate(children/*[1]/text(),"abcdefghijklmnopqrstuvwxyz", ""))','children/*[2][text()="\u2032"]');(0,sre.ClearspeakRules.defineRule_)("minute-angle",
-"clearspeak.Prime_Angle",'[n] children/*[1]; [t] "minute"; [p] (pause:short)',"self::superscript",'children/*[2][@role="prime"]','children/*[2][text()="\u2032"]','children/*[1][text()="1"]');(0,sre.ClearspeakRules.defineRule_)("seconds-angle","clearspeak.Prime_Angle",'[n] children/*[1]; [t] "seconds"; [p] (pause:short)',"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="number" or (children/*[1][@role="latinletter"] and ""=translate(children/*[1]/text(),"abcdefghijklmnopqrstuvwxyz", ""))',
-'children/*[2][text()="\u2033"]');(0,sre.ClearspeakRules.defineRule_)("second-angle","clearspeak.Prime_Angle",'[n] children/*[1]; [t] "second"; [p] (pause:short)',"self::superscript",'children/*[2][@role="prime"]','children/*[2][text()="\u2033"]','children/*[1][text()="1"]');(0,sre.ClearspeakRules.defineRule_)("feet-length","clearspeak.Prime_Length",'[n] children/*[1]; [t] "feet"; [p] (pause:short)',"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="number" or (children/*[1][@role="latinletter"] and ""=translate(children/*[1]/text(),"abcdefghijklmnopqrstuvwxyz", ""))',
-'children/*[2][text()="\u2032"]');(0,sre.ClearspeakRules.defineRule_)("foot-length","clearspeak.Prime_Length",'[n] children/*[1]; [t] "foot"; [p] (pause:short)',"self::superscript",'children/*[2][@role="prime"]','children/*[2][text()="\u2032"]','children/*[1][text()="1"]');(0,sre.ClearspeakRules.defineRule_)("inches-length","clearspeak.Prime_Length",'[n] children/*[1]; [t] "inches"; [p] (pause:short)',"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="number" or (children/*[1][@role="latinletter"] and ""=translate(children/*[1]/text(),"abcdefghijklmnopqrstuvwxyz", ""))',
-'children/*[2][text()="\u2033"]');(0,sre.ClearspeakRules.defineRule_)("inch-length","clearspeak.Prime_Length",'[n] children/*[1]; [t] "inch"; [p] (pause:short)',"self::superscript",'children/*[2][@role="prime"]','children/*[2][text()="\u2033"]','children/*[1][text()="1"]');(0,sre.ClearspeakRules.defineRule_)("punctuated","clearspeak.default","[m] children/*","self::punctuated");(0,sre.ClearspeakRules.defineRule_)("function","clearspeak.default","[n] text()","self::function");(0,sre.ClearspeakRules.defineRule_)("appl",
-"clearspeak.default",'[n] children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:"short")',"self::appl");(0,sre.ClearspeakRules.defineRule_)("appl-simple","clearspeak.default",'[n] children/*[1]; [t] "of"; [p] (pause:"short"); [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="simple function"','name(children/*[2])="appl"');(0,sre.ClearspeakRules.defineRule_)("appl-simple","clearspeak.default",'[n] children/*[1]; [t] "of"; [p] (pause:"short"); [n] children/*[2]; [p] (pause:"short")',"self::appl",
-'@role="simple function"','name(children/*[2])="fenced"','name(children/*[2]/children/*[1])="appl"');(0,sre.ClearspeakRules.defineRule_)("appl","clearspeak.Functions_None",'[p] (pause:"short"); [n] children/*[1]; [t] "times"; [n] children/*[2]; [p] (pause:"short")',"self::appl");(0,sre.ClearspeakRules.defineRule_)("function-prefix","clearspeak.default","[n] children/*[1]; [n] children/*[2]","self::appl",'@role="prefix function"');(0,sre.ClearspeakRules.defineRule_)("binary-operation","clearspeak.ImpliedTimes_MoreImpliedTimes",
-'[n] . (grammar:impliedTimes); [p] (pause:"short")',"self::appl",'@role="prefix function"','parent::*/parent::infixop[@role="implicit"]',"following-sibling::*",'not(contains(@grammar, "impliedTimes"))');(0,sre.ClearspeakRules.defineRule_)("function-prefix-simple-arg","clearspeak.default","[n] children/*[1]; [n] children/*[2]","self::appl",'@role="prefix function"','name(children/*[2])="fenced"','contains(children/*[2]/children/*[1]/@annotation, "clearspeak:simple")','name(children/*[2]/children/*[1])!="number"',
-'name(children/*[2]/children/*[1])!="identifier"','name(children/*[2]/children/*[1])!="appl"');(0,sre.ClearspeakRules.defineRule_)("function-prefix-embell","clearspeak.default",'[p] (pause:"short"); [n] children/*[1]; [n] children/*[2]; [p] (pause:"short"); ',"self::appl",'@role="prefix function"','name(children/*[1])!="function"');(0,sre.ClearspeakRules.defineRule_)("function-prefix-fenced-or-frac-arg","clearspeak.default",'[p] (pause:"short"); [t] "the"; [n] children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:"short")',
-"self::appl",'@role="prefix function"','(name(children/*[2])="fenced" and not(contains(children/*[2]/children/*[1]/@annotation, "clearspeak:simple"))) or name(children/*[2])="fraction" or (name(children/*[2])!="fenced" and not(contains(children/*[2]/@annotation, "clearspeak:simple")))',"self::*");(0,sre.ClearspeakRules.defineRule_)("function-prefix-subscript","clearspeak.default",'[p] (pause:"short"); [t] "the"; [n] children/*[1]; [t] "of"; [p] (pause:"short"); [n] children/*[2]; [p] (pause:"short")',
-"self::appl",'@role="prefix function"','name(children/*[1])="subscript"',"self::*");(0,sre.ClearspeakRules.defineRule_)("function-ln","clearspeak.default","[n] children/*[1]; [n] children/*[2]","self::appl",'@role="prefix function"','content/*[2][text()="ln"]',"not(following-sibling::*)",'not(contains(@grammar, "NatLog"))');(0,sre.ClearspeakRules.defineRule_)("function-ln","clearspeak.default",'[n] children/*[1]; [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"','content/*[2][text()="ln"]',
-'not(contains(@grammar, "NatLog"))');(0,sre.ClearspeakRules.defineRule_)("function-ln","clearspeak.default",'[n] children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"','content/*[2][text()="ln"]','name(children/*[2])="fenced"','not(contains(@grammar, "NatLog"))');(0,sre.ClearspeakRules.defineRule_)("function-ln","clearspeak.Log_LnAsNaturalLog","[n] . (grammar:NatLog)","self::appl",'@role="prefix function"','content/*[2][text()="ln"]',"not(following-sibling::*)",
-'not(contains(@grammar, "NatLog"))');(0,sre.ClearspeakRules.defineRule_)("function-ln","clearspeak.Log_LnAsNaturalLog",'[n] . (grammar:NatLog); [p] (pause:"short")',"self::appl",'@role="prefix function"','content/*[2][text()="ln"]','not(contains(@grammar, "NatLog"))');(0,sre.ClearspeakRules.defineRule_)("function-prefix-as-exp","clearspeak.default",'[n] children/*[1]; [t] "of"; [p] (pause:"short"); [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"','name(parent::*/parent::*)="superscript"',
-"not(following-sibling::*)",'(name(children/*[2])="fenced" and not(contains(children/*[2]/children/*[1]/@annotation, "clearspeak:simple"))) or name(children/*[2])="fraction" or (name(children/*[2])!="fenced" and not(contains(children/*[2]/@annotation, "clearspeak:simple")))');(0,sre.ClearspeakRules.defineRule_)("function-prefix-subscript-as-exp","clearspeak.default",'[n] children/*[1]; [t] "of"; [p] (pause:"short"); [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"','name(parent::*/parent::*)="superscript"',
-"not(following-sibling::*)",'name(children/*[1])="subscript"');(0,sre.ClearspeakRules.defineRule_)("function-prefix-hyper","clearspeak.default",'[p] (pause:"short"); [n] children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"',"CQFisHyperbolic");(0,sre.ClearspeakRules.defineRule_)("function-prefix-inverse","clearspeak.default",'[p] (pause:"short"); [t] "the inverse"; [n] children/*[1]/children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:"short")',"self::appl",
-'@role="prefix function"','name(children/*[1])="superscript"','name(children/*[1]/children/*[2])="prefixop"','children/*[1]/children/*[2][@role="negative"]','children/*[1]/children/*[2]/children/*[1][text()="1"]','not(contains(@grammar, "functions_none"))');(0,sre.ClearspeakRules.defineRule_)("appl-triginverse","clearspeak.Trig_TrigInverse",'[p] (pause:"short"); [n] children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"','name(children/*[1])="superscript"',
-'name(children/*[1]/children/*[2])="prefixop"','children/*[1]/children/*[2][@role="negative"]','children/*[1]/children/*[2]/children/*[1][text()="1"]');(0,sre.ClearspeakRules.defineRule_)("function-prefix-arc-simple","clearspeak.Trig_ArcTrig",'[p] (pause:"short"); [t] "arc"; [n] children/*[1]/children/*[1]; [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"','name(children/*[1])="superscript"','name(children/*[1]/children/*[2])="prefixop"','children/*[1]/children/*[2][@role="negative"]',
-'children/*[1]/children/*[2]/children/*[1][text()="1"]','not(contains(@grammar, "functions_none"))');(0,sre.ClearspeakRules.defineRule_)("function-prefix-arc-simple","clearspeak.Trig_ArcTrig",'[p] (pause:"short"); [t] "arc"; [n] children/*[1]/children/*[1]; [p] (pause:"short"); [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"','name(children/*[1])="superscript"','name(children/*[1]/children/*[2])="prefixop"','children/*[1]/children/*[2][@role="negative"]','children/*[1]/children/*[2]/children/*[1][text()="1"]',
-'name(children/*[2])="fenced"','children/*[2]/children/*[1][@role="prefix function"]','contains(children/*[2]/children/*[1]/@annotation, "clearspeak:simple")','not(contains(@grammar, "functions_none"))');(0,sre.ClearspeakRules.defineRule_)("function-prefix-arc","clearspeak.Trig_ArcTrig",'[p] (pause:"short"); [t] "arc"; [n] children/*[1]/children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:"short")',"self::appl",'@role="prefix function"','name(children/*[1])="superscript"','name(children/*[1]/children/*[2])="prefixop"',
-'children/*[1]/children/*[2][@role="negative"]','children/*[1]/children/*[2]/children/*[1][text()="1"]','not(contains(@grammar, "functions_none"))','(name(children/*[2])="fenced" and not(contains(children/*[2]/children/*[1]/@annotation, "clearspeak:simple"))) or (name(children/*[2])="fraction" and children/*[2][@role!="vulgar"])');(0,sre.ClearspeakRules.defineRule_)("function-inverse","clearspeak.default",'[n] children/*[1]; [t] "inverse"',"self::superscript",'@role="prefix function" or @role="simple function"',
-'name(children/*[2])="prefixop"','children/*[2][@role="negative"]','children/*[2]/children/*[1][text()="1"]','not(contains(@grammar, "functions_none"))');(0,sre.ClearspeakRules.defineRule_)("superscript-prefix-function","clearspeak.default",'[t] "the"; [n] children/*[2] (grammar:ordinal); [t] "power of"; [n] children/*[1]',"self::superscript",'@role="prefix function"','name(children/*[2])="number"','children/*[2][@role="integer"]');(0,sre.ClearspeakRules.defineRule_)("superscript-prefix-function",
-"clearspeak.default",'[t] "the"; [n] children/*[2] (grammar:ordinal); [t] "power of"; [n] children/*[1]',"self::superscript",'@role="prefix function"','name(children/*[2])="identifier"');(0,sre.ClearspeakRules.defineRule_)("function-inverse","clearspeak.Functions_None","[n] . (grammar:functions_none)","self::superscript",'@role="prefix function" or @role="simple function"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]','children/*[2]/children/*[1][text()="1"]','not(contains(@grammar, "functions_none"))');
-(0,sre.ClearspeakRules.defineRule_)("superscript","clearspeak.default",'[n] children/*[1]; [t] "raised to the exponent" (pause:"short"); [n] children/*[2]; [p] (pause:"short"); [t] "end exponent" (pause:"short")',"self::superscript");(0,sre.ClearspeakRules.defineRule_)("superscript-simple-exponent","clearspeak.default",'[n] children/*[1]; [t] "raised to the"; [n] children/*[2]; [t] "power" (pause:"short")',"self::superscript","not(descendant::superscript)");(0,sre.ClearspeakRules.defineRule_)("superscript-simple-exponent",
-"clearspeak.default",'[n] children/*[1]; [t] "raised to the"; [n] children/*[2]; [t] "power"',"self::superscript","not(descendant::superscript)","not(following-sibling::*)");(0,sre.ClearspeakRules.defineRuleAlias_)("superscript-simple-exponent","self::superscript",'children/superscript/children/*[2][text()="2"] or children/superscript/children/*[2][text()="3"]','name(children/superscript/children/*[1])="number"','contains(children/superscript/children/*[1]/@annotation, "clearspeak:simple")');(0,sre.ClearspeakRules.defineRuleAlias_)("superscript-simple-exponent",
-"self::superscript",'children/superscript/children/*[2][text()="2"] or children/superscript/children/*[2][text()="3"]','name(children/superscript/children/*[1])="fraction"','contains(children/superscript/children/*[1]/@annotation, "clearspeak:simple")');(0,sre.ClearspeakRules.defineRuleAlias_)("superscript-simple-exponent","self::superscript",'children/superscript/children/*[2][text()="2"] or children/superscript/children/*[2][text()="3"]','name(children/superscript/children/*[1])="identifier"');
-(0,sre.ClearspeakRules.defineRuleAlias_)("superscript-simple-exponent","self::superscript",'children/*[2][@role="implicit"]',"count(children/*[2]/children/*)=2",'contains(children/*[2]/children/*[1]/@annotation, "simple")','name(children/*[2]/children/*[2])="superscript"','(name(children/*[2]/children/*[2]/children/*[1])="number" and contains(children/*[2]/children/*[2]/children/*[1]/@annotation, "clearspeak:simple")) or name(children/*[2]/children/*[2]/children/*[1])="identifier"','children/*[2]/children/*[2]/children/*[2][text()="2"] or children/*[2]/children/*[2]/children/*[2][text()="3"]');
-(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal","clearspeak.default",'[n] children/*[1]; [t] "to the"; [n] children/*[2] (grammar:ordinal); [t] "power" (pause:"short")',"self::superscript",'name(children/*[2])="number"','children/*[2][@role="integer"]');(0,sre.ClearspeakRules.defineRuleAlias_)("superscript-ordinal","self::superscript",'name(children/*[2])="identifier"','children/*[2][@role="latinletter" or @role="greekletter" or @role="otherletter"]');(0,sre.ClearspeakRules.defineRule_)("superscript-non-ordinal",
-"clearspeak.default",'[n] children/*[1]; [t] "to the"; [n] children/*[2]; [t] "power" (pause:"short")',"self::superscript",'children/*[2][@role="negative"]','name(children/*[2]/children/*[1])="number"','children/*[2]/children/*[1][@role="integer"]');(0,sre.ClearspeakRules.defineRule_)("superscript-simple-function","clearspeak.default",'[t] "the"; [n] children/*[2] (grammar:ordinal); [t] "power of" (pause:"short"); [n] children/*[1]',"self::superscript",'name(children/*[1])="identifier"','children/*[1][@role="simple function"]',
-'children/*[2][@role!="prime"]','not(contains(@grammar, "functions_none"))');(0,sre.ClearspeakRules.defineRule_)("superscript-simple-function","clearspeak.Functions_None","[n] . (grammar:functions_none)","self::superscript",'name(children/*[1])="identifier"','children/*[1][@role="simple function"]','not(contains(@grammar, "functions_none"))');(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal","clearspeak.Exponent_Ordinal",'[n] children/*[1]; [t] "to the"; [n] children/*[2] (grammar:ordinal); [p] (pause:"short")',
-"self::superscript",'name(children/*[2])="number"','children/*[2][@role="integer"]');(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal","clearspeak.Exponent_Ordinal",'[n] children/*[1]; [t] "to the"; [n] children/*[2]; [p] (pause:"short")',"self::superscript",'name(children/*[2])="prefixop"','children/*[2][@role="negative"]','name(children/*[2]/children/*[1])="number"','children/*[2]/children/*[1][@role="integer"]');(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal","clearspeak.Exponent_Ordinal",
-'[n] children/*[1]; [t] "to the"; [n] children/*[2] (grammar:ordinal); [p] (pause:"short")',"self::superscript",'name(children/*[2])="identifier"','children/*[2][@role="latinletter" or @role="greekletter" or @role="otherletter"]');(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal-default","clearspeak.Exponent_Ordinal",'[n] children/*[1]; [t] "raised to the exponent" (pause:"short"); [n] children/*[2]; [p] (pause:"short"); [t] "end exponent" (pause:"short")',"self::superscript","children//superscript");
-(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal","clearspeak.Exponent_OrdinalPower",'[n] children/*[1]; [t] "to the"; [n] children/*[2] (grammar:ordinal); [t] "power"; [p] (pause:"short")',"self::superscript",'name(children/*[2])="number"','children/*[2][@role="integer"]');(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal","clearspeak.Exponent_OrdinalPower",'[n] children/*[1]; [t] "to the"; [n] children/*[2]; [t] "power"; [p] (pause:"short")',"self::superscript",'name(children/*[2])="prefixop"',
-'children/*[2][@role="negative"]','name(children/*[2]/children/*[1])="number"','children/*[2]/children/*[1][@role="integer"]');(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal","clearspeak.Exponent_OrdinalPower",'[n] children/*[1]; [t] "to the"; [n] children/*[2] (grammar:ordinal); [t] "power"; [p] (pause:"short")',"self::superscript",'name(children/*[2])="identifier"','children/*[2][@role="latinletter" or @role="greekletter" or @role="otherletter"]');(0,sre.ClearspeakRules.defineRule_)("superscript-ordinal-default",
-"clearspeak.Exponent_OrdinalPower",'[n] children/*[1]; [t] "raised to the exponent" (pause:"short"); [n] children/*[2]; [p] (pause:"short"); [t] "end exponent" (pause:"short")',"self::superscript","children//superscript");(0,sre.ClearspeakRules.defineRule_)("superscript-power","clearspeak.Exponent_AfterPower",'[n] children/*[1]; [t] "raised to the power"; [n] children/*[2] (grammar:afterPower); [p] (pause:"short")',"self::superscript");(0,sre.ClearspeakRules.defineRule_)("superscript-power-default",
-"clearspeak.Exponent_AfterPower",'[n] children/*[1]; [t] "raised to the exponent" (pause:"short"); [n] children/*[2]; [p] (pause:"short"); [t] "end exponent" (pause:"short")',"self::superscript","children//superscript");(0,sre.ClearspeakRules.defineRule_)("exponent","clearspeak.default",'[n] text() (join:""); [t] "th"',"self::identifier",'contains(@grammar, "ordinal")');(0,sre.ClearspeakRules.defineRule_)("exponent","clearspeak.default","[t] CSFordinalExponent","self::number",'@role="integer"','contains(@grammar, "ordinal")',
-'text()!="0"');(0,sre.ClearspeakRules.defineRule_)("exponent","clearspeak.Exponent_Ordinal","[t] CSFwordOrdinal","self::number",'@role="integer"','contains(@grammar, "ordinal")','text()!="0"');(0,sre.ClearspeakRules.defineRule_)("exponent","clearspeak.Exponent_Ordinal",'[t] "zero"',"self::number",'@role="integer"','contains(@grammar, "ordinal")','text()="0"');(0,sre.ClearspeakRules.defineRule_)("exponent","clearspeak.Exponent_OrdinalPower","[t] CSFwordOrdinal","self::number",'@role="integer"','contains(@grammar, "ordinal")',
-'text()!="0"');(0,sre.ClearspeakRules.defineRule_)("exponent","clearspeak.Exponent_OrdinalPower",'[t] "zero"',"self::number",'@role="integer"','contains(@grammar, "ordinal")','text()="0"');(0,sre.ClearspeakRules.defineRule_)("square","clearspeak.default",'[n] children/*[1]; [t] "squared"',"self::superscript",'children/*[2][text()="2"]','name(children/*[1])!="text" or not(name(children/*[1])="text" and (name(../../../punctuated[@role="text"]/..)="stree" or name(..)="stree"))',"self::*","self::*");
-(0,sre.ClearspeakRules.defineRule_)("cube","clearspeak.default",'[n] children/*[1]; [t] "cubed"',"self::superscript",'children/*[2][text()="3"]','name(children/*[1])!="text" or not(name(children/*[1])="text" and (name(../../../punctuated[@role="text"]/..)="stree" or name(..)="stree"))',"self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("paren-simple","clearspeak.default","[n] children/*[1]","self::fenced",'@role="leftright"','contains(children/*[1]/@annotation, "clearspeak:simple")','name(../..)!="superscript" and name(../..)!="subscript"');
-(0,sre.ClearspeakRules.defineRule_)("paren-simple-exp","clearspeak.default","[n] children/*[1]","self::fenced",'@role="leftright"','name(../..)="superscript"','children/*[1][@role="integer"] or children/*[1][@role="float"] or (children/*[1][@role="vulgar"] and contains(children/*[1]/@annotation, "clearspeak:simple")) or children/*[1][@role="latinletter"] or children/*[1][@role="greekletter"] or children/*[1][@role="otherletter"]');(0,sre.ClearspeakRules.defineRule_)("paren-simple-nested-func","clearspeak.default",
-"[n] children/*[1]","self::fenced",'@role="leftright"','name(../*[1])="identifier" or name(../*[1])="function"','parent::*/parent::*[@role="simple function" or @role="prefix function"]','children/*[1][@role="simple function" or @role="prefix function"]','contains(children/*[1]/children/*[2]/children/*[1]/@annotation, "clearspeak:simple") or name(children/*[1]/children/*[2]/children/*[1])="subscript" or name(children/*[1]/children/*[2]/children/*[1])="superscript" or children/*[1]/children/*[2]/children/*[1][@role="vulgar"] ');
-(0,sre.ClearspeakRules.defineRule_)("paren-simple-nested-func-no-bracket","clearspeak.Functions_None","[n] children/*[1];","self::fenced",'@role="leftright"','name(../*[1])="identifier" or name(../*[1])="function"','parent::*/parent::*[@role="simple function" or @role="prefix function"]','children/*[1][@role="simple function" or @role="prefix function"]','name(children/*[1]/children/*[1])="identifier" or name(children/*[1]/children/*[1])="function"','contains(children/*[1]/children/*[2]/children/*[1]/@annotation, "clearspeak:simple")',
-'name(children/*[1]/children/*[2]/children/*[1])="identifier" or name(children/*[1]/children/*[2]/children/*[1])="number"');(0,sre.ClearspeakRules.defineRule_)("fences-open-close","clearspeak.default",'[p] (pause:"short"); [n] content/*[1] (grammar:spokenFence); [p] (pause:"short"); [n] children/*[1]; [p] (pause:"short"); [n] content/*[2] (grammar:spokenFence); [p] (pause:"short")',"self::fenced",'@role="leftright"');(0,sre.ClearspeakRules.defineRule_)("paren-simple-nested-func","clearspeak.default",
-'[p] (pause:"short"); [n] content/*[1]; [p] (pause:"short"); [n] children/*[1]; [p] (pause:"short"); [n] content/*[2]; [p] (pause:"short")',"self::fenced",'@role="leftright"','name(../*[1])="identifier" or name(../*[1])="function"','parent::*/parent::*[@role="simple function" or @role="prefix function"]','not(contains(children/*[1]/@annotation, "clearspeak:simple"))');(0,sre.ClearspeakRules.defineRule_)("paren-simple-nested-func","clearspeak.Functions_None",'[p] (pause:"short"); [n] content/*[1] (grammar:spokenFence); [p] (pause:"short"); [n] children/*[1]; [p] (pause:"short"); [n] content/*[2] (grammar:spokenFence); [p] (pause:"short")',
-"self::fenced",'@role="leftright"','name(../*[1])="identifier" or name(../*[1])="function"','parent::*/parent::*[@role="simple function" or @role="prefix function"]','children/*[1][@role="simple function" or @role="prefix function"]','contains(children/*[1]/children/*[2]/children/*[1]/@annotation, "clearspeak:simple") or name(children/*[1]/children/*[2]/children/*[1])="subscript" or name(children/*[1]/children/*[2]/children/*[1])="superscript" or children/*[1]/children/*[2]/children/*[1][@role="vulgar"] ');
-(0,sre.ClearspeakRules.defineSpecialisedRule_)("fences-open-close","clearspeak.default","clearspeak.Paren_Speak");(0,sre.ClearspeakRules.defineRuleAlias_)("fences-open-close","self::fenced",'@role="composed function"');(0,sre.ClearspeakRules.defineRule_)("fence-silent","clearspeak.Paren_Silent",'[p] (pause:"short"); [n] children/*[1]; [p] (pause:"short")',"self::fenced");(0,sre.ClearspeakRules.defineRule_)("fences-open-close","clearspeak.ImpliedTimes_None",'[p] (pause:"short"); [n] content/*[1] (grammar:spokenFence); [p] (pause:"short"); [n] children/*[1]; [p] (pause:"short"); [n] content/*[2] (grammar:spokenFence); [p] (pause:"short")',
-"self::fenced",'@role="leftright"','parent::*/parent::*[@role!="simple function"]','parent::*/parent::*[@role!="prefix function"]');(0,sre.ClearspeakRules.defineRule_)("fence-nesting","clearspeak.Paren_SpeakNestingLevel","[n] text() (grammar:insertNesting=CSFnestingDepth)","self::fence",'contains(@grammar, "spokenFence")',"CQFmatchingFences");(0,sre.ClearspeakRules.defineRule_)("fence-no-nesting","clearspeak.Paren_SpeakNestingLevel","[n] text()","self::fence");(0,sre.ClearspeakRules.defineRule_)("fences-points",
-"clearspeak.Paren_CoordPoint",'[t] "the point with coordinates"; [n] children/*[1]',"self::fenced",'name(children/*[1])="punctuated"','children/*[1][@role="sequence"]');(0,sre.ClearspeakRules.defineRule_)("fences-interval","clearspeak.Paren_Interval",'[t] "the interval from"; [n] children/*[1]/children/*[1]; [t] "to"; [n] children/*[1]/children/*[3]; [p] (pause:"short"); [n] . (grammar:interval)',"self::fenced",'not(contains(@grammar, "interval"))','name(children/*[1])="punctuated"','children/*[1][@role="sequence"]',
-"count(./children/*[1]/content/*)=1",'children/*[1]/content/*[1][@role="comma"]');(0,sre.ClearspeakRules.defineRule_)("interval-open","clearspeak.Paren_Interval",'[t] "not including"; [n] children/*[1]/children/*[1]; [t] "or"; [n] children/*[1]/children/*[3]',"self::fenced",'contains(@grammar, "interval")','content/*[1]/text()="("','content/*[2]/text()=")"');(0,sre.ClearspeakRules.defineRule_)("interval-closed-open","clearspeak.Paren_Interval",'[t] "including"; [n] children/*[1]/children/*[1]; [p] (pause:"short"); [t] "but not including"; [n] children/*[1]/children/*[3]',
-"self::fenced",'contains(@grammar, "interval")','content/*[1]/text()="["','content/*[2]/text()=")"');(0,sre.ClearspeakRules.defineRule_)("interval-open-closed","clearspeak.Paren_Interval",'[t] "not including"; [n] children/*[1]/children/*[1]; [p] (pause:"short"); [t] "but including"; [n] children/*[1]/children/*[3]',"self::fenced",'contains(@grammar, "interval")','content/*[1]/text()="("','content/*[2]/text()="]"');(0,sre.ClearspeakRules.defineRule_)("interval-closed","clearspeak.Paren_Interval",
-'[t] "including"; [n] children/*[1]/children/*[1]; [t] "and"; [n] children/*[1]/children/*[3]',"self::fenced",'contains(@grammar, "interval")','content/*[1]/text()="["','content/*[2]/text()="]"');(0,sre.ClearspeakRules.defineRule_)("interval-open-inf-r","clearspeak.Paren_Interval",'[t] "not including"; [n] children/*[1]/children/*[1]',"self::fenced",'contains(@grammar, "interval")','content/*[1]/text()="("','content/*[2]/text()=")"','children/*[1]/children/*[3]/text()="\u221e" or (name(children/*[1]/children/*[3])="prefixop" and children/*[1]/children/*[3]/children/*[1]/text()="\u221e")');
-(0,sre.ClearspeakRules.defineRule_)("interval-open-inf-l","clearspeak.Paren_Interval",'[t] "not including"; [n] children/*[1]/children/*[3]',"self::fenced",'contains(@grammar, "interval")','content/*[1]/text()="("','content/*[2]/text()=")"','children/*[1]/children/*[1]/text()="\u221e" or (name(children/*[1]/children/*[1])="prefixop" and children/*[1]/children/*[1]/children/*[1]/text()="\u221e")');(0,sre.ClearspeakRules.defineRule_)("interval-open-inf-lr","clearspeak.Paren_Interval","","self::fenced",
-'contains(@grammar, "interval")','content/*[1]/text()="("','content/*[2]/text()=")"','children/*[1]/children/*[3]/text()="\u221e" or (name(children/*[1]/children/*[3])="prefixop" and children/*[1]/children/*[3]/children/*[1]/text()="\u221e")','children/*[1]/children/*[1]/text()="\u221e" or (name(children/*[1]/children/*[1])="prefixop" and children/*[1]/children/*[1]/children/*[1]/text()="\u221e")');(0,sre.ClearspeakRules.defineRule_)("interval-closed-open-inf","clearspeak.Paren_Interval",'[t] "including"; [n] children/*[1]/children/*[1]',
-"self::fenced",'contains(@grammar, "interval")','content/*[1]/text()="["','content/*[2]/text()=")"','children/*[1]/children/*[3]/text()="\u221e" or (name(children/*[1]/children/*[3])="prefixop" and children/*[1]/children/*[3]/children/*[1]/text()="\u221e")');(0,sre.ClearspeakRules.defineRule_)("interval-open-closed-inf","clearspeak.Paren_Interval",'[t] "including"; [n] children/*[1]/children/*[3]',"self::fenced",'contains(@grammar, "interval")','content/*[1]/text()="("','content/*[2]/text()="]"',
-'children/*[1]/children/*[1]/text()="\u221e" or (name(children/*[1]/children/*[1])="prefixop" and children/*[1]/children/*[1]/children/*[1]/text()="\u221e")');(0,sre.ClearspeakRules.defineRule_)("paren-nested-embellished-funcs","clearspeak.Functions_None",'[p] (pause:"short"); [n] content/*[1]; [p] (pause:"short"); [n] children/*[1]; [p] (pause:"short"); [n] content/*[2]; [p] (pause:"short")',"self::fenced",'@role="leftright"','name(../..)="appl"','name(children/*[1]) = "appl"','preceding-sibling::*/descendant-or-self::*[@role="subsup"] or children/*[1]/descendant-or-self::*[@role="subsup"]');
-(0,sre.ClearspeakRules.defineRule_)("set-empty","clearspeak.default",'[t] "the empty set"',"self::fenced",'@role="set empty"');(0,sre.ClearspeakRules.defineRule_)("set-extended","clearspeak.default",'[t] "the set of all"; [n] children/*[1]/children/*[1]; [t] "such that"; [n] children/*[1]/children/*[3]',"self::fenced",'@role="set extended"');(0,sre.ClearspeakRules.defineRule_)("set-collection","clearspeak.default",'[t] "the set"; [n] children/*[1]',"self::fenced",'@role="set collection"');(0,sre.ClearspeakRules.defineRuleAlias_)("set-collection",
-"self::fenced",'@role="set singleton"');(0,sre.ClearspeakRules.defineRule_)("set-extended","clearspeak.Sets_woAll",'[t] "the set of"; [n] children/*[1]/children/*[1]; [t] "such that"; [n] children/*[1]/children/*[3]',"self::fenced",'@role="set extended"');(0,sre.ClearspeakRules.defineRule_)("set-collection","clearspeak.Sets_SilentBracket","[n] children/*[1]","self::fenced",'@role="set collection"');(0,sre.ClearspeakRules.defineRule_)("subscript","clearspeak.default",'[p] (pause:short); [n] children/*[1]; [t] "sub"; [n] children/*[2]; [p] (pause:short)',
-"self::subscript");(0,sre.ClearspeakRules.defineRule_)("subscript-base","clearspeak.default",'[n] children/*[1]; [t] "base"; [n] children/*[2]',"self::subscript","CQFisLogarithm");(0,sre.ClearspeakRules.defineRule_)("subscript-index","clearspeak.default",'[n] children/*[1]; [t] "sub"; [n] children/*[2]',"self::subscript",'contains(@grammar, "simpleDet")');(0,sre.ClearspeakRules.defineRule_)("fraction","clearspeak.default",'[p] (pause:short); [t] "the fraction with numerator"; [n] children/*[1]; [p] (pause:short); [t] "and denominator"; [n] children/*[2]; [p] (pause:short)',
-"self::fraction");(0,sre.ClearspeakRules.defineRule_)("fraction","clearspeak.Functions_None",'[p] (pause:short); [t] "the fraction with numerator"; [n] children/*[1]; [p] (pause:short); [t] "and denominator"; [n] children/*[2]; [p] (pause:short)',"self::fraction",'name(children/*[1])="appl" or name(children/*[2])="appl"');(0,sre.ClearspeakRules.defineRule_)("simple-fraction","clearspeak.default",'[p] (pause:short); [n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::fraction",
-'contains(children/*[1]/@annotation, "clearspeak:simple") or contains(children/*[1]/@annotation, "clearspeak:unit")','contains(children/*[2]/@annotation, "clearspeak:simple") or contains(children/*[2]/@annotation, "clearspeak:unit")');(0,sre.ClearspeakRules.defineRule_)("simple-vulgar-fraction","clearspeak.default",'[p] (pause:short); [n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::fraction",'@role="vulgar"');(0,sre.ClearspeakRules.defineRule_)("simple-text-fraction","clearspeak.default",
-'[p] (pause:short); [n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::fraction",'name(children/*[1])="text"','name(children/*[2])="text"');(0,sre.ClearspeakRules.defineRule_)("simple-text-fraction","clearspeak.default",'[p] (pause:short); [n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::fraction",'name(children/*[1])="infixop"','children/*[1][@role="unit"]','name(children/*[2])="text"');(0,sre.ClearspeakRules.defineRule_)("vulgar-fraction","clearspeak.default",
-"[t] CSFvulgarFraction","self::fraction",'@role="vulgar"',"CQFvulgarFractionSmall");(0,sre.ClearspeakRules.defineRule_)("fraction","clearspeak.Fraction_Over",'[p] (pause:short); [n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::fraction");(0,sre.ClearspeakRules.defineRule_)("fraction","clearspeak.Fraction_OverEndFrac",'[p] (pause:short); [n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short); [t] "end fraction"; [p] (pause:short)',"self::fraction");(0,sre.ClearspeakRules.defineRule_)("fraction",
-"clearspeak.Fraction_FracOver",'[p] (pause:short); [t] "the fraction"; [n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::fraction");(0,sre.ClearspeakRules.defineRule_)("fraction","clearspeak.Fraction_Per",'[p] (pause:short); [n] children/*[1]; [t] "per"; [n] children/*[2]; [p] (pause:short)',"self::fraction");(0,sre.ClearspeakRules.defineRule_)("fraction","clearspeak.Fraction_GeneralEndFrac",'[p] (pause:short); [t] "the fraction with numerator"; [n] children/*[1]; [p] (pause:short); [t] "and denominator"; [n] children/*[2]; [p] (pause:short); [t] "end fraction"; [p] (pause:short)',
-"self::fraction");(0,sre.ClearspeakRules.defineRule_)("fraction","clearspeak.Fraction_General",'[p] (pause:short); [t] "the fraction with numerator"; [n] children/*[1]; [p] (pause:short); [t] "and denominator"; [n] children/*[2]; [p] (pause:short)',"self::fraction");(0,sre.ClearspeakRules.defineRule_)("simple-vulgar-fraction","clearspeak.Fraction_Ordinal","[t] CSFvulgarFraction","self::fraction",'@role="vulgar"');(0,sre.ClearspeakRules.defineRule_)("fraction","clearspeak.Fraction_EndFrac",'[p] (pause:short); [n] . (grammar:endfrac); [t] "end fraction"; [p] (pause:short)',
-"self::fraction",'not(contains(@grammar, "endfrac"))','not(contains(children/*[1]/@annotation, "clearspeak:unit"))','not(contains(children/*[2]/@annotation, "clearspeak:unit"))');(0,sre.ClearspeakRules.defineRule_)("vulgar-fraction","clearspeak.Fraction_EndFrac",'[p] (pause:short); [n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::fraction",'name(children/*[1])="fraction"','name(children/*[2])="fraction"','contains(children/*[1]/@annotation, "clearspeak:simple")','contains(children/*[2]/@annotation, "clearspeak:simple")');
-(0,sre.ClearspeakRules.defineRule_)("simple-vulgar-fraction","clearspeak.Fraction_EndFrac","[t] CSFvulgarFraction","self::fraction",'@role="vulgar"','contains(@annotation, "clearspeak:simple")',"self::*");(0,sre.ClearspeakRules.defineRule_)("sqrt","clearspeak.default",'[t] "the square root of"; [n] children/*[1] (grammar:EndRoot=false); [p] (pause:short)',"self::sqrt");(0,sre.ClearspeakRules.defineRule_)("sqrt-nested","clearspeak.default",'[p] (pause: "short"); [t] "the square root of"; [n] children/*[1] (grammar:EndRoot=false); [p] (pause:short)',
-"self::sqrt","not(preceding-sibling::*)","ancestor::sqrt|ancestor::root");(0,sre.ClearspeakRules.defineRule_)("negative-sqrt","clearspeak.default",'[t] "the negative square root of"; [n] children/*[1]/children/*[1] (grammar:EndRoot=false); [p] (pause:short)',"self::prefixop",'@role="negative"','name(children/*[1])="sqrt"');(0,sre.ClearspeakRules.defineRule_)("negative-sqrt","clearspeak.default",'[p] (pause: "short"); [t] "the negative square root of"; [n] children/*[1]/children/*[1] (grammar:EndRoot=false); [p] (pause:short)',
-"self::prefixop",'@role="negative"','name(children/*[1])="sqrt"',"not(preceding-sibling::*)","ancestor::sqrt|ancestor::root");(0,sre.ClearspeakRules.defineRule_)("sqrt-plus-minus","clearspeak.Roots_PosNegSqRoot",'[t] "the positive square root of"; [n] children/*[1] (grammar:EndRoot=false); [p] (pause:short)',"self::sqrt",'parent::stree or not(parent::*/parent::infixop[@role="addition"]) or (parent::*/parent::*[1]/text()!="\u00b1" and parent::*/parent::*/text()!="\u2213")');(0,sre.ClearspeakRules.defineRule_)("sqrt-nested-plus-minus",
-"clearspeak.Roots_PosNegSqRoot",'[p] (pause: "short"); [t] "the positive square root of"; [n] children/*[1] (grammar:EndRoot=false); [p] (pause:short)',"self::sqrt","not(preceding-sibling::*)","ancestor::sqrt|ancestor::root",'parent::stree or not(parent::*/parent::infixop[@role="addition"]) or (parent::*/parent::*[1]/text()!="\u00b1" and parent::*/parent::*/text()!="\u2213")');(0,sre.ClearspeakRules.defineRule_)("sqrt-plus-minus","clearspeak.Roots_PosNegSqRootEnd",'[t] "the positive square root of"; [n] children/*[1] (grammar:EndRoot=false); [p] (pause:short)',
-"self::sqrt",'parent::stree or not(parent::*/parent::infixop[@role="addition"]) or (parent::*/parent::*[1]/text()!="\u00b1" and parent::*/parent::*/text()!="\u2213")');(0,sre.ClearspeakRules.defineRule_)("sqrt-nested-plus-minus","clearspeak.Roots_PosNegSqRootEnd",'[p] (pause: "short"); [t] "the positive square root of"; [n] children/*[1] (grammar:EndRoot=false); [p] (pause:short)',"self::sqrt","not(preceding-sibling::*)","ancestor::sqrt|ancestor::root",'parent::stree or not(parent::*/parent::infixop[@role="addition"]) or (parent::*/parent::*[1]/text()!="\u00b1" and parent::*/parent::*/text()!="\u2213")');
-(0,sre.ClearspeakRules.defineRule_)("sqrt-endroot","clearspeak.Roots_RootEnd",'[n] . (grammar:EndRoot); [t] "end root"; [p] (pause:short)',"self::sqrt",'not(contains(@grammar, "EndRoot"))');(0,sre.ClearspeakRules.defineRule_)("negative-sqrt-endroot","clearspeak.Roots_RootEnd",'[n] . (grammar:EndRoot); [t] "end root"; [p] (pause:short)',"self::prefixop",'@role="negative"','name(children/*[1])="sqrt"','not(contains(@grammar, "EndRoot"))');(0,sre.ClearspeakRules.defineRule_)("sqrt-endroot","clearspeak.Roots_PosNegSqRootEnd",
-'[n] . (grammar:EndRoot); [t] "end root"; [p] (pause:short)',"self::sqrt",'not(contains(@grammar, "EndRoot"))');(0,sre.ClearspeakRules.defineRule_)("negative-sqrt-endroot","clearspeak.Roots_PosNegSqRootEnd",'[n] . (grammar:EndRoot); [t] "end root"; [p] (pause:short)',"self::prefixop",'@role="negative"','name(children/*[1])="sqrt"','not(contains(@grammar, "EndRoot"))');(0,sre.ClearspeakRules.defineRule_)("cube","clearspeak.default",'[t] "the cube root of"; [n] children/*[2] (grammar:EndRoot=false); [p] (pause:short)',
-"self::root",'children/*[1][text()="3"]');(0,sre.ClearspeakRules.defineRule_)("cube-nested","clearspeak.default",'[p] (pause:short); [t] "the cube root of"; [n] children/*[2] (grammar:EndRoot=false); [p] (pause:short)',"self::root",'children/*[1][text()="3"]',"not(preceding-sibling::*)","ancestor::sqrt|ancestor::root");(0,sre.ClearspeakRules.defineRule_)("root","clearspeak.default",'[t] "the"; [n] children/*[1] (grammar:ordinal); [t] "root of"; [n] children/*[2] (grammar:EndRoot=false); [p] (pause:short)',
-"self::root");(0,sre.ClearspeakRules.defineRule_)("root-nested","clearspeak.default",'[p] (pause:short); [t] "the"; [n] children/*[1] (grammar:ordinal); [t] "root of"; [n] children/*[2] (grammar:EndRoot=false); [p] (pause:short)',"self::root","not(preceding-sibling::*)","ancestor::sqrt|ancestor::root");(0,sre.ClearspeakRules.defineRule_)("root-endroot","clearspeak.Roots_RootEnd",'[n] . (grammar:EndRoot); [t] "end root"; [p] (pause:short)',"self::root",'not(contains(@grammar, "EndRoot"))');(0,sre.ClearspeakRules.defineRule_)("root-endroot",
-"clearspeak.Roots_PosNegSqRootEnd",'[n] . (grammar:EndRoot); [t] "end root"; [p] (pause:short)',"self::root",'not(contains(@grammar, "EndRoot"))');(0,sre.ClearspeakRules.defineRule_)("negative","clearspeak.default",'[t] "negative"; [n] children/*[1]',"self::prefixop",'@role="negative"');(0,sre.ClearspeakRules.defineRule_)("positive","clearspeak.default",'[t] "positive"; [n] children/*[1]',"self::prefixop",'@role="positive"');(0,sre.ClearspeakRules.defineRule_)("angle-measure","clearspeak.default",
-'[t] "the measure of"; [n] content/*[1]; [n] children/*[2] (grammar:angle)',"self::infixop",'content/*[1]/text()="\u2220"','children/*[1][text()="m"]');(0,sre.ClearspeakRules.defineRule_)("prefix","clearspeak.default","[m] content/* (grammar:prefix); [n] children/*[1]","self::prefixop");(0,sre.ClearspeakRules.defineRule_)("postfix","clearspeak.default","[n] children/*[1]; [m] content/* (grammar:postfix)","self::postfixop");(0,sre.ClearspeakRules.defineRule_)("set-prefix-operators","clearspeak.default",
-'[t] "the"; [n] self::* (grammar:!prefix); [t] "of"',"self::*",'contains(@grammar,"prefix")','descendant-or-self::*/text()="\u2229" or descendant-or-self::*/text()="\u222a"',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("binary-operation","clearspeak.default","[m] children/* (sepFunc:CTXFcontentIterator);","self::infixop");(0,sre.ClearspeakRules.defineRule_)("binary-operation","clearspeak.ImpliedTimes_MoreImpliedTimes","[m] children/* (sepFunc:CTXFcontentIterator);","self::infixop",
-'@role="implicit"');(0,sre.ClearspeakRules.defineRule_)("binary-operation-pause","clearspeak.default","[p] (pause:short); [m] children/* (sepFunc:CTXFcontentIterator);","self::infixop",'@role="implicit"','name(children/*[1])="appl"');(0,sre.ClearspeakRules.defineRule_)("binary-operation-pause","clearspeak.default","[m] children/* (sepFunc:CTXFcontentIterator); [p] (pause:short)","self::infixop",'@role="implicit"','name(children/*[last()])="appl"');(0,sre.ClearspeakRules.defineRule_)("binary-operation-pause",
-"clearspeak.default","[p] (pause:short); [m] children/* (sepFunc:CTXFcontentIterator); [p] (pause:short)","self::infixop",'@role="implicit"','name(children/*[1])="appl"','name(children/*[last()])="appl"');(0,sre.ClearspeakRules.defineRule_)("implicit-times","clearspeak.default","[p] (pause:short)","self::operator",'@role="multiplication"','text()="\u2062"');(0,sre.ClearspeakRules.defineRule_)("implicit-times","clearspeak.default","","self::operator",'@role="multiplication"','text()="\u2062"',"CQFsimpleArguments");
-(0,sre.ClearspeakRules.defineRule_)("implicit-times","clearspeak.default","[n] text()","self::operator",'@role="multiplication"','text()="\u2062"',"CQFfencedArguments");(0,sre.ClearspeakRules.defineRule_)("implicit-times","clearspeak.ImpliedTimes_MoreImpliedTimes","[n] text()","self::operator",'@role="multiplication"','text()="\u2062"');(0,sre.ClearspeakRules.defineRule_)("implicit-times","clearspeak.ImpliedTimes_None","","self::operator",'@role="multiplication"','text()="\u2062"');(0,sre.ClearspeakRules.defineRule_)("binary-operation-simple",
-"clearspeak.default",'[m] children/* (rate:"0.5"); [p] (pause:short)',"self::infixop",'@role="implicit"','contains(@annotation, "clearspeak:simple")','not(contains(@grammar, "inFrac"))');(0,sre.ClearspeakRules.defineRule_)("simple-in-fraction","clearspeak.default",'[n] . (rate:"0.5",grammar:inFrac)',"self::*",'contains(@annotation, "clearspeak:simple")','not(contains(@grammar, "inFrac"))','name(.)!="identifier"','name(.)!="function"','name(.)!="number"','name(parent::*/parent::*)="fraction"',"not(preceding-sibling::*)");
-(0,sre.ClearspeakRules.defineRule_)("operators-after-power","clearspeak.Exponent_AfterPower",'[m] children/* (rate:"0.5")',"self::infixop",'@role="implicit"','contains(@grammar, "afterPower")');(0,sre.ClearspeakRules.defineRule_)("relseq","clearspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::relseq");(0,sre.ClearspeakRules.defineRule_)("multrel","clearspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::multirel");(0,sre.ClearspeakRules.defineRule_)("natural-numbers",
-"clearspeak.default",'[t] "the natural numbers"',"self::identifier",'text()="\u2115" or (text()="N" and @font="double-struck")',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("integers","clearspeak.default",'[t] "the integers"',"self::identifier",'text()="\u2124" or (text()="Z" and @font="double-struck")',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("rational-numbers","clearspeak.default",'[t] "the rational numbers"',"self::identifier",'text()="\u211a" or (text()="Q" and @font="double-struck")',
-"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("real-numbers","clearspeak.default",'[t] "the real numbers"',"self::identifier",'text()="\u211d" or (text()="R" and @font="double-struck")',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("complex-numbers","clearspeak.default",'[t] "the complex numbers"',"self::identifier",'text()="\u2102" or (text()="C" and @font="double-struck")',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("natural-numbers-super",
-"clearspeak.default",'[t] "n" (join: "-"); [n] children/*[2] (grammar:numbers2alpha)',"self::superscript",'children/*[1]/text()="\u2115" or (children/*[1]/text()="N" and @font="double-struck")',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("integers-super","clearspeak.default",'[t] "z" (join: "-"); [n] children/*[2] (grammar:numbers2alpha)',"self::superscript",'children/*[1]/text()="\u2124" or (children/*[1]/text()="Z" and @font="double-struck")',"self::*","self::*","self::*");
-(0,sre.ClearspeakRules.defineRule_)("rational-numbers-super","clearspeak.default",'[t] "q" (join: "-"); [n] children/*[2] (grammar:numbers2alpha)',"self::superscript",'children/*[1]/text()="\u211a" or (children/*[1]/text()="Q" and @font="double-struck")',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("real-numbers-super","clearspeak.default",'[t] "r" (join:"-"); [n] children/*[2] (grammar:numbers2alpha)',"self::superscript",'children/*[1]/text()="\u211d" or (children/*[1]/text()="R" and @font="double-struck")',
-"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("complex-numbers-super","clearspeak.default",'[t] "c" (join:"-"); [n] children/*[2] (grammar:numbers2alpha)',"self::superscript",'children/*[1]/text()="\u2102" or (children/*[1]/text()="C" and @font="double-struck")',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("natural-numbers-with-zero","clearspeak.default",'[t] "the natural numbers with zero"',"self::subscript",'children/*[1]/text()="\u2115" or (children/*[1]/text()="N" and @font="double-struck")',
-'children/*[2]/text()="0"');(0,sre.ClearspeakRules.defineRule_)("positive-integers","clearspeak.default",'[t] "the positive integers"',"self::superscript",'children/*[1]/text()="\u2124" or (children/*[1]/text()="Z" and @font="double-struck")','children/*[2]/text()="+"',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("positive-integers","clearspeak.default",'[t] "the negative integers"',"self::superscript",'children/*[1]/text()="\u2124" or (children/*[1]/text()="Z" and @font="double-struck")',
-'children/*[2]/text()="-"',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("positive-rational-numbers","clearspeak.default",'[t] "the positive rational numbers"',"self::superscript",'children/*[1]/text()="\u211a" or (children/*[1]/text()="Q" and @font="double-struck")','children/*[2]/text()="+"',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("negative-rational-numbers","clearspeak.default",'[t] "the negative rational numbers"',"self::superscript",'children/*[1]/text()="\u211a" or (children/*[1]/text()="Q" and @font="double-struck")',
-'children/*[2]/text()="-"',"self::*","self::*","self::*");(0,sre.ClearspeakRules.defineRule_)("fences-neutral","clearspeak.default",'[p] (pause:short); [t] "the absolute value of"; [n] children/*[1]; [p] (pause: short)',"self::fenced",'@role="neutral"','content/*[1][text()]="|" or content/*[1][text()]="\u2758" or content/*[1][text()]="\uff5c"');(0,sre.ClearspeakRules.defineRule_)("fences-neutral","clearspeak.AbsoluteValue_AbsEnd",'[p] (pause:short); [t] "the absolute value of"; [n] children/*[1]; [p] (pause: short); [t] "end absolute value"; [p] (pause: short)',
-"self::fenced",'@role="neutral"','content/*[1][text()]="|" or content/*[1][text()]="\u2758" or content/*[1][text()]="\uff5c"');(0,sre.ClearspeakRules.defineRule_)("fences-neutral","clearspeak.AbsoluteValue_Cardinality",'[p] (pause:short); [t] "the cardinality of"; [n] children/*[1]; [p] (pause: short)',"self::fenced",'@role="neutral"','content/*[1][text()]="|" or content/*[1][text()]="\u2758" or content/*[1][text()]="\uff5c"');(0,sre.ClearspeakRules.defineRule_)("fences-neutral","clearspeak.AbsoluteValue_Determinant",
-'[p] (pause:short); [t] "the determinant of"; [n] children/*[1]; [p] (pause: short)',"self::fenced",'@role="neutral"','content/*[1][text()]="|" or content/*[1][text()]="\u2758" or content/*[1][text()]="\uff5c"');(0,sre.ClearspeakRules.defineRule_)("matrix","clearspeak.default",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "matrix"; [p] (pause:long); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Row-:"); [p] (pause:long)',"self::matrix");(0,sre.ClearspeakRules.defineRule_)("matrix-simple",
-"clearspeak.default",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "matrix"; [p] (pause:long); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Row-:",grammar:simpleDet); [p] (pause:long)',"self::matrix","count(children/*)<4","count(children/*[1]/children/*)<4","CQFcellsSimple");(0,sre.ClearspeakRules.defineRule_)("matrix-trivial","clearspeak.default",'[t] "the 1 by 1 matrix with entry"; [n] children/*[1]; [p] (pause:long)',"self::vector",'@role="squarematrix"');
-(0,sre.ClearspeakRules.defineRule_)("determinant","clearspeak.default",'[t] "the determinant of the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "matrix"; [p] (pause:long); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Row-:",grammar:simpleDet); [p] (pause:long)',"self::matrix",'@role="determinant"',"count(children/*)<4","CQFcellsSimple");(0,sre.ClearspeakRules.defineRule_)("determinant-simple","clearspeak.default",'[t] "the determinant of the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "matrix"; [p] (pause:long); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Row-:"); [p] (pause:long)',
-"self::matrix",'@role="determinant"');(0,sre.ClearspeakRules.defineRule_)("matrix-vector","clearspeak.default",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "column matrix"; [p] (pause:long); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Row-:",grammar:simpleDet); [p] (pause:long)',"self::vector");(0,sre.ClearspeakRules.defineSpecialisedRule_)("matrix-vector","clearspeak.default","clearspeak.Matrix_SpeakColNum");(0,sre.ClearspeakRules.defineRule_)("matrix-vector-simple",
-"clearspeak.default",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "column matrix"; [p] (pause:long); [m] children/* (sepFunc:CTXFpauseSeparator,separator:"short",grammar:simpleDet); [p] (pause:long)',"self::vector","count(children/*)<4","CQFcellsSimple",'@role!="squarematrix"');(0,sre.ClearspeakRules.defineRule_)("matrix-vector-simple","clearspeak.Matrix_SilentColNum",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "column matrix"; [p] (pause:long); [m] children/* (sepFunc:CTXFpauseSeparator,separator:"short",grammar:simpleDet); [p] (pause:long)',
-"self::vector");(0,sre.ClearspeakRules.defineRule_)("matrix-row-vector","clearspeak.default",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "row matrix"; [p] (pause:long); [m] children/*[1]/children/* (ctxtFunc:CTXFnodeCounter,context:"Column-:",grammar:simpleDet); [p] (pause:long)',"self::matrix",'@role="rowvector"');(0,sre.ClearspeakRules.defineSpecialisedRule_)("matrix-row-vector","clearspeak.default","clearspeak.Matrix_SpeakColNum");(0,sre.ClearspeakRules.defineRule_)("matrix-row-vector-simple",
-"clearspeak.default",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "row matrix"; [p] (pause:long); [m] children/*[1]/children/* (sepFunc:CTXFpauseSeparator,separator:"short",grammar:simpleDet); [p] (pause:long)',"self::matrix",'@role="rowvector"',"count(children/*[1]/children/*)<4","CQFcellsSimple");(0,sre.ClearspeakRules.defineRule_)("matrix-row-vector-simple","clearspeak.Matrix_SilentColNum",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "row matrix"; [p] (pause:long); [m] children/*[1]/children/* (sepFunc:CTXFpauseSeparator,separator:"short",grammar:simpleDet); [p] (pause:long)',
-"self::matrix",'@role="rowvector"');(0,sre.ClearspeakRules.defineRule_)("matrix-row-simple","clearspeak.default",'[m] children/* (sepFunc:CTXFpauseSeparator,separator:"short")',"self::row",'contains(@grammar, "simpleDet")');(0,sre.ClearspeakRules.defineRule_)("matrix-row-simple","clearspeak.Matrix_SilentColNum",'[m] children/* (sepFunc:CTXFpauseSeparator,separator:"short")',"self::row");(0,sre.ClearspeakRules.defineRule_)("line-simple","clearspeak.default","[n] children/*[1]","self::line",'contains(@grammar, "simpleDet")');
-(0,sre.ClearspeakRules.defineRule_)("matrix-row","clearspeak.default",'[m] children/* (ctxtFunc:CTXFnodeCounter,context:"Column-,- ",sepFunc:CTXFpauseSeparator,separator:"medium"); [p] (pause:long)',"self::row");(0,sre.ClearspeakRules.defineSpecialisedRule_)("matrix-row","clearspeak.default","clearspeak.Matrix_SpeakColNum");(0,sre.ClearspeakRules.defineRule_)("matrix-cell","clearspeak.default","[n] children/*[1]","self::cell");(0,sre.ClearspeakRules.defineRule_)("matrix-end-matrix","clearspeak.Matrix_EndMatrix",
-'[n] . (grammar:EndMatrix); [t] "end matrix"',"self::matrix",'not(contains(@grammar, "EndMatrix"))');(0,sre.ClearspeakRules.defineRule_)("matrix-end-vector","clearspeak.Matrix_EndMatrix",'[n] . (grammar:EndMatrix); [t] "end matrix"',"self::vector",'not(contains(@grammar, "EndMatrix"))');(0,sre.ClearspeakRules.defineRule_)("matrix-end-determinant","clearspeak.Matrix_EndMatrix",'[n] . (grammar:EndMatrix); [t] "end determinant"',"self::matrix",'@role="determinant"','not(contains(@grammar, "EndMatrix"))');
-(0,sre.ClearspeakRules.defineRule_)("vector","clearspeak.Matrix_Vector",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "column vector"; [p] (pause:long); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Row-:",grammar:simpleDet); [p] (pause:long)',"self::vector");(0,sre.ClearspeakRules.defineSpecialisedRule_)("vector","clearspeak.Matrix_Vector","clearspeak.Matrix_EndVector");(0,sre.ClearspeakRules.defineRule_)("vector-simple","clearspeak.Matrix_Vector",'[t] "the"; [t] count(children/*); [t] "by"; [t] count(children/*[1]/children/*); [t] "column vector"; [p] (pause:long); [m] children/* (sepFunc:CTXFpauseSeparator,separator:"short",grammar:simpleDet); [p] (pause:long)',
-"self::vector","count(children/*)<4","CQFcellsSimple");(0,sre.ClearspeakRules.defineSpecialisedRule_)("vector-simple","clearspeak.Matrix_Vector","clearspeak.Matrix_EndVector");(0,sre.ClearspeakRules.defineRule_)("row-vector","clearspeak.Matrix_Vector",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "row vector"; [p] (pause:long); [m] children/*[1]/children/* (ctxtFunc:CTXFnodeCounter,context:"Column-:",grammar:simpleDet); [p] (pause:long)',"self::matrix",'@role="rowvector"');
-(0,sre.ClearspeakRules.defineSpecialisedRule_)("row-vector","clearspeak.Matrix_Vector","clearspeak.Matrix_EndVector");(0,sre.ClearspeakRules.defineRule_)("row-vector-simple","clearspeak.Matrix_Vector",'[t] "the"; [t] count(children/*); [t] "by";[t] count(children/*[1]/children/*); [t] "row vector"; [p] (pause:long); [m] children/*[1]/children/* (sepFunc:CTXFpauseSeparator,separator:"short",grammar:simpleDet); [p] (pause:long)',"self::matrix",'@role="rowvector"',"count(children/*[1]/children/*)<4",
-"CQFcellsSimple");(0,sre.ClearspeakRules.defineSpecialisedRule_)("row-vector-simple","clearspeak.Matrix_Vector","clearspeak.Matrix_EndVector");(0,sre.ClearspeakRules.defineRule_)("vector-end-matrix","clearspeak.Matrix_EndVector",'[n] . (grammar:EndMatrix); [t] "end matrix"',"self::matrix",'not(contains(@grammar, "EndMatrix"))',"self::*");(0,sre.ClearspeakRules.defineRule_)("vector-end-vector","clearspeak.Matrix_EndVector",'[n] . (grammar:EndMatrix); [t] "end vector"',"self::vector",'not(contains(@grammar, "EndMatrix"))',
-"self::*");(0,sre.ClearspeakRules.defineRule_)("vector-end-vector","clearspeak.Matrix_EndVector",'[n] . (grammar:EndMatrix); [t] "end vector"',"self::matrix",'@role="rowvector"','not(contains(@grammar, "EndMatrix"))',"self::*");(0,sre.ClearspeakRules.defineRule_)("vector-end-determinant","clearspeak.Matrix_EndVector",'[n] . (grammar:EndMatrix); [t] "end determinant"',"self::matrix",'@role="determinant"','not(contains(@grammar, "EndMatrix"))',"self::*");(0,sre.ClearspeakRules.defineRule_)("binomial",
-"clearspeak.Matrix_Combinatoric",'[n] children/*[1]/children/*[1]; [t] "choose"; [n] children/*[2]/children/*[1]; ',"self::vector",'@role="binomial"');(0,sre.ClearspeakRules.defineRule_)("lines-summary","clearspeak.default",'[p] (pause:short); [t] count(children/*); [t] "lines"; [n] . (grammar:layoutSummary)',"self::multiline",'not(contains(@grammar, "layoutSummary"))',"self::*");(0,sre.ClearspeakRules.defineRule_)("lines-summary","clearspeak.MultiLineOverview_None","[n] . (grammar:layoutSummary)",
-"self::multiline",'not(contains(@grammar, "layoutSummary"))',"self::*");(0,sre.ClearspeakRules.defineRuleAlias_)("lines-summary","self::table",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRule_)("cases-summary","clearspeak.default",'[p] (pause:short); [t] count(children/*); [t] "cases"; [n] . (grammar:layoutSummary)',"self::cases",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRule_)("cases-summary","clearspeak.MultiLineOverview_None","[n] . (grammar:layoutSummary)",
-"self::cases",'not(contains(@grammar, "layoutSummary"))',"self::*");(0,sre.ClearspeakRules.defineRule_)("lines","clearspeak.default",'[p] (pause:short); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Line-:",sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',"self::table");(0,sre.ClearspeakRules.defineRuleAlias_)("lines","self::multiline");(0,sre.ClearspeakRules.defineRule_)("line","clearspeak.default","[n] children/*[1]","self::line");(0,sre.ClearspeakRules.defineRule_)("row-medium",
-"clearspeak.default",'[m] children/* (sepFunc:CTXFpauseSeparator,separator:"medium")',"self::row",'@role="table"');(0,sre.ClearspeakRules.defineRuleAlias_)("row-medium","self::row",'@role="cases"');(0,sre.ClearspeakRules.defineRule_)("row-long","clearspeak.MultiLinePausesBetweenColumns_Long",'[m] children/* (sepFunc:CTXFpauseSeparator,separator:"long")',"self::row",'@role="table"');(0,sre.ClearspeakRules.defineRuleAlias_)("row-long","self::row",'@role="cases"');(0,sre.ClearspeakRules.defineRule_)("row-short",
-"clearspeak.MultiLinePausesBetweenColumns_Short",'[m] children/* (sepFunc:CTXFpauseSeparator,separator:"short")',"self::row",'@role="table"');(0,sre.ClearspeakRules.defineRuleAlias_)("row-short","self::row",'@role="cases"');(0,sre.ClearspeakRules.defineRule_)("blank-cell","clearspeak.default",'[t] "blank"',"self::cell","count(children/*)=0");(0,sre.ClearspeakRules.defineRule_)("blank-empty","clearspeak.default",'[t] "blank"',"self::empty","count(../*)=1",'name(../..)="cell" or name(../..)="line"');
-(0,sre.ClearspeakRules.defineRule_)("cases","clearspeak.default",'[p] (pause:short); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Case-:",sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',"self::cases");(0,sre.ClearspeakRules.defineRule_)("lines-cases-summary","clearspeak.MultiLineLabel_Case",'[p] (pause:short); [t] count(children/*); [t] "cases"; [n] . (grammar:layoutSummary)',"self::multiline",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRuleAlias_)("lines-cases-summary",
-"self::table",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRule_)("lines-cases","clearspeak.MultiLineLabel_Case",'[p] (pause:short); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Case-:",sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',"self::table");(0,sre.ClearspeakRules.defineRuleAlias_)("lines-cases","self::multiline");(0,sre.ClearspeakRules.defineRule_)("lines-equations-summary","clearspeak.MultiLineLabel_Equation",'[p] (pause:short); [t] count(children/*); [t] "equations"; [n] . (grammar:layoutSummary)',
-"self::multiline",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRuleAlias_)("lines-equations-summary","self::table",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRule_)("lines-equations","clearspeak.MultiLineLabel_Equation",'[p] (pause:short); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Equation-:",sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',"self::table");(0,sre.ClearspeakRules.defineRuleAlias_)("lines-equations","self::multiline");
-(0,sre.ClearspeakRules.defineRule_)("lines-steps-summary","clearspeak.MultiLineLabel_Step",'[p] (pause:short); [t] count(children/*); [t] "steps"; [n] . (grammar:layoutSummary)',"self::multiline",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRuleAlias_)("lines-steps-summary","self::table",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRule_)("lines-steps","clearspeak.MultiLineLabel_Step",'[p] (pause:short); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Step-:",sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',
-"self::table");(0,sre.ClearspeakRules.defineRuleAlias_)("lines-steps","self::multiline");(0,sre.ClearspeakRules.defineRule_)("lines-rows-summary","clearspeak.MultiLineLabel_Row",'[p] (pause:short); [t] count(children/*); [t] "rows"; [n] . (grammar:layoutSummary)',"self::multiline",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRuleAlias_)("lines-rows-summary","self::table",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRule_)("lines-rows","clearspeak.MultiLineLabel_Row",
-'[p] (pause:short); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Row-:",sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',"self::table");(0,sre.ClearspeakRules.defineRuleAlias_)("lines-rows","self::multiline");(0,sre.ClearspeakRules.defineRule_)("lines-steps-summary","clearspeak.MultiLineLabel_Step",'[p] (pause:short); [t] count(children/*); [t] "steps"; [n] . (grammar:layoutSummary)',"self::multiline",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRuleAlias_)("lines-steps-summary",
-"self::table",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRule_)("lines-steps","clearspeak.MultiLineLabel_Step",'[p] (pause:short); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Step-:",sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',"self::table");(0,sre.ClearspeakRules.defineRuleAlias_)("lines-steps","self::multiline");(0,sre.ClearspeakRules.defineRule_)("lines-constraints-summary","clearspeak.MultiLineLabel_Constraint",'[p] (pause:short); [t] count(children/*); [t] "constraints"; [n] . (grammar:layoutSummary)',
-"self::multiline",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRuleAlias_)("lines-constraints-summary","self::table",'not(contains(@grammar, "layoutSummary"))');(0,sre.ClearspeakRules.defineRule_)("lines-constraints","clearspeak.MultiLineLabel_Constraint",'[p] (pause:short); [m] children/* (ctxtFunc:CTXFnodeCounter,context:"Constraint-:",sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',"self::table");(0,sre.ClearspeakRules.defineRuleAlias_)("lines-constraints",
-"self::multiline");(0,sre.ClearspeakRules.defineRule_)("lines-none","clearspeak.MultiLineLabel_None",'[p] (pause:short); [m] children/* (sepFunc:CTXFpauseSeparator,separator:"long"); [p] (pause:long)',"self::table",'contains(@grammar, "layoutSummary")');(0,sre.ClearspeakRules.defineRuleAlias_)("lines-none","self::multiline",'contains(@grammar, "layoutSummary")');(0,sre.ClearspeakRules.defineRuleAlias_)("lines-none","self::cases",'contains(@grammar, "layoutSummary")');(0,sre.ClearspeakRules.defineRule_)("bigop",
-"clearspeak.default",'[t] "the"; [n] children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:short)',"self::bigop");(0,sre.ClearspeakRules.defineRule_)("limboth","clearspeak.default",'[n] children/*[1]; [t] "from"; [n] children/*[2];[t] "to"; [n] children/*[3];',"self::limboth");(0,sre.ClearspeakRules.defineRule_)("limlower","clearspeak.default",'[n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::limlower");(0,sre.ClearspeakRules.defineRule_)("limupper","clearspeak.default",
-'[n] children/*[1]; [t] "under"; [n] children/*[2]; [p] (pause:short)',"self::limupper");(0,sre.ClearspeakRules.defineRule_)("integral","clearspeak.default",'[t] "the"; [n] children/*[1]; [t] "of"; [n] children/*[2]; [p] (pause:short)',"self::integral");(0,sre.ClearspeakRules.defineRule_)("overscript","clearspeak.default",'[n] children/*[1]; [t] "under"; [n] children/*[2]; [p] (pause:short)',"self::overscore");(0,sre.ClearspeakRules.defineRule_)("overscript","clearspeak.default","[n] children/*[1]; [n] children/*[2];",
-"self::overscore",'children/*[2][@role="overaccent"]');(0,sre.ClearspeakRules.defineRule_)("overscript-limits","clearspeak.default",'[n] children/*[1]; [t] "to"; [n] children/*[2]',"self::overscore",'children/*[2][@role!="overaccent"]','name(children/*[1])="underscore"','children/*[1]/children/*[2][@role!="underaccent"]');(0,sre.ClearspeakRules.defineRule_)("underscript","clearspeak.default",'[n] children/*[1]; [t] "over"; [n] children/*[2]; [p] (pause:short)',"self::underscore");(0,sre.ClearspeakRules.defineRule_)("underscript-limits",
-"clearspeak.default",'[n] children/*[1]; [t] "from"; [n] children/*[2]',"self::underscore",'@role="underover"','children/*[2][@role!="underaccent"]');(0,sre.ClearspeakRules.defineRule_)("decimal-period","clearspeak.default",'[t] "the repeating decimal"; [n] children/*[1] (grammar:spaceout); [t] "point followed by repeating digits"; [n] children/*[3]/children/*[1] (grammar:spaceout)',"self::punctuated",'@role="sequence"',"count(./content/*)=1",'./content/*[1][@role="fullstop"]','name(children/*[1])="number"',
-'children/*[1][@role="integer"]','name(children/*[3])="overscore"','children/*[3][@role="integer"]','children/*[3]/children/*[2][@role="overaccent"]','children/*[3]/children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]');(0,sre.ClearspeakRules.defineRule_)("decimal-period","clearspeak.default",'[t] "the repeating decimal"; [n] children/*[1] (grammar:spaceout); [t] "followed by repeating digits"; [n] children/*[2]/children/*[1] (grammar:spaceout);',
-"self::infixop",'@role="implicit"',"count(./children/*)=2",'name(children/*[1])="number"','children/*[1][@role="float"]','name(children/*[2])="overscore"','children/*[2][@role="integer"]','children/*[2]/children/*[2][@role="overaccent"]','children/*[2]/children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]');(0,sre.ClearspeakRules.defineRule_)("decimal-period-singular","clearspeak.default",'[t] "the repeating decimal"; [n] children/*[1] (grammar:spaceout); [t] "point followed by repeating digit"; [n] children/*[3]/children/*[1] (grammar:spaceout)',
-"self::punctuated",'@role="sequence"',"count(./content/*)=1",'./content/*[1][@role="fullstop"]','name(children/*[1])="number"','children/*[1][@role="integer"]','name(children/*[3])="overscore"','children/*[3][@role="integer"]','children/*[3]/children/*[2][@role="overaccent"]','children/*[3]/children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]',"string-length(./children/*[3]/children/*[1]/text())=1");(0,sre.ClearspeakRules.defineRule_)("decimal-period-singular",
-"clearspeak.default",'[t] "the repeating decimal"; [n] children/*[1] (grammar:spaceout); [t] "followed by repeating digit"; [n] children/*[2]/children/*[1] (grammar:spaceout);',"self::infixop",'@role="implicit"',"count(./children/*)=2",'name(children/*[1])="number"','children/*[1][@role="float"]','name(children/*[2])="overscore"','children/*[2][@role="integer"]','children/*[2]/children/*[2][@role="overaccent"]','children/*[2]/children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]',
-"string-length(./children/*[2]/children/*[1]/text())=1");(0,sre.ClearspeakRules.defineRule_)("number-with-spaces","clearspeak.default","[m] CQFspaceoutNumber (grammar:!spaceout)","self::number",'contains(@grammar, "spaceout")');(0,sre.ClearspeakRules.defineRule_)("decimal-point","clearspeak.default",'[t] "point"',"self::number",'@role="fullstop"');(0,sre.ClearspeakRules.defineRule_)("line-segment","clearspeak.default",'[t] "the line segment"; [n] children/*[1]/children/*[1]; [n] children/*[1]/children/*[2]; [p] (pause:short)',
-"self::overscore",'@role="implicit"','children/*[2][@role="overaccent"]','children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]','name(children/*[1])="infixop"',"count(./children/*[1]/children/*)=2");(0,sre.ClearspeakRules.defineRule_)("conjugate","clearspeak.Bar_Conjugate",'[t] "the complex conjugate of"; [n] children/*[1]',"self::overscore",'children/*[2][@role="overaccent"]','children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]');
-(0,sre.ClearspeakRules.defineRule_)("defined-by","clearspeak.default",'[t] "is defined to be" (pause:short)',"self::overscore",'@role="equality"','@embellished="relation"','name(children/*[2])="text"','children/*[2][text()]="def"');(0,sre.ClearspeakRules.defineRule_)("adorned-sign","clearspeak.default",'[n] children/*[1] ; [t] "sign with"; [n] children/*[2]; [t] "over it"',"self::overscore","@embellished",'name(children/*[1])="operator" or name(children/*[1])="relation"');(0,sre.ClearspeakRules.defineRule_)("factorial",
-"clearspeak.default",'[t] "factorial"',"self::punctuation",'text()="!"','name(preceding-sibling::*[1])!="text"');(0,sre.ClearspeakRules.defineRule_)("tensor-base","clearspeak.default","[n] children/*[2]; [n] children/*[3]; [n] children/*[1]; [n] children/*[4]; [n] children/*[5]","self::tensor");(0,sre.ClearspeakRules.defineRule_)("left-super","clearspeak.default",'[t] "left super"; [n] text()','self::*[@role="leftsuper"]','not(contains(@grammar,"combinatorics"))');(0,sre.ClearspeakRules.defineRule_)("left-super",
-"clearspeak.default",'[t] "left super"; [m] children/*',"self::punctuated",'@role="leftsuper"','not(contains(@grammar,"combinatorics"))');(0,sre.ClearspeakRules.defineRule_)("left-sub","clearspeak.default",'[t] "left sub"; [n] text()','self::*[@role="leftsub"]','not(contains(@grammar,"combinatorics"))');(0,sre.ClearspeakRules.defineRule_)("left-sub","clearspeak.default",'[t] "left sub"; [m] children/*',"self::punctuated",'@role="leftsub"','not(contains(@grammar,"combinatorics"))');(0,sre.ClearspeakRules.defineRule_)("right-super",
-"clearspeak.default",'[t] "right super"; [n] text()','self::*[@role="rightsuper"]','not(contains(@grammar,"combinatorics"))');(0,sre.ClearspeakRules.defineRule_)("right-super","clearspeak.default",'[t] "right super"; [m] children/*',"self::punctuated",'@role="rightsuper"','not(contains(@grammar,"combinatorics"))');(0,sre.ClearspeakRules.defineRule_)("right-sub","clearspeak.default",'[t] "right sub"; [n] text()','self::*[@role="rightsub"]','not(contains(@grammar,"combinatorics"))');(0,sre.ClearspeakRules.defineRule_)("right-sub",
-"clearspeak.default",'[t] "right sub"; [m] children/*',"self::punctuated",'@role="rightsub"','not(contains(@grammar,"combinatorics"))');(0,sre.ClearspeakRules.defineRule_)("empty-index","clearspeak.default","[p] (pause:medium)","self::empty",'@role="rightsub" or @role="rightsuper" or @role="leftsub" or @role="leftsuper"');(0,sre.ClearspeakRules.defineRule_)("combinatorics","clearspeak.default","[n] children/*[2] (grammar:combinatorics); [n] children/*[1]; [n] children/*[4] (grammar:combinatorics)",
-"self::tensor",'name(children/*[3])="empty"','name(children/*[5])="empty"','children/*[1][text()="P" or text()="C"]');(0,sre.ClearspeakRules.defineRule_)("choose","clearspeak.CombinationPermutation_ChoosePermute",'[n] children/*[2] (grammar:combinatorics); [t] "choose"; [n] children/*[4] (grammar:combinatorics)',"self::tensor",'name(children/*[3])="empty"','name(children/*[5])="empty"','children/*[1][text()="C"]');(0,sre.ClearspeakRules.defineRule_)("permute","clearspeak.CombinationPermutation_ChoosePermute",
-'[n] children/*[2] (grammar:combinatorics); [t] "permute"; [n] children/*[4] (grammar:combinatorics)',"self::tensor",'name(children/*[3])="empty"','name(children/*[5])="empty"','children/*[1][text()="P"]')};sre.ClearspeakRules.getInstance().initializer=[sre.ClearspeakRules.initCustomFunctions_,sre.ClearspeakRules.initClearspeakRules_,sre.ClearspeakRules.addAnnotators_,sre.ClearspeakRules.addComparator_];sre.Grammar.getInstance().setPreprocessor("numbers2alpha",sre.ClearspeakUtil.numbersToAlpha);sre.MathmlStoreUtil={};sre.MathmlStoreUtil.matchMathjaxToMathml=function(a){return sre.Engine.getInstance().alternativeHost.querySelector("#"+a.id)};sre.MathmlStoreUtil.retrieveMathjaxExtender=function(a){return(a=sre.MathmlStoreUtil.matchMathjaxToMathml(a))?[a]:[]};sre.MathmlStoreUtil.retrieveMathjaxLeaf=function(a){return(a=sre.MathmlStoreUtil.matchMathjaxToMathml(a))?[a]:[]};
-sre.MathmlStoreUtil.checkMathjaxTag=function(a,b){var c=sre.MathmlStoreUtil.matchMathjaxToMathml(a);return c&&c.tagName.toUpperCase()==b?[c]:[]};sre.MathmlStoreUtil.checkMathjaxMunder=function(a){return sre.MathmlStoreUtil.checkMathjaxTag(a,"MUNDER")};sre.MathmlStoreUtil.checkMathjaxMover=function(a){return sre.MathmlStoreUtil.checkMathjaxTag(a,"MOVER")};sre.MathmlStoreUtil.checkMathjaxMsub=function(a){return sre.MathmlStoreUtil.checkMathjaxTag(a,"MSUB")};
-sre.MathmlStoreUtil.checkMathjaxMsup=function(a){return sre.MathmlStoreUtil.checkMathjaxTag(a,"MSUP")};sre.MathmlStoreUtil.mfencedSeparators=function(a,b){var c=sre.MathUtil.nextSeparatorFunction(b);return function(){return c?[sre.AuditoryDescription.create({text:c()},{translate:!0})]:[]}};
-sre.MathmlStoreUtil.contentIterator=function(a,b){var c=0<a.length?sre.XpathUtil.evalXPath("../../content/*",a[0]):[];return function(){var a=c.shift(),e=b?[sre.AuditoryDescription.create({text:b},{translate:!0})]:[];if(!a)return e;a=sre.SpeechRuleEngine.getInstance().evaluateNode(a);return e.concat(a)}};sre.EmacspeakRules=function(){sre.MathStore.call(this)};goog.inherits(sre.EmacspeakRules,sre.MathStore);goog.addSingletonGetter(sre.EmacspeakRules);sre.EmacspeakRules.mathStore=sre.EmacspeakRules.getInstance();sre.EmacspeakRules.defineRule_=goog.bind(sre.EmacspeakRules.mathStore.defineRule,sre.EmacspeakRules.mathStore);sre.EmacspeakRules.defineRuleAlias_=goog.bind(sre.EmacspeakRules.mathStore.defineRuleAlias,sre.EmacspeakRules.mathStore);
-sre.EmacspeakRules.addContextFunction_=goog.bind(sre.EmacspeakRules.mathStore.contextFunctions.add,sre.EmacspeakRules.mathStore.contextFunctions);sre.EmacspeakRules.addCustomQuery_=goog.bind(sre.EmacspeakRules.mathStore.customQueries.add,sre.EmacspeakRules.mathStore.customQueries);sre.EmacspeakRules.addCustomString_=goog.bind(sre.EmacspeakRules.mathStore.customStrings.add,sre.EmacspeakRules.mathStore.customStrings);
-sre.EmacspeakRules.initCustomFunctions_=function(){(0,sre.EmacspeakRules.addContextFunction_)("CTXFnodeCounter",sre.StoreUtil.nodeCounter);(0,sre.EmacspeakRules.addContextFunction_)("CTXFcontentIterator",sre.MathmlStoreUtil.contentIterator);(0,sre.EmacspeakRules.addCustomQuery_)("CQFvulgarFractionSmall",sre.MathspeakUtil.isSmallVulgarFraction);(0,sre.EmacspeakRules.addCustomString_)("CSFvulgarFraction",sre.MathspeakUtil.vulgarFraction)};
-sre.EmacspeakRules.initSemanticRules_=function(){(0,sre.EmacspeakRules.defineRule_)("stree","emacspeak.default","[n] ./*[1]","self::stree");(0,sre.EmacspeakRules.defineRule_)("multrel","emacspeak.default",'[t] "multirelation"; [m] children/* (sepFunc:CTXFcontentIterator)',"self::multirel");(0,sre.EmacspeakRules.defineRule_)("variable-equality","emacspeak.default",'[t] "equation sequence"; [m] children/* (context:"part",ctxtFunc:CTXFnodeCounter,sepFunc:CTXFcontentIterator)','self::relseq[@role="equality"]',
-"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.EmacspeakRules.defineRule_)("multi-equality","emacspeak.default",'[t] "equation sequence"; [m] children/* (context:"part",ctxtFunc:CTXFnodeCounter,sepFunc:CTXFcontentIterator)','self::relseq[@role="equality"]',"count(./children/*)>2");(0,sre.EmacspeakRules.defineRule_)("multi-equality","emacspeak.short",'[t] "equation sequence"; [m] children/* (sepFunc:CTXFcontentIterator)','self::relseq[@role="equality"]',"count(./children/*)>2");
-(0,sre.EmacspeakRules.defineRule_)("equality","emacspeak.default",'[t] "equation"; [t] "left hand side"; [n] children/*[1];[p] (pause:200); [n] content/*[1] (pause:200);[t] "right hand side"; [n] children/*[2]','self::relseq[@role="equality"]',"count(./children/*)=2");(0,sre.EmacspeakRules.defineRule_)("simple-equality","emacspeak.default","[n] children/*[1]; [p] (pause:200); [n] content/*[1] (pause:200);[n] children/*[2]",'self::relseq[@role="equality"]',"count(./children/*)=2","./children/identifier or ./children/number");
-(0,sre.EmacspeakRules.defineRule_)("simple-equality2","emacspeak.default","[n] children/*[1]; [p] (pause:200); [n] content/*[1] (pause:200);[n] children/*[2]",'self::relseq[@role="equality"]',"count(./children/*)=2","./children/function or ./children/appl");(0,sre.EmacspeakRules.defineRule_)("relseq","emacspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::relseq");(0,sre.EmacspeakRules.defineRule_)("implicit","emacspeak.default","[m] children/*","self::infixop",'@role="implicit"',
-'children/*[1][@role="latinletter"] or children/*[1][@role="greekletter"] or children/*[1][@role="otherletter"] or name(children/*[1])="number"','children/*[2][@role="latinletter"] or children/*[2][@role="greekletter"] or children/*[2][@role="otherletter"] or name(children/*[2])="number"');(0,sre.EmacspeakRules.defineRule_)("binary-operation","emacspeak.default","[p] (pause:100); [m] children/* (sepFunc:CTXFcontentIterator); [p] (pause:100);","self::infixop");(0,sre.EmacspeakRules.defineRule_)("variable-addition",
-"emacspeak.default",'[t] "sum with variable number of summands";[p] (pause:400); [m] children/* (sepFunc:CTXFcontentIterator)','self::infixop[@role="addition"]',"count(children/*)>2",'children/punctuation[@role="ellipsis"]');(0,sre.EmacspeakRules.defineRule_)("prefix","emacspeak.default",'[t] "prefix"; [n] text(); [t] "of" (pause 150);[n] children/*[1]',"self::prefixop");(0,sre.EmacspeakRules.defineRule_)("negative","emacspeak.default",'[t] "negative"; [n] children/*[1]',"self::prefixop",'self::prefixop[@role="negative"]');
-(0,sre.EmacspeakRules.defineRule_)("postfix","emacspeak.default",'[n] children/*[1]; [t] "postfix"; [n] text() (pause 300)',"self::postfixop");(0,sre.EmacspeakRules.defineRule_)("identifier","emacspeak.default","[n] text()","self::identifier");(0,sre.EmacspeakRules.defineRule_)("number","emacspeak.default","[n] text()","self::number");(0,sre.EmacspeakRules.defineRule_)("font","mathspeak.default","[t] @font; [n] . (grammar:ignoreFont=@font)","self::*","@font",'not(contains(@grammar, "ignoreFont"))',
-'@font!="normal"');(0,sre.EmacspeakRules.defineRule_)("font-identifier-short","emacspeak.default","[t] @font; [n] CQFhideFont; [t] CSFshowFont","self::identifier","string-length(text())=1","@font",'@font="normal"','""=translate(text(), "abcdefghijklmnopqrstuvwxyz\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9", "")',
-'@role!="unit"');(0,sre.EmacspeakRules.defineRule_)("font-identifier","mathspeak.default","[t] @font; [n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'@font="normal"','not(contains(@grammar, "ignoreFont"))','@role!="unit"');(0,sre.EmacspeakRules.defineRule_)("omit-font","mathspeak.default","[n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'not(contains(@grammar, "ignoreFont"))','@font="italic"');(0,sre.EmacspeakRules.defineRule_)("simple-fraction",
-"emacspeak.default",'[p] (pause:100); [n] children/*[1] (rate:0.35); [t] "over"; [n] children/*[2] (rate:-0.35); [p] (pause:100)',"self::fraction",'name(children/*[1])="number" or name(children/*[1])="identifier"','name(children/*[2])="number" or name(children/*[2])="identifier"');(0,sre.EmacspeakRules.defineRule_)("vulgar-fraction","emacspeak.default","[t] CSFvulgarFraction","self::fraction",'@role="vulgar"',"CQFvulgarFractionSmall");(0,sre.EmacspeakRules.defineRule_)("fraction","emacspeak.default",
-'[p] (pause:250); [n] children/*[1] (rate:0.35); [p] (pause:250); [t] "divided by"; [p] (pause:250); [n] children/*[2] (rate:-0.35); [p] (pause:250)',"self::fraction");(0,sre.EmacspeakRules.defineRule_)("superscript","emacspeak.default",'[n] children/*[1]; [t] "super"; [n] children/*[2] (pitch:0.35);[p] (pause:300)',"self::superscript");(0,sre.EmacspeakRules.defineRule_)("subscript","emacspeak.default",'[n] children/*[1]; [t] "sub"; [n] children/*[2] (pitch:-0.35);[p] (pause:300)',"self::subscript");
-(0,sre.EmacspeakRules.defineRule_)("ellipsis","emacspeak.default",'[p] (pause:200); [t] "ellipsis"; [p] (pause:300)',"self::punctuation",'self::punctuation[@role="ellipsis"]');(0,sre.EmacspeakRules.defineRule_)("fence-single","emacspeak.default","[n] text()","self::punctuation",'self::punctuation[@role="openfence"]');(0,sre.EmacspeakRules.defineRuleAlias_)("fence-single","self::punctuation",'self::punctuation[@role="closefence"]');(0,sre.EmacspeakRules.defineRuleAlias_)("fence-single","self::punctuation",
-'self::punctuation[@role="vbar"]');(0,sre.EmacspeakRules.defineRuleAlias_)("fence-single","self::punctuation",'self::punctuation[@role="application"]');(0,sre.EmacspeakRules.defineRule_)("omit-empty","emacspeak.default","[p] (pause:100)","self::empty");(0,sre.EmacspeakRules.defineRule_)("fences-open-close","emacspeak.default","[p] (pause:200); [n] children/*[1] (rate:0.35); [p] (pause:200)","self::fenced",'@role="leftright"');(0,sre.EmacspeakRules.defineRule_)("fences-open-close-in-appl","emacspeak.default",
-"[p] (pause:200); [n] children/*[1]; [p] (pause:200);",'self::fenced[@role="leftright"]',"./parent::children/parent::appl");(0,sre.EmacspeakRules.defineRule_)("fences-neutral","emacspeak.default",'[p] (pause:100); [t] "absolute value of"; [n] children/*[1];[p] (pause:350);',"self::fenced",'self::fenced[@role="neutral"]');(0,sre.EmacspeakRules.defineRule_)("omit-fences","emacspeak.default","[p] (pause:500); [n] children/*[1]; [p] (pause:200);","self::fenced");(0,sre.EmacspeakRules.defineRule_)("matrix",
-"emacspeak.default",'[t] "matrix"; [m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:100)',"self::matrix");(0,sre.EmacspeakRules.defineRule_)("matrix-row","emacspeak.default",'[m] children/* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)','self::row[@role="matrix"]');(0,sre.EmacspeakRules.defineRule_)("matrix-cell","emacspeak.default","[n] children/*[1]",'self::cell[@role="matrix"]');(0,sre.EmacspeakRules.defineRule_)("vector","emacspeak.default",'[t] "vector"; [m] children/* (ctxtFunc:CTXFnodeCounter,context:"element",pause:100)',
-"self::vector");(0,sre.EmacspeakRules.defineRule_)("cases","emacspeak.default",'[t] "case statement"; [m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100)',"self::cases");(0,sre.EmacspeakRules.defineRule_)("cases-row","emacspeak.default","[m] children/*",'self::row[@role="cases"]');(0,sre.EmacspeakRules.defineRule_)("cases-cell","emacspeak.default","[n] children/*[1]",'self::cell[@role="cases"]');(0,sre.EmacspeakRules.defineRule_)("row","emacspeak.default",'[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
-"self::row");(0,sre.EmacspeakRules.defineRule_)("cases-end","emacspeak.default",'[t] "case statement"; [m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100);[t] "end cases"',"self::cases","following-sibling::*");(0,sre.EmacspeakRules.defineRule_)("multiline","emacspeak.default",'[t] "multiline equation";[m] children/* (ctxtFunc:CTXFnodeCounter,context:"line",pause:100)',"self::multiline");(0,sre.EmacspeakRules.defineRule_)("line","emacspeak.default","[m] children/*","self::line");(0,sre.EmacspeakRules.defineRule_)("table",
-"emacspeak.default",'[t] "multiline equation";[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:200)',"self::table");(0,sre.EmacspeakRules.defineRule_)("table-row","emacspeak.default","[m] children/* (pause:100)",'self::row[@role="table"]');(0,sre.EmacspeakRules.defineRuleAlias_)("cases-cell",'self::cell[@role="table"]');(0,sre.EmacspeakRules.defineRule_)("end-punct","emacspeak.default","[m] children/*; [p] (pause:300)","self::punctuated",'@role="endpunct"');(0,sre.EmacspeakRules.defineRule_)("start-punct",
-"emacspeak.default","[n] content/*[1]; [p] (pause:200); [m] children/*[position()>1]","self::punctuated",'@role="startpunct"');(0,sre.EmacspeakRules.defineRule_)("integral-punct","emacspeak.default","[n] children/*[1] (rate:0.2); [n] children/*[3] (rate:0.2)","self::punctuated",'@role="integral"');(0,sre.EmacspeakRules.defineRule_)("punctuated","emacspeak.default","[m] children/* (pause:100)","self::punctuated");(0,sre.EmacspeakRules.defineRule_)("function","emacspeak.default","[n] text()","self::function");
-(0,sre.EmacspeakRules.defineRule_)("appl","emacspeak.default","[n] children/*[1]; [n] content/*[1]; [n] children/*[2]","self::appl");(0,sre.EmacspeakRules.defineRule_)("sum-only","emacspeak.default",'[n] children/*[1]; [t] "from"; [n] children/*[2]; [t] "to";[n] children/*[3]',"self::limboth",'@role="sum" or @role="integral"');(0,sre.EmacspeakRules.defineRule_)("limboth","emacspeak.default",'[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];[t] "under"; [n] children/*[3]; [p] (pause 250);',
-"self::limboth");(0,sre.EmacspeakRules.defineRule_)("limlower","emacspeak.default",'[n] children/*[1]; [t] "over"; [n] children/*[2];',"self::limlower");(0,sre.EmacspeakRules.defineRule_)("limupper","emacspeak.default",'[n] children/*[1]; [t] "under"; [n] children/*[2];',"self::limupper");(0,sre.EmacspeakRules.defineRule_)("largeop","emacspeak.default","[n] text()","self::largeop");(0,sre.EmacspeakRules.defineRule_)("bigop","emacspeak.default",'[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];[p] (pause 250);',
-"self::bigop");(0,sre.EmacspeakRules.defineRule_)("integral","emacspeak.default","[n] children/*[1]; [p] (pause 100); [n] children/*[2];[p] (pause 200); [n] children/*[3] (rate:0.35);","self::integral");(0,sre.EmacspeakRules.defineRule_)("sqrt","emacspeak.default",'[t] "Square root of"; [n] children/*[1] (rate:0.35); [p] (pause:400)',"self::sqrt");(0,sre.EmacspeakRules.defineRule_)("square","emacspeak.default",'[n] children/*[1]; [t] "squared" (pitch:0.35); [p] (pause:200)',"self::superscript","children/*[2][text()=2]",
-'name(./children/*[1])!="text"');(0,sre.EmacspeakRules.defineRule_)("cube","emacspeak.default",'[n] children/*[1]; [t] "cubed" (pitch:0.35); [p] (pause:200)',"self::superscript","children/*[2][text()=3]",'name(./children/*[1])!="text"');(0,sre.EmacspeakRules.defineRule_)("root","emacspeak.default",'[t] "root of order"; [n] children/*[1];[t] "over"; [n] children/*[1] (rate:0.35); [p] (pause:400)',"self::root");(0,sre.EmacspeakRules.defineRule_)("text-no-mult","emacspeak.default","[n] children/*[1]; [p] (pause:200); [n] children/*[2]",
-"self::infixop","children/text");(0,sre.EmacspeakRules.defineRule_)("text","emacspeak.default","[n] text(); [p] (pause:200)","self::text");(0,sre.EmacspeakRules.defineRule_)("unit","emacspeak.default","[t] text() (annotation:unit, preprocess)","self::identifier",'@role="unit"');(0,sre.EmacspeakRules.defineRule_)("unit-square","emacspeak.default",'[t] "square"; [n] children/*[1]',"self::superscript",'@role="unit"',"children/*[2][text()=2]",'name(children/*[1])="identifier"');(0,sre.EmacspeakRules.defineRule_)("unit-cubic",
-"emacspeak.default",'[t] "cubic"; [n] children/*[1]',"self::superscript",'@role="unit"',"children/*[2][text()=3]",'name(children/*[1])="identifier"');(0,sre.EmacspeakRules.defineRule_)("reciprocal","emacspeak.default",'[t] "reciprocal"; [n] children/*[1]',"self::superscript",'@role="unit"','name(children/*[1])="identifier"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]',"children/*[2]/children/*[1][text()=1]",'count(preceding-sibling::*)=0 or preceding-sibling::*[@role!="unit"]');
-(0,sre.EmacspeakRules.defineRule_)("reciprocal","emacspeak.default",'[t] "per"; [n] children/*[1]',"self::superscript",'@role="unit"','name(children/*[1])="identifier"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]',"children/*[2]/children/*[1][text()=1]",'preceding-sibling::*[@role="unit"]');(0,sre.EmacspeakRules.defineRule_)("unit-combine","emacspeak.default","[m] children/*","self::infixop",'@role="unit"');(0,sre.EmacspeakRules.defineRule_)("unit-divide","emacspeak.default",
-'[n] children/*[1] (pitch:0.3); [t] "per"; [n] children/*[2] (pitch:-0.3)',"self::fraction",'@role="unit"')};sre.EmacspeakRules.getInstance().initializer=[sre.EmacspeakRules.initCustomFunctions_,sre.EmacspeakRules.initSemanticRules_];sre.MathmlStore=function(){sre.MathStore.call(this)};goog.inherits(sre.MathmlStore,sre.MathStore);goog.addSingletonGetter(sre.MathmlStore);sre.MathmlStore.prototype.defineMathmlRule=function(a,b,c){this.defineRule(a,b,c,"self::mathml:"+a)};sre.MathmlStore.prototype.defineDefaultMathmlRule=function(a,b){this.defineRule(a,"default.default",b,"self::mathml:"+a)};sre.MathmlStoreRules=function(){sre.MathmlStore.call(this)};goog.inherits(sre.MathmlStoreRules,sre.MathmlStore);goog.addSingletonGetter(sre.MathmlStoreRules);sre.MathmlStoreRules.mathStore=sre.MathmlStoreRules.getInstance();sre.MathmlStoreRules.defineDefaultMathmlRule_=goog.bind(sre.MathmlStoreRules.mathStore.defineDefaultMathmlRule,sre.MathmlStoreRules.mathStore);sre.MathmlStoreRules.defineRule_=goog.bind(sre.MathmlStoreRules.mathStore.defineRule,sre.MathmlStoreRules.mathStore);
-sre.MathmlStoreRules.defineRuleAlias_=goog.bind(sre.MathmlStoreRules.mathStore.defineRuleAlias,sre.MathmlStoreRules.mathStore);sre.MathmlStoreRules.addContextFunction_=goog.bind(sre.MathmlStoreRules.mathStore.contextFunctions.add,sre.MathmlStoreRules.mathStore.contextFunctions);sre.MathmlStoreRules.addCustomQuery_=goog.bind(sre.MathmlStoreRules.mathStore.customQueries.add,sre.MathmlStoreRules.mathStore.customQueries);
-sre.MathmlStoreRules.initCustomFunctions_=function(){(0,sre.MathmlStoreRules.addContextFunction_)("CTXFnodeCounter",sre.StoreUtil.nodeCounter);(0,sre.MathmlStoreRules.addContextFunction_)("CTXFmfSeparators",sre.MathmlStoreUtil.mfencedSeparators);(0,sre.MathmlStoreRules.addCustomQuery_)("CQFextender",sre.MathmlStoreUtil.retrieveMathjaxExtender);(0,sre.MathmlStoreRules.addCustomQuery_)("CQFmathmlmunder",sre.MathmlStoreUtil.checkMathjaxMunder);(0,sre.MathmlStoreRules.addCustomQuery_)("CQFmathmlmover",
-sre.MathmlStoreUtil.checkMathjaxMover);(0,sre.MathmlStoreRules.addCustomQuery_)("CQFmathmlmsub",sre.MathmlStoreUtil.checkMathjaxMsub);(0,sre.MathmlStoreRules.addCustomQuery_)("CQFmathmlmsup",sre.MathmlStoreUtil.checkMathjaxMsup);(0,sre.MathmlStoreRules.addCustomQuery_)("CQFlookupleaf",sre.MathmlStoreUtil.retrieveMathjaxLeaf)};
-sre.MathmlStoreRules.initDefaultRules_=function(){(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("math","[m] ./*");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("semantics","[n] ./*[1]");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mspace","[p] (pause:250)");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mstyle","[m] ./*");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mpadded","[m] ./*");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("merror","[m] ./*");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mphantom",
-"[m] ./*");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mtext","[t] text(); [p] (pause:200)");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mi","[n] text()");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mo","[n] text() (rate:-0.1)");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mn","[n] text()");(0,sre.MathmlStoreRules.defineRule_)("mtext-variant","default.default",'[t] "begin"; [t] @mathvariant (pause:150);[t] text() (pause:150); [t] "end"; [t] @mathvariant (pause:200)',"self::mathml:mtext",
-"@mathvariant",'@mathvariant!="normal"');(0,sre.MathmlStoreRules.defineRule_)("mi-variant","default.default","[t] @mathvariant; [n] text()","self::mathml:mi","@mathvariant",'@mathvariant!="normal"');(0,sre.MathmlStoreRules.defineRuleAlias_)("mi-variant","self::mathml:mn","@mathvariant",'@mathvariant!="normal"');(0,sre.MathmlStoreRules.defineRule_)("mo-variant","default.default","[t] @mathvariant; [n] text() (rate:-0.1)","self::mathml:mo","@mathvariant",'@mathvariant!="normal"');(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("ms",
-'[t] "string" (pitch:0.5, rate:0.5); [t] text()');(0,sre.MathmlStoreRules.defineRule_)("unit","default.default",'[t] text() (grammar:annotation="unit":translate)',"self::mathml:mi",'@class="MathML-Unit"');(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("msup",'[n] ./*[1]; [t] "super";[n] ./*[2] (pitch:0.35); [p] (pause:300)');(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("msubsup",'[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);[t] "super"; [n] ./*[3] (pitch:0.35); [p] (pause:300)');
-(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("msub",'[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:300)');(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mover",'[n] ./*[2] (pitch:0.35); [p] (pause:200); [t] "over"; [n] ./*[1]; [p] (pause:400)');(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("munder",'[n] ./*[2] (pitch:-0.35); [t] "under"; [n] ./*[1]; [p] (pause:400)');(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("munderover",'[n] ./*[2] (pitch:-0.35); [t] "under and"; [n] ./*[3] (pitch:0.35); [t] "over"; [n] ./*[1]; [p] (pause:400)');
-(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mrow","[m] ./*");(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("msqrt",'[t] "Square root of"; [m] ./* (rate:0.2); [p] (pause:400)');(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mroot",'[t] "root of order"; [n] ./*[2]; [t] "of";[n] ./*[1] (rate:0.2); [p] (pause:400)');(0,sre.MathmlStoreRules.defineDefaultMathmlRule_)("mfrac",' [p] (pause:400); [n] ./*[1] (pitch:0.3); [t] "divided by"; [n] ./*[2] (pitch:-0.3); [p] (pause:400)');(0,sre.MathmlStoreRules.defineRule_)("mfrac",
-"default.short",'[p] (pause:200); [t] "start frac";[n] ./*[1] (pitch:0.3); [t] "over"; [n] ./*[2] (pitch:-0.3); [p] (pause:400); [t] "end frac"',"self::mathml:mfrac");(0,sre.MathmlStoreRules.defineRule_)("mfenced-single","default.default","[n] @open; [m] ./* (separator:@separators); [n] @close","self::mathml:mfenced","@open","@close","string-length(string(@separators))=1");(0,sre.MathmlStoreRules.defineRule_)("mfenced-single","default.default",'[t] "(" (grammar:translate); [m] ./* (separator:@separators); [n] @close',
-"self::mathml:mfenced","not(@open)","@close","string-length(string(@separators))=1");(0,sre.MathmlStoreRules.defineRule_)("mfenced-single","default.default",'[t] "(" (grammar:translate); [m] ./* (separator:@separators); [t] ")" (grammar:translate)',"self::mathml:mfenced","not(@open)","not(@close)","string-length(string(@separators))=1");(0,sre.MathmlStoreRules.defineRule_)("mfenced-single","default.default",'[n] @open; [m] ./* (separator:@separators); [t] ")" (grammar:translate)',"self::mathml:mfenced",
-"@open","not(@close)","string-length(string(@separators))=1");(0,sre.MathmlStoreRules.defineRule_)("mfenced-omit","default.default","[n] @open; [m] ./*; [n] @close","self::mathml:mfenced","@separators","@open","@close",'string(@separators)="" or string(@separators)=" "');(0,sre.MathmlStoreRules.defineRule_)("mfenced-omit","default.default",'[t] "(" (grammar:translate); [m] ./*; [n] @close',"self::mathml:mfenced","@separators","not(@open)","@close",'string(@separators)="" or string(@separators)=" "');
-(0,sre.MathmlStoreRules.defineRule_)("mfenced-omit","default.default",'[n] @open; [m] ./*; [t] ")" (grammar:translate)',"self::mathml:mfenced","@separators","@open","not(@close)",'string(@separators)="" or string(@separators)=" "');(0,sre.MathmlStoreRules.defineRule_)("mfenced-omit","default.default",'[t] "(" (grammar:translate); [m] ./*; [t] ")" (grammar:translate)',"self::mathml:mfenced","@separators","not(@open)","not(@close)",'string(@separators)="" or string(@separators)=" "');(0,sre.MathmlStoreRules.defineRule_)("mfenced-comma",
-"default.default",'[n] @open; [m] ./* (separator:"comma"); [n] @close',"self::mathml:mfenced","@open","@close","not(@separators)");(0,sre.MathmlStoreRules.defineRule_)("mfenced-comma","default.default",'[t] "(" (grammar:translate); [m] ./* (separator:"comma"); [n] @close',"self::mathml:mfenced","not(@open)","@close","not(@separators)");(0,sre.MathmlStoreRules.defineRule_)("mfenced-comma","default.default",'[n] @open; [m] ./* (separator:"comma"); [t] ")" (grammar:translate)',"self::mathml:mfenced",
-"@open","not(@close)","not(@separators)");(0,sre.MathmlStoreRules.defineRule_)("mfenced-comma","default.default",'[t] "(" (grammar:translate); [m] ./* (separator:"comma"); [t] ")" (grammar:translate)',"self::mathml:mfenced","not(@open)","not(@close)","not(@separators)");(0,sre.MathmlStoreRules.defineRule_)("mfenced-multi","default.default","[n] @open; [m] ./* (sepFunc:CTXFmfSeparators, separator:@separators); [n] @close","self::mathml:mfenced","@open","@close","string-length(string(@separators))>1");
-(0,sre.MathmlStoreRules.defineRule_)("mfenced-multi","default.default",'[t] "(" (grammar:translate); [m] ./* (sepFunc:CTXFmfSeparators, separator:@separators); [n] @close',"self::mathml:mfenced","not(@open)","@close","string-length(string(@separators))>1");(0,sre.MathmlStoreRules.defineRule_)("mfenced-multi","default.default",'[n] @open; [m] ./* (sepFunc:CTXFmfSeparators, separator:@separators); [t] ")" (grammar:translate)',"self::mathml:mfenced","@open","not(@close)","string-length(string(@separators))>1");
-(0,sre.MathmlStoreRules.defineRule_)("mfenced-multi","default.default",'[t] "(" (grammar:translate); [m] ./* (sepFunc:CTXFmfSeparators, separator:@separators); [t] ")" (grammar:translate)',"self::mathml:mfenced","not(@open)","not(@close)","string-length(string(@separators))>1");(0,sre.MathmlStoreRules.defineRule_)("mtable","default.default",'[t] "matrix"; [m] ./* (ctxtFunc:CTXFnodeCounter,context:"row",pause:100)',"self::mathml:mtable");(0,sre.MathmlStoreRules.defineRule_)("mtr","default.default",
-'[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',"self::mathml:mtr");(0,sre.MathmlStoreRules.defineRule_)("mtd","default.default","[m] ./*","self::mathml:mtd");(0,sre.MathmlStoreRules.defineRule_)("mtable","default.superbrief",'[t] count(child::mathml:mtr); [t] "by";[t] count(child::mathml:mtr[1]/mathml:mtd); [t] "matrix";',"self::mathml:mtable");(0,sre.MathmlStoreRules.defineRule_)("mtable","default.short",'[t] "matrix"; [m] ./*',"self::mathml:mtable");(0,sre.MathmlStoreRules.defineRule_)("mtr",
-"default.short","[m] ./*","self::mathml:mtr");(0,sre.MathmlStoreRules.defineRule_)("mtd","default.short",'[t] "Element"; [t] count(./preceding-sibling::mathml:mtd)+1;[t] count(./parent::mathml:mtr/preceding-sibling::mathml:mtr)+1;[p] (pause:500); [m] ./*',"self::mathml:mtd");(0,sre.MathmlStoreRules.defineRule_)("mmultiscripts-4","default.default",'[n] ./*[1]; [p] (pause:200);[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
-"self::mathml:mmultiscripts");(0,sre.MathmlStoreRules.defineRule_)("mmultiscripts-3-1","default.default",'[n] ./*[1]; [p] (pause:200);[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',"self::mathml:mmultiscripts","./mathml:none=./*[2]","./mathml:mprescripts=./*[4]");(0,sre.MathmlStoreRules.defineRule_)("mmultiscripts-3-2","default.default",'[n] ./*[1]; [p] (pause:200);[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);',
-"self::mathml:mmultiscripts","./mathml:none=./*[3]","./mathml:mprescripts=./*[4]");(0,sre.MathmlStoreRules.defineRule_)("mmultiscripts-3-3","default.default",'[n] ./*[1]; [p] (pause:200);[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',"self::mathml:mmultiscripts","./mathml:none=./*[5]","./mathml:mprescripts=./*[4]");(0,sre.MathmlStoreRules.defineRule_)("mmultiscripts-3-4",
-"default.default",'[n] ./*[1]; [p] (pause:200);[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',"self::mathml:mmultiscripts","./mathml:none=./*[6]","./mathml:mprescripts=./*[4]");(0,sre.MathmlStoreRules.defineRule_)("mmultiscripts-2-1","default.default",'[n] ./*[1]; [p] (pause:200);[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:300);',
-"self::mathml:mmultiscripts","./mathml:none=./*[2]","./mathml:none=./*[3]","./mathml:mprescripts=./*[4]");(0,sre.MathmlStoreRules.defineRule_)("mmultiscripts-1-1","default.default",'[n] ./*[1]; [p] (pause:200);[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:300);',"self::mathml:mmultiscripts","./mathml:none=./*[2]","./mathml:none=./*[3]","./mathml:mprescripts=./*[4]","./mathml:none=./*[5]");(0,sre.MathmlStoreRules.defineRule_)("mmultiscripts-1-2","default.default",'[n] ./*[1]; [p] (pause:200);[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);',
-"self::mathml:mmultiscripts","./mathml:none=./*[2]","./mathml:none=./*[3]","./mathml:mprescripts=./*[4]","./mathml:none=./*[6]")};
-sre.MathmlStoreRules.initMathjaxRules_=function(){(0,sre.MathmlStoreRules.defineRule_)("mj-math","default.default","[n] ./*[1]/*[1]/*[1]",'self::span[@class="math"]');(0,sre.MathmlStoreRules.defineRule_)("mj-leaf","default.default","[n] CQFlookupleaf",'self::span[@class="mi"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-leaf",'self::span[@class="mo"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-leaf",'self::span[@class="mn"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-leaf",'self::span[@class="mtext"]');
-(0,sre.MathmlStoreRules.defineRule_)("mj-mo-ext","default.default","[n] CQFextender",'self::span[@class="mo"]',"./*[1]/*[1]/text()","./*[1]/*[2]/text()");(0,sre.MathmlStoreRules.defineRule_)("mj-texatom","default.default","[n] ./*[1]",'self::span[@class="texatom"]');(0,sre.MathmlStoreRules.defineRule_)("mj-msubsup","default.default",'[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35);[p] (pause:200); [t] "super"; [n] ./*[1]/*[2]/*[1] (pitch:0.35);[p] (pause:300)','self::span[@class="msubsup"]');
-(0,sre.MathmlStoreRules.defineRule_)("mj-msub","default.default",'[n] ./*[1]/*[1]/*[1]; [t] "sub";[n] ./*[1]/*[2]/*[1] (pitch:-0.35); [p] (pause:300)','self::span[@class="msub"]');(0,sre.MathmlStoreRules.defineRule_)("mj-msup","default.default",'[n] ./*[1]/*[1]/*[1]; [t] "super";[n] ./*[1]/*[2]/*[1] (pitch:0.35); [p] (pause:300)','self::span[@class="msup"]');(0,sre.MathmlStoreRules.defineRule_)("mj-munderover","default.default",'[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "under and";[n] ./*[1]/*[3]/*[1] (pitch:-0.35); [t] "over";[n] ./*[1]/*[1]/*[1]; [p] (pause:400)',
-'self::span[@class="munderover"]');(0,sre.MathmlStoreRules.defineRule_)("mj-munder","default.default",'[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "under";[n] ./*[1]/*[1]/*[1]; [p] (pause:400)','self::span[@class="munder"]');(0,sre.MathmlStoreRules.defineRule_)("mj-mover","default.default",'[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "over";[n] ./*[1]/*[1]/*[1]; [p] (pause:400)','self::span[@class="mover"]');(0,sre.MathmlStoreRules.defineRule_)("mj-mfrac","default.default",'[p] (pause:250); [n] ./*[1]/*[1]/*[1] (pitch:0.3); [p] (pause:250); [t] "divided by"; [n] ./*[1]/*[2]/*[1] (pitch:-0.3);[p] (pause:400)',
-'self::span[@class="mfrac"]');(0,sre.MathmlStoreRules.defineRule_)("mj-msqrt","default.default",'[t] "Square root of";[n] ./*[1]/*[1]/*[1] (rate:0.2); [p] (pause:400)','self::span[@class="msqrt"]');(0,sre.MathmlStoreRules.defineRule_)("mj-mroot","default.default",'[t] "root of order"; [n] ./*[1]/*[4]/*[1]; [t] "of";[n] ./*[1]/*[1]/*[1] (rate:0.2); [p] (pause:400)','self::span[@class="mroot"]');(0,sre.MathmlStoreRules.defineRule_)("mj-mfenced","default.default",'[t] "opening"; [n] ./*[1]; [m] ./*[position()>1 and position()<last()]; [t] "closing"; [n] ./*[last()]',
-'self::span[@class="mfenced"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-leaf",'self::span[@class="mtable"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-leaf",'self::span[@class="mmultiscripts"]')};
-sre.MathmlStoreRules.initAliases_=function(){(0,sre.MathmlStoreRules.defineRuleAlias_)("mspace",'self::span[@class="mspace"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mstyle",'self::span[@class="mstyle"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mpadded",'self::span[@class="mpadded"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("merror",'self::span[@class="merror"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mphantom",'self::span[@class="mphantom"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("ms",
-'self::span[@class="ms"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mrow",'self::span[@class="mrow"]');(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-msub",'self::span[@class="msubsup"]',"CQFmathmlmsub");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-msup",'self::span[@class="msubsup"]',"CQFmathmlmsup");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-munder",'self::span[@class="munderover"]',"CQFmathmlmunder");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-mover",'self::span[@class="munderover"]',"CQFmathmlmover")};
-sre.MathmlStoreRules.initSpecializationRules_=function(){(0,sre.MathmlStoreRules.defineRule_)("square","default.default",'[n] ./*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',"self::mathml:msup","./*[2][text()=2]");(0,sre.MathmlStoreRules.defineRuleAlias_)("square","self::mathml:msup","./mathml:mrow=./*[2]","count(./*[2]/*)=1","./*[2]/*[1][text()=2]");(0,sre.MathmlStoreRules.defineRule_)("cube","default.default",'[n] ./*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)',"self::mathml:msup","./*[2][text()=3]");
-(0,sre.MathmlStoreRules.defineRuleAlias_)("cube","self::mathml:msup","./mathml:mrow=./*[2]","count(./*[2]/*)=1","./*[2]/*[1][text()=3]");(0,sre.MathmlStoreRules.defineRule_)("square-sub","default.default",'[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35);[p] (pause:300); [t] "square" (pitch:0.35); [p] (pause:400)',"self::mathml:msubsup","./*[3][text()=2]");(0,sre.MathmlStoreRules.defineRuleAlias_)("square-sub","self::mathml:msubsup","./mathml:mrow=./*[3]","count(./*[3]/*)=1","./*[3]/*[1][text()=2]");
-(0,sre.MathmlStoreRules.defineRule_)("cube-sub","default.default",'[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35);[p] (pause:300); [t] "cube" (pitch:0.35); [p] (pause:400)',"self::mathml:msubsup","./*[3][text()=3]");(0,sre.MathmlStoreRules.defineRuleAlias_)("cube-sub","self::mathml:msubsup","./mathml:mrow=./*[3]","count(./*[3]/*)=1","./*[3]/*[1][text()=3]");(0,sre.MathmlStoreRules.defineRule_)("mj-square","default.default",'[n] ./*[1]/*[1]/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)','self::span[@class="msup"]',
-"./*[1]/*[2]/*[1][text()=2]");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-square",'self::span[@class="msup"]','./*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',"count(./*[1]/*[2]/*[1]/*)=1","./*[1]/*[2]/*[1]/*[1][text()=2]");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-square",'self::span[@class="msubsup"]',"CQFmathmlmsup","./*[1]/*[2]/*[1][text()=2]");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-square",'self::span[@class="msubsup"]',"CQFmathmlmsup",'./*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
-"count(./*[1]/*[2]/*[1]/*)=1","./*[1]/*[2]/*[1]/*[1][text()=2]");(0,sre.MathmlStoreRules.defineRule_)("mj-cube","default.default",'[n] ./*[1]/*[1]/*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)','self::span[@class="msup"]',"./*[1]/*[2]/*[1][text()=3]");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-cube",'self::span[@class="msup"]','./*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',"count(./*[1]/*[2]/*[1]/*)=1","./*[1]/*[2]/*[1]/*[1][text()=3]");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-cube",
-'self::span[@class="msubsup"]',"CQFmathmlmsup","./*[1]/*[2]/*[1][text()=3]");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-cube",'self::span[@class="msubsup"]',"CQFmathmlmsup",'./*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',"count(./*[1]/*[2]/*[1]/*)=1","./*[1]/*[2]/*[1]/*[1][text()=3]");(0,sre.MathmlStoreRules.defineRule_)("mj-square-sub","default.default",'[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35); [p] (pause:300); [t] "square" (pitch:0.35); [p] (pause:400)','self::span[@class="msubsup"]',
-"./*[1]/*[2]/*[1][text()=2]");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-square-sub",'self::span[@class="msubsup"]','./*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',"count(./*[1]/*[2]/*[1]/*)=1","./*[1]/*[2]/*[1]/*[1][text()=2]");(0,sre.MathmlStoreRules.defineRule_)("mj-cube-sub","default.default",'[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35); [p] (pause:300); [t] "cube" (pitch:0.35); [p] (pause:400)','self::span[@class="msubsup"]',"./*[1]/*[2]/*[1][text()=3]");(0,sre.MathmlStoreRules.defineRuleAlias_)("mj-cube-sub",
-'self::span[@class="msubsup"]','./*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',"count(./*[1]/*[2]/*[1]/*)=1","./*[1]/*[2]/*[1]/*[1][text()=3]")};sre.MathmlStoreRules.getInstance().initializer=[sre.MathmlStoreRules.initCustomFunctions_,sre.MathmlStoreRules.initDefaultRules_,sre.MathmlStoreRules.initMathjaxRules_,sre.MathmlStoreRules.initAliases_,sre.MathmlStoreRules.initSpecializationRules_];sre.MathspeakRules=function(){sre.MathStore.call(this)};goog.inherits(sre.MathspeakRules,sre.MathStore);goog.addSingletonGetter(sre.MathspeakRules);sre.MathspeakRules.mathStore=sre.MathspeakRules.getInstance();sre.MathspeakRules.defineRule_=goog.bind(sre.MathspeakRules.mathStore.defineRule,sre.MathspeakRules.mathStore);sre.MathspeakRules.defineRuleAlias_=goog.bind(sre.MathspeakRules.mathStore.defineRulesAlias,sre.MathspeakRules.mathStore);
-sre.MathspeakRules.defineSpecialisedRule_=goog.bind(sre.MathspeakRules.mathStore.defineSpecialisedRule,sre.MathspeakRules.mathStore);sre.MathspeakRules.addContextFunction_=goog.bind(sre.MathspeakRules.mathStore.contextFunctions.add,sre.MathspeakRules.mathStore.contextFunctions);sre.MathspeakRules.addCustomQuery_=goog.bind(sre.MathspeakRules.mathStore.customQueries.add,sre.MathspeakRules.mathStore.customQueries);
-sre.MathspeakRules.addCustomString_=goog.bind(sre.MathspeakRules.mathStore.customStrings.add,sre.MathspeakRules.mathStore.customStrings);
-sre.MathspeakRules.initCustomFunctions_=function(){(0,sre.MathspeakRules.addCustomQuery_)("CQFspaceoutNumber",sre.MathspeakUtil.spaceoutNumber);(0,sre.MathspeakRules.addCustomQuery_)("CQFspaceoutIdentifier",sre.MathspeakUtil.spaceoutIdentifier);(0,sre.MathspeakRules.addCustomString_)("CSFspaceoutText",sre.MathspeakUtil.spaceoutText);(0,sre.MathspeakRules.addCustomString_)("CSFopenFracVerbose",sre.MathspeakUtil.openingFractionVerbose);(0,sre.MathspeakRules.addCustomString_)("CSFcloseFracVerbose",sre.MathspeakUtil.closingFractionVerbose);
-(0,sre.MathspeakRules.addCustomString_)("CSFoverFracVerbose",sre.MathspeakUtil.overFractionVerbose);(0,sre.MathspeakRules.addCustomString_)("CSFopenFracBrief",sre.MathspeakUtil.openingFractionBrief);(0,sre.MathspeakRules.addCustomString_)("CSFcloseFracBrief",sre.MathspeakUtil.closingFractionBrief);(0,sre.MathspeakRules.addCustomString_)("CSFopenFracSbrief",sre.MathspeakUtil.openingFractionSbrief);(0,sre.MathspeakRules.addCustomString_)("CSFcloseFracSbrief",sre.MathspeakUtil.closingFractionSbrief);
-(0,sre.MathspeakRules.addCustomString_)("CSFoverFracSbrief",sre.MathspeakUtil.overFractionSbrief);(0,sre.MathspeakRules.addCustomString_)("CSFvulgarFraction",sre.MathspeakUtil.vulgarFraction);(0,sre.MathspeakRules.addCustomQuery_)("CQFvulgarFractionSmall",sre.MathspeakUtil.isSmallVulgarFraction);(0,sre.MathspeakRules.addCustomString_)("CSFopenRadicalVerbose",sre.MathspeakUtil.openingRadicalVerbose);(0,sre.MathspeakRules.addCustomString_)("CSFcloseRadicalVerbose",sre.MathspeakUtil.closingRadicalVerbose);
-(0,sre.MathspeakRules.addCustomString_)("CSFindexRadicalVerbose",sre.MathspeakUtil.indexRadicalVerbose);(0,sre.MathspeakRules.addCustomString_)("CSFopenRadicalBrief",sre.MathspeakUtil.openingRadicalBrief);(0,sre.MathspeakRules.addCustomString_)("CSFcloseRadicalBrief",sre.MathspeakUtil.closingRadicalBrief);(0,sre.MathspeakRules.addCustomString_)("CSFindexRadicalBrief",sre.MathspeakUtil.indexRadicalBrief);(0,sre.MathspeakRules.addCustomString_)("CSFopenRadicalSbrief",sre.MathspeakUtil.openingRadicalSbrief);
-(0,sre.MathspeakRules.addCustomString_)("CSFindexRadicalSbrief",sre.MathspeakUtil.indexRadicalSbrief);(0,sre.MathspeakRules.addCustomString_)("CSFsuperscriptVerbose",sre.MathspeakUtil.superscriptVerbose);(0,sre.MathspeakRules.addCustomString_)("CSFsuperscriptBrief",sre.MathspeakUtil.superscriptBrief);(0,sre.MathspeakRules.addCustomString_)("CSFsubscriptVerbose",sre.MathspeakUtil.subscriptVerbose);(0,sre.MathspeakRules.addCustomString_)("CSFsubscriptBrief",sre.MathspeakUtil.subscriptBrief);(0,sre.MathspeakRules.addCustomString_)("CSFbaselineVerbose",
-sre.MathspeakUtil.baselineVerbose);(0,sre.MathspeakRules.addCustomString_)("CSFbaselineBrief",sre.MathspeakUtil.baselineBrief);(0,sre.MathspeakRules.addCustomString_)("CSFunderscript",sre.MathspeakUtil.nestedUnderscore);(0,sre.MathspeakRules.addCustomString_)("CSFoverscript",sre.MathspeakUtil.nestedOverscore);(0,sre.MathspeakRules.addContextFunction_)("CTXFordinalCounter",sre.MathspeakUtil.ordinalCounter);(0,sre.MathspeakRules.addContextFunction_)("CTXFcontentIterator",sre.MathmlStoreUtil.contentIterator);
-(0,sre.MathspeakRules.addCustomQuery_)("CQFdetIsSimple",sre.MathspeakUtil.determinantIsSimple);(0,sre.MathspeakRules.addCustomString_)("CSFRemoveParens",sre.MathspeakUtil.removeParens);(0,sre.MathspeakRules.addCustomQuery_)("CQFresetNesting",sre.MathspeakUtil.resetNestingDepth)};
-sre.MathspeakRules.initMathspeakRules_=function(){(0,sre.MathspeakRules.defineRule_)("stree","mathspeak.default","[n] ./*[1]","self::stree","CQFresetNesting");(0,sre.MathspeakRules.defineRule_)("unknown","mathspeak.default","[n] text()","self::unknown");(0,sre.MathspeakRules.defineRule_)("protected","mathspeak.default","[t] text()","self::*",'@role="protected"');(0,sre.MathspeakRules.defineRule_)("omit-empty","mathspeak.default","[p] (pause:100)","self::empty");(0,sre.MathspeakRules.defineRule_)("blank-empty",
-"mathspeak.default",'[t] "Blank"',"self::empty","count(../*)=1",'name(../..)="cell" or name(../..)="line"');(0,sre.MathspeakRules.defineRule_)("font","mathspeak.default","[t] @font (grammar:localFont); [n] . (grammar:ignoreFont=@font)","self::*","@font",'not(contains(@grammar, "ignoreFont"))','@font!="normal"');(0,sre.MathspeakRules.defineRule_)("font-identifier-short","mathspeak.default","[t] @font (grammar:localFont); [n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1",
-"@font",'not(contains(@grammar, "ignoreFont"))','@font="normal"','""=translate(text(), "abcdefghijklmnopqrstuvwxyz\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9", "")','@role!="unit"');(0,sre.MathspeakRules.defineRule_)("font-identifier",
-"mathspeak.default","[t] @font (grammar:localFont); [n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'@font="normal"','not(contains(@grammar, "ignoreFont"))','@role!="unit"');(0,sre.MathspeakRules.defineRule_)("omit-font","mathspeak.default","[n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'not(contains(@grammar, "ignoreFont"))','@font="italic"');(0,sre.MathspeakRules.defineRule_)("german-font","mathspeak.default",'[t] "German"; [n] . (grammar:ignoreFont=@font)',
-"self::*","@font",'not(contains(@grammar, "ignoreFont"))','@font="fraktur"');(0,sre.MathspeakRules.defineRule_)("german-font","mathspeak.default",'[t] "bold German"; [n] . (grammar:ignoreFont=@font)',"self::*","@font",'not(contains(@grammar, "ignoreFont"))','@font="bold-fraktur"');(0,sre.MathspeakRules.defineRule_)("number","mathspeak.default","[n] text()","self::number");(0,sre.MathspeakRules.defineRule_)("mixed-number","mathspeak.default",'[n] children/*[1]; [t] "and"; [n] children/*[2]; ',"self::number",
-'@role="mixed"');(0,sre.MathspeakRules.defineRule_)("number-with-chars","mathspeak.default",'[t] "Number"; [m] CQFspaceoutNumber',"self::number",'"" != translate(text(), "0123456789.,", "")','text() != translate(text(), "0123456789.,", "")');(0,sre.MathspeakRules.defineSpecialisedRule_)("number-with-chars","mathspeak.default","mathspeak.brief",'[t] "Num"; [m] CQFspaceoutNumber');(0,sre.MathspeakRules.defineSpecialisedRule_)("number-with-chars","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("number-as-upper-word",
-"mathspeak.default",'[t] "UpperWord"; [t] CSFspaceoutText',"self::number","string-length(text())>1",'text()=translate(text(), "abcdefghijklmnopqrstuvwxyz\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9", "ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9")','""=translate(text(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9","")');
-(0,sre.MathspeakRules.defineRule_)("number-baseline","mathspeak.default",'[t] "Baseline"; [n] text()',"self::number",'not(contains(@grammar, "ignoreFont"))',"preceding-sibling::identifier",'preceding-sibling::*[1][@role="latinletter" or @role="greekletter" or @role="otherletter"]','parent::*/parent::infixop[@role="implicit"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("number-baseline","mathspeak.default","mathspeak.brief",'[t] "Base"; [n] text()');(0,sre.MathspeakRules.defineSpecialisedRule_)("number-baseline",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("number-baseline-font","mathspeak.default",'[t] "Baseline"; [t] @font; [n] . (grammar:ignoreFont=@font)',"self::number","@font",'not(contains(@grammar, "ignoreFont"))','@font!="normal"',"preceding-sibling::identifier",'preceding-sibling::*[@role="latinletter" or @role="greekletter" or @role="otherletter"]','parent::*/parent::infixop[@role="implicit"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("number-baseline-font","mathspeak.default",
-"mathspeak.brief",'[t] "Base"; [n] text()');(0,sre.MathspeakRules.defineSpecialisedRule_)("number-baseline-font","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("identifier","mathspeak.default","[m] CQFspaceoutIdentifier","self::identifier","string-length(text())>1",'@role!="unit"','@role!="protected"','not(@font) or @font="normal" or contains(@grammar, "ignoreFont")');(0,sre.MathspeakRules.defineRule_)("identifier","mathspeak.default","[n] text()","self::identifier",'@role="protected"');
-(0,sre.MathspeakRules.defineRule_)("negative","mathspeak.default",'[t] "negative"; [n] children/*[1]',"self::prefixop",'@role="negative"',"children/identifier");(0,sre.MathspeakRules.defineRuleAlias_)("negative","self::prefixop",'@role="negative"',"children/number");(0,sre.MathspeakRules.defineRuleAlias_)("negative","self::prefixop",'@role="negative"','children/fraction[@role="vulgar"]');(0,sre.MathspeakRules.defineRule_)("negative","mathspeak.default",'[t] "minus"; [n] children/*[1]',"self::prefixop",
-'@role="negative"');(0,sre.MathspeakRules.defineRule_)("prefix","mathspeak.default","[n] text(); [n] children/*[1]","self::prefixop");(0,sre.MathspeakRules.defineRule_)("postfix","mathspeak.default","[n] children/*[1]; [n] text()","self::postfixop");(0,sre.MathspeakRules.defineRule_)("binary-operation","mathspeak.default","[m] children/* (sepFunc:CTXFcontentIterator);","self::infixop");(0,sre.MathspeakRules.defineRule_)("implicit","mathspeak.default","[m] children/*","self::infixop",'@role="implicit"');
-(0,sre.MathspeakRules.defineRuleAlias_)("implicit","self::infixop",'@role="leftsuper" or @role="leftsub" or @role="rightsuper" or @role="rightsub"');(0,sre.MathspeakRules.defineRule_)("subtraction","mathspeak.default",'[m] children/* (separator:"minus");',"self::infixop",'@role="subtraction"');(0,sre.MathspeakRules.defineRule_)("function-unknown","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::appl");(0,sre.MathspeakRules.defineRule_)("function-prefix","mathspeak.default","[n] children/*[1]; [n] children/*[2]",
-"self::appl",'children/*[1][@role="prefix function"]');(0,sre.MathspeakRules.defineRule_)("fences-open-close","mathspeak.default","[n] content/*[1]; [n] children/*[1]; [n] content/*[2]","self::fenced",'@role="leftright"');(0,sre.MathspeakRules.defineRule_)("fences-neutral","mathspeak.default",'[t] "StartAbsoluteValue"; [n] children/*[1]; [t] "EndAbsoluteValue"',"self::fenced",'@role="neutral"','content/*[1][text()]="|" or content/*[1][text()]="\u2758" or content/*[1][text()]="\uff5c"');(0,sre.MathspeakRules.defineSpecialisedRule_)("fences-neutral",
-"mathspeak.default","mathspeak.sbrief",'[t] "AbsoluteValue"; [n] children/*[1]; [t] "EndAbsoluteValue"');(0,sre.MathspeakRules.defineRule_)("fences-neutral","mathspeak.default","[n] content/*[1]; [n] children/*[1]; [n] content/*[2]","self::fenced",'@role="neutral"');(0,sre.MathspeakRules.defineRule_)("fences-set","mathspeak.default",'[t] "StartSet"; [n] children/*[1]; [t] "EndSet"',"self::fenced",'@role="set empty" or @role="set extended" or @role="set singleton" or @role="set collection"','not(name(../..)="appl")');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("fences-set","mathspeak.default","mathspeak.sbrief",'[t] "Set"; [n] children/*[1]; [t] "EndSet"');(0,sre.MathspeakRules.defineRule_)("text","mathspeak.default","[n] text()","self::text");(0,sre.MathspeakRules.defineRule_)("factorial","mathspeak.default",'[t] "factorial"',"self::punctuation",'text()="!"','name(preceding-sibling::*[1])!="text"');(0,sre.MathspeakRules.defineRule_)("minus","mathspeak.default",'[t] "minus"',"self::operator",'text()="-"');(0,sre.MathspeakRules.defineRule_)("single-prime",
-"mathspeak.default",'[t] "prime"',"self::punctuated",'@role="prime"',"count(children/*)=1");(0,sre.MathspeakRules.defineRule_)("double-prime","mathspeak.default",'[t] "double-prime"',"self::punctuated",'@role="prime"',"count(children/*)=2");(0,sre.MathspeakRules.defineRule_)("triple-prime","mathspeak.default",'[t] "triple-prime"',"self::punctuated",'@role="prime"',"count(children/*)=3");(0,sre.MathspeakRules.defineRule_)("quadruple-prime","mathspeak.default",'[t] "quadruple-prime"',"self::punctuated",
-'@role="prime"',"count(children/*)=4");(0,sre.MathspeakRules.defineRule_)("counted-prime","mathspeak.default",'[t] count(children/*); [t] "prime"',"self::punctuated",'@role="prime"');(0,sre.MathspeakRules.defineRule_)("fraction","mathspeak.default","[t] CSFopenFracVerbose; [n] children/*[1]; [t] CSFoverFracVerbose; [n] children/*[2]; [t] CSFcloseFracVerbose","self::fraction");(0,sre.MathspeakRules.defineRule_)("fraction","mathspeak.brief","[t] CSFopenFracBrief; [n] children/*[1]; [t] CSFoverFracVerbose; [n] children/*[2]; [t] CSFcloseFracBrief",
-"self::fraction");(0,sre.MathspeakRules.defineRule_)("fraction","mathspeak.sbrief","[t] CSFopenFracSbrief; [n] children/*[1]; [t] CSFoverFracSbrief; [n] children/*[2]; [t] CSFcloseFracSbrief","self::fraction");(0,sre.MathspeakRules.defineRule_)("vulgar-fraction","mathspeak.default","[t] CSFvulgarFraction","self::fraction",'@role="vulgar"',"CQFvulgarFractionSmall");(0,sre.MathspeakRules.defineSpecialisedRule_)("vulgar-fraction","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("vulgar-fraction",
-"mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("continued-fraction-outer","mathspeak.default",'[t] "ContinuedFraction"; [n] children/*[1];[t] "Over"; [n] children/*[2]',"self::fraction","not(ancestor::fraction)",'children/*[2]/descendant-or-self::*[@role="ellipsis" and not(following-sibling::*)]');(0,sre.MathspeakRules.defineSpecialisedRule_)("continued-fraction-outer","mathspeak.default","mathspeak.brief",'[t] "ContinuedFrac"; [n] children/*[1];[t] "Over"; [n] children/*[2]');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("continued-fraction-outer","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("continued-fraction-inner","mathspeak.default",'[t] "StartFraction"; [n] children/*[1];[t] "Over"; [n] children/*[2]',"self::fraction","ancestor::fraction",'children/*[2]/descendant-or-self::*[@role="ellipsis" and not(following-sibling::*)]');(0,sre.MathspeakRules.defineSpecialisedRule_)("continued-fraction-inner","mathspeak.default","mathspeak.brief",'[t] "StartFrac"; [n] children/*[1];[t] "Over"; [n] children/*[2]');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("continued-fraction-inner","mathspeak.brief","mathspeak.sbrief",'[t] "Frac"; [n] children/*[1];[t] "Over"; [n] children/*[2]');(0,sre.MathspeakRules.defineRule_)("sqrt","mathspeak.default","[t] CSFopenRadicalVerbose; [n] children/*[1]; [t] CSFcloseRadicalVerbose","self::sqrt");(0,sre.MathspeakRules.defineRule_)("sqrt","mathspeak.brief","[t] CSFopenRadicalBrief; [n] children/*[1]; [t] CSFcloseRadicalBrief","self::sqrt");(0,sre.MathspeakRules.defineRule_)("sqrt",
-"mathspeak.sbrief","[t] CSFopenRadicalSbrief; [n] children/*[1]; [t] CSFcloseRadicalBrief","self::sqrt");(0,sre.MathspeakRules.defineRule_)("root","mathspeak.default","[t] CSFindexRadicalVerbose; [n] children/*[1];[t] CSFopenRadicalVerbose; [n] children/*[2]; [t] CSFcloseRadicalVerbose","self::root");(0,sre.MathspeakRules.defineRule_)("root","mathspeak.brief","[t] CSFindexRadicalBrief; [n] children/*[1];[t] CSFopenRadicalBrief; [n] children/*[2]; [t] CSFcloseRadicalBrief","self::root");(0,sre.MathspeakRules.defineRule_)("root",
-"mathspeak.sbrief","[t] CSFindexRadicalSbrief; [n] children/*[1];[t] CSFopenRadicalSbrief; [n] children/*[2]; [t] CSFcloseRadicalBrief","self::root");(0,sre.MathspeakRules.defineRule_)("limboth","mathspeak.default","[n] children/*[1]; [t] CSFunderscript; [n] children/*[2];[t] CSFoverscript; [n] children/*[3]","self::limboth",'name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakRules.defineRule_)("limlower","mathspeak.default",
-"[n] children/*[1]; [t] CSFunderscript; [n] children/*[2];","self::limlower",'name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakRules.defineRule_)("limupper","mathspeak.default","[n] children/*[1]; [t] CSFoverscript; [n] children/*[2];","self::limupper",'name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakRules.defineRuleAlias_)("limlower",
-"self::underscore",'@role="limit function"','name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakRules.defineRuleAlias_)("limlower","self::underscore",'children/*[2][@role!="underaccent"]','name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakRules.defineRuleAlias_)("limupper","self::overscore",'children/*[2][@role!="overaccent"]',
-'name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakRules.defineRule_)("limboth-end","mathspeak.default",'[n] children/*[1]; [t] CSFunderscript; [n] children/*[2];[t] CSFoverscript; [n] children/*[3]; [t] "Endscripts"',"self::limboth");(0,sre.MathspeakRules.defineRule_)("limlower-end","mathspeak.default",'[n] children/*[1]; [t] CSFunderscript; [n] children/*[2]; [t] "Endscripts"',"self::limlower");(0,sre.MathspeakRules.defineRule_)("limupper-end",
-"mathspeak.default",'[n] children/*[1]; [t] CSFoverscript; [n] children/*[2]; [t] "Endscripts"',"self::limupper");(0,sre.MathspeakRules.defineRuleAlias_)("limlower-end","self::underscore",'@role="limit function"');(0,sre.MathspeakRules.defineRuleAlias_)("limlower-end","self::underscore");(0,sre.MathspeakRules.defineRuleAlias_)("limupper-end","self::overscore");(0,sre.MathspeakRules.defineRule_)("integral","mathspeak.default","[n] children/*[1]; [n] children/*[2]; [n] children/*[3];","self::integral");
-(0,sre.MathspeakRules.defineRule_)("integral","mathspeak.default",'[n] children/*[1]; [t] "Subscript"; [n] children/*[2];[t] "Superscript"; [n] children/*[3]; [t] "Baseline";',"self::limboth",'@role="integral"');(0,sre.MathspeakRules.defineSpecialisedRule_)("integral","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "Sub"; [n] children/*[2];[t] "Sup"; [n] children/*[3]; [t] "Base";');(0,sre.MathspeakRules.defineSpecialisedRule_)("integral","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("bigop",
-"mathspeak.default","[n] children/*[1]; [n] children/*[2];","self::bigop");(0,sre.MathspeakRules.defineRule_)("relseq","mathspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::relseq");(0,sre.MathspeakRules.defineRule_)("equality","mathspeak.default","[n] children/*[1]; [n] content/*[1]; [n] children/*[2]","self::relseq",'@role="equality"',"count(./children/*)=2");(0,sre.MathspeakRules.defineRule_)("multi-equality","mathspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)",
-"self::relseq",'@role="equality"',"count(./children/*)>2");(0,sre.MathspeakRules.defineRule_)("multrel","mathspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::multirel");(0,sre.MathspeakRules.defineRule_)("subscript","mathspeak.default","[n] children/*[1]; [t] CSFsubscriptVerbose; [n] children/*[2]","self::subscript");(0,sre.MathspeakRules.defineRule_)("subscript","mathspeak.brief","[n] children/*[1]; [t] CSFsubscriptBrief; [n] children/*[2]","self::subscript");(0,sre.MathspeakRules.defineSpecialisedRule_)("subscript",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("subscript-simple","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::subscript",'name(./children/*[1])="identifier"','name(./children/*[2])="number"','./children/*[2][@role!="mixed"]','./children/*[2][@role!="othernumber"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("subscript-simple","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("subscript-simple","mathspeak.default",
-"mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("subscript-baseline","mathspeak.default","[n] children/*[1]; [t] CSFsubscriptVerbose; [n] children/*[2]; [t] CSFbaselineVerbose","self::subscript","following-sibling::*",'not(name(following-sibling::subscript/children/*[1])="empty" or (name(following-sibling::infixop[@role="implicit"]/children/*[1])="subscript" and name(following-sibling::*/children/*[1]/children/*[1])="empty")) and @role!="subsup"','not(following-sibling::*[@role="rightsuper" or @role="rightsub" or @role="leftsub" or @role="leftsub"])');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("subscript-baseline","mathspeak.default","mathspeak.brief","[n] children/*[1]; [t] CSFsubscriptBrief; [n] children/*[2]; [t] CSFbaselineBrief");(0,sre.MathspeakRules.defineSpecialisedRule_)("subscript-baseline","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRuleAlias_)("subscript-baseline","self::subscript","not(following-sibling::*)","ancestor::fenced|ancestor::root|ancestor::sqrt|ancestor::punctuated|ancestor::fraction",'not(ancestor::punctuated[@role="leftsuper" or @role="rightsub" or @role="rightsuper" or @role="rightsub"])');
-(0,sre.MathspeakRules.defineRuleAlias_)("subscript-baseline","self::subscript","not(following-sibling::*)","ancestor::relseq|ancestor::multirel",sre.MathspeakUtil.generateBaselineConstraint());(0,sre.MathspeakRules.defineRuleAlias_)("subscript-baseline","self::subscript","not(following-sibling::*)","@embellished");(0,sre.MathspeakRules.defineRule_)("subscript-empty-sup","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::subscript",'name(children/*[2])="infixop"','name(children/*[2][@role="implicit"]/children/*[1])="superscript"',
-'name(children/*[2]/children/*[1]/children/*[1])="empty"');(0,sre.MathspeakRules.defineSpecialisedRule_)("subscript-empty-sup","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("subscript-empty-sup","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRuleAlias_)("subscript-empty-sup","self::subscript",'name(children/*[2])="superscript"','name(children/*[2]/children/*[1])="empty"');(0,sre.MathspeakRules.defineRule_)("superscript","mathspeak.default",
-"[n] children/*[1]; [t] CSFsuperscriptVerbose; [n] children/*[2]","self::superscript");(0,sre.MathspeakRules.defineSpecialisedRule_)("superscript","mathspeak.default","mathspeak.brief","[n] children/*[1]; [t] CSFsuperscriptBrief; [n] children/*[2]");(0,sre.MathspeakRules.defineSpecialisedRule_)("superscript","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("superscript-baseline","mathspeak.default","[n] children/*[1]; [t] CSFsuperscriptVerbose; [n] children/*[2];[t] CSFbaselineVerbose",
-"self::superscript","following-sibling::*",'not(name(following-sibling::superscript/children/*[1])="empty" or (name(following-sibling::infixop[@role="implicit"]/children/*[1])="superscript" and name(following-sibling::*/children/*[1]/children/*[1])="empty")) and not(following-sibling::*[@role="rightsuper" or @role="rightsub" or @role="leftsub" or @role="leftsub"])');(0,sre.MathspeakRules.defineSpecialisedRule_)("superscript-baseline","mathspeak.default","mathspeak.brief","[n] children/*[1]; [t] CSFsuperscriptBrief; [n] children/*[2];[t] CSFbaselineBrief");
-(0,sre.MathspeakRules.defineSpecialisedRule_)("superscript-baseline","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRuleAlias_)("superscript-baseline","self::superscript","not(following-sibling::*)","ancestor::punctuated",'ancestor::*/following-sibling::* and not(ancestor::punctuated[@role="leftsuper" or @role="rightsub" or @role="rightsuper" or @role="rightsub"])');(0,sre.MathspeakRules.defineRuleAlias_)("superscript-baseline","self::superscript","not(following-sibling::*)","ancestor::fraction|ancestor::fenced|ancestor::root|ancestor::sqrt");
-(0,sre.MathspeakRules.defineRuleAlias_)("superscript-baseline","self::superscript","not(following-sibling::*)","ancestor::relseq|ancestor::multirel","not(@embellished)",sre.MathspeakUtil.generateBaselineConstraint());(0,sre.MathspeakRules.defineRuleAlias_)("superscript-baseline","self::superscript","not(following-sibling::*)","@embellished",'not(children/*[2][@role="prime"])');(0,sre.MathspeakRules.defineRule_)("superscript-empty-sub","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::superscript",
-'name(children/*[2])="infixop"','name(children/*[2][@role="implicit"]/children/*[1])="subscript"','name(children/*[2]/children/*[1]/children/*[1])="empty"');(0,sre.MathspeakRules.defineSpecialisedRule_)("superscript-empty-sub","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("superscript-empty-sub","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRuleAlias_)("superscript-empty-sub","self::superscript",'name(children/*[2])="subscript"','name(children/*[2]/children/*[1])="empty"');
-(0,sre.MathspeakRules.defineRule_)("square","mathspeak.default",'[n] children/*[1]; [t] "squared"',"self::superscript","children/*[2]","children/*[2][text()=2]",'name(children/*[1])!="text" or not(name(children/*[1])="text" and (name(../../../punctuated[@role="text"]/..)="stree" or name(..)="stree"))','name(children/*[1])!="subscript" or (name(children/*[1])="subscript" and name(children/*[1]/children/*[1])="identifier" and name(children/*[1]/children/*[2])="number" and children/*[1]/children/*[2][@role!="mixed"] and children/*[1]/children/*[2][@role!="othernumber"])',
-"not(@embellished)");(0,sre.MathspeakRules.defineSpecialisedRule_)("square","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("square","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("cube","mathspeak.default",'[n] children/*[1]; [t] "cubed"',"self::superscript","children/*[2]","children/*[2][text()=3]",'name(children/*[1])!="text" or not(name(children/*[1])="text" and (name(../../../punctuated[@role="text"]/..)="stree" or name(..)="stree"))',
-'name(children/*[1])!="subscript" or (name(children/*[1])="subscript" and name(children/*[1]/children/*[1])="identifier" and name(children/*[1]/children/*[2])="number" and children/*[1]/children/*[2][@role!="mixed"] and children/*[1]/children/*[2][@role!="othernumber"])',"not(@embellished)");(0,sre.MathspeakRules.defineSpecialisedRule_)("cube","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("cube","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("prime",
-"mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::superscript","children/*[2]",'children/*[2][@role="prime"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("prime","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("prime","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("prime-subscript","mathspeak.default","[n] children/*[1]/children/*[1]; [n] children/*[2]; [t] CSFsubscriptVerbose; [n] children/*[1]/children/*[2]","self::superscript",
-'children/*[2][@role="prime"]','name(children/*[1])="subscript"',"not(following-sibling::*)");(0,sre.MathspeakRules.defineSpecialisedRule_)("prime-subscript","mathspeak.default","mathspeak.brief","[n] children/*[1]/children/*[1]; [n] children/*[2]; [t] CSFsubscriptBrief; [n] children/*[1]/children/*[2]");(0,sre.MathspeakRules.defineSpecialisedRule_)("prime-subscript","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("prime-subscript-baseline","mathspeak.default","[n] children/*[1]/children/*[1]; [n] children/*[2]; [t] CSFsubscriptVerbose; [n] children/*[1]/children/*[2]; [t] CSFbaselineVerbose",
-"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="subscript"',"following-sibling::*");(0,sre.MathspeakRules.defineSpecialisedRule_)("prime-subscript-baseline","mathspeak.default","mathspeak.brief","[n] children/*[1]/children/*[1]; [n] children/*[2]; [t] CSFsubscriptBrief; [n] children/*[1]/children/*[2]; [t] CSFbaselineBrief");(0,sre.MathspeakRules.defineSpecialisedRule_)("prime-subscript-baseline","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRuleAlias_)("prime-subscript-baseline",
-"self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="subscript"',"not(following-sibling::*)","@embellished");(0,sre.MathspeakRules.defineRule_)("prime-subscript-simple","mathspeak.default","[n] children/*[1]/children/*[1]; [n] children/*[2];[n] children/*[1]/children/*[2]","self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="subscript"','name(children/*[1]/children/*[1])="identifier"','name(children/*[1]/children/*[2])="number"','children/*[1]/children/*[2][@role!="mixed"]',
-'children/*[1]/children/*[2][@role!="othernumber"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("prime-subscript-simple","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("prime-subscript-simple","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("overscore","mathspeak.default",'[t] "ModifyingAbove"; [n] children/*[1]; [t] "With"; [n] children/*[2]',"self::overscore",'children/*[2][@role="overaccent"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("overscore",
-"mathspeak.default","mathspeak.brief",'[t] "ModAbove"; [n] children/*[1]; [t] "With"; [n] children/*[2]');(0,sre.MathspeakRules.defineSpecialisedRule_)("overscore","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("double-overscore","mathspeak.default",'[t] "ModifyingAbove Above"; [n] children/*[1]; [t] "With"; [n] children/*[2]',"self::overscore",'children/*[2][@role="overaccent"]','name(children/*[1])="overscore"','children/*[1]/children/*[2][@role="overaccent"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("double-overscore",
-"mathspeak.default","mathspeak.brief",'[t] "ModAbove Above"; [n] children/*[1]; [t] "With"; [n] children/*[2]');(0,sre.MathspeakRules.defineSpecialisedRule_)("double-overscore","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("underscore","mathspeak.default",'[t] "ModifyingBelow"; [n] children/*[1]; [t] "With"; [n] children/*[2]',"self::underscore",'children/*[2][@role="underaccent"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("underscore","mathspeak.default","mathspeak.brief",
-'[t] "ModBelow"; [n] children/*[1]; [t] "With"; [n] children/*[2]');(0,sre.MathspeakRules.defineSpecialisedRule_)("underscore","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("double-underscore","mathspeak.default",'[t] "ModifyingBelow Below"; [n] children/*[1]; [t] "With"; [n] children/*[2]',"self::underscore",'children/*[2][@role="underaccent"]','name(children/*[1])="underscore"','children/*[1]/children/*[2][@role="underaccent"]');(0,sre.MathspeakRules.defineSpecialisedRule_)("double-underscore",
-"mathspeak.default","mathspeak.brief",'[t] "ModBelow Below"; [n] children/*[1]; [t] "With"; [n] children/*[2]');(0,sre.MathspeakRules.defineSpecialisedRule_)("double-underscore","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("overbar","mathspeak.default",'[n] children/*[1]; [t] "overbar"',"self::overscore",'@role="latinletter" or @role="greekletter" or @role="otherletter"','children/*[2][@role="overaccent"]','children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("overbar","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "overBar"');(0,sre.MathspeakRules.defineSpecialisedRule_)("overbar","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("underbar","mathspeak.default",'[n] children/*[1]; [t] "underbar"',"self::underscore",'@role="latinletter" or @role="greekletter" or @role="otherletter"','children/*[2][@role="underaccent"]','children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("underbar","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "underBar"');(0,sre.MathspeakRules.defineSpecialisedRule_)("underbar","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("overtilde","mathspeak.default",'[n] children/*[1]; [t] "overTilde"',"self::overscore",'children/*[2][@role="overaccent"]','@role="latinletter" or @role="greekletter" or @role="otherletter"','children/*[2][text()="~" or text()="\u02dc" or text()="\u223c" or text()="\uff5e"]');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("overtilde","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "overtilde"');(0,sre.MathspeakRules.defineSpecialisedRule_)("overtilde","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("undertilde","mathspeak.default",'[n] children/*[1]; [t] "underTilde"',"self::underscore",'@role="latinletter" or @role="greekletter" or @role="otherletter"','children/*[2][@role="underaccent"]','children/*[2][text()="~" or text()="\u02dc" or text()="\u223c" or text()="\uff5e"]');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("undertilde","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "undertilde"');(0,sre.MathspeakRules.defineSpecialisedRule_)("undertilde","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("matrix-fence","mathspeak.default","[n] children/*[1];","self::fenced","count(children/*)=1",'name(children/*[1])="matrix"');(0,sre.MathspeakRules.defineRule_)("matrix","mathspeak.default",'[t] "Start"; [t] count(children/*); [t] "By";[t] count(children/*[1]/children/*); [t] "Matrix"; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row "); [t] "EndMatrix"',
-"self::matrix");(0,sre.MathspeakRules.defineRule_)("matrix","mathspeak.sbrief",'[t] count(children/*); [t] "By";[t] count(children/*[1]/children/*); [t] "Matrix"; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row "); [t] "EndMatrix"',"self::matrix");(0,sre.MathspeakRules.defineRuleAlias_)("matrix","self::vector");(0,sre.MathspeakRules.defineRule_)("matrix-row","mathspeak.default",'[m] children/* (ctxtFunc:CTXFordinalCounter,context:"Column");[p] (pause: 200)',"self::row");(0,sre.MathspeakRules.defineRule_)("row-with-label",
-"mathspeak.default",'[t] "with Label"; [n] content/*[1]; [t] "EndLabel"(pause: 200); [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Column")',"self::row","content");(0,sre.MathspeakRules.defineRule_)("row-with-label","mathspeak.brief",'[t] "Label"; [n] content/*[1]; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Column")',"self::row","content");(0,sre.MathspeakRules.defineSpecialisedRule_)("row-with-label","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("row-with-text-label",
-"mathspeak.sbrief",'[t] "Label"; [t] CSFRemoveParens;[m] children/* (ctxtFunc:CTXFordinalCounter,context:"Column")',"self::row","content",'name(content/cell/children/*[1])="text"');(0,sre.MathspeakRules.defineRule_)("empty-row","mathspeak.default",'[t] "Blank"',"self::row","count(children/*)=0");(0,sre.MathspeakRules.defineRule_)("matrix-cell","mathspeak.default","[n] children/*[1]; [p] (pause: 300)","self::cell");(0,sre.MathspeakRules.defineRule_)("empty-cell","mathspeak.default",'[t] "Blank"; [p] (pause: 300)',
-"self::cell","count(children/*)=0");(0,sre.MathspeakRules.defineRule_)("determinant","mathspeak.default",'[t] "Start"; [t] count(children/*); [t] "By";[t] count(children/*[1]/children/*); [t] "Determinant"; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row "); [t] "EndDeterminant"',"self::matrix",'@role="determinant"');(0,sre.MathspeakRules.defineSpecialisedRule_)("determinant","mathspeak.default","mathspeak.sbrief",'[t] count(children/*); [t] "By";[t] count(children/*[1]/children/*); [t] "Determinant"; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row "); [t] "EndDeterminant"');
-(0,sre.MathspeakRules.defineRule_)("determinant-simple","mathspeak.default",'[t] "Start"; [t] count(children/*); [t] "By";[t] count(children/*[1]/children/*); [t] "Determinant"; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row",grammar:simpleDet); [t] "EndDeterminant"',"self::matrix",'@role="determinant"',"CQFdetIsSimple");(0,sre.MathspeakRules.defineSpecialisedRule_)("determinant-simple","mathspeak.default","mathspeak.sbrief",'[t] count(children/*); [t] "By";[t] count(children/*[1]/children/*); [t] "Determinant"; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row",grammar:simpleDet); [t] "EndDeterminant"');
-(0,sre.MathspeakRules.defineRule_)("row-simple","mathspeak.default","[m] children/*;","self::row",'@role="determinant"','contains(@grammar, "simpleDet")');(0,sre.MathspeakRules.defineRule_)("layout","mathspeak.default",'[t] "StartLayout"; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row "); [t] "EndLayout"',"self::table");(0,sre.MathspeakRules.defineRule_)("layout","mathspeak.sbrief",'[t] "Layout"; [m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row "); [t] "EndLayout"',"self::table");
-(0,sre.MathspeakRules.defineRule_)("binomial","mathspeak.default",'[t] "StartBinomialOrMatrix"; [n] children/*[1]/children/*[1]; [t] "Choose"; [n] children/*[2]/children/*[1]; [t] "EndBinomialOrMatrix"',"self::vector",'@role="binomial"');(0,sre.MathspeakRules.defineRule_)("binomial","mathspeak.sbrief",'[t] "BinomialOrMatrix"; [n] children/*[1]/children/*[1]; [t] "Choose"; [n] children/*[2]/children/*[1]; [t] "EndBinomialOrMatrix"',"self::vector",'@role="binomial"');(0,sre.MathspeakRules.defineRule_)("cases",
-"mathspeak.default",'[t] "StartLayout"; [t] "Enlarged"; [n] content/*[1];[m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row "); [t] "EndLayout"',"self::cases");(0,sre.MathspeakRules.defineRule_)("cases","mathspeak.sbrief",'[t] "Layout"; [t] "Enlarged"; [n] content/*[1];[m] children/* (ctxtFunc:CTXFordinalCounter,context:"Row "); [t] "EndLayout"',"self::cases");(0,sre.MathspeakRules.defineRuleAlias_)("layout","self::multiline");(0,sre.MathspeakRules.defineRule_)("line","mathspeak.default","[m] children/*",
-"self::line");(0,sre.MathspeakRules.defineRule_)("line-with-label","mathspeak.default",'[t] "with Label"; [n] content/*[1]; [t] "EndLabel" (pause: 200); [m] children/*',"self::line","content");(0,sre.MathspeakRules.defineSpecialisedRule_)("line-with-label","mathspeak.default","mathspeak.brief",'[t] "Label"; [n] content/*[1] (pause: 200); [m] children/*');(0,sre.MathspeakRules.defineSpecialisedRule_)("line-with-label","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("line-with-text-label",
-"mathspeak.sbrief",'[t] "Label"; [t] CSFRemoveParens; [m] children/*',"self::line","content",'name(content/cell/children/*[1])="text"');(0,sre.MathspeakRules.defineRule_)("empty-line","mathspeak.default",'[t] "Blank"',"self::line","count(children/*)=0","not(content)");(0,sre.MathspeakRules.defineSpecialisedRule_)("empty-line","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("empty-line","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("empty-line-with-label",
-"mathspeak.default",'[t] "with Label"; [n] content/*[1]; [t] "EndLabel"(pause: 200); [t] "Blank"',"self::line","count(children/*)=0","content");(0,sre.MathspeakRules.defineSpecialisedRule_)("empty-line-with-label","mathspeak.default","mathspeak.brief",'[t] "Label"; [n] content/*[1] (pause: 200); [t] "Blank"');(0,sre.MathspeakRules.defineSpecialisedRule_)("empty-line-with-label","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakRules.defineRule_)("enclose","mathspeak.default",'[t] "StartEnclose"; [t] @role (grammar:localEnclose); [n] children/*[1]; [t] "EndEnclose"',
-"self::enclose");(0,sre.MathspeakRules.defineRuleAlias_)("overbar","self::enclose",'@role="top"');(0,sre.MathspeakRules.defineRuleAlias_)("underbar","self::enclose",'@role="bottom"');(0,sre.MathspeakRules.defineRule_)("leftbar","mathspeak.default",'[t] "vertical-bar"; [n] children/*[1]',"self::enclose",'@role="left"');(0,sre.MathspeakRules.defineRule_)("rightbar","mathspeak.default",'[n] children/*[1]; [t] "vertical-bar"',"self::enclose",'@role="right"');(0,sre.MathspeakRules.defineRule_)("crossout",
-"mathspeak.default",'[t] "CrossOut"; [n] children/*[1]; [t] "EndCrossOut"',"self::enclose",'@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"');(0,sre.MathspeakRules.defineRule_)("cancel","mathspeak.default",'[t] "CrossOut"; [n] children/*[1]/children/*[1]; [t] "With"; [n] children/*[2]; [t] "EndCrossOut"',"self::overscore",'@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"');(0,sre.MathspeakRules.defineSpecialisedRule_)("cancel","mathspeak.default",
-"mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("cancel","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakRules.defineRuleAlias_)("cancel","self::underscore",'@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"');(0,sre.MathspeakRules.defineRule_)("cancel-reverse","mathspeak.default",'[t] "CrossOut"; [n] children/*[2]/children/*[1]; [t] "With"; [n] children/*[1]; [t] "EndCrossOut"',"self::overscore",'name(children/*[2])="enclose"','children/*[2][@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"]');
-(0,sre.MathspeakRules.defineSpecialisedRule_)("cancel-reverse","mathspeak.default","mathspeak.brief");(0,sre.MathspeakRules.defineSpecialisedRule_)("cancel-reverse","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakRules.defineRuleAlias_)("cancel-reverse","self::underscore",'name(children/*[2])="enclose"','children/*[2][@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"]');(0,sre.MathspeakRules.defineRule_)("end-punct","mathspeak.default","[m] children/*","self::punctuated",
-'@role="endpunct"');(0,sre.MathspeakRules.defineRule_)("start-punct","mathspeak.default","[n] content/*[1]; [m] children/*[position()>1]","self::punctuated",'@role="startpunct"');(0,sre.MathspeakRules.defineRule_)("integral-punct","mathspeak.default","[n] children/*[1]; [n] children/*[3]","self::punctuated",'@role="integral"');(0,sre.MathspeakRules.defineRule_)("punctuated","mathspeak.default","[m] children/*","self::punctuated");(0,sre.MathspeakRules.defineRule_)("unit","mathspeak.default",'[t] text() (grammar:annotation="unit":translate)',
-"self::identifier",'@role="unit"');(0,sre.MathspeakRules.defineRule_)("unit-square","mathspeak.default",'[t] "square"; [n] children/*[1]',"self::superscript",'@role="unit"',"children/*[2][text()=2]",'name(children/*[1])="identifier"');(0,sre.MathspeakRules.defineRule_)("unit-cubic","mathspeak.default",'[t] "cubic"; [n] children/*[1]',"self::superscript",'@role="unit"',"children/*[2][text()=3]",'name(children/*[1])="identifier"');(0,sre.MathspeakRules.defineRule_)("reciprocal","mathspeak.default",
-'[t] "reciprocal"; [n] children/*[1]',"self::superscript",'@role="unit"','name(children/*[1])="identifier"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]',"children/*[2]/children/*[1][text()=1]",'count(preceding-sibling::*)=0 or preceding-sibling::*[@role!="unit"]');(0,sre.MathspeakRules.defineRule_)("reciprocal","mathspeak.default",'[t] "per"; [n] children/*[1]',"self::superscript",'@role="unit"','name(children/*[1])="identifier"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]',
-"children/*[2]/children/*[1][text()=1]",'preceding-sibling::*[@role="unit"]');(0,sre.MathspeakRules.defineRule_)("unit-combine","mathspeak.default","[m] children/*","self::infixop",'@role="unit"');(0,sre.MathspeakRules.defineRule_)("unit-divide","mathspeak.default",'[n] children/*[1]; [t] "per"; [n] children/*[2]',"self::fraction",'@role="unit"')};sre.MathspeakRules.componentString_={2:"CSFbaseline",1:"CSFsubscript",0:"CSFsuperscript"};sre.MathspeakRules.childNumber_={4:2,3:3,2:1,1:4,0:5};
-sre.MathspeakRules.generateTensorRuleStrings_=function(a){var b=[],c="",d="";a=parseInt(a,2);for(var e=0;5>e;e++){var f="children/*["+sre.MathspeakRules.childNumber_[e]+"]";if(a&1)var g=sre.MathspeakRules.componentString_[e%3],c="[t] "+g+"Verbose; [n] "+f+";"+c,d="[t] "+g+"Brief; [n] "+f+";"+d;else b.unshift("name("+f+')="empty"');a>>=1}b.push(c);b.push(d);return b};
-sre.MathspeakRules.generateMathspeakTensorRules_=function(){for(var a="11111 11110 11101 11100 10111 10110 10101 10100 01111 01110 01101 01100".split(" "),b=0,c;c=a[b];b++){var d="tensor"+c;c=sre.MathspeakRules.generateTensorRuleStrings_(c);var e=c.pop(),f=c.pop(),g=[d,"mathspeak.default",f,"self::tensor"].concat(c),h=[d,"mathspeak.brief",e,"self::tensor"].concat(c);sre.MathspeakRules.defineRule_.apply(null,g);sre.MathspeakRules.defineRule_.apply(null,h);(0,sre.MathspeakRules.defineSpecialisedRule_)(d,
-"mathspeak.brief","mathspeak.sbrief");g=sre.MathspeakRules.componentString_[2];f+="; [t]"+g+"Verbose";e+="; [t]"+g+"Brief";d+="-baseline";g=[d,"mathspeak.default",f,"self::tensor","following-sibling::*"].concat(c);h=[d,"mathspeak.brief",e,"self::tensor","following-sibling::*"].concat(c);sre.MathspeakRules.defineRule_.apply(null,g);sre.MathspeakRules.defineRule_.apply(null,h);(0,sre.MathspeakRules.defineSpecialisedRule_)(d,"mathspeak.brief","mathspeak.sbrief");d=[d,"self::tensor","not(following-sibling::*)",
-"ancestor::fraction|ancestor::punctuated|ancestor::fenced|ancestor::root|ancestor::sqrt|ancestor::relseq|ancestor::multirel|@embellished"].concat(c);sre.MathspeakRules.defineRuleAlias_.apply(null,d)}};sre.MathspeakRules.getInstance().initializer=[sre.MathspeakRules.initCustomFunctions_,sre.MathspeakRules.initMathspeakRules_,sre.MathspeakRules.generateMathspeakTensorRules_];sre.MathspeakSpanishUtil={};sre.MathspeakSpanishUtil.europeanNumber=function(a){return a=a.replace(/,/g,"").replace(/\./g,",")};sre.Grammar.getInstance().setCorrection("euroNum",sre.MathspeakSpanishUtil.europeanNumber);sre.MathspeakSpanishUtil.onesOrdinals="primera segunda tercera cuarta quinta sexta s\u00e9ptima octava novena d\u00e9cima und\u00e9cima duod\u00e9cima".split(" ");sre.MathspeakSpanishUtil.tensOrdinals="d\u00e9cima vig\u00e9sima trig\u00e9sima cuadrag\u00e9sima quincuag\u00e9sima sexag\u00e9sima septuag\u00e9sima octog\u00e9sima nonag\u00e9sima".split(" ");
-sre.MathspeakSpanishUtil.hundredsOrdinals="cent\u00e9sima ducent\u00e9sima tricent\u00e9sima cuadringent\u00e9sima quingent\u00e9sima sexcent\u00e9sima septingent\u00e9sima octingent\u00e9sima noningent\u00e9sima".split(" ");
-sre.MathspeakSpanishUtil.numberToOrdinal=function(a){if(1999<a)return a.toString()+"a";if(12>=a)return sre.MathspeakSpanishUtil.onesOrdinals[a-1];var b=[];1E3<a&&(a-=1E3,b.push("mil\u00e9sima"));var c;c=Math.floor(a/100);0<c&&(b.push(sre.MathspeakSpanishUtil.hundredsOrdinals[c-1]),a%=100);12>=a?b.push(sre.MathspeakSpanishUtil.onesOrdinals[a-1]):(c=Math.floor(a/10),0<c&&(b.push(sre.MathspeakSpanishUtil.tensOrdinals[c-1]),a%=10),0<a&&b.push(sre.MathspeakSpanishUtil.onesOrdinals[a-1]));return b.join(" ")};
-sre.MathspeakSpanishUtil.ordinalCounter=function(a,b){var c=0;return function(){return sre.MathspeakSpanishUtil.numberToOrdinal(++c)+" "+b}};sre.MathspeakSpanishUtil.smallRoot=function(a){if(!a.childNodes||0===a.childNodes.length||!a.childNodes[0].childNodes)return[];var b=a.childNodes[0].childNodes[0].textContent;if(!/^\d+$/.test(b))return[];b=parseInt(b,10);return 1<b&&10>=b?[a]:[]};
-sre.MathspeakSpanishUtil.unitMultipliers=function(a,b){var c=0;return function(){var b=sre.AuditoryDescription.create({text:sre.MathspeakSpanishUtil.rightMostUnit(a[c])&&sre.MathspeakSpanishUtil.leftMostUnit(a[c+1])?"por":""},{});c++;return[b]}};sre.MathspeakSpanishUtil.SCRIPT_ELEMENTS=[sre.SemanticAttr.Type.SUPERSCRIPT,sre.SemanticAttr.Type.SUBSCRIPT,sre.SemanticAttr.Type.OVERSCORE,sre.SemanticAttr.Type.UNDERSCORE];
-sre.MathspeakSpanishUtil.rightMostUnit=function(a){for(;a;){if("unit"===a.getAttribute("role"))return!0;var b=a.tagName;a=sre.XpathUtil.evalXPath("children/*",a);a=-1!==sre.MathspeakSpanishUtil.SCRIPT_ELEMENTS.indexOf(b)?a[0]:a[a.length-1]}return!1};sre.MathspeakSpanishUtil.leftMostUnit=function(a){for(;a;){if("unit"===a.getAttribute("role"))return!0;a=sre.XpathUtil.evalXPath("children/*",a)[0]}return!1};sre.MathspeakSpanishUtil.makePlural=function(a){return/.*s$/.test(a)?a:a+"s"};
-sre.Grammar.getInstance().setCorrection("plural",sre.MathspeakSpanishUtil.makePlural);sre.MathspeakSpanishUtil.oneLeft=function(a){for(;a;){if("number"===a.tagName&&"1"===a.textContent)return[a];if("infixop"!==a.tagName||"multiplication"!==a.getAttribute("role")&&"implicit"!==a.getAttribute("role"))break;a=sre.XpathUtil.evalXPath("children/*",a)[0]}return[]};sre.MathspeakSpanish=function(){sre.MathStore.call(this);this.locale="es"};goog.inherits(sre.MathspeakSpanish,sre.MathStore);goog.addSingletonGetter(sre.MathspeakSpanish);sre.MathspeakSpanish.prototype.evaluateDefault=function(a){return[sre.AuditoryDescription.create({text:a.textContent})]};sre.MathspeakSpanish.SPANISH_REGEXP="a-zA-Z\u00e1\u00e9\u00ed\u00f3\u00fa\u00f1\u00c1\u00c9\u00cd\u00d3\u00da\u00d1";
-sre.MathspeakSpanish.evaluateDefault=function(a){a=a.textContent;for(var b=[],c=new sre.SystemExternal.xmldom.DOMParser,d=new RegExp("^["+sre.MathspeakSpanish.SPANISH_REGEXP+"]+"),e=new RegExp("^[^"+sre.MathspeakSpanish.SPANISH_REGEXP+"]+");a;){var f=d.exec(a);if(f)var g=sre.Semantic.Type.TEXT,h=sre.Semantic.Role.PROTECTED;else f=e.exec(a),g=sre.Semantic.Type.UNKNOWN,h=sre.Semantic.Role.TEXT;g=c.parseFromString("<"+g+' role="'+h+'">'+f[0]+"</"+g+">","text/xml");b.push(g.documentElement);a=a.slice(f[0].length).trimLeft()}return b};
-sre.MathspeakSpanish.mathStore=sre.MathspeakSpanish.getInstance();sre.MathspeakSpanish.defineRule_=goog.bind(sre.MathspeakSpanish.mathStore.defineRule,sre.MathspeakSpanish.mathStore);sre.MathspeakSpanish.defineRuleAlias_=goog.bind(sre.MathspeakSpanish.mathStore.defineRulesAlias,sre.MathspeakSpanish.mathStore);sre.MathspeakSpanish.defineSpecialisedRule_=goog.bind(sre.MathspeakSpanish.mathStore.defineSpecialisedRule,sre.MathspeakSpanish.mathStore);
-sre.MathspeakSpanish.addContextFunction_=goog.bind(sre.MathspeakSpanish.mathStore.contextFunctions.add,sre.MathspeakSpanish.mathStore.contextFunctions);sre.MathspeakSpanish.addCustomQuery_=goog.bind(sre.MathspeakSpanish.mathStore.customQueries.add,sre.MathspeakSpanish.mathStore.customQueries);sre.MathspeakSpanish.addCustomString_=goog.bind(sre.MathspeakSpanish.mathStore.customStrings.add,sre.MathspeakSpanish.mathStore.customStrings);
-sre.MathspeakSpanish.initCustomFunctions_=function(){(0,sre.MathspeakSpanish.addCustomQuery_)("CQFspaceoutNumber",sre.MathspeakUtil.spaceoutNumber);(0,sre.MathspeakSpanish.addCustomQuery_)("CQFspaceoutIdentifier",sre.MathspeakUtil.spaceoutIdentifier);(0,sre.MathspeakSpanish.addCustomString_)("CSFspaceoutText",sre.MathspeakUtil.spaceoutText);(0,sre.MathspeakSpanish.addCustomString_)("CSFopenFracVerbose",sre.MathspeakUtil.openingFractionVerbose);(0,sre.MathspeakSpanish.addCustomString_)("CSFcloseFracVerbose",
-sre.MathspeakUtil.closingFractionVerbose);(0,sre.MathspeakSpanish.addCustomString_)("CSFoverFracVerbose",sre.MathspeakUtil.overFractionVerbose);(0,sre.MathspeakSpanish.addCustomString_)("CSFopenFracBrief",sre.MathspeakUtil.openingFractionBrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFcloseFracBrief",sre.MathspeakUtil.closingFractionBrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFopenFracSbrief",sre.MathspeakUtil.openingFractionSbrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFcloseFracSbrief",
-sre.MathspeakUtil.closingFractionSbrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFoverFracSbrief",sre.MathspeakUtil.overFractionSbrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFopenRadicalVerbose",sre.MathspeakUtil.openingRadicalVerbose);(0,sre.MathspeakSpanish.addCustomString_)("CSFcloseRadicalVerbose",sre.MathspeakUtil.closingRadicalVerbose);(0,sre.MathspeakSpanish.addCustomString_)("CSFindexRadicalVerbose",sre.MathspeakUtil.indexRadicalVerbose);(0,sre.MathspeakSpanish.addCustomString_)("CSFopenRadicalBrief",
-sre.MathspeakUtil.openingRadicalBrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFcloseRadicalBrief",sre.MathspeakUtil.closingRadicalBrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFindexRadicalBrief",sre.MathspeakUtil.indexRadicalBrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFopenRadicalSbrief",sre.MathspeakUtil.openingRadicalSbrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFindexRadicalSbrief",sre.MathspeakUtil.indexRadicalSbrief);(0,sre.MathspeakSpanish.addCustomQuery_)("CQFisSmallRoot",
-sre.MathspeakSpanishUtil.smallRoot);(0,sre.MathspeakSpanish.addCustomString_)("CSFsuperscriptVerbose",sre.MathspeakUtil.superscriptVerbose);(0,sre.MathspeakSpanish.addCustomString_)("CSFsuperscriptBrief",sre.MathspeakUtil.superscriptBrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFsubscriptVerbose",sre.MathspeakUtil.subscriptVerbose);(0,sre.MathspeakSpanish.addCustomString_)("CSFsubscriptBrief",sre.MathspeakUtil.subscriptBrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFbaselineVerbose",sre.MathspeakUtil.baselineVerbose);
-(0,sre.MathspeakSpanish.addCustomString_)("CSFbaselineBrief",sre.MathspeakUtil.baselineBrief);(0,sre.MathspeakSpanish.addCustomString_)("CSFunderscript",sre.MathspeakUtil.nestedUnderscore);(0,sre.MathspeakSpanish.addCustomString_)("CSFoverscript",sre.MathspeakUtil.nestedOverscore);(0,sre.MathspeakSpanish.addContextFunction_)("CTXFordinalCounterEs",sre.MathspeakSpanishUtil.ordinalCounter);(0,sre.MathspeakSpanish.addContextFunction_)("CTXFcontentIterator",sre.MathmlStoreUtil.contentIterator);(0,sre.MathspeakSpanish.addContextFunction_)("CTXFunitMultipliers",
-sre.MathspeakSpanishUtil.unitMultipliers);(0,sre.MathspeakSpanish.addCustomQuery_)("CQFdetIsSimple",sre.MathspeakUtil.determinantIsSimple);(0,sre.MathspeakSpanish.addCustomString_)("CSFRemoveParens",sre.MathspeakUtil.removeParens);(0,sre.MathspeakSpanish.addCustomQuery_)("CQFoneLeft",sre.MathspeakSpanishUtil.oneLeft);(0,sre.MathspeakSpanish.addCustomQuery_)("CQFresetNesting",sre.MathspeakUtil.resetNestingDepth);(0,sre.MathspeakSpanish.addCustomQuery_)("CQFtextEvaluator",sre.MathspeakSpanish.evaluateDefault)};
-sre.MathspeakSpanish.initMathspeakSpanish_=function(){(0,sre.MathspeakSpanish.defineRule_)("stree","mathspeak.default","[n] ./*[1]","self::stree","CQFresetNesting");(0,sre.MathspeakSpanish.defineRule_)("unknown","mathspeak.default","[n] text()","self::unknown");(0,sre.MathspeakSpanish.defineRule_)("protected","mathspeak.default","[t] text()","self::*",'@role="protected"');(0,sre.MathspeakSpanish.defineRule_)("omit-empty","mathspeak.default","[p] (pause:100)","self::empty");(0,sre.MathspeakSpanish.defineRule_)("blank-empty",
-"mathspeak.default",'[t] "espacio"',"self::empty","count(../*)=1",'name(../..)="cell" or name(../..)="line"');(0,sre.MathspeakSpanish.defineRule_)("font","mathspeak.default","[t] @font (grammar:localFont); [n] . (grammar:ignoreFont=@font)","self::*","@font",'not(contains(@grammar, "ignoreFont"))','@font!="normal"');(0,sre.MathspeakSpanish.defineRule_)("font-identifier-short","mathspeak.default","[t] @font (grammar:localFont); [n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1",
-"@font",'not(contains(@grammar, "ignoreFont"))','@font="normal"','""=translate(text(), "abcdefghijklmnopqrstuvwxyz\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9", "")','@role!="unit"');(0,sre.MathspeakSpanish.defineRule_)("font-identifier",
-"mathspeak.default","[t] @font (grammar:localFont); [n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'@font="normal"','not(contains(@grammar, "ignoreFont"))','@role!="unit"');(0,sre.MathspeakSpanish.defineRule_)("omit-font","mathspeak.default","[n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'not(contains(@grammar, "ignoreFont"))','@font="italic"');(0,sre.MathspeakSpanish.defineRule_)("number","mathspeak.default","[n] text() (grammar:euroNum)",
-"self::number");(0,sre.MathspeakSpanish.defineRule_)("mixed-number","mathspeak.default",'[n] children/*[1]; [t] "m\u00e1s"; [n] children/*[2]; ',"self::number",'@role="mixed"');(0,sre.MathspeakSpanish.defineRule_)("number-with-chars","mathspeak.default",'[t] "n\u00famero"; [m] CQFspaceoutNumber',"self::number",'"" != translate(text(), "0123456789.,", "")','text() != translate(text(), "0123456789.,", "")');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("number-with-chars","mathspeak.default","mathspeak.brief",
-'[t] "n\u00fam"; [m] CQFspaceoutNumber');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("number-with-chars","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("number-as-upper-word","mathspeak.default",'[t] "may\u00fascula"; [t] CSFspaceoutText',"self::number","string-length(text())>1",'text()=translate(text(), "abcdefghijklmnopqrstuvwxyz\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9", "ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9")',
-'""=translate(text(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9","")');(0,sre.MathspeakSpanish.defineRule_)("number-baseline","mathspeak.default",'[t] "l\u00ednea base"; [n] text()',"self::number",'not(contains(@grammar, "ignoreFont"))',"preceding-sibling::identifier",'preceding-sibling::*[1][@role="latinletter" or @role="greekletter" or @role="otherletter"]','parent::*/parent::infixop[@role="implicit"]');
-(0,sre.MathspeakSpanish.defineSpecialisedRule_)("number-baseline","mathspeak.default","mathspeak.brief",'[t] "base"; [n] text()');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("number-baseline","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("number-baseline-font","mathspeak.default",'[t] "l\u00ednea base"; [t] @font (grammar:localFont); [n] . (grammar:ignoreFont=@font)',"self::number","@font",'not(contains(@grammar, "ignoreFont"))','@font!="normal"',"preceding-sibling::identifier",
-'preceding-sibling::*[@role="latinletter" or @role="greekletter" or @role="otherletter"]','parent::*/parent::infixop[@role="implicit"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("number-baseline-font","mathspeak.default","mathspeak.brief",'[t] "base"; [n] text()');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("number-baseline-font","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("identifier","mathspeak.default","[m] CQFspaceoutIdentifier","self::identifier","string-length(text())>1",
-'@role!="unit"','@role!="protected"','not(@font) or @font="normal" or contains(@grammar, "ignoreFont")');(0,sre.MathspeakSpanish.defineRule_)("identifier","mathspeak.default","[n] text()","self::identifier",'@role="protected"');(0,sre.MathspeakSpanish.defineRule_)("negative","mathspeak.default",'[t] "menos"; [n] children/*[1]',"self::prefixop",'@role="negative"',"children/identifier");(0,sre.MathspeakSpanish.defineRuleAlias_)("negative","self::prefixop",'@role="negative"',"children/number");(0,sre.MathspeakSpanish.defineRuleAlias_)("negative",
-"self::prefixop",'@role="negative"','children/fraction[@role="vulgar"]');(0,sre.MathspeakSpanish.defineRule_)("negative","mathspeak.default",'[t] "menos"; [n] children/*[1]',"self::prefixop",'@role="negative"');(0,sre.MathspeakSpanish.defineRule_)("prefix","mathspeak.default","[n] text(); [n] children/*[1]","self::prefixop");(0,sre.MathspeakSpanish.defineRule_)("postfix","mathspeak.default","[n] children/*[1]; [n] text()","self::postfixop");(0,sre.MathspeakSpanish.defineRule_)("binary-operation",
-"mathspeak.default","[m] children/* (sepFunc:CTXFcontentIterator);","self::infixop");(0,sre.MathspeakSpanish.defineRule_)("implicit","mathspeak.default","[m] children/*","self::infixop",'@role="implicit"');(0,sre.MathspeakSpanish.defineRuleAlias_)("implicit","self::infixop",'@role="leftsuper" or @role="leftsub" or @role="rightsuper" or @role="rightsub"');(0,sre.MathspeakSpanish.defineRule_)("subtraction","mathspeak.default",'[m] children/* (separator:"menos");',"self::infixop",'@role="subtraction"');
-(0,sre.MathspeakSpanish.defineRule_)("function-unknown","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::appl");(0,sre.MathspeakSpanish.defineRule_)("function-prefix","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::appl",'children/*[1][@role="prefix function"]');(0,sre.MathspeakSpanish.defineRule_)("fences-open-close","mathspeak.default","[n] content/*[1]; [n] children/*[1]; [n] content/*[2]","self::fenced",'@role="leftright"');(0,sre.MathspeakSpanish.defineRule_)("fences-neutral",
-"mathspeak.default",'[t] "empezar valor absoluto"; [n] children/*[1]; [t] "finalizar valor absoluto"',"self::fenced",'@role="neutral"','content/*[1][text()]="|" or content/*[1][text()]="\u2758" or content/*[1][text()]="\uff5c"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("fences-neutral","mathspeak.default","mathspeak.sbrief",'[t] "valor absoluto"; [n] children/*[1]; [t] "finalizar valor absoluto"');(0,sre.MathspeakSpanish.defineRule_)("fences-neutral","mathspeak.default","[n] content/*[1]; [n] children/*[1]; [n] content/*[2]",
-"self::fenced",'@role="neutral"');(0,sre.MathspeakSpanish.defineRule_)("fences-set","mathspeak.default",'[t] "empezar llave"; [n] children/*[1]; [t] "finalizar llave"',"self::fenced",'@role="set empty" or @role="set extended" or @role="set singleton" or @role="set collection"','not(name(../..)="appl")');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("fences-set","mathspeak.default","mathspeak.sbrief",'[t] "llave"; [n] children/*[1]; [t] "finalizar llave"');(0,sre.MathspeakSpanish.defineRule_)("text",
-"mathspeak.default","[m] CQFtextEvaluator","self::text");(0,sre.MathspeakSpanish.defineRule_)("factorial","mathspeak.default",'[t] "factorial"',"self::punctuation",'text()="!"','name(preceding-sibling::*[1])!="text"');(0,sre.MathspeakSpanish.defineRule_)("minus","mathspeak.default",'[t] "menos"',"self::operator",'text()="-"');(0,sre.MathspeakSpanish.defineRule_)("single-prime","mathspeak.default",'[t] "prima"',"self::punctuated",'@role="prime"',"count(children/*)=1");(0,sre.MathspeakSpanish.defineRule_)("double-prime",
-"mathspeak.default",'[t] "doble prima"',"self::punctuated",'@role="prime"',"count(children/*)=2");(0,sre.MathspeakSpanish.defineRule_)("triple-prime","mathspeak.default",'[t] "triple prima"',"self::punctuated",'@role="prime"',"count(children/*)=3");(0,sre.MathspeakSpanish.defineRule_)("quadruple-prime","mathspeak.default",'[t] "cuadruplicar prima"',"self::punctuated",'@role="prime"',"count(children/*)=4");(0,sre.MathspeakSpanish.defineRule_)("counted-prime","mathspeak.default",'[t] count(children/*); [t] "prime"',
-"self::punctuated",'@role="prime"');(0,sre.MathspeakSpanish.defineRule_)("fraction","mathspeak.default","[t] CSFopenFracVerbose; [n] children/*[1]; [t] CSFoverFracVerbose; [n] children/*[2]; [t] CSFcloseFracVerbose","self::fraction");(0,sre.MathspeakSpanish.defineRule_)("fraction","mathspeak.brief","[t] CSFopenFracBrief; [n] children/*[1]; [t] CSFoverFracVerbose; [n] children/*[2]; [t] CSFcloseFracBrief","self::fraction");(0,sre.MathspeakSpanish.defineRule_)("fraction","mathspeak.sbrief","[t] CSFopenFracSbrief; [n] children/*[1]; [t] CSFoverFracSbrief; [n] children/*[2]; [t] CSFcloseFracSbrief",
-"self::fraction");(0,sre.MathspeakSpanish.defineRule_)("continued-fraction-outer","mathspeak.default",'[t] "fracci\u00f3n continua"; [n] children/*[1];[t] "entre"; [n] children/*[2]',"self::fraction","not(ancestor::fraction)",'children/*[2]/descendant-or-self::*[@role="ellipsis" and not(following-sibling::*)]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("continued-fraction-outer","mathspeak.default","mathspeak.brief",'[t] "frac continua"; [n] children/*[1];[t] "entre"; [n] children/*[2]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("continued-fraction-outer",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("continued-fraction-inner","mathspeak.default",'[t] "empezar fracci\u00f3n"; [n] children/*[1];[t] "entre"; [n] children/*[2]',"self::fraction","ancestor::fraction",'children/*[2]/descendant-or-self::*[@role="ellipsis" and not(following-sibling::*)]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("continued-fraction-inner","mathspeak.default","mathspeak.brief",'[t] "empezar frac"; [n] children/*[1];[t] "entre"; [n] children/*[2]');
-(0,sre.MathspeakSpanish.defineSpecialisedRule_)("continued-fraction-inner","mathspeak.brief","mathspeak.sbrief",'[t] "frac"; [n] children/*[1];[t] "entre"; [n] children/*[2]');(0,sre.MathspeakSpanish.defineRule_)("sqrt","mathspeak.default","[t] CSFopenRadicalVerbose; [n] children/*[1]; [t] CSFcloseRadicalVerbose","self::sqrt");(0,sre.MathspeakSpanish.defineRule_)("sqrt","mathspeak.brief","[t] CSFopenRadicalBrief; [n] children/*[1]; [t] CSFcloseRadicalBrief","self::sqrt");(0,sre.MathspeakSpanish.defineRule_)("sqrt",
-"mathspeak.sbrief","[t] CSFopenRadicalSbrief; [n] children/*[1]; [t] CSFcloseRadicalBrief","self::sqrt");(0,sre.MathspeakSpanish.defineRule_)("root-small","mathspeak.default","[t] CSFopenRadicalVerbose; [n] children/*[2]; [t] CSFcloseRadicalVerbose","self::root","CQFisSmallRoot");(0,sre.MathspeakSpanish.defineRule_)("root-small","mathspeak.brief","[t] CSFopenRadicalBrief; [n] children/*[2]; [t] CSFcloseRadicalBrief","self::root","CQFisSmallRoot");(0,sre.MathspeakSpanish.defineRule_)("root-small",
-"mathspeak.sbrief","[t] CSFopenRadicalSbrief; [n] children/*[2]; [t] CSFcloseRadicalBrief","self::root","CQFisSmallRoot");(0,sre.MathspeakSpanish.defineRule_)("root","mathspeak.default","[t] CSFindexRadicalVerbose; [n] children/*[1];[t] CSFopenRadicalVerbose; [n] children/*[2]; [t] CSFcloseRadicalVerbose","self::root");(0,sre.MathspeakSpanish.defineRule_)("root","mathspeak.brief","[t] CSFindexRadicalBrief; [n] children/*[1];[t] CSFopenRadicalBrief; [n] children/*[2]; [t] CSFcloseRadicalBrief","self::root");
-(0,sre.MathspeakSpanish.defineRule_)("root","mathspeak.sbrief","[t] CSFindexRadicalSbrief; [n] children/*[1];[t] CSFopenRadicalSbrief; [n] children/*[2]; [t] CSFcloseRadicalBrief","self::root");(0,sre.MathspeakSpanish.defineRule_)("limboth","mathspeak.default","[n] children/*[1]; [t] CSFunderscript; [n] children/*[2];[t] CSFoverscript; [n] children/*[3]","self::limboth",'name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakSpanish.defineRule_)("limlower",
-"mathspeak.default","[n] children/*[1]; [t] CSFunderscript; [n] children/*[2];","self::limlower",'name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakSpanish.defineRule_)("limupper","mathspeak.default","[n] children/*[1]; [t] CSFoverscript; [n] children/*[2];","self::limupper",'name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakSpanish.defineRuleAlias_)("limlower",
-"self::underscore",'@role="limit function"','name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakSpanish.defineRuleAlias_)("limlower","self::underscore",'children/*[2][@role!="underaccent"]','name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakSpanish.defineRuleAlias_)("limupper","self::overscore",'children/*[2][@role!="overaccent"]',
-'name(../..)="underscore" or name(../..)="overscore"','following-sibling::*[@role!="underaccent" and @role!="overaccent"]');(0,sre.MathspeakSpanish.defineRule_)("limboth-end","mathspeak.default",'[n] children/*[1]; [t] CSFunderscript; [n] children/*[2];[t] CSFoverscript; [n] children/*[3]; [t] "finalizar \u00edndices"',"self::limboth");(0,sre.MathspeakSpanish.defineRule_)("limlower-end","mathspeak.default",'[n] children/*[1]; [t] CSFunderscript; [n] children/*[2]; [t] "finalizar \u00edndices"',"self::limlower");
-(0,sre.MathspeakSpanish.defineRule_)("limupper-end","mathspeak.default",'[n] children/*[1]; [t] CSFoverscript; [n] children/*[2]; [t] "finalizar \u00edndices"',"self::limupper");(0,sre.MathspeakSpanish.defineRuleAlias_)("limlower-end","self::underscore",'@role="limit function"');(0,sre.MathspeakSpanish.defineRuleAlias_)("limlower-end","self::underscore");(0,sre.MathspeakSpanish.defineRuleAlias_)("limupper-end","self::overscore");(0,sre.MathspeakSpanish.defineRule_)("integral","mathspeak.default",
-"[n] children/*[1]; [n] children/*[2]; [n] children/*[3];","self::integral");(0,sre.MathspeakSpanish.defineRule_)("integral","mathspeak.default",'[n] children/*[1]; [t] "definida"; [t] "sub\u00edndice"; [n] children/*[2];[t] "super\u00edndice"; [n] children/*[3]; [t] "l\u00ednea base";',"self::limboth",'@role="integral"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("integral","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "Sub"; [n] children/*[2];[t] "Sup"; [n] children/*[3]; [t] "Base";');
-(0,sre.MathspeakSpanish.defineSpecialisedRule_)("integral","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("bigop","mathspeak.default","[n] children/*[1]; [n] children/*[2];","self::bigop");(0,sre.MathspeakSpanish.defineRule_)("relseq","mathspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::relseq");(0,sre.MathspeakSpanish.defineRule_)("equality","mathspeak.default","[n] children/*[1]; [n] content/*[1]; [n] children/*[2]","self::relseq",'@role="equality"',
-"count(./children/*)=2");(0,sre.MathspeakSpanish.defineRule_)("multi-equality","mathspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::relseq",'@role="equality"',"count(./children/*)>2");(0,sre.MathspeakSpanish.defineRule_)("multrel","mathspeak.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::multirel");(0,sre.MathspeakSpanish.defineRule_)("subscript","mathspeak.default","[n] children/*[1]; [t] CSFsubscriptVerbose; [n] children/*[2]","self::subscript");(0,sre.MathspeakSpanish.defineRule_)("subscript",
-"mathspeak.brief","[n] children/*[1]; [t] CSFsubscriptBrief; [n] children/*[2]","self::subscript");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("subscript","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("subscript-baseline","mathspeak.default","[n] children/*[1]; [t] CSFsubscriptVerbose; [n] children/*[2]; [t] CSFbaselineVerbose","self::subscript","following-sibling::*",'not(name(following-sibling::subscript/children/*[1])="empty" or (name(following-sibling::infixop[@role="implicit"]/children/*[1])="subscript" and name(following-sibling::*/children/*[1]/children/*[1])="empty")) and @role!="subsup"',
-'not(following-sibling::*[@role="rightsuper" or @role="rightsub" or @role="leftsub" or @role="leftsub"])');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("subscript-baseline","mathspeak.default","mathspeak.brief","[n] children/*[1]; [t] CSFsubscriptBrief; [n] children/*[2]; [t] CSFbaselineBriefS");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("subscript-baseline","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRuleAlias_)("subscript-baseline","self::subscript","not(following-sibling::*)",
-"ancestor::fenced|ancestor::root|ancestor::sqrt|ancestor::punctuated|ancestor::fraction",'not(ancestor::punctuated[@role="leftsuper" or @role="rightsub" or @role="rightsuper" or @role="rightsub"])');(0,sre.MathspeakSpanish.defineRuleAlias_)("subscript-baseline","self::subscript","not(following-sibling::*)","ancestor::relseq|ancestor::multirel",sre.MathspeakUtil.generateBaselineConstraint());(0,sre.MathspeakSpanish.defineRuleAlias_)("subscript-baseline","self::subscript","not(following-sibling::*)",
-"@embellished");(0,sre.MathspeakSpanish.defineRule_)("subscript-empty-sup","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::subscript",'name(children/*[2])="infixop"','name(children/*[2][@role="implicit"]/children/*[1])="superscript"','name(children/*[2]/children/*[1]/children/*[1])="empty"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("subscript-empty-sup","mathspeak.default","mathspeak.brief");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("subscript-empty-sup","mathspeak.brief",
-"mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRuleAlias_)("subscript-empty-sup","self::subscript",'name(children/*[2])="superscript"','name(children/*[2]/children/*[1])="empty"');(0,sre.MathspeakSpanish.defineRule_)("superscript","mathspeak.default","[n] children/*[1]; [t] CSFsuperscriptVerbose; [n] children/*[2]","self::superscript");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("superscript","mathspeak.default","mathspeak.brief","[n] children/*[1]; [t] CSFsuperscriptBrief; [n] children/*[2]");
-(0,sre.MathspeakSpanish.defineSpecialisedRule_)("superscript","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("superscript-baseline","mathspeak.default","[n] children/*[1]; [t] CSFsuperscriptVerbose; [n] children/*[2];[t] CSFbaselineVerbose","self::superscript","following-sibling::*",'not(name(following-sibling::superscript/children/*[1])="empty" or (name(following-sibling::infixop[@role="implicit"]/children/*[1])="superscript" and name(following-sibling::*/children/*[1]/children/*[1])="empty")) and not(following-sibling::*[@role="rightsuper" or @role="rightsub" or @role="leftsub" or @role="leftsub"])');
-(0,sre.MathspeakSpanish.defineSpecialisedRule_)("superscript-baseline","mathspeak.default","mathspeak.brief","[n] children/*[1]; [t] CSFsuperscriptBrief; [n] children/*[2];[t] CSFbaselineBriefS");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("superscript-baseline","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRuleAlias_)("superscript-baseline","self::superscript","not(following-sibling::*)","ancestor::punctuated",'ancestor::*/following-sibling::* and not(ancestor::punctuated[@role="leftsuper" or @role="rightsub" or @role="rightsuper" or @role="rightsub"])');
-(0,sre.MathspeakSpanish.defineRuleAlias_)("superscript-baseline","self::superscript","not(following-sibling::*)","ancestor::fraction|ancestor::fenced|ancestor::root|ancestor::sqrt");(0,sre.MathspeakSpanish.defineRuleAlias_)("superscript-baseline","self::superscript","not(following-sibling::*)","ancestor::relseq|ancestor::multirel","not(@embellished)",sre.MathspeakUtil.generateBaselineConstraint());(0,sre.MathspeakSpanish.defineRuleAlias_)("superscript-baseline","self::superscript","not(following-sibling::*)",
-"@embellished",'not(children/*[2][@role="prime"])');(0,sre.MathspeakSpanish.defineRule_)("superscript-empty-sub","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::superscript",'name(children/*[2])="infixop"','name(children/*[2][@role="implicit"]/children/*[1])="subscript"','name(children/*[2]/children/*[1]/children/*[1])="empty"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("superscript-empty-sub","mathspeak.default","mathspeak.brief");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("superscript-empty-sub",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRuleAlias_)("superscript-empty-sub","self::superscript",'name(children/*[2])="subscript"','name(children/*[2]/children/*[1])="empty"');(0,sre.MathspeakSpanish.defineRule_)("square","mathspeak.default",'[n] children/*[1]; [t] "al cuadrado"',"self::superscript","children/*[2]","children/*[2][text()=2]",'name(children/*[1])!="text" or not(name(children/*[1])="text" and (name(../../../punctuated[@role="text"]/..)="stree" or name(..)="stree"))',
-'name(children/*[1])!="subscript" or (name(children/*[1])="subscript" and name(children/*[1]/children/*[1])="identifier" and name(children/*[1]/children/*[2])="number" and children/*[1]/children/*[2][@role!="mixed"] and children/*[1]/children/*[2][@role!="othernumber"])',"not(@embellished)");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("square","mathspeak.default","mathspeak.brief");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("square","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("cube",
-"mathspeak.default",'[n] children/*[1]; [t] "al cubo"',"self::superscript","children/*[2]","children/*[2][text()=3]",'name(children/*[1])!="text" or not(name(children/*[1])="text" and (name(../../../punctuated[@role="text"]/..)="stree" or name(..)="stree"))','name(children/*[1])!="subscript" or (name(children/*[1])="subscript" and name(children/*[1]/children/*[1])="identifier" and name(children/*[1]/children/*[2])="number" and children/*[1]/children/*[2][@role!="mixed"] and children/*[1]/children/*[2][@role!="othernumber"])',
-"not(@embellished)");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("cube","mathspeak.default","mathspeak.brief");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("cube","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("prime","mathspeak.default","[n] children/*[1]; [n] children/*[2]","self::superscript","children/*[2]",'children/*[2][@role="prime"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("prime","mathspeak.default","mathspeak.brief");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("prime",
-"mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("prime-subscript","mathspeak.default","[n] children/*[1]/children/*[1]; [n] children/*[2]; [t] CSFsubscriptVerbose; [n] children/*[1]/children/*[2]","self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="subscript"',"not(following-sibling::*)");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("prime-subscript","mathspeak.default","mathspeak.brief","[n] children/*[1]/children/*[1]; [n] children/*[2]; [t] CSFsubscriptBrief; [n] children/*[1]/children/*[2]");
-(0,sre.MathspeakSpanish.defineSpecialisedRule_)("prime-subscript","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("prime-subscript-baseline","mathspeak.default","[n] children/*[1]/children/*[1]; [n] children/*[2]; [t] CSFsubscriptVerbose; [n] children/*[1]/children/*[2]; [t] CSFbaselineVerbose","self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="subscript"',"following-sibling::*");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("prime-subscript-baseline",
-"mathspeak.default","mathspeak.brief","[n] children/*[1]/children/*[1]; [n] children/*[2]; [t] CSFsubscriptBrief; [n] children/*[1]/children/*[2]; [t] CSFbaselineBriefS");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("prime-subscript-baseline","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRuleAlias_)("prime-subscript-baseline","self::superscript",'children/*[2][@role="prime"]','name(children/*[1])="subscript"',"not(following-sibling::*)","@embellished");(0,sre.MathspeakSpanish.defineRule_)("overscore",
-"mathspeak.default",'[t] "modificando superior"; [n] children/*[1]; [t] "con"; [n] children/*[2]',"self::overscore",'children/*[2][@role="overaccent"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("overscore","mathspeak.default","mathspeak.brief",'[t] "mod superior"; [n] children/*[1]; [t] "con"; [n] children/*[2]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("overscore","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("double-overscore","mathspeak.default",'[t] "modificando superior superior"; [n] children/*[1]; [t] "con"; [n] children/*[2]',
-"self::overscore",'children/*[2][@role="overaccent"]','name(children/*[1])="overscore"','children/*[1]/children/*[2][@role="overaccent"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("double-overscore","mathspeak.default","mathspeak.brief",'[t] "mod superior superior"; [n] children/*[1]; [t] "con"; [n] children/*[2]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("double-overscore","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("underscore","mathspeak.default",'[t] "modificando inferior"; [n] children/*[1]; [t] "con"; [n] children/*[2]',
-"self::underscore",'children/*[2][@role="underaccent"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("underscore","mathspeak.default","mathspeak.brief",'[t] "mod inferior"; [n] children/*[1]; [t] "con"; [n] children/*[2]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("underscore","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("double-underscore","mathspeak.default",'[t] "modificando inferior inferior"; [n] children/*[1]; [t] "con"; [n] children/*[2]',"self::underscore",
-'children/*[2][@role="underaccent"]','name(children/*[1])="underscore"','children/*[1]/children/*[2][@role="underaccent"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("double-underscore","mathspeak.default","mathspeak.brief",'[t] "mod inferior inferior"; [n] children/*[1]; [t] "con"; [n] children/*[2]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("double-underscore","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("overbar","mathspeak.default",'[n] children/*[1]; [t] "barra"',
-"self::overscore",'@role="latinletter" or @role="greekletter" or @role="otherletter"','children/*[2][@role="overaccent"]','children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("overbar","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "barra"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("overbar","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("underbar",
-"mathspeak.default",'[n] children/*[1]; [t] "subbarra"',"self::underscore",'@role="latinletter" or @role="greekletter" or @role="otherletter"','children/*[2][@role="underaccent"]','children/*[2][text()="\u00af" or text()="\uffe3" or text()="\uff3f" or text()="_" or text()="\u203e"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("underbar","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "subbarra"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("underbar","mathspeak.brief","mathspeak.sbrief");
-(0,sre.MathspeakSpanish.defineRule_)("overtilde","mathspeak.default",'[n] children/*[1]; [t] "tilde"',"self::overscore",'children/*[2][@role="overaccent"]','@role="latinletter" or @role="greekletter" or @role="otherletter"','children/*[2][text()="~" or text()="\u02dc" or text()="\u223c" or text()="\uff5e"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("overtilde","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "tilde"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("overtilde",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("undertilde","mathspeak.default",'[n] children/*[1]; [t] "subtilde"',"self::underscore",'@role="latinletter" or @role="greekletter" or @role="otherletter"','children/*[2][@role="underaccent"]','children/*[2][text()="~" or text()="\u02dc" or text()="\u223c" or text()="\uff5e"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("undertilde","mathspeak.default","mathspeak.brief",'[n] children/*[1]; [t] "subtilde"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("undertilde",
-"mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("matrix-fence","mathspeak.default","[n] children/*[1];","self::fenced","count(children/*)=1",'name(children/*[1])="matrix"');(0,sre.MathspeakSpanish.defineRule_)("matrix","mathspeak.default",'[t] "empezar matriz"; [t] count(children/*); [t] "por";[t] count(children/*[1]/children/*); [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila "); [t] "finalizar matriz"',"self::matrix");(0,sre.MathspeakSpanish.defineRule_)("matrix",
-"mathspeak.sbrief",'[t] "matriz"; [t] count(children/*); [t] "por";[t] count(children/*[1]/children/*); [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:" "); [t] "finalizar matriz"',"self::matrix");(0,sre.MathspeakSpanish.defineRuleAlias_)("matrix","self::vector");(0,sre.MathspeakSpanish.defineRule_)("matrix-row","mathspeak.default",'[m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"columna");[p] (pause: 200)',"self::row");(0,sre.MathspeakSpanish.defineRule_)("row-with-label","mathspeak.default",
-'[t] "con etiqueta"; [n] content/*[1]; [t] "finalizar etiqueta" (pause: 200); [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"columna")',"self::row","content");(0,sre.MathspeakSpanish.defineRule_)("row-with-label","mathspeak.brief",'[t] "etiqueta"; [n] content/*[1]; [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"columna")',"self::row","content");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("row-with-label","mathspeak.brief","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("row-with-text-label",
-"mathspeak.sbrief",'[t] "etiqueta"; [t] CSFRemoveParens;[m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"columna")',"self::row","content",'name(content/cell/children/*[1])="text"');(0,sre.MathspeakSpanish.defineRule_)("empty-row","mathspeak.default",'[t] "espacio"',"self::row","count(children/*)=0");(0,sre.MathspeakSpanish.defineRule_)("matrix-cell","mathspeak.default","[n] children/*[1]; [p] (pause: 300)","self::cell");(0,sre.MathspeakSpanish.defineRule_)("empty-cell","mathspeak.default",'[t] "espacio"; [p] (pause: 300)',
-"self::cell","count(children/*)=0");(0,sre.MathspeakSpanish.defineRule_)("determinant","mathspeak.default",'[t] "empezar determinante"; [t] count(children/*); [t] "por";[t] count(children/*[1]/children/*); [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila "); [t] "finalizar determinante"',"self::matrix",'@role="determinant"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("determinant","mathspeak.default","mathspeak.sbrief",'[t] "determinante"; [t] count(children/*); [t] "por";[t] count(children/*[1]/children/*); [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila "); [t] "finalizar determinante"');
-(0,sre.MathspeakSpanish.defineRule_)("determinant-simple","mathspeak.default",'[t] "empezar determinante"; [t] count(children/*); [t] "por";[t] count(children/*[1]/children/*); [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila",grammar:simpleDet); [t] "finalizar determinante"',"self::matrix",'@role="determinant"',"CQFdetIsSimple");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("determinant-simple","mathspeak.default","mathspeak.sbrief",'[t] "determinante"; [t] count(children/*); [t] "por";[t] count(children/*[1]/children/*); [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila",grammar:simpleDet); [t] "finalizar determinante"');
-(0,sre.MathspeakSpanish.defineRule_)("row-simple","mathspeak.default","[m] children/*;","self::row",'@role="determinant"','contains(@grammar, "simpleDet")');(0,sre.MathspeakSpanish.defineRule_)("layout","mathspeak.default",'[t] "empezar esquema"; [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila "); [t] "finalizar esquema"',"self::table");(0,sre.MathspeakSpanish.defineRule_)("layout","mathspeak.sbrief",'[t] "esquema"; [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila "); [t] "finalizar esquema"',
-"self::table");(0,sre.MathspeakSpanish.defineRule_)("binomial","mathspeak.default",'[t] "empezar binomial"; [n] children/*[1]/children/*[1]; [t] "en"; [n] children/*[2]/children/*[1]; [t] "finalizar binomial"',"self::vector",'@role="binomial"');(0,sre.MathspeakSpanish.defineRule_)("binomial","mathspeak.sbrief",'[t] "binomial"; [n] children/*[1]/children/*[1]; [t] "en"; [n] children/*[2]/children/*[1]; [t] "finalizar binomial"',"self::vector",'@role="binomial"');(0,sre.MathspeakSpanish.defineRule_)("cases",
-"mathspeak.default",'[t] "empezar esquema"; [n] content/*[1]; [t] "alargada"; [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila "); [t] "finalizar esquema"',"self::cases");(0,sre.MathspeakSpanish.defineRule_)("cases","mathspeak.sbrief",'[t] "esquema"; [n] content/*[1]; [t] "alargada"; [m] children/* (ctxtFunc:CTXFordinalCounterEs,context:"fila "); [t] "finalizar esquema"',"self::cases");(0,sre.MathspeakSpanish.defineRuleAlias_)("layout","self::multiline");(0,sre.MathspeakSpanish.defineRule_)("line",
-"mathspeak.default","[m] children/*","self::line");(0,sre.MathspeakSpanish.defineRule_)("line-with-label","mathspeak.default",'[t] "con etiqueta"; [n] content/*[1]; [t] "finalizar etiqueta" (pause: 200); [m] children/*',"self::line","content");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("line-with-label","mathspeak.default","mathspeak.brief",'[t] "etiqueta"; [n] content/*[1] (pause: 200); [m] children/*');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("line-with-label","mathspeak.brief","mathspeak.sbrief");
-(0,sre.MathspeakSpanish.defineRule_)("line-with-text-label","mathspeak.sbrief",'[t] "etiqueta"; [t] CSFRemoveParens; [m] children/*',"self::line","content",'name(content/cell/children/*[1])="text"');(0,sre.MathspeakSpanish.defineRule_)("empty-line","mathspeak.default",'[t] "espacio"',"self::line","count(children/*)=0","not(content)");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("empty-line","mathspeak.default","mathspeak.brief");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("empty-line","mathspeak.brief",
-"mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("empty-line-with-label","mathspeak.default",'[t] "con etiqueta"; [n] content/*[1]; [t] "finalizar etiqueta" (pause: 200); [t] "espacio"',"self::line","count(children/*)=0","content");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("empty-line-with-label","mathspeak.default","mathspeak.brief",'[t] "etiqueta"; [n] content/*[1] (pause: 200); [t] "espacio"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("empty-line-with-label","mathspeak.brief",
-"mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRule_)("enclose","mathspeak.default",'[t] "empezar rodear"; [t] @role (grammar:localEnclose); [n] children/*[1]; [t] "finalizar rodear"',"self::enclose");(0,sre.MathspeakSpanish.defineRuleAlias_)("overbar","self::enclose",'@role="top"');(0,sre.MathspeakSpanish.defineRuleAlias_)("underbar","self::enclose",'@role="bottom"');(0,sre.MathspeakSpanish.defineRule_)("leftbar","mathspeak.default",'[t] "barra vertical"; [n] children/*[1]',"self::enclose",'@role="left"');
-(0,sre.MathspeakSpanish.defineRule_)("rightbar","mathspeak.default",'[n] children/*[1]; [t] "barra vertical"',"self::enclose",'@role="right"');(0,sre.MathspeakSpanish.defineRule_)("crossout","mathspeak.default",'[t] "tachado"; [n] children/*[1]; [t] "finalizar tachado"',"self::enclose",'@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"');(0,sre.MathspeakSpanish.defineRule_)("cancel","mathspeak.default",'[t] "tachado"; [n] children/*[1]/children/*[1]; [t] "con"; [n] children/*[2]; [t] "finalizar tachado"',
-"self::overscore",'@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("cancel","mathspeak.default","mathspeak.brief");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("cancel","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRuleAlias_)("cancel","self::underscore",'@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"');(0,sre.MathspeakSpanish.defineRule_)("cancel-reverse",
-"mathspeak.default",'[t] "tachado"; [n] children/*[2]/children/*[1]; [t] "con"; [n] children/*[1]; [t] "finalizar tachado"',"self::overscore",'name(children/*[2])="enclose"','children/*[2][@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"]');(0,sre.MathspeakSpanish.defineSpecialisedRule_)("cancel-reverse","mathspeak.default","mathspeak.brief");(0,sre.MathspeakSpanish.defineSpecialisedRule_)("cancel-reverse","mathspeak.default","mathspeak.sbrief");(0,sre.MathspeakSpanish.defineRuleAlias_)("cancel-reverse",
-"self::underscore",'name(children/*[2])="enclose"','children/*[2][@role="updiagonalstrike" or @role="downdiagonalstrike" or @role="horizontalstrike"]');(0,sre.MathspeakSpanish.defineRule_)("end-punct","mathspeak.default","[m] children/*","self::punctuated",'@role="endpunct"');(0,sre.MathspeakSpanish.defineRule_)("start-punct","mathspeak.default","[n] content/*[1]; [m] children/*[position()>1]","self::punctuated",'@role="startpunct"');(0,sre.MathspeakSpanish.defineRule_)("integral-punct","mathspeak.default",
-"[n] children/*[1]; [n] children/*[3]","self::punctuated",'@role="integral"');(0,sre.MathspeakSpanish.defineRule_)("punctuated","mathspeak.default","[m] children/*","self::punctuated");(0,sre.MathspeakSpanish.defineRule_)("unit","mathspeak.default",'[t] text() (grammar:annotation="unit":translate)',"self::identifier",'@role="unit"');(0,sre.MathspeakSpanish.defineRule_)("unit","mathspeak.default",'[t] text() (grammar:annotation="unit":translate:plural)',"self::identifier",'@role="unit"','not(contains(@grammar, "singularUnit"))');
-(0,sre.MathspeakSpanish.defineRule_)("unit-square","mathspeak.default",'[t] "square"; [n] children/*[1]',"self::superscript",'@role="unit"',"children/*[2][text()=2]",'name(children/*[1])="identifier"');(0,sre.MathspeakSpanish.defineRule_)("unit-cubic","mathspeak.default",'[t] "cubic"; [n] children/*[1]',"self::superscript",'@role="unit"',"children/*[2][text()=3]",'name(children/*[1])="identifier"');(0,sre.MathspeakSpanish.defineRule_)("reciprocal","mathspeak.default",'[t] "reciprocal"; [n] children/*[1]',
-"self::superscript",'@role="unit"','name(children/*[1])="identifier"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]',"children/*[2]/children/*[1][text()=1]",'count(preceding-sibling::*)=0 or preceding-sibling::*[@role!="unit"]');(0,sre.MathspeakSpanish.defineRule_)("reciprocal","mathspeak.default",'[t] "per"; [n] children/*[1]',"self::superscript",'@role="unit"','name(children/*[1])="identifier"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]',"children/*[2]/children/*[1][text()=1]",
-'preceding-sibling::*[@role="unit"]');(0,sre.MathspeakSpanish.defineRule_)("unit-combine","mathspeak.default","[m] children/* (sepFunc:CTXFunitMultipliers)","self::infixop",'@role="unit"');(0,sre.MathspeakSpanish.defineRule_)("unit-combine","mathspeak.default","[m] children/* (sepFunc:CTXFunitMultipliers);","self::infixop",'@role="multiplication" or @role="implicit"','children/*[@role="unit"]');(0,sre.MathspeakSpanish.defineRule_)("unit-combine","mathspeak.default","[n] . (grammar:singularUnit);",
-"self::infixop",'@role="multiplication" or @role="implicit"','children/*[@role="unit"]','not(contains(@grammar, "singularUnit"))',"CQFoneLeft");(0,sre.MathspeakSpanish.defineRule_)("unit-divide","mathspeak.default",'[n] children/*[1]; [t] "per"; [n] children/*[2]',"self::fraction",'@role="unit"')};sre.MathspeakSpanish.componentString_={2:"CSFbaseline",1:"CSFsubscript",0:"CSFsuperscript"};sre.MathspeakSpanish.childNumber_={4:2,3:3,2:1,1:4,0:5};
-sre.MathspeakSpanish.generateTensorRuleStrings_=function(a){var b=[],c="",d="";a=parseInt(a,2);for(var e=0;5>e;e++){var f="children/*["+sre.MathspeakSpanish.childNumber_[e]+"]";if(a&1)var g=sre.MathspeakSpanish.componentString_[e%3],c="[t] "+g+"Verbose; [n] "+f+";"+c,d="[t] "+g+"Brief; [n] "+f+";"+d;else b.unshift("name("+f+')="empty"');a>>=1}b.push(c);b.push(d);return b};
-sre.MathspeakSpanish.generateMathspeakTensorRules_=function(){for(var a="11111 11110 11101 11100 10111 10110 10101 10100 01111 01110 01101 01100".split(" "),b=0,c;c=a[b];b++){var d="tensor"+c;c=sre.MathspeakSpanish.generateTensorRuleStrings_(c);var e=c.pop(),f=c.pop(),g=[d,"mathspeak.default",f,"self::tensor"].concat(c),h=[d,"mathspeak.brief",e,"self::tensor"].concat(c);sre.MathspeakSpanish.defineRule_.apply(null,g);sre.MathspeakSpanish.defineRule_.apply(null,h);(0,sre.MathspeakSpanish.defineSpecialisedRule_)(d,
-"mathspeak.brief","mathspeak.sbrief");g=sre.MathspeakSpanish.componentString_[2];f+="; [t]"+g+"Verbose";e+="; [t]"+g+"Brief";d+="-baseline";g=[d,"mathspeak.default",f,"self::tensor","following-sibling::*"].concat(c);h=[d,"mathspeak.brief",e,"self::tensor","following-sibling::*"].concat(c);sre.MathspeakSpanish.defineRule_.apply(null,g);sre.MathspeakSpanish.defineRule_.apply(null,h);(0,sre.MathspeakSpanish.defineSpecialisedRule_)(d,"mathspeak.brief","mathspeak.sbrief");d=[d,"self::tensor","not(following-sibling::*)",
-"ancestor::fraction|ancestor::punctuated|ancestor::fenced|ancestor::root|ancestor::sqrt|ancestor::relseq|ancestor::multirel|@embellished"].concat(c);sre.MathspeakSpanish.defineRuleAlias_.apply(null,d)}};sre.MathspeakSpanish.getInstance().initializer=[sre.MathspeakSpanish.initCustomFunctions_,sre.MathspeakSpanish.initMathspeakSpanish_,sre.MathspeakSpanish.generateMathspeakTensorRules_];sre.PrefixRules=function(){sre.MathStore.call(this)};goog.inherits(sre.PrefixRules,sre.MathStore);goog.addSingletonGetter(sre.PrefixRules);sre.PrefixRules.mathStore=sre.PrefixRules.getInstance();sre.PrefixRules.defineRule_=goog.bind(sre.PrefixRules.mathStore.defineRule,sre.PrefixRules.mathStore);sre.PrefixRules.defineRuleAlias_=goog.bind(sre.PrefixRules.mathStore.defineRulesAlias,sre.PrefixRules.mathStore);sre.PrefixRules.addCustomString_=goog.bind(sre.PrefixRules.mathStore.customStrings.add,sre.PrefixRules.mathStore.customStrings);
-sre.PrefixRules.ordinalPosition=function(a){var b=sre.DomUtil.toArray(a.parentNode.childNodes);return sre.MathspeakUtil.simpleOrdinal(b.indexOf(a)+1).toString()};sre.PrefixRules.initCustomFunctions_=function(){(0,sre.PrefixRules.addCustomString_)("CSFordinalPosition",sre.PrefixRules.ordinalPosition)};
-sre.PrefixRules.initPrefixRules_=function(){(0,sre.PrefixRules.defineRule_)("numerator","prefix.default",'[t] "Numerator"; [p] (pause:200)',"self::*",'name(../..)="fraction"',"count(preceding-sibling::*)=0");(0,sre.PrefixRules.defineRule_)("denominator","prefix.default",'[t] "Denominator"; [p] (pause:200)',"self::*",'name(../..)="fraction"',"count(preceding-sibling::*)=1");(0,sre.PrefixRules.defineRule_)("base","prefix.default",'[t] "Base"; [p] (pause:200)',"self::*",'name(../..)="superscript" or name(../..)="subscript" or name(../..)="overscore" or name(../..)="underscore" or name(../..)="tensor"',
-"count(preceding-sibling::*)=0");(0,sre.PrefixRules.defineRule_)("exponent","prefix.default",'[t] "Exponent"; [p] (pause:200)',"self::*",'name(../..)="superscript"',"count(preceding-sibling::*)=1");(0,sre.PrefixRules.defineRule_)("subscript","prefix.default",'[t] "Subscript"; [p] (pause:200)',"self::*",'name(../..)="subscript"',"count(preceding-sibling::*)=1");(0,sre.PrefixRules.defineRule_)("overscript","prefix.default",'[t] "Overscript"; [p] (pause:200)',"self::*",'name(../..)="overscore"',"count(preceding-sibling::*)=1");
-(0,sre.PrefixRules.defineRule_)("underscript","prefix.default",'[t] "Underscript"; [p] (pause:200)',"self::*",'name(../..)="underscore"',"count(preceding-sibling::*)=1");(0,sre.PrefixRules.defineRule_)("radicand","prefix.default",'[t] "Radicand"; [p] (pause:200)',"self::*",'name(../..)="sqrt"');(0,sre.PrefixRules.defineRule_)("radicand","prefix.default",'[t] "Radicand"; [p] (pause:200)',"self::*",'name(../..)="root"',"count(preceding-sibling::*)=1");(0,sre.PrefixRules.defineRule_)("index","prefix.default",
-'[t] "Index"; [p] (pause:200)',"self::*",'name(../..)="root"',"count(preceding-sibling::*)=0");(0,sre.PrefixRules.defineRule_)("leftsub","prefix.default",'[t] "Left Subscript"; [p] (pause:200)',"self::*",'name(../..)="tensor"','@role="leftsub"');(0,sre.PrefixRules.defineRule_)("leftsub","prefix.default",'[t] CSFordinalPosition; [t] "Left Subscript"; [p] (pause:200)',"self::*",'name(../..)="punctuated"','name(../../../..)="tensor"','../../@role="leftsub"');(0,sre.PrefixRules.defineRule_)("leftsuper",
-"prefix.default",'[t] "Left Superscript"; [p] (pause:200)',"self::*",'name(../..)="tensor"','@role="leftsuper"');(0,sre.PrefixRules.defineRule_)("leftsuper","prefix.default",'[t] CSFordinalPosition; [t] "Left Superscript"; [p] (pause:200)',"self::*",'name(../..)="punctuated"','name(../../../..)="tensor"','../../@role="leftsuper"');(0,sre.PrefixRules.defineRule_)("rightsub","prefix.default",'[t] "Right Subscript"; [p] (pause:200)',"self::*",'name(../..)="tensor"','@role="rightsub"');(0,sre.PrefixRules.defineRule_)("rightsub",
-"prefix.default",'[t] CSFordinalPosition; [t] "Right Subscript"; [p] (pause:200)',"self::*",'name(../..)="punctuated"','name(../../../..)="tensor"','../../@role="rightsub"');(0,sre.PrefixRules.defineRule_)("rightsuper","prefix.default",'[t] "Right Superscript"; [p] (pause:200)',"self::*",'name(../..)="tensor"','@role="rightsuper"');(0,sre.PrefixRules.defineRule_)("rightsuper","prefix.default",'[t] CSFordinalPosition; [t] "Right Superscript"; [p] (pause:200)',"self::*",'name(../..)="punctuated"','name(../../../..)="tensor"',
-'../../@role="rightsuper"');(0,sre.PrefixRules.defineRule_)("choice","prefix.default",'[t] "Choice Quantity"; [p] (pause:200)',"self::line",'@role="binomial"',"parent::*/parent::vector","count(preceding-sibling::*)=0");(0,sre.PrefixRules.defineRule_)("select","prefix.default",'[t] "Selection Quantity"; [p] (pause:200)',"self::line",'@role="binomial"',"parent::*/parent::vector","count(preceding-sibling::*)=1");(0,sre.PrefixRules.defineRule_)("row","prefix.default",'[t] CSFordinalPosition; [t] "Row"; [p] (pause:200)',
-"self::row");(0,sre.PrefixRules.defineRuleAlias_)("row","self::line");(0,sre.PrefixRules.defineRule_)("cell","prefix.default",'[n] ../..; [t] CSFordinalPosition; [t] "Column"; [p] (pause:200)',"self::cell",'contains(@grammar,"depth")');(0,sre.PrefixRules.defineRule_)("cell","prefix.default",'[t] CSFordinalPosition; [t] "Column"; [p] (pause:200)',"self::cell")};sre.PrefixRules.getInstance().initializer=[sre.PrefixRules.initCustomFunctions_,sre.PrefixRules.initPrefixRules_];sre.PrefixSpanish=function(){sre.MathStore.call(this);this.locale="es"};goog.inherits(sre.PrefixSpanish,sre.MathStore);goog.addSingletonGetter(sre.PrefixSpanish);sre.PrefixSpanish.mathStore=sre.PrefixSpanish.getInstance();sre.PrefixSpanish.defineRule_=goog.bind(sre.PrefixSpanish.mathStore.defineRule,sre.PrefixSpanish.mathStore);sre.PrefixSpanish.defineRuleAlias_=goog.bind(sre.PrefixSpanish.mathStore.defineRulesAlias,sre.PrefixSpanish.mathStore);
-sre.PrefixSpanish.addCustomString_=goog.bind(sre.PrefixSpanish.mathStore.customStrings.add,sre.PrefixSpanish.mathStore.customStrings);sre.PrefixSpanish.ordinalPosition=function(a){var b=sre.DomUtil.toArray(a.parentNode.childNodes);return sre.MathspeakUtil.simpleOrdinal(b.indexOf(a)+1).toString()};sre.PrefixSpanish.initCustomFunctions_=function(){(0,sre.PrefixSpanish.addCustomString_)("CSFordinalPosition",sre.PrefixSpanish.ordinalPosition)};
-sre.PrefixSpanish.initPrefixSpanish_=function(){(0,sre.PrefixSpanish.defineRule_)("numerator","prefix.default",'[t] "numerador"; [p] (pause:200)',"self::*",'name(../..)="fraction"',"count(preceding-sibling::*)=0");(0,sre.PrefixSpanish.defineRule_)("denominator","prefix.default",'[t] "denominador"; [p] (pause:200)',"self::*",'name(../..)="fraction"',"count(preceding-sibling::*)=1");(0,sre.PrefixSpanish.defineRule_)("base","prefix.default",'[t] "base"; [p] (pause:200)',"self::*",'name(../..)="superscript" or name(../..)="subscript" or name(../..)="overscore" or name(../..)="underscore" or name(../..)="tensor"',
-"count(preceding-sibling::*)=0");(0,sre.PrefixSpanish.defineRule_)("exponent","prefix.default",'[t] "exponente"; [p] (pause:200)',"self::*",'name(../..)="superscript"',"count(preceding-sibling::*)=1");(0,sre.PrefixSpanish.defineRule_)("subscript","prefix.default",'[t] "sub\u00edndice"; [p] (pause:200)',"self::*",'name(../..)="subscript"',"count(preceding-sibling::*)=1");(0,sre.PrefixSpanish.defineRule_)("overscript","prefix.default",'[t] "overscript"; [p] (pause:200)',"self::*",'name(../..)="overscore"',
-"count(preceding-sibling::*)=1");(0,sre.PrefixSpanish.defineRule_)("underscript","prefix.default",'[t] "underscript"; [p] (pause:200)',"self::*",'name(../..)="underscore"',"count(preceding-sibling::*)=1");(0,sre.PrefixSpanish.defineRule_)("radicand","prefix.default",'[t] "radicand"; [p] (pause:200)',"self::*",'name(../..)="sqrt"');(0,sre.PrefixSpanish.defineRule_)("radicand","prefix.default",'[t] "radicand"; [p] (pause:200)',"self::*",'name(../..)="root"',"count(preceding-sibling::*)=1");(0,sre.PrefixSpanish.defineRule_)("index",
-"prefix.default",'[t] "\u00edndice"; [p] (pause:200)',"self::*",'name(../..)="root"',"count(preceding-sibling::*)=0");(0,sre.PrefixSpanish.defineRule_)("leftsub","prefix.default",'[t] "sub\u00edndice izquierdo"; [p] (pause:200)',"self::*",'name(../..)="tensor"','@role="leftsub"');(0,sre.PrefixSpanish.defineRule_)("leftsub","prefix.default",'[t] CSFordinalPosition; [t] "sub\u00edndice izquierdo"; [p] (pause:200)',"self::*",'name(../..)="punctuated"','name(../../../..)="tensor"','../../@role="leftsub"');
-(0,sre.PrefixSpanish.defineRule_)("leftsuper","prefix.default",'[t] "super\u00edndice izquierdo"; [p] (pause:200)',"self::*",'name(../..)="tensor"','@role="leftsuper"');(0,sre.PrefixSpanish.defineRule_)("leftsuper","prefix.default",'[t] CSFordinalPosition; [t] "super\u00edndice izquierdo"; [p] (pause:200)',"self::*",'name(../..)="punctuated"','name(../../../..)="tensor"','../../@role="leftsuper"');(0,sre.PrefixSpanish.defineRule_)("rightsub","prefix.default",'[t] "derecha sub\u00edndice"; [p] (pause:200)',
-"self::*",'name(../..)="tensor"','@role="rightsub"');(0,sre.PrefixSpanish.defineRule_)("rightsub","prefix.default",'[t] CSFordinalPosition; [t] "derecha sub\u00edndice"; [p] (pause:200)',"self::*",'name(../..)="punctuated"','name(../../../..)="tensor"','../../@role="rightsub"');(0,sre.PrefixSpanish.defineRule_)("rightsuper","prefix.default",'[t] "super\u00edndice derecho"; [p] (pause:200)',"self::*",'name(../..)="tensor"','@role="rightsuper"');(0,sre.PrefixSpanish.defineRule_)("rightsuper","prefix.default",
-'[t] CSFordinalPosition; [t] "super\u00edndice derecho"; [p] (pause:200)',"self::*",'name(../..)="punctuated"','name(../../../..)="tensor"','../../@role="rightsuper"');(0,sre.PrefixSpanish.defineRule_)("choice","prefix.default",'[t] "cantidad de elecci\u00f3n"; [p] (pause:200)',"self::line",'@role="binomial"',"parent::*/parent::vector","count(preceding-sibling::*)=0");(0,sre.PrefixSpanish.defineRule_)("select","prefix.default",'[t] "cantidad de selecci\u00f3n"; [p] (pause:200)',"self::line",'@role="binomial"',
-"parent::*/parent::vector","count(preceding-sibling::*)=1");(0,sre.PrefixSpanish.defineRule_)("row","prefix.default",'[t] CSFordinalPosition; [t] "fila"; [p] (pause:200)',"self::row");(0,sre.PrefixSpanish.defineRuleAlias_)("row","self::line");(0,sre.PrefixSpanish.defineRule_)("cell","prefix.default",'[n] ../..; [t] CSFordinalPosition; [t] "columna"; [p] (pause:200)',"self::cell",'contains(@grammar,"depth")');(0,sre.PrefixSpanish.defineRule_)("cell","prefix.default",'[t] CSFordinalPosition; [t] "columna"; [p] (pause:200)',
-"self::cell")};sre.PrefixSpanish.getInstance().initializer=[sre.PrefixSpanish.initCustomFunctions_,sre.PrefixSpanish.initPrefixSpanish_];sre.SemanticTreeRules=function(){sre.MathStore.call(this)};goog.inherits(sre.SemanticTreeRules,sre.MathStore);goog.addSingletonGetter(sre.SemanticTreeRules);sre.SemanticTreeRules.mathStore=sre.SemanticTreeRules.getInstance();sre.SemanticTreeRules.defineRule_=goog.bind(sre.SemanticTreeRules.mathStore.defineRule,sre.SemanticTreeRules.mathStore);sre.SemanticTreeRules.defineRuleAlias_=goog.bind(sre.SemanticTreeRules.mathStore.defineRuleAlias,sre.SemanticTreeRules.mathStore);
-sre.SemanticTreeRules.addContextFunction_=goog.bind(sre.SemanticTreeRules.mathStore.contextFunctions.add,sre.SemanticTreeRules.mathStore.contextFunctions);sre.SemanticTreeRules.initCustomFunctions_=function(){(0,sre.SemanticTreeRules.addContextFunction_)("CTXFnodeCounter",sre.StoreUtil.nodeCounter);(0,sre.SemanticTreeRules.addContextFunction_)("CTXFcontentIterator",sre.MathmlStoreUtil.contentIterator)};
-sre.SemanticTreeRules.initSemanticRules_=function(){(0,sre.SemanticTreeRules.defineRule_)("stree","default.default","[n] ./*[1]","self::stree");(0,sre.SemanticTreeRules.defineRule_)("multrel","default.default",'[t] "multirelation"; [m] children/* (sepFunc:CTXFcontentIterator)',"self::multirel");(0,sre.SemanticTreeRules.defineRule_)("variable-equality","default.default",'[t] "equation sequence"; [m] children/* (context:"part",ctxtFunc:CTXFnodeCounter,sepFunc:CTXFcontentIterator)','self::relseq[@role="equality"]',
-"count(./children/*)>2",'./children/punctuation[@role="ellipsis"]');(0,sre.SemanticTreeRules.defineRule_)("multi-equality","default.default",'[t] "equation sequence"; [m] children/* (context:"part",ctxtFunc:CTXFnodeCounter,sepFunc:CTXFcontentIterator)','self::relseq[@role="equality"]',"count(./children/*)>2");(0,sre.SemanticTreeRules.defineRule_)("multi-equality","default.short",'[t] "equation sequence"; [m] children/* (sepFunc:CTXFcontentIterator)','self::relseq[@role="equality"]',"count(./children/*)>2");
-(0,sre.SemanticTreeRules.defineRule_)("equality","default.default","[n] children/*[1]; [p] (pause:200); [n] content/*[1] (pause:200);[n] children/*[2]",'self::relseq[@role="equality"]',"count(./children/*)=2");(0,sre.SemanticTreeRules.defineRule_)("simple-equality","default.default","[n] children/*[1]; [p] (pause:200); [n] content/*[1] (pause:200);[n] children/*[2]",'self::relseq[@role="equality"]',"count(./children/*)=2","./children/identifier or ./children/number");(0,sre.SemanticTreeRules.defineRule_)("simple-equality2",
-"default.default","[n] children/*[1]; [p] (pause:200); [n] content/*[1] (pause:200);[n] children/*[2]",'self::relseq[@role="equality"]',"count(./children/*)=2","./children/function or ./children/appl");(0,sre.SemanticTreeRules.defineRule_)("relseq","default.default","[m] children/* (sepFunc:CTXFcontentIterator)","self::relseq");(0,sre.SemanticTreeRules.defineRule_)("binary-operation","default.default","[m] children/* (sepFunc:CTXFcontentIterator);","self::infixop");(0,sre.SemanticTreeRules.defineRule_)("variable-addition",
-"default.default",'[t] "sum with variable number of summands";[p] (pause:400); [m] children/* (sepFunc:CTXFcontentIterator)','self::infixop[@role="addition"]',"count(children/*)>2",'children/punctuation[@role="ellipsis"]');(0,sre.SemanticTreeRules.defineRule_)("multi-addition","default.default",'[t] "sum with"; [t] count(./children/*); [t] "summands";[p] (pause:400); [m] children/* (sepFunc:CTXFcontentIterator)','self::infixop[@role="addition"]',"count(./children/*)>2");(0,sre.SemanticTreeRules.defineRule_)("prefix",
-"default.default",'[t] "prefix"; [n] text(); [t] "of" (pause 150);[n] children/*[1]',"self::prefixop");(0,sre.SemanticTreeRules.defineRule_)("negative","default.default",'[t] "negative"; [n] children/*[1]',"self::prefixop",'self::prefixop[@role="negative"]');(0,sre.SemanticTreeRules.defineRule_)("postfix","default.default",'[n] children/*[1]; [t] "postfix"; [n] text() (pause 300)',"self::postfixop");(0,sre.SemanticTreeRules.defineRule_)("identifier","default.default","[n] text()","self::identifier");
-(0,sre.SemanticTreeRules.defineRule_)("number","default.default","[n] text()","self::number");(0,sre.SemanticTreeRules.defineRule_)("font","default.default","[t] @font; [n] . (grammar:ignoreFont=@font)","self::*","@font",'not(contains(@grammar, "ignoreFont"))','@font!="normal"');(0,sre.SemanticTreeRules.defineRule_)("font-identifier-short","default.default","[t] @font; [n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'not(contains(@grammar, "ignoreFont"))','@font="normal"',
-'""=translate(text(), "abcdefghijklmnopqrstuvwxyz\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9ABCDEFGHIJKLMNOPQRSTUVWXYZ\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9", "")','@role!="unit"');(0,sre.SemanticTreeRules.defineRule_)("font-identifier","default.default","[t] @font; [n] . (grammar:ignoreFont=@font)",
-"self::identifier","string-length(text())=1","@font",'@font="normal"','not(contains(@grammar, "ignoreFont"))','@role!="unit"');(0,sre.SemanticTreeRules.defineRule_)("omit-font","default.default","[n] . (grammar:ignoreFont=@font)","self::identifier","string-length(text())=1","@font",'not(contains(@grammar, "ignoreFont"))','@font="italic"');(0,sre.SemanticTreeRules.defineRule_)("fraction","default.default",'[p] (pause:250); [n] children/*[1] (rate:0.35); [p] (pause:250); [t] "divided by"; [n] children/*[2] (rate:-0.35); [p] (pause:400)',
-"self::fraction");(0,sre.SemanticTreeRules.defineRule_)("superscript","default.default",'[n] children/*[1]; [t] "super"; [n] children/*[2] (pitch:0.35);[p] (pause:300)',"self::superscript");(0,sre.SemanticTreeRules.defineRule_)("subscript","default.default",'[n] children/*[1]; [t] "sub"; [n] children/*[2] (pitch:-0.35);[p] (pause:300)',"self::subscript");(0,sre.SemanticTreeRules.defineRule_)("ellipsis","default.default",'[p] (pause:200); [t] "ellipsis"; [p] (pause:300)',"self::punctuation",'self::punctuation[@role="ellipsis"]');
-(0,sre.SemanticTreeRules.defineRule_)("fence-single","default.default","[n] text()","self::punctuation",'self::punctuation[@role="openfence"]');(0,sre.SemanticTreeRules.defineRuleAlias_)("fence-single","self::punctuation",'self::punctuation[@role="closefence"]');(0,sre.SemanticTreeRules.defineRuleAlias_)("fence-single","self::punctuation",'self::punctuation[@role="vbar"]');(0,sre.SemanticTreeRules.defineRuleAlias_)("fence-single","self::punctuation",'self::punctuation[@role="application"]');(0,sre.SemanticTreeRules.defineRule_)("omit-empty",
-"default.default","[p] (pause:100)","self::empty");(0,sre.SemanticTreeRules.defineRule_)("fences-open-close","default.default","[p] (pause:100); [n] content/*[1]; [n] children/*[1]; [n] content/*[2]; [p] (pause:100)","self::fenced",'@role="leftright"');(0,sre.SemanticTreeRules.defineRule_)("fences-open-close-in-appl","default.default","[p] (pause:200); [n] children/*[1]; [p] (pause:200);",'self::fenced[@role="leftright"]',"./parent::children/parent::appl");(0,sre.SemanticTreeRules.defineRule_)("fences-neutral",
-"default.default",'[p] (pause:100); [t] "absolute value of"; [n] children/*[1];[p] (pause:350);',"self::fenced",'self::fenced[@role="neutral"]');(0,sre.SemanticTreeRules.defineRule_)("omit-fences","default.default","[p] (pause:500); [n] children/*[1]; [p] (pause:200);","self::fenced");(0,sre.SemanticTreeRules.defineRule_)("matrix","default.default",'[t] "matrix"; [m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:100)',"self::matrix");(0,sre.SemanticTreeRules.defineRule_)("matrix-row","default.default",
-'[m] children/* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)','self::row[@role="matrix"]');(0,sre.SemanticTreeRules.defineRule_)("matrix-cell","default.default","[n] children/*[1]",'self::cell[@role="matrix"]');(0,sre.SemanticTreeRules.defineRule_)("vector","default.default",'[t] "vector"; [m] children/* (ctxtFunc:CTXFnodeCounter,context:"element",pause:100)',"self::vector");(0,sre.SemanticTreeRules.defineRule_)("cases","default.default",'[t] "case statement"; [m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100)',
-"self::cases");(0,sre.SemanticTreeRules.defineRule_)("cases-row","default.default","[m] children/*",'self::row[@role="cases"]');(0,sre.SemanticTreeRules.defineRule_)("cases-cell","default.default","[n] children/*[1]",'self::cell[@role="cases"]');(0,sre.SemanticTreeRules.defineRule_)("row","default.default",'[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',"self::row");(0,sre.SemanticTreeRules.defineRule_)("cases-end","default.default",'[t] "case statement"; [m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100);[t] "end cases"',
-"self::cases","following-sibling::*");(0,sre.SemanticTreeRules.defineRule_)("multiline","default.default",'[t] "multiline equation";[m] children/* (ctxtFunc:CTXFnodeCounter,context:"line",pause:100)',"self::multiline");(0,sre.SemanticTreeRules.defineRule_)("multiline-ineq","default.default",'[t] "multiline inequality";[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:100)',"self::multiline",'@role="inequality"');(0,sre.SemanticTreeRules.defineRule_)("line","default.default","[m] children/*",
-"self::line");(0,sre.SemanticTreeRules.defineRule_)("table","default.default",'[t] "multiline equation";[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:200)',"self::table");(0,sre.SemanticTreeRules.defineRule_)("table-ineq","default.default",'[t] "multiline inequality";[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:200)',"self::table",'@role="inequality"');(0,sre.SemanticTreeRules.defineRule_)("table-row","default.default","[m] children/* (pause:100)",'self::row[@role="table"]');
-(0,sre.SemanticTreeRules.defineRuleAlias_)("cases-cell",'self::cell[@role="table"]');(0,sre.SemanticTreeRules.defineRule_)("empty-cell","mathspeak.default",'[t] "Blank"',"self::cell","count(children/*)=0");(0,sre.SemanticTreeRules.defineRule_)("end-punct","default.default","[m] children/*; [p] (pause:300)","self::punctuated",'@role="endpunct"');(0,sre.SemanticTreeRules.defineRule_)("start-punct","default.default","[n] content/*[1]; [p] (pause:200); [m] children/*[position()>1]","self::punctuated",
-'@role="startpunct"');(0,sre.SemanticTreeRules.defineRule_)("integral-punct","default.default","[n] children/*[1] (rate:0.2); [n] children/*[3] (rate:0.2)","self::punctuated",'@role="integral"');(0,sre.SemanticTreeRules.defineRule_)("punctuated","default.default","[m] children/* (pause:100)","self::punctuated");(0,sre.SemanticTreeRules.defineRule_)("function","default.default","[n] text()","self::function");(0,sre.SemanticTreeRules.defineRule_)("appl","default.default","[n] children/*[1]; [n] content/*[1]; [n] children/*[2]",
-"self::appl");(0,sre.SemanticTreeRules.defineRule_)("sum-only","default.default",'[n] children/*[1]; [t] "from"; [n] children/*[2]; [t] "to";[n] children/*[3]',"self::limboth",'self::limboth[@role="sum"]');(0,sre.SemanticTreeRules.defineRule_)("limboth","default.default",'[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];[t] "under"; [n] children/*[3]; [p] (pause 250);',"self::limboth");(0,sre.SemanticTreeRules.defineRule_)("limlower","default.default",'[n] children/*[1]; [t] "over"; [n] children/*[2];',
-"self::limlower");(0,sre.SemanticTreeRules.defineRule_)("limupper","default.default",'[n] children/*[1]; [t] "under"; [n] children/*[2];',"self::limupper");(0,sre.SemanticTreeRules.defineRule_)("largeop","default.default","[n] text()","self::largeop");(0,sre.SemanticTreeRules.defineRule_)("bigop","default.default",'[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];[p] (pause 250);',"self::bigop");(0,sre.SemanticTreeRules.defineRule_)("integral","default.default","[n] children/*[1]; [p] (pause 100); [n] children/*[2];[p] (pause 200); [n] children/*[3] (rate:0.35);",
-"self::integral");(0,sre.SemanticTreeRules.defineRule_)("sqrt","default.default",'[t] "Square root of"; [n] children/*[1] (rate:0.35); [p] (pause:400)',"self::sqrt");(0,sre.SemanticTreeRules.defineRule_)("square","default.default",'[n] children/*[1]; [t] "squared" (pitch:0.35); [p] (pause:300)',"self::superscript","children/*[2][text()=2]",'name(./children/*[1])!="text"');(0,sre.SemanticTreeRules.defineRule_)("cube","default.default",'[n] children/*[1]; [t] "cubed" (pitch:0.35); [p] (pause:300)',
-"self::superscript","children/*[2][text()=3]",'name(./children/*[1])!="text"');(0,sre.SemanticTreeRules.defineRule_)("root","default.default",'[t] "root of order"; [n] children/*[1];[t] "over"; [n] children/*[1] (rate:0.35); [p] (pause:400)',"self::root");(0,sre.SemanticTreeRules.defineRule_)("text","default.default","[n] text(); [p] (pause:200)","self::text");(0,sre.SemanticTreeRules.defineRule_)("unit","default.default",'[t] text() (grammar:annotation="unit":translate)',"self::identifier",'@role="unit"');
-(0,sre.SemanticTreeRules.defineRule_)("unit-square","default.default",'[t] "square"; [n] children/*[1]',"self::superscript",'@role="unit"',"children/*[2][text()=2]",'name(children/*[1])="identifier"');(0,sre.SemanticTreeRules.defineRule_)("unit-cubic","default.default",'[t] "cubic"; [n] children/*[1]',"self::superscript",'@role="unit"',"children/*[2][text()=3]",'name(children/*[1])="identifier"');(0,sre.SemanticTreeRules.defineRule_)("reciprocal","default.default",'[t] "reciprocal"; [n] children/*[1]',
-"self::superscript",'@role="unit"','name(children/*[1])="identifier"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]',"children/*[2]/children/*[1][text()=1]",'count(preceding-sibling::*)=0 or preceding-sibling::*[@role!="unit"]');(0,sre.SemanticTreeRules.defineRule_)("reciprocal","default.default",'[t] "per"; [n] children/*[1]',"self::superscript",'@role="unit"','name(children/*[1])="identifier"','name(children/*[2])="prefixop"','children/*[2][@role="negative"]',"children/*[2]/children/*[1][text()=1]",
-'preceding-sibling::*[@role="unit"]');(0,sre.SemanticTreeRules.defineRule_)("unit-combine","default.default","[m] children/*","self::infixop",'@role="unit"');(0,sre.SemanticTreeRules.defineRule_)("unit-divide","default.default",'[n] children/*[1] (pitch:0.3); [t] "per"; [n] children/*[2] (pitch:-0.3)',"self::fraction",'@role="unit"')};sre.SemanticTreeRules.getInstance().initializer=[sre.SemanticTreeRules.initCustomFunctions_,sre.SemanticTreeRules.initSemanticRules_];sre.SpeechRuleStores={};sre.SpeechRuleStores.RULE_SETS_={MathmlStoreRules:sre.MathmlStoreRules,SemanticTreeRules:sre.SemanticTreeRules,MathspeakRules:sre.MathspeakRules,MathspeakSpanish:sre.MathspeakSpanish,ClearspeakRules:sre.ClearspeakRules,EmacspeakRules:sre.EmacspeakRules,AbstractionRules:sre.AbstractionRules,AbstractionSpanish:sre.AbstractionSpanish,PrefixRules:sre.PrefixRules,PrefixSpanish:sre.PrefixSpanish};sre.SpeechRuleStores.availableSets=function(){return Object.keys(sre.SpeechRuleStores.RULE_SETS_)};
-sre.SpeechRuleStores.getConstructor=function(a){return(a=sre.SpeechRuleStores.RULE_SETS_[a])?a:null};sre.SpeechRuleEngine=function(){this.activeStore_=null;this.cache_={};this.ready_=!0;this.combinedStores_={};sre.Engine.registerTest(goog.bind(function(a){return this.ready_},this))};goog.addSingletonGetter(sre.SpeechRuleEngine);sre.SpeechRuleEngine.prototype.parameterize=function(a){for(var b={},c=0,d=a.length;c<d;c++){var e=a[c],f=sre.SpeechRuleStores.getConstructor(e);f&&f.getInstance&&(b[e]=f.getInstance())}this.parameterize_(b)};
-sre.SpeechRuleEngine.prototype.parameterize_=function(a){try{this.activeStore_=this.combineStores_(a)}catch(b){if("StoreError"==b.name)console.log("Store Error:",b.message);else throw b;}this.updateEngine()};sre.SpeechRuleEngine.prototype.constructString=function(a,b){if(!b)return"";if('"'==b.charAt(0))return b.slice(1,-1);var c=this.activeStore_.customStrings.lookup(b);return c?c(a):sre.XpathUtil.evaluateString(b,a)};sre.SpeechRuleEngine.prototype.clearCache=function(){this.cache_={}};
-sre.SpeechRuleEngine.prototype.forCache=function(a){for(var b in this.cache_)a(b,this.cache_[b])};sre.SpeechRuleEngine.prototype.getCacheForNode_=function(a){if(!a||!a.getAttribute)return null;a=a.getAttribute("id");return"undefined"===a||""===a?null:this.getCache(a)};sre.SpeechRuleEngine.prototype.getCache=function(a){return(a=this.cache_[a])?this.cloneCache(a):a};sre.SpeechRuleEngine.prototype.cloneCache=function(a){return a.map(function(a){return a.clone()})};
-sre.SpeechRuleEngine.prototype.pushCache_=function(a,b){if(sre.Engine.getInstance().cache&&a.getAttribute){var c=a.getAttribute("id");c&&(this.cache_[c]=this.cloneCache(b))}};sre.SpeechRuleEngine.prototype.evaluateNode=function(a){var b=(new Date).getTime();a=this.evaluateNode_(a);var c=(new Date).getTime();sre.Debugger.getInstance().output("Time:",c-b);return a};sre.SpeechRuleEngine.prototype.evaluateNode_=function(a){if(!a)return[];this.updateConstraint_();return this.evaluateTree_(a)};
-sre.SpeechRuleEngine.prototype.evaluateTree_=function(a){sre.Debugger.getInstance().output(a.toString());var b=sre.Engine.getInstance();if(b.cache){var c=this.getCacheForNode_(a);if(c)return c}sre.Grammar.getInstance().setAttribute(a);var d=this.activeStore_.lookupRule(a,b.dynamicCstr);if(!d){if(b.strict)return[];c=this.activeStore_.evaluateDefault(a);this.pushCache_(a,c);return c}sre.Debugger.getInstance().generateOutput(goog.bind(function(){return[d.name,d.dynamicCstr.toString(),a.toString()]},
-this));for(var b=d.action.components,c=[],e=0,f;f=b[e];e++){var g=[],h=f.content||"",k=f.attributes||{},l=!1;f.grammar&&this.processGrammar(a,f.grammar);switch(f.type){case sre.SpeechRule.Type.NODE:(h=this.activeStore_.applyQuery(a,h))&&(g=this.evaluateTree_(h));break;case sre.SpeechRule.Type.MULTI:l=!0;h=this.activeStore_.applySelector(a,h);0<h.length&&(g=this.evaluateNodeList_(h,k.sepFunc,this.constructString(a,k.separator),k.ctxtFunc,this.constructString(a,k.context)));break;case sre.SpeechRule.Type.TEXT:(h=
-this.constructString(a,h))&&(g=[sre.AuditoryDescription.create({text:h},{adjust:!0})]);break;default:g=[sre.AuditoryDescription.create({text:h})]}g[0]&&!l&&(k.context&&(g[0].context=this.constructString(a,k.context)+(g[0].context||"")),k.annotation&&(g[0].annotation=k.annotation));f.grammar&&sre.Grammar.getInstance().popState();c=c.concat(this.addPersonality_(g,k,l))}this.pushCache_(a,c);return c};
-sre.SpeechRuleEngine.prototype.evaluateNodeList_=function(a,b,c,d,e){if(a==[])return[];var f=c||"",g=e||"";c=(c=this.activeStore_.contextFunctions.lookup(d))?c(a,g):function(){return g};b=(b=this.activeStore_.contextFunctions.lookup(b))?b(a,f):function(){return sre.AuditoryDescription.create({text:f},{translate:!0})};d=[];e=0;for(var h;h=a[e];e++)h=this.evaluateTree_(h),0<h.length&&(h[0].context=c()+(h[0].context||""),d=d.concat(h),e<a.length-1&&(h=b(),d=d.concat(h)));return d};
-sre.SpeechRuleEngine.prototype.addPersonality_=function(a,b,c){var d={},e;for(e in sre.Engine.personalityProps){var f=b[sre.Engine.personalityProps[e]];if("undefined"!==typeof f){var g=parseFloat(f);d[sre.Engine.personalityProps[e]]=isNaN(g)?'"'==f.charAt(0)?f.slice(1,-1):f:g}}for(b=0;e=a[b];b++)this.addRelativePersonality_(e,d);c&&delete a[a.length-1].personality[sre.Engine.personalityProps.JOIN];return a};
-sre.SpeechRuleEngine.prototype.addRelativePersonality_=function(a,b){if(!a.personality)return a.personality=b,a;var c=a.personality,d;for(d in b)c[d]=c[d]&&"number"==typeof c[d]&&"number"==typeof b[d]?c[d]+b[d]:b[d];return a};sre.SpeechRuleEngine.prototype.toString=function(){return this.activeStore_.findAllRules(function(a){return!0}).map(function(a){return a.toString()}).join("\n")};
-sre.SpeechRuleEngine.debugSpeechRule=function(a,b){var c=sre.SpeechRuleEngine.getInstance().activeStore_;c&&c.debugSpeechRule(a,b)};sre.SpeechRuleEngine.debugNamedSpeechRule=function(a,b){var c=sre.SpeechRuleEngine.getInstance().activeStore_;if(c)for(var d=c.findAllRules(function(b){return b.name==a}),e=0,f;f=d[e];e++)sre.Debugger.getInstance().output("Rule",a,"DynamicCstr:",f.dynamicCstr.toString(),"number",e),c.debugSpeechRule(f,b)};
-sre.SpeechRuleEngine.prototype.runInSetting=function(a,b){var c=sre.Engine.getInstance(),d={},e=null,f;for(f in a)"rules"===f?(e=this.activeStore_,c.ruleSets=a[f],this.parameterize(c.ruleSets)):(d[f]=c[f],c[f]=a[f]);c.dynamicCstr=sre.DynamicCstr.create(c.locale,c.domain,c.style);var g=b();for(f in d)c[f]=d[f];e&&(this.activeStore_=e);c.dynamicCstr=sre.DynamicCstr.create(c.locale,c.domain,c.style);return g};
-sre.SpeechRuleEngine.prototype.combineStores_=function(a){var b=this.cachedStore_(a);if(b)return b;var b=new sre.MathStore,c;for(c in a){var d=a[c];d.initialize();d.getSpeechRules().forEach(function(a){b.trie.addRule(a)});b.contextFunctions.addStore(d.contextFunctions);b.customQueries.addStore(d.customQueries);b.customStrings.addStore(d.customStrings)}b.setSpeechRules(b.trie.collectRules());return this.combinedStores_[this.combinedStoreName_(Object.keys(a))]=b};
-sre.SpeechRuleEngine.prototype.combinedStoreName_=function(a){return a.sort().join("-")};sre.SpeechRuleEngine.prototype.cachedStore_=function(a){var b=Object.keys(a);return b.some(function(b){return!a[b].initialized})?null:this.combinedStores_[this.combinedStoreName_(b)]};
-sre.SpeechRuleEngine.prototype.updateEngine=function(){this.ready_=!0;var a=sre.MathMap.getInstance();sre.Engine.isReady()?sre.Engine.getInstance().evaluator=goog.bind(a.store.lookupString,a.store):(this.ready_=!1,setTimeout(goog.bind(this.updateEngine,this),250))};sre.SpeechRuleEngine.prototype.processGrammar=function(a,b){var c={},d;for(d in b){var e=b[d];c[d]="string"===typeof e?this.constructString(a,e):e}sre.Grammar.getInstance().pushState(c)};
-sre.SpeechRuleEngine.prototype.updateConstraint_=function(){var a=sre.Engine.getInstance().dynamicCstr,b=sre.Engine.getInstance().strict,c={},d=[a.getValue(sre.DynamicCstr.Axis.LOCALE),a.getValue(sre.DynamicCstr.Axis.DOMAIN)],e=sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE],f=sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.DOMAIN],g=this.activeStore_.trie.hasSubtrie(d);c[sre.DynamicCstr.Axis.LOCALE]=[g?d[0]:e];g=g?g:this.activeStore_.trie.hasSubtrie([e,d[1]]);c[sre.DynamicCstr.Axis.DOMAIN]=
-[g?d[1]:f];d=a.getOrder();for(e=0;f=d[e];e++)if(!c[f]){var g=a.getValue(f),h=this.makeSet_(g,a.preference),k=sre.DynamicCstr.DEFAULT_VALUES[f];b||g===k||h.push(k);c[f]=h}a.updateProperties(c)};sre.SpeechRuleEngine.prototype.makeSet_=function(a,b){return b&&Object.keys(b).length?a.split(":"):[a]};sre.SpeechGeneratorUtil={};sre.SpeechGeneratorUtil.computeSpeech=function(a){var b=sre.SpeechRuleEngine.getInstance();b.clearCache();return b.evaluateNode(a)};sre.SpeechGeneratorUtil.recomputeSpeech=function(a){a=sre.SemanticTree.fromNode(a);return sre.SpeechRuleEngine.getInstance().evaluateNode(a.xml())};
-sre.SpeechGeneratorUtil.computeSpeechWithoutCache=function(a){var b=sre.Engine.getInstance().cache;sre.Engine.getInstance().cache=!1;a=sre.SpeechRuleEngine.getInstance().evaluateNode(a);sre.Engine.getInstance().cache=b;return a};sre.SpeechGeneratorUtil.retrieveSpeech=function(a){var b=null;sre.Engine.getInstance().cache&&(b=sre.SpeechRuleEngine.getInstance().getCache(a.id.toString()));b||(b=sre.SpeechGeneratorUtil.recomputeSpeech(a));return sre.AuralRendering.getInstance().markup(b)};
-sre.SpeechGeneratorUtil.addSpeech=function(a,b){var c=sre.SpeechGeneratorUtil.retrieveSpeech(b);a.setAttribute(sre.EnrichMathml.Attribute.SPEECH,c)};sre.SpeechGeneratorUtil.addPrefix=function(a,b){var c=sre.SpeechGeneratorUtil.retrievePrefix(b);c&&a.setAttribute(sre.EnrichMathml.Attribute.PREFIX,c)};sre.SpeechGeneratorUtil.retrievePrefix=function(a){a=sre.SpeechGeneratorUtil.computePrefix_(a);return sre.AuralRendering.getInstance().markup(a)};
-sre.SpeechGeneratorUtil.computePrefix_=function(a){var b=sre.SemanticTree.fromRoot(a),c=sre.XpathUtil.evalXPath('.//*[@id="'+a.id+'"]',b.xml())[0];return c?sre.SpeechRuleEngine.getInstance().runInSetting({domain:"prefix",style:"default",strict:!0,cache:!1,speech:!0,rules:["PrefixRules","PrefixSpanish"]},function(){return sre.SpeechRuleEngine.getInstance().evaluateNode(c)}):[]};
-sre.SpeechGeneratorUtil.connectMactions=function(a,b,c){b=sre.DomUtil.querySelectorAll(b,"maction");for(var d=0,e;e=b[d];d++){var f=e.getAttribute("id");if(f=sre.DomUtil.querySelectorAllByAttrValue(a,"id",f)[0]){var g=e.childNodes[1];e=g.getAttribute(sre.EnrichMathml.Attribute.ID);var h=sre.WalkerUtil.getBySemanticId(a,e);h&&"dummy"!==h.getAttribute(sre.EnrichMathml.Attribute.TYPE)||(h=f.childNodes[0],(f=g.getAttribute(sre.EnrichMathml.Attribute.PARENT))&&h.setAttribute(sre.EnrichMathml.Attribute.PARENT,
-f),h.setAttribute(sre.EnrichMathml.Attribute.TYPE,"dummy"),h.setAttribute(sre.EnrichMathml.Attribute.ID,e),sre.DomUtil.querySelectorAllByAttrValue(c,"id",e)[0].setAttribute("alternative",e))}}};sre.SpeechGeneratorUtil.connectAllMactions=function(a,b){for(var c=sre.DomUtil.querySelectorAll(a,"maction"),d=0,e;e=c[d];d++)e=e.childNodes[1].getAttribute(sre.EnrichMathml.Attribute.ID),sre.DomUtil.querySelectorAllByAttrValue(b,"id",e)[0].setAttribute("alternative",e)};sre.AbstractSpeechGenerator=function(){this.rebuilt_=null};sre.AbstractSpeechGenerator.prototype.getRebuilt=function(){return this.rebuilt_};sre.AbstractSpeechGenerator.prototype.setRebuilt=function(a){this.rebuilt_=a};sre.AbstractSpeechGenerator.prototype.getSpeech=goog.abstractMethod;sre.AbstractSpeechGenerator.prototype.start=function(){};sre.AbstractSpeechGenerator.prototype.end=function(){};
-sre.AbstractSpeechGenerator.prototype.generateSpeech=function(a,b){this.rebuilt_||(this.rebuilt_=new sre.RebuildStree(b));var c=sre.SpeechGeneratorUtil.computeSpeech(this.getRebuilt().xml);return sre.AuralRendering.getInstance().markup(c)};sre.AdhocSpeechGenerator=function(){sre.AbstractSpeechGenerator.call(this)};goog.inherits(sre.AdhocSpeechGenerator,sre.AbstractSpeechGenerator);sre.AdhocSpeechGenerator.prototype.getSpeech=function(a,b){var c=this.generateSpeech(a,b);a.setAttribute(sre.EnrichMathml.Attribute.SPEECH,c);return c};sre.DirectSpeechGenerator=function(){sre.AbstractSpeechGenerator.call(this)};goog.inherits(sre.DirectSpeechGenerator,sre.AbstractSpeechGenerator);sre.DirectSpeechGenerator.prototype.getSpeech=function(a,b){return sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.SPEECH)};sre.DummySpeechGenerator=function(){sre.AbstractSpeechGenerator.call(this)};goog.inherits(sre.DummySpeechGenerator,sre.AbstractSpeechGenerator);sre.DummySpeechGenerator.prototype.getSpeech=function(a,b){return""};sre.TreeSpeechGenerator=function(){};goog.inherits(sre.TreeSpeechGenerator,sre.AbstractSpeechGenerator);sre.TreeSpeechGenerator.prototype.getSpeech=function(a,b){var c=this.generateSpeech(a,b);a.setAttribute(sre.EnrichMathml.Attribute.SPEECH,c);var d=this.getRebuilt().nodeDict,e;for(e in d){var f=d[e],g=sre.WalkerUtil.getBySemanticId(b,e),h=sre.WalkerUtil.getBySemanticId(a,e);g&&h&&(sre.SpeechGeneratorUtil.addSpeech(h,f),sre.SpeechGeneratorUtil.addPrefix(h,f))}return c};sre.NodeSpeechGenerator=function(){sre.TreeSpeechGenerator.call(this)};goog.inherits(sre.NodeSpeechGenerator,sre.TreeSpeechGenerator);sre.NodeSpeechGenerator.prototype.getSpeech=function(a,b){var c=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.SPEECH);return c?c:sre.NodeSpeechGenerator.superClass_.getSpeech.call(this,a,b)};sre.SummarySpeechGenerator=function(){};goog.inherits(sre.SummarySpeechGenerator,sre.AbstractSpeechGenerator);sre.SummarySpeechGenerator.prototype.getSpeech=function(a,b){sre.SpeechGeneratorUtil.connectAllMactions(b,this.getRebuilt().xml);return this.generateSpeech(a,b)};sre.SpeechGeneratorFactory={};sre.SpeechGeneratorFactory.generator=function(a){return new (sre.SpeechGeneratorFactory.generatorMapping_[a]||sre.SpeechGeneratorFactory.generatorMapping_.Direct)};sre.SpeechGeneratorFactory.generatorMapping_={Adhoc:sre.AdhocSpeechGenerator,Direct:sre.DirectSpeechGenerator,Dummy:sre.DummySpeechGenerator,Node:sre.NodeSpeechGenerator,Summary:sre.SummarySpeechGenerator,Tree:sre.TreeSpeechGenerator};sre.EventUtil={};sre.EventUtil.KeyCode={ENTER:13,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,TAB:9,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90};
-sre.EventUtil.EventType={CLICK:"click",DBLCLICK:"dblclick",MOUSEDOWN:"mousedown",MOUSEUP:"mouseup",MOUSEOVER:"mouseover",MOUSEOUT:"mouseout",MOUSEMOVE:"mousemove",SELECTSTART:"selectstart",KEYPRESS:"keypress",KEYDOWN:"keydown",KEYUP:"keyup",TOUCHSTART:"touchstart",TOUCHMOVE:"touchmove",TOUCHEND:"touchend",TOUCHCANCEL:"touchcancel"};sre.EventUtil.Event=function(a,b,c){this.src=a;this.type=b;this.callback=c};sre.EventUtil.Event.prototype.add=function(){this.src.addEventListener(this.type,this.callback)};
-sre.EventUtil.Event.prototype.remove=function(){this.src.removeEventListener(this.type,this.callback)};sre.Focus=function(a,b){this.semanticNodes_=a;this.semanticPrimary_=b;this.domNodes_=[];this.domPrimary_=null;this.allNodes_=[]};sre.Focus.prototype.getSemanticPrimary=function(){return this.semanticPrimary_};sre.Focus.prototype.getSemanticNodes=function(){return this.semanticNodes_};sre.Focus.prototype.getNodes=function(){return this.allNodes_};sre.Focus.prototype.getDomNodes=function(){return this.domNodes_};sre.Focus.prototype.getDomPrimary=function(){return this.domPrimary_};
-sre.Focus.prototype.toString=function(){return"Primary:"+this.domPrimary_+" Nodes:"+this.domNodes_};sre.Focus.prototype.clone=function(){var a=new sre.Focus(this.semanticNodes_,this.semanticPrimary_);a.domNodes_=this.domNodes_;a.domPrimary_=this.domPrimary_;a.allNodes_=this.allNodes_;return a};
-sre.Focus.factory=function(a,b,c,d){var e=function(a){return sre.WalkerUtil.getBySemanticId(d,a)},f=c.nodeDict;c=e(a);var e=b.map(e),g=b.map(function(a){return f[a]});a=new sre.Focus(g,f[a]);a.domNodes_=e;a.domPrimary_=c;a.allNodes_=sre.Focus.generateAllVisibleNodes_(b,e,f,d);return a};
-sre.Focus.generateAllVisibleNodes_=function(a,b,c,d){for(var e=function(a){return sre.WalkerUtil.getBySemanticId(d,a)},f=[],g=0,h=a.length;g<h;g++)if(b[g])f.push(b[g]);else{var k=c[a[g]];if(k)var k=k.childNodes.map(function(a){return a.id.toString()}),l=k.map(e),f=f.concat(sre.Focus.generateAllVisibleNodes_(k,l,c,d))}return f};sre.Levels=function(){this.level_=[]};sre.Levels.prototype.push=function(a){this.level_.push(a)};sre.Levels.prototype.pop=function(){return this.level_.pop()};sre.Levels.prototype.peek=function(){return this.level_[this.level_.length-1]||null};sre.Levels.prototype.indexOf=function(a){var b=this.peek();return b?b.indexOf(a):null};sre.Levels.prototype.find=function(a){var b=this.peek();if(!b)return null;for(var c=0,d=b.length;c<d;c++)if(a(b[c]))return b[c];return null};
-sre.Levels.prototype.get=function(a){var b=this.peek();return!b||0>a||a>=b.length?null:b[a]};sre.Levels.prototype.depth=function(){return this.level_.length};sre.Levels.prototype.clone=function(){var a=new sre.Levels;a.level_=this.level_.slice(0);return a};sre.Levels.prototype.toString=function(){for(var a="",b=0,c;c=this.level_[b];b++)a+="\n"+c.map(function(a){return a.toString()});return a};sre.Walker=function(){};sre.Walker.prototype.isActive=function(){};sre.Walker.prototype.activate=function(){};sre.Walker.prototype.deactivate=function(){};sre.Walker.prototype.speech=function(){};sre.Walker.prototype.getFocus=function(){};sre.Walker.prototype.setFocus=function(a){};sre.Walker.prototype.getDepth=function(){};sre.Walker.prototype.move=function(a){};
-sre.Walker.move={UP:"up",DOWN:"down",LEFT:"left",RIGHT:"right",REPEAT:"repeat",DEPTH:"depth",ENTER:"enter",EXPAND:"expand",HOME:"home",SUMMARY:"summary",DETAIL:"detail",ROW:"row",CELL:"cell"};sre.AbstractWalker=function(a,b,c,d){this.node=a;this.xml=sre.DomUtil.parseInput(d);this.generator=b;this.rebuilt=this.rebuildStree_();this.generator.setRebuilt(this.rebuilt);this.highlighter=c;this.active_=!1;this.keyMapping={};this.keyMapping[sre.EventUtil.KeyCode.UP]=goog.bind(this.up,this);this.keyMapping[sre.EventUtil.KeyCode.DOWN]=goog.bind(this.down,this);this.keyMapping[sre.EventUtil.KeyCode.RIGHT]=goog.bind(this.right,this);this.keyMapping[sre.EventUtil.KeyCode.LEFT]=goog.bind(this.left,
-this);this.keyMapping[sre.EventUtil.KeyCode.TAB]=goog.bind(this.repeat,this);this.keyMapping[sre.EventUtil.KeyCode.ENTER]=goog.bind(this.expand,this);this.keyMapping[sre.EventUtil.KeyCode.SPACE]=goog.bind(this.depth,this);this.keyMapping[sre.EventUtil.KeyCode.HOME]=goog.bind(this.home,this);this.keyMapping[sre.EventUtil.KeyCode.X]=goog.bind(this.summary,this);this.keyMapping[sre.EventUtil.KeyCode.Z]=goog.bind(this.detail,this);this.keyMapping[sre.EventUtil.KeyCode.V]=goog.bind(this.virtualize,this);
-this.keyMapping[sre.EventUtil.KeyCode.P]=goog.bind(this.previous,this);this.keyMapping[sre.EventUtil.KeyCode.U]=goog.bind(this.undo,this);this.dummy_=function(){};this.rootNode=sre.WalkerUtil.getSemanticRoot(a);this.rootId=this.rebuilt.stree.root.id.toString();this.focus_=sre.Focus.factory(this.rootId,[this.rootId],this.rebuilt,this.node);this.moved=sre.Walker.move.ENTER;this.cursors=[]};sre.AbstractWalker.prototype.isActive=function(){return this.active_};
-sre.AbstractWalker.prototype.toggleActive_=function(){this.active_=!this.active_};sre.AbstractWalker.prototype.activate=function(){this.isActive()||(this.generator.start(),this.toggleActive_())};sre.AbstractWalker.prototype.deactivate=function(){this.isActive()&&(this.highlighter.setState(this.node.id,this.primaryId()),this.generator.end(),this.toggleActive_())};sre.AbstractWalker.prototype.getFocus=function(){return this.focus_};sre.AbstractWalker.prototype.setFocus=function(a){this.focus_=a};
-sre.AbstractWalker.prototype.getDepth=function(){return this.levels.depth()-1};
-sre.AbstractWalker.prototype.speech=function(){var a=this.focus_.getDomNodes();if(!a.length)return"";var b=this.specialMove();if(null!==b)return b;switch(this.moved){case sre.Walker.move.DEPTH:return this.depth_();case sre.Walker.move.SUMMARY:return this.summary_();case sre.Walker.move.DETAIL:return this.detail_();default:for(var b=[],c=this.focus_.getSemanticNodes(),d=0,e=a.length;d<e;d++){var f=a[d],g=c[d];b.push(f?this.generator.getSpeech(f,this.xml):sre.SpeechGeneratorUtil.retrieveSpeech(g))}return this.mergePrefix_(b)}};
-sre.AbstractWalker.prototype.mergePrefix_=function(a,b){var c=b||[],d=this.prefix_();d&&a.unshift(d);return sre.AuralRendering.getInstance().merge(c.concat(a))};sre.AbstractWalker.prototype.prefix_=function(){var a=this.focus_.getDomNodes(),b=this.focus_.getSemanticNodes();return a[0]?sre.WalkerUtil.getAttribute(a[0],sre.EnrichMathml.Attribute.PREFIX):sre.SpeechGeneratorUtil.retrievePrefix(b[0])};
-sre.AbstractWalker.prototype.move=function(a){a=this.keyMapping[a];if(!a)return null;a=a();if(!a||a===this.focus_)return!1;this.focus_=a;this.moved===sre.Walker.move.HOME&&(this.levels=this.initLevels());return!0};sre.AbstractWalker.prototype.up=function(){this.moved=sre.Walker.move.UP;return this.focus_};sre.AbstractWalker.prototype.down=function(){this.moved=sre.Walker.move.DOWN;return this.focus_};sre.AbstractWalker.prototype.left=function(){this.moved=sre.Walker.move.LEFT;return this.focus_};
-sre.AbstractWalker.prototype.right=function(){this.moved=sre.Walker.move.RIGHT;return this.focus_};sre.AbstractWalker.prototype.repeat=function(){this.moved=sre.Walker.move.REPEAT;return this.focus_.clone()};sre.AbstractWalker.prototype.depth=function(){this.moved=sre.Walker.move.DEPTH;return this.focus_.clone()};
-sre.AbstractWalker.prototype.depth_=function(){var a=sre.Grammar.getInstance().getParameter("depth");sre.Grammar.getInstance().setParameter("depth",!0);var b=this.focus_.getDomPrimary(),b=this.expandable(b)&&[sre.Messages.NAVIGATE.EXPANDABLE]||this.collapsible(b)&&[sre.Messages.NAVIGATE.COLLAPSIBLE]||[],c=[sre.AuralRendering.getInstance().markup([new sre.AuditoryDescription({text:sre.Messages.NAVIGATE.LEVEL+" "+this.getDepth(),personality:{}})])],d=this.focus_.getSemanticNodes();(d=sre.SpeechGeneratorUtil.retrievePrefix(d[0]))&&
-c.push(d);sre.Grammar.getInstance().setParameter("depth",a);return sre.AuralRendering.getInstance().merge(c.concat(b))};sre.AbstractWalker.prototype.home=function(){this.moved=sre.Walker.move.HOME;return sre.Focus.factory(this.rootId,[this.rootId],this.rebuilt,this.node)};sre.AbstractWalker.prototype.getBySemanticId=function(a){return sre.WalkerUtil.getBySemanticId(this.node,a)};sre.AbstractWalker.prototype.primaryId=function(){return this.focus_.getSemanticPrimary().id.toString()};
-sre.AbstractWalker.prototype.expand=function(){var a=this.focus_.getDomPrimary(),a=this.actionable_(a);if(!a)return this.focus_;this.moved=sre.Walker.move.EXPAND;a.onclick();return this.focus_.clone()};sre.AbstractWalker.prototype.actionable_=function(a){return a&&a.parentNode&&this.highlighter.isMactionNode(a.parentNode)?a.parentNode:null};sre.AbstractWalker.prototype.expandable=function(a){return!!this.actionable_(a)&&0===a.childNodes.length};
-sre.AbstractWalker.prototype.collapsible=function(a){return!!this.actionable_(a)&&0<a.childNodes.length};sre.AbstractWalker.prototype.restoreState=function(){if(this.highlighter){var a=this.highlighter.getState(this.node.id);if(a){for(var b=this.rebuilt.nodeDict[a],a=[];b;)a.push(b.id),b=b.parent;for(a.pop();0<a.length;){this.down();b=a.pop();b=this.findFocusOnLevel(b);if(!b)break;this.focus_=b}this.moved=sre.Walker.move.ENTER}}};sre.AbstractWalker.prototype.findFocusOnLevel=goog.abstractMethod;
-sre.AbstractWalker.prototype.initLevels=goog.abstractMethod;sre.AbstractWalker.prototype.rebuildStree_=function(){var a=new sre.RebuildStree(this.xml);sre.SpeechGeneratorUtil.connectMactions(this.node,this.xml,a.xml);return a};sre.AbstractWalker.prototype.previousLevel=function(){var a=this.focus_.getDomPrimary();return a?sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.PARENT):this.focus_.getSemanticPrimary().parent.id.toString()};
-sre.AbstractWalker.prototype.nextLevel=function(){var a=this.focus_.getDomPrimary();if(a){var b=sre.WalkerUtil.splitAttribute(sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.CHILDREN)),c=sre.WalkerUtil.splitAttribute(sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.CONTENT)),d=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.TYPE),a=sre.WalkerUtil.getAttribute(a,sre.EnrichMathml.Attribute.ROLE);return this.combineContentChildren(d,a,c,b)}c=function(a){return a.id.toString()};
-d=this.rebuilt.nodeDict[this.primaryId()];b=d.childNodes.map(c);c=d.contentNodes.map(c);return 0===b.length?[]:this.combineContentChildren(d.type,d.role,c,b)};sre.AbstractWalker.prototype.combineContentChildren=goog.abstractMethod;sre.AbstractWalker.prototype.singletonFocus=function(a){return this.focusFromId(a,[a])};sre.AbstractWalker.prototype.focusFromId=function(a,b){return sre.Focus.factory(a,b,this.rebuilt,this.node)};
-sre.AbstractWalker.prototype.summary=function(){this.moved=sre.Walker.move.SUMMARY;return this.focus_.clone()};
-sre.AbstractWalker.prototype.summary_=function(){var a=this.focus_.getSemanticPrimary().id.toString(),a=this.rebuilt.xml.getAttribute("id")===a?this.rebuilt.xml:sre.DomUtil.querySelectorAllByAttrValue(this.rebuilt.xml,"id",a)[0],b=a.getAttribute("alternative");a.setAttribute("alternative","summary");var c=sre.SpeechGeneratorUtil.computeSpeechWithoutCache(a),c=sre.AuralRendering.getInstance().markup(c),c=this.mergePrefix_([c]);b?a.setAttribute("alternative",b):a.removeAttribute("alternative");return c};
-sre.AbstractWalker.prototype.detail=function(){this.moved=sre.Walker.move.DETAIL;return this.focus_.clone()};
-sre.AbstractWalker.prototype.detail_=function(){var a=this.focus_.getSemanticPrimary().id.toString(),a=this.rebuilt.xml.getAttribute("id")===a?this.rebuilt.xml:sre.DomUtil.querySelectorAllByAttrValue(this.rebuilt.xml,"id",a)[0],b=a.getAttribute("alternative");a.removeAttribute("alternative");var c=sre.SpeechGeneratorUtil.computeSpeechWithoutCache(a),c=sre.AuralRendering.getInstance().markup(c),c=this.mergePrefix_([c]);a.setAttribute("alternative",b);return c};
-sre.AbstractWalker.prototype.specialMove=function(){return null};sre.AbstractWalker.prototype.virtualize=function(a){this.cursors.push({focus:this.focus_,levels:this.levels,undo:a||!this.cursors.length});this.levels=this.levels.clone();return this.focus_.clone()};sre.AbstractWalker.prototype.previous=function(){var a=this.cursors.pop();if(!a)return this.focus_;this.levels=a.levels;return a.focus};
-sre.AbstractWalker.prototype.undo=function(){do var a=this.cursors.pop();while(a&&!a.undo);if(!a)return this.focus_;this.levels=a.levels;return a.focus};sre.DummyWalker=function(a,b,c,d){sre.AbstractWalker.call(this,a,b,c,d)};goog.inherits(sre.DummyWalker,sre.AbstractWalker);sre.DummyWalker.prototype.up=function(){};sre.DummyWalker.prototype.down=function(){};sre.DummyWalker.prototype.left=function(){};sre.DummyWalker.prototype.right=function(){};sre.DummyWalker.prototype.repeat=function(){};sre.DummyWalker.prototype.depth=function(){};sre.DummyWalker.prototype.home=function(){};sre.DummyWalker.prototype.getDepth=function(){return 0};sre.SemanticWalker=function(a,b,c,d){sre.AbstractWalker.call(this,a,b,c,d);this.levels=this.initLevels();this.restoreState()};goog.inherits(sre.SemanticWalker,sre.AbstractWalker);sre.SemanticWalker.prototype.initLevels=function(){var a=new sre.Levels;a.push([this.getFocus()]);return a};
-sre.SemanticWalker.prototype.up=function(){sre.SemanticWalker.superClass_.up.call(this);var a=this.previousLevel();if(!a)return null;this.levels.pop();return this.levels.find(function(b){return b.getSemanticNodes().some(function(b){return b.id.toString()===a})})};sre.SemanticWalker.prototype.down=function(){sre.SemanticWalker.superClass_.down.call(this);var a=this.nextLevel();if(0===a.length)return null;this.levels.push(a);return a[0]};
-sre.SemanticWalker.prototype.combineContentChildren=function(a,b,c,d){switch(a){case sre.SemanticAttr.Type.RELSEQ:case sre.SemanticAttr.Type.INFIXOP:case sre.SemanticAttr.Type.MULTIREL:return this.makePairList(d,c);case sre.SemanticAttr.Type.PREFIXOP:return[this.focusFromId(d[0],c.concat(d))];case sre.SemanticAttr.Type.POSTFIXOP:return[this.focusFromId(d[0],d.concat(c))];case sre.SemanticAttr.Type.MATRIX:case sre.SemanticAttr.Type.VECTOR:case sre.SemanticAttr.Type.FENCED:return[this.focusFromId(d[0],
-[c[0],d[0],c[1]])];case sre.SemanticAttr.Type.CASES:return[this.focusFromId(d[0],[c[0],d[0]])];case sre.SemanticAttr.Type.PUNCTUATED:return b===sre.SemanticAttr.Role.TEXT?d.map(goog.bind(this.singletonFocus,this)):d.length===c.length?c.map(goog.bind(this.singletonFocus,this)):this.combinePunctuations(d,c,[],[]);case sre.SemanticAttr.Type.APPL:return[this.focusFromId(d[0],[d[0],c[0]]),this.singletonFocus(d[1])];case sre.SemanticAttr.Type.ROOT:return[this.singletonFocus(d[1]),this.singletonFocus(d[0])];
-default:return d.map(goog.bind(this.singletonFocus,this))}};sre.SemanticWalker.prototype.combinePunctuations=function(a,b,c,d){if(0===a.length)return d;var e=a.shift(),f=b.shift();if(e===f)return c.push(f),this.combinePunctuations(a,b,c,d);b.unshift(f);c.push(e);if(a.length===b.length)return d.push(this.focusFromId(e,c.concat(b))),d;d.push(this.focusFromId(e,c));return this.combinePunctuations(a,b,[],d)};
-sre.SemanticWalker.prototype.makePairList=function(a,b){if(0===a.length)return[];if(1===a.length)return[this.singletonFocus(a[0])];for(var c=[this.singletonFocus(a.shift())],d=0,e=a.length;d<e;d++)c.push(this.focusFromId(a[d],[b[d],a[d]]));return c};sre.SemanticWalker.prototype.left=function(){sre.SemanticWalker.superClass_.left.call(this);var a=this.levels.indexOf(this.getFocus())-1;return(a=this.levels.get(a))?a:null};
-sre.SemanticWalker.prototype.right=function(){sre.SemanticWalker.superClass_.right.call(this);var a=this.levels.indexOf(this.getFocus())+1;return(a=this.levels.get(a))?a:null};sre.SemanticWalker.prototype.findFocusOnLevel=function(a){return this.levels.find(function(b){return b.getSemanticPrimary().id===a})};sre.SyntaxWalker=function(a,b,c,d){sre.AbstractWalker.call(this,a,b,c,d);this.levels=this.initLevels();this.restoreState()};goog.inherits(sre.SyntaxWalker,sre.AbstractWalker);sre.SyntaxWalker.prototype.initLevels=function(){var a=new sre.Levels;a.push([this.primaryId()]);return a};sre.SyntaxWalker.prototype.up=function(){sre.SyntaxWalker.superClass_.up.call(this);var a=this.previousLevel();if(!a)return null;this.levels.pop();return this.singletonFocus(a)};
-sre.SyntaxWalker.prototype.down=function(){sre.SyntaxWalker.superClass_.down.call(this);var a=this.nextLevel();if(0===a.length)return null;var b=this.singletonFocus(a[0]);b&&this.levels.push(a);return b};
-sre.SyntaxWalker.prototype.combineContentChildren=function(a,b,c,d){switch(a){case sre.SemanticAttr.Type.RELSEQ:case sre.SemanticAttr.Type.INFIXOP:case sre.SemanticAttr.Type.MULTIREL:return sre.BaseUtil.interleaveLists(d,c);case sre.SemanticAttr.Type.PREFIXOP:return c.concat(d);case sre.SemanticAttr.Type.POSTFIXOP:return d.concat(c);case sre.SemanticAttr.Type.MATRIX:case sre.SemanticAttr.Type.VECTOR:case sre.SemanticAttr.Type.FENCED:return d.unshift(c[0]),d.push(c[1]),d;case sre.SemanticAttr.Type.CASES:return d.unshift(c[0]),
-d;case sre.SemanticAttr.Type.PUNCTUATED:return b===sre.SemanticAttr.Role.TEXT?sre.BaseUtil.interleaveLists(d,c):d;case sre.SemanticAttr.Type.APPL:return[d[0],c[0],d[1]];case sre.SemanticAttr.Type.ROOT:return[d[1],d[0]];default:return d}};sre.SyntaxWalker.prototype.left=function(){sre.SyntaxWalker.superClass_.left.call(this);var a=this.levels.indexOf(this.primaryId())-1;return(a=this.levels.get(a))?this.singletonFocus(a):null};
-sre.SyntaxWalker.prototype.right=function(){sre.SyntaxWalker.superClass_.right.call(this);var a=this.levels.indexOf(this.primaryId())+1;return(a=this.levels.get(a))?this.singletonFocus(a):null};sre.SyntaxWalker.prototype.findFocusOnLevel=function(a){return this.singletonFocus(a.toString())};sre.TableWalker=function(a,b,c,d){sre.SyntaxWalker.call(this,a,b,c,d);this.modifier=!1;this.keyMapping[sre.EventUtil.KeyCode["0"]]=goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["1"]]=goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["2"]]=goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["3"]]=goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["4"]]=goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["5"]]=
-goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["6"]]=goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["7"]]=goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["8"]]=goog.bind(this.jumpCell,this);this.keyMapping[sre.EventUtil.KeyCode["9"]]=goog.bind(this.jumpCell,this);this.key_=null;this.row_=0;this.firstJump=this.currentTable_=null};goog.inherits(sre.TableWalker,sre.SyntaxWalker);
-sre.TableWalker.prototype.move=function(a){this.key_=a;a=sre.TableWalker.superClass_.move.call(this,a);this.modifier=!1;return a};sre.TableWalker.prototype.up=function(){this.moved=sre.Walker.move.UP;return this.eligibleCell_()?this.verticalMove_(!1):sre.TableWalker.superClass_.up.call(this)};sre.TableWalker.prototype.down=function(){this.moved=sre.Walker.move.DOWN;return this.eligibleCell_()?this.verticalMove_(!0):sre.TableWalker.superClass_.down.call(this)};
-sre.TableWalker.ELIGIBLE_CELL_ROLES=[sre.SemanticAttr.Role.DETERMINANT,sre.SemanticAttr.Role.ROWVECTOR,sre.SemanticAttr.Role.BINOMIAL,sre.SemanticAttr.Role.SQUAREMATRIX,sre.SemanticAttr.Role.MULTILINE,sre.SemanticAttr.Role.MATRIX,sre.SemanticAttr.Role.VECTOR,sre.SemanticAttr.Role.CASES,sre.SemanticAttr.Role.TABLE];sre.TableWalker.ELIGIBLE_TABLE_TYPES=[sre.SemanticAttr.Type.MULTILINE,sre.SemanticAttr.Type.MATRIX,sre.SemanticAttr.Type.VECTOR,sre.SemanticAttr.Type.CASES,sre.SemanticAttr.Type.TABLE];
-sre.TableWalker.prototype.eligibleCell_=function(){var a=this.getFocus().getSemanticPrimary();return this.modifier&&a.type===sre.SemanticAttr.Type.CELL&&-1!==sre.TableWalker.ELIGIBLE_CELL_ROLES.indexOf(a.role)};
-sre.TableWalker.prototype.verticalMove_=function(a){var b=this.previousLevel();if(!b)return null;var c=this.getFocus(),d=this.levels.indexOf(this.primaryId()),e=this.levels.pop(),b=this.levels.indexOf(b);a=this.levels.get(a?b+1:b-1);if(!a)return this.levels.push(e),null;this.setFocus(this.singletonFocus(a));a=this.nextLevel();if(!a[d])return this.setFocus(c),this.levels.push(e),null;this.levels.push(a);return this.singletonFocus(a[d])};
-sre.TableWalker.prototype.jumpCell=function(){if(!this.isInTable_())return this.getFocus();if(this.moved===sre.Walker.move.ROW){this.moved=sre.Walker.move.CELL;var a=this.key_-sre.EventUtil.KeyCode["0"];return this.isLegalJump_(this.row_,a)?this.jumpCell_(this.row_,a):this.getFocus()}a=this.key_-sre.EventUtil.KeyCode["0"];if(a>this.currentTable_.childNodes.length)return this.getFocus();this.row_=a;this.moved=sre.Walker.move.ROW;return this.getFocus().clone()};
-sre.TableWalker.prototype.jumpCell_=function(a,b){this.firstJump?this.virtualize(!1):(this.firstJump=this.getFocus(),this.virtualize(!0));var c=this.currentTable_.id.toString();do var d=this.levels.pop();while(-1===d.indexOf(c));this.levels.push(d);this.setFocus(this.singletonFocus(c));this.levels.push(this.nextLevel());c=this.currentTable_.childNodes[a-1];this.setFocus(this.singletonFocus(c.id.toString()));this.levels.push(this.nextLevel());return this.singletonFocus(c.childNodes[b-1].id.toString())};
-sre.TableWalker.prototype.isLegalJump_=function(a,b){var c=sre.DomUtil.querySelectorAllByAttrValue(this.rebuilt.xml,"id",this.currentTable_.id.toString())[0];if(!c||c.hasAttribute("alternative"))return!1;var d=this.currentTable_.childNodes[a-1];if(!d)return!1;c=sre.DomUtil.querySelectorAllByAttrValue(c,"id",d.id.toString())[0];return!c||c.hasAttribute("alternative")?!1:!(!d||!d.childNodes[b-1])};
-sre.TableWalker.prototype.isInTable_=function(){for(var a=this.getFocus().getSemanticPrimary();a;){if(-1!==sre.TableWalker.ELIGIBLE_TABLE_TYPES.indexOf(a.type))return this.currentTable_=a,!0;a=a.parent}return!1};sre.TableWalker.prototype.undo=function(){var a=sre.TableWalker.superClass_.undo.call(this);a===this.firstJump&&(this.firstJump=null);return a};sre.WalkerFactory={};sre.WalkerFactory.walker=function(a,b,c,d,e){return new (sre.WalkerFactory.walkerMapping_[a]||sre.WalkerFactory.walkerMapping_.Dummy)(b,c,d,e)};sre.WalkerFactory.walkerMapping_={Dummy:sre.DummyWalker,Semantic:sre.SemanticWalker,Syntax:sre.SyntaxWalker,Table:sre.TableWalker};sre.System=function(){this.version="2.3.0-beta.0"};goog.addSingletonGetter(sre.System);sre.System.Error=function(a){Error.call(this);this.message=a||"";this.name="System Error"};goog.inherits(sre.System.Error,Error);sre.System.LocalStorage_=function(){this.speechGenerator=this.walker=null};goog.addSingletonGetter(sre.System.LocalStorage_);
-sre.System.prototype.setupEngine=function(a){var b=sre.Engine.getInstance(),c=function(c){b[c]=a[c]||b[c]};c("mode");sre.System.prototype.configBlocks_(a);["strict","cache","semantics"].forEach(function(c){"undefined"!==typeof a[c]&&(b[c]=!!a[c])});"markup style domain speech walker locale".split(" ").forEach(c);a.json&&(sre.SystemExternal.jsonPath=sre.BaseUtil.makePath(a.json));a.xpath&&(sre.SystemExternal.WGXpath=a.xpath);b.setupBrowsers();b.ruleSets=a.rules?a.rules:sre.SpeechRuleStores.availableSets();
-sre.SpeechRuleEngine.getInstance().parameterize(b.ruleSets);b.dynamicCstr=b.parser.parse(b.locale+"."+b.domain+"."+b.style);c=b.comparators[b.domain];b.comparator=c?c():new sre.DynamicCstr.DefaultComparator(b.dynamicCstr,sre.DynamicProperties.create([sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE]],[sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.DOMAIN]],["short",sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.STYLE]]));sre.L10n.setLocale()};
-sre.System.prototype.configBlocks_=function(a){if(sre.Engine.getInstance().mode===sre.Engine.Mode.HTTP)for(var b=document.documentElement.querySelectorAll('script[type="text/x-sre-config"]'),c=0,d=b.length;c<d;c++)try{var e=b[c].innerHTML,f=JSON.parse(e),g;for(g in f)a[g]=f[g]}catch(h){sre.Debugger.getInstance().output("Illegal configuration ",e)}};
-sre.System.prototype.toSpeech=function(a){return(a=sre.System.getInstance().parseExpression_(a,sre.Engine.getInstance().semantics))?sre.System.getInstance().processXml(a):""};sre.System.prototype.processExpression=sre.System.prototype.toSpeech;sre.System.prototype.toSemantic=function(a){return sre.System.getInstance().parseExpression_(a,!0)};sre.System.prototype.toJson=function(a){a=sre.DomUtil.parseInput(a,sre.System.Error);return sre.Semantic.getTree(a).toJson()};
-sre.System.prototype.toDescription=function(a){return(a=sre.System.getInstance().parseExpression_(a,sre.Engine.getInstance().semantics))?sre.SpeechGeneratorUtil.computeSpeech(a):[]};
-sre.System.prototype.toEnriched=function(a){a=sre.Enrich.semanticMathmlSync(a);var b=sre.WalkerUtil.getSemanticRoot(a);switch(sre.Engine.getInstance().speech){case sre.Engine.Speech.SHALLOW:var c=sre.SpeechGeneratorFactory.generator("Adhoc");c.getSpeech(b,a);break;case sre.Engine.Speech.DEEP:c=sre.SpeechGeneratorFactory.generator("Tree"),c.getSpeech(b,a)}return a};sre.System.prototype.fileToSpeech=function(a,b){sre.System.getInstance().processFile_(sre.System.getInstance().toSpeech,a,b)};
-sre.System.prototype.processFile=sre.System.prototype.fileToSpeech;sre.System.prototype.fileToSemantic=function(a,b){sre.System.getInstance().processFile_(function(a){return sre.System.getInstance().toSemantic(a).toString()},a,b)};sre.System.prototype.fileToJson=function(a,b){sre.System.getInstance().processFile_(function(a){return JSON.stringify(sre.System.getInstance().toJson(a))},a,b)};
-sre.System.prototype.fileToDescription=function(a,b){sre.System.getInstance().processFile_(function(a){return JSON.stringify(sre.System.getInstance().toDescription(a))},a,b)};sre.System.prototype.fileToEnriched=function(a,b){sre.System.getInstance().processFile_(function(a){return sre.System.getInstance().toEnriched(a).toString()},a,b)};sre.System.prototype.processXml=function(a){a=sre.SpeechGeneratorUtil.computeSpeech(a);return sre.AuralRendering.getInstance().markup(a)};
-sre.System.prototype.parseExpression_=function(a,b){var c=null;try{c=sre.DomUtil.parseInput(a,sre.System.Error),b&&(c=sre.System.getInstance().getSemanticTree(c)),sre.Debugger.getInstance().generateOutput(goog.bind(function(){return c.toString()},this))}catch(d){console.log("Parse Error: "+d.message)}return c};sre.System.prototype.getSemanticTree=function(a){return sre.Semantic.xmlTree(a)};
-sre.System.prototype.processFile_=function(a,b,c){sre.Engine.isReady()?sre.Engine.getInstance().mode===sre.Engine.Mode.SYNC?this.processFileSync_(a,b,c):this.processFileAsync_(a,b,c):setTimeout(goog.bind(function(){this.processFile_(a,b,c)},this),100)};sre.System.prototype.inputFileSync_=function(a){try{var b=sre.SystemExternal.fs.readFileSync(a,{encoding:"utf8"})}catch(c){throw new sre.System.Error("Can not open file: "+a);}return b};
-sre.System.prototype.processFileSync_=function(a,b,c){b=sre.System.getInstance().inputFileSync_(b);a=a(b);if(c)try{sre.SystemExternal.fs.writeFileSync(c,a,function(){})}catch(d){throw new sre.System.Error("Can not write to file: "+c);}else console.log(a)};sre.System.prototype.inputFileAsync_=function(a,b){sre.SystemExternal.fs.readFile(a,{encoding:"utf8"},goog.bind(function(c,d){if(c)throw new sre.System.Error("Can not open file: "+a);b(d)},this))};
-sre.System.prototype.processFileAsync_=function(a,b,c){sre.System.getInstance().inputFileAsync_(b,goog.bind(function(b){b=a(b);c?sre.SystemExternal.fs.writeFile(c,b,function(a){if(a)throw new sre.System.Error("Can not write to file: "+c);}):console.log(b)},this))};
-sre.System.prototype.walk=function(a){var b=sre.SpeechGeneratorFactory.generator("Node");sre.System.LocalStorage_.getInstance().speechGenerator=b;var c=sre.HighlighterFactory.highlighter({color:"black"},{color:"white"},{renderer:"NativeMML"});a=sre.System.getInstance().toEnriched(a);var d=(new sre.SystemExternal.xmldom.XMLSerializer).serializeToString(a);sre.System.LocalStorage_.getInstance().walker=sre.WalkerFactory.walker(sre.Engine.getInstance().walker,a,b,c,d);return sre.System.LocalStorage_.getInstance().walker.speech()};
-sre.System.prototype.move=function(a){if(!sre.System.LocalStorage_.getInstance().walker)return null;var b="string"===typeof a?sre.EventUtil.KeyCode[a.toUpperCase()]:a;return!1===sre.System.LocalStorage_.getInstance().walker.move(b)?sre.AuralRendering.getInstance().error(a):sre.System.LocalStorage_.getInstance().walker.speech()};sre.Browser={};sre.System.getInstance().setupEngine({mode:sre.Engine.Mode.HTTP,domain:"mathspeak",style:"default",semantics:!0});var SRE=sre.System.getInstance();
diff --git a/chromium/third_party/cld_3/LICENSE b/chromium/third_party/cld_3/LICENSE
deleted file mode 100644
index c5899b26feb..00000000000
--- a/chromium/third_party/cld_3/LICENSE
+++ /dev/null
@@ -1,203 +0,0 @@
-Copyright 2016 Google Inc. All rights reserved.
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright 2016, Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/chromium/third_party/cld_3/OWNERS b/chromium/third_party/cld_3/OWNERS
deleted file mode 100644
index 99c5de00588..00000000000
--- a/chromium/third_party/cld_3/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-andrewhayden@chromium.org
-abakalov@chromium.org \ No newline at end of file
diff --git a/chromium/third_party/cld_3/README.chromium b/chromium/third_party/cld_3/README.chromium
deleted file mode 100644
index eda94857beb..00000000000
--- a/chromium/third_party/cld_3/README.chromium
+++ /dev/null
@@ -1,12 +0,0 @@
-Name: Compact Language Detector v3
-Short Name: cld_3
-URL: https://github.com/google/cld3
-Version: 0
-License: Apache 2.0
-Security Critical: yes
-
-Description:
-CLD3 is a neural net model for detecting the language of text.
-
-Local Modifications:
-None. \ No newline at end of file
diff --git a/chromium/third_party/cld_3/src/CONTRIBUTING.md b/chromium/third_party/cld_3/src/CONTRIBUTING.md
deleted file mode 100644
index ade29dbfc34..00000000000
--- a/chromium/third_party/cld_3/src/CONTRIBUTING.md
+++ /dev/null
@@ -1,26 +0,0 @@
-Want to contribute? Great! First, read this page (including the small print at
-the end).
-
-### Before you contribute
-Before we can use your code, you must sign the
-[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual)
-(CLA), which you can do online. The CLA is necessary mainly because you own the
-copyright to your changes, even after your contribution becomes part of our
-codebase, so we need your permission to use and distribute your code. We also
-need to be sure of various other things—for instance that you'll tell us if you
-know that your code infringes on other people's patents. You don't have to sign
-the CLA until after you've submitted your code for review and a member has
-approved it, but you must do it before we can put your code into our codebase.
-Before you start working on a larger contribution, you should get in touch with
-us first through the issue tracker with your idea so that we can help out and
-possibly guide you. Coordinating up front makes it much easier to avoid
-frustration later on.
-
-### Code reviews
-All submissions, including submissions by project members, require review. We
-use Github pull requests for this purpose.
-
-### The small print
-Contributions made by corporations are covered by a different agreement than
-the one above, the
-[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate).
diff --git a/chromium/third_party/cld_3/src/LICENSE b/chromium/third_party/cld_3/src/LICENSE
deleted file mode 100644
index c5899b26feb..00000000000
--- a/chromium/third_party/cld_3/src/LICENSE
+++ /dev/null
@@ -1,203 +0,0 @@
-Copyright 2016 Google Inc. All rights reserved.
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright 2016, Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/chromium/third_party/cld_3/src/README.md b/chromium/third_party/cld_3/src/README.md
deleted file mode 100644
index 86008330c43..00000000000
--- a/chromium/third_party/cld_3/src/README.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# Compact Language Detector v3 (CLD3)
-
-* [Model](#model)
-* [Installation](#installation)
-* [Contact](#contact)
-* [Credits](#credits)
-
-### Model
-
-CLD3 is a neural network model for language identification. This package
- contains the inference code and a trained model. The inference code
- extracts character ngrams from the input text and computes the fraction
- of times each of them appears. For example, as shown in the figure below,
- if the input text is "banana", then one of the extracted trigrams is "ana"
- and the corresponding fraction is 2/4. The ngrams are hashed down to an id
- within a small range, and each id is represented by a dense embedding vector
- estimated during training.
-
-The model averages the embeddings corresponding to each ngram type according
- to the fractions, and the averaged embeddings are concatenated to produce
- the embedding layer. The remaining components of the network are a hidden
- (Rectified linear) layer and a softmax layer.
-
-To get a language prediction for the input text, we simply perform a forward
- pass through the network.
-
-![Figure](model.png "CLD3")
-
-### Installation
-CLD3 is designed to run in the Chrome browser, so it relies on code in
-[Chromium](http://www.chromium.org/).
-The steps for building and running the demo of the language detection model are:
-
-- [check out](http://www.chromium.org/developers/how-tos/get-the-code) the
- Chromium repository.
-- copy the code to `//third_party/cld_3`
-- Uncomment `language_identifier_main` executable in `src/BUILD.gn`.
-- build and run the model using the commands:
-
-```shell
-gn gen out/Default
-ninja -C out/Default third_party/cld_3/src/src:language_identifier_main
-out/Default/language_identifier_main
-```
-### Bugs and Feature Requests
-
-Open a [GitHub issue](https://github.com/google/cld3/issues) for this repository to file bugs and feature requests.
-
-### Announcements and Discussion
-
-For announcements regarding major updates as well as general discussion list, please subscribe to:
-[cld3-users@googlegroups.com](https://groups.google.com/forum/#!forum/cld3-users)
-
-### Credits
-
-Original authors of the code in this package include (in alphabetical order):
-
-* Alex Salcianu
-* Andy Golding
-* Anton Bakalov
-* Chris Alberti
-* Daniel Andor
-* David Weiss
-* Emily Pitler
-* Greg Coppola
-* Jason Riesa
-* Kuzman Ganchev
-* Michael Ringgaard
-* Nan Hua
-* Ryan McDonald
-* Slav Petrov
-* Stefan Istrate
-* Terry Koo
diff --git a/chromium/third_party/cld_3/src/model.png b/chromium/third_party/cld_3/src/model.png
deleted file mode 100644
index 87f0f14db0b..00000000000
--- a/chromium/third_party/cld_3/src/model.png
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/cld_3/src/src/DEPS b/chromium/third_party/cld_3/src/src/DEPS
deleted file mode 100644
index e00022d82b9..00000000000
--- a/chromium/third_party/cld_3/src/src/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- '+cld_3',
- '+script_span',
-] \ No newline at end of file
diff --git a/chromium/third_party/cld_3/src/src/base.cc b/chromium/third_party/cld_3/src/src/base.cc
deleted file mode 100644
index aaa363c9c6d..00000000000
--- a/chromium/third_party/cld_3/src/src/base.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "base.h"
-
-#include <string>
-#if defined(COMPILER_MSVC) || defined(_WIN32)
-#include <sstream>
-#endif // defined(COMPILER_MSVC) || defined(_WIN32)
-
-namespace chrome_lang_id {
-
-// TODO(abakalov): Pick the most efficient approach.
-#if defined(COMPILER_MSVC) || defined(_WIN32)
-std::string Int64ToString(int64 input) {
- std::stringstream stream;
- stream << input;
- return stream.str();
-}
-#else
-std::string Int64ToString(int64 input) { return std::to_string(input); }
-#endif // defined(COMPILER_MSVC) || defined(_WIN32)
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/base.h b/chromium/third_party/cld_3/src/src/base.h
deleted file mode 100644
index 20189e2cd09..00000000000
--- a/chromium/third_party/cld_3/src/src/base.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef BASE_H_
-#define BASE_H_
-
-#include <cassert>
-#include <map>
-#include <string>
-#include <vector>
-
-namespace chrome_lang_id {
-
-using std::vector;
-using std::string;
-using std::map;
-using std::pair;
-typedef unsigned int uint32;
-
-#if LANG_CXX11
-#define CLD3_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName &) = delete; \
- TypeName &operator=(const TypeName &) = delete
-#else // C++98 case follows
-
-// Note that these C++98 implementations cannot completely disallow copying,
-// as members and friends can still accidentally make elided copies without
-// triggering a linker error.
-#define CLD3_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName &); \
- TypeName &operator=(const TypeName &)
-#endif // LANG_CXX11
-
-#ifndef CLD3_IMMEDIATE_CRASH
-#if defined(__GNUC__) || defined(__clang__)
-#define CLD3_IMMEDIATE_CRASH() __builtin_trap()
-#else
-#define CLD3_IMMEDIATE_CRASH() ((void)(*(volatile char *)0 = 0))
-#endif
-#endif // CLD3_IMMEDIATE_CRASH
-
-#define CLD3_CHECK(f) (!(f) ? CLD3_IMMEDIATE_CRASH() : (void)0)
-
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-#define CLD3_DCHECK(f) ((void)0)
-#else
-#define CLD3_DCHECK(f) CLD3_CHECK(f)
-#endif
-
-#ifndef SWIG
-typedef int int32;
-typedef unsigned char uint8; // NOLINT
-typedef unsigned short uint16; // NOLINT
-
-// A type to represent a Unicode code-point value. As of Unicode 4.0,
-// such values require up to 21 bits.
-// (For type-checking on pointers, make this explicitly signed,
-// and it should always be the signed version of whatever int32 is.)
-typedef signed int char32;
-#endif // SWIG
-
-#ifdef COMPILER_MSVC
-typedef __int64 int64;
-#else
-typedef long long int64; // NOLINT
-#endif // COMPILER_MSVC
-
-#if defined(__GNUC__) && \
- (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
-
-// For functions we want to force inline.
-// Introduced in gcc 3.1.
-#define CLD3_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
-
-#elif defined(_MSC_VER)
-#define CLD3_ATTRIBUTE_ALWAYS_INLINE __forceinline
-#else
-
-// Other compilers will have to figure it out for themselves.
-#define CLD3_ATTRIBUTE_ALWAYS_INLINE
-#endif
-
-#ifdef INTERNAL_BUILD
-typedef basic_string<char> bstring;
-#else
-typedef std::basic_string<char> bstring;
-#endif // INTERNAL_BUILD
-
-// Converts int64 to string.
-std::string Int64ToString(int64 input);
-
-} // namespace chrome_lang_id
-
-#endif // BASE_H_
diff --git a/chromium/third_party/cld_3/src/src/casts.h b/chromium/third_party/cld_3/src/src/casts.h
deleted file mode 100644
index 4c9ecd788a1..00000000000
--- a/chromium/third_party/cld_3/src/src/casts.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// This code is compiled directly on many platforms, including client
-// platforms like Windows, Mac, and embedded systems. Before making
-// any changes here, make sure that you're not breaking any platforms.
-//
-
-#ifndef CASTS_H_
-#define CASTS_H_
-
-#include <string.h> // for memcpy
-
-namespace chrome_lang_id {
-
-// lang_id_bit_cast<Dest,Source> is a template function that implements the
-// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in
-// very low-level functions like the protobuf library and fast math
-// support.
-//
-// float f = 3.14159265358979;
-// int i = lang_id_bit_cast<int32>(f);
-// // i = 0x40490fdb
-//
-// The classical address-casting method is:
-//
-// // WRONG
-// float f = 3.14159265358979; // WRONG
-// int i = * reinterpret_cast<int*>(&f); // WRONG
-//
-// The address-casting method actually produces undefined behavior
-// according to ISO C++ specification section 3.10 -15 -. Roughly, this
-// section says: if an object in memory has one type, and a program
-// accesses it with a different type, then the result is undefined
-// behavior for most values of "different type".
-//
-// This is true for any cast syntax, either *(int*)&f or
-// *reinterpret_cast<int*>(&f). And it is particularly true for
-// conversions between integral lvalues and floating-point lvalues.
-//
-// The purpose of 3.10 -15- is to allow optimizing compilers to assume
-// that expressions with different types refer to different memory. gcc
-// 4.0.1 has an optimizer that takes advantage of this. So a
-// non-conforming program quietly produces wildly incorrect output.
-//
-// The problem is not the use of reinterpret_cast. The problem is type
-// punning: holding an object in memory of one type and reading its bits
-// back using a different type.
-//
-// The C++ standard is more subtle and complex than this, but that
-// is the basic idea.
-//
-// Anyways ...
-//
-// lang_id_bit_cast<> calls memcpy() which is blessed by the standard,
-// especially by the example in section 3.9 . Also, of course,
-// lang_id_bit_cast<> wraps up the nasty logic in one place.
-//
-// Fortunately memcpy() is very fast. In optimized mode, with a
-// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
-// code with the minimal amount of data movement. On a 32-bit system,
-// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
-// compiles to two loads and two stores.
-//
-// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
-//
-// WARNING: if Dest or Source is a non-POD type, the result of the memcpy
-// is likely to surprise you.
-//
-// Props to Bill Gibbons for the compile time assertion technique and
-// Art Komninos and Igor Tandetnik for the msvc experiments.
-//
-// -- mec 2005-10-17
-
-template <class Dest, class Source>
-inline Dest lang_id_bit_cast(const Source &source) {
- static_assert(sizeof(Dest) == sizeof(Source), "Sizes do not match");
-
- Dest dest;
- memcpy(&dest, &source, sizeof(dest));
- return dest;
-}
-
-} // namespace chrome_lang_id
-
-#endif // CASTS_H_
diff --git a/chromium/third_party/cld_3/src/src/embedding_feature_extractor.cc b/chromium/third_party/cld_3/src/src/embedding_feature_extractor.cc
deleted file mode 100644
index 16692b3937d..00000000000
--- a/chromium/third_party/cld_3/src/src/embedding_feature_extractor.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "embedding_feature_extractor.h"
-
-#include <stddef.h>
-#include <vector>
-
-#include "feature_extractor.h"
-#include "feature_types.h"
-#include "task_context.h"
-#include "utils.h"
-
-namespace chrome_lang_id {
-
-GenericEmbeddingFeatureExtractor::GenericEmbeddingFeatureExtractor() {}
-
-GenericEmbeddingFeatureExtractor::~GenericEmbeddingFeatureExtractor() {}
-
-void GenericEmbeddingFeatureExtractor::Setup(TaskContext *context) {
- // Don't use version to determine how to get feature FML.
- string features_param = ArgPrefix();
- features_param += "_features";
- const string features = context->Get(features_param, "");
- const string embedding_names =
- context->Get(GetParamName("embedding_names"), "");
- const string embedding_dims =
- context->Get(GetParamName("embedding_dims"), "");
- embedding_fml_ = utils::Split(features, ';');
- add_strings_ = context->Get(GetParamName("add_varlen_strings"), false);
- embedding_names_ = utils::Split(embedding_names, ';');
- for (const string &dim : utils::Split(embedding_dims, ';')) {
- embedding_dims_.push_back(utils::ParseUsing<int>(dim, utils::ParseInt32));
- }
-}
-
-void GenericEmbeddingFeatureExtractor::Init(TaskContext *context) {}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/embedding_feature_extractor.h b/chromium/third_party/cld_3/src/src/embedding_feature_extractor.h
deleted file mode 100644
index 4ff3e52f740..00000000000
--- a/chromium/third_party/cld_3/src/src/embedding_feature_extractor.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef EMBEDDING_FEATURE_EXTRACTOR_H_
-#define EMBEDDING_FEATURE_EXTRACTOR_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "feature_extractor.h"
-#include "task_context.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-
-// An EmbeddingFeatureExtractor manages the extraction of features for
-// embedding-based models. It wraps a sequence of underlying classes of feature
-// extractors, along with associated predicate maps. Each class of feature
-// extractors is associated with a name, e.g., "unigrams", "bigrams".
-//
-// The class is split between a generic abstract version,
-// GenericEmbeddingFeatureExtractor (that can be initialized without knowing the
-// signature of the ExtractFeatures method) and a typed version.
-//
-// The predicate maps must be initialized before use: they can be loaded using
-// Read() or updated via UpdateMapsForExample.
-class GenericEmbeddingFeatureExtractor {
- public:
- GenericEmbeddingFeatureExtractor();
- virtual ~GenericEmbeddingFeatureExtractor();
-
- // Get the prefix string to put in front of all arguments, so they don't
- // conflict with other embedding models.
- virtual const string ArgPrefix() const = 0;
-
- // Sets up predicate maps and embedding space names that are common for all
- // embedding based feature extractors.
- virtual void Setup(TaskContext *context);
- virtual void Init(TaskContext *context);
-
- // Requests workspace for the underlying feature extractors. This is
- // implemented in the typed class.
- virtual void RequestWorkspaces(WorkspaceRegistry *registry) = 0;
-
- // Number of predicates for the embedding at a given index (vocabulary size.)
- int EmbeddingSize(int index) const {
- return generic_feature_extractor(index).GetDomainSize();
- }
-
- // Returns number of embedding spaces.
- int NumEmbeddings() const { return embedding_dims_.size(); }
-
- // Returns the number of features in the embedding space.
- int FeatureSize(int idx) const {
- return generic_feature_extractor(idx).feature_types();
- }
-
- // Returns the dimensionality of the embedding space.
- int EmbeddingDims(int index) const { return embedding_dims_[index]; }
-
- // Accessor for embedding dims (dimensions of the embedding spaces).
- const std::vector<int> &embedding_dims() const { return embedding_dims_; }
-
- const std::vector<string> &embedding_fml() const { return embedding_fml_; }
-
- // Get parameter name by concatenating the prefix and the original name.
- string GetParamName(const string &param_name) const {
- string name = ArgPrefix();
- name += "_";
- name += param_name;
- return name;
- }
-
- protected:
- // Provides the generic class with access to the templated extractors. This is
- // used to get the type information out of the feature extractor without
- // knowing the specific calling arguments of the extractor itself.
- virtual const GenericFeatureExtractor &generic_feature_extractor(
- int idx) const = 0;
-
- private:
- // Embedding space names for parameter sharing.
- std::vector<string> embedding_names_;
-
- // FML strings for each feature extractor.
- std::vector<string> embedding_fml_;
-
- // Size of each of the embedding spaces (maximum predicate id).
- std::vector<int> embedding_sizes_;
-
- // Embedding dimensions of the embedding spaces (i.e. 32, 64 etc.)
- std::vector<int> embedding_dims_;
-
- // Whether or not to add string descriptions to converted examples.
- bool add_strings_;
-};
-
-// Templated, object-specific implementation of the
-// EmbeddingFeatureExtractor. EXTRACTOR should be a FeatureExtractor<OBJ,
-// ARGS...> class that has the appropriate FeatureTraits() to ensure that
-// locator type features work.
-//
-// Note: for backwards compatibility purposes, this always reads the FML spec
-// from "<prefix>_features".
-template <class EXTRACTOR, class OBJ, class... ARGS>
-class EmbeddingFeatureExtractor : public GenericEmbeddingFeatureExtractor {
- public:
- // Sets up all predicate maps, feature extractors, and flags.
- void Setup(TaskContext *context) override {
- GenericEmbeddingFeatureExtractor::Setup(context);
- feature_extractors_.resize(embedding_fml().size());
- for (size_t i = 0; i < embedding_fml().size(); ++i) {
- feature_extractors_[i].Parse(embedding_fml()[i]);
- feature_extractors_[i].Setup(context);
- }
- }
-
- // Initializes resources needed by the feature extractors.
- void Init(TaskContext *context) override {
- GenericEmbeddingFeatureExtractor::Init(context);
- for (auto &feature_extractor : feature_extractors_) {
- feature_extractor.Init(context);
- }
- }
-
- // Requests workspaces from the registry. Must be called after Init(), and
- // before Preprocess().
- void RequestWorkspaces(WorkspaceRegistry *registry) override {
- for (auto &feature_extractor : feature_extractors_) {
- feature_extractor.RequestWorkspaces(registry);
- }
- }
-
- // Must be called on the object one state for each sentence, before any
- // feature extraction (e.g., UpdateMapsForExample, ExtractSparseFeatures).
- void Preprocess(WorkspaceSet *workspaces, OBJ *obj) const {
- for (auto &feature_extractor : feature_extractors_) {
- feature_extractor.Preprocess(workspaces, obj);
- }
- }
-
- // Extracts features using the extractors. Note that features must already
- // be initialized to the correct number of feature extractors. No predicate
- // mapping is applied.
- void ExtractFeatures(const WorkspaceSet &workspaces, const OBJ &obj,
- ARGS... args,
- std::vector<FeatureVector> *features) const {
- for (size_t i = 0; i < feature_extractors_.size(); ++i) {
- features->at(i).clear();
- feature_extractors_.at(i).ExtractFeatures(workspaces, obj, args...,
- &features->at(i));
- }
- }
-
- protected:
- // Provides generic access to the feature extractors.
- const GenericFeatureExtractor &generic_feature_extractor(
- int idx) const override {
- return feature_extractors_.at(idx);
- }
-
- private:
- // Templated feature extractor class.
- std::vector<EXTRACTOR> feature_extractors_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // EMBEDDING_FEATURE_EXTRACTOR_H_
diff --git a/chromium/third_party/cld_3/src/src/embedding_network.cc b/chromium/third_party/cld_3/src/src/embedding_network.cc
deleted file mode 100644
index f2e0801c267..00000000000
--- a/chromium/third_party/cld_3/src/src/embedding_network.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "embedding_network.h"
-
-#include "base.h"
-#include "embedding_network_params.h"
-#include "float16.h"
-#include "simple_adder.h"
-
-namespace chrome_lang_id {
-namespace {
-
-using VectorWrapper = EmbeddingNetwork::VectorWrapper;
-
-void CheckNoQuantization(const EmbeddingNetworkParams::Matrix matrix) {
- // Quantization not allowed here.
- CLD3_DCHECK(static_cast<int>(QuantizationType::NONE) ==
- static_cast<int>(matrix.quant_type));
-}
-
-// Fills a Matrix object with the parameters in the given MatrixParams. This
-// function is used to initialize weight matrices that are *not* embedding
-// matrices.
-void FillMatrixParams(const EmbeddingNetworkParams::Matrix source_matrix,
- EmbeddingNetwork::Matrix *mat) {
- mat->resize(source_matrix.rows);
- CheckNoQuantization(source_matrix);
- const float *weights =
- reinterpret_cast<const float *>(source_matrix.elements);
- for (int r = 0; r < source_matrix.rows; ++r) {
- (*mat)[r] = EmbeddingNetwork::VectorWrapper(weights, source_matrix.cols);
- weights += source_matrix.cols;
- }
-}
-
-// Computes y = weights * Relu(x) + b where Relu is optionally applied.
-template <typename ScaleAdderClass>
-void SparseReluProductPlusBias(bool apply_relu,
- const EmbeddingNetwork::Matrix &weights,
- const EmbeddingNetwork::VectorWrapper &b,
- const EmbeddingNetwork::Vector &x,
- EmbeddingNetwork::Vector *y) {
- y->assign(b.data(), b.data() + b.size());
- ScaleAdderClass adder(y->data(), y->size());
-
- const int x_size = x.size();
- for (int i = 0; i < x_size; ++i) {
- const float &scale = x[i];
- if (apply_relu) {
- if (scale > 0) {
- adder.LazyScaleAdd(weights[i].data(), scale);
- }
- } else {
- adder.LazyScaleAdd(weights[i].data(), scale);
- }
- }
- adder.Finalize();
-}
-} // namespace
-
-void EmbeddingNetwork::ConcatEmbeddings(
- const std::vector<FeatureVector> &feature_vectors, Vector *concat) const {
- concat->resize(model_->concat_layer_size());
-
- // "es_index" stands for "embedding space index".
- for (size_t es_index = 0; es_index < feature_vectors.size(); ++es_index) {
- const int concat_offset = model_->concat_offset(es_index);
- const int embedding_dim = model_->embedding_dim(es_index);
-
- const EmbeddingMatrix &embedding_matrix = embedding_matrices_[es_index];
- CLD3_DCHECK(embedding_matrix.dim() == embedding_dim);
-
- const bool is_quantized =
- embedding_matrix.quant_type() != QuantizationType::NONE;
-
- const FeatureVector &feature_vector = feature_vectors[es_index];
- const int num_features = feature_vector.size();
- for (int fi = 0; fi < num_features; ++fi) {
- const FeatureType *feature_type = feature_vector.type(fi);
- int feature_offset = concat_offset + feature_type->base() * embedding_dim;
- CLD3_DCHECK(feature_offset + embedding_dim <=
- static_cast<int>(concat->size()));
-
- // Weighted embeddings will be added starting from this address.
- float *concat_ptr = concat->data() + feature_offset;
-
- // Pointer to float / uint8 weights for relevant embedding.
- const void *embedding_data;
-
- // Multiplier for each embedding weight.
- float multiplier;
- const FeatureValue feature_value = feature_vector.value(fi);
- if (feature_type->is_continuous()) {
- // Continuous features (encoded as FloatFeatureValue).
- FloatFeatureValue float_feature_value(feature_value);
- const int id = float_feature_value.value.id;
- embedding_matrix.get_embedding(id, &embedding_data, &multiplier);
- multiplier *= float_feature_value.value.weight;
- } else {
- // Discrete features: every present feature has implicit value 1.0.
- embedding_matrix.get_embedding(feature_value, &embedding_data,
- &multiplier);
- }
-
- if (is_quantized) {
- const uint8 *quant_weights =
- reinterpret_cast<const uint8 *>(embedding_data);
- for (int i = 0; i < embedding_dim; ++i, ++quant_weights, ++concat_ptr) {
- // 128 is bias for UINT8 quantization, only one we currently support.
- *concat_ptr += (static_cast<int>(*quant_weights) - 128) * multiplier;
- }
- } else {
- const float *weights = reinterpret_cast<const float *>(embedding_data);
- for (int i = 0; i < embedding_dim; ++i, ++weights, ++concat_ptr) {
- *concat_ptr += *weights * multiplier;
- }
- }
- }
- }
-}
-
-template <typename ScaleAdderClass>
-void EmbeddingNetwork::FinishComputeFinalScores(const Vector &concat,
- Vector *scores) const {
- Vector h0(hidden_bias_[0].size());
- SparseReluProductPlusBias<ScaleAdderClass>(false, hidden_weights_[0],
- hidden_bias_[0], concat, &h0);
-
- CLD3_DCHECK((hidden_weights_.size() == 1) || (hidden_weights_.size() == 2));
- if (hidden_weights_.size() == 1) { // 1 hidden layer
- SparseReluProductPlusBias<ScaleAdderClass>(true, softmax_weights_,
- softmax_bias_, h0, scores);
- } else if (hidden_weights_.size() == 2) { // 2 hidden layers
- Vector h1(hidden_bias_[1].size());
- SparseReluProductPlusBias<ScaleAdderClass>(true, hidden_weights_[1],
- hidden_bias_[1], h0, &h1);
- SparseReluProductPlusBias<ScaleAdderClass>(true, softmax_weights_,
- softmax_bias_, h1, scores);
- }
-}
-
-void EmbeddingNetwork::ComputeFinalScores(
- const std::vector<FeatureVector> &features, Vector *scores) const {
- Vector concat;
- ConcatEmbeddings(features, &concat);
-
- scores->resize(softmax_bias_.size());
- FinishComputeFinalScores<SimpleAdder>(concat, scores);
-}
-
-EmbeddingNetwork::EmbeddingNetwork(const EmbeddingNetworkParams *model)
- : model_(model) {
- int offset_sum = 0;
- for (int i = 0; i < model_->embedding_dim_size(); ++i) {
- CLD3_DCHECK(offset_sum == model_->concat_offset(i));
- offset_sum += model_->embedding_dim(i) * model_->embedding_num_features(i);
- embedding_matrices_.emplace_back(model_->GetEmbeddingMatrix(i));
- }
-
- CLD3_DCHECK(model_->hidden_size() == model_->hidden_bias_size());
- hidden_weights_.resize(model_->hidden_size());
- hidden_bias_.resize(model_->hidden_size());
- for (int i = 0; i < model_->hidden_size(); ++i) {
- FillMatrixParams(model_->GetHiddenLayerMatrix(i), &hidden_weights_[i]);
- EmbeddingNetworkParams::Matrix bias = model_->GetHiddenLayerBias(i);
- CLD3_DCHECK(1 == bias.cols);
- CheckNoQuantization(bias);
- hidden_bias_[i] = VectorWrapper(
- reinterpret_cast<const float *>(bias.elements), bias.rows);
- }
-
- CLD3_DCHECK(model_->HasSoftmax());
- FillMatrixParams(model_->GetSoftmaxMatrix(), &softmax_weights_);
-
- EmbeddingNetworkParams::Matrix softmax_bias = model_->GetSoftmaxBias();
- CLD3_DCHECK(1 == softmax_bias.cols);
- CheckNoQuantization(softmax_bias);
- softmax_bias_ =
- VectorWrapper(reinterpret_cast<const float *>(softmax_bias.elements),
- softmax_bias.rows);
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/embedding_network.h b/chromium/third_party/cld_3/src/src/embedding_network.h
deleted file mode 100644
index af11e89e3dd..00000000000
--- a/chromium/third_party/cld_3/src/src/embedding_network.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef EMBEDDING_NETWORK_H_
-#define EMBEDDING_NETWORK_H_
-
-#include <vector>
-
-#include "embedding_network_params.h"
-#include "feature_extractor.h"
-#include "float16.h"
-
-namespace chrome_lang_id {
-
-// Classifier using a hand-coded feed-forward neural network.
-//
-// No gradient computation, just inference.
-//
-// Based on the more general nlp_saft::EmbeddingNetwork.
-//
-// Classification works as follows:
-//
-// Discrete features -> Embeddings -> Concatenation -> Hidden+ -> Softmax
-//
-// In words: given some discrete features, this class extracts the embeddings
-// for these features, concatenates them, passes them through one or two hidden
-// layers (each layer uses Relu) and next through a softmax layer that computes
-// an unnormalized score for each possible class. Note: there is always a
-// softmax layer.
-//
-// NOTE(salcianu): current code can easily be changed to allow more than two
-// hidden layers. Feel free to do so if you have a genuine need for that.
-class EmbeddingNetwork {
- public:
- // Class used to represent an embedding matrix. Each row is the embedding on
- // a vocabulary element. Number of columns = number of embedding dimensions.
- class EmbeddingMatrix {
- public:
- explicit EmbeddingMatrix(const EmbeddingNetworkParams::Matrix source_matrix)
- : rows_(source_matrix.rows),
- cols_(source_matrix.cols),
- quant_type_(source_matrix.quant_type),
- data_(source_matrix.elements),
- row_size_in_bytes_(GetRowSizeInBytes(cols_, quant_type_)),
- quant_scales_(source_matrix.quant_scales) {}
-
- // Returns vocabulary size; one embedding for each vocabulary element.
- int size() const { return rows_; }
-
- // Returns number of weights in embedding of each vocabulary element.
- int dim() const { return cols_; }
-
- // Returns quantization type for this embedding matrix.
- QuantizationType quant_type() const { return quant_type_; }
-
- // Gets embedding for k-th vocabulary element: on return, sets *data to
- // point to the embedding weights and *scale to the quantization scale (1.0
- // if no quantization).
- void get_embedding(int k, const void **data, float *scale) const {
- CLD3_CHECK(k >= 0);
- CLD3_CHECK(k < size());
- *data = reinterpret_cast<const char *>(data_) + k * row_size_in_bytes_;
- if (quant_type_ == QuantizationType::NONE) {
- *scale = 1.0;
- } else {
- *scale = Float16To32(quant_scales_[k]);
- }
- }
-
- private:
- static int GetRowSizeInBytes(int cols, QuantizationType quant_type) {
- CLD3_DCHECK((quant_type == QuantizationType::NONE) ||
- (quant_type == QuantizationType::UINT8));
- if (quant_type == QuantizationType::NONE) {
- return cols * sizeof(float);
- } else { // QuantizationType::UINT8
- return cols * sizeof(uint8);
- }
- }
-
- // Vocabulary size.
- int rows_;
-
- // Number of elements in each embedding.
- int cols_;
-
- QuantizationType quant_type_;
-
- // Pointer to the embedding weights, in row-major order. This is a pointer
- // to an array of floats / uint8, depending on the quantization type.
- // Not owned.
- const void *data_;
-
- // Number of bytes for one row. Used to jump to next row in data_.
- int row_size_in_bytes_;
-
- // Pointer to quantization scales. nullptr if no quantization. Otherwise,
- // quant_scales_[i] is scale for embedding of i-th vocabulary element.
- const float16 *quant_scales_;
- };
-
- // An immutable vector that doesn't own the memory that stores the underlying
- // floats. Can be used e.g., as a wrapper around model weights stored in the
- // static memory.
- class VectorWrapper {
- public:
- VectorWrapper() : VectorWrapper(nullptr, 0) {}
-
- // Constructs a vector wrapper around the size consecutive floats that start
- // at address data. Note: the underlying data should be alive for at least
- // the lifetime of this VectorWrapper object. That's trivially true if data
- // points to statically allocated data :)
- VectorWrapper(const float *data, int size) : data_(data), size_(size) {}
-
- int size() const { return size_; }
-
- const float *data() const { return data_; }
-
- private:
- const float *data_; // Not owned.
- int size_;
-
- // Doesn't own anything, so it can be copied and assigned at will :)
- };
-
- typedef std::vector<VectorWrapper> Matrix;
- typedef std::vector<float> Vector;
-
- // Constructs an embedding network using the parameters from model.
- //
- // Note: model should stay alive for at least the lifetime of this
- // EmbeddingNetwork object. TODO(salcianu): remove this constraint: we should
- // copy all necessary data (except, of course, the static weights) at
- // construction time and use that, instead of relying on model.
- explicit EmbeddingNetwork(const EmbeddingNetworkParams *model);
-
- virtual ~EmbeddingNetwork() {}
-
- // Runs forward computation to fill scores with unnormalized output unit
- // scores. This is useful for making predictions.
- void ComputeFinalScores(const std::vector<FeatureVector> &features,
- Vector *scores) const;
-
- private:
- // Computes the softmax scores (prior to normalization) from the concatenated
- // representation.
- template <typename ScaleAdderClass>
- void FinishComputeFinalScores(const Vector &concat, Vector *scores) const;
-
- // Constructs the concatenated input embedding vector in place in output
- // vector concat.
- void ConcatEmbeddings(const std::vector<FeatureVector> &features,
- Vector *concat) const;
-
- // Pointer to the model object passed to the constructor. Not owned.
- const EmbeddingNetworkParams *model_;
-
- // Network parameters.
-
- // One weight matrix for each embedding.
- std::vector<EmbeddingMatrix> embedding_matrices_;
-
- // One weight matrix and one vector of bias weights for each hiden layer.
- std::vector<Matrix> hidden_weights_;
- std::vector<VectorWrapper> hidden_bias_;
-
- // Weight matrix and bias vector for the softmax layer.
- Matrix softmax_weights_;
- VectorWrapper softmax_bias_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // EMBEDDING_NETWORK_H_
diff --git a/chromium/third_party/cld_3/src/src/embedding_network_params.h b/chromium/third_party/cld_3/src/src/embedding_network_params.h
deleted file mode 100644
index 447e0bb2fa0..00000000000
--- a/chromium/third_party/cld_3/src/src/embedding_network_params.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef EMBEDDING_NETWORK_PARAMS_H_
-#define EMBEDDING_NETWORK_PARAMS_H_
-
-#include <string>
-
-#include "base.h"
-#include "float16.h"
-
-namespace chrome_lang_id {
-
-enum class QuantizationType { NONE = 0, UINT8 };
-
-// API for accessing parameters from a statically-linked EmbeddingNetworkProto.
-class EmbeddingNetworkParams {
- public:
- virtual ~EmbeddingNetworkParams() {}
-
- // **** High-level API.
-
- // Simple representation of a matrix. This small struct that doesn't own any
- // resource intentionally supports copy / assign, to simplify our APIs.
- struct Matrix {
- // Number of rows.
- int rows;
-
- // Number of columns.
- int cols;
-
- QuantizationType quant_type;
-
- // Pointer to matrix elements, in row-major order
- // (https://en.wikipedia.org/wiki/Row-major_order) Not owned.
- const void *elements;
-
- // Quantization scales: one scale for each row.
- const float16 *quant_scales;
- };
-
- // Returns i-th embedding matrix. Crashes on out of bounds indices.
- //
- // This is the transpose of the corresponding matrix from the original proto.
- Matrix GetEmbeddingMatrix(int i) const {
- CheckMatrixRange(i, embeddings_size(), "embedding matrix");
- Matrix matrix;
- matrix.rows = embeddings_num_rows(i);
- matrix.cols = embeddings_num_cols(i);
- matrix.elements = embeddings_weights(i);
- matrix.quant_type = embeddings_quant_type(i);
- matrix.quant_scales = embeddings_quant_scales(i);
- return matrix;
- }
-
- // Returns weight matrix for i-th hidden layer. Crashes on out of bounds
- // indices.
- //
- // This is the transpose of the corresponding matrix from the original proto.
- Matrix GetHiddenLayerMatrix(int i) const {
- CheckMatrixRange(i, hidden_size(), "hidden layer");
- Matrix matrix;
- matrix.rows = hidden_num_rows(i);
- matrix.cols = hidden_num_cols(i);
-
- // Quantization not supported here.
- matrix.quant_type = QuantizationType::NONE;
- matrix.elements = hidden_weights(i);
- return matrix;
- }
-
- // Returns bias for i-th hidden layer. Technically a Matrix, but we expect it
- // to be a row/column vector (i.e., num rows or num cols is 1). However, we
- // don't CHECK for that: we just provide access to underlying data. Crashes
- // on out of bounds indices.
- Matrix GetHiddenLayerBias(int i) const {
- CheckMatrixRange(i, hidden_bias_size(), "hidden layer bias");
- Matrix matrix;
- matrix.rows = hidden_bias_num_rows(i);
- matrix.cols = hidden_bias_num_cols(i);
-
- // Quantization not supported here.
- matrix.quant_type = QuantizationType::NONE;
- matrix.elements = hidden_bias_weights(i);
- return matrix;
- }
-
- // Returns true if a softmax layer exists.
- bool HasSoftmax() const { return softmax_size() == 1; }
-
- // Returns weight matrix for the softmax layer. Note: should be called only
- // if HasSoftmax() is true.
- //
- // This is the transpose of the corresponding matrix from the original proto.
- Matrix GetSoftmaxMatrix() const {
- CLD3_DCHECK(HasSoftmax());
- Matrix matrix;
- matrix.rows = softmax_num_rows(0);
- matrix.cols = softmax_num_cols(0);
-
- // Quantization not supported here.
- matrix.quant_type = QuantizationType::NONE;
- matrix.elements = softmax_weights(0);
- return matrix;
- }
-
- // Returns bias for the softmax layer. Technically a Matrix, but we expect it
- // to be a row/column vector (i.e., num rows or num cols is 1). However, we
- // don't CHECK for that: we just provide access to underlying data.
- Matrix GetSoftmaxBias() const {
- CLD3_DCHECK(HasSoftmax());
- Matrix matrix;
- matrix.rows = softmax_bias_num_rows(0);
- matrix.cols = softmax_bias_num_cols(0);
-
- // Quantization not supported here.
- matrix.quant_type = QuantizationType::NONE;
- matrix.elements = softmax_bias_weights(0);
- return matrix;
- }
-
- // **** Low-level API.
- //
- // * Most low-level API methods are documented by giving an equivalent
- // function call on proto, the original proto (of type
- // EmbeddingNetworkProto) which was used to generate the C++ code.
- //
- // * To simplify our generation code, optional proto fields of message type
- // are treated as repeated fields with 0 or 1 instances. As such, we have
- // *_size() methods for such optional fields: they return 0 or 1.
- //
- // * "transpose(M)" denotes the transpose of a matrix M.
-
- // ** Access methods for repeated MatrixParams embeddings.
- //
- // Returns proto.embeddings_size().
- virtual int embeddings_size() const = 0;
-
- // Returns number of rows of transpose(proto.embeddings(i)).
- virtual int embeddings_num_rows(int i) const = 0;
-
- // Returns number of columns of transpose(proto.embeddings(i)).
- virtual int embeddings_num_cols(int i) const = 0;
-
- // Returns pointer to elements of transpose(proto.embeddings(i)), in row-major
- // order.
- virtual const void *embeddings_weights(int i) const = 0;
-
- virtual QuantizationType embeddings_quant_type(int i) const {
- return QuantizationType::NONE;
- }
-
- virtual const float16 *embeddings_quant_scales(int i) const {
- return nullptr;
- }
-
- // ** Access methods for repeated MatrixParams hidden.
- //
- // Returns embedding_network_proto.hidden_size().
- virtual int hidden_size() const = 0;
-
- // Returns embedding_network_proto.hidden(i).rows().
- virtual int hidden_num_rows(int i) const = 0;
-
- // Returns embedding_network_proto.hidden(i).rows().
- virtual int hidden_num_cols(int i) const = 0;
-
- // Returns pointer to beginning of array of floats with all values from
- // embedding_network_proto.hidden(i).
- virtual const void *hidden_weights(int i) const = 0;
-
- // ** Access methods for repeated MatrixParams hidden_bias.
- //
- // Returns proto.hidden_bias_size().
- virtual int hidden_bias_size() const = 0;
-
- // Returns number of rows of proto.hidden_bias(i).
- virtual int hidden_bias_num_rows(int i) const = 0;
-
- // Returns number of columns of proto.hidden_bias(i).
- virtual int hidden_bias_num_cols(int i) const = 0;
-
- // Returns pointer to elements of proto.hidden_bias(i), in row-major order.
- virtual const void *hidden_bias_weights(int i) const = 0;
-
- // ** Access methods for optional MatrixParams softmax.
- //
- // Returns 1 if proto has optional field softmax, 0 otherwise.
- virtual int softmax_size() const = 0;
-
- // Returns number of rows of transpose(proto.softmax()).
- virtual int softmax_num_rows(int i) const = 0;
-
- // Returns number of columns of transpose(proto.softmax()).
- virtual int softmax_num_cols(int i) const = 0;
-
- // Returns pointer to elements of transpose(proto.softmax()), in row-major
- // order.
- virtual const void *softmax_weights(int i) const = 0;
-
- // ** Access methods for optional MatrixParams softmax_bias.
- //
- // Returns 1 if proto has optional field softmax_bias, 0 otherwise.
- virtual int softmax_bias_size() const = 0;
-
- // Returns number of rows of proto.softmax_bias().
- virtual int softmax_bias_num_rows(int i) const = 0;
-
- // Returns number of columns of proto.softmax_bias().
- virtual int softmax_bias_num_cols(int i) const = 0;
-
- // Returns pointer to elements of proto.softmax_bias(), in row-major order.
- virtual const void *softmax_bias_weights(int i) const = 0;
-
- // ** Access methods for repeated int32 embedding_dim.
- //
- // Returns proto.embedding_dim_size().
- virtual int embedding_dim_size() const = 0;
-
- // Returns proto.embedding_dim(i).
- virtual int embedding_dim(int i) const = 0;
-
- // ** Access methods for repeated int32 embedding_num_features.
- //
- // Returns proto.embedding_num_features_size().
- virtual int embedding_num_features_size() const = 0;
-
- // Returns proto.embedding_num_features(i).
- virtual int embedding_num_features(int i) const = 0;
-
- // ** Access methods for repeated int32 embedding_features_domain_size.
- //
- // Returns proto.embedding_features_domain_size_size().
- virtual int embedding_features_domain_size_size() const = 0;
-
- // Returns proto.embedding_features_domain_size(i).
- virtual int embedding_features_domain_size(int i) const = 0;
-
- // ** Access methods for repeated int32 concat_offset.
- //
- // Returns proto.concat_offset_size().
- virtual int concat_offset(int i) const = 0;
-
- // Returns proto.concat_offset(i).
- virtual int concat_offset_size() const = 0;
-
- // ** Access methods for concat_layer_size.
- //
- // Returns proto.has_concat_layer_size().
- virtual bool has_concat_layer_size() const = 0;
-
- // Returns proto.concat_layer_size().
- virtual int concat_layer_size() const = 0;
-
- // ** Access methods for is_precomputed
- //
- // Returns proto.has_is_precomputed().
- virtual bool has_is_precomputed() const = 0;
-
- // Returns proto.is_precomputed().
- virtual bool is_precomputed() const = 0;
-
- private:
- void CheckMatrixRange(int index, int num_matrices,
- const string &description) const {
- CLD3_DCHECK(index >= 0);
- CLD3_DCHECK(index < num_matrices);
- }
-}; // class EmbeddingNetworkParams
-
-} // namespace chrome_lang_id
-
-#endif // EMBEDDING_NETWORK_PARAMS_H_
diff --git a/chromium/third_party/cld_3/src/src/feature_extractor.cc b/chromium/third_party/cld_3/src/src/feature_extractor.cc
deleted file mode 100644
index 10d1348725a..00000000000
--- a/chromium/third_party/cld_3/src/src/feature_extractor.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "feature_extractor.h"
-
-#include <string>
-
-#include "feature_types.h"
-#include "fml_parser.h"
-#include "utils.h"
-
-namespace chrome_lang_id {
-
-constexpr FeatureValue GenericFeatureFunction::kNone;
-
-FeatureVector::FeatureVector() {}
-
-FeatureVector::~FeatureVector() {}
-
-GenericFeatureExtractor::GenericFeatureExtractor() {}
-
-GenericFeatureExtractor::~GenericFeatureExtractor() {}
-
-GenericFeatureExtractor::GenericFeatureExtractor(
- const GenericFeatureExtractor &extractor)
- : descriptor_(extractor.descriptor_),
- feature_types_(extractor.feature_types_) {}
-
-void GenericFeatureExtractor::Parse(const string &source) {
- // Parse feature specification into descriptor.
- FMLParser parser;
- parser.Parse(source, mutable_descriptor());
-
- // Initialize feature extractor from descriptor.
- InitializeFeatureFunctions();
-}
-
-void GenericFeatureExtractor::InitializeFeatureTypes() {
- // Register all feature types.
- GetFeatureTypes(&feature_types_);
- for (size_t i = 0; i < feature_types_.size(); ++i) {
- FeatureType *ft = feature_types_[i];
- ft->set_base(i);
-
- // Check for feature space overflow.
- CLD3_DCHECK(ft->GetDomainSize() >= 0);
- }
-
- std::vector<string> types_names;
- GetFeatureTypeNames(&types_names);
- CLD3_DCHECK(feature_types_.size() == types_names.size());
-}
-
-void GenericFeatureExtractor::GetFeatureTypeNames(
- std::vector<string> *type_names) const {
- for (size_t i = 0; i < feature_types_.size(); ++i) {
- FeatureType *ft = feature_types_[i];
- type_names->push_back(ft->name());
- }
-}
-
-FeatureValue GenericFeatureExtractor::GetDomainSize() const {
- // Domain size of the set of features is equal to:
- // [largest domain size of any feature types] * [number of feature types]
- FeatureValue max_feature_type_dsize = 0;
- for (size_t i = 0; i < feature_types_.size(); ++i) {
- FeatureType *ft = feature_types_[i];
- const FeatureValue feature_type_dsize = ft->GetDomainSize();
- if (feature_type_dsize > max_feature_type_dsize) {
- max_feature_type_dsize = feature_type_dsize;
- }
- }
-
- return max_feature_type_dsize;
-}
-
-string GenericFeatureFunction::GetParameter(const string &name) const {
- // Find named parameter in feature descriptor.
- for (int i = 0; i < descriptor_->parameter_size(); ++i) {
- if (name == descriptor_->parameter(i).name()) {
- return descriptor_->parameter(i).value();
- }
- }
- return "";
-}
-
-GenericFeatureFunction::GenericFeatureFunction() {}
-
-GenericFeatureFunction::~GenericFeatureFunction() { delete feature_type_; }
-
-int GenericFeatureFunction::GetIntParameter(const string &name,
- int default_value) const {
- string value = GetParameter(name);
- return value.empty() ? default_value
- : utils::ParseUsing<int>(value, utils::ParseInt32);
-}
-
-bool GenericFeatureFunction::GetBoolParameter(const string &name,
- bool default_value) const {
- string value = GetParameter(name);
- if (value.empty()) return default_value;
- if (value == "true") return true;
- if (value == "false") return false;
- return false;
-}
-
-void GenericFeatureFunction::GetFeatureTypes(
- std::vector<FeatureType *> *types) const {
- if (feature_type_ != nullptr) types->push_back(feature_type_);
-}
-
-FeatureType *GenericFeatureFunction::GetFeatureType() const {
- // If a single feature type has been registered return it.
- if (feature_type_ != nullptr) return feature_type_;
-
- // Get feature types for function.
- std::vector<FeatureType *> types;
- GetFeatureTypes(&types);
-
- // If there is exactly one feature type return this, else return null.
- if (types.size() == 1) return types[0];
- return nullptr;
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/feature_extractor.h b/chromium/third_party/cld_3/src/src/feature_extractor.h
deleted file mode 100644
index 81c7766a1ee..00000000000
--- a/chromium/third_party/cld_3/src/src/feature_extractor.h
+++ /dev/null
@@ -1,633 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Generic feature extractor for extracting features from objects. The feature
-// extractor can be used for extracting features from any object. The feature
-// extractor and feature function classes are template classes that have to
-// be instantiated for extracting feature from a specific object type.
-//
-// A feature extractor consists of a hierarchy of feature functions. Each
-// feature function extracts one or more feature type and value pairs from the
-// object.
-//
-// The feature extractor has a modular design where new feature functions can be
-// registered as components. The feature extractor is initialized from a
-// descriptor represented by a protocol buffer. The feature extractor can also
-// be initialized from a text-based source specification of the feature
-// extractor. Feature specification parsers can be added as components. By
-// default the feature extractor can be read from an ASCII protocol buffer or in
-// a simple feature modeling language (fml).
-
-// A feature function is invoked with a focus. Nested feature function can be
-// invoked with another focus determined by the parent feature function.
-
-#ifndef FEATURE_EXTRACTOR_H_
-#define FEATURE_EXTRACTOR_H_
-
-#include <stddef.h>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base.h"
-#include "cld_3/protos/feature_extractor.pb.h"
-#include "feature_types.h"
-#include "registry.h"
-#include "script_span/stringpiece.h"
-#include "task_context.h"
-#include "utils.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-
-// TODO(djweiss) Clean this up as well.
-// Use the same type for feature values as is used for predicated.
-typedef int64 Predicate;
-typedef Predicate FeatureValue;
-
-// Output feature model in FML format.
-void ToFMLFunction(const FeatureFunctionDescriptor &function, string *output);
-void ToFML(const FeatureFunctionDescriptor &function, string *output);
-
-// A union used to represent discrete and continuous feature values.
-union FloatFeatureValue {
- public:
- explicit FloatFeatureValue(FeatureValue v) : discrete_value(v) {}
- FloatFeatureValue(uint32 i, float w) {
- value.id = i;
- value.weight = w;
- }
- FeatureValue discrete_value;
- struct IdWeight {
- uint32 id;
- float weight;
- } value;
-};
-
-// A feature vector contains feature type and value pairs.
-class FeatureVector {
- public:
- FeatureVector();
- ~FeatureVector();
-
- // Adds feature type and value pair to feature vector.
- void add(FeatureType *type, FeatureValue value) {
- features_.emplace_back(type, value);
- }
-
- // Removes all elements from the feature vector.
- void clear() { features_.clear(); }
-
- // Returns the number of elements in the feature vector.
- int size() const { return features_.size(); }
-
- // Reserves space in the underlying feature vector.
- void reserve(int n) { features_.reserve(n); }
-
- // Returns feature type for an element in the feature vector.
- FeatureType *type(int index) const { return features_[index].type; }
-
- // Returns feature value for an element in the feature vector.
- FeatureValue value(int index) const { return features_[index].value; }
-
- private:
- // Structure for holding feature type and value pairs.
- struct Element {
- Element() : type(NULL), value(-1) {}
- Element(FeatureType *t, FeatureValue v) : type(t), value(v) {}
-
- FeatureType *type;
- FeatureValue value;
- };
-
- // Array for storing feature vector elements.
- std::vector<Element> features_;
-
- CLD3_DISALLOW_COPY_AND_ASSIGN(FeatureVector);
-};
-
-// The generic feature extractor is the type-independent part of a feature
-// extractor. This holds the descriptor for the feature extractor and the
-// collection of feature types used in the feature extractor. The feature
-// types are not available until FeatureExtractor<>::Init() has been called.
-class GenericFeatureExtractor {
- public:
- GenericFeatureExtractor();
- virtual ~GenericFeatureExtractor();
- GenericFeatureExtractor(const GenericFeatureExtractor &extractor);
-
- // Initializes the feature extractor from a source representation of the
- // feature extractor. The first line is used for determining the feature
- // specification language. If the first line starts with #! followed by a name
- // then this name is used for instantiating a feature specification parser
- // with that name. If the language cannot be detected this way it falls back
- // to using the default language supplied.
- void Parse(const string &source);
-
- // Returns the feature extractor descriptor.
- const FeatureExtractorDescriptor &descriptor() const { return descriptor_; }
- FeatureExtractorDescriptor *mutable_descriptor() { return &descriptor_; }
-
- // Returns the number of feature types in the feature extractor. Invalid
- // before Init() has been called.
- int feature_types() const { return feature_types_.size(); }
-
- // Returns all feature types names used by the extractor. The names are
- // added to the types_names array. Invalid before Init() has been called.
- void GetFeatureTypeNames(std::vector<string> *type_names) const;
-
- // Returns a feature type used in the extractor. Invalid before Init() has
- // been called.
- const FeatureType *feature_type(int index) const {
- return feature_types_[index];
- }
-
- // Returns the feature domain size of this feature extractor.
- // NOTE: The way that domain size is calculated is, for some, unintuitive. It
- // is the largest domain size of any feature type.
- FeatureValue GetDomainSize() const;
-
- protected:
- // Initializes the feature types used by the extractor. Called from
- // FeatureExtractor<>::Init().
- void InitializeFeatureTypes();
-
- private:
- // Initializes the top-level feature functions.
- virtual void InitializeFeatureFunctions() = 0;
-
- // Returns all feature types used by the extractor. The feature types are
- // added to the result array.
- virtual void GetFeatureTypes(std::vector<FeatureType *> *types) const = 0;
-
- // Descriptor for the feature extractor. This is a protocol buffer that
- // contains all the information about the feature extractor. The feature
- // functions are initialized from the information in the descriptor.
- FeatureExtractorDescriptor descriptor_;
-
- // All feature types used by the feature extractor. The collection of all the
- // feature types describes the feature space of the feature set produced by
- // the feature extractor. Not owned.
- std::vector<FeatureType *> feature_types_;
-};
-
-// The generic feature function is the type-independent part of a feature
-// function. Each feature function is associated with the descriptor that it is
-// instantiated from. The feature types associated with this feature function
-// will be established by the time FeatureExtractor<>::Init() completes.
-class GenericFeatureFunction {
- public:
- // A feature value that represents the absence of a value.
- static constexpr FeatureValue kNone = -1;
-
- GenericFeatureFunction();
- virtual ~GenericFeatureFunction();
-
- // Sets up the feature function. NB: FeatureTypes of nested functions are not
- // guaranteed to be available until Init().
- virtual void Setup(TaskContext *context) {}
-
- // Initializes the feature function. NB: The FeatureType of this function must
- // be established when this method completes.
- virtual void Init(TaskContext *context) {}
-
- // Requests workspaces from a registry to obtain indices into a WorkspaceSet
- // for any Workspace objects used by this feature function. NB: This will be
- // called after Init(), so it can depend on resources and arguments.
- virtual void RequestWorkspaces(WorkspaceRegistry *registry) {}
-
- // Appends the feature types produced by the feature function to types. The
- // default implementation appends feature_type(), if non-null. Invalid
- // before Init() has been called.
- virtual void GetFeatureTypes(std::vector<FeatureType *> *types) const;
-
- // Returns the feature type for feature produced by this feature function. If
- // the feature function produces features of different types this returns
- // null. Invalid before Init() has been called.
- virtual FeatureType *GetFeatureType() const;
-
- // Returns the name of the registry used for creating the feature function.
- // This can be used for checking if two feature functions are of the same
- // kind.
- virtual const char *RegistryName() const = 0;
-
- // Returns the value of a named parameter in the feature functions descriptor.
- // If the named parameter is not found the global parameters are searched.
- string GetParameter(const string &name) const;
- int GetIntParameter(const string &name, int default_value) const;
- bool GetBoolParameter(const string &name, bool default_value) const;
-
- // Returns the FML function description for the feature function, i.e. the
- // name and parameters without the nested features.
- string FunctionName() const {
- string output;
- ToFMLFunction(*descriptor_, &output);
- return output;
- }
-
- // Returns the prefix for nested feature functions. This is the prefix of this
- // feature function concatenated with the feature function name.
- string SubPrefix() const {
- return prefix_.empty() ? FunctionName() : prefix_ + "." + FunctionName();
- }
-
- // Returns/sets the feature extractor this function belongs to.
- GenericFeatureExtractor *extractor() const { return extractor_; }
- void set_extractor(GenericFeatureExtractor *extractor) {
- extractor_ = extractor;
- }
-
- // Returns/sets the feature function descriptor.
- FeatureFunctionDescriptor *descriptor() const { return descriptor_; }
- void set_descriptor(FeatureFunctionDescriptor *descriptor) {
- descriptor_ = descriptor;
- }
-
- // Returns a descriptive name for the feature function. The name is taken from
- // the descriptor for the feature function. If the name is empty or the
- // feature function is a variable the name is the FML representation of the
- // feature, including the prefix.
- string name() const {
- string output;
- if (descriptor_->name().empty()) {
- if (!prefix_.empty()) {
- output.append(prefix_);
- output.append(".");
- }
- ToFML(*descriptor_, &output);
- } else {
- output = descriptor_->name();
- }
- StringPiece stripped(output);
- utils::RemoveWhitespaceContext(&stripped);
-
- string stripped_output(stripped.data(), stripped.size());
- return stripped_output;
- }
-
- // Returns the argument from the feature function descriptor. It defaults to
- // 0 if the argument has not been specified.
- int argument() const {
- return descriptor_->has_argument() ? descriptor_->argument() : 0;
- }
-
- // Returns/sets/clears function name prefix.
- const string &prefix() const { return prefix_; }
- void set_prefix(const string &prefix) { prefix_ = prefix; }
-
- protected:
- // Returns the feature type for single-type feature functions.
- FeatureType *feature_type() const { return feature_type_; }
-
- // Sets the feature type for single-type feature functions. This takes
- // ownership of feature_type. Can only be called once.
- void set_feature_type(FeatureType *feature_type) {
- CLD3_DCHECK(feature_type_ == nullptr);
- feature_type_ = feature_type;
- }
-
- private:
- // Feature extractor this feature function belongs to. Not owned.
- GenericFeatureExtractor *extractor_ = nullptr;
-
- // Descriptor for feature function. Not owned.
- FeatureFunctionDescriptor *descriptor_ = nullptr;
-
- // Feature type for features produced by this feature function. If the
- // feature function produces features of multiple feature types this is null
- // and the feature function must return it's feature types in
- // GetFeatureTypes(). Owned.
- FeatureType *feature_type_ = nullptr;
-
- // Prefix used for sub-feature types of this function.
- string prefix_;
-};
-
-// Feature function that can extract features from an object. Templated on
-// two type arguments:
-//
-// OBJ: The "object" from which features are extracted; e.g., a sentence. This
-// should be a plain type, rather than a reference or pointer.
-//
-// ARGS: A set of 0 or more types that are used to "index" into some part of the
-// object that should be extracted, e.g. an int token index for a sentence
-// object. This should not be a reference type.
-template <class OBJ, class... ARGS>
-class FeatureFunction
- : public GenericFeatureFunction,
- public RegisterableClass<FeatureFunction<OBJ, ARGS...> > {
- public:
- using Self = FeatureFunction<OBJ, ARGS...>;
-
- // Preprocesses the object. This will be called prior to calling Evaluate()
- // or Compute() on that object.
- virtual void Preprocess(WorkspaceSet *workspaces, OBJ *object) const {}
-
- // Appends features computed from the object and focus to the result. The
- // default implementation delegates to Compute(), adding a single value if
- // available. Multi-valued feature functions must override this method.
- virtual void Evaluate(const WorkspaceSet &workspaces, const OBJ &object,
- ARGS... args, FeatureVector *result) const {
- FeatureValue value = Compute(workspaces, object, args..., result);
- if (value != kNone) result->add(feature_type(), value);
- }
-
- // Returns a feature value computed from the object and focus, or kNone if no
- // value is computed. Single-valued feature functions only need to override
- // this method.
- virtual FeatureValue Compute(const WorkspaceSet &workspaces,
- const OBJ &object, ARGS... args,
- const FeatureVector *fv) const {
- return kNone;
- }
-
- // Instantiates a new feature function in a feature extractor from a feature
- // descriptor.
- static Self *Instantiate(GenericFeatureExtractor *extractor,
- FeatureFunctionDescriptor *fd,
- const string &prefix) {
- Self *f = Self::Create(fd->type());
- f->set_extractor(extractor);
- f->set_descriptor(fd);
- f->set_prefix(prefix);
- return f;
- }
-
- // Returns the name of the registry for the feature function.
- const char *RegistryName() const override { return Self::registry()->name; }
-
- private:
- // Special feature function class for resolving variable references. The type
- // of the feature function is used for resolving the variable reference. When
- // evaluated it will either get the feature value(s) from the variable portion
- // of the feature vector, if present, or otherwise it will call the referenced
- // feature extractor function directly to extract the feature(s).
- class Reference;
-};
-
-// Base class for features with nested feature functions. The nested functions
-// are of type NES, which may be different from the type of the parent function.
-// NB: NestedFeatureFunction will ensure that all initialization of nested
-// functions takes place during Setup() and Init() -- after the nested features
-// are initialized, the parent feature is initialized via SetupNested() and
-// InitNested(). Alternatively, a derived classes that overrides Setup() and
-// Init() directly should call Parent::Setup(), Parent::Init(), etc. first.
-//
-// Note: NestedFeatureFunction cannot know how to call Preprocess, Evaluate, or
-// Compute, since the nested functions may be of a different type.
-template <class NES, class OBJ, class... ARGS>
-class NestedFeatureFunction : public FeatureFunction<OBJ, ARGS...> {
- public:
- using Parent = NestedFeatureFunction<NES, OBJ, ARGS...>;
-
- // Clean up nested functions.
- ~NestedFeatureFunction() override { utils::STLDeleteElements(&nested_); }
-
- // By default, just appends the nested feature types.
- void GetFeatureTypes(std::vector<FeatureType *> *types) const override {
- // Nested features require nested features to be defined.
- CLD3_DCHECK(!this->nested().empty());
- for (auto *function : nested_) function->GetFeatureTypes(types);
- }
-
- // Sets up the nested features.
- void Setup(TaskContext *context) override {
- CreateNested(this->extractor(), this->descriptor(), &nested_,
- this->SubPrefix());
- for (auto *function : nested_) function->Setup(context);
- SetupNested(context);
- }
-
- // Sets up this NestedFeatureFunction specifically.
- virtual void SetupNested(TaskContext *context) {}
-
- // Initializes the nested features.
- void Init(TaskContext *context) override {
- for (auto *function : nested_) function->Init(context);
- InitNested(context);
- }
-
- // Initializes this NestedFeatureFunction specifically.
- virtual void InitNested(TaskContext *context) {}
-
- // Gets all the workspaces needed for the nested functions.
- void RequestWorkspaces(WorkspaceRegistry *registry) override {
- for (auto *function : nested_) function->RequestWorkspaces(registry);
- }
-
- // Returns the list of nested feature functions.
- const vector<NES *> &nested() const { return nested_; }
-
- // Instantiates nested feature functions for a feature function. Creates and
- // initializes one feature function for each sub-descriptor in the feature
- // descriptor.
- static void CreateNested(GenericFeatureExtractor *extractor,
- FeatureFunctionDescriptor *fd,
- vector<NES *> *functions, const string &prefix) {
- for (int i = 0; i < fd->feature_size(); ++i) {
- FeatureFunctionDescriptor *sub = fd->mutable_feature(i);
- NES *f = NES::Instantiate(extractor, sub, prefix);
- functions->push_back(f);
- }
- }
-
- protected:
- // The nested feature functions, if any, in order of declaration in the
- // feature descriptor. Owned.
- vector<NES *> nested_;
-};
-
-// Base class for a nested feature function that takes nested features with the
-// same signature as these features, i.e. a meta feature. For this class, we can
-// provide preprocessing of the nested features.
-template <class OBJ, class... ARGS>
-class MetaFeatureFunction
- : public NestedFeatureFunction<FeatureFunction<OBJ, ARGS...>, OBJ,
- ARGS...> {
- public:
- // Preprocesses using the nested features.
- void Preprocess(WorkspaceSet *workspaces, OBJ *object) const override {
- for (auto *function : this->nested_) {
- function->Preprocess(workspaces, object);
- }
- }
-};
-
-// Template for a special type of locator: The locator of type
-// FeatureFunction<OBJ, ARGS...> calls nested functions of type
-// FeatureFunction<OBJ, IDX, ARGS...>, where the derived class DER is
-// responsible for translating by providing the following:
-//
-// // Gets the new additional focus.
-// IDX GetFocus(const WorkspaceSet &workspaces, const OBJ &object);
-//
-// This is useful to e.g. add a token focus to a parser state based on some
-// desired property of that state.
-template <class DER, class OBJ, class IDX, class... ARGS>
-class FeatureAddFocusLocator
- : public NestedFeatureFunction<FeatureFunction<OBJ, IDX, ARGS...>, OBJ,
- ARGS...> {
- public:
- void Preprocess(WorkspaceSet *workspaces, OBJ *object) const override {
- for (auto *function : this->nested_) {
- function->Preprocess(workspaces, object);
- }
- }
-
- void Evaluate(const WorkspaceSet &workspaces, const OBJ &object, ARGS... args,
- FeatureVector *result) const override {
- IDX focus =
- static_cast<const DER *>(this)->GetFocus(workspaces, object, args...);
- for (auto *function : this->nested()) {
- function->Evaluate(workspaces, object, focus, args..., result);
- }
- }
-
- // Returns the first nested feature's computed value.
- FeatureValue Compute(const WorkspaceSet &workspaces, const OBJ &object,
- ARGS... args,
- const FeatureVector *result) const override {
- IDX focus =
- static_cast<const DER *>(this)->GetFocus(workspaces, object, args...);
- return this->nested()[0]->Compute(workspaces, object, focus, args...,
- result);
- }
-};
-
-// CRTP feature locator class. This is a meta feature that modifies ARGS and
-// then calls the nested feature functions with the modified ARGS. Note that in
-// order for this template to work correctly, all of ARGS must be types for
-// which the reference operator & can be interpreted as a pointer to the
-// argument. The derived class DER must implement the UpdateFocus method which
-// takes pointers to the ARGS arguments:
-//
-// // Updates the current arguments.
-// void UpdateArgs(const OBJ &object, ARGS *...args) const;
-template <class DER, class OBJ, class... ARGS>
-class FeatureLocator : public MetaFeatureFunction<OBJ, ARGS...> {
- public:
- // Feature locators have an additional check that there is no intrinsic type.
- void GetFeatureTypes(std::vector<FeatureType *> *types) const override {
- // FeatureLocators should not have an intrinsic type.
- CLD3_DCHECK(this->feature_type() == nullptr);
- MetaFeatureFunction<OBJ, ARGS...>::GetFeatureTypes(types);
- }
-
- // Evaluates the locator.
- void Evaluate(const WorkspaceSet &workspaces, const OBJ &object, ARGS... args,
- FeatureVector *result) const override {
- static_cast<const DER *>(this)->UpdateArgs(workspaces, object, &args...);
- for (auto *function : this->nested()) {
- function->Evaluate(workspaces, object, args..., result);
- }
- }
-
- // Returns the first nested feature's computed value.
- FeatureValue Compute(const WorkspaceSet &workspaces, const OBJ &object,
- ARGS... args,
- const FeatureVector *result) const override {
- static_cast<const DER *>(this)->UpdateArgs(workspaces, object, &args...);
- return this->nested()[0]->Compute(workspaces, object, args..., result);
- }
-};
-
-// Feature extractor for extracting features from objects of a certain class.
-// Template type parameters are as defined for FeatureFunction.
-template <class OBJ, class... ARGS>
-class FeatureExtractor : public GenericFeatureExtractor {
- public:
- // Feature function type for top-level functions in the feature extractor.
- typedef FeatureFunction<OBJ, ARGS...> Function;
- typedef FeatureExtractor<OBJ, ARGS...> Self;
-
- // Feature locator type for the feature extractor.
- template <class DER>
- using Locator = FeatureLocator<DER, OBJ, ARGS...>;
-
- // Initializes feature extractor.
- FeatureExtractor() {}
-
- ~FeatureExtractor() override { utils::STLDeleteElements(&functions_); }
-
- // Sets up the feature extractor. Note that only top-level functions exist
- // until Setup() is called. This does not take ownership over the context,
- // which must outlive this.
- void Setup(TaskContext *context) {
- for (Function *function : functions_) function->Setup(context);
- }
-
- // Initializes the feature extractor. Must be called after Setup(). This
- // does not take ownership over the context, which must outlive this.
- void Init(TaskContext *context) {
- for (Function *function : functions_) function->Init(context);
- this->InitializeFeatureTypes();
- }
-
- // Requests workspaces from the registry. Must be called after Init(), and
- // before Preprocess(). Does not take ownership over registry. This should be
- // the same registry used to initialize the WorkspaceSet used in Preprocess()
- // and ExtractFeatures(). NB: This is a different ordering from that used in
- // SentenceFeatureRepresentation style feature computation.
- void RequestWorkspaces(WorkspaceRegistry *registry) {
- for (auto *function : functions_) function->RequestWorkspaces(registry);
- }
-
- // Preprocesses the object using feature functions for the phase. Must be
- // called before any calls to ExtractFeatures() on that object and phase.
- void Preprocess(WorkspaceSet *workspaces, OBJ *object) const {
- for (Function *function : functions_) {
- function->Preprocess(workspaces, object);
- }
- }
-
- // Extracts features from an object with a focus. This invokes all the
- // top-level feature functions in the feature extractor. Only feature
- // functions belonging to the specified phase are invoked.
- void ExtractFeatures(const WorkspaceSet &workspaces, const OBJ &object,
- ARGS... args, FeatureVector *result) const {
- result->reserve(this->feature_types());
-
- // Extract features.
- for (size_t i = 0; i < functions_.size(); ++i) {
- functions_[i]->Evaluate(workspaces, object, args..., result);
- }
- }
-
- private:
- // Creates and initializes all feature functions in the feature extractor.
- void InitializeFeatureFunctions() override {
- // Create all top-level feature functions.
- for (int i = 0; i < descriptor().feature_size(); ++i) {
- FeatureFunctionDescriptor *fd = mutable_descriptor()->mutable_feature(i);
- Function *function = Function::Instantiate(this, fd, "");
- functions_.push_back(function);
- }
- }
-
- // Collect all feature types used in the feature extractor.
- void GetFeatureTypes(std::vector<FeatureType *> *types) const override {
- for (size_t i = 0; i < functions_.size(); ++i) {
- functions_[i]->GetFeatureTypes(types);
- }
- }
-
- // Top-level feature functions (and variables) in the feature extractor.
- // Owned.
- std::vector<Function *> functions_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // FEATURE_EXTRACTOR_H_
diff --git a/chromium/third_party/cld_3/src/src/feature_extractor.proto b/chromium/third_party/cld_3/src/src/feature_extractor.proto
deleted file mode 100644
index 50a4c83ce68..00000000000
--- a/chromium/third_party/cld_3/src/src/feature_extractor.proto
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Protocol buffers for feature extractor.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package chrome_lang_id;
-
-message Parameter {
- optional string name = 1;
- optional string value = 2;
-}
-
-// Descriptor for feature function.
-message FeatureFunctionDescriptor {
- // Feature function type.
- required string type = 1;
-
- // Feature function name.
- optional string name = 2;
-
- // Default argument for feature function.
- optional int32 argument = 3 [default = 0];
-
- // Named parameters for feature descriptor.
- repeated Parameter parameter = 4;
-
- // Nested sub-feature function descriptors.
- repeated FeatureFunctionDescriptor feature = 7;
-};
-
-// Descriptor for feature extractor.
-message FeatureExtractorDescriptor {
- // Top-level feature function for extractor.
- repeated FeatureFunctionDescriptor feature = 1;
-};
diff --git a/chromium/third_party/cld_3/src/src/feature_types.cc b/chromium/third_party/cld_3/src/src/feature_types.cc
deleted file mode 100644
index 059a7dd6d4b..00000000000
--- a/chromium/third_party/cld_3/src/src/feature_types.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "feature_types.h"
-
-#include <algorithm>
-#include <map>
-#include <string>
-#include <utility>
-
-#include "base.h"
-
-namespace chrome_lang_id {
-
-FeatureType::FeatureType(const string &name)
- : name_(name),
- base_(0),
- is_continuous_(name.find("continuous") != string::npos) {}
-
-FeatureType::~FeatureType() {}
-
-template <class Resource>
-ResourceBasedFeatureType<Resource>::ResourceBasedFeatureType(
- const string &name, const Resource *resource,
- const std::map<FeatureValue, string> &values)
- : FeatureType(name), resource_(resource), values_(values) {
- max_value_ = resource->NumValues() - 1;
- for (const auto &pair : values) {
- CLD3_DCHECK(pair.first >= resource->NumValues());
- max_value_ = pair.first > max_value_ ? pair.first : max_value_;
- }
-}
-
-template <class Resource>
-ResourceBasedFeatureType<Resource>::ResourceBasedFeatureType(
- const string &name, const Resource *resource)
- : ResourceBasedFeatureType(name, resource, {}) {}
-
-EnumFeatureType::EnumFeatureType(
- const string &name, const std::map<FeatureValue, string> &value_names)
- : FeatureType(name), value_names_(value_names) {
- for (const auto &pair : value_names) {
- CLD3_DCHECK(pair.first >= 0);
- domain_size_ = std::max(domain_size_, pair.first + 1);
- }
-}
-
-EnumFeatureType::~EnumFeatureType() {}
-
-string EnumFeatureType::GetFeatureValueName(FeatureValue value) const {
- auto it = value_names_.find(value);
- if (it == value_names_.end()) {
- return "<INVALID>";
- }
- return it->second;
-}
-
-FeatureValue EnumFeatureType::GetDomainSize() const { return domain_size_; }
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/feature_types.h b/chromium/third_party/cld_3/src/src/feature_types.h
deleted file mode 100644
index 6e138904328..00000000000
--- a/chromium/third_party/cld_3/src/src/feature_types.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Common feature types for parser components.
-
-#ifndef FEATURE_TYPES_H_
-#define FEATURE_TYPES_H_
-
-#include <algorithm>
-#include <map>
-#include <string>
-#include <utility>
-
-#include "base.h"
-
-namespace chrome_lang_id {
-
-// TODO(djweiss) Clean this up as well.
-// Use the same type for feature values as is used for predicated.
-typedef int64 Predicate;
-typedef Predicate FeatureValue;
-
-// Each feature value in a feature vector has a feature type. The feature type
-// is used for converting feature type and value pairs to predicate values. The
-// feature type can also return names for feature values and calculate the size
-// of the feature value domain. The FeatureType class is abstract and must be
-// specialized for the concrete feature types.
-class FeatureType {
- public:
- // Initializes a feature type.
- explicit FeatureType(const string &name);
-
- virtual ~FeatureType();
-
- // Converts a feature value to a name.
- virtual string GetFeatureValueName(FeatureValue value) const = 0;
-
- // Returns the size of the feature values domain.
- virtual int64 GetDomainSize() const = 0;
-
- // Returns the feature type name.
- const string &name() const { return name_; }
-
- Predicate base() const { return base_; }
- void set_base(Predicate base) { base_ = base; }
-
- // Returns true iff this feature is continuous; see FloatFeatureValue.
- bool is_continuous() const { return is_continuous_; }
-
- private:
- // Feature type name.
- string name_;
-
- // "Base" feature value: i.e. a "slot" in a global ordering of features.
- Predicate base_;
-
- // See doc for is_continuous().
- bool is_continuous_;
-};
-
-// Templated generic resource based feature type. This feature type delegates
-// look up of feature value names to an unknown resource class, which is not
-// owned. Optionally, this type can also store a mapping of extra values which
-// are not in the resource.
-//
-// Note: this class assumes that Resource->GetFeatureValueName() will return
-// successfully for values ONLY in the range [0, Resource->NumValues()) Any
-// feature value not in the extra value map and not in the above range of
-// Resource will result in a ERROR and return of "<INVALID>".
-template <class Resource>
-class ResourceBasedFeatureType : public FeatureType {
- public:
- // Creates a new type with given name, resource object, and a mapping of
- // special values. The values must be greater or equal to
- // resource->NumValues() so as to avoid collisions; this is verified with
- // CHECK at creation.
- ResourceBasedFeatureType(const string &name, const Resource *resource,
- const std::map<FeatureValue, string> &values);
-
- // Creates a new type with no special values.
- ResourceBasedFeatureType(const string &name, const Resource *resource);
-
- // Returns the feature name for a given feature value. First checks the values
- // map, then checks the resource to look up the name.
- string GetFeatureValueName(FeatureValue value) const override {
- if (values_.find(value) != values_.end()) {
- return values_.find(value)->second;
- }
- if (value >= 0 && value < resource_->NumValues()) {
- return resource_->GetFeatureValueName(value);
- } else {
- return "<INVALID>";
- }
- }
-
- // Returns the number of possible values for this feature type. This is the
- // based on the largest value that was observed in the extra values.
- FeatureValue GetDomainSize() const override { return max_value_ + 1; }
-
- protected:
- // Shared resource. Not owned.
- const Resource *resource_ = nullptr;
-
- // Maximum possible value this feature could take.
- FeatureValue max_value_;
-
- // Mapping for extra feature values not in the resource.
- std::map<FeatureValue, string> values_;
-};
-
-// Feature type that is defined using an explicit map from FeatureValue to
-// string values. This can reduce some of the boilerplate when defining
-// features that generate enum values. Example usage:
-//
-// class BeverageSizeFeature : public FeatureFunction<Beverage>
-// enum FeatureValue { SMALL, MEDIUM, LARGE }; // values for this feature
-// void Init(TaskContext *context) override {
-// set_feature_type(new EnumFeatureType("beverage_size",
-// {{SMALL, "SMALL"}, {MEDIUM, "MEDIUM"}, {LARGE, "LARGE"}});
-// }
-// [...]
-// };
-class EnumFeatureType : public FeatureType {
- public:
- EnumFeatureType(const string &name,
- const std::map<FeatureValue, string> &value_names);
- ~EnumFeatureType() override;
-
- // Returns the feature name for a given feature value.
- string GetFeatureValueName(FeatureValue value) const override;
-
- // Returns the number of possible values for this feature type. This is one
- // greater than the largest value in the value_names map.
- FeatureValue GetDomainSize() const override;
-
- protected:
- // Maximum possible value this feature could take.
- FeatureValue domain_size_ = 0;
-
- // Names of feature values.
- std::map<FeatureValue, string> value_names_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // FEATURE_TYPES_H_
diff --git a/chromium/third_party/cld_3/src/src/float16.h b/chromium/third_party/cld_3/src/src/float16.h
deleted file mode 100644
index 7bed57da42d..00000000000
--- a/chromium/third_party/cld_3/src/src/float16.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef FLOAT16_H_
-#define FLOAT16_H_
-
-#include <string.h> // for memcpy
-
-#include "base.h"
-#include "casts.h"
-
-namespace chrome_lang_id {
-
-// Compact 16-bit encoding of floating point numbers. This
-// representation uses 1 bit for the sign, 8 bits for the exponent and
-// 7 bits for the mantissa. It is assumed that floats are in IEEE 754
-// format so a float16 is just bits 16-31 of a single precision float.
-//
-// NOTE: The IEEE floating point standard defines a float16 format that
-// is different than this format (it has fewer bits of exponent and more
-// bits of mantissa). We don't use that format here because conversion
-// to/from 32-bit floats is more complex for that format, and the
-// conversion for this format is very simple.
-//
-// <---------float16------------>
-// s e e e e e e e e f f f f f f f f f f f f f f f f f f f f f f f
-// <------------------------------float-------------------------->
-// 3 3 2 2 1 1 0
-// 1 0 3 2 5 4 0
-
-typedef uint16 float16;
-
-static inline float16 Float32To16(float f) {
- // Note that we just truncate the mantissa bits: we make no effort to
- // do any smarter rounding.
- return (lang_id_bit_cast<uint32>(f) >> 16) & 0xffff;
-}
-
-static inline float Float16To32(float16 f) {
- // We fill in the new mantissa bits with 0, and don't do anything smarter.
- return lang_id_bit_cast<float>(f << 16);
-}
-
-} // namespace chrome_lang_id
-
-#endif // FLOAT16_H_
diff --git a/chromium/third_party/cld_3/src/src/fml_parser.cc b/chromium/third_party/cld_3/src/src/fml_parser.cc
deleted file mode 100644
index c9cb4d8bf13..00000000000
--- a/chromium/third_party/cld_3/src/src/fml_parser.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "fml_parser.h"
-
-#include <ctype.h>
-#include <string>
-
-#include "base.h"
-#include "utils.h"
-
-namespace chrome_lang_id {
-
-namespace {
-
-inline bool IsValidCharAtStartOfIdentifier(char c) {
- return isalpha(c) || (c == '_') || (c == '/');
-}
-
-// Returns true iff character c can appear inside an identifier.
-inline bool IsValidCharInsideIdentifier(char c) {
- return isalnum(c) || (c == '_') || (c == '-') || (c == '/');
-}
-
-// Returns true iff character c can appear at the beginning of a number.
-inline bool IsValidCharAtStartOfNumber(char c) {
- return isdigit(c) || (c == '+') || (c == '-');
-}
-
-// Returns true iff character c can appear inside a number.
-inline bool IsValidCharInsideNumber(char c) { return isdigit(c) || (c == '.'); }
-
-} // namespace
-
-FMLParser::FMLParser() {}
-FMLParser::~FMLParser() {}
-
-void FMLParser::Initialize(const string &source) {
- // Initialize parser state.
- source_ = source;
- current_ = source_.begin();
- item_start_ = line_start_ = current_;
- line_number_ = item_line_number_ = 1;
-
- // Read first input item.
- NextItem();
-}
-
-void FMLParser::Next() {
- // Move to the next input character. If we are at a line break update line
- // number and line start position.
- if (CurrentChar() == '\n') {
- ++line_number_;
- ++current_;
- line_start_ = current_;
- } else {
- ++current_;
- }
-}
-
-void FMLParser::NextItem() {
- // Skip white space and comments.
- while (!eos()) {
- if (CurrentChar() == '#') {
- // Skip comment.
- while (!eos() && CurrentChar() != '\n') Next();
- } else if (isspace(CurrentChar())) {
- // Skip whitespace.
- while (!eos() && isspace(CurrentChar())) Next();
- } else {
- break;
- }
- }
-
- // Record start position for next item.
- item_start_ = current_;
- item_line_number_ = line_number_;
-
- // Check for end of input.
- if (eos()) {
- item_type_ = END;
- return;
- }
-
- // Parse number.
- if (IsValidCharAtStartOfNumber(CurrentChar())) {
- string::iterator start = current_;
- Next();
- while (!eos() && IsValidCharInsideNumber(CurrentChar())) Next();
- item_text_.assign(start, current_);
- item_type_ = NUMBER;
- return;
- }
-
- // Parse string.
- if (CurrentChar() == '"') {
- Next();
- string::iterator start = current_;
- while (CurrentChar() != '"') {
- CLD3_DCHECK(!eos());
- Next();
- }
- item_text_.assign(start, current_);
- item_type_ = STRING;
- Next();
- return;
- }
-
- // Parse identifier name.
- if (IsValidCharAtStartOfIdentifier(CurrentChar())) {
- string::iterator start = current_;
- while (!eos() && IsValidCharInsideIdentifier(CurrentChar())) {
- Next();
- }
- item_text_.assign(start, current_);
- item_type_ = NAME;
- return;
- }
-
- // Single character item.
- item_type_ = CurrentChar();
- Next();
-}
-
-void FMLParser::Parse(const string &source,
- FeatureExtractorDescriptor *result) {
- // Initialize parser.
- Initialize(source);
-
- while (item_type_ != END) {
- // Parse either a parameter name or a feature.
- CLD3_DCHECK(item_type_ == NAME);
- string name = item_text_;
- NextItem();
-
- // Feature expected.
- CLD3_DCHECK(static_cast<char>(item_type_) != '=');
-
- // Parse feature.
- FeatureFunctionDescriptor *descriptor = result->add_feature();
- descriptor->set_type(name);
- ParseFeature(descriptor);
- }
-}
-
-void FMLParser::ParseFeature(FeatureFunctionDescriptor *result) {
- // Parse argument and parameters.
- if (item_type_ == '(') {
- NextItem();
- ParseParameter(result);
- while (item_type_ == ',') {
- NextItem();
- ParseParameter(result);
- }
-
- CLD3_DCHECK(item_type_ == ')');
- NextItem();
- }
-
- // Parse feature name.
- if (item_type_ == ':') {
- NextItem();
-
- // Feature name expected.
- CLD3_DCHECK((item_type_ == NAME) || (item_type_ == STRING));
- string name = item_text_;
- NextItem();
-
- // Set feature name.
- result->set_name(name);
- }
-
- // Parse sub-features.
- if (item_type_ == '.') {
- // Parse dotted sub-feature.
- NextItem();
- CLD3_DCHECK(item_type_ == NAME);
- string type = item_text_;
- NextItem();
-
- // Parse sub-feature.
- FeatureFunctionDescriptor *subfeature = result->add_feature();
- subfeature->set_type(type);
- ParseFeature(subfeature);
- } else if (item_type_ == '{') {
- // Parse sub-feature block.
- NextItem();
- while (item_type_ != '}') {
- CLD3_DCHECK(item_type_ == NAME);
- string type = item_text_;
- NextItem();
-
- // Parse sub-feature.
- FeatureFunctionDescriptor *subfeature = result->add_feature();
- subfeature->set_type(type);
- ParseFeature(subfeature);
- }
- NextItem();
- }
-}
-
-void FMLParser::ParseParameter(FeatureFunctionDescriptor *result) {
- CLD3_DCHECK((item_type_ == NUMBER) || (item_type_ == NAME));
- if (item_type_ == NUMBER) {
- int argument = utils::ParseUsing<int>(item_text_, utils::ParseInt32);
- NextItem();
-
- // Set default argument for feature.
- result->set_argument(argument);
- } else { // item_type_ == NAME
- string name = item_text_;
- NextItem();
- CLD3_DCHECK(item_type_ == '=');
- NextItem();
-
- // Parameter value expected.
- CLD3_DCHECK(item_type_ < END);
- string value = item_text_;
- NextItem();
-
- // Add parameter to feature.
- Parameter *parameter;
- parameter = result->add_parameter();
- parameter->set_name(name);
- parameter->set_value(value);
- }
-}
-
-void ToFMLFunction(const FeatureFunctionDescriptor &function, string *output) {
- output->append(function.type());
- if (function.argument() != 0 || function.parameter_size() > 0) {
- output->append("(");
- bool first = true;
- if (function.argument() != 0) {
- output->append(Int64ToString(function.argument()));
- first = false;
- }
- for (int i = 0; i < function.parameter_size(); ++i) {
- if (!first) output->append(",");
- output->append(function.parameter(i).name());
- output->append("=");
- output->append("\"");
- output->append(function.parameter(i).value());
- output->append("\"");
- first = false;
- }
- output->append(")");
- }
-}
-
-void ToFML(const FeatureFunctionDescriptor &function, string *output) {
- ToFMLFunction(function, output);
- if (function.feature_size() == 1) {
- output->append(".");
- ToFML(function.feature(0), output);
- } else if (function.feature_size() > 1) {
- output->append(" { ");
- for (int i = 0; i < function.feature_size(); ++i) {
- if (i > 0) output->append(" ");
- ToFML(function.feature(i), output);
- }
- output->append(" } ");
- }
-}
-
-void ToFML(const FeatureExtractorDescriptor &extractor, string *output) {
- for (int i = 0; i < extractor.feature_size(); ++i) {
- ToFML(extractor.feature(i), output);
- output->append("\n");
- }
-}
-
-string AsFML(const FeatureFunctionDescriptor &function) {
- string str;
- ToFML(function, &str);
- return str;
-}
-
-string AsFML(const FeatureExtractorDescriptor &extractor) {
- string str;
- ToFML(extractor, &str);
- return str;
-}
-
-void StripFML(string *fml_string) {
- auto it = fml_string->begin();
- while (it != fml_string->end()) {
- if (*it == '"') {
- it = fml_string->erase(it);
- } else {
- ++it;
- }
- }
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/fml_parser.h b/chromium/third_party/cld_3/src/src/fml_parser.h
deleted file mode 100644
index ba87b4504ca..00000000000
--- a/chromium/third_party/cld_3/src/src/fml_parser.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Feature modeling language (fml) parser.
-//
-// BNF grammar for fml:
-//
-// <feature model> ::= { <feature extractor> }
-//
-// <feature extractor> ::= <extractor spec> |
-// <extractor spec> '.' <feature extractor> |
-// <extractor spec> '{' { <feature extractor> } '}'
-//
-// <extractor spec> ::= <extractor type>
-// [ '(' <parameter list> ')' ]
-// [ ':' <extractor name> ]
-//
-// <parameter list> = ( <parameter> | <argument> ) { ',' <parameter> }
-//
-// <parameter> ::= <parameter name> '=' <parameter value>
-//
-// <extractor type> ::= NAME
-// <extractor name> ::= NAME | STRING
-// <argument> ::= NUMBER
-// <parameter name> ::= NAME
-// <parameter value> ::= NUMBER | STRING | NAME
-
-#ifndef FML_PARSER_H_
-#define FML_PARSER_H_
-
-#include <string>
-
-#include "base.h"
-#include "cld_3/protos/feature_extractor.pb.h"
-
-namespace chrome_lang_id {
-
-class FMLParser {
- public:
- // Parses fml specification into feature extractor descriptor.
- void Parse(const string &source, FeatureExtractorDescriptor *result);
-
- FMLParser();
- ~FMLParser();
-
- private:
- // Initializes the parser with the source text.
- void Initialize(const string &source);
-
- // Moves to the next input character.
- void Next();
-
- // Moves to the next input item.
- void NextItem();
-
- // Parses a feature descriptor.
- void ParseFeature(FeatureFunctionDescriptor *result);
-
- // Parses a parameter specification.
- void ParseParameter(FeatureFunctionDescriptor *result);
-
- // Returns true if end of source input has been reached.
- bool eos() const { return current_ == source_.end(); }
-
- // Returns current character. Other methods should access the current
- // character through this method (instead of using *current_ directly): this
- // method performs extra safety checks.
- char CurrentChar() const {
- // CLD3_DCHECK that we are reading from inside the string.
- CLD3_DCHECK(current_ >= source_.begin());
- CLD3_DCHECK(current_ < source_.end());
- return *current_;
- }
-
- // Item types.
- enum ItemTypes {
- END = 0,
- NAME = -1,
- NUMBER = -2,
- STRING = -3,
- };
-
- // Source text.
- string source_;
-
- // Current input position.
- string::iterator current_;
-
- // Line number for current input position.
- int line_number_;
-
- // Start position for current item.
- string::iterator item_start_;
-
- // Start position for current line.
- string::iterator line_start_;
-
- // Line number for current item.
- int item_line_number_;
-
- // Item type for current item. If this is positive it is interpreted as a
- // character. If it is negative it is interpreted as an item type.
- int item_type_;
-
- // Text for current item.
- string item_text_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // FML_PARSER_H_
diff --git a/chromium/third_party/cld_3/src/src/lang_id_nn_params.cc b/chromium/third_party/cld_3/src/src/lang_id_nn_params.cc
deleted file mode 100644
index af286199962..00000000000
--- a/chromium/third_party/cld_3/src/src/lang_id_nn_params.cc
+++ /dev/null
@@ -1,57449 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "lang_id_nn_params.h"
-
-#include "base.h"
-#include "float16.h"
-
-namespace chrome_lang_id {
-
-const int LangIdNNParams::kEmbeddingsNumRows[] = {1000, 5000, 12, 103, 5000, 100};
-
-const int LangIdNNParams::kEmbeddingsNumCols[] = {16, 16, 8, 8, 16, 16};
-
-const float16 LangIdNNParams::kEmbeddingsQuantScales0[] = {
- 15392u, 15478u, 15306u, 15497u,
- 15384u, 15427u, 15373u, 15490u,
- 15487u, 15490u, 15660u, 15327u,
- 15407u, 15259u, 15362u, 15323u,
- 15276u, 15471u, 15460u, 15368u,
- 15457u, 15317u, 15535u, 15673u,
- 15332u, 15459u, 15473u, 15449u,
- 15484u, 15499u, 15558u, 15481u,
- 15320u, 15536u, 15389u, 15454u,
- 15516u, 15275u, 15354u, 15471u,
- 15300u, 15358u, 15424u, 15553u,
- 15255u, 15344u, 15367u, 15418u,
- 15237u, 15186u, 15415u, 15304u,
- 15493u, 15290u, 15365u, 15321u,
- 15452u, 15262u, 15381u, 15203u,
- 15397u, 15510u, 15393u, 15278u,
- 15616u, 15403u, 15363u, 15405u,
- 15486u, 15446u, 15164u, 15508u,
- 15233u, 15398u, 15419u, 15384u,
- 15301u, 15320u, 15546u, 15391u,
- 15478u, 15196u, 15363u, 15478u,
- 15368u, 15468u, 15247u, 15403u,
- 15466u, 15618u, 15516u, 15482u,
- 15446u, 15558u, 15333u, 15447u,
- 15488u, 15512u, 15509u, 15451u,
- 15342u, 15513u, 15450u, 15232u,
- 15424u, 15377u, 15309u, 15387u,
- 15392u, 15494u, 15392u, 15246u,
- 15371u, 15492u, 15456u, 15412u,
- 15416u, 15546u, 15445u, 15462u,
- 15394u, 15343u, 15393u, 15635u,
- 15549u, 15592u, 15367u, 15186u,
- 15421u, 15425u, 15400u, 15266u,
- 15500u, 15334u, 15495u, 15492u,
- 15420u, 15357u, 15445u, 15290u,
- 15512u, 15350u, 15459u, 15346u,
- 15446u, 15407u, 15376u, 15398u,
- 15528u, 15429u, 15323u, 15349u,
- 15437u, 15467u, 15465u, 15353u,
- 15418u, 15438u, 15393u, 15270u,
- 15228u, 15384u, 15319u, 15300u,
- 15380u, 15286u, 15508u, 15534u,
- 15629u, 15337u, 15432u, 15496u,
- 15366u, 15625u, 15391u, 15393u,
- 15451u, 15408u, 15389u, 15391u,
- 15256u, 15374u, 15336u, 15424u,
- 15429u, 15475u, 15457u, 15396u,
- 15392u, 15262u, 15639u, 15434u,
- 15409u, 15389u, 15575u, 15366u,
- 15411u, 15241u, 15578u, 15392u,
- 15403u, 15358u, 15322u, 15487u,
- 15436u, 15387u, 15315u, 15498u,
- 15283u, 15443u, 15358u, 15418u,
- 15440u, 15402u, 15249u, 15380u,
- 15530u, 15368u, 15412u, 15335u,
- 15589u, 15371u, 15375u, 15361u,
- 15479u, 15550u, 15420u, 15385u,
- 15402u, 15255u, 15478u, 15280u,
- 15365u, 15531u, 15600u, 15237u,
- 15481u, 15374u, 15387u, 15477u,
- 15393u, 15421u, 15447u, 15394u,
- 15512u, 15437u, 15348u, 15391u,
- 15578u, 15339u, 15498u, 15472u,
- 15372u, 15326u, 15419u, 15617u,
- 15232u, 15476u, 15414u, 15230u,
- 15548u, 15321u, 15307u, 15544u,
- 15398u, 15382u, 15507u, 15395u,
- 15382u, 15416u, 15489u, 15384u,
- 15421u, 15504u, 15499u, 15549u,
- 15500u, 15293u, 15559u, 15474u,
- 15510u, 15452u, 15441u, 15337u,
- 15441u, 15490u, 15551u, 15371u,
- 15412u, 15434u, 15468u, 15449u,
- 15402u, 15268u, 15446u, 15243u,
- 15487u, 15389u, 15419u, 15293u,
- 15587u, 15490u, 15506u, 15418u,
- 15344u, 15511u, 15477u, 15449u,
- 15293u, 15517u, 15531u, 15256u,
- 15363u, 15485u, 15495u, 15427u,
- 15416u, 15493u, 15455u, 15499u,
- 15500u, 15370u, 15623u, 15456u,
- 15356u, 15512u, 15371u, 15519u,
- 15306u, 15379u, 15514u, 15488u,
- 15391u, 15508u, 15426u, 15278u,
- 15345u, 15532u, 15352u, 15522u,
- 15457u, 15450u, 15528u, 15285u,
- 15330u, 15313u, 15406u, 15438u,
- 15385u, 15407u, 15440u, 15507u,
- 15483u, 15391u, 15492u, 15385u,
- 15411u, 15340u, 15324u, 15530u,
- 15511u, 15538u, 15532u, 15397u,
- 15449u, 15467u, 15440u, 15548u,
- 15285u, 15400u, 15361u, 15431u,
- 15552u, 15342u, 15273u, 15376u,
- 15493u, 15446u, 15348u, 15492u,
- 15361u, 15415u, 15542u, 15537u,
- 15413u, 15439u, 15389u, 15298u,
- 15492u, 15362u, 15468u, 15454u,
- 15493u, 15461u, 15157u, 15250u,
- 15560u, 15561u, 15510u, 15347u,
- 15354u, 15417u, 15454u, 15417u,
- 15364u, 15389u, 15461u, 15393u,
- 15373u, 15406u, 15463u, 15302u,
- 15449u, 15270u, 15355u, 15368u,
- 15514u, 15405u, 15385u, 15384u,
- 15293u, 15506u, 15424u, 15442u,
- 15418u, 15361u, 15500u, 15449u,
- 15466u, 15502u, 15527u, 15354u,
- 15251u, 15317u, 15482u, 15494u,
- 15393u, 15380u, 15441u, 15468u,
- 15250u, 15440u, 15403u, 15349u,
- 15468u, 15337u, 15392u, 15424u,
- 15493u, 15390u, 15581u, 15472u,
- 15364u, 15470u, 15321u, 15265u,
- 15316u, 15302u, 15338u, 15360u,
- 15516u, 15426u, 15281u, 15497u,
- 15415u, 15369u, 15556u, 15346u,
- 15270u, 15512u, 15504u, 15399u,
- 15375u, 15366u, 15335u, 15399u,
- 15401u, 15568u, 15504u, 15343u,
- 15408u, 15414u, 15361u, 15288u,
- 15318u, 15345u, 15364u, 15421u,
- 15383u, 15392u, 15391u, 15434u,
- 15467u, 15428u, 15339u, 15394u,
- 15504u, 15370u, 15445u, 15396u,
- 15518u, 15387u, 15324u, 15281u,
- 15409u, 15405u, 15333u, 15441u,
- 15276u, 15311u, 15489u, 15389u,
- 15419u, 15405u, 15427u, 15404u,
- 15310u, 15497u, 15462u, 15391u,
- 15560u, 15405u, 15531u, 15363u,
- 15286u, 15479u, 15482u, 15498u,
- 15377u, 15561u, 15347u, 15627u,
- 15434u, 15435u, 15614u, 15440u,
- 15620u, 15338u, 15366u, 15383u,
- 15426u, 15248u, 15406u, 15243u,
- 15479u, 15404u, 15422u, 15481u,
- 15456u, 15413u, 15286u, 15477u,
- 15401u, 15494u, 15388u, 15189u,
- 15397u, 15444u, 15508u, 15489u,
- 15470u, 15403u, 15369u, 15396u,
- 15412u, 15499u, 15553u, 15616u,
- 15624u, 15362u, 15398u, 15494u,
- 15374u, 15288u, 15482u, 15507u,
- 15489u, 15570u, 15400u, 15460u,
- 15429u, 15492u, 15396u, 15290u,
- 15515u, 15496u, 15399u, 15395u,
- 15358u, 15360u, 15561u, 15368u,
- 15388u, 15227u, 15525u, 15295u,
- 15430u, 15419u, 15391u, 15260u,
- 15316u, 15465u, 15302u, 15401u,
- 15477u, 15461u, 15521u, 15233u,
- 15279u, 15432u, 15427u, 15436u,
- 15593u, 15538u, 15467u, 15254u,
- 15566u, 15329u, 15480u, 15293u,
- 15360u, 15255u, 15545u, 15467u,
- 15264u, 15403u, 15413u, 15449u,
- 15439u, 15457u, 15374u, 15447u,
- 15480u, 15363u, 15365u, 15483u,
- 15403u, 15403u, 15285u, 15306u,
- 15405u, 15288u, 15534u, 15348u,
- 15324u, 15517u, 15398u, 15278u,
- 15490u, 15530u, 15287u, 15523u,
- 15403u, 15319u, 15261u, 15258u,
- 15432u, 15550u, 15563u, 15247u,
- 15495u, 15434u, 15390u, 15418u,
- 15375u, 15332u, 15627u, 15471u,
- 15318u, 15373u, 15392u, 15612u,
- 15433u, 15371u, 15133u, 15388u,
- 15419u, 15434u, 15521u, 15520u,
- 15483u, 15302u, 15431u, 15347u,
- 15382u, 15540u, 15531u, 15379u,
- 15484u, 15430u, 15461u, 15380u,
- 15402u, 15496u, 15363u, 15338u,
- 15291u, 15282u, 15321u, 15360u,
- 15251u, 15252u, 15488u, 15387u,
- 15464u, 15492u, 15545u, 15505u,
- 15469u, 15418u, 15331u, 15426u,
- 15438u, 15416u, 15254u, 15509u,
- 15514u, 15432u, 15420u, 15431u,
- 15373u, 15507u, 15243u, 15372u,
- 15315u, 15424u, 15536u, 15495u,
- 15400u, 15586u, 15289u, 15376u,
- 15497u, 15234u, 15395u, 15371u,
- 15438u, 15315u, 15332u, 15431u,
- 15618u, 15465u, 15619u, 15299u,
- 15342u, 15444u, 15465u, 15556u,
- 15509u, 15244u, 15499u, 15387u,
- 15434u, 15497u, 15514u, 15387u,
- 15380u, 15467u, 15414u, 15441u,
- 15382u, 15482u, 15345u, 15474u,
- 15520u, 15456u, 15388u, 15234u,
- 15416u, 15379u, 15537u, 15537u,
- 15397u, 15372u, 15281u, 15372u,
- 15252u, 15367u, 15431u, 15356u,
- 15408u, 15353u, 15385u, 15370u,
- 15413u, 15369u, 15354u, 15515u,
- 15512u, 15465u, 15299u, 15566u,
- 15336u, 15368u, 15399u, 15574u,
- 15504u, 15268u, 15371u, 15459u,
- 15377u, 15387u, 15418u, 15459u,
- 15494u, 15394u, 15414u, 15339u,
- 15312u, 15460u, 15303u, 15356u,
- 15491u, 15450u, 15431u, 15423u,
- 15423u, 15462u, 15408u, 15408u,
- 15520u, 15554u, 15671u, 15463u,
- 15406u, 15490u, 15567u, 15409u,
- 15335u, 15518u, 15372u, 15583u,
- 15255u, 15328u, 15433u, 15424u,
- 15285u, 15391u, 15540u, 15457u,
- 15460u, 15372u, 15465u, 15393u,
- 15490u, 15202u, 15357u, 15603u,
- 15498u, 15453u, 15267u, 15516u,
- 15442u, 15306u, 15489u, 15204u,
- 15460u, 15327u, 15252u, 15332u,
- 15222u, 15362u, 15519u, 15309u,
- 15365u, 15515u, 15349u, 15378u,
- 15514u, 15307u, 15522u, 15325u,
- 15391u, 15291u, 15237u, 15489u,
- 15294u, 15524u, 15394u, 15341u,
- 15385u, 15394u, 15390u, 15279u,
- 15517u, 15494u, 15418u, 15535u,
- 15501u, 15393u, 15457u, 15527u,
- 15392u, 15372u, 15362u, 15403u,
- 15392u, 15442u, 15563u, 15399u,
- 15432u, 15624u, 15286u, 15261u,
- 15509u, 15255u, 15289u, 15438u,
- 15407u, 15462u, 15466u, 15292u,
- 15387u, 15415u, 15195u, 15522u,
- 15418u, 15424u, 15459u, 15238u,
- 15514u, 15463u, 15519u, 15282u,
- 15468u, 15494u, 15626u, 15512u,
- 15374u, 15416u, 15503u, 15380u,
- 15332u, 15385u, 15431u, 15449u,
- 15244u, 15443u, 15381u, 15625u,
- 15421u, 15376u, 15461u, 15429u,
- 15355u, 15278u, 15367u, 15504u,
- 15279u, 15505u, 15538u, 15348u,
- 15414u, 15377u, 15528u, 15385u,
- 15285u, 15410u, 15545u, 15306u,
- 15496u, 15401u, 15360u, 15536u,
- 15275u, 15398u, 15366u, 15411u,
- 15384u, 15419u, 15390u, 15294u,
- 15456u, 15475u, 15416u, 15441u,
- 15516u, 15634u, 15502u, 15541u,
- 15516u, 15270u, 15448u, 15572u,
- 15441u, 15424u, 15446u, 15468u,
- 15432u, 15485u, 15295u, 15319u,
- 15383u, 15347u, 15522u, 15438u,
- 15428u, 15469u, 15408u, 15463u
-};
-
-const uint8 LangIdNNParams::kEmbeddingsWeights0[] = {
- 37u, 120u, 90u, 69u,
- 195u, 59u, 213u, 165u,
- 82u, 141u, 170u, 210u,
- 255u, 100u, 18u, 107u,
- 60u, 93u, 135u, 255u,
- 137u, 189u, 119u, 210u,
- 150u, 89u, 187u, 124u,
- 171u, 35u, 79u, 106u,
- 68u, 228u, 115u, 74u,
- 123u, 149u, 178u, 36u,
- 183u, 149u, 137u, 147u,
- 182u, 76u, 114u, 0u,
- 159u, 122u, 172u, 185u,
- 15u, 191u, 123u, 179u,
- 55u, 79u, 242u, 172u,
- 172u, 11u, 1u, 235u,
- 163u, 85u, 227u, 190u,
- 99u, 132u, 155u, 129u,
- 144u, 39u, 142u, 147u,
- 121u, 106u, 1u, 98u,
- 105u, 83u, 154u, 86u,
- 74u, 165u, 128u, 71u,
- 212u, 84u, 1u, 158u,
- 155u, 66u, 117u, 125u,
- 67u, 152u, 84u, 168u,
- 134u, 193u, 0u, 186u,
- 110u, 32u, 57u, 136u,
- 170u, 186u, 101u, 84u,
- 14u, 207u, 74u, 165u,
- 68u, 46u, 150u, 169u,
- 140u, 164u, 128u, 123u,
- 148u, 255u, 70u, 116u,
- 188u, 158u, 88u, 255u,
- 216u, 85u, 129u, 63u,
- 192u, 151u, 154u, 121u,
- 99u, 125u, 202u, 194u,
- 112u, 68u, 150u, 167u,
- 89u, 183u, 66u, 131u,
- 132u, 1u, 76u, 114u,
- 111u, 133u, 102u, 99u,
- 76u, 131u, 180u, 210u,
- 93u, 78u, 107u, 144u,
- 141u, 91u, 46u, 154u,
- 1u, 89u, 110u, 153u,
- 182u, 123u, 168u, 1u,
- 113u, 137u, 50u, 131u,
- 120u, 38u, 36u, 55u,
- 185u, 3u, 146u, 113u,
- 141u, 119u, 173u, 188u,
- 49u, 75u, 166u, 1u,
- 213u, 30u, 180u, 61u,
- 150u, 181u, 121u, 84u,
- 127u, 123u, 174u, 96u,
- 165u, 171u, 162u, 140u,
- 59u, 45u, 31u, 160u,
- 239u, 255u, 167u, 158u,
- 170u, 137u, 1u, 100u,
- 157u, 96u, 180u, 91u,
- 87u, 227u, 90u, 125u,
- 101u, 221u, 158u, 128u,
- 53u, 209u, 179u, 128u,
- 192u, 103u, 25u, 200u,
- 183u, 122u, 96u, 190u,
- 42u, 106u, 116u, 255u,
- 77u, 101u, 118u, 120u,
- 222u, 180u, 225u, 42u,
- 130u, 3u, 93u, 232u,
- 182u, 255u, 167u, 241u,
- 49u, 9u, 17u, 143u,
- 107u, 229u, 187u, 30u,
- 189u, 53u, 1u, 238u,
- 49u, 72u, 131u, 30u,
- 141u, 141u, 158u, 72u,
- 146u, 170u, 184u, 255u,
- 194u, 103u, 172u, 198u,
- 106u, 159u, 109u, 231u,
- 87u, 115u, 126u, 213u,
- 126u, 171u, 127u, 167u,
- 199u, 155u, 191u, 222u,
- 212u, 43u, 255u, 173u,
- 60u, 120u, 109u, 176u,
- 156u, 52u, 178u, 176u,
- 97u, 251u, 255u, 229u,
- 49u, 185u, 41u, 202u,
- 103u, 1u, 165u, 141u,
- 112u, 150u, 126u, 132u,
- 89u, 78u, 84u, 138u,
- 123u, 75u, 119u, 81u,
- 110u, 189u, 225u, 58u,
- 160u, 137u, 165u, 64u,
- 198u, 114u, 194u, 84u,
- 95u, 142u, 255u, 127u,
- 144u, 5u, 84u, 161u,
- 136u, 85u, 114u, 176u,
- 136u, 1u, 134u, 114u,
- 93u, 175u, 97u, 186u,
- 126u, 125u, 159u, 114u,
- 31u, 222u, 162u, 105u,
- 133u, 49u, 10u, 169u,
- 77u, 50u, 177u, 255u,
- 118u, 108u, 92u, 80u,
- 110u, 94u, 162u, 78u,
- 160u, 206u, 255u, 118u,
- 105u, 75u, 157u, 98u,
- 96u, 124u, 242u, 91u,
- 182u, 153u, 104u, 41u,
- 124u, 217u, 206u, 18u,
- 133u, 201u, 181u, 1u,
- 103u, 175u, 117u, 191u,
- 223u, 102u, 135u, 161u,
- 255u, 180u, 108u, 164u,
- 211u, 195u, 166u, 100u,
- 87u, 212u, 158u, 91u,
- 73u, 172u, 219u, 124u,
- 124u, 127u, 154u, 255u,
- 51u, 141u, 26u, 44u,
- 159u, 148u, 85u, 116u,
- 126u, 66u, 110u, 148u,
- 73u, 140u, 204u, 0u,
- 156u, 102u, 103u, 89u,
- 188u, 139u, 143u, 136u,
- 124u, 43u, 131u, 76u,
- 126u, 105u, 160u, 147u,
- 56u, 143u, 60u, 1u,
- 195u, 200u, 150u, 170u,
- 178u, 38u, 255u, 103u,
- 106u, 218u, 234u, 158u,
- 64u, 236u, 88u, 188u,
- 63u, 96u, 184u, 227u,
- 166u, 70u, 255u, 54u,
- 20u, 85u, 249u, 197u,
- 16u, 251u, 25u, 117u,
- 1u, 156u, 197u, 143u,
- 175u, 202u, 36u, 208u,
- 210u, 19u, 6u, 229u,
- 147u, 62u, 58u, 138u,
- 26u, 108u, 43u, 13u,
- 68u, 88u, 157u, 255u,
- 83u, 42u, 187u, 246u,
- 107u, 211u, 89u, 141u,
- 175u, 1u, 92u, 162u,
- 197u, 84u, 189u, 166u,
- 52u, 187u, 129u, 129u,
- 146u, 152u, 167u, 161u,
- 84u, 21u, 81u, 141u,
- 143u, 122u, 200u, 97u,
- 198u, 100u, 68u, 240u,
- 255u, 77u, 136u, 112u,
- 95u, 31u, 118u, 179u,
- 169u, 47u, 186u, 147u,
- 121u, 168u, 202u, 96u,
- 92u, 132u, 214u, 255u,
- 185u, 134u, 23u, 37u,
- 60u, 104u, 255u, 123u,
- 151u, 120u, 214u, 131u,
- 70u, 116u, 104u, 127u,
- 13u, 46u, 162u, 110u,
- 138u, 238u, 112u, 192u,
- 184u, 1u, 120u, 251u,
- 156u, 181u, 17u, 38u,
- 193u, 141u, 203u, 114u,
- 147u, 244u, 107u, 145u,
- 132u, 109u, 89u, 62u,
- 107u, 1u, 181u, 87u,
- 71u, 128u, 131u, 52u,
- 127u, 34u, 71u, 142u,
- 162u, 243u, 130u, 255u,
- 167u, 126u, 118u, 164u,
- 10u, 112u, 148u, 152u,
- 54u, 245u, 160u, 105u,
- 206u, 1u, 210u, 181u,
- 193u, 159u, 39u, 124u,
- 1u, 142u, 113u, 110u,
- 146u, 130u, 141u, 138u,
- 183u, 65u, 106u, 161u,
- 132u, 106u, 177u, 58u,
- 44u, 11u, 1u, 103u,
- 51u, 26u, 150u, 108u,
- 84u, 249u, 225u, 188u,
- 33u, 154u, 116u, 106u,
- 57u, 223u, 151u, 96u,
- 168u, 52u, 219u, 110u,
- 150u, 120u, 255u, 136u,
- 124u, 125u, 176u, 142u,
- 152u, 199u, 198u, 91u,
- 189u, 139u, 123u, 169u,
- 83u, 117u, 0u, 111u,
- 102u, 131u, 212u, 105u,
- 133u, 205u, 111u, 106u,
- 111u, 184u, 161u, 15u,
- 90u, 120u, 93u, 141u,
- 141u, 76u, 57u, 1u,
- 179u, 182u, 0u, 115u,
- 155u, 30u, 128u, 113u,
- 88u, 189u, 73u, 119u,
- 75u, 142u, 107u, 54u,
- 112u, 0u, 155u, 110u,
- 41u, 117u, 164u, 101u,
- 174u, 166u, 131u, 211u,
- 251u, 167u, 255u, 56u,
- 170u, 152u, 42u, 227u,
- 136u, 135u, 172u, 252u,
- 1u, 158u, 142u, 194u,
- 181u, 219u, 35u, 184u,
- 255u, 206u, 167u, 63u,
- 180u, 228u, 86u, 40u,
- 48u, 56u, 140u, 194u,
- 182u, 127u, 161u, 129u,
- 103u, 24u, 165u, 133u,
- 59u, 166u, 120u, 65u,
- 228u, 43u, 1u, 163u,
- 135u, 55u, 153u, 71u,
- 134u, 163u, 108u, 120u,
- 239u, 90u, 92u, 195u,
- 83u, 119u, 0u, 240u,
- 164u, 117u, 21u, 195u,
- 113u, 1u, 156u, 138u,
- 160u, 39u, 191u, 121u,
- 131u, 103u, 58u, 154u,
- 97u, 117u, 220u, 126u,
- 72u, 209u, 153u, 126u,
- 179u, 216u, 59u, 175u,
- 118u, 64u, 76u, 233u,
- 255u, 171u, 122u, 76u,
- 179u, 103u, 144u, 163u,
- 153u, 42u, 1u, 180u,
- 85u, 132u, 48u, 120u,
- 160u, 169u, 81u, 169u,
- 145u, 145u, 59u, 151u,
- 95u, 150u, 196u, 164u,
- 159u, 154u, 152u, 180u,
- 50u, 255u, 193u, 114u,
- 40u, 134u, 220u, 111u,
- 210u, 10u, 128u, 179u,
- 186u, 180u, 255u, 37u,
- 205u, 195u, 27u, 174u,
- 99u, 197u, 53u, 154u,
- 104u, 61u, 140u, 107u,
- 1u, 107u, 105u, 84u,
- 211u, 206u, 125u, 55u,
- 150u, 255u, 119u, 76u,
- 103u, 56u, 68u, 174u,
- 133u, 164u, 101u, 124u,
- 154u, 82u, 66u, 102u,
- 88u, 109u, 246u, 157u,
- 0u, 78u, 105u, 215u,
- 157u, 183u, 151u, 119u,
- 111u, 124u, 108u, 171u,
- 187u, 1u, 56u, 157u,
- 177u, 48u, 11u, 126u,
- 45u, 144u, 173u, 94u,
- 109u, 176u, 139u, 3u,
- 208u, 94u, 212u, 98u,
- 161u, 109u, 211u, 255u,
- 89u, 95u, 158u, 194u,
- 62u, 172u, 28u, 134u,
- 161u, 255u, 196u, 142u,
- 134u, 206u, 43u, 194u,
- 132u, 136u, 86u, 97u,
- 158u, 216u, 143u, 197u,
- 182u, 1u, 101u, 182u,
- 95u, 156u, 28u, 99u,
- 117u, 168u, 213u, 118u,
- 93u, 46u, 140u, 134u,
- 62u, 42u, 157u, 156u,
- 66u, 45u, 77u, 108u,
- 161u, 139u, 216u, 136u,
- 155u, 1u, 131u, 125u,
- 158u, 164u, 244u, 188u,
- 165u, 121u, 115u, 75u,
- 156u, 9u, 160u, 255u,
- 143u, 82u, 144u, 139u,
- 97u, 85u, 123u, 170u,
- 34u, 65u, 61u, 128u,
- 118u, 147u, 144u, 106u,
- 76u, 255u, 172u, 129u,
- 131u, 41u, 143u, 158u,
- 98u, 69u, 147u, 136u,
- 135u, 135u, 167u, 1u,
- 104u, 67u, 138u, 102u,
- 208u, 76u, 49u, 102u,
- 43u, 175u, 148u, 178u,
- 1u, 35u, 42u, 5u,
- 109u, 39u, 48u, 189u,
- 123u, 0u, 128u, 0u,
- 46u, 136u, 74u, 108u,
- 196u, 136u, 95u, 188u,
- 145u, 83u, 221u, 234u,
- 44u, 186u, 81u, 29u,
- 90u, 244u, 186u, 224u,
- 64u, 110u, 255u, 26u,
- 128u, 186u, 48u, 143u,
- 211u, 83u, 178u, 248u,
- 130u, 174u, 139u, 148u,
- 73u, 45u, 1u, 90u,
- 168u, 197u, 131u, 110u,
- 102u, 53u, 125u, 192u,
- 16u, 207u, 79u, 80u,
- 255u, 29u, 232u, 22u,
- 75u, 8u, 118u, 66u,
- 188u, 49u, 180u, 106u,
- 151u, 87u, 94u, 0u,
- 165u, 43u, 7u, 163u,
- 118u, 165u, 95u, 77u,
- 146u, 112u, 32u, 105u,
- 138u, 31u, 206u, 47u,
- 124u, 216u, 255u, 198u,
- 73u, 220u, 61u, 89u,
- 142u, 83u, 166u, 114u,
- 49u, 173u, 80u, 127u,
- 50u, 0u, 118u, 109u,
- 74u, 130u, 71u, 58u,
- 104u, 37u, 130u, 116u,
- 69u, 150u, 36u, 172u,
- 82u, 1u, 33u, 122u,
- 125u, 208u, 228u, 133u,
- 60u, 76u, 24u, 255u,
- 117u, 101u, 206u, 178u,
- 165u, 114u, 159u, 166u,
- 119u, 226u, 105u, 170u,
- 157u, 152u, 127u, 214u,
- 107u, 161u, 219u, 162u,
- 144u, 9u, 99u, 124u,
- 255u, 129u, 64u, 245u,
- 102u, 103u, 255u, 211u,
- 85u, 194u, 72u, 128u,
- 27u, 12u, 109u, 157u,
- 205u, 79u, 38u, 242u,
- 40u, 75u, 76u, 213u,
- 127u, 147u, 194u, 83u,
- 204u, 78u, 100u, 222u,
- 98u, 255u, 87u, 95u,
- 189u, 145u, 184u, 143u,
- 224u, 146u, 153u, 60u,
- 156u, 151u, 128u, 117u,
- 206u, 231u, 255u, 206u,
- 84u, 80u, 80u, 136u,
- 162u, 104u, 133u, 255u,
- 182u, 118u, 225u, 64u,
- 141u, 14u, 178u, 36u,
- 97u, 111u, 107u, 156u,
- 226u, 89u, 64u, 255u,
- 126u, 146u, 63u, 162u,
- 165u, 192u, 104u, 108u,
- 243u, 98u, 100u, 147u,
- 255u, 207u, 52u, 12u,
- 85u, 154u, 15u, 110u,
- 202u, 165u, 164u, 194u,
- 217u, 177u, 143u, 204u,
- 31u, 112u, 62u, 127u,
- 186u, 1u, 68u, 131u,
- 140u, 100u, 8u, 82u,
- 155u, 107u, 75u, 50u,
- 91u, 59u, 170u, 89u,
- 140u, 46u, 78u, 255u,
- 141u, 99u, 133u, 146u,
- 111u, 129u, 107u, 135u,
- 103u, 158u, 179u, 165u,
- 190u, 118u, 86u, 235u,
- 148u, 255u, 110u, 222u,
- 104u, 82u, 121u, 139u,
- 127u, 107u, 216u, 71u,
- 148u, 124u, 194u, 141u,
- 159u, 1u, 150u, 131u,
- 86u, 189u, 91u, 178u,
- 199u, 95u, 78u, 212u,
- 134u, 129u, 160u, 171u,
- 44u, 118u, 70u, 255u,
- 125u, 237u, 165u, 37u,
- 100u, 148u, 99u, 185u,
- 135u, 0u, 125u, 98u,
- 107u, 115u, 145u, 181u,
- 249u, 154u, 190u, 152u,
- 114u, 37u, 141u, 1u,
- 170u, 215u, 168u, 117u,
- 36u, 160u, 172u, 108u,
- 137u, 153u, 140u, 119u,
- 79u, 186u, 181u, 143u,
- 95u, 104u, 84u, 148u,
- 155u, 1u, 168u, 221u,
- 168u, 209u, 136u, 167u,
- 35u, 255u, 177u, 58u,
- 124u, 142u, 198u, 74u,
- 174u, 140u, 165u, 236u,
- 112u, 151u, 106u, 88u,
- 116u, 137u, 143u, 162u,
- 255u, 90u, 116u, 196u,
- 180u, 52u, 50u, 176u,
- 153u, 108u, 115u, 118u,
- 155u, 137u, 149u, 75u,
- 113u, 109u, 0u, 186u,
- 143u, 198u, 115u, 87u,
- 143u, 113u, 175u, 161u,
- 1u, 109u, 161u, 203u,
- 194u, 146u, 165u, 62u,
- 110u, 164u, 106u, 126u,
- 99u, 101u, 80u, 152u,
- 183u, 113u, 255u, 133u,
- 178u, 86u, 177u, 209u,
- 68u, 117u, 90u, 140u,
- 38u, 35u, 112u, 81u,
- 204u, 126u, 149u, 79u,
- 113u, 68u, 1u, 229u,
- 120u, 174u, 122u, 17u,
- 70u, 1u, 230u, 216u,
- 115u, 119u, 158u, 136u,
- 120u, 39u, 79u, 64u,
- 118u, 214u, 126u, 139u,
- 109u, 16u, 169u, 255u,
- 135u, 56u, 17u, 167u,
- 144u, 48u, 53u, 142u,
- 69u, 30u, 94u, 58u,
- 151u, 234u, 104u, 34u,
- 199u, 95u, 11u, 190u,
- 175u, 80u, 77u, 83u,
- 231u, 0u, 50u, 139u,
- 114u, 125u, 131u, 175u,
- 171u, 115u, 183u, 160u,
- 71u, 1u, 81u, 182u,
- 144u, 145u, 13u, 141u,
- 89u, 142u, 107u, 42u,
- 157u, 54u, 122u, 129u,
- 114u, 85u, 164u, 178u,
- 114u, 122u, 181u, 1u,
- 130u, 80u, 122u, 190u,
- 82u, 178u, 171u, 86u,
- 81u, 240u, 255u, 91u,
- 140u, 195u, 159u, 241u,
- 43u, 92u, 81u, 244u,
- 52u, 203u, 224u, 234u,
- 122u, 127u, 244u, 167u,
- 167u, 235u, 85u, 255u,
- 227u, 111u, 116u, 149u,
- 118u, 53u, 201u, 228u,
- 120u, 208u, 185u, 83u,
- 47u, 255u, 199u, 26u,
- 132u, 165u, 17u, 100u,
- 85u, 255u, 151u, 159u,
- 90u, 109u, 62u, 160u,
- 168u, 177u, 153u, 67u,
- 255u, 226u, 108u, 34u,
- 76u, 121u, 96u, 101u,
- 164u, 67u, 18u, 144u,
- 194u, 166u, 175u, 198u,
- 163u, 194u, 124u, 75u,
- 156u, 139u, 137u, 105u,
- 255u, 84u, 61u, 28u,
- 175u, 78u, 147u, 56u,
- 162u, 71u, 167u, 118u,
- 154u, 209u, 24u, 77u,
- 164u, 56u, 91u, 1u,
- 204u, 115u, 160u, 37u,
- 176u, 90u, 154u, 19u,
- 101u, 51u, 37u, 158u,
- 255u, 203u, 227u, 148u,
- 215u, 38u, 76u, 185u,
- 156u, 133u, 202u, 0u,
- 130u, 130u, 118u, 156u,
- 72u, 38u, 112u, 196u,
- 154u, 46u, 107u, 177u,
- 2u, 193u, 198u, 81u,
- 21u, 154u, 199u, 64u,
- 91u, 128u, 229u, 41u,
- 185u, 48u, 111u, 255u,
- 113u, 186u, 207u, 103u,
- 70u, 172u, 193u, 151u,
- 147u, 39u, 131u, 0u,
- 134u, 184u, 28u, 155u,
- 111u, 140u, 111u, 122u,
- 135u, 138u, 116u, 149u,
- 104u, 97u, 126u, 108u,
- 106u, 109u, 120u, 255u,
- 62u, 1u, 145u, 133u,
- 110u, 168u, 136u, 114u,
- 217u, 44u, 139u, 159u,
- 158u, 71u, 170u, 95u,
- 93u, 117u, 186u, 255u,
- 172u, 214u, 101u, 240u,
- 117u, 44u, 166u, 149u,
- 199u, 93u, 69u, 169u,
- 251u, 214u, 45u, 191u,
- 62u, 161u, 177u, 188u,
- 62u, 254u, 148u, 62u,
- 255u, 217u, 132u, 129u,
- 160u, 1u, 168u, 139u,
- 119u, 171u, 70u, 99u,
- 139u, 39u, 4u, 169u,
- 189u, 159u, 91u, 125u,
- 135u, 25u, 176u, 22u,
- 129u, 113u, 138u, 156u,
- 35u, 74u, 183u, 235u,
- 151u, 255u, 165u, 189u,
- 152u, 88u, 146u, 107u,
- 80u, 255u, 92u, 111u,
- 165u, 142u, 137u, 129u,
- 147u, 113u, 88u, 135u,
- 181u, 85u, 201u, 184u,
- 109u, 160u, 162u, 124u,
- 100u, 84u, 63u, 139u,
- 84u, 255u, 158u, 142u,
- 137u, 43u, 255u, 103u,
- 53u, 157u, 40u, 106u,
- 155u, 62u, 104u, 67u,
- 134u, 175u, 78u, 144u,
- 109u, 192u, 188u, 123u,
- 124u, 49u, 163u, 200u,
- 99u, 213u, 149u, 146u,
- 198u, 66u, 1u, 124u,
- 215u, 146u, 149u, 190u,
- 149u, 236u, 156u, 255u,
- 171u, 10u, 237u, 81u,
- 109u, 197u, 78u, 255u,
- 208u, 255u, 210u, 53u,
- 110u, 97u, 100u, 134u,
- 169u, 124u, 124u, 137u,
- 164u, 61u, 127u, 89u,
- 123u, 194u, 186u, 132u,
- 106u, 178u, 48u, 241u,
- 77u, 92u, 114u, 140u,
- 131u, 150u, 255u, 132u,
- 119u, 136u, 74u, 130u,
- 94u, 121u, 87u, 121u,
- 161u, 0u, 37u, 133u,
- 123u, 48u, 87u, 221u,
- 139u, 0u, 81u, 104u,
- 94u, 129u, 96u, 132u,
- 150u, 125u, 39u, 222u,
- 162u, 177u, 82u, 85u,
- 179u, 139u, 123u, 85u,
- 94u, 148u, 53u, 106u,
- 144u, 8u, 0u, 114u,
- 181u, 79u, 148u, 139u,
- 177u, 53u, 30u, 95u,
- 85u, 44u, 103u, 1u,
- 88u, 152u, 239u, 14u,
- 167u, 103u, 183u, 124u,
- 15u, 142u, 207u, 134u,
- 173u, 112u, 121u, 82u,
- 67u, 205u, 144u, 68u,
- 13u, 255u, 103u, 185u,
- 119u, 77u, 252u, 201u,
- 81u, 169u, 104u, 107u,
- 179u, 142u, 129u, 1u,
- 21u, 87u, 203u, 163u,
- 53u, 214u, 158u, 58u,
- 255u, 208u, 159u, 147u,
- 142u, 78u, 100u, 221u,
- 56u, 154u, 158u, 103u,
- 13u, 92u, 51u, 53u,
- 142u, 63u, 211u, 1u,
- 224u, 41u, 220u, 249u,
- 93u, 205u, 95u, 94u,
- 133u, 196u, 174u, 106u,
- 131u, 207u, 92u, 196u,
- 145u, 45u, 95u, 128u,
- 150u, 202u, 255u, 104u,
- 164u, 255u, 151u, 126u,
- 87u, 94u, 32u, 108u,
- 200u, 171u, 158u, 72u,
- 80u, 43u, 107u, 169u,
- 113u, 140u, 255u, 196u,
- 120u, 170u, 132u, 161u,
- 80u, 26u, 76u, 98u,
- 95u, 243u, 144u, 151u,
- 43u, 28u, 29u, 34u,
- 144u, 27u, 103u, 160u,
- 122u, 174u, 146u, 115u,
- 133u, 86u, 255u, 63u,
- 108u, 5u, 142u, 111u,
- 106u, 133u, 254u, 47u,
- 57u, 255u, 168u, 119u,
- 198u, 161u, 99u, 124u,
- 188u, 176u, 211u, 52u,
- 121u, 37u, 145u, 188u,
- 79u, 237u, 98u, 146u,
- 255u, 133u, 13u, 208u,
- 164u, 84u, 129u, 117u,
- 255u, 99u, 115u, 104u,
- 40u, 123u, 122u, 145u,
- 123u, 166u, 234u, 48u,
- 118u, 0u, 160u, 187u,
- 186u, 80u, 111u, 160u,
- 146u, 95u, 119u, 109u,
- 171u, 154u, 71u, 14u,
- 140u, 206u, 98u, 0u,
- 127u, 198u, 169u, 88u,
- 54u, 94u, 119u, 32u,
- 70u, 228u, 67u, 224u,
- 92u, 132u, 193u, 62u,
- 1u, 108u, 179u, 255u,
- 148u, 80u, 177u, 100u,
- 61u, 123u, 192u, 142u,
- 159u, 123u, 180u, 224u,
- 129u, 149u, 137u, 119u,
- 217u, 66u, 80u, 215u,
- 107u, 80u, 1u, 114u,
- 111u, 56u, 118u, 163u,
- 118u, 12u, 39u, 183u,
- 104u, 151u, 208u, 1u,
- 148u, 155u, 131u, 181u,
- 144u, 35u, 136u, 134u,
- 39u, 255u, 118u, 123u,
- 209u, 161u, 53u, 117u,
- 130u, 61u, 181u, 110u,
- 1u, 161u, 230u, 179u,
- 126u, 228u, 132u, 191u,
- 93u, 148u, 143u, 120u,
- 107u, 189u, 174u, 244u,
- 128u, 69u, 255u, 58u,
- 60u, 169u, 29u, 167u,
- 236u, 149u, 108u, 191u,
- 111u, 85u, 75u, 84u,
- 144u, 123u, 71u, 1u,
- 48u, 106u, 108u, 79u,
- 86u, 127u, 185u, 106u,
- 123u, 143u, 169u, 46u,
- 206u, 190u, 255u, 37u,
- 141u, 140u, 97u, 115u,
- 69u, 50u, 53u, 155u,
- 223u, 107u, 245u, 94u,
- 121u, 214u, 240u, 102u,
- 204u, 255u, 95u, 37u,
- 164u, 34u, 192u, 119u,
- 102u, 239u, 134u, 111u,
- 85u, 116u, 78u, 191u,
- 112u, 153u, 159u, 209u,
- 222u, 99u, 83u, 255u,
- 109u, 184u, 42u, 236u,
- 99u, 159u, 165u, 27u,
- 69u, 1u, 96u, 176u,
- 181u, 124u, 37u, 147u,
- 122u, 182u, 106u, 141u,
- 148u, 20u, 34u, 164u,
- 51u, 102u, 133u, 128u,
- 185u, 183u, 209u, 42u,
- 97u, 1u, 154u, 95u,
- 232u, 167u, 114u, 47u,
- 85u, 59u, 98u, 147u,
- 22u, 92u, 178u, 1u,
- 14u, 97u, 137u, 243u,
- 183u, 47u, 55u, 51u,
- 125u, 255u, 147u, 123u,
- 112u, 33u, 77u, 179u,
- 102u, 23u, 95u, 166u,
- 255u, 107u, 180u, 212u,
- 36u, 54u, 32u, 128u,
- 84u, 200u, 24u, 67u,
- 138u, 110u, 126u, 222u,
- 1u, 156u, 139u, 215u,
- 54u, 151u, 183u, 121u,
- 152u, 155u, 147u, 94u,
- 116u, 138u, 147u, 191u,
- 168u, 98u, 106u, 31u,
- 172u, 1u, 107u, 22u,
- 99u, 20u, 185u, 96u,
- 99u, 161u, 77u, 29u,
- 181u, 110u, 108u, 81u,
- 105u, 144u, 144u, 107u,
- 59u, 142u, 0u, 231u,
- 97u, 160u, 140u, 102u,
- 107u, 83u, 250u, 193u,
- 85u, 180u, 1u, 130u,
- 218u, 1u, 229u, 71u,
- 145u, 87u, 68u, 49u,
- 103u, 128u, 1u, 158u,
- 170u, 121u, 123u, 92u,
- 136u, 100u, 32u, 130u,
- 204u, 141u, 80u, 122u,
- 125u, 121u, 73u, 86u,
- 79u, 123u, 89u, 101u,
- 121u, 128u, 140u, 62u,
- 100u, 1u, 132u, 117u,
- 164u, 1u, 39u, 143u,
- 62u, 73u, 123u, 57u,
- 123u, 117u, 130u, 52u,
- 68u, 74u, 177u, 139u,
- 223u, 105u, 79u, 111u,
- 147u, 112u, 1u, 186u,
- 137u, 177u, 175u, 101u,
- 96u, 44u, 117u, 41u,
- 94u, 1u, 106u, 87u,
- 66u, 18u, 144u, 81u,
- 144u, 186u, 136u, 194u,
- 247u, 182u, 131u, 31u,
- 16u, 138u, 163u, 214u,
- 128u, 21u, 109u, 144u,
- 210u, 160u, 199u, 153u,
- 1u, 176u, 124u, 117u,
- 121u, 0u, 138u, 145u,
- 88u, 184u, 120u, 82u,
- 66u, 148u, 162u, 74u,
- 67u, 145u, 130u, 95u,
- 181u, 176u, 148u, 158u,
- 105u, 137u, 255u, 186u,
- 157u, 88u, 145u, 153u,
- 19u, 94u, 149u, 121u,
- 66u, 116u, 205u, 109u,
- 252u, 135u, 126u, 237u,
- 48u, 2u, 183u, 171u,
- 97u, 255u, 80u, 89u,
- 200u, 203u, 166u, 130u,
- 50u, 17u, 245u, 59u,
- 140u, 108u, 159u, 130u,
- 210u, 102u, 81u, 255u,
- 252u, 54u, 174u, 229u,
- 255u, 162u, 217u, 100u,
- 152u, 45u, 139u, 240u,
- 205u, 152u, 70u, 110u,
- 82u, 189u, 206u, 160u,
- 116u, 163u, 207u, 63u,
- 189u, 100u, 93u, 112u,
- 99u, 91u, 224u, 255u,
- 213u, 89u, 151u, 255u,
- 102u, 207u, 85u, 163u,
- 163u, 83u, 12u, 161u,
- 67u, 126u, 60u, 110u,
- 125u, 154u, 167u, 107u,
- 97u, 99u, 136u, 84u,
- 151u, 174u, 199u, 70u,
- 95u, 101u, 255u, 204u,
- 196u, 199u, 182u, 122u,
- 150u, 157u, 47u, 23u,
- 166u, 212u, 141u, 181u,
- 100u, 1u, 135u, 149u,
- 129u, 117u, 226u, 200u,
- 127u, 189u, 247u, 99u,
- 116u, 61u, 185u, 238u,
- 187u, 255u, 34u, 216u,
- 185u, 255u, 121u, 179u,
- 186u, 158u, 86u, 209u,
- 113u, 73u, 105u, 97u,
- 143u, 147u, 21u, 93u,
- 162u, 104u, 157u, 28u,
- 97u, 184u, 112u, 234u,
- 141u, 62u, 155u, 160u,
- 1u, 146u, 56u, 103u,
- 42u, 163u, 76u, 96u,
- 196u, 76u, 212u, 100u,
- 130u, 255u, 241u, 202u,
- 65u, 152u, 31u, 136u,
- 134u, 80u, 83u, 160u,
- 106u, 189u, 94u, 125u,
- 104u, 99u, 98u, 103u,
- 1u, 39u, 160u, 211u,
- 194u, 87u, 188u, 205u,
- 101u, 67u, 150u, 62u,
- 200u, 110u, 114u, 147u,
- 16u, 82u, 66u, 1u,
- 90u, 186u, 20u, 61u,
- 115u, 136u, 255u, 131u,
- 114u, 141u, 140u, 236u,
- 87u, 75u, 155u, 155u,
- 133u, 176u, 129u, 75u,
- 74u, 242u, 199u, 146u,
- 56u, 168u, 116u, 139u,
- 74u, 86u, 182u, 255u,
- 122u, 153u, 146u, 79u,
- 52u, 155u, 119u, 185u,
- 75u, 119u, 122u, 131u,
- 219u, 1u, 127u, 165u,
- 116u, 101u, 119u, 119u,
- 91u, 156u, 69u, 116u,
- 167u, 131u, 94u, 150u,
- 161u, 255u, 105u, 120u,
- 148u, 137u, 166u, 75u,
- 41u, 111u, 11u, 255u,
- 129u, 137u, 172u, 128u,
- 174u, 148u, 148u, 7u,
- 102u, 140u, 193u, 107u,
- 113u, 128u, 173u, 73u,
- 152u, 99u, 128u, 119u,
- 158u, 245u, 255u, 144u,
- 143u, 24u, 143u, 204u,
- 197u, 0u, 102u, 121u,
- 171u, 167u, 140u, 226u,
- 100u, 204u, 225u, 165u,
- 64u, 141u, 101u, 191u,
- 152u, 79u, 182u, 133u,
- 170u, 144u, 179u, 163u,
- 70u, 255u, 54u, 206u,
- 23u, 155u, 94u, 79u,
- 91u, 206u, 0u, 33u,
- 185u, 104u, 128u, 63u,
- 10u, 94u, 228u, 146u,
- 25u, 42u, 204u, 95u,
- 138u, 101u, 35u, 99u,
- 255u, 116u, 53u, 146u,
- 167u, 187u, 225u, 102u,
- 91u, 113u, 195u, 210u,
- 83u, 255u, 143u, 66u,
- 180u, 140u, 227u, 106u,
- 160u, 85u, 187u, 67u,
- 143u, 135u, 101u, 48u,
- 77u, 188u, 255u, 99u,
- 97u, 226u, 117u, 245u,
- 220u, 160u, 199u, 66u,
- 88u, 134u, 184u, 186u,
- 193u, 221u, 172u, 255u,
- 92u, 115u, 136u, 171u,
- 45u, 106u, 136u, 240u,
- 121u, 62u, 184u, 180u,
- 168u, 110u, 194u, 83u,
- 95u, 79u, 1u, 172u,
- 168u, 143u, 148u, 51u,
- 74u, 83u, 160u, 255u,
- 123u, 46u, 68u, 147u,
- 156u, 211u, 157u, 111u,
- 41u, 87u, 96u, 191u,
- 99u, 76u, 155u, 180u,
- 174u, 137u, 92u, 170u,
- 173u, 161u, 130u, 75u,
- 26u, 142u, 255u, 119u,
- 117u, 255u, 239u, 173u,
- 169u, 131u, 228u, 124u,
- 108u, 116u, 194u, 108u,
- 112u, 158u, 183u, 178u,
- 83u, 1u, 113u, 63u,
- 96u, 36u, 143u, 97u,
- 108u, 163u, 161u, 69u,
- 196u, 227u, 191u, 50u,
- 216u, 1u, 164u, 56u,
- 213u, 185u, 119u, 80u,
- 114u, 182u, 129u, 245u,
- 150u, 76u, 49u, 186u,
- 53u, 118u, 54u, 93u,
- 255u, 79u, 238u, 108u,
- 70u, 237u, 125u, 167u,
- 156u, 98u, 53u, 88u,
- 150u, 1u, 147u, 139u,
- 108u, 111u, 39u, 78u,
- 179u, 167u, 66u, 181u,
- 98u, 14u, 23u, 255u,
- 134u, 108u, 18u, 241u,
- 251u, 81u, 255u, 82u,
- 133u, 221u, 249u, 237u,
- 102u, 193u, 209u, 187u,
- 178u, 83u, 134u, 140u,
- 112u, 74u, 137u, 91u,
- 78u, 49u, 91u, 96u,
- 255u, 238u, 146u, 219u,
- 230u, 200u, 134u, 110u,
- 131u, 154u, 102u, 105u,
- 133u, 157u, 255u, 103u,
- 63u, 131u, 40u, 79u,
- 111u, 87u, 103u, 144u,
- 99u, 98u, 201u, 14u,
- 159u, 101u, 60u, 141u,
- 130u, 158u, 129u, 1u,
- 177u, 133u, 115u, 215u,
- 84u, 108u, 1u, 140u,
- 201u, 161u, 118u, 65u,
- 179u, 86u, 82u, 172u,
- 70u, 213u, 1u, 132u,
- 217u, 205u, 110u, 213u,
- 80u, 33u, 35u, 245u,
- 49u, 100u, 35u, 154u,
- 71u, 108u, 109u, 77u,
- 232u, 172u, 47u, 147u,
- 217u, 255u, 71u, 93u,
- 107u, 92u, 90u, 166u,
- 38u, 206u, 68u, 134u,
- 100u, 118u, 255u, 233u,
- 89u, 113u, 132u, 91u,
- 116u, 100u, 77u, 81u,
- 164u, 137u, 105u, 176u,
- 177u, 0u, 139u, 202u,
- 132u, 155u, 74u, 135u,
- 178u, 183u, 94u, 224u,
- 101u, 126u, 68u, 105u,
- 206u, 31u, 141u, 109u,
- 0u, 230u, 124u, 124u,
- 12u, 85u, 71u, 35u,
- 104u, 116u, 245u, 212u,
- 161u, 222u, 70u, 170u,
- 67u, 1u, 49u, 104u,
- 78u, 236u, 189u, 142u,
- 3u, 71u, 109u, 115u,
- 61u, 100u, 25u, 40u,
- 132u, 136u, 247u, 1u,
- 148u, 102u, 133u, 56u,
- 133u, 140u, 238u, 180u,
- 130u, 153u, 131u, 142u,
- 103u, 66u, 63u, 95u,
- 91u, 255u, 181u, 103u,
- 160u, 88u, 90u, 255u,
- 148u, 15u, 161u, 160u,
- 37u, 230u, 123u, 119u,
- 118u, 129u, 113u, 179u,
- 75u, 132u, 144u, 48u,
- 165u, 170u, 119u, 161u,
- 141u, 0u, 8u, 224u,
- 173u, 139u, 75u, 15u,
- 1u, 195u, 13u, 221u,
- 114u, 145u, 248u, 106u,
- 18u, 255u, 209u, 159u,
- 15u, 138u, 27u, 225u,
- 91u, 235u, 158u, 80u,
- 197u, 131u, 32u, 194u,
- 66u, 143u, 147u, 61u,
- 1u, 84u, 162u, 99u,
- 103u, 56u, 63u, 197u,
- 121u, 119u, 162u, 115u,
- 103u, 164u, 110u, 167u,
- 40u, 83u, 121u, 0u,
- 211u, 60u, 103u, 66u,
- 86u, 155u, 27u, 84u,
- 178u, 1u, 66u, 38u,
- 189u, 53u, 152u, 122u,
- 84u, 84u, 194u, 66u,
- 59u, 108u, 127u, 1u,
- 18u, 209u, 148u, 13u,
- 98u, 165u, 90u, 12u,
- 187u, 255u, 155u, 109u,
- 157u, 120u, 145u, 171u,
- 120u, 202u, 130u, 107u,
- 78u, 77u, 95u, 169u,
- 208u, 83u, 73u, 82u,
- 102u, 105u, 160u, 109u,
- 52u, 83u, 191u, 234u,
- 255u, 226u, 228u, 215u,
- 135u, 120u, 31u, 90u,
- 1u, 96u, 172u, 87u,
- 114u, 147u, 142u, 157u,
- 231u, 135u, 99u, 191u,
- 124u, 118u, 152u, 166u,
- 190u, 108u, 119u, 184u,
- 26u, 52u, 132u, 106u,
- 172u, 255u, 163u, 153u,
- 113u, 113u, 165u, 127u,
- 98u, 150u, 107u, 106u,
- 118u, 123u, 158u, 78u,
- 144u, 0u, 120u, 82u,
- 134u, 140u, 187u, 166u,
- 163u, 120u, 45u, 202u,
- 157u, 84u, 0u, 138u,
- 151u, 159u, 128u, 159u,
- 40u, 124u, 150u, 101u,
- 115u, 183u, 179u, 110u,
- 181u, 38u, 58u, 255u,
- 169u, 178u, 127u, 40u,
- 161u, 10u, 99u, 199u,
- 121u, 1u, 170u, 211u,
- 231u, 206u, 243u, 139u,
- 205u, 92u, 95u, 161u,
- 74u, 170u, 150u, 231u,
- 115u, 43u, 149u, 103u,
- 136u, 209u, 129u, 141u,
- 72u, 255u, 143u, 101u,
- 71u, 187u, 114u, 47u,
- 138u, 136u, 126u, 155u,
- 100u, 39u, 26u, 255u,
- 122u, 35u, 30u, 81u,
- 241u, 255u, 129u, 87u,
- 110u, 191u, 85u, 114u,
- 170u, 54u, 63u, 181u,
- 18u, 115u, 65u, 32u,
- 81u, 48u, 62u, 95u,
- 73u, 178u, 218u, 86u,
- 156u, 1u, 74u, 216u,
- 87u, 164u, 104u, 67u,
- 69u, 1u, 77u, 145u,
- 102u, 31u, 141u, 75u,
- 169u, 135u, 138u, 104u,
- 172u, 107u, 105u, 28u,
- 79u, 177u, 112u, 113u,
- 162u, 113u, 203u, 208u,
- 255u, 225u, 192u, 192u,
- 136u, 21u, 141u, 92u,
- 169u, 44u, 187u, 77u,
- 137u, 161u, 1u, 118u,
- 176u, 81u, 95u, 62u,
- 177u, 178u, 180u, 87u,
- 82u, 135u, 99u, 154u,
- 169u, 47u, 202u, 193u,
- 80u, 180u, 255u, 169u,
- 58u, 169u, 54u, 232u,
- 137u, 120u, 37u, 171u,
- 172u, 101u, 166u, 73u,
- 1u, 202u, 68u, 146u,
- 175u, 204u, 49u, 131u,
- 170u, 255u, 169u, 196u,
- 109u, 101u, 180u, 135u,
- 218u, 144u, 148u, 167u,
- 111u, 154u, 147u, 186u,
- 153u, 36u, 77u, 119u,
- 5u, 172u, 162u, 103u,
- 135u, 91u, 64u, 178u,
- 151u, 34u, 255u, 186u,
- 150u, 114u, 197u, 185u,
- 46u, 118u, 74u, 25u,
- 195u, 50u, 100u, 143u,
- 110u, 178u, 0u, 115u,
- 62u, 157u, 255u, 91u,
- 48u, 182u, 217u, 59u,
- 214u, 51u, 160u, 112u,
- 154u, 146u, 173u, 96u,
- 222u, 73u, 197u, 245u,
- 69u, 73u, 109u, 61u,
- 81u, 97u, 161u, 123u,
- 113u, 110u, 1u, 137u,
- 50u, 117u, 100u, 186u,
- 92u, 193u, 144u, 253u,
- 157u, 95u, 145u, 255u,
- 87u, 83u, 58u, 104u,
- 150u, 172u, 105u, 12u,
- 249u, 141u, 40u, 217u,
- 99u, 140u, 105u, 92u,
- 141u, 1u, 149u, 105u,
- 224u, 198u, 160u, 168u,
- 93u, 153u, 98u, 62u,
- 159u, 143u, 144u, 126u,
- 0u, 171u, 159u, 170u,
- 219u, 80u, 158u, 37u,
- 33u, 173u, 111u, 1u,
- 109u, 175u, 13u, 162u,
- 217u, 131u, 144u, 106u,
- 98u, 88u, 70u, 96u,
- 20u, 223u, 70u, 154u,
- 86u, 107u, 72u, 210u,
- 236u, 0u, 93u, 66u,
- 0u, 76u, 168u, 164u,
- 145u, 188u, 135u, 131u,
- 202u, 45u, 96u, 115u,
- 98u, 45u, 174u, 111u,
- 109u, 187u, 119u, 132u,
- 255u, 71u, 136u, 124u,
- 115u, 68u, 212u, 45u,
- 159u, 255u, 21u, 189u,
- 105u, 160u, 255u, 175u,
- 137u, 148u, 108u, 135u,
- 175u, 94u, 44u, 111u,
- 108u, 96u, 112u, 189u,
- 255u, 233u, 210u, 224u,
- 90u, 213u, 5u, 206u,
- 159u, 158u, 202u, 35u,
- 63u, 232u, 143u, 202u,
- 152u, 91u, 23u, 3u,
- 104u, 227u, 255u, 148u,
- 167u, 111u, 95u, 203u,
- 96u, 156u, 205u, 88u,
- 3u, 171u, 151u, 164u,
- 139u, 159u, 85u, 166u,
- 215u, 62u, 174u, 215u,
- 78u, 94u, 1u, 124u,
- 113u, 102u, 80u, 64u,
- 201u, 136u, 120u, 195u,
- 62u, 87u, 1u, 110u,
- 120u, 184u, 120u, 103u,
- 62u, 28u, 12u, 185u,
- 153u, 33u, 247u, 224u,
- 131u, 91u, 154u, 255u,
- 31u, 224u, 142u, 217u,
- 112u, 91u, 1u, 151u,
- 153u, 219u, 172u, 211u,
- 89u, 112u, 175u, 122u,
- 95u, 101u, 179u, 167u,
- 1u, 50u, 170u, 180u,
- 84u, 183u, 86u, 189u,
- 180u, 49u, 148u, 208u,
- 103u, 88u, 101u, 131u,
- 111u, 254u, 0u, 6u,
- 142u, 70u, 134u, 130u,
- 154u, 158u, 151u, 116u,
- 117u, 85u, 79u, 64u,
- 101u, 97u, 118u, 221u,
- 74u, 70u, 179u, 35u,
- 121u, 243u, 202u, 105u,
- 37u, 165u, 202u, 255u,
- 11u, 125u, 248u, 64u,
- 133u, 166u, 92u, 127u,
- 202u, 87u, 167u, 59u,
- 1u, 82u, 133u, 80u,
- 122u, 75u, 77u, 182u,
- 96u, 0u, 127u, 92u,
- 73u, 148u, 192u, 22u,
- 116u, 102u, 137u, 173u,
- 118u, 187u, 68u, 112u,
- 94u, 122u, 1u, 52u,
- 35u, 173u, 149u, 74u,
- 86u, 167u, 115u, 76u,
- 88u, 67u, 200u, 235u,
- 255u, 181u, 113u, 136u,
- 169u, 37u, 64u, 147u,
- 170u, 45u, 124u, 122u,
- 201u, 119u, 156u, 104u,
- 250u, 64u, 124u, 167u,
- 124u, 125u, 80u, 185u,
- 166u, 255u, 56u, 109u,
- 61u, 72u, 196u, 86u,
- 160u, 177u, 255u, 128u,
- 165u, 164u, 107u, 245u,
- 109u, 239u, 186u, 145u,
- 99u, 98u, 74u, 31u,
- 168u, 156u, 104u, 152u,
- 0u, 75u, 88u, 111u,
- 229u, 163u, 138u, 160u,
- 102u, 89u, 157u, 192u,
- 183u, 8u, 91u, 198u,
- 53u, 109u, 119u, 59u,
- 148u, 255u, 185u, 251u,
- 115u, 76u, 89u, 183u,
- 55u, 169u, 255u, 91u,
- 200u, 124u, 189u, 154u,
- 91u, 138u, 207u, 47u,
- 24u, 141u, 83u, 117u,
- 164u, 103u, 129u, 229u,
- 88u, 117u, 103u, 211u,
- 96u, 255u, 109u, 134u,
- 73u, 152u, 191u, 90u,
- 112u, 211u, 255u, 60u,
- 156u, 96u, 194u, 163u,
- 165u, 209u, 203u, 186u,
- 81u, 213u, 140u, 148u,
- 154u, 160u, 201u, 111u,
- 134u, 67u, 96u, 146u,
- 119u, 104u, 157u, 255u,
- 186u, 137u, 188u, 225u,
- 80u, 38u, 205u, 65u,
- 125u, 50u, 28u, 204u,
- 214u, 181u, 1u, 127u,
- 83u, 60u, 31u, 106u,
- 149u, 86u, 226u, 54u,
- 133u, 119u, 46u, 255u,
- 114u, 247u, 84u, 137u,
- 183u, 31u, 166u, 144u,
- 77u, 41u, 75u, 35u,
- 115u, 155u, 109u, 99u,
- 211u, 255u, 112u, 36u,
- 125u, 151u, 102u, 150u,
- 172u, 61u, 121u, 194u,
- 106u, 125u, 78u, 231u,
- 145u, 187u, 147u, 255u,
- 111u, 141u, 34u, 255u,
- 106u, 158u, 175u, 66u,
- 87u, 89u, 36u, 84u,
- 166u, 145u, 167u, 144u,
- 92u, 115u, 47u, 180u,
- 180u, 41u, 242u, 84u,
- 101u, 220u, 255u, 164u,
- 92u, 194u, 96u, 202u,
- 123u, 179u, 162u, 141u,
- 144u, 147u, 22u, 140u,
- 143u, 35u, 139u, 68u,
- 95u, 58u, 95u, 255u,
- 88u, 103u, 117u, 126u,
- 121u, 103u, 175u, 91u,
- 176u, 96u, 203u, 137u,
- 85u, 153u, 182u, 1u,
- 255u, 242u, 39u, 175u,
- 128u, 229u, 107u, 191u,
- 127u, 198u, 43u, 50u,
- 212u, 107u, 242u, 100u,
- 109u, 148u, 100u, 131u,
- 215u, 117u, 115u, 121u,
- 171u, 186u, 254u, 135u,
- 183u, 74u, 1u, 143u,
- 141u, 87u, 87u, 225u,
- 180u, 55u, 67u, 119u,
- 96u, 111u, 34u, 116u,
- 126u, 113u, 1u, 136u,
- 166u, 132u, 255u, 165u,
- 143u, 159u, 171u, 150u,
- 98u, 96u, 99u, 155u,
- 126u, 60u, 239u, 75u,
- 164u, 116u, 217u, 74u,
- 255u, 186u, 82u, 165u,
- 71u, 104u, 96u, 185u,
- 127u, 247u, 227u, 10u,
- 143u, 190u, 199u, 64u,
- 0u, 199u, 114u, 168u,
- 109u, 53u, 232u, 109u,
- 181u, 10u, 79u, 170u,
- 108u, 166u, 60u, 3u,
- 192u, 154u, 85u, 255u,
- 87u, 11u, 33u, 240u,
- 95u, 186u, 195u, 96u,
- 189u, 160u, 225u, 194u,
- 100u, 223u, 51u, 190u,
- 135u, 179u, 45u, 34u,
- 145u, 222u, 153u, 255u,
- 67u, 38u, 73u, 68u,
- 214u, 48u, 171u, 171u,
- 144u, 33u, 251u, 255u,
- 121u, 175u, 175u, 246u,
- 45u, 47u, 116u, 187u,
- 150u, 37u, 255u, 60u,
- 128u, 185u, 98u, 127u,
- 112u, 130u, 91u, 95u,
- 125u, 148u, 197u, 186u,
- 170u, 211u, 168u, 139u,
- 148u, 160u, 226u, 35u,
- 70u, 91u, 173u, 255u,
- 148u, 133u, 255u, 200u,
- 95u, 220u, 147u, 107u,
- 220u, 79u, 79u, 83u,
- 208u, 157u, 192u, 141u,
- 54u, 41u, 196u, 150u,
- 139u, 0u, 107u, 87u,
- 79u, 62u, 113u, 133u,
- 155u, 174u, 24u, 143u,
- 145u, 64u, 1u, 186u,
- 84u, 142u, 126u, 136u,
- 89u, 172u, 138u, 197u,
- 60u, 79u, 43u, 154u,
- 210u, 120u, 98u, 117u,
- 127u, 146u, 81u, 68u,
- 95u, 102u, 1u, 190u,
- 127u, 53u, 32u, 72u,
- 0u, 203u, 167u, 134u,
- 151u, 204u, 139u, 244u,
- 119u, 29u, 71u, 176u,
- 177u, 204u, 175u, 160u,
- 108u, 45u, 49u, 229u,
- 53u, 221u, 94u, 217u,
- 157u, 156u, 254u, 94u,
- 114u, 23u, 1u, 44u,
- 0u, 78u, 73u, 161u,
- 120u, 62u, 158u, 101u,
- 107u, 77u, 109u, 218u,
- 119u, 194u, 122u, 164u,
- 57u, 107u, 154u, 65u,
- 216u, 37u, 101u, 124u,
- 150u, 98u, 255u, 72u,
- 86u, 96u, 131u, 83u,
- 255u, 254u, 155u, 75u,
- 151u, 213u, 80u, 153u,
- 96u, 208u, 180u, 91u,
- 60u, 68u, 173u, 80u,
- 122u, 86u, 174u, 97u,
- 29u, 224u, 146u, 255u,
- 158u, 204u, 133u, 207u,
- 193u, 125u, 82u, 147u,
- 129u, 124u, 66u, 209u,
- 0u, 76u, 165u, 16u,
- 142u, 108u, 39u, 146u,
- 167u, 75u, 127u, 253u,
- 157u, 66u, 108u, 145u,
- 27u, 132u, 191u, 143u,
- 148u, 252u, 255u, 82u,
- 143u, 108u, 154u, 114u,
- 165u, 132u, 146u, 128u,
- 140u, 99u, 69u, 255u,
- 95u, 91u, 149u, 61u,
- 124u, 69u, 90u, 182u,
- 67u, 225u, 200u, 150u,
- 143u, 255u, 218u, 190u,
- 155u, 174u, 47u, 194u,
- 125u, 228u, 188u, 211u,
- 108u, 66u, 166u, 181u,
- 100u, 157u, 255u, 98u,
- 188u, 171u, 179u, 92u,
- 82u, 73u, 148u, 82u,
- 203u, 213u, 186u, 173u,
- 114u, 178u, 1u, 213u,
- 128u, 125u, 100u, 116u,
- 126u, 193u, 33u, 206u,
- 30u, 58u, 99u, 213u,
- 113u, 42u, 163u, 83u,
- 200u, 172u, 134u, 103u,
- 184u, 80u, 0u, 140u,
- 61u, 146u, 162u, 177u,
- 255u, 69u, 114u, 147u,
- 139u, 148u, 247u, 230u,
- 30u, 91u, 20u, 122u,
- 73u, 63u, 93u, 167u,
- 136u, 168u, 104u, 54u,
- 150u, 60u, 43u, 179u,
- 1u, 80u, 172u, 60u,
- 175u, 118u, 102u, 62u,
- 207u, 133u, 211u, 161u,
- 122u, 185u, 105u, 255u,
- 234u, 81u, 129u, 221u,
- 255u, 114u, 250u, 165u,
- 74u, 223u, 72u, 80u,
- 126u, 37u, 127u, 75u,
- 185u, 169u, 159u, 124u,
- 114u, 100u, 37u, 161u,
- 201u, 0u, 173u, 168u,
- 116u, 184u, 183u, 132u,
- 50u, 121u, 116u, 216u,
- 133u, 92u, 88u, 218u,
- 140u, 144u, 228u, 8u,
- 160u, 39u, 82u, 93u,
- 135u, 143u, 231u, 255u,
- 173u, 160u, 162u, 206u,
- 217u, 100u, 150u, 62u,
- 102u, 109u, 255u, 124u,
- 173u, 164u, 7u, 185u,
- 1u, 56u, 102u, 182u,
- 131u, 111u, 219u, 138u,
- 143u, 134u, 200u, 202u,
- 128u, 164u, 34u, 136u,
- 116u, 169u, 255u, 192u,
- 123u, 131u, 163u, 129u,
- 109u, 80u, 96u, 133u,
- 93u, 133u, 128u, 138u,
- 98u, 23u, 1u, 142u,
- 102u, 115u, 82u, 88u,
- 178u, 154u, 99u, 168u,
- 162u, 194u, 105u, 110u,
- 183u, 112u, 45u, 73u,
- 184u, 100u, 152u, 66u,
- 109u, 181u, 148u, 158u,
- 0u, 86u, 181u, 38u,
- 255u, 127u, 155u, 134u,
- 157u, 210u, 64u, 138u,
- 58u, 61u, 165u, 103u,
- 119u, 100u, 162u, 54u,
- 47u, 169u, 94u, 150u,
- 92u, 169u, 255u, 80u,
- 159u, 187u, 112u, 195u,
- 112u, 71u, 24u, 190u,
- 152u, 129u, 159u, 67u,
- 106u, 42u, 96u, 208u,
- 147u, 175u, 253u, 54u,
- 97u, 75u, 47u, 255u,
- 67u, 147u, 86u, 202u,
- 192u, 90u, 255u, 129u,
- 144u, 126u, 194u, 171u,
- 65u, 202u, 17u, 151u,
- 218u, 1u, 108u, 158u,
- 128u, 125u, 128u, 146u,
- 105u, 117u, 96u, 44u,
- 166u, 74u, 255u, 158u,
- 154u, 1u, 46u, 137u,
- 67u, 63u, 80u, 70u,
- 136u, 73u, 138u, 6u,
- 113u, 124u, 186u, 184u,
- 175u, 197u, 50u, 0u,
- 156u, 108u, 181u, 147u,
- 246u, 176u, 2u, 207u,
- 125u, 51u, 106u, 197u,
- 44u, 202u, 39u, 117u,
- 163u, 163u, 222u, 86u,
- 225u, 81u, 120u, 96u,
- 176u, 76u, 255u, 55u,
- 156u, 141u, 149u, 228u,
- 57u, 255u, 16u, 194u,
- 196u, 120u, 127u, 126u,
- 74u, 65u, 179u, 236u,
- 91u, 210u, 111u, 62u,
- 174u, 255u, 30u, 242u,
- 109u, 2u, 24u, 128u,
- 125u, 60u, 134u, 92u,
- 207u, 157u, 215u, 108u,
- 133u, 181u, 1u, 191u,
- 156u, 17u, 33u, 182u,
- 133u, 174u, 130u, 77u,
- 142u, 124u, 90u, 108u,
- 113u, 1u, 145u, 136u,
- 93u, 153u, 149u, 144u,
- 81u, 105u, 90u, 140u,
- 19u, 182u, 74u, 130u,
- 144u, 100u, 93u, 203u,
- 103u, 134u, 127u, 255u,
- 84u, 91u, 94u, 158u,
- 21u, 110u, 158u, 149u,
- 157u, 145u, 89u, 140u,
- 77u, 134u, 115u, 142u,
- 1u, 76u, 172u, 166u,
- 72u, 124u, 148u, 165u,
- 161u, 25u, 97u, 255u,
- 81u, 115u, 134u, 144u,
- 20u, 55u, 49u, 162u,
- 81u, 74u, 125u, 255u,
- 91u, 122u, 149u, 97u,
- 185u, 43u, 189u, 162u,
- 134u, 168u, 30u, 94u,
- 205u, 255u, 145u, 103u,
- 189u, 178u, 85u, 151u,
- 81u, 145u, 104u, 94u,
- 101u, 85u, 123u, 132u,
- 161u, 57u, 255u, 221u,
- 97u, 131u, 83u, 151u,
- 211u, 14u, 32u, 215u,
- 118u, 203u, 61u, 99u,
- 182u, 146u, 7u, 62u,
- 146u, 19u, 165u, 124u,
- 86u, 255u, 142u, 110u,
- 191u, 128u, 117u, 226u,
- 182u, 197u, 68u, 112u,
- 86u, 124u, 156u, 146u,
- 51u, 118u, 123u, 186u,
- 157u, 124u, 1u, 158u,
- 145u, 8u, 113u, 107u,
- 31u, 38u, 180u, 124u,
- 85u, 255u, 74u, 212u,
- 89u, 138u, 66u, 31u,
- 213u, 168u, 112u, 182u,
- 203u, 145u, 147u, 86u,
- 252u, 165u, 72u, 225u,
- 167u, 51u, 255u, 9u,
- 81u, 82u, 140u, 201u,
- 54u, 251u, 131u, 130u,
- 103u, 156u, 98u, 77u,
- 96u, 87u, 255u, 117u,
- 49u, 129u, 112u, 238u,
- 239u, 162u, 114u, 156u,
- 126u, 130u, 166u, 157u,
- 254u, 216u, 255u, 174u,
- 50u, 130u, 147u, 93u,
- 74u, 187u, 127u, 100u,
- 217u, 140u, 162u, 87u,
- 36u, 70u, 255u, 61u,
- 125u, 46u, 142u, 131u,
- 97u, 5u, 102u, 93u,
- 134u, 174u, 116u, 105u,
- 238u, 255u, 172u, 77u,
- 157u, 87u, 137u, 173u,
- 122u, 26u, 150u, 110u,
- 162u, 133u, 255u, 123u,
- 117u, 169u, 5u, 148u,
- 144u, 75u, 77u, 74u,
- 107u, 55u, 175u, 52u,
- 84u, 84u, 102u, 1u,
- 143u, 243u, 149u, 129u,
- 239u, 255u, 151u, 59u,
- 178u, 170u, 63u, 120u,
- 89u, 116u, 103u, 55u,
- 77u, 80u, 185u, 148u,
- 105u, 104u, 134u, 164u,
- 101u, 157u, 57u, 183u,
- 124u, 74u, 66u, 22u,
- 255u, 67u, 220u, 55u,
- 177u, 84u, 78u, 170u,
- 55u, 96u, 188u, 114u,
- 142u, 112u, 193u, 117u,
- 1u, 48u, 82u, 233u,
- 219u, 147u, 189u, 138u,
- 118u, 134u, 113u, 192u,
- 61u, 179u, 251u, 68u,
- 142u, 1u, 135u, 146u,
- 151u, 131u, 115u, 122u,
- 119u, 83u, 141u, 129u,
- 131u, 75u, 137u, 146u,
- 126u, 108u, 1u, 119u,
- 50u, 1u, 79u, 144u,
- 82u, 55u, 149u, 92u,
- 158u, 134u, 129u, 136u,
- 163u, 138u, 166u, 172u,
- 26u, 81u, 0u, 225u,
- 93u, 167u, 164u, 178u,
- 98u, 146u, 65u, 124u,
- 93u, 74u, 70u, 140u,
- 170u, 67u, 184u, 114u,
- 88u, 31u, 101u, 62u,
- 126u, 169u, 85u, 130u,
- 187u, 255u, 129u, 13u,
- 222u, 105u, 239u, 159u,
- 167u, 248u, 113u, 1u,
- 205u, 23u, 101u, 39u,
- 188u, 111u, 156u, 96u,
- 152u, 72u, 159u, 176u,
- 50u, 47u, 177u, 34u,
- 149u, 212u, 255u, 56u,
- 54u, 151u, 190u, 154u,
- 132u, 227u, 38u, 176u,
- 77u, 144u, 104u, 227u,
- 1u, 205u, 138u, 55u,
- 144u, 234u, 158u, 149u,
- 135u, 127u, 195u, 122u,
- 85u, 61u, 35u, 1u,
- 109u, 105u, 104u, 162u,
- 91u, 59u, 53u, 187u,
- 255u, 171u, 201u, 182u,
- 74u, 124u, 122u, 127u,
- 131u, 169u, 89u, 125u,
- 170u, 136u, 98u, 123u,
- 123u, 197u, 239u, 188u,
- 135u, 197u, 170u, 85u,
- 183u, 56u, 130u, 255u,
- 165u, 219u, 44u, 123u,
- 165u, 147u, 198u, 205u,
- 79u, 17u, 150u, 255u,
- 91u, 40u, 43u, 177u,
- 189u, 224u, 162u, 124u,
- 0u, 205u, 79u, 176u,
- 224u, 222u, 212u, 152u,
- 178u, 115u, 29u, 140u,
- 86u, 44u, 155u, 171u,
- 169u, 133u, 130u, 171u,
- 57u, 255u, 191u, 77u,
- 138u, 193u, 55u, 163u,
- 129u, 105u, 160u, 91u,
- 199u, 128u, 122u, 168u,
- 68u, 28u, 66u, 145u,
- 105u, 160u, 160u, 105u,
- 112u, 1u, 90u, 205u,
- 196u, 51u, 32u, 111u,
- 138u, 50u, 48u, 163u,
- 163u, 221u, 124u, 173u,
- 116u, 68u, 255u, 55u,
- 177u, 118u, 106u, 161u,
- 123u, 35u, 118u, 155u,
- 130u, 170u, 152u, 105u,
- 69u, 159u, 192u, 255u,
- 83u, 226u, 194u, 240u,
- 168u, 106u, 1u, 130u,
- 110u, 213u, 130u, 100u,
- 173u, 169u, 113u, 226u,
- 28u, 119u, 255u, 87u,
- 127u, 174u, 77u, 193u,
- 135u, 44u, 214u, 69u,
- 67u, 54u, 169u, 201u,
- 89u, 152u, 141u, 82u,
- 103u, 126u, 152u, 66u,
- 178u, 212u, 255u, 121u,
- 119u, 133u, 190u, 171u,
- 22u, 189u, 133u, 92u,
- 132u, 198u, 164u, 132u,
- 153u, 45u, 43u, 255u,
- 174u, 186u, 141u, 7u,
- 141u, 99u, 116u, 169u,
- 187u, 125u, 1u, 101u,
- 116u, 252u, 202u, 249u,
- 225u, 104u, 32u, 193u,
- 149u, 84u, 102u, 119u,
- 234u, 77u, 135u, 208u,
- 85u, 99u, 59u, 255u,
- 140u, 108u, 62u, 177u,
- 24u, 15u, 91u, 239u,
- 199u, 152u, 1u, 118u,
- 218u, 59u, 69u, 9u,
- 56u, 255u, 144u, 195u,
- 242u, 116u, 135u, 183u,
- 177u, 114u, 46u, 90u,
- 255u, 55u, 54u, 153u,
- 147u, 36u, 209u, 86u,
- 88u, 60u, 149u, 153u,
- 83u, 124u, 203u, 138u,
- 165u, 73u, 100u, 117u,
- 125u, 114u, 255u, 15u,
- 116u, 213u, 181u, 204u,
- 83u, 169u, 86u, 176u,
- 117u, 76u, 51u, 105u,
- 139u, 149u, 118u, 255u,
- 92u, 143u, 159u, 209u,
- 1u, 155u, 200u, 154u,
- 244u, 91u, 77u, 210u,
- 128u, 102u, 228u, 155u,
- 1u, 163u, 130u, 49u,
- 185u, 122u, 208u, 77u,
- 132u, 73u, 104u, 203u,
- 120u, 159u, 148u, 121u,
- 107u, 14u, 61u, 215u,
- 179u, 21u, 84u, 207u,
- 89u, 0u, 98u, 20u,
- 23u, 173u, 65u, 148u,
- 133u, 63u, 124u, 187u,
- 161u, 23u, 249u, 24u,
- 93u, 56u, 196u, 148u,
- 112u, 177u, 22u, 255u,
- 88u, 95u, 219u, 167u,
- 51u, 255u, 141u, 156u,
- 163u, 85u, 81u, 161u,
- 139u, 83u, 218u, 142u,
- 67u, 94u, 135u, 255u,
- 219u, 177u, 204u, 198u,
- 145u, 149u, 161u, 196u,
- 178u, 102u, 64u, 132u,
- 153u, 140u, 68u, 136u,
- 7u, 105u, 1u, 149u,
- 192u, 109u, 92u, 52u,
- 137u, 145u, 186u, 49u,
- 53u, 152u, 35u, 41u,
- 119u, 255u, 122u, 248u,
- 237u, 133u, 180u, 162u,
- 192u, 116u, 109u, 179u,
- 121u, 109u, 107u, 116u,
- 214u, 108u, 138u, 197u,
- 101u, 202u, 86u, 111u,
- 159u, 177u, 50u, 255u,
- 92u, 126u, 255u, 80u,
- 183u, 160u, 107u, 23u,
- 187u, 162u, 200u, 127u,
- 62u, 81u, 215u, 172u,
- 160u, 222u, 154u, 133u,
- 136u, 255u, 119u, 167u,
- 168u, 84u, 119u, 88u,
- 203u, 214u, 140u, 49u,
- 168u, 135u, 165u, 63u,
- 202u, 149u, 123u, 255u,
- 175u, 96u, 142u, 70u,
- 51u, 54u, 32u, 99u,
- 207u, 255u, 231u, 161u,
- 151u, 176u, 74u, 167u,
- 180u, 121u, 92u, 151u,
- 112u, 161u, 25u, 152u,
- 125u, 202u, 174u, 148u,
- 28u, 87u, 227u, 136u,
- 187u, 139u, 170u, 122u,
- 64u, 155u, 255u, 126u,
- 133u, 131u, 176u, 120u,
- 83u, 165u, 134u, 155u,
- 184u, 77u, 21u, 156u,
- 66u, 95u, 141u, 255u,
- 139u, 66u, 19u, 3u,
- 215u, 39u, 158u, 146u,
- 149u, 146u, 82u, 255u,
- 106u, 113u, 172u, 146u,
- 137u, 195u, 145u, 185u,
- 142u, 20u, 10u, 146u,
- 156u, 105u, 184u, 166u,
- 60u, 157u, 1u, 114u,
- 1u, 136u, 89u, 131u,
- 120u, 120u, 169u, 111u,
- 90u, 36u, 77u, 158u,
- 122u, 129u, 166u, 108u,
- 237u, 149u, 86u, 136u,
- 114u, 1u, 139u, 103u,
- 182u, 178u, 30u, 83u,
- 199u, 175u, 52u, 100u,
- 152u, 255u, 64u, 37u,
- 128u, 197u, 100u, 218u,
- 40u, 82u, 38u, 87u,
- 143u, 94u, 50u, 159u,
- 105u, 120u, 109u, 52u,
- 255u, 88u, 107u, 117u,
- 137u, 35u, 180u, 140u,
- 168u, 107u, 98u, 110u,
- 0u, 94u, 65u, 160u,
- 132u, 98u, 197u, 237u,
- 67u, 89u, 167u, 240u,
- 163u, 194u, 30u, 153u,
- 18u, 51u, 106u, 219u,
- 70u, 211u, 136u, 153u,
- 155u, 200u, 168u, 108u,
- 87u, 1u, 200u, 187u,
- 116u, 1u, 55u, 136u,
- 161u, 78u, 221u, 115u,
- 128u, 255u, 149u, 134u,
- 159u, 160u, 111u, 208u,
- 169u, 119u, 133u, 138u,
- 108u, 151u, 59u, 178u,
- 150u, 0u, 48u, 186u,
- 102u, 138u, 79u, 99u,
- 77u, 41u, 153u, 202u,
- 182u, 145u, 155u, 86u,
- 161u, 19u, 126u, 255u,
- 134u, 176u, 60u, 25u,
- 112u, 123u, 1u, 151u,
- 87u, 198u, 82u, 107u,
- 95u, 202u, 71u, 142u,
- 185u, 226u, 59u, 94u,
- 246u, 101u, 244u, 169u,
- 249u, 255u, 99u, 13u,
- 117u, 47u, 137u, 1u,
- 227u, 138u, 62u, 110u,
- 244u, 58u, 97u, 156u,
- 1u, 169u, 209u, 93u,
- 168u, 141u, 128u, 175u,
- 186u, 146u, 198u, 81u,
- 62u, 96u, 122u, 203u,
- 118u, 115u, 255u, 43u,
- 79u, 201u, 164u, 103u,
- 46u, 133u, 100u, 222u,
- 98u, 161u, 191u, 146u,
- 96u, 151u, 139u, 160u,
- 190u, 170u, 81u, 146u,
- 82u, 26u, 192u, 255u,
- 108u, 219u, 88u, 43u,
- 153u, 198u, 76u, 197u,
- 126u, 88u, 108u, 128u,
- 110u, 1u, 68u, 128u,
- 244u, 147u, 118u, 47u,
- 118u, 93u, 4u, 95u,
- 97u, 1u, 16u, 33u,
- 154u, 118u, 95u, 72u,
- 141u, 88u, 142u, 123u,
- 137u, 39u, 123u, 82u,
- 103u, 241u, 169u, 107u,
- 190u, 255u, 77u, 68u,
- 60u, 193u, 66u, 60u,
- 103u, 112u, 163u, 181u,
- 163u, 130u, 139u, 237u,
- 149u, 1u, 34u, 151u,
- 119u, 212u, 154u, 72u,
- 106u, 85u, 215u, 74u,
- 168u, 152u, 255u, 83u,
- 133u, 188u, 185u, 168u,
- 204u, 165u, 198u, 89u,
- 1u, 168u, 194u, 224u,
- 155u, 83u, 30u, 254u,
- 207u, 26u, 187u, 55u,
- 102u, 118u, 105u, 124u,
- 0u, 212u, 193u, 160u,
- 99u, 63u, 143u, 93u,
- 23u, 146u, 106u, 121u,
- 99u, 151u, 75u, 200u,
- 1u, 151u, 155u, 203u,
- 82u, 125u, 97u, 119u,
- 168u, 170u, 90u, 104u,
- 94u, 142u, 159u, 1u,
- 167u, 139u, 70u, 139u,
- 155u, 108u, 158u, 202u,
- 84u, 68u, 91u, 94u,
- 67u, 95u, 169u, 255u,
- 241u, 142u, 84u, 109u,
- 197u, 44u, 99u, 110u,
- 76u, 100u, 33u, 93u,
- 77u, 75u, 24u, 124u,
- 92u, 97u, 57u, 185u,
- 187u, 148u, 173u, 1u,
- 122u, 129u, 190u, 226u,
- 143u, 127u, 215u, 156u,
- 161u, 118u, 26u, 108u,
- 180u, 166u, 195u, 1u,
- 85u, 72u, 169u, 100u,
- 70u, 62u, 55u, 137u,
- 105u, 140u, 222u, 90u,
- 126u, 78u, 142u, 1u,
- 181u, 48u, 144u, 120u,
- 173u, 93u, 78u, 1u,
- 36u, 28u, 52u, 160u,
- 155u, 87u, 148u, 56u,
- 193u, 53u, 163u, 189u,
- 247u, 110u, 214u, 227u,
- 125u, 60u, 97u, 123u,
- 251u, 91u, 109u, 95u,
- 1u, 26u, 183u, 179u,
- 212u, 157u, 195u, 249u,
- 167u, 47u, 223u, 1u,
- 73u, 3u, 243u, 37u,
- 132u, 181u, 60u, 203u,
- 77u, 102u, 209u, 104u,
- 124u, 136u, 202u, 97u,
- 160u, 170u, 255u, 140u,
- 121u, 201u, 122u, 171u,
- 171u, 253u, 194u, 63u,
- 193u, 101u, 255u, 197u,
- 248u, 95u, 150u, 179u,
- 133u, 67u, 153u, 246u,
- 147u, 166u, 174u, 255u,
- 135u, 102u, 177u, 150u,
- 158u, 78u, 122u, 40u,
- 101u, 73u, 56u, 60u,
- 112u, 175u, 181u, 150u,
- 163u, 66u, 152u, 133u,
- 114u, 189u, 164u, 137u,
- 72u, 50u, 190u, 255u,
- 88u, 187u, 160u, 32u,
- 159u, 220u, 132u, 86u,
- 157u, 78u, 99u, 127u,
- 132u, 187u, 255u, 139u,
- 133u, 134u, 162u, 194u,
- 173u, 149u, 110u, 54u,
- 65u, 129u, 184u, 195u,
- 0u, 86u, 99u, 72u,
- 61u, 1u, 127u, 151u,
- 147u, 195u, 152u, 138u,
- 34u, 98u, 102u, 173u,
- 168u, 136u, 183u, 111u,
- 204u, 110u, 167u, 242u,
- 143u, 98u, 69u, 147u,
- 163u, 36u, 57u, 175u,
- 43u, 67u, 1u, 33u,
- 132u, 89u, 173u, 223u,
- 241u, 1u, 20u, 193u,
- 116u, 2u, 125u, 76u,
- 83u, 121u, 99u, 142u,
- 218u, 195u, 108u, 105u,
- 34u, 207u, 118u, 45u,
- 27u, 127u, 41u, 85u,
- 153u, 114u, 38u, 255u,
- 129u, 233u, 115u, 115u,
- 126u, 116u, 84u, 255u,
- 62u, 123u, 167u, 86u,
- 102u, 117u, 98u, 206u,
- 142u, 158u, 114u, 89u,
- 178u, 184u, 143u, 206u,
- 171u, 1u, 121u, 253u,
- 101u, 126u, 122u, 171u,
- 118u, 179u, 138u, 164u,
- 141u, 154u, 255u, 120u,
- 167u, 131u, 162u, 147u,
- 191u, 148u, 20u, 128u,
- 36u, 59u, 89u, 244u,
- 83u, 92u, 37u, 105u,
- 124u, 33u, 94u, 139u,
- 1u, 136u, 57u, 107u,
- 35u, 143u, 147u, 96u,
- 162u, 169u, 212u, 128u,
- 147u, 122u, 144u, 160u,
- 98u, 198u, 115u, 1u,
- 138u, 39u, 150u, 162u,
- 123u, 189u, 107u, 170u,
- 98u, 136u, 131u, 86u,
- 108u, 84u, 255u, 167u,
- 136u, 173u, 168u, 138u,
- 101u, 86u, 171u, 81u,
- 133u, 255u, 221u, 77u,
- 109u, 120u, 160u, 174u,
- 147u, 202u, 218u, 155u,
- 84u, 236u, 140u, 82u,
- 183u, 1u, 189u, 171u,
- 145u, 148u, 13u, 82u,
- 71u, 90u, 171u, 137u,
- 0u, 121u, 168u, 146u,
- 102u, 234u, 97u, 113u,
- 220u, 18u, 142u, 130u,
- 26u, 104u, 174u, 233u,
- 139u, 12u, 220u, 77u,
- 201u, 145u, 156u, 158u,
- 1u, 231u, 171u, 112u,
- 86u, 180u, 145u, 71u,
- 146u, 107u, 107u, 163u,
- 148u, 78u, 224u, 149u,
- 166u, 105u, 1u, 77u,
- 0u, 81u, 89u, 95u,
- 186u, 84u, 124u, 154u,
- 158u, 116u, 221u, 91u,
- 85u, 124u, 77u, 175u,
- 80u, 104u, 244u, 191u,
- 200u, 138u, 185u, 34u,
- 144u, 68u, 46u, 255u,
- 172u, 249u, 13u, 101u,
- 61u, 116u, 145u, 203u,
- 68u, 154u, 137u, 215u,
- 124u, 1u, 95u, 190u,
- 253u, 203u, 167u, 224u,
- 137u, 165u, 127u, 164u,
- 147u, 0u, 94u, 71u,
- 153u, 222u, 240u, 134u,
- 131u, 93u, 4u, 102u,
- 202u, 137u, 125u, 144u,
- 112u, 218u, 104u, 133u,
- 135u, 129u, 1u, 79u,
- 115u, 96u, 69u, 91u,
- 56u, 128u, 93u, 22u,
- 75u, 29u, 0u, 191u,
- 186u, 53u, 152u, 21u,
- 227u, 141u, 153u, 100u,
- 121u, 152u, 120u, 101u,
- 78u, 1u, 180u, 104u,
- 220u, 127u, 242u, 84u,
- 149u, 156u, 249u, 148u,
- 10u, 0u, 238u, 149u,
- 15u, 216u, 55u, 112u,
- 192u, 40u, 195u, 93u,
- 88u, 23u, 142u, 151u,
- 139u, 92u, 89u, 156u,
- 108u, 28u, 183u, 29u,
- 150u, 255u, 188u, 72u,
- 120u, 75u, 188u, 133u,
- 65u, 206u, 161u, 181u,
- 119u, 171u, 100u, 157u,
- 200u, 108u, 237u, 122u,
- 1u, 167u, 127u, 88u,
- 151u, 133u, 164u, 107u,
- 223u, 165u, 96u, 76u,
- 248u, 115u, 225u, 69u,
- 255u, 122u, 153u, 102u,
- 143u, 127u, 156u, 103u,
- 149u, 140u, 139u, 82u,
- 71u, 12u, 71u, 72u,
- 255u, 233u, 129u, 46u,
- 14u, 239u, 255u, 90u,
- 147u, 221u, 180u, 73u,
- 230u, 129u, 163u, 136u,
- 132u, 183u, 244u, 71u,
- 239u, 213u, 177u, 106u,
- 77u, 128u, 255u, 40u,
- 122u, 123u, 244u, 151u,
- 108u, 175u, 120u, 31u,
- 176u, 152u, 255u, 142u,
- 138u, 189u, 88u, 122u,
- 112u, 65u, 54u, 143u,
- 111u, 145u, 133u, 39u,
- 17u, 155u, 175u, 97u,
- 102u, 77u, 117u, 134u,
- 174u, 72u, 160u, 147u,
- 164u, 214u, 225u, 1u,
- 31u, 11u, 133u, 97u,
- 124u, 110u, 223u, 101u,
- 255u, 148u, 254u, 255u,
- 165u, 120u, 141u, 174u,
- 134u, 255u, 150u, 96u,
- 159u, 211u, 108u, 184u,
- 109u, 87u, 148u, 175u,
- 72u, 67u, 73u, 153u,
- 99u, 154u, 164u, 255u,
- 173u, 136u, 128u, 122u,
- 141u, 124u, 85u, 139u,
- 137u, 58u, 120u, 176u,
- 92u, 15u, 145u, 137u,
- 200u, 127u, 176u, 1u,
- 74u, 90u, 18u, 142u,
- 169u, 105u, 88u, 64u,
- 166u, 184u, 126u, 176u,
- 95u, 255u, 237u, 60u,
- 96u, 37u, 68u, 182u,
- 107u, 53u, 129u, 202u,
- 1u, 34u, 118u, 105u,
- 155u, 83u, 93u, 183u,
- 212u, 96u, 194u, 209u,
- 40u, 49u, 115u, 28u,
- 126u, 148u, 192u, 171u,
- 94u, 255u, 89u, 182u,
- 183u, 1u, 139u, 63u,
- 104u, 153u, 104u, 40u,
- 209u, 213u, 178u, 92u,
- 123u, 107u, 1u, 210u,
- 114u, 139u, 132u, 169u,
- 216u, 72u, 8u, 119u,
- 103u, 109u, 128u, 133u,
- 98u, 238u, 107u, 96u,
- 112u, 35u, 114u, 72u,
- 140u, 147u, 145u, 255u,
- 1u, 130u, 124u, 138u,
- 196u, 98u, 145u, 189u,
- 101u, 51u, 53u, 191u,
- 224u, 125u, 142u, 134u,
- 46u, 162u, 53u, 202u,
- 145u, 152u, 253u, 213u,
- 149u, 52u, 125u, 239u,
- 57u, 203u, 0u, 252u,
- 238u, 163u, 146u, 130u,
- 117u, 158u, 1u, 207u,
- 223u, 59u, 88u, 204u,
- 126u, 48u, 13u, 40u,
- 108u, 53u, 107u, 198u,
- 140u, 0u, 136u, 150u,
- 169u, 238u, 201u, 58u,
- 63u, 164u, 162u, 159u,
- 141u, 79u, 19u, 76u,
- 88u, 255u, 67u, 223u,
- 132u, 239u, 157u, 110u,
- 49u, 66u, 62u, 137u,
- 122u, 189u, 143u, 11u,
- 97u, 151u, 131u, 88u,
- 126u, 113u, 21u, 99u,
- 255u, 53u, 149u, 29u,
- 123u, 0u, 195u, 149u,
- 208u, 66u, 32u, 138u,
- 160u, 73u, 141u, 73u,
- 143u, 93u, 96u, 91u,
- 211u, 145u, 101u, 86u,
- 196u, 198u, 39u, 233u,
- 255u, 84u, 168u, 108u,
- 194u, 31u, 154u, 22u,
- 69u, 192u, 82u, 60u,
- 151u, 123u, 158u, 150u,
- 80u, 53u, 193u, 255u,
- 163u, 207u, 82u, 201u,
- 111u, 105u, 131u, 39u,
- 1u, 224u, 46u, 15u,
- 193u, 106u, 11u, 170u,
- 12u, 151u, 134u, 175u,
- 130u, 176u, 116u, 94u,
- 128u, 156u, 196u, 191u,
- 54u, 255u, 127u, 133u,
- 228u, 59u, 139u, 161u,
- 159u, 83u, 93u, 104u,
- 132u, 101u, 110u, 126u,
- 119u, 80u, 73u, 171u,
- 135u, 255u, 84u, 164u,
- 255u, 92u, 147u, 65u,
- 214u, 156u, 175u, 145u,
- 77u, 205u, 97u, 131u,
- 161u, 152u, 164u, 203u,
- 29u, 104u, 88u, 181u,
- 253u, 218u, 70u, 255u,
- 150u, 107u, 173u, 169u,
- 50u, 254u, 131u, 46u,
- 93u, 166u, 127u, 143u,
- 116u, 146u, 182u, 165u,
- 124u, 150u, 255u, 194u,
- 85u, 179u, 73u, 189u,
- 14u, 140u, 75u, 143u,
- 63u, 188u, 231u, 239u,
- 222u, 99u, 132u, 255u,
- 217u, 203u, 85u, 200u,
- 177u, 161u, 168u, 184u,
- 109u, 129u, 126u, 116u,
- 32u, 109u, 141u, 95u,
- 124u, 255u, 148u, 150u,
- 222u, 128u, 148u, 239u,
- 177u, 104u, 143u, 65u,
- 110u, 151u, 156u, 49u,
- 152u, 255u, 97u, 185u,
- 206u, 247u, 85u, 111u,
- 64u, 216u, 144u, 169u,
- 59u, 176u, 95u, 25u,
- 109u, 108u, 255u, 219u,
- 115u, 1u, 147u, 177u,
- 98u, 87u, 140u, 85u,
- 105u, 219u, 110u, 137u,
- 140u, 183u, 88u, 80u,
- 151u, 124u, 73u, 165u,
- 158u, 70u, 172u, 145u,
- 141u, 245u, 255u, 69u,
- 153u, 92u, 175u, 96u,
- 235u, 249u, 112u, 39u,
- 133u, 109u, 98u, 55u,
- 102u, 155u, 164u, 79u,
- 98u, 149u, 171u, 255u,
- 109u, 116u, 124u, 183u,
- 106u, 140u, 59u, 219u,
- 88u, 160u, 0u, 158u,
- 152u, 234u, 149u, 203u,
- 170u, 127u, 187u, 63u,
- 107u, 224u, 0u, 131u,
- 91u, 72u, 127u, 100u,
- 142u, 230u, 89u, 107u,
- 96u, 188u, 173u, 69u,
- 192u, 107u, 90u, 174u,
- 1u, 154u, 205u, 150u,
- 248u, 228u, 53u, 130u,
- 91u, 223u, 148u, 187u,
- 195u, 115u, 123u, 233u,
- 136u, 255u, 244u, 96u,
- 18u, 116u, 66u, 148u,
- 184u, 253u, 69u, 128u,
- 138u, 191u, 206u, 174u,
- 59u, 149u, 255u, 192u,
- 74u, 119u, 61u, 149u,
- 208u, 197u, 133u, 170u,
- 228u, 131u, 235u, 247u,
- 1u, 62u, 152u, 158u,
- 178u, 223u, 222u, 125u,
- 48u, 194u, 163u, 1u,
- 226u, 155u, 83u, 131u,
- 117u, 118u, 106u, 223u,
- 68u, 125u, 85u, 54u,
- 145u, 163u, 129u, 189u,
- 197u, 86u, 162u, 126u,
- 181u, 190u, 147u, 85u,
- 151u, 1u, 117u, 125u,
- 131u, 225u, 249u, 173u,
- 193u, 97u, 247u, 116u,
- 71u, 151u, 156u, 114u,
- 146u, 202u, 255u, 235u,
- 102u, 73u, 115u, 89u,
- 98u, 142u, 80u, 128u,
- 153u, 54u, 1u, 144u,
- 136u, 178u, 113u, 15u,
- 100u, 70u, 185u, 190u,
- 102u, 64u, 148u, 91u,
- 47u, 151u, 181u, 93u,
- 255u, 171u, 110u, 210u,
- 42u, 154u, 173u, 178u,
- 129u, 86u, 116u, 188u,
- 137u, 255u, 72u, 76u,
- 5u, 66u, 97u, 165u,
- 168u, 164u, 138u, 102u,
- 83u, 95u, 21u, 255u,
- 201u, 196u, 157u, 17u,
- 132u, 75u, 224u, 131u,
- 141u, 178u, 173u, 213u,
- 139u, 212u, 147u, 164u,
- 1u, 115u, 87u, 124u,
- 253u, 115u, 227u, 188u,
- 108u, 255u, 152u, 101u,
- 219u, 208u, 161u, 203u,
- 97u, 86u, 68u, 224u,
- 113u, 109u, 115u, 44u,
- 98u, 70u, 119u, 173u,
- 5u, 162u, 113u, 216u,
- 235u, 1u, 188u, 160u,
- 36u, 108u, 158u, 126u,
- 149u, 41u, 90u, 226u,
- 196u, 193u, 41u, 255u,
- 76u, 111u, 131u, 123u,
- 119u, 113u, 137u, 138u,
- 96u, 126u, 75u, 149u,
- 146u, 252u, 117u, 230u,
- 57u, 122u, 79u, 179u,
- 99u, 57u, 199u, 1u,
- 61u, 185u, 160u, 111u,
- 171u, 0u, 114u, 138u,
- 214u, 143u, 206u, 44u,
- 35u, 111u, 67u, 151u,
- 58u, 100u, 117u, 210u,
- 246u, 176u, 150u, 212u,
- 103u, 125u, 151u, 101u,
- 133u, 125u, 255u, 133u,
- 233u, 88u, 18u, 38u,
- 31u, 1u, 122u, 182u,
- 168u, 67u, 85u, 209u,
- 128u, 30u, 80u, 118u,
- 137u, 91u, 123u, 86u,
- 0u, 129u, 154u, 73u,
- 158u, 84u, 82u, 90u,
- 122u, 145u, 199u, 134u,
- 0u, 93u, 78u, 211u,
- 163u, 99u, 144u, 188u,
- 122u, 112u, 141u, 240u,
- 64u, 225u, 9u, 85u,
- 159u, 93u, 139u, 80u,
- 140u, 200u, 19u, 146u,
- 187u, 132u, 141u, 191u,
- 117u, 255u, 133u, 12u,
- 97u, 48u, 148u, 84u,
- 225u, 71u, 136u, 1u,
- 95u, 209u, 121u, 195u,
- 71u, 188u, 73u, 114u,
- 146u, 150u, 105u, 110u,
- 192u, 166u, 43u, 187u,
- 95u, 91u, 187u, 220u,
- 169u, 132u, 14u, 1u,
- 125u, 85u, 90u, 201u,
- 143u, 131u, 180u, 146u,
- 103u, 77u, 137u, 249u,
- 143u, 255u, 25u, 231u,
- 140u, 147u, 71u, 144u,
- 64u, 126u, 33u, 159u,
- 123u, 252u, 255u, 130u,
- 108u, 174u, 91u, 91u,
- 72u, 74u, 119u, 150u,
- 96u, 52u, 165u, 143u,
- 170u, 206u, 255u, 82u,
- 84u, 172u, 115u, 170u,
- 149u, 1u, 117u, 189u,
- 135u, 190u, 120u, 235u,
- 51u, 0u, 80u, 77u,
- 194u, 117u, 178u, 169u,
- 103u, 148u, 45u, 150u,
- 62u, 186u, 52u, 174u,
- 122u, 88u, 0u, 207u,
- 4u, 164u, 82u, 45u,
- 83u, 196u, 209u, 169u,
- 179u, 220u, 63u, 255u,
- 97u, 10u, 71u, 237u,
- 95u, 247u, 72u, 131u,
- 1u, 115u, 227u, 171u,
- 197u, 182u, 110u, 184u,
- 115u, 65u, 125u, 149u,
- 108u, 92u, 157u, 79u,
- 234u, 181u, 205u, 0u,
- 73u, 151u, 130u, 154u,
- 92u, 109u, 69u, 106u,
- 109u, 4u, 156u, 201u,
- 161u, 250u, 204u, 142u,
- 60u, 193u, 47u, 208u,
- 91u, 77u, 143u, 140u,
- 52u, 213u, 127u, 255u,
- 1u, 48u, 209u, 163u,
- 234u, 188u, 155u, 175u,
- 85u, 117u, 129u, 86u,
- 115u, 133u, 157u, 112u,
- 60u, 88u, 111u, 255u,
- 65u, 194u, 4u, 87u,
- 128u, 149u, 239u, 111u,
- 144u, 39u, 182u, 131u,
- 91u, 110u, 123u, 122u,
- 197u, 58u, 97u, 135u,
- 175u, 156u, 255u, 80u,
- 91u, 115u, 125u, 81u,
- 22u, 130u, 198u, 133u,
- 158u, 229u, 255u, 166u,
- 150u, 171u, 105u, 232u,
- 110u, 214u, 151u, 82u,
- 160u, 0u, 135u, 198u,
- 249u, 72u, 189u, 167u,
- 92u, 132u, 125u, 81u,
- 186u, 111u, 155u, 157u,
- 98u, 85u, 0u, 88u,
- 93u, 131u, 88u, 155u,
- 186u, 57u, 165u, 172u,
- 31u, 43u, 143u, 138u,
- 255u, 218u, 107u, 45u,
- 249u, 195u, 151u, 70u,
- 207u, 22u, 184u, 202u,
- 99u, 186u, 105u, 122u,
- 43u, 151u, 221u, 172u,
- 150u, 255u, 149u, 135u,
- 77u, 69u, 187u, 143u,
- 155u, 239u, 86u, 59u,
- 0u, 184u, 118u, 127u,
- 141u, 124u, 121u, 69u,
- 180u, 147u, 133u, 61u,
- 192u, 51u, 159u, 139u,
- 208u, 51u, 13u, 245u,
- 34u, 9u, 6u, 0u,
- 222u, 74u, 79u, 11u,
- 92u, 113u, 179u, 105u,
- 164u, 59u, 183u, 145u,
- 1u, 80u, 122u, 109u,
- 80u, 47u, 183u, 142u,
- 93u, 90u, 111u, 20u,
- 153u, 172u, 149u, 154u,
- 130u, 244u, 113u, 98u,
- 159u, 27u, 1u, 255u,
- 1u, 244u, 208u, 126u,
- 143u, 75u, 169u, 176u,
- 87u, 170u, 93u, 136u,
- 51u, 99u, 1u, 161u,
- 161u, 109u, 248u, 231u,
- 151u, 182u, 170u, 162u,
- 125u, 255u, 146u, 85u,
- 127u, 87u, 142u, 145u,
- 123u, 154u, 49u, 112u,
- 63u, 17u, 51u, 196u,
- 67u, 39u, 255u, 147u,
- 76u, 133u, 212u, 163u,
- 122u, 185u, 55u, 174u,
- 105u, 129u, 131u, 63u,
- 137u, 215u, 226u, 0u,
- 247u, 174u, 117u, 240u,
- 55u, 99u, 165u, 83u,
- 96u, 165u, 111u, 92u,
- 44u, 255u, 17u, 81u,
- 100u, 47u, 189u, 178u,
- 170u, 85u, 135u, 100u,
- 213u, 255u, 217u, 53u,
- 135u, 140u, 60u, 141u,
- 108u, 103u, 170u, 82u,
- 81u, 12u, 72u, 87u,
- 97u, 17u, 255u, 184u,
- 93u, 176u, 167u, 73u,
- 185u, 123u, 94u, 78u,
- 125u, 170u, 198u, 94u,
- 233u, 169u, 114u, 1u,
- 207u, 105u, 118u, 176u,
- 201u, 93u, 147u, 213u,
- 118u, 106u, 76u, 71u,
- 135u, 228u, 45u, 128u,
- 169u, 11u, 172u, 217u,
- 7u, 187u, 150u, 78u,
- 126u, 240u, 132u, 255u,
- 90u, 203u, 58u, 87u,
- 112u, 197u, 177u, 157u,
- 155u, 78u, 169u, 255u,
- 1u, 112u, 217u, 19u,
- 31u, 114u, 62u, 140u,
- 79u, 134u, 88u, 116u,
- 186u, 63u, 83u, 175u,
- 0u, 28u, 110u, 152u,
- 104u, 127u, 120u, 255u,
- 224u, 216u, 150u, 7u,
- 87u, 15u, 116u, 36u,
- 108u, 145u, 141u, 231u,
- 101u, 7u, 76u, 167u,
- 120u, 71u, 186u, 16u,
- 160u, 255u, 236u, 68u,
- 79u, 69u, 182u, 116u,
- 198u, 114u, 141u, 230u,
- 55u, 93u, 108u, 92u,
- 156u, 171u, 168u, 178u,
- 116u, 255u, 111u, 62u,
- 84u, 183u, 169u, 95u,
- 176u, 205u, 131u, 190u,
- 157u, 1u, 132u, 169u,
- 74u, 113u, 62u, 155u,
- 70u, 143u, 172u, 92u,
- 223u, 109u, 184u, 249u,
- 17u, 102u, 219u, 97u,
- 137u, 160u, 127u, 1u,
- 157u, 165u, 125u, 151u,
- 149u, 119u, 1u, 217u,
- 129u, 193u, 104u, 119u,
- 82u, 174u, 48u, 148u,
- 107u, 50u, 132u, 199u,
- 118u, 112u, 57u, 165u,
- 174u, 33u, 77u, 208u,
- 162u, 51u, 1u, 68u,
- 166u, 150u, 199u, 138u,
- 1u, 136u, 87u, 228u,
- 167u, 77u, 112u, 35u,
- 131u, 143u, 128u, 24u,
- 24u, 164u, 156u, 181u,
- 133u, 140u, 158u, 116u,
- 178u, 87u, 163u, 165u,
- 42u, 131u, 0u, 102u,
- 132u, 83u, 155u, 231u,
- 183u, 57u, 127u, 160u,
- 220u, 136u, 251u, 120u,
- 1u, 120u, 123u, 39u,
- 143u, 165u, 132u, 189u,
- 95u, 15u, 135u, 82u,
- 105u, 212u, 127u, 110u,
- 79u, 98u, 114u, 255u,
- 87u, 130u, 107u, 202u,
- 75u, 157u, 255u, 146u,
- 187u, 90u, 135u, 174u,
- 132u, 137u, 197u, 118u,
- 52u, 182u, 179u, 180u,
- 163u, 191u, 134u, 91u,
- 119u, 64u, 255u, 155u,
- 143u, 174u, 132u, 131u,
- 232u, 60u, 154u, 255u,
- 92u, 56u, 103u, 92u,
- 118u, 111u, 88u, 173u,
- 42u, 93u, 38u, 73u,
- 27u, 91u, 106u, 163u,
- 200u, 0u, 89u, 6u,
- 198u, 102u, 176u, 31u,
- 94u, 150u, 145u, 165u,
- 26u, 1u, 143u, 220u,
- 74u, 68u, 183u, 89u,
- 222u, 18u, 216u, 124u,
- 50u, 163u, 147u, 96u,
- 75u, 198u, 38u, 200u,
- 179u, 177u, 255u, 151u,
- 116u, 139u, 140u, 158u,
- 52u, 143u, 222u, 213u,
- 195u, 1u, 84u, 113u,
- 100u, 89u, 207u, 5u,
- 166u, 102u, 1u, 187u,
- 164u, 116u, 150u, 81u,
- 184u, 52u, 135u, 54u,
- 152u, 173u, 170u, 138u,
- 184u, 97u, 255u, 210u,
- 62u, 91u, 147u, 187u,
- 255u, 177u, 162u, 112u,
- 102u, 76u, 108u, 116u,
- 92u, 171u, 15u, 135u,
- 240u, 168u, 102u, 216u,
- 46u, 41u, 163u, 194u,
- 145u, 1u, 85u, 205u,
- 49u, 110u, 76u, 158u,
- 38u, 131u, 2u, 131u,
- 82u, 42u, 148u, 255u,
- 95u, 155u, 64u, 150u,
- 138u, 40u, 123u, 154u,
- 104u, 138u, 114u, 138u,
- 183u, 139u, 154u, 160u,
- 141u, 235u, 148u, 106u,
- 67u, 12u, 139u, 186u,
- 111u, 255u, 78u, 68u,
- 157u, 143u, 202u, 175u,
- 66u, 255u, 170u, 133u,
- 126u, 181u, 136u, 125u,
- 93u, 123u, 198u, 179u,
- 246u, 29u, 172u, 195u,
- 184u, 208u, 109u, 66u,
- 155u, 56u, 144u, 0u,
- 177u, 67u, 159u, 140u,
- 81u, 113u, 125u, 76u,
- 148u, 28u, 194u, 60u,
- 137u, 255u, 202u, 65u,
- 54u, 42u, 126u, 166u,
- 81u, 255u, 124u, 94u,
- 159u, 133u, 223u, 155u,
- 186u, 65u, 220u, 211u,
- 13u, 140u, 232u, 122u,
- 44u, 139u, 9u, 99u,
- 1u, 156u, 171u, 185u,
- 205u, 118u, 119u, 205u,
- 93u, 6u, 174u, 37u,
- 1u, 94u, 196u, 122u,
- 143u, 172u, 89u, 186u,
- 229u, 111u, 138u, 167u,
- 127u, 31u, 114u, 46u,
- 185u, 69u, 213u, 255u,
- 142u, 91u, 86u, 103u,
- 206u, 85u, 56u, 152u,
- 116u, 58u, 50u, 17u,
- 29u, 74u, 155u, 165u,
- 220u, 7u, 187u, 209u,
- 172u, 168u, 205u, 161u,
- 64u, 59u, 0u, 34u,
- 1u, 8u, 63u, 103u,
- 148u, 26u, 224u, 54u,
- 161u, 147u, 168u, 145u,
- 66u, 222u, 98u, 98u,
- 34u, 181u, 127u, 156u,
- 136u, 155u, 142u, 93u,
- 120u, 182u, 255u, 84u,
- 30u, 121u, 133u, 90u,
- 43u, 82u, 69u, 177u,
- 124u, 190u, 85u, 233u,
- 208u, 157u, 180u, 140u,
- 160u, 1u, 91u, 140u,
- 202u, 155u, 232u, 24u,
- 186u, 229u, 107u, 138u,
- 109u, 97u, 122u, 37u,
- 112u, 125u, 255u, 121u,
- 183u, 69u, 84u, 108u,
- 48u, 221u, 155u, 56u,
- 27u, 85u, 95u, 162u,
- 148u, 255u, 151u, 163u,
- 103u, 95u, 106u, 81u,
- 218u, 165u, 35u, 205u,
- 133u, 105u, 10u, 149u,
- 135u, 113u, 239u, 1u,
- 65u, 114u, 106u, 193u,
- 161u, 190u, 98u, 176u,
- 137u, 114u, 155u, 99u,
- 255u, 165u, 38u, 110u,
- 64u, 49u, 152u, 112u,
- 116u, 101u, 104u, 101u,
- 60u, 57u, 40u, 90u,
- 119u, 104u, 175u, 255u,
- 115u, 61u, 255u, 217u,
- 219u, 107u, 17u, 74u,
- 100u, 147u, 24u, 96u,
- 186u, 163u, 49u, 18u,
- 145u, 0u, 186u, 163u,
- 129u, 226u, 114u, 153u,
- 81u, 112u, 74u, 129u,
- 134u, 107u, 102u, 166u,
- 96u, 116u, 56u, 69u,
- 165u, 89u, 175u, 180u,
- 176u, 135u, 219u, 109u,
- 42u, 1u, 177u, 91u,
- 35u, 99u, 1u, 142u,
- 73u, 35u, 64u, 172u,
- 64u, 5u, 117u, 81u,
- 103u, 29u, 96u, 179u,
- 255u, 12u, 222u, 101u,
- 52u, 91u, 94u, 75u,
- 142u, 54u, 132u, 52u,
- 146u, 153u, 180u, 40u,
- 168u, 39u, 204u, 112u,
- 93u, 89u, 63u, 255u,
- 40u, 159u, 148u, 211u,
- 76u, 142u, 145u, 175u,
- 126u, 82u, 51u, 87u,
- 145u, 99u, 133u, 191u,
- 90u, 255u, 187u, 113u,
- 166u, 81u, 224u, 127u,
- 118u, 163u, 111u, 181u,
- 139u, 130u, 72u, 165u,
- 164u, 109u, 175u, 129u,
- 29u, 91u, 1u, 56u,
- 141u, 142u, 109u, 120u,
- 114u, 84u, 255u, 126u,
- 171u, 188u, 233u, 217u,
- 96u, 187u, 212u, 78u,
- 119u, 79u, 201u, 153u,
- 143u, 62u, 41u, 91u,
- 120u, 243u, 1u, 81u,
- 102u, 31u, 176u, 188u,
- 52u, 185u, 137u, 87u,
- 125u, 167u, 133u, 156u,
- 164u, 103u, 117u, 127u,
- 120u, 156u, 169u, 1u,
- 169u, 120u, 173u, 121u,
- 102u, 134u, 170u, 158u,
- 123u, 185u, 182u, 149u,
- 60u, 48u, 255u, 163u,
- 5u, 139u, 127u, 215u,
- 255u, 112u, 178u, 106u,
- 79u, 224u, 232u, 166u,
- 108u, 187u, 154u, 233u,
- 119u, 122u, 62u, 148u,
- 137u, 1u, 234u, 57u,
- 98u, 215u, 161u, 117u,
- 63u, 101u, 114u, 225u,
- 107u, 113u, 201u, 162u,
- 154u, 90u, 164u, 87u,
- 78u, 1u, 196u, 107u,
- 125u, 239u, 173u, 129u,
- 140u, 29u, 73u, 132u,
- 105u, 29u, 129u, 72u,
- 154u, 255u, 211u, 58u,
- 109u, 90u, 177u, 122u,
- 191u, 65u, 53u, 28u,
- 1u, 158u, 129u, 117u,
- 199u, 166u, 96u, 161u,
- 76u, 65u, 220u, 74u,
- 37u, 75u, 100u, 163u,
- 99u, 43u, 177u, 137u,
- 162u, 255u, 132u, 114u,
- 101u, 103u, 112u, 37u,
- 110u, 199u, 138u, 125u,
- 140u, 81u, 169u, 131u,
- 155u, 71u, 255u, 177u,
- 116u, 240u, 121u, 43u,
- 85u, 56u, 190u, 185u,
- 186u, 241u, 212u, 95u,
- 255u, 16u, 52u, 118u,
- 56u, 148u, 237u, 230u,
- 80u, 102u, 85u, 153u,
- 54u, 117u, 125u, 143u,
- 166u, 84u, 138u, 106u,
- 21u, 92u, 255u, 115u,
- 81u, 115u, 209u, 255u,
- 165u, 53u, 228u, 209u,
- 155u, 26u, 203u, 26u,
- 149u, 136u, 110u, 121u,
- 178u, 133u, 163u, 121u,
- 17u, 146u, 50u, 145u,
- 143u, 109u, 116u, 1u,
- 181u, 124u, 247u, 238u,
- 232u, 177u, 179u, 117u,
- 0u, 124u, 94u, 191u,
- 108u, 129u, 84u, 150u,
- 115u, 168u, 123u, 247u,
- 88u, 131u, 0u, 38u,
- 105u, 40u, 173u, 172u,
- 203u, 107u, 226u, 178u,
- 195u, 90u, 70u, 93u,
- 179u, 162u, 94u, 255u,
- 113u, 60u, 134u, 4u,
- 83u, 138u, 204u, 112u,
- 129u, 231u, 122u, 195u,
- 129u, 73u, 81u, 150u,
- 186u, 88u, 137u, 152u,
- 47u, 118u, 132u, 109u,
- 255u, 161u, 77u, 100u,
- 152u, 32u, 196u, 194u,
- 103u, 141u, 77u, 113u,
- 255u, 218u, 121u, 134u,
- 233u, 166u, 49u, 83u,
- 97u, 96u, 49u, 255u,
- 181u, 110u, 86u, 171u,
- 100u, 158u, 196u, 110u,
- 148u, 165u, 180u, 109u,
- 133u, 0u, 151u, 185u,
- 147u, 141u, 187u, 83u,
- 67u, 90u, 237u, 103u,
- 198u, 24u, 144u, 129u,
- 121u, 255u, 233u, 115u,
- 159u, 111u, 228u, 187u,
- 114u, 114u, 173u, 171u,
- 120u, 200u, 95u, 210u,
- 134u, 4u, 125u, 188u,
- 19u, 255u, 130u, 16u,
- 157u, 133u, 76u, 145u,
- 101u, 98u, 152u, 119u,
- 119u, 220u, 104u, 129u,
- 170u, 139u, 1u, 196u,
- 110u, 70u, 48u, 96u,
- 127u, 207u, 74u, 106u,
- 30u, 117u, 101u, 255u,
- 215u, 112u, 110u, 183u,
- 154u, 96u, 54u, 92u,
- 195u, 174u, 24u, 113u,
- 166u, 131u, 4u, 125u,
- 178u, 57u, 0u, 139u,
- 147u, 6u, 184u, 123u,
- 86u, 143u, 139u, 60u,
- 223u, 168u, 82u, 86u,
- 114u, 2u, 90u, 100u,
- 67u, 144u, 1u, 126u,
- 254u, 196u, 93u, 171u,
- 1u, 193u, 214u, 113u,
- 107u, 200u, 110u, 162u,
- 175u, 93u, 43u, 230u,
- 208u, 117u, 243u, 186u,
- 67u, 141u, 110u, 210u,
- 201u, 144u, 68u, 164u,
- 102u, 164u, 255u, 160u,
- 8u, 186u, 37u, 173u,
- 76u, 97u, 215u, 171u,
- 109u, 126u, 190u, 91u,
- 168u, 56u, 1u, 121u,
- 123u, 164u, 179u, 103u,
- 189u, 101u, 163u, 149u,
- 133u, 81u, 87u, 81u,
- 162u, 127u, 22u, 176u,
- 151u, 160u, 80u, 255u,
- 182u, 216u, 127u, 165u,
- 186u, 120u, 27u, 243u,
- 42u, 108u, 1u, 103u,
- 163u, 243u, 85u, 79u,
- 155u, 50u, 36u, 90u,
- 8u, 115u, 201u, 198u,
- 121u, 65u, 180u, 96u,
- 81u, 101u, 255u, 128u,
- 253u, 173u, 159u, 119u,
- 138u, 255u, 140u, 150u,
- 131u, 94u, 181u, 24u,
- 192u, 196u, 197u, 181u,
- 141u, 133u, 172u, 172u,
- 156u, 237u, 101u, 115u,
- 142u, 86u, 181u, 115u,
- 148u, 255u, 146u, 179u,
- 62u, 192u, 248u, 177u,
- 161u, 255u, 121u, 94u,
- 182u, 9u, 151u, 253u,
- 116u, 152u, 34u, 50u,
- 178u, 98u, 52u, 169u,
- 159u, 1u, 206u, 153u,
- 78u, 175u, 161u, 66u,
- 129u, 206u, 128u, 93u,
- 80u, 0u, 99u, 132u,
- 168u, 95u, 148u, 168u,
- 119u, 137u, 65u, 199u,
- 117u, 170u, 146u, 58u,
- 223u, 5u, 168u, 76u,
- 94u, 107u, 118u, 0u,
- 92u, 106u, 120u, 79u,
- 92u, 139u, 253u, 23u,
- 1u, 227u, 175u, 179u,
- 73u, 210u, 127u, 193u,
- 193u, 22u, 110u, 221u,
- 137u, 83u, 29u, 207u,
- 150u, 91u, 146u, 140u,
- 255u, 182u, 96u, 226u,
- 128u, 130u, 130u, 123u,
- 117u, 63u, 91u, 7u,
- 59u, 131u, 36u, 224u,
- 188u, 55u, 252u, 252u,
- 156u, 124u, 209u, 232u,
- 63u, 255u, 56u, 223u,
- 124u, 153u, 255u, 105u,
- 69u, 172u, 143u, 69u,
- 77u, 92u, 174u, 95u,
- 149u, 178u, 123u, 202u,
- 133u, 104u, 89u, 153u,
- 137u, 148u, 150u, 165u,
- 173u, 123u, 0u, 151u,
- 224u, 17u, 128u, 154u,
- 125u, 141u, 242u, 123u,
- 185u, 1u, 186u, 79u,
- 109u, 162u, 115u, 117u,
- 138u, 142u, 89u, 141u,
- 129u, 213u, 1u, 138u,
- 163u, 143u, 76u, 98u,
- 162u, 140u, 52u, 66u,
- 88u, 171u, 158u, 124u,
- 186u, 66u, 154u, 124u,
- 80u, 143u, 185u, 89u,
- 1u, 184u, 133u, 50u,
- 180u, 152u, 120u, 201u,
- 83u, 62u, 65u, 151u,
- 165u, 51u, 74u, 184u,
- 169u, 103u, 71u, 160u,
- 255u, 171u, 85u, 36u,
- 106u, 109u, 180u, 205u,
- 73u, 185u, 0u, 238u,
- 135u, 94u, 157u, 147u,
- 24u, 195u, 135u, 136u,
- 66u, 52u, 255u, 87u,
- 6u, 179u, 220u, 129u,
- 230u, 61u, 87u, 147u,
- 165u, 115u, 154u, 170u,
- 210u, 167u, 226u, 76u,
- 213u, 162u, 104u, 163u,
- 137u, 34u, 1u, 239u,
- 131u, 204u, 120u, 52u,
- 213u, 57u, 144u, 102u,
- 198u, 161u, 164u, 92u,
- 61u, 170u, 175u, 192u,
- 255u, 209u, 102u, 173u,
- 142u, 71u, 90u, 136u,
- 1u, 57u, 127u, 54u,
- 237u, 82u, 37u, 222u,
- 97u, 77u, 216u, 19u,
- 144u, 154u, 91u, 132u,
- 111u, 72u, 133u, 156u,
- 150u, 88u, 68u, 133u,
- 66u, 38u, 163u, 255u,
- 73u, 163u, 25u, 100u,
- 1u, 105u, 143u, 42u,
- 150u, 175u, 220u, 37u,
- 71u, 241u, 11u, 67u,
- 52u, 34u, 77u, 180u,
- 139u, 49u, 255u, 49u,
- 68u, 206u, 177u, 108u,
- 131u, 135u, 120u, 147u,
- 175u, 150u, 137u, 164u,
- 80u, 55u, 37u, 90u,
- 98u, 158u, 137u, 100u,
- 155u, 216u, 149u, 255u,
- 191u, 1u, 147u, 131u,
- 155u, 124u, 122u, 97u,
- 241u, 172u, 229u, 158u,
- 124u, 108u, 130u, 150u,
- 148u, 202u, 255u, 126u,
- 104u, 176u, 96u, 145u,
- 74u, 51u, 57u, 117u,
- 128u, 109u, 53u, 134u,
- 127u, 116u, 161u, 161u,
- 73u, 103u, 123u, 87u,
- 190u, 46u, 1u, 213u,
- 124u, 140u, 121u, 92u,
- 84u, 51u, 244u, 178u,
- 88u, 31u, 240u, 1u,
- 165u, 79u, 121u, 43u,
- 123u, 211u, 160u, 148u,
- 103u, 161u, 85u, 149u,
- 153u, 116u, 194u, 197u,
- 129u, 126u, 67u, 255u,
- 88u, 36u, 76u, 233u,
- 86u, 0u, 132u, 164u,
- 108u, 108u, 165u, 91u,
- 194u, 94u, 70u, 193u,
- 181u, 108u, 80u, 59u,
- 190u, 27u, 117u, 96u,
- 254u, 81u, 75u, 20u,
- 105u, 200u, 152u, 1u,
- 61u, 162u, 185u, 243u,
- 75u, 125u, 0u, 140u,
- 98u, 72u, 88u, 169u,
- 202u, 98u, 195u, 161u,
- 108u, 151u, 191u, 140u,
- 193u, 43u, 177u, 199u,
- 147u, 139u, 120u, 121u,
- 78u, 181u, 1u, 179u,
- 171u, 66u, 116u, 172u,
- 190u, 105u, 158u, 85u,
- 66u, 81u, 121u, 67u,
- 150u, 109u, 1u, 154u,
- 127u, 144u, 130u, 93u,
- 101u, 120u, 50u, 57u,
- 229u, 191u, 94u, 109u,
- 176u, 68u, 38u, 255u,
- 139u, 164u, 79u, 140u,
- 98u, 68u, 153u, 32u,
- 140u, 71u, 144u, 108u,
- 117u, 103u, 107u, 109u,
- 106u, 98u, 255u, 145u,
- 162u, 146u, 211u, 228u,
- 198u, 249u, 1u, 107u,
- 68u, 101u, 134u, 167u,
- 132u, 49u, 146u, 155u,
- 126u, 125u, 139u, 30u,
- 118u, 89u, 142u, 78u,
- 174u, 68u, 46u, 139u,
- 116u, 139u, 255u, 48u,
- 140u, 198u, 87u, 78u,
- 16u, 9u, 52u, 108u,
- 149u, 0u, 154u, 10u,
- 175u, 199u, 216u, 127u,
- 81u, 34u, 69u, 87u,
- 230u, 24u, 255u, 98u,
- 35u, 244u, 103u, 208u,
- 184u, 173u, 6u, 209u,
- 115u, 42u, 187u, 238u,
- 129u, 174u, 136u, 121u,
- 169u, 1u, 147u, 181u,
- 209u, 64u, 143u, 126u,
- 128u, 179u, 86u, 255u,
- 57u, 154u, 94u, 189u,
- 97u, 151u, 103u, 162u,
- 3u, 101u, 107u, 116u,
- 141u, 1u, 93u, 162u,
- 59u, 179u, 127u, 177u,
- 188u, 105u, 112u, 159u,
- 98u, 47u, 167u, 119u,
- 39u, 78u, 129u, 156u,
- 84u, 60u, 243u, 88u,
- 176u, 103u, 146u, 255u,
- 216u, 139u, 23u, 103u,
- 164u, 169u, 84u, 145u,
- 218u, 82u, 210u, 176u,
- 92u, 123u, 72u, 95u,
- 223u, 0u, 94u, 44u,
- 212u, 108u, 98u, 37u,
- 145u, 156u, 13u, 139u,
- 65u, 28u, 0u, 142u,
- 188u, 81u, 60u, 136u,
- 51u, 142u, 255u, 158u,
- 125u, 183u, 131u, 218u,
- 117u, 48u, 55u, 107u,
- 77u, 236u, 220u, 174u,
- 226u, 255u, 190u, 203u,
- 152u, 111u, 73u, 63u,
- 55u, 163u, 49u, 23u,
- 222u, 148u, 46u, 25u,
- 73u, 209u, 164u, 164u,
- 124u, 117u, 174u, 160u,
- 203u, 109u, 207u, 130u,
- 79u, 1u, 122u, 108u,
- 219u, 144u, 103u, 96u,
- 153u, 73u, 195u, 144u,
- 137u, 255u, 223u, 116u,
- 74u, 53u, 228u, 168u,
- 45u, 106u, 176u, 114u,
- 37u, 62u, 98u, 170u,
- 118u, 140u, 63u, 83u,
- 1u, 234u, 80u, 61u,
- 162u, 211u, 255u, 108u,
- 46u, 138u, 237u, 179u,
- 93u, 163u, 232u, 99u,
- 157u, 73u, 157u, 25u,
- 84u, 111u, 1u, 163u,
- 50u, 228u, 142u, 118u,
- 188u, 105u, 173u, 104u,
- 82u, 23u, 116u, 178u,
- 164u, 87u, 91u, 88u,
- 193u, 176u, 146u, 88u,
- 125u, 118u, 179u, 136u,
- 116u, 68u, 0u, 38u,
- 212u, 222u, 19u, 1u,
- 129u, 97u, 189u, 224u,
- 233u, 92u, 225u, 215u,
- 196u, 111u, 159u, 91u,
- 113u, 165u, 101u, 67u,
- 94u, 163u, 186u, 105u,
- 157u, 129u, 98u, 255u,
- 154u, 118u, 147u, 139u,
- 11u, 120u, 5u, 95u,
- 219u, 195u, 111u, 182u,
- 93u, 255u, 149u, 252u,
- 118u, 146u, 110u, 99u,
- 89u, 142u, 129u, 255u,
- 174u, 93u, 102u, 208u,
- 186u, 174u, 60u, 190u,
- 100u, 79u, 150u, 73u,
- 159u, 64u, 114u, 106u,
- 110u, 120u, 99u, 193u,
- 241u, 59u, 139u, 1u,
- 65u, 156u, 107u, 155u,
- 178u, 29u, 128u, 214u,
- 38u, 16u, 64u, 52u,
- 220u, 95u, 199u, 87u,
- 1u, 108u, 155u, 97u,
- 149u, 218u, 121u, 151u,
- 143u, 102u, 135u, 198u,
- 148u, 0u, 104u, 40u,
- 132u, 73u, 83u, 248u,
- 153u, 76u, 64u, 255u,
- 117u, 184u, 147u, 107u,
- 78u, 161u, 182u, 78u,
- 136u, 103u, 194u, 132u,
- 119u, 189u, 0u, 225u,
- 154u, 83u, 225u, 204u,
- 133u, 24u, 144u, 149u,
- 55u, 148u, 213u, 200u,
- 156u, 59u, 99u, 163u,
- 10u, 68u, 156u, 133u,
- 209u, 161u, 78u, 97u,
- 62u, 22u, 1u, 161u,
- 171u, 204u, 205u, 74u,
- 80u, 138u, 19u, 193u,
- 90u, 84u, 121u, 80u,
- 137u, 33u, 0u, 208u,
- 73u, 62u, 135u, 69u,
- 192u, 108u, 101u, 208u,
- 78u, 106u, 101u, 154u,
- 159u, 194u, 255u, 110u,
- 131u, 140u, 147u, 88u,
- 128u, 191u, 86u, 182u,
- 107u, 1u, 66u, 132u,
- 129u, 174u, 120u, 135u,
- 160u, 51u, 119u, 112u,
- 43u, 66u, 185u, 1u,
- 108u, 210u, 142u, 148u,
- 231u, 241u, 143u, 81u,
- 133u, 114u, 112u, 104u,
- 131u, 179u, 90u, 144u,
- 108u, 74u, 4u, 255u,
- 150u, 160u, 111u, 45u,
- 1u, 89u, 175u, 249u,
- 127u, 100u, 197u, 106u,
- 123u, 129u, 97u, 117u,
- 210u, 93u, 126u, 123u,
- 46u, 226u, 147u, 179u,
- 198u, 203u, 40u, 255u,
- 172u, 91u, 58u, 224u,
- 146u, 53u, 86u, 140u,
- 75u, 95u, 154u, 207u,
- 105u, 156u, 135u, 87u,
- 106u, 79u, 92u, 83u,
- 0u, 107u, 206u, 247u,
- 132u, 35u, 114u, 171u,
- 32u, 220u, 142u, 68u,
- 189u, 81u, 1u, 190u,
- 190u, 105u, 164u, 124u,
- 174u, 64u, 240u, 255u,
- 106u, 165u, 163u, 113u,
- 72u, 169u, 189u, 144u,
- 66u, 78u, 102u, 132u,
- 106u, 30u, 85u, 189u,
- 146u, 221u, 66u, 192u,
- 121u, 154u, 25u, 205u,
- 101u, 255u, 76u, 97u,
- 173u, 138u, 82u, 171u,
- 86u, 97u, 166u, 106u,
- 93u, 101u, 143u, 114u,
- 83u, 236u, 111u, 255u,
- 226u, 255u, 116u, 239u,
- 111u, 201u, 204u, 84u,
- 90u, 87u, 102u, 180u,
- 33u, 98u, 103u, 254u,
- 199u, 116u, 150u, 212u,
- 131u, 102u, 107u, 137u,
- 182u, 57u, 130u, 190u,
- 88u, 83u, 0u, 81u,
- 70u, 40u, 255u, 118u,
- 170u, 184u, 80u, 153u,
- 0u, 133u, 178u, 181u,
- 82u, 175u, 219u, 131u,
- 210u, 187u, 254u, 94u,
- 27u, 1u, 131u, 186u,
- 61u, 54u, 66u, 11u,
- 80u, 87u, 140u, 160u,
- 0u, 129u, 186u, 142u,
- 21u, 128u, 67u, 199u,
- 188u, 41u, 124u, 113u,
- 179u, 168u, 63u, 94u,
- 189u, 184u, 180u, 49u,
- 130u, 206u, 184u, 42u,
- 158u, 1u, 97u, 250u,
- 160u, 213u, 106u, 36u,
- 215u, 132u, 255u, 14u,
- 141u, 209u, 59u, 142u,
- 8u, 250u, 22u, 182u,
- 173u, 16u, 102u, 170u,
- 136u, 74u, 168u, 255u,
- 116u, 148u, 180u, 78u,
- 35u, 6u, 129u, 64u,
- 118u, 165u, 100u, 246u,
- 154u, 142u, 72u, 77u,
- 201u, 69u, 255u, 89u,
- 174u, 104u, 177u, 129u,
- 62u, 209u, 140u, 63u,
- 87u, 14u, 90u, 180u,
- 131u, 66u, 162u, 88u,
- 191u, 255u, 167u, 96u,
- 73u, 119u, 149u, 120u,
- 121u, 150u, 144u, 108u,
- 229u, 15u, 217u, 127u,
- 75u, 206u, 255u, 104u,
- 107u, 177u, 7u, 169u,
- 114u, 45u, 19u, 120u,
- 205u, 1u, 134u, 156u,
- 140u, 178u, 180u, 119u,
- 115u, 61u, 60u, 140u,
- 224u, 255u, 196u, 125u,
- 165u, 252u, 102u, 80u,
- 128u, 113u, 101u, 114u,
- 116u, 138u, 155u, 93u,
- 100u, 124u, 34u, 47u,
- 239u, 118u, 131u, 42u,
- 48u, 220u, 108u, 255u,
- 83u, 60u, 41u, 145u,
- 34u, 111u, 115u, 99u,
- 125u, 75u, 247u, 1u,
- 164u, 180u, 170u, 227u,
- 87u, 166u, 15u, 151u,
- 155u, 123u, 77u, 51u,
- 1u, 208u, 87u, 152u,
- 182u, 106u, 73u, 176u,
- 132u, 131u, 111u, 122u,
- 77u, 149u, 83u, 232u,
- 65u, 255u, 100u, 134u,
- 84u, 245u, 22u, 144u,
- 237u, 191u, 66u, 241u,
- 110u, 113u, 125u, 112u,
- 153u, 1u, 101u, 220u,
- 134u, 97u, 233u, 171u,
- 51u, 136u, 81u, 138u,
- 130u, 215u, 74u, 96u,
- 87u, 182u, 90u, 143u,
- 68u, 126u, 38u, 117u,
- 161u, 126u, 81u, 255u,
- 192u, 117u, 14u, 173u,
- 92u, 112u, 117u, 189u,
- 1u, 129u, 101u, 100u,
- 96u, 73u, 168u, 233u,
- 151u, 49u, 95u, 73u,
- 39u, 209u, 101u, 126u,
- 104u, 195u, 255u, 113u,
- 179u, 69u, 174u, 130u,
- 140u, 16u, 92u, 140u,
- 80u, 132u, 255u, 133u,
- 187u, 195u, 161u, 233u,
- 171u, 166u, 121u, 78u,
- 161u, 136u, 161u, 83u,
- 155u, 211u, 1u, 180u,
- 167u, 50u, 115u, 73u,
- 131u, 102u, 183u, 136u,
- 96u, 141u, 117u, 99u,
- 131u, 126u, 121u, 215u,
- 95u, 40u, 149u, 111u,
- 144u, 0u, 91u, 181u,
- 160u, 44u, 68u, 49u,
- 179u, 223u, 1u, 131u,
- 88u, 206u, 52u, 237u,
- 160u, 70u, 199u, 136u,
- 212u, 233u, 158u, 106u,
- 121u, 167u, 121u, 124u,
- 115u, 130u, 27u, 161u,
- 171u, 132u, 90u, 255u,
- 203u, 69u, 67u, 149u,
- 37u, 94u, 44u, 49u,
- 131u, 34u, 150u, 1u,
- 76u, 112u, 173u, 167u,
- 190u, 120u, 148u, 95u,
- 197u, 199u, 81u, 245u,
- 126u, 21u, 1u, 168u,
- 96u, 117u, 220u, 142u,
- 158u, 189u, 198u, 130u,
- 111u, 170u, 142u, 126u,
- 175u, 117u, 111u, 140u,
- 100u, 173u, 152u, 0u,
- 189u, 206u, 181u, 174u,
- 239u, 87u, 189u, 101u,
- 170u, 60u, 160u, 150u,
- 111u, 0u, 175u, 205u,
- 141u, 137u, 99u, 140u,
- 147u, 113u, 213u, 40u,
- 45u, 125u, 123u, 86u,
- 133u, 255u, 68u, 179u,
- 129u, 30u, 86u, 107u,
- 220u, 94u, 158u, 169u,
- 86u, 161u, 74u, 127u,
- 203u, 255u, 52u, 156u,
- 156u, 63u, 154u, 151u,
- 157u, 65u, 107u, 105u,
- 201u, 67u, 1u, 241u,
- 112u, 75u, 32u, 16u,
- 139u, 137u, 151u, 114u,
- 95u, 80u, 158u, 124u,
- 151u, 127u, 170u, 240u,
- 50u, 148u, 1u, 121u,
- 28u, 109u, 150u, 122u,
- 195u, 87u, 51u, 166u,
- 180u, 242u, 216u, 1u,
- 114u, 105u, 231u, 65u,
- 99u, 14u, 166u, 190u,
- 169u, 134u, 1u, 214u,
- 179u, 77u, 104u, 129u,
- 131u, 196u, 136u, 83u,
- 74u, 160u, 244u, 68u,
- 106u, 236u, 160u, 204u,
- 211u, 143u, 172u, 255u,
- 78u, 95u, 234u, 77u,
- 134u, 255u, 169u, 157u,
- 149u, 192u, 40u, 233u,
- 200u, 144u, 89u, 97u,
- 80u, 122u, 84u, 213u,
- 94u, 223u, 137u, 144u,
- 101u, 244u, 90u, 182u,
- 6u, 255u, 199u, 244u,
- 0u, 133u, 45u, 3u,
- 1u, 195u, 115u, 108u,
- 131u, 174u, 186u, 109u,
- 200u, 20u, 82u, 230u,
- 137u, 136u, 185u, 1u,
- 46u, 49u, 105u, 152u,
- 179u, 117u, 255u, 137u,
- 179u, 126u, 130u, 168u,
- 227u, 137u, 110u, 167u,
- 136u, 255u, 151u, 102u,
- 188u, 182u, 145u, 155u,
- 86u, 219u, 146u, 197u,
- 62u, 114u, 83u, 159u,
- 255u, 119u, 122u, 220u,
- 78u, 108u, 84u, 225u,
- 90u, 188u, 85u, 153u,
- 110u, 143u, 127u, 252u,
- 177u, 1u, 217u, 137u,
- 10u, 205u, 67u, 230u,
- 45u, 66u, 209u, 124u,
- 44u, 245u, 85u, 111u,
- 141u, 121u, 137u, 94u,
- 148u, 186u, 78u, 130u,
- 113u, 60u, 1u, 89u,
- 105u, 61u, 174u, 71u,
- 142u, 73u, 56u, 207u,
- 64u, 165u, 255u, 53u,
- 124u, 243u, 202u, 128u,
- 134u, 250u, 133u, 158u,
- 178u, 189u, 82u, 97u,
- 147u, 23u, 106u, 200u,
- 219u, 161u, 205u, 143u,
- 37u, 176u, 112u, 255u,
- 90u, 255u, 185u, 81u,
- 167u, 162u, 171u, 168u,
- 160u, 135u, 58u, 150u,
- 138u, 149u, 243u, 241u,
- 68u, 223u, 238u, 124u,
- 130u, 182u, 126u, 94u,
- 148u, 68u, 139u, 37u,
- 164u, 91u, 255u, 140u,
- 33u, 94u, 157u, 152u,
- 255u, 98u, 84u, 178u,
- 78u, 89u, 141u, 209u,
- 146u, 62u, 68u, 105u,
- 98u, 1u, 120u, 165u,
- 134u, 70u, 111u, 142u,
- 126u, 154u, 100u, 111u,
- 157u, 126u, 141u, 93u,
- 171u, 1u, 52u, 227u,
- 50u, 110u, 43u, 152u,
- 105u, 48u, 55u, 164u,
- 31u, 184u, 25u, 216u,
- 91u, 71u, 144u, 114u,
- 96u, 255u, 110u, 162u,
- 131u, 201u, 15u, 173u,
- 175u, 153u, 82u, 141u,
- 253u, 0u, 79u, 255u,
- 70u, 183u, 125u, 38u,
- 122u, 121u, 55u, 54u,
- 201u, 79u, 179u, 107u,
- 130u, 168u, 158u, 147u,
- 255u, 156u, 141u, 33u,
- 47u, 233u, 103u, 118u,
- 107u, 182u, 78u, 237u,
- 127u, 22u, 137u, 156u,
- 75u, 155u, 196u, 45u,
- 141u, 72u, 1u, 211u,
- 138u, 101u, 73u, 100u,
- 65u, 105u, 120u, 61u,
- 130u, 128u, 212u, 227u,
- 185u, 223u, 122u, 255u,
- 129u, 150u, 103u, 173u,
- 139u, 153u, 108u, 92u,
- 136u, 152u, 156u, 117u,
- 147u, 1u, 102u, 139u,
- 124u, 132u, 121u, 121u,
- 255u, 98u, 249u, 232u,
- 120u, 95u, 120u, 65u,
- 173u, 15u, 110u, 167u,
- 56u, 54u, 11u, 158u,
- 170u, 121u, 74u, 122u,
- 208u, 35u, 178u, 128u,
- 79u, 255u, 245u, 188u,
- 152u, 190u, 72u, 124u,
- 113u, 112u, 232u, 1u,
- 152u, 132u, 122u, 82u,
- 189u, 112u, 93u, 225u,
- 137u, 78u, 186u, 182u,
- 182u, 126u, 52u, 174u,
- 113u, 0u, 129u, 133u,
- 117u, 203u, 76u, 185u,
- 13u, 55u, 166u, 255u,
- 71u, 182u, 208u, 141u,
- 115u, 221u, 184u, 205u,
- 1u, 99u, 50u, 175u,
- 160u, 213u, 35u, 212u,
- 71u, 72u, 151u, 149u,
- 41u, 113u, 165u, 93u,
- 169u, 177u, 90u, 57u,
- 0u, 109u, 216u, 167u,
- 195u, 57u, 91u, 13u,
- 146u, 169u, 167u, 154u,
- 146u, 1u, 107u, 25u,
- 146u, 201u, 164u, 161u,
- 95u, 198u, 152u, 91u,
- 178u, 32u, 1u, 100u,
- 175u, 106u, 155u, 41u,
- 133u, 182u, 106u, 237u,
- 79u, 187u, 18u, 250u,
- 150u, 227u, 115u, 255u,
- 40u, 153u, 130u, 52u,
- 113u, 177u, 165u, 69u,
- 152u, 73u, 91u, 182u,
- 155u, 194u, 144u, 60u,
- 148u, 1u, 46u, 89u,
- 124u, 154u, 183u, 176u,
- 17u, 141u, 177u, 131u,
- 57u, 111u, 111u, 44u,
- 106u, 177u, 81u, 152u,
- 169u, 0u, 101u, 103u,
- 216u, 133u, 37u, 86u,
- 76u, 115u, 1u, 186u,
- 151u, 96u, 135u, 110u,
- 166u, 19u, 123u, 126u,
- 0u, 18u, 148u, 191u,
- 131u, 68u, 127u, 120u,
- 207u, 203u, 203u, 139u,
- 90u, 85u, 160u, 85u,
- 128u, 88u, 185u, 167u,
- 102u, 139u, 151u, 81u,
- 154u, 1u, 145u, 84u,
- 158u, 183u, 133u, 3u,
- 253u, 167u, 149u, 72u,
- 134u, 169u, 250u, 181u,
- 52u, 255u, 227u, 216u,
- 63u, 71u, 207u, 65u,
- 64u, 54u, 84u, 44u,
- 127u, 115u, 182u, 116u,
- 198u, 32u, 224u, 106u,
- 0u, 109u, 177u, 19u,
- 23u, 108u, 211u, 136u,
- 168u, 199u, 130u, 238u,
- 162u, 60u, 46u, 226u,
- 129u, 170u, 152u, 1u,
- 178u, 246u, 211u, 211u,
- 164u, 94u, 236u, 56u,
- 176u, 157u, 101u, 137u,
- 152u, 155u, 255u, 180u,
- 153u, 194u, 193u, 195u,
- 71u, 188u, 200u, 105u,
- 219u, 88u, 48u, 170u,
- 54u, 69u, 253u, 255u,
- 94u, 170u, 172u, 32u,
- 176u, 99u, 81u, 85u,
- 35u, 139u, 67u, 75u,
- 91u, 147u, 1u, 8u,
- 171u, 228u, 91u, 96u,
- 165u, 200u, 1u, 135u,
- 203u, 86u, 6u, 102u,
- 106u, 193u, 57u, 76u,
- 180u, 255u, 203u, 6u,
- 158u, 93u, 105u, 221u,
- 166u, 94u, 105u, 29u,
- 197u, 130u, 220u, 185u,
- 177u, 223u, 186u, 184u,
- 104u, 245u, 176u, 73u,
- 144u, 9u, 173u, 254u,
- 122u, 167u, 0u, 106u,
- 103u, 182u, 138u, 204u,
- 24u, 107u, 133u, 202u,
- 116u, 148u, 137u, 102u,
- 1u, 135u, 175u, 182u,
- 77u, 19u, 107u, 206u,
- 113u, 128u, 143u, 112u,
- 190u, 1u, 78u, 124u,
- 138u, 20u, 40u, 2u,
- 91u, 90u, 62u, 137u,
- 119u, 144u, 255u, 46u,
- 103u, 182u, 110u, 175u,
- 197u, 168u, 145u, 53u,
- 194u, 137u, 72u, 126u,
- 63u, 128u, 209u, 114u,
- 1u, 234u, 220u, 124u,
- 148u, 111u, 70u, 215u,
- 65u, 179u, 104u, 128u,
- 120u, 170u, 125u, 145u,
- 141u, 77u, 110u, 255u,
- 155u, 216u, 84u, 171u,
- 127u, 0u, 78u, 184u,
- 90u, 28u, 118u, 102u,
- 174u, 184u, 130u, 120u,
- 176u, 215u, 127u, 43u,
- 123u, 179u, 112u, 189u,
- 229u, 139u, 129u, 255u,
- 39u, 229u, 196u, 79u,
- 67u, 218u, 118u, 138u,
- 108u, 153u, 239u, 255u,
- 152u, 195u, 70u, 144u,
- 108u, 64u, 82u, 111u,
- 214u, 42u, 196u, 85u,
- 75u, 173u, 80u, 96u,
- 218u, 86u, 22u, 29u,
- 180u, 108u, 143u, 165u,
- 255u, 122u, 152u, 120u,
- 36u, 175u, 49u, 230u,
- 117u, 176u, 119u, 1u,
- 143u, 168u, 69u, 110u,
- 129u, 187u, 70u, 182u,
- 129u, 30u, 184u, 214u,
- 96u, 151u, 218u, 96u,
- 111u, 255u, 241u, 52u,
- 44u, 137u, 244u, 54u,
- 116u, 87u, 176u, 160u,
- 60u, 86u, 124u, 41u,
- 125u, 144u, 136u, 86u,
- 238u, 255u, 132u, 63u,
- 183u, 141u, 170u, 140u,
- 1u, 226u, 14u, 124u,
- 50u, 31u, 120u, 139u,
- 202u, 70u, 164u, 66u,
- 255u, 102u, 183u, 182u,
- 96u, 140u, 41u, 22u,
- 178u, 180u, 230u, 59u,
- 128u, 82u, 81u, 91u,
- 155u, 3u, 64u, 44u,
- 140u, 90u, 189u, 180u,
- 151u, 106u, 100u, 108u,
- 166u, 255u, 139u, 123u,
- 167u, 131u, 63u, 131u,
- 82u, 169u, 177u, 1u,
- 162u, 90u, 161u, 45u,
- 117u, 138u, 201u, 149u,
- 36u, 20u, 148u, 237u,
- 96u, 1u, 123u, 153u,
- 198u, 101u, 60u, 54u,
- 88u, 18u, 99u, 96u,
- 89u, 132u, 128u, 169u,
- 136u, 0u, 182u, 95u,
- 231u, 199u, 252u, 87u,
- 57u, 223u, 88u, 150u,
- 168u, 68u, 107u, 129u,
- 1u, 121u, 79u, 141u,
- 162u, 203u, 239u, 26u,
- 189u, 54u, 133u, 195u,
- 114u, 102u, 157u, 84u,
- 34u, 177u, 116u, 39u,
- 160u, 32u, 1u, 207u,
- 154u, 75u, 81u, 71u,
- 49u, 20u, 84u, 198u,
- 208u, 9u, 192u, 152u,
- 177u, 190u, 255u, 120u,
- 118u, 191u, 91u, 136u,
- 164u, 147u, 134u, 151u,
- 175u, 66u, 102u, 157u,
- 139u, 147u, 255u, 69u,
- 109u, 50u, 32u, 190u,
- 207u, 106u, 50u, 67u,
- 174u, 99u, 36u, 73u,
- 101u, 192u, 236u, 44u,
- 164u, 1u, 215u, 118u,
- 135u, 102u, 132u, 98u,
- 163u, 75u, 70u, 136u,
- 75u, 147u, 169u, 82u,
- 91u, 68u, 103u, 255u,
- 87u, 73u, 159u, 22u,
- 160u, 1u, 145u, 105u,
- 128u, 155u, 86u, 192u,
- 171u, 126u, 34u, 126u,
- 129u, 114u, 222u, 255u,
- 104u, 106u, 184u, 49u,
- 45u, 78u, 210u, 37u,
- 112u, 115u, 252u, 135u,
- 171u, 168u, 173u, 255u,
- 116u, 59u, 161u, 30u,
- 122u, 42u, 234u, 43u,
- 125u, 199u, 24u, 194u,
- 18u, 90u, 255u, 160u,
- 185u, 158u, 171u, 158u,
- 98u, 83u, 136u, 95u,
- 100u, 101u, 210u, 77u,
- 214u, 131u, 84u, 0u,
- 72u, 124u, 37u, 129u,
- 186u, 69u, 124u, 82u,
- 125u, 80u, 133u, 58u,
- 104u, 78u, 135u, 102u,
- 66u, 211u, 154u, 144u,
- 140u, 1u, 41u, 193u,
- 174u, 215u, 132u, 125u,
- 171u, 217u, 153u, 105u,
- 129u, 150u, 60u, 145u,
- 115u, 98u, 90u, 96u,
- 124u, 5u, 194u, 255u,
- 154u, 129u, 139u, 90u,
- 132u, 97u, 127u, 153u,
- 99u, 1u, 116u, 114u,
- 108u, 129u, 143u, 56u,
- 161u, 201u, 164u, 59u,
- 164u, 255u, 108u, 96u,
- 68u, 91u, 136u, 128u,
- 34u, 174u, 169u, 29u,
- 81u, 106u, 81u, 45u,
- 255u, 112u, 123u, 188u,
- 27u, 63u, 38u, 240u,
- 134u, 197u, 123u, 117u,
- 130u, 95u, 117u, 208u,
- 86u, 27u, 223u, 159u,
- 103u, 148u, 0u, 208u,
- 182u, 134u, 144u, 229u,
- 89u, 197u, 190u, 184u,
- 86u, 145u, 71u, 0u,
- 229u, 75u, 128u, 65u,
- 41u, 99u, 224u, 116u,
- 150u, 174u, 196u, 152u,
- 96u, 255u, 101u, 150u,
- 119u, 130u, 87u, 125u,
- 102u, 62u, 235u, 176u,
- 156u, 126u, 106u, 30u,
- 173u, 250u, 147u, 141u,
- 144u, 228u, 0u, 182u,
- 111u, 53u, 149u, 27u,
- 97u, 131u, 196u, 34u,
- 116u, 87u, 240u, 163u,
- 93u, 87u, 1u, 166u,
- 194u, 116u, 155u, 65u,
- 52u, 1u, 123u, 171u,
- 229u, 91u, 129u, 101u,
- 153u, 117u, 113u, 190u,
- 237u, 182u, 117u, 216u,
- 161u, 185u, 128u, 61u,
- 153u, 156u, 150u, 255u,
- 61u, 179u, 178u, 150u,
- 93u, 58u, 152u, 173u,
- 165u, 233u, 129u, 55u,
- 195u, 153u, 224u, 127u,
- 37u, 255u, 18u, 182u,
- 201u, 159u, 126u, 234u,
- 161u, 15u, 136u, 157u,
- 1u, 137u, 219u, 23u,
- 144u, 227u, 174u, 161u,
- 142u, 101u, 131u, 195u,
- 140u, 222u, 70u, 179u,
- 211u, 162u, 86u, 78u,
- 57u, 110u, 160u, 201u,
- 146u, 143u, 140u, 1u,
- 167u, 5u, 164u, 123u,
- 141u, 190u, 82u, 43u,
- 166u, 101u, 1u, 127u,
- 141u, 34u, 163u, 100u,
- 169u, 126u, 171u, 246u,
- 101u, 98u, 215u, 31u,
- 101u, 1u, 195u, 59u,
- 135u, 210u, 101u, 175u,
- 43u, 103u, 165u, 219u,
- 235u, 106u, 136u, 255u,
- 152u, 181u, 178u, 163u,
- 76u, 175u, 158u, 205u,
- 136u, 104u, 202u, 115u,
- 1u, 124u, 116u, 92u,
- 212u, 100u, 211u, 186u,
- 123u, 103u, 116u, 113u,
- 136u, 255u, 99u, 22u,
- 128u, 162u, 152u, 158u,
- 56u, 118u, 51u, 134u,
- 59u, 39u, 108u, 18u,
- 125u, 132u, 31u, 111u,
- 82u, 114u, 163u, 255u,
- 125u, 87u, 198u, 186u,
- 119u, 115u, 111u, 144u,
- 96u, 149u, 123u, 1u,
- 126u, 17u, 214u, 1u,
- 92u, 212u, 116u, 213u,
- 109u, 102u, 39u, 98u,
- 124u, 233u, 134u, 205u,
- 182u, 145u, 100u, 255u,
- 103u, 212u, 122u, 154u,
- 71u, 166u, 91u, 210u,
- 180u, 45u, 143u, 156u,
- 121u, 152u, 67u, 109u,
- 79u, 1u, 134u, 136u,
- 23u, 231u, 95u, 132u,
- 189u, 122u, 65u, 151u,
- 88u, 93u, 188u, 162u,
- 244u, 19u, 218u, 0u,
- 201u, 112u, 85u, 172u,
- 1u, 14u, 179u, 185u,
- 138u, 164u, 133u, 139u,
- 94u, 128u, 114u, 110u,
- 146u, 152u, 204u, 88u,
- 171u, 151u, 61u, 129u,
- 214u, 255u, 84u, 74u,
- 188u, 47u, 128u, 194u,
- 130u, 116u, 224u, 50u,
- 103u, 150u, 168u, 150u,
- 113u, 204u, 158u, 32u,
- 113u, 128u, 86u, 84u,
- 140u, 0u, 202u, 106u,
- 144u, 140u, 99u, 84u,
- 140u, 221u, 160u, 120u,
- 92u, 64u, 19u, 255u,
- 153u, 187u, 94u, 63u,
- 255u, 36u, 126u, 147u,
- 126u, 36u, 245u, 57u,
- 147u, 184u, 185u, 75u,
- 104u, 47u, 47u, 111u,
- 195u, 19u, 224u, 100u,
- 151u, 173u, 102u, 255u,
- 158u, 181u, 123u, 57u,
- 67u, 178u, 218u, 206u,
- 142u, 96u, 124u, 191u,
- 25u, 33u, 245u, 8u,
- 77u, 196u, 255u, 251u,
- 134u, 127u, 30u, 23u,
- 154u, 149u, 1u, 114u,
- 215u, 11u, 152u, 163u,
- 76u, 171u, 220u, 203u,
- 49u, 110u, 3u, 196u,
- 192u, 1u, 68u, 172u,
- 62u, 152u, 149u, 131u,
- 115u, 70u, 128u, 149u,
- 90u, 194u, 148u, 214u,
- 175u, 202u, 113u, 153u,
- 67u, 255u, 114u, 160u,
- 115u, 63u, 137u, 137u,
- 88u, 86u, 197u, 178u,
- 176u, 180u, 123u, 228u,
- 245u, 134u, 116u, 161u,
- 174u, 121u, 255u, 199u,
- 33u, 148u, 71u, 129u,
- 85u, 191u, 202u, 71u,
- 201u, 1u, 77u, 67u,
- 83u, 190u, 221u, 218u,
- 118u, 158u, 88u, 67u,
- 255u, 119u, 82u, 93u,
- 209u, 183u, 203u, 177u,
- 161u, 209u, 145u, 235u,
- 197u, 37u, 88u, 35u,
- 142u, 116u, 163u, 106u,
- 52u, 130u, 136u, 1u,
- 164u, 186u, 154u, 126u,
- 9u, 124u, 81u, 180u,
- 43u, 152u, 69u, 107u,
- 193u, 39u, 218u, 99u,
- 77u, 150u, 255u, 161u,
- 155u, 216u, 31u, 103u,
- 56u, 74u, 60u, 189u,
- 132u, 119u, 163u, 104u,
- 100u, 1u, 86u, 80u,
- 161u, 93u, 111u, 148u,
- 168u, 216u, 211u, 161u,
- 217u, 107u, 135u, 61u,
- 170u, 161u, 131u, 207u,
- 1u, 10u, 23u, 4u,
- 117u, 55u, 125u, 143u,
- 156u, 97u, 89u, 255u,
- 128u, 43u, 1u, 148u,
- 134u, 140u, 152u, 101u,
- 164u, 140u, 112u, 121u,
- 118u, 153u, 56u, 140u,
- 117u, 77u, 0u, 192u,
- 169u, 149u, 122u, 174u,
- 0u, 78u, 121u, 140u,
- 124u, 83u, 188u, 144u,
- 176u, 89u, 206u, 183u,
- 110u, 195u, 18u, 176u,
- 80u, 139u, 134u, 116u,
- 57u, 129u, 59u, 39u,
- 86u, 136u, 83u, 59u,
- 131u, 255u, 93u, 129u,
- 104u, 210u, 161u, 85u,
- 79u, 255u, 124u, 174u,
- 119u, 73u, 194u, 166u,
- 142u, 14u, 109u, 173u,
- 29u, 1u, 234u, 244u,
- 99u, 156u, 45u, 170u,
- 102u, 96u, 49u, 23u,
- 95u, 208u, 217u, 32u,
- 138u, 100u, 195u, 159u,
- 27u, 211u, 82u, 103u,
- 159u, 49u, 1u, 78u,
- 106u, 34u, 220u, 169u,
- 3u, 94u, 168u, 1u,
- 142u, 143u, 242u, 123u,
- 171u, 115u, 72u, 148u,
- 25u, 126u, 171u, 115u,
- 120u, 179u, 2u, 144u,
- 229u, 25u, 178u, 211u,
- 1u, 186u, 195u, 135u,
- 151u, 178u, 108u, 154u,
- 147u, 88u, 57u, 92u,
- 168u, 119u, 128u, 11u,
- 156u, 94u, 196u, 110u,
- 56u, 255u, 113u, 144u,
- 137u, 29u, 130u, 225u,
- 176u, 154u, 92u, 117u,
- 163u, 111u, 11u, 36u,
- 255u, 120u, 245u, 131u,
- 162u, 82u, 88u, 102u,
- 40u, 0u, 122u, 100u,
- 106u, 149u, 194u, 40u,
- 121u, 120u, 109u, 80u,
- 126u, 178u, 5u, 105u,
- 175u, 53u, 152u, 47u,
- 51u, 255u, 161u, 64u,
- 113u, 98u, 134u, 135u,
- 29u, 234u, 17u, 1u,
- 255u, 222u, 69u, 132u,
- 102u, 95u, 164u, 61u,
- 142u, 156u, 116u, 133u,
- 128u, 114u, 223u, 153u,
- 221u, 174u, 108u, 53u,
- 97u, 236u, 235u, 255u,
- 198u, 187u, 145u, 58u,
- 27u, 0u, 5u, 189u,
- 181u, 84u, 70u, 130u,
- 38u, 122u, 154u, 116u,
- 177u, 132u, 191u, 125u,
- 119u, 139u, 120u, 135u,
- 85u, 175u, 199u, 88u,
- 133u, 15u, 116u, 94u,
- 68u, 255u, 99u, 127u,
- 1u, 99u, 53u, 164u,
- 208u, 140u, 220u, 151u,
- 135u, 112u, 135u, 92u,
- 63u, 208u, 132u, 130u,
- 102u, 101u, 171u, 73u,
- 74u, 108u, 109u, 54u,
- 165u, 123u, 90u, 108u,
- 120u, 154u, 107u, 1u,
- 174u, 4u, 113u, 122u,
- 242u, 87u, 72u, 234u,
- 93u, 153u, 34u, 222u,
- 172u, 95u, 1u, 61u,
- 108u, 0u, 62u, 93u,
- 142u, 74u, 243u, 186u,
- 103u, 56u, 220u, 149u,
- 166u, 63u, 184u, 97u,
- 155u, 125u, 64u, 72u,
- 41u, 211u, 142u, 208u,
- 145u, 153u, 94u, 243u,
- 221u, 38u, 106u, 255u,
- 28u, 0u, 175u, 112u,
- 53u, 173u, 126u, 99u,
- 215u, 126u, 89u, 147u,
- 115u, 132u, 192u, 123u,
- 114u, 82u, 155u, 136u,
- 63u, 141u, 159u, 1u,
- 196u, 106u, 72u, 133u,
- 96u, 79u, 92u, 193u,
- 126u, 5u, 115u, 187u,
- 44u, 255u, 216u, 17u,
- 193u, 90u, 97u, 220u,
- 118u, 85u, 117u, 82u,
- 33u, 155u, 143u, 86u,
- 177u, 117u, 118u, 126u,
- 246u, 208u, 255u, 230u,
- 21u, 75u, 111u, 148u,
- 255u, 178u, 36u, 152u,
- 147u, 167u, 91u, 107u,
- 66u, 255u, 118u, 149u,
- 67u, 119u, 57u, 116u,
- 247u, 201u, 233u, 58u,
- 144u, 255u, 76u, 117u,
- 141u, 181u, 82u, 224u,
- 215u, 108u, 123u, 187u,
- 146u, 189u, 255u, 145u,
- 106u, 164u, 128u, 141u,
- 141u, 7u, 61u, 183u,
- 103u, 127u, 189u, 137u,
- 149u, 160u, 25u, 113u,
- 155u, 127u, 94u, 170u,
- 102u, 110u, 29u, 157u,
- 255u, 221u, 149u, 68u,
- 108u, 116u, 77u, 113u,
- 120u, 114u, 144u, 235u,
- 131u, 255u, 207u, 245u,
- 104u, 2u, 95u, 131u,
- 80u, 48u, 115u, 104u,
- 83u, 23u, 162u, 55u,
- 171u, 253u, 255u, 90u,
- 121u, 82u, 108u, 80u,
- 143u, 104u, 135u, 62u,
- 47u, 146u, 59u, 214u,
- 91u, 165u, 150u, 177u,
- 149u, 100u, 255u, 74u,
- 149u, 68u, 54u, 238u,
- 130u, 81u, 243u, 89u,
- 110u, 179u, 175u, 57u,
- 51u, 1u, 15u, 72u,
- 92u, 117u, 189u, 110u,
- 105u, 255u, 232u, 182u,
- 81u, 73u, 178u, 105u,
- 77u, 82u, 93u, 123u,
- 79u, 34u, 94u, 187u,
- 141u, 94u, 176u, 130u,
- 158u, 179u, 255u, 121u,
- 88u, 144u, 115u, 127u,
- 114u, 122u, 133u, 107u,
- 162u, 1u, 169u, 138u,
- 159u, 177u, 203u, 77u,
- 116u, 57u, 237u, 48u,
- 1u, 22u, 148u, 114u,
- 78u, 78u, 252u, 19u,
- 241u, 163u, 154u, 133u,
- 30u, 23u, 241u, 25u,
- 25u, 184u, 198u, 92u,
- 95u, 214u, 135u, 145u,
- 238u, 1u, 86u, 207u,
- 179u, 161u, 162u, 106u,
- 70u, 124u, 153u, 111u,
- 111u, 211u, 80u, 244u,
- 233u, 81u, 186u, 113u,
- 158u, 1u, 103u, 222u,
- 50u, 97u, 70u, 130u,
- 0u, 38u, 115u, 174u,
- 10u, 180u, 197u, 96u,
- 82u, 151u, 90u, 242u,
- 47u, 132u, 137u, 209u,
- 131u, 22u, 221u, 137u,
- 255u, 190u, 119u, 159u,
- 168u, 46u, 184u, 247u,
- 198u, 11u, 255u, 187u,
- 108u, 24u, 100u, 53u,
- 157u, 145u, 98u, 41u,
- 163u, 196u, 106u, 73u,
- 37u, 72u, 201u, 73u,
- 255u, 220u, 182u, 127u,
- 57u, 61u, 176u, 167u,
- 181u, 167u, 145u, 139u,
- 139u, 102u, 137u, 104u,
- 88u, 42u, 95u, 93u,
- 182u, 157u, 116u, 116u,
- 222u, 255u, 114u, 56u,
- 107u, 115u, 131u, 154u,
- 166u, 179u, 112u, 208u,
- 41u, 127u, 87u, 235u,
- 198u, 83u, 1u, 152u,
- 92u, 151u, 182u, 202u,
- 176u, 148u, 104u, 111u,
- 255u, 131u, 172u, 76u,
- 163u, 86u, 120u, 62u,
- 153u, 113u, 41u, 147u,
- 92u, 34u, 179u, 127u,
- 100u, 202u, 255u, 150u,
- 101u, 149u, 75u, 152u,
- 94u, 105u, 82u, 32u,
- 62u, 160u, 10u, 42u,
- 24u, 195u, 15u, 135u,
- 32u, 167u, 162u, 255u,
- 157u, 255u, 109u, 197u,
- 120u, 181u, 144u, 137u,
- 111u, 33u, 43u, 163u,
- 15u, 51u, 188u, 249u,
- 42u, 82u, 166u, 227u,
- 159u, 58u, 91u, 222u,
- 142u, 68u, 71u, 201u,
- 34u, 136u, 0u, 41u,
- 125u, 9u, 169u, 117u,
- 129u, 34u, 172u, 55u,
- 171u, 151u, 240u, 1u,
- 0u, 42u, 216u, 60u,
- 228u, 213u, 162u, 157u,
- 134u, 172u, 94u, 151u,
- 57u, 105u, 52u, 142u,
- 243u, 194u, 1u, 196u,
- 31u, 1u, 23u, 150u,
- 159u, 53u, 65u, 118u,
- 53u, 160u, 107u, 131u,
- 40u, 135u, 8u, 110u,
- 210u, 110u, 81u, 168u,
- 125u, 163u, 91u, 128u,
- 45u, 173u, 221u, 105u,
- 68u, 0u, 122u, 228u,
- 165u, 57u, 86u, 180u,
- 143u, 1u, 111u, 105u,
- 70u, 165u, 72u, 169u,
- 233u, 179u, 130u, 149u,
- 148u, 161u, 90u, 97u,
- 106u, 133u, 132u, 225u,
- 113u, 244u, 255u, 18u,
- 167u, 76u, 73u, 142u,
- 179u, 137u, 89u, 68u,
- 0u, 150u, 35u, 206u,
- 96u, 133u, 152u, 145u,
- 144u, 90u, 226u, 131u,
- 142u, 98u, 155u, 226u,
- 73u, 101u, 77u, 90u,
- 255u, 132u, 178u, 122u,
- 148u, 155u, 135u, 117u,
- 255u, 149u, 176u, 147u,
- 54u, 154u, 138u, 32u,
- 191u, 84u, 31u, 197u,
- 77u, 177u, 138u, 136u,
- 164u, 99u, 107u, 132u,
- 73u, 76u, 135u, 164u,
- 125u, 255u, 255u, 18u,
- 181u, 78u, 124u, 229u,
- 165u, 126u, 1u, 158u,
- 45u, 163u, 99u, 146u,
- 80u, 189u, 98u, 134u,
- 147u, 201u, 79u, 206u,
- 111u, 138u, 140u, 89u,
- 143u, 115u, 128u, 29u,
- 255u, 12u, 133u, 222u,
- 125u, 109u, 87u, 85u,
- 139u, 1u, 42u, 180u,
- 169u, 58u, 127u, 194u,
- 86u, 161u, 87u, 163u,
- 128u, 116u, 49u, 138u,
- 40u, 126u, 255u, 164u,
- 187u, 117u, 99u, 158u,
- 149u, 142u, 68u, 137u,
- 97u, 181u, 109u, 197u,
- 125u, 118u, 160u, 224u,
- 99u, 116u, 152u, 126u,
- 255u, 70u, 148u, 117u,
- 193u, 86u, 90u, 73u,
- 232u, 193u, 112u, 1u,
- 123u, 146u, 54u, 159u,
- 81u, 41u, 8u, 39u,
- 158u, 61u, 160u, 80u,
- 75u, 109u, 10u, 83u,
- 252u, 122u, 114u, 64u,
- 218u, 143u, 38u, 128u,
- 169u, 167u, 0u, 130u,
- 209u, 242u, 207u, 114u,
- 187u, 234u, 81u, 123u,
- 62u, 99u, 55u, 139u,
- 82u, 109u, 123u, 1u,
- 255u, 169u, 71u, 187u,
- 103u, 98u, 86u, 137u,
- 142u, 201u, 87u, 113u,
- 63u, 94u, 76u, 122u,
- 166u, 130u, 255u, 89u,
- 57u, 199u, 102u, 36u,
- 181u, 134u, 182u, 119u,
- 147u, 31u, 138u, 28u,
- 102u, 93u, 1u, 87u,
- 158u, 73u, 204u, 69u,
- 110u, 125u, 152u, 132u,
- 153u, 149u, 11u, 163u,
- 93u, 191u, 110u, 101u,
- 126u, 51u, 49u, 120u,
- 117u, 124u, 192u, 0u,
- 108u, 123u, 172u, 107u,
- 161u, 77u, 112u, 53u,
- 0u, 184u, 132u, 195u,
- 178u, 161u, 148u, 119u,
- 141u, 117u, 86u, 126u,
- 255u, 153u, 119u, 116u,
- 146u, 177u, 167u, 149u,
- 143u, 104u, 119u, 186u,
- 137u, 192u, 86u, 85u,
- 42u, 66u, 149u, 254u,
- 92u, 124u, 172u, 81u,
- 255u, 108u, 150u, 251u,
- 112u, 205u, 105u, 27u,
- 80u, 117u, 54u, 152u,
- 180u, 36u, 76u, 154u,
- 106u, 58u, 80u, 76u,
- 255u, 180u, 99u, 115u,
- 73u, 72u, 54u, 74u,
- 88u, 31u, 69u, 255u,
- 172u, 182u, 133u, 126u,
- 59u, 65u, 154u, 132u,
- 59u, 183u, 130u, 162u,
- 174u, 89u, 89u, 107u,
- 119u, 209u, 255u, 65u,
- 20u, 170u, 181u, 118u,
- 76u, 253u, 197u, 160u,
- 35u, 76u, 255u, 143u,
- 128u, 106u, 122u, 232u,
- 128u, 153u, 144u, 52u,
- 188u, 240u, 168u, 57u,
- 227u, 208u, 183u, 67u,
- 119u, 153u, 96u, 186u,
- 93u, 173u, 94u, 0u,
- 116u, 133u, 146u, 116u,
- 138u, 147u, 56u, 255u,
- 125u, 111u, 74u, 128u,
- 167u, 76u, 160u, 132u,
- 42u, 166u, 244u, 28u,
- 255u, 247u, 114u, 146u,
- 88u, 52u, 86u, 166u,
- 84u, 181u, 111u, 95u,
- 165u, 177u, 98u, 116u,
- 177u, 218u, 166u, 128u,
- 151u, 128u, 93u, 235u,
- 161u, 100u, 1u, 38u,
- 123u, 65u, 103u, 161u,
- 162u, 0u, 74u, 159u,
- 85u, 143u, 79u, 134u,
- 118u, 141u, 103u, 133u,
- 219u, 97u, 147u, 180u,
- 107u, 196u, 79u, 6u,
- 204u, 81u, 124u, 1u,
- 140u, 106u, 152u, 35u,
- 175u, 64u, 174u, 67u,
- 189u, 106u, 0u, 208u,
- 164u, 109u, 190u, 134u,
- 247u, 144u, 72u, 127u,
- 116u, 66u, 111u, 89u,
- 93u, 45u, 123u, 182u,
- 81u, 143u, 83u, 255u,
- 132u, 152u, 106u, 64u,
- 84u, 169u, 123u, 21u,
- 255u, 25u, 127u, 126u,
- 79u, 199u, 211u, 80u,
- 66u, 220u, 211u, 145u,
- 1u, 68u, 156u, 226u,
- 143u, 14u, 149u, 178u,
- 135u, 159u, 98u, 75u,
- 106u, 136u, 141u, 149u,
- 177u, 64u, 34u, 169u,
- 119u, 0u, 56u, 99u,
- 39u, 202u, 128u, 180u,
- 59u, 145u, 25u, 110u,
- 78u, 27u, 69u, 185u,
- 115u, 250u, 202u, 130u,
- 125u, 205u, 137u, 104u,
- 104u, 195u, 255u, 91u,
- 147u, 112u, 211u, 249u,
- 131u, 1u, 187u, 88u,
- 170u, 177u, 77u, 145u,
- 200u, 238u, 215u, 208u,
- 123u, 102u, 204u, 125u,
- 189u, 189u, 74u, 72u,
- 217u, 1u, 35u, 217u,
- 125u, 54u, 145u, 13u,
- 125u, 169u, 175u, 230u,
- 7u, 186u, 0u, 132u,
- 106u, 189u, 87u, 121u,
- 128u, 182u, 245u, 194u,
- 102u, 234u, 116u, 1u,
- 200u, 253u, 57u, 28u,
- 81u, 82u, 111u, 187u,
- 175u, 206u, 122u, 100u,
- 125u, 183u, 94u, 114u,
- 184u, 87u, 159u, 178u,
- 149u, 175u, 197u, 237u,
- 140u, 201u, 0u, 157u,
- 1u, 160u, 93u, 82u,
- 176u, 74u, 141u, 102u,
- 91u, 133u, 114u, 139u,
- 183u, 99u, 15u, 190u,
- 125u, 68u, 204u, 0u,
- 246u, 175u, 51u, 103u,
- 189u, 78u, 208u, 140u,
- 75u, 102u, 11u, 172u,
- 127u, 85u, 65u, 72u,
- 217u, 41u, 76u, 172u,
- 125u, 55u, 137u, 208u,
- 105u, 81u, 0u, 82u,
- 34u, 2u, 126u, 174u,
- 154u, 83u, 90u, 50u,
- 124u, 109u, 115u, 127u,
- 102u, 104u, 61u, 255u,
- 175u, 99u, 35u, 103u,
- 61u, 123u, 165u, 60u,
- 129u, 171u, 255u, 93u,
- 99u, 35u, 35u, 149u,
- 0u, 174u, 132u, 206u,
- 82u, 150u, 255u, 127u,
- 180u, 217u, 224u, 255u,
- 95u, 155u, 34u, 191u,
- 113u, 126u, 171u, 1u,
- 50u, 204u, 120u, 31u,
- 193u, 37u, 47u, 124u,
- 216u, 99u, 81u, 142u,
- 103u, 191u, 123u, 192u,
- 100u, 190u, 150u, 164u,
- 193u, 124u, 123u, 255u,
- 146u, 193u, 115u, 234u,
- 179u, 56u, 124u, 184u,
- 70u, 96u, 109u, 56u,
- 74u, 27u, 70u, 74u,
- 72u, 176u, 1u, 129u,
- 86u, 41u, 191u, 151u,
- 84u, 160u, 111u, 79u,
- 255u, 160u, 93u, 136u,
- 154u, 100u, 156u, 93u,
- 238u, 116u, 158u, 123u,
- 191u, 127u, 174u, 84u,
- 1u, 167u, 169u, 132u,
- 153u, 152u, 151u, 90u,
- 131u, 54u, 156u, 129u,
- 112u, 188u, 160u, 38u,
- 163u, 88u, 1u, 182u,
- 162u, 99u, 176u, 147u,
- 128u, 84u, 251u, 255u,
- 194u, 52u, 107u, 108u,
- 168u, 49u, 97u, 2u,
- 84u, 61u, 227u, 215u,
- 255u, 50u, 220u, 170u,
- 238u, 86u, 245u, 134u,
- 172u, 88u, 101u, 167u,
- 202u, 84u, 197u, 133u,
- 131u, 102u, 200u, 100u,
- 131u, 189u, 84u, 112u,
- 255u, 117u, 153u, 152u,
- 108u, 89u, 160u, 109u,
- 101u, 87u, 126u, 66u,
- 107u, 117u, 96u, 76u,
- 89u, 53u, 248u, 133u,
- 106u, 161u, 1u, 76u,
- 95u, 63u, 127u, 119u,
- 103u, 112u, 103u, 93u,
- 191u, 138u, 235u, 66u,
- 94u, 1u, 162u, 132u,
- 137u, 100u, 190u, 134u,
- 96u, 205u, 119u, 179u,
- 188u, 100u, 209u, 53u,
- 134u, 1u, 116u, 118u,
- 56u, 82u, 131u, 121u,
- 113u, 255u, 193u, 118u,
- 56u, 121u, 84u, 152u,
- 151u, 185u, 160u, 214u,
- 36u, 175u, 199u, 154u,
- 128u, 173u, 99u, 147u,
- 146u, 33u, 28u, 255u,
- 79u, 139u, 113u, 100u,
- 55u, 123u, 255u, 160u,
- 242u, 155u, 170u, 237u,
- 89u, 10u, 159u, 191u,
- 112u, 141u, 158u, 39u,
- 197u, 108u, 1u, 92u,
- 96u, 170u, 153u, 132u,
- 165u, 88u, 123u, 178u,
- 117u, 114u, 97u, 69u,
- 115u, 150u, 1u, 51u,
- 141u, 162u, 124u, 90u,
- 135u, 126u, 141u, 84u,
- 125u, 129u, 133u, 158u,
- 131u, 121u, 223u, 185u,
- 26u, 255u, 2u, 135u,
- 168u, 101u, 54u, 66u,
- 104u, 99u, 179u, 121u,
- 113u, 102u, 118u, 109u,
- 133u, 93u, 147u, 124u,
- 104u, 156u, 255u, 105u,
- 151u, 95u, 123u, 133u,
- 206u, 72u, 72u, 56u,
- 1u, 104u, 66u, 171u,
- 189u, 22u, 191u, 139u,
- 190u, 129u, 136u, 142u,
- 88u, 135u, 135u, 49u,
- 160u, 27u, 163u, 208u,
- 127u, 1u, 150u, 47u,
- 153u, 43u, 210u, 150u,
- 98u, 144u, 68u, 110u,
- 162u, 58u, 197u, 199u,
- 48u, 180u, 142u, 255u,
- 107u, 192u, 73u, 168u,
- 164u, 90u, 245u, 251u,
- 56u, 104u, 87u, 111u,
- 236u, 172u, 78u, 255u,
- 71u, 131u, 15u, 25u,
- 1u, 149u, 160u, 101u,
- 42u, 159u, 173u, 164u,
- 183u, 89u, 150u, 213u,
- 172u, 89u, 148u, 133u,
- 1u, 195u, 196u, 42u,
- 115u, 141u, 106u, 238u,
- 229u, 30u, 74u, 181u,
- 137u, 130u, 207u, 88u,
- 189u, 54u, 166u, 81u,
- 116u, 24u, 211u, 55u,
- 62u, 65u, 218u, 50u,
- 115u, 102u, 255u, 58u,
- 93u, 110u, 99u, 152u,
- 85u, 104u, 255u, 55u,
- 147u, 196u, 174u, 133u,
- 108u, 112u, 91u, 129u,
- 104u, 0u, 188u, 156u,
- 70u, 36u, 110u, 96u,
- 76u, 186u, 12u, 185u,
- 254u, 87u, 106u, 148u,
- 137u, 169u, 172u, 76u,
- 149u, 255u, 187u, 98u,
- 87u, 54u, 44u, 202u,
- 207u, 210u, 140u, 130u,
- 1u, 98u, 119u, 155u,
- 187u, 95u, 117u, 161u,
- 211u, 139u, 24u, 170u,
- 205u, 226u, 36u, 76u,
- 23u, 1u, 162u, 180u,
- 197u, 181u, 141u, 133u,
- 72u, 141u, 111u, 173u,
- 52u, 172u, 56u, 2u
-};
-
-const float16 LangIdNNParams::kEmbeddingsQuantScales1[] = {
- 15339u, 15412u, 15432u, 15371u,
- 15312u, 15494u, 15344u, 15449u,
- 15369u, 15449u, 15378u, 15369u,
- 15386u, 15296u, 15364u, 15363u,
- 15281u, 15380u, 15420u, 15367u,
- 15365u, 15307u, 15308u, 15361u,
- 15421u, 15384u, 15344u, 15357u,
- 15367u, 15388u, 15366u, 15348u,
- 15399u, 15297u, 15411u, 15317u,
- 15442u, 15431u, 15389u, 15385u,
- 15446u, 15322u, 15356u, 15366u,
- 15394u, 15459u, 15257u, 15316u,
- 15413u, 15347u, 15437u, 15411u,
- 15535u, 15338u, 15386u, 15280u,
- 15305u, 15388u, 15451u, 15312u,
- 15358u, 15323u, 15385u, 15313u,
- 15339u, 15350u, 15369u, 15283u,
- 15407u, 15361u, 15384u, 15395u,
- 15380u, 15357u, 15372u, 15287u,
- 15348u, 15447u, 15366u, 15380u,
- 15332u, 15375u, 15391u, 15420u,
- 15373u, 15383u, 15417u, 15303u,
- 15349u, 15388u, 15284u, 15343u,
- 15402u, 15337u, 15466u, 15343u,
- 15327u, 15398u, 15386u, 15381u,
- 15418u, 15394u, 15386u, 15390u,
- 15414u, 15361u, 15388u, 15338u,
- 15331u, 15319u, 15365u, 15322u,
- 15281u, 15372u, 15400u, 15356u,
- 15255u, 15346u, 15327u, 15413u,
- 15409u, 15403u, 15365u, 15349u,
- 15312u, 15321u, 15387u, 15316u,
- 15336u, 15344u, 15294u, 15388u,
- 15282u, 15369u, 15394u, 15407u,
- 15463u, 15432u, 15360u, 15323u,
- 15383u, 15393u, 15362u, 15411u,
- 15385u, 15375u, 15343u, 15406u,
- 15287u, 15301u, 15374u, 15351u,
- 15360u, 15384u, 15362u, 15396u,
- 15326u, 15318u, 15400u, 15380u,
- 15370u, 15353u, 15390u, 15296u,
- 15316u, 15491u, 15409u, 15409u,
- 15377u, 15450u, 15358u, 15469u,
- 15376u, 15429u, 15401u, 15364u,
- 15402u, 15347u, 15391u, 15348u,
- 15336u, 15327u, 15333u, 15399u,
- 15421u, 15348u, 15519u, 15291u,
- 15350u, 15459u, 15353u, 15372u,
- 15371u, 15325u, 15332u, 15409u,
- 15362u, 15274u, 15417u, 15329u,
- 15498u, 15388u, 15391u, 15270u,
- 15317u, 15311u, 15365u, 15429u,
- 15352u, 15381u, 15300u, 15422u,
- 15383u, 15381u, 15236u, 15334u,
- 15262u, 15387u, 15333u, 15500u,
- 15340u, 15300u, 15388u, 15419u,
- 15362u, 15363u, 15387u, 15320u,
- 15302u, 15372u, 15371u, 15301u,
- 15506u, 15400u, 15423u, 15390u,
- 15425u, 15310u, 15347u, 15310u,
- 15380u, 15317u, 15280u, 15353u,
- 15416u, 15398u, 15320u, 15399u,
- 15375u, 15392u, 15332u, 15355u,
- 15420u, 15404u, 15381u, 15310u,
- 15330u, 15376u, 15408u, 15382u,
- 15382u, 15442u, 15396u, 15376u,
- 15290u, 15299u, 15432u, 15375u,
- 15492u, 15309u, 15401u, 15366u,
- 15339u, 15406u, 15327u, 15407u,
- 15316u, 15335u, 15425u, 15364u,
- 15284u, 15407u, 15313u, 15409u,
- 15384u, 15373u, 15352u, 15433u,
- 15392u, 15383u, 15506u, 15327u,
- 15297u, 15327u, 15288u, 15372u,
- 15386u, 15414u, 15276u, 15389u,
- 15328u, 15372u, 15341u, 15354u,
- 15431u, 15385u, 15396u, 15364u,
- 15374u, 15294u, 15375u, 15398u,
- 15507u, 15378u, 15398u, 15401u,
- 15381u, 15365u, 15345u, 15412u,
- 15402u, 15339u, 15290u, 15395u,
- 15364u, 15391u, 15370u, 15319u,
- 15253u, 15371u, 15293u, 15356u,
- 15300u, 15252u, 15444u, 15298u,
- 15377u, 15365u, 15276u, 15291u,
- 15356u, 15448u, 15512u, 15384u,
- 15338u, 15335u, 15363u, 15392u,
- 15365u, 15340u, 15395u, 15466u,
- 15310u, 15386u, 15371u, 15384u,
- 15414u, 15361u, 15375u, 15416u,
- 15425u, 15359u, 15425u, 15402u,
- 15396u, 15439u, 15350u, 15329u,
- 15382u, 15365u, 15294u, 15265u,
- 15319u, 15390u, 15383u, 15386u,
- 15404u, 15373u, 15355u, 15451u,
- 15330u, 15393u, 15327u, 15408u,
- 15360u, 15375u, 15394u, 15370u,
- 15319u, 15324u, 15277u, 15296u,
- 15349u, 15363u, 15413u, 15324u,
- 15502u, 15362u, 15408u, 15365u,
- 15365u, 15436u, 15393u, 15396u,
- 15376u, 15442u, 15390u, 15331u,
- 15299u, 15313u, 15400u, 15261u,
- 15434u, 15345u, 15338u, 15332u,
- 15395u, 15371u, 15393u, 15289u,
- 15361u, 15338u, 15374u, 15336u,
- 15379u, 15384u, 15395u, 15260u,
- 15324u, 15449u, 15304u, 15337u,
- 15357u, 15445u, 15376u, 15336u,
- 15367u, 15326u, 15274u, 15361u,
- 15380u, 15380u, 15335u, 15445u,
- 15393u, 15446u, 15367u, 15302u,
- 15463u, 15400u, 15385u, 15297u,
- 15392u, 15320u, 15312u, 15357u,
- 15484u, 15382u, 15435u, 15367u,
- 15370u, 15232u, 15392u, 15371u,
- 15433u, 15427u, 15283u, 15327u,
- 15381u, 15393u, 15395u, 15362u,
- 15305u, 15369u, 15425u, 15456u,
- 15338u, 15369u, 15366u, 15380u,
- 15427u, 15396u, 15327u, 15364u,
- 15392u, 15314u, 15465u, 15349u,
- 15392u, 15430u, 15332u, 15307u,
- 15275u, 15343u, 15295u, 15383u,
- 15433u, 15420u, 15330u, 15446u,
- 15495u, 15416u, 15420u, 15426u,
- 15504u, 15336u, 15394u, 15385u,
- 15354u, 15313u, 15405u, 15470u,
- 15401u, 15395u, 15382u, 15379u,
- 15361u, 15307u, 15264u, 15364u,
- 15323u, 15389u, 15352u, 15382u,
- 15390u, 15367u, 15400u, 15327u,
- 15351u, 15287u, 15392u, 15392u,
- 15401u, 15356u, 15373u, 15361u,
- 15434u, 15489u, 15585u, 15386u,
- 15410u, 15387u, 15302u, 15359u,
- 15424u, 15398u, 15376u, 15289u,
- 15294u, 15381u, 15497u, 15396u,
- 15398u, 15372u, 15454u, 15359u,
- 15381u, 15367u, 15477u, 15308u,
- 15314u, 15317u, 15402u, 15289u,
- 15370u, 15279u, 15383u, 15332u,
- 15363u, 15382u, 15413u, 15385u,
- 15285u, 15456u, 15476u, 15392u,
- 15360u, 15458u, 15382u, 15387u,
- 15368u, 15300u, 15391u, 15282u,
- 15307u, 15420u, 15321u, 15368u,
- 15312u, 15308u, 15457u, 15323u,
- 15385u, 15476u, 15369u, 15407u,
- 15347u, 15440u, 15303u, 15474u,
- 15396u, 15310u, 15195u, 15331u,
- 15246u, 15353u, 15364u, 15441u,
- 15400u, 15376u, 15305u, 15393u,
- 15405u, 15350u, 15421u, 15388u,
- 15441u, 15495u, 15280u, 15381u,
- 15336u, 15233u, 15362u, 15383u,
- 15396u, 15439u, 15318u, 15266u,
- 15264u, 15286u, 15275u, 15375u,
- 15410u, 15258u, 15284u, 15364u,
- 15350u, 15354u, 15246u, 15398u,
- 15321u, 15373u, 15363u, 15405u,
- 15318u, 15280u, 15403u, 15365u,
- 15284u, 15425u, 15390u, 15382u,
- 15384u, 15408u, 15398u, 15317u,
- 15304u, 15403u, 15375u, 15387u,
- 15394u, 15271u, 15434u, 15340u,
- 15344u, 15279u, 15502u, 15357u,
- 15322u, 15407u, 15304u, 15374u,
- 15302u, 15389u, 15539u, 15383u,
- 15267u, 15370u, 15363u, 15371u,
- 15409u, 15328u, 15331u, 15464u,
- 15366u, 15433u, 15308u, 15334u,
- 15458u, 15402u, 15229u, 15331u,
- 15422u, 15289u, 15410u, 15336u,
- 15402u, 15365u, 15348u, 15365u,
- 15319u, 15386u, 15483u, 15361u,
- 15365u, 15410u, 15393u, 15397u,
- 15360u, 15263u, 15292u, 15445u,
- 15433u, 15364u, 15298u, 15408u,
- 15410u, 15267u, 15404u, 15417u,
- 15399u, 15418u, 15499u, 15426u,
- 15291u, 15358u, 15443u, 15298u,
- 15285u, 15371u, 15371u, 15450u,
- 15426u, 15326u, 15339u, 15391u,
- 15437u, 15357u, 15362u, 15383u,
- 15354u, 15364u, 15405u, 15373u,
- 15304u, 15338u, 15414u, 15432u,
- 15291u, 15376u, 15431u, 15420u,
- 15374u, 15312u, 15388u, 15363u,
- 15383u, 15381u, 15556u, 15328u,
- 15464u, 15400u, 15304u, 15360u,
- 15411u, 15402u, 15460u, 15344u,
- 15364u, 15399u, 15418u, 15277u,
- 15368u, 15380u, 15371u, 15416u,
- 15413u, 15403u, 15381u, 15414u,
- 15390u, 15367u, 15297u, 15414u,
- 15393u, 15389u, 15346u, 15420u,
- 15322u, 15363u, 15489u, 15306u,
- 15276u, 15443u, 15364u, 15443u,
- 15498u, 15325u, 15375u, 15347u,
- 15391u, 15510u, 15397u, 15409u,
- 15401u, 15397u, 15370u, 15348u,
- 15399u, 15264u, 15308u, 15383u,
- 15470u, 15413u, 15420u, 15436u,
- 15290u, 15416u, 15388u, 15286u,
- 15402u, 15397u, 15265u, 15408u,
- 15322u, 15358u, 15409u, 15364u,
- 15360u, 15320u, 15384u, 15363u,
- 15367u, 15391u, 15424u, 15445u,
- 15305u, 15341u, 15368u, 15362u,
- 15310u, 15440u, 15331u, 15359u,
- 15297u, 15328u, 15372u, 15379u,
- 15408u, 15348u, 15349u, 15386u,
- 15365u, 15399u, 15404u, 15302u,
- 15264u, 15318u, 15379u, 15322u,
- 15364u, 15563u, 15343u, 15365u,
- 15333u, 15345u, 15356u, 15328u,
- 15335u, 15466u, 15347u, 15306u,
- 15404u, 15325u, 15406u, 15238u,
- 15428u, 15382u, 15396u, 15421u,
- 15423u, 15381u, 15383u, 15314u,
- 15360u, 15387u, 15369u, 15379u,
- 15407u, 15382u, 15323u, 15376u,
- 15384u, 15416u, 15271u, 15412u,
- 15370u, 15309u, 15369u, 15379u,
- 15305u, 15386u, 15306u, 15383u,
- 15377u, 15290u, 15307u, 15407u,
- 15491u, 15360u, 15448u, 15382u,
- 15418u, 15370u, 15322u, 15373u,
- 15420u, 15399u, 15291u, 15366u,
- 15405u, 15320u, 15407u, 15347u,
- 15458u, 15469u, 15323u, 15390u,
- 15448u, 15408u, 15346u, 15339u,
- 15312u, 15442u, 15395u, 15285u,
- 15398u, 15346u, 15437u, 15301u,
- 15397u, 15448u, 15260u, 15488u,
- 15349u, 15291u, 15372u, 15428u,
- 15423u, 15386u, 15262u, 15371u,
- 15331u, 15353u, 15412u, 15387u,
- 15353u, 15510u, 15312u, 15247u,
- 15411u, 15409u, 15403u, 15366u,
- 15404u, 15266u, 15390u, 15365u,
- 15361u, 15367u, 15394u, 15363u,
- 15387u, 15438u, 15330u, 15268u,
- 15494u, 15403u, 15302u, 15496u,
- 15363u, 15368u, 15382u, 15412u,
- 15330u, 15312u, 15356u, 15395u,
- 15359u, 15378u, 15419u, 15384u,
- 15387u, 15282u, 15338u, 15332u,
- 15259u, 15341u, 15293u, 15368u,
- 15365u, 15228u, 15394u, 15282u,
- 15393u, 15315u, 15355u, 15381u,
- 15362u, 15277u, 15401u, 15382u,
- 15339u, 15406u, 15404u, 15373u,
- 15421u, 15347u, 15419u, 15261u,
- 15364u, 15317u, 15342u, 15276u,
- 15306u, 15374u, 15313u, 15459u,
- 15319u, 15291u, 15472u, 15406u,
- 15314u, 15374u, 15302u, 15430u,
- 15282u, 15354u, 15304u, 15391u,
- 15372u, 15356u, 15415u, 15345u,
- 15403u, 15382u, 15350u, 15368u,
- 15329u, 15277u, 15378u, 15349u,
- 15407u, 15329u, 15510u, 15335u,
- 15373u, 15278u, 15339u, 15396u,
- 15285u, 15339u, 15388u, 15331u,
- 15381u, 15367u, 15444u, 15320u,
- 15382u, 15432u, 15356u, 15369u,
- 15366u, 15492u, 15258u, 15450u,
- 15402u, 15420u, 15379u, 15371u,
- 15497u, 15470u, 15320u, 15369u,
- 15358u, 15404u, 15385u, 15579u,
- 15314u, 15365u, 15342u, 15394u,
- 15392u, 15263u, 15327u, 15406u,
- 15436u, 15517u, 15387u, 15397u,
- 15412u, 15334u, 15369u, 15407u,
- 15367u, 15285u, 15389u, 15443u,
- 15366u, 15369u, 15308u, 15407u,
- 15384u, 15411u, 15315u, 15390u,
- 15408u, 15384u, 15401u, 15516u,
- 15426u, 15418u, 15337u, 15402u,
- 15238u, 15391u, 15329u, 15377u,
- 15394u, 15369u, 15378u, 15362u,
- 15333u, 15371u, 15326u, 15347u,
- 15425u, 15378u, 15420u, 15345u,
- 15361u, 15300u, 15371u, 15389u,
- 15360u, 15452u, 15345u, 15364u,
- 15502u, 15413u, 15339u, 15222u,
- 15372u, 15429u, 15364u, 15388u,
- 15315u, 15392u, 15510u, 15317u,
- 15367u, 15439u, 15429u, 15357u,
- 15439u, 15433u, 15345u, 15419u,
- 15355u, 15308u, 15402u, 15238u,
- 15422u, 15349u, 15337u, 15375u,
- 15424u, 15340u, 15317u, 15417u,
- 15442u, 15325u, 15269u, 15349u,
- 15336u, 15412u, 15379u, 15408u,
- 15338u, 15241u, 15349u, 15381u,
- 15423u, 15306u, 15376u, 15445u,
- 15381u, 15389u, 15309u, 15363u,
- 15403u, 15417u, 15237u, 15480u,
- 15429u, 15399u, 15327u, 15340u,
- 15433u, 15374u, 15366u, 15331u,
- 15310u, 15339u, 15334u, 15351u,
- 15345u, 15295u, 15347u, 15413u,
- 15304u, 15370u, 15385u, 15298u,
- 15338u, 15409u, 15321u, 15360u,
- 15370u, 15402u, 15399u, 15403u,
- 15307u, 15239u, 15280u, 15366u,
- 15381u, 15377u, 15346u, 15407u,
- 15396u, 15419u, 15401u, 15369u,
- 15321u, 15328u, 15389u, 15371u,
- 15412u, 15338u, 15376u, 15394u,
- 15369u, 15364u, 15426u, 15312u,
- 15396u, 15448u, 15319u, 15288u,
- 15392u, 15411u, 15297u, 15400u,
- 15394u, 15386u, 15385u, 15333u,
- 15361u, 15400u, 15401u, 15313u,
- 15308u, 15414u, 15321u, 15399u,
- 15392u, 15455u, 15454u, 15354u,
- 15362u, 15340u, 15335u, 15398u,
- 15263u, 15371u, 15377u, 15361u,
- 15370u, 15274u, 15309u, 15408u,
- 15391u, 15251u, 15441u, 15323u,
- 15305u, 15366u, 15279u, 15363u,
- 15364u, 15285u, 15380u, 15380u,
- 15406u, 15473u, 15437u, 15422u,
- 15351u, 15412u, 15385u, 15298u,
- 15389u, 15370u, 15332u, 15291u,
- 15492u, 15469u, 15382u, 15381u,
- 15379u, 15365u, 15391u, 15408u,
- 15412u, 15350u, 15307u, 15394u,
- 15362u, 15402u, 15443u, 15364u,
- 15367u, 15380u, 15363u, 15397u,
- 15374u, 15283u, 15338u, 15248u,
- 15394u, 15392u, 15416u, 15258u,
- 15354u, 15356u, 15360u, 15433u,
- 15526u, 15363u, 15405u, 15347u,
- 15367u, 15384u, 15415u, 15366u,
- 15316u, 15341u, 15422u, 15370u,
- 15389u, 15404u, 15330u, 15232u,
- 15372u, 15327u, 15302u, 15366u,
- 15326u, 15385u, 15290u, 15360u,
- 15300u, 15349u, 15456u, 15401u,
- 15403u, 15338u, 15456u, 15487u,
- 15371u, 15377u, 15350u, 15366u,
- 15348u, 15444u, 15629u, 15422u,
- 15363u, 15365u, 15384u, 15269u,
- 15405u, 15383u, 15411u, 15417u,
- 15376u, 15404u, 15347u, 15401u,
- 15365u, 15387u, 15443u, 15380u,
- 15303u, 15319u, 15434u, 15370u,
- 15368u, 15297u, 15392u, 15504u,
- 15419u, 15522u, 15432u, 15332u,
- 15380u, 15386u, 15383u, 15284u,
- 15370u, 15324u, 15413u, 15362u,
- 15353u, 15363u, 15288u, 15400u,
- 15367u, 15445u, 15385u, 15378u,
- 15194u, 15349u, 15248u, 15323u,
- 15315u, 15395u, 15384u, 15315u,
- 15409u, 15420u, 15372u, 15343u,
- 15428u, 15408u, 15352u, 15388u,
- 15391u, 15402u, 15444u, 15384u,
- 15409u, 15327u, 15279u, 15327u,
- 15351u, 15349u, 15336u, 15418u,
- 15372u, 15361u, 15408u, 15360u,
- 15382u, 15389u, 15210u, 15409u,
- 15399u, 15327u, 15352u, 15363u,
- 15374u, 15355u, 15342u, 15313u,
- 15287u, 15432u, 15478u, 15541u,
- 15379u, 15393u, 15317u, 15470u,
- 15375u, 15381u, 15385u, 15411u,
- 15367u, 15368u, 15414u, 15305u,
- 15531u, 15475u, 15418u, 15350u,
- 15391u, 15376u, 15361u, 15326u,
- 15362u, 15343u, 15287u, 15412u,
- 15342u, 15276u, 15369u, 15306u,
- 15423u, 15309u, 15532u, 15390u,
- 15414u, 15378u, 15318u, 15432u,
- 15361u, 15368u, 15364u, 15380u,
- 15337u, 15386u, 15320u, 15328u,
- 15395u, 15326u, 15243u, 15405u,
- 15366u, 15415u, 15282u, 15401u,
- 15411u, 15356u, 15418u, 15447u,
- 15371u, 15295u, 15381u, 15293u,
- 15298u, 15417u, 15326u, 15370u,
- 15362u, 15393u, 15269u, 15385u,
- 15387u, 15370u, 15389u, 15362u,
- 15374u, 15309u, 15486u, 15347u,
- 15273u, 15451u, 15407u, 15402u,
- 15297u, 15371u, 15383u, 15331u,
- 15395u, 15465u, 15319u, 15310u,
- 15352u, 15362u, 15383u, 15321u,
- 15400u, 15422u, 15470u, 15391u,
- 15403u, 15437u, 15275u, 15394u,
- 15355u, 15379u, 15371u, 15385u,
- 15331u, 15397u, 15303u, 15370u,
- 15492u, 15276u, 15501u, 15309u,
- 15538u, 15350u, 15243u, 15307u,
- 15349u, 15398u, 15464u, 15387u,
- 15305u, 15318u, 15519u, 15259u,
- 15289u, 15421u, 15331u, 15489u,
- 15384u, 15362u, 15363u, 15409u,
- 15227u, 15439u, 15445u, 15298u,
- 15393u, 15376u, 15406u, 15411u,
- 15400u, 15310u, 15362u, 15382u,
- 15386u, 15464u, 15318u, 15420u,
- 15286u, 15362u, 15338u, 15284u,
- 15344u, 15372u, 15297u, 15392u,
- 15294u, 15368u, 15376u, 15404u,
- 15326u, 15335u, 15314u, 15268u,
- 15405u, 15360u, 15435u, 15291u,
- 15423u, 15290u, 15349u, 15377u,
- 15274u, 15334u, 15430u, 15411u,
- 15430u, 15402u, 15372u, 15339u,
- 15356u, 15363u, 15364u, 15471u,
- 15439u, 15373u, 15383u, 15487u,
- 15354u, 15389u, 15343u, 15382u,
- 15373u, 15405u, 15272u, 15377u,
- 15383u, 15296u, 15423u, 15357u,
- 15383u, 15270u, 15332u, 15321u,
- 15361u, 15390u, 15377u, 15402u,
- 15437u, 15338u, 15344u, 15351u,
- 15430u, 15382u, 15259u, 15372u,
- 15508u, 15390u, 15347u, 15353u,
- 15426u, 15364u, 15327u, 15395u,
- 15348u, 15369u, 15442u, 15273u,
- 15285u, 15441u, 15411u, 15334u,
- 15338u, 15314u, 15400u, 15364u,
- 15359u, 15410u, 15320u, 15302u,
- 15305u, 15495u, 15262u, 15226u,
- 15390u, 15392u, 15350u, 15388u,
- 15400u, 15360u, 15294u, 15326u,
- 15434u, 15317u, 15320u, 15381u,
- 15418u, 15275u, 15392u, 15507u,
- 15356u, 15407u, 15375u, 15325u,
- 15338u, 15398u, 15245u, 15367u,
- 15425u, 15409u, 15384u, 15369u,
- 15418u, 15310u, 15360u, 15351u,
- 15349u, 15387u, 15417u, 15323u,
- 15365u, 15311u, 15284u, 15377u,
- 15364u, 15397u, 15361u, 15386u,
- 15344u, 15272u, 15403u, 15461u,
- 15219u, 15279u, 15217u, 15372u,
- 15360u, 15364u, 15297u, 15471u,
- 15338u, 15379u, 15281u, 15377u,
- 15326u, 15280u, 15421u, 15498u,
- 15325u, 15395u, 15436u, 15367u,
- 15366u, 15417u, 15301u, 15573u,
- 15354u, 15276u, 15358u, 15261u,
- 15282u, 15328u, 15436u, 15402u,
- 15466u, 15345u, 15223u, 15402u,
- 15536u, 15327u, 15470u, 15323u,
- 15334u, 15448u, 15299u, 15323u,
- 15384u, 15381u, 15312u, 15422u,
- 15408u, 15367u, 15440u, 15370u,
- 15357u, 15365u, 15384u, 15437u,
- 15375u, 15297u, 15300u, 15396u,
- 15360u, 15400u, 15375u, 15338u,
- 15398u, 15329u, 15405u, 15162u,
- 15542u, 15404u, 15272u, 15406u,
- 15420u, 15373u, 15339u, 15327u,
- 15379u, 15382u, 15442u, 15441u,
- 15383u, 15326u, 15407u, 15355u,
- 15404u, 15342u, 15377u, 15361u,
- 15270u, 15309u, 15480u, 15297u,
- 15394u, 15307u, 15376u, 15407u,
- 15324u, 15400u, 15436u, 15363u,
- 15324u, 15508u, 15320u, 15369u,
- 15376u, 15328u, 15371u, 15381u,
- 15253u, 15414u, 15328u, 15284u,
- 15367u, 15326u, 15365u, 15512u,
- 15356u, 15344u, 15419u, 15376u,
- 15392u, 15405u, 15392u, 15393u,
- 15410u, 15325u, 15267u, 15388u,
- 15402u, 15281u, 15255u, 15286u,
- 15318u, 15363u, 15362u, 15368u,
- 15342u, 15313u, 15353u, 15288u,
- 15366u, 15367u, 15391u, 15281u,
- 15344u, 15319u, 15365u, 15349u,
- 15295u, 15320u, 15370u, 15261u,
- 15370u, 15362u, 15525u, 15309u,
- 15439u, 15361u, 15367u, 15385u,
- 15371u, 15390u, 15396u, 15358u,
- 15388u, 15279u, 15250u, 15484u,
- 15259u, 15339u, 15413u, 15326u,
- 15494u, 15350u, 15323u, 15338u,
- 15395u, 15371u, 15339u, 15393u,
- 15389u, 15299u, 15386u, 15427u,
- 15397u, 15363u, 15390u, 15307u,
- 15377u, 15250u, 15467u, 15382u,
- 15351u, 15401u, 15313u, 15291u,
- 15332u, 15305u, 15340u, 15447u,
- 15298u, 15391u, 15455u, 15367u,
- 15282u, 15438u, 15338u, 15320u,
- 15428u, 15391u, 15394u, 15491u,
- 15365u, 15373u, 15425u, 15436u,
- 15365u, 15455u, 15366u, 15334u,
- 15398u, 15388u, 15360u, 15387u,
- 15310u, 15302u, 15367u, 15361u,
- 15349u, 15403u, 15296u, 15389u,
- 15458u, 15438u, 15367u, 15403u,
- 15385u, 15360u, 15327u, 15527u,
- 15394u, 15425u, 15324u, 15387u,
- 15376u, 15476u, 15378u, 15391u,
- 15397u, 15404u, 15387u, 15402u,
- 15242u, 15389u, 15393u, 15363u,
- 15376u, 15327u, 15335u, 15295u,
- 15326u, 15395u, 15349u, 15342u,
- 15283u, 15434u, 15453u, 15449u,
- 15327u, 15222u, 15381u, 15303u,
- 15330u, 15364u, 15338u, 15409u,
- 15337u, 15349u, 15369u, 15363u,
- 15382u, 15339u, 15385u, 15261u,
- 15373u, 15442u, 15401u, 15361u,
- 15289u, 15362u, 15325u, 15332u,
- 15405u, 15369u, 15350u, 15404u,
- 15364u, 15285u, 15383u, 15403u,
- 15384u, 15355u, 15292u, 15263u,
- 15382u, 15341u, 15389u, 15422u,
- 15358u, 15419u, 15333u, 15418u,
- 15406u, 15425u, 15410u, 15374u,
- 15290u, 15387u, 15425u, 15353u,
- 15393u, 15289u, 15424u, 15365u,
- 15314u, 15454u, 15342u, 15372u,
- 15468u, 15533u, 15371u, 15384u,
- 15374u, 15401u, 15321u, 15343u,
- 15317u, 15424u, 15333u, 15386u,
- 15369u, 15334u, 15320u, 15337u,
- 15380u, 15428u, 15386u, 15341u,
- 15442u, 15287u, 15469u, 15346u,
- 15438u, 15341u, 15294u, 15325u,
- 15379u, 15305u, 15365u, 15405u,
- 15314u, 15377u, 15338u, 15381u,
- 15396u, 15344u, 15373u, 15320u,
- 15417u, 15277u, 15402u, 15439u,
- 15310u, 15466u, 15309u, 15406u,
- 15396u, 15345u, 15361u, 15327u,
- 15361u, 15308u, 15336u, 15254u,
- 15397u, 15388u, 15374u, 15498u,
- 15332u, 15386u, 15441u, 15276u,
- 15359u, 15322u, 15256u, 15387u,
- 15392u, 15405u, 15370u, 15361u,
- 15361u, 15434u, 15400u, 15364u,
- 15330u, 15388u, 15257u, 15344u,
- 15362u, 15440u, 15308u, 15368u,
- 15369u, 15347u, 15430u, 15341u,
- 15349u, 15366u, 15381u, 15450u,
- 15326u, 15320u, 15306u, 15367u,
- 15333u, 15387u, 15341u, 15360u,
- 15394u, 15420u, 15415u, 15275u,
- 15296u, 15466u, 15410u, 15359u,
- 15375u, 15386u, 15281u, 15310u,
- 15366u, 15310u, 15329u, 15314u,
- 15327u, 15393u, 15363u, 15415u,
- 15449u, 15392u, 15341u, 15465u,
- 15443u, 15378u, 15361u, 15308u,
- 15355u, 15325u, 15296u, 15325u,
- 15464u, 15416u, 15320u, 15367u,
- 15405u, 15434u, 15400u, 15371u,
- 15420u, 15349u, 15414u, 15355u,
- 15360u, 15415u, 15332u, 15488u,
- 15308u, 15403u, 15364u, 15286u,
- 15420u, 15321u, 15388u, 15379u,
- 15308u, 15367u, 15489u, 15442u,
- 15387u, 15376u, 15380u, 15364u,
- 15364u, 15447u, 15336u, 15404u,
- 15483u, 15372u, 15414u, 15358u,
- 15379u, 15245u, 15370u, 15294u,
- 15485u, 15362u, 15373u, 15375u,
- 15350u, 15371u, 15374u, 15384u,
- 15440u, 15395u, 15374u, 15281u,
- 15303u, 15316u, 15494u, 15389u,
- 15403u, 15394u, 15364u, 15269u,
- 15430u, 15399u, 15416u, 15384u,
- 15431u, 15488u, 15367u, 15380u,
- 15437u, 15313u, 15384u, 15389u,
- 15326u, 15397u, 15337u, 15374u,
- 15390u, 15335u, 15306u, 15281u,
- 15295u, 15382u, 15444u, 15366u,
- 15329u, 15359u, 15405u, 15377u,
- 15354u, 15449u, 15421u, 15423u,
- 15358u, 15393u, 15355u, 15401u,
- 15343u, 15351u, 15255u, 15424u,
- 15362u, 15282u, 15372u, 15290u,
- 15407u, 15335u, 15308u, 15290u,
- 15388u, 15357u, 15406u, 15322u,
- 15348u, 15376u, 15521u, 15504u,
- 15337u, 15387u, 15312u, 15277u,
- 15269u, 15316u, 15348u, 15466u,
- 15393u, 15388u, 15398u, 15400u,
- 15433u, 15301u, 15335u, 15407u,
- 15435u, 15331u, 15313u, 15449u,
- 15395u, 15411u, 15366u, 15359u,
- 15369u, 15421u, 15290u, 15390u,
- 15377u, 15421u, 15398u, 15377u,
- 15312u, 15394u, 15395u, 15364u,
- 15496u, 15286u, 15459u, 15352u,
- 15525u, 15297u, 15394u, 15502u,
- 15377u, 15360u, 15452u, 15390u,
- 15375u, 15416u, 15338u, 15392u,
- 15348u, 15361u, 15354u, 15422u,
- 15333u, 15503u, 15312u, 15321u,
- 15408u, 15491u, 15544u, 15271u,
- 15357u, 15420u, 15376u, 15362u,
- 15408u, 15494u, 15277u, 15330u,
- 15412u, 15408u, 15369u, 15341u,
- 15412u, 15376u, 15367u, 15415u,
- 15274u, 15397u, 15371u, 15295u,
- 15381u, 15262u, 15437u, 15361u,
- 15384u, 15393u, 15436u, 15449u,
- 15360u, 15324u, 15244u, 15319u,
- 15350u, 15422u, 15316u, 15396u,
- 15304u, 15403u, 15348u, 15372u,
- 15328u, 15349u, 15361u, 15374u,
- 15443u, 15432u, 15384u, 15370u,
- 15360u, 15262u, 15340u, 15391u,
- 15316u, 15385u, 15335u, 15374u,
- 15422u, 15372u, 15398u, 15382u,
- 15448u, 15298u, 15379u, 15269u,
- 15289u, 15400u, 15377u, 15422u,
- 15216u, 15318u, 15425u, 15372u,
- 15319u, 15362u, 15327u, 15378u,
- 15426u, 15350u, 15290u, 15366u,
- 15402u, 15289u, 15383u, 15436u,
- 15443u, 15424u, 15346u, 15403u,
- 15392u, 15364u, 15299u, 15363u,
- 15426u, 15337u, 15253u, 15403u,
- 15402u, 15507u, 15415u, 15425u,
- 15373u, 15307u, 15488u, 15339u,
- 15296u, 15377u, 15383u, 15462u,
- 15471u, 15355u, 15456u, 15352u,
- 15454u, 15251u, 15447u, 15300u,
- 15425u, 15276u, 15377u, 15382u,
- 15398u, 15376u, 15297u, 15385u,
- 15394u, 15373u, 15295u, 15383u,
- 15383u, 15491u, 15395u, 15446u,
- 15369u, 15365u, 15447u, 15639u,
- 15348u, 15327u, 15322u, 15307u,
- 15435u, 15316u, 15367u, 15308u,
- 15329u, 15390u, 15283u, 15386u,
- 15326u, 15407u, 15383u, 15365u,
- 15323u, 15384u, 15426u, 15412u,
- 15373u, 15490u, 15374u, 15308u,
- 15498u, 15304u, 15296u, 15304u,
- 15278u, 15324u, 15369u, 15355u,
- 15334u, 15330u, 15376u, 15391u,
- 15299u, 15358u, 15411u, 15384u,
- 15267u, 15317u, 15307u, 15414u,
- 15411u, 15276u, 15357u, 15283u,
- 15393u, 15409u, 15367u, 15340u,
- 15386u, 15389u, 15366u, 15273u,
- 15316u, 15217u, 15331u, 15360u,
- 15429u, 15376u, 15374u, 15322u,
- 15300u, 15373u, 15402u, 15337u,
- 15362u, 15356u, 15368u, 15376u,
- 15380u, 15291u, 15313u, 15338u,
- 15328u, 15354u, 15355u, 15230u,
- 15401u, 15388u, 15398u, 15355u,
- 15438u, 15481u, 15320u, 15413u,
- 15279u, 15437u, 15366u, 15342u,
- 15334u, 15306u, 15368u, 15323u,
- 15357u, 15404u, 15375u, 15287u,
- 15311u, 15361u, 15223u, 15359u,
- 15370u, 15407u, 15416u, 15335u,
- 15314u, 15451u, 15360u, 15391u,
- 15343u, 15396u, 15362u, 15484u,
- 15423u, 15394u, 15345u, 15439u,
- 15384u, 15356u, 15282u, 15379u,
- 15418u, 15490u, 15323u, 15409u,
- 15338u, 15464u, 15399u, 15370u,
- 15337u, 15275u, 15339u, 15384u,
- 15392u, 15336u, 15381u, 15346u,
- 15343u, 15417u, 15392u, 15387u,
- 15407u, 15413u, 15361u, 15372u,
- 15307u, 15361u, 15426u, 15393u,
- 15482u, 15409u, 15393u, 15366u,
- 15395u, 15475u, 15320u, 15432u,
- 15311u, 15478u, 15424u, 15262u,
- 15510u, 15377u, 15404u, 15385u,
- 15349u, 15379u, 15318u, 15274u,
- 15294u, 15345u, 15322u, 15446u,
- 15236u, 15409u, 15392u, 15367u,
- 15411u, 15500u, 15416u, 15269u,
- 15329u, 15468u, 15345u, 15264u,
- 15319u, 15392u, 15410u, 15500u,
- 15361u, 15321u, 15374u, 15372u,
- 15397u, 15387u, 15449u, 15411u,
- 15452u, 15310u, 15342u, 15401u,
- 15325u, 15325u, 15306u, 15406u,
- 15394u, 15361u, 15298u, 15364u,
- 15508u, 15417u, 15390u, 15456u,
- 15383u, 15385u, 15369u, 15330u,
- 15343u, 15377u, 15424u, 15447u,
- 15270u, 15444u, 15400u, 15411u,
- 15316u, 15283u, 15354u, 15398u,
- 15314u, 15355u, 15408u, 15384u,
- 15323u, 15438u, 15305u, 15303u,
- 15447u, 15413u, 15464u, 15346u,
- 15393u, 15515u, 15321u, 15436u,
- 15326u, 15367u, 15346u, 15353u,
- 15407u, 15360u, 15342u, 15418u,
- 15490u, 15328u, 15288u, 15311u,
- 15398u, 15413u, 15352u, 15306u,
- 15406u, 15374u, 15281u, 15400u,
- 15423u, 15276u, 15340u, 15427u,
- 15295u, 15402u, 15365u, 15456u,
- 15291u, 15341u, 15243u, 15363u,
- 15321u, 15379u, 15298u, 15414u,
- 15282u, 15404u, 15372u, 15377u,
- 15372u, 15332u, 15385u, 15295u,
- 15440u, 15362u, 15392u, 15483u,
- 15401u, 15377u, 15424u, 15380u,
- 15339u, 15304u, 15442u, 15371u,
- 15308u, 15331u, 15364u, 15303u,
- 15296u, 15347u, 15262u, 15366u,
- 15313u, 15386u, 15344u, 15427u,
- 15321u, 15387u, 15304u, 15337u,
- 15273u, 15392u, 15351u, 15398u,
- 15361u, 15390u, 15351u, 15412u,
- 15350u, 15417u, 15399u, 15349u,
- 15365u, 15343u, 15297u, 15543u,
- 15272u, 15316u, 15322u, 15407u,
- 15344u, 15373u, 15348u, 15453u,
- 15372u, 15307u, 15300u, 15412u,
- 15317u, 15380u, 15412u, 15289u,
- 15432u, 15403u, 15363u, 15372u,
- 15392u, 15301u, 15321u, 15326u,
- 15360u, 15453u, 15278u, 15429u,
- 15366u, 15274u, 15459u, 15370u,
- 15376u, 15315u, 15387u, 15383u,
- 15368u, 15373u, 15373u, 15324u,
- 15304u, 15341u, 15318u, 15361u,
- 15313u, 15320u, 15363u, 15369u,
- 15471u, 15351u, 15476u, 15415u,
- 15339u, 15380u, 15318u, 15322u,
- 15353u, 15258u, 15368u, 15430u,
- 15377u, 15327u, 15387u, 15251u,
- 15446u, 15380u, 15324u, 15391u,
- 15457u, 15256u, 15316u, 15433u,
- 15410u, 15386u, 15427u, 15446u,
- 15380u, 15310u, 15417u, 15412u,
- 15375u, 15365u, 15369u, 15323u,
- 15363u, 15330u, 15352u, 15325u,
- 15359u, 15360u, 15497u, 15361u,
- 15352u, 15458u, 15413u, 15386u,
- 15367u, 15325u, 15379u, 15452u,
- 15464u, 15420u, 15359u, 15326u,
- 15361u, 15393u, 15417u, 15403u,
- 15429u, 15362u, 15383u, 15262u,
- 15367u, 15394u, 15418u, 15351u,
- 15360u, 15450u, 15370u, 15314u,
- 15297u, 15362u, 15349u, 15390u,
- 15365u, 15391u, 15319u, 15370u,
- 15286u, 15431u, 15399u, 15389u,
- 15331u, 15274u, 15425u, 15374u,
- 15308u, 15269u, 15374u, 15350u,
- 15347u, 15335u, 15280u, 15302u,
- 15285u, 15424u, 15394u, 15297u,
- 15290u, 15255u, 15419u, 15368u,
- 15344u, 15376u, 15380u, 15332u,
- 15383u, 15375u, 15305u, 15304u,
- 15370u, 15412u, 15312u, 15352u,
- 15398u, 15464u, 15384u, 15354u,
- 15423u, 15337u, 15310u, 15427u,
- 15363u, 15369u, 15459u, 15318u,
- 15306u, 15396u, 15387u, 15314u,
- 15361u, 15366u, 15320u, 15374u,
- 15328u, 15424u, 15354u, 15374u,
- 15333u, 15398u, 15372u, 15360u,
- 15344u, 15408u, 15379u, 15384u,
- 15306u, 15399u, 15397u, 15239u,
- 15335u, 15377u, 15372u, 15406u,
- 15283u, 15378u, 15494u, 15415u,
- 15338u, 15360u, 15350u, 15403u,
- 15347u, 15399u, 15380u, 15276u,
- 15248u, 15394u, 15289u, 15310u,
- 15469u, 15419u, 15280u, 15408u,
- 15379u, 15396u, 15385u, 15307u,
- 15381u, 15372u, 15358u, 15456u,
- 15524u, 15309u, 15395u, 15368u,
- 15398u, 15386u, 15385u, 15382u,
- 15428u, 15384u, 15307u, 15423u,
- 15389u, 15346u, 15401u, 15415u,
- 15460u, 15386u, 15351u, 15295u,
- 15364u, 15363u, 15347u, 15316u,
- 15269u, 15613u, 15454u, 15350u,
- 15443u, 15372u, 15358u, 15375u,
- 15394u, 15266u, 15289u, 15283u,
- 15403u, 15439u, 15393u, 15300u,
- 15338u, 15372u, 15327u, 15346u,
- 15343u, 15395u, 15368u, 15326u,
- 15427u, 15369u, 15434u, 15346u,
- 15366u, 15413u, 15296u, 15290u,
- 15413u, 15420u, 15278u, 15373u,
- 15433u, 15391u, 15359u, 15370u,
- 15320u, 15359u, 15361u, 15419u,
- 15376u, 15364u, 15387u, 15352u,
- 15366u, 15389u, 15258u, 15396u,
- 15401u, 15342u, 15431u, 15355u,
- 15391u, 15420u, 15422u, 15314u,
- 15423u, 15437u, 15354u, 15377u,
- 15421u, 15336u, 15464u, 15427u,
- 15361u, 15358u, 15401u, 15332u,
- 15377u, 15443u, 15382u, 15260u,
- 15343u, 15405u, 15391u, 15388u,
- 15355u, 15397u, 15510u, 15408u,
- 15314u, 15379u, 15375u, 15306u,
- 15266u, 15329u, 15306u, 15475u,
- 15477u, 15322u, 15332u, 15291u,
- 15336u, 15208u, 15484u, 15276u,
- 15370u, 15369u, 15353u, 15381u,
- 15512u, 15366u, 15404u, 15325u,
- 15276u, 15329u, 15298u, 15531u,
- 15287u, 15383u, 15391u, 15310u,
- 15350u, 15447u, 15314u, 15434u,
- 15453u, 15365u, 15368u, 15369u,
- 15323u, 15302u, 15396u, 15263u,
- 15419u, 15368u, 15476u, 15426u,
- 15227u, 15398u, 15313u, 15320u,
- 15420u, 15379u, 15282u, 15361u,
- 15401u, 15390u, 15353u, 15268u,
- 15387u, 15352u, 15327u, 15354u,
- 15363u, 15401u, 15344u, 15322u,
- 15388u, 15296u, 15378u, 15394u,
- 15318u, 15271u, 15338u, 15479u,
- 15305u, 15367u, 15401u, 15350u,
- 15363u, 15398u, 15325u, 15529u,
- 15374u, 15304u, 15330u, 15379u,
- 15347u, 15342u, 15377u, 15335u,
- 15379u, 15324u, 15336u, 15384u,
- 15396u, 15288u, 15363u, 15358u,
- 15362u, 15371u, 15390u, 15306u,
- 15274u, 15264u, 15320u, 15317u,
- 15367u, 15416u, 15385u, 15283u,
- 15277u, 15338u, 15380u, 15385u,
- 15284u, 15477u, 15407u, 15377u,
- 15379u, 15366u, 15393u, 15429u,
- 15420u, 15364u, 15325u, 15337u,
- 15361u, 15271u, 15309u, 15254u,
- 15276u, 15312u, 15328u, 15453u,
- 15468u, 15362u, 15260u, 15249u,
- 15406u, 15386u, 15397u, 15348u,
- 15387u, 15347u, 15363u, 15368u,
- 15316u, 15257u, 15283u, 15283u,
- 15348u, 15387u, 15389u, 15272u,
- 15361u, 15341u, 15252u, 15362u,
- 15368u, 15394u, 15299u, 15381u,
- 15544u, 15365u, 15425u, 15355u,
- 15315u, 15334u, 15335u, 15392u,
- 15387u, 15379u, 15331u, 15281u,
- 15326u, 15318u, 15322u, 15355u,
- 15371u, 15323u, 15443u, 15325u,
- 15298u, 15365u, 15374u, 15372u,
- 15271u, 15471u, 15399u, 15379u,
- 15316u, 15343u, 15405u, 15358u,
- 15427u, 15330u, 15334u, 15321u,
- 15398u, 15405u, 15359u, 15380u,
- 15438u, 15396u, 15357u, 15409u,
- 15275u, 15319u, 15268u, 15414u,
- 15347u, 15459u, 15378u, 15248u,
- 15368u, 15344u, 15378u, 15395u,
- 15332u, 15393u, 15327u, 15389u,
- 15393u, 15332u, 15434u, 15367u,
- 15417u, 15460u, 15411u, 15309u,
- 15375u, 15278u, 15426u, 15364u,
- 15450u, 15411u, 15373u, 15289u,
- 15302u, 15372u, 15361u, 15374u,
- 15311u, 15377u, 15390u, 15416u,
- 15347u, 15437u, 15498u, 15367u,
- 15380u, 15438u, 15278u, 15444u,
- 15268u, 15422u, 15361u, 15525u,
- 15333u, 15405u, 15393u, 15404u,
- 15352u, 15414u, 15471u, 15254u,
- 15389u, 15425u, 15351u, 15391u,
- 15333u, 15350u, 15518u, 15370u,
- 15464u, 15451u, 15394u, 15335u,
- 15327u, 15347u, 15322u, 15455u,
- 15263u, 15477u, 15379u, 15447u,
- 15310u, 15390u, 15366u, 15406u,
- 15455u, 15338u, 15388u, 15361u,
- 15276u, 15292u, 15379u, 15397u,
- 15426u, 15338u, 15332u, 15338u,
- 15420u, 15362u, 15425u, 15409u,
- 15381u, 15263u, 15472u, 15317u,
- 15511u, 15344u, 15356u, 15286u,
- 15347u, 15377u, 15297u, 15489u,
- 15393u, 15333u, 15352u, 15393u,
- 15367u, 15355u, 15409u, 15421u,
- 15300u, 15363u, 15321u, 15457u,
- 15352u, 15438u, 15385u, 15363u,
- 15380u, 15338u, 15354u, 15361u,
- 15324u, 15370u, 15244u, 15350u,
- 15419u, 15371u, 15278u, 15406u,
- 15379u, 15432u, 15379u, 15329u,
- 15419u, 15366u, 15345u, 15454u,
- 15345u, 15334u, 15398u, 15478u,
- 15382u, 15277u, 15367u, 15384u,
- 15360u, 15367u, 15325u, 15377u,
- 15416u, 15420u, 15402u, 15341u,
- 15376u, 15353u, 15296u, 15351u,
- 15292u, 15423u, 15395u, 15362u,
- 15287u, 15386u, 15288u, 15376u,
- 15388u, 15387u, 15432u, 15369u,
- 15448u, 15380u, 15317u, 15405u,
- 15409u, 15395u, 15423u, 15443u,
- 15398u, 15384u, 15381u, 15354u,
- 15292u, 15350u, 15371u, 15485u,
- 15305u, 15313u, 15381u, 15423u,
- 15352u, 15320u, 15389u, 15337u,
- 15317u, 15354u, 15354u, 15332u,
- 15241u, 15342u, 15395u, 15339u,
- 15353u, 15304u, 15274u, 15391u,
- 15314u, 15273u, 15296u, 15383u,
- 15386u, 15277u, 15355u, 15354u,
- 15404u, 15410u, 15278u, 15355u,
- 15389u, 15383u, 15262u, 15373u,
- 15228u, 15451u, 15280u, 15402u,
- 15290u, 15308u, 15366u, 15444u,
- 15360u, 15440u, 15468u, 15298u,
- 15371u, 15335u, 15372u, 15391u,
- 15435u, 15314u, 15219u, 15282u,
- 15401u, 15408u, 15378u, 15365u,
- 15397u, 15412u, 15335u, 15367u,
- 15286u, 15304u, 15380u, 15423u,
- 15320u, 15299u, 15282u, 15519u,
- 15422u, 15433u, 15410u, 15381u,
- 15395u, 15332u, 15440u, 15298u,
- 15610u, 15488u, 15353u, 15341u,
- 15357u, 15280u, 15439u, 15441u,
- 15369u, 15334u, 15272u, 15385u,
- 15445u, 15439u, 15313u, 15392u,
- 15483u, 15331u, 15344u, 15329u,
- 15395u, 15396u, 15355u, 15392u,
- 15309u, 15370u, 15366u, 15399u,
- 15326u, 15378u, 15362u, 15384u,
- 15367u, 15372u, 15337u, 15376u,
- 15367u, 15365u, 15261u, 15390u,
- 15321u, 15428u, 15362u, 15364u,
- 15405u, 15376u, 15403u, 15380u,
- 15356u, 15383u, 15450u, 15375u,
- 15370u, 15358u, 15365u, 15399u,
- 15322u, 15342u, 15314u, 15380u,
- 15365u, 15312u, 15393u, 15412u,
- 15375u, 15338u, 15324u, 15394u,
- 15363u, 15384u, 15360u, 15414u,
- 15380u, 15348u, 15376u, 15406u,
- 15290u, 15349u, 15352u, 15422u,
- 15284u, 15329u, 15440u, 15374u,
- 15311u, 15489u, 15438u, 15348u,
- 15394u, 15328u, 15376u, 15304u,
- 15403u, 15371u, 15333u, 15402u,
- 15371u, 15290u, 15408u, 15391u,
- 15258u, 15383u, 15366u, 15303u,
- 15411u, 15442u, 15378u, 15340u,
- 15365u, 15396u, 15442u, 15375u,
- 15304u, 15325u, 15460u, 15401u,
- 15491u, 15421u, 15409u, 15371u,
- 15414u, 15377u, 15402u, 15337u,
- 15310u, 15407u, 15300u, 15399u,
- 15385u, 15363u, 15404u, 15340u,
- 15299u, 15375u, 15287u, 15320u,
- 15311u, 15359u, 15320u, 15381u,
- 15370u, 15344u, 15397u, 15404u,
- 15415u, 15266u, 15523u, 15284u,
- 15466u, 15428u, 15391u, 15324u,
- 15318u, 15474u, 15249u, 15391u,
- 15386u, 15332u, 15364u, 15424u,
- 15381u, 15363u, 15356u, 15308u,
- 15327u, 15384u, 15334u, 15362u,
- 15418u, 15355u, 15306u, 15328u,
- 15400u, 15396u, 15361u, 15244u,
- 15403u, 15362u, 15386u, 15300u,
- 15280u, 15478u, 15352u, 15421u,
- 15357u, 15404u, 15388u, 15276u,
- 15375u, 15308u, 15453u, 15338u,
- 15394u, 15310u, 15332u, 15343u,
- 15350u, 15409u, 15421u, 15385u,
- 15411u, 15407u, 15437u, 15276u,
- 15378u, 15406u, 15360u, 15399u,
- 15395u, 15470u, 15304u, 15403u,
- 15386u, 15458u, 15425u, 15347u,
- 15323u, 15401u, 15411u, 15470u,
- 15419u, 15404u, 15417u, 15387u,
- 15395u, 15369u, 15344u, 15370u,
- 15473u, 15397u, 15371u, 15379u,
- 15359u, 15389u, 15453u, 15288u,
- 15488u, 15353u, 15422u, 15300u,
- 15412u, 15332u, 15393u, 15409u,
- 15387u, 15335u, 15443u, 15305u,
- 15340u, 15351u, 15385u, 15370u,
- 15456u, 15286u, 15385u, 15403u,
- 15342u, 15366u, 15294u, 15426u,
- 15353u, 15405u, 15269u, 15385u,
- 15364u, 15376u, 15390u, 15400u,
- 15392u, 15360u, 15399u, 15320u,
- 15363u, 15372u, 15215u, 15264u,
- 15411u, 15443u, 15321u, 15363u,
- 15327u, 15321u, 15465u, 15405u,
- 15362u, 15277u, 15494u, 15507u,
- 15472u, 15402u, 15369u, 15383u,
- 15326u, 15389u, 15264u, 15522u,
- 15368u, 15349u, 15439u, 15491u,
- 15379u, 15346u, 15290u, 15277u,
- 15358u, 15324u, 15275u, 15346u,
- 15380u, 15379u, 15413u, 15301u,
- 15383u, 15272u, 15403u, 15363u,
- 15386u, 15346u, 15259u, 15394u,
- 15362u, 15285u, 15381u, 15320u,
- 15360u, 15371u, 15327u, 15361u,
- 15434u, 15446u, 15370u, 15365u,
- 15414u, 15351u, 15376u, 15322u,
- 15364u, 15330u, 15364u, 15314u,
- 15257u, 15399u, 15466u, 15355u,
- 15396u, 15428u, 15298u, 15467u,
- 15285u, 15381u, 15255u, 15374u,
- 15402u, 15370u, 15344u, 15296u,
- 15426u, 15327u, 15273u, 15328u,
- 15302u, 15450u, 15350u, 15409u,
- 15408u, 15493u, 15381u, 15244u,
- 15288u, 15370u, 15221u, 15365u,
- 15374u, 15490u, 15350u, 15362u,
- 15422u, 15389u, 15294u, 15377u,
- 15384u, 15268u, 15416u, 15363u,
- 15384u, 15360u, 15378u, 15363u,
- 15334u, 15290u, 15372u, 15284u,
- 15265u, 15368u, 15368u, 15454u,
- 15343u, 15306u, 15387u, 15304u,
- 15429u, 15329u, 15437u, 15367u,
- 15288u, 15421u, 15327u, 15381u,
- 15378u, 15415u, 15310u, 15373u,
- 15386u, 15360u, 15557u, 15393u,
- 15390u, 15381u, 15466u, 15294u,
- 15294u, 15457u, 15397u, 15409u,
- 15344u, 15500u, 15384u, 15387u,
- 15377u, 15412u, 15345u, 15321u,
- 15386u, 15394u, 15394u, 15330u,
- 15388u, 15374u, 15343u, 15363u,
- 15373u, 15377u, 15390u, 15388u,
- 15338u, 15312u, 15410u, 15371u,
- 15348u, 15342u, 15415u, 15422u,
- 15285u, 15441u, 15338u, 15292u,
- 15275u, 15416u, 15394u, 15380u,
- 15307u, 15415u, 15295u, 15456u,
- 15388u, 15422u, 15373u, 15275u,
- 15361u, 15350u, 15390u, 15394u,
- 15376u, 15440u, 15372u, 15324u,
- 15362u, 15321u, 15389u, 15372u,
- 15383u, 15308u, 15312u, 15401u,
- 15372u, 15436u, 15330u, 15442u,
- 15406u, 15355u, 15411u, 15426u,
- 15472u, 15322u, 15289u, 15333u,
- 15259u, 15424u, 15295u, 15430u,
- 15365u, 15306u, 15394u, 15414u,
- 15360u, 15405u, 15395u, 15364u,
- 15363u, 15294u, 15401u, 15490u,
- 15446u, 15415u, 15390u, 15379u,
- 15423u, 15369u, 15364u, 15301u,
- 15401u, 15329u, 15303u, 15309u,
- 15401u, 15464u, 15384u, 15412u,
- 15442u, 15368u, 15402u, 15365u,
- 15363u, 15421u, 15401u, 15289u,
- 15384u, 15515u, 15332u, 15332u,
- 15393u, 15379u, 15252u, 15387u,
- 15361u, 15470u, 15356u, 15296u,
- 15334u, 15402u, 15406u, 15292u,
- 15383u, 15316u, 15347u, 15261u,
- 15328u, 15378u, 15258u, 15385u,
- 15388u, 15373u, 15362u, 15403u,
- 15334u, 15317u, 15341u, 15318u,
- 15336u, 15365u, 15362u, 15346u,
- 15490u, 15393u, 15362u, 15380u,
- 15423u, 15350u, 15383u, 15333u,
- 15376u, 15305u, 15279u, 15407u,
- 15326u, 15337u, 15326u, 15237u,
- 15348u, 15407u, 15338u, 15391u,
- 15421u, 15322u, 15332u, 15408u,
- 15355u, 15420u, 15436u, 15274u,
- 15417u, 15318u, 15426u, 15340u,
- 15310u, 15297u, 15341u, 15253u,
- 15506u, 15304u, 15380u, 15431u,
- 15376u, 15373u, 15392u, 15397u,
- 15367u, 15280u, 15427u, 15387u,
- 15280u, 15379u, 15434u, 15289u,
- 15378u, 15340u, 15399u, 15374u,
- 15443u, 15356u, 15385u, 15388u,
- 15429u, 15385u, 15430u, 15401u,
- 15351u, 15317u, 15374u, 15410u,
- 15415u, 15360u, 15305u, 15294u,
- 15444u, 15419u, 15253u, 15369u,
- 15356u, 15270u, 15375u, 15371u,
- 15377u, 15349u, 15292u, 15343u,
- 15349u, 15508u, 15440u, 15401u,
- 15412u, 15349u, 15447u, 15303u,
- 15362u, 15412u, 15310u, 15399u,
- 15407u, 15307u, 15362u, 15382u,
- 15407u, 15223u, 15376u, 15416u,
- 15341u, 15374u, 15291u, 15332u,
- 15405u, 15416u, 15338u, 15417u,
- 15371u, 15391u, 15329u, 15493u,
- 15397u, 15377u, 15369u, 15465u,
- 15340u, 15357u, 15383u, 15502u,
- 15348u, 15324u, 15299u, 15338u,
- 15357u, 15401u, 15410u, 15441u,
- 15510u, 15353u, 15381u, 15389u,
- 15373u, 15420u, 15401u, 15327u,
- 15366u, 15369u, 15358u, 15355u,
- 15439u, 15383u, 15376u, 15420u,
- 15278u, 15381u, 15335u, 15406u,
- 15372u, 15414u, 15405u, 15368u,
- 15335u, 15376u, 15359u, 15367u,
- 15402u, 15355u, 15364u, 15360u,
- 15355u, 15415u, 15268u, 15519u,
- 15313u, 15389u, 15350u, 15392u,
- 15382u, 15389u, 15445u, 15326u,
- 15301u, 15278u, 15431u, 15335u,
- 15241u, 15371u, 15286u, 15400u,
- 15316u, 15253u, 15315u, 15393u,
- 15393u, 15394u, 15407u, 15439u,
- 15332u, 15388u, 15347u, 15317u,
- 15405u, 15323u, 15362u, 15414u,
- 15421u, 15369u, 15380u, 15391u,
- 15253u, 15395u, 15397u, 15368u,
- 15272u, 15381u, 15300u, 15349u,
- 15418u, 15412u, 15322u, 15367u,
- 15288u, 15326u, 15455u, 15423u,
- 15433u, 15385u, 15377u, 15355u,
- 15395u, 15298u, 15319u, 15366u,
- 15379u, 15270u, 15454u, 15368u,
- 15311u, 15424u, 15338u, 15216u,
- 15433u, 15397u, 15332u, 15403u,
- 15276u, 15359u, 15272u, 15350u,
- 15387u, 15470u, 15360u, 15355u,
- 15376u, 15363u, 15440u, 15394u,
- 15439u, 15429u, 15333u, 15378u,
- 15497u, 15321u, 15365u, 15400u,
- 15363u, 15388u, 15385u, 15391u,
- 15332u, 15363u, 15363u, 15389u,
- 15351u, 15414u, 15403u, 15411u,
- 15415u, 15374u, 15366u, 15384u,
- 15384u, 15307u, 15435u, 15464u,
- 15327u, 15363u, 15347u, 15451u,
- 15394u, 15376u, 15364u, 15381u,
- 15371u, 15357u, 15383u, 15433u,
- 15455u, 15270u, 15410u, 15273u,
- 15303u, 15440u, 15330u, 15357u,
- 15367u, 15326u, 15394u, 15320u,
- 15331u, 15426u, 15367u, 15284u,
- 15256u, 15342u, 15370u, 15362u,
- 15405u, 15310u, 15310u, 15388u,
- 15390u, 15337u, 15330u, 15375u,
- 15295u, 15330u, 15422u, 15394u,
- 15329u, 15307u, 15341u, 15343u,
- 15398u, 15280u, 15406u, 15395u,
- 15333u, 15387u, 15297u, 15391u,
- 15402u, 15337u, 15299u, 15422u,
- 15363u, 15261u, 15308u, 15418u,
- 15345u, 15370u, 15362u, 15439u,
- 15401u, 15356u, 15344u, 15392u,
- 15395u, 15463u, 15398u, 15366u,
- 15485u, 15402u, 15405u, 15366u,
- 15427u, 15382u, 15345u, 15382u,
- 15390u, 15295u, 15339u, 15369u,
- 15254u, 15418u, 15397u, 15427u,
- 15397u, 15362u, 15419u, 15334u,
- 15398u, 15229u, 15333u, 15287u,
- 15363u, 15390u, 15330u, 15345u,
- 15331u, 15370u, 15269u, 15317u,
- 15346u, 15367u, 15420u, 15412u,
- 15377u, 15394u, 15388u, 15423u,
- 15304u, 15366u, 15354u, 15425u,
- 15246u, 15365u, 15295u, 15381u,
- 15274u, 15304u, 15350u, 15242u,
- 15374u, 15373u, 15330u, 15345u,
- 15316u, 15425u, 15370u, 15337u,
- 15377u, 15369u, 15251u, 15350u,
- 15366u, 15400u, 15390u, 15409u,
- 15295u, 15344u, 15308u, 15391u,
- 15261u, 15394u, 15403u, 15395u,
- 15247u, 15360u, 15375u, 15370u,
- 15384u, 15452u, 15347u, 15336u,
- 15340u, 15301u, 15454u, 15427u,
- 15443u, 15391u, 15390u, 15348u,
- 15361u, 15368u, 15459u, 15454u,
- 15336u, 15336u, 15363u, 15390u,
- 15422u, 15294u, 15358u, 15240u,
- 15525u, 15430u, 15329u, 15287u,
- 15375u, 15383u, 15363u, 15320u,
- 15377u, 15363u, 15268u, 15350u,
- 15402u, 15405u, 15386u, 15319u,
- 15345u, 15363u, 15366u, 15239u,
- 15371u, 15398u, 15367u, 15380u,
- 15431u, 15362u, 15287u, 15369u,
- 15309u, 15365u, 15301u, 15355u,
- 15312u, 15502u, 15367u, 15380u,
- 15291u, 15457u, 15390u, 15402u,
- 15435u, 15366u, 15333u, 15259u,
- 15396u, 15346u, 15330u, 15303u,
- 15360u, 15429u, 15306u, 15357u,
- 15388u, 15365u, 15300u, 15353u,
- 15384u, 15327u, 15280u, 15290u,
- 15420u, 15361u, 15366u, 15361u,
- 15379u, 15358u, 15342u, 15312u,
- 15299u, 15351u, 15378u, 15409u,
- 15418u, 15368u, 15301u, 15495u,
- 15281u, 15304u, 15439u, 15349u,
- 15300u, 15280u, 15371u, 15416u,
- 15369u, 15371u, 15407u, 15405u,
- 15298u, 15369u, 15466u, 15386u,
- 15378u, 15435u, 15348u, 15388u,
- 15403u, 15269u, 15305u, 15290u,
- 15405u, 15289u, 15397u, 15375u,
- 15302u, 15407u, 15315u, 15374u,
- 15341u, 15301u, 15369u, 15418u,
- 15302u, 15496u, 15345u, 15347u,
- 15267u, 15408u, 15380u, 15336u,
- 15542u, 15292u, 15385u, 15321u,
- 15398u, 15401u, 15189u, 15303u,
- 15400u, 15356u, 15294u, 15411u,
- 15377u, 15358u, 15400u, 15361u,
- 15317u, 15364u, 15323u, 15475u,
- 15385u, 15442u, 15402u, 15297u,
- 15361u, 15397u, 15260u, 15418u,
- 15340u, 15386u, 15391u, 15318u,
- 15407u, 15377u, 15382u, 15405u,
- 15358u, 15437u, 15339u, 15300u,
- 15366u, 15414u, 15400u, 15424u,
- 15421u, 15353u, 15414u, 15383u,
- 15431u, 15376u, 15358u, 15397u,
- 15365u, 15426u, 15392u, 15368u,
- 15386u, 15271u, 15372u, 15403u,
- 15272u, 15316u, 15375u, 15374u,
- 15392u, 15347u, 15369u, 15403u,
- 15265u, 15371u, 15408u, 15416u,
- 15357u, 15439u, 15413u, 15451u,
- 15306u, 15361u, 15372u, 15380u,
- 15295u, 15421u, 15363u, 15308u,
- 15374u, 15267u, 15375u, 15432u,
- 15300u, 15401u, 15315u, 15392u,
- 15380u, 15346u, 15442u, 15401u,
- 15414u, 15363u, 15278u, 15371u,
- 15415u, 15365u, 15425u, 15309u,
- 15400u, 15365u, 15422u, 15419u,
- 15295u, 15360u, 15334u, 15296u,
- 15262u, 15410u, 15424u, 15361u,
- 15369u, 15305u, 15432u, 15416u,
- 15431u, 15371u, 15284u, 15308u,
- 15382u, 15314u, 15358u, 15337u,
- 15316u, 15373u, 15400u, 15491u,
- 15359u, 15341u, 15311u, 15340u
-};
-
-const uint8 LangIdNNParams::kEmbeddingsWeights1[] = {
- 96u, 188u, 120u, 112u,
- 147u, 89u, 255u, 35u,
- 75u, 178u, 79u, 119u,
- 215u, 162u, 136u, 12u,
- 190u, 255u, 58u, 118u,
- 68u, 42u, 237u, 107u,
- 51u, 141u, 144u, 132u,
- 238u, 144u, 144u, 25u,
- 117u, 255u, 131u, 107u,
- 136u, 184u, 60u, 198u,
- 122u, 24u, 166u, 71u,
- 183u, 96u, 177u, 97u,
- 93u, 157u, 38u, 162u,
- 1u, 45u, 225u, 64u,
- 64u, 187u, 187u, 171u,
- 146u, 21u, 143u, 161u,
- 218u, 74u, 33u, 174u,
- 112u, 99u, 176u, 113u,
- 140u, 105u, 1u, 64u,
- 81u, 198u, 16u, 90u,
- 85u, 145u, 126u, 56u,
- 154u, 109u, 255u, 114u,
- 191u, 122u, 48u, 150u,
- 141u, 142u, 206u, 126u,
- 234u, 164u, 224u, 20u,
- 220u, 151u, 192u, 166u,
- 111u, 1u, 72u, 96u,
- 211u, 255u, 167u, 90u,
- 157u, 92u, 55u, 255u,
- 43u, 70u, 159u, 38u,
- 179u, 210u, 164u, 138u,
- 165u, 97u, 116u, 7u,
- 157u, 146u, 176u, 0u,
- 81u, 155u, 110u, 227u,
- 152u, 185u, 163u, 172u,
- 142u, 133u, 127u, 219u,
- 91u, 176u, 123u, 148u,
- 255u, 85u, 159u, 164u,
- 91u, 49u, 67u, 115u,
- 225u, 129u, 118u, 47u,
- 76u, 143u, 73u, 191u,
- 1u, 129u, 57u, 162u,
- 44u, 94u, 183u, 46u,
- 97u, 118u, 151u, 211u,
- 169u, 93u, 133u, 93u,
- 108u, 89u, 177u, 100u,
- 74u, 137u, 120u, 113u,
- 229u, 169u, 255u, 70u,
- 108u, 153u, 255u, 73u,
- 84u, 149u, 195u, 123u,
- 59u, 127u, 115u, 158u,
- 201u, 79u, 173u, 152u,
- 164u, 80u, 182u, 60u,
- 137u, 124u, 104u, 216u,
- 148u, 122u, 99u, 57u,
- 20u, 44u, 152u, 255u,
- 181u, 130u, 52u, 191u,
- 158u, 0u, 211u, 104u,
- 6u, 209u, 14u, 102u,
- 162u, 144u, 169u, 138u,
- 142u, 255u, 171u, 143u,
- 44u, 123u, 77u, 147u,
- 88u, 83u, 110u, 104u,
- 51u, 96u, 171u, 228u,
- 124u, 28u, 147u, 134u,
- 164u, 146u, 235u, 137u,
- 1u, 56u, 1u, 96u,
- 195u, 218u, 215u, 197u,
- 36u, 105u, 85u, 67u,
- 86u, 191u, 35u, 221u,
- 164u, 188u, 246u, 91u,
- 60u, 1u, 184u, 211u,
- 174u, 205u, 117u, 46u,
- 122u, 176u, 94u, 255u,
- 68u, 65u, 204u, 128u,
- 215u, 198u, 57u, 73u,
- 194u, 173u, 234u, 142u,
- 213u, 127u, 255u, 201u,
- 127u, 168u, 1u, 79u,
- 95u, 57u, 215u, 182u,
- 210u, 255u, 251u, 141u,
- 91u, 151u, 140u, 239u,
- 92u, 196u, 200u, 205u,
- 9u, 175u, 149u, 125u,
- 199u, 118u, 161u, 1u,
- 35u, 217u, 96u, 124u,
- 72u, 119u, 162u, 146u,
- 135u, 171u, 195u, 12u,
- 199u, 83u, 103u, 161u,
- 126u, 151u, 139u, 140u,
- 81u, 121u, 7u, 0u,
- 178u, 160u, 163u, 113u,
- 152u, 71u, 255u, 73u,
- 240u, 124u, 183u, 32u,
- 169u, 172u, 94u, 229u,
- 210u, 173u, 220u, 145u,
- 255u, 149u, 178u, 75u,
- 189u, 85u, 128u, 84u,
- 135u, 73u, 82u, 151u,
- 49u, 174u, 84u, 105u,
- 167u, 96u, 155u, 156u,
- 179u, 70u, 120u, 123u,
- 83u, 164u, 137u, 145u,
- 255u, 125u, 81u, 108u,
- 74u, 188u, 124u, 184u,
- 105u, 91u, 141u, 87u,
- 1u, 110u, 103u, 51u,
- 171u, 98u, 149u, 71u,
- 1u, 13u, 191u, 55u,
- 90u, 55u, 81u, 72u,
- 128u, 106u, 63u, 52u,
- 12u, 75u, 165u, 220u,
- 129u, 97u, 156u, 49u,
- 162u, 113u, 95u, 183u,
- 140u, 255u, 202u, 67u,
- 41u, 106u, 51u, 196u,
- 117u, 101u, 125u, 165u,
- 82u, 74u, 188u, 0u,
- 47u, 212u, 75u, 233u,
- 162u, 92u, 193u, 67u,
- 169u, 128u, 159u, 91u,
- 108u, 222u, 1u, 192u,
- 194u, 6u, 208u, 118u,
- 140u, 223u, 171u, 48u,
- 100u, 91u, 228u, 109u,
- 181u, 208u, 170u, 146u,
- 127u, 146u, 92u, 98u,
- 142u, 110u, 136u, 255u,
- 195u, 150u, 115u, 114u,
- 1u, 146u, 80u, 56u,
- 202u, 47u, 197u, 66u,
- 104u, 85u, 136u, 123u,
- 70u, 86u, 201u, 203u,
- 98u, 20u, 21u, 152u,
- 14u, 18u, 195u, 132u,
- 56u, 46u, 255u, 98u,
- 131u, 115u, 64u, 210u,
- 156u, 151u, 157u, 109u,
- 136u, 1u, 140u, 134u,
- 127u, 211u, 130u, 78u,
- 116u, 207u, 248u, 129u,
- 1u, 63u, 103u, 71u,
- 115u, 24u, 108u, 109u,
- 171u, 122u, 136u, 101u,
- 168u, 78u, 1u, 97u,
- 120u, 122u, 164u, 221u,
- 134u, 206u, 129u, 137u,
- 166u, 123u, 123u, 187u,
- 105u, 103u, 59u, 136u,
- 124u, 64u, 160u, 127u,
- 99u, 80u, 133u, 73u,
- 112u, 255u, 161u, 204u,
- 226u, 118u, 138u, 170u,
- 112u, 150u, 167u, 135u,
- 104u, 114u, 123u, 169u,
- 95u, 128u, 0u, 170u,
- 75u, 144u, 146u, 225u,
- 81u, 190u, 137u, 116u,
- 46u, 0u, 91u, 133u,
- 158u, 97u, 174u, 129u,
- 96u, 1u, 116u, 135u,
- 143u, 137u, 188u, 118u,
- 35u, 143u, 88u, 40u,
- 98u, 107u, 78u, 199u,
- 146u, 154u, 159u, 152u,
- 139u, 7u, 1u, 179u,
- 78u, 210u, 79u, 135u,
- 118u, 57u, 155u, 201u,
- 24u, 6u, 20u, 161u,
- 149u, 138u, 147u, 167u,
- 166u, 185u, 111u, 182u,
- 63u, 89u, 161u, 255u,
- 156u, 103u, 165u, 195u,
- 100u, 83u, 30u, 9u,
- 125u, 70u, 255u, 161u,
- 110u, 137u, 151u, 164u,
- 147u, 129u, 97u, 181u,
- 68u, 211u, 1u, 146u,
- 139u, 78u, 122u, 120u,
- 118u, 150u, 104u, 132u,
- 156u, 170u, 1u, 151u,
- 39u, 94u, 150u, 106u,
- 171u, 2u, 208u, 82u,
- 124u, 91u, 203u, 144u,
- 60u, 255u, 254u, 3u,
- 178u, 160u, 207u, 206u,
- 15u, 224u, 110u, 113u,
- 230u, 117u, 158u, 77u,
- 87u, 165u, 85u, 45u,
- 187u, 77u, 154u, 76u,
- 141u, 129u, 1u, 113u,
- 67u, 212u, 124u, 56u,
- 101u, 155u, 1u, 184u,
- 114u, 219u, 81u, 179u,
- 154u, 108u, 133u, 181u,
- 98u, 122u, 115u, 122u,
- 57u, 66u, 131u, 166u,
- 62u, 160u, 168u, 1u,
- 73u, 150u, 63u, 167u,
- 41u, 171u, 91u, 237u,
- 246u, 128u, 136u, 152u,
- 109u, 108u, 106u, 255u,
- 146u, 80u, 135u, 136u,
- 133u, 110u, 101u, 65u,
- 142u, 143u, 189u, 106u,
- 160u, 215u, 62u, 92u,
- 0u, 153u, 85u, 105u,
- 181u, 144u, 221u, 123u,
- 109u, 59u, 71u, 131u,
- 186u, 163u, 33u, 132u,
- 86u, 0u, 94u, 127u,
- 92u, 51u, 77u, 149u,
- 184u, 120u, 147u, 60u,
- 101u, 148u, 151u, 116u,
- 86u, 118u, 30u, 58u,
- 116u, 114u, 125u, 255u,
- 84u, 214u, 140u, 229u,
- 22u, 172u, 76u, 75u,
- 146u, 29u, 222u, 120u,
- 247u, 255u, 126u, 85u,
- 138u, 85u, 176u, 234u,
- 255u, 190u, 157u, 16u,
- 79u, 196u, 21u, 190u,
- 179u, 169u, 123u, 86u,
- 169u, 68u, 218u, 52u,
- 213u, 146u, 1u, 205u,
- 37u, 238u, 49u, 192u,
- 137u, 181u, 101u, 77u,
- 160u, 20u, 215u, 137u,
- 120u, 133u, 0u, 143u,
- 122u, 116u, 76u, 138u,
- 38u, 58u, 69u, 196u,
- 114u, 211u, 197u, 80u,
- 92u, 255u, 106u, 84u,
- 177u, 136u, 131u, 228u,
- 217u, 187u, 159u, 131u,
- 131u, 124u, 132u, 247u,
- 1u, 57u, 138u, 145u,
- 57u, 166u, 226u, 125u,
- 76u, 218u, 144u, 129u,
- 21u, 193u, 48u, 255u,
- 8u, 139u, 172u, 100u,
- 247u, 149u, 191u, 40u,
- 212u, 70u, 220u, 148u,
- 179u, 28u, 184u, 128u,
- 100u, 190u, 90u, 121u,
- 189u, 105u, 135u, 107u,
- 178u, 255u, 106u, 142u,
- 203u, 1u, 151u, 60u,
- 222u, 71u, 105u, 237u,
- 109u, 143u, 147u, 106u,
- 90u, 116u, 124u, 111u,
- 137u, 36u, 167u, 110u,
- 116u, 18u, 71u, 26u,
- 240u, 63u, 169u, 194u,
- 69u, 145u, 1u, 91u,
- 99u, 176u, 168u, 102u,
- 187u, 159u, 177u, 62u,
- 255u, 153u, 140u, 24u,
- 106u, 136u, 131u, 81u,
- 71u, 60u, 67u, 127u,
- 255u, 110u, 146u, 143u,
- 50u, 218u, 110u, 149u,
- 124u, 63u, 145u, 202u,
- 141u, 86u, 169u, 78u,
- 144u, 90u, 145u, 178u,
- 46u, 182u, 114u, 255u,
- 165u, 76u, 111u, 184u,
- 65u, 236u, 58u, 141u,
- 87u, 34u, 225u, 62u,
- 235u, 99u, 211u, 120u,
- 133u, 1u, 150u, 25u,
- 240u, 148u, 233u, 1u,
- 171u, 41u, 74u, 119u,
- 184u, 136u, 223u, 112u,
- 188u, 194u, 145u, 249u,
- 163u, 15u, 55u, 180u,
- 93u, 81u, 6u, 168u,
- 27u, 227u, 88u, 31u,
- 1u, 173u, 120u, 188u,
- 152u, 88u, 73u, 95u,
- 20u, 116u, 132u, 147u,
- 82u, 114u, 183u, 46u,
- 171u, 1u, 81u, 137u,
- 151u, 132u, 60u, 100u,
- 134u, 95u, 95u, 255u,
- 113u, 147u, 87u, 72u,
- 123u, 173u, 117u, 122u,
- 192u, 105u, 187u, 126u,
- 160u, 122u, 154u, 196u,
- 188u, 131u, 148u, 74u,
- 166u, 129u, 147u, 1u,
- 32u, 148u, 161u, 154u,
- 28u, 195u, 106u, 160u,
- 255u, 46u, 219u, 207u,
- 67u, 162u, 94u, 81u,
- 164u, 170u, 120u, 255u,
- 153u, 148u, 199u, 91u,
- 168u, 43u, 209u, 195u,
- 84u, 206u, 38u, 136u,
- 76u, 97u, 114u, 209u,
- 167u, 192u, 210u, 71u,
- 138u, 39u, 134u, 63u,
- 181u, 28u, 0u, 167u,
- 130u, 194u, 63u, 130u,
- 192u, 115u, 1u, 104u,
- 106u, 113u, 161u, 96u,
- 16u, 60u, 129u, 3u,
- 71u, 94u, 212u, 113u,
- 143u, 194u, 223u, 73u,
- 125u, 117u, 138u, 139u,
- 194u, 0u, 24u, 149u,
- 136u, 95u, 101u, 55u,
- 64u, 155u, 88u, 90u,
- 90u, 52u, 192u, 153u,
- 64u, 255u, 72u, 50u,
- 138u, 101u, 181u, 234u,
- 120u, 160u, 115u, 126u,
- 0u, 132u, 93u, 134u,
- 204u, 228u, 100u, 198u,
- 49u, 224u, 134u, 224u,
- 183u, 208u, 39u, 76u,
- 199u, 184u, 75u, 71u,
- 1u, 136u, 124u, 136u,
- 169u, 79u, 114u, 178u,
- 137u, 100u, 106u, 236u,
- 69u, 136u, 72u, 224u,
- 128u, 64u, 1u, 173u,
- 185u, 187u, 159u, 165u,
- 254u, 147u, 58u, 77u,
- 151u, 17u, 1u, 28u,
- 143u, 128u, 156u, 57u,
- 150u, 111u, 148u, 144u,
- 255u, 66u, 169u, 154u,
- 174u, 249u, 113u, 159u,
- 213u, 81u, 128u, 103u,
- 143u, 190u, 22u, 160u,
- 83u, 171u, 78u, 255u,
- 197u, 74u, 166u, 120u,
- 67u, 77u, 139u, 100u,
- 137u, 144u, 163u, 77u,
- 201u, 136u, 99u, 240u,
- 177u, 124u, 144u, 1u,
- 197u, 55u, 181u, 135u,
- 127u, 132u, 107u, 151u,
- 154u, 117u, 147u, 157u,
- 73u, 166u, 109u, 112u,
- 244u, 146u, 129u, 0u,
- 135u, 45u, 45u, 255u,
- 235u, 165u, 135u, 104u,
- 50u, 16u, 4u, 11u,
- 205u, 158u, 15u, 51u,
- 163u, 104u, 197u, 43u,
- 163u, 33u, 231u, 127u,
- 77u, 255u, 138u, 143u,
- 152u, 162u, 127u, 128u,
- 183u, 35u, 108u, 1u,
- 111u, 168u, 51u, 99u,
- 64u, 102u, 142u, 147u,
- 168u, 202u, 196u, 186u,
- 192u, 134u, 4u, 61u,
- 134u, 41u, 197u, 92u,
- 136u, 54u, 236u, 205u,
- 149u, 255u, 117u, 38u,
- 121u, 105u, 165u, 118u,
- 103u, 81u, 115u, 141u,
- 176u, 255u, 178u, 205u,
- 144u, 102u, 115u, 201u,
- 255u, 65u, 206u, 57u,
- 155u, 105u, 128u, 93u,
- 140u, 110u, 97u, 18u,
- 152u, 166u, 134u, 77u,
- 227u, 171u, 34u, 61u,
- 150u, 76u, 81u, 178u,
- 83u, 142u, 173u, 166u,
- 203u, 128u, 80u, 1u,
- 73u, 136u, 134u, 140u,
- 164u, 164u, 128u, 94u,
- 140u, 1u, 115u, 169u,
- 166u, 116u, 187u, 122u,
- 156u, 103u, 173u, 154u,
- 132u, 227u, 43u, 87u,
- 44u, 122u, 15u, 54u,
- 143u, 1u, 146u, 202u,
- 79u, 87u, 0u, 246u,
- 101u, 88u, 72u, 124u,
- 188u, 92u, 48u, 143u,
- 215u, 107u, 108u, 122u,
- 172u, 118u, 255u, 73u,
- 109u, 100u, 208u, 54u,
- 53u, 189u, 200u, 193u,
- 170u, 145u, 193u, 170u,
- 195u, 236u, 186u, 77u,
- 109u, 104u, 48u, 7u,
- 88u, 255u, 83u, 65u,
- 129u, 45u, 48u, 199u,
- 169u, 41u, 255u, 161u,
- 110u, 88u, 154u, 91u,
- 125u, 92u, 178u, 68u,
- 39u, 117u, 145u, 189u,
- 108u, 84u, 218u, 110u,
- 133u, 125u, 242u, 1u,
- 101u, 192u, 202u, 176u,
- 217u, 153u, 173u, 87u,
- 229u, 59u, 255u, 133u,
- 109u, 113u, 240u, 104u,
- 130u, 156u, 113u, 101u,
- 115u, 186u, 111u, 83u,
- 130u, 99u, 91u, 202u,
- 117u, 91u, 129u, 110u,
- 255u, 79u, 132u, 89u,
- 128u, 62u, 129u, 85u,
- 43u, 148u, 168u, 1u,
- 68u, 126u, 35u, 200u,
- 104u, 115u, 243u, 108u,
- 97u, 129u, 123u, 77u,
- 206u, 88u, 122u, 168u,
- 181u, 93u, 0u, 78u,
- 115u, 88u, 129u, 137u,
- 125u, 233u, 126u, 146u,
- 63u, 162u, 101u, 149u,
- 228u, 40u, 111u, 103u,
- 161u, 239u, 223u, 98u,
- 119u, 72u, 165u, 0u,
- 47u, 183u, 125u, 140u,
- 121u, 152u, 0u, 140u,
- 83u, 83u, 186u, 144u,
- 66u, 109u, 172u, 223u,
- 255u, 153u, 92u, 146u,
- 226u, 118u, 172u, 153u,
- 133u, 180u, 117u, 189u,
- 208u, 126u, 11u, 44u,
- 196u, 167u, 185u, 132u,
- 198u, 136u, 94u, 101u,
- 156u, 167u, 82u, 139u,
- 194u, 180u, 1u, 71u,
- 56u, 238u, 122u, 140u,
- 68u, 255u, 141u, 192u,
- 102u, 196u, 171u, 69u,
- 114u, 79u, 132u, 214u,
- 189u, 116u, 184u, 155u,
- 141u, 224u, 108u, 52u,
- 111u, 40u, 143u, 242u,
- 255u, 92u, 57u, 69u,
- 170u, 244u, 142u, 0u,
- 74u, 55u, 164u, 107u,
- 50u, 177u, 253u, 140u,
- 118u, 132u, 78u, 80u,
- 106u, 159u, 1u, 232u,
- 111u, 139u, 124u, 206u,
- 194u, 131u, 211u, 212u,
- 146u, 192u, 35u, 40u,
- 55u, 111u, 184u, 79u,
- 145u, 164u, 185u, 138u,
- 255u, 42u, 79u, 113u,
- 70u, 92u, 12u, 155u,
- 115u, 128u, 196u, 255u,
- 169u, 90u, 134u, 67u,
- 132u, 6u, 64u, 110u,
- 139u, 127u, 155u, 106u,
- 128u, 135u, 132u, 138u,
- 168u, 95u, 110u, 195u,
- 56u, 195u, 117u, 225u,
- 160u, 14u, 255u, 180u,
- 255u, 177u, 154u, 198u,
- 197u, 217u, 60u, 54u,
- 177u, 139u, 32u, 11u,
- 156u, 34u, 97u, 146u,
- 97u, 77u, 200u, 179u,
- 177u, 171u, 14u, 233u,
- 152u, 1u, 88u, 67u,
- 28u, 228u, 100u, 67u,
- 200u, 49u, 255u, 217u,
- 136u, 130u, 144u, 184u,
- 246u, 91u, 53u, 153u,
- 216u, 100u, 27u, 110u,
- 108u, 110u, 194u, 175u,
- 97u, 100u, 174u, 148u,
- 138u, 188u, 92u, 181u,
- 181u, 255u, 149u, 84u,
- 146u, 93u, 152u, 74u,
- 75u, 141u, 102u, 155u,
- 164u, 168u, 255u, 147u,
- 54u, 97u, 128u, 69u,
- 103u, 94u, 122u, 122u,
- 111u, 138u, 26u, 100u,
- 212u, 82u, 255u, 172u,
- 81u, 150u, 151u, 124u,
- 137u, 255u, 112u, 204u,
- 26u, 137u, 91u, 128u,
- 160u, 91u, 170u, 134u,
- 96u, 85u, 40u, 145u,
- 146u, 255u, 100u, 13u,
- 175u, 78u, 239u, 167u,
- 163u, 67u, 174u, 206u,
- 134u, 239u, 171u, 114u,
- 138u, 132u, 106u, 180u,
- 211u, 190u, 169u, 143u,
- 18u, 70u, 1u, 137u,
- 242u, 100u, 195u, 141u,
- 200u, 157u, 35u, 116u,
- 110u, 152u, 169u, 196u,
- 98u, 1u, 99u, 33u,
- 202u, 220u, 109u, 14u,
- 178u, 154u, 211u, 97u,
- 255u, 137u, 6u, 174u,
- 179u, 44u, 192u, 157u,
- 228u, 205u, 132u, 33u,
- 102u, 189u, 31u, 85u,
- 255u, 81u, 5u, 98u,
- 101u, 143u, 249u, 100u,
- 141u, 27u, 226u, 117u,
- 174u, 50u, 162u, 183u,
- 108u, 126u, 99u, 1u,
- 48u, 149u, 17u, 157u,
- 74u, 229u, 148u, 218u,
- 130u, 87u, 99u, 139u,
- 108u, 182u, 82u, 215u,
- 170u, 191u, 161u, 205u,
- 240u, 255u, 145u, 97u,
- 217u, 40u, 158u, 255u,
- 54u, 77u, 199u, 163u,
- 220u, 171u, 79u, 102u,
- 97u, 137u, 28u, 173u,
- 145u, 189u, 194u, 53u,
- 159u, 160u, 118u, 81u,
- 70u, 118u, 149u, 255u,
- 178u, 166u, 25u, 254u,
- 140u, 94u, 127u, 91u,
- 148u, 148u, 35u, 55u,
- 206u, 157u, 29u, 59u,
- 239u, 132u, 255u, 223u,
- 1u, 54u, 113u, 39u,
- 124u, 134u, 73u, 54u,
- 223u, 246u, 230u, 177u,
- 146u, 44u, 185u, 195u,
- 156u, 126u, 142u, 211u,
- 84u, 141u, 80u, 185u,
- 233u, 94u, 123u, 240u,
- 119u, 47u, 0u, 80u,
- 192u, 131u, 164u, 147u,
- 255u, 167u, 73u, 63u,
- 118u, 131u, 63u, 44u,
- 131u, 246u, 131u, 83u,
- 211u, 130u, 125u, 100u,
- 1u, 160u, 155u, 143u,
- 120u, 148u, 154u, 106u,
- 116u, 65u, 124u, 155u,
- 187u, 200u, 171u, 1u,
- 150u, 152u, 150u, 196u,
- 171u, 106u, 107u, 142u,
- 92u, 125u, 147u, 129u,
- 206u, 208u, 122u, 192u,
- 78u, 134u, 255u, 200u,
- 56u, 99u, 115u, 230u,
- 173u, 186u, 193u, 127u,
- 100u, 120u, 74u, 149u,
- 1u, 58u, 180u, 13u,
- 94u, 236u, 234u, 220u,
- 255u, 129u, 126u, 127u,
- 201u, 113u, 166u, 142u,
- 108u, 211u, 255u, 189u,
- 175u, 165u, 156u, 139u,
- 215u, 48u, 171u, 129u,
- 148u, 92u, 124u, 118u,
- 75u, 125u, 224u, 228u,
- 165u, 0u, 125u, 187u,
- 74u, 132u, 108u, 62u,
- 109u, 85u, 146u, 72u,
- 210u, 134u, 255u, 155u,
- 80u, 87u, 83u, 51u,
- 236u, 148u, 111u, 101u,
- 64u, 67u, 104u, 71u,
- 92u, 229u, 119u, 255u,
- 194u, 93u, 99u, 172u,
- 52u, 105u, 68u, 185u,
- 46u, 106u, 117u, 115u,
- 115u, 128u, 66u, 71u,
- 122u, 255u, 151u, 140u,
- 119u, 139u, 168u, 150u,
- 80u, 115u, 97u, 170u,
- 60u, 182u, 138u, 228u,
- 170u, 159u, 255u, 141u,
- 177u, 120u, 165u, 151u,
- 163u, 194u, 140u, 148u,
- 63u, 107u, 178u, 183u,
- 92u, 143u, 255u, 151u,
- 96u, 82u, 119u, 80u,
- 129u, 134u, 0u, 96u,
- 57u, 107u, 202u, 94u,
- 131u, 80u, 170u, 157u,
- 172u, 206u, 88u, 37u,
- 50u, 161u, 227u, 11u,
- 233u, 135u, 229u, 70u,
- 82u, 223u, 83u, 0u,
- 213u, 185u, 121u, 4u,
- 136u, 65u, 127u, 152u,
- 216u, 39u, 123u, 1u,
- 121u, 97u, 31u, 67u,
- 183u, 145u, 99u, 123u,
- 157u, 97u, 106u, 23u,
- 69u, 52u, 242u, 255u,
- 206u, 188u, 184u, 112u,
- 179u, 15u, 193u, 54u,
- 118u, 98u, 112u, 94u,
- 181u, 118u, 80u, 199u,
- 153u, 26u, 69u, 1u,
- 25u, 50u, 154u, 166u,
- 116u, 207u, 166u, 81u,
- 30u, 178u, 128u, 160u,
- 94u, 213u, 110u, 121u,
- 122u, 104u, 108u, 255u,
- 92u, 203u, 255u, 125u,
- 113u, 136u, 96u, 183u,
- 18u, 201u, 53u, 133u,
- 120u, 135u, 91u, 139u,
- 116u, 166u, 212u, 165u,
- 28u, 76u, 75u, 12u,
- 11u, 67u, 255u, 194u,
- 159u, 68u, 130u, 108u,
- 121u, 241u, 111u, 58u,
- 79u, 172u, 255u, 151u,
- 224u, 194u, 147u, 129u,
- 148u, 172u, 12u, 93u,
- 130u, 197u, 3u, 92u,
- 72u, 135u, 13u, 209u,
- 101u, 193u, 145u, 255u,
- 122u, 124u, 79u, 133u,
- 189u, 195u, 127u, 143u,
- 147u, 121u, 89u, 87u,
- 199u, 1u, 184u, 241u,
- 71u, 190u, 143u, 88u,
- 55u, 200u, 84u, 136u,
- 111u, 255u, 37u, 151u,
- 111u, 40u, 181u, 167u,
- 125u, 58u, 135u, 154u,
- 101u, 187u, 43u, 39u,
- 8u, 168u, 165u, 134u,
- 140u, 255u, 213u, 92u,
- 147u, 168u, 164u, 88u,
- 199u, 63u, 132u, 187u,
- 121u, 56u, 227u, 163u,
- 57u, 29u, 54u, 255u,
- 95u, 82u, 213u, 161u,
- 177u, 112u, 110u, 146u,
- 94u, 105u, 187u, 54u,
- 159u, 208u, 229u, 107u,
- 165u, 236u, 205u, 1u,
- 70u, 171u, 165u, 81u,
- 223u, 101u, 0u, 191u,
- 127u, 109u, 139u, 122u,
- 126u, 156u, 58u, 141u,
- 226u, 195u, 96u, 255u,
- 31u, 145u, 29u, 216u,
- 20u, 8u, 133u, 50u,
- 196u, 66u, 20u, 107u,
- 202u, 214u, 172u, 169u,
- 162u, 31u, 69u, 19u,
- 102u, 93u, 105u, 0u,
- 179u, 131u, 158u, 28u,
- 121u, 108u, 255u, 84u,
- 199u, 249u, 97u, 117u,
- 45u, 20u, 44u, 71u,
- 189u, 219u, 122u, 232u,
- 189u, 153u, 19u, 216u,
- 123u, 129u, 106u, 1u,
- 223u, 177u, 137u, 214u,
- 133u, 195u, 96u, 37u,
- 84u, 61u, 176u, 186u,
- 128u, 168u, 182u, 118u,
- 55u, 94u, 1u, 131u,
- 44u, 144u, 90u, 163u,
- 134u, 64u, 64u, 1u,
- 143u, 104u, 250u, 85u,
- 94u, 192u, 82u, 65u,
- 182u, 72u, 236u, 173u,
- 79u, 149u, 86u, 129u,
- 174u, 118u, 80u, 255u,
- 126u, 101u, 131u, 106u,
- 177u, 84u, 106u, 70u,
- 86u, 126u, 55u, 166u,
- 52u, 21u, 231u, 128u,
- 183u, 113u, 158u, 255u,
- 175u, 114u, 232u, 45u,
- 119u, 112u, 160u, 189u,
- 144u, 157u, 151u, 155u,
- 113u, 1u, 85u, 144u,
- 119u, 183u, 153u, 105u,
- 115u, 78u, 85u, 146u,
- 33u, 68u, 88u, 107u,
- 36u, 241u, 126u, 1u,
- 135u, 55u, 158u, 107u,
- 119u, 77u, 188u, 57u,
- 255u, 104u, 145u, 124u,
- 98u, 111u, 95u, 83u,
- 99u, 88u, 120u, 155u,
- 181u, 134u, 169u, 221u,
- 199u, 1u, 20u, 63u,
- 75u, 55u, 164u, 126u,
- 107u, 99u, 153u, 85u,
- 177u, 82u, 171u, 140u,
- 153u, 0u, 106u, 39u,
- 87u, 83u, 100u, 72u,
- 108u, 173u, 104u, 101u,
- 244u, 122u, 218u, 109u,
- 97u, 126u, 0u, 158u,
- 168u, 69u, 139u, 148u,
- 65u, 176u, 67u, 136u,
- 7u, 46u, 96u, 240u,
- 87u, 74u, 162u, 14u,
- 209u, 97u, 219u, 219u,
- 107u, 88u, 1u, 126u,
- 133u, 124u, 116u, 114u,
- 38u, 140u, 83u, 113u,
- 118u, 106u, 143u, 86u,
- 89u, 202u, 53u, 255u,
- 95u, 183u, 1u, 254u,
- 16u, 135u, 118u, 113u,
- 233u, 189u, 210u, 160u,
- 128u, 60u, 92u, 37u,
- 153u, 255u, 80u, 125u,
- 59u, 165u, 61u, 81u,
- 58u, 141u, 199u, 222u,
- 174u, 117u, 50u, 73u,
- 134u, 239u, 104u, 120u,
- 237u, 0u, 144u, 147u,
- 139u, 195u, 137u, 104u,
- 211u, 196u, 122u, 118u,
- 212u, 255u, 183u, 121u,
- 84u, 77u, 97u, 190u,
- 109u, 176u, 200u, 81u,
- 230u, 51u, 88u, 206u,
- 108u, 96u, 138u, 139u,
- 129u, 89u, 92u, 115u,
- 255u, 121u, 106u, 159u,
- 148u, 110u, 117u, 162u,
- 190u, 153u, 166u, 69u,
- 12u, 181u, 84u, 114u,
- 106u, 135u, 255u, 91u,
- 171u, 20u, 122u, 170u,
- 108u, 116u, 44u, 193u,
- 116u, 206u, 145u, 153u,
- 16u, 130u, 112u, 141u,
- 255u, 138u, 98u, 188u,
- 180u, 180u, 27u, 0u,
- 147u, 113u, 74u, 206u,
- 158u, 175u, 208u, 20u,
- 147u, 111u, 123u, 119u,
- 44u, 124u, 141u, 1u,
- 38u, 186u, 126u, 168u,
- 93u, 21u, 33u, 98u,
- 115u, 97u, 3u, 104u,
- 38u, 32u, 120u, 1u,
- 211u, 43u, 111u, 116u,
- 72u, 1u, 187u, 142u,
- 33u, 145u, 87u, 141u,
- 150u, 81u, 134u, 147u,
- 148u, 101u, 96u, 170u,
- 62u, 72u, 135u, 121u,
- 200u, 172u, 18u, 1u,
- 171u, 137u, 133u, 99u,
- 144u, 231u, 149u, 255u,
- 119u, 122u, 176u, 186u,
- 151u, 177u, 176u, 131u,
- 87u, 104u, 118u, 206u,
- 62u, 56u, 16u, 138u,
- 41u, 42u, 1u, 150u,
- 91u, 62u, 91u, 217u,
- 101u, 65u, 83u, 255u,
- 158u, 27u, 85u, 132u,
- 121u, 49u, 214u, 237u,
- 130u, 63u, 58u, 166u,
- 112u, 134u, 158u, 178u,
- 1u, 117u, 62u, 248u,
- 199u, 25u, 182u, 5u,
- 87u, 106u, 101u, 63u,
- 188u, 68u, 148u, 157u,
- 95u, 110u, 151u, 110u,
- 190u, 104u, 151u, 81u,
- 1u, 149u, 76u, 88u,
- 151u, 211u, 134u, 216u,
- 70u, 145u, 102u, 60u,
- 166u, 153u, 146u, 71u,
- 116u, 78u, 1u, 49u,
- 117u, 80u, 30u, 85u,
- 158u, 57u, 100u, 191u,
- 99u, 251u, 130u, 169u,
- 229u, 75u, 1u, 127u,
- 124u, 52u, 108u, 142u,
- 132u, 149u, 135u, 48u,
- 236u, 194u, 208u, 255u,
- 181u, 153u, 80u, 108u,
- 122u, 176u, 121u, 201u,
- 104u, 114u, 178u, 154u,
- 100u, 110u, 84u, 255u,
- 71u, 160u, 33u, 219u,
- 177u, 124u, 56u, 234u,
- 88u, 247u, 255u, 146u,
- 128u, 195u, 154u, 212u,
- 135u, 154u, 119u, 251u,
- 149u, 167u, 151u, 143u,
- 95u, 108u, 168u, 129u,
- 192u, 0u, 190u, 116u,
- 94u, 183u, 176u, 115u,
- 121u, 88u, 109u, 167u,
- 228u, 194u, 125u, 114u,
- 201u, 57u, 153u, 164u,
- 128u, 160u, 91u, 1u,
- 110u, 37u, 158u, 92u,
- 102u, 97u, 187u, 110u,
- 126u, 255u, 117u, 144u,
- 56u, 85u, 130u, 129u,
- 101u, 239u, 231u, 9u,
- 170u, 64u, 237u, 56u,
- 1u, 25u, 187u, 195u,
- 71u, 178u, 163u, 37u,
- 198u, 252u, 205u, 45u,
- 51u, 30u, 125u, 80u,
- 215u, 141u, 255u, 117u,
- 205u, 228u, 192u, 128u,
- 88u, 158u, 14u, 244u,
- 27u, 210u, 115u, 125u,
- 113u, 1u, 209u, 123u,
- 123u, 141u, 136u, 178u,
- 183u, 79u, 81u, 191u,
- 138u, 18u, 203u, 31u,
- 210u, 142u, 169u, 171u,
- 94u, 0u, 126u, 126u,
- 135u, 255u, 137u, 97u,
- 158u, 214u, 13u, 18u,
- 60u, 134u, 53u, 170u,
- 185u, 26u, 1u, 159u,
- 145u, 147u, 152u, 172u,
- 73u, 143u, 186u, 75u,
- 107u, 86u, 98u, 129u,
- 54u, 255u, 205u, 170u,
- 187u, 33u, 83u, 177u,
- 103u, 74u, 130u, 255u,
- 204u, 141u, 213u, 217u,
- 51u, 33u, 55u, 150u,
- 185u, 86u, 176u, 130u,
- 118u, 216u, 128u, 1u,
- 217u, 118u, 111u, 85u,
- 86u, 79u, 166u, 72u,
- 72u, 200u, 108u, 180u,
- 73u, 122u, 101u, 67u,
- 105u, 177u, 228u, 147u,
- 255u, 82u, 149u, 110u,
- 149u, 119u, 120u, 196u,
- 142u, 58u, 168u, 150u,
- 27u, 212u, 92u, 67u,
- 130u, 0u, 90u, 59u,
- 103u, 97u, 199u, 199u,
- 138u, 114u, 168u, 176u,
- 44u, 183u, 112u, 235u,
- 53u, 50u, 139u, 255u,
- 163u, 190u, 172u, 63u,
- 255u, 255u, 130u, 230u,
- 142u, 223u, 136u, 219u,
- 216u, 209u, 118u, 227u,
- 128u, 113u, 127u, 1u,
- 147u, 62u, 195u, 83u,
- 108u, 126u, 171u, 220u,
- 60u, 78u, 219u, 139u,
- 41u, 243u, 65u, 18u,
- 223u, 29u, 200u, 249u,
- 104u, 130u, 1u, 81u,
- 123u, 197u, 226u, 26u,
- 140u, 102u, 1u, 90u,
- 132u, 112u, 88u, 154u,
- 192u, 112u, 170u, 227u,
- 73u, 146u, 136u, 166u,
- 172u, 209u, 126u, 111u,
- 108u, 118u, 1u, 113u,
- 59u, 51u, 209u, 114u,
- 115u, 173u, 51u, 31u,
- 1u, 110u, 154u, 136u,
- 147u, 143u, 93u, 86u,
- 86u, 129u, 147u, 95u,
- 88u, 88u, 118u, 180u,
- 175u, 139u, 68u, 196u,
- 63u, 160u, 86u, 255u,
- 150u, 221u, 46u, 41u,
- 63u, 144u, 36u, 101u,
- 156u, 127u, 110u, 236u,
- 150u, 167u, 43u, 148u,
- 93u, 1u, 178u, 183u,
- 98u, 154u, 169u, 26u,
- 101u, 159u, 157u, 83u,
- 205u, 169u, 198u, 71u,
- 0u, 174u, 29u, 120u,
- 105u, 178u, 130u, 144u,
- 47u, 200u, 84u, 180u,
- 4u, 158u, 106u, 132u,
- 7u, 231u, 180u, 127u,
- 178u, 0u, 54u, 154u,
- 68u, 131u, 19u, 255u,
- 78u, 157u, 130u, 90u,
- 145u, 222u, 103u, 114u,
- 144u, 108u, 118u, 135u,
- 6u, 235u, 92u, 0u,
- 31u, 146u, 160u, 182u,
- 237u, 103u, 130u, 79u,
- 107u, 95u, 63u, 165u,
- 125u, 58u, 112u, 155u,
- 144u, 181u, 196u, 83u,
- 118u, 255u, 27u, 125u,
- 152u, 213u, 243u, 188u,
- 147u, 186u, 93u, 133u,
- 112u, 230u, 253u, 29u,
- 113u, 231u, 52u, 77u,
- 139u, 184u, 255u, 173u,
- 214u, 179u, 128u, 34u,
- 252u, 118u, 92u, 51u,
- 255u, 11u, 176u, 170u,
- 119u, 90u, 116u, 77u,
- 80u, 103u, 1u, 204u,
- 109u, 119u, 57u, 138u,
- 149u, 56u, 185u, 147u,
- 244u, 75u, 205u, 132u,
- 186u, 148u, 99u, 105u,
- 160u, 171u, 199u, 255u,
- 115u, 74u, 101u, 150u,
- 135u, 124u, 116u, 103u,
- 57u, 197u, 189u, 208u,
- 134u, 243u, 106u, 209u,
- 30u, 77u, 113u, 148u,
- 158u, 70u, 142u, 255u,
- 255u, 113u, 180u, 192u,
- 68u, 156u, 146u, 79u,
- 106u, 91u, 66u, 2u,
- 189u, 153u, 150u, 85u,
- 83u, 104u, 92u, 122u,
- 97u, 113u, 140u, 88u,
- 159u, 205u, 107u, 79u,
- 84u, 1u, 157u, 183u,
- 106u, 24u, 62u, 219u,
- 37u, 171u, 59u, 246u,
- 255u, 136u, 212u, 202u,
- 185u, 64u, 171u, 170u,
- 202u, 67u, 181u, 213u,
- 44u, 184u, 50u, 197u,
- 255u, 137u, 122u, 86u,
- 134u, 86u, 74u, 128u,
- 91u, 75u, 180u, 233u,
- 110u, 127u, 50u, 1u,
- 65u, 81u, 16u, 26u,
- 155u, 174u, 124u, 93u,
- 211u, 153u, 141u, 147u,
- 216u, 65u, 106u, 96u,
- 137u, 253u, 192u, 118u,
- 235u, 89u, 255u, 138u,
- 92u, 244u, 131u, 254u,
- 105u, 94u, 96u, 190u,
- 81u, 79u, 77u, 163u,
- 172u, 23u, 1u, 74u,
- 169u, 138u, 183u, 121u,
- 113u, 138u, 9u, 176u,
- 133u, 114u, 170u, 115u,
- 143u, 228u, 199u, 1u,
- 1u, 111u, 113u, 114u,
- 72u, 176u, 193u, 163u,
- 108u, 151u, 56u, 12u,
- 147u, 140u, 115u, 119u,
- 31u, 162u, 150u, 156u,
- 131u, 220u, 122u, 132u,
- 136u, 170u, 176u, 212u,
- 255u, 10u, 147u, 130u,
- 242u, 61u, 88u, 128u,
- 97u, 10u, 122u, 1u,
- 154u, 172u, 222u, 123u,
- 149u, 104u, 64u, 43u,
- 170u, 88u, 200u, 220u,
- 33u, 226u, 73u, 97u,
- 173u, 182u, 104u, 1u,
- 177u, 203u, 140u, 127u,
- 137u, 186u, 99u, 76u,
- 76u, 124u, 255u, 198u,
- 125u, 161u, 103u, 149u,
- 104u, 100u, 174u, 142u,
- 154u, 202u, 153u, 188u,
- 0u, 89u, 148u, 134u,
- 120u, 76u, 73u, 85u,
- 131u, 176u, 119u, 60u,
- 229u, 85u, 68u, 100u,
- 62u, 1u, 140u, 118u,
- 31u, 198u, 160u, 134u,
- 109u, 139u, 207u, 91u,
- 67u, 160u, 32u, 246u,
- 1u, 75u, 220u, 90u,
- 37u, 223u, 101u, 50u,
- 197u, 45u, 193u, 82u,
- 195u, 189u, 132u, 113u,
- 91u, 197u, 1u, 125u,
- 120u, 109u, 108u, 124u,
- 112u, 57u, 239u, 165u,
- 130u, 190u, 44u, 144u,
- 71u, 246u, 230u, 223u,
- 12u, 175u, 87u, 114u,
- 255u, 120u, 58u, 168u,
- 126u, 149u, 54u, 166u,
- 212u, 97u, 152u, 158u,
- 116u, 180u, 118u, 248u,
- 181u, 1u, 81u, 76u,
- 154u, 87u, 255u, 167u,
- 16u, 118u, 172u, 114u,
- 139u, 125u, 158u, 95u,
- 139u, 111u, 129u, 80u,
- 212u, 128u, 108u, 96u,
- 212u, 105u, 243u, 180u,
- 157u, 0u, 90u, 153u,
- 68u, 171u, 105u, 55u,
- 164u, 95u, 174u, 113u,
- 114u, 76u, 150u, 47u,
- 68u, 255u, 95u, 128u,
- 61u, 196u, 98u, 207u,
- 147u, 198u, 75u, 108u,
- 170u, 33u, 115u, 1u,
- 95u, 140u, 201u, 153u,
- 212u, 181u, 100u, 125u,
- 218u, 197u, 241u, 137u,
- 105u, 101u, 91u, 169u,
- 177u, 133u, 181u, 255u,
- 24u, 118u, 19u, 125u,
- 233u, 115u, 168u, 140u,
- 39u, 21u, 102u, 255u,
- 165u, 176u, 226u, 21u,
- 186u, 6u, 103u, 34u,
- 74u, 222u, 167u, 1u,
- 221u, 76u, 117u, 228u,
- 179u, 78u, 160u, 105u,
- 153u, 126u, 99u, 138u,
- 135u, 119u, 135u, 170u,
- 149u, 143u, 70u, 195u,
- 98u, 109u, 165u, 35u,
- 255u, 106u, 108u, 141u,
- 212u, 159u, 118u, 205u,
- 189u, 183u, 195u, 79u,
- 0u, 128u, 59u, 117u,
- 182u, 221u, 226u, 76u,
- 120u, 95u, 189u, 162u,
- 77u, 152u, 88u, 168u,
- 60u, 159u, 90u, 192u,
- 0u, 182u, 191u, 168u,
- 77u, 146u, 56u, 219u,
- 14u, 228u, 128u, 189u,
- 141u, 175u, 150u, 156u,
- 158u, 0u, 80u, 149u,
- 23u, 198u, 160u, 100u,
- 105u, 174u, 1u, 159u,
- 60u, 201u, 160u, 128u,
- 40u, 15u, 130u, 215u,
- 108u, 167u, 27u, 139u,
- 0u, 110u, 216u, 168u,
- 179u, 170u, 161u, 169u,
- 132u, 155u, 147u, 20u,
- 142u, 255u, 58u, 113u,
- 33u, 197u, 164u, 203u,
- 168u, 88u, 212u, 225u,
- 167u, 148u, 96u, 100u,
- 255u, 196u, 132u, 184u,
- 107u, 152u, 171u, 217u,
- 156u, 105u, 12u, 120u,
- 86u, 165u, 49u, 11u,
- 173u, 128u, 101u, 93u,
- 128u, 84u, 164u, 255u,
- 153u, 115u, 172u, 171u,
- 140u, 143u, 114u, 64u,
- 99u, 147u, 90u, 102u,
- 120u, 94u, 127u, 103u,
- 255u, 63u, 133u, 145u,
- 98u, 100u, 149u, 114u,
- 176u, 158u, 162u, 255u,
- 47u, 65u, 44u, 143u,
- 36u, 63u, 89u, 70u,
- 110u, 81u, 112u, 217u,
- 61u, 64u, 74u, 116u,
- 230u, 152u, 168u, 107u,
- 171u, 1u, 149u, 173u,
- 95u, 246u, 115u, 68u,
- 52u, 62u, 4u, 115u,
- 55u, 59u, 147u, 127u,
- 178u, 178u, 144u, 150u,
- 0u, 68u, 145u, 196u,
- 125u, 255u, 68u, 204u,
- 137u, 116u, 81u, 102u,
- 78u, 83u, 213u, 179u,
- 185u, 145u, 80u, 107u,
- 228u, 105u, 255u, 59u,
- 224u, 31u, 53u, 149u,
- 77u, 32u, 56u, 105u,
- 232u, 64u, 242u, 95u,
- 193u, 173u, 41u, 108u,
- 43u, 87u, 93u, 255u,
- 151u, 162u, 205u, 162u,
- 187u, 26u, 153u, 51u,
- 88u, 225u, 214u, 75u,
- 247u, 255u, 21u, 99u,
- 161u, 70u, 146u, 22u,
- 240u, 166u, 8u, 166u,
- 96u, 117u, 75u, 127u,
- 255u, 199u, 156u, 77u,
- 187u, 63u, 102u, 121u,
- 104u, 170u, 111u, 89u,
- 142u, 113u, 224u, 126u,
- 141u, 206u, 78u, 153u,
- 84u, 105u, 255u, 182u,
- 116u, 131u, 87u, 149u,
- 111u, 140u, 145u, 173u,
- 73u, 163u, 169u, 113u,
- 114u, 203u, 57u, 63u,
- 83u, 148u, 123u, 1u,
- 158u, 85u, 136u, 183u,
- 44u, 95u, 255u, 44u,
- 142u, 135u, 46u, 180u,
- 184u, 108u, 62u, 119u,
- 142u, 73u, 83u, 212u,
- 240u, 74u, 144u, 110u,
- 185u, 0u, 119u, 156u,
- 192u, 186u, 88u, 56u,
- 153u, 113u, 41u, 22u,
- 170u, 92u, 241u, 186u,
- 183u, 125u, 61u, 169u,
- 121u, 145u, 62u, 255u,
- 90u, 98u, 98u, 83u,
- 105u, 170u, 255u, 155u,
- 137u, 105u, 99u, 178u,
- 121u, 125u, 110u, 97u,
- 142u, 1u, 90u, 168u,
- 55u, 141u, 62u, 203u,
- 156u, 102u, 174u, 112u,
- 99u, 86u, 185u, 145u,
- 111u, 149u, 83u, 255u,
- 179u, 96u, 195u, 122u,
- 120u, 107u, 47u, 78u,
- 164u, 193u, 157u, 123u,
- 178u, 63u, 174u, 182u,
- 170u, 43u, 120u, 113u,
- 124u, 134u, 1u, 37u,
- 168u, 52u, 64u, 126u,
- 146u, 160u, 246u, 117u,
- 98u, 135u, 146u, 125u,
- 147u, 98u, 133u, 87u,
- 199u, 203u, 255u, 76u,
- 139u, 65u, 209u, 101u,
- 167u, 142u, 55u, 156u,
- 86u, 113u, 67u, 195u,
- 164u, 144u, 1u, 106u,
- 138u, 146u, 255u, 136u,
- 144u, 146u, 88u, 53u,
- 60u, 191u, 101u, 162u,
- 139u, 101u, 150u, 204u,
- 111u, 136u, 47u, 44u,
- 157u, 210u, 1u, 142u,
- 181u, 183u, 225u, 122u,
- 137u, 74u, 71u, 200u,
- 125u, 255u, 156u, 73u,
- 23u, 143u, 135u, 116u,
- 92u, 85u, 159u, 166u,
- 96u, 192u, 135u, 178u,
- 104u, 127u, 0u, 141u,
- 177u, 178u, 94u, 125u,
- 215u, 122u, 153u, 172u,
- 75u, 130u, 169u, 143u,
- 89u, 87u, 255u, 5u,
- 131u, 60u, 199u, 61u,
- 133u, 138u, 139u, 156u,
- 61u, 182u, 173u, 114u,
- 196u, 132u, 56u, 255u,
- 15u, 125u, 68u, 91u,
- 234u, 173u, 89u, 9u,
- 158u, 161u, 174u, 255u,
- 177u, 112u, 188u, 1u,
- 48u, 197u, 64u, 249u,
- 236u, 81u, 177u, 172u,
- 104u, 204u, 115u, 164u,
- 87u, 121u, 60u, 163u,
- 207u, 249u, 138u, 236u,
- 197u, 254u, 120u, 1u,
- 168u, 203u, 87u, 39u,
- 134u, 1u, 158u, 54u,
- 195u, 45u, 85u, 119u,
- 194u, 67u, 154u, 161u,
- 80u, 127u, 139u, 213u,
- 171u, 145u, 100u, 255u,
- 137u, 4u, 234u, 104u,
- 242u, 120u, 97u, 165u,
- 175u, 82u, 150u, 107u,
- 133u, 168u, 107u, 77u,
- 128u, 103u, 153u, 183u,
- 83u, 148u, 83u, 119u,
- 39u, 1u, 107u, 197u,
- 222u, 127u, 124u, 130u,
- 135u, 105u, 52u, 218u,
- 85u, 186u, 213u, 1u,
- 115u, 87u, 55u, 25u,
- 88u, 97u, 126u, 144u,
- 255u, 119u, 91u, 95u,
- 113u, 132u, 141u, 230u,
- 150u, 56u, 176u, 119u,
- 168u, 136u, 158u, 83u,
- 114u, 248u, 68u, 82u,
- 96u, 255u, 196u, 112u,
- 202u, 84u, 110u, 93u,
- 56u, 182u, 138u, 77u,
- 132u, 67u, 196u, 255u,
- 105u, 170u, 100u, 117u,
- 149u, 65u, 159u, 7u,
- 52u, 153u, 113u, 168u,
- 255u, 146u, 132u, 90u,
- 74u, 3u, 54u, 175u,
- 119u, 251u, 120u, 146u,
- 109u, 131u, 156u, 200u,
- 31u, 172u, 111u, 111u,
- 125u, 183u, 118u, 68u,
- 64u, 1u, 168u, 191u,
- 126u, 154u, 170u, 1u,
- 153u, 116u, 55u, 242u,
- 143u, 130u, 149u, 81u,
- 63u, 229u, 186u, 178u,
- 73u, 255u, 108u, 159u,
- 102u, 164u, 204u, 184u,
- 105u, 105u, 62u, 55u,
- 170u, 86u, 118u, 13u,
- 107u, 105u, 165u, 100u,
- 144u, 56u, 138u, 80u,
- 131u, 168u, 137u, 169u,
- 1u, 70u, 138u, 131u,
- 162u, 78u, 71u, 174u,
- 105u, 109u, 189u, 0u,
- 161u, 126u, 123u, 146u,
- 90u, 144u, 139u, 113u,
- 65u, 80u, 170u, 82u,
- 48u, 146u, 121u, 207u,
- 1u, 219u, 49u, 88u,
- 50u, 148u, 97u, 195u,
- 148u, 113u, 190u, 101u,
- 112u, 143u, 158u, 113u,
- 125u, 14u, 41u, 1u,
- 96u, 137u, 188u, 150u,
- 92u, 144u, 51u, 184u,
- 194u, 1u, 171u, 166u,
- 166u, 114u, 94u, 184u,
- 98u, 83u, 38u, 132u,
- 189u, 157u, 104u, 1u,
- 250u, 125u, 26u, 238u,
- 109u, 97u, 195u, 169u,
- 66u, 227u, 105u, 182u,
- 152u, 142u, 125u, 147u,
- 101u, 141u, 207u, 163u,
- 113u, 74u, 137u, 117u,
- 235u, 120u, 101u, 0u,
- 1u, 114u, 117u, 14u,
- 254u, 25u, 19u, 90u,
- 103u, 112u, 97u, 107u,
- 91u, 182u, 171u, 126u,
- 106u, 87u, 62u, 121u,
- 55u, 134u, 61u, 43u,
- 174u, 145u, 91u, 124u,
- 1u, 235u, 78u, 186u,
- 73u, 186u, 85u, 135u,
- 195u, 97u, 89u, 143u,
- 59u, 1u, 103u, 59u,
- 96u, 239u, 137u, 110u,
- 221u, 186u, 57u, 196u,
- 119u, 218u, 228u, 150u,
- 104u, 90u, 68u, 147u,
- 255u, 175u, 158u, 103u,
- 104u, 85u, 1u, 191u,
- 227u, 126u, 153u, 199u,
- 79u, 169u, 27u, 127u,
- 117u, 142u, 73u, 152u,
- 212u, 203u, 112u, 137u,
- 255u, 98u, 161u, 143u,
- 243u, 146u, 127u, 202u,
- 173u, 88u, 106u, 123u,
- 147u, 131u, 0u, 138u,
- 5u, 147u, 191u, 204u,
- 82u, 222u, 170u, 98u,
- 94u, 138u, 225u, 90u,
- 122u, 104u, 146u, 1u,
- 124u, 106u, 171u, 31u,
- 127u, 164u, 130u, 121u,
- 164u, 170u, 168u, 96u,
- 124u, 102u, 235u, 123u,
- 164u, 122u, 160u, 244u,
- 170u, 69u, 197u, 216u,
- 55u, 35u, 1u, 146u,
- 122u, 152u, 174u, 189u,
- 10u, 144u, 233u, 255u,
- 172u, 20u, 121u, 225u,
- 67u, 110u, 78u, 166u,
- 57u, 126u, 255u, 168u,
- 113u, 135u, 88u, 108u,
- 81u, 221u, 103u, 127u,
- 91u, 75u, 134u, 138u,
- 120u, 144u, 0u, 129u,
- 127u, 194u, 32u, 106u,
- 206u, 125u, 112u, 161u,
- 87u, 182u, 98u, 111u,
- 152u, 55u, 150u, 224u,
- 58u, 238u, 174u, 119u,
- 169u, 112u, 45u, 1u,
- 96u, 184u, 105u, 31u,
- 250u, 42u, 235u, 166u,
- 135u, 74u, 139u, 1u,
- 93u, 80u, 13u, 63u,
- 103u, 154u, 145u, 58u,
- 112u, 136u, 164u, 170u,
- 105u, 95u, 208u, 225u,
- 166u, 109u, 1u, 127u,
- 161u, 80u, 132u, 76u,
- 186u, 74u, 169u, 141u,
- 91u, 2u, 19u, 135u,
- 255u, 87u, 227u, 104u,
- 108u, 62u, 45u, 234u,
- 214u, 104u, 235u, 210u,
- 49u, 186u, 156u, 90u,
- 108u, 1u, 141u, 47u,
- 109u, 22u, 49u, 88u,
- 70u, 44u, 116u, 166u,
- 239u, 119u, 217u, 146u,
- 154u, 104u, 33u, 127u,
- 87u, 255u, 106u, 155u,
- 187u, 222u, 100u, 123u,
- 72u, 116u, 86u, 106u,
- 100u, 83u, 210u, 105u,
- 255u, 189u, 119u, 62u,
- 123u, 122u, 146u, 66u,
- 211u, 219u, 126u, 103u,
- 67u, 117u, 54u, 102u,
- 63u, 105u, 72u, 255u,
- 69u, 123u, 42u, 66u,
- 77u, 73u, 135u, 46u,
- 255u, 190u, 134u, 126u,
- 9u, 16u, 105u, 220u,
- 121u, 166u, 124u, 201u,
- 97u, 95u, 48u, 255u,
- 94u, 213u, 175u, 104u,
- 121u, 68u, 75u, 106u,
- 162u, 157u, 206u, 1u,
- 134u, 134u, 133u, 161u,
- 222u, 15u, 84u, 41u,
- 21u, 163u, 181u, 164u,
- 170u, 140u, 111u, 57u,
- 165u, 154u, 148u, 188u,
- 173u, 106u, 67u, 174u,
- 154u, 192u, 99u, 0u,
- 213u, 50u, 168u, 106u,
- 10u, 136u, 191u, 115u,
- 88u, 89u, 124u, 108u,
- 1u, 85u, 18u, 134u,
- 99u, 148u, 176u, 29u,
- 165u, 201u, 39u, 225u,
- 39u, 65u, 40u, 36u,
- 90u, 217u, 255u, 171u,
- 31u, 73u, 144u, 154u,
- 121u, 110u, 186u, 33u,
- 0u, 227u, 115u, 110u,
- 24u, 29u, 76u, 228u,
- 190u, 217u, 217u, 98u,
- 85u, 50u, 116u, 178u,
- 80u, 72u, 180u, 73u,
- 255u, 91u, 115u, 58u,
- 158u, 80u, 149u, 45u,
- 255u, 133u, 165u, 58u,
- 113u, 40u, 104u, 132u,
- 146u, 133u, 134u, 119u,
- 107u, 162u, 115u, 101u,
- 139u, 104u, 85u, 150u,
- 130u, 107u, 97u, 84u,
- 121u, 1u, 130u, 114u,
- 174u, 255u, 171u, 37u,
- 145u, 142u, 46u, 161u,
- 204u, 122u, 239u, 181u,
- 206u, 161u, 222u, 2u,
- 71u, 152u, 7u, 44u,
- 198u, 132u, 68u, 255u,
- 103u, 108u, 98u, 115u,
- 199u, 102u, 80u, 144u,
- 164u, 58u, 12u, 149u,
- 134u, 184u, 68u, 40u,
- 103u, 101u, 70u, 133u,
- 1u, 207u, 103u, 207u,
- 17u, 143u, 255u, 107u,
- 112u, 36u, 131u, 107u,
- 132u, 197u, 161u, 212u,
- 211u, 72u, 155u, 111u,
- 108u, 153u, 111u, 159u,
- 111u, 214u, 84u, 141u,
- 65u, 100u, 107u, 34u,
- 71u, 170u, 223u, 255u,
- 75u, 125u, 49u, 176u,
- 146u, 99u, 118u, 120u,
- 160u, 91u, 142u, 121u,
- 93u, 124u, 78u, 1u,
- 140u, 231u, 102u, 24u,
- 32u, 182u, 88u, 1u,
- 33u, 181u, 150u, 109u,
- 250u, 51u, 177u, 178u,
- 151u, 91u, 0u, 182u,
- 24u, 135u, 180u, 104u,
- 154u, 251u, 69u, 125u,
- 178u, 142u, 142u, 78u,
- 145u, 102u, 120u, 125u,
- 111u, 34u, 238u, 231u,
- 88u, 207u, 105u, 126u,
- 167u, 255u, 104u, 119u,
- 31u, 196u, 233u, 36u,
- 70u, 120u, 128u, 146u,
- 155u, 150u, 1u, 53u,
- 36u, 208u, 177u, 35u,
- 119u, 108u, 178u, 217u,
- 122u, 123u, 67u, 97u,
- 17u, 215u, 26u, 1u,
- 67u, 107u, 48u, 32u,
- 169u, 155u, 119u, 107u,
- 162u, 204u, 101u, 120u,
- 255u, 44u, 150u, 138u,
- 167u, 122u, 47u, 21u,
- 151u, 169u, 177u, 126u,
- 92u, 62u, 194u, 205u,
- 135u, 110u, 142u, 151u,
- 187u, 196u, 173u, 255u,
- 113u, 152u, 49u, 136u,
- 93u, 82u, 70u, 93u,
- 147u, 86u, 90u, 37u,
- 1u, 155u, 116u, 174u,
- 98u, 43u, 120u, 127u,
- 2u, 136u, 98u, 101u,
- 183u, 130u, 240u, 255u,
- 129u, 230u, 204u, 204u,
- 102u, 87u, 88u, 124u,
- 21u, 1u, 65u, 122u,
- 83u, 115u, 172u, 65u,
- 75u, 93u, 132u, 150u,
- 75u, 77u, 88u, 58u,
- 148u, 250u, 152u, 86u,
- 60u, 181u, 8u, 1u,
- 182u, 167u, 238u, 231u,
- 201u, 150u, 165u, 173u,
- 160u, 241u, 63u, 68u,
- 115u, 178u, 177u, 253u,
- 55u, 164u, 83u, 255u,
- 248u, 104u, 143u, 195u,
- 97u, 129u, 170u, 126u,
- 131u, 140u, 1u, 163u,
- 172u, 247u, 105u, 127u,
- 137u, 188u, 77u, 70u,
- 167u, 166u, 90u, 136u,
- 178u, 98u, 191u, 203u,
- 117u, 255u, 163u, 74u,
- 208u, 144u, 205u, 112u,
- 34u, 211u, 86u, 167u,
- 102u, 1u, 138u, 144u,
- 146u, 234u, 232u, 181u,
- 145u, 107u, 198u, 165u,
- 211u, 143u, 235u, 152u,
- 169u, 152u, 1u, 160u,
- 143u, 177u, 159u, 95u,
- 142u, 153u, 134u, 50u,
- 255u, 138u, 84u, 203u,
- 196u, 128u, 150u, 198u,
- 159u, 164u, 33u, 87u,
- 28u, 202u, 75u, 113u,
- 1u, 211u, 164u, 76u,
- 36u, 111u, 185u, 181u,
- 166u, 165u, 11u, 185u,
- 125u, 92u, 151u, 99u,
- 67u, 98u, 106u, 83u,
- 146u, 13u, 1u, 80u,
- 173u, 77u, 180u, 217u,
- 196u, 142u, 102u, 57u,
- 109u, 35u, 236u, 124u,
- 144u, 253u, 151u, 84u,
- 152u, 146u, 255u, 23u,
- 108u, 205u, 93u, 143u,
- 50u, 160u, 119u, 48u,
- 185u, 201u, 255u, 146u,
- 114u, 222u, 165u, 187u,
- 189u, 169u, 112u, 75u,
- 98u, 140u, 255u, 204u,
- 201u, 95u, 181u, 150u,
- 107u, 74u, 214u, 28u,
- 24u, 179u, 0u, 151u,
- 62u, 98u, 149u, 175u,
- 92u, 155u, 142u, 118u,
- 108u, 57u, 17u, 97u,
- 27u, 217u, 203u, 76u,
- 144u, 193u, 1u, 217u,
- 105u, 168u, 109u, 92u,
- 234u, 168u, 235u, 75u,
- 124u, 102u, 153u, 157u,
- 96u, 39u, 169u, 109u,
- 255u, 162u, 98u, 41u,
- 50u, 173u, 40u, 120u,
- 99u, 197u, 137u, 69u,
- 131u, 138u, 116u, 248u,
- 68u, 181u, 200u, 1u,
- 227u, 93u, 124u, 124u,
- 184u, 71u, 73u, 221u,
- 96u, 117u, 174u, 46u,
- 88u, 49u, 138u, 207u,
- 255u, 193u, 83u, 110u,
- 167u, 225u, 121u, 123u,
- 136u, 87u, 199u, 103u,
- 126u, 191u, 211u, 175u,
- 0u, 117u, 143u, 86u,
- 255u, 249u, 69u, 83u,
- 34u, 182u, 251u, 208u,
- 163u, 156u, 177u, 232u,
- 112u, 107u, 103u, 76u,
- 192u, 149u, 117u, 189u,
- 147u, 27u, 255u, 117u,
- 134u, 248u, 39u, 215u,
- 24u, 29u, 53u, 170u,
- 186u, 135u, 1u, 192u,
- 9u, 98u, 129u, 81u,
- 144u, 230u, 101u, 22u,
- 139u, 211u, 162u, 90u,
- 147u, 204u, 10u, 170u,
- 181u, 127u, 126u, 1u,
- 124u, 198u, 132u, 216u,
- 144u, 136u, 133u, 162u,
- 172u, 127u, 111u, 91u,
- 144u, 209u, 43u, 216u,
- 197u, 67u, 205u, 1u,
- 210u, 139u, 109u, 39u,
- 210u, 89u, 65u, 157u,
- 56u, 236u, 163u, 255u,
- 111u, 2u, 184u, 201u,
- 213u, 195u, 158u, 104u,
- 71u, 202u, 103u, 39u,
- 162u, 231u, 131u, 255u,
- 134u, 161u, 231u, 167u,
- 100u, 130u, 254u, 222u,
- 66u, 61u, 127u, 218u,
- 255u, 106u, 18u, 75u,
- 103u, 182u, 11u, 60u,
- 71u, 67u, 203u, 243u,
- 111u, 116u, 194u, 104u,
- 75u, 132u, 18u, 138u,
- 41u, 162u, 255u, 149u,
- 121u, 60u, 142u, 109u,
- 169u, 68u, 127u, 79u,
- 213u, 119u, 120u, 126u,
- 117u, 106u, 131u, 113u,
- 197u, 1u, 238u, 67u,
- 169u, 106u, 177u, 42u,
- 82u, 96u, 135u, 47u,
- 161u, 30u, 123u, 206u,
- 77u, 175u, 255u, 147u,
- 219u, 177u, 183u, 111u,
- 1u, 92u, 148u, 158u,
- 7u, 131u, 152u, 92u,
- 101u, 112u, 98u, 21u,
- 155u, 144u, 153u, 188u,
- 127u, 210u, 26u, 70u,
- 114u, 193u, 107u, 76u,
- 0u, 80u, 195u, 200u,
- 156u, 171u, 146u, 206u,
- 201u, 161u, 43u, 130u,
- 174u, 164u, 108u, 75u,
- 255u, 92u, 222u, 113u,
- 162u, 160u, 133u, 97u,
- 255u, 68u, 63u, 110u,
- 47u, 183u, 190u, 131u,
- 112u, 67u, 127u, 218u,
- 51u, 110u, 129u, 165u,
- 86u, 150u, 203u, 154u,
- 163u, 52u, 133u, 108u,
- 223u, 1u, 112u, 121u,
- 107u, 111u, 1u, 211u,
- 7u, 136u, 142u, 223u,
- 229u, 219u, 165u, 97u,
- 108u, 100u, 109u, 121u,
- 135u, 203u, 202u, 29u,
- 255u, 125u, 251u, 141u,
- 39u, 117u, 115u, 219u,
- 184u, 172u, 170u, 203u,
- 105u, 82u, 255u, 90u,
- 50u, 119u, 223u, 118u,
- 74u, 70u, 86u, 85u,
- 112u, 197u, 171u, 194u,
- 136u, 136u, 108u, 33u,
- 89u, 239u, 255u, 102u,
- 173u, 237u, 63u, 150u,
- 167u, 124u, 26u, 109u,
- 50u, 128u, 69u, 98u,
- 78u, 141u, 77u, 129u,
- 167u, 116u, 121u, 217u,
- 176u, 255u, 138u, 161u,
- 177u, 52u, 255u, 99u,
- 127u, 129u, 171u, 106u,
- 223u, 97u, 20u, 108u,
- 156u, 141u, 159u, 194u,
- 93u, 224u, 176u, 103u,
- 76u, 46u, 118u, 20u,
- 206u, 183u, 32u, 121u,
- 152u, 0u, 128u, 89u,
- 23u, 184u, 89u, 37u,
- 39u, 97u, 97u, 118u,
- 175u, 35u, 220u, 72u,
- 141u, 131u, 255u, 81u,
- 133u, 77u, 75u, 132u,
- 133u, 40u, 106u, 77u,
- 1u, 175u, 69u, 118u,
- 203u, 205u, 187u, 188u,
- 75u, 96u, 38u, 201u,
- 1u, 161u, 93u, 168u,
- 105u, 207u, 108u, 84u,
- 100u, 122u, 131u, 176u,
- 151u, 163u, 130u, 192u,
- 67u, 59u, 163u, 173u,
- 179u, 190u, 163u, 194u,
- 54u, 0u, 118u, 66u,
- 85u, 151u, 1u, 165u,
- 90u, 55u, 143u, 157u,
- 84u, 196u, 159u, 112u,
- 141u, 77u, 139u, 74u,
- 126u, 125u, 180u, 130u,
- 65u, 81u, 0u, 119u,
- 90u, 165u, 149u, 80u,
- 84u, 85u, 103u, 148u,
- 185u, 128u, 130u, 154u,
- 0u, 180u, 138u, 124u,
- 176u, 95u, 159u, 131u,
- 212u, 115u, 99u, 95u,
- 110u, 181u, 151u, 69u,
- 158u, 152u, 131u, 180u,
- 61u, 255u, 219u, 61u,
- 173u, 68u, 139u, 177u,
- 120u, 177u, 1u, 157u,
- 37u, 144u, 147u, 88u,
- 108u, 126u, 150u, 172u,
- 55u, 76u, 140u, 169u,
- 127u, 142u, 118u, 140u,
- 1u, 175u, 197u, 124u,
- 81u, 165u, 183u, 144u,
- 222u, 237u, 103u, 77u,
- 255u, 125u, 96u, 129u,
- 139u, 54u, 36u, 83u,
- 88u, 96u, 86u, 31u,
- 63u, 132u, 123u, 145u,
- 34u, 163u, 121u, 232u,
- 74u, 3u, 145u, 98u,
- 166u, 1u, 50u, 226u,
- 125u, 183u, 246u, 98u,
- 169u, 127u, 121u, 138u,
- 148u, 178u, 47u, 186u,
- 110u, 68u, 194u, 3u,
- 146u, 209u, 87u, 1u,
- 186u, 184u, 255u, 113u,
- 32u, 87u, 117u, 43u,
- 29u, 247u, 205u, 125u,
- 174u, 182u, 79u, 161u,
- 139u, 53u, 182u, 61u,
- 197u, 59u, 9u, 69u,
- 255u, 12u, 207u, 69u,
- 72u, 97u, 123u, 207u,
- 69u, 187u, 4u, 166u,
- 55u, 147u, 108u, 151u,
- 112u, 198u, 255u, 73u,
- 191u, 66u, 176u, 80u,
- 72u, 40u, 92u, 142u,
- 143u, 11u, 171u, 93u,
- 190u, 139u, 86u, 158u,
- 80u, 0u, 209u, 143u,
- 124u, 177u, 162u, 140u,
- 233u, 232u, 94u, 37u,
- 116u, 56u, 64u, 122u,
- 180u, 131u, 76u, 255u,
- 113u, 206u, 129u, 67u,
- 138u, 125u, 54u, 113u,
- 70u, 105u, 174u, 214u,
- 80u, 106u, 87u, 255u,
- 48u, 103u, 192u, 158u,
- 130u, 159u, 233u, 68u,
- 26u, 85u, 35u, 129u,
- 146u, 255u, 96u, 200u,
- 124u, 163u, 1u, 184u,
- 121u, 124u, 153u, 187u,
- 115u, 100u, 149u, 214u,
- 125u, 153u, 209u, 226u,
- 147u, 101u, 157u, 210u,
- 161u, 255u, 195u, 17u,
- 130u, 161u, 60u, 29u,
- 79u, 162u, 189u, 107u,
- 55u, 58u, 70u, 214u,
- 52u, 185u, 186u, 72u,
- 0u, 89u, 116u, 252u,
- 200u, 197u, 90u, 186u,
- 255u, 157u, 39u, 176u,
- 147u, 5u, 47u, 41u,
- 133u, 30u, 102u, 65u,
- 104u, 132u, 80u, 83u,
- 63u, 217u, 186u, 104u,
- 72u, 127u, 255u, 47u,
- 183u, 108u, 172u, 150u,
- 188u, 38u, 24u, 184u,
- 70u, 94u, 48u, 243u,
- 86u, 72u, 255u, 129u,
- 146u, 140u, 88u, 49u,
- 73u, 41u, 196u, 55u,
- 139u, 112u, 172u, 129u,
- 149u, 173u, 153u, 112u,
- 255u, 223u, 108u, 132u,
- 180u, 130u, 106u, 169u,
- 127u, 104u, 182u, 108u,
- 1u, 72u, 186u, 91u,
- 235u, 154u, 5u, 10u,
- 146u, 3u, 243u, 212u,
- 43u, 129u, 198u, 88u,
- 163u, 230u, 100u, 112u,
- 56u, 55u, 232u, 1u,
- 255u, 244u, 171u, 172u,
- 174u, 137u, 168u, 255u,
- 101u, 144u, 27u, 144u,
- 125u, 134u, 111u, 178u,
- 146u, 140u, 171u, 181u,
- 165u, 158u, 160u, 156u,
- 147u, 82u, 131u, 151u,
- 106u, 109u, 221u, 255u,
- 109u, 141u, 166u, 52u,
- 144u, 117u, 171u, 119u,
- 164u, 179u, 141u, 1u,
- 169u, 112u, 37u, 39u,
- 152u, 149u, 73u, 111u,
- 159u, 160u, 31u, 110u,
- 196u, 145u, 202u, 195u,
- 197u, 115u, 143u, 121u,
- 225u, 241u, 255u, 42u,
- 116u, 194u, 205u, 130u,
- 137u, 165u, 78u, 191u,
- 131u, 255u, 159u, 123u,
- 159u, 94u, 56u, 134u,
- 164u, 107u, 144u, 138u,
- 55u, 215u, 65u, 82u,
- 139u, 88u, 233u, 139u,
- 90u, 76u, 152u, 255u,
- 7u, 190u, 101u, 96u,
- 214u, 130u, 3u, 203u,
- 8u, 172u, 136u, 1u,
- 178u, 41u, 158u, 110u,
- 229u, 105u, 114u, 132u,
- 1u, 69u, 210u, 107u,
- 31u, 72u, 123u, 136u,
- 91u, 91u, 96u, 154u,
- 133u, 33u, 1u, 63u,
- 142u, 52u, 184u, 62u,
- 188u, 180u, 223u, 99u,
- 48u, 216u, 173u, 108u,
- 70u, 157u, 78u, 188u,
- 170u, 194u, 4u, 77u,
- 6u, 123u, 149u, 252u,
- 114u, 72u, 234u, 255u,
- 46u, 62u, 147u, 140u,
- 101u, 203u, 162u, 85u,
- 96u, 77u, 135u, 58u,
- 59u, 255u, 197u, 95u,
- 71u, 143u, 78u, 74u,
- 159u, 134u, 113u, 65u,
- 84u, 160u, 89u, 255u,
- 117u, 132u, 86u, 236u,
- 148u, 124u, 125u, 255u,
- 61u, 98u, 140u, 75u,
- 126u, 174u, 198u, 140u,
- 132u, 160u, 203u, 68u,
- 255u, 65u, 227u, 178u,
- 105u, 191u, 230u, 181u,
- 59u, 108u, 10u, 198u,
- 209u, 129u, 102u, 198u,
- 116u, 69u, 127u, 137u,
- 255u, 158u, 92u, 110u,
- 143u, 120u, 131u, 126u,
- 78u, 176u, 35u, 146u,
- 105u, 224u, 1u, 79u,
- 55u, 159u, 46u, 246u,
- 106u, 170u, 146u, 106u,
- 187u, 195u, 119u, 48u,
- 202u, 153u, 255u, 82u,
- 230u, 104u, 43u, 190u,
- 186u, 189u, 50u, 56u,
- 103u, 178u, 160u, 80u,
- 190u, 70u, 203u, 200u,
- 108u, 45u, 135u, 153u,
- 177u, 255u, 116u, 151u,
- 128u, 121u, 195u, 58u,
- 125u, 255u, 233u, 103u,
- 73u, 228u, 149u, 12u,
- 73u, 217u, 64u, 177u,
- 100u, 122u, 106u, 72u,
- 106u, 137u, 81u, 101u,
- 66u, 194u, 167u, 213u,
- 167u, 101u, 255u, 204u,
- 186u, 91u, 242u, 120u,
- 1u, 205u, 112u, 208u,
- 67u, 59u, 37u, 59u,
- 159u, 145u, 111u, 137u,
- 106u, 31u, 86u, 74u,
- 211u, 135u, 121u, 163u,
- 88u, 1u, 35u, 147u,
- 102u, 150u, 100u, 53u,
- 27u, 26u, 226u, 76u,
- 161u, 254u, 181u, 1u,
- 54u, 150u, 60u, 156u,
- 165u, 202u, 216u, 4u,
- 124u, 116u, 145u, 15u,
- 179u, 157u, 163u, 103u,
- 1u, 109u, 12u, 178u,
- 176u, 103u, 170u, 52u,
- 47u, 106u, 65u, 111u,
- 223u, 118u, 9u, 255u,
- 231u, 84u, 128u, 119u,
- 248u, 49u, 10u, 64u,
- 73u, 209u, 179u, 53u,
- 196u, 183u, 116u, 185u,
- 126u, 170u, 26u, 255u,
- 219u, 67u, 212u, 116u,
- 113u, 73u, 44u, 104u,
- 22u, 163u, 255u, 70u,
- 155u, 49u, 167u, 41u,
- 124u, 163u, 123u, 169u,
- 137u, 42u, 130u, 253u,
- 255u, 224u, 103u, 124u,
- 87u, 128u, 115u, 191u,
- 154u, 155u, 119u, 127u,
- 98u, 129u, 113u, 101u,
- 148u, 190u, 139u, 124u,
- 1u, 136u, 120u, 169u,
- 203u, 135u, 192u, 156u,
- 214u, 162u, 201u, 105u,
- 25u, 176u, 1u, 84u,
- 211u, 198u, 75u, 188u,
- 177u, 136u, 135u, 68u,
- 55u, 134u, 149u, 193u,
- 186u, 0u, 121u, 192u,
- 228u, 61u, 10u, 82u,
- 8u, 110u, 15u, 90u,
- 193u, 79u, 138u, 119u,
- 47u, 153u, 37u, 70u,
- 61u, 90u, 84u, 150u,
- 123u, 191u, 150u, 110u,
- 4u, 96u, 170u, 255u,
- 171u, 109u, 56u, 136u,
- 255u, 170u, 103u, 186u,
- 126u, 109u, 102u, 232u,
- 142u, 184u, 204u, 250u,
- 97u, 140u, 141u, 1u,
- 183u, 144u, 184u, 90u,
- 140u, 189u, 169u, 202u,
- 163u, 200u, 91u, 103u,
- 159u, 149u, 165u, 1u,
- 118u, 138u, 59u, 163u,
- 192u, 87u, 168u, 82u,
- 42u, 201u, 60u, 89u,
- 103u, 121u, 157u, 0u,
- 118u, 200u, 102u, 140u,
- 116u, 182u, 201u, 145u,
- 85u, 123u, 46u, 181u,
- 147u, 255u, 118u, 246u,
- 174u, 134u, 96u, 5u,
- 3u, 7u, 151u, 220u,
- 54u, 205u, 122u, 181u,
- 126u, 111u, 1u, 65u,
- 177u, 157u, 82u, 158u,
- 100u, 140u, 157u, 33u,
- 143u, 160u, 71u, 168u,
- 0u, 96u, 145u, 238u,
- 60u, 252u, 155u, 147u,
- 36u, 30u, 136u, 26u,
- 205u, 118u, 149u, 92u,
- 159u, 48u, 141u, 205u,
- 41u, 87u, 1u, 42u,
- 102u, 184u, 117u, 104u,
- 96u, 66u, 17u, 246u,
- 220u, 163u, 61u, 40u,
- 89u, 142u, 0u, 143u,
- 11u, 187u, 201u, 142u,
- 164u, 239u, 97u, 130u,
- 1u, 46u, 145u, 239u,
- 255u, 227u, 117u, 58u,
- 148u, 135u, 9u, 172u,
- 108u, 65u, 215u, 124u,
- 113u, 140u, 173u, 179u,
- 168u, 135u, 128u, 86u,
- 1u, 139u, 227u, 84u,
- 149u, 12u, 129u, 61u,
- 123u, 155u, 124u, 80u,
- 144u, 172u, 224u, 27u,
- 255u, 104u, 76u, 234u,
- 204u, 60u, 47u, 107u,
- 247u, 158u, 255u, 72u,
- 179u, 92u, 137u, 4u,
- 131u, 152u, 129u, 143u,
- 125u, 124u, 167u, 70u,
- 163u, 144u, 151u, 125u,
- 104u, 127u, 172u, 112u,
- 139u, 115u, 73u, 255u,
- 113u, 183u, 119u, 178u,
- 164u, 125u, 189u, 1u,
- 136u, 112u, 154u, 189u,
- 103u, 200u, 197u, 227u,
- 178u, 82u, 60u, 147u,
- 112u, 39u, 128u, 108u,
- 87u, 89u, 77u, 71u,
- 203u, 87u, 239u, 184u,
- 106u, 1u, 178u, 85u,
- 148u, 171u, 114u, 220u,
- 31u, 140u, 255u, 95u,
- 131u, 167u, 89u, 126u,
- 136u, 208u, 99u, 56u,
- 62u, 167u, 191u, 53u,
- 133u, 170u, 224u, 103u,
- 36u, 24u, 114u, 1u,
- 41u, 154u, 163u, 244u,
- 184u, 129u, 164u, 0u,
- 30u, 82u, 39u, 196u,
- 82u, 169u, 235u, 109u,
- 95u, 120u, 128u, 116u,
- 212u, 161u, 129u, 121u,
- 163u, 69u, 1u, 99u,
- 194u, 213u, 194u, 100u,
- 85u, 107u, 127u, 166u,
- 182u, 128u, 109u, 88u,
- 125u, 1u, 152u, 96u,
- 94u, 187u, 103u, 140u,
- 75u, 80u, 165u, 80u,
- 83u, 142u, 77u, 52u,
- 111u, 147u, 171u, 145u,
- 203u, 101u, 137u, 165u,
- 70u, 53u, 148u, 255u,
- 255u, 143u, 208u, 8u,
- 183u, 196u, 160u, 229u,
- 88u, 35u, 204u, 202u,
- 206u, 72u, 126u, 153u,
- 73u, 160u, 52u, 126u,
- 128u, 128u, 22u, 183u,
- 175u, 104u, 255u, 43u,
- 140u, 67u, 91u, 68u,
- 25u, 143u, 208u, 156u,
- 246u, 66u, 99u, 195u,
- 7u, 1u, 148u, 87u,
- 133u, 143u, 22u, 210u,
- 172u, 116u, 187u, 165u,
- 152u, 181u, 181u, 120u,
- 255u, 90u, 172u, 127u,
- 174u, 141u, 70u, 113u,
- 93u, 152u, 25u, 77u,
- 120u, 59u, 219u, 101u,
- 232u, 207u, 152u, 1u,
- 134u, 129u, 141u, 108u,
- 23u, 129u, 125u, 1u,
- 108u, 153u, 173u, 53u,
- 120u, 140u, 139u, 168u,
- 23u, 205u, 158u, 124u,
- 162u, 133u, 89u, 24u,
- 137u, 119u, 175u, 105u,
- 160u, 159u, 114u, 255u,
- 172u, 158u, 100u, 31u,
- 43u, 86u, 46u, 163u,
- 217u, 113u, 66u, 211u,
- 198u, 191u, 134u, 129u,
- 1u, 40u, 95u, 149u,
- 91u, 175u, 254u, 176u,
- 89u, 81u, 220u, 51u,
- 144u, 132u, 223u, 179u,
- 63u, 1u, 135u, 68u,
- 200u, 200u, 156u, 109u,
- 181u, 48u, 79u, 167u,
- 82u, 193u, 78u, 81u,
- 221u, 197u, 251u, 1u,
- 163u, 84u, 104u, 154u,
- 59u, 131u, 125u, 73u,
- 108u, 192u, 169u, 1u,
- 138u, 107u, 104u, 147u,
- 138u, 152u, 255u, 90u,
- 185u, 241u, 201u, 240u,
- 111u, 173u, 27u, 55u,
- 206u, 115u, 137u, 130u,
- 137u, 119u, 242u, 191u,
- 173u, 105u, 106u, 98u,
- 110u, 183u, 0u, 20u,
- 33u, 35u, 65u, 102u,
- 193u, 174u, 96u, 116u,
- 1u, 165u, 73u, 202u,
- 122u, 190u, 216u, 85u,
- 117u, 2u, 112u, 81u,
- 148u, 98u, 176u, 207u,
- 92u, 1u, 99u, 39u,
- 159u, 125u, 148u, 121u,
- 49u, 84u, 224u, 77u,
- 179u, 90u, 129u, 1u,
- 116u, 24u, 50u, 136u,
- 125u, 145u, 212u, 86u,
- 127u, 94u, 130u, 127u,
- 135u, 165u, 100u, 112u,
- 53u, 133u, 50u, 135u,
- 125u, 218u, 255u, 117u,
- 165u, 75u, 144u, 113u,
- 184u, 147u, 139u, 198u,
- 83u, 147u, 80u, 255u,
- 171u, 28u, 188u, 144u,
- 186u, 90u, 101u, 13u,
- 90u, 79u, 162u, 140u,
- 128u, 158u, 159u, 128u,
- 103u, 163u, 115u, 146u,
- 118u, 255u, 147u, 142u,
- 76u, 151u, 127u, 121u,
- 142u, 185u, 56u, 180u,
- 122u, 173u, 133u, 108u,
- 1u, 167u, 65u, 169u,
- 105u, 255u, 154u, 112u,
- 41u, 228u, 34u, 154u,
- 124u, 193u, 164u, 98u,
- 175u, 162u, 165u, 138u,
- 161u, 71u, 103u, 85u,
- 128u, 101u, 255u, 39u,
- 198u, 117u, 118u, 169u,
- 126u, 172u, 103u, 149u,
- 123u, 165u, 255u, 166u,
- 112u, 141u, 117u, 169u,
- 123u, 139u, 27u, 89u,
- 101u, 158u, 111u, 147u,
- 198u, 225u, 176u, 35u,
- 212u, 159u, 12u, 152u,
- 58u, 158u, 166u, 119u,
- 146u, 153u, 143u, 255u,
- 255u, 176u, 195u, 29u,
- 117u, 140u, 52u, 107u,
- 104u, 156u, 156u, 83u,
- 58u, 89u, 69u, 118u,
- 47u, 152u, 112u, 84u,
- 136u, 146u, 100u, 169u,
- 127u, 58u, 111u, 136u,
- 130u, 123u, 117u, 1u,
- 167u, 91u, 213u, 167u,
- 103u, 66u, 176u, 1u,
- 159u, 192u, 160u, 185u,
- 212u, 140u, 166u, 92u,
- 146u, 147u, 197u, 84u,
- 88u, 63u, 152u, 106u,
- 198u, 130u, 195u, 188u,
- 91u, 1u, 104u, 179u,
- 172u, 119u, 113u, 132u,
- 93u, 109u, 79u, 146u,
- 130u, 150u, 125u, 117u,
- 149u, 128u, 95u, 1u,
- 74u, 211u, 149u, 1u,
- 37u, 156u, 105u, 143u,
- 41u, 51u, 184u, 34u,
- 192u, 66u, 181u, 114u,
- 38u, 134u, 192u, 143u,
- 14u, 94u, 79u, 183u,
- 118u, 1u, 225u, 26u,
- 119u, 56u, 95u, 53u,
- 149u, 100u, 173u, 21u,
- 255u, 169u, 185u, 119u,
- 208u, 30u, 88u, 177u,
- 148u, 172u, 18u, 68u,
- 255u, 128u, 126u, 124u,
- 29u, 91u, 141u, 124u,
- 52u, 76u, 65u, 71u,
- 112u, 133u, 145u, 120u,
- 222u, 108u, 255u, 9u,
- 135u, 178u, 83u, 126u,
- 138u, 69u, 157u, 147u,
- 75u, 141u, 133u, 55u,
- 138u, 96u, 77u, 33u,
- 43u, 93u, 250u, 194u,
- 133u, 64u, 255u, 107u,
- 71u, 48u, 121u, 100u,
- 82u, 121u, 171u, 112u,
- 41u, 149u, 241u, 184u,
- 88u, 81u, 206u, 120u,
- 18u, 31u, 149u, 1u,
- 105u, 87u, 171u, 28u,
- 196u, 197u, 80u, 255u,
- 177u, 63u, 237u, 77u,
- 57u, 191u, 205u, 43u,
- 42u, 144u, 254u, 229u,
- 200u, 132u, 142u, 104u,
- 23u, 81u, 91u, 255u,
- 215u, 154u, 53u, 143u,
- 100u, 123u, 182u, 144u,
- 23u, 191u, 160u, 51u,
- 152u, 71u, 223u, 255u,
- 200u, 121u, 125u, 208u,
- 71u, 194u, 1u, 6u,
- 125u, 94u, 91u, 110u,
- 216u, 99u, 199u, 197u,
- 30u, 217u, 50u, 130u,
- 125u, 96u, 72u, 192u,
- 128u, 113u, 141u, 115u,
- 18u, 54u, 64u, 0u,
- 39u, 184u, 153u, 153u,
- 107u, 152u, 149u, 102u,
- 162u, 119u, 17u, 183u,
- 66u, 156u, 90u, 1u,
- 169u, 63u, 232u, 95u,
- 168u, 102u, 90u, 220u,
- 221u, 126u, 155u, 178u,
- 110u, 160u, 80u, 79u,
- 255u, 166u, 100u, 154u,
- 74u, 189u, 122u, 237u,
- 181u, 216u, 209u, 184u,
- 120u, 1u, 39u, 116u,
- 187u, 185u, 127u, 192u,
- 158u, 88u, 218u, 41u,
- 48u, 60u, 68u, 255u,
- 67u, 235u, 203u, 91u,
- 27u, 101u, 147u, 233u,
- 22u, 1u, 100u, 164u,
- 164u, 148u, 178u, 155u,
- 172u, 187u, 111u, 201u,
- 192u, 142u, 124u, 186u,
- 78u, 199u, 80u, 116u,
- 35u, 145u, 252u, 227u,
- 67u, 255u, 253u, 123u,
- 237u, 204u, 147u, 180u,
- 159u, 70u, 144u, 255u,
- 157u, 223u, 94u, 164u,
- 167u, 17u, 106u, 82u,
- 131u, 98u, 61u, 95u,
- 1u, 163u, 133u, 118u,
- 220u, 195u, 164u, 157u,
- 95u, 189u, 104u, 188u,
- 126u, 65u, 148u, 132u,
- 162u, 93u, 180u, 130u,
- 241u, 142u, 125u, 83u,
- 127u, 185u, 1u, 128u,
- 101u, 183u, 199u, 118u,
- 64u, 64u, 181u, 202u,
- 30u, 255u, 165u, 160u,
- 128u, 50u, 54u, 46u,
- 99u, 209u, 67u, 22u,
- 146u, 129u, 141u, 0u,
- 189u, 84u, 214u, 137u,
- 64u, 203u, 185u, 174u,
- 201u, 103u, 168u, 75u,
- 163u, 182u, 1u, 183u,
- 54u, 110u, 160u, 248u,
- 37u, 90u, 209u, 133u,
- 89u, 148u, 80u, 98u,
- 121u, 121u, 119u, 123u,
- 137u, 231u, 114u, 109u,
- 89u, 190u, 154u, 136u,
- 143u, 145u, 1u, 119u,
- 136u, 62u, 1u, 207u,
- 58u, 193u, 104u, 102u,
- 179u, 97u, 117u, 100u,
- 156u, 149u, 94u, 132u,
- 166u, 159u, 175u, 140u,
- 109u, 122u, 104u, 118u,
- 59u, 182u, 90u, 124u,
- 130u, 80u, 155u, 255u,
- 203u, 101u, 102u, 149u,
- 0u, 110u, 91u, 75u,
- 128u, 226u, 148u, 161u,
- 172u, 55u, 109u, 127u,
- 68u, 148u, 113u, 127u,
- 55u, 155u, 66u, 194u,
- 149u, 219u, 255u, 175u,
- 85u, 74u, 109u, 160u,
- 0u, 157u, 147u, 200u,
- 162u, 151u, 193u, 192u,
- 59u, 94u, 111u, 127u,
- 54u, 92u, 189u, 170u,
- 34u, 121u, 114u, 14u,
- 115u, 34u, 19u, 20u,
- 65u, 94u, 189u, 1u,
- 68u, 31u, 209u, 39u,
- 122u, 178u, 82u, 99u,
- 172u, 251u, 29u, 153u,
- 6u, 1u, 164u, 206u,
- 140u, 82u, 115u, 49u,
- 255u, 110u, 236u, 129u,
- 94u, 167u, 206u, 138u,
- 160u, 149u, 48u, 137u,
- 152u, 174u, 60u, 139u,
- 177u, 172u, 170u, 82u,
- 73u, 1u, 60u, 51u,
- 25u, 180u, 145u, 152u,
- 118u, 57u, 103u, 144u,
- 122u, 152u, 127u, 150u,
- 154u, 255u, 15u, 175u,
- 117u, 183u, 128u, 171u,
- 195u, 149u, 110u, 177u,
- 62u, 121u, 115u, 255u,
- 82u, 66u, 82u, 24u,
- 159u, 60u, 158u, 29u,
- 160u, 53u, 109u, 37u,
- 221u, 191u, 249u, 176u,
- 219u, 120u, 52u, 45u,
- 8u, 137u, 125u, 140u,
- 172u, 173u, 165u, 1u,
- 255u, 124u, 142u, 94u,
- 101u, 156u, 75u, 252u,
- 90u, 125u, 179u, 158u,
- 207u, 164u, 59u, 183u,
- 145u, 166u, 118u, 157u,
- 114u, 135u, 83u, 110u,
- 146u, 72u, 152u, 130u,
- 100u, 191u, 82u, 1u,
- 211u, 131u, 101u, 98u,
- 167u, 96u, 156u, 139u,
- 128u, 103u, 112u, 150u,
- 79u, 255u, 54u, 85u,
- 174u, 76u, 173u, 205u,
- 147u, 68u, 192u, 1u,
- 97u, 101u, 62u, 72u,
- 202u, 95u, 137u, 119u,
- 196u, 176u, 150u, 86u,
- 161u, 146u, 178u, 115u,
- 255u, 83u, 175u, 135u,
- 51u, 225u, 79u, 48u,
- 135u, 129u, 160u, 85u,
- 185u, 73u, 1u, 133u,
- 79u, 149u, 169u, 107u,
- 112u, 113u, 35u, 133u,
- 160u, 138u, 109u, 78u,
- 138u, 74u, 230u, 38u,
- 93u, 129u, 79u, 132u,
- 88u, 255u, 170u, 48u,
- 65u, 174u, 146u, 0u,
- 85u, 180u, 168u, 168u,
- 59u, 141u, 96u, 217u,
- 47u, 74u, 170u, 190u,
- 116u, 250u, 88u, 128u,
- 49u, 255u, 160u, 172u,
- 203u, 110u, 219u, 103u,
- 159u, 233u, 106u, 94u,
- 94u, 180u, 84u, 128u,
- 130u, 191u, 1u, 159u,
- 78u, 120u, 198u, 38u,
- 101u, 105u, 136u, 127u,
- 54u, 67u, 61u, 67u,
- 235u, 1u, 177u, 215u,
- 237u, 67u, 162u, 193u,
- 133u, 193u, 183u, 13u,
- 171u, 32u, 145u, 143u,
- 22u, 139u, 191u, 184u,
- 26u, 153u, 74u, 180u,
- 127u, 1u, 6u, 247u,
- 111u, 140u, 0u, 113u,
- 206u, 171u, 243u, 142u,
- 102u, 244u, 111u, 111u,
- 140u, 58u, 134u, 108u,
- 225u, 74u, 39u, 108u,
- 97u, 123u, 28u, 197u,
- 112u, 163u, 142u, 109u,
- 145u, 255u, 61u, 166u,
- 150u, 89u, 194u, 34u,
- 63u, 176u, 45u, 93u,
- 157u, 172u, 229u, 255u,
- 139u, 47u, 70u, 179u,
- 129u, 142u, 181u, 0u,
- 223u, 131u, 74u, 132u,
- 151u, 99u, 88u, 69u,
- 128u, 193u, 50u, 147u,
- 134u, 12u, 191u, 109u,
- 210u, 49u, 220u, 109u,
- 58u, 136u, 0u, 145u,
- 236u, 134u, 122u, 28u,
- 139u, 77u, 129u, 32u,
- 200u, 101u, 102u, 98u,
- 255u, 110u, 154u, 98u,
- 169u, 98u, 31u, 70u,
- 151u, 144u, 211u, 96u,
- 255u, 19u, 246u, 202u,
- 71u, 14u, 40u, 200u,
- 204u, 113u, 151u, 131u,
- 193u, 157u, 255u, 112u,
- 176u, 61u, 185u, 37u,
- 155u, 173u, 49u, 135u,
- 133u, 145u, 195u, 125u,
- 69u, 125u, 86u, 131u,
- 162u, 212u, 1u, 77u,
- 154u, 149u, 212u, 123u,
- 85u, 76u, 104u, 218u,
- 139u, 84u, 100u, 154u,
- 112u, 81u, 159u, 47u,
- 180u, 255u, 68u, 98u,
- 35u, 168u, 143u, 160u,
- 191u, 156u, 178u, 117u,
- 158u, 201u, 0u, 181u,
- 84u, 81u, 189u, 103u,
- 108u, 207u, 160u, 233u,
- 133u, 161u, 127u, 40u,
- 52u, 73u, 255u, 248u,
- 48u, 24u, 52u, 33u,
- 168u, 93u, 90u, 158u,
- 106u, 146u, 140u, 183u,
- 135u, 153u, 59u, 169u,
- 133u, 0u, 109u, 110u,
- 76u, 135u, 112u, 116u,
- 178u, 248u, 115u, 36u,
- 255u, 110u, 94u, 195u,
- 81u, 178u, 144u, 180u,
- 217u, 43u, 141u, 187u,
- 191u, 151u, 52u, 89u,
- 1u, 110u, 88u, 168u,
- 105u, 140u, 232u, 119u,
- 58u, 132u, 123u, 178u,
- 69u, 14u, 16u, 125u,
- 165u, 127u, 208u, 255u,
- 221u, 93u, 90u, 99u,
- 53u, 168u, 179u, 116u,
- 190u, 28u, 174u, 93u,
- 255u, 95u, 89u, 69u,
- 186u, 106u, 60u, 147u,
- 104u, 145u, 125u, 164u,
- 200u, 152u, 141u, 122u,
- 120u, 23u, 124u, 98u,
- 31u, 84u, 164u, 255u,
- 182u, 175u, 77u, 104u,
- 209u, 70u, 100u, 163u,
- 197u, 129u, 151u, 122u,
- 123u, 0u, 42u, 89u,
- 82u, 204u, 81u, 112u,
- 255u, 64u, 135u, 142u,
- 104u, 104u, 82u, 75u,
- 116u, 151u, 121u, 228u,
- 96u, 115u, 77u, 165u,
- 255u, 112u, 198u, 104u,
- 53u, 97u, 210u, 64u,
- 183u, 215u, 211u, 212u,
- 124u, 50u, 202u, 176u,
- 100u, 191u, 172u, 81u,
- 89u, 201u, 186u, 83u,
- 255u, 141u, 182u, 131u,
- 170u, 142u, 156u, 92u,
- 40u, 50u, 124u, 159u,
- 255u, 180u, 66u, 63u,
- 98u, 204u, 41u, 105u,
- 14u, 37u, 163u, 255u,
- 47u, 115u, 27u, 187u,
- 68u, 89u, 197u, 136u,
- 111u, 237u, 1u, 89u,
- 56u, 146u, 238u, 214u,
- 59u, 156u, 119u, 170u,
- 99u, 154u, 134u, 82u,
- 90u, 81u, 16u, 1u,
- 97u, 115u, 201u, 122u,
- 190u, 219u, 168u, 216u,
- 97u, 175u, 108u, 209u,
- 26u, 135u, 134u, 141u,
- 130u, 12u, 161u, 255u,
- 195u, 107u, 177u, 75u,
- 185u, 255u, 184u, 202u,
- 52u, 126u, 55u, 53u,
- 255u, 197u, 105u, 79u,
- 219u, 3u, 193u, 180u,
- 233u, 155u, 132u, 59u,
- 144u, 112u, 3u, 97u,
- 88u, 38u, 0u, 66u,
- 115u, 81u, 153u, 147u,
- 1u, 161u, 137u, 125u,
- 167u, 174u, 227u, 205u,
- 82u, 125u, 40u, 157u,
- 121u, 144u, 94u, 101u,
- 150u, 200u, 26u, 164u,
- 160u, 119u, 190u, 158u,
- 123u, 133u, 1u, 128u,
- 162u, 117u, 29u, 64u,
- 0u, 134u, 67u, 136u,
- 71u, 63u, 217u, 132u,
- 140u, 140u, 23u, 151u,
- 193u, 134u, 127u, 65u,
- 180u, 133u, 74u, 171u,
- 177u, 168u, 148u, 150u,
- 255u, 163u, 58u, 131u,
- 166u, 124u, 75u, 153u,
- 124u, 148u, 138u, 99u,
- 127u, 182u, 129u, 255u,
- 163u, 119u, 175u, 109u,
- 105u, 178u, 13u, 116u,
- 165u, 180u, 69u, 234u,
- 86u, 96u, 114u, 127u,
- 78u, 142u, 0u, 87u,
- 13u, 152u, 139u, 117u,
- 171u, 125u, 105u, 68u,
- 1u, 61u, 186u, 127u,
- 147u, 112u, 182u, 118u,
- 61u, 255u, 62u, 86u,
- 137u, 104u, 123u, 155u,
- 92u, 60u, 231u, 124u,
- 135u, 180u, 166u, 158u,
- 145u, 92u, 158u, 94u,
- 230u, 255u, 112u, 191u,
- 84u, 195u, 86u, 244u,
- 181u, 163u, 36u, 112u,
- 255u, 86u, 225u, 116u,
- 87u, 196u, 196u, 199u,
- 28u, 251u, 147u, 153u,
- 58u, 124u, 15u, 246u,
- 192u, 153u, 66u, 162u,
- 1u, 60u, 167u, 116u,
- 141u, 60u, 99u, 60u,
- 130u, 110u, 138u, 124u,
- 191u, 151u, 169u, 74u,
- 113u, 146u, 131u, 72u,
- 187u, 142u, 192u, 160u,
- 207u, 0u, 98u, 232u,
- 98u, 114u, 214u, 74u,
- 122u, 105u, 117u, 112u,
- 34u, 120u, 87u, 71u,
- 1u, 113u, 200u, 230u,
- 66u, 103u, 130u, 61u,
- 177u, 98u, 135u, 150u,
- 60u, 88u, 81u, 140u,
- 133u, 219u, 1u, 166u,
- 111u, 159u, 83u, 131u,
- 34u, 116u, 104u, 212u,
- 111u, 213u, 255u, 111u,
- 99u, 99u, 103u, 153u,
- 208u, 153u, 148u, 1u,
- 73u, 194u, 151u, 115u,
- 43u, 117u, 136u, 194u,
- 128u, 167u, 161u, 185u,
- 101u, 157u, 115u, 255u,
- 26u, 159u, 78u, 152u,
- 93u, 171u, 123u, 57u,
- 133u, 52u, 33u, 113u,
- 97u, 205u, 123u, 67u,
- 83u, 41u, 255u, 125u,
- 134u, 198u, 233u, 115u,
- 79u, 108u, 171u, 171u,
- 143u, 96u, 76u, 151u,
- 155u, 147u, 255u, 116u,
- 124u, 161u, 42u, 154u,
- 199u, 167u, 212u, 93u,
- 57u, 136u, 255u, 73u,
- 190u, 234u, 129u, 51u,
- 227u, 128u, 200u, 214u,
- 186u, 67u, 49u, 142u,
- 91u, 187u, 91u, 88u,
- 68u, 155u, 162u, 117u,
- 88u, 60u, 135u, 170u,
- 204u, 119u, 1u, 114u,
- 7u, 112u, 185u, 7u,
- 157u, 98u, 68u, 126u,
- 80u, 120u, 141u, 214u,
- 120u, 1u, 224u, 235u,
- 70u, 154u, 159u, 60u,
- 180u, 107u, 144u, 106u,
- 166u, 87u, 255u, 81u,
- 150u, 192u, 156u, 162u,
- 58u, 146u, 167u, 85u,
- 160u, 51u, 149u, 57u,
- 94u, 18u, 147u, 82u,
- 100u, 255u, 37u, 73u,
- 144u, 120u, 231u, 126u,
- 255u, 116u, 70u, 161u,
- 150u, 227u, 141u, 111u,
- 61u, 184u, 83u, 136u,
- 114u, 170u, 98u, 72u,
- 1u, 182u, 51u, 169u,
- 135u, 106u, 195u, 117u,
- 121u, 153u, 146u, 162u,
- 100u, 85u, 8u, 255u,
- 153u, 115u, 182u, 146u,
- 20u, 199u, 122u, 155u,
- 127u, 156u, 140u, 152u,
- 174u, 239u, 123u, 43u,
- 225u, 111u, 161u, 97u,
- 163u, 255u, 107u, 154u,
- 170u, 145u, 141u, 62u,
- 102u, 123u, 111u, 228u,
- 107u, 140u, 173u, 155u,
- 110u, 134u, 52u, 0u,
- 109u, 73u, 65u, 165u,
- 139u, 218u, 227u, 47u,
- 33u, 171u, 248u, 242u,
- 39u, 116u, 193u, 255u,
- 187u, 34u, 108u, 206u,
- 58u, 34u, 92u, 255u,
- 193u, 52u, 169u, 96u,
- 78u, 228u, 34u, 241u,
- 190u, 105u, 138u, 138u,
- 127u, 175u, 153u, 102u,
- 255u, 24u, 91u, 105u,
- 10u, 86u, 33u, 140u,
- 142u, 246u, 105u, 56u,
- 14u, 255u, 49u, 174u,
- 20u, 199u, 248u, 138u,
- 85u, 25u, 239u, 204u,
- 165u, 209u, 106u, 211u,
- 155u, 143u, 249u, 21u,
- 189u, 206u, 255u, 177u,
- 159u, 84u, 243u, 229u,
- 84u, 168u, 148u, 239u,
- 87u, 218u, 131u, 255u,
- 101u, 55u, 60u, 63u,
- 42u, 205u, 106u, 69u,
- 175u, 140u, 186u, 92u,
- 151u, 99u, 120u, 182u,
- 148u, 5u, 144u, 96u,
- 168u, 127u, 105u, 131u,
- 141u, 198u, 77u, 1u,
- 217u, 248u, 66u, 136u,
- 98u, 75u, 116u, 255u,
- 173u, 108u, 234u, 154u,
- 174u, 11u, 156u, 73u,
- 251u, 87u, 105u, 1u,
- 32u, 46u, 200u, 239u,
- 159u, 179u, 211u, 136u,
- 123u, 187u, 31u, 89u,
- 94u, 123u, 53u, 102u,
- 226u, 163u, 43u, 78u,
- 137u, 76u, 151u, 196u,
- 100u, 236u, 91u, 1u,
- 1u, 225u, 72u, 199u,
- 144u, 124u, 112u, 118u,
- 83u, 232u, 189u, 208u,
- 104u, 138u, 5u, 199u,
- 125u, 98u, 59u, 117u,
- 124u, 40u, 140u, 83u,
- 121u, 79u, 187u, 255u,
- 104u, 72u, 48u, 253u,
- 169u, 185u, 108u, 60u,
- 209u, 1u, 198u, 50u,
- 26u, 101u, 129u, 185u,
- 43u, 108u, 220u, 12u,
- 140u, 119u, 255u, 85u,
- 128u, 89u, 112u, 102u,
- 113u, 137u, 93u, 136u,
- 234u, 188u, 114u, 199u,
- 145u, 52u, 1u, 208u,
- 108u, 70u, 147u, 148u,
- 154u, 134u, 147u, 184u,
- 118u, 123u, 173u, 115u,
- 50u, 74u, 136u, 153u,
- 255u, 215u, 27u, 25u,
- 130u, 98u, 232u, 153u,
- 153u, 56u, 156u, 211u,
- 89u, 118u, 149u, 19u,
- 1u, 8u, 249u, 244u,
- 138u, 76u, 188u, 185u,
- 10u, 156u, 172u, 213u,
- 5u, 81u, 1u, 108u,
- 155u, 207u, 97u, 104u,
- 192u, 95u, 144u, 129u,
- 136u, 32u, 125u, 233u,
- 70u, 184u, 139u, 26u,
- 142u, 86u, 147u, 211u,
- 1u, 181u, 140u, 239u,
- 86u, 223u, 64u, 80u,
- 29u, 1u, 99u, 56u,
- 181u, 155u, 30u, 133u,
- 183u, 158u, 142u, 68u,
- 139u, 62u, 144u, 174u,
- 171u, 169u, 61u, 44u,
- 117u, 121u, 247u, 15u,
- 125u, 116u, 237u, 210u,
- 255u, 76u, 11u, 189u,
- 108u, 95u, 68u, 167u,
- 222u, 135u, 41u, 91u,
- 15u, 255u, 169u, 86u,
- 217u, 76u, 174u, 191u,
- 176u, 99u, 76u, 229u,
- 255u, 122u, 161u, 112u,
- 97u, 92u, 71u, 76u,
- 146u, 162u, 154u, 20u,
- 124u, 139u, 190u, 71u,
- 139u, 187u, 150u, 102u,
- 130u, 1u, 85u, 98u,
- 161u, 161u, 76u, 139u,
- 166u, 99u, 9u, 125u,
- 41u, 110u, 164u, 178u,
- 173u, 255u, 184u, 173u,
- 46u, 167u, 121u, 77u,
- 105u, 132u, 128u, 79u,
- 50u, 181u, 121u, 255u,
- 117u, 170u, 142u, 171u,
- 66u, 63u, 149u, 149u,
- 93u, 208u, 115u, 0u,
- 112u, 142u, 189u, 199u,
- 30u, 39u, 159u, 130u,
- 134u, 135u, 151u, 189u,
- 52u, 74u, 160u, 50u,
- 232u, 171u, 113u, 93u,
- 255u, 57u, 196u, 156u,
- 35u, 108u, 119u, 130u,
- 54u, 102u, 63u, 255u,
- 44u, 78u, 90u, 73u,
- 130u, 116u, 101u, 59u,
- 71u, 120u, 219u, 172u,
- 255u, 110u, 153u, 227u,
- 77u, 63u, 32u, 139u,
- 122u, 59u, 124u, 59u,
- 134u, 22u, 1u, 70u,
- 255u, 25u, 190u, 156u,
- 87u, 60u, 82u, 104u,
- 88u, 84u, 44u, 96u,
- 67u, 77u, 145u, 3u,
- 155u, 28u, 192u, 107u,
- 102u, 80u, 178u, 73u,
- 89u, 157u, 79u, 255u,
- 91u, 221u, 40u, 163u,
- 56u, 221u, 210u, 54u,
- 64u, 146u, 1u, 125u,
- 130u, 189u, 145u, 84u,
- 80u, 85u, 134u, 142u,
- 228u, 90u, 91u, 164u,
- 147u, 70u, 1u, 244u,
- 114u, 8u, 85u, 147u,
- 50u, 68u, 87u, 141u,
- 46u, 90u, 71u, 113u,
- 92u, 42u, 78u, 139u,
- 167u, 142u, 141u, 198u,
- 84u, 109u, 73u, 1u,
- 64u, 103u, 204u, 113u,
- 1u, 120u, 152u, 195u,
- 174u, 123u, 221u, 195u,
- 98u, 111u, 174u, 168u,
- 134u, 108u, 86u, 92u,
- 142u, 120u, 25u, 167u,
- 145u, 1u, 125u, 105u,
- 35u, 131u, 143u, 236u,
- 132u, 116u, 94u, 72u,
- 91u, 63u, 64u, 0u,
- 189u, 128u, 143u, 170u,
- 93u, 128u, 139u, 107u,
- 127u, 102u, 173u, 159u,
- 19u, 108u, 117u, 220u,
- 147u, 220u, 193u, 17u,
- 150u, 55u, 255u, 90u,
- 147u, 133u, 189u, 32u,
- 242u, 239u, 142u, 255u,
- 88u, 74u, 128u, 156u,
- 169u, 228u, 102u, 148u,
- 109u, 116u, 79u, 137u,
- 1u, 82u, 186u, 206u,
- 45u, 194u, 92u, 84u,
- 59u, 30u, 71u, 190u,
- 0u, 189u, 160u, 86u,
- 39u, 160u, 148u, 195u,
- 11u, 222u, 165u, 99u,
- 154u, 89u, 186u, 72u,
- 70u, 114u, 193u, 174u,
- 69u, 211u, 10u, 192u,
- 114u, 189u, 140u, 91u,
- 91u, 145u, 255u, 226u,
- 55u, 162u, 182u, 255u,
- 24u, 165u, 130u, 243u,
- 124u, 173u, 179u, 122u,
- 25u, 61u, 172u, 236u,
- 70u, 139u, 150u, 154u,
- 65u, 255u, 119u, 115u,
- 96u, 65u, 120u, 123u,
- 196u, 175u, 95u, 149u,
- 174u, 128u, 178u, 179u,
- 4u, 171u, 209u, 21u,
- 1u, 183u, 78u, 149u,
- 232u, 42u, 126u, 218u,
- 47u, 208u, 85u, 251u,
- 126u, 50u, 1u, 190u,
- 95u, 147u, 253u, 150u,
- 187u, 61u, 114u, 153u,
- 7u, 187u, 13u, 69u,
- 110u, 135u, 61u, 107u,
- 92u, 160u, 161u, 1u,
- 236u, 178u, 105u, 113u,
- 255u, 198u, 89u, 112u,
- 131u, 94u, 103u, 156u,
- 116u, 98u, 223u, 132u,
- 87u, 143u, 83u, 102u,
- 91u, 134u, 107u, 87u,
- 255u, 77u, 213u, 172u,
- 119u, 36u, 111u, 115u,
- 102u, 132u, 98u, 134u,
- 59u, 122u, 255u, 52u,
- 126u, 226u, 151u, 164u,
- 144u, 154u, 250u, 135u,
- 222u, 185u, 105u, 102u,
- 238u, 112u, 110u, 115u,
- 95u, 70u, 87u, 178u,
- 169u, 112u, 255u, 211u,
- 53u, 191u, 87u, 111u,
- 39u, 148u, 3u, 166u,
- 99u, 255u, 1u, 26u,
- 106u, 206u, 171u, 74u,
- 182u, 112u, 218u, 89u,
- 101u, 208u, 108u, 112u,
- 44u, 255u, 114u, 63u,
- 51u, 79u, 131u, 137u,
- 197u, 128u, 217u, 105u,
- 113u, 153u, 122u, 193u,
- 58u, 82u, 178u, 28u,
- 85u, 70u, 114u, 93u,
- 255u, 102u, 193u, 11u,
- 108u, 43u, 72u, 132u,
- 74u, 167u, 18u, 8u,
- 178u, 173u, 199u, 1u,
- 161u, 206u, 228u, 220u,
- 126u, 127u, 110u, 196u,
- 1u, 121u, 73u, 150u,
- 118u, 139u, 194u, 126u,
- 154u, 66u, 100u, 109u,
- 205u, 112u, 69u, 98u,
- 54u, 35u, 114u, 141u,
- 166u, 192u, 235u, 95u,
- 120u, 120u, 255u, 142u,
- 177u, 41u, 192u, 105u,
- 129u, 27u, 100u, 21u,
- 50u, 226u, 32u, 200u,
- 65u, 77u, 0u, 45u,
- 208u, 141u, 162u, 152u,
- 163u, 166u, 132u, 167u,
- 122u, 146u, 212u, 213u,
- 230u, 148u, 89u, 0u,
- 116u, 92u, 98u, 172u,
- 165u, 85u, 56u, 114u,
- 39u, 255u, 76u, 193u,
- 112u, 136u, 88u, 88u,
- 142u, 17u, 109u, 137u,
- 163u, 161u, 63u, 169u,
- 122u, 99u, 110u, 192u,
- 114u, 255u, 120u, 130u,
- 159u, 88u, 118u, 1u,
- 140u, 154u, 61u, 186u,
- 143u, 88u, 188u, 172u,
- 61u, 151u, 112u, 173u,
- 36u, 48u, 77u, 220u,
- 129u, 69u, 44u, 67u,
- 142u, 131u, 163u, 116u,
- 114u, 1u, 123u, 162u,
- 255u, 100u, 208u, 193u,
- 58u, 195u, 104u, 173u,
- 176u, 124u, 80u, 30u,
- 153u, 98u, 136u, 132u,
- 155u, 149u, 122u, 115u,
- 20u, 108u, 61u, 135u,
- 162u, 146u, 255u, 173u,
- 88u, 106u, 156u, 123u,
- 79u, 162u, 1u, 167u,
- 41u, 109u, 110u, 208u,
- 80u, 89u, 83u, 103u,
- 105u, 52u, 110u, 127u,
- 34u, 119u, 92u, 103u,
- 160u, 212u, 155u, 255u,
- 132u, 67u, 156u, 130u,
- 159u, 152u, 57u, 142u,
- 158u, 170u, 1u, 154u,
- 128u, 66u, 91u, 114u,
- 156u, 243u, 176u, 189u,
- 126u, 58u, 205u, 188u,
- 125u, 211u, 1u, 111u,
- 78u, 25u, 16u, 23u,
- 97u, 181u, 198u, 182u,
- 73u, 55u, 84u, 81u,
- 127u, 84u, 255u, 163u,
- 76u, 215u, 152u, 157u,
- 112u, 123u, 54u, 108u,
- 133u, 96u, 107u, 59u,
- 77u, 103u, 113u, 51u,
- 23u, 158u, 152u, 255u,
- 161u, 96u, 67u, 133u,
- 92u, 3u, 125u, 60u,
- 126u, 192u, 207u, 42u,
- 47u, 99u, 94u, 153u,
- 64u, 20u, 173u, 118u,
- 255u, 114u, 125u, 69u,
- 33u, 116u, 145u, 113u,
- 141u, 143u, 246u, 171u,
- 1u, 234u, 3u, 39u,
- 222u, 85u, 171u, 125u,
- 147u, 142u, 255u, 52u,
- 152u, 170u, 153u, 228u,
- 175u, 115u, 144u, 124u,
- 44u, 165u, 110u, 145u,
- 203u, 72u, 255u, 187u,
- 149u, 245u, 227u, 59u,
- 86u, 26u, 48u, 120u,
- 159u, 226u, 137u, 132u,
- 81u, 114u, 124u, 37u,
- 169u, 47u, 172u, 150u,
- 167u, 213u, 93u, 150u,
- 126u, 1u, 143u, 144u,
- 150u, 209u, 125u, 142u,
- 255u, 180u, 108u, 85u,
- 82u, 155u, 30u, 87u,
- 165u, 181u, 142u, 92u,
- 255u, 143u, 135u, 172u,
- 160u, 136u, 110u, 160u,
- 189u, 99u, 157u, 143u,
- 37u, 89u, 50u, 113u,
- 232u, 122u, 255u, 179u,
- 161u, 62u, 47u, 49u,
- 176u, 96u, 83u, 43u,
- 231u, 169u, 122u, 125u,
- 73u, 180u, 206u, 154u,
- 87u, 125u, 243u, 193u,
- 192u, 1u, 208u, 197u,
- 74u, 60u, 45u, 188u,
- 165u, 160u, 92u, 222u,
- 130u, 234u, 121u, 136u,
- 1u, 83u, 149u, 78u,
- 181u, 95u, 171u, 160u,
- 125u, 200u, 123u, 153u,
- 199u, 83u, 91u, 183u,
- 78u, 101u, 80u, 51u,
- 1u, 255u, 25u, 12u,
- 231u, 64u, 141u, 217u,
- 159u, 1u, 79u, 86u,
- 171u, 171u, 59u, 114u,
- 167u, 86u, 61u, 31u,
- 100u, 163u, 120u, 255u,
- 185u, 143u, 124u, 129u,
- 110u, 137u, 26u, 122u,
- 160u, 212u, 162u, 146u,
- 183u, 9u, 241u, 182u,
- 74u, 68u, 139u, 143u,
- 255u, 105u, 132u, 85u,
- 186u, 119u, 96u, 121u,
- 172u, 123u, 93u, 130u,
- 183u, 1u, 142u, 32u,
- 69u, 151u, 117u, 6u,
- 25u, 87u, 130u, 76u,
- 104u, 85u, 118u, 133u,
- 78u, 117u, 83u, 1u,
- 112u, 201u, 97u, 78u,
- 126u, 123u, 115u, 137u,
- 139u, 181u, 223u, 71u,
- 51u, 182u, 1u, 151u,
- 55u, 130u, 203u, 154u,
- 128u, 166u, 134u, 167u,
- 255u, 214u, 150u, 162u,
- 199u, 100u, 89u, 195u,
- 55u, 171u, 154u, 133u,
- 150u, 90u, 110u, 173u,
- 41u, 165u, 117u, 205u,
- 51u, 92u, 78u, 95u,
- 115u, 221u, 213u, 95u,
- 124u, 0u, 121u, 176u,
- 220u, 101u, 159u, 61u,
- 70u, 170u, 150u, 105u,
- 121u, 137u, 101u, 80u,
- 0u, 226u, 146u, 116u,
- 95u, 52u, 0u, 179u,
- 90u, 74u, 99u, 159u,
- 202u, 172u, 149u, 165u,
- 99u, 181u, 41u, 103u,
- 19u, 86u, 97u, 38u,
- 152u, 156u, 121u, 255u,
- 87u, 162u, 200u, 164u,
- 147u, 97u, 176u, 158u,
- 94u, 119u, 108u, 94u,
- 170u, 63u, 200u, 111u,
- 192u, 120u, 113u, 184u,
- 1u, 140u, 171u, 128u,
- 153u, 163u, 129u, 128u,
- 134u, 183u, 186u, 20u,
- 165u, 255u, 109u, 69u,
- 148u, 107u, 221u, 55u,
- 160u, 188u, 61u, 225u,
- 113u, 71u, 114u, 203u,
- 38u, 255u, 154u, 117u,
- 116u, 81u, 73u, 108u,
- 184u, 32u, 1u, 215u,
- 130u, 75u, 197u, 101u,
- 78u, 88u, 0u, 145u,
- 131u, 111u, 157u, 188u,
- 200u, 36u, 118u, 158u,
- 1u, 105u, 169u, 117u,
- 230u, 189u, 133u, 146u,
- 118u, 41u, 175u, 212u,
- 175u, 56u, 182u, 96u,
- 117u, 180u, 0u, 28u,
- 98u, 220u, 146u, 72u,
- 82u, 150u, 54u, 193u,
- 112u, 131u, 111u, 87u,
- 124u, 255u, 148u, 201u,
- 163u, 85u, 60u, 131u,
- 114u, 206u, 30u, 204u,
- 140u, 98u, 1u, 144u,
- 192u, 121u, 193u, 125u,
- 166u, 199u, 125u, 132u,
- 135u, 152u, 169u, 81u,
- 136u, 115u, 108u, 131u,
- 78u, 157u, 114u, 223u,
- 165u, 123u, 151u, 90u,
- 0u, 127u, 44u, 116u,
- 80u, 107u, 59u, 255u,
- 18u, 82u, 133u, 78u,
- 145u, 150u, 90u, 99u,
- 93u, 83u, 102u, 156u,
- 108u, 91u, 173u, 1u,
- 192u, 84u, 116u, 240u,
- 206u, 112u, 226u, 148u,
- 126u, 231u, 98u, 45u,
- 136u, 102u, 33u, 161u,
- 79u, 137u, 52u, 187u,
- 143u, 155u, 45u, 52u,
- 33u, 55u, 177u, 255u,
- 42u, 92u, 153u, 110u,
- 245u, 154u, 228u, 73u,
- 128u, 56u, 177u, 21u,
- 136u, 255u, 39u, 186u,
- 159u, 210u, 113u, 65u,
- 45u, 225u, 1u, 176u,
- 156u, 101u, 190u, 63u,
- 130u, 95u, 93u, 252u,
- 232u, 1u, 208u, 206u,
- 191u, 100u, 103u, 107u,
- 156u, 220u, 143u, 148u,
- 82u, 117u, 96u, 147u,
- 69u, 89u, 1u, 169u,
- 52u, 178u, 199u, 126u,
- 145u, 134u, 48u, 75u,
- 60u, 133u, 91u, 119u,
- 83u, 251u, 60u, 160u,
- 215u, 112u, 53u, 74u,
- 109u, 44u, 1u, 113u,
- 181u, 138u, 142u, 152u,
- 166u, 88u, 106u, 127u,
- 255u, 130u, 127u, 91u,
- 127u, 121u, 73u, 46u,
- 246u, 177u, 139u, 73u,
- 72u, 172u, 97u, 142u,
- 124u, 116u, 1u, 101u,
- 108u, 195u, 197u, 120u,
- 94u, 176u, 111u, 127u,
- 154u, 67u, 201u, 56u,
- 46u, 130u, 167u, 105u,
- 74u, 255u, 221u, 158u,
- 188u, 124u, 169u, 64u,
- 90u, 133u, 133u, 124u,
- 1u, 84u, 98u, 97u,
- 126u, 143u, 153u, 184u,
- 162u, 71u, 58u, 179u,
- 214u, 162u, 74u, 157u,
- 148u, 71u, 189u, 175u,
- 86u, 46u, 109u, 148u,
- 1u, 160u, 59u, 155u,
- 205u, 209u, 95u, 74u,
- 88u, 52u, 136u, 102u,
- 118u, 255u, 109u, 182u,
- 216u, 182u, 228u, 22u,
- 169u, 86u, 85u, 155u,
- 222u, 130u, 95u, 203u,
- 76u, 54u, 75u, 156u,
- 248u, 73u, 115u, 1u,
- 183u, 201u, 1u, 29u,
- 138u, 70u, 146u, 204u,
- 83u, 103u, 148u, 158u,
- 55u, 255u, 68u, 130u,
- 74u, 99u, 217u, 75u,
- 52u, 44u, 209u, 107u,
- 228u, 114u, 255u, 218u,
- 183u, 216u, 40u, 137u,
- 170u, 188u, 210u, 97u,
- 255u, 153u, 125u, 169u,
- 130u, 103u, 147u, 51u,
- 55u, 182u, 100u, 54u,
- 62u, 150u, 78u, 196u,
- 117u, 139u, 40u, 115u,
- 79u, 116u, 48u, 0u,
- 65u, 118u, 174u, 130u,
- 217u, 63u, 129u, 64u,
- 255u, 114u, 239u, 135u,
- 243u, 111u, 42u, 36u,
- 172u, 114u, 150u, 23u,
- 166u, 41u, 111u, 197u,
- 185u, 191u, 190u, 60u,
- 123u, 151u, 0u, 67u,
- 130u, 179u, 185u, 184u,
- 143u, 66u, 108u, 149u,
- 153u, 157u, 93u, 140u,
- 138u, 133u, 132u, 111u,
- 16u, 120u, 1u, 136u,
- 95u, 208u, 93u, 137u,
- 155u, 170u, 150u, 62u,
- 67u, 230u, 212u, 184u,
- 239u, 111u, 26u, 0u,
- 102u, 5u, 116u, 200u,
- 5u, 134u, 151u, 167u,
- 99u, 144u, 74u, 142u,
- 125u, 224u, 1u, 119u,
- 74u, 168u, 50u, 82u,
- 38u, 255u, 129u, 132u,
- 255u, 114u, 150u, 63u,
- 129u, 204u, 138u, 65u,
- 113u, 119u, 1u, 120u,
- 94u, 113u, 129u, 120u,
- 108u, 110u, 202u, 138u,
- 95u, 186u, 154u, 115u,
- 105u, 145u, 147u, 110u,
- 224u, 120u, 115u, 25u,
- 158u, 104u, 100u, 98u,
- 75u, 255u, 254u, 115u,
- 109u, 166u, 19u, 175u,
- 62u, 151u, 173u, 93u,
- 67u, 193u, 1u, 108u,
- 202u, 17u, 209u, 177u,
- 227u, 53u, 218u, 48u,
- 144u, 123u, 124u, 113u,
- 1u, 86u, 45u, 55u,
- 143u, 87u, 139u, 128u,
- 140u, 37u, 217u, 155u,
- 106u, 131u, 192u, 121u,
- 232u, 128u, 44u, 190u,
- 38u, 47u, 255u, 188u,
- 193u, 150u, 142u, 188u,
- 137u, 48u, 212u, 190u,
- 148u, 136u, 29u, 96u,
- 0u, 91u, 48u, 90u,
- 164u, 170u, 88u, 107u,
- 175u, 82u, 132u, 155u,
- 133u, 32u, 146u, 255u,
- 98u, 136u, 119u, 85u,
- 125u, 162u, 1u, 214u,
- 183u, 209u, 85u, 139u,
- 205u, 37u, 193u, 81u,
- 221u, 128u, 183u, 170u,
- 194u, 100u, 143u, 117u,
- 108u, 77u, 154u, 0u,
- 48u, 54u, 46u, 147u,
- 34u, 239u, 205u, 161u,
- 208u, 156u, 14u, 255u,
- 156u, 61u, 133u, 66u,
- 142u, 234u, 87u, 236u,
- 89u, 133u, 149u, 93u,
- 195u, 57u, 20u, 241u,
- 116u, 119u, 113u, 191u,
- 76u, 255u, 52u, 88u,
- 97u, 99u, 116u, 74u,
- 169u, 144u, 188u, 125u,
- 1u, 121u, 146u, 145u,
- 123u, 84u, 107u, 90u,
- 46u, 128u, 151u, 195u,
- 135u, 2u, 255u, 134u,
- 196u, 132u, 143u, 147u,
- 18u, 138u, 8u, 112u,
- 23u, 150u, 145u, 150u,
- 223u, 60u, 63u, 1u,
- 104u, 78u, 128u, 239u,
- 91u, 239u, 222u, 219u,
- 141u, 73u, 37u, 105u,
- 130u, 114u, 178u, 116u,
- 167u, 97u, 1u, 99u,
- 176u, 169u, 127u, 99u,
- 108u, 93u, 117u, 86u,
- 21u, 85u, 104u, 148u,
- 220u, 213u, 114u, 134u,
- 169u, 83u, 0u, 40u,
- 105u, 113u, 255u, 114u,
- 140u, 127u, 148u, 184u,
- 111u, 0u, 49u, 178u,
- 146u, 147u, 76u, 27u,
- 131u, 6u, 184u, 89u,
- 105u, 102u, 177u, 230u,
- 203u, 107u, 93u, 33u,
- 165u, 188u, 111u, 136u,
- 51u, 99u, 1u, 138u,
- 1u, 54u, 114u, 130u,
- 157u, 30u, 43u, 137u,
- 158u, 98u, 62u, 118u,
- 14u, 56u, 140u, 117u,
- 169u, 144u, 189u, 90u,
- 100u, 244u, 111u, 76u,
- 147u, 129u, 96u, 132u,
- 232u, 176u, 106u, 255u,
- 104u, 115u, 212u, 102u,
- 102u, 83u, 135u, 1u,
- 101u, 88u, 142u, 130u,
- 114u, 151u, 51u, 136u,
- 153u, 114u, 14u, 68u,
- 124u, 104u, 2u, 113u,
- 183u, 179u, 205u, 114u,
- 1u, 133u, 116u, 211u,
- 151u, 181u, 139u, 127u,
- 141u, 140u, 142u, 0u,
- 156u, 133u, 67u, 213u,
- 124u, 139u, 163u, 185u,
- 139u, 161u, 103u, 186u,
- 37u, 110u, 141u, 32u,
- 1u, 151u, 150u, 67u,
- 100u, 229u, 158u, 188u,
- 176u, 124u, 255u, 75u,
- 177u, 87u, 110u, 133u,
- 140u, 174u, 95u, 6u,
- 208u, 178u, 163u, 144u,
- 180u, 255u, 211u, 116u,
- 12u, 114u, 216u, 166u,
- 111u, 136u, 226u, 120u,
- 74u, 144u, 55u, 105u,
- 165u, 93u, 186u, 6u,
- 214u, 118u, 150u, 44u,
- 223u, 69u, 154u, 185u,
- 1u, 183u, 61u, 90u,
- 209u, 59u, 64u, 192u,
- 79u, 247u, 82u, 128u,
- 85u, 138u, 165u, 136u,
- 255u, 80u, 182u, 179u,
- 147u, 83u, 148u, 73u,
- 146u, 134u, 142u, 165u,
- 158u, 255u, 165u, 143u,
- 139u, 26u, 159u, 148u,
- 36u, 184u, 112u, 46u,
- 120u, 95u, 17u, 65u,
- 144u, 75u, 223u, 175u,
- 1u, 138u, 129u, 171u,
- 150u, 160u, 175u, 0u,
- 202u, 210u, 76u, 168u,
- 105u, 48u, 115u, 139u,
- 153u, 117u, 96u, 162u,
- 99u, 90u, 94u, 158u,
- 1u, 138u, 167u, 179u,
- 91u, 160u, 153u, 177u,
- 96u, 95u, 171u, 243u,
- 154u, 1u, 151u, 186u,
- 101u, 121u, 100u, 195u,
- 252u, 207u, 145u, 72u,
- 88u, 142u, 80u, 77u,
- 83u, 157u, 1u, 162u,
- 176u, 134u, 106u, 136u,
- 89u, 120u, 150u, 175u,
- 94u, 163u, 147u, 143u,
- 129u, 124u, 155u, 230u,
- 1u, 134u, 209u, 112u,
- 218u, 84u, 121u, 106u,
- 80u, 173u, 75u, 178u,
- 255u, 20u, 174u, 86u,
- 141u, 107u, 204u, 202u,
- 207u, 80u, 186u, 249u,
- 100u, 229u, 135u, 116u,
- 70u, 201u, 66u, 64u,
- 129u, 134u, 59u, 254u,
- 110u, 143u, 1u, 143u,
- 54u, 28u, 199u, 251u,
- 95u, 77u, 158u, 133u,
- 255u, 122u, 57u, 80u,
- 104u, 52u, 131u, 64u,
- 145u, 190u, 154u, 38u,
- 102u, 108u, 148u, 177u,
- 0u, 183u, 129u, 161u,
- 75u, 171u, 98u, 112u,
- 154u, 115u, 156u, 220u,
- 1u, 189u, 182u, 86u,
- 192u, 156u, 181u, 102u,
- 160u, 113u, 213u, 173u,
- 190u, 132u, 239u, 148u,
- 204u, 101u, 41u, 167u,
- 16u, 192u, 222u, 116u,
- 255u, 183u, 86u, 95u,
- 72u, 150u, 76u, 82u,
- 98u, 215u, 255u, 8u,
- 215u, 151u, 76u, 169u,
- 99u, 169u, 202u, 111u,
- 155u, 117u, 163u, 204u,
- 87u, 69u, 232u, 180u,
- 40u, 171u, 20u, 69u,
- 176u, 0u, 42u, 65u,
- 22u, 124u, 130u, 168u,
- 167u, 148u, 212u, 45u,
- 217u, 73u, 176u, 116u,
- 0u, 38u, 88u, 161u,
- 139u, 1u, 160u, 82u,
- 165u, 172u, 86u, 167u,
- 43u, 161u, 145u, 169u,
- 137u, 118u, 175u, 78u,
- 135u, 212u, 80u, 0u,
- 110u, 161u, 86u, 89u,
- 63u, 90u, 164u, 58u,
- 76u, 90u, 205u, 211u,
- 219u, 156u, 1u, 208u,
- 130u, 193u, 85u, 111u,
- 140u, 76u, 89u, 52u,
- 131u, 255u, 197u, 78u,
- 140u, 152u, 151u, 54u,
- 127u, 91u, 148u, 123u,
- 1u, 176u, 88u, 102u,
- 75u, 116u, 90u, 113u,
- 116u, 131u, 118u, 196u,
- 140u, 57u, 148u, 227u,
- 171u, 107u, 255u, 109u,
- 187u, 165u, 5u, 74u,
- 11u, 182u, 121u, 50u,
- 136u, 124u, 120u, 157u,
- 37u, 130u, 1u, 119u,
- 130u, 59u, 125u, 28u,
- 11u, 143u, 128u, 124u,
- 134u, 86u, 104u, 189u,
- 216u, 163u, 103u, 0u,
- 127u, 70u, 45u, 89u,
- 113u, 133u, 123u, 148u,
- 176u, 120u, 161u, 211u,
- 93u, 104u, 184u, 0u,
- 244u, 104u, 81u, 60u,
- 161u, 76u, 239u, 48u,
- 122u, 73u, 183u, 107u,
- 179u, 111u, 255u, 140u,
- 106u, 129u, 88u, 81u,
- 130u, 148u, 107u, 122u,
- 151u, 97u, 96u, 255u,
- 81u, 99u, 87u, 117u,
- 188u, 132u, 59u, 107u,
- 52u, 184u, 79u, 135u,
- 43u, 165u, 105u, 7u,
- 229u, 208u, 70u, 147u,
- 139u, 128u, 255u, 151u,
- 233u, 163u, 120u, 184u,
- 133u, 116u, 109u, 177u,
- 167u, 248u, 181u, 96u,
- 199u, 56u, 73u, 51u,
- 1u, 188u, 114u, 145u,
- 167u, 165u, 1u, 184u,
- 113u, 114u, 99u, 185u,
- 75u, 169u, 149u, 135u,
- 141u, 66u, 215u, 133u,
- 57u, 162u, 66u, 126u,
- 102u, 122u, 74u, 255u,
- 99u, 75u, 157u, 144u,
- 141u, 168u, 34u, 63u,
- 184u, 124u, 34u, 160u,
- 1u, 112u, 121u, 98u,
- 99u, 147u, 154u, 121u,
- 186u, 204u, 31u, 15u,
- 48u, 170u, 107u, 141u,
- 115u, 94u, 91u, 1u,
- 215u, 60u, 176u, 146u,
- 178u, 139u, 24u, 133u,
- 9u, 255u, 159u, 197u,
- 175u, 217u, 14u, 13u,
- 146u, 86u, 147u, 99u,
- 167u, 16u, 93u, 173u,
- 101u, 238u, 201u, 92u,
- 136u, 55u, 1u, 100u,
- 83u, 143u, 224u, 198u,
- 129u, 65u, 27u, 56u,
- 138u, 215u, 89u, 122u,
- 175u, 185u, 118u, 70u,
- 108u, 184u, 151u, 160u,
- 176u, 73u, 1u, 124u,
- 164u, 165u, 93u, 1u,
- 115u, 34u, 173u, 235u,
- 138u, 210u, 202u, 69u,
- 4u, 66u, 41u, 34u,
- 200u, 157u, 1u, 130u,
- 180u, 234u, 227u, 85u,
- 152u, 88u, 200u, 240u,
- 119u, 201u, 177u, 109u,
- 53u, 187u, 220u, 108u,
- 116u, 105u, 139u, 99u,
- 163u, 1u, 72u, 145u,
- 222u, 212u, 130u, 53u,
- 121u, 131u, 158u, 143u,
- 72u, 112u, 188u, 94u,
- 142u, 78u, 136u, 138u,
- 111u, 71u, 131u, 255u,
- 83u, 178u, 92u, 148u,
- 131u, 150u, 109u, 255u,
- 112u, 107u, 141u, 114u,
- 189u, 123u, 52u, 84u,
- 104u, 103u, 255u, 81u,
- 85u, 148u, 137u, 115u,
- 100u, 117u, 104u, 136u,
- 105u, 76u, 93u, 151u,
- 105u, 149u, 81u, 170u,
- 131u, 146u, 220u, 58u,
- 88u, 255u, 119u, 137u,
- 144u, 52u, 102u, 66u,
- 85u, 132u, 125u, 202u,
- 231u, 185u, 61u, 133u,
- 132u, 142u, 104u, 15u,
- 190u, 240u, 255u, 127u,
- 168u, 37u, 102u, 141u,
- 255u, 42u, 232u, 8u,
- 127u, 135u, 105u, 130u,
- 95u, 162u, 175u, 110u,
- 162u, 86u, 88u, 128u,
- 71u, 41u, 102u, 177u,
- 208u, 88u, 150u, 161u,
- 14u, 1u, 36u, 140u,
- 86u, 61u, 127u, 1u,
- 169u, 156u, 164u, 144u,
- 175u, 67u, 157u, 173u,
- 127u, 253u, 76u, 165u,
- 149u, 177u, 108u, 164u,
- 240u, 215u, 16u, 255u,
- 40u, 219u, 115u, 165u,
- 181u, 63u, 154u, 200u,
- 92u, 95u, 165u, 131u,
- 150u, 149u, 98u, 142u,
- 126u, 71u, 85u, 126u,
- 152u, 158u, 109u, 255u,
- 92u, 185u, 90u, 147u,
- 1u, 107u, 96u, 154u,
- 195u, 179u, 177u, 68u,
- 136u, 148u, 64u, 103u,
- 189u, 142u, 252u, 1u,
- 69u, 175u, 112u, 181u,
- 156u, 88u, 195u, 136u,
- 142u, 125u, 132u, 108u,
- 112u, 103u, 255u, 106u,
- 137u, 22u, 236u, 85u,
- 183u, 41u, 109u, 228u,
- 191u, 58u, 139u, 243u,
- 167u, 159u, 124u, 146u,
- 128u, 163u, 31u, 159u,
- 169u, 1u, 184u, 198u,
- 151u, 101u, 117u, 211u,
- 137u, 1u, 159u, 140u,
- 189u, 151u, 56u, 17u,
- 99u, 103u, 101u, 108u,
- 175u, 240u, 76u, 168u,
- 148u, 210u, 29u, 219u,
- 99u, 203u, 125u, 93u,
- 157u, 81u, 178u, 212u,
- 113u, 123u, 187u, 1u,
- 138u, 135u, 34u, 93u,
- 193u, 135u, 89u, 220u,
- 0u, 150u, 199u, 194u,
- 138u, 41u, 128u, 229u,
- 69u, 154u, 1u, 134u,
- 77u, 75u, 41u, 222u,
- 151u, 95u, 216u, 120u,
- 28u, 177u, 131u, 239u,
- 155u, 161u, 106u, 182u,
- 146u, 85u, 108u, 29u,
- 113u, 124u, 34u, 1u,
- 134u, 106u, 208u, 37u,
- 109u, 75u, 227u, 154u,
- 64u, 129u, 229u, 159u,
- 219u, 0u, 51u, 198u,
- 72u, 196u, 120u, 157u,
- 158u, 159u, 122u, 254u,
- 83u, 230u, 90u, 36u,
- 76u, 170u, 48u, 120u,
- 255u, 99u, 255u, 184u,
- 126u, 152u, 97u, 192u,
- 61u, 108u, 134u, 127u,
- 0u, 132u, 93u, 63u,
- 138u, 241u, 103u, 164u,
- 161u, 195u, 140u, 180u,
- 0u, 101u, 98u, 97u,
- 96u, 133u, 154u, 156u,
- 192u, 173u, 136u, 101u,
- 35u, 150u, 106u, 224u,
- 1u, 190u, 110u, 186u,
- 49u, 89u, 78u, 135u,
- 92u, 90u, 99u, 124u,
- 255u, 209u, 235u, 109u,
- 243u, 171u, 210u, 213u,
- 251u, 138u, 5u, 215u,
- 174u, 170u, 17u, 109u,
- 146u, 129u, 205u, 254u,
- 197u, 255u, 108u, 215u,
- 212u, 112u, 110u, 118u,
- 201u, 61u, 90u, 171u,
- 107u, 119u, 84u, 99u,
- 82u, 27u, 145u, 136u,
- 78u, 246u, 172u, 167u,
- 255u, 105u, 103u, 54u,
- 134u, 142u, 187u, 47u,
- 62u, 251u, 36u, 118u,
- 81u, 206u, 145u, 183u,
- 72u, 1u, 31u, 68u,
- 82u, 146u, 47u, 65u,
- 64u, 111u, 168u, 240u,
- 151u, 72u, 188u, 236u,
- 134u, 78u, 0u, 113u,
- 1u, 171u, 63u, 87u,
- 126u, 131u, 145u, 163u,
- 141u, 125u, 226u, 150u,
- 167u, 74u, 174u, 192u,
- 125u, 110u, 136u, 174u,
- 99u, 39u, 18u, 61u,
- 9u, 199u, 219u, 115u,
- 37u, 33u, 27u, 1u,
- 153u, 154u, 121u, 162u,
- 115u, 48u, 173u, 153u,
- 113u, 248u, 132u, 182u,
- 206u, 194u, 255u, 167u,
- 207u, 79u, 151u, 123u,
- 153u, 221u, 76u, 255u,
- 242u, 118u, 248u, 179u,
- 144u, 119u, 0u, 43u,
- 255u, 153u, 103u, 141u,
- 126u, 188u, 68u, 208u,
- 132u, 13u, 160u, 136u,
- 139u, 67u, 157u, 165u,
- 219u, 59u, 56u, 174u,
- 246u, 143u, 87u, 75u,
- 255u, 180u, 96u, 114u,
- 171u, 223u, 129u, 6u,
- 177u, 9u, 89u, 198u,
- 125u, 121u, 139u, 149u,
- 175u, 173u, 228u, 138u,
- 0u, 216u, 121u, 129u,
- 142u, 152u, 132u, 65u,
- 255u, 146u, 61u, 153u,
- 75u, 109u, 111u, 121u,
- 112u, 130u, 152u, 177u,
- 240u, 134u, 127u, 226u,
- 94u, 70u, 186u, 104u,
- 123u, 252u, 181u, 243u,
- 138u, 255u, 51u, 134u,
- 144u, 191u, 84u, 84u,
- 139u, 142u, 169u, 159u,
- 184u, 147u, 166u, 255u,
- 156u, 67u, 176u, 71u,
- 133u, 107u, 13u, 234u,
- 70u, 78u, 149u, 58u,
- 1u, 175u, 75u, 161u,
- 151u, 71u, 173u, 145u,
- 167u, 135u, 173u, 69u,
- 17u, 205u, 102u, 175u,
- 96u, 206u, 128u, 10u,
- 1u, 226u, 97u, 185u,
- 255u, 152u, 110u, 81u,
- 85u, 85u, 145u, 155u,
- 154u, 139u, 233u, 115u,
- 143u, 92u, 81u, 86u,
- 230u, 148u, 181u, 44u,
- 113u, 110u, 1u, 118u,
- 94u, 93u, 178u, 151u,
- 153u, 188u, 107u, 130u,
- 133u, 37u, 86u, 118u,
- 1u, 85u, 241u, 121u,
- 44u, 227u, 188u, 45u,
- 160u, 252u, 138u, 57u,
- 140u, 167u, 6u, 82u,
- 75u, 31u, 173u, 122u,
- 76u, 167u, 255u, 240u,
- 199u, 86u, 130u, 93u,
- 68u, 109u, 1u, 55u,
- 254u, 92u, 172u, 208u,
- 75u, 236u, 64u, 82u,
- 117u, 127u, 136u, 137u,
- 163u, 255u, 144u, 95u,
- 164u, 90u, 167u, 116u,
- 84u, 60u, 167u, 163u,
- 192u, 196u, 153u, 74u,
- 255u, 122u, 153u, 187u,
- 143u, 150u, 110u, 132u,
- 131u, 110u, 148u, 189u,
- 128u, 177u, 128u, 129u,
- 210u, 170u, 150u, 189u,
- 109u, 58u, 80u, 64u,
- 113u, 239u, 113u, 207u,
- 105u, 0u, 61u, 177u,
- 176u, 79u, 129u, 255u,
- 128u, 69u, 88u, 101u,
- 175u, 89u, 102u, 163u,
- 116u, 113u, 73u, 127u,
- 165u, 147u, 219u, 153u,
- 10u, 123u, 168u, 213u,
- 133u, 164u, 174u, 146u,
- 159u, 1u, 203u, 177u,
- 85u, 77u, 0u, 188u,
- 48u, 123u, 115u, 73u,
- 205u, 91u, 187u, 169u,
- 133u, 143u, 146u, 106u,
- 132u, 159u, 129u, 126u,
- 109u, 122u, 180u, 1u,
- 96u, 49u, 164u, 91u,
- 171u, 4u, 202u, 213u,
- 255u, 18u, 154u, 154u,
- 69u, 79u, 83u, 100u,
- 196u, 83u, 91u, 116u,
- 213u, 229u, 166u, 37u,
- 153u, 43u, 161u, 141u,
- 1u, 98u, 185u, 180u,
- 99u, 82u, 49u, 97u,
- 121u, 169u, 175u, 225u,
- 153u, 52u, 112u, 67u,
- 99u, 75u, 177u, 15u,
- 189u, 148u, 211u, 199u,
- 1u, 165u, 74u, 10u,
- 104u, 129u, 167u, 76u,
- 136u, 146u, 233u, 200u,
- 255u, 81u, 196u, 114u,
- 167u, 88u, 145u, 141u,
- 201u, 132u, 146u, 168u,
- 102u, 109u, 69u, 75u,
- 121u, 135u, 122u, 127u,
- 120u, 176u, 1u, 159u,
- 209u, 156u, 118u, 59u,
- 23u, 146u, 122u, 255u,
- 146u, 158u, 227u, 217u,
- 226u, 113u, 26u, 138u,
- 107u, 127u, 216u, 41u,
- 92u, 168u, 128u, 120u,
- 105u, 1u, 148u, 59u,
- 15u, 118u, 29u, 102u,
- 210u, 255u, 173u, 82u,
- 211u, 180u, 82u, 119u,
- 134u, 134u, 85u, 87u,
- 160u, 235u, 93u, 133u,
- 57u, 162u, 94u, 72u,
- 191u, 111u, 162u, 255u,
- 67u, 154u, 60u, 153u,
- 73u, 193u, 136u, 80u,
- 50u, 77u, 83u, 255u,
- 190u, 139u, 89u, 102u,
- 75u, 119u, 60u, 58u,
- 161u, 70u, 157u, 105u,
- 183u, 32u, 79u, 15u,
- 111u, 77u, 35u, 14u,
- 0u, 105u, 34u, 4u,
- 69u, 205u, 148u, 120u,
- 144u, 151u, 255u, 87u,
- 144u, 112u, 183u, 104u,
- 155u, 140u, 137u, 147u,
- 123u, 119u, 163u, 81u,
- 174u, 42u, 80u, 255u,
- 44u, 146u, 138u, 95u,
- 222u, 106u, 125u, 50u,
- 128u, 56u, 155u, 74u,
- 172u, 76u, 57u, 255u,
- 115u, 119u, 85u, 79u,
- 161u, 162u, 138u, 48u,
- 163u, 93u, 181u, 161u,
- 129u, 134u, 1u, 44u,
- 136u, 139u, 167u, 131u,
- 97u, 88u, 134u, 166u,
- 125u, 154u, 143u, 70u,
- 159u, 94u, 94u, 156u,
- 78u, 215u, 193u, 139u,
- 170u, 187u, 133u, 255u,
- 136u, 109u, 81u, 141u,
- 102u, 159u, 232u, 149u,
- 182u, 165u, 255u, 103u,
- 158u, 120u, 192u, 130u,
- 150u, 116u, 85u, 167u,
- 97u, 141u, 41u, 110u,
- 90u, 101u, 255u, 124u,
- 133u, 219u, 81u, 158u,
- 177u, 27u, 182u, 195u,
- 1u, 61u, 179u, 25u,
- 210u, 73u, 209u, 123u,
- 17u, 118u, 143u, 144u,
- 81u, 67u, 115u, 157u,
- 169u, 188u, 35u, 109u,
- 97u, 199u, 17u, 142u,
- 26u, 1u, 14u, 142u,
- 95u, 89u, 136u, 187u,
- 153u, 129u, 149u, 255u,
- 113u, 108u, 121u, 91u,
- 148u, 109u, 90u, 50u,
- 98u, 54u, 184u, 24u,
- 110u, 81u, 68u, 169u,
- 144u, 173u, 124u, 221u,
- 255u, 91u, 151u, 137u,
- 39u, 174u, 117u, 144u,
- 108u, 137u, 54u, 53u,
- 176u, 150u, 117u, 102u,
- 71u, 149u, 250u, 0u,
- 130u, 165u, 61u, 170u,
- 147u, 198u, 107u, 136u,
- 145u, 237u, 123u, 192u,
- 255u, 92u, 112u, 80u,
- 77u, 119u, 77u, 105u,
- 67u, 157u, 47u, 121u,
- 40u, 129u, 15u, 135u,
- 30u, 179u, 150u, 1u,
- 151u, 74u, 130u, 198u,
- 100u, 40u, 116u, 1u,
- 245u, 178u, 150u, 131u,
- 232u, 122u, 96u, 34u,
- 217u, 72u, 61u, 79u,
- 143u, 88u, 152u, 136u,
- 135u, 1u, 70u, 143u,
- 78u, 110u, 80u, 240u,
- 211u, 129u, 76u, 40u,
- 87u, 45u, 124u, 158u,
- 37u, 191u, 197u, 107u,
- 148u, 179u, 1u, 68u,
- 159u, 48u, 85u, 120u,
- 146u, 70u, 193u, 53u,
- 114u, 182u, 43u, 109u,
- 132u, 84u, 129u, 50u,
- 1u, 144u, 149u, 177u,
- 156u, 125u, 99u, 162u,
- 20u, 230u, 121u, 172u,
- 173u, 76u, 121u, 255u,
- 31u, 136u, 112u, 83u,
- 167u, 148u, 223u, 238u,
- 70u, 76u, 129u, 202u,
- 152u, 0u, 9u, 27u,
- 88u, 48u, 146u, 45u,
- 202u, 8u, 91u, 87u,
- 150u, 127u, 84u, 255u,
- 69u, 135u, 66u, 180u,
- 84u, 92u, 145u, 112u,
- 143u, 47u, 108u, 141u,
- 32u, 0u, 229u, 62u,
- 152u, 219u, 14u, 80u,
- 70u, 167u, 115u, 118u,
- 121u, 193u, 81u, 132u,
- 71u, 71u, 73u, 142u,
- 132u, 116u, 255u, 188u,
- 140u, 172u, 136u, 179u,
- 46u, 245u, 136u, 107u,
- 116u, 255u, 140u, 172u,
- 189u, 163u, 109u, 106u,
- 71u, 157u, 133u, 207u,
- 104u, 192u, 1u, 222u,
- 151u, 128u, 39u, 125u,
- 6u, 34u, 137u, 70u,
- 100u, 80u, 151u, 238u,
- 130u, 74u, 113u, 97u,
- 91u, 69u, 113u, 210u,
- 166u, 162u, 228u, 197u,
- 1u, 137u, 90u, 165u,
- 146u, 255u, 135u, 94u,
- 42u, 77u, 207u, 11u,
- 77u, 109u, 63u, 131u,
- 129u, 165u, 49u, 187u,
- 186u, 169u, 128u, 121u,
- 136u, 157u, 184u, 163u,
- 151u, 1u, 170u, 124u,
- 137u, 169u, 148u, 52u,
- 145u, 101u, 1u, 157u,
- 86u, 163u, 10u, 64u,
- 248u, 111u, 171u, 105u,
- 151u, 170u, 102u, 74u,
- 204u, 45u, 195u, 167u,
- 200u, 203u, 128u, 126u,
- 255u, 62u, 139u, 119u,
- 188u, 152u, 63u, 214u,
- 61u, 123u, 90u, 0u,
- 35u, 100u, 147u, 178u,
- 50u, 198u, 218u, 249u,
- 231u, 92u, 196u, 86u,
- 66u, 171u, 109u, 150u,
- 149u, 182u, 102u, 191u,
- 144u, 171u, 184u, 83u,
- 255u, 39u, 60u, 98u,
- 154u, 77u, 145u, 140u,
- 78u, 221u, 130u, 143u,
- 175u, 92u, 255u, 140u,
- 206u, 101u, 229u, 163u,
- 236u, 129u, 86u, 240u,
- 156u, 39u, 239u, 182u,
- 255u, 132u, 57u, 41u,
- 209u, 63u, 90u, 118u,
- 13u, 174u, 67u, 161u,
- 127u, 50u, 66u, 113u,
- 141u, 149u, 73u, 6u,
- 134u, 87u, 255u, 147u,
- 182u, 92u, 217u, 0u,
- 139u, 135u, 144u, 195u,
- 129u, 177u, 138u, 149u,
- 242u, 6u, 157u, 96u,
- 111u, 125u, 255u, 120u,
- 72u, 166u, 217u, 58u,
- 239u, 213u, 66u, 109u,
- 175u, 17u, 61u, 162u,
- 255u, 152u, 179u, 156u,
- 97u, 87u, 133u, 166u,
- 146u, 88u, 177u, 248u,
- 123u, 134u, 60u, 47u,
- 0u, 90u, 232u, 53u,
- 125u, 117u, 71u, 112u,
- 144u, 108u, 107u, 142u,
- 6u, 85u, 174u, 172u,
- 106u, 179u, 84u, 84u,
- 90u, 68u, 197u, 255u,
- 224u, 68u, 179u, 187u,
- 82u, 16u, 123u, 190u,
- 80u, 134u, 127u, 87u,
- 255u, 121u, 106u, 167u,
- 101u, 162u, 103u, 143u,
- 222u, 168u, 92u, 31u,
- 188u, 143u, 92u, 106u,
- 0u, 184u, 232u, 156u,
- 163u, 105u, 147u, 152u,
- 141u, 174u, 176u, 185u,
- 105u, 204u, 90u, 241u,
- 255u, 133u, 126u, 170u,
- 137u, 197u, 71u, 73u,
- 157u, 27u, 46u, 42u,
- 15u, 53u, 48u, 26u,
- 87u, 115u, 43u, 129u,
- 112u, 255u, 135u, 120u,
- 153u, 88u, 56u, 116u,
- 90u, 130u, 169u, 54u,
- 172u, 194u, 255u, 210u,
- 52u, 199u, 107u, 201u,
- 187u, 147u, 161u, 164u,
- 137u, 98u, 27u, 255u,
- 107u, 110u, 86u, 124u,
- 74u, 65u, 42u, 87u,
- 37u, 156u, 66u, 32u,
- 1u, 83u, 47u, 143u,
- 148u, 146u, 96u, 118u,
- 162u, 123u, 157u, 97u,
- 49u, 125u, 150u, 216u,
- 29u, 19u, 87u, 103u,
- 6u, 32u, 194u, 166u,
- 4u, 255u, 134u, 195u,
- 163u, 91u, 72u, 117u,
- 137u, 194u, 107u, 137u,
- 52u, 156u, 1u, 175u,
- 127u, 155u, 217u, 122u,
- 167u, 19u, 138u, 147u,
- 83u, 108u, 173u, 91u,
- 165u, 148u, 164u, 146u,
- 171u, 132u, 128u, 192u,
- 255u, 135u, 118u, 99u,
- 107u, 192u, 251u, 214u,
- 142u, 73u, 135u, 215u,
- 61u, 1u, 109u, 219u,
- 157u, 106u, 138u, 213u,
- 121u, 106u, 76u, 0u,
- 197u, 142u, 91u, 102u,
- 36u, 191u, 65u, 108u,
- 115u, 203u, 190u, 229u,
- 65u, 151u, 152u, 86u,
- 255u, 157u, 165u, 122u,
- 124u, 100u, 102u, 113u,
- 99u, 196u, 123u, 163u,
- 134u, 106u, 177u, 99u,
- 127u, 176u, 91u, 183u,
- 164u, 199u, 198u, 166u,
- 157u, 37u, 1u, 199u,
- 112u, 95u, 189u, 121u,
- 175u, 165u, 142u, 202u,
- 200u, 125u, 10u, 40u,
- 1u, 204u, 175u, 156u,
- 116u, 129u, 145u, 116u,
- 69u, 147u, 1u, 151u,
- 228u, 152u, 186u, 99u,
- 35u, 171u, 212u, 177u,
- 112u, 68u, 108u, 179u,
- 37u, 255u, 155u, 156u,
- 65u, 175u, 14u, 20u,
- 57u, 218u, 99u, 191u,
- 215u, 173u, 97u, 133u,
- 1u, 111u, 39u, 234u,
- 118u, 130u, 108u, 76u,
- 139u, 106u, 44u, 82u,
- 181u, 97u, 173u, 95u,
- 87u, 128u, 68u, 73u,
- 83u, 135u, 255u, 92u,
- 185u, 57u, 204u, 97u,
- 221u, 35u, 58u, 94u,
- 34u, 183u, 176u, 171u,
- 174u, 59u, 77u, 140u,
- 51u, 255u, 164u, 59u,
- 109u, 217u, 108u, 152u,
- 55u, 95u, 48u, 189u,
- 157u, 201u, 223u, 59u,
- 183u, 47u, 232u, 0u,
- 141u, 81u, 1u, 151u,
- 164u, 84u, 99u, 161u,
- 38u, 178u, 82u, 162u,
- 157u, 166u, 138u, 105u,
- 133u, 152u, 110u, 107u,
- 164u, 57u, 188u, 113u,
- 134u, 132u, 95u, 86u,
- 141u, 255u, 128u, 63u,
- 141u, 10u, 92u, 62u,
- 211u, 120u, 133u, 56u,
- 172u, 46u, 9u, 43u,
- 51u, 203u, 0u, 101u,
- 51u, 117u, 7u, 178u,
- 176u, 141u, 18u, 255u,
- 90u, 54u, 185u, 80u,
- 152u, 129u, 157u, 110u,
- 225u, 2u, 162u, 209u,
- 188u, 49u, 71u, 0u,
- 217u, 151u, 125u, 182u,
- 193u, 70u, 127u, 121u,
- 103u, 175u, 34u, 213u,
- 156u, 124u, 33u, 17u,
- 35u, 88u, 105u, 69u,
- 255u, 210u, 125u, 170u,
- 215u, 142u, 76u, 181u,
- 1u, 98u, 170u, 145u,
- 79u, 133u, 143u, 202u,
- 107u, 169u, 97u, 123u,
- 89u, 174u, 130u, 207u,
- 79u, 134u, 173u, 63u,
- 114u, 223u, 218u, 86u,
- 106u, 255u, 83u, 142u,
- 123u, 253u, 35u, 87u,
- 146u, 1u, 71u, 87u,
- 158u, 130u, 177u, 100u,
- 181u, 107u, 54u, 88u,
- 67u, 130u, 34u, 0u,
- 204u, 76u, 130u, 137u,
- 209u, 53u, 152u, 138u,
- 120u, 150u, 67u, 41u,
- 132u, 142u, 200u, 206u,
- 169u, 132u, 0u, 95u,
- 167u, 149u, 155u, 94u,
- 158u, 41u, 80u, 141u,
- 111u, 154u, 184u, 143u,
- 132u, 161u, 38u, 41u,
- 158u, 116u, 241u, 255u,
- 201u, 140u, 99u, 154u,
- 123u, 83u, 24u, 156u,
- 149u, 50u, 138u, 67u,
- 210u, 0u, 52u, 115u,
- 64u, 255u, 106u, 34u,
- 170u, 126u, 179u, 50u,
- 151u, 100u, 168u, 216u,
- 1u, 232u, 128u, 173u,
- 98u, 174u, 176u, 57u,
- 130u, 148u, 177u, 151u,
- 51u, 79u, 67u, 34u,
- 96u, 184u, 104u, 165u,
- 0u, 169u, 67u, 137u,
- 114u, 93u, 71u, 167u,
- 87u, 90u, 177u, 133u,
- 171u, 255u, 20u, 124u,
- 83u, 198u, 94u, 207u,
- 122u, 122u, 139u, 115u,
- 35u, 73u, 84u, 151u,
- 129u, 75u, 165u, 125u,
- 114u, 255u, 136u, 64u,
- 110u, 76u, 95u, 179u,
- 1u, 128u, 135u, 140u,
- 117u, 88u, 161u, 101u,
- 54u, 78u, 164u, 179u,
- 83u, 111u, 79u, 110u,
- 40u, 175u, 116u, 106u,
- 111u, 202u, 140u, 136u,
- 152u, 1u, 144u, 223u,
- 170u, 122u, 235u, 1u,
- 180u, 124u, 63u, 26u,
- 107u, 134u, 101u, 120u,
- 171u, 136u, 231u, 244u,
- 28u, 117u, 141u, 255u,
- 138u, 124u, 49u, 71u,
- 133u, 35u, 72u, 149u,
- 41u, 82u, 108u, 149u,
- 127u, 157u, 185u, 152u,
- 156u, 190u, 70u, 141u,
- 214u, 105u, 171u, 228u,
- 191u, 255u, 130u, 179u,
- 229u, 216u, 200u, 1u,
- 99u, 221u, 119u, 187u,
- 117u, 54u, 198u, 246u,
- 114u, 8u, 243u, 151u,
- 159u, 191u, 68u, 189u,
- 221u, 165u, 30u, 133u,
- 1u, 132u, 165u, 152u,
- 159u, 200u, 88u, 176u,
- 172u, 254u, 141u, 71u,
- 196u, 108u, 112u, 103u,
- 169u, 103u, 108u, 96u,
- 104u, 255u, 106u, 86u,
- 131u, 95u, 82u, 140u,
- 64u, 193u, 74u, 136u,
- 102u, 138u, 180u, 149u,
- 123u, 184u, 143u, 255u,
- 192u, 1u, 161u, 45u,
- 106u, 130u, 48u, 134u,
- 116u, 229u, 89u, 104u,
- 63u, 121u, 112u, 122u,
- 172u, 54u, 196u, 106u,
- 255u, 127u, 81u, 106u,
- 112u, 198u, 116u, 136u,
- 181u, 96u, 84u, 101u,
- 195u, 133u, 181u, 215u,
- 30u, 55u, 152u, 164u,
- 67u, 133u, 150u, 33u,
- 147u, 1u, 126u, 237u,
- 204u, 144u, 111u, 207u,
- 1u, 120u, 206u, 90u,
- 102u, 55u, 255u, 147u,
- 137u, 56u, 127u, 127u,
- 176u, 55u, 130u, 33u,
- 255u, 96u, 202u, 134u,
- 68u, 185u, 61u, 102u,
- 169u, 155u, 118u, 137u,
- 149u, 101u, 162u, 110u,
- 9u, 225u, 255u, 112u,
- 85u, 54u, 31u, 147u,
- 224u, 184u, 250u, 165u,
- 86u, 255u, 121u, 90u,
- 29u, 168u, 185u, 135u,
- 42u, 142u, 200u, 154u,
- 174u, 168u, 79u, 111u,
- 101u, 129u, 138u, 141u,
- 114u, 110u, 0u, 131u,
- 149u, 198u, 110u, 82u,
- 84u, 183u, 213u, 176u,
- 136u, 1u, 73u, 95u,
- 43u, 72u, 153u, 126u,
- 56u, 180u, 190u, 115u,
- 44u, 115u, 48u, 176u,
- 112u, 166u, 36u, 11u,
- 180u, 172u, 64u, 211u,
- 33u, 196u, 78u, 23u,
- 147u, 180u, 255u, 190u,
- 141u, 99u, 125u, 210u,
- 199u, 93u, 255u, 61u,
- 118u, 158u, 42u, 209u,
- 190u, 186u, 130u, 131u,
- 134u, 199u, 98u, 1u,
- 151u, 161u, 186u, 110u,
- 92u, 135u, 171u, 148u,
- 233u, 158u, 83u, 110u,
- 69u, 151u, 203u, 255u,
- 146u, 195u, 126u, 57u,
- 202u, 23u, 93u, 110u,
- 188u, 126u, 145u, 27u,
- 178u, 155u, 91u, 1u,
- 155u, 67u, 132u, 136u,
- 146u, 135u, 124u, 141u,
- 72u, 125u, 116u, 147u,
- 132u, 68u, 125u, 156u,
- 153u, 15u, 147u, 60u,
- 68u, 103u, 1u, 149u,
- 96u, 247u, 132u, 202u,
- 187u, 145u, 207u, 119u,
- 69u, 138u, 150u, 194u,
- 218u, 108u, 255u, 134u,
- 49u, 167u, 15u, 158u,
- 41u, 109u, 51u, 255u,
- 128u, 141u, 61u, 85u,
- 37u, 117u, 145u, 52u,
- 120u, 24u, 107u, 190u,
- 164u, 112u, 55u, 121u,
- 125u, 186u, 57u, 103u,
- 71u, 233u, 66u, 85u,
- 129u, 255u, 119u, 126u,
- 181u, 53u, 170u, 155u,
- 159u, 243u, 255u, 189u,
- 142u, 100u, 58u, 162u,
- 55u, 100u, 40u, 201u,
- 123u, 185u, 209u, 1u,
- 171u, 185u, 151u, 171u,
- 114u, 30u, 141u, 170u,
- 139u, 174u, 206u, 200u,
- 53u, 123u, 167u, 131u,
- 111u, 117u, 219u, 33u,
- 0u, 168u, 118u, 190u,
- 127u, 157u, 246u, 185u,
- 78u, 196u, 194u, 37u,
- 126u, 107u, 54u, 158u,
- 137u, 226u, 211u, 255u,
- 131u, 53u, 80u, 185u,
- 125u, 151u, 94u, 117u,
- 195u, 221u, 1u, 164u,
- 79u, 60u, 69u, 157u,
- 151u, 232u, 131u, 177u,
- 205u, 14u, 79u, 151u,
- 149u, 115u, 120u, 43u,
- 176u, 255u, 23u, 164u,
- 132u, 182u, 37u, 77u,
- 104u, 85u, 194u, 108u,
- 255u, 100u, 95u, 135u,
- 148u, 139u, 198u, 85u,
- 104u, 140u, 177u, 130u,
- 154u, 68u, 199u, 173u,
- 112u, 151u, 1u, 114u,
- 57u, 170u, 86u, 85u,
- 187u, 130u, 198u, 171u,
- 255u, 139u, 127u, 100u,
- 166u, 113u, 54u, 125u,
- 117u, 115u, 151u, 212u,
- 186u, 74u, 152u, 203u,
- 109u, 70u, 85u, 167u,
- 71u, 207u, 85u, 197u,
- 76u, 48u, 101u, 141u,
- 41u, 115u, 119u, 255u,
- 79u, 114u, 171u, 94u,
- 210u, 138u, 144u, 233u,
- 199u, 255u, 71u, 124u,
- 139u, 122u, 101u, 106u,
- 99u, 18u, 255u, 213u,
- 54u, 46u, 119u, 169u,
- 198u, 204u, 94u, 121u,
- 13u, 81u, 53u, 91u,
- 75u, 92u, 178u, 116u,
- 0u, 180u, 120u, 200u,
- 119u, 189u, 109u, 87u,
- 227u, 233u, 69u, 211u,
- 44u, 176u, 255u, 22u,
- 143u, 138u, 161u, 124u,
- 111u, 206u, 163u, 113u,
- 186u, 124u, 146u, 137u,
- 190u, 127u, 170u, 56u,
- 91u, 122u, 255u, 112u,
- 137u, 173u, 68u, 92u,
- 128u, 90u, 111u, 109u,
- 186u, 255u, 140u, 19u,
- 196u, 171u, 92u, 107u,
- 117u, 38u, 77u, 31u,
- 149u, 201u, 224u, 150u,
- 255u, 204u, 102u, 148u,
- 184u, 69u, 184u, 186u,
- 184u, 137u, 195u, 91u,
- 240u, 56u, 240u, 132u,
- 150u, 67u, 165u, 153u,
- 252u, 69u, 137u, 1u,
- 140u, 205u, 13u, 57u,
- 150u, 133u, 212u, 53u,
- 186u, 107u, 105u, 195u,
- 141u, 1u, 171u, 219u,
- 90u, 179u, 67u, 147u,
- 118u, 155u, 92u, 84u,
- 255u, 76u, 183u, 109u,
- 211u, 37u, 149u, 79u,
- 158u, 138u, 44u, 190u,
- 77u, 144u, 145u, 121u,
- 106u, 44u, 164u, 51u,
- 155u, 178u, 103u, 89u,
- 138u, 193u, 65u, 152u,
- 99u, 255u, 29u, 93u,
- 151u, 66u, 209u, 135u,
- 62u, 177u, 128u, 69u,
- 102u, 110u, 102u, 162u,
- 70u, 150u, 0u, 212u,
- 105u, 125u, 34u, 37u,
- 80u, 144u, 114u, 155u,
- 0u, 179u, 203u, 173u,
- 87u, 82u, 17u, 171u,
- 160u, 37u, 160u, 239u,
- 88u, 225u, 99u, 210u,
- 66u, 53u, 129u, 140u,
- 0u, 97u, 87u, 55u,
- 89u, 94u, 198u, 93u,
- 124u, 180u, 126u, 105u,
- 255u, 169u, 237u, 41u,
- 212u, 73u, 130u, 129u,
- 249u, 144u, 140u, 103u,
- 1u, 137u, 80u, 244u,
- 244u, 124u, 172u, 126u,
- 96u, 243u, 51u, 203u,
- 92u, 153u, 14u, 63u,
- 84u, 245u, 148u, 248u,
- 120u, 255u, 91u, 154u,
- 123u, 122u, 146u, 244u,
- 182u, 129u, 47u, 161u,
- 0u, 111u, 177u, 128u,
- 45u, 133u, 218u, 147u,
- 118u, 105u, 127u, 139u,
- 187u, 121u, 98u, 193u,
- 118u, 118u, 198u, 138u,
- 45u, 218u, 1u, 217u,
- 252u, 135u, 69u, 133u,
- 167u, 6u, 108u, 158u,
- 55u, 94u, 187u, 189u,
- 149u, 255u, 112u, 190u,
- 140u, 29u, 56u, 127u,
- 255u, 115u, 220u, 150u,
- 200u, 49u, 55u, 145u,
- 188u, 113u, 241u, 150u,
- 44u, 92u, 132u, 188u,
- 179u, 37u, 156u, 191u,
- 191u, 160u, 237u, 91u,
- 185u, 159u, 21u, 226u,
- 255u, 169u, 67u, 45u,
- 132u, 236u, 110u, 98u,
- 144u, 52u, 90u, 92u,
- 111u, 128u, 255u, 102u,
- 190u, 147u, 254u, 138u,
- 140u, 109u, 86u, 102u,
- 152u, 137u, 192u, 255u,
- 109u, 24u, 156u, 205u,
- 51u, 82u, 194u, 141u,
- 43u, 73u, 76u, 221u,
- 209u, 0u, 134u, 65u,
- 54u, 199u, 87u, 211u,
- 153u, 30u, 146u, 96u,
- 125u, 101u, 101u, 161u,
- 137u, 98u, 128u, 140u,
- 118u, 1u, 89u, 54u,
- 98u, 164u, 56u, 84u,
- 140u, 108u, 220u, 144u,
- 93u, 115u, 100u, 146u,
- 55u, 238u, 75u, 255u,
- 246u, 113u, 127u, 46u,
- 27u, 89u, 69u, 255u,
- 130u, 128u, 118u, 5u,
- 121u, 142u, 157u, 119u,
- 87u, 69u, 99u, 12u,
- 137u, 221u, 107u, 180u,
- 13u, 218u, 154u, 71u,
- 1u, 130u, 196u, 187u,
- 172u, 54u, 114u, 234u,
- 87u, 149u, 162u, 77u,
- 129u, 207u, 255u, 125u,
- 47u, 171u, 79u, 178u,
- 179u, 169u, 111u, 53u,
- 171u, 76u, 255u, 55u,
- 69u, 210u, 54u, 243u,
- 224u, 138u, 96u, 107u,
- 85u, 98u, 134u, 56u,
- 120u, 147u, 103u, 116u,
- 184u, 184u, 58u, 99u,
- 138u, 35u, 123u, 157u,
- 1u, 169u, 161u, 233u,
- 220u, 141u, 209u, 52u,
- 255u, 244u, 19u, 171u,
- 48u, 152u, 163u, 132u,
- 221u, 150u, 92u, 192u,
- 179u, 149u, 255u, 5u,
- 101u, 189u, 117u, 155u,
- 158u, 25u, 234u, 59u,
- 43u, 65u, 95u, 97u,
- 166u, 95u, 177u, 150u,
- 133u, 171u, 181u, 65u,
- 89u, 134u, 20u, 0u,
- 59u, 124u, 121u, 233u,
- 1u, 109u, 46u, 104u,
- 72u, 158u, 204u, 114u,
- 90u, 58u, 111u, 147u,
- 152u, 92u, 160u, 227u,
- 163u, 93u, 172u, 138u,
- 104u, 151u, 146u, 90u,
- 170u, 99u, 141u, 49u,
- 118u, 167u, 1u, 45u,
- 25u, 134u, 1u, 119u,
- 172u, 115u, 215u, 163u,
- 120u, 141u, 169u, 69u,
- 229u, 70u, 241u, 104u,
- 96u, 145u, 119u, 40u,
- 219u, 177u, 184u, 1u,
- 153u, 113u, 80u, 42u,
- 243u, 234u, 177u, 32u,
- 123u, 149u, 102u, 120u,
- 255u, 146u, 143u, 63u,
- 155u, 99u, 48u, 124u,
- 157u, 211u, 162u, 176u,
- 184u, 193u, 236u, 161u,
- 244u, 162u, 70u, 101u,
- 67u, 149u, 131u, 113u,
- 152u, 255u, 115u, 184u,
- 127u, 72u, 244u, 59u,
- 179u, 77u, 23u, 152u,
- 80u, 138u, 108u, 32u,
- 1u, 196u, 68u, 98u,
- 107u, 135u, 37u, 129u,
- 55u, 143u, 255u, 82u,
- 193u, 81u, 194u, 123u,
- 72u, 88u, 49u, 31u,
- 106u, 249u, 207u, 134u,
- 78u, 69u, 140u, 165u,
- 115u, 166u, 236u, 191u,
- 193u, 87u, 54u, 0u,
- 133u, 0u, 84u, 101u,
- 113u, 103u, 139u, 135u,
- 91u, 202u, 68u, 157u,
- 148u, 155u, 91u, 187u,
- 121u, 170u, 180u, 18u,
- 31u, 48u, 255u, 98u,
- 120u, 142u, 172u, 86u,
- 67u, 114u, 174u, 93u,
- 75u, 112u, 162u, 235u,
- 190u, 91u, 1u, 59u,
- 110u, 195u, 61u, 88u,
- 226u, 67u, 160u, 72u,
- 167u, 186u, 105u, 104u,
- 161u, 255u, 129u, 122u,
- 164u, 174u, 148u, 31u,
- 213u, 248u, 39u, 53u,
- 132u, 44u, 215u, 103u,
- 91u, 166u, 95u, 184u,
- 136u, 136u, 146u, 0u,
- 106u, 67u, 179u, 163u,
- 176u, 112u, 104u, 146u,
- 1u, 118u, 120u, 126u,
- 136u, 154u, 162u, 29u,
- 135u, 157u, 111u, 75u,
- 255u, 137u, 152u, 88u,
- 145u, 119u, 246u, 209u,
- 94u, 77u, 66u, 122u,
- 24u, 145u, 175u, 106u,
- 161u, 157u, 255u, 92u,
- 172u, 143u, 147u, 151u,
- 139u, 112u, 68u, 133u,
- 191u, 62u, 222u, 142u,
- 35u, 106u, 86u, 160u,
- 179u, 148u, 69u, 15u,
- 136u, 255u, 59u, 178u,
- 148u, 68u, 27u, 194u,
- 179u, 118u, 163u, 158u,
- 143u, 177u, 144u, 1u,
- 110u, 16u, 99u, 167u,
- 179u, 188u, 144u, 170u,
- 101u, 116u, 161u, 110u,
- 211u, 122u, 99u, 0u,
- 116u, 219u, 121u, 59u,
- 127u, 109u, 147u, 160u,
- 23u, 172u, 145u, 1u,
- 177u, 51u, 168u, 173u,
- 108u, 255u, 126u, 135u,
- 74u, 35u, 216u, 243u,
- 123u, 111u, 171u, 202u,
- 1u, 238u, 156u, 217u,
- 243u, 138u, 111u, 251u,
- 57u, 158u, 72u, 74u,
- 108u, 106u, 112u, 104u,
- 91u, 230u, 140u, 165u,
- 164u, 204u, 152u, 1u,
- 146u, 122u, 86u, 14u,
- 40u, 108u, 167u, 103u,
- 60u, 168u, 187u, 157u,
- 20u, 244u, 104u, 203u,
- 142u, 125u, 212u, 255u,
- 113u, 232u, 190u, 116u,
- 1u, 178u, 13u, 109u,
- 145u, 67u, 242u, 84u,
- 108u, 163u, 162u, 78u,
- 188u, 154u, 224u, 163u,
- 1u, 89u, 96u, 138u,
- 132u, 245u, 108u, 120u,
- 64u, 118u, 111u, 150u,
- 128u, 101u, 1u, 14u,
- 127u, 51u, 216u, 170u,
- 144u, 191u, 185u, 152u,
- 208u, 202u, 190u, 87u,
- 59u, 86u, 160u, 160u,
- 29u, 100u, 1u, 145u,
- 88u, 105u, 196u, 79u,
- 217u, 86u, 160u, 228u,
- 226u, 145u, 156u, 72u,
- 104u, 96u, 88u, 35u,
- 255u, 198u, 142u, 71u,
- 182u, 120u, 172u, 140u,
- 232u, 132u, 200u, 167u,
- 0u, 245u, 34u, 104u,
- 13u, 19u, 108u, 68u,
- 173u, 198u, 87u, 107u,
- 178u, 63u, 106u, 228u,
- 104u, 59u, 115u, 246u,
- 79u, 53u, 0u, 103u,
- 139u, 109u, 66u, 141u,
- 126u, 87u, 133u, 127u,
- 130u, 74u, 64u, 52u,
- 92u, 115u, 222u, 97u,
- 255u, 198u, 49u, 58u,
- 228u, 87u, 1u, 149u,
- 44u, 119u, 247u, 136u,
- 148u, 214u, 115u, 179u,
- 112u, 154u, 85u, 19u,
- 142u, 81u, 255u, 126u,
- 193u, 187u, 125u, 114u,
- 81u, 119u, 159u, 168u,
- 81u, 133u, 142u, 190u,
- 95u, 196u, 70u, 192u,
- 28u, 126u, 221u, 145u,
- 76u, 217u, 97u, 1u,
- 226u, 57u, 141u, 181u,
- 190u, 50u, 153u, 208u,
- 243u, 218u, 215u, 18u,
- 118u, 109u, 45u, 83u,
- 213u, 255u, 120u, 98u,
- 3u, 92u, 37u, 4u,
- 96u, 86u, 203u, 74u,
- 131u, 252u, 255u, 213u,
- 181u, 80u, 198u, 104u,
- 58u, 217u, 67u, 113u,
- 146u, 80u, 66u, 20u,
- 164u, 131u, 140u, 121u,
- 153u, 255u, 125u, 89u,
- 185u, 177u, 122u, 90u,
- 127u, 109u, 118u, 170u,
- 19u, 155u, 202u, 214u,
- 254u, 1u, 165u, 213u,
- 179u, 200u, 148u, 93u,
- 150u, 127u, 155u, 231u,
- 255u, 50u, 94u, 187u,
- 190u, 127u, 157u, 72u,
- 150u, 107u, 49u, 156u,
- 140u, 143u, 80u, 194u,
- 255u, 180u, 203u, 97u,
- 140u, 115u, 142u, 65u,
- 57u, 103u, 121u, 164u,
- 155u, 222u, 123u, 151u,
- 136u, 137u, 67u, 251u,
- 135u, 1u, 105u, 196u,
- 144u, 79u, 223u, 211u,
- 71u, 51u, 186u, 170u,
- 158u, 255u, 111u, 156u,
- 179u, 67u, 70u, 1u,
- 133u, 142u, 118u, 72u,
- 68u, 130u, 143u, 194u,
- 119u, 255u, 130u, 66u,
- 122u, 195u, 141u, 170u,
- 202u, 98u, 155u, 255u,
- 139u, 231u, 118u, 239u,
- 123u, 111u, 15u, 185u,
- 96u, 71u, 46u, 235u,
- 105u, 169u, 69u, 189u,
- 171u, 0u, 137u, 41u,
- 141u, 31u, 66u, 77u,
- 32u, 189u, 18u, 6u,
- 105u, 206u, 1u, 158u,
- 54u, 48u, 104u, 106u,
- 180u, 175u, 153u, 132u,
- 169u, 93u, 139u, 90u,
- 119u, 147u, 255u, 152u,
- 166u, 90u, 90u, 148u,
- 56u, 151u, 124u, 115u,
- 182u, 76u, 75u, 166u,
- 70u, 69u, 57u, 36u,
- 97u, 86u, 154u, 197u,
- 58u, 179u, 204u, 95u,
- 255u, 162u, 66u, 87u,
- 125u, 117u, 170u, 145u,
- 51u, 133u, 189u, 152u,
- 255u, 150u, 152u, 146u,
- 175u, 116u, 87u, 130u,
- 136u, 136u, 118u, 118u,
- 81u, 106u, 161u, 154u,
- 135u, 96u, 162u, 139u,
- 148u, 146u, 1u, 96u,
- 125u, 143u, 164u, 47u,
- 214u, 209u, 157u, 77u,
- 99u, 129u, 122u, 166u,
- 255u, 230u, 97u, 24u,
- 144u, 197u, 69u, 147u,
- 162u, 110u, 122u, 169u,
- 177u, 255u, 103u, 162u,
- 115u, 44u, 101u, 69u,
- 155u, 226u, 171u, 163u,
- 104u, 145u, 8u, 81u,
- 193u, 130u, 148u, 1u,
- 19u, 140u, 40u, 74u,
- 155u, 156u, 88u, 111u,
- 153u, 86u, 92u, 216u,
- 130u, 255u, 101u, 126u,
- 131u, 18u, 3u, 116u,
- 103u, 151u, 133u, 129u,
- 101u, 119u, 156u, 96u,
- 1u, 99u, 124u, 49u,
- 169u, 44u, 139u, 148u,
- 117u, 24u, 113u, 139u,
- 154u, 112u, 87u, 135u,
- 89u, 174u, 1u, 41u,
- 94u, 163u, 180u, 178u,
- 115u, 76u, 99u, 255u,
- 119u, 116u, 15u, 125u,
- 84u, 174u, 11u, 39u,
- 15u, 140u, 141u, 111u,
- 114u, 38u, 138u, 58u,
- 61u, 1u, 226u, 106u,
- 172u, 109u, 210u, 59u,
- 55u, 72u, 95u, 60u,
- 135u, 96u, 237u, 82u,
- 130u, 144u, 255u, 149u,
- 145u, 176u, 109u, 113u,
- 190u, 174u, 122u, 57u,
- 151u, 73u, 103u, 131u,
- 30u, 177u, 255u, 66u,
- 176u, 105u, 176u, 122u,
- 155u, 183u, 138u, 119u,
- 146u, 149u, 90u, 132u,
- 61u, 135u, 127u, 114u,
- 157u, 140u, 163u, 115u,
- 192u, 255u, 127u, 104u,
- 78u, 78u, 166u, 113u,
- 255u, 111u, 75u, 86u,
- 122u, 102u, 128u, 207u,
- 180u, 38u, 169u, 70u,
- 45u, 108u, 121u, 87u,
- 60u, 67u, 191u, 188u,
- 114u, 126u, 130u, 157u,
- 103u, 0u, 118u, 101u,
- 111u, 113u, 172u, 91u,
- 150u, 1u, 218u, 91u,
- 95u, 152u, 124u, 97u,
- 144u, 31u, 186u, 151u,
- 255u, 75u, 169u, 140u,
- 113u, 110u, 201u, 170u,
- 85u, 85u, 107u, 192u,
- 177u, 137u, 179u, 120u,
- 101u, 143u, 151u, 185u,
- 91u, 128u, 116u, 0u,
- 16u, 93u, 174u, 43u,
- 212u, 118u, 118u, 93u,
- 199u, 34u, 181u, 41u,
- 203u, 154u, 207u, 120u,
- 103u, 60u, 40u, 198u,
- 1u, 175u, 85u, 161u,
- 96u, 10u, 11u, 224u,
- 8u, 84u, 205u, 10u,
- 247u, 73u, 94u, 93u,
- 37u, 120u, 128u, 255u,
- 112u, 169u, 92u, 152u,
- 43u, 54u, 125u, 84u,
- 81u, 175u, 218u, 126u,
- 103u, 57u, 126u, 0u,
- 237u, 47u, 245u, 68u,
- 135u, 38u, 140u, 114u,
- 163u, 184u, 132u, 76u,
- 149u, 176u, 201u, 1u,
- 151u, 145u, 158u, 99u,
- 142u, 140u, 143u, 128u,
- 120u, 152u, 134u, 111u,
- 255u, 135u, 145u, 106u,
- 236u, 107u, 162u, 1u,
- 86u, 179u, 113u, 212u,
- 94u, 190u, 246u, 154u,
- 142u, 171u, 75u, 116u,
- 177u, 162u, 120u, 118u,
- 119u, 114u, 255u, 116u,
- 134u, 174u, 62u, 179u,
- 119u, 184u, 71u, 136u,
- 82u, 128u, 164u, 117u,
- 229u, 108u, 158u, 116u,
- 118u, 120u, 83u, 72u,
- 92u, 255u, 142u, 156u,
- 152u, 82u, 202u, 146u,
- 208u, 51u, 94u, 121u,
- 89u, 235u, 255u, 186u,
- 145u, 39u, 180u, 168u,
- 107u, 129u, 206u, 162u,
- 255u, 220u, 66u, 120u,
- 127u, 111u, 74u, 121u,
- 167u, 160u, 126u, 194u,
- 1u, 164u, 150u, 96u,
- 98u, 202u, 126u, 111u,
- 101u, 162u, 127u, 96u,
- 96u, 153u, 147u, 117u,
- 208u, 206u, 67u, 174u,
- 66u, 221u, 144u, 147u,
- 111u, 202u, 108u, 133u,
- 0u, 98u, 143u, 159u,
- 117u, 97u, 152u, 87u,
- 93u, 69u, 255u, 147u,
- 33u, 126u, 225u, 59u,
- 69u, 169u, 28u, 125u,
- 29u, 59u, 133u, 180u,
- 233u, 191u, 201u, 97u,
- 170u, 72u, 1u, 173u,
- 18u, 180u, 122u, 185u,
- 131u, 146u, 127u, 49u,
- 152u, 46u, 135u, 98u,
- 109u, 150u, 136u, 180u,
- 1u, 120u, 78u, 108u,
- 100u, 144u, 167u, 121u,
- 115u, 162u, 111u, 182u,
- 156u, 100u, 204u, 112u,
- 0u, 128u, 38u, 146u,
- 184u, 168u, 170u, 1u,
- 122u, 171u, 127u, 197u,
- 192u, 147u, 186u, 191u,
- 178u, 61u, 137u, 153u,
- 162u, 36u, 116u, 194u,
- 4u, 166u, 247u, 70u,
- 176u, 201u, 39u, 73u,
- 94u, 37u, 109u, 255u,
- 173u, 98u, 225u, 118u,
- 216u, 113u, 218u, 196u,
- 168u, 1u, 95u, 127u,
- 207u, 90u, 217u, 8u,
- 109u, 172u, 30u, 204u,
- 128u, 56u, 84u, 67u,
- 100u, 167u, 39u, 69u,
- 77u, 0u, 107u, 153u,
- 194u, 83u, 205u, 76u,
- 255u, 197u, 181u, 114u,
- 179u, 128u, 52u, 120u,
- 146u, 118u, 28u, 154u,
- 243u, 160u, 246u, 1u,
- 203u, 161u, 95u, 155u,
- 31u, 114u, 172u, 173u,
- 183u, 230u, 90u, 125u,
- 62u, 157u, 3u, 228u,
- 1u, 151u, 53u, 104u,
- 199u, 57u, 165u, 148u,
- 84u, 39u, 108u, 153u,
- 137u, 130u, 152u, 126u,
- 155u, 162u, 85u, 96u,
- 142u, 81u, 85u, 140u,
- 64u, 157u, 111u, 255u,
- 204u, 38u, 84u, 255u,
- 170u, 111u, 75u, 132u,
- 164u, 174u, 217u, 146u,
- 249u, 68u, 140u, 114u,
- 150u, 86u, 95u, 112u,
- 61u, 72u, 0u, 149u,
- 145u, 147u, 64u, 109u,
- 136u, 95u, 93u, 126u,
- 166u, 201u, 87u, 106u,
- 172u, 103u, 85u, 145u,
- 82u, 0u, 112u, 99u,
- 124u, 129u, 151u, 101u,
- 143u, 55u, 60u, 64u,
- 193u, 76u, 173u, 146u,
- 202u, 1u, 55u, 102u,
- 75u, 184u, 180u, 116u,
- 69u, 112u, 70u, 180u,
- 105u, 70u, 32u, 160u,
- 186u, 22u, 138u, 100u,
- 1u, 40u, 173u, 230u,
- 133u, 141u, 8u, 248u,
- 201u, 12u, 32u, 182u,
- 198u, 215u, 163u, 110u,
- 36u, 1u, 132u, 66u,
- 255u, 108u, 135u, 147u,
- 66u, 130u, 210u, 220u,
- 109u, 99u, 124u, 175u,
- 73u, 78u, 80u, 147u,
- 119u, 23u, 41u, 230u,
- 209u, 59u, 80u, 161u,
- 255u, 156u, 171u, 142u,
- 37u, 67u, 141u, 221u,
- 71u, 154u, 32u, 49u,
- 165u, 68u, 170u, 158u,
- 255u, 168u, 198u, 183u,
- 113u, 93u, 33u, 87u,
- 155u, 195u, 159u, 213u,
- 90u, 14u, 44u, 66u,
- 66u, 162u, 31u, 1u,
- 91u, 219u, 177u, 221u,
- 27u, 53u, 25u, 137u,
- 142u, 67u, 1u, 111u,
- 100u, 87u, 218u, 57u,
- 119u, 119u, 100u, 170u,
- 191u, 81u, 176u, 183u,
- 226u, 85u, 213u, 66u,
- 144u, 255u, 46u, 130u,
- 245u, 154u, 138u, 46u,
- 113u, 20u, 245u, 26u,
- 25u, 185u, 100u, 59u,
- 159u, 214u, 194u, 219u,
- 0u, 102u, 54u, 21u,
- 149u, 161u, 153u, 92u,
- 68u, 118u, 193u, 255u,
- 192u, 150u, 232u, 128u,
- 145u, 99u, 66u, 55u,
- 191u, 109u, 157u, 120u,
- 59u, 107u, 186u, 241u,
- 178u, 1u, 73u, 96u,
- 103u, 156u, 18u, 152u,
- 194u, 133u, 180u, 22u,
- 47u, 160u, 219u, 188u,
- 1u, 115u, 103u, 72u,
- 199u, 161u, 224u, 191u,
- 154u, 0u, 147u, 214u,
- 80u, 108u, 125u, 86u,
- 37u, 116u, 103u, 60u,
- 151u, 177u, 143u, 151u,
- 80u, 84u, 31u, 11u,
- 105u, 148u, 38u, 161u,
- 161u, 79u, 118u, 102u,
- 118u, 125u, 255u, 71u,
- 134u, 139u, 105u, 86u,
- 208u, 130u, 147u, 103u,
- 125u, 1u, 28u, 110u,
- 90u, 233u, 132u, 160u,
- 70u, 72u, 177u, 67u,
- 123u, 166u, 61u, 107u,
- 125u, 68u, 113u, 1u,
- 83u, 101u, 215u, 232u,
- 240u, 148u, 255u, 107u,
- 132u, 165u, 58u, 130u,
- 183u, 167u, 172u, 27u,
- 139u, 224u, 141u, 142u,
- 165u, 134u, 156u, 111u,
- 201u, 133u, 1u, 124u,
- 126u, 77u, 128u, 94u,
- 115u, 224u, 85u, 40u,
- 92u, 68u, 118u, 74u,
- 136u, 101u, 87u, 243u,
- 134u, 255u, 248u, 176u,
- 116u, 102u, 47u, 175u,
- 181u, 128u, 211u, 107u,
- 88u, 61u, 27u, 83u,
- 106u, 39u, 108u, 35u,
- 1u, 237u, 177u, 162u,
- 93u, 190u, 72u, 109u,
- 219u, 122u, 134u, 157u,
- 91u, 164u, 87u, 148u,
- 229u, 207u, 172u, 1u,
- 148u, 166u, 132u, 0u,
- 92u, 154u, 104u, 234u,
- 78u, 101u, 215u, 83u,
- 128u, 100u, 142u, 115u,
- 202u, 165u, 121u, 187u,
- 43u, 193u, 78u, 255u,
- 160u, 135u, 93u, 62u,
- 118u, 99u, 213u, 171u,
- 51u, 25u, 104u, 14u,
- 94u, 129u, 110u, 160u,
- 228u, 154u, 157u, 102u,
- 105u, 125u, 228u, 255u,
- 168u, 63u, 158u, 233u,
- 119u, 137u, 251u, 1u,
- 127u, 174u, 69u, 162u,
- 226u, 128u, 142u, 127u,
- 63u, 199u, 127u, 52u,
- 193u, 164u, 48u, 176u,
- 147u, 23u, 227u, 255u,
- 184u, 227u, 72u, 94u,
- 119u, 128u, 183u, 87u,
- 233u, 144u, 100u, 70u,
- 182u, 203u, 0u, 140u,
- 175u, 55u, 169u, 193u,
- 110u, 219u, 1u, 155u,
- 143u, 101u, 144u, 16u,
- 127u, 59u, 188u, 153u,
- 119u, 199u, 93u, 166u,
- 66u, 156u, 105u, 186u,
- 116u, 50u, 56u, 126u,
- 185u, 68u, 61u, 118u,
- 141u, 1u, 193u, 51u,
- 63u, 43u, 76u, 255u,
- 192u, 152u, 48u, 80u,
- 149u, 48u, 179u, 169u,
- 128u, 140u, 70u, 87u,
- 114u, 186u, 218u, 180u,
- 15u, 148u, 52u, 165u,
- 69u, 153u, 89u, 162u,
- 255u, 174u, 116u, 36u,
- 255u, 109u, 118u, 199u,
- 123u, 66u, 144u, 72u,
- 118u, 127u, 19u, 88u,
- 225u, 105u, 178u, 86u,
- 148u, 192u, 149u, 101u,
- 255u, 150u, 85u, 115u,
- 123u, 107u, 148u, 84u,
- 140u, 67u, 105u, 104u,
- 90u, 187u, 66u, 115u,
- 114u, 237u, 108u, 100u,
- 201u, 42u, 226u, 255u,
- 28u, 143u, 133u, 207u,
- 158u, 143u, 161u, 193u,
- 96u, 71u, 149u, 132u,
- 0u, 174u, 181u, 120u,
- 118u, 117u, 131u, 170u,
- 171u, 130u, 219u, 150u,
- 83u, 1u, 171u, 168u,
- 137u, 183u, 143u, 34u,
- 194u, 69u, 114u, 142u,
- 160u, 58u, 105u, 119u,
- 82u, 104u, 110u, 90u,
- 114u, 99u, 96u, 149u,
- 1u, 176u, 131u, 113u,
- 135u, 124u, 85u, 184u,
- 43u, 109u, 134u, 162u,
- 116u, 166u, 166u, 83u,
- 205u, 38u, 92u, 0u,
- 255u, 204u, 143u, 156u,
- 94u, 110u, 151u, 248u,
- 15u, 186u, 177u, 138u,
- 97u, 98u, 38u, 169u,
- 102u, 150u, 1u, 202u,
- 73u, 82u, 155u, 53u,
- 107u, 220u, 205u, 220u,
- 228u, 120u, 69u, 67u,
- 107u, 190u, 70u, 62u,
- 128u, 87u, 151u, 74u,
- 103u, 129u, 177u, 193u,
- 103u, 255u, 130u, 78u,
- 171u, 103u, 133u, 130u,
- 115u, 123u, 161u, 170u,
- 136u, 1u, 92u, 131u,
- 151u, 159u, 65u, 73u,
- 1u, 128u, 113u, 108u,
- 211u, 217u, 223u, 111u,
- 116u, 74u, 50u, 73u,
- 165u, 141u, 70u, 230u,
- 36u, 201u, 102u, 1u,
- 206u, 157u, 215u, 175u,
- 65u, 155u, 197u, 187u,
- 156u, 43u, 196u, 154u,
- 96u, 82u, 158u, 115u,
- 110u, 171u, 1u, 60u,
- 92u, 177u, 124u, 20u,
- 62u, 220u, 252u, 145u,
- 101u, 52u, 12u, 136u,
- 92u, 1u, 151u, 195u,
- 223u, 190u, 183u, 217u,
- 115u, 75u, 62u, 114u,
- 105u, 90u, 101u, 83u,
- 90u, 144u, 229u, 255u,
- 167u, 55u, 167u, 108u,
- 103u, 134u, 84u, 114u,
- 16u, 182u, 18u, 193u,
- 4u, 178u, 176u, 190u,
- 186u, 103u, 144u, 65u,
- 1u, 29u, 100u, 170u,
- 217u, 183u, 174u, 239u,
- 80u, 133u, 40u, 1u,
- 133u, 206u, 173u, 16u,
- 182u, 161u, 98u, 220u,
- 155u, 162u, 155u, 108u,
- 157u, 255u, 145u, 122u,
- 44u, 135u, 85u, 187u,
- 234u, 207u, 154u, 100u,
- 216u, 180u, 152u, 1u,
- 143u, 26u, 128u, 74u,
- 54u, 192u, 176u, 217u,
- 87u, 52u, 132u, 53u,
- 106u, 167u, 255u, 116u,
- 76u, 146u, 144u, 90u,
- 139u, 192u, 129u, 105u,
- 90u, 59u, 195u, 233u,
- 144u, 183u, 156u, 109u,
- 189u, 106u, 107u, 255u,
- 75u, 128u, 52u, 69u,
- 238u, 201u, 176u, 170u,
- 133u, 72u, 36u, 204u,
- 148u, 139u, 89u, 205u,
- 197u, 228u, 66u, 119u,
- 1u, 101u, 4u, 183u,
- 123u, 1u, 234u, 48u,
- 193u, 98u, 139u, 110u,
- 150u, 128u, 108u, 167u,
- 112u, 209u, 47u, 204u,
- 147u, 66u, 152u, 111u,
- 30u, 84u, 147u, 93u,
- 140u, 105u, 210u, 177u,
- 162u, 76u, 255u, 162u,
- 73u, 114u, 58u, 25u,
- 1u, 143u, 76u, 200u,
- 12u, 19u, 150u, 99u,
- 92u, 71u, 82u, 170u,
- 62u, 34u, 77u, 93u,
- 31u, 124u, 107u, 93u,
- 64u, 168u, 122u, 1u,
- 71u, 109u, 205u, 231u,
- 113u, 32u, 243u, 125u,
- 1u, 78u, 236u, 20u,
- 130u, 88u, 112u, 127u,
- 85u, 150u, 149u, 26u,
- 165u, 153u, 126u, 59u,
- 226u, 142u, 255u, 121u,
- 110u, 240u, 156u, 240u,
- 215u, 39u, 191u, 71u,
- 2u, 80u, 6u, 245u,
- 20u, 83u, 61u, 86u,
- 171u, 154u, 230u, 176u,
- 102u, 167u, 107u, 255u,
- 167u, 97u, 143u, 75u,
- 117u, 52u, 255u, 249u,
- 161u, 116u, 66u, 154u,
- 94u, 126u, 198u, 87u,
- 103u, 157u, 157u, 237u,
- 40u, 255u, 165u, 210u,
- 107u, 76u, 144u, 198u,
- 190u, 113u, 89u, 125u,
- 14u, 57u, 208u, 128u,
- 130u, 149u, 179u, 255u,
- 93u, 115u, 191u, 100u,
- 109u, 148u, 41u, 230u,
- 171u, 189u, 82u, 57u,
- 87u, 148u, 163u, 126u,
- 114u, 108u, 255u, 154u,
- 69u, 174u, 159u, 116u,
- 148u, 189u, 242u, 120u,
- 213u, 201u, 50u, 196u,
- 136u, 68u, 80u, 177u,
- 255u, 202u, 87u, 208u,
- 167u, 125u, 170u, 100u,
- 255u, 148u, 95u, 148u,
- 91u, 127u, 166u, 95u,
- 111u, 150u, 146u, 94u,
- 120u, 46u, 200u, 155u,
- 44u, 122u, 83u, 94u,
- 66u, 97u, 223u, 117u,
- 1u, 116u, 79u, 114u,
- 195u, 151u, 220u, 159u,
- 170u, 173u, 102u, 80u,
- 87u, 193u, 52u, 27u,
- 95u, 247u, 0u, 193u,
- 101u, 162u, 118u, 139u,
- 153u, 41u, 240u, 102u,
- 183u, 255u, 108u, 228u,
- 214u, 56u, 218u, 36u,
- 66u, 85u, 45u, 193u,
- 54u, 49u, 106u, 133u,
- 60u, 125u, 173u, 175u,
- 88u, 0u, 161u, 201u,
- 107u, 99u, 144u, 116u,
- 96u, 1u, 152u, 156u,
- 122u, 213u, 207u, 152u,
- 133u, 135u, 232u, 26u,
- 103u, 89u, 162u, 106u,
- 83u, 173u, 179u, 50u,
- 99u, 182u, 130u, 195u,
- 108u, 180u, 0u, 122u,
- 255u, 159u, 147u, 87u,
- 68u, 96u, 165u, 167u,
- 148u, 83u, 182u, 170u,
- 121u, 202u, 86u, 106u,
- 107u, 67u, 191u, 88u,
- 127u, 208u, 104u, 248u,
- 147u, 51u, 77u, 73u,
- 103u, 1u, 141u, 223u,
- 125u, 100u, 80u, 255u,
- 15u, 239u, 28u, 217u,
- 77u, 104u, 218u, 120u,
- 207u, 87u, 149u, 165u,
- 133u, 132u, 1u, 143u,
- 159u, 172u, 8u, 200u,
- 126u, 253u, 135u, 114u,
- 160u, 27u, 147u, 156u,
- 128u, 127u, 61u, 190u,
- 37u, 163u, 86u, 180u,
- 48u, 106u, 185u, 0u,
- 105u, 131u, 98u, 196u,
- 214u, 162u, 43u, 175u,
- 91u, 161u, 77u, 1u,
- 55u, 124u, 137u, 129u,
- 193u, 95u, 126u, 63u,
- 125u, 51u, 170u, 181u,
- 151u, 44u, 172u, 82u,
- 166u, 141u, 90u, 153u,
- 119u, 255u, 187u, 89u,
- 183u, 86u, 134u, 36u,
- 83u, 43u, 180u, 140u,
- 128u, 228u, 148u, 106u,
- 40u, 132u, 255u, 88u,
- 74u, 150u, 202u, 190u,
- 30u, 58u, 132u, 18u,
- 57u, 137u, 141u, 182u,
- 201u, 255u, 155u, 99u,
- 89u, 149u, 115u, 116u,
- 61u, 141u, 135u, 106u,
- 154u, 116u, 215u, 198u,
- 117u, 123u, 151u, 255u,
- 72u, 92u, 194u, 1u,
- 127u, 103u, 130u, 74u,
- 103u, 140u, 176u, 186u,
- 95u, 145u, 119u, 135u,
- 79u, 148u, 199u, 86u,
- 179u, 176u, 154u, 255u,
- 145u, 170u, 69u, 152u,
- 127u, 128u, 108u, 174u,
- 65u, 0u, 184u, 101u,
- 73u, 203u, 17u, 57u,
- 133u, 195u, 58u, 71u,
- 173u, 174u, 218u, 172u,
- 165u, 99u, 110u, 161u,
- 165u, 1u, 130u, 25u,
- 77u, 158u, 130u, 106u,
- 58u, 128u, 163u, 89u,
- 132u, 136u, 169u, 184u,
- 76u, 158u, 255u, 90u,
- 81u, 191u, 69u, 158u,
- 146u, 77u, 192u, 173u,
- 85u, 137u, 35u, 251u,
- 107u, 65u, 233u, 12u,
- 120u, 67u, 1u, 62u,
- 144u, 119u, 111u, 152u,
- 127u, 91u, 223u, 1u,
- 194u, 86u, 236u, 54u,
- 5u, 174u, 88u, 171u,
- 180u, 198u, 72u, 123u,
- 161u, 153u, 67u, 104u,
- 51u, 1u, 161u, 22u,
- 83u, 162u, 148u, 190u,
- 154u, 139u, 133u, 64u,
- 28u, 161u, 1u, 144u,
- 113u, 153u, 91u, 174u,
- 208u, 171u, 115u, 12u,
- 160u, 25u, 44u, 209u,
- 159u, 117u, 90u, 156u,
- 248u, 1u, 62u, 154u,
- 91u, 94u, 29u, 149u,
- 118u, 22u, 139u, 111u,
- 188u, 171u, 229u, 1u,
- 218u, 153u, 81u, 123u,
- 62u, 95u, 148u, 72u,
- 219u, 150u, 123u, 15u,
- 46u, 110u, 56u, 33u,
- 70u, 75u, 221u, 150u,
- 162u, 98u, 196u, 97u,
- 198u, 237u, 181u, 1u,
- 144u, 103u, 152u, 46u,
- 121u, 66u, 192u, 167u,
- 129u, 131u, 189u, 154u,
- 1u, 113u, 120u, 139u,
- 81u, 255u, 98u, 133u,
- 217u, 129u, 235u, 211u,
- 130u, 106u, 54u, 192u,
- 240u, 141u, 140u, 68u,
- 90u, 55u, 58u, 97u,
- 188u, 81u, 255u, 217u,
- 118u, 83u, 155u, 149u,
- 229u, 104u, 180u, 133u,
- 57u, 156u, 183u, 119u,
- 37u, 127u, 108u, 140u,
- 104u, 174u, 255u, 174u,
- 92u, 40u, 189u, 175u,
- 134u, 51u, 74u, 108u,
- 121u, 223u, 177u, 78u,
- 167u, 163u, 97u, 226u,
- 255u, 105u, 55u, 105u,
- 71u, 64u, 80u, 163u,
- 167u, 58u, 129u, 1u,
- 45u, 158u, 87u, 201u,
- 180u, 39u, 117u, 196u,
- 134u, 111u, 77u, 99u,
- 151u, 144u, 139u, 226u,
- 204u, 195u, 102u, 112u,
- 203u, 84u, 49u, 1u,
- 119u, 95u, 91u, 255u,
- 176u, 137u, 45u, 160u,
- 117u, 201u, 83u, 55u,
- 126u, 78u, 101u, 103u,
- 1u, 160u, 143u, 184u,
- 23u, 209u, 109u, 128u,
- 79u, 138u, 131u, 164u,
- 107u, 118u, 195u, 128u,
- 112u, 174u, 150u, 68u,
- 148u, 58u, 219u, 125u,
- 206u, 242u, 150u, 255u,
- 140u, 34u, 110u, 179u,
- 87u, 99u, 88u, 107u,
- 135u, 129u, 169u, 227u,
- 102u, 182u, 147u, 176u,
- 1u, 46u, 145u, 197u,
- 206u, 80u, 75u, 142u,
- 255u, 180u, 126u, 99u,
- 157u, 135u, 36u, 121u,
- 69u, 209u, 210u, 161u,
- 239u, 76u, 131u, 35u,
- 150u, 149u, 77u, 80u,
- 51u, 101u, 132u, 98u,
- 122u, 247u, 0u, 139u,
- 151u, 234u, 180u, 136u,
- 0u, 157u, 220u, 69u,
- 156u, 238u, 231u, 177u,
- 67u, 109u, 86u, 235u,
- 195u, 78u, 152u, 196u,
- 70u, 162u, 174u, 110u,
- 135u, 134u, 0u, 143u,
- 133u, 56u, 36u, 117u,
- 66u, 94u, 106u, 91u,
- 77u, 55u, 199u, 255u,
- 95u, 155u, 86u, 158u,
- 105u, 80u, 128u, 127u,
- 64u, 127u, 183u, 102u,
- 28u, 211u, 109u, 122u,
- 238u, 233u, 34u, 1u,
- 71u, 114u, 61u, 141u,
- 145u, 141u, 47u, 216u,
- 30u, 102u, 0u, 128u,
- 36u, 230u, 98u, 141u,
- 88u, 140u, 119u, 54u,
- 215u, 104u, 129u, 217u,
- 155u, 163u, 191u, 179u,
- 179u, 27u, 15u, 2u,
- 168u, 255u, 121u, 3u,
- 114u, 69u, 126u, 117u,
- 121u, 3u, 138u, 83u,
- 118u, 255u, 142u, 228u,
- 70u, 181u, 147u, 146u,
- 120u, 151u, 54u, 18u,
- 171u, 116u, 200u, 96u,
- 133u, 226u, 255u, 249u,
- 163u, 253u, 181u, 157u,
- 1u, 101u, 153u, 139u,
- 126u, 92u, 76u, 208u,
- 120u, 149u, 146u, 152u,
- 111u, 24u, 60u, 130u,
- 255u, 102u, 182u, 65u,
- 210u, 203u, 26u, 46u,
- 134u, 133u, 96u, 191u,
- 110u, 148u, 59u, 212u,
- 225u, 114u, 18u, 246u,
- 156u, 93u, 106u, 166u,
- 126u, 128u, 119u, 32u,
- 166u, 143u, 51u, 0u,
- 178u, 86u, 255u, 164u,
- 88u, 178u, 137u, 97u,
- 142u, 21u, 108u, 104u,
- 204u, 106u, 146u, 147u,
- 149u, 81u, 103u, 1u,
- 77u, 149u, 14u, 177u,
- 136u, 91u, 227u, 94u,
- 118u, 88u, 129u, 108u,
- 114u, 160u, 78u, 87u,
- 156u, 130u, 110u, 203u,
- 105u, 255u, 138u, 74u,
- 105u, 38u, 175u, 160u,
- 114u, 122u, 126u, 123u,
- 1u, 165u, 116u, 116u,
- 43u, 185u, 101u, 78u,
- 62u, 171u, 94u, 133u,
- 166u, 115u, 96u, 200u,
- 75u, 149u, 226u, 36u,
- 34u, 158u, 64u, 185u,
- 201u, 206u, 94u, 255u,
- 188u, 206u, 119u, 134u,
- 84u, 101u, 122u, 219u,
- 176u, 1u, 71u, 24u,
- 124u, 97u, 53u, 189u,
- 149u, 69u, 1u, 221u,
- 143u, 124u, 65u, 161u,
- 133u, 127u, 62u, 43u,
- 77u, 249u, 106u, 59u,
- 229u, 120u, 195u, 103u,
- 31u, 180u, 150u, 205u,
- 144u, 87u, 171u, 1u,
- 175u, 214u, 141u, 171u,
- 65u, 133u, 62u, 253u,
- 47u, 131u, 255u, 223u,
- 116u, 109u, 132u, 177u,
- 163u, 89u, 98u, 157u,
- 63u, 127u, 168u, 48u,
- 1u, 88u, 112u, 148u,
- 152u, 130u, 125u, 145u,
- 104u, 113u, 25u, 213u,
- 121u, 145u, 105u, 27u,
- 106u, 79u, 157u, 195u,
- 1u, 148u, 135u, 76u,
- 95u, 61u, 127u, 127u,
- 255u, 81u, 17u, 98u,
- 170u, 176u, 126u, 88u,
- 24u, 181u, 2u, 184u,
- 232u, 178u, 131u, 118u,
- 219u, 190u, 0u, 160u,
- 125u, 94u, 85u, 105u,
- 165u, 236u, 217u, 105u,
- 116u, 111u, 48u, 123u,
- 79u, 1u, 243u, 109u,
- 184u, 100u, 113u, 75u,
- 60u, 150u, 57u, 67u,
- 5u, 93u, 140u, 205u,
- 40u, 50u, 112u, 131u,
- 52u, 255u, 213u, 160u,
- 232u, 156u, 86u, 110u,
- 139u, 80u, 157u, 230u,
- 98u, 121u, 24u, 125u,
- 147u, 160u, 255u, 140u,
- 158u, 63u, 143u, 193u,
- 177u, 78u, 171u, 102u,
- 155u, 31u, 198u, 147u,
- 99u, 165u, 42u, 112u,
- 99u, 140u, 114u, 115u,
- 142u, 1u, 146u, 137u,
- 43u, 91u, 188u, 152u,
- 255u, 9u, 228u, 164u,
- 174u, 118u, 128u, 190u,
- 70u, 174u, 156u, 112u,
- 98u, 157u, 255u, 20u,
- 142u, 135u, 173u, 92u,
- 105u, 23u, 73u, 117u,
- 82u, 175u, 205u, 104u,
- 55u, 225u, 23u, 146u,
- 255u, 22u, 94u, 178u,
- 113u, 58u, 110u, 182u,
- 110u, 60u, 21u, 199u,
- 185u, 216u, 92u, 107u,
- 95u, 55u, 3u, 203u,
- 67u, 164u, 255u, 133u,
- 74u, 97u, 132u, 54u,
- 142u, 80u, 51u, 132u,
- 183u, 23u, 249u, 164u,
- 223u, 59u, 59u, 161u,
- 68u, 1u, 156u, 194u,
- 128u, 134u, 44u, 161u,
- 36u, 57u, 0u, 121u,
- 2u, 93u, 119u, 116u,
- 185u, 151u, 168u, 83u,
- 104u, 126u, 103u, 185u,
- 75u, 150u, 201u, 131u,
- 130u, 255u, 76u, 109u,
- 167u, 152u, 120u, 108u,
- 1u, 148u, 102u, 152u,
- 104u, 202u, 177u, 145u,
- 170u, 229u, 140u, 107u,
- 72u, 221u, 157u, 211u,
- 75u, 154u, 136u, 102u,
- 71u, 150u, 112u, 140u,
- 158u, 136u, 173u, 172u,
- 74u, 1u, 106u, 172u,
- 109u, 152u, 1u, 134u,
- 86u, 147u, 189u, 220u,
- 25u, 84u, 130u, 121u,
- 153u, 124u, 105u, 42u,
- 148u, 162u, 194u, 1u,
- 123u, 71u, 200u, 99u,
- 42u, 207u, 179u, 248u,
- 156u, 174u, 194u, 228u,
- 160u, 183u, 185u, 0u,
- 49u, 49u, 36u, 85u,
- 120u, 192u, 149u, 112u,
- 210u, 70u, 38u, 188u,
- 160u, 114u, 127u, 114u,
- 31u, 52u, 106u, 213u,
- 98u, 143u, 178u, 116u,
- 93u, 1u, 111u, 123u,
- 142u, 158u, 186u, 67u,
- 146u, 132u, 47u, 139u,
- 198u, 173u, 180u, 131u,
- 205u, 1u, 187u, 137u,
- 197u, 73u, 87u, 246u,
- 229u, 154u, 255u, 232u,
- 39u, 166u, 16u, 187u,
- 221u, 160u, 14u, 150u,
- 93u, 30u, 70u, 208u,
- 98u, 128u, 135u, 177u,
- 1u, 68u, 65u, 75u,
- 66u, 118u, 125u, 105u,
- 137u, 108u, 143u, 158u,
- 125u, 187u, 148u, 122u,
- 167u, 114u, 255u, 103u,
- 120u, 134u, 110u, 164u,
- 106u, 186u, 184u, 91u,
- 120u, 255u, 79u, 160u,
- 131u, 119u, 91u, 114u,
- 9u, 9u, 67u, 172u,
- 116u, 148u, 143u, 255u,
- 9u, 116u, 90u, 115u,
- 105u, 84u, 149u, 126u,
- 180u, 44u, 80u, 122u,
- 100u, 35u, 240u, 107u,
- 255u, 158u, 126u, 180u,
- 242u, 180u, 94u, 201u,
- 229u, 94u, 94u, 54u,
- 128u, 155u, 120u, 157u,
- 140u, 166u, 166u, 101u,
- 135u, 1u, 134u, 196u,
- 121u, 205u, 88u, 146u,
- 135u, 120u, 131u, 90u,
- 53u, 156u, 103u, 109u,
- 101u, 120u, 255u, 130u,
- 99u, 117u, 139u, 165u,
- 110u, 113u, 218u, 255u,
- 83u, 2u, 98u, 124u,
- 48u, 233u, 181u, 101u,
- 187u, 86u, 231u, 119u,
- 33u, 94u, 1u, 146u,
- 91u, 154u, 45u, 29u,
- 146u, 127u, 136u, 140u,
- 227u, 65u, 121u, 180u,
- 96u, 193u, 180u, 111u,
- 95u, 234u, 143u, 148u,
- 169u, 255u, 137u, 50u,
- 179u, 54u, 127u, 99u,
- 110u, 50u, 255u, 101u,
- 59u, 127u, 54u, 125u,
- 16u, 148u, 159u, 84u,
- 162u, 59u, 211u, 240u,
- 131u, 78u, 159u, 104u,
- 130u, 112u, 75u, 78u,
- 184u, 21u, 255u, 73u,
- 168u, 139u, 96u, 72u,
- 185u, 91u, 81u, 201u,
- 32u, 218u, 255u, 127u,
- 35u, 171u, 5u, 93u,
- 109u, 248u, 170u, 187u,
- 146u, 148u, 175u, 195u,
- 0u, 186u, 222u, 27u,
- 151u, 222u, 149u, 126u,
- 184u, 121u, 128u, 114u,
- 143u, 245u, 29u, 128u,
- 187u, 192u, 255u, 182u,
- 31u, 214u, 54u, 187u,
- 207u, 216u, 145u, 127u,
- 173u, 184u, 187u, 82u,
- 36u, 18u, 105u, 44u,
- 1u, 121u, 198u, 44u,
- 110u, 125u, 152u, 6u,
- 157u, 120u, 84u, 56u,
- 147u, 72u, 126u, 109u,
- 150u, 155u, 255u, 108u,
- 190u, 113u, 210u, 124u,
- 78u, 69u, 32u, 219u,
- 1u, 111u, 100u, 213u,
- 71u, 125u, 114u, 101u,
- 179u, 58u, 77u, 110u,
- 209u, 163u, 171u, 153u,
- 131u, 109u, 142u, 171u,
- 126u, 0u, 183u, 158u,
- 232u, 178u, 165u, 27u,
- 89u, 119u, 1u, 220u,
- 227u, 71u, 85u, 86u,
- 171u, 250u, 114u, 183u,
- 57u, 107u, 125u, 81u,
- 115u, 75u, 181u, 1u,
- 158u, 128u, 13u, 121u,
- 198u, 65u, 202u, 83u,
- 120u, 157u, 185u, 123u,
- 25u, 157u, 86u, 84u,
- 89u, 134u, 1u, 129u,
- 171u, 1u, 144u, 115u,
- 232u, 61u, 62u, 44u,
- 88u, 155u, 176u, 86u,
- 137u, 145u, 208u, 170u,
- 89u, 200u, 1u, 221u,
- 109u, 22u, 116u, 244u,
- 183u, 158u, 109u, 148u,
- 62u, 187u, 123u, 95u,
- 154u, 140u, 57u, 71u,
- 1u, 201u, 169u, 66u,
- 144u, 198u, 162u, 71u,
- 154u, 127u, 96u, 234u,
- 255u, 69u, 229u, 243u,
- 217u, 212u, 66u, 145u,
- 195u, 255u, 78u, 193u,
- 203u, 151u, 165u, 35u,
- 131u, 95u, 80u, 99u,
- 98u, 146u, 81u, 156u,
- 54u, 89u, 126u, 151u,
- 179u, 58u, 110u, 204u,
- 82u, 108u, 44u, 108u,
- 174u, 54u, 59u, 255u,
- 58u, 242u, 136u, 118u,
- 119u, 156u, 133u, 255u,
- 224u, 209u, 57u, 201u,
- 211u, 52u, 118u, 96u,
- 140u, 232u, 167u, 97u,
- 159u, 151u, 113u, 28u,
- 126u, 109u, 116u, 91u,
- 102u, 255u, 220u, 138u,
- 184u, 52u, 6u, 255u,
- 184u, 160u, 181u, 128u,
- 107u, 156u, 29u, 68u,
- 146u, 105u, 222u, 146u,
- 185u, 95u, 214u, 71u,
- 104u, 134u, 133u, 132u,
- 146u, 255u, 161u, 160u,
- 46u, 197u, 112u, 120u,
- 249u, 172u, 188u, 132u,
- 76u, 22u, 145u, 1u,
- 8u, 92u, 119u, 139u,
- 102u, 96u, 150u, 110u,
- 91u, 236u, 153u, 173u,
- 38u, 83u, 112u, 58u,
- 1u, 230u, 126u, 109u,
- 142u, 53u, 55u, 150u,
- 81u, 62u, 125u, 55u,
- 48u, 102u, 69u, 178u,
- 117u, 146u, 255u, 173u,
- 87u, 111u, 172u, 153u,
- 112u, 99u, 151u, 71u,
- 113u, 152u, 122u, 255u,
- 105u, 200u, 143u, 91u,
- 139u, 82u, 122u, 98u,
- 121u, 157u, 1u, 159u,
- 95u, 112u, 178u, 60u,
- 70u, 115u, 166u, 162u,
- 214u, 183u, 67u, 121u,
- 157u, 195u, 135u, 146u,
- 97u, 243u, 96u, 1u,
- 150u, 105u, 255u, 56u,
- 94u, 35u, 179u, 158u,
- 140u, 131u, 170u, 80u,
- 164u, 164u, 1u, 109u,
- 198u, 96u, 108u, 131u,
- 104u, 102u, 126u, 54u,
- 158u, 88u, 248u, 86u,
- 255u, 143u, 149u, 164u,
- 209u, 143u, 52u, 90u,
- 156u, 160u, 109u, 117u,
- 51u, 84u, 5u, 0u,
- 61u, 170u, 138u, 57u,
- 129u, 132u, 215u, 212u,
- 51u, 192u, 130u, 90u,
- 224u, 98u, 199u, 139u,
- 195u, 157u, 61u, 107u,
- 128u, 42u, 131u, 95u,
- 17u, 255u, 153u, 204u,
- 14u, 96u, 30u, 1u,
- 184u, 157u, 195u, 234u,
- 142u, 161u, 50u, 142u,
- 163u, 137u, 140u, 28u,
- 18u, 108u, 201u, 135u,
- 51u, 171u, 195u, 127u,
- 111u, 121u, 155u, 116u,
- 137u, 255u, 164u, 193u,
- 137u, 255u, 156u, 103u,
- 15u, 60u, 32u, 217u,
- 111u, 145u, 201u, 11u,
- 103u, 137u, 220u, 174u,
- 138u, 168u, 176u, 93u,
- 134u, 100u, 255u, 141u,
- 167u, 119u, 120u, 127u,
- 154u, 128u, 158u, 93u,
- 114u, 107u, 103u, 166u,
- 118u, 112u, 158u, 135u,
- 76u, 116u, 1u, 130u,
- 129u, 125u, 102u, 159u,
- 107u, 52u, 53u, 177u,
- 131u, 82u, 181u, 156u,
- 162u, 146u, 89u, 0u,
- 76u, 179u, 118u, 116u,
- 106u, 60u, 123u, 142u,
- 205u, 169u, 144u, 1u,
- 192u, 71u, 96u, 86u,
- 162u, 100u, 105u, 156u,
- 213u, 118u, 255u, 171u,
- 108u, 32u, 93u, 146u,
- 131u, 197u, 113u, 25u,
- 116u, 120u, 147u, 158u,
- 206u, 85u, 111u, 192u,
- 255u, 218u, 10u, 121u,
- 90u, 123u, 147u, 197u,
- 226u, 219u, 157u, 177u,
- 150u, 205u, 142u, 124u,
- 122u, 147u, 158u, 135u,
- 142u, 160u, 116u, 117u,
- 170u, 150u, 53u, 1u,
- 99u, 1u, 116u, 199u,
- 144u, 197u, 109u, 100u,
- 142u, 125u, 137u, 124u,
- 146u, 73u, 208u, 161u,
- 120u, 255u, 211u, 64u,
- 101u, 42u, 58u, 82u,
- 145u, 6u, 75u, 35u,
- 138u, 72u, 107u, 9u,
- 149u, 134u, 1u, 132u,
- 208u, 209u, 70u, 167u,
- 142u, 170u, 43u, 224u,
- 196u, 58u, 26u, 184u,
- 85u, 131u, 251u, 82u,
- 226u, 107u, 77u, 78u,
- 80u, 48u, 68u, 36u,
- 1u, 169u, 96u, 192u,
- 59u, 98u, 87u, 145u,
- 130u, 132u, 48u, 64u,
- 255u, 116u, 98u, 132u,
- 57u, 194u, 82u, 131u,
- 108u, 199u, 55u, 83u,
- 108u, 169u, 58u, 201u,
- 106u, 175u, 148u, 191u,
- 234u, 1u, 119u, 67u,
- 96u, 106u, 161u, 132u,
- 106u, 112u, 86u, 163u,
- 60u, 155u, 117u, 1u,
- 120u, 125u, 130u, 187u,
- 124u, 106u, 123u, 108u,
- 255u, 156u, 178u, 94u,
- 205u, 60u, 58u, 197u,
- 83u, 165u, 162u, 201u,
- 67u, 207u, 52u, 62u,
- 163u, 204u, 194u, 255u,
- 137u, 105u, 121u, 158u,
- 90u, 239u, 117u, 116u,
- 80u, 190u, 169u, 162u,
- 125u, 179u, 127u, 111u,
- 186u, 64u, 131u, 71u,
- 222u, 0u, 166u, 116u,
- 153u, 171u, 255u, 7u,
- 179u, 133u, 187u, 91u,
- 199u, 138u, 24u, 123u,
- 55u, 234u, 148u, 147u,
- 64u, 137u, 165u, 147u,
- 79u, 0u, 61u, 167u,
- 121u, 75u, 129u, 78u,
- 66u, 117u, 99u, 64u,
- 135u, 169u, 85u, 131u,
- 113u, 178u, 1u, 243u,
- 80u, 107u, 107u, 153u,
- 146u, 90u, 159u, 196u,
- 164u, 91u, 216u, 118u,
- 168u, 212u, 49u, 193u,
- 77u, 119u, 192u, 127u,
- 118u, 179u, 128u, 255u,
- 116u, 36u, 150u, 224u,
- 144u, 128u, 104u, 111u,
- 146u, 208u, 182u, 1u,
- 96u, 3u, 117u, 221u,
- 89u, 94u, 80u, 135u,
- 242u, 108u, 162u, 101u,
- 63u, 30u, 156u, 152u,
- 174u, 255u, 185u, 47u,
- 103u, 205u, 250u, 43u,
- 104u, 188u, 53u, 176u,
- 164u, 144u, 157u, 243u,
- 173u, 142u, 49u, 255u,
- 57u, 142u, 119u, 111u,
- 207u, 143u, 49u, 143u,
- 206u, 164u, 184u, 181u,
- 130u, 1u, 93u, 111u,
- 122u, 160u, 110u, 111u,
- 0u, 154u, 107u, 155u,
- 129u, 174u, 171u, 135u,
- 111u, 98u, 100u, 54u,
- 189u, 85u, 248u, 172u,
- 232u, 80u, 143u, 101u,
- 118u, 127u, 169u, 255u,
- 221u, 185u, 96u, 89u,
- 25u, 137u, 58u, 114u,
- 148u, 105u, 25u, 226u,
- 160u, 37u, 22u, 150u,
- 34u, 255u, 130u, 126u,
- 13u, 132u, 126u, 146u,
- 27u, 251u, 10u, 72u,
- 182u, 223u, 255u, 140u,
- 147u, 25u, 69u, 189u,
- 68u, 176u, 113u, 148u,
- 110u, 140u, 31u, 65u,
- 172u, 153u, 193u, 105u,
- 41u, 100u, 117u, 255u,
- 181u, 94u, 131u, 192u,
- 90u, 115u, 138u, 121u,
- 166u, 192u, 61u, 82u,
- 1u, 109u, 45u, 92u,
- 123u, 98u, 170u, 68u,
- 243u, 124u, 187u, 89u,
- 206u, 147u, 101u, 255u,
- 117u, 167u, 141u, 87u,
- 147u, 139u, 158u, 149u,
- 128u, 255u, 118u, 93u,
- 158u, 122u, 140u, 138u,
- 150u, 74u, 136u, 167u,
- 188u, 137u, 1u, 239u,
- 73u, 89u, 148u, 12u,
- 121u, 181u, 226u, 106u,
- 55u, 164u, 73u, 92u,
- 62u, 142u, 121u, 200u,
- 136u, 128u, 255u, 106u,
- 117u, 186u, 23u, 116u,
- 102u, 179u, 143u, 123u,
- 6u, 120u, 145u, 137u,
- 84u, 255u, 225u, 114u,
- 246u, 144u, 137u, 48u,
- 109u, 172u, 133u, 72u,
- 114u, 157u, 124u, 131u,
- 73u, 255u, 164u, 55u,
- 153u, 59u, 203u, 184u,
- 136u, 90u, 114u, 59u,
- 119u, 130u, 109u, 55u,
- 194u, 168u, 98u, 158u,
- 180u, 159u, 53u, 74u,
- 255u, 55u, 92u, 41u,
- 27u, 105u, 101u, 128u,
- 198u, 203u, 194u, 255u,
- 162u, 130u, 34u, 230u,
- 122u, 60u, 84u, 183u,
- 216u, 96u, 171u, 15u,
- 255u, 197u, 95u, 164u,
- 134u, 117u, 147u, 122u,
- 147u, 164u, 127u, 141u,
- 213u, 175u, 34u, 212u,
- 117u, 172u, 129u, 133u,
- 134u, 178u, 101u, 73u,
- 255u, 142u, 136u, 169u,
- 116u, 204u, 185u, 94u,
- 231u, 68u, 188u, 114u,
- 165u, 10u, 253u, 54u,
- 92u, 255u, 191u, 127u,
- 66u, 119u, 82u, 175u,
- 160u, 103u, 195u, 126u,
- 120u, 134u, 88u, 1u,
- 55u, 98u, 189u, 72u,
- 146u, 204u, 228u, 82u,
- 52u, 97u, 67u, 57u,
- 55u, 160u, 189u, 113u,
- 124u, 66u, 255u, 123u,
- 123u, 188u, 161u, 144u,
- 67u, 139u, 30u, 61u,
- 206u, 140u, 168u, 151u,
- 92u, 1u, 110u, 146u,
- 89u, 168u, 150u, 77u,
- 49u, 162u, 46u, 177u,
- 142u, 77u, 255u, 97u,
- 77u, 34u, 109u, 168u,
- 136u, 205u, 167u, 132u,
- 125u, 235u, 98u, 60u,
- 190u, 133u, 172u, 255u,
- 225u, 119u, 161u, 194u,
- 92u, 69u, 37u, 149u,
- 138u, 111u, 88u, 119u,
- 255u, 15u, 173u, 117u,
- 173u, 52u, 95u, 78u,
- 113u, 167u, 191u, 158u,
- 239u, 126u, 239u, 103u,
- 255u, 148u, 54u, 142u,
- 152u, 35u, 137u, 69u,
- 12u, 104u, 113u, 123u,
- 104u, 150u, 72u, 1u,
- 136u, 172u, 132u, 113u,
- 172u, 166u, 111u, 57u,
- 147u, 66u, 97u, 186u,
- 49u, 35u, 90u, 0u,
- 242u, 147u, 162u, 133u,
- 136u, 114u, 51u, 109u,
- 113u, 140u, 244u, 117u,
- 170u, 255u, 147u, 27u,
- 95u, 74u, 183u, 139u,
- 127u, 236u, 62u, 97u,
- 125u, 83u, 41u, 150u,
- 220u, 163u, 105u, 138u,
- 159u, 184u, 1u, 198u,
- 71u, 144u, 174u, 144u,
- 196u, 160u, 186u, 73u,
- 150u, 63u, 125u, 212u,
- 139u, 55u, 237u, 233u,
- 189u, 255u, 29u, 36u,
- 64u, 157u, 255u, 98u,
- 119u, 191u, 101u, 126u,
- 66u, 142u, 162u, 127u,
- 174u, 44u, 6u, 140u,
- 255u, 56u, 144u, 105u,
- 205u, 143u, 216u, 69u,
- 183u, 128u, 133u, 102u,
- 165u, 202u, 88u, 84u,
- 152u, 165u, 81u, 92u,
- 246u, 155u, 214u, 54u,
- 201u, 113u, 157u, 171u,
- 86u, 152u, 255u, 116u,
- 171u, 50u, 1u, 147u,
- 19u, 99u, 158u, 73u,
- 64u, 172u, 53u, 107u,
- 12u, 72u, 196u, 246u,
- 225u, 41u, 138u, 112u,
- 120u, 1u, 123u, 107u,
- 120u, 209u, 106u, 104u,
- 141u, 117u, 143u, 96u,
- 72u, 183u, 69u, 82u,
- 46u, 124u, 48u, 132u,
- 0u, 105u, 229u, 109u,
- 128u, 131u, 125u, 141u,
- 59u, 168u, 103u, 109u,
- 18u, 98u, 111u, 144u,
- 182u, 175u, 255u, 137u,
- 156u, 144u, 100u, 96u,
- 40u, 60u, 89u, 39u,
- 214u, 126u, 255u, 139u,
- 98u, 51u, 5u, 39u,
- 192u, 15u, 54u, 232u,
- 178u, 143u, 163u, 162u,
- 45u, 111u, 142u, 185u,
- 135u, 121u, 163u, 155u,
- 171u, 1u, 118u, 131u,
- 118u, 97u, 132u, 62u,
- 255u, 43u, 191u, 173u,
- 118u, 179u, 70u, 204u,
- 137u, 77u, 200u, 129u,
- 149u, 92u, 5u, 245u,
- 176u, 90u, 116u, 58u,
- 255u, 82u, 34u, 93u,
- 134u, 75u, 59u, 18u,
- 197u, 156u, 63u, 56u,
- 122u, 111u, 161u, 152u,
- 115u, 204u, 108u, 147u,
- 178u, 175u, 165u, 0u,
- 64u, 157u, 101u, 7u,
- 197u, 111u, 82u, 66u,
- 91u, 136u, 203u, 175u,
- 61u, 255u, 147u, 88u,
- 79u, 209u, 86u, 122u,
- 158u, 156u, 52u, 137u,
- 181u, 97u, 126u, 130u,
- 7u, 1u, 158u, 154u,
- 122u, 140u, 179u, 116u,
- 75u, 255u, 161u, 228u,
- 56u, 71u, 100u, 106u,
- 84u, 134u, 106u, 224u,
- 198u, 177u, 174u, 228u,
- 118u, 111u, 167u, 125u,
- 133u, 110u, 1u, 162u,
- 115u, 118u, 84u, 140u,
- 169u, 99u, 165u, 156u,
- 123u, 106u, 150u, 193u,
- 146u, 120u, 208u, 172u,
- 100u, 1u, 173u, 113u,
- 132u, 102u, 127u, 97u,
- 71u, 111u, 165u, 255u,
- 187u, 116u, 225u, 118u,
- 135u, 158u, 91u, 70u,
- 130u, 118u, 121u, 171u,
- 215u, 1u, 105u, 156u,
- 143u, 94u, 228u, 59u,
- 171u, 88u, 215u, 125u,
- 5u, 113u, 56u, 126u,
- 111u, 71u, 224u, 92u,
- 71u, 236u, 162u, 82u,
- 255u, 145u, 159u, 57u,
- 163u, 205u, 44u, 55u,
- 120u, 171u, 115u, 146u,
- 99u, 134u, 255u, 132u,
- 177u, 185u, 156u, 110u,
- 86u, 215u, 113u, 27u,
- 187u, 176u, 179u, 102u,
- 37u, 140u, 125u, 151u,
- 129u, 239u, 1u, 47u,
- 126u, 162u, 114u, 54u,
- 164u, 124u, 81u, 116u,
- 81u, 153u, 255u, 241u,
- 147u, 92u, 76u, 61u,
- 40u, 210u, 188u, 144u,
- 15u, 122u, 86u, 144u,
- 174u, 180u, 255u, 122u,
- 144u, 73u, 71u, 119u,
- 96u, 120u, 198u, 100u,
- 56u, 167u, 167u, 169u,
- 129u, 235u, 80u, 133u,
- 83u, 108u, 255u, 253u,
- 166u, 175u, 154u, 109u,
- 125u, 108u, 0u, 81u,
- 136u, 155u, 141u, 101u,
- 182u, 42u, 126u, 170u,
- 132u, 54u, 33u, 168u,
- 195u, 202u, 63u, 0u,
- 175u, 81u, 177u, 200u,
- 135u, 121u, 194u, 212u,
- 109u, 100u, 57u, 109u,
- 255u, 157u, 100u, 188u,
- 160u, 16u, 130u, 163u,
- 90u, 177u, 98u, 96u,
- 85u, 104u, 93u, 198u,
- 101u, 191u, 63u, 175u,
- 96u, 147u, 115u, 89u,
- 87u, 131u, 108u, 255u,
- 113u, 121u, 36u, 224u,
- 57u, 61u, 114u, 52u,
- 137u, 93u, 110u, 105u,
- 1u, 96u, 81u, 123u,
- 96u, 71u, 69u, 118u,
- 126u, 155u, 255u, 193u,
- 38u, 34u, 74u, 228u,
- 184u, 122u, 110u, 133u,
- 208u, 120u, 95u, 180u,
- 94u, 172u, 0u, 59u,
- 146u, 153u, 71u, 109u,
- 177u, 181u, 149u, 183u,
- 112u, 169u, 108u, 255u,
- 43u, 100u, 99u, 72u,
- 181u, 185u, 84u, 84u,
- 189u, 199u, 152u, 123u,
- 98u, 122u, 129u, 218u,
- 68u, 128u, 41u, 178u,
- 116u, 1u, 131u, 147u,
- 97u, 139u, 208u, 102u,
- 132u, 54u, 29u, 199u,
- 62u, 58u, 83u, 125u,
- 97u, 128u, 73u, 1u,
- 27u, 92u, 127u, 119u,
- 122u, 14u, 84u, 143u,
- 209u, 122u, 198u, 38u,
- 166u, 136u, 1u, 198u,
- 119u, 255u, 58u, 201u,
- 132u, 143u, 85u, 240u,
- 46u, 91u, 106u, 159u,
- 106u, 112u, 89u, 30u,
- 121u, 2u, 255u, 143u,
- 118u, 80u, 48u, 49u,
- 72u, 33u, 0u, 249u,
- 133u, 131u, 140u, 132u,
- 85u, 61u, 211u, 195u,
- 138u, 86u, 142u, 255u,
- 108u, 180u, 236u, 47u,
- 130u, 84u, 73u, 214u,
- 164u, 129u, 144u, 168u,
- 223u, 151u, 106u, 177u,
- 126u, 18u, 166u, 59u,
- 252u, 237u, 144u, 99u,
- 241u, 255u, 69u, 33u,
- 109u, 81u, 157u, 0u,
- 150u, 73u, 113u, 132u,
- 177u, 113u, 220u, 137u,
- 64u, 130u, 95u, 111u,
- 103u, 151u, 117u, 172u,
- 141u, 148u, 255u, 191u,
- 108u, 109u, 69u, 127u,
- 115u, 163u, 104u, 123u,
- 149u, 222u, 111u, 143u,
- 1u, 127u, 148u, 142u,
- 173u, 152u, 224u, 136u,
- 133u, 118u, 118u, 185u,
- 170u, 82u, 157u, 221u,
- 148u, 101u, 46u, 1u,
- 133u, 75u, 77u, 47u,
- 132u, 190u, 112u, 91u,
- 110u, 125u, 120u, 229u,
- 69u, 135u, 106u, 117u,
- 118u, 255u, 49u, 43u,
- 110u, 134u, 22u, 150u,
- 90u, 105u, 153u, 239u,
- 70u, 186u, 53u, 48u,
- 145u, 243u, 73u, 1u,
- 172u, 146u, 128u, 84u,
- 179u, 78u, 123u, 83u,
- 179u, 180u, 121u, 166u,
- 161u, 162u, 219u, 137u,
- 132u, 255u, 149u, 47u,
- 206u, 228u, 65u, 0u,
- 130u, 77u, 111u, 228u,
- 31u, 129u, 119u, 24u,
- 26u, 150u, 154u, 0u,
- 120u, 119u, 113u, 172u,
- 118u, 68u, 156u, 145u,
- 255u, 115u, 82u, 110u,
- 52u, 158u, 65u, 14u,
- 6u, 112u, 124u, 23u,
- 135u, 125u, 255u, 241u,
- 104u, 204u, 67u, 168u,
- 21u, 52u, 160u, 204u,
- 109u, 73u, 179u, 204u,
- 125u, 135u, 67u, 114u,
- 162u, 197u, 54u, 17u,
- 0u, 106u, 68u, 87u,
- 1u, 133u, 45u, 129u,
- 102u, 166u, 73u, 213u,
- 199u, 67u, 178u, 150u,
- 186u, 125u, 162u, 34u,
- 155u, 181u, 194u, 44u,
- 187u, 169u, 255u, 93u,
- 163u, 82u, 130u, 166u,
- 158u, 217u, 117u, 119u,
- 113u, 1u, 188u, 199u,
- 123u, 178u, 170u, 133u,
- 107u, 102u, 171u, 124u,
- 107u, 66u, 29u, 49u,
- 51u, 179u, 210u, 63u,
- 97u, 167u, 113u, 1u,
- 143u, 138u, 97u, 145u,
- 108u, 66u, 136u, 97u,
- 208u, 130u, 89u, 255u,
- 9u, 111u, 223u, 95u,
- 173u, 189u, 48u, 55u,
- 238u, 104u, 145u, 144u,
- 255u, 46u, 152u, 251u,
- 111u, 157u, 30u, 231u,
- 170u, 70u, 76u, 238u,
- 107u, 158u, 143u, 231u,
- 77u, 1u, 53u, 201u,
- 145u, 99u, 191u, 88u,
- 86u, 87u, 107u, 156u,
- 141u, 120u, 164u, 75u,
- 111u, 92u, 152u, 164u,
- 83u, 255u, 183u, 116u,
- 68u, 76u, 58u, 153u,
- 107u, 33u, 69u, 108u,
- 146u, 89u, 171u, 158u,
- 156u, 77u, 145u, 146u,
- 178u, 114u, 1u, 58u,
- 170u, 116u, 86u, 106u,
- 154u, 76u, 156u, 164u,
- 130u, 49u, 178u, 119u,
- 168u, 1u, 140u, 120u,
- 106u, 190u, 96u, 125u,
- 153u, 139u, 146u, 146u,
- 0u, 120u, 219u, 155u,
- 131u, 113u, 85u, 61u,
- 141u, 72u, 78u, 161u,
- 113u, 141u, 155u, 236u,
- 90u, 211u, 21u, 174u,
- 54u, 200u, 41u, 176u,
- 255u, 41u, 214u, 225u,
- 129u, 95u, 255u, 44u,
- 136u, 120u, 158u, 97u,
- 208u, 132u, 99u, 174u,
- 176u, 125u, 76u, 152u,
- 76u, 105u, 214u, 72u,
- 109u, 213u, 1u, 223u,
- 22u, 108u, 146u, 25u,
- 88u, 51u, 83u, 202u,
- 139u, 154u, 204u, 41u,
- 145u, 87u, 155u, 1u,
- 151u, 217u, 72u, 199u,
- 72u, 180u, 188u, 145u,
- 1u, 132u, 112u, 16u,
- 251u, 150u, 175u, 177u,
- 202u, 73u, 95u, 253u,
- 65u, 216u, 175u, 143u,
- 64u, 216u, 1u, 224u,
- 100u, 83u, 128u, 124u,
- 140u, 134u, 116u, 153u,
- 118u, 115u, 158u, 27u,
- 203u, 143u, 70u, 204u,
- 1u, 39u, 140u, 77u,
- 133u, 189u, 173u, 166u,
- 161u, 99u, 131u, 154u,
- 89u, 72u, 179u, 70u,
- 98u, 99u, 195u, 54u,
- 57u, 1u, 242u, 158u,
- 103u, 237u, 165u, 177u,
- 119u, 198u, 117u, 90u,
- 121u, 135u, 0u, 157u,
- 98u, 165u, 143u, 74u,
- 149u, 99u, 101u, 72u,
- 126u, 159u, 139u, 145u,
- 120u, 71u, 161u, 1u,
- 94u, 50u, 101u, 168u,
- 126u, 105u, 143u, 178u,
- 125u, 111u, 60u, 210u,
- 136u, 90u, 84u, 0u,
- 16u, 116u, 155u, 137u,
- 199u, 95u, 31u, 67u,
- 244u, 96u, 151u, 222u,
- 118u, 10u, 129u, 168u,
- 49u, 37u, 130u, 128u,
- 88u, 87u, 1u, 73u,
- 52u, 152u, 100u, 99u,
- 191u, 223u, 29u, 170u,
- 123u, 150u, 155u, 1u,
- 64u, 84u, 134u, 139u,
- 232u, 133u, 250u, 165u,
- 120u, 10u, 112u, 63u,
- 152u, 183u, 77u, 16u,
- 166u, 55u, 175u, 1u,
- 174u, 186u, 255u, 107u,
- 154u, 154u, 75u, 122u,
- 131u, 44u, 23u, 144u,
- 183u, 146u, 84u, 39u,
- 161u, 76u, 97u, 148u,
- 141u, 165u, 143u, 102u,
- 61u, 127u, 54u, 1u,
- 201u, 82u, 137u, 108u,
- 68u, 158u, 146u, 162u,
- 172u, 255u, 65u, 108u,
- 152u, 111u, 90u, 74u,
- 145u, 109u, 177u, 105u,
- 168u, 165u, 157u, 42u,
- 42u, 140u, 115u, 206u,
- 83u, 255u, 135u, 103u,
- 162u, 93u, 204u, 114u,
- 114u, 131u, 107u, 162u,
- 32u, 170u, 155u, 133u,
- 168u, 190u, 185u, 166u,
- 129u, 151u, 1u, 169u,
- 97u, 185u, 132u, 116u,
- 219u, 156u, 120u, 5u,
- 112u, 61u, 161u, 56u,
- 115u, 97u, 103u, 255u,
- 159u, 173u, 55u, 78u,
- 30u, 146u, 208u, 255u,
- 86u, 142u, 172u, 100u,
- 245u, 161u, 36u, 109u,
- 161u, 217u, 139u, 79u,
- 111u, 175u, 187u, 149u,
- 103u, 62u, 164u, 228u,
- 160u, 255u, 122u, 88u,
- 216u, 150u, 231u, 1u,
- 84u, 143u, 117u, 178u,
- 131u, 100u, 121u, 76u,
- 66u, 237u, 174u, 226u,
- 161u, 222u, 95u, 160u,
- 95u, 160u, 134u, 232u,
- 237u, 36u, 61u, 1u,
- 200u, 86u, 212u, 104u,
- 182u, 103u, 95u, 172u,
- 92u, 194u, 75u, 196u,
- 133u, 98u, 248u, 218u,
- 255u, 103u, 56u, 11u,
- 90u, 168u, 34u, 255u,
- 105u, 142u, 65u, 83u,
- 157u, 167u, 184u, 93u,
- 231u, 93u, 52u, 102u,
- 151u, 91u, 59u, 158u,
- 106u, 138u, 49u, 165u,
- 133u, 144u, 153u, 135u,
- 1u, 147u, 87u, 127u,
- 42u, 132u, 206u, 164u,
- 206u, 192u, 134u, 89u,
- 58u, 1u, 66u, 54u,
- 86u, 160u, 153u, 182u,
- 215u, 165u, 199u, 108u,
- 130u, 223u, 156u, 145u,
- 118u, 1u, 115u, 100u,
- 177u, 139u, 144u, 135u,
- 83u, 46u, 137u, 134u,
- 185u, 100u, 100u, 6u,
- 0u, 6u, 92u, 210u,
- 160u, 112u, 80u, 120u,
- 104u, 96u, 0u, 181u,
- 113u, 150u, 122u, 122u,
- 133u, 117u, 117u, 206u,
- 115u, 101u, 65u, 139u,
- 39u, 219u, 150u, 144u,
- 91u, 255u, 100u, 113u,
- 24u, 83u, 206u, 189u,
- 185u, 23u, 55u, 174u,
- 119u, 20u, 0u, 129u,
- 192u, 103u, 19u, 127u,
- 122u, 211u, 80u, 69u,
- 167u, 24u, 69u, 28u,
- 115u, 157u, 35u, 144u,
- 40u, 41u, 65u, 103u,
- 143u, 107u, 183u, 0u,
- 145u, 124u, 179u, 55u,
- 145u, 49u, 1u, 196u,
- 110u, 104u, 173u, 131u,
- 134u, 103u, 113u, 229u,
- 122u, 74u, 238u, 219u,
- 150u, 156u, 226u, 50u,
- 91u, 255u, 105u, 103u,
- 91u, 82u, 163u, 147u,
- 210u, 55u, 104u, 153u,
- 33u, 153u, 72u, 199u,
- 35u, 166u, 43u, 167u,
- 169u, 95u, 189u, 106u,
- 90u, 1u, 109u, 235u,
- 150u, 89u, 1u, 157u,
- 207u, 109u, 64u, 232u,
- 96u, 160u, 95u, 200u,
- 101u, 102u, 159u, 212u,
- 90u, 156u, 211u, 25u,
- 22u, 60u, 95u, 49u,
- 118u, 179u, 255u, 114u,
- 95u, 154u, 29u, 88u,
- 168u, 153u, 255u, 174u,
- 172u, 171u, 3u, 150u,
- 76u, 229u, 58u, 153u,
- 162u, 48u, 99u, 214u,
- 185u, 59u, 113u, 153u,
- 22u, 181u, 81u, 113u,
- 91u, 201u, 171u, 147u,
- 93u, 145u, 0u, 99u,
- 201u, 213u, 139u, 138u,
- 149u, 111u, 1u, 181u,
- 83u, 101u, 168u, 168u,
- 166u, 88u, 153u, 102u,
- 57u, 104u, 228u, 69u,
- 156u, 120u, 137u, 48u,
- 8u, 140u, 46u, 1u,
- 132u, 32u, 178u, 232u,
- 154u, 127u, 178u, 69u,
- 117u, 63u, 132u, 237u,
- 28u, 164u, 210u, 225u,
- 169u, 156u, 1u, 199u,
- 158u, 41u, 153u, 133u,
- 245u, 133u, 218u, 103u,
- 214u, 109u, 1u, 212u,
- 166u, 200u, 57u, 73u,
- 157u, 133u, 255u, 90u,
- 69u, 106u, 198u, 101u,
- 125u, 124u, 145u, 164u,
- 131u, 176u, 158u, 138u,
- 192u, 142u, 165u, 132u,
- 152u, 120u, 60u, 110u,
- 170u, 1u, 105u, 196u,
- 106u, 121u, 97u, 153u,
- 137u, 135u, 70u, 168u,
- 163u, 107u, 1u, 86u,
- 144u, 162u, 126u, 97u,
- 154u, 133u, 94u, 176u,
- 254u, 107u, 188u, 105u,
- 60u, 140u, 26u, 102u,
- 76u, 32u, 100u, 50u,
- 171u, 139u, 84u, 255u,
- 144u, 127u, 223u, 189u,
- 204u, 159u, 154u, 13u,
- 104u, 255u, 76u, 131u,
- 181u, 62u, 106u, 209u,
- 112u, 171u, 149u, 44u,
- 135u, 134u, 25u, 209u,
- 82u, 124u, 119u, 1u,
- 103u, 145u, 102u, 131u,
- 135u, 50u, 78u, 164u,
- 180u, 144u, 104u, 64u,
- 92u, 174u, 1u, 100u,
- 124u, 182u, 168u, 171u,
- 183u, 124u, 46u, 48u,
- 181u, 204u, 149u, 149u,
- 80u, 149u, 213u, 153u,
- 249u, 255u, 222u, 128u,
- 234u, 111u, 197u, 124u,
- 190u, 127u, 139u, 172u,
- 158u, 131u, 120u, 138u,
- 158u, 1u, 81u, 109u,
- 152u, 103u, 168u, 161u,
- 185u, 155u, 52u, 94u,
- 96u, 1u, 70u, 69u,
- 132u, 133u, 122u, 121u,
- 182u, 177u, 185u, 114u,
- 196u, 181u, 89u, 75u,
- 99u, 1u, 146u, 182u,
- 149u, 81u, 96u, 180u,
- 67u, 155u, 89u, 46u,
- 255u, 83u, 82u, 33u,
- 124u, 146u, 241u, 211u,
- 87u, 164u, 172u, 137u,
- 146u, 198u, 164u, 128u,
- 139u, 158u, 57u, 99u,
- 255u, 106u, 202u, 186u,
- 54u, 96u, 164u, 215u,
- 143u, 64u, 181u, 212u,
- 119u, 90u, 57u, 0u,
- 56u, 162u, 72u, 58u,
- 134u, 88u, 196u, 115u,
- 89u, 188u, 187u, 156u,
- 111u, 219u, 62u, 98u,
- 173u, 48u, 167u, 141u,
- 214u, 1u, 58u, 164u,
- 175u, 102u, 199u, 173u,
- 0u, 163u, 226u, 77u,
- 132u, 113u, 47u, 120u,
- 139u, 150u, 142u, 211u,
- 213u, 112u, 136u, 154u,
- 231u, 67u, 253u, 94u,
- 151u, 141u, 1u, 143u,
- 206u, 245u, 210u, 64u,
- 17u, 108u, 140u, 98u,
- 88u, 156u, 177u, 171u,
- 165u, 157u, 117u, 65u,
- 158u, 134u, 255u, 200u,
- 45u, 96u, 51u, 152u,
- 255u, 15u, 242u, 121u,
- 207u, 82u, 120u, 219u,
- 75u, 190u, 203u, 89u,
- 175u, 123u, 79u, 218u,
- 105u, 117u, 156u, 140u,
- 211u, 1u, 152u, 180u,
- 100u, 169u, 87u, 79u,
- 120u, 130u, 117u, 81u,
- 255u, 144u, 88u, 113u,
- 144u, 156u, 139u, 61u,
- 205u, 67u, 54u, 107u,
- 76u, 63u, 55u, 56u,
- 72u, 121u, 89u, 141u,
- 120u, 154u, 66u, 75u,
- 255u, 73u, 151u, 130u,
- 192u, 124u, 234u, 177u,
- 141u, 99u, 219u, 18u,
- 255u, 182u, 162u, 230u,
- 232u, 133u, 85u, 108u,
- 62u, 72u, 104u, 47u,
- 89u, 42u, 88u, 1u,
- 168u, 140u, 92u, 78u,
- 80u, 195u, 17u, 54u,
- 136u, 138u, 140u, 77u,
- 221u, 255u, 179u, 205u,
- 195u, 56u, 65u, 88u,
- 134u, 203u, 195u, 68u,
- 229u, 239u, 193u, 115u,
- 187u, 134u, 216u, 202u,
- 134u, 92u, 57u, 205u,
- 1u, 79u, 0u, 229u,
- 110u, 111u, 197u, 49u,
- 122u, 194u, 199u, 199u,
- 111u, 68u, 194u, 146u,
- 167u, 154u, 1u, 28u,
- 126u, 92u, 1u, 110u,
- 167u, 43u, 226u, 230u,
- 133u, 80u, 210u, 104u,
- 184u, 200u, 154u, 135u,
- 50u, 198u, 149u, 66u,
- 224u, 63u, 52u, 11u,
- 87u, 0u, 58u, 36u,
- 57u, 215u, 189u, 218u,
- 82u, 122u, 73u, 218u,
- 215u, 0u, 84u, 93u,
- 78u, 44u, 212u, 213u,
- 77u, 248u, 118u, 91u,
- 110u, 97u, 79u, 49u,
- 152u, 101u, 255u, 219u,
- 234u, 93u, 74u, 128u,
- 168u, 72u, 169u, 146u,
- 157u, 170u, 165u, 155u,
- 1u, 161u, 145u, 123u,
- 153u, 100u, 223u, 166u,
- 178u, 171u, 166u, 111u,
- 132u, 141u, 231u, 49u,
- 81u, 107u, 81u, 155u,
- 29u, 192u, 75u, 234u,
- 1u, 126u, 56u, 244u,
- 111u, 34u, 119u, 118u,
- 135u, 143u, 129u, 145u,
- 255u, 118u, 106u, 145u,
- 114u, 171u, 113u, 107u,
- 140u, 248u, 119u, 154u,
- 237u, 218u, 1u, 88u,
- 110u, 89u, 111u, 47u,
- 141u, 156u, 95u, 183u,
- 102u, 255u, 42u, 95u,
- 52u, 92u, 97u, 62u,
- 179u, 48u, 175u, 150u,
- 45u, 158u, 100u, 158u,
- 139u, 144u, 105u, 255u,
- 132u, 157u, 124u, 95u,
- 201u, 150u, 82u, 113u,
- 53u, 224u, 100u, 161u,
- 220u, 77u, 237u, 161u,
- 171u, 255u, 74u, 123u,
- 149u, 50u, 148u, 199u,
- 199u, 64u, 159u, 226u,
- 191u, 107u, 83u, 213u,
- 179u, 60u, 233u, 63u,
- 113u, 81u, 11u, 115u,
- 213u, 216u, 167u, 1u,
- 103u, 87u, 192u, 8u,
- 53u, 153u, 74u, 212u,
- 171u, 105u, 45u, 127u,
- 8u, 1u, 172u, 208u,
- 146u, 124u, 109u, 255u,
- 69u, 149u, 78u, 124u,
- 201u, 204u, 175u, 173u,
- 183u, 148u, 91u, 178u,
- 153u, 133u, 91u, 213u,
- 51u, 47u, 146u, 130u,
- 103u, 255u, 149u, 26u,
- 147u, 140u, 139u, 22u,
- 105u, 205u, 123u, 137u,
- 93u, 0u, 54u, 122u,
- 127u, 67u, 126u, 118u,
- 9u, 104u, 19u, 109u,
- 168u, 72u, 183u, 87u,
- 96u, 139u, 242u, 49u,
- 255u, 162u, 156u, 191u,
- 190u, 180u, 203u, 136u,
- 42u, 178u, 20u, 255u,
- 50u, 27u, 169u, 130u,
- 184u, 149u, 107u, 151u,
- 156u, 19u, 113u, 66u,
- 46u, 97u, 101u, 164u,
- 25u, 151u, 255u, 209u,
- 85u, 250u, 110u, 193u,
- 189u, 228u, 143u, 44u,
- 184u, 42u, 107u, 135u,
- 124u, 103u, 200u, 136u,
- 193u, 34u, 70u, 125u,
- 1u, 201u, 126u, 67u,
- 153u, 137u, 58u, 161u,
- 131u, 172u, 105u, 208u,
- 99u, 74u, 5u, 62u,
- 108u, 81u, 38u, 255u,
- 14u, 145u, 121u, 22u,
- 145u, 36u, 79u, 123u,
- 100u, 68u, 87u, 110u,
- 122u, 44u, 82u, 255u,
- 227u, 40u, 30u, 122u,
- 124u, 154u, 255u, 250u,
- 208u, 36u, 163u, 251u,
- 60u, 161u, 141u, 68u,
- 87u, 170u, 198u, 20u,
- 100u, 196u, 168u, 121u,
- 101u, 135u, 161u, 255u,
- 163u, 52u, 118u, 213u,
- 129u, 180u, 95u, 201u,
- 95u, 139u, 85u, 28u,
- 175u, 14u, 246u, 255u,
- 47u, 202u, 97u, 122u,
- 209u, 151u, 81u, 189u,
- 137u, 1u, 143u, 170u,
- 238u, 143u, 125u, 110u,
- 110u, 152u, 111u, 106u,
- 174u, 48u, 124u, 20u,
- 172u, 253u, 137u, 190u,
- 232u, 124u, 128u, 152u,
- 247u, 85u, 1u, 19u,
- 140u, 129u, 127u, 255u,
- 44u, 53u, 121u, 183u,
- 120u, 182u, 169u, 155u,
- 94u, 47u, 71u, 196u,
- 100u, 136u, 54u, 159u,
- 71u, 173u, 109u, 206u,
- 95u, 108u, 134u, 157u,
- 103u, 1u, 185u, 192u,
- 159u, 163u, 182u, 173u,
- 175u, 255u, 64u, 77u,
- 104u, 99u, 52u, 90u,
- 113u, 199u, 97u, 210u,
- 46u, 117u, 104u, 185u,
- 107u, 170u, 109u, 174u,
- 56u, 186u, 76u, 95u,
- 80u, 0u, 92u, 167u,
- 155u, 155u, 162u, 1u,
- 103u, 125u, 100u, 120u,
- 154u, 82u, 151u, 127u,
- 57u, 235u, 135u, 163u,
- 153u, 164u, 130u, 51u,
- 58u, 56u, 95u, 135u,
- 12u, 255u, 176u, 174u,
- 94u, 40u, 179u, 162u,
- 104u, 50u, 198u, 192u,
- 76u, 219u, 119u, 18u,
- 63u, 60u, 172u, 164u,
- 44u, 255u, 178u, 44u,
- 124u, 138u, 52u, 116u,
- 11u, 255u, 13u, 107u,
- 62u, 96u, 240u, 103u,
- 123u, 121u, 92u, 224u,
- 228u, 135u, 145u, 204u,
- 90u, 190u, 99u, 215u,
- 173u, 110u, 30u, 39u,
- 224u, 255u, 165u, 34u,
- 187u, 140u, 152u, 123u,
- 79u, 130u, 97u, 142u,
- 12u, 255u, 137u, 244u,
- 81u, 119u, 134u, 10u,
- 151u, 151u, 138u, 1u,
- 123u, 134u, 156u, 160u,
- 35u, 145u, 171u, 83u,
- 93u, 189u, 92u, 195u,
- 210u, 233u, 138u, 1u,
- 148u, 33u, 134u, 134u,
- 106u, 184u, 185u, 136u,
- 143u, 245u, 149u, 166u,
- 49u, 66u, 217u, 122u,
- 255u, 125u, 88u, 119u,
- 118u, 82u, 109u, 169u,
- 99u, 164u, 77u, 89u,
- 111u, 151u, 198u, 233u,
- 101u, 70u, 163u, 106u,
- 184u, 82u, 135u, 159u,
- 60u, 123u, 255u, 156u,
- 196u, 189u, 161u, 68u,
- 255u, 167u, 138u, 195u,
- 108u, 143u, 127u, 55u,
- 178u, 192u, 226u, 161u,
- 192u, 137u, 113u, 26u,
- 49u, 17u, 163u, 48u,
- 34u, 199u, 146u, 236u,
- 93u, 13u, 255u, 87u,
- 227u, 134u, 170u, 255u,
- 111u, 42u, 68u, 74u,
- 77u, 124u, 168u, 115u,
- 186u, 36u, 74u, 100u,
- 153u, 88u, 122u, 142u,
- 0u, 160u, 84u, 255u,
- 97u, 150u, 139u, 168u,
- 167u, 86u, 88u, 128u,
- 10u, 131u, 66u, 88u,
- 92u, 120u, 183u, 255u,
- 217u, 192u, 122u, 67u,
- 52u, 161u, 64u, 163u,
- 82u, 146u, 32u, 100u,
- 20u, 96u, 124u, 125u,
- 205u, 249u, 136u, 95u,
- 55u, 0u, 9u, 139u,
- 140u, 145u, 155u, 255u,
- 97u, 78u, 251u, 152u,
- 183u, 137u, 208u, 175u,
- 160u, 155u, 170u, 67u,
- 142u, 219u, 152u, 22u,
- 255u, 135u, 167u, 226u,
- 117u, 67u, 129u, 189u,
- 188u, 129u, 229u, 144u,
- 90u, 224u, 152u, 204u,
- 255u, 62u, 190u, 93u,
- 117u, 99u, 118u, 218u,
- 199u, 111u, 178u, 147u,
- 166u, 147u, 209u, 164u,
- 23u, 146u, 112u, 255u,
- 148u, 144u, 146u, 128u,
- 118u, 102u, 148u, 157u,
- 69u, 96u, 61u, 64u,
- 43u, 116u, 200u, 197u,
- 255u, 138u, 208u, 98u,
- 91u, 108u, 116u, 94u,
- 180u, 73u, 1u, 115u,
- 194u, 62u, 28u, 191u,
- 206u, 26u, 142u, 165u,
- 24u, 107u, 61u, 47u,
- 143u, 80u, 172u, 175u,
- 136u, 164u, 47u, 151u,
- 128u, 140u, 116u, 47u,
- 255u, 197u, 126u, 62u,
- 235u, 42u, 185u, 164u,
- 197u, 145u, 147u, 48u,
- 141u, 23u, 79u, 255u,
- 187u, 168u, 137u, 159u,
- 102u, 194u, 152u, 139u,
- 121u, 41u, 255u, 76u,
- 45u, 181u, 139u, 188u,
- 82u, 80u, 190u, 92u,
- 28u, 193u, 159u, 179u,
- 71u, 221u, 53u, 100u,
- 1u, 108u, 119u, 197u,
- 215u, 52u, 145u, 113u,
- 121u, 190u, 172u, 159u,
- 185u, 171u, 97u, 131u,
- 137u, 255u, 78u, 199u,
- 127u, 209u, 124u, 153u,
- 84u, 132u, 41u, 5u,
- 217u, 107u, 62u, 179u,
- 71u, 255u, 96u, 99u,
- 35u, 118u, 208u, 144u,
- 77u, 45u, 28u, 94u,
- 255u, 119u, 233u, 45u,
- 101u, 207u, 6u, 122u,
- 180u, 206u, 88u, 154u,
- 104u, 53u, 52u, 171u,
- 121u, 41u, 135u, 9u,
- 1u, 55u, 134u, 111u,
- 39u, 85u, 111u, 85u,
- 133u, 117u, 255u, 112u,
- 120u, 128u, 167u, 115u,
- 164u, 82u, 84u, 158u,
- 128u, 122u, 157u, 122u,
- 1u, 202u, 180u, 57u,
- 190u, 169u, 242u, 130u,
- 90u, 189u, 156u, 118u,
- 84u, 236u, 57u, 10u,
- 98u, 162u, 85u, 168u,
- 43u, 255u, 25u, 155u,
- 154u, 77u, 176u, 55u,
- 160u, 156u, 148u, 163u,
- 61u, 84u, 164u, 161u,
- 89u, 152u, 210u, 212u,
- 112u, 201u, 51u, 213u,
- 1u, 63u, 32u, 129u,
- 167u, 154u, 136u, 126u,
- 108u, 86u, 255u, 183u,
- 84u, 86u, 79u, 162u,
- 171u, 125u, 173u, 71u,
- 138u, 126u, 124u, 149u,
- 135u, 119u, 174u, 125u,
- 104u, 160u, 48u, 1u,
- 106u, 144u, 100u, 142u,
- 86u, 161u, 194u, 151u,
- 83u, 3u, 99u, 69u,
- 54u, 236u, 255u, 128u,
- 140u, 182u, 247u, 86u,
- 132u, 135u, 112u, 136u,
- 118u, 162u, 140u, 122u,
- 193u, 92u, 255u, 93u,
- 155u, 121u, 105u, 76u,
- 130u, 104u, 68u, 149u,
- 184u, 121u, 185u, 100u,
- 91u, 135u, 72u, 150u,
- 255u, 155u, 76u, 32u,
- 145u, 4u, 81u, 112u,
- 1u, 21u, 133u, 52u,
- 198u, 62u, 157u, 93u,
- 150u, 164u, 94u, 224u,
- 121u, 140u, 77u, 122u,
- 118u, 236u, 210u, 108u,
- 64u, 170u, 54u, 141u,
- 141u, 201u, 249u, 255u,
- 82u, 185u, 120u, 156u,
- 62u, 130u, 255u, 56u,
- 75u, 95u, 107u, 118u,
- 161u, 169u, 193u, 43u,
- 221u, 126u, 182u, 124u,
- 120u, 85u, 152u, 115u,
- 136u, 92u, 133u, 199u,
- 255u, 140u, 175u, 117u,
- 37u, 48u, 166u, 91u,
- 171u, 93u, 147u, 151u,
- 255u, 173u, 200u, 27u,
- 30u, 242u, 181u, 226u,
- 199u, 168u, 174u, 96u,
- 231u, 178u, 177u, 122u,
- 107u, 152u, 155u, 196u,
- 216u, 255u, 97u, 102u,
- 94u, 140u, 187u, 133u,
- 150u, 168u, 12u, 38u,
- 59u, 207u, 188u, 90u,
- 148u, 1u, 85u, 186u,
- 163u, 105u, 186u, 96u,
- 106u, 194u, 160u, 175u,
- 94u, 137u, 122u, 77u,
- 148u, 255u, 195u, 206u,
- 151u, 255u, 205u, 102u,
- 165u, 81u, 235u, 72u,
- 206u, 242u, 200u, 169u,
- 77u, 138u, 185u, 96u,
- 0u, 89u, 149u, 47u,
- 122u, 178u, 160u, 172u,
- 110u, 144u, 85u, 100u,
- 25u, 196u, 137u, 181u,
- 48u, 242u, 236u, 162u,
- 250u, 217u, 255u, 148u,
- 198u, 166u, 160u, 117u,
- 237u, 80u, 226u, 248u,
- 131u, 130u, 184u, 72u,
- 56u, 141u, 182u, 38u,
- 1u, 201u, 132u, 148u,
- 202u, 82u, 139u, 183u,
- 13u, 1u, 182u, 10u,
- 134u, 60u, 129u, 169u,
- 57u, 227u, 185u, 207u,
- 62u, 18u, 108u, 143u,
- 152u, 97u, 114u, 117u,
- 226u, 34u, 156u, 1u,
- 181u, 97u, 122u, 82u,
- 144u, 174u, 229u, 137u,
- 149u, 141u, 112u, 169u,
- 107u, 187u, 255u, 145u,
- 167u, 91u, 118u, 171u,
- 126u, 156u, 68u, 74u,
- 122u, 169u, 109u, 142u,
- 99u, 99u, 84u, 1u,
- 72u, 107u, 217u, 79u,
- 176u, 115u, 206u, 45u,
- 178u, 145u, 197u, 42u,
- 161u, 226u, 152u, 158u,
- 144u, 86u, 10u, 82u,
- 61u, 255u, 129u, 103u,
- 143u, 119u, 68u, 255u,
- 95u, 74u, 107u, 107u,
- 83u, 157u, 170u, 208u,
- 255u, 92u, 125u, 50u,
- 116u, 94u, 149u, 151u,
- 153u, 139u, 75u, 172u,
- 181u, 8u, 160u, 134u,
- 1u, 175u, 204u, 52u,
- 103u, 208u, 73u, 19u,
- 139u, 143u, 201u, 162u,
- 125u, 65u, 208u, 168u,
- 154u, 226u, 1u, 86u,
- 40u, 255u, 143u, 78u,
- 73u, 162u, 249u, 151u,
- 53u, 50u, 142u, 236u,
- 76u, 67u, 125u, 149u,
- 208u, 255u, 91u, 141u,
- 194u, 231u, 206u, 134u,
- 115u, 248u, 56u, 108u,
- 122u, 70u, 119u, 45u,
- 169u, 1u, 158u, 174u,
- 16u, 100u, 89u, 115u,
- 135u, 114u, 133u, 14u,
- 147u, 5u, 133u, 110u,
- 175u, 203u, 46u, 205u,
- 113u, 96u, 125u, 0u,
- 38u, 109u, 52u, 117u,
- 94u, 211u, 104u, 105u,
- 255u, 32u, 70u, 133u,
- 182u, 98u, 199u, 96u,
- 64u, 156u, 3u, 122u,
- 246u, 176u, 144u, 26u,
- 127u, 165u, 47u, 185u,
- 102u, 112u, 26u, 71u,
- 162u, 22u, 132u, 0u,
- 135u, 158u, 104u, 15u,
- 115u, 134u, 126u, 224u,
- 89u, 96u, 112u, 27u,
- 217u, 99u, 8u, 44u,
- 1u, 171u, 127u, 134u,
- 187u, 30u, 29u, 40u,
- 46u, 31u, 71u, 217u,
- 35u, 146u, 162u, 23u,
- 1u, 60u, 237u, 193u,
- 99u, 135u, 60u, 156u,
- 99u, 139u, 1u, 154u,
- 180u, 112u, 204u, 83u,
- 69u, 98u, 133u, 92u,
- 82u, 102u, 208u, 199u,
- 126u, 5u, 142u, 196u,
- 130u, 242u, 92u, 1u,
- 77u, 94u, 212u, 125u,
- 211u, 111u, 128u, 95u,
- 57u, 37u, 67u, 255u,
- 102u, 18u, 133u, 146u,
- 77u, 181u, 139u, 53u,
- 100u, 57u, 212u, 105u,
- 171u, 98u, 255u, 129u,
- 189u, 128u, 97u, 165u,
- 144u, 125u, 87u, 84u,
- 180u, 1u, 77u, 205u,
- 110u, 141u, 194u, 163u,
- 200u, 99u, 119u, 66u,
- 143u, 115u, 181u, 128u,
- 62u, 156u, 101u, 133u,
- 125u, 76u, 255u, 48u,
- 129u, 152u, 110u, 150u,
- 98u, 115u, 158u, 164u,
- 45u, 119u, 89u, 1u,
- 180u, 136u, 120u, 145u,
- 91u, 232u, 123u, 115u,
- 129u, 125u, 144u, 165u,
- 113u, 69u, 160u, 111u,
- 53u, 146u, 158u, 79u,
- 191u, 117u, 169u, 4u,
- 131u, 4u, 111u, 255u,
- 85u, 211u, 55u, 138u,
- 66u, 193u, 134u, 45u,
- 160u, 133u, 255u, 194u,
- 238u, 82u, 114u, 89u,
- 126u, 195u, 115u, 3u,
- 184u, 148u, 56u, 152u,
- 144u, 255u, 148u, 134u,
- 140u, 60u, 148u, 165u,
- 127u, 87u, 116u, 1u,
- 15u, 229u, 192u, 239u,
- 80u, 217u, 156u, 243u,
- 122u, 7u, 35u, 100u,
- 93u, 128u, 56u, 178u,
- 77u, 139u, 161u, 178u,
- 158u, 1u, 146u, 127u,
- 113u, 125u, 157u, 92u,
- 36u, 53u, 45u, 214u,
- 112u, 187u, 200u, 255u,
- 161u, 118u, 115u, 136u,
- 114u, 165u, 130u, 178u,
- 207u, 67u, 169u, 138u,
- 104u, 65u, 210u, 44u,
- 240u, 146u, 255u, 126u,
- 130u, 132u, 148u, 36u,
- 20u, 130u, 175u, 136u,
- 172u, 22u, 104u, 255u,
- 92u, 149u, 158u, 138u,
- 48u, 79u, 96u, 130u,
- 80u, 255u, 57u, 182u,
- 110u, 102u, 135u, 135u,
- 15u, 168u, 188u, 135u,
- 223u, 40u, 141u, 178u,
- 173u, 104u, 102u, 184u,
- 183u, 151u, 168u, 184u,
- 162u, 1u, 151u, 153u,
- 127u, 197u, 148u, 112u,
- 102u, 251u, 141u, 1u,
- 164u, 149u, 250u, 142u,
- 109u, 126u, 124u, 154u,
- 73u, 95u, 220u, 241u,
- 1u, 89u, 164u, 120u,
- 166u, 108u, 112u, 45u,
- 217u, 131u, 136u, 177u,
- 255u, 81u, 182u, 67u,
- 102u, 15u, 102u, 216u,
- 25u, 255u, 126u, 110u,
- 172u, 77u, 102u, 5u,
- 58u, 110u, 157u, 145u,
- 88u, 147u, 60u, 58u,
- 186u, 119u, 106u, 145u,
- 0u, 252u, 138u, 110u,
- 182u, 96u, 127u, 132u,
- 66u, 189u, 102u, 99u,
- 121u, 132u, 112u, 126u,
- 141u, 255u, 156u, 159u,
- 148u, 101u, 168u, 102u,
- 54u, 121u, 116u, 201u,
- 51u, 81u, 68u, 148u,
- 65u, 104u, 152u, 178u,
- 1u, 93u, 129u, 207u,
- 83u, 147u, 118u, 142u,
- 102u, 193u, 106u, 125u,
- 1u, 109u, 191u, 167u,
- 170u, 75u, 44u, 144u,
- 218u, 170u, 0u, 220u,
- 70u, 141u, 149u, 225u,
- 65u, 131u, 142u, 160u,
- 37u, 204u, 116u, 84u,
- 181u, 133u, 200u, 166u,
- 1u, 200u, 221u, 87u,
- 152u, 113u, 141u, 218u,
- 217u, 121u, 110u, 176u,
- 177u, 132u, 48u, 206u,
- 164u, 94u, 134u, 184u,
- 173u, 219u, 122u, 124u,
- 189u, 93u, 0u, 74u,
- 209u, 170u, 132u, 234u,
- 135u, 0u, 80u, 82u,
- 105u, 130u, 166u, 171u,
- 129u, 255u, 79u, 46u,
- 255u, 103u, 239u, 233u,
- 131u, 202u, 205u, 94u,
- 17u, 145u, 59u, 173u,
- 209u, 198u, 124u, 100u,
- 142u, 189u, 138u, 20u,
- 170u, 54u, 2u, 203u,
- 255u, 42u, 174u, 229u,
- 100u, 173u, 62u, 129u,
- 118u, 54u, 118u, 100u,
- 1u, 78u, 70u, 88u,
- 234u, 80u, 195u, 115u,
- 135u, 85u, 249u, 112u,
- 188u, 97u, 1u, 72u,
- 94u, 126u, 71u, 56u,
- 110u, 159u, 248u, 54u,
- 172u, 52u, 189u, 251u,
- 161u, 122u, 188u, 216u,
- 154u, 159u, 55u, 0u,
- 236u, 112u, 79u, 185u,
- 133u, 12u, 159u, 229u,
- 193u, 140u, 123u, 118u,
- 192u, 117u, 255u, 128u,
- 103u, 112u, 92u, 170u,
- 138u, 139u, 148u, 66u,
- 0u, 227u, 237u, 25u,
- 209u, 209u, 90u, 222u,
- 82u, 108u, 153u, 93u,
- 133u, 111u, 135u, 174u,
- 19u, 152u, 137u, 163u,
- 112u, 184u, 167u, 149u,
- 255u, 194u, 50u, 95u,
- 60u, 198u, 138u, 87u,
- 34u, 182u, 112u, 123u,
- 74u, 142u, 255u, 196u,
- 216u, 18u, 131u, 116u,
- 1u, 153u, 154u, 139u,
- 105u, 62u, 255u, 139u,
- 149u, 167u, 62u, 155u,
- 142u, 107u, 120u, 157u,
- 188u, 165u, 34u, 162u,
- 190u, 137u, 161u, 75u,
- 255u, 133u, 179u, 128u,
- 49u, 94u, 104u, 140u,
- 222u, 208u, 108u, 74u,
- 66u, 255u, 129u, 207u,
- 3u, 178u, 107u, 207u,
- 157u, 137u, 204u, 199u,
- 48u, 69u, 15u, 201u,
- 85u, 131u, 62u, 81u,
- 128u, 87u, 255u, 221u,
- 25u, 69u, 113u, 147u,
- 113u, 111u, 205u, 125u,
- 197u, 191u, 222u, 115u,
- 1u, 51u, 5u, 46u,
- 91u, 199u, 172u, 5u,
- 162u, 84u, 46u, 88u,
- 108u, 155u, 151u, 140u,
- 48u, 102u, 146u, 95u,
- 109u, 202u, 171u, 172u,
- 1u, 159u, 186u, 135u,
- 163u, 255u, 115u, 190u,
- 124u, 153u, 198u, 151u,
- 50u, 122u, 175u, 178u,
- 189u, 125u, 150u, 155u,
- 55u, 149u, 149u, 153u,
- 160u, 255u, 106u, 172u,
- 126u, 70u, 18u, 67u,
- 133u, 202u, 114u, 107u,
- 105u, 107u, 170u, 28u,
- 195u, 48u, 170u, 108u,
- 255u, 148u, 57u, 159u,
- 55u, 165u, 104u, 185u,
- 160u, 155u, 147u, 133u,
- 140u, 114u, 139u, 20u,
- 147u, 87u, 112u, 136u,
- 142u, 157u, 96u, 1u,
- 181u, 119u, 191u, 171u,
- 22u, 99u, 131u, 132u,
- 156u, 220u, 131u, 11u,
- 118u, 168u, 205u, 255u,
- 158u, 152u, 112u, 192u,
- 81u, 119u, 103u, 193u,
- 255u, 51u, 133u, 33u,
- 69u, 128u, 86u, 18u,
- 182u, 141u, 69u, 169u,
- 135u, 145u, 159u, 7u,
- 156u, 255u, 195u, 112u,
- 77u, 151u, 184u, 121u,
- 108u, 90u, 221u, 149u,
- 123u, 153u, 74u, 250u,
- 1u, 177u, 139u, 73u,
- 113u, 44u, 134u, 243u,
- 148u, 210u, 156u, 214u,
- 66u, 242u, 202u, 138u,
- 255u, 4u, 88u, 238u,
- 158u, 155u, 146u, 104u,
- 30u, 161u, 122u, 134u,
- 1u, 109u, 97u, 91u,
- 154u, 147u, 209u, 106u,
- 119u, 113u, 122u, 84u,
- 155u, 36u, 122u, 64u,
- 79u, 136u, 136u, 151u,
- 112u, 121u, 176u, 188u,
- 114u, 228u, 108u, 255u,
- 65u, 159u, 212u, 1u,
- 66u, 98u, 142u, 89u,
- 99u, 210u, 238u, 195u,
- 116u, 137u, 196u, 247u,
- 134u, 109u, 144u, 0u,
- 162u, 135u, 75u, 116u,
- 160u, 58u, 173u, 163u,
- 99u, 189u, 104u, 148u,
- 198u, 64u, 60u, 178u,
- 52u, 99u, 136u, 1u,
- 146u, 128u, 226u, 190u,
- 164u, 154u, 133u, 168u,
- 86u, 133u, 1u, 189u,
- 65u, 57u, 103u, 103u,
- 126u, 137u, 145u, 98u,
- 147u, 93u, 111u, 149u,
- 237u, 79u, 128u, 40u,
- 84u, 1u, 174u, 118u,
- 172u, 207u, 193u, 166u,
- 59u, 230u, 100u, 223u,
- 1u, 173u, 73u, 132u,
- 53u, 142u, 188u, 61u,
- 198u, 95u, 148u, 117u,
- 83u, 59u, 167u, 127u,
- 202u, 173u, 0u, 198u,
- 48u, 169u, 93u, 163u,
- 135u, 62u, 198u, 73u,
- 232u, 149u, 132u, 29u,
- 65u, 224u, 154u, 149u,
- 145u, 143u, 1u, 42u,
- 71u, 117u, 199u, 72u,
- 71u, 122u, 176u, 72u,
- 188u, 147u, 171u, 255u,
- 84u, 136u, 142u, 116u,
- 105u, 123u, 90u, 91u,
- 196u, 84u, 137u, 101u,
- 189u, 141u, 90u, 97u,
- 203u, 166u, 255u, 121u,
- 162u, 68u, 109u, 171u,
- 237u, 213u, 121u, 29u,
- 178u, 76u, 75u, 79u,
- 255u, 196u, 178u, 212u,
- 98u, 164u, 74u, 123u,
- 122u, 184u, 67u, 71u,
- 112u, 114u, 184u, 125u,
- 61u, 1u, 113u, 208u,
- 164u, 215u, 117u, 109u,
- 84u, 83u, 107u, 173u,
- 180u, 170u, 100u, 93u,
- 46u, 75u, 68u, 164u,
- 128u, 151u, 158u, 8u,
- 1u, 144u, 112u, 249u,
- 176u, 87u, 130u, 182u,
- 49u, 77u, 202u, 227u,
- 159u, 114u, 81u, 255u,
- 92u, 164u, 142u, 161u,
- 205u, 166u, 32u, 95u,
- 134u, 27u, 200u, 1u,
- 207u, 194u, 135u, 159u,
- 165u, 212u, 126u, 91u,
- 197u, 102u, 53u, 177u,
- 148u, 92u, 62u, 218u,
- 89u, 215u, 149u, 154u,
- 255u, 31u, 166u, 79u,
- 103u, 51u, 244u, 121u,
- 46u, 90u, 92u, 75u,
- 57u, 255u, 194u, 118u,
- 142u, 116u, 98u, 120u,
- 179u, 160u, 137u, 118u,
- 66u, 158u, 81u, 172u,
- 0u, 101u, 144u, 113u,
- 185u, 91u, 194u, 171u,
- 29u, 0u, 28u, 85u,
- 225u, 172u, 134u, 109u,
- 94u, 115u, 165u, 125u,
- 249u, 123u, 42u, 124u,
- 255u, 110u, 102u, 114u,
- 78u, 138u, 142u, 117u,
- 127u, 167u, 146u, 181u,
- 176u, 121u, 122u, 127u,
- 171u, 88u, 132u, 195u,
- 204u, 127u, 94u, 116u,
- 154u, 1u, 26u, 145u,
- 111u, 92u, 80u, 226u,
- 88u, 1u, 120u, 229u,
- 100u, 125u, 60u, 114u,
- 199u, 189u, 176u, 158u,
- 245u, 83u, 58u, 23u,
- 247u, 67u, 207u, 206u,
- 190u, 103u, 201u, 69u,
- 68u, 116u, 1u, 133u,
- 97u, 199u, 83u, 121u,
- 197u, 143u, 119u, 85u,
- 168u, 66u, 1u, 106u,
- 88u, 5u, 171u, 183u,
- 189u, 180u, 88u, 62u,
- 155u, 70u, 102u, 232u,
- 158u, 132u, 0u, 98u,
- 111u, 207u, 132u, 180u,
- 206u, 84u, 116u, 161u,
- 183u, 184u, 191u, 100u,
- 170u, 74u, 0u, 75u,
- 149u, 244u, 195u, 41u,
- 200u, 152u, 234u, 69u,
- 110u, 100u, 214u, 160u,
- 160u, 180u, 187u, 89u,
- 134u, 56u, 1u, 160u,
- 102u, 201u, 66u, 76u,
- 196u, 97u, 232u, 156u,
- 72u, 2u, 124u, 36u,
- 192u, 119u, 130u, 140u,
- 37u, 134u, 255u, 165u,
- 196u, 117u, 137u, 141u,
- 64u, 63u, 213u, 201u,
- 149u, 195u, 29u, 214u,
- 255u, 108u, 82u, 117u,
- 171u, 139u, 86u, 137u,
- 14u, 1u, 88u, 71u,
- 181u, 130u, 154u, 52u,
- 76u, 171u, 80u, 54u,
- 92u, 70u, 172u, 98u,
- 105u, 46u, 238u, 0u,
- 122u, 239u, 45u, 72u,
- 184u, 111u, 230u, 76u,
- 158u, 1u, 139u, 149u,
- 54u, 57u, 144u, 132u,
- 205u, 222u, 67u, 162u,
- 86u, 193u, 191u, 205u,
- 111u, 110u, 147u, 35u,
- 109u, 146u, 51u, 194u,
- 0u, 189u, 213u, 201u,
- 21u, 20u, 84u, 123u,
- 132u, 55u, 38u, 163u,
- 118u, 116u, 183u, 129u,
- 231u, 186u, 139u, 155u,
- 149u, 160u, 66u, 1u,
- 41u, 92u, 191u, 100u,
- 67u, 164u, 153u, 87u,
- 214u, 74u, 177u, 115u,
- 72u, 93u, 117u, 255u,
- 90u, 44u, 142u, 149u,
- 101u, 46u, 123u, 23u,
- 1u, 135u, 85u, 88u,
- 155u, 137u, 167u, 170u,
- 126u, 102u, 28u, 86u,
- 134u, 36u, 228u, 60u,
- 71u, 239u, 89u, 237u,
- 255u, 65u, 129u, 35u,
- 159u, 224u, 56u, 128u,
- 129u, 187u, 67u, 144u,
- 180u, 209u, 91u, 70u,
- 100u, 80u, 1u, 106u,
- 143u, 191u, 143u, 121u,
- 247u, 1u, 188u, 82u,
- 67u, 178u, 36u, 214u,
- 182u, 13u, 236u, 150u,
- 188u, 0u, 210u, 177u,
- 212u, 169u, 92u, 105u,
- 176u, 137u, 99u, 105u,
- 142u, 57u, 105u, 160u,
- 164u, 120u, 255u, 139u,
- 112u, 91u, 40u, 54u,
- 220u, 92u, 107u, 95u,
- 73u, 57u, 143u, 80u,
- 51u, 136u, 194u, 121u,
- 146u, 198u, 150u, 152u,
- 118u, 164u, 52u, 148u,
- 255u, 150u, 29u, 105u,
- 92u, 127u, 48u, 56u,
- 230u, 123u, 113u, 174u,
- 89u, 207u, 103u, 116u,
- 80u, 16u, 97u, 255u,
- 94u, 148u, 229u, 97u,
- 66u, 185u, 181u, 1u,
- 143u, 186u, 181u, 117u,
- 146u, 33u, 139u, 115u,
- 96u, 184u, 97u, 186u,
- 149u, 27u, 156u, 176u,
- 1u, 112u, 154u, 127u,
- 55u, 98u, 127u, 196u,
- 76u, 126u, 172u, 40u,
- 255u, 105u, 51u, 210u,
- 80u, 155u, 152u, 203u,
- 182u, 129u, 128u, 113u,
- 30u, 113u, 42u, 255u,
- 32u, 84u, 219u, 89u,
- 169u, 74u, 136u, 97u,
- 138u, 87u, 202u, 127u,
- 89u, 147u, 111u, 63u,
- 156u, 156u, 60u, 119u,
- 226u, 1u, 96u, 171u,
- 74u, 45u, 98u, 173u,
- 117u, 173u, 174u, 170u,
- 112u, 201u, 105u, 174u,
- 144u, 124u, 211u, 155u,
- 255u, 134u, 126u, 186u,
- 122u, 124u, 102u, 181u,
- 160u, 144u, 125u, 42u,
- 212u, 155u, 36u, 77u,
- 91u, 1u, 187u, 217u,
- 255u, 121u, 198u, 176u,
- 58u, 149u, 206u, 153u,
- 130u, 157u, 64u, 92u,
- 166u, 99u, 47u, 103u,
- 123u, 14u, 210u, 160u,
- 47u, 92u, 49u, 255u,
- 107u, 220u, 65u, 85u,
- 133u, 1u, 1u, 95u,
- 108u, 125u, 125u, 148u,
- 156u, 43u, 255u, 118u,
- 36u, 183u, 129u, 200u,
- 143u, 110u, 192u, 240u,
- 140u, 138u, 197u, 65u,
- 148u, 154u, 158u, 178u,
- 95u, 92u, 115u, 110u,
- 1u, 123u, 156u, 172u,
- 167u, 79u, 189u, 96u,
- 220u, 128u, 243u, 239u,
- 107u, 204u, 173u, 216u,
- 255u, 119u, 155u, 57u,
- 25u, 98u, 104u, 121u,
- 83u, 165u, 111u, 209u,
- 148u, 51u, 125u, 149u,
- 40u, 1u, 219u, 214u,
- 241u, 112u, 118u, 78u,
- 70u, 76u, 113u, 130u,
- 101u, 247u, 91u, 14u,
- 1u, 184u, 154u, 52u,
- 108u, 138u, 234u, 90u,
- 255u, 117u, 180u, 70u,
- 151u, 56u, 125u, 149u,
- 172u, 145u, 165u, 153u,
- 152u, 155u, 231u, 149u,
- 185u, 96u, 180u, 156u,
- 208u, 30u, 1u, 105u,
- 169u, 80u, 169u, 142u,
- 93u, 79u, 162u, 210u,
- 130u, 124u, 181u, 199u,
- 197u, 105u, 101u, 150u,
- 241u, 76u, 255u, 134u,
- 128u, 110u, 81u, 169u,
- 169u, 127u, 158u, 115u,
- 199u, 25u, 2u, 150u,
- 255u, 167u, 71u, 175u,
- 133u, 95u, 99u, 1u,
- 132u, 188u, 181u, 196u,
- 185u, 226u, 113u, 160u,
- 154u, 141u, 177u, 123u,
- 176u, 153u, 94u, 220u,
- 1u, 182u, 144u, 21u,
- 104u, 55u, 119u, 136u,
- 172u, 221u, 200u, 220u,
- 173u, 229u, 228u, 14u,
- 7u, 215u, 102u, 126u,
- 43u, 137u, 255u, 178u,
- 245u, 246u, 51u, 225u,
- 119u, 174u, 82u, 89u,
- 175u, 185u, 152u, 208u,
- 129u, 89u, 90u, 255u,
- 112u, 108u, 208u, 228u,
- 114u, 177u, 166u, 0u,
- 162u, 136u, 119u, 139u,
- 157u, 101u, 212u, 222u,
- 132u, 211u, 92u, 129u,
- 57u, 62u, 197u, 20u,
- 55u, 73u, 99u, 158u,
- 46u, 214u, 113u, 255u,
- 73u, 79u, 186u, 230u,
- 139u, 119u, 9u, 110u,
- 16u, 69u, 177u, 101u,
- 119u, 255u, 243u, 127u,
- 224u, 29u, 207u, 11u,
- 112u, 108u, 167u, 70u,
- 183u, 117u, 146u, 143u,
- 134u, 136u, 245u, 255u,
- 182u, 126u, 208u, 181u,
- 14u, 100u, 18u, 2u,
- 82u, 28u, 200u, 255u,
- 84u, 91u, 182u, 192u,
- 50u, 171u, 160u, 206u,
- 70u, 1u, 142u, 99u,
- 195u, 197u, 135u, 209u,
- 168u, 189u, 152u, 89u,
- 163u, 123u, 216u, 106u,
- 196u, 79u, 75u, 166u,
- 18u, 57u, 152u, 171u,
- 65u, 197u, 112u, 244u,
- 1u, 185u, 62u, 201u,
- 199u, 82u, 217u, 1u,
- 214u, 103u, 214u, 50u,
- 87u, 149u, 47u, 122u,
- 139u, 242u, 209u, 113u,
- 128u, 206u, 188u, 1u,
- 71u, 139u, 174u, 221u,
- 85u, 225u, 187u, 151u,
- 132u, 103u, 161u, 55u,
- 168u, 110u, 191u, 168u,
- 32u, 204u, 211u, 245u,
- 225u, 242u, 129u, 44u,
- 156u, 255u, 90u, 5u,
- 200u, 111u, 255u, 136u,
- 81u, 32u, 95u, 107u,
- 78u, 188u, 128u, 159u,
- 127u, 143u, 7u, 39u,
- 172u, 170u, 126u, 215u,
- 171u, 189u, 87u, 65u,
- 84u, 105u, 104u, 227u,
- 1u, 171u, 163u, 201u,
- 157u, 94u, 56u, 255u,
- 145u, 34u, 201u, 240u,
- 53u, 158u, 89u, 21u,
- 163u, 115u, 127u, 19u,
- 5u, 71u, 230u, 194u,
- 1u, 147u, 161u, 84u,
- 74u, 177u, 134u, 13u,
- 106u, 82u, 34u, 230u,
- 196u, 43u, 139u, 109u,
- 127u, 150u, 178u, 184u,
- 174u, 21u, 73u, 155u,
- 182u, 0u, 37u, 189u,
- 77u, 98u, 127u, 138u,
- 121u, 121u, 37u, 148u,
- 140u, 45u, 126u, 78u,
- 1u, 139u, 185u, 176u,
- 187u, 225u, 5u, 0u,
- 222u, 113u, 183u, 172u,
- 117u, 150u, 101u, 214u,
- 177u, 147u, 171u, 66u,
- 39u, 180u, 182u, 70u,
- 162u, 83u, 96u, 134u,
- 0u, 218u, 192u, 225u,
- 144u, 252u, 120u, 92u,
- 89u, 140u, 229u, 121u,
- 181u, 222u, 24u, 255u,
- 230u, 53u, 249u, 175u,
- 245u, 101u, 107u, 98u,
- 75u, 96u, 120u, 33u,
- 109u, 76u, 229u, 223u,
- 117u, 255u, 152u, 240u,
- 151u, 100u, 143u, 178u,
- 128u, 177u, 109u, 151u,
- 197u, 98u, 39u, 255u,
- 172u, 73u, 161u, 82u,
- 45u, 94u, 29u, 43u,
- 130u, 123u, 196u, 255u,
- 178u, 91u, 177u, 33u,
- 23u, 95u, 26u, 167u,
- 135u, 90u, 178u, 96u,
- 156u, 189u, 125u, 159u,
- 111u, 76u, 29u, 131u,
- 67u, 39u, 172u, 127u,
- 93u, 146u, 120u, 1u,
- 149u, 255u, 189u, 29u,
- 168u, 192u, 129u, 236u,
- 22u, 228u, 28u, 82u,
- 159u, 197u, 52u, 111u,
- 138u, 129u, 72u, 130u,
- 90u, 121u, 146u, 126u,
- 122u, 255u, 126u, 135u,
- 110u, 128u, 118u, 182u,
- 151u, 4u, 228u, 141u,
- 179u, 100u, 184u, 79u,
- 255u, 37u, 6u, 118u,
- 200u, 248u, 87u, 183u,
- 124u, 119u, 109u, 192u,
- 110u, 109u, 113u, 157u,
- 255u, 148u, 142u, 107u,
- 108u, 59u, 56u, 44u,
- 107u, 134u, 118u, 113u,
- 58u, 103u, 189u, 156u,
- 170u, 111u, 164u, 255u,
- 203u, 145u, 173u, 102u,
- 53u, 123u, 156u, 198u,
- 94u, 70u, 102u, 92u,
- 109u, 143u, 255u, 59u,
- 157u, 140u, 159u, 182u,
- 70u, 68u, 180u, 131u,
- 101u, 103u, 153u, 107u,
- 174u, 55u, 126u, 0u,
- 132u, 124u, 150u, 121u,
- 141u, 202u, 168u, 63u,
- 167u, 159u, 61u, 159u,
- 183u, 65u, 255u, 190u,
- 147u, 146u, 44u, 123u,
- 109u, 142u, 134u, 158u,
- 100u, 33u, 255u, 141u,
- 159u, 48u, 133u, 140u,
- 154u, 89u, 50u, 35u,
- 127u, 49u, 110u, 109u,
- 156u, 207u, 211u, 163u,
- 162u, 44u, 47u, 170u,
- 114u, 255u, 59u, 180u,
- 14u, 210u, 186u, 174u,
- 56u, 206u, 188u, 1u,
- 116u, 219u, 46u, 94u,
- 141u, 170u, 114u, 58u,
- 198u, 104u, 122u, 185u,
- 109u, 116u, 183u, 91u,
- 68u, 156u, 171u, 255u,
- 34u, 144u, 51u, 141u,
- 98u, 184u, 188u, 111u,
- 125u, 126u, 1u, 164u,
- 142u, 203u, 214u, 76u,
- 102u, 87u, 33u, 158u,
- 158u, 114u, 154u, 136u,
- 154u, 115u, 158u, 50u,
- 120u, 24u, 174u, 191u,
- 35u, 255u, 82u, 193u,
- 54u, 126u, 170u, 149u,
- 10u, 221u, 10u, 89u,
- 125u, 181u, 211u, 117u,
- 121u, 65u, 1u, 108u,
- 203u, 252u, 193u, 60u,
- 45u, 160u, 85u, 60u,
- 176u, 1u, 238u, 134u,
- 63u, 251u, 58u, 163u,
- 165u, 179u, 102u, 170u,
- 63u, 233u, 117u, 0u,
- 32u, 140u, 180u, 114u,
- 188u, 103u, 231u, 163u,
- 137u, 89u, 165u, 153u,
- 69u, 142u, 88u, 125u,
- 34u, 255u, 65u, 51u,
- 40u, 69u, 79u, 142u,
- 130u, 51u, 92u, 137u,
- 22u, 21u, 120u, 53u,
- 247u, 255u, 231u, 95u,
- 192u, 46u, 14u, 51u,
- 113u, 116u, 175u, 1u,
- 133u, 177u, 159u, 61u,
- 102u, 27u, 155u, 131u,
- 109u, 205u, 85u, 115u,
- 45u, 141u, 1u, 132u,
- 120u, 228u, 71u, 164u,
- 77u, 196u, 177u, 168u,
- 165u, 140u, 17u, 113u,
- 136u, 123u, 117u, 187u,
- 1u, 199u, 117u, 112u,
- 132u, 136u, 188u, 113u,
- 147u, 248u, 241u, 203u,
- 21u, 164u, 255u, 74u,
- 124u, 124u, 75u, 115u,
- 114u, 201u, 114u, 216u,
- 136u, 46u, 168u, 177u,
- 120u, 82u, 76u, 255u,
- 185u, 131u, 109u, 176u,
- 219u, 82u, 136u, 152u,
- 130u, 75u, 11u, 156u,
- 169u, 124u, 102u, 190u,
- 74u, 59u, 133u, 49u,
- 74u, 92u, 233u, 255u,
- 245u, 131u, 125u, 58u,
- 163u, 255u, 82u, 127u,
- 130u, 66u, 88u, 237u,
- 115u, 147u, 160u, 168u,
- 248u, 79u, 91u, 16u,
- 109u, 61u, 1u, 116u,
- 175u, 56u, 153u, 158u,
- 138u, 131u, 122u, 136u,
- 129u, 174u, 206u, 56u,
- 158u, 150u, 51u, 232u,
- 36u, 76u, 112u, 181u,
- 230u, 95u, 211u, 56u,
- 221u, 255u, 181u, 154u,
- 185u, 56u, 36u, 210u,
- 148u, 177u, 78u, 97u,
- 118u, 255u, 185u, 133u,
- 198u, 40u, 102u, 140u,
- 47u, 119u, 78u, 132u,
- 16u, 151u, 4u, 207u,
- 149u, 124u, 255u, 177u,
- 39u, 126u, 184u, 214u,
- 169u, 198u, 156u, 226u,
- 12u, 207u, 154u, 1u,
- 34u, 167u, 49u, 25u,
- 152u, 112u, 25u, 130u,
- 120u, 228u, 225u, 175u,
- 86u, 124u, 198u, 219u,
- 38u, 165u, 142u, 255u,
- 169u, 80u, 132u, 209u,
- 91u, 137u, 133u, 178u,
- 57u, 186u, 255u, 131u,
- 141u, 105u, 84u, 195u,
- 115u, 182u, 54u, 194u,
- 186u, 115u, 60u, 121u,
- 170u, 111u, 119u, 178u,
- 80u, 120u, 249u, 255u,
- 139u, 59u, 38u, 179u,
- 167u, 36u, 255u, 58u,
- 212u, 192u, 126u, 149u,
- 69u, 157u, 95u, 74u,
- 44u, 249u, 52u, 222u,
- 175u, 84u, 1u, 195u,
- 104u, 148u, 67u, 89u,
- 139u, 168u, 64u, 104u,
- 154u, 192u, 104u, 127u,
- 127u, 112u, 92u, 133u,
- 159u, 109u, 101u, 156u,
- 255u, 37u, 125u, 80u,
- 165u, 158u, 145u, 112u,
- 181u, 68u, 159u, 67u,
- 161u, 90u, 95u, 92u,
- 76u, 73u, 134u, 74u,
- 149u, 128u, 80u, 1u,
- 163u, 210u, 62u, 140u,
- 99u, 172u, 106u, 255u,
- 112u, 255u, 12u, 53u,
- 75u, 191u, 2u, 235u,
- 230u, 92u, 0u, 207u,
- 47u, 223u, 99u, 166u,
- 194u, 109u, 183u, 106u,
- 137u, 204u, 87u, 101u,
- 132u, 32u, 170u, 83u,
- 177u, 40u, 136u, 101u,
- 241u, 68u, 136u, 155u,
- 152u, 136u, 28u, 1u,
- 161u, 205u, 172u, 137u,
- 0u, 249u, 146u, 59u,
- 111u, 5u, 67u, 101u,
- 112u, 36u, 27u, 186u,
- 164u, 184u, 42u, 88u,
- 122u, 125u, 205u, 156u,
- 165u, 185u, 146u, 255u,
- 115u, 114u, 97u, 118u,
- 190u, 58u, 179u, 4u,
- 238u, 213u, 0u, 141u,
- 107u, 140u, 66u, 19u,
- 138u, 131u, 139u, 191u,
- 1u, 23u, 43u, 137u,
- 141u, 56u, 107u, 178u,
- 61u, 154u, 54u, 89u,
- 110u, 137u, 186u, 156u,
- 99u, 110u, 151u, 59u,
- 183u, 124u, 124u, 115u,
- 143u, 75u, 255u, 122u,
- 150u, 96u, 209u, 138u,
- 140u, 66u, 132u, 191u,
- 1u, 156u, 146u, 134u,
- 146u, 104u, 79u, 153u,
- 129u, 64u, 62u, 115u,
- 48u, 73u, 83u, 189u,
- 112u, 89u, 43u, 255u,
- 174u, 77u, 146u, 202u,
- 170u, 152u, 102u, 101u,
- 206u, 108u, 61u, 64u,
- 215u, 181u, 105u, 86u,
- 105u, 126u, 1u, 217u,
- 82u, 123u, 84u, 143u,
- 176u, 142u, 249u, 130u,
- 228u, 85u, 248u, 5u,
- 142u, 143u, 1u, 100u,
- 161u, 194u, 163u, 147u,
- 93u, 209u, 40u, 0u,
- 110u, 219u, 34u, 186u,
- 130u, 54u, 231u, 213u,
- 193u, 247u, 175u, 94u,
- 54u, 134u, 196u, 1u,
- 114u, 138u, 90u, 132u,
- 188u, 87u, 162u, 63u,
- 76u, 184u, 131u, 93u,
- 166u, 178u, 110u, 108u,
- 253u, 89u, 159u, 8u,
- 255u, 39u, 235u, 232u,
- 144u, 90u, 47u, 91u,
- 76u, 115u, 166u, 206u,
- 160u, 217u, 10u, 113u,
- 141u, 100u, 100u, 145u,
- 1u, 154u, 50u, 235u,
- 189u, 73u, 59u, 170u,
- 87u, 213u, 191u, 95u,
- 95u, 1u, 165u, 195u,
- 40u, 240u, 100u, 198u,
- 235u, 150u, 255u, 97u,
- 39u, 238u, 156u, 29u,
- 188u, 64u, 185u, 162u,
- 105u, 207u, 100u, 222u,
- 6u, 152u, 68u, 106u,
- 44u, 167u, 181u, 255u,
- 227u, 240u, 46u, 73u,
- 73u, 167u, 39u, 147u,
- 101u, 94u, 43u, 121u,
- 232u, 129u, 211u, 255u,
- 184u, 56u, 77u, 17u,
- 113u, 253u, 212u, 120u,
- 148u, 93u, 139u, 186u,
- 165u, 183u, 77u, 66u,
- 119u, 90u, 1u, 38u,
- 101u, 208u, 79u, 145u,
- 122u, 97u, 138u, 153u,
- 95u, 22u, 7u, 68u,
- 179u, 118u, 132u, 41u,
- 1u, 160u, 140u, 111u,
- 141u, 89u, 73u, 144u,
- 1u, 99u, 144u, 44u,
- 122u, 143u, 147u, 106u,
- 118u, 96u, 188u, 193u,
- 31u, 155u, 116u, 30u,
- 78u, 185u, 105u, 255u,
- 116u, 161u, 176u, 142u,
- 77u, 55u, 136u, 148u,
- 201u, 41u, 255u, 170u,
- 230u, 160u, 134u, 102u,
- 236u, 193u, 97u, 232u,
- 233u, 239u, 252u, 199u,
- 128u, 120u, 116u, 89u,
- 94u, 110u, 210u, 157u,
- 241u, 1u, 184u, 134u,
- 123u, 144u, 140u, 135u,
- 159u, 45u, 162u, 129u,
- 134u, 161u, 114u, 117u,
- 255u, 185u, 129u, 140u,
- 153u, 83u, 116u, 86u,
- 207u, 82u, 42u, 49u,
- 182u, 127u, 14u, 255u,
- 187u, 34u, 183u, 221u,
- 64u, 207u, 86u, 227u,
- 79u, 132u, 149u, 1u,
- 114u, 120u, 155u, 118u,
- 93u, 183u, 157u, 130u,
- 92u, 70u, 197u, 187u,
- 109u, 130u, 139u, 226u,
- 186u, 188u, 211u, 132u,
- 228u, 179u, 109u, 255u,
- 153u, 192u, 114u, 155u,
- 74u, 187u, 255u, 104u,
- 40u, 98u, 210u, 198u,
- 195u, 62u, 156u, 126u,
- 141u, 45u, 118u, 189u,
- 97u, 176u, 84u, 255u,
- 51u, 190u, 158u, 101u,
- 64u, 227u, 106u, 157u,
- 157u, 60u, 133u, 196u,
- 156u, 68u, 255u, 174u,
- 91u, 146u, 186u, 166u,
- 216u, 192u, 201u, 145u,
- 175u, 21u, 108u, 127u,
- 1u, 231u, 119u, 113u,
- 144u, 159u, 166u, 167u,
- 73u, 63u, 53u, 139u,
- 179u, 71u, 83u, 85u,
- 58u, 150u, 88u, 1u,
- 64u, 124u, 191u, 140u,
- 131u, 177u, 206u, 166u,
- 30u, 218u, 193u, 113u,
- 156u, 149u, 206u, 137u,
- 3u, 153u, 0u, 91u,
- 78u, 192u, 163u, 44u,
- 145u, 73u, 70u, 93u,
- 1u, 145u, 190u, 138u,
- 67u, 206u, 119u, 171u,
- 99u, 75u, 73u, 64u,
- 79u, 166u, 153u, 145u,
- 93u, 163u, 77u, 86u,
- 123u, 95u, 120u, 34u,
- 71u, 137u, 149u, 130u,
- 143u, 255u, 212u, 120u,
- 103u, 158u, 89u, 197u,
- 183u, 101u, 47u, 161u,
- 100u, 41u, 111u, 103u,
- 106u, 168u, 255u, 174u,
- 162u, 102u, 82u, 207u,
- 99u, 13u, 139u, 135u,
- 53u, 154u, 67u, 100u,
- 215u, 1u, 136u, 101u,
- 95u, 120u, 153u, 133u,
- 188u, 133u, 124u, 119u,
- 113u, 183u, 151u, 255u,
- 159u, 182u, 68u, 144u,
- 148u, 133u, 131u, 217u,
- 115u, 115u, 255u, 93u,
- 119u, 142u, 71u, 164u,
- 128u, 145u, 118u, 171u,
- 128u, 142u, 1u, 181u,
- 16u, 53u, 56u, 91u,
- 102u, 246u, 202u, 83u,
- 174u, 88u, 151u, 111u,
- 59u, 89u, 146u, 91u,
- 80u, 217u, 66u, 143u,
- 104u, 200u, 161u, 0u,
- 105u, 255u, 54u, 170u,
- 79u, 192u, 102u, 1u,
- 186u, 136u, 141u, 192u,
- 234u, 174u, 132u, 176u,
- 66u, 156u, 130u, 137u,
- 41u, 156u, 164u, 152u,
- 96u, 110u, 215u, 127u,
- 152u, 136u, 152u, 225u,
- 127u, 75u, 255u, 162u,
- 158u, 95u, 127u, 1u,
- 189u, 196u, 111u, 109u,
- 143u, 120u, 142u, 117u,
- 91u, 206u, 157u, 160u,
- 7u, 187u, 117u, 51u,
- 115u, 66u, 1u, 106u,
- 36u, 184u, 176u, 20u,
- 214u, 149u, 232u, 69u,
- 132u, 142u, 169u, 23u,
- 132u, 39u, 132u, 27u,
- 68u, 83u, 255u, 219u,
- 42u, 149u, 80u, 76u,
- 73u, 162u, 70u, 39u,
- 194u, 59u, 71u, 255u,
- 93u, 233u, 147u, 158u,
- 146u, 31u, 71u, 190u,
- 99u, 57u, 183u, 152u,
- 38u, 150u, 215u, 227u,
- 140u, 199u, 171u, 117u,
- 59u, 158u, 198u, 255u,
- 181u, 147u, 255u, 163u,
- 133u, 170u, 24u, 137u,
- 115u, 128u, 151u, 89u,
- 132u, 188u, 111u, 91u,
- 188u, 165u, 128u, 156u,
- 188u, 252u, 172u, 128u,
- 119u, 143u, 93u, 226u,
- 255u, 37u, 217u, 144u,
- 16u, 121u, 48u, 109u,
- 27u, 187u, 122u, 112u,
- 42u, 127u, 68u, 202u,
- 241u, 255u, 46u, 178u,
- 154u, 136u, 159u, 104u,
- 128u, 235u, 162u, 184u,
- 165u, 83u, 165u, 211u,
- 134u, 193u, 1u, 185u,
- 137u, 147u, 101u, 112u,
- 182u, 61u, 76u, 99u,
- 135u, 183u, 111u, 188u,
- 173u, 1u, 42u, 119u,
- 59u, 75u, 119u, 123u,
- 160u, 108u, 180u, 92u,
- 255u, 96u, 70u, 112u,
- 23u, 112u, 153u, 182u,
- 67u, 1u, 88u, 181u,
- 141u, 112u, 174u, 241u,
- 244u, 66u, 66u, 170u,
- 134u, 91u, 193u, 191u,
- 165u, 110u, 164u, 170u,
- 144u, 167u, 23u, 1u,
- 148u, 89u, 167u, 119u,
- 164u, 96u, 113u, 141u,
- 156u, 120u, 104u, 147u,
- 98u, 110u, 133u, 121u,
- 119u, 98u, 199u, 0u,
- 162u, 28u, 175u, 157u,
- 115u, 158u, 237u, 21u,
- 89u, 129u, 140u, 138u,
- 149u, 146u, 255u, 139u,
- 134u, 138u, 216u, 214u,
- 73u, 97u, 114u, 119u,
- 0u, 137u, 112u, 189u,
- 56u, 177u, 158u, 134u,
- 76u, 21u, 131u, 131u,
- 126u, 7u, 38u, 48u,
- 142u, 48u, 133u, 215u,
- 61u, 234u, 80u, 75u,
- 1u, 179u, 61u, 164u,
- 129u, 82u, 146u, 71u,
- 125u, 88u, 255u, 99u,
- 168u, 94u, 145u, 164u,
- 86u, 244u, 164u, 156u,
- 172u, 120u, 66u, 106u,
- 1u, 36u, 211u, 82u,
- 96u, 215u, 119u, 158u,
- 142u, 36u, 204u, 130u,
- 125u, 190u, 156u, 160u,
- 39u, 112u, 169u, 116u,
- 90u, 167u, 118u, 255u,
- 48u, 63u, 67u, 219u,
- 182u, 129u, 198u, 109u,
- 1u, 109u, 161u, 106u,
- 141u, 214u, 146u, 57u,
- 96u, 172u, 192u, 49u,
- 155u, 119u, 137u, 112u,
- 114u, 147u, 188u, 208u,
- 97u, 138u, 0u, 54u,
- 78u, 87u, 129u, 113u,
- 134u, 120u, 104u, 146u,
- 145u, 151u, 150u, 135u,
- 87u, 255u, 141u, 115u,
- 206u, 94u, 85u, 77u,
- 140u, 223u, 150u, 1u,
- 166u, 172u, 130u, 145u,
- 98u, 99u, 55u, 61u,
- 179u, 188u, 122u, 132u,
- 255u, 89u, 187u, 177u,
- 59u, 157u, 69u, 108u,
- 129u, 134u, 100u, 202u,
- 159u, 204u, 34u, 229u,
- 155u, 169u, 39u, 77u,
- 177u, 138u, 109u, 210u,
- 175u, 24u, 21u, 140u,
- 33u, 1u, 103u, 169u,
- 180u, 145u, 139u, 122u,
- 132u, 127u, 115u, 78u,
- 186u, 108u, 174u, 188u,
- 180u, 169u, 1u, 63u,
- 199u, 77u, 1u, 63u,
- 110u, 83u, 112u, 26u,
- 62u, 168u, 150u, 160u,
- 248u, 151u, 252u, 102u,
- 6u, 110u, 90u, 69u,
- 74u, 217u, 87u, 210u,
- 175u, 110u, 170u, 141u,
- 41u, 1u, 66u, 171u,
- 215u, 57u, 9u, 228u,
- 151u, 96u, 18u, 51u,
- 186u, 156u, 69u, 93u,
- 59u, 106u, 1u, 52u,
- 201u, 119u, 110u, 146u,
- 176u, 146u, 71u, 139u,
- 117u, 97u, 129u, 255u,
- 55u, 14u, 168u, 211u,
- 74u, 198u, 167u, 158u,
- 114u, 142u, 1u, 94u,
- 14u, 184u, 144u, 152u,
- 186u, 50u, 82u, 135u,
- 77u, 55u, 98u, 3u,
- 115u, 255u, 201u, 62u,
- 76u, 98u, 12u, 126u,
- 26u, 50u, 232u, 221u,
- 212u, 174u, 156u, 230u,
- 117u, 107u, 206u, 41u,
- 203u, 1u, 89u, 148u,
- 149u, 172u, 78u, 95u,
- 49u, 66u, 111u, 178u,
- 70u, 94u, 119u, 106u,
- 122u, 1u, 89u, 116u,
- 90u, 186u, 109u, 111u,
- 130u, 119u, 164u, 165u,
- 1u, 169u, 105u, 92u,
- 173u, 39u, 161u, 64u,
- 194u, 223u, 180u, 118u,
- 137u, 197u, 142u, 115u,
- 90u, 185u, 42u, 93u,
- 255u, 158u, 165u, 135u,
- 53u, 96u, 150u, 124u,
- 193u, 88u, 200u, 198u,
- 191u, 218u, 140u, 71u,
- 206u, 39u, 56u, 255u,
- 55u, 155u, 131u, 236u,
- 119u, 47u, 142u, 111u,
- 113u, 235u, 117u, 38u,
- 152u, 116u, 0u, 218u,
- 150u, 143u, 204u, 164u,
- 184u, 59u, 140u, 220u,
- 225u, 15u, 151u, 165u,
- 86u, 181u, 0u, 216u,
- 164u, 97u, 148u, 70u,
- 168u, 83u, 177u, 134u,
- 1u, 106u, 89u, 160u,
- 248u, 9u, 169u, 201u,
- 48u, 101u, 60u, 119u,
- 50u, 88u, 124u, 157u,
- 123u, 158u, 213u, 132u,
- 55u, 0u, 112u, 155u,
- 140u, 183u, 127u, 184u,
- 147u, 88u, 145u, 110u,
- 45u, 203u, 255u, 125u,
- 122u, 235u, 107u, 171u,
- 155u, 53u, 167u, 158u,
- 110u, 249u, 185u, 43u,
- 153u, 197u, 3u, 181u,
- 97u, 184u, 201u, 147u,
- 165u, 130u, 148u, 255u,
- 106u, 54u, 140u, 92u,
- 255u, 233u, 143u, 216u,
- 92u, 45u, 34u, 173u,
- 126u, 131u, 67u, 108u,
- 146u, 21u, 150u, 181u,
- 84u, 255u, 154u, 116u,
- 157u, 93u, 109u, 156u,
- 166u, 133u, 136u, 189u,
- 56u, 25u, 113u, 225u,
- 99u, 226u, 105u, 65u,
- 180u, 119u, 204u, 112u,
- 255u, 125u, 142u, 108u,
- 89u, 118u, 179u, 67u,
- 103u, 1u, 92u, 173u,
- 126u, 244u, 142u, 117u,
- 7u, 7u, 125u, 77u,
- 99u, 101u, 125u, 110u,
- 61u, 214u, 118u, 121u,
- 34u, 121u, 155u, 40u,
- 117u, 77u, 87u, 255u,
- 176u, 164u, 255u, 168u,
- 14u, 124u, 29u, 4u,
- 225u, 46u, 162u, 162u,
- 177u, 108u, 53u, 140u,
- 207u, 152u, 211u, 175u,
- 121u, 231u, 64u, 255u,
- 203u, 82u, 106u, 92u,
- 187u, 150u, 111u, 69u,
- 88u, 134u, 75u, 1u,
- 105u, 56u, 128u, 77u,
- 68u, 64u, 212u, 206u,
- 90u, 205u, 100u, 133u,
- 198u, 52u, 173u, 97u,
- 144u, 106u, 90u, 255u,
- 108u, 170u, 135u, 153u,
- 3u, 253u, 28u, 65u,
- 118u, 189u, 123u, 70u,
- 67u, 195u, 145u, 111u,
- 136u, 88u, 255u, 102u,
- 74u, 94u, 120u, 140u,
- 1u, 1u, 106u, 58u,
- 119u, 218u, 218u, 186u,
- 203u, 6u, 21u, 127u,
- 50u, 138u, 77u, 190u,
- 99u, 161u, 49u, 167u,
- 55u, 29u, 114u, 150u,
- 225u, 161u, 198u, 41u,
- 239u, 1u, 162u, 63u,
- 80u, 104u, 106u, 102u,
- 129u, 254u, 161u, 146u,
- 90u, 238u, 78u, 64u,
- 105u, 67u, 105u, 1u,
- 26u, 227u, 54u, 153u,
- 1u, 81u, 216u, 142u,
- 99u, 196u, 158u, 196u,
- 40u, 59u, 198u, 167u,
- 187u, 138u, 157u, 117u,
- 140u, 127u, 123u, 166u,
- 0u, 232u, 206u, 184u,
- 188u, 142u, 121u, 179u,
- 125u, 163u, 116u, 55u,
- 155u, 130u, 90u, 146u,
- 88u, 187u, 153u, 103u,
- 119u, 255u, 105u, 150u,
- 143u, 82u, 148u, 149u,
- 118u, 72u, 1u, 111u,
- 55u, 241u, 168u, 161u,
- 222u, 107u, 195u, 82u,
- 128u, 131u, 151u, 189u,
- 154u, 128u, 96u, 126u,
- 255u, 75u, 120u, 42u,
- 138u, 102u, 104u, 82u,
- 1u, 185u, 113u, 46u,
- 29u, 93u, 230u, 156u,
- 174u, 79u, 168u, 172u,
- 203u, 28u, 46u, 88u,
- 189u, 69u, 171u, 160u,
- 40u, 178u, 153u, 40u,
- 6u, 100u, 30u, 28u,
- 144u, 255u, 230u, 171u,
- 160u, 48u, 78u, 255u,
- 194u, 166u, 143u, 107u,
- 166u, 91u, 90u, 87u,
- 183u, 199u, 213u, 50u,
- 114u, 141u, 0u, 130u,
- 130u, 76u, 216u, 142u,
- 147u, 89u, 118u, 193u,
- 94u, 94u, 106u, 110u,
- 164u, 192u, 242u, 81u,
- 115u, 162u, 1u, 80u,
- 51u, 127u, 222u, 86u,
- 222u, 159u, 178u, 1u,
- 122u, 92u, 255u, 142u,
- 119u, 99u, 77u, 77u,
- 113u, 113u, 106u, 121u,
- 149u, 158u, 107u, 162u,
- 1u, 200u, 88u, 101u,
- 101u, 228u, 168u, 168u,
- 91u, 89u, 182u, 151u,
- 196u, 228u, 118u, 142u,
- 53u, 189u, 161u, 16u,
- 73u, 208u, 198u, 151u,
- 187u, 226u, 169u, 175u,
- 217u, 1u, 148u, 181u,
- 148u, 255u, 171u, 70u,
- 34u, 160u, 6u, 1u,
- 224u, 62u, 226u, 177u,
- 96u, 119u, 37u, 109u,
- 106u, 63u, 77u, 141u,
- 163u, 121u, 40u, 7u,
- 255u, 123u, 172u, 212u,
- 178u, 185u, 174u, 145u,
- 29u, 30u, 181u, 1u,
- 68u, 81u, 216u, 111u,
- 171u, 124u, 230u, 165u,
- 69u, 140u, 131u, 150u,
- 203u, 175u, 145u, 15u,
- 71u, 157u, 195u, 255u,
- 86u, 136u, 146u, 251u,
- 89u, 82u, 134u, 145u,
- 101u, 118u, 153u, 168u,
- 44u, 135u, 212u, 101u,
- 60u, 62u, 67u, 43u,
- 156u, 1u, 192u, 66u,
- 249u, 109u, 255u, 117u,
- 172u, 161u, 203u, 196u,
- 22u, 126u, 177u, 161u,
- 113u, 196u, 146u, 125u,
- 74u, 134u, 158u, 105u,
- 242u, 113u, 174u, 15u,
- 204u, 54u, 77u, 255u,
- 103u, 43u, 178u, 200u,
- 74u, 162u, 223u, 81u,
- 14u, 149u, 181u, 199u,
- 84u, 255u, 161u, 186u,
- 234u, 41u, 155u, 98u,
- 255u, 43u, 106u, 79u,
- 50u, 123u, 176u, 174u,
- 62u, 126u, 61u, 158u,
- 192u, 158u, 113u, 27u,
- 114u, 191u, 160u, 176u,
- 73u, 112u, 144u, 145u,
- 104u, 131u, 49u, 64u,
- 188u, 245u, 1u, 185u,
- 176u, 156u, 108u, 91u,
- 248u, 187u, 109u, 54u,
- 255u, 112u, 149u, 54u,
- 120u, 138u, 115u, 204u,
- 21u, 238u, 255u, 184u,
- 158u, 243u, 175u, 34u,
- 134u, 130u, 87u, 158u,
- 105u, 128u, 191u, 183u,
- 49u, 124u, 42u, 128u,
- 52u, 38u, 153u, 160u,
- 159u, 70u, 181u, 141u,
- 1u, 1u, 146u, 208u,
- 22u, 24u, 171u, 172u,
- 209u, 215u, 72u, 171u,
- 251u, 197u, 147u, 136u,
- 0u, 42u, 152u, 242u,
- 160u, 143u, 74u, 90u,
- 79u, 168u, 93u, 83u,
- 160u, 60u, 152u, 47u,
- 63u, 255u, 193u, 163u,
- 194u, 7u, 89u, 194u,
- 218u, 124u, 1u, 114u,
- 114u, 179u, 209u, 153u,
- 142u, 208u, 6u, 190u,
- 136u, 114u, 133u, 173u,
- 165u, 33u, 151u, 106u,
- 136u, 147u, 139u, 174u,
- 134u, 126u, 212u, 1u,
- 109u, 183u, 185u, 131u,
- 181u, 255u, 18u, 147u,
- 68u, 216u, 105u, 204u,
- 164u, 202u, 51u, 121u,
- 126u, 62u, 194u, 170u,
- 37u, 83u, 15u, 152u,
- 17u, 124u, 161u, 0u,
- 114u, 10u, 160u, 182u,
- 97u, 156u, 67u, 255u,
- 37u, 130u, 52u, 96u,
- 167u, 169u, 107u, 203u,
- 222u, 94u, 181u, 142u,
- 137u, 126u, 0u, 124u,
- 42u, 101u, 9u, 168u,
- 117u, 32u, 176u, 38u,
- 62u, 47u, 153u, 113u,
- 193u, 203u, 173u, 92u,
- 66u, 153u, 200u, 121u,
- 195u, 230u, 78u, 169u,
- 128u, 110u, 147u, 255u,
- 216u, 66u, 140u, 117u,
- 78u, 90u, 126u, 115u,
- 255u, 40u, 79u, 74u,
- 46u, 124u, 65u, 119u,
- 174u, 194u, 63u, 117u,
- 82u, 158u, 1u, 39u,
- 87u, 180u, 134u, 8u,
- 129u, 158u, 187u, 158u,
- 130u, 242u, 184u, 0u,
- 56u, 181u, 96u, 176u,
- 69u, 135u, 173u, 78u,
- 219u, 129u, 213u, 237u,
- 103u, 255u, 242u, 63u,
- 152u, 93u, 17u, 230u,
- 194u, 149u, 161u, 163u,
- 159u, 114u, 150u, 169u,
- 138u, 159u, 131u, 39u,
- 100u, 34u, 92u, 231u,
- 174u, 192u, 255u, 197u,
- 150u, 147u, 88u, 115u,
- 24u, 162u, 158u, 230u,
- 88u, 168u, 1u, 98u,
- 78u, 188u, 178u, 69u,
- 165u, 7u, 174u, 206u,
- 141u, 168u, 89u, 115u,
- 141u, 95u, 144u, 53u,
- 0u, 238u, 63u, 206u,
- 107u, 170u, 102u, 113u,
- 154u, 93u, 74u, 64u,
- 76u, 0u, 58u, 75u,
- 133u, 193u, 110u, 98u,
- 8u, 75u, 248u, 95u,
- 166u, 69u, 124u, 99u,
- 147u, 128u, 126u, 152u,
- 255u, 166u, 94u, 137u,
- 100u, 188u, 103u, 114u,
- 90u, 110u, 240u, 111u,
- 101u, 200u, 35u, 158u,
- 255u, 87u, 200u, 77u,
- 99u, 130u, 95u, 224u,
- 132u, 132u, 170u, 106u,
- 182u, 106u, 189u, 255u,
- 151u, 76u, 84u, 93u,
- 49u, 189u, 106u, 172u,
- 99u, 100u, 210u, 82u,
- 122u, 117u, 115u, 1u,
- 80u, 137u, 47u, 74u,
- 93u, 157u, 118u, 177u,
- 174u, 105u, 133u, 132u,
- 154u, 79u, 124u, 255u,
- 114u, 112u, 151u, 173u,
- 21u, 105u, 172u, 114u,
- 152u, 172u, 101u, 157u,
- 76u, 101u, 85u, 122u,
- 118u, 0u, 203u, 110u,
- 129u, 196u, 128u, 144u,
- 133u, 154u, 255u, 56u,
- 83u, 174u, 182u, 201u,
- 26u, 87u, 82u, 99u,
- 100u, 171u, 137u, 242u,
- 159u, 92u, 1u, 218u,
- 204u, 144u, 117u, 191u,
- 181u, 117u, 145u, 203u,
- 158u, 248u, 29u, 10u,
- 40u, 151u, 156u, 113u,
- 0u, 204u, 191u, 174u,
- 139u, 201u, 64u, 147u,
- 148u, 133u, 171u, 95u,
- 170u, 123u, 56u, 14u,
- 153u, 8u, 171u, 86u,
- 255u, 16u, 142u, 224u,
- 27u, 64u, 55u, 215u,
- 189u, 117u, 255u, 161u,
- 252u, 105u, 218u, 190u,
- 60u, 122u, 115u, 26u,
- 255u, 184u, 246u, 27u,
- 109u, 80u, 209u, 151u,
- 42u, 145u, 165u, 75u,
- 134u, 170u, 154u, 98u,
- 119u, 1u, 153u, 102u,
- 178u, 81u, 52u, 163u,
- 217u, 124u, 121u, 176u,
- 166u, 255u, 172u, 253u,
- 102u, 98u, 0u, 142u,
- 126u, 111u, 32u, 127u,
- 98u, 41u, 198u, 156u,
- 32u, 124u, 7u, 99u,
- 125u, 100u, 255u, 100u,
- 193u, 90u, 1u, 155u,
- 66u, 193u, 210u, 158u,
- 138u, 188u, 61u, 147u,
- 162u, 197u, 88u, 50u,
- 75u, 219u, 214u, 101u,
- 20u, 134u, 112u, 115u,
- 137u, 115u, 180u, 212u,
- 209u, 48u, 175u, 0u,
- 153u, 132u, 164u, 135u,
- 211u, 194u, 133u, 255u,
- 176u, 84u, 93u, 151u,
- 150u, 159u, 118u, 139u,
- 173u, 100u, 255u, 182u,
- 144u, 168u, 188u, 60u,
- 11u, 134u, 110u, 180u,
- 178u, 133u, 127u, 7u,
- 136u, 62u, 124u, 135u,
- 1u, 122u, 174u, 116u,
- 139u, 112u, 154u, 167u,
- 89u, 38u, 64u, 194u,
- 255u, 170u, 206u, 158u,
- 71u, 120u, 254u, 42u,
- 142u, 138u, 42u, 8u,
- 162u, 57u, 158u, 151u,
- 195u, 163u, 123u, 147u,
- 182u, 128u, 179u, 1u,
- 203u, 131u, 87u, 103u,
- 48u, 218u, 217u, 118u,
- 168u, 147u, 20u, 125u,
- 182u, 74u, 130u, 171u,
- 70u, 159u, 131u, 153u,
- 99u, 1u, 60u, 56u,
- 134u, 194u, 200u, 244u,
- 19u, 126u, 220u, 234u,
- 158u, 67u, 127u, 143u,
- 88u, 94u, 9u, 255u,
- 209u, 130u, 96u, 37u,
- 169u, 0u, 71u, 115u,
- 50u, 154u, 238u, 177u,
- 178u, 214u, 39u, 19u,
- 150u, 229u, 88u, 223u,
- 68u, 255u, 9u, 44u,
- 153u, 42u, 236u, 121u,
- 224u, 111u, 142u, 89u,
- 0u, 128u, 132u, 163u,
- 189u, 183u, 212u, 2u,
- 99u, 101u, 117u, 37u,
- 75u, 14u, 211u, 44u,
- 80u, 115u, 43u, 255u,
- 112u, 202u, 163u, 100u,
- 85u, 212u, 38u, 103u,
- 183u, 185u, 104u, 231u,
- 183u, 51u, 176u, 112u,
- 255u, 97u, 164u, 132u,
- 127u, 99u, 91u, 41u,
- 113u, 176u, 118u, 175u,
- 145u, 186u, 65u, 223u,
- 120u, 144u, 103u, 0u,
- 125u, 112u, 50u, 139u,
- 136u, 90u, 100u, 137u,
- 15u, 82u, 65u, 229u,
- 122u, 114u, 134u, 1u,
- 162u, 255u, 95u, 166u,
- 172u, 96u, 94u, 27u,
- 134u, 99u, 122u, 93u,
- 75u, 187u, 255u, 109u,
- 192u, 178u, 52u, 110u,
- 168u, 185u, 62u, 76u,
- 94u, 69u, 132u, 106u,
- 87u, 4u, 1u, 27u,
- 0u, 163u, 188u, 69u,
- 101u, 55u, 221u, 137u,
- 146u, 39u, 55u, 94u,
- 152u, 104u, 137u, 64u,
- 109u, 167u, 100u, 255u,
- 111u, 242u, 159u, 166u,
- 125u, 1u, 104u, 207u,
- 0u, 17u, 180u, 13u,
- 89u, 232u, 67u, 93u,
- 35u, 73u, 99u, 228u,
- 177u, 148u, 230u, 134u,
- 111u, 119u, 111u, 60u,
- 54u, 117u, 121u, 1u,
- 201u, 70u, 201u, 113u,
- 143u, 95u, 60u, 123u,
- 184u, 54u, 1u, 95u,
- 163u, 69u, 163u, 207u,
- 57u, 106u, 136u, 250u,
- 118u, 135u, 127u, 159u,
- 255u, 24u, 66u, 50u,
- 26u, 91u, 39u, 124u,
- 194u, 129u, 236u, 125u,
- 38u, 118u, 161u, 111u,
- 121u, 78u, 164u, 207u,
- 131u, 157u, 36u, 76u,
- 56u, 86u, 186u, 255u,
- 122u, 151u, 128u, 146u,
- 1u, 157u, 221u, 202u,
- 160u, 8u, 123u, 126u,
- 135u, 19u, 114u, 153u,
- 33u, 153u, 43u, 255u,
- 223u, 83u, 117u, 83u,
- 128u, 194u, 130u, 246u,
- 156u, 163u, 182u, 107u,
- 177u, 93u, 196u, 166u,
- 186u, 54u, 71u, 201u,
- 118u, 110u, 12u, 1u,
- 59u, 81u, 160u, 116u,
- 232u, 228u, 174u, 59u,
- 76u, 1u, 88u, 43u,
- 186u, 42u, 154u, 136u,
- 134u, 138u, 46u, 59u,
- 55u, 176u, 118u, 209u,
- 78u, 124u, 112u, 96u,
- 112u, 147u, 133u, 140u,
- 1u, 59u, 69u, 187u,
- 145u, 93u, 59u, 123u,
- 109u, 82u, 105u, 255u,
- 66u, 74u, 140u, 167u,
- 67u, 47u, 142u, 160u,
- 99u, 114u, 198u, 35u,
- 31u, 115u, 7u, 84u,
- 171u, 161u, 242u, 73u,
- 46u, 107u, 158u, 255u,
- 64u, 129u, 130u, 90u,
- 160u, 156u, 139u, 139u,
- 149u, 130u, 219u, 162u,
- 149u, 255u, 105u, 119u,
- 1u, 162u, 139u, 144u,
- 69u, 100u, 188u, 136u,
- 111u, 173u, 84u, 108u,
- 111u, 79u, 122u, 72u,
- 131u, 171u, 104u, 16u,
- 79u, 202u, 92u, 255u,
- 113u, 188u, 79u, 87u,
- 183u, 111u, 26u, 62u,
- 3u, 142u, 36u, 207u,
- 96u, 170u, 62u, 109u,
- 1u, 148u, 31u, 58u,
- 69u, 199u, 149u, 183u,
- 79u, 156u, 126u, 96u,
- 192u, 151u, 255u, 123u,
- 150u, 123u, 104u, 157u,
- 138u, 173u, 182u, 140u,
- 13u, 215u, 129u, 232u,
- 40u, 154u, 154u, 194u,
- 111u, 148u, 138u, 109u,
- 255u, 74u, 104u, 54u,
- 115u, 186u, 14u, 23u,
- 109u, 255u, 96u, 179u,
- 191u, 184u, 199u, 159u,
- 239u, 169u, 155u, 213u,
- 128u, 138u, 116u, 126u,
- 112u, 92u, 93u, 56u,
- 125u, 1u, 148u, 89u,
- 60u, 147u, 145u, 126u,
- 174u, 106u, 136u, 68u,
- 168u, 195u, 157u, 86u,
- 167u, 181u, 142u, 255u,
- 127u, 123u, 64u, 161u,
- 99u, 97u, 79u, 130u,
- 114u, 132u, 137u, 150u,
- 96u, 39u, 222u, 204u,
- 214u, 1u, 85u, 188u,
- 189u, 159u, 158u, 83u,
- 182u, 1u, 130u, 176u,
- 12u, 186u, 75u, 8u,
- 82u, 66u, 200u, 81u,
- 87u, 75u, 169u, 89u,
- 147u, 0u, 201u, 63u,
- 218u, 96u, 53u, 197u,
- 98u, 205u, 189u, 58u,
- 246u, 89u, 151u, 214u,
- 70u, 126u, 207u, 167u,
- 255u, 111u, 98u, 149u,
- 101u, 10u, 146u, 74u,
- 93u, 133u, 208u, 44u,
- 249u, 103u, 106u, 74u,
- 65u, 153u, 87u, 72u,
- 75u, 145u, 255u, 132u,
- 0u, 95u, 57u, 126u,
- 107u, 202u, 122u, 165u,
- 146u, 96u, 154u, 194u,
- 162u, 123u, 178u, 132u,
- 107u, 1u, 85u, 210u,
- 207u, 127u, 97u, 27u,
- 138u, 186u, 21u, 148u,
- 247u, 178u, 156u, 255u,
- 110u, 246u, 105u, 150u,
- 70u, 172u, 0u, 188u,
- 93u, 195u, 184u, 89u,
- 117u, 136u, 148u, 152u,
- 175u, 180u, 142u, 40u,
- 142u, 108u, 20u, 72u,
- 79u, 55u, 76u, 208u,
- 1u, 161u, 221u, 234u,
- 39u, 182u, 161u, 126u,
- 105u, 60u, 88u, 7u,
- 78u, 1u, 196u, 132u,
- 140u, 192u, 145u, 176u,
- 149u, 160u, 134u, 74u,
- 115u, 181u, 246u, 89u,
- 125u, 184u, 1u, 82u,
- 138u, 148u, 188u, 121u,
- 117u, 120u, 1u, 225u,
- 197u, 6u, 93u, 127u,
- 203u, 134u, 188u, 26u,
- 85u, 75u, 69u, 50u,
- 54u, 135u, 12u, 244u,
- 44u, 144u, 127u, 85u,
- 141u, 180u, 186u, 212u,
- 95u, 1u, 68u, 129u,
- 89u, 115u, 157u, 93u,
- 83u, 168u, 255u, 69u,
- 83u, 135u, 112u, 56u,
- 153u, 77u, 169u, 200u,
- 109u, 30u, 121u, 113u,
- 208u, 209u, 214u, 96u,
- 5u, 124u, 1u, 1u,
- 198u, 233u, 138u, 95u,
- 204u, 129u, 84u, 22u,
- 1u, 97u, 98u, 108u,
- 87u, 87u, 146u, 174u,
- 120u, 138u, 48u, 70u,
- 180u, 151u, 145u, 135u,
- 155u, 255u, 117u, 124u,
- 180u, 84u, 115u, 202u,
- 101u, 136u, 39u, 82u,
- 206u, 100u, 30u, 44u,
- 129u, 165u, 141u, 168u,
- 73u, 226u, 191u, 168u,
- 138u, 255u, 127u, 154u,
- 92u, 98u, 130u, 135u,
- 85u, 125u, 56u, 185u,
- 175u, 174u, 199u, 182u,
- 51u, 0u, 128u, 89u,
- 159u, 110u, 223u, 130u,
- 151u, 149u, 222u, 114u,
- 178u, 87u, 1u, 116u,
- 139u, 102u, 67u, 132u,
- 4u, 68u, 204u, 193u,
- 222u, 224u, 11u, 173u,
- 38u, 57u, 1u, 96u,
- 26u, 141u, 88u, 154u,
- 127u, 110u, 113u, 106u,
- 56u, 114u, 204u, 180u,
- 188u, 146u, 81u, 139u,
- 56u, 255u, 89u, 134u,
- 100u, 116u, 120u, 123u,
- 117u, 42u, 154u, 148u,
- 54u, 212u, 186u, 124u,
- 147u, 1u, 133u, 95u,
- 56u, 219u, 133u, 116u,
- 38u, 157u, 23u, 193u,
- 146u, 119u, 255u, 98u,
- 76u, 67u, 175u, 155u,
- 112u, 165u, 172u, 40u,
- 232u, 124u, 186u, 103u,
- 182u, 202u, 78u, 122u,
- 156u, 80u, 66u, 255u,
- 255u, 182u, 41u, 147u,
- 60u, 26u, 76u, 204u,
- 242u, 169u, 162u, 143u,
- 128u, 36u, 106u, 140u,
- 66u, 164u, 107u, 29u,
- 106u, 161u, 156u, 173u,
- 214u, 92u, 255u, 167u,
- 229u, 114u, 166u, 124u,
- 123u, 144u, 59u, 212u,
- 59u, 187u, 0u, 136u,
- 36u, 174u, 163u, 100u,
- 95u, 147u, 164u, 217u,
- 233u, 180u, 188u, 172u,
- 21u, 162u, 120u, 1u,
- 171u, 161u, 243u, 200u,
- 239u, 57u, 87u, 112u,
- 165u, 151u, 97u, 146u,
- 200u, 58u, 150u, 1u,
- 178u, 100u, 171u, 166u,
- 117u, 109u, 191u, 130u,
- 58u, 172u, 6u, 104u,
- 1u, 173u, 89u, 211u,
- 142u, 137u, 161u, 137u,
- 12u, 211u, 36u, 145u,
- 11u, 177u, 255u, 35u,
- 134u, 202u, 122u, 168u,
- 93u, 126u, 124u, 165u,
- 145u, 147u, 166u, 195u,
- 93u, 20u, 1u, 13u,
- 143u, 146u, 49u, 81u,
- 174u, 49u, 214u, 209u,
- 221u, 115u, 16u, 50u,
- 132u, 186u, 190u, 125u,
- 98u, 125u, 255u, 118u,
- 42u, 196u, 98u, 166u,
- 120u, 164u, 68u, 117u,
- 115u, 57u, 181u, 182u,
- 145u, 249u, 118u, 77u,
- 64u, 79u, 0u, 39u,
- 221u, 231u, 87u, 197u,
- 123u, 118u, 109u, 180u,
- 14u, 95u, 85u, 129u,
- 88u, 175u, 255u, 145u,
- 170u, 29u, 175u, 95u,
- 79u, 170u, 171u, 179u,
- 255u, 69u, 158u, 45u,
- 152u, 159u, 128u, 169u,
- 66u, 178u, 181u, 100u,
- 142u, 129u, 173u, 177u,
- 169u, 220u, 193u, 86u,
- 142u, 0u, 125u, 140u,
- 178u, 164u, 122u, 172u,
- 105u, 144u, 86u, 157u,
- 1u, 222u, 159u, 175u,
- 103u, 151u, 168u, 70u,
- 169u, 130u, 87u, 172u,
- 167u, 150u, 164u, 1u,
- 217u, 137u, 140u, 139u,
- 144u, 206u, 122u, 123u,
- 142u, 12u, 82u, 147u,
- 157u, 66u, 137u, 78u,
- 150u, 87u, 255u, 241u,
- 50u, 113u, 30u, 65u,
- 63u, 89u, 148u, 111u,
- 101u, 134u, 128u, 199u,
- 76u, 69u, 1u, 98u,
- 164u, 109u, 67u, 54u,
- 80u, 158u, 126u, 37u,
- 136u, 63u, 157u, 137u,
- 151u, 1u, 231u, 202u,
- 57u, 145u, 243u, 178u,
- 145u, 125u, 136u, 52u,
- 156u, 128u, 149u, 98u,
- 1u, 220u, 84u, 27u,
- 127u, 175u, 173u, 122u,
- 112u, 117u, 106u, 214u,
- 98u, 134u, 80u, 186u,
- 0u, 239u, 215u, 127u,
- 141u, 123u, 152u, 40u,
- 178u, 85u, 182u, 54u,
- 92u, 133u, 134u, 73u,
- 193u, 0u, 247u, 139u,
- 102u, 119u, 27u, 19u,
- 112u, 56u, 55u, 105u,
- 112u, 128u, 151u, 126u,
- 248u, 65u, 255u, 102u,
- 130u, 127u, 160u, 156u,
- 238u, 110u, 110u, 56u,
- 150u, 191u, 1u, 143u,
- 77u, 146u, 183u, 213u,
- 27u, 89u, 32u, 3u,
- 171u, 11u, 70u, 86u,
- 9u, 98u, 66u, 149u,
- 80u, 42u, 64u, 211u,
- 79u, 125u, 68u, 94u,
- 184u, 255u, 160u, 37u,
- 207u, 142u, 220u, 31u,
- 127u, 161u, 145u, 69u,
- 38u, 7u, 0u, 87u,
- 74u, 204u, 14u, 191u,
- 129u, 177u, 139u, 155u,
- 38u, 193u, 104u, 194u,
- 128u, 66u, 137u, 27u,
- 17u, 255u, 162u, 102u,
- 25u, 73u, 128u, 117u,
- 112u, 240u, 40u, 71u,
- 83u, 210u, 215u, 146u,
- 203u, 1u, 102u, 159u,
- 1u, 204u, 119u, 122u,
- 121u, 133u, 172u, 163u,
- 113u, 101u, 161u, 128u,
- 46u, 94u, 57u, 171u,
- 139u, 227u, 91u, 144u,
- 39u, 130u, 12u, 80u,
- 128u, 209u, 255u, 173u,
- 144u, 47u, 174u, 105u,
- 149u, 93u, 127u, 71u,
- 255u, 129u, 1u, 35u,
- 205u, 131u, 188u, 212u,
- 151u, 144u, 211u, 233u,
- 117u, 163u, 46u, 123u,
- 64u, 178u, 182u, 186u,
- 187u, 73u, 215u, 156u,
- 208u, 137u, 176u, 1u,
- 150u, 154u, 187u, 124u,
- 130u, 116u, 123u, 1u,
- 125u, 90u, 129u, 73u,
- 82u, 163u, 177u, 126u,
- 123u, 154u, 119u, 136u,
- 111u, 110u, 78u, 142u,
- 95u, 39u, 255u, 104u,
- 138u, 193u, 52u, 181u,
- 100u, 64u, 133u, 241u,
- 35u, 202u, 255u, 12u,
- 148u, 182u, 214u, 172u,
- 177u, 55u, 195u, 150u,
- 129u, 107u, 126u, 141u,
- 162u, 32u, 220u, 7u,
- 212u, 13u, 38u, 255u,
- 211u, 238u, 165u, 124u,
- 53u, 121u, 86u, 127u,
- 125u, 124u, 162u, 227u,
- 119u, 162u, 200u, 128u,
- 108u, 51u, 89u, 255u,
- 29u, 159u, 102u, 0u,
- 123u, 212u, 137u, 170u,
- 220u, 192u, 152u, 241u,
- 70u, 125u, 179u, 126u,
- 198u, 48u, 76u, 140u,
- 208u, 151u, 135u, 7u,
- 81u, 46u, 90u, 1u,
- 155u, 223u, 114u, 45u,
- 33u, 95u, 110u, 207u,
- 154u, 147u, 240u, 104u,
- 255u, 17u, 34u, 88u,
- 73u, 136u, 140u, 162u,
- 110u, 95u, 168u, 129u,
- 222u, 83u, 85u, 181u,
- 134u, 182u, 24u, 158u,
- 58u, 117u, 1u, 106u,
- 120u, 181u, 134u, 68u,
- 1u, 102u, 162u, 124u,
- 62u, 203u, 178u, 136u,
- 69u, 132u, 84u, 144u,
- 157u, 64u, 51u, 255u,
- 132u, 35u, 74u, 51u,
- 111u, 112u, 157u, 79u,
- 95u, 43u, 78u, 157u,
- 208u, 149u, 136u, 224u,
- 98u, 154u, 156u, 56u,
- 77u, 94u, 69u, 50u,
- 255u, 64u, 90u, 64u,
- 190u, 123u, 82u, 97u,
- 255u, 142u, 69u, 76u,
- 241u, 104u, 83u, 131u,
- 239u, 142u, 230u, 125u,
- 53u, 171u, 177u, 62u,
- 28u, 110u, 161u, 57u,
- 73u, 160u, 87u, 164u,
- 55u, 113u, 164u, 255u,
- 200u, 156u, 123u, 64u,
- 255u, 160u, 224u, 46u,
- 106u, 202u, 48u, 188u,
- 182u, 70u, 226u, 137u,
- 42u, 104u, 49u, 142u,
- 209u, 161u, 255u, 101u,
- 79u, 105u, 32u, 165u,
- 206u, 133u, 153u, 116u,
- 92u, 155u, 74u, 6u,
- 164u, 0u, 135u, 183u,
- 50u, 115u, 181u, 158u,
- 99u, 240u, 148u, 63u,
- 201u, 207u, 69u, 255u,
- 59u, 195u, 153u, 55u,
- 41u, 74u, 176u, 229u,
- 229u, 216u, 132u, 92u,
- 168u, 105u, 141u, 0u,
- 149u, 182u, 61u, 39u,
- 43u, 140u, 176u, 150u,
- 133u, 84u, 194u, 202u,
- 1u, 173u, 132u, 158u,
- 179u, 150u, 99u, 110u,
- 97u, 29u, 150u, 185u,
- 114u, 210u, 186u, 231u,
- 121u, 179u, 79u, 183u,
- 150u, 208u, 1u, 128u,
- 76u, 196u, 188u, 102u,
- 139u, 144u, 155u, 86u,
- 99u, 119u, 110u, 123u,
- 149u, 85u, 58u, 160u,
- 149u, 255u, 67u, 19u,
- 65u, 1u, 154u, 192u,
- 255u, 131u, 126u, 2u,
- 40u, 175u, 176u, 146u,
- 102u, 162u, 209u, 254u,
- 253u, 194u, 115u, 229u,
- 164u, 235u, 106u, 1u,
- 69u, 181u, 115u, 130u,
- 130u, 163u, 155u, 41u,
- 155u, 139u, 89u, 137u,
- 123u, 212u, 98u, 54u,
- 65u, 197u, 87u, 255u,
- 139u, 40u, 253u, 145u,
- 247u, 101u, 143u, 125u,
- 191u, 106u, 32u, 234u,
- 7u, 188u, 255u, 166u,
- 164u, 166u, 34u, 112u,
- 136u, 77u, 115u, 73u,
- 0u, 37u, 53u, 181u,
- 55u, 56u, 41u, 107u,
- 68u, 42u, 171u, 130u,
- 25u, 130u, 139u, 135u,
- 143u, 68u, 146u, 161u,
- 220u, 144u, 103u, 20u,
- 1u, 145u, 71u, 158u,
- 138u, 129u, 156u, 166u,
- 105u, 109u, 158u, 51u,
- 22u, 63u, 1u, 57u,
- 184u, 69u, 173u, 7u,
- 81u, 148u, 105u, 177u,
- 122u, 105u, 44u, 86u,
- 1u, 84u, 127u, 169u,
- 112u, 246u, 163u, 124u,
- 65u, 158u, 77u, 81u,
- 156u, 67u, 223u, 181u,
- 76u, 122u, 135u, 186u,
- 157u, 65u, 85u, 186u,
- 61u, 134u, 119u, 0u,
- 76u, 116u, 126u, 185u,
- 93u, 149u, 223u, 35u,
- 84u, 130u, 255u, 250u,
- 246u, 169u, 203u, 110u,
- 255u, 166u, 142u, 77u,
- 16u, 156u, 125u, 252u,
- 186u, 83u, 208u, 126u,
- 183u, 117u, 54u, 128u,
- 168u, 105u, 187u, 98u,
- 94u, 161u, 255u, 82u,
- 140u, 113u, 115u, 123u,
- 48u, 97u, 188u, 179u,
- 65u, 68u, 6u, 164u,
- 124u, 130u, 3u, 255u,
- 216u, 130u, 190u, 141u,
- 150u, 46u, 98u, 79u,
- 126u, 144u, 240u, 1u,
- 34u, 104u, 231u, 75u,
- 73u, 174u, 127u, 130u,
- 192u, 110u, 120u, 67u,
- 49u, 94u, 255u, 26u,
- 125u, 206u, 14u, 161u,
- 222u, 189u, 242u, 244u,
- 65u, 211u, 31u, 166u,
- 2u, 168u, 70u, 173u,
- 70u, 132u, 177u, 200u,
- 207u, 92u, 166u, 223u,
- 180u, 38u, 161u, 1u,
- 82u, 184u, 197u, 133u,
- 131u, 90u, 216u, 79u,
- 37u, 132u, 132u, 233u,
- 1u, 103u, 186u, 235u,
- 83u, 110u, 38u, 200u,
- 22u, 178u, 160u, 114u,
- 124u, 203u, 216u, 255u,
- 95u, 180u, 58u, 119u,
- 119u, 74u, 255u, 172u,
- 37u, 169u, 219u, 127u,
- 151u, 199u, 52u, 156u,
- 34u, 168u, 9u, 56u,
- 1u, 101u, 92u, 170u,
- 124u, 87u, 188u, 119u,
- 209u, 130u, 192u, 173u,
- 158u, 69u, 144u, 136u,
- 121u, 181u, 175u, 167u,
- 136u, 115u, 253u, 224u,
- 191u, 123u, 55u, 154u,
- 182u, 115u, 1u, 116u,
- 57u, 255u, 158u, 44u,
- 95u, 116u, 144u, 71u,
- 137u, 109u, 113u, 99u,
- 140u, 141u, 129u, 109u,
- 140u, 204u, 168u, 132u,
- 170u, 136u, 255u, 35u,
- 114u, 137u, 92u, 159u,
- 168u, 183u, 99u, 22u,
- 164u, 108u, 95u, 131u,
- 155u, 62u, 130u, 82u,
- 128u, 131u, 202u, 255u,
- 199u, 82u, 90u, 35u,
- 164u, 208u, 167u, 0u,
- 116u, 145u, 53u, 163u,
- 149u, 87u, 236u, 155u,
- 49u, 127u, 118u, 143u,
- 116u, 138u, 196u, 32u,
- 168u, 104u, 93u, 255u,
- 178u, 141u, 110u, 100u,
- 173u, 136u, 66u, 143u,
- 172u, 123u, 167u, 63u,
- 152u, 212u, 83u, 207u,
- 127u, 129u, 125u, 142u,
- 255u, 142u, 153u, 83u,
- 243u, 134u, 125u, 91u,
- 138u, 91u, 134u, 0u,
- 159u, 40u, 50u, 112u,
- 93u, 191u, 176u, 182u,
- 91u, 147u, 187u, 160u,
- 120u, 110u, 206u, 88u,
- 225u, 181u, 134u, 146u,
- 192u, 255u, 2u, 143u,
- 64u, 114u, 1u, 158u,
- 36u, 147u, 192u, 186u,
- 121u, 164u, 130u, 200u,
- 117u, 86u, 147u, 73u,
- 0u, 134u, 239u, 76u,
- 177u, 69u, 184u, 67u,
- 69u, 129u, 108u, 182u,
- 68u, 51u, 132u, 223u,
- 104u, 118u, 89u, 161u,
- 176u, 187u, 65u, 98u,
- 139u, 135u, 153u, 102u,
- 133u, 255u, 175u, 211u,
- 94u, 99u, 1u, 110u,
- 134u, 117u, 132u, 180u,
- 39u, 153u, 123u, 133u,
- 179u, 123u, 135u, 130u,
- 126u, 135u, 187u, 91u,
- 195u, 186u, 195u, 235u,
- 187u, 1u, 192u, 153u,
- 148u, 214u, 180u, 163u,
- 101u, 101u, 142u, 115u,
- 224u, 78u, 183u, 171u,
- 108u, 222u, 96u, 126u,
- 93u, 110u, 1u, 76u,
- 106u, 124u, 119u, 41u,
- 164u, 82u, 149u, 132u,
- 138u, 188u, 246u, 155u,
- 42u, 255u, 145u, 134u,
- 186u, 77u, 181u, 102u,
- 218u, 121u, 119u, 77u,
- 50u, 9u, 54u, 1u,
- 145u, 127u, 145u, 80u,
- 111u, 152u, 143u, 136u,
- 0u, 177u, 92u, 144u,
- 113u, 95u, 119u, 122u,
- 164u, 76u, 85u, 196u,
- 199u, 110u, 100u, 79u,
- 113u, 49u, 255u, 87u,
- 81u, 181u, 246u, 57u,
- 145u, 152u, 26u, 105u,
- 76u, 163u, 128u, 38u,
- 150u, 199u, 201u, 129u,
- 88u, 156u, 111u, 63u,
- 56u, 166u, 255u, 252u,
- 122u, 154u, 82u, 239u,
- 85u, 95u, 157u, 25u,
- 100u, 33u, 78u, 1u,
- 14u, 155u, 111u, 152u,
- 150u, 86u, 160u, 98u,
- 140u, 105u, 94u, 102u,
- 255u, 128u, 177u, 110u,
- 120u, 78u, 138u, 120u,
- 135u, 173u, 107u, 159u,
- 0u, 99u, 112u, 161u,
- 158u, 152u, 153u, 204u,
- 171u, 160u, 144u, 120u,
- 164u, 198u, 112u, 62u,
- 157u, 177u, 88u, 164u,
- 0u, 174u, 207u, 150u,
- 169u, 175u, 126u, 118u,
- 70u, 175u, 114u, 82u,
- 21u, 129u, 84u, 122u,
- 0u, 152u, 235u, 218u,
- 205u, 100u, 203u, 99u,
- 255u, 125u, 143u, 47u,
- 112u, 47u, 141u, 191u,
- 97u, 82u, 181u, 195u,
- 138u, 208u, 58u, 109u,
- 241u, 154u, 148u, 45u,
- 164u, 54u, 81u, 178u,
- 67u, 125u, 1u, 24u,
- 212u, 193u, 206u, 154u,
- 1u, 204u, 110u, 95u,
- 83u, 113u, 10u, 103u,
- 129u, 153u, 189u, 27u,
- 42u, 20u, 148u, 133u,
- 64u, 242u, 114u, 53u,
- 101u, 120u, 39u, 145u,
- 230u, 194u, 218u, 182u,
- 131u, 140u, 82u, 1u,
- 126u, 168u, 122u, 74u,
- 186u, 1u, 51u, 108u,
- 130u, 111u, 163u, 153u,
- 61u, 95u, 30u, 53u,
- 218u, 1u, 43u, 128u,
- 127u, 248u, 107u, 142u,
- 198u, 73u, 116u, 142u,
- 65u, 178u, 171u, 133u,
- 184u, 83u, 102u, 230u,
- 124u, 156u, 59u, 69u,
- 134u, 255u, 78u, 46u,
- 119u, 9u, 190u, 99u,
- 160u, 80u, 123u, 108u,
- 198u, 185u, 187u, 97u,
- 204u, 142u, 0u, 140u,
- 162u, 164u, 140u, 172u,
- 1u, 166u, 137u, 98u,
- 98u, 87u, 169u, 239u,
- 149u, 133u, 120u, 162u,
- 197u, 74u, 29u, 116u,
- 176u, 209u, 78u, 46u,
- 1u, 159u, 182u, 181u,
- 130u, 151u, 199u, 180u,
- 55u, 2u, 90u, 112u,
- 190u, 104u, 164u, 93u,
- 106u, 145u, 44u, 151u,
- 83u, 33u, 37u, 66u,
- 1u, 148u, 113u, 93u,
- 26u, 3u, 85u, 126u,
- 138u, 126u, 93u, 95u,
- 176u, 204u, 126u, 70u,
- 91u, 83u, 219u, 1u,
- 178u, 176u, 87u, 140u,
- 174u, 239u, 51u, 196u,
- 131u, 222u, 38u, 157u,
- 175u, 197u, 178u, 255u,
- 234u, 86u, 209u, 1u,
- 93u, 135u, 171u, 154u,
- 148u, 90u, 239u, 196u,
- 155u, 141u, 86u, 255u,
- 121u, 124u, 36u, 121u,
- 199u, 186u, 155u, 104u,
- 54u, 84u, 16u, 89u,
- 148u, 111u, 255u, 39u,
- 165u, 255u, 47u, 144u,
- 86u, 139u, 115u, 117u,
- 131u, 70u, 213u, 119u,
- 110u, 89u, 174u, 185u,
- 67u, 101u, 1u, 26u,
- 63u, 110u, 193u, 99u,
- 63u, 113u, 229u, 51u,
- 77u, 188u, 149u, 143u,
- 1u, 61u, 89u, 74u,
- 61u, 122u, 150u, 163u,
- 255u, 185u, 194u, 130u,
- 131u, 138u, 149u, 152u,
- 93u, 184u, 111u, 1u,
- 196u, 102u, 83u, 66u,
- 184u, 208u, 137u, 158u,
- 142u, 4u, 193u, 141u,
- 62u, 122u, 200u, 132u,
- 168u, 122u, 155u, 58u,
- 150u, 185u, 166u, 92u,
- 219u, 1u, 180u, 44u,
- 116u, 51u, 171u, 102u,
- 255u, 196u, 94u, 94u,
- 106u, 19u, 51u, 96u,
- 134u, 158u, 59u, 81u,
- 132u, 235u, 186u, 70u,
- 181u, 255u, 35u, 194u,
- 131u, 50u, 66u, 92u,
- 119u, 222u, 106u, 215u,
- 110u, 225u, 206u, 130u,
- 84u, 232u, 149u, 136u,
- 12u, 176u, 200u, 164u,
- 63u, 143u, 1u, 87u,
- 239u, 113u, 203u, 124u,
- 98u, 57u, 168u, 97u,
- 167u, 126u, 226u, 205u,
- 134u, 214u, 220u, 0u,
- 116u, 104u, 154u, 91u,
- 140u, 35u, 88u, 138u,
- 161u, 185u, 153u, 255u,
- 180u, 222u, 180u, 91u,
- 153u, 99u, 206u, 102u,
- 255u, 153u, 23u, 77u,
- 94u, 176u, 123u, 169u,
- 211u, 153u, 63u, 153u,
- 60u, 52u, 150u, 80u,
- 79u, 47u, 255u, 138u,
- 73u, 245u, 78u, 207u,
- 132u, 50u, 111u, 205u,
- 1u, 87u, 175u, 134u,
- 114u, 98u, 105u, 230u,
- 132u, 102u, 65u, 57u,
- 101u, 120u, 19u, 35u,
- 168u, 33u, 115u, 187u,
- 255u, 62u, 188u, 131u,
- 130u, 85u, 25u, 187u,
- 214u, 188u, 184u, 53u,
- 229u, 1u, 221u, 170u,
- 154u, 191u, 198u, 76u,
- 44u, 121u, 148u, 156u,
- 174u, 79u, 152u, 182u,
- 110u, 166u, 105u, 255u,
- 101u, 95u, 159u, 35u,
- 112u, 122u, 68u, 142u,
- 119u, 140u, 116u, 82u,
- 162u, 255u, 223u, 191u,
- 133u, 199u, 66u, 33u,
- 70u, 78u, 99u, 142u,
- 193u, 89u, 94u, 8u,
- 69u, 144u, 89u, 179u,
- 175u, 85u, 130u, 216u,
- 139u, 61u, 116u, 137u,
- 125u, 15u, 255u, 117u,
- 69u, 148u, 248u, 22u,
- 84u, 89u, 196u, 116u,
- 124u, 206u, 130u, 110u,
- 167u, 101u, 91u, 255u,
- 40u, 117u, 129u, 44u,
- 1u, 83u, 202u, 220u,
- 77u, 93u, 80u, 102u,
- 14u, 118u, 104u, 228u,
- 161u, 96u, 98u, 170u,
- 137u, 104u, 94u, 151u,
- 115u, 175u, 163u, 143u,
- 125u, 103u, 1u, 187u,
- 23u, 12u, 115u, 171u,
- 78u, 149u, 165u, 69u,
- 176u, 104u, 1u, 109u,
- 194u, 78u, 95u, 216u,
- 202u, 1u, 193u, 116u,
- 69u, 154u, 68u, 156u,
- 171u, 164u, 174u, 85u,
- 39u, 146u, 134u, 155u,
- 144u, 164u, 97u, 216u,
- 130u, 249u, 150u, 157u,
- 1u, 138u, 22u, 188u,
- 152u, 45u, 212u, 209u,
- 158u, 153u, 44u, 255u,
- 183u, 145u, 237u, 111u,
- 213u, 86u, 70u, 97u,
- 90u, 63u, 154u, 47u,
- 103u, 163u, 119u, 75u,
- 157u, 115u, 100u, 161u,
- 181u, 113u, 192u, 208u,
- 189u, 255u, 104u, 116u,
- 132u, 155u, 192u, 65u,
- 94u, 138u, 108u, 101u,
- 147u, 44u, 230u, 255u,
- 150u, 238u, 86u, 86u,
- 0u, 47u, 29u, 82u,
- 180u, 188u, 11u, 141u,
- 75u, 112u, 19u, 17u,
- 80u, 104u, 75u, 123u,
- 154u, 153u, 1u, 44u,
- 169u, 66u, 90u, 107u,
- 207u, 176u, 230u, 112u,
- 171u, 81u, 186u, 221u,
- 1u, 111u, 66u, 176u,
- 116u, 176u, 112u, 234u,
- 72u, 153u, 245u, 68u,
- 233u, 11u, 196u, 175u,
- 49u, 53u, 22u, 138u,
- 146u, 201u, 255u, 196u,
- 77u, 93u, 150u, 25u,
- 196u, 63u, 252u, 76u,
- 233u, 147u, 152u, 238u,
- 206u, 124u, 123u, 81u,
- 89u, 88u, 126u, 163u,
- 151u, 113u, 1u, 7u,
- 151u, 130u, 255u, 99u,
- 224u, 82u, 140u, 147u,
- 111u, 147u, 54u, 127u,
- 107u, 91u, 190u, 46u,
- 62u, 152u, 83u, 106u,
- 92u, 184u, 113u, 239u,
- 36u, 105u, 255u, 192u,
- 247u, 102u, 38u, 160u,
- 119u, 127u, 65u, 87u,
- 136u, 113u, 178u, 173u,
- 193u, 112u, 68u, 178u,
- 84u, 115u, 1u, 251u,
- 30u, 199u, 0u, 105u,
- 170u, 71u, 235u, 72u,
- 53u, 40u, 202u, 195u,
- 3u, 212u, 5u, 49u,
- 118u, 104u, 114u, 132u,
- 74u, 143u, 80u, 129u,
- 128u, 130u, 166u, 55u,
- 101u, 179u, 1u, 154u,
- 168u, 112u, 45u, 119u,
- 17u, 149u, 180u, 154u,
- 191u, 255u, 151u, 163u,
- 138u, 130u, 126u, 177u,
- 216u, 76u, 59u, 238u,
- 249u, 0u, 75u, 112u,
- 124u, 130u, 170u, 218u,
- 73u, 132u, 179u, 63u,
- 34u, 97u, 47u, 195u,
- 101u, 129u, 81u, 57u,
- 255u, 106u, 218u, 212u,
- 34u, 110u, 66u, 96u,
- 1u, 157u, 16u, 180u,
- 89u, 206u, 143u, 145u,
- 155u, 195u, 142u, 75u,
- 131u, 101u, 84u, 4u,
- 130u, 83u, 239u, 38u,
- 221u, 142u, 182u, 126u,
- 65u, 134u, 89u, 116u,
- 209u, 163u, 255u, 176u,
- 174u, 146u, 83u, 60u,
- 138u, 118u, 145u, 255u,
- 41u, 125u, 154u, 133u,
- 125u, 102u, 109u, 122u,
- 167u, 123u, 18u, 134u,
- 137u, 204u, 100u, 196u,
- 89u, 157u, 75u, 11u,
- 39u, 255u, 249u, 94u,
- 100u, 194u, 160u, 167u,
- 60u, 142u, 100u, 1u,
- 143u, 106u, 178u, 88u,
- 67u, 74u, 74u, 132u,
- 215u, 119u, 131u, 168u,
- 101u, 102u, 88u, 116u,
- 67u, 126u, 49u, 76u,
- 127u, 216u, 185u, 255u,
- 148u, 90u, 160u, 103u,
- 112u, 70u, 47u, 92u,
- 190u, 121u, 113u, 186u,
- 255u, 62u, 194u, 102u,
- 153u, 151u, 96u, 145u,
- 13u, 119u, 157u, 255u,
- 91u, 208u, 179u, 79u,
- 115u, 115u, 137u, 152u,
- 140u, 130u, 156u, 101u,
- 137u, 111u, 155u, 140u,
- 165u, 144u, 221u, 173u,
- 145u, 191u, 171u, 1u,
- 182u, 136u, 161u, 80u,
- 158u, 116u, 114u, 111u,
- 103u, 142u, 121u, 255u,
- 151u, 118u, 108u, 107u,
- 177u, 175u, 170u, 86u,
- 202u, 47u, 163u, 0u,
- 115u, 194u, 27u, 113u,
- 189u, 196u, 133u, 73u,
- 102u, 24u, 159u, 65u,
- 192u, 31u, 160u, 0u,
- 237u, 119u, 148u, 215u,
- 179u, 135u, 204u, 138u,
- 2u, 120u, 82u, 214u,
- 123u, 74u, 135u, 112u,
- 160u, 138u, 136u, 110u,
- 140u, 88u, 100u, 0u,
- 163u, 111u, 134u, 59u,
- 186u, 106u, 70u, 149u,
- 136u, 140u, 76u, 88u,
- 26u, 134u, 127u, 255u,
- 160u, 170u, 80u, 176u,
- 128u, 84u, 128u, 112u,
- 184u, 189u, 63u, 58u,
- 148u, 141u, 125u, 1u,
- 255u, 201u, 188u, 142u,
- 199u, 140u, 132u, 115u,
- 171u, 86u, 50u, 199u,
- 190u, 207u, 95u, 154u,
- 116u, 164u, 97u, 150u,
- 54u, 1u, 137u, 120u,
- 13u, 152u, 76u, 159u,
- 53u, 87u, 115u, 123u,
- 111u, 95u, 242u, 114u,
- 250u, 104u, 255u, 12u,
- 82u, 96u, 20u, 157u,
- 216u, 164u, 144u, 54u,
- 136u, 116u, 11u, 80u,
- 58u, 84u, 89u, 91u,
- 118u, 255u, 164u, 85u,
- 242u, 89u, 167u, 145u,
- 1u, 68u, 138u, 113u,
- 111u, 56u, 19u, 53u,
- 102u, 71u, 138u, 82u,
- 60u, 154u, 165u, 174u,
- 30u, 172u, 255u, 77u,
- 41u, 228u, 99u, 161u,
- 74u, 196u, 108u, 98u,
- 146u, 56u, 162u, 248u,
- 96u, 108u, 169u, 111u,
- 186u, 154u, 1u, 55u,
- 141u, 169u, 156u, 63u,
- 91u, 54u, 136u, 202u,
- 255u, 68u, 164u, 7u,
- 130u, 161u, 92u, 230u,
- 118u, 119u, 157u, 148u,
- 162u, 138u, 144u, 105u,
- 186u, 153u, 95u, 208u,
- 158u, 92u, 120u, 255u,
- 180u, 133u, 166u, 181u,
- 111u, 133u, 159u, 92u,
- 208u, 132u, 105u, 97u,
- 28u, 202u, 42u, 57u,
- 171u, 102u, 241u, 198u,
- 155u, 255u, 164u, 220u,
- 132u, 1u, 144u, 73u,
- 76u, 65u, 105u, 230u,
- 153u, 96u, 66u, 75u,
- 31u, 149u, 155u, 192u,
- 196u, 206u, 95u, 53u,
- 124u, 165u, 151u, 255u,
- 198u, 142u, 146u, 140u,
- 132u, 144u, 142u, 79u,
- 156u, 102u, 247u, 42u,
- 213u, 95u, 45u, 73u,
- 18u, 174u, 128u, 1u,
- 60u, 152u, 128u, 217u,
- 187u, 99u, 163u, 139u,
- 147u, 79u, 154u, 248u,
- 175u, 255u, 29u, 106u,
- 223u, 92u, 86u, 43u,
- 95u, 48u, 189u, 255u,
- 111u, 121u, 13u, 95u,
- 157u, 50u, 72u, 88u,
- 2u, 120u, 31u, 217u,
- 109u, 89u, 48u, 255u,
- 36u, 172u, 196u, 134u,
- 53u, 234u, 174u, 148u,
- 128u, 68u, 74u, 99u,
- 158u, 92u, 131u, 107u,
- 189u, 100u, 141u, 1u,
- 106u, 107u, 162u, 133u,
- 156u, 212u, 175u, 113u,
- 166u, 174u, 138u, 90u,
- 19u, 21u, 255u, 172u,
- 163u, 177u, 220u, 205u,
- 123u, 149u, 153u, 78u,
- 184u, 132u, 173u, 87u,
- 114u, 182u, 206u, 220u,
- 127u, 177u, 49u, 82u,
- 152u, 64u, 1u, 136u,
- 157u, 112u, 219u, 170u,
- 49u, 174u, 5u, 19u,
- 115u, 118u, 49u, 1u,
- 144u, 147u, 107u, 124u,
- 217u, 24u, 216u, 34u,
- 50u, 0u, 137u, 159u,
- 98u, 213u, 92u, 58u,
- 108u, 144u, 145u, 120u,
- 1u, 161u, 34u, 251u,
- 54u, 133u, 157u, 21u,
- 208u, 124u, 172u, 163u,
- 16u, 167u, 165u, 161u,
- 238u, 119u, 31u, 93u,
- 138u, 255u, 240u, 223u,
- 177u, 85u, 102u, 208u,
- 114u, 221u, 97u, 179u,
- 237u, 189u, 163u, 106u,
- 222u, 122u, 143u, 161u,
- 189u, 156u, 224u, 177u,
- 172u, 90u, 231u, 1u,
- 111u, 37u, 255u, 202u,
- 61u, 146u, 203u, 93u,
- 185u, 139u, 106u, 236u,
- 194u, 222u, 126u, 191u,
- 152u, 53u, 172u, 84u,
- 114u, 127u, 183u, 20u,
- 101u, 56u, 87u, 79u,
- 255u, 213u, 119u, 118u,
- 101u, 193u, 91u, 171u,
- 106u, 255u, 43u, 171u,
- 120u, 160u, 121u, 97u,
- 160u, 96u, 149u, 209u,
- 103u, 188u, 153u, 145u,
- 213u, 41u, 150u, 107u,
- 53u, 0u, 132u, 198u,
- 117u, 215u, 94u, 42u,
- 217u, 135u, 206u, 103u,
- 165u, 90u, 144u, 135u,
- 168u, 133u, 134u, 35u,
- 176u, 70u, 255u, 102u,
- 102u, 78u, 157u, 148u,
- 156u, 112u, 43u, 146u,
- 167u, 92u, 193u, 1u,
- 13u, 159u, 56u, 117u,
- 148u, 131u, 72u, 217u,
- 111u, 255u, 84u, 210u,
- 111u, 132u, 80u, 98u,
- 159u, 85u, 139u, 132u,
- 115u, 89u, 99u, 155u,
- 40u, 165u, 174u, 152u,
- 238u, 113u, 71u, 159u,
- 42u, 174u, 86u, 1u,
- 163u, 168u, 206u, 188u,
- 116u, 255u, 116u, 140u,
- 98u, 121u, 58u, 161u,
- 141u, 55u, 140u, 186u,
- 57u, 102u, 95u, 157u,
- 64u, 158u, 69u, 171u,
- 84u, 151u, 133u, 204u,
- 55u, 105u, 176u, 0u,
- 105u, 119u, 161u, 36u,
- 109u, 150u, 146u, 150u,
- 143u, 98u, 110u, 1u,
- 76u, 113u, 200u, 85u,
- 128u, 255u, 177u, 129u,
- 102u, 161u, 100u, 114u,
- 89u, 189u, 165u, 46u,
- 63u, 117u, 116u, 152u,
- 161u, 19u, 106u, 132u,
- 80u, 219u, 130u, 146u,
- 255u, 75u, 206u, 74u,
- 59u, 179u, 118u, 156u,
- 130u, 167u, 150u, 119u,
- 122u, 193u, 139u, 140u,
- 154u, 100u, 255u, 138u,
- 170u, 177u, 137u, 140u,
- 178u, 223u, 167u, 134u,
- 78u, 70u, 38u, 235u,
- 255u, 25u, 211u, 184u,
- 74u, 70u, 55u, 28u,
- 49u, 101u, 255u, 113u,
- 82u, 247u, 250u, 154u,
- 195u, 109u, 88u, 125u,
- 75u, 107u, 105u, 58u,
- 213u, 129u, 96u, 120u,
- 17u, 93u, 113u, 141u,
- 97u, 160u, 255u, 144u,
- 130u, 115u, 137u, 157u,
- 11u, 130u, 163u, 133u,
- 28u, 112u, 71u, 73u,
- 123u, 201u, 58u, 182u,
- 1u, 126u, 126u, 114u,
- 154u, 140u, 81u, 114u,
- 0u, 79u, 102u, 191u,
- 189u, 126u, 186u, 145u,
- 68u, 110u, 147u, 153u,
- 227u, 77u, 116u, 255u,
- 106u, 178u, 134u, 150u,
- 156u, 169u, 42u, 69u,
- 135u, 165u, 149u, 62u,
- 189u, 255u, 26u, 107u,
- 93u, 97u, 99u, 211u,
- 73u, 124u, 99u, 72u,
- 143u, 99u, 33u, 73u,
- 146u, 186u, 104u, 76u,
- 151u, 179u, 76u, 255u,
- 139u, 78u, 165u, 44u,
- 124u, 158u, 126u, 36u,
- 99u, 22u, 179u, 156u,
- 187u, 77u, 1u, 125u,
- 131u, 94u, 107u, 148u,
- 193u, 45u, 113u, 113u,
- 82u, 91u, 195u, 156u,
- 54u, 85u, 30u, 70u,
- 200u, 164u, 255u, 91u,
- 26u, 60u, 151u, 249u,
- 182u, 255u, 191u, 97u,
- 152u, 133u, 191u, 223u,
- 217u, 106u, 90u, 123u,
- 102u, 72u, 201u, 47u,
- 91u, 109u, 102u, 190u,
- 1u, 111u, 232u, 193u,
- 119u, 40u, 134u, 100u,
- 216u, 152u, 106u, 114u,
- 100u, 135u, 112u, 188u,
- 145u, 160u, 168u, 64u,
- 61u, 153u, 141u, 110u,
- 255u, 62u, 127u, 119u,
- 90u, 99u, 255u, 129u,
- 160u, 176u, 109u, 200u,
- 101u, 156u, 46u, 148u,
- 175u, 35u, 130u, 113u,
- 74u, 189u, 62u, 8u,
- 8u, 199u, 68u, 156u,
- 231u, 64u, 246u, 110u,
- 1u, 156u, 69u, 108u,
- 1u, 179u, 119u, 164u,
- 137u, 148u, 209u, 138u,
- 112u, 160u, 69u, 197u,
- 181u, 51u, 73u, 181u,
- 192u, 5u, 1u, 175u,
- 84u, 48u, 109u, 162u,
- 131u, 121u, 239u, 91u,
- 253u, 42u, 188u, 126u,
- 242u, 22u, 74u, 221u,
- 244u, 147u, 119u, 173u,
- 133u, 212u, 1u, 113u,
- 108u, 138u, 182u, 171u,
- 41u, 30u, 117u, 179u,
- 94u, 120u, 92u, 63u,
- 106u, 162u, 101u, 120u,
- 100u, 127u, 140u, 255u,
- 57u, 151u, 89u, 156u,
- 238u, 133u, 162u, 81u,
- 69u, 26u, 93u, 95u,
- 74u, 255u, 151u, 99u,
- 121u, 145u, 147u, 98u,
- 90u, 108u, 1u, 56u,
- 93u, 99u, 218u, 102u,
- 149u, 89u, 76u, 168u,
- 122u, 190u, 9u, 111u,
- 135u, 117u, 165u, 102u,
- 62u, 18u, 108u, 1u,
- 238u, 105u, 120u, 200u,
- 255u, 108u, 81u, 201u,
- 164u, 64u, 25u, 102u,
- 24u, 116u, 209u, 153u,
- 74u, 64u, 93u, 9u,
- 255u, 123u, 28u, 214u,
- 144u, 98u, 121u, 116u,
- 116u, 88u, 164u, 31u,
- 146u, 201u, 105u, 88u,
- 119u, 216u, 147u, 73u,
- 205u, 182u, 115u, 170u,
- 119u, 73u, 154u, 119u,
- 255u, 234u, 158u, 71u,
- 191u, 152u, 40u, 130u,
- 66u, 94u, 1u, 148u,
- 137u, 91u, 250u, 101u,
- 81u, 106u, 104u, 61u,
- 157u, 85u, 93u, 217u,
- 191u, 170u, 252u, 255u,
- 229u, 132u, 32u, 154u,
- 212u, 72u, 247u, 78u,
- 105u, 127u, 184u, 170u,
- 99u, 122u, 144u, 127u,
- 117u, 1u, 38u, 122u,
- 59u, 110u, 64u, 175u,
- 62u, 237u, 106u, 255u,
- 10u, 230u, 235u, 154u,
- 49u, 81u, 159u, 101u,
- 165u, 192u, 107u, 68u,
- 91u, 150u, 121u, 169u,
- 59u, 197u, 69u, 255u,
- 109u, 97u, 114u, 78u,
- 59u, 78u, 102u, 92u,
- 147u, 114u, 197u, 124u,
- 122u, 87u, 153u, 153u,
- 128u, 106u, 196u, 81u,
- 173u, 182u, 255u, 105u,
- 207u, 163u, 0u, 123u,
- 183u, 80u, 77u, 162u,
- 198u, 138u, 172u, 207u,
- 81u, 73u, 82u, 103u,
- 69u, 138u, 155u, 131u,
- 29u, 147u, 40u, 101u,
- 161u, 155u, 255u, 135u,
- 156u, 45u, 192u, 128u,
- 200u, 160u, 2u, 136u,
- 84u, 99u, 6u, 136u,
- 232u, 65u, 216u, 122u,
- 121u, 179u, 1u, 1u,
- 0u, 199u, 126u, 111u,
- 101u, 130u, 156u, 154u,
- 158u, 56u, 142u, 127u,
- 95u, 130u, 99u, 219u,
- 81u, 123u, 191u, 150u,
- 30u, 103u, 206u, 75u,
- 170u, 129u, 69u, 22u,
- 137u, 1u, 44u, 135u,
- 113u, 63u, 126u, 86u,
- 190u, 94u, 133u, 120u,
- 122u, 94u, 61u, 0u,
- 130u, 215u, 111u, 151u,
- 174u, 155u, 132u, 190u,
- 115u, 167u, 92u, 50u,
- 213u, 92u, 167u, 255u,
- 178u, 114u, 64u, 142u,
- 255u, 145u, 105u, 53u,
- 90u, 127u, 102u, 71u,
- 202u, 155u, 223u, 131u,
- 206u, 104u, 102u, 218u,
- 111u, 144u, 207u, 86u,
- 101u, 135u, 127u, 108u,
- 137u, 121u, 148u, 95u,
- 66u, 109u, 151u, 255u,
- 180u, 7u, 8u, 156u,
- 27u, 1u, 49u, 103u,
- 163u, 219u, 59u, 132u,
- 68u, 224u, 87u, 83u,
- 108u, 107u, 52u, 126u,
- 172u, 125u, 115u, 62u,
- 191u, 182u, 96u, 144u,
- 1u, 250u, 173u, 93u,
- 140u, 118u, 131u, 112u,
- 148u, 227u, 182u, 25u,
- 114u, 118u, 1u, 108u,
- 118u, 124u, 126u, 179u,
- 132u, 72u, 226u, 50u,
- 20u, 106u, 252u, 110u,
- 255u, 200u, 100u, 148u,
- 182u, 17u, 86u, 107u,
- 130u, 152u, 80u, 214u,
- 21u, 93u, 192u, 145u,
- 191u, 149u, 1u, 135u,
- 107u, 118u, 208u, 163u,
- 157u, 129u, 5u, 141u,
- 151u, 135u, 178u, 119u,
- 110u, 153u, 167u, 111u,
- 204u, 82u, 255u, 123u,
- 131u, 61u, 185u, 164u,
- 151u, 207u, 89u, 104u,
- 128u, 129u, 72u, 226u,
- 61u, 178u, 40u, 255u,
- 120u, 31u, 168u, 116u,
- 82u, 124u, 57u, 148u,
- 82u, 144u, 126u, 45u,
- 114u, 1u, 154u, 185u,
- 147u, 155u, 153u, 181u,
- 137u, 119u, 0u, 117u,
- 212u, 119u, 84u, 110u,
- 246u, 31u, 248u, 131u,
- 99u, 174u, 116u, 1u,
- 119u, 223u, 132u, 136u,
- 152u, 213u, 181u, 204u,
- 67u, 92u, 88u, 164u,
- 162u, 104u, 241u, 130u,
- 189u, 210u, 137u, 1u,
- 66u, 140u, 134u, 174u,
- 180u, 46u, 135u, 186u,
- 98u, 85u, 204u, 143u,
- 173u, 86u, 96u, 163u,
- 127u, 121u, 146u, 108u,
- 59u, 255u, 130u, 101u,
- 114u, 180u, 84u, 152u,
- 1u, 170u, 78u, 154u,
- 96u, 115u, 215u, 111u,
- 119u, 93u, 138u, 152u,
- 18u, 83u, 78u, 127u,
- 109u, 233u, 61u, 28u,
- 149u, 255u, 148u, 115u,
- 75u, 63u, 175u, 99u,
- 104u, 36u, 183u, 193u,
- 240u, 1u, 142u, 102u,
- 109u, 160u, 30u, 136u,
- 37u, 176u, 172u, 102u,
- 144u, 231u, 138u, 58u,
- 164u, 157u, 201u, 150u,
- 149u, 93u, 207u, 255u,
- 151u, 199u, 78u, 167u,
- 158u, 184u, 90u, 0u,
- 59u, 39u, 105u, 249u,
- 196u, 151u, 201u, 189u,
- 115u, 20u, 175u, 98u,
- 94u, 106u, 190u, 205u,
- 112u, 159u, 119u, 1u,
- 97u, 118u, 144u, 188u,
- 72u, 139u, 148u, 205u,
- 167u, 132u, 106u, 84u,
- 109u, 191u, 255u, 120u,
- 155u, 218u, 73u, 148u,
- 83u, 250u, 113u, 138u,
- 144u, 68u, 174u, 255u,
- 70u, 185u, 138u, 142u,
- 109u, 86u, 105u, 132u,
- 135u, 107u, 133u, 124u,
- 151u, 173u, 165u, 162u,
- 16u, 0u, 90u, 221u,
- 94u, 148u, 187u, 196u,
- 42u, 88u, 135u, 143u,
- 193u, 103u, 116u, 199u,
- 106u, 119u, 191u, 143u,
- 199u, 76u, 119u, 73u,
- 185u, 128u, 152u, 255u,
- 224u, 122u, 208u, 241u,
- 165u, 104u, 95u, 100u,
- 174u, 4u, 1u, 127u,
- 211u, 91u, 85u, 55u,
- 147u, 153u, 121u, 123u,
- 92u, 137u, 1u, 169u,
- 78u, 168u, 125u, 119u,
- 116u, 46u, 121u, 121u,
- 44u, 139u, 0u, 215u,
- 97u, 112u, 18u, 146u,
- 103u, 213u, 73u, 76u,
- 132u, 76u, 5u, 154u,
- 164u, 172u, 7u, 133u,
- 158u, 91u, 1u, 153u,
- 136u, 102u, 151u, 45u,
- 109u, 114u, 103u, 69u,
- 104u, 89u, 56u, 1u,
- 117u, 138u, 132u, 112u,
- 52u, 172u, 243u, 205u,
- 131u, 106u, 93u, 234u,
- 164u, 102u, 255u, 106u,
- 190u, 117u, 114u, 156u,
- 180u, 142u, 181u, 93u,
- 164u, 97u, 92u, 35u,
- 105u, 0u, 31u, 95u,
- 253u, 155u, 132u, 22u,
- 116u, 107u, 160u, 185u,
- 177u, 179u, 64u, 54u,
- 102u, 117u, 116u, 106u,
- 176u, 172u, 209u, 183u,
- 86u, 70u, 114u, 255u,
- 59u, 22u, 132u, 149u,
- 155u, 82u, 61u, 255u,
- 153u, 101u, 207u, 66u,
- 49u, 151u, 38u, 168u,
- 174u, 142u, 82u, 119u,
- 138u, 150u, 84u, 142u,
- 0u, 79u, 113u, 169u,
- 156u, 109u, 158u, 93u,
- 134u, 105u, 193u, 112u,
- 108u, 80u, 148u, 111u,
- 162u, 0u, 198u, 88u,
- 118u, 184u, 40u, 107u,
- 59u, 31u, 140u, 130u,
- 69u, 228u, 112u, 1u,
- 139u, 95u, 201u, 177u,
- 155u, 217u, 170u, 219u,
- 185u, 157u, 118u, 141u,
- 194u, 176u, 183u, 1u,
- 166u, 65u, 114u, 155u,
- 37u, 116u, 132u, 181u,
- 42u, 120u, 91u, 156u,
- 186u, 227u, 102u, 1u,
- 218u, 183u, 198u, 200u,
- 11u, 130u, 186u, 62u,
- 132u, 219u, 166u, 83u,
- 185u, 149u, 151u, 93u,
- 16u, 92u, 116u, 91u,
- 224u, 133u, 236u, 81u,
- 185u, 115u, 245u, 1u,
- 92u, 65u, 116u, 137u,
- 114u, 146u, 47u, 118u,
- 92u, 129u, 29u, 33u,
- 8u, 114u, 174u, 255u,
- 176u, 168u, 213u, 1u,
- 111u, 109u, 238u, 152u,
- 96u, 137u, 100u, 96u,
- 170u, 131u, 58u, 92u,
- 100u, 133u, 138u, 164u,
- 75u, 219u, 179u, 213u,
- 139u, 179u, 68u, 20u,
- 255u, 159u, 156u, 127u,
- 127u, 124u, 187u, 64u,
- 255u, 123u, 176u, 107u,
- 133u, 100u, 137u, 220u,
- 73u, 125u, 112u, 232u,
- 255u, 135u, 118u, 47u,
- 194u, 183u, 120u, 167u,
- 163u, 31u, 86u, 144u,
- 164u, 135u, 132u, 73u,
- 138u, 70u, 255u, 131u,
- 129u, 179u, 67u, 118u,
- 137u, 105u, 158u, 19u,
- 88u, 233u, 120u, 193u,
- 147u, 107u, 134u, 128u,
- 7u, 167u, 222u, 44u,
- 255u, 197u, 100u, 110u,
- 163u, 142u, 133u, 205u,
- 39u, 129u, 178u, 86u,
- 185u, 119u, 188u, 211u,
- 172u, 132u, 1u, 77u,
- 145u, 143u, 114u, 27u,
- 142u, 81u, 90u, 210u,
- 49u, 50u, 179u, 141u,
- 36u, 208u, 139u, 153u,
- 118u, 1u, 149u, 60u,
- 106u, 224u, 210u, 116u,
- 132u, 61u, 82u, 127u,
- 117u, 171u, 217u, 181u,
- 110u, 1u, 112u, 134u,
- 99u, 207u, 198u, 132u,
- 191u, 180u, 155u, 39u,
- 15u, 141u, 1u, 78u,
- 147u, 148u, 232u, 217u,
- 108u, 46u, 159u, 47u,
- 189u, 115u, 197u, 93u,
- 175u, 122u, 1u, 54u,
- 113u, 130u, 134u, 95u,
- 104u, 118u, 90u, 226u,
- 255u, 201u, 62u, 19u,
- 205u, 167u, 79u, 127u,
- 149u, 246u, 148u, 154u,
- 236u, 112u, 121u, 67u,
- 103u, 67u, 149u, 255u,
- 69u, 166u, 69u, 115u,
- 116u, 93u, 161u, 128u,
- 201u, 148u, 84u, 146u,
- 149u, 141u, 140u, 114u,
- 112u, 171u, 132u, 56u,
- 131u, 163u, 255u, 107u,
- 153u, 201u, 138u, 183u,
- 25u, 36u, 143u, 1u,
- 122u, 233u, 167u, 153u,
- 237u, 172u, 168u, 123u,
- 1u, 155u, 168u, 106u,
- 107u, 180u, 125u, 147u,
- 88u, 98u, 49u, 118u,
- 63u, 154u, 115u, 250u,
- 255u, 157u, 161u, 93u,
- 83u, 117u, 88u, 45u,
- 158u, 82u, 84u, 113u,
- 91u, 174u, 149u, 152u,
- 123u, 118u, 45u, 195u,
- 138u, 191u, 134u, 154u,
- 173u, 229u, 218u, 255u,
- 255u, 60u, 120u, 208u,
- 121u, 80u, 255u, 114u,
- 142u, 90u, 228u, 88u,
- 235u, 82u, 25u, 93u,
- 126u, 170u, 147u, 110u,
- 97u, 128u, 77u, 113u,
- 72u, 1u, 8u, 183u,
- 128u, 108u, 213u, 200u,
- 176u, 17u, 27u, 171u,
- 89u, 108u, 255u, 121u,
- 123u, 26u, 250u, 182u,
- 86u, 210u, 115u, 128u,
- 20u, 95u, 128u, 153u,
- 89u, 116u, 141u, 175u,
- 102u, 146u, 126u, 114u,
- 46u, 116u, 97u, 169u,
- 53u, 15u, 155u, 255u,
- 222u, 75u, 51u, 179u,
- 44u, 145u, 151u, 206u,
- 32u, 255u, 35u, 126u,
- 127u, 164u, 168u, 150u,
- 157u, 107u, 190u, 255u,
- 166u, 178u, 187u, 147u,
- 235u, 93u, 183u, 123u,
- 142u, 139u, 157u, 166u,
- 36u, 67u, 66u, 222u,
- 168u, 172u, 1u, 83u,
- 44u, 166u, 124u, 9u,
- 125u, 89u, 54u, 95u,
- 126u, 46u, 163u, 202u,
- 142u, 19u, 157u, 216u,
- 11u, 57u, 1u, 85u,
- 139u, 100u, 61u, 204u,
- 113u, 1u, 102u, 181u,
- 103u, 136u, 120u, 128u,
- 222u, 68u, 132u, 189u,
- 156u, 145u, 79u, 120u,
- 95u, 70u, 157u, 105u,
- 194u, 71u, 233u, 109u,
- 163u, 70u, 80u, 155u,
- 171u, 105u, 74u, 1u,
- 165u, 167u, 0u, 199u,
- 65u, 132u, 87u, 158u,
- 5u, 136u, 139u, 141u,
- 104u, 163u, 166u, 176u,
- 194u, 192u, 236u, 53u,
- 255u, 207u, 11u, 69u,
- 156u, 225u, 75u, 82u,
- 225u, 103u, 61u, 118u,
- 121u, 192u, 48u, 183u,
- 241u, 169u, 103u, 12u,
- 91u, 1u, 84u, 108u,
- 166u, 167u, 153u, 83u,
- 114u, 215u, 137u, 97u,
- 124u, 221u, 114u, 148u,
- 142u, 98u, 173u, 255u,
- 134u, 105u, 87u, 161u,
- 120u, 183u, 75u, 1u,
- 191u, 58u, 138u, 162u,
- 137u, 93u, 214u, 216u,
- 107u, 145u, 130u, 98u,
- 24u, 70u, 1u, 91u,
- 43u, 185u, 245u, 150u,
- 215u, 112u, 175u, 144u,
- 168u, 146u, 148u, 173u,
- 159u, 211u, 246u, 26u,
- 157u, 157u, 78u, 95u,
- 0u, 105u, 68u, 76u,
- 195u, 207u, 169u, 165u,
- 111u, 142u, 204u, 165u,
- 85u, 116u, 37u, 152u,
- 145u, 116u, 127u, 141u,
- 1u, 149u, 55u, 216u,
- 126u, 255u, 119u, 119u,
- 94u, 150u, 91u, 94u,
- 110u, 158u, 124u, 79u,
- 94u, 171u, 118u, 117u,
- 178u, 78u, 89u, 193u,
- 78u, 167u, 1u, 137u,
- 148u, 117u, 114u, 159u,
- 147u, 156u, 102u, 187u,
- 139u, 197u, 171u, 1u,
- 150u, 120u, 173u, 126u,
- 161u, 142u, 124u, 128u,
- 160u, 198u, 134u, 69u,
- 97u, 49u, 1u, 183u,
- 225u, 103u, 170u, 175u,
- 43u, 94u, 55u, 80u,
- 139u, 67u, 86u, 94u,
- 87u, 92u, 189u, 72u,
- 127u, 80u, 170u, 146u,
- 185u, 44u, 80u, 86u,
- 38u, 205u, 120u, 255u,
- 82u, 104u, 115u, 102u,
- 255u, 65u, 44u, 168u,
- 230u, 186u, 183u, 176u,
- 98u, 142u, 150u, 60u,
- 73u, 18u, 83u, 138u,
- 87u, 255u, 140u, 168u,
- 124u, 117u, 169u, 156u,
- 209u, 215u, 195u, 213u,
- 0u, 51u, 107u, 163u,
- 168u, 203u, 203u, 73u,
- 85u, 167u, 86u, 118u,
- 236u, 143u, 97u, 84u,
- 81u, 135u, 171u, 79u,
- 93u, 255u, 157u, 141u,
- 193u, 46u, 143u, 110u,
- 112u, 24u, 105u, 155u,
- 108u, 154u, 99u, 151u,
- 177u, 79u, 167u, 172u,
- 200u, 105u, 167u, 0u,
- 93u, 188u, 191u, 198u,
- 57u, 89u, 128u, 224u,
- 176u, 145u, 245u, 204u,
- 112u, 207u, 102u, 177u,
- 90u, 142u, 255u, 94u,
- 200u, 113u, 203u, 138u,
- 161u, 134u, 9u, 47u,
- 157u, 185u, 198u, 101u,
- 128u, 255u, 38u, 62u,
- 199u, 72u, 255u, 132u,
- 175u, 144u, 106u, 20u,
- 163u, 110u, 79u, 76u,
- 184u, 214u, 122u, 80u,
- 138u, 79u, 137u, 171u,
- 141u, 176u, 99u, 66u,
- 91u, 131u, 0u, 149u,
- 83u, 130u, 184u, 137u,
- 255u, 31u, 207u, 96u,
- 129u, 3u, 198u, 119u,
- 155u, 114u, 67u, 164u,
- 188u, 191u, 162u, 105u,
- 191u, 222u, 118u, 36u,
- 153u, 189u, 34u, 110u,
- 61u, 1u, 235u, 125u,
- 232u, 226u, 143u, 42u,
- 169u, 168u, 132u, 27u,
- 45u, 60u, 129u, 94u,
- 117u, 104u, 60u, 84u,
- 210u, 176u, 1u, 63u,
- 37u, 116u, 67u, 88u,
- 0u, 112u, 96u, 189u,
- 26u, 110u, 234u, 199u,
- 105u, 21u, 62u, 154u,
- 132u, 121u, 117u, 201u,
- 92u, 96u, 29u, 69u,
- 63u, 160u, 175u, 78u,
- 193u, 1u, 153u, 43u,
- 56u, 143u, 114u, 43u,
- 130u, 111u, 175u, 143u,
- 102u, 151u, 65u, 187u,
- 138u, 1u, 170u, 196u,
- 231u, 81u, 222u, 23u,
- 15u, 138u, 67u, 113u,
- 130u, 255u, 126u, 125u,
- 60u, 154u, 36u, 227u,
- 108u, 133u, 57u, 106u,
- 70u, 38u, 154u, 64u,
- 200u, 224u, 158u, 189u,
- 32u, 108u, 41u, 1u,
- 144u, 131u, 204u, 41u,
- 197u, 186u, 127u, 255u,
- 100u, 28u, 150u, 149u,
- 133u, 119u, 137u, 130u,
- 139u, 142u, 29u, 89u,
- 194u, 107u, 107u, 74u,
- 150u, 193u, 255u, 45u,
- 162u, 107u, 240u, 164u,
- 61u, 145u, 53u, 181u,
- 75u, 180u, 90u, 111u,
- 255u, 59u, 227u, 185u,
- 78u, 128u, 90u, 137u,
- 178u, 112u, 17u, 109u,
- 149u, 60u, 248u, 71u,
- 255u, 89u, 122u, 118u,
- 170u, 137u, 137u, 75u,
- 1u, 145u, 132u, 139u,
- 110u, 113u, 201u, 53u,
- 103u, 24u, 117u, 135u,
- 119u, 67u, 180u, 131u,
- 18u, 45u, 150u, 158u,
- 88u, 90u, 130u, 1u,
- 81u, 134u, 221u, 37u,
- 119u, 72u, 134u, 145u,
- 42u, 164u, 157u, 53u,
- 88u, 180u, 201u, 156u,
- 5u, 117u, 12u, 68u,
- 19u, 26u, 100u, 255u,
- 245u, 182u, 115u, 96u,
- 180u, 140u, 17u, 78u,
- 148u, 205u, 90u, 5u,
- 255u, 144u, 38u, 64u,
- 129u, 25u, 120u, 206u,
- 115u, 116u, 0u, 74u,
- 112u, 133u, 83u, 158u,
- 127u, 160u, 24u, 38u,
- 149u, 69u, 98u, 63u,
- 69u, 255u, 74u, 219u,
- 179u, 122u, 49u, 106u,
- 25u, 151u, 122u, 133u,
- 75u, 117u, 1u, 194u,
- 99u, 200u, 173u, 139u,
- 61u, 141u, 28u, 187u,
- 120u, 139u, 118u, 149u,
- 151u, 164u, 152u, 77u,
- 88u, 27u, 170u, 1u,
- 90u, 188u, 122u, 129u,
- 174u, 52u, 177u, 145u,
- 132u, 82u, 40u, 115u,
- 150u, 139u, 235u, 174u,
- 229u, 86u, 1u, 56u,
- 91u, 121u, 116u, 91u,
- 158u, 88u, 102u, 114u,
- 141u, 105u, 144u, 124u,
- 85u, 136u, 177u, 186u,
- 237u, 144u, 255u, 91u,
- 161u, 90u, 140u, 74u,
- 188u, 184u, 91u, 185u,
- 146u, 20u, 161u, 212u,
- 173u, 214u, 1u, 120u,
- 81u, 127u, 106u, 199u,
- 1u, 109u, 150u, 145u,
- 93u, 163u, 139u, 49u,
- 187u, 29u, 142u, 93u,
- 52u, 247u, 104u, 135u,
- 144u, 20u, 96u, 80u,
- 172u, 103u, 208u, 56u,
- 118u, 1u, 92u, 132u,
- 193u, 104u, 24u, 101u,
- 162u, 104u, 74u, 219u,
- 223u, 227u, 160u, 209u,
- 37u, 64u, 1u, 63u,
- 87u, 90u, 45u, 65u,
- 186u, 122u, 110u, 86u,
- 138u, 151u, 114u, 10u,
- 155u, 105u, 140u, 1u,
- 136u, 191u, 152u, 104u,
- 123u, 156u, 126u, 169u,
- 0u, 122u, 108u, 156u,
- 103u, 103u, 181u, 96u,
- 66u, 1u, 115u, 140u,
- 209u, 145u, 176u, 249u,
- 73u, 222u, 53u, 120u,
- 159u, 152u, 189u, 43u,
- 111u, 87u, 47u, 130u,
- 170u, 105u, 127u, 148u,
- 163u, 117u, 126u, 83u,
- 159u, 255u, 107u, 98u,
- 70u, 172u, 49u, 63u,
- 255u, 133u, 72u, 104u,
- 27u, 69u, 88u, 86u,
- 96u, 232u, 103u, 141u,
- 209u, 153u, 104u, 129u,
- 191u, 225u, 86u, 45u,
- 142u, 115u, 163u, 191u,
- 255u, 195u, 116u, 96u,
- 83u, 177u, 59u, 129u,
- 44u, 55u, 67u, 116u,
- 3u, 82u, 255u, 193u,
- 173u, 252u, 76u, 178u,
- 223u, 1u, 82u, 229u,
- 105u, 141u, 67u, 60u,
- 157u, 147u, 196u, 147u,
- 255u, 32u, 186u, 71u,
- 125u, 175u, 109u, 93u,
- 120u, 144u, 157u, 139u,
- 56u, 192u, 140u, 222u,
- 255u, 80u, 137u, 153u,
- 23u, 65u, 117u, 146u,
- 152u, 79u, 156u, 83u,
- 205u, 238u, 255u, 116u,
- 225u, 135u, 73u, 132u,
- 169u, 127u, 130u, 183u,
- 115u, 118u, 92u, 182u,
- 93u, 100u, 52u, 0u,
- 62u, 201u, 125u, 120u,
- 57u, 90u, 66u, 127u,
- 152u, 112u, 240u, 102u,
- 82u, 84u, 52u, 5u,
- 185u, 117u, 255u, 54u,
- 163u, 148u, 90u, 188u,
- 99u, 141u, 124u, 62u,
- 1u, 33u, 146u, 107u,
- 67u, 169u, 125u, 145u,
- 116u, 101u, 121u, 3u,
- 174u, 32u, 1u, 68u,
- 143u, 163u, 176u, 120u,
- 4u, 44u, 108u, 91u,
- 123u, 178u, 70u, 49u,
- 72u, 104u, 102u, 255u,
- 142u, 191u, 190u, 151u,
- 134u, 77u, 156u, 124u,
- 97u, 174u, 93u, 109u,
- 106u, 189u, 84u, 49u,
- 255u, 23u, 173u, 100u,
- 178u, 163u, 113u, 185u,
- 228u, 119u, 84u, 255u,
- 178u, 133u, 89u, 180u,
- 160u, 193u, 92u, 80u,
- 95u, 189u, 141u, 158u,
- 48u, 118u, 205u, 251u,
- 62u, 61u, 121u, 11u,
- 46u, 143u, 43u, 143u,
- 226u, 10u, 241u, 255u,
- 150u, 148u, 112u, 131u,
- 55u, 133u, 167u, 152u,
- 176u, 106u, 255u, 193u,
- 98u, 132u, 138u, 180u,
- 184u, 85u, 255u, 125u,
- 145u, 71u, 203u, 102u,
- 146u, 105u, 54u, 115u,
- 148u, 127u, 136u, 19u,
- 75u, 85u, 77u, 118u,
- 0u, 45u, 127u, 160u,
- 121u, 141u, 137u, 170u,
- 59u, 154u, 137u, 216u,
- 121u, 119u, 170u, 90u,
- 140u, 105u, 255u, 149u,
- 141u, 137u, 95u, 172u,
- 158u, 64u, 119u, 137u,
- 80u, 105u, 164u, 81u,
- 5u, 255u, 186u, 82u,
- 114u, 245u, 92u, 183u,
- 172u, 172u, 182u, 163u,
- 161u, 158u, 184u, 39u,
- 164u, 153u, 115u, 163u,
- 165u, 53u, 188u, 212u,
- 69u, 255u, 70u, 148u,
- 144u, 77u, 57u, 86u,
- 197u, 50u, 192u, 220u,
- 107u, 75u, 79u, 159u,
- 156u, 255u, 127u, 32u,
- 134u, 86u, 115u, 202u,
- 155u, 205u, 1u, 58u,
- 112u, 28u, 96u, 41u,
- 163u, 191u, 125u, 111u,
- 255u, 157u, 67u, 168u,
- 82u, 166u, 167u, 255u,
- 95u, 167u, 144u, 32u,
- 176u, 98u, 30u, 78u,
- 37u, 101u, 130u, 115u,
- 147u, 105u, 210u, 134u,
- 184u, 130u, 1u, 109u,
- 187u, 97u, 159u, 59u,
- 121u, 85u, 110u, 144u,
- 255u, 107u, 207u, 36u,
- 148u, 91u, 51u, 119u,
- 133u, 175u, 191u, 143u,
- 155u, 210u, 93u, 255u,
- 145u, 113u, 90u, 88u,
- 134u, 34u, 223u, 172u,
- 95u, 157u, 52u, 146u,
- 29u, 153u, 145u, 90u,
- 62u, 43u, 83u, 195u,
- 127u, 253u, 224u, 51u,
- 0u, 51u, 169u, 206u,
- 109u, 114u, 52u, 71u,
- 255u, 175u, 118u, 101u,
- 113u, 120u, 78u, 133u,
- 104u, 132u, 117u, 155u,
- 127u, 187u, 170u, 142u,
- 120u, 93u, 62u, 200u,
- 150u, 98u, 255u, 61u,
- 38u, 219u, 141u, 82u,
- 56u, 158u, 231u, 33u,
- 160u, 129u, 255u, 91u,
- 54u, 239u, 73u, 146u,
- 182u, 105u, 253u, 102u,
- 103u, 71u, 211u, 145u,
- 182u, 202u, 142u, 183u,
- 239u, 118u, 0u, 79u,
- 72u, 124u, 134u, 106u,
- 113u, 126u, 153u, 93u,
- 255u, 123u, 85u, 219u,
- 153u, 45u, 92u, 109u,
- 192u, 55u, 55u, 46u,
- 84u, 134u, 141u, 99u,
- 119u, 86u, 1u, 96u,
- 170u, 134u, 226u, 160u,
- 144u, 63u, 150u, 145u,
- 146u, 80u, 200u, 127u,
- 77u, 130u, 142u, 234u,
- 186u, 114u, 232u, 47u,
- 66u, 14u, 52u, 1u,
- 57u, 234u, 108u, 255u,
- 74u, 37u, 71u, 166u,
- 78u, 192u, 180u, 175u,
- 25u, 73u, 143u, 168u,
- 58u, 64u, 118u, 207u,
- 226u, 255u, 10u, 117u,
- 126u, 163u, 100u, 166u,
- 66u, 202u, 55u, 156u,
- 53u, 90u, 151u, 98u,
- 139u, 83u, 119u, 161u,
- 121u, 255u, 175u, 175u,
- 125u, 21u, 75u, 128u,
- 251u, 75u, 147u, 93u,
- 125u, 255u, 141u, 172u,
- 119u, 144u, 143u, 201u,
- 127u, 223u, 61u, 141u,
- 140u, 188u, 108u, 213u,
- 156u, 125u, 93u, 132u,
- 127u, 255u, 44u, 108u,
- 186u, 89u, 62u, 60u,
- 132u, 36u, 3u, 255u,
- 83u, 175u, 247u, 46u,
- 132u, 176u, 25u, 125u,
- 110u, 214u, 54u, 94u,
- 185u, 124u, 74u, 168u,
- 122u, 36u, 225u, 175u,
- 255u, 74u, 81u, 253u,
- 7u, 95u, 19u, 39u,
- 196u, 168u, 155u, 69u,
- 255u, 90u, 124u, 81u,
- 150u, 100u, 115u, 151u,
- 157u, 198u, 185u, 49u,
- 255u, 64u, 176u, 147u,
- 16u, 145u, 186u, 90u,
- 152u, 125u, 62u, 133u,
- 156u, 123u, 87u, 125u,
- 65u, 112u, 145u, 125u,
- 103u, 181u, 108u, 137u,
- 149u, 140u, 156u, 162u,
- 114u, 106u, 166u, 255u,
- 163u, 103u, 185u, 146u,
- 255u, 122u, 196u, 157u,
- 216u, 134u, 50u, 69u,
- 27u, 109u, 170u, 99u,
- 121u, 101u, 159u, 190u,
- 124u, 56u, 187u, 1u,
- 56u, 146u, 36u, 92u,
- 165u, 91u, 94u, 178u,
- 171u, 139u, 141u, 106u,
- 111u, 103u, 154u, 159u,
- 115u, 146u, 93u, 170u,
- 72u, 107u, 1u, 29u,
- 184u, 89u, 173u, 87u,
- 1u, 242u, 79u, 165u,
- 128u, 231u, 95u, 41u,
- 38u, 59u, 106u, 228u,
- 65u, 173u, 110u, 127u,
- 26u, 151u, 136u, 152u,
- 139u, 176u, 100u, 125u,
- 235u, 58u, 105u, 255u,
- 73u, 137u, 137u, 101u,
- 102u, 33u, 20u, 139u,
- 63u, 138u, 134u, 1u,
- 72u, 137u, 232u, 156u,
- 140u, 108u, 112u, 105u,
- 122u, 125u, 0u, 86u,
- 145u, 177u, 106u, 64u,
- 121u, 118u, 106u, 169u,
- 134u, 106u, 101u, 131u,
- 67u, 139u, 255u, 2u,
- 191u, 95u, 217u, 99u,
- 121u, 159u, 14u, 111u,
- 129u, 198u, 117u, 34u,
- 160u, 154u, 0u, 131u,
- 41u, 107u, 240u, 89u,
- 237u, 162u, 242u, 76u,
- 104u, 121u, 205u, 24u,
- 92u, 142u, 176u, 146u,
- 107u, 173u, 153u, 139u,
- 178u, 1u, 115u, 150u,
- 133u, 61u, 55u, 169u,
- 45u, 102u, 32u, 91u,
- 127u, 210u, 184u, 108u,
- 102u, 1u, 78u, 173u,
- 0u, 81u, 72u, 202u,
- 110u, 136u, 96u, 107u,
- 204u, 125u, 153u, 90u,
- 63u, 52u, 250u, 182u,
- 163u, 94u, 253u, 121u,
- 138u, 87u, 162u, 60u,
- 155u, 82u, 183u, 127u,
- 156u, 1u, 95u, 63u,
- 173u, 113u, 59u, 96u,
- 91u, 107u, 171u, 176u,
- 174u, 160u, 156u, 213u,
- 153u, 236u, 124u, 0u,
- 107u, 70u, 135u, 171u,
- 220u, 129u, 108u, 129u,
- 248u, 255u, 92u, 33u,
- 135u, 113u, 61u, 119u,
- 156u, 150u, 65u, 75u,
- 143u, 1u, 123u, 174u,
- 149u, 244u, 255u, 187u,
- 150u, 157u, 28u, 92u,
- 107u, 72u, 119u, 1u,
- 238u, 52u, 142u, 195u,
- 120u, 171u, 113u, 226u,
- 116u, 171u, 64u, 147u,
- 41u, 53u, 188u, 81u,
- 17u, 191u, 58u, 128u,
- 48u, 86u, 169u, 30u,
- 255u, 57u, 52u, 139u,
- 255u, 182u, 198u, 94u,
- 164u, 237u, 162u, 161u,
- 213u, 183u, 96u, 168u,
- 173u, 178u, 126u, 173u,
- 132u, 140u, 0u, 71u,
- 219u, 1u, 114u, 64u,
- 180u, 224u, 209u, 156u,
- 152u, 131u, 123u, 61u,
- 179u, 255u, 116u, 229u,
- 48u, 211u, 113u, 165u,
- 157u, 75u, 141u, 187u,
- 181u, 87u, 64u, 158u,
- 51u, 110u, 112u, 171u,
- 1u, 113u, 87u, 196u,
- 114u, 186u, 179u, 70u,
- 24u, 1u, 36u, 218u,
- 119u, 67u, 185u, 144u,
- 240u, 166u, 142u, 23u,
- 84u, 149u, 115u, 202u,
- 27u, 100u, 19u, 255u,
- 164u, 108u, 136u, 39u,
- 184u, 135u, 71u, 97u,
- 118u, 127u, 197u, 220u,
- 165u, 142u, 175u, 255u,
- 255u, 162u, 201u, 161u,
- 160u, 137u, 109u, 138u,
- 202u, 206u, 148u, 172u,
- 143u, 148u, 157u, 117u,
- 150u, 224u, 145u, 74u,
- 182u, 184u, 28u, 174u,
- 166u, 181u, 197u, 159u,
- 255u, 126u, 112u, 74u,
- 129u, 23u, 120u, 115u,
- 148u, 63u, 122u, 184u,
- 255u, 125u, 145u, 157u,
- 79u, 174u, 94u, 46u,
- 119u, 85u, 121u, 181u,
- 54u, 179u, 185u, 181u,
- 28u, 255u, 36u, 110u,
- 226u, 142u, 191u, 136u,
- 136u, 207u, 255u, 127u,
- 132u, 173u, 138u, 182u,
- 128u, 62u, 129u, 102u,
- 168u, 140u, 201u, 162u,
- 172u, 145u, 214u, 212u,
- 185u, 121u, 65u, 143u,
- 250u, 5u, 1u, 48u,
- 176u, 122u, 142u, 85u,
- 140u, 207u, 76u, 83u,
- 84u, 255u, 231u, 223u,
- 185u, 185u, 58u, 158u,
- 191u, 14u, 107u, 70u,
- 113u, 28u, 28u, 177u,
- 255u, 220u, 9u, 186u,
- 211u, 104u, 172u, 192u,
- 82u, 66u, 139u, 129u,
- 52u, 123u, 100u, 255u,
- 116u, 123u, 229u, 145u,
- 73u, 111u, 105u, 25u,
- 135u, 123u, 100u, 107u,
- 117u, 197u, 81u, 189u,
- 186u, 154u, 150u, 102u,
- 171u, 80u, 52u, 1u,
- 151u, 168u, 82u, 11u,
- 137u, 143u, 132u, 190u,
- 1u, 179u, 63u, 145u,
- 135u, 87u, 154u, 45u,
- 104u, 120u, 128u, 188u,
- 255u, 136u, 204u, 141u,
- 234u, 114u, 94u, 82u,
- 119u, 192u, 69u, 66u,
- 115u, 10u, 130u, 201u,
- 173u, 132u, 1u, 80u,
- 117u, 124u, 149u, 165u,
- 79u, 178u, 90u, 58u,
- 88u, 219u, 103u, 151u,
- 75u, 189u, 174u, 159u,
- 93u, 131u, 219u, 170u,
- 211u, 51u, 96u, 90u,
- 190u, 44u, 1u, 39u,
- 137u, 63u, 189u, 255u,
- 55u, 139u, 187u, 155u,
- 129u, 110u, 106u, 108u,
- 141u, 41u, 99u, 157u,
- 82u, 143u, 125u, 134u,
- 111u, 117u, 101u, 137u,
- 207u, 132u, 96u, 152u,
- 138u, 1u, 59u, 44u,
- 189u, 195u, 100u, 98u,
- 132u, 195u, 154u, 255u,
- 177u, 123u, 194u, 241u,
- 132u, 152u, 27u, 134u,
- 123u, 127u, 53u, 149u,
- 124u, 137u, 73u, 97u,
- 74u, 78u, 1u, 36u,
- 78u, 145u, 56u, 178u,
- 1u, 203u, 63u, 242u,
- 207u, 119u, 27u, 87u,
- 109u, 17u, 84u, 74u,
- 75u, 124u, 213u, 69u,
- 229u, 127u, 148u, 114u,
- 255u, 128u, 113u, 169u,
- 205u, 126u, 153u, 200u,
- 174u, 119u, 55u, 43u,
- 136u, 121u, 204u, 177u,
- 28u, 110u, 236u, 53u,
- 141u, 38u, 149u, 255u,
- 119u, 48u, 151u, 214u,
- 117u, 83u, 125u, 160u,
- 47u, 136u, 127u, 154u,
- 255u, 220u, 178u, 173u,
- 167u, 59u, 181u, 109u,
- 129u, 66u, 113u, 120u,
- 121u, 118u, 106u, 87u,
- 198u, 200u, 133u, 163u,
- 125u, 83u, 255u, 149u,
- 62u, 158u, 226u, 0u,
- 118u, 127u, 66u, 171u,
- 137u, 154u, 198u, 130u,
- 77u, 158u, 102u, 92u,
- 45u, 220u, 245u, 160u,
- 113u, 87u, 204u, 39u,
- 87u, 52u, 162u, 63u,
- 63u, 255u, 169u, 141u,
- 133u, 118u, 148u, 151u,
- 89u, 104u, 246u, 63u,
- 77u, 143u, 116u, 194u,
- 184u, 255u, 214u, 164u,
- 98u, 125u, 98u, 15u,
- 71u, 120u, 29u, 255u,
- 204u, 178u, 85u, 53u,
- 26u, 97u, 100u, 107u,
- 190u, 90u, 92u, 160u,
- 188u, 254u, 166u, 93u,
- 63u, 154u, 117u, 182u,
- 255u, 91u, 202u, 47u,
- 210u, 87u, 247u, 102u,
- 189u, 1u, 149u, 186u,
- 140u, 133u, 120u, 112u,
- 91u, 100u, 100u, 51u,
- 186u, 207u, 97u, 182u,
- 46u, 170u, 8u, 155u,
- 120u, 64u, 192u, 87u,
- 101u, 7u, 255u, 103u,
- 93u, 110u, 101u, 255u,
- 89u, 171u, 60u, 52u,
- 87u, 127u, 130u, 110u,
- 109u, 127u, 125u, 52u,
- 143u, 129u, 121u, 166u,
- 148u, 126u, 56u, 46u,
- 195u, 50u, 166u, 200u,
- 118u, 55u, 0u, 113u,
- 189u, 133u, 221u, 153u,
- 132u, 164u, 69u, 55u,
- 221u, 145u, 148u, 180u,
- 77u, 173u, 1u, 67u,
- 105u, 150u, 143u, 57u,
- 98u, 94u, 100u, 128u,
- 104u, 255u, 174u, 152u,
- 119u, 78u, 141u, 141u,
- 210u, 94u, 186u, 128u,
- 39u, 164u, 142u, 167u,
- 188u, 149u, 255u, 231u,
- 206u, 64u, 94u, 72u,
- 153u, 105u, 128u, 108u,
- 197u, 98u, 120u, 168u,
- 142u, 52u, 122u, 255u,
- 33u, 123u, 149u, 113u,
- 108u, 106u, 10u, 154u,
- 21u, 221u, 140u, 27u,
- 255u, 71u, 215u, 230u,
- 113u, 95u, 157u, 170u,
- 1u, 108u, 141u, 200u,
- 102u, 105u, 159u, 59u,
- 153u, 152u, 159u, 165u,
- 155u, 45u, 92u, 163u,
- 119u, 122u, 82u, 228u,
- 86u, 101u, 114u, 161u,
- 255u, 142u, 139u, 56u,
- 165u, 110u, 100u, 140u,
- 201u, 255u, 212u, 171u,
- 75u, 209u, 214u, 178u,
- 76u, 116u, 156u, 184u,
- 152u, 65u, 51u, 91u,
- 138u, 252u, 177u, 97u,
- 101u, 106u, 0u, 139u,
- 137u, 226u, 184u, 150u,
- 42u, 108u, 227u, 184u,
- 76u, 225u, 123u, 234u,
- 152u, 79u, 187u, 210u,
- 23u, 255u, 223u, 140u,
- 144u, 131u, 165u, 248u,
- 151u, 69u, 157u, 140u,
- 177u, 154u, 198u, 119u,
- 108u, 171u, 1u, 31u,
- 154u, 219u, 121u, 95u,
- 151u, 32u, 219u, 121u,
- 57u, 39u, 117u, 185u,
- 62u, 190u, 80u, 39u,
- 57u, 154u, 255u, 112u,
- 176u, 191u, 90u, 99u,
- 112u, 173u, 76u, 190u,
- 138u, 83u, 171u, 130u,
- 123u, 255u, 100u, 117u,
- 57u, 251u, 151u, 164u,
- 171u, 235u, 110u, 123u,
- 186u, 171u, 1u, 165u,
- 253u, 177u, 143u, 134u,
- 29u, 113u, 198u, 1u,
- 60u, 213u, 148u, 59u,
- 102u, 193u, 81u, 38u,
- 129u, 225u, 109u, 140u,
- 134u, 164u, 143u, 180u,
- 255u, 29u, 151u, 171u,
- 111u, 92u, 121u, 187u,
- 152u, 129u, 98u, 90u,
- 149u, 228u, 230u, 92u,
- 57u, 90u, 105u, 83u,
- 54u, 192u, 156u, 139u,
- 255u, 154u, 139u, 117u,
- 113u, 163u, 159u, 147u,
- 115u, 246u, 229u, 80u,
- 123u, 132u, 40u, 156u,
- 149u, 172u, 169u, 0u,
- 166u, 133u, 209u, 96u,
- 255u, 215u, 174u, 247u,
- 31u, 101u, 80u, 181u,
- 225u, 211u, 151u, 82u,
- 1u, 244u, 121u, 77u,
- 164u, 128u, 232u, 104u,
- 90u, 101u, 236u, 155u,
- 173u, 120u, 63u, 144u,
- 163u, 126u, 1u, 124u,
- 126u, 84u, 178u, 102u,
- 162u, 175u, 185u, 168u,
- 118u, 127u, 105u, 160u,
- 164u, 179u, 168u, 71u,
- 86u, 137u, 95u, 255u,
- 119u, 183u, 165u, 193u,
- 168u, 65u, 162u, 146u,
- 178u, 90u, 133u, 95u,
- 120u, 57u, 173u, 255u,
- 175u, 161u, 156u, 2u,
- 138u, 215u, 120u, 72u,
- 77u, 78u, 156u, 135u,
- 108u, 67u, 28u, 157u,
- 255u, 192u, 79u, 94u,
- 214u, 198u, 56u, 91u,
- 139u, 138u, 206u, 139u,
- 72u, 180u, 209u, 111u,
- 67u, 255u, 97u, 87u,
- 177u, 22u, 109u, 138u,
- 255u, 153u, 139u, 113u,
- 81u, 207u, 74u, 89u,
- 138u, 3u, 123u, 99u,
- 179u, 175u, 68u, 179u,
- 134u, 51u, 31u, 161u,
- 82u, 202u, 255u, 119u,
- 116u, 58u, 119u, 243u,
- 92u, 175u, 100u, 233u,
- 209u, 101u, 176u, 216u,
- 114u, 100u, 140u, 255u,
- 174u, 19u, 169u, 215u,
- 75u, 169u, 115u, 52u,
- 191u, 198u, 123u, 225u,
- 192u, 135u, 133u, 119u,
- 159u, 1u, 135u, 190u,
- 216u, 142u, 133u, 162u,
- 222u, 123u, 115u, 118u,
- 1u, 135u, 134u, 107u,
- 184u, 137u, 177u, 151u,
- 102u, 75u, 124u, 144u,
- 138u, 33u, 46u, 118u,
- 173u, 111u, 174u, 81u,
- 112u, 112u, 53u, 118u,
- 88u, 119u, 107u, 1u,
- 126u, 169u, 1u, 179u,
- 160u, 121u, 175u, 63u,
- 108u, 100u, 115u, 218u,
- 189u, 120u, 98u, 140u,
- 176u, 87u, 156u, 124u,
- 156u, 126u, 78u, 1u,
- 151u, 60u, 76u, 31u,
- 103u, 246u, 164u, 122u,
- 113u, 171u, 96u, 255u,
- 124u, 194u, 190u, 194u,
- 98u, 101u, 36u, 94u,
- 179u, 222u, 103u, 122u,
- 172u, 165u, 73u, 65u,
- 136u, 109u, 15u, 122u,
- 137u, 60u, 218u, 142u,
- 124u, 255u, 84u, 130u,
- 102u, 121u, 164u, 1u,
- 125u, 65u, 193u, 134u,
- 15u, 124u, 112u, 223u,
- 112u, 82u, 72u, 156u,
- 116u, 130u, 255u, 103u,
- 98u, 103u, 121u, 129u,
- 133u, 144u, 149u, 167u,
- 115u, 177u, 74u, 155u,
- 109u, 98u, 85u, 173u,
- 122u, 162u, 131u, 95u,
- 41u, 172u, 181u, 135u,
- 255u, 50u, 130u, 79u,
- 114u, 51u, 235u, 141u,
- 1u, 187u, 172u, 114u,
- 70u, 50u, 163u, 206u,
- 225u, 193u, 48u, 188u,
- 227u, 86u, 148u, 181u,
- 47u, 88u, 126u, 65u,
- 177u, 89u, 32u, 70u,
- 161u, 1u, 141u, 120u,
- 96u, 83u, 140u, 1u,
- 193u, 125u, 189u, 148u,
- 149u, 105u, 55u, 237u,
- 70u, 92u, 124u, 161u,
- 1u, 52u, 120u, 94u,
- 245u, 104u, 153u, 180u,
- 83u, 156u, 40u, 96u,
- 117u, 60u, 110u, 76u,
- 87u, 103u, 142u, 192u,
- 102u, 160u, 153u, 133u,
- 124u, 123u, 131u, 162u,
- 255u, 81u, 151u, 125u,
- 149u, 51u, 71u, 255u,
- 103u, 38u, 70u, 88u,
- 152u, 105u, 111u, 94u,
- 91u, 38u, 49u, 106u,
- 94u, 98u, 139u, 132u,
- 255u, 42u, 87u, 124u,
- 148u, 171u, 161u, 100u,
- 75u, 89u, 177u, 124u,
- 99u, 0u, 105u, 116u,
- 101u, 115u, 231u, 105u,
- 83u, 150u, 108u, 191u,
- 184u, 159u, 152u, 179u,
- 170u, 99u, 52u, 255u,
- 66u, 166u, 166u, 126u,
- 129u, 92u, 59u, 131u,
- 254u, 216u, 255u, 90u,
- 114u, 58u, 189u, 113u,
- 197u, 74u, 138u, 158u,
- 139u, 69u, 103u, 255u,
- 207u, 72u, 174u, 91u,
- 140u, 131u, 85u, 44u,
- 128u, 134u, 144u, 1u,
- 18u, 145u, 160u, 218u,
- 195u, 145u, 206u, 87u,
- 111u, 81u, 26u, 79u,
- 120u, 76u, 137u, 94u,
- 117u, 251u, 167u, 176u,
- 101u, 108u, 255u, 233u,
- 183u, 134u, 196u, 191u,
- 97u, 135u, 43u, 161u,
- 123u, 91u, 81u, 132u,
- 18u, 1u, 75u, 73u,
- 105u, 86u, 194u, 135u,
- 160u, 166u, 54u, 138u,
- 98u, 224u, 81u, 0u,
- 136u, 143u, 9u, 245u,
- 225u, 162u, 137u, 164u,
- 137u, 1u, 106u, 5u,
- 233u, 53u, 160u, 78u,
- 94u, 42u, 128u, 212u,
- 134u, 35u, 101u, 213u,
- 134u, 126u, 255u, 35u,
- 118u, 48u, 79u, 128u,
- 156u, 194u, 188u, 138u,
- 153u, 112u, 152u, 166u,
- 168u, 111u, 64u, 95u,
- 85u, 116u, 58u, 133u,
- 255u, 74u, 154u, 145u,
- 83u, 156u, 43u, 183u,
- 182u, 1u, 157u, 147u,
- 110u, 139u, 111u, 157u,
- 101u, 149u, 65u, 131u,
- 199u, 219u, 18u, 171u,
- 202u, 84u, 135u, 101u,
- 175u, 137u, 43u, 1u,
- 49u, 65u, 64u, 97u,
- 255u, 136u, 82u, 74u,
- 66u, 121u, 64u, 158u,
- 94u, 135u, 130u, 203u,
- 131u, 182u, 96u, 111u,
- 232u, 158u, 67u, 159u,
- 108u, 143u, 185u, 146u,
- 126u, 12u, 159u, 191u,
- 239u, 255u, 232u, 162u,
- 117u, 141u, 131u, 119u,
- 174u, 81u, 106u, 132u,
- 49u, 155u, 161u, 125u,
- 255u, 18u, 156u, 81u,
- 88u, 106u, 145u, 255u,
- 196u, 155u, 215u, 116u,
- 233u, 151u, 129u, 190u,
- 183u, 94u, 85u, 98u,
- 88u, 131u, 175u, 144u,
- 255u, 147u, 92u, 154u,
- 154u, 97u, 82u, 128u,
- 164u, 87u, 165u, 140u,
- 155u, 78u, 61u, 255u,
- 6u, 80u, 35u, 34u,
- 223u, 43u, 74u, 121u,
- 125u, 160u, 115u, 217u,
- 87u, 85u, 219u, 11u,
- 200u, 126u, 71u, 219u,
- 171u, 255u, 83u, 127u,
- 108u, 74u, 91u, 123u,
- 106u, 116u, 189u, 121u,
- 13u, 150u, 136u, 71u,
- 67u, 169u, 180u, 32u,
- 255u, 52u, 103u, 157u,
- 162u, 154u, 255u, 218u,
- 30u, 247u, 68u, 127u,
- 37u, 130u, 70u, 161u,
- 153u, 166u, 139u, 207u,
- 106u, 250u, 99u, 145u,
- 177u, 143u, 0u, 96u,
- 63u, 75u, 212u, 128u,
- 123u, 208u, 177u, 126u,
- 255u, 110u, 147u, 244u,
- 246u, 180u, 102u, 203u,
- 158u, 128u, 109u, 178u,
- 150u, 134u, 66u, 26u,
- 255u, 112u, 67u, 142u,
- 88u, 113u, 147u, 130u,
- 231u, 61u, 142u, 8u,
- 48u, 20u, 79u, 113u,
- 73u, 172u, 69u, 157u,
- 88u, 75u, 1u, 35u,
- 149u, 133u, 187u, 72u,
- 43u, 153u, 82u, 101u,
- 182u, 113u, 174u, 58u,
- 249u, 92u, 43u, 86u,
- 124u, 126u, 93u, 74u,
- 91u, 255u, 217u, 184u,
- 153u, 190u, 37u, 228u,
- 84u, 186u, 97u, 87u,
- 130u, 255u, 146u, 120u,
- 189u, 32u, 131u, 49u,
- 94u, 157u, 79u, 44u,
- 70u, 255u, 89u, 191u,
- 122u, 49u, 192u, 133u,
- 3u, 116u, 35u, 208u,
- 210u, 0u, 170u, 220u,
- 48u, 98u, 161u, 55u,
- 59u, 102u, 86u, 83u,
- 105u, 48u, 139u, 109u,
- 109u, 130u, 140u, 142u,
- 36u, 118u, 255u, 120u,
- 123u, 188u, 129u, 182u,
- 136u, 93u, 120u, 101u,
- 173u, 39u, 209u, 190u,
- 174u, 129u, 164u, 13u,
- 123u, 84u, 118u, 153u,
- 140u, 255u, 169u, 152u,
- 63u, 152u, 194u, 1u,
- 139u, 108u, 120u, 167u,
- 102u, 122u, 112u, 86u,
- 90u, 141u, 151u, 178u,
- 169u, 11u, 149u, 164u,
- 193u, 154u, 114u, 208u,
- 194u, 166u, 64u, 119u,
- 255u, 74u, 76u, 146u,
- 122u, 130u, 168u, 129u,
- 85u, 71u, 0u, 118u,
- 29u, 213u, 205u, 159u,
- 32u, 157u, 30u, 63u,
- 127u, 108u, 134u, 98u,
- 144u, 199u, 255u, 135u,
- 153u, 147u, 50u, 144u,
- 121u, 164u, 119u, 68u,
- 117u, 160u, 0u, 133u,
- 152u, 106u, 95u, 132u,
- 193u, 87u, 153u, 128u,
- 74u, 130u, 159u, 206u,
- 1u, 161u, 208u, 218u,
- 58u, 151u, 157u, 195u,
- 145u, 149u, 163u, 138u,
- 154u, 11u, 250u, 215u,
- 188u, 46u, 244u, 34u,
- 158u, 192u, 1u, 95u,
- 79u, 125u, 151u, 183u,
- 99u, 170u, 176u, 200u,
- 229u, 218u, 225u, 1u,
- 90u, 180u, 24u, 42u,
- 80u, 123u, 207u, 44u,
- 180u, 127u, 40u, 196u,
- 77u, 255u, 11u, 233u,
- 95u, 66u, 162u, 174u,
- 124u, 137u, 137u, 210u,
- 220u, 122u, 232u, 12u,
- 142u, 146u, 139u, 91u,
- 147u, 149u, 116u, 145u,
- 93u, 192u, 115u, 127u,
- 81u, 85u, 129u, 255u,
- 107u, 87u, 79u, 112u,
- 204u, 27u, 113u, 168u,
- 124u, 255u, 134u, 189u,
- 187u, 45u, 116u, 92u,
- 48u, 96u, 0u, 48u,
- 212u, 88u, 102u, 148u,
- 162u, 210u, 146u, 206u,
- 90u, 176u, 140u, 61u,
- 188u, 143u, 194u, 130u,
- 68u, 106u, 189u, 138u,
- 255u, 128u, 123u, 179u,
- 172u, 136u, 142u, 152u,
- 194u, 13u, 107u, 255u,
- 135u, 42u, 202u, 114u,
- 67u, 213u, 107u, 111u,
- 145u, 131u, 104u, 26u,
- 252u, 142u, 107u, 111u,
- 52u, 57u, 60u, 186u,
- 116u, 158u, 159u, 43u,
- 95u, 244u, 0u, 212u,
- 98u, 139u, 96u, 49u,
- 52u, 168u, 97u, 94u,
- 40u, 245u, 255u, 10u,
- 236u, 114u, 163u, 167u,
- 1u, 123u, 254u, 19u,
- 243u, 46u, 52u, 137u,
- 53u, 87u, 148u, 147u,
- 37u, 54u, 221u, 74u,
- 66u, 65u, 88u, 70u,
- 130u, 112u, 220u, 135u,
- 129u, 155u, 90u, 138u,
- 176u, 1u, 211u, 107u,
- 87u, 207u, 131u, 45u,
- 104u, 144u, 96u, 73u,
- 1u, 102u, 87u, 130u,
- 73u, 139u, 124u, 216u,
- 98u, 150u, 98u, 118u,
- 150u, 205u, 58u, 147u,
- 184u, 145u, 134u, 89u,
- 255u, 70u, 113u, 124u,
- 134u, 189u, 160u, 17u,
- 222u, 128u, 152u, 0u,
- 182u, 223u, 248u, 125u,
- 122u, 183u, 131u, 201u,
- 158u, 168u, 61u, 103u,
- 148u, 190u, 1u, 218u,
- 97u, 12u, 208u, 109u,
- 236u, 186u, 44u, 202u,
- 157u, 102u, 97u, 177u,
- 173u, 181u, 54u, 89u,
- 77u, 66u, 1u, 111u,
- 167u, 139u, 91u, 66u,
- 165u, 123u, 219u, 146u,
- 103u, 109u, 217u, 1u,
- 146u, 141u, 166u, 184u,
- 112u, 157u, 101u, 163u,
- 194u, 111u, 218u, 159u,
- 212u, 121u, 152u, 100u,
- 76u, 119u, 1u, 115u,
- 175u, 147u, 150u, 25u,
- 143u, 109u, 158u, 164u,
- 253u, 141u, 158u, 122u,
- 187u, 172u, 128u, 119u,
- 255u, 208u, 109u, 101u,
- 113u, 102u, 83u, 82u,
- 57u, 143u, 140u, 151u,
- 103u, 136u, 171u, 135u,
- 127u, 112u, 85u, 255u,
- 67u, 96u, 133u, 82u,
- 163u, 129u, 152u, 131u,
- 62u, 171u, 91u, 255u,
- 37u, 35u, 112u, 231u,
- 98u, 153u, 146u, 27u,
- 16u, 10u, 198u, 108u,
- 43u, 116u, 54u, 94u,
- 255u, 13u, 81u, 75u,
- 151u, 123u, 117u, 103u,
- 177u, 186u, 121u, 224u,
- 136u, 140u, 123u, 132u,
- 118u, 170u, 1u, 56u,
- 93u, 200u, 62u, 93u,
- 188u, 123u, 255u, 135u,
- 174u, 102u, 146u, 98u,
- 230u, 202u, 222u, 76u,
- 181u, 169u, 120u, 92u,
- 105u, 138u, 120u, 66u,
- 132u, 255u, 69u, 231u,
- 120u, 101u, 129u, 235u,
- 164u, 200u, 13u, 236u,
- 208u, 82u, 62u, 71u,
- 59u, 22u, 87u, 168u,
- 196u, 98u, 137u, 255u,
- 77u, 128u, 104u, 84u,
- 82u, 157u, 167u, 187u,
- 58u, 255u, 128u, 78u,
- 107u, 98u, 48u, 132u,
- 105u, 88u, 157u, 152u,
- 197u, 213u, 1u, 81u,
- 83u, 201u, 54u, 66u,
- 235u, 115u, 215u, 99u,
- 255u, 21u, 55u, 199u,
- 241u, 37u, 201u, 59u,
- 77u, 122u, 27u, 154u,
- 159u, 155u, 244u, 140u,
- 201u, 194u, 127u, 58u,
- 52u, 156u, 8u, 21u,
- 136u, 1u, 219u, 12u,
- 107u, 118u, 21u, 193u,
- 47u, 255u, 163u, 200u,
- 137u, 124u, 129u, 138u,
- 234u, 49u, 90u, 87u,
- 179u, 130u, 121u, 20u,
- 137u, 178u, 148u, 87u,
- 105u, 220u, 165u, 195u,
- 168u, 198u, 255u, 199u,
- 211u, 186u, 101u, 134u,
- 147u, 79u, 217u, 1u,
- 105u, 207u, 205u, 92u,
- 142u, 62u, 213u, 124u,
- 137u, 73u, 80u, 120u,
- 255u, 140u, 91u, 166u,
- 160u, 51u, 168u, 57u,
- 154u, 126u, 177u, 220u,
- 113u, 166u, 138u, 6u,
- 132u, 47u, 68u, 181u,
- 52u, 79u, 196u, 1u,
- 154u, 120u, 163u, 190u,
- 164u, 106u, 114u, 220u,
- 157u, 1u, 211u, 28u,
- 5u, 91u, 207u, 87u,
- 172u, 107u, 230u, 165u,
- 86u, 119u, 28u, 222u,
- 132u, 132u, 144u, 255u,
- 148u, 150u, 83u, 111u,
- 206u, 29u, 126u, 58u,
- 135u, 177u, 135u, 151u,
- 0u, 98u, 187u, 54u,
- 179u, 149u, 20u, 190u,
- 70u, 160u, 109u, 96u,
- 44u, 86u, 94u, 205u,
- 97u, 160u, 117u, 147u,
- 162u, 217u, 148u, 72u,
- 82u, 227u, 212u, 107u,
- 147u, 206u, 255u, 136u,
- 58u, 131u, 1u, 86u,
- 174u, 167u, 103u, 141u,
- 117u, 5u, 84u, 146u,
- 17u, 111u, 41u, 138u,
- 197u, 141u, 152u, 183u,
- 196u, 1u, 117u, 40u,
- 171u, 108u, 153u, 144u,
- 181u, 130u, 202u, 37u,
- 141u, 109u, 73u, 129u,
- 85u, 101u, 255u, 235u,
- 255u, 122u, 188u, 217u,
- 37u, 156u, 114u, 108u,
- 128u, 123u, 187u, 163u,
- 164u, 104u, 40u, 70u,
- 90u, 147u, 237u, 104u,
- 83u, 25u, 255u, 247u,
- 138u, 97u, 112u, 176u,
- 147u, 193u, 1u, 44u,
- 195u, 195u, 126u, 248u,
- 225u, 113u, 133u, 71u,
- 1u, 98u, 92u, 44u,
- 207u, 168u, 146u, 174u,
- 40u, 181u, 146u, 205u,
- 137u, 95u, 137u, 160u,
- 197u, 84u, 46u, 45u,
- 194u, 102u, 122u, 37u,
- 78u, 54u, 211u, 255u,
- 130u, 96u, 170u, 92u,
- 67u, 0u, 102u, 110u,
- 120u, 133u, 170u, 155u,
- 104u, 188u, 136u, 158u,
- 150u, 145u, 185u, 137u,
- 108u, 155u, 1u, 171u,
- 25u, 127u, 114u, 66u,
- 189u, 104u, 60u, 148u,
- 100u, 204u, 111u, 139u,
- 86u, 8u, 181u, 89u,
- 146u, 189u, 127u, 95u,
- 0u, 176u, 110u, 138u,
- 99u, 240u, 49u, 101u,
- 56u, 223u, 110u, 200u,
- 66u, 85u, 136u, 94u,
- 191u, 108u, 225u, 171u,
- 255u, 211u, 5u, 109u,
- 141u, 160u, 103u, 40u,
- 185u, 70u, 99u, 255u,
- 81u, 105u, 161u, 108u,
- 81u, 215u, 53u, 117u,
- 96u, 132u, 177u, 215u,
- 135u, 255u, 87u, 110u,
- 110u, 43u, 153u, 196u,
- 132u, 211u, 101u, 185u,
- 144u, 198u, 58u, 106u,
- 150u, 151u, 160u, 16u,
- 152u, 193u, 0u, 95u,
- 215u, 130u, 35u, 93u,
- 255u, 46u, 171u, 178u,
- 143u, 53u, 70u, 112u,
- 128u, 96u, 166u, 203u,
- 67u, 213u, 194u, 150u,
- 1u, 174u, 13u, 150u,
- 134u, 124u, 196u, 129u,
- 228u, 27u, 87u, 224u,
- 24u, 79u, 172u, 170u,
- 235u, 241u, 78u, 1u,
- 180u, 36u, 1u, 173u,
- 64u, 97u, 225u, 220u,
- 153u, 158u, 110u, 104u,
- 133u, 122u, 96u, 114u,
- 208u, 109u, 164u, 187u,
- 210u, 67u, 81u, 111u,
- 74u, 125u, 34u, 255u,
- 80u, 90u, 30u, 105u,
- 77u, 61u, 255u, 191u,
- 90u, 239u, 120u, 196u,
- 171u, 135u, 81u, 120u,
- 100u, 153u, 139u, 113u,
- 141u, 123u, 107u, 112u,
- 137u, 79u, 143u, 128u,
- 157u, 255u, 97u, 76u,
- 116u, 98u, 141u, 107u,
- 108u, 1u, 117u, 136u,
- 65u, 144u, 191u, 154u,
- 92u, 30u, 142u, 135u,
- 255u, 153u, 196u, 21u,
- 43u, 139u, 114u, 91u,
- 214u, 195u, 182u, 67u,
- 82u, 141u, 133u, 81u,
- 251u, 155u, 245u, 206u,
- 188u, 110u, 1u, 185u,
- 127u, 112u, 102u, 149u,
- 184u, 122u, 168u, 187u,
- 162u, 1u, 195u, 138u,
- 102u, 8u, 90u, 178u,
- 155u, 193u, 144u, 35u,
- 139u, 93u, 38u, 15u,
- 176u, 177u, 121u, 104u,
- 157u, 165u, 183u, 174u,
- 186u, 114u, 114u, 255u,
- 105u, 48u, 143u, 179u,
- 111u, 186u, 24u, 160u,
- 1u, 70u, 132u, 108u,
- 115u, 242u, 194u, 118u,
- 121u, 76u, 64u, 50u,
- 166u, 181u, 117u, 208u,
- 35u, 128u, 132u, 91u,
- 92u, 255u, 142u, 125u,
- 230u, 25u, 77u, 74u,
- 59u, 119u, 101u, 1u,
- 93u, 88u, 111u, 163u,
- 164u, 235u, 138u, 112u,
- 68u, 109u, 184u, 227u,
- 90u, 110u, 211u, 186u,
- 141u, 200u, 29u, 96u,
- 85u, 4u, 1u, 3u,
- 162u, 138u, 194u, 160u,
- 140u, 22u, 120u, 206u,
- 34u, 176u, 57u, 174u,
- 98u, 1u, 47u, 99u,
- 97u, 188u, 97u, 118u,
- 82u, 241u, 163u, 104u,
- 123u, 210u, 255u, 160u,
- 196u, 103u, 176u, 223u,
- 111u, 75u, 26u, 159u,
- 15u, 84u, 108u, 146u,
- 140u, 33u, 52u, 74u,
- 178u, 201u, 100u, 76u,
- 0u, 125u, 123u, 208u,
- 74u, 213u, 54u, 19u,
- 80u, 255u, 146u, 55u,
- 182u, 138u, 186u, 133u,
- 106u, 191u, 241u, 225u,
- 104u, 147u, 150u, 182u,
- 11u, 143u, 1u, 200u,
- 4u, 198u, 160u, 157u,
- 142u, 88u, 135u, 215u,
- 13u, 131u, 116u, 229u,
- 106u, 151u, 112u, 255u,
- 118u, 132u, 190u, 152u,
- 192u, 28u, 87u, 75u,
- 5u, 109u, 86u, 212u,
- 17u, 19u, 72u, 86u,
- 1u, 246u, 206u, 147u,
- 46u, 106u, 87u, 124u,
- 190u, 41u, 10u, 237u,
- 1u, 70u, 12u, 126u,
- 141u, 149u, 191u, 202u,
- 92u, 124u, 81u, 186u,
- 45u, 124u, 229u, 138u,
- 141u, 148u, 217u, 76u,
- 32u, 83u, 19u, 179u,
- 71u, 149u, 72u, 255u,
- 222u, 33u, 130u, 212u,
- 53u, 109u, 163u, 233u,
- 108u, 22u, 179u, 123u,
- 167u, 1u, 149u, 94u,
- 148u, 168u, 63u, 145u,
- 156u, 57u, 160u, 122u,
- 100u, 80u, 176u, 213u,
- 143u, 255u, 191u, 87u,
- 127u, 66u, 125u, 187u,
- 17u, 105u, 26u, 104u,
- 109u, 48u, 166u, 51u,
- 12u, 89u, 30u, 255u,
- 20u, 165u, 36u, 182u,
- 170u, 90u, 132u, 89u,
- 105u, 126u, 1u, 124u,
- 76u, 73u, 188u, 227u,
- 208u, 140u, 129u, 185u,
- 24u, 169u, 105u, 156u,
- 89u, 75u, 189u, 235u,
- 136u, 1u, 54u, 183u,
- 183u, 123u, 178u, 209u,
- 82u, 154u, 255u, 90u,
- 144u, 175u, 32u, 133u,
- 125u, 115u, 125u, 138u,
- 105u, 144u, 94u, 130u,
- 255u, 65u, 89u, 40u,
- 102u, 20u, 179u, 194u,
- 178u, 160u, 195u, 207u,
- 80u, 223u, 103u, 60u,
- 237u, 180u, 179u, 192u,
- 43u, 128u, 160u, 255u,
- 174u, 167u, 180u, 207u,
- 168u, 111u, 159u, 124u,
- 99u, 255u, 84u, 137u,
- 239u, 104u, 138u, 108u,
- 147u, 66u, 69u, 71u,
- 172u, 23u, 197u, 41u,
- 255u, 180u, 111u, 222u,
- 181u, 128u, 84u, 164u,
- 53u, 252u, 17u, 140u,
- 152u, 144u, 205u, 166u,
- 113u, 139u, 149u, 153u,
- 113u, 163u, 142u, 181u,
- 144u, 1u, 161u, 165u,
- 235u, 22u, 211u, 111u,
- 220u, 152u, 60u, 209u,
- 171u, 255u, 110u, 140u,
- 69u, 204u, 158u, 160u,
- 118u, 7u, 76u, 110u,
- 171u, 155u, 191u, 76u,
- 81u, 85u, 110u, 192u,
- 127u, 215u, 1u, 170u,
- 6u, 106u, 126u, 155u,
- 40u, 10u, 191u, 98u,
- 50u, 230u, 124u, 84u,
- 125u, 92u, 255u, 145u,
- 1u, 124u, 132u, 122u,
- 203u, 207u, 14u, 78u,
- 86u, 227u, 94u, 84u,
- 157u, 56u, 36u, 28u,
- 1u, 199u, 87u, 132u,
- 114u, 179u, 190u, 187u,
- 94u, 118u, 105u, 177u,
- 83u, 201u, 210u, 207u,
- 140u, 100u, 40u, 61u,
- 0u, 47u, 221u, 157u,
- 128u, 135u, 168u, 132u,
- 127u, 78u, 152u, 154u,
- 120u, 120u, 41u, 216u,
- 5u, 93u, 76u, 242u,
- 255u, 64u, 218u, 64u,
- 49u, 44u, 56u, 186u,
- 140u, 107u, 115u, 90u,
- 48u, 143u, 83u, 205u,
- 158u, 96u, 255u, 83u,
- 136u, 118u, 134u, 153u,
- 165u, 163u, 172u, 79u,
- 14u, 255u, 151u, 160u,
- 88u, 86u, 123u, 154u,
- 175u, 155u, 56u, 140u,
- 122u, 180u, 255u, 113u,
- 176u, 184u, 191u, 46u,
- 216u, 103u, 60u, 183u,
- 162u, 192u, 60u, 76u,
- 60u, 113u, 114u, 68u,
- 101u, 155u, 118u, 192u,
- 124u, 110u, 114u, 124u,
- 1u, 129u, 70u, 110u,
- 183u, 143u, 97u, 167u,
- 84u, 177u, 180u, 255u,
- 140u, 78u, 98u, 124u,
- 97u, 243u, 193u, 115u,
- 12u, 29u, 65u, 160u,
- 176u, 217u, 153u, 129u,
- 67u, 113u, 74u, 1u,
- 59u, 136u, 123u, 244u,
- 98u, 120u, 61u, 181u,
- 180u, 21u, 88u, 137u,
- 1u, 156u, 191u, 109u,
- 127u, 136u, 74u, 94u,
- 129u, 105u, 183u, 1u,
- 149u, 40u, 89u, 47u,
- 82u, 36u, 254u, 86u,
- 133u, 164u, 143u, 164u,
- 158u, 172u, 136u, 69u,
- 255u, 176u, 157u, 162u,
- 152u, 71u, 121u, 149u,
- 123u, 240u, 151u, 154u,
- 188u, 105u, 102u, 179u,
- 145u, 57u, 122u, 201u,
- 255u, 65u, 114u, 86u,
- 182u, 112u, 74u, 69u,
- 63u, 206u, 55u, 0u,
- 151u, 70u, 187u, 179u,
- 231u, 164u, 84u, 176u,
- 184u, 114u, 108u, 81u,
- 48u, 76u, 87u, 128u,
- 126u, 165u, 28u, 131u,
- 116u, 238u, 77u, 138u,
- 113u, 61u, 1u, 123u,
- 196u, 117u, 198u, 217u,
- 1u, 160u, 90u, 208u,
- 96u, 144u, 168u, 107u,
- 77u, 121u, 142u, 121u,
- 163u, 110u, 255u, 174u,
- 180u, 86u, 31u, 194u,
- 197u, 174u, 160u, 7u,
- 91u, 45u, 215u, 30u,
- 255u, 156u, 138u, 140u,
- 94u, 121u, 193u, 35u,
- 165u, 37u, 76u, 201u,
- 134u, 143u, 5u, 179u,
- 97u, 125u, 255u, 94u,
- 141u, 237u, 107u, 191u,
- 155u, 136u, 152u, 172u,
- 117u, 60u, 70u, 203u,
- 147u, 78u, 91u, 192u,
- 159u, 175u, 160u, 167u,
- 59u, 1u, 141u, 228u,
- 111u, 177u, 41u, 168u,
- 35u, 106u, 45u, 165u,
- 255u, 100u, 74u, 117u,
- 43u, 46u, 63u, 192u,
- 158u, 150u, 102u, 89u,
- 101u, 126u, 133u, 131u,
- 107u, 101u, 169u, 61u,
- 134u, 255u, 80u, 118u,
- 171u, 94u, 146u, 138u,
- 142u, 83u, 144u, 159u,
- 95u, 89u, 110u, 174u,
- 88u, 73u, 81u, 124u,
- 61u, 255u, 82u, 153u,
- 193u, 46u, 147u, 187u,
- 1u, 164u, 124u, 119u,
- 217u, 116u, 217u, 182u,
- 132u, 193u, 46u, 166u,
- 250u, 37u, 81u, 178u,
- 157u, 148u, 173u, 51u,
- 65u, 185u, 1u, 221u,
- 156u, 139u, 140u, 148u,
- 146u, 151u, 135u, 119u,
- 123u, 171u, 255u, 143u,
- 232u, 159u, 51u, 160u,
- 124u, 59u, 96u, 118u,
- 61u, 169u, 91u, 146u,
- 93u, 194u, 45u, 42u,
- 179u, 0u, 190u, 137u,
- 221u, 116u, 133u, 29u,
- 107u, 149u, 53u, 58u,
- 61u, 95u, 31u, 1u,
- 3u, 184u, 99u, 94u,
- 73u, 46u, 243u, 162u,
- 162u, 73u, 97u, 187u,
- 157u, 125u, 152u, 118u,
- 89u, 255u, 52u, 70u,
- 122u, 237u, 181u, 134u,
- 92u, 146u, 1u, 93u,
- 1u, 19u, 103u, 208u,
- 67u, 125u, 182u, 99u,
- 23u, 234u, 167u, 188u,
- 183u, 159u, 143u, 255u,
- 109u, 55u, 86u, 138u,
- 62u, 202u, 167u, 159u,
- 130u, 36u, 32u, 105u,
- 158u, 99u, 84u, 114u,
- 143u, 80u, 100u, 255u,
- 159u, 130u, 183u, 100u,
- 200u, 121u, 142u, 88u,
- 153u, 148u, 101u, 200u,
- 110u, 98u, 65u, 95u,
- 66u, 1u, 172u, 78u,
- 56u, 95u, 71u, 210u,
- 201u, 159u, 142u, 135u,
- 58u, 151u, 100u, 145u,
- 1u, 91u, 178u, 84u,
- 169u, 157u, 104u, 169u,
- 42u, 156u, 144u, 113u,
- 214u, 217u, 198u, 169u,
- 148u, 126u, 138u, 195u,
- 50u, 255u, 192u, 168u,
- 129u, 99u, 128u, 123u,
- 93u, 95u, 1u, 158u,
- 134u, 110u, 252u, 81u,
- 113u, 45u, 104u, 123u,
- 77u, 94u, 78u, 97u,
- 111u, 146u, 114u, 82u,
- 150u, 151u, 42u, 91u,
- 91u, 53u, 35u, 255u,
- 166u, 0u, 97u, 123u,
- 35u, 135u, 192u, 71u,
- 112u, 168u, 167u, 126u,
- 56u, 92u, 132u, 108u,
- 128u, 175u, 82u, 34u,
- 109u, 1u, 90u, 206u,
- 221u, 240u, 228u, 81u,
- 78u, 129u, 91u, 140u,
- 208u, 183u, 17u, 154u,
- 96u, 250u, 96u, 115u,
- 1u, 112u, 39u, 165u,
- 142u, 134u, 48u, 218u,
- 63u, 255u, 190u, 214u,
- 94u, 146u, 125u, 132u,
- 145u, 92u, 132u, 66u,
- 189u, 113u, 252u, 210u,
- 175u, 76u, 106u, 63u,
- 127u, 20u, 1u, 144u,
- 238u, 159u, 120u, 110u,
- 119u, 141u, 96u, 98u,
- 110u, 156u, 242u, 120u,
- 131u, 151u, 209u, 135u,
- 89u, 185u, 84u, 255u,
- 137u, 229u, 137u, 126u,
- 124u, 169u, 175u, 1u,
- 102u, 6u, 169u, 64u,
- 70u, 153u, 214u, 112u,
- 193u, 109u, 120u, 104u,
- 125u, 93u, 197u, 186u,
- 1u, 149u, 187u, 209u,
- 178u, 164u, 128u, 205u,
- 85u, 55u, 86u, 138u,
- 154u, 172u, 215u, 117u,
- 95u, 110u, 148u, 86u,
- 155u, 33u, 227u, 54u,
- 1u, 47u, 156u, 181u,
- 173u, 1u, 251u, 209u,
- 21u, 116u, 138u, 85u,
- 187u, 156u, 101u, 74u,
- 79u, 7u, 221u, 223u,
- 172u, 1u, 122u, 160u,
- 239u, 200u, 165u, 130u,
- 110u, 84u, 61u, 165u,
- 90u, 217u, 113u, 166u,
- 71u, 161u, 250u, 100u,
- 83u, 186u, 53u, 131u,
- 175u, 98u, 178u, 79u,
- 125u, 42u, 215u, 255u,
- 161u, 148u, 118u, 50u,
- 255u, 128u, 164u, 148u,
- 119u, 127u, 80u, 108u,
- 196u, 148u, 71u, 91u,
- 175u, 68u, 255u, 184u,
- 94u, 136u, 146u, 15u,
- 96u, 177u, 103u, 174u,
- 169u, 72u, 137u, 189u,
- 114u, 190u, 115u, 185u,
- 69u, 49u, 219u, 127u,
- 129u, 56u, 116u, 119u,
- 130u, 123u, 0u, 130u,
- 86u, 178u, 87u, 65u,
- 79u, 149u, 206u, 85u,
- 132u, 169u, 180u, 63u,
- 144u, 131u, 255u, 192u,
- 155u, 69u, 193u, 1u,
- 239u, 42u, 252u, 17u,
- 9u, 156u, 24u, 187u,
- 85u, 188u, 176u, 143u,
- 171u, 136u, 1u, 221u,
- 51u, 104u, 158u, 123u,
- 157u, 128u, 90u, 15u,
- 167u, 148u, 104u, 151u,
- 223u, 138u, 250u, 0u,
- 154u, 143u, 146u, 143u,
- 100u, 86u, 60u, 250u,
- 132u, 226u, 97u, 62u,
- 135u, 103u, 96u, 121u,
- 120u, 217u, 151u, 103u,
- 225u, 86u, 134u, 132u,
- 41u, 152u, 1u, 193u,
- 101u, 87u, 93u, 172u,
- 162u, 168u, 101u, 111u,
- 149u, 97u, 114u, 164u,
- 0u, 70u, 135u, 198u,
- 106u, 193u, 98u, 198u,
- 77u, 153u, 85u, 164u,
- 168u, 1u, 145u, 100u,
- 109u, 119u, 177u, 76u,
- 63u, 61u, 106u, 109u,
- 128u, 128u, 89u, 84u,
- 51u, 156u, 64u, 113u,
- 149u, 0u, 227u, 112u,
- 63u, 33u, 86u, 228u,
- 58u, 17u, 80u, 121u,
- 173u, 178u, 221u, 188u,
- 1u, 131u, 43u, 210u,
- 100u, 60u, 148u, 91u,
- 191u, 171u, 114u, 142u,
- 0u, 153u, 195u, 254u,
- 211u, 121u, 240u, 113u,
- 131u, 109u, 159u, 132u,
- 165u, 199u, 175u, 122u,
- 83u, 54u, 142u, 255u,
- 137u, 177u, 153u, 180u,
- 158u, 161u, 43u, 53u,
- 88u, 94u, 169u, 181u,
- 102u, 140u, 255u, 147u,
- 174u, 158u, 131u, 91u,
- 150u, 205u, 212u, 155u,
- 75u, 123u, 98u, 147u,
- 4u, 190u, 129u, 211u,
- 182u, 197u, 149u, 255u,
- 212u, 97u, 255u, 189u,
- 155u, 124u, 208u, 127u,
- 149u, 132u, 62u, 135u,
- 155u, 181u, 66u, 81u,
- 111u, 255u, 133u, 58u,
- 79u, 194u, 166u, 189u,
- 150u, 103u, 116u, 44u,
- 181u, 246u, 152u, 159u,
- 167u, 122u, 116u, 171u,
- 117u, 141u, 150u, 59u,
- 129u, 97u, 143u, 155u,
- 76u, 255u, 160u, 99u,
- 60u, 157u, 255u, 126u,
- 181u, 123u, 148u, 161u,
- 167u, 112u, 143u, 146u,
- 81u, 135u, 178u, 137u,
- 63u, 178u, 164u, 0u,
- 139u, 43u, 45u, 111u,
- 55u, 234u, 49u, 78u,
- 84u, 30u, 155u, 127u,
- 145u, 150u, 133u, 160u,
- 166u, 107u, 154u, 118u,
- 115u, 122u, 128u, 162u,
- 164u, 182u, 76u, 0u,
- 228u, 99u, 255u, 8u,
- 135u, 159u, 119u, 143u,
- 207u, 135u, 124u, 134u,
- 33u, 203u, 43u, 187u,
- 202u, 83u, 1u, 157u,
- 124u, 126u, 110u, 143u,
- 153u, 174u, 136u, 118u,
- 122u, 142u, 159u, 73u,
- 170u, 82u, 107u, 49u,
- 85u, 136u, 117u, 91u,
- 189u, 255u, 66u, 140u,
- 136u, 85u, 111u, 62u,
- 126u, 236u, 71u, 91u,
- 135u, 161u, 154u, 1u,
- 95u, 92u, 1u, 13u,
- 154u, 192u, 123u, 148u,
- 105u, 64u, 152u, 98u,
- 0u, 83u, 66u, 131u,
- 64u, 179u, 155u, 124u,
- 102u, 82u, 109u, 142u,
- 125u, 177u, 146u, 126u,
- 217u, 63u, 1u, 163u,
- 158u, 158u, 206u, 161u,
- 225u, 122u, 67u, 85u,
- 1u, 89u, 119u, 99u,
- 94u, 143u, 140u, 198u,
- 174u, 93u, 159u, 132u,
- 117u, 176u, 178u, 168u,
- 217u, 175u, 124u, 168u,
- 39u, 1u, 136u, 115u,
- 99u, 149u, 113u, 106u,
- 64u, 231u, 188u, 196u,
- 207u, 180u, 132u, 91u,
- 138u, 126u, 120u, 124u,
- 83u, 130u, 181u, 189u,
- 71u, 151u, 1u, 89u,
- 125u, 150u, 86u, 70u,
- 78u, 139u, 131u, 135u,
- 80u, 31u, 62u, 1u,
- 100u, 196u, 142u, 134u,
- 142u, 110u, 134u, 144u,
- 105u, 156u, 190u, 139u,
- 255u, 146u, 102u, 159u,
- 141u, 128u, 164u, 102u,
- 235u, 154u, 143u, 4u,
- 58u, 125u, 77u, 255u,
- 209u, 77u, 17u, 177u,
- 185u, 143u, 120u, 178u,
- 189u, 41u, 135u, 110u,
- 210u, 120u, 146u, 219u,
- 45u, 143u, 1u, 182u,
- 197u, 119u, 154u, 122u,
- 155u, 136u, 137u, 1u,
- 127u, 97u, 109u, 140u,
- 135u, 138u, 155u, 190u,
- 103u, 166u, 108u, 182u,
- 87u, 142u, 37u, 169u,
- 40u, 166u, 185u, 110u,
- 175u, 0u, 190u, 149u,
- 136u, 203u, 114u, 75u,
- 93u, 140u, 112u, 68u,
- 112u, 140u, 87u, 212u,
- 19u, 123u, 160u, 174u,
- 123u, 168u, 167u, 255u,
- 66u, 93u, 86u, 255u,
- 138u, 95u, 165u, 125u,
- 127u, 205u, 98u, 107u,
- 107u, 98u, 139u, 176u,
- 155u, 146u, 127u, 97u,
- 209u, 99u, 255u, 129u,
- 179u, 147u, 123u, 169u,
- 209u, 125u, 135u, 91u,
- 70u, 169u, 75u, 157u,
- 64u, 116u, 1u, 66u,
- 81u, 133u, 129u, 75u,
- 127u, 151u, 219u, 205u,
- 115u, 111u, 140u, 158u,
- 108u, 192u, 190u, 202u,
- 167u, 50u, 115u, 70u,
- 218u, 34u, 1u, 144u,
- 52u, 144u, 96u, 255u,
- 202u, 187u, 108u, 153u,
- 136u, 183u, 99u, 163u,
- 212u, 34u, 122u, 229u,
- 246u, 151u, 217u, 53u,
- 236u, 235u, 160u, 113u,
- 1u, 96u, 85u, 169u,
- 213u, 205u, 215u, 114u,
- 60u, 237u, 205u, 147u,
- 0u, 218u, 22u, 218u,
- 81u, 233u, 187u, 11u,
- 163u, 142u, 46u, 13u,
- 139u, 105u, 106u, 186u,
- 77u, 47u, 92u, 87u,
- 255u, 165u, 254u, 165u,
- 74u, 193u, 118u, 65u,
- 191u, 30u, 137u, 146u,
- 111u, 35u, 140u, 57u,
- 110u, 26u, 55u, 179u,
- 1u, 111u, 89u, 196u,
- 75u, 121u, 53u, 162u,
- 151u, 141u, 97u, 153u,
- 127u, 130u, 83u, 193u,
- 170u, 1u, 107u, 156u,
- 172u, 76u, 144u, 145u,
- 1u, 147u, 180u, 180u,
- 140u, 135u, 143u, 120u,
- 92u, 156u, 149u, 159u,
- 228u, 115u, 178u, 61u,
- 255u, 173u, 205u, 184u,
- 143u, 229u, 28u, 178u,
- 180u, 31u, 200u, 171u,
- 131u, 39u, 255u, 81u,
- 151u, 128u, 120u, 80u,
- 171u, 45u, 23u, 152u,
- 132u, 170u, 144u, 126u,
- 202u, 82u, 98u, 0u,
- 194u, 14u, 210u, 186u,
- 166u, 118u, 80u, 217u,
- 79u, 35u, 168u, 101u,
- 178u, 111u, 143u, 133u,
- 193u, 113u, 132u, 128u,
- 103u, 51u, 161u, 122u,
- 116u, 180u, 255u, 26u,
- 116u, 82u, 107u, 146u,
- 175u, 166u, 192u, 176u,
- 168u, 162u, 62u, 80u,
- 182u, 112u, 90u, 1u,
- 166u, 136u, 102u, 115u,
- 255u, 97u, 148u, 136u,
- 111u, 116u, 128u, 165u,
- 154u, 214u, 136u, 125u,
- 142u, 124u, 125u, 74u,
- 122u, 90u, 108u, 255u,
- 166u, 95u, 128u, 114u,
- 160u, 129u, 162u, 115u,
- 46u, 167u, 255u, 178u,
- 41u, 168u, 161u, 118u,
- 17u, 102u, 41u, 106u,
- 125u, 112u, 152u, 130u,
- 86u, 159u, 95u, 0u,
- 97u, 135u, 113u, 211u,
- 39u, 114u, 177u, 145u,
- 209u, 60u, 127u, 168u,
- 181u, 87u, 72u, 133u,
- 141u, 40u, 87u, 42u,
- 7u, 32u, 123u, 165u,
- 146u, 255u, 122u, 149u,
- 172u, 94u, 78u, 150u,
- 227u, 198u, 242u, 175u,
- 255u, 9u, 85u, 163u,
- 83u, 161u, 149u, 41u,
- 67u, 130u, 148u, 98u,
- 118u, 111u, 175u, 107u,
- 67u, 126u, 147u, 197u,
- 255u, 228u, 200u, 127u,
- 108u, 95u, 10u, 101u,
- 160u, 64u, 135u, 112u,
- 255u, 185u, 48u, 104u,
- 170u, 186u, 168u, 199u,
- 149u, 152u, 188u, 136u,
- 61u, 78u, 59u, 189u,
- 17u, 81u, 0u, 37u,
- 114u, 165u, 174u, 149u,
- 97u, 135u, 162u, 17u,
- 200u, 168u, 87u, 46u,
- 130u, 144u, 156u, 17u,
- 255u, 187u, 153u, 163u,
- 56u, 120u, 51u, 122u,
- 72u, 181u, 101u, 162u,
- 182u, 176u, 76u, 35u,
- 61u, 144u, 1u, 32u,
- 237u, 1u, 162u, 100u,
- 196u, 54u, 102u, 105u,
- 161u, 188u, 105u, 107u,
- 167u, 117u, 37u, 118u,
- 103u, 130u, 130u, 100u,
- 67u, 255u, 157u, 177u,
- 201u, 111u, 153u, 165u,
- 90u, 174u, 72u, 165u,
- 60u, 82u, 5u, 68u,
- 94u, 227u, 168u, 228u,
- 0u, 217u, 61u, 138u,
- 250u, 225u, 147u, 192u,
- 93u, 43u, 67u, 255u,
- 82u, 64u, 202u, 191u,
- 99u, 132u, 17u, 99u,
- 0u, 157u, 206u, 111u,
- 125u, 95u, 145u, 89u,
- 119u, 105u, 149u, 130u,
- 255u, 132u, 155u, 165u,
- 144u, 135u, 100u, 122u,
- 112u, 137u, 124u, 88u,
- 39u, 137u, 129u, 205u,
- 144u, 255u, 188u, 102u,
- 14u, 24u, 56u, 196u,
- 255u, 110u, 206u, 95u,
- 161u, 57u, 212u, 98u,
- 186u, 170u, 102u, 111u,
- 132u, 100u, 162u, 6u,
- 104u, 141u, 172u, 100u,
- 129u, 155u, 131u, 159u,
- 128u, 78u, 128u, 148u,
- 97u, 140u, 160u, 255u,
- 62u, 145u, 79u, 179u,
- 27u, 53u, 6u, 140u,
- 88u, 86u, 221u, 65u,
- 184u, 0u, 153u, 112u,
- 0u, 95u, 91u, 190u,
- 89u, 125u, 82u, 92u,
- 172u, 131u, 145u, 114u,
- 143u, 245u, 56u, 161u,
- 141u, 181u, 97u, 199u,
- 96u, 98u, 73u, 36u,
- 0u, 133u, 67u, 73u,
- 197u, 223u, 157u, 206u,
- 167u, 99u, 47u, 255u,
- 17u, 67u, 187u, 114u,
- 129u, 126u, 58u, 160u,
- 44u, 68u, 34u, 93u,
- 220u, 0u, 242u, 188u,
- 125u, 132u, 152u, 56u,
- 232u, 232u, 41u, 104u,
- 90u, 144u, 83u, 200u,
- 100u, 191u, 107u, 97u,
- 111u, 190u, 132u, 154u,
- 103u, 111u, 94u, 1u,
- 227u, 107u, 221u, 99u,
- 208u, 145u, 131u, 136u,
- 203u, 201u, 255u, 253u,
- 88u, 132u, 44u, 183u,
- 169u, 153u, 74u, 183u,
- 48u, 102u, 153u, 121u,
- 40u, 174u, 160u, 102u,
- 134u, 189u, 111u, 75u,
- 136u, 115u, 158u, 0u,
- 132u, 104u, 135u, 94u,
- 153u, 174u, 88u, 105u,
- 124u, 175u, 93u, 68u,
- 175u, 255u, 110u, 218u,
- 86u, 85u, 143u, 138u,
- 1u, 129u, 89u, 143u,
- 105u, 175u, 125u, 140u,
- 101u, 142u, 161u, 177u,
- 115u, 143u, 169u, 153u,
- 148u, 34u, 69u, 85u,
- 55u, 204u, 115u, 63u,
- 121u, 1u, 200u, 132u,
- 102u, 152u, 255u, 57u,
- 134u, 202u, 255u, 197u,
- 129u, 170u, 95u, 142u,
- 123u, 105u, 74u, 127u,
- 255u, 150u, 109u, 178u,
- 33u, 152u, 157u, 138u,
- 84u, 148u, 184u, 110u,
- 209u, 160u, 190u, 23u,
- 102u, 93u, 224u, 129u,
- 159u, 158u, 167u, 91u,
- 94u, 130u, 125u, 220u,
- 255u, 136u, 73u, 191u,
- 117u, 78u, 193u, 96u,
- 255u, 244u, 123u, 157u,
- 164u, 99u, 86u, 93u,
- 67u, 141u, 96u, 164u,
- 9u, 106u, 173u, 155u,
- 88u, 74u, 17u, 255u,
- 156u, 65u, 144u, 69u,
- 53u, 169u, 10u, 79u,
- 145u, 121u, 131u, 66u,
- 98u, 44u, 157u, 161u,
- 121u, 239u, 91u, 135u,
- 252u, 1u, 48u, 69u,
- 84u, 160u, 168u, 18u,
- 101u, 89u, 221u, 171u,
- 59u, 160u, 255u, 163u,
- 163u, 72u, 191u, 117u,
- 127u, 122u, 139u, 140u,
- 119u, 255u, 98u, 121u,
- 126u, 93u, 85u, 132u,
- 149u, 144u, 5u, 205u,
- 171u, 128u, 113u, 127u,
- 1u, 177u, 211u, 129u,
- 169u, 159u, 160u, 71u,
- 72u, 123u, 23u, 102u,
- 172u, 255u, 133u, 147u,
- 35u, 10u, 156u, 189u,
- 180u, 118u, 112u, 31u,
- 209u, 156u, 133u, 62u,
- 197u, 188u, 74u, 103u,
- 105u, 101u, 128u, 117u,
- 136u, 0u, 135u, 83u,
- 91u, 151u, 125u, 67u,
- 151u, 88u, 80u, 135u,
- 125u, 199u, 2u, 131u,
- 97u, 170u, 85u, 112u,
- 87u, 188u, 77u, 255u,
- 157u, 206u, 103u, 186u,
- 92u, 255u, 90u, 183u,
- 82u, 177u, 126u, 94u,
- 223u, 59u, 103u, 247u,
- 107u, 83u, 158u, 85u,
- 129u, 141u, 123u, 1u,
- 106u, 114u, 86u, 137u,
- 76u, 216u, 191u, 174u,
- 107u, 97u, 31u, 160u,
- 255u, 159u, 72u, 116u,
- 137u, 57u, 110u, 154u,
- 63u, 160u, 35u, 155u,
- 190u, 231u, 116u, 78u,
- 141u, 104u, 190u, 188u,
- 70u, 217u, 205u, 186u,
- 53u, 1u, 151u, 153u,
- 92u, 147u, 141u, 127u,
- 116u, 113u, 146u, 71u,
- 48u, 255u, 103u, 165u,
- 41u, 25u, 39u, 173u,
- 0u, 112u, 136u, 237u,
- 98u, 225u, 210u, 99u,
- 18u, 18u, 118u, 176u,
- 176u, 160u, 111u, 214u,
- 138u, 221u, 76u, 113u,
- 149u, 142u, 131u, 255u,
- 175u, 216u, 179u, 110u,
- 157u, 35u, 39u, 62u,
- 86u, 12u, 111u, 255u,
- 110u, 135u, 202u, 5u,
- 142u, 174u, 158u, 66u,
- 204u, 212u, 186u, 157u,
- 153u, 123u, 125u, 128u,
- 184u, 146u, 255u, 133u,
- 110u, 155u, 4u, 124u,
- 163u, 189u, 148u, 109u,
- 83u, 174u, 105u, 19u,
- 138u, 177u, 139u, 255u,
- 136u, 185u, 215u, 236u,
- 214u, 205u, 151u, 74u,
- 146u, 136u, 87u, 1u,
- 40u, 150u, 71u, 159u,
- 167u, 161u, 57u, 117u,
- 40u, 89u, 48u, 168u,
- 204u, 92u, 158u, 57u,
- 186u, 144u, 226u, 52u,
- 93u, 245u, 1u, 30u,
- 141u, 81u, 168u, 74u,
- 255u, 109u, 99u, 164u,
- 83u, 157u, 111u, 192u,
- 135u, 181u, 118u, 137u,
- 79u, 80u, 23u, 170u,
- 57u, 157u, 194u, 99u,
- 136u, 135u, 69u, 61u,
- 103u, 131u, 144u, 1u,
- 154u, 141u, 128u, 164u,
- 122u, 228u, 1u, 169u,
- 129u, 58u, 117u, 148u,
- 91u, 85u, 189u, 105u,
- 160u, 227u, 240u, 62u,
- 150u, 94u, 145u, 136u,
- 109u, 1u, 236u, 73u,
- 154u, 207u, 51u, 185u,
- 75u, 29u, 205u, 29u,
- 101u, 71u, 152u, 193u,
- 65u, 190u, 1u, 168u,
- 173u, 35u, 118u, 30u,
- 92u, 136u, 85u, 74u,
- 130u, 73u, 59u, 129u,
- 112u, 53u, 155u, 180u,
- 95u, 159u, 114u, 165u,
- 46u, 147u, 1u, 89u,
- 1u, 123u, 13u, 209u,
- 99u, 210u, 71u, 157u,
- 92u, 122u, 152u, 244u,
- 236u, 179u, 85u, 173u,
- 65u, 187u, 255u, 68u,
- 152u, 122u, 253u, 3u,
- 23u, 247u, 126u, 97u,
- 236u, 86u, 165u, 108u,
- 118u, 90u, 206u, 87u,
- 128u, 102u, 255u, 104u,
- 211u, 208u, 161u, 213u,
- 117u, 104u, 100u, 124u,
- 47u, 223u, 128u, 90u,
- 176u, 153u, 69u, 181u,
- 0u, 128u, 117u, 78u,
- 152u, 87u, 122u, 146u,
- 89u, 189u, 118u, 130u,
- 51u, 167u, 62u, 32u,
- 171u, 146u, 255u, 101u,
- 218u, 108u, 195u, 136u,
- 137u, 197u, 180u, 74u,
- 134u, 179u, 113u, 255u,
- 90u, 140u, 207u, 181u,
- 151u, 152u, 92u, 168u,
- 171u, 118u, 1u, 147u,
- 139u, 142u, 124u, 228u,
- 144u, 129u, 168u, 217u,
- 198u, 110u, 51u, 29u,
- 79u, 236u, 117u, 39u,
- 243u, 154u, 241u, 167u,
- 132u, 89u, 73u, 63u,
- 84u, 255u, 135u, 24u,
- 255u, 153u, 121u, 213u,
- 24u, 129u, 213u, 127u,
- 132u, 77u, 101u, 203u,
- 80u, 148u, 106u, 70u,
- 104u, 213u, 206u, 51u,
- 1u, 138u, 156u, 163u,
- 48u, 194u, 242u, 152u,
- 249u, 49u, 117u, 75u,
- 56u, 163u, 153u, 145u,
- 255u, 183u, 67u, 102u,
- 133u, 137u, 148u, 138u,
- 144u, 55u, 140u, 245u,
- 130u, 144u, 4u, 180u,
- 61u, 103u, 143u, 8u,
- 162u, 195u, 159u, 81u,
- 156u, 1u, 173u, 216u,
- 80u, 122u, 172u, 186u,
- 40u, 167u, 178u, 51u,
- 90u, 234u, 179u, 217u,
- 251u, 133u, 1u, 125u,
- 97u, 9u, 26u, 128u,
- 181u, 247u, 115u, 227u,
- 22u, 40u, 38u, 244u,
- 108u, 112u, 255u, 211u,
- 103u, 96u, 98u, 181u,
- 94u, 152u, 162u, 120u,
- 109u, 142u, 58u, 1u,
- 58u, 78u, 111u, 123u,
- 22u, 1u, 65u, 108u,
- 229u, 89u, 241u, 163u,
- 59u, 106u, 46u, 98u,
- 183u, 159u, 194u, 136u,
- 159u, 52u, 104u, 116u,
- 164u, 100u, 1u, 81u,
- 112u, 143u, 40u, 80u,
- 116u, 116u, 70u, 162u,
- 156u, 49u, 182u, 90u,
- 92u, 156u, 42u, 240u,
- 97u, 85u, 104u, 175u,
- 56u, 1u, 120u, 123u,
- 116u, 165u, 34u, 109u,
- 52u, 11u, 90u, 56u,
- 206u, 255u, 138u, 77u,
- 39u, 240u, 75u, 73u,
- 63u, 32u, 224u, 131u,
- 124u, 250u, 124u, 115u,
- 216u, 201u, 87u, 1u,
- 197u, 220u, 173u, 219u,
- 57u, 138u, 148u, 168u,
- 100u, 112u, 182u, 85u,
- 255u, 232u, 122u, 79u,
- 97u, 1u, 164u, 207u,
- 207u, 61u, 168u, 92u,
- 233u, 219u, 189u, 15u,
- 147u, 68u, 54u, 4u,
- 168u, 255u, 71u, 72u,
- 181u, 70u, 150u, 77u,
- 60u, 192u, 124u, 228u,
- 156u, 190u, 192u, 1u,
- 209u, 92u, 122u, 185u,
- 197u, 101u, 255u, 147u,
- 134u, 81u, 110u, 62u,
- 214u, 52u, 139u, 133u,
- 181u, 104u, 142u, 29u,
- 160u, 202u, 107u, 45u,
- 140u, 41u, 164u, 135u,
- 121u, 161u, 255u, 79u,
- 127u, 130u, 150u, 77u,
- 86u, 75u, 202u, 174u,
- 135u, 27u, 33u, 111u,
- 161u, 119u, 85u, 246u,
- 151u, 42u, 21u, 1u,
- 216u, 120u, 155u, 175u,
- 83u, 179u, 197u, 2u,
- 77u, 113u, 81u, 95u,
- 255u, 228u, 231u, 145u,
- 204u, 127u, 66u, 145u,
- 110u, 43u, 210u, 96u,
- 1u, 124u, 160u, 147u,
- 158u, 41u, 133u, 204u,
- 105u, 33u, 65u, 139u,
- 123u, 154u, 106u, 146u,
- 255u, 131u, 136u, 93u,
- 113u, 155u, 137u, 58u,
- 134u, 146u, 71u, 118u,
- 111u, 130u, 73u, 130u,
- 137u, 78u, 61u, 0u,
- 63u, 110u, 163u, 116u,
- 96u, 118u, 113u, 79u,
- 115u, 95u, 255u, 107u,
- 204u, 70u, 143u, 156u,
- 175u, 195u, 102u, 63u,
- 127u, 110u, 191u, 56u,
- 127u, 112u, 172u, 98u,
- 181u, 123u, 167u, 151u,
- 93u, 100u, 1u, 145u,
- 1u, 148u, 242u, 59u,
- 108u, 101u, 159u, 151u,
- 20u, 140u, 194u, 137u,
- 166u, 223u, 129u, 138u,
- 134u, 96u, 48u, 157u,
- 121u, 161u, 202u, 123u,
- 157u, 106u, 121u, 255u,
- 125u, 218u, 42u, 102u,
- 162u, 0u, 115u, 92u,
- 183u, 100u, 171u, 99u,
- 217u, 178u, 76u, 239u,
- 155u, 189u, 17u, 84u,
- 94u, 140u, 133u, 145u,
- 108u, 110u, 124u, 189u,
- 183u, 255u, 167u, 201u,
- 111u, 54u, 112u, 82u,
- 248u, 111u, 178u, 212u,
- 96u, 209u, 126u, 171u,
- 155u, 86u, 121u, 144u,
- 0u, 145u, 153u, 204u,
- 121u, 152u, 154u, 119u,
- 73u, 23u, 120u, 158u,
- 121u, 153u, 69u, 173u,
- 1u, 107u, 146u, 137u,
- 127u, 158u, 1u, 151u,
- 130u, 107u, 159u, 196u,
- 167u, 79u, 171u, 123u,
- 88u, 165u, 136u, 77u,
- 77u, 95u, 118u, 1u,
- 221u, 103u, 112u, 131u,
- 187u, 92u, 144u, 214u,
- 66u, 151u, 115u, 183u,
- 60u, 141u, 161u, 145u,
- 115u, 210u, 96u, 166u,
- 115u, 77u, 181u, 81u,
- 188u, 187u, 255u, 131u,
- 145u, 48u, 54u, 212u,
- 73u, 163u, 255u, 126u,
- 179u, 149u, 138u, 155u,
- 44u, 59u, 99u, 59u,
- 124u, 120u, 48u, 167u,
- 198u, 163u, 1u, 158u,
- 59u, 143u, 156u, 36u,
- 179u, 129u, 151u, 87u,
- 185u, 64u, 210u, 141u,
- 115u, 152u, 96u, 118u,
- 150u, 184u, 1u, 13u,
- 199u, 185u, 176u, 63u,
- 1u, 50u, 240u, 166u,
- 85u, 113u, 207u, 66u,
- 173u, 108u, 204u, 187u,
- 100u, 142u, 139u, 140u,
- 108u, 95u, 93u, 121u,
- 221u, 54u, 66u, 105u,
- 152u, 255u, 98u, 37u,
- 93u, 52u, 113u, 102u,
- 52u, 162u, 183u, 73u,
- 67u, 151u, 175u, 159u,
- 167u, 102u, 92u, 1u,
- 109u, 146u, 106u, 181u,
- 45u, 255u, 155u, 70u,
- 149u, 248u, 218u, 139u,
- 145u, 39u, 161u, 237u,
- 89u, 217u, 6u, 110u,
- 111u, 112u, 1u, 122u,
- 188u, 107u, 79u, 157u,
- 160u, 134u, 82u, 114u,
- 64u, 163u, 164u, 166u,
- 126u, 39u, 55u, 181u,
- 126u, 109u, 142u, 255u,
- 192u, 204u, 126u, 109u,
- 117u, 88u, 105u, 78u,
- 135u, 158u, 159u, 165u,
- 130u, 187u, 240u, 168u,
- 100u, 145u, 29u, 248u,
- 19u, 28u, 0u, 154u,
- 1u, 113u, 108u, 29u,
- 201u, 115u, 130u, 130u,
- 84u, 1u, 117u, 235u,
- 65u, 232u, 214u, 54u,
- 130u, 68u, 151u, 49u,
- 157u, 216u, 122u, 180u,
- 17u, 185u, 182u, 157u,
- 255u, 152u, 95u, 131u,
- 118u, 69u, 181u, 89u,
- 27u, 82u, 186u, 112u,
- 14u, 224u, 255u, 215u,
- 89u, 153u, 213u, 187u,
- 253u, 198u, 79u, 170u,
- 156u, 1u, 125u, 17u,
- 224u, 67u, 192u, 220u,
- 124u, 211u, 108u, 24u,
- 57u, 92u, 131u, 134u,
- 50u, 212u, 226u, 89u,
- 153u, 40u, 132u, 189u,
- 186u, 86u, 103u, 255u,
- 131u, 170u, 64u, 142u,
- 1u, 255u, 105u, 255u,
- 120u, 131u, 137u, 83u,
- 88u, 38u, 122u, 175u,
- 140u, 153u, 246u, 216u,
- 27u, 224u, 198u, 154u,
- 133u, 1u, 43u, 137u,
- 184u, 112u, 86u, 146u,
- 185u, 196u, 187u, 1u,
- 152u, 113u, 29u, 117u,
- 174u, 100u, 186u, 147u,
- 50u, 137u, 111u, 208u,
- 102u, 253u, 71u, 180u,
- 50u, 185u, 28u, 159u,
- 118u, 30u, 21u, 98u,
- 87u, 255u, 190u, 107u,
- 131u, 225u, 170u, 92u,
- 1u, 131u, 110u, 63u,
- 82u, 129u, 201u, 180u,
- 88u, 117u, 152u, 166u,
- 22u, 83u, 59u, 211u,
- 34u, 64u, 98u, 115u,
- 167u, 255u, 81u, 96u,
- 117u, 85u, 67u, 110u,
- 182u, 219u, 20u, 39u,
- 87u, 149u, 134u, 179u,
- 76u, 71u, 191u, 63u,
- 233u, 255u, 188u, 81u,
- 211u, 233u, 98u, 158u,
- 0u, 86u, 143u, 192u,
- 182u, 130u, 211u, 52u,
- 115u, 148u, 30u, 111u,
- 17u, 68u, 255u, 88u,
- 224u, 62u, 121u, 202u,
- 121u, 78u, 110u, 116u,
- 162u, 193u, 183u, 185u,
- 15u, 43u, 199u, 85u,
- 6u, 131u, 46u, 48u,
- 117u, 250u, 161u, 118u,
- 255u, 105u, 70u, 125u,
- 155u, 65u, 177u, 146u,
- 185u, 1u, 56u, 27u,
- 134u, 211u, 100u, 168u,
- 124u, 92u, 61u, 44u,
- 120u, 153u, 209u, 146u,
- 150u, 169u, 165u, 169u,
- 155u, 210u, 110u, 149u,
- 115u, 106u, 1u, 72u,
- 95u, 76u, 83u, 122u,
- 105u, 139u, 103u, 134u,
- 57u, 187u, 84u, 58u,
- 120u, 117u, 0u, 196u,
- 46u, 96u, 81u, 70u,
- 226u, 129u, 180u, 1u,
- 194u, 221u, 151u, 170u,
- 135u, 201u, 117u, 56u,
- 82u, 215u, 29u, 198u,
- 39u, 99u, 125u, 28u,
- 83u, 255u, 95u, 92u,
- 110u, 92u, 39u, 161u,
- 243u, 15u, 178u, 127u,
- 100u, 157u, 255u, 193u,
- 148u, 208u, 73u, 134u,
- 154u, 126u, 161u, 202u,
- 154u, 45u, 144u, 137u,
- 171u, 129u, 255u, 78u,
- 148u, 100u, 59u, 147u,
- 120u, 186u, 125u, 101u,
- 132u, 111u, 139u, 1u,
- 161u, 126u, 159u, 130u,
- 173u, 158u, 69u, 130u,
- 172u, 126u, 118u, 187u,
- 235u, 142u, 179u, 128u,
- 82u, 79u, 54u, 194u,
- 206u, 100u, 194u, 255u,
- 119u, 78u, 137u, 103u,
- 132u, 0u, 163u, 167u,
- 150u, 66u, 147u, 53u,
- 137u, 191u, 102u, 122u,
- 196u, 151u, 177u, 134u,
- 38u, 72u, 136u, 19u,
- 152u, 118u, 92u, 160u,
- 172u, 147u, 171u, 145u,
- 115u, 33u, 1u, 164u,
- 159u, 132u, 65u, 99u,
- 104u, 73u, 21u, 201u,
- 255u, 45u, 104u, 85u,
- 95u, 114u, 122u, 57u,
- 140u, 134u, 255u, 72u,
- 116u, 100u, 178u, 179u,
- 151u, 130u, 171u, 141u,
- 114u, 92u, 133u, 142u,
- 80u, 45u, 145u, 116u,
- 126u, 44u, 1u, 85u,
- 93u, 29u, 132u, 191u,
- 144u, 180u, 147u, 125u,
- 48u, 124u, 119u, 195u,
- 24u, 255u, 202u, 111u,
- 175u, 138u, 63u, 16u,
- 109u, 59u, 31u, 193u,
- 255u, 144u, 103u, 48u,
- 46u, 21u, 31u, 144u,
- 174u, 197u, 249u, 152u,
- 55u, 7u, 236u, 18u,
- 55u, 173u, 208u, 142u,
- 0u, 219u, 139u, 111u,
- 155u, 124u, 90u, 85u,
- 94u, 95u, 162u, 186u,
- 154u, 73u, 110u, 55u,
- 200u, 10u, 255u, 42u,
- 161u, 151u, 69u, 202u,
- 125u, 161u, 247u, 185u,
- 191u, 161u, 255u, 40u,
- 190u, 182u, 163u, 87u,
- 43u, 105u, 141u, 193u,
- 129u, 73u, 107u, 144u,
- 107u, 125u, 1u, 52u,
- 66u, 204u, 88u, 102u,
- 79u, 125u, 221u, 212u,
- 112u, 197u, 96u, 160u,
- 104u, 134u, 255u, 154u,
- 147u, 167u, 218u, 165u,
- 77u, 159u, 122u, 160u,
- 229u, 197u, 167u, 193u,
- 83u, 98u, 115u, 143u,
- 194u, 22u, 148u, 174u,
- 133u, 133u, 36u, 0u,
- 138u, 169u, 116u, 84u,
- 1u, 125u, 33u, 53u,
- 63u, 67u, 141u, 140u,
- 176u, 198u, 112u, 116u,
- 46u, 88u, 102u, 182u,
- 134u, 194u, 68u, 139u,
- 100u, 227u, 112u, 255u,
- 159u, 111u, 164u, 208u,
- 147u, 137u, 79u, 57u,
- 178u, 187u, 1u, 76u,
- 178u, 83u, 95u, 179u,
- 126u, 55u, 219u, 152u,
- 20u, 167u, 37u, 185u,
- 143u, 195u, 123u, 88u,
- 255u, 248u, 94u, 137u,
- 190u, 102u, 43u, 193u,
- 191u, 88u, 150u, 102u,
- 230u, 206u, 33u, 71u,
- 180u, 135u, 98u, 246u,
- 49u, 178u, 144u, 242u,
- 171u, 186u, 1u, 34u,
- 81u, 102u, 159u, 127u,
- 169u, 123u, 150u, 163u,
- 53u, 133u, 23u, 0u,
- 88u, 127u, 162u, 38u,
- 78u, 72u, 216u, 206u,
- 185u, 215u, 47u, 1u,
- 101u, 30u, 37u, 245u,
- 114u, 156u, 50u, 107u,
- 110u, 169u, 105u, 139u,
- 120u, 255u, 98u, 208u,
- 217u, 115u, 129u, 86u,
- 68u, 135u, 78u, 117u,
- 150u, 148u, 66u, 188u,
- 101u, 120u, 255u, 48u,
- 183u, 169u, 68u, 127u,
- 197u, 178u, 248u, 51u,
- 42u, 85u, 224u, 255u,
- 76u, 220u, 238u, 136u,
- 117u, 22u, 100u, 202u,
- 81u, 61u, 162u, 225u,
- 179u, 158u, 181u, 84u,
- 97u, 126u, 117u, 255u,
- 164u, 239u, 203u, 187u,
- 76u, 47u, 148u, 142u,
- 124u, 63u, 114u, 133u,
- 139u, 0u, 155u, 209u,
- 114u, 81u, 74u, 101u,
- 47u, 47u, 100u, 139u,
- 118u, 87u, 154u, 146u,
- 129u, 148u, 157u, 99u,
- 80u, 207u, 8u, 1u,
- 106u, 168u, 159u, 188u,
- 146u, 163u, 233u, 83u,
- 1u, 144u, 28u, 53u,
- 32u, 117u, 160u, 142u,
- 91u, 115u, 78u, 203u,
- 113u, 1u, 119u, 119u,
- 109u, 24u, 124u, 114u,
- 157u, 152u, 104u, 160u,
- 118u, 198u, 90u, 148u,
- 60u, 66u, 119u, 213u,
- 159u, 111u, 169u, 245u,
- 132u, 107u, 90u, 132u,
- 158u, 251u, 255u, 160u,
- 208u, 72u, 136u, 128u,
- 80u, 155u, 213u, 238u,
- 181u, 255u, 133u, 106u,
- 123u, 123u, 82u, 89u,
- 134u, 167u, 255u, 224u,
- 129u, 62u, 170u, 58u,
- 172u, 152u, 114u, 178u,
- 133u, 158u, 72u, 114u,
- 155u, 131u, 155u, 177u,
- 88u, 104u, 132u, 150u,
- 106u, 133u, 106u, 102u,
- 100u, 113u, 1u, 131u,
- 136u, 111u, 83u, 119u,
- 212u, 104u, 109u, 255u,
- 160u, 250u, 166u, 122u,
- 225u, 134u, 72u, 52u,
- 177u, 180u, 32u, 224u,
- 162u, 157u, 34u, 255u,
- 172u, 133u, 7u, 193u,
- 140u, 237u, 79u, 130u,
- 81u, 160u, 183u, 1u,
- 89u, 128u, 133u, 118u,
- 107u, 87u, 141u, 69u,
- 79u, 130u, 139u, 186u,
- 15u, 84u, 162u, 104u,
- 28u, 95u, 81u, 197u,
- 186u, 1u, 142u, 163u,
- 107u, 84u, 138u, 177u,
- 176u, 93u, 131u, 162u,
- 210u, 59u, 79u, 101u,
- 255u, 211u, 154u, 178u,
- 123u, 97u, 160u, 181u,
- 80u, 199u, 146u, 129u,
- 6u, 1u, 13u, 127u,
- 47u, 152u, 189u, 65u,
- 20u, 43u, 189u, 76u,
- 167u, 125u, 99u, 49u,
- 152u, 155u, 91u, 139u,
- 71u, 255u, 59u, 5u,
- 105u, 131u, 68u, 137u,
- 139u, 149u, 83u, 155u,
- 84u, 152u, 132u, 170u,
- 145u, 127u, 160u, 181u,
- 169u, 90u, 255u, 62u,
- 180u, 185u, 242u, 127u,
- 18u, 255u, 24u, 65u,
- 30u, 144u, 141u, 134u,
- 143u, 125u, 12u, 68u,
- 173u, 108u, 64u, 170u,
- 229u, 106u, 162u, 153u,
- 75u, 255u, 117u, 118u,
- 210u, 239u, 168u, 160u,
- 170u, 68u, 140u, 151u,
- 159u, 139u, 89u, 76u,
- 144u, 0u, 87u, 75u,
- 132u, 103u, 100u, 110u,
- 254u, 127u, 255u, 223u,
- 76u, 211u, 174u, 174u,
- 219u, 97u, 52u, 182u,
- 238u, 168u, 42u, 32u,
- 253u, 168u, 9u, 174u,
- 182u, 124u, 244u, 255u,
- 150u, 90u, 35u, 113u,
- 141u, 81u, 184u, 83u,
- 165u, 167u, 181u, 1u,
- 194u, 223u, 118u, 190u,
- 194u, 143u, 64u, 139u,
- 47u, 195u, 103u, 224u,
- 50u, 142u, 255u, 124u,
- 229u, 210u, 254u, 60u,
- 126u, 38u, 97u, 147u,
- 151u, 199u, 73u, 153u,
- 0u, 141u, 112u, 84u,
- 123u, 55u, 60u, 150u,
- 78u, 62u, 148u, 109u,
- 188u, 179u, 218u, 72u,
- 132u, 181u, 254u, 151u,
- 92u, 120u, 134u, 136u,
- 1u, 212u, 198u, 232u,
- 247u, 45u, 141u, 156u,
- 13u, 63u, 1u, 232u,
- 75u, 133u, 172u, 159u,
- 41u, 223u, 51u, 84u,
- 183u, 67u, 22u, 122u,
- 142u, 195u, 100u, 255u,
- 221u, 104u, 99u, 49u,
- 90u, 75u, 63u, 198u,
- 242u, 126u, 90u, 74u,
- 149u, 135u, 47u, 139u,
- 129u, 129u, 192u, 167u,
- 255u, 129u, 139u, 188u,
- 207u, 109u, 107u, 117u,
- 138u, 138u, 189u, 100u,
- 107u, 64u, 158u, 107u,
- 131u, 120u, 173u, 125u,
- 130u, 144u, 116u, 1u,
- 111u, 201u, 75u, 137u,
- 255u, 70u, 134u, 189u,
- 44u, 106u, 114u, 110u,
- 145u, 98u, 106u, 155u,
- 148u, 127u, 119u, 122u,
- 143u, 105u, 140u, 109u,
- 142u, 1u, 194u, 105u,
- 108u, 124u, 123u, 186u,
- 143u, 123u, 101u, 198u,
- 95u, 124u, 133u, 154u,
- 160u, 1u, 54u, 13u,
- 72u, 132u, 84u, 53u,
- 235u, 121u, 1u, 49u,
- 122u, 148u, 197u, 129u,
- 85u, 44u, 188u, 89u,
- 208u, 183u, 173u, 50u,
- 69u, 169u, 1u, 146u,
- 148u, 110u, 120u, 46u,
- 151u, 142u, 142u, 151u,
- 162u, 103u, 100u, 162u,
- 45u, 87u, 78u, 99u,
- 181u, 180u, 233u, 153u,
- 77u, 149u, 1u, 127u,
- 244u, 170u, 157u, 155u,
- 235u, 197u, 133u, 92u,
- 119u, 173u, 100u, 30u,
- 152u, 87u, 214u, 90u,
- 203u, 157u, 171u, 255u,
- 113u, 101u, 163u, 122u,
- 13u, 137u, 106u, 135u,
- 114u, 79u, 243u, 118u,
- 72u, 80u, 1u, 89u,
- 87u, 116u, 82u, 140u,
- 156u, 26u, 188u, 0u,
- 85u, 34u, 29u, 134u,
- 6u, 188u, 218u, 241u,
- 100u, 190u, 22u, 99u,
- 100u, 179u, 81u, 125u,
- 255u, 180u, 226u, 99u,
- 118u, 105u, 139u, 138u,
- 149u, 133u, 122u, 165u,
- 114u, 61u, 190u, 112u,
- 33u, 118u, 40u, 61u,
- 151u, 255u, 221u, 69u,
- 255u, 106u, 59u, 178u,
- 64u, 108u, 203u, 211u,
- 40u, 107u, 37u, 76u,
- 176u, 98u, 103u, 122u,
- 181u, 181u, 97u, 47u,
- 141u, 7u, 226u, 69u,
- 30u, 36u, 193u, 202u,
- 255u, 232u, 213u, 83u,
- 16u, 184u, 24u, 134u,
- 5u, 63u, 153u, 184u,
- 91u, 193u, 174u, 130u,
- 123u, 1u, 193u, 133u,
- 116u, 105u, 86u, 144u,
- 218u, 56u, 239u, 129u,
- 179u, 151u, 225u, 255u,
- 179u, 34u, 81u, 167u,
- 206u, 63u, 144u, 108u,
- 47u, 226u, 201u, 123u,
- 119u, 116u, 111u, 1u,
- 105u, 128u, 215u, 162u,
- 74u, 158u, 191u, 105u,
- 40u, 181u, 224u, 118u,
- 104u, 229u, 128u, 108u,
- 217u, 143u, 255u, 200u,
- 150u, 254u, 127u, 140u,
- 74u, 89u, 158u, 216u,
- 116u, 86u, 185u, 168u,
- 255u, 221u, 105u, 135u,
- 255u, 55u, 217u, 168u,
- 130u, 60u, 106u, 95u,
- 175u, 240u, 91u, 130u,
- 169u, 161u, 140u, 84u,
- 53u, 116u, 10u, 143u,
- 21u, 102u, 189u, 150u,
- 160u, 228u, 112u, 96u,
- 1u, 15u, 136u, 239u,
- 81u, 124u, 140u, 231u,
- 94u, 255u, 125u, 123u,
- 136u, 143u, 36u, 252u,
- 210u, 105u, 106u, 91u,
- 193u, 51u, 155u, 57u,
- 21u, 109u, 172u, 156u,
- 87u, 114u, 140u, 118u,
- 1u, 209u, 145u, 117u,
- 121u, 146u, 135u, 120u,
- 255u, 82u, 104u, 93u,
- 66u, 119u, 76u, 155u,
- 106u, 248u, 177u, 202u,
- 125u, 150u, 110u, 87u,
- 255u, 158u, 127u, 157u,
- 96u, 107u, 62u, 121u,
- 177u, 99u, 132u, 187u,
- 209u, 193u, 164u, 184u,
- 55u, 162u, 18u, 0u,
- 92u, 110u, 131u, 20u,
- 81u, 148u, 211u, 180u,
- 114u, 121u, 44u, 164u,
- 90u, 153u, 110u, 173u,
- 101u, 255u, 117u, 95u,
- 159u, 55u, 47u, 110u,
- 129u, 138u, 142u, 75u,
- 51u, 157u, 101u, 255u,
- 158u, 133u, 216u, 103u,
- 169u, 25u, 156u, 122u,
- 7u, 135u, 85u, 125u,
- 135u, 160u, 255u, 184u,
- 74u, 88u, 77u, 224u,
- 164u, 86u, 144u, 160u,
- 149u, 236u, 66u, 174u,
- 68u, 160u, 1u, 173u,
- 106u, 109u, 109u, 33u,
- 177u, 97u, 132u, 121u,
- 89u, 76u, 127u, 144u,
- 105u, 131u, 139u, 139u,
- 202u, 255u, 130u, 193u,
- 142u, 47u, 101u, 136u,
- 79u, 43u, 1u, 184u,
- 169u, 69u, 124u, 152u,
- 144u, 116u, 63u, 111u,
- 73u, 167u, 144u, 182u,
- 159u, 154u, 75u, 131u,
- 173u, 207u, 255u, 182u,
- 151u, 204u, 83u, 158u,
- 103u, 215u, 88u, 49u,
- 180u, 61u, 37u, 255u,
- 62u, 174u, 241u, 33u,
- 96u, 182u, 35u, 60u,
- 163u, 96u, 222u, 91u,
- 154u, 173u, 86u, 182u,
- 119u, 227u, 82u, 115u,
- 0u, 240u, 28u, 71u,
- 124u, 234u, 149u, 191u,
- 120u, 181u, 219u, 176u,
- 1u, 145u, 232u, 239u,
- 158u, 196u, 66u, 101u,
- 136u, 246u, 9u, 84u,
- 65u, 89u, 108u, 156u,
- 172u, 225u, 54u, 153u,
- 249u, 93u, 167u, 1u,
- 197u, 199u, 169u, 163u,
- 130u, 160u, 149u, 173u,
- 105u, 27u, 39u, 62u,
- 109u, 140u, 143u, 109u,
- 255u, 187u, 131u, 20u,
- 115u, 157u, 115u, 149u,
- 72u, 34u, 166u, 239u,
- 172u, 106u, 255u, 174u,
- 251u, 199u, 204u, 57u,
- 139u, 163u, 133u, 80u,
- 193u, 136u, 99u, 78u,
- 213u, 56u, 163u, 117u,
- 181u, 255u, 80u, 98u,
- 189u, 107u, 96u, 178u,
- 1u, 174u, 91u, 160u,
- 103u, 117u, 166u, 54u,
- 78u, 114u, 145u, 153u,
- 151u, 70u, 40u, 105u,
- 17u, 98u, 255u, 156u,
- 115u, 94u, 139u, 86u,
- 150u, 133u, 70u, 74u,
- 196u, 40u, 156u, 255u,
- 131u, 163u, 83u, 38u,
- 115u, 96u, 51u, 176u,
- 92u, 198u, 103u, 99u,
- 1u, 145u, 127u, 92u,
- 59u, 65u, 42u, 66u,
- 42u, 38u, 188u, 128u,
- 153u, 25u, 222u, 207u,
- 141u, 43u, 230u, 127u,
- 177u, 56u, 255u, 57u,
- 80u, 65u, 130u, 92u,
- 247u, 121u, 48u, 76u,
- 132u, 99u, 139u, 106u,
- 41u, 210u, 208u, 201u,
- 173u, 8u, 169u, 245u,
- 109u, 181u, 69u, 1u,
- 140u, 255u, 127u, 109u,
- 162u, 164u, 227u, 83u,
- 84u, 11u, 149u, 40u,
- 146u, 148u, 215u, 16u,
- 107u, 123u, 11u, 255u,
- 56u, 170u, 113u, 104u,
- 20u, 206u, 119u, 140u,
- 152u, 96u, 119u, 114u,
- 161u, 112u, 214u, 198u,
- 147u, 85u, 137u, 88u,
- 181u, 146u, 109u, 209u,
- 255u, 143u, 171u, 165u,
- 201u, 67u, 89u, 122u,
- 209u, 190u, 74u, 87u,
- 120u, 0u, 144u, 128u,
- 233u, 177u, 207u, 131u,
- 139u, 81u, 115u, 192u,
- 128u, 44u, 0u, 195u,
- 199u, 217u, 150u, 82u,
- 58u, 91u, 119u, 169u,
- 59u, 80u, 109u, 1u,
- 155u, 135u, 33u, 159u,
- 208u, 104u, 191u, 139u,
- 106u, 153u, 177u, 145u,
- 220u, 189u, 181u, 77u,
- 1u, 149u, 211u, 150u,
- 68u, 150u, 111u, 142u,
- 164u, 123u, 217u, 210u,
- 76u, 110u, 1u, 62u,
- 123u, 163u, 140u, 123u,
- 143u, 145u, 190u, 84u,
- 126u, 105u, 158u, 143u,
- 118u, 15u, 255u, 154u,
- 8u, 47u, 112u, 60u,
- 209u, 178u, 228u, 168u,
- 45u, 114u, 160u, 163u,
- 102u, 129u, 66u, 7u,
- 251u, 94u, 98u, 85u,
- 78u, 255u, 127u, 219u,
- 159u, 215u, 197u, 100u,
- 216u, 118u, 212u, 174u,
- 179u, 83u, 92u, 0u,
- 116u, 135u, 76u, 177u,
- 125u, 185u, 59u, 30u,
- 255u, 164u, 129u, 15u,
- 126u, 186u, 88u, 185u,
- 82u, 140u, 171u, 127u,
- 180u, 168u, 12u, 128u,
- 115u, 197u, 112u, 124u,
- 255u, 169u, 94u, 186u,
- 80u, 140u, 96u, 144u,
- 176u, 172u, 233u, 126u,
- 150u, 1u, 198u, 133u,
- 100u, 66u, 174u, 43u,
- 165u, 183u, 151u, 238u,
- 146u, 158u, 157u, 123u,
- 142u, 118u, 189u, 101u,
- 75u, 208u, 77u, 131u,
- 81u, 255u, 215u, 209u,
- 148u, 75u, 110u, 132u,
- 132u, 136u, 58u, 1u,
- 144u, 205u, 144u, 145u,
- 240u, 33u, 139u, 115u,
- 93u, 145u, 108u, 168u,
- 56u, 119u, 135u, 255u,
- 16u, 127u, 206u, 2u,
- 197u, 120u, 188u, 215u,
- 161u, 73u, 30u, 25u,
- 80u, 61u, 123u, 55u,
- 156u, 72u, 145u, 44u,
- 223u, 91u, 85u, 157u,
- 152u, 100u, 255u, 178u,
- 58u, 55u, 14u, 166u,
- 64u, 147u, 255u, 167u,
- 22u, 134u, 134u, 119u,
- 130u, 76u, 97u, 82u,
- 123u, 211u, 147u, 0u,
- 118u, 109u, 117u, 187u,
- 28u, 111u, 91u, 134u,
- 70u, 64u, 81u, 131u,
- 184u, 163u, 92u, 126u,
- 138u, 1u, 150u, 115u,
- 159u, 49u, 113u, 101u,
- 89u, 136u, 118u, 141u,
- 239u, 84u, 73u, 255u,
- 147u, 119u, 15u, 117u,
- 118u, 109u, 147u, 131u,
- 63u, 108u, 47u, 163u,
- 84u, 178u, 255u, 108u,
- 172u, 213u, 116u, 185u,
- 78u, 59u, 124u, 176u,
- 105u, 32u, 94u, 225u,
- 142u, 180u, 12u, 123u,
- 103u, 174u, 109u, 210u,
- 51u, 89u, 168u, 37u,
- 185u, 226u, 118u, 1u,
- 150u, 150u, 0u, 2u,
- 109u, 35u, 178u, 78u,
- 109u, 242u, 128u, 128u,
- 105u, 113u, 134u, 84u,
- 175u, 224u, 97u, 156u,
- 0u, 111u, 89u, 14u,
- 72u, 116u, 254u, 145u,
- 114u, 25u, 96u, 124u,
- 158u, 134u, 68u, 0u,
- 243u, 64u, 87u, 143u,
- 218u, 142u, 123u, 111u,
- 120u, 143u, 156u, 85u,
- 176u, 208u, 158u, 167u,
- 231u, 194u, 179u, 232u,
- 16u, 53u, 166u, 214u,
- 165u, 125u, 0u, 161u,
- 167u, 142u, 86u, 190u,
- 137u, 89u, 255u, 5u,
- 139u, 101u, 68u, 154u,
- 133u, 189u, 178u, 24u,
- 126u, 158u, 147u, 39u,
- 255u, 160u, 143u, 147u,
- 208u, 116u, 98u, 106u,
- 81u, 191u, 134u, 126u,
- 146u, 144u, 1u, 169u,
- 47u, 98u, 178u, 122u,
- 135u, 144u, 252u, 69u,
- 157u, 126u, 130u, 163u,
- 107u, 94u, 32u, 98u,
- 158u, 140u, 195u, 86u,
- 102u, 56u, 87u, 164u,
- 154u, 255u, 176u, 134u,
- 0u, 97u, 101u, 129u,
- 168u, 139u, 153u, 175u,
- 77u, 184u, 84u, 180u,
- 181u, 54u, 240u, 157u,
- 133u, 135u, 217u, 0u,
- 209u, 89u, 93u, 150u,
- 85u, 129u, 152u, 122u,
- 75u, 108u, 117u, 183u,
- 231u, 148u, 53u, 197u,
- 49u, 96u, 117u, 47u,
- 119u, 74u, 161u, 38u,
- 84u, 255u, 120u, 231u,
- 109u, 78u, 255u, 170u,
- 177u, 174u, 169u, 74u,
- 127u, 146u, 52u, 135u,
- 178u, 148u, 198u, 128u,
- 184u, 170u, 54u, 122u,
- 82u, 142u, 193u, 186u,
- 255u, 83u, 135u, 129u,
- 185u, 59u, 162u, 92u,
- 164u, 159u, 93u, 226u,
- 94u, 120u, 126u, 96u,
- 82u, 91u, 82u, 1u,
- 30u, 163u, 50u, 173u,
- 48u, 183u, 96u, 57u,
- 96u, 129u, 167u, 255u,
- 46u, 125u, 189u, 230u,
- 140u, 72u, 115u, 191u,
- 166u, 97u, 84u, 86u,
- 16u, 85u, 89u, 1u,
- 209u, 182u, 227u, 252u,
- 13u, 148u, 147u, 115u,
- 80u, 216u, 24u, 135u,
- 205u, 155u, 103u, 193u,
- 77u, 99u, 155u, 255u,
- 138u, 212u, 72u, 126u,
- 96u, 199u, 114u, 69u,
- 148u, 255u, 29u, 143u,
- 121u, 49u, 205u, 161u,
- 208u, 207u, 18u, 116u,
- 204u, 255u, 152u, 110u,
- 67u, 212u, 181u, 254u,
- 196u, 154u, 206u, 123u,
- 251u, 100u, 142u, 108u,
- 80u, 228u, 164u, 135u,
- 249u, 177u, 151u, 35u,
- 95u, 155u, 186u, 255u,
- 164u, 102u, 235u, 148u,
- 90u, 188u, 158u, 125u,
- 65u, 244u, 60u, 213u,
- 54u, 0u, 154u, 109u,
- 121u, 181u, 64u, 186u,
- 125u, 247u, 56u, 72u,
- 199u, 255u, 55u, 166u,
- 165u, 77u, 111u, 233u,
- 116u, 169u, 150u, 146u,
- 144u, 56u, 129u, 216u,
- 102u, 153u, 130u, 113u,
- 96u, 82u, 100u, 35u,
- 135u, 134u, 156u, 255u,
- 222u, 38u, 69u, 122u,
- 185u, 73u, 126u, 203u,
- 1u, 121u, 66u, 108u,
- 114u, 134u, 198u, 210u,
- 83u, 88u, 143u, 215u,
- 41u, 173u, 30u, 1u,
- 224u, 38u, 140u, 80u,
- 246u, 50u, 214u, 74u,
- 77u, 178u, 146u, 106u,
- 108u, 177u, 108u, 1u,
- 46u, 164u, 74u, 191u,
- 228u, 185u, 238u, 146u,
- 162u, 193u, 224u, 152u,
- 0u, 238u, 196u, 74u,
- 100u, 204u, 83u, 175u,
- 241u, 178u, 214u, 172u,
- 123u, 148u, 129u, 151u,
- 91u, 149u, 26u, 157u,
- 208u, 132u, 129u, 135u,
- 57u, 1u, 101u, 183u,
- 53u, 162u, 255u, 172u,
- 165u, 96u, 89u, 126u,
- 127u, 83u, 118u, 58u,
- 60u, 233u, 186u, 177u,
- 72u, 242u, 196u, 48u,
- 111u, 162u, 234u, 251u,
- 27u, 255u, 166u, 72u,
- 134u, 70u, 176u, 207u,
- 217u, 185u, 198u, 124u,
- 183u, 69u, 241u, 227u,
- 1u, 79u, 64u, 190u,
- 216u, 141u, 189u, 139u,
- 114u, 157u, 58u, 170u,
- 178u, 44u, 72u, 171u,
- 52u, 241u, 52u, 211u,
- 0u, 98u, 49u, 110u,
- 41u, 161u, 80u, 105u,
- 151u, 4u, 255u, 170u,
- 105u, 84u, 219u, 102u,
- 54u, 126u, 48u, 117u,
- 86u, 53u, 101u, 191u,
- 39u, 114u, 65u, 199u,
- 18u, 203u, 187u, 85u,
- 55u, 1u, 74u, 103u,
- 122u, 115u, 197u, 79u,
- 47u, 156u, 63u, 147u,
- 250u, 147u, 160u, 150u,
- 28u, 53u, 1u, 165u,
- 66u, 147u, 139u, 153u,
- 34u, 127u, 44u, 0u,
- 83u, 93u, 157u, 184u,
- 85u, 166u, 171u, 95u,
- 215u, 138u, 126u, 108u,
- 201u, 133u, 83u, 124u,
- 0u, 84u, 83u, 143u,
- 70u, 135u, 197u, 112u,
- 150u, 89u, 212u, 155u,
- 53u, 251u, 80u, 172u,
- 170u, 106u, 127u, 175u,
- 155u, 103u, 1u, 196u,
- 109u, 173u, 147u, 0u,
- 211u, 184u, 85u, 116u,
- 103u, 190u, 137u, 110u,
- 121u, 206u, 21u, 206u,
- 255u, 87u, 184u, 150u,
- 175u, 131u, 208u, 8u,
- 150u, 38u, 108u, 213u,
- 189u, 217u, 172u, 53u,
- 221u, 86u, 232u, 255u,
- 241u, 71u, 239u, 20u,
- 53u, 96u, 153u, 130u,
- 53u, 184u, 173u, 220u,
- 68u, 196u, 128u, 51u,
- 63u, 147u, 171u, 186u,
- 1u, 69u, 27u, 99u,
- 29u, 91u, 135u, 173u,
- 67u, 92u, 217u, 255u,
- 152u, 148u, 109u, 71u,
- 186u, 18u, 50u, 82u,
- 171u, 79u, 65u, 24u,
- 43u, 167u, 129u, 76u,
- 188u, 255u, 127u, 136u,
- 114u, 92u, 73u, 152u,
- 128u, 152u, 79u, 159u,
- 142u, 158u, 112u, 1u,
- 134u, 88u, 118u, 108u,
- 49u, 250u, 158u, 104u,
- 186u, 155u, 108u, 181u,
- 133u, 139u, 64u, 104u,
- 255u, 95u, 93u, 85u,
- 111u, 218u, 44u, 140u,
- 156u, 139u, 113u, 69u,
- 1u, 173u, 200u, 71u,
- 102u, 203u, 120u, 96u,
- 54u, 191u, 107u, 138u,
- 118u, 132u, 197u, 175u,
- 103u, 145u, 153u, 109u,
- 222u, 134u, 51u, 154u,
- 23u, 61u, 121u, 124u,
- 1u, 184u, 206u, 52u,
- 153u, 139u, 162u, 71u,
- 67u, 233u, 1u, 187u,
- 83u, 148u, 223u, 170u,
- 196u, 63u, 4u, 109u,
- 96u, 183u, 157u, 149u,
- 58u, 199u, 180u, 142u,
- 36u, 156u, 83u, 140u,
- 179u, 196u, 255u, 212u,
- 168u, 136u, 98u, 27u,
- 82u, 79u, 173u, 255u,
- 110u, 189u, 180u, 192u,
- 102u, 120u, 146u, 108u,
- 202u, 94u, 80u, 125u,
- 142u, 134u, 186u, 115u,
- 209u, 212u, 143u, 155u,
- 255u, 160u, 230u, 22u,
- 85u, 246u, 67u, 173u,
- 13u, 199u, 26u, 15u,
- 113u, 114u, 255u, 11u,
- 99u, 160u, 127u, 206u,
- 186u, 88u, 133u, 108u,
- 160u, 98u, 82u, 110u,
- 55u, 158u, 116u, 122u,
- 109u, 255u, 107u, 136u,
- 160u, 115u, 146u, 114u,
- 167u, 96u, 40u, 124u,
- 161u, 108u, 63u, 96u,
- 174u, 0u, 117u, 177u,
- 142u, 105u, 90u, 74u,
- 113u, 84u, 140u, 149u,
- 84u, 111u, 186u, 255u,
- 143u, 57u, 176u, 168u,
- 197u, 104u, 138u, 132u,
- 1u, 168u, 64u, 129u,
- 116u, 127u, 240u, 179u,
- 88u, 105u, 151u, 169u,
- 195u, 161u, 92u, 0u,
- 103u, 175u, 66u, 222u,
- 147u, 111u, 188u, 109u,
- 217u, 160u, 194u, 155u,
- 145u, 80u, 122u, 228u,
- 143u, 51u, 189u, 3u,
- 216u, 64u, 1u, 136u,
- 231u, 196u, 135u, 9u,
- 93u, 138u, 66u, 84u,
- 195u, 103u, 255u, 140u,
- 125u, 98u, 125u, 161u,
- 191u, 152u, 243u, 84u,
- 102u, 152u, 0u, 134u,
- 118u, 150u, 99u, 157u,
- 245u, 157u, 216u, 155u,
- 171u, 98u, 167u, 71u,
- 86u, 191u, 100u, 155u,
- 74u, 115u, 1u, 119u,
- 142u, 136u, 106u, 76u,
- 212u, 87u, 89u, 250u,
- 41u, 191u, 255u, 129u,
- 106u, 147u, 19u, 59u,
- 201u, 76u, 214u, 78u,
- 133u, 192u, 165u, 150u,
- 244u, 187u, 195u, 103u,
- 0u, 201u, 10u, 217u,
- 183u, 57u, 234u, 103u,
- 218u, 145u, 118u, 125u,
- 98u, 53u, 47u, 217u,
- 164u, 174u, 142u, 163u,
- 196u, 1u, 32u, 155u,
- 226u, 177u, 147u, 76u,
- 207u, 117u, 93u, 153u,
- 244u, 126u, 63u, 255u,
- 172u, 71u, 40u, 76u,
- 140u, 159u, 108u, 42u,
- 158u, 1u, 138u, 114u,
- 107u, 112u, 173u, 212u,
- 162u, 241u, 166u, 241u,
- 132u, 162u, 81u, 80u,
- 84u, 94u, 117u, 132u,
- 175u, 78u, 110u, 98u,
- 181u, 118u, 57u, 94u,
- 1u, 106u, 122u, 78u,
- 111u, 147u, 35u, 72u,
- 255u, 160u, 29u, 65u,
- 131u, 99u, 38u, 157u,
- 210u, 206u, 125u, 82u,
- 192u, 193u, 116u, 180u,
- 0u, 127u, 105u, 172u,
- 96u, 132u, 187u, 107u,
- 174u, 107u, 104u, 79u,
- 57u, 154u, 136u, 103u,
- 151u, 116u, 195u, 249u,
- 133u, 208u, 227u, 255u,
- 61u, 19u, 72u, 182u,
- 0u, 144u, 87u, 82u,
- 98u, 64u, 241u, 215u,
- 175u, 182u, 91u, 197u,
- 104u, 81u, 85u, 188u,
- 218u, 75u, 81u, 178u,
- 228u, 98u, 1u, 144u,
- 150u, 190u, 149u, 186u,
- 103u, 137u, 92u, 182u,
- 32u, 134u, 51u, 128u,
- 46u, 221u, 165u, 193u,
- 19u, 84u, 188u, 157u,
- 148u, 18u, 0u, 101u,
- 37u, 160u, 163u, 151u,
- 145u, 123u, 41u, 84u,
- 83u, 48u, 150u, 162u,
- 164u, 254u, 255u, 145u,
- 150u, 210u, 184u, 143u,
- 84u, 204u, 173u, 241u,
- 137u, 84u, 123u, 1u,
- 184u, 180u, 135u, 113u,
- 168u, 0u, 19u, 161u,
- 205u, 59u, 24u, 145u,
- 160u, 198u, 102u, 93u,
- 105u, 137u, 156u, 126u,
- 67u, 166u, 78u, 139u,
- 137u, 157u, 255u, 177u,
- 158u, 125u, 83u, 51u,
- 78u, 39u, 103u, 43u,
- 20u, 58u, 107u, 30u,
- 22u, 166u, 218u, 218u,
- 124u, 1u, 125u, 250u,
- 124u, 44u, 153u, 180u,
- 130u, 144u, 5u, 150u,
- 128u, 159u, 150u, 176u,
- 157u, 145u, 150u, 255u,
- 185u, 110u, 70u, 131u,
- 188u, 213u, 154u, 1u,
- 6u, 143u, 107u, 173u,
- 19u, 76u, 217u, 119u,
- 74u, 187u, 23u, 194u,
- 87u, 175u, 167u, 108u,
- 167u, 157u, 54u, 255u,
- 98u, 251u, 227u, 193u,
- 197u, 96u, 12u, 37u,
- 88u, 46u, 37u, 158u,
- 93u, 21u, 147u, 127u,
- 217u, 82u, 45u, 62u,
- 87u, 1u, 77u, 65u,
- 205u, 186u, 163u, 109u,
- 154u, 95u, 244u, 107u,
- 108u, 158u, 119u, 142u,
- 152u, 126u, 255u, 127u,
- 82u, 165u, 99u, 88u,
- 169u, 13u, 50u, 255u,
- 99u, 59u, 146u, 16u,
- 126u, 95u, 91u, 89u,
- 75u, 157u, 168u, 111u,
- 197u, 255u, 113u, 71u,
- 151u, 96u, 112u, 119u,
- 39u, 151u, 79u, 206u,
- 44u, 152u, 207u, 157u,
- 60u, 201u, 67u, 227u,
- 0u, 100u, 224u, 129u,
- 218u, 85u, 172u, 33u,
- 26u, 115u, 173u, 84u,
- 68u, 168u, 163u, 1u,
- 145u, 100u, 89u, 1u,
- 65u, 212u, 158u, 149u,
- 102u, 160u, 179u, 49u,
- 139u, 124u, 87u, 103u,
- 95u, 51u, 61u, 50u,
- 255u, 180u, 101u, 154u,
- 73u, 61u, 167u, 169u,
- 146u, 101u, 149u, 255u,
- 93u, 112u, 91u, 182u,
- 133u, 95u, 130u, 87u,
- 216u, 38u, 168u, 219u,
- 38u, 112u, 67u, 193u,
- 137u, 60u, 224u, 139u,
- 255u, 41u, 68u, 236u,
- 179u, 227u, 102u, 152u,
- 146u, 76u, 215u, 121u,
- 220u, 204u, 255u, 88u,
- 243u, 78u, 151u, 30u,
- 133u, 13u, 216u, 98u,
- 255u, 109u, 72u, 118u,
- 30u, 80u, 22u, 139u,
- 19u, 210u, 87u, 108u,
- 98u, 146u, 63u, 115u,
- 186u, 60u, 255u, 73u,
- 132u, 111u, 53u, 141u,
- 152u, 202u, 183u, 35u,
- 80u, 130u, 150u, 128u,
- 22u, 78u, 86u, 90u,
- 110u, 215u, 93u, 5u,
- 70u, 1u, 68u, 225u,
- 75u, 143u, 134u, 93u,
- 157u, 141u, 97u, 38u,
- 135u, 255u, 81u, 132u,
- 69u, 125u, 212u, 155u,
- 78u, 102u, 114u, 218u,
- 1u, 91u, 115u, 98u,
- 68u, 224u, 85u, 67u,
- 198u, 28u, 140u, 69u,
- 1u, 133u, 52u, 160u,
- 219u, 164u, 140u, 109u,
- 143u, 201u, 86u, 115u,
- 134u, 18u, 246u, 126u,
- 57u, 160u, 87u, 255u,
- 112u, 71u, 30u, 44u,
- 111u, 177u, 113u, 9u,
- 222u, 190u, 237u, 90u,
- 158u, 112u, 55u, 237u,
- 166u, 214u, 86u, 157u,
- 252u, 40u, 102u, 126u,
- 60u, 138u, 0u, 154u,
- 191u, 183u, 50u, 113u,
- 150u, 172u, 137u, 207u,
- 255u, 92u, 146u, 141u,
- 21u, 17u, 34u, 217u,
- 143u, 192u, 91u, 216u,
- 131u, 156u, 255u, 77u,
- 27u, 43u, 67u, 158u,
- 252u, 166u, 144u, 79u,
- 129u, 96u, 112u, 139u,
- 124u, 195u, 130u, 177u,
- 155u, 145u, 142u, 109u,
- 255u, 131u, 69u, 101u,
- 92u, 195u, 53u, 198u,
- 1u, 48u, 139u, 108u,
- 178u, 138u, 197u, 181u,
- 113u, 103u, 18u, 5u,
- 81u, 136u, 87u, 182u,
- 175u, 239u, 249u, 98u,
- 155u, 173u, 112u, 177u,
- 166u, 49u, 255u, 166u,
- 51u, 103u, 135u, 38u,
- 238u, 235u, 175u, 81u,
- 192u, 137u, 144u, 255u,
- 218u, 128u, 77u, 240u,
- 113u, 129u, 1u, 246u,
- 32u, 125u, 176u, 181u,
- 25u, 239u, 150u, 110u,
- 192u, 51u, 189u, 33u,
- 145u, 58u, 115u, 192u,
- 98u, 103u, 124u, 187u,
- 7u, 134u, 144u, 110u,
- 113u, 0u, 75u, 174u,
- 239u, 0u, 241u, 155u,
- 97u, 111u, 208u, 89u,
- 113u, 186u, 75u, 79u,
- 143u, 122u, 158u, 87u,
- 191u, 149u, 110u, 155u,
- 91u, 229u, 101u, 140u,
- 195u, 238u, 255u, 136u,
- 96u, 56u, 9u, 115u,
- 144u, 169u, 106u, 111u,
- 45u, 184u, 112u, 150u,
- 104u, 137u, 1u, 134u,
- 121u, 48u, 130u, 197u,
- 200u, 149u, 162u, 103u,
- 60u, 64u, 41u, 123u,
- 165u, 68u, 255u, 163u,
- 156u, 205u, 108u, 121u,
- 206u, 162u, 240u, 125u,
- 88u, 1u, 28u, 25u,
- 47u, 190u, 106u, 81u,
- 91u, 191u, 249u, 98u,
- 104u, 120u, 118u, 143u,
- 255u, 131u, 170u, 122u,
- 141u, 234u, 31u, 105u,
- 154u, 192u, 97u, 106u,
- 130u, 112u, 147u, 1u,
- 180u, 151u, 97u, 136u,
- 152u, 66u, 138u, 176u,
- 105u, 183u, 133u, 163u,
- 203u, 1u, 220u, 252u,
- 235u, 89u, 183u, 149u,
- 214u, 170u, 59u, 14u,
- 244u, 90u, 73u, 164u,
- 153u, 255u, 46u, 65u,
- 107u, 132u, 54u, 134u,
- 89u, 36u, 237u, 126u,
- 161u, 187u, 142u, 140u,
- 171u, 97u, 0u, 148u,
- 139u, 141u, 156u, 113u,
- 108u, 119u, 67u, 56u,
- 163u, 210u, 136u, 61u,
- 217u, 75u, 159u, 112u,
- 35u, 201u, 211u, 147u,
- 172u, 182u, 98u, 126u,
- 135u, 255u, 36u, 84u,
- 244u, 174u, 197u, 129u,
- 57u, 168u, 118u, 86u,
- 255u, 211u, 88u, 152u,
- 140u, 167u, 110u, 114u,
- 255u, 114u, 102u, 163u,
- 159u, 48u, 217u, 47u,
- 178u, 189u, 130u, 155u,
- 119u, 130u, 241u, 23u,
- 117u, 95u, 255u, 221u,
- 68u, 44u, 202u, 125u,
- 145u, 107u, 70u, 89u,
- 194u, 18u, 70u, 203u,
- 87u, 231u, 98u, 130u,
- 194u, 108u, 48u, 89u,
- 154u, 1u, 70u, 77u,
- 150u, 154u, 160u, 103u,
- 113u, 17u, 148u, 255u,
- 32u, 118u, 144u, 91u,
- 121u, 101u, 51u, 180u,
- 71u, 67u, 82u, 145u,
- 142u, 131u, 174u, 230u,
- 156u, 112u, 51u, 76u,
- 55u, 64u, 1u, 94u,
- 158u, 181u, 141u, 152u,
- 66u, 138u, 32u, 158u,
- 118u, 30u, 144u, 135u,
- 69u, 150u, 41u, 177u,
- 1u, 190u, 45u, 145u,
- 173u, 84u, 126u, 194u,
- 139u, 139u, 117u, 74u,
- 0u, 142u, 108u, 136u,
- 176u, 225u, 126u, 105u,
- 165u, 164u, 213u, 24u,
- 255u, 73u, 141u, 114u,
- 138u, 144u, 103u, 106u,
- 131u, 226u, 139u, 101u,
- 56u, 128u, 12u, 173u,
- 183u, 82u, 110u, 98u,
- 135u, 111u, 30u, 86u,
- 255u, 93u, 119u, 118u,
- 158u, 219u, 201u, 0u,
- 161u, 181u, 5u, 100u,
- 14u, 71u, 173u, 77u,
- 134u, 148u, 237u, 223u,
- 72u, 175u, 109u, 94u,
- 153u, 174u, 135u, 201u,
- 255u, 192u, 181u, 176u,
- 183u, 78u, 116u, 44u,
- 118u, 75u, 91u, 212u,
- 129u, 80u, 207u, 154u,
- 51u, 215u, 81u, 58u,
- 193u, 63u, 221u, 1u,
- 153u, 159u, 189u, 58u,
- 144u, 185u, 255u, 127u,
- 73u, 106u, 207u, 230u,
- 111u, 202u, 75u, 99u,
- 50u, 125u, 63u, 1u,
- 142u, 112u, 193u, 225u,
- 116u, 250u, 136u, 157u,
- 166u, 61u, 121u, 176u,
- 122u, 120u, 134u, 129u,
- 255u, 132u, 157u, 148u,
- 202u, 22u, 46u, 175u,
- 232u, 169u, 147u, 17u,
- 0u, 122u, 84u, 161u,
- 87u, 148u, 168u, 94u,
- 83u, 132u, 28u, 59u,
- 61u, 214u, 167u, 130u,
- 255u, 131u, 232u, 238u,
- 192u, 120u, 172u, 152u,
- 111u, 219u, 34u, 204u,
- 197u, 110u, 8u, 140u,
- 53u, 164u, 178u, 213u,
- 110u, 136u, 1u, 57u,
- 13u, 99u, 231u, 148u,
- 184u, 134u, 110u, 197u,
- 190u, 97u, 94u, 155u,
- 33u, 28u, 173u, 67u,
- 139u, 113u, 204u, 255u,
- 73u, 46u, 146u, 178u,
- 140u, 136u, 163u, 176u,
- 209u, 138u, 48u, 1u,
- 175u, 91u, 138u, 99u,
- 187u, 153u, 109u, 130u,
- 125u, 101u, 202u, 163u,
- 255u, 129u, 126u, 82u,
- 170u, 162u, 39u, 48u,
- 160u, 194u, 169u, 56u,
- 13u, 152u, 122u, 58u,
- 203u, 102u, 157u, 207u,
- 97u, 255u, 246u, 144u,
- 86u, 167u, 101u, 144u,
- 101u, 117u, 136u, 255u,
- 144u, 41u, 74u, 73u,
- 162u, 55u, 86u, 26u,
- 97u, 129u, 137u, 61u,
- 27u, 57u, 56u, 190u,
- 1u, 151u, 49u, 180u,
- 123u, 197u, 88u, 108u,
- 136u, 21u, 141u, 220u,
- 255u, 70u, 64u, 149u,
- 77u, 89u, 109u, 32u,
- 205u, 109u, 148u, 27u,
- 192u, 177u, 85u, 78u,
- 32u, 128u, 0u, 160u,
- 115u, 109u, 145u, 163u,
- 114u, 70u, 38u, 79u,
- 15u, 116u, 156u, 164u,
- 121u, 59u, 101u, 47u,
- 127u, 104u, 166u, 255u,
- 99u, 115u, 199u, 138u,
- 72u, 101u, 101u, 120u,
- 145u, 255u, 215u, 42u,
- 198u, 129u, 45u, 171u,
- 141u, 143u, 165u, 157u,
- 140u, 75u, 44u, 217u,
- 33u, 138u, 235u, 177u,
- 213u, 175u, 255u, 217u,
- 146u, 113u, 130u, 49u,
- 175u, 171u, 104u, 79u,
- 146u, 34u, 114u, 31u,
- 63u, 44u, 231u, 205u,
- 148u, 255u, 128u, 130u,
- 153u, 65u, 145u, 101u,
- 199u, 168u, 113u, 167u,
- 160u, 92u, 120u, 1u,
- 117u, 150u, 165u, 146u,
- 196u, 172u, 142u, 105u,
- 99u, 125u, 176u, 58u,
- 168u, 1u, 120u, 123u,
- 85u, 138u, 100u, 64u,
- 75u, 109u, 186u, 156u,
- 170u, 162u, 0u, 111u,
- 146u, 119u, 130u, 125u,
- 118u, 175u, 188u, 95u,
- 115u, 81u, 77u, 187u,
- 14u, 158u, 169u, 18u,
- 143u, 86u, 199u, 44u,
- 122u, 122u, 178u, 255u,
- 96u, 103u, 112u, 214u,
- 137u, 134u, 228u, 81u,
- 170u, 54u, 25u, 45u,
- 196u, 255u, 144u, 140u,
- 171u, 137u, 100u, 141u,
- 192u, 108u, 104u, 170u,
- 58u, 147u, 1u, 147u,
- 95u, 235u, 197u, 160u,
- 215u, 145u, 210u, 11u,
- 110u, 46u, 101u, 102u,
- 255u, 69u, 99u, 143u,
- 249u, 88u, 40u, 69u,
- 64u, 50u, 108u, 127u,
- 71u, 32u, 255u, 218u,
- 229u, 155u, 128u, 86u,
- 97u, 162u, 7u, 123u,
- 32u, 77u, 53u, 238u,
- 178u, 67u, 103u, 211u,
- 194u, 89u, 199u, 148u,
- 88u, 183u, 17u, 115u,
- 122u, 0u, 136u, 104u,
- 202u, 56u, 112u, 180u,
- 255u, 46u, 125u, 57u,
- 115u, 152u, 76u, 189u,
- 173u, 142u, 152u, 216u,
- 55u, 195u, 208u, 104u,
- 136u, 147u, 255u, 122u,
- 11u, 202u, 75u, 224u,
- 160u, 210u, 165u, 231u,
- 89u, 107u, 255u, 90u,
- 52u, 131u, 78u, 102u,
- 154u, 167u, 17u, 106u,
- 11u, 74u, 176u, 239u,
- 207u, 144u, 46u, 77u,
- 109u, 197u, 143u, 90u,
- 155u, 126u, 131u, 114u,
- 182u, 255u, 113u, 107u,
- 159u, 1u, 108u, 95u,
- 139u, 39u, 154u, 95u,
- 150u, 145u, 158u, 142u,
- 166u, 113u, 199u, 95u,
- 129u, 114u, 112u, 119u,
- 255u, 94u, 133u, 218u,
- 225u, 183u, 114u, 103u,
- 125u, 166u, 147u, 78u,
- 69u, 255u, 100u, 158u,
- 116u, 162u, 16u, 28u,
- 42u, 158u, 109u, 203u,
- 79u, 32u, 173u, 126u,
- 160u, 83u, 232u, 159u,
- 85u, 164u, 0u, 196u,
- 155u, 141u, 146u, 67u,
- 130u, 108u, 86u, 85u,
- 123u, 111u, 72u, 157u,
- 105u, 48u, 255u, 78u,
- 43u, 205u, 84u, 137u,
- 160u, 110u, 162u, 102u,
- 10u, 73u, 200u, 98u,
- 255u, 165u, 99u, 146u,
- 157u, 132u, 144u, 77u,
- 141u, 189u, 97u, 103u,
- 19u, 146u, 27u, 164u,
- 77u, 120u, 255u, 102u,
- 197u, 172u, 83u, 33u,
- 139u, 107u, 143u, 35u,
- 140u, 121u, 226u, 29u,
- 214u, 125u, 1u, 178u,
- 117u, 124u, 146u, 53u,
- 41u, 84u, 53u, 110u,
- 82u, 191u, 128u, 117u,
- 155u, 58u, 88u, 159u,
- 156u, 155u, 176u, 255u,
- 170u, 120u, 123u, 144u,
- 173u, 127u, 78u, 175u,
- 96u, 1u, 227u, 36u,
- 147u, 81u, 222u, 156u,
- 86u, 28u, 94u, 47u,
- 165u, 80u, 225u, 99u,
- 207u, 219u, 176u, 63u,
- 114u, 133u, 197u, 128u,
- 79u, 255u, 110u, 173u,
- 142u, 125u, 248u, 110u,
- 79u, 66u, 150u, 1u,
- 71u, 149u, 73u, 135u,
- 162u, 110u, 166u, 139u,
- 182u, 61u, 237u, 238u,
- 191u, 205u, 53u, 71u,
- 81u, 141u, 1u, 85u,
- 110u, 245u, 59u, 146u,
- 94u, 113u, 181u, 215u,
- 104u, 202u, 1u, 129u,
- 72u, 106u, 205u, 167u,
- 163u, 127u, 117u, 134u,
- 215u, 83u, 181u, 118u,
- 136u, 33u, 136u, 32u,
- 177u, 92u, 78u, 210u,
- 1u, 57u, 148u, 153u,
- 124u, 165u, 89u, 94u,
- 106u, 1u, 170u, 86u,
- 47u, 189u, 157u, 149u,
- 152u, 154u, 221u, 156u,
- 153u, 163u, 48u, 241u,
- 1u, 150u, 111u, 237u,
- 204u, 136u, 180u, 87u,
- 210u, 22u, 128u, 175u,
- 169u, 85u, 183u, 136u,
- 12u, 236u, 110u, 1u,
- 89u, 191u, 111u, 174u,
- 194u, 122u, 46u, 170u,
- 46u, 159u, 149u, 105u,
- 128u, 134u, 0u, 136u,
- 117u, 83u, 160u, 97u,
- 54u, 123u, 42u, 159u,
- 134u, 193u, 255u, 183u,
- 138u, 179u, 184u, 72u,
- 78u, 108u, 97u, 70u,
- 114u, 187u, 233u, 47u,
- 117u, 141u, 163u, 166u,
- 30u, 213u, 127u, 168u,
- 66u, 183u, 255u, 220u,
- 158u, 129u, 45u, 140u,
- 170u, 169u, 120u, 99u,
- 130u, 47u, 91u, 170u,
- 82u, 21u, 178u, 172u,
- 110u, 83u, 209u, 0u,
- 179u, 255u, 39u, 126u,
- 246u, 192u, 142u, 160u,
- 73u, 99u, 99u, 107u,
- 101u, 105u, 70u, 171u,
- 118u, 178u, 142u, 105u,
- 216u, 115u, 189u, 55u,
- 83u, 60u, 50u, 1u,
- 131u, 127u, 248u, 119u,
- 91u, 131u, 73u, 56u,
- 153u, 70u, 157u, 54u,
- 84u, 145u, 175u, 255u,
- 143u, 180u, 171u, 83u,
- 112u, 206u, 158u, 117u,
- 182u, 59u, 213u, 157u,
- 189u, 19u, 218u, 120u,
- 10u, 233u, 120u, 0u,
- 1u, 142u, 71u, 222u,
- 92u, 192u, 187u, 108u,
- 165u, 168u, 143u, 126u,
- 162u, 179u, 124u, 146u,
- 1u, 165u, 57u, 40u,
- 163u, 157u, 178u, 150u,
- 231u, 107u, 192u, 110u,
- 64u, 121u, 110u, 45u,
- 28u, 112u, 21u, 143u,
- 33u, 201u, 244u, 179u,
- 155u, 113u, 123u, 193u,
- 197u, 84u, 90u, 255u,
- 56u, 134u, 86u, 41u,
- 192u, 88u, 35u, 222u,
- 86u, 123u, 152u, 176u,
- 1u, 47u, 117u, 67u,
- 87u, 209u, 76u, 197u,
- 0u, 239u, 52u, 174u,
- 87u, 103u, 78u, 63u,
- 171u, 140u, 20u, 83u,
- 162u, 184u, 120u, 166u,
- 136u, 47u, 78u, 155u,
- 1u, 199u, 168u, 105u,
- 156u, 43u, 151u, 63u,
- 181u, 145u, 140u, 113u,
- 113u, 87u, 158u, 0u,
- 60u, 179u, 77u, 134u,
- 148u, 148u, 121u, 133u,
- 151u, 159u, 91u, 180u,
- 35u, 255u, 160u, 138u,
- 120u, 151u, 238u, 146u,
- 217u, 149u, 142u, 97u,
- 223u, 35u, 230u, 68u,
- 190u, 71u, 1u, 174u,
- 211u, 141u, 119u, 191u,
- 50u, 183u, 196u, 164u,
- 131u, 96u, 255u, 124u,
- 119u, 70u, 145u, 101u,
- 93u, 173u, 117u, 152u,
- 139u, 92u, 142u, 245u,
- 142u, 148u, 180u, 0u,
- 143u, 175u, 80u, 173u,
- 96u, 145u, 130u, 122u,
- 23u, 146u, 62u, 168u,
- 154u, 25u, 117u, 163u,
- 2u, 135u, 255u, 175u,
- 121u, 61u, 49u, 110u,
- 137u, 186u, 10u, 174u,
- 82u, 36u, 0u, 251u,
- 38u, 76u, 108u, 114u,
- 169u, 148u, 121u, 65u,
- 119u, 29u, 151u, 136u,
- 158u, 196u, 74u, 165u,
- 109u, 163u, 130u, 180u,
- 160u, 168u, 255u, 191u,
- 164u, 136u, 178u, 106u,
- 120u, 150u, 156u, 240u,
- 1u, 74u, 163u, 46u,
- 203u, 61u, 109u, 164u,
- 40u, 126u, 44u, 131u,
- 255u, 116u, 155u, 167u,
- 79u, 80u, 99u, 121u,
- 151u, 133u, 143u, 142u,
- 115u, 120u, 133u, 168u,
- 152u, 115u, 255u, 116u,
- 152u, 73u, 88u, 81u,
- 147u, 85u, 195u, 187u,
- 216u, 230u, 167u, 66u,
- 166u, 76u, 1u, 104u,
- 100u, 169u, 106u, 167u,
- 82u, 20u, 79u, 133u,
- 145u, 138u, 187u, 164u,
- 246u, 128u, 218u, 40u,
- 225u, 255u, 108u, 181u,
- 159u, 56u, 137u, 152u,
- 150u, 235u, 51u, 168u,
- 152u, 114u, 1u, 128u,
- 26u, 75u, 42u, 182u,
- 125u, 158u, 215u, 92u,
- 115u, 91u, 230u, 71u,
- 107u, 173u, 43u, 116u,
- 203u, 4u, 51u, 180u,
- 49u, 229u, 142u, 114u,
- 255u, 91u, 187u, 88u,
- 116u, 61u, 49u, 46u,
- 73u, 19u, 81u, 113u,
- 153u, 193u, 109u, 126u,
- 30u, 134u, 255u, 162u,
- 149u, 175u, 148u, 119u,
- 57u, 157u, 255u, 132u,
- 121u, 122u, 156u, 167u,
- 213u, 199u, 175u, 178u,
- 113u, 104u, 58u, 151u,
- 46u, 63u, 229u, 104u,
- 166u, 127u, 185u, 217u,
- 109u, 160u, 136u, 0u,
- 172u, 109u, 143u, 57u,
- 43u, 77u, 130u, 60u,
- 87u, 92u, 23u, 1u,
- 44u, 45u, 120u, 207u,
- 184u, 110u, 191u, 107u,
- 120u, 60u, 193u, 93u,
- 165u, 99u, 111u, 255u,
- 78u, 124u, 162u, 176u,
- 99u, 143u, 88u, 144u,
- 217u, 24u, 189u, 70u,
- 204u, 118u, 112u, 173u,
- 1u, 254u, 37u, 93u,
- 151u, 100u, 110u, 45u,
- 255u, 54u, 76u, 128u,
- 69u, 114u, 147u, 231u,
- 169u, 171u, 104u, 96u,
- 17u, 69u, 87u, 79u,
- 196u, 79u, 80u, 147u,
- 161u, 255u, 100u, 127u,
- 86u, 83u, 148u, 49u,
- 122u, 156u, 93u, 87u,
- 160u, 157u, 236u, 212u,
- 255u, 138u, 150u, 209u,
- 168u, 115u, 50u, 141u,
- 206u, 71u, 162u, 128u,
- 168u, 154u, 127u, 77u,
- 115u, 155u, 191u, 69u,
- 255u, 128u, 158u, 47u,
- 193u, 121u, 123u, 67u,
- 110u, 120u, 134u, 255u,
- 100u, 113u, 106u, 160u,
- 108u, 93u, 130u, 171u,
- 155u, 103u, 136u, 135u,
- 114u, 167u, 0u, 126u,
- 189u, 82u, 220u, 107u,
- 106u, 120u, 132u, 222u,
- 132u, 215u, 155u, 126u,
- 1u, 99u, 118u, 207u,
- 111u, 130u, 105u, 52u,
- 52u, 103u, 138u, 146u,
- 138u, 62u, 190u, 113u,
- 211u, 156u, 255u, 26u,
- 157u, 162u, 53u, 104u,
- 158u, 169u, 186u, 230u,
- 76u, 105u, 27u, 255u,
- 65u, 185u, 77u, 93u,
- 182u, 137u, 209u, 61u,
- 139u, 153u, 65u, 211u,
- 89u, 144u, 16u, 1u,
- 161u, 221u, 84u, 184u,
- 128u, 99u, 230u, 77u,
- 129u, 202u, 39u, 134u,
- 187u, 10u, 71u, 106u,
- 195u, 59u, 127u, 187u,
- 52u, 146u, 90u, 0u,
- 49u, 139u, 152u, 49u,
- 242u, 55u, 132u, 73u,
- 1u, 82u, 171u, 214u,
- 6u, 163u, 199u, 130u,
- 49u, 11u, 232u, 184u,
- 53u, 177u, 180u, 142u,
- 255u, 135u, 146u, 183u,
- 236u, 172u, 68u, 163u,
- 207u, 110u, 115u, 214u,
- 227u, 136u, 75u, 191u,
- 1u, 145u, 62u, 162u,
- 159u, 168u, 245u, 180u,
- 76u, 108u, 35u, 167u,
- 118u, 145u, 115u, 61u,
- 132u, 211u, 244u, 189u,
- 153u, 255u, 30u, 93u,
- 172u, 80u, 103u, 141u,
- 91u, 162u, 85u, 91u,
- 83u, 84u, 67u, 76u,
- 182u, 46u, 222u, 0u,
- 105u, 125u, 70u, 22u,
- 60u, 38u, 1u, 199u,
- 156u, 121u, 158u, 178u,
- 139u, 108u, 81u, 172u,
- 103u, 130u, 131u, 150u,
- 241u, 47u, 14u, 228u,
- 191u, 122u, 171u, 32u,
- 255u, 239u, 59u, 31u,
- 39u, 151u, 77u, 136u,
- 134u, 141u, 120u, 127u,
- 106u, 162u, 155u, 1u,
- 89u, 103u, 45u, 174u,
- 128u, 151u, 141u, 193u,
- 235u, 55u, 85u, 57u,
- 213u, 116u, 117u, 120u,
- 186u, 255u, 194u, 168u,
- 232u, 125u, 29u, 81u,
- 134u, 174u, 149u, 255u,
- 115u, 152u, 141u, 100u,
- 121u, 57u, 64u, 87u,
- 88u, 85u, 149u, 120u,
- 147u, 176u, 148u, 84u,
- 219u, 120u, 54u, 130u,
- 1u, 130u, 182u, 188u,
- 237u, 114u, 56u, 97u,
- 147u, 118u, 13u, 141u,
- 38u, 210u, 1u, 204u,
- 86u, 99u, 183u, 94u,
- 97u, 175u, 8u, 78u,
- 36u, 190u, 137u, 119u,
- 85u, 180u, 127u, 197u,
- 166u, 0u, 181u, 166u,
- 182u, 129u, 171u, 76u,
- 221u, 186u, 118u, 96u,
- 115u, 75u, 109u, 99u,
- 116u, 76u, 219u, 178u,
- 163u, 255u, 144u, 160u,
- 102u, 147u, 204u, 150u,
- 125u, 58u, 81u, 47u,
- 168u, 49u, 159u, 138u,
- 255u, 132u, 69u, 157u,
- 107u, 98u, 106u, 205u,
- 72u, 143u, 113u, 111u,
- 166u, 66u, 114u, 0u,
- 75u, 107u, 142u, 145u,
- 205u, 129u, 123u, 0u,
- 145u, 58u, 165u, 221u,
- 126u, 126u, 123u, 190u,
- 125u, 149u, 95u, 208u,
- 44u, 29u, 125u, 121u,
- 146u, 169u, 117u, 122u,
- 131u, 1u, 117u, 108u,
- 95u, 184u, 135u, 127u,
- 144u, 168u, 200u, 120u,
- 78u, 48u, 181u, 29u,
- 23u, 255u, 171u, 199u,
- 199u, 178u, 87u, 51u,
- 99u, 131u, 73u, 238u,
- 23u, 71u, 122u, 189u,
- 1u, 131u, 159u, 122u,
- 191u, 46u, 92u, 226u,
- 194u, 152u, 61u, 1u,
- 132u, 122u, 54u, 162u,
- 192u, 160u, 153u, 123u,
- 131u, 114u, 176u, 130u,
- 220u, 98u, 77u, 107u,
- 169u, 86u, 172u, 199u,
- 103u, 212u, 2u, 5u,
- 255u, 167u, 182u, 52u,
- 142u, 88u, 158u, 159u,
- 186u, 138u, 75u, 148u,
- 177u, 152u, 127u, 122u,
- 255u, 57u, 185u, 156u,
- 136u, 17u, 101u, 17u,
- 71u, 74u, 84u, 175u,
- 209u, 170u, 97u, 47u,
- 0u, 20u, 4u, 138u,
- 80u, 217u, 219u, 115u,
- 140u, 131u, 104u, 70u,
- 76u, 0u, 155u, 176u,
- 55u, 59u, 159u, 190u,
- 146u, 173u, 94u, 1u,
- 61u, 138u, 159u, 201u,
- 57u, 89u, 117u, 49u,
- 95u, 69u, 84u, 190u,
- 161u, 120u, 133u, 125u,
- 239u, 90u, 80u, 144u,
- 68u, 134u, 32u, 255u,
- 152u, 125u, 125u, 191u,
- 201u, 123u, 194u, 49u,
- 120u, 125u, 181u, 154u,
- 1u, 155u, 33u, 111u,
- 117u, 183u, 114u, 134u,
- 255u, 143u, 155u, 157u,
- 124u, 155u, 136u, 99u,
- 137u, 172u, 122u, 121u,
- 246u, 94u, 143u, 114u,
- 97u, 128u, 123u, 62u,
- 135u, 227u, 79u, 174u,
- 177u, 234u, 222u, 113u,
- 110u, 1u, 235u, 126u,
- 174u, 74u, 129u, 158u,
- 132u, 165u, 1u, 161u,
- 96u, 24u, 174u, 74u,
- 72u, 128u, 95u, 166u,
- 109u, 183u, 127u, 93u,
- 119u, 148u, 69u, 156u,
- 1u, 111u, 231u, 142u,
- 106u, 96u, 132u, 166u,
- 12u, 184u, 10u, 95u,
- 101u, 90u, 86u, 28u,
- 89u, 72u, 84u, 1u,
- 57u, 144u, 145u, 165u,
- 100u, 137u, 140u, 205u,
- 218u, 183u, 64u, 75u,
- 87u, 129u, 216u, 132u,
- 190u, 255u, 176u, 113u,
- 198u, 148u, 55u, 184u,
- 192u, 78u, 86u, 124u,
- 188u, 23u, 169u, 133u,
- 161u, 255u, 67u, 244u,
- 1u, 171u, 46u, 144u,
- 74u, 95u, 184u, 41u,
- 17u, 225u, 156u, 111u,
- 224u, 77u, 112u, 80u,
- 75u, 211u, 32u, 118u,
- 137u, 1u, 135u, 194u,
- 255u, 219u, 78u, 116u,
- 156u, 160u, 200u, 113u,
- 173u, 159u, 81u, 55u,
- 125u, 169u, 181u, 126u,
- 180u, 227u, 208u, 123u,
- 255u, 184u, 122u, 43u,
- 74u, 229u, 1u, 94u,
- 89u, 56u, 78u, 221u,
- 118u, 217u, 168u, 183u,
- 81u, 130u, 169u, 6u,
- 108u, 20u, 113u, 143u,
- 222u, 51u, 253u, 94u,
- 167u, 182u, 152u, 255u,
- 165u, 78u, 125u, 227u,
- 121u, 201u, 163u, 86u,
- 2u, 142u, 217u, 145u,
- 81u, 230u, 179u, 138u,
- 168u, 150u, 251u, 255u,
- 150u, 149u, 108u, 156u,
- 131u, 190u, 91u, 1u,
- 85u, 89u, 96u, 105u,
- 130u, 202u, 160u, 191u,
- 58u, 60u, 130u, 167u,
- 68u, 118u, 156u, 88u,
- 180u, 181u, 123u, 140u,
- 1u, 180u, 43u, 125u,
- 240u, 1u, 25u, 197u,
- 28u, 106u, 203u, 151u,
- 143u, 31u, 160u, 115u,
- 243u, 243u, 21u, 113u,
- 1u, 152u, 89u, 119u,
- 123u, 76u, 149u, 245u,
- 85u, 110u, 129u, 101u,
- 174u, 75u, 58u, 119u,
- 94u, 198u, 169u, 83u,
- 164u, 113u, 90u, 143u,
- 72u, 184u, 255u, 169u,
- 154u, 113u, 180u, 178u,
- 1u, 131u, 123u, 202u,
- 142u, 217u, 203u, 156u,
- 183u, 149u, 104u, 206u,
- 153u, 129u, 32u, 243u,
- 152u, 142u, 85u, 217u,
- 149u, 51u, 81u, 83u,
- 120u, 60u, 143u, 114u,
- 1u, 140u, 26u, 157u,
- 136u, 104u, 223u, 86u,
- 80u, 86u, 235u, 77u,
- 194u, 45u, 95u, 211u,
- 196u, 0u, 196u, 186u,
- 162u, 190u, 12u, 225u,
- 117u, 186u, 133u, 17u,
- 125u, 6u, 124u, 157u,
- 156u, 227u, 96u, 255u,
- 78u, 87u, 215u, 103u,
- 86u, 239u, 151u, 5u,
- 110u, 162u, 0u, 129u,
- 38u, 174u, 55u, 146u,
- 138u, 172u, 95u, 0u,
- 174u, 224u, 135u, 171u,
- 112u, 98u, 136u, 161u,
- 212u, 194u, 119u, 152u,
- 109u, 173u, 14u, 233u,
- 51u, 70u, 144u, 142u,
- 123u, 76u, 182u, 77u,
- 86u, 1u, 168u, 133u,
- 1u, 13u, 128u, 159u,
- 66u, 201u, 240u, 125u,
- 104u, 89u, 28u, 139u,
- 91u, 187u, 226u, 79u,
- 114u, 73u, 46u, 88u,
- 239u, 237u, 1u, 234u,
- 7u, 201u, 85u, 164u,
- 137u, 154u, 102u, 109u,
- 113u, 255u, 182u, 103u,
- 148u, 173u, 93u, 76u,
- 44u, 152u, 237u, 93u,
- 101u, 139u, 51u, 180u,
- 58u, 119u, 66u, 91u,
- 92u, 93u, 38u, 77u,
- 40u, 118u, 255u, 148u,
- 133u, 35u, 251u, 211u,
- 243u, 137u, 178u, 123u,
- 184u, 194u, 197u, 47u,
- 154u, 125u, 149u, 213u,
- 199u, 74u, 255u, 176u,
- 163u, 209u, 228u, 166u,
- 150u, 177u, 178u, 169u,
- 1u, 139u, 6u, 121u,
- 188u, 148u, 30u, 119u,
- 187u, 159u, 178u, 146u,
- 83u, 91u, 82u, 155u,
- 142u, 99u, 105u, 72u,
- 145u, 1u, 82u, 115u,
- 144u, 118u, 194u, 72u,
- 30u, 88u, 142u, 81u,
- 174u, 136u, 126u, 62u,
- 67u, 104u, 1u, 134u,
- 234u, 106u, 125u, 74u,
- 122u, 83u, 124u, 0u,
- 61u, 164u, 128u, 137u,
- 233u, 122u, 44u, 114u,
- 238u, 123u, 255u, 40u,
- 46u, 22u, 65u, 165u,
- 180u, 228u, 203u, 115u,
- 188u, 31u, 157u, 63u,
- 144u, 137u, 255u, 118u,
- 209u, 89u, 152u, 77u,
- 166u, 105u, 173u, 191u,
- 140u, 159u, 118u, 51u,
- 44u, 139u, 175u, 8u,
- 188u, 36u, 141u, 198u,
- 177u, 202u, 255u, 75u,
- 104u, 123u, 198u, 79u,
- 104u, 243u, 96u, 203u,
- 127u, 69u, 123u, 170u,
- 216u, 1u, 129u, 212u,
- 134u, 218u, 134u, 0u,
- 133u, 119u, 111u, 65u,
- 209u, 81u, 147u, 56u,
- 125u, 67u, 1u, 91u,
- 5u, 147u, 132u, 121u,
- 6u, 169u, 44u, 200u,
- 129u, 1u, 105u, 184u,
- 48u, 152u, 108u, 217u,
- 44u, 106u, 175u, 90u,
- 66u, 60u, 124u, 164u,
- 80u, 112u, 137u, 97u,
- 1u, 143u, 28u, 79u,
- 108u, 107u, 41u, 199u,
- 182u, 155u, 93u, 1u,
- 190u, 140u, 143u, 195u,
- 143u, 107u, 70u, 18u,
- 77u, 142u, 205u, 159u,
- 93u, 76u, 179u, 150u,
- 96u, 116u, 193u, 115u,
- 98u, 170u, 87u, 154u,
- 130u, 1u, 94u, 178u,
- 188u, 188u, 191u, 255u,
- 194u, 114u, 189u, 155u,
- 177u, 140u, 134u, 165u,
- 66u, 220u, 63u, 69u,
- 107u, 130u, 133u, 137u,
- 255u, 149u, 73u, 176u,
- 68u, 254u, 65u, 117u,
- 123u, 141u, 169u, 142u,
- 1u, 133u, 129u, 106u,
- 186u, 73u, 179u, 170u,
- 216u, 152u, 117u, 184u,
- 75u, 61u, 62u, 149u,
- 216u, 128u, 202u, 197u,
- 2u, 33u, 147u, 67u,
- 102u, 240u, 132u, 120u,
- 167u, 153u, 1u, 209u,
- 144u, 147u, 255u, 94u,
- 31u, 141u, 117u, 108u,
- 219u, 104u, 207u, 28u,
- 223u, 49u, 102u, 138u,
- 120u, 97u, 39u, 209u,
- 13u, 87u, 214u, 61u,
- 140u, 163u, 186u, 99u,
- 1u, 190u, 82u, 95u,
- 227u, 200u, 120u, 161u,
- 98u, 200u, 164u, 97u,
- 142u, 169u, 64u, 126u,
- 176u, 255u, 57u, 86u,
- 113u, 171u, 151u, 155u,
- 8u, 178u, 1u, 138u,
- 109u, 141u, 187u, 103u,
- 120u, 35u, 75u, 139u,
- 184u, 84u, 197u, 201u,
- 96u, 65u, 0u, 168u,
- 136u, 53u, 192u, 148u,
- 177u, 189u, 172u, 190u,
- 149u, 129u, 220u, 159u,
- 72u, 42u, 88u, 197u,
- 219u, 221u, 117u, 227u,
- 103u, 93u, 154u, 1u,
- 16u, 255u, 167u, 29u,
- 93u, 24u, 13u, 152u,
- 21u, 138u, 163u, 46u,
- 8u, 135u, 197u, 140u,
- 210u, 195u, 168u, 195u,
- 1u, 189u, 177u, 100u,
- 137u, 82u, 180u, 159u,
- 121u, 128u, 83u, 108u,
- 47u, 85u, 36u, 134u,
- 26u, 120u, 237u, 1u,
- 147u, 178u, 222u, 64u,
- 227u, 54u, 189u, 112u,
- 206u, 138u, 99u, 230u,
- 0u, 224u, 179u, 98u,
- 73u, 31u, 61u, 89u,
- 224u, 216u, 25u, 158u,
- 130u, 193u, 200u, 115u,
- 170u, 92u, 126u, 1u,
- 144u, 151u, 122u, 78u,
- 101u, 122u, 106u, 91u,
- 196u, 177u, 158u, 88u,
- 152u, 157u, 255u, 103u,
- 166u, 113u, 110u, 97u,
- 90u, 64u, 93u, 140u,
- 105u, 139u, 99u, 124u,
- 237u, 20u, 76u, 46u,
- 61u, 40u, 255u, 92u,
- 168u, 189u, 158u, 108u,
- 230u, 31u, 106u, 156u,
- 141u, 127u, 184u, 213u,
- 255u, 60u, 150u, 122u,
- 165u, 126u, 131u, 11u,
- 129u, 145u, 42u, 255u,
- 94u, 50u, 94u, 28u,
- 137u, 41u, 161u, 104u,
- 153u, 80u, 138u, 127u,
- 111u, 176u, 168u, 70u,
- 140u, 202u, 185u, 91u,
- 128u, 138u, 54u, 104u,
- 59u, 181u, 129u, 255u,
- 255u, 103u, 143u, 50u,
- 86u, 82u, 150u, 122u,
- 129u, 35u, 198u, 150u,
- 109u, 157u, 118u, 125u,
- 132u, 124u, 1u, 124u,
- 120u, 28u, 100u, 173u,
- 133u, 211u, 177u, 72u,
- 88u, 172u, 101u, 252u,
- 162u, 0u, 81u, 173u,
- 116u, 152u, 135u, 134u,
- 172u, 22u, 60u, 130u,
- 25u, 65u, 119u, 234u,
- 104u, 255u, 157u, 171u,
- 177u, 108u, 106u, 132u,
- 156u, 155u, 68u, 70u,
- 94u, 146u, 121u, 21u,
- 211u, 116u, 91u, 137u,
- 136u, 1u, 93u, 105u,
- 104u, 141u, 205u, 86u,
- 172u, 114u, 68u, 37u,
- 255u, 128u, 100u, 117u,
- 96u, 110u, 155u, 120u,
- 28u, 26u, 150u, 53u,
- 187u, 66u, 125u, 146u,
- 59u, 136u, 108u, 100u,
- 23u, 92u, 209u, 162u,
- 185u, 215u, 168u, 131u,
- 107u, 33u, 1u, 148u,
- 16u, 117u, 54u, 90u,
- 98u, 163u, 225u, 232u,
- 120u, 20u, 160u, 189u,
- 1u, 113u, 12u, 143u,
- 58u, 1u, 134u, 181u,
- 54u, 251u, 190u, 1u,
- 237u, 208u, 104u, 164u,
- 171u, 174u, 124u, 127u,
- 232u, 55u, 1u, 95u,
- 59u, 110u, 214u, 38u,
- 130u, 156u, 232u, 208u,
- 219u, 223u, 26u, 88u,
- 183u, 111u, 164u, 108u,
- 49u, 63u, 255u, 190u,
- 208u, 99u, 84u, 98u,
- 89u, 132u, 140u, 53u,
- 218u, 156u, 12u, 249u,
- 23u, 151u, 172u, 201u,
- 141u, 65u, 115u, 159u,
- 133u, 130u, 1u, 94u,
- 49u, 174u, 255u, 120u,
- 198u, 61u, 68u, 30u,
- 134u, 33u, 134u, 89u,
- 48u, 165u, 191u, 80u,
- 123u, 138u, 132u, 163u,
- 255u, 45u, 215u, 142u,
- 129u, 133u, 73u, 152u,
- 171u, 36u, 144u, 47u,
- 94u, 196u, 111u, 159u,
- 93u, 200u, 185u, 127u,
- 123u, 114u, 149u, 172u,
- 255u, 103u, 161u, 4u,
- 106u, 167u, 90u, 32u,
- 255u, 214u, 80u, 231u,
- 175u, 118u, 218u, 198u,
- 201u, 134u, 48u, 130u,
- 224u, 247u, 17u, 40u,
- 46u, 101u, 66u, 255u,
- 139u, 136u, 250u, 97u,
- 16u, 164u, 135u, 190u,
- 103u, 48u, 197u, 73u,
- 241u, 106u, 186u, 64u,
- 25u, 159u, 71u, 130u,
- 255u, 181u, 174u, 147u,
- 160u, 92u, 121u, 198u,
- 69u, 190u, 76u, 255u,
- 204u, 164u, 242u, 212u,
- 172u, 183u, 118u, 141u,
- 97u, 153u, 1u, 200u,
- 60u, 63u, 93u, 94u,
- 95u, 135u, 95u, 202u,
- 77u, 152u, 126u, 146u,
- 187u, 114u, 0u, 27u,
- 117u, 255u, 214u, 101u,
- 195u, 195u, 123u, 159u,
- 86u, 179u, 65u, 194u,
- 138u, 151u, 176u, 160u,
- 80u, 144u, 74u, 169u,
- 79u, 165u, 141u, 0u,
- 80u, 71u, 106u, 147u,
- 51u, 78u, 193u, 90u,
- 150u, 78u, 208u, 139u,
- 91u, 255u, 98u, 163u,
- 117u, 151u, 137u, 110u,
- 169u, 112u, 71u, 190u,
- 61u, 64u, 51u, 114u,
- 70u, 255u, 105u, 66u,
- 67u, 15u, 120u, 121u,
- 166u, 105u, 230u, 114u,
- 255u, 155u, 118u, 78u,
- 90u, 148u, 90u, 157u,
- 197u, 154u, 153u, 209u,
- 113u, 141u, 125u, 221u,
- 135u, 105u, 163u, 9u,
- 120u, 126u, 135u, 226u,
- 143u, 128u, 255u, 230u,
- 127u, 182u, 87u, 10u,
- 128u, 57u, 95u, 236u,
- 143u, 157u, 119u, 159u,
- 1u, 64u, 90u, 143u,
- 127u, 154u, 96u, 102u,
- 147u, 91u, 129u, 255u,
- 137u, 99u, 166u, 124u,
- 81u, 67u, 125u, 137u,
- 255u, 153u, 93u, 185u,
- 204u, 55u, 95u, 153u,
- 67u, 60u, 186u, 137u,
- 218u, 250u, 223u, 76u,
- 255u, 150u, 213u, 96u,
- 113u, 116u, 177u, 170u,
- 145u, 104u, 85u, 107u,
- 95u, 85u, 84u, 114u,
- 92u, 170u, 199u, 1u,
- 147u, 35u, 179u, 176u,
- 212u, 138u, 182u, 228u,
- 182u, 110u, 204u, 102u,
- 236u, 246u, 110u, 99u,
- 158u, 92u, 97u, 185u,
- 149u, 154u, 201u, 122u,
- 98u, 106u, 1u, 128u,
- 137u, 136u, 95u, 115u,
- 193u, 157u, 185u, 97u,
- 192u, 45u, 93u, 80u,
- 98u, 178u, 61u, 255u,
- 1u, 123u, 129u, 169u,
- 241u, 83u, 61u, 86u,
- 55u, 130u, 240u, 139u,
- 99u, 79u, 35u, 243u,
- 187u, 126u, 137u, 173u,
- 101u, 252u, 81u, 191u,
- 62u, 1u, 105u, 225u,
- 88u, 187u, 252u, 210u,
- 61u, 27u, 225u, 25u,
- 28u, 102u, 153u, 217u,
- 160u, 165u, 159u, 0u,
- 211u, 39u, 104u, 85u,
- 71u, 193u, 192u, 172u,
- 152u, 126u, 255u, 69u,
- 98u, 40u, 135u, 121u,
- 150u, 206u, 189u, 93u,
- 152u, 66u, 98u, 199u,
- 8u, 64u, 170u, 1u,
- 93u, 177u, 100u, 38u,
- 150u, 87u, 73u, 235u,
- 139u, 54u, 29u, 254u,
- 255u, 100u, 128u, 212u,
- 191u, 67u, 47u, 79u,
- 123u, 246u, 176u, 214u,
- 0u, 91u, 155u, 161u,
- 118u, 101u, 93u, 77u,
- 108u, 189u, 170u, 124u,
- 103u, 90u, 73u, 171u,
- 103u, 180u, 127u, 140u,
- 45u, 123u, 1u, 81u,
- 61u, 162u, 175u, 19u,
- 71u, 112u, 213u, 136u,
- 16u, 146u, 234u, 112u,
- 193u, 45u, 244u, 137u,
- 98u, 102u, 128u, 235u,
- 57u, 255u, 181u, 143u,
- 186u, 3u, 124u, 203u,
- 1u, 68u, 13u, 135u,
- 90u, 128u, 200u, 80u,
- 194u, 109u, 154u, 249u,
- 188u, 136u, 225u, 153u,
- 97u, 46u, 245u, 145u,
- 125u, 116u, 255u, 77u,
- 143u, 236u, 131u, 90u,
- 198u, 127u, 120u, 251u,
- 150u, 15u, 159u, 176u,
- 1u, 138u, 50u, 173u,
- 41u, 63u, 89u, 187u,
- 90u, 54u, 0u, 211u,
- 127u, 161u, 106u, 113u,
- 212u, 40u, 181u, 224u,
- 95u, 255u, 71u, 117u,
- 101u, 68u, 207u, 152u,
- 159u, 103u, 102u, 162u,
- 140u, 178u, 173u, 99u,
- 183u, 1u, 91u, 211u,
- 129u, 214u, 202u, 123u,
- 154u, 222u, 148u, 171u,
- 155u, 1u, 69u, 79u,
- 115u, 132u, 113u, 122u,
- 182u, 90u, 129u, 196u,
- 66u, 142u, 196u, 0u,
- 170u, 67u, 162u, 183u,
- 226u, 227u, 202u, 79u,
- 180u, 12u, 161u, 255u,
- 243u, 178u, 84u, 124u,
- 201u, 135u, 26u, 207u,
- 233u, 178u, 46u, 101u,
- 50u, 255u, 169u, 156u,
- 176u, 136u, 151u, 179u,
- 189u, 214u, 141u, 177u,
- 194u, 44u, 53u, 198u,
- 83u, 165u, 155u, 110u,
- 126u, 177u, 166u, 1u,
- 109u, 133u, 174u, 214u,
- 200u, 111u, 156u, 153u,
- 231u, 101u, 38u, 175u,
- 54u, 135u, 125u, 210u,
- 86u, 238u, 66u, 54u,
- 202u, 227u, 36u, 0u,
- 160u, 172u, 84u, 179u,
- 25u, 132u, 198u, 111u,
- 180u, 150u, 241u, 141u,
- 175u, 42u, 25u, 0u,
- 166u, 124u, 221u, 101u,
- 132u, 81u, 249u, 120u,
- 223u, 82u, 175u, 252u,
- 255u, 165u, 1u, 69u,
- 150u, 67u, 78u, 242u,
- 171u, 98u, 215u, 197u,
- 140u, 255u, 97u, 142u,
- 216u, 110u, 84u, 60u,
- 193u, 126u, 85u, 102u,
- 255u, 95u, 61u, 99u,
- 255u, 243u, 204u, 227u,
- 169u, 142u, 189u, 62u,
- 119u, 67u, 97u, 178u,
- 202u, 106u, 30u, 20u,
- 144u, 92u, 204u, 255u,
- 187u, 205u, 168u, 120u,
- 255u, 89u, 211u, 65u,
- 117u, 139u, 149u, 229u,
- 179u, 65u, 150u, 113u,
- 41u, 187u, 37u, 67u,
- 146u, 132u, 79u, 151u,
- 130u, 151u, 197u, 138u,
- 69u, 229u, 70u, 162u,
- 123u, 255u, 92u, 87u,
- 108u, 137u, 209u, 172u,
- 130u, 176u, 2u, 95u,
- 152u, 1u, 182u, 88u,
- 81u, 60u, 81u, 159u,
- 134u, 158u, 154u, 67u,
- 134u, 82u, 222u, 122u,
- 24u, 143u, 83u, 202u,
- 128u, 255u, 76u, 166u,
- 105u, 235u, 156u, 30u,
- 222u, 137u, 201u, 127u,
- 0u, 57u, 142u, 139u,
- 231u, 249u, 205u, 212u,
- 115u, 142u, 79u, 136u,
- 121u, 150u, 183u, 129u,
- 115u, 128u, 59u, 64u,
- 160u, 0u, 131u, 78u,
- 224u, 147u, 179u, 78u,
- 52u, 164u, 128u, 176u,
- 135u, 220u, 140u, 195u,
- 255u, 108u, 251u, 83u,
- 102u, 86u, 87u, 112u,
- 148u, 148u, 119u, 134u,
- 89u, 102u, 155u, 217u,
- 163u, 255u, 148u, 100u,
- 156u, 153u, 102u, 159u,
- 154u, 150u, 137u, 224u,
- 141u, 10u, 190u, 224u,
- 0u, 121u, 71u, 78u,
- 155u, 27u, 168u, 129u,
- 132u, 95u, 212u, 118u,
- 117u, 237u, 12u, 122u,
- 138u, 166u, 220u, 255u,
- 108u, 117u, 38u, 110u,
- 61u, 141u, 139u, 162u,
- 169u, 109u, 255u, 180u,
- 197u, 38u, 204u, 112u,
- 187u, 127u, 87u, 123u,
- 115u, 144u, 255u, 212u,
- 125u, 119u, 88u, 166u,
- 157u, 135u, 167u, 84u,
- 194u, 116u, 101u, 107u,
- 255u, 150u, 106u, 130u,
- 158u, 167u, 67u, 68u,
- 125u, 113u, 159u, 130u,
- 34u, 115u, 118u, 255u,
- 76u, 158u, 93u, 123u,
- 173u, 144u, 13u, 156u,
- 254u, 205u, 175u, 106u,
- 127u, 116u, 53u, 111u,
- 194u, 44u, 255u, 111u,
- 168u, 112u, 113u, 175u,
- 99u, 188u, 208u, 137u,
- 160u, 148u, 133u, 122u,
- 70u, 182u, 136u, 142u,
- 147u, 126u, 71u, 166u,
- 255u, 128u, 114u, 101u,
- 95u, 73u, 94u, 42u,
- 113u, 54u, 188u, 68u,
- 159u, 168u, 37u, 1u,
- 125u, 69u, 127u, 143u,
- 160u, 255u, 64u, 99u,
- 87u, 78u, 80u, 218u,
- 65u, 196u, 94u, 150u,
- 101u, 165u, 87u, 216u,
- 198u, 110u, 255u, 62u,
- 94u, 69u, 61u, 80u,
- 119u, 157u, 201u, 146u,
- 144u, 125u, 198u, 152u,
- 81u, 72u, 112u, 43u,
- 92u, 96u, 115u, 0u,
- 141u, 121u, 75u, 40u,
- 93u, 166u, 240u, 90u,
- 130u, 70u, 63u, 112u,
- 143u, 139u, 119u, 118u,
- 66u, 44u, 1u, 104u,
- 165u, 94u, 7u, 117u,
- 142u, 98u, 235u, 121u,
- 60u, 63u, 167u, 49u,
- 202u, 226u, 255u, 155u,
- 128u, 181u, 164u, 29u,
- 151u, 108u, 216u, 88u,
- 93u, 113u, 218u, 255u,
- 246u, 77u, 86u, 185u,
- 79u, 115u, 78u, 121u,
- 161u, 74u, 196u, 99u,
- 6u, 184u, 145u, 94u,
- 231u, 99u, 106u, 4u,
- 220u, 255u, 218u, 97u,
- 56u, 76u, 169u, 172u,
- 1u, 107u, 134u, 46u,
- 96u, 206u, 149u, 103u,
- 190u, 23u, 132u, 89u,
- 198u, 118u, 83u, 202u,
- 144u, 107u, 255u, 89u,
- 129u, 144u, 93u, 113u,
- 168u, 188u, 209u, 130u,
- 106u, 123u, 107u, 166u,
- 114u, 14u, 64u, 83u,
- 18u, 237u, 134u, 178u,
- 96u, 188u, 0u, 131u,
- 75u, 155u, 1u, 144u,
- 136u, 144u, 161u, 36u,
- 163u, 180u, 119u, 190u,
- 59u, 115u, 77u, 219u,
- 111u, 166u, 131u, 122u,
- 162u, 1u, 26u, 147u,
- 31u, 36u, 153u, 137u,
- 116u, 62u, 150u, 173u,
- 37u, 89u, 95u, 114u,
- 114u, 37u, 70u, 1u,
- 50u, 167u, 168u, 206u,
- 63u, 149u, 73u, 95u,
- 61u, 1u, 71u, 112u,
- 186u, 148u, 10u, 21u,
- 91u, 127u, 78u, 208u,
- 82u, 74u, 115u, 214u,
- 237u, 178u, 83u, 20u,
- 87u, 94u, 122u, 255u,
- 115u, 130u, 203u, 178u,
- 0u, 140u, 104u, 172u,
- 255u, 77u, 73u, 255u,
- 144u, 104u, 198u, 41u,
- 111u, 22u, 49u, 117u,
- 204u, 90u, 154u, 123u,
- 141u, 52u, 190u, 138u,
- 1u, 201u, 175u, 85u,
- 73u, 108u, 84u, 174u,
- 226u, 32u, 70u, 134u,
- 145u, 168u, 255u, 19u,
- 161u, 95u, 85u, 158u,
- 160u, 223u, 170u, 81u,
- 4u, 26u, 186u, 135u,
- 133u, 146u, 167u, 119u,
- 159u, 131u, 155u, 153u,
- 105u, 1u, 91u, 214u,
- 91u, 207u, 158u, 131u,
- 98u, 255u, 162u, 46u,
- 175u, 126u, 72u, 217u,
- 181u, 165u, 151u, 109u,
- 152u, 21u, 162u, 88u,
- 76u, 86u, 92u, 204u,
- 144u, 77u, 85u, 136u,
- 255u, 183u, 48u, 121u,
- 78u, 75u, 130u, 110u,
- 159u, 124u, 119u, 65u,
- 157u, 144u, 110u, 49u,
- 255u, 60u, 99u, 127u,
- 101u, 72u, 142u, 222u,
- 123u, 194u, 17u, 214u,
- 51u, 66u, 75u, 114u,
- 155u, 58u, 248u, 102u,
- 17u, 16u, 135u, 1u,
- 112u, 122u, 130u, 109u,
- 170u, 88u, 127u, 94u,
- 70u, 1u, 70u, 47u,
- 189u, 132u, 168u, 23u,
- 174u, 145u, 68u, 35u,
- 60u, 106u, 255u, 194u,
- 82u, 176u, 140u, 155u,
- 149u, 136u, 226u, 99u,
- 137u, 113u, 149u, 255u,
- 180u, 117u, 149u, 22u,
- 129u, 129u, 137u, 156u,
- 145u, 66u, 120u, 197u,
- 135u, 151u, 125u, 139u,
- 128u, 155u, 125u, 202u,
- 111u, 82u, 56u, 109u,
- 34u, 75u, 81u, 255u,
- 14u, 49u, 168u, 243u,
- 237u, 197u, 150u, 19u,
- 126u, 230u, 186u, 244u,
- 144u, 7u, 1u, 98u,
- 85u, 209u, 1u, 40u,
- 137u, 32u, 126u, 99u,
- 159u, 42u, 151u, 119u,
- 155u, 200u, 154u, 108u,
- 79u, 177u, 67u, 135u,
- 94u, 150u, 191u, 167u,
- 68u, 255u, 75u, 107u,
- 205u, 77u, 99u, 23u,
- 160u, 142u, 43u, 208u,
- 122u, 124u, 59u, 142u,
- 170u, 21u, 132u, 67u,
- 129u, 255u, 139u, 56u,
- 73u, 222u, 91u, 182u,
- 46u, 133u, 185u, 208u,
- 150u, 111u, 221u, 130u,
- 72u, 156u, 255u, 163u,
- 182u, 73u, 165u, 79u,
- 255u, 64u, 230u, 104u,
- 226u, 159u, 60u, 188u,
- 90u, 185u, 60u, 77u,
- 135u, 172u, 201u, 0u,
- 244u, 192u, 78u, 63u,
- 103u, 81u, 156u, 179u,
- 202u, 170u, 59u, 134u,
- 158u, 130u, 49u, 104u,
- 110u, 69u, 228u, 61u,
- 109u, 113u, 45u, 145u,
- 140u, 152u, 255u, 103u,
- 138u, 255u, 123u, 233u,
- 104u, 180u, 132u, 104u,
- 182u, 241u, 226u, 156u,
- 158u, 158u, 197u, 177u,
- 192u, 157u, 65u, 153u,
- 169u, 1u, 142u, 111u,
- 126u, 144u, 181u, 152u,
- 181u, 247u, 103u, 90u,
- 88u, 58u, 166u, 86u,
- 105u, 1u, 163u, 71u,
- 79u, 243u, 55u, 100u,
- 81u, 35u, 153u, 78u,
- 47u, 76u, 97u, 144u,
- 242u, 126u, 132u, 112u,
- 114u, 49u, 68u, 145u,
- 255u, 160u, 120u, 4u,
- 52u, 175u, 180u, 248u,
- 34u, 144u, 98u, 172u,
- 255u, 109u, 78u, 162u,
- 132u, 98u, 170u, 176u,
- 149u, 178u, 147u, 102u,
- 201u, 134u, 80u, 189u,
- 144u, 104u, 173u, 134u,
- 195u, 145u, 20u, 0u,
- 140u, 22u, 176u, 255u,
- 195u, 170u, 248u, 95u,
- 71u, 61u, 1u, 250u,
- 158u, 141u, 46u, 4u,
- 118u, 202u, 255u, 154u,
- 222u, 156u, 89u, 186u,
- 64u, 48u, 103u, 60u,
- 134u, 208u, 34u, 150u,
- 172u, 142u, 56u, 147u,
- 184u, 176u, 163u, 53u,
- 153u, 177u, 1u, 138u,
- 212u, 47u, 242u, 163u,
- 7u, 56u, 108u, 46u,
- 84u, 255u, 188u, 136u,
- 1u, 93u, 51u, 133u,
- 122u, 223u, 213u, 202u,
- 238u, 72u, 101u, 5u,
- 112u, 32u, 105u, 115u,
- 138u, 235u, 130u, 173u,
- 255u, 249u, 244u, 128u,
- 101u, 15u, 94u, 30u,
- 86u, 94u, 150u, 172u,
- 44u, 184u, 165u, 255u,
- 155u, 53u, 98u, 100u,
- 146u, 126u, 120u, 152u,
- 0u, 116u, 117u, 90u,
- 97u, 212u, 88u, 50u,
- 55u, 83u, 58u, 147u,
- 141u, 148u, 212u, 107u,
- 147u, 207u, 110u, 149u,
- 201u, 88u, 150u, 139u,
- 110u, 255u, 48u, 124u,
- 128u, 194u, 209u, 51u,
- 171u, 90u, 99u, 99u,
- 78u, 227u, 104u, 167u,
- 147u, 0u, 88u, 56u,
- 111u, 160u, 140u, 138u,
- 170u, 161u, 81u, 18u,
- 89u, 160u, 156u, 176u,
- 221u, 255u, 91u, 122u,
- 132u, 75u, 221u, 38u,
- 122u, 218u, 104u, 217u,
- 35u, 151u, 166u, 122u,
- 53u, 1u, 110u, 241u,
- 194u, 22u, 176u, 119u,
- 137u, 106u, 54u, 196u,
- 140u, 214u, 92u, 95u,
- 62u, 76u, 1u, 105u,
- 172u, 108u, 136u, 128u,
- 126u, 123u, 33u, 168u,
- 103u, 184u, 106u, 79u,
- 141u, 95u, 0u, 87u,
- 196u, 196u, 123u, 194u,
- 255u, 147u, 64u, 193u,
- 47u, 245u, 122u, 187u,
- 227u, 122u, 179u, 109u,
- 152u, 201u, 126u, 60u,
- 255u, 104u, 165u, 102u,
- 90u, 125u, 110u, 196u,
- 167u, 166u, 118u, 117u,
- 40u, 78u, 114u, 125u,
- 72u, 116u, 143u, 49u,
- 109u, 255u, 143u, 240u,
- 181u, 92u, 55u, 143u,
- 81u, 135u, 106u, 171u,
- 255u, 126u, 221u, 116u,
- 104u, 141u, 17u, 118u,
- 177u, 155u, 119u, 89u,
- 123u, 1u, 130u, 85u,
- 159u, 72u, 143u, 151u,
- 150u, 141u, 127u, 80u,
- 126u, 80u, 114u, 139u,
- 125u, 146u, 93u, 119u,
- 54u, 87u, 136u, 126u,
- 152u, 111u, 255u, 149u,
- 128u, 186u, 131u, 89u,
- 46u, 217u, 169u, 1u,
- 69u, 209u, 90u, 177u,
- 110u, 128u, 40u, 24u,
- 27u, 224u, 159u, 163u,
- 116u, 129u, 183u, 92u,
- 186u, 101u, 195u, 8u,
- 152u, 152u, 55u, 187u,
- 203u, 178u, 150u, 255u,
- 137u, 222u, 137u, 46u,
- 211u, 1u, 210u, 70u,
- 33u, 42u, 144u, 218u,
- 180u, 191u, 55u, 159u,
- 109u, 68u, 75u, 161u,
- 153u, 138u, 127u, 99u,
- 36u, 255u, 83u, 107u,
- 162u, 85u, 185u, 195u,
- 202u, 138u, 0u, 70u,
- 185u, 26u, 193u, 172u,
- 163u, 63u, 100u, 144u,
- 41u, 214u, 63u, 59u,
- 0u, 140u, 129u, 86u,
- 148u, 203u, 55u, 185u,
- 102u, 131u, 220u, 58u,
- 188u, 175u, 158u, 163u,
- 168u, 111u, 137u, 54u,
- 120u, 136u, 163u, 146u,
- 157u, 131u, 242u, 255u,
- 97u, 252u, 69u, 132u,
- 107u, 94u, 124u, 125u,
- 192u, 147u, 58u, 135u,
- 203u, 183u, 169u, 132u,
- 94u, 85u, 255u, 107u,
- 232u, 196u, 162u, 169u,
- 227u, 255u, 168u, 134u,
- 132u, 130u, 109u, 116u,
- 166u, 160u, 124u, 64u,
- 220u, 213u, 167u, 255u,
- 37u, 218u, 25u, 119u,
- 139u, 35u, 234u, 147u,
- 115u, 103u, 194u, 42u,
- 10u, 234u, 157u, 152u,
- 103u, 193u, 70u, 92u,
- 143u, 168u, 224u, 143u,
- 1u, 160u, 139u, 107u,
- 37u, 103u, 110u, 182u,
- 66u, 88u, 247u, 0u,
- 103u, 59u, 99u, 158u,
- 94u, 112u, 63u, 200u,
- 92u, 121u, 62u, 62u,
- 156u, 193u, 0u, 148u,
- 32u, 140u, 111u, 87u,
- 122u, 112u, 126u, 129u,
- 210u, 76u, 219u, 83u,
- 238u, 158u, 20u, 107u,
- 94u, 93u, 91u, 129u,
- 162u, 255u, 130u, 151u,
- 2u, 38u, 133u, 156u,
- 114u, 178u, 171u, 84u,
- 42u, 204u, 3u, 147u,
- 112u, 17u, 94u, 255u,
- 106u, 123u, 146u, 255u,
- 21u, 127u, 150u, 158u,
- 107u, 121u, 114u, 161u,
- 177u, 107u, 103u, 122u,
- 53u, 122u, 127u, 138u,
- 148u, 141u, 146u, 138u,
- 88u, 255u, 128u, 92u,
- 135u, 101u, 131u, 143u,
- 131u, 70u, 212u, 204u,
- 164u, 99u, 65u, 203u,
- 56u, 36u, 94u, 255u,
- 125u, 153u, 72u, 201u,
- 133u, 170u, 184u, 75u,
- 255u, 133u, 192u, 117u,
- 128u, 151u, 102u, 146u,
- 117u, 139u, 125u, 138u,
- 150u, 189u, 21u, 213u,
- 159u, 85u, 189u, 67u,
- 99u, 48u, 1u, 57u,
- 38u, 90u, 154u, 185u,
- 90u, 198u, 162u, 147u,
- 87u, 189u, 116u, 187u,
- 87u, 1u, 191u, 88u,
- 104u, 99u, 116u, 171u,
- 88u, 164u, 38u, 139u,
- 33u, 51u, 183u, 115u,
- 136u, 197u, 122u, 124u,
- 57u, 180u, 1u, 161u,
- 116u, 154u, 207u, 162u,
- 96u, 142u, 255u, 159u,
- 65u, 127u, 151u, 191u,
- 159u, 164u, 182u, 162u,
- 2u, 255u, 70u, 180u,
- 170u, 199u, 206u, 214u,
- 195u, 2u, 115u, 19u,
- 236u, 190u, 251u, 3u,
- 89u, 130u, 104u, 105u,
- 1u, 117u, 153u, 166u,
- 128u, 194u, 196u, 94u,
- 123u, 110u, 125u, 169u,
- 219u, 129u, 81u, 240u,
- 81u, 163u, 82u, 145u,
- 49u, 240u, 203u, 103u,
- 137u, 240u, 43u, 255u,
- 138u, 148u, 183u, 148u,
- 172u, 100u, 226u, 106u,
- 212u, 1u, 116u, 203u,
- 126u, 153u, 49u, 146u,
- 54u, 128u, 115u, 133u,
- 63u, 136u, 17u, 58u,
- 152u, 151u, 92u, 142u,
- 93u, 121u, 105u, 255u,
- 154u, 79u, 153u, 172u,
- 188u, 74u, 20u, 113u,
- 150u, 255u, 143u, 114u,
- 83u, 125u, 21u, 140u,
- 147u, 142u, 144u, 92u,
- 170u, 88u, 44u, 90u,
- 1u, 186u, 37u, 123u,
- 87u, 114u, 181u, 149u,
- 171u, 79u, 64u, 193u,
- 1u, 148u, 196u, 197u,
- 130u, 124u, 131u, 155u,
- 151u, 89u, 114u, 129u,
- 112u, 125u, 187u, 147u,
- 128u, 138u, 102u, 103u,
- 0u, 206u, 111u, 78u,
- 242u, 111u, 165u, 193u,
- 146u, 109u, 51u, 96u,
- 125u, 151u, 112u, 255u,
- 163u, 44u, 84u, 29u,
- 76u, 144u, 101u, 93u,
- 163u, 77u, 194u, 167u,
- 180u, 255u, 177u, 121u,
- 187u, 128u, 70u, 118u,
- 166u, 188u, 148u, 95u,
- 137u, 79u, 97u, 126u,
- 153u, 94u, 207u, 168u,
- 255u, 143u, 10u, 70u,
- 126u, 186u, 146u, 32u,
- 151u, 114u, 183u, 107u,
- 77u, 106u, 1u, 149u,
- 136u, 119u, 183u, 83u,
- 138u, 133u, 100u, 126u,
- 164u, 146u, 75u, 188u,
- 73u, 20u, 255u, 55u,
- 157u, 120u, 188u, 251u,
- 47u, 117u, 161u, 218u,
- 117u, 123u, 139u, 149u,
- 255u, 81u, 118u, 205u,
- 184u, 96u, 110u, 133u,
- 191u, 47u, 128u, 35u,
- 191u, 80u, 98u, 56u,
- 255u, 125u, 26u, 131u,
- 140u, 148u, 127u, 170u,
- 207u, 119u, 67u, 6u,
- 127u, 71u, 40u, 115u,
- 112u, 137u, 207u, 149u,
- 27u, 8u, 59u, 157u,
- 165u, 255u, 96u, 110u,
- 162u, 134u, 135u, 94u,
- 94u, 71u, 199u, 85u,
- 197u, 81u, 144u, 138u,
- 204u, 201u, 133u, 1u,
- 209u, 170u, 143u, 31u,
- 73u, 156u, 38u, 134u,
- 227u, 148u, 187u, 255u,
- 29u, 107u, 61u, 162u,
- 81u, 63u, 52u, 107u,
- 137u, 123u, 96u, 104u,
- 119u, 255u, 98u, 167u,
- 99u, 146u, 82u, 84u,
- 172u, 158u, 255u, 75u,
- 183u, 181u, 86u, 186u,
- 100u, 103u, 146u, 157u,
- 153u, 155u, 75u, 79u,
- 115u, 18u, 82u, 145u,
- 39u, 73u, 255u, 151u,
- 173u, 116u, 79u, 168u,
- 117u, 151u, 173u, 107u,
- 116u, 162u, 119u, 183u,
- 175u, 137u, 47u, 143u,
- 130u, 75u, 114u, 94u,
- 1u, 149u, 67u, 163u,
- 127u, 105u, 170u, 134u,
- 137u, 184u, 71u, 144u,
- 131u, 119u, 175u, 35u,
- 118u, 90u, 255u, 170u,
- 77u, 66u, 117u, 198u,
- 136u, 44u, 175u, 102u,
- 150u, 224u, 15u, 106u,
- 131u, 0u, 112u, 207u,
- 203u, 61u, 106u, 45u,
- 198u, 144u, 59u, 175u,
- 1u, 110u, 77u, 8u,
- 89u, 236u, 187u, 106u,
- 35u, 181u, 11u, 134u,
- 133u, 101u, 175u, 173u,
- 162u, 169u, 107u, 213u,
- 52u, 106u, 255u, 89u,
- 133u, 130u, 130u, 226u,
- 201u, 120u, 120u, 132u,
- 146u, 190u, 33u, 99u,
- 119u, 54u, 255u, 152u,
- 172u, 55u, 62u, 94u,
- 7u, 121u, 167u, 255u,
- 177u, 84u, 127u, 227u,
- 77u, 58u, 112u, 144u,
- 187u, 132u, 157u, 40u,
- 162u, 0u, 163u, 102u,
- 87u, 140u, 100u, 138u,
- 88u, 115u, 217u, 139u,
- 255u, 153u, 87u, 162u,
- 185u, 143u, 86u, 51u,
- 113u, 67u, 172u, 110u,
- 112u, 82u, 52u, 118u,
- 105u, 137u, 94u, 147u,
- 96u, 169u, 170u, 221u,
- 169u, 97u, 157u, 167u,
- 175u, 136u, 1u, 100u,
- 189u, 19u, 134u, 117u,
- 179u, 133u, 1u, 176u,
- 114u, 116u, 73u, 153u,
- 140u, 158u, 151u, 134u,
- 207u, 157u, 151u, 143u,
- 94u, 81u, 47u, 215u,
- 177u, 154u, 232u, 154u,
- 101u, 1u, 95u, 135u,
- 196u, 219u, 35u, 211u,
- 98u, 104u, 66u, 178u,
- 0u, 138u, 111u, 92u,
- 93u, 130u, 138u, 140u,
- 208u, 147u, 186u, 218u,
- 119u, 245u, 158u, 8u,
- 97u, 168u, 78u, 145u,
- 255u, 185u, 166u, 108u,
- 28u, 83u, 212u, 179u,
- 104u, 185u, 90u, 93u,
- 61u, 144u, 138u, 165u,
- 190u, 88u, 139u, 255u,
- 221u, 72u, 255u, 140u,
- 174u, 109u, 113u, 41u,
- 196u, 156u, 82u, 103u,
- 114u, 201u, 138u, 168u,
- 146u, 156u, 51u, 111u,
- 172u, 85u, 255u, 159u,
- 178u, 111u, 59u, 194u,
- 107u, 77u, 143u, 78u,
- 159u, 199u, 255u, 181u,
- 37u, 110u, 75u, 114u,
- 75u, 196u, 148u, 243u,
- 134u, 110u, 211u, 121u,
- 159u, 102u, 38u, 121u,
- 255u, 98u, 72u, 126u,
- 100u, 154u, 47u, 126u,
- 181u, 61u, 159u, 101u,
- 232u, 48u, 189u, 143u,
- 62u, 125u, 255u, 120u,
- 88u, 250u, 188u, 122u,
- 141u, 8u, 34u, 19u,
- 171u, 106u, 228u, 185u,
- 178u, 233u, 201u, 229u,
- 102u, 148u, 163u, 103u,
- 204u, 255u, 152u, 180u,
- 183u, 226u, 66u, 59u,
- 1u, 113u, 184u, 112u,
- 46u, 122u, 183u, 184u,
- 169u, 167u, 134u, 83u,
- 165u, 212u, 211u, 81u,
- 135u, 93u, 122u, 89u,
- 141u, 1u, 210u, 81u,
- 123u, 176u, 155u, 181u,
- 76u, 217u, 184u, 29u,
- 48u, 151u, 160u, 70u,
- 0u, 188u, 214u, 104u,
- 86u, 32u, 111u, 209u,
- 179u, 190u, 75u, 128u,
- 140u, 0u, 134u, 130u,
- 92u, 188u, 152u, 161u,
- 70u, 7u, 139u, 140u,
- 209u, 138u, 168u, 220u,
- 1u, 134u, 49u, 82u,
- 92u, 25u, 166u, 83u,
- 114u, 230u, 42u, 189u,
- 172u, 160u, 4u, 144u,
- 85u, 211u, 79u, 155u,
- 174u, 69u, 255u, 216u,
- 101u, 165u, 130u, 112u,
- 215u, 124u, 212u, 214u,
- 77u, 166u, 121u, 112u,
- 181u, 75u, 98u, 103u,
- 69u, 1u, 68u, 118u,
- 141u, 124u, 181u, 54u,
- 171u, 128u, 141u, 255u,
- 140u, 180u, 115u, 92u,
- 103u, 180u, 102u, 76u,
- 81u, 96u, 1u, 232u,
- 182u, 127u, 216u, 71u,
- 33u, 116u, 123u, 229u,
- 81u, 99u, 125u, 191u,
- 106u, 117u, 255u, 73u,
- 148u, 117u, 72u, 115u,
- 130u, 143u, 78u, 90u,
- 77u, 156u, 153u, 209u,
- 151u, 124u, 122u, 118u,
- 167u, 141u, 66u, 99u,
- 0u, 88u, 117u, 108u,
- 70u, 132u, 96u, 200u,
- 51u, 79u, 41u, 139u,
- 120u, 164u, 35u, 126u,
- 167u, 229u, 126u, 128u,
- 137u, 255u, 42u, 117u,
- 106u, 39u, 145u, 116u,
- 46u, 17u, 127u, 20u,
- 195u, 21u, 192u, 1u,
- 146u, 209u, 223u, 151u,
- 183u, 100u, 49u, 1u,
- 181u, 78u, 104u, 158u,
- 61u, 110u, 92u, 127u,
- 72u, 172u, 142u, 132u,
- 28u, 94u, 112u, 201u,
- 56u, 168u, 127u, 33u,
- 138u, 110u, 94u, 82u,
- 133u, 60u, 1u, 73u,
- 177u, 114u, 94u, 103u,
- 204u, 65u, 194u, 106u,
- 119u, 163u, 67u, 164u,
- 156u, 57u, 255u, 122u,
- 126u, 143u, 13u, 195u,
- 79u, 90u, 17u, 63u,
- 99u, 74u, 105u, 1u,
- 85u, 171u, 134u, 162u,
- 83u, 163u, 124u, 76u,
- 108u, 230u, 255u, 170u,
- 229u, 143u, 208u, 93u,
- 88u, 108u, 218u, 247u,
- 103u, 90u, 204u, 217u,
- 12u, 7u, 170u, 185u,
- 164u, 60u, 163u, 162u,
- 160u, 115u, 192u, 255u,
- 148u, 228u, 112u, 136u,
- 61u, 76u, 13u, 48u,
- 46u, 165u, 187u, 111u,
- 178u, 1u, 171u, 185u,
- 117u, 136u, 255u, 89u,
- 58u, 188u, 161u, 70u,
- 130u, 187u, 33u, 131u,
- 117u, 135u, 178u, 188u,
- 131u, 189u, 174u, 113u,
- 177u, 203u, 57u, 86u,
- 88u, 108u, 195u, 69u,
- 146u, 129u, 255u, 157u,
- 93u, 129u, 225u, 61u,
- 136u, 134u, 151u, 141u,
- 124u, 157u, 107u, 168u,
- 69u, 91u, 140u, 255u,
- 105u, 151u, 67u, 145u,
- 168u, 125u, 162u, 1u,
- 89u, 105u, 219u, 153u,
- 112u, 193u, 143u, 150u,
- 176u, 152u, 163u, 82u,
- 1u, 31u, 167u, 203u,
- 123u, 117u, 186u, 104u,
- 165u, 80u, 170u, 207u,
- 196u, 152u, 153u, 138u,
- 109u, 152u, 1u, 63u,
- 62u, 166u, 38u, 81u,
- 173u, 162u, 112u, 165u,
- 82u, 47u, 130u, 0u,
- 116u, 186u, 72u, 213u,
- 185u, 17u, 138u, 15u,
- 114u, 223u, 152u, 89u,
- 165u, 66u, 138u, 132u,
- 24u, 137u, 226u, 69u,
- 105u, 1u, 111u, 156u,
- 135u, 151u, 84u, 100u,
- 115u, 50u, 49u, 78u,
- 255u, 184u, 139u, 228u,
- 191u, 120u, 152u, 160u,
- 69u, 130u, 24u, 126u,
- 37u, 178u, 202u, 88u,
- 71u, 116u, 159u, 126u,
- 144u, 104u, 207u, 255u,
- 101u, 78u, 142u, 203u,
- 204u, 39u, 212u, 175u,
- 67u, 255u, 214u, 135u,
- 178u, 27u, 52u, 110u,
- 115u, 152u, 64u, 187u,
- 121u, 140u, 1u, 113u,
- 181u, 121u, 213u, 236u,
- 198u, 66u, 33u, 83u,
- 66u, 187u, 118u, 27u,
- 255u, 53u, 112u, 41u,
- 177u, 111u, 31u, 208u,
- 174u, 72u, 188u, 114u,
- 70u, 192u, 57u, 75u,
- 170u, 194u, 98u, 156u,
- 170u, 132u, 66u, 1u,
- 133u, 113u, 186u, 131u,
- 171u, 12u, 83u, 142u,
- 185u, 143u, 255u, 139u,
- 47u, 111u, 214u, 128u,
- 134u, 44u, 139u, 140u,
- 161u, 136u, 120u, 143u,
- 163u, 128u, 159u, 71u,
- 184u, 166u, 59u, 136u,
- 163u, 125u, 152u, 1u,
- 207u, 70u, 80u, 199u,
- 166u, 120u, 247u, 110u,
- 208u, 115u, 174u, 92u,
- 149u, 111u, 70u, 21u,
- 167u, 255u, 126u, 136u,
- 84u, 72u, 50u, 185u,
- 183u, 208u, 242u, 153u,
- 119u, 130u, 0u, 120u,
- 59u, 98u, 167u, 107u,
- 189u, 148u, 48u, 156u,
- 1u, 46u, 84u, 169u,
- 140u, 198u, 213u, 119u,
- 92u, 73u, 146u, 106u,
- 95u, 132u, 25u, 56u,
- 14u, 84u, 0u, 121u,
- 81u, 187u, 228u, 130u,
- 131u, 17u, 117u, 202u,
- 109u, 128u, 109u, 1u,
- 209u, 219u, 170u, 119u,
- 90u, 142u, 80u, 122u,
- 55u, 109u, 218u, 174u,
- 110u, 131u, 191u, 52u,
- 218u, 38u, 119u, 204u,
- 99u, 189u, 113u, 136u,
- 1u, 141u, 152u, 251u,
- 117u, 141u, 36u, 49u,
- 60u, 103u, 255u, 119u,
- 65u, 223u, 96u, 127u,
- 115u, 189u, 214u, 208u,
- 148u, 123u, 195u, 199u,
- 158u, 47u, 145u, 164u,
- 83u, 89u, 50u, 255u,
- 79u, 92u, 165u, 108u,
- 3u, 123u, 58u, 199u,
- 158u, 66u, 0u, 131u,
- 174u, 123u, 255u, 252u,
- 175u, 49u, 73u, 115u,
- 156u, 117u, 71u, 233u,
- 119u, 202u, 80u, 36u,
- 30u, 216u, 111u, 147u,
- 177u, 124u, 40u, 255u,
- 235u, 91u, 128u, 224u,
- 114u, 123u, 130u, 218u,
- 34u, 202u, 128u, 236u,
- 171u, 35u, 1u, 70u,
- 150u, 179u, 81u, 73u,
- 128u, 23u, 207u, 255u,
- 98u, 183u, 238u, 183u,
- 92u, 80u, 135u, 142u,
- 186u, 117u, 174u, 103u,
- 238u, 179u, 141u, 128u,
- 85u, 78u, 77u, 169u,
- 255u, 197u, 106u, 97u,
- 9u, 219u, 65u, 221u,
- 22u, 140u, 1u, 11u,
- 234u, 30u, 219u, 206u,
- 77u, 33u, 242u, 130u,
- 111u, 56u, 40u, 135u,
- 196u, 84u, 66u, 81u,
- 255u, 249u, 111u, 144u,
- 80u, 139u, 57u, 121u,
- 74u, 132u, 82u, 166u,
- 124u, 43u, 89u, 161u,
- 147u, 123u, 255u, 176u,
- 27u, 42u, 149u, 172u,
- 102u, 195u, 116u, 139u,
- 117u, 150u, 141u, 157u,
- 168u, 1u, 129u, 64u,
- 60u, 177u, 101u, 99u,
- 175u, 167u, 139u, 97u,
- 212u, 223u, 146u, 212u,
- 128u, 211u, 203u, 224u,
- 255u, 63u, 109u, 130u,
- 241u, 155u, 240u, 45u,
- 192u, 171u, 73u, 189u,
- 126u, 42u, 121u, 132u,
- 180u, 175u, 255u, 251u,
- 195u, 62u, 171u, 255u,
- 124u, 176u, 43u, 146u,
- 77u, 41u, 59u, 128u,
- 153u, 143u, 120u, 165u,
- 187u, 120u, 98u, 127u,
- 151u, 162u, 83u, 152u,
- 23u, 131u, 30u, 44u,
- 101u, 116u, 255u, 237u,
- 2u, 132u, 100u, 1u,
- 105u, 152u, 186u, 233u,
- 170u, 180u, 217u, 169u,
- 38u, 73u, 187u, 228u,
- 126u, 185u, 1u, 152u,
- 67u, 64u, 236u, 96u,
- 132u, 47u, 121u, 140u,
- 112u, 193u, 181u, 179u,
- 42u, 209u, 119u, 36u,
- 88u, 137u, 156u, 227u,
- 168u, 47u, 115u, 93u,
- 59u, 1u, 215u, 182u,
- 47u, 132u, 126u, 191u,
- 30u, 151u, 37u, 165u,
- 143u, 101u, 184u, 166u,
- 21u, 1u, 58u, 152u,
- 63u, 208u, 112u, 194u,
- 202u, 176u, 137u, 113u,
- 139u, 83u, 1u, 139u,
- 132u, 119u, 109u, 118u,
- 115u, 158u, 88u, 77u,
- 157u, 255u, 86u, 170u,
- 97u, 80u, 170u, 141u,
- 128u, 144u, 94u, 153u,
- 210u, 104u, 186u, 136u,
- 178u, 169u, 0u, 163u,
- 137u, 53u, 40u, 22u,
- 123u, 176u, 167u, 213u,
- 121u, 192u, 255u, 19u,
- 190u, 104u, 27u, 103u,
- 154u, 34u, 152u, 141u,
- 63u, 112u, 157u, 57u,
- 93u, 190u, 164u, 192u,
- 0u, 133u, 140u, 131u,
- 202u, 148u, 139u, 163u,
- 131u, 43u, 87u, 225u,
- 71u, 97u, 133u, 133u,
- 97u, 173u, 122u, 0u,
- 149u, 104u, 97u, 65u,
- 178u, 107u, 231u, 169u,
- 82u, 154u, 108u, 125u,
- 208u, 161u, 99u, 160u,
- 135u, 225u, 46u, 144u,
- 125u, 197u, 74u, 0u,
- 198u, 118u, 246u, 153u,
- 159u, 75u, 133u, 110u,
- 147u, 108u, 119u, 183u,
- 137u, 161u, 121u, 0u,
- 140u, 147u, 94u, 140u,
- 86u, 46u, 17u, 104u,
- 217u, 158u, 243u, 186u,
- 25u, 1u, 125u, 197u,
- 124u, 120u, 249u, 77u,
- 137u, 88u, 146u, 92u,
- 92u, 166u, 197u, 152u,
- 94u, 165u, 255u, 148u,
- 158u, 126u, 115u, 114u,
- 182u, 191u, 101u, 104u,
- 88u, 37u, 211u, 103u,
- 255u, 98u, 112u, 28u,
- 115u, 92u, 208u, 177u,
- 203u, 163u, 81u, 159u,
- 170u, 255u, 127u, 133u,
- 167u, 83u, 167u, 179u,
- 138u, 164u, 160u, 92u,
- 1u, 104u, 75u, 242u,
- 132u, 165u, 145u, 131u,
- 64u, 89u, 103u, 170u,
- 87u, 2u, 182u, 177u,
- 115u, 181u, 194u, 13u,
- 255u, 161u, 94u, 27u,
- 117u, 143u, 153u, 233u,
- 132u, 124u, 55u, 181u,
- 59u, 142u, 90u, 160u,
- 186u, 177u, 78u, 0u,
- 157u, 94u, 46u, 111u,
- 8u, 169u, 129u, 157u,
- 85u, 255u, 216u, 162u,
- 48u, 139u, 122u, 108u,
- 176u, 181u, 103u, 255u,
- 157u, 98u, 171u, 93u,
- 51u, 143u, 1u, 212u,
- 85u, 231u, 203u, 95u,
- 43u, 216u, 50u, 87u,
- 110u, 209u, 1u, 63u,
- 219u, 70u, 132u, 144u,
- 139u, 117u, 117u, 52u,
- 131u, 166u, 192u, 43u,
- 57u, 19u, 83u, 230u,
- 255u, 151u, 181u, 117u,
- 24u, 137u, 67u, 141u,
- 172u, 90u, 160u, 134u,
- 134u, 165u, 255u, 133u,
- 149u, 255u, 88u, 78u,
- 41u, 55u, 113u, 103u,
- 97u, 130u, 180u, 231u,
- 124u, 211u, 189u, 88u,
- 85u, 154u, 115u, 95u,
- 251u, 163u, 204u, 145u,
- 159u, 82u, 109u, 1u,
- 201u, 166u, 168u, 167u,
- 65u, 155u, 206u, 142u,
- 77u, 116u, 104u, 197u,
- 127u, 177u, 0u, 231u,
- 172u, 93u, 123u, 126u,
- 147u, 123u, 255u, 94u,
- 191u, 70u, 129u, 42u,
- 137u, 168u, 45u, 105u,
- 161u, 195u, 175u, 91u,
- 203u, 117u, 142u, 124u,
- 180u, 14u, 146u, 73u,
- 71u, 255u, 133u, 150u,
- 195u, 48u, 173u, 73u,
- 184u, 167u, 73u, 71u,
- 27u, 77u, 60u, 176u,
- 38u, 1u, 173u, 143u,
- 134u, 175u, 155u, 129u,
- 175u, 54u, 185u, 133u,
- 203u, 255u, 153u, 88u,
- 122u, 131u, 213u, 71u,
- 206u, 250u, 69u, 59u,
- 163u, 242u, 39u, 180u,
- 44u, 86u, 126u, 109u,
- 151u, 211u, 129u, 255u,
- 110u, 152u, 185u, 135u,
- 153u, 95u, 1u, 115u,
- 206u, 118u, 223u, 177u,
- 66u, 169u, 107u, 185u,
- 43u, 168u, 188u, 113u,
- 96u, 139u, 78u, 68u,
- 64u, 183u, 140u, 58u,
- 148u, 0u, 112u, 229u,
- 106u, 139u, 132u, 0u,
- 82u, 179u, 71u, 139u,
- 107u, 116u, 144u, 138u,
- 65u, 136u, 193u, 218u,
- 134u, 145u, 149u, 102u,
- 115u, 140u, 105u, 56u,
- 69u, 124u, 68u, 123u,
- 1u, 107u, 151u, 56u,
- 118u, 92u, 89u, 101u,
- 0u, 129u, 121u, 145u,
- 117u, 76u, 185u, 129u,
- 144u, 72u, 103u, 152u,
- 57u, 186u, 240u, 102u,
- 125u, 88u, 128u, 162u,
- 213u, 71u, 127u, 243u,
- 1u, 27u, 133u, 205u,
- 79u, 233u, 86u, 113u,
- 192u, 88u, 118u, 255u,
- 56u, 204u, 122u, 166u,
- 111u, 192u, 56u, 179u,
- 19u, 176u, 152u, 80u,
- 131u, 137u, 128u, 153u,
- 137u, 94u, 95u, 55u,
- 113u, 116u, 231u, 255u,
- 148u, 150u, 52u, 195u,
- 60u, 167u, 144u, 1u,
- 175u, 247u, 196u, 124u,
- 167u, 14u, 196u, 199u,
- 133u, 20u, 165u, 255u,
- 92u, 188u, 161u, 94u,
- 145u, 29u, 6u, 77u,
- 105u, 55u, 140u, 178u,
- 42u, 185u, 112u, 6u,
- 94u, 194u, 113u, 146u,
- 255u, 180u, 165u, 90u,
- 114u, 54u, 80u, 84u,
- 60u, 142u, 50u, 104u,
- 109u, 107u, 76u, 126u,
- 197u, 181u, 70u, 255u,
- 162u, 78u, 91u, 47u,
- 0u, 78u, 90u, 242u,
- 98u, 93u, 166u, 193u,
- 63u, 190u, 63u, 154u,
- 96u, 232u, 202u, 164u,
- 192u, 254u, 173u, 180u,
- 155u, 59u, 173u, 41u,
- 137u, 161u, 51u, 157u,
- 164u, 167u, 64u, 1u,
- 107u, 236u, 189u, 44u,
- 114u, 180u, 255u, 121u,
- 109u, 153u, 182u, 146u,
- 163u, 79u, 190u, 155u,
- 156u, 57u, 144u, 179u,
- 110u, 68u, 174u, 255u,
- 248u, 175u, 5u, 58u,
- 79u, 106u, 119u, 107u,
- 72u, 244u, 135u, 81u,
- 129u, 128u, 43u, 23u,
- 126u, 139u, 250u, 52u,
- 231u, 28u, 255u, 68u,
- 105u, 152u, 201u, 40u,
- 48u, 241u, 63u, 210u,
- 103u, 157u, 208u, 73u,
- 255u, 156u, 139u, 121u,
- 91u, 149u, 116u, 150u,
- 88u, 142u, 38u, 160u,
- 118u, 180u, 175u, 115u,
- 143u, 1u, 85u, 160u,
- 155u, 113u, 116u, 201u,
- 0u, 169u, 116u, 146u,
- 112u, 70u, 195u, 190u,
- 132u, 64u, 110u, 170u,
- 154u, 146u, 239u, 3u,
- 49u, 192u, 255u, 69u,
- 112u, 45u, 232u, 244u,
- 131u, 214u, 110u, 185u,
- 138u, 174u, 84u, 52u,
- 122u, 111u, 147u, 253u,
- 105u, 108u, 255u, 106u,
- 120u, 99u, 172u, 106u,
- 120u, 170u, 83u, 150u,
- 26u, 233u, 255u, 70u,
- 47u, 199u, 20u, 118u,
- 245u, 44u, 155u, 148u,
- 106u, 165u, 183u, 55u,
- 109u, 115u, 138u, 133u,
- 167u, 255u, 127u, 92u,
- 139u, 147u, 159u, 75u,
- 52u, 104u, 124u, 154u,
- 95u, 100u, 0u, 219u,
- 187u, 64u, 191u, 193u,
- 62u, 10u, 4u, 50u,
- 0u, 114u, 93u, 130u,
- 86u, 176u, 146u, 205u,
- 149u, 67u, 148u, 124u,
- 174u, 99u, 149u, 220u,
- 75u, 1u, 133u, 170u,
- 219u, 107u, 73u, 150u,
- 184u, 24u, 143u, 152u,
- 31u, 196u, 69u, 123u,
- 184u, 25u, 204u, 108u,
- 136u, 208u, 49u, 169u,
- 157u, 114u, 78u, 171u,
- 222u, 64u, 255u, 133u,
- 153u, 164u, 90u, 33u,
- 196u, 32u, 56u, 160u,
- 1u, 170u, 152u, 124u,
- 149u, 122u, 165u, 136u,
- 160u, 12u, 83u, 196u,
- 1u, 19u, 233u, 69u,
- 177u, 171u, 59u, 139u,
- 120u, 81u, 248u, 86u,
- 110u, 173u, 212u, 139u,
- 164u, 120u, 67u, 203u,
- 141u, 75u, 100u, 1u,
- 131u, 87u, 61u, 115u,
- 112u, 148u, 133u, 53u,
- 52u, 123u, 62u, 82u,
- 6u, 197u, 230u, 58u,
- 31u, 231u, 255u, 183u,
- 108u, 110u, 156u, 225u,
- 48u, 237u, 137u, 67u,
- 24u, 137u, 18u, 35u,
- 114u, 1u, 184u, 250u,
- 117u, 119u, 46u, 88u,
- 118u, 116u, 0u, 169u,
- 155u, 111u, 158u, 72u,
- 57u, 61u, 143u, 199u,
- 131u, 156u, 151u, 237u,
- 255u, 135u, 181u, 131u,
- 51u, 153u, 43u, 106u,
- 149u, 162u, 225u, 28u,
- 81u, 229u, 104u, 149u,
- 165u, 255u, 235u, 33u,
- 75u, 96u, 89u, 122u,
- 96u, 215u, 165u, 197u,
- 134u, 119u, 10u, 118u,
- 1u, 149u, 146u, 128u,
- 72u, 173u, 149u, 252u,
- 65u, 66u, 170u, 186u,
- 176u, 129u, 51u, 111u,
- 105u, 45u, 58u, 173u,
- 62u, 126u, 114u, 59u,
- 29u, 255u, 34u, 70u,
- 255u, 111u, 152u, 174u,
- 118u, 113u, 69u, 120u,
- 164u, 146u, 148u, 148u,
- 168u, 122u, 157u, 76u,
- 74u, 66u, 136u, 24u,
- 190u, 126u, 119u, 108u,
- 113u, 30u, 251u, 74u,
- 67u, 155u, 242u, 255u,
- 188u, 83u, 108u, 174u,
- 1u, 88u, 142u, 15u,
- 164u, 159u, 108u, 10u,
- 89u, 37u, 193u, 166u,
- 119u, 35u, 113u, 1u,
- 70u, 230u, 168u, 186u,
- 130u, 97u, 198u, 233u,
- 144u, 236u, 105u, 47u,
- 48u, 120u, 69u, 134u,
- 103u, 97u, 187u, 129u,
- 138u, 109u, 91u, 150u,
- 28u, 1u, 184u, 172u,
- 60u, 86u, 118u, 181u,
- 158u, 197u, 105u, 57u,
- 114u, 215u, 1u, 80u,
- 102u, 159u, 123u, 188u,
- 84u, 66u, 60u, 255u,
- 214u, 90u, 69u, 182u,
- 114u, 198u, 139u, 54u,
- 110u, 78u, 34u, 114u,
- 192u, 166u, 89u, 71u,
- 255u, 83u, 105u, 186u,
- 128u, 62u, 172u, 159u,
- 194u, 113u, 182u, 40u,
- 72u, 123u, 26u, 159u,
- 60u, 213u, 111u, 190u,
- 140u, 155u, 200u, 131u,
- 164u, 1u, 37u, 59u,
- 126u, 101u, 82u, 175u,
- 65u, 95u, 176u, 153u,
- 108u, 204u, 22u, 153u,
- 210u, 96u, 54u, 0u,
- 109u, 102u, 80u, 155u,
- 64u, 131u, 136u, 218u,
- 255u, 152u, 168u, 48u,
- 151u, 105u, 200u, 147u,
- 67u, 63u, 189u, 121u,
- 201u, 169u, 220u, 14u,
- 1u, 237u, 44u, 162u,
- 170u, 176u, 86u, 207u,
- 252u, 224u, 112u, 110u,
- 1u, 136u, 3u, 174u,
- 126u, 83u, 148u, 40u,
- 36u, 43u, 69u, 236u,
- 69u, 187u, 180u, 255u,
- 99u, 174u, 70u, 79u,
- 64u, 90u, 168u, 111u,
- 162u, 69u, 180u, 20u,
- 181u, 33u, 109u, 202u,
- 98u, 78u, 106u, 190u,
- 255u, 171u, 106u, 78u,
- 36u, 190u, 68u, 100u,
- 193u, 143u, 191u, 97u,
- 237u, 88u, 111u, 72u,
- 125u, 233u, 1u, 89u,
- 100u, 157u, 253u, 79u,
- 67u, 70u, 118u, 217u,
- 165u, 144u, 173u, 218u,
- 146u, 171u, 1u, 71u,
- 87u, 216u, 61u, 77u,
- 162u, 51u, 154u, 138u,
- 135u, 100u, 161u, 213u,
- 1u, 228u, 40u, 110u,
- 188u, 169u, 3u, 233u,
- 162u, 118u, 162u, 147u,
- 166u, 158u, 255u, 147u,
- 170u, 100u, 35u, 149u,
- 134u, 174u, 183u, 192u,
- 113u, 220u, 99u, 109u,
- 49u, 169u, 246u, 36u,
- 255u, 15u, 158u, 253u,
- 161u, 167u, 115u, 125u,
- 17u, 112u, 77u, 169u,
- 110u, 108u, 177u, 173u,
- 28u, 255u, 154u, 153u,
- 129u, 35u, 86u, 203u,
- 219u, 62u, 255u, 136u,
- 7u, 94u, 16u, 129u,
- 38u, 145u, 176u, 190u,
- 78u, 151u, 141u, 130u,
- 102u, 1u, 176u, 154u,
- 63u, 87u, 3u, 230u,
- 204u, 199u, 242u, 243u,
- 68u, 36u, 108u, 104u,
- 176u, 99u, 143u, 30u,
- 215u, 111u, 255u, 44u,
- 165u, 27u, 165u, 127u,
- 180u, 162u, 114u, 182u,
- 147u, 142u, 161u, 88u,
- 107u, 212u, 73u, 132u,
- 86u, 104u, 169u, 157u,
- 120u, 175u, 82u, 1u,
- 42u, 231u, 99u, 61u,
- 80u, 165u, 1u, 149u,
- 40u, 146u, 255u, 132u,
- 120u, 87u, 97u, 203u,
- 131u, 122u, 137u, 77u,
- 185u, 110u, 97u, 255u,
- 60u, 68u, 239u, 207u,
- 175u, 165u, 114u, 37u,
- 110u, 133u, 194u, 47u,
- 169u, 107u, 122u, 80u,
- 120u, 91u, 58u, 1u,
- 142u, 200u, 111u, 113u,
- 255u, 84u, 210u, 103u,
- 197u, 132u, 62u, 57u,
- 116u, 116u, 49u, 209u,
- 166u, 248u, 139u, 132u,
- 183u, 107u, 145u, 216u,
- 89u, 90u, 255u, 70u,
- 110u, 84u, 56u, 164u,
- 116u, 196u, 167u, 176u,
- 118u, 112u, 130u, 241u,
- 1u, 109u, 55u, 211u,
- 173u, 110u, 170u, 113u,
- 118u, 77u, 161u, 89u,
- 173u, 193u, 140u, 27u,
- 130u, 163u, 36u, 132u,
- 51u, 195u, 198u, 108u,
- 173u, 179u, 255u, 177u,
- 192u, 153u, 115u, 88u,
- 45u, 255u, 34u, 166u,
- 93u, 67u, 186u, 183u,
- 139u, 157u, 117u, 215u,
- 127u, 255u, 126u, 80u,
- 107u, 135u, 159u, 84u,
- 149u, 64u, 106u, 41u,
- 146u, 143u, 204u, 130u,
- 121u, 76u, 108u, 170u,
- 133u, 159u, 10u, 35u,
- 116u, 255u, 42u, 43u,
- 143u, 78u, 207u, 245u,
- 249u, 227u, 49u, 1u,
- 218u, 43u, 134u, 166u,
- 226u, 126u, 224u, 112u,
- 228u, 249u, 11u, 250u,
- 96u, 51u, 96u, 93u,
- 41u, 132u, 178u, 159u,
- 193u, 1u, 158u, 151u,
- 150u, 78u, 135u, 231u,
- 121u, 201u, 56u, 118u,
- 1u, 174u, 87u, 127u,
- 36u, 218u, 164u, 181u,
- 111u, 113u, 87u, 143u,
- 114u, 90u, 255u, 147u,
- 138u, 181u, 216u, 62u,
- 46u, 232u, 63u, 106u,
- 131u, 130u, 140u, 175u,
- 192u, 58u, 230u, 61u,
- 199u, 51u, 80u, 139u,
- 146u, 104u, 104u, 255u,
- 126u, 148u, 38u, 56u,
- 76u, 70u, 183u, 151u,
- 255u, 103u, 250u, 49u,
- 88u, 79u, 25u, 168u,
- 242u, 118u, 240u, 17u,
- 123u, 111u, 160u, 96u,
- 159u, 57u, 146u, 38u,
- 88u, 50u, 113u, 144u,
- 95u, 255u, 146u, 106u,
- 146u, 104u, 178u, 255u,
- 65u, 167u, 139u, 116u,
- 182u, 131u, 171u, 189u,
- 95u, 157u, 126u, 130u,
- 251u, 149u, 115u, 166u,
- 243u, 19u, 80u, 118u,
- 140u, 131u, 58u, 158u,
- 108u, 87u, 1u, 60u,
- 170u, 77u, 110u, 157u,
- 117u, 40u, 198u, 80u,
- 54u, 147u, 1u, 55u,
- 173u, 168u, 150u, 55u,
- 197u, 113u, 255u, 226u,
- 242u, 61u, 169u, 149u,
- 66u, 56u, 211u, 125u,
- 159u, 154u, 233u, 119u,
- 161u, 144u, 109u, 70u,
- 137u, 1u, 190u, 186u,
- 140u, 219u, 27u, 247u,
- 182u, 136u, 187u, 61u,
- 151u, 177u, 155u, 139u,
- 94u, 83u, 45u, 255u,
- 159u, 103u, 193u, 70u,
- 74u, 83u, 36u, 126u,
- 0u, 99u, 75u, 114u,
- 128u, 30u, 97u, 68u,
- 97u, 173u, 82u, 183u,
- 87u, 56u, 86u, 102u,
- 168u, 47u, 143u, 217u,
- 94u, 255u, 199u, 164u,
- 95u, 174u, 106u, 65u,
- 200u, 191u, 208u, 128u,
- 71u, 123u, 1u, 101u,
- 240u, 128u, 92u, 109u,
- 63u, 192u, 26u, 59u,
- 115u, 163u, 157u, 133u,
- 140u, 23u, 80u, 239u,
- 81u, 70u, 166u, 30u,
- 219u, 0u, 31u, 31u,
- 90u, 15u, 206u, 149u,
- 90u, 233u, 68u, 70u,
- 217u, 79u, 141u, 203u,
- 1u, 248u, 181u, 209u,
- 177u, 37u, 197u, 157u,
- 135u, 154u, 92u, 1u,
- 114u, 80u, 123u, 216u,
- 65u, 126u, 150u, 42u,
- 110u, 140u, 152u, 171u,
- 98u, 86u, 210u, 105u,
- 98u, 160u, 157u, 0u,
- 112u, 89u, 98u, 190u,
- 130u, 122u, 217u, 102u,
- 184u, 109u, 152u, 85u,
- 150u, 130u, 62u, 129u,
- 117u, 112u, 122u, 39u,
- 87u, 255u, 133u, 125u,
- 188u, 29u, 105u, 179u,
- 255u, 41u, 103u, 119u,
- 172u, 124u, 53u, 117u,
- 116u, 61u, 159u, 107u,
- 103u, 163u, 255u, 138u,
- 90u, 142u, 201u, 60u,
- 130u, 144u, 146u, 40u,
- 206u, 131u, 221u, 148u,
- 213u, 198u, 0u, 139u,
- 187u, 190u, 206u, 92u,
- 178u, 37u, 77u, 156u,
- 106u, 206u, 57u, 140u,
- 128u, 146u, 93u, 80u,
- 182u, 157u, 133u, 175u,
- 135u, 103u, 90u, 168u,
- 156u, 60u, 147u, 255u,
- 60u, 129u, 255u, 155u,
- 185u, 217u, 182u, 134u,
- 199u, 83u, 94u, 158u,
- 220u, 149u, 166u, 114u,
- 176u, 125u, 88u, 122u,
- 99u, 69u, 132u, 255u,
- 163u, 140u, 162u, 135u,
- 131u, 97u, 80u, 117u,
- 90u, 106u, 77u, 133u,
- 26u, 150u, 225u, 213u,
- 108u, 81u, 162u, 1u,
- 47u, 61u, 127u, 67u,
- 107u, 95u, 211u, 194u,
- 92u, 133u, 87u, 77u,
- 206u, 131u, 173u, 255u,
- 164u, 88u, 67u, 123u,
- 91u, 37u, 102u, 78u,
- 239u, 0u, 127u, 147u,
- 181u, 97u, 119u, 111u,
- 74u, 177u, 124u, 39u,
- 103u, 145u, 165u, 190u,
- 1u, 146u, 141u, 57u,
- 30u, 159u, 94u, 48u,
- 50u, 166u, 23u, 129u,
- 161u, 77u, 117u, 94u,
- 71u, 0u, 137u, 111u,
- 125u, 198u, 188u, 192u,
- 102u, 88u, 31u, 33u,
- 87u, 83u, 199u, 167u,
- 104u, 146u, 84u, 150u,
- 134u, 1u, 187u, 212u,
- 66u, 133u, 122u, 165u,
- 172u, 54u, 187u, 121u,
- 0u, 165u, 156u, 113u,
- 159u, 60u, 152u, 120u,
- 13u, 149u, 105u, 94u,
- 134u, 171u, 93u, 99u,
- 43u, 135u, 255u, 122u,
- 131u, 201u, 113u, 133u,
- 105u, 136u, 167u, 129u,
- 201u, 88u, 203u, 150u,
- 81u, 220u, 255u, 50u,
- 195u, 91u, 142u, 126u,
- 60u, 95u, 127u, 148u,
- 181u, 157u, 112u, 117u,
- 203u, 56u, 1u, 86u,
- 231u, 70u, 238u, 148u,
- 88u, 107u, 167u, 26u,
- 202u, 101u, 255u, 164u,
- 167u, 160u, 45u, 254u,
- 183u, 236u, 106u, 205u,
- 210u, 79u, 74u, 151u,
- 121u, 146u, 108u, 114u,
- 85u, 205u, 255u, 170u,
- 214u, 230u, 54u, 173u,
- 183u, 177u, 117u, 134u,
- 96u, 207u, 92u, 113u,
- 43u, 173u, 73u, 152u,
- 55u, 239u, 195u, 186u,
- 124u, 56u, 76u, 255u,
- 102u, 212u, 85u, 96u,
- 103u, 203u, 120u, 209u,
- 148u, 255u, 159u, 206u,
- 111u, 145u, 90u, 137u,
- 152u, 50u, 188u, 129u,
- 1u, 206u, 255u, 164u,
- 143u, 141u, 48u, 156u,
- 172u, 113u, 22u, 236u,
- 102u, 74u, 77u, 232u,
- 72u, 111u, 160u, 120u,
- 55u, 255u, 90u, 97u,
- 164u, 74u, 110u, 150u,
- 54u, 95u, 37u, 112u,
- 127u, 242u, 82u, 233u,
- 130u, 126u, 1u, 141u,
- 122u, 174u, 152u, 130u,
- 175u, 139u, 107u, 54u,
- 88u, 64u, 20u, 169u,
- 7u, 173u, 129u, 86u,
- 133u, 69u, 155u, 255u,
- 41u, 184u, 107u, 127u,
- 104u, 98u, 59u, 202u,
- 81u, 67u, 255u, 109u,
- 87u, 53u, 136u, 245u,
- 114u, 255u, 31u, 209u,
- 40u, 120u, 24u, 184u,
- 73u, 191u, 136u, 79u,
- 94u, 174u, 47u, 93u,
- 105u, 123u, 49u, 106u,
- 168u, 134u, 208u, 255u,
- 170u, 117u, 60u, 73u,
- 62u, 99u, 84u, 138u,
- 193u, 113u, 68u, 83u,
- 240u, 205u, 207u, 143u,
- 24u, 188u, 1u, 58u,
- 240u, 145u, 138u, 147u,
- 107u, 122u, 74u, 98u,
- 143u, 1u, 92u, 127u,
- 33u, 190u, 100u, 81u,
- 104u, 98u, 213u, 215u,
- 79u, 128u, 62u, 101u,
- 1u, 217u, 174u, 234u,
- 13u, 238u, 86u, 225u,
- 112u, 176u, 49u, 210u,
- 154u, 88u, 229u, 232u,
- 71u, 176u, 187u, 133u,
- 172u, 255u, 86u, 198u,
- 193u, 54u, 19u, 253u,
- 88u, 194u, 170u, 136u,
- 29u, 96u, 87u, 52u,
- 50u, 104u, 171u, 79u,
- 83u, 67u, 255u, 163u,
- 223u, 157u, 107u, 255u,
- 132u, 131u, 175u, 190u,
- 199u, 98u, 42u, 127u,
- 176u, 114u, 187u, 104u,
- 129u, 101u, 141u, 35u,
- 186u, 196u, 243u, 255u,
- 92u, 141u, 166u, 71u,
- 75u, 100u, 176u, 168u,
- 203u, 183u, 245u, 88u,
- 93u, 164u, 220u, 137u,
- 82u, 12u, 30u, 136u,
- 218u, 255u, 138u, 119u,
- 181u, 135u, 126u, 38u,
- 86u, 83u, 76u, 110u,
- 169u, 67u, 168u, 242u,
- 1u, 248u, 39u, 134u,
- 71u, 62u, 137u, 85u,
- 99u, 97u, 255u, 41u,
- 164u, 117u, 60u, 113u,
- 54u, 195u, 93u, 162u,
- 208u, 57u, 117u, 155u,
- 128u, 130u, 203u, 138u,
- 200u, 163u, 147u, 101u,
- 255u, 246u, 223u, 83u,
- 102u, 51u, 80u, 110u,
- 222u, 108u, 9u, 52u,
- 103u, 255u, 19u, 49u,
- 115u, 181u, 17u, 134u,
- 152u, 116u, 146u, 158u,
- 106u, 1u, 130u, 144u,
- 79u, 57u, 9u, 15u,
- 90u, 158u, 251u, 62u,
- 100u, 133u, 94u, 2u,
- 195u, 136u, 164u, 255u,
- 96u, 149u, 160u, 159u,
- 134u, 116u, 173u, 210u,
- 255u, 114u, 174u, 206u,
- 121u, 222u, 138u, 122u,
- 57u, 32u, 35u, 182u,
- 92u, 137u, 59u, 113u,
- 116u, 58u, 93u, 107u,
- 119u, 221u, 193u, 160u,
- 142u, 195u, 60u, 223u,
- 86u, 255u, 62u, 147u,
- 96u, 1u, 119u, 172u,
- 185u, 60u, 127u, 199u,
- 62u, 220u, 18u, 99u,
- 75u, 91u, 128u, 88u,
- 144u, 100u, 76u, 59u,
- 114u, 134u, 63u, 205u,
- 0u, 177u, 158u, 109u,
- 138u, 44u, 128u, 128u,
- 169u, 236u, 40u, 69u,
- 61u, 128u, 93u, 167u,
- 101u, 1u, 107u, 108u,
- 143u, 215u, 164u, 214u,
- 58u, 153u, 47u, 217u,
- 1u, 189u, 92u, 138u,
- 184u, 221u, 168u, 44u,
- 90u, 136u, 100u, 171u,
- 86u, 59u, 185u, 59u,
- 127u, 163u, 186u, 177u,
- 190u, 136u, 1u, 65u,
- 48u, 105u, 144u, 250u,
- 57u, 146u, 122u, 13u,
- 29u, 182u, 65u, 123u,
- 41u, 225u, 255u, 116u,
- 92u, 91u, 183u, 149u,
- 195u, 208u, 143u, 1u,
- 66u, 121u, 162u, 125u,
- 168u, 164u, 186u, 95u,
- 164u, 160u, 114u, 40u,
- 182u, 31u, 129u, 202u,
- 20u, 230u, 0u, 136u,
- 161u, 53u, 179u, 72u,
- 60u, 146u, 195u, 98u,
- 255u, 160u, 119u, 39u,
- 177u, 190u, 169u, 150u,
- 152u, 166u, 98u, 123u,
- 131u, 228u, 191u, 112u,
- 82u, 119u, 174u, 112u,
- 48u, 195u, 255u, 161u,
- 103u, 91u, 19u, 63u,
- 170u, 59u, 67u, 68u,
- 103u, 103u, 66u, 117u,
- 95u, 71u, 255u, 233u,
- 142u, 138u, 37u, 73u,
- 73u, 166u, 50u, 104u,
- 155u, 124u, 6u, 109u,
- 88u, 99u, 131u, 40u,
- 84u, 157u, 108u, 228u,
- 181u, 185u, 255u, 129u,
- 123u, 119u, 117u, 100u,
- 152u, 84u, 98u, 135u,
- 146u, 255u, 236u, 119u,
- 102u, 121u, 147u, 129u,
- 255u, 111u, 223u, 168u,
- 80u, 189u, 197u, 72u,
- 111u, 200u, 111u, 168u,
- 194u, 150u, 1u, 134u,
- 92u, 1u, 39u, 239u,
- 73u, 116u, 163u, 159u,
- 34u, 126u, 33u, 133u,
- 187u, 153u, 109u, 14u,
- 18u, 87u, 111u, 191u,
- 79u, 55u, 219u, 1u,
- 58u, 144u, 110u, 143u,
- 161u, 138u, 148u, 190u,
- 255u, 217u, 197u, 157u,
- 93u, 159u, 61u, 65u,
- 149u, 87u, 216u, 40u,
- 12u, 50u, 80u, 186u,
- 128u, 128u, 255u, 132u,
- 196u, 129u, 130u, 112u,
- 125u, 22u, 66u, 162u,
- 168u, 146u, 199u, 104u,
- 23u, 100u, 57u, 232u,
- 1u, 159u, 82u, 57u,
- 37u, 164u, 168u, 205u,
- 175u, 47u, 104u, 116u,
- 255u, 164u, 137u, 20u,
- 123u, 73u, 208u, 220u,
- 213u, 81u, 179u, 144u,
- 129u, 171u, 204u, 138u,
- 67u, 128u, 195u, 92u,
- 13u, 234u, 99u, 65u,
- 82u, 16u, 190u, 200u,
- 105u, 255u, 160u, 228u,
- 76u, 161u, 112u, 192u,
- 93u, 132u, 81u, 103u,
- 71u, 255u, 249u, 232u,
- 152u, 32u, 121u, 111u,
- 177u, 145u, 126u, 255u,
- 167u, 109u, 93u, 25u,
- 139u, 103u, 188u, 222u,
- 233u, 237u, 130u, 62u,
- 57u, 129u, 199u, 173u,
- 182u, 164u, 72u, 29u,
- 119u, 75u, 146u, 105u,
- 211u, 116u, 116u, 1u,
- 66u, 158u, 52u, 80u,
- 183u, 142u, 62u, 193u,
- 239u, 0u, 179u, 185u,
- 72u, 138u, 94u, 76u,
- 62u, 93u, 207u, 40u,
- 67u, 162u, 131u, 111u,
- 152u, 99u, 216u, 62u,
- 133u, 0u, 97u, 85u,
- 255u, 160u, 243u, 187u,
- 12u, 57u, 104u, 75u,
- 132u, 173u, 77u, 166u,
- 87u, 115u, 72u, 144u,
- 143u, 126u, 53u, 202u,
- 57u, 135u, 56u, 35u,
- 49u, 153u, 243u, 255u,
- 157u, 153u, 142u, 126u,
- 183u, 118u, 8u, 79u,
- 167u, 26u, 243u, 251u,
- 119u, 212u, 129u, 153u,
- 181u, 140u, 113u, 1u,
- 48u, 158u, 205u, 59u,
- 20u, 158u, 169u, 129u,
- 164u, 255u, 243u, 137u,
- 100u, 31u, 119u, 183u,
- 97u, 118u, 180u, 53u,
- 197u, 193u, 137u, 103u,
- 247u, 63u, 0u, 114u,
- 63u, 136u, 134u, 111u,
- 33u, 114u, 221u, 47u,
- 129u, 84u, 137u, 106u,
- 54u, 255u, 69u, 198u,
- 125u, 121u, 214u, 134u,
- 142u, 96u, 255u, 70u,
- 151u, 89u, 238u, 79u,
- 125u, 222u, 109u, 157u,
- 192u, 69u, 184u, 145u,
- 149u, 45u, 139u, 158u,
- 78u, 99u, 195u, 68u,
- 107u, 206u, 88u, 186u,
- 133u, 255u, 51u, 173u,
- 201u, 40u, 178u, 38u,
- 218u, 26u, 1u, 55u,
- 188u, 236u, 198u, 231u,
- 61u, 83u, 85u, 215u,
- 255u, 187u, 238u, 147u,
- 151u, 44u, 36u, 7u,
- 67u, 228u, 119u, 112u,
- 111u, 210u, 73u, 71u,
- 171u, 182u, 85u, 173u,
- 145u, 160u, 127u, 121u,
- 48u, 79u, 86u, 16u,
- 146u, 1u, 132u, 88u,
- 134u, 68u, 117u, 135u,
- 66u, 87u, 255u, 61u,
- 41u, 71u, 56u, 145u,
- 149u, 49u, 41u, 148u,
- 239u, 131u, 136u, 1u,
- 84u, 45u, 46u, 138u,
- 93u, 213u, 30u, 223u,
- 93u, 112u, 161u, 170u,
- 47u, 87u, 6u, 93u,
- 136u, 129u, 122u, 89u,
- 161u, 108u, 232u, 255u,
- 179u, 151u, 133u, 71u,
- 235u, 86u, 110u, 116u,
- 45u, 109u, 168u, 223u,
- 28u, 169u, 76u, 150u,
- 1u, 42u, 100u, 124u,
- 123u, 100u, 145u, 139u,
- 184u, 75u, 73u, 126u,
- 192u, 233u, 97u, 103u,
- 191u, 54u, 0u, 34u,
- 122u, 137u, 70u, 175u,
- 186u, 88u, 0u, 117u,
- 131u, 198u, 67u, 69u,
- 135u, 85u, 95u, 161u,
- 220u, 62u, 206u, 41u,
- 255u, 86u, 89u, 76u,
- 22u, 179u, 93u, 121u,
- 113u, 23u, 174u, 186u,
- 219u, 41u, 36u, 56u,
- 115u, 1u, 32u, 112u,
- 146u, 151u, 181u, 198u,
- 66u, 125u, 39u, 60u,
- 150u, 255u, 114u, 139u,
- 41u, 87u, 152u, 67u,
- 148u, 206u, 99u, 155u,
- 159u, 148u, 215u, 137u,
- 171u, 97u, 43u, 202u,
- 207u, 75u, 131u, 93u,
- 157u, 103u, 173u, 59u,
- 141u, 183u, 167u, 1u,
- 136u, 62u, 155u, 93u,
- 110u, 140u, 170u, 53u,
- 134u, 159u, 43u, 33u,
- 113u, 255u, 155u, 164u,
- 82u, 77u, 96u, 118u,
- 1u, 151u, 142u, 163u,
- 129u, 68u, 146u, 141u,
- 99u, 56u, 30u, 129u,
- 219u, 99u, 99u, 255u,
- 56u, 64u, 166u, 128u,
- 154u, 164u, 141u, 159u,
- 120u, 34u, 159u, 36u,
- 167u, 117u, 45u, 135u,
- 158u, 126u, 158u, 167u,
- 57u, 3u, 73u, 151u,
- 215u, 238u, 162u, 1u,
- 190u, 101u, 101u, 240u,
- 176u, 198u, 149u, 25u,
- 198u, 120u, 71u, 229u,
- 215u, 31u, 186u, 1u,
- 172u, 165u, 133u, 34u,
- 40u, 92u, 181u, 157u,
- 17u, 94u, 119u, 130u,
- 156u, 217u, 255u, 145u,
- 119u, 83u, 13u, 63u,
- 117u, 137u, 85u, 255u,
- 252u, 120u, 124u, 31u,
- 159u, 54u, 124u, 6u,
- 112u, 175u, 116u, 101u,
- 48u, 153u, 1u, 131u,
- 216u, 116u, 147u, 129u,
- 80u, 54u, 79u, 129u,
- 179u, 192u, 150u, 255u,
- 120u, 190u, 75u, 109u,
- 182u, 11u, 57u, 84u,
- 191u, 86u, 56u, 39u,
- 204u, 255u, 105u, 144u,
- 24u, 112u, 135u, 43u,
- 84u, 151u, 222u, 84u,
- 152u, 89u, 156u, 97u,
- 100u, 156u, 99u, 140u,
- 97u, 90u, 1u, 102u,
- 148u, 191u, 181u, 123u,
- 22u, 18u, 51u, 132u,
- 51u, 209u, 36u, 63u,
- 132u, 70u, 143u, 179u,
- 117u, 129u, 182u, 137u,
- 1u, 74u, 112u, 75u,
- 22u, 77u, 124u, 159u,
- 54u, 94u, 217u, 160u,
- 124u, 255u, 140u, 84u,
- 68u, 29u, 98u, 143u,
- 90u, 152u, 208u, 70u,
- 53u, 51u, 99u, 100u,
- 191u, 63u, 255u, 124u,
- 126u, 20u, 167u, 117u,
- 112u, 118u, 93u, 97u,
- 65u, 163u, 41u, 98u,
- 160u, 169u, 114u, 107u,
- 0u, 78u, 123u, 195u,
- 252u, 183u, 133u, 62u,
- 1u, 7u, 87u, 243u,
- 49u, 143u, 19u, 146u,
- 186u, 213u, 137u, 140u,
- 147u, 87u, 106u, 187u,
- 69u, 58u, 162u, 110u,
- 255u, 105u, 238u, 185u,
- 92u, 164u, 52u, 144u,
- 129u, 63u, 149u, 101u,
- 119u, 83u, 216u, 255u,
- 121u, 170u, 36u, 31u,
- 82u, 159u, 98u, 156u,
- 143u, 114u, 229u, 123u,
- 1u, 124u, 179u, 160u,
- 48u, 249u, 16u, 127u,
- 210u, 75u, 100u, 129u,
- 75u, 147u, 181u, 30u,
- 97u, 242u, 12u, 136u,
- 106u, 140u, 135u, 95u,
- 125u, 71u, 213u, 255u,
- 166u, 40u, 132u, 193u,
- 0u, 168u, 229u, 111u,
- 74u, 181u, 31u, 119u,
- 121u, 20u, 119u, 91u,
- 145u, 170u, 255u, 159u,
- 151u, 141u, 204u, 149u,
- 138u, 44u, 84u, 203u,
- 198u, 3u, 120u, 138u,
- 26u, 148u, 155u, 196u,
- 0u, 131u, 202u, 24u,
- 43u, 173u, 91u, 108u,
- 201u, 149u, 80u, 120u,
- 250u, 95u, 63u, 128u,
- 128u, 137u, 31u, 155u,
- 166u, 110u, 118u, 57u,
- 221u, 255u, 95u, 92u,
- 103u, 182u, 61u, 207u,
- 81u, 144u, 129u, 138u,
- 49u, 135u, 141u, 35u,
- 186u, 1u, 125u, 150u,
- 168u, 76u, 124u, 178u,
- 150u, 128u, 47u, 153u,
- 119u, 117u, 107u, 0u,
- 175u, 173u, 175u, 41u,
- 180u, 132u, 172u, 138u,
- 1u, 159u, 249u, 146u,
- 71u, 111u, 33u, 202u,
- 41u, 132u, 49u, 145u,
- 1u, 83u, 56u, 83u,
- 89u, 107u, 105u, 154u,
- 27u, 142u, 105u, 141u,
- 195u, 43u, 216u, 204u,
- 70u, 250u, 168u, 1u,
- 109u, 148u, 181u, 107u,
- 28u, 134u, 176u, 113u,
- 82u, 75u, 155u, 119u,
- 196u, 172u, 125u, 223u,
- 31u, 150u, 1u, 99u,
- 125u, 124u, 67u, 63u,
- 164u, 166u, 88u, 132u,
- 146u, 142u, 49u, 183u,
- 206u, 187u, 189u, 196u,
- 221u, 103u, 52u, 158u,
- 255u, 122u, 121u, 154u,
- 78u, 160u, 67u, 124u,
- 0u, 93u, 145u, 119u,
- 250u, 174u, 180u, 67u,
- 230u, 23u, 121u, 150u,
- 107u, 43u, 24u, 250u,
- 189u, 104u, 180u, 154u,
- 90u, 60u, 1u, 167u,
- 74u, 156u, 112u, 124u,
- 115u, 97u, 167u, 140u,
- 118u, 142u, 203u, 59u,
- 211u, 1u, 165u, 162u,
- 197u, 134u, 173u, 95u,
- 186u, 255u, 218u, 157u,
- 56u, 169u, 136u, 241u,
- 109u, 64u, 147u, 133u,
- 177u, 84u, 60u, 2u,
- 123u, 105u, 197u, 192u,
- 137u, 138u, 255u, 101u,
- 152u, 179u, 71u, 57u,
- 163u, 178u, 97u, 52u,
- 163u, 227u, 169u, 225u,
- 35u, 233u, 55u, 255u,
- 188u, 160u, 206u, 59u,
- 226u, 116u, 89u, 52u,
- 163u, 103u, 215u, 134u,
- 107u, 17u, 194u, 1u,
- 233u, 116u, 100u, 59u,
- 111u, 161u, 175u, 80u,
- 77u, 5u, 92u, 207u,
- 224u, 164u, 127u, 194u,
- 29u, 103u, 1u, 141u,
- 161u, 165u, 88u, 30u,
- 160u, 113u, 94u, 42u,
- 255u, 206u, 135u, 109u,
- 85u, 115u, 155u, 211u,
- 180u, 254u, 130u, 102u,
- 201u, 158u, 228u, 125u,
- 132u, 213u, 102u, 131u,
- 83u, 150u, 216u, 179u,
- 255u, 150u, 150u, 106u,
- 1u, 97u, 141u, 4u,
- 16u, 53u, 11u, 206u,
- 27u, 130u, 115u, 152u,
- 57u, 109u, 195u, 60u,
- 255u, 203u, 76u, 206u,
- 124u, 159u, 117u, 203u,
- 34u, 223u, 167u, 135u,
- 109u, 2u, 90u, 113u,
- 133u, 148u, 165u, 155u,
- 47u, 181u, 255u, 89u,
- 92u, 160u, 101u, 119u,
- 190u, 142u, 143u, 148u,
- 214u, 75u, 169u, 85u,
- 82u, 92u, 49u, 1u,
- 97u, 133u, 195u, 15u,
- 204u, 184u, 227u, 86u,
- 113u, 173u, 57u, 164u,
- 255u, 130u, 120u, 106u,
- 61u, 209u, 85u, 104u,
- 207u, 226u, 150u, 98u,
- 120u, 55u, 75u, 217u,
- 76u, 88u, 109u, 114u,
- 187u, 153u, 129u, 201u,
- 181u, 92u, 158u, 1u,
- 155u, 137u, 203u, 70u,
- 228u, 181u, 106u, 161u,
- 131u, 168u, 1u, 153u,
- 44u, 228u, 28u, 109u,
- 83u, 109u, 0u, 169u,
- 193u, 178u, 73u, 211u,
- 142u, 127u, 46u, 86u,
- 134u, 137u, 176u, 187u,
- 127u, 176u, 191u, 113u,
- 149u, 111u, 208u, 177u,
- 179u, 175u, 69u, 154u,
- 100u, 0u, 126u, 111u,
- 173u, 84u, 172u, 145u,
- 255u, 109u, 68u, 95u,
- 142u, 77u, 121u, 193u,
- 70u, 188u, 86u, 167u,
- 138u, 52u, 10u, 50u,
- 80u, 112u, 1u, 49u,
- 57u, 107u, 168u, 193u,
- 19u, 100u, 126u, 137u,
- 54u, 157u, 113u, 146u,
- 87u, 100u, 74u, 112u,
- 47u, 255u, 108u, 173u,
- 167u, 84u, 97u, 109u,
- 114u, 109u, 126u, 147u,
- 255u, 93u, 252u, 69u,
- 121u, 71u, 102u, 185u,
- 47u, 63u, 103u, 107u,
- 169u, 132u, 106u, 113u,
- 133u, 125u, 255u, 183u,
- 240u, 122u, 68u, 194u,
- 37u, 179u, 100u, 184u,
- 80u, 94u, 186u, 187u,
- 49u, 174u, 19u, 117u,
- 107u, 127u, 255u, 31u,
- 89u, 207u, 231u, 130u,
- 187u, 101u, 170u, 59u,
- 134u, 133u, 226u, 113u,
- 255u, 151u, 82u, 54u,
- 130u, 212u, 64u, 236u,
- 107u, 104u, 161u, 190u,
- 210u, 171u, 100u, 100u,
- 86u, 122u, 87u, 98u,
- 105u, 1u, 88u, 76u,
- 1u, 140u, 175u, 79u,
- 169u, 149u, 70u, 192u,
- 143u, 102u, 170u, 110u,
- 151u, 193u, 153u, 148u,
- 105u, 95u, 94u, 42u,
- 145u, 145u, 103u, 186u,
- 98u, 158u, 150u, 89u,
- 100u, 117u, 169u, 255u,
- 129u, 120u, 170u, 193u,
- 28u, 201u, 154u, 115u,
- 255u, 146u, 139u, 170u,
- 120u, 154u, 37u, 157u,
- 142u, 85u, 110u, 118u,
- 85u, 172u, 167u, 170u,
- 255u, 107u, 182u, 164u,
- 127u, 166u, 127u, 136u,
- 255u, 230u, 145u, 110u,
- 203u, 131u, 83u, 29u,
- 198u, 236u, 162u, 178u,
- 255u, 225u, 174u, 106u,
- 159u, 127u, 150u, 171u,
- 156u, 62u, 94u, 79u,
- 122u, 149u, 134u, 90u,
- 158u, 170u, 141u, 1u,
- 173u, 181u, 140u, 206u,
- 226u, 170u, 182u, 1u,
- 136u, 197u, 143u, 162u,
- 191u, 35u, 84u, 143u,
- 76u, 117u, 185u, 163u,
- 255u, 129u, 117u, 76u,
- 58u, 164u, 102u, 127u,
- 117u, 159u, 125u, 159u,
- 154u, 111u, 86u, 180u,
- 178u, 63u, 191u, 136u,
- 173u, 217u, 1u, 163u,
- 33u, 42u, 42u, 108u,
- 49u, 127u, 255u, 81u,
- 232u, 58u, 159u, 54u,
- 36u, 113u, 47u, 161u,
- 174u, 159u, 200u, 118u,
- 151u, 110u, 125u, 27u,
- 115u, 139u, 98u, 119u,
- 113u, 174u, 122u, 101u,
- 139u, 153u, 174u, 255u,
- 210u, 220u, 15u, 108u,
- 104u, 223u, 5u, 255u,
- 64u, 56u, 239u, 160u,
- 213u, 44u, 7u, 70u,
- 143u, 143u, 101u, 162u,
- 119u, 169u, 255u, 83u,
- 76u, 215u, 99u, 157u,
- 138u, 178u, 149u, 220u,
- 71u, 146u, 96u, 1u,
- 140u, 134u, 73u, 48u,
- 29u, 113u, 163u, 137u,
- 107u, 85u, 22u, 178u,
- 156u, 133u, 225u, 60u,
- 84u, 158u, 85u, 66u,
- 227u, 184u, 173u, 255u,
- 169u, 64u, 43u, 185u,
- 106u, 0u, 156u, 162u,
- 83u, 191u, 172u, 42u,
- 143u, 78u, 60u, 117u,
- 165u, 85u, 135u, 169u,
- 148u, 136u, 156u, 59u,
- 133u, 255u, 85u, 117u,
- 41u, 138u, 144u, 63u,
- 106u, 195u, 121u, 156u,
- 142u, 178u, 210u, 101u,
- 178u, 105u, 96u, 62u,
- 18u, 56u, 86u, 132u,
- 109u, 255u, 169u, 196u,
- 123u, 95u, 0u, 156u,
- 120u, 76u, 240u, 106u,
- 119u, 170u, 102u, 221u,
- 142u, 239u, 215u, 179u,
- 1u, 136u, 55u, 191u,
- 221u, 125u, 105u, 81u,
- 174u, 147u, 137u, 114u,
- 145u, 69u, 106u, 220u,
- 86u, 187u, 78u, 241u,
- 96u, 42u, 200u, 79u,
- 74u, 22u, 162u, 148u,
- 2u, 1u, 157u, 223u,
- 77u, 179u, 114u, 152u,
- 150u, 61u, 205u, 104u,
- 35u, 214u, 212u, 200u,
- 255u, 71u, 132u, 96u,
- 119u, 0u, 119u, 90u,
- 54u, 71u, 149u, 71u,
- 98u, 164u, 182u, 98u,
- 141u, 1u, 170u, 117u,
- 29u, 192u, 101u, 152u,
- 194u, 33u, 76u, 202u,
- 158u, 236u, 255u, 180u,
- 163u, 73u, 180u, 78u,
- 235u, 153u, 92u, 217u,
- 173u, 255u, 215u, 99u,
- 153u, 167u, 160u, 191u,
- 192u, 245u, 62u, 88u,
- 189u, 185u, 55u, 159u,
- 49u, 126u, 173u, 149u,
- 179u, 93u, 143u, 107u,
- 148u, 134u, 78u, 1u,
- 138u, 100u, 186u, 125u,
- 113u, 196u, 184u, 255u,
- 111u, 80u, 140u, 98u,
- 103u, 136u, 33u, 48u,
- 211u, 137u, 201u, 136u,
- 118u, 1u, 108u, 53u,
- 109u, 156u, 95u, 79u,
- 170u, 113u, 73u, 108u,
- 167u, 168u, 94u, 172u,
- 117u, 155u, 200u, 23u,
- 178u, 201u, 124u, 131u,
- 178u, 140u, 255u, 169u,
- 177u, 181u, 250u, 92u,
- 192u, 127u, 124u, 161u,
- 202u, 80u, 112u, 118u,
- 64u, 255u, 43u, 119u,
- 87u, 131u, 173u, 186u,
- 137u, 155u, 92u, 62u,
- 183u, 1u, 128u, 99u,
- 166u, 164u, 156u, 182u,
- 67u, 223u, 227u, 42u,
- 78u, 215u, 255u, 201u,
- 133u, 2u, 195u, 201u,
- 121u, 191u, 175u, 188u,
- 232u, 21u, 162u, 46u,
- 186u, 103u, 231u, 126u,
- 129u, 4u, 255u, 254u,
- 39u, 172u, 119u, 211u,
- 190u, 125u, 125u, 160u,
- 107u, 76u, 165u, 116u,
- 232u, 203u, 126u, 71u,
- 255u, 169u, 49u, 83u,
- 56u, 190u, 128u, 84u,
- 205u, 184u, 177u, 117u,
- 104u, 136u, 91u, 95u,
- 155u, 203u, 193u, 255u,
- 120u, 208u, 177u, 145u,
- 142u, 226u, 109u, 104u,
- 126u, 1u, 86u, 76u,
- 188u, 255u, 209u, 125u,
- 191u, 255u, 83u, 242u,
- 43u, 13u, 218u, 66u,
- 182u, 226u, 130u, 60u,
- 79u, 62u, 190u, 105u,
- 50u, 24u, 143u, 226u,
- 120u, 1u, 188u, 153u,
- 167u, 116u, 22u, 220u,
- 220u, 200u, 228u, 94u,
- 180u, 165u, 109u, 190u,
- 138u, 95u, 182u, 1u,
- 101u, 114u, 88u, 143u,
- 154u, 202u, 136u, 98u,
- 132u, 111u, 167u, 90u,
- 35u, 252u, 184u, 45u,
- 99u, 200u, 59u, 166u,
- 129u, 233u, 178u, 1u,
- 160u, 126u, 148u, 162u,
- 114u, 131u, 76u, 156u,
- 137u, 134u, 176u, 133u,
- 159u, 122u, 1u, 102u,
- 247u, 60u, 127u, 197u,
- 130u, 88u, 44u, 139u,
- 186u, 121u, 55u, 176u,
- 87u, 1u, 33u, 77u,
- 50u, 91u, 131u, 116u,
- 113u, 168u, 178u, 225u,
- 40u, 115u, 0u, 13u,
- 106u, 61u, 186u, 135u,
- 190u, 90u, 140u, 172u,
- 1u, 152u, 210u, 103u,
- 141u, 132u, 104u, 109u,
- 148u, 111u, 144u, 103u,
- 168u, 51u, 220u, 149u,
- 29u, 14u, 219u, 159u,
- 230u, 186u, 255u, 126u,
- 57u, 52u, 83u, 110u,
- 192u, 154u, 237u, 190u,
- 109u, 153u, 84u, 103u,
- 124u, 154u, 64u, 43u,
- 158u, 255u, 215u, 171u,
- 173u, 134u, 38u, 156u,
- 149u, 69u, 168u, 155u,
- 1u, 76u, 83u, 192u,
- 105u, 74u, 111u, 109u,
- 170u, 48u, 136u, 165u,
- 0u, 34u, 153u, 112u,
- 150u, 155u, 218u, 180u,
- 122u, 104u, 171u, 64u,
- 159u, 98u, 141u, 36u,
- 150u, 31u, 255u, 64u,
- 102u, 166u, 206u, 116u,
- 253u, 189u, 45u, 57u,
- 130u, 92u, 91u, 147u,
- 204u, 153u, 231u, 44u,
- 69u, 148u, 18u, 163u,
- 104u, 42u, 255u, 89u,
- 179u, 81u, 138u, 186u,
- 194u, 4u, 29u, 103u,
- 121u, 53u, 157u, 111u,
- 137u, 110u, 85u, 0u,
- 153u, 80u, 144u, 42u,
- 152u, 142u, 250u, 232u,
- 222u, 8u, 167u, 255u,
- 57u, 247u, 35u, 70u,
- 127u, 101u, 77u, 136u,
- 100u, 151u, 183u, 125u,
- 92u, 1u, 100u, 182u,
- 212u, 203u, 126u, 171u,
- 77u, 117u, 132u, 88u,
- 93u, 81u, 146u, 112u,
- 151u, 102u, 215u, 155u,
- 122u, 175u, 255u, 123u,
- 89u, 119u, 91u, 115u,
- 97u, 117u, 209u, 106u,
- 100u, 82u, 174u, 255u,
- 184u, 145u, 152u, 51u,
- 96u, 55u, 98u, 167u,
- 0u, 188u, 202u, 156u,
- 58u, 173u, 90u, 162u,
- 164u, 90u, 142u, 186u,
- 75u, 191u, 255u, 116u,
- 38u, 214u, 195u, 155u,
- 125u, 110u, 35u, 185u,
- 192u, 199u, 116u, 241u,
- 117u, 91u, 203u, 98u,
- 150u, 99u, 147u, 125u,
- 111u, 255u, 133u, 171u,
- 153u, 60u, 125u, 137u,
- 53u, 200u, 64u, 167u,
- 153u, 171u, 67u, 132u,
- 255u, 96u, 211u, 197u,
- 60u, 44u, 240u, 162u,
- 175u, 138u, 153u, 81u,
- 255u, 137u, 173u, 176u,
- 108u, 81u, 90u, 140u,
- 112u, 171u, 59u, 80u,
- 157u, 69u, 241u, 1u,
- 163u, 154u, 132u, 151u,
- 90u, 90u, 105u, 183u,
- 69u, 162u, 163u, 115u,
- 161u, 1u, 172u, 95u,
- 71u, 20u, 56u, 72u,
- 97u, 165u, 143u, 10u,
- 113u, 152u, 124u, 69u,
- 33u, 24u, 184u, 171u,
- 85u, 193u, 208u, 170u,
- 0u, 205u, 140u, 161u,
- 164u, 105u, 100u, 237u,
- 140u, 1u, 146u, 152u,
- 185u, 107u, 84u, 138u,
- 209u, 85u, 112u, 68u,
- 134u, 176u, 162u, 60u,
- 199u, 111u, 157u, 145u,
- 134u, 110u, 128u, 142u,
- 255u, 24u, 74u, 151u,
- 108u, 99u, 86u, 82u,
- 216u, 124u, 71u, 1u,
- 165u, 85u, 162u, 127u,
- 130u, 135u, 134u, 202u,
- 77u, 120u, 156u, 135u,
- 66u, 136u, 148u, 99u,
- 1u, 154u, 55u, 142u,
- 148u, 102u, 174u, 104u,
- 77u, 88u, 101u, 146u,
- 120u, 173u, 212u, 15u,
- 108u, 105u, 1u, 196u,
- 219u, 55u, 116u, 83u,
- 1u, 131u, 17u, 130u,
- 97u, 126u, 128u, 115u,
- 1u, 101u, 208u, 22u,
- 98u, 155u, 154u, 181u,
- 178u, 92u, 233u, 104u,
- 68u, 107u, 230u, 97u,
- 116u, 201u, 148u, 255u,
- 78u, 184u, 131u, 98u,
- 182u, 85u, 206u, 128u,
- 143u, 160u, 65u, 199u,
- 1u, 88u, 127u, 188u,
- 87u, 174u, 181u, 114u,
- 108u, 135u, 169u, 123u,
- 150u, 176u, 213u, 106u,
- 159u, 199u, 56u, 163u,
- 156u, 95u, 93u, 38u,
- 179u, 255u, 160u, 43u,
- 73u, 98u, 255u, 182u,
- 165u, 184u, 180u, 19u,
- 137u, 160u, 39u, 58u,
- 109u, 246u, 223u, 123u,
- 59u, 41u, 178u, 1u,
- 213u, 72u, 137u, 153u,
- 166u, 21u, 74u, 103u,
- 133u, 226u, 222u, 30u,
- 118u, 177u, 71u, 0u,
- 123u, 151u, 68u, 165u,
- 77u, 153u, 112u, 95u,
- 91u, 114u, 144u, 164u,
- 127u, 139u, 130u, 83u,
- 162u, 106u, 61u, 113u,
- 109u, 164u, 149u, 119u,
- 150u, 1u, 164u, 124u,
- 177u, 96u, 107u, 105u,
- 108u, 102u, 216u, 127u,
- 155u, 255u, 118u, 86u,
- 153u, 118u, 180u, 122u,
- 1u, 140u, 144u, 28u,
- 181u, 166u, 118u, 124u,
- 88u, 191u, 202u, 183u,
- 184u, 173u, 119u, 138u,
- 40u, 110u, 138u, 146u,
- 78u, 127u, 109u, 158u,
- 148u, 22u, 154u, 20u,
- 123u, 0u, 42u, 68u,
- 113u, 109u, 117u, 1u,
- 43u, 111u, 165u, 119u,
- 106u, 143u, 141u, 104u,
- 73u, 68u, 142u, 177u,
- 86u, 145u, 118u, 149u,
- 62u, 175u, 64u, 103u,
- 243u, 162u, 191u, 198u,
- 131u, 0u, 69u, 180u,
- 129u, 119u, 36u, 128u,
- 15u, 93u, 88u, 178u,
- 1u, 92u, 95u, 106u,
- 135u, 103u, 201u, 158u,
- 134u, 194u, 92u, 66u,
- 36u, 154u, 135u, 138u,
- 186u, 92u, 255u, 220u,
- 174u, 118u, 60u, 162u,
- 179u, 106u, 200u, 10u,
- 182u, 171u, 1u, 98u,
- 126u, 192u, 171u, 68u,
- 40u, 167u, 145u, 232u,
- 151u, 120u, 108u, 207u,
- 255u, 73u, 138u, 82u,
- 161u, 211u, 138u, 72u,
- 207u, 81u, 71u, 75u,
- 157u, 157u, 84u, 160u,
- 20u, 160u, 123u, 170u,
- 84u, 42u, 136u, 124u,
- 89u, 1u, 126u, 169u,
- 1u, 90u, 110u, 145u,
- 130u, 52u, 234u, 182u,
- 142u, 133u, 161u, 167u,
- 169u, 167u, 61u, 118u,
- 151u, 112u, 4u, 150u,
- 172u, 119u, 210u, 222u,
- 140u, 228u, 100u, 110u,
- 212u, 1u, 110u, 87u,
- 171u, 186u, 142u, 0u,
- 123u, 147u, 184u, 108u,
- 160u, 153u, 252u, 209u,
- 106u, 211u, 141u, 145u,
- 198u, 231u, 39u, 124u,
- 224u, 22u, 134u, 120u,
- 142u, 222u, 37u, 136u,
- 255u, 10u, 172u, 220u,
- 123u, 206u, 175u, 1u,
- 156u, 164u, 25u, 165u,
- 192u, 76u, 139u, 188u,
- 62u, 112u, 34u, 75u,
- 211u, 131u, 156u, 131u,
- 142u, 103u, 164u, 114u,
- 189u, 7u, 126u, 101u,
- 199u, 207u, 80u, 1u,
- 135u, 47u, 251u, 1u,
- 171u, 217u, 185u, 236u,
- 216u, 92u, 169u, 141u,
- 174u, 183u, 71u, 157u,
- 105u, 177u, 95u, 200u,
- 0u, 182u, 51u, 103u,
- 156u, 93u, 181u, 17u,
- 111u, 88u, 169u, 149u,
- 62u, 66u, 249u, 45u,
- 214u, 225u, 157u, 140u,
- 56u, 245u, 65u, 219u,
- 191u, 127u, 1u, 133u,
- 101u, 171u, 127u, 169u,
- 77u, 206u, 141u, 178u,
- 171u, 121u, 170u, 153u,
- 89u, 95u, 1u, 116u,
- 162u, 122u, 52u, 162u,
- 21u, 96u, 1u, 39u,
- 128u, 146u, 211u, 43u,
- 56u, 222u, 149u, 25u,
- 130u, 66u, 220u, 68u,
- 126u, 53u, 161u, 64u,
- 105u, 100u, 110u, 97u,
- 84u, 112u, 225u, 1u,
- 158u, 100u, 123u, 92u,
- 120u, 79u, 255u, 222u,
- 71u, 216u, 62u, 163u,
- 2u, 91u, 97u, 180u,
- 90u, 92u, 11u, 200u,
- 69u, 166u, 158u, 200u,
- 158u, 179u, 144u, 181u,
- 117u, 54u, 1u, 74u,
- 56u, 79u, 207u, 45u,
- 255u, 116u, 206u, 53u,
- 102u, 89u, 86u, 121u,
- 71u, 245u, 250u, 163u,
- 126u, 91u, 170u, 172u,
- 36u, 96u, 211u, 63u,
- 220u, 93u, 1u, 153u,
- 169u, 97u, 119u, 93u,
- 71u, 117u, 3u, 91u,
- 104u, 213u, 79u, 53u,
- 218u, 71u, 203u, 170u,
- 233u, 1u, 69u, 205u,
- 117u, 120u, 123u, 175u,
- 152u, 146u, 119u, 62u,
- 80u, 1u, 119u, 96u,
- 164u, 193u, 104u, 51u,
- 166u, 32u, 146u, 106u,
- 57u, 100u, 30u, 255u,
- 209u, 77u, 116u, 138u,
- 87u, 251u, 81u, 199u,
- 29u, 166u, 90u, 98u,
- 71u, 181u, 149u, 1u,
- 229u, 31u, 214u, 129u,
- 100u, 63u, 194u, 141u,
- 152u, 74u, 22u, 82u,
- 80u, 16u, 100u, 136u,
- 170u, 193u, 136u, 190u,
- 114u, 1u, 116u, 122u,
- 220u, 72u, 130u, 159u,
- 123u, 158u, 255u, 176u,
- 152u, 185u, 159u, 114u,
- 227u, 171u, 76u, 64u,
- 170u, 92u, 173u, 148u,
- 92u, 123u, 108u, 181u,
- 255u, 134u, 110u, 100u,
- 94u, 47u, 56u, 152u,
- 152u, 84u, 120u, 1u,
- 150u, 85u, 101u, 145u,
- 77u, 193u, 158u, 42u,
- 114u, 102u, 226u, 176u,
- 111u, 17u, 116u, 255u,
- 165u, 123u, 155u, 139u,
- 109u, 57u, 132u, 121u,
- 115u, 173u, 166u, 108u,
- 66u, 96u, 75u, 112u,
- 255u, 98u, 64u, 137u,
- 127u, 61u, 159u, 88u,
- 94u, 227u, 111u, 141u,
- 30u, 65u, 125u, 150u,
- 117u, 86u, 137u, 48u,
- 188u, 98u, 145u, 101u,
- 132u, 212u, 255u, 207u,
- 174u, 183u, 205u, 132u,
- 7u, 210u, 153u, 73u,
- 78u, 95u, 130u, 96u,
- 255u, 159u, 221u, 108u,
- 240u, 119u, 145u, 72u,
- 162u, 137u, 31u, 192u,
- 219u, 120u, 164u, 99u,
- 102u, 255u, 75u, 185u,
- 99u, 144u, 196u, 1u,
- 74u, 89u, 12u, 107u,
- 160u, 149u, 89u, 59u,
- 194u, 41u, 29u, 106u,
- 154u, 128u, 121u, 110u,
- 146u, 215u, 86u, 133u,
- 79u, 130u, 123u, 95u,
- 141u, 255u, 83u, 151u,
- 144u, 136u, 255u, 171u,
- 29u, 179u, 51u, 79u,
- 226u, 212u, 162u, 142u,
- 137u, 125u, 158u, 253u,
- 87u, 106u, 137u, 70u,
- 255u, 229u, 104u, 210u,
- 136u, 110u, 146u, 178u,
- 219u, 117u, 46u, 99u,
- 157u, 255u, 84u, 107u,
- 236u, 187u, 28u, 130u,
- 207u, 20u, 128u, 104u,
- 71u, 177u, 100u, 165u,
- 98u, 136u, 176u, 59u,
- 172u, 172u, 113u, 0u,
- 173u, 184u, 161u, 188u,
- 167u, 86u, 156u, 159u,
- 40u, 166u, 86u, 56u,
- 53u, 70u, 255u, 246u,
- 163u, 88u, 240u, 224u,
- 118u, 132u, 111u, 182u,
- 52u, 115u, 253u, 83u,
- 66u, 105u, 1u, 43u,
- 155u, 58u, 177u, 88u,
- 65u, 168u, 83u, 142u,
- 38u, 255u, 102u, 170u,
- 140u, 94u, 121u, 21u,
- 96u, 40u, 95u, 124u,
- 54u, 83u, 82u, 151u,
- 78u, 147u, 187u, 77u,
- 149u, 169u, 0u, 203u,
- 124u, 129u, 141u, 70u,
- 138u, 157u, 38u, 173u,
- 67u, 137u, 77u, 135u,
- 116u, 93u, 146u, 112u,
- 27u, 132u, 138u, 84u,
- 75u, 127u, 198u, 255u,
- 101u, 90u, 208u, 209u,
- 1u, 146u, 114u, 166u,
- 58u, 103u, 69u, 44u,
- 6u, 144u, 222u, 112u,
- 95u, 126u, 16u, 201u,
- 82u, 255u, 147u, 225u,
- 143u, 121u, 113u, 139u,
- 188u, 48u, 130u, 162u,
- 1u, 42u, 176u, 152u,
- 102u, 191u, 6u, 157u,
- 167u, 174u, 52u, 83u,
- 11u, 81u, 40u, 157u,
- 220u, 120u, 130u, 180u,
- 51u, 15u, 94u, 0u,
- 205u, 110u, 153u, 111u,
- 136u, 201u, 183u, 66u,
- 125u, 161u, 117u, 128u,
- 174u, 80u, 50u, 63u,
- 73u, 173u, 74u, 151u,
- 208u, 53u, 255u, 156u,
- 122u, 130u, 179u, 180u,
- 179u, 167u, 84u, 48u,
- 0u, 40u, 159u, 212u,
- 153u, 224u, 53u, 59u,
- 133u, 88u, 70u, 201u,
- 76u, 206u, 108u, 189u,
- 194u, 244u, 165u, 64u,
- 183u, 125u, 1u, 81u,
- 165u, 156u, 255u, 88u,
- 207u, 215u, 87u, 133u,
- 68u, 95u, 180u, 135u,
- 205u, 126u, 183u, 121u,
- 176u, 168u, 95u, 214u,
- 187u, 53u, 175u, 130u,
- 119u, 255u, 151u, 150u,
- 156u, 181u, 149u, 111u,
- 123u, 58u, 1u, 184u,
- 255u, 101u, 100u, 162u,
- 163u, 112u, 10u, 96u,
- 40u, 230u, 110u, 70u,
- 77u, 120u, 107u, 101u,
- 156u, 162u, 255u, 243u,
- 118u, 241u, 57u, 127u,
- 143u, 83u, 143u, 119u,
- 220u, 69u, 255u, 153u,
- 103u, 81u, 21u, 85u,
- 232u, 118u, 83u, 170u,
- 121u, 95u, 45u, 197u,
- 255u, 147u, 41u, 154u,
- 189u, 137u, 208u, 89u,
- 235u, 180u, 118u, 156u,
- 204u, 107u, 71u, 37u,
- 174u, 237u, 143u, 105u,
- 22u, 178u, 1u, 164u,
- 149u, 150u, 233u, 56u,
- 88u, 36u, 29u, 141u,
- 144u, 80u, 176u, 105u,
- 47u, 106u, 1u, 142u,
- 112u, 151u, 134u, 125u,
- 129u, 58u, 141u, 134u,
- 160u, 129u, 132u, 97u,
- 87u, 78u, 84u, 148u,
- 145u, 147u, 81u, 128u,
- 143u, 101u, 84u, 1u,
- 21u, 134u, 220u, 131u,
- 179u, 147u, 163u, 133u,
- 92u, 213u, 20u, 1u,
- 222u, 174u, 151u, 136u,
- 119u, 125u, 75u, 203u,
- 95u, 109u, 205u, 170u,
- 45u, 255u, 49u, 169u,
- 169u, 96u, 119u, 139u,
- 51u, 165u, 119u, 3u,
- 104u, 57u, 160u, 112u,
- 158u, 230u, 183u, 255u,
- 104u, 219u, 189u, 83u,
- 121u, 130u, 133u, 104u,
- 153u, 121u, 158u, 144u,
- 195u, 148u, 121u, 158u,
- 78u, 1u, 119u, 160u,
- 139u, 228u, 89u, 84u,
- 89u, 199u, 245u, 182u,
- 110u, 133u, 44u, 109u,
- 255u, 131u, 123u, 88u,
- 115u, 81u, 114u, 191u,
- 107u, 1u, 105u, 57u,
- 181u, 119u, 111u, 113u,
- 135u, 100u, 117u, 133u,
- 80u, 215u, 12u, 0u,
- 236u, 105u, 103u, 189u,
- 166u, 24u, 120u, 97u,
- 28u, 252u, 162u, 167u,
- 50u, 220u, 1u, 84u,
- 123u, 117u, 141u, 155u,
- 151u, 107u, 168u, 155u,
- 84u, 205u, 131u, 81u,
- 125u, 30u, 170u, 131u,
- 92u, 146u, 162u, 255u,
- 65u, 142u, 245u, 123u,
- 113u, 189u, 73u, 147u,
- 106u, 156u, 103u, 26u,
- 212u, 83u, 119u, 183u,
- 189u, 20u, 102u, 54u,
- 5u, 255u, 100u, 79u,
- 148u, 124u, 94u, 192u,
- 1u, 116u, 39u, 166u,
- 74u, 138u, 185u, 134u,
- 125u, 60u, 134u, 139u,
- 1u, 172u, 204u, 77u,
- 171u, 87u, 117u, 74u,
- 32u, 179u, 164u, 39u,
- 165u, 23u, 10u, 160u,
- 219u, 160u, 100u, 31u,
- 173u, 192u, 1u, 125u,
- 115u, 177u, 210u, 201u,
- 205u, 130u, 128u, 219u,
- 255u, 59u, 223u, 132u,
- 70u, 85u, 176u, 157u,
- 114u, 158u, 138u, 25u,
- 132u, 110u, 124u, 145u,
- 170u, 155u, 215u, 74u,
- 98u, 151u, 123u, 120u,
- 131u, 91u, 148u, 0u,
- 126u, 140u, 148u, 177u,
- 242u, 227u, 53u, 118u,
- 76u, 122u, 255u, 197u,
- 166u, 122u, 49u, 72u,
- 170u, 187u, 113u, 213u,
- 145u, 253u, 120u, 129u,
- 66u, 15u, 49u, 105u,
- 1u, 177u, 210u, 136u,
- 84u, 172u, 82u, 205u,
- 227u, 131u, 93u, 72u,
- 70u, 1u, 214u, 175u,
- 104u, 214u, 20u, 161u,
- 160u, 214u, 133u, 72u,
- 51u, 116u, 148u, 126u,
- 87u, 52u, 217u, 67u,
- 151u, 113u, 135u, 90u,
- 141u, 1u, 118u, 210u,
- 129u, 160u, 174u, 151u,
- 25u, 140u, 131u, 51u,
- 1u, 65u, 125u, 120u,
- 193u, 52u, 134u, 163u,
- 107u, 62u, 130u, 66u,
- 180u, 35u, 95u, 127u,
- 123u, 225u, 84u, 161u,
- 1u, 216u, 143u, 139u,
- 119u, 106u, 81u, 215u,
- 127u, 63u, 191u, 68u,
- 25u, 169u, 105u, 217u,
- 131u, 118u, 93u, 1u,
- 25u, 122u, 89u, 138u,
- 177u, 207u, 178u, 255u,
- 94u, 107u, 149u, 100u,
- 72u, 4u, 196u, 243u,
- 84u, 151u, 229u, 25u,
- 159u, 146u, 255u, 198u,
- 176u, 175u, 222u, 235u,
- 143u, 140u, 88u, 136u,
- 168u, 179u, 119u, 65u,
- 255u, 213u, 136u, 233u,
- 153u, 31u, 71u, 142u,
- 182u, 243u, 104u, 62u,
- 118u, 144u, 1u, 132u,
- 185u, 48u, 52u, 100u,
- 93u, 225u, 128u, 170u,
- 112u, 152u, 62u, 108u,
- 130u, 66u, 225u, 121u,
- 71u, 117u, 80u, 179u,
- 133u, 124u, 86u, 176u,
- 162u, 1u, 115u, 176u,
- 98u, 74u, 174u, 68u,
- 255u, 148u, 231u, 138u,
- 197u, 80u, 2u, 106u,
- 55u, 142u, 185u, 220u,
- 200u, 209u, 174u, 81u,
- 152u, 249u, 51u, 255u,
- 206u, 248u, 64u, 66u,
- 37u, 77u, 66u, 132u,
- 155u, 147u, 154u, 144u,
- 193u, 162u, 166u, 82u,
- 203u, 117u, 140u, 168u,
- 255u, 44u, 101u, 91u,
- 83u, 77u, 164u, 184u,
- 59u, 56u, 255u, 44u,
- 144u, 174u, 79u, 95u,
- 66u, 65u, 225u, 124u,
- 216u, 156u, 161u, 178u,
- 168u, 154u, 45u, 187u,
- 255u, 73u, 83u, 103u,
- 142u, 137u, 32u, 132u,
- 80u, 141u, 122u, 94u,
- 114u, 134u, 68u, 83u,
- 153u, 55u, 167u, 190u,
- 198u, 150u, 53u, 255u,
- 193u, 234u, 82u, 63u,
- 235u, 250u, 30u, 64u,
- 176u, 124u, 244u, 104u,
- 1u, 185u, 85u, 248u,
- 63u, 115u, 171u, 109u,
- 136u, 157u, 139u, 126u,
- 151u, 117u, 60u, 101u,
- 111u, 0u, 160u, 170u,
- 227u, 220u, 122u, 137u,
- 132u, 106u, 67u, 109u,
- 0u, 116u, 105u, 186u,
- 126u, 91u, 140u, 78u,
- 144u, 192u, 125u, 106u,
- 132u, 135u, 103u, 212u,
- 199u, 206u, 255u, 207u,
- 57u, 22u, 80u, 164u,
- 100u, 77u, 188u, 56u,
- 187u, 135u, 108u, 119u,
- 140u, 158u, 160u, 78u,
- 255u, 144u, 222u, 103u,
- 79u, 169u, 86u, 171u,
- 49u, 179u, 85u, 91u,
- 255u, 142u, 110u, 169u,
- 13u, 83u, 98u, 100u,
- 88u, 155u, 242u, 208u,
- 74u, 68u, 184u, 116u,
- 57u, 230u, 55u, 120u,
- 69u, 1u, 38u, 194u,
- 128u, 1u, 167u, 216u,
- 174u, 23u, 208u, 20u,
- 163u, 202u, 81u, 237u,
- 85u, 194u, 157u, 109u,
- 197u, 48u, 123u, 153u,
- 72u, 120u, 130u, 207u,
- 96u, 158u, 93u, 129u,
- 126u, 1u, 52u, 34u,
- 187u, 82u, 255u, 134u,
- 234u, 131u, 104u, 75u,
- 113u, 16u, 85u, 139u,
- 84u, 211u, 124u, 65u,
- 110u, 128u, 255u, 96u,
- 223u, 91u, 159u, 102u,
- 166u, 189u, 37u, 129u,
- 70u, 123u, 158u, 127u,
- 81u, 151u, 127u, 93u,
- 68u, 180u, 105u, 84u,
- 98u, 159u, 152u, 109u,
- 113u, 1u, 104u, 223u,
- 232u, 114u, 144u, 39u,
- 187u, 0u, 99u, 51u,
- 135u, 127u, 132u, 141u,
- 163u, 225u, 96u, 126u,
- 0u, 186u, 120u, 205u,
- 116u, 165u, 217u, 121u,
- 65u, 186u, 131u, 233u,
- 188u, 216u, 165u, 41u,
- 202u, 137u, 255u, 110u,
- 100u, 123u, 93u, 84u,
- 153u, 63u, 129u, 113u,
- 138u, 116u, 135u, 24u,
- 134u, 131u, 122u, 110u,
- 60u, 179u, 59u, 91u,
- 155u, 124u, 196u, 70u,
- 50u, 197u, 255u, 118u,
- 158u, 166u, 16u, 0u,
- 125u, 49u, 177u, 162u,
- 52u, 149u, 106u, 211u,
- 99u, 87u, 173u, 222u,
- 168u, 1u, 136u, 44u,
- 126u, 92u, 54u, 104u,
- 88u, 166u, 124u, 110u,
- 147u, 235u, 118u, 96u,
- 155u, 180u, 142u, 117u,
- 178u, 166u, 101u, 133u,
- 122u, 132u, 201u, 187u,
- 255u, 17u, 140u, 126u,
- 152u, 214u, 149u, 21u,
- 157u, 155u, 164u, 153u,
- 101u, 116u, 1u, 176u,
- 92u, 243u, 169u, 184u,
- 122u, 207u, 103u, 93u,
- 202u, 132u, 63u, 184u,
- 255u, 63u, 169u, 223u,
- 67u, 94u, 118u, 143u,
- 191u, 116u, 151u, 117u,
- 1u, 70u, 170u, 152u,
- 182u, 106u, 93u, 174u,
- 154u, 254u, 179u, 85u,
- 144u, 126u, 191u, 175u,
- 100u, 120u, 1u, 227u,
- 121u, 147u, 233u, 55u,
- 116u, 95u, 46u, 61u,
- 151u, 255u, 151u, 164u,
- 115u, 255u, 75u, 147u,
- 116u, 135u, 122u, 144u,
- 133u, 148u, 124u, 179u,
- 104u, 120u, 26u, 184u,
- 255u, 143u, 92u, 128u,
- 71u, 113u, 88u, 166u,
- 203u, 133u, 176u, 127u,
- 195u, 214u, 126u, 112u,
- 95u, 54u, 103u, 1u,
- 64u, 98u, 163u, 12u,
- 152u, 163u, 164u, 77u,
- 88u, 205u, 155u, 182u,
- 189u, 124u, 68u, 148u,
- 104u, 114u, 93u, 1u,
- 173u, 53u, 145u, 75u,
- 145u, 91u, 109u, 75u,
- 137u, 68u, 145u, 110u,
- 193u, 255u, 111u, 110u,
- 116u, 183u, 95u, 142u,
- 121u, 221u, 146u, 164u,
- 67u, 178u, 111u, 175u,
- 57u, 255u, 190u, 161u,
- 100u, 38u, 248u, 215u,
- 113u, 37u, 141u, 173u,
- 84u, 118u, 135u, 163u,
- 255u, 143u, 134u, 130u,
- 119u, 30u, 90u, 67u,
- 102u, 78u, 199u, 114u,
- 1u, 208u, 163u, 137u,
- 142u, 218u, 232u, 174u,
- 129u, 28u, 160u, 139u,
- 108u, 163u, 83u, 181u,
- 0u, 71u, 148u, 69u,
- 169u, 200u, 101u, 127u,
- 100u, 146u, 92u, 164u,
- 1u, 56u, 116u, 212u,
- 24u, 16u, 116u, 134u,
- 67u, 94u, 113u, 0u,
- 79u, 61u, 205u, 34u,
- 175u, 164u, 81u, 0u,
- 128u, 152u, 161u, 163u,
- 168u, 235u, 103u, 163u,
- 100u, 114u, 248u, 221u,
- 102u, 255u, 191u, 57u,
- 105u, 153u, 214u, 29u,
- 84u, 172u, 173u, 127u,
- 170u, 167u, 85u, 52u,
- 100u, 130u, 89u, 235u,
- 129u, 43u, 153u, 95u,
- 237u, 175u, 187u, 149u,
- 189u, 109u, 48u, 0u,
- 121u, 158u, 106u, 118u,
- 141u, 205u, 157u, 33u,
- 104u, 189u, 1u, 129u,
- 140u, 200u, 25u, 176u,
- 1u, 86u, 58u, 219u,
- 127u, 202u, 69u, 132u,
- 173u, 61u, 66u, 56u,
- 81u, 213u, 199u, 86u,
- 81u, 160u, 166u, 159u,
- 104u, 105u, 1u, 101u,
- 88u, 184u, 140u, 49u,
- 70u, 200u, 153u, 177u,
- 33u, 119u, 174u, 143u,
- 185u, 136u, 118u, 51u,
- 29u, 1u, 126u, 170u,
- 159u, 186u, 82u, 169u,
- 190u, 43u, 126u, 209u,
- 143u, 127u, 162u, 129u,
- 209u, 255u, 119u, 16u,
- 125u, 121u, 155u, 17u,
- 129u, 183u, 72u, 241u,
- 44u, 129u, 6u, 118u,
- 128u, 219u, 86u, 107u,
- 99u, 1u, 80u, 142u,
- 117u, 104u, 116u, 82u,
- 170u, 34u, 118u, 156u,
- 118u, 79u, 109u, 180u,
- 150u, 197u, 1u, 169u,
- 72u, 115u, 18u, 117u,
- 177u, 123u, 255u, 156u,
- 100u, 246u, 56u, 132u,
- 133u, 99u, 101u, 79u,
- 151u, 67u, 186u, 143u,
- 58u, 20u, 140u, 187u,
- 27u, 41u, 213u, 163u,
- 159u, 255u, 140u, 89u,
- 163u, 184u, 146u, 182u,
- 127u, 109u, 133u, 40u,
- 100u, 82u, 160u, 147u,
- 255u, 130u, 146u, 103u,
- 0u, 178u, 113u, 249u,
- 88u, 129u, 139u, 103u,
- 177u, 163u, 53u, 124u,
- 51u, 164u, 138u, 54u,
- 140u, 142u, 119u, 51u,
- 255u, 187u, 81u, 107u,
- 105u, 68u, 146u, 149u,
- 136u, 159u, 111u, 217u,
- 199u, 208u, 167u, 38u,
- 22u, 150u, 119u, 118u,
- 136u, 122u, 163u, 133u,
- 1u, 120u, 65u, 152u,
- 75u, 61u, 175u, 100u,
- 142u, 147u, 239u, 121u,
- 255u, 196u, 127u, 238u,
- 24u, 65u, 110u, 93u,
- 115u, 168u, 88u, 181u,
- 202u, 84u, 130u, 255u,
- 255u, 189u, 57u, 49u,
- 159u, 123u, 104u, 25u,
- 209u, 17u, 93u, 230u,
- 50u, 252u, 1u, 120u,
- 41u, 126u, 77u, 186u,
- 11u, 222u, 179u, 255u,
- 229u, 101u, 125u, 79u,
- 238u, 172u, 214u, 96u,
- 1u, 162u, 156u, 208u,
- 193u, 152u, 149u, 116u,
- 170u, 29u, 221u, 161u,
- 214u, 182u, 168u, 0u,
- 170u, 165u, 3u, 149u,
- 235u, 172u, 120u, 254u,
- 191u, 53u, 180u, 220u,
- 119u, 175u, 255u, 255u,
- 102u, 111u, 119u, 224u,
- 132u, 90u, 189u, 140u,
- 144u, 113u, 214u, 121u,
- 137u, 158u, 1u, 99u,
- 164u, 142u, 168u, 123u,
- 89u, 122u, 41u, 140u,
- 140u, 53u, 255u, 122u,
- 40u, 74u, 122u, 60u,
- 214u, 232u, 177u, 110u,
- 140u, 145u, 126u, 193u,
- 219u, 146u, 255u, 78u,
- 115u, 83u, 119u, 59u,
- 224u, 64u, 226u, 194u,
- 83u, 98u, 96u, 23u,
- 33u, 114u, 83u, 181u,
- 1u, 106u, 70u, 51u,
- 31u, 128u, 142u, 111u,
- 81u, 98u, 142u, 130u,
- 118u, 181u, 230u, 199u,
- 255u, 120u, 68u, 35u,
- 135u, 96u, 39u, 110u,
- 81u, 53u, 109u, 90u,
- 153u, 73u, 1u, 66u,
- 187u, 126u, 128u, 147u,
- 62u, 194u, 71u, 201u,
- 90u, 130u, 173u, 158u,
- 207u, 108u, 255u, 173u,
- 239u, 181u, 107u, 111u,
- 4u, 40u, 64u, 147u,
- 216u, 183u, 123u, 99u,
- 160u, 132u, 130u, 105u,
- 157u, 146u, 31u, 90u,
- 107u, 119u, 210u, 115u,
- 154u, 0u, 134u, 139u,
- 108u, 174u, 1u, 107u,
- 211u, 167u, 138u, 113u,
- 53u, 150u, 59u, 216u,
- 63u, 222u, 153u, 160u,
- 136u, 79u, 134u, 169u,
- 157u, 212u, 56u, 68u,
- 1u, 62u, 123u, 42u,
- 185u, 139u, 150u, 183u,
- 134u, 131u, 105u, 67u,
- 255u, 11u, 104u, 132u,
- 159u, 195u, 179u, 181u,
- 195u, 106u, 158u, 73u,
- 1u, 82u, 180u, 125u,
- 204u, 81u, 96u, 170u,
- 94u, 193u, 50u, 43u,
- 115u, 70u, 182u, 177u,
- 188u, 114u, 155u, 238u,
- 106u, 137u, 107u, 88u,
- 121u, 53u, 1u, 80u,
- 159u, 110u, 165u, 184u,
- 22u, 122u, 255u, 151u,
- 109u, 165u, 94u, 24u,
- 77u, 101u, 119u, 113u,
- 55u, 120u, 91u, 240u,
- 191u, 195u, 173u, 118u,
- 222u, 255u, 92u, 151u,
- 105u, 78u, 26u, 122u,
- 106u, 71u, 120u, 217u,
- 186u, 219u, 36u, 88u,
- 14u, 141u, 224u, 63u,
- 77u, 253u, 100u, 214u,
- 255u, 131u, 218u, 143u,
- 122u, 119u, 219u, 92u,
- 98u, 162u, 22u, 109u,
- 99u, 137u, 104u, 0u,
- 60u, 189u, 101u, 137u,
- 133u, 58u, 82u, 67u,
- 73u, 43u, 144u, 125u,
- 198u, 138u, 151u, 145u,
- 53u, 63u, 97u, 1u,
- 224u, 3u, 60u, 82u,
- 255u, 41u, 132u, 140u,
- 77u, 211u, 56u, 85u,
- 159u, 190u, 125u, 136u,
- 3u, 236u, 255u, 28u,
- 68u, 169u, 34u, 250u,
- 99u, 194u, 182u, 26u,
- 73u, 49u, 80u, 55u,
- 171u, 130u, 171u, 160u,
- 42u, 172u, 71u, 189u,
- 120u, 161u, 178u, 33u,
- 0u, 89u, 103u, 107u,
- 113u, 190u, 1u, 190u,
- 62u, 86u, 25u, 111u,
- 62u, 73u, 168u, 59u,
- 229u, 53u, 162u, 115u,
- 97u, 143u, 125u, 138u,
- 90u, 146u, 55u, 147u,
- 136u, 141u, 120u, 72u,
- 185u, 1u, 82u, 114u,
- 183u, 185u, 255u, 138u,
- 164u, 95u, 209u, 241u,
- 116u, 225u, 148u, 147u,
- 139u, 238u, 128u, 23u,
- 174u, 255u, 76u, 158u,
- 154u, 136u, 1u, 129u,
- 184u, 154u, 87u, 85u,
- 35u, 89u, 142u, 151u,
- 94u, 130u, 167u, 150u,
- 142u, 110u, 150u, 156u,
- 28u, 255u, 150u, 107u,
- 140u, 111u, 153u, 201u,
- 179u, 215u, 210u, 202u,
- 158u, 48u, 207u, 179u,
- 213u, 1u, 104u, 222u,
- 95u, 43u, 95u, 151u,
- 107u, 127u, 177u, 138u,
- 67u, 190u, 141u, 104u,
- 14u, 193u, 255u, 149u,
- 148u, 77u, 130u, 120u,
- 91u, 121u, 155u, 27u,
- 242u, 31u, 62u, 93u,
- 177u, 226u, 213u, 221u,
- 1u, 98u, 125u, 85u,
- 173u, 81u, 255u, 168u,
- 75u, 160u, 131u, 125u,
- 98u, 76u, 149u, 27u,
- 129u, 128u, 151u, 118u,
- 142u, 200u, 160u, 172u,
- 208u, 87u, 147u, 156u,
- 131u, 57u, 0u, 212u,
- 85u, 217u, 129u, 96u,
- 148u, 189u, 148u, 86u,
- 19u, 201u, 80u, 208u,
- 74u, 151u, 153u, 44u,
- 213u, 94u, 0u, 235u,
- 82u, 198u, 1u, 218u,
- 26u, 116u, 126u, 109u,
- 26u, 162u, 93u, 179u,
- 148u, 94u, 148u, 119u,
- 100u, 3u, 97u, 153u,
- 99u, 46u, 162u, 24u,
- 255u, 236u, 72u, 109u,
- 88u, 105u, 105u, 57u,
- 176u, 198u, 251u, 233u,
- 17u, 117u, 241u, 81u,
- 255u, 145u, 196u, 146u,
- 153u, 82u, 123u, 65u,
- 138u, 94u, 213u, 219u,
- 179u, 41u, 1u, 161u,
- 174u, 145u, 139u, 47u,
- 162u, 131u, 57u, 168u,
- 101u, 207u, 128u, 87u,
- 148u, 149u, 121u, 152u,
- 98u, 1u, 135u, 128u,
- 114u, 149u, 153u, 152u,
- 84u, 138u, 198u, 148u,
- 56u, 30u, 1u, 115u,
- 134u, 163u, 222u, 84u,
- 97u, 100u, 204u, 133u,
- 121u, 80u, 146u, 196u,
- 231u, 57u, 222u, 95u,
- 197u, 45u, 1u, 95u,
- 108u, 145u, 242u, 156u,
- 84u, 1u, 138u, 186u,
- 26u, 92u, 199u, 136u,
- 100u, 185u, 120u, 111u,
- 201u, 56u, 165u, 125u,
- 98u, 97u, 167u, 168u,
- 107u, 178u, 88u, 61u,
- 255u, 63u, 234u, 176u,
- 56u, 84u, 70u, 254u,
- 208u, 110u, 131u, 189u,
- 124u, 128u, 20u, 185u,
- 166u, 1u, 127u, 165u,
- 190u, 128u, 119u, 52u,
- 172u, 156u, 139u, 95u,
- 193u, 176u, 85u, 157u,
- 94u, 148u, 78u, 117u,
- 130u, 1u, 176u, 130u,
- 170u, 98u, 248u, 82u,
- 138u, 138u, 53u, 0u,
- 88u, 81u, 128u, 132u,
- 86u, 181u, 210u, 129u,
- 147u, 160u, 154u, 177u,
- 57u, 187u, 152u, 170u,
- 196u, 255u, 228u, 116u,
- 163u, 65u, 37u, 148u,
- 1u, 171u, 35u, 113u,
- 149u, 137u, 107u, 67u,
- 197u, 197u, 174u, 187u,
- 154u, 66u, 143u, 82u,
- 92u, 93u, 0u, 240u,
- 97u, 172u, 112u, 154u,
- 126u, 99u, 120u, 109u,
- 94u, 112u, 168u, 128u,
- 161u, 255u, 108u, 5u,
- 192u, 110u, 70u, 2u,
- 2u, 159u, 171u, 71u,
- 18u, 208u, 116u, 119u,
- 255u, 72u, 174u, 177u,
- 104u, 149u, 222u, 197u,
- 185u, 122u, 76u, 124u,
- 150u, 98u, 93u, 132u,
- 161u, 151u, 107u, 144u,
- 155u, 96u, 202u, 163u,
- 230u, 111u, 94u, 105u,
- 157u, 135u, 67u, 0u,
- 154u, 157u, 18u, 87u,
- 169u, 32u, 104u, 88u,
- 74u, 186u, 94u, 112u,
- 113u, 50u, 255u, 112u,
- 143u, 170u, 14u, 55u,
- 255u, 246u, 128u, 136u,
- 79u, 221u, 226u, 194u,
- 200u, 135u, 169u, 156u,
- 143u, 109u, 45u, 125u,
- 197u, 113u, 146u, 157u,
- 255u, 172u, 128u, 156u,
- 141u, 126u, 131u, 107u,
- 116u, 125u, 43u, 137u,
- 220u, 150u, 160u, 149u,
- 172u, 130u, 110u, 64u,
- 181u, 78u, 97u, 0u,
- 46u, 148u, 66u, 172u,
- 68u, 255u, 103u, 227u,
- 138u, 161u, 98u, 134u,
- 125u, 123u, 204u, 185u,
- 234u, 162u, 203u, 207u,
- 103u, 109u, 78u, 120u,
- 161u, 189u, 108u, 87u,
- 138u, 201u, 127u, 0u,
- 125u, 90u, 255u, 168u,
- 155u, 63u, 133u, 123u,
- 153u, 130u, 94u, 138u,
- 132u, 99u, 122u, 155u,
- 186u, 1u, 27u, 179u,
- 127u, 123u, 107u, 125u,
- 97u, 168u, 52u, 30u,
- 129u, 30u, 137u, 30u,
- 61u, 255u, 167u, 128u,
- 205u, 28u, 209u, 215u,
- 233u, 123u, 100u, 118u,
- 128u, 191u, 114u, 96u,
- 1u, 107u, 76u, 171u,
- 58u, 230u, 99u, 155u,
- 192u, 159u, 48u, 8u,
- 145u, 233u, 239u, 198u,
- 148u, 104u, 55u, 255u,
- 8u, 136u, 101u, 91u,
- 128u, 142u, 95u, 72u,
- 66u, 102u, 131u, 54u,
- 125u, 80u, 144u, 101u,
- 114u, 184u, 145u, 35u,
- 143u, 96u, 81u, 164u,
- 32u, 255u, 107u, 176u,
- 118u, 175u, 160u, 1u,
- 44u, 132u, 199u, 34u,
- 62u, 123u, 191u, 196u,
- 88u, 223u, 137u, 236u,
- 83u, 173u, 117u, 148u,
- 1u, 185u, 11u, 104u,
- 64u, 129u, 223u, 133u,
- 119u, 89u, 189u, 158u,
- 151u, 159u, 79u, 90u,
- 64u, 129u, 154u, 114u,
- 255u, 147u, 234u, 166u,
- 115u, 125u, 113u, 157u,
- 233u, 126u, 92u, 198u,
- 169u, 230u, 1u, 62u,
- 172u, 41u, 180u, 193u,
- 200u, 145u, 39u, 48u,
- 255u, 102u, 118u, 79u,
- 119u, 127u, 17u, 93u,
- 221u, 164u, 187u, 154u,
- 176u, 60u, 56u, 52u,
- 161u, 164u, 40u, 64u,
- 180u, 120u, 0u, 95u,
- 164u, 56u, 126u, 158u,
- 95u, 230u, 209u, 111u,
- 54u, 252u, 176u, 27u,
- 78u, 84u, 58u, 49u,
- 165u, 194u, 255u, 126u,
- 137u, 165u, 134u, 86u,
- 238u, 107u, 146u, 148u,
- 202u, 135u, 165u, 1u,
- 89u, 123u, 109u, 146u,
- 112u, 150u, 161u, 180u,
- 177u, 144u, 76u, 111u,
- 86u, 154u, 111u, 255u,
- 176u, 152u, 133u, 74u,
- 49u, 131u, 115u, 130u,
- 80u, 155u, 18u, 217u,
- 1u, 201u, 120u, 159u,
- 165u, 42u, 105u, 22u,
- 132u, 50u, 150u, 149u,
- 170u, 126u, 144u, 27u,
- 57u, 169u, 95u, 51u,
- 56u, 59u, 187u, 142u,
- 154u, 255u, 128u, 211u,
- 143u, 110u, 79u, 25u,
- 204u, 110u, 255u, 113u,
- 93u, 153u, 103u, 152u,
- 138u, 95u, 179u, 127u,
- 99u, 85u, 113u, 170u,
- 143u, 131u, 59u, 165u,
- 44u, 155u, 123u, 79u,
- 228u, 111u, 1u, 154u,
- 160u, 169u, 255u, 99u,
- 98u, 99u, 85u, 128u,
- 105u, 28u, 109u, 136u,
- 105u, 93u, 25u, 85u,
- 31u, 187u, 81u, 53u,
- 1u, 114u, 90u, 254u,
- 117u, 34u, 205u, 198u,
- 198u, 71u, 195u, 112u,
- 82u, 100u, 11u, 182u,
- 81u, 159u, 87u, 77u,
- 118u, 193u, 255u, 113u,
- 128u, 53u, 94u, 69u,
- 196u, 152u, 86u, 221u,
- 65u, 47u, 164u, 1u,
- 66u, 86u, 210u, 126u,
- 108u, 122u, 167u, 166u,
- 1u, 48u, 182u, 44u,
- 72u, 199u, 227u, 175u,
- 170u, 72u, 225u, 119u,
- 205u, 12u, 114u, 219u,
- 154u, 129u, 130u, 120u,
- 158u, 33u, 203u, 49u,
- 217u, 1u, 215u, 204u,
- 71u, 104u, 64u, 82u,
- 141u, 185u, 48u, 54u,
- 93u, 61u, 1u, 107u,
- 85u, 35u, 253u, 60u,
- 104u, 89u, 175u, 159u,
- 213u, 209u, 43u, 67u,
- 42u, 255u, 131u, 249u,
- 181u, 139u, 217u, 125u,
- 206u, 91u, 144u, 108u,
- 116u, 69u, 166u, 204u,
- 147u, 170u, 204u, 8u,
- 1u, 159u, 41u, 96u,
- 130u, 200u, 186u, 74u,
- 255u, 134u, 183u, 49u,
- 100u, 143u, 78u, 147u,
- 187u, 158u, 201u, 200u,
- 147u, 125u, 74u, 76u,
- 87u, 113u, 220u, 51u,
- 74u, 181u, 182u, 75u,
- 134u, 91u, 147u, 107u,
- 255u, 55u, 103u, 100u,
- 169u, 142u, 164u, 81u,
- 149u, 162u, 143u, 181u,
- 148u, 138u, 255u, 200u,
- 163u, 81u, 108u, 26u,
- 139u, 23u, 23u, 159u,
- 0u, 109u, 80u, 196u,
- 153u, 191u, 164u, 32u,
- 188u, 188u, 159u, 53u,
- 45u, 78u, 137u, 13u,
- 156u, 202u, 254u, 130u,
- 123u, 92u, 65u, 53u,
- 80u, 92u, 255u, 127u,
- 238u, 73u, 230u, 126u,
- 161u, 151u, 140u, 56u,
- 7u, 255u, 55u, 129u,
- 177u, 149u, 168u, 20u,
- 153u, 104u, 156u, 128u,
- 152u, 77u, 118u, 1u,
- 119u, 51u, 87u, 25u,
- 69u, 170u, 143u, 168u,
- 61u, 121u, 187u, 176u,
- 166u, 153u, 255u, 71u,
- 13u, 170u, 164u, 200u,
- 197u, 50u, 156u, 77u,
- 104u, 102u, 66u, 1u,
- 96u, 133u, 85u, 91u,
- 68u, 51u, 163u, 124u,
- 94u, 129u, 116u, 203u,
- 117u, 132u, 209u, 64u,
- 171u, 203u, 157u, 255u,
- 154u, 75u, 132u, 88u,
- 35u, 142u, 76u, 128u,
- 59u, 161u, 151u, 153u,
- 83u, 89u, 45u, 235u,
- 31u, 102u, 50u, 113u,
- 9u, 218u, 139u, 1u,
- 141u, 151u, 94u, 64u,
- 129u, 164u, 79u, 148u,
- 207u, 135u, 188u, 16u,
- 66u, 99u, 0u, 133u,
- 131u, 168u, 9u, 104u,
- 1u, 44u, 196u, 117u,
- 146u, 137u, 241u, 142u,
- 186u, 125u, 112u, 94u,
- 201u, 96u, 62u, 141u,
- 206u, 155u, 183u, 163u,
- 160u, 131u, 180u, 255u,
- 138u, 113u, 90u, 138u,
- 169u, 20u, 172u, 61u,
- 100u, 126u, 90u, 87u,
- 223u, 55u, 255u, 217u,
- 159u, 164u, 99u, 191u,
- 109u, 130u, 97u, 98u,
- 42u, 193u, 172u, 150u,
- 128u, 255u, 154u, 150u,
- 94u, 151u, 85u, 82u,
- 130u, 196u, 110u, 57u,
- 97u, 144u, 120u, 255u,
- 160u, 114u, 190u, 160u,
- 78u, 168u, 109u, 87u,
- 110u, 82u, 111u, 0u,
- 160u, 112u, 174u, 213u,
- 169u, 137u, 43u, 60u,
- 149u, 92u, 133u, 179u,
- 121u, 49u, 255u, 167u,
- 38u, 33u, 214u, 45u,
- 149u, 165u, 111u, 198u,
- 149u, 114u, 63u, 73u,
- 155u, 74u, 255u, 40u,
- 110u, 132u, 11u, 157u,
- 112u, 165u, 124u, 19u,
- 16u, 120u, 66u, 222u,
- 209u, 155u, 121u, 1u,
- 135u, 152u, 101u, 152u,
- 55u, 51u, 22u, 135u,
- 207u, 210u, 55u, 117u,
- 77u, 72u, 63u, 141u,
- 93u, 168u, 178u, 60u,
- 107u, 124u, 87u, 131u,
- 132u, 237u, 148u, 255u,
- 149u, 178u, 255u, 132u,
- 85u, 124u, 169u, 118u,
- 151u, 42u, 181u, 178u,
- 217u, 187u, 102u, 75u,
- 6u, 185u, 81u, 58u,
- 153u, 179u, 136u, 131u,
- 108u, 0u, 123u, 162u,
- 75u, 154u, 170u, 193u,
- 83u, 139u, 218u, 143u,
- 1u, 185u, 141u, 69u,
- 85u, 177u, 84u, 159u,
- 146u, 61u, 34u, 107u,
- 30u, 100u, 138u, 106u,
- 167u, 109u, 88u, 188u,
- 91u, 255u, 165u, 163u,
- 63u, 45u, 115u, 102u,
- 107u, 255u, 206u, 134u,
- 13u, 149u, 140u, 104u,
- 44u, 20u, 140u, 201u,
- 55u, 108u, 189u, 148u,
- 218u, 255u, 22u, 209u,
- 53u, 64u, 86u, 87u,
- 136u, 62u, 220u, 71u,
- 119u, 223u, 118u, 11u,
- 193u, 55u, 109u, 125u,
- 197u, 142u, 100u, 157u,
- 155u, 109u, 1u, 15u,
- 106u, 74u, 136u, 135u,
- 65u, 73u, 228u, 255u,
- 85u, 217u, 154u, 77u,
- 175u, 134u, 220u, 207u,
- 160u, 27u, 60u, 7u,
- 132u, 165u, 35u, 196u,
- 34u, 255u, 241u, 124u,
- 233u, 91u, 39u, 172u,
- 68u, 159u, 137u, 131u,
- 181u, 186u, 255u, 132u,
- 186u, 189u, 143u, 95u,
- 240u, 101u, 138u, 144u,
- 102u, 93u, 172u, 145u,
- 112u, 88u, 203u, 59u,
- 255u, 101u, 133u, 121u,
- 15u, 129u, 90u, 171u,
- 91u, 137u, 198u, 211u,
- 170u, 29u, 203u, 166u,
- 217u, 95u, 255u, 40u,
- 201u, 139u, 7u, 181u,
- 178u, 176u, 163u, 97u,
- 134u, 144u, 68u, 141u,
- 135u, 123u, 114u, 152u,
- 81u, 255u, 124u, 76u,
- 170u, 176u, 102u, 31u,
- 93u, 123u, 119u, 146u,
- 120u, 100u, 130u, 159u,
- 128u, 122u, 184u, 255u,
- 159u, 112u, 99u, 99u,
- 38u, 255u, 50u, 147u,
- 124u, 206u, 156u, 60u,
- 157u, 207u, 129u, 208u,
- 143u, 150u, 64u, 114u,
- 146u, 92u, 116u, 118u,
- 226u, 175u, 142u, 192u,
- 28u, 255u, 169u, 242u,
- 251u, 166u, 71u, 131u,
- 155u, 40u, 1u, 239u,
- 84u, 186u, 67u, 199u,
- 95u, 121u, 143u, 188u,
- 243u, 90u, 126u, 167u,
- 128u, 145u, 37u, 166u,
- 82u, 169u, 255u, 78u,
- 210u, 145u, 97u, 15u,
- 97u, 200u, 156u, 208u,
- 159u, 67u, 163u, 154u,
- 56u, 210u, 203u, 217u,
- 152u, 75u, 80u, 114u,
- 255u, 171u, 165u, 129u,
- 169u, 160u, 193u, 139u,
- 1u, 220u, 154u, 53u,
- 122u, 113u, 134u, 131u,
- 135u, 143u, 112u, 128u,
- 151u, 98u, 153u, 105u,
- 190u, 144u, 122u, 179u,
- 124u, 18u, 63u, 111u,
- 1u, 245u, 108u, 190u,
- 80u, 46u, 91u, 142u,
- 34u, 231u, 110u, 91u,
- 172u, 255u, 72u, 124u,
- 120u, 178u, 120u, 247u,
- 150u, 107u, 173u, 242u,
- 94u, 74u, 66u, 111u,
- 156u, 1u, 150u, 26u,
- 11u, 49u, 89u, 120u,
- 93u, 255u, 146u, 123u,
- 106u, 135u, 116u, 149u,
- 99u, 109u, 201u, 175u,
- 164u, 142u, 111u, 131u,
- 112u, 95u, 88u, 155u,
- 125u, 17u, 233u, 167u,
- 159u, 133u, 192u, 176u,
- 151u, 125u, 84u, 1u,
- 89u, 134u, 94u, 147u,
- 216u, 120u, 132u, 255u,
- 120u, 103u, 165u, 164u,
- 246u, 149u, 144u, 88u,
- 100u, 87u, 66u, 77u,
- 81u, 88u, 96u, 164u,
- 123u, 136u, 133u, 0u,
- 77u, 107u, 149u, 126u,
- 73u, 64u, 141u, 144u,
- 131u, 184u, 29u, 227u,
- 255u, 67u, 150u, 79u,
- 219u, 109u, 142u, 71u,
- 55u, 89u, 122u, 160u,
- 183u, 173u, 128u, 28u,
- 134u, 140u, 81u, 223u,
- 237u, 196u, 255u, 154u,
- 106u, 44u, 202u, 171u,
- 149u, 138u, 115u, 74u,
- 139u, 255u, 87u, 137u,
- 130u, 185u, 159u, 113u,
- 255u, 120u, 84u, 20u,
- 189u, 155u, 187u, 167u,
- 167u, 137u, 16u, 85u,
- 112u, 232u, 106u, 128u,
- 131u, 137u, 255u, 144u,
- 121u, 49u, 153u, 26u,
- 15u, 117u, 84u, 146u,
- 178u, 89u, 140u, 149u,
- 88u, 117u, 171u, 90u,
- 184u, 80u, 1u, 80u,
- 84u, 113u, 102u, 118u,
- 121u, 35u, 204u, 184u,
- 12u, 97u, 85u, 111u,
- 131u, 113u, 255u, 169u,
- 150u, 157u, 92u, 147u,
- 54u, 44u, 147u, 71u,
- 89u, 165u, 88u, 83u,
- 170u, 166u, 191u, 255u,
- 130u, 131u, 115u, 229u,
- 146u, 111u, 48u, 178u,
- 61u, 155u, 104u, 175u,
- 69u, 159u, 196u, 255u,
- 107u, 32u, 102u, 27u,
- 107u, 156u, 160u, 188u,
- 224u, 57u, 134u, 167u,
- 1u, 219u, 116u, 54u,
- 70u, 217u, 100u, 154u,
- 181u, 159u, 171u, 120u,
- 198u, 145u, 221u, 179u,
- 1u, 147u, 139u, 78u,
- 143u, 138u, 128u, 155u,
- 225u, 145u, 175u, 91u,
- 174u, 93u, 102u, 123u,
- 139u, 248u, 255u, 90u,
- 206u, 162u, 96u, 107u,
- 91u, 226u, 120u, 119u,
- 157u, 223u, 170u, 114u,
- 95u, 87u, 141u, 186u,
- 31u, 255u, 52u, 144u,
- 106u, 201u, 115u, 140u,
- 160u, 79u, 233u, 129u,
- 189u, 119u, 121u, 194u,
- 239u, 159u, 127u, 255u,
- 213u, 218u, 140u, 136u,
- 83u, 1u, 93u, 163u,
- 73u, 53u, 119u, 79u,
- 28u, 120u, 95u, 179u,
- 52u, 104u, 93u, 184u,
- 108u, 29u, 84u, 108u,
- 29u, 128u, 100u, 54u,
- 74u, 202u, 167u, 188u,
- 102u, 140u, 218u, 255u,
- 93u, 222u, 235u, 114u,
- 94u, 121u, 66u, 119u,
- 73u, 117u, 207u, 21u,
- 43u, 255u, 145u, 126u,
- 99u, 150u, 232u, 162u,
- 218u, 33u, 255u, 46u,
- 45u, 142u, 143u, 112u,
- 178u, 53u, 241u, 113u,
- 51u, 195u, 255u, 34u,
- 241u, 122u, 87u, 75u,
- 142u, 155u, 61u, 82u,
- 174u, 96u, 114u, 47u,
- 196u, 168u, 145u, 138u,
- 1u, 89u, 174u, 222u,
- 153u, 157u, 187u, 101u,
- 79u, 103u, 129u, 128u,
- 0u, 188u, 139u, 114u,
- 153u, 103u, 16u, 116u,
- 128u, 87u, 61u, 56u,
- 163u, 30u, 74u, 137u,
- 109u, 103u, 81u, 242u,
- 1u, 147u, 195u, 195u,
- 149u, 99u, 66u, 93u,
- 22u, 113u, 192u, 138u,
- 250u, 143u, 209u, 105u,
- 130u, 178u, 141u, 0u,
- 74u, 169u, 131u, 148u,
- 211u, 106u, 53u, 79u,
- 109u, 80u, 140u, 79u,
- 139u, 243u, 163u, 254u,
- 101u, 141u, 1u, 214u,
- 191u, 15u, 45u, 200u,
- 143u, 160u, 54u, 196u,
- 86u, 111u, 211u, 134u,
- 148u, 184u, 89u, 238u,
- 0u, 191u, 223u, 153u,
- 137u, 59u, 83u, 136u,
- 79u, 167u, 255u, 66u,
- 71u, 204u, 36u, 120u,
- 179u, 216u, 20u, 178u,
- 154u, 86u, 156u, 185u,
- 1u, 182u, 77u, 84u,
- 164u, 94u, 97u, 110u,
- 170u, 92u, 53u, 119u,
- 221u, 146u, 101u, 78u,
- 65u, 0u, 130u, 45u,
- 183u, 140u, 179u, 131u,
- 177u, 7u, 40u, 75u,
- 109u, 147u, 170u, 222u,
- 121u, 141u, 0u, 197u,
- 112u, 147u, 80u, 123u,
- 22u, 112u, 68u, 122u,
- 121u, 94u, 114u, 255u,
- 79u, 232u, 230u, 147u,
- 175u, 45u, 12u, 90u,
- 94u, 63u, 119u, 185u,
- 106u, 223u, 129u, 74u,
- 239u, 59u, 150u, 44u,
- 1u, 153u, 137u, 138u,
- 140u, 138u, 143u, 137u,
- 177u, 44u, 72u, 111u,
- 130u, 0u, 168u, 69u,
- 123u, 83u, 137u, 8u,
- 80u, 82u, 97u, 194u,
- 107u, 191u, 171u, 175u,
- 215u, 57u, 137u, 120u,
- 37u, 12u, 100u, 162u,
- 255u, 208u, 181u, 35u,
- 127u, 77u, 142u, 97u,
- 255u, 217u, 12u, 63u,
- 115u, 110u, 160u, 60u,
- 179u, 111u, 252u, 145u,
- 57u, 190u, 54u, 161u,
- 132u, 146u, 175u, 80u,
- 25u, 158u, 1u, 93u,
- 128u, 116u, 44u, 202u,
- 255u, 161u, 163u, 217u,
- 114u, 90u, 238u, 26u,
- 95u, 145u, 210u, 216u,
- 187u, 192u, 165u, 151u,
- 127u, 163u, 89u, 189u,
- 32u, 87u, 160u, 81u,
- 188u, 255u, 118u, 89u,
- 96u, 141u, 180u, 139u,
- 69u, 140u, 103u, 146u,
- 97u, 120u, 205u, 153u,
- 131u, 167u, 138u, 0u,
- 188u, 113u, 95u, 142u,
- 149u, 155u, 108u, 60u,
- 84u, 121u, 191u, 32u,
- 140u, 127u, 255u, 169u,
- 186u, 87u, 134u, 26u,
- 201u, 116u, 255u, 152u,
- 135u, 57u, 160u, 106u,
- 64u, 129u, 56u, 65u,
- 122u, 138u, 179u, 130u,
- 141u, 90u, 97u, 184u,
- 110u, 20u, 185u, 1u,
- 164u, 99u, 101u, 215u,
- 97u, 177u, 178u, 214u,
- 40u, 17u, 68u, 203u,
- 133u, 42u, 1u, 108u,
- 70u, 245u, 12u, 119u,
- 191u, 128u, 216u, 203u,
- 188u, 83u, 1u, 220u,
- 147u, 106u, 184u, 160u,
- 213u, 132u, 230u, 139u,
- 152u, 126u, 107u, 60u,
- 105u, 80u, 150u, 118u,
- 108u, 53u, 179u, 128u,
- 195u, 139u, 124u, 186u,
- 24u, 1u, 133u, 177u,
- 185u, 96u, 255u, 6u,
- 173u, 89u, 23u, 128u,
- 169u, 163u, 167u, 151u,
- 105u, 72u, 183u, 70u,
- 41u, 133u, 23u, 82u,
- 70u, 80u, 197u, 252u,
- 123u, 100u, 249u, 255u,
- 176u, 61u, 149u, 214u,
- 127u, 154u, 130u, 1u,
- 156u, 103u, 107u, 132u,
- 112u, 174u, 188u, 144u,
- 118u, 134u, 134u, 143u,
- 54u, 1u, 140u, 137u,
- 154u, 164u, 68u, 210u,
- 64u, 183u, 125u, 158u,
- 195u, 210u, 93u, 156u,
- 143u, 217u, 232u, 91u,
- 28u, 119u, 156u, 1u,
- 114u, 125u, 211u, 99u,
- 192u, 161u, 165u, 35u,
- 174u, 238u, 155u, 235u,
- 98u, 192u, 108u, 88u,
- 108u, 0u, 121u, 99u,
- 244u, 197u, 83u, 150u,
- 104u, 88u, 44u, 105u,
- 231u, 153u, 255u, 79u,
- 142u, 172u, 100u, 162u,
- 109u, 62u, 152u, 167u,
- 173u, 228u, 7u, 100u,
- 61u, 171u, 150u, 140u,
- 56u, 243u, 123u, 187u,
- 255u, 113u, 156u, 130u,
- 103u, 12u, 179u, 244u,
- 0u, 109u, 168u, 120u,
- 87u, 132u, 73u, 42u,
- 201u, 59u, 167u, 232u,
- 105u, 111u, 85u, 255u,
- 82u, 94u, 71u, 69u,
- 134u, 147u, 138u, 121u,
- 110u, 40u, 80u, 112u,
- 161u, 101u, 135u, 28u,
- 173u, 162u, 0u, 201u,
- 210u, 114u, 170u, 109u,
- 9u, 192u, 80u, 141u,
- 181u, 87u, 203u, 179u,
- 153u, 135u, 29u, 1u,
- 158u, 149u, 53u, 53u,
- 74u, 193u, 64u, 78u,
- 167u, 164u, 174u, 107u,
- 85u, 189u, 174u, 164u,
- 182u, 255u, 125u, 87u,
- 115u, 41u, 75u, 141u,
- 93u, 139u, 86u, 115u,
- 118u, 123u, 0u, 119u,
- 98u, 130u, 223u, 80u,
- 100u, 130u, 102u, 161u,
- 160u, 197u, 12u, 98u,
- 141u, 101u, 171u, 203u,
- 120u, 255u, 209u, 112u,
- 187u, 101u, 181u, 62u,
- 122u, 85u, 38u, 165u,
- 223u, 9u, 57u, 126u,
- 212u, 104u, 87u, 183u,
- 1u, 199u, 175u, 100u,
- 204u, 133u, 198u, 174u,
- 255u, 206u, 62u, 51u,
- 121u, 123u, 62u, 29u,
- 177u, 182u, 175u, 109u,
- 7u, 35u, 248u, 1u,
- 230u, 123u, 53u, 186u,
- 81u, 164u, 115u, 205u,
- 27u, 161u, 122u, 132u,
- 32u, 200u, 170u, 71u,
- 126u, 139u, 141u, 108u,
- 1u, 165u, 143u, 160u,
- 137u, 125u, 126u, 208u,
- 169u, 165u, 65u, 160u,
- 223u, 144u, 28u, 166u,
- 99u, 8u, 0u, 151u,
- 156u, 128u, 68u, 54u,
- 171u, 2u, 89u, 97u,
- 68u, 134u, 255u, 110u,
- 139u, 161u, 52u, 179u,
- 165u, 146u, 76u, 127u,
- 138u, 84u, 113u, 87u,
- 1u, 52u, 130u, 102u,
- 130u, 64u, 184u, 108u,
- 205u, 63u, 10u, 73u,
- 81u, 130u, 142u, 145u,
- 189u, 137u, 169u, 142u,
- 157u, 255u, 105u, 138u,
- 157u, 83u, 144u, 130u,
- 155u, 85u, 159u, 207u,
- 94u, 109u, 124u, 94u,
- 208u, 120u, 211u, 215u,
- 1u, 119u, 127u, 98u,
- 11u, 99u, 160u, 130u,
- 150u, 195u, 192u, 73u,
- 2u, 184u, 0u, 91u,
- 207u, 110u, 120u, 196u,
- 68u, 221u, 145u, 73u,
- 155u, 63u, 127u, 14u,
- 255u, 109u, 189u, 150u,
- 126u, 104u, 35u, 51u,
- 103u, 127u, 111u, 80u,
- 97u, 190u, 209u, 116u,
- 74u, 230u, 142u, 84u,
- 83u, 112u, 0u, 88u,
- 101u, 168u, 179u, 1u,
- 61u, 200u, 126u, 220u,
- 40u, 110u, 54u, 68u,
- 131u, 124u, 105u, 159u,
- 124u, 114u, 76u, 150u,
- 90u, 0u, 209u, 102u,
- 54u, 232u, 164u, 80u,
- 82u, 108u, 149u, 144u,
- 38u, 118u, 136u, 63u,
- 197u, 74u, 102u, 222u,
- 0u, 126u, 94u, 85u,
- 8u, 126u, 197u, 178u,
- 114u, 176u, 181u, 0u,
- 170u, 205u, 158u, 132u,
- 224u, 70u, 110u, 52u,
- 106u, 186u, 58u, 149u,
- 12u, 58u, 73u, 199u,
- 28u, 147u, 47u, 1u,
- 58u, 138u, 134u, 96u,
- 240u, 67u, 197u, 186u,
- 167u, 120u, 61u, 32u,
- 38u, 205u, 92u, 62u,
- 142u, 229u, 155u, 9u,
- 237u, 69u, 255u, 251u,
- 223u, 107u, 108u, 118u,
- 144u, 151u, 154u, 99u,
- 111u, 195u, 26u, 88u,
- 92u, 206u, 97u, 0u,
- 109u, 197u, 164u, 207u,
- 77u, 69u, 255u, 157u,
- 85u, 148u, 80u, 121u,
- 175u, 110u, 117u, 179u,
- 45u, 85u, 193u, 1u,
- 159u, 212u, 224u, 178u,
- 33u, 147u, 242u, 120u,
- 150u, 121u, 139u, 188u,
- 88u, 151u, 184u, 200u,
- 130u, 247u, 74u, 186u,
- 6u, 130u, 184u, 59u,
- 23u, 94u, 139u, 255u,
- 62u, 38u, 71u, 72u,
- 95u, 75u, 196u, 68u,
- 40u, 88u, 145u, 169u,
- 233u, 155u, 249u, 255u,
- 154u, 77u, 157u, 55u,
- 22u, 254u, 111u, 128u,
- 55u, 98u, 255u, 255u,
- 159u, 166u, 67u, 84u,
- 176u, 116u, 141u, 113u,
- 172u, 135u, 82u, 167u,
- 126u, 196u, 162u, 126u,
- 57u, 1u, 125u, 186u,
- 184u, 177u, 0u, 92u,
- 52u, 183u, 135u, 250u,
- 160u, 96u, 206u, 145u,
- 106u, 24u, 226u, 200u,
- 106u, 185u, 27u, 200u,
- 65u, 99u, 1u, 212u,
- 150u, 208u, 170u, 135u,
- 144u, 154u, 142u, 80u,
- 87u, 86u, 141u, 62u,
- 139u, 129u, 128u, 255u,
- 167u, 57u, 90u, 170u,
- 116u, 75u, 20u, 80u,
- 25u, 14u, 136u, 127u,
- 191u, 40u, 61u, 41u,
- 108u, 172u, 1u, 48u,
- 29u, 121u, 126u, 114u,
- 76u, 97u, 168u, 62u,
- 179u, 214u, 137u, 74u,
- 35u, 171u, 134u, 71u,
- 51u, 107u, 1u, 82u,
- 255u, 243u, 90u, 171u,
- 128u, 209u, 115u, 191u,
- 136u, 116u, 75u, 84u,
- 217u, 180u, 176u, 131u,
- 99u, 122u, 99u, 137u,
- 24u, 88u, 230u, 176u,
- 255u, 173u, 124u, 35u,
- 38u, 166u, 34u, 241u,
- 149u, 155u, 95u, 104u,
- 51u, 107u, 79u, 120u,
- 151u, 135u, 229u, 172u,
- 41u, 1u, 81u, 120u,
- 98u, 187u, 107u, 136u,
- 106u, 144u, 182u, 140u,
- 111u, 129u, 119u, 136u,
- 96u, 1u, 85u, 90u,
- 255u, 33u, 218u, 133u,
- 147u, 165u, 81u, 186u,
- 129u, 180u, 176u, 83u,
- 68u, 86u, 117u, 20u,
- 248u, 129u, 103u, 250u,
- 47u, 44u, 165u, 93u,
- 147u, 170u, 60u, 155u,
- 195u, 0u, 84u, 123u,
- 179u, 100u, 103u, 168u,
- 138u, 1u, 238u, 77u,
- 196u, 135u, 139u, 190u,
- 99u, 158u, 153u, 53u,
- 255u, 67u, 96u, 163u,
- 125u, 98u, 192u, 100u,
- 89u, 139u, 105u, 143u,
- 100u, 166u, 60u, 182u,
- 113u, 182u, 117u, 80u,
- 99u, 218u, 112u, 212u,
- 179u, 185u, 145u, 129u,
- 234u, 127u, 1u, 117u,
- 146u, 211u, 255u, 76u,
- 87u, 91u, 145u, 231u,
- 214u, 121u, 160u, 40u,
- 138u, 134u, 139u, 62u,
- 122u, 150u, 115u, 62u,
- 255u, 45u, 255u, 73u,
- 84u, 97u, 64u, 89u,
- 59u, 190u, 167u, 172u,
- 54u, 40u, 75u, 232u,
- 210u, 208u, 156u, 169u,
- 29u, 93u, 44u, 55u,
- 246u, 248u, 86u, 255u,
- 81u, 103u, 255u, 39u,
- 170u, 54u, 14u, 92u,
- 69u, 16u, 68u, 40u,
- 248u, 201u, 138u, 151u,
- 171u, 142u, 115u, 110u,
- 140u, 84u, 163u, 0u,
- 156u, 120u, 85u, 109u,
- 161u, 127u, 114u, 92u,
- 245u, 5u, 129u, 151u,
- 74u, 202u, 227u, 151u,
- 119u, 138u, 1u, 145u,
- 67u, 128u, 171u, 195u,
- 60u, 157u, 181u, 255u,
- 68u, 185u, 86u, 32u,
- 82u, 34u, 142u, 177u,
- 96u, 138u, 62u, 186u,
- 125u, 116u, 143u, 112u,
- 126u, 197u, 147u, 255u,
- 158u, 81u, 61u, 132u,
- 120u, 80u, 57u, 174u,
- 101u, 139u, 128u, 196u,
- 77u, 237u, 94u, 116u,
- 1u, 96u, 66u, 23u,
- 116u, 137u, 79u, 184u,
- 120u, 89u, 116u, 213u,
- 135u, 129u, 218u, 150u,
- 161u, 82u, 119u, 169u,
- 23u, 255u, 105u, 174u,
- 172u, 79u, 146u, 152u,
- 199u, 176u, 194u, 94u,
- 153u, 103u, 255u, 178u,
- 56u, 242u, 148u, 153u,
- 181u, 185u, 255u, 51u,
- 247u, 87u, 151u, 229u,
- 194u, 67u, 109u, 127u,
- 190u, 179u, 33u, 50u,
- 74u, 142u, 70u, 108u,
- 60u, 88u, 255u, 208u,
- 80u, 42u, 185u, 165u,
- 207u, 83u, 113u, 49u,
- 231u, 135u, 100u, 159u,
- 62u, 48u, 95u, 93u,
- 232u, 18u, 195u, 105u,
- 0u, 54u, 251u, 109u,
- 120u, 160u, 176u, 201u,
- 225u, 143u, 67u, 160u,
- 126u, 152u, 89u, 255u,
- 127u, 54u, 151u, 205u,
- 134u, 111u, 178u, 62u,
- 114u, 197u, 131u, 155u,
- 255u, 9u, 228u, 212u,
- 136u, 180u, 97u, 178u,
- 30u, 28u, 25u, 159u,
- 118u, 91u, 169u, 10u,
- 81u, 183u, 91u, 45u,
- 98u, 108u, 83u, 255u,
- 255u, 157u, 93u, 170u,
- 98u, 97u, 65u, 113u,
- 153u, 89u, 194u, 82u,
- 115u, 146u, 107u, 33u,
- 74u, 179u, 125u, 173u,
- 135u, 136u, 255u, 127u,
- 136u, 166u, 80u, 179u,
- 146u, 127u, 183u, 122u,
- 191u, 221u, 10u, 1u,
- 173u, 134u, 1u, 111u,
- 131u, 27u, 128u, 85u,
- 98u, 70u, 223u, 42u,
- 93u, 116u, 183u, 157u,
- 63u, 255u, 61u, 68u,
- 70u, 165u, 114u, 85u,
- 102u, 49u, 41u, 224u,
- 153u, 77u, 231u, 142u,
- 208u, 70u, 94u, 43u,
- 160u, 111u, 136u, 1u,
- 177u, 112u, 103u, 161u,
- 42u, 110u, 53u, 177u,
- 151u, 143u, 142u, 115u,
- 176u, 253u, 42u, 1u,
- 65u, 117u, 156u, 122u,
- 140u, 103u, 178u, 133u,
- 197u, 39u, 175u, 96u,
- 39u, 126u, 73u, 189u,
- 255u, 157u, 134u, 189u,
- 213u, 119u, 208u, 131u,
- 147u, 125u, 150u, 1u,
- 49u, 145u, 87u, 96u,
- 146u, 209u, 139u, 131u,
- 123u, 223u, 233u, 87u,
- 86u, 131u, 123u, 1u,
- 81u, 55u, 113u, 81u,
- 110u, 112u, 220u, 237u,
- 98u, 40u, 88u, 179u,
- 22u, 73u, 186u, 124u,
- 48u, 255u, 86u, 123u,
- 83u, 154u, 121u, 154u,
- 169u, 176u, 148u, 211u,
- 0u, 173u, 60u, 102u,
- 78u, 149u, 136u, 131u,
- 51u, 148u, 88u, 161u,
- 117u, 181u, 115u, 126u,
- 172u, 146u, 108u, 23u,
- 1u, 50u, 114u, 139u,
- 186u, 222u, 130u, 166u,
- 127u, 137u, 107u, 164u,
- 132u, 162u, 103u, 81u,
- 126u, 203u, 194u, 212u,
- 124u, 96u, 1u, 173u,
- 91u, 222u, 189u, 71u,
- 59u, 242u, 108u, 193u,
- 100u, 76u, 255u, 148u,
- 108u, 178u, 101u, 101u,
- 108u, 119u, 123u, 21u,
- 108u, 127u, 158u, 135u,
- 76u, 123u, 93u, 125u,
- 122u, 98u, 155u, 255u,
- 180u, 181u, 13u, 2u,
- 130u, 73u, 128u, 83u,
- 141u, 228u, 137u, 178u,
- 75u, 179u, 1u, 167u,
- 174u, 173u, 121u, 1u,
- 128u, 156u, 221u, 121u,
- 41u, 44u, 116u, 141u,
- 94u, 118u, 112u, 119u,
- 157u, 124u, 46u, 128u,
- 68u, 105u, 78u, 137u,
- 132u, 181u, 255u, 147u,
- 37u, 55u, 72u, 107u,
- 161u, 128u, 155u, 98u,
- 222u, 68u, 205u, 165u,
- 116u, 73u, 142u, 255u,
- 64u, 132u, 136u, 78u,
- 172u, 137u, 147u, 173u,
- 112u, 1u, 64u, 127u,
- 121u, 154u, 167u, 161u,
- 175u, 97u, 104u, 105u,
- 96u, 55u, 51u, 210u,
- 15u, 70u, 69u, 102u,
- 107u, 255u, 149u, 117u,
- 184u, 120u, 196u, 126u,
- 134u, 89u, 135u, 227u,
- 127u, 255u, 187u, 97u,
- 173u, 118u, 72u, 94u,
- 136u, 243u, 139u, 142u,
- 138u, 188u, 56u, 255u,
- 150u, 27u, 42u, 25u,
- 137u, 97u, 63u, 122u,
- 131u, 174u, 47u, 43u,
- 255u, 146u, 110u, 83u,
- 100u, 151u, 157u, 173u,
- 90u, 192u, 176u, 189u,
- 168u, 217u, 70u, 111u,
- 137u, 148u, 142u, 148u,
- 134u, 81u, 61u, 91u,
- 52u, 101u, 86u, 121u,
- 7u, 120u, 1u, 197u,
- 140u, 38u, 137u, 199u,
- 255u, 42u, 51u, 70u,
- 172u, 138u, 198u, 147u,
- 51u, 165u, 131u, 143u,
- 76u, 239u, 200u, 74u,
- 206u, 156u, 1u, 174u,
- 118u, 161u, 179u, 117u,
- 142u, 178u, 34u, 85u,
- 116u, 209u, 80u, 195u,
- 81u, 112u, 48u, 2u,
- 108u, 1u, 150u, 55u,
- 70u, 113u, 145u, 111u,
- 66u, 23u, 67u, 98u,
- 251u, 76u, 47u, 60u,
- 207u, 255u, 151u, 45u,
- 209u, 5u, 26u, 119u,
- 235u, 193u, 133u, 119u,
- 1u, 147u, 142u, 140u,
- 186u, 152u, 105u, 71u,
- 111u, 195u, 119u, 76u,
- 21u, 70u, 136u, 194u,
- 255u, 76u, 188u, 62u,
- 203u, 77u, 20u, 167u,
- 54u, 86u, 61u, 105u,
- 162u, 73u, 36u, 53u,
- 158u, 110u, 85u, 134u,
- 127u, 90u, 92u, 1u,
- 136u, 183u, 118u, 150u,
- 40u, 94u, 144u, 78u,
- 175u, 61u, 184u, 143u,
- 205u, 203u, 1u, 222u,
- 30u, 213u, 131u, 159u,
- 133u, 31u, 150u, 124u,
- 104u, 188u, 64u, 100u,
- 156u, 255u, 10u, 64u,
- 202u, 91u, 177u, 254u,
- 174u, 151u, 150u, 175u,
- 198u, 120u, 255u, 238u,
- 219u, 161u, 147u, 150u,
- 204u, 143u, 155u, 39u,
- 169u, 161u, 80u, 169u,
- 103u, 168u, 247u, 40u,
- 155u, 179u, 251u, 223u,
- 91u, 255u, 22u, 58u,
- 97u, 103u, 129u, 196u,
- 81u, 112u, 155u, 177u,
- 145u, 58u, 84u, 172u,
- 0u, 90u, 139u, 103u,
- 125u, 106u, 104u, 104u,
- 110u, 127u, 255u, 128u,
- 143u, 109u, 77u, 139u,
- 106u, 181u, 101u, 153u,
- 196u, 169u, 173u, 165u,
- 109u, 139u, 180u, 104u,
- 90u, 255u, 180u, 154u,
- 65u, 49u, 165u, 254u,
- 132u, 134u, 142u, 198u,
- 142u, 105u, 125u, 99u,
- 1u, 121u, 134u, 124u,
- 115u, 81u, 204u, 49u,
- 72u, 132u, 162u, 163u,
- 165u, 154u, 138u, 110u,
- 217u, 209u, 194u, 115u,
- 99u, 165u, 1u, 58u,
- 41u, 127u, 84u, 76u,
- 20u, 172u, 223u, 104u,
- 95u, 255u, 79u, 206u,
- 142u, 115u, 92u, 226u,
- 160u, 241u, 144u, 141u,
- 116u, 175u, 68u, 118u,
- 30u, 238u, 149u, 147u,
- 255u, 150u, 81u, 133u,
- 232u, 207u, 153u, 196u,
- 36u, 157u, 255u, 147u,
- 56u, 79u, 76u, 194u,
- 204u, 156u, 68u, 85u,
- 73u, 141u, 120u, 97u,
- 96u, 214u, 159u, 215u,
- 255u, 244u, 137u, 76u,
- 168u, 63u, 172u, 159u,
- 192u, 169u, 193u, 72u,
- 139u, 155u, 93u, 34u,
- 118u, 35u, 82u, 186u,
- 69u, 255u, 135u, 190u,
- 148u, 93u, 135u, 255u,
- 84u, 116u, 82u, 141u,
- 176u, 79u, 105u, 102u,
- 140u, 84u, 123u, 183u,
- 110u, 76u, 176u, 70u,
- 147u, 151u, 37u, 117u,
- 114u, 67u, 152u, 130u,
- 204u, 146u, 1u, 97u,
- 228u, 142u, 82u, 185u,
- 131u, 11u, 183u, 6u,
- 125u, 15u, 170u, 152u,
- 210u, 186u, 255u, 88u,
- 148u, 255u, 124u, 225u,
- 167u, 218u, 100u, 141u,
- 100u, 98u, 182u, 100u,
- 133u, 106u, 173u, 195u,
- 157u, 148u, 252u, 47u,
- 255u, 157u, 155u, 130u,
- 72u, 107u, 103u, 166u,
- 117u, 114u, 159u, 220u,
- 223u, 108u, 129u, 129u,
- 101u, 88u, 191u, 38u,
- 129u, 142u, 0u, 124u,
- 103u, 219u, 147u, 143u,
- 123u, 124u, 30u, 101u,
- 119u, 52u, 179u, 235u,
- 224u, 149u, 205u, 167u,
- 1u, 155u, 196u, 229u,
- 159u, 129u, 44u, 148u,
- 0u, 213u, 134u, 170u,
- 122u, 70u, 205u, 91u,
- 77u, 200u, 101u, 172u,
- 255u, 140u, 226u, 83u,
- 115u, 153u, 26u, 91u,
- 78u, 90u, 134u, 72u,
- 172u, 140u, 136u, 62u,
- 126u, 141u, 69u, 45u,
- 149u, 212u, 213u, 137u,
- 107u, 117u, 135u, 122u,
- 226u, 170u, 174u, 1u,
- 131u, 93u, 159u, 201u,
- 216u, 46u, 0u, 55u,
- 111u, 118u, 137u, 8u,
- 101u, 169u, 112u, 111u,
- 128u, 203u, 21u, 206u,
- 103u, 119u, 150u, 42u,
- 159u, 234u, 255u, 108u,
- 164u, 175u, 122u, 128u,
- 45u, 146u, 81u, 185u,
- 67u, 143u, 59u, 229u,
- 86u, 128u, 255u, 227u,
- 179u, 13u, 106u, 104u,
- 164u, 65u, 189u, 148u,
- 133u, 140u, 58u, 169u,
- 168u, 255u, 167u, 135u,
- 169u, 146u, 69u, 189u,
- 156u, 132u, 170u, 194u,
- 103u, 189u, 181u, 165u,
- 242u, 181u, 147u, 88u,
- 185u, 1u, 150u, 153u,
- 1u, 66u, 70u, 111u,
- 122u, 42u, 234u, 46u,
- 131u, 170u, 2u, 74u,
- 84u, 210u, 197u, 94u,
- 193u, 104u, 154u, 90u,
- 129u, 100u, 163u, 133u,
- 128u, 104u, 148u, 0u,
- 151u, 139u, 171u, 74u,
- 255u, 152u, 75u, 218u,
- 197u, 102u, 123u, 215u,
- 197u, 253u, 70u, 135u,
- 191u, 124u, 128u, 58u,
- 63u, 139u, 77u, 91u,
- 119u, 118u, 70u, 148u,
- 102u, 1u, 187u, 175u,
- 120u, 97u, 42u, 51u,
- 10u, 78u, 217u, 48u,
- 183u, 1u, 86u, 139u,
- 48u, 53u, 145u, 131u,
- 87u, 175u, 191u, 89u,
- 133u, 156u, 109u, 124u,
- 85u, 144u, 142u, 255u,
- 82u, 164u, 87u, 129u,
- 18u, 128u, 80u, 136u,
- 108u, 193u, 196u, 75u,
- 117u, 165u, 152u, 157u,
- 95u, 153u, 146u, 68u,
- 49u, 1u, 141u, 112u,
- 111u, 73u, 255u, 85u,
- 129u, 147u, 238u, 77u,
- 211u, 99u, 100u, 161u,
- 103u, 226u, 184u, 252u,
- 102u, 147u, 243u, 9u,
- 187u, 136u, 113u, 151u,
- 110u, 168u, 96u, 80u,
- 187u, 1u, 219u, 127u,
- 168u, 117u, 174u, 170u,
- 85u, 147u, 96u, 112u,
- 124u, 135u, 99u, 125u,
- 53u, 164u, 142u, 255u,
- 233u, 52u, 86u, 151u,
- 151u, 176u, 176u, 105u,
- 96u, 1u, 56u, 113u,
- 127u, 135u, 89u, 65u,
- 105u, 255u, 77u, 45u,
- 169u, 123u, 90u, 7u,
- 71u, 75u, 156u, 172u,
- 151u, 219u, 153u, 197u,
- 122u, 177u, 137u, 117u,
- 100u, 144u, 80u, 154u,
- 70u, 184u, 178u, 197u,
- 94u, 130u, 83u, 0u,
- 115u, 137u, 99u, 110u,
- 100u, 133u, 131u, 84u,
- 77u, 255u, 129u, 159u,
- 133u, 39u, 150u, 165u,
- 21u, 166u, 1u, 23u,
- 231u, 159u, 120u, 116u,
- 50u, 117u, 159u, 215u,
- 177u, 228u, 74u, 114u,
- 46u, 208u, 117u, 1u,
- 70u, 231u, 152u, 178u,
- 255u, 177u, 146u, 32u,
- 121u, 142u, 32u, 130u,
- 0u, 158u, 212u, 138u,
- 123u, 93u, 171u, 171u,
- 111u, 5u, 83u, 92u,
- 197u, 171u, 175u, 12u,
- 98u, 91u, 130u, 218u,
- 117u, 46u, 182u, 1u,
- 156u, 64u, 165u, 129u,
- 106u, 120u, 173u, 184u,
- 159u, 188u, 208u, 2u,
- 127u, 200u, 84u, 171u,
- 92u, 188u, 210u, 255u,
- 119u, 152u, 42u, 150u,
- 125u, 112u, 148u, 87u,
- 204u, 141u, 182u, 171u,
- 102u, 94u, 255u, 233u,
- 150u, 156u, 98u, 163u,
- 0u, 158u, 110u, 166u,
- 101u, 170u, 148u, 103u,
- 183u, 119u, 76u, 34u,
- 172u, 74u, 160u, 98u,
- 50u, 88u, 165u, 140u,
- 157u, 133u, 139u, 120u,
- 255u, 98u, 146u, 144u,
- 73u, 176u, 136u, 66u,
- 97u, 186u, 97u, 255u,
- 82u, 144u, 104u, 109u,
- 131u, 92u, 146u, 1u,
- 89u, 77u, 168u, 149u,
- 86u, 255u, 103u, 88u,
- 165u, 124u, 103u, 94u,
- 16u, 152u, 221u, 140u,
- 238u, 33u, 142u, 28u,
- 131u, 79u, 59u, 181u,
- 101u, 127u, 62u, 123u,
- 255u, 32u, 205u, 184u,
- 133u, 191u, 67u, 115u,
- 186u, 162u, 255u, 142u,
- 207u, 128u, 49u, 174u,
- 48u, 194u, 62u, 107u,
- 182u, 114u, 171u, 133u,
- 121u, 199u, 168u, 141u,
- 164u, 229u, 0u, 88u,
- 116u, 146u, 154u, 140u,
- 177u, 99u, 136u, 236u,
- 204u, 217u, 121u, 79u,
- 98u, 121u, 94u, 133u,
- 104u, 172u, 255u, 154u,
- 155u, 89u, 163u, 133u,
- 161u, 47u, 126u, 54u,
- 255u, 29u, 109u, 114u,
- 19u, 180u, 98u, 111u,
- 101u, 156u, 130u, 109u,
- 146u, 69u, 42u, 54u,
- 127u, 255u, 38u, 221u,
- 114u, 125u, 226u, 158u,
- 173u, 148u, 87u, 82u,
- 153u, 124u, 161u, 171u,
- 94u, 67u, 1u, 49u,
- 78u, 169u, 165u, 173u,
- 195u, 116u, 188u, 25u,
- 143u, 42u, 174u, 79u,
- 174u, 169u, 151u, 121u,
- 62u, 93u, 168u, 147u,
- 130u, 255u, 154u, 191u,
- 56u, 169u, 180u, 19u,
- 17u, 123u, 226u, 222u,
- 186u, 180u, 107u, 143u,
- 8u, 1u, 181u, 130u,
- 171u, 91u, 147u, 138u,
- 114u, 1u, 145u, 103u,
- 134u, 160u, 102u, 131u,
- 77u, 156u, 84u, 13u,
- 110u, 141u, 58u, 180u,
- 1u, 183u, 54u, 133u,
- 61u, 125u, 141u, 77u,
- 122u, 111u, 201u, 143u,
- 114u, 98u, 171u, 197u,
- 115u, 162u, 240u, 124u,
- 144u, 19u, 62u, 45u,
- 255u, 15u, 63u, 44u,
- 189u, 107u, 79u, 105u,
- 59u, 130u, 200u, 255u,
- 179u, 179u, 137u, 44u,
- 177u, 66u, 66u, 61u,
- 110u, 95u, 168u, 64u,
- 75u, 182u, 212u, 228u,
- 99u, 105u, 115u, 125u,
- 135u, 108u, 196u, 1u,
- 222u, 175u, 66u, 200u,
- 1u, 212u, 110u, 116u,
- 95u, 121u, 204u, 203u,
- 178u, 175u, 97u, 126u,
- 117u, 134u, 93u, 158u,
- 121u, 159u, 55u, 29u,
- 17u, 188u, 79u, 95u,
- 128u, 114u, 1u, 170u,
- 45u, 134u, 217u, 65u,
- 157u, 139u, 86u, 94u,
- 30u, 175u, 33u, 45u,
- 80u, 255u, 249u, 88u,
- 98u, 113u, 57u, 171u,
- 151u, 167u, 76u, 64u,
- 153u, 81u, 52u, 77u,
- 185u, 255u, 74u, 136u,
- 120u, 162u, 59u, 74u,
- 22u, 111u, 176u, 156u,
- 86u, 255u, 115u, 170u,
- 86u, 92u, 61u, 224u,
- 106u, 149u, 255u, 78u,
- 98u, 105u, 161u, 214u,
- 141u, 81u, 166u, 143u,
- 86u, 133u, 55u, 82u,
- 121u, 159u, 107u, 82u,
- 100u, 146u, 46u, 254u,
- 119u, 138u, 170u, 71u,
- 1u, 22u, 81u, 173u,
- 167u, 120u, 91u, 33u,
- 41u, 128u, 105u, 129u,
- 81u, 150u, 155u, 255u,
- 45u, 179u, 154u, 204u,
- 127u, 121u, 138u, 1u,
- 109u, 144u, 78u, 146u,
- 212u, 65u, 176u, 114u,
- 149u, 80u, 148u, 191u,
- 33u, 221u, 90u, 74u,
- 118u, 152u, 142u, 149u,
- 157u, 135u, 255u, 134u,
- 180u, 60u, 45u, 161u,
- 39u, 130u, 122u, 1u,
- 154u, 150u, 153u, 60u,
- 9u, 129u, 114u, 132u,
- 164u, 51u, 168u, 237u,
- 75u, 133u, 184u, 0u,
- 127u, 91u, 108u, 86u,
- 252u, 64u, 118u, 95u,
- 158u, 200u, 133u, 25u,
- 171u, 131u, 129u, 248u,
- 46u, 53u, 127u, 86u,
- 141u, 189u, 121u, 138u,
- 131u, 1u, 73u, 28u,
- 113u, 238u, 183u, 85u,
- 208u, 114u, 81u, 1u,
- 98u, 171u, 168u, 89u,
- 148u, 46u, 157u, 119u,
- 126u, 201u, 125u, 156u,
- 1u, 185u, 44u, 226u,
- 96u, 194u, 112u, 142u,
- 150u, 30u, 131u, 164u,
- 52u, 84u, 128u, 136u,
- 255u, 47u, 59u, 53u,
- 34u, 108u, 166u, 160u,
- 165u, 205u, 215u, 91u,
- 188u, 171u, 98u, 134u,
- 77u, 232u, 1u, 174u,
- 90u, 63u, 147u, 97u,
- 239u, 211u, 198u, 199u,
- 116u, 118u, 58u, 149u,
- 106u, 138u, 193u, 97u,
- 255u, 126u, 184u, 133u,
- 127u, 92u, 203u, 176u,
- 255u, 169u, 251u, 76u,
- 154u, 118u, 177u, 170u,
- 121u, 31u, 163u, 205u,
- 200u, 233u, 204u, 232u,
- 197u, 113u, 132u, 115u,
- 175u, 79u, 255u, 119u,
- 141u, 78u, 39u, 96u,
- 169u, 238u, 154u, 66u,
- 77u, 141u, 117u, 197u,
- 1u, 212u, 220u, 100u,
- 126u, 157u, 98u, 137u,
- 106u, 59u, 76u, 87u,
- 188u, 73u, 209u, 110u,
- 128u, 2u, 120u, 211u,
- 59u, 8u, 104u, 255u,
- 124u, 182u, 20u, 37u,
- 195u, 108u, 177u, 31u,
- 16u, 168u, 102u, 231u,
- 255u, 131u, 103u, 6u,
- 49u, 178u, 147u, 204u,
- 64u, 164u, 214u, 18u,
- 234u, 79u, 124u, 84u,
- 122u, 90u, 100u, 91u,
- 132u, 255u, 107u, 148u,
- 153u, 220u, 34u, 46u,
- 124u, 147u, 1u, 151u,
- 99u, 122u, 221u, 91u,
- 167u, 186u, 100u, 91u,
- 108u, 74u, 78u, 140u,
- 33u, 62u, 255u, 170u,
- 72u, 130u, 135u, 108u,
- 89u, 76u, 153u, 111u,
- 96u, 150u, 189u, 61u,
- 226u, 171u, 169u, 76u,
- 121u, 184u, 1u, 28u,
- 164u, 173u, 178u, 168u,
- 127u, 136u, 59u, 255u,
- 73u, 127u, 141u, 99u,
- 136u, 96u, 99u, 94u,
- 216u, 14u, 133u, 59u,
- 233u, 132u, 178u, 1u,
- 119u, 165u, 168u, 177u,
- 115u, 99u, 171u, 163u,
- 94u, 212u, 206u, 202u,
- 72u, 155u, 50u, 120u,
- 234u, 72u, 160u, 119u,
- 181u, 75u, 128u, 175u,
- 225u, 175u, 89u, 1u,
- 255u, 114u, 139u, 240u,
- 59u, 132u, 182u, 138u,
- 171u, 177u, 99u, 85u,
- 211u, 115u, 151u, 110u,
- 188u, 157u, 133u, 1u,
- 248u, 119u, 174u, 43u,
- 98u, 156u, 125u, 139u,
- 152u, 196u, 247u, 19u,
- 54u, 77u, 245u, 0u,
- 18u, 207u, 155u, 213u,
- 24u, 215u, 93u, 133u,
- 178u, 13u, 89u, 250u,
- 52u, 44u, 0u, 142u,
- 63u, 94u, 148u, 192u,
- 98u, 115u, 79u, 211u,
- 139u, 129u, 159u, 55u,
- 30u, 89u, 221u, 178u,
- 109u, 170u, 138u, 211u,
- 131u, 154u, 148u, 4u,
- 93u, 41u, 0u, 90u,
- 55u, 164u, 130u, 29u,
- 119u, 76u, 92u, 159u,
- 185u, 212u, 255u, 253u,
- 127u, 202u, 88u, 82u,
- 170u, 86u, 227u, 123u,
- 56u, 0u, 85u, 162u,
- 120u, 139u, 175u, 51u,
- 159u, 131u, 124u, 99u,
- 8u, 32u, 229u, 155u,
- 1u, 185u, 206u, 16u,
- 191u, 42u, 51u, 153u,
- 130u, 25u, 162u, 152u,
- 15u, 131u, 124u, 38u,
- 174u, 61u, 72u, 178u,
- 12u, 153u, 84u, 58u,
- 1u, 112u, 158u, 94u,
- 197u, 20u, 85u, 188u,
- 1u, 47u, 126u, 121u,
- 138u, 134u, 90u, 119u,
- 66u, 173u, 110u, 129u,
- 118u, 84u, 141u, 31u,
- 161u, 142u, 122u, 95u,
- 255u, 101u, 211u, 166u,
- 146u, 99u, 154u, 181u,
- 234u, 134u, 125u, 116u,
- 42u, 167u, 192u, 119u,
- 91u, 20u, 166u, 143u,
- 255u, 177u, 245u, 196u,
- 124u, 134u, 193u, 18u,
- 112u, 109u, 1u, 201u,
- 54u, 105u, 206u, 112u,
- 101u, 141u, 67u, 141u,
- 176u, 139u, 191u, 109u,
- 96u, 167u, 78u, 170u,
- 114u, 119u, 47u, 1u,
- 60u, 125u, 146u, 252u,
- 153u, 179u, 189u, 56u,
- 41u, 71u, 26u, 255u,
- 162u, 162u, 232u, 166u,
- 209u, 102u, 183u, 134u,
- 163u, 190u, 102u, 49u,
- 223u, 166u, 1u, 110u,
- 161u, 136u, 161u, 180u,
- 93u, 126u, 86u, 168u,
- 95u, 100u, 121u, 131u,
- 131u, 166u, 255u, 124u,
- 82u, 202u, 124u, 130u,
- 156u, 152u, 212u, 108u,
- 111u, 171u, 90u, 1u,
- 200u, 50u, 141u, 162u,
- 181u, 60u, 135u, 59u,
- 7u, 199u, 85u, 97u,
- 35u, 133u, 120u, 110u,
- 255u, 157u, 185u, 117u,
- 117u, 86u, 35u, 180u,
- 24u, 28u, 90u, 217u,
- 119u, 153u, 113u, 244u,
- 1u, 43u, 81u, 163u,
- 166u, 51u, 205u, 67u,
- 35u, 23u, 86u, 154u,
- 127u, 150u, 225u, 38u,
- 94u, 255u, 232u, 166u,
- 101u, 208u, 105u, 191u,
- 151u, 84u, 69u, 226u,
- 171u, 81u, 148u, 95u,
- 255u, 209u, 149u, 189u,
- 6u, 229u, 96u, 93u,
- 107u, 109u, 74u, 57u,
- 93u, 86u, 167u, 115u,
- 108u, 125u, 179u, 47u,
- 201u, 185u, 192u, 193u,
- 184u, 119u, 141u, 0u,
- 196u, 172u, 255u, 69u,
- 192u, 52u, 100u, 180u,
- 104u, 203u, 107u, 228u,
- 45u, 135u, 97u, 139u,
- 198u, 103u, 0u, 217u,
- 235u, 104u, 110u, 237u,
- 94u, 132u, 138u, 231u,
- 150u, 111u, 105u, 127u,
- 109u, 36u, 138u, 107u,
- 255u, 33u, 97u, 139u,
- 95u, 221u, 158u, 158u,
- 100u, 155u, 159u, 60u,
- 183u, 201u, 91u, 0u,
- 139u, 74u, 124u, 49u,
- 44u, 225u, 127u, 86u,
- 219u, 36u, 195u, 113u,
- 223u, 214u, 73u, 105u,
- 157u, 75u, 1u, 155u,
- 15u, 240u, 163u, 144u,
- 186u, 157u, 92u, 67u,
- 156u, 100u, 108u, 154u,
- 44u, 172u, 244u, 222u,
- 164u, 243u, 1u, 107u,
- 63u, 124u, 83u, 218u,
- 140u, 35u, 197u, 251u,
- 224u, 89u, 183u, 125u,
- 0u, 57u, 17u, 82u,
- 171u, 139u, 188u, 171u,
- 188u, 3u, 187u, 22u,
- 173u, 33u, 1u, 172u,
- 98u, 163u, 75u, 7u,
- 132u, 176u, 79u, 59u,
- 134u, 143u, 87u, 237u,
- 98u, 177u, 127u, 161u,
- 133u, 154u, 84u, 1u,
- 185u, 1u, 100u, 29u,
- 18u, 122u, 231u, 55u,
- 228u, 189u, 107u, 29u,
- 193u, 62u, 210u, 210u,
- 52u, 0u, 59u, 149u,
- 255u, 170u, 227u, 71u,
- 214u, 149u, 54u, 52u,
- 153u, 29u, 97u, 41u,
- 180u, 166u, 176u, 188u,
- 140u, 109u, 84u, 106u,
- 19u, 80u, 132u, 193u,
- 1u, 165u, 125u, 74u,
- 137u, 161u, 124u, 87u,
- 183u, 139u, 84u, 55u,
- 99u, 41u, 171u, 255u,
- 159u, 105u, 205u, 164u,
- 156u, 81u, 175u, 124u,
- 236u, 128u, 143u, 82u,
- 132u, 235u, 191u, 96u,
- 80u, 164u, 167u, 52u,
- 223u, 255u, 143u, 60u,
- 80u, 72u, 109u, 139u,
- 180u, 212u, 42u, 235u,
- 134u, 76u, 28u, 2u,
- 165u, 89u, 15u, 255u,
- 250u, 156u, 255u, 210u,
- 25u, 165u, 114u, 175u,
- 91u, 114u, 152u, 143u,
- 146u, 179u, 51u, 162u,
- 207u, 189u, 23u, 178u,
- 105u, 35u, 79u, 130u,
- 198u, 100u, 176u, 47u,
- 1u, 201u, 28u, 132u,
- 186u, 168u, 148u, 57u,
- 223u, 156u, 255u, 125u,
- 147u, 56u, 49u, 161u,
- 181u, 190u, 185u, 50u,
- 94u, 35u, 119u, 113u,
- 24u, 46u, 73u, 153u,
- 192u, 102u, 75u, 58u,
- 39u, 73u, 1u, 108u,
- 111u, 107u, 228u, 88u,
- 69u, 132u, 207u, 182u,
- 76u, 255u, 83u, 227u,
- 40u, 165u, 115u, 127u,
- 138u, 130u, 121u, 217u,
- 140u, 255u, 255u, 203u,
- 227u, 79u, 133u, 183u,
- 171u, 102u, 175u, 198u,
- 135u, 65u, 109u, 255u,
- 125u, 137u, 57u, 70u,
- 99u, 115u, 152u, 80u,
- 153u, 123u, 137u, 111u,
- 209u, 107u, 35u, 166u,
- 146u, 35u, 117u, 82u,
- 175u, 215u, 120u, 92u,
- 224u, 147u, 1u, 92u,
- 82u, 122u, 150u, 181u,
- 89u, 151u, 73u, 127u,
- 73u, 137u, 255u, 229u,
- 241u, 96u, 82u, 172u,
- 60u, 43u, 181u, 104u,
- 93u, 118u, 146u, 16u,
- 131u, 210u, 1u, 207u,
- 58u, 5u, 47u, 161u,
- 17u, 78u, 26u, 162u,
- 195u, 239u, 255u, 166u,
- 173u, 113u, 30u, 210u,
- 203u, 81u, 136u, 150u,
- 93u, 142u, 72u, 1u,
- 55u, 110u, 156u, 167u,
- 59u, 148u, 254u, 180u,
- 120u, 147u, 130u, 203u,
- 147u, 132u, 172u, 128u,
- 130u, 180u, 86u, 173u,
- 170u, 0u, 183u, 123u,
- 215u, 114u, 40u, 62u,
- 71u, 162u, 143u, 1u,
- 149u, 37u, 65u, 155u,
- 112u, 68u, 254u, 116u,
- 188u, 69u, 74u, 246u,
- 162u, 77u, 154u, 196u,
- 71u, 71u, 125u, 89u,
- 111u, 211u, 76u, 94u,
- 26u, 1u, 184u, 171u,
- 103u, 153u, 71u, 255u,
- 118u, 6u, 73u, 128u,
- 196u, 108u, 107u, 144u,
- 35u, 128u, 60u, 108u,
- 96u, 226u, 73u, 188u,
- 5u, 158u, 35u, 87u,
- 174u, 90u, 255u, 111u,
- 121u, 66u, 119u, 132u,
- 144u, 194u, 88u, 239u,
- 93u, 148u, 155u, 152u,
- 1u, 193u, 86u, 152u,
- 205u, 128u, 58u, 58u,
- 160u, 10u, 255u, 142u,
- 116u, 79u, 51u, 99u,
- 213u, 157u, 111u, 119u,
- 106u, 63u, 66u, 129u,
- 236u, 92u, 103u, 238u,
- 250u, 193u, 52u, 0u,
- 49u, 47u, 76u, 145u,
- 25u, 179u, 121u, 202u,
- 140u, 70u, 141u, 162u,
- 59u, 160u, 131u, 1u,
- 164u, 154u, 95u, 56u,
- 100u, 149u, 205u, 82u,
- 134u, 41u, 19u, 37u,
- 17u, 202u, 110u, 101u,
- 85u, 62u, 68u, 1u,
- 132u, 159u, 241u, 174u,
- 73u, 211u, 132u, 103u,
- 198u, 101u, 150u, 141u,
- 214u, 206u, 98u, 124u,
- 113u, 31u, 56u, 1u,
- 228u, 146u, 56u, 232u,
- 173u, 98u, 176u, 92u,
- 110u, 98u, 1u, 88u,
- 163u, 186u, 61u, 0u,
- 211u, 202u, 163u, 43u,
- 220u, 76u, 161u, 7u,
- 33u, 187u, 24u, 108u,
- 158u, 0u, 249u, 137u,
- 65u, 75u, 255u, 148u,
- 237u, 67u, 253u, 88u,
- 87u, 99u, 54u, 191u,
- 89u, 117u, 24u, 187u,
- 255u, 148u, 2u, 155u,
- 138u, 97u, 39u, 95u,
- 23u, 118u, 231u, 67u,
- 212u, 179u, 239u, 129u,
- 147u, 96u, 82u, 119u,
- 177u, 154u, 21u, 163u,
- 86u, 173u, 58u, 139u,
- 63u, 77u, 1u, 116u,
- 34u, 134u, 96u, 153u,
- 111u, 150u, 63u, 95u,
- 172u, 144u, 209u, 255u,
- 218u, 2u, 225u, 116u,
- 83u, 159u, 85u, 255u,
- 126u, 157u, 97u, 145u,
- 101u, 79u, 126u, 105u,
- 71u, 76u, 178u, 164u,
- 165u, 113u, 143u, 110u,
- 136u, 52u, 107u, 103u,
- 1u, 147u, 14u, 160u,
- 211u, 121u, 88u, 174u,
- 166u, 86u, 60u, 135u,
- 196u, 15u, 93u, 104u,
- 170u, 134u, 55u, 111u,
- 140u, 124u, 100u, 1u,
- 144u, 177u, 101u, 94u,
- 21u, 148u, 52u, 211u,
- 72u, 206u, 255u, 154u,
- 57u, 150u, 90u, 182u,
- 174u, 97u, 155u, 200u,
- 62u, 117u, 26u, 62u,
- 107u, 87u, 255u, 147u,
- 68u, 168u, 22u, 84u,
- 113u, 147u, 189u, 128u,
- 145u, 151u, 151u, 97u,
- 101u, 109u, 133u, 110u,
- 109u, 255u, 124u, 118u,
- 133u, 135u, 175u, 163u,
- 134u, 141u, 220u, 158u,
- 163u, 208u, 83u, 87u,
- 255u, 109u, 196u, 53u,
- 150u, 110u, 37u, 200u,
- 41u, 196u, 170u, 255u,
- 220u, 207u, 88u, 120u,
- 144u, 88u, 89u, 91u,
- 59u, 141u, 148u, 20u,
- 114u, 175u, 85u, 116u,
- 162u, 62u, 131u, 77u,
- 90u, 119u, 255u, 157u,
- 15u, 216u, 130u, 1u,
- 43u, 138u, 136u, 154u,
- 86u, 154u, 220u, 197u,
- 171u, 31u, 148u, 155u,
- 100u, 182u, 193u, 1u,
- 124u, 107u, 128u, 205u,
- 162u, 113u, 110u, 192u,
- 58u, 189u, 149u, 84u,
- 185u, 93u, 134u, 119u,
- 127u, 137u, 179u, 127u,
- 96u, 115u, 57u, 1u,
- 149u, 130u, 152u, 150u,
- 190u, 81u, 142u, 217u,
- 1u, 143u, 169u, 31u,
- 121u, 179u, 209u, 182u,
- 204u, 248u, 54u, 94u,
- 116u, 164u, 185u, 54u,
- 51u, 255u, 54u, 234u,
- 230u, 148u, 122u, 103u,
- 90u, 0u, 190u, 240u,
- 168u, 105u, 161u, 131u,
- 170u, 1u, 94u, 162u,
- 45u, 137u, 151u, 242u,
- 105u, 78u, 108u, 93u,
- 72u, 154u, 120u, 112u,
- 51u, 232u, 211u, 127u,
- 165u, 91u, 255u, 187u,
- 199u, 96u, 107u, 146u,
- 61u, 137u, 121u, 92u,
- 188u, 197u, 60u, 189u,
- 42u, 188u, 1u, 142u,
- 156u, 145u, 106u, 238u,
- 202u, 105u, 219u, 94u,
- 224u, 44u, 117u, 62u,
- 136u, 43u, 50u, 255u,
- 157u, 207u, 79u, 158u,
- 59u, 122u, 131u, 124u,
- 54u, 92u, 158u, 82u,
- 184u, 187u, 146u, 255u,
- 255u, 178u, 119u, 84u,
- 70u, 183u, 111u, 62u,
- 246u, 99u, 185u, 151u,
- 78u, 1u, 79u, 150u,
- 116u, 183u, 211u, 151u,
- 165u, 147u, 158u, 141u,
- 58u, 150u, 89u, 98u,
- 154u, 0u, 171u, 171u,
- 117u, 117u, 173u, 118u,
- 171u, 149u, 234u, 122u,
- 228u, 175u, 253u, 87u,
- 22u, 118u, 1u, 99u,
- 212u, 184u, 123u, 166u,
- 84u, 167u, 166u, 84u,
- 165u, 132u, 145u, 172u,
- 172u, 255u, 179u, 142u,
- 204u, 59u, 34u, 34u,
- 165u, 206u, 229u, 55u,
- 120u, 101u, 152u, 160u,
- 151u, 107u, 103u, 74u,
- 255u, 229u, 122u, 129u,
- 133u, 98u, 103u, 237u,
- 128u, 122u, 74u, 143u,
- 103u, 82u, 97u, 1u,
- 54u, 156u, 84u, 75u,
- 200u, 111u, 94u, 192u,
- 185u, 100u, 93u, 102u,
- 113u, 132u, 160u, 158u,
- 135u, 155u, 113u, 0u,
- 179u, 100u, 62u, 255u,
- 88u, 164u, 52u, 82u,
- 97u, 110u, 106u, 136u,
- 101u, 185u, 107u, 136u,
- 148u, 147u, 118u, 122u,
- 199u, 133u, 186u, 142u,
- 255u, 102u, 114u, 128u,
- 124u, 207u, 54u, 125u,
- 172u, 66u, 34u, 255u,
- 15u, 56u, 125u, 233u,
- 208u, 163u, 131u, 90u,
- 59u, 152u, 8u, 22u,
- 74u, 0u, 167u, 120u,
- 134u, 47u, 55u, 92u,
- 88u, 125u, 146u, 126u,
- 54u, 110u, 65u, 102u,
- 122u, 161u, 225u, 113u,
- 194u, 206u, 203u, 90u,
- 151u, 160u, 126u, 164u,
- 74u, 255u, 145u, 64u,
- 151u, 97u, 129u, 58u,
- 87u, 45u, 161u, 169u,
- 124u, 183u, 78u, 148u,
- 0u, 113u, 98u, 142u,
- 1u, 202u, 39u, 146u,
- 197u, 224u, 67u, 237u,
- 153u, 201u, 181u, 25u,
- 68u, 58u, 112u, 144u,
- 132u, 61u, 178u, 148u,
- 91u, 87u, 99u, 75u,
- 32u, 108u, 140u, 0u,
- 94u, 108u, 73u, 60u,
- 98u, 147u, 95u, 191u,
- 42u, 41u, 218u, 166u,
- 130u, 136u, 90u, 94u,
- 1u, 143u, 87u, 138u,
- 30u, 74u, 161u, 42u,
- 255u, 160u, 45u, 84u,
- 142u, 178u, 111u, 63u,
- 150u, 141u, 121u, 50u,
- 109u, 171u, 92u, 0u,
- 129u, 54u, 126u, 140u,
- 134u, 119u, 148u, 189u,
- 128u, 167u, 130u, 202u,
- 255u, 119u, 221u, 162u,
- 187u, 20u, 131u, 88u,
- 205u, 35u, 123u, 51u,
- 111u, 213u, 137u, 1u,
- 54u, 93u, 178u, 224u,
- 122u, 109u, 128u, 255u,
- 162u, 125u, 49u, 101u,
- 164u, 124u, 26u, 121u,
- 33u, 215u, 88u, 205u,
- 100u, 186u, 121u, 139u,
- 157u, 181u, 117u, 171u,
- 118u, 1u, 74u, 75u,
- 124u, 166u, 255u, 139u,
- 182u, 113u, 107u, 134u,
- 125u, 107u, 103u, 92u,
- 46u, 89u, 160u, 126u,
- 255u, 202u, 152u, 75u,
- 192u, 206u, 215u, 200u,
- 114u, 159u, 10u, 131u,
- 111u, 250u, 37u, 199u,
- 169u, 89u, 132u, 121u,
- 170u, 169u, 143u, 169u,
- 66u, 146u, 116u, 202u,
- 255u, 141u, 100u, 177u,
- 103u, 208u, 105u, 233u,
- 46u, 93u, 49u, 45u,
- 6u, 164u, 106u, 1u,
- 129u, 121u, 135u, 157u,
- 74u, 15u, 255u, 75u,
- 130u, 61u, 195u, 100u,
- 222u, 38u, 53u, 97u,
- 192u, 23u, 212u, 82u,
- 133u, 120u, 101u, 144u,
- 71u, 143u, 90u, 62u,
- 206u, 1u, 172u, 165u,
- 106u, 191u, 122u, 116u,
- 146u, 188u, 141u, 92u,
- 42u, 152u, 1u, 141u,
- 70u, 165u, 224u, 168u,
- 84u, 52u, 71u, 137u,
- 53u, 90u, 150u, 140u,
- 255u, 81u, 119u, 178u,
- 121u, 66u, 119u, 155u,
- 162u, 172u, 136u, 90u,
- 132u, 43u, 183u, 155u,
- 134u, 255u, 104u, 187u,
- 228u, 31u, 208u, 72u,
- 158u, 56u, 83u, 90u,
- 104u, 184u, 107u, 27u,
- 74u, 255u, 128u, 115u,
- 89u, 179u, 158u, 75u,
- 163u, 116u, 195u, 221u,
- 24u, 246u, 219u, 125u,
- 55u, 148u, 91u, 1u,
- 125u, 191u, 211u, 221u,
- 173u, 45u, 159u, 163u,
- 173u, 48u, 175u, 151u,
- 177u, 170u, 78u, 114u,
- 1u, 243u, 121u, 25u,
- 235u, 90u, 184u, 70u,
- 49u, 73u, 142u, 58u,
- 195u, 113u, 140u, 149u,
- 156u, 126u, 76u, 27u,
- 136u, 1u, 194u, 80u,
- 64u, 93u, 207u, 15u,
- 150u, 82u, 81u, 169u,
- 59u, 226u, 134u, 139u,
- 158u, 255u, 127u, 133u,
- 168u, 230u, 48u, 162u,
- 207u, 75u, 94u, 144u,
- 49u, 117u, 26u, 76u,
- 136u, 171u, 217u, 1u,
- 95u, 150u, 255u, 103u,
- 90u, 117u, 193u, 162u,
- 110u, 125u, 182u, 156u,
- 89u, 102u, 159u, 89u,
- 146u, 82u, 171u, 109u,
- 255u, 32u, 119u, 147u,
- 6u, 166u, 206u, 145u,
- 197u, 216u, 113u, 175u,
- 149u, 196u, 114u, 111u,
- 15u, 105u, 255u, 255u,
- 186u, 115u, 180u, 52u,
- 121u, 108u, 109u, 74u,
- 67u, 115u, 131u, 137u,
- 84u, 200u, 213u, 151u,
- 146u, 81u, 180u, 65u,
- 255u, 58u, 28u, 88u,
- 116u, 101u, 255u, 115u,
- 235u, 154u, 82u, 65u,
- 153u, 87u, 81u, 143u,
- 89u, 101u, 130u, 99u,
- 94u, 133u, 68u, 179u,
- 1u, 134u, 136u, 159u,
- 148u, 95u, 209u, 176u,
- 172u, 76u, 89u, 113u,
- 103u, 27u, 40u, 166u,
- 152u, 181u, 65u, 158u,
- 194u, 59u, 120u, 119u,
- 255u, 169u, 89u, 101u,
- 184u, 243u, 95u, 181u,
- 151u, 255u, 117u, 226u,
- 230u, 149u, 247u, 138u,
- 143u, 116u, 75u, 181u,
- 110u, 210u, 113u, 210u,
- 143u, 0u, 84u, 70u,
- 99u, 106u, 211u, 184u,
- 138u, 111u, 119u, 62u,
- 67u, 129u, 68u, 46u,
- 77u, 149u, 81u, 83u,
- 178u, 255u, 217u, 152u,
- 51u, 192u, 70u, 151u,
- 50u, 1u, 76u, 151u,
- 128u, 22u, 213u, 53u,
- 131u, 81u, 84u, 187u,
- 47u, 184u, 145u, 56u,
- 157u, 78u, 77u, 159u,
- 183u, 44u, 255u, 150u,
- 234u, 132u, 59u, 188u,
- 72u, 40u, 127u, 138u,
- 1u, 175u, 81u, 207u,
- 19u, 102u, 162u, 77u,
- 54u, 169u, 106u, 77u,
- 154u, 30u, 86u, 181u,
- 206u, 200u, 222u, 29u,
- 152u, 121u, 3u, 171u,
- 138u, 162u, 223u, 162u,
- 0u, 237u, 57u, 96u,
- 221u, 138u, 92u, 178u,
- 21u, 121u, 255u, 34u,
- 125u, 123u, 89u, 132u,
- 100u, 221u, 40u, 57u,
- 157u, 151u, 114u, 138u,
- 198u, 78u, 192u, 64u,
- 79u, 169u, 124u, 255u,
- 116u, 194u, 134u, 175u,
- 62u, 157u, 90u, 67u,
- 163u, 35u, 164u, 255u,
- 163u, 188u, 173u, 225u,
- 123u, 156u, 51u, 107u,
- 105u, 219u, 132u, 92u,
- 43u, 146u, 75u, 222u,
- 60u, 197u, 171u, 151u,
- 51u, 1u, 98u, 223u,
- 255u, 139u, 34u, 217u,
- 101u, 76u, 202u, 59u,
- 225u, 82u, 115u, 55u,
- 158u, 152u, 93u, 101u,
- 65u, 92u, 1u, 77u,
- 115u, 108u, 133u, 113u,
- 127u, 82u, 225u, 203u,
- 143u, 106u, 212u, 131u,
- 159u, 220u, 255u, 238u,
- 34u, 63u, 150u, 151u,
- 161u, 63u, 149u, 125u,
- 44u, 173u, 218u, 39u,
- 219u, 90u, 220u, 13u,
- 187u, 62u, 167u, 178u,
- 159u, 153u, 133u, 182u,
- 32u, 112u, 78u, 255u,
- 109u, 122u, 186u, 148u,
- 165u, 86u, 255u, 38u,
- 124u, 156u, 72u, 118u,
- 145u, 170u, 144u, 100u,
- 107u, 185u, 16u, 195u,
- 66u, 108u, 215u, 86u,
- 194u, 1u, 202u, 168u,
- 149u, 87u, 60u, 159u,
- 95u, 204u, 136u, 101u,
- 51u, 158u, 183u, 142u,
- 33u, 81u, 61u, 205u,
- 125u, 1u, 66u, 127u,
- 219u, 159u, 255u, 180u,
- 103u, 161u, 58u, 188u,
- 154u, 140u, 102u, 58u,
- 251u, 110u, 116u, 31u,
- 166u, 46u, 146u, 113u,
- 160u, 163u, 225u, 1u,
- 28u, 130u, 159u, 146u,
- 214u, 55u, 222u, 101u,
- 141u, 84u, 153u, 219u,
- 73u, 147u, 36u, 141u,
- 137u, 1u, 106u, 88u,
- 127u, 95u, 122u, 96u,
- 159u, 116u, 115u, 82u,
- 104u, 112u, 177u, 76u,
- 236u, 177u, 188u, 135u,
- 239u, 99u, 42u, 0u,
- 139u, 255u, 180u, 123u,
- 192u, 212u, 188u, 99u,
- 9u, 88u, 111u, 65u,
- 32u, 63u, 154u, 171u,
- 158u, 162u, 255u, 89u,
- 120u, 188u, 102u, 100u,
- 84u, 189u, 88u, 112u,
- 134u, 77u, 116u, 100u,
- 181u, 171u, 55u, 165u,
- 72u, 77u, 104u, 255u,
- 82u, 213u, 140u, 197u,
- 184u, 110u, 95u, 13u,
- 208u, 52u, 141u, 232u,
- 161u, 162u, 103u, 140u,
- 1u, 46u, 25u, 159u,
- 176u, 91u, 92u, 88u,
- 108u, 110u, 213u, 1u,
- 148u, 77u, 252u, 46u,
- 151u, 88u, 26u, 112u,
- 138u, 144u, 151u, 105u,
- 153u, 172u, 118u, 180u,
- 35u, 105u, 184u, 125u,
- 21u, 57u, 151u, 167u,
- 1u, 29u, 88u, 123u,
- 121u, 92u, 176u, 101u,
- 205u, 144u, 226u, 107u,
- 103u, 255u, 58u, 223u,
- 145u, 181u, 67u, 173u,
- 147u, 122u, 95u, 140u,
- 168u, 45u, 149u, 114u,
- 151u, 93u, 79u, 127u,
- 244u, 250u, 78u, 1u,
- 126u, 94u, 126u, 111u,
- 98u, 46u, 169u, 183u,
- 140u, 137u, 176u, 150u,
- 190u, 206u, 117u, 1u,
- 88u, 167u, 111u, 124u,
- 110u, 38u, 131u, 146u,
- 59u, 210u, 194u, 231u,
- 7u, 1u, 56u, 124u,
- 155u, 109u, 101u, 205u,
- 4u, 112u, 45u, 105u,
- 218u, 152u, 250u, 194u,
- 1u, 138u, 63u, 118u,
- 135u, 151u, 203u, 51u,
- 229u, 29u, 192u, 123u,
- 26u, 242u, 0u, 86u,
- 137u, 81u, 56u, 79u,
- 40u, 59u, 233u, 255u,
- 228u, 134u, 248u, 74u,
- 45u, 25u, 2u, 137u,
- 199u, 187u, 203u, 193u,
- 208u, 44u, 79u, 111u,
- 63u, 1u, 93u, 113u,
- 154u, 67u, 187u, 89u,
- 132u, 155u, 142u, 205u,
- 87u, 48u, 80u, 156u,
- 106u, 169u, 1u, 119u,
- 222u, 114u, 164u, 84u,
- 133u, 123u, 153u, 52u,
- 157u, 183u, 34u, 249u,
- 172u, 115u, 97u, 170u,
- 1u, 184u, 120u, 104u,
- 117u, 118u, 131u, 137u,
- 238u, 94u, 255u, 55u,
- 7u, 139u, 86u, 145u,
- 50u, 65u, 235u, 136u,
- 173u, 135u, 76u, 127u,
- 162u, 118u, 113u, 102u,
- 156u, 133u, 86u, 172u,
- 91u, 155u, 103u, 127u,
- 111u, 106u, 1u, 125u,
- 168u, 110u, 154u, 149u,
- 208u, 104u, 23u, 143u,
- 63u, 255u, 85u, 94u,
- 125u, 109u, 61u, 165u,
- 99u, 166u, 88u, 141u,
- 110u, 255u, 66u, 112u,
- 58u, 101u, 76u, 104u,
- 82u, 123u, 121u, 141u,
- 181u, 120u, 24u, 190u,
- 83u, 100u, 149u, 109u,
- 91u, 213u, 255u, 187u,
- 116u, 67u, 48u, 165u,
- 167u, 111u, 83u, 175u,
- 162u, 255u, 220u, 63u,
- 55u, 144u, 51u, 136u,
- 155u, 156u, 219u, 126u,
- 142u, 232u, 144u, 154u,
- 148u, 107u, 255u, 160u,
- 59u, 105u, 46u, 116u,
- 54u, 163u, 146u, 33u,
- 165u, 181u, 153u, 255u,
- 70u, 84u, 119u, 193u,
- 71u, 170u, 184u, 113u,
- 176u, 148u, 132u, 69u,
- 180u, 84u, 81u, 192u,
- 158u, 110u, 255u, 120u,
- 161u, 127u, 83u, 150u,
- 86u, 149u, 108u, 147u,
- 51u, 95u, 70u, 0u,
- 98u, 170u, 171u, 91u,
- 130u, 137u, 48u, 72u,
- 11u, 190u, 75u, 195u,
- 132u, 101u, 140u, 189u,
- 132u, 156u, 105u, 77u,
- 85u, 0u, 99u, 158u,
- 172u, 210u, 97u, 74u,
- 170u, 176u, 93u, 129u,
- 115u, 94u, 91u, 103u,
- 1u, 124u, 141u, 170u,
- 62u, 91u, 99u, 179u,
- 160u, 1u, 164u, 73u,
- 225u, 85u, 143u, 39u,
- 165u, 184u, 79u, 143u,
- 116u, 157u, 85u, 85u,
- 236u, 133u, 182u, 29u,
- 174u, 255u, 87u, 204u,
- 144u, 224u, 81u, 69u,
- 183u, 130u, 63u, 110u,
- 90u, 90u, 136u, 145u,
- 116u, 189u, 144u, 148u,
- 105u, 150u, 207u, 96u,
- 255u, 87u, 253u, 97u,
- 72u, 71u, 68u, 67u,
- 145u, 217u, 94u, 131u,
- 173u, 255u, 137u, 91u,
- 50u, 104u, 46u, 73u,
- 103u, 191u, 178u, 147u,
- 131u, 1u, 166u, 106u,
- 146u, 28u, 199u, 105u,
- 84u, 206u, 164u, 160u,
- 159u, 120u, 140u, 223u,
- 184u, 167u, 51u, 55u,
- 129u, 1u, 111u, 129u,
- 113u, 78u, 155u, 102u,
- 113u, 165u, 1u, 182u,
- 105u, 138u, 155u, 126u,
- 100u, 134u, 17u, 127u,
- 70u, 73u, 130u, 218u,
- 126u, 55u, 90u, 0u,
- 85u, 94u, 161u, 144u,
- 139u, 133u, 118u, 127u,
- 38u, 188u, 205u, 134u,
- 16u, 82u, 217u, 226u,
- 102u, 221u, 128u, 89u,
- 8u, 255u, 42u, 153u,
- 237u, 9u, 34u, 223u,
- 71u, 192u, 124u, 68u,
- 124u, 167u, 116u, 149u,
- 100u, 255u, 65u, 156u,
- 129u, 53u, 33u, 199u,
- 181u, 224u, 85u, 0u,
- 61u, 109u, 127u, 158u,
- 140u, 229u, 109u, 95u,
- 150u, 45u, 141u, 34u,
- 115u, 158u, 84u, 255u,
- 92u, 106u, 54u, 73u,
- 185u, 51u, 44u, 114u,
- 239u, 84u, 75u, 72u,
- 127u, 208u, 255u, 96u,
- 117u, 176u, 159u, 148u,
- 125u, 93u, 177u, 156u,
- 90u, 132u, 210u, 168u,
- 110u, 149u, 0u, 152u,
- 61u, 78u, 115u, 67u,
- 151u, 207u, 196u, 207u,
- 149u, 189u, 148u, 170u,
- 184u, 135u, 80u, 181u,
- 124u, 87u, 157u, 69u,
- 90u, 92u, 122u, 227u,
- 255u, 189u, 146u, 55u,
- 74u, 190u, 255u, 74u,
- 123u, 153u, 93u, 216u,
- 46u, 68u, 145u, 159u,
- 104u, 103u, 120u, 174u,
- 115u, 122u, 114u, 155u,
- 70u, 74u, 134u, 88u,
- 1u, 169u, 115u, 36u,
- 82u, 26u, 109u, 25u,
- 138u, 139u, 128u, 106u,
- 173u, 171u, 189u, 169u,
- 123u, 100u, 188u, 255u,
- 129u, 191u, 107u, 116u,
- 124u, 122u, 2u, 191u,
- 30u, 255u, 106u, 169u,
- 115u, 243u, 245u, 232u,
- 104u, 225u, 136u, 127u,
- 123u, 193u, 136u, 168u,
- 96u, 187u, 100u, 232u,
- 159u, 19u, 120u, 93u,
- 255u, 175u, 175u, 33u,
- 252u, 134u, 103u, 47u,
- 7u, 199u, 181u, 104u,
- 25u, 172u, 84u, 44u,
- 53u, 255u, 161u, 24u,
- 59u, 62u, 246u, 100u,
- 59u, 116u, 24u, 109u,
- 113u, 49u, 160u, 101u,
- 125u, 153u, 110u, 255u,
- 142u, 108u, 139u, 173u,
- 221u, 141u, 55u, 212u,
- 164u, 167u, 123u, 255u,
- 82u, 74u, 150u, 144u,
- 24u, 91u, 185u, 41u,
- 114u, 141u, 130u, 165u,
- 149u, 49u, 50u, 145u,
- 29u, 162u, 147u, 255u,
- 89u, 83u, 118u, 129u,
- 107u, 107u, 88u, 134u,
- 163u, 123u, 79u, 188u,
- 1u, 94u, 130u, 208u,
- 95u, 97u, 119u, 51u,
- 101u, 173u, 139u, 255u,
- 72u, 187u, 56u, 169u,
- 54u, 158u, 25u, 89u,
- 168u, 179u, 183u, 66u,
- 168u, 175u, 20u, 187u,
- 43u, 162u, 191u, 203u,
- 138u, 1u, 145u, 226u,
- 109u, 163u, 127u, 185u,
- 148u, 137u, 141u, 133u,
- 63u, 190u, 117u, 41u,
- 219u, 38u, 172u, 255u,
- 163u, 89u, 198u, 106u,
- 117u, 180u, 255u, 151u,
- 83u, 176u, 164u, 156u,
- 125u, 102u, 65u, 106u,
- 76u, 133u, 129u, 106u,
- 255u, 139u, 61u, 88u,
- 217u, 101u, 180u, 29u,
- 24u, 157u, 36u, 91u,
- 221u, 1u, 44u, 229u,
- 102u, 118u, 159u, 147u,
- 212u, 139u, 90u, 76u,
- 128u, 25u, 75u, 113u,
- 236u, 108u, 173u, 165u,
- 175u, 56u, 255u, 55u,
- 193u, 86u, 22u, 199u,
- 125u, 202u, 147u, 108u,
- 33u, 93u, 23u, 187u,
- 181u, 157u, 240u, 255u,
- 166u, 18u, 64u, 186u,
- 163u, 171u, 249u, 99u,
- 69u, 131u, 136u, 163u,
- 151u, 155u, 96u, 116u,
- 169u, 155u, 184u, 142u,
- 120u, 0u, 116u, 108u,
- 216u, 154u, 36u, 209u,
- 133u, 225u, 255u, 129u,
- 177u, 213u, 43u, 177u,
- 145u, 80u, 158u, 106u,
- 168u, 131u, 38u, 146u,
- 93u, 122u, 145u, 68u,
- 121u, 218u, 82u, 164u,
- 100u, 255u, 157u, 174u,
- 159u, 57u, 213u, 188u,
- 0u, 116u, 237u, 39u,
- 166u, 109u, 170u, 84u,
- 162u, 33u, 147u, 83u,
- 188u, 121u, 84u, 187u,
- 95u, 204u, 204u, 255u,
- 133u, 158u, 145u, 175u,
- 219u, 130u, 117u, 169u,
- 141u, 111u, 164u, 161u,
- 0u, 161u, 234u, 144u,
- 78u, 176u, 81u, 178u,
- 127u, 114u, 170u, 143u,
- 170u, 67u, 1u, 160u,
- 231u, 134u, 122u, 156u,
- 226u, 60u, 155u, 204u,
- 149u, 148u, 200u, 137u,
- 213u, 122u, 190u, 55u,
- 233u, 1u, 50u, 41u,
- 111u, 153u, 203u, 83u,
- 25u, 164u, 139u, 84u,
- 195u, 228u, 94u, 84u,
- 1u, 88u, 103u, 59u,
- 51u, 145u, 248u, 234u,
- 138u, 58u, 164u, 146u,
- 126u, 189u, 89u, 139u,
- 57u, 125u, 71u, 206u,
- 79u, 138u, 160u, 145u,
- 80u, 255u, 121u, 86u,
- 160u, 107u, 83u, 127u,
- 101u, 210u, 0u, 241u,
- 172u, 111u, 98u, 125u,
- 199u, 126u, 134u, 183u,
- 117u, 55u, 143u, 16u,
- 178u, 180u, 108u, 141u,
- 104u, 144u, 83u, 175u,
- 103u, 165u, 80u, 255u,
- 65u, 1u, 123u, 85u,
- 191u, 74u, 181u, 57u,
- 203u, 252u, 190u, 93u,
- 218u, 106u, 11u, 104u,
- 134u, 158u, 87u, 98u,
- 82u, 112u, 49u, 255u,
- 30u, 70u, 138u, 151u,
- 190u, 52u, 114u, 141u,
- 152u, 49u, 103u, 90u,
- 14u, 223u, 133u, 145u,
- 241u, 124u, 196u, 211u,
- 1u, 158u, 80u, 192u,
- 174u, 40u, 45u, 0u,
- 140u, 159u, 82u, 188u,
- 136u, 147u, 238u, 194u,
- 45u, 225u, 62u, 202u,
- 123u, 30u, 118u, 87u,
- 127u, 85u, 178u, 184u,
- 87u, 140u, 92u, 203u,
- 114u, 255u, 100u, 116u,
- 132u, 192u, 255u, 189u,
- 175u, 89u, 192u, 220u,
- 239u, 102u, 93u, 45u,
- 96u, 105u, 42u, 47u,
- 109u, 165u, 96u, 209u,
- 1u, 173u, 21u, 126u,
- 26u, 112u, 105u, 94u,
- 85u, 42u, 151u, 153u,
- 161u, 213u, 90u, 77u,
- 182u, 112u, 178u, 81u,
- 255u, 96u, 229u, 165u,
- 197u, 237u, 234u, 126u,
- 150u, 63u, 54u, 239u,
- 121u, 61u, 255u, 71u,
- 115u, 143u, 167u, 107u,
- 103u, 72u, 172u, 46u,
- 199u, 35u, 199u, 251u,
- 138u, 135u, 154u, 47u,
- 73u, 69u, 1u, 93u,
- 113u, 211u, 210u, 252u,
- 154u, 35u, 76u, 146u,
- 237u, 73u, 255u, 111u,
- 244u, 109u, 27u, 202u,
- 68u, 225u, 159u, 79u,
- 175u, 47u, 169u, 152u,
- 1u, 115u, 200u, 167u,
- 92u, 133u, 44u, 32u,
- 149u, 54u, 134u, 3u,
- 70u, 228u, 143u, 99u,
- 129u, 171u, 144u, 135u,
- 133u, 113u, 153u, 213u,
- 49u, 88u, 123u, 255u,
- 69u, 117u, 181u, 246u,
- 119u, 119u, 229u, 117u,
- 179u, 46u, 156u, 255u,
- 35u, 112u, 179u, 239u,
- 144u, 87u, 0u, 192u,
- 128u, 145u, 194u, 107u,
- 162u, 106u, 167u, 216u,
- 127u, 17u, 12u, 94u,
- 110u, 108u, 54u, 128u,
- 115u, 133u, 205u, 255u,
- 155u, 182u, 153u, 153u,
- 121u, 156u, 76u, 251u,
- 151u, 54u, 167u, 85u,
- 182u, 95u, 185u, 142u,
- 123u, 86u, 92u, 79u,
- 134u, 223u, 162u, 1u,
- 125u, 144u, 29u, 221u,
- 1u, 22u, 129u, 90u,
- 123u, 112u, 129u, 36u,
- 16u, 231u, 190u, 89u,
- 70u, 107u, 129u, 158u,
- 96u, 118u, 68u, 83u,
- 73u, 225u, 21u, 29u,
- 201u, 125u, 122u, 0u,
- 100u, 132u, 1u, 185u,
- 100u, 114u, 151u, 155u,
- 124u, 111u, 120u, 84u,
- 96u, 83u, 203u, 163u,
- 131u, 185u, 168u, 145u,
- 86u, 149u, 255u, 116u,
- 148u, 4u, 106u, 151u,
- 129u, 137u, 145u, 164u,
- 179u, 92u, 255u, 161u,
- 87u, 36u, 157u, 55u,
- 124u, 127u, 80u, 86u,
- 1u, 126u, 91u, 99u,
- 194u, 125u, 71u, 20u,
- 0u, 175u, 121u, 242u,
- 146u, 21u, 140u, 137u,
- 84u, 36u, 80u, 108u,
- 179u, 30u, 227u, 196u,
- 62u, 123u, 63u, 144u,
- 224u, 112u, 49u, 76u,
- 168u, 1u, 252u, 187u,
- 233u, 104u, 38u, 87u,
- 182u, 67u, 126u, 189u,
- 58u, 78u, 175u, 82u,
- 255u, 92u, 224u, 156u,
- 134u, 113u, 99u, 178u,
- 143u, 1u, 113u, 162u,
- 82u, 192u, 142u, 145u,
- 63u, 83u, 91u, 137u,
- 62u, 255u, 210u, 89u,
- 91u, 158u, 125u, 128u,
- 32u, 223u, 234u, 176u,
- 200u, 167u, 111u, 155u,
- 133u, 116u, 255u, 98u,
- 42u, 120u, 145u, 110u,
- 103u, 161u, 229u, 130u,
- 100u, 18u, 123u, 233u,
- 162u, 143u, 255u, 118u,
- 165u, 83u, 145u, 93u,
- 155u, 179u, 54u, 160u,
- 162u, 155u, 128u, 194u,
- 176u, 108u, 147u, 17u,
- 217u, 229u, 99u, 165u,
- 56u, 219u, 130u, 190u,
- 255u, 107u, 74u, 154u,
- 9u, 160u, 161u, 94u,
- 237u, 173u, 137u, 206u,
- 13u, 135u, 21u, 62u,
- 255u, 88u, 223u, 224u,
- 99u, 115u, 52u, 255u,
- 189u, 102u, 81u, 90u,
- 134u, 82u, 166u, 181u,
- 165u, 115u, 112u, 180u,
- 141u, 163u, 220u, 168u,
- 170u, 128u, 218u, 1u,
- 163u, 0u, 117u, 149u,
- 186u, 192u, 100u, 100u,
- 72u, 154u, 113u, 255u,
- 82u, 146u, 171u, 185u,
- 132u, 17u, 110u, 87u,
- 67u, 151u, 95u, 55u,
- 214u, 181u, 1u, 136u,
- 125u, 227u, 123u, 144u,
- 95u, 162u, 63u, 162u,
- 128u, 218u, 78u, 156u,
- 106u, 158u, 226u, 85u,
- 255u, 63u, 112u, 90u,
- 129u, 108u, 151u, 53u,
- 98u, 160u, 233u, 115u,
- 118u, 166u, 69u, 255u,
- 96u, 85u, 107u, 139u,
- 52u, 174u, 173u, 9u,
- 137u, 153u, 151u, 42u,
- 116u, 214u, 103u, 1u,
- 78u, 124u, 8u, 170u,
- 185u, 102u, 206u, 111u,
- 73u, 32u, 158u, 156u,
- 222u, 255u, 245u, 4u,
- 200u, 69u, 34u, 16u,
- 74u, 131u, 177u, 214u,
- 109u, 195u, 106u, 229u,
- 153u, 255u, 43u, 87u,
- 215u, 200u, 32u, 171u,
- 160u, 153u, 49u, 130u,
- 107u, 88u, 16u, 135u,
- 128u, 141u, 118u, 180u,
- 117u, 165u, 133u, 1u,
- 155u, 160u, 132u, 183u,
- 202u, 165u, 104u, 90u,
- 106u, 129u, 121u, 146u,
- 136u, 165u, 177u, 98u,
- 1u, 58u, 77u, 144u,
- 166u, 235u, 126u, 196u,
- 91u, 96u, 140u, 202u,
- 57u, 59u, 185u, 70u,
- 70u, 255u, 103u, 123u,
- 150u, 98u, 162u, 146u,
- 134u, 110u, 106u, 109u,
- 200u, 32u, 118u, 141u,
- 196u, 1u, 158u, 183u,
- 65u, 90u, 132u, 170u,
- 255u, 86u, 173u, 185u,
- 122u, 61u, 82u, 192u,
- 135u, 163u, 185u, 134u,
- 84u, 86u, 69u, 98u,
- 20u, 63u, 70u, 177u,
- 51u, 24u, 252u, 145u,
- 55u, 255u, 172u, 229u,
- 208u, 41u, 103u, 30u,
- 35u, 93u, 204u, 11u,
- 162u, 130u, 181u, 98u,
- 70u, 134u, 58u, 0u,
- 154u, 88u, 138u, 79u,
- 87u, 159u, 162u, 226u,
- 153u, 102u, 111u, 45u,
- 244u, 144u, 133u, 19u,
- 72u, 189u, 42u, 0u,
- 255u, 125u, 212u, 121u,
- 247u, 73u, 33u, 136u,
- 77u, 174u, 63u, 137u,
- 118u, 161u, 31u, 164u,
- 146u, 135u, 73u, 90u,
- 99u, 119u, 114u, 213u,
- 52u, 141u, 108u, 141u,
- 255u, 142u, 149u, 72u,
- 5u, 97u, 88u, 60u,
- 201u, 197u, 221u, 171u,
- 146u, 255u, 91u, 20u,
- 179u, 246u, 140u, 173u,
- 111u, 87u, 123u, 198u,
- 255u, 187u, 107u, 173u,
- 145u, 59u, 116u, 197u,
- 182u, 201u, 215u, 88u,
- 115u, 173u, 143u, 175u,
- 213u, 64u, 169u, 44u,
- 171u, 1u, 79u, 225u,
- 127u, 171u, 133u, 140u,
- 172u, 138u, 58u, 88u,
- 178u, 118u, 175u, 145u,
- 132u, 109u, 190u, 54u,
- 74u, 118u, 1u, 141u,
- 84u, 189u, 100u, 121u,
- 178u, 255u, 137u, 255u,
- 123u, 137u, 143u, 98u,
- 171u, 72u, 148u, 109u,
- 156u, 151u, 242u, 177u,
- 25u, 197u, 189u, 251u,
- 28u, 134u, 21u, 42u,
- 127u, 93u, 7u, 0u,
- 179u, 145u, 128u, 138u,
- 137u, 111u, 1u, 122u,
- 140u, 142u, 70u, 220u,
- 151u, 211u, 31u, 185u,
- 244u, 134u, 94u, 152u,
- 70u, 194u, 216u, 128u,
- 37u, 198u, 46u, 249u,
- 107u, 255u, 46u, 216u,
- 72u, 137u, 74u, 109u,
- 101u, 195u, 124u, 255u,
- 142u, 47u, 121u, 129u,
- 56u, 46u, 47u, 173u,
- 160u, 161u, 139u, 1u,
- 116u, 166u, 26u, 130u,
- 112u, 119u, 240u, 204u,
- 162u, 174u, 62u, 25u,
- 154u, 76u, 135u, 121u,
- 145u, 130u, 184u, 165u,
- 199u, 116u, 162u, 59u,
- 81u, 138u, 193u, 0u,
- 124u, 109u, 123u, 12u,
- 156u, 123u, 52u, 135u,
- 117u, 133u, 111u, 97u,
- 72u, 1u, 162u, 50u,
- 105u, 203u, 0u, 94u,
- 48u, 158u, 26u, 128u,
- 89u, 102u, 210u, 115u,
- 114u, 192u, 59u, 145u,
- 255u, 48u, 137u, 187u,
- 108u, 23u, 167u, 18u,
- 102u, 79u, 21u, 110u,
- 100u, 173u, 149u, 193u,
- 124u, 211u, 83u, 145u,
- 38u, 177u, 112u, 207u,
- 136u, 206u, 168u, 108u,
- 255u, 77u, 126u, 10u,
- 212u, 111u, 124u, 67u,
- 165u, 106u, 255u, 83u,
- 139u, 10u, 25u, 99u,
- 182u, 177u, 129u, 43u,
- 141u, 113u, 32u, 139u,
- 49u, 63u, 162u, 118u,
- 139u, 171u, 7u, 105u,
- 161u, 1u, 120u, 99u,
- 224u, 63u, 51u, 96u,
- 17u, 8u, 91u, 90u,
- 222u, 169u, 228u, 157u,
- 77u, 196u, 1u, 69u,
- 63u, 255u, 149u, 64u,
- 233u, 115u, 152u, 121u,
- 200u, 198u, 190u, 167u,
- 84u, 127u, 106u, 54u,
- 103u, 162u, 146u, 65u,
- 211u, 232u, 58u, 119u,
- 133u, 1u, 193u, 114u,
- 83u, 119u, 57u, 226u,
- 89u, 96u, 92u, 207u,
- 29u, 120u, 105u, 99u,
- 142u, 107u, 218u, 144u,
- 75u, 110u, 221u, 255u,
- 127u, 237u, 95u, 113u,
- 8u, 255u, 52u, 239u,
- 190u, 133u, 184u, 54u,
- 174u, 133u, 30u, 46u,
- 110u, 219u, 73u, 142u,
- 59u, 129u, 60u, 161u,
- 1u, 153u, 111u, 167u,
- 186u, 68u, 68u, 86u,
- 137u, 13u, 202u, 154u,
- 225u, 151u, 183u, 75u,
- 125u, 255u, 27u, 146u,
- 98u, 198u, 199u, 184u,
- 184u, 173u, 118u, 160u,
- 110u, 108u, 136u, 153u,
- 232u, 57u, 98u, 170u,
- 100u, 230u, 184u, 1u,
- 105u, 124u, 206u, 9u,
- 255u, 76u, 148u, 56u,
- 166u, 133u, 149u, 194u,
- 223u, 189u, 136u, 158u,
- 255u, 70u, 23u, 170u,
- 130u, 144u, 170u, 114u,
- 199u, 185u, 122u, 164u,
- 80u, 150u, 26u, 232u,
- 236u, 143u, 247u, 146u,
- 60u, 175u, 54u, 62u,
- 162u, 1u, 162u, 116u,
- 36u, 137u, 222u, 230u,
- 91u, 100u, 146u, 142u,
- 110u, 182u, 219u, 115u,
- 168u, 0u, 58u, 165u,
- 139u, 34u, 131u, 188u,
- 14u, 119u, 64u, 131u,
- 91u, 115u, 0u, 100u,
- 85u, 139u, 214u, 24u,
- 118u, 63u, 158u, 150u,
- 111u, 144u, 100u, 123u,
- 159u, 66u, 97u, 72u,
- 142u, 126u, 104u, 255u,
- 216u, 77u, 140u, 58u,
- 130u, 139u, 40u, 101u,
- 125u, 156u, 195u, 128u,
- 91u, 224u, 163u, 186u,
- 1u, 169u, 84u, 75u,
- 157u, 130u, 160u, 82u,
- 135u, 181u, 184u, 145u,
- 217u, 113u, 173u, 134u,
- 198u, 255u, 93u, 23u,
- 247u, 0u, 109u, 192u,
- 59u, 96u, 105u, 188u,
- 239u, 178u, 116u, 147u,
- 93u, 25u, 156u, 147u,
- 126u, 1u, 82u, 171u,
- 18u, 94u, 22u, 220u,
- 183u, 27u, 88u, 120u,
- 225u, 157u, 76u, 80u,
- 95u, 145u, 27u, 98u,
- 150u, 172u, 191u, 0u,
- 139u, 132u, 233u, 206u,
- 241u, 140u, 201u, 98u,
- 154u, 156u, 153u, 63u,
- 134u, 178u, 115u, 116u,
- 0u, 153u, 41u, 125u,
- 47u, 239u, 113u, 210u,
- 153u, 122u, 155u, 198u,
- 102u, 142u, 115u, 0u,
- 119u, 173u, 96u, 115u,
- 124u, 166u, 163u, 180u,
- 255u, 181u, 122u, 175u,
- 29u, 196u, 60u, 189u,
- 245u, 149u, 151u, 30u,
- 134u, 49u, 105u, 201u,
- 214u, 166u, 147u, 187u,
- 116u, 56u, 90u, 237u,
- 145u, 210u, 73u, 53u,
- 85u, 76u, 1u, 169u,
- 1u, 65u, 232u, 62u,
- 87u, 219u, 116u, 240u,
- 213u, 157u, 44u, 77u,
- 88u, 182u, 106u, 29u,
- 104u, 122u, 1u, 134u,
- 141u, 162u, 81u, 178u,
- 188u, 78u, 161u, 133u,
- 59u, 145u, 70u, 120u,
- 119u, 170u, 1u, 72u,
- 141u, 127u, 59u, 144u,
- 103u, 154u, 121u, 97u,
- 131u, 27u, 89u, 148u,
- 74u, 111u, 130u, 172u,
- 228u, 104u, 178u, 123u,
- 72u, 172u, 112u, 205u,
- 238u, 255u, 149u, 16u,
- 220u, 71u, 140u, 184u,
- 206u, 104u, 0u, 140u,
- 64u, 131u, 50u, 187u,
- 159u, 69u, 99u, 124u,
- 33u, 114u, 134u, 160u,
- 244u, 255u, 67u, 204u,
- 224u, 63u, 171u, 186u,
- 163u, 45u, 134u, 21u,
- 225u, 210u, 207u, 85u,
- 32u, 196u, 128u, 200u,
- 113u, 75u, 255u, 209u,
- 172u, 71u, 2u, 92u,
- 143u, 131u, 103u, 149u,
- 86u, 87u, 248u, 46u,
- 151u, 255u, 102u, 179u,
- 130u, 113u, 172u, 165u,
- 112u, 201u, 51u, 149u,
- 1u, 190u, 125u, 151u,
- 145u, 106u, 152u, 114u,
- 187u, 123u, 44u, 135u,
- 213u, 179u, 176u, 33u,
- 181u, 45u, 1u, 137u,
- 80u, 160u, 183u, 123u,
- 47u, 165u, 104u, 133u,
- 183u, 26u, 103u, 248u,
- 116u, 111u, 255u, 214u,
- 107u, 70u, 47u, 124u,
- 154u, 175u, 156u, 127u,
- 188u, 163u, 2u, 155u,
- 96u, 203u, 78u, 142u,
- 226u, 107u, 185u, 125u,
- 239u, 255u, 6u, 94u,
- 181u, 123u, 147u, 0u,
- 135u, 168u, 151u, 151u,
- 174u, 51u, 154u, 144u,
- 158u, 244u, 126u, 130u,
- 129u, 143u, 103u, 210u,
- 151u, 147u, 86u, 1u,
- 83u, 158u, 187u, 126u,
- 159u, 35u, 77u, 67u,
- 102u, 48u, 176u, 212u,
- 185u, 134u, 81u, 63u,
- 111u, 210u, 127u, 175u,
- 171u, 82u, 94u, 255u,
- 131u, 178u, 35u, 38u,
- 225u, 190u, 13u, 118u,
- 158u, 143u, 187u, 33u,
- 255u, 224u, 148u, 160u,
- 160u, 255u, 133u, 97u,
- 129u, 157u, 69u, 98u,
- 186u, 30u, 225u, 154u,
- 244u, 154u, 111u, 55u,
- 116u, 155u, 167u, 191u,
- 1u, 158u, 127u, 172u,
- 164u, 164u, 170u, 131u,
- 139u, 3u, 57u, 139u,
- 233u, 53u, 103u, 166u,
- 200u, 27u, 164u, 191u,
- 79u, 2u, 1u, 34u,
- 144u, 177u, 114u, 37u,
- 232u, 95u, 239u, 148u,
- 90u, 154u, 138u, 78u,
- 252u, 250u, 137u, 242u,
- 117u, 255u, 68u, 143u,
- 105u, 170u, 151u, 0u,
- 53u, 112u, 136u, 172u,
- 172u, 245u, 235u, 74u,
- 152u, 138u, 162u, 159u,
- 87u, 64u, 1u, 159u,
- 121u, 204u, 142u, 91u,
- 207u, 131u, 72u, 178u,
- 146u, 197u, 156u, 161u,
- 70u, 129u, 104u, 134u,
- 122u, 0u, 193u, 92u,
- 125u, 58u, 141u, 9u,
- 19u, 15u, 22u, 21u,
- 107u, 187u, 175u, 250u,
- 51u, 181u, 194u, 53u,
- 1u, 202u, 100u, 170u,
- 228u, 152u, 147u, 117u,
- 174u, 50u, 136u, 109u,
- 149u, 104u, 77u, 148u,
- 255u, 115u, 200u, 116u,
- 105u, 126u, 71u, 168u,
- 41u, 132u, 18u, 236u,
- 191u, 136u, 140u, 79u,
- 130u, 213u, 6u, 129u,
- 121u, 131u, 255u, 132u,
- 242u, 157u, 68u, 140u,
- 97u, 59u, 138u, 93u,
- 4u, 144u, 148u, 123u,
- 89u, 255u, 18u, 180u,
- 157u, 1u, 91u, 165u,
- 20u, 152u, 84u, 157u,
- 202u, 34u, 131u, 70u,
- 114u, 209u, 224u, 114u,
- 102u, 153u, 161u, 54u,
- 42u, 154u, 1u, 89u,
- 77u, 56u, 153u, 91u,
- 109u, 87u, 138u, 215u,
- 177u, 70u, 211u, 199u,
- 196u, 196u, 22u, 121u,
- 122u, 123u, 83u, 169u,
- 219u, 141u, 191u, 0u,
- 176u, 124u, 255u, 79u,
- 77u, 58u, 7u, 149u,
- 48u, 182u, 55u, 98u,
- 130u, 147u, 167u, 66u,
- 37u, 152u, 122u, 92u,
- 108u, 87u, 137u, 141u,
- 255u, 92u, 187u, 95u,
- 47u, 210u, 122u, 81u,
- 91u, 91u, 53u, 143u,
- 51u, 214u, 190u, 56u,
- 155u, 105u, 158u, 122u,
- 158u, 144u, 1u, 171u,
- 140u, 80u, 1u, 140u,
- 161u, 58u, 165u, 133u,
- 210u, 132u, 150u, 78u,
- 87u, 137u, 186u, 152u,
- 182u, 204u, 241u, 16u,
- 124u, 142u, 55u, 135u,
- 218u, 119u, 255u, 66u,
- 61u, 208u, 111u, 35u,
- 95u, 146u, 54u, 171u,
- 146u, 255u, 215u, 108u,
- 164u, 100u, 214u, 151u,
- 54u, 33u, 242u, 118u,
- 102u, 91u, 113u, 93u,
- 38u, 179u, 176u, 255u,
- 115u, 71u, 160u, 133u,
- 104u, 171u, 31u, 228u,
- 160u, 71u, 205u, 138u,
- 100u, 255u, 44u, 154u,
- 134u, 122u, 110u, 137u,
- 17u, 73u, 110u, 113u,
- 89u, 70u, 66u, 161u,
- 149u, 132u, 99u, 186u,
- 213u, 177u, 134u, 130u,
- 87u, 43u, 0u, 84u,
- 204u, 120u, 104u, 132u,
- 138u, 38u, 172u, 217u,
- 91u, 201u, 255u, 120u,
- 135u, 71u, 182u, 82u,
- 115u, 162u, 187u, 126u,
- 96u, 90u, 70u, 153u,
- 162u, 86u, 82u, 62u,
- 1u, 179u, 146u, 123u,
- 174u, 37u, 91u, 120u,
- 120u, 144u, 213u, 98u,
- 217u, 45u, 67u, 157u,
- 221u, 255u, 200u, 5u,
- 234u, 72u, 82u, 250u,
- 182u, 255u, 101u, 146u,
- 83u, 93u, 7u, 83u,
- 158u, 180u, 113u, 244u,
- 164u, 133u, 109u, 162u,
- 1u, 125u, 85u, 124u,
- 55u, 203u, 141u, 94u,
- 112u, 89u, 87u, 120u,
- 204u, 215u, 20u, 40u,
- 154u, 163u, 255u, 247u,
- 94u, 65u, 103u, 142u,
- 78u, 2u, 142u, 120u,
- 102u, 100u, 166u, 73u,
- 255u, 115u, 208u, 77u,
- 168u, 76u, 129u, 112u,
- 110u, 66u, 153u, 153u,
- 160u, 146u, 183u, 137u,
- 132u, 143u, 1u, 84u,
- 142u, 38u, 128u, 141u,
- 65u, 195u, 66u, 130u,
- 224u, 217u, 174u, 26u,
- 192u, 61u, 235u, 1u,
- 132u, 137u, 160u, 98u,
- 98u, 124u, 172u, 58u,
- 106u, 99u, 137u, 221u,
- 111u, 57u, 98u, 113u,
- 158u, 146u, 4u, 232u,
- 132u, 179u, 1u, 214u,
- 255u, 70u, 18u, 197u,
- 11u, 30u, 210u, 172u,
- 97u, 156u, 55u, 187u,
- 1u, 137u, 107u, 26u,
- 144u, 150u, 113u, 149u,
- 184u, 138u, 93u, 59u,
- 84u, 71u, 110u, 163u,
- 113u, 143u, 49u, 1u,
- 55u, 134u, 0u, 190u,
- 177u, 131u, 153u, 147u,
- 152u, 145u, 129u, 98u,
- 184u, 88u, 94u, 66u,
- 97u, 38u, 164u, 248u,
- 32u, 122u, 138u, 123u,
- 89u, 207u, 0u, 69u,
- 225u, 59u, 123u, 48u,
- 191u, 123u, 48u, 255u,
- 45u, 143u, 112u, 188u,
- 140u, 137u, 135u, 117u,
- 104u, 185u, 30u, 145u,
- 210u, 165u, 198u, 63u,
- 163u, 103u, 101u, 116u,
- 157u, 30u, 139u, 255u,
- 62u, 202u, 139u, 133u,
- 121u, 111u, 1u, 126u,
- 95u, 163u, 78u, 64u,
- 84u, 131u, 160u, 179u,
- 89u, 128u, 169u, 143u,
- 124u, 255u, 180u, 205u,
- 108u, 207u, 91u, 90u,
- 54u, 72u, 107u, 145u,
- 102u, 89u, 110u, 121u,
- 61u, 200u, 54u, 128u,
- 169u, 26u, 106u, 125u,
- 110u, 255u, 114u, 243u,
- 141u, 140u, 95u, 142u,
- 217u, 102u, 137u, 60u,
- 105u, 83u, 159u, 255u,
- 177u, 141u, 124u, 157u,
- 104u, 113u, 68u, 99u,
- 191u, 133u, 93u, 106u,
- 149u, 169u, 131u, 91u,
- 111u, 100u, 92u, 142u,
- 123u, 255u, 119u, 132u,
- 198u, 63u, 201u, 199u,
- 120u, 147u, 117u, 159u,
- 90u, 91u, 45u, 0u,
- 115u, 152u, 203u, 112u,
- 137u, 142u, 84u, 133u,
- 81u, 104u, 255u, 75u,
- 170u, 113u, 153u, 145u,
- 198u, 104u, 175u, 89u,
- 91u, 135u, 69u, 243u,
- 80u, 130u, 221u, 156u,
- 97u, 159u, 55u, 255u,
- 231u, 158u, 160u, 135u,
- 149u, 55u, 185u, 89u,
- 159u, 99u, 1u, 221u,
- 122u, 229u, 181u, 101u,
- 37u, 167u, 4u, 97u,
- 85u, 145u, 159u, 255u,
- 181u, 199u, 66u, 105u,
- 75u, 157u, 39u, 158u,
- 204u, 34u, 150u, 177u,
- 52u, 13u, 255u, 152u,
- 43u, 187u, 54u, 82u,
- 233u, 4u, 242u, 197u,
- 228u, 102u, 147u, 159u,
- 115u, 212u, 155u, 49u,
- 154u, 171u, 177u, 104u,
- 104u, 27u, 255u, 107u,
- 147u, 130u, 125u, 132u,
- 96u, 58u, 122u, 216u,
- 112u, 43u, 148u, 96u,
- 161u, 101u, 133u, 81u,
- 35u, 190u, 138u, 1u,
- 109u, 54u, 211u, 93u,
- 138u, 107u, 255u, 128u,
- 105u, 115u, 129u, 163u,
- 94u, 167u, 181u, 143u,
- 26u, 201u, 134u, 64u,
- 107u, 126u, 142u, 83u,
- 150u, 82u, 155u, 205u,
- 119u, 121u, 224u, 255u,
- 195u, 141u, 255u, 125u,
- 30u, 50u, 48u, 75u,
- 134u, 115u, 158u, 102u,
- 49u, 180u, 74u, 159u,
- 199u, 151u, 155u, 77u,
- 70u, 26u, 36u, 132u,
- 149u, 255u, 162u, 51u,
- 48u, 73u, 55u, 125u,
- 232u, 196u, 125u, 39u,
- 1u, 84u, 120u, 135u,
- 58u, 4u, 198u, 199u,
- 100u, 77u, 210u, 167u,
- 186u, 172u, 183u, 55u,
- 112u, 99u, 172u, 107u,
- 1u, 148u, 100u, 144u,
- 152u, 176u, 101u, 157u,
- 123u, 159u, 1u, 122u,
- 204u, 93u, 69u, 192u,
- 173u, 156u, 202u, 184u,
- 35u, 82u, 120u, 134u,
- 127u, 119u, 163u, 44u,
- 92u, 163u, 94u, 175u,
- 186u, 164u, 255u, 198u,
- 110u, 212u, 131u, 98u,
- 94u, 159u, 175u, 111u,
- 163u, 246u, 80u, 170u,
- 216u, 53u, 87u, 144u,
- 58u, 172u, 69u, 255u,
- 210u, 125u, 63u, 229u,
- 34u, 189u, 255u, 118u,
- 149u, 69u, 124u, 161u,
- 248u, 230u, 102u, 129u,
- 164u, 184u, 156u, 188u,
- 122u, 123u, 172u, 123u,
- 255u, 103u, 29u, 152u,
- 214u, 41u, 103u, 122u,
- 106u, 167u, 80u, 79u,
- 123u, 172u, 87u, 255u,
- 108u, 152u, 117u, 130u,
- 143u, 96u, 112u, 130u,
- 84u, 57u, 147u, 11u,
- 173u, 132u, 1u, 170u,
- 47u, 170u, 50u, 108u,
- 123u, 228u, 67u, 63u,
- 134u, 109u, 255u, 67u,
- 87u, 207u, 184u, 141u,
- 45u, 86u, 85u, 150u,
- 147u, 195u, 97u, 196u,
- 88u, 156u, 170u, 182u,
- 1u, 141u, 133u, 162u,
- 125u, 30u, 150u, 226u,
- 121u, 227u, 110u, 240u,
- 202u, 69u, 17u, 228u,
- 66u, 4u, 80u, 19u,
- 129u, 165u, 217u, 214u,
- 116u, 189u, 128u, 1u,
- 1u, 146u, 45u, 205u,
- 101u, 72u, 154u, 232u,
- 112u, 75u, 17u, 156u,
- 91u, 134u, 84u, 161u,
- 129u, 206u, 164u, 119u,
- 104u, 174u, 45u, 127u,
- 87u, 1u, 192u, 176u,
- 125u, 182u, 82u, 190u,
- 162u, 184u, 189u, 41u,
- 100u, 97u, 185u, 114u,
- 181u, 1u, 206u, 102u,
- 69u, 119u, 136u, 130u,
- 203u, 63u, 73u, 54u,
- 223u, 19u, 128u, 222u,
- 34u, 241u, 165u, 116u,
- 82u, 201u, 144u, 1u,
- 60u, 124u, 91u, 18u,
- 126u, 94u, 169u, 171u,
- 209u, 163u, 160u, 255u,
- 137u, 127u, 134u, 74u,
- 71u, 157u, 115u, 93u,
- 187u, 98u, 1u, 187u,
- 113u, 40u, 102u, 151u,
- 72u, 21u, 41u, 161u,
- 178u, 152u, 160u, 255u,
- 84u, 132u, 145u, 125u,
- 138u, 130u, 87u, 170u,
- 115u, 83u, 135u, 117u,
- 197u, 107u, 148u, 181u,
- 1u, 113u, 126u, 91u,
- 168u, 176u, 116u, 147u,
- 126u, 108u, 194u, 130u,
- 0u, 187u, 254u, 88u,
- 196u, 123u, 45u, 67u,
- 197u, 39u, 145u, 123u,
- 92u, 160u, 70u, 84u,
- 128u, 125u, 1u, 126u,
- 76u, 29u, 131u, 186u,
- 21u, 56u, 23u, 117u,
- 78u, 188u, 124u, 95u,
- 51u, 51u, 140u, 97u,
- 137u, 104u, 160u, 116u,
- 159u, 14u, 255u, 69u,
- 142u, 137u, 86u, 146u,
- 105u, 88u, 0u, 99u,
- 197u, 188u, 63u, 106u,
- 169u, 183u, 58u, 67u,
- 19u, 155u, 73u, 222u,
- 172u, 155u, 1u, 207u,
- 135u, 143u, 87u, 97u,
- 103u, 186u, 29u, 111u,
- 138u, 137u, 109u, 96u,
- 73u, 130u, 174u, 132u,
- 140u, 254u, 86u, 102u,
- 90u, 50u, 140u, 141u,
- 255u, 121u, 153u, 157u,
- 223u, 211u, 172u, 99u,
- 150u, 56u, 117u, 73u,
- 166u, 148u, 137u, 178u,
- 75u, 255u, 83u, 59u,
- 94u, 171u, 159u, 110u,
- 113u, 141u, 46u, 238u,
- 11u, 213u, 119u, 47u,
- 200u, 1u, 150u, 199u,
- 123u, 54u, 160u, 74u,
- 255u, 106u, 136u, 99u,
- 140u, 203u, 130u, 217u,
- 241u, 192u, 162u, 94u,
- 1u, 155u, 189u, 126u,
- 102u, 78u, 202u, 174u,
- 203u, 67u, 128u, 108u,
- 83u, 41u, 107u, 63u,
- 84u, 49u, 89u, 169u,
- 168u, 135u, 96u, 174u,
- 78u, 204u, 1u, 104u,
- 205u, 88u, 92u, 164u,
- 180u, 178u, 118u, 104u,
- 255u, 90u, 145u, 135u,
- 80u, 95u, 143u, 131u,
- 113u, 248u, 148u, 106u,
- 55u, 57u, 72u, 174u,
- 190u, 234u, 127u, 148u,
- 139u, 62u, 90u, 117u,
- 116u, 182u, 191u, 255u,
- 191u, 206u, 111u, 173u,
- 145u, 204u, 168u, 118u,
- 84u, 145u, 140u, 211u,
- 85u, 133u, 1u, 148u,
- 97u, 95u, 186u, 102u,
- 64u, 153u, 255u, 110u,
- 30u, 225u, 55u, 122u,
- 132u, 72u, 190u, 200u,
- 218u, 141u, 74u, 206u,
- 76u, 148u, 70u, 255u,
- 187u, 137u, 140u, 77u,
- 97u, 138u, 34u, 127u,
- 119u, 131u, 211u, 84u,
- 166u, 255u, 210u, 183u,
- 134u, 91u, 166u, 195u,
- 129u, 146u, 107u, 69u,
- 107u, 1u, 90u, 134u,
- 149u, 63u, 245u, 87u,
- 104u, 120u, 7u, 66u,
- 49u, 198u, 125u, 108u,
- 115u, 180u, 130u, 151u,
- 0u, 153u, 233u, 113u,
- 133u, 69u, 143u, 65u,
- 189u, 133u, 212u, 107u,
- 9u, 170u, 255u, 120u,
- 107u, 151u, 71u, 34u,
- 19u, 34u, 132u, 159u,
- 190u, 166u, 115u, 172u,
- 37u, 58u, 198u, 187u,
- 91u, 96u, 105u, 37u,
- 1u, 41u, 40u, 29u,
- 60u, 154u, 156u, 177u,
- 91u, 159u, 136u, 151u,
- 154u, 95u, 255u, 148u,
- 83u, 173u, 138u, 206u,
- 217u, 138u, 65u, 69u,
- 191u, 76u, 222u, 106u,
- 100u, 236u, 139u, 78u,
- 97u, 97u, 255u, 247u,
- 210u, 212u, 127u, 93u,
- 1u, 147u, 161u, 100u,
- 209u, 143u, 150u, 56u,
- 98u, 124u, 102u, 72u,
- 164u, 126u, 252u, 119u,
- 43u, 206u, 226u, 160u,
- 134u, 172u, 73u, 52u,
- 100u, 142u, 164u, 255u,
- 90u, 160u, 5u, 255u,
- 1u, 168u, 132u, 96u,
- 151u, 189u, 74u, 131u,
- 86u, 102u, 108u, 106u,
- 102u, 111u, 150u, 193u,
- 157u, 64u, 71u, 90u,
- 165u, 177u, 211u, 213u,
- 65u, 116u, 1u, 97u,
- 119u, 144u, 86u, 79u,
- 54u, 82u, 46u, 255u,
- 116u, 67u, 183u, 127u,
- 99u, 132u, 56u, 88u,
- 171u, 34u, 182u, 147u,
- 174u, 95u, 110u, 106u,
- 7u, 21u, 109u, 78u,
- 113u, 169u, 122u, 60u,
- 1u, 65u, 131u, 127u,
- 96u, 13u, 48u, 255u,
- 127u, 80u, 191u, 81u,
- 185u, 132u, 46u, 213u,
- 44u, 77u, 69u, 142u,
- 158u, 208u, 35u, 255u,
- 58u, 172u, 119u, 156u,
- 82u, 86u, 89u, 171u,
- 133u, 70u, 53u, 175u,
- 146u, 67u, 165u, 121u,
- 172u, 137u, 181u, 223u,
- 139u, 84u, 102u, 1u,
- 124u, 144u, 116u, 70u,
- 184u, 35u, 221u, 201u,
- 156u, 97u, 1u, 126u,
- 29u, 101u, 36u, 171u,
- 93u, 1u, 77u, 168u,
- 147u, 161u, 80u, 92u,
- 127u, 150u, 70u, 150u,
- 109u, 130u, 255u, 223u,
- 151u, 148u, 170u, 84u,
- 255u, 186u, 168u, 190u,
- 165u, 24u, 53u, 185u,
- 191u, 245u, 140u, 245u,
- 87u, 184u, 194u, 199u,
- 111u, 172u, 80u, 184u,
- 5u, 192u, 191u, 198u,
- 117u, 255u, 115u, 123u,
- 133u, 106u, 33u, 237u,
- 152u, 174u, 107u, 195u,
- 150u, 255u, 14u, 34u,
- 138u, 60u, 109u, 135u,
- 118u, 120u, 231u, 117u,
- 84u, 173u, 63u, 43u,
- 140u, 200u, 122u, 0u,
- 160u, 184u, 139u, 67u,
- 176u, 177u, 57u, 83u,
- 164u, 101u, 224u, 180u,
- 176u, 103u, 255u, 29u,
- 112u, 160u, 30u, 132u,
- 209u, 241u, 115u, 107u,
- 175u, 82u, 202u, 194u,
- 91u, 179u, 190u, 112u,
- 186u, 116u, 1u, 91u,
- 158u, 141u, 95u, 147u,
- 179u, 85u, 72u, 255u,
- 76u, 209u, 104u, 65u,
- 130u, 107u, 70u, 152u,
- 185u, 204u, 12u, 163u,
- 223u, 142u, 165u, 220u,
- 172u, 97u, 127u, 85u,
- 170u, 104u, 59u, 160u,
- 211u, 227u, 143u, 1u,
- 86u, 91u, 72u, 162u,
- 133u, 146u, 126u, 18u,
- 97u, 158u, 106u, 31u,
- 47u, 255u, 173u, 140u,
- 86u, 92u, 16u, 108u,
- 73u, 111u, 195u, 184u,
- 148u, 255u, 91u, 157u,
- 68u, 109u, 148u, 167u,
- 132u, 165u, 179u, 149u,
- 68u, 90u, 142u, 144u,
- 136u, 154u, 163u, 126u,
- 255u, 104u, 127u, 55u,
- 117u, 164u, 123u, 118u,
- 166u, 101u, 160u, 12u,
- 51u, 106u, 145u, 135u,
- 124u, 121u, 255u, 166u,
- 44u, 155u, 154u, 52u,
- 255u, 182u, 164u, 116u,
- 59u, 97u, 70u, 122u,
- 39u, 132u, 151u, 128u,
- 75u, 126u, 164u, 147u,
- 209u, 144u, 120u, 48u,
- 141u, 217u, 143u, 158u,
- 91u, 109u, 114u, 255u,
- 72u, 126u, 96u, 97u,
- 130u, 185u, 167u, 67u,
- 41u, 129u, 126u, 115u,
- 255u, 92u, 113u, 163u,
- 53u, 147u, 9u, 80u,
- 16u, 102u, 211u, 224u,
- 172u, 157u, 255u, 219u,
- 106u, 46u, 101u, 120u,
- 178u, 152u, 184u, 212u,
- 19u, 255u, 236u, 120u,
- 220u, 197u, 124u, 179u,
- 124u, 213u, 225u, 109u,
- 69u, 176u, 45u, 98u,
- 177u, 255u, 26u, 138u,
- 190u, 137u, 146u, 110u,
- 118u, 130u, 121u, 97u,
- 51u, 167u, 50u, 0u,
- 65u, 115u, 88u, 116u,
- 148u, 146u, 212u, 123u,
- 149u, 133u, 191u, 168u,
- 84u, 136u, 235u, 141u,
- 32u, 150u, 151u, 49u,
- 255u, 129u, 157u, 194u,
- 60u, 197u, 140u, 196u,
- 167u, 233u, 151u, 160u,
- 63u, 214u, 166u, 116u,
- 132u, 22u, 173u, 255u,
- 114u, 126u, 203u, 121u,
- 140u, 139u, 1u, 146u,
- 108u, 184u, 149u, 199u,
- 183u, 121u, 172u, 188u,
- 118u, 173u, 120u, 110u,
- 135u, 68u, 31u, 151u,
- 124u, 111u, 190u, 161u,
- 194u, 207u, 39u, 55u,
- 1u, 221u, 65u, 49u,
- 212u, 135u, 152u, 141u,
- 120u, 115u, 149u, 151u,
- 110u, 0u, 139u, 219u,
- 74u, 234u, 232u, 162u,
- 61u, 148u, 193u, 15u,
- 153u, 201u, 233u, 165u,
- 74u, 255u, 83u, 159u,
- 179u, 99u, 54u, 110u,
- 149u, 255u, 194u, 113u,
- 128u, 135u, 66u, 190u,
- 165u, 153u, 150u, 128u,
- 130u, 137u, 78u, 131u,
- 141u, 195u, 51u, 84u,
- 196u, 255u, 50u, 124u,
- 168u, 213u, 132u, 155u,
- 145u, 158u, 26u, 85u,
- 166u, 209u, 212u, 91u,
- 175u, 84u, 154u, 30u,
- 138u, 25u, 255u, 118u,
- 147u, 254u, 248u, 213u,
- 152u, 144u, 68u, 180u,
- 170u, 174u, 103u, 188u,
- 170u, 180u, 156u, 85u,
- 9u, 21u, 0u, 87u,
- 180u, 190u, 93u, 239u,
- 208u, 255u, 102u, 144u,
- 12u, 96u, 44u, 119u,
- 197u, 150u, 125u, 90u,
- 90u, 191u, 117u, 112u,
- 0u, 142u, 92u, 140u,
- 129u, 232u, 132u, 189u,
- 14u, 159u, 92u, 211u,
- 88u, 119u, 176u, 129u,
- 241u, 119u, 42u, 0u,
- 100u, 115u, 94u, 144u,
- 182u, 75u, 120u, 201u,
- 106u, 148u, 218u, 141u,
- 239u, 83u, 181u, 94u,
- 100u, 162u, 1u, 50u,
- 87u, 89u, 218u, 184u,
- 98u, 225u, 75u, 178u,
- 1u, 129u, 80u, 187u,
- 92u, 150u, 237u, 117u,
- 147u, 68u, 94u, 159u,
- 77u, 68u, 245u, 114u,
- 84u, 153u, 150u, 201u,
- 1u, 25u, 42u, 23u,
- 62u, 103u, 126u, 202u,
- 33u, 136u, 126u, 73u,
- 227u, 90u, 119u, 115u,
- 230u, 32u, 148u, 224u,
- 82u, 255u, 80u, 60u,
- 190u, 78u, 170u, 138u,
- 156u, 115u, 255u, 60u,
- 225u, 182u, 27u, 102u,
- 85u, 117u, 80u, 92u,
- 1u, 160u, 30u, 159u,
- 168u, 56u, 92u, 42u,
- 54u, 122u, 145u, 98u,
- 75u, 72u, 157u, 168u,
- 255u, 140u, 136u, 214u,
- 17u, 67u, 102u, 49u,
- 176u, 251u, 42u, 38u,
- 146u, 76u, 69u, 83u,
- 176u, 73u, 90u, 186u,
- 144u, 171u, 74u, 131u,
- 255u, 131u, 125u, 121u,
- 129u, 80u, 95u, 153u,
- 170u, 255u, 109u, 94u,
- 84u, 85u, 152u, 161u,
- 96u, 233u, 214u, 155u,
- 170u, 149u, 122u, 108u,
- 122u, 156u, 160u, 26u,
- 157u, 207u, 93u, 255u,
- 71u, 189u, 197u, 182u,
- 115u, 124u, 141u, 225u,
- 68u, 100u, 223u, 60u,
- 142u, 91u, 51u, 84u,
- 75u, 108u, 107u, 1u,
- 86u, 216u, 109u, 108u,
- 196u, 74u, 195u, 58u,
- 118u, 76u, 1u, 155u,
- 148u, 157u, 201u, 31u,
- 92u, 89u, 181u, 88u,
- 106u, 226u, 79u, 44u,
- 40u, 135u, 255u, 99u,
- 51u, 124u, 120u, 120u,
- 136u, 118u, 149u, 133u,
- 209u, 24u, 72u, 81u,
- 11u, 120u, 115u, 255u,
- 99u, 112u, 67u, 34u,
- 79u, 32u, 218u, 78u,
- 252u, 71u, 117u, 156u,
- 99u, 31u, 63u, 111u,
- 239u, 158u, 104u, 93u,
- 42u, 103u, 255u, 196u,
- 39u, 201u, 118u, 112u,
- 137u, 0u, 126u, 24u,
- 155u, 10u, 235u, 205u,
- 63u, 97u, 97u, 57u,
- 163u, 166u, 205u, 61u,
- 122u, 80u, 173u, 0u,
- 98u, 49u, 119u, 187u,
- 141u, 194u, 180u, 143u,
- 1u, 77u, 138u, 55u,
- 113u, 184u, 164u, 199u,
- 143u, 203u, 148u, 119u,
- 139u, 179u, 79u, 182u,
- 88u, 145u, 121u, 145u,
- 37u, 156u, 163u, 173u,
- 106u, 135u, 172u, 98u,
- 127u, 255u, 126u, 155u,
- 156u, 105u, 63u, 108u,
- 149u, 65u, 255u, 205u,
- 136u, 115u, 112u, 170u,
- 193u, 118u, 91u, 51u,
- 97u, 72u, 94u, 197u,
- 132u, 169u, 165u, 200u,
- 137u, 1u, 145u, 80u,
- 127u, 84u, 159u, 104u,
- 115u, 76u, 123u, 82u,
- 132u, 133u, 255u, 234u,
- 189u, 96u, 140u, 217u,
- 124u, 124u, 203u, 122u,
- 77u, 149u, 71u, 153u,
- 101u, 93u, 1u, 215u,
- 139u, 112u, 130u, 172u,
- 17u, 41u, 137u, 220u,
- 100u, 167u, 178u, 150u,
- 255u, 223u, 116u, 126u,
- 77u, 48u, 63u, 137u,
- 104u, 124u, 7u, 135u,
- 255u, 193u, 130u, 167u,
- 86u, 159u, 186u, 127u,
- 41u, 173u, 109u, 128u,
- 207u, 181u, 131u, 159u,
- 107u, 144u, 141u, 101u,
- 101u, 139u, 81u, 162u,
- 168u, 1u, 134u, 105u,
- 38u, 174u, 95u, 75u,
- 102u, 148u, 152u, 131u,
- 162u, 156u, 100u, 111u,
- 183u, 0u, 86u, 68u,
- 86u, 134u, 182u, 117u,
- 134u, 123u, 68u, 151u,
- 1u, 73u, 124u, 39u,
- 201u, 134u, 114u, 161u,
- 71u, 192u, 108u, 141u,
- 222u, 99u, 108u, 122u,
- 209u, 105u, 209u, 232u,
- 98u, 83u, 69u, 72u,
- 61u, 22u, 255u, 160u,
- 120u, 131u, 154u, 179u,
- 239u, 255u, 246u, 114u,
- 43u, 100u, 43u, 134u,
- 134u, 208u, 98u, 151u,
- 154u, 162u, 171u, 61u,
- 59u, 114u, 153u, 83u,
- 173u, 144u, 255u, 188u,
- 144u, 169u, 149u, 25u,
- 252u, 129u, 106u, 155u,
- 126u, 126u, 0u, 181u,
- 54u, 154u, 144u, 69u,
- 69u, 40u, 129u, 185u,
- 157u, 125u, 138u, 92u,
- 124u, 209u, 255u, 132u,
- 114u, 254u, 10u, 146u,
- 150u, 36u, 76u, 94u,
- 1u, 100u, 20u, 195u,
- 139u, 228u, 70u, 244u,
- 208u, 6u, 152u, 117u,
- 15u, 47u, 212u, 194u,
- 210u, 152u, 157u, 137u,
- 100u, 146u, 139u, 180u,
- 160u, 0u, 90u, 137u,
- 173u, 173u, 77u, 126u,
- 59u, 69u, 173u, 61u,
- 179u, 207u, 105u, 85u,
- 255u, 237u, 70u, 129u,
- 92u, 161u, 152u, 107u,
- 28u, 124u, 12u, 103u,
- 93u, 189u, 210u, 184u,
- 81u, 190u, 142u, 69u,
- 129u, 1u, 186u, 165u,
- 176u, 97u, 105u, 255u,
- 142u, 99u, 96u, 66u,
- 112u, 89u, 82u, 146u,
- 102u, 138u, 87u, 162u,
- 170u, 255u, 143u, 76u,
- 187u, 233u, 243u, 198u,
- 32u, 45u, 20u, 199u,
- 83u, 25u, 210u, 242u,
- 152u, 148u, 6u, 38u,
- 10u, 174u, 80u, 229u,
- 93u, 47u, 238u, 123u,
- 145u, 160u, 196u, 255u,
- 213u, 180u, 116u, 113u,
- 83u, 212u, 167u, 150u,
- 73u, 126u, 37u, 227u,
- 86u, 175u, 52u, 1u,
- 247u, 221u, 148u, 1u,
- 23u, 23u, 145u, 166u,
- 76u, 78u, 134u, 138u,
- 36u, 219u, 241u, 95u,
- 220u, 40u, 76u, 151u,
- 0u, 144u, 41u, 116u,
- 118u, 152u, 135u, 75u,
- 14u, 127u, 42u, 159u,
- 130u, 180u, 1u, 11u,
- 165u, 101u, 121u, 241u,
- 72u, 144u, 217u, 132u,
- 159u, 175u, 150u, 224u,
- 1u, 72u, 119u, 202u,
- 48u, 163u, 134u, 149u,
- 137u, 194u, 78u, 112u,
- 173u, 94u, 131u, 63u,
- 144u, 169u, 255u, 53u,
- 25u, 173u, 170u, 69u,
- 108u, 34u, 92u, 146u,
- 150u, 160u, 140u, 147u,
- 146u, 140u, 108u, 50u,
- 68u, 77u, 255u, 139u,
- 133u, 159u, 164u, 122u,
- 144u, 124u, 108u, 93u,
- 92u, 34u, 153u, 119u,
- 137u, 99u, 255u, 83u,
- 211u, 199u, 113u, 129u,
- 132u, 22u, 12u, 15u,
- 104u, 76u, 152u, 1u,
- 192u, 109u, 150u, 181u,
- 128u, 129u, 156u, 150u,
- 142u, 46u, 130u, 108u,
- 162u, 103u, 1u, 213u,
- 144u, 96u, 96u, 94u,
- 111u, 45u, 123u, 68u,
- 110u, 128u, 116u, 77u,
- 85u, 142u, 1u, 150u,
- 130u, 59u, 160u, 88u,
- 205u, 127u, 185u, 193u,
- 81u, 30u, 57u, 109u,
- 255u, 126u, 82u, 173u,
- 151u, 144u, 73u, 80u,
- 61u, 71u, 82u, 154u,
- 186u, 116u, 165u, 116u,
- 134u, 74u, 144u, 221u,
- 71u, 129u, 201u, 164u,
- 119u, 214u, 87u, 255u,
- 177u, 74u, 130u, 80u,
- 60u, 119u, 103u, 132u,
- 105u, 175u, 95u, 41u,
- 117u, 223u, 94u, 255u,
- 114u, 25u, 55u, 170u,
- 191u, 53u, 58u, 255u,
- 108u, 139u, 182u, 24u,
- 63u, 66u, 3u, 29u,
- 102u, 197u, 173u, 63u,
- 36u, 182u, 194u, 107u,
- 240u, 102u, 178u, 114u,
- 30u, 245u, 145u, 255u,
- 143u, 103u, 47u, 152u,
- 113u, 127u, 150u, 1u,
- 169u, 160u, 155u, 227u,
- 173u, 136u, 220u, 142u,
- 106u, 243u, 115u, 85u,
- 122u, 129u, 39u, 98u,
- 1u, 76u, 96u, 35u,
- 42u, 237u, 165u, 79u,
- 70u, 216u, 210u, 172u,
- 172u, 1u, 92u, 254u,
- 100u, 228u, 111u, 166u,
- 137u, 138u, 55u, 25u,
- 65u, 118u, 92u, 222u,
- 123u, 42u, 165u, 99u,
- 50u, 150u, 80u, 103u,
- 131u, 180u, 36u, 1u,
- 98u, 111u, 200u, 183u,
- 218u, 79u, 120u, 138u,
- 35u, 110u, 1u, 165u,
- 66u, 146u, 157u, 42u,
- 60u, 84u, 69u, 108u,
- 181u, 148u, 208u, 118u,
- 255u, 187u, 108u, 109u,
- 157u, 94u, 107u, 137u,
- 116u, 167u, 147u, 115u,
- 90u, 72u, 162u, 111u,
- 255u, 104u, 111u, 14u,
- 182u, 209u, 105u, 161u,
- 246u, 53u, 177u, 129u,
- 181u, 50u, 128u, 192u,
- 160u, 170u, 21u, 1u,
- 166u, 98u, 62u, 134u,
- 76u, 159u, 133u, 144u,
- 130u, 133u, 105u, 11u,
- 239u, 154u, 78u, 151u,
- 144u, 170u, 214u, 111u,
- 161u, 182u, 255u, 124u,
- 114u, 27u, 193u, 53u,
- 173u, 170u, 156u, 206u,
- 75u, 167u, 97u, 122u,
- 101u, 59u, 1u, 138u
-};
-
-const float16 LangIdNNParams::kEmbeddingsQuantScales2[] = {
- 15326u, 14732u, 15691u, 15376u,
- 15247u, 15495u, 15073u, 15315u,
- 15133u, 15123u, 15689u, 15563u
-};
-
-const uint8 LangIdNNParams::kEmbeddingsWeights2[] = {
- 86u, 205u, 131u, 1u,
- 133u, 159u, 159u, 17u,
- 0u, 223u, 83u, 110u,
- 158u, 191u, 203u, 63u,
- 255u, 60u, 160u, 192u,
- 92u, 63u, 31u, 162u,
- 175u, 4u, 191u, 1u,
- 174u, 89u, 174u, 242u,
- 16u, 248u, 108u, 69u,
- 112u, 134u, 179u, 1u,
- 140u, 108u, 128u, 155u,
- 203u, 137u, 112u, 1u,
- 1u, 244u, 86u, 136u,
- 105u, 176u, 186u, 123u,
- 107u, 101u, 139u, 122u,
- 255u, 79u, 170u, 117u,
- 151u, 161u, 111u, 255u,
- 192u, 78u, 79u, 16u,
- 75u, 122u, 75u, 80u,
- 7u, 83u, 82u, 0u,
- 20u, 255u, 70u, 190u,
- 123u, 186u, 149u, 25u,
- 35u, 255u, 35u, 181u,
- 136u, 190u, 152u, 23u
-};
-
-const float16 LangIdNNParams::kEmbeddingsQuantScales3[] = {
- 15326u, 14533u, 15603u, 15265u,
- 15642u, 15510u, 15463u, 15291u,
- 15305u, 15116u, 15569u, 15640u,
- 15626u, 15259u, 15567u, 15633u,
- 15628u, 15614u, 15599u, 15599u,
- 15566u, 15260u, 15637u, 15629u,
- 15539u, 15632u, 15235u, 15275u,
- 15343u, 15218u, 15574u, 15282u,
- 15207u, 15297u, 15356u, 15232u,
- 15334u, 15260u, 15309u, 15238u,
- 15203u, 15293u, 15251u, 15311u,
- 15240u, 15236u, 15259u, 15266u,
- 15162u, 15302u, 15194u, 15271u,
- 15263u, 15171u, 15240u, 15296u,
- 15370u, 15205u, 15288u, 15259u,
- 15262u, 15347u, 15296u, 15357u,
- 15190u, 15259u, 15302u, 15282u,
- 15240u, 15285u, 15254u, 15264u,
- 15267u, 15342u, 15222u, 15267u,
- 15322u, 15353u, 15235u, 15252u,
- 15243u, 15222u, 15268u, 15232u,
- 15233u, 15201u, 15293u, 15140u,
- 15241u, 15299u, 15305u, 15338u,
- 15257u, 15202u, 15274u, 15284u,
- 15175u, 15239u, 15215u, 15233u,
- 15341u, 15230u, 15648u
-};
-
-const uint8 LangIdNNParams::kEmbeddingsWeights3[] = {
- 86u, 205u, 131u, 1u,
- 133u, 159u, 159u, 17u,
- 255u, 66u, 64u, 129u,
- 65u, 15u, 161u, 199u,
- 189u, 189u, 81u, 255u,
- 55u, 138u, 90u, 110u,
- 136u, 76u, 183u, 70u,
- 185u, 1u, 171u, 183u,
- 154u, 255u, 88u, 170u,
- 67u, 36u, 218u, 99u,
- 255u, 190u, 89u, 205u,
- 91u, 51u, 176u, 15u,
- 142u, 112u, 46u, 141u,
- 12u, 74u, 171u, 255u,
- 142u, 110u, 145u, 236u,
- 185u, 0u, 109u, 203u,
- 168u, 67u, 129u, 66u,
- 117u, 1u, 233u, 200u,
- 51u, 32u, 100u, 175u,
- 150u, 192u, 107u, 0u,
- 1u, 153u, 153u, 7u,
- 136u, 59u, 212u, 204u,
- 255u, 151u, 60u, 115u,
- 93u, 95u, 126u, 157u,
- 85u, 131u, 38u, 255u,
- 135u, 153u, 61u, 176u,
- 94u, 123u, 179u, 118u,
- 217u, 213u, 1u, 29u,
- 156u, 182u, 34u, 255u,
- 24u, 154u, 112u, 218u,
- 169u, 154u, 167u, 112u,
- 108u, 116u, 164u, 255u,
- 184u, 159u, 144u, 255u,
- 172u, 82u, 130u, 165u,
- 88u, 72u, 103u, 150u,
- 179u, 205u, 58u, 255u,
- 1u, 117u, 108u, 175u,
- 91u, 113u, 161u, 238u,
- 56u, 1u, 159u, 39u,
- 83u, 161u, 145u, 236u,
- 175u, 1u, 73u, 224u,
- 129u, 32u, 121u, 249u,
- 94u, 31u, 1u, 42u,
- 21u, 124u, 154u, 208u,
- 128u, 142u, 209u, 1u,
- 159u, 163u, 139u, 141u,
- 188u, 161u, 137u, 68u,
- 152u, 0u, 209u, 151u,
- 101u, 255u, 124u, 141u,
- 59u, 79u, 175u, 145u,
- 255u, 67u, 103u, 132u,
- 171u, 164u, 110u, 191u,
- 123u, 77u, 153u, 77u,
- 190u, 120u, 255u, 77u,
- 77u, 92u, 135u, 132u,
- 255u, 218u, 174u, 189u,
- 156u, 135u, 1u, 54u,
- 172u, 78u, 89u, 140u,
- 125u, 116u, 93u, 175u,
- 36u, 238u, 62u, 1u,
- 253u, 77u, 203u, 22u,
- 135u, 91u, 175u, 255u,
- 181u, 148u, 255u, 124u,
- 112u, 163u, 155u, 200u,
- 31u, 58u, 111u, 155u,
- 255u, 240u, 145u, 155u,
- 116u, 1u, 113u, 193u,
- 153u, 255u, 132u, 201u,
- 146u, 1u, 158u, 105u,
- 123u, 146u, 106u, 113u,
- 46u, 132u, 205u, 226u,
- 68u, 99u, 148u, 255u,
- 109u, 110u, 64u, 26u,
- 44u, 157u, 255u, 111u,
- 113u, 255u, 121u, 153u,
- 73u, 116u, 11u, 56u,
- 201u, 255u, 149u, 202u,
- 171u, 190u, 123u, 186u,
- 1u, 5u, 212u, 31u,
- 13u, 150u, 252u, 187u,
- 74u, 255u, 145u, 173u,
- 162u, 69u, 19u, 145u,
- 134u, 153u, 245u, 242u,
- 4u, 243u, 81u, 1u,
- 220u, 1u, 161u, 3u,
- 124u, 138u, 73u, 77u,
- 1u, 213u, 83u, 172u,
- 131u, 64u, 138u, 93u,
- 121u, 8u, 244u, 0u,
- 57u, 123u, 109u, 0u,
- 158u, 117u, 115u, 135u,
- 255u, 21u, 123u, 190u,
- 183u, 197u, 24u, 114u,
- 224u, 53u, 116u, 1u,
- 104u, 107u, 64u, 159u,
- 109u, 184u, 116u, 255u,
- 98u, 89u, 130u, 15u,
- 18u, 255u, 219u, 4u,
- 201u, 10u, 1u, 177u,
- 56u, 103u, 127u, 97u,
- 106u, 48u, 143u, 255u,
- 68u, 29u, 137u, 44u,
- 164u, 255u, 170u, 134u,
- 132u, 226u, 234u, 143u,
- 48u, 150u, 47u, 49u,
- 132u, 35u, 255u, 28u,
- 0u, 146u, 165u, 72u,
- 34u, 130u, 165u, 148u,
- 146u, 180u, 159u, 101u,
- 1u, 115u, 166u, 44u,
- 237u, 0u, 237u, 80u,
- 148u, 118u, 213u, 112u,
- 110u, 128u, 255u, 113u,
- 104u, 157u, 76u, 80u,
- 130u, 129u, 212u, 1u,
- 205u, 22u, 133u, 142u,
- 29u, 84u, 156u, 118u,
- 49u, 147u, 173u, 255u,
- 92u, 152u, 135u, 171u,
- 22u, 1u, 212u, 55u,
- 147u, 255u, 57u, 91u,
- 92u, 68u, 128u, 153u,
- 86u, 67u, 62u, 132u,
- 163u, 164u, 182u, 1u,
- 255u, 210u, 131u, 77u,
- 76u, 24u, 204u, 107u,
- 151u, 255u, 133u, 146u,
- 112u, 151u, 85u, 192u,
- 24u, 15u, 149u, 255u,
- 122u, 234u, 187u, 120u,
- 130u, 36u, 205u, 85u,
- 131u, 82u, 182u, 1u,
- 55u, 1u, 196u, 78u,
- 145u, 158u, 94u, 158u,
- 31u, 76u, 50u, 18u,
- 78u, 255u, 162u, 134u,
- 29u, 77u, 92u, 128u,
- 48u, 206u, 147u, 255u,
- 104u, 158u, 93u, 1u,
- 72u, 92u, 99u, 183u,
- 9u, 24u, 225u, 236u,
- 255u, 148u, 84u, 128u,
- 113u, 136u, 70u, 204u,
- 97u, 255u, 73u, 107u,
- 159u, 1u, 55u, 134u,
- 230u, 117u, 132u, 215u,
- 98u, 175u, 96u, 82u,
- 255u, 100u, 71u, 223u,
- 86u, 146u, 81u, 139u,
- 232u, 1u, 169u, 149u,
- 90u, 119u, 99u, 160u,
- 90u, 190u, 164u, 255u,
- 242u, 107u, 28u, 113u,
- 151u, 178u, 255u, 180u,
- 179u, 21u, 135u, 178u,
- 137u, 150u, 1u, 159u,
- 209u, 233u, 255u, 132u,
- 214u, 108u, 91u, 121u,
- 14u, 118u, 16u, 36u,
- 116u, 51u, 120u, 1u,
- 178u, 1u, 150u, 228u,
- 161u, 140u, 216u, 98u,
- 128u, 181u, 146u, 91u,
- 170u, 1u, 88u, 18u,
- 215u, 97u, 170u, 191u,
- 144u, 0u, 36u, 101u,
- 62u, 134u, 91u, 255u,
- 40u, 15u, 181u, 82u,
- 95u, 82u, 1u, 56u,
- 183u, 215u, 149u, 80u,
- 183u, 218u, 255u, 157u,
- 232u, 138u, 105u, 38u,
- 54u, 81u, 94u, 91u,
- 255u, 99u, 82u, 91u,
- 53u, 204u, 206u, 112u,
- 213u, 255u, 216u, 117u,
- 67u, 92u, 67u, 45u,
- 0u, 90u, 88u, 93u,
- 83u, 112u, 103u, 255u,
- 66u, 159u, 126u, 13u,
- 1u, 147u, 124u, 139u,
- 130u, 94u, 216u, 130u,
- 136u, 64u, 135u, 172u,
- 161u, 1u, 155u, 146u,
- 202u, 195u, 255u, 236u,
- 101u, 48u, 145u, 63u,
- 124u, 165u, 119u, 255u,
- 141u, 111u, 106u, 3u,
- 1u, 228u, 64u, 16u,
- 106u, 146u, 127u, 151u,
- 105u, 174u, 39u, 193u,
- 142u, 185u, 50u, 1u,
- 208u, 163u, 71u, 72u,
- 154u, 9u, 1u, 155u,
- 168u, 105u, 135u, 14u,
- 61u, 74u, 146u, 1u,
- 140u, 1u, 153u, 111u,
- 26u, 99u, 168u, 73u,
- 172u, 200u, 168u, 211u,
- 227u, 168u, 255u, 79u,
- 231u, 201u, 193u, 169u,
- 138u, 144u, 64u, 255u,
- 120u, 110u, 172u, 201u,
- 157u, 123u, 82u, 255u,
- 255u, 166u, 152u, 74u,
- 188u, 115u, 118u, 81u
-};
-
-const float16 LangIdNNParams::kEmbeddingsQuantScales4[] = {
- 15435u, 15371u, 15387u, 15344u,
- 15402u, 15321u, 15429u, 15362u,
- 15265u, 15246u, 15376u, 15408u,
- 15279u, 15365u, 15498u, 15299u,
- 15394u, 15419u, 15405u, 15264u,
- 15426u, 15367u, 15244u, 15484u,
- 15422u, 15293u, 15407u, 15313u,
- 15432u, 15459u, 15391u, 15388u,
- 15381u, 15284u, 15279u, 15239u,
- 15326u, 15391u, 15298u, 15380u,
- 15418u, 15354u, 15385u, 15304u,
- 15499u, 15301u, 15445u, 15399u,
- 15455u, 15355u, 15461u, 15404u,
- 15404u, 15249u, 15339u, 15314u,
- 15399u, 15562u, 15245u, 15446u,
- 15421u, 15406u, 15422u, 15401u,
- 15279u, 15360u, 15338u, 15426u,
- 15370u, 15404u, 15379u, 15371u,
- 15214u, 15298u, 15430u, 15330u,
- 15256u, 15391u, 15363u, 15385u,
- 15325u, 15436u, 15258u, 15433u,
- 15245u, 15428u, 15262u, 15472u,
- 15297u, 15316u, 15159u, 15400u,
- 15357u, 15434u, 15348u, 15228u,
- 15308u, 15439u, 15384u, 15364u,
- 15346u, 15424u, 15380u, 15336u,
- 15319u, 15361u, 15372u, 15423u,
- 15256u, 15329u, 15482u, 15363u,
- 15432u, 15386u, 15365u, 15274u,
- 15373u, 15426u, 15244u, 15396u,
- 15166u, 15251u, 15405u, 15275u,
- 15305u, 15384u, 15417u, 15321u,
- 15402u, 15351u, 15378u, 15335u,
- 15534u, 15375u, 15318u, 15410u,
- 15434u, 15276u, 15384u, 15266u,
- 15425u, 15382u, 15280u, 15276u,
- 15361u, 15404u, 15291u, 15375u,
- 15288u, 15405u, 15343u, 15343u,
- 15352u, 15373u, 15439u, 15337u,
- 15497u, 15492u, 15332u, 15464u,
- 15312u, 15266u, 15372u, 15373u,
- 15358u, 15399u, 15419u, 15262u,
- 15365u, 15403u, 15490u, 15176u,
- 15348u, 15340u, 15353u, 15265u,
- 15421u, 15329u, 15416u, 15210u,
- 15364u, 15362u, 15386u, 15415u,
- 15309u, 15245u, 15412u, 15370u,
- 15423u, 15310u, 15389u, 15351u,
- 15295u, 15443u, 15402u, 15231u,
- 15430u, 15381u, 15293u, 15464u,
- 15289u, 15424u, 15221u, 15366u,
- 15249u, 15413u, 15410u, 15482u,
- 15364u, 15279u, 15454u, 15338u,
- 15256u, 15343u, 15364u, 15404u,
- 15303u, 15396u, 15335u, 15344u,
- 15395u, 15338u, 15380u, 15322u,
- 15382u, 15378u, 15299u, 15405u,
- 15368u, 15286u, 15464u, 15266u,
- 15271u, 15386u, 15442u, 15371u,
- 15308u, 15360u, 15446u, 15384u,
- 15305u, 15369u, 15456u, 15372u,
- 15288u, 15482u, 15424u, 15387u,
- 15377u, 15528u, 15370u, 15382u,
- 15363u, 15321u, 15212u, 15477u,
- 15409u, 15421u, 15379u, 15343u,
- 15354u, 15420u, 15315u, 15287u,
- 15281u, 15274u, 15434u, 15404u,
- 15241u, 15205u, 15378u, 15290u,
- 15167u, 15469u, 15397u, 15383u,
- 15400u, 15382u, 15419u, 15357u,
- 15383u, 15376u, 15314u, 15354u,
- 15326u, 15493u, 15396u, 15184u,
- 15267u, 15304u, 15308u, 15271u,
- 15495u, 15426u, 15320u, 15440u,
- 15283u, 15262u, 15440u, 15380u,
- 15361u, 15387u, 15263u, 15397u,
- 15353u, 15280u, 15427u, 15322u,
- 15338u, 15282u, 15355u, 15279u,
- 15510u, 15327u, 15409u, 15338u,
- 15360u, 15318u, 15434u, 15475u,
- 15231u, 15374u, 15349u, 15571u,
- 15607u, 15409u, 15428u, 15465u,
- 15264u, 15434u, 15360u, 15338u,
- 15434u, 15266u, 15379u, 15464u,
- 15293u, 15376u, 15290u, 15389u,
- 15287u, 15323u, 15283u, 15521u,
- 15290u, 15340u, 15371u, 15435u,
- 15391u, 15470u, 15357u, 15477u,
- 15414u, 15374u, 15252u, 15302u,
- 15431u, 15304u, 15410u, 15470u,
- 15560u, 15372u, 15377u, 15436u,
- 15234u, 15464u, 15318u, 15381u,
- 15254u, 15309u, 15396u, 15377u,
- 15240u, 15358u, 15319u, 15262u,
- 15383u, 15424u, 15387u, 15193u,
- 15330u, 15338u, 15384u, 15502u,
- 15383u, 15396u, 15447u, 15235u,
- 15199u, 15374u, 15250u, 15291u,
- 15328u, 15252u, 15344u, 15340u,
- 15406u, 15349u, 15407u, 15401u,
- 15385u, 15256u, 15264u, 15355u,
- 15381u, 15376u, 15352u, 15364u,
- 15488u, 15459u, 15260u, 15523u,
- 15370u, 15378u, 15402u, 15443u,
- 15354u, 15361u, 15384u, 15392u,
- 15415u, 15378u, 15300u, 15371u,
- 15462u, 15429u, 15373u, 15329u,
- 15363u, 15389u, 15358u, 15366u,
- 15335u, 15256u, 15323u, 15302u,
- 15349u, 15555u, 15370u, 15412u,
- 15317u, 15527u, 15409u, 15508u,
- 15283u, 15261u, 15420u, 15502u,
- 15349u, 15352u, 15494u, 15414u,
- 15527u, 15295u, 15300u, 15288u,
- 15405u, 15316u, 15475u, 15454u,
- 15570u, 15246u, 15376u, 15293u,
- 15391u, 15254u, 15335u, 15257u,
- 15395u, 15478u, 15279u, 15337u,
- 15376u, 15246u, 15371u, 15410u,
- 15323u, 15265u, 15414u, 15395u,
- 15271u, 15361u, 15399u, 15251u,
- 15436u, 15363u, 15546u, 15296u,
- 15293u, 15277u, 15424u, 15233u,
- 15482u, 15340u, 15359u, 15381u,
- 15298u, 15383u, 15383u, 15278u,
- 15257u, 15453u, 15346u, 15540u,
- 15429u, 15279u, 15334u, 15379u,
- 15354u, 15173u, 15289u, 15162u,
- 15258u, 15316u, 15294u, 15456u,
- 15267u, 15362u, 15300u, 15305u,
- 15354u, 15251u, 15424u, 15373u,
- 15367u, 15397u, 15243u, 15488u,
- 15320u, 15331u, 15264u, 15429u,
- 15433u, 15421u, 15276u, 15454u,
- 15355u, 15529u, 15291u, 15379u,
- 15436u, 15332u, 15398u, 15449u,
- 15265u, 15337u, 15322u, 15245u,
- 15312u, 15383u, 15492u, 15350u,
- 15368u, 15454u, 15356u, 15275u,
- 15344u, 15421u, 15309u, 15221u,
- 15371u, 15369u, 15441u, 15424u,
- 15408u, 15362u, 15506u, 15367u,
- 15302u, 15524u, 15343u, 15374u,
- 15351u, 15387u, 15233u, 15340u,
- 15261u, 15280u, 15375u, 15544u,
- 15343u, 15313u, 15361u, 15341u,
- 15278u, 15272u, 15187u, 15406u,
- 15318u, 15380u, 15333u, 15406u,
- 15340u, 15385u, 15260u, 15304u,
- 15392u, 15391u, 15362u, 15406u,
- 15442u, 15286u, 15367u, 15358u,
- 15324u, 15414u, 15255u, 15420u,
- 15290u, 15388u, 15490u, 15433u,
- 15396u, 15347u, 15423u, 15333u,
- 15256u, 15418u, 15398u, 15371u,
- 15414u, 15437u, 15349u, 15455u,
- 15290u, 15376u, 15338u, 15348u,
- 15491u, 15383u, 15423u, 15420u,
- 15290u, 15472u, 15310u, 15287u,
- 15362u, 15351u, 15428u, 15384u,
- 15369u, 15332u, 15368u, 15299u,
- 15329u, 15376u, 15363u, 15262u,
- 15411u, 15350u, 15343u, 15293u,
- 15380u, 15293u, 15384u, 15250u,
- 15447u, 15364u, 15422u, 15329u,
- 15454u, 15324u, 15296u, 15176u,
- 15489u, 15356u, 15369u, 15374u,
- 15398u, 15371u, 15302u, 15326u,
- 15465u, 15276u, 15304u, 15368u,
- 15317u, 15365u, 15367u, 15349u,
- 15368u, 15353u, 15262u, 15236u,
- 15423u, 15350u, 15305u, 15266u,
- 15357u, 15283u, 15404u, 15368u,
- 15195u, 15470u, 15428u, 15331u,
- 15388u, 15320u, 15294u, 15493u,
- 15275u, 15308u, 15398u, 15272u,
- 15354u, 15373u, 15380u, 15285u,
- 15374u, 15226u, 15261u, 15361u,
- 15305u, 15269u, 15389u, 15495u,
- 15303u, 15219u, 15394u, 15270u,
- 15352u, 15389u, 15342u, 15387u,
- 15328u, 15337u, 15380u, 15298u,
- 15249u, 15436u, 15326u, 15391u,
- 15344u, 15256u, 15393u, 15310u,
- 15308u, 15397u, 15324u, 15448u,
- 15245u, 15364u, 15463u, 15273u,
- 15342u, 15354u, 15265u, 15328u,
- 15490u, 15234u, 15280u, 15435u,
- 15320u, 15335u, 15375u, 15425u,
- 15267u, 15356u, 15377u, 15384u,
- 15435u, 15449u, 15361u, 15394u,
- 15327u, 15507u, 15327u, 15390u,
- 15304u, 15262u, 15401u, 15505u,
- 15420u, 15268u, 15354u, 15381u,
- 15386u, 15318u, 15437u, 15398u,
- 15391u, 15282u, 15389u, 15373u,
- 15281u, 15341u, 15297u, 15329u,
- 15216u, 15459u, 15370u, 15435u,
- 15432u, 15400u, 15412u, 15414u,
- 15480u, 15307u, 15398u, 15275u,
- 15153u, 15381u, 15266u, 15344u,
- 15274u, 15446u, 15360u, 15393u,
- 15337u, 15528u, 15366u, 15316u,
- 15258u, 15391u, 15430u, 15414u,
- 15299u, 15287u, 15471u, 15383u,
- 15317u, 15447u, 15212u, 15396u,
- 15256u, 15468u, 15332u, 15360u,
- 15411u, 15330u, 15385u, 15406u,
- 15238u, 15354u, 15377u, 15339u,
- 15261u, 15273u, 15407u, 15383u,
- 15401u, 15392u, 15442u, 15273u,
- 15532u, 15249u, 15497u, 15474u,
- 15189u, 15388u, 15422u, 15442u,
- 15279u, 15460u, 15339u, 15275u,
- 15420u, 15457u, 15332u, 15330u,
- 15451u, 15290u, 15465u, 15374u,
- 15412u, 15301u, 15363u, 15308u,
- 15331u, 15357u, 15453u, 15270u,
- 15412u, 15418u, 15371u, 15553u,
- 15248u, 15210u, 15228u, 15406u,
- 15257u, 15314u, 15319u, 15301u,
- 15278u, 15371u, 15372u, 15386u,
- 15380u, 15382u, 15273u, 15360u,
- 15405u, 15446u, 15343u, 15298u,
- 15262u, 15388u, 15359u, 15452u,
- 15447u, 15410u, 15281u, 15225u,
- 15505u, 15255u, 15415u, 15465u,
- 15267u, 15317u, 15370u, 15324u,
- 15390u, 15441u, 15457u, 15415u,
- 15265u, 15249u, 15415u, 15379u,
- 15289u, 15280u, 15284u, 15240u,
- 15439u, 15204u, 15396u, 15489u,
- 15377u, 15322u, 15358u, 15236u,
- 15389u, 15415u, 15334u, 15340u,
- 15244u, 15366u, 15362u, 15492u,
- 15484u, 15340u, 15362u, 15375u,
- 15436u, 15375u, 15358u, 15368u,
- 15288u, 15415u, 15432u, 15331u,
- 15286u, 15294u, 15384u, 15419u,
- 15257u, 15499u, 15465u, 15455u,
- 15321u, 15564u, 15491u, 15328u,
- 15420u, 15412u, 15253u, 15532u,
- 15333u, 15443u, 15496u, 15388u,
- 15277u, 15397u, 15369u, 15308u,
- 15304u, 15420u, 15397u, 15414u,
- 15510u, 15344u, 15421u, 15398u,
- 15400u, 15386u, 15244u, 15487u,
- 15286u, 15457u, 15302u, 15361u,
- 15391u, 15380u, 15368u, 15375u,
- 15421u, 15338u, 15415u, 15367u,
- 15427u, 15245u, 15460u, 15403u,
- 15452u, 15253u, 15399u, 15520u,
- 15395u, 15371u, 15455u, 15368u,
- 15306u, 15417u, 15294u, 15346u,
- 15519u, 15297u, 15289u, 15259u,
- 15363u, 15316u, 15311u, 15393u,
- 15386u, 15363u, 15389u, 15405u,
- 15274u, 15353u, 15405u, 15367u,
- 15451u, 15417u, 15419u, 15303u,
- 15220u, 15279u, 15256u, 15337u,
- 15308u, 15413u, 15433u, 15184u,
- 15351u, 15374u, 15400u, 15386u,
- 15452u, 15269u, 15384u, 15464u,
- 15421u, 15193u, 15313u, 15266u,
- 15345u, 15435u, 15365u, 15172u,
- 15491u, 15350u, 15460u, 15378u,
- 15295u, 15370u, 15437u, 15248u,
- 15361u, 15270u, 15271u, 15393u,
- 15273u, 15236u, 15265u, 15346u,
- 15391u, 15376u, 15470u, 15497u,
- 15553u, 15285u, 15334u, 15410u,
- 15422u, 15264u, 15382u, 15316u,
- 15315u, 15366u, 15447u, 15437u,
- 15316u, 15396u, 15414u, 15383u,
- 15247u, 15371u, 15372u, 15507u,
- 15322u, 15448u, 15462u, 15363u,
- 15368u, 15370u, 15333u, 15379u,
- 15401u, 15235u, 15336u, 15397u,
- 15449u, 15349u, 15327u, 15217u,
- 15297u, 15267u, 15419u, 15447u,
- 15228u, 15370u, 15458u, 15351u,
- 15366u, 15255u, 15398u, 15396u,
- 15359u, 15417u, 15339u, 15357u,
- 15457u, 15503u, 15252u, 15455u,
- 15384u, 15364u, 15321u, 15372u,
- 15362u, 15333u, 15387u, 15316u,
- 15263u, 15362u, 15293u, 15355u,
- 15252u, 15468u, 15385u, 15274u,
- 15391u, 15328u, 15421u, 15289u,
- 15388u, 15259u, 15378u, 15427u,
- 15238u, 15296u, 15521u, 15295u,
- 15282u, 15275u, 15301u, 15461u,
- 15335u, 15339u, 15317u, 15427u,
- 15242u, 15395u, 15416u, 15398u,
- 15265u, 15358u, 15379u, 15465u,
- 15393u, 15354u, 15303u, 15289u,
- 15434u, 15258u, 15223u, 15489u,
- 15414u, 15440u, 15497u, 15445u,
- 15400u, 15463u, 15331u, 15459u,
- 15309u, 15433u, 15322u, 15392u,
- 15387u, 15367u, 15296u, 15236u,
- 15342u, 15266u, 15306u, 15347u,
- 15319u, 15510u, 15372u, 15389u,
- 15436u, 15446u, 15508u, 15528u,
- 15377u, 15336u, 15329u, 15321u,
- 15428u, 15304u, 15299u, 15287u,
- 15367u, 15427u, 15306u, 15292u,
- 15487u, 15391u, 15415u, 15255u,
- 15351u, 15365u, 15419u, 15287u,
- 15364u, 15361u, 15251u, 15381u,
- 15278u, 15307u, 15379u, 15342u,
- 15255u, 15344u, 15347u, 15250u,
- 15491u, 15399u, 15399u, 15315u,
- 15361u, 15329u, 15376u, 15389u,
- 15470u, 15433u, 15253u, 15396u,
- 15348u, 15245u, 15460u, 15442u,
- 15421u, 15280u, 15268u, 15369u,
- 15266u, 15357u, 15363u, 15393u,
- 15339u, 15371u, 15365u, 15241u,
- 15273u, 15362u, 15188u, 15311u,
- 15473u, 15412u, 15380u, 15396u,
- 15282u, 15533u, 15241u, 15335u,
- 15215u, 15276u, 15366u, 15304u,
- 15332u, 15326u, 15395u, 15401u,
- 15245u, 15436u, 15275u, 15379u,
- 15331u, 15333u, 15405u, 15258u,
- 15350u, 15268u, 15340u, 15374u,
- 15460u, 15375u, 15328u, 15284u,
- 15381u, 15408u, 15302u, 15467u,
- 15317u, 15368u, 15349u, 15295u,
- 15391u, 15362u, 15336u, 15399u,
- 15347u, 15422u, 15418u, 15345u,
- 15304u, 15396u, 15408u, 15257u,
- 15395u, 15232u, 15226u, 15239u,
- 15361u, 15455u, 15367u, 15390u,
- 15365u, 15377u, 15425u, 15395u,
- 15350u, 15517u, 15332u, 15328u,
- 15259u, 15287u, 15299u, 15362u,
- 15418u, 15430u, 15368u, 15377u,
- 15428u, 15396u, 15351u, 15372u,
- 15331u, 15245u, 15253u, 15391u,
- 15368u, 15388u, 15342u, 15258u,
- 15451u, 15390u, 15309u, 15401u,
- 15379u, 15381u, 15406u, 15371u,
- 15370u, 15490u, 15360u, 15384u,
- 15400u, 15404u, 15246u, 15421u,
- 15291u, 15263u, 15277u, 15475u,
- 15404u, 15334u, 15517u, 15266u,
- 15371u, 15365u, 15361u, 15373u,
- 15242u, 15403u, 15286u, 15161u,
- 15386u, 15503u, 15267u, 15214u,
- 15243u, 15403u, 15341u, 15413u,
- 15248u, 15425u, 15311u, 15273u,
- 15495u, 15415u, 15385u, 15251u,
- 15402u, 15408u, 15495u, 15365u,
- 15318u, 15306u, 15264u, 15444u,
- 15391u, 15299u, 15518u, 15376u,
- 15384u, 15323u, 15257u, 15431u,
- 15389u, 15452u, 15375u, 15280u,
- 15304u, 15292u, 15296u, 15379u,
- 15290u, 15358u, 15388u, 15435u,
- 15391u, 15421u, 15352u, 15304u,
- 15292u, 15381u, 15351u, 15338u,
- 15399u, 15505u, 15323u, 15395u,
- 15310u, 15393u, 15236u, 15313u,
- 15370u, 15483u, 15423u, 15263u,
- 15490u, 15262u, 15251u, 15408u,
- 15510u, 15417u, 15287u, 15419u,
- 15510u, 15450u, 15409u, 15365u,
- 15333u, 15378u, 15418u, 15511u,
- 15251u, 15393u, 15381u, 15360u,
- 15390u, 15203u, 15464u, 15300u,
- 15420u, 15282u, 15368u, 15581u,
- 15313u, 15419u, 15390u, 15338u,
- 15300u, 15342u, 15304u, 15304u,
- 15365u, 15352u, 15343u, 15333u,
- 15396u, 15279u, 15482u, 15355u,
- 15400u, 15314u, 15274u, 15382u,
- 15450u, 15325u, 15361u, 15245u,
- 15323u, 15337u, 15364u, 15396u,
- 15495u, 15270u, 15259u, 15411u,
- 15410u, 15263u, 15437u, 15390u,
- 15213u, 15467u, 15255u, 15371u,
- 15520u, 15304u, 15358u, 15463u,
- 15425u, 15251u, 15230u, 15243u,
- 15519u, 15430u, 15293u, 15312u,
- 15517u, 15298u, 15356u, 15386u,
- 15239u, 15403u, 15215u, 15359u,
- 15462u, 15386u, 15394u, 15399u,
- 15240u, 15346u, 15461u, 15507u,
- 15246u, 15366u, 15390u, 15416u,
- 15450u, 15398u, 15361u, 15373u,
- 15285u, 15413u, 15272u, 15376u,
- 15496u, 15376u, 15303u, 15360u,
- 15387u, 15441u, 15463u, 15354u,
- 15311u, 15381u, 15446u, 15269u,
- 15422u, 15362u, 15194u, 15473u,
- 15430u, 15368u, 15489u, 15364u,
- 15267u, 15276u, 15360u, 15414u,
- 15236u, 15313u, 15375u, 15369u,
- 15500u, 15414u, 15353u, 15411u,
- 15232u, 15316u, 15394u, 15378u,
- 15421u, 15415u, 15371u, 15270u,
- 15328u, 15392u, 15262u, 15311u,
- 15447u, 15392u, 15426u, 15283u,
- 15355u, 15385u, 15344u, 15349u,
- 15332u, 15425u, 15506u, 15413u,
- 15401u, 15388u, 15383u, 15289u,
- 15249u, 15472u, 15425u, 15252u,
- 15419u, 15490u, 15377u, 15356u,
- 15505u, 15450u, 15331u, 15387u,
- 15377u, 15484u, 15226u, 15423u,
- 15337u, 15314u, 15370u, 15312u,
- 15376u, 15364u, 15381u, 15385u,
- 15405u, 15309u, 15358u, 15344u,
- 15324u, 15434u, 15365u, 15279u,
- 15341u, 15294u, 15358u, 15304u,
- 15400u, 15384u, 15376u, 15392u,
- 15371u, 15362u, 15372u, 15374u,
- 15416u, 15380u, 15340u, 15325u,
- 15383u, 15266u, 15434u, 15408u,
- 15469u, 15398u, 15344u, 15426u,
- 15291u, 15417u, 15200u, 15385u,
- 15368u, 15248u, 15402u, 15509u,
- 15303u, 15334u, 15354u, 15409u,
- 15370u, 15271u, 15240u, 15498u,
- 15371u, 15426u, 15384u, 15339u,
- 15349u, 15375u, 15481u, 15373u,
- 15285u, 15315u, 15435u, 15498u,
- 15453u, 15259u, 15415u, 15408u,
- 15403u, 15357u, 15360u, 15275u,
- 15298u, 15404u, 15362u, 15290u,
- 15406u, 15378u, 15371u, 15262u,
- 15513u, 15263u, 15403u, 15287u,
- 15372u, 15533u, 15411u, 15375u,
- 15386u, 15351u, 15338u, 15610u,
- 15402u, 15347u, 15413u, 15471u,
- 15368u, 15523u, 15386u, 15421u,
- 15434u, 15366u, 15372u, 15433u,
- 15411u, 15278u, 15380u, 15352u,
- 15451u, 15430u, 15381u, 15322u,
- 15512u, 15352u, 15408u, 15256u,
- 15397u, 15236u, 15395u, 15360u,
- 15374u, 15190u, 15366u, 15319u,
- 15404u, 15338u, 15326u, 15366u,
- 15310u, 15359u, 15458u, 15376u,
- 15383u, 15360u, 15300u, 15380u,
- 15431u, 15522u, 15391u, 15317u,
- 15375u, 15361u, 15507u, 15338u,
- 15270u, 15391u, 15365u, 15325u,
- 15236u, 15276u, 15288u, 15362u,
- 15353u, 15326u, 15338u, 15296u,
- 15445u, 15379u, 15410u, 15257u,
- 15370u, 15252u, 15484u, 15180u,
- 15262u, 15418u, 15381u, 15398u,
- 15437u, 15391u, 15526u, 15288u,
- 15363u, 15357u, 15358u, 15285u,
- 15335u, 15347u, 15401u, 15210u,
- 15428u, 15414u, 15256u, 15375u,
- 15348u, 15201u, 15340u, 15206u,
- 15329u, 15333u, 15294u, 15441u,
- 15249u, 15315u, 15264u, 15331u,
- 15474u, 15488u, 15521u, 15385u,
- 15400u, 15229u, 15364u, 15271u,
- 15391u, 15487u, 15437u, 15403u,
- 15529u, 15188u, 15489u, 15269u,
- 15440u, 15505u, 15260u, 15242u,
- 15245u, 15387u, 15364u, 15319u,
- 15372u, 15288u, 15303u, 15427u,
- 15441u, 15317u, 15312u, 15411u,
- 15418u, 15427u, 15370u, 15388u,
- 15350u, 15432u, 15402u, 15510u,
- 15370u, 15386u, 15277u, 15290u,
- 15465u, 15491u, 15374u, 15269u,
- 15537u, 15468u, 15405u, 15246u,
- 15398u, 15234u, 15332u, 15424u,
- 15343u, 15379u, 15347u, 15298u,
- 15350u, 15423u, 15442u, 15304u,
- 15325u, 15419u, 15377u, 15381u,
- 15349u, 15344u, 15374u, 15357u,
- 15336u, 15342u, 15377u, 15383u,
- 15388u, 15453u, 15388u, 15275u,
- 15326u, 15501u, 15432u, 15422u,
- 15369u, 15259u, 15292u, 15395u,
- 15351u, 15334u, 15368u, 15373u,
- 15391u, 15352u, 15408u, 15464u,
- 15375u, 15353u, 15454u, 15308u,
- 15573u, 15266u, 15273u, 15515u,
- 15468u, 15419u, 15408u, 15425u,
- 15365u, 15333u, 15469u, 15311u,
- 15490u, 15268u, 15387u, 15379u,
- 15362u, 15298u, 15372u, 15350u,
- 15310u, 15285u, 15397u, 15435u,
- 15448u, 15330u, 15281u, 15292u,
- 15300u, 15401u, 15299u, 15185u,
- 15287u, 15488u, 15275u, 15360u,
- 15353u, 15437u, 15456u, 15373u,
- 15455u, 15392u, 15255u, 15275u,
- 15362u, 15426u, 15342u, 15368u,
- 15402u, 15353u, 15415u, 15448u,
- 15383u, 15377u, 15267u, 15376u,
- 15265u, 15424u, 15348u, 15305u,
- 15238u, 15327u, 15372u, 15368u,
- 15259u, 15307u, 15339u, 15298u,
- 15306u, 15393u, 15404u, 15381u,
- 15246u, 15279u, 15265u, 15309u,
- 15299u, 15410u, 15304u, 15302u,
- 15450u, 15344u, 15466u, 15336u,
- 15491u, 15397u, 15441u, 15453u,
- 15342u, 15465u, 15375u, 15426u,
- 15428u, 15432u, 15285u, 15246u,
- 15401u, 15355u, 15388u, 15350u,
- 15242u, 15343u, 15414u, 15327u,
- 15451u, 15393u, 15461u, 15283u,
- 15361u, 15348u, 15419u, 15402u,
- 15343u, 15394u, 15274u, 15354u,
- 15356u, 15185u, 15366u, 15440u,
- 15413u, 15230u, 15205u, 15433u,
- 15305u, 15484u, 15312u, 15240u,
- 15384u, 15322u, 15433u, 15377u,
- 15374u, 15311u, 15295u, 15379u,
- 15263u, 15393u, 15316u, 15336u,
- 15259u, 15268u, 15438u, 15212u,
- 15480u, 15279u, 15306u, 15370u,
- 15403u, 15380u, 15329u, 15288u,
- 15370u, 15408u, 15410u, 15253u,
- 15417u, 15471u, 15383u, 15443u,
- 15389u, 15323u, 15351u, 15338u,
- 15503u, 15447u, 15320u, 15468u,
- 15453u, 15229u, 15298u, 15424u,
- 15487u, 15418u, 15249u, 15381u,
- 15284u, 15363u, 15334u, 15333u,
- 15219u, 15441u, 15472u, 15339u,
- 15365u, 15358u, 15421u, 15361u,
- 15354u, 15330u, 15235u, 15471u,
- 15286u, 15426u, 15401u, 15436u,
- 15370u, 15381u, 15436u, 15510u,
- 15396u, 15311u, 15503u, 15437u,
- 15384u, 15266u, 15232u, 15369u,
- 15413u, 15407u, 15304u, 15402u,
- 15421u, 15373u, 15238u, 15378u,
- 15361u, 15336u, 15218u, 15379u,
- 15406u, 15313u, 15349u, 15327u,
- 15423u, 15478u, 15361u, 15365u,
- 15349u, 15331u, 15360u, 15300u,
- 15401u, 15363u, 15345u, 15295u,
- 15409u, 15424u, 15435u, 15405u,
- 15494u, 15404u, 15301u, 15370u,
- 15480u, 15393u, 15324u, 15465u,
- 15303u, 15282u, 15352u, 15289u,
- 15364u, 15345u, 15356u, 15278u,
- 15427u, 15399u, 15356u, 15504u,
- 15307u, 15338u, 15356u, 15363u,
- 15391u, 15479u, 15391u, 15347u,
- 15352u, 15429u, 15336u, 15192u,
- 15393u, 15491u, 15480u, 15365u,
- 15453u, 15274u, 15335u, 15251u,
- 15412u, 15396u, 15311u, 15354u,
- 15222u, 15241u, 15383u, 15253u,
- 15374u, 15268u, 15377u, 15377u,
- 15209u, 15370u, 15406u, 15332u,
- 15339u, 15408u, 15479u, 15404u,
- 15302u, 15373u, 15174u, 15459u,
- 15493u, 15452u, 15311u, 15382u,
- 15483u, 15243u, 15453u, 15481u,
- 15385u, 15426u, 15413u, 15392u,
- 15369u, 15401u, 15376u, 15427u,
- 15378u, 15413u, 15482u, 15264u,
- 15455u, 15411u, 15422u, 15260u,
- 15373u, 15366u, 15380u, 15231u,
- 15387u, 15397u, 15443u, 15397u,
- 15329u, 15472u, 15354u, 15428u,
- 15323u, 15422u, 15467u, 15388u,
- 15289u, 15338u, 15418u, 15327u,
- 15381u, 15258u, 15278u, 15370u,
- 15377u, 15450u, 15411u, 15247u,
- 15422u, 15379u, 15251u, 15358u,
- 15381u, 15378u, 15389u, 15304u,
- 15324u, 15419u, 15441u, 15418u,
- 15271u, 15372u, 15260u, 15398u,
- 15420u, 15319u, 15412u, 15347u,
- 15329u, 15310u, 15269u, 15409u,
- 15452u, 15370u, 15294u, 15366u,
- 15298u, 15279u, 15315u, 15343u,
- 15410u, 15425u, 15310u, 15385u,
- 15283u, 15188u, 15306u, 15457u,
- 15449u, 15427u, 15410u, 15227u,
- 15281u, 15420u, 15517u, 15331u,
- 15360u, 15442u, 15386u, 15378u,
- 15489u, 15376u, 15409u, 15373u,
- 15235u, 15385u, 15393u, 15396u,
- 15515u, 15457u, 15384u, 15363u,
- 15492u, 15318u, 15258u, 15401u,
- 15443u, 15516u, 15363u, 15303u,
- 15441u, 15438u, 15470u, 15362u,
- 15334u, 15364u, 15355u, 15437u,
- 15513u, 15385u, 15403u, 15470u,
- 15425u, 15436u, 15360u, 15370u,
- 15370u, 15324u, 15390u, 15273u,
- 15377u, 15339u, 15328u, 15336u,
- 15326u, 15377u, 15293u, 15392u,
- 15265u, 15381u, 15309u, 15397u,
- 15400u, 15304u, 15362u, 15279u,
- 15352u, 15477u, 15355u, 15402u,
- 15362u, 15249u, 15490u, 15354u,
- 15417u, 15473u, 15381u, 15284u,
- 15224u, 15269u, 15443u, 15398u,
- 15631u, 15340u, 15329u, 15414u,
- 15444u, 15231u, 15336u, 15244u,
- 15408u, 15344u, 15412u, 15418u,
- 15234u, 15411u, 15404u, 15486u,
- 15345u, 15386u, 15415u, 15215u,
- 15343u, 15366u, 15257u, 15363u,
- 15315u, 15386u, 15346u, 15266u,
- 15316u, 15383u, 15371u, 15352u,
- 15386u, 15331u, 15314u, 15413u,
- 15364u, 15314u, 15458u, 15312u,
- 15459u, 15279u, 15237u, 15338u,
- 15284u, 15326u, 15489u, 15409u,
- 15351u, 15459u, 15267u, 15385u,
- 15343u, 15364u, 15332u, 15407u,
- 15373u, 15423u, 15296u, 15318u,
- 15375u, 15342u, 15300u, 15450u,
- 15397u, 15462u, 15287u, 15324u,
- 15321u, 15397u, 15397u, 15291u,
- 15354u, 15321u, 15316u, 15494u,
- 15310u, 15426u, 15233u, 15357u,
- 15334u, 15400u, 15397u, 15426u,
- 15337u, 15362u, 15443u, 15139u,
- 15440u, 15386u, 15567u, 15315u,
- 15317u, 15429u, 15412u, 15275u,
- 15294u, 15398u, 15390u, 15323u,
- 15370u, 15333u, 15406u, 15490u,
- 15248u, 15451u, 15214u, 15234u,
- 15295u, 15327u, 15307u, 15390u,
- 15429u, 15477u, 15387u, 15294u,
- 15348u, 15234u, 15369u, 15351u,
- 15307u, 15440u, 15400u, 15434u,
- 15378u, 15376u, 15310u, 15390u,
- 15372u, 15339u, 15587u, 15299u,
- 15309u, 15283u, 15287u, 15523u,
- 15425u, 15322u, 15241u, 15383u,
- 15481u, 15255u, 15360u, 15317u,
- 15296u, 15239u, 15249u, 15403u,
- 15339u, 15439u, 15489u, 15411u,
- 15386u, 15538u, 15390u, 15334u,
- 15302u, 15496u, 15363u, 15375u,
- 15379u, 15246u, 15362u, 15398u,
- 15254u, 15360u, 15304u, 15499u,
- 15389u, 15288u, 15341u, 15239u,
- 15264u, 15446u, 15431u, 15401u,
- 15344u, 15381u, 15266u, 15280u,
- 15432u, 15271u, 15311u, 15393u,
- 15301u, 15342u, 15424u, 15296u,
- 15329u, 15266u, 15315u, 15265u,
- 15310u, 15399u, 15307u, 15302u,
- 15369u, 15537u, 15453u, 15480u,
- 15354u, 15518u, 15244u, 15316u,
- 15513u, 15483u, 15379u, 15334u,
- 15333u, 15322u, 15324u, 15342u,
- 15391u, 15317u, 15423u, 15253u,
- 15402u, 15425u, 15376u, 15256u,
- 15426u, 15397u, 15337u, 15385u,
- 15413u, 15385u, 15391u, 15390u,
- 15470u, 15404u, 15240u, 15403u,
- 15340u, 15360u, 15259u, 15317u,
- 15269u, 15400u, 15353u, 15420u,
- 15290u, 15220u, 15274u, 15345u,
- 15397u, 15386u, 15346u, 15393u,
- 15409u, 15256u, 15243u, 15371u,
- 15290u, 15235u, 15406u, 15393u,
- 15240u, 15356u, 15243u, 15455u,
- 15270u, 15380u, 15425u, 15398u,
- 15443u, 15432u, 15311u, 15298u,
- 15386u, 15316u, 15361u, 15518u,
- 15495u, 15419u, 15412u, 15250u,
- 15427u, 15348u, 15424u, 15348u,
- 15401u, 15234u, 15396u, 15443u,
- 15508u, 15428u, 15314u, 15261u,
- 15467u, 15322u, 15418u, 15456u,
- 15373u, 15427u, 15489u, 15238u,
- 15289u, 15372u, 15357u, 15283u,
- 15256u, 15438u, 15365u, 15391u,
- 15425u, 15293u, 15619u, 15290u,
- 15403u, 15297u, 15532u, 15428u,
- 15429u, 15344u, 15340u, 15311u,
- 15350u, 15421u, 15358u, 15365u,
- 15413u, 15362u, 15374u, 15315u,
- 15298u, 15395u, 15268u, 15304u,
- 15501u, 15335u, 15416u, 15440u,
- 15369u, 15423u, 15294u, 15414u,
- 15293u, 15365u, 15535u, 15361u,
- 15292u, 15245u, 15287u, 15289u,
- 15279u, 15420u, 15325u, 15349u,
- 15300u, 15345u, 15301u, 15325u,
- 15250u, 15260u, 15220u, 15382u,
- 15284u, 15447u, 15333u, 15284u,
- 15421u, 15420u, 15393u, 15378u,
- 15491u, 15367u, 15209u, 15446u,
- 15414u, 15479u, 15238u, 15534u,
- 15418u, 15236u, 15402u, 15456u,
- 15425u, 15421u, 15241u, 15339u,
- 15285u, 15321u, 15333u, 15412u,
- 15354u, 15350u, 15403u, 15225u,
- 15360u, 15356u, 15397u, 15354u,
- 15367u, 15249u, 15468u, 15405u,
- 15270u, 15408u, 15294u, 15299u,
- 15495u, 15317u, 15436u, 15299u,
- 15366u, 15270u, 15276u, 15393u,
- 15343u, 15366u, 15302u, 15234u,
- 15355u, 15417u, 15382u, 15285u,
- 15333u, 15297u, 15313u, 15376u,
- 15472u, 15259u, 15396u, 15134u,
- 15422u, 15503u, 15411u, 15366u,
- 15372u, 15404u, 15322u, 15296u,
- 15369u, 15404u, 15422u, 15291u,
- 15317u, 15325u, 15319u, 15277u,
- 15440u, 15371u, 15578u, 15265u,
- 15271u, 15247u, 15297u, 15360u,
- 15384u, 15396u, 15382u, 15361u,
- 15324u, 15283u, 15381u, 15379u,
- 15448u, 15366u, 15401u, 15439u,
- 15283u, 15416u, 15311u, 15483u,
- 15386u, 15307u, 15364u, 15432u,
- 15333u, 15409u, 15468u, 15380u,
- 15340u, 15254u, 15261u, 15337u,
- 15360u, 15359u, 15213u, 15324u,
- 15510u, 15361u, 15292u, 15401u,
- 15390u, 15323u, 15349u, 15354u,
- 15386u, 15389u, 15417u, 15420u,
- 15290u, 15310u, 15377u, 15420u,
- 15295u, 15188u, 15377u, 15296u,
- 15254u, 15226u, 15232u, 15406u,
- 15516u, 15421u, 15509u, 15381u,
- 15377u, 15215u, 15349u, 15377u,
- 15257u, 15458u, 15448u, 15243u,
- 15377u, 15374u, 15392u, 15232u,
- 15214u, 15397u, 15364u, 15351u,
- 15249u, 15503u, 15313u, 15366u,
- 15269u, 15514u, 15403u, 15383u,
- 15271u, 15411u, 15461u, 15338u,
- 15364u, 15410u, 15347u, 15309u,
- 15297u, 15429u, 15240u, 15247u,
- 15431u, 15347u, 15266u, 15396u,
- 15476u, 15254u, 15325u, 15254u,
- 15386u, 15323u, 15399u, 15347u,
- 15230u, 15433u, 15426u, 15275u,
- 15251u, 15281u, 15332u, 15380u,
- 15360u, 15374u, 15329u, 15286u,
- 15400u, 15353u, 15426u, 15325u,
- 15378u, 15315u, 15319u, 15377u,
- 15286u, 15416u, 15342u, 15398u,
- 15375u, 15363u, 15408u, 15286u,
- 15366u, 15267u, 15440u, 15395u,
- 15330u, 15387u, 15431u, 15387u,
- 15390u, 15399u, 15319u, 15221u,
- 15411u, 15202u, 15537u, 15282u,
- 15324u, 15478u, 15364u, 15291u,
- 15358u, 15311u, 15457u, 15346u,
- 15263u, 15391u, 15298u, 15130u,
- 15254u, 15392u, 15233u, 15324u,
- 15353u, 15375u, 15353u, 15279u,
- 15285u, 15407u, 15278u, 15295u,
- 15393u, 15301u, 15467u, 15411u,
- 15342u, 15300u, 15420u, 15410u,
- 15389u, 15296u, 15319u, 15368u,
- 15239u, 15368u, 15371u, 15392u,
- 15397u, 15344u, 15409u, 15352u,
- 15355u, 15309u, 15366u, 15351u,
- 15253u, 15255u, 15315u, 15471u,
- 15452u, 15228u, 15370u, 15364u,
- 15272u, 15253u, 15365u, 15365u,
- 15388u, 15370u, 15303u, 15249u,
- 15379u, 15354u, 15426u, 15324u,
- 15340u, 15336u, 15314u, 15301u,
- 15448u, 15320u, 15498u, 15353u,
- 15541u, 15392u, 15386u, 15276u,
- 15424u, 15364u, 15260u, 15390u,
- 15390u, 15391u, 15272u, 15338u,
- 15343u, 15238u, 15262u, 15309u,
- 15447u, 15392u, 15442u, 15415u,
- 15400u, 15312u, 15271u, 15292u,
- 15361u, 15308u, 15340u, 15344u,
- 15313u, 15320u, 15288u, 15306u,
- 15561u, 15247u, 15363u, 15407u,
- 15323u, 15350u, 15360u, 15440u,
- 15289u, 15299u, 15392u, 15384u,
- 15426u, 15374u, 15367u, 15347u,
- 15443u, 15400u, 15377u, 15411u,
- 15409u, 15310u, 15416u, 15374u,
- 15488u, 15366u, 15248u, 15417u,
- 15359u, 15489u, 15447u, 15368u,
- 15342u, 15293u, 15405u, 15299u,
- 15355u, 15366u, 15345u, 15272u,
- 15395u, 15408u, 15418u, 15431u,
- 15382u, 15385u, 15266u, 15270u,
- 15248u, 15369u, 15275u, 15409u,
- 15498u, 15468u, 15384u, 15204u,
- 15323u, 15507u, 15396u, 15367u,
- 15364u, 15409u, 15373u, 15331u,
- 15319u, 15168u, 15379u, 15226u,
- 15377u, 15414u, 15357u, 15401u,
- 15449u, 15416u, 15414u, 15253u,
- 15390u, 15339u, 15391u, 15527u,
- 15385u, 15361u, 15409u, 15264u,
- 15372u, 15385u, 15258u, 15432u,
- 15283u, 15368u, 15250u, 15336u,
- 15377u, 15343u, 15387u, 15285u,
- 15380u, 15248u, 15371u, 15178u,
- 15396u, 15355u, 15400u, 15401u,
- 15355u, 15295u, 15410u, 15357u,
- 15400u, 15291u, 15303u, 15423u,
- 15395u, 15408u, 15286u, 15429u,
- 15335u, 15204u, 15376u, 15347u,
- 15312u, 15390u, 15286u, 15408u,
- 15452u, 15317u, 15296u, 15382u,
- 15348u, 15485u, 15309u, 15387u,
- 15305u, 15455u, 15325u, 15444u,
- 15334u, 15422u, 15429u, 15444u,
- 15408u, 15288u, 15404u, 15292u,
- 15466u, 15278u, 15503u, 15353u,
- 15402u, 15301u, 15493u, 15500u,
- 15394u, 15485u, 15333u, 15302u,
- 15353u, 15336u, 15373u, 15238u,
- 15404u, 15332u, 15211u, 15309u,
- 15355u, 15395u, 15441u, 15244u,
- 15260u, 15243u, 15418u, 15458u,
- 15416u, 15294u, 15453u, 15325u,
- 15460u, 15394u, 15398u, 15313u,
- 15343u, 15326u, 15416u, 15348u,
- 15424u, 15418u, 15305u, 15414u,
- 15261u, 15444u, 15345u, 15375u,
- 15454u, 15314u, 15327u, 15378u,
- 15360u, 15410u, 15365u, 15466u,
- 15281u, 15369u, 15277u, 15241u,
- 15425u, 15357u, 15397u, 15516u,
- 15365u, 15339u, 15412u, 15393u,
- 15336u, 15431u, 15232u, 15382u,
- 15356u, 15453u, 15280u, 15338u,
- 15425u, 15409u, 15289u, 15508u,
- 15295u, 15330u, 15358u, 15410u,
- 15315u, 15406u, 15302u, 15368u,
- 15339u, 15393u, 15247u, 15287u,
- 15215u, 15236u, 15510u, 15369u,
- 15221u, 15492u, 15421u, 15355u,
- 15437u, 15278u, 15394u, 15382u,
- 15262u, 15312u, 15349u, 15410u,
- 15228u, 15413u, 15232u, 15303u,
- 15348u, 15373u, 15467u, 15234u,
- 15399u, 15371u, 15304u, 15415u,
- 15210u, 15340u, 15292u, 15357u,
- 15302u, 15309u, 15515u, 15495u,
- 15237u, 15333u, 15364u, 15258u,
- 15428u, 15436u, 15450u, 15255u,
- 15330u, 15487u, 15328u, 15432u,
- 15388u, 15398u, 15409u, 15355u,
- 15278u, 15290u, 15340u, 15366u,
- 15317u, 15341u, 15486u, 15431u,
- 15400u, 15510u, 15279u, 15369u,
- 15378u, 15328u, 15524u, 15335u,
- 15224u, 15387u, 15393u, 15420u,
- 15342u, 15381u, 15345u, 15431u,
- 15412u, 15288u, 15422u, 15296u,
- 15312u, 15422u, 15497u, 15349u,
- 15369u, 15506u, 15365u, 15312u,
- 15299u, 15283u, 15301u, 15397u,
- 15260u, 15537u, 15443u, 15392u,
- 15474u, 15402u, 15464u, 15429u,
- 15403u, 15391u, 15287u, 15474u,
- 15322u, 15349u, 15401u, 15378u,
- 15372u, 15355u, 15358u, 15445u,
- 15371u, 15349u, 15384u, 15413u,
- 15390u, 15465u, 15274u, 15363u,
- 15296u, 15342u, 15290u, 15307u,
- 15362u, 15608u, 15410u, 15427u,
- 15374u, 15352u, 15416u, 15250u,
- 15454u, 15246u, 15323u, 15394u,
- 15507u, 15348u, 15391u, 15568u,
- 15279u, 15424u, 15511u, 15493u,
- 15223u, 15362u, 15384u, 15375u,
- 15294u, 15330u, 15242u, 15521u,
- 15362u, 15311u, 15244u, 15307u,
- 15429u, 15274u, 15233u, 15428u,
- 15414u, 15301u, 15422u, 15303u,
- 15396u, 15268u, 15388u, 15237u,
- 15308u, 15508u, 15372u, 15283u,
- 15242u, 15386u, 15284u, 15297u,
- 15271u, 15390u, 15393u, 15376u,
- 15509u, 15309u, 15277u, 15203u,
- 15331u, 15367u, 15294u, 15360u,
- 15382u, 15232u, 15426u, 15333u,
- 15404u, 15290u, 15459u, 15402u,
- 15363u, 15378u, 15287u, 15360u,
- 15321u, 15417u, 15281u, 15334u,
- 15316u, 15372u, 15309u, 15346u,
- 15420u, 15249u, 15272u, 15332u,
- 15495u, 15259u, 15396u, 15490u,
- 15270u, 15259u, 15416u, 15457u,
- 15362u, 15320u, 15471u, 15341u,
- 15377u, 15397u, 15384u, 15468u,
- 15395u, 15278u, 15438u, 15410u,
- 15459u, 15236u, 15388u, 15378u,
- 15359u, 15356u, 15327u, 15428u,
- 15344u, 15401u, 15350u, 15346u,
- 15344u, 15260u, 15453u, 15340u,
- 15349u, 15359u, 15350u, 15503u,
- 15427u, 15389u, 15384u, 15348u,
- 15313u, 15450u, 15360u, 15351u,
- 15250u, 15230u, 15344u, 15306u,
- 15217u, 15382u, 15361u, 15324u,
- 15441u, 15413u, 15299u, 15386u,
- 15297u, 15292u, 15343u, 15364u,
- 15404u, 15485u, 15456u, 15316u,
- 15320u, 15383u, 15311u, 15336u,
- 15246u, 15384u, 15317u, 15437u,
- 15412u, 15451u, 15411u, 15362u,
- 15287u, 15318u, 15366u, 15239u,
- 15297u, 15391u, 15364u, 15371u,
- 15496u, 15406u, 15425u, 15473u,
- 15355u, 15371u, 15415u, 15401u,
- 15394u, 15488u, 15302u, 15402u,
- 15397u, 15381u, 15328u, 15264u,
- 15361u, 15323u, 15284u, 15423u,
- 15376u, 15252u, 15241u, 15442u,
- 15434u, 15374u, 15473u, 15415u,
- 15415u, 15372u, 15371u, 15432u,
- 15437u, 15300u, 15338u, 15396u,
- 15263u, 15334u, 15265u, 15487u,
- 15387u, 15359u, 15483u, 15344u,
- 15328u, 15401u, 15409u, 15500u,
- 15361u, 15332u, 15267u, 15300u,
- 15481u, 15399u, 15343u, 15370u,
- 15377u, 15215u, 15379u, 15377u,
- 15312u, 15338u, 15433u, 15395u,
- 15278u, 15259u, 15350u, 15395u,
- 15313u, 15382u, 15300u, 15351u,
- 15361u, 15355u, 15254u, 15361u,
- 15250u, 15457u, 15394u, 15371u,
- 15398u, 15383u, 15362u, 15364u,
- 15285u, 15393u, 15352u, 15435u,
- 15272u, 15248u, 15427u, 15270u,
- 15454u, 15429u, 15279u, 15373u,
- 15327u, 15262u, 15436u, 15320u,
- 15302u, 15225u, 15306u, 15415u,
- 15324u, 15270u, 15376u, 15436u,
- 15339u, 15456u, 15332u, 15437u,
- 15246u, 15376u, 15261u, 15249u,
- 15364u, 15409u, 15360u, 15237u,
- 15376u, 15494u, 15351u, 15363u,
- 15401u, 15275u, 15298u, 15309u,
- 15374u, 15407u, 15384u, 15370u,
- 15374u, 15250u, 15244u, 15365u,
- 15372u, 15429u, 15315u, 15518u,
- 15234u, 15517u, 15461u, 15394u,
- 15465u, 15326u, 15298u, 15312u,
- 15307u, 15241u, 15380u, 15279u,
- 15309u, 15337u, 15477u, 15427u,
- 15363u, 15457u, 15335u, 15264u,
- 15328u, 15287u, 15390u, 15326u,
- 15471u, 15367u, 15333u, 15324u,
- 15256u, 15367u, 15313u, 15398u,
- 15398u, 15291u, 15479u, 15287u,
- 15357u, 15366u, 15301u, 15386u,
- 15362u, 15401u, 15355u, 15446u,
- 15401u, 15271u, 15309u, 15407u,
- 15338u, 15351u, 15387u, 15385u,
- 15374u, 15210u, 15311u, 15335u,
- 15461u, 15523u, 15344u, 15383u,
- 15344u, 15308u, 15445u, 15455u,
- 15460u, 15316u, 15383u, 15500u,
- 15212u, 15444u, 15364u, 15286u,
- 15304u, 15487u, 15266u, 15274u,
- 15352u, 15374u, 15362u, 15350u,
- 15351u, 15329u, 15377u, 15232u,
- 15394u, 15398u, 15253u, 15381u,
- 15457u, 15132u, 15509u, 15408u,
- 15390u, 15383u, 15290u, 15324u,
- 15437u, 15514u, 15375u, 15320u,
- 15312u, 15476u, 15308u, 15430u,
- 15478u, 15676u, 15287u, 15266u,
- 15361u, 15313u, 15392u, 15306u,
- 15306u, 15377u, 15415u, 15309u,
- 15411u, 15271u, 15373u, 15400u,
- 15398u, 15485u, 15294u, 15349u,
- 15496u, 15288u, 15392u, 15391u,
- 15321u, 15391u, 15305u, 15379u,
- 15402u, 15260u, 15429u, 15376u,
- 15485u, 15420u, 15298u, 15443u,
- 15397u, 15281u, 15287u, 15328u,
- 15376u, 15340u, 15432u, 15386u,
- 15258u, 15316u, 15307u, 15473u,
- 15245u, 15423u, 15404u, 15389u,
- 15198u, 15469u, 15254u, 15523u,
- 15405u, 15318u, 15268u, 15324u,
- 15446u, 15406u, 15293u, 15318u,
- 15370u, 15355u, 15324u, 15432u,
- 15425u, 15386u, 15258u, 15313u,
- 15444u, 15297u, 15405u, 15393u,
- 15297u, 15244u, 15255u, 15362u,
- 15334u, 15233u, 15388u, 15412u,
- 15297u, 15328u, 15383u, 15407u,
- 15262u, 15364u, 15254u, 15353u,
- 15233u, 15357u, 15250u, 15307u,
- 15540u, 15247u, 15197u, 15311u,
- 15374u, 15451u, 15434u, 15352u,
- 15282u, 15373u, 15358u, 15361u,
- 15365u, 15362u, 15370u, 15322u,
- 15274u, 15376u, 15400u, 15428u,
- 15355u, 15405u, 15317u, 15374u,
- 15501u, 15476u, 15278u, 15347u,
- 15358u, 15443u, 15419u, 15302u,
- 15243u, 15420u, 15368u, 15385u,
- 15400u, 15378u, 15423u, 15284u,
- 15280u, 15343u, 15289u, 15356u,
- 15261u, 15325u, 15327u, 15362u,
- 15221u, 15358u, 15364u, 15403u,
- 15309u, 15340u, 15374u, 15460u,
- 15289u, 15408u, 15223u, 15374u,
- 15397u, 15369u, 15303u, 15215u,
- 15309u, 15240u, 15557u, 15477u,
- 15219u, 15412u, 15386u, 15393u,
- 15288u, 15351u, 15407u, 15380u,
- 15414u, 15378u, 15476u, 15425u,
- 15449u, 15249u, 15359u, 15242u,
- 15380u, 15446u, 15308u, 15228u,
- 15313u, 15312u, 15333u, 15517u,
- 15449u, 15375u, 15385u, 15349u,
- 15497u, 15412u, 15373u, 15363u,
- 15404u, 15463u, 15291u, 15327u,
- 15367u, 15383u, 15322u, 15287u,
- 15390u, 15317u, 15342u, 15279u,
- 15239u, 15418u, 15300u, 15322u,
- 15442u, 15359u, 15374u, 15316u,
- 15311u, 15277u, 15289u, 15414u,
- 15366u, 15632u, 15287u, 15298u,
- 15300u, 15311u, 15334u, 15374u,
- 15466u, 15360u, 15433u, 15400u,
- 15401u, 15495u, 15398u, 15540u,
- 15318u, 15374u, 15420u, 15421u,
- 15357u, 15418u, 15442u, 15390u,
- 15265u, 15584u, 15443u, 15397u,
- 15365u, 15372u, 15249u, 15309u,
- 15262u, 15309u, 15383u, 15334u,
- 15347u, 15376u, 15260u, 15378u,
- 15410u, 15314u, 15281u, 15325u,
- 15479u, 15249u, 15297u, 15346u,
- 15280u, 15254u, 15559u, 15250u,
- 15427u, 15501u, 15382u, 15348u,
- 15260u, 15380u, 15402u, 15353u,
- 15274u, 15309u, 15443u, 15355u,
- 15410u, 15363u, 15406u, 15251u,
- 15384u, 15349u, 15326u, 15426u,
- 15347u, 15432u, 15473u, 15457u,
- 15327u, 15284u, 15454u, 15425u,
- 15313u, 15369u, 15351u, 15368u,
- 15422u, 15521u, 15263u, 15406u,
- 15436u, 15372u, 15381u, 15255u,
- 15322u, 15427u, 15384u, 15377u,
- 15367u, 15529u, 15396u, 15410u,
- 15495u, 15235u, 15438u, 15278u,
- 15591u, 15460u, 15317u, 15375u,
- 15407u, 15268u, 15399u, 15172u,
- 15343u, 15382u, 15466u, 15298u,
- 15353u, 15338u, 15346u, 15352u,
- 15330u, 15494u, 15381u, 15342u,
- 15337u, 15434u, 15425u, 15428u,
- 15359u, 15337u, 15360u, 15377u,
- 15379u, 15195u, 15403u, 15313u,
- 15399u, 15364u, 15310u, 15375u,
- 15397u, 15326u, 15371u, 15241u,
- 15331u, 15366u, 15297u, 15247u,
- 15394u, 15330u, 15341u, 15354u,
- 15355u, 15472u, 15455u, 15294u,
- 15341u, 15249u, 15320u, 15462u,
- 15255u, 15247u, 15405u, 15436u,
- 15233u, 15464u, 15299u, 15367u,
- 15274u, 15358u, 15297u, 15281u,
- 15398u, 15207u, 15356u, 15461u,
- 15403u, 15316u, 15288u, 15376u,
- 15252u, 15391u, 15389u, 15342u,
- 15270u, 15403u, 15337u, 15491u,
- 15438u, 15328u, 15328u, 15359u,
- 15373u, 15336u, 15489u, 15281u,
- 15260u, 15241u, 15263u, 15262u,
- 15389u, 15465u, 15376u, 15441u,
- 15325u, 15467u, 15273u, 15219u,
- 15362u, 15287u, 15313u, 15351u,
- 15389u, 15485u, 15401u, 15317u,
- 15421u, 15300u, 15362u, 15265u,
- 15503u, 15384u, 15365u, 15290u,
- 15286u, 15304u, 15366u, 15254u,
- 15459u, 15315u, 15382u, 15283u,
- 15257u, 15258u, 15341u, 15435u,
- 15397u, 15416u, 15377u, 15373u,
- 15393u, 15461u, 15495u, 15384u,
- 15414u, 15427u, 15366u, 15373u,
- 15432u, 15278u, 15427u, 15323u,
- 15412u, 15395u, 15426u, 15413u,
- 15271u, 15368u, 15394u, 15413u,
- 15310u, 15265u, 15295u, 15376u,
- 15423u, 15410u, 15225u, 15386u,
- 15331u, 15373u, 15383u, 15388u,
- 15321u, 15278u, 15394u, 15364u,
- 15479u, 15261u, 15323u, 15306u,
- 15339u, 15262u, 15433u, 15214u,
- 15479u, 15313u, 15330u, 15265u,
- 15385u, 15270u, 15292u, 15376u,
- 15248u, 15250u, 15248u, 15418u,
- 15388u, 15508u, 15415u, 15324u,
- 15370u, 15276u, 15426u, 15444u,
- 15352u, 15380u, 15212u, 15454u,
- 15266u, 15243u, 15457u, 15329u,
- 15429u, 15383u, 15448u, 15281u,
- 15281u, 15389u, 15321u, 15485u,
- 15425u, 15286u, 15410u, 15273u,
- 15219u, 15351u, 15367u, 15250u,
- 15207u, 15256u, 15356u, 15398u,
- 15400u, 15313u, 15413u, 15390u,
- 15257u, 15241u, 15288u, 15326u,
- 15374u, 15253u, 15401u, 15281u,
- 15285u, 15268u, 15342u, 15391u,
- 15524u, 15405u, 15417u, 15320u,
- 15395u, 15390u, 15422u, 15405u,
- 15424u, 15248u, 15309u, 15234u,
- 15288u, 15508u, 15340u, 15339u,
- 15363u, 15404u, 15288u, 15478u,
- 15405u, 15368u, 15416u, 15268u,
- 15375u, 15380u, 15368u, 15411u,
- 15525u, 15432u, 15328u, 15364u,
- 15251u, 15389u, 15325u, 15350u,
- 15428u, 15417u, 15434u, 15454u,
- 15298u, 15301u, 15361u, 15414u,
- 15418u, 15367u, 15357u, 15409u,
- 15307u, 15282u, 15329u, 15466u,
- 15524u, 15376u, 15384u, 15367u,
- 15355u, 15521u, 15346u, 15392u,
- 15405u, 15334u, 15242u, 15259u,
- 15323u, 15321u, 15377u, 15281u,
- 15454u, 15377u, 15298u, 15299u,
- 15359u, 15280u, 15330u, 15438u,
- 15196u, 15302u, 15463u, 15316u,
- 15271u, 15324u, 15237u, 15264u,
- 15273u, 15229u, 15387u, 15329u,
- 15301u, 15368u, 15331u, 15386u,
- 15372u, 15324u, 15371u, 15378u,
- 15275u, 15370u, 15296u, 15441u,
- 15483u, 15409u, 15275u, 15428u,
- 15352u, 15394u, 15378u, 15298u,
- 15283u, 15440u, 15260u, 15283u,
- 15255u, 15466u, 15375u, 15364u,
- 15335u, 15538u, 15528u, 15327u,
- 15325u, 15354u, 15369u, 15362u,
- 15468u, 15268u, 15426u, 15385u,
- 15225u, 15294u, 15352u, 15314u,
- 15351u, 15479u, 15331u, 15370u,
- 15239u, 15357u, 15482u, 15449u,
- 15487u, 15430u, 15254u, 15441u,
- 15314u, 15307u, 15479u, 15416u,
- 15306u, 15432u, 15264u, 15527u,
- 15333u, 15398u, 15300u, 15533u,
- 15496u, 15443u, 15321u, 15328u,
- 15496u, 15317u, 15368u, 15357u,
- 15365u, 15319u, 15432u, 15280u,
- 15205u, 15294u, 15408u, 15401u,
- 15275u, 15493u, 15205u, 15311u,
- 15400u, 15236u, 15383u, 15422u,
- 15295u, 15372u, 15359u, 15334u,
- 15322u, 15290u, 15307u, 15263u,
- 15488u, 15423u, 15324u, 15305u,
- 15333u, 15498u, 15365u, 15295u,
- 15364u, 15324u, 15375u, 15402u,
- 15363u, 15379u, 15386u, 15481u,
- 15232u, 15429u, 15368u, 15311u,
- 15373u, 15338u, 15274u, 15304u,
- 15436u, 15398u, 15423u, 15433u,
- 15382u, 15245u, 15425u, 15361u,
- 15275u, 15377u, 15407u, 15460u,
- 15394u, 15222u, 15369u, 15397u,
- 15402u, 15266u, 15423u, 15351u,
- 15363u, 15310u, 15334u, 15362u,
- 15254u, 15477u, 15382u, 15364u,
- 15402u, 15367u, 15384u, 15333u,
- 15387u, 15386u, 15322u, 15469u,
- 15514u, 15313u, 15372u, 15355u,
- 15285u, 15374u, 15271u, 15570u,
- 15426u, 15374u, 15277u, 15471u,
- 15309u, 15235u, 15388u, 15348u,
- 15367u, 15293u, 15228u, 15177u,
- 15428u, 15363u, 15421u, 15359u,
- 15328u, 15368u, 15271u, 15488u,
- 15370u, 15408u, 15269u, 15379u,
- 15238u, 15450u, 15302u, 15257u,
- 15369u, 15348u, 15433u, 15396u,
- 15336u, 15319u, 15230u, 15418u,
- 15471u, 15356u, 15341u, 15372u,
- 15252u, 15272u, 15348u, 15247u,
- 15434u, 15285u, 15315u, 15433u,
- 15397u, 15238u, 15340u, 15283u,
- 15212u, 15348u, 15319u, 15317u,
- 15292u, 15323u, 15385u, 15313u,
- 15339u, 15395u, 15415u, 15414u,
- 15295u, 15340u, 15382u, 15247u,
- 15255u, 15406u, 15205u, 15449u,
- 15376u, 15271u, 15437u, 15435u,
- 15325u, 15253u, 15233u, 15255u,
- 15357u, 15586u, 15318u, 15427u,
- 15439u, 15302u, 15385u, 15398u,
- 15394u, 15378u, 15447u, 15267u,
- 15331u, 15426u, 15454u, 15438u,
- 15294u, 15402u, 15154u, 15418u,
- 15331u, 15270u, 15265u, 15369u,
- 15283u, 15324u, 15334u, 15395u,
- 15352u, 15326u, 15318u, 15298u,
- 15342u, 15378u, 15427u, 15472u,
- 15401u, 15449u, 15301u, 15299u,
- 15368u, 15250u, 15409u, 15365u,
- 15319u, 15331u, 15382u, 15362u,
- 15279u, 15374u, 15338u, 15367u,
- 15324u, 15401u, 15420u, 15260u,
- 15413u, 15426u, 15373u, 15243u,
- 15295u, 15367u, 15425u, 15424u,
- 15496u, 15344u, 15385u, 15257u,
- 15315u, 15489u, 15510u, 15412u,
- 15332u, 15250u, 15382u, 15335u,
- 15425u, 15230u, 15248u, 15376u,
- 15423u, 15387u, 15365u, 15308u,
- 15293u, 15398u, 15293u, 15447u,
- 15319u, 15346u, 15280u, 15389u,
- 15399u, 15404u, 15385u, 15324u,
- 15518u, 15265u, 15327u, 15346u,
- 15376u, 15407u, 15391u, 15402u,
- 15392u, 15296u, 15254u, 15385u,
- 15285u, 15362u, 15376u, 15373u,
- 15389u, 15315u, 15492u, 15360u,
- 15300u, 15288u, 15222u, 15547u,
- 15210u, 15362u, 15536u, 15285u,
- 15215u, 15385u, 15241u, 15352u,
- 15367u, 15247u, 15333u, 15247u,
- 15467u, 15396u, 15334u, 15341u,
- 15426u, 15287u, 15376u, 15473u,
- 15266u, 15354u, 15308u, 15366u,
- 15383u, 15392u, 15332u, 15245u,
- 15394u, 15322u, 15142u, 15397u,
- 15407u, 15333u, 15215u, 15441u,
- 15398u, 15301u, 15296u, 15270u,
- 15385u, 15368u, 15253u, 15415u,
- 15448u, 15356u, 15429u, 15379u,
- 15274u, 15261u, 15370u, 15365u,
- 15400u, 15386u, 15371u, 15356u,
- 15365u, 15590u, 15353u, 15405u
-};
-
-const uint8 LangIdNNParams::kEmbeddingsWeights4[] = {
- 173u, 216u, 255u, 127u,
- 175u, 139u, 119u, 104u,
- 160u, 109u, 199u, 239u,
- 180u, 54u, 222u, 16u,
- 255u, 148u, 136u, 239u,
- 147u, 72u, 141u, 229u,
- 190u, 33u, 83u, 68u,
- 221u, 80u, 83u, 143u,
- 98u, 203u, 161u, 150u,
- 173u, 137u, 191u, 19u,
- 134u, 126u, 150u, 227u,
- 160u, 47u, 164u, 1u,
- 151u, 182u, 201u, 127u,
- 110u, 41u, 125u, 180u,
- 181u, 136u, 68u, 189u,
- 255u, 12u, 89u, 20u,
- 123u, 151u, 139u, 133u,
- 190u, 66u, 255u, 222u,
- 66u, 120u, 151u, 148u,
- 183u, 47u, 87u, 81u,
- 116u, 165u, 146u, 219u,
- 163u, 1u, 178u, 26u,
- 169u, 187u, 48u, 142u,
- 184u, 165u, 91u, 203u,
- 34u, 135u, 67u, 255u,
- 19u, 208u, 226u, 156u,
- 137u, 170u, 224u, 167u,
- 245u, 126u, 109u, 208u,
- 92u, 115u, 29u, 143u,
- 148u, 97u, 106u, 170u,
- 150u, 86u, 174u, 36u,
- 1u, 121u, 59u, 111u,
- 146u, 135u, 202u, 234u,
- 233u, 105u, 146u, 117u,
- 90u, 182u, 106u, 161u,
- 255u, 70u, 14u, 31u,
- 44u, 171u, 132u, 255u,
- 206u, 20u, 136u, 62u,
- 49u, 138u, 122u, 15u,
- 178u, 242u, 80u, 190u,
- 144u, 0u, 214u, 82u,
- 105u, 6u, 36u, 242u,
- 92u, 127u, 121u, 155u,
- 138u, 221u, 165u, 246u,
- 64u, 175u, 183u, 79u,
- 167u, 125u, 134u, 74u,
- 148u, 152u, 147u, 129u,
- 230u, 1u, 108u, 154u,
- 169u, 135u, 93u, 110u,
- 21u, 1u, 81u, 132u,
- 177u, 62u, 184u, 77u,
- 253u, 101u, 176u, 163u,
- 77u, 118u, 81u, 131u,
- 180u, 151u, 207u, 77u,
- 129u, 189u, 128u, 179u,
- 255u, 154u, 128u, 101u,
- 97u, 27u, 39u, 97u,
- 97u, 0u, 64u, 158u,
- 228u, 123u, 192u, 129u,
- 126u, 154u, 42u, 101u,
- 143u, 47u, 255u, 33u,
- 173u, 60u, 116u, 195u,
- 169u, 203u, 205u, 119u,
- 156u, 165u, 150u, 158u,
- 185u, 108u, 126u, 88u,
- 179u, 42u, 134u, 128u,
- 0u, 89u, 102u, 91u,
- 184u, 124u, 86u, 203u,
- 84u, 106u, 134u, 0u,
- 98u, 44u, 97u, 23u,
- 164u, 191u, 106u, 190u,
- 203u, 98u, 160u, 125u,
- 103u, 66u, 28u, 164u,
- 46u, 153u, 52u, 117u,
- 165u, 198u, 157u, 84u,
- 181u, 1u, 107u, 126u,
- 178u, 221u, 193u, 226u,
- 197u, 140u, 188u, 101u,
- 113u, 130u, 255u, 27u,
- 127u, 166u, 209u, 227u,
- 104u, 96u, 186u, 162u,
- 73u, 42u, 89u, 48u,
- 120u, 152u, 141u, 224u,
- 133u, 255u, 91u, 55u,
- 232u, 149u, 57u, 89u,
- 1u, 151u, 221u, 152u,
- 78u, 84u, 49u, 254u,
- 53u, 191u, 218u, 86u,
- 140u, 192u, 156u, 1u,
- 115u, 200u, 104u, 63u,
- 181u, 65u, 41u, 243u,
- 159u, 64u, 148u, 121u,
- 102u, 148u, 152u, 118u,
- 132u, 139u, 88u, 1u,
- 105u, 99u, 157u, 123u,
- 134u, 135u, 84u, 207u,
- 140u, 156u, 203u, 157u,
- 125u, 198u, 154u, 192u,
- 143u, 77u, 118u, 195u,
- 203u, 159u, 108u, 1u,
- 38u, 200u, 50u, 114u,
- 145u, 181u, 31u, 115u,
- 77u, 154u, 141u, 0u,
- 190u, 140u, 46u, 182u,
- 119u, 159u, 139u, 191u,
- 84u, 92u, 255u, 93u,
- 155u, 149u, 123u, 69u,
- 68u, 77u, 215u, 159u,
- 255u, 155u, 166u, 46u,
- 142u, 103u, 137u, 193u,
- 133u, 173u, 169u, 72u,
- 156u, 188u, 239u, 85u,
- 120u, 125u, 109u, 160u,
- 150u, 255u, 140u, 121u,
- 94u, 36u, 81u, 126u,
- 157u, 53u, 97u, 99u,
- 92u, 90u, 141u, 201u,
- 142u, 249u, 179u, 199u,
- 127u, 73u, 229u, 255u,
- 162u, 76u, 94u, 97u,
- 92u, 238u, 113u, 93u,
- 196u, 155u, 161u, 149u,
- 23u, 1u, 110u, 178u,
- 83u, 46u, 71u, 51u,
- 90u, 199u, 137u, 130u,
- 56u, 142u, 255u, 79u,
- 138u, 119u, 132u, 78u,
- 30u, 104u, 104u, 144u,
- 128u, 62u, 129u, 157u,
- 97u, 170u, 104u, 209u,
- 162u, 124u, 255u, 110u,
- 158u, 198u, 152u, 120u,
- 57u, 132u, 137u, 101u,
- 189u, 11u, 130u, 168u,
- 119u, 88u, 105u, 26u,
- 255u, 17u, 132u, 244u,
- 28u, 188u, 145u, 151u,
- 77u, 194u, 187u, 255u,
- 210u, 149u, 142u, 52u,
- 143u, 20u, 45u, 221u,
- 78u, 40u, 247u, 186u,
- 243u, 120u, 58u, 148u,
- 84u, 117u, 125u, 190u,
- 129u, 255u, 100u, 137u,
- 220u, 144u, 201u, 34u,
- 96u, 213u, 223u, 255u,
- 217u, 196u, 41u, 173u,
- 37u, 62u, 131u, 153u,
- 145u, 255u, 177u, 56u,
- 136u, 48u, 157u, 68u,
- 79u, 100u, 82u, 186u,
- 28u, 211u, 187u, 234u,
- 246u, 32u, 123u, 164u,
- 123u, 73u, 233u, 17u,
- 82u, 57u, 25u, 202u,
- 117u, 255u, 124u, 105u,
- 210u, 113u, 255u, 114u,
- 188u, 25u, 103u, 74u,
- 89u, 235u, 97u, 77u,
- 222u, 194u, 211u, 83u,
- 93u, 220u, 98u, 170u,
- 110u, 196u, 171u, 163u,
- 255u, 160u, 176u, 87u,
- 30u, 88u, 137u, 77u,
- 152u, 168u, 178u, 244u,
- 52u, 23u, 201u, 21u,
- 40u, 45u, 127u, 119u,
- 128u, 255u, 113u, 185u,
- 96u, 95u, 119u, 140u,
- 78u, 144u, 98u, 1u,
- 151u, 170u, 178u, 212u,
- 80u, 89u, 151u, 1u,
- 128u, 133u, 36u, 178u,
- 205u, 150u, 117u, 93u,
- 116u, 4u, 226u, 70u,
- 117u, 109u, 147u, 255u,
- 121u, 255u, 159u, 128u,
- 163u, 160u, 88u, 152u,
- 41u, 51u, 193u, 201u,
- 184u, 173u, 89u, 105u,
- 42u, 183u, 151u, 146u,
- 142u, 104u, 206u, 128u,
- 122u, 67u, 168u, 148u,
- 160u, 1u, 157u, 176u,
- 115u, 153u, 99u, 127u,
- 91u, 104u, 66u, 0u,
- 100u, 123u, 139u, 45u,
- 184u, 7u, 96u, 170u,
- 44u, 107u, 42u, 144u,
- 166u, 184u, 156u, 44u,
- 181u, 252u, 81u, 121u,
- 96u, 103u, 81u, 0u,
- 152u, 206u, 184u, 88u,
- 80u, 131u, 150u, 218u,
- 209u, 107u, 201u, 162u,
- 1u, 80u, 208u, 142u,
- 98u, 67u, 164u, 113u,
- 136u, 73u, 135u, 125u,
- 108u, 193u, 180u, 129u,
- 255u, 128u, 98u, 103u,
- 144u, 229u, 167u, 128u,
- 179u, 255u, 130u, 120u,
- 106u, 107u, 40u, 124u,
- 75u, 129u, 179u, 154u,
- 226u, 184u, 241u, 57u,
- 121u, 111u, 13u, 5u,
- 1u, 83u, 206u, 112u,
- 172u, 92u, 182u, 177u,
- 109u, 152u, 225u, 237u,
- 155u, 0u, 70u, 148u,
- 220u, 149u, 92u, 110u,
- 71u, 95u, 97u, 191u,
- 161u, 49u, 95u, 72u,
- 221u, 104u, 95u, 92u,
- 131u, 237u, 1u, 152u,
- 107u, 42u, 142u, 122u,
- 180u, 130u, 211u, 153u,
- 210u, 21u, 96u, 157u,
- 146u, 137u, 133u, 222u,
- 50u, 167u, 255u, 77u,
- 182u, 55u, 89u, 197u,
- 135u, 210u, 59u, 178u,
- 51u, 0u, 127u, 219u,
- 206u, 128u, 80u, 104u,
- 210u, 128u, 106u, 173u,
- 95u, 1u, 74u, 230u,
- 114u, 45u, 182u, 131u,
- 119u, 186u, 188u, 181u,
- 100u, 70u, 148u, 134u,
- 118u, 162u, 74u, 148u,
- 98u, 123u, 138u, 93u,
- 69u, 153u, 123u, 1u,
- 82u, 236u, 168u, 114u,
- 178u, 144u, 70u, 126u,
- 116u, 31u, 1u, 196u,
- 69u, 254u, 18u, 42u,
- 133u, 92u, 142u, 108u,
- 167u, 122u, 30u, 88u,
- 1u, 159u, 166u, 82u,
- 169u, 174u, 24u, 64u,
- 172u, 104u, 105u, 255u,
- 143u, 235u, 161u, 132u,
- 139u, 54u, 202u, 87u,
- 97u, 139u, 55u, 194u,
- 171u, 149u, 255u, 176u,
- 161u, 172u, 188u, 131u,
- 177u, 62u, 29u, 110u,
- 185u, 191u, 117u, 112u,
- 83u, 154u, 157u, 158u,
- 255u, 129u, 207u, 148u,
- 106u, 183u, 150u, 133u,
- 147u, 150u, 171u, 140u,
- 92u, 167u, 135u, 157u,
- 115u, 159u, 210u, 185u,
- 116u, 131u, 177u, 45u,
- 255u, 77u, 82u, 28u,
- 120u, 93u, 104u, 66u,
- 74u, 115u, 130u, 1u,
- 55u, 120u, 98u, 5u,
- 60u, 160u, 164u, 148u,
- 189u, 138u, 228u, 202u,
- 72u, 113u, 64u, 1u,
- 86u, 187u, 209u, 84u,
- 230u, 79u, 43u, 191u,
- 81u, 150u, 189u, 81u,
- 103u, 110u, 70u, 133u,
- 127u, 148u, 148u, 255u,
- 185u, 43u, 118u, 158u,
- 128u, 202u, 132u, 0u,
- 184u, 23u, 105u, 48u,
- 246u, 179u, 53u, 7u,
- 158u, 77u, 65u, 114u,
- 136u, 74u, 222u, 179u,
- 134u, 26u, 53u, 188u,
- 166u, 162u, 172u, 183u,
- 125u, 255u, 128u, 44u,
- 170u, 0u, 132u, 151u,
- 111u, 71u, 105u, 99u,
- 78u, 184u, 119u, 57u,
- 123u, 174u, 160u, 141u,
- 76u, 158u, 42u, 22u,
- 174u, 191u, 65u, 245u,
- 42u, 138u, 153u, 67u,
- 66u, 99u, 0u, 205u,
- 164u, 136u, 1u, 76u,
- 110u, 114u, 62u, 140u,
- 35u, 75u, 216u, 155u,
- 54u, 129u, 145u, 188u,
- 119u, 126u, 169u, 20u,
- 119u, 228u, 140u, 255u,
- 28u, 71u, 180u, 15u,
- 59u, 235u, 54u, 92u,
- 97u, 163u, 255u, 209u,
- 101u, 164u, 150u, 81u,
- 96u, 81u, 77u, 69u,
- 122u, 206u, 165u, 61u,
- 1u, 187u, 47u, 59u,
- 101u, 73u, 156u, 113u,
- 203u, 182u, 155u, 101u,
- 154u, 98u, 148u, 99u,
- 75u, 119u, 67u, 125u,
- 113u, 144u, 53u, 255u,
- 85u, 99u, 116u, 168u,
- 66u, 13u, 177u, 128u,
- 46u, 80u, 54u, 217u,
- 116u, 128u, 231u, 8u,
- 139u, 87u, 255u, 189u,
- 111u, 103u, 155u, 52u,
- 103u, 255u, 158u, 183u,
- 137u, 150u, 206u, 185u,
- 151u, 128u, 116u, 115u,
- 112u, 120u, 117u, 180u,
- 62u, 144u, 100u, 98u,
- 126u, 1u, 186u, 150u,
- 245u, 129u, 106u, 235u,
- 189u, 142u, 79u, 90u,
- 161u, 86u, 80u, 213u,
- 133u, 93u, 156u, 153u,
- 35u, 173u, 122u, 126u,
- 189u, 145u, 255u, 94u,
- 1u, 93u, 1u, 180u,
- 57u, 93u, 158u, 120u,
- 109u, 180u, 160u, 104u,
- 79u, 223u, 132u, 124u,
- 150u, 99u, 189u, 75u,
- 112u, 157u, 105u, 95u,
- 69u, 117u, 178u, 184u,
- 255u, 224u, 140u, 234u,
- 173u, 208u, 108u, 201u,
- 217u, 142u, 126u, 60u,
- 189u, 60u, 127u, 59u,
- 127u, 94u, 191u, 255u,
- 246u, 136u, 174u, 125u,
- 138u, 190u, 173u, 94u,
- 185u, 184u, 98u, 78u,
- 1u, 116u, 238u, 110u,
- 161u, 240u, 64u, 42u,
- 189u, 158u, 89u, 255u,
- 133u, 70u, 32u, 134u,
- 65u, 138u, 85u, 45u,
- 179u, 53u, 110u, 106u,
- 166u, 124u, 164u, 255u,
- 93u, 148u, 114u, 95u,
- 170u, 68u, 128u, 91u,
- 1u, 54u, 144u, 8u,
- 186u, 114u, 101u, 157u,
- 58u, 128u, 108u, 176u,
- 103u, 115u, 174u, 93u,
- 33u, 90u, 65u, 110u,
- 65u, 188u, 183u, 109u,
- 157u, 144u, 139u, 184u,
- 146u, 79u, 55u, 1u,
- 187u, 65u, 129u, 23u,
- 121u, 57u, 39u, 143u,
- 255u, 255u, 171u, 225u,
- 135u, 49u, 15u, 120u,
- 80u, 50u, 142u, 154u,
- 158u, 158u, 149u, 228u,
- 105u, 165u, 100u, 161u,
- 0u, 167u, 60u, 8u,
- 255u, 251u, 102u, 65u,
- 201u, 68u, 95u, 98u,
- 72u, 48u, 204u, 188u,
- 198u, 69u, 162u, 234u,
- 145u, 156u, 160u, 97u,
- 184u, 170u, 161u, 174u,
- 81u, 175u, 204u, 159u,
- 91u, 0u, 31u, 132u,
- 62u, 137u, 98u, 124u,
- 134u, 108u, 129u, 99u,
- 110u, 92u, 3u, 219u,
- 124u, 255u, 159u, 231u,
- 150u, 1u, 123u, 77u,
- 114u, 180u, 92u, 147u,
- 110u, 190u, 146u, 84u,
- 91u, 220u, 228u, 159u,
- 71u, 241u, 141u, 92u,
- 137u, 152u, 140u, 180u,
- 142u, 135u, 57u, 255u,
- 199u, 126u, 40u, 201u,
- 152u, 147u, 195u, 45u,
- 74u, 140u, 16u, 202u,
- 57u, 237u, 87u, 135u,
- 255u, 97u, 116u, 117u,
- 86u, 177u, 130u, 80u,
- 160u, 90u, 103u, 220u,
- 110u, 82u, 1u, 135u,
- 22u, 144u, 12u, 114u,
- 101u, 127u, 147u, 96u,
- 190u, 211u, 92u, 216u,
- 125u, 60u, 143u, 165u,
- 152u, 143u, 1u, 168u,
- 73u, 255u, 116u, 125u,
- 114u, 117u, 208u, 62u,
- 149u, 198u, 86u, 94u,
- 115u, 77u, 34u, 154u,
- 164u, 45u, 151u, 112u,
- 248u, 163u, 5u, 13u,
- 60u, 114u, 32u, 0u,
- 206u, 74u, 66u, 79u,
- 136u, 154u, 250u, 42u,
- 255u, 106u, 192u, 143u,
- 50u, 93u, 137u, 222u,
- 137u, 164u, 88u, 47u,
- 81u, 85u, 92u, 178u,
- 103u, 150u, 189u, 11u,
- 201u, 182u, 101u, 1u,
- 91u, 92u, 187u, 154u,
- 155u, 96u, 97u, 155u,
- 173u, 86u, 97u, 25u,
- 1u, 160u, 223u, 57u,
- 130u, 117u, 156u, 46u,
- 173u, 192u, 176u, 159u,
- 129u, 185u, 55u, 242u,
- 166u, 37u, 161u, 103u,
- 149u, 1u, 141u, 197u,
- 64u, 134u, 88u, 229u,
- 199u, 61u, 188u, 154u,
- 112u, 241u, 64u, 22u,
- 1u, 193u, 166u, 30u,
- 244u, 185u, 182u, 144u,
- 207u, 200u, 65u, 92u,
- 204u, 134u, 255u, 213u,
- 6u, 65u, 147u, 40u,
- 138u, 107u, 114u, 135u,
- 54u, 202u, 118u, 48u,
- 114u, 135u, 135u, 86u,
- 64u, 137u, 175u, 255u,
- 92u, 70u, 134u, 23u,
- 138u, 115u, 130u, 152u,
- 72u, 118u, 178u, 84u,
- 108u, 141u, 1u, 145u,
- 200u, 1u, 164u, 226u,
- 138u, 161u, 81u, 127u,
- 181u, 244u, 65u, 182u,
- 254u, 161u, 3u, 64u,
- 154u, 208u, 147u, 1u,
- 227u, 92u, 225u, 88u,
- 153u, 127u, 77u, 206u,
- 153u, 186u, 211u, 151u,
- 189u, 86u, 142u, 1u,
- 106u, 109u, 131u, 157u,
- 166u, 136u, 67u, 224u,
- 25u, 150u, 112u, 105u,
- 154u, 150u, 237u, 217u,
- 60u, 161u, 196u, 83u,
- 183u, 216u, 183u, 117u,
- 229u, 255u, 56u, 87u,
- 105u, 131u, 151u, 185u,
- 142u, 113u, 131u, 129u,
- 124u, 135u, 197u, 134u,
- 255u, 109u, 124u, 115u,
- 111u, 81u, 41u, 119u,
- 1u, 224u, 150u, 197u,
- 174u, 95u, 40u, 152u,
- 110u, 119u, 192u, 118u,
- 182u, 13u, 206u, 231u,
- 130u, 94u, 7u, 140u,
- 200u, 176u, 66u, 164u,
- 134u, 53u, 168u, 0u,
- 48u, 176u, 40u, 255u,
- 123u, 160u, 193u, 23u,
- 117u, 165u, 144u, 109u,
- 152u, 48u, 156u, 151u,
- 192u, 174u, 31u, 192u,
- 136u, 222u, 65u, 179u,
- 159u, 10u, 197u, 1u,
- 61u, 176u, 120u, 157u,
- 124u, 194u, 56u, 19u,
- 86u, 140u, 130u, 100u,
- 21u, 22u, 10u, 153u,
- 60u, 195u, 1u, 216u,
- 61u, 154u, 60u, 148u,
- 170u, 176u, 23u, 207u,
- 98u, 44u, 138u, 252u,
- 161u, 97u, 0u, 96u,
- 200u, 133u, 86u, 103u,
- 170u, 173u, 197u, 108u,
- 214u, 137u, 78u, 48u,
- 119u, 1u, 239u, 137u,
- 104u, 20u, 143u, 250u,
- 198u, 199u, 47u, 134u,
- 26u, 86u, 194u, 148u,
- 31u, 255u, 119u, 108u,
- 157u, 9u, 93u, 206u,
- 102u, 150u, 50u, 171u,
- 255u, 58u, 169u, 140u,
- 153u, 155u, 84u, 67u,
- 5u, 23u, 55u, 151u,
- 127u, 23u, 86u, 165u,
- 83u, 1u, 186u, 191u,
- 209u, 188u, 236u, 178u,
- 247u, 156u, 217u, 34u,
- 160u, 51u, 97u, 110u,
- 134u, 163u, 245u, 46u,
- 211u, 1u, 204u, 134u,
- 255u, 129u, 174u, 80u,
- 123u, 125u, 123u, 140u,
- 236u, 8u, 88u, 41u,
- 200u, 215u, 37u, 235u,
- 192u, 47u, 59u, 197u,
- 187u, 14u, 1u, 247u,
- 66u, 187u, 129u, 51u,
- 127u, 200u, 73u, 96u,
- 143u, 100u, 143u, 255u,
- 79u, 162u, 99u, 147u,
- 173u, 146u, 199u, 98u,
- 173u, 125u, 69u, 107u,
- 169u, 81u, 153u, 147u,
- 164u, 200u, 157u, 219u,
- 141u, 65u, 170u, 65u,
- 1u, 205u, 127u, 101u,
- 155u, 185u, 120u, 111u,
- 199u, 50u, 28u, 41u,
- 109u, 255u, 100u, 192u,
- 170u, 178u, 11u, 104u,
- 85u, 154u, 41u, 75u,
- 109u, 221u, 63u, 1u,
- 52u, 95u, 223u, 57u,
- 119u, 167u, 247u, 99u,
- 133u, 99u, 114u, 255u,
- 66u, 152u, 4u, 242u,
- 214u, 93u, 205u, 147u,
- 94u, 137u, 121u, 76u,
- 219u, 119u, 134u, 148u,
- 89u, 183u, 87u, 168u,
- 144u, 153u, 97u, 35u,
- 133u, 141u, 255u, 67u,
- 31u, 189u, 67u, 164u,
- 99u, 158u, 59u, 149u,
- 34u, 54u, 224u, 87u,
- 255u, 148u, 201u, 26u,
- 120u, 60u, 230u, 0u,
- 116u, 224u, 61u, 69u,
- 233u, 180u, 87u, 151u,
- 218u, 53u, 136u, 105u,
- 42u, 134u, 183u, 169u,
- 181u, 155u, 128u, 73u,
- 156u, 105u, 159u, 163u,
- 194u, 122u, 0u, 64u,
- 120u, 90u, 106u, 122u,
- 78u, 183u, 93u, 189u,
- 154u, 159u, 118u, 137u,
- 0u, 131u, 144u, 135u,
- 138u, 86u, 222u, 133u,
- 76u, 80u, 1u, 177u,
- 212u, 77u, 199u, 166u,
- 44u, 133u, 220u, 111u,
- 99u, 94u, 97u, 186u,
- 73u, 100u, 54u, 64u,
- 255u, 130u, 16u, 168u,
- 110u, 193u, 147u, 112u,
- 46u, 171u, 81u, 96u,
- 151u, 201u, 137u, 255u,
- 45u, 68u, 15u, 249u,
- 11u, 170u, 144u, 169u,
- 160u, 221u, 255u, 10u,
- 102u, 125u, 3u, 106u,
- 214u, 237u, 193u, 160u,
- 100u, 65u, 148u, 140u,
- 104u, 176u, 131u, 190u,
- 102u, 117u, 65u, 122u,
- 71u, 126u, 138u, 120u,
- 67u, 30u, 155u, 1u,
- 230u, 29u, 156u, 191u,
- 24u, 254u, 116u, 181u,
- 115u, 138u, 125u, 212u,
- 70u, 136u, 197u, 255u,
- 65u, 107u, 203u, 71u,
- 176u, 188u, 147u, 134u,
- 15u, 134u, 150u, 1u,
- 112u, 97u, 148u, 114u,
- 103u, 76u, 158u, 182u,
- 97u, 167u, 153u, 153u,
- 72u, 255u, 127u, 81u,
- 190u, 68u, 210u, 81u,
- 71u, 149u, 71u, 191u,
- 239u, 255u, 107u, 146u,
- 120u, 139u, 59u, 79u,
- 49u, 65u, 105u, 59u,
- 53u, 89u, 197u, 174u,
- 190u, 255u, 106u, 154u,
- 91u, 190u, 182u, 105u,
- 177u, 144u, 99u, 105u,
- 237u, 148u, 255u, 240u,
- 222u, 77u, 146u, 108u,
- 225u, 252u, 109u, 136u,
- 129u, 203u, 127u, 163u,
- 129u, 166u, 138u, 163u,
- 198u, 173u, 226u, 67u,
- 0u, 101u, 211u, 145u,
- 156u, 58u, 139u, 70u,
- 152u, 190u, 198u, 8u,
- 138u, 78u, 99u, 84u,
- 96u, 154u, 134u, 187u,
- 222u, 220u, 1u, 67u,
- 130u, 179u, 167u, 112u,
- 179u, 137u, 147u, 163u,
- 102u, 132u, 218u, 164u,
- 231u, 0u, 146u, 99u,
- 181u, 255u, 192u, 27u,
- 158u, 96u, 115u, 219u,
- 200u, 201u, 87u, 187u,
- 187u, 82u, 117u, 140u,
- 120u, 138u, 255u, 114u,
- 118u, 167u, 135u, 99u,
- 141u, 175u, 144u, 92u,
- 161u, 224u, 184u, 127u,
- 98u, 219u, 29u, 172u,
- 0u, 144u, 185u, 237u,
- 127u, 137u, 68u, 26u,
- 28u, 199u, 237u, 145u,
- 163u, 129u, 114u, 147u,
- 122u, 106u, 90u, 255u,
- 129u, 184u, 82u, 95u,
- 105u, 208u, 96u, 49u,
- 147u, 112u, 139u, 164u,
- 106u, 163u, 176u, 157u,
- 100u, 141u, 186u, 88u,
- 73u, 132u, 127u, 1u,
- 1u, 94u, 132u, 77u,
- 196u, 189u, 40u, 141u,
- 131u, 178u, 211u, 38u,
- 250u, 166u, 97u, 151u,
- 215u, 194u, 144u, 131u,
- 194u, 78u, 217u, 44u,
- 1u, 115u, 115u, 153u,
- 123u, 57u, 35u, 143u,
- 96u, 166u, 97u, 1u,
- 106u, 150u, 164u, 153u,
- 163u, 108u, 104u, 177u,
- 61u, 85u, 164u, 76u,
- 166u, 136u, 93u, 135u,
- 64u, 126u, 146u, 91u,
- 169u, 171u, 255u, 110u,
- 210u, 69u, 184u, 158u,
- 117u, 71u, 133u, 126u,
- 87u, 123u, 255u, 61u,
- 58u, 151u, 83u, 202u,
- 156u, 139u, 141u, 60u,
- 174u, 1u, 22u, 101u,
- 25u, 194u, 121u, 20u,
- 157u, 99u, 18u, 124u,
- 45u, 22u, 205u, 200u,
- 170u, 121u, 71u, 98u,
- 119u, 181u, 128u, 125u,
- 42u, 255u, 8u, 78u,
- 123u, 195u, 83u, 165u,
- 184u, 89u, 115u, 26u,
- 50u, 39u, 118u, 218u,
- 59u, 0u, 156u, 116u,
- 133u, 116u, 102u, 68u,
- 103u, 126u, 146u, 98u,
- 137u, 81u, 135u, 42u,
- 18u, 64u, 131u, 103u,
- 185u, 151u, 1u, 64u,
- 50u, 8u, 206u, 67u,
- 118u, 96u, 39u, 18u,
- 79u, 107u, 39u, 255u,
- 81u, 255u, 14u, 166u,
- 255u, 101u, 167u, 131u,
- 171u, 102u, 61u, 242u,
- 35u, 129u, 197u, 170u,
- 181u, 151u, 125u, 78u,
- 21u, 142u, 31u, 1u,
- 179u, 133u, 150u, 197u,
- 120u, 81u, 186u, 201u,
- 24u, 197u, 147u, 148u,
- 72u, 98u, 58u, 92u,
- 35u, 89u, 139u, 118u,
- 21u, 93u, 17u, 138u,
- 15u, 172u, 130u, 255u,
- 113u, 97u, 163u, 97u,
- 118u, 50u, 136u, 1u,
- 176u, 183u, 136u, 124u,
- 224u, 207u, 139u, 143u,
- 164u, 0u, 137u, 45u,
- 223u, 188u, 123u, 143u,
- 49u, 207u, 41u, 171u,
- 3u, 221u, 28u, 75u,
- 187u, 156u, 197u, 84u,
- 92u, 164u, 41u, 95u,
- 117u, 141u, 160u, 136u,
- 111u, 1u, 92u, 112u,
- 62u, 126u, 162u, 242u,
- 90u, 152u, 122u, 255u,
- 160u, 1u, 158u, 204u,
- 70u, 230u, 178u, 108u,
- 78u, 161u, 255u, 67u,
- 102u, 28u, 150u, 211u,
- 189u, 25u, 121u, 139u,
- 158u, 152u, 100u, 112u,
- 135u, 255u, 206u, 77u,
- 225u, 170u, 120u, 161u,
- 97u, 176u, 125u, 189u,
- 78u, 136u, 157u, 137u,
- 161u, 186u, 131u, 128u,
- 146u, 155u, 106u, 200u,
- 10u, 134u, 177u, 1u,
- 55u, 206u, 170u, 133u,
- 74u, 50u, 233u, 193u,
- 124u, 69u, 161u, 0u,
- 103u, 227u, 151u, 202u,
- 215u, 190u, 82u, 48u,
- 83u, 100u, 22u, 255u,
- 97u, 155u, 140u, 116u,
- 120u, 110u, 78u, 8u,
- 24u, 216u, 156u, 213u,
- 23u, 54u, 213u, 130u,
- 137u, 18u, 71u, 245u,
- 140u, 67u, 206u, 208u,
- 81u, 255u, 4u, 202u,
- 28u, 77u, 57u, 70u,
- 78u, 125u, 166u, 98u,
- 145u, 100u, 77u, 114u,
- 126u, 89u, 76u, 255u,
- 1u, 213u, 29u, 36u,
- 89u, 201u, 224u, 37u,
- 223u, 95u, 150u, 249u,
- 79u, 66u, 204u, 253u,
- 236u, 72u, 19u, 159u,
- 55u, 138u, 1u, 167u,
- 202u, 182u, 144u, 127u,
- 105u, 145u, 126u, 146u,
- 178u, 146u, 144u, 101u,
- 207u, 96u, 92u, 116u,
- 110u, 1u, 169u, 106u,
- 145u, 138u, 11u, 227u,
- 255u, 80u, 128u, 126u,
- 74u, 132u, 136u, 234u,
- 42u, 138u, 172u, 84u,
- 127u, 94u, 207u, 215u,
- 147u, 108u, 114u, 160u,
- 75u, 255u, 100u, 63u,
- 135u, 62u, 93u, 153u,
- 177u, 201u, 216u, 166u,
- 253u, 105u, 115u, 150u,
- 151u, 255u, 140u, 191u,
- 85u, 92u, 145u, 112u,
- 94u, 133u, 91u, 139u,
- 123u, 0u, 98u, 71u,
- 159u, 83u, 185u, 95u,
- 8u, 213u, 31u, 164u,
- 131u, 238u, 113u, 135u,
- 72u, 91u, 115u, 255u,
- 107u, 231u, 159u, 129u,
- 170u, 154u, 69u, 158u,
- 76u, 81u, 21u, 106u,
- 62u, 185u, 113u, 16u,
- 52u, 124u, 215u, 195u,
- 224u, 82u, 130u, 255u,
- 98u, 20u, 223u, 194u,
- 200u, 184u, 168u, 42u,
- 150u, 214u, 50u, 125u,
- 0u, 202u, 127u, 36u,
- 94u, 144u, 98u, 57u,
- 86u, 200u, 130u, 1u,
- 130u, 144u, 94u, 174u,
- 70u, 86u, 181u, 90u,
- 203u, 23u, 36u, 219u,
- 142u, 97u, 163u, 95u,
- 226u, 127u, 189u, 121u,
- 57u, 89u, 138u, 17u,
- 77u, 255u, 176u, 126u,
- 130u, 27u, 70u, 61u,
- 1u, 5u, 122u, 152u,
- 81u, 129u, 188u, 32u,
- 159u, 247u, 89u, 52u,
- 121u, 160u, 183u, 140u,
- 23u, 65u, 82u, 75u,
- 142u, 148u, 237u, 105u,
- 84u, 255u, 132u, 214u,
- 141u, 122u, 71u, 117u,
- 189u, 55u, 12u, 70u,
- 156u, 201u, 156u, 61u,
- 180u, 86u, 1u, 158u,
- 134u, 5u, 150u, 1u,
- 125u, 136u, 118u, 70u,
- 56u, 145u, 190u, 88u,
- 173u, 119u, 66u, 174u,
- 75u, 161u, 118u, 139u,
- 136u, 135u, 1u, 81u,
- 66u, 112u, 127u, 112u,
- 65u, 199u, 101u, 157u,
- 174u, 135u, 7u, 29u,
- 255u, 155u, 189u, 78u,
- 63u, 229u, 130u, 171u,
- 167u, 70u, 112u, 60u,
- 219u, 161u, 118u, 164u,
- 79u, 46u, 87u, 180u,
- 178u, 115u, 138u, 215u,
- 85u, 0u, 196u, 71u,
- 142u, 218u, 207u, 103u,
- 173u, 92u, 228u, 1u,
- 91u, 201u, 16u, 221u,
- 115u, 207u, 182u, 46u,
- 97u, 69u, 128u, 152u,
- 141u, 164u, 89u, 158u,
- 40u, 193u, 110u, 126u,
- 122u, 255u, 129u, 173u,
- 70u, 168u, 253u, 58u,
- 119u, 155u, 181u, 171u,
- 111u, 101u, 162u, 144u,
- 25u, 201u, 255u, 93u,
- 0u, 87u, 20u, 113u,
- 115u, 203u, 147u, 104u,
- 107u, 140u, 94u, 120u,
- 118u, 69u, 79u, 143u,
- 72u, 83u, 238u, 187u,
- 181u, 48u, 91u, 34u,
- 1u, 155u, 166u, 45u,
- 70u, 108u, 129u, 218u,
- 111u, 191u, 115u, 116u,
- 103u, 136u, 255u, 126u,
- 30u, 70u, 98u, 149u,
- 81u, 144u, 152u, 146u,
- 5u, 16u, 180u, 60u,
- 255u, 62u, 104u, 110u,
- 125u, 136u, 73u, 76u,
- 161u, 250u, 49u, 61u,
- 144u, 187u, 118u, 40u,
- 255u, 232u, 109u, 184u,
- 86u, 96u, 35u, 88u,
- 23u, 132u, 40u, 150u,
- 242u, 194u, 217u, 173u,
- 74u, 137u, 104u, 197u,
- 172u, 1u, 218u, 183u,
- 210u, 95u, 139u, 162u,
- 131u, 142u, 143u, 90u,
- 178u, 110u, 119u, 255u,
- 152u, 94u, 62u, 224u,
- 183u, 147u, 174u, 106u,
- 255u, 200u, 172u, 100u,
- 149u, 174u, 86u, 193u,
- 54u, 128u, 171u, 138u,
- 115u, 188u, 123u, 138u,
- 215u, 192u, 162u, 155u,
- 136u, 57u, 104u, 43u,
- 124u, 109u, 187u, 94u,
- 144u, 134u, 255u, 86u,
- 75u, 93u, 74u, 126u,
- 176u, 169u, 128u, 173u,
- 139u, 236u, 208u, 125u,
- 230u, 242u, 103u, 1u,
- 158u, 205u, 92u, 157u,
- 17u, 73u, 91u, 128u,
- 107u, 97u, 185u, 142u,
- 220u, 234u, 146u, 1u,
- 136u, 126u, 75u, 255u,
- 202u, 206u, 197u, 198u,
- 155u, 182u, 113u, 124u,
- 52u, 92u, 117u, 104u,
- 185u, 136u, 94u, 189u,
- 83u, 255u, 99u, 138u,
- 54u, 52u, 120u, 76u,
- 50u, 64u, 145u, 169u,
- 85u, 255u, 137u, 109u,
- 203u, 165u, 225u, 130u,
- 6u, 52u, 142u, 111u,
- 95u, 200u, 55u, 177u,
- 109u, 123u, 192u, 207u,
- 21u, 255u, 195u, 93u,
- 173u, 231u, 58u, 215u,
- 102u, 253u, 107u, 67u,
- 181u, 155u, 213u, 96u,
- 228u, 48u, 79u, 217u,
- 66u, 129u, 165u, 120u,
- 169u, 74u, 255u, 31u,
- 184u, 139u, 148u, 97u,
- 117u, 122u, 128u, 164u,
- 131u, 1u, 100u, 163u,
- 117u, 44u, 116u, 144u,
- 84u, 1u, 114u, 203u,
- 174u, 139u, 8u, 124u,
- 6u, 77u, 77u, 93u,
- 139u, 177u, 127u, 11u,
- 138u, 162u, 142u, 1u,
- 215u, 113u, 58u, 211u,
- 144u, 94u, 140u, 95u,
- 93u, 204u, 124u, 89u,
- 97u, 170u, 14u, 58u,
- 235u, 255u, 171u, 160u,
- 104u, 63u, 121u, 7u,
- 31u, 122u, 184u, 176u,
- 107u, 147u, 150u, 211u,
- 201u, 203u, 103u, 106u,
- 86u, 255u, 209u, 94u,
- 135u, 127u, 228u, 41u,
- 204u, 38u, 148u, 17u,
- 255u, 227u, 244u, 181u,
- 44u, 218u, 181u, 137u,
- 72u, 63u, 100u, 24u,
- 103u, 66u, 54u, 204u,
- 50u, 105u, 123u, 150u,
- 61u, 152u, 1u, 126u,
- 134u, 178u, 61u, 112u,
- 167u, 94u, 255u, 141u,
- 118u, 38u, 35u, 158u,
- 35u, 139u, 236u, 50u,
- 182u, 77u, 228u, 179u,
- 93u, 67u, 146u, 188u,
- 155u, 0u, 74u, 128u,
- 143u, 189u, 144u, 137u,
- 247u, 188u, 99u, 105u,
- 209u, 142u, 212u, 208u,
- 0u, 233u, 16u, 16u,
- 249u, 141u, 102u, 128u,
- 117u, 154u, 112u, 192u,
- 82u, 144u, 120u, 38u,
- 124u, 134u, 124u, 79u,
- 90u, 70u, 114u, 1u,
- 70u, 125u, 172u, 135u,
- 184u, 103u, 169u, 86u,
- 117u, 129u, 144u, 69u,
- 44u, 150u, 164u, 1u,
- 106u, 16u, 42u, 155u,
- 122u, 33u, 79u, 28u,
- 186u, 37u, 192u, 91u,
- 23u, 241u, 193u, 154u,
- 255u, 184u, 186u, 135u,
- 1u, 166u, 130u, 114u,
- 124u, 133u, 168u, 105u,
- 137u, 130u, 125u, 152u,
- 120u, 145u, 171u, 159u,
- 155u, 144u, 89u, 192u,
- 204u, 175u, 111u, 188u,
- 1u, 45u, 101u, 102u,
- 152u, 240u, 218u, 240u,
- 218u, 150u, 85u, 131u,
- 140u, 91u, 64u, 180u,
- 80u, 117u, 103u, 82u,
- 4u, 168u, 202u, 255u,
- 95u, 80u, 76u, 86u,
- 178u, 100u, 255u, 111u,
- 146u, 157u, 155u, 148u,
- 118u, 79u, 92u, 91u,
- 69u, 193u, 95u, 1u,
- 86u, 224u, 253u, 135u,
- 196u, 126u, 52u, 117u,
- 86u, 147u, 227u, 111u,
- 85u, 37u, 167u, 235u,
- 168u, 118u, 200u, 88u,
- 65u, 91u, 51u, 114u,
- 131u, 239u, 1u, 149u,
- 68u, 142u, 97u, 255u,
- 20u, 116u, 160u, 34u,
- 113u, 34u, 190u, 129u,
- 166u, 94u, 161u, 152u,
- 101u, 79u, 172u, 93u,
- 85u, 124u, 115u, 64u,
- 156u, 167u, 121u, 93u,
- 81u, 0u, 94u, 116u,
- 186u, 116u, 179u, 47u,
- 107u, 174u, 159u, 155u,
- 191u, 1u, 206u, 158u,
- 120u, 91u, 25u, 208u,
- 105u, 30u, 202u, 156u,
- 55u, 31u, 167u, 17u,
- 140u, 132u, 48u, 131u,
- 169u, 200u, 198u, 255u,
- 1u, 207u, 43u, 112u,
- 179u, 219u, 117u, 178u,
- 99u, 97u, 63u, 176u,
- 36u, 44u, 101u, 137u,
- 116u, 185u, 143u, 131u,
- 133u, 171u, 179u, 134u,
- 40u, 1u, 234u, 244u,
- 139u, 185u, 165u, 146u,
- 226u, 62u, 89u, 130u,
- 130u, 126u, 1u, 143u,
- 88u, 141u, 37u, 109u,
- 77u, 229u, 131u, 83u,
- 101u, 133u, 139u, 108u,
- 217u, 255u, 127u, 182u,
- 104u, 148u, 147u, 67u,
- 156u, 126u, 173u, 144u,
- 60u, 137u, 18u, 215u,
- 185u, 177u, 110u, 103u,
- 64u, 226u, 129u, 1u,
- 239u, 117u, 186u, 79u,
- 94u, 163u, 89u, 89u,
- 126u, 135u, 202u, 85u,
- 63u, 123u, 64u, 113u,
- 124u, 182u, 255u, 59u,
- 147u, 131u, 86u, 85u,
- 138u, 125u, 136u, 161u,
- 1u, 163u, 116u, 136u,
- 94u, 165u, 167u, 227u,
- 55u, 237u, 120u, 121u,
- 141u, 59u, 94u, 1u,
- 79u, 229u, 28u, 146u,
- 35u, 182u, 105u, 12u,
- 143u, 250u, 148u, 78u,
- 173u, 219u, 228u, 17u,
- 1u, 39u, 170u, 59u,
- 202u, 106u, 115u, 154u,
- 72u, 179u, 76u, 178u,
- 185u, 168u, 156u, 189u,
- 127u, 112u, 180u, 103u,
- 65u, 1u, 103u, 100u,
- 129u, 75u, 142u, 34u,
- 199u, 156u, 142u, 165u,
- 65u, 92u, 146u, 126u,
- 41u, 20u, 61u, 0u,
- 109u, 105u, 255u, 119u,
- 161u, 238u, 166u, 125u,
- 182u, 151u, 114u, 167u,
- 113u, 84u, 138u, 161u,
- 75u, 1u, 39u, 147u,
- 197u, 67u, 87u, 224u,
- 150u, 5u, 53u, 152u,
- 69u, 177u, 147u, 146u,
- 170u, 84u, 132u, 173u,
- 66u, 52u, 128u, 44u,
- 130u, 255u, 137u, 139u,
- 164u, 211u, 175u, 96u,
- 86u, 100u, 108u, 102u,
- 223u, 131u, 120u, 144u,
- 31u, 127u, 29u, 218u,
- 188u, 206u, 1u, 143u,
- 60u, 112u, 162u, 255u,
- 86u, 72u, 146u, 72u,
- 190u, 139u, 77u, 208u,
- 144u, 231u, 155u, 186u,
- 108u, 32u, 143u, 119u,
- 178u, 126u, 114u, 152u,
- 85u, 255u, 161u, 83u,
- 247u, 80u, 20u, 100u,
- 131u, 177u, 255u, 236u,
- 103u, 84u, 143u, 106u,
- 201u, 79u, 143u, 85u,
- 101u, 110u, 188u, 220u,
- 124u, 209u, 169u, 79u,
- 0u, 102u, 93u, 110u,
- 121u, 124u, 243u, 99u,
- 63u, 193u, 199u, 203u,
- 210u, 255u, 179u, 105u,
- 8u, 127u, 175u, 95u,
- 195u, 143u, 96u, 178u,
- 108u, 121u, 147u, 129u,
- 145u, 134u, 115u, 113u,
- 143u, 189u, 41u, 167u,
- 117u, 89u, 169u, 126u,
- 1u, 126u, 127u, 119u,
- 33u, 100u, 138u, 73u,
- 135u, 112u, 232u, 136u,
- 130u, 165u, 77u, 1u,
- 150u, 32u, 114u, 55u,
- 136u, 26u, 97u, 158u,
- 94u, 148u, 127u, 49u,
- 29u, 122u, 118u, 101u,
- 1u, 160u, 119u, 184u,
- 102u, 112u, 36u, 115u,
- 58u, 64u, 255u, 191u,
- 253u, 126u, 177u, 177u,
- 229u, 94u, 148u, 73u,
- 195u, 193u, 86u, 155u,
- 0u, 70u, 168u, 52u,
- 161u, 49u, 154u, 185u,
- 203u, 79u, 219u, 181u,
- 150u, 232u, 93u, 173u,
- 134u, 222u, 152u, 137u,
- 182u, 60u, 24u, 147u,
- 59u, 255u, 153u, 80u,
- 228u, 172u, 150u, 221u,
- 86u, 71u, 150u, 166u,
- 255u, 76u, 88u, 201u,
- 42u, 106u, 138u, 72u,
- 104u, 230u, 189u, 38u,
- 170u, 255u, 179u, 121u,
- 145u, 151u, 140u, 148u,
- 8u, 75u, 135u, 102u,
- 237u, 122u, 197u, 146u,
- 37u, 21u, 66u, 173u,
- 23u, 84u, 83u, 88u,
- 93u, 164u, 255u, 181u,
- 196u, 186u, 111u, 122u,
- 188u, 255u, 40u, 250u,
- 189u, 122u, 162u, 95u,
- 76u, 76u, 77u, 212u,
- 129u, 113u, 90u, 153u,
- 111u, 65u, 144u, 87u,
- 127u, 91u, 92u, 255u,
- 138u, 163u, 134u, 149u,
- 91u, 212u, 21u, 83u,
- 145u, 40u, 130u, 69u,
- 163u, 200u, 130u, 48u,
- 154u, 1u, 108u, 119u,
- 133u, 63u, 222u, 137u,
- 170u, 60u, 193u, 156u,
- 70u, 151u, 76u, 247u,
- 218u, 69u, 1u, 74u,
- 83u, 71u, 187u, 107u,
- 76u, 167u, 127u, 103u,
- 88u, 60u, 236u, 159u,
- 119u, 255u, 79u, 125u,
- 120u, 31u, 130u, 40u,
- 255u, 226u, 178u, 134u,
- 130u, 110u, 93u, 38u,
- 167u, 170u, 117u, 114u,
- 154u, 112u, 106u, 71u,
- 213u, 54u, 252u, 192u,
- 21u, 133u, 49u, 174u,
- 255u, 111u, 80u, 237u,
- 65u, 150u, 182u, 103u,
- 43u, 167u, 71u, 1u,
- 171u, 88u, 143u, 158u,
- 137u, 145u, 87u, 92u,
- 146u, 226u, 30u, 88u,
- 187u, 95u, 196u, 211u,
- 68u, 0u, 89u, 49u,
- 210u, 168u, 172u, 148u,
- 126u, 53u, 72u, 255u,
- 152u, 95u, 98u, 85u,
- 142u, 7u, 56u, 81u,
- 71u, 187u, 213u, 126u,
- 107u, 125u, 162u, 199u,
- 59u, 95u, 255u, 50u,
- 113u, 160u, 87u, 150u,
- 182u, 168u, 134u, 156u,
- 118u, 231u, 121u, 45u,
- 255u, 125u, 181u, 115u,
- 14u, 28u, 121u, 161u,
- 187u, 187u, 5u, 95u,
- 69u, 43u, 165u, 148u,
- 39u, 124u, 147u, 146u,
- 78u, 45u, 135u, 153u,
- 79u, 145u, 116u, 1u,
- 150u, 123u, 134u, 94u,
- 1u, 181u, 222u, 165u,
- 219u, 116u, 91u, 152u,
- 40u, 192u, 218u, 88u,
- 1u, 163u, 41u, 213u,
- 160u, 191u, 203u, 94u,
- 75u, 142u, 118u, 109u,
- 131u, 109u, 142u, 58u,
- 1u, 72u, 74u, 121u,
- 116u, 185u, 181u, 128u,
- 116u, 192u, 229u, 109u,
- 200u, 85u, 97u, 162u,
- 112u, 170u, 129u, 185u,
- 111u, 80u, 98u, 113u,
- 255u, 119u, 100u, 105u,
- 152u, 93u, 102u, 201u,
- 168u, 117u, 112u, 255u,
- 48u, 104u, 43u, 135u,
- 38u, 23u, 181u, 168u,
- 74u, 174u, 139u, 157u,
- 236u, 245u, 163u, 186u,
- 60u, 178u, 154u, 117u,
- 251u, 238u, 59u, 171u,
- 26u, 0u, 64u, 67u,
- 59u, 94u, 34u, 210u,
- 195u, 180u, 124u, 108u,
- 180u, 228u, 156u, 114u,
- 218u, 1u, 51u, 171u,
- 162u, 234u, 139u, 182u,
- 46u, 184u, 92u, 154u,
- 83u, 106u, 133u, 175u,
- 1u, 184u, 219u, 54u,
- 208u, 130u, 206u, 247u,
- 126u, 65u, 64u, 149u,
- 147u, 212u, 130u, 129u,
- 126u, 244u, 255u, 57u,
- 114u, 63u, 153u, 137u,
- 11u, 90u, 123u, 1u,
- 128u, 30u, 149u, 170u,
- 136u, 199u, 195u, 69u,
- 128u, 172u, 153u, 255u,
- 42u, 117u, 145u, 71u,
- 154u, 136u, 103u, 184u,
- 127u, 201u, 162u, 126u,
- 89u, 79u, 104u, 66u,
- 136u, 81u, 117u, 206u,
- 33u, 171u, 100u, 72u,
- 186u, 255u, 99u, 108u,
- 38u, 1u, 78u, 89u,
- 198u, 61u, 89u, 227u,
- 116u, 192u, 203u, 8u,
- 234u, 104u, 113u, 114u,
- 88u, 129u, 208u, 21u,
- 84u, 92u, 192u, 74u,
- 121u, 196u, 200u, 157u,
- 133u, 139u, 173u, 255u,
- 155u, 167u, 150u, 151u,
- 232u, 109u, 55u, 193u,
- 78u, 179u, 104u, 1u,
- 90u, 107u, 18u, 114u,
- 94u, 189u, 146u, 114u,
- 255u, 135u, 81u, 60u,
- 235u, 80u, 79u, 111u,
- 100u, 47u, 128u, 228u,
- 117u, 161u, 91u, 106u,
- 117u, 197u, 22u, 109u,
- 1u, 95u, 117u, 147u,
- 148u, 177u, 99u, 126u,
- 175u, 85u, 147u, 151u,
- 129u, 65u, 153u, 235u,
- 87u, 0u, 163u, 158u,
- 194u, 157u, 53u, 77u,
- 126u, 160u, 155u, 182u,
- 82u, 115u, 146u, 138u,
- 199u, 193u, 160u, 211u,
- 144u, 26u, 1u, 119u,
- 102u, 163u, 137u, 144u,
- 10u, 184u, 129u, 102u,
- 189u, 136u, 1u, 96u,
- 57u, 63u, 146u, 149u,
- 50u, 107u, 156u, 89u,
- 255u, 76u, 170u, 163u,
- 106u, 201u, 64u, 217u,
- 102u, 182u, 37u, 186u,
- 112u, 151u, 152u, 135u,
- 121u, 152u, 74u, 64u,
- 164u, 255u, 146u, 73u,
- 193u, 125u, 197u, 90u,
- 1u, 118u, 60u, 219u,
- 11u, 95u, 105u, 121u,
- 98u, 38u, 137u, 156u,
- 115u, 146u, 135u, 201u,
- 110u, 208u, 255u, 125u,
- 155u, 110u, 27u, 123u,
- 100u, 50u, 247u, 103u,
- 131u, 58u, 72u, 31u,
- 115u, 125u, 141u, 80u,
- 140u, 89u, 103u, 122u,
- 0u, 142u, 155u, 190u,
- 40u, 106u, 139u, 69u,
- 44u, 255u, 25u, 60u,
- 240u, 246u, 208u, 189u,
- 107u, 170u, 175u, 184u,
- 84u, 102u, 231u, 54u,
- 19u, 148u, 255u, 94u,
- 143u, 148u, 100u, 214u,
- 124u, 253u, 160u, 233u,
- 109u, 182u, 89u, 100u,
- 37u, 92u, 136u, 141u,
- 150u, 81u, 187u, 66u,
- 47u, 150u, 176u, 68u,
- 103u, 209u, 1u, 104u,
- 180u, 189u, 49u, 117u,
- 168u, 147u, 69u, 142u,
- 1u, 72u, 35u, 100u,
- 37u, 163u, 119u, 184u,
- 76u, 36u, 70u, 26u,
- 134u, 109u, 203u, 143u,
- 0u, 157u, 181u, 85u,
- 88u, 171u, 143u, 108u,
- 172u, 87u, 187u, 94u,
- 101u, 124u, 170u, 127u,
- 129u, 126u, 145u, 57u,
- 110u, 71u, 255u, 45u,
- 127u, 28u, 47u, 66u,
- 90u, 116u, 105u, 255u,
- 55u, 2u, 101u, 155u,
- 95u, 109u, 164u, 164u,
- 108u, 155u, 146u, 69u,
- 183u, 110u, 106u, 120u,
- 102u, 104u, 174u, 124u,
- 144u, 111u, 0u, 114u,
- 83u, 192u, 176u, 159u,
- 179u, 99u, 141u, 123u,
- 82u, 188u, 255u, 170u,
- 75u, 109u, 118u, 177u,
- 140u, 140u, 0u, 225u,
- 162u, 91u, 192u, 85u,
- 84u, 55u, 59u, 187u,
- 235u, 158u, 167u, 170u,
- 79u, 157u, 15u, 166u,
- 187u, 164u, 144u, 169u,
- 240u, 0u, 101u, 172u,
- 63u, 181u, 32u, 156u,
- 199u, 112u, 255u, 168u,
- 219u, 174u, 114u, 134u,
- 200u, 97u, 148u, 223u,
- 52u, 151u, 161u, 143u,
- 123u, 138u, 73u, 1u,
- 151u, 120u, 162u, 131u,
- 147u, 98u, 143u, 182u,
- 128u, 123u, 230u, 112u,
- 57u, 79u, 102u, 243u,
- 60u, 200u, 127u, 115u,
- 91u, 128u, 154u, 201u,
- 106u, 255u, 222u, 86u,
- 0u, 139u, 16u, 136u,
- 211u, 180u, 127u, 87u,
- 238u, 202u, 191u, 221u,
- 133u, 103u, 119u, 120u,
- 7u, 148u, 178u, 166u,
- 113u, 103u, 255u, 47u,
- 135u, 104u, 138u, 182u,
- 95u, 105u, 116u, 167u,
- 109u, 143u, 116u, 166u,
- 175u, 194u, 130u, 149u,
- 90u, 123u, 115u, 126u,
- 1u, 184u, 91u, 85u,
- 156u, 166u, 49u, 125u,
- 112u, 231u, 84u, 229u,
- 145u, 98u, 81u, 123u,
- 1u, 133u, 121u, 179u,
- 78u, 159u, 146u, 255u,
- 120u, 171u, 192u, 95u,
- 56u, 98u, 181u, 94u,
- 156u, 181u, 104u, 85u,
- 167u, 181u, 64u, 252u,
- 152u, 170u, 1u, 103u,
- 162u, 116u, 144u, 77u,
- 42u, 59u, 95u, 115u,
- 171u, 57u, 132u, 114u,
- 179u, 143u, 103u, 1u,
- 101u, 227u, 95u, 160u,
- 110u, 223u, 108u, 144u,
- 138u, 146u, 194u, 128u,
- 85u, 74u, 172u, 114u,
- 255u, 176u, 128u, 137u,
- 57u, 138u, 28u, 188u,
- 47u, 63u, 165u, 97u,
- 202u, 115u, 84u, 134u,
- 44u, 149u, 95u, 41u,
- 141u, 122u, 1u, 111u,
- 255u, 89u, 136u, 100u,
- 147u, 117u, 97u, 198u,
- 205u, 143u, 156u, 59u,
- 117u, 13u, 201u, 187u,
- 172u, 193u, 124u, 9u,
- 65u, 120u, 136u, 38u,
- 250u, 158u, 112u, 80u,
- 61u, 168u, 146u, 255u,
- 153u, 124u, 192u, 149u,
- 188u, 124u, 134u, 80u,
- 195u, 118u, 146u, 130u,
- 79u, 255u, 150u, 146u,
- 92u, 252u, 67u, 88u,
- 134u, 121u, 106u, 121u,
- 255u, 70u, 187u, 108u,
- 46u, 71u, 68u, 247u,
- 53u, 157u, 98u, 211u,
- 134u, 102u, 178u, 255u,
- 196u, 177u, 144u, 187u,
- 103u, 111u, 107u, 78u,
- 200u, 175u, 135u, 96u,
- 150u, 90u, 64u, 180u,
- 165u, 130u, 169u, 68u,
- 94u, 184u, 0u, 224u,
- 215u, 27u, 212u, 79u,
- 163u, 230u, 97u, 125u,
- 3u, 125u, 1u, 124u,
- 231u, 184u, 84u, 44u,
- 255u, 178u, 149u, 120u,
- 197u, 192u, 201u, 117u,
- 189u, 157u, 187u, 136u,
- 139u, 25u, 210u, 75u,
- 74u, 155u, 148u, 95u,
- 44u, 88u, 109u, 48u,
- 144u, 225u, 99u, 81u,
- 168u, 91u, 255u, 121u,
- 82u, 159u, 86u, 167u,
- 163u, 232u, 196u, 149u,
- 97u, 109u, 121u, 149u,
- 104u, 0u, 168u, 174u,
- 198u, 80u, 200u, 61u,
- 159u, 146u, 255u, 215u,
- 38u, 134u, 145u, 112u,
- 112u, 101u, 33u, 92u,
- 93u, 123u, 143u, 163u,
- 123u, 102u, 165u, 1u,
- 142u, 152u, 139u, 80u,
- 177u, 79u, 221u, 135u,
- 151u, 158u, 180u, 150u,
- 168u, 154u, 137u, 84u,
- 1u, 143u, 171u, 54u,
- 229u, 100u, 115u, 161u,
- 1u, 96u, 214u, 91u,
- 118u, 137u, 85u, 151u,
- 68u, 152u, 158u, 179u,
- 126u, 145u, 35u, 28u,
- 177u, 139u, 64u, 65u,
- 132u, 132u, 172u, 121u,
- 106u, 197u, 68u, 119u,
- 152u, 255u, 117u, 133u,
- 177u, 250u, 102u, 148u,
- 98u, 205u, 114u, 163u,
- 161u, 142u, 75u, 110u,
- 81u, 61u, 82u, 255u,
- 91u, 46u, 162u, 121u,
- 136u, 53u, 24u, 99u,
- 142u, 255u, 61u, 38u,
- 107u, 81u, 117u, 62u,
- 137u, 134u, 89u, 102u,
- 138u, 163u, 102u, 134u,
- 121u, 140u, 131u, 174u,
- 79u, 179u, 255u, 97u,
- 106u, 97u, 80u, 138u,
- 140u, 104u, 134u, 153u,
- 122u, 127u, 100u, 193u,
- 91u, 88u, 104u, 1u,
- 1u, 130u, 57u, 56u,
- 122u, 118u, 207u, 102u,
- 106u, 208u, 94u, 127u,
- 155u, 116u, 150u, 161u,
- 145u, 241u, 3u, 224u,
- 143u, 221u, 132u, 77u,
- 208u, 125u, 68u, 62u,
- 184u, 211u, 179u, 255u,
- 150u, 214u, 231u, 51u,
- 137u, 177u, 137u, 255u,
- 61u, 138u, 122u, 96u,
- 83u, 103u, 31u, 172u,
- 176u, 202u, 131u, 159u,
- 114u, 187u, 159u, 182u,
- 203u, 255u, 100u, 155u,
- 157u, 79u, 164u, 28u,
- 149u, 119u, 166u, 166u,
- 84u, 126u, 170u, 121u,
- 213u, 151u, 136u, 158u,
- 64u, 133u, 255u, 238u,
- 249u, 124u, 117u, 161u,
- 198u, 0u, 171u, 247u,
- 245u, 40u, 145u, 139u,
- 46u, 92u, 153u, 137u,
- 224u, 82u, 1u, 179u,
- 113u, 149u, 153u, 236u,
- 108u, 122u, 60u, 167u,
- 142u, 75u, 165u, 96u,
- 120u, 138u, 244u, 62u,
- 255u, 142u, 182u, 133u,
- 120u, 135u, 99u, 133u,
- 83u, 116u, 82u, 147u,
- 137u, 117u, 211u, 142u,
- 188u, 131u, 210u, 255u,
- 103u, 147u, 134u, 223u,
- 244u, 4u, 45u, 199u,
- 94u, 158u, 57u, 60u,
- 96u, 129u, 114u, 24u,
- 204u, 207u, 133u, 147u,
- 173u, 48u, 1u, 133u,
- 186u, 42u, 134u, 200u,
- 117u, 57u, 92u, 170u,
- 152u, 186u, 167u, 144u,
- 189u, 88u, 255u, 151u,
- 255u, 88u, 145u, 219u,
- 127u, 101u, 163u, 159u,
- 110u, 150u, 99u, 96u,
- 183u, 102u, 151u, 177u,
- 98u, 134u, 117u, 93u,
- 118u, 116u, 238u, 191u,
- 207u, 175u, 255u, 84u,
- 245u, 141u, 46u, 105u,
- 121u, 198u, 90u, 50u,
- 192u, 164u, 195u, 74u,
- 45u, 129u, 0u, 172u,
- 78u, 127u, 113u, 152u,
- 96u, 113u, 37u, 140u,
- 81u, 33u, 178u, 152u,
- 80u, 153u, 149u, 92u,
- 148u, 255u, 169u, 162u,
- 127u, 165u, 179u, 216u,
- 146u, 132u, 101u, 255u,
- 158u, 5u, 108u, 191u,
- 68u, 79u, 60u, 97u,
- 99u, 83u, 145u, 255u,
- 123u, 155u, 72u, 206u,
- 94u, 131u, 198u, 153u,
- 125u, 157u, 205u, 107u,
- 217u, 156u, 135u, 158u,
- 198u, 40u, 184u, 136u,
- 178u, 208u, 44u, 1u,
- 251u, 33u, 220u, 208u,
- 142u, 176u, 60u, 107u,
- 67u, 130u, 28u, 172u,
- 223u, 0u, 102u, 69u,
- 124u, 42u, 212u, 146u,
- 163u, 91u, 107u, 168u,
- 45u, 1u, 134u, 243u,
- 72u, 145u, 159u, 151u,
- 167u, 183u, 200u, 77u,
- 121u, 255u, 49u, 146u,
- 141u, 162u, 95u, 139u,
- 247u, 139u, 141u, 91u,
- 159u, 68u, 158u, 86u,
- 146u, 255u, 106u, 148u,
- 141u, 159u, 159u, 19u,
- 108u, 159u, 92u, 112u,
- 126u, 107u, 179u, 168u,
- 174u, 105u, 201u, 161u,
- 158u, 79u, 60u, 109u,
- 28u, 97u, 132u, 152u,
- 240u, 148u, 83u, 0u,
- 177u, 56u, 154u, 221u,
- 40u, 143u, 129u, 140u,
- 137u, 114u, 1u, 109u,
- 41u, 133u, 193u, 5u,
- 1u, 10u, 129u, 195u,
- 146u, 185u, 102u, 206u,
- 23u, 100u, 197u, 89u,
- 133u, 158u, 208u, 18u,
- 215u, 250u, 24u, 204u,
- 64u, 28u, 83u, 51u,
- 218u, 103u, 1u, 52u,
- 107u, 150u, 16u, 142u,
- 0u, 66u, 52u, 155u,
- 133u, 94u, 153u, 67u,
- 91u, 132u, 144u, 40u,
- 165u, 156u, 107u, 210u,
- 117u, 202u, 173u, 102u,
- 106u, 218u, 100u, 94u,
- 77u, 191u, 70u, 120u,
- 67u, 78u, 63u, 1u,
- 153u, 148u, 1u, 97u,
- 147u, 87u, 234u, 112u,
- 81u, 137u, 59u, 95u,
- 62u, 84u, 99u, 139u,
- 95u, 201u, 203u, 175u,
- 88u, 33u, 191u, 57u,
- 110u, 58u, 109u, 75u,
- 1u, 214u, 157u, 158u,
- 169u, 111u, 60u, 177u,
- 168u, 189u, 54u, 1u,
- 65u, 242u, 6u, 7u,
- 122u, 69u, 20u, 211u,
- 208u, 89u, 159u, 41u,
- 149u, 84u, 44u, 189u,
- 255u, 229u, 127u, 160u,
- 84u, 149u, 176u, 63u,
- 152u, 1u, 176u, 80u,
- 174u, 131u, 182u, 57u,
- 221u, 179u, 45u, 139u,
- 46u, 245u, 192u, 17u,
- 217u, 32u, 180u, 143u,
- 62u, 96u, 214u, 101u,
- 1u, 15u, 95u, 152u,
- 212u, 218u, 148u, 133u,
- 188u, 206u, 158u, 89u,
- 112u, 113u, 1u, 115u,
- 81u, 152u, 144u, 89u,
- 122u, 157u, 131u, 162u,
- 96u, 188u, 57u, 31u,
- 124u, 126u, 210u, 174u,
- 255u, 45u, 221u, 99u,
- 102u, 17u, 88u, 215u,
- 125u, 120u, 142u, 71u,
- 146u, 152u, 86u, 93u,
- 1u, 116u, 152u, 126u,
- 122u, 95u, 94u, 103u,
- 114u, 106u, 144u, 132u,
- 141u, 96u, 153u, 148u,
- 255u, 129u, 91u, 101u,
- 143u, 116u, 142u, 173u,
- 126u, 174u, 181u, 33u,
- 69u, 159u, 142u, 37u,
- 100u, 29u, 139u, 110u,
- 164u, 54u, 153u, 255u,
- 182u, 108u, 204u, 144u,
- 41u, 1u, 148u, 67u,
- 59u, 169u, 165u, 117u,
- 86u, 4u, 177u, 182u,
- 237u, 214u, 211u, 231u,
- 184u, 48u, 133u, 202u,
- 255u, 118u, 165u, 189u,
- 51u, 114u, 161u, 159u,
- 86u, 255u, 117u, 226u,
- 80u, 229u, 133u, 109u,
- 189u, 126u, 161u, 202u,
- 127u, 221u, 201u, 121u,
- 186u, 180u, 101u, 118u,
- 255u, 58u, 77u, 205u,
- 74u, 144u, 191u, 52u,
- 91u, 227u, 177u, 62u,
- 71u, 1u, 16u, 122u,
- 106u, 42u, 212u, 63u,
- 139u, 187u, 154u, 35u,
- 107u, 245u, 117u, 210u,
- 98u, 220u, 90u, 139u,
- 121u, 126u, 73u, 171u,
- 144u, 192u, 209u, 61u,
- 145u, 186u, 255u, 146u,
- 122u, 255u, 171u, 112u,
- 198u, 208u, 112u, 167u,
- 19u, 119u, 77u, 145u,
- 117u, 142u, 75u, 94u,
- 82u, 65u, 35u, 218u,
- 235u, 252u, 179u, 152u,
- 31u, 190u, 225u, 128u,
- 198u, 86u, 1u, 61u,
- 139u, 204u, 255u, 61u,
- 50u, 143u, 151u, 83u,
- 214u, 192u, 130u, 171u,
- 92u, 121u, 122u, 134u,
- 22u, 156u, 125u, 171u,
- 13u, 153u, 102u, 90u,
- 145u, 161u, 74u, 129u,
- 255u, 145u, 235u, 153u,
- 138u, 125u, 255u, 99u,
- 77u, 86u, 165u, 53u,
- 118u, 73u, 119u, 146u,
- 129u, 56u, 101u, 190u,
- 142u, 53u, 146u, 76u,
- 145u, 131u, 179u, 57u,
- 72u, 134u, 176u, 162u,
- 200u, 190u, 85u, 255u,
- 112u, 172u, 84u, 104u,
- 0u, 154u, 171u, 90u,
- 146u, 57u, 45u, 75u,
- 152u, 77u, 216u, 111u,
- 149u, 197u, 0u, 181u,
- 66u, 110u, 95u, 148u,
- 19u, 35u, 77u, 100u,
- 128u, 143u, 242u, 184u,
- 230u, 49u, 219u, 179u,
- 62u, 55u, 49u, 174u,
- 191u, 130u, 127u, 16u,
- 255u, 100u, 101u, 79u,
- 225u, 1u, 81u, 143u,
- 145u, 156u, 108u, 162u,
- 156u, 153u, 153u, 30u,
- 129u, 73u, 144u, 14u,
- 218u, 137u, 154u, 0u,
- 208u, 87u, 87u, 10u,
- 101u, 187u, 162u, 226u,
- 248u, 253u, 123u, 173u,
- 206u, 16u, 97u, 173u,
- 130u, 86u, 183u, 53u,
- 55u, 68u, 140u, 30u,
- 132u, 200u, 1u, 167u,
- 64u, 155u, 179u, 70u,
- 72u, 207u, 1u, 102u,
- 159u, 125u, 199u, 40u,
- 112u, 54u, 37u, 201u,
- 55u, 215u, 112u, 88u,
- 125u, 255u, 183u, 15u,
- 170u, 169u, 53u, 160u,
- 121u, 55u, 174u, 143u,
- 16u, 206u, 93u, 175u,
- 146u, 73u, 226u, 61u,
- 255u, 213u, 54u, 59u,
- 132u, 40u, 41u, 196u,
- 118u, 119u, 137u, 56u,
- 178u, 97u, 227u, 255u,
- 71u, 109u, 191u, 148u,
- 61u, 75u, 99u, 75u,
- 212u, 36u, 122u, 201u,
- 42u, 101u, 1u, 149u,
- 134u, 156u, 40u, 125u,
- 138u, 188u, 167u, 49u,
- 179u, 81u, 73u, 121u,
- 13u, 199u, 67u, 198u,
- 101u, 48u, 60u, 132u,
- 130u, 31u, 255u, 69u,
- 129u, 88u, 134u, 78u,
- 159u, 117u, 59u, 191u,
- 149u, 154u, 80u, 227u,
- 177u, 156u, 0u, 99u,
- 52u, 195u, 232u, 70u,
- 101u, 234u, 103u, 165u,
- 200u, 171u, 122u, 196u,
- 65u, 255u, 181u, 202u,
- 93u, 131u, 96u, 105u,
- 164u, 0u, 189u, 244u,
- 209u, 102u, 177u, 226u,
- 74u, 144u, 159u, 142u,
- 125u, 144u, 135u, 166u,
- 154u, 178u, 97u, 184u,
- 190u, 178u, 111u, 190u,
- 100u, 61u, 255u, 95u,
- 59u, 153u, 143u, 118u,
- 188u, 19u, 132u, 163u,
- 199u, 147u, 45u, 99u,
- 255u, 111u, 36u, 136u,
- 57u, 227u, 142u, 102u,
- 175u, 142u, 124u, 154u,
- 86u, 149u, 166u, 86u,
- 255u, 141u, 25u, 176u,
- 1u, 224u, 154u, 36u,
- 105u, 114u, 159u, 55u,
- 145u, 167u, 92u, 137u,
- 144u, 37u, 119u, 162u,
- 102u, 255u, 100u, 207u,
- 79u, 82u, 77u, 118u,
- 63u, 83u, 141u, 78u,
- 177u, 62u, 227u, 142u,
- 149u, 27u, 145u, 183u,
- 45u, 140u, 58u, 156u,
- 20u, 68u, 112u, 137u,
- 110u, 218u, 164u, 0u,
- 206u, 203u, 245u, 251u,
- 170u, 131u, 99u, 239u,
- 112u, 66u, 210u, 165u,
- 255u, 147u, 228u, 73u,
- 200u, 1u, 157u, 93u,
- 107u, 48u, 82u, 139u,
- 209u, 139u, 97u, 95u,
- 224u, 28u, 126u, 154u,
- 93u, 116u, 125u, 126u,
- 152u, 125u, 102u, 251u,
- 87u, 41u, 255u, 159u,
- 148u, 106u, 118u, 176u,
- 214u, 162u, 102u, 99u,
- 189u, 1u, 58u, 235u,
- 79u, 104u, 215u, 152u,
- 101u, 59u, 196u, 236u,
- 140u, 34u, 129u, 69u,
- 146u, 113u, 123u, 94u,
- 70u, 200u, 122u, 95u,
- 54u, 255u, 81u, 210u,
- 173u, 60u, 176u, 156u,
- 123u, 170u, 108u, 22u,
- 126u, 203u, 218u, 46u,
- 255u, 165u, 146u, 130u,
- 171u, 105u, 65u, 255u,
- 38u, 138u, 174u, 36u,
- 111u, 147u, 75u, 90u,
- 172u, 70u, 217u, 173u,
- 250u, 114u, 217u, 142u,
- 143u, 15u, 32u, 154u,
- 42u, 158u, 116u, 15u,
- 255u, 91u, 121u, 55u,
- 176u, 255u, 238u, 209u,
- 131u, 43u, 43u, 138u,
- 118u, 96u, 203u, 56u,
- 97u, 101u, 243u, 130u,
- 63u, 235u, 126u, 241u,
- 255u, 89u, 177u, 147u,
- 149u, 80u, 235u, 201u,
- 157u, 118u, 91u, 225u,
- 11u, 72u, 197u, 91u,
- 58u, 156u, 142u, 74u,
- 111u, 108u, 163u, 104u,
- 255u, 134u, 123u, 203u,
- 119u, 235u, 44u, 149u,
- 235u, 156u, 255u, 239u,
- 159u, 116u, 93u, 114u,
- 76u, 193u, 161u, 225u,
- 56u, 178u, 211u, 219u,
- 45u, 118u, 255u, 155u,
- 184u, 139u, 87u, 45u,
- 61u, 83u, 36u, 38u,
- 197u, 63u, 49u, 119u,
- 1u, 109u, 94u, 147u,
- 152u, 38u, 158u, 28u,
- 141u, 121u, 127u, 163u,
- 49u, 141u, 1u, 138u,
- 101u, 103u, 156u, 145u,
- 174u, 152u, 99u, 30u,
- 51u, 163u, 234u, 191u,
- 151u, 60u, 166u, 178u,
- 140u, 170u, 53u, 130u,
- 171u, 11u, 179u, 158u,
- 255u, 194u, 94u, 110u,
- 92u, 163u, 140u, 131u,
- 227u, 138u, 144u, 217u,
- 61u, 87u, 223u, 170u,
- 148u, 137u, 182u, 1u,
- 172u, 55u, 92u, 33u,
- 93u, 3u, 151u, 174u,
- 228u, 116u, 27u, 93u,
- 0u, 16u, 153u, 60u,
- 141u, 92u, 61u, 14u,
- 198u, 109u, 106u, 85u,
- 54u, 69u, 184u, 89u,
- 166u, 1u, 54u, 73u,
- 106u, 143u, 146u, 62u,
- 139u, 85u, 109u, 188u,
- 170u, 144u, 173u, 130u,
- 255u, 62u, 20u, 230u,
- 155u, 179u, 123u, 168u,
- 103u, 106u, 156u, 184u,
- 126u, 117u, 145u, 112u,
- 143u, 127u, 255u, 113u,
- 173u, 79u, 242u, 201u,
- 222u, 135u, 0u, 50u,
- 169u, 81u, 105u, 54u,
- 179u, 98u, 174u, 133u,
- 124u, 207u, 171u, 180u,
- 215u, 140u, 163u, 210u,
- 79u, 108u, 191u, 128u,
- 214u, 141u, 114u, 0u,
- 95u, 200u, 75u, 216u,
- 99u, 159u, 72u, 1u,
- 47u, 99u, 14u, 210u,
- 60u, 141u, 118u, 135u,
- 141u, 122u, 143u, 69u,
- 146u, 193u, 100u, 243u,
- 90u, 88u, 157u, 99u,
- 144u, 177u, 76u, 0u,
- 148u, 115u, 111u, 202u,
- 129u, 126u, 99u, 150u,
- 129u, 196u, 114u, 109u,
- 97u, 144u, 255u, 113u,
- 76u, 141u, 144u, 192u,
- 79u, 117u, 130u, 98u,
- 115u, 160u, 157u, 67u,
- 255u, 105u, 146u, 150u,
- 107u, 162u, 203u, 102u,
- 85u, 198u, 173u, 177u,
- 255u, 141u, 250u, 54u,
- 194u, 158u, 180u, 237u,
- 84u, 102u, 135u, 185u,
- 101u, 1u, 160u, 242u,
- 119u, 205u, 98u, 78u,
- 208u, 61u, 116u, 48u,
- 121u, 166u, 43u, 97u,
- 81u, 111u, 89u, 1u,
- 129u, 115u, 55u, 135u,
- 111u, 202u, 134u, 174u,
- 99u, 201u, 148u, 177u,
- 236u, 1u, 99u, 91u,
- 119u, 135u, 147u, 50u,
- 150u, 195u, 115u, 146u,
- 117u, 84u, 90u, 78u,
- 51u, 185u, 139u, 82u,
- 213u, 112u, 55u, 106u,
- 1u, 127u, 107u, 251u,
- 107u, 145u, 198u, 255u,
- 160u, 72u, 167u, 157u,
- 144u, 229u, 83u, 121u,
- 111u, 135u, 160u, 110u,
- 201u, 81u, 90u, 141u,
- 124u, 1u, 199u, 183u,
- 100u, 118u, 187u, 164u,
- 199u, 178u, 132u, 108u,
- 213u, 32u, 136u, 104u,
- 95u, 1u, 156u, 74u,
- 35u, 163u, 139u, 79u,
- 145u, 203u, 147u, 47u,
- 53u, 90u, 15u, 120u,
- 72u, 154u, 123u, 1u,
- 157u, 162u, 61u, 70u,
- 44u, 82u, 53u, 221u,
- 136u, 119u, 231u, 101u,
- 108u, 114u, 107u, 172u,
- 96u, 135u, 160u, 1u,
- 234u, 132u, 222u, 133u,
- 119u, 40u, 1u, 184u,
- 172u, 188u, 130u, 208u,
- 10u, 203u, 170u, 88u,
- 154u, 92u, 178u, 47u,
- 98u, 69u, 145u, 193u,
- 61u, 110u, 77u, 171u,
- 128u, 107u, 105u, 113u,
- 98u, 115u, 170u, 1u,
- 162u, 117u, 178u, 221u,
- 81u, 173u, 135u, 120u,
- 129u, 130u, 164u, 153u,
- 195u, 154u, 255u, 137u,
- 169u, 166u, 106u, 255u,
- 176u, 109u, 147u, 156u,
- 150u, 113u, 97u, 81u,
- 129u, 181u, 163u, 202u,
- 87u, 211u, 174u, 191u,
- 87u, 141u, 53u, 29u,
- 91u, 143u, 255u, 138u,
- 146u, 86u, 110u, 117u,
- 87u, 179u, 107u, 223u,
- 62u, 159u, 100u, 171u,
- 50u, 43u, 215u, 95u,
- 134u, 193u, 169u, 0u,
- 83u, 103u, 188u, 116u,
- 157u, 136u, 139u, 30u,
- 158u, 255u, 148u, 128u,
- 18u, 176u, 75u, 112u,
- 173u, 255u, 175u, 125u,
- 167u, 24u, 118u, 151u,
- 227u, 153u, 57u, 164u,
- 98u, 156u, 125u, 67u,
- 130u, 101u, 95u, 31u,
- 231u, 241u, 99u, 184u,
- 39u, 69u, 62u, 161u,
- 113u, 255u, 51u, 85u,
- 94u, 153u, 100u, 126u,
- 42u, 90u, 139u, 255u,
- 124u, 106u, 173u, 66u,
- 165u, 99u, 124u, 109u,
- 53u, 163u, 129u, 56u,
- 206u, 184u, 255u, 195u,
- 129u, 32u, 123u, 229u,
- 154u, 21u, 114u, 112u,
- 104u, 155u, 194u, 139u,
- 169u, 152u, 156u, 120u,
- 123u, 191u, 118u, 115u,
- 84u, 147u, 1u, 92u,
- 62u, 99u, 183u, 70u,
- 218u, 59u, 104u, 1u,
- 79u, 162u, 122u, 107u,
- 83u, 113u, 88u, 93u,
- 115u, 105u, 107u, 134u,
- 255u, 180u, 117u, 131u,
- 60u, 46u, 116u, 56u,
- 116u, 88u, 74u, 66u,
- 75u, 128u, 35u, 215u,
- 70u, 255u, 174u, 102u,
- 89u, 100u, 98u, 178u,
- 135u, 148u, 154u, 107u,
- 30u, 8u, 98u, 166u,
- 170u, 102u, 150u, 1u,
- 24u, 129u, 202u, 223u,
- 204u, 125u, 217u, 82u,
- 127u, 161u, 106u, 201u,
- 178u, 155u, 101u, 255u,
- 155u, 100u, 187u, 171u,
- 225u, 175u, 100u, 143u,
- 154u, 85u, 150u, 97u,
- 142u, 147u, 52u, 168u,
- 154u, 172u, 191u, 82u,
- 1u, 126u, 56u, 218u,
- 169u, 102u, 106u, 130u,
- 120u, 181u, 195u, 11u,
- 1u, 42u, 195u, 42u,
- 183u, 120u, 115u, 147u,
- 115u, 191u, 149u, 50u,
- 255u, 125u, 69u, 146u,
- 111u, 87u, 120u, 166u,
- 135u, 210u, 206u, 63u,
- 121u, 156u, 172u, 123u,
- 102u, 79u, 89u, 94u,
- 18u, 165u, 198u, 97u,
- 163u, 43u, 0u, 71u,
- 178u, 215u, 120u, 33u,
- 238u, 176u, 191u, 245u,
- 113u, 183u, 219u, 58u,
- 70u, 204u, 178u, 1u,
- 124u, 114u, 132u, 125u,
- 111u, 0u, 145u, 168u,
- 193u, 150u, 29u, 61u,
- 106u, 170u, 207u, 224u,
- 70u, 182u, 98u, 15u,
- 154u, 216u, 0u, 97u,
- 122u, 120u, 92u, 134u,
- 98u, 118u, 41u, 105u,
- 75u, 90u, 56u, 117u,
- 164u, 147u, 136u, 104u,
- 112u, 138u, 63u, 107u,
- 255u, 125u, 255u, 145u,
- 180u, 116u, 219u, 106u,
- 191u, 142u, 76u, 86u,
- 232u, 0u, 143u, 182u,
- 158u, 67u, 155u, 37u,
- 183u, 99u, 88u, 94u,
- 165u, 65u, 97u, 166u,
- 118u, 115u, 144u, 146u,
- 164u, 1u, 148u, 143u,
- 73u, 180u, 222u, 227u,
- 118u, 86u, 0u, 91u,
- 176u, 160u, 245u, 71u,
- 250u, 56u, 214u, 69u,
- 153u, 179u, 168u, 158u,
- 162u, 68u, 125u, 134u,
- 136u, 111u, 87u, 199u,
- 165u, 124u, 76u, 1u,
- 180u, 171u, 255u, 179u,
- 110u, 48u, 226u, 1u,
- 245u, 114u, 155u, 26u,
- 144u, 133u, 183u, 222u,
- 126u, 29u, 123u, 58u,
- 53u, 59u, 27u, 1u,
- 101u, 155u, 196u, 22u,
- 158u, 253u, 154u, 130u,
- 147u, 176u, 153u, 186u,
- 147u, 122u, 99u, 106u,
- 200u, 105u, 1u, 150u,
- 198u, 111u, 81u, 76u,
- 37u, 123u, 141u, 194u,
- 169u, 100u, 121u, 99u,
- 135u, 125u, 171u, 115u,
- 144u, 172u, 1u, 162u,
- 77u, 143u, 82u, 66u,
- 181u, 163u, 185u, 131u,
- 212u, 172u, 255u, 212u,
- 230u, 85u, 115u, 127u,
- 155u, 150u, 186u, 207u,
- 121u, 154u, 141u, 224u,
- 94u, 108u, 83u, 136u,
- 126u, 167u, 176u, 1u,
- 163u, 122u, 138u, 96u,
- 177u, 151u, 146u, 189u,
- 255u, 66u, 230u, 85u,
- 49u, 101u, 77u, 160u,
- 174u, 152u, 133u, 165u,
- 140u, 98u, 109u, 80u,
- 148u, 199u, 146u, 151u,
- 210u, 255u, 168u, 68u,
- 1u, 107u, 43u, 177u,
- 63u, 72u, 117u, 118u,
- 174u, 174u, 69u, 143u,
- 233u, 79u, 192u, 96u,
- 181u, 1u, 123u, 84u,
- 179u, 244u, 92u, 174u,
- 127u, 147u, 225u, 68u,
- 160u, 139u, 164u, 184u,
- 232u, 246u, 241u, 96u,
- 52u, 135u, 211u, 58u,
- 184u, 189u, 137u, 96u,
- 191u, 69u, 255u, 183u,
- 255u, 72u, 194u, 111u,
- 78u, 137u, 161u, 126u,
- 116u, 116u, 140u, 58u,
- 134u, 107u, 83u, 16u,
- 80u, 81u, 159u, 153u,
- 255u, 136u, 147u, 179u,
- 86u, 179u, 70u, 109u,
- 132u, 169u, 119u, 76u,
- 85u, 221u, 77u, 168u,
- 115u, 160u, 87u, 140u,
- 148u, 255u, 96u, 50u,
- 223u, 107u, 196u, 154u,
- 173u, 96u, 124u, 16u,
- 205u, 1u, 110u, 119u,
- 203u, 201u, 215u, 44u,
- 150u, 129u, 104u, 97u,
- 145u, 252u, 236u, 109u,
- 23u, 131u, 118u, 1u,
- 197u, 139u, 173u, 99u,
- 205u, 175u, 151u, 146u,
- 114u, 134u, 1u, 197u,
- 92u, 117u, 164u, 162u,
- 203u, 128u, 117u, 97u,
- 118u, 37u, 171u, 88u,
- 39u, 136u, 188u, 126u,
- 71u, 122u, 23u, 226u,
- 255u, 209u, 72u, 105u,
- 120u, 96u, 148u, 162u,
- 105u, 255u, 235u, 217u,
- 86u, 194u, 140u, 163u,
- 211u, 159u, 28u, 109u,
- 224u, 56u, 216u, 41u,
- 255u, 139u, 113u, 117u,
- 123u, 50u, 41u, 202u,
- 118u, 176u, 138u, 87u,
- 142u, 126u, 221u, 140u,
- 179u, 148u, 138u, 0u,
- 120u, 88u, 162u, 20u,
- 80u, 170u, 151u, 112u,
- 191u, 65u, 182u, 159u,
- 164u, 215u, 47u, 208u,
- 220u, 162u, 91u, 177u,
- 63u, 226u, 1u, 205u,
- 5u, 175u, 100u, 90u,
- 67u, 255u, 217u, 130u,
- 175u, 126u, 250u, 251u,
- 85u, 37u, 40u, 182u,
- 252u, 22u, 114u, 107u,
- 163u, 148u, 254u, 56u,
- 153u, 76u, 0u, 205u,
- 176u, 122u, 154u, 64u,
- 86u, 102u, 176u, 114u,
- 31u, 181u, 115u, 68u,
- 52u, 37u, 71u, 166u,
- 105u, 93u, 69u, 164u,
- 175u, 35u, 68u, 1u,
- 12u, 132u, 179u, 97u,
- 106u, 255u, 133u, 235u,
- 126u, 108u, 172u, 117u,
- 118u, 29u, 171u, 202u,
- 159u, 191u, 209u, 81u,
- 181u, 181u, 244u, 178u,
- 153u, 47u, 177u, 130u,
- 136u, 100u, 189u, 1u,
- 112u, 157u, 165u, 162u,
- 61u, 190u, 254u, 58u,
- 72u, 127u, 255u, 235u,
- 174u, 28u, 134u, 91u,
- 242u, 57u, 138u, 192u,
- 119u, 200u, 43u, 255u,
- 76u, 130u, 183u, 149u,
- 175u, 71u, 83u, 76u,
- 114u, 70u, 118u, 255u,
- 4u, 177u, 196u, 50u,
- 134u, 186u, 104u, 180u,
- 93u, 8u, 185u, 117u,
- 62u, 49u, 144u, 101u,
- 149u, 97u, 169u, 1u,
- 65u, 178u, 72u, 96u,
- 78u, 202u, 149u, 55u,
- 68u, 119u, 177u, 171u,
- 30u, 141u, 243u, 66u,
- 140u, 123u, 231u, 115u,
- 179u, 57u, 255u, 110u,
- 131u, 77u, 191u, 212u,
- 255u, 156u, 141u, 135u,
- 89u, 100u, 179u, 95u,
- 100u, 187u, 143u, 52u,
- 61u, 163u, 200u, 143u,
- 196u, 121u, 115u, 121u,
- 72u, 231u, 213u, 174u,
- 255u, 168u, 164u, 50u,
- 124u, 30u, 216u, 105u,
- 8u, 53u, 37u, 42u,
- 11u, 83u, 181u, 191u,
- 255u, 98u, 34u, 81u,
- 72u, 157u, 49u, 101u,
- 80u, 205u, 135u, 1u,
- 198u, 206u, 161u, 93u,
- 129u, 125u, 145u, 206u,
- 127u, 108u, 189u, 148u,
- 111u, 114u, 28u, 33u,
- 108u, 161u, 88u, 149u,
- 40u, 255u, 132u, 62u,
- 90u, 215u, 128u, 77u,
- 159u, 173u, 111u, 126u,
- 107u, 51u, 73u, 143u,
- 178u, 189u, 58u, 255u,
- 255u, 24u, 179u, 76u,
- 113u, 106u, 75u, 182u,
- 125u, 144u, 154u, 104u,
- 134u, 132u, 206u, 76u,
- 146u, 207u, 167u, 100u,
- 232u, 54u, 184u, 135u,
- 147u, 44u, 84u, 77u,
- 195u, 255u, 231u, 223u,
- 100u, 141u, 149u, 136u,
- 104u, 204u, 199u, 144u,
- 121u, 132u, 46u, 206u,
- 12u, 255u, 217u, 75u,
- 134u, 41u, 137u, 28u,
- 114u, 133u, 74u, 222u,
- 102u, 255u, 209u, 22u,
- 250u, 125u, 187u, 128u,
- 87u, 158u, 112u, 103u,
- 159u, 98u, 245u, 57u,
- 108u, 184u, 136u, 127u,
- 113u, 74u, 1u, 153u,
- 255u, 145u, 180u, 100u,
- 161u, 204u, 126u, 60u,
- 199u, 222u, 49u, 99u,
- 55u, 132u, 88u, 114u,
- 114u, 217u, 99u, 157u,
- 139u, 113u, 219u, 93u,
- 110u, 85u, 123u, 101u,
- 152u, 76u, 0u, 65u,
- 195u, 219u, 141u, 114u,
- 104u, 127u, 110u, 104u,
- 123u, 140u, 60u, 66u,
- 97u, 58u, 255u, 129u,
- 141u, 232u, 163u, 161u,
- 198u, 130u, 121u, 214u,
- 11u, 14u, 202u, 178u,
- 215u, 91u, 110u, 1u,
- 186u, 75u, 89u, 74u,
- 40u, 255u, 43u, 245u,
- 229u, 123u, 38u, 99u,
- 41u, 131u, 137u, 181u,
- 109u, 143u, 153u, 131u,
- 115u, 151u, 109u, 49u,
- 215u, 216u, 255u, 107u,
- 134u, 83u, 164u, 104u,
- 46u, 87u, 45u, 234u,
- 180u, 164u, 47u, 199u,
- 1u, 35u, 234u, 133u,
- 156u, 196u, 159u, 9u,
- 29u, 84u, 223u, 127u,
- 1u, 143u, 144u, 110u,
- 65u, 124u, 233u, 210u,
- 115u, 97u, 111u, 36u,
- 242u, 255u, 87u, 84u,
- 210u, 134u, 170u, 27u,
- 255u, 134u, 60u, 158u,
- 168u, 50u, 149u, 209u,
- 255u, 193u, 83u, 65u,
- 113u, 97u, 175u, 20u,
- 72u, 94u, 213u, 87u,
- 237u, 157u, 117u, 123u,
- 116u, 191u, 95u, 118u,
- 106u, 94u, 112u, 178u,
- 1u, 136u, 179u, 102u,
- 83u, 233u, 69u, 173u,
- 91u, 148u, 171u, 106u,
- 114u, 112u, 184u, 99u,
- 194u, 255u, 131u, 133u,
- 125u, 185u, 211u, 133u,
- 93u, 141u, 211u, 182u,
- 9u, 111u, 115u, 114u,
- 134u, 1u, 157u, 143u,
- 108u, 63u, 49u, 126u,
- 246u, 151u, 197u, 139u,
- 95u, 92u, 1u, 193u,
- 156u, 124u, 105u, 91u,
- 122u, 140u, 130u, 166u,
- 107u, 151u, 150u, 147u,
- 1u, 114u, 154u, 82u,
- 96u, 101u, 156u, 66u,
- 184u, 24u, 25u, 157u,
- 161u, 71u, 155u, 220u,
- 127u, 138u, 97u, 155u,
- 98u, 99u, 67u, 70u,
- 140u, 100u, 1u, 91u,
- 141u, 88u, 177u, 135u,
- 198u, 94u, 26u, 198u,
- 58u, 158u, 52u, 217u,
- 105u, 174u, 255u, 92u,
- 113u, 82u, 138u, 201u,
- 236u, 176u, 175u, 74u,
- 161u, 196u, 64u, 99u,
- 58u, 176u, 1u, 65u,
- 115u, 207u, 26u, 146u,
- 214u, 255u, 47u, 210u,
- 143u, 57u, 215u, 212u,
- 97u, 146u, 129u, 75u,
- 175u, 119u, 32u, 144u,
- 222u, 112u, 184u, 102u,
- 66u, 177u, 78u, 17u,
- 0u, 122u, 177u, 106u,
- 204u, 12u, 0u, 17u,
- 103u, 228u, 118u, 242u,
- 173u, 224u, 75u, 65u,
- 97u, 107u, 187u, 147u,
- 83u, 151u, 108u, 1u,
- 156u, 112u, 182u, 132u,
- 251u, 72u, 114u, 117u,
- 77u, 119u, 98u, 137u,
- 42u, 124u, 145u, 171u,
- 218u, 85u, 229u, 132u,
- 255u, 123u, 3u, 14u,
- 126u, 111u, 106u, 157u,
- 85u, 103u, 197u, 87u,
- 158u, 131u, 139u, 152u,
- 46u, 144u, 167u, 139u,
- 103u, 163u, 1u, 214u,
- 146u, 164u, 78u, 132u,
- 96u, 144u, 145u, 255u,
- 112u, 144u, 107u, 73u,
- 152u, 120u, 117u, 95u,
- 80u, 198u, 54u, 74u,
- 204u, 82u, 102u, 196u,
- 28u, 50u, 169u, 158u,
- 1u, 137u, 120u, 43u,
- 1u, 173u, 170u, 70u,
- 157u, 152u, 140u, 45u,
- 176u, 165u, 71u, 156u,
- 125u, 63u, 123u, 91u,
- 136u, 186u, 168u, 215u,
- 86u, 148u, 82u, 73u,
- 91u, 69u, 120u, 79u,
- 184u, 255u, 64u, 188u,
- 203u, 35u, 221u, 72u,
- 153u, 0u, 201u, 170u,
- 142u, 136u, 227u, 65u,
- 245u, 111u, 111u, 118u,
- 144u, 243u, 1u, 187u,
- 71u, 234u, 31u, 122u,
- 150u, 82u, 130u, 64u,
- 115u, 6u, 249u, 188u,
- 86u, 136u, 170u, 119u,
- 98u, 76u, 255u, 144u,
- 74u, 17u, 81u, 152u,
- 133u, 10u, 13u, 58u,
- 95u, 75u, 189u, 96u,
- 139u, 142u, 128u, 120u,
- 1u, 117u, 139u, 95u,
- 177u, 90u, 167u, 94u,
- 160u, 126u, 121u, 1u,
- 110u, 130u, 75u, 107u,
- 142u, 226u, 153u, 35u,
- 110u, 121u, 142u, 120u,
- 210u, 186u, 207u, 91u,
- 91u, 141u, 43u, 1u,
- 185u, 149u, 92u, 106u,
- 93u, 153u, 87u, 135u,
- 197u, 157u, 0u, 200u,
- 85u, 155u, 157u, 204u,
- 139u, 61u, 137u, 45u,
- 86u, 62u, 148u, 224u,
- 182u, 192u, 136u, 255u,
- 128u, 87u, 88u, 80u,
- 122u, 98u, 96u, 164u,
- 180u, 103u, 192u, 170u,
- 84u, 185u, 8u, 159u,
- 110u, 146u, 151u, 182u,
- 113u, 0u, 74u, 138u,
- 164u, 147u, 158u, 176u,
- 208u, 147u, 171u, 166u,
- 114u, 206u, 17u, 50u,
- 78u, 71u, 111u, 255u,
- 80u, 108u, 153u, 145u,
- 142u, 236u, 188u, 54u,
- 27u, 127u, 192u, 77u,
- 159u, 67u, 212u, 151u,
- 239u, 31u, 168u, 255u,
- 112u, 99u, 106u, 190u,
- 96u, 166u, 46u, 145u,
- 79u, 132u, 160u, 107u,
- 136u, 123u, 255u, 93u,
- 139u, 97u, 95u, 154u,
- 144u, 138u, 121u, 136u,
- 1u, 139u, 109u, 183u,
- 62u, 186u, 124u, 109u,
- 100u, 10u, 99u, 219u,
- 159u, 96u, 204u, 111u,
- 1u, 136u, 136u, 74u,
- 155u, 205u, 27u, 138u,
- 176u, 140u, 235u, 1u,
- 162u, 84u, 174u, 184u,
- 151u, 71u, 163u, 110u,
- 187u, 65u, 95u, 168u,
- 87u, 159u, 1u, 108u,
- 134u, 150u, 38u, 90u,
- 65u, 75u, 0u, 208u,
- 113u, 173u, 198u, 136u,
- 154u, 191u, 52u, 100u,
- 255u, 212u, 201u, 170u,
- 89u, 53u, 104u, 167u,
- 33u, 80u, 141u, 119u,
- 35u, 206u, 122u, 107u,
- 116u, 118u, 255u, 79u,
- 212u, 173u, 160u, 86u,
- 184u, 108u, 69u, 78u,
- 146u, 1u, 166u, 177u,
- 105u, 31u, 202u, 71u,
- 136u, 203u, 53u, 37u,
- 183u, 79u, 155u, 2u,
- 178u, 83u, 147u, 59u,
- 207u, 162u, 121u, 98u,
- 61u, 99u, 165u, 88u,
- 219u, 110u, 1u, 64u,
- 139u, 128u, 102u, 130u,
- 108u, 206u, 123u, 129u,
- 195u, 181u, 179u, 148u,
- 255u, 73u, 150u, 185u,
- 114u, 88u, 125u, 199u,
- 111u, 44u, 100u, 255u,
- 220u, 188u, 65u, 79u,
- 106u, 104u, 49u, 121u,
- 186u, 189u, 74u, 81u,
- 65u, 142u, 194u, 255u,
- 148u, 126u, 202u, 89u,
- 96u, 149u, 223u, 126u,
- 144u, 104u, 86u, 209u,
- 65u, 255u, 164u, 72u,
- 117u, 148u, 191u, 131u,
- 91u, 72u, 114u, 118u,
- 0u, 70u, 98u, 48u,
- 171u, 65u, 211u, 199u,
- 76u, 255u, 235u, 67u,
- 138u, 133u, 190u, 109u,
- 175u, 165u, 175u, 255u,
- 146u, 216u, 51u, 178u,
- 156u, 30u, 174u, 181u,
- 156u, 124u, 181u, 52u,
- 29u, 115u, 138u, 184u,
- 59u, 153u, 128u, 200u,
- 89u, 184u, 116u, 255u,
- 125u, 172u, 219u, 101u,
- 11u, 176u, 109u, 255u,
- 52u, 118u, 246u, 115u,
- 163u, 168u, 97u, 193u,
- 118u, 31u, 59u, 124u,
- 138u, 76u, 226u, 255u,
- 224u, 88u, 74u, 155u,
- 88u, 166u, 52u, 153u,
- 148u, 94u, 102u, 146u,
- 36u, 102u, 83u, 222u,
- 74u, 255u, 151u, 250u,
- 211u, 131u, 105u, 108u,
- 161u, 138u, 115u, 73u,
- 122u, 25u, 145u, 119u,
- 1u, 38u, 71u, 1u,
- 165u, 106u, 86u, 135u,
- 190u, 137u, 87u, 140u,
- 66u, 135u, 120u, 91u,
- 38u, 112u, 213u, 46u,
- 132u, 84u, 195u, 96u,
- 165u, 219u, 255u, 218u,
- 149u, 86u, 75u, 115u,
- 74u, 227u, 145u, 208u,
- 73u, 60u, 94u, 175u,
- 1u, 166u, 158u, 75u,
- 117u, 84u, 1u, 128u,
- 104u, 51u, 86u, 216u,
- 161u, 155u, 135u, 104u,
- 147u, 170u, 98u, 125u,
- 166u, 214u, 198u, 134u,
- 153u, 104u, 72u, 255u,
- 137u, 138u, 72u, 77u,
- 5u, 155u, 12u, 169u,
- 128u, 122u, 195u, 63u,
- 152u, 106u, 89u, 110u,
- 19u, 102u, 145u, 90u,
- 99u, 27u, 91u, 1u,
- 41u, 218u, 87u, 198u,
- 107u, 217u, 66u, 104u,
- 99u, 50u, 159u, 97u,
- 138u, 112u, 55u, 1u,
- 150u, 1u, 176u, 81u,
- 197u, 67u, 120u, 115u,
- 85u, 158u, 123u, 35u,
- 194u, 114u, 229u, 186u,
- 30u, 51u, 1u, 123u,
- 5u, 67u, 128u, 103u,
- 106u, 112u, 138u, 115u,
- 108u, 187u, 145u, 199u,
- 255u, 154u, 46u, 22u,
- 136u, 117u, 11u, 169u,
- 148u, 113u, 156u, 126u,
- 130u, 89u, 140u, 105u,
- 125u, 91u, 116u, 138u,
- 124u, 112u, 255u, 232u,
- 163u, 52u, 168u, 165u,
- 89u, 140u, 119u, 163u,
- 125u, 93u, 117u, 142u,
- 16u, 164u, 95u, 170u,
- 0u, 131u, 68u, 172u,
- 180u, 241u, 158u, 168u,
- 104u, 255u, 32u, 88u,
- 121u, 93u, 97u, 132u,
- 135u, 112u, 46u, 70u,
- 142u, 140u, 134u, 102u,
- 217u, 153u, 222u, 155u,
- 67u, 93u, 106u, 98u,
- 100u, 23u, 152u, 173u,
- 210u, 171u, 255u, 120u,
- 151u, 99u, 155u, 72u,
- 143u, 94u, 98u, 102u,
- 1u, 178u, 125u, 90u,
- 84u, 157u, 81u, 112u,
- 193u, 140u, 197u, 95u,
- 136u, 24u, 110u, 123u,
- 105u, 169u, 73u, 161u,
- 5u, 153u, 255u, 79u,
- 76u, 240u, 82u, 27u,
- 239u, 246u, 205u, 255u,
- 37u, 159u, 118u, 217u,
- 111u, 138u, 54u, 197u,
- 201u, 161u, 214u, 67u,
- 90u, 238u, 107u, 155u,
- 35u, 1u, 97u, 217u,
- 71u, 43u, 179u, 148u,
- 1u, 192u, 125u, 65u,
- 126u, 102u, 102u, 93u,
- 128u, 142u, 115u, 55u,
- 100u, 166u, 121u, 131u,
- 69u, 159u, 75u, 109u,
- 133u, 255u, 99u, 134u,
- 96u, 66u, 135u, 14u,
- 89u, 13u, 80u, 214u,
- 24u, 169u, 119u, 145u,
- 204u, 255u, 136u, 73u,
- 131u, 86u, 156u, 180u,
- 25u, 120u, 93u, 91u,
- 98u, 130u, 67u, 159u,
- 129u, 214u, 139u, 70u,
- 213u, 119u, 1u, 181u,
- 164u, 98u, 30u, 102u,
- 78u, 138u, 108u, 223u,
- 121u, 217u, 133u, 255u,
- 113u, 59u, 159u, 188u,
- 151u, 158u, 102u, 95u,
- 249u, 125u, 163u, 64u,
- 156u, 107u, 132u, 106u,
- 188u, 125u, 182u, 5u,
- 172u, 151u, 99u, 255u,
- 139u, 67u, 213u, 139u,
- 22u, 113u, 239u, 0u,
- 68u, 60u, 189u, 4u,
- 37u, 214u, 112u, 136u,
- 166u, 193u, 12u, 166u,
- 7u, 239u, 127u, 181u,
- 212u, 36u, 19u, 189u,
- 1u, 179u, 236u, 95u,
- 134u, 140u, 22u, 183u,
- 104u, 186u, 74u, 255u,
- 7u, 13u, 140u, 158u,
- 2u, 212u, 80u, 114u,
- 60u, 7u, 138u, 241u,
- 133u, 97u, 167u, 178u,
- 163u, 174u, 120u, 144u,
- 108u, 255u, 95u, 144u,
- 124u, 219u, 1u, 17u,
- 220u, 145u, 103u, 79u,
- 112u, 145u, 22u, 164u,
- 75u, 162u, 102u, 243u,
- 72u, 43u, 104u, 236u,
- 117u, 155u, 121u, 195u,
- 187u, 107u, 135u, 77u,
- 58u, 152u, 1u, 121u,
- 107u, 169u, 191u, 5u,
- 169u, 76u, 186u, 151u,
- 181u, 255u, 96u, 171u,
- 184u, 165u, 117u, 118u,
- 112u, 179u, 214u, 73u,
- 31u, 206u, 111u, 127u,
- 148u, 57u, 149u, 143u,
- 0u, 12u, 151u, 93u,
- 150u, 163u, 159u, 140u,
- 1u, 131u, 159u, 74u,
- 198u, 61u, 114u, 163u,
- 109u, 169u, 173u, 118u,
- 134u, 211u, 112u, 137u,
- 177u, 118u, 102u, 91u,
- 104u, 154u, 174u, 114u,
- 70u, 80u, 0u, 155u,
- 162u, 65u, 254u, 242u,
- 4u, 162u, 44u, 177u,
- 1u, 86u, 221u, 238u,
- 131u, 160u, 230u, 138u,
- 218u, 154u, 152u, 47u,
- 48u, 40u, 100u, 139u,
- 111u, 129u, 108u, 134u,
- 146u, 118u, 58u, 255u,
- 100u, 89u, 116u, 157u,
- 199u, 70u, 146u, 129u,
- 160u, 221u, 168u, 42u,
- 255u, 78u, 185u, 94u,
- 82u, 161u, 116u, 215u,
- 82u, 56u, 46u, 104u,
- 3u, 189u, 255u, 247u,
- 115u, 132u, 122u, 201u,
- 201u, 40u, 232u, 33u,
- 181u, 48u, 140u, 104u,
- 122u, 124u, 62u, 112u,
- 143u, 255u, 66u, 80u,
- 142u, 85u, 187u, 88u,
- 150u, 147u, 170u, 130u,
- 1u, 96u, 170u, 111u,
- 129u, 156u, 71u, 171u,
- 125u, 207u, 135u, 82u,
- 106u, 152u, 63u, 104u,
- 229u, 170u, 147u, 200u,
- 59u, 141u, 1u, 219u,
- 137u, 78u, 19u, 64u,
- 165u, 79u, 111u, 255u,
- 23u, 30u, 109u, 145u,
- 109u, 167u, 100u, 147u,
- 70u, 164u, 179u, 84u,
- 1u, 69u, 184u, 142u,
- 134u, 72u, 128u, 181u,
- 116u, 94u, 245u, 115u,
- 90u, 153u, 107u, 149u,
- 139u, 66u, 111u, 145u,
- 130u, 112u, 161u, 110u,
- 167u, 115u, 97u, 255u,
- 162u, 70u, 255u, 168u,
- 137u, 179u, 174u, 67u,
- 249u, 253u, 67u, 126u,
- 230u, 227u, 246u, 240u,
- 32u, 157u, 159u, 50u,
- 147u, 154u, 75u, 28u,
- 83u, 186u, 111u, 101u,
- 203u, 1u, 156u, 159u,
- 112u, 236u, 68u, 216u,
- 102u, 155u, 167u, 139u,
- 142u, 100u, 1u, 163u,
- 80u, 82u, 107u, 143u,
- 1u, 85u, 151u, 221u,
- 181u, 182u, 160u, 29u,
- 124u, 17u, 133u, 211u,
- 116u, 188u, 138u, 123u,
- 125u, 255u, 135u, 122u,
- 145u, 60u, 146u, 186u,
- 111u, 165u, 113u, 188u,
- 146u, 229u, 201u, 111u,
- 59u, 115u, 62u, 255u,
- 41u, 137u, 150u, 111u,
- 99u, 123u, 230u, 172u,
- 207u, 134u, 177u, 58u,
- 139u, 120u, 144u, 94u,
- 134u, 170u, 173u, 69u,
- 255u, 112u, 154u, 152u,
- 153u, 159u, 139u, 41u,
- 220u, 255u, 189u, 170u,
- 174u, 199u, 140u, 40u,
- 179u, 177u, 209u, 196u,
- 193u, 201u, 179u, 41u,
- 115u, 60u, 144u, 159u,
- 123u, 191u, 116u, 96u,
- 1u, 171u, 163u, 142u,
- 136u, 197u, 127u, 45u,
- 150u, 1u, 246u, 139u,
- 88u, 35u, 191u, 187u,
- 244u, 157u, 24u, 66u,
- 66u, 124u, 59u, 143u,
- 242u, 173u, 173u, 142u,
- 127u, 200u, 163u, 245u,
- 177u, 111u, 104u, 229u,
- 98u, 38u, 1u, 166u,
- 159u, 138u, 138u, 135u,
- 91u, 162u, 82u, 150u,
- 146u, 155u, 136u, 231u,
- 89u, 111u, 255u, 40u,
- 121u, 175u, 142u, 255u,
- 71u, 3u, 183u, 138u,
- 84u, 102u, 133u, 89u,
- 222u, 186u, 82u, 213u,
- 37u, 158u, 215u, 211u,
- 48u, 46u, 87u, 1u,
- 217u, 148u, 196u, 160u,
- 154u, 183u, 12u, 115u,
- 122u, 98u, 131u, 213u,
- 169u, 105u, 105u, 142u,
- 0u, 250u, 227u, 121u,
- 153u, 130u, 220u, 98u,
- 160u, 141u, 217u, 81u,
- 60u, 155u, 1u, 69u,
- 59u, 48u, 158u, 73u,
- 177u, 111u, 186u, 184u,
- 158u, 150u, 99u, 152u,
- 125u, 110u, 115u, 157u,
- 124u, 120u, 194u, 151u,
- 121u, 255u, 149u, 172u,
- 180u, 188u, 129u, 134u,
- 154u, 1u, 122u, 152u,
- 139u, 37u, 152u, 197u,
- 193u, 70u, 175u, 97u,
- 147u, 203u, 1u, 79u,
- 133u, 158u, 115u, 68u,
- 160u, 120u, 72u, 114u,
- 54u, 128u, 233u, 142u,
- 167u, 178u, 164u, 106u,
- 224u, 134u, 192u, 131u,
- 0u, 12u, 173u, 114u,
- 255u, 159u, 83u, 140u,
- 112u, 4u, 1u, 100u,
- 109u, 130u, 170u, 73u,
- 176u, 141u, 66u, 208u,
- 139u, 115u, 117u, 146u,
- 78u, 27u, 103u, 156u,
- 1u, 52u, 51u, 112u,
- 203u, 176u, 127u, 152u,
- 17u, 182u, 143u, 251u,
- 190u, 126u, 248u, 140u,
- 135u, 120u, 229u, 255u,
- 220u, 226u, 194u, 211u,
- 49u, 227u, 134u, 93u,
- 236u, 119u, 172u, 46u,
- 155u, 254u, 165u, 161u,
- 68u, 249u, 0u, 200u,
- 31u, 250u, 174u, 35u,
- 113u, 187u, 173u, 157u,
- 148u, 114u, 42u, 129u,
- 162u, 140u, 133u, 162u,
- 108u, 59u, 77u, 255u,
- 84u, 121u, 83u, 129u,
- 155u, 154u, 115u, 162u,
- 173u, 150u, 99u, 146u,
- 89u, 67u, 255u, 65u,
- 169u, 107u, 146u, 77u,
- 118u, 157u, 140u, 200u,
- 68u, 61u, 187u, 93u,
- 73u, 0u, 57u, 122u,
- 91u, 163u, 42u, 142u,
- 88u, 199u, 82u, 173u,
- 115u, 212u, 151u, 1u,
- 86u, 164u, 115u, 108u,
- 174u, 216u, 101u, 164u,
- 147u, 147u, 59u, 129u,
- 1u, 155u, 140u, 131u,
- 205u, 158u, 122u, 78u,
- 90u, 120u, 105u, 212u,
- 106u, 203u, 207u, 8u,
- 88u, 65u, 170u, 233u,
- 1u, 90u, 162u, 81u,
- 112u, 106u, 202u, 1u,
- 106u, 124u, 125u, 96u,
- 102u, 207u, 58u, 64u,
- 151u, 221u, 164u, 197u,
- 176u, 177u, 233u, 96u,
- 59u, 60u, 244u, 168u,
- 6u, 170u, 213u, 1u,
- 246u, 38u, 49u, 145u,
- 178u, 54u, 204u, 139u,
- 114u, 1u, 39u, 199u,
- 138u, 130u, 163u, 127u,
- 187u, 129u, 85u, 92u,
- 73u, 201u, 98u, 255u,
- 149u, 100u, 118u, 64u,
- 139u, 212u, 200u, 156u,
- 163u, 50u, 48u, 84u,
- 106u, 255u, 155u, 136u,
- 199u, 179u, 220u, 221u,
- 163u, 36u, 178u, 130u,
- 170u, 123u, 116u, 149u,
- 0u, 138u, 122u, 135u,
- 202u, 116u, 193u, 102u,
- 51u, 124u, 151u, 127u,
- 153u, 161u, 46u, 221u,
- 134u, 116u, 48u, 194u,
- 104u, 5u, 147u, 255u,
- 92u, 50u, 73u, 90u,
- 150u, 220u, 175u, 57u,
- 126u, 23u, 0u, 204u,
- 4u, 163u, 75u, 227u,
- 203u, 247u, 124u, 183u,
- 63u, 107u, 249u, 215u,
- 210u, 173u, 209u, 157u,
- 152u, 204u, 166u, 252u,
- 230u, 188u, 187u, 161u,
- 1u, 89u, 189u, 3u,
- 135u, 212u, 150u, 158u,
- 216u, 165u, 241u, 61u,
- 144u, 209u, 178u, 1u,
- 98u, 66u, 114u, 147u,
- 57u, 141u, 158u, 155u,
- 134u, 147u, 110u, 1u,
- 57u, 146u, 167u, 169u,
- 147u, 138u, 89u, 117u,
- 0u, 178u, 72u, 211u,
- 129u, 75u, 188u, 99u,
- 152u, 72u, 184u, 139u,
- 75u, 61u, 165u, 196u,
- 14u, 15u, 168u, 61u,
- 108u, 65u, 100u, 50u,
- 130u, 134u, 1u, 150u,
- 157u, 188u, 29u, 87u,
- 162u, 142u, 193u, 49u,
- 141u, 118u, 193u, 98u,
- 183u, 149u, 132u, 136u,
- 108u, 199u, 255u, 251u,
- 255u, 84u, 80u, 110u,
- 41u, 139u, 107u, 208u,
- 130u, 230u, 150u, 145u,
- 59u, 38u, 108u, 86u,
- 20u, 130u, 50u, 110u,
- 29u, 78u, 150u, 48u,
- 102u, 148u, 129u, 26u,
- 253u, 48u, 255u, 114u,
- 126u, 165u, 230u, 179u,
- 105u, 39u, 59u, 140u,
- 38u, 0u, 192u, 158u,
- 100u, 217u, 97u, 139u,
- 172u, 85u, 112u, 33u,
- 233u, 43u, 56u, 255u,
- 146u, 253u, 132u, 204u,
- 241u, 115u, 78u, 190u,
- 75u, 55u, 40u, 222u,
- 62u, 255u, 215u, 208u,
- 17u, 80u, 64u, 122u,
- 92u, 159u, 134u, 104u,
- 61u, 143u, 168u, 178u,
- 123u, 110u, 190u, 20u,
- 154u, 244u, 175u, 216u,
- 121u, 96u, 107u, 1u,
- 117u, 144u, 201u, 149u,
- 190u, 196u, 138u, 174u,
- 1u, 135u, 107u, 160u,
- 216u, 16u, 107u, 203u,
- 122u, 161u, 14u, 120u,
- 100u, 116u, 96u, 37u,
- 141u, 215u, 149u, 100u,
- 133u, 0u, 82u, 103u,
- 77u, 116u, 94u, 93u,
- 200u, 180u, 120u, 175u,
- 0u, 99u, 89u, 76u,
- 188u, 91u, 89u, 63u,
- 154u, 77u, 123u, 237u,
- 75u, 145u, 152u, 102u,
- 1u, 91u, 124u, 101u,
- 203u, 160u, 48u, 116u,
- 46u, 93u, 214u, 240u,
- 126u, 83u, 197u, 114u,
- 1u, 89u, 206u, 211u,
- 139u, 97u, 45u, 82u,
- 194u, 140u, 218u, 120u,
- 199u, 1u, 167u, 162u,
- 152u, 195u, 178u, 171u,
- 115u, 102u, 87u, 110u,
- 73u, 125u, 91u, 92u,
- 71u, 1u, 160u, 163u,
- 82u, 86u, 111u, 140u,
- 238u, 229u, 198u, 107u,
- 111u, 148u, 108u, 88u,
- 180u, 142u, 102u, 114u,
- 119u, 239u, 151u, 255u,
- 182u, 223u, 207u, 155u,
- 52u, 135u, 127u, 125u,
- 68u, 130u, 210u, 1u,
- 158u, 120u, 144u, 131u,
- 27u, 63u, 189u, 25u,
- 202u, 69u, 0u, 133u,
- 67u, 228u, 97u, 73u,
- 87u, 100u, 74u, 76u,
- 31u, 204u, 213u, 69u,
- 82u, 244u, 255u, 113u,
- 130u, 118u, 116u, 215u,
- 133u, 247u, 229u, 144u,
- 24u, 150u, 118u, 22u,
- 206u, 190u, 117u, 173u,
- 71u, 160u, 72u, 184u,
- 141u, 89u, 124u, 121u,
- 87u, 74u, 255u, 110u,
- 99u, 161u, 151u, 96u,
- 169u, 107u, 145u, 115u,
- 255u, 186u, 55u, 96u,
- 132u, 89u, 170u, 127u,
- 69u, 202u, 140u, 19u,
- 213u, 196u, 86u, 1u,
- 158u, 189u, 38u, 200u,
- 179u, 83u, 125u, 50u,
- 82u, 156u, 157u, 61u,
- 141u, 180u, 147u, 177u,
- 204u, 42u, 255u, 120u,
- 33u, 202u, 96u, 124u,
- 121u, 255u, 27u, 132u,
- 116u, 169u, 49u, 129u,
- 128u, 126u, 45u, 159u,
- 18u, 198u, 89u, 150u,
- 104u, 240u, 110u, 80u,
- 112u, 59u, 94u, 74u,
- 154u, 1u, 77u, 67u,
- 184u, 177u, 110u, 204u,
- 178u, 184u, 120u, 184u,
- 184u, 255u, 113u, 86u,
- 107u, 159u, 138u, 139u,
- 90u, 29u, 113u, 116u,
- 120u, 245u, 78u, 245u,
- 170u, 150u, 131u, 38u,
- 193u, 51u, 127u, 180u,
- 90u, 255u, 126u, 251u,
- 166u, 89u, 110u, 158u,
- 92u, 92u, 200u, 145u,
- 59u, 135u, 102u, 161u,
- 192u, 167u, 0u, 157u,
- 164u, 255u, 111u, 167u,
- 234u, 71u, 107u, 185u,
- 146u, 75u, 155u, 138u,
- 142u, 189u, 87u, 122u,
- 93u, 168u, 200u, 0u,
- 144u, 160u, 124u, 165u,
- 217u, 197u, 100u, 195u,
- 161u, 35u, 223u, 127u,
- 161u, 1u, 182u, 4u,
- 172u, 127u, 177u, 115u,
- 22u, 148u, 176u, 41u,
- 112u, 189u, 113u, 35u,
- 121u, 181u, 11u, 103u,
- 194u, 197u, 142u, 86u,
- 168u, 91u, 255u, 34u,
- 142u, 165u, 158u, 117u,
- 77u, 206u, 255u, 176u,
- 175u, 86u, 109u, 190u,
- 136u, 155u, 192u, 159u,
- 88u, 174u, 96u, 99u,
- 103u, 126u, 151u, 188u,
- 169u, 189u, 117u, 151u,
- 117u, 102u, 120u, 115u,
- 131u, 0u, 115u, 203u,
- 115u, 93u, 156u, 125u,
- 255u, 141u, 175u, 39u,
- 112u, 130u, 68u, 113u,
- 151u, 68u, 106u, 8u,
- 164u, 149u, 105u, 95u,
- 127u, 195u, 127u, 93u,
- 1u, 220u, 130u, 81u,
- 90u, 159u, 207u, 104u,
- 108u, 243u, 92u, 255u,
- 45u, 225u, 111u, 138u,
- 162u, 170u, 143u, 155u,
- 100u, 168u, 142u, 201u,
- 81u, 242u, 126u, 102u,
- 222u, 90u, 237u, 118u,
- 81u, 217u, 96u, 255u,
- 254u, 75u, 111u, 20u,
- 38u, 230u, 161u, 60u,
- 194u, 179u, 37u, 156u,
- 101u, 106u, 238u, 142u,
- 113u, 33u, 53u, 255u,
- 187u, 119u, 47u, 123u,
- 65u, 243u, 134u, 101u,
- 66u, 23u, 157u, 27u,
- 76u, 131u, 213u, 255u,
- 152u, 130u, 1u, 189u,
- 87u, 150u, 182u, 118u,
- 112u, 215u, 203u, 130u,
- 58u, 43u, 114u, 201u,
- 157u, 81u, 33u, 145u,
- 166u, 255u, 223u, 168u,
- 120u, 11u, 161u, 125u,
- 123u, 148u, 135u, 180u,
- 79u, 139u, 151u, 79u,
- 132u, 255u, 49u, 24u,
- 65u, 127u, 153u, 241u,
- 178u, 168u, 162u, 116u,
- 134u, 124u, 63u, 167u,
- 75u, 150u, 139u, 38u,
- 177u, 97u, 146u, 132u,
- 23u, 141u, 255u, 29u,
- 15u, 129u, 13u, 127u,
- 3u, 172u, 1u, 85u,
- 170u, 100u, 129u, 40u,
- 174u, 203u, 116u, 209u,
- 218u, 22u, 240u, 159u,
- 30u, 44u, 95u, 0u,
- 245u, 94u, 231u, 226u,
- 220u, 106u, 126u, 54u,
- 229u, 175u, 152u, 99u,
- 67u, 126u, 201u, 88u,
- 166u, 171u, 149u, 107u,
- 18u, 106u, 1u, 227u,
- 143u, 83u, 127u, 169u,
- 81u, 113u, 74u, 195u,
- 126u, 54u, 39u, 117u,
- 72u, 49u, 0u, 52u,
- 255u, 132u, 81u, 174u,
- 203u, 117u, 242u, 154u,
- 155u, 152u, 197u, 4u,
- 163u, 100u, 111u, 169u,
- 87u, 123u, 53u, 189u,
- 207u, 205u, 103u, 255u,
- 78u, 144u, 74u, 179u,
- 194u, 161u, 91u, 111u,
- 141u, 63u, 211u, 109u,
- 90u, 163u, 144u, 77u,
- 117u, 255u, 186u, 123u,
- 106u, 191u, 127u, 103u,
- 168u, 108u, 79u, 236u,
- 116u, 20u, 207u, 34u,
- 155u, 255u, 34u, 219u,
- 206u, 143u, 52u, 124u,
- 129u, 158u, 103u, 154u,
- 117u, 116u, 150u, 61u,
- 66u, 111u, 200u, 132u,
- 118u, 114u, 255u, 26u,
- 69u, 43u, 95u, 163u,
- 69u, 71u, 153u, 22u,
- 50u, 205u, 165u, 11u,
- 240u, 112u, 81u, 0u,
- 98u, 216u, 168u, 36u,
- 198u, 130u, 182u, 106u,
- 228u, 169u, 1u, 100u,
- 124u, 205u, 74u, 136u,
- 120u, 82u, 175u, 210u,
- 76u, 215u, 151u, 95u,
- 203u, 117u, 123u, 73u,
- 52u, 135u, 146u, 1u,
- 57u, 133u, 145u, 174u,
- 119u, 247u, 65u, 75u,
- 46u, 197u, 77u, 8u,
- 143u, 150u, 119u, 1u,
- 120u, 72u, 177u, 158u,
- 114u, 48u, 164u, 159u,
- 198u, 129u, 0u, 226u,
- 120u, 219u, 152u, 123u,
- 53u, 161u, 1u, 128u,
- 161u, 180u, 69u, 193u,
- 132u, 97u, 116u, 112u,
- 57u, 210u, 54u, 135u,
- 120u, 173u, 11u, 254u,
- 4u, 116u, 144u, 57u,
- 112u, 196u, 47u, 163u,
- 102u, 213u, 255u, 201u,
- 61u, 73u, 86u, 84u,
- 181u, 66u, 124u, 50u,
- 96u, 255u, 64u, 102u,
- 125u, 125u, 97u, 111u,
- 227u, 92u, 222u, 159u,
- 199u, 255u, 199u, 99u,
- 150u, 61u, 127u, 210u,
- 164u, 178u, 123u, 63u,
- 116u, 189u, 114u, 93u,
- 255u, 70u, 156u, 27u,
- 148u, 145u, 114u, 127u,
- 200u, 157u, 130u, 55u,
- 193u, 209u, 167u, 158u,
- 58u, 87u, 162u, 122u,
- 132u, 105u, 192u, 81u,
- 1u, 82u, 140u, 170u,
- 69u, 53u, 65u, 208u,
- 58u, 255u, 127u, 5u,
- 98u, 125u, 228u, 155u,
- 71u, 35u, 181u, 45u,
- 103u, 100u, 100u, 165u,
- 68u, 122u, 135u, 83u,
- 200u, 204u, 109u, 186u,
- 1u, 156u, 150u, 113u,
- 71u, 94u, 41u, 0u,
- 117u, 45u, 112u, 145u,
- 50u, 134u, 117u, 172u,
- 158u, 121u, 160u, 123u,
- 183u, 45u, 156u, 73u,
- 170u, 181u, 226u, 86u,
- 175u, 255u, 141u, 91u,
- 158u, 45u, 220u, 32u,
- 203u, 73u, 132u, 170u,
- 152u, 255u, 154u, 178u,
- 142u, 164u, 161u, 75u,
- 116u, 114u, 83u, 119u,
- 74u, 230u, 205u, 221u,
- 0u, 89u, 215u, 54u,
- 134u, 62u, 164u, 191u,
- 169u, 23u, 186u, 137u,
- 124u, 133u, 175u, 114u,
- 105u, 114u, 47u, 255u,
- 170u, 11u, 117u, 25u,
- 222u, 183u, 218u, 187u,
- 59u, 179u, 164u, 140u,
- 100u, 175u, 159u, 85u,
- 178u, 132u, 50u, 84u,
- 111u, 130u, 183u, 1u,
- 209u, 55u, 123u, 149u,
- 148u, 93u, 255u, 161u,
- 213u, 251u, 96u, 192u,
- 73u, 98u, 100u, 63u,
- 218u, 171u, 185u, 35u,
- 129u, 255u, 120u, 113u,
- 86u, 170u, 129u, 94u,
- 92u, 89u, 168u, 94u,
- 147u, 103u, 105u, 167u,
- 159u, 120u, 90u, 160u,
- 190u, 169u, 142u, 174u,
- 255u, 119u, 89u, 78u,
- 147u, 193u, 151u, 84u,
- 136u, 140u, 107u, 81u,
- 67u, 97u, 157u, 71u,
- 248u, 255u, 10u, 253u,
- 162u, 105u, 106u, 100u,
- 132u, 175u, 89u, 156u,
- 208u, 167u, 194u, 141u,
- 97u, 29u, 123u, 255u,
- 99u, 82u, 115u, 173u,
- 101u, 76u, 163u, 124u,
- 120u, 173u, 70u, 141u,
- 129u, 255u, 118u, 119u,
- 181u, 137u, 79u, 86u,
- 46u, 183u, 149u, 175u,
- 183u, 60u, 165u, 182u,
- 1u, 131u, 209u, 170u,
- 6u, 255u, 90u, 176u,
- 208u, 193u, 239u, 73u,
- 114u, 73u, 129u, 142u,
- 140u, 90u, 46u, 249u,
- 21u, 68u, 51u, 102u,
- 255u, 77u, 139u, 136u,
- 92u, 67u, 105u, 162u,
- 107u, 46u, 138u, 147u,
- 60u, 194u, 175u, 97u,
- 168u, 202u, 109u, 1u,
- 159u, 117u, 141u, 98u,
- 116u, 145u, 95u, 84u,
- 225u, 75u, 107u, 248u,
- 110u, 225u, 176u, 223u,
- 81u, 217u, 138u, 255u,
- 78u, 170u, 101u, 60u,
- 112u, 255u, 36u, 124u,
- 199u, 149u, 183u, 136u,
- 131u, 214u, 200u, 110u,
- 147u, 164u, 88u, 65u,
- 251u, 56u, 134u, 101u,
- 104u, 110u, 69u, 1u,
- 41u, 104u, 84u, 71u,
- 209u, 157u, 82u, 67u,
- 250u, 31u, 233u, 93u,
- 98u, 102u, 182u, 108u,
- 66u, 66u, 126u, 234u,
- 145u, 99u, 97u, 0u,
- 173u, 229u, 177u, 0u,
- 170u, 129u, 68u, 114u,
- 28u, 130u, 102u, 69u,
- 191u, 133u, 114u, 56u,
- 40u, 73u, 101u, 155u,
- 120u, 75u, 137u, 113u,
- 143u, 146u, 1u, 152u,
- 106u, 162u, 55u, 139u,
- 81u, 150u, 142u, 191u,
- 101u, 165u, 99u, 148u,
- 99u, 70u, 118u, 63u,
- 130u, 81u, 255u, 101u,
- 47u, 130u, 112u, 86u,
- 80u, 76u, 175u, 1u,
- 176u, 134u, 137u, 143u,
- 245u, 94u, 120u, 124u,
- 99u, 80u, 93u, 159u,
- 106u, 97u, 34u, 135u,
- 75u, 98u, 1u, 153u,
- 100u, 222u, 101u, 58u,
- 61u, 101u, 69u, 156u,
- 47u, 226u, 114u, 136u,
- 151u, 25u, 89u, 139u,
- 163u, 0u, 76u, 99u,
- 14u, 238u, 147u, 1u,
- 195u, 88u, 208u, 121u,
- 55u, 132u, 186u, 124u,
- 163u, 87u, 6u, 115u,
- 141u, 65u, 66u, 99u,
- 163u, 179u, 123u, 57u,
- 160u, 255u, 69u, 84u,
- 76u, 133u, 86u, 235u,
- 255u, 97u, 75u, 59u,
- 11u, 140u, 187u, 31u,
- 161u, 89u, 133u, 55u,
- 135u, 109u, 159u, 157u,
- 135u, 65u, 147u, 197u,
- 225u, 0u, 143u, 200u,
- 137u, 137u, 137u, 54u,
- 138u, 87u, 17u, 38u,
- 188u, 146u, 193u, 193u,
- 131u, 150u, 170u, 158u,
- 171u, 170u, 72u, 170u,
- 177u, 1u, 230u, 144u,
- 58u, 210u, 165u, 105u,
- 169u, 147u, 191u, 37u,
- 255u, 164u, 125u, 119u,
- 62u, 142u, 250u, 181u,
- 154u, 255u, 126u, 78u,
- 181u, 92u, 97u, 179u,
- 191u, 141u, 180u, 190u,
- 63u, 199u, 16u, 194u,
- 170u, 50u, 5u, 166u,
- 212u, 142u, 157u, 135u,
- 72u, 255u, 140u, 169u,
- 170u, 212u, 118u, 55u,
- 55u, 180u, 218u, 23u,
- 125u, 149u, 67u, 83u,
- 163u, 201u, 1u, 223u,
- 191u, 32u, 167u, 154u,
- 184u, 155u, 186u, 208u,
- 103u, 35u, 63u, 255u,
- 7u, 97u, 237u, 58u,
- 83u, 172u, 210u, 44u,
- 174u, 63u, 65u, 133u,
- 110u, 170u, 98u, 190u,
- 74u, 98u, 100u, 140u,
- 0u, 162u, 98u, 55u,
- 1u, 105u, 218u, 131u,
- 108u, 144u, 130u, 160u,
- 41u, 117u, 58u, 126u,
- 95u, 193u, 94u, 73u,
- 84u, 106u, 141u, 109u,
- 127u, 194u, 108u, 255u,
- 252u, 162u, 136u, 115u,
- 13u, 102u, 145u, 227u,
- 85u, 105u, 68u, 117u,
- 201u, 169u, 84u, 1u,
- 66u, 145u, 106u, 28u,
- 60u, 172u, 65u, 132u,
- 175u, 110u, 197u, 132u,
- 241u, 1u, 84u, 138u,
- 39u, 97u, 159u, 107u,
- 135u, 252u, 180u, 165u,
- 174u, 110u, 56u, 197u,
- 131u, 230u, 170u, 66u,
- 151u, 72u, 62u, 57u,
- 1u, 157u, 108u, 158u,
- 146u, 125u, 222u, 118u,
- 123u, 125u, 164u, 168u,
- 1u, 161u, 217u, 116u,
- 161u, 11u, 100u, 194u,
- 112u, 118u, 225u, 153u,
- 14u, 192u, 99u, 58u,
- 72u, 62u, 88u, 134u,
- 150u, 255u, 224u, 42u,
- 180u, 90u, 85u, 205u,
- 143u, 6u, 215u, 119u,
- 142u, 218u, 152u, 61u,
- 224u, 254u, 255u, 104u,
- 98u, 145u, 240u, 115u,
- 141u, 129u, 255u, 85u,
- 110u, 220u, 61u, 221u,
- 88u, 228u, 82u, 43u,
- 173u, 233u, 37u, 139u,
- 8u, 255u, 127u, 208u,
- 246u, 97u, 100u, 85u,
- 96u, 2u, 161u, 145u,
- 225u, 85u, 109u, 1u,
- 152u, 214u, 113u, 182u,
- 179u, 78u, 146u, 87u,
- 25u, 131u, 202u, 87u,
- 211u, 57u, 235u, 128u,
- 39u, 1u, 47u, 245u,
- 89u, 101u, 178u, 222u,
- 145u, 172u, 236u, 115u,
- 145u, 117u, 118u, 152u,
- 99u, 145u, 98u, 255u,
- 174u, 29u, 149u, 75u,
- 28u, 171u, 138u, 64u,
- 86u, 151u, 85u, 218u,
- 218u, 17u, 199u, 88u,
- 202u, 133u, 125u, 167u,
- 255u, 74u, 115u, 164u,
- 93u, 138u, 1u, 247u,
- 111u, 112u, 89u, 154u,
- 160u, 84u, 118u, 109u,
- 163u, 172u, 241u, 45u,
- 117u, 170u, 46u, 97u,
- 131u, 239u, 190u, 49u,
- 104u, 179u, 86u, 69u,
- 1u, 195u, 113u, 74u,
- 1u, 93u, 86u, 137u,
- 55u, 189u, 116u, 96u,
- 119u, 70u, 39u, 144u,
- 40u, 187u, 110u, 147u,
- 96u, 168u, 140u, 128u,
- 255u, 148u, 89u, 147u,
- 58u, 208u, 167u, 155u,
- 201u, 192u, 187u, 147u,
- 109u, 45u, 198u, 243u,
- 134u, 164u, 85u, 225u,
- 157u, 126u, 70u, 113u,
- 98u, 255u, 79u, 74u,
- 86u, 216u, 126u, 163u,
- 255u, 189u, 185u, 42u,
- 156u, 77u, 59u, 100u,
- 133u, 124u, 80u, 157u,
- 112u, 149u, 109u, 116u,
- 0u, 214u, 100u, 120u,
- 123u, 133u, 55u, 135u,
- 111u, 157u, 239u, 128u,
- 130u, 117u, 166u, 77u,
- 144u, 89u, 120u, 80u,
- 1u, 183u, 125u, 74u,
- 125u, 179u, 47u, 143u,
- 204u, 56u, 203u, 215u,
- 191u, 111u, 76u, 214u,
- 208u, 141u, 40u, 255u,
- 36u, 163u, 232u, 132u,
- 29u, 146u, 23u, 155u,
- 107u, 213u, 255u, 159u,
- 165u, 118u, 210u, 228u,
- 56u, 179u, 156u, 111u,
- 79u, 128u, 0u, 159u,
- 97u, 124u, 204u, 160u,
- 253u, 128u, 85u, 140u,
- 163u, 113u, 68u, 223u,
- 132u, 31u, 109u, 200u,
- 175u, 207u, 107u, 201u,
- 54u, 255u, 50u, 160u,
- 95u, 149u, 127u, 122u,
- 70u, 164u, 127u, 156u,
- 85u, 175u, 69u, 46u,
- 134u, 137u, 0u, 139u,
- 133u, 159u, 193u, 138u,
- 136u, 98u, 91u, 0u,
- 114u, 53u, 2u, 124u,
- 24u, 196u, 135u, 131u,
- 220u, 194u, 17u, 192u,
- 193u, 177u, 144u, 100u,
- 93u, 154u, 162u, 61u,
- 150u, 108u, 0u, 117u,
- 87u, 90u, 109u, 107u,
- 58u, 160u, 79u, 165u,
- 155u, 100u, 70u, 203u,
- 138u, 122u, 143u, 133u,
- 128u, 0u, 31u, 218u,
- 128u, 214u, 84u, 168u,
- 74u, 100u, 252u, 165u,
- 171u, 144u, 118u, 0u,
- 99u, 203u, 159u, 159u,
- 204u, 74u, 220u, 129u,
- 72u, 70u, 94u, 97u,
- 59u, 242u, 157u, 229u,
- 159u, 255u, 56u, 60u,
- 251u, 255u, 214u, 130u,
- 138u, 142u, 81u, 111u,
- 42u, 124u, 150u, 96u,
- 128u, 137u, 99u, 111u,
- 202u, 254u, 9u, 198u,
- 121u, 104u, 180u, 30u,
- 178u, 124u, 234u, 232u,
- 176u, 91u, 255u, 222u,
- 141u, 164u, 195u, 109u,
- 221u, 38u, 177u, 130u,
- 117u, 240u, 1u, 197u,
- 105u, 211u, 197u, 48u,
- 132u, 182u, 58u, 37u,
- 149u, 162u, 124u, 3u,
- 194u, 67u, 134u, 1u,
- 50u, 132u, 40u, 187u,
- 73u, 78u, 110u, 168u,
- 182u, 145u, 168u, 134u,
- 100u, 179u, 213u, 1u,
- 164u, 203u, 70u, 190u,
- 50u, 108u, 192u, 139u,
- 87u, 94u, 87u, 183u,
- 210u, 69u, 81u, 102u,
- 84u, 1u, 176u, 103u,
- 25u, 104u, 8u, 45u,
- 64u, 125u, 1u, 130u,
- 136u, 139u, 122u, 104u,
- 86u, 185u, 94u, 203u,
- 255u, 142u, 188u, 180u,
- 135u, 218u, 189u, 71u,
- 190u, 130u, 195u, 218u,
- 24u, 103u, 100u, 127u,
- 104u, 65u, 48u, 50u,
- 255u, 138u, 2u, 78u,
- 37u, 146u, 137u, 63u,
- 149u, 67u, 207u, 163u,
- 145u, 127u, 107u, 1u,
- 148u, 112u, 28u, 145u,
- 112u, 123u, 90u, 105u,
- 162u, 110u, 159u, 241u,
- 119u, 238u, 23u, 94u,
- 131u, 85u, 121u, 85u,
- 1u, 100u, 135u, 150u,
- 142u, 23u, 32u, 232u,
- 108u, 70u, 116u, 42u,
- 91u, 140u, 144u, 181u,
- 188u, 216u, 126u, 146u,
- 18u, 99u, 132u, 255u,
- 194u, 148u, 163u, 129u,
- 100u, 175u, 66u, 105u,
- 104u, 73u, 255u, 66u,
- 144u, 103u, 245u, 77u,
- 85u, 184u, 183u, 41u,
- 168u, 196u, 37u, 110u,
- 80u, 200u, 175u, 48u,
- 98u, 128u, 1u, 119u,
- 199u, 117u, 245u, 65u,
- 77u, 1u, 121u, 133u,
- 81u, 127u, 143u, 138u,
- 151u, 99u, 128u, 44u,
- 46u, 5u, 148u, 76u,
- 1u, 36u, 147u, 195u,
- 151u, 114u, 90u, 42u,
- 78u, 187u, 47u, 201u,
- 117u, 84u, 166u, 78u,
- 117u, 128u, 122u, 159u,
- 174u, 195u, 124u, 255u,
- 159u, 115u, 184u, 124u,
- 104u, 45u, 1u, 112u,
- 109u, 110u, 113u, 177u,
- 91u, 189u, 109u, 182u,
- 108u, 202u, 202u, 79u,
- 55u, 204u, 71u, 120u,
- 255u, 193u, 217u, 89u,
- 143u, 95u, 72u, 188u,
- 89u, 169u, 87u, 120u,
- 127u, 113u, 105u, 37u,
- 198u, 108u, 109u, 181u,
- 1u, 137u, 234u, 132u,
- 215u, 144u, 144u, 216u,
- 70u, 151u, 255u, 156u,
- 98u, 173u, 148u, 140u,
- 213u, 115u, 89u, 37u,
- 117u, 156u, 54u, 129u,
- 165u, 119u, 201u, 130u,
- 85u, 1u, 26u, 73u,
- 237u, 155u, 100u, 101u,
- 142u, 89u, 197u, 37u,
- 159u, 255u, 122u, 186u,
- 109u, 177u, 146u, 157u,
- 105u, 46u, 127u, 248u,
- 43u, 73u, 79u, 135u,
- 156u, 95u, 79u, 0u,
- 243u, 217u, 160u, 237u,
- 111u, 227u, 42u, 46u,
- 86u, 42u, 29u, 23u,
- 116u, 17u, 34u, 191u,
- 150u, 178u, 1u, 134u,
- 91u, 132u, 205u, 222u,
- 168u, 140u, 157u, 101u,
- 255u, 53u, 93u, 93u,
- 97u, 25u, 47u, 82u,
- 192u, 162u, 144u, 198u,
- 170u, 130u, 246u, 210u,
- 123u, 175u, 108u, 199u,
- 152u, 119u, 95u, 222u,
- 37u, 47u, 255u, 230u,
- 160u, 95u, 131u, 3u,
- 137u, 255u, 208u, 55u,
- 200u, 127u, 114u, 125u,
- 50u, 237u, 30u, 165u,
- 139u, 176u, 196u, 167u,
- 131u, 139u, 177u, 148u,
- 36u, 252u, 234u, 78u,
- 52u, 163u, 213u, 168u,
- 0u, 68u, 76u, 226u,
- 179u, 93u, 190u, 134u,
- 181u, 87u, 119u, 166u,
- 255u, 255u, 190u, 56u,
- 137u, 182u, 94u, 95u,
- 18u, 26u, 92u, 109u,
- 0u, 164u, 54u, 54u,
- 222u, 255u, 119u, 1u,
- 79u, 44u, 155u, 224u,
- 161u, 154u, 133u, 82u,
- 111u, 69u, 149u, 0u,
- 154u, 155u, 112u, 59u,
- 116u, 182u, 101u, 160u,
- 126u, 78u, 89u, 77u,
- 165u, 149u, 204u, 255u,
- 225u, 167u, 103u, 181u,
- 35u, 169u, 119u, 176u,
- 131u, 143u, 179u, 164u,
- 0u, 123u, 89u, 68u,
- 155u, 65u, 92u, 176u,
- 209u, 224u, 226u, 137u,
- 0u, 70u, 63u, 172u,
- 117u, 235u, 209u, 142u,
- 77u, 181u, 98u, 69u,
- 43u, 171u, 236u, 59u,
- 227u, 152u, 109u, 1u,
- 84u, 86u, 84u, 134u,
- 163u, 86u, 163u, 62u,
- 145u, 16u, 106u, 144u,
- 136u, 84u, 175u, 51u,
- 39u, 12u, 135u, 1u,
- 136u, 152u, 93u, 212u,
- 213u, 103u, 61u, 86u,
- 156u, 167u, 79u, 154u,
- 137u, 0u, 106u, 175u,
- 201u, 142u, 140u, 98u,
- 147u, 183u, 133u, 148u,
- 123u, 158u, 91u, 145u,
- 162u, 195u, 196u, 107u,
- 70u, 1u, 118u, 131u,
- 51u, 106u, 102u, 164u,
- 205u, 77u, 190u, 1u,
- 191u, 46u, 58u, 62u,
- 82u, 154u, 78u, 120u,
- 102u, 232u, 112u, 87u,
- 222u, 203u, 81u, 38u,
- 115u, 64u, 20u, 94u,
- 119u, 123u, 122u, 68u,
- 0u, 126u, 164u, 171u,
- 26u, 132u, 54u, 138u,
- 185u, 180u, 83u, 121u,
- 179u, 137u, 110u, 237u,
- 1u, 140u, 144u, 76u,
- 120u, 175u, 157u, 22u,
- 128u, 158u, 199u, 177u,
- 103u, 78u, 118u, 183u,
- 1u, 81u, 148u, 138u,
- 218u, 93u, 152u, 1u,
- 165u, 139u, 71u, 98u,
- 28u, 194u, 226u, 14u,
- 152u, 46u, 83u, 71u,
- 143u, 115u, 138u, 98u,
- 142u, 180u, 167u, 201u,
- 150u, 98u, 165u, 136u,
- 16u, 1u, 10u, 156u,
- 158u, 216u, 80u, 82u,
- 70u, 223u, 85u, 199u,
- 54u, 67u, 1u, 120u,
- 38u, 194u, 151u, 148u,
- 57u, 124u, 203u, 30u,
- 2u, 89u, 79u, 65u,
- 160u, 138u, 219u, 197u,
- 3u, 4u, 0u, 145u,
- 108u, 7u, 112u, 83u,
- 138u, 123u, 123u, 255u,
- 217u, 62u, 177u, 172u,
- 137u, 130u, 183u, 88u,
- 214u, 78u, 120u, 162u,
- 88u, 140u, 123u, 255u,
- 161u, 71u, 78u, 190u,
- 220u, 111u, 146u, 150u,
- 204u, 194u, 184u, 72u,
- 185u, 173u, 177u, 255u,
- 48u, 106u, 213u, 168u,
- 16u, 180u, 113u, 58u,
- 24u, 181u, 55u, 190u,
- 85u, 164u, 149u, 255u,
- 186u, 140u, 161u, 101u,
- 51u, 109u, 124u, 177u,
- 184u, 120u, 141u, 125u,
- 203u, 172u, 150u, 146u,
- 255u, 178u, 131u, 99u,
- 178u, 138u, 107u, 153u,
- 255u, 154u, 196u, 27u,
- 132u, 166u, 206u, 163u,
- 251u, 162u, 89u, 146u,
- 49u, 186u, 208u, 121u,
- 75u, 113u, 123u, 64u,
- 98u, 139u, 108u, 90u,
- 76u, 152u, 150u, 190u,
- 145u, 1u, 81u, 166u,
- 76u, 137u, 114u, 214u,
- 173u, 78u, 186u, 116u,
- 50u, 1u, 214u, 91u,
- 216u, 162u, 58u, 176u,
- 96u, 137u, 142u, 140u,
- 147u, 66u, 137u, 81u,
- 1u, 63u, 96u, 84u,
- 136u, 116u, 202u, 167u,
- 139u, 241u, 255u, 173u,
- 173u, 200u, 107u, 45u,
- 125u, 117u, 49u, 83u,
- 76u, 98u, 127u, 146u,
- 85u, 93u, 35u, 171u,
- 152u, 75u, 123u, 210u,
- 1u, 127u, 85u, 114u,
- 115u, 157u, 221u, 157u,
- 121u, 91u, 68u, 130u,
- 208u, 129u, 153u, 34u,
- 158u, 94u, 235u, 143u,
- 255u, 147u, 133u, 109u,
- 152u, 68u, 172u, 86u,
- 90u, 238u, 196u, 74u,
- 57u, 197u, 150u, 1u,
- 243u, 78u, 125u, 99u,
- 89u, 86u, 101u, 162u,
- 118u, 144u, 81u, 132u,
- 72u, 231u, 179u, 75u,
- 145u, 208u, 43u, 1u,
- 80u, 93u, 94u, 154u,
- 255u, 62u, 200u, 74u,
- 97u, 106u, 106u, 137u,
- 137u, 142u, 75u, 168u,
- 119u, 163u, 111u, 174u,
- 114u, 132u, 74u, 0u,
- 75u, 112u, 147u, 144u,
- 62u, 152u, 57u, 78u,
- 134u, 107u, 128u, 213u,
- 84u, 92u, 66u, 71u,
- 187u, 167u, 85u, 255u,
- 106u, 117u, 131u, 109u,
- 70u, 170u, 118u, 42u,
- 120u, 153u, 233u, 84u,
- 159u, 135u, 58u, 67u,
- 132u, 99u, 206u, 255u,
- 97u, 212u, 255u, 118u,
- 72u, 104u, 151u, 98u,
- 61u, 106u, 129u, 65u,
- 178u, 17u, 156u, 136u,
- 255u, 138u, 156u, 50u,
- 127u, 141u, 67u, 88u,
- 98u, 164u, 120u, 61u,
- 80u, 137u, 84u, 76u,
- 78u, 215u, 116u, 203u,
- 215u, 133u, 58u, 0u,
- 155u, 241u, 89u, 13u,
- 254u, 193u, 142u, 113u,
- 189u, 42u, 119u, 195u,
- 62u, 12u, 171u, 1u,
- 112u, 30u, 91u, 53u,
- 58u, 88u, 127u, 131u,
- 88u, 104u, 29u, 41u,
- 231u, 7u, 76u, 1u,
- 62u, 119u, 135u, 66u,
- 196u, 191u, 42u, 115u,
- 142u, 151u, 46u, 211u,
- 157u, 74u, 51u, 230u,
- 24u, 62u, 138u, 241u,
- 85u, 255u, 185u, 104u,
- 71u, 81u, 120u, 150u,
- 1u, 219u, 116u, 78u,
- 71u, 172u, 74u, 117u,
- 103u, 138u, 152u, 71u,
- 185u, 35u, 203u, 153u,
- 213u, 1u, 57u, 174u,
- 152u, 163u, 202u, 204u,
- 147u, 141u, 131u, 139u,
- 197u, 142u, 186u, 64u,
- 105u, 26u, 1u, 156u,
- 93u, 175u, 67u, 68u,
- 70u, 181u, 210u, 185u,
- 109u, 49u, 165u, 1u,
- 181u, 71u, 209u, 35u,
- 80u, 165u, 226u, 74u,
- 110u, 168u, 24u, 177u,
- 106u, 105u, 132u, 154u,
- 112u, 180u, 0u, 104u,
- 196u, 56u, 39u, 66u,
- 80u, 48u, 120u, 166u,
- 128u, 72u, 235u, 237u,
- 228u, 83u, 255u, 249u,
- 88u, 235u, 146u, 149u,
- 84u, 97u, 47u, 142u,
- 32u, 201u, 108u, 176u,
- 200u, 43u, 217u, 175u,
- 160u, 177u, 205u, 123u,
- 255u, 130u, 49u, 234u,
- 231u, 88u, 66u, 81u,
- 10u, 55u, 35u, 163u,
- 255u, 170u, 107u, 84u,
- 126u, 180u, 108u, 77u,
- 94u, 119u, 96u, 71u,
- 137u, 158u, 221u, 0u,
- 129u, 46u, 68u, 104u,
- 98u, 31u, 70u, 212u,
- 172u, 77u, 127u, 59u,
- 127u, 86u, 134u, 102u,
- 229u, 195u, 172u, 1u,
- 146u, 106u, 186u, 161u,
- 6u, 155u, 143u, 173u,
- 162u, 181u, 223u, 92u,
- 113u, 93u, 149u, 221u,
- 135u, 255u, 62u, 202u,
- 70u, 236u, 135u, 1u,
- 158u, 219u, 164u, 42u,
- 229u, 30u, 90u, 102u,
- 196u, 125u, 241u, 245u,
- 30u, 210u, 185u, 255u,
- 97u, 139u, 59u, 78u,
- 130u, 139u, 131u, 217u,
- 135u, 215u, 105u, 183u,
- 155u, 96u, 24u, 114u,
- 99u, 143u, 2u, 1u,
- 52u, 96u, 197u, 222u,
- 72u, 126u, 83u, 190u,
- 58u, 162u, 145u, 144u,
- 241u, 109u, 216u, 205u,
- 47u, 72u, 77u, 208u,
- 115u, 1u, 69u, 33u,
- 144u, 124u, 124u, 169u,
- 140u, 215u, 160u, 255u,
- 206u, 94u, 26u, 150u,
- 40u, 87u, 100u, 133u,
- 45u, 102u, 166u, 182u,
- 94u, 1u, 110u, 249u,
- 202u, 188u, 144u, 183u,
- 251u, 39u, 117u, 80u,
- 112u, 171u, 152u, 253u,
- 69u, 175u, 98u, 49u,
- 135u, 159u, 157u, 102u,
- 192u, 247u, 255u, 153u,
- 233u, 101u, 247u, 24u,
- 63u, 93u, 1u, 125u,
- 228u, 160u, 148u, 202u,
- 161u, 185u, 139u, 144u,
- 189u, 150u, 174u, 143u,
- 144u, 98u, 146u, 107u,
- 165u, 255u, 109u, 110u,
- 38u, 100u, 77u, 79u,
- 117u, 85u, 247u, 43u,
- 132u, 151u, 16u, 23u,
- 8u, 124u, 157u, 0u,
- 65u, 30u, 41u, 84u,
- 109u, 57u, 104u, 76u,
- 157u, 82u, 100u, 96u,
- 157u, 173u, 21u, 51u,
- 109u, 157u, 1u, 127u,
- 60u, 200u, 56u, 110u,
- 205u, 81u, 255u, 153u,
- 120u, 179u, 175u, 154u,
- 148u, 163u, 163u, 112u,
- 196u, 123u, 218u, 84u,
- 91u, 63u, 187u, 132u,
- 83u, 76u, 158u, 33u,
- 122u, 171u, 255u, 36u,
- 181u, 255u, 215u, 112u,
- 140u, 102u, 84u, 174u,
- 232u, 43u, 75u, 242u,
- 229u, 64u, 40u, 76u,
- 89u, 116u, 115u, 6u,
- 210u, 96u, 110u, 255u,
- 198u, 173u, 173u, 110u,
- 118u, 54u, 118u, 112u,
- 255u, 131u, 137u, 118u,
- 191u, 144u, 148u, 236u,
- 145u, 221u, 120u, 105u,
- 118u, 106u, 196u, 86u,
- 91u, 134u, 119u, 229u,
- 174u, 58u, 154u, 87u,
- 144u, 87u, 155u, 51u,
- 150u, 119u, 162u, 255u,
- 227u, 191u, 197u, 255u,
- 230u, 248u, 131u, 11u,
- 106u, 47u, 40u, 36u,
- 229u, 194u, 89u, 14u,
- 25u, 75u, 50u, 59u,
- 255u, 77u, 122u, 123u,
- 233u, 155u, 20u, 26u,
- 44u, 83u, 92u, 94u,
- 99u, 185u, 79u, 75u,
- 58u, 136u, 255u, 158u,
- 243u, 144u, 72u, 107u,
- 112u, 115u, 71u, 184u,
- 162u, 149u, 87u, 193u,
- 106u, 149u, 118u, 111u,
- 163u, 162u, 16u, 191u,
- 181u, 1u, 91u, 51u,
- 172u, 125u, 179u, 216u,
- 93u, 118u, 169u, 85u,
- 155u, 178u, 146u, 93u,
- 205u, 195u, 216u, 1u,
- 147u, 132u, 123u, 166u,
- 102u, 193u, 122u, 161u,
- 143u, 60u, 159u, 207u,
- 105u, 1u, 165u, 114u,
- 123u, 136u, 142u, 79u,
- 255u, 154u, 42u, 30u,
- 78u, 186u, 127u, 160u,
- 130u, 155u, 41u, 172u,
- 79u, 113u, 2u, 118u,
- 255u, 28u, 158u, 133u,
- 92u, 200u, 120u, 48u,
- 182u, 163u, 179u, 97u,
- 117u, 83u, 224u, 255u,
- 74u, 115u, 160u, 95u,
- 90u, 179u, 106u, 71u,
- 214u, 207u, 154u, 79u,
- 0u, 111u, 73u, 129u,
- 117u, 164u, 211u, 142u,
- 87u, 211u, 59u, 24u,
- 108u, 208u, 103u, 217u,
- 94u, 80u, 153u, 233u,
- 131u, 172u, 31u, 108u,
- 1u, 123u, 191u, 127u,
- 250u, 162u, 109u, 56u,
- 141u, 49u, 111u, 223u,
- 74u, 66u, 27u, 153u,
- 175u, 147u, 0u, 226u,
- 126u, 252u, 111u, 201u,
- 132u, 138u, 172u, 101u,
- 75u, 202u, 0u, 91u,
- 3u, 181u, 157u, 80u,
- 115u, 159u, 185u, 161u,
- 181u, 23u, 128u, 114u,
- 106u, 255u, 50u, 172u,
- 69u, 3u, 138u, 154u,
- 113u, 148u, 122u, 26u,
- 122u, 72u, 47u, 163u,
- 180u, 170u, 162u, 220u,
- 63u, 135u, 96u, 23u,
- 33u, 255u, 1u, 192u,
- 121u, 93u, 140u, 61u,
- 56u, 29u, 125u, 55u,
- 90u, 68u, 255u, 138u,
- 162u, 99u, 94u, 180u,
- 198u, 128u, 140u, 22u,
- 66u, 101u, 73u, 133u,
- 255u, 210u, 141u, 181u,
- 208u, 63u, 148u, 164u,
- 99u, 60u, 209u, 65u,
- 1u, 48u, 191u, 104u,
- 185u, 107u, 124u, 92u,
- 150u, 127u, 144u, 91u,
- 102u, 218u, 84u, 182u,
- 151u, 20u, 114u, 1u,
- 115u, 58u, 133u, 208u,
- 131u, 19u, 82u, 117u,
- 154u, 127u, 207u, 82u,
- 134u, 156u, 103u, 195u,
- 92u, 255u, 175u, 165u,
- 97u, 104u, 87u, 100u,
- 154u, 140u, 208u, 206u,
- 209u, 141u, 102u, 201u,
- 149u, 1u, 184u, 216u,
- 120u, 102u, 89u, 88u,
- 180u, 90u, 119u, 213u,
- 155u, 115u, 112u, 117u,
- 102u, 202u, 110u, 127u,
- 164u, 53u, 0u, 151u,
- 174u, 126u, 133u, 135u,
- 102u, 188u, 167u, 128u,
- 196u, 141u, 81u, 169u,
- 79u, 232u, 255u, 202u,
- 73u, 195u, 178u, 165u,
- 225u, 100u, 86u, 4u,
- 29u, 143u, 28u, 12u,
- 199u, 255u, 204u, 215u,
- 1u, 180u, 118u, 128u,
- 46u, 121u, 140u, 83u,
- 161u, 93u, 157u, 118u,
- 180u, 226u, 18u, 229u,
- 127u, 133u, 52u, 82u,
- 70u, 204u, 54u, 235u,
- 235u, 143u, 74u, 147u,
- 82u, 4u, 51u, 255u,
- 145u, 134u, 143u, 255u,
- 104u, 116u, 113u, 89u,
- 66u, 118u, 92u, 112u,
- 134u, 191u, 170u, 96u,
- 183u, 137u, 79u, 146u,
- 57u, 232u, 175u, 142u,
- 215u, 95u, 59u, 183u,
- 1u, 147u, 189u, 100u,
- 181u, 255u, 198u, 58u,
- 130u, 221u, 141u, 127u,
- 204u, 103u, 112u, 175u,
- 147u, 88u, 70u, 82u,
- 167u, 85u, 242u, 51u,
- 84u, 47u, 115u, 104u,
- 168u, 183u, 32u, 187u,
- 0u, 227u, 35u, 152u,
- 128u, 255u, 62u, 94u,
- 126u, 140u, 84u, 69u,
- 81u, 55u, 104u, 71u,
- 114u, 155u, 163u, 163u,
- 99u, 137u, 120u, 64u,
- 209u, 178u, 52u, 118u,
- 103u, 153u, 98u, 85u,
- 86u, 118u, 0u, 115u,
- 163u, 204u, 132u, 91u,
- 255u, 166u, 151u, 160u,
- 96u, 187u, 113u, 133u,
- 107u, 80u, 165u, 143u,
- 150u, 80u, 136u, 168u,
- 45u, 64u, 207u, 80u,
- 255u, 95u, 100u, 152u,
- 133u, 220u, 227u, 63u,
- 155u, 113u, 119u, 96u,
- 65u, 151u, 139u, 37u,
- 204u, 174u, 92u, 116u,
- 58u, 152u, 186u, 255u,
- 77u, 127u, 98u, 15u,
- 54u, 101u, 156u, 109u,
- 224u, 152u, 92u, 143u,
- 67u, 255u, 28u, 208u,
- 96u, 172u, 110u, 147u,
- 177u, 92u, 135u, 57u,
- 130u, 60u, 55u, 1u,
- 27u, 92u, 83u, 217u,
- 86u, 126u, 235u, 116u,
- 154u, 1u, 177u, 107u,
- 145u, 218u, 157u, 156u,
- 218u, 127u, 77u, 29u,
- 199u, 56u, 170u, 155u,
- 168u, 77u, 194u, 74u,
- 143u, 65u, 161u, 110u,
- 150u, 255u, 84u, 48u,
- 148u, 32u, 156u, 138u,
- 192u, 149u, 255u, 151u,
- 156u, 23u, 202u, 97u,
- 164u, 8u, 141u, 232u,
- 16u, 88u, 43u, 54u,
- 37u, 147u, 62u, 61u,
- 204u, 159u, 129u, 1u,
- 162u, 90u, 86u, 66u,
- 128u, 174u, 33u, 143u,
- 255u, 148u, 144u, 191u,
- 143u, 96u, 75u, 66u,
- 247u, 199u, 68u, 87u,
- 148u, 231u, 204u, 146u,
- 74u, 100u, 141u, 95u,
- 114u, 109u, 143u, 167u,
- 172u, 106u, 255u, 150u,
- 87u, 148u, 72u, 156u,
- 153u, 218u, 73u, 32u,
- 59u, 61u, 88u, 65u,
- 80u, 1u, 231u, 16u,
- 210u, 106u, 123u, 41u,
- 209u, 171u, 159u, 81u,
- 103u, 156u, 116u, 173u,
- 46u, 81u, 1u, 176u,
- 83u, 199u, 124u, 128u,
- 95u, 69u, 121u, 11u,
- 136u, 105u, 23u, 183u,
- 124u, 187u, 250u, 255u,
- 240u, 160u, 200u, 121u,
- 190u, 179u, 128u, 178u,
- 68u, 84u, 255u, 135u,
- 145u, 88u, 175u, 173u,
- 3u, 83u, 15u, 188u,
- 72u, 106u, 192u, 171u,
- 142u, 144u, 99u, 134u,
- 255u, 113u, 183u, 139u,
- 74u, 87u, 48u, 112u,
- 103u, 48u, 47u, 137u,
- 136u, 157u, 123u, 213u,
- 170u, 0u, 55u, 106u,
- 128u, 123u, 87u, 191u,
- 98u, 100u, 137u, 235u,
- 191u, 137u, 122u, 120u,
- 88u, 78u, 255u, 198u,
- 167u, 145u, 194u, 173u,
- 78u, 140u, 132u, 43u,
- 154u, 83u, 255u, 59u,
- 166u, 47u, 199u, 254u,
- 169u, 55u, 79u, 126u,
- 130u, 86u, 111u, 255u,
- 131u, 108u, 113u, 126u,
- 152u, 205u, 155u, 27u,
- 156u, 72u, 136u, 170u,
- 93u, 224u, 173u, 37u,
- 140u, 230u, 87u, 158u,
- 157u, 255u, 210u, 127u,
- 112u, 89u, 16u, 106u,
- 138u, 38u, 133u, 202u,
- 84u, 104u, 97u, 73u,
- 126u, 255u, 173u, 112u,
- 80u, 93u, 129u, 170u,
- 160u, 192u, 139u, 134u,
- 187u, 113u, 147u, 95u,
- 161u, 148u, 0u, 202u,
- 136u, 81u, 1u, 163u,
- 119u, 111u, 68u, 45u,
- 80u, 210u, 140u, 196u,
- 26u, 117u, 152u, 76u,
- 73u, 16u, 102u, 135u,
- 46u, 179u, 59u, 255u,
- 68u, 96u, 101u, 131u,
- 218u, 100u, 72u, 76u,
- 108u, 241u, 122u, 161u,
- 187u, 147u, 106u, 176u,
- 132u, 121u, 151u, 167u,
- 135u, 1u, 160u, 152u,
- 239u, 71u, 171u, 180u,
- 207u, 94u, 131u, 77u,
- 54u, 193u, 55u, 10u,
- 31u, 95u, 109u, 0u,
- 101u, 181u, 145u, 80u,
- 111u, 122u, 86u, 1u,
- 137u, 68u, 163u, 148u,
- 173u, 15u, 175u, 171u,
- 92u, 175u, 69u, 35u,
- 183u, 139u, 255u, 178u,
- 92u, 181u, 18u, 94u,
- 24u, 77u, 237u, 22u,
- 135u, 72u, 187u, 94u,
- 115u, 142u, 116u, 95u,
- 158u, 138u, 147u, 125u,
- 255u, 174u, 107u, 164u,
- 149u, 87u, 101u, 129u,
- 79u, 161u, 255u, 81u,
- 26u, 61u, 90u, 119u,
- 113u, 183u, 138u, 206u,
- 146u, 69u, 189u, 225u,
- 1u, 147u, 2u, 129u,
- 170u, 180u, 214u, 169u,
- 193u, 47u, 174u, 95u,
- 191u, 1u, 117u, 94u,
- 203u, 56u, 102u, 155u,
- 133u, 151u, 138u, 107u,
- 89u, 210u, 222u, 92u,
- 112u, 133u, 129u, 138u,
- 154u, 102u, 1u, 138u,
- 87u, 173u, 92u, 137u,
- 159u, 167u, 153u, 187u,
- 255u, 51u, 216u, 96u,
- 84u, 40u, 76u, 142u,
- 158u, 150u, 146u, 70u,
- 139u, 147u, 185u, 55u,
- 134u, 42u, 193u, 146u,
- 163u, 65u, 68u, 113u,
- 119u, 150u, 152u, 104u,
- 255u, 120u, 151u, 65u,
- 184u, 38u, 1u, 163u,
- 124u, 113u, 210u, 69u,
- 174u, 125u, 158u, 114u,
- 208u, 25u, 114u, 191u,
- 142u, 19u, 171u, 255u,
- 41u, 179u, 23u, 200u,
- 99u, 46u, 179u, 128u,
- 209u, 244u, 236u, 114u,
- 126u, 190u, 100u, 141u,
- 118u, 179u, 53u, 100u,
- 108u, 16u, 255u, 81u,
- 164u, 97u, 160u, 232u,
- 91u, 46u, 106u, 72u,
- 150u, 143u, 172u, 104u,
- 135u, 115u, 127u, 1u,
- 182u, 85u, 153u, 82u,
- 205u, 53u, 255u, 252u,
- 127u, 9u, 117u, 203u,
- 185u, 210u, 150u, 193u,
- 144u, 129u, 8u, 94u,
- 107u, 66u, 142u, 175u,
- 62u, 111u, 168u, 1u,
- 139u, 198u, 144u, 79u,
- 71u, 79u, 170u, 195u,
- 155u, 100u, 70u, 154u,
- 91u, 1u, 38u, 205u,
- 56u, 180u, 142u, 140u,
- 167u, 114u, 172u, 141u,
- 105u, 115u, 174u, 227u,
- 88u, 48u, 202u, 0u,
- 148u, 175u, 95u, 125u,
- 124u, 198u, 194u, 152u,
- 124u, 199u, 59u, 148u,
- 102u, 97u, 142u, 218u,
- 188u, 155u, 126u, 229u,
- 97u, 255u, 103u, 35u,
- 135u, 132u, 150u, 111u,
- 195u, 146u, 156u, 66u,
- 149u, 132u, 131u, 146u,
- 69u, 136u, 0u, 162u,
- 44u, 189u, 131u, 138u,
- 69u, 210u, 148u, 198u,
- 111u, 200u, 77u, 242u,
- 255u, 78u, 96u, 111u,
- 166u, 201u, 184u, 225u,
- 126u, 101u, 29u, 147u,
- 162u, 162u, 169u, 120u,
- 143u, 1u, 255u, 63u,
- 246u, 133u, 191u, 124u,
- 118u, 129u, 71u, 61u,
- 37u, 92u, 212u, 123u,
- 255u, 205u, 104u, 137u,
- 195u, 142u, 141u, 54u,
- 159u, 183u, 129u, 119u,
- 117u, 239u, 141u, 16u,
- 88u, 135u, 255u, 96u,
- 102u, 165u, 61u, 242u,
- 149u, 69u, 214u, 145u,
- 78u, 84u, 166u, 155u,
- 255u, 36u, 255u, 211u,
- 242u, 52u, 249u, 86u,
- 80u, 54u, 88u, 192u,
- 255u, 236u, 157u, 143u,
- 125u, 180u, 243u, 9u,
- 98u, 112u, 183u, 184u,
- 70u, 96u, 124u, 91u,
- 213u, 255u, 147u, 181u,
- 131u, 148u, 143u, 99u,
- 105u, 156u, 121u, 137u,
- 125u, 145u, 134u, 255u,
- 154u, 105u, 104u, 155u,
- 82u, 188u, 121u, 176u,
- 67u, 37u, 117u, 61u,
- 138u, 0u, 164u, 89u,
- 229u, 161u, 114u, 91u,
- 104u, 148u, 115u, 246u,
- 255u, 211u, 190u, 75u,
- 236u, 56u, 128u, 184u,
- 129u, 208u, 187u, 189u,
- 7u, 188u, 187u, 88u,
- 1u, 167u, 131u, 165u,
- 219u, 162u, 59u, 83u,
- 154u, 62u, 89u, 111u,
- 197u, 102u, 216u, 98u,
- 130u, 163u, 137u, 139u,
- 96u, 161u, 153u, 186u,
- 161u, 79u, 168u, 90u,
- 74u, 186u, 255u, 198u,
- 144u, 162u, 178u, 146u,
- 98u, 117u, 126u, 65u,
- 121u, 156u, 150u, 152u,
- 85u, 15u, 255u, 19u,
- 127u, 148u, 172u, 169u,
- 160u, 64u, 224u, 230u,
- 73u, 1u, 137u, 179u,
- 142u, 115u, 50u, 139u,
- 82u, 116u, 71u, 88u,
- 157u, 217u, 215u, 255u,
- 16u, 6u, 100u, 115u,
- 111u, 118u, 58u, 102u,
- 196u, 11u, 143u, 182u,
- 14u, 112u, 49u, 72u,
- 1u, 52u, 111u, 156u,
- 156u, 68u, 197u, 4u,
- 159u, 101u, 135u, 182u,
- 127u, 255u, 124u, 53u,
- 144u, 147u, 140u, 139u,
- 125u, 171u, 100u, 113u,
- 20u, 112u, 77u, 126u,
- 151u, 185u, 156u, 210u,
- 169u, 239u, 109u, 100u,
- 85u, 156u, 1u, 76u,
- 182u, 154u, 188u, 201u,
- 28u, 215u, 119u, 151u,
- 198u, 1u, 201u, 170u,
- 180u, 78u, 171u, 148u,
- 72u, 172u, 129u, 55u,
- 215u, 118u, 239u, 70u,
- 85u, 99u, 244u, 20u,
- 255u, 125u, 13u, 135u,
- 122u, 84u, 117u, 100u,
- 1u, 148u, 155u, 127u,
- 165u, 151u, 55u, 189u,
- 23u, 169u, 118u, 189u,
- 112u, 111u, 48u, 105u,
- 39u, 154u, 112u, 146u,
- 138u, 130u, 168u, 156u,
- 134u, 1u, 133u, 172u,
- 255u, 135u, 91u, 147u,
- 148u, 83u, 127u, 185u,
- 67u, 111u, 121u, 165u,
- 163u, 98u, 169u, 132u,
- 45u, 96u, 68u, 137u,
- 92u, 187u, 167u, 136u,
- 73u, 62u, 92u, 106u,
- 155u, 145u, 0u, 212u,
- 152u, 62u, 122u, 153u,
- 145u, 152u, 255u, 103u,
- 127u, 130u, 136u, 152u,
- 127u, 143u, 118u, 124u,
- 214u, 178u, 178u, 174u,
- 255u, 210u, 177u, 199u,
- 8u, 96u, 170u, 164u,
- 207u, 141u, 79u, 95u,
- 86u, 0u, 141u, 37u,
- 74u, 57u, 123u, 36u,
- 54u, 200u, 79u, 86u,
- 185u, 155u, 140u, 69u,
- 151u, 134u, 137u, 253u,
- 118u, 58u, 167u, 114u,
- 94u, 132u, 255u, 159u,
- 230u, 77u, 104u, 159u,
- 161u, 50u, 188u, 168u,
- 127u, 127u, 154u, 255u,
- 72u, 117u, 164u, 100u,
- 233u, 245u, 65u, 33u,
- 151u, 56u, 106u, 54u,
- 147u, 124u, 114u, 199u,
- 60u, 182u, 44u, 193u,
- 1u, 181u, 110u, 166u,
- 147u, 78u, 141u, 75u,
- 155u, 68u, 234u, 103u,
- 188u, 223u, 43u, 155u,
- 77u, 203u, 206u, 1u,
- 186u, 62u, 240u, 120u,
- 81u, 140u, 87u, 98u,
- 242u, 212u, 102u, 255u,
- 228u, 177u, 223u, 111u,
- 169u, 212u, 140u, 255u,
- 129u, 73u, 97u, 144u,
- 170u, 142u, 198u, 164u,
- 101u, 123u, 179u, 123u,
- 130u, 129u, 117u, 102u,
- 102u, 187u, 197u, 149u,
- 179u, 165u, 127u, 83u,
- 15u, 124u, 0u, 198u,
- 156u, 49u, 61u, 163u,
- 1u, 224u, 143u, 164u,
- 18u, 92u, 75u, 216u,
- 134u, 189u, 104u, 118u,
- 133u, 99u, 149u, 132u,
- 138u, 249u, 1u, 197u,
- 108u, 163u, 158u, 92u,
- 194u, 143u, 75u, 49u,
- 96u, 251u, 43u, 109u,
- 185u, 188u, 247u, 46u,
- 97u, 162u, 227u, 101u,
- 114u, 1u, 119u, 197u,
- 255u, 52u, 200u, 115u,
- 133u, 127u, 123u, 180u,
- 126u, 92u, 111u, 138u,
- 69u, 192u, 113u, 221u,
- 255u, 25u, 247u, 179u,
- 188u, 39u, 108u, 177u,
- 234u, 211u, 140u, 162u,
- 113u, 196u, 22u, 120u,
- 200u, 209u, 65u, 151u,
- 204u, 194u, 37u, 168u,
- 161u, 148u, 1u, 26u,
- 86u, 51u, 71u, 194u,
- 60u, 187u, 80u, 250u,
- 101u, 101u, 149u, 137u,
- 163u, 159u, 134u, 107u,
- 100u, 255u, 200u, 112u,
- 255u, 221u, 82u, 182u,
- 114u, 165u, 149u, 75u,
- 235u, 61u, 57u, 66u,
- 155u, 133u, 36u, 66u,
- 125u, 61u, 13u, 86u,
- 128u, 119u, 146u, 119u,
- 142u, 179u, 217u, 71u,
- 102u, 35u, 255u, 128u,
- 22u, 168u, 50u, 183u,
- 102u, 185u, 199u, 16u,
- 40u, 179u, 178u, 137u,
- 1u, 163u, 122u, 98u,
- 81u, 102u, 96u, 176u,
- 120u, 163u, 0u, 79u,
- 54u, 123u, 89u, 136u,
- 86u, 89u, 151u, 30u,
- 147u, 162u, 187u, 126u,
- 126u, 197u, 37u, 112u,
- 124u, 12u, 195u, 249u,
- 192u, 197u, 58u, 255u,
- 92u, 139u, 120u, 174u,
- 1u, 151u, 140u, 83u,
- 86u, 151u, 124u, 177u,
- 90u, 189u, 165u, 119u,
- 136u, 133u, 98u, 98u,
- 180u, 116u, 110u, 91u,
- 80u, 97u, 133u, 231u,
- 89u, 1u, 142u, 198u,
- 170u, 128u, 199u, 132u,
- 209u, 140u, 124u, 101u,
- 255u, 125u, 109u, 186u,
- 90u, 83u, 127u, 172u,
- 133u, 160u, 166u, 1u,
- 115u, 115u, 60u, 47u,
- 153u, 139u, 160u, 7u,
- 89u, 171u, 112u, 121u,
- 155u, 203u, 212u, 9u,
- 120u, 29u, 222u, 98u,
- 161u, 87u, 114u, 1u,
- 70u, 166u, 166u, 104u,
- 82u, 122u, 200u, 119u,
- 155u, 90u, 128u, 234u,
- 151u, 175u, 99u, 46u,
- 211u, 69u, 255u, 163u,
- 0u, 162u, 134u, 63u,
- 136u, 39u, 168u, 113u,
- 156u, 103u, 133u, 132u,
- 100u, 109u, 127u, 229u,
- 141u, 109u, 133u, 222u,
- 82u, 172u, 140u, 80u,
- 255u, 234u, 160u, 79u,
- 159u, 47u, 254u, 144u,
- 102u, 165u, 107u, 64u,
- 133u, 198u, 147u, 165u,
- 137u, 165u, 159u, 142u,
- 105u, 193u, 1u, 108u,
- 218u, 102u, 175u, 94u,
- 181u, 205u, 65u, 88u,
- 167u, 176u, 89u, 69u,
- 1u, 102u, 109u, 195u,
- 134u, 61u, 118u, 126u,
- 154u, 73u, 73u, 128u,
- 129u, 139u, 69u, 104u,
- 204u, 255u, 211u, 118u,
- 92u, 186u, 182u, 31u,
- 79u, 86u, 9u, 132u,
- 193u, 125u, 175u, 85u,
- 55u, 202u, 1u, 130u,
- 87u, 62u, 160u, 255u,
- 197u, 197u, 239u, 117u,
- 71u, 70u, 169u, 162u,
- 200u, 168u, 12u, 114u,
- 105u, 94u, 139u, 61u,
- 81u, 117u, 137u, 1u,
- 127u, 129u, 155u, 95u,
- 144u, 183u, 121u, 89u,
- 185u, 17u, 208u, 0u,
- 162u, 74u, 206u, 89u,
- 96u, 205u, 116u, 173u,
- 123u, 78u, 107u, 151u,
- 213u, 241u, 255u, 58u,
- 49u, 221u, 201u, 146u,
- 195u, 44u, 179u, 207u,
- 106u, 145u, 146u, 162u,
- 86u, 121u, 168u, 185u,
- 140u, 102u, 142u, 116u,
- 10u, 146u, 126u, 90u,
- 94u, 54u, 43u, 1u,
- 166u, 169u, 138u, 216u,
- 47u, 131u, 82u, 68u,
- 0u, 11u, 217u, 214u,
- 87u, 109u, 237u, 231u,
- 1u, 36u, 11u, 236u,
- 77u, 68u, 122u, 191u,
- 109u, 126u, 165u, 134u,
- 226u, 165u, 85u, 121u,
- 136u, 157u, 110u, 136u,
- 167u, 149u, 62u, 161u,
- 176u, 255u, 105u, 61u,
- 100u, 221u, 151u, 129u,
- 233u, 33u, 105u, 206u,
- 165u, 75u, 0u, 115u,
- 156u, 113u, 151u, 133u,
- 216u, 115u, 189u, 29u,
- 23u, 70u, 92u, 55u,
- 54u, 1u, 116u, 183u,
- 78u, 226u, 70u, 88u,
- 148u, 169u, 133u, 69u,
- 196u, 169u, 140u, 99u,
- 57u, 58u, 111u, 67u,
- 103u, 136u, 165u, 6u,
- 181u, 187u, 1u, 184u,
- 214u, 71u, 105u, 107u,
- 0u, 184u, 192u, 124u,
- 55u, 73u, 175u, 127u,
- 51u, 93u, 193u, 129u,
- 95u, 246u, 40u, 85u,
- 151u, 152u, 104u, 160u,
- 149u, 67u, 119u, 87u,
- 110u, 30u, 158u, 255u,
- 81u, 57u, 87u, 201u,
- 56u, 135u, 131u, 48u,
- 159u, 51u, 79u, 80u,
- 124u, 213u, 1u, 65u,
- 141u, 229u, 105u, 245u,
- 157u, 234u, 232u, 53u,
- 255u, 135u, 70u, 197u,
- 69u, 215u, 141u, 149u,
- 146u, 250u, 195u, 63u,
- 204u, 90u, 238u, 194u,
- 90u, 51u, 255u, 60u,
- 253u, 147u, 74u, 150u,
- 117u, 183u, 110u, 131u,
- 64u, 184u, 125u, 84u,
- 204u, 169u, 116u, 96u,
- 83u, 108u, 255u, 203u,
- 117u, 178u, 95u, 112u,
- 131u, 238u, 174u, 107u,
- 255u, 166u, 195u, 170u,
- 108u, 97u, 152u, 140u,
- 161u, 138u, 111u, 140u,
- 111u, 131u, 148u, 132u,
- 112u, 173u, 116u, 131u,
- 129u, 123u, 255u, 95u,
- 0u, 129u, 227u, 133u,
- 102u, 112u, 218u, 65u,
- 49u, 176u, 161u, 115u,
- 94u, 93u, 26u, 139u,
- 79u, 119u, 125u, 145u,
- 225u, 63u, 179u, 102u,
- 15u, 122u, 167u, 72u,
- 192u, 1u, 160u, 94u,
- 164u, 159u, 130u, 224u,
- 112u, 13u, 255u, 142u,
- 137u, 37u, 46u, 130u,
- 92u, 185u, 156u, 174u,
- 222u, 155u, 134u, 136u,
- 181u, 231u, 211u, 195u,
- 150u, 78u, 147u, 255u,
- 157u, 100u, 211u, 114u,
- 110u, 9u, 0u, 105u,
- 230u, 155u, 78u, 197u,
- 157u, 56u, 195u, 132u,
- 142u, 44u, 172u, 166u,
- 85u, 36u, 158u, 151u,
- 103u, 77u, 151u, 108u,
- 154u, 153u, 109u, 101u,
- 176u, 191u, 0u, 20u,
- 220u, 175u, 185u, 10u,
- 255u, 143u, 167u, 241u,
- 24u, 151u, 61u, 248u,
- 110u, 120u, 139u, 30u,
- 169u, 227u, 191u, 140u,
- 203u, 87u, 187u, 189u,
- 30u, 255u, 84u, 42u,
- 95u, 173u, 132u, 216u,
- 195u, 159u, 193u, 255u,
- 162u, 125u, 20u, 130u,
- 136u, 82u, 186u, 207u,
- 160u, 125u, 116u, 111u,
- 117u, 228u, 108u, 1u,
- 43u, 139u, 75u, 113u,
- 238u, 125u, 3u, 140u,
- 61u, 46u, 6u, 109u,
- 193u, 78u, 78u, 100u,
- 145u, 108u, 205u, 176u,
- 72u, 99u, 55u, 104u,
- 185u, 117u, 0u, 66u,
- 147u, 149u, 41u, 190u,
- 144u, 123u, 202u, 181u,
- 57u, 154u, 74u, 63u,
- 126u, 67u, 242u, 255u,
- 111u, 175u, 155u, 56u,
- 206u, 134u, 158u, 246u,
- 83u, 34u, 197u, 89u,
- 96u, 89u, 1u, 119u,
- 132u, 181u, 0u, 83u,
- 110u, 188u, 128u, 157u,
- 112u, 203u, 64u, 173u,
- 113u, 159u, 159u, 92u,
- 139u, 247u, 71u, 210u,
- 127u, 159u, 153u, 0u,
- 193u, 132u, 188u, 19u,
- 161u, 114u, 142u, 193u,
- 255u, 173u, 176u, 141u,
- 157u, 138u, 99u, 121u,
- 160u, 140u, 126u, 144u,
- 120u, 93u, 100u, 114u,
- 125u, 156u, 28u, 115u,
- 31u, 149u, 175u, 59u,
- 208u, 109u, 105u, 125u,
- 24u, 78u, 143u, 255u,
- 202u, 134u, 65u, 40u,
- 91u, 145u, 146u, 180u,
- 92u, 154u, 246u, 207u,
- 174u, 128u, 162u, 255u,
- 155u, 19u, 85u, 90u,
- 143u, 27u, 158u, 129u,
- 98u, 210u, 128u, 56u,
- 208u, 150u, 85u, 1u,
- 179u, 197u, 246u, 190u,
- 138u, 62u, 222u, 32u,
- 74u, 92u, 52u, 219u,
- 165u, 194u, 255u, 112u,
- 91u, 160u, 52u, 66u,
- 110u, 215u, 66u, 64u,
- 173u, 108u, 159u, 164u,
- 126u, 139u, 255u, 111u,
- 207u, 125u, 191u, 222u,
- 102u, 235u, 159u, 53u,
- 71u, 23u, 135u, 1u,
- 93u, 94u, 113u, 149u,
- 0u, 241u, 91u, 221u,
- 138u, 74u, 241u, 95u,
- 114u, 197u, 112u, 111u,
- 150u, 51u, 163u, 219u,
- 108u, 27u, 189u, 99u,
- 30u, 108u, 37u, 121u,
- 122u, 160u, 148u, 190u,
- 162u, 141u, 0u, 115u,
- 157u, 65u, 165u, 166u,
- 88u, 125u, 126u, 115u,
- 82u, 30u, 135u, 61u,
- 255u, 201u, 178u, 208u,
- 200u, 103u, 175u, 135u,
- 116u, 188u, 80u, 99u,
- 87u, 239u, 151u, 112u,
- 235u, 53u, 162u, 1u,
- 140u, 107u, 173u, 148u,
- 202u, 194u, 56u, 136u,
- 1u, 122u, 125u, 128u,
- 24u, 197u, 94u, 91u,
- 121u, 94u, 194u, 41u,
- 105u, 192u, 1u, 103u,
- 221u, 88u, 171u, 146u,
- 87u, 93u, 89u, 229u,
- 108u, 168u, 175u, 189u,
- 255u, 106u, 144u, 179u,
- 39u, 106u, 134u, 202u,
- 100u, 133u, 38u, 36u,
- 101u, 98u, 3u, 101u,
- 116u, 112u, 145u, 133u,
- 102u, 82u, 158u, 120u,
- 249u, 178u, 55u, 1u,
- 202u, 187u, 174u, 119u,
- 91u, 87u, 93u, 111u,
- 195u, 119u, 161u, 143u,
- 184u, 1u, 113u, 200u,
- 173u, 212u, 192u, 108u,
- 243u, 209u, 130u, 255u,
- 132u, 34u, 207u, 173u,
- 48u, 78u, 98u, 26u,
- 162u, 99u, 142u, 159u,
- 168u, 127u, 0u, 159u,
- 125u, 156u, 120u, 144u,
- 151u, 16u, 159u, 143u,
- 135u, 143u, 75u, 87u,
- 148u, 101u, 228u, 232u,
- 132u, 147u, 208u, 66u,
- 1u, 100u, 189u, 192u,
- 57u, 204u, 149u, 167u,
- 170u, 69u, 196u, 235u,
- 255u, 211u, 211u, 190u,
- 178u, 84u, 50u, 223u,
- 141u, 1u, 99u, 189u,
- 21u, 41u, 79u, 89u,
- 109u, 17u, 185u, 242u,
- 221u, 120u, 115u, 97u,
- 107u, 100u, 1u, 91u,
- 109u, 155u, 156u, 105u,
- 89u, 86u, 151u, 166u,
- 86u, 93u, 141u, 197u,
- 144u, 28u, 126u, 192u,
- 74u, 74u, 104u, 113u,
- 155u, 106u, 54u, 77u,
- 1u, 52u, 226u, 187u,
- 136u, 153u, 170u, 222u,
- 84u, 153u, 85u, 117u,
- 161u, 144u, 147u, 94u,
- 187u, 125u, 255u, 104u,
- 112u, 134u, 41u, 72u,
- 155u, 119u, 128u, 125u,
- 186u, 93u, 151u, 255u,
- 84u, 119u, 192u, 206u,
- 29u, 94u, 82u, 202u,
- 121u, 255u, 187u, 164u,
- 145u, 242u, 174u, 41u,
- 233u, 247u, 146u, 205u,
- 154u, 193u, 133u, 149u,
- 153u, 231u, 118u, 241u,
- 255u, 108u, 22u, 124u,
- 14u, 140u, 11u, 102u,
- 103u, 81u, 170u, 233u,
- 102u, 113u, 171u, 75u,
- 133u, 57u, 180u, 132u,
- 98u, 255u, 183u, 116u,
- 33u, 131u, 63u, 96u,
- 123u, 176u, 82u, 255u,
- 97u, 73u, 139u, 144u,
- 98u, 255u, 32u, 200u,
- 162u, 87u, 83u, 255u,
- 87u, 88u, 81u, 189u,
- 55u, 113u, 137u, 132u,
- 218u, 97u, 153u, 177u,
- 184u, 167u, 108u, 255u,
- 135u, 158u, 164u, 147u,
- 207u, 197u, 140u, 91u,
- 48u, 134u, 160u, 200u,
- 109u, 82u, 45u, 255u,
- 134u, 245u, 101u, 238u,
- 79u, 50u, 160u, 167u,
- 164u, 168u, 236u, 231u,
- 136u, 255u, 73u, 91u,
- 105u, 78u, 185u, 58u,
- 129u, 131u, 63u, 156u,
- 83u, 35u, 109u, 129u,
- 107u, 1u, 97u, 140u,
- 144u, 148u, 22u, 140u,
- 15u, 113u, 225u, 133u,
- 119u, 139u, 32u, 153u,
- 63u, 140u, 167u, 117u,
- 122u, 91u, 159u, 146u,
- 255u, 161u, 43u, 144u,
- 71u, 63u, 161u, 127u,
- 114u, 122u, 89u, 111u,
- 141u, 152u, 237u, 174u,
- 48u, 255u, 129u, 136u,
- 73u, 137u, 125u, 150u,
- 173u, 194u, 255u, 207u,
- 140u, 137u, 100u, 155u,
- 89u, 105u, 181u, 176u,
- 121u, 151u, 104u, 88u,
- 11u, 154u, 31u, 255u,
- 50u, 138u, 84u, 155u,
- 138u, 63u, 82u, 192u,
- 74u, 42u, 116u, 83u,
- 36u, 219u, 76u, 136u,
- 203u, 116u, 247u, 121u,
- 132u, 218u, 130u, 167u,
- 90u, 203u, 1u, 199u,
- 250u, 118u, 138u, 45u,
- 232u, 82u, 39u, 255u,
- 255u, 197u, 151u, 11u,
- 117u, 14u, 83u, 209u,
- 143u, 151u, 110u, 99u,
- 39u, 131u, 119u, 142u,
- 206u, 123u, 68u, 77u,
- 1u, 41u, 175u, 178u,
- 1u, 134u, 56u, 185u,
- 127u, 113u, 140u, 148u,
- 114u, 212u, 153u, 134u,
- 53u, 68u, 228u, 180u,
- 84u, 94u, 1u, 176u,
- 38u, 190u, 32u, 180u,
- 124u, 82u, 132u, 175u,
- 199u, 139u, 3u, 63u,
- 83u, 43u, 102u, 115u,
- 49u, 60u, 255u, 10u,
- 5u, 146u, 248u, 65u,
- 200u, 179u, 82u, 33u,
- 93u, 113u, 146u, 156u,
- 122u, 78u, 1u, 167u,
- 25u, 72u, 117u, 210u,
- 155u, 166u, 127u, 167u,
- 203u, 125u, 52u, 1u,
- 107u, 245u, 88u, 174u,
- 47u, 28u, 95u, 82u,
- 36u, 150u, 103u, 240u,
- 110u, 124u, 128u, 170u,
- 255u, 153u, 131u, 154u,
- 139u, 96u, 59u, 108u,
- 62u, 135u, 87u, 120u,
- 56u, 154u, 136u, 28u,
- 119u, 141u, 209u, 88u,
- 202u, 87u, 47u, 167u,
- 1u, 113u, 234u, 62u,
- 98u, 72u, 130u, 47u,
- 92u, 98u, 63u, 148u,
- 1u, 125u, 39u, 93u,
- 225u, 30u, 114u, 7u,
- 46u, 76u, 91u, 99u,
- 147u, 58u, 208u, 1u,
- 161u, 146u, 144u, 98u,
- 121u, 75u, 78u, 101u,
- 39u, 203u, 169u, 123u,
- 156u, 185u, 151u, 179u,
- 1u, 61u, 238u, 155u,
- 76u, 109u, 37u, 63u,
- 97u, 1u, 166u, 149u,
- 92u, 173u, 66u, 46u,
- 85u, 199u, 156u, 134u,
- 167u, 159u, 75u, 3u,
- 215u, 1u, 140u, 222u,
- 112u, 2u, 137u, 35u,
- 125u, 208u, 85u, 220u,
- 242u, 235u, 125u, 83u,
- 155u, 235u, 255u, 41u,
- 88u, 232u, 71u, 119u,
- 128u, 102u, 126u, 114u,
- 102u, 76u, 155u, 115u,
- 113u, 89u, 162u, 160u,
- 114u, 148u, 255u, 112u,
- 95u, 119u, 79u, 93u,
- 1u, 225u, 167u, 228u,
- 93u, 97u, 177u, 108u,
- 231u, 92u, 71u, 188u,
- 253u, 151u, 195u, 1u,
- 158u, 213u, 157u, 90u,
- 96u, 92u, 0u, 138u,
- 113u, 252u, 56u, 104u,
- 104u, 101u, 131u, 142u,
- 26u, 81u, 129u, 34u,
- 212u, 123u, 209u, 145u,
- 149u, 125u, 172u, 174u,
- 97u, 149u, 215u, 73u,
- 176u, 198u, 1u, 173u,
- 210u, 190u, 248u, 1u,
- 149u, 136u, 126u, 85u,
- 125u, 117u, 117u, 190u,
- 157u, 244u, 86u, 147u,
- 127u, 255u, 77u, 151u,
- 80u, 169u, 163u, 151u,
- 162u, 245u, 145u, 90u,
- 130u, 249u, 202u, 0u,
- 87u, 169u, 195u, 252u,
- 40u, 86u, 112u, 122u,
- 108u, 255u, 254u, 147u,
- 254u, 49u, 160u, 90u,
- 50u, 221u, 218u, 127u,
- 51u, 137u, 63u, 133u,
- 74u, 175u, 127u, 183u,
- 83u, 243u, 0u, 161u,
- 148u, 150u, 143u, 134u,
- 235u, 121u, 62u, 42u,
- 127u, 173u, 255u, 77u,
- 59u, 63u, 61u, 150u,
- 81u, 203u, 177u, 213u,
- 198u, 112u, 242u, 185u,
- 90u, 255u, 212u, 108u,
- 152u, 151u, 151u, 160u,
- 62u, 119u, 225u, 10u,
- 76u, 70u, 94u, 1u,
- 128u, 183u, 197u, 202u,
- 152u, 174u, 61u, 133u,
- 255u, 160u, 213u, 164u,
- 122u, 116u, 104u, 124u,
- 74u, 72u, 43u, 112u,
- 138u, 134u, 39u, 80u,
- 165u, 117u, 0u, 143u,
- 198u, 74u, 127u, 44u,
- 197u, 234u, 104u, 126u,
- 90u, 214u, 176u, 47u,
- 160u, 97u, 173u, 255u,
- 23u, 102u, 97u, 67u,
- 41u, 129u, 169u, 174u,
- 208u, 136u, 63u, 145u,
- 32u, 107u, 34u, 192u,
- 196u, 153u, 10u, 1u,
- 51u, 231u, 161u, 126u,
- 193u, 255u, 112u, 166u,
- 1u, 1u, 123u, 107u,
- 86u, 75u, 27u, 52u,
- 130u, 134u, 151u, 118u,
- 218u, 28u, 86u, 130u,
- 255u, 70u, 117u, 130u,
- 162u, 177u, 111u, 130u,
- 147u, 117u, 161u, 213u,
- 118u, 251u, 179u, 123u,
- 107u, 255u, 78u, 91u,
- 158u, 112u, 167u, 90u,
- 34u, 82u, 30u, 204u,
- 76u, 131u, 110u, 130u,
- 87u, 168u, 208u, 191u,
- 169u, 7u, 209u, 63u,
- 89u, 150u, 255u, 79u,
- 78u, 123u, 110u, 136u,
- 99u, 191u, 41u, 181u,
- 0u, 222u, 40u, 172u,
- 114u, 121u, 93u, 138u,
- 46u, 116u, 158u, 165u,
- 139u, 153u, 123u, 40u,
- 190u, 197u, 61u, 190u,
- 133u, 198u, 141u, 103u,
- 98u, 123u, 167u, 0u,
- 53u, 141u, 121u, 183u,
- 209u, 187u, 145u, 101u,
- 193u, 255u, 149u, 62u,
- 113u, 177u, 136u, 15u,
- 171u, 128u, 196u, 139u,
- 121u, 179u, 255u, 132u,
- 38u, 193u, 146u, 113u,
- 133u, 147u, 113u, 169u,
- 172u, 185u, 124u, 143u,
- 68u, 103u, 255u, 161u,
- 81u, 144u, 199u, 85u,
- 110u, 154u, 59u, 183u,
- 114u, 59u, 100u, 175u,
- 130u, 123u, 1u, 181u,
- 64u, 31u, 174u, 98u,
- 131u, 166u, 42u, 232u,
- 135u, 178u, 159u, 184u,
- 87u, 149u, 160u, 176u,
- 47u, 203u, 38u, 123u,
- 79u, 0u, 138u, 99u,
- 133u, 110u, 85u, 99u,
- 22u, 163u, 148u, 77u,
- 255u, 157u, 34u, 138u,
- 47u, 105u, 116u, 229u,
- 14u, 115u, 44u, 80u,
- 117u, 109u, 48u, 212u,
- 69u, 146u, 117u, 1u,
- 243u, 207u, 39u, 244u,
- 122u, 104u, 69u, 1u,
- 81u, 128u, 220u, 94u,
- 145u, 148u, 106u, 107u,
- 188u, 222u, 151u, 35u,
- 70u, 161u, 117u, 1u,
- 216u, 219u, 150u, 4u,
- 226u, 87u, 146u, 111u,
- 187u, 119u, 209u, 41u,
- 233u, 128u, 151u, 136u,
- 82u, 78u, 150u, 53u,
- 100u, 130u, 90u, 155u,
- 153u, 141u, 126u, 255u,
- 86u, 109u, 98u, 99u,
- 155u, 230u, 117u, 149u,
- 82u, 0u, 109u, 136u,
- 77u, 115u, 121u, 56u,
- 69u, 154u, 251u, 137u,
- 166u, 255u, 41u, 74u,
- 160u, 92u, 71u, 186u,
- 114u, 32u, 233u, 110u,
- 131u, 66u, 121u, 156u,
- 94u, 111u, 161u, 131u,
- 167u, 209u, 0u, 112u,
- 19u, 158u, 91u, 88u,
- 175u, 57u, 170u, 119u,
- 217u, 1u, 134u, 106u,
- 50u, 97u, 234u, 67u,
- 250u, 7u, 97u, 144u,
- 89u, 133u, 163u, 112u,
- 210u, 53u, 47u, 161u,
- 160u, 84u, 75u, 1u,
- 150u, 200u, 63u, 50u,
- 138u, 120u, 80u, 232u,
- 1u, 116u, 24u, 108u,
- 152u, 128u, 202u, 7u,
- 90u, 91u, 160u, 178u,
- 164u, 186u, 186u, 94u,
- 134u, 118u, 189u, 119u,
- 255u, 146u, 97u, 106u,
- 134u, 82u, 133u, 169u,
- 129u, 128u, 45u, 55u,
- 143u, 165u, 255u, 192u,
- 69u, 124u, 25u, 147u,
- 187u, 213u, 112u, 115u,
- 163u, 161u, 102u, 208u,
- 92u, 230u, 86u, 178u,
- 110u, 158u, 129u, 127u,
- 1u, 157u, 127u, 137u,
- 81u, 255u, 23u, 151u,
- 44u, 175u, 79u, 52u,
- 229u, 175u, 98u, 87u,
- 130u, 143u, 218u, 176u,
- 147u, 155u, 181u, 195u,
- 135u, 87u, 187u, 88u,
- 71u, 255u, 164u, 133u,
- 162u, 39u, 208u, 67u,
- 178u, 33u, 197u, 133u,
- 255u, 52u, 211u, 17u,
- 125u, 54u, 20u, 188u,
- 122u, 235u, 179u, 101u,
- 193u, 163u, 255u, 57u,
- 219u, 209u, 85u, 150u,
- 251u, 96u, 131u, 193u,
- 52u, 15u, 19u, 133u,
- 141u, 193u, 255u, 89u,
- 102u, 199u, 173u, 207u,
- 193u, 235u, 38u, 213u,
- 224u, 190u, 206u, 110u,
- 188u, 107u, 141u, 134u,
- 138u, 107u, 111u, 134u,
- 54u, 60u, 111u, 6u,
- 255u, 185u, 96u, 91u,
- 159u, 134u, 104u, 161u,
- 135u, 221u, 114u, 148u,
- 126u, 194u, 255u, 180u,
- 207u, 138u, 117u, 233u,
- 93u, 170u, 112u, 132u,
- 85u, 118u, 71u, 1u,
- 100u, 136u, 80u, 86u,
- 150u, 82u, 106u, 123u,
- 29u, 182u, 49u, 181u,
- 176u, 146u, 181u, 6u,
- 160u, 255u, 185u, 148u,
- 185u, 230u, 174u, 78u,
- 115u, 144u, 98u, 95u,
- 161u, 255u, 170u, 85u,
- 126u, 145u, 34u, 190u,
- 28u, 247u, 133u, 86u,
- 150u, 83u, 255u, 90u,
- 163u, 105u, 212u, 77u,
- 156u, 133u, 81u, 143u,
- 85u, 161u, 180u, 189u,
- 114u, 212u, 72u, 165u,
- 110u, 250u, 161u, 193u,
- 79u, 39u, 9u, 255u,
- 42u, 222u, 150u, 129u,
- 60u, 167u, 143u, 60u,
- 168u, 134u, 138u, 157u,
- 178u, 173u, 201u, 95u,
- 1u, 164u, 74u, 140u,
- 47u, 27u, 47u, 159u,
- 168u, 131u, 78u, 171u,
- 103u, 50u, 255u, 99u,
- 124u, 115u, 90u, 21u,
- 185u, 145u, 139u, 133u,
- 145u, 221u, 89u, 108u,
- 126u, 195u, 1u, 32u,
- 204u, 129u, 37u, 132u,
- 1u, 129u, 70u, 160u,
- 206u, 115u, 173u, 213u,
- 125u, 64u, 159u, 90u,
- 128u, 121u, 140u, 85u,
- 130u, 119u, 238u, 243u,
- 117u, 132u, 152u, 162u,
- 130u, 240u, 214u, 255u,
- 13u, 129u, 194u, 119u,
- 69u, 169u, 129u, 85u,
- 99u, 14u, 176u, 74u,
- 128u, 177u, 255u, 175u,
- 123u, 19u, 115u, 149u,
- 82u, 136u, 179u, 53u,
- 152u, 158u, 163u, 1u,
- 88u, 166u, 115u, 143u,
- 218u, 59u, 163u, 151u,
- 153u, 140u, 144u, 183u,
- 108u, 1u, 144u, 141u,
- 175u, 114u, 91u, 157u,
- 86u, 38u, 248u, 141u,
- 123u, 125u, 146u, 1u,
- 160u, 84u, 156u, 123u,
- 158u, 206u, 134u, 152u,
- 144u, 104u, 115u, 101u,
- 137u, 71u, 131u, 172u,
- 157u, 97u, 23u, 35u,
- 131u, 81u, 238u, 94u,
- 170u, 1u, 230u, 72u,
- 106u, 131u, 157u, 100u,
- 183u, 54u, 125u, 146u,
- 1u, 100u, 121u, 117u,
- 154u, 137u, 101u, 101u,
- 71u, 73u, 154u, 174u,
- 172u, 30u, 120u, 200u,
- 41u, 1u, 255u, 183u,
- 192u, 47u, 30u, 103u,
- 152u, 128u, 150u, 74u,
- 182u, 220u, 161u, 186u,
- 93u, 139u, 148u, 125u,
- 145u, 144u, 255u, 119u,
- 155u, 64u, 177u, 155u,
- 182u, 128u, 8u, 1u,
- 19u, 190u, 59u, 40u,
- 74u, 172u, 33u, 78u,
- 136u, 79u, 255u, 155u,
- 76u, 230u, 211u, 100u,
- 93u, 130u, 101u, 89u,
- 75u, 215u, 113u, 40u,
- 211u, 111u, 117u, 0u,
- 175u, 126u, 43u, 148u,
- 176u, 168u, 131u, 181u,
- 139u, 139u, 118u, 117u,
- 223u, 135u, 223u, 191u,
- 1u, 87u, 125u, 239u,
- 147u, 98u, 157u, 137u,
- 39u, 142u, 245u, 105u,
- 77u, 164u, 101u, 140u,
- 85u, 173u, 167u, 178u,
- 36u, 0u, 134u, 246u,
- 135u, 223u, 108u, 27u,
- 72u, 60u, 184u, 195u,
- 26u, 151u, 128u, 78u,
- 108u, 144u, 144u, 197u,
- 225u, 215u, 255u, 120u,
- 162u, 66u, 143u, 53u,
- 124u, 156u, 64u, 180u,
- 72u, 215u, 173u, 114u,
- 255u, 132u, 38u, 99u,
- 110u, 67u, 159u, 97u,
- 135u, 114u, 25u, 37u,
- 107u, 235u, 255u, 105u,
- 233u, 210u, 69u, 134u,
- 129u, 255u, 185u, 47u,
- 227u, 160u, 240u, 255u,
- 167u, 100u, 128u, 115u,
- 132u, 181u, 106u, 162u,
- 55u, 213u, 108u, 213u,
- 95u, 67u, 165u, 128u,
- 133u, 39u, 138u, 101u,
- 20u, 83u, 255u, 12u,
- 1u, 171u, 106u, 218u,
- 63u, 117u, 180u, 178u,
- 152u, 7u, 127u, 85u,
- 119u, 81u, 228u, 85u,
- 255u, 103u, 97u, 94u,
- 127u, 23u, 39u, 169u,
- 122u, 86u, 100u, 86u,
- 154u, 187u, 133u, 183u,
- 168u, 164u, 106u, 126u,
- 180u, 136u, 122u, 1u,
- 103u, 135u, 113u, 76u,
- 101u, 132u, 120u, 169u,
- 91u, 44u, 111u, 38u,
- 159u, 89u, 182u, 131u,
- 255u, 247u, 110u, 220u,
- 111u, 195u, 206u, 65u,
- 209u, 130u, 117u, 113u,
- 156u, 38u, 124u, 103u,
- 148u, 255u, 120u, 115u,
- 181u, 66u, 140u, 70u,
- 97u, 137u, 118u, 164u,
- 189u, 108u, 192u, 64u,
- 148u, 255u, 89u, 135u,
- 196u, 228u, 183u, 92u,
- 138u, 149u, 170u, 116u,
- 110u, 107u, 200u, 161u,
- 172u, 46u, 164u, 106u,
- 73u, 22u, 255u, 199u,
- 174u, 255u, 141u, 103u,
- 135u, 119u, 199u, 81u,
- 158u, 113u, 99u, 167u,
- 89u, 123u, 196u, 138u,
- 1u, 181u, 115u, 143u,
- 149u, 67u, 193u, 140u,
- 123u, 133u, 160u, 170u,
- 222u, 87u, 55u, 197u,
- 154u, 235u, 94u, 129u,
- 68u, 82u, 147u, 64u,
- 60u, 53u, 1u, 96u,
- 97u, 82u, 73u, 208u,
- 1u, 197u, 150u, 152u,
- 92u, 159u, 103u, 92u,
- 159u, 130u, 132u, 54u,
- 143u, 71u, 163u, 134u,
- 8u, 46u, 110u, 85u,
- 163u, 136u, 107u, 119u,
- 203u, 124u, 129u, 69u,
- 62u, 94u, 1u, 195u,
- 112u, 164u, 193u, 96u,
- 28u, 180u, 174u, 80u,
- 235u, 109u, 145u, 160u,
- 1u, 96u, 183u, 209u,
- 100u, 153u, 172u, 125u,
- 51u, 166u, 73u, 1u,
- 146u, 105u, 139u, 110u,
- 145u, 35u, 170u, 147u,
- 218u, 186u, 104u, 139u,
- 36u, 145u, 0u, 98u,
- 203u, 131u, 43u, 201u,
- 87u, 212u, 97u, 116u,
- 148u, 190u, 208u, 140u,
- 100u, 220u, 69u, 165u,
- 104u, 104u, 49u, 156u,
- 1u, 207u, 106u, 148u,
- 99u, 165u, 82u, 177u,
- 94u, 178u, 122u, 193u,
- 255u, 5u, 218u, 191u,
- 26u, 5u, 97u, 208u,
- 110u, 66u, 71u, 160u,
- 133u, 173u, 1u, 120u,
- 79u, 156u, 159u, 148u,
- 100u, 68u, 110u, 125u,
- 125u, 88u, 91u, 99u,
- 97u, 122u, 81u, 255u,
- 76u, 115u, 148u, 220u,
- 60u, 114u, 187u, 121u,
- 118u, 203u, 221u, 216u,
- 67u, 124u, 52u, 58u,
- 208u, 143u, 1u, 72u,
- 111u, 56u, 248u, 155u,
- 43u, 75u, 34u, 117u,
- 193u, 160u, 0u, 157u,
- 192u, 179u, 191u, 105u,
- 131u, 48u, 50u, 25u,
- 139u, 171u, 156u, 94u,
- 1u, 154u, 84u, 15u,
- 159u, 106u, 157u, 156u,
- 148u, 107u, 172u, 111u,
- 59u, 107u, 62u, 161u,
- 161u, 86u, 181u, 152u,
- 130u, 147u, 128u, 0u,
- 188u, 124u, 50u, 121u,
- 50u, 129u, 157u, 118u,
- 133u, 97u, 166u, 3u,
- 176u, 82u, 118u, 255u,
- 118u, 170u, 109u, 181u,
- 188u, 255u, 181u, 83u,
- 73u, 249u, 203u, 157u,
- 50u, 205u, 85u, 113u,
- 126u, 226u, 187u, 253u,
- 112u, 131u, 158u, 78u,
- 11u, 145u, 126u, 94u,
- 101u, 48u, 179u, 158u,
- 1u, 182u, 93u, 181u,
- 112u, 175u, 171u, 160u,
- 0u, 139u, 44u, 93u,
- 127u, 201u, 162u, 121u,
- 95u, 78u, 127u, 157u,
- 122u, 69u, 252u, 255u,
- 81u, 130u, 181u, 63u,
- 150u, 44u, 241u, 75u,
- 125u, 163u, 100u, 115u,
- 62u, 76u, 52u, 166u,
- 149u, 35u, 212u, 207u,
- 94u, 132u, 145u, 73u,
- 176u, 112u, 1u, 105u,
- 115u, 183u, 197u, 106u,
- 121u, 84u, 76u, 61u,
- 93u, 195u, 255u, 149u,
- 175u, 143u, 50u, 112u,
- 166u, 43u, 136u, 208u,
- 132u, 108u, 94u, 195u,
- 65u, 140u, 198u, 158u,
- 95u, 194u, 255u, 109u,
- 115u, 228u, 157u, 33u,
- 125u, 150u, 229u, 31u,
- 51u, 67u, 105u, 255u,
- 108u, 120u, 32u, 215u,
- 1u, 106u, 101u, 131u,
- 142u, 132u, 110u, 100u,
- 143u, 171u, 179u, 104u,
- 89u, 169u, 129u, 131u,
- 92u, 44u, 1u, 97u,
- 51u, 185u, 115u, 167u,
- 119u, 125u, 70u, 130u,
- 45u, 98u, 174u, 227u,
- 115u, 76u, 110u, 130u,
- 85u, 77u, 103u, 156u,
- 110u, 143u, 1u, 231u,
- 189u, 214u, 177u, 99u,
- 104u, 210u, 104u, 130u,
- 186u, 218u, 195u, 108u,
- 170u, 152u, 0u, 78u,
- 34u, 145u, 145u, 174u,
- 255u, 129u, 207u, 8u,
- 64u, 244u, 130u, 117u,
- 227u, 139u, 175u, 190u,
- 72u, 193u, 252u, 164u,
- 161u, 239u, 1u, 254u,
- 160u, 140u, 161u, 154u,
- 156u, 167u, 148u, 156u,
- 200u, 210u, 57u, 82u,
- 135u, 255u, 81u, 107u,
- 206u, 137u, 118u, 86u,
- 99u, 77u, 80u, 124u,
- 114u, 68u, 34u, 188u,
- 159u, 38u, 25u, 84u,
- 235u, 255u, 67u, 119u,
- 218u, 67u, 37u, 22u,
- 107u, 154u, 47u, 148u,
- 213u, 178u, 98u, 252u,
- 169u, 191u, 1u, 203u,
- 89u, 69u, 209u, 169u,
- 122u, 60u, 59u, 227u,
- 102u, 34u, 168u, 211u,
- 47u, 121u, 125u, 0u,
- 83u, 54u, 201u, 162u,
- 102u, 205u, 135u, 34u,
- 167u, 184u, 103u, 171u,
- 132u, 1u, 128u, 112u,
- 104u, 95u, 157u, 130u,
- 108u, 177u, 190u, 115u,
- 237u, 108u, 235u, 193u,
- 98u, 149u, 120u, 114u,
- 162u, 55u, 255u, 184u,
- 66u, 49u, 146u, 95u,
- 135u, 118u, 170u, 16u,
- 1u, 74u, 65u, 110u,
- 28u, 39u, 66u, 85u,
- 160u, 52u, 109u, 54u,
- 132u, 152u, 92u, 139u,
- 255u, 109u, 98u, 121u,
- 146u, 253u, 192u, 96u,
- 52u, 128u, 93u, 57u,
- 178u, 181u, 128u, 163u,
- 221u, 191u, 154u, 1u,
- 199u, 170u, 44u, 174u,
- 35u, 115u, 104u, 89u,
- 157u, 67u, 15u, 183u,
- 90u, 104u, 74u, 255u,
- 3u, 162u, 91u, 69u,
- 218u, 231u, 124u, 87u,
- 29u, 158u, 79u, 214u,
- 61u, 111u, 122u, 104u,
- 255u, 182u, 65u, 246u,
- 159u, 176u, 181u, 144u,
- 92u, 107u, 125u, 190u,
- 141u, 132u, 1u, 166u,
- 126u, 62u, 63u, 122u,
- 159u, 169u, 176u, 20u,
- 255u, 181u, 235u, 105u,
- 156u, 130u, 165u, 188u,
- 143u, 189u, 109u, 124u,
- 186u, 117u, 137u, 151u,
- 159u, 192u, 168u, 125u,
- 167u, 62u, 72u, 118u,
- 188u, 189u, 93u, 160u,
- 130u, 40u, 179u, 255u,
- 116u, 198u, 250u, 59u,
- 84u, 206u, 63u, 114u,
- 26u, 167u, 76u, 203u,
- 72u, 226u, 0u, 151u,
- 251u, 157u, 255u, 178u,
- 155u, 96u, 57u, 201u,
- 75u, 164u, 197u, 172u,
- 177u, 151u, 60u, 133u,
- 253u, 203u, 255u, 170u,
- 54u, 5u, 119u, 161u,
- 127u, 114u, 105u, 184u,
- 155u, 64u, 241u, 184u,
- 64u, 155u, 53u, 34u,
- 112u, 162u, 167u, 9u,
- 84u, 181u, 140u, 82u,
- 98u, 179u, 84u, 255u,
- 131u, 131u, 133u, 140u,
- 108u, 99u, 142u, 101u,
- 174u, 112u, 140u, 109u,
- 121u, 129u, 149u, 255u,
- 125u, 78u, 32u, 121u,
- 158u, 97u, 95u, 169u,
- 200u, 144u, 101u, 17u,
- 26u, 255u, 155u, 197u,
- 14u, 1u, 120u, 182u,
- 123u, 59u, 159u, 62u,
- 212u, 246u, 15u, 138u,
- 244u, 61u, 121u, 79u,
- 85u, 201u, 26u, 241u,
- 176u, 84u, 193u, 148u,
- 43u, 35u, 178u, 157u,
- 255u, 202u, 158u, 93u,
- 112u, 201u, 123u, 86u,
- 107u, 21u, 116u, 76u,
- 0u, 183u, 145u, 43u,
- 187u, 94u, 162u, 162u,
- 110u, 173u, 113u, 102u,
- 115u, 195u, 243u, 211u,
- 126u, 81u, 142u, 169u,
- 159u, 150u, 1u, 152u,
- 147u, 205u, 150u, 94u,
- 187u, 135u, 64u, 200u,
- 1u, 112u, 110u, 90u,
- 81u, 119u, 4u, 233u,
- 135u, 57u, 144u, 214u,
- 109u, 124u, 255u, 234u,
- 196u, 131u, 76u, 118u,
- 124u, 200u, 116u, 68u,
- 164u, 97u, 184u, 241u,
- 136u, 113u, 104u, 188u,
- 141u, 123u, 168u, 109u,
- 192u, 1u, 89u, 78u,
- 0u, 111u, 3u, 112u,
- 18u, 73u, 181u, 59u,
- 171u, 71u, 96u, 101u,
- 79u, 103u, 106u, 185u,
- 55u, 119u, 195u, 100u,
- 243u, 150u, 84u, 111u,
- 34u, 88u, 124u, 112u,
- 134u, 86u, 0u, 63u,
- 228u, 72u, 215u, 36u,
- 147u, 140u, 141u, 115u,
- 98u, 189u, 115u, 78u,
- 103u, 149u, 183u, 1u,
- 153u, 58u, 177u, 160u,
- 89u, 0u, 213u, 39u,
- 93u, 192u, 161u, 156u,
- 247u, 169u, 95u, 66u,
- 75u, 156u, 227u, 189u,
- 255u, 22u, 251u, 16u,
- 83u, 166u, 177u, 32u,
- 216u, 51u, 126u, 96u,
- 163u, 91u, 130u, 1u,
- 131u, 54u, 128u, 148u,
- 181u, 255u, 186u, 99u,
- 221u, 23u, 13u, 156u,
- 157u, 41u, 168u, 255u,
- 94u, 182u, 119u, 35u,
- 127u, 26u, 134u, 120u,
- 68u, 11u, 80u, 164u,
- 181u, 1u, 203u, 66u,
- 86u, 126u, 187u, 64u,
- 83u, 128u, 120u, 73u,
- 81u, 205u, 225u, 180u,
- 119u, 1u, 142u, 207u,
- 151u, 93u, 154u, 151u,
- 79u, 200u, 141u, 153u,
- 146u, 183u, 140u, 32u,
- 199u, 79u, 158u, 241u,
- 95u, 120u, 143u, 93u,
- 86u, 64u, 146u, 5u,
- 255u, 90u, 197u, 170u,
- 108u, 107u, 107u, 212u,
- 46u, 171u, 90u, 106u,
- 166u, 112u, 122u, 84u,
- 101u, 46u, 255u, 124u,
- 131u, 128u, 157u, 210u,
- 24u, 160u, 33u, 255u,
- 94u, 38u, 217u, 83u,
- 51u, 34u, 116u, 150u,
- 103u, 225u, 104u, 126u,
- 117u, 173u, 163u, 166u,
- 62u, 104u, 179u, 217u,
- 129u, 104u, 255u, 155u,
- 143u, 126u, 179u, 163u,
- 186u, 202u, 144u, 110u,
- 130u, 255u, 157u, 95u,
- 132u, 144u, 121u, 47u,
- 172u, 191u, 33u, 225u,
- 136u, 117u, 255u, 180u,
- 64u, 209u, 132u, 182u,
- 176u, 131u, 129u, 119u,
- 127u, 87u, 189u, 249u,
- 98u, 58u, 91u, 223u,
- 1u, 18u, 77u, 251u,
- 152u, 119u, 184u, 59u,
- 119u, 222u, 147u, 168u,
- 106u, 204u, 144u, 251u,
- 17u, 190u, 254u, 182u,
- 58u, 255u, 35u, 140u,
- 69u, 174u, 1u, 150u,
- 84u, 180u, 27u, 145u,
- 189u, 20u, 57u, 145u,
- 52u, 106u, 133u, 179u,
- 168u, 161u, 116u, 197u,
- 210u, 255u, 223u, 218u,
- 161u, 129u, 43u, 139u,
- 95u, 177u, 71u, 102u,
- 170u, 177u, 135u, 77u,
- 135u, 148u, 133u, 121u,
- 66u, 255u, 62u, 193u,
- 102u, 147u, 207u, 121u,
- 14u, 81u, 186u, 31u,
- 4u, 129u, 99u, 30u,
- 76u, 53u, 145u, 250u,
- 163u, 111u, 90u, 1u,
- 70u, 191u, 99u, 119u,
- 239u, 48u, 140u, 99u,
- 49u, 88u, 103u, 181u,
- 242u, 255u, 98u, 5u,
- 128u, 123u, 83u, 135u,
- 157u, 159u, 1u, 141u,
- 108u, 116u, 117u, 66u,
- 214u, 234u, 106u, 209u,
- 101u, 154u, 115u, 113u,
- 91u, 164u, 107u, 81u,
- 113u, 137u, 190u, 131u,
- 66u, 90u, 73u, 255u,
- 168u, 176u, 149u, 255u,
- 10u, 167u, 139u, 144u,
- 139u, 71u, 183u, 212u,
- 70u, 186u, 94u, 121u,
- 24u, 1u, 101u, 225u,
- 101u, 69u, 169u, 134u,
- 255u, 146u, 206u, 74u,
- 91u, 55u, 80u, 205u,
- 51u, 209u, 89u, 141u,
- 166u, 114u, 119u, 137u,
- 159u, 23u, 1u, 3u,
- 51u, 156u, 134u, 184u,
- 90u, 128u, 154u, 158u,
- 121u, 112u, 139u, 77u,
- 116u, 125u, 100u, 58u,
- 255u, 127u, 67u, 154u,
- 150u, 131u, 198u, 41u,
- 128u, 131u, 1u, 121u,
- 111u, 231u, 198u, 71u,
- 216u, 212u, 165u, 172u,
- 77u, 165u, 89u, 174u,
- 110u, 101u, 209u, 141u,
- 94u, 139u, 223u, 155u,
- 78u, 124u, 1u, 159u,
- 167u, 96u, 136u, 115u,
- 64u, 136u, 28u, 191u,
- 146u, 187u, 84u, 255u,
- 239u, 129u, 166u, 141u,
- 182u, 112u, 163u, 138u,
- 77u, 68u, 245u, 177u,
- 62u, 165u, 82u, 132u,
- 48u, 255u, 158u, 43u,
- 49u, 45u, 20u, 43u,
- 97u, 124u, 159u, 18u,
- 164u, 255u, 139u, 100u,
- 131u, 197u, 102u, 217u,
- 17u, 180u, 11u, 80u,
- 134u, 113u, 221u, 33u,
- 72u, 9u, 72u, 82u,
- 208u, 209u, 65u, 1u,
- 23u, 62u, 255u, 228u,
- 120u, 183u, 209u, 139u,
- 230u, 138u, 15u, 131u,
- 185u, 222u, 16u, 140u,
- 119u, 82u, 76u, 108u,
- 215u, 43u, 183u, 105u,
- 33u, 66u, 170u, 111u,
- 165u, 84u, 0u, 193u,
- 86u, 143u, 214u, 1u,
- 148u, 164u, 105u, 127u,
- 143u, 186u, 223u, 184u,
- 97u, 75u, 192u, 213u,
- 0u, 155u, 143u, 152u,
- 80u, 147u, 48u, 127u,
- 232u, 225u, 108u, 219u,
- 152u, 174u, 126u, 87u,
- 105u, 68u, 119u, 160u,
- 161u, 171u, 25u, 116u,
- 140u, 243u, 1u, 110u,
- 20u, 153u, 49u, 176u,
- 69u, 108u, 151u, 153u,
- 112u, 255u, 128u, 35u,
- 219u, 197u, 69u, 56u,
- 137u, 49u, 113u, 112u,
- 145u, 126u, 151u, 23u,
- 133u, 162u, 142u, 12u,
- 126u, 215u, 178u, 41u,
- 1u, 75u, 102u, 116u,
- 118u, 74u, 169u, 141u,
- 125u, 183u, 91u, 177u,
- 179u, 114u, 160u, 113u,
- 142u, 128u, 1u, 83u,
- 1u, 125u, 202u, 61u,
- 173u, 58u, 136u, 197u,
- 59u, 210u, 202u, 159u,
- 117u, 189u, 162u, 212u,
- 166u, 207u, 179u, 255u,
- 111u, 84u, 155u, 143u,
- 95u, 162u, 127u, 177u,
- 115u, 156u, 174u, 106u,
- 93u, 216u, 225u, 253u,
- 87u, 40u, 175u, 72u,
- 97u, 195u, 255u, 147u,
- 160u, 142u, 133u, 195u,
- 0u, 148u, 117u, 154u,
- 72u, 159u, 173u, 128u,
- 131u, 160u, 118u, 60u,
- 47u, 195u, 41u, 213u,
- 64u, 99u, 43u, 104u,
- 179u, 64u, 255u, 151u,
- 65u, 246u, 162u, 227u,
- 108u, 65u, 120u, 92u,
- 124u, 23u, 174u, 1u,
- 37u, 184u, 52u, 71u,
- 91u, 99u, 146u, 146u,
- 76u, 89u, 119u, 66u,
- 90u, 190u, 55u, 150u,
- 227u, 193u, 96u, 64u,
- 101u, 205u, 123u, 196u,
- 38u, 11u, 50u, 1u,
- 141u, 114u, 181u, 111u,
- 81u, 255u, 105u, 205u,
- 149u, 219u, 114u, 126u,
- 122u, 129u, 64u, 120u,
- 194u, 188u, 208u, 54u,
- 149u, 120u, 97u, 220u,
- 244u, 178u, 190u, 14u,
- 103u, 1u, 15u, 121u,
- 173u, 129u, 88u, 116u,
- 181u, 214u, 131u, 57u,
- 50u, 175u, 128u, 136u,
- 138u, 1u, 83u, 109u,
- 175u, 255u, 84u, 75u,
- 99u, 161u, 113u, 107u,
- 92u, 102u, 64u, 164u,
- 71u, 82u, 119u, 235u,
- 35u, 204u, 95u, 118u,
- 201u, 52u, 202u, 93u,
- 155u, 200u, 122u, 133u,
- 249u, 57u, 1u, 201u,
- 98u, 172u, 86u, 156u,
- 248u, 179u, 187u, 112u,
- 127u, 162u, 126u, 81u,
- 255u, 95u, 100u, 56u,
- 164u, 190u, 141u, 201u,
- 77u, 101u, 34u, 191u,
- 99u, 42u, 105u, 86u,
- 116u, 219u, 255u, 94u,
- 117u, 126u, 85u, 1u,
- 181u, 123u, 63u, 217u,
- 193u, 132u, 71u, 210u,
- 141u, 126u, 169u, 45u,
- 133u, 116u, 96u, 176u,
- 230u, 190u, 11u, 114u,
- 0u, 70u, 98u, 31u,
- 112u, 111u, 85u, 124u,
- 225u, 108u, 109u, 156u,
- 109u, 149u, 1u, 38u,
- 103u, 147u, 120u, 124u,
- 54u, 178u, 43u, 130u,
- 179u, 172u, 46u, 0u,
- 212u, 50u, 62u, 168u,
- 92u, 230u, 30u, 18u,
- 157u, 15u, 205u, 50u,
- 134u, 115u, 118u, 147u,
- 152u, 194u, 72u, 205u,
- 128u, 63u, 96u, 102u,
- 84u, 86u, 87u, 1u,
- 136u, 133u, 126u, 156u,
- 59u, 255u, 74u, 169u,
- 168u, 9u, 64u, 183u,
- 215u, 116u, 238u, 82u,
- 154u, 71u, 141u, 243u,
- 26u, 128u, 25u, 255u,
- 113u, 176u, 52u, 16u,
- 131u, 190u, 47u, 203u,
- 126u, 255u, 143u, 108u,
- 86u, 26u, 74u, 61u,
- 93u, 69u, 6u, 49u,
- 129u, 169u, 248u, 184u,
- 68u, 104u, 102u, 227u,
- 255u, 83u, 156u, 119u,
- 50u, 153u, 94u, 65u,
- 147u, 163u, 86u, 191u,
- 1u, 66u, 77u, 123u,
- 127u, 171u, 121u, 135u,
- 194u, 127u, 149u, 176u,
- 98u, 195u, 147u, 43u,
- 146u, 112u, 102u, 193u,
- 129u, 180u, 26u, 255u,
- 106u, 115u, 181u, 229u,
- 158u, 203u, 139u, 24u,
- 7u, 40u, 127u, 99u,
- 116u, 66u, 119u, 103u,
- 122u, 255u, 152u, 96u,
- 196u, 144u, 147u, 133u,
- 197u, 239u, 252u, 61u,
- 129u, 80u, 193u, 166u,
- 40u, 146u, 166u, 189u,
- 1u, 161u, 74u, 27u,
- 178u, 131u, 35u, 184u,
- 85u, 191u, 6u, 78u,
- 1u, 141u, 137u, 30u,
- 89u, 228u, 143u, 142u,
- 39u, 168u, 129u, 115u,
- 141u, 238u, 109u, 159u,
- 255u, 120u, 143u, 147u,
- 137u, 133u, 79u, 62u,
- 158u, 44u, 134u, 149u,
- 33u, 124u, 44u, 160u,
- 106u, 159u, 144u, 158u,
- 150u, 255u, 122u, 155u,
- 134u, 115u, 174u, 95u,
- 173u, 88u, 72u, 171u,
- 135u, 153u, 237u, 1u,
- 138u, 60u, 206u, 194u,
- 102u, 178u, 125u, 181u,
- 97u, 66u, 153u, 96u,
- 166u, 156u, 77u, 191u,
- 110u, 255u, 240u, 181u,
- 1u, 145u, 63u, 152u,
- 129u, 42u, 178u, 113u,
- 244u, 187u, 176u, 61u,
- 232u, 118u, 38u, 233u,
- 30u, 102u, 174u, 31u,
- 239u, 173u, 172u, 194u,
- 120u, 249u, 18u, 172u,
- 34u, 255u, 86u, 59u,
- 110u, 99u, 144u, 158u,
- 132u, 141u, 128u, 130u,
- 88u, 103u, 149u, 1u,
- 195u, 222u, 159u, 48u,
- 145u, 148u, 187u, 175u,
- 185u, 133u, 59u, 127u,
- 1u, 59u, 100u, 191u,
- 69u, 177u, 51u, 127u,
- 21u, 71u, 127u, 255u,
- 67u, 61u, 234u, 27u,
- 92u, 139u, 26u, 167u,
- 184u, 154u, 94u, 112u,
- 85u, 115u, 237u, 149u,
- 26u, 127u, 182u, 126u,
- 249u, 124u, 158u, 203u,
- 63u, 255u, 88u, 201u,
- 123u, 174u, 1u, 106u,
- 139u, 151u, 133u, 120u,
- 84u, 200u, 31u, 138u,
- 170u, 102u, 14u, 53u,
- 177u, 46u, 98u, 24u,
- 41u, 19u, 86u, 120u,
- 188u, 255u, 174u, 148u,
- 214u, 92u, 71u, 56u,
- 139u, 170u, 162u, 125u,
- 116u, 131u, 85u, 168u,
- 255u, 161u, 140u, 112u,
- 86u, 41u, 82u, 199u,
- 141u, 137u, 116u, 134u,
- 102u, 142u, 72u, 139u,
- 177u, 114u, 191u, 41u,
- 1u, 52u, 103u, 107u,
- 87u, 171u, 45u, 121u,
- 168u, 52u, 110u, 1u,
- 187u, 228u, 82u, 54u,
- 107u, 22u, 57u, 166u,
- 99u, 218u, 107u, 24u,
- 188u, 250u, 176u, 118u,
- 123u, 156u, 139u, 200u,
- 1u, 163u, 83u, 161u,
- 131u, 156u, 61u, 109u,
- 168u, 148u, 93u, 92u,
- 117u, 161u, 157u, 45u,
- 61u, 1u, 161u, 188u,
- 210u, 100u, 142u, 102u,
- 122u, 25u, 65u, 233u,
- 1u, 194u, 82u, 62u,
- 151u, 149u, 207u, 92u,
- 109u, 248u, 202u, 196u,
- 175u, 85u, 225u, 109u,
- 150u, 121u, 65u, 203u,
- 38u, 124u, 1u, 142u,
- 95u, 123u, 234u, 142u,
- 165u, 107u, 209u, 153u,
- 1u, 105u, 245u, 80u,
- 242u, 185u, 107u, 208u,
- 193u, 13u, 69u, 48u,
- 91u, 163u, 137u, 102u,
- 170u, 77u, 0u, 175u,
- 39u, 74u, 99u, 116u,
- 171u, 84u, 1u, 83u,
- 53u, 33u, 195u, 182u,
- 166u, 151u, 177u, 144u,
- 98u, 244u, 29u, 109u,
- 167u, 145u, 113u, 198u,
- 160u, 79u, 165u, 113u,
- 255u, 99u, 69u, 103u,
- 138u, 39u, 149u, 131u,
- 52u, 95u, 169u, 178u,
- 118u, 15u, 159u, 197u,
- 63u, 125u, 156u, 255u,
- 188u, 138u, 164u, 97u,
- 208u, 81u, 48u, 106u,
- 87u, 1u, 61u, 206u,
- 105u, 152u, 133u, 104u,
- 29u, 221u, 132u, 223u,
- 80u, 119u, 87u, 135u,
- 148u, 255u, 122u, 219u,
- 114u, 141u, 166u, 23u,
- 64u, 147u, 47u, 153u,
- 250u, 177u, 1u, 44u,
- 238u, 35u, 248u, 146u,
- 5u, 110u, 81u, 97u,
- 56u, 247u, 72u, 23u,
- 101u, 92u, 145u, 8u,
- 156u, 141u, 92u, 187u,
- 110u, 110u, 255u, 78u,
- 127u, 31u, 52u, 74u,
- 46u, 173u, 62u, 84u,
- 84u, 135u, 170u, 215u,
- 31u, 79u, 165u, 144u,
- 119u, 1u, 7u, 111u,
- 154u, 111u, 83u, 156u,
- 185u, 93u, 20u, 192u,
- 243u, 204u, 255u, 64u,
- 37u, 92u, 43u, 85u,
- 160u, 89u, 123u, 0u,
- 126u, 158u, 93u, 140u,
- 133u, 151u, 180u, 98u,
- 46u, 112u, 213u, 193u,
- 179u, 174u, 167u, 220u,
- 255u, 219u, 60u, 150u,
- 46u, 253u, 185u, 197u,
- 51u, 158u, 208u, 58u,
- 154u, 103u, 217u, 244u,
- 135u, 255u, 193u, 118u,
- 78u, 78u, 139u, 180u,
- 68u, 203u, 165u, 100u,
- 81u, 149u, 49u, 125u,
- 46u, 160u, 120u, 56u,
- 156u, 238u, 255u, 143u,
- 71u, 60u, 151u, 62u,
- 18u, 102u, 18u, 62u,
- 62u, 93u, 54u, 255u,
- 102u, 210u, 137u, 90u,
- 109u, 162u, 191u, 69u,
- 109u, 157u, 150u, 255u,
- 110u, 105u, 200u, 159u,
- 109u, 120u, 96u, 169u,
- 81u, 148u, 136u, 219u,
- 107u, 95u, 245u, 128u,
- 139u, 202u, 141u, 142u,
- 156u, 241u, 74u, 91u,
- 45u, 136u, 255u, 105u,
- 82u, 52u, 173u, 158u,
- 43u, 63u, 151u, 161u,
- 198u, 129u, 125u, 92u,
- 255u, 139u, 159u, 120u,
- 133u, 223u, 114u, 195u,
- 141u, 114u, 190u, 188u,
- 255u, 105u, 194u, 109u,
- 163u, 255u, 249u, 83u,
- 128u, 156u, 138u, 99u,
- 120u, 189u, 158u, 255u,
- 165u, 128u, 183u, 193u,
- 38u, 122u, 127u, 132u,
- 60u, 77u, 105u, 92u,
- 220u, 75u, 128u, 23u,
- 1u, 134u, 133u, 182u,
- 82u, 222u, 144u, 169u,
- 201u, 118u, 96u, 88u,
- 95u, 54u, 168u, 73u,
- 141u, 44u, 82u, 78u,
- 218u, 157u, 107u, 255u,
- 255u, 46u, 64u, 174u,
- 53u, 87u, 43u, 138u,
- 135u, 27u, 123u, 106u,
- 132u, 136u, 225u, 69u,
- 194u, 102u, 234u, 123u,
- 255u, 134u, 83u, 112u,
- 177u, 151u, 133u, 170u,
- 125u, 165u, 223u, 126u,
- 12u, 164u, 122u, 213u,
- 94u, 102u, 245u, 164u,
- 240u, 192u, 150u, 99u,
- 191u, 1u, 126u, 195u,
- 59u, 109u, 116u, 174u,
- 110u, 156u, 124u, 152u,
- 43u, 130u, 152u, 131u,
- 199u, 195u, 147u, 1u,
- 156u, 255u, 128u, 140u,
- 185u, 99u, 153u, 51u,
- 137u, 99u, 59u, 140u,
- 123u, 126u, 93u, 104u,
- 1u, 229u, 52u, 135u,
- 172u, 56u, 131u, 149u,
- 173u, 235u, 197u, 111u,
- 214u, 204u, 79u, 178u,
- 118u, 255u, 90u, 204u,
- 179u, 89u, 94u, 117u,
- 132u, 119u, 126u, 194u,
- 183u, 89u, 93u, 159u,
- 114u, 167u, 130u, 91u,
- 59u, 70u, 106u, 38u,
- 186u, 170u, 100u, 96u,
- 228u, 47u, 1u, 117u,
- 194u, 158u, 209u, 71u,
- 125u, 105u, 199u, 74u,
- 157u, 142u, 143u, 132u,
- 163u, 62u, 255u, 250u,
- 103u, 255u, 120u, 144u,
- 119u, 131u, 159u, 87u,
- 206u, 179u, 174u, 198u,
- 152u, 118u, 98u, 134u,
- 144u, 89u, 115u, 162u,
- 26u, 123u, 125u, 177u,
- 176u, 75u, 120u, 234u,
- 3u, 109u, 255u, 186u,
- 105u, 194u, 115u, 117u,
- 149u, 215u, 195u, 104u,
- 191u, 77u, 61u, 1u,
- 57u, 25u, 132u, 170u,
- 80u, 217u, 185u, 28u,
- 234u, 213u, 167u, 64u,
- 136u, 89u, 135u, 138u,
- 15u, 1u, 105u, 187u,
- 161u, 75u, 128u, 178u,
- 45u, 163u, 115u, 132u,
- 158u, 129u, 134u, 36u,
- 87u, 105u, 255u, 242u,
- 217u, 96u, 181u, 79u,
- 89u, 125u, 194u, 3u,
- 121u, 136u, 123u, 139u,
- 136u, 192u, 199u, 255u,
- 193u, 83u, 153u, 160u,
- 39u, 176u, 186u, 182u,
- 179u, 107u, 255u, 183u,
- 92u, 0u, 81u, 184u,
- 212u, 205u, 156u, 123u,
- 207u, 198u, 83u, 122u,
- 31u, 140u, 183u, 131u,
- 51u, 1u, 188u, 96u,
- 188u, 163u, 142u, 147u,
- 217u, 167u, 172u, 177u,
- 150u, 118u, 132u, 173u,
- 92u, 159u, 255u, 115u,
- 120u, 105u, 3u, 255u,
- 150u, 250u, 133u, 110u,
- 85u, 47u, 82u, 82u,
- 59u, 130u, 20u, 237u,
- 68u, 143u, 171u, 169u,
- 102u, 16u, 1u, 107u,
- 149u, 126u, 42u, 174u,
- 179u, 244u, 201u, 122u,
- 117u, 3u, 145u, 193u,
- 136u, 29u, 245u, 189u,
- 220u, 161u, 85u, 1u,
- 136u, 212u, 130u, 185u,
- 115u, 1u, 94u, 189u,
- 95u, 159u, 61u, 92u,
- 130u, 109u, 125u, 156u,
- 146u, 136u, 146u, 131u,
- 196u, 105u, 144u, 140u,
- 15u, 61u, 27u, 171u,
- 255u, 174u, 70u, 143u,
- 175u, 55u, 232u, 63u,
- 101u, 148u, 186u, 120u,
- 156u, 58u, 222u, 155u,
- 14u, 0u, 160u, 124u,
- 133u, 122u, 63u, 167u,
- 180u, 152u, 85u, 191u,
- 87u, 255u, 156u, 158u,
- 97u, 121u, 80u, 112u,
- 10u, 231u, 163u, 102u,
- 153u, 157u, 131u, 148u,
- 76u, 85u, 83u, 152u,
- 107u, 74u, 121u, 255u,
- 166u, 151u, 163u, 53u,
- 255u, 50u, 141u, 169u,
- 207u, 137u, 142u, 121u,
- 126u, 122u, 198u, 114u,
- 169u, 132u, 102u, 90u,
- 146u, 204u, 232u, 174u,
- 255u, 104u, 225u, 229u,
- 181u, 71u, 156u, 69u,
- 2u, 144u, 196u, 160u,
- 136u, 175u, 148u, 135u,
- 130u, 70u, 158u, 142u,
- 153u, 198u, 115u, 171u,
- 1u, 226u, 134u, 148u,
- 63u, 148u, 95u, 115u,
- 1u, 194u, 92u, 88u,
- 74u, 165u, 100u, 191u,
- 78u, 100u, 127u, 155u,
- 181u, 140u, 138u, 0u,
- 167u, 140u, 196u, 48u,
- 94u, 214u, 155u, 119u,
- 202u, 2u, 87u, 211u,
- 159u, 134u, 67u, 55u,
- 182u, 146u, 129u, 166u,
- 176u, 215u, 67u, 255u,
- 150u, 185u, 250u, 63u,
- 255u, 137u, 175u, 31u,
- 142u, 174u, 58u, 190u,
- 162u, 132u, 152u, 104u,
- 94u, 99u, 206u, 119u,
- 213u, 23u, 183u, 118u,
- 168u, 238u, 133u, 202u,
- 134u, 119u, 88u, 191u,
- 85u, 31u, 129u, 1u,
- 249u, 165u, 183u, 109u,
- 106u, 91u, 88u, 171u,
- 191u, 90u, 255u, 135u,
- 209u, 109u, 177u, 188u,
- 171u, 145u, 76u, 219u,
- 0u, 174u, 75u, 83u,
- 160u, 169u, 111u, 95u,
- 48u, 121u, 145u, 171u,
- 136u, 37u, 123u, 117u,
- 120u, 167u, 100u, 169u,
- 255u, 139u, 227u, 131u,
- 49u, 140u, 125u, 152u,
- 41u, 62u, 85u, 201u,
- 70u, 171u, 41u, 104u,
- 151u, 69u, 173u, 113u,
- 89u, 83u, 1u, 70u,
- 97u, 92u, 255u, 87u,
- 186u, 59u, 138u, 204u,
- 163u, 147u, 201u, 221u,
- 240u, 198u, 88u, 28u,
- 212u, 74u, 61u, 115u,
- 164u, 174u, 82u, 226u,
- 60u, 0u, 196u, 132u,
- 137u, 125u, 56u, 189u,
- 114u, 1u, 41u, 229u,
- 71u, 164u, 78u, 128u,
- 29u, 162u, 153u, 152u,
- 191u, 238u, 52u, 86u,
- 127u, 117u, 73u, 202u,
- 120u, 44u, 103u, 255u,
- 170u, 145u, 112u, 130u,
- 251u, 101u, 79u, 66u,
- 216u, 140u, 146u, 175u,
- 172u, 126u, 81u, 124u,
- 42u, 40u, 127u, 65u,
- 124u, 137u, 0u, 87u,
- 154u, 127u, 156u, 132u,
- 144u, 186u, 144u, 184u,
- 93u, 118u, 139u, 122u,
- 1u, 123u, 120u, 88u,
- 28u, 193u, 138u, 179u,
- 174u, 10u, 229u, 175u,
- 127u, 131u, 103u, 255u,
- 215u, 134u, 32u, 80u,
- 79u, 139u, 85u, 159u,
- 173u, 103u, 255u, 154u,
- 180u, 44u, 133u, 44u,
- 163u, 89u, 49u, 131u,
- 177u, 128u, 116u, 164u,
- 96u, 0u, 137u, 195u,
- 69u, 118u, 143u, 115u,
- 185u, 86u, 45u, 90u,
- 120u, 166u, 255u, 17u,
- 86u, 95u, 116u, 161u,
- 77u, 135u, 176u, 99u,
- 72u, 15u, 103u, 95u,
- 172u, 195u, 155u, 155u,
- 164u, 108u, 65u, 159u,
- 56u, 132u, 75u, 156u,
- 255u, 241u, 255u, 80u,
- 173u, 1u, 32u, 94u,
- 81u, 110u, 84u, 170u,
- 85u, 192u, 118u, 102u,
- 38u, 179u, 224u, 164u,
- 142u, 191u, 106u, 194u,
- 1u, 160u, 197u, 89u,
- 255u, 118u, 231u, 120u,
- 131u, 61u, 203u, 238u,
- 216u, 255u, 132u, 117u,
- 159u, 201u, 75u, 229u,
- 152u, 61u, 233u, 195u,
- 221u, 104u, 78u, 255u,
- 172u, 43u, 135u, 189u,
- 114u, 162u, 151u, 190u,
- 1u, 185u, 162u, 200u,
- 132u, 136u, 181u, 31u,
- 159u, 114u, 143u, 155u,
- 170u, 76u, 122u, 118u,
- 141u, 89u, 218u, 255u,
- 142u, 79u, 129u, 92u,
- 70u, 130u, 107u, 95u,
- 78u, 111u, 1u, 109u,
- 24u, 157u, 127u, 74u,
- 238u, 125u, 231u, 83u,
- 177u, 153u, 169u, 90u,
- 150u, 41u, 163u, 8u,
- 193u, 107u, 115u, 39u,
- 138u, 39u, 0u, 136u,
- 57u, 188u, 134u, 236u,
- 196u, 220u, 9u, 255u,
- 201u, 171u, 100u, 157u,
- 29u, 199u, 191u, 36u,
- 26u, 145u, 37u, 90u,
- 158u, 190u, 108u, 212u,
- 63u, 120u, 136u, 12u,
- 168u, 152u, 1u, 236u,
- 130u, 175u, 115u, 102u,
- 177u, 157u, 22u, 75u,
- 249u, 137u, 87u, 110u,
- 255u, 157u, 145u, 112u,
- 141u, 142u, 62u, 155u,
- 148u, 1u, 158u, 196u,
- 187u, 239u, 50u, 156u,
- 125u, 85u, 136u, 40u,
- 232u, 66u, 103u, 160u,
- 76u, 177u, 1u, 90u,
- 119u, 94u, 135u, 128u,
- 147u, 167u, 211u, 71u,
- 185u, 123u, 243u, 146u,
- 75u, 168u, 206u, 98u,
- 227u, 162u, 255u, 103u,
- 194u, 71u, 205u, 70u,
- 67u, 140u, 153u, 164u,
- 182u, 181u, 139u, 3u,
- 1u, 215u, 38u, 95u,
- 186u, 83u, 55u, 83u,
- 33u, 122u, 120u, 125u,
- 109u, 154u, 169u, 255u,
- 184u, 130u, 84u, 150u,
- 12u, 131u, 150u, 106u,
- 193u, 177u, 255u, 219u,
- 218u, 106u, 64u, 158u,
- 143u, 68u, 59u, 218u,
- 67u, 67u, 192u, 66u,
- 224u, 225u, 76u, 15u,
- 148u, 213u, 108u, 255u,
- 87u, 138u, 111u, 58u,
- 158u, 150u, 163u, 172u,
- 255u, 167u, 194u, 174u,
- 126u, 173u, 178u, 133u,
- 106u, 61u, 108u, 247u,
- 50u, 72u, 98u, 127u,
- 129u, 190u, 112u, 98u,
- 196u, 144u, 110u, 140u,
- 69u, 64u, 161u, 107u,
- 143u, 190u, 1u, 182u,
- 66u, 164u, 104u, 86u,
- 207u, 106u, 145u, 110u,
- 104u, 255u, 44u, 46u,
- 68u, 130u, 29u, 109u,
- 134u, 126u, 67u, 99u,
- 117u, 156u, 140u, 144u,
- 139u, 103u, 95u, 221u,
- 0u, 123u, 64u, 181u,
- 197u, 107u, 153u, 100u,
- 185u, 148u, 89u, 255u,
- 137u, 117u, 142u, 156u,
- 129u, 144u, 147u, 178u,
- 100u, 116u, 107u, 129u,
- 255u, 134u, 70u, 118u,
- 69u, 11u, 88u, 44u,
- 224u, 238u, 136u, 107u,
- 238u, 138u, 140u, 1u,
- 146u, 237u, 197u, 196u,
- 90u, 52u, 81u, 83u,
- 153u, 239u, 106u, 242u,
- 87u, 124u, 136u, 63u,
- 136u, 122u, 45u, 117u,
- 139u, 73u, 131u, 1u,
- 122u, 54u, 100u, 70u,
- 153u, 152u, 137u, 111u,
- 126u, 255u, 61u, 179u,
- 61u, 170u, 158u, 124u,
- 76u, 112u, 61u, 55u,
- 110u, 244u, 129u, 119u,
- 120u, 64u, 139u, 99u,
- 6u, 58u, 177u, 64u,
- 86u, 23u, 84u, 255u,
- 105u, 132u, 0u, 71u,
- 200u, 126u, 188u, 90u,
- 64u, 187u, 106u, 92u,
- 232u, 120u, 23u, 125u,
- 101u, 211u, 99u, 80u,
- 87u, 86u, 175u, 1u,
- 154u, 111u, 89u, 103u,
- 27u, 99u, 85u, 185u,
- 131u, 83u, 165u, 255u,
- 60u, 154u, 49u, 196u,
- 115u, 113u, 104u, 219u,
- 73u, 163u, 183u, 78u,
- 65u, 186u, 68u, 168u,
- 51u, 228u, 62u, 73u,
- 255u, 111u, 137u, 143u,
- 191u, 151u, 111u, 156u,
- 115u, 180u, 82u, 108u,
- 121u, 255u, 132u, 212u,
- 126u, 34u, 80u, 147u,
- 12u, 78u, 84u, 129u,
- 187u, 29u, 130u, 99u,
- 26u, 209u, 0u, 42u,
- 60u, 114u, 4u, 84u,
- 197u, 80u, 130u, 104u,
- 128u, 156u, 209u, 210u,
- 219u, 1u, 47u, 185u,
- 155u, 203u, 88u, 160u,
- 104u, 202u, 168u, 174u,
- 144u, 146u, 88u, 68u,
- 125u, 187u, 165u, 102u,
- 154u, 121u, 107u, 90u,
- 255u, 145u, 49u, 169u,
- 71u, 124u, 162u, 188u,
- 108u, 110u, 165u, 147u,
- 131u, 116u, 163u, 119u,
- 178u, 133u, 102u, 0u,
- 255u, 147u, 132u, 153u,
- 177u, 145u, 149u, 116u,
- 180u, 144u, 184u, 149u,
- 46u, 169u, 165u, 156u,
- 103u, 171u, 89u, 73u,
- 255u, 146u, 194u, 68u,
- 54u, 215u, 234u, 29u,
- 116u, 81u, 57u, 171u,
- 63u, 36u, 55u, 133u,
- 112u, 69u, 130u, 179u,
- 186u, 173u, 104u, 35u,
- 144u, 86u, 156u, 255u,
- 134u, 163u, 169u, 87u,
- 255u, 155u, 103u, 168u,
- 86u, 154u, 207u, 180u,
- 191u, 84u, 89u, 33u,
- 97u, 216u, 116u, 65u,
- 141u, 117u, 209u, 77u,
- 172u, 175u, 121u, 142u,
- 127u, 39u, 112u, 255u,
- 84u, 73u, 124u, 89u,
- 174u, 158u, 101u, 139u,
- 18u, 113u, 141u, 152u,
- 255u, 229u, 117u, 165u,
- 48u, 245u, 152u, 80u,
- 227u, 185u, 106u, 141u,
- 56u, 72u, 91u, 72u,
- 63u, 101u, 0u, 126u,
- 64u, 58u, 158u, 164u,
- 139u, 220u, 104u, 71u,
- 231u, 182u, 157u, 132u,
- 221u, 255u, 101u, 103u,
- 145u, 81u, 1u, 47u,
- 4u, 122u, 197u, 113u,
- 119u, 107u, 17u, 230u,
- 103u, 151u, 228u, 175u,
- 190u, 72u, 190u, 99u,
- 68u, 97u, 98u, 71u,
- 121u, 203u, 193u, 89u,
- 255u, 162u, 93u, 37u,
- 109u, 155u, 113u, 184u,
- 101u, 112u, 55u, 65u,
- 100u, 129u, 177u, 80u,
- 159u, 1u, 184u, 144u,
- 212u, 117u, 204u, 118u,
- 176u, 89u, 15u, 140u,
- 157u, 245u, 164u, 8u,
- 255u, 245u, 216u, 176u,
- 103u, 119u, 111u, 123u,
- 114u, 170u, 177u, 111u,
- 100u, 146u, 109u, 89u,
- 186u, 150u, 103u, 1u,
- 163u, 185u, 162u, 174u,
- 70u, 162u, 124u, 117u,
- 98u, 81u, 99u, 1u,
- 74u, 194u, 117u, 190u,
- 142u, 214u, 175u, 129u,
- 131u, 151u, 65u, 43u,
- 132u, 185u, 95u, 224u,
- 78u, 44u, 95u, 255u,
- 177u, 99u, 155u, 182u,
- 77u, 150u, 37u, 252u,
- 109u, 74u, 171u, 133u,
- 156u, 1u, 144u, 151u,
- 191u, 188u, 152u, 77u,
- 101u, 197u, 225u, 35u,
- 159u, 80u, 180u, 234u,
- 132u, 51u, 255u, 147u,
- 164u, 57u, 138u, 180u,
- 122u, 161u, 127u, 92u,
- 192u, 61u, 192u, 62u,
- 255u, 138u, 87u, 109u,
- 241u, 242u, 212u, 144u,
- 193u, 235u, 74u, 28u,
- 255u, 166u, 48u, 156u,
- 103u, 137u, 28u, 221u,
- 87u, 38u, 10u, 83u,
- 85u, 210u, 255u, 128u,
- 46u, 111u, 133u, 135u,
- 38u, 168u, 208u, 92u,
- 1u, 102u, 115u, 202u,
- 147u, 80u, 57u, 201u,
- 54u, 24u, 126u, 217u,
- 232u, 93u, 98u, 89u,
- 199u, 136u, 192u, 127u,
- 183u, 36u, 38u, 129u,
- 149u, 157u, 255u, 180u,
- 146u, 109u, 7u, 127u,
- 104u, 145u, 188u, 190u,
- 104u, 255u, 164u, 76u,
- 103u, 46u, 158u, 144u,
- 80u, 62u, 146u, 135u,
- 105u, 255u, 147u, 96u,
- 95u, 84u, 24u, 122u,
- 240u, 116u, 62u, 205u,
- 176u, 200u, 155u, 161u,
- 60u, 195u, 126u, 168u,
- 160u, 83u, 153u, 73u,
- 255u, 196u, 214u, 233u,
- 121u, 95u, 82u, 184u,
- 183u, 110u, 85u, 137u,
- 59u, 144u, 46u, 47u,
- 82u, 49u, 154u, 77u,
- 255u, 164u, 91u, 162u,
- 86u, 123u, 194u, 86u,
- 209u, 60u, 255u, 141u,
- 160u, 146u, 122u, 1u,
- 108u, 221u, 107u, 153u,
- 105u, 90u, 149u, 180u,
- 82u, 169u, 252u, 223u,
- 134u, 227u, 148u, 128u,
- 9u, 224u, 138u, 0u,
- 130u, 255u, 169u, 88u,
- 94u, 218u, 70u, 108u,
- 187u, 42u, 206u, 138u,
- 78u, 98u, 182u, 110u,
- 191u, 1u, 195u, 128u,
- 23u, 132u, 87u, 136u,
- 150u, 238u, 108u, 98u,
- 176u, 49u, 242u, 214u,
- 101u, 100u, 47u, 162u,
- 19u, 73u, 10u, 164u,
- 79u, 127u, 175u, 57u,
- 133u, 255u, 101u, 234u,
- 84u, 125u, 62u, 75u,
- 117u, 136u, 130u, 65u,
- 151u, 96u, 19u, 92u,
- 75u, 107u, 0u, 106u,
- 150u, 208u, 132u, 129u,
- 128u, 146u, 95u, 108u,
- 178u, 50u, 19u, 127u,
- 38u, 125u, 1u, 129u,
- 139u, 182u, 178u, 147u,
- 69u, 130u, 125u, 74u,
- 162u, 140u, 255u, 76u,
- 232u, 61u, 102u, 137u,
- 108u, 94u, 38u, 157u,
- 58u, 166u, 159u, 165u,
- 91u, 189u, 146u, 136u,
- 42u, 177u, 1u, 163u,
- 113u, 252u, 99u, 118u,
- 225u, 202u, 255u, 103u,
- 180u, 150u, 120u, 75u,
- 159u, 88u, 155u, 152u,
- 1u, 142u, 30u, 226u,
- 67u, 199u, 27u, 4u,
- 172u, 200u, 200u, 140u,
- 107u, 90u, 247u, 85u,
- 71u, 174u, 140u, 98u,
- 1u, 51u, 104u, 86u,
- 171u, 133u, 159u, 99u,
- 120u, 154u, 153u, 167u,
- 136u, 155u, 87u, 87u,
- 173u, 73u, 132u, 132u,
- 1u, 211u, 127u, 91u,
- 216u, 45u, 223u, 50u,
- 1u, 162u, 161u, 186u,
- 207u, 166u, 163u, 62u,
- 134u, 121u, 123u, 78u,
- 187u, 93u, 178u, 137u,
- 61u, 62u, 1u, 225u,
- 122u, 129u, 196u, 104u,
- 167u, 91u, 142u, 160u,
- 126u, 105u, 16u, 137u,
- 44u, 201u, 103u, 208u,
- 166u, 255u, 83u, 195u,
- 177u, 96u, 168u, 175u,
- 26u, 164u, 114u, 200u,
- 141u, 159u, 90u, 61u,
- 146u, 131u, 101u, 208u,
- 147u, 130u, 123u, 87u,
- 115u, 151u, 1u, 121u,
- 170u, 120u, 209u, 130u,
- 1u, 135u, 82u, 146u,
- 157u, 104u, 173u, 96u,
- 150u, 93u, 49u, 102u,
- 255u, 110u, 195u, 123u,
- 167u, 111u, 87u, 132u,
- 207u, 188u, 144u, 107u,
- 179u, 97u, 155u, 114u,
- 121u, 255u, 169u, 78u,
- 130u, 165u, 185u, 115u,
- 237u, 113u, 116u, 40u,
- 131u, 59u, 228u, 220u,
- 137u, 174u, 196u, 1u,
- 198u, 136u, 98u, 5u,
- 80u, 217u, 234u, 51u,
- 154u, 184u, 147u, 2u,
- 126u, 127u, 140u, 130u,
- 97u, 88u, 161u, 187u,
- 162u, 130u, 0u, 127u,
- 118u, 100u, 174u, 180u,
- 139u, 255u, 189u, 91u,
- 201u, 73u, 170u, 193u,
- 199u, 150u, 35u, 168u,
- 176u, 102u, 1u, 116u,
- 99u, 101u, 94u, 133u,
- 59u, 255u, 245u, 201u,
- 100u, 143u, 100u, 108u,
- 90u, 229u, 132u, 114u,
- 163u, 39u, 133u, 129u,
- 107u, 133u, 43u, 181u,
- 32u, 68u, 104u, 74u,
- 145u, 135u, 1u, 143u,
- 112u, 171u, 255u, 110u,
- 94u, 142u, 121u, 125u,
- 119u, 98u, 142u, 187u,
- 1u, 120u, 157u, 123u,
- 54u, 191u, 170u, 176u,
- 67u, 86u, 122u, 58u,
- 128u, 155u, 73u, 255u,
- 67u, 231u, 42u, 165u,
- 89u, 159u, 157u, 120u,
- 141u, 120u, 136u, 111u,
- 83u, 154u, 153u, 142u,
- 130u, 170u, 255u, 18u,
- 181u, 132u, 183u, 147u,
- 102u, 147u, 111u, 187u,
- 134u, 116u, 127u, 147u,
- 147u, 124u, 255u, 174u,
- 124u, 235u, 61u, 112u,
- 165u, 109u, 213u, 8u,
- 157u, 126u, 1u, 208u,
- 121u, 90u, 121u, 120u,
- 93u, 165u, 127u, 33u,
- 112u, 198u, 163u, 52u,
- 69u, 143u, 94u, 201u,
- 113u, 149u, 1u, 160u,
- 157u, 132u, 255u, 107u,
- 75u, 58u, 91u, 45u,
- 159u, 163u, 168u, 127u,
- 134u, 135u, 132u, 151u,
- 177u, 97u, 26u, 172u,
- 92u, 170u, 60u, 96u,
- 72u, 115u, 73u, 85u,
- 113u, 143u, 255u, 104u,
- 117u, 157u, 106u, 170u,
- 214u, 191u, 152u, 79u,
- 112u, 72u, 199u, 218u,
- 1u, 88u, 182u, 146u,
- 207u, 157u, 142u, 44u,
- 150u, 121u, 143u, 83u,
- 67u, 152u, 125u, 0u,
- 120u, 121u, 157u, 132u,
- 229u, 85u, 39u, 152u,
- 1u, 141u, 155u, 91u,
- 241u, 150u, 61u, 133u,
- 153u, 107u, 144u, 105u,
- 141u, 68u, 157u, 232u,
- 155u, 97u, 126u, 158u,
- 159u, 153u, 150u, 235u,
- 255u, 222u, 107u, 107u,
- 148u, 119u, 255u, 92u,
- 108u, 116u, 215u, 50u,
- 95u, 83u, 149u, 102u,
- 97u, 112u, 174u, 95u,
- 225u, 166u, 112u, 156u,
- 137u, 132u, 135u, 236u,
- 210u, 169u, 152u, 210u,
- 164u, 1u, 250u, 165u,
- 136u, 211u, 26u, 123u,
- 145u, 226u, 66u, 18u,
- 1u, 114u, 70u, 70u,
- 40u, 58u, 106u, 159u,
- 125u, 136u, 151u, 138u,
- 19u, 138u, 95u, 93u,
- 141u, 80u, 143u, 141u,
- 145u, 123u, 219u, 255u,
- 200u, 131u, 122u, 84u,
- 83u, 166u, 156u, 118u,
- 114u, 168u, 1u, 118u,
- 159u, 189u, 128u, 191u,
- 73u, 165u, 53u, 164u,
- 103u, 189u, 216u, 236u,
- 72u, 200u, 220u, 203u,
- 15u, 119u, 255u, 158u,
- 206u, 161u, 122u, 190u,
- 38u, 254u, 133u, 13u,
- 7u, 1u, 99u, 176u,
- 199u, 88u, 118u, 232u,
- 87u, 166u, 174u, 158u,
- 42u, 189u, 125u, 70u,
- 39u, 110u, 162u, 168u,
- 193u, 255u, 199u, 129u,
- 127u, 170u, 0u, 162u,
- 154u, 214u, 59u, 136u,
- 69u, 147u, 109u, 193u,
- 3u, 121u, 134u, 114u,
- 151u, 121u, 180u, 102u,
- 188u, 201u, 131u, 75u,
- 0u, 120u, 84u, 93u,
- 139u, 172u, 64u, 84u,
- 255u, 118u, 101u, 145u,
- 137u, 252u, 159u, 248u,
- 115u, 121u, 193u, 142u,
- 143u, 106u, 123u, 77u,
- 59u, 36u, 185u, 117u,
- 192u, 94u, 130u, 205u,
- 198u, 245u, 64u, 255u,
- 50u, 104u, 174u, 40u,
- 139u, 140u, 94u, 152u,
- 166u, 118u, 101u, 182u,
- 142u, 81u, 191u, 142u,
- 153u, 214u, 255u, 125u,
- 145u, 212u, 157u, 169u,
- 161u, 172u, 67u, 124u,
- 233u, 111u, 186u, 111u,
- 80u, 77u, 255u, 213u,
- 197u, 176u, 201u, 126u,
- 41u, 144u, 1u, 136u,
- 108u, 170u, 165u, 144u,
- 142u, 126u, 101u, 57u,
- 70u, 255u, 165u, 240u,
- 171u, 159u, 126u, 244u,
- 44u, 177u, 145u, 159u,
- 174u, 247u, 234u, 61u,
- 184u, 169u, 192u, 255u,
- 114u, 78u, 14u, 142u,
- 68u, 88u, 124u, 163u,
- 177u, 167u, 175u, 35u,
- 196u, 105u, 131u, 189u,
- 127u, 151u, 0u, 131u,
- 123u, 112u, 124u, 9u,
- 123u, 203u, 168u, 154u,
- 114u, 246u, 77u, 55u,
- 165u, 21u, 93u, 108u,
- 239u, 147u, 72u, 131u,
- 227u, 161u, 101u, 255u,
- 140u, 93u, 203u, 77u,
- 211u, 100u, 97u, 106u,
- 1u, 173u, 177u, 71u,
- 222u, 85u, 77u, 127u,
- 181u, 255u, 176u, 151u,
- 130u, 133u, 73u, 86u,
- 162u, 94u, 195u, 195u,
- 145u, 53u, 146u, 138u,
- 201u, 141u, 193u, 200u,
- 59u, 96u, 93u, 161u,
- 143u, 188u, 186u, 134u,
- 255u, 63u, 168u, 162u,
- 84u, 255u, 172u, 48u,
- 115u, 223u, 134u, 217u,
- 90u, 45u, 34u, 194u,
- 70u, 130u, 172u, 180u,
- 0u, 51u, 111u, 139u,
- 112u, 55u, 107u, 103u,
- 179u, 181u, 185u, 30u,
- 221u, 97u, 36u, 144u,
- 110u, 245u, 78u, 171u,
- 241u, 62u, 118u, 15u,
- 41u, 0u, 205u, 255u,
- 175u, 158u, 28u, 128u,
- 72u, 127u, 104u, 82u,
- 181u, 104u, 248u, 172u,
- 97u, 82u, 184u, 153u,
- 220u, 11u, 1u, 162u,
- 149u, 213u, 69u, 112u,
- 184u, 97u, 115u, 187u,
- 165u, 165u, 193u, 54u,
- 159u, 255u, 113u, 73u,
- 39u, 117u, 142u, 88u,
- 102u, 97u, 255u, 109u,
- 119u, 110u, 87u, 158u,
- 75u, 138u, 106u, 134u,
- 177u, 215u, 155u, 94u,
- 165u, 244u, 127u, 82u,
- 46u, 191u, 83u, 179u,
- 190u, 97u, 94u, 1u,
- 178u, 150u, 199u, 169u,
- 97u, 102u, 71u, 144u,
- 255u, 169u, 78u, 164u,
- 177u, 79u, 101u, 102u,
- 1u, 38u, 29u, 251u,
- 62u, 170u, 143u, 78u,
- 90u, 129u, 177u, 88u,
- 114u, 193u, 88u, 130u,
- 123u, 137u, 124u, 255u,
- 148u, 151u, 127u, 140u,
- 214u, 132u, 103u, 120u,
- 164u, 180u, 194u, 127u,
- 130u, 113u, 84u, 107u,
- 141u, 125u, 173u, 110u,
- 73u, 101u, 120u, 101u,
- 1u, 106u, 179u, 117u,
- 200u, 131u, 212u, 246u,
- 27u, 1u, 32u, 125u,
- 126u, 228u, 109u, 211u,
- 168u, 105u, 218u, 33u,
- 75u, 188u, 110u, 91u,
- 118u, 168u, 146u, 126u,
- 64u, 89u, 115u, 123u,
- 80u, 149u, 1u, 137u,
- 151u, 153u, 61u, 176u,
- 94u, 103u, 164u, 26u,
- 115u, 152u, 246u, 255u,
- 98u, 180u, 235u, 125u,
- 221u, 128u, 199u, 120u,
- 11u, 116u, 155u, 201u,
- 158u, 50u, 124u, 208u,
- 105u, 112u, 255u, 6u,
- 96u, 167u, 62u, 81u,
- 146u, 255u, 197u, 183u,
- 112u, 144u, 168u, 140u,
- 99u, 73u, 139u, 110u,
- 226u, 236u, 204u, 208u,
- 25u, 255u, 123u, 131u,
- 144u, 197u, 80u, 147u,
- 152u, 127u, 100u, 25u,
- 105u, 106u, 146u, 64u,
- 155u, 135u, 121u, 242u,
- 49u, 137u, 67u, 32u,
- 115u, 187u, 1u, 103u,
- 159u, 93u, 147u, 134u,
- 122u, 202u, 55u, 112u,
- 107u, 150u, 149u, 117u,
- 116u, 186u, 1u, 41u,
- 44u, 59u, 67u, 93u,
- 153u, 160u, 255u, 211u,
- 204u, 178u, 212u, 161u,
- 217u, 221u, 132u, 130u,
- 64u, 73u, 98u, 41u,
- 86u, 78u, 158u, 114u,
- 91u, 92u, 97u, 100u,
- 23u, 151u, 1u, 151u,
- 102u, 67u, 245u, 87u,
- 208u, 208u, 160u, 1u,
- 79u, 140u, 127u, 49u,
- 91u, 177u, 146u, 113u,
- 119u, 161u, 149u, 134u,
- 150u, 160u, 73u, 162u,
- 153u, 95u, 106u, 255u,
- 213u, 139u, 0u, 161u,
- 176u, 92u, 16u, 82u,
- 109u, 29u, 136u, 232u,
- 145u, 117u, 76u, 78u,
- 148u, 255u, 182u, 124u,
- 151u, 85u, 1u, 143u,
- 137u, 143u, 124u, 187u,
- 159u, 116u, 122u, 78u,
- 99u, 135u, 168u, 179u,
- 170u, 169u, 223u, 184u,
- 189u, 170u, 100u, 189u,
- 84u, 77u, 255u, 174u,
- 108u, 171u, 138u, 188u,
- 175u, 113u, 149u, 28u,
- 224u, 156u, 166u, 255u,
- 120u, 181u, 206u, 160u,
- 78u, 219u, 70u, 162u,
- 109u, 164u, 112u, 227u,
- 155u, 158u, 228u, 92u,
- 24u, 102u, 255u, 122u,
- 187u, 46u, 115u, 47u,
- 148u, 207u, 136u, 101u,
- 166u, 121u, 188u, 67u,
- 128u, 35u, 1u, 89u,
- 149u, 149u, 176u, 245u,
- 202u, 185u, 98u, 74u,
- 9u, 174u, 130u, 255u,
- 175u, 116u, 158u, 210u,
- 117u, 68u, 61u, 53u,
- 145u, 219u, 165u, 109u,
- 203u, 255u, 234u, 150u,
- 104u, 177u, 189u, 189u,
- 79u, 190u, 115u, 157u,
- 103u, 116u, 70u, 136u,
- 62u, 122u, 225u, 119u,
- 1u, 44u, 121u, 133u,
- 131u, 181u, 132u, 69u,
- 56u, 49u, 60u, 61u,
- 115u, 255u, 160u, 189u,
- 30u, 95u, 230u, 181u,
- 107u, 117u, 30u, 152u,
- 167u, 74u, 175u, 39u,
- 106u, 76u, 122u, 175u,
- 162u, 171u, 116u, 117u,
- 116u, 137u, 238u, 1u,
- 67u, 83u, 96u, 91u,
- 130u, 73u, 105u, 186u,
- 213u, 255u, 197u, 106u,
- 188u, 167u, 175u, 69u,
- 161u, 117u, 135u, 197u,
- 153u, 140u, 159u, 155u,
- 92u, 209u, 103u, 255u,
- 162u, 72u, 240u, 86u,
- 75u, 172u, 152u, 166u,
- 174u, 47u, 255u, 192u,
- 144u, 141u, 118u, 155u,
- 116u, 151u, 162u, 137u,
- 131u, 156u, 255u, 249u,
- 139u, 137u, 142u, 104u,
- 25u, 139u, 37u, 180u,
- 40u, 116u, 196u, 68u,
- 63u, 212u, 145u, 227u,
- 134u, 49u, 255u, 175u,
- 88u, 121u, 174u, 133u,
- 118u, 125u, 105u, 148u,
- 121u, 97u, 206u, 66u,
- 104u, 172u, 193u, 167u,
- 192u, 147u, 92u, 125u,
- 165u, 255u, 135u, 186u,
- 87u, 78u, 226u, 174u,
- 0u, 131u, 122u, 75u,
- 106u, 55u, 86u, 156u,
- 170u, 80u, 123u, 66u,
- 109u, 136u, 154u, 119u,
- 111u, 44u, 144u, 138u,
- 159u, 144u, 1u, 217u,
- 137u, 255u, 64u, 174u,
- 179u, 30u, 205u, 137u,
- 9u, 142u, 38u, 175u,
- 80u, 43u, 213u, 121u,
- 1u, 96u, 215u, 135u,
- 246u, 90u, 217u, 84u,
- 220u, 203u, 52u, 235u,
- 252u, 133u, 53u, 147u,
- 136u, 171u, 58u, 255u,
- 255u, 69u, 82u, 128u,
- 17u, 172u, 56u, 185u,
- 170u, 163u, 53u, 96u,
- 118u, 99u, 127u, 141u,
- 167u, 56u, 137u, 88u,
- 51u, 229u, 16u, 126u,
- 72u, 128u, 175u, 1u,
- 178u, 88u, 188u, 23u,
- 148u, 78u, 169u, 70u,
- 180u, 44u, 133u, 106u,
- 190u, 167u, 38u, 113u,
- 68u, 140u, 57u, 0u,
- 188u, 3u, 137u, 146u,
- 52u, 43u, 221u, 144u,
- 172u, 159u, 195u, 63u,
- 144u, 101u, 255u, 248u,
- 119u, 169u, 100u, 159u,
- 151u, 97u, 72u, 84u,
- 191u, 217u, 146u, 139u,
- 73u, 98u, 255u, 86u,
- 147u, 132u, 185u, 110u,
- 149u, 197u, 105u, 255u,
- 122u, 123u, 81u, 116u,
- 83u, 129u, 158u, 87u,
- 198u, 129u, 145u, 84u,
- 35u, 114u, 69u, 255u,
- 143u, 47u, 130u, 118u,
- 101u, 187u, 156u, 7u,
- 225u, 30u, 177u, 91u,
- 148u, 247u, 114u, 127u,
- 86u, 255u, 118u, 114u,
- 36u, 112u, 8u, 126u,
- 132u, 108u, 163u, 42u,
- 114u, 46u, 117u, 101u,
- 141u, 130u, 199u, 78u,
- 255u, 54u, 203u, 37u,
- 139u, 167u, 138u, 109u,
- 133u, 44u, 162u, 174u,
- 157u, 144u, 70u, 134u,
- 129u, 119u, 1u, 121u,
- 209u, 129u, 70u, 178u,
- 16u, 115u, 140u, 146u,
- 169u, 149u, 100u, 1u,
- 201u, 180u, 9u, 197u,
- 229u, 133u, 127u, 116u,
- 134u, 104u, 121u, 170u,
- 255u, 165u, 139u, 94u,
- 112u, 113u, 68u, 96u,
- 180u, 83u, 235u, 78u,
- 166u, 25u, 54u, 148u,
- 203u, 151u, 68u, 164u,
- 255u, 172u, 111u, 100u,
- 114u, 65u, 253u, 137u,
- 134u, 71u, 34u, 112u,
- 65u, 197u, 163u, 56u,
- 255u, 29u, 202u, 2u,
- 165u, 106u, 113u, 88u,
- 66u, 194u, 160u, 138u,
- 1u, 119u, 155u, 182u,
- 87u, 191u, 117u, 184u,
- 102u, 165u, 171u, 137u,
- 1u, 195u, 80u, 145u,
- 195u, 27u, 110u, 132u,
- 66u, 171u, 38u, 22u,
- 160u, 236u, 182u, 173u,
- 202u, 212u, 132u, 111u,
- 208u, 2u, 211u, 236u,
- 1u, 54u, 148u, 210u,
- 71u, 36u, 65u, 211u,
- 156u, 155u, 181u, 223u,
- 78u, 152u, 214u, 28u,
- 1u, 254u, 174u, 36u,
- 103u, 138u, 156u, 255u,
- 96u, 79u, 100u, 173u,
- 105u, 157u, 191u, 172u,
- 143u, 157u, 154u, 97u,
- 160u, 182u, 123u, 129u,
- 184u, 85u, 62u, 232u,
- 93u, 218u, 97u, 101u,
- 255u, 151u, 187u, 51u,
- 185u, 191u, 126u, 255u,
- 197u, 150u, 167u, 58u,
- 160u, 105u, 80u, 99u,
- 80u, 88u, 121u, 86u,
- 219u, 43u, 35u, 218u,
- 70u, 88u, 255u, 156u,
- 83u, 175u, 104u, 194u,
- 21u, 167u, 190u, 41u,
- 35u, 36u, 1u, 119u,
- 193u, 97u, 127u, 176u,
- 117u, 54u, 109u, 171u,
- 32u, 108u, 129u, 48u,
- 122u, 140u, 170u, 60u,
- 65u, 255u, 83u, 4u,
- 204u, 81u, 199u, 183u,
- 92u, 104u, 130u, 47u,
- 41u, 107u, 128u, 1u,
- 56u, 186u, 143u, 203u,
- 67u, 174u, 86u, 37u,
- 174u, 118u, 127u, 49u,
- 154u, 102u, 211u, 201u,
- 39u, 120u, 184u, 123u,
- 230u, 179u, 169u, 255u,
- 22u, 208u, 246u, 120u,
- 130u, 220u, 229u, 187u,
- 218u, 255u, 105u, 111u,
- 126u, 114u, 24u, 169u,
- 100u, 176u, 94u, 89u,
- 167u, 167u, 175u, 120u,
- 67u, 102u, 87u, 156u,
- 240u, 133u, 189u, 67u,
- 172u, 64u, 95u, 255u,
- 149u, 174u, 140u, 102u,
- 87u, 85u, 156u, 0u,
- 19u, 127u, 114u, 105u,
- 135u, 138u, 130u, 126u,
- 54u, 115u, 116u, 241u,
- 167u, 131u, 185u, 255u,
- 212u, 92u, 138u, 65u,
- 236u, 53u, 88u, 100u,
- 65u, 154u, 98u, 122u,
- 146u, 208u, 112u, 128u,
- 18u, 82u, 61u, 109u,
- 77u, 94u, 186u, 0u,
- 255u, 45u, 153u, 137u,
- 116u, 155u, 203u, 118u,
- 184u, 180u, 163u, 81u,
- 239u, 56u, 27u, 151u,
- 158u, 145u, 162u, 221u,
- 113u, 123u, 255u, 110u,
- 190u, 194u, 178u, 84u,
- 227u, 139u, 165u, 68u,
- 117u, 57u, 84u, 126u,
- 157u, 95u, 105u, 225u,
- 114u, 182u, 96u, 141u,
- 12u, 80u, 34u, 255u,
- 158u, 153u, 200u, 66u,
- 139u, 156u, 62u, 88u,
- 89u, 197u, 110u, 48u,
- 220u, 74u, 255u, 175u,
- 130u, 153u, 142u, 132u,
- 128u, 104u, 34u, 124u,
- 177u, 125u, 93u, 255u,
- 49u, 167u, 70u, 201u,
- 209u, 108u, 173u, 137u,
- 166u, 83u, 43u, 112u,
- 138u, 152u, 139u, 54u,
- 255u, 144u, 72u, 134u,
- 236u, 107u, 89u, 228u,
- 125u, 116u, 37u, 224u,
- 172u, 134u, 29u, 130u,
- 40u, 69u, 1u, 98u,
- 90u, 183u, 83u, 250u,
- 156u, 255u, 148u, 151u,
- 161u, 139u, 144u, 78u,
- 164u, 157u, 208u, 148u,
- 220u, 145u, 131u, 143u,
- 119u, 116u, 182u, 152u,
- 165u, 158u, 36u, 212u,
- 157u, 93u, 209u, 1u,
- 28u, 255u, 102u, 125u,
- 42u, 165u, 156u, 150u,
- 143u, 94u, 19u, 88u,
- 44u, 146u, 160u, 153u,
- 132u, 41u, 144u, 141u,
- 84u, 103u, 91u, 175u,
- 255u, 130u, 150u, 122u,
- 123u, 184u, 23u, 111u,
- 104u, 216u, 155u, 242u,
- 44u, 203u, 146u, 255u,
- 151u, 80u, 40u, 120u,
- 170u, 61u, 199u, 176u,
- 202u, 125u, 114u, 102u,
- 159u, 96u, 129u, 226u,
- 175u, 147u, 100u, 144u,
- 1u, 3u, 249u, 152u,
- 255u, 28u, 213u, 124u,
- 151u, 151u, 78u, 155u,
- 106u, 214u, 122u, 109u,
- 117u, 98u, 141u, 132u,
- 68u, 79u, 47u, 0u,
- 79u, 87u, 148u, 72u,
- 77u, 32u, 100u, 11u,
- 215u, 138u, 114u, 122u,
- 72u, 255u, 26u, 94u,
- 139u, 214u, 172u, 166u,
- 202u, 167u, 114u, 83u,
- 58u, 114u, 187u, 185u,
- 142u, 248u, 133u, 188u,
- 123u, 129u, 21u, 184u,
- 64u, 227u, 144u, 180u,
- 147u, 255u, 57u, 1u,
- 121u, 166u, 223u, 127u,
- 1u, 92u, 129u, 120u,
- 197u, 109u, 111u, 144u,
- 132u, 211u, 250u, 149u,
- 148u, 83u, 231u, 255u,
- 132u, 76u, 175u, 139u,
- 79u, 109u, 150u, 112u,
- 147u, 204u, 90u, 119u,
- 225u, 151u, 173u, 72u,
- 76u, 133u, 75u, 103u,
- 22u, 66u, 161u, 185u,
- 126u, 84u, 107u, 1u,
- 136u, 169u, 63u, 126u,
- 170u, 22u, 255u, 69u,
- 91u, 183u, 102u, 110u,
- 102u, 196u, 102u, 139u,
- 121u, 121u, 104u, 169u,
- 200u, 80u, 208u, 134u,
- 255u, 45u, 79u, 126u,
- 80u, 8u, 121u, 153u,
- 162u, 153u, 27u, 143u,
- 178u, 222u, 149u, 1u,
- 73u, 134u, 77u, 31u,
- 48u, 133u, 255u, 133u,
- 154u, 67u, 42u, 114u,
- 174u, 227u, 233u, 252u,
- 184u, 49u, 127u, 0u,
- 29u, 131u, 113u, 176u,
- 149u, 117u, 214u, 39u,
- 100u, 54u, 144u, 160u,
- 198u, 206u, 93u, 131u,
- 97u, 255u, 36u, 181u,
- 5u, 116u, 96u, 205u,
- 192u, 150u, 94u, 215u,
- 11u, 129u, 228u, 116u,
- 255u, 71u, 121u, 20u,
- 57u, 92u, 123u, 63u,
- 250u, 113u, 227u, 45u,
- 20u, 217u, 164u, 43u,
- 16u, 1u, 137u, 125u,
- 29u, 39u, 61u, 37u,
- 0u, 195u, 99u, 70u,
- 164u, 153u, 184u, 143u,
- 201u, 84u, 176u, 231u,
- 82u, 19u, 141u, 139u,
- 1u, 25u, 92u, 61u,
- 170u, 93u, 128u, 86u,
- 141u, 132u, 143u, 115u,
- 105u, 1u, 127u, 76u,
- 110u, 86u, 55u, 211u,
- 89u, 98u, 166u, 109u,
- 124u, 153u, 113u, 24u,
- 88u, 84u, 114u, 15u,
- 70u, 84u, 138u, 52u,
- 181u, 51u, 167u, 141u,
- 52u, 42u, 1u, 254u,
- 71u, 1u, 213u, 222u,
- 222u, 11u, 118u, 109u,
- 97u, 254u, 196u, 158u,
- 160u, 152u, 42u, 128u,
- 129u, 1u, 222u, 127u,
- 45u, 97u, 64u, 146u,
- 144u, 206u, 136u, 207u,
- 44u, 200u, 68u, 7u,
- 98u, 214u, 118u, 112u,
- 137u, 123u, 77u, 140u,
- 179u, 146u, 145u, 170u,
- 255u, 94u, 86u, 92u,
- 183u, 99u, 149u, 9u,
- 185u, 1u, 40u, 146u,
- 74u, 73u, 111u, 43u,
- 104u, 126u, 85u, 153u,
- 164u, 141u, 189u, 28u,
- 87u, 80u, 38u, 6u,
- 96u, 109u, 132u, 152u,
- 211u, 255u, 114u, 168u,
- 89u, 123u, 206u, 82u,
- 139u, 110u, 101u, 240u,
- 1u, 151u, 169u, 64u,
- 25u, 152u, 16u, 126u,
- 147u, 170u, 171u, 76u,
- 79u, 16u, 1u, 89u,
- 92u, 191u, 113u, 122u,
- 150u, 135u, 65u, 225u,
- 120u, 151u, 187u, 104u,
- 125u, 109u, 125u, 198u,
- 255u, 83u, 1u, 127u,
- 26u, 229u, 10u, 163u,
- 41u, 162u, 106u, 85u,
- 67u, 128u, 155u, 42u,
- 214u, 124u, 95u, 69u,
- 1u, 27u, 162u, 203u,
- 106u, 0u, 96u, 117u,
- 5u, 127u, 150u, 159u,
- 140u, 211u, 195u, 199u,
- 168u, 166u, 57u, 156u,
- 88u, 146u, 88u, 87u,
- 180u, 91u, 255u, 156u,
- 176u, 203u, 123u, 175u,
- 130u, 135u, 214u, 132u,
- 131u, 110u, 47u, 97u,
- 120u, 179u, 27u, 255u,
- 111u, 166u, 97u, 122u,
- 173u, 100u, 227u, 98u,
- 137u, 1u, 163u, 50u,
- 120u, 223u, 56u, 197u,
- 149u, 160u, 105u, 9u,
- 49u, 44u, 165u, 95u,
- 255u, 175u, 108u, 78u,
- 120u, 94u, 127u, 145u,
- 115u, 112u, 85u, 141u,
- 109u, 204u, 84u, 95u,
- 39u, 100u, 225u, 1u,
- 158u, 181u, 142u, 139u,
- 165u, 102u, 165u, 101u,
- 53u, 91u, 37u, 100u,
- 197u, 88u, 130u, 146u,
- 92u, 18u, 162u, 124u,
- 144u, 152u, 222u, 113u,
- 255u, 85u, 58u, 186u,
- 178u, 184u, 57u, 200u,
- 182u, 108u, 127u, 208u,
- 68u, 1u, 232u, 141u,
- 93u, 32u, 144u, 149u,
- 139u, 192u, 153u, 214u,
- 0u, 123u, 132u, 53u,
- 215u, 23u, 219u, 156u,
- 162u, 92u, 210u, 208u,
- 30u, 96u, 77u, 169u,
- 10u, 74u, 54u, 73u,
- 24u, 167u, 116u, 84u,
- 127u, 255u, 94u, 248u,
- 53u, 1u, 202u, 188u,
- 16u, 21u, 195u, 6u,
- 173u, 201u, 187u, 153u,
- 238u, 173u, 110u, 111u,
- 200u, 239u, 35u, 166u,
- 109u, 178u, 151u, 104u,
- 127u, 56u, 181u, 96u,
- 228u, 234u, 255u, 165u,
- 137u, 85u, 255u, 236u,
- 1u, 206u, 102u, 100u,
- 95u, 164u, 136u, 57u,
- 84u, 85u, 195u, 217u,
- 66u, 161u, 126u, 106u,
- 222u, 172u, 103u, 181u,
- 59u, 90u, 134u, 130u,
- 117u, 110u, 1u, 129u,
- 10u, 66u, 146u, 12u,
- 80u, 145u, 101u, 98u,
- 160u, 107u, 1u, 191u,
- 85u, 190u, 56u, 86u,
- 12u, 113u, 100u, 255u,
- 78u, 132u, 132u, 74u,
- 234u, 84u, 74u, 169u,
- 116u, 134u, 194u, 112u,
- 102u, 80u, 130u, 133u,
- 147u, 85u, 107u, 85u,
- 172u, 103u, 133u, 111u,
- 184u, 255u, 158u, 174u,
- 130u, 209u, 138u, 146u,
- 96u, 172u, 172u, 1u,
- 149u, 160u, 225u, 255u,
- 188u, 7u, 27u, 103u,
- 169u, 177u, 78u, 200u,
- 255u, 113u, 101u, 78u,
- 174u, 121u, 62u, 130u,
- 43u, 131u, 47u, 61u,
- 210u, 37u, 142u, 126u,
- 126u, 1u, 124u, 204u,
- 156u, 71u, 164u, 255u,
- 143u, 183u, 129u, 60u,
- 155u, 191u, 43u, 104u,
- 138u, 231u, 187u, 89u,
- 122u, 179u, 188u, 158u,
- 146u, 255u, 67u, 197u,
- 132u, 65u, 206u, 90u,
- 222u, 117u, 238u, 68u,
- 181u, 42u, 151u, 77u,
- 254u, 0u, 87u, 71u,
- 77u, 163u, 183u, 237u,
- 100u, 138u, 162u, 12u,
- 149u, 88u, 145u, 109u,
- 190u, 141u, 255u, 178u,
- 110u, 121u, 179u, 255u,
- 61u, 166u, 150u, 66u,
- 183u, 189u, 163u, 133u,
- 165u, 156u, 175u, 135u,
- 206u, 86u, 102u, 124u,
- 77u, 164u, 74u, 217u,
- 113u, 174u, 95u, 95u,
- 169u, 59u, 191u, 255u,
- 255u, 161u, 195u, 206u,
- 106u, 129u, 86u, 88u,
- 133u, 144u, 125u, 127u,
- 126u, 97u, 161u, 95u,
- 86u, 120u, 126u, 210u,
- 134u, 128u, 136u, 143u,
- 113u, 78u, 90u, 181u,
- 255u, 114u, 129u, 16u,
- 90u, 113u, 86u, 173u,
- 255u, 51u, 131u, 69u,
- 182u, 171u, 43u, 114u,
- 228u, 167u, 21u, 95u,
- 78u, 106u, 34u, 128u,
- 201u, 187u, 97u, 174u,
- 66u, 255u, 215u, 168u,
- 100u, 77u, 182u, 51u,
- 163u, 106u, 159u, 1u,
- 173u, 15u, 121u, 164u,
- 183u, 223u, 123u, 63u,
- 132u, 65u, 110u, 35u,
- 172u, 60u, 195u, 186u,
- 75u, 86u, 65u, 114u,
- 134u, 100u, 155u, 179u,
- 204u, 82u, 1u, 49u,
- 139u, 255u, 57u, 182u,
- 221u, 197u, 192u, 152u,
- 187u, 99u, 254u, 124u,
- 63u, 19u, 78u, 148u,
- 19u, 156u, 145u, 216u,
- 147u, 92u, 71u, 255u,
- 54u, 135u, 230u, 91u,
- 187u, 99u, 61u, 14u,
- 85u, 52u, 59u, 171u,
- 1u, 144u, 133u, 61u,
- 88u, 82u, 176u, 73u,
- 84u, 181u, 140u, 40u,
- 96u, 62u, 155u, 167u,
- 33u, 206u, 178u, 189u,
- 152u, 183u, 32u, 179u,
- 0u, 126u, 167u, 204u,
- 160u, 152u, 119u, 120u,
- 164u, 169u, 82u, 189u,
- 144u, 0u, 141u, 133u,
- 92u, 13u, 106u, 138u,
- 1u, 90u, 44u, 148u,
- 159u, 217u, 209u, 215u,
- 107u, 73u, 99u, 45u,
- 152u, 162u, 102u, 188u,
- 87u, 0u, 155u, 238u,
- 35u, 100u, 83u, 157u,
- 191u, 88u, 205u, 134u,
- 63u, 233u, 51u, 94u,
- 67u, 255u, 127u, 136u,
- 214u, 127u, 215u, 117u,
- 174u, 110u, 190u, 235u,
- 204u, 137u, 202u, 107u,
- 137u, 240u, 68u, 24u,
- 255u, 154u, 179u, 77u,
- 68u, 128u, 119u, 160u,
- 84u, 57u, 65u, 127u,
- 181u, 183u, 255u, 111u,
- 135u, 202u, 138u, 34u,
- 100u, 129u, 145u, 195u,
- 216u, 142u, 103u, 91u,
- 127u, 72u, 189u, 137u,
- 142u, 93u, 125u, 251u,
- 118u, 97u, 187u, 135u,
- 1u, 198u, 160u, 98u,
- 219u, 137u, 204u, 255u,
- 224u, 144u, 73u, 247u,
- 186u, 69u, 236u, 224u,
- 131u, 145u, 71u, 111u,
- 174u, 90u, 39u, 140u,
- 181u, 133u, 73u, 250u,
- 92u, 150u, 155u, 1u,
- 178u, 23u, 105u, 130u,
- 18u, 180u, 127u, 140u,
- 165u, 197u, 156u, 1u,
- 188u, 154u, 176u, 185u,
- 127u, 5u, 8u, 214u,
- 69u, 186u, 63u, 100u,
- 139u, 196u, 152u, 74u,
- 114u, 140u, 38u, 150u,
- 1u, 155u, 150u, 120u,
- 161u, 154u, 185u, 140u,
- 137u, 98u, 177u, 112u,
- 33u, 89u, 65u, 196u,
- 80u, 136u, 100u, 1u,
- 139u, 182u, 179u, 73u,
- 144u, 86u, 118u, 255u,
- 200u, 135u, 152u, 128u,
- 69u, 143u, 132u, 133u,
- 103u, 65u, 169u, 132u,
- 255u, 144u, 126u, 172u,
- 128u, 133u, 109u, 70u,
- 236u, 64u, 120u, 158u,
- 63u, 106u, 47u, 83u,
- 91u, 33u, 110u, 175u,
- 101u, 125u, 67u, 65u,
- 80u, 255u, 139u, 115u,
- 25u, 93u, 84u, 113u,
- 147u, 96u, 133u, 102u,
- 65u, 95u, 119u, 116u,
- 191u, 147u, 1u, 148u,
- 133u, 204u, 62u, 149u,
- 161u, 152u, 112u, 81u,
- 87u, 184u, 249u, 115u,
- 168u, 1u, 131u, 154u,
- 203u, 68u, 249u, 197u,
- 186u, 100u, 112u, 89u,
- 184u, 84u, 171u, 92u,
- 255u, 220u, 191u, 73u,
- 11u, 159u, 75u, 120u,
- 255u, 168u, 192u, 196u,
- 130u, 239u, 38u, 218u,
- 99u, 218u, 68u, 125u,
- 189u, 104u, 223u, 79u,
- 255u, 79u, 107u, 153u,
- 155u, 187u, 206u, 125u,
- 126u, 119u, 148u, 111u,
- 73u, 19u, 194u, 242u,
- 100u, 146u, 152u, 203u,
- 70u, 106u, 108u, 123u,
- 182u, 255u, 105u, 173u,
- 168u, 178u, 155u, 153u,
- 94u, 113u, 120u, 183u,
- 181u, 116u, 212u, 174u,
- 93u, 153u, 198u, 255u,
- 49u, 225u, 203u, 64u,
- 193u, 168u, 60u, 75u,
- 209u, 123u, 0u, 107u,
- 8u, 149u, 197u, 139u,
- 92u, 153u, 143u, 76u,
- 243u, 11u, 178u, 37u,
- 111u, 207u, 76u, 89u,
- 255u, 79u, 129u, 195u,
- 148u, 194u, 124u, 109u,
- 36u, 139u, 77u, 147u,
- 131u, 152u, 128u, 61u,
- 122u, 162u, 255u, 220u,
- 148u, 149u, 101u, 195u,
- 165u, 145u, 43u, 206u,
- 224u, 156u, 104u, 117u,
- 49u, 60u, 176u, 0u,
- 101u, 41u, 68u, 162u,
- 56u, 125u, 131u, 101u,
- 186u, 135u, 104u, 1u,
- 87u, 100u, 149u, 214u,
- 105u, 200u, 208u, 162u,
- 36u, 145u, 77u, 231u,
- 255u, 165u, 138u, 161u,
- 123u, 13u, 162u, 114u,
- 178u, 103u, 255u, 105u,
- 169u, 130u, 177u, 166u,
- 133u, 174u, 132u, 100u,
- 144u, 169u, 55u, 128u,
- 181u, 4u, 150u, 130u,
- 162u, 0u, 125u, 223u,
- 180u, 236u, 51u, 63u,
- 211u, 209u, 149u, 58u,
- 152u, 242u, 167u, 192u,
- 98u, 141u, 77u, 23u,
- 189u, 56u, 198u, 255u,
- 185u, 137u, 97u, 227u,
- 160u, 112u, 112u, 79u,
- 134u, 161u, 115u, 191u,
- 112u, 31u, 58u, 92u,
- 155u, 185u, 52u, 1u,
- 149u, 138u, 145u, 44u,
- 102u, 192u, 97u, 105u,
- 120u, 141u, 99u, 185u,
- 1u, 193u, 160u, 86u,
- 143u, 184u, 142u, 211u,
- 114u, 132u, 62u, 122u,
- 127u, 64u, 60u, 126u,
- 125u, 180u, 255u, 92u,
- 139u, 126u, 35u, 1u,
- 103u, 142u, 137u, 113u,
- 112u, 142u, 101u, 110u,
- 18u, 77u, 181u, 164u,
- 155u, 78u, 255u, 65u,
- 186u, 101u, 122u, 114u,
- 60u, 218u, 183u, 103u,
- 144u, 87u, 112u, 108u,
- 165u, 199u, 229u, 135u,
- 238u, 116u, 131u, 168u,
- 95u, 159u, 175u, 69u,
- 117u, 255u, 55u, 161u,
- 154u, 104u, 228u, 163u,
- 173u, 201u, 130u, 185u,
- 1u, 215u, 177u, 78u,
- 141u, 180u, 84u, 197u,
- 222u, 197u, 169u, 1u,
- 157u, 143u, 92u, 22u,
- 25u, 147u, 155u, 47u,
- 142u, 27u, 108u, 127u,
- 76u, 179u, 182u, 115u,
- 71u, 192u, 81u, 1u,
- 154u, 110u, 141u, 126u,
- 152u, 128u, 158u, 131u,
- 81u, 178u, 134u, 135u,
- 139u, 173u, 74u, 100u,
- 105u, 119u, 45u, 1u,
- 145u, 79u, 82u, 142u,
- 30u, 177u, 99u, 76u,
- 89u, 159u, 207u, 114u,
- 166u, 68u, 255u, 23u,
- 218u, 55u, 166u, 211u,
- 151u, 161u, 150u, 113u,
- 126u, 89u, 156u, 216u,
- 61u, 83u, 124u, 79u,
- 1u, 183u, 133u, 194u,
- 75u, 126u, 90u, 255u,
- 103u, 135u, 171u, 103u,
- 124u, 126u, 132u, 73u,
- 153u, 159u, 133u, 138u,
- 97u, 176u, 187u, 155u,
- 194u, 212u, 140u, 194u,
- 158u, 120u, 99u, 148u,
- 255u, 128u, 59u, 18u,
- 36u, 131u, 107u, 138u,
- 142u, 183u, 84u, 96u,
- 155u, 152u, 177u, 141u,
- 101u, 255u, 54u, 161u,
- 216u, 44u, 45u, 128u,
- 94u, 120u, 183u, 103u,
- 102u, 200u, 129u, 85u,
- 0u, 147u, 196u, 121u,
- 95u, 62u, 111u, 46u,
- 68u, 115u, 71u, 230u,
- 139u, 171u, 69u, 209u,
- 173u, 134u, 85u, 255u,
- 104u, 117u, 103u, 198u,
- 152u, 109u, 158u, 70u,
- 255u, 139u, 113u, 147u,
- 99u, 171u, 82u, 186u,
- 89u, 36u, 122u, 90u,
- 255u, 163u, 121u, 90u,
- 144u, 150u, 118u, 38u,
- 205u, 154u, 48u, 193u,
- 103u, 119u, 112u, 162u,
- 167u, 157u, 1u, 131u,
- 144u, 153u, 111u, 105u,
- 93u, 187u, 119u, 44u,
- 224u, 104u, 153u, 127u,
- 255u, 172u, 236u, 170u,
- 79u, 138u, 8u, 142u,
- 93u, 172u, 32u, 60u,
- 93u, 159u, 170u, 204u,
- 158u, 118u, 75u, 38u,
- 200u, 255u, 137u, 129u,
- 99u, 23u, 217u, 181u,
- 70u, 86u, 0u, 55u,
- 67u, 169u, 166u, 95u,
- 66u, 93u, 116u, 122u,
- 145u, 63u, 160u, 86u,
- 57u, 120u, 163u, 132u,
- 137u, 146u, 25u, 39u,
- 106u, 155u, 114u, 246u,
- 60u, 26u, 0u, 158u,
- 209u, 148u, 55u, 64u,
- 26u, 203u, 139u, 159u,
- 115u, 74u, 67u, 109u,
- 1u, 159u, 95u, 216u,
- 87u, 33u, 147u, 113u,
- 1u, 174u, 196u, 162u,
- 31u, 73u, 75u, 126u,
- 187u, 177u, 175u, 58u,
- 255u, 166u, 87u, 45u,
- 213u, 61u, 171u, 179u,
- 112u, 70u, 158u, 57u,
- 177u, 147u, 123u, 127u,
- 135u, 108u, 1u, 115u,
- 146u, 180u, 100u, 152u,
- 110u, 119u, 48u, 99u,
- 81u, 131u, 62u, 183u,
- 1u, 22u, 175u, 91u,
- 244u, 89u, 166u, 115u,
- 238u, 150u, 14u, 79u,
- 78u, 73u, 73u, 24u,
- 127u, 94u, 140u, 136u,
- 131u, 149u, 113u, 103u,
- 128u, 187u, 114u, 109u,
- 153u, 150u, 79u, 0u,
- 129u, 67u, 192u, 188u,
- 77u, 238u, 143u, 255u,
- 84u, 175u, 177u, 117u,
- 230u, 152u, 25u, 8u,
- 102u, 167u, 212u, 149u,
- 128u, 184u, 0u, 182u,
- 136u, 72u, 157u, 58u,
- 105u, 119u, 72u, 162u,
- 117u, 77u, 0u, 196u,
- 2u, 213u, 162u, 27u,
- 138u, 141u, 250u, 37u,
- 146u, 118u, 122u, 59u,
- 116u, 102u, 166u, 235u,
- 121u, 139u, 89u, 99u,
- 144u, 11u, 255u, 86u,
- 97u, 134u, 184u, 117u,
- 105u, 232u, 129u, 255u,
- 74u, 62u, 152u, 102u,
- 152u, 202u, 101u, 57u,
- 129u, 131u, 197u, 145u,
- 164u, 52u, 187u, 109u,
- 131u, 84u, 27u, 69u,
- 15u, 143u, 113u, 66u,
- 206u, 94u, 1u, 84u,
- 0u, 145u, 9u, 158u,
- 43u, 192u, 175u, 201u,
- 153u, 0u, 0u, 187u,
- 154u, 71u, 77u, 87u,
- 67u, 70u, 250u, 97u,
- 44u, 122u, 255u, 76u,
- 76u, 117u, 177u, 159u,
- 45u, 66u, 194u, 101u,
- 85u, 104u, 131u, 199u,
- 102u, 4u, 79u, 148u,
- 51u, 59u, 252u, 150u,
- 126u, 49u, 89u, 255u,
- 133u, 165u, 85u, 150u,
- 161u, 145u, 92u, 0u,
- 151u, 163u, 145u, 109u,
- 159u, 86u, 71u, 160u,
- 189u, 140u, 159u, 117u,
- 135u, 28u, 82u, 149u,
- 146u, 137u, 171u, 117u,
- 106u, 189u, 194u, 255u,
- 165u, 146u, 133u, 145u,
- 164u, 255u, 59u, 87u,
- 184u, 105u, 158u, 243u,
- 154u, 183u, 47u, 148u,
- 201u, 75u, 106u, 116u,
- 103u, 156u, 126u, 216u,
- 91u, 1u, 56u, 116u,
- 97u, 153u, 195u, 67u,
- 89u, 49u, 102u, 70u,
- 150u, 60u, 209u, 106u,
- 111u, 97u, 27u, 1u,
- 117u, 58u, 57u, 111u,
- 106u, 157u, 203u, 203u,
- 94u, 96u, 209u, 48u,
- 188u, 183u, 19u, 173u,
- 162u, 255u, 210u, 146u,
- 32u, 108u, 137u, 113u,
- 121u, 85u, 156u, 60u,
- 91u, 168u, 145u, 161u,
- 166u, 255u, 85u, 77u,
- 4u, 158u, 58u, 62u,
- 105u, 134u, 174u, 86u,
- 71u, 117u, 96u, 170u,
- 1u, 210u, 135u, 90u,
- 87u, 202u, 95u, 183u,
- 141u, 95u, 115u, 183u,
- 172u, 198u, 162u, 157u,
- 165u, 1u, 151u, 87u,
- 124u, 80u, 189u, 173u,
- 104u, 83u, 179u, 73u,
- 125u, 118u, 115u, 114u,
- 167u, 255u, 110u, 134u,
- 4u, 127u, 84u, 188u,
- 45u, 160u, 97u, 103u,
- 110u, 134u, 140u, 201u,
- 71u, 255u, 65u, 219u,
- 57u, 83u, 162u, 140u,
- 92u, 164u, 255u, 122u,
- 238u, 244u, 62u, 145u,
- 53u, 181u, 217u, 150u,
- 158u, 215u, 153u, 129u,
- 52u, 79u, 123u, 146u,
- 255u, 117u, 87u, 222u,
- 111u, 190u, 43u, 170u,
- 172u, 189u, 217u, 6u,
- 162u, 96u, 0u, 65u,
- 51u, 109u, 148u, 104u,
- 212u, 235u, 120u, 168u,
- 255u, 187u, 166u, 63u,
- 134u, 131u, 39u, 144u,
- 198u, 239u, 74u, 102u,
- 221u, 53u, 36u, 216u,
- 147u, 90u, 255u, 90u,
- 97u, 163u, 162u, 76u,
- 73u, 89u, 147u, 86u,
- 156u, 189u, 69u, 146u,
- 79u, 88u, 194u, 123u,
- 89u, 171u, 123u, 93u,
- 65u, 71u, 255u, 126u,
- 175u, 140u, 212u, 128u,
- 90u, 65u, 149u, 115u,
- 173u, 44u, 112u, 193u,
- 1u, 95u, 96u, 226u,
- 80u, 59u, 64u, 122u,
- 37u, 129u, 1u, 130u,
- 123u, 185u, 132u, 83u,
- 56u, 99u, 96u, 153u,
- 53u, 133u, 91u, 170u,
- 131u, 115u, 141u, 200u,
- 232u, 122u, 178u, 202u,
- 159u, 62u, 112u, 88u,
- 162u, 122u, 194u, 0u,
- 120u, 106u, 181u, 151u,
- 176u, 184u, 170u, 96u,
- 98u, 145u, 153u, 255u,
- 160u, 79u, 100u, 124u,
- 128u, 129u, 133u, 134u,
- 151u, 143u, 71u, 42u,
- 74u, 255u, 126u, 117u,
- 133u, 127u, 94u, 73u,
- 104u, 184u, 81u, 213u,
- 162u, 185u, 63u, 104u,
- 164u, 19u, 94u, 1u,
- 118u, 44u, 112u, 118u,
- 134u, 182u, 208u, 132u,
- 151u, 94u, 1u, 54u,
- 157u, 196u, 131u, 29u,
- 131u, 107u, 96u, 130u,
- 110u, 30u, 24u, 143u,
- 48u, 15u, 185u, 167u,
- 88u, 136u, 145u, 31u,
- 121u, 255u, 76u, 151u,
- 183u, 162u, 125u, 157u,
- 31u, 165u, 255u, 49u,
- 179u, 27u, 76u, 142u,
- 120u, 89u, 129u, 164u,
- 22u, 255u, 186u, 12u,
- 148u, 249u, 154u, 145u,
- 230u, 239u, 76u, 121u,
- 66u, 170u, 188u, 254u,
- 156u, 138u, 173u, 112u,
- 150u, 136u, 248u, 111u,
- 132u, 71u, 82u, 212u,
- 119u, 71u, 255u, 121u,
- 144u, 129u, 134u, 164u,
- 198u, 67u, 120u, 122u,
- 255u, 99u, 102u, 109u,
- 164u, 141u, 164u, 176u,
- 158u, 114u, 195u, 57u,
- 109u, 1u, 39u, 160u,
- 36u, 80u, 134u, 166u,
- 101u, 238u, 129u, 154u,
- 157u, 81u, 103u, 248u,
- 133u, 213u, 26u, 68u,
- 130u, 95u, 114u, 163u,
- 115u, 124u, 255u, 128u,
- 129u, 189u, 204u, 1u,
- 219u, 64u, 139u, 171u,
- 20u, 199u, 118u, 120u,
- 56u, 35u, 1u, 195u,
- 115u, 150u, 111u, 109u,
- 161u, 173u, 72u, 240u,
- 162u, 113u, 174u, 129u,
- 134u, 167u, 1u, 186u,
- 218u, 84u, 136u, 159u,
- 64u, 88u, 94u, 228u,
- 140u, 110u, 164u, 51u,
- 130u, 71u, 130u, 1u,
- 212u, 179u, 44u, 55u,
- 165u, 167u, 180u, 32u,
- 143u, 160u, 64u, 85u,
- 137u, 107u, 113u, 255u,
- 108u, 113u, 128u, 141u,
- 177u, 80u, 41u, 255u,
- 58u, 136u, 166u, 133u,
- 82u, 186u, 31u, 143u,
- 130u, 255u, 228u, 216u,
- 195u, 128u, 114u, 119u,
- 35u, 126u, 189u, 76u,
- 141u, 98u, 100u, 124u,
- 52u, 101u, 185u, 165u,
- 99u, 255u, 186u, 119u,
- 124u, 92u, 120u, 199u,
- 47u, 117u, 87u, 179u,
- 188u, 134u, 248u, 80u,
- 0u, 142u, 56u, 80u,
- 190u, 150u, 191u, 97u,
- 42u, 104u, 148u, 159u,
- 121u, 255u, 139u, 204u,
- 15u, 198u, 57u, 170u,
- 60u, 138u, 152u, 140u,
- 8u, 113u, 130u, 159u,
- 188u, 172u, 106u, 3u,
- 73u, 1u, 142u, 137u,
- 41u, 85u, 167u, 149u,
- 110u, 142u, 242u, 168u,
- 77u, 247u, 110u, 178u,
- 183u, 115u, 235u, 134u,
- 7u, 1u, 175u, 210u,
- 190u, 147u, 130u, 27u,
- 224u, 51u, 79u, 26u,
- 95u, 239u, 127u, 255u,
- 117u, 99u, 8u, 70u,
- 30u, 217u, 157u, 158u,
- 46u, 246u, 200u, 142u,
- 134u, 87u, 255u, 89u,
- 149u, 79u, 161u, 80u,
- 178u, 116u, 122u, 151u,
- 178u, 89u, 180u, 255u,
- 113u, 70u, 121u, 233u,
- 49u, 191u, 140u, 52u,
- 219u, 116u, 102u, 86u,
- 78u, 144u, 81u, 118u,
- 175u, 108u, 217u, 130u,
- 29u, 97u, 74u, 133u,
- 112u, 97u, 1u, 28u,
- 121u, 10u, 56u, 174u,
- 58u, 112u, 114u, 165u,
- 113u, 197u, 157u, 81u,
- 165u, 203u, 173u, 1u,
- 121u, 76u, 174u, 42u,
- 109u, 153u, 63u, 222u,
- 18u, 64u, 197u, 130u,
- 255u, 123u, 145u, 182u,
- 255u, 188u, 162u, 212u,
- 160u, 92u, 118u, 226u,
- 109u, 128u, 195u, 126u,
- 99u, 187u, 168u, 89u,
- 52u, 204u, 1u, 170u,
- 93u, 132u, 82u, 92u,
- 71u, 124u, 60u, 179u,
- 72u, 172u, 117u, 221u,
- 92u, 149u, 255u, 202u,
- 141u, 182u, 110u, 121u,
- 143u, 234u, 119u, 207u,
- 108u, 133u, 172u, 83u,
- 174u, 162u, 127u, 100u,
- 136u, 173u, 92u, 77u,
- 65u, 147u, 50u, 1u,
- 187u, 142u, 204u, 92u,
- 113u, 182u, 190u, 105u,
- 255u, 173u, 248u, 115u,
- 142u, 98u, 53u, 122u,
- 144u, 225u, 54u, 76u,
- 119u, 174u, 104u, 129u,
- 155u, 235u, 234u, 102u,
- 164u, 143u, 97u, 192u,
- 59u, 255u, 208u, 151u,
- 138u, 69u, 255u, 59u,
- 108u, 73u, 83u, 22u,
- 11u, 176u, 154u, 51u,
- 195u, 149u, 95u, 52u,
- 131u, 88u, 158u, 138u,
- 1u, 180u, 47u, 164u,
- 108u, 92u, 125u, 248u,
- 209u, 244u, 241u, 66u,
- 30u, 208u, 104u, 113u,
- 248u, 83u, 185u, 138u,
- 95u, 138u, 111u, 201u,
- 149u, 133u, 0u, 175u,
- 101u, 1u, 89u, 15u,
- 245u, 20u, 143u, 198u,
- 118u, 238u, 58u, 109u,
- 110u, 136u, 192u, 223u,
- 142u, 123u, 142u, 103u,
- 121u, 201u, 79u, 193u,
- 137u, 187u, 151u, 142u,
- 1u, 194u, 81u, 91u,
- 166u, 170u, 187u, 164u,
- 174u, 30u, 117u, 168u,
- 58u, 112u, 255u, 61u,
- 243u, 68u, 45u, 136u,
- 116u, 181u, 255u, 185u,
- 105u, 177u, 223u, 129u,
- 42u, 214u, 153u, 192u,
- 151u, 58u, 236u, 205u,
- 1u, 164u, 102u, 105u,
- 177u, 46u, 134u, 109u,
- 159u, 212u, 133u, 121u,
- 229u, 84u, 20u, 172u,
- 171u, 88u, 129u, 129u,
- 150u, 126u, 131u, 238u,
- 106u, 126u, 149u, 161u,
- 198u, 132u, 255u, 82u,
- 102u, 147u, 236u, 185u,
- 62u, 96u, 217u, 146u,
- 226u, 105u, 158u, 132u,
- 59u, 1u, 14u, 114u,
- 131u, 1u, 146u, 153u,
- 80u, 35u, 101u, 120u,
- 106u, 136u, 98u, 118u,
- 153u, 193u, 148u, 91u,
- 70u, 255u, 32u, 244u,
- 7u, 142u, 218u, 147u,
- 228u, 198u, 254u, 126u,
- 219u, 30u, 250u, 143u,
- 202u, 63u, 36u, 163u,
- 36u, 223u, 132u, 181u,
- 255u, 185u, 75u, 167u,
- 71u, 175u, 204u, 88u,
- 125u, 224u, 36u, 157u,
- 206u, 175u, 195u, 181u,
- 76u, 111u, 0u, 175u,
- 27u, 192u, 136u, 209u,
- 231u, 123u, 231u, 143u,
- 156u, 83u, 1u, 135u,
- 93u, 21u, 210u, 31u,
- 203u, 102u, 189u, 172u,
- 70u, 103u, 56u, 105u,
- 99u, 124u, 231u, 1u,
- 37u, 250u, 113u, 100u,
- 106u, 173u, 99u, 63u,
- 84u, 184u, 107u, 140u,
- 1u, 38u, 254u, 181u,
- 143u, 108u, 188u, 178u,
- 187u, 145u, 163u, 97u,
- 149u, 47u, 149u, 151u,
- 149u, 0u, 137u, 84u,
- 151u, 149u, 178u, 166u,
- 198u, 136u, 129u, 73u,
- 155u, 33u, 93u, 78u,
- 7u, 49u, 133u, 97u,
- 255u, 131u, 79u, 216u,
- 163u, 143u, 191u, 174u,
- 211u, 190u, 189u, 116u,
- 61u, 120u, 101u, 97u,
- 25u, 99u, 129u, 174u,
- 83u, 171u, 255u, 201u,
- 180u, 1u, 198u, 45u,
- 100u, 194u, 106u, 60u,
- 94u, 188u, 157u, 154u,
- 245u, 42u, 154u, 170u,
- 255u, 186u, 138u, 62u,
- 65u, 88u, 136u, 72u,
- 132u, 153u, 184u, 137u,
- 134u, 113u, 174u, 197u,
- 12u, 155u, 1u, 197u,
- 147u, 169u, 125u, 115u,
- 129u, 134u, 168u, 21u,
- 146u, 159u, 104u, 235u,
- 41u, 122u, 159u, 125u,
- 210u, 129u, 102u, 73u,
- 81u, 119u, 74u, 208u,
- 81u, 132u, 0u, 154u,
- 1u, 97u, 155u, 102u,
- 152u, 104u, 219u, 140u,
- 68u, 153u, 76u, 162u,
- 200u, 67u, 38u, 181u,
- 255u, 134u, 144u, 129u,
- 6u, 38u, 142u, 209u,
- 168u, 136u, 167u, 150u,
- 128u, 89u, 108u, 206u,
- 195u, 52u, 118u, 0u,
- 237u, 171u, 158u, 186u,
- 38u, 113u, 228u, 11u,
- 207u, 96u, 78u, 94u,
- 100u, 1u, 90u, 180u,
- 133u, 189u, 142u, 174u,
- 196u, 134u, 120u, 139u,
- 135u, 161u, 34u, 119u,
- 122u, 126u, 103u, 159u,
- 150u, 42u, 69u, 255u,
- 136u, 151u, 148u, 49u,
- 130u, 137u, 182u, 135u,
- 132u, 146u, 80u, 151u,
- 1u, 149u, 118u, 98u,
- 230u, 111u, 170u, 90u,
- 89u, 42u, 205u, 157u,
- 169u, 66u, 67u, 0u,
- 164u, 91u, 125u, 156u,
- 84u, 160u, 115u, 83u,
- 165u, 85u, 140u, 245u,
- 97u, 68u, 96u, 93u,
- 120u, 108u, 155u, 52u,
- 226u, 80u, 133u, 49u,
- 53u, 92u, 210u, 255u,
- 117u, 1u, 175u, 97u,
- 161u, 185u, 167u, 211u,
- 122u, 43u, 211u, 78u,
- 123u, 79u, 79u, 32u,
- 32u, 255u, 94u, 217u,
- 64u, 62u, 117u, 78u,
- 178u, 163u, 108u, 28u,
- 107u, 75u, 181u, 215u,
- 111u, 86u, 251u, 255u,
- 82u, 43u, 207u, 64u,
- 204u, 64u, 124u, 111u,
- 122u, 114u, 192u, 188u,
- 191u, 169u, 144u, 142u,
- 57u, 28u, 73u, 214u,
- 154u, 77u, 219u, 1u,
- 212u, 90u, 249u, 39u,
- 40u, 87u, 42u, 164u,
- 57u, 1u, 132u, 90u,
- 56u, 120u, 124u, 134u,
- 233u, 66u, 72u, 166u,
- 224u, 55u, 148u, 74u,
- 46u, 130u, 1u, 124u,
- 174u, 148u, 101u, 126u,
- 115u, 115u, 212u, 78u,
- 154u, 248u, 58u, 198u,
- 68u, 254u, 8u, 107u,
- 96u, 243u, 170u, 255u,
- 51u, 180u, 171u, 246u,
- 125u, 0u, 138u, 174u,
- 61u, 1u, 70u, 205u,
- 75u, 139u, 139u, 149u,
- 154u, 240u, 81u, 226u,
- 209u, 255u, 236u, 159u,
- 80u, 106u, 102u, 144u,
- 226u, 62u, 172u, 241u,
- 184u, 100u, 188u, 185u,
- 158u, 150u, 104u, 80u,
- 106u, 150u, 219u, 211u,
- 121u, 66u, 174u, 178u,
- 1u, 154u, 230u, 144u,
- 250u, 255u, 151u, 131u,
- 49u, 137u, 200u, 168u,
- 167u, 64u, 124u, 130u,
- 94u, 23u, 250u, 209u,
- 48u, 58u, 98u, 207u,
- 148u, 246u, 73u, 255u,
- 59u, 201u, 149u, 151u,
- 195u, 197u, 98u, 61u,
- 0u, 110u, 92u, 174u,
- 192u, 185u, 47u, 104u,
- 87u, 26u, 148u, 128u,
- 244u, 152u, 47u, 135u,
- 255u, 130u, 169u, 83u,
- 180u, 250u, 69u, 122u,
- 108u, 157u, 71u, 47u,
- 132u, 141u, 78u, 68u,
- 104u, 119u, 59u, 104u,
- 110u, 170u, 88u, 157u,
- 113u, 81u, 255u, 53u,
- 126u, 120u, 187u, 138u,
- 255u, 90u, 186u, 132u,
- 157u, 171u, 134u, 208u,
- 64u, 217u, 142u, 111u,
- 98u, 173u, 82u, 144u,
- 58u, 33u, 166u, 62u,
- 255u, 144u, 224u, 142u,
- 81u, 175u, 63u, 82u,
- 89u, 12u, 135u, 129u,
- 219u, 190u, 255u, 97u,
- 56u, 155u, 85u, 151u,
- 184u, 90u, 132u, 173u,
- 78u, 62u, 179u, 204u,
- 166u, 178u, 140u, 50u,
- 90u, 135u, 1u, 98u,
- 149u, 120u, 185u, 123u,
- 179u, 207u, 108u, 152u,
- 35u, 185u, 113u, 92u,
- 179u, 86u, 255u, 81u,
- 124u, 166u, 139u, 100u,
- 182u, 53u, 143u, 141u,
- 73u, 114u, 152u, 96u,
- 207u, 143u, 157u, 201u,
- 1u, 98u, 183u, 43u,
- 215u, 75u, 71u, 141u,
- 121u, 185u, 71u, 130u,
- 1u, 137u, 115u, 165u,
- 143u, 242u, 159u, 16u,
- 172u, 199u, 150u, 156u,
- 135u, 54u, 132u, 122u,
- 131u, 130u, 199u, 193u,
- 167u, 114u, 96u, 255u,
- 30u, 132u, 97u, 81u,
- 81u, 202u, 1u, 11u,
- 132u, 76u, 90u, 143u,
- 88u, 181u, 26u, 154u,
- 53u, 162u, 206u, 176u,
- 32u, 55u, 158u, 124u,
- 175u, 135u, 200u, 117u,
- 165u, 168u, 79u, 126u,
- 65u, 197u, 152u, 1u,
- 96u, 174u, 163u, 132u,
- 191u, 255u, 190u, 164u,
- 69u, 77u, 133u, 184u,
- 136u, 121u, 140u, 154u,
- 63u, 4u, 78u, 126u,
- 121u, 19u, 195u, 144u,
- 27u, 137u, 81u, 255u,
- 84u, 159u, 182u, 31u,
- 75u, 255u, 151u, 198u,
- 109u, 111u, 68u, 47u,
- 68u, 127u, 136u, 173u,
- 129u, 160u, 129u, 125u,
- 135u, 225u, 27u, 17u,
- 86u, 45u, 177u, 122u,
- 41u, 113u, 4u, 239u,
- 30u, 255u, 130u, 89u,
- 145u, 133u, 210u, 140u,
- 208u, 1u, 55u, 111u,
- 97u, 131u, 162u, 130u,
- 173u, 95u, 111u, 120u,
- 141u, 189u, 195u, 177u,
- 126u, 135u, 113u, 187u,
- 1u, 39u, 82u, 83u,
- 101u, 89u, 71u, 164u,
- 177u, 168u, 92u, 56u,
- 68u, 239u, 167u, 158u,
- 113u, 118u, 129u, 160u,
- 1u, 220u, 128u, 193u,
- 1u, 179u, 86u, 92u,
- 220u, 143u, 138u, 135u,
- 82u, 162u, 141u, 72u,
- 148u, 154u, 15u, 110u,
- 139u, 96u, 137u, 193u,
- 50u, 161u, 77u, 149u,
- 102u, 72u, 130u, 107u,
- 116u, 187u, 255u, 112u,
- 61u, 201u, 71u, 126u,
- 118u, 115u, 182u, 122u,
- 117u, 140u, 153u, 146u,
- 176u, 51u, 70u, 255u,
- 146u, 29u, 1u, 34u,
- 131u, 53u, 210u, 90u,
- 168u, 196u, 143u, 61u,
- 194u, 198u, 56u, 44u,
- 152u, 148u, 112u, 151u,
- 113u, 155u, 122u, 141u,
- 157u, 126u, 113u, 100u,
- 113u, 118u, 255u, 127u,
- 97u, 193u, 118u, 84u,
- 193u, 87u, 148u, 8u,
- 165u, 255u, 100u, 74u,
- 138u, 28u, 120u, 106u,
- 121u, 129u, 190u, 144u,
- 142u, 150u, 70u, 169u,
- 117u, 109u, 149u, 91u,
- 0u, 88u, 96u, 77u,
- 165u, 98u, 166u, 74u,
- 92u, 139u, 169u, 136u,
- 89u, 140u, 95u, 136u,
- 142u, 150u, 1u, 201u,
- 0u, 56u, 92u, 151u,
- 152u, 70u, 187u, 145u,
- 201u, 137u, 148u, 68u,
- 141u, 158u, 65u, 104u,
- 161u, 237u, 172u, 108u,
- 209u, 0u, 127u, 216u,
- 206u, 199u, 202u, 169u,
- 132u, 44u, 183u, 219u,
- 106u, 53u, 40u, 100u,
- 80u, 45u, 212u, 83u,
- 255u, 148u, 48u, 45u,
- 24u, 112u, 33u, 221u,
- 166u, 1u, 140u, 183u,
- 169u, 88u, 150u, 146u,
- 185u, 107u, 74u, 121u,
- 69u, 131u, 68u, 114u,
- 49u, 202u, 89u, 126u,
- 34u, 128u, 104u, 146u,
- 136u, 75u, 126u, 109u,
- 41u, 1u, 217u, 162u,
- 203u, 182u, 153u, 190u,
- 180u, 147u, 86u, 204u,
- 68u, 94u, 41u, 255u,
- 34u, 126u, 112u, 107u,
- 255u, 53u, 167u, 97u,
- 56u, 73u, 90u, 113u,
- 46u, 106u, 157u, 155u,
- 172u, 191u, 112u, 32u,
- 91u, 214u, 179u, 255u,
- 55u, 186u, 18u, 97u,
- 251u, 153u, 62u, 142u,
- 208u, 161u, 75u, 154u,
- 161u, 34u, 129u, 133u,
- 169u, 178u, 104u, 142u,
- 68u, 193u, 133u, 1u,
- 170u, 133u, 126u, 125u,
- 201u, 120u, 156u, 0u,
- 200u, 53u, 107u, 126u,
- 89u, 186u, 174u, 114u,
- 97u, 167u, 138u, 108u,
- 103u, 28u, 1u, 175u,
- 124u, 70u, 176u, 185u,
- 76u, 126u, 199u, 132u,
- 115u, 242u, 118u, 137u,
- 59u, 192u, 94u, 199u,
- 95u, 87u, 139u, 217u,
- 188u, 87u, 196u, 234u,
- 136u, 144u, 255u, 130u,
- 130u, 49u, 80u, 230u,
- 88u, 204u, 115u, 198u,
- 255u, 188u, 188u, 191u,
- 84u, 179u, 125u, 238u,
- 0u, 102u, 157u, 174u,
- 91u, 115u, 172u, 107u,
- 180u, 73u, 150u, 184u,
- 152u, 192u, 253u, 145u,
- 1u, 84u, 199u, 253u,
- 90u, 2u, 133u, 238u,
- 15u, 63u, 246u, 166u,
- 208u, 125u, 29u, 100u,
- 118u, 211u, 1u, 203u,
- 190u, 178u, 242u, 150u,
- 103u, 49u, 96u, 148u,
- 94u, 92u, 91u, 173u,
- 117u, 223u, 180u, 17u,
- 131u, 33u, 243u, 164u,
- 75u, 211u, 175u, 53u,
- 142u, 163u, 85u, 1u,
- 44u, 158u, 88u, 55u,
- 111u, 148u, 24u, 73u,
- 184u, 187u, 37u, 155u,
- 209u, 1u, 61u, 94u,
- 240u, 122u, 190u, 73u,
- 109u, 132u, 119u, 160u,
- 233u, 183u, 156u, 255u,
- 107u, 128u, 180u, 80u,
- 84u, 47u, 255u, 235u,
- 87u, 2u, 71u, 107u,
- 152u, 210u, 117u, 169u,
- 6u, 183u, 62u, 36u,
- 148u, 154u, 146u, 142u,
- 34u, 156u, 159u, 1u,
- 179u, 154u, 116u, 123u,
- 175u, 85u, 218u, 169u,
- 142u, 223u, 3u, 89u,
- 146u, 132u, 84u, 59u,
- 192u, 136u, 124u, 88u,
- 193u, 255u, 217u, 175u,
- 167u, 164u, 120u, 108u,
- 111u, 90u, 106u, 86u,
- 140u, 160u, 74u, 201u,
- 87u, 255u, 191u, 113u,
- 171u, 255u, 176u, 130u,
- 137u, 103u, 21u, 183u,
- 185u, 73u, 124u, 220u,
- 166u, 101u, 106u, 117u,
- 46u, 30u, 169u, 1u,
- 178u, 183u, 113u, 177u,
- 68u, 186u, 181u, 7u,
- 168u, 139u, 115u, 116u,
- 154u, 147u, 148u, 255u,
- 53u, 90u, 90u, 152u,
- 119u, 78u, 158u, 163u,
- 73u, 130u, 119u, 145u,
- 28u, 147u, 136u, 147u,
- 149u, 124u, 203u, 111u,
- 95u, 255u, 92u, 127u,
- 173u, 112u, 92u, 68u,
- 131u, 206u, 87u, 129u,
- 230u, 255u, 108u, 162u,
- 89u, 214u, 167u, 243u,
- 108u, 39u, 174u, 41u,
- 159u, 223u, 251u, 111u,
- 89u, 170u, 0u, 76u,
- 127u, 128u, 180u, 105u,
- 207u, 58u, 70u, 53u,
- 210u, 0u, 189u, 123u,
- 105u, 32u, 29u, 150u,
- 145u, 180u, 46u, 109u,
- 161u, 116u, 187u, 70u,
- 119u, 171u, 192u, 121u,
- 255u, 121u, 225u, 171u,
- 176u, 79u, 111u, 159u,
- 162u, 206u, 78u, 135u,
- 149u, 162u, 133u, 87u,
- 81u, 101u, 1u, 121u,
- 126u, 105u, 201u, 127u,
- 88u, 83u, 113u, 168u,
- 0u, 140u, 82u, 159u,
- 81u, 156u, 180u, 84u,
- 109u, 107u, 121u, 90u,
- 214u, 251u, 222u, 255u,
- 182u, 119u, 154u, 167u,
- 113u, 18u, 181u, 255u,
- 108u, 87u, 228u, 97u,
- 245u, 156u, 88u, 1u,
- 255u, 202u, 164u, 70u,
- 147u, 223u, 122u, 249u,
- 131u, 82u, 90u, 149u,
- 36u, 227u, 180u, 129u,
- 155u, 192u, 122u, 98u,
- 178u, 232u, 114u, 167u,
- 126u, 255u, 167u, 89u,
- 229u, 253u, 199u, 161u,
- 154u, 100u, 241u, 69u,
- 208u, 203u, 3u, 102u,
- 145u, 117u, 42u, 188u,
- 155u, 114u, 255u, 86u,
- 178u, 248u, 117u, 138u,
- 15u, 154u, 130u, 61u,
- 255u, 10u, 209u, 195u,
- 118u, 106u, 145u, 193u,
- 129u, 64u, 243u, 96u,
- 212u, 57u, 105u, 194u,
- 74u, 255u, 188u, 123u,
- 114u, 165u, 73u, 39u,
- 88u, 181u, 208u, 58u,
- 200u, 195u, 205u, 174u,
- 51u, 148u, 200u, 179u,
- 119u, 145u, 1u, 155u,
- 255u, 128u, 78u, 104u,
- 176u, 77u, 132u, 158u,
- 121u, 160u, 136u, 107u,
- 120u, 78u, 85u, 55u,
- 12u, 59u, 105u, 21u,
- 131u, 148u, 2u, 213u,
- 203u, 177u, 146u, 1u,
- 154u, 119u, 167u, 12u,
- 111u, 59u, 173u, 28u,
- 33u, 195u, 147u, 255u,
- 140u, 196u, 150u, 236u,
- 245u, 140u, 135u, 132u,
- 21u, 159u, 87u, 225u,
- 160u, 39u, 161u, 119u,
- 50u, 126u, 135u, 184u,
- 255u, 177u, 20u, 76u,
- 109u, 116u, 181u, 21u,
- 209u, 70u, 255u, 177u,
- 105u, 142u, 170u, 92u,
- 125u, 112u, 159u, 116u,
- 112u, 153u, 7u, 17u,
- 215u, 21u, 255u, 122u,
- 97u, 76u, 60u, 119u,
- 16u, 50u, 93u, 243u,
- 255u, 110u, 64u, 127u,
- 24u, 105u, 159u, 91u,
- 115u, 142u, 92u, 157u,
- 183u, 108u, 110u, 191u,
- 203u, 166u, 78u, 162u,
- 99u, 191u, 213u, 65u,
- 7u, 35u, 54u, 1u,
- 177u, 174u, 8u, 27u,
- 154u, 127u, 124u, 91u,
- 162u, 92u, 2u, 77u,
- 165u, 92u, 156u, 122u,
- 50u, 151u, 1u, 166u,
- 177u, 34u, 86u, 255u,
- 37u, 92u, 114u, 52u,
- 129u, 152u, 131u, 36u,
- 86u, 132u, 142u, 104u,
- 133u, 137u, 116u, 112u,
- 100u, 163u, 115u, 124u,
- 138u, 179u, 88u, 161u,
- 197u, 255u, 154u, 122u,
- 217u, 62u, 66u, 108u,
- 90u, 121u, 104u, 149u,
- 155u, 112u, 103u, 1u,
- 120u, 92u, 139u, 150u,
- 136u, 127u, 164u, 208u,
- 116u, 168u, 145u, 110u,
- 157u, 137u, 156u, 95u,
- 91u, 81u, 78u, 1u,
- 108u, 116u, 88u, 153u,
- 102u, 123u, 172u, 1u,
- 127u, 155u, 108u, 87u,
- 187u, 69u, 112u, 178u,
- 1u, 164u, 33u, 253u,
- 123u, 153u, 167u, 40u,
- 150u, 129u, 157u, 89u,
- 201u, 70u, 125u, 238u,
- 132u, 166u, 19u, 126u,
- 117u, 117u, 238u, 131u,
- 174u, 126u, 255u, 225u,
- 101u, 110u, 169u, 164u,
- 173u, 94u, 191u, 255u,
- 20u, 207u, 37u, 132u,
- 31u, 227u, 19u, 124u,
- 72u, 157u, 123u, 10u,
- 234u, 47u, 200u, 216u,
- 1u, 129u, 33u, 123u,
- 188u, 143u, 87u, 59u,
- 95u, 108u, 50u, 124u,
- 93u, 86u, 125u, 178u,
- 174u, 154u, 176u, 1u,
- 208u, 181u, 56u, 88u,
- 134u, 121u, 152u, 140u,
- 159u, 177u, 147u, 156u,
- 182u, 162u, 168u, 50u,
- 1u, 93u, 161u, 147u,
- 174u, 56u, 172u, 135u,
- 113u, 207u, 73u, 145u,
- 191u, 171u, 1u, 131u,
- 94u, 56u, 144u, 127u,
- 124u, 99u, 143u, 80u,
- 124u, 156u, 140u, 127u,
- 0u, 228u, 91u, 212u,
- 206u, 206u, 124u, 111u,
- 62u, 76u, 155u, 170u,
- 190u, 72u, 184u, 11u,
- 110u, 101u, 164u, 126u,
- 130u, 255u, 113u, 231u,
- 187u, 217u, 232u, 66u,
- 151u, 120u, 91u, 164u,
- 140u, 23u, 96u, 187u,
- 92u, 146u, 142u, 93u,
- 219u, 255u, 175u, 147u,
- 121u, 154u, 146u, 73u,
- 60u, 14u, 166u, 74u,
- 26u, 137u, 245u, 98u,
- 11u, 0u, 22u, 98u,
- 33u, 127u, 161u, 13u,
- 115u, 48u, 103u, 110u,
- 147u, 96u, 193u, 164u,
- 83u, 155u, 255u, 113u,
- 49u, 203u, 61u, 81u,
- 110u, 117u, 255u, 243u,
- 184u, 101u, 165u, 77u,
- 103u, 138u, 129u, 216u,
- 59u, 133u, 185u, 151u,
- 54u, 140u, 68u, 68u,
- 197u, 203u, 134u, 196u,
- 207u, 255u, 186u, 113u,
- 241u, 161u, 207u, 109u,
- 93u, 1u, 120u, 164u,
- 129u, 121u, 193u, 84u,
- 217u, 115u, 86u, 221u,
- 135u, 189u, 198u, 73u,
- 200u, 1u, 145u, 99u,
- 82u, 102u, 232u, 100u,
- 73u, 215u, 58u, 97u,
- 198u, 175u, 174u, 76u,
- 174u, 125u, 167u, 151u,
- 117u, 136u, 113u, 74u,
- 1u, 123u, 105u, 88u,
- 67u, 52u, 56u, 66u,
- 85u, 51u, 65u, 128u,
- 190u, 43u, 131u, 68u,
- 144u, 145u, 255u, 122u,
- 116u, 139u, 63u, 100u,
- 232u, 181u, 152u, 255u,
- 89u, 164u, 152u, 100u,
- 184u, 89u, 7u, 86u,
- 91u, 121u, 103u, 165u,
- 58u, 188u, 171u, 125u,
- 255u, 71u, 125u, 119u,
- 65u, 28u, 204u, 141u,
- 58u, 255u, 85u, 202u,
- 71u, 172u, 51u, 117u,
- 60u, 166u, 105u, 52u,
- 113u, 38u, 194u, 128u,
- 112u, 183u, 39u, 79u,
- 194u, 148u, 134u, 57u,
- 132u, 255u, 15u, 150u,
- 103u, 120u, 65u, 219u,
- 164u, 86u, 67u, 123u,
- 134u, 196u, 255u, 95u,
- 22u, 166u, 141u, 146u,
- 174u, 215u, 183u, 87u,
- 163u, 168u, 93u, 255u,
- 130u, 46u, 137u, 140u,
- 140u, 113u, 88u, 61u,
- 120u, 98u, 186u, 156u,
- 58u, 73u, 189u, 109u,
- 127u, 115u, 77u, 66u,
- 57u, 246u, 72u, 163u,
- 135u, 255u, 220u, 177u,
- 1u, 86u, 12u, 37u,
- 160u, 40u, 99u, 208u,
- 103u, 230u, 65u, 244u,
- 105u, 185u, 28u, 86u,
- 173u, 154u, 189u, 127u,
- 254u, 100u, 180u, 152u,
- 1u, 93u, 102u, 221u,
- 199u, 83u, 171u, 62u,
- 116u, 151u, 60u, 157u,
- 172u, 154u, 146u, 148u,
- 121u, 201u, 150u, 153u,
- 147u, 98u, 1u, 50u,
- 135u, 113u, 152u, 159u,
- 17u, 200u, 83u, 151u,
- 97u, 42u, 255u, 108u,
- 138u, 175u, 37u, 163u,
- 121u, 109u, 245u, 157u,
- 76u, 255u, 185u, 93u,
- 98u, 180u, 84u, 104u,
- 63u, 187u, 124u, 66u,
- 41u, 132u, 213u, 145u,
- 154u, 132u, 76u, 23u,
- 85u, 197u, 159u, 79u,
- 255u, 1u, 100u, 79u,
- 131u, 80u, 168u, 90u,
- 139u, 82u, 113u, 59u,
- 255u, 226u, 58u, 99u,
- 112u, 40u, 152u, 153u,
- 146u, 94u, 23u, 255u,
- 72u, 207u, 106u, 207u,
- 116u, 90u, 110u, 117u,
- 82u, 70u, 125u, 154u,
- 255u, 85u, 134u, 28u,
- 64u, 113u, 241u, 141u,
- 88u, 130u, 127u, 31u,
- 250u, 50u, 152u, 195u,
- 163u, 102u, 83u, 133u,
- 207u, 210u, 129u, 98u,
- 96u, 50u, 195u, 51u,
- 207u, 165u, 125u, 255u,
- 255u, 251u, 240u, 135u,
- 174u, 198u, 200u, 62u,
- 150u, 236u, 132u, 116u,
- 49u, 129u, 123u, 164u,
- 232u, 156u, 1u, 205u,
- 123u, 202u, 150u, 129u,
- 25u, 83u, 32u, 157u,
- 141u, 116u, 147u, 4u,
- 63u, 69u, 172u, 31u,
- 63u, 138u, 1u, 128u,
- 116u, 130u, 115u, 26u,
- 68u, 68u, 160u, 7u,
- 74u, 119u, 97u, 111u,
- 91u, 53u, 74u, 84u,
- 141u, 255u, 102u, 85u,
- 150u, 227u, 238u, 170u,
- 119u, 100u, 1u, 85u,
- 165u, 41u, 73u, 181u,
- 200u, 170u, 200u, 92u,
- 34u, 131u, 110u, 179u,
- 123u, 132u, 108u, 137u,
- 86u, 190u, 214u, 162u,
- 68u, 44u, 1u, 104u,
- 68u, 127u, 91u, 140u,
- 169u, 202u, 170u, 131u,
- 219u, 148u, 214u, 220u,
- 0u, 52u, 180u, 103u,
- 229u, 91u, 152u, 68u,
- 172u, 92u, 157u, 155u,
- 131u, 222u, 112u, 1u,
- 41u, 162u, 59u, 24u,
- 43u, 118u, 164u, 126u,
- 83u, 187u, 20u, 38u,
- 71u, 132u, 42u, 173u,
- 27u, 1u, 220u, 250u,
- 128u, 102u, 75u, 157u,
- 21u, 163u, 119u, 155u,
- 143u, 167u, 207u, 1u,
- 102u, 181u, 137u, 118u,
- 152u, 60u, 99u, 129u,
- 112u, 88u, 184u, 130u,
- 134u, 189u, 70u, 74u,
- 123u, 159u, 144u, 84u,
- 43u, 111u, 255u, 84u,
- 97u, 177u, 251u, 222u,
- 63u, 70u, 126u, 1u,
- 78u, 78u, 223u, 140u,
- 152u, 144u, 89u, 55u,
- 175u, 144u, 74u, 176u,
- 255u, 204u, 239u, 224u,
- 113u, 61u, 95u, 136u,
- 51u, 177u, 93u, 158u,
- 122u, 87u, 207u, 122u,
- 173u, 54u, 215u, 234u,
- 62u, 0u, 205u, 86u,
- 158u, 88u, 66u, 13u,
- 150u, 150u, 118u, 106u,
- 88u, 162u, 116u, 174u,
- 188u, 184u, 1u, 109u,
- 96u, 167u, 159u, 111u,
- 74u, 172u, 141u, 118u,
- 0u, 189u, 242u, 12u,
- 155u, 83u, 58u, 205u,
- 162u, 135u, 179u, 105u,
- 119u, 105u, 108u, 201u,
- 55u, 99u, 118u, 69u,
- 163u, 141u, 141u, 111u,
- 144u, 137u, 255u, 97u,
- 255u, 229u, 133u, 126u,
- 61u, 172u, 108u, 120u,
- 183u, 64u, 164u, 129u,
- 69u, 104u, 190u, 200u,
- 185u, 247u, 119u, 214u,
- 7u, 143u, 51u, 105u,
- 174u, 77u, 114u, 129u,
- 188u, 0u, 88u, 179u,
- 91u, 0u, 185u, 103u,
- 165u, 156u, 84u, 39u,
- 133u, 126u, 137u, 53u,
- 84u, 231u, 243u, 135u,
- 61u, 159u, 65u, 82u,
- 87u, 226u, 158u, 104u,
- 102u, 154u, 107u, 255u,
- 127u, 160u, 138u, 242u,
- 107u, 123u, 181u, 255u,
- 147u, 40u, 198u, 123u,
- 116u, 84u, 194u, 81u,
- 212u, 162u, 44u, 248u,
- 183u, 86u, 115u, 8u,
- 104u, 86u, 69u, 56u,
- 224u, 132u, 160u, 70u,
- 0u, 88u, 170u, 185u,
- 255u, 85u, 203u, 196u,
- 190u, 65u, 187u, 113u,
- 102u, 76u, 21u, 173u,
- 110u, 141u, 74u, 101u,
- 112u, 125u, 162u, 137u,
- 202u, 125u, 98u, 174u,
- 136u, 157u, 1u, 113u,
- 164u, 77u, 97u, 139u,
- 159u, 50u, 192u, 1u,
- 68u, 23u, 117u, 175u,
- 230u, 135u, 193u, 152u,
- 115u, 62u, 143u, 111u,
- 147u, 211u, 191u, 124u,
- 214u, 141u, 152u, 172u,
- 65u, 90u, 171u, 1u,
- 95u, 207u, 79u, 185u,
- 162u, 1u, 186u, 140u,
- 1u, 149u, 132u, 128u,
- 73u, 63u, 74u, 99u,
- 165u, 147u, 111u, 158u,
- 185u, 195u, 39u, 74u,
- 121u, 0u, 95u, 107u,
- 131u, 127u, 133u, 82u,
- 63u, 169u, 138u, 164u,
- 148u, 102u, 197u, 67u,
- 120u, 55u, 121u, 53u,
- 255u, 172u, 153u, 130u,
- 226u, 177u, 146u, 185u,
- 149u, 34u, 162u, 150u,
- 194u, 218u, 183u, 86u,
- 255u, 69u, 32u, 138u,
- 142u, 111u, 81u, 115u,
- 161u, 1u, 67u, 191u,
- 53u, 175u, 76u, 110u,
- 51u, 141u, 197u, 77u,
- 71u, 143u, 158u, 102u,
- 179u, 162u, 121u, 114u,
- 155u, 255u, 116u, 92u,
- 65u, 96u, 75u, 170u,
- 69u, 193u, 82u, 155u,
- 100u, 84u, 178u, 177u,
- 110u, 143u, 158u, 138u,
- 107u, 114u, 255u, 180u,
- 224u, 69u, 172u, 191u,
- 155u, 181u, 164u, 76u,
- 61u, 178u, 22u, 64u,
- 45u, 149u, 79u, 46u,
- 255u, 127u, 113u, 41u,
- 142u, 55u, 124u, 178u,
- 116u, 159u, 116u, 114u,
- 185u, 116u, 154u, 114u,
- 1u, 128u, 175u, 106u,
- 55u, 75u, 162u, 90u,
- 85u, 125u, 145u, 6u,
- 152u, 154u, 109u, 71u,
- 125u, 255u, 135u, 162u,
- 144u, 152u, 162u, 195u,
- 53u, 164u, 155u, 153u,
- 255u, 144u, 107u, 85u,
- 184u, 124u, 190u, 108u,
- 147u, 87u, 139u, 104u,
- 129u, 125u, 220u, 119u,
- 81u, 151u, 157u, 137u,
- 116u, 1u, 89u, 6u,
- 152u, 130u, 125u, 196u,
- 191u, 135u, 210u, 1u,
- 30u, 153u, 87u, 71u,
- 140u, 166u, 121u, 120u,
- 230u, 77u, 75u, 229u,
- 114u, 38u, 169u, 69u,
- 197u, 191u, 116u, 1u,
- 110u, 197u, 210u, 88u,
- 163u, 141u, 63u, 112u,
- 40u, 136u, 86u, 95u,
- 1u, 149u, 132u, 211u,
- 58u, 175u, 143u, 82u,
- 218u, 246u, 203u, 214u,
- 78u, 196u, 87u, 140u,
- 3u, 187u, 255u, 147u,
- 115u, 97u, 147u, 82u,
- 80u, 48u, 155u, 122u,
- 137u, 75u, 70u, 88u,
- 191u, 172u, 136u, 74u,
- 171u, 201u, 1u, 107u,
- 180u, 170u, 97u, 183u,
- 37u, 100u, 29u, 245u,
- 45u, 108u, 186u, 224u,
- 150u, 151u, 152u, 0u,
- 151u, 131u, 63u, 187u,
- 63u, 16u, 138u, 118u,
- 151u, 94u, 224u, 146u,
- 1u, 189u, 96u, 56u,
- 107u, 196u, 171u, 162u,
- 83u, 255u, 88u, 34u,
- 136u, 201u, 189u, 90u,
- 70u, 153u, 190u, 235u,
- 255u, 35u, 93u, 118u,
- 108u, 91u, 100u, 155u,
- 110u, 78u, 214u, 58u,
- 175u, 190u, 183u, 131u,
- 124u, 85u, 146u, 255u,
- 102u, 168u, 80u, 155u,
- 112u, 129u, 117u, 215u,
- 126u, 199u, 150u, 32u,
- 69u, 232u, 114u, 46u,
- 204u, 145u, 255u, 61u,
- 129u, 151u, 87u, 210u,
- 125u, 113u, 176u, 187u,
- 102u, 149u, 152u, 133u,
- 132u, 149u, 85u, 102u,
- 101u, 111u, 152u, 90u,
- 131u, 255u, 78u, 107u,
- 132u, 108u, 96u, 116u,
- 160u, 148u, 89u, 19u,
- 80u, 192u, 135u, 0u,
- 213u, 107u, 194u, 156u,
- 147u, 67u, 170u, 56u,
- 99u, 137u, 167u, 255u,
- 229u, 168u, 87u, 107u,
- 112u, 110u, 202u, 174u,
- 92u, 108u, 121u, 178u,
- 143u, 200u, 241u, 200u,
- 69u, 127u, 255u, 179u,
- 107u, 161u, 59u, 135u,
- 110u, 194u, 101u, 111u,
- 200u, 255u, 63u, 193u,
- 169u, 218u, 41u, 252u,
- 142u, 208u, 155u, 114u,
- 131u, 131u, 110u, 215u,
- 84u, 171u, 161u, 217u,
- 148u, 185u, 179u, 49u,
- 255u, 156u, 236u, 183u,
- 156u, 1u, 173u, 119u,
- 170u, 101u, 113u, 121u,
- 167u, 181u, 135u, 130u,
- 105u, 58u, 196u, 36u,
- 41u, 142u, 35u, 168u,
- 144u, 255u, 20u, 85u,
- 103u, 138u, 114u, 186u,
- 19u, 118u, 63u, 92u,
- 99u, 189u, 168u, 68u,
- 165u, 61u, 11u, 159u,
- 159u, 114u, 152u, 89u,
- 95u, 101u, 1u, 43u,
- 104u, 132u, 19u, 155u,
- 255u, 100u, 89u, 230u,
- 87u, 93u, 159u, 154u,
- 132u, 37u, 48u, 247u,
- 118u, 120u, 22u, 60u,
- 104u, 251u, 136u, 125u,
- 158u, 115u, 106u, 75u,
- 1u, 120u, 60u, 119u,
- 162u, 172u, 221u, 100u,
- 186u, 163u, 182u, 183u,
- 193u, 158u, 173u, 201u,
- 43u, 1u, 141u, 78u,
- 92u, 189u, 118u, 43u,
- 172u, 255u, 98u, 177u,
- 77u, 51u, 84u, 164u,
- 102u, 175u, 125u, 173u,
- 155u, 113u, 212u, 96u,
- 179u, 106u, 55u, 101u,
- 54u, 243u, 191u, 152u,
- 255u, 133u, 125u, 97u,
- 188u, 154u, 102u, 79u,
- 180u, 60u, 130u, 119u,
- 56u, 135u, 25u, 138u,
- 144u, 67u, 136u, 1u,
- 75u, 159u, 157u, 174u,
- 180u, 134u, 98u, 255u,
- 48u, 41u, 237u, 171u,
- 145u, 105u, 125u, 24u,
- 121u, 208u, 136u, 113u,
- 106u, 246u, 150u, 132u,
- 48u, 91u, 124u, 255u,
- 118u, 167u, 125u, 101u,
- 158u, 1u, 237u, 54u,
- 101u, 27u, 137u, 85u,
- 77u, 156u, 153u, 102u,
- 205u, 216u, 114u, 73u,
- 51u, 213u, 158u, 149u,
- 112u, 232u, 132u, 141u,
- 164u, 217u, 82u, 179u,
- 50u, 187u, 1u, 94u,
- 127u, 131u, 126u, 103u,
- 107u, 127u, 255u, 178u,
- 104u, 135u, 105u, 112u,
- 169u, 120u, 93u, 56u,
- 171u, 86u, 184u, 1u,
- 205u, 41u, 133u, 128u,
- 122u, 235u, 195u, 153u,
- 120u, 159u, 91u, 95u,
- 159u, 152u, 135u, 94u,
- 132u, 93u, 89u, 183u,
- 0u, 64u, 150u, 91u,
- 114u, 101u, 199u, 69u,
- 255u, 186u, 194u, 99u,
- 184u, 124u, 80u, 191u,
- 101u, 81u, 138u, 140u,
- 126u, 133u, 90u, 115u,
- 85u, 163u, 93u, 125u,
- 102u, 242u, 255u, 97u,
- 85u, 146u, 55u, 61u,
- 150u, 211u, 61u, 150u,
- 171u, 91u, 169u, 121u,
- 171u, 255u, 172u, 136u,
- 156u, 161u, 35u, 172u,
- 125u, 253u, 61u, 56u,
- 225u, 221u, 1u, 41u,
- 168u, 162u, 200u, 75u,
- 149u, 237u, 242u, 171u,
- 166u, 31u, 186u, 194u,
- 170u, 1u, 112u, 231u,
- 58u, 114u, 174u, 29u,
- 112u, 128u, 174u, 226u,
- 105u, 119u, 150u, 134u,
- 184u, 241u, 138u, 157u,
- 75u, 169u, 73u, 0u,
- 61u, 142u, 44u, 142u,
- 121u, 180u, 40u, 85u,
- 55u, 112u, 1u, 184u,
- 131u, 118u, 150u, 92u,
- 129u, 177u, 105u, 130u,
- 159u, 127u, 162u, 95u,
- 82u, 122u, 255u, 168u,
- 146u, 18u, 149u, 66u,
- 224u, 98u, 231u, 119u,
- 182u, 26u, 80u, 91u,
- 154u, 82u, 55u, 210u,
- 1u, 77u, 153u, 119u,
- 131u, 171u, 98u, 50u,
- 116u, 71u, 178u, 149u,
- 194u, 106u, 121u, 84u,
- 1u, 31u, 138u, 117u,
- 231u, 165u, 73u, 52u,
- 228u, 139u, 129u, 77u,
- 106u, 150u, 126u, 103u,
- 210u, 158u, 100u, 138u,
- 68u, 93u, 150u, 114u,
- 131u, 158u, 1u, 147u,
- 95u, 1u, 226u, 109u,
- 180u, 199u, 87u, 88u,
- 190u, 224u, 98u, 232u,
- 105u, 93u, 103u, 229u,
- 226u, 137u, 95u, 48u,
- 59u, 70u, 115u, 95u,
- 1u, 51u, 162u, 123u,
- 74u, 130u, 165u, 164u,
- 168u, 122u, 236u, 255u,
- 84u, 122u, 189u, 32u,
- 114u, 241u, 255u, 175u,
- 170u, 210u, 23u, 15u,
- 0u, 36u, 144u, 23u,
- 97u, 204u, 93u, 135u,
- 130u, 123u, 56u, 164u,
- 156u, 189u, 28u, 32u,
- 136u, 122u, 0u, 176u,
- 25u, 81u, 135u, 128u,
- 184u, 140u, 65u, 17u,
- 62u, 179u, 181u, 214u,
- 119u, 98u, 185u, 180u,
- 134u, 135u, 169u, 104u,
- 136u, 188u, 113u, 98u,
- 187u, 255u, 155u, 19u,
- 85u, 134u, 132u, 174u,
- 255u, 219u, 111u, 99u,
- 205u, 216u, 168u, 101u,
- 144u, 198u, 219u, 15u,
- 1u, 116u, 138u, 224u,
- 161u, 146u, 217u, 93u,
- 161u, 212u, 189u, 54u,
- 104u, 99u, 135u, 194u,
- 81u, 163u, 191u, 178u,
- 164u, 140u, 33u, 155u,
- 195u, 65u, 144u, 53u,
- 230u, 34u, 0u, 180u,
- 141u, 131u, 25u, 79u,
- 129u, 255u, 43u, 74u,
- 137u, 203u, 20u, 17u,
- 175u, 235u, 21u, 148u,
- 177u, 74u, 196u, 101u,
- 39u, 136u, 1u, 155u,
- 35u, 128u, 82u, 128u,
- 120u, 152u, 111u, 78u,
- 100u, 69u, 86u, 158u,
- 149u, 94u, 255u, 47u,
- 97u, 131u, 66u, 191u,
- 195u, 109u, 120u, 80u,
- 15u, 211u, 37u, 8u,
- 63u, 82u, 47u, 221u,
- 84u, 115u, 113u, 115u,
- 213u, 255u, 102u, 107u,
- 80u, 56u, 255u, 215u,
- 155u, 120u, 190u, 179u,
- 126u, 86u, 205u, 162u,
- 77u, 61u, 43u, 135u,
- 171u, 106u, 164u, 61u,
- 164u, 159u, 167u, 50u,
- 61u, 173u, 119u, 98u,
- 96u, 76u, 161u, 0u,
- 145u, 1u, 175u, 52u,
- 97u, 155u, 14u, 122u,
- 43u, 178u, 190u, 17u,
- 148u, 190u, 146u, 62u,
- 110u, 208u, 210u, 169u,
- 92u, 255u, 202u, 187u,
- 169u, 91u, 33u, 166u,
- 114u, 188u, 130u, 134u,
- 136u, 93u, 64u, 87u,
- 13u, 142u, 187u, 14u,
- 202u, 115u, 49u, 161u,
- 112u, 79u, 191u, 1u,
- 143u, 179u, 53u, 88u,
- 162u, 91u, 142u, 154u,
- 114u, 63u, 30u, 159u,
- 125u, 255u, 160u, 157u,
- 225u, 57u, 244u, 82u,
- 143u, 56u, 63u, 210u,
- 166u, 112u, 76u, 165u,
- 134u, 239u, 85u, 1u,
- 152u, 78u, 201u, 245u,
- 45u, 88u, 1u, 156u,
- 89u, 22u, 202u, 140u,
- 144u, 223u, 209u, 147u,
- 191u, 162u, 187u, 115u,
- 216u, 180u, 119u, 91u,
- 101u, 26u, 172u, 255u,
- 107u, 64u, 59u, 112u,
- 199u, 255u, 84u, 112u,
- 141u, 160u, 167u, 119u,
- 128u, 215u, 27u, 34u,
- 208u, 10u, 198u, 147u,
- 125u, 130u, 1u, 73u,
- 36u, 167u, 149u, 186u,
- 127u, 138u, 62u, 78u,
- 133u, 185u, 227u, 140u,
- 118u, 0u, 134u, 43u,
- 167u, 116u, 208u, 233u,
- 69u, 40u, 147u, 164u,
- 99u, 181u, 65u, 164u,
- 155u, 21u, 255u, 201u,
- 15u, 127u, 108u, 61u,
- 147u, 115u, 57u, 255u,
- 229u, 165u, 8u, 35u,
- 182u, 115u, 207u, 71u,
- 107u, 64u, 255u, 80u,
- 48u, 177u, 126u, 172u,
- 85u, 196u, 84u, 167u,
- 36u, 65u, 149u, 129u,
- 106u, 196u, 125u, 128u,
- 83u, 71u, 253u, 213u,
- 1u, 90u, 42u, 104u,
- 111u, 102u, 133u, 94u,
- 84u, 117u, 181u, 76u,
- 100u, 129u, 255u, 124u,
- 252u, 167u, 123u, 193u,
- 15u, 92u, 47u, 1u,
- 180u, 189u, 168u, 55u,
- 136u, 206u, 53u, 90u,
- 91u, 105u, 29u, 177u,
- 162u, 171u, 146u, 175u,
- 1u, 161u, 108u, 120u,
- 143u, 141u, 131u, 125u,
- 146u, 93u, 186u, 117u,
- 118u, 202u, 240u, 39u,
- 44u, 209u, 82u, 1u,
- 8u, 140u, 167u, 58u,
- 56u, 78u, 119u, 164u,
- 114u, 144u, 114u, 123u,
- 128u, 144u, 99u, 72u,
- 58u, 174u, 57u, 146u,
- 124u, 255u, 119u, 83u,
- 63u, 106u, 82u, 119u,
- 115u, 165u, 248u, 255u,
- 200u, 107u, 178u, 148u,
- 87u, 201u, 135u, 201u,
- 138u, 102u, 126u, 86u,
- 137u, 41u, 148u, 255u,
- 128u, 129u, 164u, 54u,
- 174u, 131u, 157u, 181u,
- 233u, 54u, 212u, 135u,
- 176u, 137u, 198u, 164u,
- 43u, 165u, 129u, 99u,
- 117u, 255u, 169u, 103u,
- 189u, 170u, 94u, 197u,
- 157u, 167u, 30u, 138u,
- 97u, 215u, 54u, 69u,
- 122u, 195u, 255u, 83u,
- 244u, 106u, 110u, 183u,
- 161u, 1u, 103u, 79u,
- 148u, 229u, 89u, 27u,
- 113u, 42u, 206u, 205u,
- 80u, 90u, 78u, 77u,
- 223u, 32u, 196u, 177u,
- 180u, 180u, 138u, 200u,
- 181u, 52u, 133u, 255u,
- 190u, 38u, 175u, 253u,
- 26u, 157u, 255u, 1u,
- 142u, 21u, 153u, 121u,
- 97u, 231u, 150u, 90u,
- 58u, 88u, 154u, 127u,
- 124u, 115u, 62u, 120u,
- 124u, 173u, 171u, 67u,
- 0u, 109u, 155u, 71u,
- 142u, 144u, 143u, 187u,
- 126u, 73u, 78u, 255u,
- 99u, 96u, 146u, 120u,
- 142u, 106u, 68u, 125u,
- 122u, 151u, 60u, 210u,
- 76u, 190u, 142u, 184u,
- 212u, 255u, 116u, 161u,
- 240u, 102u, 193u, 36u,
- 145u, 49u, 132u, 190u,
- 1u, 118u, 120u, 183u,
- 69u, 78u, 69u, 143u,
- 151u, 146u, 143u, 164u,
- 154u, 1u, 107u, 96u,
- 122u, 205u, 200u, 77u,
- 104u, 113u, 134u, 21u,
- 38u, 146u, 80u, 187u,
- 222u, 207u, 146u, 255u,
- 71u, 206u, 59u, 108u,
- 80u, 47u, 250u, 59u,
- 176u, 160u, 141u, 111u,
- 215u, 117u, 143u, 115u,
- 88u, 162u, 255u, 27u,
- 130u, 114u, 38u, 136u,
- 108u, 150u, 125u, 109u,
- 116u, 1u, 161u, 158u,
- 86u, 136u, 110u, 203u,
- 110u, 104u, 135u, 177u,
- 53u, 135u, 69u, 83u,
- 156u, 52u, 255u, 80u,
- 157u, 194u, 194u, 134u,
- 91u, 128u, 110u, 157u,
- 125u, 121u, 132u, 160u,
- 223u, 91u, 198u, 54u,
- 35u, 0u, 121u, 56u,
- 142u, 145u, 170u, 74u,
- 138u, 111u, 132u, 82u,
- 141u, 110u, 200u, 149u,
- 51u, 147u, 103u, 134u,
- 165u, 49u, 27u, 255u,
- 59u, 231u, 177u, 110u,
- 98u, 50u, 149u, 255u,
- 141u, 93u, 137u, 194u,
- 130u, 165u, 128u, 140u,
- 182u, 172u, 131u, 48u,
- 176u, 139u, 217u, 161u,
- 135u, 164u, 218u, 125u,
- 127u, 255u, 210u, 181u,
- 48u, 132u, 95u, 92u,
- 241u, 83u, 160u, 211u,
- 146u, 141u, 112u, 255u,
- 119u, 73u, 149u, 38u,
- 77u, 171u, 220u, 158u,
- 132u, 196u, 206u, 103u,
- 153u, 48u, 116u, 61u,
- 156u, 164u, 160u, 207u,
- 255u, 112u, 11u, 204u,
- 158u, 224u, 179u, 177u,
- 139u, 133u, 146u, 175u,
- 244u, 125u, 241u, 93u,
- 1u, 39u, 138u, 252u,
- 221u, 32u, 104u, 75u,
- 168u, 38u, 213u, 176u,
- 165u, 210u, 205u, 6u,
- 227u, 205u, 1u, 58u,
- 158u, 130u, 119u, 110u,
- 109u, 195u, 108u, 255u,
- 103u, 32u, 132u, 140u,
- 127u, 85u, 174u, 209u,
- 41u, 0u, 148u, 209u,
- 96u, 66u, 166u, 189u,
- 181u, 169u, 220u, 93u,
- 157u, 152u, 164u, 54u,
- 119u, 192u, 58u, 108u,
- 159u, 150u, 106u, 160u,
- 1u, 169u, 64u, 131u,
- 77u, 156u, 69u, 83u,
- 172u, 169u, 79u, 28u,
- 161u, 109u, 175u, 186u,
- 223u, 79u, 1u, 34u,
- 210u, 86u, 125u, 55u,
- 51u, 188u, 115u, 1u,
- 239u, 129u, 251u, 160u,
- 195u, 214u, 89u, 249u,
- 160u, 203u, 106u, 111u,
- 142u, 141u, 201u, 84u,
- 122u, 86u, 107u, 79u,
- 113u, 145u, 162u, 140u,
- 134u, 0u, 160u, 131u,
- 213u, 15u, 181u, 238u,
- 179u, 1u, 62u, 213u,
- 133u, 129u, 204u, 206u,
- 172u, 104u, 138u, 135u,
- 133u, 225u, 64u, 87u,
- 88u, 164u, 144u, 255u,
- 86u, 76u, 103u, 83u,
- 193u, 100u, 204u, 100u,
- 196u, 156u, 92u, 154u,
- 198u, 255u, 195u, 214u,
- 181u, 76u, 84u, 25u,
- 69u, 47u, 105u, 88u,
- 76u, 177u, 58u, 181u,
- 157u, 106u, 130u, 97u,
- 173u, 193u, 118u, 81u,
- 154u, 57u, 1u, 212u,
- 153u, 184u, 157u, 160u,
- 149u, 121u, 164u, 255u,
- 122u, 59u, 143u, 131u,
- 171u, 129u, 134u, 54u,
- 110u, 119u, 145u, 188u,
- 217u, 169u, 145u, 145u,
- 117u, 216u, 255u, 118u,
- 209u, 234u, 59u, 204u,
- 111u, 136u, 255u, 134u,
- 129u, 78u, 113u, 127u,
- 117u, 128u, 123u, 178u,
- 175u, 196u, 176u, 60u,
- 87u, 62u, 129u, 140u,
- 81u, 69u, 182u, 11u,
- 201u, 227u, 82u, 126u,
- 151u, 194u, 192u, 1u,
- 88u, 88u, 112u, 214u,
- 131u, 175u, 152u, 1u,
- 94u, 120u, 116u, 5u,
- 162u, 119u, 161u, 227u,
- 72u, 120u, 74u, 220u,
- 55u, 255u, 208u, 142u,
- 176u, 93u, 124u, 159u,
- 59u, 123u, 212u, 170u,
- 73u, 103u, 96u, 255u,
- 112u, 216u, 103u, 121u,
- 120u, 127u, 125u, 134u,
- 181u, 137u, 157u, 142u,
- 88u, 150u, 255u, 128u,
- 105u, 227u, 70u, 10u,
- 53u, 61u, 208u, 173u,
- 196u, 126u, 38u, 94u,
- 24u, 109u, 115u, 140u,
- 1u, 64u, 117u, 105u,
- 139u, 134u, 189u, 185u,
- 205u, 130u, 250u, 87u,
- 143u, 83u, 247u, 81u,
- 180u, 76u, 178u, 136u,
- 1u, 124u, 149u, 209u,
- 89u, 140u, 182u, 65u,
- 127u, 24u, 50u, 192u,
- 61u, 109u, 129u, 81u,
- 223u, 255u, 26u, 49u,
- 149u, 217u, 125u, 67u,
- 148u, 165u, 113u, 136u,
- 104u, 190u, 191u, 162u,
- 206u, 108u, 136u, 188u,
- 1u, 117u, 208u, 123u,
- 98u, 72u, 140u, 124u,
- 172u, 171u, 105u, 106u,
- 81u, 136u, 137u, 88u,
- 1u, 239u, 93u, 82u,
- 91u, 185u, 191u, 97u,
- 181u, 65u, 163u, 147u,
- 43u, 152u, 208u, 89u,
- 154u, 158u, 0u, 125u,
- 66u, 200u, 102u, 73u,
- 108u, 205u, 129u, 145u,
- 1u, 122u, 127u, 152u,
- 182u, 143u, 57u, 193u,
- 57u, 247u, 38u, 1u,
- 234u, 9u, 95u, 73u,
- 118u, 232u, 66u, 20u,
- 152u, 1u, 34u, 67u,
- 100u, 124u, 125u, 69u,
- 149u, 0u, 94u, 144u,
- 132u, 106u, 181u, 138u,
- 207u, 76u, 15u, 130u,
- 170u, 254u, 97u, 186u,
- 124u, 144u, 115u, 13u,
- 62u, 174u, 144u, 59u,
- 134u, 166u, 123u, 255u,
- 66u, 179u, 137u, 125u,
- 129u, 63u, 153u, 0u,
- 241u, 165u, 83u, 98u,
- 107u, 152u, 9u, 120u,
- 163u, 65u, 123u, 170u,
- 161u, 149u, 119u, 171u,
- 105u, 149u, 109u, 170u,
- 104u, 255u, 138u, 158u,
- 12u, 131u, 135u, 95u,
- 174u, 79u, 99u, 90u,
- 27u, 111u, 145u, 86u,
- 140u, 255u, 117u, 206u,
- 170u, 142u, 97u, 70u,
- 250u, 170u, 1u, 107u,
- 88u, 168u, 50u, 69u,
- 150u, 114u, 115u, 50u,
- 171u, 108u, 40u, 12u,
- 114u, 110u, 218u, 177u,
- 152u, 196u, 123u, 166u,
- 66u, 245u, 255u, 88u,
- 237u, 1u, 103u, 84u,
- 126u, 56u, 244u, 124u,
- 89u, 189u, 79u, 146u,
- 128u, 116u, 204u, 119u,
- 70u, 250u, 225u, 185u,
- 217u, 154u, 234u, 1u,
- 94u, 252u, 144u, 46u,
- 126u, 178u, 92u, 80u,
- 128u, 142u, 86u, 255u,
- 182u, 83u, 177u, 35u,
- 19u, 166u, 148u, 57u,
- 67u, 175u, 119u, 122u,
- 56u, 255u, 197u, 182u,
- 210u, 115u, 206u, 102u,
- 84u, 99u, 171u, 110u,
- 191u, 71u, 23u, 130u,
- 252u, 69u, 213u, 41u,
- 3u, 4u, 88u, 109u,
- 148u, 136u, 122u, 255u,
- 230u, 79u, 223u, 18u,
- 111u, 149u, 163u, 149u,
- 56u, 124u, 99u, 51u,
- 176u, 247u, 218u, 143u,
- 170u, 148u, 255u, 96u,
- 255u, 202u, 75u, 93u,
- 109u, 56u, 29u, 103u,
- 142u, 185u, 164u, 144u,
- 68u, 82u, 108u, 170u,
- 53u, 192u, 83u, 86u,
- 137u, 1u, 224u, 103u,
- 216u, 181u, 13u, 193u,
- 164u, 155u, 212u, 143u,
- 132u, 143u, 220u, 126u,
- 221u, 90u, 164u, 1u,
- 34u, 127u, 144u, 24u,
- 232u, 107u, 112u, 140u,
- 211u, 193u, 7u, 158u,
- 231u, 88u, 115u, 26u,
- 22u, 16u, 183u, 255u,
- 158u, 183u, 86u, 223u,
- 157u, 183u, 154u, 155u,
- 135u, 214u, 124u, 101u,
- 255u, 132u, 155u, 188u,
- 57u, 132u, 175u, 126u,
- 118u, 1u, 71u, 119u,
- 149u, 83u, 159u, 180u,
- 113u, 172u, 81u, 112u,
- 95u, 171u, 120u, 108u,
- 63u, 117u, 172u, 41u,
- 223u, 131u, 137u, 224u,
- 144u, 232u, 234u, 181u,
- 124u, 10u, 0u, 97u,
- 166u, 194u, 120u, 224u,
- 70u, 166u, 60u, 126u,
- 169u, 52u, 173u, 185u,
- 228u, 167u, 255u, 161u,
- 144u, 143u, 187u, 16u,
- 52u, 15u, 73u, 28u,
- 1u, 40u, 173u, 46u,
- 157u, 72u, 167u, 133u,
- 27u, 98u, 169u, 1u,
- 108u, 93u, 90u, 203u,
- 225u, 142u, 158u, 153u,
- 193u, 185u, 50u, 202u,
- 117u, 119u, 181u, 222u,
- 57u, 175u, 130u, 157u,
- 255u, 208u, 204u, 198u,
- 137u, 138u, 191u, 176u,
- 67u, 163u, 177u, 52u,
- 115u, 34u, 74u, 45u,
- 144u, 123u, 191u, 242u,
- 138u, 72u, 61u, 255u,
- 153u, 97u, 122u, 118u,
- 161u, 197u, 107u, 255u,
- 124u, 154u, 147u, 100u,
- 98u, 69u, 177u, 123u,
- 138u, 179u, 85u, 80u,
- 216u, 221u, 108u, 180u,
- 74u, 164u, 136u, 136u,
- 97u, 129u, 1u, 154u,
- 3u, 111u, 1u, 118u,
- 229u, 59u, 42u, 239u,
- 74u, 97u, 119u, 67u,
- 230u, 157u, 104u, 40u,
- 238u, 224u, 195u, 255u,
- 204u, 216u, 88u, 216u,
- 122u, 112u, 119u, 172u,
- 93u, 101u, 82u, 104u,
- 48u, 102u, 191u, 255u,
- 65u, 101u, 116u, 113u,
- 163u, 42u, 128u, 124u,
- 84u, 206u, 173u, 125u,
- 143u, 44u, 204u, 91u,
- 90u, 220u, 24u, 146u,
- 33u, 1u, 68u, 27u,
- 167u, 139u, 189u, 79u,
- 32u, 255u, 164u, 178u,
- 203u, 172u, 44u, 102u,
- 122u, 100u, 77u, 105u,
- 142u, 63u, 95u, 176u,
- 155u, 238u, 69u, 94u,
- 177u, 160u, 121u, 128u,
- 141u, 141u, 164u, 126u,
- 73u, 57u, 133u, 255u,
- 44u, 217u, 64u, 189u,
- 119u, 255u, 171u, 55u,
- 126u, 121u, 44u, 172u,
- 33u, 184u, 134u, 160u,
- 88u, 69u, 111u, 26u,
- 60u, 64u, 147u, 82u,
- 210u, 78u, 96u, 182u,
- 105u, 131u, 95u, 255u,
- 147u, 128u, 240u, 165u,
- 85u, 197u, 84u, 151u,
- 0u, 154u, 195u, 27u,
- 145u, 137u, 21u, 84u,
- 206u, 127u, 144u, 48u,
- 57u, 235u, 75u, 175u,
- 164u, 57u, 184u, 145u,
- 114u, 55u, 250u, 255u,
- 173u, 131u, 230u, 255u,
- 134u, 82u, 196u, 112u,
- 145u, 173u, 159u, 150u,
- 179u, 250u, 215u, 58u,
- 176u, 91u, 159u, 55u,
- 197u, 133u, 188u, 82u,
- 88u, 255u, 133u, 93u,
- 148u, 140u, 63u, 94u,
- 145u, 132u, 85u, 128u,
- 145u, 156u, 129u, 74u,
- 85u, 255u, 26u, 108u,
- 96u, 125u, 135u, 39u,
- 92u, 124u, 107u, 96u,
- 99u, 122u, 160u, 90u,
- 124u, 124u, 132u, 67u,
- 109u, 32u, 92u, 255u,
- 207u, 18u, 215u, 171u,
- 135u, 69u, 105u, 36u,
- 135u, 133u, 163u, 1u,
- 171u, 118u, 119u, 220u,
- 234u, 133u, 145u, 128u,
- 85u, 78u, 161u, 69u,
- 120u, 255u, 98u, 141u,
- 65u, 77u, 196u, 103u,
- 106u, 161u, 145u, 135u,
- 212u, 141u, 154u, 1u,
- 170u, 177u, 96u, 156u,
- 186u, 114u, 94u, 52u,
- 51u, 116u, 47u, 199u,
- 183u, 194u, 224u, 184u,
- 110u, 33u, 115u, 161u,
- 0u, 159u, 16u, 221u,
- 8u, 137u, 128u, 255u,
- 38u, 176u, 163u, 46u,
- 77u, 175u, 181u, 139u,
- 195u, 212u, 153u, 81u,
- 188u, 191u, 189u, 150u,
- 162u, 135u, 211u, 64u,
- 186u, 255u, 219u, 144u,
- 113u, 147u, 148u, 213u,
- 1u, 163u, 130u, 47u,
- 245u, 77u, 67u, 114u,
- 179u, 22u, 109u, 242u,
- 155u, 85u, 195u, 175u,
- 200u, 151u, 147u, 53u,
- 131u, 142u, 104u, 88u,
- 174u, 255u, 103u, 46u,
- 119u, 42u, 102u, 49u,
- 255u, 112u, 178u, 153u,
- 122u, 133u, 96u, 98u,
- 144u, 69u, 132u, 156u,
- 119u, 162u, 189u, 161u,
- 159u, 144u, 129u, 202u,
- 127u, 92u, 1u, 97u,
- 64u, 186u, 133u, 165u,
- 108u, 141u, 158u, 109u,
- 144u, 183u, 144u, 122u,
- 182u, 202u, 205u, 124u,
- 84u, 156u, 46u, 122u,
- 1u, 237u, 121u, 109u,
- 77u, 126u, 161u, 34u,
- 109u, 182u, 1u, 173u,
- 110u, 230u, 153u, 148u,
- 168u, 186u, 151u, 66u,
- 208u, 101u, 130u, 193u,
- 129u, 214u, 119u, 169u,
- 150u, 255u, 237u, 91u,
- 94u, 123u, 148u, 140u,
- 219u, 175u, 239u, 138u,
- 137u, 166u, 109u, 148u,
- 78u, 110u, 240u, 145u,
- 1u, 76u, 199u, 152u,
- 97u, 201u, 238u, 182u,
- 48u, 185u, 1u, 4u,
- 14u, 52u, 190u, 69u,
- 212u, 15u, 51u, 172u,
- 108u, 216u, 96u, 58u,
- 138u, 121u, 51u, 7u,
- 139u, 250u, 255u, 141u,
- 181u, 54u, 229u, 137u,
- 65u, 194u, 93u, 97u,
- 216u, 102u, 154u, 71u,
- 39u, 115u, 191u, 78u,
- 255u, 53u, 43u, 183u,
- 189u, 229u, 166u, 185u,
- 165u, 134u, 116u, 112u,
- 135u, 255u, 107u, 138u,
- 41u, 144u, 95u, 97u,
- 255u, 41u, 181u, 165u,
- 50u, 165u, 110u, 185u,
- 189u, 127u, 112u, 151u,
- 53u, 104u, 230u, 82u,
- 185u, 167u, 141u, 108u,
- 94u, 255u, 89u, 193u,
- 56u, 125u, 161u, 170u,
- 80u, 193u, 99u, 210u,
- 109u, 53u, 219u, 90u,
- 55u, 75u, 3u, 51u,
- 146u, 179u, 124u, 156u,
- 11u, 53u, 1u, 187u,
- 255u, 97u, 195u, 159u,
- 118u, 88u, 96u, 85u,
- 115u, 136u, 84u, 138u,
- 54u, 222u, 188u, 140u,
- 179u, 165u, 143u, 192u,
- 220u, 111u, 55u, 182u,
- 129u, 75u, 10u, 243u,
- 93u, 56u, 255u, 124u,
- 255u, 177u, 247u, 87u,
- 102u, 77u, 174u, 195u,
- 96u, 101u, 184u, 81u,
- 43u, 40u, 126u, 13u,
- 139u, 84u, 123u, 164u,
- 1u, 157u, 55u, 245u,
- 219u, 145u, 175u, 123u,
- 213u, 209u, 221u, 50u,
- 167u, 53u, 151u, 118u,
- 177u, 0u, 132u, 230u,
- 160u, 116u, 61u, 138u,
- 222u, 93u, 86u, 71u,
- 125u, 120u, 35u, 143u,
- 153u, 174u, 108u, 90u,
- 132u, 139u, 169u, 154u,
- 139u, 1u, 155u, 173u,
- 178u, 151u, 255u, 77u,
- 113u, 149u, 98u, 148u,
- 213u, 84u, 64u, 186u,
- 142u, 74u, 94u, 149u,
- 189u, 1u, 88u, 87u,
- 167u, 129u, 153u, 191u,
- 97u, 201u, 124u, 106u,
- 147u, 93u, 248u, 175u,
- 219u, 84u, 64u, 6u,
- 7u, 163u, 185u, 85u,
- 177u, 218u, 123u, 0u,
- 122u, 57u, 120u, 170u,
- 109u, 140u, 115u, 129u,
- 65u, 91u, 11u, 87u,
- 102u, 158u, 73u, 0u,
- 134u, 16u, 150u, 69u,
- 168u, 255u, 127u, 198u,
- 102u, 185u, 201u, 107u,
- 143u, 9u, 33u, 152u,
- 49u, 89u, 206u, 156u,
- 25u, 92u, 196u, 116u,
- 255u, 153u, 168u, 179u,
- 239u, 127u, 69u, 106u,
- 95u, 138u, 97u, 77u,
- 61u, 69u, 113u, 128u,
- 153u, 172u, 163u, 147u,
- 74u, 111u, 70u, 106u,
- 123u, 246u, 131u, 255u,
- 169u, 153u, 206u, 251u,
- 237u, 195u, 176u, 145u,
- 119u, 53u, 255u, 51u,
- 110u, 103u, 87u, 14u,
- 32u, 226u, 2u, 14u,
- 117u, 137u, 128u, 1u,
- 108u, 109u, 92u, 136u,
- 116u, 93u, 169u, 201u,
- 123u, 37u, 118u, 145u,
- 90u, 95u, 177u, 104u,
- 255u, 209u, 146u, 152u,
- 181u, 114u, 228u, 144u,
- 136u, 147u, 110u, 13u,
- 229u, 118u, 182u, 144u,
- 0u, 175u, 209u, 125u,
- 167u, 92u, 112u, 104u,
- 108u, 64u, 184u, 255u,
- 78u, 85u, 49u, 192u,
- 39u, 15u, 200u, 168u,
- 175u, 239u, 109u, 42u,
- 127u, 98u, 171u, 191u,
- 141u, 117u, 148u, 173u,
- 132u, 191u, 221u, 151u,
- 166u, 255u, 113u, 67u,
- 134u, 177u, 131u, 88u,
- 196u, 147u, 255u, 30u,
- 136u, 144u, 148u, 49u,
- 9u, 1u, 111u, 164u,
- 70u, 53u, 145u, 97u,
- 113u, 89u, 112u, 84u,
- 53u, 116u, 188u, 62u,
- 133u, 255u, 93u, 153u,
- 152u, 158u, 255u, 60u,
- 51u, 52u, 24u, 42u,
- 163u, 145u, 138u, 149u,
- 17u, 177u, 206u, 27u,
- 6u, 211u, 205u, 237u,
- 205u, 134u, 36u, 156u,
- 31u, 51u, 19u, 81u,
- 255u, 128u, 185u, 39u,
- 119u, 149u, 105u, 240u,
- 100u, 119u, 61u, 182u,
- 12u, 14u, 106u, 72u,
- 217u, 97u, 1u, 181u,
- 168u, 71u, 198u, 251u,
- 173u, 243u, 29u, 224u,
- 65u, 112u, 171u, 123u,
- 118u, 126u, 137u, 0u,
- 126u, 134u, 109u, 255u,
- 123u, 208u, 120u, 199u,
- 88u, 91u, 92u, 112u,
- 249u, 212u, 112u, 34u,
- 96u, 79u, 162u, 255u,
- 105u, 123u, 140u, 114u,
- 119u, 128u, 223u, 151u,
- 181u, 196u, 135u, 112u,
- 212u, 39u, 156u, 138u,
- 192u, 52u, 146u, 102u,
- 39u, 20u, 70u, 79u,
- 136u, 255u, 33u, 130u,
- 94u, 1u, 122u, 96u,
- 51u, 58u, 84u, 119u,
- 158u, 159u, 117u, 87u,
- 99u, 88u, 138u, 58u,
- 136u, 144u, 90u, 222u,
- 144u, 124u, 164u, 116u,
- 255u, 129u, 86u, 123u,
- 148u, 151u, 151u, 149u,
- 109u, 1u, 225u, 124u,
- 74u, 64u, 88u, 95u,
- 181u, 232u, 109u, 132u,
- 148u, 148u, 90u, 65u,
- 140u, 255u, 152u, 185u,
- 66u, 211u, 86u, 70u,
- 134u, 64u, 26u, 87u,
- 51u, 126u, 121u, 234u,
- 113u, 115u, 30u, 255u,
- 99u, 130u, 142u, 11u,
- 170u, 119u, 148u, 48u,
- 144u, 34u, 166u, 152u,
- 52u, 202u, 203u, 140u,
- 178u, 255u, 133u, 225u,
- 154u, 68u, 234u, 154u,
- 219u, 119u, 172u, 244u,
- 184u, 110u, 233u, 135u,
- 185u, 109u, 161u, 140u,
- 76u, 108u, 194u, 117u,
- 166u, 180u, 1u, 134u,
- 106u, 182u, 31u, 15u,
- 154u, 36u, 202u, 24u,
- 161u, 146u, 0u, 75u,
- 130u, 164u, 100u, 196u,
- 165u, 138u, 20u, 43u,
- 228u, 127u, 139u, 96u,
- 110u, 178u, 131u, 124u,
- 169u, 103u, 1u, 242u,
- 107u, 90u, 217u, 202u,
- 67u, 158u, 131u, 162u,
- 175u, 123u, 43u, 207u,
- 1u, 29u, 88u, 199u,
- 92u, 180u, 51u, 124u,
- 99u, 255u, 211u, 100u,
- 189u, 77u, 63u, 111u,
- 92u, 45u, 165u, 218u,
- 169u, 154u, 107u, 47u,
- 205u, 116u, 143u, 114u,
- 188u, 228u, 109u, 20u,
- 145u, 115u, 1u, 236u,
- 231u, 92u, 50u, 176u,
- 76u, 103u, 108u, 152u,
- 183u, 136u, 46u, 31u,
- 181u, 89u, 255u, 140u,
- 147u, 35u, 74u, 155u,
- 65u, 121u, 140u, 167u,
- 163u, 165u, 156u, 161u,
- 71u, 255u, 131u, 81u,
- 150u, 111u, 161u, 220u,
- 124u, 96u, 71u, 157u,
- 159u, 160u, 121u, 232u,
- 255u, 167u, 57u, 152u,
- 90u, 103u, 125u, 149u,
- 84u, 255u, 194u, 182u,
- 115u, 61u, 119u, 105u,
- 188u, 171u, 240u, 162u,
- 56u, 145u, 188u, 255u,
- 23u, 159u, 88u, 55u,
- 243u, 224u, 128u, 167u,
- 216u, 192u, 136u, 155u,
- 113u, 128u, 144u, 108u,
- 69u, 161u, 113u, 99u,
- 1u, 156u, 62u, 26u,
- 92u, 179u, 108u, 146u,
- 93u, 84u, 165u, 139u,
- 70u, 140u, 221u, 0u,
- 166u, 200u, 104u, 146u,
- 91u, 223u, 198u, 71u,
- 18u, 150u, 98u, 128u,
- 153u, 135u, 218u, 136u,
- 93u, 185u, 116u, 190u,
- 122u, 255u, 155u, 69u,
- 83u, 93u, 149u, 221u,
- 0u, 153u, 62u, 97u,
- 139u, 104u, 114u, 169u,
- 178u, 195u, 146u, 69u,
- 149u, 167u, 15u, 175u,
- 93u, 105u, 34u, 150u,
- 218u, 149u, 153u, 247u,
- 0u, 179u, 83u, 160u,
- 200u, 102u, 163u, 165u,
- 71u, 1u, 43u, 133u,
- 213u, 182u, 189u, 195u,
- 168u, 58u, 32u, 138u,
- 145u, 173u, 177u, 163u,
- 130u, 132u, 255u, 154u,
- 123u, 142u, 198u, 172u,
- 161u, 155u, 176u, 203u,
- 66u, 178u, 83u, 0u,
- 108u, 144u, 177u, 71u,
- 223u, 160u, 109u, 71u,
- 213u, 60u, 58u, 220u,
- 148u, 64u, 160u, 144u,
- 168u, 255u, 103u, 148u,
- 132u, 69u, 154u, 58u,
- 195u, 149u, 224u, 118u,
- 148u, 238u, 56u, 29u,
- 182u, 224u, 187u, 37u,
- 129u, 196u, 83u, 144u,
- 67u, 214u, 0u, 174u,
- 97u, 47u, 53u, 145u,
- 180u, 62u, 179u, 1u,
- 30u, 73u, 77u, 194u,
- 137u, 156u, 124u, 105u,
- 109u, 56u, 84u, 255u,
- 105u, 97u, 156u, 195u,
- 56u, 137u, 175u, 183u,
- 232u, 132u, 44u, 54u,
- 144u, 138u, 69u, 142u,
- 161u, 87u, 183u, 182u,
- 70u, 123u, 135u, 173u,
- 137u, 255u, 109u, 178u,
- 24u, 252u, 252u, 147u,
- 18u, 146u, 164u, 1u,
- 140u, 13u, 135u, 136u,
- 249u, 107u, 164u, 140u,
- 98u, 158u, 123u, 127u,
- 188u, 1u, 113u, 114u,
- 124u, 186u, 137u, 135u,
- 192u, 81u, 74u, 194u,
- 100u, 91u, 218u, 123u,
- 46u, 195u, 234u, 134u,
- 181u, 161u, 81u, 22u,
- 107u, 164u, 208u, 0u,
- 143u, 133u, 112u, 115u,
- 63u, 242u, 134u, 103u,
- 255u, 192u, 90u, 99u,
- 31u, 155u, 138u, 184u,
- 83u, 1u, 185u, 38u,
- 123u, 192u, 222u, 75u,
- 121u, 174u, 177u, 198u,
- 150u, 199u, 171u, 53u,
- 137u, 36u, 248u, 192u,
- 34u, 17u, 189u, 76u,
- 255u, 197u, 216u, 94u,
- 122u, 193u, 190u, 134u,
- 113u, 146u, 64u, 195u,
- 118u, 255u, 39u, 91u,
- 147u, 133u, 149u, 78u,
- 161u, 115u, 35u, 140u,
- 126u, 167u, 223u, 255u,
- 144u, 61u, 167u, 183u,
- 147u, 109u, 158u, 81u,
- 82u, 122u, 116u, 223u,
- 173u, 102u, 168u, 67u,
- 168u, 0u, 95u, 155u,
- 166u, 128u, 90u, 127u,
- 166u, 43u, 88u, 75u,
- 76u, 209u, 0u, 66u,
- 51u, 89u, 114u, 98u,
- 239u, 64u, 23u, 130u,
- 20u, 88u, 133u, 255u,
- 48u, 170u, 139u, 123u,
- 102u, 118u, 141u, 1u,
- 111u, 37u, 149u, 87u,
- 149u, 163u, 72u, 212u,
- 87u, 97u, 246u, 156u,
- 71u, 232u, 209u, 255u,
- 102u, 224u, 103u, 144u,
- 75u, 233u, 57u, 14u,
- 255u, 194u, 215u, 117u,
- 94u, 140u, 165u, 106u,
- 143u, 106u, 68u, 169u,
- 98u, 223u, 198u, 77u,
- 99u, 117u, 123u, 1u,
- 128u, 94u, 88u, 11u,
- 125u, 206u, 82u, 35u,
- 97u, 122u, 154u, 236u,
- 132u, 117u, 113u, 128u,
- 100u, 231u, 128u, 251u,
- 131u, 51u, 1u, 125u,
- 77u, 189u, 49u, 71u,
- 207u, 1u, 77u, 64u,
- 39u, 109u, 111u, 161u,
- 138u, 134u, 119u, 204u,
- 56u, 157u, 177u, 156u,
- 173u, 140u, 255u, 20u,
- 170u, 125u, 57u, 149u,
- 107u, 151u, 71u, 72u,
- 140u, 195u, 22u, 153u,
- 1u, 107u, 149u, 191u,
- 129u, 133u, 246u, 160u,
- 42u, 100u, 29u, 254u,
- 127u, 138u, 19u, 100u,
- 153u, 107u, 98u, 66u,
- 213u, 59u, 142u, 200u,
- 182u, 109u, 87u, 75u,
- 106u, 87u, 99u, 1u,
- 89u, 142u, 132u, 127u,
- 68u, 148u, 171u, 51u,
- 199u, 153u, 96u, 157u,
- 99u, 119u, 255u, 156u,
- 37u, 137u, 255u, 91u,
- 133u, 86u, 64u, 96u,
- 207u, 154u, 181u, 89u,
- 208u, 211u, 6u, 195u,
- 74u, 164u, 1u, 142u,
- 80u, 76u, 203u, 149u,
- 202u, 92u, 120u, 34u,
- 149u, 137u, 127u, 130u,
- 164u, 129u, 144u, 255u,
- 135u, 173u, 104u, 124u,
- 220u, 43u, 89u, 126u,
- 194u, 167u, 144u, 96u,
- 102u, 181u, 130u, 204u,
- 1u, 202u, 153u, 35u,
- 106u, 32u, 146u, 99u,
- 158u, 13u, 219u, 243u,
- 110u, 139u, 190u, 204u,
- 80u, 100u, 117u, 83u,
- 117u, 255u, 168u, 127u,
- 215u, 122u, 242u, 119u,
- 157u, 192u, 119u, 93u,
- 151u, 156u, 120u, 142u,
- 31u, 143u, 55u, 1u,
- 162u, 170u, 152u, 86u,
- 249u, 66u, 138u, 112u,
- 172u, 75u, 67u, 255u,
- 94u, 150u, 172u, 106u,
- 180u, 71u, 114u, 127u,
- 4u, 155u, 255u, 66u,
- 219u, 114u, 71u, 158u,
- 105u, 237u, 167u, 17u,
- 186u, 96u, 110u, 177u,
- 119u, 129u, 76u, 200u,
- 41u, 110u, 171u, 63u,
- 125u, 197u, 66u, 145u,
- 255u, 161u, 91u, 50u,
- 63u, 139u, 125u, 153u,
- 150u, 130u, 255u, 91u,
- 108u, 151u, 144u, 118u,
- 216u, 120u, 139u, 230u,
- 134u, 213u, 84u, 161u,
- 159u, 1u, 98u, 146u,
- 222u, 162u, 88u, 97u,
- 98u, 83u, 213u, 201u,
- 215u, 98u, 255u, 92u,
- 170u, 85u, 126u, 164u,
- 173u, 187u, 189u, 65u,
- 80u, 169u, 47u, 135u,
- 177u, 177u, 145u, 151u,
- 109u, 163u, 4u, 238u,
- 192u, 78u, 47u, 173u,
- 136u, 58u, 177u, 1u,
- 113u, 81u, 46u, 178u,
- 39u, 176u, 100u, 143u,
- 92u, 163u, 94u, 136u,
- 108u, 168u, 255u, 141u,
- 181u, 74u, 125u, 255u,
- 108u, 78u, 109u, 192u,
- 142u, 124u, 149u, 36u,
- 184u, 140u, 90u, 74u,
- 108u, 116u, 97u, 70u,
- 0u, 76u, 19u, 77u,
- 104u, 84u, 151u, 122u,
- 189u, 175u, 185u, 251u,
- 131u, 169u, 255u, 230u,
- 59u, 43u, 251u, 37u,
- 113u, 39u, 67u, 139u,
- 116u, 181u, 195u, 200u,
- 157u, 151u, 141u, 148u,
- 123u, 162u, 159u, 168u,
- 92u, 106u, 1u, 174u,
- 22u, 245u, 49u, 114u,
- 107u, 142u, 76u, 145u,
- 1u, 166u, 147u, 104u,
- 166u, 159u, 103u, 88u,
- 104u, 96u, 148u, 222u,
- 134u, 138u, 133u, 156u,
- 193u, 72u, 255u, 92u,
- 161u, 173u, 86u, 78u,
- 147u, 219u, 159u, 161u,
- 1u, 195u, 113u, 201u,
- 187u, 97u, 182u, 89u,
- 145u, 154u, 136u, 73u,
- 229u, 88u, 210u, 139u,
- 11u, 102u, 118u, 60u,
- 109u, 165u, 51u, 33u,
- 195u, 172u, 151u, 67u,
- 255u, 178u, 87u, 252u,
- 153u, 1u, 158u, 123u,
- 114u, 83u, 158u, 168u,
- 155u, 76u, 140u, 110u,
- 146u, 124u, 78u, 86u,
- 79u, 134u, 70u, 125u,
- 143u, 223u, 200u, 255u,
- 47u, 16u, 205u, 82u,
- 92u, 129u, 138u, 88u,
- 96u, 134u, 1u, 124u,
- 121u, 25u, 178u, 109u,
- 69u, 115u, 135u, 25u,
- 120u, 147u, 38u, 165u,
- 5u, 159u, 201u, 97u,
- 128u, 206u, 80u, 112u,
- 221u, 49u, 197u, 124u,
- 167u, 193u, 243u, 1u,
- 228u, 53u, 206u, 155u,
- 167u, 135u, 143u, 185u,
- 94u, 53u, 102u, 69u,
- 108u, 195u, 1u, 8u,
- 132u, 73u, 126u, 244u,
- 130u, 147u, 213u, 129u,
- 0u, 46u, 8u, 110u,
- 112u, 163u, 205u, 70u,
- 162u, 118u, 68u, 145u,
- 93u, 112u, 206u, 140u,
- 206u, 147u, 34u, 137u,
- 1u, 126u, 233u, 77u,
- 94u, 24u, 129u, 236u,
- 20u, 36u, 246u, 4u,
- 129u, 112u, 90u, 150u,
- 255u, 227u, 161u, 45u,
- 65u, 149u, 33u, 98u,
- 90u, 224u, 182u, 96u,
- 230u, 116u, 1u, 116u,
- 141u, 67u, 75u, 185u,
- 106u, 81u, 229u, 148u,
- 84u, 87u, 75u, 119u,
- 118u, 212u, 108u, 63u,
- 107u, 100u, 179u, 1u,
- 139u, 200u, 232u, 255u,
- 61u, 84u, 16u, 75u,
- 154u, 188u, 77u, 151u,
- 43u, 155u, 73u, 240u,
- 176u, 1u, 116u, 202u,
- 69u, 141u, 44u, 82u,
- 97u, 129u, 124u, 143u,
- 168u, 193u, 74u, 96u,
- 122u, 131u, 124u, 110u,
- 255u, 120u, 170u, 3u,
- 173u, 185u, 36u, 212u,
- 130u, 169u, 122u, 18u,
- 54u, 143u, 109u, 185u,
- 125u, 149u, 150u, 13u,
- 219u, 183u, 154u, 255u,
- 165u, 160u, 235u, 68u,
- 46u, 115u, 7u, 118u,
- 165u, 105u, 138u, 30u,
- 207u, 232u, 0u, 145u,
- 71u, 178u, 55u, 160u,
- 119u, 76u, 207u, 144u,
- 160u, 141u, 119u, 54u,
- 133u, 255u, 96u, 173u,
- 99u, 198u, 71u, 122u,
- 201u, 110u, 68u, 87u,
- 129u, 74u, 128u, 82u,
- 84u, 129u, 141u, 71u,
- 226u, 255u, 22u, 74u,
- 27u, 61u, 96u, 249u,
- 49u, 196u, 92u, 89u,
- 24u, 181u, 96u, 15u,
- 255u, 144u, 65u, 149u,
- 212u, 150u, 142u, 51u,
- 143u, 118u, 0u, 45u,
- 52u, 62u, 139u, 40u,
- 90u, 146u, 76u, 135u,
- 82u, 158u, 236u, 254u,
- 76u, 102u, 146u, 95u,
- 125u, 1u, 203u, 116u,
- 140u, 82u, 194u, 211u,
- 159u, 106u, 90u, 140u,
- 151u, 233u, 208u, 140u,
- 141u, 132u, 137u, 84u,
- 101u, 1u, 137u, 197u,
- 0u, 120u, 88u, 196u,
- 206u, 89u, 156u, 141u,
- 75u, 18u, 125u, 146u,
- 63u, 199u, 95u, 78u,
- 168u, 114u, 148u, 104u,
- 197u, 1u, 1u, 247u,
- 155u, 197u, 116u, 99u,
- 85u, 103u, 137u, 122u,
- 255u, 91u, 105u, 13u,
- 59u, 222u, 101u, 152u,
- 234u, 125u, 103u, 124u,
- 169u, 133u, 185u, 86u,
- 146u, 135u, 137u, 84u,
- 182u, 105u, 80u, 108u,
- 103u, 107u, 181u, 216u,
- 255u, 235u, 217u, 182u,
- 233u, 73u, 207u, 84u,
- 157u, 25u, 150u, 194u,
- 225u, 255u, 150u, 36u,
- 202u, 39u, 110u, 244u,
- 243u, 106u, 177u, 206u,
- 100u, 8u, 1u, 83u,
- 51u, 113u, 160u, 57u,
- 229u, 98u, 141u, 6u,
- 71u, 97u, 139u, 172u,
- 68u, 123u, 169u, 184u,
- 159u, 42u, 146u, 120u,
- 69u, 88u, 255u, 150u,
- 104u, 214u, 78u, 212u,
- 85u, 108u, 217u, 64u,
- 145u, 38u, 185u, 144u,
- 166u, 163u, 209u, 255u,
- 139u, 187u, 204u, 113u,
- 110u, 117u, 137u, 88u,
- 192u, 63u, 100u, 137u,
- 144u, 149u, 235u, 255u,
- 140u, 168u, 135u, 37u,
- 93u, 172u, 1u, 138u,
- 107u, 204u, 128u, 77u,
- 132u, 89u, 84u, 55u,
- 78u, 225u, 97u, 187u,
- 255u, 119u, 153u, 137u,
- 193u, 180u, 9u, 158u,
- 22u, 41u, 213u, 8u,
- 207u, 1u, 37u, 129u,
- 170u, 37u, 30u, 225u,
- 154u, 206u, 165u, 64u,
- 166u, 107u, 177u, 118u,
- 116u, 127u, 1u, 122u,
- 136u, 159u, 133u, 194u,
- 79u, 98u, 129u, 113u,
- 86u, 254u, 161u, 131u,
- 159u, 242u, 190u, 176u,
- 26u, 255u, 118u, 47u,
- 195u, 189u, 113u, 157u,
- 27u, 92u, 83u, 198u,
- 76u, 116u, 255u, 118u,
- 160u, 167u, 184u, 222u,
- 76u, 132u, 156u, 146u,
- 133u, 132u, 186u, 85u,
- 159u, 108u, 162u, 144u,
- 206u, 127u, 196u, 173u,
- 54u, 78u, 166u, 95u,
- 123u, 197u, 167u, 1u,
- 121u, 80u, 248u, 138u,
- 93u, 156u, 174u, 0u,
- 211u, 81u, 73u, 144u,
- 241u, 154u, 230u, 227u,
- 103u, 199u, 253u, 8u,
- 81u, 155u, 148u, 85u,
- 202u, 255u, 139u, 201u,
- 162u, 115u, 52u, 186u,
- 255u, 206u, 161u, 103u,
- 143u, 150u, 127u, 229u,
- 126u, 127u, 120u, 135u,
- 76u, 88u, 120u, 159u,
- 50u, 31u, 0u, 71u,
- 62u, 228u, 117u, 2u,
- 36u, 155u, 146u, 154u,
- 99u, 55u, 49u, 164u,
- 97u, 177u, 140u, 75u,
- 85u, 138u, 148u, 102u,
- 120u, 255u, 79u, 124u,
- 98u, 131u, 197u, 84u,
- 151u, 70u, 119u, 188u,
- 1u, 205u, 111u, 100u,
- 107u, 60u, 110u, 133u,
- 150u, 118u, 193u, 128u,
- 213u, 158u, 24u, 84u,
- 52u, 127u, 229u, 210u,
- 138u, 163u, 191u, 245u,
- 206u, 156u, 1u, 119u,
- 167u, 131u, 174u, 151u,
- 136u, 97u, 167u, 181u,
- 215u, 145u, 88u, 255u,
- 180u, 87u, 93u, 73u,
- 147u, 120u, 175u, 189u,
- 213u, 93u, 151u, 174u,
- 121u, 183u, 0u, 146u,
- 120u, 128u, 120u, 28u,
- 151u, 157u, 115u, 83u,
- 123u, 136u, 1u, 105u,
- 67u, 103u, 168u, 93u,
- 158u, 74u, 63u, 70u,
- 97u, 171u, 135u, 172u,
- 117u, 128u, 98u, 87u,
- 199u, 130u, 85u, 125u,
- 98u, 0u, 63u, 146u,
- 126u, 78u, 120u, 255u,
- 149u, 73u, 194u, 75u,
- 104u, 119u, 166u, 130u,
- 151u, 160u, 129u, 189u,
- 125u, 137u, 218u, 154u,
- 184u, 100u, 142u, 120u,
- 222u, 211u, 0u, 74u,
- 20u, 79u, 219u, 90u,
- 17u, 240u, 234u, 197u,
- 71u, 72u, 56u, 37u,
- 131u, 255u, 103u, 177u,
- 143u, 241u, 79u, 110u,
- 105u, 136u, 66u, 1u,
- 199u, 197u, 120u, 235u,
- 55u, 142u, 75u, 128u,
- 11u, 109u, 61u, 46u,
- 172u, 202u, 150u, 191u,
- 93u, 134u, 207u, 156u,
- 178u, 159u, 121u, 223u,
- 23u, 206u, 255u, 206u,
- 125u, 123u, 142u, 159u,
- 1u, 141u, 82u, 168u,
- 134u, 47u, 126u, 41u,
- 99u, 131u, 93u, 78u,
- 1u, 65u, 68u, 93u,
- 155u, 122u, 228u, 225u,
- 44u, 149u, 131u, 64u,
- 65u, 122u, 84u, 85u,
- 1u, 77u, 129u, 98u,
- 175u, 173u, 69u, 239u,
- 61u, 208u, 95u, 158u,
- 53u, 160u, 115u, 140u,
- 95u, 68u, 175u, 115u,
- 191u, 46u, 152u, 110u,
- 201u, 119u, 0u, 118u,
- 69u, 116u, 73u, 100u,
- 170u, 49u, 224u, 166u,
- 1u, 111u, 53u, 205u,
- 100u, 79u, 223u, 117u,
- 102u, 101u, 200u, 57u,
- 167u, 201u, 200u, 209u,
- 128u, 192u, 123u, 7u,
- 199u, 109u, 53u, 55u,
- 156u, 0u, 99u, 73u,
- 140u, 176u, 165u, 232u,
- 105u, 151u, 115u, 112u,
- 118u, 140u, 123u, 111u,
- 104u, 241u, 255u, 114u,
- 0u, 166u, 160u, 79u,
- 195u, 129u, 195u, 121u,
- 91u, 166u, 146u, 118u,
- 159u, 117u, 84u, 156u,
- 144u, 147u, 70u, 26u,
- 190u, 191u, 255u, 122u,
- 149u, 80u, 94u, 64u,
- 136u, 136u, 111u, 174u,
- 160u, 162u, 175u, 93u,
- 169u, 156u, 152u, 94u,
- 94u, 254u, 43u, 165u,
- 22u, 255u, 58u, 187u,
- 103u, 22u, 141u, 156u,
- 135u, 130u, 1u, 79u,
- 81u, 149u, 111u, 100u,
- 192u, 62u, 106u, 86u,
- 146u, 161u, 155u, 133u,
- 67u, 54u, 193u, 56u,
- 11u, 149u, 43u, 159u,
- 119u, 161u, 255u, 107u,
- 239u, 134u, 232u, 180u,
- 125u, 184u, 169u, 191u,
- 255u, 180u, 218u, 224u,
- 12u, 203u, 241u, 123u,
- 201u, 194u, 83u, 167u,
- 149u, 1u, 102u, 91u,
- 126u, 101u, 227u, 106u,
- 80u, 181u, 83u, 223u,
- 169u, 207u, 181u, 169u,
- 101u, 156u, 123u, 131u,
- 100u, 98u, 140u, 194u,
- 91u, 122u, 255u, 144u,
- 93u, 37u, 143u, 159u,
- 119u, 154u, 130u, 89u,
- 25u, 132u, 120u, 118u,
- 168u, 255u, 109u, 160u,
- 41u, 194u, 255u, 96u,
- 36u, 25u, 237u, 97u,
- 179u, 125u, 217u, 94u,
- 173u, 97u, 159u, 136u,
- 165u, 88u, 169u, 105u,
- 185u, 80u, 160u, 214u,
- 255u, 120u, 126u, 135u,
- 135u, 142u, 53u, 102u,
- 112u, 65u, 201u, 83u,
- 90u, 120u, 157u, 54u,
- 95u, 233u, 84u, 151u,
- 201u, 145u, 213u, 255u,
- 144u, 166u, 101u, 130u,
- 153u, 161u, 149u, 129u,
- 193u, 106u, 255u, 106u,
- 198u, 204u, 195u, 187u,
- 146u, 42u, 120u, 123u,
- 0u, 186u, 63u, 195u,
- 59u, 18u, 239u, 182u,
- 35u, 217u, 133u, 38u,
- 112u, 2u, 37u, 231u,
- 140u, 91u, 181u, 129u,
- 204u, 255u, 185u, 14u,
- 186u, 102u, 56u, 59u,
- 52u, 50u, 86u, 255u,
- 112u, 89u, 173u, 111u,
- 146u, 149u, 128u, 116u,
- 173u, 175u, 176u, 96u,
- 103u, 139u, 52u, 151u,
- 197u, 142u, 141u, 82u,
- 115u, 134u, 138u, 113u,
- 161u, 178u, 1u, 118u,
- 203u, 53u, 183u, 111u,
- 131u, 42u, 117u, 145u,
- 136u, 82u, 96u, 144u,
- 185u, 94u, 99u, 1u,
- 195u, 208u, 31u, 146u,
- 255u, 172u, 212u, 250u,
- 166u, 112u, 170u, 189u,
- 125u, 192u, 73u, 77u,
- 200u, 91u, 126u, 163u,
- 113u, 49u, 51u, 145u,
- 118u, 69u, 52u, 113u,
- 24u, 116u, 64u, 1u,
- 73u, 165u, 159u, 64u,
- 180u, 90u, 67u, 177u,
- 194u, 78u, 255u, 68u,
- 8u, 13u, 176u, 223u,
- 89u, 254u, 106u, 7u,
- 219u, 180u, 206u, 28u,
- 29u, 140u, 23u, 255u,
- 113u, 215u, 131u, 155u,
- 120u, 182u, 68u, 182u,
- 111u, 125u, 214u, 202u,
- 122u, 59u, 130u, 207u,
- 1u, 151u, 193u, 181u,
- 69u, 82u, 65u, 98u,
- 126u, 189u, 170u, 184u,
- 102u, 142u, 22u, 105u,
- 4u, 44u, 255u, 109u,
- 229u, 105u, 12u, 183u,
- 143u, 174u, 255u, 80u,
- 167u, 22u, 76u, 88u,
- 87u, 188u, 126u, 157u,
- 166u, 144u, 255u, 150u,
- 89u, 154u, 212u, 87u,
- 112u, 144u, 104u, 94u,
- 167u, 179u, 119u, 117u,
- 100u, 80u, 89u, 23u,
- 135u, 166u, 164u, 201u,
- 118u, 82u, 125u, 239u,
- 108u, 1u, 106u, 119u,
- 108u, 90u, 87u, 95u,
- 240u, 150u, 249u, 182u,
- 24u, 67u, 204u, 12u,
- 9u, 1u, 41u, 24u,
- 255u, 169u, 140u, 200u,
- 141u, 113u, 146u, 162u,
- 51u, 167u, 129u, 179u,
- 128u, 108u, 109u, 34u,
- 147u, 50u, 102u, 186u,
- 153u, 1u, 99u, 123u,
- 144u, 154u, 183u, 100u,
- 154u, 157u, 142u, 137u,
- 62u, 1u, 38u, 168u,
- 45u, 214u, 109u, 149u,
- 14u, 71u, 96u, 185u,
- 91u, 91u, 99u, 97u,
- 188u, 149u, 103u, 235u,
- 74u, 133u, 193u, 210u,
- 253u, 142u, 24u, 113u,
- 69u, 228u, 161u, 255u,
- 193u, 156u, 119u, 171u,
- 28u, 48u, 218u, 134u,
- 255u, 134u, 122u, 216u,
- 118u, 216u, 156u, 147u,
- 67u, 5u, 139u, 245u,
- 119u, 150u, 177u, 165u,
- 89u, 148u, 137u, 144u,
- 153u, 114u, 70u, 1u,
- 97u, 202u, 81u, 79u,
- 59u, 255u, 86u, 143u,
- 150u, 139u, 89u, 139u,
- 40u, 124u, 72u, 84u,
- 42u, 85u, 70u, 74u,
- 228u, 58u, 95u, 230u,
- 163u, 255u, 162u, 158u,
- 194u, 113u, 100u, 63u,
- 151u, 113u, 129u, 155u,
- 166u, 60u, 75u, 130u,
- 139u, 1u, 140u, 189u,
- 138u, 80u, 63u, 164u,
- 115u, 131u, 132u, 195u,
- 79u, 109u, 131u, 212u,
- 91u, 184u, 77u, 101u,
- 142u, 155u, 255u, 86u,
- 45u, 107u, 199u, 70u,
- 0u, 184u, 156u, 129u,
- 139u, 155u, 250u, 78u,
- 96u, 103u, 230u, 116u,
- 84u, 121u, 70u, 234u,
- 0u, 137u, 175u, 50u,
- 101u, 106u, 106u, 54u,
- 153u, 78u, 164u, 167u,
- 100u, 86u, 8u, 160u,
- 140u, 38u, 139u, 70u,
- 62u, 50u, 170u, 90u,
- 69u, 215u, 83u, 1u,
- 108u, 139u, 151u, 88u,
- 143u, 166u, 159u, 1u,
- 166u, 173u, 92u, 113u,
- 53u, 78u, 133u, 134u,
- 114u, 43u, 185u, 60u,
- 121u, 55u, 147u, 123u,
- 80u, 143u, 176u, 85u,
- 119u, 202u, 173u, 255u,
- 166u, 63u, 173u, 134u,
- 170u, 1u, 97u, 97u,
- 183u, 182u, 185u, 122u,
- 55u, 181u, 38u, 132u,
- 132u, 106u, 50u, 68u,
- 73u, 140u, 193u, 113u,
- 168u, 119u, 89u, 108u,
- 13u, 82u, 148u, 255u,
- 150u, 145u, 177u, 0u,
- 223u, 107u, 182u, 144u,
- 109u, 165u, 108u, 50u,
- 136u, 49u, 30u, 32u,
- 84u, 158u, 88u, 1u,
- 84u, 108u, 200u, 27u,
- 58u, 105u, 113u, 246u,
- 193u, 201u, 88u, 69u,
- 68u, 61u, 92u, 7u,
- 14u, 190u, 217u, 161u,
- 4u, 25u, 201u, 1u,
- 57u, 126u, 174u, 155u,
- 224u, 58u, 255u, 69u,
- 117u, 139u, 135u, 52u,
- 172u, 159u, 134u, 151u,
- 125u, 48u, 139u, 122u,
- 120u, 255u, 119u, 46u,
- 145u, 132u, 217u, 150u,
- 72u, 92u, 101u, 76u,
- 114u, 223u, 184u, 148u,
- 70u, 158u, 76u, 144u,
- 196u, 75u, 146u, 75u,
- 96u, 152u, 100u, 59u,
- 112u, 1u, 55u, 98u,
- 158u, 141u, 163u, 140u,
- 64u, 130u, 46u, 150u,
- 124u, 161u, 68u, 67u,
- 1u, 71u, 207u, 127u,
- 126u, 166u, 1u, 214u,
- 89u, 173u, 201u, 112u,
- 216u, 157u, 153u, 131u,
- 81u, 157u, 173u, 175u,
- 110u, 159u, 119u, 130u,
- 201u, 13u, 164u, 113u,
- 149u, 124u, 203u, 96u,
- 173u, 141u, 0u, 124u,
- 85u, 55u, 150u, 119u,
- 147u, 63u, 149u, 133u,
- 85u, 113u, 110u, 91u,
- 127u, 255u, 42u, 79u,
- 34u, 136u, 64u, 64u,
- 120u, 211u, 113u, 255u,
- 85u, 24u, 208u, 165u,
- 121u, 57u, 89u, 55u,
- 255u, 152u, 178u, 211u,
- 81u, 114u, 120u, 231u,
- 202u, 204u, 123u, 71u,
- 49u, 243u, 223u, 91u,
- 84u, 114u, 200u, 159u,
- 101u, 44u, 125u, 5u,
- 255u, 86u, 110u, 126u,
- 143u, 114u, 112u, 84u,
- 208u, 236u, 158u, 82u,
- 64u, 164u, 189u, 223u,
- 135u, 1u, 37u, 253u,
- 125u, 15u, 160u, 170u,
- 174u, 204u, 141u, 10u,
- 167u, 125u, 216u, 115u,
- 199u, 119u, 80u, 76u,
- 225u, 39u, 37u, 255u,
- 10u, 85u, 70u, 206u,
- 21u, 53u, 1u, 147u,
- 187u, 106u, 29u, 128u,
- 172u, 231u, 149u, 93u,
- 210u, 119u, 130u, 69u,
- 170u, 103u, 128u, 187u,
- 255u, 204u, 131u, 135u,
- 209u, 185u, 92u, 43u,
- 149u, 66u, 117u, 91u,
- 69u, 196u, 35u, 153u,
- 255u, 153u, 118u, 195u,
- 20u, 140u, 193u, 128u,
- 106u, 73u, 113u, 4u,
- 69u, 144u, 128u, 102u,
- 0u, 219u, 50u, 197u,
- 170u, 129u, 122u, 254u,
- 246u, 189u, 47u, 43u,
- 200u, 255u, 99u, 44u,
- 208u, 171u, 220u, 155u,
- 96u, 159u, 124u, 162u,
- 112u, 101u, 193u, 176u,
- 99u, 76u, 111u, 181u,
- 128u, 124u, 144u, 255u,
- 132u, 173u, 98u, 185u,
- 255u, 158u, 181u, 142u,
- 74u, 111u, 107u, 168u,
- 202u, 107u, 128u, 90u,
- 83u, 78u, 148u, 106u,
- 255u, 228u, 146u, 72u,
- 123u, 190u, 41u, 203u,
- 199u, 67u, 110u, 175u,
- 53u, 17u, 110u, 88u,
- 148u, 132u, 81u, 49u,
- 0u, 132u, 98u, 65u,
- 190u, 154u, 55u, 88u,
- 88u, 118u, 142u, 216u,
- 26u, 92u, 85u, 105u,
- 135u, 83u, 117u, 118u,
- 120u, 111u, 126u, 208u,
- 86u, 55u, 1u, 115u,
- 77u, 82u, 255u, 91u,
- 224u, 203u, 194u, 69u,
- 86u, 133u, 194u, 19u,
- 109u, 74u, 192u, 184u,
- 126u, 143u, 159u, 148u,
- 177u, 255u, 138u, 102u,
- 95u, 31u, 76u, 76u,
- 86u, 168u, 95u, 42u,
- 199u, 171u, 171u, 198u,
- 0u, 107u, 102u, 2u,
- 239u, 103u, 235u, 83u,
- 125u, 42u, 93u, 132u,
- 175u, 134u, 173u, 56u,
- 173u, 146u, 96u, 80u,
- 181u, 234u, 233u, 34u,
- 111u, 187u, 0u, 96u,
- 188u, 29u, 32u, 45u,
- 53u, 53u, 32u, 205u,
- 107u, 255u, 88u, 17u,
- 121u, 136u, 35u, 64u,
- 120u, 145u, 166u, 193u,
- 18u, 102u, 255u, 132u,
- 85u, 142u, 205u, 113u,
- 211u, 94u, 232u, 182u,
- 180u, 67u, 163u, 140u,
- 124u, 86u, 131u, 177u,
- 67u, 193u, 205u, 115u,
- 217u, 1u, 92u, 171u,
- 1u, 146u, 89u, 217u,
- 49u, 226u, 120u, 129u,
- 115u, 106u, 126u, 66u,
- 87u, 125u, 144u, 42u,
- 181u, 76u, 163u, 32u,
- 164u, 224u, 152u, 118u,
- 43u, 255u, 116u, 116u,
- 46u, 60u, 170u, 37u,
- 204u, 169u, 44u, 68u,
- 184u, 167u, 255u, 97u,
- 159u, 70u, 86u, 190u,
- 94u, 35u, 53u, 69u,
- 130u, 119u, 197u, 175u,
- 0u, 136u, 105u, 113u,
- 116u, 73u, 106u, 128u,
- 45u, 200u, 82u, 40u,
- 255u, 199u, 89u, 112u,
- 138u, 140u, 68u, 161u,
- 196u, 93u, 138u, 117u,
- 54u, 62u, 126u, 183u,
- 46u, 252u, 155u, 97u,
- 229u, 198u, 209u, 8u,
- 255u, 146u, 45u, 191u,
- 219u, 108u, 38u, 185u,
- 0u, 190u, 186u, 165u,
- 113u, 119u, 196u, 11u,
- 188u, 213u, 161u, 65u,
- 90u, 103u, 71u, 137u,
- 98u, 106u, 191u, 118u,
- 60u, 228u, 92u, 26u,
- 174u, 67u, 32u, 213u,
- 1u, 224u, 151u, 33u,
- 184u, 117u, 64u, 0u,
- 102u, 14u, 158u, 168u,
- 183u, 136u, 92u, 15u,
- 227u, 197u, 54u, 205u,
- 125u, 108u, 151u, 166u,
- 102u, 103u, 175u, 77u,
- 105u, 189u, 144u, 127u,
- 255u, 83u, 150u, 124u,
- 42u, 233u, 152u, 7u,
- 154u, 91u, 249u, 174u,
- 190u, 167u, 165u, 171u,
- 255u, 104u, 122u, 213u,
- 143u, 175u, 178u, 107u,
- 24u, 150u, 159u, 7u,
- 177u, 167u, 75u, 150u,
- 144u, 97u, 241u, 1u,
- 154u, 105u, 223u, 86u,
- 93u, 98u, 17u, 1u,
- 16u, 127u, 166u, 73u,
- 183u, 56u, 73u, 64u,
- 157u, 166u, 163u, 68u,
- 158u, 150u, 121u, 66u,
- 218u, 148u, 248u, 183u,
- 176u, 1u, 98u, 214u,
- 179u, 87u, 181u, 214u,
- 129u, 193u, 62u, 139u,
- 122u, 56u, 97u, 118u,
- 4u, 68u, 255u, 87u,
- 62u, 134u, 37u, 255u,
- 60u, 87u, 29u, 8u,
- 118u, 129u, 22u, 199u,
- 55u, 242u, 193u, 212u,
- 170u, 217u, 92u, 102u,
- 213u, 188u, 130u, 86u,
- 135u, 19u, 34u, 90u,
- 40u, 255u, 154u, 28u,
- 151u, 156u, 145u, 113u,
- 135u, 35u, 99u, 242u,
- 40u, 23u, 126u, 95u,
- 136u, 171u, 1u, 145u,
- 100u, 116u, 142u, 37u,
- 221u, 137u, 104u, 58u,
- 88u, 189u, 122u, 68u,
- 1u, 134u, 208u, 71u,
- 1u, 132u, 28u, 79u,
- 103u, 144u, 75u, 127u,
- 51u, 226u, 108u, 92u,
- 92u, 80u, 72u, 185u,
- 98u, 136u, 255u, 211u,
- 141u, 129u, 170u, 141u,
- 119u, 106u, 170u, 183u,
- 60u, 177u, 166u, 131u,
- 255u, 160u, 210u, 128u,
- 132u, 154u, 175u, 158u,
- 114u, 80u, 173u, 43u,
- 26u, 121u, 111u, 157u,
- 107u, 134u, 187u, 66u,
- 98u, 124u, 75u, 129u,
- 52u, 152u, 219u, 143u,
- 132u, 17u, 141u, 1u,
- 227u, 97u, 212u, 238u,
- 40u, 113u, 127u, 155u,
- 253u, 183u, 92u, 1u,
- 134u, 75u, 180u, 139u,
- 190u, 222u, 117u, 85u,
- 172u, 255u, 224u, 130u,
- 100u, 94u, 158u, 157u,
- 77u, 75u, 16u, 156u,
- 229u, 139u, 175u, 255u,
- 99u, 120u, 106u, 225u,
- 69u, 3u, 150u, 201u,
- 207u, 122u, 135u, 84u,
- 125u, 153u, 153u, 206u,
- 84u, 37u, 63u, 119u,
- 107u, 157u, 170u, 255u,
- 73u, 238u, 224u, 146u,
- 213u, 31u, 133u, 71u,
- 131u, 146u, 101u, 153u,
- 142u, 89u, 147u, 123u,
- 8u, 255u, 152u, 41u,
- 175u, 106u, 33u, 225u,
- 82u, 161u, 124u, 255u,
- 4u, 111u, 168u, 132u,
- 42u, 141u, 84u, 176u,
- 150u, 141u, 93u, 8u,
- 167u, 130u, 33u, 255u,
- 16u, 29u, 117u, 45u,
- 69u, 183u, 123u, 255u,
- 96u, 69u, 239u, 255u,
- 78u, 94u, 161u, 7u,
- 144u, 62u, 155u, 228u,
- 178u, 221u, 43u, 55u,
- 145u, 141u, 159u, 89u,
- 51u, 255u, 198u, 87u,
- 114u, 120u, 129u, 187u,
- 163u, 209u, 126u, 202u,
- 73u, 127u, 101u, 199u,
- 190u, 125u, 152u, 203u,
- 218u, 162u, 93u, 181u,
- 103u, 145u, 1u, 56u,
- 222u, 196u, 211u, 197u,
- 111u, 1u, 144u, 109u,
- 105u, 35u, 72u, 162u,
- 14u, 130u, 175u, 157u,
- 112u, 175u, 83u, 222u,
- 161u, 85u, 255u, 166u,
- 179u, 109u, 112u, 151u,
- 97u, 74u, 96u, 133u,
- 67u, 70u, 91u, 161u,
- 172u, 46u, 141u, 255u,
- 91u, 206u, 77u, 93u,
- 149u, 123u, 245u, 73u,
- 121u, 245u, 215u, 166u,
- 73u, 30u, 255u, 54u,
- 225u, 189u, 12u, 178u,
- 228u, 158u, 146u, 103u,
- 33u, 166u, 1u, 122u,
- 191u, 203u, 233u, 151u,
- 182u, 172u, 113u, 103u,
- 145u, 195u, 22u, 147u,
- 192u, 50u, 96u, 116u,
- 162u, 134u, 113u, 255u,
- 89u, 135u, 28u, 227u,
- 62u, 105u, 144u, 127u,
- 255u, 98u, 147u, 135u,
- 137u, 76u, 191u, 192u,
- 144u, 135u, 147u, 94u,
- 50u, 117u, 186u, 174u,
- 255u, 188u, 177u, 158u,
- 40u, 39u, 100u, 163u,
- 200u, 17u, 94u, 95u,
- 212u, 172u, 169u, 117u,
- 130u, 147u, 1u, 172u,
- 114u, 102u, 195u, 144u,
- 29u, 135u, 215u, 43u,
- 86u, 105u, 85u, 152u,
- 255u, 132u, 91u, 73u,
- 159u, 192u, 138u, 127u,
- 202u, 99u, 28u, 108u,
- 13u, 62u, 87u, 116u,
- 205u, 199u, 183u, 158u,
- 97u, 216u, 145u, 153u,
- 255u, 167u, 137u, 235u,
- 52u, 74u, 204u, 130u,
- 203u, 85u, 200u, 178u,
- 226u, 96u, 142u, 255u,
- 25u, 57u, 114u, 100u,
- 15u, 194u, 76u, 4u,
- 112u, 177u, 68u, 160u,
- 166u, 111u, 45u, 165u,
- 67u, 0u, 189u, 39u,
- 115u, 128u, 129u, 181u,
- 110u, 90u, 142u, 113u,
- 97u, 109u, 131u, 93u,
- 149u, 73u, 98u, 226u,
- 90u, 72u, 132u, 255u,
- 139u, 70u, 69u, 204u,
- 1u, 85u, 153u, 92u,
- 141u, 17u, 35u, 214u,
- 153u, 139u, 123u, 69u,
- 222u, 89u, 141u, 111u,
- 7u, 145u, 1u, 78u,
- 116u, 61u, 162u, 95u,
- 133u, 80u, 160u, 75u,
- 189u, 105u, 161u, 0u,
- 125u, 92u, 77u, 101u,
- 175u, 145u, 94u, 52u,
- 66u, 79u, 150u, 170u,
- 125u, 45u, 77u, 152u,
- 98u, 203u, 16u, 98u,
- 83u, 152u, 121u, 195u,
- 1u, 133u, 116u, 190u,
- 51u, 175u, 102u, 130u,
- 102u, 165u, 79u, 0u,
- 217u, 77u, 65u, 195u,
- 94u, 191u, 19u, 63u,
- 130u, 235u, 1u, 58u,
- 76u, 196u, 118u, 249u,
- 115u, 17u, 167u, 207u,
- 77u, 49u, 49u, 170u,
- 210u, 153u, 124u, 160u,
- 69u, 134u, 42u, 163u,
- 255u, 159u, 122u, 79u,
- 126u, 79u, 191u, 95u,
- 216u, 175u, 184u, 1u,
- 45u, 199u, 191u, 13u,
- 105u, 113u, 162u, 98u,
- 185u, 114u, 192u, 93u,
- 0u, 240u, 85u, 133u,
- 102u, 143u, 80u, 130u,
- 165u, 193u, 105u, 165u,
- 198u, 211u, 82u, 171u,
- 85u, 108u, 67u, 237u,
- 118u, 169u, 113u, 119u,
- 119u, 116u, 119u, 64u,
- 179u, 134u, 255u, 90u,
- 176u, 156u, 103u, 147u,
- 53u, 185u, 121u, 169u,
- 187u, 175u, 126u, 1u,
- 165u, 212u, 223u, 165u,
- 67u, 107u, 129u, 106u,
- 195u, 170u, 174u, 101u,
- 114u, 140u, 127u, 130u,
- 204u, 116u, 1u, 205u,
- 197u, 69u, 178u, 117u,
- 81u, 220u, 74u, 164u,
- 130u, 151u, 102u, 153u,
- 120u, 120u, 255u, 130u,
- 95u, 21u, 160u, 48u,
- 93u, 1u, 113u, 178u,
- 51u, 168u, 163u, 175u,
- 75u, 231u, 55u, 155u,
- 127u, 1u, 225u, 118u,
- 135u, 202u, 242u, 93u,
- 47u, 194u, 253u, 39u,
- 98u, 134u, 206u, 43u,
- 158u, 105u, 81u, 54u,
- 200u, 149u, 91u, 192u,
- 1u, 174u, 175u, 142u,
- 142u, 145u, 52u, 174u,
- 47u, 168u, 128u, 35u,
- 137u, 150u, 192u, 94u,
- 230u, 249u, 85u, 182u,
- 152u, 200u, 71u, 255u,
- 168u, 154u, 114u, 97u,
- 173u, 109u, 132u, 155u,
- 148u, 190u, 109u, 123u,
- 98u, 255u, 201u, 86u,
- 84u, 128u, 68u, 74u,
- 1u, 255u, 168u, 108u,
- 89u, 83u, 78u, 96u,
- 104u, 99u, 252u, 2u,
- 31u, 11u, 66u, 223u,
- 101u, 255u, 138u, 149u,
- 50u, 131u, 78u, 70u,
- 13u, 214u, 55u, 215u,
- 207u, 255u, 175u, 114u,
- 123u, 105u, 82u, 93u,
- 102u, 141u, 172u, 107u,
- 163u, 180u, 149u, 37u,
- 135u, 181u, 167u, 163u,
- 60u, 129u, 130u, 142u,
- 1u, 157u, 157u, 133u,
- 120u, 200u, 58u, 17u,
- 67u, 250u, 122u, 148u,
- 80u, 28u, 115u, 143u,
- 1u, 86u, 82u, 178u,
- 76u, 120u, 115u, 40u,
- 76u, 152u, 106u, 235u,
- 166u, 179u, 115u, 1u,
- 171u, 168u, 144u, 33u,
- 207u, 140u, 150u, 193u,
- 95u, 181u, 154u, 174u,
- 71u, 170u, 37u, 53u,
- 236u, 170u, 171u, 118u,
- 128u, 235u, 132u, 255u,
- 108u, 126u, 40u, 238u,
- 220u, 173u, 182u, 255u,
- 208u, 154u, 200u, 90u,
- 9u, 179u, 189u, 156u,
- 7u, 176u, 95u, 66u,
- 74u, 231u, 65u, 188u,
- 41u, 109u, 193u, 97u,
- 177u, 1u, 128u, 72u,
- 100u, 106u, 112u, 162u,
- 146u, 106u, 193u, 179u,
- 240u, 200u, 0u, 97u,
- 167u, 162u, 50u, 70u,
- 85u, 185u, 95u, 67u,
- 174u, 168u, 117u, 58u,
- 178u, 70u, 101u, 196u,
- 106u, 255u, 5u, 241u,
- 120u, 1u, 84u, 162u,
- 115u, 133u, 141u, 179u,
- 59u, 109u, 131u, 114u,
- 142u, 231u, 71u, 113u,
- 94u, 101u, 150u, 183u,
- 233u, 90u, 154u, 131u,
- 173u, 144u, 1u, 94u,
- 100u, 84u, 100u, 45u,
- 84u, 145u, 73u, 141u,
- 77u, 101u, 128u, 61u,
- 255u, 110u, 128u, 46u,
- 130u, 207u, 95u, 119u,
- 184u, 145u, 255u, 220u,
- 167u, 107u, 78u, 175u,
- 101u, 120u, 127u, 171u,
- 209u, 111u, 88u, 127u,
- 232u, 146u, 109u, 1u,
- 185u, 229u, 176u, 238u,
- 46u, 199u, 58u, 88u,
- 117u, 88u, 74u, 2u,
- 163u, 177u, 217u, 74u,
- 102u, 242u, 136u, 58u,
- 161u, 189u, 255u, 16u,
- 78u, 81u, 118u, 190u,
- 184u, 255u, 94u, 174u,
- 187u, 139u, 33u, 178u,
- 10u, 192u, 109u, 148u,
- 101u, 118u, 102u, 28u,
- 106u, 99u, 177u, 1u,
- 130u, 116u, 152u, 173u,
- 104u, 125u, 86u, 8u,
- 196u, 174u, 253u, 47u,
- 177u, 82u, 241u, 111u,
- 112u, 79u, 44u, 129u,
- 1u, 151u, 122u, 178u,
- 103u, 136u, 16u, 25u,
- 255u, 117u, 148u, 118u,
- 225u, 118u, 64u, 185u,
- 98u, 215u, 138u, 131u,
- 124u, 100u, 141u, 100u,
- 138u, 158u, 228u, 162u,
- 91u, 144u, 16u, 171u,
- 1u, 103u, 153u, 161u,
- 72u, 137u, 203u, 105u,
- 94u, 146u, 224u, 126u,
- 251u, 90u, 92u, 162u,
- 126u, 170u, 111u, 173u,
- 162u, 200u, 38u, 1u,
- 84u, 178u, 179u, 87u,
- 161u, 155u, 177u, 96u,
- 138u, 145u, 88u, 185u,
- 0u, 206u, 104u, 88u,
- 212u, 12u, 70u, 96u,
- 75u, 159u, 255u, 181u,
- 85u, 143u, 174u, 91u,
- 148u, 209u, 103u, 228u,
- 81u, 1u, 216u, 183u,
- 143u, 46u, 86u, 119u,
- 182u, 84u, 120u, 155u,
- 99u, 206u, 128u, 137u,
- 199u, 44u, 104u, 28u,
- 100u, 54u, 44u, 255u,
- 83u, 151u, 31u, 213u,
- 8u, 219u, 179u, 116u,
- 112u, 93u, 169u, 246u,
- 141u, 255u, 202u, 129u,
- 141u, 173u, 49u, 127u,
- 94u, 253u, 15u, 57u,
- 23u, 170u, 91u, 48u,
- 1u, 139u, 131u, 98u,
- 60u, 106u, 62u, 115u,
- 130u, 122u, 24u, 222u,
- 115u, 129u, 85u, 183u,
- 156u, 103u, 0u, 236u,
- 87u, 195u, 75u, 150u,
- 113u, 120u, 156u, 69u,
- 65u, 52u, 201u, 132u,
- 1u, 102u, 69u, 218u,
- 130u, 95u, 143u, 209u,
- 165u, 136u, 146u, 66u,
- 221u, 186u, 127u, 255u,
- 246u, 68u, 132u, 229u,
- 75u, 138u, 123u, 191u,
- 62u, 236u, 232u, 149u,
- 56u, 133u, 61u, 95u,
- 15u, 205u, 153u, 88u,
- 111u, 104u, 110u, 117u,
- 1u, 130u, 56u, 248u,
- 122u, 159u, 255u, 215u,
- 79u, 125u, 141u, 114u,
- 87u, 108u, 150u, 65u,
- 177u, 142u, 155u, 174u,
- 117u, 80u, 126u, 75u,
- 137u, 123u, 1u, 236u,
- 51u, 203u, 254u, 166u,
- 227u, 150u, 91u, 157u,
- 165u, 137u, 1u, 89u,
- 166u, 170u, 47u, 60u,
- 108u, 223u, 38u, 25u,
- 96u, 171u, 48u, 82u,
- 208u, 111u, 169u, 79u,
- 9u, 10u, 95u, 119u,
- 255u, 99u, 95u, 143u,
- 46u, 148u, 203u, 137u,
- 127u, 143u, 142u, 120u,
- 132u, 126u, 77u, 171u,
- 81u, 73u, 1u, 124u,
- 145u, 76u, 228u, 129u,
- 248u, 137u, 244u, 166u,
- 26u, 216u, 101u, 149u,
- 230u, 60u, 119u, 139u,
- 213u, 138u, 188u, 1u,
- 55u, 171u, 114u, 44u,
- 37u, 146u, 93u, 83u,
- 79u, 61u, 141u, 255u,
- 101u, 29u, 153u, 67u,
- 179u, 209u, 68u, 97u,
- 120u, 0u, 41u, 143u,
- 160u, 191u, 148u, 77u,
- 152u, 198u, 155u, 90u,
- 127u, 32u, 1u, 225u,
- 164u, 167u, 230u, 120u,
- 119u, 155u, 19u, 15u,
- 97u, 151u, 226u, 55u,
- 201u, 26u, 130u, 129u,
- 251u, 1u, 202u, 235u,
- 33u, 87u, 152u, 156u,
- 198u, 133u, 77u, 81u,
- 71u, 134u, 42u, 242u,
- 171u, 176u, 38u, 93u,
- 162u, 51u, 74u, 63u,
- 121u, 0u, 34u, 241u,
- 48u, 108u, 154u, 0u,
- 152u, 185u, 104u, 140u,
- 180u, 159u, 169u, 205u,
- 116u, 157u, 109u, 179u,
- 160u, 124u, 129u, 158u,
- 92u, 123u, 107u, 66u,
- 128u, 100u, 223u, 193u,
- 1u, 105u, 215u, 131u,
- 120u, 209u, 101u, 142u,
- 75u, 219u, 167u, 75u,
- 92u, 112u, 15u, 76u,
- 1u, 17u, 140u, 243u,
- 167u, 13u, 65u, 87u,
- 91u, 190u, 209u, 189u,
- 211u, 164u, 108u, 0u,
- 132u, 68u, 184u, 214u,
- 184u, 115u, 128u, 105u,
- 184u, 122u, 129u, 0u,
- 124u, 233u, 35u, 114u,
- 175u, 229u, 119u, 72u,
- 146u, 46u, 178u, 153u,
- 164u, 135u, 77u, 69u,
- 112u, 72u, 59u, 255u,
- 138u, 148u, 89u, 140u,
- 36u, 210u, 107u, 60u,
- 0u, 147u, 4u, 89u,
- 176u, 193u, 35u, 116u,
- 188u, 27u, 38u, 165u,
- 170u, 132u, 181u, 130u,
- 48u, 69u, 107u, 113u,
- 144u, 156u, 108u, 1u,
- 54u, 176u, 138u, 94u,
- 122u, 0u, 121u, 145u,
- 62u, 181u, 172u, 173u,
- 116u, 162u, 100u, 62u,
- 184u, 165u, 154u, 21u,
- 255u, 91u, 139u, 171u,
- 178u, 33u, 42u, 135u,
- 119u, 139u, 111u, 115u,
- 112u, 72u, 217u, 100u,
- 64u, 46u, 95u, 0u,
- 214u, 203u, 195u, 209u,
- 107u, 175u, 28u, 46u,
- 153u, 196u, 33u, 165u,
- 112u, 255u, 178u, 200u,
- 169u, 151u, 127u, 55u,
- 44u, 2u, 163u, 127u,
- 126u, 141u, 128u, 182u,
- 250u, 166u, 142u, 57u,
- 102u, 0u, 127u, 148u,
- 104u, 66u, 102u, 64u,
- 181u, 177u, 156u, 179u,
- 130u, 120u, 173u, 125u,
- 110u, 156u, 187u, 109u,
- 204u, 170u, 117u, 65u,
- 43u, 185u, 201u, 1u,
- 176u, 239u, 161u, 130u,
- 232u, 1u, 159u, 186u,
- 167u, 137u, 197u, 95u,
- 233u, 163u, 109u, 129u,
- 255u, 30u, 198u, 107u,
- 60u, 61u, 57u, 103u,
- 153u, 142u, 168u, 47u,
- 148u, 47u, 233u, 59u,
- 162u, 239u, 212u, 130u,
- 115u, 105u, 19u, 198u,
- 107u, 14u, 172u, 255u,
- 109u, 118u, 204u, 134u,
- 46u, 72u, 149u, 140u,
- 107u, 170u, 39u, 46u,
- 110u, 186u, 107u, 67u,
- 100u, 255u, 67u, 79u,
- 249u, 26u, 149u, 77u,
- 108u, 157u, 1u, 11u,
- 61u, 32u, 126u, 198u,
- 107u, 97u, 236u, 132u,
- 92u, 151u, 44u, 130u,
- 151u, 1u, 128u, 100u,
- 175u, 112u, 111u, 132u,
- 174u, 156u, 140u, 225u,
- 157u, 255u, 128u, 123u,
- 136u, 130u, 171u, 138u,
- 170u, 58u, 78u, 102u,
- 122u, 130u, 62u, 179u,
- 23u, 41u, 202u, 39u,
- 82u, 99u, 175u, 19u,
- 176u, 227u, 109u, 40u,
- 177u, 1u, 86u, 51u,
- 59u, 80u, 135u, 227u,
- 135u, 135u, 83u, 139u,
- 255u, 169u, 112u, 128u,
- 84u, 186u, 118u, 188u,
- 39u, 39u, 70u, 161u,
- 64u, 185u, 71u, 214u,
- 91u, 121u, 228u, 81u,
- 61u, 255u, 235u, 139u,
- 173u, 149u, 20u, 191u,
- 184u, 153u, 158u, 178u,
- 211u, 255u, 107u, 226u,
- 115u, 94u, 174u, 30u,
- 106u, 114u, 52u, 155u,
- 89u, 116u, 142u, 202u,
- 4u, 1u, 244u, 112u,
- 115u, 79u, 10u, 131u,
- 255u, 207u, 136u, 56u,
- 162u, 94u, 162u, 194u,
- 184u, 76u, 68u, 115u,
- 20u, 198u, 134u, 165u,
- 155u, 210u, 50u, 200u,
- 74u, 122u, 232u, 255u,
- 251u, 121u, 173u, 75u,
- 93u, 159u, 128u, 128u,
- 14u, 210u, 123u, 97u,
- 255u, 136u, 149u, 82u,
- 159u, 148u, 199u, 196u,
- 188u, 37u, 36u, 182u,
- 242u, 32u, 134u, 156u,
- 31u, 240u, 81u, 76u,
- 96u, 40u, 246u, 69u,
- 238u, 118u, 63u, 0u,
- 151u, 183u, 65u, 225u,
- 100u, 156u, 90u, 65u,
- 69u, 47u, 97u, 155u,
- 134u, 135u, 1u, 99u,
- 83u, 168u, 74u, 138u,
- 96u, 199u, 133u, 151u,
- 105u, 83u, 162u, 148u,
- 212u, 44u, 150u, 255u,
- 107u, 166u, 193u, 140u,
- 194u, 255u, 162u, 81u,
- 179u, 184u, 49u, 138u,
- 110u, 161u, 114u, 98u,
- 243u, 69u, 130u, 111u,
- 193u, 172u, 186u, 255u,
- 107u, 56u, 61u, 88u,
- 130u, 106u, 235u, 71u,
- 80u, 120u, 115u, 227u,
- 178u, 243u, 27u, 255u,
- 222u, 151u, 95u, 147u,
- 160u, 77u, 88u, 162u,
- 1u, 185u, 98u, 136u,
- 55u, 153u, 205u, 67u,
- 102u, 119u, 147u, 111u,
- 222u, 45u, 64u, 162u,
- 104u, 14u, 32u, 194u,
- 140u, 131u, 209u, 0u,
- 248u, 192u, 189u, 131u,
- 142u, 68u, 201u, 44u,
- 91u, 18u, 51u, 90u,
- 142u, 104u, 236u, 50u,
- 151u, 205u, 149u, 94u,
- 178u, 195u, 242u, 1u,
- 85u, 184u, 95u, 138u,
- 64u, 156u, 78u, 114u,
- 130u, 134u, 114u, 132u,
- 83u, 70u, 119u, 255u,
- 68u, 156u, 122u, 144u,
- 149u, 216u, 94u, 1u,
- 105u, 248u, 137u, 93u,
- 61u, 81u, 48u, 103u,
- 132u, 121u, 61u, 224u,
- 69u, 13u, 200u, 219u,
- 151u, 162u, 255u, 180u,
- 171u, 51u, 193u, 153u,
- 159u, 56u, 181u, 67u,
- 47u, 38u, 67u, 221u,
- 32u, 185u, 217u, 100u,
- 103u, 235u, 125u, 255u,
- 90u, 122u, 180u, 82u,
- 216u, 245u, 255u, 19u,
- 179u, 163u, 87u, 97u,
- 72u, 167u, 141u, 191u,
- 13u, 78u, 150u, 122u,
- 147u, 23u, 0u, 196u,
- 87u, 192u, 183u, 132u,
- 115u, 58u, 19u, 88u,
- 158u, 152u, 130u, 41u,
- 169u, 185u, 58u, 136u,
- 148u, 177u, 78u, 101u,
- 140u, 195u, 255u, 70u,
- 69u, 255u, 153u, 164u,
- 220u, 128u, 87u, 166u,
- 175u, 79u, 201u, 210u,
- 176u, 108u, 79u, 142u,
- 115u, 52u, 118u, 76u,
- 112u, 160u, 230u, 172u,
- 119u, 43u, 104u, 141u,
- 1u, 35u, 157u, 167u,
- 188u, 89u, 253u, 199u,
- 117u, 0u, 164u, 201u,
- 199u, 6u, 95u, 154u,
- 104u, 119u, 124u, 136u,
- 165u, 119u, 170u, 117u,
- 117u, 118u, 143u, 170u,
- 183u, 92u, 187u, 125u,
- 25u, 0u, 157u, 71u,
- 152u, 160u, 1u, 221u,
- 198u, 76u, 159u, 139u,
- 28u, 236u, 219u, 191u,
- 115u, 59u, 95u, 157u,
- 112u, 203u, 255u, 192u,
- 147u, 167u, 92u, 103u,
- 137u, 105u, 166u, 64u,
- 49u, 94u, 177u, 250u,
- 150u, 107u, 153u, 138u,
- 110u, 83u, 255u, 182u,
- 136u, 139u, 111u, 127u,
- 118u, 64u, 155u, 74u,
- 85u, 138u, 133u, 255u,
- 138u, 201u, 244u, 119u,
- 106u, 0u, 81u, 205u,
- 188u, 155u, 49u, 161u,
- 174u, 144u, 205u, 196u,
- 168u, 130u, 123u, 92u,
- 102u, 170u, 122u, 1u,
- 121u, 149u, 68u, 107u,
- 0u, 237u, 249u, 149u,
- 187u, 49u, 203u, 27u,
- 225u, 122u, 118u, 50u,
- 216u, 128u, 71u, 92u,
- 146u, 171u, 154u, 205u,
- 153u, 238u, 111u, 183u,
- 44u, 255u, 142u, 163u,
- 214u, 242u, 180u, 1u,
- 100u, 156u, 5u, 55u,
- 248u, 212u, 114u, 188u,
- 99u, 1u, 37u, 21u,
- 116u, 149u, 69u, 206u,
- 118u, 71u, 139u, 1u,
- 109u, 205u, 165u, 181u,
- 191u, 91u, 79u, 204u,
- 42u, 123u, 156u, 134u,
- 98u, 124u, 56u, 56u,
- 144u, 131u, 193u, 240u,
- 153u, 127u, 128u, 114u,
- 103u, 75u, 156u, 255u,
- 111u, 142u, 160u, 186u,
- 124u, 121u, 12u, 31u,
- 166u, 19u, 102u, 157u,
- 169u, 100u, 143u, 255u,
- 75u, 130u, 137u, 191u,
- 88u, 187u, 112u, 94u,
- 143u, 142u, 166u, 126u,
- 155u, 178u, 1u, 110u,
- 131u, 110u, 159u, 255u,
- 217u, 205u, 55u, 87u,
- 222u, 138u, 248u, 221u,
- 49u, 178u, 196u, 205u,
- 218u, 174u, 218u, 62u,
- 142u, 85u, 85u, 99u,
- 77u, 104u, 196u, 128u,
- 205u, 66u, 255u, 142u,
- 99u, 124u, 145u, 93u,
- 113u, 71u, 235u, 115u,
- 119u, 152u, 98u, 255u,
- 117u, 118u, 177u, 155u,
- 72u, 171u, 124u, 167u,
- 151u, 73u, 233u, 154u,
- 106u, 167u, 213u, 130u,
- 173u, 67u, 1u, 236u,
- 51u, 40u, 138u, 11u,
- 59u, 72u, 193u, 82u,
- 194u, 182u, 181u, 109u,
- 97u, 117u, 1u, 123u,
- 119u, 85u, 112u, 158u,
- 202u, 255u, 214u, 192u,
- 140u, 133u, 123u, 125u,
- 92u, 88u, 125u, 153u,
- 208u, 140u, 248u, 12u,
- 200u, 15u, 252u, 198u,
- 255u, 114u, 112u, 11u,
- 95u, 21u, 197u, 140u,
- 156u, 255u, 144u, 25u,
- 145u, 242u, 74u, 104u,
- 88u, 28u, 173u, 134u,
- 115u, 67u, 130u, 125u,
- 57u, 139u, 100u, 119u,
- 134u, 161u, 46u, 142u,
- 119u, 151u, 139u, 158u,
- 121u, 183u, 1u, 113u,
- 176u, 177u, 152u, 163u,
- 102u, 161u, 141u, 246u,
- 135u, 1u, 194u, 205u,
- 62u, 189u, 141u, 130u,
- 154u, 143u, 1u, 92u,
- 172u, 230u, 167u, 179u,
- 35u, 183u, 144u, 211u,
- 185u, 127u, 32u, 188u,
- 163u, 30u, 248u, 97u,
- 166u, 98u, 172u, 127u,
- 177u, 190u, 255u, 123u,
- 237u, 153u, 135u, 126u,
- 114u, 167u, 87u, 40u,
- 136u, 148u, 170u, 255u,
- 107u, 225u, 84u, 117u,
- 86u, 152u, 251u, 67u,
- 64u, 41u, 90u, 1u,
- 146u, 162u, 255u, 170u,
- 26u, 44u, 92u, 50u,
- 189u, 94u, 21u, 175u,
- 212u, 59u, 212u, 69u,
- 86u, 125u, 1u, 147u,
- 134u, 145u, 60u, 178u,
- 124u, 201u, 134u, 46u,
- 86u, 115u, 120u, 61u,
- 237u, 212u, 155u, 240u,
- 51u, 64u, 182u, 123u,
- 178u, 1u, 14u, 95u,
- 229u, 227u, 208u, 17u,
- 255u, 57u, 87u, 138u,
- 61u, 120u, 119u, 176u,
- 85u, 110u, 120u, 116u,
- 137u, 152u, 148u, 81u,
- 240u, 147u, 126u, 255u,
- 124u, 144u, 116u, 151u,
- 13u, 7u, 127u, 57u,
- 202u, 190u, 154u, 1u,
- 121u, 67u, 55u, 127u,
- 126u, 186u, 87u, 173u,
- 187u, 81u, 21u, 85u,
- 55u, 82u, 189u, 29u,
- 225u, 255u, 124u, 75u,
- 54u, 126u, 60u, 125u,
- 102u, 78u, 100u, 131u,
- 238u, 180u, 145u, 111u,
- 108u, 138u, 1u, 171u,
- 110u, 172u, 47u, 57u,
- 128u, 172u, 97u, 77u,
- 102u, 154u, 138u, 174u,
- 106u, 159u, 34u, 37u,
- 198u, 199u, 190u, 104u,
- 176u, 90u, 78u, 0u,
- 133u, 56u, 205u, 251u,
- 77u, 93u, 118u, 108u,
- 32u, 86u, 255u, 55u,
- 135u, 163u, 183u, 176u,
- 193u, 183u, 48u, 178u,
- 32u, 1u, 191u, 5u,
- 204u, 113u, 76u, 139u,
- 161u, 192u, 182u, 57u,
- 122u, 103u, 112u, 136u,
- 121u, 39u, 151u, 18u,
- 108u, 191u, 110u, 139u,
- 240u, 195u, 1u, 140u,
- 216u, 204u, 156u, 138u,
- 255u, 95u, 157u, 201u,
- 117u, 131u, 125u, 169u,
- 77u, 162u, 75u, 62u,
- 140u, 163u, 143u, 131u,
- 1u, 112u, 91u, 60u,
- 53u, 81u, 83u, 123u,
- 117u, 161u, 99u, 74u,
- 54u, 199u, 151u, 134u,
- 221u, 220u, 118u, 141u,
- 255u, 153u, 167u, 210u,
- 187u, 90u, 179u, 35u,
- 83u, 166u, 101u, 221u,
- 69u, 100u, 180u, 139u,
- 106u, 26u, 220u, 108u,
- 137u, 88u, 95u, 255u,
- 134u, 88u, 32u, 141u,
- 59u, 112u, 115u, 43u,
- 161u, 232u, 64u, 78u,
- 8u, 255u, 89u, 250u,
- 155u, 176u, 115u, 192u,
- 186u, 144u, 198u, 171u,
- 54u, 255u, 170u, 153u,
- 173u, 171u, 156u, 13u,
- 31u, 170u, 109u, 168u,
- 125u, 140u, 175u, 84u,
- 110u, 74u, 1u, 83u,
- 174u, 161u, 146u, 120u,
- 142u, 90u, 124u, 133u,
- 132u, 52u, 114u, 165u,
- 110u, 167u, 141u, 134u,
- 149u, 255u, 95u, 130u,
- 0u, 176u, 66u, 210u,
- 48u, 159u, 171u, 25u,
- 146u, 119u, 144u, 137u,
- 107u, 141u, 163u, 156u,
- 193u, 159u, 72u, 174u,
- 211u, 30u, 135u, 89u,
- 174u, 162u, 56u, 81u,
- 152u, 138u, 51u, 1u,
- 159u, 255u, 57u, 42u,
- 125u, 161u, 90u, 54u,
- 153u, 163u, 124u, 124u,
- 47u, 41u, 167u, 144u,
- 148u, 87u, 244u, 1u,
- 196u, 210u, 122u, 14u,
- 212u, 137u, 49u, 103u,
- 206u, 156u, 65u, 38u,
- 156u, 62u, 255u, 97u,
- 67u, 88u, 180u, 17u,
- 161u, 253u, 58u, 139u,
- 204u, 78u, 164u, 93u,
- 190u, 255u, 206u, 182u,
- 5u, 106u, 155u, 255u,
- 189u, 37u, 115u, 106u,
- 40u, 177u, 127u, 44u,
- 167u, 145u, 143u, 119u,
- 108u, 160u, 164u, 118u,
- 219u, 140u, 140u, 90u,
- 84u, 53u, 1u, 155u,
- 154u, 208u, 138u, 149u,
- 136u, 71u, 229u, 162u,
- 255u, 110u, 92u, 126u,
- 205u, 101u, 229u, 199u,
- 243u, 191u, 62u, 125u,
- 241u, 115u, 35u, 88u,
- 115u, 178u, 168u, 0u,
- 237u, 84u, 192u, 165u,
- 55u, 226u, 231u, 174u,
- 159u, 120u, 255u, 66u,
- 108u, 83u, 91u, 218u,
- 236u, 107u, 150u, 117u,
- 109u, 104u, 101u, 101u,
- 73u, 185u, 207u, 141u,
- 156u, 114u, 120u, 1u,
- 126u, 61u, 172u, 53u,
- 60u, 255u, 245u, 254u,
- 162u, 108u, 89u, 48u,
- 108u, 123u, 204u, 182u,
- 212u, 72u, 59u, 226u,
- 213u, 39u, 213u, 103u,
- 29u, 71u, 219u, 107u,
- 157u, 86u, 188u, 130u,
- 255u, 110u, 110u, 224u,
- 102u, 210u, 63u, 170u,
- 209u, 166u, 105u, 6u,
- 132u, 231u, 83u, 163u,
- 211u, 244u, 255u, 157u,
- 147u, 97u, 54u, 140u,
- 85u, 174u, 164u, 63u,
- 155u, 162u, 119u, 98u,
- 83u, 31u, 1u, 108u,
- 89u, 255u, 97u, 161u,
- 91u, 133u, 125u, 175u,
- 89u, 78u, 35u, 160u,
- 91u, 31u, 91u, 146u,
- 143u, 101u, 255u, 198u,
- 64u, 100u, 59u, 76u,
- 66u, 184u, 151u, 150u,
- 128u, 151u, 182u, 143u,
- 65u, 67u, 173u, 1u,
- 210u, 116u, 105u, 137u,
- 210u, 59u, 90u, 191u,
- 101u, 142u, 167u, 91u,
- 140u, 217u, 171u, 146u,
- 72u, 136u, 153u, 104u,
- 199u, 137u, 141u, 99u,
- 1u, 164u, 142u, 196u,
- 135u, 144u, 188u, 127u,
- 146u, 254u, 184u, 234u,
- 183u, 142u, 173u, 69u,
- 149u, 255u, 214u, 139u,
- 59u, 105u, 211u, 84u,
- 56u, 68u, 208u, 49u,
- 134u, 139u, 137u, 76u,
- 47u, 100u, 75u, 255u,
- 208u, 214u, 161u, 160u,
- 30u, 103u, 154u, 107u,
- 255u, 58u, 130u, 60u,
- 128u, 59u, 210u, 165u,
- 184u, 96u, 203u, 174u,
- 189u, 165u, 255u, 157u,
- 30u, 108u, 167u, 163u,
- 80u, 217u, 180u, 73u,
- 173u, 0u, 106u, 229u,
- 43u, 132u, 154u, 180u,
- 79u, 191u, 110u, 74u,
- 102u, 157u, 58u, 129u,
- 203u, 129u, 63u, 236u,
- 115u, 1u, 85u, 70u,
- 161u, 104u, 176u, 91u,
- 117u, 124u, 70u, 237u,
- 4u, 79u, 102u, 170u,
- 191u, 156u, 141u, 99u,
- 215u, 229u, 1u, 158u,
- 199u, 103u, 31u, 100u,
- 0u, 159u, 72u, 188u,
- 77u, 167u, 102u, 137u,
- 100u, 249u, 227u, 113u,
- 81u, 213u, 130u, 112u,
- 105u, 248u, 77u, 62u,
- 39u, 201u, 91u, 150u,
- 165u, 129u, 140u, 228u,
- 122u, 156u, 0u, 239u,
- 237u, 122u, 213u, 46u,
- 42u, 128u, 1u, 17u,
- 45u, 120u, 202u, 66u,
- 136u, 123u, 96u, 109u,
- 129u, 210u, 173u, 1u,
- 112u, 163u, 168u, 122u,
- 93u, 94u, 151u, 56u,
- 52u, 111u, 255u, 209u,
- 166u, 153u, 108u, 1u,
- 125u, 119u, 202u, 146u,
- 158u, 111u, 76u, 36u,
- 44u, 62u, 85u, 195u,
- 105u, 152u, 120u, 176u,
- 126u, 85u, 147u, 1u,
- 75u, 110u, 160u, 170u,
- 180u, 132u, 172u, 97u,
- 197u, 105u, 95u, 152u,
- 124u, 68u, 127u, 227u,
- 135u, 1u, 99u, 62u,
- 90u, 151u, 101u, 80u,
- 125u, 114u, 149u, 107u,
- 92u, 170u, 233u, 150u,
- 255u, 143u, 85u, 112u,
- 100u, 154u, 170u, 215u,
- 122u, 1u, 180u, 179u,
- 101u, 75u, 49u, 162u,
- 63u, 96u, 56u, 102u,
- 154u, 107u, 211u, 56u,
- 255u, 154u, 100u, 178u,
- 52u, 147u, 201u, 116u,
- 222u, 148u, 126u, 31u,
- 48u, 112u, 213u, 130u,
- 83u, 134u, 134u, 62u,
- 10u, 193u, 62u, 1u,
- 151u, 75u, 76u, 130u,
- 109u, 42u, 222u, 113u,
- 213u, 96u, 137u, 212u,
- 64u, 19u, 146u, 49u,
- 255u, 81u, 193u, 126u,
- 236u, 154u, 180u, 172u,
- 131u, 61u, 86u, 153u,
- 165u, 81u, 114u, 109u,
- 139u, 168u, 73u, 42u,
- 255u, 85u, 173u, 86u,
- 91u, 131u, 133u, 255u,
- 76u, 177u, 106u, 210u,
- 128u, 204u, 135u, 180u,
- 29u, 225u, 151u, 176u,
- 106u, 75u, 210u, 143u,
- 142u, 144u, 142u, 56u,
- 135u, 180u, 71u, 161u,
- 140u, 255u, 101u, 69u,
- 13u, 113u, 196u, 128u,
- 225u, 22u, 139u, 64u,
- 182u, 127u, 20u, 169u,
- 63u, 211u, 0u, 118u,
- 104u, 158u, 114u, 129u,
- 158u, 87u, 175u, 77u,
- 182u, 255u, 79u, 150u,
- 197u, 137u, 85u, 143u,
- 122u, 4u, 59u, 157u,
- 108u, 85u, 34u, 222u,
- 95u, 142u, 185u, 88u,
- 151u, 0u, 82u, 197u,
- 117u, 157u, 247u, 189u,
- 151u, 58u, 100u, 166u,
- 208u, 173u, 130u, 100u,
- 255u, 103u, 138u, 35u,
- 168u, 176u, 68u, 15u,
- 209u, 98u, 133u, 113u,
- 227u, 196u, 252u, 172u,
- 121u, 1u, 52u, 188u,
- 85u, 227u, 172u, 1u,
- 106u, 224u, 195u, 14u,
- 58u, 165u, 173u, 24u,
- 149u, 122u, 96u, 105u,
- 139u, 149u, 191u, 85u,
- 54u, 81u, 145u, 165u,
- 76u, 166u, 129u, 255u,
- 61u, 186u, 60u, 105u,
- 255u, 32u, 58u, 46u,
- 218u, 5u, 87u, 222u,
- 46u, 165u, 214u, 45u,
- 226u, 42u, 235u, 223u,
- 184u, 222u, 158u, 110u,
- 71u, 156u, 55u, 98u,
- 156u, 196u, 92u, 171u,
- 73u, 144u, 255u, 88u,
- 103u, 35u, 154u, 234u,
- 177u, 78u, 1u, 33u,
- 67u, 231u, 149u, 54u,
- 132u, 128u, 141u, 226u,
- 99u, 184u, 139u, 79u,
- 142u, 168u, 147u, 82u,
- 120u, 121u, 111u, 202u,
- 1u, 176u, 106u, 128u,
- 231u, 138u, 157u, 162u,
- 27u, 210u, 181u, 50u,
- 116u, 128u, 113u, 21u,
- 96u, 165u, 255u, 88u,
- 127u, 85u, 173u, 56u,
- 120u, 115u, 145u, 116u,
- 141u, 109u, 96u, 137u,
- 99u, 88u, 1u, 201u,
- 136u, 57u, 103u, 109u,
- 133u, 164u, 104u, 173u,
- 127u, 178u, 152u, 100u,
- 1u, 101u, 133u, 115u,
- 81u, 151u, 109u, 152u,
- 186u, 128u, 153u, 79u,
- 175u, 255u, 91u, 141u,
- 143u, 136u, 76u, 128u,
- 157u, 41u, 163u, 12u,
- 126u, 83u, 102u, 122u,
- 45u, 163u, 127u, 143u,
- 57u, 255u, 142u, 87u,
- 192u, 132u, 255u, 138u,
- 93u, 143u, 71u, 79u,
- 84u, 58u, 182u, 86u,
- 48u, 200u, 176u, 147u,
- 111u, 221u, 173u, 43u,
- 97u, 234u, 75u, 255u,
- 185u, 112u, 11u, 114u,
- 53u, 109u, 193u, 105u,
- 194u, 176u, 81u, 189u,
- 103u, 65u, 82u, 222u,
- 140u, 199u, 146u, 192u,
- 131u, 123u, 255u, 50u,
- 86u, 25u, 168u, 134u,
- 234u, 60u, 62u, 56u,
- 169u, 173u, 79u, 112u,
- 45u, 172u, 1u, 131u,
- 80u, 15u, 201u, 93u,
- 145u, 143u, 151u, 169u,
- 74u, 36u, 190u, 58u,
- 205u, 97u, 1u, 90u,
- 140u, 131u, 128u, 106u,
- 114u, 170u, 17u, 69u,
- 133u, 159u, 151u, 117u,
- 78u, 170u, 25u, 255u,
- 163u, 161u, 146u, 85u,
- 130u, 100u, 181u, 0u,
- 50u, 134u, 120u, 130u,
- 205u, 159u, 41u, 27u,
- 51u, 134u, 201u, 139u,
- 96u, 79u, 105u, 71u,
- 151u, 177u, 156u, 139u,
- 157u, 187u, 1u, 181u,
- 159u, 179u, 159u, 120u,
- 178u, 160u, 115u, 82u,
- 131u, 130u, 104u, 0u,
- 114u, 105u, 41u, 76u,
- 125u, 162u, 135u, 105u,
- 194u, 140u, 139u, 121u,
- 213u, 161u, 151u, 0u,
- 24u, 120u, 229u, 241u,
- 160u, 95u, 255u, 76u,
- 114u, 38u, 70u, 9u,
- 14u, 217u, 140u, 52u,
- 235u, 136u, 89u, 89u,
- 255u, 82u, 150u, 158u,
- 47u, 91u, 124u, 106u,
- 173u, 173u, 50u, 185u,
- 88u, 221u, 199u, 36u,
- 150u, 115u, 52u, 112u,
- 216u, 159u, 235u, 139u,
- 101u, 217u, 198u, 255u,
- 91u, 157u, 129u, 167u,
- 16u, 107u, 64u, 171u,
- 47u, 226u, 124u, 1u,
- 171u, 87u, 163u, 125u,
- 218u, 126u, 87u, 214u,
- 109u, 136u, 102u, 11u,
- 28u, 194u, 103u, 99u,
- 146u, 210u, 128u, 255u,
- 36u, 212u, 174u, 45u,
- 107u, 193u, 129u, 53u,
- 15u, 190u, 104u, 108u,
- 246u, 161u, 93u, 215u,
- 1u, 117u, 116u, 159u,
- 204u, 97u, 237u, 162u,
- 147u, 168u, 139u, 1u,
- 108u, 170u, 126u, 160u,
- 119u, 176u, 10u, 90u,
- 128u, 86u, 175u, 95u,
- 19u, 112u, 58u, 51u,
- 146u, 155u, 104u, 134u,
- 129u, 255u, 163u, 105u,
- 21u, 199u, 85u, 149u,
- 107u, 168u, 1u, 163u,
- 46u, 62u, 148u, 153u,
- 210u, 92u, 154u, 77u,
- 184u, 111u, 118u, 226u,
- 139u, 30u, 113u, 145u,
- 255u, 153u, 198u, 95u,
- 154u, 94u, 46u, 201u,
- 193u, 136u, 228u, 111u,
- 85u, 52u, 1u, 156u,
- 181u, 58u, 76u, 184u,
- 180u, 75u, 231u, 1u,
- 115u, 221u, 1u, 91u,
- 131u, 79u, 155u, 38u,
- 141u, 187u, 193u, 74u,
- 85u, 155u, 103u, 169u,
- 162u, 59u, 68u, 153u,
- 171u, 77u, 223u, 207u,
- 201u, 81u, 122u, 28u,
- 255u, 171u, 61u, 66u,
- 6u, 82u, 28u, 121u,
- 38u, 169u, 242u, 108u,
- 145u, 221u, 180u, 126u,
- 18u, 97u, 75u, 255u,
- 169u, 104u, 143u, 138u,
- 170u, 198u, 135u, 148u,
- 157u, 110u, 193u, 220u,
- 121u, 127u, 255u, 147u,
- 35u, 200u, 200u, 122u,
- 204u, 147u, 232u, 96u,
- 143u, 137u, 149u, 214u,
- 68u, 151u, 1u, 181u,
- 118u, 135u, 101u, 1u,
- 126u, 96u, 103u, 123u,
- 158u, 141u, 106u, 130u,
- 97u, 200u, 130u, 255u,
- 221u, 19u, 133u, 107u,
- 255u, 18u, 77u, 187u,
- 97u, 171u, 96u, 225u,
- 63u, 153u, 175u, 214u,
- 161u, 104u, 86u, 255u,
- 179u, 160u, 97u, 126u,
- 74u, 122u, 118u, 100u,
- 150u, 220u, 39u, 140u,
- 252u, 144u, 188u, 106u,
- 71u, 64u, 27u, 98u,
- 74u, 141u, 180u, 26u,
- 211u, 255u, 136u, 164u,
- 69u, 175u, 121u, 1u,
- 189u, 134u, 91u, 40u,
- 160u, 109u, 137u, 246u,
- 54u, 61u, 234u, 229u,
- 95u, 122u, 1u, 40u,
- 132u, 143u, 192u, 119u,
- 155u, 150u, 89u, 60u,
- 91u, 112u, 101u, 209u,
- 135u, 244u, 127u, 65u,
- 98u, 185u, 56u, 204u,
- 90u, 87u, 122u, 97u,
- 68u, 53u, 255u, 57u,
- 158u, 255u, 177u, 196u,
- 198u, 168u, 213u, 109u,
- 215u, 89u, 83u, 133u,
- 123u, 189u, 54u, 112u,
- 255u, 167u, 208u, 99u,
- 49u, 95u, 65u, 116u,
- 104u, 167u, 111u, 136u,
- 179u, 184u, 193u, 47u,
- 66u, 109u, 68u, 158u,
- 220u, 63u, 115u, 144u,
- 150u, 188u, 169u, 144u,
- 254u, 161u, 0u, 111u,
- 107u, 86u, 175u, 119u,
- 83u, 164u, 74u, 97u,
- 131u, 142u, 151u, 107u,
- 255u, 141u, 106u, 142u,
- 88u, 169u, 108u, 135u,
- 50u, 144u, 14u, 1u,
- 44u, 64u, 44u, 39u,
- 211u, 103u, 250u, 118u,
- 0u, 96u, 127u, 157u,
- 59u, 107u, 110u, 77u,
- 156u, 11u, 106u, 194u,
- 30u, 60u, 220u, 169u,
- 222u, 57u, 255u, 147u,
- 78u, 66u, 220u, 207u,
- 119u, 110u, 212u, 102u,
- 137u, 148u, 95u, 76u,
- 142u, 152u, 112u, 236u,
- 255u, 105u, 228u, 98u,
- 86u, 26u, 140u, 215u,
- 73u, 152u, 235u, 168u,
- 46u, 129u, 167u, 95u,
- 36u, 55u, 180u, 85u,
- 163u, 255u, 135u, 155u,
- 210u, 214u, 166u, 125u,
- 136u, 165u, 44u, 98u,
- 180u, 64u, 162u, 95u,
- 142u, 255u, 102u, 71u,
- 115u, 138u, 84u, 120u,
- 230u, 109u, 159u, 98u,
- 143u, 1u, 42u, 134u,
- 84u, 95u, 149u, 191u,
- 178u, 120u, 158u, 81u,
- 17u, 193u, 32u, 255u,
- 124u, 124u, 199u, 52u,
- 120u, 49u, 179u, 57u,
- 189u, 72u, 78u, 165u,
- 150u, 68u, 40u, 255u,
- 171u, 1u, 55u, 34u,
- 224u, 218u, 159u, 187u,
- 243u, 145u, 24u, 226u,
- 255u, 219u, 87u, 5u,
- 81u, 86u, 209u, 162u,
- 181u, 69u, 135u, 127u,
- 211u, 25u, 251u, 187u,
- 189u, 218u, 94u, 1u,
- 88u, 56u, 118u, 12u,
- 144u, 66u, 111u, 99u,
- 122u, 113u, 54u, 202u,
- 21u, 31u, 73u, 69u,
- 88u, 139u, 109u, 187u,
- 76u, 68u, 106u, 207u,
- 35u, 255u, 139u, 109u,
- 79u, 101u, 105u, 88u,
- 171u, 162u, 143u, 68u,
- 118u, 138u, 188u, 47u,
- 172u, 94u, 1u, 243u,
- 250u, 211u, 0u, 219u,
- 170u, 3u, 35u, 158u,
- 119u, 91u, 124u, 106u,
- 246u, 82u, 112u, 207u,
- 180u, 105u, 152u, 95u,
- 67u, 151u, 175u, 102u,
- 163u, 106u, 176u, 125u,
- 38u, 0u, 156u, 108u,
- 158u, 170u, 132u, 184u,
- 133u, 192u, 103u, 118u,
- 24u, 107u, 123u, 1u,
- 137u, 168u, 179u, 209u,
- 153u, 164u, 16u, 112u,
- 197u, 69u, 169u, 96u,
- 67u, 213u, 227u, 142u,
- 164u, 131u, 83u, 255u,
- 128u, 148u, 137u, 144u,
- 194u, 194u, 209u, 49u,
- 88u, 136u, 0u, 138u,
- 106u, 193u, 97u, 174u,
- 107u, 169u, 172u, 107u,
- 194u, 49u, 255u, 37u,
- 135u, 56u, 207u, 32u,
- 111u, 181u, 126u, 93u,
- 75u, 222u, 70u, 189u,
- 64u, 151u, 164u, 129u,
- 161u, 104u, 119u, 104u,
- 12u, 179u, 69u, 255u,
- 170u, 173u, 255u, 210u,
- 169u, 88u, 99u, 54u,
- 52u, 42u, 108u, 98u,
- 113u, 99u, 79u, 142u,
- 138u, 255u, 239u, 87u,
- 109u, 153u, 122u, 116u,
- 185u, 170u, 88u, 216u,
- 129u, 124u, 57u, 245u,
- 147u, 255u, 193u, 133u,
- 234u, 38u, 130u, 96u,
- 60u, 150u, 90u, 213u,
- 84u, 46u, 87u, 96u,
- 113u, 105u, 94u, 220u,
- 173u, 75u, 129u, 80u,
- 196u, 192u, 63u, 82u,
- 96u, 193u, 1u, 215u,
- 148u, 140u, 187u, 137u,
- 89u, 151u, 37u, 1u,
- 152u, 81u, 98u, 46u,
- 191u, 145u, 13u, 65u,
- 43u, 186u, 1u, 134u,
- 155u, 72u, 185u, 123u,
- 133u, 166u, 115u, 50u,
- 176u, 28u, 173u, 163u,
- 114u, 1u, 175u, 132u,
- 132u, 85u, 168u, 215u,
- 210u, 182u, 190u, 108u,
- 144u, 161u, 166u, 99u,
- 238u, 207u, 144u, 15u,
- 247u, 219u, 255u, 119u,
- 78u, 119u, 115u, 235u,
- 69u, 192u, 184u, 102u,
- 83u, 61u, 54u, 100u,
- 160u, 1u, 65u, 141u,
- 159u, 188u, 163u, 52u,
- 21u, 51u, 38u, 130u,
- 21u, 95u, 110u, 138u,
- 144u, 71u, 158u, 255u,
- 132u, 82u, 173u, 40u,
- 234u, 156u, 234u, 140u,
- 106u, 114u, 249u, 52u,
- 146u, 159u, 77u, 88u,
- 34u, 172u, 148u, 149u,
- 255u, 136u, 137u, 35u,
- 183u, 61u, 198u, 101u,
- 163u, 255u, 155u, 76u,
- 252u, 212u, 152u, 157u,
- 105u, 185u, 85u, 64u,
- 1u, 96u, 181u, 132u,
- 123u, 44u, 139u, 215u,
- 137u, 123u, 174u, 185u,
- 152u, 144u, 88u, 160u,
- 47u, 202u, 115u, 235u,
- 154u, 101u, 158u, 57u,
- 34u, 221u, 134u, 135u,
- 221u, 0u, 196u, 112u,
- 127u, 52u, 69u, 143u,
- 144u, 111u, 120u, 151u,
- 58u, 133u, 51u, 93u,
- 255u, 186u, 168u, 68u,
- 117u, 85u, 155u, 115u,
- 150u, 98u, 51u, 178u,
- 18u, 87u, 121u, 105u,
- 100u, 190u, 1u, 158u,
- 188u, 156u, 44u, 0u,
- 217u, 96u, 232u, 80u,
- 78u, 127u, 83u, 53u,
- 98u, 104u, 108u, 73u,
- 140u, 42u, 140u, 114u,
- 58u, 138u, 149u, 123u,
- 1u, 83u, 107u, 171u,
- 128u, 148u, 68u, 126u,
- 67u, 55u, 194u, 186u,
- 130u, 106u, 218u, 66u,
- 170u, 151u, 255u, 119u,
- 175u, 206u, 147u, 146u,
- 123u, 145u, 1u, 145u,
- 118u, 86u, 119u, 198u,
- 118u, 70u, 38u, 115u,
- 62u, 145u, 111u, 170u,
- 73u, 59u, 142u, 146u,
- 106u, 241u, 44u, 33u,
- 196u, 95u, 122u, 120u,
- 170u, 44u, 0u, 98u,
- 126u, 104u, 129u, 108u,
- 113u, 165u, 136u, 101u,
- 72u, 117u, 105u, 148u,
- 108u, 27u, 0u, 97u,
- 255u, 111u, 175u, 95u,
- 140u, 63u, 23u, 78u,
- 95u, 184u, 133u, 76u,
- 172u, 149u, 110u, 113u,
- 39u, 88u, 156u, 200u,
- 37u, 18u, 132u, 89u,
- 130u, 69u, 246u, 13u,
- 51u, 1u, 158u, 246u,
- 46u, 107u, 101u, 142u,
- 151u, 153u, 106u, 73u,
- 167u, 177u, 48u, 82u,
- 17u, 117u, 1u, 126u,
- 247u, 124u, 54u, 177u,
- 192u, 153u, 164u, 255u,
- 132u, 105u, 139u, 86u,
- 173u, 108u, 204u, 109u,
- 84u, 67u, 122u, 166u,
- 97u, 160u, 199u, 120u,
- 71u, 156u, 86u, 255u,
- 129u, 250u, 85u, 121u,
- 165u, 203u, 210u, 142u,
- 151u, 31u, 114u, 172u,
- 194u, 148u, 193u, 84u,
- 109u, 0u, 115u, 178u,
- 66u, 255u, 113u, 101u,
- 179u, 103u, 176u, 99u,
- 133u, 188u, 126u, 89u,
- 116u, 58u, 54u, 159u,
- 100u, 141u, 156u, 118u,
- 89u, 153u, 68u, 32u,
- 176u, 152u, 1u, 160u,
- 146u, 121u, 175u, 102u,
- 117u, 236u, 223u, 14u,
- 90u, 49u, 3u, 40u,
- 41u, 113u, 52u, 172u,
- 134u, 0u, 163u, 80u,
- 129u, 127u, 255u, 197u,
- 74u, 32u, 167u, 75u,
- 137u, 71u, 94u, 113u,
- 43u, 241u, 172u, 37u,
- 69u, 148u, 108u, 90u,
- 117u, 129u, 138u, 121u,
- 97u, 99u, 170u, 152u,
- 110u, 122u, 58u, 255u,
- 127u, 149u, 138u, 161u,
- 88u, 152u, 207u, 109u,
- 172u, 168u, 126u, 109u,
- 149u, 255u, 142u, 158u,
- 244u, 125u, 92u, 142u,
- 95u, 255u, 108u, 42u,
- 138u, 175u, 77u, 77u,
- 138u, 164u, 139u, 52u,
- 124u, 255u, 236u, 217u,
- 18u, 89u, 179u, 71u,
- 134u, 187u, 188u, 235u,
- 137u, 35u, 196u, 15u,
- 169u, 50u, 189u, 29u,
- 14u, 97u, 45u, 124u,
- 255u, 156u, 123u, 119u,
- 148u, 7u, 229u, 91u,
- 87u, 1u, 89u, 185u,
- 99u, 187u, 122u, 168u,
- 160u, 118u, 214u, 113u,
- 136u, 183u, 101u, 93u,
- 40u, 255u, 71u, 248u,
- 197u, 105u, 122u, 25u,
- 143u, 194u, 103u, 38u,
- 178u, 156u, 177u, 238u,
- 154u, 187u, 154u, 95u,
- 217u, 64u, 255u, 102u,
- 130u, 64u, 85u, 53u,
- 102u, 96u, 105u, 186u,
- 155u, 169u, 118u, 156u,
- 11u, 120u, 124u, 59u,
- 200u, 121u, 139u, 158u,
- 137u, 139u, 255u, 173u,
- 154u, 103u, 165u, 40u,
- 193u, 111u, 143u, 158u,
- 71u, 162u, 13u, 174u,
- 133u, 247u, 1u, 138u,
- 96u, 154u, 86u, 198u,
- 77u, 222u, 1u, 122u,
- 80u, 170u, 206u, 165u,
- 167u, 157u, 151u, 109u,
- 157u, 104u, 82u, 170u,
- 163u, 99u, 123u, 120u,
- 183u, 161u, 135u, 141u,
- 1u, 187u, 73u, 99u,
- 75u, 233u, 48u, 161u,
- 101u, 13u, 135u, 51u,
- 255u, 37u, 237u, 162u,
- 92u, 43u, 95u, 231u,
- 184u, 145u, 39u, 205u,
- 113u, 100u, 15u, 75u,
- 129u, 115u, 162u, 163u,
- 89u, 223u, 1u, 199u,
- 115u, 124u, 201u, 156u,
- 190u, 98u, 9u, 209u,
- 1u, 237u, 135u, 186u,
- 144u, 226u, 129u, 8u,
- 42u, 202u, 56u, 181u,
- 37u, 170u, 114u, 94u,
- 99u, 143u, 124u, 72u,
- 190u, 133u, 1u, 232u,
- 154u, 172u, 137u, 153u,
- 86u, 99u, 101u, 172u,
- 153u, 57u, 255u, 195u,
- 91u, 71u, 172u, 133u,
- 167u, 116u, 161u, 163u,
- 246u, 255u, 173u, 85u,
- 171u, 167u, 131u, 196u,
- 158u, 28u, 94u, 86u,
- 59u, 95u, 186u, 41u,
- 165u, 166u, 126u, 133u,
- 80u, 255u, 139u, 173u,
- 129u, 186u, 91u, 70u,
- 215u, 147u, 116u, 115u,
- 117u, 105u, 128u, 140u,
- 255u, 165u, 110u, 207u,
- 118u, 122u, 189u, 142u,
- 173u, 136u, 208u, 161u,
- 14u, 103u, 42u, 87u,
- 143u, 195u, 133u, 160u,
- 47u, 186u, 255u, 192u,
- 1u, 126u, 79u, 177u,
- 85u, 77u, 81u, 3u,
- 185u, 189u, 15u, 44u,
- 121u, 167u, 74u, 118u,
- 180u, 145u, 129u, 124u,
- 82u, 126u, 12u, 26u,
- 255u, 245u, 63u, 159u,
- 136u, 235u, 240u, 151u,
- 134u, 110u, 255u, 151u,
- 70u, 68u, 117u, 146u,
- 206u, 169u, 163u, 206u,
- 132u, 70u, 170u, 193u,
- 119u, 125u, 92u, 92u,
- 184u, 46u, 179u, 56u,
- 1u, 181u, 45u, 75u,
- 125u, 127u, 130u, 8u,
- 146u, 185u, 127u, 120u,
- 122u, 150u, 194u, 150u,
- 166u, 213u, 154u, 243u,
- 131u, 255u, 224u, 151u,
- 95u, 61u, 173u, 145u,
- 94u, 189u, 112u, 216u,
- 114u, 255u, 146u, 195u,
- 222u, 84u, 110u, 58u,
- 202u, 148u, 133u, 35u,
- 58u, 56u, 0u, 29u,
- 90u, 124u, 187u, 89u,
- 144u, 5u, 217u, 241u,
- 65u, 27u, 223u, 1u,
- 168u, 196u, 242u, 178u,
- 52u, 99u, 142u, 34u,
- 15u, 62u, 103u, 19u,
- 118u, 70u, 1u, 46u,
- 180u, 146u, 175u, 55u,
- 43u, 163u, 96u, 78u,
- 65u, 85u, 90u, 123u,
- 106u, 50u, 83u, 130u,
- 1u, 48u, 33u, 80u,
- 172u, 180u, 107u, 253u,
- 214u, 3u, 90u, 74u,
- 66u, 27u, 16u, 131u,
- 35u, 89u, 124u, 125u,
- 138u, 43u, 114u, 123u,
- 129u, 255u, 105u, 64u,
- 71u, 26u, 46u, 183u,
- 66u, 46u, 87u, 254u,
- 2u, 201u, 209u, 154u,
- 255u, 140u, 172u, 11u,
- 151u, 215u, 146u, 77u,
- 151u, 82u, 255u, 139u,
- 83u, 78u, 100u, 162u,
- 216u, 64u, 105u, 174u,
- 202u, 100u, 252u, 152u,
- 125u, 54u, 130u, 34u,
- 92u, 173u, 0u, 167u,
- 152u, 113u, 117u, 132u,
- 108u, 160u, 1u, 146u,
- 56u, 200u, 50u, 171u,
- 175u, 45u, 70u, 85u,
- 148u, 172u, 136u, 86u,
- 118u, 23u, 59u, 50u,
- 163u, 208u, 115u, 145u,
- 59u, 196u, 104u, 194u,
- 251u, 74u, 178u, 0u,
- 91u, 252u, 22u, 199u,
- 68u, 190u, 216u, 189u,
- 131u, 80u, 1u, 216u,
- 107u, 213u, 51u, 127u,
- 124u, 155u, 123u, 136u,
- 233u, 190u, 255u, 91u,
- 176u, 179u, 114u, 141u,
- 110u, 130u, 171u, 156u,
- 116u, 99u, 122u, 140u,
- 95u, 83u, 104u, 131u,
- 53u, 178u, 147u, 136u,
- 107u, 243u, 85u, 255u,
- 176u, 199u, 134u, 120u,
- 140u, 147u, 95u, 122u,
- 63u, 1u, 160u, 125u,
- 198u, 70u, 255u, 131u,
- 107u, 200u, 196u, 188u,
- 1u, 64u, 220u, 121u,
- 145u, 63u, 207u, 146u,
- 213u, 18u, 182u, 255u,
- 12u, 73u, 235u, 181u,
- 61u, 202u, 130u, 164u,
- 255u, 147u, 129u, 137u,
- 118u, 74u, 61u, 217u,
- 129u, 161u, 141u, 190u,
- 97u, 30u, 0u, 177u,
- 123u, 57u, 97u, 178u,
- 158u, 154u, 157u, 202u,
- 69u, 107u, 60u, 210u,
- 1u, 138u, 122u, 72u,
- 113u, 143u, 38u, 118u,
- 144u, 121u, 136u, 139u,
- 70u, 124u, 122u, 127u,
- 167u, 121u, 119u, 158u,
- 99u, 186u, 183u, 137u,
- 189u, 116u, 1u, 153u,
- 127u, 178u, 116u, 251u,
- 178u, 142u, 176u, 194u,
- 63u, 136u, 85u, 195u,
- 118u, 157u, 255u, 41u,
- 242u, 255u, 62u, 163u,
- 135u, 98u, 120u, 99u,
- 145u, 110u, 147u, 169u,
- 162u, 101u, 85u, 94u,
- 121u, 157u, 84u, 129u,
- 204u, 100u, 80u, 147u,
- 85u, 255u, 223u, 34u,
- 153u, 238u, 17u, 81u,
- 85u, 255u, 114u, 69u,
- 227u, 196u, 180u, 216u,
- 232u, 189u, 159u, 89u,
- 72u, 108u, 37u, 169u,
- 147u, 106u, 167u, 255u,
- 169u, 96u, 123u, 171u,
- 111u, 116u, 144u, 130u,
- 182u, 143u, 174u, 105u,
- 21u, 38u, 163u, 255u,
- 122u, 85u, 74u, 225u,
- 76u, 61u, 108u, 185u,
- 143u, 169u, 78u, 192u,
- 94u, 131u, 139u, 237u,
- 82u, 84u, 197u, 70u,
- 166u, 213u, 165u, 187u,
- 255u, 172u, 61u, 7u,
- 194u, 102u, 153u, 164u,
- 174u, 148u, 134u, 1u,
- 31u, 132u, 87u, 83u,
- 140u, 227u, 155u, 111u,
- 103u, 145u, 97u, 102u,
- 91u, 152u, 115u, 74u,
- 185u, 175u, 131u, 68u,
- 129u, 214u, 125u, 255u,
- 255u, 194u, 163u, 173u,
- 161u, 74u, 46u, 211u,
- 139u, 10u, 180u, 56u,
- 145u, 111u, 130u, 198u,
- 43u, 204u, 157u, 63u,
- 96u, 4u, 120u, 133u,
- 123u, 255u, 13u, 244u,
- 139u, 79u, 125u, 142u,
- 1u, 117u, 163u, 111u,
- 137u, 141u, 169u, 137u,
- 148u, 145u, 39u, 122u,
- 46u, 83u, 107u, 58u,
- 57u, 78u, 255u, 233u,
- 155u, 140u, 11u, 198u,
- 101u, 158u, 181u, 193u,
- 150u, 111u, 93u, 106u,
- 153u, 197u, 172u, 104u,
- 151u, 244u, 140u, 55u,
- 17u, 255u, 126u, 150u,
- 69u, 233u, 126u, 131u,
- 195u, 168u, 189u, 99u,
- 188u, 53u, 1u, 191u,
- 37u, 142u, 112u, 206u,
- 83u, 176u, 185u, 170u,
- 255u, 68u, 25u, 105u,
- 86u, 61u, 17u, 160u,
- 119u, 83u, 113u, 31u,
- 92u, 209u, 90u, 114u,
- 120u, 131u, 248u, 126u,
- 82u, 151u, 46u, 111u,
- 83u, 147u, 115u, 1u,
- 144u, 57u, 72u, 91u,
- 195u, 120u, 123u, 154u,
- 112u, 66u, 195u, 255u,
- 118u, 101u, 35u, 144u,
- 164u, 222u, 124u, 37u,
- 77u, 200u, 60u, 213u,
- 250u, 33u, 124u, 79u,
- 66u, 109u, 193u, 118u,
- 255u, 91u, 134u, 196u,
- 1u, 89u, 69u, 157u,
- 85u, 110u, 162u, 75u,
- 31u, 97u, 106u, 159u,
- 252u, 96u, 175u, 153u,
- 233u, 43u, 176u, 85u,
- 1u, 35u, 38u, 175u,
- 232u, 216u, 142u, 134u,
- 155u, 111u, 180u, 34u,
- 101u, 220u, 75u, 73u,
- 207u, 194u, 114u, 84u,
- 71u, 135u, 77u, 67u,
- 59u, 179u, 1u, 208u,
- 206u, 148u, 140u, 147u,
- 163u, 0u, 151u, 178u,
- 204u, 227u, 107u, 121u,
- 79u, 223u, 199u, 166u,
- 172u, 166u, 149u, 192u,
- 36u, 95u, 255u, 150u,
- 244u, 228u, 102u, 118u,
- 105u, 205u, 80u, 64u,
- 155u, 144u, 245u, 156u,
- 0u, 50u, 131u, 193u,
- 79u, 186u, 197u, 228u,
- 22u, 154u, 192u, 141u,
- 121u, 39u, 195u, 123u,
- 154u, 255u, 79u, 118u,
- 84u, 59u, 134u, 124u,
- 94u, 99u, 89u, 94u,
- 73u, 74u, 191u, 118u,
- 29u, 212u, 0u, 141u,
- 145u, 158u, 135u, 43u,
- 71u, 108u, 139u, 109u,
- 102u, 1u, 166u, 103u,
- 85u, 173u, 225u, 180u,
- 191u, 188u, 252u, 96u,
- 110u, 212u, 138u, 115u,
- 146u, 199u, 93u, 98u,
- 194u, 56u, 122u, 214u,
- 130u, 86u, 178u, 87u,
- 194u, 0u, 158u, 18u,
- 117u, 167u, 133u, 145u,
- 126u, 106u, 255u, 143u,
- 184u, 165u, 161u, 114u,
- 61u, 78u, 143u, 75u,
- 0u, 181u, 108u, 105u,
- 120u, 206u, 188u, 76u,
- 238u, 178u, 7u, 185u,
- 17u, 199u, 70u, 204u,
- 1u, 149u, 9u, 131u,
- 149u, 255u, 210u, 43u,
- 153u, 140u, 124u, 133u,
- 14u, 53u, 203u, 125u,
- 174u, 190u, 42u, 113u,
- 126u, 193u, 144u, 94u,
- 87u, 72u, 191u, 87u,
- 39u, 0u, 157u, 108u,
- 186u, 111u, 170u, 96u,
- 125u, 1u, 57u, 168u,
- 141u, 52u, 131u, 175u,
- 199u, 85u, 173u, 139u,
- 103u, 42u, 79u, 255u,
- 163u, 136u, 90u, 160u,
- 216u, 155u, 70u, 118u,
- 99u, 200u, 11u, 135u,
- 162u, 168u, 180u, 193u,
- 113u, 199u, 45u, 196u,
- 207u, 88u, 183u, 176u,
- 46u, 1u, 158u, 184u,
- 196u, 32u, 148u, 132u,
- 106u, 218u, 36u, 250u,
- 215u, 67u, 1u, 155u,
- 126u, 84u, 154u, 93u,
- 31u, 196u, 60u, 101u,
- 255u, 104u, 104u, 56u,
- 95u, 139u, 154u, 138u,
- 167u, 168u, 88u, 137u,
- 174u, 175u, 144u, 209u,
- 162u, 125u, 118u, 126u,
- 74u, 130u, 16u, 106u,
- 255u, 175u, 18u, 63u,
- 32u, 103u, 43u, 90u,
- 160u, 89u, 189u, 113u,
- 138u, 99u, 66u, 98u,
- 255u, 127u, 183u, 81u,
- 165u, 88u, 207u, 148u,
- 98u, 133u, 142u, 76u,
- 1u, 176u, 67u, 207u,
- 7u, 182u, 153u, 92u,
- 202u, 175u, 119u, 0u,
- 131u, 137u, 144u, 68u,
- 184u, 79u, 20u, 101u,
- 179u, 147u, 165u, 185u,
- 1u, 141u, 78u, 78u,
- 48u, 112u, 163u, 170u,
- 88u, 138u, 146u, 83u,
- 145u, 218u, 167u, 84u,
- 53u, 115u, 193u, 171u,
- 229u, 147u, 255u, 1u,
- 160u, 143u, 115u, 73u,
- 120u, 104u, 54u, 175u,
- 167u, 119u, 201u, 136u,
- 235u, 117u, 113u, 108u,
- 130u, 124u, 113u, 84u,
- 98u, 0u, 90u, 86u,
- 252u, 195u, 255u, 154u,
- 120u, 101u, 213u, 81u,
- 47u, 78u, 195u, 71u,
- 174u, 62u, 137u, 147u,
- 62u, 134u, 114u, 104u,
- 174u, 106u, 255u, 101u,
- 70u, 143u, 193u, 161u,
- 65u, 59u, 91u, 26u,
- 100u, 29u, 170u, 93u,
- 255u, 9u, 199u, 223u,
- 134u, 183u, 16u, 183u,
- 67u, 175u, 96u, 62u,
- 94u, 41u, 163u, 113u,
- 134u, 41u, 85u, 136u,
- 131u, 166u, 124u, 97u,
- 141u, 158u, 106u, 255u,
- 164u, 94u, 68u, 150u,
- 66u, 176u, 138u, 143u,
- 98u, 140u, 89u, 191u,
- 73u, 172u, 255u, 37u,
- 255u, 205u, 115u, 59u,
- 98u, 114u, 120u, 85u,
- 239u, 111u, 120u, 128u,
- 114u, 65u, 172u, 107u,
- 139u, 172u, 168u, 185u,
- 68u, 174u, 199u, 1u,
- 179u, 173u, 75u, 145u,
- 111u, 165u, 213u, 138u,
- 182u, 152u, 165u, 182u,
- 80u, 255u, 156u, 239u,
- 81u, 127u, 48u, 35u,
- 129u, 101u, 129u, 183u,
- 56u, 171u, 211u, 182u,
- 189u, 78u, 181u, 88u,
- 7u, 68u, 163u, 93u,
- 152u, 0u, 79u, 242u,
- 187u, 207u, 255u, 101u,
- 230u, 216u, 64u, 99u,
- 165u, 157u, 120u, 126u,
- 84u, 237u, 23u, 73u,
- 235u, 107u, 138u, 99u,
- 111u, 255u, 138u, 185u,
- 101u, 178u, 151u, 124u,
- 3u, 98u, 160u, 176u,
- 139u, 239u, 158u, 55u,
- 208u, 129u, 1u, 92u,
- 81u, 184u, 144u, 202u,
- 123u, 199u, 169u, 196u,
- 47u, 39u, 147u, 206u,
- 133u, 157u, 1u, 193u,
- 105u, 132u, 248u, 131u,
- 14u, 129u, 42u, 16u,
- 96u, 107u, 89u, 158u,
- 51u, 39u, 226u, 219u,
- 53u, 70u, 133u, 18u,
- 224u, 239u, 255u, 172u,
- 99u, 71u, 98u, 172u,
- 73u, 116u, 69u, 39u,
- 134u, 140u, 92u, 75u,
- 163u, 89u, 1u, 130u,
- 224u, 154u, 124u, 255u,
- 114u, 160u, 167u, 96u,
- 140u, 87u, 134u, 97u,
- 65u, 55u, 73u, 126u,
- 126u, 85u, 52u, 70u,
- 80u, 108u, 1u, 128u,
- 104u, 62u, 95u, 150u,
- 107u, 55u, 188u, 219u,
- 118u, 70u, 30u, 172u,
- 178u, 113u, 118u, 80u,
- 60u, 86u, 1u, 122u,
- 213u, 94u, 99u, 172u,
- 116u, 145u, 130u, 101u,
- 172u, 139u, 125u, 139u,
- 180u, 150u, 1u, 177u,
- 70u, 177u, 168u, 149u,
- 124u, 133u, 186u, 203u,
- 1u, 195u, 169u, 218u,
- 131u, 252u, 92u, 78u,
- 74u, 114u, 135u, 100u,
- 173u, 180u, 193u, 83u,
- 170u, 75u, 1u, 119u,
- 68u, 146u, 112u, 75u,
- 247u, 112u, 41u, 37u,
- 175u, 171u, 178u, 191u,
- 158u, 83u, 124u, 121u,
- 131u, 95u, 255u, 182u,
- 163u, 118u, 104u, 118u,
- 150u, 115u, 92u, 71u,
- 230u, 119u, 135u, 184u,
- 1u, 25u, 137u, 84u,
- 137u, 133u, 115u, 118u,
- 1u, 62u, 54u, 137u,
- 70u, 127u, 143u, 190u,
- 165u, 123u, 124u, 179u,
- 198u, 33u, 30u, 142u,
- 92u, 178u, 73u, 76u,
- 150u, 148u, 207u, 122u,
- 88u, 83u, 153u, 104u,
- 184u, 153u, 179u, 255u,
- 193u, 137u, 204u, 94u,
- 140u, 191u, 29u, 166u,
- 145u, 133u, 88u, 130u,
- 1u, 168u, 121u, 113u,
- 122u, 64u, 101u, 110u,
- 151u, 117u, 115u, 255u,
- 160u, 80u, 197u, 94u,
- 187u, 82u, 113u, 199u,
- 180u, 141u, 178u, 196u,
- 8u, 143u, 114u, 51u,
- 122u, 169u, 225u, 137u,
- 111u, 255u, 94u, 94u,
- 165u, 103u, 147u, 110u,
- 69u, 107u, 44u, 150u,
- 141u, 17u, 66u, 195u,
- 0u, 181u, 84u, 189u,
- 28u, 152u, 66u, 113u,
- 142u, 182u, 166u, 255u,
- 84u, 133u, 118u, 135u,
- 165u, 85u, 122u, 176u,
- 205u, 159u, 44u, 18u,
- 58u, 159u, 69u, 103u,
- 181u, 234u, 70u, 208u,
- 162u, 88u, 255u, 41u,
- 62u, 116u, 1u, 169u,
- 166u, 25u, 56u, 121u,
- 140u, 73u, 152u, 175u,
- 81u, 97u, 41u, 93u,
- 104u, 1u, 36u, 4u,
- 116u, 109u, 249u, 37u,
- 202u, 118u, 125u, 25u,
- 153u, 50u, 147u, 62u,
- 146u, 95u, 79u, 154u,
- 112u, 170u, 106u, 216u,
- 120u, 135u, 161u, 111u,
- 150u, 255u, 107u, 45u,
- 23u, 0u, 88u, 144u,
- 127u, 145u, 67u, 193u,
- 116u, 109u, 83u, 128u,
- 79u, 236u, 139u, 80u,
- 69u, 255u, 198u, 71u,
- 78u, 224u, 153u, 19u,
- 163u, 125u, 59u, 175u,
- 77u, 123u, 139u, 139u,
- 134u, 162u, 188u, 110u,
- 33u, 140u, 201u, 146u,
- 152u, 208u, 172u, 151u,
- 0u, 98u, 113u, 24u,
- 42u, 185u, 202u, 90u,
- 232u, 111u, 247u, 164u,
- 131u, 206u, 120u, 108u,
- 231u, 255u, 182u, 104u,
- 81u, 130u, 120u, 147u,
- 140u, 101u, 151u, 155u,
- 133u, 131u, 110u, 94u,
- 188u, 161u, 1u, 109u,
- 1u, 47u, 72u, 221u,
- 18u, 97u, 120u, 105u,
- 187u, 200u, 103u, 47u,
- 171u, 169u, 56u, 64u,
- 255u, 47u, 162u, 113u,
- 153u, 39u, 54u, 225u,
- 72u, 170u, 168u, 116u,
- 201u, 89u, 214u, 109u,
- 255u, 149u, 140u, 156u,
- 60u, 128u, 73u, 47u,
- 139u, 98u, 112u, 96u,
- 87u, 168u, 210u, 159u,
- 1u, 151u, 124u, 118u,
- 52u, 129u, 101u, 135u,
- 95u, 89u, 116u, 87u,
- 86u, 89u, 201u, 166u,
- 1u, 246u, 243u, 161u,
- 210u, 6u, 229u, 88u,
- 129u, 120u, 99u, 86u,
- 136u, 143u, 98u, 199u,
- 149u, 81u, 73u, 186u,
- 128u, 1u, 97u, 78u,
- 71u, 151u, 140u, 66u,
- 224u, 82u, 242u, 121u,
- 125u, 175u, 216u, 223u,
- 10u, 40u, 155u, 85u,
- 158u, 164u, 70u, 1u,
- 215u, 27u, 58u, 108u,
- 133u, 0u, 110u, 68u,
- 179u, 177u, 187u, 128u,
- 3u, 27u, 23u, 154u,
- 90u, 188u, 37u, 158u,
- 133u, 255u, 221u, 150u,
- 98u, 162u, 241u, 218u,
- 63u, 185u, 198u, 107u,
- 243u, 151u, 55u, 157u,
- 135u, 141u, 117u, 187u,
- 142u, 162u, 135u, 117u,
- 195u, 203u, 88u, 153u,
- 193u, 83u, 255u, 28u,
- 80u, 31u, 143u, 127u,
- 106u, 81u, 96u, 16u,
- 175u, 255u, 141u, 4u,
- 108u, 137u, 150u, 166u,
- 112u, 178u, 197u, 181u,
- 123u, 201u, 80u, 132u,
- 124u, 40u, 255u, 117u,
- 220u, 56u, 73u, 250u,
- 216u, 133u, 255u, 109u,
- 149u, 173u, 128u, 209u,
- 26u, 97u, 72u, 108u,
- 71u, 194u, 28u, 30u,
- 161u, 71u, 32u, 201u,
- 64u, 83u, 0u, 150u,
- 90u, 121u, 154u, 160u,
- 207u, 144u, 47u, 55u,
- 179u, 180u, 205u, 255u,
- 94u, 60u, 88u, 224u,
- 12u, 196u, 82u, 23u,
- 35u, 249u, 72u, 80u,
- 130u, 10u, 67u, 1u,
- 108u, 114u, 23u, 163u,
- 219u, 209u, 34u, 177u,
- 59u, 190u, 150u, 45u,
- 75u, 208u, 37u, 34u,
- 192u, 51u, 254u, 255u,
- 161u, 76u, 120u, 84u,
- 177u, 37u, 64u, 193u,
- 147u, 85u, 182u, 139u,
- 58u, 38u, 153u, 82u,
- 156u, 87u, 166u, 76u,
- 115u, 113u, 255u, 93u,
- 140u, 73u, 128u, 55u,
- 124u, 165u, 202u, 36u,
- 255u, 83u, 101u, 121u,
- 51u, 33u, 76u, 162u,
- 3u, 30u, 143u, 75u,
- 138u, 89u, 1u, 89u,
- 175u, 68u, 192u, 101u,
- 99u, 164u, 105u, 68u,
- 211u, 122u, 171u, 78u,
- 135u, 115u, 0u, 150u,
- 148u, 110u, 109u, 85u,
- 98u, 69u, 184u, 169u,
- 155u, 75u, 110u, 255u,
- 111u, 94u, 15u, 107u,
- 62u, 62u, 41u, 113u,
- 152u, 159u, 102u, 119u,
- 186u, 169u, 98u, 124u,
- 131u, 161u, 118u, 1u,
- 101u, 168u, 132u, 142u,
- 170u, 196u, 151u, 167u,
- 72u, 88u, 112u, 20u,
- 167u, 62u, 139u, 197u,
- 127u, 134u, 147u, 237u,
- 1u, 143u, 60u, 93u,
- 94u, 102u, 1u, 163u,
- 74u, 207u, 126u, 128u,
- 159u, 150u, 23u, 147u,
- 131u, 195u, 85u, 117u,
- 113u, 200u, 145u, 2u,
- 0u, 97u, 64u, 35u,
- 106u, 162u, 140u, 140u,
- 51u, 134u, 105u, 138u,
- 149u, 165u, 87u, 139u,
- 138u, 147u, 58u, 142u,
- 122u, 194u, 41u, 255u,
- 175u, 231u, 134u, 31u,
- 133u, 1u, 141u, 141u,
- 237u, 97u, 85u, 230u,
- 174u, 191u, 87u, 138u,
- 237u, 54u, 166u, 63u,
- 76u, 151u, 147u, 73u,
- 143u, 155u, 167u, 122u,
- 147u, 127u, 193u, 113u,
- 122u, 1u, 78u, 111u,
- 116u, 146u, 96u, 142u,
- 152u, 90u, 144u, 76u,
- 107u, 255u, 77u, 102u,
- 106u, 102u, 186u, 115u,
- 154u, 23u, 159u, 123u,
- 38u, 165u, 181u, 130u,
- 187u, 130u, 76u, 1u,
- 98u, 140u, 181u, 111u,
- 81u, 91u, 27u, 62u,
- 226u, 255u, 117u, 171u,
- 10u, 90u, 75u, 205u,
- 74u, 105u, 179u, 100u,
- 82u, 255u, 174u, 138u,
- 119u, 45u, 195u, 78u,
- 86u, 124u, 121u, 216u,
- 66u, 144u, 93u, 127u,
- 1u, 127u, 119u, 208u,
- 166u, 79u, 135u, 216u,
- 143u, 228u, 176u, 156u,
- 201u, 91u, 29u, 224u,
- 180u, 146u, 20u, 126u,
- 160u, 105u, 89u, 1u,
- 192u, 69u, 230u, 100u,
- 178u, 82u, 149u, 158u,
- 151u, 168u, 206u, 102u,
- 214u, 156u, 113u, 246u,
- 154u, 212u, 255u, 163u,
- 40u, 213u, 53u, 31u,
- 127u, 234u, 120u, 101u,
- 196u, 184u, 145u, 147u,
- 84u, 138u, 141u, 146u,
- 144u, 200u, 165u, 1u,
- 186u, 201u, 213u, 180u,
- 78u, 92u, 93u, 0u,
- 102u, 71u, 145u, 176u,
- 199u, 113u, 73u, 92u,
- 83u, 175u, 111u, 72u,
- 153u, 59u, 1u, 147u,
- 65u, 169u, 112u, 82u,
- 168u, 109u, 9u, 207u,
- 81u, 180u, 57u, 255u,
- 173u, 185u, 97u, 152u,
- 142u, 122u, 148u, 70u,
- 116u, 132u, 106u, 59u,
- 120u, 90u, 89u, 1u,
- 97u, 196u, 159u, 149u,
- 229u, 206u, 76u, 135u,
- 64u, 174u, 181u, 119u,
- 91u, 141u, 150u, 255u,
- 95u, 51u, 94u, 127u,
- 241u, 97u, 137u, 55u,
- 191u, 26u, 108u, 161u,
- 29u, 103u, 95u, 1u,
- 221u, 118u, 175u, 76u,
- 116u, 204u, 73u, 116u,
- 59u, 194u, 84u, 193u,
- 57u, 1u, 103u, 189u,
- 127u, 94u, 135u, 157u,
- 78u, 106u, 94u, 167u,
- 109u, 171u, 54u, 152u,
- 153u, 89u, 74u, 182u,
- 45u, 255u, 137u, 125u,
- 142u, 96u, 81u, 56u,
- 38u, 133u, 37u, 4u,
- 163u, 39u, 164u, 219u,
- 66u, 0u, 69u, 99u,
- 69u, 196u, 95u, 92u,
- 198u, 210u, 162u, 163u,
- 84u, 152u, 134u, 130u,
- 4u, 145u, 59u, 207u,
- 80u, 1u, 154u, 174u,
- 105u, 89u, 3u, 130u,
- 173u, 255u, 127u, 144u,
- 147u, 38u, 141u, 86u,
- 110u, 92u, 103u, 54u,
- 128u, 81u, 151u, 239u,
- 174u, 145u, 134u, 1u,
- 145u, 151u, 147u, 165u,
- 68u, 165u, 74u, 161u,
- 77u, 209u, 97u, 135u,
- 121u, 1u, 76u, 168u,
- 230u, 44u, 86u, 205u,
- 149u, 158u, 74u, 106u,
- 90u, 160u, 114u, 197u,
- 51u, 173u, 118u, 180u,
- 129u, 243u, 133u, 128u,
- 20u, 108u, 125u, 106u,
- 21u, 255u, 29u, 252u,
- 114u, 174u, 152u, 243u,
- 84u, 111u, 97u, 187u,
- 183u, 8u, 140u, 52u,
- 255u, 91u, 211u, 229u,
- 147u, 119u, 131u, 24u,
- 149u, 76u, 211u, 163u,
- 170u, 148u, 1u, 130u,
- 165u, 61u, 86u, 160u,
- 81u, 144u, 69u, 199u,
- 87u, 130u, 119u, 70u,
- 168u, 145u, 64u, 79u,
- 100u, 101u, 136u, 255u,
- 227u, 122u, 133u, 167u,
- 153u, 240u, 105u, 167u,
- 20u, 85u, 1u, 166u,
- 69u, 243u, 49u, 56u,
- 101u, 191u, 150u, 28u,
- 80u, 66u, 109u, 168u,
- 1u, 200u, 65u, 107u,
- 158u, 224u, 22u, 127u,
- 49u, 86u, 164u, 87u,
- 199u, 142u, 168u, 98u,
- 152u, 174u, 83u, 117u,
- 159u, 205u, 164u, 1u,
- 134u, 255u, 183u, 166u,
- 107u, 156u, 200u, 73u,
- 222u, 212u, 125u, 122u,
- 180u, 141u, 244u, 79u,
- 111u, 253u, 169u, 199u,
- 239u, 116u, 149u, 101u,
- 127u, 152u, 220u, 255u,
- 244u, 119u, 191u, 87u,
- 41u, 191u, 132u, 255u,
- 114u, 127u, 136u, 11u,
- 69u, 82u, 157u, 84u,
- 143u, 99u, 163u, 67u,
- 96u, 139u, 29u, 137u,
- 155u, 151u, 204u, 95u,
- 0u, 90u, 138u, 150u,
- 94u, 76u, 59u, 139u,
- 123u, 115u, 147u, 255u,
- 237u, 104u, 123u, 40u,
- 24u, 141u, 122u, 71u,
- 182u, 46u, 130u, 84u,
- 173u, 109u, 178u, 105u,
- 97u, 83u, 102u, 108u,
- 149u, 37u, 113u, 96u,
- 84u, 0u, 102u, 69u,
- 196u, 112u, 130u, 128u,
- 184u, 167u, 134u, 103u,
- 1u, 137u, 121u, 53u,
- 95u, 170u, 18u, 134u,
- 178u, 238u, 1u, 107u,
- 174u, 209u, 196u, 137u,
- 238u, 145u, 90u, 112u,
- 36u, 176u, 153u, 65u,
- 82u, 179u, 133u, 191u,
- 37u, 163u, 49u, 94u,
- 0u, 130u, 109u, 220u,
- 63u, 211u, 232u, 112u,
- 84u, 42u, 175u, 121u,
- 185u, 1u, 111u, 43u,
- 160u, 144u, 51u, 132u,
- 253u, 241u, 13u, 203u,
- 49u, 184u, 159u, 82u,
- 96u, 72u, 181u, 91u,
- 50u, 134u, 188u, 235u,
- 255u, 111u, 118u, 18u,
- 51u, 106u, 130u, 84u,
- 173u, 179u, 120u, 82u,
- 64u, 122u, 1u, 155u,
- 97u, 215u, 123u, 68u,
- 105u, 73u, 175u, 51u,
- 118u, 73u, 170u, 122u,
- 131u, 93u, 99u, 129u,
- 96u, 146u, 80u, 1u,
- 205u, 123u, 203u, 152u,
- 113u, 49u, 116u, 189u,
- 193u, 146u, 255u, 174u,
- 144u, 69u, 160u, 117u,
- 183u, 130u, 164u, 255u,
- 200u, 30u, 150u, 151u,
- 85u, 132u, 97u, 47u,
- 255u, 125u, 67u, 46u,
- 122u, 76u, 139u, 144u,
- 96u, 102u, 74u, 124u,
- 133u, 123u, 58u, 78u,
- 125u, 69u, 123u, 1u,
- 235u, 192u, 146u, 58u,
- 38u, 1u, 30u, 147u,
- 123u, 137u, 200u, 7u,
- 174u, 191u, 197u, 19u,
- 200u, 204u, 255u, 223u,
- 132u, 88u, 183u, 202u,
- 149u, 116u, 250u, 172u,
- 159u, 145u, 127u, 79u,
- 65u, 62u, 220u, 168u,
- 61u, 240u, 105u, 4u,
- 232u, 68u, 175u, 94u,
- 25u, 8u, 97u, 255u,
- 75u, 1u, 167u, 85u,
- 108u, 144u, 166u, 220u,
- 159u, 149u, 103u, 189u,
- 38u, 81u, 138u, 151u,
- 146u, 218u, 163u, 52u,
- 121u, 255u, 85u, 118u,
- 149u, 143u, 99u, 124u,
- 18u, 68u, 62u, 166u,
- 127u, 80u, 183u, 255u,
- 145u, 113u, 228u, 135u,
- 171u, 191u, 144u, 185u,
- 192u, 230u, 168u, 104u,
- 187u, 234u, 101u, 212u,
- 167u, 110u, 249u, 226u,
- 189u, 94u, 255u, 238u,
- 147u, 147u, 108u, 168u,
- 94u, 85u, 105u, 84u,
- 98u, 163u, 137u, 72u,
- 59u, 255u, 131u, 226u,
- 178u, 157u, 135u, 86u,
- 164u, 185u, 51u, 1u,
- 236u, 190u, 148u, 160u,
- 124u, 115u, 124u, 147u,
- 56u, 89u, 78u, 153u,
- 139u, 124u, 141u, 130u,
- 84u, 71u, 67u, 140u,
- 140u, 88u, 195u, 94u,
- 255u, 110u, 158u, 153u,
- 202u, 88u, 203u, 128u,
- 53u, 77u, 108u, 1u,
- 112u, 246u, 201u, 69u,
- 110u, 228u, 149u, 70u,
- 158u, 134u, 94u, 156u,
- 119u, 156u, 137u, 49u,
- 132u, 255u, 175u, 63u,
- 80u, 141u, 179u, 142u,
- 255u, 90u, 157u, 120u,
- 142u, 68u, 130u, 53u,
- 158u, 108u, 153u, 77u,
- 116u, 107u, 133u, 131u,
- 42u, 104u, 163u, 255u,
- 38u, 105u, 135u, 28u,
- 81u, 189u, 132u, 165u,
- 127u, 96u, 218u, 210u,
- 97u, 211u, 47u, 127u,
- 176u, 123u, 154u, 131u,
- 84u, 149u, 174u, 133u,
- 255u, 138u, 177u, 247u,
- 66u, 114u, 104u, 60u,
- 160u, 170u, 219u, 255u,
- 126u, 154u, 105u, 84u,
- 143u, 106u, 114u, 115u,
- 124u, 214u, 134u, 200u,
- 82u, 85u, 255u, 78u,
- 250u, 22u, 106u, 116u,
- 38u, 91u, 154u, 139u,
- 81u, 138u, 228u, 161u,
- 145u, 110u, 60u, 43u,
- 203u, 46u, 107u, 255u,
- 253u, 206u, 76u, 36u,
- 199u, 161u, 152u, 167u,
- 137u, 98u, 138u, 255u,
- 212u, 59u, 99u, 135u,
- 181u, 192u, 113u, 145u,
- 94u, 193u, 157u, 69u,
- 200u, 233u, 124u, 255u,
- 24u, 137u, 111u, 142u,
- 40u, 243u, 166u, 161u,
- 132u, 151u, 112u, 148u,
- 81u, 95u, 0u, 184u,
- 135u, 43u, 102u, 200u,
- 205u, 132u, 201u, 143u,
- 86u, 255u, 63u, 82u,
- 164u, 141u, 137u, 91u,
- 166u, 20u, 163u, 149u,
- 201u, 48u, 95u, 148u,
- 109u, 50u, 146u, 36u,
- 10u, 84u, 196u, 3u,
- 31u, 1u, 76u, 149u,
- 203u, 202u, 155u, 120u,
- 86u, 147u, 65u, 56u,
- 86u, 222u, 108u, 157u,
- 1u, 75u, 79u, 131u,
- 97u, 104u, 148u, 39u,
- 141u, 181u, 132u, 199u,
- 1u, 34u, 104u, 119u,
- 137u, 163u, 171u, 59u,
- 217u, 220u, 167u, 112u,
- 43u, 42u, 86u, 45u,
- 165u, 170u, 95u, 89u,
- 218u, 128u, 51u, 107u,
- 98u, 102u, 255u, 126u,
- 157u, 188u, 240u, 49u,
- 1u, 152u, 102u, 163u,
- 73u, 136u, 166u, 140u,
- 84u, 16u, 94u, 158u,
- 196u, 74u, 121u, 97u,
- 62u, 199u, 32u, 132u,
- 255u, 140u, 137u, 158u,
- 60u, 100u, 171u, 129u,
- 159u, 171u, 181u, 93u,
- 178u, 184u, 255u, 116u,
- 122u, 84u, 46u, 94u,
- 82u, 193u, 98u, 137u,
- 99u, 186u, 140u, 197u,
- 184u, 128u, 213u, 1u,
- 108u, 35u, 243u, 145u,
- 235u, 97u, 178u, 128u,
- 96u, 164u, 91u, 217u,
- 104u, 132u, 163u, 130u,
- 16u, 110u, 136u, 97u,
- 28u, 106u, 255u, 82u,
- 14u, 163u, 111u, 184u,
- 102u, 149u, 145u, 165u,
- 119u, 59u, 0u, 187u,
- 76u, 142u, 58u, 30u,
- 188u, 134u, 80u, 214u,
- 40u, 172u, 229u, 174u,
- 216u, 99u, 157u, 122u,
- 1u, 150u, 216u, 167u,
- 235u, 203u, 132u, 116u,
- 144u, 86u, 130u, 164u,
- 126u, 43u, 255u, 120u,
- 63u, 88u, 67u, 230u,
- 93u, 154u, 120u, 101u,
- 92u, 213u, 62u, 169u,
- 0u, 167u, 77u, 107u,
- 140u, 29u, 124u, 65u,
- 113u, 72u, 23u, 100u,
- 161u, 74u, 68u, 245u,
- 91u, 177u, 126u, 119u,
- 255u, 174u, 58u, 132u,
- 170u, 182u, 59u, 237u,
- 174u, 167u, 125u, 204u,
- 171u, 185u, 67u, 22u,
- 129u, 149u, 173u, 1u,
- 195u, 40u, 142u, 98u,
- 203u, 132u, 163u, 149u,
- 166u, 88u, 101u, 119u,
- 218u, 92u, 154u, 1u,
- 125u, 179u, 154u, 210u,
- 93u, 189u, 255u, 127u,
- 97u, 50u, 149u, 119u,
- 164u, 176u, 23u, 193u,
- 112u, 52u, 153u, 245u,
- 0u, 76u, 93u, 224u,
- 192u, 134u, 101u, 202u,
- 185u, 66u, 208u, 109u,
- 227u, 126u, 141u, 134u,
- 231u, 102u, 187u, 69u,
- 77u, 200u, 233u, 68u,
- 158u, 1u, 199u, 138u,
- 54u, 153u, 112u, 86u,
- 133u, 204u, 107u, 100u,
- 165u, 157u, 57u, 255u,
- 93u, 169u, 152u, 109u,
- 100u, 49u, 24u, 222u,
- 77u, 102u, 0u, 218u,
- 132u, 16u, 179u, 98u,
- 63u, 62u, 52u, 189u,
- 182u, 92u, 83u, 114u,
- 128u, 130u, 115u, 113u,
- 180u, 194u, 218u, 255u,
- 121u, 134u, 139u, 82u,
- 220u, 123u, 141u, 44u,
- 169u, 102u, 134u, 96u,
- 111u, 121u, 133u, 195u,
- 141u, 255u, 180u, 128u,
- 62u, 174u, 108u, 140u,
- 51u, 137u, 94u, 1u,
- 205u, 196u, 168u, 178u,
- 166u, 213u, 225u, 131u,
- 43u, 133u, 201u, 66u,
- 86u, 212u, 125u, 183u,
- 132u, 152u, 152u, 115u,
- 198u, 114u, 93u, 1u,
- 120u, 198u, 175u, 34u,
- 106u, 63u, 0u, 169u,
- 193u, 112u, 237u, 156u,
- 59u, 21u, 141u, 71u,
- 118u, 146u, 174u, 156u,
- 83u, 80u, 108u, 1u,
- 129u, 88u, 50u, 198u,
- 119u, 219u, 158u, 150u,
- 96u, 119u, 105u, 154u,
- 74u, 65u, 153u, 106u,
- 119u, 203u, 141u, 119u,
- 157u, 255u, 169u, 247u,
- 22u, 175u, 247u, 81u,
- 158u, 171u, 127u, 48u,
- 152u, 197u, 80u, 32u,
- 1u, 101u, 216u, 81u,
- 149u, 114u, 199u, 173u,
- 103u, 131u, 182u, 35u,
- 131u, 255u, 138u, 152u,
- 190u, 110u, 75u, 93u,
- 89u, 126u, 169u, 72u,
- 92u, 1u, 202u, 58u,
- 184u, 207u, 59u, 103u,
- 169u, 61u, 208u, 135u,
- 20u, 152u, 126u, 76u,
- 10u, 66u, 72u, 58u,
- 145u, 195u, 134u, 87u,
- 141u, 36u, 255u, 156u,
- 41u, 124u, 72u, 100u,
- 148u, 153u, 219u, 194u,
- 1u, 105u, 201u, 105u,
- 184u, 38u, 55u, 231u,
- 174u, 64u, 109u, 64u,
- 162u, 0u, 105u, 109u,
- 135u, 127u, 129u, 77u,
- 154u, 104u, 201u, 93u,
- 141u, 125u, 189u, 84u,
- 174u, 183u, 84u, 50u,
- 1u, 166u, 195u, 136u,
- 98u, 176u, 59u, 100u,
- 1u, 85u, 119u, 167u,
- 109u, 69u, 193u, 130u,
- 109u, 169u, 57u, 96u,
- 206u, 72u, 200u, 166u,
- 238u, 177u, 255u, 186u,
- 166u, 160u, 100u, 149u,
- 148u, 214u, 17u, 125u,
- 218u, 187u, 183u, 7u,
- 195u, 154u, 145u, 173u,
- 200u, 6u, 115u, 249u,
- 46u, 49u, 121u, 166u,
- 186u, 75u, 255u, 28u,
- 130u, 116u, 1u, 105u,
- 139u, 143u, 100u, 168u,
- 176u, 165u, 161u, 112u,
- 108u, 137u, 87u, 91u,
- 218u, 223u, 228u, 101u,
- 149u, 33u, 56u, 118u,
- 158u, 113u, 122u, 162u,
- 198u, 0u, 97u, 178u,
- 100u, 70u, 199u, 100u,
- 74u, 107u, 160u, 76u,
- 249u, 223u, 28u, 241u,
- 133u, 255u, 229u, 1u,
- 214u, 1u, 151u, 225u,
- 143u, 181u, 31u, 203u,
- 121u, 63u, 58u, 112u,
- 176u, 160u, 186u, 33u,
- 125u, 33u, 248u, 226u,
- 57u, 89u, 130u, 91u,
- 0u, 157u, 195u, 94u,
- 122u, 250u, 91u, 75u,
- 165u, 144u, 106u, 151u,
- 141u, 169u, 143u, 128u,
- 158u, 91u, 1u, 142u,
- 124u, 160u, 105u, 110u,
- 160u, 1u, 177u, 12u,
- 140u, 181u, 61u, 142u,
- 76u, 171u, 158u, 110u,
- 49u, 82u, 99u, 65u,
- 255u, 183u, 88u, 72u,
- 145u, 95u, 130u, 165u,
- 125u, 198u, 36u, 18u,
- 46u, 136u, 197u, 68u,
- 232u, 212u, 164u, 90u,
- 77u, 99u, 107u, 139u,
- 131u, 0u, 78u, 199u,
- 157u, 120u, 120u, 106u,
- 159u, 102u, 134u, 72u,
- 131u, 158u, 163u, 89u,
- 74u, 143u, 255u, 99u,
- 178u, 106u, 94u, 123u,
- 55u, 214u, 97u, 211u,
- 65u, 155u, 174u, 1u,
- 171u, 125u, 164u, 159u,
- 176u, 33u, 153u, 219u,
- 20u, 114u, 115u, 228u,
- 229u, 24u, 186u, 255u,
- 54u, 184u, 95u, 23u,
- 103u, 177u, 76u, 204u,
- 117u, 131u, 116u, 128u,
- 178u, 0u, 43u, 126u,
- 143u, 225u, 193u, 142u,
- 246u, 142u, 136u, 232u,
- 138u, 71u, 92u, 144u,
- 118u, 1u, 161u, 165u,
- 1u, 126u, 133u, 154u,
- 181u, 245u, 137u, 146u,
- 155u, 185u, 255u, 197u,
- 177u, 180u, 163u, 141u,
- 41u, 98u, 164u, 122u,
- 61u, 150u, 105u, 133u,
- 221u, 169u, 88u, 199u,
- 128u, 58u, 90u, 185u,
- 46u, 243u, 92u, 1u,
- 130u, 180u, 127u, 54u,
- 143u, 175u, 200u, 74u,
- 100u, 255u, 131u, 89u,
- 120u, 194u, 225u, 71u,
- 152u, 48u, 234u, 71u,
- 200u, 88u, 106u, 186u,
- 69u, 131u, 193u, 102u,
- 138u, 84u, 115u, 95u,
- 117u, 98u, 255u, 226u,
- 94u, 147u, 144u, 253u,
- 1u, 126u, 40u, 155u,
- 104u, 39u, 88u, 197u,
- 221u, 34u, 124u, 49u,
- 124u, 32u, 130u, 255u,
- 104u, 33u, 69u, 112u,
- 52u, 94u, 192u, 98u,
- 114u, 78u, 109u, 107u,
- 176u, 85u, 67u, 35u,
- 176u, 57u, 207u, 170u,
- 1u, 180u, 92u, 180u,
- 154u, 29u, 17u, 79u,
- 10u, 255u, 78u, 62u,
- 178u, 146u, 118u, 156u,
- 206u, 45u, 105u, 42u,
- 146u, 119u, 189u, 102u,
- 13u, 135u, 207u, 255u,
- 92u, 93u, 130u, 153u,
- 176u, 66u, 100u, 168u,
- 141u, 91u, 127u, 217u,
- 137u, 46u, 82u, 179u,
- 133u, 231u, 138u, 214u,
- 1u, 80u, 111u, 133u,
- 114u, 152u, 70u, 102u,
- 99u, 26u, 56u, 128u,
- 183u, 119u, 6u, 195u,
- 74u, 1u, 132u, 208u,
- 209u, 59u, 180u, 41u,
- 186u, 52u, 219u, 188u,
- 0u, 73u, 21u, 131u,
- 212u, 194u, 168u, 43u,
- 235u, 36u, 181u, 157u,
- 99u, 196u, 42u, 97u,
- 183u, 28u, 255u, 214u,
- 126u, 136u, 181u, 103u,
- 196u, 121u, 100u, 203u,
- 179u, 168u, 147u, 109u,
- 157u, 175u, 255u, 171u,
- 227u, 99u, 143u, 186u,
- 58u, 119u, 162u, 137u,
- 177u, 202u, 238u, 127u,
- 186u, 127u, 128u, 163u,
- 194u, 74u, 82u, 157u,
- 170u, 1u, 53u, 146u,
- 44u, 179u, 208u, 136u,
- 82u, 191u, 43u, 107u,
- 121u, 255u, 178u, 106u,
- 112u, 208u, 38u, 68u,
- 59u, 99u, 136u, 1u,
- 189u, 121u, 116u, 220u,
- 105u, 202u, 191u, 143u,
- 110u, 97u, 25u, 135u,
- 214u, 121u, 201u, 29u,
- 227u, 156u, 162u, 169u,
- 165u, 110u, 148u, 165u,
- 111u, 119u, 255u, 83u,
- 97u, 119u, 128u, 234u,
- 255u, 106u, 2u, 113u,
- 146u, 143u, 66u, 156u,
- 172u, 55u, 32u, 139u,
- 96u, 151u, 148u, 89u,
- 99u, 157u, 127u, 255u,
- 153u, 107u, 237u, 127u,
- 149u, 127u, 199u, 39u,
- 31u, 179u, 127u, 190u,
- 203u, 74u, 204u, 110u,
- 110u, 200u, 126u, 113u,
- 249u, 105u, 1u, 189u,
- 68u, 178u, 95u, 149u,
- 94u, 78u, 35u, 110u,
- 135u, 153u, 82u, 101u,
- 1u, 149u, 174u, 158u,
- 184u, 106u, 233u, 122u,
- 145u, 128u, 143u, 177u,
- 69u, 189u, 189u, 115u,
- 103u, 197u, 255u, 80u,
- 216u, 171u, 126u, 26u,
- 126u, 105u, 79u, 213u,
- 255u, 140u, 75u, 166u,
- 54u, 109u, 230u, 128u,
- 154u, 98u, 130u, 123u,
- 129u, 113u, 53u, 92u,
- 192u, 137u, 208u, 1u,
- 160u, 100u, 119u, 116u,
- 141u, 255u, 121u, 172u,
- 178u, 108u, 205u, 116u,
- 125u, 125u, 143u, 139u,
- 138u, 33u, 94u, 173u,
- 80u, 180u, 113u, 134u,
- 165u, 114u, 165u, 124u,
- 156u, 111u, 125u, 132u,
- 56u, 110u, 60u, 255u,
- 99u, 163u, 23u, 131u,
- 140u, 147u, 131u, 193u,
- 36u, 94u, 73u, 60u,
- 153u, 0u, 178u, 130u,
- 91u, 101u, 74u, 26u,
- 140u, 174u, 190u, 49u,
- 190u, 255u, 174u, 109u,
- 151u, 33u, 46u, 143u,
- 36u, 231u, 255u, 157u,
- 242u, 104u, 218u, 158u,
- 92u, 15u, 176u, 23u,
- 62u, 51u, 79u, 109u,
- 1u, 211u, 193u, 83u,
- 250u, 27u, 245u, 57u,
- 187u, 170u, 216u, 213u,
- 174u, 87u, 87u, 238u,
- 143u, 114u, 97u, 80u,
- 229u, 187u, 139u, 113u,
- 1u, 123u, 190u, 128u,
- 93u, 71u, 163u, 30u,
- 94u, 127u, 56u, 144u,
- 146u, 132u, 93u, 198u,
- 75u, 155u, 135u, 40u,
- 185u, 255u, 86u, 176u,
- 189u, 6u, 178u, 191u,
- 205u, 37u, 172u, 219u,
- 1u, 107u, 43u, 105u,
- 58u, 230u, 167u, 53u,
- 75u, 166u, 173u, 193u,
- 163u, 255u, 255u, 35u,
- 120u, 221u, 68u, 25u,
- 78u, 114u, 134u, 128u,
- 149u, 180u, 98u, 22u,
- 199u, 157u, 159u, 126u,
- 36u, 1u, 132u, 173u,
- 41u, 219u, 87u, 169u,
- 226u, 237u, 58u, 52u,
- 37u, 179u, 40u, 119u,
- 192u, 164u, 15u, 116u,
- 7u, 1u, 84u, 127u,
- 108u, 190u, 221u, 94u,
- 42u, 149u, 156u, 59u,
- 168u, 175u, 152u, 126u,
- 170u, 226u, 255u, 145u,
- 181u, 100u, 191u, 165u,
- 147u, 0u, 176u, 128u,
- 149u, 107u, 111u, 87u,
- 93u, 106u, 224u, 132u,
- 79u, 89u, 160u, 132u,
- 141u, 121u, 103u, 109u,
- 51u, 173u, 111u, 82u,
- 255u, 231u, 93u, 193u,
- 154u, 152u, 126u, 74u,
- 155u, 165u, 153u, 94u,
- 132u, 192u, 120u, 0u,
- 140u, 113u, 86u, 155u,
- 133u, 18u, 206u, 30u,
- 241u, 30u, 75u, 63u,
- 86u, 154u, 198u, 255u,
- 203u, 110u, 1u, 180u,
- 117u, 200u, 211u, 172u,
- 1u, 221u, 82u, 9u,
- 115u, 115u, 148u, 89u,
- 127u, 35u, 195u, 112u,
- 148u, 197u, 47u, 138u,
- 233u, 42u, 116u, 61u,
- 141u, 122u, 33u, 165u,
- 137u, 154u, 255u, 184u,
- 158u, 104u, 121u, 90u,
- 111u, 255u, 98u, 232u,
- 147u, 145u, 166u, 180u,
- 157u, 133u, 144u, 198u,
- 114u, 152u, 129u, 118u,
- 106u, 190u, 118u, 255u,
- 150u, 45u, 57u, 38u,
- 111u, 56u, 80u, 132u,
- 223u, 111u, 218u, 38u,
- 67u, 211u, 120u, 105u,
- 209u, 194u, 110u, 101u,
- 159u, 137u, 177u, 1u,
- 127u, 77u, 213u, 222u,
- 245u, 0u, 252u, 205u,
- 67u, 13u, 200u, 36u,
- 139u, 150u, 167u, 152u,
- 125u, 37u, 7u, 109u,
- 159u, 40u, 195u, 143u,
- 0u, 57u, 140u, 228u,
- 165u, 141u, 105u, 1u,
- 81u, 208u, 45u, 76u,
- 95u, 64u, 109u, 231u,
- 114u, 38u, 152u, 186u,
- 6u, 255u, 159u, 208u,
- 164u, 114u, 90u, 197u,
- 77u, 199u, 90u, 209u,
- 127u, 176u, 135u, 173u,
- 104u, 203u, 255u, 179u,
- 160u, 145u, 89u, 148u,
- 200u, 92u, 164u, 172u,
- 102u, 119u, 27u, 204u,
- 135u, 1u, 94u, 241u,
- 98u, 88u, 71u, 118u,
- 98u, 170u, 124u, 107u,
- 132u, 189u, 1u, 143u,
- 135u, 106u, 78u, 46u,
- 205u, 127u, 131u, 255u,
- 174u, 56u, 68u, 241u,
- 32u, 103u, 169u, 106u,
- 74u, 126u, 138u, 76u,
- 32u, 176u, 40u, 214u,
- 155u, 83u, 111u, 201u,
- 196u, 155u, 84u, 207u,
- 255u, 90u, 128u, 191u,
- 101u, 247u, 102u, 117u,
- 71u, 25u, 1u, 56u,
- 129u, 130u, 213u, 96u,
- 104u, 131u, 110u, 75u,
- 134u, 124u, 166u, 126u,
- 97u, 182u, 188u, 164u,
- 180u, 106u, 1u, 144u,
- 89u, 57u, 45u, 86u,
- 139u, 129u, 76u, 61u,
- 3u, 1u, 179u, 110u,
- 184u, 185u, 135u, 100u,
- 69u, 162u, 140u, 130u,
- 35u, 74u, 162u, 62u,
- 210u, 212u, 255u, 171u,
- 128u, 111u, 58u, 191u,
- 78u, 206u, 121u, 136u,
- 167u, 86u, 149u, 163u,
- 1u, 213u, 133u, 131u,
- 190u, 44u, 168u, 11u,
- 46u, 110u, 210u, 111u,
- 204u, 211u, 104u, 210u,
- 39u, 121u, 101u, 146u,
- 154u, 56u, 144u, 171u,
- 195u, 37u, 255u, 240u,
- 155u, 90u, 184u, 140u,
- 131u, 48u, 42u, 255u,
- 172u, 61u, 164u, 66u,
- 170u, 54u, 185u, 64u,
- 89u, 1u, 79u, 233u,
- 114u, 64u, 237u, 186u,
- 206u, 126u, 229u, 143u,
- 206u, 163u, 85u, 223u,
- 142u, 183u, 152u, 143u,
- 255u, 156u, 143u, 76u,
- 90u, 103u, 171u, 109u,
- 182u, 118u, 83u, 167u,
- 109u, 106u, 130u, 202u,
- 183u, 152u, 5u, 213u,
- 234u, 109u, 63u, 255u,
- 192u, 127u, 131u, 132u,
- 103u, 239u, 130u, 255u,
- 111u, 177u, 105u, 195u,
- 166u, 35u, 179u, 201u,
- 165u, 31u, 69u, 131u,
- 195u, 195u, 232u, 107u,
- 131u, 47u, 0u, 177u,
- 91u, 156u, 170u, 56u,
- 135u, 109u, 141u, 88u,
- 120u, 179u, 141u, 234u,
- 121u, 83u, 106u, 180u,
- 93u, 136u, 255u, 77u,
- 168u, 106u, 178u, 94u,
- 145u, 122u, 54u, 177u,
- 162u, 148u, 255u, 109u,
- 156u, 39u, 123u, 76u,
- 156u, 165u, 187u, 138u,
- 110u, 161u, 86u, 90u,
- 224u, 74u, 193u, 129u,
- 142u, 115u, 15u, 165u,
- 57u, 255u, 160u, 125u,
- 21u, 160u, 159u, 122u,
- 213u, 67u, 182u, 168u,
- 100u, 133u, 114u, 122u,
- 206u, 231u, 1u, 251u,
- 175u, 241u, 215u, 57u,
- 191u, 113u, 131u, 38u,
- 181u, 164u, 104u, 82u,
- 100u, 153u, 1u, 27u,
- 77u, 25u, 167u, 101u,
- 165u, 120u, 116u, 184u,
- 142u, 145u, 129u, 49u,
- 1u, 170u, 71u, 86u,
- 99u, 136u, 154u, 120u,
- 28u, 109u, 68u, 111u,
- 42u, 255u, 117u, 147u,
- 183u, 120u, 115u, 151u,
- 89u, 35u, 162u, 164u,
- 139u, 82u, 119u, 98u,
- 95u, 255u, 202u, 102u,
- 167u, 111u, 166u, 44u,
- 108u, 176u, 127u, 183u,
- 64u, 216u, 86u, 199u,
- 255u, 153u, 241u, 145u,
- 64u, 51u, 155u, 190u,
- 179u, 153u, 203u, 126u,
- 102u, 91u, 126u, 63u,
- 165u, 161u, 158u, 138u,
- 112u, 74u, 103u, 1u,
- 131u, 147u, 248u, 60u,
- 176u, 90u, 1u, 147u,
- 53u, 178u, 68u, 108u,
- 117u, 135u, 205u, 151u,
- 43u, 134u, 119u, 120u,
- 210u, 158u, 95u, 142u,
- 101u, 147u, 78u, 87u,
- 202u, 139u, 0u, 154u,
- 35u, 166u, 1u, 156u,
- 207u, 174u, 153u, 144u,
- 106u, 111u, 167u, 29u,
- 193u, 20u, 58u, 41u,
- 35u, 68u, 163u, 217u,
- 162u, 255u, 85u, 125u,
- 90u, 130u, 98u, 144u,
- 4u, 114u, 125u, 122u,
- 75u, 181u, 196u, 106u,
- 168u, 103u, 173u, 89u,
- 138u, 116u, 158u, 161u,
- 255u, 157u, 107u, 121u,
- 154u, 82u, 128u, 174u,
- 157u, 71u, 66u, 148u,
- 34u, 151u, 1u, 241u,
- 69u, 178u, 134u, 87u,
- 75u, 88u, 27u, 43u,
- 45u, 187u, 87u, 114u,
- 141u, 103u, 91u, 23u,
- 1u, 112u, 137u, 237u,
- 138u, 160u, 219u, 69u,
- 101u, 173u, 115u, 167u,
- 170u, 85u, 71u, 94u,
- 160u, 97u, 1u, 37u,
- 134u, 119u, 33u, 0u,
- 141u, 33u, 160u, 195u,
- 131u, 139u, 116u, 164u,
- 86u, 52u, 100u, 86u,
- 125u, 63u, 118u, 255u,
- 44u, 27u, 50u, 144u,
- 226u, 0u, 117u, 168u,
- 154u, 218u, 127u, 167u,
- 128u, 100u, 173u, 216u,
- 24u, 89u, 116u, 110u,
- 184u, 109u, 93u, 49u,
- 163u, 145u, 1u, 144u,
- 40u, 249u, 125u, 34u,
- 119u, 121u, 163u, 72u,
- 70u, 142u, 131u, 255u,
- 242u, 247u, 112u, 131u,
- 84u, 10u, 15u, 133u,
- 115u, 60u, 162u, 156u,
- 112u, 234u, 241u, 105u,
- 255u, 155u, 31u, 53u,
- 176u, 132u, 136u, 87u,
- 104u, 240u, 54u, 105u,
- 74u, 129u, 255u, 149u,
- 80u, 88u, 151u, 222u,
- 162u, 200u, 119u, 44u,
- 126u, 150u, 64u, 186u,
- 95u, 121u, 133u, 255u,
- 95u, 155u, 121u, 138u,
- 156u, 165u, 152u, 102u,
- 216u, 237u, 165u, 190u,
- 93u, 47u, 136u, 99u,
- 1u, 132u, 202u, 96u,
- 192u, 174u, 117u, 185u,
- 135u, 130u, 87u, 161u,
- 202u, 123u, 60u, 95u,
- 49u, 33u, 92u, 1u,
- 189u, 60u, 102u, 4u,
- 180u, 255u, 113u, 173u,
- 69u, 165u, 143u, 53u,
- 166u, 151u, 10u, 131u,
- 48u, 151u, 97u, 187u,
- 207u, 129u, 172u, 192u,
- 255u, 185u, 108u, 138u,
- 8u, 47u, 222u, 128u,
- 137u, 70u, 145u, 140u,
- 255u, 140u, 173u, 156u,
- 99u, 151u, 79u, 95u,
- 134u, 152u, 67u, 124u,
- 169u, 115u, 106u, 255u,
- 79u, 74u, 91u, 153u,
- 185u, 153u, 102u, 140u,
- 148u, 123u, 133u, 67u,
- 1u, 215u, 102u, 115u,
- 75u, 77u, 104u, 89u,
- 69u, 88u, 117u, 185u,
- 83u, 81u, 76u, 86u,
- 134u, 162u, 93u, 99u,
- 204u, 202u, 130u, 130u,
- 25u, 105u, 102u, 170u,
- 0u, 152u, 114u, 125u,
- 77u, 115u, 82u, 8u,
- 146u, 59u, 237u, 127u,
- 137u, 96u, 0u, 178u,
- 116u, 102u, 79u, 41u,
- 131u, 119u, 171u, 124u,
- 70u, 159u, 255u, 168u,
- 100u, 177u, 161u, 158u,
- 82u, 125u, 182u, 129u,
- 173u, 132u, 207u, 255u,
- 169u, 101u, 61u, 186u,
- 17u, 109u, 186u, 233u,
- 149u, 100u, 84u, 127u,
- 113u, 148u, 255u, 100u,
- 101u, 147u, 70u, 99u,
- 154u, 143u, 14u, 201u,
- 61u, 125u, 85u, 128u,
- 214u, 236u, 239u, 165u,
- 60u, 58u, 64u, 85u,
- 161u, 96u, 236u, 84u,
- 255u, 115u, 86u, 146u,
- 31u, 103u, 69u, 116u,
- 147u, 254u, 26u, 137u,
- 101u, 172u, 60u, 255u,
- 143u, 203u, 167u, 133u,
- 240u, 20u, 175u, 65u,
- 119u, 155u, 59u, 52u,
- 11u, 143u, 138u, 211u,
- 243u, 1u, 85u, 27u,
- 138u, 156u, 190u, 139u,
- 93u, 85u, 94u, 108u,
- 146u, 90u, 172u, 23u,
- 139u, 234u, 79u, 255u,
- 123u, 124u, 80u, 101u,
- 214u, 166u, 69u, 106u,
- 107u, 177u, 51u, 135u,
- 0u, 176u, 19u, 97u,
- 75u, 101u, 217u, 255u,
- 179u, 170u, 54u, 150u,
- 235u, 101u, 71u, 156u,
- 154u, 154u, 170u, 80u,
- 134u, 68u, 125u, 133u,
- 121u, 114u, 96u, 88u,
- 177u, 206u, 220u, 134u,
- 137u, 21u, 255u, 117u,
- 232u, 233u, 1u, 56u,
- 31u, 152u, 171u, 144u,
- 25u, 75u, 215u, 132u,
- 181u, 165u, 173u, 135u,
- 54u, 160u, 182u, 94u,
- 56u, 195u, 142u, 118u,
- 125u, 131u, 175u, 1u,
- 142u, 54u, 128u, 168u,
- 45u, 148u, 84u, 103u,
- 111u, 119u, 170u, 99u,
- 122u, 115u, 69u, 157u,
- 123u, 116u, 255u, 45u,
- 161u, 101u, 211u, 19u,
- 195u, 177u, 214u, 176u,
- 138u, 5u, 105u, 72u,
- 124u, 0u, 35u, 182u,
- 0u, 165u, 160u, 211u,
- 109u, 157u, 167u, 225u,
- 202u, 76u, 118u, 200u,
- 95u, 136u, 183u, 18u,
- 136u, 176u, 186u, 93u,
- 221u, 18u, 203u, 129u,
- 25u, 20u, 255u, 45u,
- 88u, 77u, 4u, 218u,
- 186u, 110u, 152u, 132u,
- 107u, 137u, 91u, 179u,
- 1u, 113u, 118u, 103u,
- 105u, 162u, 106u, 182u,
- 207u, 37u, 195u, 188u,
- 27u, 59u, 179u, 229u,
- 138u, 0u, 171u, 216u,
- 153u, 128u, 92u, 117u,
- 1u, 199u, 91u, 179u,
- 144u, 132u, 187u, 81u,
- 153u, 114u, 119u, 212u,
- 115u, 137u, 114u, 216u,
- 76u, 164u, 149u, 223u,
- 128u, 125u, 46u, 147u,
- 147u, 203u, 139u, 141u,
- 174u, 218u, 105u, 255u,
- 97u, 148u, 188u, 97u,
- 24u, 141u, 103u, 116u,
- 184u, 121u, 53u, 255u,
- 150u, 232u, 199u, 53u,
- 243u, 10u, 57u, 233u,
- 81u, 84u, 116u, 207u,
- 79u, 65u, 151u, 0u,
- 149u, 145u, 126u, 154u,
- 66u, 76u, 152u, 200u,
- 255u, 61u, 48u, 98u,
- 214u, 219u, 244u, 151u,
- 127u, 165u, 194u, 243u,
- 71u, 163u, 168u, 93u,
- 171u, 103u, 162u, 209u,
- 255u, 56u, 66u, 243u,
- 103u, 215u, 206u, 30u,
- 163u, 30u, 164u, 141u,
- 152u, 155u, 221u, 144u,
- 178u, 155u, 63u, 102u,
- 52u, 255u, 86u, 73u,
- 123u, 131u, 157u, 78u,
- 240u, 88u, 129u, 70u,
- 79u, 255u, 88u, 29u,
- 32u, 146u, 100u, 89u,
- 147u, 89u, 119u, 246u,
- 69u, 206u, 61u, 255u,
- 91u, 26u, 131u, 202u,
- 98u, 124u, 225u, 143u,
- 100u, 239u, 203u, 132u,
- 69u, 172u, 79u, 0u,
- 120u, 75u, 177u, 127u,
- 108u, 117u, 141u, 104u,
- 133u, 51u, 171u, 220u,
- 107u, 18u, 32u, 147u,
- 131u, 39u, 173u, 33u,
- 164u, 255u, 113u, 98u,
- 141u, 92u, 148u, 46u,
- 171u, 86u, 129u, 90u,
- 42u, 157u, 174u, 99u,
- 146u, 1u, 73u, 40u,
- 137u, 41u, 220u, 245u,
- 93u, 0u, 130u, 177u,
- 130u, 235u, 181u, 221u,
- 180u, 175u, 108u, 64u,
- 62u, 42u, 124u, 84u,
- 65u, 159u, 176u, 223u,
- 30u, 36u, 153u, 120u,
- 6u, 107u, 1u, 191u,
- 70u, 68u, 20u, 125u,
- 131u, 123u, 143u, 155u,
- 116u, 194u, 143u, 99u,
- 1u, 169u, 182u, 169u,
- 147u, 131u, 80u, 125u,
- 184u, 25u, 69u, 1u,
- 130u, 162u, 100u, 10u,
- 171u, 101u, 112u, 111u,
- 27u, 197u, 0u, 163u,
- 150u, 204u, 166u, 87u,
- 132u, 102u, 21u, 188u,
- 102u, 164u, 86u, 177u,
- 71u, 151u, 133u, 195u,
- 255u, 176u, 128u, 219u,
- 134u, 121u, 142u, 87u,
- 117u, 65u, 24u, 212u,
- 16u, 85u, 130u, 54u,
- 166u, 167u, 171u, 21u,
- 1u, 116u, 105u, 115u,
- 190u, 215u, 52u, 133u,
- 125u, 92u, 156u, 63u,
- 37u, 151u, 1u, 207u,
- 110u, 92u, 117u, 104u,
- 29u, 90u, 73u, 83u,
- 126u, 77u, 107u, 103u,
- 234u, 182u, 77u, 1u,
- 109u, 103u, 73u, 65u,
- 6u, 186u, 59u, 68u,
- 103u, 173u, 103u, 255u,
- 127u, 62u, 149u, 34u,
- 38u, 108u, 164u, 141u,
- 160u, 225u, 214u, 11u,
- 98u, 104u, 204u, 152u,
- 114u, 81u, 154u, 44u,
- 159u, 79u, 160u, 1u,
- 20u, 128u, 196u, 170u,
- 53u, 125u, 193u, 191u,
- 141u, 190u, 190u, 152u,
- 237u, 1u, 255u, 48u,
- 175u, 205u, 108u, 193u,
- 58u, 1u, 206u, 72u,
- 105u, 78u, 40u, 107u,
- 98u, 130u, 60u, 82u,
- 141u, 90u, 31u, 3u,
- 165u, 232u, 208u, 163u,
- 192u, 72u, 240u, 189u,
- 247u, 249u, 125u, 191u,
- 255u, 201u, 146u, 228u,
- 122u, 91u, 180u, 146u,
- 104u, 91u, 255u, 39u,
- 101u, 105u, 248u, 165u,
- 173u, 104u, 161u, 99u,
- 100u, 0u, 156u, 93u,
- 161u, 109u, 94u, 136u,
- 121u, 239u, 51u, 105u,
- 132u, 81u, 19u, 168u,
- 206u, 155u, 231u, 167u,
- 26u, 240u, 80u, 131u,
- 125u, 86u, 222u, 161u,
- 174u, 109u, 255u, 227u,
- 120u, 175u, 169u, 163u,
- 41u, 80u, 1u, 208u,
- 164u, 177u, 128u, 216u,
- 108u, 221u, 209u, 140u,
- 95u, 196u, 79u, 78u,
- 198u, 134u, 81u, 133u,
- 205u, 140u, 34u, 1u,
- 208u, 72u, 74u, 41u,
- 150u, 116u, 194u, 211u,
- 115u, 127u, 74u, 124u,
- 197u, 173u, 243u, 148u,
- 255u, 111u, 15u, 189u,
- 186u, 65u, 172u, 24u,
- 84u, 123u, 216u, 169u,
- 193u, 108u, 74u, 103u,
- 63u, 183u, 1u, 39u,
- 153u, 115u, 164u, 150u,
- 0u, 163u, 72u, 162u,
- 101u, 87u, 128u, 190u,
- 129u, 143u, 174u, 47u,
- 158u, 0u, 169u, 47u,
- 170u, 175u, 188u, 190u,
- 86u, 114u, 181u, 107u,
- 119u, 167u, 156u, 180u,
- 154u, 196u, 142u, 255u,
- 89u, 129u, 117u, 158u,
- 188u, 160u, 133u, 124u,
- 133u, 137u, 117u, 176u,
- 10u, 168u, 153u, 240u,
- 117u, 144u, 82u, 15u,
- 242u, 67u, 68u, 77u,
- 28u, 70u, 98u, 255u,
- 118u, 177u, 156u, 182u,
- 200u, 122u, 203u, 101u,
- 135u, 154u, 80u, 118u,
- 47u, 157u, 1u, 76u,
- 165u, 142u, 124u, 210u,
- 153u, 115u, 79u, 56u,
- 140u, 182u, 238u, 88u,
- 182u, 173u, 255u, 233u,
- 86u, 255u, 136u, 160u,
- 222u, 161u, 119u, 193u,
- 67u, 85u, 213u, 160u,
- 184u, 144u, 100u, 103u,
- 195u, 123u, 111u, 171u,
- 93u, 188u, 124u, 145u,
- 63u, 62u, 148u, 0u,
- 107u, 169u, 104u, 206u,
- 78u, 228u, 61u, 145u,
- 208u, 19u, 174u, 31u,
- 67u, 255u, 24u, 49u,
- 34u, 51u, 54u, 35u,
- 175u, 48u, 121u, 255u,
- 169u, 70u, 207u, 159u,
- 59u, 137u, 93u, 143u,
- 235u, 114u, 109u, 170u,
- 43u, 143u, 218u, 160u,
- 84u, 49u, 182u, 105u,
- 254u, 175u, 142u, 188u,
- 184u, 93u, 255u, 32u,
- 145u, 195u, 141u, 229u,
- 199u, 104u, 179u, 255u,
- 59u, 133u, 164u, 193u,
- 206u, 170u, 56u, 53u,
- 35u, 73u, 98u, 136u,
- 151u, 160u, 119u, 255u,
- 92u, 121u, 162u, 82u,
- 132u, 176u, 74u, 175u,
- 186u, 226u, 193u, 125u,
- 170u, 141u, 118u, 155u,
- 183u, 52u, 113u, 192u,
- 98u, 255u, 135u, 140u,
- 107u, 168u, 107u, 59u,
- 182u, 102u, 141u, 176u,
- 96u, 107u, 173u, 211u,
- 173u, 203u, 179u, 1u,
- 164u, 152u, 197u, 172u,
- 85u, 255u, 88u, 99u,
- 144u, 66u, 67u, 222u,
- 51u, 141u, 69u, 44u,
- 64u, 167u, 84u, 94u,
- 232u, 90u, 255u, 232u,
- 83u, 138u, 146u, 64u,
- 177u, 64u, 46u, 138u,
- 255u, 210u, 179u, 109u,
- 209u, 70u, 143u, 130u,
- 190u, 201u, 151u, 236u,
- 72u, 174u, 139u, 110u,
- 127u, 108u, 176u, 162u,
- 116u, 66u, 129u, 1u,
- 86u, 153u, 168u, 212u,
- 189u, 153u, 188u, 127u,
- 120u, 129u, 141u, 170u,
- 69u, 138u, 136u, 145u,
- 104u, 176u, 149u, 255u,
- 138u, 165u, 63u, 139u,
- 77u, 165u, 164u, 44u,
- 132u, 147u, 110u, 185u,
- 142u, 131u, 142u, 119u,
- 31u, 95u, 123u, 255u,
- 79u, 82u, 161u, 14u,
- 40u, 255u, 188u, 97u,
- 156u, 223u, 98u, 207u,
- 131u, 61u, 133u, 127u,
- 174u, 224u, 144u, 7u,
- 239u, 165u, 111u, 187u,
- 176u, 76u, 87u, 104u,
- 81u, 77u, 1u, 148u,
- 85u, 255u, 57u, 83u,
- 250u, 204u, 140u, 52u,
- 105u, 193u, 144u, 188u,
- 193u, 111u, 22u, 148u,
- 255u, 163u, 169u, 106u,
- 83u, 153u, 98u, 78u,
- 66u, 152u, 212u, 69u,
- 177u, 108u, 58u, 65u,
- 71u, 255u, 110u, 157u,
- 252u, 125u, 164u, 206u,
- 165u, 164u, 177u, 108u,
- 117u, 181u, 30u, 125u,
- 161u, 201u, 22u, 148u,
- 83u, 137u, 145u, 159u,
- 182u, 92u, 206u, 255u,
- 82u, 105u, 171u, 66u,
- 180u, 137u, 124u, 217u,
- 136u, 147u, 95u, 103u,
- 1u, 4u, 177u, 122u,
- 113u, 180u, 114u, 155u,
- 55u, 91u, 118u, 141u,
- 80u, 151u, 63u, 131u,
- 59u, 91u, 173u, 104u,
- 134u, 116u, 1u, 105u,
- 179u, 156u, 12u, 47u,
- 182u, 170u, 216u, 176u,
- 1u, 44u, 46u, 123u,
- 100u, 11u, 113u, 160u,
- 140u, 1u, 88u, 124u,
- 210u, 143u, 105u, 225u,
- 61u, 123u, 122u, 53u,
- 167u, 175u, 175u, 23u,
- 255u, 119u, 100u, 173u,
- 97u, 185u, 145u, 57u,
- 187u, 165u, 62u, 165u,
- 63u, 135u, 94u, 136u,
- 255u, 110u, 163u, 104u,
- 106u, 36u, 51u, 207u,
- 105u, 104u, 154u, 160u,
- 154u, 139u, 165u, 220u,
- 138u, 223u, 105u, 109u,
- 205u, 124u, 101u, 7u,
- 72u, 24u, 107u, 170u,
- 1u, 254u, 117u, 87u,
- 216u, 145u, 198u, 255u,
- 80u, 70u, 90u, 53u,
- 144u, 31u, 207u, 88u,
- 177u, 129u, 129u, 145u,
- 124u, 203u, 89u, 153u,
- 98u, 215u, 143u, 188u,
- 221u, 132u, 191u, 205u,
- 49u, 104u, 116u, 255u,
- 0u, 96u, 253u, 189u,
- 69u, 50u, 164u, 69u,
- 36u, 170u, 227u, 236u,
- 216u, 215u, 124u, 35u,
- 91u, 241u, 134u, 131u,
- 115u, 162u, 164u, 116u,
- 255u, 162u, 56u, 134u,
- 161u, 67u, 189u, 146u,
- 255u, 169u, 170u, 141u,
- 67u, 169u, 83u, 37u,
- 120u, 185u, 178u, 153u,
- 54u, 229u, 197u, 152u,
- 165u, 111u, 127u, 54u,
- 81u, 173u, 129u, 162u,
- 1u, 131u, 91u, 92u,
- 77u, 153u, 194u, 119u,
- 191u, 221u, 165u, 75u,
- 51u, 128u, 138u, 64u,
- 225u, 186u, 114u, 255u,
- 30u, 56u, 243u, 214u,
- 53u, 255u, 122u, 124u,
- 161u, 248u, 186u, 102u,
- 151u, 118u, 51u, 141u,
- 12u, 96u, 128u, 169u,
- 49u, 169u, 124u, 255u,
- 192u, 175u, 191u, 87u,
- 158u, 47u, 90u, 106u,
- 138u, 169u, 193u, 125u,
- 100u, 184u, 1u, 113u,
- 120u, 180u, 110u, 60u,
- 70u, 168u, 214u, 127u,
- 24u, 18u, 159u, 115u,
- 79u, 219u, 170u, 137u,
- 174u, 111u, 199u, 88u,
- 146u, 255u, 154u, 98u,
- 127u, 166u, 119u, 144u,
- 221u, 88u, 78u, 170u,
- 161u, 141u, 213u, 142u,
- 145u, 68u, 1u, 183u,
- 81u, 91u, 213u, 89u,
- 105u, 138u, 85u, 130u,
- 108u, 30u, 130u, 178u,
- 206u, 100u, 0u, 105u,
- 146u, 183u, 145u, 152u,
- 88u, 84u, 167u, 183u,
- 113u, 142u, 255u, 133u,
- 125u, 94u, 166u, 179u,
- 125u, 239u, 206u, 136u,
- 108u, 255u, 140u, 161u,
- 142u, 70u, 133u, 190u,
- 166u, 157u, 118u, 164u,
- 92u, 67u, 145u, 109u,
- 233u, 58u, 105u, 141u,
- 91u, 55u, 126u, 148u,
- 206u, 141u, 255u, 128u,
- 174u, 117u, 227u, 105u,
- 98u, 150u, 117u, 255u,
- 58u, 141u, 106u, 64u,
- 149u, 104u, 149u, 74u,
- 169u, 148u, 105u, 137u,
- 93u, 1u, 32u, 143u,
- 78u, 62u, 207u, 4u,
- 238u, 193u, 51u, 192u,
- 47u, 72u, 199u, 67u,
- 95u, 150u, 144u, 134u,
- 193u, 210u, 219u, 118u,
- 161u, 115u, 110u, 12u,
- 255u, 116u, 115u, 136u,
- 107u, 122u, 10u, 224u,
- 188u, 249u, 173u, 213u,
- 157u, 122u, 255u, 115u,
- 135u, 47u, 127u, 90u,
- 148u, 53u, 230u, 104u,
- 112u, 100u, 102u, 1u,
- 75u, 175u, 174u, 76u,
- 218u, 175u, 128u, 97u,
- 1u, 50u, 86u, 143u,
- 200u, 166u, 132u, 113u,
- 104u, 115u, 103u, 170u,
- 150u, 136u, 49u, 95u,
- 33u, 126u, 185u, 255u,
- 138u, 82u, 134u, 232u,
- 173u, 135u, 216u, 237u,
- 224u, 92u, 221u, 134u,
- 101u, 131u, 163u, 89u,
- 62u, 143u, 83u, 46u,
- 1u, 105u, 142u, 192u,
- 77u, 218u, 150u, 229u,
- 219u, 145u, 167u, 114u,
- 103u, 206u, 188u, 1u,
- 122u, 22u, 130u, 135u,
- 74u, 75u, 81u, 129u,
- 108u, 144u, 77u, 141u,
- 194u, 38u, 127u, 107u,
- 140u, 133u, 0u, 149u,
- 41u, 69u, 219u, 80u,
- 115u, 142u, 47u, 255u,
- 4u, 58u, 161u, 157u,
- 156u, 126u, 155u, 153u,
- 22u, 94u, 36u, 178u,
- 124u, 248u, 96u, 175u,
- 191u, 158u, 1u, 168u,
- 79u, 144u, 195u, 164u,
- 174u, 104u, 98u, 123u,
- 10u, 123u, 126u, 177u,
- 0u, 127u, 188u, 65u,
- 109u, 136u, 167u, 121u,
- 49u, 183u, 133u, 177u,
- 19u, 170u, 255u, 198u,
- 78u, 50u, 101u, 215u,
- 3u, 94u, 216u, 146u,
- 144u, 204u, 212u, 23u,
- 116u, 173u, 121u, 96u,
- 173u, 142u, 201u, 48u,
- 100u, 246u, 36u, 65u,
- 108u, 0u, 246u, 43u,
- 214u, 91u, 255u, 193u,
- 177u, 135u, 166u, 105u,
- 146u, 157u, 144u, 59u,
- 164u, 139u, 127u, 175u,
- 209u, 142u, 138u, 135u,
- 20u, 70u, 224u, 255u,
- 174u, 82u, 126u, 181u,
- 145u, 136u, 126u, 11u,
- 36u, 80u, 138u, 173u,
- 247u, 112u, 202u, 24u,
- 156u, 1u, 167u, 210u,
- 99u, 88u, 21u, 53u,
- 48u, 207u, 173u, 200u,
- 138u, 1u, 103u, 185u,
- 116u, 104u, 181u, 162u,
- 139u, 156u, 119u, 125u,
- 84u, 151u, 20u, 23u,
- 1u, 146u, 168u, 9u,
- 159u, 178u, 19u, 138u,
- 45u, 94u, 229u, 174u,
- 73u, 255u, 122u, 150u,
- 120u, 209u, 158u, 34u,
- 138u, 118u, 96u, 104u,
- 193u, 159u, 86u, 193u,
- 146u, 187u, 132u, 217u,
- 3u, 169u, 65u, 56u,
- 35u, 83u, 81u, 98u,
- 183u, 0u, 80u, 147u,
- 23u, 222u, 137u, 187u,
- 164u, 211u, 174u, 74u,
- 30u, 0u, 239u, 92u,
- 212u, 226u, 70u, 188u,
- 1u, 100u, 83u, 165u,
- 84u, 175u, 156u, 90u,
- 119u, 199u, 111u, 230u,
- 173u, 137u, 37u, 4u,
- 90u, 97u, 255u, 202u,
- 140u, 89u, 103u, 154u,
- 151u, 159u, 152u, 172u,
- 163u, 191u, 41u, 124u,
- 138u, 122u, 57u, 166u,
- 136u, 40u, 183u, 136u,
- 156u, 175u, 180u, 67u,
- 255u, 125u, 141u, 157u,
- 21u, 125u, 1u, 186u,
- 51u, 121u, 219u, 162u,
- 178u, 61u, 99u, 187u,
- 54u, 65u, 247u, 200u,
- 1u, 151u, 157u, 125u,
- 167u, 73u, 252u, 103u,
- 115u, 134u, 201u, 177u,
- 177u, 133u, 73u, 242u,
- 151u, 221u, 121u, 67u,
- 249u, 135u, 255u, 177u,
- 21u, 28u, 200u, 118u,
- 196u, 129u, 82u, 130u,
- 161u, 128u, 198u, 6u,
- 154u, 195u, 188u, 131u,
- 113u, 61u, 8u, 170u,
- 66u, 1u, 129u, 129u,
- 114u, 83u, 15u, 195u,
- 123u, 1u, 156u, 132u,
- 77u, 101u, 146u, 74u,
- 148u, 153u, 126u, 103u,
- 153u, 30u, 204u, 83u,
- 132u, 109u, 127u, 0u,
- 95u, 104u, 95u, 230u,
- 189u, 104u, 115u, 65u,
- 216u, 105u, 182u, 221u,
- 182u, 136u, 87u, 119u,
- 155u, 163u, 57u, 118u,
- 74u, 160u, 1u, 20u,
- 255u, 140u, 158u, 167u,
- 29u, 138u, 46u, 168u,
- 214u, 111u, 145u, 208u,
- 181u, 95u, 14u, 77u,
- 13u, 25u, 105u, 1u,
- 106u, 36u, 170u, 65u,
- 102u, 237u, 165u, 131u,
- 77u, 153u, 46u, 152u,
- 99u, 114u, 199u, 108u,
- 160u, 44u, 226u, 132u,
- 60u, 148u, 189u, 104u,
- 179u, 21u, 1u, 201u,
- 171u, 255u, 173u, 184u,
- 126u, 206u, 119u, 132u,
- 155u, 94u, 147u, 124u,
- 87u, 156u, 150u, 152u,
- 255u, 239u, 149u, 230u,
- 79u, 181u, 158u, 6u,
- 179u, 201u, 108u, 223u,
- 146u, 162u, 119u, 92u,
- 219u, 95u, 142u, 141u,
- 142u, 55u, 63u, 144u,
- 42u, 76u, 233u, 85u,
- 235u, 150u, 255u, 105u,
- 68u, 131u, 102u, 168u,
- 215u, 132u, 132u, 194u,
- 107u, 150u, 139u, 115u,
- 255u, 98u, 85u, 115u,
- 221u, 153u, 191u, 129u,
- 204u, 93u, 167u, 187u,
- 1u, 98u, 249u, 166u,
- 181u, 117u, 54u, 108u,
- 104u, 118u, 142u, 156u,
- 49u, 167u, 67u, 131u,
- 183u, 161u, 0u, 214u,
- 82u, 154u, 122u, 129u,
- 64u, 68u, 94u, 95u,
- 113u, 33u, 110u, 0u,
- 177u, 160u, 123u, 94u,
- 167u, 114u, 108u, 137u,
- 153u, 103u, 170u, 156u,
- 66u, 49u, 80u, 69u,
- 159u, 153u, 194u, 101u,
- 255u, 164u, 179u, 210u,
- 101u, 130u, 200u, 1u,
- 74u, 201u, 162u, 197u,
- 244u, 184u, 54u, 160u,
- 144u, 217u, 82u, 174u,
- 158u, 255u, 132u, 169u,
- 71u, 140u, 161u, 151u,
- 149u, 155u, 103u, 145u,
- 71u, 195u, 73u, 58u,
- 43u, 114u, 88u, 238u,
- 109u, 20u, 44u, 1u,
- 123u, 134u, 169u, 141u,
- 161u, 46u, 181u, 175u,
- 113u, 217u, 139u, 43u,
- 41u, 211u, 46u, 82u,
- 203u, 95u, 152u, 197u,
- 1u, 37u, 122u, 241u,
- 61u, 169u, 121u, 54u,
- 156u, 143u, 146u, 79u,
- 50u, 114u, 123u, 96u,
- 121u, 119u, 91u, 255u,
- 92u, 228u, 119u, 86u,
- 112u, 160u, 76u, 97u,
- 68u, 88u, 195u, 99u,
- 131u, 16u, 95u, 255u,
- 139u, 92u, 53u, 127u,
- 104u, 157u, 128u, 166u,
- 236u, 141u, 77u, 137u,
- 91u, 43u, 1u, 170u,
- 77u, 140u, 127u, 0u,
- 184u, 106u, 190u, 129u,
- 29u, 175u, 178u, 165u,
- 135u, 126u, 90u, 199u,
- 230u, 61u, 248u, 218u,
- 138u, 147u, 88u, 255u,
- 61u, 3u, 74u, 119u,
- 191u, 106u, 56u, 8u,
- 197u, 135u, 139u, 196u,
- 118u, 176u, 9u, 255u,
- 174u, 94u, 200u, 152u,
- 41u, 199u, 193u, 22u,
- 62u, 255u, 56u, 65u,
- 192u, 142u, 115u, 143u,
- 51u, 79u, 163u, 154u,
- 48u, 111u, 95u, 193u,
- 121u, 146u, 117u, 53u,
- 255u, 160u, 96u, 106u,
- 43u, 86u, 31u, 89u,
- 103u, 94u, 109u, 181u,
- 66u, 109u, 109u, 243u,
- 135u, 44u, 108u, 92u,
- 247u, 222u, 23u, 199u,
- 255u, 32u, 103u, 31u,
- 138u, 127u, 0u, 176u,
- 79u, 93u, 55u, 21u,
- 174u, 57u, 254u, 37u,
- 87u, 158u, 90u, 137u,
- 182u, 204u, 65u, 183u,
- 143u, 92u, 129u, 254u,
- 255u, 145u, 126u, 105u,
- 134u, 81u, 194u, 117u,
- 102u, 252u, 206u, 169u,
- 111u, 208u, 139u, 64u,
- 94u, 104u, 106u, 220u,
- 1u, 42u, 161u, 70u,
- 201u, 85u, 162u, 255u,
- 56u, 210u, 163u, 211u,
- 205u, 169u, 154u, 170u,
- 41u, 239u, 172u, 74u,
- 107u, 105u, 153u, 122u,
- 197u, 146u, 162u, 169u,
- 60u, 134u, 143u, 181u,
- 173u, 100u, 1u, 212u,
- 183u, 109u, 114u, 55u,
- 201u, 126u, 153u, 227u,
- 153u, 222u, 146u, 93u,
- 246u, 119u, 1u, 119u,
- 125u, 74u, 202u, 199u,
- 208u, 1u, 57u, 125u,
- 14u, 105u, 103u, 50u,
- 234u, 119u, 4u, 142u,
- 210u, 54u, 144u, 93u,
- 40u, 129u, 113u, 83u,
- 120u, 79u, 134u, 8u,
- 0u, 199u, 75u, 113u,
- 255u, 137u, 196u, 132u,
- 116u, 141u, 103u, 155u,
- 158u, 128u, 164u, 111u,
- 46u, 184u, 184u, 120u,
- 96u, 205u, 174u, 203u,
- 158u, 177u, 180u, 1u,
- 119u, 52u, 108u, 188u,
- 91u, 47u, 254u, 251u,
- 67u, 157u, 125u, 165u,
- 255u, 39u, 88u, 201u,
- 173u, 121u, 159u, 168u,
- 239u, 164u, 142u, 109u,
- 178u, 198u, 126u, 64u,
- 112u, 92u, 95u, 194u,
- 71u, 124u, 89u, 60u,
- 53u, 241u, 91u, 0u,
- 51u, 145u, 43u, 155u,
- 134u, 71u, 19u, 88u,
- 34u, 119u, 166u, 0u,
- 90u, 177u, 77u, 81u,
- 193u, 58u, 97u, 163u,
- 88u, 138u, 214u, 129u,
- 92u, 165u, 79u, 1u,
- 100u, 195u, 132u, 147u,
- 188u, 159u, 150u, 84u,
- 165u, 173u, 95u, 82u,
- 232u, 198u, 112u, 178u,
- 50u, 1u, 86u, 159u,
- 166u, 134u, 236u, 241u,
- 52u, 226u, 70u, 235u,
- 198u, 165u, 28u, 244u,
- 255u, 141u, 217u, 227u,
- 203u, 246u, 142u, 157u,
- 170u, 145u, 130u, 114u,
- 158u, 112u, 153u, 104u,
- 130u, 135u, 98u, 255u,
- 182u, 153u, 157u, 212u,
- 190u, 205u, 255u, 163u,
- 221u, 174u, 205u, 98u,
- 8u, 93u, 14u, 242u,
- 190u, 128u, 68u, 192u,
- 4u, 132u, 149u, 71u,
- 1u, 101u, 167u, 114u,
- 183u, 168u, 211u, 252u,
- 137u, 210u, 1u, 73u,
- 154u, 151u, 90u, 12u,
- 50u, 209u, 195u, 203u,
- 237u, 212u, 188u, 199u,
- 0u, 118u, 53u, 84u,
- 86u, 147u, 192u, 139u,
- 90u, 95u, 96u, 188u,
- 88u, 112u, 165u, 130u,
- 167u, 88u, 203u, 172u,
- 85u, 143u, 255u, 193u,
- 100u, 85u, 171u, 118u,
- 52u, 215u, 76u, 92u,
- 90u, 150u, 1u, 90u,
- 166u, 108u, 200u, 57u,
- 186u, 124u, 143u, 20u,
- 136u, 107u, 37u, 192u,
- 116u, 152u, 175u, 100u,
- 226u, 115u, 93u, 255u,
- 106u, 157u, 182u, 233u,
- 238u, 116u, 134u, 83u,
- 31u, 58u, 129u, 175u,
- 107u, 68u, 168u, 160u,
- 79u, 141u, 105u, 63u,
- 206u, 255u, 92u, 146u,
- 123u, 154u, 219u, 117u,
- 61u, 109u, 122u, 71u,
- 145u, 123u, 153u, 157u,
- 120u, 255u, 17u, 145u,
- 154u, 124u, 82u, 214u,
- 133u, 142u, 156u, 52u,
- 255u, 227u, 11u, 115u,
- 109u, 157u, 190u, 87u,
- 115u, 156u, 197u, 255u,
- 72u, 139u, 152u, 120u,
- 121u, 239u, 80u, 3u,
- 107u, 60u, 137u, 17u,
- 205u, 175u, 110u, 74u,
- 248u, 40u, 212u, 255u,
- 73u, 197u, 20u, 140u,
- 47u, 147u, 188u, 55u,
- 77u, 238u, 3u, 157u,
- 74u, 128u, 68u, 57u,
- 155u, 212u, 140u, 92u,
- 101u, 63u, 161u, 255u,
- 111u, 0u, 162u, 27u,
- 114u, 192u, 55u, 155u,
- 167u, 64u, 111u, 106u,
- 13u, 98u, 101u, 110u,
- 134u, 49u, 184u, 186u,
- 195u, 99u, 172u, 255u,
- 1u, 88u, 117u, 77u,
- 223u, 147u, 101u, 128u,
- 220u, 219u, 70u, 20u,
- 227u, 187u, 7u, 228u,
- 51u, 46u, 64u, 9u,
- 1u, 76u, 114u, 151u,
- 153u, 100u, 83u, 226u,
- 31u, 166u, 255u, 105u,
- 136u, 110u, 125u, 208u,
- 29u, 181u, 83u, 20u,
- 57u, 54u, 20u, 176u,
- 78u, 223u, 159u, 2u,
- 255u, 85u, 113u, 204u,
- 218u, 97u, 103u, 238u,
- 170u, 236u, 115u, 209u,
- 186u, 102u, 130u, 166u,
- 111u, 134u, 126u, 189u,
- 151u, 135u, 20u, 1u,
- 167u, 93u, 222u, 61u,
- 193u, 170u, 110u, 173u,
- 150u, 211u, 255u, 138u,
- 175u, 66u, 93u, 127u,
- 178u, 212u, 1u, 208u,
- 104u, 245u, 209u, 145u,
- 193u, 145u, 64u, 190u,
- 11u, 36u, 242u, 242u,
- 54u, 108u, 35u, 169u,
- 39u, 206u, 124u, 101u,
- 142u, 126u, 97u, 73u,
- 172u, 107u, 1u, 144u,
- 149u, 86u, 99u, 60u,
- 149u, 143u, 76u, 1u,
- 123u, 175u, 245u, 24u,
- 49u, 118u, 23u, 149u,
- 94u, 46u, 188u, 255u,
- 149u, 106u, 67u, 130u,
- 147u, 163u, 71u, 54u,
- 110u, 223u, 121u, 23u,
- 49u, 158u, 198u, 138u,
- 165u, 185u, 161u, 145u,
- 149u, 86u, 67u, 39u,
- 1u, 190u, 129u, 145u,
- 152u, 181u, 144u, 181u,
- 181u, 170u, 108u, 193u,
- 236u, 119u, 180u, 255u,
- 148u, 141u, 192u, 147u,
- 168u, 108u, 150u, 31u,
- 153u, 84u, 157u, 204u,
- 140u, 101u, 176u, 158u,
- 172u, 44u, 104u, 255u,
- 130u, 91u, 90u, 101u,
- 122u, 109u, 88u, 116u,
- 96u, 151u, 102u, 131u,
- 236u, 186u, 135u, 255u,
- 93u, 75u, 14u, 255u,
- 106u, 155u, 156u, 72u,
- 195u, 73u, 159u, 75u,
- 134u, 171u, 70u, 202u,
- 140u, 125u, 137u, 94u,
- 212u, 120u, 138u, 117u,
- 151u, 255u, 218u, 119u,
- 239u, 231u, 50u, 218u,
- 212u, 110u, 213u, 49u,
- 154u, 101u, 181u, 1u,
- 136u, 185u, 148u, 53u,
- 193u, 198u, 144u, 224u,
- 240u, 158u, 146u, 87u,
- 109u, 131u, 59u, 74u,
- 100u, 158u, 95u, 109u,
- 85u, 1u, 162u, 48u,
- 127u, 167u, 210u, 115u,
- 59u, 213u, 36u, 134u,
- 71u, 166u, 105u, 255u,
- 152u, 95u, 152u, 126u,
- 143u, 93u, 147u, 63u,
- 103u, 123u, 1u, 74u,
- 8u, 135u, 122u, 61u,
- 144u, 116u, 113u, 45u,
- 123u, 33u, 182u, 181u,
- 186u, 202u, 66u, 255u,
- 55u, 106u, 166u, 245u,
- 99u, 156u, 105u, 161u,
- 176u, 148u, 48u, 149u,
- 129u, 233u, 195u, 213u,
- 200u, 60u, 32u, 187u,
- 1u, 155u, 196u, 131u,
- 170u, 32u, 126u, 208u,
- 161u, 87u, 235u, 94u,
- 1u, 78u, 172u, 123u,
- 135u, 179u, 174u, 143u,
- 86u, 150u, 87u, 177u,
- 74u, 85u, 255u, 129u,
- 41u, 24u, 134u, 180u,
- 88u, 35u, 62u, 124u,
- 108u, 76u, 179u, 112u,
- 116u, 151u, 100u, 139u,
- 143u, 140u, 151u, 142u,
- 82u, 152u, 87u, 1u,
- 103u, 214u, 196u, 214u,
- 1u, 162u, 185u, 62u,
- 221u, 177u, 140u, 238u,
- 142u, 67u, 178u, 246u,
- 25u, 233u, 255u, 227u,
- 153u, 127u, 55u, 168u,
- 132u, 74u, 164u, 196u,
- 132u, 197u, 229u, 205u,
- 179u, 118u, 173u, 71u,
- 67u, 77u, 18u, 72u,
- 102u, 135u, 124u, 93u,
- 255u, 79u, 82u, 140u,
- 66u, 228u, 42u, 173u,
- 123u, 202u, 103u, 255u,
- 65u, 51u, 185u, 107u,
- 52u, 166u, 66u, 133u,
- 92u, 255u, 225u, 146u,
- 164u, 106u, 147u, 16u,
- 195u, 150u, 147u, 163u,
- 151u, 125u, 117u, 66u,
- 126u, 134u, 145u, 51u,
- 255u, 198u, 20u, 224u,
- 70u, 227u, 116u, 151u,
- 191u, 172u, 187u, 95u,
- 181u, 181u, 73u, 137u,
- 139u, 255u, 122u, 171u,
- 121u, 173u, 67u, 181u,
- 70u, 20u, 138u, 51u,
- 62u, 86u, 109u, 84u,
- 107u, 146u, 109u, 1u,
- 74u, 140u, 7u, 93u,
- 42u, 227u, 111u, 154u,
- 28u, 149u, 83u, 230u,
- 85u, 240u, 108u, 130u,
- 80u, 54u, 255u, 94u,
- 169u, 131u, 164u, 148u,
- 182u, 144u, 204u, 64u,
- 157u, 172u, 212u, 255u,
- 197u, 81u, 78u, 194u,
- 138u, 170u, 128u, 123u,
- 31u, 89u, 104u, 211u,
- 33u, 6u, 109u, 7u,
- 227u, 116u, 6u, 113u,
- 155u, 1u, 244u, 131u,
- 134u, 101u, 49u, 130u,
- 145u, 255u, 182u, 139u,
- 83u, 161u, 175u, 183u,
- 189u, 108u, 158u, 145u,
- 111u, 174u, 122u, 74u,
- 177u, 153u, 114u, 95u,
- 96u, 195u, 170u, 202u,
- 176u, 144u, 255u, 111u,
- 210u, 146u, 227u, 205u,
- 198u, 246u, 97u, 171u,
- 143u, 188u, 181u, 131u,
- 0u, 127u, 119u, 70u,
- 117u, 119u, 119u, 156u,
- 139u, 136u, 201u, 1u,
- 213u, 176u, 142u, 32u,
- 219u, 103u, 163u, 110u,
- 166u, 76u, 135u, 33u,
- 186u, 65u, 57u, 191u,
- 115u, 146u, 112u, 58u,
- 108u, 166u, 1u, 110u,
- 41u, 78u, 189u, 69u,
- 125u, 198u, 1u, 41u,
- 22u, 179u, 180u, 103u,
- 69u, 117u, 7u, 70u,
- 171u, 115u, 107u, 109u,
- 103u, 123u, 183u, 73u,
- 66u, 255u, 121u, 225u,
- 176u, 186u, 118u, 126u,
- 103u, 119u, 113u, 145u,
- 186u, 144u, 138u, 225u,
- 0u, 71u, 90u, 129u,
- 52u, 87u, 102u, 196u,
- 71u, 64u, 127u, 173u,
- 24u, 204u, 107u, 152u,
- 24u, 100u, 176u, 255u,
- 134u, 85u, 139u, 94u,
- 190u, 99u, 154u, 219u,
- 90u, 137u, 204u, 0u,
- 231u, 114u, 63u, 127u,
- 99u, 12u, 249u, 27u,
- 155u, 168u, 164u, 190u,
- 84u, 214u, 155u, 115u,
- 122u, 163u, 109u, 228u,
- 1u, 87u, 164u, 130u,
- 178u, 69u, 28u, 69u,
- 101u, 129u, 1u, 229u,
- 122u, 50u, 237u, 27u,
- 78u, 82u, 7u, 195u,
- 84u, 177u, 175u, 137u,
- 193u, 174u, 80u, 58u,
- 255u, 78u, 84u, 224u,
- 232u, 183u, 73u, 20u,
- 121u, 199u, 218u, 255u,
- 129u, 116u, 29u, 175u,
- 189u, 116u, 126u, 180u,
- 164u, 132u, 106u, 243u,
- 123u, 107u, 109u, 160u,
- 147u, 83u, 89u, 255u,
- 249u, 100u, 68u, 114u,
- 98u, 93u, 114u, 85u,
- 246u, 116u, 203u, 221u,
- 235u, 143u, 117u, 111u,
- 0u, 60u, 172u, 92u,
- 128u, 124u, 179u, 175u,
- 145u, 74u, 86u, 118u,
- 111u, 143u, 162u, 184u,
- 0u, 144u, 128u, 4u,
- 180u, 203u, 208u, 101u,
- 122u, 135u, 211u, 168u,
- 115u, 188u, 189u, 125u,
- 1u, 15u, 176u, 98u,
- 192u, 147u, 101u, 110u,
- 92u, 98u, 139u, 107u,
- 149u, 121u, 202u, 119u,
- 126u, 116u, 96u, 120u,
- 124u, 123u, 105u, 255u,
- 76u, 221u, 111u, 241u,
- 13u, 234u, 36u, 33u,
- 121u, 85u, 56u, 204u,
- 72u, 170u, 116u, 255u,
- 159u, 96u, 125u, 115u,
- 255u, 117u, 102u, 212u,
- 140u, 107u, 102u, 100u,
- 110u, 119u, 83u, 53u,
- 1u, 112u, 87u, 46u,
- 73u, 136u, 190u, 52u,
- 116u, 162u, 173u, 145u,
- 113u, 57u, 54u, 234u,
- 192u, 16u, 138u, 48u,
- 63u, 81u, 122u, 179u,
- 126u, 227u, 199u, 165u,
- 233u, 14u, 255u, 221u,
- 36u, 12u, 68u, 188u,
- 7u, 216u, 116u, 132u,
- 255u, 192u, 79u, 87u,
- 104u, 152u, 215u, 97u,
- 218u, 114u, 93u, 93u,
- 123u, 1u, 133u, 118u,
- 165u, 140u, 115u, 121u,
- 167u, 66u, 168u, 128u,
- 142u, 79u, 116u, 1u,
- 106u, 105u, 106u, 24u,
- 81u, 145u, 53u, 147u,
- 99u, 159u, 155u, 126u,
- 101u, 26u, 96u, 116u,
- 147u, 142u, 106u, 255u,
- 140u, 77u, 88u, 134u,
- 80u, 171u, 3u, 53u,
- 36u, 193u, 122u, 148u,
- 64u, 121u, 255u, 87u,
- 101u, 19u, 90u, 235u,
- 225u, 33u, 97u, 76u,
- 31u, 92u, 244u, 68u,
- 143u, 52u, 1u, 148u,
- 221u, 156u, 223u, 162u,
- 129u, 162u, 46u, 111u,
- 144u, 112u, 91u, 61u,
- 129u, 121u, 7u, 151u,
- 135u, 115u, 186u, 102u,
- 49u, 99u, 255u, 147u,
- 57u, 196u, 174u, 137u,
- 115u, 206u, 255u, 45u,
- 133u, 84u, 90u, 187u,
- 105u, 225u, 191u, 111u,
- 174u, 115u, 162u, 55u,
- 98u, 178u, 35u, 111u,
- 100u, 156u, 141u, 95u,
- 57u, 196u, 53u, 1u,
- 112u, 118u, 255u, 245u,
- 103u, 61u, 166u, 65u,
- 185u, 98u, 172u, 112u,
- 144u, 142u, 151u, 181u,
- 164u, 216u, 32u, 140u,
- 127u, 101u, 18u, 207u,
- 14u, 84u, 255u, 167u,
- 26u, 137u, 229u, 150u,
- 220u, 20u, 29u, 191u,
- 139u, 119u, 45u, 187u,
- 99u, 85u, 25u, 193u,
- 16u, 101u, 202u, 1u,
- 167u, 255u, 115u, 134u,
- 129u, 71u, 144u, 101u,
- 108u, 124u, 131u, 116u,
- 149u, 57u, 125u, 173u,
- 130u, 182u, 83u, 160u,
- 56u, 216u, 179u, 66u,
- 149u, 85u, 0u, 108u,
- 59u, 127u, 151u, 196u,
- 209u, 70u, 192u, 42u,
- 67u, 1u, 113u, 101u,
- 234u, 141u, 238u, 85u,
- 115u, 40u, 218u, 94u,
- 132u, 248u, 39u, 128u,
- 196u, 251u, 110u, 172u,
- 100u, 151u, 36u, 255u,
- 32u, 54u, 154u, 120u,
- 181u, 120u, 65u, 172u,
- 54u, 255u, 93u, 164u,
- 192u, 130u, 102u, 181u,
- 100u, 146u, 139u, 153u,
- 173u, 84u, 189u, 158u,
- 255u, 59u, 131u, 117u,
- 109u, 131u, 255u, 51u,
- 177u, 230u, 100u, 205u,
- 187u, 181u, 122u, 175u,
- 118u, 110u, 1u, 203u,
- 132u, 123u, 160u, 137u,
- 80u, 207u, 58u, 34u,
- 146u, 136u, 216u, 7u,
- 129u, 116u, 255u, 12u,
- 49u, 184u, 39u, 168u,
- 131u, 138u, 194u, 155u,
- 172u, 24u, 199u, 181u,
- 41u, 222u, 49u, 79u,
- 144u, 119u, 140u, 46u,
- 141u, 255u, 145u, 32u,
- 146u, 93u, 69u, 240u,
- 91u, 184u, 75u, 51u,
- 136u, 95u, 165u, 65u,
- 87u, 75u, 255u, 132u,
- 60u, 190u, 1u, 176u,
- 81u, 158u, 100u, 179u,
- 49u, 195u, 57u, 183u,
- 4u, 156u, 4u, 160u,
- 227u, 67u, 255u, 165u,
- 50u, 138u, 86u, 213u,
- 185u, 23u, 93u, 174u,
- 169u, 101u, 120u, 53u,
- 164u, 112u, 195u, 91u,
- 110u, 178u, 48u, 92u,
- 111u, 210u, 196u, 77u,
- 255u, 170u, 122u, 79u,
- 84u, 120u, 87u, 131u,
- 94u, 116u, 142u, 111u,
- 143u, 143u, 93u, 210u,
- 86u, 135u, 103u, 255u,
- 26u, 199u, 118u, 1u,
- 66u, 151u, 108u, 145u,
- 106u, 144u, 55u, 112u,
- 178u, 80u, 132u, 107u,
- 201u, 177u, 66u, 195u,
- 134u, 105u, 4u, 186u,
- 227u, 172u, 78u, 123u,
- 96u, 131u, 1u, 120u,
- 201u, 120u, 95u, 158u,
- 45u, 102u, 111u, 132u,
- 150u, 61u, 195u, 85u,
- 154u, 133u, 255u, 177u,
- 139u, 99u, 138u, 134u,
- 111u, 81u, 153u, 111u,
- 255u, 165u, 51u, 183u,
- 165u, 205u, 227u, 80u,
- 238u, 61u, 220u, 190u,
- 1u, 123u, 44u, 173u,
- 219u, 21u, 221u, 163u,
- 135u, 96u, 251u, 62u,
- 180u, 165u, 53u, 97u,
- 76u, 129u, 255u, 124u,
- 156u, 167u, 89u, 129u,
- 49u, 152u, 227u, 182u,
- 230u, 255u, 135u, 122u,
- 50u, 152u, 100u, 142u,
- 215u, 122u, 186u, 208u,
- 189u, 20u, 154u, 134u,
- 131u, 123u, 178u, 1u,
- 229u, 110u, 149u, 1u,
- 106u, 184u, 49u, 112u,
- 11u, 93u, 95u, 107u,
- 126u, 148u, 76u, 138u,
- 84u, 55u, 206u, 80u,
- 118u, 132u, 8u, 145u,
- 104u, 255u, 86u, 84u,
- 0u, 240u, 161u, 88u,
- 103u, 161u, 129u, 102u,
- 44u, 173u, 243u, 136u,
- 104u, 142u, 59u, 250u,
- 126u, 189u, 202u, 185u,
- 142u, 111u, 167u, 117u,
- 183u, 150u, 179u, 161u,
- 145u, 106u, 166u, 0u,
- 98u, 77u, 0u, 211u,
- 109u, 159u, 99u, 11u,
- 140u, 105u, 132u, 50u,
- 127u, 83u, 147u, 161u,
- 234u, 117u, 104u, 98u,
- 149u, 123u, 244u, 26u,
- 46u, 160u, 189u, 117u,
- 176u, 212u, 255u, 168u,
- 132u, 140u, 164u, 141u,
- 64u, 97u, 40u, 1u,
- 100u, 159u, 166u, 97u,
- 116u, 171u, 13u, 78u,
- 147u, 83u, 198u, 158u,
- 89u, 144u, 198u, 105u,
- 68u, 151u, 170u, 86u,
- 68u, 1u, 226u, 149u,
- 120u, 188u, 146u, 170u,
- 71u, 110u, 255u, 51u,
- 158u, 148u, 169u, 229u,
- 86u, 185u, 202u, 177u,
- 110u, 144u, 40u, 60u,
- 134u, 198u, 105u, 100u,
- 122u, 107u, 53u, 142u,
- 1u, 14u, 77u, 223u,
- 127u, 70u, 113u, 82u,
- 1u, 99u, 109u, 34u,
- 214u, 151u, 59u, 142u,
- 10u, 133u, 137u, 181u,
- 198u, 137u, 16u, 25u,
- 130u, 98u, 230u, 87u,
- 173u, 255u, 126u, 94u,
- 170u, 27u, 163u, 172u,
- 38u, 165u, 157u, 126u,
- 48u, 68u, 102u, 55u,
- 127u, 166u, 1u, 255u,
- 203u, 86u, 76u, 195u,
- 204u, 164u, 138u, 27u,
- 17u, 204u, 30u, 114u,
- 255u, 158u, 53u, 175u,
- 3u, 106u, 245u, 75u,
- 1u, 54u, 201u, 38u,
- 128u, 38u, 148u, 152u,
- 171u, 153u, 91u, 186u,
- 87u, 119u, 105u, 164u,
- 163u, 121u, 112u, 108u,
- 146u, 147u, 76u, 255u,
- 87u, 164u, 157u, 81u,
- 123u, 43u, 155u, 88u,
- 125u, 172u, 189u, 255u,
- 182u, 175u, 114u, 140u,
- 153u, 64u, 161u, 85u,
- 137u, 90u, 121u, 37u,
- 255u, 145u, 147u, 118u,
- 157u, 69u, 114u, 207u,
- 7u, 160u, 208u, 90u,
- 107u, 243u, 223u, 10u,
- 69u, 212u, 127u, 203u,
- 92u, 228u, 140u, 160u,
- 212u, 82u, 10u, 185u,
- 98u, 187u, 1u, 125u,
- 185u, 218u, 148u, 203u,
- 189u, 81u, 225u, 100u,
- 131u, 1u, 243u, 170u,
- 165u, 216u, 205u, 212u,
- 146u, 83u, 199u, 176u,
- 200u, 133u, 65u, 103u,
- 65u, 255u, 160u, 106u,
- 177u, 109u, 121u, 103u,
- 187u, 127u, 73u, 136u,
- 137u, 175u, 165u, 113u,
- 49u, 151u, 192u, 70u,
- 129u, 142u, 43u, 0u,
- 103u, 165u, 67u, 117u,
- 155u, 79u, 255u, 231u,
- 120u, 162u, 167u, 119u,
- 90u, 166u, 177u, 223u,
- 137u, 129u, 79u, 158u,
- 40u, 143u, 119u, 125u,
- 168u, 175u, 137u, 116u,
- 1u, 145u, 101u, 171u,
- 60u, 221u, 45u, 194u,
- 204u, 124u, 255u, 175u,
- 177u, 58u, 140u, 98u,
- 251u, 171u, 140u, 199u,
- 117u, 191u, 190u, 158u,
- 118u, 76u, 111u, 189u,
- 145u, 0u, 159u, 46u,
- 189u, 182u, 162u, 215u,
- 104u, 65u, 79u, 65u,
- 195u, 45u, 19u, 144u,
- 110u, 242u, 215u, 140u,
- 255u, 165u, 48u, 180u,
- 110u, 58u, 98u, 163u,
- 146u, 47u, 96u, 80u,
- 1u, 165u, 146u, 72u,
- 216u, 85u, 137u, 67u,
- 171u, 97u, 73u, 83u,
- 84u, 120u, 107u, 151u,
- 239u, 255u, 196u, 65u,
- 85u, 145u, 78u, 222u,
- 0u, 145u, 135u, 92u,
- 61u, 126u, 111u, 54u,
- 179u, 188u, 143u, 154u,
- 75u, 81u, 166u, 105u,
- 106u, 53u, 61u, 42u,
- 133u, 103u, 102u, 30u,
- 172u, 255u, 160u, 61u,
- 56u, 97u, 242u, 102u,
- 169u, 180u, 55u, 92u,
- 35u, 184u, 118u, 190u,
- 198u, 169u, 92u, 130u,
- 118u, 246u, 255u, 182u,
- 91u, 58u, 78u, 1u,
- 110u, 48u, 58u, 219u,
- 81u, 179u, 104u, 116u,
- 207u, 163u, 175u, 132u,
- 60u, 100u, 143u, 160u,
- 86u, 194u, 188u, 155u,
- 1u, 52u, 139u, 79u,
- 76u, 174u, 107u, 108u,
- 119u, 124u, 144u, 71u,
- 227u, 48u, 197u, 229u,
- 205u, 146u, 100u, 255u,
- 209u, 196u, 6u, 61u,
- 75u, 144u, 140u, 188u,
- 125u, 183u, 93u, 122u,
- 81u, 120u, 173u, 116u,
- 187u, 117u, 151u, 1u,
- 221u, 133u, 124u, 109u,
- 145u, 182u, 103u, 171u,
- 91u, 198u, 109u, 74u,
- 0u, 164u, 64u, 236u,
- 123u, 113u, 127u, 116u,
- 193u, 255u, 202u, 140u,
- 155u, 144u, 197u, 169u,
- 78u, 133u, 83u, 128u,
- 252u, 71u, 207u, 77u,
- 128u, 104u, 130u, 255u,
- 139u, 127u, 137u, 127u,
- 34u, 84u, 233u, 63u,
- 3u, 121u, 104u, 59u,
- 67u, 144u, 34u, 148u,
- 108u, 1u, 147u, 228u,
- 168u, 98u, 122u, 7u,
- 183u, 91u, 72u, 41u,
- 126u, 108u, 1u, 179u,
- 82u, 200u, 86u, 42u,
- 165u, 255u, 27u, 35u,
- 222u, 204u, 174u, 92u,
- 113u, 190u, 148u, 148u,
- 137u, 42u, 114u, 156u,
- 65u, 208u, 93u, 255u,
- 66u, 233u, 152u, 175u,
- 130u, 97u, 101u, 164u,
- 195u, 63u, 162u, 147u,
- 76u, 156u, 1u, 174u,
- 188u, 130u, 148u, 255u,
- 197u, 156u, 154u, 24u,
- 74u, 97u, 190u, 173u,
- 85u, 197u, 152u, 21u,
- 142u, 248u, 54u, 135u,
- 228u, 169u, 154u, 141u,
- 41u, 123u, 135u, 131u,
- 41u, 39u, 0u, 195u,
- 37u, 255u, 93u, 108u,
- 160u, 78u, 94u, 86u,
- 43u, 139u, 144u, 134u,
- 175u, 195u, 102u, 211u,
- 55u, 118u, 18u, 176u,
- 76u, 170u, 69u, 184u,
- 0u, 101u, 33u, 163u,
- 119u, 169u, 81u, 109u,
- 39u, 104u, 255u, 147u,
- 42u, 93u, 133u, 166u,
- 190u, 122u, 101u, 140u,
- 201u, 173u, 157u, 121u,
- 165u, 121u, 226u, 97u,
- 61u, 166u, 75u, 142u,
- 154u, 108u, 115u, 255u,
- 103u, 34u, 153u, 123u,
- 89u, 128u, 44u, 195u,
- 103u, 89u, 161u, 78u,
- 89u, 202u, 85u, 43u,
- 145u, 110u, 255u, 145u,
- 48u, 1u, 150u, 165u,
- 185u, 129u, 133u, 108u,
- 135u, 178u, 128u, 103u,
- 104u, 175u, 147u, 107u,
- 206u, 137u, 124u, 97u,
- 85u, 255u, 102u, 143u,
- 128u, 101u, 104u, 164u,
- 84u, 154u, 180u, 86u,
- 168u, 165u, 180u, 204u,
- 149u, 69u, 169u, 188u,
- 42u, 56u, 164u, 97u,
- 151u, 238u, 129u, 1u,
- 96u, 255u, 108u, 173u,
- 149u, 255u, 206u, 209u,
- 5u, 69u, 128u, 69u,
- 79u, 55u, 53u, 129u,
- 117u, 215u, 142u, 179u,
- 181u, 138u, 132u, 202u,
- 1u, 62u, 132u, 216u,
- 241u, 138u, 113u, 61u,
- 223u, 74u, 147u, 131u,
- 222u, 30u, 59u, 66u,
- 92u, 98u, 108u, 255u,
- 103u, 197u, 161u, 45u,
- 48u, 38u, 96u, 56u,
- 137u, 56u, 118u, 88u,
- 60u, 115u, 0u, 61u,
- 126u, 148u, 171u, 202u,
- 146u, 72u, 98u, 112u,
- 95u, 102u, 243u, 164u,
- 163u, 253u, 171u, 0u,
- 173u, 6u, 35u, 133u,
- 255u, 196u, 182u, 94u,
- 107u, 145u, 67u, 151u,
- 99u, 69u, 125u, 147u,
- 38u, 134u, 188u, 78u,
- 54u, 119u, 147u, 185u,
- 114u, 153u, 255u, 203u,
- 145u, 174u, 120u, 207u,
- 178u, 188u, 100u, 73u,
- 89u, 108u, 1u, 199u,
- 187u, 107u, 45u, 35u,
- 81u, 173u, 83u, 133u,
- 188u, 41u, 165u, 52u,
- 128u, 84u, 219u, 59u,
- 184u, 136u, 201u, 180u,
- 61u, 44u, 186u, 55u,
- 36u, 0u, 83u, 91u,
- 50u, 222u, 193u, 63u,
- 129u, 168u, 153u, 0u,
- 60u, 157u, 160u, 107u,
- 137u, 112u, 54u, 204u,
- 156u, 128u, 56u, 141u,
- 101u, 145u, 242u, 140u,
- 25u, 90u, 255u, 131u,
- 84u, 59u, 92u, 111u,
- 99u, 123u, 160u, 180u,
- 255u, 106u, 148u, 216u,
- 62u, 44u, 123u, 47u,
- 199u, 106u, 73u, 218u,
- 140u, 132u, 119u, 40u,
- 148u, 175u, 167u, 63u,
- 51u, 178u, 255u, 116u,
- 37u, 86u, 122u, 152u,
- 12u, 175u, 1u, 140u,
- 136u, 69u, 186u, 158u,
- 138u, 192u, 128u, 109u,
- 137u, 176u, 132u, 164u,
- 134u, 124u, 111u, 126u,
- 78u, 199u, 78u, 14u,
- 175u, 251u, 234u, 107u,
- 255u, 123u, 142u, 186u,
- 118u, 172u, 5u, 226u,
- 1u, 235u, 50u, 140u,
- 91u, 27u, 235u, 156u,
- 65u, 33u, 119u, 172u,
- 111u, 160u, 220u, 145u,
- 36u, 146u, 127u, 6u,
- 196u, 255u, 120u, 155u,
- 220u, 124u, 195u, 8u,
- 81u, 79u, 120u, 83u,
- 155u, 157u, 223u, 145u,
- 182u, 137u, 1u, 148u,
- 91u, 177u, 23u, 142u,
- 172u, 84u, 179u, 125u,
- 117u, 110u, 223u, 106u,
- 255u, 108u, 70u, 211u,
- 142u, 199u, 201u, 105u,
- 89u, 88u, 255u, 154u,
- 122u, 123u, 19u, 40u,
- 145u, 75u, 119u, 209u,
- 63u, 151u, 107u, 157u,
- 103u, 187u, 118u, 130u,
- 91u, 255u, 223u, 240u,
- 72u, 14u, 112u, 159u,
- 69u, 188u, 152u, 114u,
- 69u, 108u, 110u, 140u,
- 183u, 162u, 40u, 196u,
- 110u, 169u, 109u, 178u,
- 163u, 163u, 1u, 219u,
- 124u, 243u, 133u, 242u,
- 210u, 62u, 115u, 180u,
- 119u, 6u, 255u, 202u,
- 213u, 62u, 167u, 36u,
- 118u, 141u, 161u, 105u,
- 207u, 91u, 7u, 133u,
- 132u, 188u, 94u, 246u,
- 255u, 182u, 86u, 207u,
- 56u, 134u, 111u, 173u,
- 0u, 107u, 72u, 94u,
- 26u, 120u, 169u, 17u,
- 167u, 236u, 13u, 69u,
- 93u, 25u, 126u, 159u,
- 123u, 79u, 105u, 149u,
- 25u, 151u, 0u, 126u,
- 72u, 208u, 152u, 94u,
- 174u, 255u, 86u, 90u,
- 196u, 53u, 172u, 127u,
- 59u, 122u, 135u, 70u,
- 170u, 115u, 22u, 131u,
- 161u, 155u, 109u, 83u,
- 83u, 163u, 255u, 158u,
- 205u, 168u, 149u, 158u,
- 32u, 161u, 160u, 161u,
- 195u, 113u, 175u, 133u,
- 239u, 72u, 132u, 148u,
- 0u, 100u, 132u, 137u,
- 221u, 88u, 78u, 192u,
- 107u, 182u, 170u, 127u,
- 116u, 117u, 79u, 139u,
- 70u, 255u, 92u, 241u,
- 168u, 143u, 163u, 114u,
- 101u, 78u, 115u, 125u,
- 36u, 42u, 71u, 60u,
- 0u, 52u, 44u, 86u,
- 104u, 118u, 148u, 59u,
- 61u, 255u, 229u, 143u,
- 33u, 101u, 68u, 110u,
- 69u, 117u, 87u, 119u,
- 126u, 128u, 33u, 178u,
- 131u, 25u, 53u, 177u,
- 173u, 90u, 62u, 255u,
- 14u, 169u, 82u, 128u,
- 125u, 235u, 169u, 124u,
- 94u, 112u, 205u, 146u,
- 129u, 90u, 34u, 86u,
- 42u, 42u, 110u, 77u,
- 0u, 96u, 155u, 99u,
- 166u, 93u, 165u, 250u,
- 175u, 78u, 48u, 250u,
- 160u, 168u, 122u, 175u,
- 145u, 92u, 255u, 79u,
- 96u, 161u, 181u, 53u,
- 60u, 37u, 181u, 1u,
- 84u, 140u, 86u, 116u,
- 139u, 88u, 57u, 104u,
- 94u, 159u, 85u, 124u,
- 43u, 170u, 129u, 186u,
- 57u, 1u, 42u, 186u,
- 132u, 212u, 147u, 92u,
- 220u, 110u, 128u, 107u,
- 72u, 45u, 136u, 178u,
- 1u, 53u, 70u, 127u,
- 159u, 111u, 8u, 105u,
- 171u, 101u, 115u, 73u,
- 102u, 98u, 167u, 191u,
- 150u, 195u, 255u, 133u,
- 65u, 174u, 220u, 178u,
- 47u, 152u, 162u, 164u,
- 149u, 121u, 206u, 146u,
- 181u, 108u, 92u, 255u,
- 132u, 60u, 143u, 138u,
- 149u, 99u, 64u, 22u,
- 1u, 148u, 187u, 142u,
- 64u, 167u, 172u, 65u,
- 132u, 120u, 241u, 201u,
- 80u, 206u, 108u, 234u,
- 133u, 160u, 179u, 84u,
- 255u, 154u, 92u, 143u,
- 159u, 153u, 93u, 165u,
- 208u, 133u, 201u, 176u,
- 28u, 145u, 149u, 82u,
- 195u, 191u, 135u, 200u,
- 244u, 255u, 126u, 68u,
- 250u, 109u, 138u, 150u,
- 4u, 143u, 92u, 1u,
- 162u, 166u, 91u, 43u,
- 103u, 43u, 215u, 85u,
- 255u, 199u, 125u, 155u,
- 92u, 41u, 149u, 78u,
- 210u, 231u, 80u, 172u,
- 8u, 72u, 210u, 48u,
- 108u, 89u, 82u, 89u,
- 144u, 77u, 157u, 0u,
- 178u, 126u, 81u, 89u,
- 142u, 156u, 114u, 187u,
- 255u, 55u, 169u, 199u,
- 92u, 65u, 176u, 111u,
- 57u, 204u, 149u, 4u,
- 142u, 151u, 221u, 100u,
- 76u, 130u, 19u, 88u,
- 155u, 32u, 146u, 167u,
- 82u, 172u, 151u, 93u,
- 204u, 255u, 122u, 134u,
- 101u, 100u, 119u, 166u,
- 48u, 151u, 255u, 190u,
- 237u, 106u, 81u, 171u,
- 27u, 137u, 148u, 136u,
- 47u, 1u, 17u, 109u,
- 174u, 155u, 130u, 78u,
- 109u, 216u, 108u, 104u,
- 109u, 95u, 195u, 29u,
- 77u, 131u, 139u, 68u,
- 22u, 236u, 186u, 83u,
- 195u, 185u, 176u, 125u,
- 101u, 157u, 255u, 150u,
- 125u, 90u, 255u, 84u,
- 120u, 160u, 110u, 171u,
- 74u, 163u, 189u, 221u,
- 125u, 223u, 91u, 151u,
- 131u, 255u, 118u, 173u,
- 46u, 108u, 141u, 34u,
- 96u, 72u, 81u, 184u,
- 190u, 61u, 93u, 161u,
- 108u, 83u, 106u, 0u,
- 94u, 115u, 116u, 150u,
- 83u, 74u, 90u, 161u,
- 112u, 183u, 114u, 144u,
- 127u, 93u, 213u, 131u,
- 123u, 169u, 43u, 52u,
- 100u, 188u, 141u, 138u,
- 156u, 82u, 175u, 0u,
- 42u, 31u, 81u, 198u,
- 129u, 82u, 28u, 87u,
- 180u, 116u, 1u, 152u,
- 54u, 230u, 121u, 244u,
- 168u, 113u, 110u, 187u,
- 79u, 18u, 206u, 217u,
- 155u, 103u, 147u, 255u,
- 190u, 155u, 63u, 168u,
- 163u, 240u, 135u, 207u,
- 184u, 85u, 134u, 185u,
- 27u, 92u, 207u, 110u,
- 214u, 255u, 102u, 58u,
- 69u, 154u, 187u, 156u,
- 98u, 185u, 134u, 126u,
- 122u, 127u, 133u, 121u,
- 166u, 42u, 95u, 1u,
- 10u, 255u, 22u, 38u,
- 212u, 230u, 31u, 122u,
- 31u, 90u, 49u, 45u,
- 17u, 114u, 111u, 112u,
- 121u, 157u, 130u, 74u,
- 97u, 115u, 180u, 175u,
- 217u, 187u, 158u, 130u,
- 1u, 157u, 156u, 107u,
- 173u, 183u, 239u, 118u,
- 130u, 88u, 82u, 121u,
- 93u, 131u, 252u, 255u,
- 133u, 87u, 137u, 68u,
- 125u, 107u, 1u, 137u,
- 105u, 48u, 123u, 181u,
- 65u, 160u, 60u, 101u,
- 244u, 223u, 89u, 108u,
- 146u, 56u, 194u, 255u,
- 14u, 119u, 139u, 35u,
- 93u, 148u, 128u, 142u,
- 240u, 230u, 176u, 148u,
- 176u, 195u, 250u, 103u,
- 170u, 146u, 178u, 169u,
- 132u, 103u, 189u, 229u,
- 137u, 84u, 1u, 150u,
- 135u, 125u, 128u, 91u,
- 198u, 179u, 77u, 194u,
- 73u, 142u, 118u, 87u,
- 133u, 104u, 0u, 103u,
- 135u, 255u, 141u, 49u,
- 189u, 134u, 187u, 158u,
- 79u, 89u, 126u, 126u,
- 121u, 112u, 167u, 225u,
- 141u, 39u, 75u, 0u,
- 133u, 27u, 155u, 183u,
- 197u, 198u, 112u, 121u,
- 104u, 53u, 153u, 45u,
- 119u, 200u, 124u, 43u,
- 180u, 114u, 126u, 184u,
- 125u, 91u, 79u, 255u,
- 49u, 137u, 156u, 191u,
- 82u, 128u, 255u, 143u,
- 40u, 92u, 140u, 93u,
- 136u, 144u, 149u, 181u,
- 96u, 61u, 103u, 94u,
- 0u, 164u, 52u, 197u,
- 24u, 173u, 118u, 5u,
- 138u, 151u, 218u, 211u,
- 249u, 14u, 248u, 111u,
- 98u, 218u, 203u, 120u,
- 121u, 176u, 141u, 76u,
- 16u, 126u, 236u, 165u,
- 161u, 76u, 0u, 234u,
- 149u, 94u, 198u, 127u,
- 179u, 95u, 180u, 169u,
- 113u, 143u, 186u, 135u,
- 203u, 107u, 1u, 118u,
- 138u, 0u, 191u, 193u,
- 55u, 168u, 112u, 86u,
- 194u, 211u, 51u, 62u,
- 141u, 190u, 136u, 34u,
- 137u, 145u, 232u, 203u,
- 48u, 109u, 13u, 0u,
- 200u, 126u, 165u, 60u,
- 144u, 122u, 160u, 167u,
- 172u, 66u, 185u, 255u,
- 121u, 153u, 95u, 235u,
- 248u, 190u, 197u, 160u,
- 153u, 141u, 184u, 83u,
- 68u, 101u, 43u, 110u,
- 134u, 153u, 103u, 86u,
- 1u, 160u, 207u, 157u,
- 110u, 91u, 116u, 102u,
- 77u, 23u, 196u, 182u,
- 245u, 29u, 128u, 170u,
- 112u, 115u, 98u, 0u,
- 52u, 247u, 225u, 214u,
- 107u, 219u, 176u, 149u,
- 46u, 255u, 54u, 100u,
- 87u, 153u, 123u, 42u,
- 93u, 101u, 137u, 91u,
- 81u, 103u, 175u, 255u,
- 27u, 106u, 192u, 147u,
- 201u, 163u, 47u, 130u,
- 174u, 109u, 153u, 50u,
- 156u, 113u, 238u, 102u,
- 150u, 66u, 134u, 29u,
- 1u, 178u, 128u, 116u,
- 183u, 237u, 120u, 142u,
- 207u, 157u, 105u, 135u,
- 172u, 145u, 1u, 117u,
- 74u, 154u, 100u, 106u,
- 28u, 110u, 119u, 123u,
- 200u, 229u, 212u, 190u,
- 107u, 102u, 36u, 150u,
- 161u, 236u, 203u, 255u,
- 160u, 187u, 196u, 44u,
- 135u, 149u, 124u, 130u,
- 109u, 48u, 94u, 169u,
- 93u, 125u, 154u, 122u,
- 188u, 158u, 0u, 80u,
- 103u, 228u, 111u, 99u,
- 139u, 230u, 151u, 137u,
- 102u, 90u, 98u, 103u,
- 1u, 99u, 138u, 226u,
- 134u, 198u, 201u, 181u,
- 145u, 107u, 119u, 203u,
- 80u, 0u, 207u, 166u,
- 160u, 101u, 41u, 93u,
- 104u, 121u, 117u, 176u,
- 62u, 79u, 202u, 115u,
- 235u, 210u, 175u, 200u,
- 255u, 213u, 71u, 204u,
- 65u, 84u, 60u, 110u,
- 183u, 255u, 121u, 119u,
- 228u, 181u, 105u, 33u,
- 80u, 126u, 153u, 146u,
- 236u, 85u, 135u, 7u,
- 173u, 162u, 175u, 94u,
- 168u, 100u, 82u, 0u,
- 130u, 51u, 98u, 156u,
- 100u, 119u, 102u, 153u,
- 255u, 141u, 139u, 126u,
- 106u, 211u, 128u, 102u,
- 252u, 206u, 133u, 53u,
- 73u, 214u, 1u, 136u,
- 143u, 86u, 189u, 229u,
- 50u, 175u, 166u, 156u,
- 65u, 128u, 137u, 91u,
- 255u, 136u, 179u, 191u,
- 50u, 185u, 91u, 91u,
- 157u, 36u, 104u, 85u,
- 125u, 89u, 124u, 58u,
- 177u, 152u, 128u, 143u,
- 0u, 161u, 138u, 87u,
- 128u, 125u, 103u, 12u,
- 126u, 188u, 151u, 215u,
- 185u, 167u, 159u, 157u,
- 154u, 122u, 172u, 214u,
- 193u, 108u, 179u, 176u,
- 115u, 184u, 1u, 200u,
- 98u, 43u, 230u, 188u,
- 33u, 45u, 69u, 2u,
- 115u, 253u, 100u, 221u,
- 177u, 255u, 156u, 75u,
- 76u, 78u, 140u, 161u,
- 145u, 180u, 78u, 60u,
- 78u, 98u, 98u, 191u,
- 164u, 46u, 157u, 1u,
- 189u, 81u, 71u, 158u,
- 173u, 151u, 1u, 117u,
- 102u, 105u, 153u, 63u,
- 108u, 122u, 99u, 48u,
- 144u, 47u, 1u, 175u,
- 174u, 169u, 141u, 173u,
- 181u, 127u, 102u, 127u,
- 207u, 59u, 169u, 126u,
- 109u, 174u, 64u, 196u,
- 241u, 210u, 134u, 40u,
- 0u, 153u, 54u, 58u,
- 255u, 106u, 64u, 58u,
- 231u, 23u, 209u, 23u,
- 109u, 41u, 122u, 1u,
- 122u, 184u, 152u, 184u,
- 205u, 136u, 1u, 31u,
- 155u, 168u, 55u, 120u,
- 115u, 199u, 80u, 210u,
- 89u, 1u, 226u, 131u,
- 150u, 20u, 184u, 86u,
- 57u, 192u, 190u, 47u,
- 88u, 255u, 223u, 109u,
- 185u, 205u, 228u, 113u,
- 67u, 120u, 94u, 199u,
- 122u, 124u, 56u, 190u,
- 57u, 202u, 64u, 193u,
- 174u, 8u, 182u, 31u,
- 168u, 40u, 142u, 255u,
- 116u, 245u, 134u, 118u,
- 157u, 129u, 180u, 117u,
- 113u, 102u, 140u, 109u,
- 31u, 75u, 77u, 255u,
- 156u, 133u, 68u, 232u,
- 178u, 39u, 143u, 141u,
- 181u, 92u, 173u, 53u,
- 39u, 255u, 160u, 96u,
- 13u, 249u, 39u, 109u,
- 197u, 197u, 183u, 114u,
- 150u, 158u, 149u, 29u,
- 37u, 57u, 181u, 255u,
- 205u, 143u, 114u, 141u,
- 67u, 191u, 106u, 117u,
- 239u, 170u, 204u, 31u,
- 161u, 27u, 255u, 154u,
- 153u, 80u, 131u, 189u,
- 156u, 67u, 142u, 140u,
- 112u, 197u, 181u, 177u,
- 165u, 114u, 63u, 1u,
- 87u, 241u, 146u, 190u,
- 196u, 139u, 98u, 83u,
- 174u, 137u, 90u, 112u,
- 255u, 73u, 163u, 153u,
- 118u, 112u, 162u, 250u,
- 100u, 110u, 90u, 135u,
- 94u, 182u, 184u, 145u,
- 208u, 161u, 255u, 111u,
- 103u, 122u, 130u, 60u,
- 185u, 73u, 154u, 146u,
- 255u, 39u, 138u, 100u,
- 41u, 117u, 205u, 137u,
- 127u, 255u, 189u, 80u,
- 130u, 105u, 156u, 171u,
- 77u, 120u, 153u, 140u,
- 173u, 119u, 84u, 196u,
- 255u, 74u, 118u, 129u,
- 15u, 101u, 176u, 226u,
- 211u, 105u, 138u, 138u,
- 19u, 103u, 198u, 85u,
- 105u, 97u, 146u, 167u,
- 126u, 179u, 131u, 156u,
- 102u, 169u, 130u, 110u,
- 81u, 71u, 134u, 255u,
- 182u, 155u, 192u, 203u,
- 151u, 154u, 128u, 177u,
- 200u, 131u, 142u, 103u,
- 152u, 121u, 61u, 255u,
- 0u, 157u, 104u, 88u,
- 163u, 141u, 150u, 181u,
- 88u, 100u, 207u, 197u,
- 200u, 77u, 98u, 49u,
- 188u, 135u, 1u, 126u,
- 83u, 144u, 22u, 235u,
- 193u, 225u, 117u, 102u,
- 93u, 49u, 218u, 207u,
- 255u, 165u, 123u, 48u,
- 163u, 72u, 183u, 138u,
- 137u, 189u, 162u, 122u,
- 250u, 153u, 225u, 231u,
- 55u, 214u, 25u, 255u,
- 135u, 208u, 125u, 110u,
- 156u, 120u, 213u, 76u,
- 205u, 77u, 236u, 201u,
- 241u, 231u, 195u, 77u,
- 172u, 1u, 251u, 168u,
- 116u, 105u, 243u, 126u,
- 225u, 27u, 40u, 25u,
- 17u, 176u, 29u, 113u,
- 136u, 222u, 1u, 212u,
- 89u, 204u, 47u, 74u,
- 124u, 69u, 78u, 5u,
- 72u, 7u, 140u, 154u,
- 207u, 88u, 204u, 94u,
- 1u, 235u, 123u, 28u,
- 78u, 183u, 94u, 105u,
- 68u, 58u, 139u, 40u,
- 135u, 103u, 182u, 110u,
- 98u, 255u, 84u, 147u,
- 155u, 113u, 144u, 130u,
- 144u, 68u, 145u, 124u,
- 63u, 103u, 255u, 253u,
- 224u, 165u, 145u, 144u,
- 23u, 172u, 143u, 141u,
- 97u, 121u, 61u, 139u,
- 234u, 126u, 236u, 79u,
- 91u, 130u, 165u, 237u,
- 110u, 255u, 42u, 77u,
- 59u, 145u, 184u, 177u,
- 30u, 95u, 119u, 109u,
- 114u, 121u, 1u, 180u,
- 140u, 175u, 129u, 175u,
- 65u, 76u, 1u, 244u,
- 122u, 128u, 181u, 123u,
- 80u, 112u, 164u, 169u,
- 130u, 119u, 87u, 204u,
- 101u, 186u, 171u, 64u,
- 1u, 118u, 107u, 124u,
- 121u, 170u, 95u, 174u,
- 149u, 111u, 182u, 58u,
- 83u, 238u, 210u, 255u,
- 225u, 146u, 220u, 162u,
- 103u, 148u, 166u, 68u,
- 157u, 135u, 51u, 37u,
- 149u, 104u, 131u, 146u,
- 40u, 83u, 147u, 147u,
- 255u, 139u, 240u, 74u,
- 78u, 89u, 133u, 130u,
- 104u, 130u, 161u, 184u,
- 33u, 78u, 103u, 1u,
- 198u, 243u, 171u, 188u,
- 231u, 21u, 99u, 87u,
- 135u, 255u, 247u, 108u,
- 92u, 158u, 88u, 153u,
- 173u, 164u, 230u, 119u,
- 130u, 115u, 172u, 211u,
- 171u, 75u, 171u, 162u,
- 148u, 124u, 150u, 122u,
- 140u, 177u, 102u, 185u,
- 56u, 178u, 255u, 102u,
- 185u, 207u, 159u, 179u,
- 169u, 108u, 67u, 197u,
- 211u, 89u, 69u, 121u,
- 0u, 66u, 80u, 206u,
- 111u, 102u, 44u, 119u,
- 131u, 211u, 91u, 145u,
- 125u, 186u, 64u, 126u,
- 11u, 130u, 255u, 58u,
- 103u, 87u, 144u, 148u,
- 174u, 89u, 172u, 113u,
- 166u, 244u, 32u, 128u,
- 117u, 219u, 183u, 1u,
- 255u, 190u, 169u, 108u,
- 139u, 144u, 125u, 195u,
- 91u, 134u, 123u, 147u,
- 103u, 163u, 176u, 131u,
- 117u, 124u, 88u, 158u,
- 93u, 28u, 194u, 139u,
- 89u, 182u, 255u, 79u,
- 166u, 213u, 43u, 158u,
- 154u, 79u, 187u, 255u,
- 98u, 195u, 132u, 113u,
- 131u, 40u, 116u, 163u,
- 143u, 124u, 122u, 193u,
- 52u, 55u, 91u, 58u,
- 185u, 198u, 85u, 33u,
- 93u, 180u, 170u, 139u,
- 57u, 255u, 52u, 47u,
- 224u, 80u, 255u, 101u,
- 64u, 88u, 26u, 197u,
- 8u, 160u, 248u, 64u,
- 105u, 139u, 244u, 227u,
- 84u, 154u, 168u, 155u,
- 51u, 255u, 171u, 26u,
- 18u, 146u, 128u, 175u,
- 149u, 5u, 44u, 212u,
- 0u, 197u, 189u, 206u,
- 69u, 173u, 151u, 149u,
- 64u, 167u, 119u, 109u,
- 170u, 217u, 12u, 139u,
- 133u, 99u, 105u, 85u,
- 141u, 229u, 77u, 255u,
- 6u, 74u, 167u, 88u,
- 2u, 138u, 205u, 115u,
- 163u, 165u, 181u, 64u,
- 133u, 255u, 159u, 244u,
- 147u, 36u, 178u, 133u,
- 135u, 131u, 70u, 116u,
- 45u, 124u, 138u, 188u,
- 103u, 41u, 177u, 81u,
- 147u, 116u, 141u, 119u,
- 255u, 55u, 66u, 134u,
- 234u, 144u, 197u, 209u,
- 115u, 149u, 20u, 179u,
- 252u, 127u, 175u, 157u,
- 0u, 106u, 165u, 96u,
- 29u, 42u, 1u, 142u,
- 42u, 102u, 151u, 39u,
- 153u, 225u, 85u, 61u,
- 77u, 51u, 179u, 127u,
- 141u, 33u, 197u, 39u,
- 113u, 61u, 28u, 1u,
- 191u, 62u, 93u, 194u,
- 214u, 212u, 146u, 215u,
- 191u, 168u, 14u, 221u,
- 49u, 185u, 118u, 148u,
- 123u, 181u, 104u, 171u,
- 1u, 131u, 213u, 138u,
- 255u, 119u, 97u, 145u,
- 46u, 192u, 56u, 120u,
- 192u, 75u, 83u, 188u,
- 170u, 98u, 90u, 159u,
- 123u, 141u, 197u, 255u,
- 76u, 104u, 128u, 136u,
- 76u, 134u, 195u, 148u,
- 171u, 179u, 240u, 190u,
- 172u, 83u, 75u, 0u,
- 135u, 19u, 65u, 189u,
- 156u, 210u, 129u, 29u,
- 78u, 156u, 31u, 121u,
- 117u, 81u, 200u, 155u,
- 186u, 154u, 39u, 166u,
- 101u, 111u, 115u, 124u,
- 139u, 187u, 0u, 67u,
- 143u, 79u, 188u, 224u,
- 99u, 115u, 100u, 129u,
- 196u, 198u, 183u, 88u,
- 255u, 93u, 132u, 124u,
- 103u, 255u, 171u, 150u,
- 94u, 4u, 129u, 136u,
- 140u, 176u, 136u, 206u,
- 137u, 128u, 127u, 241u,
- 160u, 184u, 175u, 208u,
- 176u, 181u, 154u, 146u,
- 163u, 0u, 184u, 71u,
- 127u, 80u, 56u, 148u,
- 255u, 174u, 190u, 100u,
- 165u, 88u, 93u, 149u,
- 167u, 103u, 185u, 144u,
- 176u, 89u, 95u, 158u,
- 120u, 255u, 31u, 199u,
- 118u, 127u, 65u, 46u,
- 169u, 202u, 108u, 1u,
- 101u, 105u, 105u, 235u,
- 241u, 134u, 184u, 81u,
- 174u, 150u, 48u, 232u,
- 176u, 77u, 176u, 93u,
- 143u, 1u, 177u, 56u,
- 1u, 159u, 134u, 169u,
- 184u, 137u, 195u, 71u,
- 141u, 180u, 220u, 165u,
- 169u, 33u, 56u, 197u,
- 92u, 51u, 1u, 120u,
- 135u, 169u, 53u, 92u,
- 133u, 106u, 85u, 140u,
- 109u, 125u, 82u, 107u,
- 13u, 123u, 135u, 55u,
- 114u, 124u, 138u, 1u,
- 59u, 182u, 93u, 106u,
- 76u, 209u, 135u, 156u,
- 211u, 55u, 94u, 255u,
- 55u, 50u, 212u, 137u,
- 164u, 134u, 185u, 33u,
- 60u, 191u, 140u, 92u,
- 0u, 181u, 63u, 109u,
- 173u, 130u, 216u, 132u,
- 141u, 174u, 132u, 152u,
- 187u, 103u, 36u, 241u,
- 255u, 146u, 204u, 213u,
- 108u, 35u, 28u, 71u,
- 125u, 134u, 207u, 150u,
- 191u, 185u, 116u, 58u,
- 120u, 182u, 14u, 45u,
- 112u, 96u, 1u, 227u,
- 91u, 29u, 194u, 123u,
- 133u, 120u, 101u, 135u,
- 52u, 145u, 64u, 68u,
- 97u, 117u, 80u, 189u,
- 90u, 140u, 90u, 140u,
- 1u, 138u, 198u, 142u,
- 91u, 60u, 146u, 249u,
- 42u, 138u, 118u, 108u,
- 255u, 17u, 95u, 98u,
- 168u, 184u, 156u, 162u,
- 191u, 226u, 100u, 93u,
- 74u, 211u, 51u, 124u,
- 42u, 148u, 166u, 0u,
- 142u, 64u, 175u, 110u,
- 89u, 131u, 116u, 134u,
- 142u, 142u, 255u, 164u,
- 23u, 224u, 189u, 219u,
- 131u, 105u, 73u, 84u,
- 10u, 149u, 39u, 96u,
- 108u, 65u, 198u, 68u,
- 1u, 114u, 103u, 173u,
- 129u, 193u, 174u, 202u,
- 122u, 135u, 181u, 139u,
- 24u, 207u, 205u, 57u,
- 182u, 136u, 105u, 183u,
- 229u, 209u, 255u, 253u,
- 226u, 149u, 128u, 1u,
- 183u, 118u, 83u, 144u,
- 198u, 110u, 54u, 193u,
- 218u, 78u, 203u, 103u,
- 95u, 210u, 101u, 153u,
- 123u, 144u, 125u, 147u,
- 255u, 188u, 157u, 148u,
- 157u, 26u, 160u, 158u,
- 121u, 42u, 252u, 124u,
- 144u, 46u, 101u, 87u,
- 165u, 154u, 57u, 111u,
- 154u, 1u, 14u, 31u,
- 136u, 186u, 93u, 1u,
- 199u, 70u, 97u, 98u,
- 73u, 120u, 151u, 170u,
- 145u, 42u, 110u, 122u,
- 115u, 136u, 161u, 154u,
- 43u, 21u, 52u, 49u,
- 108u, 116u, 197u, 189u,
- 241u, 105u, 54u, 1u,
- 206u, 151u, 143u, 234u,
- 104u, 95u, 135u, 158u,
- 189u, 183u, 217u, 197u,
- 120u, 98u, 255u, 87u,
- 146u, 7u, 103u, 134u,
- 170u, 98u, 191u, 162u,
- 62u, 239u, 132u, 239u,
- 119u, 255u, 41u, 98u,
- 243u, 111u, 108u, 255u,
- 170u, 159u, 186u, 141u,
- 11u, 108u, 129u, 63u,
- 31u, 194u, 81u, 104u,
- 220u, 154u, 180u, 156u,
- 77u, 78u, 156u, 161u,
- 146u, 28u, 189u, 144u,
- 143u, 1u, 167u, 158u,
- 94u, 125u, 95u, 172u,
- 62u, 86u, 228u, 129u,
- 159u, 155u, 135u, 85u,
- 193u, 157u, 77u, 255u,
- 126u, 60u, 141u, 134u,
- 116u, 107u, 198u, 96u,
- 195u, 255u, 46u, 160u,
- 90u, 214u, 106u, 15u,
- 80u, 122u, 148u, 121u,
- 88u, 83u, 157u, 1u,
- 103u, 165u, 111u, 83u,
- 106u, 108u, 162u, 128u,
- 135u, 56u, 107u, 94u,
- 178u, 101u, 93u, 231u,
- 68u, 142u, 183u, 132u,
- 69u, 67u, 1u, 133u,
- 118u, 122u, 60u, 255u,
- 119u, 42u, 101u, 181u,
- 88u, 8u, 173u, 105u,
- 103u, 149u, 188u, 59u,
- 88u, 255u, 138u, 125u,
- 219u, 215u, 176u, 27u,
- 121u, 203u, 28u, 123u,
- 17u, 219u, 112u, 150u,
- 96u, 125u, 89u, 198u,
- 255u, 146u, 153u, 190u,
- 140u, 77u, 193u, 86u,
- 137u, 120u, 3u, 139u,
- 21u, 37u, 19u, 105u,
- 148u, 91u, 1u, 224u,
- 137u, 151u, 213u, 40u,
- 143u, 110u, 61u, 182u,
- 99u, 117u, 173u, 51u,
- 110u, 225u, 151u, 64u,
- 188u, 165u, 17u, 244u,
- 246u, 1u, 231u, 49u,
- 27u, 143u, 183u, 246u,
- 94u, 223u, 140u, 1u,
- 135u, 71u, 78u, 169u,
- 62u, 110u, 109u, 136u,
- 109u, 176u, 88u, 171u,
- 82u, 208u, 168u, 56u,
- 1u, 53u, 49u, 172u,
- 37u, 135u, 201u, 143u,
- 116u, 152u, 103u, 76u,
- 177u, 128u, 215u, 142u,
- 1u, 90u, 148u, 50u,
- 85u, 149u, 29u, 149u,
- 5u, 120u, 131u, 127u,
- 80u, 99u, 108u, 39u,
- 255u, 160u, 116u, 162u,
- 152u, 14u, 25u, 192u,
- 114u, 221u, 174u, 100u,
- 224u, 38u, 170u, 108u,
- 185u, 195u, 198u, 195u,
- 41u, 185u, 255u, 142u,
- 161u, 113u, 200u, 140u,
- 138u, 227u, 110u, 125u,
- 127u, 151u, 156u, 255u,
- 154u, 117u, 91u, 112u,
- 223u, 98u, 241u, 45u,
- 188u, 203u, 42u, 169u,
- 149u, 142u, 1u, 214u,
- 198u, 205u, 244u, 42u,
- 145u, 73u, 224u, 160u,
- 88u, 60u, 178u, 92u,
- 84u, 173u, 112u, 169u,
- 83u, 218u, 1u, 75u,
- 176u, 217u, 167u, 154u,
- 107u, 245u, 161u, 113u,
- 255u, 121u, 100u, 154u,
- 68u, 118u, 207u, 152u,
- 130u, 35u, 79u, 203u,
- 112u, 98u, 42u, 138u,
- 205u, 91u, 187u, 1u,
- 109u, 95u, 165u, 65u,
- 167u, 70u, 110u, 92u,
- 100u, 94u, 131u, 97u,
- 86u, 185u, 199u, 16u,
- 139u, 255u, 144u, 138u,
- 142u, 46u, 127u, 123u,
- 74u, 151u, 106u, 109u,
- 123u, 145u, 88u, 86u,
- 1u, 106u, 235u, 80u,
- 77u, 130u, 82u, 188u,
- 154u, 115u, 165u, 255u,
- 152u, 31u, 163u, 128u,
- 113u, 80u, 105u, 67u,
- 75u, 112u, 154u, 147u,
- 140u, 134u, 159u, 151u,
- 162u, 144u, 135u, 95u,
- 141u, 125u, 140u, 0u,
- 147u, 130u, 145u, 129u,
- 73u, 106u, 124u, 138u,
- 180u, 255u, 169u, 87u,
- 194u, 132u, 95u, 68u,
- 203u, 255u, 97u, 230u,
- 73u, 73u, 196u, 202u,
- 23u, 137u, 142u, 149u,
- 171u, 255u, 98u, 15u,
- 151u, 83u, 40u, 133u,
- 80u, 255u, 203u, 183u,
- 165u, 217u, 194u, 181u,
- 209u, 37u, 48u, 207u,
- 136u, 30u, 197u, 193u,
- 147u, 153u, 168u, 101u,
- 40u, 39u, 31u, 30u,
- 65u, 255u, 238u, 75u,
- 101u, 157u, 118u, 255u,
- 231u, 97u, 160u, 142u,
- 184u, 124u, 161u, 99u,
- 73u, 112u, 118u, 136u,
- 169u, 161u, 1u, 122u,
- 149u, 70u, 171u, 135u,
- 121u, 107u, 87u, 91u,
- 188u, 180u, 133u, 103u,
- 146u, 166u, 67u, 182u,
- 57u, 110u, 213u, 164u,
- 218u, 192u, 173u, 161u,
- 0u, 114u, 173u, 125u,
- 119u, 153u, 115u, 225u,
- 179u, 149u, 110u, 1u,
- 241u, 30u, 47u, 129u,
- 136u, 50u, 121u, 240u,
- 0u, 127u, 91u, 237u,
- 126u, 104u, 139u, 147u,
- 97u, 133u, 158u, 119u,
- 127u, 146u, 45u, 85u,
- 205u, 77u, 92u, 37u,
- 49u, 133u, 137u, 111u,
- 197u, 128u, 34u, 159u,
- 180u, 255u, 70u, 143u,
- 132u, 120u, 194u, 47u,
- 75u, 195u, 209u, 146u,
- 48u, 72u, 133u, 127u,
- 1u, 30u, 45u, 83u,
- 235u, 255u, 189u, 210u,
- 189u, 164u, 65u, 246u,
- 75u, 92u, 191u, 95u,
- 159u, 123u, 153u, 110u,
- 227u, 255u, 51u, 75u,
- 179u, 69u, 71u, 210u,
- 102u, 82u, 196u, 183u,
- 147u, 96u, 100u, 111u,
- 105u, 108u, 1u, 224u,
- 158u, 141u, 96u, 226u,
- 73u, 138u, 141u, 127u,
- 25u, 34u, 76u, 107u,
- 60u, 144u, 155u, 58u,
- 1u, 97u, 118u, 137u,
- 83u, 60u, 189u, 99u,
- 73u, 139u, 138u, 148u,
- 149u, 165u, 125u, 254u,
- 49u, 117u, 198u, 84u,
- 130u, 103u, 192u, 159u,
- 116u, 112u, 198u, 255u,
- 190u, 185u, 117u, 83u,
- 102u, 41u, 68u, 255u,
- 128u, 204u, 237u, 168u,
- 148u, 69u, 151u, 113u,
- 94u, 10u, 186u, 200u,
- 87u, 41u, 255u, 177u,
- 227u, 213u, 211u, 161u,
- 92u, 207u, 186u, 165u,
- 39u, 222u, 122u, 93u,
- 126u, 208u, 179u, 248u,
- 152u, 1u, 165u, 176u,
- 92u, 114u, 27u, 163u,
- 20u, 148u, 116u, 239u,
- 81u, 119u, 94u, 101u,
- 108u, 140u, 175u, 0u,
- 156u, 16u, 77u, 118u,
- 145u, 60u, 138u, 88u,
- 162u, 148u, 116u, 127u,
- 42u, 145u, 255u, 117u,
- 120u, 103u, 173u, 183u,
- 50u, 63u, 161u, 237u,
- 0u, 178u, 109u, 71u,
- 26u, 128u, 147u, 102u,
- 158u, 78u, 75u, 109u,
- 59u, 94u, 73u, 166u,
- 106u, 162u, 218u, 140u,
- 145u, 58u, 104u, 184u,
- 65u, 236u, 1u, 203u,
- 169u, 186u, 121u, 183u,
- 168u, 217u, 173u, 164u,
- 5u, 64u, 107u, 127u,
- 68u, 255u, 33u, 190u,
- 178u, 161u, 210u, 85u,
- 124u, 130u, 146u, 255u,
- 226u, 105u, 136u, 136u,
- 149u, 128u, 183u, 111u,
- 8u, 43u, 73u, 153u,
- 87u, 110u, 92u, 134u,
- 93u, 76u, 1u, 134u,
- 187u, 109u, 146u, 127u,
- 64u, 61u, 180u, 117u,
- 10u, 1u, 79u, 183u,
- 43u, 170u, 246u, 75u,
- 147u, 158u, 180u, 204u,
- 90u, 120u, 80u, 126u,
- 123u, 255u, 167u, 166u,
- 154u, 82u, 112u, 83u,
- 103u, 168u, 107u, 186u,
- 130u, 87u, 184u, 43u,
- 80u, 116u, 255u, 113u,
- 147u, 143u, 37u, 240u,
- 46u, 77u, 176u, 30u,
- 48u, 105u, 173u, 172u,
- 119u, 167u, 154u, 168u,
- 141u, 51u, 166u, 63u,
- 1u, 232u, 100u, 8u,
- 78u, 1u, 94u, 195u,
- 50u, 186u, 99u, 179u,
- 95u, 132u, 115u, 111u,
- 76u, 127u, 154u, 170u,
- 181u, 93u, 129u, 157u,
- 182u, 153u, 255u, 90u,
- 45u, 152u, 112u, 198u,
- 125u, 114u, 95u, 22u,
- 40u, 172u, 0u, 117u,
- 59u, 222u, 169u, 101u,
- 111u, 82u, 137u, 207u,
- 116u, 191u, 88u, 144u,
- 169u, 6u, 149u, 159u,
- 99u, 83u, 122u, 73u,
- 0u, 165u, 129u, 113u,
- 121u, 112u, 75u, 41u,
- 209u, 248u, 163u, 85u,
- 155u, 161u, 37u, 94u,
- 221u, 225u, 43u, 186u,
- 18u, 196u, 247u, 255u,
- 41u, 238u, 118u, 63u,
- 142u, 133u, 129u, 1u,
- 113u, 202u, 97u, 184u,
- 37u, 195u, 43u, 194u,
- 201u, 195u, 86u, 127u,
- 69u, 143u, 142u, 136u,
- 210u, 76u, 64u, 165u,
- 255u, 108u, 128u, 160u,
- 115u, 174u, 163u, 70u,
- 92u, 92u, 94u, 141u,
- 228u, 106u, 28u, 1u,
- 195u, 137u, 68u, 207u,
- 186u, 190u, 92u, 138u,
- 129u, 206u, 184u, 183u,
- 196u, 147u, 119u, 112u,
- 1u, 148u, 143u, 210u,
- 99u, 6u, 1u, 88u,
- 83u, 16u, 225u, 217u,
- 105u, 142u, 108u, 57u,
- 172u, 241u, 184u, 65u,
- 142u, 51u, 92u, 21u,
- 141u, 20u, 96u, 105u,
- 124u, 181u, 67u, 104u,
- 133u, 96u, 1u, 41u,
- 217u, 193u, 154u, 124u,
- 129u, 202u, 25u, 49u,
- 76u, 158u, 66u, 255u,
- 59u, 160u, 225u, 189u,
- 174u, 25u, 191u, 1u,
- 222u, 96u, 64u, 154u,
- 171u, 144u, 154u, 100u,
- 142u, 41u, 118u, 147u,
- 155u, 119u, 181u, 158u,
- 136u, 225u, 145u, 137u,
- 236u, 186u, 154u, 199u,
- 1u, 133u, 182u, 172u,
- 65u, 255u, 48u, 149u,
- 152u, 142u, 117u, 225u,
- 190u, 88u, 109u, 130u,
- 85u, 51u, 162u, 132u,
- 255u, 19u, 139u, 66u,
- 98u, 57u, 93u, 234u,
- 82u, 151u, 166u, 53u,
- 147u, 18u, 157u, 108u,
- 144u, 174u, 133u, 255u,
- 237u, 85u, 168u, 203u,
- 156u, 130u, 207u, 122u,
- 111u, 74u, 77u, 111u,
- 130u, 59u, 68u, 199u,
- 255u, 144u, 117u, 221u,
- 134u, 60u, 138u, 88u,
- 163u, 40u, 205u, 131u,
- 71u, 190u, 219u, 215u,
- 90u, 168u, 7u, 1u,
- 148u, 73u, 133u, 166u,
- 194u, 166u, 58u, 179u,
- 144u, 124u, 97u, 5u,
- 255u, 126u, 190u, 232u,
- 84u, 124u, 176u, 80u,
- 109u, 130u, 168u, 106u,
- 117u, 155u, 85u, 111u,
- 134u, 148u, 255u, 194u,
- 60u, 18u, 86u, 212u,
- 184u, 63u, 66u, 83u,
- 117u, 127u, 237u, 255u,
- 108u, 223u, 22u, 21u,
- 173u, 223u, 96u, 170u,
- 49u, 186u, 73u, 65u,
- 143u, 176u, 93u, 188u,
- 255u, 141u, 113u, 115u,
- 88u, 155u, 113u, 124u,
- 115u, 127u, 119u, 255u,
- 137u, 68u, 121u, 218u,
- 43u, 159u, 173u, 1u,
- 89u, 225u, 159u, 171u,
- 250u, 155u, 108u, 77u,
- 199u, 156u, 119u, 235u,
- 186u, 255u, 216u, 78u,
- 197u, 2u, 24u, 228u,
- 24u, 174u, 57u, 38u,
- 58u, 98u, 162u, 104u,
- 83u, 109u, 91u, 1u,
- 152u, 131u, 129u, 120u,
- 211u, 27u, 161u, 135u,
- 117u, 187u, 218u, 75u,
- 107u, 1u, 59u, 164u,
- 135u, 237u, 92u, 98u,
- 163u, 204u, 155u, 155u,
- 43u, 199u, 70u, 170u,
- 57u, 209u, 1u, 34u,
- 131u, 71u, 151u, 102u,
- 74u, 64u, 72u, 74u,
- 159u, 179u, 235u, 85u,
- 156u, 109u, 150u, 255u,
- 127u, 39u, 185u, 237u,
- 235u, 120u, 149u, 213u,
- 38u, 0u, 68u, 147u,
- 141u, 98u, 138u, 131u,
- 165u, 141u, 110u, 79u,
- 128u, 93u, 53u, 153u,
- 143u, 88u, 30u, 99u,
- 25u, 255u, 96u, 208u,
- 182u, 10u, 85u, 88u,
- 222u, 185u, 62u, 100u,
- 141u, 130u, 146u, 123u,
- 220u, 116u, 100u, 180u,
- 127u, 1u, 113u, 85u,
- 120u, 126u, 109u, 130u,
- 255u, 100u, 213u, 44u,
- 155u, 121u, 89u, 150u,
- 186u, 135u, 113u, 58u,
- 75u, 139u, 129u, 135u,
- 129u, 196u, 109u, 189u,
- 102u, 232u, 125u, 158u,
- 170u, 144u, 158u, 130u,
- 223u, 159u, 255u, 61u,
- 164u, 1u, 128u, 77u,
- 168u, 109u, 107u, 213u,
- 137u, 239u, 172u, 243u,
- 216u, 76u, 145u, 69u,
- 104u, 255u, 140u, 204u,
- 104u, 137u, 112u, 219u,
- 140u, 123u, 202u, 157u,
- 34u, 134u, 225u, 170u,
- 136u, 210u, 154u, 59u,
- 180u, 108u, 1u, 183u,
- 152u, 136u, 196u, 112u,
- 119u, 16u, 62u, 223u,
- 163u, 182u, 98u, 121u,
- 124u, 158u, 169u, 186u,
- 72u, 130u, 91u, 7u,
- 46u, 54u, 255u, 157u,
- 124u, 124u, 255u, 213u,
- 77u, 154u, 151u, 189u,
- 63u, 108u, 203u, 225u,
- 43u, 154u, 161u, 29u,
- 171u, 139u, 205u, 32u,
- 133u, 170u, 139u, 1u,
- 24u, 66u, 76u, 184u,
- 114u, 57u, 165u, 76u,
- 67u, 131u, 132u, 143u,
- 146u, 154u, 197u, 101u,
- 75u, 117u, 159u, 201u,
- 158u, 71u, 255u, 45u,
- 98u, 249u, 210u, 74u,
- 139u, 162u, 151u, 203u,
- 182u, 255u, 189u, 96u,
- 93u, 80u, 242u, 6u,
- 72u, 126u, 196u, 255u,
- 241u, 79u, 55u, 252u,
- 144u, 120u, 74u, 175u,
- 176u, 90u, 105u, 54u,
- 109u, 128u, 97u, 73u,
- 205u, 195u, 74u, 221u,
- 34u, 99u, 139u, 92u,
- 128u, 98u, 1u, 152u,
- 100u, 131u, 91u, 132u,
- 156u, 160u, 146u, 106u,
- 200u, 109u, 1u, 132u,
- 42u, 145u, 120u, 131u,
- 110u, 211u, 99u, 104u,
- 73u, 132u, 100u, 109u,
- 0u, 118u, 123u, 114u,
- 202u, 116u, 173u, 192u,
- 79u, 40u, 161u, 140u,
- 120u, 58u, 93u, 164u,
- 123u, 113u, 220u, 130u,
- 255u, 119u, 142u, 82u,
- 22u, 57u, 255u, 168u,
- 88u, 77u, 121u, 57u,
- 31u, 139u, 179u, 89u,
- 184u, 89u, 196u, 2u,
- 254u, 1u, 133u, 222u,
- 180u, 99u, 10u, 166u,
- 104u, 200u, 127u, 25u,
- 174u, 161u, 201u, 124u,
- 142u, 189u, 112u, 96u,
- 180u, 127u, 162u, 46u,
- 1u, 156u, 158u, 121u,
- 85u, 57u, 158u, 71u,
- 46u, 27u, 1u, 89u,
- 135u, 178u, 145u, 168u,
- 70u, 200u, 135u, 42u,
- 103u, 179u, 31u, 35u,
- 136u, 140u, 55u, 128u,
- 65u, 102u, 179u, 192u,
- 232u, 140u, 96u, 108u,
- 23u, 1u, 187u, 157u,
- 101u, 255u, 143u, 89u,
- 63u, 200u, 171u, 84u,
- 144u, 173u, 116u, 163u,
- 93u, 100u, 154u, 139u,
- 109u, 98u, 187u, 34u,
- 53u, 121u, 204u, 152u,
- 226u, 1u, 135u, 141u,
- 110u, 31u, 92u, 116u,
- 170u, 58u, 149u, 7u,
- 109u, 36u, 91u, 175u,
- 97u, 130u, 127u, 47u,
- 184u, 255u, 96u, 120u,
- 247u, 102u, 46u, 107u,
- 59u, 232u, 156u, 126u,
- 167u, 179u, 31u, 1u,
- 51u, 201u, 138u, 132u,
- 118u, 153u, 1u, 70u,
- 161u, 218u, 42u, 120u,
- 108u, 185u, 203u, 201u,
- 98u, 32u, 185u, 204u,
- 89u, 131u, 194u, 109u,
- 56u, 169u, 86u, 254u,
- 96u, 36u, 215u, 255u,
- 66u, 116u, 37u, 179u,
- 255u, 162u, 148u, 100u,
- 146u, 124u, 82u, 175u,
- 110u, 159u, 100u, 138u,
- 118u, 186u, 176u, 137u,
- 1u, 162u, 39u, 189u,
- 230u, 129u, 239u, 78u,
- 208u, 110u, 194u, 212u,
- 200u, 133u, 69u, 167u,
- 68u, 154u, 155u, 197u,
- 95u, 80u, 191u, 1u,
- 175u, 144u, 108u, 70u,
- 59u, 88u, 114u, 132u,
- 216u, 105u, 204u, 57u,
- 167u, 121u, 189u, 98u,
- 154u, 206u, 74u, 255u,
- 129u, 211u, 62u, 93u,
- 86u, 248u, 224u, 62u,
- 145u, 56u, 124u, 163u,
- 180u, 122u, 0u, 81u,
- 200u, 209u, 135u, 112u,
- 122u, 16u, 1u, 169u,
- 106u, 29u, 80u, 153u,
- 138u, 201u, 163u, 92u,
- 107u, 89u, 113u, 150u,
- 70u, 20u, 1u, 137u,
- 143u, 208u, 92u, 181u,
- 59u, 75u, 137u, 144u,
- 97u, 132u, 26u, 110u,
- 167u, 72u, 171u, 0u,
- 64u, 6u, 141u, 160u,
- 84u, 139u, 168u, 21u,
- 136u, 199u, 49u, 198u,
- 154u, 155u, 144u, 181u,
- 61u, 255u, 27u, 157u,
- 105u, 127u, 108u, 134u,
- 142u, 105u, 144u, 114u,
- 109u, 64u, 14u, 76u,
- 18u, 248u, 164u, 92u,
- 128u, 220u, 114u, 1u,
- 161u, 136u, 141u, 147u,
- 76u, 153u, 102u, 183u,
- 125u, 173u, 1u, 69u,
- 90u, 82u, 76u, 76u,
- 183u, 135u, 166u, 162u,
- 133u, 127u, 159u, 181u,
- 1u, 158u, 83u, 103u,
- 95u, 39u, 152u, 84u,
- 109u, 71u, 116u, 140u,
- 31u, 3u, 124u, 152u,
- 122u, 171u, 1u, 186u,
- 178u, 211u, 156u, 112u,
- 238u, 216u, 12u, 158u,
- 144u, 163u, 121u, 64u,
- 123u, 125u, 159u, 181u,
- 94u, 129u, 210u, 71u,
- 255u, 129u, 8u, 146u,
- 213u, 71u, 194u, 151u,
- 87u, 98u, 27u, 180u,
- 193u, 174u, 84u, 193u,
- 64u, 162u, 152u, 0u,
- 233u, 58u, 151u, 99u,
- 99u, 67u, 203u, 170u,
- 68u, 115u, 1u, 128u,
- 132u, 46u, 63u, 117u,
- 56u, 255u, 55u, 85u,
- 131u, 174u, 87u, 223u,
- 43u, 136u, 109u, 174u,
- 128u, 92u, 105u, 162u,
- 114u, 161u, 130u, 162u,
- 123u, 255u, 123u, 27u,
- 87u, 121u, 85u, 143u,
- 132u, 77u, 157u, 81u,
- 220u, 117u, 64u, 67u,
- 115u, 178u, 1u, 93u,
- 121u, 124u, 123u, 66u,
- 145u, 132u, 80u, 149u,
- 204u, 107u, 115u, 125u,
- 164u, 158u, 255u, 69u,
- 154u, 106u, 61u, 134u,
- 131u, 49u, 135u, 82u,
- 107u, 102u, 146u, 126u,
- 145u, 0u, 135u, 182u,
- 240u, 154u, 167u, 82u,
- 161u, 60u, 163u, 109u,
- 141u, 69u, 226u, 87u,
- 121u, 121u, 160u, 171u,
- 99u, 127u, 175u, 130u,
- 255u, 180u, 132u, 146u,
- 1u, 144u, 78u, 142u,
- 88u, 168u, 247u, 105u,
- 158u, 121u, 146u, 119u,
- 60u, 200u, 156u, 208u,
- 84u, 129u, 146u, 229u,
- 125u, 161u, 1u, 56u,
- 155u, 179u, 61u, 221u,
- 140u, 55u, 51u, 107u,
- 140u, 189u, 147u, 161u,
- 105u, 182u, 192u, 118u,
- 1u, 205u, 105u, 126u,
- 48u, 186u, 96u, 154u,
- 48u, 255u, 124u, 110u,
- 159u, 188u, 165u, 123u,
- 155u, 75u, 159u, 128u,
- 73u, 187u, 1u, 154u,
- 57u, 216u, 142u, 255u,
- 100u, 98u, 109u, 58u,
- 138u, 206u, 109u, 68u,
- 154u, 90u, 73u, 172u,
- 83u, 255u, 152u, 176u,
- 119u, 83u, 141u, 106u,
- 149u, 184u, 226u, 51u,
- 132u, 36u, 183u, 190u,
- 81u, 69u, 113u, 68u,
- 150u, 103u, 159u, 168u,
- 99u, 127u, 94u, 255u,
- 92u, 158u, 104u, 153u,
- 127u, 120u, 172u, 116u,
- 84u, 159u, 61u, 88u,
- 0u, 131u, 162u, 99u,
- 81u, 23u, 155u, 50u,
- 136u, 255u, 112u, 122u,
- 96u, 105u, 88u, 188u,
- 142u, 70u, 132u, 151u,
- 159u, 92u, 163u, 187u,
- 74u, 15u, 1u, 73u,
- 70u, 80u, 160u, 145u,
- 99u, 40u, 78u, 67u,
- 187u, 201u, 109u, 65u,
- 142u, 142u, 70u, 83u,
- 123u, 1u, 133u, 133u,
- 187u, 181u, 78u, 20u,
- 135u, 220u, 146u, 105u,
- 94u, 136u, 71u, 50u,
- 126u, 131u, 208u, 178u,
- 71u, 1u, 170u, 55u,
- 204u, 34u, 162u, 195u,
- 255u, 213u, 123u, 100u,
- 100u, 67u, 141u, 200u,
- 139u, 110u, 166u, 47u,
- 81u, 67u, 115u, 142u,
- 153u, 94u, 139u, 103u,
- 212u, 47u, 84u, 172u,
- 133u, 102u, 168u, 136u,
- 255u, 23u, 99u, 62u,
- 113u, 191u, 93u, 142u,
- 171u, 250u, 90u, 1u,
- 161u, 114u, 95u, 221u,
- 164u, 80u, 161u, 147u,
- 165u, 126u, 133u, 51u,
- 216u, 168u, 160u, 83u,
- 85u, 176u, 102u, 0u,
- 134u, 60u, 57u, 30u,
- 144u, 168u, 143u, 148u,
- 133u, 129u, 87u, 78u,
- 164u, 124u, 168u, 66u,
- 86u, 1u, 162u, 180u,
- 60u, 39u, 113u, 152u,
- 129u, 117u, 152u, 0u,
- 171u, 215u, 132u, 213u,
- 131u, 182u, 213u, 111u,
- 53u, 101u, 166u, 24u,
- 93u, 42u, 31u, 78u,
- 123u, 17u, 39u, 148u,
- 234u, 101u, 1u, 222u,
- 1u, 55u, 23u, 164u,
- 82u, 255u, 175u, 153u,
- 99u, 213u, 232u, 196u,
- 143u, 235u, 171u, 159u,
- 156u, 244u, 103u, 116u,
- 145u, 186u, 255u, 120u,
- 46u, 64u, 119u, 84u,
- 12u, 152u, 175u, 191u,
- 141u, 91u, 153u, 135u,
- 212u, 1u, 183u, 201u,
- 238u, 114u, 77u, 188u,
- 198u, 222u, 134u, 174u,
- 166u, 86u, 225u, 114u,
- 47u, 70u, 255u, 118u,
- 136u, 82u, 219u, 144u,
- 170u, 121u, 225u, 92u,
- 95u, 33u, 126u, 208u,
- 142u, 39u, 128u, 124u,
- 102u, 144u, 214u, 81u,
- 232u, 151u, 79u, 1u,
- 150u, 90u, 1u, 149u,
- 167u, 1u, 73u, 130u,
- 75u, 135u, 141u, 39u,
- 111u, 63u, 164u, 226u,
- 101u, 196u, 78u, 104u,
- 146u, 151u, 254u, 129u,
- 10u, 1u, 98u, 112u,
- 128u, 180u, 164u, 74u,
- 104u, 138u, 84u, 185u,
- 167u, 144u, 129u, 154u,
- 86u, 197u, 211u, 1u,
- 219u, 100u, 136u, 229u,
- 95u, 162u, 109u, 194u,
- 134u, 139u, 82u, 245u,
- 155u, 215u, 24u, 1u,
- 212u, 55u, 19u, 46u,
- 202u, 88u, 189u, 221u,
- 122u, 1u, 229u, 125u,
- 226u, 134u, 124u, 127u,
- 170u, 109u, 250u, 211u,
- 43u, 200u, 163u, 60u,
- 255u, 179u, 184u, 186u,
- 46u, 136u, 163u, 106u,
- 228u, 147u, 66u, 119u,
- 76u, 116u, 215u, 175u,
- 182u, 52u, 202u, 106u,
- 196u, 125u, 30u, 145u,
- 128u, 255u, 156u, 20u,
- 45u, 150u, 109u, 30u,
- 255u, 98u, 131u, 122u,
- 225u, 192u, 81u, 154u,
- 80u, 51u, 132u, 10u,
- 181u, 255u, 90u, 192u,
- 154u, 148u, 35u, 8u,
- 14u, 124u, 34u, 165u,
- 45u, 183u, 205u, 171u,
- 145u, 131u, 87u, 80u,
- 74u, 103u, 135u, 79u,
- 157u, 136u, 56u, 124u,
- 0u, 105u, 20u, 201u,
- 65u, 80u, 1u, 104u,
- 115u, 189u, 61u, 148u,
- 114u, 136u, 86u, 141u,
- 97u, 167u, 103u, 121u,
- 248u, 79u, 248u, 94u,
- 77u, 155u, 168u, 147u,
- 99u, 243u, 210u, 109u,
- 199u, 188u, 78u, 1u,
- 175u, 217u, 148u, 111u,
- 79u, 255u, 115u, 187u,
- 150u, 17u, 185u, 105u,
- 207u, 24u, 120u, 77u,
- 205u, 144u, 155u, 211u,
- 203u, 135u, 94u, 198u,
- 129u, 175u, 70u, 87u,
- 255u, 132u, 195u, 18u,
- 18u, 107u, 41u, 140u,
- 126u, 174u, 73u, 106u,
- 128u, 137u, 112u, 80u,
- 57u, 98u, 1u, 159u,
- 54u, 145u, 129u, 113u,
- 166u, 131u, 167u, 87u,
- 95u, 212u, 153u, 150u,
- 255u, 157u, 118u, 84u,
- 1u, 181u, 141u, 165u,
- 40u, 129u, 103u, 135u,
- 104u, 192u, 71u, 206u,
- 193u, 125u, 207u, 198u,
- 67u, 98u, 143u, 120u,
- 197u, 104u, 124u, 110u,
- 100u, 135u, 208u, 104u,
- 197u, 112u, 1u, 160u,
- 247u, 125u, 152u, 255u,
- 114u, 154u, 204u, 180u,
- 85u, 200u, 144u, 106u,
- 82u, 218u, 220u, 99u,
- 129u, 204u, 34u, 255u,
- 78u, 207u, 208u, 177u,
- 254u, 99u, 81u, 167u,
- 37u, 121u, 224u, 163u,
- 151u, 208u, 191u, 165u,
- 227u, 112u, 63u, 153u,
- 78u, 229u, 173u, 86u,
- 255u, 125u, 121u, 65u,
- 182u, 180u, 88u, 140u,
- 195u, 1u, 98u, 50u,
- 180u, 190u, 19u, 91u,
- 100u, 125u, 113u, 105u,
- 40u, 2u, 137u, 168u,
- 98u, 159u, 62u, 117u,
- 59u, 134u, 208u, 123u,
- 149u, 82u, 100u, 1u,
- 147u, 112u, 155u, 107u,
- 177u, 104u, 39u, 203u,
- 255u, 195u, 168u, 69u,
- 124u, 100u, 237u, 206u,
- 141u, 255u, 223u, 239u,
- 32u, 127u, 117u, 190u,
- 167u, 126u, 91u, 118u,
- 196u, 93u, 105u, 82u,
- 111u, 87u, 166u, 156u,
- 132u, 108u, 199u, 72u,
- 254u, 227u, 50u, 153u,
- 100u, 220u, 217u, 1u,
- 255u, 80u, 130u, 143u,
- 114u, 184u, 112u, 54u,
- 147u, 14u, 83u, 103u,
- 190u, 63u, 214u, 75u,
- 54u, 80u, 114u, 69u,
- 108u, 164u, 186u, 87u,
- 193u, 212u, 153u, 1u,
- 97u, 226u, 136u, 184u,
- 73u, 52u, 71u, 135u,
- 7u, 108u, 149u, 135u,
- 65u, 106u, 67u, 52u,
- 182u, 109u, 0u, 241u,
- 122u, 163u, 111u, 126u,
- 84u, 118u, 4u, 35u,
- 154u, 186u, 141u, 1u,
- 118u, 43u, 105u, 119u,
- 1u, 148u, 187u, 128u,
- 133u, 158u, 144u, 134u,
- 12u, 84u, 189u, 105u,
- 102u, 133u, 77u, 129u,
- 1u, 132u, 41u, 108u,
- 136u, 98u, 167u, 174u,
- 120u, 113u, 130u, 111u,
- 245u, 227u, 23u, 235u,
- 116u, 17u, 69u, 217u,
- 102u, 1u, 145u, 72u,
- 33u, 148u, 189u, 141u,
- 226u, 227u, 81u, 141u,
- 166u, 142u, 1u, 206u,
- 27u, 27u, 97u, 137u,
- 23u, 135u, 56u, 174u,
- 3u, 70u, 146u, 98u,
- 148u, 107u, 13u, 39u,
- 157u, 87u, 133u, 186u,
- 133u, 169u, 211u, 27u,
- 128u, 255u, 113u, 141u,
- 236u, 110u, 69u, 32u,
- 178u, 185u, 118u, 255u,
- 175u, 24u, 125u, 122u,
- 85u, 57u, 215u, 219u,
- 32u, 69u, 149u, 97u,
- 68u, 150u, 129u, 198u,
- 87u, 102u, 1u, 96u,
- 29u, 182u, 129u, 39u,
- 255u, 151u, 248u, 19u,
- 211u, 90u, 12u, 254u,
- 248u, 92u, 193u, 244u,
- 67u, 68u, 91u, 35u,
- 138u, 101u, 0u, 202u,
- 140u, 19u, 206u, 163u,
- 37u, 160u, 121u, 214u,
- 238u, 38u, 88u, 239u,
- 250u, 181u, 119u, 174u,
- 75u, 1u, 105u, 35u,
- 87u, 21u, 178u, 138u,
- 145u, 7u, 231u, 157u,
- 187u, 175u, 174u, 255u,
- 203u, 252u, 227u, 211u,
- 254u, 151u, 161u, 156u,
- 79u, 114u, 106u, 174u,
- 142u, 203u, 127u, 94u,
- 118u, 183u, 174u, 154u,
- 197u, 101u, 97u, 110u,
- 87u, 119u, 255u, 104u,
- 178u, 83u, 76u, 1u,
- 118u, 198u, 100u, 153u,
- 62u, 108u, 91u, 114u,
- 32u, 90u, 130u, 70u,
- 98u, 156u, 85u, 89u,
- 181u, 150u, 155u, 140u,
- 180u, 168u, 1u, 153u,
- 199u, 78u, 64u, 170u,
- 163u, 91u, 231u, 124u,
- 85u, 255u, 200u, 93u,
- 119u, 105u, 107u, 80u,
- 117u, 172u, 133u, 133u,
- 187u, 73u, 188u, 105u,
- 122u, 143u, 69u, 141u,
- 217u, 91u, 216u, 41u,
- 170u, 165u, 0u, 44u,
- 88u, 103u, 49u, 135u,
- 113u, 1u, 137u, 145u,
- 91u, 137u, 103u, 86u,
- 116u, 228u, 137u, 138u,
- 167u, 217u, 111u, 82u,
- 228u, 233u, 101u, 178u,
- 161u, 218u, 145u, 201u,
- 18u, 147u, 1u, 164u,
- 205u, 38u, 111u, 89u,
- 36u, 141u, 122u, 90u,
- 56u, 182u, 224u, 56u,
- 80u, 155u, 255u, 141u,
- 87u, 151u, 60u, 162u,
- 72u, 255u, 204u, 115u,
- 112u, 16u, 114u, 93u,
- 247u, 96u, 194u, 184u,
- 129u, 151u, 72u, 69u,
- 86u, 149u, 147u, 73u,
- 226u, 102u, 60u, 123u,
- 3u, 56u, 117u, 255u,
- 1u, 221u, 93u, 37u,
- 217u, 144u, 98u, 239u,
- 131u, 116u, 184u, 168u,
- 187u, 16u, 81u, 49u,
- 68u, 38u, 134u, 80u,
- 117u, 89u, 139u, 206u,
- 104u, 126u, 122u, 107u,
- 255u, 226u, 184u, 219u,
- 166u, 105u, 143u, 119u,
- 110u, 121u, 133u, 118u,
- 94u, 1u, 125u, 114u,
- 219u, 155u, 67u, 148u,
- 158u, 1u, 77u, 85u,
- 159u, 124u, 160u, 108u,
- 58u, 122u, 175u, 175u,
- 27u, 114u, 54u, 173u,
- 145u, 137u, 167u, 151u,
- 141u, 98u, 1u, 159u,
- 76u, 109u, 109u, 107u,
- 155u, 75u, 143u, 142u,
- 117u, 101u, 176u, 87u,
- 145u, 144u, 255u, 52u,
- 130u, 137u, 128u, 121u,
- 149u, 55u, 78u, 171u,
- 70u, 131u, 167u, 64u,
- 141u, 78u, 193u, 110u,
- 91u, 131u, 1u, 165u,
- 122u, 110u, 56u, 170u,
- 202u, 115u, 255u, 213u,
- 98u, 91u, 11u, 120u,
- 126u, 163u, 185u, 131u,
- 233u, 198u, 179u, 82u,
- 231u, 108u, 126u, 134u,
- 63u, 116u, 106u, 233u,
- 139u, 94u, 159u, 176u,
- 84u, 80u, 255u, 99u,
- 146u, 152u, 121u, 104u,
- 40u, 86u, 202u, 99u,
- 255u, 182u, 143u, 99u,
- 20u, 29u, 111u, 155u,
- 242u, 159u, 132u, 26u,
- 108u, 52u, 255u, 129u,
- 93u, 162u, 85u, 171u,
- 173u, 6u, 176u, 71u,
- 110u, 79u, 103u, 195u,
- 170u, 179u, 90u, 76u,
- 59u, 121u, 109u, 106u,
- 1u, 183u, 61u, 73u,
- 43u, 61u, 31u, 145u,
- 129u, 99u, 101u, 99u,
- 144u, 137u, 133u, 81u,
- 85u, 126u, 1u, 170u,
- 70u, 43u, 22u, 196u,
- 147u, 129u, 115u, 192u,
- 34u, 155u, 232u, 228u,
- 114u, 255u, 137u, 91u,
- 207u, 174u, 189u, 65u,
- 125u, 164u, 88u, 0u,
- 98u, 38u, 41u, 97u,
- 162u, 116u, 76u, 46u,
- 180u, 52u, 184u, 57u,
- 51u, 154u, 108u, 85u,
- 54u, 175u, 122u, 145u,
- 85u, 255u, 250u, 207u,
- 163u, 124u, 102u, 89u,
- 96u, 30u, 78u, 85u,
- 223u, 41u, 173u, 93u,
- 255u, 38u, 146u, 227u,
- 116u, 136u, 128u, 131u,
- 121u, 154u, 171u, 255u,
- 99u, 63u, 202u, 147u,
- 145u, 101u, 99u, 89u,
- 137u, 235u, 221u, 134u,
- 22u, 217u, 0u, 214u,
- 147u, 22u, 115u, 179u,
- 107u, 193u, 95u, 174u,
- 80u, 1u, 75u, 124u,
- 170u, 127u, 134u, 233u,
- 125u, 117u, 59u, 179u,
- 139u, 138u, 217u, 101u,
- 253u, 162u, 255u, 118u,
- 255u, 250u, 160u, 123u,
- 213u, 215u, 179u, 169u,
- 93u, 30u, 161u, 202u,
- 43u, 102u, 225u, 82u,
- 55u, 184u, 150u, 1u,
- 116u, 133u, 42u, 76u,
- 99u, 113u, 189u, 151u,
- 114u, 194u, 141u, 156u,
- 113u, 80u, 122u, 105u,
- 170u, 81u, 167u, 139u,
- 62u, 155u, 132u, 255u,
- 19u, 127u, 1u, 99u,
- 115u, 42u, 154u, 39u,
- 199u, 105u, 139u, 70u,
- 182u, 133u, 72u, 102u,
- 38u, 119u, 159u, 110u,
- 93u, 129u, 133u, 131u,
- 108u, 197u, 104u, 37u,
- 255u, 122u, 181u, 184u,
- 138u, 125u, 84u, 81u,
- 143u, 203u, 93u, 164u,
- 115u, 81u, 1u, 143u,
- 43u, 103u, 183u, 96u,
- 120u, 153u, 151u, 8u,
- 86u, 119u, 95u, 131u,
- 56u, 255u, 121u, 136u,
- 141u, 154u, 179u, 155u,
- 149u, 137u, 171u, 155u,
- 146u, 255u, 110u, 145u,
- 132u, 78u, 61u, 113u,
- 89u, 196u, 104u, 65u,
- 106u, 104u, 90u, 84u,
- 91u, 1u, 150u, 146u,
- 124u, 141u, 148u, 136u,
- 213u, 204u, 130u, 182u,
- 137u, 142u, 255u, 117u,
- 153u, 169u, 37u, 200u,
- 74u, 88u, 75u, 100u,
- 53u, 111u, 128u, 133u,
- 84u, 158u, 84u, 1u,
- 54u, 120u, 136u, 228u,
- 197u, 234u, 21u, 114u,
- 86u, 84u, 107u, 103u,
- 110u, 61u, 120u, 60u,
- 118u, 255u, 108u, 154u,
- 108u, 171u, 111u, 40u,
- 111u, 164u, 97u, 136u,
- 166u, 90u, 162u, 51u,
- 53u, 254u, 88u, 117u,
- 43u, 116u, 89u, 138u,
- 117u, 222u, 255u, 236u,
- 0u, 159u, 133u, 117u,
- 168u, 181u, 119u, 167u,
- 155u, 139u, 103u, 170u,
- 113u, 29u, 175u, 123u,
- 58u, 180u, 89u, 166u,
- 131u, 167u, 147u, 1u,
- 209u, 195u, 109u, 126u,
- 50u, 147u, 192u, 238u,
- 10u, 253u, 145u, 109u,
- 190u, 246u, 131u, 58u,
- 154u, 110u, 28u, 92u,
- 64u, 135u, 0u, 141u,
- 1u, 113u, 209u, 215u,
- 41u, 112u, 193u, 41u,
- 203u, 115u, 171u, 103u,
- 157u, 104u, 63u, 89u,
- 141u, 125u, 113u, 134u,
- 39u, 172u, 163u, 1u,
- 95u, 167u, 202u, 40u,
- 146u, 73u, 128u, 164u,
- 162u, 158u, 136u, 82u,
- 53u, 90u, 177u, 255u,
- 170u, 171u, 199u, 177u,
- 126u, 142u, 121u, 83u,
- 146u, 255u, 131u, 190u,
- 30u, 165u, 87u, 81u,
- 209u, 117u, 195u, 236u,
- 66u, 181u, 180u, 144u,
- 142u, 111u, 88u, 122u,
- 129u, 255u, 36u, 63u,
- 129u, 167u, 76u, 210u,
- 124u, 125u, 49u, 65u,
- 128u, 144u, 62u, 255u,
- 196u, 30u, 152u, 198u,
- 24u, 107u, 170u, 142u,
- 147u, 115u, 10u, 87u,
- 206u, 69u, 185u, 141u,
- 99u, 79u, 255u, 71u,
- 177u, 175u, 20u, 212u,
- 74u, 70u, 112u, 143u,
- 17u, 94u, 1u, 240u,
- 70u, 173u, 164u, 191u,
- 151u, 140u, 172u, 73u,
- 209u, 217u, 206u, 170u,
- 170u, 174u, 158u, 169u,
- 133u, 134u, 116u, 101u,
- 144u, 160u, 142u, 255u,
- 133u, 79u, 139u, 133u,
- 185u, 161u, 144u, 92u,
- 134u, 100u, 255u, 216u,
- 58u, 151u, 167u, 212u,
- 98u, 156u, 227u, 100u,
- 88u, 137u, 226u, 54u,
- 142u, 77u, 135u, 116u,
- 150u, 96u, 196u, 126u,
- 191u, 0u, 43u, 109u,
- 97u, 75u, 97u, 164u,
- 242u, 66u, 179u, 47u,
- 107u, 135u, 99u, 205u,
- 49u, 225u, 255u, 182u,
- 169u, 105u, 155u, 255u,
- 58u, 117u, 141u, 176u,
- 10u, 181u, 99u, 113u,
- 29u, 135u, 17u, 39u,
- 201u, 33u, 136u, 66u,
- 185u, 1u, 141u, 193u,
- 193u, 246u, 49u, 243u,
- 155u, 253u, 191u, 128u,
- 214u, 66u, 129u, 75u,
- 68u, 143u, 84u, 161u,
- 59u, 255u, 64u, 127u,
- 130u, 91u, 105u, 101u,
- 55u, 150u, 169u, 61u,
- 25u, 255u, 229u, 174u,
- 237u, 186u, 148u, 131u,
- 137u, 134u, 135u, 200u,
- 129u, 202u, 142u, 181u,
- 55u, 146u, 191u, 140u,
- 98u, 10u, 58u, 57u,
- 236u, 178u, 158u, 255u,
- 47u, 65u, 187u, 88u,
- 165u, 149u, 1u, 106u,
- 39u, 238u, 125u, 134u,
- 182u, 126u, 28u, 74u,
- 154u, 77u, 255u, 199u,
- 83u, 94u, 88u, 123u,
- 181u, 127u, 176u, 135u,
- 253u, 144u, 83u, 125u,
- 127u, 45u, 255u, 10u,
- 186u, 66u, 33u, 83u,
- 206u, 143u, 184u, 185u,
- 117u, 172u, 88u, 57u,
- 111u, 59u, 142u, 20u,
- 100u, 1u, 174u, 105u,
- 99u, 111u, 120u, 159u,
- 103u, 154u, 103u, 187u,
- 166u, 0u, 186u, 102u,
- 131u, 81u, 145u, 191u,
- 151u, 206u, 217u, 104u,
- 173u, 141u, 155u, 139u,
- 147u, 67u, 150u, 173u,
- 52u, 111u, 101u, 113u,
- 1u, 189u, 146u, 118u,
- 102u, 173u, 117u, 75u,
- 45u, 1u, 15u, 101u,
- 73u, 195u, 34u, 43u,
- 160u, 157u, 82u, 118u,
- 35u, 144u, 139u, 93u,
- 155u, 251u, 174u, 229u,
- 186u, 41u, 151u, 145u,
- 231u, 76u, 63u, 255u,
- 129u, 158u, 71u, 169u,
- 117u, 91u, 111u, 144u,
- 255u, 68u, 171u, 126u,
- 20u, 79u, 182u, 44u,
- 175u, 66u, 61u, 145u,
- 104u, 66u, 170u, 217u,
- 119u, 148u, 122u, 75u,
- 255u, 148u, 110u, 137u,
- 153u, 25u, 158u, 153u,
- 159u, 45u, 81u, 110u,
- 171u, 81u, 14u, 127u,
- 138u, 106u, 94u, 255u,
- 143u, 180u, 200u, 204u,
- 219u, 226u, 105u, 158u,
- 168u, 59u, 65u, 72u,
- 101u, 44u, 211u, 96u,
- 76u, 127u, 1u, 195u,
- 127u, 111u, 69u, 138u,
- 62u, 92u, 118u, 195u,
- 179u, 227u, 143u, 255u,
- 66u, 110u, 134u, 38u,
- 153u, 136u, 167u, 145u,
- 64u, 80u, 151u, 89u,
- 145u, 131u, 163u, 167u,
- 144u, 136u, 255u, 158u,
- 110u, 89u, 128u, 152u,
- 1u, 199u, 133u, 87u,
- 61u, 106u, 158u, 222u,
- 84u, 164u, 159u, 168u,
- 1u, 199u, 44u, 99u,
- 193u, 120u, 160u, 59u,
- 157u, 170u, 120u, 136u,
- 155u, 210u, 82u, 237u,
- 114u, 203u, 58u, 71u,
- 135u, 42u, 255u, 79u,
- 125u, 139u, 77u, 134u,
- 149u, 153u, 66u, 146u,
- 105u, 173u, 121u, 255u,
- 160u, 88u, 105u, 135u,
- 99u, 58u, 106u, 121u,
- 237u, 170u, 66u, 251u,
- 177u, 115u, 1u, 98u,
- 132u, 252u, 178u, 159u,
- 11u, 71u, 59u, 115u,
- 158u, 24u, 133u, 98u,
- 149u, 195u, 173u, 208u,
- 167u, 45u, 126u, 255u,
- 88u, 94u, 105u, 154u,
- 57u, 120u, 163u, 196u,
- 182u, 104u, 184u, 157u,
- 114u, 26u, 73u, 178u,
- 255u, 122u, 129u, 50u,
- 91u, 82u, 148u, 127u,
- 77u, 155u, 141u, 152u,
- 106u, 55u, 122u, 177u,
- 171u, 154u, 185u, 98u,
- 255u, 65u, 67u, 90u,
- 150u, 109u, 77u, 19u,
- 225u, 198u, 152u, 255u,
- 37u, 147u, 167u, 205u,
- 89u, 112u, 132u, 205u,
- 243u, 129u, 182u, 146u,
- 118u, 60u, 52u, 168u,
- 63u, 178u, 55u, 50u,
- 158u, 82u, 93u, 1u,
- 131u, 160u, 99u, 226u,
- 156u, 228u, 106u, 107u,
- 150u, 106u, 100u, 210u,
- 133u, 255u, 213u, 69u,
- 1u, 182u, 41u, 176u,
- 175u, 197u, 120u, 117u,
- 141u, 56u, 93u, 100u,
- 171u, 111u, 56u, 59u,
- 149u, 151u, 201u, 31u,
- 194u, 151u, 215u, 81u,
- 79u, 69u, 108u, 183u,
- 52u, 115u, 74u, 1u,
- 186u, 203u, 165u, 208u,
- 147u, 32u, 24u, 23u,
- 162u, 86u, 173u, 72u,
- 232u, 1u, 177u, 173u,
- 145u, 210u, 69u, 98u,
- 191u, 92u, 36u, 240u,
- 69u, 46u, 255u, 81u,
- 167u, 119u, 83u, 228u,
- 182u, 140u, 32u, 119u,
- 112u, 170u, 151u, 187u,
- 255u, 190u, 113u, 8u,
- 56u, 114u, 243u, 206u,
- 188u, 19u, 166u, 255u,
- 45u, 152u, 157u, 100u,
- 149u, 22u, 181u, 59u,
- 143u, 89u, 131u, 109u,
- 136u, 110u, 113u, 120u,
- 186u, 100u, 67u, 255u,
- 57u, 88u, 189u, 189u,
- 205u, 91u, 228u, 56u,
- 185u, 105u, 181u, 1u,
- 221u, 139u, 114u, 59u,
- 143u, 111u, 168u, 120u,
- 177u, 149u, 111u, 165u,
- 1u, 196u, 117u, 63u,
- 143u, 162u, 147u, 120u,
- 156u, 127u, 153u, 61u,
- 149u, 150u, 129u, 140u,
- 91u, 132u, 93u, 126u,
- 104u, 144u, 201u, 144u,
- 157u, 151u, 95u, 94u,
- 255u, 113u, 207u, 70u,
- 81u, 192u, 229u, 189u,
- 131u, 157u, 153u, 118u,
- 67u, 75u, 255u, 58u,
- 50u, 64u, 244u, 157u,
- 88u, 141u, 158u, 67u,
- 73u, 74u, 158u, 50u,
- 181u, 135u, 216u, 0u,
- 137u, 50u, 3u, 41u,
- 220u, 124u, 80u, 98u,
- 136u, 138u, 55u, 102u,
- 125u, 169u, 1u, 170u,
- 97u, 143u, 115u, 57u,
- 188u, 156u, 95u, 192u,
- 184u, 247u, 87u, 203u,
- 84u, 1u, 54u, 144u,
- 44u, 36u, 94u, 59u,
- 79u, 17u, 103u, 155u,
- 125u, 14u, 128u, 207u,
- 56u, 41u, 137u, 1u,
- 228u, 207u, 232u, 122u,
- 150u, 186u, 255u, 26u,
- 156u, 121u, 180u, 120u,
- 171u, 125u, 154u, 189u,
- 177u, 167u, 127u, 92u,
- 175u, 154u, 171u, 99u,
- 102u, 196u, 255u, 136u,
- 233u, 199u, 164u, 115u,
- 13u, 61u, 153u, 35u,
- 175u, 196u, 106u, 125u,
- 162u, 245u, 105u, 70u,
- 173u, 119u, 165u, 255u,
- 57u, 92u, 90u, 30u,
- 96u, 247u, 208u, 12u,
- 136u, 67u, 134u, 208u,
- 128u, 104u, 108u, 196u,
- 105u, 81u, 62u, 255u,
- 97u, 81u, 60u, 115u,
- 143u, 48u, 255u, 82u,
- 177u, 205u, 194u, 63u,
- 134u, 211u, 240u, 135u,
- 51u, 128u, 28u, 149u,
- 55u, 191u, 233u, 153u,
- 86u, 132u, 31u, 134u,
- 93u, 211u, 255u, 133u,
- 175u, 115u, 170u, 141u,
- 202u, 177u, 29u, 117u,
- 98u, 133u, 23u, 2u,
- 82u, 114u, 0u, 68u,
- 119u, 127u, 115u, 129u,
- 1u, 86u, 75u, 212u,
- 37u, 126u, 207u, 62u,
- 159u, 136u, 172u, 118u,
- 110u, 255u, 120u, 254u,
- 186u, 129u, 100u, 167u,
- 252u, 5u, 180u, 146u,
- 156u, 122u, 84u, 245u,
- 145u, 119u, 155u, 72u,
- 201u, 208u, 118u, 255u,
- 49u, 159u, 30u, 191u,
- 15u, 224u, 78u, 82u,
- 171u, 142u, 120u, 126u,
- 213u, 47u, 161u, 23u,
- 89u, 132u, 255u, 123u,
- 69u, 13u, 43u, 121u,
- 195u, 104u, 220u, 138u,
- 21u, 198u, 142u, 91u,
- 117u, 189u, 180u, 163u,
- 1u, 52u, 189u, 28u,
- 104u, 55u, 255u, 165u,
- 58u, 58u, 44u, 196u,
- 230u, 210u, 78u, 124u,
- 146u, 107u, 170u, 84u,
- 120u, 153u, 174u, 181u,
- 47u, 117u, 255u, 131u,
- 139u, 132u, 103u, 67u,
- 104u, 112u, 153u, 166u,
- 97u, 165u, 154u, 93u,
- 255u, 134u, 115u, 135u,
- 45u, 83u, 198u, 122u,
- 203u, 102u, 91u, 82u,
- 182u, 187u, 62u, 0u,
- 90u, 164u, 151u, 82u,
- 195u, 135u, 202u, 74u,
- 165u, 243u, 41u, 156u,
- 65u, 115u, 1u, 98u,
- 192u, 141u, 230u, 63u,
- 140u, 161u, 217u, 152u,
- 14u, 74u, 206u, 165u,
- 198u, 34u, 124u, 167u,
- 123u, 113u, 236u, 1u,
- 82u, 112u, 121u, 65u,
- 76u, 159u, 34u, 3u,
- 129u, 178u, 89u, 155u,
- 154u, 236u, 106u, 111u,
- 1u, 140u, 1u, 143u,
- 59u, 61u, 198u, 114u,
- 124u, 104u, 118u, 251u,
- 137u, 206u, 71u, 114u,
- 1u, 62u, 122u, 131u,
- 18u, 95u, 199u, 132u,
- 3u, 169u, 129u, 61u,
- 207u, 19u, 178u, 149u,
- 109u, 192u, 155u, 140u,
- 237u, 104u, 1u, 145u,
- 118u, 142u, 85u, 137u,
- 255u, 97u, 190u, 95u,
- 51u, 143u, 193u, 106u,
- 162u, 41u, 85u, 114u,
- 13u, 176u, 1u, 230u,
- 66u, 27u, 178u, 168u,
- 230u, 129u, 106u, 165u,
- 168u, 150u, 106u, 208u,
- 147u, 157u, 149u, 191u,
- 244u, 87u, 188u, 138u,
- 149u, 154u, 130u, 194u,
- 65u, 109u, 77u, 0u,
- 183u, 255u, 152u, 114u,
- 188u, 63u, 79u, 148u,
- 173u, 180u, 174u, 231u,
- 209u, 62u, 66u, 200u,
- 113u, 13u, 116u, 93u,
- 54u, 1u, 141u, 174u,
- 163u, 198u, 73u, 215u,
- 160u, 130u, 23u, 89u,
- 113u, 95u, 135u, 65u,
- 95u, 127u, 177u, 198u,
- 118u, 255u, 179u, 115u,
- 226u, 96u, 133u, 145u,
- 66u, 120u, 22u, 122u,
- 117u, 108u, 137u, 255u,
- 157u, 188u, 220u, 121u,
- 135u, 161u, 148u, 130u,
- 43u, 154u, 95u, 57u,
- 255u, 49u, 225u, 110u,
- 100u, 223u, 146u, 79u,
- 235u, 159u, 122u, 167u,
- 91u, 54u, 49u, 115u,
- 125u, 198u, 106u, 95u,
- 20u, 116u, 131u, 178u,
- 1u, 218u, 42u, 124u,
- 55u, 121u, 167u, 42u,
- 182u, 99u, 23u, 125u,
- 113u, 69u, 181u, 1u,
- 108u, 191u, 122u, 244u,
- 91u, 147u, 0u, 40u,
- 171u, 34u, 125u, 254u,
- 58u, 156u, 129u, 109u,
- 199u, 180u, 33u, 118u,
- 123u, 94u, 55u, 100u,
- 209u, 93u, 25u, 53u,
- 101u, 176u, 85u, 38u,
- 64u, 163u, 1u, 142u,
- 255u, 135u, 148u, 81u,
- 120u, 159u, 137u, 152u,
- 159u, 117u, 80u, 94u,
- 45u, 90u, 118u, 108u,
- 148u, 129u, 141u, 55u,
- 74u, 170u, 218u, 127u,
- 145u, 182u, 119u, 142u,
- 87u, 191u, 255u, 175u,
- 43u, 91u, 157u, 255u,
- 147u, 105u, 152u, 45u,
- 41u, 114u, 183u, 69u,
- 148u, 169u, 45u, 103u,
- 255u, 166u, 149u, 202u,
- 238u, 174u, 148u, 239u,
- 185u, 143u, 216u, 138u,
- 146u, 146u, 5u, 163u,
- 106u, 126u, 1u, 255u,
- 28u, 116u, 161u, 75u,
- 58u, 194u, 126u, 162u,
- 206u, 118u, 180u, 82u,
- 94u, 179u, 1u, 247u,
- 63u, 241u, 143u, 35u,
- 131u, 69u, 32u, 188u,
- 14u, 199u, 183u, 152u,
- 132u, 136u, 161u, 155u,
- 183u, 115u, 105u, 89u,
- 220u, 180u, 111u, 165u,
- 255u, 114u, 97u, 82u,
- 165u, 1u, 214u, 144u,
- 54u, 165u, 142u, 74u,
- 71u, 187u, 62u, 45u,
- 43u, 232u, 26u, 55u,
- 129u, 156u, 168u, 149u,
- 255u, 117u, 136u, 161u,
- 122u, 75u, 189u, 94u,
- 89u, 186u, 167u, 255u,
- 150u, 250u, 199u, 71u,
- 115u, 70u, 117u, 238u,
- 107u, 92u, 1u, 219u,
- 84u, 131u, 193u, 167u,
- 160u, 255u, 189u, 238u,
- 119u, 135u, 159u, 93u,
- 143u, 145u, 131u, 187u,
- 222u, 180u, 215u, 71u,
- 167u, 226u, 80u, 113u,
- 69u, 121u, 173u, 203u,
- 255u, 134u, 114u, 253u,
- 29u, 131u, 246u, 94u,
- 208u, 136u, 226u, 141u,
- 107u, 63u, 19u, 214u,
- 255u, 180u, 83u, 164u,
- 200u, 128u, 182u, 58u,
- 111u, 255u, 139u, 245u,
- 134u, 127u, 104u, 138u,
- 55u, 235u, 14u, 90u,
- 104u, 34u, 205u, 50u,
- 102u, 77u, 106u, 168u,
- 103u, 0u, 49u, 60u,
- 166u, 109u, 130u, 21u,
- 162u, 18u, 171u, 156u,
- 0u, 164u, 167u, 101u,
- 107u, 92u, 228u, 125u,
- 243u, 98u, 95u, 36u,
- 134u, 251u, 81u, 106u,
- 113u, 46u, 0u, 145u,
- 32u, 142u, 181u, 177u,
- 157u, 160u, 121u, 92u,
- 100u, 133u, 146u, 91u,
- 157u, 100u, 160u, 94u,
- 168u, 144u, 61u, 182u,
- 80u, 133u, 159u, 83u,
- 127u, 80u, 1u, 98u,
- 49u, 216u, 172u, 1u,
- 102u, 128u, 155u, 87u,
- 116u, 74u, 108u, 224u,
- 208u, 156u, 130u, 144u,
- 113u, 91u, 4u, 160u,
- 157u, 72u, 36u, 173u,
- 60u, 149u, 1u, 130u,
- 237u, 184u, 45u, 159u,
- 106u, 64u, 65u, 105u,
- 53u, 82u, 1u, 125u,
- 11u, 148u, 183u, 165u,
- 81u, 236u, 117u, 108u,
- 131u, 98u, 255u, 155u,
- 79u, 76u, 78u, 131u,
- 48u, 84u, 215u, 54u,
- 94u, 151u, 58u, 85u,
- 95u, 253u, 124u, 165u,
- 140u, 179u, 92u, 166u,
- 188u, 125u, 72u, 223u,
- 74u, 99u, 170u, 255u,
- 111u, 73u, 242u, 165u,
- 147u, 78u, 201u, 196u,
- 131u, 155u, 97u, 198u,
- 17u, 144u, 255u, 5u,
- 156u, 166u, 113u, 93u,
- 222u, 167u, 86u, 214u,
- 109u, 148u, 94u, 155u,
- 185u, 255u, 114u, 33u,
- 24u, 165u, 161u, 135u,
- 221u, 193u, 87u, 139u,
- 1u, 80u, 144u, 81u,
- 221u, 73u, 20u, 166u,
- 122u, 19u, 183u, 1u,
- 63u, 98u, 51u, 140u,
- 68u, 192u, 186u, 190u,
- 199u, 214u, 191u, 196u,
- 84u, 99u, 212u, 229u,
- 151u, 55u, 165u, 179u,
- 103u, 206u, 208u, 103u,
- 87u, 255u, 146u, 161u,
- 28u, 140u, 122u, 94u,
- 132u, 75u, 153u, 211u,
- 43u, 72u, 112u, 114u,
- 148u, 1u, 27u, 134u,
- 130u, 75u, 224u, 153u,
- 64u, 138u, 255u, 47u,
- 45u, 201u, 108u, 124u,
- 79u, 182u, 211u, 3u,
- 167u, 160u, 83u, 156u,
- 98u, 72u, 110u, 81u,
- 166u, 115u, 116u, 103u,
- 168u, 135u, 104u, 255u,
- 83u, 183u, 115u, 70u,
- 178u, 185u, 103u, 198u,
- 71u, 116u, 255u, 37u,
- 144u, 112u, 45u, 208u,
- 106u, 182u, 77u, 189u,
- 199u, 129u, 114u, 119u,
- 252u, 137u, 194u, 51u,
- 255u, 151u, 1u, 196u,
- 206u, 150u, 193u, 71u,
- 39u, 57u, 141u, 1u,
- 63u, 95u, 237u, 168u,
- 83u, 171u, 201u, 128u,
- 64u, 184u, 166u, 40u,
- 160u, 205u, 191u, 155u,
- 217u, 155u, 190u, 173u,
- 1u, 78u, 147u, 108u,
- 84u, 199u, 212u, 85u,
- 141u, 78u, 138u, 11u,
- 165u, 48u, 218u, 249u,
- 144u, 201u, 1u, 85u,
- 39u, 184u, 135u, 95u,
- 25u, 78u, 34u, 115u,
- 153u, 98u, 178u, 183u,
- 1u, 181u, 159u, 82u,
- 234u, 195u, 238u, 136u,
- 52u, 142u, 141u, 134u,
- 38u, 1u, 142u, 119u,
- 38u, 103u, 100u, 140u,
- 153u, 137u, 255u, 161u,
- 104u, 101u, 66u, 190u,
- 111u, 124u, 173u, 141u,
- 115u, 139u, 186u, 76u,
- 69u, 248u, 170u, 223u,
- 53u, 201u, 175u, 84u,
- 182u, 146u, 223u, 80u,
- 1u, 111u, 163u, 189u,
- 121u, 112u, 30u, 182u,
- 84u, 212u, 177u, 108u,
- 77u, 68u, 103u, 0u,
- 67u, 172u, 123u, 125u,
- 106u, 112u, 49u, 79u,
- 187u, 102u, 99u, 157u,
- 105u, 144u, 255u, 88u,
- 236u, 169u, 118u, 179u,
- 33u, 169u, 68u, 236u,
- 189u, 173u, 122u, 255u,
- 10u, 118u, 140u, 85u,
- 190u, 143u, 34u, 20u,
- 62u, 209u, 162u, 89u,
- 65u, 255u, 10u, 29u,
- 158u, 195u, 34u, 36u,
- 122u, 147u, 123u, 43u,
- 154u, 174u, 42u, 150u,
- 125u, 42u, 68u, 160u,
- 255u, 211u, 83u, 95u,
- 184u, 77u, 104u, 36u,
- 186u, 219u, 138u, 38u,
- 169u, 91u, 0u, 89u,
- 167u, 114u, 123u, 121u,
- 10u, 15u, 105u, 153u,
- 240u, 231u, 26u, 198u,
- 171u, 169u, 120u, 115u,
- 1u, 29u, 184u, 95u,
- 211u, 95u, 191u, 214u,
- 119u, 145u, 86u, 83u,
- 140u, 179u, 78u, 145u,
- 89u, 132u, 119u, 104u,
- 52u, 117u, 1u, 156u,
- 175u, 158u, 68u, 176u,
- 209u, 1u, 125u, 200u,
- 56u, 184u, 98u, 171u,
- 146u, 148u, 130u, 242u,
- 238u, 255u, 217u, 89u,
- 66u, 184u, 175u, 183u,
- 162u, 236u, 50u, 46u,
- 62u, 138u, 121u, 98u,
- 145u, 95u, 127u, 94u,
- 78u, 238u, 1u, 106u,
- 85u, 83u, 119u, 121u,
- 67u, 97u, 57u, 108u,
- 65u, 88u, 79u, 90u,
- 179u, 89u, 255u, 121u,
- 88u, 80u, 73u, 174u,
- 121u, 152u, 24u, 160u,
- 28u, 197u, 198u, 175u,
- 73u, 93u, 52u, 46u,
- 79u, 200u, 179u, 255u,
- 119u, 131u, 137u, 231u,
- 56u, 59u, 111u, 118u,
- 215u, 139u, 170u, 216u,
- 78u, 121u, 126u, 223u,
- 162u, 255u, 94u, 74u,
- 79u, 92u, 103u, 103u,
- 134u, 174u, 143u, 164u,
- 208u, 88u, 159u, 13u,
- 107u, 135u, 116u, 255u,
- 1u, 63u, 54u, 213u,
- 67u, 73u, 229u, 178u,
- 185u, 132u, 107u, 130u,
- 241u, 75u, 185u, 79u,
- 114u, 101u, 142u, 120u,
- 54u, 147u, 171u, 115u,
- 206u, 139u, 122u, 148u,
- 1u, 143u, 127u, 174u,
- 79u, 163u, 130u, 115u,
- 117u, 108u, 174u, 80u,
- 117u, 162u, 137u, 147u,
- 246u, 1u, 29u, 55u,
- 214u, 148u, 187u, 115u,
- 168u, 183u, 46u, 110u,
- 59u, 140u, 0u, 160u,
- 116u, 133u, 68u, 112u,
- 103u, 119u, 88u, 255u,
- 177u, 159u, 227u, 42u,
- 2u, 81u, 163u, 181u,
- 171u, 169u, 97u, 77u,
- 107u, 118u, 137u, 194u,
- 179u, 197u, 0u, 110u,
- 147u, 202u, 85u, 139u,
- 189u, 141u, 40u, 192u,
- 116u, 108u, 108u, 180u,
- 142u, 228u, 109u, 123u,
- 166u, 0u, 200u, 196u,
- 166u, 144u, 51u, 102u,
- 84u, 155u, 104u, 1u,
- 137u, 177u, 138u, 125u,
- 112u, 130u, 52u, 192u,
- 9u, 165u, 156u, 105u,
- 126u, 244u, 186u, 146u,
- 243u, 20u, 150u, 1u,
- 7u, 101u, 118u, 198u,
- 68u, 183u, 42u, 177u,
- 1u, 24u, 150u, 203u,
- 157u, 102u, 157u, 13u,
- 145u, 23u, 44u, 227u,
- 40u, 120u, 178u, 68u,
- 63u, 139u, 130u, 72u,
- 88u, 129u, 105u, 188u,
- 255u, 174u, 99u, 92u,
- 18u, 168u, 116u, 142u,
- 149u, 103u, 168u, 255u,
- 98u, 1u, 77u, 158u,
- 72u, 51u, 183u, 86u,
- 193u, 164u, 2u, 89u,
- 141u, 232u, 157u, 106u,
- 106u, 123u, 175u, 129u,
- 174u, 120u, 255u, 234u,
- 104u, 124u, 68u, 233u,
- 255u, 23u, 117u, 94u,
- 204u, 143u, 91u, 37u,
- 91u, 212u, 106u, 99u,
- 165u, 126u, 249u, 14u,
- 163u, 196u, 1u, 81u,
- 160u, 192u, 42u, 145u,
- 60u, 134u, 75u, 146u,
- 168u, 157u, 178u, 162u,
- 121u, 48u, 160u, 80u,
- 1u, 94u, 89u, 46u,
- 229u, 161u, 158u, 79u,
- 96u, 49u, 217u, 119u,
- 127u, 143u, 69u, 94u,
- 2u, 153u, 137u, 255u,
- 60u, 144u, 167u, 183u,
- 133u, 85u, 103u, 131u,
- 193u, 110u, 95u, 89u,
- 139u, 118u, 255u, 75u,
- 109u, 137u, 39u, 99u,
- 124u, 172u, 124u, 129u,
- 203u, 83u, 127u, 1u,
- 27u, 171u, 56u, 180u,
- 78u, 185u, 160u, 124u,
- 101u, 219u, 230u, 192u,
- 114u, 102u, 153u, 40u,
- 189u, 144u, 255u, 183u,
- 12u, 99u, 221u, 150u,
- 34u, 112u, 167u, 99u,
- 75u, 98u, 48u, 160u,
- 0u, 127u, 99u, 76u,
- 127u, 81u, 160u, 98u,
- 100u, 111u, 190u, 125u,
- 132u, 217u, 240u, 123u,
- 238u, 245u, 90u, 172u,
- 1u, 103u, 194u, 119u,
- 166u, 161u, 132u, 156u,
- 133u, 158u, 166u, 128u,
- 107u, 166u, 160u, 191u,
- 181u, 151u, 158u, 157u,
- 1u, 144u, 177u, 120u,
- 16u, 125u, 133u, 115u,
- 104u, 95u, 105u, 47u,
- 124u, 189u, 25u, 131u,
- 134u, 1u, 144u, 120u,
- 113u, 229u, 151u, 255u,
- 32u, 229u, 229u, 103u,
- 186u, 128u, 180u, 224u,
- 121u, 148u, 189u, 115u,
- 161u, 159u, 88u, 94u,
- 221u, 92u, 121u, 184u,
- 129u, 151u, 108u, 113u,
- 0u, 103u, 120u, 116u,
- 143u, 73u, 194u, 138u,
- 157u, 43u, 96u, 203u,
- 172u, 134u, 145u, 206u,
- 247u, 53u, 1u, 85u,
- 77u, 163u, 164u, 164u,
- 88u, 213u, 29u, 140u,
- 144u, 151u, 167u, 89u,
- 201u, 1u, 190u, 24u,
- 235u, 170u, 160u, 181u,
- 111u, 157u, 255u, 189u,
- 72u, 104u, 173u, 180u,
- 96u, 76u, 66u, 123u,
- 175u, 213u, 255u, 168u,
- 124u, 146u, 90u, 224u,
- 138u, 142u, 157u, 163u,
- 224u, 152u, 164u, 70u,
- 63u, 148u, 159u, 113u,
- 51u, 118u, 50u, 150u,
- 5u, 162u, 255u, 94u,
- 165u, 131u, 74u, 158u,
- 49u, 178u, 0u, 81u,
- 105u, 206u, 115u, 84u,
- 150u, 191u, 48u, 157u,
- 56u, 73u, 13u, 160u,
- 188u, 60u, 139u, 126u,
- 1u, 199u, 125u, 95u,
- 161u, 208u, 172u, 66u,
- 117u, 143u, 139u, 72u,
- 178u, 153u, 242u, 177u,
- 96u, 157u, 138u, 0u,
- 143u, 245u, 177u, 47u,
- 56u, 108u, 106u, 32u,
- 172u, 219u, 192u, 182u,
- 147u, 116u, 126u, 114u,
- 115u, 176u, 202u, 77u,
- 152u, 135u, 103u, 255u,
- 125u, 132u, 255u, 164u,
- 50u, 69u, 115u, 74u,
- 105u, 93u, 124u, 171u,
- 116u, 87u, 88u, 35u,
- 131u, 191u, 215u, 161u,
- 203u, 124u, 89u, 255u,
- 161u, 108u, 94u, 206u,
- 47u, 200u, 82u, 145u,
- 167u, 255u, 132u, 151u,
- 250u, 74u, 145u, 230u,
- 174u, 108u, 216u, 250u,
- 146u, 127u, 73u, 102u,
- 34u, 101u, 50u, 255u,
- 129u, 185u, 132u, 124u,
- 42u, 133u, 194u, 136u,
- 216u, 179u, 63u, 141u,
- 102u, 209u, 236u, 148u,
- 167u, 231u, 56u, 89u,
- 26u, 152u, 192u, 21u,
- 170u, 187u, 165u, 1u,
- 118u, 132u, 32u, 182u,
- 163u, 149u, 54u, 55u,
- 107u, 1u, 96u, 176u,
- 149u, 185u, 138u, 144u,
- 219u, 97u, 224u, 194u,
- 255u, 126u, 186u, 71u,
- 43u, 118u, 34u, 102u,
- 187u, 90u, 212u, 113u,
- 51u, 102u, 86u, 179u,
- 246u, 96u, 200u, 138u,
- 106u, 176u, 162u, 98u,
- 255u, 214u, 144u, 124u,
- 223u, 126u, 186u, 255u,
- 154u, 93u, 106u, 72u,
- 42u, 45u, 104u, 112u,
- 132u, 163u, 142u, 67u,
- 101u, 177u, 39u, 164u,
- 138u, 255u, 136u, 164u,
- 136u, 78u, 27u, 101u,
- 1u, 87u, 97u, 202u,
- 67u, 54u, 72u, 255u,
- 42u, 148u, 188u, 32u,
- 73u, 47u, 99u, 148u,
- 238u, 188u, 119u, 231u,
- 172u, 254u, 99u, 231u,
- 203u, 169u, 129u, 1u,
- 28u, 98u, 137u, 117u,
- 70u, 108u, 217u, 123u,
- 150u, 255u, 132u, 62u,
- 168u, 160u, 204u, 192u,
- 184u, 156u, 82u, 118u,
- 91u, 151u, 89u, 36u,
- 132u, 159u, 196u, 206u,
- 168u, 130u, 115u, 183u,
- 193u, 77u, 145u, 1u,
- 168u, 73u, 102u, 202u,
- 103u, 148u, 32u, 52u,
- 206u, 219u, 93u, 111u,
- 92u, 182u, 142u, 178u,
- 125u, 64u, 106u, 1u,
- 44u, 60u, 6u, 61u,
- 221u, 57u, 169u, 219u,
- 0u, 124u, 161u, 71u,
- 183u, 90u, 60u, 31u,
- 139u, 216u, 177u, 140u,
- 255u, 120u, 137u, 196u,
- 32u, 88u, 196u, 163u,
- 234u, 137u, 95u, 21u,
- 234u, 61u, 63u, 122u,
- 197u, 89u, 1u, 95u,
- 196u, 108u, 135u, 16u,
- 75u, 46u, 179u, 60u,
- 9u, 130u, 51u, 186u,
- 152u, 173u, 187u, 50u,
- 124u, 63u, 81u, 255u,
- 101u, 123u, 103u, 108u,
- 6u, 131u, 95u, 114u,
- 162u, 255u, 194u, 109u,
- 25u, 198u, 129u, 113u,
- 166u, 177u, 78u, 63u,
- 81u, 192u, 74u, 255u,
- 105u, 97u, 110u, 121u,
- 104u, 131u, 178u, 128u,
- 244u, 173u, 110u, 169u,
- 208u, 1u, 130u, 135u,
- 127u, 112u, 38u, 171u,
- 63u, 119u, 108u, 54u,
- 103u, 105u, 139u, 82u,
- 204u, 173u, 102u, 63u,
- 231u, 77u, 205u, 160u,
- 116u, 189u, 0u, 165u,
- 183u, 251u, 73u, 167u,
- 42u, 142u, 148u, 82u,
- 70u, 178u, 157u, 1u,
- 128u, 91u, 164u, 181u,
- 160u, 85u, 107u, 102u,
- 113u, 83u, 24u, 211u,
- 1u, 147u, 50u, 40u,
- 131u, 33u, 154u, 131u,
- 151u, 94u, 212u, 137u,
- 165u, 187u, 100u, 70u,
- 112u, 84u, 70u, 174u,
- 105u, 120u, 148u, 214u,
- 143u, 133u, 1u, 102u,
- 24u, 88u, 158u, 128u,
- 108u, 107u, 160u, 127u,
- 101u, 72u, 172u, 208u,
- 111u, 255u, 72u, 149u,
- 255u, 180u, 194u, 109u,
- 190u, 197u, 128u, 160u,
- 192u, 114u, 175u, 106u,
- 44u, 67u, 155u, 198u,
- 69u, 135u, 84u, 76u,
- 190u, 111u, 255u, 180u,
- 121u, 58u, 141u, 134u,
- 166u, 77u, 27u, 104u,
- 140u, 71u, 112u, 110u,
- 120u, 131u, 215u, 100u,
- 61u, 145u, 141u, 26u,
- 205u, 254u, 0u, 127u,
- 133u, 145u, 177u, 113u,
- 115u, 109u, 103u, 0u,
- 159u, 198u, 103u, 104u,
- 134u, 148u, 122u, 141u,
- 44u, 137u, 60u, 38u,
- 47u, 238u, 37u, 1u,
- 64u, 166u, 76u, 29u,
- 69u, 110u, 157u, 127u,
- 66u, 81u, 176u, 255u,
- 68u, 84u, 144u, 75u,
- 189u, 94u, 131u, 68u,
- 126u, 210u, 151u, 166u,
- 255u, 142u, 104u, 86u,
- 209u, 117u, 42u, 113u,
- 41u, 76u, 135u, 154u,
- 44u, 16u, 255u, 50u,
- 229u, 79u, 112u, 140u,
- 133u, 177u, 127u, 165u,
- 113u, 0u, 219u, 201u,
- 140u, 119u, 224u, 132u,
- 196u, 147u, 58u, 77u,
- 241u, 187u, 86u, 42u,
- 29u, 178u, 148u, 1u,
- 85u, 197u, 90u, 63u,
- 100u, 179u, 159u, 91u,
- 94u, 62u, 141u, 142u,
- 109u, 1u, 125u, 162u,
- 177u, 143u, 38u, 127u,
- 197u, 130u, 83u, 93u,
- 86u, 130u, 117u, 167u,
- 47u, 111u, 77u, 246u,
- 86u, 118u, 255u, 20u,
- 92u, 59u, 64u, 151u,
- 1u, 159u, 232u, 127u,
- 123u, 31u, 43u, 132u,
- 72u, 131u, 91u, 115u,
- 184u, 255u, 45u, 157u,
- 48u, 166u, 142u, 201u,
- 162u, 145u, 128u, 147u,
- 39u, 90u, 114u, 64u,
- 162u, 138u, 104u, 116u,
- 133u, 83u, 17u, 147u,
- 79u, 124u, 142u, 145u,
- 123u, 124u, 170u, 1u,
- 94u, 76u, 72u, 255u,
- 169u, 213u, 209u, 82u,
- 96u, 139u, 240u, 255u,
- 170u, 100u, 123u, 62u,
- 60u, 66u, 91u, 147u,
- 255u, 94u, 81u, 213u,
- 154u, 178u, 110u, 70u,
- 143u, 71u, 28u, 130u,
- 105u, 106u, 80u, 110u,
- 48u, 137u, 168u, 152u,
- 189u, 122u, 34u, 150u,
- 72u, 255u, 111u, 241u,
- 53u, 146u, 40u, 181u,
- 213u, 237u, 238u, 103u,
- 193u, 98u, 200u, 144u,
- 174u, 55u, 0u, 175u,
- 92u, 96u, 61u, 71u,
- 126u, 176u, 179u, 132u,
- 121u, 153u, 0u, 169u,
- 87u, 136u, 119u, 61u,
- 162u, 80u, 176u, 114u,
- 131u, 162u, 203u, 115u,
- 112u, 191u, 97u, 179u,
- 206u, 85u, 0u, 201u,
- 147u, 212u, 237u, 205u,
- 117u, 160u, 162u, 78u,
- 112u, 107u, 152u, 202u,
- 60u, 53u, 0u, 44u,
- 215u, 71u, 96u, 2u,
- 133u, 170u, 184u, 119u,
- 115u, 234u, 170u, 145u,
- 168u, 58u, 15u, 1u,
- 174u, 68u, 132u, 127u,
- 87u, 36u, 173u, 168u,
- 185u, 180u, 144u, 255u,
- 178u, 163u, 140u, 85u,
- 135u, 67u, 2u, 134u,
- 103u, 162u, 87u, 164u,
- 46u, 40u, 82u, 35u,
- 205u, 233u, 255u, 143u,
- 95u, 195u, 194u, 154u,
- 1u, 165u, 128u, 119u,
- 110u, 65u, 247u, 139u,
- 163u, 177u, 194u, 245u,
- 151u, 1u, 101u, 138u,
- 85u, 68u, 112u, 143u,
- 42u, 93u, 116u, 113u,
- 87u, 164u, 231u, 80u,
- 130u, 65u, 126u, 138u,
- 103u, 208u, 142u, 99u,
- 96u, 130u, 46u, 159u,
- 98u, 255u, 205u, 31u,
- 183u, 103u, 190u, 131u,
- 155u, 132u, 1u, 157u,
- 70u, 147u, 194u, 136u,
- 171u, 127u, 92u, 147u,
- 100u, 205u, 253u, 165u,
- 187u, 152u, 255u, 174u,
- 181u, 76u, 160u, 89u,
- 155u, 117u, 87u, 177u,
- 217u, 130u, 165u, 143u,
- 155u, 137u, 159u, 15u,
- 176u, 131u, 5u, 62u,
- 96u, 255u, 177u, 156u,
- 168u, 68u, 218u, 82u,
- 157u, 115u, 106u, 94u,
- 142u, 164u, 185u, 179u,
- 189u, 255u, 176u, 147u,
- 244u, 35u, 208u, 113u,
- 101u, 100u, 242u, 85u,
- 153u, 77u, 156u, 114u,
- 168u, 255u, 101u, 192u,
- 118u, 106u, 117u, 117u,
- 121u, 69u, 255u, 82u,
- 101u, 78u, 121u, 63u,
- 223u, 172u, 131u, 221u,
- 223u, 61u, 22u, 159u,
- 65u, 117u, 186u, 83u,
- 83u, 179u, 178u, 64u,
- 205u, 124u, 0u, 131u,
- 230u, 30u, 8u, 199u,
- 35u, 72u, 154u, 112u,
- 63u, 187u, 197u, 54u,
- 215u, 255u, 168u, 208u,
- 245u, 185u, 109u, 168u,
- 111u, 221u, 1u, 8u,
- 64u, 126u, 94u, 211u,
- 53u, 127u, 105u, 189u,
- 97u, 100u, 149u, 173u,
- 181u, 123u, 189u, 146u,
- 125u, 150u, 143u, 96u,
- 106u, 169u, 158u, 0u,
- 19u, 132u, 77u, 73u,
- 116u, 220u, 132u, 191u,
- 100u, 101u, 51u, 95u,
- 154u, 2u, 255u, 13u,
- 146u, 199u, 77u, 134u,
- 152u, 178u, 68u, 118u,
- 94u, 121u, 1u, 152u,
- 91u, 96u, 149u, 99u,
- 172u, 38u, 170u, 56u,
- 222u, 201u, 55u, 82u,
- 150u, 1u, 118u, 149u,
- 0u, 134u, 5u, 153u,
- 174u, 143u, 161u, 168u,
- 1u, 182u, 145u, 152u,
- 50u, 105u, 147u, 125u,
- 98u, 104u, 125u, 90u,
- 102u, 67u, 69u, 148u,
- 93u, 198u, 73u, 202u,
- 58u, 138u, 124u, 92u,
- 144u, 87u, 192u, 1u,
- 201u, 168u, 136u, 98u,
- 83u, 142u, 114u, 185u,
- 255u, 150u, 221u, 71u,
- 50u, 122u, 83u, 98u,
- 204u, 128u, 150u, 1u,
- 61u, 143u, 81u, 136u,
- 207u, 142u, 38u, 39u,
- 65u, 51u, 127u, 169u,
- 123u, 135u, 230u, 96u,
- 96u, 3u, 61u, 41u,
- 255u, 160u, 216u, 96u,
- 229u, 106u, 167u, 155u,
- 1u, 171u, 107u, 180u,
- 141u, 150u, 129u, 60u,
- 116u, 140u, 117u, 141u,
- 221u, 114u, 73u, 135u,
- 56u, 79u, 116u, 184u,
- 105u, 31u, 174u, 68u,
- 104u, 10u, 24u, 101u,
- 125u, 59u, 1u, 7u,
- 151u, 174u, 90u, 167u,
- 179u, 46u, 78u, 139u,
- 156u, 112u, 94u, 255u,
- 122u, 229u, 193u, 237u,
- 113u, 177u, 4u, 123u,
- 150u, 157u, 118u, 157u,
- 22u, 207u, 200u, 69u,
- 241u, 255u, 153u, 187u,
- 255u, 161u, 197u, 48u,
- 133u, 103u, 30u, 221u,
- 82u, 130u, 185u, 55u,
- 215u, 42u, 239u, 247u,
- 204u, 126u, 92u, 108u,
- 187u, 1u, 178u, 207u,
- 179u, 213u, 174u, 245u,
- 116u, 175u, 73u, 112u,
- 120u, 144u, 115u, 119u,
- 125u, 253u, 1u, 116u,
- 107u, 122u, 74u, 24u,
- 22u, 150u, 96u, 75u,
- 77u, 120u, 98u, 214u,
- 117u, 79u, 125u, 134u,
- 66u, 100u, 78u, 131u,
- 255u, 206u, 149u, 178u,
- 162u, 185u, 181u, 156u,
- 138u, 240u, 104u, 109u,
- 234u, 255u, 211u, 151u,
- 103u, 8u, 251u, 56u,
- 9u, 138u, 102u, 94u,
- 99u, 97u, 49u, 33u,
- 155u, 234u, 120u, 255u,
- 126u, 177u, 89u, 160u,
- 237u, 216u, 112u, 210u,
- 0u, 199u, 171u, 112u,
- 66u, 148u, 233u, 135u,
- 206u, 194u, 141u, 126u,
- 176u, 107u, 175u, 100u,
- 104u, 62u, 1u, 202u,
- 94u, 151u, 207u, 139u,
- 188u, 127u, 128u, 160u,
- 129u, 193u, 126u, 1u,
- 131u, 158u, 202u, 54u,
- 80u, 67u, 72u, 167u,
- 25u, 118u, 78u, 140u,
- 92u, 95u, 185u, 59u,
- 96u, 54u, 163u, 211u,
- 132u, 246u, 255u, 181u,
- 142u, 146u, 195u, 157u,
- 184u, 10u, 103u, 143u,
- 110u, 114u, 78u, 105u,
- 41u, 8u, 156u, 255u,
- 238u, 149u, 128u, 187u,
- 123u, 53u, 179u, 105u,
- 180u, 53u, 131u, 43u,
- 89u, 150u, 110u, 108u,
- 255u, 131u, 43u, 82u,
- 165u, 152u, 133u, 163u,
- 116u, 177u, 51u, 97u,
- 5u, 92u, 224u, 247u,
- 255u, 111u, 42u, 91u,
- 87u, 161u, 205u, 194u,
- 158u, 132u, 163u, 153u,
- 157u, 121u, 121u, 138u,
- 28u, 255u, 132u, 12u,
- 97u, 75u, 129u, 152u,
- 157u, 47u, 97u, 196u,
- 41u, 94u, 141u, 118u,
- 100u, 255u, 150u, 61u,
- 106u, 1u, 86u, 175u,
- 93u, 115u, 165u, 34u,
- 79u, 186u, 92u, 81u,
- 30u, 146u, 82u, 159u,
- 144u, 166u, 119u, 159u,
- 228u, 69u, 167u, 241u,
- 96u, 125u, 161u, 162u,
- 223u, 1u, 116u, 151u,
- 144u, 130u, 141u, 255u,
- 120u, 148u, 71u, 117u,
- 26u, 124u, 160u, 102u,
- 171u, 126u, 65u, 80u,
- 119u, 171u, 109u, 100u,
- 72u, 90u, 205u, 125u,
- 230u, 199u, 127u, 156u,
- 53u, 255u, 252u, 82u,
- 93u, 73u, 47u, 29u,
- 255u, 113u, 132u, 172u,
- 64u, 11u, 201u, 120u,
- 176u, 100u, 66u, 131u,
- 92u, 57u, 180u, 132u,
- 63u, 189u, 98u, 166u,
- 112u, 147u, 118u, 0u,
- 106u, 150u, 139u, 150u,
- 128u, 70u, 123u, 109u,
- 116u, 132u, 163u, 103u,
- 255u, 121u, 23u, 101u,
- 74u, 154u, 163u, 34u,
- 150u, 132u, 57u, 208u,
- 133u, 138u, 89u, 140u,
- 124u, 115u, 63u, 216u,
- 220u, 255u, 83u, 87u,
- 255u, 31u, 163u, 155u,
- 124u, 85u, 153u, 147u,
- 93u, 117u, 225u, 56u,
- 120u, 165u, 39u, 63u,
- 190u, 109u, 149u, 96u,
- 159u, 174u, 168u, 100u,
- 66u, 164u, 84u, 67u,
- 130u, 255u, 196u, 106u,
- 163u, 160u, 227u, 166u,
- 147u, 134u, 11u, 29u,
- 143u, 174u, 0u, 96u,
- 93u, 76u, 81u, 145u,
- 115u, 170u, 172u, 99u,
- 90u, 172u, 255u, 151u,
- 138u, 92u, 138u, 196u,
- 140u, 91u, 191u, 125u,
- 78u, 120u, 127u, 255u,
- 147u, 84u, 159u, 201u,
- 146u, 183u, 162u, 138u,
- 124u, 161u, 155u, 155u,
- 145u, 188u, 117u, 246u,
- 119u, 2u, 128u, 204u,
- 143u, 141u, 193u, 13u,
- 170u, 38u, 255u, 137u,
- 58u, 50u, 65u, 168u,
- 125u, 176u, 26u, 114u,
- 255u, 196u, 47u, 128u,
- 83u, 121u, 140u, 193u,
- 139u, 44u, 91u, 158u,
- 118u, 119u, 255u, 3u,
- 134u, 91u, 70u, 105u,
- 123u, 25u, 150u, 165u,
- 183u, 134u, 111u, 142u,
- 54u, 140u, 74u, 94u,
- 223u, 255u, 204u, 141u,
- 210u, 32u, 211u, 199u,
- 98u, 255u, 135u, 175u,
- 61u, 217u, 34u, 131u,
- 149u, 135u, 166u, 156u,
- 113u, 132u, 56u, 149u,
- 255u, 205u, 165u, 48u,
- 156u, 123u, 169u, 180u,
- 139u, 152u, 198u, 128u,
- 82u, 120u, 129u, 47u,
- 27u, 163u, 193u, 220u,
- 89u, 142u, 126u, 52u,
- 97u, 68u, 252u, 125u,
- 127u, 0u, 150u, 236u,
- 233u, 57u, 135u, 75u,
- 84u, 84u, 47u, 126u,
- 186u, 91u, 122u, 1u,
- 48u, 131u, 21u, 237u,
- 45u, 56u, 1u, 163u,
- 75u, 77u, 152u, 192u,
- 131u, 132u, 116u, 126u,
- 134u, 188u, 179u, 192u,
- 109u, 118u, 1u, 112u,
- 128u, 101u, 162u, 131u,
- 30u, 78u, 123u, 94u,
- 111u, 92u, 149u, 176u,
- 123u, 81u, 151u, 60u,
- 132u, 1u, 123u, 181u,
- 130u, 184u, 150u, 118u,
- 193u, 157u, 189u, 148u,
- 158u, 48u, 127u, 52u,
- 151u, 110u, 160u, 255u,
- 72u, 110u, 182u, 172u,
- 138u, 166u, 95u, 101u,
- 181u, 76u, 127u, 188u,
- 150u, 123u, 23u, 211u,
- 162u, 48u, 253u, 60u,
- 1u, 59u, 91u, 160u,
- 118u, 77u, 255u, 153u,
- 97u, 140u, 107u, 140u,
- 160u, 135u, 179u, 118u,
- 181u, 116u, 147u, 87u,
- 247u, 62u, 94u, 136u,
- 1u, 150u, 161u, 190u,
- 146u, 175u, 92u, 83u,
- 187u, 100u, 164u, 101u,
- 122u, 1u, 83u, 185u,
- 147u, 72u, 136u, 66u,
- 118u, 183u, 152u, 91u,
- 111u, 154u, 129u, 104u,
- 79u, 91u, 150u, 101u,
- 148u, 165u, 82u, 108u,
- 97u, 146u, 1u, 154u,
- 75u, 238u, 118u, 132u,
- 115u, 142u, 197u, 1u,
- 185u, 37u, 114u, 218u,
- 244u, 182u, 120u, 197u,
- 208u, 142u, 162u, 96u,
- 199u, 210u, 69u, 20u,
- 155u, 93u, 165u, 1u,
- 157u, 217u, 79u, 101u,
- 165u, 158u, 134u, 149u,
- 165u, 167u, 199u, 213u,
- 68u, 90u, 79u, 227u,
- 121u, 0u, 93u, 84u,
- 193u, 82u, 92u, 87u,
- 100u, 249u, 81u, 89u,
- 225u, 170u, 137u, 183u,
- 1u, 118u, 161u, 72u,
- 223u, 18u, 165u, 227u,
- 164u, 201u, 97u, 54u,
- 30u, 172u, 176u, 255u,
- 102u, 132u, 123u, 105u,
- 65u, 97u, 232u, 104u,
- 180u, 139u, 70u, 114u,
- 222u, 55u, 125u, 160u,
- 85u, 1u, 161u, 143u,
- 100u, 145u, 114u, 82u,
- 135u, 61u, 164u, 76u,
- 65u, 68u, 93u, 188u,
- 164u, 161u, 135u, 170u,
- 153u, 186u, 0u, 203u,
- 123u, 31u, 122u, 80u,
- 124u, 95u, 196u, 59u,
- 166u, 255u, 146u, 118u,
- 69u, 214u, 135u, 80u,
- 168u, 163u, 168u, 175u,
- 182u, 157u, 146u, 107u,
- 104u, 124u, 169u, 111u,
- 102u, 255u, 191u, 65u,
- 90u, 160u, 92u, 137u,
- 203u, 118u, 186u, 138u,
- 169u, 1u, 162u, 21u,
- 72u, 122u, 174u, 107u,
- 96u, 16u, 183u, 213u,
- 32u, 58u, 36u, 255u,
- 91u, 106u, 167u, 177u,
- 223u, 203u, 100u, 151u,
- 44u, 186u, 27u, 131u,
- 126u, 254u, 183u, 1u,
- 175u, 180u, 128u, 138u,
- 88u, 183u, 136u, 151u,
- 195u, 94u, 183u, 181u,
- 28u, 39u, 24u, 81u,
- 235u, 189u, 116u, 136u,
- 255u, 95u, 232u, 97u,
- 56u, 188u, 67u, 162u,
- 121u, 94u, 169u, 20u,
- 127u, 76u, 163u, 152u,
- 197u, 168u, 1u, 102u,
- 175u, 106u, 154u, 120u,
- 136u, 131u, 68u, 56u,
- 54u, 157u, 246u, 65u,
- 255u, 108u, 145u, 110u,
- 141u, 88u, 189u, 77u,
- 214u, 59u, 130u, 170u,
- 178u, 255u, 159u, 108u,
- 187u, 152u, 179u, 149u,
- 57u, 11u, 168u, 150u,
- 173u, 124u, 213u, 184u,
- 81u, 29u, 80u, 255u,
- 36u, 27u, 182u, 67u,
- 170u, 111u, 121u, 255u,
- 127u, 115u, 111u, 181u,
- 241u, 242u, 174u, 187u,
- 32u, 21u, 105u, 253u,
- 255u, 107u, 232u, 95u,
- 5u, 184u, 105u, 46u,
- 144u, 32u, 217u, 231u,
- 116u, 110u, 147u, 168u,
- 1u, 138u, 88u, 78u,
- 205u, 59u, 142u, 93u,
- 152u, 223u, 158u, 101u,
- 203u, 194u, 140u, 103u,
- 72u, 129u, 182u, 197u,
- 157u, 74u, 187u, 146u,
- 57u, 99u, 190u, 139u,
- 253u, 145u, 1u, 92u,
- 92u, 111u, 122u, 97u,
- 142u, 112u, 87u, 94u,
- 75u, 101u, 96u, 43u,
- 143u, 109u, 1u, 100u,
- 255u, 79u, 177u, 44u,
- 201u, 170u, 165u, 206u,
- 140u, 174u, 50u, 37u,
- 250u, 100u, 58u, 175u,
- 158u, 125u, 202u, 134u,
- 139u, 255u, 48u, 114u,
- 81u, 161u, 187u, 53u,
- 193u, 213u, 75u, 53u,
- 166u, 177u, 142u, 0u,
- 192u, 49u, 86u, 144u,
- 169u, 130u, 169u, 86u,
- 255u, 94u, 102u, 153u,
- 172u, 127u, 151u, 181u,
- 184u, 86u, 228u, 74u,
- 118u, 151u, 72u, 176u,
- 163u, 224u, 229u, 0u,
- 110u, 59u, 117u, 164u,
- 175u, 218u, 87u, 199u,
- 57u, 110u, 143u, 92u,
- 100u, 114u, 195u, 0u,
- 237u, 166u, 16u, 101u,
- 23u, 100u, 31u, 255u,
- 121u, 83u, 130u, 82u,
- 116u, 46u, 148u, 142u,
- 239u, 94u, 226u, 49u,
- 139u, 101u, 120u, 120u,
- 1u, 198u, 197u, 60u,
- 228u, 199u, 144u, 183u,
- 137u, 216u, 0u, 105u,
- 108u, 193u, 183u, 83u,
- 164u, 119u, 121u, 98u,
- 201u, 138u, 77u, 227u,
- 28u, 155u, 191u, 86u,
- 180u, 129u, 230u, 61u,
- 124u, 187u, 255u, 204u,
- 111u, 118u, 221u, 172u,
- 89u, 124u, 193u, 158u,
- 99u, 172u, 139u, 1u,
- 89u, 202u, 117u, 50u,
- 151u, 186u, 185u, 104u,
- 255u, 117u, 161u, 65u,
- 224u, 121u, 110u, 177u,
- 131u, 171u, 212u, 86u,
- 254u, 92u, 90u, 129u,
- 1u, 40u, 27u, 204u,
- 15u, 165u, 43u, 158u,
- 156u, 158u, 144u, 93u,
- 85u, 137u, 246u, 120u,
- 177u, 172u, 204u, 158u,
- 98u, 220u, 65u, 185u,
- 255u, 129u, 160u, 203u,
- 47u, 196u, 116u, 85u,
- 26u, 64u, 120u, 157u,
- 244u, 255u, 69u, 182u,
- 62u, 70u, 82u, 137u,
- 166u, 83u, 10u, 192u,
- 115u, 192u, 123u, 125u,
- 136u, 149u, 229u, 212u,
- 147u, 150u, 255u, 109u,
- 116u, 134u, 185u, 176u,
- 138u, 35u, 172u, 37u,
- 169u, 136u, 123u, 60u,
- 166u, 87u, 43u, 121u,
- 167u, 255u, 121u, 58u,
- 65u, 244u, 214u, 58u,
- 1u, 162u, 70u, 26u,
- 133u, 138u, 172u, 9u,
- 61u, 48u, 138u, 199u,
- 141u, 153u, 192u, 91u,
- 36u, 109u, 192u, 153u,
- 194u, 164u, 111u, 255u,
- 14u, 191u, 245u, 53u,
- 114u, 90u, 111u, 207u,
- 13u, 220u, 183u, 1u,
- 92u, 138u, 89u, 145u,
- 150u, 220u, 237u, 250u,
- 25u, 196u, 46u, 0u,
- 197u, 187u, 111u, 197u,
- 13u, 206u, 72u, 110u,
- 150u, 163u, 97u, 31u,
- 58u, 255u, 167u, 169u,
- 88u, 76u, 148u, 91u,
- 65u, 91u, 126u, 132u,
- 85u, 173u, 201u, 245u,
- 247u, 102u, 189u, 181u,
- 198u, 118u, 199u, 104u,
- 97u, 201u, 255u, 169u,
- 78u, 158u, 142u, 150u,
- 84u, 246u, 251u, 230u,
- 196u, 138u, 145u, 12u,
- 1u, 96u, 157u, 149u,
- 225u, 178u, 60u, 98u,
- 230u, 177u, 15u, 1u,
- 165u, 141u, 167u, 173u,
- 57u, 95u, 248u, 103u,
- 250u, 16u, 49u, 187u,
- 119u, 87u, 174u, 174u,
- 88u, 166u, 178u, 60u,
- 68u, 194u, 143u, 131u,
- 110u, 194u, 32u, 1u,
- 180u, 128u, 214u, 130u,
- 162u, 140u, 160u, 58u,
- 140u, 158u, 90u, 78u,
- 1u, 157u, 52u, 21u,
- 57u, 38u, 76u, 145u,
- 52u, 119u, 52u, 162u,
- 174u, 182u, 112u, 234u,
- 165u, 117u, 1u, 165u,
- 140u, 177u, 174u, 251u,
- 43u, 93u, 122u, 177u,
- 138u, 179u, 98u, 1u,
- 131u, 113u, 222u, 155u,
- 185u, 107u, 109u, 52u,
- 127u, 148u, 83u, 193u,
- 120u, 1u, 126u, 18u,
- 167u, 170u, 59u, 123u,
- 34u, 0u, 77u, 66u,
- 149u, 156u, 82u, 61u,
- 2u, 105u, 118u, 99u,
- 84u, 205u, 113u, 151u,
- 60u, 96u, 186u, 180u,
- 95u, 112u, 193u, 1u,
- 85u, 184u, 174u, 36u,
- 215u, 143u, 114u, 183u,
- 103u, 95u, 1u, 193u,
- 71u, 77u, 111u, 213u,
- 114u, 105u, 105u, 46u,
- 142u, 192u, 179u, 140u,
- 102u, 231u, 255u, 230u,
- 82u, 0u, 159u, 215u,
- 212u, 44u, 255u, 165u,
- 213u, 71u, 200u, 235u,
- 182u, 103u, 141u, 144u,
- 75u, 244u, 186u, 216u,
- 185u, 161u, 80u, 110u,
- 95u, 255u, 170u, 22u,
- 119u, 133u, 80u, 81u,
- 129u, 33u, 180u, 115u,
- 108u, 152u, 105u, 117u,
- 175u, 255u, 177u, 182u,
- 108u, 122u, 101u, 137u,
- 115u, 118u, 153u, 104u,
- 97u, 105u, 78u, 34u,
- 103u, 255u, 177u, 140u,
- 81u, 142u, 186u, 95u,
- 69u, 255u, 39u, 51u,
- 115u, 75u, 207u, 130u,
- 85u, 136u, 95u, 145u,
- 104u, 107u, 251u, 207u,
- 124u, 96u, 155u, 122u,
- 213u, 123u, 88u, 241u,
- 37u, 255u, 138u, 173u,
- 205u, 232u, 211u, 60u,
- 181u, 177u, 37u, 255u,
- 91u, 62u, 85u, 128u,
- 60u, 115u, 90u, 23u,
- 85u, 132u, 31u, 125u,
- 211u, 138u, 119u, 123u,
- 144u, 186u, 57u, 73u,
- 95u, 85u, 135u, 0u,
- 27u, 0u, 81u, 70u,
- 125u, 170u, 97u, 187u,
- 156u, 159u, 50u, 187u,
- 163u, 155u, 170u, 46u,
- 83u, 97u, 15u, 148u,
- 73u, 149u, 69u, 155u,
- 90u, 131u, 115u, 255u,
- 4u, 128u, 171u, 122u,
- 122u, 180u, 158u, 138u,
- 166u, 225u, 55u, 86u,
- 67u, 64u, 134u, 93u,
- 1u, 209u, 152u, 184u,
- 51u, 1u, 127u, 121u,
- 177u, 229u, 46u, 113u,
- 56u, 226u, 107u, 120u,
- 157u, 85u, 27u, 161u,
- 149u, 52u, 83u, 108u,
- 161u, 129u, 173u, 66u,
- 126u, 177u, 11u, 154u,
- 184u, 117u, 163u, 1u,
- 136u, 42u, 119u, 245u,
- 1u, 126u, 121u, 3u,
- 138u, 8u, 250u, 192u,
- 75u, 35u, 245u, 135u,
- 212u, 18u, 128u, 13u,
- 145u, 1u, 44u, 169u,
- 105u, 99u, 90u, 186u,
- 94u, 76u, 96u, 107u,
- 191u, 130u, 102u, 255u,
- 180u, 240u, 109u, 186u,
- 107u, 78u, 103u, 103u,
- 63u, 57u, 128u, 65u,
- 42u, 139u, 24u, 96u,
- 129u, 129u, 209u, 130u,
- 99u, 50u, 143u, 90u,
- 119u, 7u, 102u, 255u,
- 255u, 64u, 189u, 74u,
- 64u, 145u, 2u, 161u,
- 141u, 177u, 183u, 112u,
- 133u, 77u, 145u, 46u,
- 140u, 9u, 176u, 130u,
- 81u, 52u, 63u, 67u,
- 49u, 186u, 189u, 86u,
- 197u, 255u, 98u, 126u,
- 50u, 198u, 60u, 108u,
- 161u, 213u, 162u, 168u,
- 163u, 206u, 56u, 172u,
- 120u, 118u, 0u, 160u,
- 51u, 190u, 200u, 45u,
- 220u, 69u, 182u, 214u,
- 255u, 125u, 108u, 152u,
- 129u, 88u, 146u, 144u,
- 148u, 129u, 113u, 201u,
- 99u, 76u, 102u, 178u,
- 179u, 222u, 172u, 1u,
- 144u, 194u, 99u, 214u,
- 44u, 138u, 66u, 134u,
- 126u, 145u, 255u, 115u,
- 100u, 114u, 149u, 28u,
- 110u, 100u, 109u, 193u,
- 116u, 135u, 66u, 164u,
- 118u, 88u, 73u, 255u,
- 162u, 123u, 183u, 93u,
- 75u, 73u, 167u, 95u,
- 149u, 83u, 177u, 96u,
- 136u, 89u, 120u, 122u,
- 204u, 77u, 117u, 217u,
- 255u, 200u, 117u, 167u,
- 160u, 7u, 50u, 182u,
- 150u, 157u, 69u, 73u,
- 89u, 210u, 79u, 29u,
- 38u, 128u, 1u, 162u,
- 1u, 105u, 172u, 183u,
- 39u, 112u, 184u, 154u,
- 74u, 112u, 246u, 155u,
- 98u, 100u, 86u, 134u,
- 139u, 135u, 107u, 247u,
- 92u, 122u, 94u, 77u,
- 58u, 132u, 115u, 143u,
- 82u, 172u, 1u, 100u,
- 255u, 76u, 183u, 92u,
- 146u, 136u, 126u, 163u,
- 155u, 91u, 176u, 129u,
- 198u, 160u, 118u, 78u,
- 188u, 66u, 147u, 167u,
- 97u, 105u, 77u, 79u,
- 1u, 149u, 90u, 3u,
- 38u, 135u, 92u, 80u,
- 58u, 255u, 112u, 55u,
- 126u, 166u, 207u, 98u,
- 37u, 78u, 105u, 203u,
- 66u, 203u, 19u, 161u,
- 243u, 146u, 221u, 12u,
- 137u, 1u, 129u, 96u,
- 246u, 134u, 160u, 182u,
- 95u, 49u, 167u, 223u,
- 59u, 109u, 77u, 255u,
- 33u, 73u, 180u, 81u,
- 150u, 197u, 180u, 58u,
- 178u, 152u, 165u, 104u,
- 25u, 149u, 214u, 143u,
- 172u, 74u, 174u, 1u,
- 107u, 191u, 63u, 68u,
- 253u, 60u, 45u, 87u,
- 123u, 69u, 0u, 127u,
- 173u, 209u, 161u, 120u,
- 120u, 142u, 111u, 133u,
- 116u, 100u, 104u, 112u,
- 68u, 1u, 100u, 68u,
- 128u, 242u, 126u, 138u,
- 130u, 85u, 147u, 33u,
- 72u, 137u, 78u, 145u,
- 22u, 69u, 174u, 213u,
- 106u, 13u, 241u, 1u,
- 203u, 126u, 255u, 59u,
- 242u, 104u, 141u, 249u,
- 232u, 232u, 63u, 193u,
- 215u, 49u, 107u, 171u,
- 89u, 8u, 162u, 180u,
- 142u, 176u, 92u, 255u,
- 95u, 212u, 90u, 177u,
- 95u, 204u, 84u, 199u,
- 255u, 147u, 129u, 124u,
- 160u, 196u, 81u, 180u,
- 191u, 177u, 165u, 150u,
- 192u, 196u, 186u, 129u,
- 173u, 19u, 211u, 79u,
- 72u, 0u, 28u, 181u,
- 96u, 132u, 211u, 159u,
- 63u, 60u, 147u, 1u,
- 60u, 107u, 107u, 129u,
- 148u, 202u, 55u, 179u,
- 124u, 147u, 88u, 133u,
- 151u, 1u, 169u, 187u,
- 125u, 86u, 158u, 114u,
- 119u, 157u, 63u, 203u,
- 156u, 0u, 104u, 245u,
- 109u, 135u, 126u, 62u,
- 141u, 84u, 78u, 26u,
- 132u, 106u, 187u, 55u,
- 101u, 140u, 42u, 63u,
- 127u, 187u, 210u, 122u,
- 118u, 121u, 69u, 73u,
- 116u, 117u, 1u, 172u,
- 216u, 69u, 138u, 137u,
- 170u, 151u, 93u, 87u,
- 39u, 185u, 141u, 106u,
- 49u, 255u, 93u, 174u,
- 233u, 81u, 69u, 92u,
- 159u, 220u, 121u, 133u,
- 136u, 134u, 134u, 1u,
- 107u, 152u, 248u, 188u,
- 67u, 148u, 189u, 115u,
- 21u, 111u, 113u, 221u,
- 209u, 91u, 2u, 255u,
- 24u, 58u, 37u, 78u,
- 255u, 122u, 236u, 32u,
- 32u, 212u, 7u, 6u,
- 92u, 209u, 220u, 93u,
- 92u, 84u, 208u, 147u,
- 1u, 165u, 122u, 168u,
- 179u, 202u, 209u, 77u,
- 135u, 168u, 157u, 79u,
- 144u, 48u, 73u, 111u,
- 99u, 81u, 96u, 255u,
- 236u, 72u, 130u, 117u,
- 38u, 134u, 202u, 87u,
- 66u, 170u, 168u, 192u,
- 164u, 25u, 211u, 176u,
- 135u, 83u, 0u, 116u,
- 140u, 115u, 174u, 169u,
- 230u, 55u, 86u, 160u,
- 208u, 132u, 87u, 67u,
- 99u, 206u, 147u, 151u,
- 104u, 1u, 6u, 164u,
- 2u, 136u, 161u, 138u,
- 180u, 165u, 108u, 175u,
- 75u, 165u, 18u, 151u,
- 1u, 114u, 4u, 217u,
- 70u, 250u, 205u, 119u,
- 113u, 151u, 125u, 98u,
- 185u, 185u, 98u, 187u,
- 52u, 105u, 154u, 91u,
- 63u, 128u, 1u, 115u,
- 184u, 179u, 133u, 167u,
- 88u, 184u, 20u, 139u,
- 132u, 95u, 127u, 85u,
- 116u, 205u, 255u, 200u,
- 82u, 176u, 81u, 250u,
- 212u, 226u, 215u, 164u,
- 0u, 132u, 60u, 252u,
- 137u, 131u, 29u, 113u,
- 153u, 144u, 87u, 1u,
- 176u, 99u, 102u, 93u,
- 84u, 231u, 226u, 148u,
- 51u, 100u, 182u, 182u,
- 220u, 36u, 172u, 240u,
- 131u, 29u, 137u, 131u,
- 51u, 197u, 1u, 223u,
- 167u, 201u, 176u, 79u,
- 60u, 163u, 156u, 196u,
- 117u, 238u, 163u, 60u,
- 94u, 255u, 90u, 126u,
- 29u, 127u, 112u, 29u,
- 157u, 8u, 195u, 117u,
- 135u, 154u, 121u, 38u,
- 184u, 130u, 117u, 171u,
- 249u, 133u, 255u, 178u,
- 188u, 94u, 96u, 158u,
- 156u, 127u, 89u, 121u,
- 124u, 214u, 100u, 131u,
- 146u, 121u, 145u, 1u,
- 100u, 92u, 137u, 190u,
- 145u, 97u, 55u, 85u,
- 140u, 142u, 100u, 191u,
- 179u, 158u, 70u, 0u,
- 1u, 235u, 229u, 162u,
- 218u, 64u, 116u, 126u,
- 199u, 199u, 133u, 135u,
- 87u, 163u, 87u, 235u,
- 12u, 30u, 253u, 230u,
- 16u, 139u, 73u, 148u,
- 223u, 173u, 248u, 192u,
- 116u, 47u, 122u, 1u,
- 67u, 121u, 158u, 150u,
- 113u, 128u, 113u, 7u,
- 17u, 150u, 1u, 121u,
- 118u, 186u, 93u, 216u,
- 50u, 78u, 131u, 36u,
- 255u, 112u, 132u, 145u,
- 27u, 129u, 209u, 63u,
- 57u, 15u, 44u, 225u,
- 164u, 175u, 235u, 133u,
- 226u, 72u, 18u, 190u,
- 131u, 255u, 164u, 101u,
- 101u, 62u, 136u, 106u,
- 53u, 202u, 96u, 6u,
- 238u, 214u, 196u, 255u,
- 214u, 14u, 83u, 122u,
- 23u, 153u, 213u, 159u,
- 173u, 172u, 255u, 213u,
- 189u, 93u, 94u, 73u,
- 116u, 182u, 84u, 86u,
- 191u, 70u, 101u, 133u,
- 158u, 255u, 164u, 216u,
- 116u, 169u, 70u, 236u,
- 112u, 83u, 66u, 187u,
- 13u, 121u, 123u, 143u,
- 121u, 10u, 103u, 103u,
- 115u, 170u, 171u, 232u,
- 100u, 114u, 38u, 82u,
- 161u, 138u, 0u, 199u,
- 167u, 76u, 223u, 183u,
- 129u, 243u, 228u, 153u,
- 143u, 126u, 41u, 126u,
- 61u, 255u, 139u, 20u,
- 230u, 184u, 180u, 201u,
- 58u, 181u, 161u, 35u,
- 142u, 209u, 151u, 131u,
- 0u, 62u, 195u, 69u,
- 106u, 138u, 106u, 118u,
- 135u, 85u, 244u, 202u,
- 178u, 141u, 73u, 151u,
- 2u, 154u, 255u, 123u,
- 155u, 124u, 116u, 169u,
- 113u, 114u, 206u, 35u,
- 36u, 1u, 64u, 179u,
- 191u, 246u, 14u, 109u,
- 166u, 151u, 25u, 113u,
- 122u, 205u, 136u, 108u,
- 1u, 174u, 85u, 153u,
- 24u, 217u, 133u, 130u,
- 122u, 142u, 133u, 218u,
- 79u, 108u, 149u, 161u,
- 64u, 100u, 148u, 255u,
- 176u, 146u, 113u, 143u,
- 172u, 90u, 209u, 158u,
- 255u, 184u, 78u, 156u,
- 128u, 72u, 164u, 195u,
- 149u, 150u, 193u, 231u,
- 191u, 113u, 66u, 145u,
- 0u, 163u, 136u, 95u,
- 245u, 142u, 196u, 251u,
- 229u, 184u, 199u, 106u,
- 134u, 223u, 59u, 58u,
- 191u, 143u, 229u, 1u,
- 106u, 249u, 111u, 166u,
- 79u, 42u, 113u, 21u,
- 203u, 202u, 126u, 169u,
- 72u, 87u, 255u, 238u,
- 248u, 150u, 90u, 100u,
- 144u, 52u, 73u, 136u,
- 173u, 122u, 136u, 129u,
- 143u, 66u, 69u, 73u,
- 82u, 255u, 157u, 165u,
- 57u, 94u, 112u, 146u,
- 172u, 93u, 119u, 128u,
- 112u, 255u, 69u, 97u,
- 106u, 54u, 144u, 96u,
- 99u, 138u, 89u, 139u,
- 58u, 170u, 218u, 255u,
- 40u, 188u, 46u, 113u,
- 212u, 102u, 238u, 163u,
- 79u, 28u, 161u, 253u,
- 96u, 21u, 92u, 7u,
- 181u, 115u, 176u, 67u,
- 55u, 167u, 139u, 41u,
- 95u, 1u, 91u, 44u,
- 140u, 122u, 242u, 87u,
- 119u, 205u, 176u, 84u,
- 107u, 89u, 0u, 40u,
- 208u, 147u, 182u, 222u,
- 163u, 135u, 107u, 214u,
- 56u, 167u, 186u, 255u,
- 98u, 161u, 163u, 103u,
- 91u, 139u, 222u, 103u,
- 208u, 160u, 69u, 138u,
- 220u, 75u, 94u, 157u,
- 226u, 139u, 148u, 162u,
- 79u, 0u, 158u, 246u,
- 119u, 148u, 112u, 107u,
- 102u, 38u, 89u, 10u,
- 26u, 255u, 68u, 185u,
- 102u, 175u, 170u, 136u,
- 136u, 138u, 163u, 185u,
- 166u, 135u, 255u, 105u,
- 199u, 119u, 138u, 251u,
- 159u, 77u, 208u, 224u,
- 57u, 56u, 142u, 35u,
- 154u, 118u, 84u, 80u,
- 170u, 180u, 167u, 116u,
- 182u, 1u, 112u, 153u,
- 43u, 172u, 100u, 136u,
- 118u, 35u, 158u, 85u,
- 131u, 160u, 177u, 106u,
- 193u, 1u, 1u, 225u,
- 187u, 231u, 88u, 158u,
- 255u, 220u, 195u, 217u,
- 210u, 214u, 145u, 56u,
- 207u, 99u, 103u, 62u,
- 142u, 142u, 190u, 143u,
- 152u, 114u, 1u, 105u,
- 111u, 115u, 119u, 14u,
- 135u, 92u, 121u, 172u,
- 176u, 133u, 238u, 192u,
- 18u, 126u, 127u, 56u,
- 91u, 166u, 98u, 153u,
- 148u, 191u, 255u, 137u,
- 100u, 53u, 75u, 175u,
- 82u, 32u, 186u, 1u,
- 112u, 199u, 225u, 153u,
- 72u, 80u, 168u, 187u,
- 126u, 147u, 127u, 151u,
- 56u, 142u, 125u, 101u,
- 196u, 140u, 0u, 194u,
- 150u, 184u, 146u, 97u,
- 191u, 128u, 255u, 123u,
- 93u, 186u, 54u, 186u,
- 135u, 115u, 136u, 125u,
- 69u, 109u, 137u, 109u,
- 45u, 144u, 52u, 103u,
- 207u, 1u, 221u, 56u,
- 129u, 116u, 120u, 33u,
- 67u, 208u, 151u, 211u,
- 231u, 227u, 217u, 119u,
- 166u, 155u, 140u, 77u,
- 207u, 183u, 178u, 155u,
- 48u, 99u, 166u, 1u,
- 67u, 229u, 116u, 198u,
- 200u, 196u, 141u, 104u,
- 117u, 186u, 195u, 204u,
- 1u, 131u, 100u, 150u,
- 113u, 26u, 171u, 137u,
- 148u, 35u, 148u, 97u,
- 127u, 225u, 192u, 140u,
- 255u, 109u, 134u, 177u,
- 106u, 116u, 235u, 142u,
- 113u, 54u, 72u, 162u,
- 189u, 163u, 182u, 62u,
- 65u, 1u, 141u, 112u,
- 123u, 170u, 86u, 203u,
- 138u, 74u, 72u, 194u,
- 54u, 0u, 124u, 111u,
- 207u, 120u, 172u, 219u,
- 128u, 182u, 129u, 103u,
- 255u, 99u, 136u, 130u,
- 99u, 78u, 188u, 84u,
- 146u, 142u, 135u, 142u,
- 107u, 153u, 160u, 145u,
- 66u, 119u, 108u, 50u,
- 151u, 171u, 162u, 210u,
- 195u, 105u, 27u, 1u,
- 77u, 99u, 54u, 197u,
- 190u, 147u, 67u, 255u,
- 48u, 156u, 41u, 232u,
- 138u, 208u, 159u, 109u,
- 157u, 47u, 172u, 237u,
- 1u, 131u, 95u, 26u,
- 172u, 77u, 112u, 137u,
- 223u, 111u, 209u, 161u,
- 95u, 135u, 126u, 138u,
- 158u, 120u, 146u, 111u,
- 133u, 29u, 163u, 188u,
- 149u, 1u, 95u, 208u,
- 0u, 224u, 90u, 155u,
- 101u, 134u, 78u, 46u,
- 216u, 43u, 42u, 104u,
- 163u, 43u, 37u, 154u,
- 105u, 233u, 171u, 208u,
- 60u, 21u, 120u, 52u,
- 128u, 27u, 16u, 135u,
- 83u, 34u, 1u, 73u,
- 124u, 162u, 169u, 255u,
- 18u, 154u, 83u, 45u,
- 133u, 173u, 94u, 170u,
- 86u, 184u, 85u, 248u,
- 32u, 164u, 118u, 255u,
- 135u, 196u, 130u, 114u,
- 71u, 178u, 176u, 101u,
- 192u, 63u, 143u, 123u,
- 150u, 129u, 203u, 153u,
- 3u, 49u, 83u, 1u,
- 137u, 83u, 154u, 141u,
- 198u, 104u, 165u, 160u,
- 31u, 125u, 68u, 159u,
- 77u, 225u, 165u, 122u,
- 106u, 148u, 59u, 229u,
- 131u, 255u, 111u, 70u,
- 65u, 188u, 39u, 108u,
- 205u, 183u, 145u, 222u,
- 62u, 49u, 1u, 241u,
- 32u, 190u, 44u, 80u,
- 60u, 215u, 168u, 17u,
- 183u, 127u, 156u, 10u,
- 121u, 136u, 137u, 122u,
- 44u, 1u, 143u, 150u,
- 136u, 210u, 78u, 229u,
- 178u, 154u, 217u, 186u,
- 137u, 112u, 241u, 40u,
- 76u, 255u, 58u, 193u,
- 169u, 138u, 123u, 106u,
- 131u, 123u, 53u, 162u,
- 1u, 159u, 106u, 61u,
- 181u, 193u, 158u, 142u,
- 255u, 226u, 195u, 149u,
- 150u, 35u, 218u, 103u,
- 185u, 189u, 144u, 72u,
- 136u, 117u, 210u, 93u,
- 59u, 92u, 151u, 171u,
- 202u, 176u, 183u, 229u,
- 150u, 145u, 124u, 5u,
- 59u, 255u, 82u, 66u,
- 1u, 225u, 115u, 182u,
- 99u, 171u, 142u, 121u,
- 85u, 125u, 118u, 229u,
- 210u, 115u, 180u, 147u,
- 0u, 87u, 76u, 59u,
- 101u, 98u, 99u, 31u,
- 67u, 92u, 187u, 55u,
- 211u, 174u, 87u, 120u,
- 233u, 239u, 55u, 77u,
- 100u, 200u, 99u, 134u,
- 145u, 16u, 13u, 146u,
- 15u, 168u, 1u, 30u,
- 126u, 245u, 167u, 209u,
- 137u, 60u, 170u, 117u,
- 195u, 165u, 103u, 149u,
- 50u, 1u, 49u, 135u,
- 177u, 156u, 140u, 188u,
- 161u, 13u, 117u, 82u,
- 155u, 255u, 158u, 121u,
- 77u, 151u, 141u, 52u,
- 161u, 57u, 122u, 104u,
- 128u, 89u, 165u, 110u,
- 87u, 178u, 157u, 94u,
- 114u, 127u, 255u, 181u,
- 153u, 21u, 31u, 27u,
- 185u, 119u, 105u, 144u,
- 27u, 103u, 143u, 19u,
- 167u, 128u, 1u, 27u,
- 76u, 127u, 48u, 255u,
- 93u, 61u, 130u, 11u,
- 201u, 93u, 39u, 158u,
- 224u, 94u, 175u, 239u,
- 177u, 161u, 0u, 167u,
- 87u, 139u, 101u, 46u,
- 202u, 38u, 166u, 154u,
- 150u, 182u, 135u, 60u,
- 162u, 125u, 101u, 13u,
- 81u, 184u, 74u, 146u,
- 153u, 110u, 141u, 184u,
- 1u, 83u, 97u, 173u,
- 123u, 142u, 95u, 20u,
- 107u, 1u, 120u, 127u,
- 129u, 122u, 123u, 106u,
- 112u, 229u, 168u, 188u,
- 255u, 253u, 108u, 59u,
- 123u, 91u, 4u, 147u,
- 87u, 222u, 98u, 72u,
- 157u, 49u, 116u, 151u,
- 200u, 177u, 201u, 200u,
- 65u, 109u, 180u, 73u,
- 236u, 64u, 41u, 23u,
- 165u, 118u, 1u, 8u,
- 255u, 66u, 227u, 168u,
- 220u, 124u, 200u, 137u,
- 104u, 148u, 31u, 156u,
- 179u, 189u, 58u, 19u,
- 87u, 149u, 122u, 204u,
- 98u, 136u, 106u, 55u,
- 147u, 222u, 118u, 181u,
- 193u, 255u, 71u, 137u,
- 123u, 129u, 1u, 255u,
- 45u, 135u, 113u, 194u,
- 14u, 165u, 200u, 152u,
- 119u, 56u, 134u, 53u,
- 183u, 115u, 159u, 126u,
- 51u, 99u, 111u, 0u,
- 139u, 198u, 133u, 55u,
- 156u, 118u, 143u, 154u,
- 70u, 109u, 153u, 124u,
- 133u, 159u, 149u, 148u,
- 1u, 130u, 140u, 56u,
- 156u, 11u, 142u, 52u,
- 149u, 202u, 186u, 106u,
- 139u, 155u, 80u, 254u,
- 233u, 163u, 115u, 245u,
- 138u, 1u, 57u, 159u,
- 97u, 196u, 145u, 197u,
- 163u, 96u, 189u, 135u,
- 212u, 225u, 170u, 163u,
- 255u, 200u, 72u, 119u,
- 87u, 100u, 192u, 61u,
- 124u, 53u, 162u, 12u,
- 131u, 116u, 135u, 158u,
- 120u, 255u, 146u, 134u,
- 203u, 158u, 228u, 175u,
- 142u, 150u, 119u, 196u,
- 159u, 153u, 130u, 65u,
- 85u, 255u, 154u, 159u,
- 162u, 120u, 122u, 201u,
- 125u, 12u, 117u, 246u,
- 71u, 247u, 129u, 183u,
- 208u, 255u, 238u, 116u,
- 62u, 42u, 171u, 51u,
- 187u, 229u, 116u, 133u,
- 136u, 102u, 89u, 255u,
- 108u, 98u, 163u, 95u,
- 107u, 45u, 221u, 182u,
- 88u, 111u, 76u, 169u,
- 82u, 178u, 202u, 155u,
- 73u, 121u, 247u, 1u,
- 120u, 194u, 215u, 230u,
- 194u, 164u, 131u, 93u,
- 138u, 11u, 200u, 22u,
- 131u, 196u, 255u, 149u,
- 134u, 153u, 12u, 90u,
- 142u, 126u, 64u, 115u,
- 126u, 148u, 114u, 117u,
- 1u, 120u, 54u, 129u,
- 100u, 0u, 101u, 222u,
- 108u, 98u, 4u, 192u,
- 190u, 52u, 96u, 123u,
- 191u, 143u, 46u, 194u,
- 116u, 207u, 252u, 6u,
- 236u, 123u, 158u, 0u,
- 77u, 206u, 184u, 106u,
- 140u, 14u, 153u, 194u,
- 80u, 99u, 194u, 168u,
- 142u, 236u, 82u, 149u,
- 255u, 101u, 114u, 143u,
- 89u, 130u, 105u, 110u,
- 190u, 251u, 119u, 138u,
- 166u, 111u, 153u, 111u,
- 148u, 96u, 247u, 255u,
- 165u, 74u, 184u, 44u,
- 128u, 183u, 87u, 1u,
- 184u, 144u, 167u, 101u,
- 72u, 142u, 108u, 88u,
- 80u, 95u, 112u, 168u,
- 44u, 119u, 240u, 155u,
- 88u, 218u, 91u, 87u,
- 212u, 113u, 40u, 255u,
- 134u, 62u, 211u, 107u,
- 26u, 98u, 135u, 135u,
- 135u, 155u, 151u, 170u,
- 161u, 1u, 99u, 118u,
- 112u, 153u, 93u, 152u,
- 81u, 150u, 110u, 136u,
- 174u, 99u, 92u, 205u,
- 108u, 9u, 46u, 86u,
- 101u, 63u, 255u, 34u,
- 201u, 95u, 101u, 218u,
- 86u, 21u, 100u, 207u,
- 1u, 122u, 245u, 92u,
- 111u, 107u, 42u, 215u,
- 195u, 89u, 104u, 192u,
- 157u, 14u, 68u, 188u,
- 156u, 32u, 147u, 33u,
- 222u, 172u, 163u, 255u,
- 199u, 234u, 70u, 39u,
- 109u, 217u, 146u, 191u,
- 255u, 178u, 76u, 136u,
- 192u, 45u, 199u, 84u,
- 134u, 171u, 127u, 66u,
- 89u, 144u, 1u, 197u,
- 122u, 117u, 107u, 190u,
- 112u, 195u, 154u, 150u,
- 116u, 113u, 103u, 53u,
- 193u, 173u, 57u, 188u,
- 82u, 142u, 88u, 92u,
- 143u, 119u, 1u, 101u,
- 235u, 108u, 87u, 164u,
- 95u, 124u, 255u, 240u,
- 82u, 194u, 134u, 112u,
- 122u, 205u, 120u, 122u,
- 3u, 107u, 92u, 55u,
- 144u, 78u, 138u, 119u,
- 116u, 148u, 1u, 100u,
- 71u, 161u, 82u, 164u,
- 156u, 33u, 255u, 255u,
- 38u, 54u, 152u, 176u,
- 136u, 96u, 106u, 101u,
- 145u, 59u, 56u, 97u,
- 75u, 55u, 91u, 164u,
- 133u, 170u, 216u, 255u,
- 23u, 199u, 146u, 106u,
- 190u, 198u, 83u, 102u,
- 67u, 255u, 44u, 21u,
- 108u, 137u, 135u, 107u,
- 120u, 131u, 108u, 141u,
- 204u, 200u, 209u, 17u,
- 131u, 163u, 153u, 255u,
- 74u, 209u, 147u, 28u,
- 102u, 107u, 135u, 86u,
- 186u, 161u, 180u, 184u,
- 214u, 88u, 158u, 101u,
- 5u, 0u, 33u, 239u,
- 70u, 167u, 187u, 48u,
- 96u, 26u, 169u, 97u,
- 1u, 120u, 207u, 62u,
- 5u, 125u, 120u, 79u,
- 36u, 213u, 103u, 177u,
- 155u, 50u, 158u, 166u,
- 164u, 69u, 147u, 170u,
- 46u, 86u, 40u, 151u,
- 14u, 1u, 67u, 198u,
- 171u, 40u, 167u, 32u,
- 88u, 173u, 162u, 82u,
- 255u, 109u, 111u, 184u,
- 132u, 167u, 97u, 87u,
- 110u, 139u, 62u, 120u,
- 152u, 97u, 113u, 85u,
- 112u, 142u, 1u, 133u,
- 209u, 120u, 131u, 111u,
- 120u, 213u, 164u, 83u,
- 151u, 156u, 153u, 201u,
- 116u, 17u, 172u, 201u,
- 171u, 255u, 146u, 90u,
- 232u, 128u, 194u, 122u,
- 51u, 255u, 99u, 96u,
- 180u, 55u, 140u, 131u,
- 123u, 137u, 69u, 155u,
- 164u, 200u, 74u, 187u,
- 83u, 82u, 123u, 122u,
- 94u, 183u, 141u, 1u,
- 113u, 190u, 176u, 117u,
- 109u, 139u, 156u, 199u,
- 133u, 253u, 117u, 125u,
- 193u, 1u, 132u, 43u,
- 197u, 153u, 25u, 148u,
- 159u, 172u, 153u, 205u,
- 111u, 137u, 93u, 0u,
- 170u, 145u, 81u, 103u,
- 199u, 123u, 125u, 30u,
- 58u, 91u, 141u, 178u,
- 148u, 168u, 157u, 215u,
- 155u, 161u, 255u, 218u,
- 35u, 135u, 128u, 228u,
- 100u, 91u, 236u, 240u,
- 156u, 1u, 72u, 115u,
- 66u, 200u, 177u, 26u,
- 155u, 71u, 70u, 205u,
- 180u, 173u, 81u, 227u,
- 141u, 148u, 189u, 11u,
- 131u, 129u, 88u, 1u,
- 194u, 119u, 56u, 229u,
- 8u, 162u, 153u, 193u,
- 174u, 255u, 124u, 140u,
- 4u, 90u, 101u, 167u,
- 178u, 38u, 121u, 158u,
- 67u, 147u, 239u, 124u,
- 155u, 157u, 42u, 168u,
- 180u, 139u, 19u, 1u,
- 213u, 109u, 133u, 215u,
- 196u, 154u, 178u, 128u,
- 126u, 115u, 161u, 145u,
- 49u, 141u, 98u, 78u,
- 182u, 98u, 198u, 153u,
- 90u, 74u, 255u, 226u,
- 1u, 102u, 212u, 151u,
- 102u, 167u, 239u, 84u,
- 214u, 179u, 154u, 56u,
- 27u, 194u, 116u, 122u,
- 121u, 125u, 153u, 228u,
- 133u, 152u, 170u, 1u,
- 154u, 59u, 94u, 94u,
- 118u, 53u, 84u, 103u,
- 135u, 180u, 90u, 176u,
- 112u, 3u, 155u, 203u,
- 212u, 107u, 187u, 131u,
- 205u, 83u, 100u, 255u,
- 1u, 118u, 217u, 45u,
- 51u, 129u, 189u, 152u,
- 38u, 112u, 215u, 168u,
- 54u, 163u, 22u, 70u,
- 51u, 12u, 1u, 200u,
- 141u, 57u, 170u, 30u,
- 65u, 168u, 206u, 95u,
- 156u, 196u, 55u, 146u,
- 1u, 102u, 173u, 86u,
- 83u, 169u, 92u, 32u,
- 35u, 117u, 166u, 120u,
- 134u, 142u, 127u, 65u,
- 119u, 190u, 1u, 0u,
- 115u, 93u, 121u, 166u,
- 152u, 87u, 170u, 175u,
- 151u, 147u, 169u, 246u,
- 137u, 134u, 133u, 100u,
- 185u, 187u, 166u, 139u,
- 92u, 101u, 255u, 230u,
- 221u, 111u, 22u, 180u,
- 234u, 1u, 16u, 179u,
- 35u, 195u, 11u, 177u,
- 239u, 248u, 122u, 233u,
- 69u, 167u, 222u, 189u,
- 38u, 94u, 205u, 126u,
- 36u, 148u, 128u, 1u,
- 109u, 83u, 118u, 150u,
- 172u, 143u, 135u, 87u,
- 126u, 144u, 14u, 95u,
- 81u, 135u, 8u, 114u,
- 140u, 114u, 0u, 199u,
- 107u, 180u, 211u, 113u,
- 175u, 102u, 69u, 178u,
- 185u, 86u, 166u, 255u,
- 141u, 186u, 137u, 63u,
- 182u, 211u, 35u, 214u,
- 154u, 183u, 138u, 149u,
- 193u, 255u, 174u, 52u,
- 110u, 104u, 21u, 95u,
- 34u, 113u, 199u, 151u,
- 137u, 132u, 255u, 167u,
- 101u, 134u, 51u, 106u,
- 173u, 144u, 158u, 115u,
- 144u, 154u, 198u, 110u,
- 186u, 198u, 122u, 70u,
- 25u, 233u, 69u, 67u,
- 1u, 134u, 125u, 120u,
- 116u, 125u, 170u, 178u,
- 53u, 173u, 141u, 129u,
- 210u, 71u, 235u, 121u,
- 255u, 133u, 35u, 217u,
- 70u, 117u, 78u, 30u,
- 224u, 53u, 219u, 135u,
- 75u, 1u, 100u, 103u,
- 167u, 118u, 235u, 51u,
- 203u, 12u, 33u, 235u,
- 59u, 108u, 65u, 85u,
- 24u, 67u, 178u, 255u,
- 204u, 149u, 109u, 88u,
- 80u, 183u, 164u, 108u,
- 131u, 108u, 177u, 127u,
- 171u, 50u, 55u, 204u,
- 233u, 130u, 132u, 188u,
- 70u, 173u, 59u, 255u,
- 200u, 255u, 207u, 51u,
- 178u, 64u, 46u, 162u,
- 188u, 210u, 158u, 61u,
- 150u, 82u, 46u, 179u,
- 66u, 68u, 60u, 179u,
- 255u, 133u, 212u, 127u,
- 159u, 195u, 2u, 75u,
- 152u, 77u, 51u, 110u,
- 116u, 132u, 96u, 255u,
- 17u, 163u, 183u, 212u,
- 224u, 139u, 167u, 146u,
- 50u, 121u, 56u, 227u,
- 19u, 132u, 98u, 199u,
- 120u, 149u, 77u, 139u,
- 203u, 91u, 1u, 119u,
- 104u, 167u, 131u, 125u,
- 66u, 78u, 85u, 123u,
- 164u, 132u, 187u, 1u,
- 67u, 16u, 202u, 130u,
- 211u, 56u, 217u, 27u,
- 216u, 112u, 222u, 13u,
- 73u, 153u, 62u, 178u,
- 156u, 138u, 47u, 196u,
- 1u, 221u, 221u, 65u,
- 87u, 119u, 146u, 127u,
- 255u, 124u, 113u, 132u,
- 144u, 162u, 104u, 169u,
- 216u, 88u, 60u, 142u,
- 91u, 57u, 102u, 98u,
- 88u, 206u, 142u, 87u,
- 80u, 22u, 152u, 177u,
- 28u, 214u, 10u, 1u,
- 83u, 110u, 118u, 155u,
- 97u, 94u, 124u, 128u,
- 151u, 208u, 83u, 172u,
- 153u, 255u, 127u, 139u,
- 70u, 197u, 251u, 255u,
- 192u, 70u, 203u, 142u,
- 42u, 28u, 179u, 32u,
- 170u, 168u, 21u, 190u,
- 152u, 133u, 146u, 255u,
- 116u, 129u, 60u, 118u,
- 100u, 101u, 160u, 153u,
- 152u, 71u, 95u, 192u,
- 206u, 156u, 152u, 93u,
- 204u, 240u, 88u, 162u,
- 113u, 255u, 12u, 114u,
- 173u, 84u, 117u, 122u,
- 64u, 156u, 16u, 105u,
- 75u, 108u, 117u, 169u,
- 160u, 92u, 157u, 111u,
- 153u, 40u, 255u, 205u,
- 78u, 82u, 201u, 118u,
- 78u, 60u, 236u, 117u,
- 46u, 79u, 139u, 82u,
- 0u, 143u, 116u, 40u,
- 53u, 90u, 131u, 121u,
- 178u, 141u, 162u, 184u,
- 206u, 145u, 144u, 92u,
- 125u, 102u, 0u, 139u,
- 172u, 122u, 50u, 221u,
- 255u, 155u, 139u, 168u,
- 87u, 111u, 210u, 102u,
- 136u, 89u, 118u, 121u,
- 165u, 110u, 55u, 154u,
- 120u, 131u, 106u, 151u,
- 60u, 190u, 223u, 86u,
- 134u, 255u, 52u, 66u,
- 88u, 113u, 225u, 176u,
- 176u, 78u, 106u, 149u,
- 152u, 255u, 137u, 65u,
- 174u, 131u, 164u, 152u,
- 1u, 250u, 54u, 105u,
- 136u, 198u, 215u, 71u,
- 95u, 22u, 208u, 181u,
- 196u, 215u, 238u, 247u,
- 102u, 161u, 80u, 42u,
- 71u, 146u, 103u, 1u,
- 69u, 105u, 102u, 120u,
- 81u, 124u, 73u, 211u,
- 128u, 66u, 126u, 71u,
- 147u, 32u, 53u, 128u,
- 142u, 83u, 218u, 156u,
- 192u, 229u, 255u, 210u,
- 176u, 1u, 111u, 91u,
- 108u, 156u, 133u, 157u,
- 38u, 255u, 47u, 101u,
- 82u, 206u, 165u, 56u,
- 117u, 117u, 147u, 130u,
- 94u, 109u, 0u, 125u,
- 153u, 125u, 203u, 98u,
- 158u, 135u, 205u, 110u,
- 142u, 80u, 111u, 255u,
- 138u, 181u, 154u, 222u,
- 132u, 112u, 170u, 153u,
- 167u, 102u, 221u, 95u,
- 90u, 255u, 172u, 112u,
- 153u, 148u, 150u, 110u,
- 150u, 167u, 178u, 170u,
- 88u, 118u, 133u, 110u,
- 196u, 149u, 192u, 102u,
- 95u, 136u, 112u, 98u,
- 99u, 167u, 53u, 134u,
- 73u, 166u, 59u, 0u,
- 116u, 164u, 1u, 218u,
- 214u, 197u, 140u, 204u,
- 180u, 180u, 250u, 74u,
- 170u, 70u, 118u, 166u,
- 221u, 241u, 216u, 204u,
- 65u, 47u, 146u, 223u,
- 254u, 98u, 120u, 179u,
- 177u, 173u, 255u, 237u,
- 129u, 139u, 155u, 182u,
- 126u, 73u, 131u, 140u,
- 37u, 132u, 168u, 183u,
- 23u, 255u, 98u, 151u,
- 43u, 200u, 169u, 255u,
- 91u, 191u, 99u, 24u,
- 171u, 185u, 184u, 167u,
- 67u, 97u, 81u, 140u,
- 186u, 205u, 151u, 137u,
- 1u, 167u, 88u, 177u,
- 171u, 120u, 126u, 157u,
- 65u, 81u, 131u, 194u,
- 160u, 199u, 6u, 176u,
- 129u, 187u, 19u, 117u,
- 17u, 249u, 69u, 176u,
- 170u, 113u, 108u, 0u,
- 56u, 100u, 105u, 162u,
- 111u, 255u, 9u, 98u,
- 50u, 83u, 83u, 214u,
- 150u, 107u, 192u, 109u,
- 145u, 187u, 96u, 137u,
- 141u, 124u, 82u, 176u,
- 76u, 106u, 255u, 235u,
- 90u, 70u, 105u, 111u,
- 9u, 137u, 71u, 95u,
- 149u, 251u, 1u, 148u,
- 114u, 240u, 103u, 94u,
- 129u, 251u, 39u, 187u,
- 115u, 144u, 178u, 211u,
- 109u, 132u, 171u, 41u,
- 70u, 199u, 214u, 15u,
- 255u, 216u, 73u, 85u,
- 65u, 147u, 134u, 23u,
- 224u, 172u, 109u, 197u,
- 56u, 239u, 93u, 120u,
- 221u, 118u, 255u, 109u,
- 152u, 1u, 224u, 114u,
- 165u, 176u, 89u, 131u,
- 208u, 55u, 109u, 124u,
- 156u, 117u, 226u, 116u,
- 105u, 96u, 128u, 181u,
- 124u, 69u, 105u, 166u,
- 121u, 102u, 158u, 138u,
- 175u, 169u, 1u, 105u,
- 200u, 137u, 135u, 1u,
- 173u, 65u, 61u, 190u,
- 71u, 125u, 100u, 115u,
- 145u, 116u, 164u, 51u,
- 53u, 115u, 95u, 169u,
- 149u, 46u, 70u, 103u,
- 145u, 93u, 211u, 130u,
- 198u, 241u, 1u, 56u,
- 79u, 126u, 145u, 149u,
- 174u, 183u, 125u, 189u,
- 142u, 136u, 141u, 69u,
- 199u, 89u, 0u, 42u,
- 98u, 133u, 120u, 141u,
- 143u, 162u, 138u, 121u,
- 57u, 196u, 120u, 130u,
- 104u, 179u, 149u, 255u,
- 127u, 200u, 165u, 95u,
- 87u, 176u, 106u, 1u,
- 130u, 162u, 125u, 138u,
- 143u, 111u, 161u, 64u,
- 102u, 116u, 27u, 166u,
- 107u, 139u, 20u, 138u,
- 155u, 255u, 182u, 118u,
- 193u, 106u, 160u, 109u,
- 171u, 91u, 146u, 195u,
- 52u, 147u, 109u, 52u,
- 148u, 119u, 194u, 170u,
- 255u, 157u, 71u, 235u,
- 62u, 208u, 169u, 110u,
- 209u, 214u, 102u, 109u,
- 111u, 41u, 255u, 159u,
- 166u, 52u, 124u, 95u,
- 211u, 203u, 85u, 172u,
- 85u, 255u, 91u, 209u,
- 137u, 170u, 97u, 94u,
- 103u, 136u, 94u, 86u,
- 122u, 136u, 141u, 13u,
- 119u, 28u, 21u, 52u,
- 125u, 53u, 106u, 70u,
- 34u, 255u, 92u, 187u,
- 41u, 240u, 46u, 114u,
- 135u, 14u, 102u, 42u,
- 255u, 235u, 61u, 192u,
- 224u, 169u, 80u, 87u,
- 61u, 224u, 99u, 175u,
- 52u, 136u, 57u, 88u,
- 160u, 205u, 75u, 147u,
- 200u, 134u, 199u, 255u,
- 185u, 167u, 150u, 56u,
- 56u, 152u, 75u, 179u,
- 218u, 78u, 90u, 95u,
- 1u, 135u, 197u, 189u,
- 58u, 0u, 89u, 241u,
- 7u, 131u, 47u, 85u,
- 178u, 99u, 66u, 138u,
- 127u, 148u, 153u, 109u,
- 255u, 128u, 195u, 101u,
- 131u, 98u, 148u, 110u,
- 119u, 123u, 222u, 59u,
- 53u, 116u, 177u, 134u,
- 202u, 106u, 186u, 144u,
- 38u, 85u, 110u, 116u,
- 255u, 141u, 145u, 67u,
- 178u, 148u, 152u, 101u,
- 202u, 112u, 160u, 148u,
- 138u, 255u, 26u, 70u,
- 95u, 158u, 212u, 26u,
- 153u, 118u, 172u, 170u,
- 232u, 228u, 244u, 100u,
- 99u, 201u, 152u, 176u,
- 198u, 185u, 89u, 121u,
- 25u, 128u, 255u, 97u,
- 53u, 72u, 56u, 178u,
- 134u, 89u, 63u, 102u,
- 1u, 170u, 178u, 87u,
- 155u, 164u, 119u, 189u,
- 128u, 177u, 114u, 197u,
- 81u, 78u, 124u, 79u,
- 179u, 108u, 217u, 52u,
- 220u, 155u, 113u, 255u,
- 226u, 71u, 16u, 205u,
- 166u, 142u, 90u, 255u,
- 92u, 181u, 181u, 141u,
- 166u, 173u, 103u, 25u,
- 237u, 155u, 204u, 177u,
- 46u, 139u, 107u, 82u,
- 225u, 107u, 222u, 156u,
- 126u, 18u, 255u, 148u,
- 190u, 121u, 180u, 127u,
- 143u, 117u, 142u, 204u,
- 124u, 169u, 129u, 181u,
- 160u, 160u, 0u, 69u,
- 153u, 114u, 119u, 157u,
- 161u, 189u, 100u, 180u,
- 39u, 112u, 73u, 216u,
- 1u, 111u, 95u, 155u,
- 144u, 115u, 195u, 151u,
- 119u, 198u, 100u, 151u,
- 86u, 210u, 243u, 76u,
- 92u, 1u, 190u, 33u,
- 73u, 126u, 192u, 61u,
- 121u, 95u, 154u, 106u,
- 99u, 158u, 129u, 130u,
- 119u, 1u, 171u, 119u,
- 121u, 185u, 226u, 65u,
- 147u, 57u, 118u, 212u,
- 120u, 105u, 255u, 163u,
- 163u, 70u, 52u, 176u,
- 87u, 107u, 157u, 255u,
- 218u, 156u, 187u, 115u,
- 150u, 84u, 163u, 148u,
- 77u, 133u, 173u, 114u,
- 80u, 174u, 205u, 97u,
- 144u, 83u, 230u, 192u,
- 222u, 126u, 122u, 150u,
- 112u, 242u, 124u, 255u,
- 38u, 126u, 93u, 211u,
- 255u, 116u, 50u, 167u,
- 146u, 88u, 73u, 14u,
- 186u, 40u, 70u, 126u,
- 185u, 56u, 67u, 148u,
- 134u, 55u, 128u, 215u,
- 189u, 86u, 154u, 39u,
- 145u, 51u, 255u, 128u,
- 1u, 213u, 79u, 121u,
- 93u, 203u, 88u, 176u,
- 149u, 60u, 61u, 186u,
- 134u, 120u, 213u, 166u,
- 163u, 239u, 144u, 222u,
- 107u, 143u, 100u, 213u,
- 217u, 46u, 141u, 142u,
- 107u, 160u, 1u, 155u,
- 99u, 149u, 113u, 167u,
- 255u, 116u, 233u, 92u,
- 135u, 70u, 84u, 109u,
- 111u, 13u, 156u, 117u,
- 138u, 127u, 35u, 230u,
- 58u, 153u, 243u, 79u,
- 81u, 39u, 34u, 168u,
- 1u, 78u, 120u, 169u,
- 94u, 99u, 175u, 1u,
- 195u, 202u, 112u, 117u,
- 47u, 109u, 244u, 51u,
- 193u, 199u, 204u, 79u,
- 23u, 32u, 101u, 231u,
- 84u, 189u, 65u, 161u,
- 57u, 128u, 167u, 147u,
- 182u, 163u, 1u, 92u,
- 183u, 142u, 208u, 62u,
- 95u, 177u, 143u, 115u,
- 192u, 223u, 153u, 122u,
- 255u, 113u, 240u, 126u,
- 178u, 126u, 231u, 169u,
- 138u, 223u, 166u, 138u,
- 45u, 151u, 255u, 171u,
- 90u, 151u, 3u, 70u,
- 0u, 58u, 93u, 61u,
- 94u, 171u, 208u, 119u,
- 90u, 82u, 138u, 248u,
- 226u, 165u, 105u, 162u,
- 179u, 92u, 130u, 64u,
- 132u, 105u, 38u, 160u,
- 1u, 87u, 180u, 77u,
- 183u, 110u, 68u, 105u,
- 157u, 118u, 94u, 144u,
- 84u, 97u, 1u, 151u,
- 68u, 112u, 159u, 110u,
- 100u, 156u, 160u, 135u,
- 112u, 113u, 76u, 115u,
- 35u, 199u, 40u, 128u,
- 45u, 83u, 9u, 150u,
- 138u, 182u, 255u, 122u,
- 132u, 65u, 105u, 94u,
- 99u, 151u, 131u, 196u,
- 1u, 126u, 144u, 161u,
- 109u, 191u, 77u, 155u,
- 1u, 163u, 171u, 121u,
- 117u, 61u, 115u, 118u,
- 39u, 117u, 134u, 186u,
- 160u, 148u, 92u, 11u,
- 1u, 236u, 194u, 221u,
- 149u, 171u, 158u, 184u,
- 116u, 232u, 146u, 153u,
- 254u, 243u, 30u, 141u,
- 159u, 144u, 80u, 156u,
- 172u, 195u, 191u, 182u,
- 43u, 160u, 96u, 35u,
- 163u, 255u, 137u, 157u,
- 179u, 152u, 255u, 144u,
- 124u, 105u, 64u, 127u,
- 169u, 148u, 143u, 205u,
- 178u, 8u, 147u, 166u,
- 114u, 101u, 207u, 34u,
- 168u, 135u, 188u, 176u,
- 239u, 218u, 116u, 130u,
- 58u, 255u, 179u, 143u,
- 94u, 49u, 138u, 22u,
- 105u, 158u, 168u, 255u,
- 25u, 33u, 206u, 27u,
- 170u, 86u, 255u, 214u,
- 157u, 152u, 223u, 116u,
- 71u, 91u, 83u, 1u,
- 110u, 55u, 167u, 88u,
- 220u, 93u, 134u, 175u,
- 129u, 59u, 1u, 249u,
- 95u, 168u, 109u, 123u,
- 74u, 90u, 120u, 69u,
- 62u, 110u, 99u, 118u,
- 127u, 123u, 1u, 133u,
- 20u, 92u, 80u, 80u,
- 102u, 153u, 64u, 198u,
- 233u, 81u, 169u, 132u,
- 48u, 1u, 87u, 177u,
- 159u, 202u, 114u, 166u,
- 192u, 129u, 38u, 137u,
- 125u, 220u, 104u, 181u,
- 188u, 243u, 80u, 228u,
- 183u, 102u, 207u, 60u,
- 164u, 102u, 67u, 174u,
- 65u, 17u, 255u, 197u,
- 86u, 89u, 145u, 230u,
- 1u, 89u, 160u, 2u,
- 129u, 79u, 99u, 122u,
- 186u, 70u, 120u, 165u,
- 72u, 128u, 170u, 170u,
- 89u, 84u, 159u, 1u,
- 168u, 174u, 172u, 140u,
- 94u, 182u, 100u, 110u,
- 212u, 78u, 129u, 14u,
- 159u, 116u, 41u, 173u,
- 1u, 188u, 78u, 85u,
- 116u, 85u, 65u, 118u,
- 110u, 93u, 249u, 171u,
- 59u, 94u, 174u, 0u,
- 73u, 114u, 100u, 96u,
- 195u, 63u, 165u, 132u,
- 51u, 149u, 112u, 139u,
- 169u, 111u, 214u, 140u,
- 114u, 191u, 90u, 186u,
- 21u, 225u, 255u, 78u,
- 108u, 189u, 111u, 167u,
- 91u, 62u, 136u, 173u,
- 203u, 100u, 147u, 255u,
- 145u, 147u, 93u, 152u,
- 207u, 137u, 226u, 151u,
- 18u, 60u, 132u, 1u,
- 168u, 62u, 159u, 60u,
- 135u, 151u, 171u, 121u,
- 169u, 59u, 1u, 135u,
- 119u, 121u, 154u, 57u,
- 95u, 129u, 212u, 128u,
- 171u, 122u, 149u, 120u,
- 136u, 116u, 255u, 136u,
- 66u, 67u, 84u, 94u,
- 158u, 241u, 116u, 140u,
- 183u, 187u, 157u, 146u,
- 112u, 255u, 144u, 83u,
- 221u, 145u, 159u, 204u,
- 100u, 85u, 166u, 143u,
- 105u, 134u, 101u, 105u,
- 159u, 255u, 84u, 59u,
- 145u, 126u, 225u, 98u,
- 119u, 40u, 123u, 151u,
- 111u, 111u, 189u, 202u,
- 71u, 122u, 51u, 146u,
- 28u, 1u, 187u, 28u,
- 217u, 229u, 59u, 191u,
- 130u, 237u, 117u, 135u,
- 162u, 119u, 237u, 168u,
- 33u, 42u, 56u, 14u,
- 202u, 178u, 111u, 205u,
- 65u, 255u, 146u, 28u,
- 136u, 12u, 191u, 74u,
- 135u, 125u, 111u, 133u,
- 132u, 108u, 148u, 134u,
- 92u, 191u, 60u, 1u,
- 173u, 202u, 120u, 94u,
- 178u, 155u, 82u, 97u,
- 166u, 255u, 71u, 111u,
- 101u, 155u, 118u, 55u,
- 209u, 32u, 1u, 160u,
- 135u, 59u, 189u, 57u,
- 92u, 10u, 179u, 77u,
- 61u, 77u, 160u, 87u,
- 185u, 72u, 135u, 79u,
- 103u, 35u, 133u, 105u,
- 1u, 104u, 39u, 20u,
- 159u, 126u, 120u, 37u,
- 43u, 216u, 200u, 89u,
- 84u, 186u, 124u, 35u,
- 149u, 83u, 30u, 83u,
- 142u, 179u, 0u, 71u,
- 175u, 197u, 182u, 162u,
- 126u, 87u, 204u, 0u,
- 83u, 148u, 74u, 150u,
- 106u, 93u, 79u, 181u,
- 59u, 20u, 175u, 255u,
- 75u, 117u, 168u, 26u,
- 175u, 115u, 174u, 112u,
- 142u, 164u, 150u, 178u,
- 55u, 115u, 149u, 39u,
- 223u, 180u, 121u, 237u,
- 44u, 218u, 131u, 79u,
- 1u, 190u, 78u, 20u,
- 62u, 255u, 109u, 123u,
- 159u, 119u, 171u, 75u,
- 111u, 160u, 96u, 149u,
- 167u, 200u, 124u, 188u,
- 69u, 236u, 172u, 255u,
- 225u, 56u, 245u, 172u,
- 54u, 147u, 145u, 129u,
- 208u, 69u, 86u, 176u,
- 123u, 137u, 82u, 199u,
- 93u, 140u, 90u, 255u,
- 184u, 127u, 108u, 255u,
- 82u, 184u, 186u, 93u,
- 74u, 52u, 112u, 159u,
- 139u, 59u, 43u, 109u,
- 255u, 96u, 101u, 247u,
- 157u, 77u, 135u, 56u,
- 97u, 106u, 114u, 189u,
- 41u, 72u, 82u, 255u,
- 88u, 149u, 132u, 159u,
- 79u, 124u, 180u, 201u,
- 111u, 174u, 81u, 49u,
- 207u, 157u, 157u, 125u,
- 21u, 66u, 136u, 125u,
- 1u, 31u, 107u, 142u,
- 155u, 255u, 159u, 52u,
- 147u, 239u, 168u, 228u,
- 106u, 157u, 94u, 161u,
- 153u, 135u, 81u, 146u,
- 71u, 179u, 212u, 79u,
- 165u, 150u, 175u, 169u,
- 157u, 90u, 1u, 135u,
- 197u, 215u, 5u, 162u,
- 97u, 124u, 224u, 140u,
- 64u, 73u, 120u, 156u,
- 132u, 150u, 227u, 255u,
- 73u, 158u, 28u, 56u,
- 108u, 133u, 49u, 103u,
- 74u, 102u, 163u, 91u,
- 209u, 118u, 69u, 164u,
- 1u, 105u, 46u, 239u,
- 151u, 173u, 94u, 152u,
- 121u, 201u, 87u, 42u,
- 100u, 82u, 176u, 118u,
- 144u, 1u, 143u, 145u,
- 178u, 111u, 89u, 135u,
- 92u, 138u, 156u, 165u,
- 110u, 144u, 135u, 170u,
- 1u, 79u, 124u, 106u,
- 221u, 127u, 129u, 9u,
- 120u, 61u, 211u, 171u,
- 183u, 98u, 66u, 255u,
- 136u, 245u, 0u, 225u,
- 106u, 138u, 159u, 113u,
- 9u, 94u, 121u, 177u,
- 254u, 186u, 109u, 119u,
- 124u, 255u, 50u, 251u,
- 100u, 125u, 174u, 179u,
- 123u, 140u, 134u, 127u,
- 167u, 98u, 139u, 188u,
- 96u, 114u, 255u, 192u,
- 169u, 212u, 154u, 170u,
- 41u, 246u, 225u, 45u,
- 54u, 130u, 106u, 93u,
- 0u, 175u, 237u, 130u,
- 133u, 90u, 97u, 149u,
- 75u, 218u, 133u, 120u,
- 115u, 113u, 159u, 168u,
- 20u, 0u, 194u, 78u,
- 93u, 172u, 123u, 94u,
- 144u, 105u, 126u, 134u,
- 109u, 153u, 106u, 255u,
- 110u, 137u, 58u, 134u,
- 157u, 150u, 83u, 195u,
- 106u, 74u, 100u, 227u,
- 106u, 115u, 97u, 106u,
- 203u, 36u, 255u, 228u,
- 111u, 173u, 155u, 241u,
- 166u, 201u, 111u, 111u,
- 107u, 0u, 119u, 81u,
- 188u, 132u, 250u, 158u,
- 255u, 46u, 220u, 103u,
- 60u, 126u, 47u, 145u,
- 199u, 161u, 157u, 50u,
- 70u, 73u, 230u, 51u,
- 107u, 105u, 29u, 163u,
- 127u, 250u, 175u, 155u,
- 76u, 147u, 86u, 57u,
- 107u, 76u, 149u, 0u,
- 155u, 134u, 63u, 86u,
- 87u, 148u, 155u, 70u,
- 116u, 147u, 131u, 0u,
- 95u, 100u, 98u, 83u,
- 111u, 51u, 202u, 147u,
- 143u, 94u, 107u, 29u,
- 69u, 169u, 125u, 1u,
- 187u, 218u, 102u, 174u,
- 96u, 44u, 122u, 160u,
- 175u, 208u, 220u, 219u,
- 112u, 139u, 158u, 72u,
- 1u, 184u, 64u, 97u,
- 196u, 93u, 190u, 165u,
- 134u, 37u, 166u, 154u,
- 117u, 255u, 109u, 129u,
- 137u, 159u, 112u, 52u,
- 174u, 77u, 162u, 234u,
- 47u, 60u, 48u, 61u,
- 169u, 115u, 124u, 115u,
- 178u, 255u, 37u, 89u,
- 117u, 134u, 192u, 163u,
- 88u, 133u, 142u, 97u,
- 125u, 255u, 114u, 137u,
- 172u, 204u, 199u, 111u,
- 122u, 55u, 86u, 112u,
- 37u, 255u, 136u, 76u,
- 129u, 109u, 96u, 47u,
- 125u, 189u, 203u, 122u,
- 117u, 104u, 102u, 81u,
- 23u, 205u, 79u, 1u,
- 183u, 155u, 87u, 71u,
- 150u, 97u, 67u, 176u,
- 1u, 194u, 57u, 171u,
- 157u, 168u, 209u, 125u,
- 123u, 178u, 172u, 158u,
- 85u, 123u, 121u, 170u,
- 98u, 189u, 98u, 22u,
- 1u, 118u, 13u, 130u,
- 112u, 100u, 241u, 152u,
- 71u, 110u, 179u, 96u,
- 124u, 172u, 161u, 12u,
- 144u, 106u, 82u, 120u,
- 1u, 143u, 179u, 33u,
- 4u, 197u, 119u, 134u,
- 108u, 196u, 52u, 153u,
- 124u, 195u, 124u, 149u,
- 126u, 126u, 100u, 171u,
- 0u, 172u, 188u, 86u,
- 156u, 107u, 231u, 1u,
- 118u, 98u, 105u, 159u,
- 159u, 200u, 236u, 7u,
- 218u, 114u, 154u, 99u,
- 88u, 110u, 62u, 221u,
- 96u, 163u, 117u, 103u,
- 142u, 226u, 150u, 110u,
- 255u, 102u, 88u, 141u,
- 118u, 103u, 196u, 1u,
- 129u, 126u, 141u, 80u,
- 124u, 188u, 142u, 129u,
- 200u, 169u, 132u, 183u,
- 136u, 237u, 44u, 172u,
- 66u, 1u, 143u, 129u,
- 126u, 200u, 15u, 94u,
- 215u, 127u, 101u, 61u,
- 144u, 159u, 255u, 68u,
- 210u, 192u, 70u, 72u,
- 78u, 201u, 192u, 89u,
- 200u, 188u, 110u, 122u,
- 25u, 1u, 9u, 122u,
- 242u, 122u, 86u, 91u,
- 196u, 94u, 104u, 185u,
- 208u, 51u, 161u, 88u,
- 110u, 134u, 150u, 146u,
- 99u, 96u, 155u, 48u,
- 81u, 230u, 30u, 62u,
- 94u, 133u, 255u, 136u,
- 105u, 220u, 127u, 123u,
- 236u, 98u, 212u, 46u,
- 1u, 203u, 130u, 153u,
- 219u, 128u, 109u, 109u,
- 166u, 147u, 149u, 138u,
- 60u, 175u, 167u, 200u,
- 165u, 109u, 143u, 144u,
- 0u, 146u, 187u, 112u,
- 187u, 141u, 105u, 132u,
- 170u, 152u, 115u, 153u,
- 42u, 70u, 71u, 179u,
- 53u, 255u, 123u, 60u,
- 255u, 155u, 171u, 117u,
- 153u, 94u, 80u, 150u,
- 237u, 113u, 152u, 81u,
- 72u, 53u, 116u, 168u,
- 71u, 155u, 159u, 191u,
- 232u, 138u, 255u, 131u,
- 190u, 53u, 134u, 167u,
- 122u, 72u, 77u, 206u,
- 65u, 192u, 133u, 66u,
- 154u, 164u, 224u, 255u,
- 105u, 91u, 140u, 232u,
- 149u, 81u, 203u, 121u,
- 0u, 123u, 48u, 136u,
- 151u, 118u, 141u, 101u,
- 174u, 105u, 46u, 58u,
- 169u, 171u, 140u, 85u,
- 32u, 56u, 73u, 12u,
- 38u, 11u, 1u, 149u,
- 234u, 203u, 141u, 120u,
- 191u, 107u, 234u, 118u,
- 134u, 15u, 90u, 90u,
- 168u, 240u, 206u, 195u,
- 170u, 117u, 175u, 47u,
- 112u, 1u, 129u, 27u,
- 183u, 108u, 209u, 78u,
- 166u, 63u, 100u, 165u,
- 69u, 255u, 62u, 169u,
- 72u, 227u, 183u, 159u,
- 146u, 124u, 114u, 171u,
- 177u, 229u, 98u, 237u,
- 213u, 184u, 39u, 255u,
- 143u, 175u, 210u, 155u,
- 184u, 135u, 247u, 123u,
- 77u, 140u, 0u, 120u,
- 56u, 132u, 119u, 152u,
- 160u, 87u, 118u, 139u,
- 160u, 119u, 168u, 9u,
- 116u, 153u, 1u, 183u,
- 53u, 103u, 46u, 108u,
- 74u, 147u, 82u, 117u,
- 160u, 168u, 98u, 187u,
- 134u, 124u, 134u, 36u,
- 63u, 82u, 0u, 187u,
- 60u, 114u, 182u, 35u,
- 117u, 153u, 198u, 131u,
- 161u, 73u, 133u, 36u,
- 156u, 92u, 138u, 53u,
- 1u, 153u, 86u, 77u,
- 67u, 87u, 135u, 255u,
- 91u, 180u, 195u, 138u,
- 80u, 168u, 198u, 73u,
- 107u, 70u, 189u, 123u,
- 136u, 107u, 142u, 72u,
- 211u, 98u, 186u, 47u,
- 38u, 243u, 82u, 78u,
- 255u, 197u, 132u, 160u,
- 187u, 163u, 157u, 71u,
- 254u, 185u, 163u, 49u,
- 153u, 102u, 120u, 151u,
- 100u, 31u, 160u, 255u,
- 157u, 138u, 97u, 0u,
- 110u, 115u, 107u, 183u,
- 125u, 175u, 99u, 122u,
- 75u, 101u, 123u, 208u,
- 32u, 160u, 208u, 100u,
- 21u, 97u, 191u, 106u,
- 7u, 134u, 34u, 236u,
- 87u, 28u, 255u, 155u,
- 169u, 124u, 196u, 66u,
- 206u, 101u, 109u, 247u,
- 177u, 112u, 133u, 140u,
- 1u, 161u, 137u, 91u,
- 134u, 10u, 128u, 125u,
- 109u, 255u, 116u, 94u,
- 134u, 226u, 114u, 95u,
- 147u, 220u, 88u, 175u,
- 246u, 103u, 119u, 35u,
- 95u, 163u, 205u, 140u,
- 132u, 255u, 77u, 119u,
- 151u, 219u, 99u, 81u,
- 98u, 255u, 155u, 113u,
- 162u, 189u, 115u, 72u,
- 82u, 155u, 88u, 166u,
- 96u, 96u, 117u, 106u,
- 42u, 178u, 27u, 79u,
- 255u, 120u, 14u, 121u,
- 109u, 207u, 7u, 23u,
- 240u, 121u, 105u, 170u,
- 163u, 95u, 248u, 162u,
- 1u, 172u, 96u, 74u,
- 97u, 113u, 117u, 80u,
- 131u, 148u, 95u, 49u,
- 101u, 110u, 95u, 184u,
- 97u, 167u, 58u, 50u,
- 37u, 159u, 117u, 193u,
- 51u, 143u, 197u, 0u,
- 101u, 130u, 126u, 104u,
- 111u, 215u, 31u, 150u,
- 34u, 172u, 131u, 86u,
- 1u, 132u, 115u, 150u,
- 229u, 176u, 226u, 187u,
- 124u, 110u, 185u, 143u,
- 179u, 200u, 154u, 255u,
- 207u, 203u, 103u, 38u,
- 95u, 56u, 86u, 121u,
- 1u, 57u, 80u, 239u,
- 123u, 87u, 137u, 162u,
- 183u, 162u, 144u, 198u,
- 73u, 169u, 234u, 151u,
- 97u, 69u, 79u, 152u,
- 255u, 124u, 170u, 42u,
- 164u, 132u, 182u, 41u,
- 213u, 136u, 250u, 134u,
- 90u, 182u, 169u, 116u,
- 77u, 145u, 149u, 149u,
- 133u, 221u, 1u, 110u,
- 104u, 182u, 178u, 172u,
- 75u, 107u, 151u, 96u,
- 204u, 160u, 118u, 108u,
- 71u, 163u, 255u, 115u,
- 141u, 143u, 72u, 65u,
- 95u, 171u, 84u, 142u,
- 123u, 101u, 99u, 105u,
- 91u, 1u, 68u, 149u,
- 65u, 144u, 175u, 255u,
- 111u, 208u, 16u, 174u,
- 209u, 142u, 110u, 170u,
- 68u, 82u, 125u, 120u,
- 94u, 180u, 228u, 71u,
- 145u, 101u, 92u, 1u,
- 207u, 254u, 149u, 128u,
- 84u, 72u, 150u, 131u,
- 72u, 109u, 118u, 87u,
- 229u, 149u, 138u, 117u,
- 1u, 156u, 125u, 50u,
- 133u, 7u, 38u, 111u,
- 58u, 79u, 166u, 188u,
- 78u, 1u, 229u, 47u,
- 137u, 86u, 84u, 117u,
- 215u, 108u, 142u, 65u,
- 112u, 174u, 111u, 110u,
- 159u, 118u, 147u, 183u,
- 192u, 177u, 1u, 182u,
- 125u, 67u, 56u, 73u,
- 92u, 107u, 127u, 125u,
- 137u, 164u, 63u, 79u,
- 29u, 218u, 191u, 140u,
- 147u, 214u, 181u, 255u,
- 196u, 127u, 255u, 216u,
- 57u, 160u, 4u, 166u,
- 107u, 99u, 160u, 34u,
- 99u, 178u, 172u, 79u,
- 160u, 188u, 171u, 70u,
- 169u, 74u, 209u, 227u,
- 66u, 231u, 154u, 13u,
- 1u, 165u, 132u, 88u,
- 200u, 80u, 109u, 255u,
- 125u, 208u, 146u, 106u,
- 101u, 108u, 61u, 115u,
- 159u, 100u, 112u, 67u,
- 226u, 188u, 255u, 193u,
- 72u, 69u, 97u, 121u,
- 99u, 115u, 149u, 121u,
- 121u, 133u, 124u, 104u,
- 124u, 117u, 143u, 201u,
- 143u, 255u, 128u, 187u,
- 97u, 182u, 92u, 115u,
- 134u, 99u, 105u, 119u,
- 19u, 210u, 255u, 85u,
- 111u, 155u, 75u, 128u,
- 177u, 132u, 162u, 95u,
- 186u, 196u, 198u, 89u,
- 83u, 81u, 122u, 213u,
- 188u, 86u, 209u, 185u,
- 60u, 152u, 143u, 191u,
- 191u, 158u, 1u, 97u,
- 218u, 79u, 100u, 168u,
- 176u, 126u, 82u, 147u,
- 107u, 182u, 139u, 46u,
- 205u, 162u, 1u, 107u,
- 23u, 131u, 237u, 47u,
- 74u, 122u, 32u, 50u,
- 194u, 50u, 173u, 1u,
- 55u, 206u, 79u, 127u,
- 84u, 92u, 138u, 133u,
- 44u, 77u, 120u, 6u,
- 152u, 149u, 54u, 255u,
- 117u, 88u, 45u, 183u,
- 73u, 174u, 129u, 151u,
- 238u, 155u, 80u, 229u,
- 223u, 255u, 32u, 172u,
- 129u, 195u, 98u, 79u,
- 137u, 138u, 26u, 45u,
- 233u, 64u, 126u, 142u,
- 133u, 108u, 73u, 1u,
- 133u, 20u, 71u, 123u,
- 155u, 162u, 93u, 107u,
- 191u, 112u, 127u, 255u,
- 133u, 97u, 208u, 83u,
- 180u, 113u, 172u, 134u,
- 163u, 101u, 67u, 128u,
- 114u, 109u, 136u, 103u,
- 195u, 150u, 1u, 129u,
- 53u, 174u, 166u, 106u,
- 1u, 131u, 192u, 115u,
- 75u, 160u, 109u, 80u,
- 137u, 82u, 213u, 163u,
- 56u, 141u, 9u, 212u,
- 119u, 153u, 51u, 233u,
- 154u, 185u, 53u, 94u,
- 81u, 90u, 198u, 179u,
- 255u, 9u, 44u, 90u,
- 208u, 83u, 50u, 80u,
- 177u, 66u, 113u, 255u,
- 59u, 203u, 180u, 19u,
- 113u, 143u, 247u, 111u,
- 120u, 159u, 136u, 113u,
- 178u, 182u, 158u, 255u,
- 87u, 44u, 125u, 185u,
- 235u, 207u, 90u, 206u,
- 115u, 149u, 162u, 255u,
- 83u, 125u, 188u, 190u,
- 156u, 152u, 146u, 235u,
- 114u, 149u, 126u, 74u,
- 32u, 82u, 96u, 201u,
- 100u, 130u, 185u, 157u,
- 127u, 70u, 166u, 134u,
- 255u, 175u, 59u, 218u,
- 136u, 136u, 234u, 180u,
- 115u, 41u, 62u, 159u,
- 33u, 83u, 221u, 163u,
- 165u, 74u, 1u, 183u,
- 164u, 64u, 152u, 172u,
- 24u, 80u, 95u, 140u,
- 255u, 220u, 73u, 145u,
- 181u, 105u, 195u, 183u,
- 97u, 135u, 129u, 193u,
- 104u, 167u, 112u, 75u,
- 0u, 31u, 156u, 127u,
- 185u, 141u, 168u, 212u,
- 83u, 16u, 0u, 172u,
- 139u, 122u, 12u, 161u,
- 110u, 186u, 136u, 47u,
- 91u, 111u, 150u, 111u,
- 178u, 250u, 74u, 108u,
- 205u, 249u, 109u, 152u,
- 34u, 175u, 174u, 182u,
- 184u, 131u, 1u, 89u,
- 149u, 102u, 205u, 105u,
- 72u, 139u, 158u, 139u,
- 37u, 151u, 255u, 144u,
- 151u, 253u, 116u, 160u,
- 255u, 124u, 118u, 157u,
- 211u, 206u, 80u, 64u,
- 33u, 74u, 151u, 249u,
- 53u, 125u, 121u, 248u,
- 158u, 88u, 255u, 68u,
- 167u, 120u, 185u, 115u,
- 169u, 172u, 179u, 85u,
- 120u, 98u, 109u, 74u,
- 108u, 119u, 107u, 113u,
- 134u, 181u, 154u, 147u,
- 129u, 255u, 202u, 146u,
- 125u, 118u, 118u, 89u,
- 198u, 194u, 184u, 238u,
- 29u, 144u, 141u, 147u,
- 176u, 1u, 221u, 210u,
- 197u, 33u, 162u, 188u,
- 92u, 133u, 5u, 198u,
- 65u, 195u, 237u, 169u,
- 220u, 156u, 136u, 21u,
- 255u, 106u, 122u, 247u,
- 109u, 162u, 70u, 218u,
- 101u, 105u, 255u, 76u,
- 178u, 115u, 240u, 108u,
- 125u, 49u, 74u, 5u,
- 122u, 63u, 255u, 182u,
- 97u, 59u, 56u, 213u,
- 64u, 123u, 129u, 229u,
- 146u, 210u, 172u, 123u,
- 91u, 183u, 97u, 82u,
- 240u, 255u, 110u, 56u,
- 103u, 157u, 189u, 139u,
- 180u, 48u, 143u, 125u,
- 98u, 55u, 138u, 88u,
- 123u, 0u, 196u, 152u,
- 155u, 137u, 168u, 56u,
- 195u, 173u, 124u, 139u,
- 255u, 134u, 192u, 77u,
- 184u, 155u, 96u, 137u,
- 130u, 48u, 106u, 164u,
- 43u, 135u, 46u, 169u,
- 173u, 170u, 101u, 189u,
- 194u, 63u, 119u, 66u,
- 102u, 158u, 158u, 102u,
- 183u, 102u, 141u, 255u,
- 152u, 10u, 83u, 1u,
- 55u, 91u, 93u, 70u,
- 172u, 157u, 86u, 193u,
- 122u, 92u, 97u, 55u,
- 126u, 175u, 127u, 159u,
- 198u, 163u, 139u, 189u,
- 49u, 185u, 195u, 75u,
- 255u, 140u, 111u, 47u,
- 125u, 203u, 156u, 135u,
- 1u, 171u, 178u, 123u,
- 193u, 190u, 123u, 134u,
- 90u, 242u, 115u, 107u,
- 222u, 103u, 204u, 210u,
- 0u, 151u, 153u, 139u,
- 93u, 66u, 162u, 82u,
- 123u, 58u, 113u, 93u,
- 88u, 139u, 1u, 71u,
- 68u, 119u, 98u, 80u,
- 131u, 184u, 69u, 128u,
- 50u, 146u, 166u, 187u,
- 78u, 122u, 119u, 67u,
- 17u, 255u, 78u, 170u,
- 110u, 230u, 252u, 200u,
- 99u, 132u, 93u, 242u,
- 111u, 155u, 128u, 87u,
- 85u, 167u, 190u, 49u,
- 218u, 164u, 121u, 115u,
- 120u, 149u, 163u, 255u,
- 82u, 239u, 43u, 137u,
- 60u, 116u, 122u, 130u,
- 163u, 73u, 139u, 98u,
- 65u, 55u, 90u, 255u,
- 124u, 187u, 45u, 117u,
- 65u, 182u, 150u, 9u,
- 97u, 87u, 80u, 91u,
- 0u, 97u, 132u, 249u,
- 175u, 120u, 240u, 110u,
- 140u, 76u, 179u, 156u,
- 97u, 137u, 79u, 176u,
- 131u, 255u, 165u, 182u,
- 164u, 219u, 179u, 111u,
- 99u, 147u, 78u, 55u,
- 231u, 253u, 112u, 116u,
- 111u, 81u, 124u, 255u,
- 51u, 69u, 92u, 234u,
- 26u, 73u, 0u, 144u,
- 34u, 40u, 54u, 129u,
- 222u, 173u, 148u, 156u,
- 181u, 140u, 199u, 122u,
- 89u, 155u, 137u, 96u,
- 44u, 255u, 130u, 178u,
- 163u, 124u, 89u, 185u,
- 163u, 158u, 49u, 27u,
- 173u, 79u, 128u, 138u,
- 88u, 118u, 170u, 84u,
- 0u, 173u, 63u, 93u,
- 103u, 206u, 46u, 117u,
- 70u, 239u, 131u, 168u,
- 104u, 1u, 65u, 162u,
- 179u, 188u, 124u, 99u,
- 140u, 142u, 42u, 91u,
- 255u, 65u, 172u, 151u,
- 63u, 159u, 164u, 206u,
- 19u, 127u, 99u, 135u,
- 65u, 73u, 42u, 114u,
- 163u, 207u, 145u, 155u,
- 77u, 116u, 111u, 71u,
- 138u, 255u, 50u, 134u,
- 79u, 72u, 1u, 159u,
- 104u, 150u, 24u, 138u,
- 62u, 144u, 168u, 48u,
- 231u, 154u, 122u, 145u,
- 90u, 148u, 126u, 72u,
- 160u, 82u, 240u, 239u,
- 109u, 1u, 158u, 170u,
- 113u, 241u, 102u, 170u,
- 130u, 221u, 184u, 124u,
- 209u, 12u, 243u, 62u,
- 121u, 1u, 246u, 65u,
- 145u, 182u, 125u, 156u,
- 152u, 195u, 16u, 157u,
- 28u, 199u, 92u, 50u,
- 210u, 1u, 158u, 255u,
- 88u, 15u, 120u, 84u,
- 77u, 132u, 178u, 98u,
- 36u, 176u, 94u, 92u,
- 140u, 166u, 131u, 71u,
- 0u, 161u, 130u, 111u,
- 217u, 176u, 151u, 137u,
- 165u, 182u, 182u, 64u,
- 38u, 153u, 135u, 172u,
- 0u, 73u, 119u, 156u,
- 159u, 176u, 204u, 141u,
- 225u, 101u, 112u, 173u,
- 109u, 82u, 203u, 202u,
- 231u, 147u, 105u, 1u,
- 103u, 114u, 86u, 165u,
- 153u, 83u, 109u, 58u,
- 104u, 112u, 85u, 136u,
- 255u, 117u, 87u, 130u,
- 202u, 86u, 83u, 193u,
- 144u, 130u, 90u, 189u,
- 88u, 69u, 116u, 80u,
- 1u, 187u, 162u, 164u,
- 124u, 129u, 77u, 39u,
- 199u, 160u, 203u, 143u,
- 91u, 132u, 99u, 48u,
- 93u, 1u, 147u, 53u,
- 32u, 220u, 123u, 83u,
- 0u, 110u, 128u, 140u,
- 149u, 92u, 203u, 207u,
- 70u, 129u, 153u, 135u,
- 90u, 110u, 192u, 145u,
- 115u, 126u, 0u, 12u,
- 53u, 149u, 145u, 88u,
- 184u, 123u, 95u, 66u,
- 154u, 86u, 127u, 175u,
- 0u, 195u, 97u, 211u,
- 83u, 40u, 185u, 193u,
- 99u, 28u, 159u, 180u,
- 52u, 118u, 143u, 255u,
- 133u, 99u, 82u, 56u,
- 51u, 71u, 84u, 206u,
- 173u, 11u, 143u, 35u,
- 234u, 51u, 93u, 255u,
- 102u, 77u, 2u, 81u,
- 94u, 102u, 158u, 110u,
- 97u, 32u, 12u, 254u,
- 84u, 86u, 192u, 255u,
- 108u, 197u, 111u, 97u,
- 173u, 239u, 138u, 214u,
- 149u, 62u, 162u, 35u,
- 232u, 249u, 207u, 74u,
- 96u, 255u, 99u, 193u,
- 137u, 73u, 188u, 194u,
- 106u, 13u, 16u, 255u,
- 178u, 92u, 255u, 69u,
- 84u, 198u, 92u, 125u,
- 174u, 59u, 88u, 164u,
- 112u, 119u, 98u, 116u,
- 112u, 162u, 183u, 30u,
- 38u, 248u, 106u, 1u,
- 48u, 157u, 135u, 97u,
- 130u, 172u, 183u, 213u,
- 149u, 120u, 50u, 136u,
- 76u, 174u, 245u, 70u,
- 170u, 132u, 116u, 240u,
- 38u, 4u, 255u, 130u,
- 133u, 34u, 149u, 113u,
- 0u, 130u, 135u, 14u,
- 111u, 173u, 155u, 55u,
- 178u, 181u, 189u, 185u,
- 62u, 90u, 131u, 168u,
- 70u, 98u, 255u, 102u,
- 129u, 103u, 105u, 123u,
- 140u, 109u, 168u, 69u,
- 207u, 77u, 208u, 182u,
- 141u, 230u, 1u, 137u,
- 100u, 33u, 166u, 215u,
- 184u, 93u, 222u, 78u,
- 137u, 93u, 183u, 255u,
- 139u, 72u, 177u, 75u,
- 121u, 48u, 181u, 112u,
- 182u, 216u, 176u, 137u,
- 62u, 57u, 85u, 63u,
- 2u, 171u, 62u, 26u,
- 197u, 131u, 13u, 255u,
- 32u, 59u, 182u, 11u,
- 127u, 179u, 232u, 89u,
- 253u, 178u, 150u, 141u,
- 1u, 73u, 138u, 146u,
- 222u, 183u, 155u, 23u,
- 199u, 97u, 164u, 153u,
- 107u, 226u, 161u, 206u,
- 151u, 154u, 1u, 165u,
- 118u, 70u, 182u, 219u,
- 218u, 219u, 167u, 88u,
- 205u, 120u, 160u, 1u,
- 32u, 117u, 129u, 66u,
- 109u, 79u, 99u, 173u,
- 124u, 85u, 165u, 146u,
- 145u, 102u, 146u, 107u,
- 171u, 255u, 171u, 132u,
- 206u, 90u, 149u, 70u,
- 54u, 67u, 95u, 88u,
- 132u, 67u, 63u, 22u,
- 59u, 192u, 150u, 30u,
- 139u, 118u, 1u, 102u,
- 255u, 54u, 18u, 16u,
- 152u, 104u, 59u, 203u,
- 232u, 232u, 142u, 7u,
- 152u, 63u, 229u, 127u,
- 178u, 97u, 51u, 140u,
- 186u, 51u, 25u, 147u,
- 108u, 12u, 39u, 189u,
- 1u, 132u, 194u, 211u,
- 87u, 106u, 80u, 233u,
- 153u, 89u, 35u, 87u,
- 255u, 166u, 103u, 236u,
- 80u, 110u, 255u, 116u,
- 167u, 111u, 108u, 134u,
- 1u, 185u, 18u, 29u,
- 152u, 136u, 171u, 54u,
- 47u, 25u, 223u, 215u,
- 187u, 156u, 132u, 75u,
- 109u, 133u, 45u, 68u,
- 1u, 112u, 93u, 169u,
- 91u, 149u, 76u, 47u,
- 158u, 178u, 144u, 106u,
- 98u, 5u, 193u, 0u,
- 155u, 59u, 255u, 165u,
- 111u, 130u, 234u, 232u,
- 145u, 201u, 210u, 118u,
- 74u, 156u, 75u, 1u,
- 82u, 129u, 134u, 106u,
- 131u, 121u, 146u, 104u,
- 142u, 193u, 45u, 178u,
- 133u, 119u, 43u, 165u,
- 65u, 165u, 123u, 125u,
- 111u, 47u, 1u, 152u,
- 147u, 227u, 110u, 108u,
- 248u, 83u, 38u, 250u,
- 194u, 53u, 141u, 115u,
- 125u, 1u, 139u, 22u,
- 121u, 127u, 214u, 108u,
- 85u, 174u, 36u, 104u,
- 201u, 255u, 139u, 106u,
- 132u, 147u, 224u, 175u,
- 29u, 115u, 138u, 73u,
- 143u, 140u, 111u, 136u,
- 161u, 183u, 102u, 104u,
- 140u, 133u, 150u, 255u,
- 137u, 95u, 158u, 255u,
- 155u, 141u, 131u, 110u,
- 39u, 70u, 124u, 13u,
- 193u, 118u, 79u, 88u,
- 155u, 68u, 166u, 124u,
- 189u, 147u, 177u, 162u,
- 82u, 89u, 203u, 132u,
- 152u, 125u, 1u, 96u,
- 124u, 18u, 86u, 103u,
- 69u, 131u, 150u, 168u,
- 114u, 61u, 131u, 181u,
- 125u, 88u, 0u, 90u,
- 60u, 163u, 192u, 138u,
- 147u, 178u, 52u, 40u,
- 171u, 99u, 114u, 138u,
- 255u, 62u, 54u, 163u,
- 160u, 73u, 152u, 55u,
- 72u, 194u, 208u, 158u,
- 163u, 75u, 78u, 86u,
- 102u, 120u, 148u, 255u,
- 82u, 153u, 122u, 56u,
- 240u, 184u, 167u, 135u,
- 0u, 59u, 39u, 37u,
- 46u, 170u, 55u, 247u,
- 110u, 107u, 143u, 196u,
- 18u, 219u, 120u, 78u,
- 159u, 147u, 151u, 86u,
- 173u, 255u, 153u, 209u,
- 82u, 146u, 150u, 150u,
- 255u, 125u, 208u, 167u,
- 228u, 226u, 72u, 188u,
- 89u, 117u, 174u, 137u,
- 133u, 115u, 217u, 202u,
- 89u, 173u, 174u, 156u,
- 135u, 255u, 118u, 169u,
- 60u, 166u, 125u, 200u,
- 171u, 83u, 180u, 56u,
- 62u, 132u, 155u, 190u,
- 223u, 120u, 158u, 157u,
- 198u, 0u, 184u, 119u,
- 137u, 222u, 111u, 195u,
- 88u, 223u, 130u, 149u,
- 0u, 4u, 153u, 170u,
- 69u, 119u, 101u, 201u,
- 115u, 181u, 159u, 255u,
- 58u, 97u, 129u, 123u,
- 207u, 45u, 76u, 236u,
- 152u, 164u, 178u, 193u,
- 140u, 134u, 142u, 77u,
- 190u, 1u, 140u, 182u,
- 164u, 235u, 176u, 68u,
- 232u, 31u, 24u, 114u,
- 202u, 157u, 1u, 126u,
- 76u, 146u, 71u, 78u,
- 133u, 141u, 164u, 210u,
- 61u, 200u, 170u, 104u,
- 83u, 92u, 124u, 145u,
- 118u, 56u, 148u, 182u,
- 167u, 143u, 128u, 145u,
- 255u, 108u, 128u, 100u,
- 98u, 216u, 179u, 60u,
- 83u, 255u, 58u, 133u,
- 255u, 134u, 90u, 113u,
- 133u, 72u, 214u, 212u,
- 187u, 86u, 89u, 73u,
- 209u, 111u, 156u, 69u,
- 10u, 52u, 143u, 111u,
- 211u, 164u, 72u, 255u,
- 213u, 184u, 157u, 73u,
- 255u, 98u, 85u, 121u,
- 17u, 253u, 31u, 204u,
- 222u, 174u, 80u, 251u,
- 43u, 154u, 152u, 235u,
- 101u, 74u, 158u, 103u,
- 123u, 255u, 166u, 175u,
- 177u, 121u, 222u, 114u,
- 199u, 49u, 191u, 32u,
- 88u, 115u, 58u, 181u,
- 239u, 0u, 174u, 162u,
- 228u, 58u, 146u, 126u,
- 158u, 74u, 157u, 64u,
- 121u, 183u, 66u, 164u,
- 133u, 142u, 205u, 142u,
- 52u, 46u, 255u, 168u,
- 167u, 68u, 150u, 188u,
- 86u, 159u, 163u, 171u,
- 180u, 208u, 254u, 34u,
- 39u, 147u, 1u, 70u,
- 133u, 176u, 141u, 179u,
- 186u, 133u, 1u, 53u,
- 69u, 119u, 126u, 55u,
- 79u, 106u, 147u, 79u,
- 118u, 175u, 126u, 104u,
- 39u, 169u, 194u, 255u,
- 173u, 30u, 94u, 225u,
- 123u, 136u, 104u, 178u,
- 193u, 101u, 242u, 65u,
- 187u, 116u, 0u, 37u,
- 52u, 111u, 154u, 184u,
- 146u, 126u, 114u, 161u,
- 176u, 164u, 154u, 110u,
- 96u, 191u, 165u, 112u,
- 227u, 255u, 203u, 88u,
- 186u, 57u, 153u, 170u,
- 102u, 118u, 164u, 104u,
- 137u, 130u, 127u, 203u,
- 91u, 142u, 231u, 184u,
- 157u, 1u, 181u, 92u,
- 155u, 197u, 14u, 42u,
- 173u, 72u, 124u, 169u,
- 190u, 220u, 61u, 14u,
- 108u, 26u, 255u, 216u,
- 130u, 9u, 169u, 141u,
- 49u, 255u, 83u, 118u,
- 218u, 141u, 107u, 67u,
- 255u, 240u, 209u, 152u,
- 135u, 95u, 56u, 139u,
- 116u, 120u, 132u, 117u,
- 198u, 179u, 68u, 80u,
- 177u, 72u, 35u, 0u,
- 62u, 147u, 53u, 95u,
- 167u, 255u, 144u, 106u,
- 49u, 147u, 43u, 178u,
- 74u, 83u, 64u, 143u,
- 135u, 170u, 100u, 1u,
- 179u, 187u, 208u, 165u,
- 55u, 140u, 95u, 172u,
- 65u, 66u, 142u, 97u,
- 255u, 97u, 194u, 112u,
- 67u, 135u, 99u, 138u,
- 132u, 83u, 140u, 146u,
- 78u, 91u, 176u, 53u,
- 215u, 86u, 141u, 70u,
- 121u, 96u, 148u, 128u,
- 99u, 65u, 185u, 152u,
- 180u, 108u, 255u, 249u,
- 249u, 60u, 24u, 77u,
- 57u, 109u, 104u, 170u,
- 102u, 163u, 58u, 96u,
- 154u, 255u, 99u, 53u,
- 78u, 150u, 174u, 134u,
- 100u, 1u, 142u, 93u,
- 203u, 141u, 170u, 153u,
- 77u, 209u, 74u, 89u,
- 166u, 163u, 42u, 96u,
- 20u, 153u, 103u, 72u,
- 158u, 154u, 122u, 111u,
- 0u, 83u, 125u, 91u,
- 174u, 63u, 1u, 73u,
- 45u, 78u, 55u, 81u,
- 141u, 58u, 198u, 61u,
- 155u, 21u, 171u, 149u,
- 48u, 0u, 227u, 85u,
- 166u, 135u, 142u, 106u,
- 115u, 79u, 180u, 106u,
- 57u, 222u, 30u, 111u,
- 255u, 34u, 187u, 108u,
- 81u, 39u, 64u, 154u,
- 176u, 170u, 140u, 102u,
- 133u, 102u, 181u, 52u,
- 250u, 67u, 255u, 233u,
- 161u, 180u, 203u, 121u,
- 132u, 170u, 27u, 138u,
- 16u, 128u, 197u, 67u,
- 139u, 168u, 72u, 58u,
- 111u, 142u, 85u, 66u,
- 128u, 137u, 106u, 140u,
- 107u, 0u, 95u, 138u,
- 179u, 135u, 30u, 129u,
- 97u, 159u, 100u, 107u,
- 188u, 88u, 142u, 118u,
- 1u, 147u, 202u, 99u,
- 185u, 161u, 169u, 182u,
- 147u, 161u, 201u, 62u,
- 127u, 104u, 51u, 179u,
- 1u, 156u, 179u, 130u,
- 97u, 119u, 156u, 192u,
- 39u, 113u, 159u, 120u,
- 228u, 121u, 121u, 205u,
- 1u, 193u, 202u, 107u,
- 163u, 143u, 133u, 163u,
- 69u, 155u, 106u, 158u,
- 140u, 120u, 104u, 109u,
- 108u, 167u, 255u, 164u,
- 115u, 190u, 211u, 176u,
- 199u, 153u, 1u, 47u,
- 85u, 224u, 90u, 119u,
- 135u, 123u, 78u, 173u,
- 125u, 63u, 251u, 236u,
- 89u, 145u, 141u, 210u,
- 165u, 1u, 174u, 119u,
- 44u, 212u, 119u, 50u,
- 58u, 178u, 80u, 129u,
- 222u, 146u, 238u, 173u,
- 228u, 209u, 26u, 56u,
- 184u, 255u, 193u, 142u,
- 44u, 118u, 112u, 136u,
- 241u, 255u, 115u, 106u,
- 116u, 154u, 208u, 224u,
- 36u, 16u, 119u, 36u,
- 176u, 25u, 120u, 255u,
- 58u, 130u, 143u, 104u,
- 173u, 87u, 124u, 150u,
- 197u, 121u, 160u, 161u,
- 147u, 255u, 58u, 250u,
- 173u, 224u, 99u, 167u,
- 206u, 98u, 32u, 218u,
- 91u, 85u, 14u, 186u,
- 80u, 140u, 251u, 255u,
- 100u, 62u, 1u, 15u,
- 168u, 10u, 217u, 83u,
- 233u, 89u, 68u, 192u,
- 148u, 151u, 118u, 191u,
- 144u, 161u, 234u, 93u,
- 180u, 12u, 217u, 164u,
- 175u, 184u, 221u, 255u,
- 133u, 120u, 203u, 82u,
- 85u, 96u, 126u, 65u,
- 123u, 255u, 106u, 162u,
- 69u, 215u, 240u, 73u,
- 145u, 162u, 193u, 156u,
- 179u, 147u, 138u, 106u,
- 210u, 101u, 113u, 131u,
- 7u, 116u, 255u, 60u,
- 85u, 61u, 15u, 185u,
- 136u, 58u, 64u, 239u,
- 114u, 149u, 183u, 160u,
- 255u, 69u, 169u, 172u,
- 114u, 142u, 33u, 17u,
- 100u, 59u, 60u, 255u,
- 176u, 106u, 199u, 168u,
- 122u, 143u, 105u, 114u,
- 27u, 91u, 129u, 123u,
- 7u, 98u, 255u, 146u,
- 121u, 142u, 87u, 80u,
- 144u, 178u, 229u, 170u,
- 50u, 76u, 152u, 165u,
- 40u, 178u, 61u, 155u,
- 33u, 213u, 255u, 88u,
- 87u, 168u, 209u, 152u,
- 179u, 139u, 255u, 91u,
- 86u, 42u, 117u, 162u,
- 109u, 135u, 185u, 79u,
- 213u, 120u, 52u, 78u,
- 47u, 230u, 135u, 115u,
- 69u, 84u, 44u, 163u,
- 255u, 48u, 201u, 205u,
- 35u, 203u, 55u, 191u,
- 140u, 158u, 142u, 177u,
- 176u, 91u, 132u, 177u,
- 135u, 125u, 255u, 66u,
- 210u, 163u, 181u, 62u,
- 120u, 255u, 85u, 234u,
- 86u, 75u, 194u, 59u,
- 129u, 97u, 160u, 19u,
- 210u, 177u, 100u, 208u,
- 169u, 136u, 53u, 165u,
- 127u, 155u, 148u, 234u,
- 77u, 73u, 169u, 208u,
- 93u, 141u, 1u, 95u,
- 114u, 201u, 185u, 184u,
- 85u, 123u, 123u, 122u,
- 67u, 43u, 142u, 152u,
- 134u, 137u, 255u, 189u,
- 135u, 255u, 100u, 72u,
- 157u, 128u, 57u, 148u,
- 116u, 117u, 143u, 117u,
- 146u, 71u, 188u, 244u,
- 255u, 27u, 209u, 56u,
- 52u, 56u, 11u, 171u,
- 171u, 182u, 121u, 49u,
- 138u, 84u, 187u, 51u,
- 117u, 237u, 242u, 58u,
- 126u, 117u, 127u, 64u,
- 160u, 73u, 164u, 144u,
- 167u, 1u, 182u, 90u,
- 229u, 136u, 207u, 143u,
- 110u, 38u, 141u, 145u,
- 1u, 69u, 214u, 47u,
- 241u, 192u, 149u, 223u,
- 71u, 255u, 134u, 142u,
- 180u, 8u, 215u, 198u,
- 200u, 132u, 255u, 229u,
- 147u, 128u, 152u, 138u,
- 82u, 134u, 109u, 108u,
- 68u, 135u, 123u, 163u,
- 209u, 137u, 32u, 207u,
- 71u, 190u, 255u, 88u,
- 79u, 218u, 191u, 153u,
- 125u, 141u, 161u, 64u,
- 75u, 1u, 182u, 157u,
- 186u, 165u, 121u, 176u,
- 17u, 224u, 202u, 214u,
- 66u, 149u, 255u, 5u,
- 208u, 41u, 66u, 62u,
- 97u, 170u, 154u, 198u,
- 189u, 137u, 200u, 103u,
- 94u, 117u, 131u, 117u,
- 118u, 155u, 143u, 134u,
- 0u, 79u, 194u, 110u,
- 177u, 140u, 2u, 114u,
- 89u, 134u, 102u, 135u,
- 94u, 110u, 191u, 30u,
- 64u, 243u, 1u, 19u,
- 111u, 57u, 101u, 163u,
- 116u, 158u, 77u, 138u,
- 90u, 103u, 160u, 148u,
- 174u, 120u, 1u, 226u,
- 172u, 50u, 86u, 87u,
- 185u, 175u, 90u, 211u,
- 72u, 178u, 97u, 112u,
- 102u, 117u, 168u, 1u,
- 189u, 139u, 170u, 68u,
- 41u, 78u, 230u, 2u,
- 88u, 29u, 140u, 255u,
- 81u, 55u, 193u, 197u,
- 178u, 255u, 240u, 106u,
- 195u, 86u, 45u, 118u,
- 167u, 137u, 121u, 193u,
- 80u, 150u, 85u, 140u,
- 169u, 255u, 195u, 180u,
- 89u, 7u, 144u, 179u,
- 142u, 124u, 173u, 232u,
- 216u, 57u, 128u, 94u,
- 153u, 172u, 82u, 220u,
- 120u, 32u, 62u, 86u,
- 82u, 87u, 169u, 211u,
- 62u, 255u, 35u, 199u,
- 185u, 124u, 141u, 159u,
- 117u, 183u, 100u, 83u,
- 223u, 179u, 18u, 67u,
- 1u, 140u, 200u, 236u,
- 122u, 43u, 107u, 1u,
- 140u, 113u, 136u, 147u,
- 124u, 135u, 215u, 73u,
- 125u, 75u, 146u, 25u,
- 255u, 54u, 218u, 86u,
- 169u, 110u, 147u, 201u,
- 101u, 133u, 140u, 134u,
- 197u, 166u, 146u, 54u,
- 127u, 153u, 99u, 255u,
- 174u, 127u, 128u, 151u,
- 66u, 175u, 136u, 171u,
- 146u, 206u, 127u, 92u,
- 52u, 66u, 7u, 70u,
- 96u, 47u, 129u, 161u,
- 150u, 64u, 1u, 154u,
- 133u, 155u, 153u, 58u,
- 160u, 30u, 192u, 70u,
- 178u, 77u, 237u, 114u,
- 173u, 234u, 95u, 160u,
- 143u, 132u, 217u, 0u,
- 132u, 140u, 75u, 255u,
- 95u, 125u, 202u, 88u,
- 204u, 128u, 183u, 133u,
- 41u, 180u, 130u, 133u,
- 198u, 165u, 123u, 128u,
- 27u, 46u, 40u, 20u,
- 97u, 229u, 48u, 123u,
- 132u, 100u, 0u, 136u,
- 79u, 158u, 159u, 154u,
- 189u, 231u, 120u, 78u,
- 51u, 211u, 63u, 66u,
- 72u, 255u, 249u, 140u,
- 132u, 109u, 72u, 166u,
- 97u, 227u, 115u, 178u,
- 176u, 102u, 67u, 91u,
- 97u, 151u, 192u, 255u,
- 83u, 98u, 43u, 141u,
- 175u, 178u, 97u, 128u,
- 75u, 177u, 129u, 208u,
- 161u, 155u, 1u, 102u,
- 60u, 80u, 176u, 216u,
- 243u, 71u, 101u, 163u,
- 127u, 69u, 139u, 150u,
- 90u, 255u, 125u, 157u,
- 98u, 155u, 131u, 107u,
- 189u, 129u, 255u, 113u,
- 100u, 175u, 136u, 143u,
- 49u, 11u, 41u, 232u,
- 132u, 144u, 148u, 151u,
- 135u, 132u, 69u, 154u,
- 178u, 120u, 169u, 94u,
- 145u, 85u, 0u, 119u,
- 157u, 145u, 222u, 120u,
- 121u, 101u, 95u, 177u,
- 101u, 150u, 113u, 222u,
- 37u, 255u, 189u, 168u,
- 185u, 180u, 177u, 255u,
- 100u, 58u, 185u, 188u,
- 26u, 66u, 189u, 8u,
- 206u, 178u, 246u, 107u,
- 1u, 113u, 165u, 34u,
- 172u, 141u, 136u, 233u,
- 131u, 146u, 181u, 196u,
- 36u, 221u, 224u, 156u,
- 40u, 208u, 130u, 145u,
- 67u, 116u, 1u, 121u,
- 45u, 53u, 39u, 112u,
- 37u, 70u, 82u, 168u,
- 149u, 143u, 81u, 137u,
- 156u, 201u, 109u, 189u,
- 143u, 95u, 164u, 52u,
- 52u, 124u, 0u, 125u,
- 126u, 153u, 155u, 1u,
- 112u, 74u, 129u, 132u,
- 164u, 180u, 84u, 146u,
- 120u, 165u, 130u, 239u,
- 36u, 145u, 88u, 28u,
- 176u, 70u, 110u, 80u,
- 191u, 152u, 63u, 85u,
- 168u, 168u, 0u, 188u,
- 117u, 199u, 182u, 77u,
- 156u, 156u, 73u, 68u,
- 131u, 110u, 169u, 129u,
- 115u, 143u, 101u, 255u,
- 227u, 190u, 65u, 97u,
- 137u, 5u, 154u, 192u,
- 236u, 5u, 82u, 128u,
- 70u, 84u, 0u, 64u,
- 214u, 55u, 212u, 147u,
- 170u, 78u, 58u, 146u,
- 155u, 1u, 139u, 237u,
- 125u, 82u, 83u, 10u,
- 139u, 162u, 184u, 110u,
- 147u, 214u, 76u, 151u,
- 255u, 138u, 149u, 95u,
- 88u, 19u, 95u, 176u,
- 138u, 100u, 135u, 72u,
- 112u, 68u, 66u, 179u,
- 51u, 179u, 149u, 184u,
- 255u, 106u, 215u, 145u,
- 251u, 83u, 165u, 34u,
- 50u, 89u, 53u, 242u,
- 225u, 125u, 46u, 210u,
- 1u, 8u, 156u, 196u,
- 98u, 156u, 144u, 44u,
- 187u, 133u, 154u, 88u,
- 0u, 45u, 95u, 201u,
- 139u, 39u, 76u, 111u,
- 72u, 196u, 149u, 255u,
- 82u, 130u, 165u, 24u,
- 172u, 198u, 136u, 188u,
- 188u, 76u, 185u, 144u,
- 80u, 103u, 80u, 221u,
- 214u, 73u, 169u, 242u,
- 82u, 1u, 168u, 128u,
- 73u, 125u, 43u, 180u,
- 53u, 58u, 1u, 25u,
- 177u, 61u, 98u, 172u,
- 82u, 77u, 150u, 149u,
- 50u, 153u, 158u, 117u,
- 192u, 148u, 188u, 111u,
- 48u, 152u, 139u, 66u,
- 145u, 207u, 22u, 131u,
- 1u, 149u, 1u, 155u,
- 31u, 112u, 107u, 255u,
- 28u, 198u, 136u, 210u,
- 148u, 13u, 140u, 39u,
- 114u, 62u, 208u, 55u,
- 136u, 89u, 79u, 210u,
- 56u, 106u, 127u, 96u,
- 193u, 128u, 112u, 163u,
- 195u, 56u, 255u, 94u,
- 103u, 125u, 122u, 157u,
- 255u, 177u, 207u, 109u,
- 14u, 88u, 11u, 21u,
- 170u, 200u, 139u, 95u,
- 170u, 10u, 82u, 105u,
- 112u, 159u, 1u, 91u,
- 126u, 122u, 202u, 72u,
- 120u, 87u, 143u, 114u,
- 229u, 144u, 223u, 92u,
- 72u, 136u, 119u, 136u,
- 255u, 198u, 88u, 94u,
- 49u, 149u, 216u, 123u,
- 190u, 142u, 149u, 90u,
- 125u, 123u, 113u, 124u,
- 255u, 174u, 24u, 133u,
- 15u, 139u, 134u, 30u,
- 103u, 255u, 112u, 132u,
- 117u, 241u, 77u, 226u,
- 199u, 73u, 61u, 216u,
- 48u, 136u, 117u, 131u,
- 0u, 151u, 138u, 160u,
- 132u, 103u, 126u, 3u,
- 113u, 157u, 118u, 124u,
- 22u, 69u, 141u, 107u,
- 149u, 56u, 195u, 1u,
- 116u, 117u, 104u, 90u,
- 62u, 236u, 122u, 138u,
- 118u, 152u, 76u, 34u,
- 66u, 120u, 174u, 100u,
- 252u, 128u, 220u, 184u,
- 238u, 86u, 97u, 229u,
- 226u, 255u, 140u, 144u,
- 123u, 125u, 185u, 181u,
- 88u, 119u, 143u, 100u,
- 197u, 122u, 255u, 104u,
- 212u, 132u, 204u, 218u,
- 163u, 75u, 146u, 189u,
- 35u, 0u, 72u, 236u,
- 201u, 67u, 121u, 86u,
- 143u, 214u, 87u, 84u,
- 222u, 133u, 205u, 69u,
- 178u, 31u, 84u, 234u,
- 244u, 255u, 128u, 208u,
- 177u, 77u, 16u, 217u,
- 155u, 52u, 91u, 128u,
- 133u, 185u, 1u, 104u,
- 107u, 138u, 212u, 60u,
- 172u, 31u, 121u, 205u,
- 95u, 158u, 117u, 82u,
- 150u, 144u, 131u, 59u,
- 69u, 110u, 93u, 0u,
- 3u, 151u, 84u, 85u,
- 212u, 177u, 178u, 186u,
- 189u, 181u, 255u, 144u,
- 71u, 169u, 97u, 71u,
- 22u, 156u, 168u, 149u,
- 198u, 192u, 37u, 62u,
- 146u, 76u, 217u, 1u,
- 98u, 162u, 59u, 162u,
- 141u, 135u, 34u, 224u,
- 47u, 74u, 99u, 82u,
- 160u, 164u, 160u, 131u,
- 80u, 153u, 166u, 63u,
- 173u, 151u, 1u, 133u,
- 6u, 173u, 134u, 213u,
- 114u, 212u, 180u, 47u,
- 68u, 91u, 66u, 14u,
- 188u, 163u, 113u, 1u,
- 152u, 129u, 89u, 103u,
- 144u, 215u, 189u, 195u,
- 57u, 1u, 163u, 89u,
- 79u, 78u, 70u, 119u,
- 1u, 171u, 108u, 94u,
- 119u, 137u, 105u, 50u,
- 112u, 107u, 101u, 146u,
- 170u, 129u, 22u, 163u,
- 53u, 35u, 62u, 138u,
- 79u, 167u, 38u, 55u,
- 163u, 136u, 111u, 0u,
- 142u, 148u, 43u, 27u,
- 193u, 187u, 193u, 104u,
- 203u, 175u, 131u, 70u,
- 97u, 141u, 118u, 89u,
- 1u, 25u, 81u, 124u,
- 96u, 229u, 180u, 162u,
- 72u, 72u, 120u, 179u,
- 83u, 145u, 180u, 176u,
- 77u, 255u, 98u, 178u,
- 76u, 87u, 83u, 224u,
- 151u, 94u, 1u, 113u,
- 75u, 127u, 45u, 52u,
- 92u, 45u, 138u, 69u,
- 138u, 134u, 125u, 130u,
- 102u, 255u, 146u, 202u,
- 90u, 95u, 100u, 118u,
- 67u, 93u, 178u, 154u,
- 133u, 134u, 143u, 134u,
- 134u, 153u, 124u, 186u,
- 123u, 79u, 255u, 172u,
- 131u, 244u, 126u, 132u,
- 76u, 160u, 209u, 173u,
- 124u, 157u, 172u, 104u,
- 81u, 157u, 176u, 91u,
- 162u, 255u, 112u, 86u,
- 136u, 168u, 128u, 134u,
- 106u, 255u, 182u, 144u,
- 151u, 110u, 146u, 196u,
- 74u, 158u, 205u, 119u,
- 91u, 131u, 205u, 41u,
- 124u, 118u, 1u, 190u,
- 8u, 140u, 173u, 146u,
- 202u, 130u, 172u, 163u,
- 229u, 79u, 185u, 134u,
- 20u, 83u, 18u, 218u,
- 199u, 110u, 197u, 115u,
- 167u, 131u, 255u, 127u,
- 197u, 154u, 164u, 147u,
- 121u, 131u, 111u, 189u,
- 126u, 121u, 86u, 194u,
- 1u, 119u, 212u, 112u,
- 99u, 93u, 224u, 114u,
- 227u, 1u, 129u, 144u,
- 111u, 229u, 145u, 37u,
- 71u, 209u, 192u, 91u,
- 238u, 158u, 238u, 154u,
- 75u, 158u, 138u, 55u,
- 181u, 85u, 209u, 141u,
- 136u, 0u, 57u, 35u,
- 59u, 136u, 151u, 184u,
- 125u, 31u, 1u, 20u,
- 103u, 63u, 96u, 65u,
- 211u, 141u, 81u, 42u,
- 121u, 177u, 184u, 206u,
- 126u, 99u, 115u, 186u,
- 134u, 229u, 92u, 210u,
- 255u, 135u, 211u, 13u,
- 112u, 93u, 109u, 154u,
- 162u, 172u, 100u, 145u,
- 123u, 94u, 143u, 106u,
- 1u, 148u, 123u, 32u,
- 124u, 156u, 173u, 170u,
- 136u, 81u, 215u, 106u,
- 132u, 88u, 225u, 51u,
- 255u, 218u, 125u, 78u,
- 124u, 109u, 86u, 85u,
- 181u, 255u, 85u, 212u,
- 99u, 155u, 89u, 95u,
- 60u, 165u, 125u, 56u,
- 117u, 230u, 62u, 115u,
- 126u, 128u, 186u, 127u,
- 0u, 135u, 96u, 146u,
- 56u, 233u, 91u, 97u,
- 191u, 191u, 175u, 98u,
- 241u, 164u, 129u, 211u,
- 67u, 255u, 146u, 146u,
- 220u, 132u, 86u, 154u,
- 11u, 121u, 87u, 245u,
- 8u, 124u, 1u, 179u,
- 146u, 193u, 113u, 49u,
- 43u, 203u, 200u, 93u,
- 68u, 174u, 209u, 71u,
- 77u, 133u, 222u, 1u,
- 78u, 116u, 141u, 148u,
- 107u, 155u, 118u, 132u,
- 176u, 241u, 114u, 140u,
- 15u, 209u, 142u, 134u,
- 134u, 152u, 53u, 0u,
- 151u, 109u, 174u, 137u,
- 255u, 145u, 225u, 198u,
- 186u, 98u, 53u, 212u,
- 13u, 152u, 173u, 117u,
- 149u, 174u, 91u, 133u,
- 220u, 240u, 142u, 62u,
- 191u, 104u, 85u, 138u,
- 255u, 127u, 72u, 137u,
- 94u, 134u, 211u, 106u,
- 1u, 205u, 194u, 190u,
- 144u, 136u, 109u, 97u,
- 70u, 149u, 112u, 142u,
- 140u, 166u, 114u, 80u,
- 149u, 77u, 126u, 1u,
- 63u, 58u, 113u, 91u,
- 221u, 158u, 135u, 169u,
- 91u, 132u, 211u, 77u,
- 90u, 125u, 54u, 46u,
- 129u, 35u, 227u, 229u,
- 255u, 168u, 138u, 78u,
- 41u, 202u, 24u, 41u,
- 174u, 130u, 133u, 97u,
- 16u, 17u, 85u, 46u,
- 66u, 135u, 196u, 138u,
- 160u, 255u, 68u, 218u,
- 118u, 84u, 47u, 184u,
- 106u, 1u, 158u, 64u,
- 55u, 154u, 136u, 140u,
- 219u, 88u, 116u, 107u,
- 169u, 94u, 51u, 144u,
- 255u, 202u, 233u, 106u,
- 109u, 203u, 60u, 10u,
- 102u, 143u, 154u, 114u,
- 44u, 150u, 120u, 160u,
- 23u, 103u, 80u, 151u,
- 50u, 163u, 255u, 149u,
- 107u, 177u, 115u, 234u,
- 77u, 164u, 106u, 130u,
- 139u, 102u, 129u, 167u,
- 1u, 73u, 178u, 180u,
- 114u, 162u, 172u, 178u,
- 87u, 254u, 139u, 239u,
- 125u, 133u, 116u, 59u,
- 96u, 93u, 161u, 151u,
- 94u, 8u, 122u, 255u,
- 131u, 161u, 30u, 91u,
- 164u, 149u, 169u, 174u,
- 68u, 134u, 172u, 109u,
- 110u, 153u, 0u, 146u,
- 63u, 104u, 26u, 64u,
- 22u, 134u, 91u, 1u,
- 140u, 109u, 106u, 107u,
- 87u, 112u, 172u, 124u,
- 146u, 110u, 222u, 174u,
- 59u, 133u, 174u, 177u,
- 156u, 62u, 211u, 164u,
- 214u, 131u, 255u, 173u,
- 154u, 202u, 145u, 91u,
- 72u, 139u, 169u, 19u,
- 221u, 124u, 142u, 143u,
- 73u, 95u, 109u, 1u,
- 85u, 132u, 248u, 211u,
- 162u, 113u, 175u, 107u,
- 14u, 54u, 169u, 76u,
- 66u, 110u, 1u, 110u,
- 143u, 226u, 91u, 133u,
- 123u, 95u, 155u, 186u,
- 255u, 165u, 135u, 70u,
- 185u, 122u, 48u, 72u,
- 21u, 205u, 27u, 92u,
- 153u, 1u, 28u, 129u,
- 120u, 179u, 82u, 103u,
- 155u, 196u, 29u, 134u,
- 3u, 67u, 180u, 198u,
- 36u, 255u, 106u, 128u,
- 75u, 76u, 131u, 106u,
- 167u, 95u, 61u, 83u,
- 159u, 130u, 255u, 164u,
- 74u, 110u, 125u, 93u,
- 41u, 159u, 198u, 204u,
- 114u, 147u, 165u, 182u,
- 166u, 114u, 7u, 155u,
- 144u, 200u, 208u, 93u,
- 162u, 164u, 235u, 77u,
- 123u, 136u, 127u, 0u,
- 147u, 183u, 192u, 119u,
- 162u, 108u, 252u, 125u,
- 127u, 76u, 181u, 80u,
- 181u, 207u, 154u, 255u,
- 128u, 116u, 87u, 91u,
- 78u, 156u, 137u, 80u,
- 255u, 130u, 97u, 89u,
- 4u, 80u, 232u, 228u,
- 44u, 98u, 145u, 102u,
- 33u, 18u, 186u, 154u,
- 188u, 154u, 10u, 239u,
- 88u, 0u, 95u, 237u,
- 45u, 165u, 62u, 178u,
- 163u, 82u, 255u, 213u,
- 107u, 106u, 177u, 96u,
- 199u, 162u, 191u, 124u,
- 1u, 92u, 94u, 156u,
- 242u, 153u, 87u, 183u,
- 92u, 155u, 8u, 131u,
- 136u, 111u, 200u, 63u,
- 4u, 117u, 28u, 227u,
- 1u, 93u, 196u, 186u,
- 78u, 162u, 178u, 166u,
- 79u, 57u, 170u, 62u,
- 113u, 104u, 55u, 206u,
- 5u, 181u, 113u, 96u,
- 147u, 142u, 78u, 30u,
- 45u, 126u, 194u, 1u,
- 182u, 245u, 216u, 167u,
- 72u, 160u, 130u, 104u,
- 255u, 163u, 197u, 183u,
- 188u, 229u, 153u, 175u,
- 82u, 96u, 175u, 1u,
- 153u, 102u, 227u, 118u,
- 171u, 49u, 132u, 158u,
- 183u, 132u, 86u, 194u,
- 223u, 57u, 198u, 103u,
- 85u, 83u, 74u, 174u,
- 143u, 229u, 238u, 74u,
- 235u, 44u, 255u, 87u,
- 67u, 184u, 48u, 86u,
- 74u, 179u, 50u, 110u,
- 55u, 89u, 81u, 126u,
- 43u, 203u, 255u, 228u,
- 6u, 255u, 48u, 52u,
- 152u, 43u, 117u, 207u,
- 236u, 127u, 109u, 186u,
- 194u, 18u, 60u, 166u,
- 189u, 160u, 109u, 1u,
- 114u, 98u, 92u, 74u,
- 151u, 112u, 93u, 47u,
- 174u, 36u, 71u, 158u,
- 187u, 73u, 127u, 1u,
- 135u, 111u, 146u, 90u,
- 79u, 193u, 230u, 114u,
- 109u, 100u, 109u, 155u,
- 90u, 86u, 207u, 69u,
- 11u, 130u, 84u, 1u,
- 156u, 11u, 197u, 72u,
- 46u, 138u, 165u, 117u,
- 153u, 39u, 139u, 122u,
- 146u, 227u, 98u, 120u,
- 210u, 157u, 124u, 55u,
- 146u, 63u, 85u, 1u,
- 213u, 105u, 148u, 111u,
- 144u, 176u, 82u, 69u,
- 110u, 215u, 255u, 76u,
- 125u, 165u, 125u, 119u,
- 214u, 157u, 200u, 115u,
- 123u, 85u, 63u, 15u,
- 134u, 255u, 216u, 169u,
- 222u, 212u, 174u, 203u,
- 96u, 132u, 105u, 85u,
- 140u, 208u, 166u, 170u,
- 6u, 1u, 86u, 88u,
- 136u, 131u, 77u, 168u,
- 192u, 107u, 152u, 189u,
- 129u, 255u, 79u, 123u,
- 234u, 138u, 106u, 159u,
- 85u, 65u, 107u, 73u,
- 87u, 154u, 98u, 230u,
- 125u, 192u, 1u, 152u,
- 46u, 142u, 114u, 34u,
- 194u, 77u, 61u, 159u,
- 255u, 66u, 172u, 176u,
- 120u, 144u, 102u, 234u,
- 219u, 189u, 136u, 189u,
- 206u, 83u, 6u, 178u,
- 190u, 159u, 106u, 200u,
- 120u, 148u, 162u, 132u,
- 185u, 150u, 181u, 138u,
- 255u, 112u, 167u, 127u,
- 96u, 42u, 48u, 127u,
- 170u, 199u, 79u, 1u,
- 45u, 243u, 157u, 85u,
- 110u, 151u, 37u, 187u,
- 128u, 60u, 255u, 125u,
- 92u, 97u, 127u, 192u,
- 54u, 66u, 167u, 175u,
- 14u, 92u, 96u, 70u,
- 142u, 82u, 198u, 51u,
- 118u, 92u, 1u, 168u,
- 112u, 157u, 62u, 145u,
- 104u, 123u, 83u, 45u,
- 172u, 193u, 84u, 137u,
- 115u, 121u, 31u, 97u,
- 172u, 141u, 44u, 99u,
- 115u, 18u, 79u, 0u,
- 163u, 230u, 37u, 45u,
- 201u, 39u, 180u, 108u,
- 194u, 1u, 194u, 136u,
- 96u, 99u, 66u, 220u,
- 47u, 54u, 118u, 51u,
- 207u, 216u, 214u, 105u,
- 77u, 127u, 150u, 39u,
- 167u, 184u, 0u, 204u,
- 182u, 86u, 134u, 111u,
- 121u, 169u, 109u, 89u,
- 1u, 211u, 141u, 147u,
- 71u, 139u, 127u, 124u,
- 82u, 1u, 95u, 99u,
- 180u, 141u, 128u, 151u,
- 174u, 99u, 240u, 82u,
- 189u, 96u, 125u, 210u,
- 149u, 162u, 127u, 42u,
- 162u, 124u, 133u, 99u,
- 216u, 167u, 181u, 172u,
- 100u, 1u, 2u, 212u
-};
-
-const float16 LangIdNNParams::kEmbeddingsQuantScales5[] = {
- 15345u, 15491u, 15386u, 15611u,
- 15492u, 15618u, 15408u, 15228u,
- 15182u, 15749u, 15595u, 15492u,
- 15686u, 15621u, 15466u, 15502u,
- 15399u, 15746u, 15463u, 15517u,
- 15367u, 15407u, 15445u, 15596u,
- 15464u, 15267u, 15388u, 15605u,
- 15621u, 15500u, 15559u, 15636u,
- 15676u, 15632u, 15756u, 15237u,
- 15552u, 15548u, 15674u, 15509u,
- 15502u, 15425u, 15689u, 15600u,
- 15392u, 15333u, 15617u, 15477u,
- 15283u, 15494u, 15511u, 15272u,
- 15565u, 15394u, 15696u, 15482u,
- 15569u, 15576u, 15564u, 15567u,
- 15455u, 15609u, 15527u, 15516u,
- 15496u, 15672u, 15508u, 15769u,
- 15534u, 15311u, 15465u, 15338u,
- 15532u, 15544u, 15576u, 15514u,
- 15564u, 15515u, 15549u, 15448u,
- 15514u, 15492u, 15422u, 15597u,
- 15337u, 15427u, 15620u, 15583u,
- 15380u, 15414u, 15537u, 15311u,
- 15507u, 15624u, 15508u, 15545u,
- 15431u, 15756u, 15515u, 15509u
-};
-
-const uint8 LangIdNNParams::kEmbeddingsWeights5[] = {
- 16u, 201u, 218u, 1u,
- 164u, 201u, 157u, 119u,
- 123u, 27u, 155u, 184u,
- 182u, 68u, 96u, 4u,
- 172u, 185u, 92u, 255u,
- 130u, 34u, 24u, 136u,
- 196u, 152u, 135u, 174u,
- 112u, 130u, 112u, 237u,
- 21u, 221u, 126u, 22u,
- 96u, 240u, 109u, 69u,
- 83u, 1u, 169u, 156u,
- 141u, 34u, 96u, 18u,
- 148u, 185u, 55u, 116u,
- 49u, 154u, 209u, 95u,
- 145u, 82u, 1u, 139u,
- 133u, 163u, 191u, 160u,
- 162u, 99u, 119u, 191u,
- 126u, 77u, 141u, 206u,
- 179u, 161u, 128u, 127u,
- 85u, 95u, 94u, 255u,
- 99u, 195u, 96u, 1u,
- 104u, 149u, 148u, 163u,
- 152u, 90u, 49u, 116u,
- 109u, 13u, 247u, 140u,
- 144u, 123u, 83u, 188u,
- 165u, 38u, 34u, 153u,
- 151u, 195u, 149u, 195u,
- 151u, 255u, 48u, 88u,
- 183u, 172u, 88u, 255u,
- 57u, 170u, 174u, 119u,
- 87u, 125u, 148u, 145u,
- 51u, 169u, 232u, 108u,
- 116u, 23u, 208u, 101u,
- 121u, 36u, 188u, 148u,
- 1u, 32u, 22u, 106u,
- 99u, 134u, 126u, 12u,
- 30u, 71u, 138u, 1u,
- 112u, 85u, 83u, 83u,
- 184u, 58u, 113u, 75u,
- 155u, 103u, 31u, 104u,
- 1u, 133u, 67u, 109u,
- 158u, 73u, 90u, 113u,
- 105u, 115u, 118u, 106u,
- 132u, 131u, 173u, 144u,
- 82u, 168u, 178u, 100u,
- 178u, 206u, 181u, 203u,
- 128u, 1u, 124u, 146u,
- 75u, 114u, 89u, 61u,
- 102u, 1u, 159u, 22u,
- 61u, 22u, 178u, 127u,
- 163u, 77u, 140u, 229u,
- 162u, 151u, 80u, 26u,
- 176u, 1u, 105u, 147u,
- 133u, 115u, 184u, 213u,
- 160u, 91u, 192u, 111u,
- 114u, 128u, 178u, 175u,
- 126u, 98u, 134u, 127u,
- 187u, 150u, 111u, 121u,
- 67u, 153u, 191u, 123u,
- 133u, 118u, 73u, 1u,
- 92u, 180u, 136u, 145u,
- 182u, 94u, 28u, 121u,
- 143u, 182u, 132u, 87u,
- 126u, 172u, 110u, 255u,
- 107u, 23u, 159u, 72u,
- 171u, 141u, 150u, 185u,
- 129u, 1u, 188u, 127u,
- 76u, 164u, 159u, 64u,
- 137u, 0u, 99u, 128u,
- 126u, 90u, 139u, 191u,
- 173u, 96u, 207u, 141u,
- 106u, 116u, 181u, 152u,
- 134u, 122u, 101u, 49u,
- 86u, 137u, 203u, 114u,
- 82u, 146u, 108u, 168u,
- 116u, 147u, 145u, 1u,
- 141u, 255u, 109u, 98u,
- 56u, 253u, 159u, 156u,
- 23u, 53u, 79u, 109u,
- 127u, 21u, 210u, 192u,
- 49u, 130u, 211u, 85u,
- 114u, 155u, 212u, 65u,
- 135u, 21u, 125u, 65u,
- 71u, 106u, 147u, 0u,
- 166u, 183u, 197u, 18u,
- 98u, 188u, 109u, 24u,
- 1u, 165u, 73u, 146u,
- 84u, 22u, 119u, 18u,
- 214u, 158u, 127u, 130u,
- 165u, 104u, 38u, 82u,
- 130u, 175u, 138u, 130u,
- 255u, 197u, 165u, 215u,
- 110u, 154u, 125u, 92u,
- 179u, 95u, 37u, 206u,
- 132u, 145u, 176u, 149u,
- 149u, 133u, 131u, 255u,
- 1u, 159u, 144u, 144u,
- 135u, 180u, 175u, 80u,
- 137u, 51u, 160u, 93u,
- 113u, 65u, 183u, 106u,
- 141u, 72u, 110u, 215u,
- 115u, 64u, 97u, 107u,
- 190u, 255u, 173u, 135u,
- 150u, 205u, 182u, 209u,
- 67u, 53u, 134u, 122u,
- 177u, 30u, 186u, 72u,
- 51u, 189u, 209u, 1u,
- 126u, 188u, 150u, 135u,
- 109u, 106u, 145u, 219u,
- 116u, 147u, 209u, 13u,
- 191u, 56u, 195u, 82u,
- 114u, 125u, 193u, 1u,
- 64u, 234u, 195u, 129u,
- 124u, 175u, 64u, 1u,
- 104u, 158u, 83u, 81u,
- 121u, 34u, 37u, 166u,
- 59u, 197u, 39u, 217u,
- 16u, 222u, 255u, 27u,
- 15u, 250u, 37u, 113u,
- 226u, 52u, 147u, 161u,
- 158u, 185u, 187u, 45u,
- 159u, 94u, 154u, 45u,
- 35u, 131u, 106u, 189u,
- 189u, 233u, 172u, 0u,
- 144u, 17u, 90u, 128u,
- 158u, 94u, 255u, 233u,
- 155u, 120u, 169u, 44u,
- 75u, 194u, 253u, 151u,
- 86u, 92u, 139u, 145u,
- 160u, 154u, 115u, 176u,
- 107u, 123u, 255u, 143u,
- 170u, 92u, 166u, 105u,
- 141u, 33u, 65u, 72u,
- 132u, 75u, 143u, 216u,
- 109u, 79u, 141u, 118u,
- 99u, 240u, 238u, 0u,
- 84u, 92u, 112u, 65u,
- 104u, 220u, 180u, 204u,
- 94u, 40u, 119u, 0u,
- 99u, 75u, 173u, 126u,
- 23u, 20u, 203u, 204u,
- 229u, 132u, 119u, 115u,
- 109u, 132u, 56u, 156u,
- 74u, 255u, 91u, 61u,
- 0u, 88u, 41u, 84u,
- 96u, 130u, 94u, 20u,
- 159u, 144u, 101u, 3u,
- 223u, 19u, 103u, 193u,
- 79u, 189u, 101u, 135u,
- 153u, 119u, 195u, 128u,
- 68u, 96u, 71u, 119u,
- 98u, 189u, 255u, 87u,
- 104u, 81u, 67u, 1u,
- 80u, 130u, 160u, 153u,
- 115u, 74u, 111u, 177u,
- 175u, 82u, 164u, 74u,
- 72u, 173u, 205u, 117u,
- 141u, 102u, 171u, 72u,
- 1u, 169u, 174u, 143u,
- 190u, 123u, 199u, 74u,
- 204u, 207u, 236u, 125u,
- 255u, 157u, 124u, 211u,
- 36u, 132u, 104u, 143u,
- 91u, 241u, 111u, 129u,
- 146u, 111u, 184u, 174u,
- 146u, 93u, 133u, 117u,
- 1u, 121u, 197u, 108u,
- 75u, 111u, 215u, 43u,
- 91u, 1u, 71u, 84u,
- 95u, 92u, 128u, 167u,
- 188u, 88u, 204u, 128u,
- 133u, 72u, 147u, 106u,
- 19u, 193u, 132u, 139u,
- 158u, 164u, 94u, 141u,
- 32u, 182u, 164u, 120u,
- 186u, 125u, 86u, 255u,
- 113u, 192u, 100u, 48u,
- 69u, 199u, 103u, 0u,
- 77u, 80u, 137u, 111u,
- 202u, 90u, 118u, 25u,
- 3u, 201u, 74u, 43u,
- 140u, 62u, 107u, 58u,
- 146u, 139u, 23u, 167u,
- 255u, 49u, 65u, 240u,
- 119u, 111u, 161u, 164u,
- 32u, 181u, 219u, 102u,
- 106u, 71u, 104u, 178u,
- 98u, 0u, 190u, 38u,
- 74u, 220u, 120u, 148u,
- 124u, 166u, 140u, 24u,
- 101u, 255u, 34u, 130u,
- 228u, 140u, 7u, 202u,
- 211u, 55u, 180u, 53u,
- 155u, 3u, 113u, 122u,
- 194u, 128u, 126u, 89u,
- 40u, 142u, 74u, 1u,
- 81u, 123u, 169u, 71u,
- 158u, 137u, 76u, 44u,
- 127u, 101u, 185u, 138u,
- 171u, 205u, 166u, 1u,
- 58u, 106u, 151u, 87u,
- 149u, 142u, 106u, 190u,
- 84u, 123u, 255u, 179u,
- 215u, 66u, 200u, 95u,
- 255u, 158u, 115u, 37u,
- 200u, 162u, 72u, 58u,
- 54u, 111u, 202u, 199u,
- 146u, 89u, 166u, 184u,
- 91u, 92u, 87u, 216u,
- 118u, 160u, 102u, 84u,
- 186u, 139u, 93u, 1u,
- 99u, 19u, 74u, 196u,
- 147u, 19u, 146u, 98u,
- 180u, 1u, 125u, 130u,
- 198u, 155u, 124u, 168u,
- 129u, 131u, 109u, 144u,
- 104u, 197u, 217u, 132u,
- 199u, 143u, 77u, 38u,
- 177u, 82u, 113u, 1u,
- 37u, 93u, 62u, 73u,
- 3u, 245u, 158u, 114u,
- 113u, 240u, 76u, 1u,
- 99u, 97u, 58u, 70u,
- 202u, 27u, 69u, 149u,
- 185u, 1u, 144u, 65u,
- 180u, 69u, 57u, 240u,
- 199u, 108u, 193u, 120u,
- 120u, 187u, 129u, 132u,
- 163u, 180u, 192u, 95u,
- 82u, 197u, 255u, 54u,
- 90u, 54u, 1u, 63u,
- 82u, 187u, 92u, 98u,
- 75u, 200u, 146u, 145u,
- 204u, 61u, 77u, 160u,
- 168u, 83u, 122u, 174u,
- 29u, 216u, 101u, 1u,
- 121u, 131u, 137u, 179u,
- 85u, 43u, 110u, 71u,
- 155u, 211u, 153u, 255u,
- 141u, 114u, 112u, 171u,
- 151u, 163u, 142u, 1u,
- 146u, 61u, 91u, 152u,
- 135u, 189u, 117u, 179u,
- 205u, 171u, 154u, 110u,
- 150u, 86u, 111u, 150u,
- 138u, 96u, 82u, 163u,
- 175u, 157u, 142u, 113u,
- 151u, 141u, 74u, 255u,
- 187u, 136u, 255u, 135u,
- 164u, 146u, 174u, 37u,
- 142u, 85u, 89u, 43u,
- 59u, 163u, 93u, 75u,
- 223u, 41u, 241u, 193u,
- 124u, 128u, 249u, 159u,
- 92u, 177u, 96u, 63u,
- 92u, 144u, 1u, 122u,
- 127u, 184u, 89u, 227u,
- 159u, 1u, 65u, 117u,
- 190u, 213u, 111u, 137u,
- 136u, 202u, 107u, 217u,
- 191u, 159u, 255u, 112u,
- 212u, 174u, 58u, 138u,
- 129u, 134u, 202u, 46u,
- 86u, 99u, 90u, 152u,
- 121u, 120u, 132u, 150u,
- 96u, 51u, 124u, 114u,
- 163u, 201u, 147u, 255u,
- 194u, 145u, 118u, 192u,
- 91u, 165u, 190u, 189u,
- 142u, 167u, 156u, 0u,
- 112u, 137u, 119u, 83u,
- 126u, 98u, 88u, 84u,
- 176u, 66u, 134u, 11u,
- 141u, 50u, 155u, 197u,
- 104u, 114u, 145u, 199u,
- 110u, 255u, 181u, 33u,
- 105u, 75u, 226u, 108u,
- 118u, 1u, 206u, 18u,
- 131u, 120u, 41u, 74u,
- 6u, 173u, 103u, 19u,
- 61u, 83u, 63u, 99u,
- 118u, 29u, 12u, 100u,
- 122u, 206u, 195u, 129u,
- 250u, 82u, 64u, 255u,
- 131u, 45u, 138u, 101u,
- 94u, 163u, 232u, 255u,
- 154u, 93u, 168u, 103u,
- 127u, 174u, 73u, 137u,
- 164u, 5u, 200u, 144u,
- 114u, 189u, 207u, 203u,
- 93u, 41u, 193u, 0u,
- 25u, 88u, 129u, 58u,
- 88u, 219u, 199u, 199u,
- 105u, 219u, 219u, 25u,
- 38u, 132u, 78u, 119u,
- 153u, 178u, 123u, 1u,
- 152u, 0u, 126u, 105u,
- 100u, 133u, 215u, 172u,
- 167u, 85u, 170u, 127u,
- 89u, 163u, 125u, 43u,
- 27u, 75u, 40u, 160u,
- 182u, 35u, 56u, 85u,
- 106u, 255u, 209u, 186u,
- 159u, 150u, 222u, 192u,
- 109u, 76u, 65u, 59u,
- 22u, 219u, 208u, 39u,
- 145u, 146u, 56u, 82u,
- 153u, 1u, 116u, 114u,
- 175u, 157u, 106u, 119u,
- 74u, 137u, 159u, 109u,
- 23u, 131u, 87u, 140u,
- 72u, 165u, 160u, 1u,
- 143u, 207u, 99u, 140u,
- 90u, 180u, 178u, 78u,
- 163u, 106u, 1u, 113u,
- 96u, 143u, 146u, 181u,
- 156u, 196u, 145u, 247u,
- 169u, 147u, 188u, 180u,
- 19u, 255u, 175u, 156u,
- 172u, 227u, 210u, 248u,
- 99u, 141u, 105u, 211u,
- 131u, 140u, 70u, 134u,
- 182u, 173u, 112u, 125u,
- 126u, 122u, 20u, 255u,
- 60u, 125u, 90u, 178u,
- 96u, 163u, 67u, 80u,
- 105u, 154u, 156u, 1u,
- 146u, 112u, 150u, 230u,
- 48u, 62u, 109u, 1u,
- 152u, 113u, 117u, 85u,
- 101u, 155u, 168u, 77u,
- 242u, 110u, 201u, 136u,
- 137u, 77u, 103u, 101u,
- 144u, 137u, 219u, 222u,
- 94u, 125u, 156u, 80u,
- 95u, 160u, 255u, 139u,
- 70u, 221u, 131u, 42u,
- 151u, 123u, 68u, 73u,
- 134u, 191u, 71u, 123u,
- 255u, 87u, 49u, 202u,
- 63u, 1u, 78u, 221u,
- 159u, 47u, 163u, 158u,
- 112u, 219u, 169u, 82u,
- 163u, 226u, 154u, 97u,
- 104u, 206u, 237u, 6u,
- 210u, 122u, 118u, 245u,
- 41u, 65u, 99u, 255u,
- 63u, 210u, 131u, 113u,
- 117u, 146u, 52u, 53u,
- 42u, 225u, 181u, 98u,
- 183u, 1u, 9u, 29u,
- 99u, 104u, 160u, 155u,
- 51u, 27u, 115u, 255u,
- 140u, 70u, 176u, 61u,
- 213u, 19u, 233u, 186u,
- 122u, 87u, 179u, 60u,
- 1u, 163u, 54u, 74u,
- 134u, 154u, 72u, 30u,
- 133u, 174u, 89u, 49u,
- 241u, 52u, 100u, 172u,
- 112u, 220u, 150u, 177u,
- 169u, 87u, 57u, 172u,
- 118u, 184u, 205u, 255u,
- 169u, 155u, 164u, 192u,
- 144u, 52u, 192u, 98u,
- 69u, 57u, 162u, 160u,
- 255u, 179u, 118u, 185u,
- 28u, 86u, 70u, 108u,
- 92u, 255u, 114u, 145u,
- 118u, 78u, 108u, 34u,
- 135u, 164u, 86u, 189u,
- 156u, 167u, 104u, 165u,
- 110u, 73u, 101u, 152u,
- 182u, 104u, 224u, 242u,
- 109u, 140u, 141u, 90u,
- 87u, 212u, 255u, 193u,
- 124u, 142u, 175u, 73u,
- 109u, 160u, 204u, 96u,
- 56u, 75u, 87u, 157u,
- 101u, 127u, 200u, 1u,
- 108u, 122u, 159u, 81u,
- 181u, 129u, 47u, 255u,
- 115u, 118u, 228u, 165u,
- 143u, 114u, 149u, 131u,
- 194u, 179u, 27u, 210u,
- 134u, 142u, 34u, 206u,
- 178u, 168u, 115u, 188u,
- 227u, 176u, 57u, 255u,
- 114u, 186u, 145u, 112u,
- 125u, 114u, 102u, 18u,
- 93u, 255u, 44u, 122u,
- 165u, 113u, 32u, 155u,
- 98u, 193u, 87u, 33u,
- 181u, 1u, 8u, 124u,
- 211u, 200u, 132u, 233u,
- 178u, 240u, 99u, 222u,
- 163u, 117u, 255u, 121u,
- 203u, 190u, 203u, 128u,
- 68u, 79u, 147u, 152u,
- 126u, 207u, 164u, 43u
-};
-
-const int LangIdNNParams::kHiddenNumRows[] = {80};
-
-const int LangIdNNParams::kHiddenNumCols[] = {208};
-
-const float LangIdNNParams::kHiddenWeights0[] = {
- 0.0055438327f, 0.006121323f, -0.6130986f, 0.011358412f,
- -0.24904737f, 0.0013105752f, 0.049118876f, 0.024627045f,
- 0.0044371486f, 0.1878761f, -0.0009123937f, 0.017067833f,
- -0.013430343f, 0.0021840474f, 0.17912087f, -0.024405085f,
- 0.029278088f, -0.0018431976f, 0.008366278f, 0.010326646f,
- 0.0007790954f, 0.009340239f, -0.26540864f, 0.0019623924f,
- -0.1374129f, -0.009155667f, -0.006172319f, -0.045014728f,
- -0.0791986f, 0.22250272f, 0.01093374f, 0.0098887505f,
- 0.0198656f, 0.030331021f, 0.01861249f, 0.009383037f,
- 0.013152254f, -0.014789522f, -0.004870267f, 0.0060533285f,
- -0.061748058f, 0.002460513f, 0.054705523f, 0.010801623f,
- -0.06588886f, -0.0011319848f, -0.01548539f, 0.013585477f,
- 0.0023100239f, 0.015127559f, -0.012442267f, -0.036515363f,
- 0.0066132625f, 0.0011073126f, 0.0048063495f, -0.00855078f,
- -0.15588433f, -0.05817704f, -0.07539406f, 0.040960014f,
- -0.0014563288f, -2.9055054e-05f, -0.008036686f, 0.30515048f,
- 0.01708528f, -0.15042636f, 0.09590111f, 0.009323509f,
- 0.04424292f, -0.0035161893f, 0.0043498203f, -0.0031112984f,
- 0.11581452f, 0.0062541557f, 0.03819449f, -0.0027044753f,
- 0.009228842f, 0.02719591f, 6.526655e-05f, -0.004026002f,
- 0.0020858014f, 0.030755911f, 0.01903594f, -0.0002764487f,
- 0.003162601f, 0.034881573f, 0.021350997f, 0.0015064531f,
- -0.0068919216f, -0.220686f, 0.032344546f, -0.00096531044f,
- 0.036135115f, 0.0056493953f, 0.012495903f, -0.036851387f,
- 0.0052843085f, -0.20660809f, 0.09673514f, -0.0459264f,
- -0.19556762f, 0.007981701f, -0.094217755f, 0.010938255f,
- 0.0029916451f, 0.0022379237f, -0.045892276f, -0.0020711306f,
- 0.008314466f, 0.004206805f, 0.028373208f, 0.010115378f,
- 0.0154351f, 0.010618946f, -0.031164907f, 0.022835521f,
- -0.12017471f, 0.029761272f, 0.057312936f, -0.0116307475f,
- -0.06874991f, -0.0031616616f, 0.15407008f, 0.010456005f,
- 0.012282399f, 0.0028137164f, 0.016210806f, -0.0022362277f,
- -0.06402911f, -0.026422618f, 0.0042830454f, 0.007601109f,
- -0.01905496f, -0.0027831143f, -0.0015240601f, -0.032905113f,
- -0.004927879f, 0.013781159f, 0.00097190175f, 0.37954146f,
- -0.007538219f, 0.24256834f, -0.04891233f, 0.0014381834f,
- 0.012229447f, -6.131202e-05f, 0.0035957564f, 0.04779286f,
- -0.031743206f, 0.004844833f, -0.025012035f, 0.013232069f,
- 0.0061633796f, -0.4497885f, 0.001826926f, 0.01742167f,
- 0.09605109f, 0.005904355f, -0.14243735f, -0.106969945f,
- 0.0008715465f, -0.031494454f, -0.00019970644f, 0.0041882508f,
- -0.030810824f, 0.0092503335f, -0.003973055f, 0.0043617426f,
- -0.0014272921f, 0.002685691f, -0.19498438f, -0.05858236f,
- -0.05367205f, -0.0020967787f, -9.363355e-05f, -0.0074316985f,
- 0.010548169f, 0.020454785f, -0.06165393f, -0.027417442f,
- 0.0067889104f, -0.052229866f, -0.084573224f, -0.0032624674f,
- -0.1095487f, 0.0018077974f, 0.004212426f, -0.057578925f,
- 0.001400686f, 0.0071150707f, 0.044791f, 0.015976004f,
- -0.24658069f, -0.019906001f, -0.03952184f, -0.0026615015f,
- 0.01209705f, 0.15344182f, -0.0008354965f, 0.029792393f,
- -0.0051114634f, -0.006969946f, -0.04807466f, 0.010284299f,
- 0.008203293f, -0.005593931f, 0.036034364f, 0.014091173f,
- 0.025440425f, 0.011691974f, 0.22875144f, 0.0077962046f,
- 0.09931652f, 0.010335041f, -0.04887764f, 0.06991758f,
- 0.028346287f, -0.1568082f, -0.01633638f, -0.00074138865f,
- -0.005661694f, -0.009570243f, 0.16051465f, 0.0055266214f,
- 0.06392003f, -0.016097832f, 0.0019397525f, 0.033166483f,
- 0.0020371557f, 0.01936814f, 0.26557335f, 0.0017102716f,
- -0.17524391f, -0.008141556f, -0.012666238f, 0.036791492f,
- -0.07125565f, -0.10536201f, -0.01541879f, 0.030466659f,
- 0.014526148f, -0.1308191f, 0.04911432f, -0.0036254772f,
- 0.017555458f, -0.009292092f, 0.008073721f, 0.0050214357f,
- -0.07562362f, -0.009486691f, -0.12601969f, 0.0035293323f,
- -0.18424663f, 0.046252456f, -0.056168962f, -0.025184115f,
- 0.053047575f, -0.019543735f, 0.048770413f, 0.021018691f,
- -0.011055255f, 0.0012675355f, 0.009644285f, -0.00080474094f,
- -0.04611168f, -0.057724755f, 0.019683676f, 0.02260603f,
- 0.0014054867f, -0.005527405f, -0.014988076f, 0.3115694f,
- -0.0023986932f, -0.13515158f, 0.07987137f, 0.0125136785f,
- -0.012152583f, -0.0025880842f, 0.00042009912f, -0.009727714f,
- 0.17593612f, -0.01712744f, 0.04644306f, 0.010049346f,
- 0.00792393f, -0.44661683f, -0.018038817f, -0.0261866f,
- -0.00041062958f, -0.10899811f, 0.04204847f, -0.020531822f,
- -0.001772331f, 0.058540247f, -0.058951292f, 0.0668488f,
- -0.016538458f, -0.14214537f, -0.025331464f, -0.0038897826f,
- 0.014789399f, 0.01862716f, 0.026914597f, -0.288806f,
- 0.0057862564f, 0.019008687f, -0.33104867f, 0.095154814f,
- 0.10551452f, 0.01660164f, 0.17406175f, -0.011021057f,
- -0.018099666f, 0.00018472507f, 0.13515553f, -0.008720724f,
- -0.011899676f, 0.02305671f, 0.0022345888f, -0.0045586303f,
- -0.012631391f, 0.022891335f, 0.1213485f, 0.06132337f,
- -0.040417973f, -0.013348546f, -0.054895062f, 0.0061546685f,
- -0.020349247f, -0.014724794f, -0.28968993f, -0.0032419146f,
- 0.0182386f, 0.008810574f, -0.011622318f, -0.0064354977f,
- 0.08087625f, -0.013807721f, -0.020827662f, 0.009258346f,
- -0.011345245f, -0.004159414f, -0.0003167899f, 0.0031197788f,
- -0.002272455f, -0.00041689927f, 0.021955583f, 0.2940003f,
- -0.006763404f, 0.030792283f, -0.029734768f, 0.001219185f,
- 0.0011985662f, -0.026900306f, 4.604991e-05f, 0.24964073f,
- -0.05888491f, 0.0224196f, -0.006709592f, -0.0057738936f,
- 0.028916467f, -0.24573748f, 0.019534716f, 0.05793403f,
- -0.17847644f, -0.003144348f, -0.11462238f, -0.2869773f,
- -0.0075337873f, -0.102883816f, -0.029716806f, 0.0069114924f,
- 0.041947905f, -0.0045164498f, -0.038533762f, -0.06607847f,
- -0.0027511907f, 0.02819647f, 0.006130282f, 0.065081224f,
- -0.067661315f, 0.0011542395f, -0.00096501264f, -0.0011097055f,
- 0.00710727f, 0.04819025f, 0.046788227f, 0.14584209f,
- -0.0021500578f, 0.052902013f, 0.031577066f, -0.00088431034f,
- -0.017364733f, -0.006599756f, -0.017440775f, -0.044069167f,
- -0.00082908996f, 0.013839106f, 0.05568766f, 0.017626228f,
- -0.038839303f, -0.014157442f, -0.014094078f, -0.005645087f,
- 0.00889389f, -0.34182253f, -0.004129997f, 0.0010649742f,
- -0.003994457f, 0.015435729f, -0.057376757f, -0.0078734495f,
- 0.025758866f, 0.0077668587f, 0.08443512f, -0.0087169865f,
- -0.010646654f, 0.014710016f, 0.26692545f, -0.0036403937f,
- 0.12547399f, -0.00785795f, -0.008018144f, -0.012236925f,
- -0.023003425f, -0.007457364f, -0.0075452896f, 0.014465333f,
- -0.13428602f, -0.025485318f, -0.07072867f, 0.013699107f,
- -0.04991588f, -0.0037046883f, 0.0040668254f, 0.0057441965f,
- 0.0045345305f, -0.009402122f, 0.10669224f, -0.0013956747f,
- 0.12841064f, -5.4712913e-05f, -0.002746859f, 0.019387443f,
- -0.20354253f, 0.04283828f, -0.021156115f, -0.01374572f,
- -0.023761118f, -0.03224195f, 0.0010605513f, -0.0061359517f,
- -0.010842123f, -0.032693196f, 0.0016928436f, -0.012999403f,
- -0.044672854f, 0.0021749812f, -0.101816684f, -0.013118214f,
- -0.17108053f, -0.019801812f, -0.026577683f, 0.01585304f,
- 0.011029184f, 0.026128389f, -0.00079824554f, -0.14265795f,
- -0.004280624f, -0.0031539593f, 0.008145832f, -0.3008097f,
- -0.046745878f, -0.16013521f, 0.060263623f, -0.043916855f,
- -0.0021772445f, 0.002396182f, -0.0052376883f, 0.0026859469f,
- -0.0064182077f, -0.10041129f, -0.066425584f, 0.0057354895f,
- -0.0092000635f, -0.004561931f, 0.0055908463f, 0.023924518f,
- 0.04645522f, 0.0047485894f, -0.012308861f, -0.0061037503f,
- 0.0018759472f, 0.05256515f, -0.0051931543f, -0.026874125f,
- -0.0029565585f, 0.28140047f, -0.036170516f, -0.015987003f,
- -0.005008949f, 0.029167479f, 0.06486878f, 0.011649322f,
- 0.0048009423f, -0.06172381f, 0.021186048f, 0.002081344f,
- 0.035827037f, 0.009022272f, -0.037609667f, -0.11577567f,
- -0.016729027f, 0.017031748f, 0.271903f, -0.021213574f,
- -0.00027915623f, 0.008530332f, 0.04854837f, 0.0018896415f,
- -0.0029518495f, -0.0024801085f, -0.24750835f, 0.00020527051f,
- -0.003626586f, -0.014191836f, -0.0040737595f, 0.01234723f,
- 0.004910169f, -0.0134741245f, 0.015649825f, -0.011172739f,
- 0.27675354f, 0.055099588f, 0.06052011f, 0.00361583f,
- 0.032975294f, -0.0018268999f, 0.021037493f, 0.004011109f,
- -0.0038727715f, 0.0033930957f, -0.016723791f, -0.008844552f,
- -0.036812644f, -0.0048693027f, 0.033951275f, 0.002413584f,
- 0.004048765f, -0.002131823f, 0.00034507597f, 0.016772058f,
- -0.0009882435f, 0.015382035f, -0.019767886f, 0.35756364f,
- 0.0018205543f, 0.10418363f, 0.013071072f, 0.0025029215f,
- 0.0012110391f, -0.004799309f, 0.006600619f, 0.2542326f,
- 0.008353529f, -0.00072054786f, -0.026339116f, 0.020340167f,
- -0.018623803f, -0.009017177f, -0.0047154175f, 0.18302369f,
- -0.28711015f, -0.0010119247f, -0.07905169f, 0.48688665f,
- 0.004776477f, 0.004793285f, 0.029375648f, -0.0017348857f,
- 0.043913238f, 0.009119298f, -0.007751698f, -0.052779745f,
- -0.00047313792f, -0.010235697f, 0.19207507f, 0.0744669f,
- -0.0027792454f, -0.0071423333f, -0.00019004934f, 0.026022613f,
- 0.012333517f, -0.029118512f, -0.109466374f, -0.20837292f,
- -0.017251892f, 0.041166153f, -0.01470998f, -0.0014326181f,
- 0.012604199f, 0.016383111f, -0.031545952f, -0.10653464f,
- 0.004234108f, 0.0026454267f, -0.024333242f, -0.053684406f,
- -0.08468923f, 0.0052721477f, 0.23863518f, 0.0055177244f,
- 0.0015463284f, 0.12244364f, 0.0012953874f, 0.011592855f,
- 0.004271294f, -0.023230975f, -0.03991712f, 0.017901007f,
- -0.02164662f, 0.0043782415f, 0.07525769f, 0.00211061f,
- 0.009522794f, 0.009955519f, -0.06855509f, 0.01777404f,
- 0.060447033f, 0.020717144f, 0.003848966f, 0.012222441f,
- 0.020488182f, -0.21534117f, 0.007761015f, 0.0104436865f,
- 0.018402008f, 0.008580181f, -0.34554425f, 0.029562525f,
- 0.01447637f, 2.9635532e-05f, 0.0052230693f, 0.013866713f,
- 0.0031341005f, -0.002982263f, 0.102144815f, 3.3002452e-05f,
- 0.22694622f, 0.041244574f, 0.004535295f, 0.038811527f,
- 0.29727608f, -0.38288838f, 0.0144491615f, 0.001430447f,
- -0.015487341f, 0.10725863f, 0.02489245f, 0.011276117f,
- 0.052727584f, 0.0007073286f, 0.0015961506f, -0.00069692184f,
- -0.05512769f, 0.02487039f, -0.14931394f, 0.0038857583f,
- -0.115273006f, 0.011226952f, 0.053854506f, 0.046316344f,
- 0.037712272f, 0.021349065f, 0.03911525f, 0.07261281f,
- 0.003053824f, -0.0018666574f, 0.0016394934f, 0.25381097f,
- 0.22642186f, -0.016559875f, 0.03327549f, -0.001108491f,
- 0.0011012153f, -0.0002143856f, 0.024184255f, -0.31116974f,
- 0.009539603f, -0.051876515f, -0.04169711f, 0.0076688603f,
- 0.03639722f, 0.001169193f, 0.0069029504f, 0.032856736f,
- 0.32984143f, 0.006242301f, 0.014043269f, -0.0010220681f,
- -0.0035474673f, 0.2243721f, 0.030613666f, 0.048067458f,
- -0.002115086f, -0.12813306f, -0.009609685f, 0.032716595f,
- 0.0016441629f, 0.05569492f, 0.054189265f, 0.04720799f,
- 0.03896892f, 0.06959964f, 0.02653023f, -0.0011579007f,
- 0.045615163f, 0.021720769f, 0.0037299283f, -0.02552412f,
- 0.0063135154f, 0.027984383f, 0.036793675f, -0.030336183f,
- 0.22654374f, 0.009598657f, 0.07228554f, 0.006091316f,
- 0.014765914f, -0.0014610458f, 0.07505419f, 0.0010566065f,
- -0.011894424f, -0.007239693f, -0.022713514f, 0.013045112f,
- 0.032192186f, 0.0041472344f, 0.029682716f, 0.0062230676f,
- 0.044676878f, 0.01751557f, -0.0010204847f, -0.0006833903f,
- 0.06337842f, -0.0001224741f, -0.14377995f, 0.0032627683f,
- 0.0041261036f, 0.007243585f, -0.005074503f, 0.0011899507f,
- -0.04950547f, 0.025883056f, -0.0013257879f, -0.002422245f,
- 0.012040607f, -0.0011370071f, -0.00034068784f, -0.0022763815f,
- -0.00090205984f, 0.013679832f, 0.011781621f, 0.21043818f,
- 0.0011080168f, 0.13092478f, 0.009376598f, 0.0014659724f,
- 0.004600854f, 0.02348321f, 0.0048815575f, -0.06405563f,
- 0.041178312f, 0.009015415f, -0.0001274563f, 0.0103720315f,
- 0.0017310856f, -0.09543433f, -0.0020198317f, -0.24044976f,
- 0.061626524f, 0.00693575f, 0.014844393f, 0.26264238f,
- 0.0036561475f, 0.032547362f, 0.018976696f, 0.0028236038f,
- 0.038300093f, -0.016552867f, 0.020858197f, 0.036009956f,
- 0.0013492481f, -0.012542278f, 0.17004775f, 0.09815279f,
- 0.069597736f, 0.021304807f, 0.0036809538f, 0.020387648f,
- 0.0027159865f, -0.017258644f, -0.21998797f, 0.031211786f,
- 0.010181579f, 0.12038349f, -0.016177183f, 2.3821125e-05f,
- -0.05010594f, 0.0029280004f, 0.0028548f, -0.029591667f,
- -0.00082215696f, 0.010560293f, 0.09952369f, -0.008306438f,
- 0.122285545f, 0.0021733968f, -0.047473837f, 0.0010913584f,
- 0.0013969231f, 0.18123387f, -0.001695146f, 0.03856581f,
- 0.00018555862f, 0.019944394f, 0.055140093f, 0.0066546053f,
- -0.0012280842f, -0.0035089573f, 0.12299846f, -0.011583998f,
- 0.015687926f, 0.018771496f, 0.09121631f, 0.011726651f,
- -0.3415604f, 0.009834352f, -0.008968053f, 0.028070997f,
- 0.037398256f, -0.20600373f, 0.007852086f, 0.016998544f,
- 0.068206936f, 0.008439249f, -0.0045025316f, -0.023583353f,
- -0.0005695698f, -0.004809391f, 0.006322107f, 0.013592706f,
- 0.012301552f, 0.007781827f, -0.074910656f, 0.0034196367f,
- 0.0886728f, 0.019198144f, 0.0019104021f, 0.04561018f,
- -0.14348222f, -0.17197733f, -0.002690504f, 0.0031934287f,
- 0.041876413f, -0.043491606f, 0.015308039f, 0.00537615f,
- 0.020553451f, -0.019865412f, 0.00041374267f, 0.006573813f,
- 0.052993033f, -0.00163323f, 0.0441257f, 0.012503601f,
- -0.19757655f, 0.051763818f, 0.05226168f, 0.021073394f,
- 0.045336723f, 0.016596947f, 0.022277713f, -0.05093642f,
- 0.003969471f, 0.0052919285f, 0.010997635f, 0.08150889f,
- -0.17213131f, 0.064788364f, -0.0556453f, 0.058084134f,
- 0.0017828115f, -0.0017725978f, 0.037026893f, -0.15272397f,
- 0.008442053f, -0.15885375f, 0.055777766f, 0.02091623f,
- 0.0040216125f, 0.0064139892f, -0.0017552935f, -0.03886535f,
- -0.06509005f, -0.010478659f, 0.025686849f, 0.007960161f,
- 0.0020484761f, -0.4615201f, 0.015585915f, -0.034009226f,
- 0.0059234644f, -0.2662679f, 0.033967126f, -0.02458608f,
- 0.003140815f, 0.038181093f, 0.09910824f, 0.0452179f,
- 0.0011101087f, -0.019728502f, -0.01779242f, -0.00011132655f,
- -0.0007249738f, 0.023445945f, 0.020889504f, -0.30222708f,
- 0.016371334f, -0.11166242f, -0.0024893985f, 0.08531613f,
- 0.029904353f, 0.013565008f, -0.026126046f, 0.00090050296f,
- 0.003929063f, 0.005701322f, -0.06181187f, 3.2569133e-05f,
- -0.0025217256f, 0.0052204076f, 0.01834912f, 0.020104144f,
- 0.018017123f, 0.004313703f, -0.04571334f, 0.034729518f,
- -0.08869013f, -0.024686165f, 0.03229027f, -0.0007223545f,
- -0.038628064f, -0.004068548f, 0.21237212f, -0.0006159212f,
- -0.0040773656f, 0.018236615f, 0.004616888f, 0.0045675384f,
- -0.22630164f, 0.005028187f, 0.043263823f, 0.0043929825f,
- 0.008404703f, 0.0014006027f, 0.0036091853f, 0.041411933f,
- 0.0010605333f, 0.014862628f, -0.005477582f, 0.109028f,
- 0.00062737265f, 0.1989594f, -0.004502329f, 0.005164968f,
- 0.0058290143f, 0.017733814f, 0.00093469745f, -0.075581506f,
- 0.011161983f, 0.00947858f, 0.0061076656f, 0.01313311f,
- 0.020679062f, 0.23775038f, 0.0012848104f, -0.15623039f,
- 0.17759638f, -0.00058967306f, 0.013840144f, 0.43633148f,
- 0.0066989856f, -0.030210605f, 0.10965444f, 0.0018922101f,
- 0.031724956f, 0.008829292f, 0.0010297938f, -0.018649796f,
- 0.0025210208f, 0.029587662f, -0.009414756f, 0.035032403f,
- -0.024229445f, 0.025130868f, -0.0042342176f, -0.024290549f,
- 0.0030654562f, 0.003784227f, 0.107903615f, 0.08018437f,
- 0.01468227f, 0.049681906f, -0.063488625f, 0.00063991145f,
- -0.36038196f, 0.0040912456f, 0.021906478f, 0.08981686f,
- -0.00079598645f, -0.0015893892f, -0.040067166f, 0.03988621f,
- 0.02914674f, 0.011588454f, -0.04991918f, -0.0020628572f,
- -0.002989789f, -0.20788868f, 0.00013578744f, 0.014771804f,
- -0.0026381484f, 0.039701227f, 0.0124620665f, 0.006164932f,
- 0.021655774f, 0.011749069f, -0.0893305f, 0.009843379f,
- 0.010568396f, 0.02545125f, 0.08536679f, 0.043717057f,
- 0.028438495f, 0.025641493f, 0.030633103f, 0.011526527f,
- 0.020211188f, -0.046976753f, 0.0014591482f, 0.02407188f,
- -0.027057413f, 0.019729732f, 0.018737612f, 0.059645474f,
- 0.07585192f, -6.297434e-05f, 0.004969191f, 0.01767422f,
- -0.0040772217f, 0.015669344f, 0.11507133f, -0.0025411837f,
- 0.0104911355f, 0.026532413f, 0.0026865373f, -0.023776121f,
- 0.2331885f, -0.22464971f, 0.038966622f, 0.025192821f,
- -0.03662851f, -0.113928884f, 0.03281119f, 0.010676447f,
- 0.072130404f, 0.06666872f, -0.00039114946f, 0.002769662f,
- -0.08648446f, 0.00836028f, -0.06701798f, 0.009591303f,
- 0.36451566f, -0.0057284757f, 0.11541523f, 0.013092721f,
- 0.033504248f, 0.04801747f, 0.057911895f, -0.01754153f,
- 0.002184714f, -0.007971618f, 0.01480725f, -0.036110654f,
- 0.0045352103f, -0.025177637f, 0.010407808f, -0.13461687f,
- 0.0011076726f, -0.0011258988f, -0.013623482f, 0.07592421f,
- 0.023446893f, 0.040728644f, 0.11734141f, 0.021975536f,
- 0.008107446f, -0.0007643744f, 0.01144556f, 0.011739364f,
- -0.4672068f, -0.0026461747f, 0.005961507f, 0.011720536f,
- 0.013395916f, -0.014140453f, -0.05013367f, 0.01598248f,
- -0.004964306f, 0.12591034f, 0.009356985f, -0.0050785905f,
- 0.0010016494f, -0.025931112f, 0.067348324f, 0.008783509f,
- 0.0062956074f, -0.036777046f, -0.03758303f, -0.0024304427f,
- -0.019002007f, 0.019574571f, -0.021014148f, -0.18268879f,
- 0.0022638766f, 0.040850457f, 0.29637992f, -0.08498703f,
- 0.039108656f, 0.018348478f, -0.019140236f, 0.0029306046f,
- -0.0006431206f, -0.0033881122f, -0.022727616f, 0.0027676101f,
- -0.0073477374f, 0.010350267f, 0.014408288f, 0.017864153f,
- -0.011395327f, 0.014933158f, 0.15913868f, 0.014899703f,
- 0.29356295f, -0.019076342f, 0.056755815f, 0.002465675f,
- -0.04259399f, -0.00012736165f, 0.19112737f, 0.004924544f,
- 0.044536296f, 0.01911576f, 0.00061093783f, 0.0011209893f,
- 0.006569453f, -0.03046558f, 0.026578475f, 0.0073164757f,
- 0.0147804f, -0.005772978f, -0.0029004319f, -0.08115301f,
- -0.0028729201f, 0.043115206f, 0.024103802f, 0.0019794537f,
- 0.00083721377f, -0.10243097f, 0.020588944f, -0.0050025736f,
- 0.008154325f, 0.010934032f, 0.010697303f, 0.15688518f,
- 0.025735848f, 0.024750208f, 0.104750216f, 0.03565516f,
- 0.011893833f, -0.36245322f, 0.013522484f, 0.2310177f,
- 0.029186657f, 0.0023262955f, -0.068443716f, -0.016954226f,
- 0.005637373f, 0.018455643f, 0.0077792234f, -0.003062113f,
- 0.006966892f, -0.020990234f, 0.047267597f, 0.04710746f,
- -0.0013891717f, 0.0035703452f, 0.19402291f, 0.039520755f,
- -0.04861703f, 0.0111257f, 0.0058842995f, 0.0033863161f,
- 0.010452838f, 0.029582199f, -0.25934544f, 0.15250856f,
- -0.0022174285f, 0.021304717f, 0.17600337f, -0.001112675f,
- -0.12197272f, 0.008861832f, 0.0071323416f, -0.02618871f,
- 0.0034299102f, 0.036422025f, -0.031071214f, 0.09945338f,
- 0.009251178f, -0.0020370046f, -0.009111923f, 0.00059596304f,
- 0.008239433f, -0.32097793f, -0.0020217346f, -0.04076957f,
- -0.0027270808f, 0.022222372f, -0.050826658f, 0.03637126f,
- 0.008641761f, 0.001286624f, 0.014240577f, 0.0028792315f,
- -0.011539815f, -0.014385555f, -0.035352256f, -0.016223839f,
- -0.11768992f, -0.022056533f, 0.041691534f, 0.01160857f,
- -0.031121463f, -0.32734764f, -0.031493854f, -0.0152580775f,
- -0.060165036f, 0.013924374f, 0.06562177f, 0.11039683f,
- 0.008289077f, -0.0027928308f, -0.00024879884f, -0.011809153f,
- -0.007886081f, -0.00046337236f, 0.5638149f, -0.00025007376f,
- 0.042416614f, -0.019957792f, -0.0024369778f, -0.057818413f,
- 0.099883236f, 0.17348632f, 0.044963032f, -0.006720513f,
- -0.052010186f, -0.02516501f, -0.016847184f, -0.02039234f,
- -0.009739846f, -0.06844899f, -0.0030014545f, -0.014372732f,
- -0.2429584f, -0.019237094f, 0.19049929f, -0.020168813f,
- -0.042575613f, -0.023455735f, 0.018473597f, -0.002881152f,
- -0.08454501f, -0.020226132f, 0.007279427f, -0.049155883f,
- -0.020978939f, -0.002022347f, -0.003788436f, -0.14114325f,
- -0.055853773f, 0.09407219f, 0.18103299f, 0.116307005f,
- -0.000582794f, -0.0007202879f, 0.040766478f, 0.061509114f,
- -0.025218252f, -0.027126055f, -0.05340474f, -0.011533095f,
- -0.024390474f, -0.016272873f, 0.003039938f, -0.005205575f,
- 0.027200775f, -0.010470155f, -0.116454184f, -0.0071571753f,
- -0.0056951405f, -0.14530429f, 0.053701945f, 0.011986134f,
- 0.0013266753f, 0.1884966f, -0.0035678027f, 0.013641822f,
- -0.009222335f, -0.010095587f, 0.052604992f, 0.07454713f,
- -0.015304458f, -0.046810962f, -0.019794282f, -0.00080863124f,
- -0.0033532416f, -0.014197509f, -0.033896286f, 0.2746057f,
- -0.017833754f, 0.33931363f, -0.061897323f, -0.12158852f,
- 0.08737015f, -0.006661756f, -0.22530344f, 7.3053656e-05f,
- -0.030040268f, -0.00055805634f, -0.120588f, -0.0025378691f,
- -0.019193202f, -0.014509601f, -0.041489262f, -0.008209616f,
- 0.0033181563f, -0.020225447f, -0.034180555f, -0.0077521447f,
- -0.22279409f, -0.08407787f, 0.016583882f, -0.00040549386f,
- -0.030035926f, -0.00043019798f, 0.012293189f, -0.0042476146f,
- -0.02798459f, -0.008498254f, -0.03381177f, -0.009001631f,
- 0.32899642f, 0.015733426f, -0.005605088f, 0.002005357f,
- -0.018533928f, 0.00074450346f, 0.001974818f, -0.09243045f,
- 0.0023962061f, -0.026414843f, -0.024036756f, 0.051456943f,
- -0.001196855f, -0.03669522f, -0.018951042f, 0.00011140342f,
- -0.0021896749f, -0.035374124f, -0.0131047815f, -0.36442003f,
- 0.018098269f, -0.0041416422f, -0.106250025f, -0.023565685f,
- -0.008622312f, -0.0015185397f, -0.002162187f, -0.086006984f,
- 0.10100149f, 0.006048211f, -0.13810113f, 0.13008197f,
- -0.010745371f, 0.12613007f, -0.02691129f, 0.005238015f,
- -0.06801618f, -0.02568198f, 0.027843969f, 0.07888495f,
- 0.0021010654f, -0.029550632f, 0.102314726f, -0.052254178f,
- -0.023466656f, -0.018888813f, 0.004438389f, -0.011091543f,
- 0.0044954694f, -0.017061194f, -0.3008647f, -0.09155152f,
- -0.022349536f, -0.03853637f, -0.008732484f, 0.0041466295f,
- -0.10271876f, -0.008593511f, -0.027208773f, -0.054539748f,
- 0.008277072f, -0.023362339f, -0.028650168f, 0.015508391f,
- 0.35639936f, -0.02970485f, 0.015161947f, 0.009491994f,
- -0.0052870153f, -0.041782986f, -0.0003273378f, -0.0041983025f,
- -0.002000983f, -0.023456685f, 0.026191631f, -0.020423526f,
- -0.0041606794f, -0.0071394243f, -0.03626684f, -0.016933136f,
- -0.021405842f, -0.022184137f, 0.06716153f, -0.0021676975f,
- 0.16027337f, -0.018046215f, 0.0048691067f, -0.02656958f,
- -0.043552272f, 0.19820434f, -0.005725016f, -0.032597482f,
- 0.030142209f, -0.011292162f, 0.34753957f, 0.05317901f,
- -0.066725545f, 0.006710906f, -0.0063962513f, -0.033602286f,
- 0.004691726f, -0.012567064f, -0.19131628f, 0.0015118126f,
- 0.2142634f, -0.030962374f, 0.006367109f, 0.009616747f,
- 0.36870342f, 0.013673955f, -0.025048075f, 0.0024863856f,
- -0.027900359f, -0.096346915f, -0.063942865f, -0.0166664f,
- 9.996081e-05f, 0.03695742f, -0.0028750028f, -0.005458922f,
- 0.3425955f, -0.009360694f, -0.023586927f, -0.009005178f,
- 0.16391318f, -0.037856758f, -0.06768929f, 0.024520053f,
- -0.003878979f, 0.01079353f, -0.037120115f, 0.033296105f,
- -0.008126617f, -0.0027290753f, -0.020173673f, 0.059590757f,
- -0.0034346266f, -0.29631525f, -0.18914631f, -0.040235657f,
- -0.0036628991f, 0.0026090525f, -0.016358446f, 0.070820175f,
- -0.010934736f, 0.23331998f, 0.013214279f, -0.02054653f,
- 0.034521908f, 0.0017998507f, -0.0052237622f, 0.044568073f,
- 0.2750569f, -0.0037395863f, 0.15615188f, 0.011733074f,
- -0.00956714f, -0.20695524f, 0.044071272f, -0.025634f,
- 0.0029599923f, -0.085988f, -0.033481274f, 0.022933433f,
- -0.004990859f, 0.009430861f, 0.0041018445f, -0.03850177f,
- -0.0418263f, 0.096553445f, -0.007508842f, 0.004283901f,
- 0.007265918f, -0.04605026f, 0.0001495192f, 0.017864851f,
- -0.008523763f, -0.11312352f, -0.06936849f, -0.0098722195f,
- 0.26925185f, -0.014923316f, -0.13164319f, -0.012201473f,
- -0.012923124f, -0.0022432602f, -0.14915244f, -0.0006044739f,
- -0.0011460102f, -0.01154513f, 0.0076572844f, -0.03434836f,
- 0.034365244f, 0.0056453366f, -0.09873471f, -0.035139132f,
- -0.061591968f, 0.03046015f, 0.050698545f, 0.00848834f,
- 0.10851464f, 0.0052149612f, 0.10399892f, -0.007405315f,
- -0.022772932f, -0.022395186f, -0.00079824263f, 0.0011130942f,
- 0.031921066f, 0.034686577f, -0.019780198f, -0.010735629f,
- -0.0056481715f, -0.0009389226f, 0.004651174f, -0.058506273f,
- -0.0019054819f, -0.016566858f, -0.0033119286f, -0.2492872f,
- 0.003247895f, 0.14162406f, 0.010160037f, 0.0040808865f,
- -0.003737218f, -0.03047275f, -0.019671919f, 0.14478819f,
- -0.10618468f, -0.0048549767f, 0.02728089f, -0.004645373f,
- -0.013984837f, -0.107431516f, -0.0021826555f, 0.23910011f,
- -0.0684217f, -0.0062122107f, 0.117034376f, 0.39332172f,
- -0.014243643f, -0.120273024f, 0.03857965f, -0.003289289f,
- -0.012353187f, -0.016884444f, -0.059668537f, -0.10479082f,
- 0.0013376554f, -0.04540761f, -0.31468728f, 0.002049577f,
- -0.047495298f, -0.02633313f, -0.00014948781f, 0.001364381f,
- -0.012947373f, -0.002255013f, -0.05341504f, -0.07722951f,
- -0.015858233f, -0.014842114f, 0.1184791f, -0.0020510321f,
- -0.030682173f, -0.01315841f, -0.022357948f, 0.03750992f,
- -0.0028835207f, -0.039904296f, -0.001321826f, -0.036970906f,
- -0.13728099f, -0.03227532f, 0.032296848f, -0.00209112f,
- 0.0028970006f, -0.16990891f, 0.003362184f, 0.0029552435f,
- 0.0037591553f, -0.049869712f, -0.053764276f, -0.0041815424f,
- -0.013483479f, -0.006833596f, 0.090466365f, -0.006524256f,
- -0.019481031f, -0.025002815f, 0.341731f, 0.008595071f,
- -0.15290461f, -0.011732252f, 0.07334266f, -0.029746955f,
- -0.036585603f, 0.13483615f, -0.017064314f, -0.020942526f,
- -0.063955255f, -0.049310345f, 0.08552899f, -0.01615311f,
- 0.00084924314f, 0.0020943468f, -0.0025779873f, -0.03471697f,
- 0.0012298826f, -0.02067626f, 0.28466484f, 0.0008443885f,
- -0.23287888f, -0.025855256f, 0.0007017594f, -0.023562333f,
- -0.059290834f, -0.109081164f, -0.057353873f, -0.014940213f,
- -0.018565498f, 0.055170737f, -0.045084547f, -0.03351489f,
- -0.006180943f, -0.050556645f, 0.002978701f, -0.016556684f,
- -0.31112808f, -0.0006469833f, -0.13367486f, -0.01945677f,
- 0.23645552f, -0.061947145f, 0.019001374f, 0.0087949075f,
- -0.06048598f, 0.008275381f, 0.039718796f, -0.043396212f,
- -0.024293113f, 0.00075458264f, -0.014504563f, -0.012168276f,
- 0.054145344f, -0.116943255f, -0.07195252f, 0.060511913f,
- 0.0019416072f, 0.0011703606f, 0.06337942f, -0.13634995f,
- -0.01929882f, 0.20058511f, -0.087858476f, -0.018961241f,
- -0.010879066f, -0.009139604f, -0.00058219326f, 0.0029258807f,
- 0.019881912f, -0.0010826304f, -0.06485674f, 0.0023117266f,
- -0.005012606f, 0.35567737f, 0.06347338f, 0.03254048f,
- -0.0006182651f, -0.07564265f, -0.04850352f, -0.00472424f,
- -0.01694463f, 0.005991834f, 0.065340415f, 0.09210591f,
- -0.02575542f, 0.087183625f, 0.031232852f, 0.00033471306f,
- 0.023465825f, -0.034896955f, -0.013884124f, 0.24459027f,
- -0.022851542f, -0.1040958f, -0.005755504f, -0.039325338f,
- 0.061289907f, -0.017671581f, -0.054096624f, -0.0019964774f,
- -0.027114436f, -0.0010301262f, 0.005803916f, -1.8374027e-06f,
- -0.003591723f, -0.008552325f, -0.0019900762f, -0.021667019f,
- -0.01026593f, -0.0020113806f, 0.0074027525f, -0.047315825f,
- -0.023307815f, 0.043943442f, 0.022978645f, 0.0024173679f,
- 0.0036101972f, 0.0033335304f, 0.20207581f, -0.0052444553f,
- -0.009898681f, -0.019241964f, -0.006119584f, -0.0044341623f,
- 0.05148382f, 0.04006116f, 0.0063846544f, -0.00650658f,
- 0.011547813f, 0.0018622512f, 0.0013492154f, -0.009353974f,
- 0.0031545367f, -0.012842528f, 0.009963508f, 0.067451686f,
- 0.003280902f, 0.09295687f, 0.034463793f, -0.0027356783f,
- 0.0060951067f, -0.01762902f, -0.0017083863f, 0.37438646f,
- -0.062934816f, -0.018293984f, -0.057079766f, -0.0060194083f,
- -0.027011612f, 0.009758877f, -0.0043590614f, -0.16754186f,
- 0.041262694f, -0.0008095019f, 0.029277833f, -0.08454705f,
- -0.006449735f, -0.04932842f, -0.08471393f, -0.0012616571f,
- -0.0016717326f, 0.013888514f, -0.04494026f, -0.019469645f,
- -0.00022637866f, -0.035129707f, -0.21763757f, -0.052552756f,
- 0.0063932026f, -0.033137817f, 0.009604457f, 0.008415302f,
- -0.010870923f, -0.018198509f, -0.076626286f, -0.11805734f,
- -0.031667348f, -0.08433082f, 0.08316571f, 0.00061283837f,
- 0.08352098f, 0.001552008f, -0.03000326f, -0.0022328845f,
- -0.0056367777f, -0.016872926f, 0.023020089f, 0.07410296f,
- 0.1546429f, 0.0016983873f, 0.123319164f, -0.006778998f,
- 0.008243981f, -0.042099986f, 0.0006814835f, 0.025126511f,
- 0.0030583246f, -0.032435816f, 0.019344857f, -0.0016580474f,
- -0.028280668f, -0.010294748f, -0.0971226f, -0.0041142814f,
- 0.0043677087f, 0.021242833f, -0.16502541f, -0.0021448028f,
- -0.10004319f, 0.022546485f, -0.0027409196f, 0.002556103f,
- 0.022939734f, -0.08324219f, 0.009475019f, 0.01595882f,
- -0.14648668f, 0.009836814f, -0.03955741f, 0.0670851f,
- 0.08506101f, -0.008464125f, 0.0030025793f, 0.017916163f,
- 0.000405842f, -0.0050099706f, -0.16333692f, -0.00512301f,
- -0.35957256f, 0.019914428f, -0.00807236f, 0.025468798f,
- 0.1940289f, 0.012246145f, 0.033594023f, -0.014856078f,
- 0.010626574f, -0.12232782f, 0.03643445f, 0.008730631f,
- 0.030848028f, 0.049068596f, -0.004224239f, 0.004942099f,
- 0.044355165f, -0.009945171f, 0.015002798f, 0.004778816f,
- 0.101941235f, 0.02130862f, -0.08295441f, -0.01740317f,
- 0.061421156f, -0.027440792f, -0.03534467f, -0.10054083f,
- 0.008423915f, -0.001202604f, 0.009251397f, 0.0054972484f,
- 0.12302828f, 0.04222785f, 0.19235156f, 0.07899976f,
- -0.0025242332f, -0.0060269022f, 0.0016648746f, -0.13832684f,
- 0.007285621f, -0.07998965f, -0.02631273f, 0.009487405f,
- 0.011609853f, -0.006622074f, -0.0034727682f, -0.051194552f,
- -0.06852173f, -0.011617068f, 0.07107508f, -0.00370951f,
- -0.007601027f, -0.5198699f, -0.038586017f, -0.04555583f,
- -0.006883409f, -0.19704285f, 0.019719198f, -0.041601498f,
- 0.0039739073f, -0.028022042f, -0.08391394f, -0.06135184f,
- 0.0118596f, 0.0014761487f, -0.043968942f, -0.0062478455f,
- -0.019042086f, 0.02752035f, -0.005036107f, 0.4469904f,
- 0.0037773722f, 0.048058763f, -0.07505277f, 0.03638437f,
- -0.18223579f, -0.00023350412f, -0.020086028f, -0.006072246f,
- 0.0116554685f, -0.004157238f, 0.028796514f, -0.004153041f,
- -0.005466273f, -0.005009606f, -0.00395406f, 0.0115233315f,
- 0.0061803595f, -0.0041767457f, -0.06837053f, 0.0059287837f,
- -0.07539347f, -0.075500034f, -0.08511666f, -0.0040602684f,
- -0.012598815f, -0.008163531f, -0.106179744f, -0.001308593f,
- 0.022882184f, 0.0144272335f, -0.004265141f, -0.010172657f,
- -0.0055005373f, -0.035960183f, -0.01961616f, -0.0038482277f,
- 0.007642009f, -0.003702214f, -0.0031669512f, 0.050757367f,
- -0.00035482363f, -0.004316549f, 0.007996929f, -0.057455033f,
- -0.0040652007f, 0.03205675f, 8.744361e-05f, -0.0060978574f,
- -0.0042631063f, 0.011981663f, 0.007172263f, 0.16469334f,
- 0.056212813f, 0.00016671592f, 0.030887669f, -0.015980463f,
- 0.006589802f, -0.08029234f, -0.011800482f, -0.28042608f,
- -0.36271092f, -0.0034099058f, 0.08264826f, 0.032914657f,
- 0.0052357996f, 0.10238099f, -0.014822716f, 0.00013014453f,
- 0.0065487646f, 0.00054475333f, 0.012576804f, 0.06146041f,
- -0.0020942185f, 0.004384317f, 0.3852435f, -0.01166964f,
- 0.062330242f, 0.016963387f, -0.0014882861f, 0.0016577463f,
- -0.005671896f, -0.0024845928f, 0.04827493f, 0.14245546f,
- 0.0052623875f, 0.051496524f, -0.18086712f, -0.0017741604f,
- 0.058868878f, 0.005477657f, 0.01498691f, 0.02270449f,
- -2.5304042e-05f, 0.016459944f, -0.08770728f, 0.043768074f,
- 0.031290974f, 0.01390136f, -0.013281131f, -0.002648677f,
- -0.0047606253f, 0.17720501f, -0.004886914f, -0.03331287f,
- -0.00808211f, 0.023921628f, 0.01544986f, -0.024578843f,
- -0.0015305508f, 0.010813566f, -0.099130854f, -0.014621491f,
- -0.00060686737f, 0.0053448123f, -0.10160015f, 0.02288498f,
- 0.0680197f, 0.003997983f, 0.06615869f, -0.0064918245f,
- -0.00015035138f, 0.12810114f, 0.0075585265f, 0.0057180217f,
- 0.014301422f, 0.008708906f, 0.14802963f, 0.053085323f,
- 0.031001873f, 0.005390655f, 0.0016343496f, 0.003198922f,
- 0.0047515905f, -0.0024420712f, 0.28920028f, 0.0005093776f,
- -0.2056882f, -0.009425698f, 0.0041271113f, 0.013096393f,
- 0.017897993f, -0.41758463f, 0.033428527f, -0.01390447f,
- 0.038742978f, -0.06450869f, 0.008113627f, -0.0019276728f,
- 0.0022199217f, -0.002475373f, -0.0053060693f, -0.0010514354f,
- -0.11916685f, 0.009360292f, 0.21504717f, 0.021523176f,
- 0.09067824f, 0.029819837f, -0.015041749f, 0.009308779f,
- -0.0013845365f, 0.004074482f, 0.054838914f, -0.03835772f,
- -0.0010632065f, -0.000110573295f, 0.006990094f, 0.00041373f,
- 0.26861125f, 0.02295452f, -0.060325854f, 0.004755663f,
- -1.6093896e-05f, -0.0007523528f, 0.069070324f, 0.14279085f,
- 0.025655018f, -0.20960535f, 1.4247348e-05f, 0.003699718f,
- -0.09367115f, 0.0058407835f, 0.003578159f, 0.019433334f,
- -0.07316974f, -0.005874093f, -0.08315429f, 0.005214557f,
- 0.003108636f, -0.3720953f, 0.064695284f, -0.044532362f,
- -0.0026424679f, 0.14861451f, 0.020239264f, -0.015563436f,
- 0.010143611f, -0.0013752765f, 0.002821427f, -0.022755418f,
- -0.013332962f, 0.019718895f, 0.01068573f, -0.0008862953f,
- 0.020440215f, 0.008533373f, 0.007572355f, 0.20469135f,
- -0.0027094195f, 0.21390921f, 0.1525093f, 0.09303381f,
- -0.10566512f, -0.0071057337f, -0.06652657f, 0.0049859486f,
- 0.001413281f, 0.0008749143f, 0.12834808f, -5.8459136e-05f,
- -0.0040031313f, -0.0015221301f, 0.00932817f, 0.015306671f,
- 0.022960488f, 0.026227964f, 0.11847504f, 0.001971906f,
- 0.044577397f, 0.09950092f, 0.027824713f, -0.0073086456f,
- -0.036239207f, 0.0039451336f, 0.043846127f, 0.005024327f,
- 0.019043438f, 0.003624292f, 0.020526854f, 0.0067804717f,
- -0.024044544f, 0.041837264f, 0.011314027f, -0.0006099547f,
- 0.0036567561f, 0.0016245458f, -0.0017484451f, 0.13408552f,
- -0.000848942f, 0.0042935144f, 0.03994872f, -0.0013744156f,
- 0.00056192884f, 0.32970232f, 0.029786725f, -0.0013186374f,
- -0.002729571f, -0.011023107f, 0.004896763f, -0.05061479f,
- -0.07010025f, -0.012420529f, -0.07135212f, 0.016985169f,
- 0.00064043025f, 0.14782208f, 0.0027437697f, 0.011913629f,
- 0.17107375f, -0.0017462155f, 0.28566065f, 0.12868188f,
- -0.0037124334f, -0.04502281f, 0.007171303f, -0.007909094f,
- 0.026896214f, 0.01885733f, -0.051314935f, -0.059430234f,
- 0.0007095525f, -0.013843314f, -0.22543715f, -0.049498666f,
- 0.10997496f, -0.0038057608f, 0.0042840876f, -0.014826963f,
- -0.0017302508f, -0.010279467f, 0.20990871f, -0.038633335f,
- -0.00029190595f, -0.03961005f, 0.110198356f, -0.002692564f,
- 0.39585784f, -0.009219353f, 0.010844565f, 0.14111492f,
- -0.0032017555f, 0.018829219f, -0.014798141f, -0.013186286f,
- 0.040902928f, 0.02173555f, -0.12958953f, -0.009552314f,
- -0.010955005f, 0.18635103f, 7.9421545e-05f, -0.009367439f,
- -0.003997341f, 0.010348725f, 0.061938826f, 0.0062897964f,
- 0.0050736004f, -0.0129277455f, -0.018445354f, 0.011340287f,
- 0.015651716f, 0.020818815f, 0.011650302f, 0.028986981f,
- -0.33422408f, 0.017431827f, -0.004131692f, -0.0018170968f,
- 0.006286348f, 0.034264706f, 0.014391919f, 0.017563518f,
- 0.07198694f, 0.038279332f, -0.008577887f, -0.07896815f,
- 0.024034778f, 0.0060302964f, -0.0008820046f, 0.00831524f,
- -0.0013868305f, 0.0049111317f, 0.16990268f, 0.0022650356f,
- 0.034765072f, 0.016123133f, 0.01140568f, 0.062320184f,
- 0.09481629f, 0.2615001f, -0.0013456133f, 0.00058295915f,
- 0.019334128f, 0.034252338f, 0.021026917f, 0.014883752f,
- -0.003502892f, -0.019531878f, 0.0060397224f, 0.01162793f,
- -0.041906692f, 0.025048433f, 0.08574451f, 0.013768652f,
- 0.30163994f, 0.030615183f, 0.13163072f, 0.008516747f,
- 0.030830711f, -0.005430849f, 0.091390215f, -0.13642392f,
- 0.010713374f, -0.0002465998f, 0.013662622f, 0.0166549f,
- -0.11491068f, 0.13951917f, 0.09961204f, 0.11753194f,
- 0.0019718492f, 0.0010679923f, 0.004353201f, -0.09347435f,
- 0.013635438f, 0.31621343f, 0.023988465f, 0.016403526f,
- 0.037928153f, 0.009398645f, 0.00026848915f, -0.01091602f,
- 0.097469054f, 0.018121522f, 0.02731638f, 0.011099124f,
- 0.00650968f, -0.060650498f, 0.024629083f, 0.063148886f,
- 0.0027263248f, 0.085094586f, 0.010101457f, 0.015605247f,
- 0.014635518f, 0.0347968f, 0.034918934f, 0.07940946f,
- 0.020805081f, 0.047807377f, 0.033468604f, 0.0020589351f,
- -0.0029395965f, 0.017981796f, 0.013634125f, -0.08393604f,
- 0.0126263155f, -0.16499695f, -0.16309443f, 0.060248304f,
- 0.14876875f, 0.0127112875f, 0.05723111f, -0.0003681698f,
- 0.012246915f, 0.0012429664f, 0.067749605f, 0.0064069815f,
- 0.0077821477f, 0.009245925f, 0.007988559f, 0.0066660284f,
- -0.0053594443f, 0.011916303f, 0.12713999f, 0.0025557654f,
- 0.11577951f, 0.02525111f, 0.020218235f, 0.0028935794f,
- 0.012324639f, 0.0037717635f, 0.33678415f, 0.005275738f,
- 0.008416229f, 0.017837608f, 0.011775642f, 0.015707558f,
- 0.054480217f, 0.015174899f, 0.017065713f, 0.004128433f,
- 0.027071271f, 0.0033241734f, 0.0025901634f, 0.0055330647f,
- 0.0044900123f, 0.0043667965f, 0.016633688f, 0.06714927f,
- 0.006023845f, -0.13705789f, 0.022358948f, 0.0017566171f,
- 0.001998229f, 0.015906764f, 0.011186751f, -0.34164032f,
- 0.079893045f, 0.010230568f, 0.06603146f, 0.007704579f,
- 0.0053884643f, -0.102853425f, 0.0007657228f, -0.112711675f,
- -0.48024f, -0.0038205818f, 0.12870392f, 0.09649042f,
- 0.0072103376f, 0.04699658f, 0.06910514f, -0.0039951103f,
- 0.07136469f, -0.0016037131f, 0.061515722f, 0.044545084f,
- 0.0026573108f, 0.00048583883f, -0.053561073f, 0.09015073f,
- -0.032937195f, 0.012494487f, -0.0019135963f, 0.0043060067f,
- 0.005669533f, 0.0056683444f, -0.07084969f, 0.06396917f,
- 0.015186278f, 0.049597643f, 0.2096632f, 0.0047878525f,
- -0.13098024f, 0.008331411f, 0.020639883f, 0.14428818f,
- 0.0030669111f, 0.011745096f, -0.052597236f, 0.16163406f,
- 0.28689602f, 0.00817693f, 0.10232945f, 0.0058950293f,
- -0.00044013918f, -0.12541434f, 0.0018588137f, 0.038338773f,
- 0.0059706154f, 0.040122665f, 0.010074004f, -0.0022202246f,
- 0.006566948f, 0.015745308f, -0.16969304f, 0.0026976287f,
- 0.008747522f, -0.010102729f, 0.18360431f, 0.0025747449f,
- -0.19383305f, -0.011518884f, 0.008355168f, 0.013147323f,
- 0.0012960598f, 0.036469817f, -0.006516024f, -0.016591271f,
- 0.06547196f, 0.020046487f, -0.26062858f, 0.07583178f,
- 0.013690664f, -0.009708443f, -0.00030958472f, 0.0022877888f,
- -0.003465753f, 0.0171948f, -0.1852816f, -0.001956681f,
- 0.0071198735f, -0.02757227f, -0.009302672f, -0.024712514f,
- -0.28374234f, 0.32824913f, 0.016774856f, 0.025573337f,
- 0.0036506802f, -0.102095574f, 0.003784422f, -0.0018742637f,
- 0.007919539f, 0.008616381f, 0.008564036f, 0.0015992519f,
- 0.21030495f, -0.02349006f, -0.13464943f, -0.0073609166f,
- 0.14668211f, 0.004208769f, 0.035073012f, -0.016546221f,
- -0.0011493313f, -0.010513617f, -0.0013646034f, 0.012036304f,
- -0.003908851f, 0.0015161723f, -0.0014847098f, -0.06794401f,
- -0.10288282f, -0.035549704f, -0.074701674f, -0.08480013f,
- 0.0005370789f, -0.000522558f, 0.012043144f, -0.17992343f,
- -0.0036499572f, -0.045009766f, 0.048372872f, 0.00021124759f,
- -0.010609401f, -0.010540924f, 0.002242151f, 0.008448946f,
- -0.15920414f, 0.010873814f, -0.045113537f, -0.007875768f,
- 0.0024286187f, -0.23394257f, 0.007058332f, -0.008820928f,
- 0.0047480823f, -0.11248829f, 0.015227344f, 0.010627347f,
- -0.0009091219f, -0.01644626f, 0.033793744f, 0.039622102f,
- -0.01667793f, -0.103559084f, -0.02428268f, 0.00045507992f,
- -0.008160626f, -0.000850132f, 0.018856304f, -0.052740876f,
- 0.009420302f, 0.2113917f, -0.21666276f, -0.046223145f,
- -0.07388115f, 0.0063049546f, -0.046083856f, -0.0003925659f,
- -0.013719345f, 0.0006947896f, 0.042090867f, -0.0014884521f,
- 0.002246333f, 0.018460965f, 0.0035619766f, -0.0023857427f,
- -0.00029852043f, -0.005262672f, 0.007831789f, 0.0151954265f,
- -0.06547826f, -0.0016572016f, 0.009955233f, -0.0023772449f,
- -0.121963635f, -0.0080336705f, 0.0681985f, -0.006239714f,
- 0.00066901976f, -0.0023481057f, -0.01937879f, -0.017724872f,
- -0.19226874f, -0.012210742f, 0.002992773f, 0.005784659f,
- -0.0012661486f, 5.844856e-05f, 0.0011599709f, -0.047909766f,
- 0.0019778437f, -0.019098096f, -0.023181967f, -0.28152168f,
- -0.0036557955f, 0.036708612f, -0.0072478275f, -0.0035526396f,
- 0.006587938f, -0.011950159f, -0.007647748f, -0.0037071228f,
- -0.03602863f, 0.021938749f, -0.028692259f, -0.017701168f,
- 0.017746963f, -0.5011363f, 0.006840105f, -0.06172857f,
- 0.31420416f, -0.0012785924f, -0.26038516f, 7.985169e-05f,
- 0.0045482395f, -0.022445574f, -0.016834315f, 0.00030523326f,
- 0.010074906f, -0.020007083f, -0.004078666f, 0.006151734f,
- -0.000304835f, 0.028094793f, -0.20909819f, 0.0065254504f,
- -0.04911649f, -0.0065016933f, -0.00012146035f, -0.005098928f,
- -0.0039058493f, 0.035049047f, -0.122753f, -0.050265748f,
- 0.0010176612f, -0.026060207f, 0.10145741f, 0.0029695716f,
- 0.024993053f, 0.0020602767f, 0.0032650514f, -0.11396392f,
- 2.5705604e-05f, -0.007430838f, -0.014781945f, 0.0803209f,
- 0.04421554f, -0.024411922f, -0.041136343f, 0.003886697f,
- 0.0034645784f, 0.16896586f, 0.00034375687f, -0.03176987f,
- -0.0009799687f, -0.008933441f, -0.03627294f, -0.004132845f,
- 0.019333676f, -0.0006664477f, -0.074315876f, 0.0016963523f,
- -0.012350546f, -0.01837333f, -0.41738784f, -0.027489243f,
- 0.12707537f, -0.0062305275f, -0.0024815907f, -0.03218803f,
- -0.00062404387f, 0.22200765f, -0.0023121354f, -0.015503157f,
- 0.11971796f, 0.0029700375f, -0.0961138f, 0.10044815f,
- -0.07452928f, -0.0020883563f, -0.0008797627f, -0.019875996f,
- -0.0069074584f, -0.009563095f, 0.29626673f, 0.002429349f,
- 0.05696796f, -0.0010176708f, -0.00026482466f, -0.016805021f,
- -0.046355154f, -0.022154545f, 0.02711973f, 0.0026147484f,
- -0.057592962f, 0.05060591f, -0.026405253f, -0.010790782f,
- -0.09779377f, 0.08793463f, 0.0014942025f, -0.013909658f,
- 0.23052967f, 0.0038142418f, 0.03805597f, -0.0027500319f,
- -0.09529396f, -0.039446827f, 0.06806323f, 0.027618326f,
- -0.08318886f, 0.017561175f, 0.03532768f, 0.08667137f,
- -0.0074542807f, -0.0013091207f, -0.01544808f, -0.14501356f,
- -0.08581682f, 0.08470889f, -0.19275072f, -0.11921871f,
- 0.0021333636f, 0.0009687644f, -0.0056279777f, -0.50261986f,
- -0.0043369723f, -0.08334171f, 0.04687468f, -0.017275134f,
- -0.06459124f, -0.0003207692f, 0.0044478336f, 0.020971403f,
- 0.038776364f, 0.0039565554f, 0.04521291f, 0.0038256387f,
- 0.0010188657f, -0.25192803f, 0.052469704f, 0.033651546f,
- 0.008846364f, 0.08321181f, -0.0411811f, 0.03403382f,
- -0.0019785878f, 0.04508858f, -0.08833536f, -0.012185082f,
- -0.008175505f, -0.12855741f, 0.009999335f, 0.0035434864f,
- 0.034972843f, -0.02215346f, -0.030696733f, -0.03150739f,
- -0.015545281f, 0.045673355f, -0.0789302f, -0.07762722f,
- 0.06991088f, -0.007839436f, 0.06200319f, 0.012001995f,
- -0.0073122554f, -0.00083444535f, 0.13173357f, 0.001027283f,
- -0.014422029f, -0.0007869387f, -0.028170872f, -0.007965479f,
- 0.05203176f, -0.0059681367f, 0.15452413f, -0.022288572f,
- 0.09501815f, -0.042644836f, -0.0015160034f, 0.00043832773f,
- -0.013301852f, 0.0007579568f, 0.20675682f, -0.00038580637f,
- -0.04082862f, -0.017413083f, -0.021103851f, -0.0018764647f,
- 0.021281505f, 0.015772779f, -0.0034347824f, -0.0013818144f,
- -0.029881759f, -0.00053589384f, 0.00017837256f, -0.008901706f,
- 0.0019368295f, 0.020443214f, -0.007981481f, -0.1757314f,
- -3.3662778e-05f, -0.31043988f, -0.036946177f, 0.0026719354f,
- 0.011896606f, -0.015315346f, -0.0020972113f, 0.29888776f,
- -0.005750179f, 0.0077453256f, -0.030776786f, 0.017101845f,
- -0.029587343f, 0.2084258f, 0.010055047f, 0.12533188f,
- -0.13773292f, 0.008963589f, -0.2585771f, -0.21948564f,
- -0.0133711565f, 0.04344072f, -0.022481646f, 0.0015658215f,
- 0.016509732f, -0.0042369994f, -0.011836048f, 0.021320835f,
- 0.0016466666f, -0.012445873f, -0.058199573f, 0.03479284f,
- 0.0067855003f, -0.0140258605f, 0.005203288f, 0.027371522f,
- -0.0015266795f, 0.015677942f, 8.745677e-05f, -0.14435224f,
- -0.017489688f, -0.01864188f, 0.15778771f, 0.0025384289f,
- -0.15534344f, -0.0060771783f, -0.035846703f, -0.079688415f,
- -0.00088155805f, -0.022320323f, -0.031181868f, -0.107756995f,
- -0.0022889946f, -0.027772367f, -0.0156203555f, 3.9514103e-05f,
- 0.010820973f, 0.20019077f, 0.0014564341f, 0.05345364f,
- 0.0064338357f, -0.031820007f, 0.015794704f, 0.019308917f,
- -0.028997941f, -0.020321537f, -0.031654593f, 0.009317785f,
- 0.0035734822f, 0.007415946f, 0.086883835f, -0.029001025f,
- 0.054721233f, -0.0027100358f, 0.011070004f, 0.02257343f,
- 0.024265004f, 0.14007042f, 0.0050868844f, 0.0016374344f,
- 0.06879297f, 0.021252478f, 0.044273946f, -0.00025425473f,
- -0.01964118f, 0.0046941154f, 0.0010875124f, 0.011674165f,
- -0.0037222258f, -0.006580344f, 0.1511931f, -0.0029403432f,
- -0.33084556f, 0.031953797f, -0.00013454503f, 0.0118350275f,
- 0.17454953f, 0.087730125f, 0.017284952f, -0.0027690972f,
- 0.04384165f, 0.20555621f, 0.016656294f, 0.023368325f,
- -0.03677309f, -0.045053065f, -0.0022603453f, 0.0096318945f,
- 0.15059552f, 0.035718422f, -0.09485442f, 0.008929565f,
- -0.318473f, 0.010659047f, 0.10209147f, 0.013089232f,
- -0.03956527f, 0.009646732f, 0.019415077f, 0.121040314f,
- 0.011764923f, -0.00023187026f, -0.0031318949f, 0.04212808f,
- -0.09193372f, -0.05594151f, -0.0028853302f, 0.06754036f,
- -0.0048615206f, 0.003660881f, 0.046204332f, 0.20400515f,
- 0.006809197f, 0.13732767f, 0.021016251f, -0.005238559f,
- 0.016533967f, 0.0060265707f, -0.004618882f, 0.0043235063f,
- -0.4960564f, 0.018980112f, 0.030060945f, -0.0034721477f,
- 0.002921106f, 0.11112517f, 0.033755258f, 0.036534294f,
- -0.0019378929f, 0.17888026f, 0.012305092f, 0.0030800113f,
- 0.016415332f, 0.02139406f, 0.09091874f, 0.07869592f,
- 0.054996282f, -0.046082664f, 0.027869089f, 0.0024761367f,
- 0.026668895f, 0.014879287f, 0.05864368f, 0.05774415f,
- 0.016669804f, 0.035526846f, 0.19895215f, -0.004146326f,
- 0.21617895f, -0.004762699f, 0.14573483f, 0.0071740774f,
- 0.012588529f, -0.004066228f, 0.075236365f, 0.0008265626f,
- 0.015426356f, -0.005307626f, 0.04620961f, 0.00013201383f,
- 0.005733636f, -0.0033542174f, 0.009633696f, 0.029736355f,
- -0.19353461f, 0.0010060002f, -0.0039517344f, -0.009461387f,
- -0.031259704f, 0.0044572214f, -0.23161499f, -0.009835802f,
- -0.004740848f, 0.008152159f, 0.050522562f, 0.0056017744f,
- 0.21756236f, 0.010311089f, 0.023606941f, 0.0033039108f,
- -0.000996871f, -0.00083309726f, -0.002741344f, 0.04395833f,
- -0.0036113677f, 0.022563713f, -0.045730107f, -0.06397646f,
- -0.000103076236f, 0.09615044f, -0.027514445f, -0.0030712164f,
- -1.23556565e-05f, 0.06056579f, 0.01002826f, 0.16523062f,
- -0.005728033f, -0.003955659f, -0.047935512f, 0.0070866393f,
- 0.008208974f, 0.016894965f, -0.007958605f, 0.029203244f,
- 0.10255105f, 0.0055468357f, -0.17243885f, 0.40128627f,
- 0.0123585295f, 0.0040655173f, 0.08009255f, 8.795805e-05f,
- 0.009525312f, 0.025474904f, 0.011213154f, 0.0035881659f,
- -0.00025922002f, 0.0016662069f, 0.044671066f, 0.04098998f,
- -0.002829719f, 0.020317703f, -0.0039546085f, 0.014547814f,
- 0.0021953748f, -0.010422166f, 0.1742383f, 0.118539765f,
- 0.02673582f, 0.02008971f, -0.03579138f, -0.004308571f,
- -0.09049294f, 0.008269724f, 0.033940386f, -0.046482697f,
- -0.0033732837f, -0.0065554134f, 0.13132864f, -0.042415284f,
- 0.04410755f, 0.013952282f, 0.058113076f, -0.001958908f,
- 0.0066866144f, 0.17488205f, 0.0007291262f, 0.034630306f,
- 0.00012922159f, -0.0057008723f, -0.0048011593f, 0.013191439f,
- 0.01572244f, 0.013145592f, 0.017223097f, 0.0012286745f,
- -0.02520052f, -0.019665046f, 0.14967903f, -0.051490493f,
- -0.021031333f, -0.017669067f, -0.0139373895f, -0.041069776f,
- -0.035298284f, -0.13773774f, -0.021348111f, -0.03382584f,
- 0.10004416f, -0.0033461868f, -0.42573422f, 0.0785198f,
- -0.0655101f, 0.0021953864f, -0.010908369f, -0.044922613f,
- -0.0065574995f, -0.04029704f, 0.011435325f, -0.0035600164f,
- -0.052051894f, -0.017904975f, -0.006958083f, 0.03006912f,
- 0.47263885f, 0.22447598f, 0.01438685f, -0.01748774f,
- -0.02488405f, 0.16672307f, -0.06253989f, -0.024963282f,
- -0.032019977f, 0.028880041f, -0.009712847f, -0.0041251527f,
- -0.18733238f, -0.004683315f, 0.0041845706f, -0.018445859f,
- 0.17306109f, -0.024389867f, 0.06563142f, -0.005572799f,
- 0.018896306f, -0.020003526f, -0.036167268f, 0.03494623f,
- -0.004944341f, -0.0042712763f, -0.04428721f, 0.13514715f,
- -0.067626536f, -0.122633204f, -0.27822804f, 0.008582778f,
- -0.00085779984f, 0.0032019282f, -0.039769918f, 0.60024065f,
- -0.019601002f, -0.230406f, 0.00051114283f, -0.034454722f,
- 0.010149438f, -0.015515009f, 0.006379738f, 0.0044767745f,
- 0.26963603f, 0.023755403f, 0.056809068f, -0.021350512f,
- -0.017184185f, -0.14647478f, -0.00059652637f, -0.063215114f,
- 0.0038668425f, -0.14401373f, -0.035879776f, 0.029463088f,
- -0.010886699f, 0.043139588f, -0.0038235574f, 0.026613459f,
- -0.009892429f, -0.09915031f, 0.015093727f, 0.0060325162f,
- 0.04862138f, -0.031460565f, -0.015865212f, 0.21191384f,
- -0.016231379f, 0.08435526f, 0.08229641f, -0.007945295f,
- -0.09541357f, -0.03297492f, -0.06444153f, -0.0066487757f,
- -0.014984117f, -0.0018112807f, -0.057983954f, -0.0022782611f,
- -0.013420676f, -0.01388833f, 0.0021398873f, -0.03936947f,
- -0.008321053f, -0.017357234f, 0.016738025f, -0.054282088f,
- 0.08539833f, 0.025538817f, -0.01825815f, -0.016815545f,
- 0.032551553f, 0.0055315825f, -0.12917134f, -0.009751009f,
- -0.046779312f, -0.01806844f, -0.008352793f, -0.020549348f,
- -0.25730094f, 0.00090766343f, -0.023979204f, -0.020735335f,
- -0.017437765f, -0.0011700721f, 0.0023376523f, -0.028941182f,
- -0.0009274024f, -0.034415796f, -0.04292644f, -0.03559801f,
- -0.004557299f, -0.3469418f, -0.04779272f, 0.0014010418f,
- -0.0026480912f, -0.023140935f, -0.018195849f, 0.027658287f,
- -0.069611356f, -0.026558919f, -0.05369427f, -0.039566323f,
- -0.02274239f, 0.18926027f, -0.011581404f, -0.011987872f,
- 0.011810851f, 0.004546919f, -0.17407934f, -0.13224396f,
- -0.016323397f, -0.07012564f, 0.05321512f, 0.004065477f,
- 0.03901777f, -0.0054968586f, -0.05547156f, 0.0014728211f,
- 0.0007810401f, -0.00065458514f, -0.086279005f, 0.047978457f,
- -0.0071208244f, -0.016789926f, 0.0021975564f, 0.009424408f,
- -0.0347291f, -0.022702642f, 0.040234f, -0.16325225f,
- -0.019323455f, 0.05873721f, -0.0050362097f, 0.0021417942f,
- -0.09229924f, -0.02183548f, -0.015577159f, -0.094850734f,
- 0.0044650976f, -0.0597553f, -0.002936645f, -0.026013434f,
- -0.014458194f, -0.019286448f, 0.058516197f, 0.0012444532f,
- -0.0031311852f, 0.01624375f, 0.0036538974f, 0.050165053f,
- -0.0007882908f, -0.05501115f, -0.050288767f, -0.035444178f,
- -0.024848988f, -0.0077723307f, -0.014274571f, -0.008634897f,
- 0.0021054372f, 0.011386905f, -0.09537047f, 0.00218354f,
- 0.14314573f, -0.0047551394f, -0.009096479f, -0.02789403f,
- -0.039335992f, -0.107365794f, -0.004549724f, 0.00884971f,
- 0.10044438f, -0.008354806f, -0.48024252f, -0.10898382f,
- -0.04897505f, -0.0023129084f, 0.0071077324f, 0.004077946f,
- 0.0059239264f, 0.006922377f, 0.3688023f, -0.00083200523f,
- 0.67640924f, -0.027937882f, -0.007295208f, -0.018666556f,
- -0.30207568f, -0.05563587f, -0.039134715f, 0.015170231f,
- -0.019706858f, -0.028182581f, 0.0008961933f, -0.003615141f,
- -0.029561287f, -0.12644021f, -0.0017561442f, -0.0015325485f,
- 0.39115626f, -0.0067346743f, -0.07313348f, -0.015309446f,
- 0.06586189f, -0.026835537f, 0.0070772907f, 0.02245132f,
- -0.04960096f, -0.019775318f, 0.017762847f, 0.007854563f,
- -0.009213248f, 0.0019814062f, 0.009435699f, 0.0035980798f,
- -0.13263538f, 0.16960183f, 0.052671004f, -0.103916295f,
- 0.0013719103f, -0.0023109848f, -0.019567652f, -0.27115616f,
- -0.021016255f, 0.11658159f, 0.0023956683f, 0.009949594f,
- -0.015700452f, -0.0034293737f, 0.006357882f, 0.02310353f,
- 0.18951885f, 0.0067815133f, -0.10076583f, -0.013921492f,
- 0.007498949f, 0.7416732f, 0.0037513461f, 0.054539878f,
- -0.00015564871f, -0.11398945f, -0.031784594f, 0.03397751f,
- -0.005137535f, 0.04105159f, 0.02143049f, -0.022283632f,
- -0.02372123f, 0.048236206f, -0.0019720797f, -0.0014759179f,
- 0.034462314f, 0.0067372588f, -0.024837267f, -0.35140124f,
- 0.0012390171f, 0.2925385f, -0.022970855f, -0.044822335f,
- 0.24989042f, 0.011126524f, -0.10097539f, 0.010904436f,
- -0.005840002f, 0.0017251772f, -0.068687126f, -0.001720866f,
- -0.016352346f, 0.008765576f, -0.01124869f, 0.012099247f,
- 0.023032315f, -0.026833737f, 0.116050236f, -0.019849816f,
- -0.18827532f, -0.020814046f, 0.031049997f, -0.012133404f,
- -0.0028892283f, -0.0027900606f, 0.09288151f, 0.0072836094f,
- -0.0009836467f, 0.004386162f, -0.017307742f, -0.008876932f,
- 0.19600955f, 0.004216382f, 0.029062325f, 0.004452845f,
- 0.0038205746f, -0.002184788f, -0.0015655898f, -0.080026895f,
- 0.00038885386f, -0.021684404f, -0.016534919f, -0.15069711f,
- -0.004724967f, -0.3573506f, 0.0094957715f, 0.0009163223f,
- 0.0026153205f, -0.05770462f, 0.0046548597f, -0.6314811f,
- 0.08157806f, 0.017379254f, -0.04180633f, -0.010335925f,
- 0.0047605536f, 0.34640354f, 0.003248071f, 0.27959728f,
- -0.11193876f, 0.007153666f, -0.19137728f, 0.0949576f,
- 0.0020484899f, 0.08019258f, -0.0059204083f, 0.00097490184f,
- 0.007372459f, -0.007669056f, 0.043062042f, 0.073498085f,
- -0.0007232321f, -0.018029243f, 0.33556202f, 0.05654375f,
- -0.025142409f, -0.02137831f, -0.00012779057f, 0.006249194f,
- 0.007030968f, 0.016513932f, -0.17426606f, -0.118428536f,
- -0.015068615f, 0.04168795f, 0.085688755f, 0.00054904027f,
- -0.034921464f, 0.0043987557f, -0.047446582f, -0.09142458f,
- 0.0024549256f, -0.003256329f, 0.009049515f, -0.12291348f,
- 0.18209359f, 0.0019182848f, 0.17959842f, 0.0025496788f,
- -0.002262584f, -0.056380436f, -0.0010155534f, 0.029330289f,
- -0.004005343f, -0.00945306f, 0.036319584f, -0.009498713f,
- 0.000629184f, 0.0039833873f, -0.013886289f, 0.0007966255f,
- 0.0097957775f, 0.008831077f, 0.3722798f, 0.0031461574f,
- -0.049343735f, 0.008536886f, 0.020236872f, 0.038403153f,
- 0.053756274f, -0.03263891f, 0.0068249134f, 0.013803727f,
- -0.09115391f, 0.016490206f, 0.3647389f, 0.16305877f,
- 0.06287741f, -0.012857398f, -0.0051324116f, 0.021575978f,
- -0.009175177f, 0.003983548f, 0.20032334f, -0.0004723955f,
- 0.14943789f, 0.037528228f, -0.013108614f, -0.006404207f,
- -0.25835118f, -0.28500298f, 0.031210387f, 0.011365663f,
- -0.02296758f, -0.21141459f, 0.02095083f, 0.01170372f,
- 0.031462464f, 0.0773008f, -0.008907009f, 0.0033667707f,
- 0.47267467f, 0.0036259557f, -0.15208037f, 0.011906699f,
- -0.11544234f, 0.031346347f, 0.0061938143f, -0.0033544493f,
- 0.047160216f, -0.006224503f, -0.009652454f, 0.07310975f,
- 0.009246666f, -0.0020599656f, 0.006037371f, -0.119669735f,
- 0.13695036f, 0.09607095f, 0.16992246f, -0.03834502f,
- 0.0014673173f, -0.005494337f, 0.023459807f, -0.6185468f,
- 0.013610542f, 0.30393425f, 0.08041267f, 0.004394295f,
- -0.04451241f, -0.0069984966f, 0.0030055225f, -5.1205934e-05f,
- 0.060644418f, -0.018559957f, 0.011484976f, -0.0030914072f,
- 0.006712587f, -0.5225132f, 0.022147303f, 0.041302532f,
- -0.0035223376f, 0.30513653f, 0.019254237f, -0.020981206f,
- 0.009562147f, -0.044713423f, -0.0041791396f, 0.056581423f,
- 0.028308488f, 0.06982666f, -0.04738797f, -0.008348662f,
- -0.023676675f, 0.015293587f, 0.0146838855f, 0.24694432f,
- 0.004409662f, -0.0662503f, -0.17357624f, 0.003836741f,
- 0.29547018f, 0.004154005f, 0.18371437f, -0.0002216253f,
- 0.0070043853f, -0.0012595612f, -0.093610786f, -0.003593095f,
- 0.012818295f, 0.0020164133f, -0.004081061f, 0.0060482165f,
- -0.012241964f, -4.5420114e-05f, -0.0335587f, 0.036207087f,
- -0.26671615f, -0.015432044f, -0.034019325f, -0.017310686f,
- -0.03172954f, -0.013602279f, -0.2593032f, 0.0038321486f,
- 0.010988f, 0.006868038f, 0.0028123013f, -0.008540496f,
- 0.23571181f, 0.0073699118f, -0.009096909f, 0.0056220293f,
- 0.002305238f, 5.3854656e-05f, -0.0036205512f, 0.006954367f,
- -0.0034597742f, 0.012294962f, 0.0075871195f, -0.46942997f,
- -0.009180943f, -0.19243644f, 0.017621545f, -0.0022877809f,
- 0.000408634f, 0.034722038f, 5.8745423e-05f, 0.28332773f,
- -0.015995832f, 0.0013969983f, 0.089428194f, -0.0019756004f,
- 0.009505839f, -0.26578918f, 0.0034110837f, 0.208289f,
- 0.044440713f, -0.0005744704f, 0.022953542f, 0.18938299f,
- 0.0008117698f, -0.0037547403f, -0.04646158f, -0.003831687f,
- 0.0005241934f, 0.008879628f, -0.004763481f, 0.0022209468f,
- -0.0042569507f, -0.0047077015f, -0.22241196f, 0.009120088f,
- -0.009488699f, 0.023404926f, 0.0028366325f, 0.0036167267f,
- 0.0034342473f, 0.009018572f, 0.08341915f, 0.17907113f,
- 0.0139568355f, -0.0059840023f, 0.032483142f, -0.0013399875f,
- 0.10008096f, -0.00074635254f, 0.02324155f, 0.09281296f,
- 0.0011347622f, 0.017664576f, 0.12107318f, 0.11545481f,
- 0.16880924f, -0.01027624f, -0.14758193f, -0.0008436481f,
- 0.0042828773f, -0.08390632f, -0.006113875f, -0.023021027f,
- -0.009056124f, 0.013510696f, 0.047682196f, 0.0117661655f,
- 0.008113838f, -0.0012256008f, -0.038276657f, 0.0016044491f,
- 0.0042212596f, 0.0018149498f, -0.40421832f, 0.009586176f,
- -0.038246065f, 0.007227846f, -0.026129242f, 0.027641697f,
- 0.00677417f, -0.33004606f, 0.0014567309f, -0.009667243f,
- -0.03882877f, 0.0040488103f, 0.82351613f, -0.07250374f,
- 0.016626304f, -0.0027319435f, 0.00021781195f, 0.0044861827f,
- -0.004268908f, -0.00278385f, -0.14839187f, 0.0019894703f,
- -0.059770353f, -0.0004972092f, -0.0038830247f, 0.02039091f,
- -0.33799744f, -0.25658372f, 0.0015607117f, 0.014284026f,
- 0.02484911f, -0.1541334f, 0.008061391f, -0.0071867f,
- 0.029858598f, -0.104053654f, -0.0007138386f, 0.0073966687f,
- -0.24317546f, -0.0253548f, -0.073319346f, -0.00091472146f,
- 0.00710916f, 0.021279676f, -6.962893e-05f, -0.047073364f,
- 0.029513258f, -0.019710988f, -0.0015098939f, -0.14308344f,
- -0.0026675109f, 0.0051960833f, -0.00315139f, 0.18731682f,
- 0.06104586f, 0.044360206f, 0.14656961f, -0.18204424f,
- 0.00078146684f, -0.0022310666f, -0.026711123f, -0.25557277f,
- -0.0011784235f, 0.1589993f, 0.038669873f, -0.0030422218f,
- -0.013219928f, -0.005083701f, 0.008372153f, -0.0059310556f,
- -0.42393616f, 0.0077057793f, -0.03792437f, -0.005492317f,
- 0.0032420133f, 0.24043468f, -0.056355953f, -0.01956933f,
- 0.004317455f, 0.68182635f, 0.0075756526f, 0.006647063f,
- -0.0015377593f, 0.008228467f, -0.03856139f, -0.032718938f,
- -0.021131523f, -0.003319868f, 0.019222299f, -0.0018615214f,
- -0.027181948f, -0.0007883722f, 0.013022194f, -0.44915003f,
- 0.003202667f, 0.13896422f, 0.16925208f, 0.019437416f,
- -0.1709917f, 0.0007951226f, -0.0051318463f, -0.003667309f,
- -0.0030794858f, 0.0041203494f, -0.13992664f, 0.00082978734f,
- 0.0031579055f, 0.009726659f, 0.021130914f, -4.781425e-05f,
- -0.03777821f, 0.008111979f, -0.02989234f, 0.025412405f,
- 0.2234346f, 0.01649072f, -0.03276912f, -0.006752618f,
- -0.094560795f, -0.003689971f, -0.0057132356f, -0.0008017638f,
- 0.021044878f, -0.0040540965f, 0.003545937f, -0.011351464f,
- 0.1685159f, -0.022849288f, -0.0057155876f, -0.0002285373f,
- -0.0011511911f, 0.0032219724f, 0.0033651257f, 0.014572777f,
- -0.0022962324f, -0.003750464f, 0.018642211f, 0.34081802f,
- -0.0020367287f, 0.038056053f, -0.002847237f, -0.0008854807f,
- -0.005623115f, -0.008240003f, -0.0012019405f, -0.4100316f,
- -0.0055726487f, 0.0064421515f, 0.122176886f, -0.01054725f,
- 0.0076673417f, 0.21932273f, 0.007331189f, 0.10288871f,
- 0.2759135f, -0.0067912685f, 0.19819967f, -0.5101777f,
- -0.0018324518f, 0.010781074f, -0.009817874f, -0.0022379362f,
- -0.013255465f, 0.002262935f, -0.0072479295f, 0.0022298482f,
- -0.00046409093f, 0.017676324f, 0.013983576f, 0.017391797f,
- -0.012170197f, 0.0038502451f, 0.00031595983f, -0.015023473f,
- -0.0013982933f, 0.033179935f, -0.15046532f, 0.31621885f,
- -0.0014917848f, 0.024134196f, -0.06170609f, -9.7218384e-05f,
- 0.015298564f, -0.0045681065f, 0.02233137f, 0.02977081f,
- 0.007066308f, 0.006438576f, -0.006407169f, 0.039322495f,
- -0.118496075f, 0.012391368f, -0.09439947f, 0.005015643f,
- -0.0026664066f, -0.3196525f, -0.0014377767f, -0.02315438f,
- -5.08277e-05f, 0.02367273f, -0.06691856f, -0.005034567f,
- -0.000953766f, -0.0036449053f, 0.037585195f, -0.014226065f,
- 0.00030922168f, 0.0070266956f, 0.68487424f, 0.032102477f,
- 0.27127525f, 0.0106146345f, -0.01775897f, 0.0060112597f,
- 0.020290127f, 0.02724482f, -0.014678807f, -0.004813334f,
- 0.070681185f, 0.017331315f, -0.06188916f, -0.14437632f,
- 0.045751613f, -0.010942745f, -0.0019382909f, 0.0050059557f,
- -0.0007534914f, 0.0012377303f, -0.43603325f, -0.0002545258f,
- 0.088155925f, -0.010900731f, -0.0062280153f, 0.052731916f,
- -0.28980073f, 0.18991391f, -0.0092782555f, -0.0078120213f,
- 0.026560746f, -0.13207744f, 0.02339428f, -0.004739292f,
- -0.0046070265f, 0.23997591f, 0.002694572f, -0.0013446758f,
- -0.021136664f, -0.0044217315f, 0.2511159f, 0.011720475f,
- -0.017762767f, 0.027459593f, -0.07109569f, -0.05805073f,
- 0.027609829f, 0.0013557374f, 0.039838437f, 0.21084332f,
- -0.00988755f, -0.002224182f, -0.0024673634f, 0.024964469f,
- -0.1294097f, 0.04191041f, 0.21898152f, 0.16014162f,
- 0.0046144477f, -0.0047550118f, -0.02231793f, 0.17447236f,
- 0.013217317f, 0.10160377f, 0.22927497f, 0.0008806463f,
- 0.003595381f, -0.0075083873f, -0.003247275f, 0.018440038f,
- -0.20474926f, -0.030505354f, 0.2579901f, -0.0010520981f,
- -0.001263819f, 0.20728692f, -0.07703681f, 0.026009966f,
- 0.002451449f, -0.58965886f, 0.01767851f, -0.0072106346f,
- 0.0026178472f, -0.043244217f, -0.11224664f, -0.069624215f,
- -0.007175288f, 0.018552179f, -0.010561929f, -0.0043098014f,
- -0.02279961f, 0.016362479f, -0.0096131805f, 0.4523611f,
- -0.0072444705f, 0.13713479f, -0.5287701f, 0.06784521f,
- 0.06995235f, 4.630126e-05f, 0.2970239f, 0.0079389345f,
- -0.008194189f, -1.0537332e-05f, 0.03684533f, -0.0036321448f,
- -0.0020909102f, -0.0009608812f, 0.00021652493f, -0.0031353638f,
- -0.040128436f, 0.017981818f, 0.06786067f, -0.002359835f,
- -0.35682443f, 0.03747929f, 0.025293166f, -0.00027452115f,
- 0.0020190356f, -0.011408401f, -0.07896274f, -0.001569742f,
- 0.016685346f, 0.0024745185f, -0.0037496253f, -0.005106682f,
- 0.032060366f, -0.031718954f, -0.015995268f, -0.0037245674f,
- -0.00045742298f, -0.0038120572f, -0.0017905846f, 0.03608829f,
- -0.0038202885f, -0.0022519245f, 0.006114121f, 0.18516642f,
- -0.0025151265f, -0.08793063f, 0.013186222f, -1.5537184e-05f,
- 0.0019388845f, -0.0027278017f, -0.0018442562f, -0.13795489f,
- 0.040528465f, -0.008046177f, -0.004429428f, 0.0070128413f,
- 0.0040059565f, 0.08851571f, -0.0054653217f, -0.4672855f,
- 0.022621881f, 0.0015237359f, 0.06998177f, -0.80535245f,
- -0.0004582449f, -0.040095843f, -0.05259787f, -0.0031186552f,
- 0.044227287f, 0.0022015127f, 0.010643712f, -0.054435104f,
- -0.0022767347f, 0.024524279f, 0.4015272f, 0.02980895f,
- -0.013848123f, 0.0034913481f, -0.0003070873f, 0.0063424907f,
- -0.005564393f, -0.02191891f, -0.098451994f, 0.24303955f,
- -0.008381204f, -0.0020293936f, 0.074278325f, -0.00091343693f,
- 0.07742878f, -0.00063870056f, 0.0020330993f, 0.07956755f,
- -0.0055675134f, 0.0058231135f, 0.013725786f, 0.02651671f,
- -0.04536962f, 0.014673969f, 0.08878948f, -0.0033357919f,
- -0.0019987554f, 0.2746307f, -0.0033964051f, -0.039115794f,
- -0.0058421157f, 0.006739857f, -0.0115020545f, -0.007768266f,
- 0.0057149944f, -0.0075611603f, -0.051710524f, 0.0024810818f,
- -0.009179798f, -0.008835025f, -0.58989954f, 0.030080311f,
- -0.29546452f, -0.0055691875f, 0.033679057f, -0.007118862f,
- -0.020735225f, -0.24706471f, -0.008616091f, -0.010719405f,
- -0.1865361f, -0.020306338f, -0.43398976f, -0.32927334f,
- 0.016012914f, -0.009623275f, 0.00455459f, -0.012434163f,
- 0.0022485368f, -0.022898156f, -0.39899963f, 0.00033754902f,
- -0.27365544f, -0.019712316f, -0.008151092f, -0.020606805f,
- -0.5242733f, 0.48441932f, -0.06832875f, -0.014924315f,
- -0.021240957f, -0.112215176f, -0.0022908987f, -0.021678407f,
- -0.044448406f, -0.4076333f, 0.0053484286f, 0.003389397f,
- -0.039435495f, -0.016273245f, -0.30653152f, -0.016552566f,
- -0.091276124f, -0.017483715f, -0.071939565f, -0.10449913f,
- -0.015355914f, -0.018340776f, 0.029262563f, -0.33008018f,
- -0.015682882f, -0.0006512179f, -0.014813037f, -0.09496328f,
- -0.1455393f, 0.005323398f, 0.22298904f, -0.12500323f,
- 0.0024728004f, -0.0040503494f, -0.009501682f, -0.08470648f,
- -0.017352356f, -0.17578778f, -0.22247434f, -0.0105786575f,
- -0.016386734f, -0.008275768f, 0.005515135f, 0.021941928f,
- -0.21306078f, -0.0068538217f, -0.2673559f, -0.006917794f,
- -0.0039180377f, -0.62710834f, -0.007121786f, -0.028280903f,
- -0.0029860416f, 0.26930046f, -0.004577485f, -0.007994448f,
- -0.017089842f, -0.025026426f, -0.016191358f, -0.009316192f,
- -0.006106119f, -0.06259006f, -0.034864217f, -0.0034055412f,
- -0.023781728f, 0.00026694793f, -0.0041760206f, 0.086014554f,
- -0.015950687f, 0.35522807f, -0.2614138f, -0.022119474f,
- -0.3185328f, -0.018055817f, -0.0070295273f, -0.007544436f,
- -0.015636183f, -0.0009198487f, -0.036407374f, -0.0049594236f,
- 0.0028229523f, 0.00056110614f, -0.007008695f, -0.0128360065f,
- -0.081917055f, 0.01551344f, 0.015213302f, -0.007311612f,
- 0.05132362f, 0.021465233f, -0.006402508f, -0.0059901825f,
- -0.14641468f, -0.010065595f, -0.08414735f, -0.0012903676f,
- -0.0074289045f, -0.0064615724f, -0.015104476f, -0.010063922f,
- -0.12964018f, -0.006686189f, 0.011695206f, -0.011013127f,
- 0.010575832f, 0.0020245458f, 0.0026200518f, 0.032540176f,
- 0.003625749f, -0.025884308f, 0.009879514f, -0.0033081162f,
- -0.005065944f, -0.14476047f, 0.022136912f, -0.002530654f,
- -0.002933526f, -0.011140939f, -0.0038555388f, 0.04427877f,
- 0.025654098f, -0.021689415f, -0.020404046f, -0.014721611f,
- -0.007580192f, 0.13336009f, -0.0061214482f, 0.37259483f,
- -0.21488674f, -0.007936289f, -0.004828332f, 0.27529117f,
- -0.0014411202f, 0.08794673f, -0.05525752f, -0.003399421f,
- 0.011741441f, 0.0036854558f, 0.011406933f, 0.0077857883f,
- 0.0003629323f, 0.0028523155f, 0.3107056f, -0.02287783f,
- 0.033571925f, -0.009670379f, -0.0003818231f, 0.0004068414f,
- -0.0100345295f, -0.009590073f, -0.13095485f, 0.058844235f,
- -0.020663427f, -0.045268036f, -0.03021923f, 0.002023659f,
- 0.31443503f, 0.0029122445f, -0.010092801f, -0.05844182f,
- 0.0037392292f, -0.0020694819f, -0.052120812f, 0.01733848f,
- 0.43239298f, 0.0065457984f, 0.5350353f, 0.0035280227f,
- -0.003272129f, 0.23856449f, -0.0031048954f, -0.048894346f,
- -0.0046571363f, -0.0016615292f, 0.01840911f, -0.015423428f,
- -0.0075298194f, 0.019263389f, -0.02158943f, -0.003838388f,
- 0.0009271357f, -0.019160112f, 0.4896474f, -0.0023514535f,
- 0.013768055f, -0.00066100847f, -0.0077187787f, -0.025395185f,
- 0.025288755f, 0.10791456f, 0.015047971f, -0.012628193f,
- 0.25311142f, 0.003550905f, -0.14708993f, 0.20202282f,
- -0.06922064f, 0.002551107f, 0.008169807f, -0.014593704f,
- 0.0018516734f, 0.012164124f, 0.2513742f, 0.0010325365f,
- 0.18029627f, 0.025871614f, 0.0024939566f, 0.01998438f,
- -0.53356516f, 0.10595117f, 0.011898587f, 0.019921547f,
- -0.013124627f, -0.086608045f, -0.050693024f, 0.0125225475f,
- -0.02749701f, 0.14926727f, 0.00025014632f, -0.007745109f,
- -0.1855302f, 0.013452292f, -0.08520929f, 0.0010013898f,
- 0.28377694f, -0.0029399034f, -0.062173877f, 0.0112691885f,
- -0.03165091f, 0.025032528f, 0.013232698f, 0.17995358f,
- 0.0047783502f, 0.0011682594f, 0.009342134f, -0.044827484f,
- 0.0639132f, -0.0062321997f, -0.1888438f, -0.14366636f,
- -0.00058022526f, 0.0014880075f, 0.007538069f, 0.39635003f,
- 0.0051545324f, 0.120345555f, 0.07826797f, 0.007383434f,
- -0.0585113f, 0.0039290576f, -0.0032862464f, -0.008178984f,
- -0.11957721f, 0.025394155f, 0.05283138f, 0.013507607f,
- -0.0065017585f, -0.61062783f, 0.011362503f, 0.034132693f,
- -0.0012649911f, 0.36889133f, -0.03220211f, 0.028481822f,
- 0.0016780441f, 0.0014241891f, 0.022412453f, -0.020245902f,
- 0.0141500365f, -0.082845785f, -0.010918618f, 0.0003642479f,
- 0.009643082f, -0.03604355f, -0.009614513f, -0.6338644f,
- 0.00486999f, 0.33294052f, -0.17708024f, 0.0025698815f,
- 0.13708024f, 0.014029667f, -0.0006262232f, -0.00366367f,
- 0.011157616f, 0.0019103787f, 0.0831352f, -0.0016815278f,
- -0.0072163767f, -0.0009124441f, 0.0034790577f, -0.0073664286f,
- 0.03304441f, -0.0017637144f, 0.08082414f, -0.017676711f,
- 0.238716f, 0.043989405f, 0.0028220047f, 0.009241451f,
- 0.006865225f, 0.0018633223f, 0.1691386f, -0.00069284154f,
- -0.009300744f, -0.012478698f, -0.0006683812f, 0.010799955f,
- 0.03186596f, 0.025236478f, -0.020551804f, 0.0076685324f,
- -0.014927445f, -0.0007155741f, 0.0002631947f, -0.021119663f,
- -0.001207664f, 0.008688434f, -0.0011878847f, 0.035407044f,
- 0.0050741094f, -0.14420341f, -0.014579646f, 0.0032487535f,
- -0.009180867f, 0.010900409f, -0.004036282f, 0.32494313f,
- -0.019443704f, 0.014841825f, 0.021095986f, -0.00972278f,
- -0.0050655794f, 0.2120975f, 0.0070144287f, 0.0018029037f,
- -0.11115355f, -0.002796129f, -0.18154022f, -0.31551698f,
- -0.0059147943f, -0.027428815f, -0.061175413f, 0.0018324045f,
- 0.00367732f, -0.01150888f, -0.018727235f, -0.0023337386f,
- 0.00018144638f, 0.016664675f, -0.30317304f, 0.04597282f,
- 0.004429688f, 0.010131467f, 0.0032301187f, -0.019059274f,
- 0.01359044f, 0.0048805983f, 0.25822005f, -0.23306525f,
- 0.008514639f, 0.025613608f, 0.11378684f, -0.00015990538f,
- -0.06480074f, 0.005902124f, -0.012772496f, -0.009453209f,
- 0.0010650166f, -0.015452951f, 0.035634607f, -0.03063299f,
- -0.22496934f, -0.016106421f, -0.33158076f, 0.0017262864f,
- 0.0001631451f, -0.071298085f, 0.0009297655f, 0.009157621f,
- 0.0029171396f, -0.009348481f, -0.0006619979f, 0.01217502f,
- -0.0031919782f, -0.012124728f, -0.02703068f, -0.015745256f,
- -0.0045029293f, 0.017389897f, -0.86599755f, 0.026634132f,
- 0.3589113f, 0.009476986f, 0.02241392f, 0.013314966f,
- -0.038952123f, -0.038607705f, -0.014234417f, 0.0073916013f,
- -0.03756792f, 0.016648075f, 0.3237459f, -0.43159613f,
- 0.010020967f, -0.0048384084f, -0.018005835f, 0.012636984f,
- -0.013308724f, -0.028613893f, 0.3065154f, 9.9992634e-05f,
- -0.04670672f, -0.020910034f, -0.0064397915f, 0.0107502295f,
- -0.10920006f, 0.32084304f, -0.036403958f, -0.039720528f,
- 0.06358221f, -0.10726618f, 0.049015734f, -0.017028015f,
- 0.034877077f, -0.32702005f, -0.0048129493f, 0.019383905f,
- 0.19869669f, -0.017754337f, 0.5344908f, 0.010233092f,
- 0.43050054f, -0.0061382633f, -0.054953426f, -0.12260817f,
- -0.0038797362f, -0.018807199f, 0.044052355f, -0.19286534f,
- 0.001138032f, -0.0048736045f, -0.019611964f, -0.0952867f,
- -0.26488337f, 0.02174691f, -0.0062355823f, 0.15164812f,
- -0.00031829675f, -0.0011479325f, -0.06664513f, 0.026802484f,
- 0.007816841f, 0.0750818f, 0.12917367f, -0.013249276f,
- -0.0431746f, -0.007763326f, -0.011974043f, 0.041756976f,
- -0.07877458f, -0.020832704f, 0.004361724f, -0.0022367362f,
- -0.0029798641f, -0.05914613f, -0.016119696f, -0.005043481f,
- -0.0023723505f, -0.67268354f, 0.01232139f, -0.00676664f,
- -0.009651564f, -0.018627876f, 0.057651423f, -0.095442794f,
- -0.010289831f, -0.06505942f, -0.046386424f, -0.0019737612f,
- -0.06830946f, 0.038855303f, 0.024465023f, -0.26304373f,
- -0.003152338f, 0.04631653f, -0.023282558f, 0.015030831f,
- -0.025278218f, -0.025541222f, 0.031791925f, -0.0018204666f,
- -0.009585629f, -0.0019222201f, 0.11369815f, -0.0018028842f,
- 0.025413688f, -0.0059443135f, 0.0059589203f, 0.0057377564f,
- -0.11493137f, 0.028461248f, 0.06744362f, 0.03666239f,
- -0.27276972f, 0.048834562f, 0.05993834f, -0.008340366f,
- -0.19026822f, -0.0068540345f, 0.063633636f, -0.0023424134f,
- 0.014875286f, 0.0052112634f, -0.00072043814f, -0.007253588f,
- 0.41100875f, -0.0113448985f, 0.064771466f, -0.016506549f,
- 0.0327144f, 0.0006753721f, 0.0012039553f, 0.01770613f,
- -0.0022043486f, -0.013549918f, -0.0044671404f, 0.039195728f,
- -0.004293427f, 0.061669536f, 0.03617243f, -0.003965661f,
- 0.0020034672f, -0.0024052362f, 0.004476415f, 0.77706444f,
- -0.037971303f, -0.034339983f, -0.025392577f, 0.00035122145f,
- 0.009856201f, 0.03936984f, -0.01243664f, 0.078576565f,
- -0.10936636f, -0.0024796722f, -0.008224704f, -0.044820845f,
- 0.010393085f, -0.0049911076f, -0.052360956f, -0.0016068751f,
- 0.039954342f, -0.0023811234f, -0.01380181f, 0.028726378f,
- -5.7773286e-05f, -0.000359588f, 0.020362578f, 0.041940507f,
- -0.029393302f, -0.017177004f, 0.00073381263f, 0.029836204f,
- -0.020618897f, -0.04028839f, -0.4827657f, 0.16151641f,
- 0.008539648f, 0.016188767f, 0.0044054585f, -0.00061201624f,
- -0.23161575f, -0.00954077f, 0.04617495f, 0.0127908f,
- -0.008837874f, -0.003315659f, 0.012809802f, -0.061551817f,
- 0.0721287f, -0.022094179f, 0.12557973f, -0.009067152f,
- 0.015056609f, -0.34677264f, -0.0011077767f, -0.054539606f,
- -0.0024175302f, -0.0027661591f, 0.0027561805f, -0.021937244f,
- 0.00571063f, 0.028569257f, 0.09794999f, 0.016488865f,
- 0.0028544634f, 0.002921935f, -0.021370977f, -0.0033801019f,
- 0.12027839f, 0.001383238f, -0.028697928f, 0.011540793f,
- 0.022805389f, -0.03160213f, 0.020530121f, -0.006412654f,
- -0.107322685f, -0.013737646f, -0.43041113f, 0.23743339f,
- 0.037755333f, -0.0012100626f, 0.0024678987f, 0.0039998726f,
- 0.00042600292f, 0.018347498f, 0.8169149f, -0.0039799623f,
- -0.21084826f, 0.031769913f, 0.0028372481f, -0.04448604f,
- -0.19282436f, -0.05229668f, -0.01064249f, 0.005795422f,
- -0.03109593f, 0.16537222f, 0.0011220499f, 0.0006479493f,
- -0.0042911693f, 0.09050834f, -0.005733661f, 0.0017842819f,
- -0.570817f, 0.010209406f, -0.081355266f, 0.01097861f,
- -0.2526856f, -0.0021405742f, -0.018947609f, 0.0415122f,
- 0.0065651773f, 0.025914993f, -0.07262057f, 0.048399154f,
- 0.0033508579f, -0.00228041f, 0.0010281156f, 0.023830222f,
- 0.09828875f, 0.296076f, 0.29620665f, 0.1970912f,
- -0.00045814776f, -0.00049944205f, -0.03163951f, -0.085807055f,
- 0.017489146f, 0.16911681f, -0.14616503f, 0.005031023f,
- 0.013917868f, 0.0061225314f, 0.00046357207f, 0.0017520469f,
- 0.109170586f, 0.018863106f, 0.023850938f, 0.010267159f,
- 0.0010615401f, 0.084480755f, 0.017191438f, 0.036079336f,
- 0.005011137f, 0.35968602f, 0.02479556f, 0.01059267f,
- 4.1966156e-05f, 0.001386054f, -0.0012114618f, -0.05003679f,
- 0.032750547f, 0.08564513f, -0.0068742f, -0.00046163643f,
- 0.02535201f, 0.0076581887f, 0.012972378f, 0.45613074f,
- 0.01218629f, -0.2682581f, 0.19389704f, -0.05924248f,
- 0.062321577f, 0.004300781f, 0.1168421f, -0.00399685f,
- 0.012883129f, -0.0006976051f, -0.23403785f, 0.00027484322f,
- 0.002789782f, 0.005522331f, -0.005800934f, -0.004380488f,
- 0.011217865f, 0.0037874226f, -0.037134826f, -0.00020276148f,
- -0.0153968455f, -0.041410957f, -0.022684049f, -0.0021517125f,
- 0.053107534f, -0.001071622f, -0.0006545866f, -0.003368078f,
- -0.0010152233f, 0.01162633f, 0.009396059f, 0.008040582f,
- 0.21971424f, 0.032730684f, -0.030342268f, 0.0032203111f,
- 0.005328149f, 0.0026300524f, -0.004235179f, -0.035444103f,
- -0.00077691145f, 0.0027028122f, 0.033803888f, 0.27827156f,
- -0.00029587507f, -0.1785111f, -0.00072173506f, -0.0020600588f,
- 0.0021206636f, 0.009137556f, -0.004938581f, 0.5045667f,
- 0.049689516f, 0.005959943f, 0.116801985f, -0.002292698f,
- 0.016267398f, 0.46500427f, 0.005039246f, 0.05495305f,
- -0.30964285f, -0.002372382f, 0.05359269f, 0.0097970655f,
- 0.0066331495f, 0.098229036f, -0.07573792f, 0.00040341457f,
- -0.04197822f, -0.01817161f, 0.006176352f, 0.0170036f,
- -0.00035683106f, 0.016124142f, 0.28245118f, -0.04404235f,
- -0.013561954f, 0.023802446f, 0.0035190429f, -0.006370893f,
- 0.0028825358f, 0.007743412f, 0.053726f, 0.20132479f,
- 0.0082088355f, -0.044040084f, -0.031394657f, 0.0019277952f,
- -0.38079742f, -0.006728126f, -0.0023369205f, 0.10838989f,
- 0.005277344f, -0.0035822697f, 0.040965658f, 0.047052804f,
- 0.015394161f, 0.003219381f, -0.2747629f, 0.0060144006f,
- 0.011354513f, 0.12086592f, -0.00037047773f, 0.043652005f,
- -0.0003831059f, 0.02614042f, 0.07519322f, 0.017685689f,
- 0.015642561f, 0.020278662f, 0.0027950332f, -0.002981058f,
- -0.012494497f, -0.023923816f, -0.38396564f, 0.006294659f,
- -0.18444358f, -0.003624503f, -0.0056417068f, -0.030693654f,
- -0.026340514f, 0.016772127f, -0.0009543529f, -0.019884694f,
- -0.076968655f, 0.0009542626f, -0.34282786f, -0.19628233f,
- -0.03730307f, 0.0050094393f, -0.009078399f, -0.0217989f,
- -0.0055141742f, -0.022464648f, -0.11685133f, -0.000699938f,
- -0.05888287f, -0.008901728f, 0.0064610797f, -0.025766857f,
- -0.32362357f, -0.42521688f, -0.017067f, -0.01950764f,
- -0.04130647f, 0.0444004f, -0.034847442f, 0.0023262454f,
- -0.007834062f, -0.2544876f, -4.5747074e-05f, 0.00086940476f,
- 0.27868783f, -0.0019278397f, -0.078703746f, -0.0075209145f,
- -0.009362409f, -0.019787183f, -0.063257925f, -0.01838606f,
- -0.037069928f, -0.020875301f, -0.04648865f, -0.12264692f,
- -0.006219089f, -0.0015053286f, -0.017708391f, -0.101536565f,
- 0.24202462f, 0.033910014f, 0.09868182f, -0.09119968f,
- -0.0009098568f, 0.0017785133f, -0.05337649f, 0.5480865f,
- -0.007471295f, 0.19944738f, -0.008797428f, -0.021116935f,
- -0.018702772f, 0.004295019f, -0.0016085147f, -0.0007066409f,
- -0.14810981f, 0.011310273f, -0.11042797f, 0.006376798f,
- -0.01005504f, 0.59272134f, -0.034528576f, -0.0073815375f,
- -0.0017352519f, -0.01971116f, -0.04001074f, 0.014319444f,
- -0.006895958f, -0.004442674f, -0.03036422f, -0.11209119f,
- 0.0056550456f, 0.099951044f, 0.009306829f, 0.0017577398f,
- -0.007144829f, -0.02623039f, 0.02068893f, -0.10621496f,
- 0.004937214f, -0.14405479f, 0.18012047f, -0.0656584f,
- -0.013878709f, -0.021133542f, -0.0053167893f, -0.0051148264f,
- 0.00084969297f, -0.0025530988f, 0.24046768f, 0.0052695666f,
- -0.0068318527f, -0.0059383158f, -0.009257533f, -0.018522616f,
- -0.015619957f, -0.004367441f, -0.0037197298f, -0.013457486f,
- -0.04646877f, -0.014090631f, -0.033495523f, 0.008855692f,
- -0.030754289f, 0.0051403143f, -0.2234601f, 0.0013084363f,
- -0.020810334f, -0.014247288f, 0.008416849f, 0.003529566f,
- 0.33316356f, -0.006975067f, 0.00013312332f, -0.012678868f,
- -0.0010016524f, -0.0010974753f, -0.0011592857f, 0.06779106f,
- 0.0007305228f, -0.020519467f, -9.349506e-05f, -0.40444058f,
- 0.0045231157f, 0.17413053f, 0.019963274f, -0.00076487515f,
- -0.009344516f, -0.0034233513f, -0.00957272f, 0.48754525f,
- -0.029904598f, -0.023701333f, 0.03600286f, -0.021938581f,
- -0.014874908f, 0.07481829f, -0.0057395124f, 0.36641917f,
- -0.28409976f, -0.0014782107f, 0.10970067f, -0.35484785f,
- -0.007613675f, 0.019052131f, -0.0620915f, -8.8470035e-05f,
- -0.029538821f, -0.018284513f, -0.0017728552f, -0.016330779f,
- -4.154758e-05f, -0.038305115f, -0.15057258f, 0.016761953f,
- 0.05840484f, -0.007831616f, -0.0014970729f, -0.015804598f,
- -0.020965636f, -0.017861817f, 0.40913957f, -0.021664934f,
- 0.010242152f, 0.0016961783f, -0.08272803f, -0.0012173448f,
- 0.51129293f, -0.0058283163f, 0.0049080797f, -0.026286125f,
- -0.0018120571f, -0.023369243f, 0.059298243f, -0.08029194f,
- -0.06471998f, -0.012870396f, -0.02804763f, -0.00657257f,
- -0.007195605f, 0.0536011f, 0.001594393f, -0.00866717f,
- 0.0020024516f, -0.034086306f, 0.006119105f, -0.012675584f,
- -0.009573678f, -0.007929478f, -0.019348005f, -0.0009375029f,
- 0.011562661f, -0.00062094233f, -0.4717693f, -0.024697492f,
- 0.03673982f, -0.0075352862f, 0.02406155f, 0.019266559f,
- 0.00063258293f, 0.05732134f, -0.0015363714f, 0.006225242f,
- 0.099601746f, 0.043601003f, -0.17451152f, 0.13265704f,
- -0.026639147f, 0.0018137756f, 0.0022433319f, 0.020466795f,
- 0.0017429834f, 0.016099278f, -0.26763088f, 0.00037561284f,
- 0.25781983f, -0.001641212f, -0.001338505f, -0.011055222f,
- 0.09581357f, 0.57014936f, 0.070332624f, 0.013769681f,
- 0.036408007f, 0.116753705f, 0.012003658f, 0.019684082f,
- 0.015884036f, 0.16427435f, 0.0044162166f, -0.0032872164f,
- -0.06131702f, 0.021435002f, 0.3761729f, 0.0142280655f,
- 0.2418223f, 0.021092333f, -0.001464927f, 0.021536356f,
- -0.022076547f, -0.001160334f, -0.032350235f, 0.10309485f,
- 0.004749799f, 0.00209303f, 0.011875772f, -0.026551351f,
- 0.07774148f, -0.06289727f, 0.07924012f, 0.04664392f,
- -0.0019499883f, -2.7897155e-05f, -0.014573405f, -0.6148482f,
- 0.016392177f, 0.13012771f, 0.105953425f, 0.008480525f,
- 0.02352931f, 0.002030955f, 0.0008044095f, -0.020984791f,
- 0.14628376f, 0.03354652f, 0.23432325f, -0.0046900515f,
- 0.01053582f, 0.28216296f, -0.007999511f, 0.024524864f,
- -0.0013513585f, 0.45804423f, 0.021548916f, -0.015848136f,
- 0.017818918f, 0.01210373f, 0.0396365f, 0.00019389563f,
- 0.025078528f, -0.057512302f, 0.06586244f, -0.0019405126f,
- 0.04072496f, -0.012576949f, 0.020991024f, 0.06237144f,
- 0.010646197f, 0.27444336f, 0.30305338f, 0.02498521f,
- 0.12367411f, 0.017488193f, 0.072822206f, 0.009179488f,
- 0.0022607362f, -0.0015646177f, 0.11503916f, 0.001179295f,
- -0.005945665f, 0.009045825f, 0.047904156f, 0.0069871764f,
- 0.02004828f, -0.0026295409f, -0.025203861f, 0.019818522f,
- 0.1590905f, 0.020200409f, -0.0084758615f, -0.0015432155f,
- 2.1846408e-05f, 0.00011922567f, 0.12454531f, 0.0034565271f,
- -0.0046565523f, -0.0016191169f, 0.035163287f, 0.0017965607f,
- 0.04504518f, -0.010889597f, 0.0028556213f, 0.0126320915f,
- -0.019686144f, -0.00067127467f, -0.0016250487f, 0.035737224f,
- -0.001169358f, 0.010878393f, -0.020852346f, -0.20824033f,
- 0.0010298978f, 0.30703887f, -0.027235286f, 0.00290201f,
- -0.0031114223f, 0.009746449f, 0.0066014268f, 0.118894145f,
- -0.02575129f, 0.020421948f, -0.01086647f, -0.0063777184f,
- -0.0059606745f, -0.5202239f, 0.016749479f, -0.3295264f,
- -0.3393113f, 0.0038090895f, -0.019801246f, -0.13779442f,
- 8.171431e-06f, 0.10111231f, 0.073135346f, -0.0016453455f,
- -0.017740967f, 0.011467862f, 0.0009498311f, 0.118537426f,
- -0.0014312838f, -0.010739526f, -0.36682492f, -0.0363117f,
- 0.068019226f, 0.0015445084f, -0.001615632f, -0.004827495f,
- 0.014889027f, 0.018269518f, -0.22793087f, -0.11720138f,
- 0.010066515f, 0.009771524f, -0.04309021f, -0.00041587738f,
- -0.05209083f, 0.0017297961f, 0.016056871f, -0.004185413f,
- 0.00062701275f, 0.0094968155f, 0.029773382f, 0.05718741f,
- -0.02138533f, 0.0012180402f, -0.48276916f, -0.0003902057f,
- 0.00027061012f, 0.54938555f, -0.0004272493f, 0.02649873f,
- 0.0020846634f, 0.0044970387f, 0.0019260378f, -0.0017292271f,
- 0.0052216654f, -0.02042648f, -0.05848524f, -0.0058957716f,
- -0.005722869f, -0.0002776696f, 0.028434176f, -0.01685565f,
- 0.23432592f, -0.005954775f, -0.04255613f, -0.009775196f,
- 0.016292045f, 0.48292089f, 0.0076485486f, -0.0039385757f,
- -0.07183655f, 0.0076872692f, 0.12356705f, 0.2304264f,
- -0.019076083f, -0.0015653463f, -0.0004589796f, -0.006687174f,
- 0.0005842844f, -0.013095616f, 0.044299077f, 0.0012283965f,
- -0.00501674f, 0.01770253f, -0.0026786407f, 0.05305785f,
- -0.16857925f, -0.19237337f, 0.020670649f, -0.008261809f,
- -0.021198122f, -0.015304969f, -0.018978583f, 0.010030929f,
- -0.034713384f, 0.23567377f, -0.0016548878f, -0.0074323886f,
- 0.32444328f, -0.010449246f, 0.022968207f, 0.0041608363f,
- -0.17698833f, 0.0152102765f, 0.047628336f, 0.007131262f,
- 0.05350828f, -0.0106328735f, -0.047571674f, 0.06544252f,
- 0.008340365f, -0.0003943877f, -0.0115702f, -0.020571144f,
- 0.005814791f, -0.07741055f, -0.008286585f, 0.0670827f,
- 0.0005651681f, -0.0010774717f, 0.005778671f, 0.28569937f,
- 0.0048563294f, -0.14902906f, 0.003984577f, -0.009901008f,
- -0.007905976f, -0.00078609f, -0.0029984347f, 0.001072629f,
- 0.8117797f, -0.014230644f, 0.04717084f, -0.0042834277f,
- -0.009652235f, 0.049787614f, -0.036273163f, -0.040282156f,
- -0.0009469492f, 0.49683753f, -0.00032156403f, 0.0027558669f,
- 0.0060606175f, -0.0047117546f, -0.06630365f, 0.039475873f,
- 0.0077425726f, -0.07441144f, -0.015054599f, -0.0018818292f,
- -0.0065316246f, -7.08604e-06f, -0.018963002f, 0.10521813f,
- -0.0074250284f, -0.6948486f, -0.05616396f, 0.062496256f,
- -0.30207267f, -0.00684071f, -0.07499042f, 0.0042546056f,
- 0.0066719144f, 0.002126698f, -0.056342892f, -0.0032628342f,
- -0.0045359316f, -0.01851014f, -0.009388876f, -0.010798668f,
- -0.008280905f, -0.00785727f, -0.07791482f, -0.023785882f,
- -0.16924982f, 0.016120875f, -0.019435877f, 0.0024213572f,
- 0.07831863f, -0.00068205665f, -0.22390555f, -0.0054138754f,
- -0.029618088f, -0.00465396f, -0.01617898f, -0.003563431f,
- -0.13558748f, -0.044085596f, -0.04231016f, -0.0054322584f,
- -0.013103733f, -0.00039812966f, 0.0016921426f, -0.015187187f,
- -0.0012378712f, 0.0047959434f, -0.021110773f, 0.3110938f,
- -0.0030423743f, -0.4122058f, -0.031336345f, -0.003260671f,
- -0.0046851924f, 0.016112082f, -0.00846849f, -0.2838832f,
- -0.010011679f, 0.001018117f, 0.04389785f, -0.0020592727f,
- -0.017402232f, -0.2593915f, -0.010662479f, 0.15315521f,
- 0.023649555f, 0.0024042046f, 0.07734607f, -0.109515585f,
- -0.012063191f, -0.077545494f, 0.017163267f, -0.0012465798f,
- 0.013808174f, 0.0012766763f, -0.0131989615f, -0.06032059f,
- -0.00045077605f, -0.02128143f, -0.5344877f, -0.005798304f,
- -0.02409159f, 0.017148452f, -0.0002689915f, -0.0052385493f,
- -0.0073243063f, -0.018810244f, 0.058626547f, -0.095387645f,
- 0.0058125844f, 0.030689577f, -0.011210697f, -0.0009345939f,
- -0.051036414f, -0.007011037f, 0.002816208f, 0.10966406f,
- -0.00056955725f, -0.020177508f, -0.019419562f, 0.097391054f,
- -0.10784627f, 0.002681133f, -0.16466501f, 0.0019955398f,
- -0.010517222f, 0.1377479f, -0.000484512f, 0.0063518235f,
- -0.0015500084f, 0.0019134837f, -0.02375407f, -0.0013646968f,
- -0.014562224f, -0.0014961301f, 0.16341977f, -0.013552216f,
- 0.020457393f, 0.006932875f, -0.2362371f, 0.0014366335f,
- -0.49809623f, 0.013422054f, 0.016074073f, 0.06427303f,
- 0.029254783f, -0.46720567f, 0.00842657f, 0.0098386435f,
- -0.04392909f, 0.035496343f, 0.013254038f, 0.07729318f,
- 0.13209456f, -0.0052294256f, 0.00494639f, 0.033924863f,
- 0.0017733815f, 0.018068127f, 0.17698447f, -5.406646e-05f,
- -0.008276221f, 0.03588008f, -0.007480866f, -0.012916301f,
- -0.43693855f, 0.13729084f, 0.015819438f, 0.015658638f,
- 0.022908168f, 0.10347492f, 0.054267533f, 0.025121875f,
- 0.068007864f, -0.048004985f, -0.003559833f, 0.01397655f,
- -0.0441338f, 0.026574789f, 0.053290047f, 0.019363571f,
- 0.33590943f, 0.0595692f, -0.037761163f, 0.018463315f,
- 0.09600112f, 0.009551654f, -0.0036013199f, 0.06343283f,
- 0.021166483f, -0.00085013715f, 0.011618206f, 0.18148363f,
- -0.020195957f, 0.1963729f, 0.16859053f, 0.21508361f,
- 0.0011520617f, -0.002874141f, -0.026342766f, 0.5264651f,
- 0.024835832f, 0.18417934f, 0.15969989f, 0.009961862f,
- 0.06401687f, -0.002082779f, -0.0056432844f, -0.015955385f,
- 0.47394973f, 0.032256514f, -0.10703006f, -0.005475858f,
- 0.008903209f, -0.012185635f, 0.03558249f, 0.033746492f,
- -0.003592953f, -0.18853977f, 0.062096734f, 0.019468628f,
- 0.0071971654f, 0.04045719f, 0.053455275f, 0.02781632f,
- 0.05010866f, -0.026751557f, 0.031619154f, -0.0045718537f,
- 0.060114574f, 0.0240395f, 0.02173857f, 0.047605682f,
- 0.015224951f, 0.2479488f, -0.008307166f, 0.027132824f,
- -0.030741718f, 0.014855251f, 0.15802172f, 0.0012735148f,
- 0.021776918f, -0.0016272468f, -0.31567955f, -0.00529068f,
- 0.020323904f, 0.008719695f, 0.02139729f, 0.014760292f,
- 0.026825167f, -0.0007350138f, 0.052878615f, 0.05333334f,
- -0.2555375f, -0.027264245f, -0.022180019f, -0.00616657f,
- -0.055323824f, -0.006191737f, -0.037445128f, -0.0030640627f,
- 0.02925575f, 0.014275459f, 0.030754054f, -0.0075252084f,
- 0.105160594f, 0.013915748f, -0.024178043f, 0.013965228f,
- 0.019548796f, 4.432267e-05f, 0.0006204228f, -0.020848554f,
- -0.0016303705f, 0.0023091715f, -0.0025162462f, 0.25517774f,
- -0.004449876f, -0.05413146f, 0.016161261f, -6.0246184e-05f,
- -0.0015026747f, 0.038002294f, 0.0070119253f, -0.17562646f,
- 0.068438426f, 0.005306528f, 0.12216254f, -0.011674816f,
- 0.020814708f, -0.8383529f, 0.003186526f, 0.11741204f,
- 0.048426665f, -0.0007877518f, 0.035863135f, 0.19083361f,
- 0.014457508f, 0.056300286f, -0.100193664f, -9.555329e-06f,
- -0.009224633f, -0.007912692f, 0.042794794f, 0.070281304f,
- -0.0019539646f, 0.052358262f, -0.14463265f, -0.02650309f,
- 0.018622477f, 0.029698867f, -0.0016586932f, -0.02508787f,
- 0.015776714f, 0.020716667f, -0.10328947f, 0.38705355f,
- 0.024394939f, 0.00012362798f, -0.03792675f, -0.0007364249f,
- -0.03598467f, 0.007527723f, 0.039674837f, 0.0030834733f,
- -0.007165256f, 0.04005102f, 0.15452035f, 0.24110669f,
- 0.15991884f, 0.0096865315f, -0.18452752f, -0.0064381687f,
- -0.008642179f, -0.111357376f, -0.002647415f, 0.02310848f,
- -0.0023896617f, 0.058383558f, 0.032397367f, 0.0026597374f,
- 0.020920394f, 0.020598872f, -0.098935015f, -0.0011847694f,
- -0.004884279f, -0.015770013f, -0.22955917f, 0.010370734f,
- -0.04681267f, -0.0052474015f, 0.028454201f, -0.0030382744f,
- -0.014472241f, -0.067807764f, -0.0035376824f, -0.014764397f,
- 0.016703539f, -0.0067509217f, 0.34030256f, -0.012488516f,
- 0.030534608f, -0.0012278388f, 0.0033136064f, -0.006860353f,
- -0.0030304857f, 0.0074701174f, -0.072997965f, 0.0005982911f,
- 0.39502504f, -0.0035228718f, 0.00062152726f, -0.04517574f,
- -0.14322495f, -0.14182703f, -0.019366309f, 0.010931986f,
- -0.031041332f, 0.024068065f, -0.019680176f, -0.010098414f,
- 0.016626766f, 0.022155534f, 0.0063097957f, -0.0022589392f,
- -0.20988293f, 0.0039889393f, 0.23281953f, -0.009301461f,
- 0.19260928f, -0.018242184f, -0.06346172f, 0.012343415f,
- -0.05904406f, -0.02491583f, 0.00087663933f, 0.0049942057f,
- -0.005174611f, 0.0012268106f, 0.004315632f, -0.048857525f,
- 0.2192021f, 0.056353506f, 0.017801728f, 0.07669271f,
- 0.0016237544f, -0.0020084202f, 0.021854566f, -0.04417534f,
- -0.016080854f, -0.010192832f, -0.08992729f, -0.0015198734f,
- -0.021116735f, -0.006974668f, 0.0040396242f, -0.018784206f,
- 0.55356586f, 0.0064937323f, 0.08472239f, 0.0010438089f,
- -0.002428134f, -0.4339075f, 0.028355109f, -0.0038406472f,
- -0.0023880892f, -0.3731911f, -0.0096364515f, 0.02290464f,
- -0.007388783f, 0.05560856f, -0.00078522967f, -0.037640937f,
- -0.0069617247f, 0.100078166f, 0.06781406f, 0.0003712195f,
- 0.037164353f, -0.029844765f, -0.011371137f, 0.06888713f,
- -0.004827453f, 0.17726259f, -0.2068564f, -0.010974484f,
- 0.013741716f, 0.005619607f, -0.124933235f, -0.00075477076f,
- -0.0028292614f, 0.0010215124f, 0.02350617f, -0.0014995635f,
- -0.0016031775f, 0.0076032f, -0.024744332f, -0.011803193f,
- 0.025827996f, 0.0019285111f, -0.00013969862f, -0.008703024f,
- -0.04496269f, 0.017980227f, -0.012637804f, 0.0008732736f,
- 0.040382966f, -0.00057359616f, 0.17534016f, -0.0010253708f,
- 0.008369878f, -0.013915369f, -0.016220307f, -0.0058914525f,
- 0.077394605f, 0.018997854f, -0.015860785f, 0.00519558f,
- -0.010453582f, 0.0006034836f, 0.003681141f, 0.038889676f,
- 0.0012074219f, -0.014354479f, 0.029267445f, 0.061514296f,
- -0.00166985f, 0.12959683f, 0.0043081995f, 0.0004458189f,
- -0.0039472533f, -0.008412493f, -0.0060884818f, -0.45549408f,
- -0.007696398f, 0.004829011f, -0.028014375f, -0.014355755f,
- 0.0004417034f, 0.60584265f, 0.0038967438f, -0.0483294f,
- -0.76846486f, 0.0010288553f, 0.36978185f, -0.15605538f,
- -0.0074547613f, 0.017415226f, -0.073268555f, 0.00032372322f,
- -0.07336632f, -0.008477587f, -0.010553991f, 0.013847317f,
- 0.0010352886f, -0.0446765f, -0.08655515f, -0.06498072f,
- 0.12195721f, -0.004439953f, 0.0016156995f, -0.03068431f,
- 0.001697117f, 0.012786101f, 0.13320495f, -0.21548447f,
- 0.00062454777f, -0.0649966f, -0.047007136f, 0.00080766465f,
- 0.24163502f, 0.0012220873f, -0.0077649453f, 0.16005434f,
- -0.00025912264f, 0.0017606363f, -0.026697334f, -0.06552443f,
- 0.11136251f, 0.005951438f, -0.08377984f, 0.0010971152f,
- -0.0063849534f, 0.044352166f, -0.00031282697f, 0.049855564f,
- -0.00011328995f, -0.0033356166f, 0.08768355f, -0.0035190494f,
- 0.001646553f, -0.017112657f, -0.060826212f, -0.019416992f,
- 0.0100354785f, 0.016652834f, -0.10735794f, 0.03276791f,
- -0.29876837f, 0.029744904f, -0.011199349f, 0.0324099f,
- 0.019227762f, -0.1876335f, -0.0033221245f, 0.008962686f,
- 0.046289988f, -0.014850157f, -0.1892744f, -0.2120264f,
- 0.052224927f, -0.006296977f, 0.007749775f, 0.024455125f,
- -0.002563932f, 0.009481969f, -0.781261f, 0.00020620551f,
- 0.28422165f, 0.006440108f, -0.00529989f, -0.0005352015f,
- -0.01872089f, -0.5109815f, -0.06082088f, 0.008533254f,
- -0.01434092f, 0.010322057f, 0.045461394f, 0.010790861f,
- 0.03135785f, -0.17866276f, 0.0006896232f, 0.007449053f,
- -0.07305189f, 0.01794009f, -0.34170258f, 0.021806f,
- 0.16871032f, 0.038978204f, -0.04189359f, -0.033604614f,
- 0.10250199f, 0.007338012f, 0.059345454f, 0.18764268f,
- 0.0034284173f, 0.00043095992f, 0.010685933f, -0.024904547f,
- -0.21506773f, -0.0801793f, 0.05381674f, 0.065168664f,
- 0.0009572024f, -0.0019988841f, -0.014136126f, -0.21129449f,
- 0.024685485f, 0.08674521f, 0.03268239f, 0.008240819f,
- 0.15116876f, -0.0030653432f, 0.0016060312f, 0.02090981f,
- 0.48793313f, -0.0053286212f, 0.0130376965f, 0.0048749777f,
- 0.0050190836f, 0.09409083f, 0.027330292f, 0.06361287f,
- 0.0013834654f, -0.050375417f, 0.03311648f, -0.011270253f,
- 0.0125173265f, 0.036465216f, -0.00030385563f, -0.030350573f,
- 0.0072369594f, -0.08120768f, -0.010680576f, -0.0026767666f,
- 0.012810718f, 0.024666203f, 0.017653441f, -0.6032463f,
- 0.004438308f, -0.0982112f, 0.051519748f, -0.020754209f,
- -0.0192981f, 0.009253281f, 0.26864713f, -0.0020422044f,
- 0.0050939284f, -0.0005042748f, -0.06617159f, -0.005489871f,
- -0.0030449105f, 0.0034293947f, 0.027800027f, 0.019521724f,
- -0.05063748f, 0.029208602f, 0.06079091f, 0.036147367f,
- 0.14837524f, -0.009777976f, -0.004486094f, 0.0015689355f,
- -0.018036637f, -0.0062064235f, 0.061222196f, 0.00095582905f,
- 0.024099968f, 0.015627703f, 0.015691537f, -0.00096316385f,
- -0.41386315f, 0.013057633f, -0.014526963f, 0.007994271f,
- -0.0050279126f, -0.001477965f, -0.002181496f, 0.0025979422f,
- -0.001269903f, 0.022691607f, 0.023280548f, 0.021913199f,
- -0.0027721983f, 0.04691457f, -0.015292149f, -0.0034641752f,
- 0.0073864367f, 0.02164408f, 0.016395641f, 0.58878714f,
- 0.04226501f, 0.0078172125f, 0.19623582f, 0.023696894f,
- 0.00012741819f, 0.10117151f, 0.002406229f, 0.38168707f,
- -0.18972257f, -0.0016499637f, -0.14477858f, 0.101947f,
- 0.008698817f, -0.036808476f, -0.0024785425f, -0.00019441004f,
- 0.02029656f, 0.003109385f, 0.020726778f, -0.086374566f,
- -0.0022546647f, 0.04710873f, 0.44050974f, 0.00022780364f,
- -0.08773801f, 0.008963137f, -0.00012219693f, 0.011175341f,
- 0.0069338665f, 0.016088447f, -0.08084576f, 0.08725679f,
- 0.005026773f, 0.017583953f, 0.0059502707f, -0.00065332354f,
- -0.27749094f, 0.005678844f, 0.0168253f, -0.013816483f,
- -0.003440502f, 0.033971258f, 0.078243926f, 0.15662354f,
- 0.0054533863f, 0.008680111f, 0.48217463f, -0.0037665353f,
- -0.0040720976f, -0.35622293f, -0.0026244165f, -0.01767542f,
- -0.0054334286f, 0.027834062f, -0.032737844f, 0.017816303f,
- 0.00465625f, -0.007302088f, 0.079253614f, -0.015651368f,
- 0.003162613f, 0.004473438f, -0.34017888f, -0.0052412325f,
- 0.019703193f, 0.00044294298f, -0.0002665933f, 0.00011660684f,
- 0.010204403f, -0.2569448f, 0.0020964905f, 0.009905751f,
- 0.00489786f, -0.0029552267f, -0.33534804f, -0.17691356f,
- 0.02556815f, 0.00214512f, 0.006932142f, 0.006464499f,
- 0.00464415f, 0.0023674655f, -0.21243699f, -0.0002033969f,
- -0.0030121722f, 0.013954917f, 0.0030370564f, 0.005793f,
- 0.74274737f, 0.1315128f, -0.013624065f, 0.0038311437f,
- 0.026561446f, 0.039578628f, 0.016078636f, 0.00035539342f,
- -0.027189588f, -0.12934947f, -0.0007276371f, -0.0034665994f,
- -0.013901043f, 0.010409774f, 0.14253815f, -0.0002527824f,
- 0.019891134f, -0.0014977519f, 0.05952933f, -0.009781003f,
- 0.008431491f, 0.012092025f, 0.058597267f, -0.06332802f,
- -0.009835684f, -0.002959004f, 0.0023283244f, 0.14310245f,
- -0.046713013f, 0.10218007f, 0.079740584f, -0.005241003f,
- -0.0017103516f, 0.0020760586f, -0.033062544f, 0.19565734f,
- -0.0044403886f, 0.023544123f, 0.024866438f, 0.0022162294f,
- -0.08045017f, 0.0063239713f, -0.0013492159f, 0.03069482f,
- 0.14431904f, 0.026352277f, -0.045283318f, 0.0048693675f,
- 0.0033668415f, -0.36438918f, -0.020219969f, -0.0113832895f,
- 0.0009722217f, 0.115586534f, -0.014994921f, -0.00835197f,
- -0.005064075f, -0.00029837343f, 0.011179535f, 0.06992249f,
- 0.011430547f, 0.091566995f, -0.0017744275f, 0.0011447493f,
- -0.0004153484f, 0.0041487897f, -0.023727547f, 0.14033777f,
- -0.008097506f, 0.031360622f, 0.016252128f, 0.0070561087f,
- -0.17001593f, 0.0055916063f, 0.015908178f, 0.0012722388f,
- 0.0011893861f, -0.0043640076f, 0.27459708f, -0.00045822895f,
- -0.0064938325f, -0.00095533347f, 0.0032590006f, 0.019637646f,
- -0.036003184f, 0.003215775f, 0.050564367f, 0.020152532f,
- 0.16275519f, 0.015833441f, -0.009477657f, -1.2642698e-06f,
- -0.034204844f, 0.0026981344f, -0.4139561f, -0.0011559023f,
- 0.014928441f, 0.0010513978f, 0.009525017f, 0.003632875f,
- -0.157664f, 0.009231312f, 0.025574878f, 0.0011792249f,
- 0.013346703f, 0.00047973054f, -0.0031733934f, 0.012365637f,
- 0.00063502864f, 0.008447273f, 0.009932371f, -0.5570526f,
- 0.0009627006f, -0.6431699f, 0.009640629f, 0.0042136074f,
- -0.0027242263f, 0.030863462f, 2.6263233e-05f, -0.09464275f,
- -0.02727053f, 0.009112373f, 0.088853315f, 0.0009394877f,
- -0.0007086781f, 0.3943242f, -0.0020834021f, 0.034295294f,
- 0.2196229f, 0.0011314598f, 0.13407351f, -0.56554234f,
- -0.003764177f, -0.017293615f, -0.012958005f, -0.00019413336f,
- 0.052446228f, -0.0067494228f, -0.004782503f, -0.025797874f,
- -0.0010300662f, -0.016772568f, -0.25327f, 0.0253204f,
- -0.019148633f, 0.0076526916f, -0.001415223f, 0.01927911f,
- 0.0049545467f, -0.0033993977f, -0.23963727f, 0.28985676f,
- -0.009085048f, 0.009505194f, 0.08766062f, -0.0014900714f,
- -0.029095406f, 0.0026967453f, -0.010397897f, 0.20159817f,
- -0.008966704f, 0.017285116f, -0.102201454f, 0.088873476f,
- 0.36376512f, -0.00834789f, 0.011456555f, -0.0066220835f,
- -0.0026169564f, -0.50728923f, 0.0011505231f, 0.025299143f,
- -2.9115146e-05f, 0.016770162f, -0.022858663f, 0.002732734f,
- -0.006175194f, 0.010823357f, 0.056109622f, 0.0052440427f,
- -0.014746073f, 0.0013854788f, 0.29651204f, -0.0075350185f,
- 0.066577405f, 0.0014192081f, -0.077284284f, -0.012950485f,
- 0.011901826f, -0.023430934f, -0.0018512799f, 0.0073715155f,
- 0.018944047f, -0.01876982f, 0.29865816f, 0.05597788f,
- -0.04305615f, -0.0029399956f, -0.002567612f, -0.010511995f,
- 0.0006531626f, -0.010761794f, 0.21614872f, -0.0023877572f,
- -0.24055399f, -0.0015850652f, -0.0028684898f, 0.010322423f,
- 0.4866326f, 0.56707567f, -0.017810404f, -0.021989938f,
- -0.033261094f, 0.02548806f, 0.0030278973f, -0.02252723f,
- -0.06884322f, -0.07485799f, -0.007305996f, -0.00677046f,
- 0.055871505f, -0.024409566f, -0.07727162f, -0.0035206003f,
- -0.027633408f, -0.013921181f, 0.024002826f, -0.015358601f,
- -0.030524006f, -0.014340548f, 0.025990374f, 0.17819813f,
- -0.0009855184f, 0.0021179784f, -0.0046765f, -0.2529165f,
- -0.023415472f, -0.013728794f, 0.05770779f, 0.16642746f,
- 0.0014812318f, -0.00042522597f, 0.009211946f, 0.35140237f,
- -0.012319047f, 0.14019522f, -0.087226845f, 2.8762019e-05f,
- 0.0065063443f, -0.0018922468f, -0.00043600862f, 0.011231263f,
- -0.19830406f, -0.038737547f, -0.045134373f, -0.0043671415f,
- 0.0022259098f, 0.0547479f, -0.017825177f, 0.08492959f,
- 0.006752322f, 0.3939003f, -0.012476243f, -0.0055531673f,
- -0.011252823f, -0.07350485f, -0.08172309f, 0.01099818f,
- -0.0066257888f, 0.0014122134f, -0.07072019f, 0.00031386118f,
- -0.06078973f, 0.010116073f, -0.019975118f, -0.27458093f,
- -0.013644762f, 0.07290055f, -0.13790749f, -0.0036955785f,
- 0.21522583f, -0.00952483f, 0.14932999f, -0.0021464755f,
- -0.004126876f, 0.0015734138f, 0.059728034f, -0.001773916f,
- -0.008947851f, -0.0033455505f, -0.04216518f, 0.006493015f,
- -0.03578306f, -0.0027425718f, 0.008240991f, -0.012021842f,
- 0.24075739f, 0.0009174034f, 0.008666543f, -0.002443655f,
- 0.055930406f, -0.0035013263f, -0.050224237f, -0.000484408f,
- -0.039868053f, -0.0044554016f, -0.026171295f, -0.0051152576f,
- 0.33557937f, -0.0089852335f, 0.015713567f, -0.008984928f,
- 0.005964639f, 0.0007317045f, -0.004496794f, -0.030566571f,
- 0.0007439167f, -0.0035405264f, -0.006067697f, -0.036912337f,
- -0.0017198141f, -0.10409869f, 0.016254347f, -0.001458174f,
- 0.0038408884f, 0.014206565f, -0.0029393842f, -0.29602754f,
- 0.016553856f, -0.01963655f, 0.010483202f, 0.0053416477f,
- 0.006102137f, -0.5506027f, -0.0051003355f, 0.20911835f,
- -0.7962323f, 0.0046723792f, -0.19651909f, 0.03944086f,
- -0.0076264427f, 0.035109133f, 0.057018347f, 0.001736338f,
- 0.036896452f, -0.013897554f, 0.015571781f, -0.024102498f,
- -0.00048148245f, -0.0068731345f, 0.23727782f, 0.034994557f,
- -0.05226614f, -0.0060732914f, 0.0023389459f, 0.028016564f,
- -0.005780398f, -0.008691483f, 0.101019084f, 0.10331845f,
- -0.008094913f, 0.038160536f, 0.091712f, 0.0015060563f,
- 0.050610073f, -0.009979896f, -0.009813974f, -0.058865268f,
- 0.0026283537f, -0.015465692f, -0.025477683f, -0.038095083f,
- 0.070075296f, -0.021297708f, 0.29567608f, 0.005360054f,
- 0.0015895689f, -0.36359784f, 0.00053232047f, -0.055798177f,
- -0.002507846f, -0.008576445f, -0.04014592f, -0.013704031f,
- 0.0018182815f, 0.008552673f, 0.026047787f, 0.015220382f,
- -0.011888914f, -0.004020304f, 0.03156723f, 0.023939041f,
- -0.021711195f, 0.0017497774f, 0.0902611f, -0.020339131f,
- -0.014936974f, -0.20401034f, 0.01712438f, 0.0057471995f,
- -0.0036797402f, 0.002370096f, -0.055319667f, 0.10160963f,
- -0.045418836f, 0.043006487f, 0.003601884f, -0.014274456f,
- 0.00313937f, -0.008963475f, 0.10607426f, 0.0047380873f,
- 0.14265329f, 0.017785748f, 0.030688547f, -0.064831205f,
- 0.017606493f, -0.015891543f, 0.021584256f, -0.009171981f,
- -0.041967772f, 0.19774455f, -0.011534073f, 0.013074754f,
- -0.03763871f, -0.02266482f, 0.008792921f, 0.0013819874f,
- -0.006522574f, 0.06681147f, -0.00042233602f, 0.011680611f,
- -0.043089956f, -0.046224553f, -0.01972913f, 0.09908764f,
- -0.09395833f, 0.03328499f, 0.0092848f, -0.016312141f,
- 0.012733165f, 0.0014537866f, 0.0002443548f, -0.012937319f,
- 0.00833468f, 0.058255717f, -0.026087658f, -0.034154627f,
- -0.0032972791f, 0.021335978f, 0.016454708f, 0.044640236f,
- 0.016197387f, -0.011098404f, 0.0015756945f, -0.0063062133f,
- -0.034448836f, 0.024719652f, 0.0013331125f, -0.008183154f,
- 0.20156504f, 0.06814519f, -0.0030475925f, 0.031710673f,
- 0.0039443313f, 0.045676388f, 0.10732945f, -0.006610289f,
- 0.0056557204f, -0.04590124f, -0.03489313f, 0.042107955f,
- 0.004813647f, 0.116037205f, 0.020173833f, -0.022271398f,
- 0.037683893f, 0.05172359f, 0.13246903f, 0.016920578f,
- 0.15957956f, -0.00724237f, 0.0073576444f, 0.048715264f,
- 0.0022429647f, 0.056749158f, 0.11649395f, -0.11455337f,
- 0.02884937f, -0.005584053f, -0.028782649f, 0.022135431f,
- 0.017557215f, 0.0031383492f, -0.11581665f, 0.022639953f,
- 0.014777534f, 0.0011413208f, 0.04730307f, -0.007901044f,
- 0.07551854f, 0.01627414f, 0.1640773f, -0.021733444f,
- 0.053239413f, 0.00609931f, 0.0060249176f, 0.03276201f,
- 0.1489482f, 0.040699378f, 0.076398246f, 0.006807781f,
- 0.0009895952f, -0.009421383f, 0.043114625f, 0.02832061f,
- -0.09537657f, 0.09406766f, 0.027903637f, 0.00018876979f,
- 0.018300962f, 0.0012231722f, 0.007806071f, 0.020807015f,
- 0.0077506443f, 0.018218575f, 0.02966895f, 0.03069512f,
- 0.019415863f, 0.018651037f, 0.043031137f, 0.006959412f,
- 0.012735382f, 0.02409433f, 0.009902837f, -0.06254633f,
- -0.06524882f, -0.009807274f, -0.06146772f, 0.023476738f,
- -0.013091064f, 0.059362873f, 0.0028081613f, 0.03363885f,
- -0.08580345f, 0.019170625f, 0.027890505f, -0.078981854f,
- 0.009110368f, -0.0007287681f, -0.07360115f, 0.024376443f,
- -0.016980104f, 0.0149620185f, -0.048842005f, 0.009342385f,
- 0.008368171f, -0.0056183306f, -0.0966521f, -0.030650103f,
- 0.029156175f, 0.006337148f, 0.009962917f, 0.021547763f,
- 0.004620606f, -0.00975654f, 0.044757456f, -0.06869526f,
- 0.0068549234f, -0.08798773f, -0.008917972f, 0.0036135323f,
- 0.06625765f, 0.019687412f, 0.011808033f, -0.022966038f,
- 0.0035804198f, -0.005013502f, -0.0031829874f, -0.09260652f,
- 0.0058551873f, 0.0031825237f, -0.007757804f, 0.0044835326f,
- 0.019890243f, 0.040189706f, 0.015973303f, 0.13963968f,
- 0.029132701f, -0.035513915f, 0.0047561643f, 0.01549754f,
- -0.009618935f, 0.0069606765f, 0.02377715f, 0.023591977f,
- 0.0065416167f, 0.008132208f, 0.01326984f, -0.055892162f,
- 0.022920648f, -0.021821592f, -0.10270732f, 0.015754778f,
- -0.02673631f, 0.11336852f, -0.07182895f, -0.00083184656f,
- -0.023137378f, -0.026027666f, 0.024038311f, -0.057353847f,
- 0.037468474f, -0.09521488f, -0.007324955f, 0.015480151f,
- -0.0067967298f, 0.001555334f, -0.05110799f, -0.017895177f,
- -0.08051851f, -0.0684899f, -0.08170281f, 0.049321927f,
- -0.00011361922f, 0.016896822f, -0.02778845f, 0.004594322f,
- 0.023566877f, -0.13987605f, 0.019806953f, -0.049308073f,
- 0.031205174f, -0.014118268f, -0.01758851f, -0.017499192f,
- 0.0044444916f, -0.08773083f, -0.009554782f, -0.045404416f,
- 0.02160231f, 0.018905275f, -0.012720214f, -0.075985484f,
- 0.080127165f, -0.08647408f, -0.008076537f, 0.0015016827f,
- -0.04734897f, -0.008966122f, -0.002364163f, 0.023337334f,
- -0.007322753f, -0.017131088f, 0.029714815f, 0.020130383f,
- 0.004384627f, -0.041134894f, -0.006438118f, -0.027869603f,
- -0.06837809f, 0.007180524f, -0.014124481f, 0.0076230937f,
- 0.01014456f, -0.06903538f, -0.006391234f, 0.0048367213f,
- -0.08414919f, -0.057366293f, -0.0022359255f, -0.078314506f,
- -0.0064672185f, -0.031716753f, -0.074779734f, -0.010028109f,
- -0.014685086f, 0.030519882f, 0.015909249f, -0.021563938f,
- -0.022550533f, -0.04539074f, -0.068031915f, 0.026894735f,
- -0.077733025f, -0.03412835f, -0.085484765f, -0.037707713f,
- -0.101796106f, 0.017102674f, -0.036462076f, -0.0385416f,
- -0.023189122f, -0.019400321f, -0.09355599f, 0.08790226f,
- -0.0029255203f, 0.004279291f, 0.0184892f, -0.026736436f,
- -0.0644612f, -0.0143270185f, 0.055933107f, -0.048779834f,
- -0.04087217f, -0.0079208575f, -0.07833539f, 0.007574672f,
- -0.052318927f, -0.052489206f, -0.085993305f, 0.01731345f,
- -0.021617327f, -0.001020787f, -0.05325072f, -0.07738959f,
- -0.116405025f, -0.09222787f, -0.039534323f, -0.009336529f,
- 0.002018299f, 0.008976073f, -0.0848976f, -0.07568818f,
- 0.08595911f, -0.086222f, -0.021345304f, -0.005692063f,
- -0.02219811f, -0.0070032384f, -0.024294961f, -0.02052105f,
- -0.019033559f, -0.061519563f, -0.06722928f, -0.01721853f,
- -0.048297394f, 0.0025424084f, -0.061190188f, -0.022835657f,
- -0.020742442f, -0.08977117f, -0.012341092f, 0.043356497f,
- 0.039190017f, 0.0028831905f, 0.04927138f, -0.056963596f,
- 0.013305328f, -0.024736946f, -0.011674114f, -0.0048764287f,
- 0.032553308f, -0.026580898f, -0.021131566f, 0.03074518f,
- -0.012930463f, 0.0026121852f, 0.03633941f, -0.033268217f,
- 0.017323053f, -0.02110249f, 0.030391358f, 0.005031176f,
- -0.022956798f, -0.0071341232f, 0.060871616f, 0.027930923f,
- -0.015184871f, -0.04666716f, -0.018096447f, -0.024465766f,
- -0.011142142f, 0.0055313148f, -0.025555287f, 0.03051317f,
- -0.04258143f, 0.063916095f, 0.004064899f, -0.012018572f,
- -0.020938257f, -0.01909063f, -0.06580387f, 0.014408756f,
- -0.012020113f, 0.0047221202f, -0.028014943f, 0.060760807f,
- 0.008745592f, -0.0071545034f, 0.0018731601f, -0.014481752f,
- -0.025577346f, -0.016192172f, -0.032562368f, -0.09597641f,
- -0.07293861f, 0.016857887f, -0.005792315f, -0.05103856f,
- 0.004658438f, -0.015768811f, -0.00199993f, -0.030211631f,
- -0.002600054f, -0.0042607416f, -0.007917908f, 0.028474167f,
- -0.012004475f, 0.011540464f, 0.051562995f, -0.008126214f,
- 0.014311869f, -0.054833744f, 0.0369373f, -0.00040462567f,
- 0.013296601f, 0.014269294f, -0.011428554f, 0.028200088f,
- -0.019773956f, 0.048462592f, 0.0036760631f, -0.008307551f,
- 0.0030873735f, -0.0017683872f, 0.025258573f, 0.00863043f,
- 0.038906213f, 0.035203964f, 0.041817322f, -0.01950099f,
- -0.00042852416f, -0.007289989f, 0.014659293f, -0.0027341046f,
- -0.010529462f, 0.06920739f, -0.011253162f, 0.02514046f,
- -0.016206505f, 0.008379632f, 0.008848354f, 0.008155408f,
- -0.00079378946f, 0.043831244f, 0.00628977f, 0.023162501f,
- -0.009761039f, -0.0069137374f, 0.009011385f, 0.037048712f,
- -0.035232544f, 0.04402657f, 0.0047863037f, 0.00032822543f,
- 0.023833947f, 0.0038952862f, 7.940183e-06f, -0.010087355f,
- 0.00456638f, 0.008559601f, -0.01492566f, -0.008976767f,
- -0.0032208166f, 0.021099625f, 0.0035688397f, 0.013485934f,
- 0.035011787f, -0.0030298738f, 0.008533431f, -0.0048075197f,
- -0.0035232946f, 0.03535635f, 0.0033412625f, -0.0018266868f,
- 0.040506363f, 0.028331071f, 0.0013011734f, 0.03985858f,
- 0.0026187976f, 0.016606025f, 0.036048677f, 0.006001677f,
- 0.0064301807f, -0.014443134f, -0.007673616f, 0.011335043f,
- 0.011621583f, 0.021678299f, 0.035080794f, -0.01287535f,
- 0.03941718f, 0.014431548f, 0.040993493f, 0.019638943f,
- 0.049310528f, -0.009441483f, 0.01896253f, 0.019043136f,
- 0.012229059f, 0.01034216f, 0.04720456f, -0.037033454f,
- 0.0011966178f, -0.0025043888f, -0.0044121603f, 0.0130588f,
- 0.03309057f, 0.006354099f, -0.025116332f, 0.024811886f,
- 0.019209972f, 0.0028619284f, 0.039441537f, -0.0044350913f,
- 0.0255262f, 0.02689451f, 0.04307162f, -0.009086844f,
- 0.010792242f, 0.0036790695f, 0.027791342f, 0.039283764f,
- 0.057062443f, 0.04698086f, 0.018915882f, 0.0045453464f,
- -0.0024623042f, -0.004582968f, 0.042972594f, 0.038770866f,
- -0.042918492f, 0.042403128f, 0.009181754f, 0.002219724f,
- 0.010032486f, 0.0035616276f, 0.012544867f, 0.013216979f,
- 0.009910171f, 0.03165922f, 0.03424989f, 0.008746047f,
- 0.02465262f, -0.0012721173f, 0.0293989f, 0.010741023f,
- 0.010448483f, 0.04530525f, 0.006411856f, -0.02129951f,
- -0.016334474f, -0.0013701759f, -0.02093842f, 0.02921294f,
- -0.008255211f, 0.0111762965f, 0.0048595504f, 0.0017987386f,
- -0.014321122f, 0.013369893f, 0.011507022f, -0.013721402f,
- 0.0060615307f, -2.2820133e-05f, -0.013584964f, 0.016760908f,
- -0.0059589264f, 0.01091609f, -0.012996184f, -0.001193319f,
- 0.011758389f, 0.004764292f, -0.029973697f, -0.010684709f,
- 0.008852233f, 0.02443979f, 0.008971987f, 0.011952134f,
- 0.004316354f, -0.0037034778f, 0.014384863f, -0.012627914f,
- 0.021223672f, -0.026904581f, -0.0011328073f, 0.0064195707f,
- 0.009801844f, 0.00860491f, 0.032613374f, -0.006212554f,
- 0.005791606f, -0.0035643058f, 0.014862956f, -0.027984917f,
- -0.0034727587f, 0.0042986316f, -0.00024682868f, 0.0069556255f,
- 0.012599349f, 0.0067637614f, 0.01625441f, 0.046136905f,
- 0.03767902f, -0.0067268154f, 0.003831191f, 0.026476134f,
- -0.0034305535f, 0.0068441983f, 0.000679926f, 0.013955177f,
- -0.0055390573f, 0.010929194f, 0.0662119f, -0.053493347f,
- 0.014243869f, -0.030600222f, -0.04106259f, 0.0013622558f,
- -0.059132285f, -0.094204396f, -0.085607305f, 0.010491809f,
- -0.03832661f, -0.03839295f, -0.03453522f, 0.045935623f,
- 0.0027635065f, -0.089474134f, -0.007716071f, 0.009730152f,
- -0.004564788f, -0.0027976267f, 0.06288752f, -0.017278844f,
- 0.067244925f, -0.08155541f, -0.08468575f, -0.011105388f,
- 0.027201794f, 0.0036687825f, -0.015275873f, -0.0036307354f,
- -0.018175788f, 0.042175792f, 0.024899084f, -0.058266554f,
- 0.0045747715f, -0.053932305f, -0.016672956f, -0.017992916f,
- 0.00027070395f, -0.046864074f, -0.014924279f, -0.0541156f,
- -0.022362914f, -0.033014752f, -0.045683168f, 0.011755385f,
- 0.00021279432f, -0.088198066f, 0.00144228f, -0.018126113f,
- -0.0535623f, -0.0061347703f, 0.0023501986f, 0.016248742f,
- 0.00027211275f, 0.0534985f, 0.012542377f, -0.0136912875f,
- 0.008598721f, -0.037521236f, 0.013358875f, 0.0149429245f,
- -0.082999036f, -0.005637727f, -0.022454541f, 0.009506016f,
- -0.03022441f, -0.07318291f, -0.008760197f, -0.0010492767f,
- 0.14033592f, 0.0007421561f, -0.0045650457f, -0.07782362f,
- -0.0023058478f, 0.010989768f, 0.029068926f, -0.02393187f,
- -0.012741208f, -0.012261403f, -0.0141933635f, 0.022522748f,
- -0.029999383f, 0.08612825f, -0.07957986f, 0.010839133f,
- -0.068281576f, 0.023285132f, 0.04321195f, -0.039219476f,
- 0.05227454f, 0.025862297f, -0.042872317f, 0.009882027f,
- -0.030051947f, 0.044937175f, 0.011783125f, -0.018051578f,
- 0.032214675f, 0.00064058934f, -0.012866848f, -0.0070586777f,
- -0.0741958f, -0.011403764f, -0.06646276f, -0.0455534f,
- -0.033237346f, -0.00257222f, -0.060537294f, 0.005017973f,
- 0.017647242f, -0.0581678f, 0.08310134f, 0.0039236755f,
- 0.043704253f, 0.0074283606f, -0.07406284f, -0.07518937f,
- 0.017001666f, -0.08840735f, 0.044595804f, -0.004502464f,
- 0.011913416f, 0.004992686f, -0.07338118f, -0.07972776f,
- 0.007992856f, -0.0082387095f, 0.008905438f, -0.0061207614f,
- -0.0020364774f, -0.007224656f, -0.025457704f, -0.0040091244f,
- -0.020794362f, -0.0699814f, -0.06309776f, 0.01990749f,
- -0.04835191f, 0.031071324f, -0.030263852f, -0.020677473f,
- -0.014492759f, -0.10220677f, -0.0057417783f, -0.013855232f,
- -0.026288014f, -0.008584529f, -0.0069554676f, -0.056154706f,
- 0.01776573f, 0.038633976f, -0.011151473f, 0.04888354f,
- -0.06281345f, -0.014582541f, 0.008200791f, -0.055152506f,
- -0.0032142876f, 0.0019296915f, -0.040707693f, -0.019282913f,
- 0.005555318f, -0.0087712165f, -0.016971579f, 0.01987995f,
- -0.024387326f, -0.0184672f, -0.028943725f, 0.007180194f,
- 0.015898405f, -0.06302958f, -0.0126003185f, -0.006892129f,
- -0.007088552f, 0.0011114691f, 0.019914953f, -0.04534366f,
- -0.05082997f, -0.013176327f, -0.0026413852f, -0.01619865f,
- 0.059621625f, 0.0012182946f, -0.07643057f, -0.008604931f,
- -0.014800419f, 0.0049328743f, -0.045851514f, -0.026126876f,
- 0.02272361f, -0.0048062485f, -0.0073844665f, -0.017986238f,
- -0.009875991f, 0.03329637f, -0.02851466f, 0.037159517f,
- -0.07568096f, -0.020851444f, -0.0024914087f, -0.058793027f,
- 0.0061971066f, -0.0061054444f, 0.031150086f, -0.009543884f,
- 0.003353553f, 0.0055629266f, -0.018560946f, 0.018859876f,
- 0.01162821f, 0.012581368f, 0.00058671815f, 0.009314839f,
- 0.02645461f, 0.060832437f, 0.034067545f, 0.0061699026f,
- 0.016486892f, 0.009436308f, 0.023574479f, -0.029870529f,
- 0.015633343f, 0.029082289f, 0.0010796143f, 0.008940817f,
- 0.00578324f, 0.01573655f, -0.034127068f, 0.013852121f,
- -0.036079098f, 0.02895279f, 0.02893603f, -0.0002063352f,
- -0.0035106563f, -0.003428487f, -0.00026085533f, 0.005157836f,
- 0.011901379f, -0.045662828f, 0.013316687f, 0.021218715f,
- 0.016492598f, 0.017123258f, 0.0031356227f, 0.020684008f,
- 0.0021257629f, 0.010270925f, 0.004106588f, 0.019687055f,
- 0.015745653f, 0.0113076605f, 0.015804257f, -0.019337134f,
- 0.0046312064f, 0.031001672f, 0.0010650428f, 0.008978989f,
- 0.023568438f, 0.013559539f, 0.011870357f, -0.011062227f,
- -0.002388213f, -0.023240726f, 0.0005062402f, 0.008839324f,
- 0.009499234f, 0.006613025f, -0.0032184047f, -0.011997997f,
- 0.03082099f, -5.8600577e-05f, 0.0017160984f, 0.01103242f,
- 0.013592874f, 0.025101945f, 0.0030530912f, 0.0048998357f,
- -0.06912432f, -0.009666979f, 0.007260485f, 0.027076736f,
- 0.006606448f, -0.011711793f, -0.017385133f, 0.009392487f,
- 0.009050917f, 0.011882331f, 0.022655541f, -0.015026642f,
- 0.007364944f, -0.04067362f, 0.024592193f, -0.0038437666f,
- 0.02453733f, 0.0021362556f, -0.03047378f, 0.005402783f,
- -0.040216763f, 0.010816291f, 0.021729633f, 0.0014371242f,
- 0.015806325f, -0.025871973f, -0.016353196f, 0.003181197f,
- -0.017430205f, 0.00437376f, -0.00717292f, 0.012711224f,
- 0.029097317f, 0.016786255f, 0.03627311f, 0.01367229f,
- 0.03086048f, 0.017181149f, 0.013149091f, 0.008952427f,
- -0.017973755f, 0.021886455f, -0.055598136f, 0.013261934f,
- -0.0114462925f, -0.007214845f, 0.026684739f, 0.025785914f,
- -0.02439944f, 0.028030185f, -0.016878134f, 0.004278906f,
- 0.0122849895f, 0.007261538f, 0.023333762f, 0.025162209f,
- 0.0116813695f, -0.0063929902f, 0.0060668173f, 0.007563857f,
- 0.015312125f, 0.0062307846f, 0.011705535f, -0.006839619f,
- 0.003680727f, 0.02580664f, 0.022585021f, -0.0013482493f,
- 0.016509684f, -0.008997562f, 0.020388884f, 0.017401729f,
- 0.007029291f, 0.043322917f, 0.0024383264f, 0.017007736f,
- 0.011977574f, 0.0043387f, 0.0004973798f, 0.020284599f,
- 0.024235258f, -0.022344477f, 0.0104438905f, 0.00058015884f,
- 0.034043945f, 0.0070398743f, -0.0008159997f, 0.032259632f,
- 0.010005264f, -0.004313288f, 0.017226653f, 0.005836365f,
- -0.0014899123f, 0.010548663f, 0.011050878f, -0.010475808f,
- 0.007757561f, 0.0063874847f, 0.03180814f, 0.004033517f,
- -0.010005477f, 0.023177631f, 0.008984026f, 0.0062922556f,
- 0.011474935f, 0.011419744f, -0.015052885f, 0.01957466f,
- 0.029619427f, 0.015781023f, 0.006067973f, 0.0012744464f,
- -0.021842184f, 0.0076307715f, 0.045692798f, 0.0043988377f,
- 0.0036489458f, 0.009412631f, 0.019497676f, 0.021958066f,
- -0.009323586f, 0.0058729495f, 0.0036790224f, 0.003238559f,
- 0.009674247f, -0.004741758f, 0.009698031f, -0.02778577f,
- 0.020629264f, 0.011030848f, 0.0003439892f, 0.018878607f,
- 0.02180817f, 0.019654064f, -0.008679661f, 0.013826063f,
- 0.003226028f, -0.0010874361f, -0.016736478f, -0.01863871f,
- 0.008517402f, -0.004943146f, -0.05229711f, 0.008659193f,
- 0.0010783747f, 0.10473628f, -0.018842746f, -0.0033231557f,
- -0.0067028445f, -0.0042742197f, 0.025351439f, -0.051751863f,
- 0.02524938f, -0.031571876f, -0.0025332966f, 0.0054103183f,
- -0.0031493264f, 0.0021155658f, -0.053377125f, -0.0063039484f,
- -0.072034605f, -0.017233517f, -0.024649667f, 0.029405577f,
- -0.009228286f, 0.008627437f, -0.013362604f, 0.005043612f,
- 0.019032927f, -0.10341733f, 0.0031466326f, -0.012313938f,
- 0.01808749f, 0.009569818f, -0.005321078f, -0.0056028655f,
- 0.00021474394f, -0.039755717f, -0.003110819f, -0.011110777f,
- 0.018260177f, 0.020585638f, 0.0018939152f, -0.05027453f,
- 0.04319142f, -0.026465755f, -0.00782061f, 0.004170825f,
- -0.012667652f, -0.005540046f, -0.00043042138f, 0.007592756f,
- -0.0054093497f, -0.030205276f, 0.014102726f, 0.014747958f,
- 0.00035959863f, -0.013619635f, -0.011847877f, -0.023339868f,
- -0.016591555f, 0.003815424f, -0.004525586f, 0.0017388879f,
- 0.012990406f, -0.020119637f, -0.0029088887f, 0.00061882945f,
- -0.10478237f, -0.036712397f, -0.0016965823f, -0.024642734f,
- -0.0022134725f, -0.025924955f, -0.05940502f, 0.0004146573f,
- -0.0022732315f, 0.02336928f, 0.011196923f, -0.022600995f,
- -0.00354808f, -0.060502477f, -0.017556855f, 0.011703127f,
- -0.028755965f, -0.022679769f, -0.06741168f, -0.011567775f,
- -0.08237796f, -0.000523253f, -0.014010517f, -0.032675706f,
- -0.008789221f, -0.029666144f, -0.061763775f, 0.05445522f,
- -0.015685676f, 0.0022968203f, 0.01117044f, -0.017087637f,
- -0.018483356f, -0.0056128856f, 0.05458029f, -0.015461544f,
- -0.013315829f, -0.003487268f, -0.02812459f, 0.0025651664f,
- -0.038747676f, -0.015054257f, -0.08448321f, 0.008010751f,
- -0.030352468f, -0.00813829f, -0.011411091f, -0.024739029f,
- -0.078884594f, -0.02977257f, -0.04087976f, -0.0048618643f,
- -0.00086726237f, 0.0018071294f, -0.02974773f, -0.0219246f,
- 0.051656075f, -0.05157389f, -0.012935705f, 0.00028057623f,
- -0.013026546f, -0.0051996256f, -0.010273896f, -0.016783418f,
- -0.0063503715f, -0.017672043f, -0.022866478f, -0.01961869f,
- -0.015182703f, -0.012051934f, -0.024432415f, -0.0066733737f,
- -0.010788063f, -0.022154996f, -0.007926005f, 0.030683069f,
- 0.02936597f, 0.004518806f, 0.029281983f, -0.020023199f,
- 0.00023988598f, -0.028265702f, -0.00037771894f, -0.024685947f,
- 0.038888227f, -0.014276191f, -0.01888089f, 0.038087558f,
- -0.007966506f, -0.0020402088f, 0.030150097f, -0.01697247f,
- 0.004707514f, -0.013429236f, 0.020355277f, -0.0075200805f,
- -0.006691141f, -0.0017160164f, 0.0491787f, 0.007896737f,
- -0.01820195f, -0.011348068f, -0.008319521f, -0.014350436f,
- -0.0012436077f, 0.0030995056f, -0.027315706f, 0.030385688f,
- -0.0120098675f, 0.0350462f, 0.0002827719f, -0.004110964f,
- -0.036822516f, -0.011487029f, -0.017839484f, 0.010272476f,
- -0.0024066404f, 0.004258175f, -0.0038813318f, 0.043621473f,
- -0.0017222784f, -0.0064919447f, 0.0024642807f, -0.0022849457f,
- -0.014531005f, -0.022557147f, -0.010109259f, -0.0719668f,
- -0.023049764f, 0.013995742f, -0.005991264f, -0.014917728f,
- -0.0013222356f, -0.007480457f, -0.013753673f, -0.012727955f,
- 0.00965826f, -0.0013243309f, -0.04826658f, 0.017259799f,
- 0.0056750877f, 0.016120883f, -0.023148129f, 0.010684373f,
- 0.039764646f, 0.15117176f, 0.038353235f, -0.006586068f,
- 0.023759393f, 0.018606005f, 0.04707319f, -0.07495304f,
- 0.022186419f, 0.026905097f, 0.0023840487f, 0.0041389493f,
- 0.0018102946f, 0.008000182f, -0.08575814f, 0.008299695f,
- -0.10588871f, 0.035097256f, 0.03046706f, 0.037090894f,
- -0.021690315f, 0.005528098f, -0.0029556982f, 0.006558387f,
- 0.030956296f, -0.12110258f, -0.003618646f, 0.024945427f,
- 0.018609243f, 0.038845703f, 0.0041667554f, 0.011249481f,
- 0.0039033438f, -0.007958594f, 0.008418936f, 0.023352472f,
- 0.034549702f, 0.039811786f, 0.034882747f, -0.05630324f,
- 0.04703426f, 0.03122171f, -0.0042113415f, 0.018443871f,
- 0.023203267f, 0.0048555224f, 0.00025251377f, -0.0027278408f,
- -0.004485145f, -0.056557637f, 0.0066680904f, 0.02486554f,
- -0.0012209562f, 0.00867821f, -0.013514721f, -0.029930672f,
- 0.0368195f, 0.008825126f, 0.011076925f, 0.00042535734f,
- 0.03391864f, 0.02714282f, 0.004719934f, 0.0059274277f,
- -0.17209442f, -0.034260437f, 0.005240197f, 0.02639472f,
- 9.624835e-05f, -0.028232634f, -0.06690716f, 0.016346093f,
- 0.0038756412f, 0.029575413f, 0.027823262f, -0.03284f,
- 0.012883217f, -0.101682074f, 0.032388087f, 0.0054218303f,
- 0.019020554f, -0.03719864f, -0.088659704f, 0.011596274f,
- -0.10690725f, -0.006067191f, 0.021760613f, -0.025999425f,
- 0.016858805f, -0.05187017f, -0.06418544f, 0.06475808f,
- -0.03079642f, 0.0032409246f, 0.019440465f, -0.003957976f,
- 0.03212515f, 0.00657933f, 0.093151785f, 0.01292812f,
- 0.013053384f, 0.0031534955f, 0.007979059f, 0.0032935315f,
- -0.047232952f, 0.023650208f, -0.1259202f, 0.011103866f,
- -0.047446024f, -0.006425545f, 0.037205644f, 0.024394464f,
- -0.08303669f, 0.027259639f, -0.059948288f, -3.7537244e-05f,
- -0.0044991137f, 0.0040680543f, 0.018121911f, 0.028491473f,
- 0.04354696f, -0.04190339f, -0.017228916f, 0.0034915805f,
- -0.0053560636f, 0.0047072074f, 0.0111831445f, -0.00807671f,
- 0.0071536656f, 0.029313447f, 0.019798143f, -0.023841988f,
- 0.01652442f, -0.024046948f, -0.00423676f, 0.008907893f,
- 0.0029324275f, 0.04359839f, -0.0008115798f, 0.039563652f,
- 0.04640474f, 0.009488742f, 0.033486597f, 0.01963485f,
- 0.0022759675f, -0.04996304f, 0.0045939637f, -0.03761875f,
- 0.07696637f, -0.00013648426f, -0.016614627f, 0.06882367f,
- -0.00089745934f, -0.00039831016f, 0.058399327f, -0.0005539605f,
- 0.006350717f, -0.00013205557f, 0.03430277f, -0.014349855f,
- 0.008870186f, 0.01340642f, 0.06454458f, 0.01360239f,
- -0.022140486f, 0.03134617f, 0.0031645447f, -0.005416379f,
- 0.0020735622f, 0.0057952036f, -0.0319437f, 0.05844574f,
- 0.026089814f, 0.05295713f, 0.007282509f, 0.0067970585f,
- -0.06223892f, -0.008916954f, 0.03827825f, 0.01625922f,
- 0.0058251745f, 0.0009307346f, 0.026692552f, 0.06073309f,
- -0.015394629f, 0.0029377495f, 0.00824306f, 0.006585087f,
- -0.0024746917f, -0.035073765f, 0.007110009f, -0.088810705f,
- 0.025860483f, 0.029658731f, -1.3053855e-05f, 0.02419455f,
- 0.005625279f, 0.002548419f, -0.026805926f, -0.00530075f,
- 0.0019487272f, -0.011883576f, -0.024643252f, 0.05070352f,
- -0.028170148f, 0.022385059f, 0.08661212f, -0.015540039f,
- 0.031717554f, -0.06882026f, 0.067721166f, -0.013888412f,
- 0.032618143f, 0.03119912f, -0.012503376f, 0.03327456f,
- -0.042297367f, 0.086147025f, 0.008301202f, -0.02073695f,
- 0.0021952237f, -0.012240517f, 0.022506297f, 0.011087386f,
- 0.036228344f, 0.06570313f, 0.07556459f, -0.010825327f,
- -0.013228903f, -0.0082777655f, 0.027729133f, -0.006225729f,
- -0.009425541f, 0.09857216f, -0.035924666f, 0.046177797f,
- -0.035591017f, 0.023942614f, 0.016882407f, 0.0051972214f,
- 0.00056618993f, 0.070223406f, 0.014874454f, 0.042564675f,
- -0.00791407f, 0.0039374894f, 0.031884026f, 0.05115638f,
- -0.035926644f, 0.07872583f, 0.006892722f, 0.008484217f,
- 0.040821344f, 0.0023499276f, -0.014119851f, -0.011661464f,
- 0.008114413f, 0.002701652f, -0.023927428f, -0.0062958915f,
- -0.015548103f, 0.04084797f, 0.004571493f, 0.01920211f,
- 0.06475856f, 0.0038242457f, 0.025773138f, -0.020141095f,
- 0.006822435f, 0.06389564f, 0.009132657f, -0.0003968699f,
- 0.03701939f, 0.04213839f, 0.001895304f, 0.070928656f,
- -0.0033164178f, 0.026667373f, 0.047762215f, 0.013953401f,
- 0.0036254677f, -0.021506587f, -0.0117377145f, 0.015764732f,
- 0.022995897f, 0.018104382f, 0.0674626f, -0.016050877f,
- 0.06995554f, -0.008752649f, 0.049438093f, 0.042177804f,
- 0.06533563f, -0.029354285f, 0.039498553f, 0.025684413f,
- 0.02677758f, 0.012432118f, 0.05945987f, -0.028173767f,
- 0.0041185953f, -0.0066566546f, 0.0131588075f, 0.012178643f,
- 0.061913237f, 0.0027528822f, -0.019493815f, 0.043257974f,
- 0.01581235f, -0.008887569f, 0.06742738f, -0.015192397f,
- 0.035624083f, 0.049028397f, 0.055486236f, -0.020150507f,
- 0.0020330765f, 0.012635732f, 0.056820635f, 0.06951451f,
- 0.07958431f, 0.084031574f, 0.014268403f, 0.0041978266f,
- -0.022848915f, -0.01039205f, 0.0742335f, 0.071006864f,
- -0.06554926f, 0.060830012f, -0.006515241f, -0.0031595947f,
- 0.0008488708f, 0.010327753f, 0.02666601f, 0.031946935f,
- 0.022650056f, 0.058989953f, 0.060109578f, 0.0049122865f,
- 0.044231124f, -0.0051522944f, 0.028792478f, 0.009852757f,
- 0.018707346f, 0.07541377f, 0.011772586f, -0.029800743f,
- -0.009670127f, -4.037717e-05f, -0.01684719f, 0.053928662f,
- -0.032798376f, 0.009770602f, -0.0016550405f, -0.014211915f,
- -0.0075543597f, 0.021778649f, 0.014281311f, -0.014918852f,
- 0.0026872526f, 0.0069043366f, 0.0015656821f, 0.029510941f,
- -0.0038762102f, 0.013340819f, -0.008604719f, 0.0021313708f,
- 0.021942718f, 0.016275076f, -0.048757795f, -0.0084398715f,
- 0.0148010915f, 0.050591215f, 0.011779464f, 0.0145963095f,
- -0.0062118513f, -0.01211679f, 0.025351152f, -0.00068567914f,
- 0.034546908f, -0.022794593f, 0.0008233622f, 0.019104868f,
- 0.004472528f, 0.0018459033f, 0.04936289f, -0.004383095f,
- 0.012311984f, -0.020589415f, 0.029971791f, -0.03170484f,
- -0.010666649f, 0.0082120225f, 0.0015492935f, 0.015121427f,
- 0.014740771f, -0.0038621603f, 0.025949469f, 0.0569342f,
- 0.07426999f, -0.0006366143f, 0.010291202f, 0.052693617f,
- -0.018796371f, -0.004103937f, -0.0052946336f, 0.0045923893f,
- -0.024945518f, 0.02624208f, -0.0071785194f, -0.0010294695f,
- 0.023708118f, -0.017896127f, 0.08172366f, 0.020973321f,
- 0.0026584514f, -0.009013193f, 0.0033080666f, 0.0029500914f,
- 0.098983206f, 0.066631116f, 0.018145578f, -0.0011174916f,
- 0.027978303f, -0.055648576f, -0.025131391f, 0.032237396f,
- 0.030647837f, 0.043807015f, -0.005629079f, 0.019316819f,
- 0.012052181f, -0.040062416f, -0.05674478f, -0.028640008f,
- 0.023976574f, 0.02279526f, 0.060950466f, 0.0048760856f,
- -0.033910718f, 0.014568193f, 0.039304018f, 0.011596883f,
- 0.031692054f, -0.01430615f, -0.03151974f, 0.03882119f,
- 0.008404224f, -0.008370781f, -0.038878255f, 0.043734405f,
- -0.005597831f, 0.020186637f, 0.154373f, -0.012262888f,
- -0.01400686f, -0.07167845f, -0.025344923f, -0.008601456f,
- 0.060912114f, 0.033149455f, 0.032649513f, -0.008720223f,
- 0.0055312915f, 0.03551613f, 0.04519464f, -0.01336394f,
- 0.0090468265f, -0.013700391f, 0.017263304f, 0.003966095f,
- 0.029369904f, 0.0005740124f, -0.01583961f, 0.045753617f,
- 0.028403552f, -0.0008622474f, -0.044553038f, -0.014164087f,
- 0.016430996f, -0.0077326796f, 0.019546842f, -0.037353877f,
- 0.007824029f, -0.01513098f, 0.015277253f, -0.033977628f,
- 0.02882594f, -0.0046107695f, 0.048700348f, 0.011197781f,
- 0.04180765f, 0.007573669f, -0.007996036f, -0.031918798f,
- 0.0008763262f, 0.029658692f, 0.0026086865f, -0.051380925f,
- 0.0052396934f, 0.039382607f, 0.13217086f, 0.047634076f,
- 0.025687763f, 0.009341071f, -0.0008004514f, 0.014870438f,
- 0.04487947f, 0.013567068f, -0.009217164f, 0.04662688f,
- 0.0017809824f, 0.026551018f, 0.030022098f, -0.010771655f,
- 0.09206449f, 0.02497673f, 0.04351562f, 0.047074195f,
- 0.026371114f, 0.029676083f, 0.04687042f, 0.0360241f,
- -0.012876297f, -0.015293528f, 0.01715006f, -0.047686026f,
- -0.023916004f, -0.06676791f, 0.027559662f, -0.009643466f,
- 0.0200089f, 0.020745471f, 0.10765068f, -0.04363031f,
- 0.014259204f, -0.03742854f, 0.021407098f, 0.016804531f,
- 0.026831372f, -0.000572376f, -0.0073520187f, 0.11275939f,
- -0.049390994f, -0.09120624f, -0.06289972f, 0.0071291975f,
- -0.04873263f, -0.0031719978f, 0.037531067f, 0.0155995535f,
- -0.07048156f, 0.06363638f, -0.00810571f, -0.00922338f,
- -0.0010561012f, -0.036901955f, 0.0136513375f, -0.09212502f,
- 0.05291203f, -0.005709146f, 0.021804258f, 0.057499703f,
- 0.015055209f, -0.005744907f, 0.012472864f, 0.0008730428f,
- 0.02755412f, 0.01272221f, 0.09425664f, 0.061149124f,
- -0.009152055f, 0.060836628f, -0.0012907978f, -0.030319655f,
- -0.025877666f, 0.043185733f, -0.019509885f, 0.0068675433f,
- -0.030841669f, 0.0015650996f, -0.03933981f, 0.022969028f,
- 0.01896595f, 0.013232956f, -0.005172346f, -0.009459294f,
- 0.055607077f, -0.014681269f, -0.0060923267f, -0.056390587f,
- 0.005770612f, 0.015175439f, 0.13809739f, -0.02164838f,
- -0.053826887f, 0.015040112f, 0.1001272f, -0.0047539235f,
- -0.060687177f, 0.058363985f, 0.003925395f, -0.054229364f,
- 0.031334486f, 0.03619109f, -0.0063002803f, 0.043536175f,
- -0.070917636f, -0.0038332304f, -0.020817975f, -0.07642295f,
- 0.0616289f, 0.035389695f, 0.020099297f, 0.057170115f,
- 0.03156768f, 0.01397264f, -0.027016178f, -0.074452326f,
- 0.030896345f, -0.02795951f, -0.06955153f, 0.05994862f,
- -0.0014020762f, 0.024469646f, -0.020816287f, 0.018967273f,
- 0.028504701f, 0.031512555f, -0.0137522835f, 0.008925793f,
- 0.083363995f, 0.012752125f, 0.059814658f, 0.044538964f,
- 0.07052792f, 0.087697834f, 0.0030050736f, 0.03244773f,
- -0.015163966f, -0.008794354f, -0.011955804f, -0.059394516f,
- -0.06549898f, -0.03417889f, 0.018845923f, 0.07134981f,
- 0.061254304f, 0.038244348f, 0.053122595f, 0.034793813f,
- 0.043979894f, 0.01841889f, 0.058139652f, 0.018501304f,
- 0.020830933f, 0.017303031f, -0.029994713f, 0.005268438f,
- -0.01707678f, 0.053674683f, -0.0454614f, 0.007980073f,
- -0.015421152f, -0.02395881f, -0.06485704f, 0.008960804f,
- 0.0019579818f, 0.04957805f, 0.0734189f, -0.08835373f,
- -0.025579723f, -0.008762127f, 0.06788668f, -0.009393407f,
- 0.037911884f, 0.036240295f, -0.04970598f, -0.023729218f,
- -0.004426037f, -0.021662002f, 0.035885125f, 0.06273307f,
- -0.012133435f, -0.00550301f, 0.07608901f, 0.05362885f,
- -0.040033218f, 0.009510956f, 0.009534067f, -0.0151299f,
- 0.04038754f, 0.012046966f, 0.019421104f, -0.046563394f,
- 0.10373068f, -0.023815239f, 0.060977053f, -0.0272931f,
- 0.03294856f, 0.0026158094f, -0.013344372f, 0.0332842f,
- 0.013529577f, 0.0061894096f, 0.022238936f, 0.0680638f,
- 0.018660866f, 0.027266158f, 0.02188686f, -0.07478118f,
- 0.01953727f, -0.0043005277f, 0.0071492125f, -0.03608549f,
- 0.008021571f, 0.06621995f, -0.06057762f, -0.051216833f,
- -0.009946435f, 0.048711456f, 0.03993107f, 0.007695542f,
- 0.015158603f, 0.04316979f, 0.03960755f, 0.06795127f,
- 0.005949035f, -0.055101164f, -0.080270976f, 0.057738736f,
- 0.0015101399f, -0.07381072f, -0.07340085f, -0.02429734f,
- 0.010680816f, 0.026784731f, -0.0061580883f, 0.045874987f,
- 0.045141816f, 0.020189207f, 0.016555946f, 0.0036732487f,
- -0.005581693f, 0.015771694f, -0.005872309f, 0.056763798f,
- -0.0067339176f, 0.050995104f, 0.038691893f, -0.01766047f,
- 0.06902826f, -0.031304777f, -0.0141376415f, -0.021005275f,
- 0.0024765492f, -0.014449506f, -0.03096148f, 0.045506727f,
- 0.00058529864f, -0.014393164f, -0.00015672705f, -0.013790176f,
- -0.043976407f, 0.06917222f, -0.082727015f, -0.036968615f,
- 0.057680674f, -0.00621504f, 0.0783184f, -0.012892931f,
- -0.035870403f, -0.01487499f, -0.0047641373f, -0.019595945f,
- 0.009969749f, -0.027250513f, -0.02262483f, -0.013762759f,
- -0.06368039f, -0.052597508f, -0.002207749f, -0.010840596f,
- 0.03524336f, 0.0097454805f, -0.010235127f, -0.021841899f,
- -0.034494065f, 0.0042356453f, -0.021075536f, -0.025580432f,
- 0.067468494f, 0.08983126f, -0.010651849f, 0.027945561f,
- 0.024657574f, -0.015495126f, -0.019870197f, 0.0823922f,
- 0.04254852f, 0.024669873f, -0.002658334f, -0.010553731f,
- 0.091467924f, 0.059308697f, -0.006437278f, 0.044715878f,
- -0.020000942f, -0.028426355f, -0.09776812f, 0.10694438f,
- -0.046122152f, -0.015459695f, 0.034204032f, 0.008300085f,
- -0.00023538139f, 0.00400379f, -0.017456885f, -0.011588866f,
- 0.057018314f, 0.003483618f, 0.024977114f, -0.021491567f,
- -0.000755797f, -0.044665422f, -0.018456006f, -0.0186981f,
- -0.016331315f, -0.012751132f, -0.024017638f, 0.013501261f,
- -0.0017799091f, -0.032515287f, -0.030349506f, -0.07548862f,
- 0.015781978f, 0.046264317f, -0.018058885f, 0.00951239f,
- -0.033290595f, -0.016547354f, -0.014310378f, -0.04048069f,
- -0.03084224f, -0.006195288f, 0.0019158587f, -0.0032519929f,
- -0.013970238f, 0.0020360814f, -0.009662215f, 0.04243444f,
- -0.020672455f, 0.012782469f, 0.027058687f, 0.0070763943f,
- 0.0023199434f, 0.034271993f, -0.058441285f, 0.0041133817f,
- -0.048706394f, 0.024351181f, -0.002878116f, -0.011422821f,
- 0.008126832f, 0.0057494114f, 0.015283818f, 0.036726978f,
- -0.0004499397f, 0.051951192f, 0.021907385f, 0.008195023f,
- 0.014671648f, 0.039268546f, 0.01699728f, -0.0004980496f,
- -0.023245862f, -0.0015531959f, -0.045333967f, -0.012788867f,
- 0.025897382f, 0.0013506403f, 0.00599586f, -0.000625516f,
- -0.002995399f, -0.005666789f, -0.026999313f, -0.010443403f,
- 0.036861118f, -0.029097725f, 0.002239036f, -0.05177783f,
- -0.009831323f, -0.022069374f, -0.02345408f, -0.0070459386f,
- 0.00080631825f, -0.00082733406f, 0.00025831498f, 0.047989618f,
- -0.036197502f, 0.012375012f, -0.002715004f, 0.022519536f,
- 0.0010851892f, 0.0016724346f, 0.013481848f, 0.03181787f,
- 0.025686312f, -0.009873425f, -0.013891775f, -0.008669807f,
- 0.00788027f, -0.06306137f, 0.015187422f, 0.0012821525f,
- -0.015342677f, -0.052488707f, 0.0054418286f, -0.024670836f,
- 0.0009986166f, 0.0047622765f, 0.048672233f, 0.05983857f,
- -0.01652678f, -0.025849469f, 0.076684274f, -0.053900626f,
- -0.016988998f, -0.0025460592f, 0.017573476f, -0.035296537f,
- -0.012116736f, -0.02058307f, 0.048776027f, -0.06029457f,
- -0.013702341f, 0.050067224f, 0.058770355f, -0.023657959f,
- -0.0120317945f, 0.01801224f, -0.014790904f, 0.04185092f,
- 0.02537197f, -0.013999733f, -0.0075669265f, -0.04941231f,
- -0.06462144f, -0.029677926f, 0.01572551f, 0.0051663388f,
- -0.017405879f, 0.0033145156f, -0.09060399f, -0.016230408f,
- -0.045239713f, -0.007134403f, -0.0048212013f, 0.037313897f,
- 0.0023446637f, -0.038966965f, 0.043153364f, -0.007369382f,
- -0.0009457919f, 0.0034975687f, -0.05716649f, 0.0030390348f,
- -0.035501774f, -0.043853167f, -0.038490605f, -0.009797364f,
- 0.014757681f, 0.00034634012f, 0.008388246f, -0.04189804f,
- -0.025169006f, -0.011233779f, -0.015779773f, -0.041068938f,
- -0.015575074f, -0.029574174f, 0.012770746f, 0.014800396f,
- -0.032287262f, 0.00752939f, 0.037197154f, -0.028022885f,
- -0.0016430522f, -0.04747601f, -0.008828012f, -0.010486311f,
- 0.00016208347f, 0.00027527343f, -0.0074483147f, -0.0045240805f,
- 0.00061171607f, -0.006275338f, -0.002649089f, -0.01833864f,
- -0.029883843f, 0.00094386784f, 0.009668675f, -0.0011693656f,
- -0.023500577f, 0.009437362f, 0.02357419f, -0.0022271413f,
- 0.004734695f, -0.034340374f, -0.046541028f, -0.012129122f,
- 0.007881295f, -0.04870404f, 0.007561236f, 0.0059293853f,
- 0.028792923f, -0.03817207f, -0.017061893f, 0.014999111f,
- -0.024366045f, -0.04703897f, 0.0058064125f, -0.043412406f,
- -0.021307426f, -0.020853719f, -0.015037978f, -0.028536882f,
- -0.000651465f, -0.031091236f, -0.015845923f, -0.07499202f,
- 0.0008822091f, -0.004034531f, -0.012258201f, 0.014729502f,
- 0.020841435f, 0.0041743196f, 0.038026184f, 0.031747166f,
- 0.015780369f, 0.028886387f, 0.058987208f, 0.02798586f,
- -0.0049887467f, -0.06996171f, 0.0033388247f, -0.011262697f,
- 0.008246469f, 0.021016592f, 0.015008565f, -0.0011517092f,
- -0.0006743537f, 0.0428299f, -0.009250118f, 0.017581172f,
- -0.003295566f, -0.00072433526f, 0.011857562f, -0.045930803f,
- 0.0003843544f, -0.045392904f, -0.031246306f, 0.036853872f,
- -0.041826908f, -0.034439813f, 0.010294388f, -0.0151875755f,
- 0.0013295708f, -0.021769665f, 0.04450508f, 0.031778056f,
- -0.016919727f, -0.024377389f, -0.028443646f, -0.072511435f,
- -0.017447347f, -0.047419567f, -0.009535936f, -0.0127032995f,
- -0.012709417f, -0.06570916f, -0.051600955f, 0.008415978f,
- 0.026322134f, 0.028787596f, 0.03646512f, -0.015409545f,
- -0.010021975f, 0.0164905f, 0.0030572051f, -0.011834118f,
- 0.030943742f, 0.029107088f, -0.027235374f, -0.004066218f,
- -0.0771732f, 0.022907095f, -0.035161577f, -0.0025541144f,
- -0.011593004f, 0.050228175f, -0.020507852f, -0.0338798f,
- -0.015504492f, 0.0051483624f, 0.016782247f, -0.07174444f,
- 0.054309674f, -0.00028948023f, -0.00031123497f, -0.033779595f,
- 0.05144114f, -0.026408931f, 0.038817137f, -0.061756f,
- -0.05522305f, 0.0049043032f, 0.04271609f, -0.018971018f,
- -0.0025515272f, 0.10736401f, -0.03388846f, 0.0292024f,
- -0.005493019f, 0.010832994f, -0.030314518f, 0.00029517274f,
- 0.0077174315f, -0.013566471f, -0.051392455f, -0.045225386f,
- 0.0072264643f, 0.008280993f, -0.09835726f, -0.042733084f,
- 0.038174905f, 0.029818915f, -0.033366986f, 0.05410963f,
- 0.10046508f, 0.06939685f, -0.10927409f, -0.0067910077f,
- 0.010689976f, -0.08345343f, -0.1102037f, 0.009688002f,
- 0.03973711f, -0.037580844f, 0.0422765f, -0.034750637f,
- -0.0061101005f, 0.01463179f, 0.01941164f, 0.03230367f,
- 0.053998154f, 0.0034168446f, -0.03350236f, -0.03006133f,
- 0.015983248f, -0.008499604f, 0.105070725f, 0.05589698f,
- 0.06776565f, -0.020138245f, 0.002129937f, -0.017467013f,
- 0.011359366f, 0.03870687f, -0.070789225f, 0.013027831f,
- -0.002681064f, -2.3432663e-06f, 0.116923556f, 0.055236876f,
- 0.022787513f, 0.064479254f, 0.023958938f, -0.005770508f,
- -0.017970018f, -0.024355065f, -0.0078058997f, 0.049420733f,
- 0.05329982f, -0.020744229f, 0.06320052f, 0.037392654f,
- 0.0018299688f, 0.012888123f, 0.011640452f, -0.04667929f,
- 0.04070056f, -0.0015471679f, -0.00033877738f, 0.016654283f,
- -0.03565898f, -0.039903447f, -0.026448656f, -0.02322396f,
- -0.0046807355f, -0.0026010266f, -0.0069676414f, 0.0132063385f,
- -0.011659914f, 0.021848252f, -0.02138812f, -0.021920033f,
- 0.086787455f, 0.03076811f, -0.019165574f, -0.0010257284f,
- 0.020463757f, 0.016303537f, -0.06776169f, 0.0100091295f,
- -0.02266033f, 0.062421177f, 0.04003277f, -0.003016077f,
- -0.005945528f, 0.05386383f, -0.03641078f, 0.015903665f,
- -0.010772781f, -0.036566775f, 0.01173524f, -0.01786779f,
- -0.024242543f, 0.0341078f, 0.047306556f, 0.04393666f,
- 0.084354535f, -0.030543324f, -0.0249641f, 0.050821867f,
- 0.054273f, 0.103368014f, -0.018007137f, 0.11309535f,
- -0.011579336f, -0.0717363f, -0.03718493f, 0.014109482f,
- -0.0235526f, -0.016456176f, 0.057026803f, -0.012253723f,
- -0.011132962f, -0.058500186f, 0.0019855294f, -0.1082662f,
- 0.040087286f, 0.04995066f, -0.030838745f, 0.0002537692f,
- -0.089704536f, -0.02081093f, -0.039517663f, -0.07635976f,
- -0.07925018f, -0.046571366f, -0.015358846f, -0.015371624f,
- -0.017376686f, -0.014143468f, -0.01458233f, 0.04596281f,
- -0.009731523f, 0.029659621f, 0.037761375f, -0.031527888f,
- -0.013640777f, 0.0011148644f, -0.104035504f, 0.00054057944f,
- -0.09208418f, 0.019467352f, -0.019239f, -0.012463024f,
- -0.00086470775f, -5.4111744e-05f, 0.002537694f, 0.014434535f,
- -0.0017215792f, 0.033518765f, 0.0714182f, 0.020097572f,
- 0.012906186f, -0.0039380174f, -0.017355593f, 0.00014864455f,
- -0.0019293441f, -0.00855987f, -0.08510015f, 0.0017131439f,
- 0.021011977f, 0.021202704f, 0.0009812634f, -0.018990194f,
- -0.020044997f, -0.0056350916f, -0.046682943f, -0.0028377434f,
- 0.018677998f, -0.00232338f, -0.016757421f, -0.09756315f,
- -0.00959202f, -0.0019391626f, -0.051468678f, -0.025086623f,
- -0.0076331124f, 0.005833026f, 0.006919026f, 0.006538355f,
- -0.05850282f, 0.0031160323f, 0.0033906081f, -0.006543737f,
- -0.046239156f, 0.011510651f, 0.011215505f, 0.02698139f,
- 0.017118586f, -0.00087819784f, 0.01107736f, -0.033900347f,
- 0.003189307f, -0.013422806f, 0.010380541f, -0.0056544435f,
- -0.0044387695f, -0.07430943f, 0.031721637f, 0.016667062f,
- 0.0046094297f, 0.020747866f, -0.027661182f, 0.0600463f,
- -0.009099071f, -0.067613825f, 0.0625548f, -0.102788284f,
- -0.011472205f, -0.021505209f, 0.018167935f, 0.010880467f,
- 0.014443287f, -0.026261255f, 0.030681673f, -0.11748285f,
- 0.008270768f, 0.033754356f, 0.07134693f, -0.051997017f,
- -0.018625828f, 0.008990146f, 0.009818685f, -0.0006066216f,
- 0.022206198f, -0.022833517f, -0.017009515f, -0.06910468f,
- -0.08906539f, -0.04902047f, 0.01628411f, -0.009381786f,
- -0.008327738f, 0.00037980924f, -0.036426496f, -0.04044832f,
- -0.029332606f, -0.017355775f, -0.013256066f, 0.058445856f,
- -0.019405596f, -0.02272344f, -0.0075358823f, -0.011063223f,
- -0.008843028f, -0.024570188f, 0.023885535f, -0.011267813f,
- -0.04941276f, 0.00827305f, -0.032002114f, -0.038439043f,
- 0.026600873f, -0.021202337f, 0.034662306f, -0.021619424f,
- -0.049820825f, -0.014670059f, -0.040785678f, -0.026318738f,
- -0.0013052644f, -0.042838212f, -0.0012874596f, 0.0064548803f,
- -0.031257015f, 0.00965899f, 0.06559459f, -0.028937582f,
- -0.003413315f, -0.07112139f, -0.011683188f, -0.01338723f,
- -0.010709215f, -0.0036919392f, -0.045804184f, 0.013569338f,
- -0.0103977425f, 0.0031468484f, -0.0382776f, -0.045207277f,
- -0.057716884f, -0.033791203f, -0.009755227f, -0.04543906f,
- -0.01030906f, 0.021758826f, 0.005025195f, -0.024496853f,
- -0.012945555f, -0.03989365f, -0.0016571229f, -0.021919481f,
- -0.03366185f, -0.09874838f, 0.021525832f, -0.009834083f,
- 0.015313138f, -0.053248607f, 0.002496992f, -0.030393576f,
- -0.06429327f, -0.03536059f, -0.011462372f, 0.0037080054f,
- 0.035262514f, -0.04093468f, -0.042243656f, 0.00062229176f,
- -0.010064738f, -0.013335747f, -0.022586877f, 0.005718468f,
- -0.03276903f, -0.025138445f, -0.014740378f, 0.053802527f,
- -0.05262133f, 0.010746198f, 0.03508462f, -0.028974958f,
- 0.0076124743f, 0.0022659267f, -0.0025297096f, -0.016763233f,
- -0.07903988f, -0.043051634f, -0.016116465f, -0.030752206f,
- 0.0013471554f, -0.023135614f, -0.025301788f, -0.012840402f,
- -0.017320856f, -0.041921724f, -0.019031636f, -0.018634835f,
- -0.005630111f, 0.00541903f, 0.01367964f, -0.09650796f,
- -0.015052022f, -0.022964634f, -0.026023008f, -0.021934003f,
- -0.08342343f, 0.017763536f, -0.018594852f, -0.033438656f,
- -0.007487229f, -0.014833847f, -0.029818103f, -0.0119535625f,
- -0.050723553f, 0.0041700606f, -0.02203058f, 0.017693812f,
- -0.021611165f, -0.077097625f, -0.059508853f, 0.0042393906f,
- -0.10456296f, 0.04125248f, 0.0028951066f, -0.020901822f,
- -0.014170127f, -0.036178637f, -0.020441867f, -0.018413795f,
- 0.029126499f, -0.035713706f, -0.04068912f, -0.023379622f,
- -0.015102983f, -0.0266202f, -0.026221473f, -0.006272355f,
- 0.028376391f, -0.0022812337f, -0.030857636f, -0.017333858f,
- -0.023920992f, 0.0129313385f, -0.05433631f, -0.083776124f,
- -0.039985932f, -0.0038876408f, -0.022609368f, 0.023028798f,
- -0.03472072f, -0.040208608f, -0.02577209f, -0.01820688f,
- -0.027497709f, -0.020283844f, -0.06377251f, -0.038222067f,
- -0.015001858f, -0.035864957f, 0.041715242f, -0.02396972f,
- -0.011529214f, 0.02434636f, -0.018583452f, -0.019675605f,
- 0.007754699f, -0.031339485f, -0.04113034f, -0.039743744f,
- -0.0353325f, -0.042141587f, -0.010125548f, -0.16477652f,
- -0.0049593723f, -0.015540937f, -0.03960263f, -0.057842482f,
- -0.0070165284f, -0.02491829f, -0.03442979f, 0.012421984f,
- -0.03359444f, -0.026680233f, -0.023991844f, -0.013566474f,
- -0.012194242f, 0.06738883f, 0.003057398f, -0.02747322f,
- -0.054081306f, -0.07926847f, 0.041279208f, 0.020448543f,
- -0.008662016f, -0.01226929f, -0.025804533f, -0.039144255f,
- -0.021632778f, -0.014784556f, -0.0024407713f, 0.00012342024f,
- -0.0024572324f, -0.007876402f, 0.02035383f, -0.02806346f,
- -0.017601144f, -0.04764525f, -0.040511247f, -0.08319357f,
- -0.03318178f, 0.009250714f, 0.019524064f, -0.049148142f,
- 0.02011744f, -0.001293827f, 0.019737724f, -0.019551734f,
- -0.012325012f, 0.028664775f, 0.0032879473f, -0.02243275f,
- -0.0805642f, -0.056438968f, -0.04074409f, 0.012524623f,
- -0.048894808f, -0.015949795f, -0.029841049f, -0.07482074f,
- 0.00478155f, -0.026731951f, -0.006695691f, -0.010120253f,
- -0.020368647f, -0.05747951f, -0.099268496f, -0.050752807f,
- -0.07304143f, -0.0681571f, -0.07852373f, -0.066125415f,
- -0.023684628f, -0.0621663f, -0.018338196f, -0.12179188f,
- -0.03892784f, -0.021123486f, -0.0034003954f, -0.05437736f,
- -0.048729837f, -0.033546846f, -0.04447509f, -0.033346336f,
- -0.018215759f, -0.118083104f, -0.06781651f, -0.04422807f,
- -0.04422476f, -0.035418924f, -0.001341602f, -0.007287664f,
- -0.049200535f, -0.01694033f, -0.018737346f, -0.04907433f,
- 0.0030219376f, -0.055367287f, 0.0044648405f, -0.05091269f,
- -0.053992525f, 0.006206451f, -0.009602827f, 0.027643368f,
- 0.015675599f, -0.066732824f, -0.05434814f, 0.0061866282f,
- -0.05016129f, -0.04091702f, -0.053593118f, 0.031897828f,
- 0.03127838f, 0.02669378f, 0.020297315f, -0.03371888f,
- 0.03371336f, -0.0020031794f, -0.046423152f, 0.02132832f,
- -0.002532426f, 0.004860279f, -0.01478674f, 0.0124948975f,
- 0.035511307f, 0.02795558f, 0.010507369f, 0.018765328f,
- 0.00898661f, 0.026671417f, 0.030479409f, 0.022038452f,
- 0.027650194f, 0.03697584f, 0.00044359156f, 0.01619613f,
- -0.014720046f, 0.005716712f, -0.0021388473f, 0.031735335f,
- 0.009366475f, 0.01178345f, 0.011144083f, 0.023437174f,
- 0.06489462f, -0.0022657113f, 0.026524538f, 0.022535415f,
- 0.013527068f, 0.010505294f, 0.02323362f, 0.00554751f,
- 0.025742821f, 0.0022354259f, 0.014963127f, 0.010184767f,
- 0.016638214f, 0.040314272f, 0.015139551f, 0.0009533867f,
- 0.03586888f, 0.011220936f, 0.01644118f, 0.010360771f,
- 0.0011497348f, 0.024500376f, 0.017959367f, -0.008005704f,
- -0.025566198f, -0.0013122658f, 0.02182658f, 0.020579083f,
- 0.011780489f, 0.015631061f, 0.028607039f, 0.012455224f,
- 0.005926197f, -0.014727572f, 0.019179685f, 0.026581936f,
- 0.01679574f, -0.017007962f, 0.0571229f, 0.06293547f,
- 0.022670101f, 0.0044610053f, 0.009590699f, 0.020369181f,
- 0.018481828f, 0.020212648f, 0.020119436f, 0.021912955f,
- 0.02494235f, 0.013481484f, 0.03233485f, 0.026429288f,
- 0.017951515f, 0.01536881f, -0.03503082f, 0.026687317f,
- 0.011563277f, -0.0554147f, 0.014809317f, 0.022776594f,
- -0.0010379741f, 0.027736094f, 0.022793211f, 0.016252222f,
- 0.02353381f, 0.015437734f, 0.020042317f, 0.054418184f,
- -0.0014342366f, 0.027004806f, 0.0015969981f, 0.059425045f,
- 0.0015596622f, 0.020296259f, 0.005794367f, -0.028079443f,
- -0.0020779723f, 0.0074499f, 0.027783707f, 0.02787082f,
- 0.0077818534f, -0.011668845f, -0.01470731f, 0.023222633f,
- 0.0017347954f, 0.03169006f, -0.0242201f, 0.020037863f,
- 0.010084468f, 0.022863109f, 0.010424294f, 0.028924933f,
- 0.006840561f, 0.01878555f, 0.006941517f, 0.017415678f,
- -0.0018142336f, 0.015890414f, -0.042466346f, 0.013990714f,
- -0.0059720804f, 0.041237574f, 0.03588409f, 0.018783709f,
- 0.038170595f, -0.0121518625f, 0.026080646f, 0.019745117f,
- -0.0026689474f, 0.008549168f, -0.060708933f, 0.012414726f,
- 0.02377336f, -0.042575624f, 0.00053104444f, 0.018269721f,
- 0.026513029f, 0.050939385f, -0.0074688816f, -0.013070511f,
- 0.03598789f, 0.024612622f, 0.013620761f, 0.03236397f,
- -0.008910052f, 0.027491555f, -0.010953088f, 0.012228643f,
- 0.007959679f, 0.02694664f, 0.024869062f, 0.040272694f,
- 0.032150697f, 0.0483193f, 0.041193962f, 0.03751053f,
- 0.024344401f, 0.036197253f, 0.010401214f, 0.042730615f,
- 0.014527879f, 0.0094334455f, 0.02448744f, 0.04867893f,
- 0.02043798f, 0.028846119f, 0.014293723f, 0.01905963f,
- 0.007733741f, 0.041147005f, 0.050134998f, 0.046832904f,
- 0.036521707f, 0.011699629f, -0.010629646f, 0.0053698774f,
- 0.05430496f, 0.012676146f, 0.004252787f, 0.019839562f,
- -0.0037244207f, 0.040049635f, -0.0028468515f, 0.055868734f,
- 0.051169254f, -0.0036692284f, 0.008321568f, -0.03407296f,
- -0.032170758f, 0.042878557f, 0.04009963f, -0.015293108f,
- 0.027349174f, 0.0038054746f, 0.03729282f, -0.05661808f,
- 0.015534515f, 0.04173132f, 0.018384151f, 0.048300445f,
- -0.005525562f, 0.027892258f, 0.041001044f, -0.014527823f,
- -0.05441852f, 0.05614562f, -0.039938714f, 0.070149705f,
- -0.009029721f, 0.01988474f, 0.021800127f, 0.010960936f,
- 0.01971486f, -0.043135915f, 0.051953416f, 0.017235657f,
- 0.03576991f, 0.0029290891f, 0.025708744f, -0.021083156f,
- 0.039447434f, -0.06673286f, -0.02565914f, 0.087624066f,
- 0.012811939f, 0.06766693f, 0.009079769f, 0.008278161f,
- 0.028065734f, 0.014370119f, 0.010408885f, -0.038396593f,
- 0.021723717f, -0.00921941f, 0.05733589f, -0.03171161f,
- -0.015362192f, -0.053754747f, 0.03325873f, 0.029386686f,
- 0.013938692f, 0.019642694f, 0.034020234f, -0.020167127f,
- 0.027123788f, 0.028886147f, 0.09979345f, -0.011120568f,
- -0.019497646f, -0.033660483f, 0.046460234f, 0.043405097f,
- -0.00039353909f, -0.028856905f, -0.015801758f, 0.039584205f,
- -0.024914753f, 0.01506646f, 0.064596936f, 0.026469385f,
- 0.033671208f, -0.02705111f, -0.004300509f, 0.027843356f,
- 0.030490732f, -0.018257428f, 0.05150007f, 0.02211041f,
- 0.035108034f, -0.027732005f, -0.031452294f, 0.037488908f,
- 0.05675063f, -0.02358611f, -0.037626207f, 0.08489019f,
- 0.02654913f, 0.053510748f, -0.045845848f, 0.038039118f,
- 0.026715936f, -0.023557529f, -0.009992071f, 0.016318591f,
- -0.07730447f, 0.055094313f, -0.03754544f, 0.026406461f,
- -0.024855163f, 0.0049447613f, -0.029215673f, 0.00077367097f,
- -0.037994985f, -0.009201793f, 0.06573249f, 0.07472431f,
- -0.019771041f, 0.035555407f, 0.06503567f, 0.14164859f,
- -0.05628334f, -0.032128822f, -0.04209131f, 0.032491267f,
- -0.01896107f, -0.007571913f, 0.008046055f, 0.054268904f,
- -0.011379171f, 0.09318819f, 0.06736358f, -0.010066346f,
- -0.0028576143f, 0.08731471f, 0.09020104f, 0.06681841f,
- -0.0024703108f, -0.02908796f, 0.0011654489f, 0.07853877f,
- 0.041191146f, 0.0144716315f, -0.0011882931f, -0.047258638f,
- 0.0055226637f, -0.022673447f, 0.13388972f, 0.043887753f,
- -0.0016630935f, -0.0280655f, -0.024275364f, 0.018270286f,
- 0.036277145f, 0.039429773f, 0.04075862f, 0.0074807117f,
- 0.02343431f, 0.0051100957f, 0.035158467f, -0.011737131f,
- 0.120903775f, -0.061662596f, 0.07425136f, 0.02369643f,
- 0.06005992f, 0.026972836f, 0.025422571f, 0.08062871f,
- -0.040399026f, 0.008762524f, 0.04224552f, -0.024071896f,
- 0.05000176f, 0.12912677f, -0.026353331f, -0.002330574f,
- 0.01648347f, 0.05034285f, 0.014800388f, 0.14419526f,
- 0.08606452f, 0.11687575f, 0.032173883f, 0.030555304f,
- -0.0058581526f, 0.050123736f, 0.0041470216f, 0.012838339f,
- 0.005341327f, -0.05015258f, 0.0851654f, 0.10716042f,
- 0.06600122f, -0.037835702f, 0.05395574f, 0.016561083f,
- -0.064220876f, -0.0024760244f, 0.04087225f, 0.05088179f,
- -0.009491223f, 0.03404657f, -0.06641341f, 0.0022411924f,
- 0.039273296f, 0.07270775f, 0.009651715f, -0.020845033f,
- 0.009147395f, 0.07965617f, 0.09122302f, 0.029213566f,
- 0.117578216f, 0.018777031f, 0.0076132603f, 0.018277729f,
- 0.07348738f, 0.059491545f, 0.041368626f, 0.057365168f,
- -0.051337596f, 0.0032914372f, 0.0033273238f, 0.11515516f,
- 0.0051058144f, -0.007241719f, -0.23506933f, -0.015276594f,
- -0.15783913f, -0.013425161f, 0.0396242f, -0.0050656185f,
- -0.035297364f, 0.25705013f, -0.0048521482f, -0.0010293799f,
- -0.09719481f, -0.0063537275f, -0.3219648f, -0.03124677f,
- 0.025889143f, -0.006718266f, 0.006598423f, 0.009417351f,
- 0.007870954f, 0.015383899f, 0.62561154f, 0.0004481653f,
- -0.07648505f, -0.014177602f, -0.005621776f, 0.009936041f,
- -0.06293086f, -0.051557943f, 0.013461138f, 0.025997382f,
- 0.008946045f, 0.007209159f, 0.0059978277f, -0.0014776122f,
- 0.04679774f, -0.03238895f, 0.0064791185f, -0.0017982613f,
- 0.07572991f, 0.016269164f, 0.07169033f, -0.02295379f,
- 0.19333719f, -0.02302858f, 0.048457414f, 0.012274239f,
- -0.0502068f, 0.0075106146f, 0.0018726318f, -0.2062034f,
- -0.008500507f, 0.00062769925f, 0.016426355f, -0.12442369f,
- 0.24110818f, -0.1965928f, -0.33651137f, -0.05510573f,
- 0.0007655266f, -0.0036880611f, 0.06446646f, 0.4737327f,
- -0.025690166f, 0.015143883f, 0.018007582f, 0.008507666f,
- -0.07577988f, -0.0057011163f, 0.0059523634f, 0.020138804f,
- -0.049449317f, 0.00651317f, -0.011232963f, -0.015213755f,
- 0.008857214f, 0.32891506f, 0.02881703f, -0.03560131f,
- -0.004006438f, -0.23645857f, -0.016997857f, -0.0107020335f,
- -0.0038170477f, 0.03724378f, 0.14182079f, 0.13029842f,
- -0.006100985f, 0.030522743f, 0.0014816303f, -0.005296767f,
- 0.0021324093f, -0.0191393f, -0.026651895f, 0.03723865f,
- -0.0032381546f, -0.34006682f, -0.024848327f, 0.006049041f,
- 0.14920892f, 0.016208382f, -0.18874039f, -0.008053412f,
- -0.008443927f, 0.0030026238f, 0.37028122f, -0.0041489475f,
- 4.2246254e-05f, 0.007350591f, 0.0053703887f, 0.008421637f,
- -0.0053901197f, -0.025883403f, -0.011471624f, 0.0050715813f,
- 0.0638181f, 0.0057613617f, 0.061176326f, -0.0039021394f,
- -0.017577935f, -0.0073587904f, 0.044828247f, -0.0013064678f,
- 0.019795643f, -0.005735862f, -0.007632802f, -0.0087065855f,
- 0.17796126f, 0.021193728f, 0.06292831f, 0.015100581f,
- 0.012181929f, -0.0021773183f, 0.0012515481f, 0.06957368f,
- -0.00089406746f, -0.007314919f, -0.01083701f, -0.26009175f,
- -0.0029790301f, 0.1187109f, 0.019736292f, -0.0019932524f,
- -0.0022849585f, -0.0051359558f, 0.0005333218f, 0.745173f,
- -0.074710414f, 0.021194067f, -0.14259124f, -0.002601296f,
- 0.009887769f, -0.33566162f, 0.010878301f, -0.16052045f,
- -0.004740605f, -0.0037800297f, -0.017419528f, -0.21461429f,
- -0.0015727899f, -0.07911543f, 0.010948842f, -0.0047325375f,
- 0.016984574f, -0.0040548025f, -0.037325725f, 0.012028515f,
- -0.0009765577f, -0.019700097f, -0.34769467f, 0.020433377f,
- 0.12169742f, -0.019599622f, -0.00025030127f, -0.003134264f,
- 0.013296142f, 0.020788318f, 0.19293545f, -0.16628136f,
- -0.0070460388f, 0.026298156f, 0.10557741f, -0.0017521966f,
- 0.41230235f, 0.010587587f, -0.022563748f, -0.09676189f,
- -0.0018234907f, 0.023814328f, 0.047069557f, -0.00981084f,
- -0.02802163f, 0.0029201668f, -0.09502431f, -0.00067634886f,
- -0.016239494f, 0.2959242f, -0.0036183216f, 0.013798851f,
- -0.005890698f, -0.0064486456f, 0.07213103f, -0.0030905732f,
- 0.0026422907f, -0.002432532f, -0.20087938f, 0.000402788f,
- 0.0009972395f, 0.009755058f, -0.9687651f, -0.022339776f,
- -0.19867152f, 0.0030844016f, 0.032373577f, 0.010906772f,
- 0.014964714f, -0.16399479f, 0.012906419f, 0.010921799f,
- -0.082963936f, 0.00694445f, 0.49445233f, 0.061755866f,
- 0.0035893824f, 0.0060725533f, -0.0046708155f, 0.006914863f,
- -0.00079106353f, -0.0027477513f, 0.2543801f, 0.00053999847f,
- -0.1854739f, 0.020897362f, 0.004868171f, -0.012913433f,
- 0.70867646f, 0.117565386f, 0.046587054f, 0.006853577f,
- -0.0027053952f, 0.16117519f, 0.010205607f, -0.0039471732f,
- 0.019794408f, -0.0025396885f, -0.0073014507f, 0.0039264183f,
- 0.23704079f, 0.01252446f, 0.06006683f, -0.0038108402f,
- -0.20338047f, -0.002437441f, 0.10733003f, 0.06034445f,
- 0.022732992f, -0.006372797f, -0.014004311f, -0.025851026f,
- -0.002470303f, -0.004155f, -0.0022192493f, 0.061584488f,
- 0.21073803f, 0.039586812f, 0.010078901f, 0.07724791f,
- -0.0017443498f, 0.0021816383f, 0.061090507f, -0.42423138f,
- -0.00978641f, 0.1126671f, -0.046574455f, 0.0043072733f,
- 0.0436192f, 0.011085659f, 0.0004912449f, -0.044728056f,
- 0.10009852f, 0.016238892f, -0.04591111f, 0.0026563818f,
- -0.00015544737f, -0.030097064f, 0.043014754f, 0.055467322f,
- -0.0002737925f, -0.0016418952f, -0.0047932835f, 0.0045029013f,
- -0.0034569178f, 0.054534875f, 0.028850624f, 0.051728383f,
- 0.020977808f, 0.014632044f, 0.059008982f, 0.0014632463f,
- 0.012104483f, 0.0027390632f, 0.0071648634f, 0.3628453f,
- 0.0024196478f, -0.08304524f, 0.22429046f, 0.035557207f,
- -0.045531284f, 0.0010200937f, -0.025576444f, 0.004107169f,
- 0.0056200596f, -0.00085631176f, 0.06723966f, -0.0011016045f,
- -0.0029669541f, 0.00042978657f, 0.005638325f, 0.004804113f,
- 0.04090781f, -0.01161547f, -0.09467522f, 0.01662289f,
- -0.22045226f, -0.04687037f, -0.03156062f, -0.004494426f,
- -0.013401508f, 0.006028842f, -0.028129537f, -0.005532068f,
- -0.0011651241f, 0.0063746823f, 0.019377047f, 0.010771243f,
- 0.22274578f, 0.013746683f, 0.015361324f, -0.0043618986f,
- -0.010326367f, 0.0010503472f, 2.2776292e-05f, 0.05752777f,
- -0.0014441566f, 0.021414692f, 0.005338243f, -0.23769358f,
- -9.711671e-05f, 0.095886454f, -0.024381353f, 0.00095344253f,
- 0.0020602145f, 0.029175714f, 0.002894336f, -0.36613047f,
- 0.016931264f, 0.00023725456f, 0.066704996f, 0.012874245f,
- 0.0023039216f, -0.15101357f, 0.0026775491f, -0.061590835f,
- -0.15937158f, 0.0045007244f, 0.10865402f, 0.22097842f,
- 0.0027921656f, 0.04519686f, 0.07881149f, 0.0014238547f,
- -0.029530209f, 0.011435077f, 0.02682911f, 0.08598978f,
- 0.0019634662f, -0.027022168f, -0.21771187f, -0.06694111f,
- 0.07832733f, 0.009241913f, -8.668174e-06f, -0.011190584f,
- -0.004239778f, 0.0006654754f, 0.0835183f, 0.15135692f,
- 0.0004606953f, -0.0018164215f, -0.15830016f, -0.0022559855f,
- 0.033781517f, -0.0023550203f, 0.009774732f, 0.07305986f,
- -0.0032362842f, 0.0018325454f, -0.022997858f, 0.0033059397f,
- 0.18264854f, 0.014600075f, -0.2271588f, -0.008594481f,
- -0.00217416f, -0.05834629f, 0.001298194f, 0.053636953f,
- 0.00059230626f, 0.0055614f, 0.06001712f, 0.012445908f,
- -0.0017720306f, -0.0020422023f, -0.0389582f, 0.0063345362f,
- 0.010844859f, 0.0146514345f, -0.003581947f, -0.0099355215f,
- 0.30001926f, -0.0073204446f, -0.043146398f, 0.011308441f,
- -0.011863505f, -0.12132324f, -0.011837895f, 0.016432548f,
- -0.09952297f, -0.01871716f, -0.11735872f, 0.19967166f,
- 0.019644586f, -0.005864555f, 0.0022974599f, 0.020369403f,
- 0.00084071665f, 0.011803625f, 0.18644899f, 0.0010446879f,
- 0.22695611f, -0.02283272f, -0.0020486962f, -0.02396727f,
- 0.3234641f, -0.02885973f, 0.0007610227f, 0.0048298407f,
- 0.0095937215f, 0.18026161f, 0.03794124f, -0.0072429148f,
- 0.03249358f, 0.18286039f, 0.0023772875f, 0.00072668784f,
- -0.010000183f, 0.007329475f, -0.10068485f, -0.0013517652f,
- -0.39497456f, -0.009440887f, -0.023602096f, 0.072851956f,
- 0.025678392f, -0.022855991f, -0.04451608f, 0.13603695f,
- -0.010348838f, 0.0026318044f, 0.014396789f, 0.17142154f,
- 0.15645038f, 0.084461264f, -0.0060682213f, 0.14490403f,
- -0.0005435113f, -0.0024005033f, -0.08933272f, 0.27927664f,
- -0.0029917816f, -0.16523796f, 0.023156274f, 0.0132152345f,
- 0.00436991f, -0.008092856f, -0.005214091f, 0.029674672f,
- 0.60860014f, 0.035701804f, 0.08853064f, -0.011394207f,
- 0.0021630432f, 0.32728124f, 0.038910054f, -0.014057401f,
- -0.0018115449f, -0.25647935f, -0.008663601f, 0.045908183f,
- -0.005488794f, 0.083082885f, -0.033688497f, -0.063633144f,
- -0.014824946f, 0.029052591f, 0.03636353f, -0.0021547505f,
- 0.089656286f, 0.03060459f, -0.0042053973f, 0.13494475f,
- -0.0029315432f, -0.110395f, -0.2132316f, -0.009950547f,
- 0.04639593f, 0.0061177495f, 0.20507103f, 0.005817206f,
- -0.014911272f, 0.0010131191f, -0.18198672f, -0.0009018634f,
- -0.0035211907f, 0.0034162533f, -0.017667355f, 0.017276255f,
- 0.08048155f, -0.0076441215f, 0.12057022f, 0.00672382f,
- 0.20687224f, 0.0100963395f, -0.042204697f, -0.008355015f,
- 0.10445277f, -0.0062845987f, -0.5068189f, 0.013279929f,
- 0.017029185f, 0.009792658f, -0.015182795f, -0.0072437497f,
- -0.2793616f, 0.019781703f, -0.021388061f, 0.0047770557f,
- 0.015791891f, -0.002498768f, -0.00112303f, -0.064869896f,
- -0.0031660325f, -0.01274373f, -0.006616884f, 0.12655972f,
- -0.0035265866f, 0.12890542f, 0.010201343f, 6.181811e-05f,
- 0.00320701f, -0.029668797f, 0.009895498f, 0.022062926f,
- -0.011012098f, -0.00034638934f, -0.008261924f, -0.0022271867f,
- 0.010910033f, -0.8141421f, 0.005617122f, -0.3805108f,
- 0.42760515f, 0.0066546276f, -0.041810963f, -0.19451834f,
- 0.008685443f, -0.06525099f, -0.11665164f, 0.0015010745f,
- 0.013571173f, -0.012835082f, -0.022265613f, -0.040376443f,
- -0.0018164f, 0.018275652f, -0.2717247f, 0.0074724704f,
- -0.03146354f, -0.016144454f, -0.0010205245f, 0.013940365f,
- 0.0076920814f, 0.00084437407f, -0.24770907f, 0.16023444f,
- -0.0084957285f, -0.0006632212f, 0.018063137f, -0.0004785692f,
- -0.08076803f, 0.0031238215f, -0.02619921f, -0.076714404f,
- -0.0003869675f, 0.017276088f, 0.11073273f, -0.014365375f,
- -0.2762358f, -0.0056368234f, -0.19843057f, 0.00045199302f,
- 0.005452056f, 0.2715952f, -0.0016444847f, 0.08409218f,
- -0.0044737626f, 0.0058907997f, -0.038028456f, -0.0076436535f,
- 0.006283236f, 0.009886519f, 0.106701605f, -0.006767148f,
- 0.007670777f, 0.015403537f, 0.27320206f, -0.0116839325f,
- 0.104564175f, 0.0059755105f, -0.016082086f, 0.0064605074f,
- 0.023062175f, -0.025094133f, 0.012950476f, 0.016020244f,
- 0.03440883f, -0.004840852f, 0.42712864f, 0.22188237f,
- 0.018606568f, 0.0023796072f, 0.008036843f, 0.017066466f,
- 0.0059466027f, 0.008891115f, 0.67803806f, 0.004057093f,
- 0.18663351f, 0.015872726f, 0.0025289261f, 0.010916533f,
- -0.1896592f, -0.6376288f, 0.026031818f, 0.010737786f,
- -0.021851297f, -0.10721888f, 0.023476142f, 0.0069591496f,
- 0.0040558567f, 0.13918784f, 0.0022289746f, 0.012738503f,
- -0.0010512043f, 0.018497827f, -0.053414684f, -0.0037307409f,
- 0.1773261f, 0.009544615f, 0.06534511f, 0.026968516f,
- 0.00035003657f, -0.017587552f, 0.028553788f, 0.0595454f,
- 0.005002144f, 0.0039632847f, 0.0067654704f, 0.06630941f,
- 0.20405875f, -0.075670205f, -0.23966004f, -0.14452045f,
- -0.0009865589f, -0.00034969172f, 0.09192652f, -0.33691517f,
- -0.0071999365f, 0.041777443f, 0.095842846f, 0.013345892f,
- -0.050985686f, 0.0031308548f, 0.005245455f, -0.0015843492f,
- 0.22743966f, -0.009322799f, 0.05535024f, -0.001557899f,
- 0.009217716f, -0.2299545f, 0.04962173f, -0.038542535f,
- -0.00021423808f, 0.50440717f, 0.015711097f, 0.011504519f,
- -0.0032434182f, 0.068988234f, -0.056605946f, 0.055900067f,
- 0.012220112f, 0.014741739f, 0.022907425f, 1.4837038e-05f,
- 0.012882649f, 0.02146693f, 0.014495102f, -0.034656286f,
- 0.008677277f, -0.14432445f, -0.28253666f, 0.002426362f,
- 0.1432984f, 0.008266901f, 0.01121842f, 0.002431026f,
- 0.010175217f, 0.006732675f, -0.027244171f, 0.0030832246f,
- 0.01008783f, 0.005480161f, -0.0029511803f, 0.02133696f,
- 0.045467183f, -0.0025889215f, 0.017628763f, 0.013853584f,
- 0.019631317f, -0.0027884082f, -0.016998207f, 0.006015582f,
- 0.03830276f, 0.0021574183f, 0.19798604f, 0.0018085717f,
- 0.02279613f, 0.007489132f, 0.00461886f, 0.0017577204f,
- -0.031642232f, 0.04036596f, -0.018971674f, 0.0052943113f,
- 0.011178069f, 0.0036340253f, 0.006287771f, 0.021685077f,
- 0.00022537507f, 0.011589632f, 0.026190195f, 0.23652746f,
- 0.00030110407f, -0.06415189f, 0.0051815934f, 0.00260238f,
- 0.0036574446f, 0.0028748447f, 0.0056606033f, -0.66489565f,
- -0.032412056f, 0.0033670901f, -0.019749705f, 0.011097971f,
- 0.018363237f, 0.23201007f, 0.00031182147f, -0.11992285f,
- 0.100519694f, -0.004195975f, 0.17899567f, -0.4102985f,
- 0.006177695f, -0.065444864f, 0.024950678f, -0.008903012f,
- 0.009856714f, -0.010312512f, -0.033497978f, -0.06321357f,
- 0.0028968626f, 0.00440254f, -0.16071606f, 0.017408261f,
- 0.05981706f, 0.018344872f, -0.0015432766f, -0.020383067f,
- 0.005159575f, 0.007234416f, 0.22878444f, -0.0060203825f,
- 0.011187433f, 0.05196887f, 0.22767186f, -0.0018783812f,
- 0.14256744f, 0.00713159f, 0.011003438f, 0.06311921f,
- -0.0012895048f, 0.019860681f, 0.041057613f, 0.050655287f,
- -0.13965431f, 0.0133055635f, -0.2898726f, -0.0031658013f,
- -0.014647958f, 0.24708128f, 0.0014135424f, 0.030142203f,
- 0.0028338914f, 0.021849079f, 0.050137136f, 0.015425156f,
- 0.014641457f, 0.0029842006f, -0.11487824f, 0.001780708f,
- 0.006322136f, 0.012955505f, -0.4032845f, -0.043882668f,
- 0.19605257f, -0.008354205f, -0.04698724f, 0.006811343f,
- 0.005805233f, 0.074013196f, -0.0053149457f, 0.017970303f,
- 0.09705182f, 0.015094367f, 0.13610426f, 0.033595614f,
- 0.004773696f, -0.008369559f, 0.0063464325f, 0.010372607f,
- 0.008933314f, 0.015714245f, 0.26891282f, -0.004564453f,
- -0.4925523f, -0.0019142182f, -0.0056068767f, -0.042102046f,
- 0.46688926f, 0.14056534f, 0.034326486f, 2.4671033e-05f,
- 0.018867236f, -0.018121408f, 0.017716624f, 0.0085297655f,
- -0.013790379f, -0.025381375f, 0.0013338419f, 0.0028872015f,
- -0.07527003f, -0.016563619f, -0.012349848f, -0.0051728087f,
- 0.1485284f, 0.007065945f, 0.070351444f, -0.032384083f,
- -0.063420765f, -0.033557255f, -0.013163968f, -0.07130168f,
- 0.012397631f, -0.00075107097f, 0.015355386f, 0.21216102f,
- -0.12007383f, -0.06831785f, -0.06736112f, -0.12065147f,
- -0.0005905027f, -0.0031506892f, -0.039300725f, -0.17031305f,
- -0.019074602f, 0.02588861f, 0.028671533f, 0.017829118f,
- -0.011855851f, -0.006229218f, 0.0009955557f, -0.010490558f,
- -0.61396724f, -0.01126409f, 0.0040372196f, -0.014072541f,
- 0.0076579824f, 0.231613f, -0.03622706f, -0.021314269f,
- -0.0014150573f, 0.53199166f, 0.0074580642f, 0.0028426147f,
- 0.0042075953f, -0.020583069f, -0.025777929f, 0.024104336f,
- 0.0018522649f, -0.12954888f, -0.037047237f, -0.0024924432f,
- -0.039871525f, 0.0137813715f, 0.013532136f, -0.32034668f,
- 0.006201435f, 0.2875235f, -0.16920201f, -0.051966053f,
- -0.030631235f, 0.013398577f, -0.05615137f, 0.013257284f,
- 0.0011755415f, -0.004203332f, 0.09430644f, -0.0074739344f,
- 0.0019785685f, 4.5527988e-05f, -0.002796059f, 0.01842586f,
- -0.023370203f, -0.022370445f, 0.013991342f, 0.014725707f,
- 0.29520467f, -0.05970609f, -0.050917882f, -0.011039068f,
- -0.060025536f, -0.006216453f, 0.15623352f, 0.00797439f,
- 0.017635306f, 0.010569763f, -0.0072496976f, -0.008911623f,
- 0.045389373f, -0.034928747f, 0.019887257f, 0.008165024f,
- 0.0025019706f, -0.0015997898f, -0.006358804f, -0.053849608f,
- -0.0008839239f, -0.026274057f, -0.03648342f, 0.37206063f,
- -0.004815856f, -0.1879526f, -0.017382497f, -0.0035818035f,
- 0.0021441146f, 0.008707179f, 0.0048417035f, 0.22127628f,
- -0.013303866f, 0.006053744f, -0.010192195f, -0.02392005f,
- 0.015756516f, -0.23526584f, 0.0027489166f, -0.177067f,
- 0.13437086f, 0.0079789655f, -0.17691547f, -0.31136534f,
- 0.00459402f, -0.0033744667f, 0.035803925f, 0.008029079f,
- -0.022973273f, -0.020366486f, 0.012154016f, 0.042107463f,
- -0.0020785888f, 0.011263873f, 0.034533408f, 0.003431278f,
- -0.06861265f, 0.00095258176f, -0.0007735222f, 0.003045923f,
- 0.0127097685f, 0.002442129f, -0.31523427f, 0.28348795f,
- 0.015040197f, 0.026155544f, 0.06026255f, 0.0018057306f,
- -0.33680266f, 0.0047776513f, 0.025356153f, -0.121129476f,
- -0.0049173464f, 0.014302191f, -0.013324921f, 0.024767755f,
- -0.035263605f, -0.007362928f, -0.06407235f, -0.0032041566f,
- -0.005643603f, -0.0132663f, -0.002746849f, -0.032538265f,
- -0.0065568695f, 0.011511027f, -0.066545874f, -0.025843551f,
- 0.011323848f, 0.009605953f, -0.008166552f, 0.001709396f,
- 0.017641539f, 0.009767637f, 0.34851065f, 0.0039114156f,
- 0.18407984f, 0.00929557f, -0.011763029f, 0.01710865f,
- 0.027163215f, 0.117424875f, 0.010674342f, 0.005310158f,
- 0.039306287f, 0.004717035f, -0.18405855f, 0.05587181f,
- 0.023250902f, 0.007883767f, 0.010661225f, 0.018207407f,
- 0.0058904076f, 0.018413752f, -0.3538231f, -0.0034097424f,
- 0.06115904f, 0.00696941f, 0.004136427f, 0.03871708f,
- 0.5685236f, -0.04004911f, 0.011021163f, 0.02135451f,
- 0.033313017f, -0.009083755f, 0.0155659625f, 0.0059824754f,
- 0.02768364f, 0.23173794f, -0.0066274726f, -0.0016864687f,
- -0.34221247f, -0.0030165862f, 0.2813109f, 0.007495786f,
- 0.1542964f, 0.018833527f, 0.04006987f, 0.03014058f,
- 0.01780803f, 0.010912405f, 0.02113435f, 0.07903297f,
- 0.0009824353f, 0.0035182438f, 0.013519114f, -0.02502152f,
- 0.14134605f, -0.085768f, 0.093437254f, 0.010764716f,
- 0.00087049295f, 0.0013239349f, 0.044368416f, -0.6821731f,
- 0.00884396f, 0.09999328f, 0.027602393f, 0.019866992f,
- -0.00079503405f, 0.0047233747f, 0.004543028f, -0.024138145f,
- -0.09957576f, 0.0003538026f, 0.21714948f, 0.0056106825f,
- 0.0041527157f, 0.14458941f, -0.03094357f, -0.027214134f,
- 0.0030992613f, 0.08654095f, 0.03430575f, -0.0038799832f,
- -0.0004049894f, -0.050172295f, 0.012094636f, 0.045515515f,
- 0.0064625633f, 0.18619305f, 0.01832772f, 0.00074989116f,
- -0.03156165f, 0.007385143f, 0.0099130375f, 0.42674214f,
- 0.012385211f, -0.11268848f, 0.1790353f, 0.0179664f,
- 0.17141934f, 0.014752388f, 0.014977914f, -0.010319397f,
- 0.01672847f, 0.0017052306f, 0.24053194f, 0.0021349173f,
- -0.010628838f, -0.0075883325f, -0.007866995f, 0.022040723f,
- 0.014203972f, 0.0024037887f, -0.1499192f, 0.022564461f,
- 0.2138391f, 0.00082271075f, -0.010590002f, -0.0019373747f,
- 0.07081854f, 0.0063550244f, -0.07890328f, 0.0012465756f,
- 0.018478468f, 0.012721352f, 0.0005227171f, 0.008738341f,
- -0.15761864f, 0.001985197f, 0.007880017f, 0.006853513f,
- 0.005261352f, 0.003441269f, -0.0026831364f, 0.0025473654f,
- 0.0007237496f, 0.0058846455f, 0.0053291675f, -0.47212344f,
- 0.0021424307f, 0.17639412f, 0.0022469112f, 0.00024333532f,
- 0.007085747f, 0.0042552324f, 0.0036345804f, 0.22025746f,
- -0.024592498f, 0.024487933f, -0.009593738f, 0.0021830762f,
- 0.018403767f, 0.47174993f, 0.0012242222f, -0.4186552f,
- 0.1927056f, -0.0031625868f, 0.23898292f, -0.35369208f,
- 0.0028280935f, 0.00079089054f, 0.082308486f, -0.0033265445f,
- 0.01328087f, 0.0038204095f, 0.017294567f, 0.002288071f,
- -7.92686e-05f, -0.017898435f, -0.06815557f, 0.022446277f,
- 0.009932624f, 0.013275014f, 0.005892175f, 0.0023864359f,
- 0.0057378346f, 0.013734581f, -0.14204225f, -0.1260753f,
- 0.006180807f, 0.04100106f, 0.06345564f, -0.00033492234f,
- 0.019968467f, 0.0065766773f, -0.0013389855f, 0.20904882f,
- 0.004976982f, 0.012708147f, -0.057152156f, 0.06751594f,
- 0.117767096f, 0.0111645935f, -0.1680998f, 0.0012081972f,
- 0.0036160557f, 0.08164993f, 0.00034408123f, -0.011682659f,
- 0.0025911895f, 0.021750573f, 0.029952442f, -0.0045567f,
- 0.011204378f, -0.0028025263f, -0.019961014f, 0.0041202456f,
- 0.0046694926f, -0.00031832396f, -0.6130356f, -0.02946143f,
- -0.12411129f, -0.004325441f, -0.012464275f, 0.013365973f,
- -0.0044388482f, -0.30233592f, -0.014877291f, -0.001243705f,
- -0.12850736f, -0.0195581f, 0.42049974f, -0.11912121f,
- -0.013941671f, -0.00044558954f, -0.0056317016f, 0.012602522f,
- 0.0023136735f, -0.009016528f, -0.12256991f, 0.0051956703f,
- 0.21829413f, -0.0021382899f, 0.0010743415f, 0.046339173f,
- -0.78857034f, 0.5645333f, -0.031890262f, -0.013376697f,
- 0.0010935125f, -0.013559975f, 0.0046154247f, -0.0027299412f,
- -0.0013958048f, -0.15736118f, 0.0018501647f, -0.00326976f,
- -0.23334707f, -0.005572512f, -0.11386875f, -0.011025923f,
- -0.029603587f, 0.0260963f, -0.024826963f, -0.010115404f,
- 0.021243483f, -0.016235419f, -0.035978816f, -0.077931836f,
- -0.004663703f, 0.0011591393f, -0.0049806987f, -0.13056755f,
- -0.041144848f, -0.021891959f, -0.05116447f, -0.15855779f,
- -0.0013801979f, -0.0010680483f, -0.005777684f, -0.7628361f,
- -0.016760023f, 0.025274372f, 0.027137f, -0.005991788f,
- -0.0024700272f, -0.0072212187f, -0.0047658007f, 0.00526932f,
- 0.17722501f, 0.0016435648f, -0.025513493f, -0.0031280182f,
- -0.004783488f, -0.06892282f, 0.007606413f, -0.022046598f,
- -0.0017165303f, -0.037316322f, 0.016834283f, -0.008606601f,
- 7.520021e-05f, 0.026116319f, 0.028325453f, -0.02689123f,
- -0.0057514044f, -0.038235124f, 0.0010068029f, -0.0014864189f,
- 0.0034628282f, 0.0041342787f, 0.00096513017f, -0.24050122f,
- -0.005394458f, 0.112117f, -0.1753825f, 0.029700143f,
- -0.116901144f, -0.0075939493f, 0.07773209f, 0.0022931367f,
- -0.012128562f, 0.0023725352f, -0.038804032f, 0.00045867334f,
- -0.0065714093f, -0.012163156f, 0.00070904935f, 0.0042464677f,
- 0.008640904f, -0.01159555f, -0.05502137f, 0.014491782f,
- 0.35398707f, 0.016114973f, -0.0001432115f, 0.0013168151f,
- -0.04903262f, -0.00029701f, -0.023384633f, -0.00012573115f,
- -0.011557082f, 0.00493222f, 0.0037548966f, -0.0019174027f,
- -0.09905035f, 0.0032458922f, -0.005587657f, -0.0034473632f,
- -0.01635669f, 0.0011858444f, 0.0060670516f, 0.06560674f,
- -3.07416e-05f, -0.00017417228f, -0.0058522313f, -0.0997885f,
- 0.00039003062f, -0.12254439f, -0.021997781f, 0.0002965921f,
- -0.00025299116f, 0.009588805f, 0.0022568624f, 0.10771223f,
- 0.049531255f, -0.008904044f, -0.01600292f, -0.0014254368f,
- -0.0067394776f, -0.105602734f, -0.008274544f, -0.029654615f,
- 0.32977396f, -0.002320067f, 0.04675053f, -0.48436007f,
- -0.0012958334f, 0.043181527f, 0.005243511f, -0.0023180177f,
- 0.0060345936f, 0.004681168f, -0.0012234881f, 0.015269785f,
- 0.0016793679f, 0.026228115f, -0.034082387f, -0.0032331257f,
- 0.0638347f, -0.0004055299f, -0.00047968232f, -0.0074151587f,
- -0.0026186798f, -0.024000326f, -0.12851536f, -0.05271188f,
- -0.0006843639f, 0.028543243f, -0.096231356f, 0.0008178195f,
- 0.18683659f, -0.002370232f, -0.00057135033f, -0.0778313f,
- -0.0018818039f, 0.002783539f, 0.0073601566f, -0.029214421f,
- -0.19937842f, 0.019414086f, 0.23207445f, 0.0016213108f,
- -0.0027965866f, -0.09055437f, -0.0015361469f, -0.010660613f,
- -0.0007681816f, 0.018500092f, 0.060544647f, 0.0062139956f,
- -0.0047945045f, -0.016602179f, -0.05536372f, -0.009089602f,
- 3.7077818e-05f, 0.002521542f, 0.28610507f, -0.017777765f,
- 0.044594396f, -0.0015455777f, -0.007132669f, 0.002782815f,
- 0.03195877f, -0.017607668f, 0.0073256567f, -0.0067444146f,
- -0.13584237f, -0.005028938f, 0.05731144f, 0.13960412f,
- -0.009617473f, -0.008710662f, -0.00022763496f, 0.0018415815f,
- 0.0052303527f, 0.012335253f, 0.30512136f, -0.004759576f,
- -0.4421824f, 0.033405423f, -0.0051226523f, -0.0046670185f,
- -0.16507731f, -0.04262681f, 0.032887317f, 0.018413376f,
- -0.008725877f, 0.1222842f, 0.007028389f, 0.002371087f,
- -0.05518015f, 0.006011439f, 0.0014479569f, -0.0013315298f,
- -0.14712317f, 0.029013041f, -0.4007041f, -0.0040549403f,
- -0.46460417f, 0.007559261f, 0.02643207f, 0.03874424f,
- -0.009549631f, 0.01159254f, -0.039579052f, -0.026932405f,
- -0.0009463958f, -0.0022685016f, 0.008559536f, -0.12269474f,
- 0.19280152f, 0.0010960337f, 0.06669549f, -0.14565839f,
- 0.0012970853f, -0.0027252869f, 0.0047162194f, -0.1835742f,
- -6.399237e-05f, 0.05151434f, -0.13619113f, 0.00566961f,
- -0.016910084f, -0.004149215f, -0.0032073755f, -0.03287087f,
- -0.7468943f, 0.024344679f, -0.05583236f, -0.011091966f,
- 0.0018593234f, -0.10810843f, 0.034810774f, -0.02202457f,
- 0.0006465495f, 0.44345164f, 0.0075730453f, 0.009002128f,
- -0.00081416266f, 0.024822166f, -0.010175626f, -0.040717285f,
- 0.041977026f, 0.0291561f, 0.014737935f, -0.003138475f,
- 0.04323897f, 0.0068557397f, -0.0031067028f, 0.49140513f,
- 0.0062756715f, 0.096085645f, 0.15195458f, -0.016931426f,
- 0.10156895f, 0.007663167f, 0.29663602f, 0.0024847672f,
- 0.0065185395f, -0.0051697763f, -0.14942294f, -0.0010024386f,
- -0.000611867f, 0.008268436f, 0.008925221f, -0.0041256244f,
- 0.046878655f, -0.0030155831f, 0.054445554f, 0.0077389916f,
- 0.36845532f, -0.0516496f, -0.04120198f, -0.008768159f,
- 0.023530878f, -0.007857506f, -0.111732915f, -9.640667e-05f,
- -0.0038199008f, 0.003894769f, 0.013493036f, -0.0016968232f,
- -0.012159287f, 0.035669256f, -0.030093439f, 0.0042625526f,
- -0.0063209417f, -0.0027944478f, -0.006680454f, 0.08302574f,
- 0.000231719f, 0.015221696f, 0.006289151f, -0.04529673f,
- -0.001800929f, 0.18605135f, -0.006819059f, -0.0014795982f,
- 0.0005414707f, 0.033272125f, 0.0019140998f, 0.29910877f,
- 0.0037960515f, 0.011697337f, 0.011191933f, -5.0614467e-06f,
- 0.015008976f, -0.18183978f, 0.0043235812f, -0.04309045f,
- -0.07739594f, 0.0013625893f, -0.03136932f, 0.32820413f,
- 0.0073082484f, 0.06519748f, 0.041299775f, -2.991246e-05f,
- -0.004959156f, -0.011681303f, 0.007027542f, -0.0033905027f,
- -0.0024093434f, 0.020115588f, 0.27169093f, 0.041547816f,
- 0.0810451f, 0.016398655f, 0.00054670515f, -0.010659671f,
- 0.0047241463f, 0.023068644f, 0.3646372f, 0.16125406f,
- 0.006818094f, 0.053417403f, -0.047898166f, -0.0011313327f,
- 0.28594023f, 0.008435952f, 0.0015266733f, -0.122081414f,
- -0.004386983f, -0.00048878224f, 0.06953382f, -0.068105884f,
- -0.14075942f, 0.007524351f, 0.113276824f, -0.004555131f,
- -0.0026417216f, 0.46544236f, -0.0030953223f, 0.014101734f,
- -0.0041981437f, -0.005391754f, 0.027496655f, 0.01625428f,
- 0.0111111095f, -0.0009452616f, -0.08813414f, -0.006876687f,
- 0.011375182f, 0.0015412779f, -0.50550014f, -0.018582802f,
- -0.14564206f, -0.0081056645f, 0.004010407f, 0.0050470685f,
- -0.005505177f, 0.031989485f, -0.0011655836f, 0.0062326053f,
- 0.11917531f, 0.021734599f, 0.06663312f, -0.1288088f,
- 0.045630597f, -0.009703844f, 0.0031912662f, 0.008093674f,
- -0.0009660444f, 0.016259078f, -0.5697133f, 0.00070683047f,
- 0.2077651f, -0.0035870636f, -0.0090180645f, -0.0379578f,
- -0.34577104f, -0.53679913f, 0.017408691f, 0.015169248f,
- 0.052871f, -0.037450597f, 0.002606719f, 0.010730986f,
- 0.013870832f, 0.17899305f, -0.0046554967f, 0.010919943f,
- 0.169246f, 0.0025718187f, 0.17474966f, 0.011277145f,
- -0.07990895f, 0.018856646f, -0.1471768f, -0.06600776f,
- -0.007096291f, -0.0076267687f, -0.053411912f, 0.011447301f,
- 0.00056431687f, 0.0029039534f, 0.018500905f, 0.3781407f,
- 0.019858886f, -0.022830678f, 0.017603224f, -0.0028914711f,
- 0.00025392996f, -0.0041440492f, -0.01777959f, 0.33466655f,
- 0.010211294f, -0.10225638f, 0.21658324f, 0.01100306f,
- -0.012900266f, -0.0046150563f, -0.0099890325f, -0.016538313f,
- -0.10679876f, -0.019812062f, 0.21680395f, -0.0020210831f,
- 0.0027507786f, 0.008107244f, -0.052144237f, 0.00088919024f,
- -0.0023979056f, -0.09517242f, 0.014362246f, -0.028693544f,
- 0.0069471183f, -0.04921555f, -0.053854678f, -0.068631865f,
- 0.009170206f, -0.033806745f, -0.0011709325f, -0.0059452937f,
- -0.027431777f, -0.0050914115f, -0.004918348f, 0.27899918f,
- 0.0053668427f, 0.46407983f, -0.16612744f, 0.008963059f,
- 0.10069211f, 0.01451292f, 0.022400366f, -0.001947036f,
- -0.0022204053f, 0.0023334373f, -0.07671449f, -0.0016780586f,
- 0.0061590318f, 0.008781555f, 0.011273992f, 0.0061002104f,
- -0.041182324f, -0.008817613f, -0.17366257f, 0.0013908776f,
- -0.39910156f, 0.045814943f, -0.00016917087f, 5.5311917e-05f,
- -0.05006843f, -0.008644237f, -0.10142315f, -0.008384802f,
- 0.026520204f, 0.005999422f, 0.0016260417f, -0.0015294683f,
- 0.11723679f, -0.029524501f, -0.01749358f, 0.013705148f,
- -0.0028654712f, 0.0017356371f, 0.0020151257f, 0.026588902f,
- -0.003488277f, -0.01346676f, -0.00018135503f, 0.31560552f,
- -0.005626342f, 0.018466936f, -0.011775917f, -0.0024212298f,
- 0.00034050868f, -0.034481056f, 0.0026650808f, 0.111258075f,
- 0.081300706f, 0.005246925f, -0.026952893f, -0.012987791f,
- 0.009198423f, 0.19193834f, 0.007783068f, -0.33970916f,
- 0.06947986f, -0.0040065884f, 0.049700808f, -0.13616978f,
- 0.007396323f, 0.08476237f, -0.0487685f, -0.003502168f,
- -0.02782093f, 0.01198936f, 0.037769653f, 0.074738584f,
- -0.0011434322f, 0.013294159f, 0.3528996f, -0.046097253f,
- 0.11138363f, 0.009584233f, -0.0015357231f, -0.016086675f,
- 0.019321607f, 0.019752426f, -0.017275011f, 0.20462596f,
- -0.00080784527f, -0.03820639f, -0.109572195f, -0.0029765551f,
- 0.20438665f, 0.010875018f, 0.0062703807f, -0.017382348f,
- 0.0010072335f, 0.024970207f, 0.16774672f, -0.013232833f,
- -0.06402524f, 0.027100177f, -0.12843342f, -0.0019698874f,
- -0.0066205245f, 0.72794414f, -0.004210546f, -0.06013563f,
- -0.0030349074f, 0.037655983f, 0.040865716f, -0.007247618f,
- 0.00646407f, -0.0011822673f, -0.07631864f, -0.006253181f,
- 0.01327445f, 0.0067962743f, 0.22401258f, -0.011578028f,
- 0.037228208f, 0.009012484f, -0.005038117f, 0.03925622f,
- 0.0146646f, -0.10413597f, -0.009607097f, 0.011977544f,
- 0.06651908f, -0.0054815887f, 0.39855364f, -0.03437912f,
- 0.050084207f, -0.00055516727f, 0.010143276f, 0.015330474f,
- -0.0015218691f, 0.015206756f, 0.05110057f, -0.0026331972f,
- 0.24280883f, 0.019349935f, -0.0019800623f, -0.003301147f,
- -0.008587351f, -0.19975488f, -0.0057514417f, 0.013159042f,
- 0.011400281f, 0.16451152f, 0.021901468f, 0.017523028f,
- 0.03362486f, 0.07028009f, -0.0005806571f, 0.0020798843f,
- 0.24447943f, 0.045460768f, -0.073487565f, 0.009572455f,
- 0.103294134f, 0.022779502f, 0.013114322f, 0.04049042f,
- 0.012722884f, 0.02824272f, 0.009050959f, 0.24131027f,
- 0.004787245f, -0.0023169692f, 0.013267768f, 0.027432242f,
- -0.16138569f, -0.02312229f, -0.11927564f, 0.13934931f,
- -0.0035647203f, -0.00026293096f, -0.0027615593f, -0.21581575f,
- 0.0055065765f, 0.36071584f, 0.22154063f, 0.015238779f,
- 0.07337514f, 0.0011697521f, 0.001094908f, -0.037685387f,
- -0.10301118f, 0.010723823f, 0.20577879f, 0.0026547404f,
- -0.001090728f, 0.50490934f, 0.04209597f, 0.07760994f,
- -0.010033443f, -0.54808366f, 0.009184844f, -0.001088148f,
- 0.010771011f, 0.077938445f, 0.050278373f, 0.010669248f,
- 0.02598052f, 0.026240876f, 0.05240062f, -0.0031796673f,
- 0.055852678f, 0.008151671f, -0.008499565f, -0.19657244f,
- 0.0063308193f, -0.00033467033f, -0.053388823f, -0.01497968f,
- 0.36549085f, 0.02027229f, 0.312347f, -0.0037414432f,
- 0.0056692036f, -0.0042741685f, -0.15586251f, 0.0015775647f,
- -0.003954545f, 0.0075614015f, 0.031111795f, 0.012234663f,
- -0.013807673f, -0.014335624f, 0.057678923f, 0.030051108f,
- -0.25968596f, -0.03317103f, -0.00862184f, 0.0017971655f,
- 0.07083683f, -0.00027367802f, 0.28093717f, -0.00050971203f,
- 0.020407762f, 0.0091210725f, 0.014959093f, 0.0054533123f,
- 0.10889542f, 0.04337488f, 0.008621974f, 0.00939548f,
- 0.0075946194f, -0.0053020497f, -0.0036374785f, 0.020572465f,
- -0.0035933466f, 0.02216221f, -0.0027184496f, 0.12628551f,
- -0.0016926569f, 0.042318042f, -0.00029897614f, -0.0017556658f,
- 0.00026213066f, 0.015207704f, 0.012300409f, 0.34948537f,
- 0.032781746f, 0.01957958f, 0.11147889f, 0.016342431f,
- 0.0039957757f, -0.22414732f, 0.0003541229f, -0.040070165f,
- -0.31364435f, -0.0024449169f, -0.094307266f, -0.19285974f,
- 0.011246461f, -0.028454509f, 0.010541127f, 0.0035614036f,
- -0.02066921f, -0.007698609f, 0.008939105f, 0.029117996f,
- -0.0028703213f, 0.034244698f, 0.41565976f, 0.012251456f,
- -0.009408082f, 0.01032286f, 0.00016287265f, 0.0036437172f,
- 0.011874966f, 0.013180968f, -0.022292206f, 0.28869575f,
- 0.004113919f, 0.007592211f, -0.0022166148f, -0.0058437027f,
- -0.26177627f, 0.015566673f, -0.007623297f, -0.08791226f,
- -0.0026257462f, 0.022113899f, 0.12455695f, 0.03496901f,
- -0.14041674f, -0.008407861f, 0.18533501f, -0.0058516506f,
- 0.0019245138f, -0.20643723f, -0.0021779446f, 0.03188146f,
- 0.00026157562f, 0.025690574f, 0.02480171f, 0.022279236f,
- 0.009208561f, -0.0025501223f, -0.08605375f, -0.0052080466f,
- 0.005014265f, -0.001237104f, 0.046255402f, -0.00054694316f,
- -0.08260754f, -0.005947308f, 0.0030364553f, 0.007020573f,
- 7.8552664e-05f, 0.12151088f, -0.0053063342f, -0.00739671f,
- 0.0925889f, 0.010343257f, 0.07975157f, 0.14035138f,
- -0.026326561f, -0.004359117f, -0.0032035396f, -0.00023529115f,
- -0.000890727f, 0.0032461493f, -0.05017323f, 0.003074225f,
- 0.06635781f, -0.0015170069f, -0.0026383735f, 0.025511721f,
- 0.029555403f, 0.1926165f, 0.03448851f, 0.010329867f,
- -0.011645315f, -0.044931002f, -0.008341908f, -0.0053069033f,
- -0.0031005517f, 0.18554926f, 0.0027932243f, -0.0022147933f,
- -0.0943793f, -0.0033837403f, 0.043270964f, -0.008019092f,
- 0.118047625f, -0.0009137363f, -0.038362905f, 0.0028412356f,
- 0.022979485f, -0.0075697554f, 0.0034399051f, 0.070501685f,
- -0.010316607f, 0.0034951777f, 0.00086755794f, -0.15846589f,
- 0.08819447f, -0.051605936f, 0.09042387f, 0.116821535f,
- 0.0020832764f, -0.0015864631f, -0.008286172f, -0.11518154f,
- -0.006516336f, 0.026526455f, 0.017705873f, -0.0042252075f,
- 0.023701068f, -0.00039458546f, 0.00039113863f, -0.0078696925f,
- 0.3265327f, 0.002586898f, 0.15718034f, -0.008351203f,
- 0.00493044f, -0.6122936f, 0.024316141f, 0.018850397f,
- 0.0034479992f, 0.22156426f, -0.005108468f, 0.009618197f,
- -0.0042534517f, 0.031753697f, -0.009139089f, 0.008951166f,
- 0.0037762008f, -0.11276633f, 0.017726084f, -0.00072549045f,
- 0.015661716f, -0.010223426f, -0.0014840971f, -0.065601975f,
- 1.8245495e-05f, 0.14186546f, -0.18857588f, 0.046539728f,
- 0.15053248f, 0.0021543715f, 0.07838574f, 0.00040844627f,
- -0.011573754f, 0.0024307983f, -0.074729145f, 0.0017107138f,
- -0.009861552f, 0.0068221935f, -0.010442084f, -0.008606594f,
- 0.010923603f, -0.00041660204f, 0.028236901f, -0.006465851f,
- 0.20337795f, 0.03654325f, -0.0047226027f, -0.0008139219f,
- 0.009903558f, -0.0047338097f, 0.279816f, 0.00320497f,
- -0.0051409137f, -0.0012393611f, -0.016196959f, -0.0024865742f,
- -0.06913874f, -0.00054846535f, -0.026080308f, 0.0019843911f,
- -0.009940284f, -0.0004364111f, 0.005085091f, -0.0032133642f,
- 0.0014761579f, -0.004469746f, -0.009190423f, 0.2612136f,
- -0.0021365671f, 0.28479156f, -0.002079488f, 0.0025737365f,
- -0.0025828443f, -0.014094677f, -0.0022268458f, 0.32972124f,
- 0.006772975f, 0.0043267068f, 0.07894453f, -0.012564044f,
- 0.0014808222f, -0.40718684f, 0.007710699f, -0.21993895f,
- -0.82182044f, 0.0004473598f, -0.042205937f, 0.14199187f,
- -0.0040599992f, 0.046088472f, 0.025265338f, -0.0005433985f,
- 0.0064255535f, -0.013121273f, 0.0110076675f, 0.03078848f,
- 0.002145228f, -0.013663434f, -0.22480413f, 0.011342699f,
- 0.015731944f, -0.003256557f, 0.0020964032f, -0.02375136f,
- -0.00030854423f, 0.008406728f, -0.11010467f, -0.16371006f,
- -0.008510481f, 0.03299085f, 0.09423087f, 0.0024655787f,
- -0.22044833f, 0.0012182579f, -0.02148802f, 0.031185048f,
- 0.0010706654f, -0.009373015f, -0.0213282f, 0.11577325f,
- 0.03506081f, -0.009990116f, -0.3497258f, 0.002017037f,
- -0.0044350293f, 0.29841322f, -0.0005200604f, 0.0043324507f,
- 1.0206613e-05f, -0.002816503f, -0.0078097233f, -0.0021063131f,
- 0.0030621924f, -0.0022635316f, -0.03379266f, -0.006151144f,
- 0.012222683f, 0.023137236f, 0.34174472f, 0.00703264f,
- 0.52964383f, -0.001609562f, 0.03768301f, 0.017827429f,
- 0.009877183f, 0.55016243f, -0.00016117471f, 0.022866227f,
- -0.10383171f, -0.0061201234f, 0.4418759f, 0.055434834f,
- 0.041860014f, -0.011686561f, 0.01389863f, 0.01930705f,
- 0.0065841097f, 0.02122215f, -0.061651543f, 0.0040538474f,
- -0.33219442f, 0.009772434f, -0.01023043f, -0.0059292726f,
- -0.2293796f, 0.39937153f, 0.006987741f, 0.020408364f,
- 0.07584338f, -0.14516357f, 0.031328905f, 0.0073971543f,
- 0.026298737f, 0.13875297f, -0.0016774167f, 0.005555051f,
- 0.4877798f, -0.006794006f, 0.21642531f, -0.0040437025f,
- 0.22391668f, -0.013643916f, -0.046773028f, -0.03396599f,
- -0.008212748f, 0.00858076f, -0.03012281f, -0.038806602f,
- -0.003922132f, 0.0047661625f, 0.022569312f, 0.050506756f,
- -0.038249146f, -0.10844036f, 0.0042990847f, -0.04393511f,
- 0.0054709404f, -0.00393974f, 0.01750717f, -0.32373658f,
- 0.0021953993f, 0.017661234f, 0.08225373f, 0.023682833f,
- -0.018344833f, -0.0038851073f, 0.0049284454f, 0.025069548f,
- -0.120131195f, 0.0045062955f, 0.11135527f, -0.0048205038f,
- 0.0012118483f, -0.23706311f, -0.023296386f, -0.043443568f,
- 0.005286252f, -0.4241512f, 0.012802708f, -0.032119982f,
- -0.0011277769f, -0.04805552f, -0.02632885f, 0.036462594f,
- 0.007687187f, -0.021835933f, -0.006817727f, -0.0043238183f,
- -0.028201938f, 0.029484034f, -0.002282437f, 0.40846103f,
- 0.0071716183f, -0.21000208f, -0.12744167f, 0.033032358f,
- -0.275443f, 0.025726637f, -0.106562905f, 0.003243997f,
- 0.0056325207f, 0.004694496f, -0.14815749f, -0.004970215f,
- -0.008648405f, 0.008686082f, 0.011348938f, 0.026234297f,
- -0.024629911f, -0.012805153f, -0.079543225f, 0.017443143f,
- -0.41958082f, -0.003580533f, 0.021591466f, -0.0101922015f,
- -0.04882637f, -0.011223711f, 0.12425841f, -0.0010413658f,
- 0.027840065f, 0.012048986f, 0.011360677f, -0.016236985f,
- -0.021059902f, -0.014019865f, -0.005807685f, 0.00762292f,
- 0.007389295f, 0.003766311f, 0.0042276205f, -0.0112076495f,
- -0.0015069812f, 0.011614939f, -0.0110836355f, 0.042455528f,
- -0.00535282f, -0.02924369f, 0.009768862f, 0.0019706348f,
- -0.002584837f, 0.011162698f, 0.008639816f, -0.09108174f,
- -0.07300034f, 0.02920201f, -0.028502477f, 0.00421301f,
- 0.018624445f, -0.5031979f, 0.0051229936f, -0.07828527f,
- 0.32869095f, -0.002947828f, 0.15089475f, 0.28874958f,
- 0.0060855923f, -0.0505009f, -0.06347968f, -0.008167616f,
- -0.0026650375f, 0.0013463426f, -0.02178825f, 0.020854663f,
- 0.00011414544f, -0.008976884f, -0.25331536f, -0.0012630785f,
- 0.029528257f, 0.00569989f, -0.00030620338f, 0.0032798632f,
- 0.011139974f, 0.02348513f, -0.14755504f, 0.099887356f,
- -0.005741467f, -0.02754518f, -0.022394648f, 0.00020510751f,
- 0.10352841f, 0.01348486f, -0.004782509f, 0.067663044f,
- 0.0033293222f, 0.013972282f, -0.09475662f, 0.05628574f,
- -0.086918324f, 0.0049228305f, -0.10483551f, 0.00060783536f,
- -0.007857012f, 0.24418837f, -0.0024366854f, -0.051099636f,
- -0.0050295754f, 0.008075239f, 0.005825328f, 0.0034670068f,
- 0.011337947f, 0.0068822713f, 0.14442055f, 0.00030445866f,
- 0.006743378f, -0.001025262f, 0.058024373f, -0.017041108f,
- -0.058912322f, -0.0030440672f, 0.013748996f, 0.014725468f,
- 0.023910241f, -0.017672984f, 0.012526309f, 0.0024671585f,
- -0.06704254f, -0.008853273f, 0.8087165f, 0.055723358f,
- -0.010762631f, 0.0037594426f, 0.00041893497f, -0.00078702037f,
- 0.0016646419f, 0.0073193912f, 0.050265085f, -0.0032265403f,
- 0.06853726f, 0.04933302f, 0.0051937522f, -0.04688444f,
- 0.10013189f, -0.3049905f, 0.018374491f, 0.003287354f,
- 0.011081405f, 0.00087587856f, -0.02525561f, 0.011012205f,
- 0.0065214694f, 0.104912095f, -0.00040443632f, -0.0075354045f,
- -0.040761277f, 0.011028063f, -0.0025658922f, 0.005537136f,
- -0.24657115f, -0.004684173f, -0.0057785884f, 0.036154702f,
- -0.005902455f, 0.012546671f, -0.03329644f, 0.03418642f,
- 0.0014929877f, 0.0008877198f, 0.0067649074f, 0.053166047f,
- 0.06687595f, 0.061141893f, -0.022171095f, -0.021134028f,
- -0.0018903849f, 0.0018057198f, -0.031164305f, 0.5634761f,
- 0.010804048f, 0.09373491f, 0.10524275f, 0.0042473236f,
- -0.074392654f, 0.004268486f, -0.0034653784f, 0.0035229237f,
- -0.013677562f, 0.0037818784f, 0.08206273f, 0.008494866f,
- 0.0066555934f, -0.6664512f, 0.006449347f, -0.0014226881f,
- -0.0041162465f, 0.24254797f, -0.021987423f, -0.016101843f,
- -0.0051454864f, 0.0058630332f, 0.115810916f, 0.020599486f,
- 0.031515494f, 0.023364753f, 0.008329445f, 0.0026256866f,
- -0.00424186f, -0.019476468f, -0.027392985f, -0.21399201f,
- 0.0004512646f, -0.04647995f, -0.06031758f, -0.027335797f,
- 0.15076992f, 0.008149417f, 0.06954173f, -0.0018209376f,
- 0.015836673f, 0.0021510364f, -0.17065193f, 0.0034462018f,
- -0.006233445f, 0.0025461307f, -0.0098810075f, 0.004168156f,
- 0.00065526256f, -0.008410521f, -0.12138243f, 0.012819369f,
- 0.23175974f, 0.009889783f, -0.0041308645f, 0.0052488684f,
- 0.000475255f, 0.004132255f, -0.3834532f, 0.0016821725f,
- -0.006067955f, 0.0012983017f, -0.0009792756f, 0.0016389334f,
- 0.0997516f, 0.0034269202f, 0.0127745755f, 0.0077917487f,
- 0.0067927237f, -0.0038610306f, -0.0044975323f, -0.043316334f,
- -0.0027144146f, 0.027651073f, 0.014792015f, -0.09852378f,
- 2.334302e-05f, -0.3554155f, -0.0015525738f, -0.00039247292f,
- -0.0051648794f, 0.029396659f, -0.00084416696f, 0.5914207f,
- 0.018252304f, 0.007951987f, 0.135595f, 0.00387854f,
- -0.00899016f, -0.0035133134f, 0.005853511f, 0.037851237f,
- 0.12292184f, 0.0006193803f, 0.07998678f, -0.084746964f,
- -0.0012262425f, 0.004037612f, -0.070234194f, 0.0041833874f,
- -0.0394372f, -0.0053256494f, 0.011399475f, 0.031556703f,
- -0.0008791408f, -0.0001286753f, -0.32895714f, -0.03325593f,
- -0.022154888f, 0.022388065f, -0.0052336347f, -0.015807336f,
- 0.0075433017f, 0.0027155161f, -0.09835234f, 0.21701826f,
- 0.0012337719f, -0.034910515f, -0.04314976f, -0.0025791624f,
- -0.14302246f, -0.0011291024f, -0.011294791f, 0.12957937f,
- 0.0033717246f, 0.0010591777f, 0.09856249f, 0.050844748f,
- -0.01851935f, 0.00056431314f, -0.15304044f, 0.0046777716f,
- -0.004201388f, -0.6563093f, 0.0012768045f, 0.006844156f,
- 0.0005405163f, 0.015252491f, 0.034694076f, 0.03161216f,
- -0.008728137f, 0.0042801597f, 0.0544769f, -0.014492783f,
- -0.002793333f, 0.003678444f, 0.054849286f, 0.014212855f,
- -0.018259306f, -0.0069079683f, 0.043758094f, -0.0036893578f,
- -0.0079887025f, 0.3075636f, -0.006830559f, 0.00421013f,
- -0.044992607f, -0.019577874f, -0.056386854f, 0.041525975f,
- -0.024817618f, 0.006235575f, -0.0010184315f, 0.005466249f,
- 0.0006083904f, -0.008159524f, -0.18005386f, 0.0007930024f,
- 0.28525472f, -0.012766977f, 0.0054955618f, 0.036473446f,
- -0.022375649f, -0.81374806f, 0.019825045f, -0.018959306f,
- 0.0057160403f, -0.18653268f, 0.0048209624f, -0.019781422f,
- 0.00075135607f, 0.0031389168f, -0.005520168f, 0.0020017715f,
- 0.6976741f, -0.018378016f, -0.22914621f, -0.0028340511f,
- 0.06669481f, -0.02324296f, 0.11267749f, 0.0075269397f,
- 0.042259753f, 0.0028709008f, 0.02775437f, -0.09149285f,
- -0.0057283156f, 5.7725698e-05f, -0.0050103525f, -0.09097373f,
- 0.05135256f, -0.08738296f, -0.10221193f, -0.25088382f,
- 0.0004568385f, 0.0017672231f, 0.017795218f, -0.5106263f,
- -0.0030796356f, -0.09266548f, 0.016019145f, -0.0003048183f,
- -0.0554576f, -0.0016233885f, -0.0029687188f, 0.024612512f,
- 0.044544917f, -0.027985271f, -0.09176202f, 0.003168198f,
- -0.004769082f, 0.3325845f, -0.003930059f, -0.04597863f,
- 0.0010759315f, 0.500115f, -0.014327303f, -0.024734845f,
- -0.0066701923f, -0.0032874253f, 0.044649243f, 0.061104976f,
- -0.0134594105f, -0.027516682f, -0.009259187f, -3.6734764e-05f,
- -0.021213336f, 0.011413443f, -0.010197152f, -0.33095363f,
- -0.009583345f, -0.115555204f, 0.2312482f, 0.047906153f,
- -0.052238435f, -0.011342183f, 0.03133229f, -0.003407469f,
- -0.007685376f, 0.0020140295f, -0.15555544f, 0.0010541535f,
- 0.0070185685f, -0.0055677104f, -0.003968152f, 0.012065437f,
- -0.004383572f, 0.014746869f, 0.030123048f, 0.005002083f,
- 0.19716698f, 0.045850698f, 0.013245194f, -0.0011128577f,
- -0.013714455f, 0.0049802507f, 0.00447708f, -0.007743358f,
- -0.0007382812f, 0.0010228019f, -0.010902709f, -0.00042852425f,
- -0.3526492f, -0.02268493f, 0.017233843f, -0.0070256228f,
- 0.028812123f, 0.00011282849f, 0.00025874423f, 0.006716067f,
- -0.0020169585f, 0.0085929f, -0.012852336f, -0.17157552f,
- 0.0012807825f, -0.19870374f, 0.031609148f, -0.0019313568f,
- -0.0026370997f, -0.01154453f, 0.004237775f, 0.21131133f,
- -0.060621977f, -0.007969348f, 0.070436016f, 0.0055717323f,
- 0.0140533f, -0.36374116f, -0.008466014f, 0.39372113f,
- 0.18074226f, -0.0031122668f, -0.03973252f, 0.45291927f,
- 0.00073044916f, -0.095783405f, 0.05035624f, -0.0045591113f,
- 0.043106966f, 0.00796541f, -0.034288406f, -0.022972506f,
- 0.0010325001f, -0.032109406f, -0.19648854f, 0.035505015f,
- -0.030703248f, -0.01619399f, 0.0002909787f, 0.0037629153f,
- -0.009799664f, -0.019956227f, -0.13329637f, -0.10499014f,
- -0.0049561383f, 0.018515842f, 0.12871805f, -0.0012789355f,
- 0.027271135f, -0.0006964664f, 0.0023785094f, -0.06171621f,
- 0.0023503501f, 0.00019917214f, 0.0075531784f, 0.12526295f,
- 0.17496061f, -0.0004662974f, 0.093976535f, 0.0033766902f,
- -0.0003792588f, -0.002458115f, 0.00088391884f, -0.015944507f,
- 0.00090597116f, -0.02622026f, -0.048799716f, 0.00533903f,
- 0.006380375f, 0.01749425f, 0.024741821f, -0.000642948f,
- -0.010360237f, 0.0053890385f, -0.26453617f, -0.027450377f,
- 0.1539258f, -0.011288393f, 0.021401193f, -0.009938412f,
- -0.0059376494f, 0.053914856f, -0.004013025f, -0.0025643613f,
- -0.10573814f, -0.002165234f, -0.453744f, 0.15945604f,
- -0.044455096f, -0.003657761f, 0.0053727813f, -0.0072479593f,
- 3.2506455e-06f, -0.006087812f, 0.40566048f, 0.004679202f,
- 0.04678405f, 0.0003416025f, -0.006962268f, 0.01984997f,
- -0.57150316f, -0.0026512095f, 0.0052725696f, -0.0039745066f,
- 0.0015195834f, 0.05334372f, -0.01547645f, -0.005391699f,
- -0.03916836f, 0.07656168f, -0.00029202722f, -0.00058747287f,
- 0.14888936f, 0.013663887f, 0.07055258f, -0.004076396f,
- -0.3567617f, -0.008721569f, -0.089059785f, 0.0033458865f,
- 0.06207651f, -0.0057011624f, -0.05051099f, -0.005510616f,
- -0.010571769f, 0.0034163631f, -0.003527637f, -0.1207567f,
- -0.22354846f, 0.18659171f, 0.21397813f, 0.13691242f,
- 0.00012444048f, -0.0007666f, -0.018496767f, -0.17729436f,
- -0.0016683879f, 0.19467862f, 0.028847516f, -0.004196645f,
- -0.0030822053f, -0.0076266453f, 0.0031956246f, -0.009603852f,
- 0.19226535f, 0.030625274f, 0.08274375f, -0.008544009f,
- 0.0018028528f, -0.03570806f, 0.029996946f, 0.015307062f,
- -0.0010514228f, 0.29751638f, -0.00747065f, 0.009122399f,
- -0.0023053717f, 0.054583065f, -0.04256552f, -0.038354147f,
- 0.004481129f, -0.041208997f, 0.029077385f, -0.00075555436f,
- 0.0560583f, -0.006229076f, -0.0101188645f, 0.33803713f,
- -0.005319882f, -0.5810736f, 0.1362812f, 0.015204798f,
- -0.051718935f, -0.0020980798f, 0.16938607f, -0.0014672972f,
- -0.0036364773f, 0.003236665f, -0.35301518f, -0.0004226968f,
- -0.003464035f, -2.1626714e-05f, 0.02295943f, 0.00280547f,
- 0.018409459f, -0.01047531f, -0.057966292f, -0.013579993f,
- -0.6332469f, -0.0055178804f, -0.021193104f, -0.014530998f,
- -0.027193664f, -0.0024791074f, -0.069445975f, -0.0013877067f,
- -0.008490854f, 0.0015463574f, 0.003173036f, -0.015156314f,
- 0.17029275f, 0.016212467f, -0.005440943f, -0.00013076513f,
- -0.01996173f, 8.7526125e-05f, 0.009330858f, 0.0028713075f,
- -0.00064376206f, 0.011675501f, -0.035605494f, 0.053720914f,
- -0.0036309732f, -0.25683597f, -0.030659262f, -0.000390866f,
- 0.00685621f, -0.029189436f, 0.0045059067f, 0.54146576f,
- 0.022778226f, -0.008226722f, 0.13333145f, 0.00062055606f,
- -0.017132672f, 0.49794012f, -0.0021731912f, 0.1500556f,
- 0.058193892f, -0.005467059f, -0.09774418f, 0.0181019f,
- 0.005789105f, 0.047382295f, -0.004771154f, -0.006058251f,
- 0.012782927f, 0.008575942f, -0.019303337f, 0.027265174f,
- 0.004218955f, 0.011627564f, -0.22591352f, -0.011579417f,
- -0.025402697f, 0.00039159943f, -0.0008706737f, -0.0077903615f,
- 0.0010628563f, 0.00078716787f, 0.04254597f, 0.078439645f,
- -0.010326997f, -0.019546334f, -0.118355066f, -0.0020456926f,
- -0.46577123f, 0.01068074f, -0.0103053665f, 0.07066576f,
- -0.00047039933f, -0.011509828f, 0.009886725f, 0.04314933f,
- 0.02464419f, -0.0069680633f, -0.30924097f, -0.00063229515f,
- 0.0009069659f, 0.3039606f, -6.859704e-05f, 0.07992739f,
- -0.0026917194f, 0.0014425991f, 0.036425028f, 0.00796857f,
- -0.014192695f, 0.00016073498f, 0.0053077233f, 0.004303847f,
- 0.011672746f, 0.028052216f, -0.41949466f, -0.02045236f,
- 0.21097383f, 0.0051568863f, 0.029101182f, 0.01948858f,
- 0.002994943f, -0.02510661f, 0.0043550534f, 0.020113554f,
- -0.017864166f, 0.018548185f, -0.18456335f, -0.17205606f,
- 0.09069137f, 0.0014546051f, 0.004549406f, 0.033576313f,
- 0.0030941854f, 0.01624741f, 0.40017077f, -0.001416636f,
- 0.17201924f, 0.023156367f, 0.0012718248f, -0.033261858f,
- 0.1833946f, -0.22813284f, 0.013916487f, 0.011413264f,
- 0.018623345f, 0.045160893f, 0.057104036f, 0.01999819f,
- 0.04093567f, -0.06883314f, -0.007589125f, 0.0100543685f,
- -0.11082888f, 0.028878499f, 0.07465707f, 0.006770507f,
- 0.19596152f, 0.027476028f, 0.03692842f, 0.010524358f,
- -0.016262397f, -0.006516254f, 0.0037582978f, -0.21047162f,
- 0.015789304f, 0.00320693f, 0.017301627f, 0.089784294f,
- 0.04188983f, -0.02866054f, -0.22194596f, -0.09590883f,
- -0.0013200111f, -0.00016726229f, 0.0005733983f, -0.30196708f,
- 0.00092311716f, -0.45200852f, -0.029002162f, 0.021692708f,
- -0.033219814f, 0.0033553431f, 0.0037486844f, 0.018573172f,
- 0.21334238f, -0.0070415568f, -0.04988512f, 0.0019222852f,
- 0.0076424005f, -0.6722263f, 0.044790514f, -0.08129089f,
- 0.0018280243f, -0.6066714f, 0.044592623f, -0.018588394f,
- 0.013011475f, 0.046043634f, 0.09175424f, 0.019658508f,
- 0.03548091f, -0.008292418f, 0.0041765664f, -0.0006027205f,
- 0.027184168f, 0.030067274f, 0.009973293f, 0.059056737f,
- 0.01616249f, 0.22529517f, -0.0012105226f, -0.0144727295f,
- 0.010770752f, 0.016880644f, -0.13855268f, 0.0070181275f,
- 0.010266103f, 0.0017549383f, 0.18090682f, -0.0034298017f,
- 0.012580694f, 0.0021073336f, 0.017604543f, 0.017866846f,
- -0.012939873f, -0.012282297f, 0.11600256f, 0.029183382f,
- 0.15095513f, -0.003960806f, 0.0129083935f, -0.0014659005f,
- 0.0154679855f, 0.000604669f, 0.10665721f, 0.0014224172f,
- 0.044131584f, 0.022977538f, 0.011259388f, 0.0018918441f,
- -0.21143909f, 0.008278763f, 0.026883794f, 0.013875522f,
- 0.013566983f, 0.0015483692f, 0.0028676922f, 0.068639725f,
- -0.0006022803f, 0.0061591617f, 0.004753047f, 0.2720324f,
- -0.0007939686f, -0.16378517f, 0.008577165f, 0.00030789032f,
- 0.006390912f, 0.025110593f, 0.006798893f, 0.33173555f,
- 0.06329981f, 0.014759393f, -0.14529955f, 0.0028877174f,
- 0.015007467f, 0.4636373f, 0.0034616254f, -0.05887624f,
- -0.062803775f, 0.0073363855f, 0.037758347f, 0.51654774f,
- 0.008971f, 0.04441623f, 0.0071564f, -0.0011020418f,
- 0.011508748f, -0.00558548f, 0.004051969f, 0.08513983f,
- 0.0017744069f, 0.013450424f, 0.52260965f, 0.023688382f,
- 0.10535918f, 0.020701746f, -0.00070599274f, 0.020706236f,
- 0.012414538f, 0.011186954f, -0.2110454f, -0.11645164f,
- 0.017962324f, 0.024115054f, -0.026850455f, 0.0009568163f,
- 0.0063860873f, 0.009360817f, 0.028400058f, -0.07288133f,
- 0.005620091f, 0.033520587f, 0.03188922f, -0.12925161f,
- 0.021619527f, 0.02204866f, 0.38007087f, 0.009183881f,
- 0.0026769359f, -0.00787106f, -0.0007572186f, 0.0053221383f,
- -0.0009968643f, 0.027462838f, 0.0916856f, 0.008754095f,
- 0.0146901095f, 0.007972928f, 0.05165128f, 0.0015285903f,
- -0.004636616f, 0.009743438f, -0.13631004f, -0.016177222f,
- 0.19027801f, -0.0041513275f, -0.0068386006f, -0.0065889773f,
- -0.008574995f, 0.15042767f, -0.016070787f, 0.004072964f,
- -0.046575956f, -0.01700411f, 0.05691949f, -0.039435975f,
- 0.019955054f, -0.016456181f, 0.01067398f, 0.011772197f,
- 0.005467863f, -0.00067644275f, -0.17149845f, -0.007643979f,
- -0.11714122f, -0.018809937f, -0.019302484f, -0.081126876f,
- 0.086448275f, 0.11964686f, -0.012852038f, 0.0059380713f,
- 0.014561854f, 0.05834195f, 0.018195806f, -0.010451634f,
- 0.012544452f, -0.031765297f, -0.011260656f, -0.00783913f,
- -0.06480519f, -0.019440744f, -0.06919132f, -0.009947953f,
- -0.02673653f, -0.039931014f, -0.065527394f, -0.020047814f,
- -0.038977586f, -0.017389588f, -0.046309732f, 0.11494867f,
- -0.011529947f, -0.006714785f, 0.0031407776f, -0.0058775987f,
- -0.07287307f, -0.11620867f, -0.031384427f, 0.1165233f,
- -0.0037044324f, -0.0056348704f, 0.026362093f, 0.1655151f,
- -0.012324054f, -0.031703293f, -0.06883587f, 0.011448547f,
- 0.068929434f, -0.017145647f, 0.007265652f, 0.006640547f,
- -0.05072122f, 0.01295924f, 0.03925297f, -0.022953669f,
- 0.004847822f, -0.025098298f, -0.014399359f, -0.0071539884f,
- -0.0057709618f, 0.0578963f, -0.012471563f, -0.009364343f,
- -0.0062582046f, -0.016648848f, -0.00142f, -0.049526244f,
- -0.015155491f, -0.09906719f, -0.018888306f, -0.0036710375f,
- 0.0002422918f, 0.0107219275f, -0.028560953f, 0.009493499f,
- -0.010060579f, -0.13303581f, 0.026583498f, -0.08563384f,
- -0.05073781f, 0.0087209735f, -0.084181115f, 0.006346423f,
- -0.012069089f, -0.0074952524f, 0.059091613f, -0.008783612f,
- -0.0107924845f, -0.008012274f, -0.0044295243f, 0.010156077f,
- 0.002800338f, -0.016356578f, -0.10967481f, 0.0019999833f,
- -0.14145558f, -0.03780753f, 0.017982746f, -0.019652996f,
- -0.05459057f, -0.016177762f, -0.06284574f, -0.0060182586f,
- 0.018241033f, 0.0035085452f, -0.030282049f, -0.02171506f,
- -0.013490108f, -0.015426437f, 0.021970278f, 0.0037558437f,
- -0.012897245f, -0.0041715354f, -0.0075004976f, -0.055050205f,
- -0.006012553f, -0.0028188536f, -0.026403181f, -0.0682063f,
- -0.011762416f, 0.09249254f, -0.039200757f, -0.010564122f,
- 0.008836479f, -0.007100971f, 0.010353421f, 0.09090824f,
- -0.051612142f, 0.00535828f, -0.023273151f, -0.005012543f,
- 0.0028888094f, -0.009313499f, -0.001032057f, 0.05499404f,
- -0.097571656f, 0.008710135f, -0.14698818f, 0.08921492f,
- 0.005907909f, -0.012561229f, -0.06699732f, 0.011050924f,
- -0.07177284f, 0.0080632055f, -0.030885631f, -0.024131045f,
- -0.006003334f, -0.005962128f, -0.0029736916f, -0.08871809f,
- -0.04316797f, -0.011165601f, -0.00057215564f, 0.00649828f,
- 0.0057349545f, -0.0066136047f, 0.041355424f, -0.030610602f,
- -0.016385617f, -0.08125657f, -0.07446056f, -0.0010968635f,
- -0.05109031f, -0.00022005073f, -0.014878542f, -0.019100003f,
- 0.006908897f, 0.006255416f, 0.022068236f, -0.03470117f,
- -0.15502487f, 0.008637728f, 0.09075053f, 0.0034814246f,
- 0.012080888f, 0.11766583f, -0.007439009f, -0.01702483f,
- -0.016412787f, -0.01340385f, -0.027573675f, -0.00038537878f,
- -0.010290407f, -0.0019164116f, 0.08277911f, 0.0011838584f,
- -0.013500567f, -0.009522839f, -0.0020495355f, -0.02218411f,
- -0.06307037f, -0.008400939f, -0.08919201f, -0.029049506f,
- -0.01723471f, -0.08269396f, -0.0015616853f, -0.010884397f,
- -0.0040517277f, -0.03578319f, 0.16285762f, 0.055700775f,
- -0.071978256f, 0.009279537f, -0.0154772f, -0.016737696f,
- -0.0115232915f, -0.022876183f, 0.09785864f, -0.0020389678f,
- 0.10291452f, -0.027096393f, 0.004579488f, -0.05502411f,
- -0.13669409f, 0.061231036f, -0.051598057f, -0.017763471f,
- -0.058900815f, -0.03303249f, -0.029983416f, -0.013548826f,
- -0.05359357f, -0.0012780752f, -0.0076060174f, -0.009685261f,
- -0.04689923f, -0.008627857f, -0.10322673f, -0.0067227376f,
- -0.18870491f, -0.03687977f, -0.1127711f, -0.042541802f,
- -0.03573032f, -0.035571627f, -0.025222307f, 0.031119397f,
- -0.004759111f, -0.00639762f, -0.02595637f, -0.1068997f,
- -0.077457055f, 0.017783735f, -0.07748808f, 0.0576268f,
- -0.005501133f, -0.000523357f, -0.013242243f, -0.04142053f,
- -0.011952356f, -0.0051856483f, -0.06237529f, -0.017381936f,
- 0.0033990713f, 0.002787263f, -0.018065613f, -0.03327598f,
- 0.17668657f, -0.020943876f, -0.02732877f, -0.0062490245f,
- -0.016958471f, -0.341473f, 0.051191505f, 0.0036385052f,
- -0.012724677f, 0.14320219f, -0.038796827f, -0.025796575f,
- -0.0049796454f, -0.0057287454f, -0.11123311f, -0.079231285f,
- -0.02914108f, -0.08602285f, -0.027873788f, -0.000669452f,
- 0.0037134131f, -0.020720605f, 0.0029561198f, -0.10377167f,
- -0.008589802f, 0.15267582f, -0.46174335f, -0.048968103f,
- 0.15055475f, -0.014606112f, 0.077306755f, -0.001422148f,
- -0.006771708f, -0.0065438356f, -0.15393949f, -0.010714429f,
- -0.023537615f, -0.018628625f, -0.015940806f, -0.0065925387f,
- 0.0012666371f, -0.017470827f, -0.060321424f, -0.030549929f,
- -0.017135222f, -0.033799488f, -0.04828633f, 0.0018098021f,
- 0.016775154f, 0.008343234f, 0.0943102f, -0.020444455f,
- -0.03770726f, -0.005560117f, -0.018424215f, 0.0056292163f,
- 0.017162085f, 0.02944775f, -0.053072605f, -0.01479304f,
- -0.022814017f, -0.0030777033f, 0.0026905758f, -0.06030447f,
- -0.0036043883f, -0.020214587f, 0.0019905216f, 0.048570823f,
- 9.69271e-05f, 0.074100345f, -0.043993678f, -0.0068205306f,
- -0.019049365f, -0.04951228f, -0.0012027838f, -0.060182657f,
- -0.016605124f, -0.02264149f, -0.021053946f, -0.009127886f,
- -0.034632724f, 0.114917375f, -0.015818395f, -0.11261067f,
- -0.19206697f, -0.007716286f, -0.12243851f, -0.09788195f,
- -0.0046099504f, -0.020077659f, -0.06380329f, -0.00084579573f,
- -0.026223175f, 0.009585278f, -0.017918685f, -0.0715227f,
- 0.000646428f, 0.00888671f, -0.12396681f, -0.07366249f,
- -0.06684337f, -0.016273791f, -0.0064266142f, -0.005302636f,
- -0.021065092f, -0.026886525f, 0.13558878f, -0.032334365f,
- -0.009258364f, -0.07402955f, 0.07964694f, -0.0072029713f,
- -0.11763772f, -0.015405314f, -0.023885978f, -0.039143592f,
- -0.0220459f, -0.023563677f, 0.062091954f, -0.075085126f,
- -0.10601316f, 0.006081701f, -0.011729602f, -0.016896715f,
- -0.01047973f, 0.17883763f, -0.00024473667f, -0.011770583f,
- -0.008457084f, -0.016437253f, 0.0035207116f, -0.008413713f,
- -0.035285242f, -0.022506792f, -0.056211524f, -0.037076376f,
- -0.001299664f, -0.0024680425f, 0.019034874f, -0.017457677f,
- -0.11462125f, 0.00483501f, 0.0045245048f, -0.026402324f,
- 0.0073298905f, 0.0772757f, 0.0004930905f, 0.0028119804f,
- 0.04732774f, -0.0071406006f, 0.22013967f, 0.091881834f,
- -0.035070356f, 0.010007076f, 0.0031075643f, -0.014575004f,
- -0.002973037f, 0.00048791635f, 0.02499193f, -0.0010428663f,
- -0.111930825f, 0.012629345f, 0.0071682455f, 0.040835124f,
- -0.025646042f, 0.007840885f, -0.00012008881f, -0.002864337f,
- -0.01708124f, 0.23517145f, -0.013602802f, -0.0036103723f,
- -0.019686867f, 0.08494912f, -0.0039785365f, -0.0017933256f,
- -0.09212906f, 0.011221967f, -0.053393573f, -0.023852162f,
- 0.07340088f, -0.0020100186f, 0.011107072f, 0.022900177f,
- 0.06841986f, -0.008884195f, 0.03543507f, 0.20085728f,
- -0.003302653f, -0.0014852129f, -0.0031129676f, -0.04746893f,
- -0.060539506f, 0.013755042f, -0.109243974f, 0.21716025f,
- -0.00023591328f, 0.0051986077f, 0.076865226f, -0.009646504f,
- -0.028074186f, 0.08754107f, 0.0063708713f, 0.004464078f,
- 0.090798706f, 0.00016264532f, -0.0046164063f, -0.04872417f,
- -0.04080452f, 0.022545418f, 0.034481976f, -0.018386846f,
- -0.0065073473f, 0.034128867f, 0.06330792f, 0.09010733f,
- -0.0029229566f, -0.1559824f, -0.009477727f, 0.0059959837f,
- -0.014807526f, 0.05677359f, -0.045141626f, -0.018651307f,
- 0.019869996f, -0.040965505f, 0.024064941f, 0.0029538183f,
- 0.027068796f, -0.0019419095f, -0.02641855f, 0.1321638f,
- 0.0034861295f, -0.029807804f, -0.051040925f, 0.067279f,
- 0.019229092f, 0.004417104f, 0.11308144f, 0.00023535163f,
- 0.00520721f, -0.0006361423f, -0.14945683f, 0.0016113549f,
- -0.0052588917f, 0.00036342622f, -0.017043522f, -0.0018744279f,
- 0.035144813f, -0.02213246f, 0.027901392f, -0.033614147f,
- -0.100177795f, -0.013676059f, -0.022475824f, -0.004668773f,
- 0.0037534502f, 0.009280064f, 0.35935023f, -0.006359907f,
- -0.01462047f, 0.0035773541f, -0.0128852315f, -0.0025307464f,
- 0.04789214f, 0.026006555f, -0.033386987f, -0.0027552263f,
- 0.0094859125f, -0.0022012785f, -0.0032315054f, 0.025544785f,
- 0.0010944225f, 0.006811742f, -0.035693698f, 0.0967948f,
- 0.0034560147f, 0.073412165f, -0.00838769f, 0.00045430483f,
- -0.0016824584f, -0.0055645173f, 0.006808195f, 0.026101958f,
- 0.08934552f, -0.0019129966f, 0.10713367f, 0.0030635614f,
- -0.0040853857f, -0.068265215f, -0.00867416f, 0.008895367f,
- -0.21783826f, 0.004447457f, -0.08654909f, -0.04102869f,
- 0.017133595f, 0.077777624f, 0.025606746f, 0.003082965f,
- 0.0043941895f, 0.012648418f, 0.049489588f, 0.06897138f,
- 0.00055326294f, 0.011650927f, -0.016300531f, -0.014991299f,
- 0.041419726f, 0.008379353f, 0.00044694345f, -0.008341327f,
- -0.0018103387f, -0.007869061f, 0.13067861f, 0.014502151f,
- -0.0054440047f, 0.014970577f, 0.043327317f, -0.002192951f,
- -0.14865868f, 0.015179597f, -0.01871067f, -0.016584603f,
- 0.00091260613f, -0.021008043f, -0.0009872171f, 0.039179318f,
- 0.03967906f, 0.018450517f, 0.11082973f, 0.0010417491f,
- 0.00020478349f, 0.11131959f, 0.0026666077f, 0.025691917f,
- 0.00041907243f, 0.02123984f, 0.044773947f, 0.00846327f,
- -0.0066132788f, 0.0050181895f, -0.021716675f, -0.023066528f,
- -0.006461453f, -0.002860064f, -0.25872973f, -0.02584033f,
- 0.14644654f, -0.00067674107f, -0.01827124f, -0.0027857495f,
- 0.021373732f, 0.07039539f, 0.004864486f, -0.010959522f,
- 0.11835477f, 0.016876658f, -0.08089838f, 0.10352596f,
- -0.0065485043f, 0.013744915f, -0.0035109858f, -0.005767451f,
- -0.0024113504f, -0.010957472f, 0.081595056f, 0.00027036457f,
- -0.11355669f, 0.033193115f, 0.010424465f, -0.02341748f,
- 0.17848454f, -0.092829525f, 0.0391176f, -0.006594095f,
- -0.03257118f, -0.05975181f, -0.013010266f, 0.00029502084f,
- -0.021161674f, 0.04363701f, -0.015430892f, 0.000409588f,
- 0.12852775f, -0.01271176f, 0.081539504f, -0.008298646f,
- -0.03069646f, -0.02015889f, 0.0509184f, -0.010852495f,
- -0.03820022f, 0.00199667f, -0.006380524f, 0.08807583f,
- 0.0014786227f, -0.0036997488f, -0.01344947f, 0.022874713f,
- -0.068418086f, -0.035149198f, -0.054427132f, 8.656874e-05f,
- -0.003113102f, -0.0026929113f, 0.016194453f, 0.061497264f,
- -0.009649352f, -0.17159928f, -0.018773306f, -0.010072788f,
- -0.005705153f, 0.005605885f, -0.005320508f, 0.004345263f,
- 0.020646175f, -0.014630988f, 0.017814564f, 0.0024865181f,
- -0.011909088f, -0.1991093f, -0.00656708f, 0.0013927107f,
- -0.0102026025f, 0.042609587f, -0.012769387f, 0.04736983f,
- -0.014265722f, -0.021563845f, -0.024931123f, 0.012787231f,
- 0.022571072f, -0.2044017f, -0.034191895f, -0.0037832556f,
- -0.03303907f, -0.0059708115f, -0.013459476f, -0.030127734f,
- -0.000104819366f, 0.22229753f, -0.08535589f, -0.07708527f,
- -0.06870186f, -0.0085138315f, -0.119629756f, -0.0047821263f,
- 0.010921236f, -0.0029553915f, 0.06415916f, -0.006265256f,
- -0.015812952f, -0.019471524f, -0.04428845f, -0.0015720574f,
- 0.022530366f, -0.017641421f, -0.08054364f, -0.000856906f,
- -0.09991743f, -0.0910847f, -0.011495886f, 0.0016542937f,
- -0.063701384f, 0.01122352f, 0.04307495f, -0.010659861f,
- -0.01725397f, -0.002042839f, -0.023771837f, 0.009378417f,
- 0.037814625f, -0.024817267f, -0.010595405f, -0.012850594f,
- -0.033260264f, -0.0041866754f, 0.0019177127f, -0.08520456f,
- -0.00674226f, -0.003374232f, -0.027814114f, 0.07243287f,
- 1.4787643e-05f, -0.17164189f, -0.062373124f, -0.001415342f,
- -0.009223239f, 0.023102447f, -0.013387928f, 0.20904613f,
- 0.00915966f, -0.009036809f, 0.018177547f, -0.013467015f,
- -0.005640997f, 0.23305179f, -0.019163791f, 0.07989377f,
- 0.009232488f, -0.0055054296f, -0.21858177f, 0.13006803f,
- -0.010444722f, 0.016382102f, -0.0029893327f, -0.007977918f,
- -0.04450929f, -0.028781986f, 0.008289244f, 0.03721693f,
- 0.0015871975f, -0.017882101f, 0.07770267f, 0.0005714651f,
- -0.026530486f, 0.015073705f, -0.0025435952f, -0.016299425f,
- -0.017313406f, -0.016350318f, -0.080418326f, 0.037245173f,
- 0.0061707175f, 0.033698753f, -0.018683665f, -0.009976053f,
- -0.21955773f, -0.020037808f, 0.0056082034f, 0.006824715f,
- -0.00993153f, -0.020169342f, -0.023739267f, -0.0142743215f,
- 0.17413042f, -0.023454653f, -0.032533772f, -0.0130142495f,
- -0.006856863f, -0.029177312f, -0.00027794595f, -0.019590471f,
- -0.010461576f, -0.015744703f, 0.014065444f, -0.01531115f,
- -0.010802253f, -0.0053655133f, 0.07119519f, -0.017513847f,
- 0.00702657f, 0.006836529f, 0.064847745f, -0.024262693f,
- -0.0021844807f, 9.21404e-06f, -0.033901937f, 0.01210641f,
- 0.011980978f, -0.04238776f, -0.0071953186f, 0.012423926f,
- 0.016806964f, -0.010256836f, -0.016000612f, 0.033313327f,
- 0.014094f, -0.006788555f, 0.0023740686f, 0.006469409f,
- -0.0039924905f, 0.008799566f, 0.13470253f, -0.0016526395f,
- -0.08319831f, 0.01261466f, -0.009331805f, 0.039677124f,
- -0.07587326f, -0.06206004f, -0.0074837203f, 0.008103415f,
- 0.036629874f, 0.09692148f, 0.012886844f, 0.0047455216f,
- 0.000673954f, 0.020401455f, -0.0031760612f, 0.00054516393f,
- 0.029568408f, 0.003786769f, 0.09019435f, -0.0043543703f,
- 0.020509489f, 0.038283516f, 0.037787445f, 0.008032141f,
- 0.09053133f, -0.005292312f, -0.003045652f, 0.087711155f,
- -0.0037548025f, -0.00072975515f, 0.0056984453f, -0.04345306f,
- -0.039042685f, 0.02546288f, -0.06160867f, 0.18490702f,
- 0.0003291278f, -0.002384142f, 0.050204992f, -0.021691695f,
- -0.008204569f, -0.09924736f, -0.023962617f, 0.0055399197f,
- 0.036105484f, -0.00775356f, 0.00045062022f, -0.00010775188f,
- 0.071811035f, 0.0070982417f, 0.024647495f, -0.01736043f,
- 0.005585079f, 0.120071426f, 0.018390488f, 0.00709022f,
- -0.0005927037f, -0.07858139f, 0.012186078f, 0.008770923f,
- -0.0013463664f, 0.04632529f, 0.011232444f, 0.0056693233f,
- 0.016174782f, -0.09132891f, 0.017809417f, -0.002766045f,
- -0.014887124f, 0.017735966f, -0.0032974556f, -0.06684699f,
- 0.0059301704f, -0.05237431f, -0.024351912f, 0.09082658f,
- -0.12235469f, 0.012227781f, 0.1085078f, 0.0049703033f,
- -0.0019719058f, -0.0017608353f, -0.051937316f, -0.0022154534f,
- 0.0037878205f, 0.00097137f, -0.0016991125f, 0.010159757f,
- 0.02834474f, -0.016634814f, -0.056521945f, 0.011305953f,
- -0.0051077614f, 0.030862099f, 0.0008319696f, -0.015489533f,
- -0.020479772f, -0.008178025f, 0.23165688f, -0.0020866583f,
- 0.0025516285f, 0.0075989985f, -0.0018056562f, -0.014016035f,
- -0.083038084f, 0.0053579914f, 0.017050937f, 0.003523323f,
- 0.0021867394f, -0.00090106524f, -0.00603034f, 0.058447387f,
- -0.0018760422f, -0.0010369449f, -0.023651784f, 0.20292503f,
- -0.007273431f, 0.10886698f, -0.0154712545f, 0.0018967392f,
- -0.0048239296f, -0.0017336116f, 0.002559691f, -0.01809958f,
- 0.018575303f, 0.0062622395f, 0.09606062f, -0.00038877144f,
- 0.013185288f, 0.065404825f, -0.0012150881f, 0.07322799f,
- -0.15647416f, 0.0011468976f, 0.03595144f, 0.0054921075f,
- 0.0090429885f, -0.013004292f, 0.06612797f, 0.0002546803f,
- 0.024555115f, 0.018284578f, -0.0032075078f, -0.033181485f,
- -0.0031481308f, 0.020689456f, 0.054462273f, 0.02904698f,
- 0.027079204f, 0.013066632f, 8.903992e-05f, -0.0060008517f,
- 0.008036445f, 0.010234774f, 0.21343735f, 0.08676627f,
- 0.0025413882f, 0.059847895f, -0.02351151f, -0.0015892861f,
- -0.10967907f, 0.006839535f, -0.007837574f, 0.0602108f,
- -0.0035034015f, 0.007471094f, -0.010293789f, 0.091987945f,
- 0.05274382f, 0.014095458f, 0.0410614f, -0.0068019493f,
- 0.004816894f, 0.11310616f, -0.00071293575f, 0.008481413f,
- -0.008511193f, 0.023387283f, 0.022162726f, -0.0007441394f,
- 0.0150248315f, 0.017378924f, 0.020248333f, -0.00014982716f,
- -0.0059990254f, 0.007172878f, -0.045396686f, -0.0009591997f,
- 0.018193929f, 0.008907888f, -0.022798933f, -0.01185216f,
- -0.0028008565f, -0.10063326f, -0.008141948f, -0.001518825f,
- -0.019090438f, 0.057082962f, 0.07228903f, 0.08430319f,
- -0.0074979845f, -0.002856883f, -0.00093669497f, -0.0036549633f,
- 0.0016072049f, -0.020174835f, 0.045761876f, 0.004506836f,
- 0.003759922f, -0.014935369f, -0.005802157f, -0.056424733f,
- 0.076196685f, 0.23401204f, 0.07369234f, -0.012338372f,
- -0.08572316f, -0.018015025f, -0.002394729f, 0.0024371205f,
- 0.01510374f, 0.006491726f, 0.0045131417f, 0.0088843275f,
- -0.08808664f, -0.0027548876f, -0.029639468f, 0.0037091891f,
- -0.04809536f, -0.025186572f, 0.049367454f, -0.0089951875f,
- -0.056495924f, -0.017431084f, 0.017397469f, -0.03317855f,
- 0.0048026587f, 0.0032110214f, -0.0151732555f, -0.24622066f,
- -0.07513086f, 0.03948961f, 0.07801979f, 0.06567427f,
- 0.001204123f, -0.001036823f, 0.028847693f, -0.07402418f,
- 0.0089562405f, -0.04272608f, -0.091787055f, -0.009762797f,
- 0.05999554f, -0.002135026f, -0.0027825201f, -0.04864788f,
- -0.0746933f, 0.012180377f, -0.031578142f, -0.0128269f,
- -0.012623051f, -0.08945907f, 0.0106782345f, 0.010739763f,
- 0.0016281281f, 0.093681745f, -0.003224276f, 0.02987317f,
- 0.0020653696f, -0.0046822345f, -0.010335593f, -0.022628691f,
- -0.004398227f, -0.086284414f, -0.01951369f, 0.0016615059f,
- 0.011604657f, -0.0048925695f, 0.025450287f, -0.008514032f,
- 0.0051736827f, 0.049245764f, -0.30502507f, -0.11762601f,
- 0.04410714f, -0.012335865f, -0.088300504f, 0.0032090303f,
- -0.0054656034f, 0.0030459126f, 0.083109505f, -0.007173879f,
- 0.003601805f, -0.0043968474f, 0.010643101f, -0.005189669f,
- 0.0033098976f, 0.0048264028f, 0.027374968f, -0.012910796f,
- 0.09045878f, -0.12758698f, -0.022464726f, -0.00848879f,
- -0.023631787f, -5.5378056e-05f, 0.0913231f, -0.004045106f,
- -0.0009358554f, 0.0060389424f, 0.014206129f, -0.0039027615f,
- 0.025250994f, -0.005905931f, 0.009113086f, -0.011742484f,
- -0.009010789f, 0.003952282f, 0.009528844f, -0.05555582f,
- 0.0065700375f, 0.0056108246f, -0.0075954506f, -0.2502188f,
- -0.0012849341f, 0.19698676f, -0.023935942f, 0.0038839825f,
- -0.003936558f, -0.0045362376f, 0.004552495f, -0.090687156f,
- 0.04338229f, -0.015921619f, -0.028184336f, 0.0063712946f,
- -0.014224769f, -0.13149643f, -0.01594273f, -0.17495786f,
- -0.12753469f, 0.0022813943f, -0.15581867f, -0.089735754f,
- 0.0044790376f, 0.09979278f, -0.013049035f, 0.00701575f,
- -0.051921334f, -0.025754953f, 0.07204324f, 0.084800005f,
- 0.0052827937f, -0.0070582777f, -0.0054863864f, -0.05173867f,
- -0.058523417f, -0.006135551f, 0.0034468307f, -0.024850497f,
- -0.015892508f, -0.013269548f, -0.0144546805f, -0.09798909f,
- 0.011139247f, -0.03350431f, 0.0529376f, 0.0069344956f,
- -0.120709494f, -0.0017380797f, 0.02153849f, -0.05458464f,
- 0.0018314813f, -0.0047058775f, -0.029378599f, -0.011491795f,
- 0.10190057f, -0.00010328919f, 0.0021038353f, 0.0058820634f,
- -0.014925343f, -0.021159438f, 0.00044011328f, -0.012561722f,
- -0.004587848f, -0.012984394f, -0.008502251f, -0.0006751687f,
- -0.009609917f, -0.0048051053f, -0.04888693f, -0.008441059f,
- -0.0016721874f, 0.0017879005f, -0.24873807f, -0.003443232f,
- -0.06967005f, 0.0038160942f, 0.016338684f, -0.017045869f,
- -0.0073207673f, -0.029510826f, -0.009030737f, -0.004484417f,
- -0.010486708f, 0.037777804f, 0.057824682f, 0.11283844f,
- -0.001540409f, -0.005869701f, 0.008896435f, -0.004693765f,
- 0.0089919595f, -0.00029572172f, -0.13245307f, 0.0004281831f,
- 0.10604631f, -0.015163663f, -0.00020061289f, -0.00270571f,
- 0.14844374f, 0.14365633f, 0.074518904f, -0.009075158f,
- -0.04517291f, 0.050340682f, -0.008621708f, -0.008442037f,
- 0.0049926555f, 0.09110698f, 0.013114825f, 0.0030009758f,
- -0.04933653f, -0.022311905f, -0.021672433f, -0.003536877f,
- -0.03572667f, -0.0054481537f, 0.05815397f, 0.023029463f,
- -0.013560795f, -0.017290682f, -0.008642637f, 0.013750034f,
- 0.0016867833f, 0.004187201f, 0.0040674475f, -0.049442533f,
- 0.055714224f, 0.22201498f, 0.09349168f, -0.05858593f,
- 0.0026247022f, 0.0016342308f, -0.041290045f, 0.028979035f,
- -0.006210622f, 0.016250687f, -0.005604823f, 0.00014996142f,
- -0.008713242f, 0.00027570076f, 0.0047848267f, -0.052031778f,
- -0.13872758f, 0.004334298f, -0.013136843f, 0.005061023f,
- -0.014311472f, -0.025018226f, -0.041460972f, 0.026168024f,
- 0.008086388f, -0.06587633f, 0.0028433143f, 0.041555915f,
- -0.0019456426f, -0.02000117f, -0.049808897f, -0.050622858f,
- -0.009854363f, 0.014438192f, -0.0024267829f, 0.005477177f,
- 0.0042358893f, -0.002872949f, 0.0021921182f, 0.1778285f,
- 0.0032372086f, 0.07794674f, 0.19761169f, -0.02717756f,
- -0.027225096f, -0.0064948327f, -0.026892103f, 0.0005326655f,
- -0.008764865f, 0.0036851843f, -0.05533499f, 0.0039020139f,
- -0.004536473f, -0.00016653702f, -0.02275286f, 0.0006387409f,
- 0.03700833f, 0.0013277783f, 0.09009546f, -0.01685461f,
- 0.09568457f, -0.100817874f, -0.036066193f, 0.010502023f,
- -0.001377269f, -0.00220349f, -0.09605428f, 0.004394549f,
- 0.0015203943f, 0.0040012086f, -0.004102525f, -0.004286046f,
- 0.040956534f, -0.039477896f, -0.004247017f, -0.00025810816f,
- -0.01423827f, 0.0004930833f, 0.00380874f, -0.02732742f,
- 0.007891716f, -0.0024098186f, -0.004658808f, -0.2757292f,
- 0.0075603467f, -0.18669362f, -0.020560209f, 0.0015506322f,
- 0.0043133236f, -0.013022676f, 0.008838939f, -0.07625216f,
- 0.11869124f, -0.0028513721f, 0.017310198f, -0.0016097733f,
- -0.0032857193f, -0.1028082f, -0.0061764596f, -0.06026717f,
- 0.048970502f, 0.01088547f, -0.08132822f, -0.066267334f,
- 0.0040565506f, 0.14432472f, -0.003187826f, 0.01236716f,
- -0.043076884f, -0.016903913f, 0.07405391f, 0.15025933f,
- 0.0022493673f, 0.0124576865f, 0.076628774f, -0.042683285f,
- 0.017123332f, -0.010784543f, 0.0017242521f, -0.0148136355f,
- -0.0065641403f, -0.013839312f, -0.057178743f, -0.036091313f,
- -0.0017393631f, -0.0031475693f, -0.085051425f, 0.008140764f,
- -0.015733024f, 0.00048306157f, -0.0018150192f, -0.052925307f,
- 0.01272936f, -0.0061182426f, -0.04492691f, -0.06956167f,
- -0.018199107f, 0.013838566f, -0.10007337f, 0.016158262f,
- -0.013484686f, -0.1678583f, 0.00200242f, 0.010219976f,
- 0.011959131f, 0.009838226f, 0.02875593f, 0.0020154468f,
- -0.002717191f, -0.012996444f, -0.07012981f, -0.0021883182f,
- -0.009131575f, -0.0045323367f, -0.068175726f, 0.033439286f,
- 0.14647341f, 0.0046762275f, -0.0108287055f, -0.007432649f,
- -0.0019169605f, 0.18761496f, -0.0021699306f, -0.004850992f,
- -0.14498414f, -0.00026963276f, 0.07646897f, -0.015467265f,
- -0.00022671233f, -0.0030145848f, 0.002143222f, -0.003724753f,
- -0.0018523985f, -0.004013291f, 0.066553265f, -0.0019480668f,
- -0.15790257f, -0.004034926f, 0.0006728672f, -0.09411654f,
- 0.12901628f, -0.031620722f, 0.037571616f, -0.0009619654f,
- -0.012961646f, -0.059160877f, -0.004702398f, 0.0064371433f,
- 0.0066793757f, 0.024656106f, -0.0062561696f, 0.0041000247f,
- 0.06467574f, -0.011140634f, 0.0455383f, 0.0099281715f,
- -0.08934841f, -0.031350933f, 0.0137235075f, 0.02725512f,
- -0.076027684f, 0.014101399f, -0.050459944f, -0.18564823f,
- 0.0059446883f, -0.006372511f, -0.008433118f, -0.20805992f,
- 0.047398057f, 0.09468762f, 0.026547281f, -0.020440776f,
- -0.004262243f, 0.0019867208f, -0.06834249f, -0.0058406102f,
- 0.017733531f, -0.18698277f, -0.092818424f, -0.009926642f,
- -0.05529283f, 0.0025756743f, 0.008767969f, -0.0066089197f,
- -0.05817121f, -0.0051856576f, -0.04988852f, 0.0019782109f,
- -0.0057761436f, 0.31831723f, -0.056689832f, -0.077344075f,
- 0.0003126764f, -0.05385495f, -0.0071360986f, -0.011311262f,
- 0.0039274064f, -0.02462064f, 0.0028061932f, -0.08096062f,
- -0.014392622f, -0.046522006f, 0.00062946236f, 0.0031732586f,
- -0.032867707f, -0.0044354755f, 0.014243333f, -0.13420078f,
- 0.0064633028f, -0.28258696f, 0.15617773f, -0.08691997f,
- -0.299753f, -0.0006224945f, -0.11013513f, 0.0018764681f,
- 0.0015160462f, -0.0035895149f, 0.010307259f, 0.0012358571f,
- 0.010962244f, -0.008761918f, 0.0159657f, -0.0047160066f,
- 0.020849742f, 0.02023333f, -0.009719099f, 0.0064383224f,
- 0.22936554f, -0.08343086f, 0.02667505f, 0.0048769685f,
- 0.035818513f, -0.0019866058f, 0.0626672f, -0.007429322f,
- 0.00066164834f, -0.0071022594f, 0.015805947f, -0.008714603f,
- -0.15847917f, -0.030236749f, 0.027061412f, -0.0062830974f,
- -0.0014274603f, -0.0013275134f, -0.0016406704f, -0.022323273f,
- -0.0031996116f, 0.012032232f, 0.018119045f, 0.11848759f,
- 0.0006108109f, 0.20094794f, 0.01399667f, 0.0015416989f,
- -0.004585392f, -0.0038400327f, -0.003502195f, 0.063401096f,
- -0.046842065f, -0.0004935387f, -0.027032992f, 0.025547553f,
- 0.0033791305f, -0.11226543f, -0.007835374f, 0.07966236f,
- -0.031429265f, 0.004383598f, 0.097483784f, 0.011819743f,
- -0.010045089f, -0.043350965f, -0.049661998f, 0.005675816f,
- -0.07386318f, -0.017368449f, -0.025588503f, -0.06032924f,
- 0.00069468806f, -0.008635742f, 0.036866058f, -0.0533094f,
- -0.03619604f, -0.0057225823f, 0.0025183433f, -0.003108471f,
- -0.005598163f, 0.0062575443f, 0.05987255f, -0.012549924f,
- 0.0101706f, -0.059713162f, -0.10325918f, -0.0004712065f,
- -0.047491908f, -0.012968729f, 0.0050521716f, -0.024510162f,
- 0.004754452f, -0.00071666867f, -0.07381761f, -0.06899749f,
- -0.24879882f, -0.005066182f, -0.07799204f, 0.0017320431f,
- 0.0022594626f, -0.04727983f, 0.0021166382f, -0.009724051f,
- 0.0054672477f, -0.025524572f, -0.05964547f, 0.011722708f,
- 0.0075641936f, 0.005463212f, 0.0028112594f, 0.008464174f,
- -0.00094767427f, -0.0114974985f, 0.23679926f, 0.013125691f,
- 0.121528804f, -0.009448645f, 0.032382693f, 0.020217849f,
- -0.0023259341f, 0.03540539f, -0.005312999f, -0.002033102f,
- -0.024836339f, -0.028790688f, -0.2746995f, -0.07876785f,
- 0.009509541f, 0.008205078f, 0.0045116628f, 0.0036624381f,
- -4.103098e-05f, 0.013208964f, -0.01477801f, 0.000304933f,
- -0.10550786f, 0.008361113f, 0.00405403f, -0.044537056f,
- -0.037797924f, 0.0026873345f, -0.026208133f, 0.015078334f,
- 0.025703197f, 0.059854895f, 0.0070964913f, -0.0017359272f,
- -0.023341635f, -0.05554933f, 0.0033390264f, -0.0035515504f,
- 0.03177584f, 0.014182117f, -0.030663285f, 0.0062519168f,
- 0.08407376f, -0.025152378f, 0.013266322f, 0.015490762f,
- -0.07157843f, 0.029631985f, 0.014443481f, -0.014265751f,
- -0.004632653f, 0.0020329787f, 0.0063626785f, 0.007707966f,
- -0.047242578f, -0.12776037f, -0.05517828f, -0.07768984f,
- -0.0009921746f, 0.0063799345f, 0.0225817f, -0.04673496f,
- 0.0069710887f, -0.08334311f, 0.021440217f, 0.0004370743f,
- -0.044595487f, 0.00011703315f, 0.0134734735f, 0.05063116f,
- 0.070574746f, -0.0029445197f, 0.0036316637f, 0.021850469f,
- 0.019762613f, -0.02677589f, 0.015052987f, -0.032990962f,
- 0.009028565f, -0.058067095f, 0.0016404267f, -0.010176758f,
- 0.0006219293f, 0.010964246f, 0.059976716f, 0.076370776f,
- 0.017272664f, 0.00043135622f, 0.030340398f, 0.00632745f,
- 0.011474494f, -0.0013003901f, -0.012135743f, -0.051685095f,
- -0.007421661f, -0.12299187f, 0.10612391f, -0.075091735f,
- -0.110524215f, 0.0057604928f, -0.017870486f, 0.0029445381f,
- -0.0059981323f, -0.00032477017f, -0.04582313f, 0.008921991f,
- -0.00022452329f, 0.009289864f, -0.0017747738f, -0.0041124555f,
- -0.0011486537f, 0.017871551f, -0.024989804f, 0.019369338f,
- -0.080328435f, 0.016397523f, 0.030463176f, 0.016858429f,
- 0.023556938f, 0.0069874586f, -0.09998011f, 0.008947343f,
- -0.00435961f, -0.009847805f, -0.007167826f, 0.0038187678f,
- -0.17407614f, 0.011115746f, 0.018593138f, 0.010985793f,
- 0.009000186f, 0.0028601831f, -2.9268109e-05f, -0.037834343f,
- 0.0016976133f, 0.0052492945f, 0.01863627f, 0.026506562f,
- 0.003985318f, -0.19206516f, 0.010736588f, -0.0008286099f,
- 0.018709034f, 0.017308066f, -0.00085974f, 0.056858536f,
- -0.10025101f, 0.010713779f, -0.043703213f, 0.008375019f,
- 0.010579178f, 0.030284341f, 0.021866191f, 0.12103722f,
- 0.04046663f, 0.005736606f, 0.0067353183f, -0.02112409f,
- -0.0054005105f, -0.07385366f, -0.03454109f, 0.00781121f,
- -0.018053569f, -0.007011345f, -0.07811577f, -0.056410395f,
- -0.0006511511f, -0.011008913f, -0.021250986f, -0.008171631f,
- -0.025960041f, 0.0027278934f, 0.0034044073f, 0.028855972f,
- 0.0150219025f, 0.026773881f, -0.1403834f, -0.020388694f,
- -0.0026696867f, -0.04258691f, -0.0039898246f, 0.0051367623f,
- 0.004883678f, 0.0050686f, 0.000499824f, -0.000549045f,
- 0.0105012795f, 0.0005250852f, -0.044485208f, 0.024401454f,
- 0.10112575f, -0.02348295f, 0.055737533f, 0.009605343f,
- 0.016351897f, -0.0695833f, 0.004253632f, 0.026336815f,
- 0.01170373f, -0.027840706f, -0.011854001f, 0.0050498797f,
- 0.008866888f, 0.016323777f, 0.056740046f, 0.019733723f,
- 0.0008117563f, 0.001609671f, -0.08277976f, -0.026367657f,
- 0.16333924f, -0.003981484f, -0.030532295f, -0.0060731396f,
- 0.0069661806f, 0.06350049f, 0.0036085008f, 0.002034757f,
- 0.14638738f, -0.005354533f, 0.068708256f, 0.039995637f,
- -0.005120384f, -0.007192363f, 0.0031738232f, -0.0027163534f,
- 0.00016645694f, -0.00045131933f, -0.09226363f, -0.0059560933f,
- 0.09889801f, 0.003205592f, -0.0056813094f, 0.047688767f,
- -0.016564693f, -0.22993408f, -0.03203586f, -0.005720433f,
- 0.040092353f, -0.08091629f, -0.002172249f, -0.0052106073f,
- -0.007310177f, 0.024068033f, -0.011502681f, -0.008935065f,
- 0.08110613f, -0.024377527f, 0.03269986f, -0.0035700237f,
- 0.012528742f, 0.020468796f, -0.029688288f, -0.028001187f,
- 0.07178876f, -0.014338771f, -0.015877636f, 0.21941233f,
- -0.0036146014f, -0.006769987f, 0.0022318028f, 0.21560541f,
- 0.005369455f, -0.03277184f, -0.0067479936f, 0.05776661f,
- -0.0027830396f, -0.007277674f, -0.020971471f, 0.04429352f,
- -0.008452714f, 0.0014541663f, 0.020898268f, 0.009179822f,
- 0.030886322f, -0.0038902932f, 0.00033132843f, 0.041027613f,
- -0.01004349f, -0.008989002f, 0.042175468f, -0.008193913f,
- -0.0035868997f, 0.02743802f, -0.018311707f, 0.034612536f,
- -0.009453764f, 0.16848435f, -0.014485804f, 0.03147558f,
- -0.0058453158f, -0.017331995f, -0.054136552f, -0.05787794f,
- -0.012612567f, -0.0508669f, -0.028183645f, -0.008152106f,
- -0.02215416f, 0.0050041853f, -0.022634352f, -0.04335883f,
- -0.009256653f, 0.29092026f, 0.023171766f, 0.061951406f,
- 0.116465576f, 0.0027851781f, 0.061302956f, 0.007831519f,
- 0.004197023f, -0.005521956f, -0.004595097f, -0.008149168f,
- -0.01384554f, -0.010619668f, -0.02138516f, 0.006157583f,
- 0.008450549f, -0.025196698f, -0.023014326f, -0.008318986f,
- -0.06970466f, 0.0956823f, -0.00050672924f, -0.011982017f,
- -0.06922428f, -0.007538828f, -0.037168834f, -0.0017282034f,
- 0.00054351124f, -0.002563691f, -0.02785195f, 0.00038574348f,
- 0.09664788f, -0.0075465944f, -0.022363469f, -0.0032420047f,
- -0.015781984f, -0.0059142145f, -0.010007381f, -0.020107249f,
- -0.006749232f, -0.020682154f, -0.022830443f, 0.22578415f,
- -0.0074542835f, 0.007653914f, -0.022560788f, -0.0047638537f,
- 0.0008151243f, -0.008059805f, -0.004527927f, 0.06893568f,
- -0.014744913f, 0.0029360526f, 0.07194317f, -0.025792811f,
- -0.0025977625f, 0.076388806f, -0.004617538f, 0.16098222f,
- 0.07678052f, 0.00044552155f, -0.08082877f, 0.173273f,
- -0.0015527919f, -0.045912195f, -0.010880502f, -0.0062006214f,
- 0.03658079f, 0.012077293f, -0.023378687f, -0.06063676f,
- -0.0051092124f, 0.0011487355f, -0.048691675f, 0.045437016f,
- -0.016722726f, 0.003099696f, -0.0008581316f, 0.009303826f,
- 0.00077871466f, -0.020336444f, -0.050456375f, 0.081805654f,
- -0.011884351f, 0.054155253f, 0.03643491f, -0.0071721077f,
- -0.054520182f, -0.0055296277f, -0.013618522f, 0.038504124f,
- -0.00769157f, -0.0032801398f, 0.09762241f, 0.007474431f,
- -0.0367703f, -0.0055245375f, -0.018932248f, -0.010342021f,
- 0.013014702f, 0.16843897f, -0.006694837f, -0.0359711f,
- -0.01818555f, 0.008773684f, -0.030473642f, -0.015521862f,
- -0.013301978f, -0.010182219f, 0.14468163f, -0.0058394494f,
- -0.0014607742f, -0.008617562f, -0.06694015f, -0.0048838933f,
- -0.08241629f, -0.006134283f, 0.0013933989f, 0.0016750944f,
- 0.009246451f, 0.1092245f, -0.0089785475f, -0.007830305f,
- 0.0361212f, -0.00036663027f, -0.04419957f, -0.01932955f,
- -0.016055297f, -0.008956503f, -0.007881639f, -0.017003957f,
- -0.010790794f, -0.0077364566f, -0.040989075f, 4.554913e-05f,
- -0.16503991f, 0.018969567f, -0.0056909f, 0.033399392f,
- 0.060483325f, -0.2425605f, 0.019153086f, 0.005348298f,
- 0.019166697f, -0.035980467f, -0.031341415f, 0.00087810284f,
- -0.008499298f, 0.05124075f, -0.0063363365f, -0.0037800756f,
- 0.102703236f, -0.016205227f, 0.18021f, -0.013457264f,
- 0.014684705f, 0.010164344f, 0.07533353f, 0.02534351f,
- 0.008641288f, 0.011364504f, 0.0059318184f, -0.094348595f,
- -0.0028640314f, -0.0035341457f, -0.014386897f, 0.0108260745f,
- -0.0792994f, -0.12210302f, -0.03060695f, 0.038485102f,
- -0.0008890645f, -0.00025775254f, 0.04178875f, -0.09157466f,
- -0.016056292f, -0.13718538f, 0.017894162f, -0.01376151f,
- 0.016889587f, -0.008407815f, -0.0097691445f, -0.0033312778f,
- -0.11943751f, -0.014402088f, 0.030331416f, -0.01821652f,
- -0.0047901045f, 0.35441628f, -0.02809817f, -0.013441092f,
- 0.0015444715f, -0.07894209f, -0.00461573f, -0.015771404f,
- -0.008531075f, -0.006327616f, 0.055293534f, 0.06796192f,
- 0.0021575363f, -0.061243713f, -0.007102737f, -0.0030566466f,
- -0.04027928f, -0.020228378f, -0.022452334f, -0.013766041f,
- -0.0038431948f, -0.0476949f, 0.030576415f, 0.05447465f,
- -0.1272364f, -0.00087911135f, -0.15800981f, -0.013557607f,
- -0.00017045854f, -0.002875409f, 0.014222902f, -0.007968811f,
- 0.0010764346f, -0.008847749f, -0.012187143f, -0.01687073f,
- -0.0057703126f, -0.010757802f, -0.12807278f, -0.010819863f,
- 0.047134828f, -0.001227137f, 0.036004595f, -0.00987939f,
- -0.012266977f, -0.006960793f, 0.3380531f, -0.0040402277f,
- -0.023846416f, -0.006561397f, -0.00046055653f, -0.0107622715f,
- -0.007924359f, -0.035947643f, 0.016329892f, -0.009492127f,
- -0.0018201052f, -0.0020240243f, -0.004553362f, 0.01382639f,
- -0.0045297234f, -0.0008231223f, -0.035097755f, 0.20568796f,
- -0.007518847f, 0.15576854f, 0.00027509505f, 0.008756767f,
- -0.0130368015f, -0.0016750996f, -0.021608122f, 0.11765345f,
- -0.0040755933f, 0.0012044786f, 0.03359842f, -0.0017766306f,
- -0.012858666f, 0.062152363f, -0.0064603197f, -0.015926056f,
- 0.013041366f, -0.010555822f, 0.056734335f, 0.11635159f,
- -0.011518371f, -0.00408481f, 0.099722266f, -0.007783803f,
- 0.010878967f, -0.016735118f, 0.008890535f, 0.008187971f,
- -0.0011397082f, -0.036965266f, 0.087669276f, 0.032973155f,
- 0.006816488f, 0.008735753f, -0.00282079f, -0.017864441f,
- -0.0041139987f, 0.0040672915f, -0.0473944f, 0.024212219f,
- -0.0009794565f, 0.04713285f, -0.020320047f, -0.0065461374f,
- -0.14150572f, -0.0046101003f, -0.01029838f, 0.06319639f,
- -0.006038967f, -0.019433286f, -0.08831517f, 0.07718964f,
- 0.2093247f, -0.027302712f, 0.09629958f, -0.008020071f,
- -0.004868308f, -0.063564874f, 0.0024243772f, -0.02425887f,
- -0.008469324f, -0.0025149053f, -0.006581212f, -0.012561546f,
- -0.0077495454f, 0.011382258f, 0.008689563f, -0.0018610009f,
- -0.016395384f, -0.024446875f, -0.030553073f, -0.015837558f,
- -0.13910304f, -0.03315757f, -0.05199118f, -0.03598848f,
- -0.034369837f, 0.29591006f, -0.012178503f, -0.02069815f,
- -0.041283716f, -0.08279897f, 0.2638717f, -0.082779616f,
- -0.071592905f, -0.0061568334f, -0.013204319f, -0.02598936f,
- -0.012230355f, -0.004162253f, -0.07625864f, -0.010431085f,
- -0.047161195f, -0.03455451f, -0.002496992f, -0.1143377f,
- -0.08999847f, -0.19422193f, -0.09837089f, -0.006897889f,
- 0.008818378f, -0.15785713f, -0.056828264f, -0.017160263f,
- -0.06513158f, 0.041291624f, -0.01173394f, -0.018293116f,
- 0.08992533f, -0.03971936f, -0.053484764f, -0.015779171f,
- -0.14859344f, -0.063196704f, -0.17799291f, -0.017178556f,
- -0.116279416f, -0.03673339f, -0.09627782f, -0.15554927f,
- -0.008913244f, -0.01296956f, -0.015405748f, 0.15420805f,
- -0.06471204f, 0.026686827f, -0.051163904f, -0.15381286f,
- -0.008866025f, -0.0024249067f, -0.13314156f, 0.024652204f,
- -0.03326414f, 0.1000735f, 0.014610369f, -0.014055004f,
- -0.115080446f, -0.007522218f, -0.013570194f, -0.016233763f,
- -0.014623664f, -0.052140452f, -0.027410647f, 9.324536e-05f,
- -0.010548646f, 0.081669755f, -0.03610414f, -0.053125504f,
- -0.014777026f, 0.058839153f, -0.041578386f, -0.078391135f,
- -0.0061411373f, -0.09678268f, -0.10622997f, -0.06429512f,
- -0.05344851f, 0.10046978f, -0.036172476f, -0.0059332936f,
- -0.046024386f, -0.037997916f, -0.007824763f, -0.0039059727f,
- -0.013419686f, 0.0094162095f, -0.025834216f, -0.059630778f,
- 0.020894298f, -0.007730873f, -0.12954421f, -0.009110513f,
- -0.014961665f, -0.014134285f, -0.26747182f, -0.012362606f,
- -0.02545283f, -0.016263975f, -0.020265529f, -0.011947447f,
- -0.015953787f, -0.028513938f, -0.16195166f, -0.033720378f,
- -0.10001283f, -0.04094613f, -0.043838877f, 0.009084918f,
- 0.048872683f, -0.0058545847f, -0.011208764f, -0.013691267f,
- -0.045594785f, -0.017363802f, -0.02275303f, -0.0049132355f,
- 0.04113785f, -0.019043481f, -0.06563159f, -0.00992092f,
- -0.012198351f, -0.0064656693f, -0.010309496f, -0.10895487f,
- -0.009811025f, -0.047855202f, -0.014174809f, 0.26155847f,
- -0.0057105403f, -0.19340837f, -0.0022480995f, -0.011324561f,
- -0.015036925f, -0.06287233f, -0.02256588f, 0.1870175f,
- -0.060053185f, -0.008903158f, -0.08726521f, -0.03001022f,
- -0.025357163f, 0.19869606f, -0.005867044f, 0.00030370292f,
- 0.23191024f, -0.007076815f, 0.055374116f, 0.07619691f,
- -0.022728194f, -0.08595766f, -0.13122688f, -0.0001876677f,
- -0.06262142f, 0.0022771386f, -0.07364406f, -0.10291936f,
- -0.006805287f, -0.011168928f, -0.0711713f, -0.106786914f,
- -0.07498312f, -0.028718365f, -0.0105276005f, 0.010009188f,
- -0.013234713f, -0.011705351f, -0.08197964f, 0.028458547f,
- -0.015975975f, -0.16313976f, -0.06023465f, -0.011845973f,
- -0.058245495f, -0.02384229f, -0.041045967f, -0.019672304f,
- -0.014967179f, -0.034221273f, 0.01711003f, -0.119685285f,
- -0.2783396f, -0.020094875f, -0.055132207f, -0.011723472f,
- 0.0015335766f, -0.0062144366f, -0.0034609002f, -0.0412312f,
- -0.0102767255f, -0.023605525f, -0.0344179f, -0.033342995f,
- -0.03297966f, -0.021510249f, -0.07602469f, -0.028407507f,
- -0.003493371f, -0.01061349f, 0.09115147f, -0.018718349f,
- 0.021002904f, -0.023781557f, -0.06112105f, -0.009576242f,
- -0.01954812f, 0.13396557f, -0.009657945f, -0.014612007f,
- 0.030308465f, 0.00739388f, 0.09964328f, -0.10886352f,
- -0.021900915f, -0.013443803f, -0.0074078087f, -0.015123246f,
- -0.003298385f, -0.015543744f, -0.115568586f, -0.0022351388f,
- 0.14905809f, -0.03208593f, -0.01228619f, 0.011604911f,
- -0.044809222f, -0.17597413f, -0.029756f, -0.003686272f,
- 0.016650377f, -0.19295213f, -0.023281869f, -0.0040066913f,
- -0.034457732f, -0.0053180866f, -0.0033254297f, -0.011205524f,
- 0.11025382f, -0.03281413f, 0.114813186f, -0.0017629756f,
- -0.034661643f, 0.016853463f, -0.0006471432f, -0.04729143f,
- -0.0016970118f, -0.04111409f, -0.020646652f, -0.04867086f,
- -0.009333449f, -0.0038356532f, -0.014462744f, 0.06304546f,
- -0.081302315f, -0.037809156f, 0.021609865f, -0.018775849f,
- -0.0024026898f, -0.005097225f, -0.070460334f, 0.04926651f,
- -0.012977532f, 0.06067529f, 0.022239743f, -0.014334392f,
- -0.03396041f, -0.005685155f, -0.0056277476f, 0.008591051f,
- -0.035258867f, -0.04203779f, 0.016043346f, -0.0064821662f,
- -0.005283565f, 0.10341907f, -0.050802495f, -0.030847657f,
- -0.0011430876f, 0.08844592f, -0.0128720645f, -0.037056744f,
- 0.007012671f, -0.08460115f, -0.035435922f, -0.003337771f,
- -0.04265279f, 0.08585906f, -0.064090066f, -0.0052195294f,
- -0.06375995f, -0.015909756f, -0.007044748f, -0.05663799f,
- -0.011044195f, 0.03508519f, -0.136526f, 0.03464608f,
- 0.13125235f, -0.01400203f, 0.011183041f, -0.010151952f,
- -0.01633575f, -0.003962832f, 0.0216877f, -0.0078675905f,
- -0.014589189f, -0.010824433f, -0.010755186f, -0.017256888f,
- -0.06866403f, -0.020897718f, -0.024902554f, -0.013990533f,
- 0.03915791f, 0.065170445f, -0.019797074f, -0.012931389f,
- -0.029007096f, -0.010211002f, -0.042018414f, -0.0019799161f,
- -0.024748387f, -0.009633465f, -0.022717113f, -0.0037405137f,
- 0.07778344f, -0.0303544f, -0.017934486f, -0.0051411055f,
- -0.0046420763f, -0.0008179604f, -0.004202516f, -0.023307705f,
- -0.004100032f, -0.040190864f, -0.016231153f, -0.036275197f,
- -0.010331357f, -0.026976626f, 0.011002305f, 0.001286858f,
- -0.014367141f, -0.042910058f, -0.023831075f, -0.019300967f,
- -0.012047258f, -0.0077815177f, 0.00017938156f, -0.038165797f,
- -0.022028813f, -0.029959278f, 0.0019212364f, -0.05408359f,
- 0.03806122f, -0.009832418f, 0.070802785f, 0.1267215f,
- -0.018831776f, -0.047894258f, -0.003297559f, -0.010740734f,
- 0.029453468f, -0.008740874f, 0.0009088327f, -0.046619594f,
- -0.0016790355f, -0.01950532f, -0.05246248f, 0.011815814f,
- -0.066630326f, -0.017076686f, -0.006861587f, -0.015800947f,
- -0.010450046f, -0.0069178427f, -0.107149184f, 0.042165328f,
- -0.0110433875f, -0.006674036f, 0.09284492f, -0.0058442815f,
- 0.02890295f, -0.016201574f, -0.01632748f, 0.08153904f,
- -0.0037697342f, -0.017469786f, 0.044796117f, 0.031923246f,
- 0.09573125f, -0.025567578f, -0.0073794792f, -0.0024057087f,
- -0.008130937f, -0.044883568f, -0.00247118f, -0.068841375f,
- -0.0094371615f, -0.008840624f, -0.041242383f, -0.029068027f,
- -0.021288322f, -0.012540189f, 0.012492503f, -0.004704044f,
- 0.007896004f, 0.0071850303f, -0.093719706f, -0.040393487f,
- -0.059568226f, -0.009062423f, -0.087697275f, 0.00022454548f,
- -0.004053614f, 0.02857426f, -0.004450548f, 0.004262027f,
- -0.030007035f, -0.052762266f, -0.05501989f, -0.08216758f,
- 0.011690854f, -0.008915293f, 0.0037495391f, 0.010439572f,
- 0.000930986f, 0.013645911f, -0.01137009f, -0.006545127f,
- -0.040440395f, -0.006928248f, -0.0061053107f, 0.043723643f,
- -0.035344187f, 0.058397356f, -0.0701462f, 0.005739724f,
- 0.07341688f, 0.056789584f, 0.016552169f, -0.0066693006f,
- -0.022502586f, -0.0103565045f, -0.0020088975f, -0.008480738f,
- 0.04946329f, -0.023511669f, 0.013450983f, -0.0038392737f,
- -0.08261985f, 0.039968975f, -0.032417838f, -0.04476098f,
- 0.09694516f, -0.02628732f, -0.051898926f, 0.06666721f,
- -0.011335394f, -0.004150482f, 0.011440396f, 0.17816874f,
- -0.03386783f, 0.10896894f, -0.08444451f, 0.0855205f,
- -0.0016980382f, -0.0056039f, -0.04579573f, 0.29270855f,
- -0.015378805f, -0.002500497f, -0.001033051f, 0.010298927f,
- -0.021524379f, -0.003850964f, 0.00058840617f, -0.0033961642f,
- 0.046124894f, -0.022976821f, 0.026197972f, -0.0032521433f,
- 0.0025279617f, 0.03005194f, -0.051397637f, -0.017307369f,
- -0.005240899f, -0.16247986f, 0.0031281637f, -0.045316197f,
- -0.00047296303f, -0.029176835f, -0.0452276f, -0.034246527f,
- -0.010430018f, -0.00265373f, -0.040331677f, -0.0042971307f,
- -0.06538411f, 0.02771408f, -0.0068544094f, -0.075307146f,
- 0.0017747914f, -0.09492253f, 0.15094446f, 0.1193661f,
- -0.1121999f, 0.0120534105f, 0.18297774f, 0.00046126588f,
- -0.006597114f, -0.0050738105f, -0.02666772f, 0.0018644156f,
- -0.01700055f, -0.0029645727f, -0.019930268f, 0.018181294f,
- -0.02739623f, -0.030386718f, -0.04011441f, 0.009195069f,
- 0.018495431f, 0.06473978f, -0.036312763f, -0.008472713f,
- -0.033169024f, -0.010937143f, -0.048683286f, -0.003114238f,
- -0.0014689354f, 0.008974206f, -0.026331943f, -0.012790438f,
- -0.057817332f, -0.028854022f, 0.000297702f, 0.008422978f,
- -0.006115247f, -0.0045468183f, -0.009985694f, 0.05565096f,
- -0.004731007f, -0.021667995f, -0.019054784f, 0.14370383f,
- -0.0039129495f, -0.22064453f, -0.028034188f, -0.004697079f,
- -0.009868068f, -0.019387301f, 0.0035298453f, -0.007601918f,
- 0.032139596f, 0.008474491f, 0.06783467f, -0.02404821f,
- 0.016269373f, 0.12329226f, -0.0002485556f, 0.024673946f,
- -0.030913712f, 0.0012364762f, 0.048895746f, 0.030859109f,
- 0.0033899886f, -0.050809633f, 0.020519448f, 0.0008349563f,
- 0.041882478f, 0.037167814f, -0.024134798f, -0.07505878f,
- -0.0066464604f, 0.043144077f, 0.11095707f, 0.0154247545f,
- 0.034908436f, -0.001833048f, -0.006223746f, 0.00074014376f,
- 0.0055922754f, -0.0022243054f, 0.26918873f, 0.20351787f,
- -0.011992818f, 0.049158204f, -0.09721276f, -0.004993307f,
- -0.002489602f, -0.005186123f, -0.0327647f, 0.053248774f,
- -0.0052982527f, 0.006122884f, 0.021579396f, 0.0091914795f,
- -0.18121096f, 0.03580641f, -0.025512679f, -0.008100197f,
- 0.0019497782f, 0.07122635f, -0.003519279f, -0.027492283f,
- -0.004579491f, 0.032963004f, 0.02248749f, -0.010110825f,
- 0.009724996f, -0.0009306005f, -0.008019973f, -0.004216634f,
- 0.0026501582f, -0.0001311687f, -0.3654052f, 0.000583774f,
- -0.16968936f, -0.005244386f, 0.012237824f, 0.01283352f,
- -0.0006671043f, -0.12737902f, -0.0012286915f, -0.0064152074f,
- -0.09560076f, -0.0068018762f, -0.031220756f, 0.026373357f,
- 0.0043567526f, -0.008889212f, -0.010809229f, 0.00048114237f,
- -0.0035308062f, -0.00049973483f, -0.19872947f, 0.005400485f,
- 0.19189528f, -0.015177672f, -0.0027011593f, 0.0038892035f,
- -0.05492294f, 0.029309994f, 0.041261043f, 0.0076270318f,
- 0.010410987f, -0.13706098f, -0.018995268f, -0.0047103697f,
- 0.017483193f, 0.04586307f, 0.0076140068f, 0.00046821908f,
- -0.05690555f, -0.036535f, 0.16184986f, -0.0074463775f,
- -0.1883622f, 0.012988771f, 0.012212788f, 0.030726478f,
- 0.012043908f, -0.0033423246f, -0.07094324f, -0.18274458f,
- 0.0015575361f, 7.99531e-05f, -0.0013374742f, -0.13202533f,
- 0.04331783f, 0.08773405f, 0.094151266f, -0.07172775f,
- 0.0038659815f, 1.4091444e-05f, -0.022034645f, 0.035329625f,
- -0.009017813f, -0.22027914f, 0.022748983f, -0.009361302f,
- -0.021228721f, -0.00096044195f, -0.010247235f, -0.0056618294f,
- 0.04685158f, -0.019213207f, 0.0050694f, -0.004792697f,
- -0.009300255f, 0.11332083f, -0.073678285f, -0.051552393f,
- 0.010541913f, 0.10264298f, 0.007971611f, -0.002419231f,
- -0.0012914833f, -0.024354309f, 0.03968142f, -0.0181022f,
- -0.029450856f, -0.07396027f, -0.01690529f, 0.003078879f,
- -0.021280015f, -0.015562029f, -0.017964186f, 0.024338251f,
- -0.0042667706f, -0.02787957f, 0.10608892f, 0.036900062f,
- -0.13151902f, -0.00045276503f, -0.12458968f, -0.013435122f,
- -0.0035130756f, 0.004435767f, -0.0533129f, -0.003632929f,
- 0.0011243486f, -0.0041461624f, -0.02109653f, -0.0057737706f,
- 0.036556765f, -0.007617082f, -0.18526144f, 0.007857271f,
- 0.1815563f, -0.018609831f, 0.059900653f, 0.010882678f,
- -0.005179756f, -0.0047974004f, -0.025926135f, -0.0067963526f,
- -0.008479915f, 3.525583e-05f, -0.0041714185f, -0.005734316f,
- -0.015266842f, -0.06635611f, 0.026160002f, 0.0006291806f,
- -0.02497655f, 0.0016097162f, 0.008529172f, 0.018781934f,
- 0.0024149069f, 0.0023344494f, 0.0074303215f, -0.094988406f,
- 0.0005165421f, 0.12908114f, -0.028007505f, 0.006929242f,
- -0.016453704f, -0.025563888f, -0.009494973f, -0.041517764f,
- 0.033720914f, 0.0019957537f, -0.0059978557f, 0.0073637557f,
- -0.012246654f, -0.057113543f, 0.0045587188f, -0.0461872f,
- 0.11307096f, -0.010040494f, 0.07567389f, -0.11117441f,
- -0.00880549f, 0.07416843f, 0.08765825f, -0.0012844502f,
- -0.026909785f, -0.0046501723f, 0.030082395f, 0.057570953f,
- 0.0037879252f, -0.00469398f, 0.040994875f, -0.024145097f,
- 0.014810355f, -0.003540008f, -0.005591859f, -0.02404097f,
- 0.00097421947f, 0.0021681495f, 0.035642855f, -0.09477607f,
- -0.0045372946f, 0.00822506f, -0.15590988f, 0.00250233f,
- 0.027825033f, -0.010963438f, -0.011130193f, 0.03389923f,
- -0.0048317574f, 0.0024206557f, -0.030505158f, 0.00449001f,
- -0.037686456f, -0.0033573364f, -0.063721135f, 0.0005430275f,
- -0.018795112f, -0.092411295f, 0.0037222507f, -0.015043105f,
- 0.0052362913f, 0.004841133f, 0.02186962f, 0.005674404f,
- -0.0057389187f, -0.0093265725f, -0.029604163f, 0.006133147f,
- -0.016234659f, -0.014779647f, 0.013096232f, 0.0018979716f,
- 0.24152629f, -0.016627565f, -0.021566495f, -0.017747011f,
- -0.011671204f, 0.18526453f, 0.0046733865f, -0.02480375f,
- 0.052286927f, 0.0064966595f, 0.17539655f, 0.0015579908f,
- -0.055727143f, -0.0010769228f, -0.008004794f, -0.025388556f,
- -0.0071126954f, -0.022804154f, -0.0018081085f, -0.0005127978f,
- 0.14410825f, -0.03047165f, 0.00030293208f, -0.023544798f,
- 0.028825196f, -0.057003997f, 0.00527639f, -0.018647905f,
- 0.010134416f, -0.18553758f, -0.027035926f, -0.01134948f,
- -0.056900308f, -0.00426713f, -0.014855522f, 0.0029735218f,
- 0.07157916f, -0.024819076f, 0.050086975f, 0.006257971f,
- -0.03773654f, -0.027043965f, 0.064990565f, -0.0076251444f,
- -0.019987814f, -0.0002429475f, -0.017830292f, 0.07093547f,
- 0.0019883572f, -0.0051148306f, -0.032348238f, -0.18058763f,
- -0.109206535f, -0.031147763f, -0.11670592f, -0.0048047267f,
- -0.0020277656f, -0.00035632425f, -0.056888357f, -0.021683648f,
- 0.0077749505f, -0.16032273f, -0.021375544f, -0.0270533f,
- -0.020785006f, -0.0001164903f, 0.0061901608f, 0.075590834f,
- 0.046891965f, -0.030576697f, 0.0063290033f, 0.008940972f,
- -0.015731711f, -0.047011808f, 0.00071515795f, -0.043311648f,
- 0.0025198373f, 0.17716928f, -0.014535737f, 0.00019315539f,
- -0.0012371453f, -0.020702034f, -0.018588623f, -0.08574538f,
- -0.035060234f, -0.106757075f, -0.039431576f, 0.0034480526f,
- -0.027324162f, -0.010005073f, -0.0055667446f, -0.20850092f,
- -0.00866675f, 0.085059196f, -0.012957379f, -0.036429647f,
- 0.022883335f, -0.028821366f, 0.058939062f, -0.003307707f,
- -0.005034048f, 5.6596928e-05f, -0.023846302f, -0.0037590382f,
- 0.0029156634f, -0.018784026f, -0.019918945f, -0.027662462f,
- 0.004887243f, 0.010435591f, 0.05852057f, -0.011772385f,
- 0.17851193f, 0.09017187f, 0.06183496f, 0.0044621634f,
- -0.03341316f, 0.002584582f, 0.045574114f, -0.015861997f,
- -0.036193978f, -0.015460806f, -0.028836397f, -0.0008563719f,
- -0.07583247f, -0.0079093035f, -0.012647452f, -0.017984468f,
- -0.010580003f, 0.0040732655f, 0.002749725f, -0.042953655f,
- -0.005123157f, -0.012221625f, 0.0113238245f, 0.0619324f,
- -0.0011036086f, 0.10734363f, -0.014213516f, 0.0007832347f,
- -0.006329863f, -0.017769199f, -0.018753791f, -0.008222647f,
- -0.08938086f, -0.012424385f, -0.003163048f, -0.0037993125f,
- -0.005425253f, -0.15696378f, -0.0102759125f, 0.17804873f,
- 0.021417117f, -0.00025352382f, -0.09773342f, 0.1999729f,
- -0.014199804f, -0.10198644f, -0.011368045f, -0.006062463f,
- 0.0050354097f, -0.014484415f, -0.056018554f, -0.12746474f,
- 0.0010653731f, -0.021411851f, -0.17888308f, 0.010644693f,
- -0.11859012f, -0.013231114f, -0.0028617685f, 0.0020909104f,
- -0.022903632f, -0.02371144f, -0.076052375f, -0.13436207f,
- -1.6328315e-05f, -0.025598649f, 0.14052905f, -0.0019784907f,
- -0.09283341f, -0.02493846f, 0.009433004f, -0.008036978f,
- 0.0019350603f, -0.043708928f, 0.07133913f, -0.033212345f,
- -0.081205174f, -0.038245317f, 0.011990392f, 0.004239383f,
- 0.00056150235f, -0.020306189f, 0.0012626807f, -0.029282827f,
- -0.0008983706f, -0.06336969f, -0.10183977f, 0.0017017706f,
- -0.007909134f, -0.0007898647f, 0.1347018f, 0.0029116238f
-};
-
-const int LangIdNNParams::kHiddenBiasNumRows[] = {208};
-
-const int LangIdNNParams::kHiddenBiasNumCols[] = {1};
-
-const float LangIdNNParams::kHiddenBiasWeights0[] = {
- 0.011396265f, 0.008040371f, 0.2436787f, 0.03656539f,
- 0.1900996f, 0.023890408f, 0.047371354f, 0.03678838f,
- 0.044139795f, 0.2897346f, 0.01725061f, 0.004762776f,
- 0.11439447f, 0.03279416f, 0.3277201f, 0.1069803f,
- 0.060193155f, -0.017792946f, -0.011048108f, 0.031052593f,
- -0.012962336f, 0.010137448f, 0.2778238f, -0.0042857407f,
- 0.23577267f, 0.036993384f, -0.011054215f, 0.05196488f,
- 0.29571876f, 0.38320467f, 0.041932795f, 0.0052211196f,
- 0.03228098f, 0.11264719f, 0.034287225f, 0.011260535f,
- 0.060079355f, 0.09542259f, -0.013681115f, 0.014489317f,
- 0.26295316f, 0.019091422f, 0.1376993f, 0.019432748f,
- 0.245916f, 0.025439974f, 0.1130558f, 0.052255955f,
- 0.08795709f, 0.016908197f, 0.055969138f, 0.1374195f,
- 0.008330878f, -0.005700882f, 0.004622275f, 0.13678238f,
- 0.16561824f, 0.19681399f, 0.21430476f, 0.14534107f,
- -0.0069258166f, -0.0113086505f, 0.04360687f, 0.25311685f,
- 0.02421768f, 0.17362869f, 0.115767084f, 0.00030163283f,
- 0.07341653f, -0.0018166929f, -0.010607928f, -0.006717243f,
- 0.25546724f, 0.027004022f, 0.099175245f, -0.00075415045f,
- -0.0053013503f, 0.24884938f, 0.03176513f, 0.03563826f,
- -0.014009531f, 0.32043564f, 0.03521217f, 0.008288829f,
- 0.009391188f, 0.05181945f, 0.08150759f, 0.08112108f,
- 0.035771895f, 0.09913023f, 0.032397628f, -0.013868057f,
- 0.04705419f, 0.01903745f, 0.028550914f, 0.27862012f,
- 0.010615735f, 0.28763664f, 0.16200791f, 0.06144732f,
- 0.16667129f, 0.001667916f, 0.19231322f, -0.0150118135f,
- 0.00802721f, -0.006372134f, 0.24628732f, -0.0071077906f,
- 0.007120814f, -0.00063315954f, 0.012848174f, 0.008384587f,
- 0.05485106f, 0.018966973f, 0.10730723f, 0.049516995f,
- 0.35504088f, 0.020661922f, 0.03301079f, -0.0050053657f,
- 0.035773136f, -0.020424172f, 0.2827615f, -0.0127632525f,
- 0.03236642f, 0.008378527f, 0.014926973f, -0.008034727f,
- 0.20120302f, 0.019056333f, 0.05011194f, 0.0015160257f,
- 0.02152339f, -0.0071306806f, -0.008201101f, 0.040748034f,
- -0.008675535f, 0.029707573f, 0.014128528f, 0.30729043f,
- -0.00752384f, 0.26475367f, 0.028684605f, -0.0070206523f,
- -0.0072230254f, 0.04656611f, 0.009536926f, 0.4202708f,
- 0.06610139f, 0.011083299f, 0.1323299f, 0.023825705f,
- 0.01839199f, 0.37755314f, -0.0058085397f, 0.16203359f,
- 0.36348745f, -0.010548612f, 0.17549378f, 0.33257818f,
- 0.008882848f, 0.07170095f, 0.08390297f, -0.011220845f,
- 0.047518153f, -0.004323575f, 0.022652045f, 0.0821825f,
- -0.008283167f, 0.021947531f, 0.2896341f, 0.039290275f,
- 0.047861844f, 0.023634823f, -0.00866472f, 0.003337272f,
- -0.0016377621f, -0.0011196241f, 0.22494079f, 0.19896093f,
- 0.01474775f, 0.07150735f, 0.1365495f, -0.011207452f,
- 0.24116588f, -0.0005583029f, 0.03666552f, 0.10425114f,
- -0.012291022f, 0.018157436f, 0.07008041f, 0.1452989f,
- 0.2803554f, 0.004258007f, 0.21535219f, -0.016007952f,
- -0.016182398f, 0.23536864f, -0.009757347f, 0.060943663f,
- -0.013918014f, 0.01392646f, 0.043341875f, 0.019654056f,
- 0.0094896685f, 0.020426646f, 0.086103745f, -0.0042055175f
-};
-
-const int LangIdNNParams::kSoftmaxNumRows[] = {208};
-
-const int LangIdNNParams::kSoftmaxNumCols[] = {109};
-
-const float LangIdNNParams::kSoftmaxWeights0[] = {
- -0.09282309f, -0.108547345f, -0.13598846f, 0.2935005f,
- -0.22216703f, -0.09205888f, 0.29311517f, 0.24608158f,
- 0.002571663f, -0.09343069f, -0.14843787f, -0.035503726f,
- -0.08352548f, -0.119620994f, -0.14790183f, -0.151961f,
- 0.60621834f, -0.11324467f, -0.06425572f, -0.16642796f,
- 0.037073184f, 0.18549868f, -0.08633856f, -0.22036766f,
- -0.07269159f, -0.037178136f, -0.10050726f, -0.08639516f,
- -0.045889996f, -0.052628793f, -0.023499148f, 0.4307163f,
- -0.048978783f, 0.26741755f, 0.09384352f, -0.065989114f,
- -0.085508294f, 0.31735733f, -0.036630046f, -0.1527248f,
- -0.005571292f, 0.0908959f, -0.14436379f, 0.019805811f,
- -0.21111529f, -0.005573881f, -0.0010502924f, 0.48511103f,
- -0.08069997f, -0.1174281f, -0.045094498f, -0.100228615f,
- -0.091828525f, 0.20255409f, -0.0509993f, -0.058460347f,
- -0.14979267f, -0.12016085f, 0.049422983f, 0.41284767f,
- 0.18366003f, -0.024697213f, -0.122179516f, 0.07781675f,
- -0.05418773f, 0.06880125f, -0.04466383f, 0.33339784f,
- -0.015949227f, -0.12352175f, -0.08714924f, -0.060157098f,
- -0.08935393f, -0.16142726f, -0.118220136f, -0.123585396f,
- 0.20461376f, -0.06018136f, -0.034077164f, 0.611626f,
- -0.06499543f, -0.1238126f, 0.30605435f, -0.18988848f,
- -0.12332835f, -0.055063296f, -0.104719214f, -0.0066457763f,
- 0.39065066f, -0.12858099f, 0.07153111f, -0.09561505f,
- -0.111476414f, 0.34904408f, -0.019259641f, 0.5321082f,
- 0.054289725f, -0.0415095f, 0.0032603452f, 0.01986557f,
- -0.17903124f, -0.097615466f, -0.14459136f, -0.11072559f,
- -0.07306597f, -0.074049905f, -0.07634276f, -0.055244103f,
- -0.17272125f, -0.1598377f, -0.08051392f, -0.11606808f,
- 0.6693711f, -0.19633918f, -0.1821684f, 1.2227166f,
- 0.39272648f, -0.033535026f, -0.1251789f, -0.20410913f,
- -0.12316553f, -0.057139743f, -0.1261352f, -0.16992389f,
- -0.18078576f, 0.33386132f, -0.19132896f, -0.022712614f,
- -0.17095333f, -0.03927719f, -0.12578064f, -0.10827634f,
- -0.18740675f, -0.15100886f, -0.010410284f, -0.06442261f,
- -0.14817053f, -0.041179065f, -0.08145383f, 0.1481889f,
- 1.3630648f, -0.1282142f, 0.23869514f, -0.0022799335f,
- -0.02234534f, -0.1013897f, 0.33837694f, -0.14589645f,
- -0.16855462f, -0.11234552f, -0.037630513f, -0.023691196f,
- -0.23867139f, -0.20579968f, 0.0036941853f, -0.1427586f,
- 0.11285602f, -0.15435338f, -0.3152013f, -0.05594825f,
- -0.11447589f, -0.10160865f, -0.039852142f, -0.050119814f,
- 0.058771882f, -0.100460544f, -0.24088702f, 0.4392848f,
- 0.07113976f, 0.005996949f, -0.14596929f, -0.19830272f,
- -0.092789486f, -0.115410805f, -0.10844006f, -0.101538405f,
- 1.155215f, -0.05260491f, -0.13477595f, -0.07727305f,
- -0.12402129f, -0.04565042f, -0.13778426f, -0.074012004f,
- -0.18416126f, 1.4408584f, -0.105828054f, -0.165084f,
- -0.072802894f, -1.7939417e-05f, -0.20396496f, 0.22227807f,
- -0.19935787f, -0.104895465f, -0.025540818f, -0.103261866f,
- -0.07526915f, 1.11476f, -0.14533922f, -0.040008515f,
- -0.06824363f, -0.13605885f, -0.35596305f, -0.17211024f,
- 0.15912776f, -0.23605475f, 0.047795158f, 0.11569496f,
- -0.26173478f, -0.2170113f, -0.1259953f, -0.19996601f,
- 0.030536108f, -0.07402856f, 0.009385659f, -0.087111406f,
- 0.7407535f, -0.058832858f, 2.1932075f, -3.574459f,
- -3.3839936f, -0.33975476f, -2.6625288f, 3.7084432f,
- 1.1163064f, -0.35685018f, -0.26869586f, 6.300163f,
- -1.0422505f, 0.29827234f, -2.1601174f, 0.9234228f,
- -1.3204939f, 2.004816f, 1.3248738f, -3.9290757f,
- 2.7831566f, 6.315276f, -0.9911898f, -0.34739643f,
- -1.0597428f, -2.06239f, -1.9645742f, 0.5179737f,
- -2.355657f, -0.12544325f, -2.5117574f, -2.3404226f,
- 0.11133545f, -3.5208619f, 3.841598f, 0.4714295f,
- 0.68105006f, -1.4729862f, 0.15145244f, 0.9869681f,
- -2.684468f, 1.3585265f, -3.2614186f, -2.8079338f,
- -0.35309017f, 0.06296166f, -3.1602607f, -1.340331f,
- -0.16469164f, 0.15351206f, -3.1721416f, 7.1299434f,
- 1.2226328f, -4.1984344f, -2.6357749f, -1.1449107f,
- -1.3542672f, 5.6796207f, 0.9436632f, 5.275761f,
- 0.15834276f, 0.9449899f, -2.3285582f, 2.7300894f,
- 0.11793614f, -0.24894449f, -1.1447601f, -0.82308084f,
- -1.4820242f, 1.9832526f, -1.3502942f, 2.8063197f,
- 0.94667256f, 3.1928794f, 1.1079153f, -2.4885726f,
- 2.2242389f, -1.4765519f, -0.7049186f, -3.1804445f,
- 1.7980765f, 0.0090132635f, -1.3798629f, -4.811082f,
- -0.30534112f, 0.34477946f, -3.1288097f, 0.6875961f,
- 0.7910479f, -1.2802694f, 2.9639084f, -2.7343512f,
- -2.3526952f, -0.084827594f, 0.96392846f, 0.06799879f,
- 5.3479543f, 0.104942806f, 0.9755061f, 6.4303794f,
- -0.518207f, 0.42900687f, 6.1430535f, -0.66624516f,
- -1.0910883f, 2.5300202f, -0.21244676f, -2.624041f,
- 1.0694516f, 0.42199135f, -2.3600597f, -0.07939699f,
- -0.3582729f, -0.24459395f, 0.50890857f, 0.016059466f,
- 0.21057598f, -0.11243202f, 0.40726402f, -0.018276004f,
- 0.04058873f, -0.30498964f, 1.1816696f, -0.168863f,
- -0.3220148f, 0.033891205f, 0.036084622f, -0.016898664f,
- -0.13209915f, -0.13526948f, 0.18263574f, -0.006108605f,
- -0.062013753f, -0.07478407f, -0.16915724f, 1.1858872f,
- 1.1100914f, -0.06683356f, 1.6491655f, 0.11244273f,
- 0.09215213f, 0.6744251f, -0.4331355f, -0.03823925f,
- -0.20360771f, 0.057387628f, -0.20844638f, -0.21447676f,
- -0.12363425f, -0.3162549f, -0.07884213f, -0.1519845f,
- -0.32023668f, 0.13673922f, -0.20052426f, -0.17138226f,
- 0.03032162f, 1.2304285f, -0.34538615f, 0.014518692f,
- 0.3425816f, -0.12853645f, -0.021032702f, -0.5001375f,
- 0.13982321f, -0.013372529f, 0.021414509f, -0.08335693f,
- -0.027064096f, -0.18354885f, -0.3270632f, -0.11820057f,
- -0.024382949f, -0.26287553f, -0.28961194f, -0.26557696f,
- -0.2831514f, -0.21240447f, 0.042519484f, -0.00088560395f,
- -0.50163853f, -0.33233395f, -0.16828799f, -0.039945357f,
- -0.26264608f, -0.12771755f, -0.40132734f, -0.14198767f,
- -0.23595683f, 1.0911974f, -0.13800748f, -0.029488362f,
- -0.20775387f, -0.08492399f, -0.02170667f, 0.1206877f,
- 0.21136424f, -0.14548855f, -0.49201635f, 0.26065272f,
- -0.21440615f, -0.048932724f, 0.026929941f, -0.06819804f,
- -0.046262577f, 0.16793679f, 0.5919821f, -0.18565087f,
- -0.09513635f, -0.100867726f, 0.9269906f, -0.15597305f,
- 0.23827991f, -0.04934898f, -0.31151995f, -0.19446842f,
- -0.33877435f, 0.21352965f, 0.15764654f, -0.5050032f,
- -2.1113799f, -0.33235526f, 1.5798695f, 0.09254823f,
- 0.62507784f, -0.19953112f, -0.45403883f, -0.16009744f,
- 1.9000132f, -1.7744626f, 0.94388235f, 0.052074756f,
- -1.0791167f, 3.6288862f, -0.33364958f, -1.5217161f,
- 0.16971464f, -1.8660903f, 2.3189955f, 3.1657095f,
- -0.45585164f, -1.7272973f, -1.3079957f, 0.37890252f,
- -0.26571226f, -0.48645133f, -0.092712894f, -0.23649646f,
- -1.0890867f, -0.76125133f, 0.027864672f, -0.5297606f,
- -1.6693345f, 0.33743376f, -0.45459345f, -1.025138f,
- -1.0633131f, 1.6340947f, -1.5952576f, -0.7891294f,
- 1.1856006f, -1.1908352f, -0.2914223f, -1.5835594f,
- 0.31752267f, -0.577889f, -0.10126015f, -0.6673257f,
- -1.280344f, -0.56026495f, 2.5735567f, -1.6193752f,
- -1.6452049f, -1.0163611f, 1.0073905f, 2.42313f,
- 2.603167f, -1.5731052f, 0.42190382f, 0.44539964f,
- -0.5513577f, -2.102044f, -2.0404117f, -1.126049f,
- -1.8346364f, -0.09992617f, -0.78549093f, 0.030882476f,
- 2.2018669f, -1.011329f, -0.3928914f, 1.8534964f,
- 1.9752288f, -1.0208081f, 5.8553953f, -1.6053919f,
- 2.818721f, 3.1798913f, 0.25725213f, -0.057190534f,
- 6.398827f, -0.7920969f, -0.85983527f, -1.3826349f,
- -4.184866f, 0.4279767f, 1.5495485f, -1.5063615f,
- -0.28638968f, -0.30667046f, -1.7011343f, 0.5012116f,
- -2.7537332f, 0.0055888784f, -2.3224354f, -0.043928463f,
- -0.97129756f, 5.224371f, -0.28040063f, 0.008421915f,
- -0.83235735f, -0.53416884f, 1.698747f, 1.6617267f,
- -0.57036597f, 2.63421f, 0.36546344f, 0.24196061f,
- 0.7234324f, -0.21784206f, -0.25634804f, -0.22304957f,
- 0.39097315f, -0.008741378f, -0.17681432f, 0.30564892f,
- 0.2969692f, -0.04728322f, -0.1769129f, -0.19537492f,
- 0.61476505f, 0.021090567f, -0.19044618f, -0.14660428f,
- -0.04327838f, 0.009831693f, -0.10728065f, -0.047988523f,
- -0.1953514f, 0.14574943f, 0.091007344f, -0.12548321f,
- -0.21557896f, 0.6490816f, 0.6706153f, -0.15083398f,
- 0.48909312f, -0.017384741f, -0.0691865f, 0.3273862f,
- 0.41122165f, -0.053007513f, 0.055924486f, 0.11616343f,
- -0.11381378f, -0.18861847f, 0.035475507f, -0.14463553f,
- 0.020903034f, -0.028393472f, 0.23827375f, 0.117143854f,
- -0.14295751f, -0.18281136f, -0.1315779f, 0.34399825f,
- 0.1060391f, -0.13702962f, -0.007325602f, -0.054384384f,
- 0.047968693f, -0.15058969f, 0.03528741f, -0.03264773f,
- -0.05611374f, -0.08812282f, -0.040549017f, -0.08134948f,
- -0.12322125f, 0.11173997f, -0.17985299f, -0.117379084f,
- -0.04751613f, -0.0453186f, -0.17121248f, -0.120650716f,
- 0.3008533f, -0.13604338f, -0.2312113f, -0.267777f,
- -0.06838144f, -0.102214485f, -0.24163154f, -0.19474687f,
- -0.2517283f, 0.21653143f, -0.09157197f, 0.6186702f,
- 0.21792777f, 0.11362158f, -0.10750329f, 0.021646664f,
- -0.0872163f, -0.06653854f, 0.04243477f, -0.06014599f,
- -0.15899053f, 0.4326105f, -0.10010083f, -0.13179873f,
- -0.07654102f, -0.040778946f, -0.010038068f, -0.11370343f,
- 0.529933f, 0.022405999f, -0.022277465f, 0.10587728f,
- 0.29940683f, -0.052601963f, -0.07646106f, -0.13687944f,
- -0.13781238f, -0.107919395f, -0.16034442f, -0.11209772f,
- 0.053654727f, -0.23029792f, -0.21985029f, -0.23444322f,
- -0.5287187f, 0.801521f, -0.26808834f, 0.043810233f,
- -0.30456012f, 0.3436382f, 0.06651039f, 0.23279819f,
- -0.018761072f, 1.1525649f, -0.44277027f, -0.46935633f,
- 1.2033889f, -0.1400845f, -0.3975472f, 0.27152827f,
- -0.31344834f, -0.20000494f, 0.59125596f, -0.5193746f,
- -0.6417476f, 0.547658f, 1.4984641f, 0.16770877f,
- -0.09375012f, 1.6910841f, 0.021209031f, -0.072300024f,
- 1.0841964f, -0.701817f, 0.042536065f, 0.46825033f,
- -0.41319844f, -0.38649485f, -0.2542414f, -0.37790507f,
- 0.22321616f, 1.5227073f, -0.24193677f, -0.13515894f,
- 0.48204318f, -0.6061077f, 0.06417249f, -0.45132867f,
- 2.1943748f, -0.616795f, 0.52919525f, -0.12561125f,
- -0.0453486f, -0.100962184f, -0.275838f, -0.5062743f,
- -0.30687466f, -0.1278186f, -0.011203384f, -0.040135473f,
- -0.21950784f, -0.014023699f, -0.5689156f, -0.31990737f,
- -0.62819046f, -0.7325878f, -0.22253011f, -0.26901752f,
- -0.41088143f, -0.40788725f, 0.10683648f, -0.2771732f,
- -0.052496053f, -0.48744166f, -0.07127866f, -0.2838143f,
- -0.29535636f, 1.0662079f, -0.44651407f, -0.15743932f,
- 0.98865026f, -0.3166158f, -0.56746006f, -0.0030915185f,
- -0.1676328f, 0.16340098f, -0.050461367f, -0.18945758f,
- -0.40491772f, -0.122527696f, -0.6039433f, -0.21733719f,
- -0.193425f, 0.14421636f, 0.17070553f, 1.1028305f,
- 0.24130051f, -0.22750843f, -0.40559942f, -0.52909887f,
- -0.52995145f, 1.1695341f, -0.38816306f, -0.44507048f,
- -0.09603342f, 0.11764391f, 0.0701394f, -0.3612054f,
- 0.8245945f, 1.0583714f, -0.19053051f, -0.18359883f,
- -0.28320813f, -0.23456189f, 0.2946121f, -0.40889156f,
- 0.009736172f, 0.07649413f, 0.22102253f, 0.065706134f,
- -0.08907329f, -0.48120788f, -0.09263865f, 0.083242625f,
- -0.35432968f, -0.17747238f, -0.37146932f, 1.1576375f,
- 0.16740873f, 0.052562684f, -0.27060968f, 0.4377189f,
- 0.07271332f, -0.12305617f, 0.054123107f, -0.33827266f,
- 0.33637735f, -0.2120195f, -0.07014158f, 0.09554993f,
- 0.046502456f, -0.083503f, 0.1584022f, 0.056691844f,
- 0.49514475f, 0.118390225f, 0.021038529f, -0.16262738f,
- 0.8491802f, -0.20001979f, -0.14899103f, 0.04122487f,
- -0.01781439f, -0.13489072f, -0.07485965f, -0.4490563f,
- 0.005049611f, -0.044890907f, 0.7657999f, -0.08629194f,
- -0.120190814f, 0.2350961f, -0.24878065f, -0.14938956f,
- 0.3503708f, -0.056958824f, -0.1647937f, -0.2778128f,
- -0.10236353f, 0.6930102f, 0.34379476f, 0.29535016f,
- 0.06290854f, -0.19532746f, 0.08598317f, -0.014372199f,
- 0.12364355f, -0.033260964f, 0.14872591f, -0.08283847f,
- -0.13635302f, -0.17803626f, -0.15424138f, -0.22236486f,
- -0.20047107f, -0.13545504f, -0.068497166f, 0.2004436f,
- 0.026928816f, -0.37886053f, -0.039926454f, -0.28863356f,
- -0.16515034f, 0.84477097f, -0.31454983f, -0.3209522f,
- -0.014012054f, -0.010404553f, -0.04629162f, -0.013837334f,
- -0.34164938f, 0.09523312f, -0.14785895f, 0.12515046f,
- 0.7633839f, -0.062697954f, 0.031270403f, -0.041281544f,
- 0.05953366f, 0.33388138f, -0.16169254f, -0.17160745f,
- 0.0077215284f, -0.36034396f, 0.199276f, 0.015042629f,
- 0.1482077f, -0.029946856f, -0.13723151f, -0.18796533f,
- -0.28186372f, -0.39192715f, -0.1503892f, 0.431504f,
- -0.28098878f, -0.4142621f, -0.12402334f, -0.02028827f,
- -0.043540843f, -0.31288493f, -0.30291897f, 1.2958933f,
- 0.1490672f, -0.33631718f, -0.33657217f, -0.36308494f,
- 0.35435304f, 0.09754517f, -0.111401774f, -0.31180835f,
- 0.6272829f, 0.058185097f, -0.12000916f, -0.113913514f,
- 1.3351499f, 0.3601752f, -0.11812287f, -0.15129247f,
- -0.19344296f, -0.10563926f, -0.0041462723f, 0.017456124f,
- -0.18277758f, 0.39679068f, -0.06755673f, -0.17798342f,
- -0.21949911f, 0.77046794f, -0.22799225f, -0.096470274f,
- -0.16584155f, 0.21957088f, -0.12520896f, -0.110509f,
- -0.22320558f, -0.21300258f, 0.14954196f, 0.6633367f,
- -0.25884697f, 0.10596317f, 0.033553597f, -0.18822557f,
- -0.012210129f, 0.43323874f, 0.092393234f, -0.003765035f,
- -0.33335087f, 0.17822488f, 0.37895316f, 0.027047588f,
- 0.19805887f, 0.025904287f, -0.22598429f, 0.055042848f,
- 0.018727452f, -0.016294517f, -0.14978309f, 0.21082492f,
- -0.13164519f, -0.19815104f, -0.34388208f, 0.26843324f,
- -0.25592023f, -0.34622362f, -0.31193885f, -0.39658338f,
- -0.034463134f, -0.07995029f, 1.3307846f, -0.0128201805f,
- -0.09626083f, -0.15272719f, 0.70665646f, -0.18967377f,
- -0.08395918f, -0.015629785f, -0.14296123f, -0.12569074f,
- 0.07943739f, -0.1723122f, -0.266436f, -0.07925785f,
- 0.02634826f, 0.21013555f, -0.13513534f, 0.16859907f,
- 0.08853125f, 0.08849006f, 0.123375244f, 0.24584512f,
- 0.08540219f, -0.42584068f, -0.23191947f, -0.1562568f,
- -0.028772457f, 0.04441753f, -0.14506005f, 0.19076844f,
- -0.19305545f, -0.3378347f, -1.2815661f, 2.3195052f,
- 0.23513466f, -2.1889615f, -1.7567458f, -0.52724934f,
- -0.19621283f, 1.026492f, 3.5484905f, 4.7461357f,
- -0.08541619f, -2.2039154f, 4.7287707f, 0.26187676f,
- 1.0493529f, 0.056926668f, -3.4218912f, -0.7294055f,
- 2.009485f, -0.4943022f, -0.54420793f, -2.3109689f,
- 2.2964032f, -0.51320344f, -0.4079269f, 5.5770364f,
- -0.25271305f, -1.517199f, -1.0754293f, 0.13864838f,
- -1.4120959f, 0.77633244f, 0.81496537f, -1.6322548f,
- -1.6270533f, -2.3769603f, -0.35931483f, -2.3837388f,
- -0.5858238f, 1.0401708f, -1.0375676f, -0.19178878f,
- 0.8972118f, -0.47487476f, -2.136933f, -0.20744216f,
- -1.1276842f, -0.5693123f, -3.0526197f, -1.2430822f,
- -0.013834929f, -1.9250358f, -2.1743128f, 0.8310249f,
- 3.3299127f, 2.5749636f, -2.3196511f, -0.0022389463f,
- 0.37381372f, -1.5415776f, -2.1407623f, -2.4756517f,
- -1.7394269f, 0.74767274f, 0.752431f, 4.1157646f,
- 0.09263193f, 2.6521301f, -1.4250888f, -1.3382101f,
- 2.8955317f, 0.504777f, 1.3090324f, 1.5585424f,
- -2.248061f, 0.34021223f, 1.2176989f, -0.20798108f,
- -0.25879228f, 2.4032428f, -2.289964f, 0.29493538f,
- -1.7826364f, 4.639924f, -0.15230362f, 0.54832464f,
- -2.8957746f, -0.42665747f, -1.7617737f, 0.4721964f,
- 3.388569f, 2.019412f, -0.1276606f, -0.86543006f,
- 0.15728688f, -0.30536222f, 1.9174821f, -2.7572086f,
- -0.16182229f, -1.9096575f, -0.3039301f, 4.0389476f,
- -0.8672741f, -0.34903723f, 1.5007206f, 1.5904405f,
- 0.039461024f, -0.78112805f, -0.08436093f, -0.24825224f,
- 0.025592381f, 0.6478985f, -0.16199392f, -0.43091974f,
- -0.28180754f, -0.25090092f, -0.015304262f, -0.26878914f,
- -0.19535263f, 1.8666476f, 0.04283891f, -0.16313834f,
- -0.20674278f, -0.1587209f, -0.30029413f, -0.13369042f,
- -0.1783596f, -0.15359487f, 0.23473135f, -0.1603238f,
- -0.09598814f, -0.25224665f, 2.154507f, -0.05772303f,
- -0.08173451f, 0.29443777f, -0.13814361f, -0.11952421f,
- 0.8147143f, -0.23570015f, -0.27389774f, 0.005185866f,
- -0.1345647f, -0.12892415f, -0.20618454f, 0.4189949f,
- -0.28719035f, -0.13773736f, -0.16449283f, -0.2219996f,
- -0.23598742f, -0.13278048f, -0.15563633f, -0.15606636f,
- 0.6051741f, 0.33271465f, -0.15397236f, -0.023425777f,
- -0.16978487f, -0.21138133f, 0.033704743f, 0.12527755f,
- 0.011495239f, -0.103990704f, -0.09003131f, 0.02149359f,
- 0.26734117f, 0.012367443f, -0.15167575f, -0.08532969f,
- -0.24009104f, 0.008301697f, -0.08959171f, -0.1738648f,
- -0.19733414f, -0.16367683f, -0.08730751f, -0.20501307f,
- -0.18767008f, 0.07621155f, -0.21957405f, -0.113924846f,
- -0.20235915f, -0.397544f, -0.2804616f, -0.07626827f,
- 1.8957566f, -0.11615064f, -0.1022374f, -0.08005301f,
- 0.37116328f, -0.14095655f, 0.008193444f, -0.12775972f,
- -0.11359149f, -0.11657682f, -0.1504638f, -0.0034967228f,
- -0.14520784f, -0.036062893f, -0.0014193782f, 0.87605244f,
- -0.22058469f, 0.4087201f, -0.05497325f, -0.08454893f,
- -0.09466476f, 1.3625481f, -0.20577246f, -0.28690863f,
- -0.078399636f, -0.2735109f, -0.27761284f, -0.13880941f,
- -0.13255903f, 0.5805486f, -0.26943687f, -0.16976406f,
- -0.06982756f, -0.09856063f, 1.3230991f, -0.115745544f,
- -0.12075958f, 1.437889f, 0.5515375f, -0.060528643f,
- -0.09119927f, -0.13250007f, -0.3680678f, -0.13481387f,
- -0.12505104f, -0.13050066f, -0.118254095f, 0.3965317f,
- -0.13797075f, -0.28463468f, -0.117387354f, -0.10483257f,
- -0.28949398f, -0.21503507f, -0.13508281f, -0.47217304f,
- -0.020160777f, -0.08219967f, -0.41505033f, -0.06905233f,
- -0.05093733f, 0.50464576f, 1.636901f, -0.07327187f,
- 0.28298354f, -0.18058643f, -0.14896865f, -0.18857615f,
- -0.10784328f, -0.061899412f, -0.04878722f, -0.10001152f,
- -0.24298294f, -0.19870773f, -0.3809348f, -0.2219842f,
- -0.005941358f, -0.3744718f, 0.2559465f, -0.21087526f,
- -0.4094691f, -0.15416068f, -0.09937877f, -0.077830225f,
- -0.0412637f, -0.030442547f, 0.0022136394f, -0.10549877f,
- -0.13643372f, 0.9913382f, -0.25360903f, -0.1947213f,
- -0.18271008f, -0.14867243f, -0.20128587f, -0.12788768f,
- -0.34216306f, -0.046331096f, 1.366183f, -0.11503454f,
- -0.090297155f, -0.084191926f, -0.16780698f, -0.09608864f,
- -0.07035177f, -0.1251298f, -0.09916915f, 1.4800682f,
- -0.16279575f, -0.31861454f, -0.22657223f, -0.002596071f,
- -0.15101704f, -0.17189176f, -0.14298476f, -0.10916664f,
- -0.08368682f, -0.37331408f, -0.075897485f, 1.3074678f,
- -0.17268066f, -0.009161089f, 0.010623572f, -0.08774159f,
- -0.36538914f, -0.19597016f, 0.8080526f, -0.3550649f,
- -0.01577225f, 0.0101095f, 0.57400036f, -0.12670948f,
- -0.09933071f, -0.16315319f, -0.0606557f, -0.08961001f,
- -0.022791542f, -0.14194931f, 0.9987653f, -0.11994942f,
- 1.1122749f, 1.4372432f, 0.32108647f, -0.27646768f,
- 0.8836573f, -1.3577833f, -0.5748887f, -0.0096977595f,
- -0.9155803f, -0.60391533f, -0.62437135f, 0.13113101f,
- -1.1620464f, -0.6815617f, -0.9704845f, -0.719415f,
- -0.31971526f, -1.5521828f, 1.6344692f, -0.3903355f,
- 0.919178f, 0.8357637f, -1.4343774f, -0.40080035f,
- -0.50934017f, -0.6721517f, 0.6934414f, -0.427786f,
- -0.66969293f, -0.6511647f, -0.20074236f, -0.18157747f,
- 1.0816762f, 0.1751129f, -0.47325563f, -0.015705775f,
- -0.4282315f, 1.5067525f, 0.11567471f, -0.59911126f,
- 0.5132431f, 0.9812623f, 1.2598015f, 0.060524188f,
- -0.34407812f, -0.4682127f, 0.8816723f, 0.32947794f,
- -0.40583283f, 1.3988909f, -0.2745342f, -1.119118f,
- 1.1059473f, 0.62849194f, -0.27120298f, -0.2874386f,
- 0.07903139f, -1.3567938f, -0.21474826f, 1.4827604f,
- -0.07029011f, -0.14834237f, 0.58231556f, 1.6524523f,
- 0.7067015f, -0.23309578f, 0.24449867f, -0.15490212f,
- -0.5613024f, 0.06284719f, 1.2070864f, -0.053461123f,
- -0.562692f, -1.196484f, -0.35733977f, 0.6875246f,
- -0.28977662f, -0.53476095f, 0.3691815f, -0.007896205f,
- -0.24340886f, -1.0048728f, 0.71970344f, -0.81647915f,
- -0.026831822f, 0.4844168f, -0.04569298f, 1.0620259f,
- -0.662667f, -0.65691805f, -0.6559576f, 0.32373813f,
- -0.84927f, 1.1510181f, -0.4962945f, -0.33528128f,
- 2.0250568f, -0.73306274f, -1.0351774f, -0.3780182f,
- 2.1499999f, -0.72853976f, 1.1922737f, -0.85046715f,
- 0.9968989f, -0.048206784f, -0.06877019f, 0.8319538f,
- -0.6463578f, -0.31151533f, -0.0696477f, -0.25498357f,
- -0.28795424f, 1.08308195e-05f, -0.29342607f, -0.25621444f,
- 0.73717517f, -0.31286582f, -0.2629952f, -0.18843372f,
- -0.13229032f, -0.22459164f, -0.16031079f, 0.123340115f,
- -0.1981602f, -0.058389224f, 0.289792f, 0.5287891f,
- -0.2328848f, 1.3245087f, 0.6085664f, -0.32809648f,
- -0.16848487f, -0.05914133f, -0.21200486f, -0.06394738f,
- -0.20456624f, -0.11637028f, -0.19433808f, -0.32059878f,
- -0.18559627f, -0.039251033f, -0.019514265f, 0.12606227f,
- 0.07760057f, -0.43053326f, 0.08855741f, -0.17834494f,
- -0.24874118f, -0.08451061f, 1.0810332f, 1.4024812f,
- -0.14988022f, -0.09458241f, 0.011524404f, 0.63525206f,
- 0.08995243f, 0.29076752f, 0.05718654f, -0.08213285f,
- -0.101935975f, -0.052483276f, 0.013467546f, -0.081728965f,
- -0.069264315f, -0.20304224f, -0.2998753f, -0.12627845f,
- 1.4067383f, -0.06201511f, -0.084494986f, -0.3202574f,
- -0.031270467f, -0.11509549f, -0.2719797f, -0.2368172f,
- 0.15738869f, -0.16609116f, -0.045756217f, 0.034573965f,
- -0.10260898f, -0.097559385f, -0.048218526f, 0.050305724f,
- -0.07038058f, -0.19726963f, -0.07573453f, -0.121048056f,
- 0.6991223f, -0.042374004f, -0.2024927f, 0.4370784f,
- -0.12296924f, -0.2883948f, 1.4612396f, -0.31215468f,
- -0.023952246f, -0.44410402f, -0.13560586f, -0.12370176f,
- 0.073652625f, -0.1580055f, 0.4566076f, -0.3121312f,
- -0.24917488f, 0.54001164f, -0.12926657f, -0.03865389f,
- -0.20816545f, -0.08448917f, -0.26327676f, -0.065227546f,
- -0.28552118f, 0.031175064f, -0.35016882f, -0.12777117f,
- 0.65371585f, -0.10202621f, 2.4087455f, -3.266491f,
- 6.095844f, 0.17426135f, 3.359535f, 1.036438f,
- -0.9493194f, -0.23483482f, -1.650954f, 4.5039845f,
- -2.9541116f, 0.05467842f, 4.5112863f, 5.7865195f,
- 1.6191982f, -2.3916495f, 0.0865164f, 1.6438348f,
- -2.0106442f, 0.39147246f, 0.52980113f, -1.9196848f,
- 0.7244412f, 0.06783857f, 0.6898661f, -0.25741175f,
- 3.8972783f, -0.30473477f, 2.920489f, 2.5053525f,
- 0.066058144f, -1.2725036f, -3.2180717f, -0.03810225f,
- -0.856813f, -4.2226934f, 2.2784145f, -0.30659667f,
- -2.12091f, -1.7970078f, -1.3218278f, -1.783253f,
- 0.063333035f, -3.1837528f, 1.4780867f, -3.0163717f,
- -0.3970922f, 0.5067658f, -4.2100677f, -2.0088894f,
- 6.4740615f, -3.3785388f, -0.50790095f, 4.3015857f,
- -1.4204562f, -3.7211633f, -2.1237755f, -0.9828549f,
- 0.23337576f, -0.47626746f, 5.6062694f, -0.63490283f,
- -2.5449953f, -1.0987254f, 5.2900076f, -1.7566563f,
- 0.06390288f, 1.8769423f, -4.1036754f, -4.359991f,
- 3.2178812f, -1.1620681f, -3.1524253f, 7.09223f,
- -2.8750422f, 0.42394456f, -0.19523335f, 1.1832179f,
- -0.9766359f, 0.030061971f, 0.15534171f, -1.1570352f,
- 0.23210087f, 2.557233f, 2.6630156f, -0.06609925f,
- -2.3467286f, -2.4289668f, 0.41390553f, -3.6022596f,
- 5.552863f, -3.7497773f, -3.7329082f, -0.3194792f,
- 0.043610178f, -0.08403635f, 1.3035899f, 2.9944115f,
- -3.0667975f, -0.14423798f, -2.511715f, 1.3830131f,
- 0.7811466f, -1.5587654f, 1.1133249f, 6.844821f,
- -2.2599623f, 0.026614403f, -1.0513079f, -0.50249565f,
- -0.38113603f, -0.6752348f, 0.0040815943f, -0.58440804f,
- -0.11245597f, -0.24002707f, 0.31617233f, 0.43485394f,
- -0.89328426f, -0.5245108f, -0.4981953f, -0.8809664f,
- -1.475318f, 1.822441f, -0.6764871f, -0.53207177f,
- 0.92198324f, 1.049346f, -0.6195634f, 0.23135683f,
- -0.12806688f, 0.34087345f, -0.4947116f, 0.27793264f,
- 0.3309108f, -0.35712528f, -0.055688232f, -0.07692751f,
- -0.104561776f, -0.27600068f, 0.562324f, -0.23652112f,
- 0.8648625f, -0.012875913f, -0.42779493f, -0.36293915f,
- 0.6164516f, 0.350506f, 0.11316703f, -0.54905367f,
- 1.6417748f, 0.43641415f, -0.7006657f, 1.989396f,
- 0.4320936f, 0.1891744f, 0.37457675f, -1.5293186f,
- 0.7627653f, 0.1260548f, -0.7640425f, -0.5942941f,
- -0.97550946f, -1.267875f, -1.3515993f, -0.6393995f,
- -0.42333195f, -0.021553572f, 0.6489035f, -0.19163133f,
- -0.29176754f, 0.30665162f, -0.7019377f, -0.26743677f,
- -0.7480349f, -1.0206965f, -0.039098527f, 0.5443362f,
- 0.571772f, 0.9602582f, 1.3838924f, -0.6381134f,
- -1.2501501f, 0.4280156f, 1.1424532f, 0.18656509f,
- 0.58760893f, 0.06223792f, 0.15221485f, 0.24204847f,
- -0.38740757f, 0.33904892f, 1.3466043f, -0.31835377f,
- 0.11217311f, -0.31828997f, 1.4359462f, -0.22087432f,
- 0.5546434f, -1.0068915f, -0.46132997f, -0.83066976f,
- 0.15194432f, 0.07516632f, 0.008261107f, 1.0557826f,
- -0.1952036f, -1.0550696f, -0.13910611f, -0.4241279f,
- -0.17835413f, -0.5831741f, 1.0170734f, 1.2354813f,
- 0.20353816f, 0.013965358f, 0.18969852f, 2.0707347f,
- -0.2841195f, -0.8129648f, -0.6183572f, 0.93522084f,
- -0.2952304f, 0.15583515f, 1.0578496f, 0.573059f,
- 0.059979986f, 0.15803291f, -0.49104732f, -0.084322535f,
- -0.31420475f, -0.45778072f, 0.16191567f, 0.15736192f,
- 1.9677418f, 0.10755156f, 0.067414366f, -0.4081863f,
- 0.8029641f, -0.14472248f, -0.41317734f, -0.18666159f,
- -0.3376056f, 0.38580412f, -0.25134873f, -0.1874116f,
- 0.030958945f, -0.08712697f, -0.022372497f, 1.3217231f,
- 0.48999056f, 0.3689628f, -0.0322722f, 0.31244162f,
- -0.25622398f, 0.27025655f, -0.23038468f, 0.14636667f,
- -0.30370852f, -0.17679103f, -0.25549212f, -0.41975877f,
- -0.18716364f, -0.7390592f, -0.10678755f, 1.0081719f,
- 0.14901671f, -0.47000617f, -0.076202504f, 0.03414853f,
- -1.0415605f, 1.0137601f, -0.034472004f, -0.32303518f,
- 0.00026578057f, 0.29645503f, 1.4961746f, -0.029168999f,
- 0.18210252f, 0.14360368f, -0.6744268f, -0.28373465f,
- -0.039796237f, -0.21198149f, 0.050839797f, 0.8718065f,
- -0.12473226f, -0.22330545f, -0.47386274f, -0.2927995f,
- 0.18972886f, -0.39525503f, -0.24396339f, -0.09449901f,
- 0.45069972f, -0.07413976f, -0.5068523f, -0.22930364f,
- -0.09051383f, 0.5561643f, 0.7093209f, -0.4751569f,
- -0.50685513f, -0.13290244f, -0.06885424f, -0.015516052f,
- 0.5929322f, -0.28123194f, 0.116620995f, -0.6206043f,
- 0.591219f, -0.33439574f, -0.155908f, -0.14209053f,
- -0.3868695f, -0.14380379f, 0.9181801f, -0.10742192f,
- -0.3092826f, -0.50159687f, -0.41850325f, 0.09181775f,
- -0.49969178f, -0.025447968f, -0.27810726f, 0.8391941f,
- -0.38472444f, -0.13119619f, -0.2324448f, -0.055826858f,
- 0.49854004f, -0.13219981f, -0.55701715f, -0.258551f,
- -0.21396837f, -0.107818834f, -0.17322089f, -0.18824607f,
- 2.308375f, -0.09368748f, -0.042768367f, -0.1804826f,
- -0.13848259f, 0.40300053f, -0.1832209f, -0.16628683f,
- -0.15669493f, -0.03181183f, -0.18415707f, -0.15863404f,
- -0.33306608f, 2.5261066f, -0.008794327f, -0.019759392f,
- -0.151008f, -0.15270002f, -0.13028802f, 0.05012548f,
- -0.23491031f, -0.35062093f, 0.32417506f, -0.19515914f,
- -0.13614212f, -0.2313649f, 0.20398891f, -0.27064764f,
- -0.10597283f, -0.24936433f, -0.19245611f, -0.36154202f,
- -0.09976704f, -0.2144349f, -0.096016295f, -0.19685313f,
- 1.3526001f, -0.16842547f, -0.16349222f, -0.19387081f,
- -0.21767552f, -0.0679934f, 0.055550538f, 0.041548237f,
- -0.045041054f, -0.13043144f, -0.0605531f, -0.22860025f,
- 0.60209453f, -0.08888808f, -0.1284885f, -0.20360242f,
- -0.067120455f, -0.12749858f, -0.20176163f, -0.14105466f,
- -0.14222729f, -0.041401636f, -0.15930659f, -0.14328063f,
- 0.04962233f, -0.19272764f, -0.18747331f, -0.13663806f,
- -0.32094026f, -0.2738359f, -0.03266663f, 2.277733f,
- 1.0530956f, -0.08831597f, -0.09103688f, 0.043920737f,
- -0.16843553f, -0.03302202f, 0.16642562f, -0.08115893f,
- -0.07000807f, -0.22666112f, -0.06476307f, -0.024925388f,
- -0.082181245f, -0.03201323f, 0.4910786f, -0.24727023f,
- 0.97703373f, -0.13172871f, -0.05482009f, 0.0015730319f,
- 0.7582482f, -0.15719648f, -0.33771214f, -0.06384222f,
- -0.26365042f, -0.27804112f, -0.10724621f, -0.2574277f,
- 0.082898766f, -0.39773682f, -0.08368116f, -0.047660463f,
- -0.055268764f, 0.84139085f, -0.06934373f, -0.10491718f,
- 0.5042439f, 0.7592877f, -0.056321263f, -0.044695597f,
- -0.06360281f, -0.33666867f, -0.029879978f, -0.06278437f,
- -0.058950085f, -0.09282296f, 0.87488896f, -0.10817049f,
- -0.09832582f, -0.06324502f, -0.22155645f, -0.10110401f,
- -0.09616082f, -0.124087654f, -0.43062183f, -0.26907644f,
- -0.042382464f, -0.2084363f, -0.07324683f, -0.08852807f,
- 0.099783555f, 0.57780266f, -0.07156885f, 0.3563412f,
- -0.107549556f, -0.086945996f, -0.111012094f, -0.14284222f,
- -0.10690412f, -0.13439256f, -0.03168871f, -0.1243454f,
- -0.2522219f, -0.11274909f, -0.15657057f, -0.0063189017f,
- -0.1304752f, 0.7723169f, -0.117514595f, -0.16441704f,
- -0.1208079f, -0.10375737f, -0.09737533f, -0.05241262f,
- -0.03947781f, -0.0887536f, -0.06070151f, -0.1294686f,
- 0.3151642f, 0.3196294f, -0.123402916f, -0.046598233f,
- -0.10551649f, -0.06583032f, -0.040384594f, -0.18295354f,
- -0.032555748f, 0.46381044f, -0.05056216f, -0.051094502f,
- -0.05547049f, -0.06678921f, -0.08261536f, -0.065306835f,
- -0.08873963f, -0.111642316f, 0.42966756f, -0.07937818f,
- -0.35051635f, 0.57473093f, -0.053355295f, -0.11047752f,
- -0.13087897f, -0.0930214f, -0.07408951f, -0.15162353f,
- -0.1525808f, -0.044622716f, 0.48150325f, -0.116243616f,
- -0.0361937f, -0.03430232f, -0.044966403f, 0.50839514f,
- -0.18633325f, 0.84175676f, -0.22792114f, -0.07060765f,
- -0.037386652f, 0.307682f, -0.07322931f, -0.10532315f,
- -0.061389368f, -0.07845691f, -0.069962844f, -0.034359943f,
- -0.04855299f, 0.32299995f, -0.118732534f, -0.13052003f,
- -0.21129607f, -0.14765543f, 0.7741163f, -0.28304797f,
- -0.122100286f, 1.0235435f, 0.40060794f, 0.00037895533f,
- -0.104416564f, -0.2759767f, -0.23875573f, 0.019686166f,
- -0.27059922f, -0.1740441f, -0.21198179f, 0.8749577f,
- -0.15874304f, -0.17393464f, -0.2477471f, 0.13710655f,
- -0.10917461f, -0.06393764f, -0.13451485f, -0.31405815f,
- 0.08667383f, -0.094340466f, -0.08912381f, 0.057631202f,
- 0.048601948f, -0.15414274f, 1.1279031f, -0.15870754f,
- 0.46233365f, -0.028685553f, -0.031130055f, -0.10165199f,
- 0.52506447f, -0.013705267f, -0.19499402f, 0.05246916f,
- -0.15988003f, -0.14926694f, -0.15342097f, -0.35197622f,
- 0.07545695f, -0.103687786f, 0.56443584f, -0.13868f,
- -0.27394128f, 0.08637269f, -0.124417536f, -0.18323065f,
- 0.07047054f, -0.09407884f, -0.0713883f, -0.19674529f,
- -0.15313455f, 0.8161082f, 0.09717587f, 0.0688611f,
- -0.109114304f, -0.20849043f, -0.06951481f, -0.07440941f,
- -0.04845107f, -0.0010914217f, 0.90144587f, -0.0516123f,
- -0.16539387f, -0.13193098f, -0.15375869f, -0.05470013f,
- -0.28523004f, -0.10965628f, -0.18910521f, 1.0824307f,
- -0.09918153f, -0.26267937f, -0.14576432f, 0.0725433f,
- -0.11570334f, 0.5190122f, -0.24625795f, -0.14624517f,
- -0.012077995f, -0.20233095f, -0.047745164f, 0.8216116f,
- -0.19394633f, -0.05419922f, -0.10708022f, 0.03596903f,
- -0.36058554f, -0.16062975f, -0.05766138f, -0.29010049f,
- 0.061371796f, 0.14556165f, -0.2828521f, -0.30065766f,
- -0.09859678f, -0.3003686f, 0.083196305f, -0.0576899f,
- -0.06123747f, -0.047381964f, 0.76268595f, -0.15063877f,
- -0.11109369f, -0.05174998f, -0.07765574f, 1.1259031f,
- -0.095028654f, -0.1253365f, 0.66866153f, 0.84288746f,
- -0.043506894f, -0.07915223f, -0.08746116f, -0.40622997f,
- -0.018269073f, -0.081571296f, -0.04593512f, -0.110241726f,
- 1.1997986f, -0.1767196f, -0.17663464f, -0.07010551f,
- -0.214583f, -0.16141638f, -0.115694f, -0.0947953f,
- -0.37503064f, -0.11939846f, -0.029507706f, -0.16271941f,
- -0.08723539f, -0.10056567f, -0.24840713f, 0.7565219f,
- -0.086489394f, 0.46073604f, -0.15962537f, -0.07161478f,
- -0.07011309f, 0.13287735f, -0.12199839f, -0.27217048f,
- 0.0045968574f, -0.29279864f, -0.18400094f, -0.13983598f,
- -0.12913933f, 0.013736465f, -0.23320532f, 1.050348f,
- -0.17954144f, -0.18498991f, -0.12037797f, -0.08224188f,
- -0.10723017f, -0.0057567186f, -0.032021113f, -0.1115914f,
- -0.062258676f, -0.117435604f, 0.8124806f, 0.30621663f,
- -0.13320911f, -0.059633292f, -0.1374305f, -0.11186229f,
- -0.019089593f, -0.19910643f, -0.031426374f, 0.6266844f,
- -0.07035628f, -0.029797504f, -0.040501524f, -0.050352335f,
- -0.066186346f, -0.06969192f, -0.11800144f, -0.1539169f,
- 0.5749399f, -0.104958f, -0.34239277f, -0.043641273f,
- -0.06847451f, -0.13746688f, 0.18500625f, -0.14006568f,
- -0.09373776f, -0.06506556f, -0.1885023f, -0.039818283f,
- 0.65134466f, -0.10265719f, -0.030746432f, -0.030068368f,
- -0.039620496f, -0.1416703f, -0.24374117f, 0.1883926f,
- -0.27613363f, -0.06519614f, -0.03011759f, -0.19671965f,
- -0.14726332f, -0.09792944f, -0.05695446f, -0.07739734f,
- -0.06679513f, -0.004564232f, -0.08798595f, 0.97412133f,
- -0.11236392f, -0.08368292f, -0.1113367f, -0.12154418f,
- 0.7901808f, -0.13464737f, -0.08069967f, 0.24245468f,
- 0.59300154f, -0.05661877f, -0.116541f, -0.10440867f,
- -0.46199375f, -0.036850527f, -0.09439456f, -0.004317197f,
- -0.09348827f, 1.2411786f, -0.19149007f, -0.21308044f,
- -0.10826191f, -0.10516452f, -0.09111764f, -0.08511498f,
- -0.07900209f, -0.52987474f, -0.008239507f, -0.0912693f,
- -0.1404758f, -0.11263876f, -0.11122594f, -0.17884775f,
- 0.28071728f, -0.08718163f, 0.62123305f, -0.2551762f,
- -0.03796279f, -0.1040174f, 0.8931919f, -0.110081084f,
- -0.30444592f, -0.046192363f, -0.43073097f, -0.22790459f,
- -0.10645123f, -0.2022932f, 0.08528021f, -0.26641437f,
- 1.1064006f, -0.11868103f, -0.106399275f, -0.16283742f,
- -0.09297128f, -0.060101897f, 0.07692893f, -0.04196958f,
- -0.02826893f, -0.08139377f, -0.12163745f, 1.1855142f,
- 0.58798856f, -0.09762801f, 0.018026179f, -0.14270791f,
- -0.14172679f, 0.029590499f, -0.122279145f, -0.09207396f,
- 0.25393918f, -0.04165743f, 0.02619407f, -0.07000153f,
- 0.012718133f, -0.085064545f, -0.0939306f, -0.06788999f,
- -0.13000627f, 0.0013943916f, -0.080618486f, -0.4527379f,
- -0.20644818f, -0.064025246f, -0.1130632f, 0.98146373f,
- -0.1867183f, -0.107692696f, -0.04935813f, -0.11360012f,
- 0.021498853f, 0.27727717f, -0.18011096f, -0.045388345f,
- -0.080351576f, -0.07905102f, 0.9679014f, -0.21509098f,
- -0.025141614f, -0.23827997f, -0.082579516f, 0.029328687f,
- -0.16472152f, -0.20232582f, -0.061896894f, -0.09893113f,
- -0.08643843f, -0.03902357f, 0.014971803f, -0.0673121f,
- 0.5138868f, -0.16759382f, -1.9519805f, -0.602176f,
- 2.5295804f, 0.00910939f, 2.749339f, -0.7643367f,
- -0.45122433f, 0.11093682f, 4.175706f, -0.9199247f,
- -2.0908785f, -2.489833f, -1.8552456f, -3.386875f,
- -2.2906144f, -3.4749703f, -0.45806634f, 0.90675986f,
- 2.6211383f, 1.8535618f, 0.06659838f, -1.5123895f,
- -2.414913f, -0.5025387f, 2.8002784f, -0.06677548f,
- -3.3078015f, 0.08455167f, -3.4263701f, -2.8238158f,
- -0.5129066f, 0.7717553f, 1.0060759f, 0.12290679f,
- 1.6582808f, -2.0790713f, -0.48421285f, 0.88037455f,
- -2.2000124f, -0.6396533f, 0.31693137f, 3.0822368f,
- 0.39549902f, -3.2363648f, 6.7484465f, -2.237169f,
- 0.3689931f, 1.039334f, -1.9417852f, -1.1327552f,
- 4.00565f, 0.85055447f, -2.3645377f, -1.2822101f,
- -2.809311f, -1.2797421f, -0.02811723f, -3.0291812f,
- 0.40678772f, -0.4798976f, -1.3187723f, -2.3703682f,
- -0.64878005f, 1.0855045f, -2.136626f, -2.8678892f,
- -2.8210955f, -2.1351926f, -2.8291335f, 6.646664f,
- -0.4292809f, -1.1415133f, 5.9634523f, -0.6078361f,
- 6.9101014f, 5.501686f, 1.0687903f, -1.7215645f,
- -0.044915143f, 0.17561024f, 2.6164596f, -0.5921682f,
- -0.4663366f, 4.4552207f, -2.4679074f, 0.3372961f,
- 0.29786673f, 1.5549171f, 1.4567565f, 5.5117316f,
- 2.6437716f, -0.8412153f, 1.1736205f, 0.04915113f,
- 3.5898423f, 0.1774926f, -1.9637988f, -2.275763f,
- -1.4954418f, 0.33605453f, -3.170017f, -1.7549049f,
- -1.9897196f, 7.4508157f, -1.9688671f, -2.3286178f,
- 0.97663367f, 0.4127904f, 2.9624517f, -0.055959385f,
- -0.053461473f, -0.061439205f, 0.3257586f, -0.08307456f,
- -0.059519436f, -0.06429129f, 0.07658212f, -0.058101323f,
- -0.07431584f, -0.067218475f, 0.36571473f, -0.050496545f,
- -0.062153175f, -0.05466894f, -0.059337236f, 0.4748401f,
- -0.0826262f, -0.10921034f, -0.07743116f, 0.15071645f,
- -0.07615701f, -0.08337393f, -0.09784244f, 0.5043117f,
- -0.029467536f, -0.066183165f, -0.07269186f, -0.045365922f,
- -0.053049695f, -0.050670587f, -0.09495533f, -0.073250934f,
- 0.39143428f, -0.108917676f, -0.056214742f, -0.053949352f,
- 0.6833067f, -0.056178708f, -0.25434515f, -0.03574544f,
- -0.19147204f, -0.08579028f, -0.045416966f, -0.10326086f,
- -0.041296992f, -0.009446609f, 0.5023429f, -0.09795358f,
- -0.076330565f, -0.071467936f, -0.059395038f, -0.010989187f,
- -0.03009351f, -0.024900738f, -0.05331427f, -0.06350744f,
- -0.056164544f, 0.54528564f, 0.31808436f, -0.016547022f,
- -0.06929774f, -0.11007714f, -0.069392994f, -0.0077741304f,
- -0.038647097f, -0.02652827f, -0.031298693f, -0.06218128f,
- -0.05430283f, -0.0527219f, -0.04105249f, -0.06946334f,
- -0.04962562f, -0.061021216f, -0.15101607f, -0.040421356f,
- -0.046151347f, 0.20808704f, 0.0063791643f, -0.05846619f,
- -0.07833108f, 0.6632375f, -0.15314995f, -0.05286955f,
- -0.08915751f, -0.056781124f, -0.052497f, -0.011494591f,
- -0.05846685f, -0.040417556f, -0.04534528f, -0.038942464f,
- 0.41981885f, -0.1909183f, 0.075824924f, -0.07734033f,
- -0.07750642f, -0.021268297f, 0.05423624f, -0.053912878f,
- -0.06638679f, -0.07497318f, -0.06153621f, -0.025031418f,
- -0.043833416f, -0.0917129f, 0.28302687f, -0.11614219f,
- 2.258061f, -1.130483f, -2.1507313f, -0.31885573f,
- 1.9658018f, 3.9673738f, -1.6244081f, 0.5256587f,
- 0.51154083f, -1.5373716f, -2.1380854f, 0.48148265f,
- 1.6754879f, -0.8518128f, -1.2529751f, -0.48321536f,
- -0.23504835f, -3.9271803f, 0.8208844f, 1.5294725f,
- 0.019425107f, 1.2700267f, -0.75609094f, -1.7399364f,
- 1.282176f, 0.15173934f, -1.8892016f, 0.77775383f,
- 5.8974185f, 5.907216f, 0.26897433f, 0.7408122f,
- -1.5962063f, -0.02350243f, 1.9175878f, -0.41626465f,
- 5.733645f, 0.17419395f, 1.1746888f, -0.9446142f,
- 0.2715788f, -1.0101184f, 0.20566608f, -0.5399954f,
- 0.8357004f, 1.3517275f, 0.5734244f, 1.374214f,
- 1.7202739f, 0.63113636f, 2.42144f, -1.4812343f,
- 2.621398f, -2.5555568f, -2.075362f, -2.4599626f,
- -1.3214525f, -2.8623428f, 0.5414248f, 0.4933636f,
- -0.9312378f, -3.5117433f, 1.0347116f, 0.8151741f,
- -2.3293688f, -1.5083746f, -0.3210831f, 0.49568018f,
- 1.1332704f, -4.682554f, 4.4328794f, -1.842575f,
- -2.310571f, -3.552708f, -0.9017628f, 1.2981378f,
- 1.2370092f, -0.37713897f, -1.5743316f, 0.017195078f,
- -0.5020347f, -2.624885f, -0.71366477f, -1.5710014f,
- -1.7532756f, 0.30926597f, 0.49650398f, 2.9881744f,
- 0.99009097f, 1.1868433f, -1.1227673f, -1.535681f,
- -1.4868444f, 0.07720787f, 1.4918412f, -0.20241548f,
- 3.8292606f, -2.9665334f, -2.577595f, 0.40156195f,
- -1.1673509f, 0.40748745f, 1.5127902f, -3.381581f,
- 3.4542062f, -0.46698022f, 1.1181062f, 0.5968714f,
- 1.8243774f, -0.36589947f, -0.33298156f, -0.30428368f,
- 0.2774564f, -0.19253935f, -0.56849235f, -0.12622485f,
- -0.20710973f, 0.020447982f, -0.32427529f, -0.18700576f,
- 2.0565345f, 0.32879916f, -0.17255752f, -0.34050736f,
- -0.2779344f, 0.08193694f, 0.0033037725f, -0.1917348f,
- -0.21289009f, 0.5353999f, -0.12903704f, -0.16374524f,
- -0.12719786f, 2.4100482f, 0.48129904f, -0.21071427f,
- -0.100414224f, -0.23934543f, -0.14513764f, 0.02024158f,
- -0.13327871f, -0.22057733f, 0.3373589f, -0.02577686f,
- -0.17155854f, -0.26434088f, 0.3183f, -0.21790639f,
- 0.4776627f, -0.12858164f, 0.23045908f, -0.31305844f,
- -0.16201746f, -0.17363302f, -0.37596813f, -0.036145784f,
- 0.7926746f, -0.2589597f, -0.16691214f, -0.084440485f,
- -0.13243808f, 0.022239791f, 0.21432239f, -0.09046132f,
- -0.17807402f, -0.18007255f, 0.07682247f, -0.02963357f,
- 0.18300244f, -0.025872918f, -0.14018619f, -0.3228517f,
- 0.03583287f, -0.20707402f, -0.13665022f, -0.22907318f,
- 0.19519438f, -0.24653406f, -0.088317156f, -0.28194505f,
- 0.016002513f, -0.098977275f, -0.20688125f, -0.41651037f,
- -0.31299374f, -0.17795981f, -0.02623531f, 2.1250062f,
- 0.4408557f, -0.062165014f, 0.1613344f, 0.2690011f,
- -0.3070227f, -0.030017281f, 0.49405694f, -0.0045733494f,
- -0.14140908f, -0.07388163f, 0.004902877f, -0.127181f,
- -0.065995924f, 0.10192054f, 0.17294356f, -0.18375298f,
- 0.38328654f, 0.10179841f, -0.114494085f, -0.007949122f,
- 0.36007428f, -0.08969911f, -0.45596796f, -0.2823271f,
- 0.09961858f, -0.23501326f, -0.04887572f, -0.0791287f,
- 0.06190683f, -0.39841965f, -0.08146379f, -0.22428338f,
- -0.031078693f, 0.44891346f, -0.17180671f, -0.4159691f,
- -0.21786802f, -0.041202184f, -0.1146307f, -0.20055325f,
- -0.17740759f, 2.0063798f, 0.014682035f, -0.09555009f,
- -0.2163191f, -0.15372388f, 0.023703266f, -0.14373448f,
- -0.11658951f, -0.11343396f, -0.040715534f, -0.16070846f,
- -0.13298877f, -0.28574017f, 2.2630024f, 0.6764999f,
- -0.02743622f, 0.5139466f, -0.15650484f, -0.11325717f,
- 0.24466977f, -0.1666842f, -0.27603313f, -0.085557826f,
- -0.11506133f, -0.099987134f, -0.22774358f, 0.0069206934f,
- -0.26057214f, -0.1533427f, -0.18737665f, -0.08503808f,
- -0.26358393f, -0.08055295f, -0.1758331f, -0.090465344f,
- 0.042837895f, 0.7714962f, -0.1363173f, -0.08769977f,
- -0.20687135f, -0.18984738f, -0.06199439f, 0.0710344f,
- 0.018933993f, -0.08388959f, -0.094034374f, 0.0058218082f,
- -0.21522002f, -0.03659938f, -0.084743075f, -0.07118662f,
- -0.16966565f, -0.03354038f, -0.11499422f, -0.17792515f,
- -0.13906342f, -0.122735396f, -0.06472666f, -0.23499188f,
- -0.18467985f, 0.046319783f, -0.19699596f, -0.11430557f,
- -0.22009252f, -0.27565956f, -0.2130918f, -0.090810396f,
- 2.0035002f, 0.59360594f, -0.025011906f, -0.05228649f,
- -0.07847551f, -0.13294424f, -0.004805883f, 0.36581734f,
- -0.057543825f, -0.1221756f, -0.13642736f, -0.027458264f,
- -0.06614139f, -0.081170745f, -0.04798978f, 0.19378024f,
- -0.15153123f, 0.92219967f, -0.03334791f, -0.04962749f,
- -0.117188565f, 0.91285485f, -0.1490035f, -0.26970622f,
- -0.058945976f, -0.2642649f, -0.22594811f, -0.1609646f,
- -0.19306104f, -0.00606466f, -0.29056796f, -0.24774908f,
- -0.24269848f, -0.3535273f, -0.3360429f, -0.09070311f,
- -0.67680675f, 0.43361825f, 0.25972846f, -0.18742833f,
- -0.279565f, -0.12943245f, -0.2862977f, -0.20921081f,
- -0.30378515f, -0.5829959f, -0.21499456f, 0.08932297f,
- -0.57107633f, 1.6252655f, -0.7376641f, -0.29194584f,
- 1.9313775f, -0.28734753f, -0.47400555f, -0.25546187f,
- 0.7606984f, -0.23398405f, 0.33286953f, -0.17640056f,
- -0.33401752f, 0.7483067f, 0.05494246f, -0.124012575f,
- -0.07381293f, 2.2735856f, -0.21068306f, -0.48754716f,
- -0.34609443f, 0.041532777f, -0.16075137f, -0.21829452f,
- 1.9472218f, 0.89465487f, 1.9130241f, -0.62047744f,
- -0.068095684f, 0.18740201f, -0.43873352f, -0.69254404f,
- -0.3124421f, -0.57539296f, -0.42734516f, -0.110984735f,
- -0.50547856f, -0.27836904f, 0.078305036f, -0.17600177f,
- -0.2863839f, 0.10359244f, 0.27707243f, 1.7311449f,
- -0.33253628f, -0.44208482f, 2.529758f, -0.053324386f,
- 2.0904443f, -0.5084616f, 0.23615299f, -0.5400558f,
- -0.37108588f, -0.58447546f, -0.16286045f, -0.22648291f,
- -0.25674757f, -0.17262784f, -0.58403844f, -0.210909f,
- -0.43018106f, -0.33658296f, 0.7780641f, -0.28507668f,
- -0.7907123f, -0.12883268f, -0.59148836f, -0.44443488f,
- 0.41152853f, 1.8250066f, -0.016163599f, 0.06199628f,
- -0.55652964f, -0.37390107f, -0.15890448f, -0.3599273f,
- 0.056732256f, 0.36199394f, 0.20709242f, 1.5563772f,
- -0.13581239f, -0.032195877f, -0.36661747f, -0.19979157f,
- -0.3557424f, -0.21971254f, -0.0748019f, -0.5149769f,
- -0.47239813f, -0.3035448f, -0.16423817f, -0.40378055f,
- -1.872856f, -0.8346107f, -0.32050467f, 0.66322196f,
- -1.1142993f, -0.5907424f, 0.08787416f, -0.09120813f,
- -3.7481368f, -1.553146f, -2.357213f, -3.268571f,
- -5.0136642f, -0.5117248f, 0.81506926f, 6.045549f,
- -0.44010428f, 2.4528077f, 0.44482863f, -1.0440376f,
- 0.28858107f, -1.775211f, -2.1447012f, 4.0594344f,
- 0.12862672f, 0.2684586f, 1.6364721f, 0.25992772f,
- -3.8094316f, -3.406886f, -0.0015407663f, 1.5792661f,
- 2.7942355f, 0.40592578f, -0.5638791f, 1.3874054f,
- -0.6494374f, 1.0033513f, -4.5927086f, 1.1549906f,
- 0.040286172f, 3.4282484f, 0.33645535f, -3.0670278f,
- -2.1237833f, -2.4560168f, 0.901273f, -0.940578f,
- -1.6366261f, -0.38220486f, -3.200345f, -1.4483316f,
- 5.9034204f, 1.1738936f, 3.8852453f, 1.9945848f,
- 0.19830084f, -2.034182f, 0.5209124f, 0.8063045f,
- -1.474743f, -4.2811537f, 3.576022f, -2.24559f,
- 1.0956688f, 0.6466695f, -1.810356f, -0.6289412f,
- 1.0533452f, -3.7753458f, 4.5794916f, 3.9345498f,
- 4.9681454f, 0.38930517f, -3.0756674f, 3.2549937f,
- 2.0736017f, 3.205904f, 4.7800045f, 0.16311073f,
- 6.738544f, -0.26688567f, -0.48815536f, 1.4873935f,
- -3.1892915f, 0.5883324f, 0.155257f, -3.577728f,
- -1.8864398f, -1.3671508f, -0.4395791f, 1.4579653f,
- -0.37167105f, 0.19402628f, -1.0650605f, 0.28688723f,
- -0.50026554f, -0.58012414f, 0.22083804f, -0.10480119f,
- -2.5430624f, -0.13440323f, -3.5802124f, 3.884498f,
- 2.3259788f, 2.259197f, -4.038143f, 0.011734716f,
- 0.42162162f, -1.4810863f, -0.53019875f, -2.1035078f,
- 0.49896437f, -0.97183806f, -2.7104938f, -1.6605629f,
- 0.57491654f, -2.5428684f, 0.68268263f, -1.6444156f,
- 0.122288816f, -1.3489932f, -1.0716188f, 0.037274677f,
- -2.8204086f, -0.7257868f, 7.178178f, -0.3081288f,
- -0.967814f, -0.04098258f, 4.437071f, 12.356197f,
- 1.703795f, -1.1284454f, -0.13770817f, 3.0358803f,
- 0.8831436f, 3.0425205f, 2.8286f, 0.23681363f,
- 0.9278844f, -1.3969556f, 0.84774154f, -2.444841f,
- -0.091070555f, -2.603667f, 0.3761728f, 7.606547f,
- -0.33816537f, 0.19841924f, -0.41852197f, 0.42962542f,
- -1.7426646f, 0.80124855f, 0.6179469f, 0.62130433f,
- -0.9219821f, 6.472293f, 4.558964f, -1.6759437f,
- -0.9349778f, 0.33162814f, -3.5089884f, -2.304115f,
- 2.0977242f, -0.81631994f, -3.4775565f, 0.22755583f,
- 0.55033123f, -1.2082682f, -1.3737621f, 5.7381587f,
- -1.2874542f, 7.5302024f, -0.26987734f, -1.7709676f,
- -1.3393884f, 0.41659424f, 0.91181755f, -2.4823523f,
- -4.726355f, -3.9462419f, 4.5797706f, 2.231614f,
- -0.21272695f, -0.6071537f, -3.1969872f, 0.11386541f,
- 0.43461284f, 2.4327812f, -3.2700272f, 0.11031984f,
- -1.886708f, -1.5895752f, 1.0891662f, -0.1972963f,
- -2.7681046f, 1.3309795f, -2.4369628f, -1.0575382f,
- 0.6796156f, -0.17277111f, -0.15233439f, -1.4807302f,
- 0.24751456f, -2.5830517f, 2.9050612f, -0.028462779f,
- -0.14801787f, -2.3124244f, 1.8340447f, -1.3047233f,
- -0.4266637f, -2.182621f, -1.4125471f, -3.9194782f,
- -0.021604473f, -0.21874578f, -0.5445973f, -0.080094986f,
- -0.399418f, -0.02392249f, -0.24972425f, -0.4721212f,
- -0.085990414f, 0.6785231f, -0.2840741f, -0.26309028f,
- -0.24430272f, -0.27295628f, -0.28752077f, -0.38776258f,
- 0.75253856f, -0.15038326f, -0.052184f, 0.769763f,
- 0.29379177f, -0.25637004f, 1.1434729f, 0.17955464f,
- -0.41866323f, 0.1314276f, 0.16519034f, -0.02531221f,
- 0.028396102f, 0.022699457f, -0.036944017f, -0.11141576f,
- -0.15821752f, -0.0021184522f, -0.089033104f, 0.031006882f,
- 0.40385783f, -0.17615126f, -0.5960328f, 0.27880055f,
- -0.366448f, -0.0871859f, 0.09567977f, 1.4739381f,
- 0.85210514f, -0.19013385f, 0.25014684f, 0.29895732f,
- 0.73606306f, 0.21224989f, 0.27583215f, -0.17706157f,
- -0.11267108f, 0.1535531f, 0.23554017f, -0.12448216f,
- -0.16318452f, -0.24784334f, -0.26901543f, -0.3513373f,
- -0.103869185f, 1.0244842f, -0.05652998f, -0.055757497f,
- -0.50525767f, -0.43678963f, -0.19100308f, -0.34598666f,
- -0.4765931f, 0.17689952f, -0.32168776f, 0.077399276f,
- 0.056532126f, 0.1339527f, -0.17722127f, -0.32881388f,
- 0.061036408f, 0.31383362f, -0.13945404f, 0.066857524f,
- -0.086943224f, 0.21085489f, 0.028129932f, -0.016187288f,
- 0.6317473f, 0.20802714f, -0.44119355f, 0.5939548f,
- -0.41528854f, -0.2910421f, -0.28649506f, -0.18657205f,
- -0.24638273f, 0.2869094f, -0.2565089f, 0.52948374f,
- -0.42578813f, -0.15967949f, 0.3393653f, -0.25811613f,
- -0.36954427f, -0.1699381f, -0.11172593f, -0.45919457f,
- -0.16915442f, -0.36356342f, 0.36556304f, -0.20634206f,
- 0.0013483386f, 0.6559224f, 0.5954273f, -0.043030556f,
- -0.040855613f, -0.043355256f, 0.69099647f, -0.0861944f,
- -0.04397181f, -0.09590073f, 0.46372288f, -0.05685021f,
- -0.060775682f, -0.07465221f, -0.30911782f, -0.076909535f,
- -0.058542404f, -0.073255405f, -0.07499335f, 1.3375994f,
- -0.085460156f, -0.11142948f, -0.07417113f, -0.17166245f,
- -0.06965331f, -0.080698736f, -0.04696198f, -0.30537727f,
- -0.07281143f, -0.04319762f, -0.14492385f, 0.012259152f,
- -0.06119066f, -0.18869506f, -0.118794635f, -0.04700955f,
- 0.73677856f, -0.13900182f, -0.027772538f, -0.03658812f,
- 0.44120154f, -0.03817648f, -0.32821894f, -0.024237731f,
- -0.17674342f, -0.15320285f, -0.06626018f, -0.09689588f,
- -0.0033688452f, -0.106582984f, 1.2320218f, -0.038242117f,
- -0.072363354f, -0.072158426f, -0.082239926f, -0.02381895f,
- 0.014599029f, -0.043257624f, -0.024809333f, -0.048081208f,
- -0.07489059f, 0.71166295f, 0.41147915f, -0.019741314f,
- -0.04164276f, -0.10881466f, -0.08162738f, -0.028775131f,
- -0.0022553597f, -0.016944874f, -0.026089387f, -0.041787427f,
- -0.026026888f, -0.052143093f, 0.038326025f, -0.0680127f,
- -0.068928316f, -0.06942738f, -0.17909352f, 0.026487391f,
- -0.064849004f, -0.30803254f, 0.06636305f, -0.048310824f,
- -0.090871185f, 0.3343948f, -0.14109924f, -0.07077531f,
- -0.018946331f, -0.048319288f, -0.06156078f, -0.08313412f,
- -0.06565459f, -0.00059745787f, -0.04582683f, -0.073381186f,
- 0.6949801f, -0.26241383f, 0.32847652f, -0.095710285f,
- -0.104701705f, -0.072139084f, -0.04013684f, -0.1147423f,
- -0.07495047f, -0.06857431f, -0.086990274f, -0.07002961f,
- -0.027244298f, -0.018977445f, 0.06346441f, -0.16380443f,
- 0.098154396f, 0.13397996f, 0.093210004f, -0.15188697f,
- -0.17419443f, -0.52437705f, 0.95690036f, 0.3272007f,
- -0.17880972f, 0.14872235f, 0.23977265f, 0.044290714f,
- -0.2996216f, 0.1722113f, -0.25309166f, -0.13567126f,
- 1.2431539f, -0.14075789f, -0.2910195f, -0.31969365f,
- -0.04481161f, -0.30662373f, -0.27739096f, 0.41634306f,
- -0.56653374f, -0.29258472f, 0.26386628f, -0.1905988f,
- -0.1506832f, -0.13451315f, -0.17401992f, 0.17389823f,
- -0.055538002f, 0.39749908f, 0.11512798f, -0.15357864f,
- -0.21393579f, 0.09543668f, -0.04977111f, -0.11259978f,
- 0.08914388f, -0.76914316f, -0.015345324f, 1.0750146f,
- -0.36840314f, -0.123286776f, -0.15853597f, 0.71138835f,
- -0.20089245f, -0.44904256f, -0.30639288f, -0.4575384f,
- -0.30133826f, 0.72904754f, -0.10422764f, -0.20554397f,
- 0.96745145f, -0.40602523f, -0.12360836f, 1.2919941f,
- 1.2393206f, 0.08263727f, -0.43068543f, 0.8293988f,
- 0.1552003f, 1.1948608f, 0.2582932f, 0.6150054f,
- -0.15338397f, -0.23166977f, -0.36111012f, -0.36022413f,
- -0.21158406f, -0.22998472f, -0.23097205f, -0.00063695805f,
- 0.41777387f, -0.16149028f, -0.2845907f, 1.580618f,
- -0.29985735f, -0.49509433f, 0.12458877f, -0.38226032f,
- -0.26209164f, -0.056077957f, 0.7182428f, -0.28809524f,
- -0.40339407f, -0.20477541f, 0.044111077f, -0.08072533f,
- -0.43396217f, -0.0876826f, -0.54051775f, 0.3221258f,
- -0.20357272f, 0.319258f, 0.019490348f, -0.142399f,
- -0.46692273f, -0.44483334f, -0.35169676f, -0.23840936f,
- -0.42538533f, -0.07345452f, 0.23768015f, 0.13487348f,
- -0.3496262f, -1.4163631f, 2.1090786f, -1.0601047f,
- 0.87989163f, -0.81826746f, -1.0057493f, -0.093946904f,
- 0.6694673f, 0.63598776f, -2.0222082f, -0.321465f,
- 0.32966283f, -0.61785626f, -0.21369423f, -0.15369979f,
- -0.61839265f, -0.99945056f, -0.2922375f, -0.98332095f,
- -0.98262864f, 0.935124f, 0.93269134f, -0.4607865f,
- -0.18850096f, -0.2399803f, 0.04408756f, -1.5683246f,
- 0.9324286f, -1.7013559f, -1.6967642f, -0.45271593f,
- 0.56541157f, -0.00820597f, 0.9196751f, -0.93278056f,
- 0.93905413f, -0.07815178f, 0.048115637f, 3.7262414f,
- 4.959271f, -1.72892f, 0.547625f, 0.6540449f,
- 0.8012197f, -0.678316f, -0.50359493f, 0.4762272f,
- 1.6458333f, -0.300769f, -1.0551964f, 0.05437001f,
- 1.3893167f, 0.30159402f, -1.1015186f, -1.4051142f,
- -0.8151909f, -0.43010253f, -0.939897f, -0.48863295f,
- 0.041247074f, -0.34316355f, -0.4267096f, 4.255318f,
- -1.0146745f, 0.07528014f, -1.0783662f, -0.56059384f,
- -0.8936682f, 0.8443006f, 0.9047391f, -0.74745613f,
- -0.8400601f, 1.285876f, -0.8336623f, -1.2308185f,
- 1.7965453f, -0.2087574f, 0.06923234f, 0.81520766f,
- 0.599484f, -0.94943595f, 1.555195f, 0.17118247f,
- 1.5018576f, -1.6774395f, 0.926328f, -0.3977151f,
- -0.39695293f, -0.81466746f, 0.030553397f, -0.17638284f,
- -0.36931592f, -0.66065615f, 0.85012025f, 0.54283535f,
- -0.17976667f, -1.0593966f, 0.44267696f, 0.4066066f,
- -0.17736535f, -0.42112502f, -0.0726795f, -0.99410427f,
- 2.7895443f, 0.45812353f, -0.024932958f, -1.573182f,
- 0.34525457f, 1.2986095f, -0.23432322f, -0.3226443f,
- -0.23734103f, 0.8379689f, -0.33693078f, -0.20473304f,
- 1.4488261f, 0.104681574f, -0.07161999f, -0.1613122f,
- -0.453959f, -0.2141037f, -0.053636808f, -0.33769906f,
- -0.23026857f, -0.3752652f, 1.1139752f, -0.21080194f,
- -0.07023501f, -0.40930623f, 0.26689154f, -0.1422906f,
- -0.11136127f, -0.21603152f, -0.38796672f, 0.18313578f,
- -0.11299865f, -0.14909612f, 0.04607653f, 0.034207445f,
- -0.22004928f, 1.6327896f, -0.13438256f, 0.61254674f,
- -0.06726384f, 0.018001188f, -0.17025548f, 0.94602746f,
- 0.010040466f, -0.26268902f, -0.087147646f, -0.16452388f,
- -0.18006596f, -0.27015963f, -0.47702226f, 0.0828887f,
- -0.1267261f, 0.565344f, -0.21524581f, -0.3210431f,
- 0.10992644f, 0.037535578f, -0.30666986f, 0.14874998f,
- 0.045704547f, -0.01299553f, -0.19652563f, -0.27444628f,
- 1.3492163f, -0.09736664f, 0.082850546f, -0.07190945f,
- -0.16931564f, -0.1448025f, -0.10723879f, -0.11337835f,
- -0.020834f, 1.2494979f, -0.008183859f, -0.25203055f,
- -0.2553563f, -0.23875096f, 0.18407705f, -0.5477307f,
- -0.06166429f, -0.23856182f, 1.5334507f, -0.070313744f,
- -0.38667405f, -0.2023646f, 0.26243478f, -0.20790009f,
- 0.9354315f, -0.4022652f, -0.2863819f, -0.035849378f,
- -0.25953665f, -0.14714935f, 1.1140316f, -0.32195538f,
- -0.24743539f, -0.25662875f, 0.047025893f, -0.49023545f,
- -0.17139858f, -0.16458258f, -0.5577741f, 0.25742745f,
- 0.42723936f, -0.36024547f, -0.36859244f, -0.24261265f,
- -0.42162463f, 0.41941366f, -0.12314933f, -0.053309545f,
- -0.14429626f, 0.7992471f, -0.12091434f, -0.10655437f,
- -0.1377751f, -0.07431122f, 0.1498292f, -0.12206556f,
- -0.22405066f, -0.19175658f, 0.005621554f, -0.07315084f,
- -0.09818621f, -0.09205117f, 1.0709935f, -0.05786682f,
- -0.045445565f, -0.089465395f, -0.084345125f, 0.34180662f,
- -0.11767075f, -0.15166672f, -0.104586646f, 0.9616489f,
- -0.16767354f, -0.13914394f, -0.2076902f, 1.1865098f,
- -0.3562195f, -0.062776774f, -0.14982904f, -0.07624143f,
- -0.08934266f, -0.16463436f, -0.1746892f, -0.14732707f,
- 0.5848878f, -0.24476591f, -0.06721479f, -0.17480643f,
- 0.4239139f, -0.12058381f, -0.11714428f, -0.11160952f,
- -0.24330293f, 0.018205814f, -0.05927082f, -0.19630623f,
- -0.063635625f, -0.21734393f, 0.8644332f, -0.060927253f,
- -0.122341655f, -0.09738659f, -0.14869206f, -0.06326119f,
- -0.006409125f, -0.004031961f, -0.096534714f, -0.068707675f,
- -0.11520502f, -0.1803806f, 1.1239697f, -0.07726639f,
- -0.05882626f, -0.15065436f, -0.0909295f, -0.08762611f,
- -0.087679915f, -0.08848537f, -0.068917476f, -0.04835329f,
- -0.06605867f, -0.0829682f, 0.018007524f, -0.12992078f,
- -0.07821812f, -0.08361824f, -0.27552268f, -0.16343103f,
- -0.008475716f, 1.0485393f, 0.6088237f, -0.087580115f,
- -0.052297413f, 0.3913713f, -0.14166336f, -0.026734518f,
- 0.4276865f, -0.089126244f, -0.065909415f, -0.23573169f,
- -0.09994381f, -0.017818496f, -0.0732983f, -0.053056657f,
- 0.63465637f, -0.19448687f, -0.092440724f, -0.13219067f,
- -0.072045006f, -0.0086378865f, -0.12187769f, -0.10748507f,
- -0.14040041f, -0.09100955f, -0.14713201f, -0.19572218f,
- -0.057189338f, -0.10828741f, 0.5992207f, -0.3014566f,
- -0.37196195f, -0.46802777f, -0.74665266f, 0.88256264f,
- -0.30485776f, 0.34106046f, 1.2330216f, 0.4149317f,
- -0.017046237f, -0.15210728f, -0.49216056f, -0.06008579f,
- -0.24185337f, -0.4021089f, 0.15116148f, 1.0208654f,
- 0.9524529f, -0.23149718f, -0.2836259f, -0.2940894f,
- 0.36748427f, -0.06619639f, -0.24664938f, -0.47964516f,
- -0.3184792f, 0.21491088f, -0.14817631f, -0.21117248f,
- 0.36198023f, 0.23542562f, 0.086537f, 1.3007596f,
- 0.29467008f, 0.11971072f, 0.51229846f, 0.06691215f,
- -0.25013858f, 0.50997996f, -0.17801264f, 0.36199176f,
- 0.3364647f, 0.21780315f, -0.20758857f, -0.2665953f,
- -0.37273487f, -0.35300103f, -0.09980935f, 0.50883406f,
- -0.10576248f, -0.50924385f, 0.025370909f, 0.059301548f,
- -0.518361f, 0.286068f, -0.27919936f, -0.2926577f,
- -0.03523629f, -0.048985858f, 1.1525463f, -0.053280212f,
- 0.08426257f, -0.4681139f, -0.48221758f, -0.31242675f,
- 0.12235712f, -0.06714449f, -0.1888631f, 1.3384446f,
- -0.2736398f, -0.42460704f, -0.05230771f, -0.3551564f,
- -0.036852792f, -0.2488434f, -0.40960613f, -0.10280948f,
- 0.8573936f, 0.18347634f, -0.30381718f, -0.23996325f,
- -0.13794987f, -0.15939985f, 0.6874648f, -0.30233064f,
- -0.37214094f, -0.010740588f, -0.2471081f, -0.086446315f,
- 0.93504065f, -0.4468216f, 0.6849216f, -0.42876047f,
- 0.04570991f, -0.4698483f, -0.160407f, -0.07750239f,
- -0.18194287f, -0.1297124f, 0.36373878f, -0.24797405f,
- -0.6020235f, 0.32051507f, -0.49431667f, -0.40697387f,
- -0.16121222f, -0.07821748f, 0.11935984f, 1.0427276f,
- -0.5235174f, -0.024079535f, -0.25093082f, 0.009732045f,
- 0.03619203f, -0.19068156f, -0.5395434f, -0.1681003f,
- 0.3086054f, 0.010197822f, -0.19316912f, -0.100101985f,
- 0.39090133f, -0.78674746f, -1.2288977f, 0.44164088f,
- -0.49684575f, 0.2015345f, -0.32611448f, -0.11352833f,
- -0.32294694f, 0.3820172f, -0.6439946f, -0.40717143f,
- -0.31545046f, 0.88618165f, -0.04997423f, 1.9144874f,
- -0.13525833f, 0.075452685f, 0.107292466f, -0.23098063f,
- -0.010409044f, -0.08988294f, 0.38426363f, -0.27158734f,
- 0.8324293f, -0.017331103f, 0.35478234f, -0.37975922f,
- -0.51174885f, -0.035101686f, 0.28563586f, 0.22978106f,
- 0.26267412f, -0.15397605f, -0.06391036f, -0.14409362f,
- 1.2248772f, -0.6432569f, 0.92564857f, -0.35690898f,
- -0.8616214f, 0.30989486f, 0.6635455f, -0.9524541f,
- 0.19268464f, -0.42881483f, -0.83281976f, -0.13524516f,
- 0.8020838f, 0.1269911f, -0.20142554f, -0.41543543f,
- 0.031825703f, -0.25853583f, -0.3533632f, 0.36253294f,
- 0.42302144f, 0.20300195f, -0.5299035f, 0.76761246f,
- 1.6167742f, -0.789332f, -0.83892006f, -0.41180214f,
- -0.5724753f, 0.12210439f, 0.32860038f, 0.45697537f,
- 0.7678344f, 0.37304366f, -0.46929714f, 0.0656309f,
- -0.39290962f, -0.84019345f, 0.51806146f, -0.1289343f,
- 0.084747024f, -0.20135167f, -0.055603012f, -0.7209466f,
- -0.20356007f, -0.87462074f, 0.2982724f, -0.41739586f,
- 0.23715672f, 1.4021106f, 0.6902209f, -0.4505435f,
- -0.110736296f, -0.11626132f, -0.35480046f, 0.4694372f,
- -0.796762f, 1.5864918f, 0.7747323f, -0.0315684f,
- -0.15344979f, 0.16401765f, -0.10873585f, -0.1036058f,
- -0.080569446f, 0.8279817f, -0.036646344f, -0.15174277f,
- 0.042866774f, 0.7661282f, -0.042268362f, -0.078590654f,
- -0.0531081f, -0.22457376f, -0.0452906f, -0.027749263f,
- -0.0434221f, -0.08548918f, 0.91222936f, -0.09499076f,
- -0.09701237f, -0.06154282f, -0.26103088f, 0.044343784f,
- -0.044611588f, -0.1132723f, -0.26598632f, -0.35603955f,
- -0.08881648f, -0.059066482f, -0.10014606f, -0.13243273f,
- 0.317566f, 0.36575422f, -0.05870719f, 0.35622326f,
- -0.21586874f, -0.10182897f, -0.080440275f, -0.2360619f,
- -0.054861072f, -0.1904108f, -0.04335062f, -0.21349293f,
- -0.30332047f, -0.098769695f, -0.25126013f, 0.008817065f,
- -0.28783715f, 0.9053309f, -0.029124094f, -0.17651589f,
- -0.12714618f, -0.07312992f, -0.08112163f, -0.036334127f,
- -0.03322529f, -0.067229755f, -0.051948212f, -0.09723294f,
- 0.40758166f, 0.28813547f, -0.076245405f, -0.016349306f,
- -0.10304382f, -0.11355779f, -0.094903246f, -0.13087608f,
- -0.05184694f, 0.13613574f, -0.036705498f, -0.02728073f,
- -0.063594624f, -0.08160189f, -0.06939752f, -0.09193871f,
- -0.030884804f, -0.055295445f, -0.26133698f, -0.04992433f,
- -0.23441511f, 0.5311594f, -0.07644633f, -0.097639926f,
- -0.045968566f, -0.033497002f, -0.03192958f, -0.18582818f,
- -0.09367896f, -0.053400468f, 0.43033254f, -0.113506354f,
- -0.0043429257f, -0.059262555f, -0.0576214f, 1.1180391f,
- -0.14785902f, 1.0766019f, -0.29717588f, -0.03683365f,
- -0.062560394f, 0.86480165f, -0.08277735f, -0.09927048f,
- -0.05956859f, -0.17850037f, -0.10280509f, -0.059278034f,
- -0.082146145f, 0.084875844f, -0.15937914f, -0.059800792f,
- -0.09177154f, -0.082309075f, 0.32806838f, -0.09507484f,
- -0.08449841f, -0.009536183f, 0.012745848f, -0.08303054f,
- -0.06968296f, -0.07903274f, 0.4340802f, -0.0599457f,
- -0.0668841f, -0.07061916f, -0.04168026f, 0.018207926f,
- -0.11530055f, -0.09764417f, -0.10717339f, 0.28742057f,
- -0.082518406f, -0.11359775f, -0.09635683f, 0.53395766f,
- 0.01955221f, -0.055599324f, -0.040749483f, -0.010435031f,
- -0.045928393f, 0.025122857f, -0.02369869f, -0.0706488f,
- 0.33239415f, -0.109380804f, -0.037935987f, -0.090020284f,
- 0.945929f, -0.05849789f, -0.2002414f, -0.0636184f,
- -0.21749954f, -0.05267842f, -0.053313617f, -0.058381185f,
- -0.055296123f, 0.110214755f, 0.021074608f, -0.050749604f,
- -0.13374032f, -0.045997076f, -0.09294681f, -0.029001005f,
- -0.05196487f, -0.021968914f, -0.06622613f, -0.08034149f,
- -0.061808217f, 0.7418964f, 0.039002568f, -0.021638718f,
- -0.05703948f, -0.115225025f, -0.09472714f, -0.028385183f,
- -0.028626865f, -0.05509256f, 0.027896237f, -0.10585836f,
- -0.05352996f, -0.06823693f, -0.09035105f, -0.05681995f,
- -0.02287815f, -0.071338855f, -0.16888024f, -0.011591807f,
- -0.042992517f, 0.2818652f, -0.044841617f, -0.02081284f,
- -0.10087115f, 0.9268934f, -0.15223986f, -0.085207015f,
- -0.090712786f, -0.10064631f, -0.06946227f, 0.015392107f,
- -0.06680117f, -0.09589479f, -0.009233919f, -0.04523364f,
- 0.43634182f, -0.15885802f, 0.02889221f, -0.07610303f,
- -0.0482863f, 0.0784286f, 0.09344511f, -0.06269076f,
- -0.06605838f, -0.065772414f, -0.06723921f, -0.0100588165f,
- -0.045806125f, -0.08183508f, 0.39480808f, -0.07869994f,
- -1.1326522f, -1.92271f, -1.8024542f, -0.31231052f,
- 0.17289022f, -1.2156676f, -0.96961933f, -0.29576904f,
- -2.7108932f, -3.2664897f, -2.3284986f, 1.5483862f,
- -1.3943373f, 6.931444f, -1.1560041f, -0.08874233f,
- 0.8209577f, -0.8122962f, 1.5697749f, 1.2443657f,
- 0.45456377f, -0.69560957f, -3.9789448f, 2.7349322f,
- -0.83211f, -0.26521277f, 2.9534667f, -0.2835687f,
- 5.2664614f, 5.5390725f, 0.09664031f, -0.6134988f,
- -2.3272367f, 0.1818881f, -1.3130448f, -1.2984147f,
- -1.7431798f, 1.1070229f, -0.3654684f, -0.7758429f,
- -1.0624274f, -0.5708364f, -0.25875086f, 2.0180275f,
- -2.0100815f, -1.756065f, 0.12656662f, 0.46135908f,
- -1.3836097f, -2.6253777f, 0.043934405f, -1.3589953f,
- -1.2777644f, -2.3875663f, -1.4222138f, 2.2712739f,
- 1.0293254f, -0.6412017f, 0.4061253f, 0.50554526f,
- -0.44288573f, 0.16181485f, -2.141078f, -1.0163494f,
- -0.9750269f, 2.8272195f, 5.0521717f, 1.204332f,
- 2.6761365f, -3.0788834f, 3.0376716f, -1.4323355f,
- -0.9471735f, 2.5680904f, 3.6516223f, -0.12471782f,
- 0.95176613f, 0.43099174f, -0.9280608f, -0.17760077f,
- 0.36666948f, -1.689902f, -0.3950663f, -1.6516852f,
- 4.0772653f, 0.30785787f, 2.169132f, -1.9250263f,
- 0.17029326f, -0.5810375f, -4.037572f, 4.0786285f,
- 3.1603305f, -0.08061267f, -1.2112786f, -0.10018094f,
- 3.2529263f, -0.42034623f, -2.8122659f, -0.005545627f,
- -1.4450713f, -1.6017598f, 1.1488465f, -1.7681971f,
- -0.93034357f, 3.6096225f, -0.5120243f, -0.057421397f,
- 0.761712f, -0.19513537f, -0.17139535f, -0.23840521f,
- 0.14121602f, -0.17499934f, -0.43336675f, -0.17146918f,
- -0.09318297f, 0.040055476f, -0.29925472f, -0.23632099f,
- 1.498797f, -0.26691633f, -0.109305896f, -0.08270584f,
- -0.215347f, -0.08804351f, -0.35849553f, -0.15202387f,
- -0.24172285f, 0.90383846f, -0.20498383f, -0.29070413f,
- -0.27814066f, 1.6989839f, 0.0732146f, -0.14400315f,
- 0.11601759f, -0.1826766f, -0.2511705f, -0.14447701f,
- -0.19002342f, -0.3018704f, 0.4985808f, -0.26109335f,
- -0.10652302f, 0.18352129f, 0.11172793f, 0.4342268f,
- 1.0637351f, -0.4040867f, -0.2419523f, -0.11116487f,
- -0.1933341f, 0.02688354f, -0.13567436f, 0.08875418f,
- 0.6782351f, -0.24844933f, -0.014514352f, -0.02153232f,
- -0.17715721f, -0.05435819f, -0.0019951537f, -0.18420163f,
- -0.07375348f, -0.21525289f, -0.10208302f, -0.25381324f,
- 0.41405654f, -0.21931309f, -0.11570851f, 0.09167857f,
- -0.19043377f, -0.36102542f, -0.20647883f, -0.0834061f,
- -0.089167f, 0.13486883f, 0.009214479f, -0.054857884f,
- -0.21725932f, -0.06339946f, -0.27532715f, -0.16594023f,
- 0.29381916f, -0.20200467f, -0.10423895f, 1.4783708f,
- 0.6498721f, -0.16968943f, 0.08168405f, 0.07944013f,
- 0.18073247f, -0.07817148f, 0.9807704f, -0.21374887f,
- -0.15486321f, -0.24512543f, 0.028625542f, -0.192715f,
- -0.14237987f, -0.10080641f, 0.25691855f, 0.41121715f,
- 0.025481546f, -0.21043488f, -0.06353534f, -0.06409209f,
- 0.19213697f, -0.14720853f, -0.34763354f, -0.27664006f,
- 0.33483857f, -0.014282831f, -0.15903743f, 0.04411944f,
- 0.44842374f, -0.43741733f, 0.16575342f, -0.41932365f,
- 2.9586134f, -0.23865263f, 1.3018605f, -0.867943f,
- 0.46999463f, 0.3188575f, -0.3116299f, 0.6853578f,
- -0.02860385f, 0.16674817f, -2.317509f, -1.5751435f,
- 0.09935584f, -0.9743408f, 0.43221962f, 1.2829081f,
- -0.165302f, 0.2007603f, 0.35850155f, -0.42892396f,
- -2.3981133f, 1.5496103f, 1.3231186f, 0.3294053f,
- 3.4479222f, 0.10383228f, -0.48469332f, -0.19594112f,
- 0.25758466f, 0.03224479f, 1.2300776f, -0.20902883f,
- 0.84263754f, 3.443299f, -0.5071586f, -0.08566997f,
- -1.0368904f, -0.79072464f, 3.0770605f, 1.0845158f,
- 0.4203608f, -0.37539622f, -0.3435165f, -0.10189978f,
- 0.020602822f, -0.1949287f, 2.0554686f, -0.113777645f,
- -1.7495492f, -0.6259046f, -1.1197841f, 0.78266686f,
- -0.6983109f, -0.57198405f, 0.9311513f, -0.541812f,
- -0.13735686f, 0.43444443f, 0.03794291f, -1.4870057f,
- -1.9552104f, 2.3473167f, 0.27683142f, 1.071447f,
- -0.7408096f, 0.39245358f, 0.52969265f, -0.17388238f,
- -0.4609671f, -1.7234824f, -1.321333f, -0.48867926f,
- 0.89663196f, 1.2376497f, -0.32886058f, 0.15988548f,
- -0.9021836f, 0.29779974f, 1.0245061f, -1.1200298f,
- -0.19698389f, 0.38277778f, -2.6267688f, 0.48388746f,
- -0.78307635f, -0.7103735f, 0.2144078f, 0.025013251f,
- 1.4868823f, 0.5713356f, -1.7901824f, -0.018173931f,
- -1.2423793f, 0.63449526f, 0.3540982f, 0.045088716f,
- -0.874824f, -0.12391579f, -1.8264902f, 0.116435066f,
- 0.7882354f, -1.8179978f, -1.2865481f, 0.2479189f,
- -0.7021129f, -0.2582422f, 1.1402391f, -0.08778791f,
- -0.22024935f, -0.04131864f, -0.018024303f, -0.05161924f,
- -0.103413396f, -0.19421555f, 1.0130792f, -0.028521206f,
- -0.11042733f, -0.12956169f, 0.49750948f, -0.1012928f,
- -0.14139709f, -0.15235783f, -0.20530386f, -0.05947958f,
- -0.037330195f, -0.12741415f, -0.13265459f, 0.66760296f,
- -0.17255488f, -0.10345657f, -0.19209823f, 0.51553833f,
- 0.6640762f, -0.07001908f, 0.31629562f, -0.010990693f,
- -0.019421699f, -0.1729626f, -0.24572353f, -0.19266187f,
- -0.2629248f, -0.21725965f, 0.024483519f, -0.013650228f,
- -0.15478122f, -0.23296005f, -0.17856716f, -0.09130613f,
- -0.41498265f, 1.1314006f, -0.03010942f, -0.17255512f,
- -0.08416659f, 0.7299083f, 0.21118408f, -0.10488189f,
- -0.018910222f, -0.09963583f, -0.13831028f, -0.09206149f,
- 0.21270016f, -0.048035633f, -0.06182452f, -0.08524242f,
- -0.13993247f, -0.082584694f, 0.541634f, 0.06736175f,
- -0.06646017f, -0.21383496f, -0.0146539295f, -0.13064805f,
- -0.05107058f, -0.038083404f, -0.06917374f, -0.004713674f,
- -0.1599584f, -0.048119403f, -0.03808956f, -0.088658445f,
- -0.15652151f, -0.11453644f, -0.3654242f, -0.079561755f,
- -0.092842415f, 0.44112912f, 0.6332853f, 0.0016175469f,
- -0.067502744f, -0.089069024f, -0.090124756f, -0.08081974f,
- 1.600004f, -0.01609524f, -0.0564043f, -0.21683833f,
- -0.037718967f, -0.052270852f, -0.07480935f, -0.052255668f,
- -0.051465802f, -0.13248068f, -0.13430703f, -0.16481401f,
- 0.024308866f, 0.0990428f, -0.19927302f, -0.00016093631f,
- -0.18076722f, -0.0990595f, -0.20367602f, 0.020736815f,
- 0.04299969f, -0.020918472f, 0.3858811f, -0.23562846f,
- 0.93877983f, -1.6898617f, -2.1202464f, -0.09513914f,
- 0.31243795f, -1.0650842f, 0.74318403f, -0.25383857f,
- -1.1675135f, 7.300824f, 1.0616609f, 0.058234952f,
- -2.54347f, -0.18986428f, 1.1274393f, 4.685074f,
- 0.50034595f, -1.418629f, 1.5416602f, 1.0516078f,
- 0.7336826f, 1.0045049f, -0.38905635f, -1.5097184f,
- 0.40477982f, 0.09459551f, 1.256005f, -0.28644568f,
- 0.46566322f, 0.19961897f, 0.3197087f, -0.6657925f,
- 3.8278527f, 0.35972896f, 1.1050547f, -0.28973272f,
- -1.3285891f, 1.2307599f, -1.4737246f, 1.9728298f,
- 4.1128306f, 0.65008986f, 0.08982111f, -2.0696495f,
- 1.2475315f, -2.7543423f, 0.55621886f, -0.41845766f,
- 0.37313443f, -0.32622543f, -2.5820067f, 0.021937082f,
- -1.2087622f, 1.6202984f, -1.3026087f, -1.5341401f,
- -0.44062886f, -2.1065094f, -0.037094787f, 0.6114546f,
- -1.5140557f, -2.8404968f, -2.1646543f, 2.0230033f,
- 3.3797047f, 0.05467345f, -0.9658402f, 1.1832929f,
- -1.6903812f, -1.4993231f, 0.3692876f, -2.8041844f,
- -0.12512992f, -1.4269731f, 1.8363916f, 2.263533f,
- -1.3687755f, -1.9299107f, -0.20674872f, 0.24643916f,
- 4.8004355f, -0.9700158f, -0.45131883f, -1.242062f,
- 0.0425447f, 0.7819957f, 0.09632986f, -1.48075f,
- 0.52672476f, -3.1744156f, -1.1854855f, -1.7386541f,
- 1.6188182f, 0.54169476f, 2.7533092f, 0.14497522f,
- -0.06392406f, -2.9349203f, -1.049658f, -0.0634909f,
- 0.65975684f, -0.98365533f, 1.9927137f, -1.1720389f,
- -0.081166916f, -0.46135992f, 1.0082024f, 0.18070975f,
- -1.2238231f, -0.26825908f, -0.4103043f, -0.33882308f,
- -0.34985176f, -0.29669967f, -0.22279394f, -0.28123924f,
- 0.6671638f, -0.11514206f, -0.27975145f, -0.4150369f,
- -0.2540752f, 0.13301997f, -0.3194665f, -0.35967824f,
- -0.41183138f, 0.9157113f, -0.105489746f, 0.21173753f,
- -0.43932697f, 1.1439438f, 0.7745788f, -0.15194161f,
- -0.3121807f, -0.45969746f, -0.13370675f, -0.34293264f,
- -0.20683599f, -0.06646297f, -0.10224704f, -0.1022459f,
- 0.058967706f, -0.18284437f, 0.10941016f, 1.0455753f,
- -0.020613164f, -0.25940505f, 0.18878044f, -0.35805333f,
- -0.3097461f, -0.113988355f, 0.827879f, 0.8650434f,
- 0.8643596f, -0.35241684f, -0.07311047f, -0.13821322f,
- 0.68773776f, -0.24139008f, -0.28388044f, -0.22884221f,
- -0.23334932f, -0.015387671f, 0.4838098f, -0.15342402f,
- -0.09032152f, -0.23518074f, -0.14732164f, -0.111274324f,
- 1.2610352f, 1.1540552f, -0.10493925f, -0.41553462f,
- 1.2091055f, -0.09651995f, 0.8470594f, -0.31660372f,
- 0.019507615f, -0.0783029f, -0.24000175f, -0.2118718f,
- -0.21544969f, -0.39112946f, -0.17120777f, 0.16673066f,
- -0.5141272f, -0.4299567f, -0.093242206f, -0.39996815f,
- 0.9046487f, -0.38017142f, -0.2726966f, 0.59585214f,
- -0.3307999f, -0.34827638f, 0.91831696f, 0.5085791f,
- 0.23297445f, -0.3900022f, -0.28783593f, -0.13488363f,
- -0.22864364f, -0.1367288f, 0.66957706f, -0.15389936f,
- -0.22802603f, 0.54003537f, -0.06979376f, 0.39024544f,
- -0.16524798f, -0.063739106f, -0.059955038f, -0.3399116f,
- -0.29514486f, -0.18733886f, -0.14622036f, -0.35339504f,
- 0.30339843f, -0.14703073f, -0.17664053f, -0.19383244f,
- -0.109832935f, -0.090426825f, -0.565548f, -0.42885435f,
- -0.15886661f, 0.57897264f, -0.7537268f, -0.19474971f,
- -0.7665776f, -0.31856066f, -0.7666842f, -0.4466032f,
- -1.0439634f, -0.15060535f, -0.60091066f, 0.03303638f,
- 2.1505315f, 0.422693f, 1.6756526f, 1.7247988f,
- -0.48333415f, 1.4884597f, -0.35117838f, -0.053957157f,
- -0.69615257f, 0.1412726f, -0.2739019f, -0.22469373f,
- 0.6595408f, -0.4156334f, 1.4350772f, 0.19091578f,
- 1.060779f, -0.5558242f, -1.1285672f, 1.424887f,
- -0.8050098f, -0.012943955f, -0.65940845f, 2.118391f,
- 1.6131907f, -0.9686684f, 0.6072122f, -0.52189845f,
- 2.260655f, -0.3908547f, -0.47017968f, -0.98729265f,
- -0.119957f, -0.26468754f, 0.82379645f, -0.39526778f,
- 0.58856875f, -0.48428845f, -0.9901037f, -0.47774553f,
- -0.16149247f, 1.3084915f, -0.32047263f, -0.4643128f,
- -0.22465822f, -0.112344414f, 0.12672482f, 0.27311662f,
- -0.29577222f, -0.7225504f, -1.1551617f, -0.66849095f,
- -0.09258383f, 0.7436432f, 0.49868482f, -0.18708487f,
- -0.67700255f, 0.7126372f, 0.08127915f, -0.6624651f,
- 0.24215385f, -0.48299658f, 0.14468813f, -0.5903056f,
- 0.6505168f, -0.6021134f, -0.5438075f, 0.29151735f,
- 0.4113837f, -0.81388617f, -0.08522866f, -0.09702132f,
- -0.3502639f, -0.10999098f, -0.079070464f, 1.377031f,
- 0.7112482f, -0.6325512f, 0.8358935f, -0.5580531f,
- -0.564934f, -0.6945037f, -0.49531394f, -1.1191815f,
- -0.89742273f, 0.29002434f, -0.45646602f, -0.2597457f,
- 0.9540984f, 1.1956733f, 1.830646f, -0.32866517f,
- -0.037243586f, -0.52484095f, 0.06474544f, -0.3031927f,
- 0.41346532f, -0.19656233f, 0.012301649f, 0.017278144f,
- -0.5867554f, -0.40538305f, 0.59334445f, -0.6430021f,
- -0.52424115f, 0.8075793f, -0.2956663f, -0.44438186f,
- -0.013013787f, -0.30888706f, -0.44005996f, 0.5043425f,
- -0.29905573f, -0.2562749f, 0.8052296f, 0.72647166f,
- 0.08365841f, -0.487133f, 0.47816232f, -0.086018115f,
- -0.057505496f, -0.16547707f, -0.24954635f, -0.28985578f,
- 2.432281f, -0.13636647f, -0.21580343f, 0.6087598f,
- -0.12288782f, 0.34719962f, 0.9241715f, -0.5370938f,
- -0.0469575f, -0.009528804f, -0.2013813f, 0.43018764f,
- -0.36488444f, 0.23076685f, 0.45694432f, -0.21119295f,
- -0.08191996f, 0.04489875f, 0.05832469f, 0.049515225f,
- -0.41197345f, -0.57195455f, -0.39562592f, -0.53285736f,
- -0.08476418f, -0.3927633f, 0.63206077f, -0.14457744f,
- -0.53759044f, 0.568121f, -0.49293515f, -0.5062061f,
- -0.16328885f, -0.49642217f, -0.20045573f, 0.18855172f,
- -0.047709852f, 0.28228867f, -0.1399053f, 0.037158366f,
- -0.6247128f, -0.48717964f, 0.66465163f, -0.27335563f,
- -0.1819916f, 0.8369322f, 0.46849564f, -0.34340674f,
- -0.18619147f, -0.21223937f, 0.770242f, -0.35824996f,
- 0.5848968f, -0.32313353f, 0.048985004f, -0.28175363f,
- 0.1561818f, -0.30412862f, -0.37446535f, -0.20143946f,
- 0.38863748f, 0.6071733f, 0.116461605f, -0.17816712f,
- -0.50537777f, -0.41225126f, 0.26110786f, -0.2575009f,
- 0.58829945f, -0.49209455f, 0.47206402f, 0.71355766f,
- -0.30187455f, 0.8340184f, 0.15004337f, 0.8441394f,
- -0.5388964f, -0.65271527f, -0.90491587f, -0.19543234f,
- -0.45223835f, -0.62748885f, 0.6630471f, -0.16208999f,
- -0.32800114f, -0.22945872f, 0.4099674f, 0.11956817f,
- 0.19552554f, -0.45986825f, -0.6778313f, 0.63053507f,
- 0.9486214f, -0.5505163f, 1.0168884f, -0.84848404f,
- -0.096487f, 1.626748f, -0.4501776f, -1.1556908f,
- -0.16344094f, 0.08930772f, -0.5232577f, -0.2537583f,
- 0.14321262f, 0.050429814f, 0.44903272f, 0.9177606f,
- -0.5046937f, 0.16131811f, 1.9341797f, 0.42702636f,
- -0.5344596f, 0.41132492f, -0.12965272f, -0.02324302f,
- -0.65569085f, 1.5200096f, 0.16888751f, 2.230085f,
- -0.5227585f, -0.42806312f, -0.24649335f, 0.31733087f,
- -0.9008309f, -0.6184494f, -0.5984355f, -0.84687984f,
- -0.24055105f, -0.46897137f, -0.3339603f, -0.321772f,
- -0.13376804f, -0.07351151f, 0.10665898f, 0.1993621f,
- 2.2813852f, -0.18833718f, -0.15582836f, 2.0212228f,
- 0.14101078f, 1.668164f, -0.48339954f, 0.7736288f,
- -0.08926953f, -0.40497687f, -0.58802587f, -0.26457494f,
- -0.4919645f, -0.6114556f, -0.4902151f, -0.9853185f,
- 0.5156768f, 0.4828003f, -0.15029693f, 0.22822396f,
- -0.42796913f, -0.7951039f, 0.5086343f, -0.53630793f,
- -0.3167668f, -0.27167553f, 1.7812233f, 0.4675815f,
- -0.000807627f, -0.3293155f, -0.38383892f, -0.5291207f,
- -0.29876158f, 0.0046018227f, -0.3197427f, -0.1360236f,
- 1.7887568f, 0.1302344f, 0.99634326f, -0.110868f,
- -0.40209338f, -0.1289955f, -0.24477823f, -0.28985533f,
- -0.54254264f, -0.00959388f, -0.22372265f, -0.15414439f,
- -0.31456053f, -0.22473413f, -0.32324594f, -0.17152773f,
- -0.010694106f, -0.15264979f, -0.36849955f, -0.22951159f,
- 0.68939424f, -0.014006473f, -0.33094162f, -0.22052096f,
- 1.730836f, -0.19362153f, -0.36438653f, -0.26282284f,
- -0.13225086f, -0.038500857f, -0.14350247f, -0.08662109f,
- -0.032953557f, -0.11714467f, -0.24647804f, -0.14894883f,
- 0.13876314f, 1.7776184f, 1.6311812f, -0.04620414f,
- 1.3445445f, -0.07687119f, -0.10860529f, -0.0738506f,
- -0.40616235f, -0.018061947f, -0.38844907f, -0.09259112f,
- -0.17684457f, -0.35456824f, -0.25574872f, -0.24891816f,
- 0.65932274f, -0.17091118f, -0.19259562f, 0.42699754f,
- -0.20797896f, -0.28306037f, -0.17001386f, 0.25338304f,
- 0.55737776f, -0.17874904f, -0.109964885f, -0.27832824f,
- -0.009114884f, -0.053927217f, 0.0094650965f, -0.1342862f,
- 0.031220276f, -0.047082655f, 0.005208158f, -0.100168236f,
- -0.036391985f, -0.28742838f, -0.0841545f, -0.40818918f,
- -0.2826112f, -0.29153448f, -0.15591094f, -0.3406946f,
- -0.1906612f, -0.105188884f, -0.10396257f, -0.27631554f,
- -0.06475261f, -0.14125912f, -0.26633513f, -0.3779327f,
- -0.3551989f, -0.25325844f, -0.086132385f, 1.661512f,
- 1.3137137f, -0.101864345f, -0.14601256f, -0.16887006f,
- -0.29649442f, -0.070064455f, 1.8108699f, 0.06322216f,
- -0.12909648f, -0.30711383f, -0.29654846f, -0.17009047f,
- -0.1701908f, -0.054557744f, -0.15158732f, 0.026437696f,
- 1.1125377f, -0.22083059f, -0.19369397f, 0.00921229f,
- 0.08505037f, -0.012710225f, -0.31741616f, 0.037438508f,
- -0.14698128f, -0.18838048f, -0.1218511f, 0.6265398f,
- -0.21363966f, -0.41152054f, -0.13732928f, -0.32651034f,
- -0.13809071f, -0.12125335f, 0.017778698f, -0.2740679f,
- 0.70817614f, 0.7348887f, -0.16027986f, 0.20772205f,
- -0.39843926f, -0.27925837f, -0.51471037f, -0.4535445f,
- -0.26786646f, -0.14472945f, -0.070457034f, -0.46715057f,
- 0.97995675f, -0.1436241f, -0.0913406f, 0.91935086f,
- -0.5717511f, -0.28604427f, -0.16812265f, 1.8050696f,
- -0.3989845f, 0.79318863f, -0.30027655f, -0.31104657f,
- 0.41366202f, 0.5475838f, 0.56002337f, -0.20709644f,
- 0.67614895f, -0.4424152f, -0.7435126f, -0.26183423f,
- -0.15122603f, 0.085869044f, -0.49301288f, 1.002503f,
- 1.0100877f, -0.45700628f, -0.014468892f, -0.20875207f,
- 0.48908255f, -0.30845f, -0.28963488f, 0.5157761f,
- 0.11921009f, -0.0015334955f, -0.09025386f, -0.07394696f,
- 0.18219194f, 0.050843574f, -0.19991301f, -0.24248876f,
- -0.078186385f, -0.1778625f, -0.06409071f, -0.20094736f,
- -0.19777627f, 0.5576951f, -0.121631764f, -0.015074864f,
- -0.048308235f, 0.55814743f, -0.21419913f, -0.4336517f,
- -0.16820565f, -0.14809492f, 0.1258602f, -0.38670546f,
- -0.21736494f, 0.7463599f, 0.47517756f, -0.25477946f,
- -0.17214563f, 0.7686194f, 0.015779128f, -0.5725435f,
- -0.275724f, 0.04691544f, -0.25079614f, 0.6301613f,
- -0.09543101f, -0.22273959f, 1.2870951f, -0.62280077f,
- -0.20458572f, -0.19131567f, -0.124244f, -0.26621556f,
- 0.84862715f, 0.7304462f, 0.4058797f, -0.29707813f,
- -0.53202486f, -0.4394363f, 0.20019011f, -0.41952488f,
- -0.35128796f, 0.37307283f, -0.14819236f, -0.46229452f,
- -0.20083304f, -0.16852671f, -0.6318532f, -0.34071004f,
- 0.80835855f, -1.1337019f, 0.6812201f, 1.2102109f,
- -1.1741934f, -0.21967031f, -0.032193802f, -0.963668f,
- -0.976328f, -0.44657323f, 1.0898983f, -0.35385877f,
- -0.24356385f, -0.90512794f, -0.7502535f, 0.7692646f,
- -1.6943814f, 1.3688967f, -1.3199594f, 0.31668815f,
- 1.3132946f, -1.2218748f, -1.1785786f, -0.98413193f,
- 0.40892407f, -0.8201537f, -0.18611902f, -0.5278764f,
- -0.32265547f, -0.16968027f, 0.70884013f, 0.14415708f,
- 0.09835572f, -0.942235f, 0.10699672f, 0.47296727f,
- 1.0634974f, 2.0073984f, 0.7425164f, -0.9512889f,
- 0.37452433f, 0.36471325f, 0.81406325f, -1.3421866f,
- -0.4666948f, 0.0062712235f, 0.75404763f, -1.6863875f,
- 2.00201f, 1.6536381f, -1.1594226f, -0.27827665f,
- -0.5538258f, -1.8913176f, -0.51333076f, -1.0264671f,
- -1.2057621f, 0.06648871f, 0.59697413f, 0.31086308f,
- 0.64299005f, 2.424769f, 0.55034614f, 2.7969975f,
- -1.569126f, 0.5163261f, -0.10226878f, -0.32004845f,
- -0.73082924f, 0.41024676f, -0.43915737f, -0.82381576f,
- -0.7691663f, -1.4024571f, 0.2825937f, 0.37103447f,
- 0.46214953f, 0.34609106f, 0.86730444f, 0.7233089f,
- -0.99955547f, 0.37689602f, 0.042848006f, -1.4534297f,
- -0.120819665f, -0.20042296f, 1.04801f, -0.6412162f,
- -0.48216724f, -0.85329074f, -0.7296434f, -1.0217127f,
- 0.3174752f, -0.9103821f, -0.10708326f, 2.197291f,
- 2.168559f, 0.664089f, -0.17062391f, 1.5269588f,
- -1.8852652f, 1.9886502f, 0.4591112f, 1.1734504f,
- 1.714374f, -0.65599f, 0.13417839f, -0.0916282f,
- -0.09753666f, -0.12068632f, -0.03430777f, 0.68308336f,
- -0.04995184f, -0.22729816f, -0.18219039f, 0.15557364f,
- -0.13177283f, -0.090840556f, -0.13041982f, 0.76121557f,
- -0.05193281f, -0.06299091f, -0.1248315f, -0.12250005f,
- -0.20058052f, -0.08873647f, -0.22645526f, -0.061955325f,
- 0.63442165f, -0.19728692f, -0.039451323f, -0.12111365f,
- 0.8247188f, -0.13542046f, -0.06489395f, -0.11634677f,
- -0.0784402f, -0.08515961f, 0.50754684f, -0.13613534f,
- -0.13327901f, 0.14790943f, -0.25919402f, -0.056892205f,
- -0.18820192f, 0.5896002f, -0.15722783f, -0.16052693f,
- -0.04524951f, -0.35064572f, -0.020148292f, -0.11199864f,
- -0.0953981f, -0.10952142f, 0.8111164f, 0.1850351f,
- -0.09287503f, -0.15366359f, -0.08507776f, -0.17750306f,
- 0.020713056f, 0.0062553296f, -0.061639395f, -0.11130623f,
- -0.11445909f, -0.114571564f, 0.45696732f, 0.4494273f,
- -0.14387503f, -0.09665234f, -0.058039535f, -0.18450439f,
- -0.030147348f, -0.11509533f, -0.13691035f, -0.035329726f,
- -0.07595128f, -0.082045f, -0.07505233f, -0.02625549f,
- -0.15424223f, -0.12925847f, -0.032397747f, -0.30059597f,
- 0.0031500356f, -0.033772912f, 0.7392067f, -0.10639927f,
- -0.1083419f, -0.13090342f, 0.5298167f, -0.17429748f,
- -0.065595396f, -0.2689311f, -0.19636458f, -0.07579319f,
- -0.06392717f, -0.1460543f, -0.088026725f, -0.029092746f,
- 0.020135943f, 0.743938f, -0.12894359f, -0.07457395f,
- -0.16136366f, -0.12797275f, -0.0058550863f, 0.5143326f,
- -0.03852704f, -0.073922195f, -0.079910785f, -0.12199703f,
- -0.034957346f, -0.058310226f, -0.049010307f, 1.1111803f,
- -0.18915059f, -0.05462836f, -0.06985265f, -0.097447105f,
- 0.07241867f, -0.113854825f, -0.06432796f, -0.10435448f,
- 0.038741134f, -0.021954075f, -0.12054996f, -0.11883457f,
- -0.05283621f, -0.020585282f, -0.090348005f, -0.06792721f,
- -0.07549066f, 0.64830655f, -0.109418206f, -0.12324362f,
- -0.09240216f, 0.3103019f, -0.010391475f, -0.03208255f,
- -0.056028076f, 0.046766438f, -0.0011306778f, -0.08314565f,
- -0.07881744f, -0.047946673f, -0.03046768f, -0.05498653f,
- -0.1418305f, -0.06621948f, 0.54861856f, -0.14012676f,
- -0.07068458f, -0.0737217f, 1.1573616f, -0.059793815f,
- -0.2801909f, -0.005201564f, -0.16464217f, -0.08332634f,
- 0.011316427f, -0.14176245f, 0.039665744f, -0.03530733f,
- 0.61192733f, -0.0983324f, -0.056159247f, -0.09467163f,
- -0.09419269f, 0.019707516f, 0.014433033f, -0.03480497f,
- -0.051238302f, -0.09834921f, -0.029921798f, 0.5608852f,
- 0.5648366f, 0.018117892f, -0.015272781f, -0.13010809f,
- -0.031019405f, -0.0045767147f, 0.01641698f, -0.023585781f,
- -0.017946843f, -0.06451226f, -0.029901069f, -0.056608655f,
- -0.02296124f, -0.07569932f, -0.07149305f, -0.0764328f,
- -0.17185959f, -0.043989263f, -0.022927258f, -0.10440901f,
- -0.03198454f, -0.04645653f, -0.086597815f, 1.1742536f,
- -0.19934812f, -0.108464964f, -0.046764653f, -0.06605945f,
- -0.05381676f, -0.10786623f, -0.12666157f, -0.039387565f,
- -0.021235712f, -0.02118875f, 0.60463756f, -0.1656358f,
- -0.022913517f, -0.042839255f, -0.046046887f, -0.02828037f,
- -0.1498768f, -0.12173429f, -0.045656294f, -0.09127231f,
- -0.04852999f, -0.03512028f, -0.053822894f, -0.10735359f,
- 0.17064485f, -0.12579603f, -0.10353951f, -0.10481333f,
- -0.128335f, 1.2578788f, -0.12571533f, -0.13481918f,
- 0.892528f, 0.81076473f, -0.097620346f, -0.070945546f,
- -0.10997518f, -0.47695744f, -0.05547775f, -0.08198409f,
- 0.049234144f, -0.09189605f, 1.0631332f, -0.22183084f,
- -0.2393268f, -0.08672441f, -0.22583164f, -0.1750421f,
- -0.16384289f, -0.17839372f, -0.58195716f, -0.11381048f,
- -0.020718604f, -0.33764994f, -0.08309717f, -0.09623258f,
- -0.029668443f, 0.979481f, -0.13719553f, 0.45866153f,
- -0.21335478f, -0.11574105f, -0.07825863f, 0.17212296f,
- -0.09217147f, -0.09087002f, -0.047691707f, -0.43466783f,
- -0.27312073f, -0.27355456f, -0.22922091f, 0.06565533f,
- -0.38380548f, 0.86467767f, -0.18009596f, -0.1900419f,
- -0.15884046f, -0.09437018f, -0.14297663f, -0.00626517f,
- -0.019608086f, -0.08452518f, -0.063183576f, 0.06469277f,
- 1.368588f, 0.14973804f, -0.17132059f, -0.061841313f,
- -0.18630362f, -0.21096176f, -0.035635564f, -0.23834653f,
- -0.0621279f, 0.78453326f, -0.055065956f, -0.06462024f,
- -0.042877853f, -0.08521256f, -0.039732948f, -0.14326541f,
- -0.06289648f, -0.18952349f, 0.5018134f, -0.09096161f,
- -0.46575657f, -0.28719562f, -0.033565316f, -0.06402683f,
- 0.37134558f, -0.19240095f, -0.09718161f, -0.10512735f,
- -0.2743405f, -0.047217965f, 0.7888947f, -0.08168805f,
- -0.031848744f, -0.04664353f, -0.055497114f, 0.32860255f,
- -0.264296f, 0.23948534f, -0.35077745f, -0.075986035f,
- 0.0064114076f, 0.2600404f, -0.24361749f, -0.14711924f,
- -0.09919141f, -0.092269614f, -0.06925685f, -0.020651491f,
- -0.06290698f, 1.0711867f, -0.12939873f, -0.56575525f,
- 4.6279f, -0.91050726f, -0.25223944f, 0.0417749f,
- -0.6166157f, 0.049802423f, -0.14339665f, -0.3582109f,
- -0.90088314f, -0.30425656f, 0.054889835f, -1.3982153f,
- -0.37142193f, -1.1167077f, 1.1821871f, 0.7512161f,
- -1.2383982f, -0.35453975f, -1.3107115f, -0.28454354f,
- 0.2992178f, -1.6399783f, -2.0123858f, -0.8543826f,
- 0.386484f, -0.057638526f, -0.2643288f, -0.54587966f,
- -0.72456753f, 0.9948174f, 2.2111452f, 1.025258f,
- 0.18931012f, -1.4840238f, 0.86115026f, 1.1876967f,
- 0.6298784f, -0.7032725f, -0.12458587f, -1.1450917f,
- -0.51116216f, 0.28513896f, 1.4075987f, -0.6622601f,
- -1.3507575f, 0.1172559f, 1.5183861f, -1.0958291f,
- -0.8724933f, -0.6737998f, -0.91974884f, -1.1948738f,
- 7.0009894f, -0.15338203f, -1.7565901f, 3.2467177f,
- 0.27079073f, 0.029073456f, -0.2306452f, 1.808277f,
- 2.1086266f, -0.2139741f, 1.6237531f, -0.9080442f,
- 2.0691803f, 0.2927567f, 1.0739841f, -0.8196379f,
- -1.0105622f, 1.0558069f, -0.21407937f, 2.0468752f,
- 0.53634447f, -0.59064424f, -0.6730369f, -0.088851124f,
- 0.20738664f, 0.033999097f, 0.2215048f, -0.67073333f,
- 3.0659847f, -0.19127066f, -2.144655f, -0.9146684f,
- -0.32330033f, 1.1479243f, 2.3053079f, -1.1354623f,
- -1.0472949f, -0.6329205f, -0.85622376f, -1.6022238f,
- -0.1652791f, -0.48014176f, -0.09813208f, 1.8247988f,
- -1.4331149f, 0.39753705f, -0.103675865f, -0.3525228f,
- -0.8160608f, -0.9548168f, -0.13622274f, 0.61385983f,
- -0.059669897f, -0.8771193f, -0.030074013f, -2.147628f,
- 1.1360304f, -1.3734316f, -1.4514599f, -0.3755506f,
- -0.9826977f, 1.953196f, 1.4615626f, 0.5545234f,
- 1.1889209f, -0.4882715f, 0.1084841f, -1.7769637f,
- 0.019121913f, -1.0073205f, 3.028085f, 1.2277423f,
- -0.2024642f, 0.28916913f, -0.48972937f, -1.2346588f,
- 0.42470843f, -1.1344911f, -0.44037202f, -1.6382407f,
- 1.3439572f, 0.45418876f, -1.1084528f, 0.8442094f,
- -1.0207256f, -0.90936106f, 0.16934575f, 0.31776458f,
- -0.7757774f, -0.09300356f, 3.706672f, -2.055698f,
- 1.0121989f, -0.8412044f, -0.91356134f, 0.9267261f,
- 0.84802026f, 1.8587351f, 0.27776727f, 1.1244574f,
- -0.15952352f, 0.35621634f, 0.55506855f, 0.42480817f,
- -1.0700768f, -0.27881408f, 0.3152868f, 3.0126522f,
- -0.70202225f, 0.6419099f, 0.03412417f, -1.6364516f,
- -0.5232957f, 1.1978455f, 0.1139548f, -0.33512518f,
- 0.40876037f, -1.5239811f, -1.3993722f, 0.83354634f,
- -1.206491f, 0.7911835f, -0.280928f, 0.3170723f,
- -0.74463314f, -1.9085807f, 0.9049346f, 1.1121849f,
- 0.7913572f, -0.30167308f, -1.2491792f, -0.45133412f,
- -1.1037858f, 0.5169217f, 0.68872535f, -0.041761342f,
- 1.7016255f, 3.2810295f, 1.0288575f, 1.7231157f,
- -1.114953f, 0.22699118f, 0.0057295356f, 0.80215764f,
- -0.5941404f, 0.9369243f, 0.34848556f, 0.5707486f,
- -0.41651866f, 0.033234186f, -0.47261804f, 0.02924633f,
- -0.2948239f, -0.97748554f, -2.3267684f, -0.09240121f,
- -2.1606088f, -0.33848718f, -1.3545653f, -0.4267353f,
- -0.92469066f, -1.5084553f, -0.17214775f, 0.10765261f,
- 0.3150268f, -1.0942271f, 0.5705382f, -0.45130008f,
- 0.04745762f, 2.7444663f, -0.17254639f, -1.3886417f,
- 0.42065108f, -0.020793244f, -1.4054772f, -0.62936324f,
- 0.012944343f, 1.6205044f, -1.07194f, 0.58327967f,
- -1.125682f, 0.28438777f, 1.978448f, -0.9321829f,
- -1.0233917f, 1.3410542f, 1.5247141f, 0.51864016f,
- -0.6864025f, -0.14701703f, 0.38859034f, -1.22316f,
- 0.0057992144f, 0.37505108f, 0.6065053f, 0.27051455f,
- 1.7351289f, -1.3512013f, 1.5814826f, -0.57937825f,
- 1.5157081f, -0.4598167f, 0.27076274f, -0.09312992f,
- -0.31399286f, -0.78526086f, 0.53883034f, 0.013998611f,
- -0.2891965f, 1.4114921f, -0.24826747f, 0.24166831f,
- 0.37727585f, 2.4512503f, 1.8454673f, -1.6895237f,
- -0.44241133f, -1.4011135f, 0.32151562f, -0.74614996f,
- -0.37673724f, -0.87802184f, 0.06164881f, 0.8075236f,
- 0.17834648f, 0.9653205f, 0.4424586f, 1.1142926f,
- -0.8711625f, -2.1596935f, -1.3349278f, -0.79985636f,
- -0.05207473f, -0.26826394f, 1.0458577f, -0.7182075f,
- -1.0488945f, 0.07144158f, -1.3686941f, -0.8179755f,
- -0.17300098f, -0.08368621f, -0.91314876f, -0.26487023f,
- -0.10311247f, -1.1680231f, 0.36149767f, 1.9425431f,
- 0.79288614f, -0.6059864f, -0.31451958f, -0.15716702f,
- 0.78487045f, 1.704474f, 3.914537f, -1.3704987f,
- -1.1108671f, -1.1456809f, 0.18451224f, 0.5534135f,
- -0.0006009787f, 0.34461704f, -0.2200322f, 0.4231373f,
- 0.16656224f, -0.15923412f, -1.1252607f, -0.9825976f,
- -0.6810947f, -1.7468992f, -0.52950513f, -1.4086509f,
- 0.14290006f, 3.1435795f, -1.4606413f, -1.4032458f,
- -1.6052881f, -0.30125993f, 1.0295255f, 0.6797233f,
- -0.41453794f, 0.818103f, -0.5106876f, -1.6983169f,
- -0.05115552f, 0.5378516f, 2.5276895f, -0.9246178f,
- 0.074596696f, -0.25959238f, 1.4711412f, 3.8867722f,
- -0.80570626f, -0.85293615f, 1.5619923f, 1.6278149f,
- 0.28263536f, -1.299526f, -0.56422395f, 0.689206f,
- -0.6849304f, 0.054065462f, -0.59579206f, -0.72911215f,
- 0.11557167f, 0.6631459f, -0.9621304f, 0.8623776f,
- 0.06159256f, 2.2410693f, -1.114809f, -0.15685886f,
- -0.83850586f, 0.16746871f, -0.6174656f, 0.7718721f,
- 0.28610417f, -0.5093715f, -1.414729f, 3.7192569f,
- 0.32403094f, 0.02545421f, 2.9030297f, 3.9031563f,
- -0.2829744f, -1.0615755f, -1.5456461f, -0.64362234f,
- -0.41027746f, -0.14678906f, -0.09971536f, 1.1494067f,
- 0.57017356f, 1.0258287f, -0.13708638f, 0.23456784f,
- -0.6435267f, -0.57209915f, -1.0115556f, -0.11650024f,
- -1.5101265f, -0.015386956f, 0.584149f, -0.7324359f,
- -1.4342597f, -0.907397f, -0.09618274f, 0.26136124f,
- -0.21742482f, -1.5928209f, -0.91966283f, -0.33957788f,
- -0.004837333f, 0.35257214f, -1.444851f, 0.789198f,
- 1.8578433f, -0.983993f, -0.7257963f, 0.1329607f,
- 0.1046111f, -0.8712878f, 1.5172634f, 3.2354157f,
- -1.5248847f, -0.5551041f, -0.7485186f, 0.44131237f,
- -1.3540319f, -0.22968759f, 0.12592702f, 0.91567254f,
- 1.832156f, -0.089143716f, -0.7613987f, 0.76173645f,
- -1.2539423f, -0.05214712f, -1.2005016f, -0.19924651f,
- -1.1680022f, 0.3501367f, -0.14501543f, -1.7726158f,
- -1.1561803f, -0.70352453f, 0.58699167f, 1.3918281f,
- -0.89362323f, 0.54195684f, 0.23139147f, -0.57999325f,
- -1.1023191f, -0.32814202f, 0.45994255f, -0.44669074f,
- -1.2855685f, -1.6217114f, -0.21885069f, 0.5003492f,
- 0.7876935f, -0.56714445f, -0.37112048f, 0.28109723f,
- 1.0471895f, -1.6742476f, -1.1631812f, 0.19288199f,
- 0.8448245f, 0.5553348f, -0.0047552106f, -1.4572163f,
- -1.1595637f, 0.32969904f, 1.0829419f, 0.7765458f,
- 0.05386427f, -0.83947474f, 3.7498126f, -0.18056384f,
- 0.2463649f, 1.4536493f, 0.061307468f, -1.0826098f,
- 1.1959502f, 0.955787f, 1.0237025f, -1.3537987f,
- -0.6283195f, 0.11970676f, -0.19521022f, 0.050009146f,
- 0.64853466f, -0.45627224f, -0.6757204f, -1.5549458f,
- -0.5534075f, -1.6946002f, 0.0069934265f, -0.29095617f,
- -1.0968149f, -0.026561499f, -0.0013912735f, 0.5047461f,
- -0.5087077f, 2.8593621f, 0.84754664f, 2.566076f,
- -1.3076143f, -0.04859938f, 0.4927884f, 0.4983412f,
- 1.3509537f, -0.83139086f, -0.8581676f, -0.5953354f,
- -0.23058698f, -1.2116524f, 0.20529187f, 0.0012862342f,
- -0.3519058f, -0.4974222f, 0.5802958f, 0.01826554f,
- -0.7492601f, 0.37656054f, 1.4719508f, -1.3895295f,
- -0.14304303f, -0.15035003f, -0.6487513f, 0.23634717f,
- 1.4274381f, 2.0445874f, -0.8610088f, 0.1850316f,
- -0.15863925f, -1.1676755f, 0.36991307f, 1.0185448f,
- 2.2202172f, 2.2167642f, -0.35451034f, -0.5142228f,
- 0.58095944f, -0.298247f, 1.4213024f, -0.8493213f,
- -0.018114142f, -1.075452f, -0.18148853f, -0.529935f,
- -0.019190159f, -0.030807072f, -0.04891715f, 0.18601684f,
- -0.055961374f, -0.072265245f, -0.087106414f, 0.02589026f,
- -0.062631845f, -0.13852698f, -0.074530244f, 0.5178091f,
- -0.040542096f, -0.087508105f, -0.041364342f, -0.07474421f,
- 0.7070819f, -0.060000088f, -0.07978055f, -0.07264355f,
- -0.063026704f, -0.09050781f, -0.061463572f, -0.082453124f,
- 0.66127604f, -0.017167633f, -0.09762222f, -0.11120126f,
- -0.0030072336f, -0.04819706f, -0.03491252f, -0.058411635f,
- -0.06450123f, 0.41928884f, -0.05731618f, -0.05605673f,
- -0.07183287f, 0.7056129f, -0.05401107f, -0.2489066f,
- -0.009502937f, -0.22129744f, -0.028702393f, -0.029441018f,
- -0.102413654f, -0.077371284f, -0.063075736f, 0.36461258f,
- -0.09885472f, -0.032187734f, -0.09364781f, -0.08452322f,
- -0.036246672f, -0.009754941f, -0.023804834f, -0.043817777f,
- -0.09665502f, -0.08074018f, 0.787878f, 0.03797245f,
- -0.023239654f, -0.037845645f, -0.09127772f, -0.06043957f,
- -0.041355975f, -0.022279399f, -0.01182362f, -0.034193017f,
- -0.07328232f, -0.09257405f, -0.059749413f, -0.04751234f,
- -0.042723563f, -0.08429413f, -0.052790016f, -0.111533694f,
- -0.012384924f, -0.030807642f, 0.2555325f, -0.021240305f,
- -0.035021305f, -0.08057817f, 0.7279307f, -0.16032745f,
- -0.07208911f, -0.038624533f, -0.051438063f, -0.072088934f,
- 0.06544274f, -0.066039056f, -0.06356856f, -0.066210344f,
- -0.0025171314f, 0.26771298f, -0.09801044f, 0.18840316f,
- -0.11841589f, -0.108799145f, -0.043948155f, 0.15904698f,
- -0.060737208f, -0.03476145f, -0.089615874f, -0.08722297f,
- -0.022090536f, -0.035832457f, -0.12131406f, -0.062439885f,
- -0.11693447f, -0.079965696f, -0.085035264f, -0.042563476f,
- 0.7939703f, -0.042621594f, -0.2018127f, -0.19125469f,
- 0.5697639f, -0.10481425f, -0.047589645f, -0.058277346f,
- 0.46785587f, -0.04251166f, -0.04382008f, -0.07781854f,
- -0.08214721f, 0.39520338f, -0.069797166f, -0.111951314f,
- -0.07658323f, -0.07569994f, -0.1394061f, -0.08953965f,
- -0.16478151f, 0.4959372f, -0.29030684f, -0.016307442f,
- 0.040306825f, -0.07045954f, -0.0666162f, 0.40350735f,
- -0.17491573f, -0.13045286f, 0.3176466f, -0.20294712f,
- -0.031175165f, -0.1734339f, -0.009551505f, -0.1046419f,
- -0.06312895f, -0.056767434f, -0.18347545f, -0.09594906f,
- -0.08784586f, -0.17769052f, -0.036853228f, -0.047516745f,
- 0.8046329f, -0.062443808f, -0.15521143f, -0.105685286f,
- -0.12089143f, -0.101890236f, -0.053915203f, -0.03754339f,
- -0.06395913f, -0.08265049f, -0.092264816f, 0.18770206f,
- 0.53818655f, -0.11964719f, -0.055266038f, -0.07983574f,
- -0.1367586f, -0.06719095f, -0.14397784f, -0.055249926f,
- -0.08997812f, -0.01495139f, -0.022053879f, -0.07712611f,
- -0.03175916f, -0.1094098f, -0.09337541f, -0.07303798f,
- -0.19450115f, -0.0211124f, -0.06004321f, 0.440824f,
- 0.42316493f, -0.073421225f, -0.085513584f, -0.090886235f,
- -0.1177909f, -0.059619088f, -0.2283915f, -0.13427112f,
- -0.055282313f, -0.10236669f, -0.09393899f, -0.034815315f,
- -0.058953818f, -0.04925126f, 0.91032064f, -0.14400196f,
- 0.66010934f, -0.15197298f, -0.060991388f, -0.021163303f,
- 0.6881632f, -0.09105425f, -0.10050727f, -0.087101564f,
- -0.17045216f, -0.09752714f, -0.04128709f, -0.10025938f,
- 0.55400836f, -0.25644112f, -0.5252849f, -0.50092226f,
- -0.17606834f, 0.3246151f, -0.3680127f, -0.24985354f,
- 1.8010844f, 0.49736604f, -0.0005436355f, 0.066804275f,
- -0.39508876f, -0.17648186f, -0.08008137f, -0.2924562f,
- -0.26136217f, -0.20860444f, -0.005376632f, -0.10686318f,
- 0.047078975f, -0.21069308f, -0.35770684f, 0.18609866f,
- -0.74181354f, -0.073847234f, 0.14140168f, 1.0764521f,
- -0.5727689f, -0.076415315f, -0.33297157f, -0.3555353f,
- 0.56951404f, 0.90824205f, 0.90391463f, 0.07549135f,
- 0.7325787f, -0.484219f, -0.9004867f, 0.030826328f,
- 0.22331446f, 0.6246833f, -0.40271443f, 1.1047429f,
- 0.7812234f, -0.1905303f, -0.27203238f, 0.031637594f,
- 0.427688f, -0.14980686f, -0.11995228f, -0.32420805f,
- 0.54052055f, 0.6580302f, 0.09692002f, -0.27970883f,
- -0.2653758f, -0.04738379f, -0.20548949f, 0.49067852f,
- -0.17413804f, 0.1623857f, -0.022560539f, -0.3957322f,
- -0.57208484f, 0.8692256f, 0.55629677f, 0.5213278f,
- -0.20798813f, 0.89717066f, -0.32449204f, -0.20129578f,
- -0.28176275f, 0.028431544f, -0.5617971f, -0.3956093f,
- -0.46405947f, 1.3908412f, 0.24173819f, -0.26441616f,
- -0.29131186f, 0.29738298f, -0.24952883f, -0.3117442f,
- 0.26164964f, 1.3071462f, -0.3707573f, -0.45215833f,
- -0.8629678f, -0.35783428f, 0.94043404f, -0.6077173f,
- -0.13276611f, 0.14255212f, 0.009282825f, -0.35044166f,
- -0.32060677f, 0.5184059f, -0.36346677f, -0.3815082f,
- -0.38385904f, -0.41762024f, 0.0809342f, -0.5737104f,
- -0.24435556f, 0.67792284f, -0.32999057f, -0.34154895f,
- -0.13630325f, 0.475051f, -0.6605333f, 7.960914f,
- 0.66954553f, 0.42203844f, -0.11197413f, -1.3508316f,
- -3.7394853f, -1.810372f, -0.13336752f, -3.4066782f,
- -2.2568069f, -0.20438232f, -0.6421696f, -4.5685253f,
- -1.9721928f, 2.5270965f, 4.8022847f, -0.94663596f,
- -1.3525171f, 0.4675411f, -3.5640557f, -1.6673669f,
- -0.66745895f, 1.9553022f, -2.5462472f, -0.7170252f,
- 0.10125614f, -2.5305326f, -0.2754266f, 0.12833986f,
- 0.44185966f, 0.08223241f, 0.23453198f, -0.31170893f,
- -0.73745424f, -1.0273823f, 8.888385f, -0.7364107f,
- -0.25455534f, -2.7692282f, -0.32268733f, -2.9512477f,
- -0.07149163f, -0.0021231358f, 6.341163f, -2.895886f,
- -1.9024682f, 0.06686282f, -0.69552606f, -2.706524f,
- -2.1855562f, -2.8870485f, 4.011944f, -4.8262606f,
- 2.3062506f, -2.887326f, -1.0293889f, 5.593495f,
- 1.5461315f, -0.27753246f, 0.26940802f, 0.76021683f,
- 8.134427f, 5.5838046f, -1.5337025f, -1.1797743f,
- -4.7419815f, -3.4636621f, 3.1625721f, 1.8111312f,
- 10.043274f, -2.9059045f, -3.6101694f, 3.9925888f,
- 4.735002f, -2.1225257f, -3.195592f, -1.6722633f,
- 3.1597018f, -0.32104206f, -0.11854318f, -2.0929284f,
- 2.3497174f, -0.7946553f, -1.6601566f, -4.194384f,
- -0.0005774121f, -2.2078772f, 1.056473f, -2.5630965f,
- -2.6713827f, 6.7092733f, 4.0516243f, 0.5766658f,
- -0.26849627f, -2.4346306f, -0.24923247f, -0.7861625f,
- 0.5378298f, -1.4282367f, -0.10054147f, 6.0223393f,
- -1.2900764f, 6.2461176f, -0.3973054f, 2.494013f,
- -3.8566148f, -0.59005535f, -0.11482846f, -1.7155418f,
- -0.09400954f, -0.36316344f, -0.10290246f, -0.06287613f,
- -0.14734046f, -0.13828433f, -0.29842368f, 1.0130395f,
- -0.018510083f, -0.09211513f, -0.18577932f, 1.0361755f,
- -0.058169637f, -0.29272956f, -0.18134648f, -0.24204113f,
- -0.14484142f, -0.013038923f, -0.0717918f, -0.162621f,
- 0.7027984f, -0.22426093f, -0.13985881f, -0.17975415f,
- 1.0936202f, 0.9379569f, -0.09089162f, 0.8142169f,
- 0.017918862f, -0.011620676f, -0.06767168f, -0.38175097f,
- -0.2734832f, -0.44247591f, -0.09612553f, 0.014821307f,
- -0.19761668f, -0.26865265f, -0.2156384f, -0.105433375f,
- -0.119334996f, -0.43533257f, 1.1642954f, -0.103413776f,
- -0.22416593f, -0.11218251f, 0.92101157f, 0.25961304f,
- -0.11326186f, -0.0020223444f, -0.15380189f, -0.1416423f,
- -0.1692758f, 0.2603514f, -0.08528058f, -0.10701507f,
- -0.028995095f, -0.11301107f, -0.12769894f, 0.53541404f,
- 0.010276069f, -0.10684295f, -0.24338023f, -0.15059555f,
- -0.20236605f, -0.19387388f, -0.06854222f, -0.13931786f,
- -0.02345084f, -0.21911108f, -0.15502651f, -0.057637647f,
- -0.21102928f, -0.26127f, -0.183749f, -0.49184924f,
- -0.2220888f, -0.080753766f, 0.9385605f, 0.88654464f,
- 0.047425732f, -0.10993328f, -0.18266766f, -0.13226792f,
- -0.13163157f, 1.9641384f, 0.0049684034f, -0.121424936f,
- -0.3093316f, -0.02627653f, -0.081825525f, -0.078208104f,
- -0.05098504f, -0.08199462f, -0.14548151f, 0.050718017f,
- -0.19989379f, 0.020862514f, 0.119311795f, -0.19084656f,
- -0.016311387f, -0.2743515f, -0.029267129f, -0.33449933f,
- -0.08628577f, -0.033873085f, 0.20953783f, 0.36046726f,
- -0.34738448f, -1.4895788f, 0.517706f, -1.3616003f,
- 0.067999914f, 2.8498695f, 1.4654734f, -0.38100874f,
- -0.06693601f, -0.5386105f, 3.1449418f, 0.5870799f,
- 1.0741698f, 1.0534772f, -1.5277253f, -1.4619223f,
- 1.295883f, 0.40985867f, 0.39490938f, -0.99825597f,
- 0.62853324f, 0.62759066f, 3.4393961f, -0.6449674f,
- -1.586973f, -1.2405819f, 0.06963305f, -1.0035335f,
- -0.06128926f, -0.48875573f, -0.8035316f, 0.41840366f,
- -0.31723264f, -0.8942675f, 0.31563607f, -1.1507595f,
- -0.66772395f, 2.3901303f, 0.54330266f, 0.37813574f,
- 1.9002252f, 0.17075603f, -1.2034855f, -0.007397356f,
- -0.15105309f, -1.8211484f, -0.9353147f, -0.25325045f,
- 1.1486044f, -1.498305f, 3.793511f, 1.7827554f,
- -1.7270339f, -1.4988083f, -0.062731326f, -2.5092158f,
- 0.07900781f, -1.5556484f, -0.6824679f, -0.086985424f,
- 0.070148215f, -0.9929909f, -1.0583661f, 0.20524098f,
- 0.14582114f, 3.5866134f, -0.2297251f, 1.5218673f,
- -0.27944055f, -1.6271621f, -0.7740852f, -1.2604367f,
- -2.3419602f, 0.95379776f, 3.7341175f, -0.4232276f,
- 1.0070947f, -0.7831853f, -1.2408884f, 0.2381926f,
- 0.5375229f, 0.6222608f, -1.3854114f, 0.47988316f,
- -0.861587f, 0.006967767f, -0.39894268f, -0.42138195f,
- -2.3002152f, 2.8144317f, 3.3680942f, -1.6691906f,
- -1.3476094f, -0.2652999f, 0.26121327f, 1.8171134f,
- -0.076725945f, 2.5373268f, -0.9782978f, -0.6805266f,
- 0.43114832f, -1.8134831f, -0.2139686f, 1.437447f,
- -0.7995949f, -0.8183015f, 2.6482809f, -1.8835198f,
- 0.31609654f, -1.6813555f, 0.62996715f, 0.69758403f,
- -0.018340008f, -0.002944146f, 0.16725533f, -0.76180726f,
- -0.4285053f, 0.04907789f, -0.7501441f, 0.8192934f,
- -0.5358465f, 0.85721874f, -0.6105799f, -0.4980207f,
- 0.27287924f, -0.49905777f, 1.276518f, -0.8344684f,
- 0.25094733f, -0.8536093f, 1.2700204f, 0.06651175f,
- -1.3963568f, 0.071302935f, -0.17318392f, 0.42230693f,
- 1.0714334f, -0.16221766f, 1.3786439f, 1.255099f,
- -0.07392258f, 0.12133094f, -0.6343489f, 0.27214703f,
- -0.17088099f, 0.19627716f, -0.056563362f, 0.67796975f,
- -0.49115777f, -0.40156287f, 0.4450625f, -0.24088453f,
- 0.02325804f, 0.8342655f, -1.1501614f, -0.88315326f,
- -0.101109184f, 1.4957049f, -1.1143591f, -0.2181184f,
- 0.82660234f, -0.9340353f, -0.38076928f, 1.7405573f,
- -1.1566197f, 0.22105551f, -0.14600225f, -1.2151536f,
- -0.039038286f, 0.68327147f, 0.6361185f, 1.2306731f,
- -1.5068989f, 0.60426176f, -0.081860416f, 0.18208314f,
- 0.6075538f, 0.6736436f, -0.70031804f, -0.22452676f,
- -0.12806922f, -1.1093501f, -0.6387804f, 0.5788749f,
- 0.22029798f, 0.123841956f, -0.00941046f, -0.42360094f,
- -0.8365658f, 0.57573766f, -0.5264076f, -1.0190887f,
- 0.095923446f, -1.2246488f, -0.73425406f, 0.11267476f,
- -0.09299752f, -0.33710042f, 0.22404636f, -0.5666127f,
- -0.7684971f, -1.1775466f, -0.04726114f, 0.10205497f,
- 0.79756063f, 0.024283776f, 1.600099f, -0.8809205f,
- -0.16923924f, -0.045949627f, 0.20303781f, -0.83308375f,
- 1.6119001f, -1.2521385f, 2.0674515f, 0.95784616f,
- 1.0257199f, 0.31962335f, -0.39744347f, -0.12115193f,
- -0.060598113f, -0.078551024f, 1.0416111f, -0.16364135f,
- -0.123756565f, 1.1344017f, 0.596065f, -0.081013314f,
- -0.11276181f, -0.11672551f, -0.2979981f, -0.12526798f,
- -0.13645613f, -0.09342995f, -0.066016845f, 1.0696527f,
- -0.16617724f, -0.28545302f, -0.11822461f, -0.20215636f,
- -0.2009186f, -0.1269129f, -0.1474439f, -0.32505596f,
- -0.04637094f, -0.041523833f, -0.1101048f, -0.07805641f,
- -0.0958373f, -0.26892722f, 1.1528f, -0.12869886f,
- 0.3884001f, -0.11781932f, -0.09134802f, -0.13711601f,
- 0.38811922f, -0.0976234f, -0.21623649f, -0.056077227f,
- -0.30425078f, -0.19782543f, -0.21492094f, -0.19359222f,
- 0.022328662f, -0.23925406f, 0.7861495f, -0.21415706f,
- -0.2520154f, -0.113193214f, -0.08859163f, -0.08439253f,
- 0.06073613f, -0.024431149f, -0.042937513f, -0.13778898f,
- -0.06921891f, 1.1664963f, 0.16731161f, -0.12960006f,
- -0.121535145f, -0.14926311f, -0.11601315f, -0.09769292f,
- -0.15778014f, -0.02729154f, 0.9903379f, -0.08365973f,
- -0.04681396f, -0.058638357f, -0.07852008f, -0.044518907f,
- -0.07756439f, -0.12022675f, -0.20285907f, 0.98010993f,
- -0.11887263f, -0.294497f, -0.21170336f, -0.017701885f,
- -0.15856622f, 0.46206972f, -0.20932592f, -0.11715274f,
- -0.047049146f, -0.3212236f, -0.025083553f, 0.89877397f,
- -0.12704687f, -0.05211127f, -0.08101581f, -0.02210089f,
- -0.4815588f, -0.24813473f, -0.107899375f, -0.3124688f,
- -0.013001763f, 0.05369435f, -0.34294373f, -0.20697439f,
- -0.12184811f, -0.12667026f, -0.07562452f, -0.034035675f,
- -0.019048171f, -0.07381557f, 1.1307786f, -0.17841849f,
- -0.8911193f, -0.18618797f, -0.58952355f, 0.6095083f,
- 0.024976723f, -0.34612688f, 0.2833388f, 0.34968516f,
- -0.48834774f, -0.859522f, -0.40608165f, 0.4353929f,
- -0.05741975f, -0.103158906f, -0.81539005f, 0.47579408f,
- 0.19579095f, -0.21196972f, -0.14124443f, -0.2577148f,
- 0.25161827f, 1.1736884f, -0.272247f, -0.50002164f,
- -0.34676737f, 0.30210772f, -0.29183173f, -0.009219122f,
- -0.14333718f, -0.3638206f, 0.2238708f, 0.64212793f,
- 0.46450022f, 0.27063516f, -0.2768949f, 0.14323424f,
- -0.21642621f, 0.48789623f, 0.90192395f, 0.18401507f,
- -0.44475794f, 0.66391236f, 0.5790484f, 0.09652636f,
- -0.5690377f, 0.3913855f, 0.40909165f, 0.18413836f,
- -0.08696776f, -0.026223242f, 0.20690265f, 0.086525515f,
- 0.2721793f, -0.6639634f, -0.597208f, -0.4795398f,
- -0.16434158f, -0.15852676f, -0.004216471f, 0.33466262f,
- 0.26685393f, -0.34487566f, 1.0511477f, -0.15606616f,
- 1.5566698f, -0.27198973f, -0.24243475f, 0.26260325f,
- 0.038721845f, -0.67579305f, -0.533776f, -0.27397442f,
- -0.63178813f, -0.30571648f, -0.57651424f, -0.13417721f,
- 0.15284146f, 0.1403806f, 0.23879369f, 0.2064172f,
- -0.0013619002f, -0.045177218f, 0.30106843f, -0.21188648f,
- 0.011421341f, 0.01828272f, -0.14172871f, -0.30777878f,
- 0.42671296f, -0.37172183f, 0.10074122f, -0.44427985f,
- -0.002927576f, 0.10661804f, -0.43037403f, 0.053484358f,
- 0.49051636f, 0.19255976f, 1.2406723f, -0.16635711f,
- -0.06817304f, 0.5914672f, 0.0073873745f, -0.30359212f,
- 0.148039f, -0.1636093f, -0.36440158f, 0.43788952f,
- -0.54608506f, -0.11078897f, -0.16443409f, -0.048272576f,
- 0.71869195f, -0.13521361f, -0.39818618f, -0.27579558f,
- 0.08462129f, -0.15230882f, -0.15154812f, -0.13906457f,
- 1.6343167f, -0.019862486f, -0.10287361f, -0.17084764f,
- -0.12693752f, -0.12878294f, -0.09791659f, -0.12728442f,
- -0.11654825f, 0.2623964f, -0.14714603f, -0.071403526f,
- -0.27518433f, 1.800577f, -0.06381664f, -0.060725644f,
- 0.42957726f, -0.12847112f, -0.11453474f, 0.52450395f,
- -0.24865551f, -0.26388732f, 0.028333098f, -0.1527122f,
- -0.08834418f, -0.1961583f, 0.12308083f, -0.2522723f,
- -0.1416556f, -0.15249434f, -0.19115378f, -0.20085502f,
- -0.0812266f, -0.16032997f, -0.116831936f, 0.5904607f,
- 0.49930784f, -0.07839011f, -0.07375253f, -0.20354857f,
- -0.1855164f, -0.07970588f, 0.030249791f, -0.011580562f,
- -0.08275222f, -0.11806686f, -0.0625189f, 0.22510049f,
- -0.054773092f, -0.08396246f, -0.048612837f, -0.1742276f,
- -0.094181456f, -0.07551029f, -0.1583283f, -0.10277977f,
- -0.14785992f, -0.008648019f, -0.15879183f, -0.1298084f,
- 0.025948355f, -0.17323309f, -0.121044815f, -0.11174735f,
- -0.3196017f, -0.24324238f, -0.042722408f, 1.6309026f,
- -0.090287216f, -0.06895254f, -0.092551164f, 0.08785382f,
- -0.13124041f, -0.027042767f, -0.072582826f, -0.076020345f,
- -0.07529071f, -0.19584174f, -0.03634897f, -0.008562656f,
- -0.0509318f, -0.009278459f, 0.8163749f, -0.16199182f,
- 0.40398192f, -0.08490269f, -0.049748536f, -0.056523725f,
- 1.1049541f, -0.18056364f, -0.22674999f, -0.06950584f,
- -0.24750812f, -0.23965523f, -0.082875885f, -0.17855874f,
- 0.4941343f, -0.26388985f, -0.08419361f, -0.099429585f,
- -0.041638076f, 0.5004325f, -0.05823009f, -0.07665647f,
- 0.88190526f, 0.5608558f, -0.08728955f, -0.0607426f,
- -0.13591185f, -0.38704425f, -0.097447656f, -0.1447571f,
- -0.11836638f, -0.14462589f, 1.2148792f, -0.12097401f,
- 0.067216806f, -0.052737586f, -0.23352334f, -0.1337242f,
- -0.117719404f, 0.007662752f, -0.39833555f, -0.2644608f,
- -0.05425401f, -0.2554606f, -0.10002738f, -0.086743586f,
- -0.27233255f, 0.7033545f, -0.075019926f, 0.43453905f,
- 0.035988353f, -0.110955305f, -0.119224966f, -0.05146393f,
- -0.13996534f, -0.24549638f, -0.07187416f, -0.04371189f,
- -0.1780429f, -0.18404397f, -0.21524635f, 0.014839267f,
- -0.11513966f, 0.9980235f, -0.14614761f, -0.2460508f,
- -0.14611882f, -0.10848519f, -0.09638311f, -0.012337308f,
- -0.024372837f, -0.044764407f, -0.056857314f, -0.16726641f,
- -0.19865851f, 0.768384f, -0.16722694f, -0.07015513f,
- -0.070301086f, -0.032733824f, -0.054984313f, -0.10294296f,
- -0.03944811f, 0.7383121f, -0.078158855f, -0.092321314f,
- -0.042187683f, -0.09129268f, -0.10967075f, -0.092899114f,
- -0.15025562f, -0.10937828f, 0.9628553f, -0.105292246f,
- -0.34627426f, 1.4133352f, -0.02150285f, -0.14390501f,
- -0.16531838f, -0.08977595f, -0.07353188f, -0.137821f,
- 0.016181745f, -0.044671845f, 0.616518f, -0.12513907f,
- -0.095838435f, -0.04472702f, -0.056288157f, -0.19960909f,
- -0.24172707f, 0.84151864f, -0.28192186f, -0.07022315f,
- -0.07674882f, -0.26653147f, -0.12299514f, -0.13668673f,
- -0.08511696f, -0.033129852f, -0.09219426f, -0.0496291f,
- -0.028429031f, 0.23226324f, -0.12852393f, 0.17649904f,
- -0.27003404f, -0.20931922f, -0.077400856f, -0.1295823f,
- -0.22488351f, 0.40816355f, 0.1560424f, -0.10195919f,
- -0.30709097f, -0.013667226f, -0.32063538f, -0.17257154f,
- 0.24215032f, -0.06106245f, -0.20082763f, 1.1154475f,
- -0.099756986f, 1.2891301f, -0.0008999992f, -0.25938255f,
- -0.5590645f, -0.23359731f, 0.008224368f, -0.24750853f,
- -0.29308158f, -0.35736024f, -0.10351258f, -0.1555447f,
- -0.0721146f, -0.18579772f, -0.14535472f, -0.1389735f,
- 0.718629f, 0.35086316f, -0.4534514f, -0.27158654f,
- 0.68448925f, -0.08810966f, -0.25869778f, -0.40147328f,
- -0.6551867f, -0.12247157f, 0.02934682f, -0.4193084f,
- -0.05211683f, -0.16529904f, 0.5439482f, -0.13765283f,
- -0.21974368f, -0.17541946f, -0.31366193f, -0.14902991f,
- -0.018033413f, 0.03449552f, 0.020110264f, 0.8910442f,
- -0.3666622f, -0.06440432f, 1.2011441f, -0.09621833f,
- -0.22415401f, -0.12998576f, 0.24630082f, -0.054286726f,
- 0.23019262f, -0.2897905f, 0.77566475f, 0.04933603f,
- -0.1977466f, -0.1852801f, -0.20409471f, -0.11077336f,
- -0.27221262f, 0.34278697f, -0.33407605f, 1.3641058f,
- 0.22309756f, -0.21794228f, 1.0459623f, -0.1715456f,
- -0.06347759f, -0.23378795f, -0.27671805f, -0.357571f,
- -0.0021175316f, 1.4248016f, -0.19781984f, 0.04211555f,
- -0.15542626f, -0.31132865f, -0.21789098f, -0.050059635f,
- -0.084416434f, -0.3264254f, 0.13133143f, 0.13442032f,
- -0.08298471f, -0.17731583f, -0.14540173f, -0.14734368f,
- -0.052295055f, 0.39542106f, -0.039688777f, 0.10894176f,
- -0.17995022f, 0.47941133f, 0.38065398f, -0.36412206f,
- 0.46294487f, -2.3553226f, -2.5323517f, -0.26091403f,
- -2.0266566f, 0.49159956f, -2.9142866f, 0.096036844f,
- 4.28395f, -0.19754615f, -0.9452832f, 0.15997241f,
- -1.3661814f, -0.39127687f, 0.054183945f, -1.2106922f,
- -0.87352353f, -2.836962f, -0.7550528f, -1.9728729f,
- -0.75200313f, -1.7670515f, 0.24926978f, -3.5575678f,
- 4.2460933f, 0.073438995f, -1.8968366f, 0.2292511f,
- 6.3692f, 6.597084f, -0.116786174f, 1.2807181f,
- -0.632229f, 0.21012425f, 0.7784188f, 5.951225f,
- 6.1096854f, 0.5996849f, 3.679713f, -1.3258882f,
- -3.030696f, -0.8763502f, 0.23300113f, -0.5934267f,
- 2.3953705f, -1.454476f, 0.49003744f, 0.05010974f,
- -0.41522995f, -1.1534789f, -1.9314218f, -1.3827652f,
- -2.3863f, -2.9163983f, -3.0341206f, -3.9612658f,
- -0.21198435f, -2.27265f, -0.3574891f, -0.47651875f,
- -1.7237221f, -4.5456953f, 6.104373f, 2.1089044f,
- -0.11881127f, -2.6778686f, -1.1893226f, 1.7214928f,
- 5.699658f, -2.5532844f, 1.0148431f, -2.245012f,
- -3.7635179f, -2.4798484f, 0.58403915f, 2.677361f,
- 0.5407201f, 0.6477776f, -3.3476527f, -0.1540321f,
- 1.7351344f, 0.30555636f, -0.11517568f, 0.35127345f,
- -2.648491f, 0.19525166f, 1.3200608f, 4.1838245f,
- 0.11953614f, 0.12570794f, -0.8861305f, -4.6982946f,
- 4.5470605f, 0.23465925f, 2.2320867f, 0.117387585f,
- 0.7522104f, -0.038076513f, -1.5340579f, 0.29831967f,
- -2.2340782f, 6.519719f, -0.070719615f, 3.755893f,
- 5.742652f, -2.4117448f, -2.5223906f, 0.39895847f,
- -0.018629571f, -0.14809382f, 0.2668079f, -0.41609004f,
- 0.25043234f, -0.23961605f, -0.0779132f, -0.07889772f,
- -0.03931678f, -0.018563036f, -0.24742743f, -0.35433167f,
- 0.739545f, -0.31941327f, -0.3209194f, 0.37032038f,
- -0.33134985f, -0.21013084f, 0.04725023f, -0.06163462f,
- -0.18213128f, 0.3252845f, -0.024237284f, 0.058238782f,
- -0.29930767f, 0.7250727f, -0.1337685f, -0.27005368f,
- 0.15781645f, -0.117059015f, -0.20456696f, -0.075766444f,
- -0.06555119f, -0.35271943f, 1.6647934f, -0.1596857f,
- 0.18679065f, -0.101995505f, 0.072288014f, 0.8131432f,
- 1.2295564f, -0.16441737f, -0.11156378f, -0.1173709f,
- -0.04567767f, 0.16196169f, -0.14636488f, 0.117639f,
- 0.38159716f, -0.0022345816f, 0.2672279f, -0.1566554f,
- 0.1582368f, -0.26237583f, -0.2800653f, -0.24968861f,
- -0.3543261f, -0.22899848f, -0.27874973f, -0.13431107f,
- 0.35522714f, -0.104810536f, -0.2397949f, 0.5241473f,
- -0.08802511f, -0.18049186f, -0.104556f, -0.34411702f,
- -0.064427875f, 0.16948457f, 0.10859759f, -0.042448744f,
- -0.26346081f, -0.04005416f, -0.29428777f, -0.020106755f,
- 0.2610074f, -0.10335218f, 0.002645572f, 0.7266491f,
- 0.23746222f, -0.012492392f, -0.13987449f, 0.051023003f,
- 0.10399293f, -0.23130372f, 0.29073948f, -0.23935083f,
- -0.058463152f, -0.124855176f, 0.031086603f, -0.39749223f,
- -0.084497966f, -0.3912747f, 0.38970768f, 0.1117711f,
- 0.07462744f, -0.08238401f, -0.21798971f, -0.14923714f,
- 0.23229237f, -0.1896615f, -0.26658937f, -0.21951461f,
- 0.23850441f, -0.02649164f, -0.23457225f, 0.11567377f,
- 0.12489242f, 0.20846534f, -0.38842762f, -0.24382186f,
- -0.30211952f, 0.11588516f, 0.23002319f, -0.7526559f,
- -0.09329939f, 0.05698157f, 0.018913401f, 0.15893528f,
- -0.29105157f, 0.28494406f, -0.6599804f, -0.7087611f,
- -0.09278686f, -0.15649731f, 0.43489733f, -0.9862935f,
- -0.42058378f, -0.6010658f, 0.2678604f, -0.42524037f,
- -0.8728936f, -0.08571212f, 0.0009050544f, -0.09788861f,
- 1.6829336f, -0.093793035f, -0.27233508f, -0.42911232f,
- -0.1417101f, 0.061521687f, -0.7366901f, 0.585583f,
- -0.36172324f, 1.3339931f, 1.5816587f, 1.0108571f,
- 0.84406555f, -0.19523928f, 0.6265568f, -0.5568335f,
- -0.08276194f, 0.5927004f, -1.0334198f, -0.14848381f,
- -0.12951224f, 1.028889f, -0.7391619f, 0.14463727f,
- 0.40324175f, -0.904096f, 0.40453717f, 0.7131071f,
- -0.99284285f, 1.0583549f, -0.07742344f, -0.8518291f,
- 0.20074858f, 0.6997964f, 0.4601901f, -0.64828426f,
- -0.3472982f, 0.5723569f, 0.62630576f, -0.19739147f,
- 1.1631132f, 0.35580304f, -0.27869734f, -0.7615167f,
- 0.1117386f, 0.026188988f, -0.914157f, -0.5013694f,
- -0.5667545f, -0.34290963f, 0.3105646f, -0.08548017f,
- -0.3806787f, -0.0073340074f, -0.05987275f, 0.0006121755f,
- 0.6471124f, -0.4374903f, -1.20055f, -0.055029232f,
- -0.0719591f, -0.72581327f, -0.11503035f, -0.4166544f,
- 0.32489055f, -0.67653215f, -1.3371906f, 0.44303623f,
- -0.62133986f, -0.04227854f, 1.7528225f, 0.7513945f,
- 0.236208f, -0.14071135f, 0.2109171f, -0.26626816f,
- 0.90282303f, -0.8206861f, 2.3818395f, 1.5156224f,
- -0.3142489f, 0.014541436f, -0.088439666f, -0.14142625f,
- -0.32519853f, -0.06059172f, -0.109074235f, -0.01198102f,
- -0.19187595f, -0.3182718f, 0.9163231f, -0.012283807f,
- -0.21753083f, -0.19417338f, 1.3679692f, -0.07442334f,
- -0.26297215f, -0.1899094f, -0.21156532f, -0.08626601f,
- -0.013559078f, -0.11695432f, -0.14765719f, 0.08685829f,
- -0.26171312f, -0.112410426f, -0.2114959f, 1.4814451f,
- 1.3329538f, -0.05524541f, 0.754913f, -0.020505223f,
- -0.0021258914f, -0.08187226f, -0.4009018f, -0.23540197f,
- -0.43479306f, -0.27041352f, -0.09637592f, -0.16448279f,
- -0.14030203f, -0.27455878f, -0.048223555f, -0.15089874f,
- -0.33818913f, 0.94155955f, -0.15442869f, -0.22915687f,
- -0.1377937f, 0.37114137f, 0.40559143f, -0.08506112f,
- 0.012582877f, -0.20444638f, -0.11493526f, -0.115319885f,
- 0.18390366f, -0.031187909f, -0.032709f, -0.09117981f,
- 0.026239205f, -0.11065731f, 0.44859108f, -0.10296126f,
- -0.08016613f, -0.23115584f, -0.15242508f, -0.29978704f,
- -0.14117754f, -0.19976127f, -0.16330266f, -0.054808654f,
- -0.19940002f, -0.2121338f, -0.040035922f, -0.13514428f,
- -0.20212795f, -0.14455931f, -0.43153653f, -0.20123148f,
- -0.066452034f, 1.2996639f, 1.2094126f, 0.022999942f,
- -0.058377188f, -0.1103805f, -0.16660045f, 0.006570653f,
- 1.9679648f, -0.0017114935f, -0.16153443f, -0.2849549f,
- -0.09784363f, -0.08378339f, -0.07024177f, -0.08464118f,
- -0.03929748f, -0.1216627f, 0.6015996f, -0.1570687f,
- -0.06645245f, 0.043394282f, -0.28028587f, -0.090576544f,
- -0.29764247f, -0.088364124f, -0.27371582f, -0.04703137f,
- -0.042431034f, 0.04235019f, -0.14108235f, -0.39012945f,
- -0.12285795f, -0.0587379f, -0.062406015f, 1.0270125f,
- -0.09205075f, -0.10249022f, 0.642366f, 0.7120161f,
- -0.06839489f, -0.05020134f, -0.081062555f, -0.37947518f,
- -0.06480002f, -0.09382491f, -0.08921949f, -0.1147676f,
- 0.5766359f, -0.15279733f, -0.18992683f, -0.08851649f,
- -0.24891815f, -0.15401964f, -0.07795846f, -0.14433789f,
- -0.48399583f, -0.18643212f, -0.0723601f, -0.37744635f,
- -0.10583535f, -0.08878775f, 0.6365733f, 0.80128384f,
- -0.101385f, 0.3968146f, -0.20975979f, -0.11495628f,
- -0.14345983f, -0.02168061f, -0.09509327f, -0.09367446f,
- -0.029693985f, -0.22212417f, -0.27190775f, -0.20917438f,
- -0.21654005f, 0.0030441738f, -0.3401374f, 0.5072916f,
- -0.17215097f, -0.17774512f, -0.13701849f, -0.09408228f,
- -0.08442589f, -0.06257961f, -0.03675375f, -0.08410633f,
- -0.067764476f, -0.14214064f, 0.7950402f, 0.22419326f,
- -0.15597065f, -0.06233684f, -0.08543232f, -0.14217062f,
- -0.079136774f, -0.26203078f, -0.048577152f, 0.6554676f,
- -0.030333271f, -0.030176302f, -0.05380925f, -0.11898572f,
- -0.068299234f, -0.08592791f, -0.10283964f, -0.099229574f,
- 0.71672827f, -0.11408568f, -0.36277422f, -0.09150463f,
- -0.061160214f, -0.16880155f, -0.05676354f, -0.121809326f,
- -0.058232043f, -0.11831048f, -0.24502432f, -0.057298884f,
- 0.654107f, -0.09462272f, -0.04855136f, -0.0150308395f,
- -0.07296246f, 0.75546366f, -0.19270726f, 0.79699546f,
- -0.2512139f, -0.045797125f, -0.005112976f, 0.6215531f,
- -0.10503175f, -0.110065795f, -0.07489892f, -0.068080954f,
- -0.08979587f, -0.0052138874f, -0.08332907f, 0.63606834f,
- -0.11700663f, -2.9360719f, 7.417647f, 1.2830306f,
- 0.43933985f, 4.55941f, 6.5437975f, 0.98566586f,
- -0.16722292f, -4.69681f, -1.767284f, 5.3091474f,
- 5.723231f, -3.471847f, 2.762686f, -3.5397062f,
- 2.1237185f, -0.9885293f, -4.246712f, -1.7657958f,
- 0.24101901f, 0.8379823f, 2.967348f, -2.7045238f,
- 4.665987f, -4.658255f, -0.95576584f, -4.049722f,
- 0.9191266f, -0.4501422f, -0.4722458f, 0.5841199f,
- -1.3575604f, 6.383036f, 0.06028108f, 1.4320763f,
- -2.1812222f, -0.14482982f, 0.16232349f, 0.66108084f,
- 2.166708f, -1.1809461f, -1.983383f, -0.3077051f,
- 0.85189605f, -3.1156313f, 5.3507605f, 0.014805271f,
- 0.35668522f, -3.5633013f, -3.7984338f, -3.365382f,
- 5.309252f, -0.91856855f, -5.677884f, -3.4302666f,
- -2.153246f, -1.2517222f, -2.9774559f, -0.034497518f,
- 0.6259106f, -4.668775f, 3.5175645f, 2.6141045f,
- -4.206535f, 0.7469843f, 1.6842898f, 5.5866284f,
- -0.76397586f, 1.5631874f, -4.0994334f, -4.05738f,
- -2.1315036f, 4.493727f, 2.0073547f, 4.5922565f,
- -2.56662f, 0.272414f, -0.43489605f, 2.5213857f,
- -0.013438602f, -2.0522149f, -1.1633118f, -1.2098055f,
- -2.4337883f, -3.686609f, 0.77388746f, 1.8082199f,
- -1.6000379f, 0.4753603f, 3.1224833f, -0.30001932f,
- -3.4680626f, -2.9185934f, 0.5037284f, 0.8194583f,
- 0.799107f, -2.2182198f, -2.2905052f, 0.9717309f,
- 0.4704152f, -3.1092024f, 6.839785f, 2.5561244f,
- -2.3920655f, -2.9273207f, 1.2452544f, 3.2615304f,
- -0.1439213f, 5.189765f, -0.23962474f, -0.19947192f,
- -0.41560143f, 0.118623935f, 0.0012575939f, 0.0061752694f,
- -0.07788626f, -0.25022656f, 0.6530863f, -0.29118943f,
- -0.46167684f, 0.15550077f, -0.5853621f, -0.21942838f,
- 0.29900455f, -0.27979735f, -0.30388165f, -0.42507935f,
- -0.11759697f, -0.23405613f, 0.3121268f, -0.2569767f,
- -0.49683732f, -0.0737465f, 0.6383602f, -0.18969218f,
- -0.43858743f, -0.034785774f, -0.26909798f, -0.27321976f,
- -0.18362677f, -0.23460504f, -0.256411f, 1.5078452f,
- -0.25648886f, -0.2817091f, 0.3029941f, 0.7349207f,
- 1.2773894f, 1.0461065f, -0.75892717f, -0.028989669f,
- -0.12044626f, -0.31926662f, 0.9342633f, -0.34664568f,
- -0.073781125f, 0.3758208f, -0.53936565f, 0.17775619f,
- 0.469314f, -0.45094758f, -0.24098027f, -0.5068926f,
- -0.44791943f, -0.3460319f, -0.050827272f, -0.15085253f,
- -0.27311116f, 0.5360011f, -0.1694382f, -0.28784856f,
- 0.824027f, -0.21573362f, -0.08276362f, -0.4081254f,
- -0.25016063f, -0.14878187f, 0.48778498f, 0.4993979f,
- 0.6161539f, -0.47287282f, -0.5924905f, -0.6505962f,
- -0.19002163f, 1.6355854f, -0.25795916f, -0.12699933f,
- 0.28257158f, 0.38580483f, -0.44573328f, -0.073491246f,
- 0.7550106f, 1.5545108f, 0.029535022f, 0.30055743f,
- -0.49789235f, 0.2907997f, -0.07809363f, 0.07121975f,
- -0.29318932f, -0.25164917f, 0.06456088f, 0.34209034f,
- 0.9511694f, -0.10888153f, -0.36110345f, -0.3017654f,
- -0.2279373f, -0.0061461306f, 0.03422336f, -0.18055609f,
- -0.43302682f, 1.0084068f, 0.28340825f, -0.5088862f,
- 0.045828287f, 0.23757441f, -0.61438847f, -0.18214181f,
- 0.17983477f, -0.7190359f, 0.0931693f, 1.155613f,
- -0.41913882f, -0.05017795f, 0.82609135f, -0.41810474f,
- -0.51421535f, -0.24071075f, 0.25156054f, 0.27987754f,
- -0.51987064f, -0.56087047f, -0.15824138f, -0.070240214f,
- 0.101017945f, 0.04923886f, -0.5417319f, 0.019485071f,
- 1.4682062f, -0.60885036f, -0.48154965f, -0.28437594f,
- 1.3924737f, -0.48630914f, 0.66361594f, -0.48640767f,
- -0.3879053f, 0.61486727f, 0.78167033f, 0.3511713f,
- -0.21695213f, -0.24461484f, -0.30357832f, -0.21232876f,
- -0.25644735f, 0.49354628f, 0.17684633f, -0.2394912f,
- 0.82525814f, 1.2693895f, 0.0025586889f, -0.6015824f,
- -0.16281028f, -0.063414104f, -0.030329892f, -0.022853998f,
- 0.9561334f, 0.31957698f, -0.08777725f, -0.09485205f,
- -0.53158736f, -0.5537853f, -0.10326844f, -0.1403512f,
- -0.6553209f, -0.052374102f, 0.077941716f, -0.104090154f,
- -0.2823853f, 0.6463097f, 0.09966926f, 0.8930202f,
- -0.57824796f, -0.16422468f, 0.01172114f, -0.25232407f,
- -0.48824716f, -0.5433899f, -0.21597189f, -0.010178311f,
- -0.031052759f, -0.6156893f, 0.26890907f, 0.07690539f,
- -0.24305418f, 0.045159418f, 1.0014454f, -0.030104263f,
- -0.28299156f, -0.12634473f, -0.12735106f, -0.049461663f,
- 0.34811282f, -0.21690482f, -0.026448093f, 0.96547496f,
- 0.64899164f, -0.09128104f, -0.24945259f, -0.10855101f,
- 0.0340845f, -0.08331121f, 0.794807f, 1.0249598f,
- -0.33135918f, -0.0743035f, -0.35831964f, -0.13636105f,
- -0.18112466f, 0.26270574f, -0.17938232f, -0.3211616f,
- -0.07683446f, -0.3126213f, -0.33509678f, -0.53839725f,
- -0.083560124f, -0.060549404f, -0.023496868f, 1.126115f,
- -0.04796566f, -0.06740694f, -0.10078889f, 0.8696441f,
- -0.09328896f, -0.059003033f, -0.042979967f, -0.50733316f,
- -0.05074225f, -0.051396243f, -0.05519288f, -0.07080653f,
- 1.4913118f, -0.13459514f, -0.19912656f, -0.07449951f,
- -0.27856103f, -0.17237335f, -0.06470305f, -0.055739317f,
- -0.5560634f, -0.11645225f, -0.013472242f, -0.22558822f,
- -0.09673724f, -0.06858356f, -0.15660723f, -0.11514374f,
- -0.081430934f, 0.7517176f, -0.25518316f, -0.055587597f,
- -0.053383272f, 0.34412012f, -0.16549154f, -0.3551076f,
- -0.024742212f, -0.29804474f, -0.281088f, -0.093390815f,
- -0.09093288f, -0.010429024f, -0.3280106f, 1.4273076f,
- -0.103272215f, -0.10719001f, -0.12070635f, -0.1167389f,
- -0.038120385f, -0.029838953f, -0.0019892596f, -0.07161039f,
- -0.047242474f, -0.12938026f, 1.2063516f, 0.5499403f,
- -0.10382478f, -0.0657449f, -0.09691487f, -0.124650024f,
- -0.035071753f, -0.12141817f, -0.0035622872f, -0.02741969f,
- -0.049641334f, 0.033740107f, -0.034895293f, -0.03854355f,
- -0.08791392f, -0.044074316f, -0.08532671f, -0.20651628f,
- 0.17180352f, -0.09435528f, -0.5483845f, -0.20823766f,
- -0.058974437f, -0.108081765f, 0.25099787f, -0.15589206f,
- -0.09329981f, -0.0670667f, -0.16538277f, -0.018244635f,
- -0.09065423f, -0.061861686f, 0.0013382526f, -0.038582418f,
- -0.038146853f, 1.1508734f, -0.32107368f, 0.3459198f,
- -0.13881679f, -0.07416676f, -0.017252535f, 0.17631476f,
- -0.12319713f, -0.056095306f, -0.08236915f, -0.109352104f,
- -0.011383761f, -0.008003356f, -0.059236765f, 0.6634414f,
- -0.16523887f, 3.2493489f, -0.83198607f, 4.3695226f,
- -0.23635542f, -2.4146416f, -0.6643497f, 0.10467811f,
- 0.3745251f, -2.1517324f, 2.112686f, 4.6391516f,
- 0.22490591f, 4.989621f, -3.0274765f, -0.071626894f,
- -0.5503402f, -0.45265418f, 5.4162464f, 2.3064508f,
- 0.43164498f, -0.5356831f, -0.2789652f, 1.3130108f,
- -0.6905482f, -0.71338433f, -0.4790786f, -4.5521407f,
- 0.24255411f, -2.0010889f, -2.2413158f, -0.07256683f,
- -0.66022414f, -1.2224905f, -0.121300474f, -0.8076443f,
- -0.88721627f, -0.7010758f, -0.2932995f, -1.8788337f,
- -1.6588477f, -0.8523685f, -1.4967486f, 0.34407148f,
- -2.5194633f, 4.0863433f, 8.339587f, -0.15185493f,
- -0.89419055f, -2.6330602f, 3.6660094f, 2.499951f,
- -0.79089177f, 4.1003623f, -0.42614588f, 4.060239f,
- -3.3253777f, -1.5813466f, -1.6090637f, 0.6266538f,
- -0.2573581f, -1.3914815f, -1.7670588f, -3.078264f,
- 0.9937327f, -1.3677309f, 0.021288423f, -1.0951452f,
- -1.3107287f, -0.8011009f, -0.14263926f, -1.3486457f,
- 5.9875093f, -1.8756752f, -1.6681067f, 2.0772924f,
- -0.40502015f, 0.20402578f, 0.030309007f, 0.20063396f,
- 0.5934352f, -0.849473f, -1.8203727f, -0.77699316f,
- -1.7634451f, 2.31134f, 0.47461015f, -1.4169213f,
- 1.7377629f, 1.9731216f, 2.9827678f, -4.629668f,
- 2.7919686f, -2.852662f, -0.34117642f, -0.64497143f,
- 0.6980269f, -0.25371242f, -0.6521596f, -3.6128938f,
- 0.15677688f, 0.20772271f, -1.2663095f, 1.1095146f,
- -1.2833093f, -0.49311414f, 2.36679f, -0.047373127f,
- -0.11140971f, 1.3916476f, -0.3222247f, -0.318744f,
- -0.16535243f, -0.112748906f, -0.41860875f, -0.12650205f,
- -0.01011773f, -0.024063969f, -0.087818086f, -0.04910701f,
- -0.342707f, 0.012591901f, 0.08244142f, -0.33474544f,
- 0.03966115f, -0.2838756f, 0.92707396f, -0.035671517f,
- -0.09667311f, -0.29325056f, 0.85498077f, 0.17510204f,
- -0.047266793f, 0.14086396f, -0.07402087f, 0.40540564f,
- -0.0965102f, -0.16724116f, -0.027127651f, -0.053148538f,
- -0.034253847f, 0.020938907f, -0.064478874f, 0.4823128f,
- 0.10690623f, 0.08300567f, -0.22294772f, 1.5095601f,
- -0.14127763f, -0.24698359f, -0.07866863f, 0.22515924f,
- -0.13544424f, 0.06378123f, -0.25768828f, 0.15853289f,
- -0.12752607f, 0.5564362f, 0.033855066f, -0.2536845f,
- -0.010903843f, -0.32084423f, -0.095260076f, 0.2876785f,
- -0.17867664f, -0.15312643f, -0.24605231f, -0.10509935f,
- 0.66530025f, 0.8501762f, 0.41399455f, -0.08395541f,
- -0.37856367f, 0.3388988f, 0.103469305f, 0.28638625f,
- -0.2906751f, -0.05728423f, -0.08380238f, -0.11146603f,
- -0.3352914f, -0.204873f, -0.2656677f, -0.17685403f,
- 0.09509693f, -0.22999907f, -0.17741139f, -0.00033889833f,
- -0.20452857f, -0.14450054f, -0.12551051f, -0.2441675f,
- 1.7408111f, -0.34636196f, -0.24990416f, -0.12121512f,
- -0.15501022f, -0.02907495f, -0.31558067f, -0.41508868f,
- -0.053318724f, -0.13667527f, 0.13141605f, 1.1875167f,
- -0.09772618f, -0.081181884f, -0.1816482f, -0.0045444034f,
- 0.58887327f, -0.24677965f, -0.084220715f, -0.024565116f,
- -0.15368824f, -0.05213556f, -0.068622254f, -0.104785256f,
- -0.19265898f, 0.07406227f, -0.25053158f, 0.17343001f,
- 0.33320215f, -0.3741788f, -0.11155209f, -0.16540346f,
- 0.12549582f, -0.28318307f, 0.61143976f, -0.26650915f,
- -0.35826f, -0.5445002f, -0.011573227f, -0.3910991f,
- -0.21620543f, 0.47048634f, -0.23129f, -0.045362376f,
- -0.2001089f, 1.1966714f, -0.34778705f, 0.12173801f,
- 1.0352737f, -0.047508903f, -0.2442855f, -0.026523534f,
- 0.61543137f, -0.3231377f, 0.16111301f, 0.029239977f,
- -0.020463632f, 0.020401673f, -0.1524035f, -0.019964743f,
- 0.82906026f, 0.12848325f, -0.16804615f, 0.4428795f,
- 0.017808048f, 0.61024475f, 1.4540994f, -0.33290854f,
- 1.0604022f, 0.93277f, -0.33582732f, 0.47502038f,
- -0.35833016f, 0.3151776f, -0.4007742f, -0.14921647f,
- -0.07069162f, -0.1235081f, -0.20444229f, -0.31692788f,
- -0.49856248f, -0.38400728f, -0.42741883f, -0.31477064f,
- -0.19543779f, -0.099755764f, 0.6658764f, -0.6198956f,
- -0.2547231f, 0.763141f, -0.123319104f, -0.40261775f,
- -0.52407473f, -0.22594841f, -0.21468723f, -0.32721278f,
- -0.21038213f, -0.019356834f, -0.39806148f, 0.21717155f,
- -0.39397314f, -0.20888793f, -0.23548542f, 0.02817893f,
- -0.3747644f, -0.008234085f, 0.7315f, -0.2540953f,
- -0.27827835f, -0.2357267f, 0.6174205f, -0.14320904f,
- 0.81785804f, 0.19981162f, 0.40694696f, 0.1467925f,
- 0.05096987f, -0.38640872f, -0.18914811f, -0.4461208f,
- -0.06565536f, -0.93539995f, -0.07360351f, 1.047711f,
- -0.20246512f, -0.3785084f, -0.18803938f, -0.09102549f,
- 0.15531918f, -0.30128002f, 0.40945664f, 0.27780664f,
- -0.49326703f, -0.21780372f, 0.14857848f, 0.39604777f,
- -0.100641064f, -0.079164654f, -0.04139667f, -0.024719434f,
- -0.07675755f, -0.055283345f, -0.14898911f, 0.81257725f,
- -0.06053289f, -0.06231683f, -0.06785489f, -0.07808652f,
- -0.0559577f, -0.051058773f, -0.071022175f, -0.08431292f,
- 0.14775398f, -0.07150917f, -0.09686858f, -0.08630607f,
- 0.81414986f, -0.08367042f, -0.0429543f, -0.14651267f,
- -0.059862744f, -0.09100849f, -0.045729194f, -0.013355001f,
- -0.03170174f, -0.06274579f, -0.1718385f, -0.14865208f,
- -0.08667195f, 0.079898626f, -0.16583957f, -0.04850296f,
- -0.03064521f, -0.07662814f, -0.10657943f, -0.21590951f,
- -0.08919943f, -0.19883756f, 0.9100154f, 0.019300349f,
- -0.124826804f, -0.05468137f, 0.36156183f, 0.29918462f,
- 0.016270922f, -0.04993346f, -0.067955054f, -0.1219226f,
- -0.005049039f, -0.02330441f, -0.072066166f, -0.073758654f,
- -0.062370077f, -0.10861537f, -0.12605786f, 0.8309573f,
- 0.05685353f, -0.045839116f, -0.0971746f, -0.004503727f,
- -0.058943998f, 0.043747935f, -0.021757366f, -0.038570855f,
- -0.009876959f, -0.08282457f, 0.03489131f, -0.038912956f,
- -0.08811864f, -0.07138975f, -0.0327295f, -0.18486539f,
- -0.044050407f, -0.07501776f, -0.09918028f, 0.603364f,
- -0.03986403f, -0.060504783f, -0.018466594f, -0.078576244f,
- -0.06026426f, 0.9989428f, -0.008746259f, -0.0741501f,
- -0.18490286f, -0.056675322f, 1.4854984e-05f, -0.046616036f,
- -0.048745938f, 0.1318883f, -0.07651242f, -0.080799766f,
- -0.09319375f, -0.035905637f, 0.007126688f, -0.09144419f,
- -0.018386565f, -0.060347673f, -0.06649842f, -0.100561455f,
- -0.068719804f, -0.051193643f, -0.0618952f, 0.635109f,
- -0.1967069f, -0.15588313f, -0.18285145f, -0.69359905f,
- -0.17298102f, -0.35174623f, -0.12579f, 0.24984357f,
- -0.14923766f, 0.54478604f, -0.7761816f, -0.70619065f,
- -0.22727089f, -0.6743209f, -0.5080362f, 0.28268847f,
- -0.517086f, -0.08842097f, -0.69246215f, 0.5227362f,
- -0.5834853f, 0.14396848f, 0.30812135f, -0.65959483f,
- -0.03582512f, -0.09216117f, -0.14248134f, -0.7659162f,
- -0.05430202f, 0.069542445f, -0.097567596f, -0.14080186f,
- 0.16383943f, -0.41748035f, 2.654387f, 0.5596587f,
- 0.012933386f, 0.63640285f, 0.97101164f, 1.2532467f,
- 1.4301101f, -0.8056706f, 0.59102285f, -0.15668409f,
- 0.040951926f, 0.7665565f, -0.22659174f, -0.02103819f,
- 0.48755535f, -0.5010985f, -0.48504862f, 0.4449264f,
- 0.21524285f, -0.2785476f, -0.6850409f, -0.49711895f,
- -0.5313891f, -0.37246475f, -0.5589967f, 0.027461419f,
- 0.23304394f, 0.36522f, -0.65267164f, 0.78570753f,
- 0.15762044f, -0.41988498f, -0.06845066f, -0.3659318f,
- 0.11437183f, 0.43296948f, 0.368645f, -0.20950104f,
- -0.61319554f, -0.18283954f, -0.9866157f, -0.23005715f,
- 1.139369f, 0.43231186f, -0.35877028f, -0.36631218f,
- -0.026832983f, -0.42286372f, -0.020284675f, 0.5932596f,
- 0.97116196f, -0.54338497f, -0.1851281f, 0.24304295f,
- 0.3480946f, 0.040884178f, -0.25173408f, -0.40284315f,
- -0.4333857f, -0.42935237f, 0.13843648f, 0.8479549f,
- -0.10864669f, 0.32624894f, -0.5103778f, -0.34697255f,
- -0.0015234645f, 0.1039414f, 0.3675277f, -0.64461994f,
- 1.0405436f, 1.0578108f, -0.34989724f, -0.013788954f,
- 0.17013425f, 0.6367595f, -0.02392858f, -0.59964055f,
- -0.69455564f, 0.4255757f, -0.90242183f, 0.5809387f,
- -0.15851259f, 0.10627477f, 0.5269163f, 0.118443996f,
- -0.52124333f, 1.4273409f, -0.19601145f, -0.9218799f,
- -0.5385269f, -0.13524126f, 0.19419628f, 0.253651f,
- 0.14028467f, 0.73322874f, 0.7596742f, -0.08505828f,
- -0.3107628f, 1.6714996f, 1.600497f, 0.3007777f,
- -0.6153829f, 1.1290426f, -0.09214911f, -0.17133752f,
- 0.33404303f, -0.57717633f, 0.50510037f, 0.25372803f,
- 0.6395591f, -0.27592453f, -0.6460075f, 0.1845208f,
- -0.35913622f, 1.2934179f, 0.36541992f, -0.18174964f,
- -0.16719998f, -0.53856343f, -0.5249155f, -0.5058662f,
- 1.0242208f, 0.77575463f, 0.3516664f, -0.9622758f,
- 0.37943885f, 0.41953912f, 0.5746904f, 0.012621304f,
- -0.32548976f, -0.19329064f, 0.6002018f, -0.50319546f,
- 0.0012278322f, -0.06397019f, -0.37405518f, -0.7638915f,
- -0.21924087f, -0.4688643f, -0.19783299f, 0.009364976f,
- -0.33538538f, 0.06796912f, -0.74338686f, -0.08998163f,
- 0.18921076f, -0.6837038f, -0.34476754f, -0.682455f,
- -0.75167704f, 0.6163693f, -0.004064118f, -0.32677865f,
- 1.2386727f, -0.113761194f, -0.96553236f, -0.6460945f,
- -0.20456643f, -0.5673037f, -0.34323773f, 0.18649076f,
- -0.03732361f, -0.52453935f, -0.5043756f, -0.280785f,
- 0.9447144f, -0.1156984f, 0.3951227f, 0.91349304f,
- 0.10282173f, 0.36064157f, -0.24804695f, -0.6816688f,
- -0.33063614f, 1.186187f, -0.92086893f, -0.67136484f,
- -0.64463955f, -0.11909309f, -0.39353102f, -0.12263304f,
- 2.5878234f, 0.21407065f, -0.48291904f, -0.011753646f,
- -0.34181917f, -0.35893247f, 0.16344225f, -0.97426224f,
- -0.05286716f, 0.6004592f, 0.12222906f, -0.14015275f,
- 0.7530633f, -0.5701888f, -0.32981768f, -0.6207341f,
- -0.47554913f, -0.69895506f, -0.54431933f, 1.1425894f,
- 0.3760672f, 0.5973384f, -0.0655889f, 0.023098981f,
- 0.54889655f, -0.44721627f, 0.7924068f, 0.009349255f,
- 0.21057339f, -0.6421706f, -0.21903345f, -0.20144007f,
- -0.23107572f, -0.1690056f, 0.3699225f, 1.7552505f,
- 0.2613605f, 0.38883302f, -0.11824999f, -0.57384455f,
- 0.41932005f, -0.47952527f, 0.16175793f, -0.4645134f,
- 0.66748697f, -0.08544733f, -0.50870246f, -0.5886923f,
- -0.5332116f, -0.08669448f, 0.8682504f, -0.2712052f,
- -0.1707062f, 0.015392875f, 0.08834593f, 0.43885586f,
- 0.070908785f, 0.23618351f, 0.095158204f, -0.22715457f,
- 0.012320328f, 0.2004783f, 0.3146035f, -0.41278526f,
- -0.12908965f, -0.13068242f, 0.54535145f, -0.01631169f,
- 0.8203366f, 0.084239386f, 0.6479491f, -0.41293642f,
- 0.09581829f, -0.058509924f, 0.4457866f, 0.1680085f,
- 0.002588934f, -0.2623438f, 1.6550684f, 0.50758135f,
- -0.6375206f, -0.2708747f, 0.66183484f, -0.57083875f,
- -0.4009861f, -0.0012751506f, -0.7153751f, -0.30296087f,
- -0.07565536f, 0.16415164f, -0.22131127f, 0.8100964f,
- -0.9828568f, 0.3596644f, -0.35019636f, 1.0274247f,
- -0.03885198f, 0.6289656f, 0.4388146f, -0.19154802f,
- -1.0046338f, -0.7595624f, -0.06822518f, -0.380107f,
- -0.31162512f, -0.9859716f, 1.0961376f, -0.24878128f,
- -0.38563877f, 0.2054802f, 0.24382776f, -0.782815f,
- -0.3206224f, -0.27344185f, -0.3458312f, 0.17385007f,
- -0.32347378f, -0.6680408f, -0.17342184f, -0.17233942f,
- -0.03760989f, -0.33458734f, -0.16312903f, 1.7720572f,
- 0.145215f, -0.10641033f, -0.2165515f, -0.24701414f,
- 0.045689914f, -0.005965972f, -0.19357097f, -0.3234427f,
- 0.87316674f, -0.075759806f, -0.3187098f, -0.16661721f,
- 2.0515208f, 0.060517617f, -0.20937034f, -0.14694506f,
- -0.3353316f, -0.29235f, -0.094233036f, -0.17771219f,
- -0.26390636f, 0.49844578f, -0.24337384f, -0.17943226f,
- -0.32855144f, 0.6586753f, 0.18020836f, 0.95279735f,
- -0.16136366f, 0.087674946f, -0.102666646f, -0.12674214f,
- -0.20347509f, -0.11946039f, -0.04286386f, 0.8172888f,
- -0.1641867f, -0.15828224f, -0.062307473f, -0.12035761f,
- 0.027984357f, -0.026460188f, -0.14956534f, -0.1763685f,
- -0.22481214f, -0.024610668f, -0.18043302f, 0.5917245f,
- -0.1940063f, -0.14649948f, -0.169229f, -0.08159261f,
- -0.22712089f, -0.17749642f, -0.11947405f, 0.19561525f,
- -0.17164813f, -0.068342224f, -0.26817486f, -0.12344898f,
- -0.12443161f, -0.21252503f, -0.25240362f, -0.029219182f,
- -0.21218634f, -0.08305396f, 1.7680112f, 0.45936272f,
- -0.14881806f, 0.30453545f, 0.75825256f, -0.30416235f,
- -0.16611502f, 0.6914644f, -0.10551617f, -0.14651033f,
- -0.20446351f, 0.08602447f, -0.14730924f, -0.07992274f,
- 0.15578365f, 0.6360922f, -0.08870283f, -0.04752104f,
- -0.01793844f, 0.038283315f, 0.04208007f, 0.020013304f,
- -0.14753349f, -0.63554096f, -0.37232313f, 0.41501772f,
- -0.11553225f, -0.08251885f, -0.1285659f, 0.3170265f,
- -0.4379908f, -0.19364473f, 0.80589896f, -0.57572967f,
- 0.6734866f, 0.29555285f, 2.8491797f, 1.0783544f,
- 0.23160772f, 0.3838632f, 0.32587546f, -0.19965582f,
- -0.62361497f, -0.19334194f, 0.0867236f, 0.6255389f,
- 0.6695613f, -0.5767867f, -0.8055614f, -0.59436303f,
- 0.55133283f, -0.29470873f, 0.094465084f, -0.20093215f,
- -0.807509f, -0.20868099f, -0.7686701f, -0.32414538f,
- 1.2895329f, -0.87658894f, -0.6443934f, 0.969774f,
- 0.06955318f, -0.65840757f, 0.30503583f, -0.18884002f,
- -0.024605451f, 2.3509274f, -0.6082475f, -0.52623475f,
- 1.1752683f, -0.26323572f, -1.1456463f, -0.4122169f,
- -0.45670614f, -1.1767f, -0.8064345f, 0.59996575f,
- 0.031282205f, -0.42105934f, 0.8792798f, -0.33734867f,
- -0.09500109f, -0.4565834f, 0.8409596f, -0.47654018f,
- 0.12745944f, -0.12931567f, 1.4995502f, 1.4440975f,
- -0.41830507f, -1.1645752f, -0.8779915f, -0.22193131f,
- -0.18344346f, -0.94884837f, 0.70208305f, -0.27387738f,
- 0.7115777f, -0.28039846f, -1.2438499f, 0.74528927f,
- -0.27715746f, 1.2374766f, 0.7059456f, -0.31007016f,
- -0.13033223f, -0.24576557f, -0.44860598f, 0.2146104f,
- -0.37133038f, -0.21856207f, 0.54005176f, 0.09640648f,
- 0.4734302f, -0.26330137f, -0.45376244f, -0.4413179f,
- -0.73569506f, 1.1553972f, 1.1754336f, -0.38466874f,
- -0.32588243f, -0.3351695f, 0.9853702f, 1.9155335f,
- 0.34280264f, -0.35474664f, -0.46245944f, -0.36099857f,
- 2.151012f, -1.5967754f, -0.15510967f, -0.52613574f,
- -0.98247975f, -1.0398004f, -0.47499377f, -0.71776557f,
- 0.7739135f, -0.8853458f, 0.0042237616f, 0.19207068f,
- -0.3547116f, -0.09309435f, -0.2756582f, 0.23781072f,
- -0.05578745f, -0.0772447f, 0.18884532f, -0.035448212f,
- -0.2914102f, 0.33504233f, -0.4397298f, -0.3824476f,
- 0.42143628f, -0.37493157f, -0.33907226f, -0.24595267f,
- -0.3617337f, -0.578737f, 0.66571295f, -0.16713639f,
- -0.29108772f, 0.16796766f, 0.46589294f, -0.21960169f,
- -0.27075687f, -0.1942991f, -0.08664848f, -0.2296685f,
- -0.20894247f, -0.106237486f, -0.24422497f, 1.3562249f,
- -0.2423016f, -0.022928458f, 0.27609935f, 0.0041536028f,
- 1.0571799f, 2.303784f, -0.5616675f, -0.29398134f,
- 0.18206915f, 0.005284357f, 0.17893907f, -0.22232483f,
- -0.08483204f, 0.4624998f, -0.14891411f, 0.06800109f,
- 0.036200035f, 0.16384389f, -0.25533536f, -0.5215799f,
- -0.5113894f, -0.44873425f, -0.39653438f, -0.17473136f,
- -0.25868523f, 0.8599986f, -0.042011846f, -0.45061812f,
- 0.40142214f, -0.06632186f, -0.51675284f, 0.08880637f,
- -0.077954106f, -0.11780407f, 0.5839777f, -0.1741161f,
- -0.06570812f, -0.53837925f, -0.05631169f, -0.1615481f,
- -0.47854087f, 0.96934956f, -0.12818696f, -0.5166967f,
- 0.31132123f, 0.5405264f, -0.66567755f, 0.5113458f,
- 0.18924111f, 0.9078355f, -0.56540924f, 0.7686364f,
- -0.14168431f, 0.43369058f, -0.18189056f, 0.07754213f,
- -0.36218882f, -0.5183614f, -0.77408314f, 0.12405502f,
- 0.5339788f, -0.17728081f, -0.12519781f, -0.13576612f,
- -0.6436594f, -0.24316269f, -0.2572956f, 0.7020175f,
- -0.61175233f, 0.89430773f, 0.66425943f, -0.45652068f,
- 0.0051566046f, 0.1437964f, 0.8583364f, -0.058550753f,
- -0.0800835f, -0.030542595f, 0.84051925f, -0.037073564f,
- -0.1960574f, -0.18935724f, 0.5974451f, -0.11202957f,
- -0.050432112f, -0.06740208f, 0.2556606f, -0.0308727f,
- -0.03450173f, -0.049928598f, -0.07703484f, 0.86371875f,
- -0.11926897f, -0.06988518f, -0.06368371f, -0.30979958f,
- -0.112969175f, -0.034553334f, -0.1619048f, 0.28905398f,
- -0.31063354f, -0.051491864f, 0.1217766f, -0.08100787f,
- -0.07453777f, -0.057956535f, -0.1661975f, -0.112945445f,
- 0.40669924f, -0.14794853f, -0.06858976f, -0.1336027f,
- -0.13674709f, -0.14389792f, -0.20933442f, -0.042389352f,
- -0.0910488f, -0.33146945f, -0.05506176f, -0.17686796f,
- -0.013649271f, -0.17999935f, 1.2373143f, -0.055224635f,
- -0.12823905f, -0.097137645f, -0.11951992f, -0.07695379f,
- -0.04659627f, -0.0379294f, -0.054945607f, -0.060522806f,
- -0.06846248f, 0.040187575f, 0.23148207f, -0.07009838f,
- -0.05169014f, -0.06565858f, -0.09409733f, -0.055789877f,
- -0.09242994f, -0.056179337f, -0.08793601f, -0.037960175f,
- -0.029779464f, -0.05598786f, -0.021021152f, -0.111263484f,
- -0.0902543f, -0.081627905f, -0.1986794f, -0.018834664f,
- -0.05855816f, 0.26035598f, 0.9958224f, -0.039430305f,
- -0.1077066f, -0.23545526f, -0.10064534f, -0.05993942f,
- -0.24913877f, -0.09060418f, -0.048168052f, -0.078298494f,
- -0.099454574f, -0.03733617f, -0.0693643f, -0.046338838f,
- 0.8130984f, -0.19392365f, 1.2519735f, -0.15310246f,
- -0.04223386f, -0.017556861f, 0.9316549f, -0.092174165f,
- -0.120273486f, -0.04579627f, -0.1730681f, -0.11723757f,
- -0.0357312f, -0.09244046f, -0.077901065f, -0.20618269f,
- 0.25283375f, 0.17687227f, -0.57183427f, 0.36910236f,
- -0.32705075f, 0.29417914f, -0.06888298f, -0.11297269f,
- 0.24644776f, -0.77417135f, -0.6848491f, 0.54173434f,
- -0.75619394f, -0.5648228f, 0.8929561f, -0.32402518f,
- -0.41448757f, -0.12784657f, -0.2091412f, -0.72771525f,
- 0.44951427f, -0.17811236f, -0.18560134f, 0.0035433231f,
- 0.47171143f, -0.073201105f, -0.71996117f, 0.31867093f,
- 0.058300667f, -0.085373715f, -0.10338045f, 0.046935048f,
- -0.55665934f, 2.3366303f, -0.3692659f, 0.16002625f,
- 0.6027281f, 0.014281623f, 1.3307047f, 1.7488679f,
- -0.70902795f, -0.25545213f, -0.14826864f, -0.17813022f,
- 0.5730056f, -0.20897883f, 0.33180258f, 0.3536007f,
- 0.004360649f, 0.06241795f, 0.75670683f, 0.224112f,
- -0.6048232f, -0.74232423f, -0.71931076f, -0.5834445f,
- -0.41625795f, -0.35367224f, -0.3126076f, 0.17521244f,
- -0.120382f, -0.44553176f, 0.8415658f, -0.37189215f,
- -0.6841877f, -0.1320558f, -0.40576625f, -0.26065302f,
- 0.83448416f, 0.39618346f, 0.22714496f, -0.5723813f,
- -0.08386428f, -0.9782629f, -0.17008245f, 0.80578053f,
- -0.21238442f, -0.49209517f, 0.42222422f, 0.13454379f,
- -0.5617698f, 0.14940834f, 0.059609022f, 0.7742956f,
- -0.47703484f, 0.23402844f, -0.38310373f, 0.3102058f,
- -0.19097582f, -0.104172744f, -0.76501316f, -0.44780642f,
- -0.20269468f, 0.21240881f, 0.91651964f, -0.061060667f,
- -0.24909063f, -0.37173182f, -0.014151138f, 0.34525624f,
- -0.06267062f, 0.16691172f, -0.6132017f, 1.0036784f,
- 1.2660526f, -0.3843422f, 0.18575902f, 0.58723855f,
- 0.33620113f, -0.22840904f, -0.19151507f, -0.16271935f,
- 0.42888528f, -0.20816828f, -0.19622624f, 1.3024986f,
- -0.045826852f, -0.026480744f, -0.204104f, -0.30769894f,
- -0.10256694f, -0.04993364f, -0.21201478f, -0.30866176f,
- -0.30486903f, 0.5356701f, -0.2902586f, 0.057707388f,
- -0.2335143f, -0.011927023f, -0.12739183f, -0.009080477f,
- -0.22770299f, -0.17585547f, 0.044223297f, -0.15247594f,
- -0.072915375f, -0.021809436f, 0.028654799f, -0.08935762f,
- 1.3727816f, -0.167461f, 0.44712326f, -0.009710546f,
- -0.04542405f, -0.18835872f, 0.98122066f, -0.051206954f,
- -0.26761934f, -0.08600599f, -0.043474942f, -0.09061073f,
- -0.16424638f, -0.20645161f, 0.04539659f, -0.07533322f,
- 0.11041837f, -0.24917327f, -0.28406382f, 0.041345265f,
- -0.030915858f, -0.20868903f, -0.030710181f, 0.0013510184f,
- 0.042593f, -0.08683754f, -0.19203039f, 0.87950987f,
- -0.00438865f, 0.13944687f, 0.040647227f, -0.17750101f,
- -0.06775155f, -0.062398966f, -0.015438208f, -0.072928436f,
- 1.1455705f, -0.048084017f, -0.21739703f, -0.15788579f,
- -0.21532245f, 0.06849368f, -0.41462237f, -0.03406558f,
- -0.26757902f, 1.4421564f, -0.036526933f, -0.21462107f,
- -0.08569348f, 0.17976919f, -0.330147f, 0.84907573f,
- -0.28511763f, -0.19982779f, -0.010992601f, -0.093121916f,
- -0.10988649f, 1.0099573f, -0.22581223f, -0.25430652f,
- -0.1392582f, -0.0664731f, -0.32662904f, -0.18895958f,
- -0.107851356f, -0.34788802f, 0.2199519f, 0.3316652f,
- -0.25369167f, -0.27701366f, -0.19845755f, -0.29695857f,
- 0.23892677f, -0.15676124f, -0.05566864f, -0.13779084f,
- 0.5905695f, 0.028246215f, -0.1880463f, -0.158211f,
- -0.093261994f, -0.21338391f, -0.12827787f, -0.1248872f,
- -0.23330842f, 0.27136317f, -0.07161912f, -0.08860815f,
- -0.1454992f, 0.045975402f, -0.039693728f, -0.12860975f,
- -0.069132864f, -0.13061541f, -0.24247862f, -0.09513792f,
- -0.15155111f, -0.12337352f, 1.9032909f, -0.052695416f,
- -0.023909645f, -0.26015466f, 0.065147f, -0.16039348f,
- -0.18719393f, -0.28195515f, -0.067011856f, -0.12260026f,
- -0.23486756f, -0.18357794f, -0.10384673f, 0.24335086f,
- -0.34279415f, -0.08243848f, -0.1415118f, 1.368997f,
- -0.017992727f, -0.36591917f, -0.031406403f, -0.4369986f,
- 1.0178086f, -0.054738052f, -0.036603298f, -0.009158183f,
- 0.92351335f, -0.025364432f, -0.05366998f, 0.04193047f,
- 0.0029592875f, -0.25004998f, -0.15179779f, -0.030619493f,
- -0.038603045f, -0.12015034f, -0.135503f, 0.011338909f,
- -0.28314266f, 1.1493077f, 0.060987405f, -0.14128809f,
- -0.05792581f, -0.10161759f, -0.075040564f, -0.04538528f,
- 0.06956525f, -0.10002697f, -0.04886154f, -0.04252012f,
- 0.0030279835f, -0.047484003f, -0.15519822f, -0.1097196f,
- -0.056154016f, -0.26957414f, -0.14621131f, 0.031601448f,
- 0.023409266f, -0.2908017f, -0.0981981f, -0.11827429f,
- 1.4680561f, -0.18534367f, -0.070913956f, 0.51700115f,
- -0.10618579f, -0.05003601f, -0.34164247f, -0.0844686f,
- 0.03617472f, -0.0065685376f, -0.07554547f, 0.675076f,
- -0.23642074f, -0.17815247f, -0.107637405f, -0.0053464207f,
- 0.11566401f, -0.28004172f, -0.062665306f, -0.12347386f,
- -0.17128979f, -0.12777811f, -0.16823606f, -0.04019591f,
- -0.051530566f, 1.2629687f, -0.20550388f, -4.3168464f,
- -0.24886626f, -1.431114f, 0.05540148f, -2.5580401f,
- 1.3831843f, 2.3626356f, -0.003909311f, 1.7558163f,
- 0.16587234f, 0.8989113f, -2.1229873f, -2.347771f,
- -1.0293839f, 6.8205566f, 0.0730506f, -0.07527148f,
- 4.3677545f, -0.5455533f, -1.974138f, 0.18869023f,
- -1.5495026f, -1.2175992f, 0.16089408f, 1.401868f,
- 0.14134784f, 2.3598516f, 0.25893706f, -2.9612389f,
- -2.8121846f, 0.37797537f, 1.1979729f, -1.9995649f,
- 0.11241398f, -1.5454179f, 1.1737751f, -0.6895833f,
- -1.2254364f, 2.894213f, 2.3188658f, -3.3266892f,
- 1.5436358f, 0.108194105f, 0.4806176f, -1.7371562f,
- -1.2830426f, 0.22276694f, -1.620491f, 4.261439f,
- 0.90288895f, -0.65445954f, -1.426307f, -2.7032154f,
- -1.8229043f, -0.40056947f, 1.9999362f, 0.97119737f,
- 4.3827453f, -0.48015392f, 0.48166102f, -2.8060193f,
- -0.073997624f, -1.5639548f, -0.29844198f, 0.036378663f,
- 3.0989087f, 0.12699266f, -1.3432045f, 1.5167955f,
- -1.0569842f, -0.65430695f, 1.7084807f, 0.4692697f,
- 3.5047426f, 0.3088521f, 1.7873335f, -1.046757f,
- -0.118189275f, 0.5911035f, 0.18856372f, 1.2541101f,
- 4.7505903f, 2.3271286f, 1.9932852f, -2.9223294f,
- -0.27396408f, 0.07537805f, -1.0606399f, -0.85909736f,
- 2.7495646f, -1.2174144f, 1.764061f, 1.4387304f,
- 0.09071019f, -2.0339723f, -0.08251524f, -1.1719716f,
- 0.7349904f, 4.021179f, -0.06853537f, -4.849576f,
- -2.9034114f, -1.591728f, 2.089637f, -3.1576686f,
- -1.3907044f, -2.6523864f, 0.07671407f, -1.2163798f,
- -0.07359346f, -0.08668753f, -0.09085469f, 0.017082071f,
- -0.08985676f, -0.11185875f, -0.09880342f, 0.029206404f,
- -0.016286856f, -0.07524284f, -0.08198292f, 0.47820142f,
- -0.03137328f, -0.07714865f, -0.07571334f, -0.067629434f,
- 0.21930242f, -0.1429074f, -0.20590474f, -0.08309826f,
- 0.5917472f, 0.005481364f, -0.06757667f, -0.1386418f,
- 0.5646645f, -0.108243525f, -0.086436845f, -0.15647627f,
- -0.060578432f, -0.08247181f, -0.09058331f, -0.10174875f,
- -0.07713522f, 0.5127588f, -0.14212419f, -0.06696708f,
- -0.14584361f, 1.0354104f, -0.06953503f, -0.20755054f,
- -0.066146545f, -0.028360311f, 0.06889669f, 0.016393527f,
- -0.1418715f, -0.028697541f, -0.050186716f, 0.4988721f,
- -0.05107486f, -0.101799786f, -0.07933962f, -0.10999379f,
- -0.050055157f, -0.03158206f, -0.078531794f, -0.08713288f,
- -0.060743734f, -0.07998166f, 0.033845607f, 0.7490313f,
- 0.086723655f, -0.06903709f, -0.115419805f, -0.074922904f,
- -0.009422413f, 0.0116548035f, -0.080853306f, -0.021401875f,
- -0.059212353f, -0.02900329f, -0.05556725f, -0.02860889f,
- -0.0885862f, -0.085872956f, -0.064990796f, -0.21712591f,
- -0.0643311f, -0.042169385f, 0.49360728f, 0.09765816f,
- -0.0660171f, -0.08976767f, 1.0600802f, -0.14567176f,
- -0.037014004f, 0.16465048f, -0.17666201f, -0.068531305f,
- -0.14201103f, -0.08385357f, -0.024248812f, -0.049390864f,
- -0.07698153f, 0.49063954f, -0.20889933f, -0.07089814f,
- -0.073463246f, -0.0807254f, -0.011625342f, -0.19396365f,
- -0.08568955f, -0.097195044f, -0.07670138f, -0.057440586f,
- -0.0749174f, -0.057740826f, -0.08242015f, 0.24813698f,
- -0.1661102f, 3.6731f, 1.1918759f, -0.8780679f,
- -0.10124991f, 3.1446059f, -0.6971279f, -1.1949688f,
- -0.095232055f, -1.8547423f, -1.3424116f, -1.8010441f,
- -0.7013633f, 1.2372379f, -0.81290853f, 1.9391007f,
- -0.9062321f, 0.49327886f, 2.9787655f, 1.2946081f,
- -0.8306096f, -0.11101006f, -0.52624744f, 0.45194706f,
- -1.934489f, -0.60675496f, -0.47821927f, -0.09266448f,
- -0.2381736f, -1.6736f, -1.8030536f, -0.28228125f,
- 2.4630873f, -0.638226f, -0.14869046f, -1.359076f,
- -4.579007f, -1.3367974f, -0.18328483f, 0.6602551f,
- -1.330997f, 2.5504007f, 0.429872f, 0.074421495f,
- -2.2314956f, 1.9423418f, 2.4958863f, 0.20023459f,
- 0.3403407f, 4.75503f, 4.0494385f, 3.5329075f,
- -0.6882337f, 3.1716566f, 3.6320724f, 0.27711946f,
- -2.7652895f, 0.029787945f, -1.7705483f, -0.054495957f,
- 0.16389212f, -0.008755913f, 2.5298347f, -1.4101384f,
- 0.21967898f, -1.5492338f, -1.7267256f, -1.716968f,
- -0.33292118f, -1.717969f, -1.7068119f, 6.3889236f,
- -1.9824315f, -0.47809413f, -1.7881655f, -0.7471201f,
- 1.4683284f, -0.5628763f, -1.7478974f, 1.027078f,
- 0.5941963f, -1.7425231f, 2.7673564f, 0.65283954f,
- -1.3281808f, -1.8015102f, 0.27141455f, -0.8302308f,
- 5.469293f, -0.4764163f, -0.9356305f, -0.22512823f,
- -0.023895506f, -1.1855983f, -0.23431231f, -1.338334f,
- -0.17689793f, 1.078155f, -2.5652318f, 0.8010266f,
- 0.025854954f, 3.2429273f, -2.9569576f, -1.2682651f,
- 0.10815208f, 0.13421017f, -1.1775419f, -0.16431786f,
- 0.017210174f, -2.0076933f, -1.1561013f, 2.2529395f,
- -0.6535061f, -0.1044888f, -1.6199961f, 0.41495577f,
- 1.9077429f, 1.5495837f, -1.5090318f, -1.0511693f,
- 5.2863235f, -0.1858281f, 0.7282059f, -2.4932678f,
- 1.6848266f, 1.972652f, -0.53303945f, 0.31275666f,
- -0.63367575f, -0.20547912f, 0.22068618f, -0.7165349f,
- -1.3619326f, 5.552196f, -1.0717317f, 1.2562604f,
- -1.3965939f, 1.3779693f, -1.1423243f, -1.5711361f,
- 0.52395236f, -0.9623952f, 0.18831152f, -0.27463368f,
- 0.8250733f, -0.12563594f, -1.5874671f, -0.49330857f,
- -1.8544326f, 4.7781878f, 0.54886687f, 0.6841308f,
- 0.8353607f, 1.8692322f, -2.3503385f, 1.9887958f,
- 0.85565704f, 1.2644293f, -0.6959518f, -1.7566197f,
- -2.0049534f, 0.9246352f, 2.1070392f, -1.3016248f,
- -1.9830322f, -2.7593164f, -1.2194784f, 0.9417308f,
- 0.2323362f, 0.7743562f, 1.2568893f, -2.7961514f,
- -1.424966f, -0.8219906f, -1.9414895f, 3.572039f,
- -2.0913305f, -0.96042466f, 2.8467674f, -0.7712584f,
- -1.6290495f, -2.0401282f, 2.8088295f, -1.6513517f,
- -2.1289403f, -1.208127f, 1.940771f, 3.5589206f,
- 1.3088957f, 0.45183805f, -0.5713082f, -1.027957f,
- -0.76495796f, -1.0387921f, 0.2461054f, 1.0788473f,
- 2.6320438f, -0.74531955f, -2.8921676f, -0.03143121f,
- -0.25720713f, 0.24268164f, -1.6701624f, 0.4995069f,
- -0.54359585f, 0.2937094f, -2.4054916f, -0.41559443f,
- 0.5241131f, -0.23202682f, -3.0114722f, -1.1641957f,
- -0.5638207f, 0.106554255f, -0.5123931f, -0.8979652f,
- 3.2366462f, 0.08196721f, 4.444518f, -0.06259689f,
- -0.33450896f, -0.14763285f, -0.4205563f, -0.28950304f,
- -0.77576846f, 0.53227943f, 0.44850776f, -0.37589377f,
- -0.3072115f, -0.059073724f, -0.21370003f, -0.21901844f,
- -0.54393184f, -0.58641475f, -0.23208618f, 0.7518133f,
- -0.5241223f, 0.10624801f, -0.83465976f, -0.09642914f,
- 1.5639068f, -0.55612284f, -0.46815133f, -0.4724137f,
- 0.12378365f, 0.031124895f, -0.122639075f, -0.19352186f,
- -0.23171085f, 1.2708188f, -0.103020996f, -0.51447076f,
- -0.17693104f, 2.8417432f, -0.28806293f, -0.45132315f,
- -0.454802f, -0.21391906f, -0.19921713f, -0.35537198f,
- 1.4092975f, 1.4423138f, 3.919447f, -0.419335f,
- -0.38433605f, 0.09175738f, -0.3864537f, -0.52750653f,
- -0.5047468f, -1.0184945f, -0.8278297f, -0.27164137f,
- -0.04158763f, -0.45525834f, -0.15944031f, -0.026521616f,
- -0.66158086f, 0.1304416f, 0.82900536f, 3.824954f,
- -0.36706346f, -0.41734704f, 4.028651f, 0.08966365f,
- 3.7075465f, -0.44909388f, 0.4534223f, -0.6792766f,
- -0.5956197f, -0.42047516f, -0.31450605f, -0.5311029f,
- -0.122758135f, -0.11698179f, -1.0400174f, -1.0178877f,
- -0.4353168f, -0.40116578f, 0.45234287f, -0.5230108f,
- -0.69381285f, 0.1835223f, -0.46963155f, -0.33560964f,
- -0.03586719f, 2.062213f, 0.0555504f, -0.77976567f,
- -0.5761823f, -0.023946784f, -0.32501066f, -0.23298149f,
- 0.27052367f, -0.42512324f, -0.40886405f, 1.4059507f,
- -0.051237796f, -0.23254468f, -0.4443852f, -0.49906063f,
- -0.13372438f, -0.32222295f, -0.27907786f, -0.64064837f,
- -0.34407055f, -0.7378993f, 0.31072235f, -0.3847739f,
- 0.77840286f, -1.5014623f, -1.6369667f, 0.15721892f,
- 2.310001f, 1.6780571f, -0.84452516f, -0.0037365658f,
- -0.030043738f, -1.4446723f, -2.4107285f, -0.30585098f,
- -0.9760401f, -1.522058f, -1.8837268f, -0.057901166f,
- 0.91551715f, -1.197007f, 1.272301f, 0.518048f,
- 0.44767168f, 1.2804598f, -2.5173817f, -1.285402f,
- -0.1446033f, 0.21932782f, -1.5994515f, -0.08048569f,
- -1.5461478f, -1.3743409f, 0.3367965f, 0.59793293f,
- -0.96541584f, -0.17938598f, -0.25899762f, -2.4993424f,
- 3.7861621f, 0.8685263f, 0.32286248f, -0.8386966f,
- 0.82897764f, -0.3816823f, 0.6157397f, -0.47600618f,
- -1.4087876f, 0.5339306f, 0.6141896f, 1.5369879f,
- -1.1329072f, 2.8894613f, 6.131606f, -1.7651651f,
- 2.0428774f, -0.044124477f, -1.6903048f, 1.6138542f,
- -0.49217358f, -1.6181629f, 0.114441745f, 0.07868073f,
- -0.8997363f, -2.2917824f, 0.47612783f, -0.22145548f,
- 0.4379871f, -1.4979626f, 1.306742f, -0.6269978f,
- -0.99029934f, -0.189361f, 4.113698f, -0.84382695f,
- 0.34869865f, -0.24937488f, -0.55380696f, 2.0434349f,
- 0.2995072f, -1.107016f, 1.3580266f, 0.2007551f,
- -0.78020656f, -1.2906488f, 0.7410638f, 0.3529165f,
- -1.3341801f, -0.13892464f, -0.46074846f, -1.4699724f,
- 1.8885388f, 1.9661734f, 1.4118576f, -1.0406173f,
- -0.36125627f, 0.425911f, 0.9285509f, -0.2971367f,
- 3.5788145f, -1.0758419f, 0.54847276f, 0.045025583f,
- -0.5043927f, -1.5574447f, 0.510544f, -0.46078518f,
- 3.1153083f, -0.36788052f, -0.71594995f, 0.8629354f,
- -2.0090997f, -0.09261695f, -0.04030692f, -0.092586756f,
- 1.0057175f, -0.09463941f, -0.101231255f, 0.59447837f,
- 0.71764845f, -0.04739154f, -0.07274321f, -0.10161236f,
- -0.40883014f, -0.022305872f, -0.09957483f, -0.08537533f,
- -0.11913863f, 1.1634334f, -0.12230817f, -0.18902598f,
- -0.06518236f, -0.17977642f, -0.14797439f, -0.11493504f,
- -0.08873729f, -0.42345977f, -0.12336724f, -0.017169485f,
- -0.1936536f, -0.06164696f, -0.09775351f, -0.21300812f,
- 0.6730627f, -0.07706275f, 0.47714815f, -0.14249925f,
- -0.06471867f, -0.06404842f, 0.17092016f, -0.11141843f,
- -0.25502458f, 0.0049186954f, -0.24975294f, -0.20645344f,
- -0.14156981f, -0.16339763f, -0.009144268f, -0.19147013f,
- 1.011594f, -0.18478268f, -0.17337438f, -0.11914083f,
- -0.10647544f, -0.104771666f, -0.0012048809f, -0.0023030143f,
- -0.05556736f, -0.07684619f, -0.15629049f, 0.7064602f,
- 0.34064645f, -0.12119072f, -0.056598656f, -0.14417525f,
- -0.11970901f, -0.029404746f, -0.15484911f, -0.027769716f,
- 0.60703295f, -0.049053393f, -0.07335732f, -0.046390034f,
- -0.049851365f, -0.06333611f, -0.0828848f, -0.11796604f,
- -0.12937586f, 0.58962154f, -0.11010461f, -0.36409235f,
- 0.08990689f, -0.05999607f, -0.12456095f, 0.14591037f,
- -0.15315439f, -0.0935054f, -0.0581339f, -0.18935508f,
- -0.0614902f, 0.5972278f, -0.1255121f, -0.018779743f,
- -0.029626636f, -0.075243935f, 0.109197296f, -0.20716187f,
- 0.3798646f, -0.2572378f, -0.07228504f, -0.03968359f,
- -0.090084374f, -0.09916183f, -0.098055534f, -0.058550783f,
- -0.06984982f, -0.063209385f, -0.021898052f, -0.06662524f,
- 0.6956958f, -0.116753064f, -0.26199383f, -0.9773308f,
- -1.1369494f, -0.43667504f, 0.15893255f, -1.1515857f,
- -0.4880996f, 0.574554f, -0.19744523f, -0.78930545f,
- 0.072843395f, 0.65452546f, 0.8738918f, -0.6940727f,
- -1.257824f, -0.6783757f, 0.88782537f, -0.63197905f,
- 1.8010767f, -1.0759754f, 0.969156f, 2.9260292f,
- -0.59735084f, -1.5745115f, -1.2379751f, 1.3596989f,
- -1.6962247f, 0.75249046f, -0.697698f, -0.6691517f,
- 0.42209643f, 0.42191496f, -2.4835668f, -0.17649966f,
- 1.5051452f, -1.3261797f, 1.3449857f, -0.29870632f,
- 1.7764349f, 0.49866235f, -1.661181f, -0.011293771f,
- 1.4164718f, 3.1416929f, -1.2430165f, -0.687653f,
- 0.39141482f, 1.0759271f, -2.2902806f, 1.2346398f,
- 1.8559798f, -1.232507f, -0.44538176f, -0.6452678f,
- -0.61875886f, 0.2757739f, -1.4767425f, -1.8914642f,
- 0.061856497f, -0.012764602f, 2.8324437f, 0.95154285f,
- 0.9354157f, 1.224731f, -0.8016376f, 0.3166127f,
- 2.0025215f, -0.67323744f, -0.27247533f, -0.54617447f,
- -1.5076663f, -0.5256402f, -0.86952937f, -1.5374383f,
- -0.9415668f, -1.9337566f, 0.31937236f, -0.6165179f,
- -0.062132336f, 1.117609f, -1.1759263f, -0.34810877f,
- 0.022053836f, -0.8445917f, -1.4070222f, 1.6191514f,
- 2.8135695f, -0.022204898f, 0.76820695f, 1.3381451f,
- -2.1617403f, -1.2567042f, -0.20020778f, -0.23368911f,
- 1.4091364f, -0.34981513f, 3.108128f, 2.7400885f,
- 1.9121646f, -0.5477137f, -0.06646584f, -1.2305988f,
- -1.3047715f, 0.19171669f, 1.0599023f, 1.9179039f,
- -1.4593551f, -0.07324092f, 0.6686651f, -0.21047509f,
- -0.052781418f, -0.08911627f, 0.9020384f, -0.15637892f,
- -0.26905745f, 1.5784374f, 1.0472809f, -0.029584995f,
- -0.12501834f, -0.14950213f, -0.27969247f, -0.09379165f,
- -0.09567663f, -0.113214515f, -0.19516513f, -0.4315594f,
- -0.17201786f, -0.013874925f, -0.15550871f, -0.4854814f,
- -0.2833937f, -0.18899699f, -0.19616668f, -0.41518807f,
- 1.1753173f, -0.16596186f, -0.49706194f, -0.0787877f,
- -0.06627953f, 1.0995164f, 1.9384638f, -0.13958824f,
- -0.045567162f, -0.29601428f, -0.20971927f, -0.29498008f,
- -0.2911737f, 0.020279696f, -0.0566716f, -0.02800226f,
- -0.29484183f, 1.1009415f, -0.2896551f, -0.18021879f,
- -0.04599055f, 0.23129186f, -0.41612124f, -0.2593999f,
- -0.47816712f, -0.18672895f, -0.20362999f, -0.16457576f,
- -0.18468784f, -0.1013179f, 0.10127057f, -0.047669016f,
- -0.22046356f, -0.4732283f, 0.4543924f, -0.118310906f,
- -0.13793153f, -0.12817395f, -0.25757387f, -0.068370976f,
- -0.29307798f, -0.0053827735f, 1.5706465f, -0.12631188f,
- -0.16801304f, -0.03201667f, -0.20394081f, -0.12519988f,
- -0.09314133f, -0.20099038f, -0.14220533f, 2.0537908f,
- -0.15232505f, -0.2967952f, 0.537042f, -0.003362433f,
- -0.25209048f, -0.3086927f, -0.02799718f, -0.071936354f,
- -0.5316695f, -0.03805935f, -0.09132485f, 1.5993769f,
- -0.2120136f, -0.051855188f, -0.053084534f, -0.10816766f,
- -0.5575374f, -0.25037828f, 0.85418326f, -0.39173344f,
- -0.104531616f, -0.069062375f, -0.58834356f, 0.012626199f,
- -0.1463345f, -0.13635512f, -0.106418744f, -0.10494553f,
- -0.127434f, -0.19671795f, 0.9263381f, -0.18191715f,
- -0.108005404f, -0.19404201f, -0.040611632f, 0.5639991f,
- -0.17386454f, -0.47936752f, -0.19546188f, -0.113354936f,
- -0.07663137f, -0.23196691f, -0.16083972f, 1.8644203f,
- 0.01375263f, -0.097260885f, -0.22084597f, -0.15388726f,
- -0.10175068f, -0.12909955f, -0.20129582f, -0.15371777f,
- 0.36761668f, -0.14043592f, -0.14530292f, -0.21623395f,
- 2.0977392f, 0.059948843f, -0.086177595f, -0.063414805f,
- -0.14592728f, -0.13199866f, 0.34161857f, -0.17914885f,
- -0.2310431f, 0.20942773f, -0.1336883f, -0.101135015f,
- -0.22417536f, 0.59556293f, -0.24786331f, 0.037057962f,
- -0.1594399f, -0.18982817f, -0.15628637f, -0.11587675f,
- -0.15841216f, -0.13274929f, 0.20310661f, 0.53131896f,
- -0.09314031f, -0.07334235f, -0.1523432f, -0.21035738f,
- 0.022186302f, 0.14052668f, -0.039876632f, -0.1055619f,
- -0.11666578f, 0.0020968032f, 0.20315881f, 0.11038799f,
- -0.12932496f, -0.071984075f, -0.1944466f, -0.014725659f,
- -0.071346685f, -0.13549173f, -0.15953307f, -0.054878734f,
- -0.07500111f, -0.17161822f, -0.18586704f, 0.029007705f,
- -0.23494439f, -0.123335764f, -0.1964132f, -0.32239738f,
- -0.1998691f, -0.09735949f, 1.8788278f, -0.015312608f,
- -0.10811126f, -0.040638812f, 0.53924626f, -0.15184991f,
- -0.049407512f, -0.03708832f, -0.07195476f, -0.12182032f,
- -0.10722368f, -0.023354108f, -0.10979252f, -0.03978507f,
- 0.01630108f, 0.5866805f, -0.177437f, 0.31403586f,
- -0.04232291f, -0.04919688f, -0.09016743f, 0.69189465f,
- -0.16394953f, -0.2715775f, -0.10495f, -0.21401823f,
- -0.23191936f, -0.13289666f, -0.18050006f, 0.3992159f,
- -0.25052407f, -0.026259944f, -0.04291076f, -0.06599167f,
- 0.30476677f, -0.088437855f, -0.057536f, -0.08890348f,
- 0.052292034f, -0.07146929f, -0.11709304f, -0.07164754f,
- 0.21328828f, -0.08144019f, -0.072987f, -0.06559479f,
- -0.054943558f, 0.70656586f, -0.083294936f, -0.1395102f,
- -0.100768425f, 0.13032448f, -0.10295206f, -0.074603334f,
- -0.07574017f, 0.38391972f, -0.024419945f, -0.08236121f,
- -0.10870505f, -0.046874505f, -0.045049924f, -0.080128245f,
- -0.17790586f, -0.075514756f, 0.56320155f, -0.14215477f,
- -0.06811527f, -0.06316031f, 0.9980656f, -0.053473268f,
- -0.29322404f, 0.0027916038f, -0.263273f, -0.07497117f,
- -0.049055483f, -0.07917196f, -0.008322976f, -0.07669762f,
- 0.66211003f, -0.12515971f, -0.07263492f, -0.08363722f,
- -0.07629105f, 0.003384127f, 0.019355072f, 0.00044333367f,
- -0.036863428f, -0.090355515f, -0.07918566f, 0.84256744f,
- 0.27607182f, -0.0017770889f, -0.06777987f, -0.11072644f,
- -0.08535083f, -0.021249678f, -0.034372624f, -0.028265059f,
- -0.06370129f, -0.069741316f, -0.059303727f, -0.056258f,
- -0.029151311f, -0.061341554f, -0.040974185f, -0.059032463f,
- -0.18910545f, -0.06214295f, -0.029329348f, 0.079982184f,
- -0.06913066f, -0.0758385f, -0.08224567f, 0.9832021f,
- -0.1972713f, -0.06511421f, -0.071230486f, -0.060222734f,
- -0.070533335f, -0.08823043f, -0.05673278f, -0.011073243f,
- -0.047130175f, -0.028229313f, 0.4773505f, -0.18822634f,
- -0.01799291f, -0.10730629f, -0.071527906f, -0.030331893f,
- -0.05182831f, -0.062070902f, -0.07819976f, -0.08130331f,
- -0.060268153f, -0.022450477f, -0.04501708f, -0.09298025f,
- 0.21584122f, -0.13829896f, 0.5941255f, -0.60148454f,
- 1.1278609f, -0.3192112f, -0.6342735f, -0.5594282f,
- 0.43779454f, -0.1304103f, 0.49742323f, -0.8783934f,
- -1.0611418f, -0.7419473f, -3.0265706f, -0.97900903f,
- -0.7798701f, 0.27610895f, 0.9389303f, -0.6283463f,
- 1.9119084f, -1.7713927f, 2.5593395f, 0.8980702f,
- 0.07858713f, -0.33077815f, -0.058641534f, 0.0942297f,
- -1.3521281f, -0.08244909f, -0.20634562f, 0.22672436f,
- -0.05643908f, 0.34191704f, 1.4178926f, 0.13122846f,
- 1.5809171f, -0.7293213f, -0.49273962f, 0.90367085f,
- -0.93585616f, -0.87088764f, 2.3684309f, 2.082579f,
- 0.042808644f, -0.13689524f, -1.0876788f, -1.0195911f,
- 0.385444f, 0.42845413f, 0.04048017f, -0.10003363f,
- -1.281881f, 5.007208f, 0.10830239f, 0.034152053f,
- 3.7036364f, 2.1764076f, -0.42992985f, 0.40712696f,
- 0.2189693f, 0.75290304f, -1.0877707f, -1.746042f,
- -1.0279312f, 1.4179698f, 2.0813947f, 0.64143395f,
- -0.35989678f, 0.23701258f, -0.6245644f, -1.0611823f,
- -1.194882f, 2.8087394f, 0.97500634f, 0.91774476f,
- -0.81203717f, 0.08533289f, -0.5479782f, 0.16091727f,
- 1.0793566f, 0.55938005f, 4.7970314f, -0.43696874f,
- 0.91577375f, -0.17259556f, -2.670788f, 0.90620905f,
- -0.9384425f, -1.3309355f, -0.4822158f, -1.7670957f,
- 0.58780557f, 0.9418557f, 0.5045298f, 0.35241732f,
- -0.6512243f, -0.11385758f, -1.6205927f, -1.5609951f,
- -2.0394218f, -0.11318686f, -0.01230678f, -0.9514283f,
- -0.681172f, -2.2977889f, -1.1220875f, -2.3791733f,
- -0.72869736f, 0.35630295f, -0.28271896f, -0.061559483f,
- -0.13897419f, -0.077770084f, 0.8444761f, -0.06775763f,
- -0.30433103f, -0.0064366423f, 0.21340701f, -0.102665074f,
- -0.12345311f, -0.10876255f, 0.6627697f, -0.016621169f,
- -0.082696974f, -0.09823506f, -0.08337386f, -0.016008312f,
- -0.08389742f, -0.115061365f, -0.09932064f, -0.09668162f,
- -0.15487789f, -0.060424406f, -0.18795997f, 0.67516303f,
- -0.21523239f, -0.06486029f, 1.1534078f, -0.093063235f,
- -0.08198707f, 0.5383196f, 0.015633289f, -0.15575992f,
- 0.05566862f, -0.17587951f, -0.10186054f, -0.14158933f,
- -0.23394512f, -0.08142413f, 0.027268816f, -0.09765914f,
- -0.18237518f, -0.32506323f, -0.13441281f, -0.2087243f,
- -0.051046863f, 0.42060983f, 0.3642175f, -0.0427164f,
- -0.05798518f, -0.13962187f, -0.06777634f, -0.10705565f,
- -0.025356669f, -0.03806695f, -0.10217237f, -0.084113695f,
- -0.090018936f, 0.26929906f, -0.08463043f, -0.14289328f,
- -0.032634623f, -0.12289233f, -0.16731706f, -0.12811576f,
- -0.22194967f, -0.053121805f, 0.0020362006f, 0.013136508f,
- -0.10881163f, -0.15495521f, -0.061626695f, -0.09583786f,
- -0.08645877f, -0.13627309f, -0.18976258f, -0.06583352f,
- -0.07066883f, 0.641905f, 0.113827825f, -0.030817354f,
- -0.11641156f, -0.24656433f, -0.08951639f, -0.041229274f,
- -0.22886792f, -0.17276016f, -0.065224335f, 0.11128837f,
- -0.005138242f, -0.07346115f, -0.03908621f, -0.041177012f,
- 0.6544546f, -0.1196209f, 0.74367803f, -0.17626856f,
- -0.034414977f, -0.027113896f, 1.6718704f, -0.119087815f,
- -0.16951309f, -0.06875866f, -0.18549304f, -0.1893909f,
- -0.0644383f, -0.102258965f, 0.46536827f, -0.1276183f,
- -0.10186119f, -0.14165424f, -0.08205723f, 0.5787698f,
- -0.021412399f, -0.095147304f, -0.24397609f, 0.218232f,
- -0.11331542f, -0.058344286f, -0.14520341f, 0.24356014f,
- -0.050770737f, -0.11239975f, -0.06464873f, -0.08147771f,
- -0.36730203f, -0.15715337f, -0.23336639f, -0.10126757f,
- 0.51874983f, -0.1495705f, -0.09533939f, -0.12543266f,
- 0.29181698f, -0.12303502f, -0.038557976f, -0.36796385f,
- -0.013189616f, -0.04466073f, 0.9456755f, -0.29851595f,
- -0.1859127f, 0.2652495f, -0.25712794f, -0.060414962f,
- -0.21380919f, 1.1565217f, -0.15439083f, -0.12629908f,
- -0.05534439f, -0.38690674f, -0.060293756f, -0.10807224f,
- -0.19283654f, -0.004433716f, 0.82285815f, -0.17129686f,
- -0.08470987f, -0.17174429f, -0.10640827f, -0.12212534f,
- -0.06767069f, -0.058274813f, 0.026342165f, -0.14814194f,
- -0.07874961f, -0.10288869f, 1.2240345f, 0.26997092f,
- -0.085033104f, -0.060423728f, -0.16603002f, -0.15469463f,
- -0.033361703f, -0.115449555f, -0.061311368f, -0.11323095f,
- -0.124373555f, -0.043921035f, -0.058168847f, -0.08969436f,
- -0.08963596f, -0.07320588f, -0.015290561f, -0.20968929f,
- -0.23826353f, -0.082043774f, 0.20435615f, -0.27697298f,
- -0.13326542f, -0.09752573f, 1.1459304f, -0.15850823f,
- -0.095249765f, -0.36554846f, -0.16226625f, -0.05343386f,
- -0.23799032f, -0.11458801f, -0.015429758f, -0.002539024f,
- 0.043885853f, 1.9157556f, -0.13710584f, -0.16206227f,
- -0.17021836f, -0.12062582f, 0.03219496f, 0.59024704f,
- -0.096943595f, -0.081032224f, -0.051900517f, -0.17546643f,
- -0.041656774f, -0.06075241f, -0.008864291f, 0.67406183f,
- -0.1728804f, -0.0676053f, -0.12962463f, -0.12455265f,
- 0.6114089f, -0.11458178f, -0.101230934f, 0.08998323f,
- 0.103958026f, -0.021101171f, -0.12008325f, -0.11066182f,
- -0.03763638f, -0.06597272f, -0.06722311f, -0.010186448f,
- -0.067686856f, 0.4906695f, -0.07607523f, -0.17732504f,
- -0.084387094f, -0.064110495f, -0.018664442f, -0.111581415f,
- -0.095659696f, -0.008484789f, -0.0447406f, -0.08526642f,
- -0.24750766f, -0.08697282f, -0.14370473f, 0.1764961f,
- 0.25856063f, -0.08103737f, 0.39771882f, -0.20233105f,
- -0.08090545f, -0.13299991f, 0.8492318f, -0.09103781f,
- -0.08630398f, -0.10447156f, -0.32894555f, -0.10483754f,
- -0.093136445f, -0.1920325f, -0.011478198f, -0.1954818f,
- 0.44575623f, -0.026591705f, -0.020081732f, -0.12322651f,
- -0.017247545f, -0.066123776f, 0.0481129f, 0.015131368f,
- -0.0344175f, -0.073034465f, -0.04047052f, 1.1535819f,
- 0.08578877f, -0.049611725f, -0.025564719f, -0.11264489f,
- -0.19392562f, 0.00042181523f, -0.12539913f, -0.07103489f,
- 0.17104256f, -0.05175872f, -0.056902513f, -0.093104415f,
- -0.06689917f, -0.07105359f, -0.09896184f, -0.07369876f,
- -0.088342085f, -0.20116213f, -0.05528966f, -0.04554144f,
- -0.14860569f, -0.03815804f, -0.081449434f, 0.9548166f,
- -0.13118109f, -0.07809058f, -0.08782942f, -0.074990526f,
- -0.104767375f, 0.3721641f, -0.112889916f, -0.012052116f,
- -0.05326769f, -0.045693178f, 0.97640157f, -0.102519386f,
- 0.17698808f, -0.25636744f, -0.07472169f, -0.027820364f,
- 0.5478384f, -0.16766417f, -0.16285634f, -0.08590056f,
- -0.14835012f, -0.08164314f, -0.07546314f, -0.098467335f,
- 0.3163805f, -0.10818502f, -0.22968379f, -0.18031064f,
- -0.1519225f, -0.3019484f, -0.19531368f, -0.11708601f,
- -0.35493913f, 0.66802764f, -0.14091909f, -0.18341523f,
- -0.1849875f, 0.7584279f, -0.16325769f, -0.11426192f,
- -0.14884567f, -0.17725572f, -0.088033125f, -0.09876734f,
- -0.33458883f, -0.24738221f, 1.7558635f, -0.28932807f,
- -0.18412319f, -0.112525016f, 0.5747782f, -0.08736915f,
- 0.028841933f, -0.23721708f, -0.015803307f, -0.16466154f,
- -0.34501633f, -0.34536913f, -0.22436315f, 0.31865832f,
- -0.6035561f, 0.014648969f, -0.22838464f, -0.1690392f,
- 0.027432611f, 0.5908184f, -0.12857807f, -0.5664905f,
- 1.282564f, 0.17036298f, -0.19642398f, -0.087453395f,
- 0.1926829f, 0.5331883f, 0.0023192216f, -0.17131181f,
- -0.094434194f, -0.10808443f, -0.059824467f, 0.15293339f,
- -0.104379445f, -0.13487233f, -0.11558163f, -0.1680402f,
- -0.26423994f, 1.4475054f, 0.13594751f, -0.12886676f,
- -0.21545781f, -0.33174017f, -0.2841013f, 0.174303f,
- -0.07029643f, -0.19252846f, 0.02760378f, 0.12250622f,
- -0.10535864f, -0.15025522f, -0.12653081f, -0.24595048f,
- -0.041840572f, -0.19832228f, -0.22665587f, -0.02751366f,
- 0.56202614f, 1.2427742f, -0.20002605f, -0.060487654f,
- -0.083780654f, -0.037830736f, -0.05396574f, 2.4116507f,
- 0.111853614f, 0.009762549f, -0.39183816f, -0.15347971f,
- -0.02930885f, -0.10539488f, -0.15945706f, 0.08307468f,
- 0.06310973f, -0.36644623f, -0.44726697f, -0.006095996f,
- 0.121388525f, -0.2985333f, -0.14891455f, -0.23816957f,
- -0.22299832f, -0.031214502f, -0.11856185f, -0.018885657f,
- 0.2206502f, 0.6242639f, -0.27392358f, -0.17696789f,
- -0.060161345f, -0.08284439f, 1.3601472f, -0.19142073f,
- -0.111392714f, 1.4823298f, 0.97833294f, -0.0936868f,
- -0.09600656f, -0.1523041f, -0.37329695f, 0.021657921f,
- -0.15605403f, -0.13597399f, -0.010797003f, 1.1257063f,
- -0.18671197f, -0.3147147f, -0.16217417f, -0.16337554f,
- -0.28247184f, -0.16359085f, -0.13239625f, -0.37580997f,
- -0.07339118f, -0.04491724f, -0.17162925f, -0.115817994f,
- -0.05322758f, -0.27103993f, 1.4945308f, -0.1146796f,
- 0.21184602f, -0.1045753f, -0.12464826f, -0.16583087f,
- 0.07007481f, -0.15167369f, -0.25422767f, -0.07218378f,
- -0.42808318f, -0.18354452f, -0.30127436f, -0.23079953f,
- -0.063431114f, -0.2925307f, 0.81703573f, -0.25911063f,
- -0.32954547f, -0.15876034f, -0.09446164f, -0.106434755f,
- 0.07882648f, -0.0053168912f, -0.05032121f, -0.10674659f,
- -0.12698229f, 1.0387524f, 0.14620245f, -0.2694137f,
- -0.1602534f, -0.18091154f, -0.22682297f, -0.098407865f,
- -0.33984047f, -0.030529605f, 1.2893776f, -0.08741957f,
- -0.105371915f, -0.06422729f, -0.1125131f, -0.035067778f,
- -0.098380715f, -0.17054527f, -0.2057726f, 1.3332717f,
- -0.20855938f, -0.3146948f, -0.1960705f, -0.019851746f,
- -0.23376982f, 0.1410738f, -0.109309345f, -0.12397192f,
- -0.09876571f, -0.39209354f, 0.001087319f, 1.3177013f,
- -0.16446617f, -0.08184799f, -0.08173835f, -0.027363272f,
- -0.65192825f, -0.2212995f, 0.1071583f, -0.39807388f,
- 0.007206194f, 0.04445621f, -0.27988386f, -0.21165423f,
- -0.11974586f, -0.16224419f, -0.14540572f, -0.0412059f,
- 0.0035500093f, -0.087124534f, 1.4846128f, -0.095585614f,
- -0.15961523f, -0.1477299f, -0.4425534f, 0.3631182f,
- -0.15624237f, 0.2161543f, -0.15873916f, 0.19096652f,
- -0.2197013f, -0.5783342f, -0.40531516f, 0.43903947f,
- -0.39504886f, -0.5373414f, 0.93052f, -0.3878318f,
- -0.30396816f, -0.23774143f, -0.19634879f, -0.38106012f,
- 0.32346284f, -0.28847876f, 0.04995997f, 0.30286685f,
- 0.5189715f, -0.1646156f, -0.39687702f, 0.24181712f,
- 0.061709102f, 0.06685497f, 0.1851299f, -0.11920728f,
- -0.50478137f, 3.5593767f, -0.24214017f, -0.18919367f,
- 0.3259599f, 0.13398221f, 0.844858f, -0.0014203767f,
- -0.48865497f, -0.15379505f, 0.058050632f, 0.07316261f,
- 0.5396791f, -0.3111192f, 0.37788272f, 0.25711894f,
- -0.2324713f, 0.1377098f, 0.2116928f, -0.13164149f,
- -0.11913067f, -0.5062507f, -0.6905722f, -0.4784423f,
- -0.34932497f, -0.0387059f, -0.10114358f, 0.41112995f,
- -0.024062641f, -0.30971992f, 0.6145075f, -0.25210717f,
- -0.30955768f, -0.18472499f, -0.21254764f, -0.17639285f,
- 0.08455481f, -0.10083708f, 0.24169463f, -0.21947852f,
- -0.20053005f, -0.39466745f, -0.36473313f, 0.7575502f,
- -0.19667885f, -0.34846509f, 0.5552072f, 0.07575532f,
- -0.30798393f, -0.0020207209f, 0.0718931f, 1.1408312f,
- -0.32627726f, 0.10158326f, -0.30109173f, 0.59343636f,
- -0.30277717f, -0.15106277f, -0.4772168f, -0.46803352f,
- -0.4222703f, 0.41761604f, -0.5137398f, -0.015272645f,
- -0.16394147f, -0.6527686f, -0.3094431f, 0.2916544f,
- -0.16264035f, 0.059038837f, -0.53436345f, 0.58927983f,
- 0.74883527f, -0.45920688f, 0.34326237f, 0.52533597f,
- 1.0686816f, -0.023865229f, -0.20758916f, -0.1025933f,
- -0.08665877f, -0.071389094f, -0.09658281f, -0.31777793f,
- 1.2066866f, 0.018803261f, -0.039822917f, -0.15380044f,
- 0.42781934f, -0.12558748f, -0.2601148f, -0.03008824f,
- -0.14474228f, -0.16110997f, -0.06933707f, 0.06094168f,
- -0.19695461f, 0.24962777f, -0.14849488f, -0.08288458f,
- -0.20442511f, 0.47704592f, 1.5997927f, -0.098912515f,
- 1.6235687f, 0.061482508f, 0.01455922f, 0.039753288f,
- -0.38364935f, -0.2802207f, -0.21791196f, 0.14679825f,
- -0.082009055f, -0.15180372f, -0.22026585f, -0.1781253f,
- -0.19941229f, -0.16851147f, -0.24026242f, 1.3522575f,
- -0.120523155f, -0.238645f, -0.03779989f, 1.473887f,
- -0.56302416f, -0.14570183f, 0.037778914f, -0.18889368f,
- -0.050867736f, -0.19254039f, 0.09682664f, -0.0043427953f,
- -0.0035352171f, -0.054069802f, -0.12321849f, -0.07210236f,
- -0.10766924f, -0.0010079714f, -0.09866926f, -0.1342901f,
- -0.047748312f, -0.1275037f, -0.11949954f, -0.18670987f,
- -0.14671722f, 0.0014341834f, -0.29468632f, -0.2027678f,
- -0.08429267f, -0.021755382f, -0.22010686f, -0.03930447f,
- -0.27089378f, -0.15295677f, -0.118349195f, 0.4072705f,
- 0.49795812f, 0.0037448031f, -0.10076144f, -0.1304637f,
- 0.039687302f, -0.11897828f, 1.9355478f, 0.105870895f,
- -0.21455713f, -0.21528473f, -0.2200973f, -0.13063991f,
- -0.06227775f, -0.062418777f, -0.26641342f, -0.07573588f,
- 0.08006094f, -0.2758226f, -0.039636746f, 0.004576654f,
- -0.42735505f, 0.034683287f, -0.07568413f, -0.040412847f,
- -0.20563865f, -0.067054294f, -0.10038301f, 0.057991832f,
- -0.026492536f, -0.2762205f, 0.5420894f, -0.17256866f,
- -1.121371f, -0.36154947f, 0.7319255f, -0.6960644f,
- -0.4505671f, 0.7340403f, -0.10257483f, -0.52287465f,
- -0.9074013f, -0.6256625f, -1.5854049f, -0.49357384f,
- 0.29445663f, -0.34543207f, -0.20218076f, -0.9904373f,
- 2.4090528f, -0.5542025f, 1.3370781f, 1.2701106f,
- -0.06787479f, -0.884406f, -0.6845491f, 1.0669148f,
- -1.0346956f, 1.016292f, -0.26294303f, -0.34901047f,
- 0.18624662f, -0.2239802f, -0.826165f, 0.4385783f,
- 1.3331845f, -1.191661f, -0.16625138f, -0.46351606f,
- 0.49017298f, 1.5803488f, -1.328091f, 1.6833773f,
- 1.3388318f, -0.20871481f, 2.2450702f, -0.40904304f,
- 1.1044267f, -0.5206759f, -0.15661052f, 1.0074289f,
- 0.16278544f, 0.27253133f, -1.3421316f, -0.8849983f,
- -0.55261225f, -0.30903944f, -0.729469f, -1.237332f,
- 0.10175694f, 0.3476956f, 0.49571872f, -0.38311112f,
- 0.24614395f, -0.06077394f, -1.845432f, -0.7117886f,
- -0.649977f, -0.7043598f, 0.5645651f, 0.103460744f,
- 0.39598873f, -1.1469188f, 1.6892332f, -1.3135213f,
- 0.8852702f, -0.05270132f, 0.09534033f, -0.84901667f,
- -0.003358512f, 0.73365194f, 0.6167993f, -0.48205727f,
- -0.80359995f, 0.3299386f, -0.39818674f, 1.7648283f,
- 0.9679186f, 0.32967973f, 0.5938209f, -0.8399336f,
- -1.3805199f, -0.34342444f, -0.3180734f, -0.19407775f,
- 3.725385f, -0.47905558f, 0.1118694f, -0.12443465f,
- -0.6014113f, -0.4352444f, 0.5952659f, -1.1280854f,
- -0.8507722f, 1.2696242f, 1.2089683f, -0.87075216f,
- -0.52857363f, 0.49793246f, 1.550014f, -0.14920056f,
- -0.28445473f, -0.07479021f, 0.4858375f, -0.41395485f,
- -0.10650677f, 0.558682f, 0.12292604f, 0.015028963f,
- -0.13705726f, -0.44650486f, -0.18816864f, 0.057194255f,
- -0.44942307f, -0.19159831f, -0.40951404f, 1.1915126f,
- 0.0047821896f, 0.008288269f, -0.23776686f, 0.3836254f,
- -0.0162356f, -0.09201239f, 0.24564826f, -0.41931424f,
- 0.20419522f, -0.18276404f, -0.08800804f, 0.120526284f,
- 0.10058008f, -0.1108946f, 0.57842296f, -0.12562533f,
- 0.49001834f, 0.0695201f, -0.07561312f, -0.09940605f,
- 0.99744105f, -0.19796485f, -0.17136113f, 0.16819912f,
- -0.10187153f, -0.15680516f, -0.074543774f, -0.50656265f,
- -0.057356685f, -0.07638613f, 0.7979082f, -0.205974f,
- -0.23336609f, 0.17620331f, -0.13739969f, -0.18977891f,
- 0.42115104f, -0.0015141456f, -0.071066804f, -0.32094538f,
- -0.09282156f, 0.90378886f, 0.2591793f, 0.30883446f,
- 0.026663871f, -0.26145354f, -0.0127002f, -0.04649101f,
- 0.08409823f, 0.09391574f, 0.4967249f, -0.17771281f,
- -0.15630054f, -0.23506011f, -0.18155655f, -0.1483346f,
- -0.3110853f, -0.2069929f, -0.13036321f, 0.7495217f,
- -0.015806878f, -0.34691182f, -0.12015907f, -0.11548592f,
- -0.24228565f, 0.95918286f, -0.25288036f, -0.1946273f,
- 0.0017970725f, -0.18078645f, -0.1541034f, 0.40296414f,
- -0.31034836f, -0.085719354f, -0.121858224f, 0.1147378f,
- -0.054238617f, -0.1113041f, -0.11452829f, -0.21905561f,
- 0.0975093f, 0.16721782f, -0.25198728f, -0.24288145f,
- -0.08853213f, -0.37893724f, 0.09241831f, -0.089507304f,
- 0.07670963f, 0.0472931f, 0.5201585f, -0.14196154f,
- 3.00308f, -1.5764521f, -0.63818866f, -0.33997452f,
- -2.4247515f, 1.6907567f, -0.135787f, -0.08344564f,
- -0.37125728f, 1.4240844f, -0.27991676f, -2.03627f,
- 1.4295287f, 0.22490548f, 0.9746426f, 1.0808784f,
- -1.1095698f, 0.09564222f, 1.497122f, 1.482253f,
- 0.017412005f, 1.0882617f, 5.36333f, -0.6735945f,
- -0.567026f, -0.7121823f, -2.24366f, 0.30319914f,
- -2.6704054f, -2.4659843f, 0.2763374f, -0.2610869f,
- -2.0498335f, 0.41988513f, 5.4607215f, -3.6056304f,
- 0.9744555f, 1.0718869f, -1.6893843f, 0.025939964f,
- 2.134419f, 1.0201564f, -0.38690504f, -2.2673419f,
- 4.158644f, 2.5307853f, -0.09863266f, 0.10915043f,
- -1.9880115f, -1.3374059f, -2.0802636f, 2.6421468f,
- 4.889054f, -0.21410684f, 4.273005f, -1.3458354f,
- -1.216228f, -1.8088161f, 0.6975902f, -0.006806802f,
- 0.94878507f, -2.2798793f, 0.47976422f, -0.94574934f,
- -2.1313f, -1.7409943f, -1.7555293f, -0.25862667f,
- -1.365109f, -2.2056139f, 1.2176151f, 3.908354f,
- -0.9809741f, -3.840567f, -2.1010132f, -2.970835f,
- 0.97695535f, -0.41880727f, 2.2630594f, -0.34995243f,
- 1.108299f, -0.53510964f, -0.6031154f, -1.1870165f,
- -0.14318563f, 0.40582585f, 0.9681265f, -0.50629693f,
- 0.63940233f, -2.301425f, -0.019789787f, -1.1789504f,
- -1.065349f, 0.14052142f, 3.4715436f, 0.37710816f,
- -1.6511139f, -1.2059654f, -2.483163f, 0.32957265f,
- 0.3173964f, 0.7180238f, -1.4567027f, -1.8383194f,
- 2.8280802f, -0.44567356f, 3.078956f, 0.07497677f,
- 4.033932f, 1.4323299f, -0.3933588f, -0.12618895f,
- -0.35552996f, -0.3281665f, -0.911075f, 0.85057515f,
- 0.24836454f, -0.30740157f, -0.016370684f, 0.4656131f,
- -0.028667606f, -0.47011057f, 0.03878904f, -0.62708896f,
- 0.054417513f, -0.292776f, -0.43631625f, 1.5056092f,
- -0.7044145f, -0.57217425f, 0.42272574f, -0.66527694f,
- -0.41121802f, 0.030667426f, 0.9897962f, -0.08850218f,
- 0.055992506f, -0.20066413f, -0.14662623f, 0.9969778f,
- 0.14650579f, -0.0829889f, -0.13160554f, 1.9013904f,
- -0.18206996f, 0.110209174f, -0.4240809f, 0.38957578f,
- 0.010650433f, -0.4429466f, -0.80394745f, 0.7510726f,
- 1.9914575f, -0.5095548f, -0.35583913f, 0.04824109f,
- -0.4611302f, -0.57079726f, -0.549549f, -0.18109488f,
- -0.75637835f, -0.27426538f, -0.19030938f, -0.16650769f,
- -0.399768f, 1.3858218f, -0.59827965f, -0.093568504f,
- -0.026185235f, 1.683647f, -0.33787313f, -0.6433546f,
- 2.1542284f, -0.23620205f, 2.0557654f, -0.25709024f,
- 1.1757916f, 0.24038179f, -0.54826576f, -0.49766865f,
- -0.39212373f, -0.34467265f, -0.75100493f, -0.66617405f,
- -0.74346745f, 0.70023847f, -0.44874603f, -0.5500947f,
- 0.6279592f, -0.6339841f, -0.818437f, -0.23940352f,
- -0.70922995f, -0.30768606f, 0.116695955f, 2.0596833f,
- 0.29318258f, 0.10966904f, -0.32481158f, -0.3017226f,
- -0.13023835f, -0.7902047f, -0.09903174f, 0.38479134f,
- 0.49501657f, 1.2123947f, -0.028880484f, -0.2937486f,
- -0.20034997f, -0.6246323f, -0.055660382f, 0.43057403f,
- -0.55079025f, -0.31515464f, -0.47615942f, 0.7570758f,
- -0.058055583f, -0.6502056f, 0.09970006f, -0.52591795f,
- -0.2690605f, 0.8440321f, -0.24602537f, -0.13722259f,
- -0.01683005f, 0.8253175f, -0.2621835f, 0.011417657f,
- -0.35018414f, 0.95944077f, -0.42106304f, -0.25901818f,
- -0.14265229f, -0.130633f, -0.2611672f, -0.39715093f,
- 0.19839716f, 0.6522068f, -0.28812194f, -0.35548463f,
- -0.1981392f, 1.0797652f, 0.9444378f, 1.0398633f,
- 0.19758895f, 1.5782477f, 0.12201613f, 0.1698805f,
- 1.0791184f, -0.8476935f, 0.3486277f, -0.29768038f,
- 0.28549632f, -0.20318992f, -0.30890018f, -0.51549894f,
- -0.16723067f, -0.3093801f, -0.18017882f, -0.48155737f,
- 0.55092424f, -0.3693531f, -0.38622284f, -0.19760594f,
- 1.474265f, -0.3370546f, 0.06309024f, -0.32841513f,
- 0.019959737f, -0.07743185f, 0.12432953f, -0.27848336f,
- -0.2511766f, 0.2378562f, 0.48104876f, -0.40966132f,
- -0.24333909f, -0.24868564f, -0.5264447f, -0.3964825f,
- -0.3889971f, -0.23015255f, 0.124079406f, -0.14334677f,
- -0.5627087f, 0.09641568f, -0.06985442f, -0.06287371f,
- -0.39349368f, -0.4770353f, -0.5651642f, -0.41854876f,
- 0.31703392f, -0.004221735f, 0.5201598f, -0.25347838f,
- 0.6727407f, -0.33245265f, -0.4006659f, -0.404762f,
- -0.21241459f, -0.36057013f, -0.056638163f, -0.063903265f,
- -0.037660204f, -0.45218286f, -0.21394688f, -0.41641283f,
- 0.3571241f, 0.10724707f, -0.067917034f, 0.6730494f,
- -0.17072015f, 0.8800175f, -0.34336293f, -0.5839172f,
- -0.13750827f, 0.94799423f, -0.19634286f, 0.1957077f,
- 0.8881317f, -0.5933747f, -0.24255905f, -0.26535258f,
- 1.6068975f, 0.16800088f, -0.1931759f, -0.0065743714f,
- -0.31696945f, -0.08789007f, 0.24635114f, -0.0023993142f,
- -0.20478785f, -0.38518733f, 1.1744897f, -0.09273858f,
- -0.2371807f, -0.21399558f, 1.2445673f, -0.1044853f,
- -0.22525536f, -0.1538712f, -0.1597927f, -0.053444173f,
- -0.07123603f, -0.20809679f, -0.15826425f, -0.4301957f,
- -0.28690472f, -0.10954287f, -0.17275462f, 1.3400387f,
- 1.404985f, 0.024264442f, 1.235252f, 0.050771523f,
- 0.05329575f, 0.45179954f, -0.34384412f, -0.2073749f,
- -0.45895937f, -0.33095804f, -0.19117947f, -0.15079461f,
- -0.182507f, -0.24799664f, -0.17753604f, -0.048418865f,
- -0.35762674f, 0.8655828f, -0.16545166f, -0.193545f,
- -0.05653657f, 0.3276152f, 0.47779936f, 0.016993409f,
- -0.032183606f, -0.20256008f, -0.050104532f, -0.21105707f,
- 0.12649919f, -0.023948988f, -0.048892323f, -0.14677247f,
- -0.042818945f, -0.23064333f, 0.16172127f, -0.1028542f,
- -0.095756344f, -0.17025746f, -0.25724936f, -0.22788577f,
- -0.29977587f, -0.22026625f, -0.2128194f, -0.075260445f,
- -0.2552324f, -0.25899038f, -0.035265576f, -0.1978276f,
- -0.18743324f, -0.10272222f, -0.39480695f, -0.24872698f,
- -0.08891863f, 1.1739706f, 1.0178154f, 0.004280441f,
- -0.018077834f, -0.14699808f, -0.0948811f, 0.038047876f,
- 1.1535907f, -0.091852106f, -0.16069384f, -0.20378143f,
- -0.1206604f, -0.056362487f, -0.07154377f, -0.074818425f,
- 0.35427353f, -0.15544146f, 1.1707228f, -0.24840929f,
- -0.064124845f, 0.009480719f, 0.085968986f, -0.069111705f,
- -0.10781745f, -0.06586908f, -0.3043338f, -0.010374428f,
- -0.11712369f, 0.012622767f, -0.35526446f, -0.45023662f,
- -0.3192064f, -0.22302537f, -0.4611692f, 0.07228626f,
- -0.33824617f, 1.2196138f, -0.3314699f, 0.30140722f,
- 0.37159836f, -0.8103827f, -0.6437753f, 0.6492667f,
- -1.0658495f, -0.032065354f, 0.29109877f, 0.10896513f,
- -0.73180914f, -0.7667943f, -0.67691916f, -0.22882731f,
- 0.2390776f, -0.3230283f, -0.0007543883f, 0.12649041f,
- 1.1346502f, 0.25162306f, -0.41390607f, 0.66014695f,
- -0.3592229f, -0.2566284f, 0.041753963f, -0.53106904f,
- -0.35901457f, 1.1583247f, -0.24012606f, 0.4583887f,
- 1.805386f, -0.3810752f, 0.46816108f, 1.4753085f,
- -0.8299185f, -0.50347614f, -0.0044106967f, -0.18453053f,
- -0.072953686f, -0.071448006f, 0.18027472f, 0.42322725f,
- -0.52104646f, 0.06545444f, -0.39725128f, -0.20471708f,
- -0.175757f, -0.51053566f, -1.0970505f, 0.27657443f,
- -0.51635355f, 0.041382488f, -0.4604737f, 0.44550502f,
- -0.28941292f, -0.5530657f, 1.2577735f, -0.67284924f,
- -1.0098054f, -0.40894046f, -0.7021875f, -0.1273512f,
- 1.074469f, -0.11638624f, 0.41988835f, -0.28824425f,
- 0.36833495f, -0.44298095f, 0.13941476f, 0.40021393f,
- -0.34991282f, -0.27380055f, 1.292406f, 0.6209476f,
- -0.43385217f, 0.5908461f, -0.42263764f, 1.2389411f,
- -0.24474083f, 0.6562904f, -0.16719484f, -0.5522935f,
- -0.29424548f, -0.15414813f, -0.65496796f, -0.6105816f,
- -0.115787685f, 0.65430206f, 1.1851165f, 0.53224283f,
- -0.47186095f, -0.31893414f, -0.24312462f, 0.46031442f,
- 0.15654448f, 1.4318689f, -0.77742475f, 0.67117923f,
- 1.3839366f, -0.48295417f, -0.04378236f, -0.006427122f,
- -0.51734596f, -0.095744915f, -0.20965807f, -0.042230304f,
- 0.59558225f, -0.14376393f, -0.48324552f, -0.32136577f,
- -0.05576855f, -0.09930785f, -0.14667796f, -0.17450431f,
- 2.0257375f, -0.07391893f, -0.009321558f, -0.16577198f,
- -0.15132087f, 0.5675718f, -0.16350903f, -0.1332681f,
- -0.14384696f, -0.2950026f, -0.18837571f, -0.15612482f,
- -0.30982572f, 2.2075987f, 0.15041165f, -0.021673905f,
- -0.03159342f, -0.12868f, -0.107750125f, -0.09365272f,
- -0.23069263f, -0.34884626f, 0.23634373f, -0.21490958f,
- -0.14021814f, -0.23520133f, 0.054874543f, -0.26576278f,
- -0.19805667f, -0.1773753f, -0.16153055f, -0.35734f,
- -0.08900924f, -0.16397503f, -0.07198382f, -0.17933594f,
- 1.5066329f, -0.15050252f, -0.17679651f, -0.19915155f,
- -0.17857595f, -0.07423965f, 0.057517722f, 0.014431803f,
- -0.078830265f, -0.12666512f, -0.054200605f, -0.24363196f,
- 0.31811044f, -0.088110775f, -0.10385965f, -0.18094228f,
- -0.08140875f, -0.08778824f, -0.1449781f, -0.14719062f,
- -0.10886277f, -0.05465815f, -0.15536626f, -0.119474836f,
- 0.028004475f, -0.15265954f, -0.17497623f, -0.13726762f,
- -0.26256305f, -0.23960377f, -0.047021005f, 1.9911456f,
- 1.2298088f, -0.042417563f, -0.10003631f, -0.08544405f,
- -0.188126f, -0.011722002f, 0.09695929f, -0.10386952f,
- -0.07899336f, -0.21033679f, -0.097072266f, -0.016690211f,
- -0.09345243f, -0.031344455f, 0.33031055f, -0.22491647f,
- 1.3172897f, -0.14097571f, -0.06762415f, 0.005124453f,
- 0.96712637f, -0.1121984f, -0.32193714f, -0.04053792f,
- -0.2926389f, -0.2487063f, -0.090163045f, -0.24832983f,
- -0.09753492f, -0.38552925f, -1.4902261f, -1.4963496f,
- 0.4159158f, 0.4885328f, 2.2574039f, -1.8026096f,
- 0.36719996f, -0.31399968f, -1.3992434f, 2.3613193f,
- -0.39398262f, 0.37880802f, -0.30568674f, -1.3473021f,
- -1.9630283f, 0.75505704f, 0.0034844936f, -1.4931836f,
- -0.89593834f, 2.7595353f, 0.0010778602f, 2.0993953f,
- -2.3851612f, 0.24672578f, -0.06412031f, 0.22046019f,
- 5.5575914f, -0.5008434f, -1.8948023f, -2.3435557f,
- -0.008923511f, -1.7918508f, 4.2516f, 0.64336103f,
- 0.58371896f, -2.210794f, -1.3535779f, 1.895044f,
- 0.84881395f, 0.24520703f, 1.0441041f, 1.5359674f,
- 0.5974573f, -2.4257724f, 4.428258f, 0.26618516f,
- 0.13509683f, 0.44828317f, 0.81957895f, -1.0986233f,
- -0.8296453f, 0.32310092f, 0.92889607f, -1.5586345f,
- -2.2803557f, -0.7464109f, -0.9337864f, -1.9209919f,
- 0.47250837f, 0.37619552f, 0.053280868f, -2.2575493f,
- -1.0860722f, 1.734949f, 4.072291f, -0.35068712f,
- 0.115913734f, -0.9118049f, -1.1974417f, 0.39213142f,
- -1.0173906f, -2.0964677f, -2.153499f, -3.3192801f,
- 0.18003711f, 2.875882f, -0.7552012f, -2.4341037f,
- -0.06717655f, -0.45019835f, -0.9501549f, -1.1787181f,
- -0.504052f, 3.1536992f, 5.550135f, 0.10869231f,
- -1.0534685f, -1.8873006f, 1.3429649f, -1.0952842f,
- -0.11110257f, -1.4002973f, -0.76502067f, 0.68706036f,
- 3.7021391f, 0.17042015f, 0.57459056f, -2.4780438f,
- -0.59907955f, -0.3344541f, 1.9659357f, 2.811122f,
- 0.17905644f, -0.59874856f, -0.73552185f, 0.13989826f,
- 0.17018974f, 0.3604801f, 0.94696766f, -0.1286779f,
- -0.062022217f, -0.08568493f, 1.1065475f, -0.120624535f,
- -0.09313597f, 1.0623524f, 0.77242196f, -0.07098678f,
- -0.07074234f, -0.11376867f, -0.47336355f, -0.07910606f,
- -0.111565314f, -0.08977616f, -0.117419206f, 0.73875487f,
- -0.18692958f, -0.23534858f, -0.10179684f, -0.18499275f,
- -0.16305983f, -0.13584344f, -0.17713004f, -0.58418626f,
- -0.24424247f, -0.11118174f, -0.3504515f, -0.10586617f,
- -0.09974077f, 0.5092644f, 1.2269855f, -0.11635749f,
- 0.31538004f, -0.17873721f, -0.08071274f, -0.13246384f,
- -0.22503497f, -0.09602977f, -0.115677744f, -0.042831175f,
- -0.24786396f, -0.32083762f, -0.29116115f, -0.23025037f,
- 0.05308094f, -0.4074036f, 0.61263627f, -0.1734716f,
- -0.2784456f, -0.17457284f, -0.08983628f, -0.108502366f,
- -0.10078404f, -0.054940682f, -0.07828141f, -0.06752613f,
- -0.16362022f, 0.6107547f, 0.22119454f, -0.2280412f,
- -0.0888841f, -0.13658637f, -0.20700887f, -0.0945897f,
- -0.3340315f, -0.043420535f, 0.9948023f, -0.03305459f,
- -0.10428058f, -0.0645846f, -0.101942636f, -0.03954471f,
- -0.10017186f, -0.1099546f, -0.10143653f, 0.99149156f,
- -0.1311452f, -0.46731925f, 0.35299f, -0.04974157f,
- -0.15511367f, -0.21399987f, -0.08880927f, -0.07151597f,
- -0.15998629f, -0.30476308f, -0.05831411f, 1.0393947f,
- -0.12950197f, -0.030518824f, -0.017611155f, -0.06984851f,
- 0.38415554f, -0.19087926f, 1.0069295f, -0.36448506f,
- -0.0536043f, 0.00893949f, 0.59735215f, -0.1503527f,
- -0.14732577f, -0.10376889f, -0.1078074f, -0.12478651f,
- -0.0065302886f, -0.07265687f, 0.6884109f, -0.14083773f,
- -0.12037172f, -0.29218906f, -0.29194492f, 1.1749462f,
- -0.19714198f, -0.074949466f, 1.1589689f, 0.35909948f,
- 0.06145985f, 0.036948934f, -0.26474103f, -0.35004354f,
- -0.10194756f, -0.13347639f, 0.12905166f, 0.09857264f,
- 0.75699985f, -0.31396544f, -0.23626585f, -0.23298582f,
- 0.04444105f, -0.19472799f, -0.2121144f, -0.19966057f,
- -0.54054207f, 0.010274865f, -0.076279044f, -0.49804154f,
- -0.0150694335f, -0.11234447f, 0.4571225f, 1.3190987f,
- -0.010912927f, 0.3832419f, -0.16107358f, -0.063524656f,
- -0.13115533f, 0.35801724f, -0.061391555f, 0.11570918f,
- -0.036010835f, -0.29004127f, -0.24242562f, -0.4433553f,
- -0.2245404f, -0.08674266f, -0.27662227f, 0.47535825f,
- -0.074420385f, -0.2299348f, -0.027081903f, -0.077111766f,
- -0.39593366f, 0.27729073f, -0.0488782f, -0.08984921f,
- -0.123010464f, 0.03025033f, 1.439083f, -0.16078776f,
- -0.11590599f, -0.06249763f, -0.39744824f, -0.34366795f,
- -0.1002199f, -0.18331337f, -0.04631572f, 1.0703025f,
- -0.18408188f, -0.1973999f, -0.24203038f, -0.1467578f,
- 0.036721982f, -0.2714014f, -0.10947473f, -0.17988476f,
- 0.81067336f, -0.08136624f, -0.47268796f, -0.29934815f,
- 0.08530626f, -0.06815242f, 0.46668097f, -0.25153252f,
- -0.23027469f, -0.07441455f, -0.32878536f, -0.09037745f,
- 0.93519825f, -0.2364386f, -0.074439906f, -0.054208163f,
- -0.14688703f, 0.26433754f, -0.18677703f, 0.31552288f,
- -0.41883284f, -0.058256365f, 0.14774963f, 0.6912567f,
- -0.2522151f, -0.22283636f, -0.23424396f, -0.08247458f,
- -0.18315017f, -0.017052483f, -0.015450651f, 1.0024397f,
- -0.12979153f, -0.16139594f, -0.11588098f, -0.15456983f,
- 0.62178797f, -0.19786799f, -0.13491069f, 0.7011509f,
- 0.2285666f, -0.03270757f, -0.09463957f, -0.14825651f,
- -0.0729047f, -0.021884564f, -0.10571383f, -0.1725434f,
- -0.1385692f, 0.3720802f, -0.13208613f, -0.16976409f,
- -0.14509058f, 0.039931696f, 0.0068882797f, -0.09516735f,
- -0.17438371f, -0.10353632f, 0.0602398f, -0.07022806f,
- -0.025311744f, -0.04415762f, -0.061034434f, -0.025933826f,
- 0.89309186f, -0.101629436f, 0.296554f, -0.058182742f,
- -0.010628632f, -0.12788796f, 0.49648073f, -0.059877317f,
- -0.120581545f, -0.07024613f, -0.009947099f, -0.041499227f,
- -0.10485758f, -0.15598351f, -0.01294721f, -0.006187218f,
- 0.23316988f, -0.06870517f, -0.22738087f, -0.06437704f,
- -0.11685062f, -0.059029434f, -0.082728945f, -0.07909313f,
- 0.001398751f, -0.10809889f, -0.17980239f, 0.45384842f,
- 0.03735221f, 0.054374456f, -0.097992964f, -0.09802092f,
- -0.060324848f, -0.03668729f, -0.035431966f, -0.09547777f,
- 0.6427418f, -0.061911166f, -0.07660555f, -0.049778555f,
- -0.102790795f, -0.049787287f, -0.14666508f, -0.09405036f,
- -0.11931977f, 0.7431854f, -0.094094776f, -0.08888601f,
- -0.03236449f, -0.013214349f, -0.13560787f, 0.48010975f,
- -0.20384397f, -0.09561831f, 0.0060243295f, -0.16959299f,
- -0.056468535f, 0.71248645f, -0.076162525f, -0.053158928f,
- -0.106727876f, -0.08176685f, -0.119346075f, -0.057392254f,
- 0.12860002f, -0.12542756f, -0.02254172f, 0.19932824f,
- -0.090238474f, -0.20423584f, -0.12679185f, -0.12946305f,
- -0.02059523f, 0.00038489467f, -0.021301271f, -0.08855466f,
- 0.46084094f, -0.060839362f, -0.22702968f, -0.06826973f,
- -0.09451533f, 0.13581051f, -0.29386458f, -0.220394f,
- -0.35077965f, 0.74121827f, -0.06841032f, -0.18767814f,
- -0.1572812f, 1.0384288f, 0.00735248f, -0.2469592f,
- -0.07121093f, -0.21811354f, -0.31901842f, -0.07493634f,
- -0.29871237f, -0.25380743f, 1.7129573f, -0.22880574f,
- -0.15745668f, -0.08945876f, 1.0732634f, -0.055782765f,
- -0.11613492f, -0.0706342f, -0.13911568f, -0.24268581f,
- 0.0028370034f, -0.32326594f, -0.2669438f, 0.07745403f,
- -0.39454997f, -0.05078543f, -0.15987185f, 0.21705632f,
- -0.052930016f, 0.6186477f, -0.15470219f, -0.48199317f,
- 1.2020736f, -0.080526255f, -0.27612934f, -0.09075286f,
- 1.3287567f, 0.37048563f, -0.092237405f, -0.108553566f,
- -0.09644949f, -0.12884687f, -0.008633782f, 0.15374093f,
- -0.14559746f, -0.17437969f, -0.13272141f, -0.026707925f,
- -0.45330015f, 0.8835039f, -0.101331696f, -0.20753504f,
- -0.18849415f, -0.22953416f, -0.18237084f, -0.0069239256f,
- -0.0806203f, -0.2023487f, -0.023738988f, -0.05791007f,
- -0.1338509f, -0.13389651f, -0.1256687f, -0.06785544f,
- -0.13047425f, -0.25699148f, -0.2756709f, -0.06567985f,
- 0.97851086f, -0.002686222f, -0.18394968f, 0.07455805f,
- 0.38838324f, -0.047528557f, -0.14093389f, 1.0868821f,
- -0.1062099f, -0.09556015f, -0.4247028f, 0.002680472f,
- -0.047199253f, -0.07991734f, -0.12035689f, 0.651101f,
- -0.11327955f, -0.29878044f, -0.28293702f, -0.0341368f,
- 0.03265927f, -0.3689836f, -0.1737349f, -0.28778747f,
- -0.19080248f, -0.115167834f, -0.12511791f, -0.018659983f,
- -0.056489266f, 1.2510804f, -0.279218f, -0.12698452f,
- -0.21817961f, -0.025131239f, 0.19176644f, -0.16147624f,
- -0.42207527f, -0.14329837f, -0.09337276f, -0.044887003f,
- -0.25114834f, -0.20664722f, 2.0061452f, -0.08341994f,
- -0.084647454f, -0.20213586f, -0.16159774f, 0.24918112f,
- -0.15380895f, -0.13948031f, -0.13994606f, 0.37679145f,
- -0.19150724f, -0.1756653f, -0.3416077f, 2.2218487f,
- 0.288402f, -0.04180787f, -0.10222575f, -0.15346597f,
- -0.104339294f, -0.11798264f, -0.12385877f, -0.31518233f,
- 0.17458507f, -0.1668768f, -0.17242225f, -0.18768558f,
- 0.079093456f, -0.264637f, -0.108020104f, -0.13468996f,
- -0.11432203f, -0.3316826f, -0.08255139f, -0.19155316f,
- -0.07654373f, -0.06247611f, 0.99599624f, -0.114517234f,
- -0.05159744f, -0.17095907f, -0.2156656f, -0.029821875f,
- 0.102918684f, 0.018312868f, -0.10646084f, -0.12898229f,
- 0.012451878f, -0.13114394f, 0.44798347f, -0.086405955f,
- -0.076958604f, -0.19705701f, -0.012778671f, -0.12378086f,
- -0.13149655f, -0.12658112f, -0.016535722f, -0.033906665f,
- -0.20692776f, -0.1251842f, 0.04363443f, -0.17079741f,
- -0.16650426f, -0.1575094f, -0.36216947f, -0.14112496f,
- -0.022538431f, 2.004048f, 0.9699398f, -0.07756849f,
- -0.03765529f, 0.005301168f, -0.10241244f, -0.015196876f,
- 0.90016526f, -0.07147478f, -0.09497109f, -0.11631105f,
- -0.0141888345f, -0.040720914f, -0.07151749f, -0.01922684f,
- -0.014607882f, -0.198411f, 0.5224543f, -0.05778318f,
- -0.03427515f, -0.018512718f, 0.17317744f, -0.124830365f,
- -0.30897632f, -0.053604696f, -0.28071183f, -0.2745621f,
- -0.09332919f, -0.12652111f, 0.15717374f, -0.3506686f,
- -0.1466425f, -0.6488971f, 2.2163503f, -0.0038995491f,
- 5.5111775f, -0.74744517f, -0.8514677f, 0.07464531f,
- -1.2113308f, -1.6669939f, -0.26855266f, 0.3067848f,
- 1.3358834f, -1.2794425f, -0.9959278f, -0.8180957f,
- 0.04629712f, 3.149168f, 0.1642454f, -0.6760832f,
- 0.029255075f, 1.1742233f, -2.2782164f, -1.3213329f,
- 0.1222093f, 0.09001999f, -0.7270009f, -0.038056474f,
- -1.2443163f, -1.1074288f, 0.066275656f, 0.44580355f,
- -0.09130677f, 0.38895282f, -0.85758966f, -0.5602621f,
- -0.11809422f, -0.253739f, -0.98303884f, -0.8416472f,
- 1.8353148f, 0.9993895f, 0.2611717f, -0.04502728f,
- -1.8145003f, 0.7116927f, 0.14161608f, -0.60942024f,
- 1.3686461f, 2.291472f, 3.5405376f, 0.89808005f,
- -1.4553726f, -0.4532268f, -2.4641356f, -0.29059365f,
- -1.7684573f, 0.0069304975f, 0.081979305f, 0.4188347f,
- -0.8015619f, 0.003124955f, -1.3094321f, 0.3977017f,
- 1.706374f, -0.80416363f, -0.5534955f, -0.13283491f,
- -0.5385319f, 2.0739431f, -1.8302102f, -3.026737f,
- 1.9163349f, 5.208952f, 1.1762769f, 1.0477731f,
- -0.3568694f, 0.3964332f, -0.53318375f, 0.12109558f,
- -0.11273015f, 0.70148f, 0.93457997f, 0.619443f,
- -1.2197416f, -0.23245664f, -1.0423045f, -1.9252013f,
- 1.1123309f, 4.278642f, 2.5277417f, 0.047110293f,
- -1.1301806f, 0.003537692f, -1.9769785f, -0.08968034f,
- 1.5182261f, -1.270569f, -0.47648507f, -0.04222886f,
- -1.8360426f, -0.9432039f, 3.017425f, -0.42738944f,
- -2.712806f, 0.38485774f, -2.0055897f, 0.20870644f,
- -1.1125991f, -0.13152775f, -0.09268163f, -0.31009772f,
- 0.079803534f, 0.118652426f, 0.16407685f, -0.11413712f,
- -0.07756231f, 0.37021774f, -0.29569134f, -0.3600026f,
- 1.0159371f, -0.32914057f, -0.20499636f, 0.08074022f,
- -0.1616296f, -0.15867634f, -0.52832985f, -0.16612957f,
- -0.13899203f, 0.12636246f, -0.22884902f, -0.2991632f,
- -0.22717734f, 1.2867084f, -0.019607594f, -0.28845567f,
- 0.11675105f, -0.27401957f, -0.27285284f, -0.21975152f,
- -0.3828467f, -0.25261196f, 1.0348498f, -0.119996004f,
- -0.31831533f, 0.4831145f, -0.07669671f, 0.87502855f,
- 1.214759f, -0.51368517f, -0.24687658f, -0.19784874f,
- -0.24533963f, 0.43718693f, -0.24284397f, -0.120811835f,
- 0.6100874f, -0.5547218f, 0.29489627f, 0.23372082f,
- -0.37204325f, -0.27476633f, -0.23287152f, -0.34046388f,
- -0.21599644f, -0.12531035f, -0.0805775f, -0.28035024f,
- 0.42576823f, -0.23516634f, -0.21459432f, 0.51595575f,
- -0.17949812f, -0.33173642f, -0.28197125f, -0.23081449f,
- -0.16893443f, 0.28274524f, 0.17797032f, 0.30712095f,
- -0.3914206f, -0.30918467f, -0.44586143f, -0.046529006f,
- 0.7055027f, -0.24675028f, -0.117242835f, 1.0921177f,
- 0.941259f, -0.2658568f, -0.09274022f, -0.059668887f,
- 1.0152694f, -0.054766774f, 0.66743547f, -0.29585347f,
- 0.07551295f, -0.11757679f, 0.21741603f, -0.309914f,
- -0.16273472f, -0.11267593f, 0.33042732f, 0.754229f,
- 0.409853f, -0.31491104f, -0.21907197f, -0.27077353f,
- 0.32843772f, -0.08161764f, -0.18167268f, -0.2986215f,
- 0.5141131f, -0.26793587f, -0.34087163f, 0.085759014f,
- -0.01903612f, -0.6157404f, -0.037903998f, -0.31655395f,
- -0.19305907f, 1.3992374f, -0.13540603f, -0.08196486f,
- 1.3798162f, 0.76063615f, -0.24171044f, 0.022622263f,
- -0.47705385f, -0.5362687f, -0.26611617f, -0.39651668f,
- -0.39066416f, -0.19360238f, -0.28865144f, -0.096597396f,
- -0.28010634f, 0.18819515f, -0.22736768f, -0.29506963f,
- -0.17116012f, 0.65050405f, -0.8111549f, -0.3252069f,
- -0.27406698f, 1.4660335f, -0.07711788f, -0.045452353f,
- 1.1312827f, 1.1216697f, 0.31858113f, -0.0391304f,
- -0.18109153f, -0.052308403f, -0.27464575f, -0.48307663f,
- -0.11658943f, 0.29241666f, 0.099433504f, -0.2254438f,
- -0.50037336f, -0.5877589f, -0.48281798f, -0.26277947f,
- 0.93972933f, -0.3634974f, -0.002067816f, -0.4833337f,
- -0.11474459f, 0.52443606f, 0.11064332f, 0.009806723f,
- 0.03170172f, 0.2076377f, -0.09759824f, -0.14115584f,
- 1.1113065f, -0.28889543f, -0.43727553f, -0.258321f,
- -0.22731048f, -0.53716195f, -0.13738869f, -0.2995844f,
- -0.17220157f, 1.1118493f, -0.096830405f, 0.05356518f,
- -0.2252851f, -0.2627298f, -0.19105032f, -0.35500923f,
- -0.008669335f, 0.2003516f, 1.4715651f, -0.3987353f,
- -0.64931375f, -0.39305747f, -0.2762218f, -0.52125645f,
- -0.671072f, -0.101259895f, -0.26155275f, -0.2952287f,
- -0.40770754f, -0.46642047f, 1.1833447f, -0.30738777f,
- 0.20641255f, 0.31142384f, -0.11420632f, 0.83841753f,
- -0.4109211f, 0.8820925f, -0.41951123f, -0.25370637f,
- -0.37969297f, 1.8584865f, -0.2644631f, -0.0053983326f,
- -0.28429472f, -0.28290382f, -0.22217144f, -0.020445641f,
- 0.42438716f, 0.776333f, 0.38944095f, -0.116780706f,
- -0.06274362f, -0.07208352f, 0.9444413f, -0.062188096f,
- -0.07198502f, 0.18919031f, 0.84666556f, -0.03013066f,
- -0.054672264f, -0.065065f, -0.36693156f, -0.029698957f,
- -0.056587007f, -0.022753587f, -0.09509279f, 0.7897125f,
- -0.07059489f, -0.1095679f, -0.063223846f, -0.21758337f,
- -0.084569804f, -0.066258796f, -0.11289297f, -0.39340195f,
- -0.119664505f, -0.051373146f, -0.33591354f, -0.087491795f,
- -0.10903081f, 0.36392537f, 0.41548464f, -0.0760726f,
- 0.42047337f, -0.18491706f, -0.08421229f, -0.097386956f,
- 0.048453905f, -0.092893764f, -0.1881688f, -0.021364916f,
- -0.26466775f, -0.23100258f, -0.10551516f, -0.20532992f,
- -0.023528762f, -0.31158167f, 0.7306521f, -0.0911788f,
- -0.15887104f, -0.09737608f, -0.078449115f, -0.0651377f,
- -0.037320957f, -0.045032755f, -0.054492854f, -0.060422845f,
- -0.08861498f, 0.8946291f, 0.28511244f, -0.07843334f,
- -0.026759174f, -0.11240678f, -0.09641634f, -0.052680586f,
- -0.1551209f, -0.03819081f, 0.23023885f, -0.039929394f,
- -0.0039905403f, -0.071457446f, -0.061053656f, -0.07044543f,
- -0.06317892f, -0.073645145f, -0.11852998f, 0.07896845f,
- -0.06943871f, -0.33611774f, -0.20395131f, -0.061943308f,
- -0.119481556f, 0.16702503f, -0.100533195f, -0.06450602f,
- -0.07784014f, -0.10271165f, -0.0431425f, 0.34844488f,
- -0.13604622f, -0.015630107f, -0.037789196f, -0.043594968f,
- 0.97279876f, -0.20556933f, 0.5198342f, -0.18994465f,
- -0.066684015f, -0.03570855f, 0.5017013f, -0.123929076f,
- -0.11329955f, -0.05550015f, -0.14055866f, -0.079359405f,
- -0.041256778f, -0.06922219f, 0.58959687f, -0.13469343f,
- -0.18119538f, -0.15700148f, -0.16294366f, 0.59792787f,
- -0.08398339f, 0.16268249f, 0.5419678f, -0.14056246f,
- -0.11958746f, 0.092664994f, -0.19050504f, 0.2862071f,
- -0.1430317f, -0.06626164f, -0.079397604f, 0.047507692f,
- -0.22863902f, -0.14855945f, -0.20025685f, 0.04306697f,
- -0.2018535f, -0.0065508643f, -0.17957689f, -0.24198946f,
- 0.2815782f, -0.07403094f, -0.12727404f, -0.07580935f,
- -0.13094077f, -0.09881406f, 0.7020888f, 0.27029076f,
- -0.0942998f, 0.2798589f, -0.020457804f, -0.047841035f,
- -0.06331061f, 0.6576577f, -0.14834933f, 0.27041247f,
- -0.16701624f, -0.28742322f, -0.14285341f, -0.1856053f,
- -0.13970138f, -0.056274556f, 0.2272693f, -0.115590446f,
- -0.12849468f, -0.17515771f, -0.09727338f, -0.07453157f,
- -0.15401903f, 0.093342245f, -0.08228671f, -0.054974984f,
- -0.09880404f, -0.16909185f, 0.9500688f, -0.16975498f,
- -0.20191173f, -0.073964104f, -0.14240597f, -0.20876297f,
- -0.290756f, -0.04217453f, -0.057919633f, 0.6057254f,
- -0.13195492f, -0.11828813f, -0.023878423f, -0.20829f,
- 0.16202651f, -0.19229351f, -0.06258276f, -0.016589751f,
- 0.3101017f, -0.25553778f, 0.22549435f, -0.14161143f,
- -0.09858449f, -0.17238179f, 0.55338514f, -0.014224529f,
- -0.102916814f, -0.13546126f, -0.16596602f, -0.18953784f,
- 0.6382119f, -0.21539615f, -0.13562426f, -0.06709947f,
- 0.024162782f, 0.6146526f, 0.37627488f, 0.32029608f,
- -0.21215783f, -0.11478509f, -0.09855825f, 0.99515456f,
- -0.29178047f, -0.12810925f, -0.17154033f, -0.083400205f,
- -0.10678319f, -0.073997796f, 0.0017491526f, 0.46106514f,
- -0.32722238f, -0.028743248f, -0.042994447f, -0.04729599f,
- -0.05055562f, -0.035043553f, -0.043710172f, 0.013663257f,
- -0.13275062f, -0.06422124f, -0.07242309f, -0.07933046f,
- -0.053735122f, -0.075649746f, -0.016085865f, -0.058615748f,
- -0.06235076f, 0.94426465f, -0.10465085f, -0.030571606f,
- -0.08299737f, 0.11763736f, -0.035336226f, -0.08037645f,
- -0.048299316f, 0.004799456f, -0.15896179f, -0.07336131f,
- -0.08601184f, -0.072001606f, -0.05080328f, -0.021402678f,
- -0.13584365f, -0.07597565f, 0.6131727f, -0.07109904f,
- -0.07966081f, -0.071425214f, 0.8598394f, -0.09713082f,
- -0.29034746f, -0.054596227f, -0.10699629f, -0.19410565f,
- -0.01953323f, -0.08439403f, -0.023351742f, -0.06595297f,
- 0.9096976f, -0.09254017f, -0.091247804f, -0.104555376f,
- -0.050505005f, -0.03427561f, -0.023164783f, -0.017060485f,
- -0.038872488f, -0.06353561f, -0.089330874f, -0.10431604f,
- 0.99973905f, 0.021471592f, -0.06743297f, -0.08774727f,
- 0.06375376f, 0.009428137f, 0.044771954f, -0.04953318f,
- -0.029829595f, -0.054610133f, -0.05485423f, -0.043654002f,
- -0.015139999f, -0.042373434f, -0.06566151f, -0.08184453f,
- -0.19792041f, 0.017653372f, -0.051893055f, -0.06594828f,
- 0.71327555f, -0.031774685f, -0.089574635f, 0.83452964f,
- -0.14605248f, -0.05433031f, 0.08824958f, -0.06221862f,
- -0.06668762f, -0.005956759f, -0.09549919f, -0.03786885f,
- -0.034267496f, -0.07178119f, -0.08932844f, -0.2259229f,
- -0.032398786f, -0.030790122f, -0.055349566f, -0.002424822f,
- -0.08656331f, -0.0703777f, -0.062407196f, -0.06083332f,
- -0.08825082f, -0.052404065f, -0.062566504f, -0.07256746f,
- 0.2913167f, -0.1470722f, -0.039360005f, -0.035210155f,
- -0.044251427f, 0.11552375f, -0.022341458f, -0.066829205f,
- -0.096798725f, -0.063183725f, -0.06760818f, -0.06458579f,
- -0.06891958f, 0.4412134f, -0.06957202f, -0.05806895f,
- -0.045028217f, -0.05032876f, 0.8975511f, -0.12090565f,
- -0.10985369f, -0.07108896f, 0.09599575f, -0.088957556f,
- -0.06469386f, -0.09412986f, 0.7515798f, -0.19107202f,
- -0.041756943f, -0.16957481f, -0.041114725f, -0.06335472f,
- -0.121800005f, -0.20190737f, -0.07006342f, 0.61253f,
- -0.18716183f, -0.08204743f, -0.057866532f, 0.7629332f,
- -0.07774633f, -0.3513167f, -0.04313249f, -0.1330926f,
- -0.2070185f, -0.03492167f, -0.08866682f, -0.036374882f,
- -0.075132474f, 0.96358985f, -0.06950785f, -0.10340077f,
- -0.077935375f, -0.07234064f, -0.055237636f, -0.033666126f,
- -0.032296717f, -0.036681168f, -0.059149086f, -0.09589494f,
- 0.08490658f, 0.91670454f, -0.02471843f, -0.064399384f,
- -0.115547806f, -0.08087424f, -0.038299613f, -0.034232315f,
- -0.04103469f, -0.121116176f, -0.049360335f, -0.040520187f,
- -0.05985734f, -0.035740335f, -0.05222802f, -0.061272863f,
- -0.070330866f, -0.18400162f, -0.109604105f, -0.057170745f,
- 0.25353804f, 0.5231055f, -0.050647404f, -0.07240231f,
- 0.75892055f, -0.15637983f, -0.07603429f, 0.02742856f,
- -0.032671157f, -0.074855134f, -0.107632004f, -0.08873356f,
- -0.04159863f, -0.051961318f, -0.06414285f, 0.2819072f,
- -0.2721639f, 0.036123447f, -0.09808816f, -0.065422505f,
- -0.05121401f, -0.08389359f, -0.070815906f, -0.0679937f,
- -0.06680681f, -0.08622717f, -0.065473095f, -0.054090988f,
- -0.089790314f, 0.028781211f, -0.15510309f, -0.3936104f,
- -0.6871601f, -0.14110611f, -0.48341605f, -0.63830096f,
- -0.5986485f, 0.5421424f, 0.6366408f, 0.18702425f,
- -0.26009446f, -0.04113794f, -0.59152365f, 0.31801268f,
- -0.2696009f, 0.110231064f, -0.29248455f, -0.18921049f,
- -0.440438f, -0.3698464f, -0.57125723f, 1.312835f,
- 0.46859616f, -0.54471695f, -0.1117671f, -0.035912026f,
- -0.29209283f, -0.2182037f, -0.45680085f, -0.3848514f,
- -0.5296833f, 0.57239497f, -0.23050979f, -0.5971309f,
- -0.03787801f, 1.9865607f, -0.7369276f, -0.1806398f,
- 0.21694459f, 0.26301563f, 0.9612775f, -0.31322363f,
- 1.2776724f, 1.4590065f, 2.3543935f, -0.6251941f,
- -0.21727075f, 1.0860333f, 0.014526173f, -0.3359564f,
- -0.7250731f, -0.33619526f, 0.8902602f, 0.10907831f,
- -0.2084788f, -0.15756932f, 0.20773862f, -0.22895356f,
- 0.20640416f, -0.081736006f, 0.8395877f, 2.0850284f,
- -0.44723743f, -1.1548747f, 2.2649758f, -0.07522746f,
- 2.1797009f, -0.46528402f, -0.12573896f, -0.38056135f,
- -0.34505847f, -0.32081446f, -0.37155008f, -0.5786969f,
- -0.19767553f, -0.19104828f, -0.65768087f, -0.8577443f,
- -0.49067798f, -0.5662055f, -0.28582495f, -0.59479266f,
- 0.652592f, 1.2410014f, 0.707616f, -0.40425298f,
- 0.14172266f, 0.78643674f, -0.2942635f, -0.8541957f,
- -0.47208092f, -0.21840964f, 0.19709621f, -0.25069535f,
- 0.9402872f, 0.10707666f, -0.44711518f, -0.23000924f,
- -0.12361525f, -0.21011922f, -0.38953093f, -0.4893139f,
- -0.51398516f, -0.38510203f, -0.2212714f, -0.54052f,
- -0.22345376f, -0.64199305f, 1.0607197f, 0.19225277f,
- -0.089671604f, -0.07168395f, -0.06022892f, 0.6034475f,
- -0.06009694f, -0.16257541f, 0.16442399f, 0.6225429f,
- -0.050219603f, -0.06741467f, -0.07658508f, 0.037004944f,
- -0.029793024f, -0.020363497f, -0.04385221f, -0.0738956f,
- 0.96222687f, -0.12318149f, -0.07766631f, -0.06540571f,
- -0.22748022f, 0.0044091954f, -0.11352061f, -0.13528267f,
- 0.07389047f, -0.19667062f, -0.07865617f, -0.13001938f,
- -0.1147188f, -0.10329355f, -0.14049402f, 0.28477153f,
- -0.07905342f, 0.322308f, -0.13249089f, -0.11595827f,
- -0.09485982f, -0.109610505f, -0.12221478f, -0.17032696f,
- -0.034506362f, -0.050673585f, -0.28279212f, -0.073785596f,
- -0.20728989f, 0.014931776f, -0.089648016f, 1.0182079f,
- -0.0692512f, -0.11751121f, -0.15288432f, -0.10820075f,
- -0.1074598f, -0.029030453f, -0.017474681f, -0.06421649f,
- -0.06357068f, -0.06973008f, -0.0164264f, 0.34557718f,
- -0.04820986f, -0.065694466f, -0.10337629f, -0.08620217f,
- -0.055942826f, -0.14532559f, -0.06382064f, 0.16184337f,
- -0.04107333f, -0.041030623f, -0.03400424f, -0.06690246f,
- -0.08422113f, -0.06816121f, -0.051188003f, -0.1113173f,
- -0.092377335f, -0.06878217f, 0.045285143f, 1.1060387f,
- -0.06375569f, -0.108425654f, -0.030234318f, -0.049240347f,
- -0.05037751f, -0.14211522f, -0.07681116f, -0.026614208f,
- 0.37773642f, -0.12969248f, -0.018893588f, -0.053072464f,
- -0.053790472f, 0.55269694f, -0.17072013f, 1.1151934f,
- -0.23076533f, -0.052655272f, -0.043887656f, 0.38720253f,
- -0.07323822f, -0.10583532f, -0.048918065f, -0.14746442f,
- -0.08330519f, -0.056922022f, -0.09812631f, -0.20342727f,
- -0.15581359f, -0.23996182f, -0.26229024f, -0.19840597f,
- 0.8286727f, -0.17475832f, -0.3412072f, 0.3889102f,
- 0.057768658f, -0.07320755f, -0.3157529f, -0.28036848f,
- 1.1778053f, 0.18303211f, -0.31581733f, -0.23185495f,
- -0.22605902f, -0.0937265f, -0.08232862f, -0.16645472f,
- -0.0822089f, 0.16440654f, -0.20742607f, -0.22766928f,
- 0.085628174f, 1.2993492f, 1.0032774f, -0.13896543f,
- 1.3436822f, -0.058168706f, -0.10604448f, 0.7057234f,
- 0.2594556f, -0.2701915f, -0.15950266f, -0.022401724f,
- -0.16810857f, -0.38676235f, -0.17874911f, -0.11615147f,
- 0.18746102f, -0.14182213f, 0.090781815f, -0.4055478f,
- -0.28703347f, -0.30734333f, -0.24603401f, -0.3015952f,
- 0.3807993f, -0.22389089f, -0.14513671f, -0.07659382f,
- 0.0009217367f, -0.00045803547f, -0.11399941f, -0.095874675f,
- 0.01837974f, -0.21991147f, -0.13609979f, -0.23689087f,
- -0.4576404f, -0.06383955f, -0.17607364f, -0.24291885f,
- -0.19917563f, -0.04267644f, -0.26176292f, -0.28402472f,
- 0.31846285f, -0.23158818f, -0.1965824f, -0.34937894f,
- 6.629092e-06f, -0.23945756f, -0.31535244f, -0.29625672f,
- -0.25282654f, 0.57824945f, -0.051298037f, 1.1017294f,
- 0.5329614f, -0.046684258f, -0.16038102f, -0.1910699f,
- -0.10856496f, -0.06993149f, -0.17439115f, -0.2215598f,
- -0.26537454f, 0.41048706f, -0.25570795f, -0.1610854f,
- -0.073604055f, -0.022336088f, 0.07690177f, -0.16054335f,
- 1.663433f, -0.11072177f, 0.0070353546f, -0.09489951f,
- 1.6620897f, -0.041914135f, -0.17078778f, -0.13695748f,
- -0.12774363f, 0.00027010948f, 0.015975667f, 0.16038011f,
- -0.24837296f, -0.13544177f, -0.05630607f, -0.6258479f,
- -0.040891282f, -0.086992726f, 0.09491489f, 0.19328663f,
- 0.06503682f, 0.79812634f, 0.27135232f, -0.21994963f,
- -0.24782996f, 1.111824f, -0.07675395f, -0.25034353f,
- -0.018901672f, -0.113868676f, 0.13096133f, -0.06364784f,
- -0.2023831f, -0.16248722f, -0.06724962f, -0.30153912f,
- -0.06334667f, -0.24934398f, 1.5440059f, 1.4364374f,
- -0.15525308f, 0.8847394f, -0.016591191f, -0.020828797f,
- -0.14454818f, -0.063447505f, -0.32114434f, -0.32817155f,
- 0.17935331f, -0.29628658f, 0.15406317f, -0.06492844f,
- -0.438983f, -0.13455357f, -0.24438438f, -0.36046827f,
- 0.4532917f, -0.293702f, -0.08517518f, -0.18197113f,
- 0.030843185f, 0.4040661f, -0.121532455f, 0.10152938f,
- -0.2148665f, 0.110436246f, -0.47642204f, 0.4388345f,
- 0.057591695f, -0.104783714f, -0.056428064f, 0.13565846f,
- -0.12915663f, 0.14244069f, 0.13667929f, -0.13251483f,
- -0.29087546f, -0.1203098f, -0.42154714f, -0.2771785f,
- -0.09072192f, -0.02979335f, 0.03630208f, -0.435657f,
- -0.35987523f, -0.017226018f, -0.08981669f, -0.3564257f,
- -0.33502516f, -0.48028418f, -0.34376487f, -0.21347739f,
- 1.255328f, 1.3485439f, 0.18028109f, 0.22427832f,
- -0.13325785f, 0.2187483f, 0.008196652f, 1.7224567f,
- -0.23315011f, -0.29572523f, 0.036879435f, 0.04936485f,
- -0.250861f, -0.08812593f, -0.15061389f, -0.17695872f,
- 0.04278201f, 1.023979f, -0.32596982f, -0.0045110225f,
- -0.018216144f, -0.17032687f, -0.10287703f, -0.11975308f,
- -0.18251885f, -0.467592f, -0.24095191f, -0.27485374f,
- -0.011194792f, -0.22325878f, -0.4480527f, 0.12208198f,
- 0.18877812f, 2.87885f, 0.03186317f, 1.2796358f,
- -3.108949f, -1.0736262f, -0.33522302f, -0.21511343f,
- -1.0384598f, 3.686992f, 1.0870631f, 1.5552096f,
- 0.14301623f, -2.8466997f, -2.598375f, 0.92309636f,
- -1.8955235f, -0.5023821f, -0.06750815f, -0.9991937f,
- -1.0681999f, -0.90721f, -1.4162838f, 0.27411297f,
- -0.0437628f, 3.1273363f, -0.37763023f, -2.0693135f,
- -2.5393684f, 0.6156992f, 0.7230575f, 3.078414f,
- 0.8402767f, -0.48283893f, 1.8883166f, -2.0204337f,
- 0.35348842f, -0.6925758f, -2.2665513f, -2.5739388f,
- -0.97508013f, 0.17457983f, 0.21523553f, 3.0698304f,
- 2.0488772f, -0.04698827f, 0.725493f, -2.6686933f,
- -3.1303885f, 1.5086265f, -1.2667001f, -2.161968f,
- 3.69257f, -2.9851363f, -3.3084288f, 2.09924f,
- -2.1674562f, 0.61657834f, -0.2894859f, 3.55339f,
- 2.1631138f, -1.0691493f, 0.41665584f, -2.4042554f,
- -1.1555227f, -1.7248977f, 0.9129453f, 0.5146471f,
- 3.2225816f, -2.8078773f, -2.1248164f, 0.8647357f,
- -3.2863097f, -0.13160169f, -2.5303507f, 1.1353806f,
- -1.6288954f, -0.7999279f, -0.23795238f, -3.5827637f,
- 4.1388426f, -0.32341865f, -1.6183394f, 2.4686892f,
- 0.047994234f, 1.981853f, 5.4607363f, -0.43045703f,
- -1.3343092f, 3.7452943f, -2.125115f, -2.496219f,
- -0.23255055f, 1.4266872f, 0.086633675f, -0.3378629f,
- 0.5970446f, 2.3787327f, 0.0057819854f, 3.1453817f,
- 6.2444797f, -1.6306367f, 4.504973f, 1.7945317f,
- -1.5674568f, 1.9581947f, -0.11251673f, -3.8837426f,
- -0.0516389f, -0.17886324f, -0.06521383f, 0.34992212f,
- -0.081230775f, -0.21589838f, -0.11832723f, 0.4853736f,
- -0.055448253f, -0.11712475f, -0.14085262f, 0.8330868f,
- -0.065506786f, -0.10779949f, -0.0894915f, -0.10442487f,
- 0.122607864f, -0.07648926f, -0.07389324f, -0.06877835f,
- -0.11355837f, -0.095591344f, -0.036078937f, -0.12953395f,
- 0.9238821f, 0.71522033f, -0.055465158f, 0.89555496f,
- -0.044427272f, -0.053126015f, 0.052819937f, -0.048424616f,
- -0.0866192f, -0.16020842f, -0.1941483f, -0.119650446f,
- -0.14910084f, -0.06654389f, -0.12776288f, -0.06541469f,
- -0.08131638f, -0.07926799f, -0.08684444f, -0.059120424f,
- -0.16389224f, -0.036649175f, -0.03974131f, 0.54220486f,
- 0.0024924406f, -0.021825219f, -0.10993243f, -0.05590275f,
- -0.09733803f, 0.038934533f, -0.019221663f, -0.05190304f,
- -0.09184466f, -0.014595233f, -0.1902995f, -0.17041509f,
- -0.03796463f, -0.0893188f, -0.11852292f, -0.1281945f,
- -0.11315615f, -0.13127977f, -0.13241822f, -0.07468169f,
- -0.033658348f, -0.119504765f, -0.1947371f, -0.015301468f,
- -0.09592379f, -0.08543175f, -0.122525245f, -0.20342395f,
- -0.13373546f, -0.043088693f, 0.8241273f, 0.75544983f,
- 0.0076313773f, -0.057446014f, -0.08147865f, -0.08528507f,
- -0.03342426f, 0.428709f, -0.04591254f, -0.07603531f,
- 0.059003405f, -0.06559652f, -0.089635536f, -0.06977284f,
- -0.062321845f, 0.06663681f, -0.12834664f, 0.94926894f,
- -0.13967703f, -0.06901727f, -0.046781726f, 0.57153857f,
- -0.074496776f, -0.14911404f, -0.040746212f, -0.22785394f,
- -0.11912901f, -0.11049225f, -0.09019215f, -0.1238597f,
- -0.22577223f, -0.24214976f, -2.5951147f, 0.21187973f,
- 0.10439469f, -1.4114659f, 2.6448472f, 2.3398993f,
- 0.1661445f, -0.9035961f, -1.4433118f, -2.3000243f,
- -0.27279645f, -1.7444919f, -2.0950308f, 2.8807888f,
- 1.4388257f, 0.09094748f, -0.49957177f, -1.0525507f,
- -0.71422344f, 1.0432789f, -1.2602937f, -1.4761603f,
- 0.16534302f, 0.1122405f, 0.7207526f, 2.567971f,
- 0.095635265f, -1.7541945f, -2.2821848f, 0.29451162f,
- -1.0852464f, 0.88377696f, 0.10862301f, 3.6523676f,
- -3.1670964f, -1.6276423f, 0.068609275f, 2.0036118f,
- -0.9828637f, 1.8633059f, 0.83532906f, 0.13898885f,
- 1.4089806f, -1.1658419f, 4.201665f, -0.24582803f,
- -0.014516723f, -0.92175126f, -0.0902266f, 1.7170992f,
- 3.1436582f, -0.21104744f, -1.4902972f, -1.4379964f,
- -0.78620386f, 0.41082668f, 0.08870563f, 0.02697306f,
- -0.0054978374f, 1.4972819f, -2.087572f, 0.11665725f,
- -1.1088407f, 2.9927135f, 0.4958253f, 2.2390404f,
- 1.2024227f, 1.2168853f, -1.8505324f, 1.2747138f,
- -1.4168506f, -2.7118294f, -1.6183568f, -2.339058f,
- -1.7410434f, -1.0571346f, 1.3631543f, 0.79097086f,
- -0.20333518f, -2.385979f, -1.4745524f, 1.5210557f,
- 6.390226f, 1.3064474f, 0.2557482f, -1.3873416f,
- -1.9484283f, -0.23593266f, -1.9839154f, 5.460731f,
- 1.1168587f, -2.1446116f, -0.07835669f, -1.327334f,
- 0.5614238f, -1.0012245f, 3.0041206f, 1.3204999f,
- -0.24252565f, -1.501688f, 4.6275783f, -1.9050139f,
- -1.6067029f, -0.7654905f, -2.4987843f, 0.41674078f,
- -0.055697974f, -0.6434283f, 0.028240897f, -0.107436456f,
- -0.34211653f, 0.8124057f, 0.05690035f, 0.45838237f,
- 0.053965934f, -0.14781362f, -0.15514368f, 0.20712112f,
- -0.2094119f, 0.7673072f, -0.17918111f, -0.04754815f,
- 0.19501598f, 0.11043532f, -0.53661865f, -0.16336656f,
- -0.2790585f, 0.29175586f, -0.12281481f, -0.05073921f,
- -0.293534f, -0.32408285f, 0.7749426f, -0.36763003f,
- -0.12530522f, 1.3919144f, -0.18815465f, -0.1204796f,
- 1.3559841f, -0.52072f, -0.17447667f, 0.042320684f,
- -0.004749848f, -0.19015357f, 0.066850446f, -0.022798033f,
- -0.31369767f, 0.4770239f, -0.17460752f, -0.44241488f,
- -0.42191112f, -0.37382326f, -0.21740636f, -0.0947546f,
- 1.3336773f, -0.46812144f, -0.1148556f, 0.11985874f,
- -0.05502441f, -0.08537165f, -0.34886762f, 0.07633385f,
- -0.16757539f, -0.099514514f, -0.15453476f, -0.1142746f,
- 1.2350982f, -0.32645386f, -0.56266916f, -0.047571667f,
- -0.4373675f, -0.40893388f, -0.3732906f, -0.028045222f,
- -0.187201f, 0.15948337f, -0.03940627f, -0.33267018f,
- 0.05321082f, -0.3150151f, 0.2793323f, -0.12884939f,
- 0.11673832f, -0.22630468f, -0.22881848f, -0.3472099f,
- 0.71284276f, -0.26832172f, -0.19700864f, -0.11546919f,
- -0.018624926f, -0.011418737f, -0.030239863f, -0.33591104f,
- -0.2532144f, -0.3778896f, 0.3481635f, -0.11505579f,
- -0.23554312f, 0.0378323f, 0.09722584f, 1.270829f,
- 0.6865386f, 0.25906295f, -0.31166273f, -0.2661119f,
- -0.21564032f, 2.2551768f, -0.42260286f, -0.04943927f,
- -0.1953253f, -0.1649484f, -0.24279307f, -0.29325023f,
- 0.057417527f, 0.7777043f, -0.5320563f, -0.034266148f,
- -0.11254332f, -0.06729523f, 0.5474494f, -0.079769574f,
- -0.089834906f, -0.17674474f, 0.1726467f, -0.042579196f,
- -0.08525818f, -0.08570517f, 0.24692257f, -0.10096744f,
- -0.087856025f, -0.09756702f, -0.07607908f, 0.518392f,
- -0.06695463f, -0.15330924f, -0.09991465f, 0.026819209f,
- -0.099957004f, -0.072379805f, -0.039140936f, 0.32966712f,
- -0.076963834f, -0.07474464f, -0.13613437f, -0.049978863f,
- -0.038713023f, -0.014085761f, -0.20939642f, -0.07179952f,
- 0.45727706f, -0.1482781f, -0.031934038f, -0.07345243f,
- 0.7163329f, -0.10007469f, -0.30500412f, -0.06225395f,
- -0.19855049f, -0.0987294f, -0.06715272f, -0.13006717f,
- 0.06658285f, -0.12261445f, 0.6714044f, -0.059876353f,
- -0.07046488f, -0.10040871f, -0.08134645f, -0.0050129504f,
- -0.0021754822f, -0.016717184f, -0.047175363f, -0.067463085f,
- -0.06822163f, 0.8902359f, 0.22749189f, -0.044956245f,
- -0.03690575f, -0.087383755f, -0.09973027f, -0.0120323505f,
- -0.004710382f, -0.07255326f, -0.048610717f, -0.05955762f,
- -0.02082425f, -0.08118147f, -0.023817474f, -0.08482618f,
- -0.09884793f, -0.06380515f, -0.19409084f, -0.07959464f,
- -0.07538026f, 0.23514561f, -0.11489943f, -0.06336908f,
- -0.09006662f, 0.64978534f, -0.14694186f, -0.069745414f,
- -0.10380541f, -0.0699669f, -0.0672005f, -0.12174159f,
- -0.09563721f, -0.020030048f, -0.04064674f, -0.014259389f,
- 1.1440009f, -0.15910546f, 0.20312667f, -0.08815582f,
- -0.07352142f, -0.06397113f, 0.29123303f, -0.11906115f,
- -0.07026744f, -0.10647203f, -0.069706336f, -0.097279154f,
- -0.00642807f, -0.045994032f, 0.074388005f, -0.15244494f,
- -0.22166829f, -0.08293725f, -0.12511714f, 0.9437378f,
- -0.14836587f, -0.15229075f, 0.8642379f, 0.89542234f,
- -0.075540535f, -0.102629304f, -0.15717499f, -0.36208114f,
- -0.06429368f, -0.15357521f, -0.083328985f, -0.16067784f,
- 0.23755592f, -0.18977557f, -0.099098094f, -0.061652377f,
- -0.3317063f, -0.23623069f, -0.13596357f, -0.15922824f,
- -0.4966196f, 0.864894f, -0.08963129f, 0.7690028f,
- -0.10897605f, -0.11028661f, 0.7749231f, 1.0087187f,
- -0.13044399f, -0.025778389f, -0.28799987f, -0.15207951f,
- -0.24842629f, -0.2757844f, 0.02361623f, -0.043290127f,
- -0.1447984f, -0.18001802f, 0.019175272f, -0.27023965f,
- -0.22765517f, 0.04043788f, -0.40203205f, 0.27131957f,
- -0.1553757f, -0.25671571f, -0.13909379f, -0.09732643f,
- -0.1401118f, -0.09369078f, -0.079866484f, 0.00610822f,
- -0.08460772f, -0.18669473f, -0.46651238f, -0.16936249f,
- -0.17899896f, -0.11285141f, -0.051550094f, -0.21705171f,
- -0.078117736f, -0.37530527f, -0.057651404f, 0.78304523f,
- -0.030802712f, -0.0772589f, -0.071398534f, -0.095002934f,
- -0.110136375f, -0.13903104f, -0.112977184f, -0.08317634f,
- 1.1770389f, -0.04984675f, -0.38594395f, 1.1400714f,
- -0.0051820674f, -0.1585265f, -0.283151f, -0.0681837f,
- -0.11492812f, -0.35002083f, -0.2536217f, -0.053485602f,
- 0.8206733f, -0.16219781f, -0.096090265f, -0.09493635f,
- -0.11592265f, 0.21757424f, -0.21064611f, 1.8541949f,
- -0.3693859f, -0.048756305f, -0.0022499154f, 0.80169636f,
- -0.011940004f, -0.12916818f, -0.056409076f, -0.025844961f,
- -0.013632178f, -0.070418485f, -0.123048745f, -0.18236803f,
- -0.101392694f, -0.27350533f, -0.4236556f, -0.47536093f,
- 0.8769839f, -0.3141493f, -0.58843386f, -0.28842857f,
- -0.15328166f, -0.08565826f, -0.3115036f, -0.3181577f,
- 1.9656056f, 0.28996056f, -0.22072399f, -0.33019423f,
- -0.24620819f, -0.313304f, 0.02074711f, -0.24783294f,
- -0.23637173f, 1.2038132f, -0.15244418f, -0.051758826f,
- 0.15481965f, 2.20401f, -0.007877783f, -0.21501912f,
- 0.59210503f, -0.36745045f, -0.3476092f, 0.71496195f,
- -0.22121133f, -0.18468957f, 0.08166135f, -0.30416685f,
- -0.19723016f, -0.43889472f, 0.60547024f, -0.19152898f,
- 0.8388301f, -0.29237762f, -0.0304208f, -0.25314304f,
- -0.23756765f, -0.33858556f, -0.45586225f, 1.6189517f,
- 0.32231963f, -0.31700218f, -0.14212704f, 0.019928256f,
- -0.15206398f, 0.12323535f, 0.15334916f, 0.056639813f,
- -0.05993669f, -0.25479233f, 0.09329642f, 0.808599f,
- -0.12795435f, -0.3496992f, -0.19890569f, -0.23094466f,
- -0.30692205f, 0.3394054f, -0.21157038f, -0.35089862f,
- 0.023494061f, -0.47265223f, -0.32019818f, -0.33800572f,
- 0.01706935f, -0.24367741f, -0.023182837f, -0.39783332f,
- -0.5009299f, -0.3357312f, -0.092499115f, 2.003869f,
- -0.23284096f, -0.11220179f, -0.089949995f, 0.718079f,
- -0.38842505f, -0.18609765f, -0.37396353f, -0.22889386f,
- -0.30734375f, -0.22946718f, -0.27257153f, -0.20638336f,
- -0.003938806f, 0.36863068f, 0.95922655f, -0.27954465f,
- -0.31388757f, -0.20424613f, 0.20409702f, -0.09201176f,
- 1.341637f, -0.1963476f, -0.5924843f, -0.38372713f,
- -0.012978113f, -0.14704001f, -0.15131174f, 0.068868175f,
- 1.2191799f, -0.45240316f, -0.16750194f, -0.07413088f,
- -0.13709836f, 0.9387687f, -0.08785482f, -0.13186547f,
- 0.6846859f, 0.6461645f, -0.079676874f, -0.06254926f,
- -0.11875406f, -0.18634342f, -0.0328063f, -0.08923244f,
- -0.08677594f, -0.10948124f, 0.06361078f, -0.15987346f,
- -0.14898305f, -0.10696282f, -0.11166044f, -0.07643978f,
- -0.082019486f, -0.20373961f, -0.31802693f, 0.21387215f,
- -0.107102536f, 0.63413364f, -0.08154789f, -0.108993165f,
- 0.45765254f, 0.85516137f, -0.10416374f, 0.058113858f,
- -0.16253124f, -0.12357659f, -0.1878467f, -0.17487063f,
- 0.092777f, 0.076620474f, -0.09499117f, -0.13254623f,
- -0.11628188f, -0.16751277f, -0.17632028f, -0.0032560702f,
- 0.30859056f, 0.11792222f, -0.10965748f, -0.123912185f,
- -0.03509983f, -0.061692744f, -0.11264564f, -0.08096792f,
- -0.087648265f, -0.05455177f, -0.09004864f, -0.17098315f,
- 0.091088794f, -0.147479f, -0.0777283f, -0.08170731f,
- -0.024346227f, -0.15983938f, -0.08576735f, -0.26230934f,
- -0.027043862f, 0.5973316f, -0.016992483f, -0.05596025f,
- -0.17122313f, -0.10728685f, -0.07924012f, -0.18734471f,
- -0.13454166f, -0.049337868f, 0.67648953f, -0.10849943f,
- -0.22358969f, 0.17674917f, 0.011582152f, -0.09180303f,
- -0.25401607f, 0.0076309033f, -0.11254041f, -0.2544536f,
- -0.17932776f, -0.104657374f, 0.74358505f, -0.09546649f,
- -0.08929494f, -0.03447571f, -0.09088517f, 0.20773406f,
- -0.1182133f, 0.7738339f, -0.23740825f, -0.029640198f,
- -0.025777424f, 0.74439424f, -0.057431296f, -0.18521981f,
- -0.100836575f, -0.045723423f, -0.038980316f, -0.008829578f,
- -0.09696799f, 0.3936308f, -0.07337195f, -3.340232f,
- -3.8359175f, -3.1883633f, -0.06421821f, -4.030377f,
- -2.6209671f, -0.047693323f, -0.55253524f, 9.086362f,
- 2.4490023f, 6.315959f, 1.0069863f, -1.714906f,
- 0.7810963f, 2.3456595f, -0.20269361f, 0.8118041f,
- -0.9356693f, -2.0425913f, -0.34181473f, -0.29670584f,
- -0.5788275f, -1.8649201f, -1.2779442f, -0.9333532f,
- 1.084235f, 2.046154f, -0.4459758f, -4.356723f,
- -4.225176f, 0.065317035f, -0.25614518f, -5.3963437f,
- 0.2918045f, -0.9340674f, -2.451646f, -1.6467915f,
- -0.1495209f, -1.7131006f, 3.0137317f, 9.472299f,
- -0.4197755f, -0.5502301f, 3.5713727f, -2.6548738f,
- -4.8386097f, -0.50896245f, 0.33439803f, -3.5912373f,
- -2.5142434f, 0.31759253f, 2.8036375f, 0.5107251f,
- -2.4387827f, 5.6494966f, 8.272512f, -0.6857846f,
- -4.277969f, 0.06253213f, -0.074014544f, -0.96207106f,
- -3.258291f, -3.5390236f, -1.9750332f, -3.608297f,
- -2.6604233f, 5.6921406f, -0.20409922f, -1.1969116f,
- 2.998337f, -2.8880908f, 4.3057775f, -1.6192275f,
- -3.9624197f, 1.2976433f, -2.3650267f, 1.528933f,
- 5.797898f, -0.9645366f, -0.45642358f, -1.1272233f,
- -3.7239804f, -0.10225911f, -3.0569742f, 2.9945762f,
- 0.2061069f, 3.2041075f, -3.9863253f, -0.8720719f,
- -0.19734815f, 3.9580374f, -0.12529404f, 7.522356f,
- -0.33207574f, -1.749753f, 0.012730557f, 0.83969754f,
- 1.0534894f, 3.1120992f, -0.21781741f, -3.730677f,
- -2.4570732f, 4.693341f, -3.705345f, 6.543063f,
- 5.790613f, 5.2750983f, -0.2737199f, 0.20292063f,
- -0.19565266f, 0.18959108f, -0.7141286f, -0.1421035f,
- 1.1523175f, -0.42864046f, -0.5442941f, 0.47701302f,
- -0.6918521f, -0.4566777f, -0.22964719f, -0.053935032f,
- 1.334023f, -0.24515498f, -0.32768467f, -0.098785125f,
- 0.17596051f, 0.24970356f, -0.44796598f, -0.725162f,
- 0.23690584f, 2.4115663f, 0.14600314f, -0.5032527f,
- -0.24323554f, 0.34614623f, -0.6348769f, 0.21008942f,
- -0.12548275f, -0.031216528f, 0.8781839f, 1.4928612f,
- -0.1351223f, 0.23892055f, 0.08621855f, 0.19357921f,
- -0.15621492f, -0.32136732f, -0.105860986f, -0.43773624f,
- -0.2991011f, 2.0953817f, 0.6826344f, 0.28943685f,
- -0.31151387f, 0.020587096f, 0.066338375f, 0.10279052f,
- 1.0122124f, -0.20951027f, -0.8921019f, -0.2670173f,
- 0.7008211f, 0.03144697f, -0.570858f, -0.45342627f,
- -0.49734485f, -0.31857324f, 0.06833323f, 0.64317346f,
- 0.72330225f, 0.24675474f, 0.10754503f, 0.084493704f,
- -0.049294725f, -0.3699444f, -0.65256214f, 0.11096866f,
- -0.2968797f, -0.11619944f, -0.4352658f, -0.067280576f,
- -0.37451968f, 0.08758164f, -0.44101405f, -0.89013827f,
- -0.42683706f, -0.5068986f, -0.16529635f, 0.45533752f,
- -0.39907336f, 0.60581833f, 0.7353728f, -0.44387445f,
- -0.13244885f, 0.029204527f, 0.029594982f, 0.4406457f,
- 1.090284f, 0.6668375f, -0.24140362f, -0.319228f,
- -0.15728866f, 0.16055645f, -0.81018525f, 0.11214216f,
- 1.6476907f, -0.6654847f, 0.80008614f, -0.30378923f,
- 0.045123383f, -0.30932993f, -0.69866115f, -0.67481744f,
- -0.21296617f, -0.56215996f, -0.6310222f, 0.011046439f,
- -0.5344561f, -0.025601242f, -0.07633684f, -0.019724023f,
- 0.093710914f, -0.09569747f, -0.07368093f, 0.2556301f,
- 0.42773598f, -0.021355256f, -0.06861557f, -0.13496685f,
- -0.3799303f, -0.14145431f, -0.13986817f, -0.057043213f,
- -0.14134757f, 1.2110442f, -0.080710225f, 0.11991373f,
- -0.045916308f, -0.17114373f, -0.03242872f, -0.054202504f,
- 0.045894932f, -0.4096955f, -0.30338138f, -0.05858498f,
- -0.15641452f, -0.0064510056f, -0.0397215f, -0.17965792f,
- 0.091054395f, -0.0452716f, 0.53034526f, -0.033143215f,
- -0.061527755f, -0.0826567f, 0.10934548f, -0.11527085f,
- -0.23735735f, -0.04664125f, -0.020786379f, -0.12906374f,
- -0.06724864f, -0.20173365f, 0.035704535f, -0.055301644f,
- 1.0611591f, -0.029736955f, -0.13419569f, -0.11772322f,
- -0.13287388f, -0.035557445f, 0.03848f, -0.056545507f,
- -0.024756482f, -0.08688465f, -0.16659062f, -0.15011726f,
- 1.0631641f, 0.009429684f, -0.02033283f, -0.086923525f,
- 0.0036864264f, -0.013053531f, 0.06404314f, -0.059716847f,
- 0.21586585f, -0.015353658f, -0.04348257f, -0.07714623f,
- -0.0049039447f, -0.0597445f, -0.14963177f, -0.13544802f,
- -0.11216604f, 0.4155934f, -0.09841997f, -0.31502458f,
- 1.3675573f, 0.0053203264f, -0.10823905f, -0.03735995f,
- -0.12911084f, -0.047670636f, 0.08714917f, 0.09499504f,
- -0.034430206f, 0.08743009f, -0.13216636f, -0.020682301f,
- -0.029935343f, -0.1077892f, 0.073623076f, -0.18846966f,
- 0.5205037f, -0.09475728f, -0.10284579f, -0.08943492f,
- -0.15943094f, -0.16155173f, -0.12912627f, -0.10557388f,
- -0.12936687f, -0.046011247f, -0.021065874f, 0.027395079f,
- 0.08711983f, -0.12310535f, -0.64588577f, -0.41916463f,
- -1.2377524f, -0.059316322f, 0.13759588f, -0.5455585f,
- -0.1338763f, -0.1582742f, -0.12010011f, -0.3581341f,
- 0.6880694f, 0.43410316f, 1.2716614f, -1.0843034f,
- -0.65085125f, 0.85267144f, 0.4692779f, 0.08192896f,
- 0.7342831f, -0.1857212f, -0.040173545f, 2.232935f,
- -0.98548657f, -1.0180451f, -0.41013843f, 0.46650046f,
- -0.5265122f, 0.12754534f, -0.19413193f, -0.31543508f,
- 0.6431222f, 0.21963346f, -0.5187371f, 0.452184f,
- 1.1044376f, 0.84107685f, -0.4634716f, 0.45822376f,
- -0.6623231f, 0.22325204f, -0.48321852f, 1.2109452f,
- 0.5498577f, 1.1071588f, -0.4938941f, -0.77996325f,
- 0.6216473f, 0.72124505f, -1.0595604f, 0.29715234f,
- -0.5082744f, -0.7766315f, -0.28000465f, -0.32209027f,
- -0.1631873f, -0.89486533f, -0.78939f, -0.43267784f,
- 0.15717983f, 0.08318555f, 1.7047675f, -0.10183861f,
- 0.057274815f, 1.204087f, 0.4132834f, 0.3050957f,
- -0.1452376f, 0.3055638f, -1.0023799f, -0.30476996f,
- -0.90959287f, -0.104832284f, -0.53215927f, -1.0515889f,
- -0.8940017f, -0.73338586f, 0.072635844f, 0.38406366f,
- -0.060958356f, -0.1551099f, -0.4724258f, -0.42824665f,
- -0.040052164f, -1.0936197f, 0.5408766f, -0.18912873f,
- 1.1063552f, -0.33383122f, 0.46988192f, 0.76269966f,
- -1.6159776f, -0.60667425f, -0.4073271f, 0.11208353f,
- -0.40741688f, -0.19388846f, 2.8604255f, 0.27965948f,
- 0.40005606f, -0.13897702f, -0.057497505f, 0.0043756077f,
- 0.4820958f, -0.38872454f, 0.05420346f, 2.225721f,
- -0.47451204f, 0.15105298f, 0.47737134f, -0.24425451f,
- -0.22082634f, -0.14204104f, 0.9882125f, -0.11346282f,
- -0.25642842f, 0.5447618f, 0.42833108f, -0.07402917f,
- -0.2665145f, -0.3299989f, 0.7229368f, 0.0029826134f,
- -0.22707748f, -0.19653402f, -0.1793823f, -0.243637f,
- -0.19854097f, -0.30241734f, 0.029190522f, -0.09281963f,
- -0.25104305f, -0.16150331f, 0.122732535f, 0.76694053f,
- 1.1282126f, -0.09381997f, 1.6492529f, -0.04066688f,
- -0.048601653f, 1.0235364f, 0.40067285f, -0.21935043f,
- -0.28479916f, -0.11127537f, -0.24870712f, -0.3132399f,
- -0.25464252f, -0.10896945f, 0.06591696f, -0.21984105f,
- -0.17466989f, -0.3847166f, -0.332956f, -0.27082357f,
- -0.14517142f, -0.21402599f, 0.10558696f, -0.20275474f,
- -0.20908923f, -0.15369757f, -0.033556726f, -0.06391949f,
- -0.1532982f, -0.071687974f, 0.130966f, -0.23649591f,
- -0.14010094f, -0.39976633f, -0.55061054f, -0.124691926f,
- -0.22124428f, -0.16267698f, -0.27158448f, -0.14346671f,
- -0.3714159f, -0.26736045f, 0.5096079f, -0.21625791f,
- -0.19716366f, -0.32739162f, -0.04500131f, -0.2796727f,
- -0.25834143f, -0.03396222f, -0.16163266f, 0.8115788f,
- -0.14262037f, 0.6535709f, 0.47214162f, -0.0058920006f,
- -0.19041345f, -0.166924f, 0.07267109f, -0.028633544f,
- -0.19846849f, -0.29219547f, -0.27968445f, 0.6772558f,
- -0.29634726f, -0.09351501f, -0.08077664f, -0.09850565f,
- 0.28447792f, -0.104497574f, 1.9136777f, -0.28675133f,
- -0.0359201f, -0.06834193f, 1.7297f, -0.014657564f,
- 0.12760833f, -0.03522932f, -0.14119567f, -0.07053855f,
- -0.0971273f, 0.099639736f, -0.36199284f, -0.10223977f,
- -0.04495512f, -0.10036811f, -0.0975939f, 0.18905918f,
- -0.14003104f, -0.10030257f, 0.6302978f, -0.14425503f,
- -0.10664036f, -0.110925265f, -0.18555297f, -0.21997356f,
- -0.07312499f, -0.14648652f, -0.070604205f, -0.16517913f,
- 0.77022517f, -0.17223532f, -0.09765247f, -0.21483414f,
- -0.15421468f, -0.15055467f, -0.09955809f, 0.0729144f,
- -0.23262016f, 0.029067472f, -0.09530256f, -0.064356185f,
- -0.022742117f, 0.01505502f, -0.14441235f, 0.4111333f,
- -0.067248024f, 0.6857606f, -0.06592702f, -0.1426528f,
- -0.092953995f, 1.8926553f, -0.11412823f, -0.20712128f,
- -0.03488324f, -0.19169258f, -0.08613235f, -0.17266682f,
- -0.18653971f, 0.032117926f, -0.123000495f, 0.38970628f,
- -0.13774122f, -0.104666546f, -0.1573773f, -0.013111952f,
- -0.11687493f, 0.117874034f, -0.060738873f, -0.059041686f,
- -0.18126315f, -0.07776166f, 1.3686922f, 0.233397f,
- -0.028750857f, 0.058994412f, -0.1389768f, -0.16606809f,
- -0.045185618f, -0.06822949f, 0.0066798166f, 0.50652f,
- -0.24503356f, -0.12977232f, -0.14486526f, -0.11712564f,
- -0.06794483f, -0.09611142f, -0.100870274f, -0.17538556f,
- 0.47549745f, -0.061965607f, -0.310107f, -0.08253986f,
- 0.044265144f, -0.16794863f, 1.8561782f, -0.29822424f,
- -0.14573579f, -0.025921056f, -0.29915515f, -0.1402344f,
- 0.30322963f, -0.25061992f, -0.08695211f, 0.041934963f,
- 0.007009076f, 0.37877476f, -0.23054649f, -0.08827595f,
- -0.2635812f, -0.030145187f, 0.029283015f, -0.24366757f,
- -0.19099088f, -0.25192374f, -0.15935108f, -8.574655e-05f,
- -0.11686771f, -0.086374775f, -0.026462873f, 0.1995383f,
- -0.1019526f, -2.7014601f, 4.0956535f, 5.2403665f,
- 0.057906162f, 2.2269707f, -1.0647246f, 1.8155823f,
- 0.13933566f, 7.1704235f, -1.9955367f, 3.053147f,
- -1.5506278f, 6.768529f, -3.2372158f, -3.2429109f,
- -2.750656f, -1.6101863f, -3.9786048f, -1.558298f,
- 2.4339004f, -1.5607479f, -1.9998405f, -3.2509592f,
- -0.49339542f, 1.6138321f, -0.22790357f, -1.6837083f,
- -0.32384318f, -4.2343874f, -4.1324544f, 0.20879272f,
- 0.1353085f, 0.27105832f, -0.39511555f, -4.4900894f,
- 4.512571f, 3.7453938f, -1.3309132f, -2.4456873f,
- 0.011213267f, 2.4054837f, -0.10858784f, 0.20317067f,
- -1.9206581f, -1.1248634f, -0.8684156f, -0.009830279f,
- -0.9892469f, 3.1293766f, 1.8935492f, -2.6723914f,
- -1.2483405f, 4.171465f, 3.7724512f, 5.042522f,
- 2.4891942f, -1.4196804f, 8.791865f, -0.6084768f,
- 0.49274006f, -0.995633f, -3.6946971f, -2.6049545f,
- 4.499363f, -4.1597705f, 0.857525f, -2.490818f,
- -2.363686f, -1.3907557f, 4.2467446f, -1.893917f,
- 4.2834597f, 1.7005554f, -3.431749f, -1.3029349f,
- 1.7357689f, 0.5254594f, -0.18814535f, -0.37286922f,
- -0.06643978f, -1.8165953f, 2.8025708f, 0.89778054f,
- 2.7019293f, -1.1333838f, -0.17669088f, -2.6393912f,
- 2.5323844f, -0.31268615f, 5.258141f, -1.3272643f,
- 0.49876022f, -3.8092487f, -0.24632119f, -3.421155f,
- -0.10591736f, -0.13421242f, -1.8787662f, -0.56488484f,
- -0.18160763f, 6.166697f, -2.52607f, 0.27458215f,
- -1.1939096f, -2.8609025f, -1.8025749f, -2.953268f,
- 0.035168555f, 0.3687094f, -0.09377618f, -0.054659374f,
- -0.051280815f, 1.1096923f, -0.050031714f, -0.045846067f,
- -0.011027449f, 0.7485932f, -0.09257217f, -0.05873733f,
- -0.056658614f, -0.42532808f, -0.08149817f, -0.086201176f,
- -0.074168354f, -0.08879434f, 1.0401856f, -0.119960666f,
- -0.18535165f, -0.074207485f, -0.24603386f, -0.17909183f,
- -0.047283422f, -0.063143425f, -0.47164217f, -0.13136859f,
- -0.045684736f, -0.3444732f, -0.07854757f, -0.091530114f,
- 0.1974248f, 0.027969697f, -0.08321694f, 0.6965803f,
- -0.22593693f, -0.054170817f, -0.10692354f, 0.2195847f,
- -0.16297673f, -0.2788185f, -0.027782606f, -0.26616147f,
- -0.2676773f, -0.122127004f, -0.19700572f, 0.0012905252f,
- -0.41827896f, 0.9888474f, -0.14162292f, -0.11046131f,
- -0.08860871f, -0.12409941f, -0.03759789f, -0.044008173f,
- -0.018424973f, -0.087843046f, -0.06628657f, -0.13190351f,
- 1.1951147f, 0.39260325f, -0.101336986f, -0.050653856f,
- -0.111892685f, -0.12990597f, -0.048253607f, -0.14406419f,
- -0.012492356f, 0.06508579f, -0.030098684f, 0.03570622f,
- -0.046869785f, -0.0116679575f, -0.082965724f, -0.07187547f,
- -0.062279783f, -0.15465601f, 0.2368763f, -0.10009748f,
- -0.44332957f, -0.25780582f, -0.07083814f, -0.1366524f,
- 0.13219672f, -0.11648779f, -0.060196854f, -0.081672385f,
- -0.19247109f, -0.008067654f, 0.016193064f, -0.077722766f,
- -0.027123874f, -0.018180462f, -0.044730958f, 1.188201f,
- -0.219514f, 0.50425416f, -0.15672347f, -0.08785794f,
- -0.0044647483f, 0.6576291f, -0.13024026f, -0.07079115f,
- -0.10326849f, -0.1289815f, 0.009784586f, 0.010393538f,
- -0.05091059f, 0.7503312f, -0.15001035f, 0.8175264f,
- -0.81792384f, 0.23747092f, 0.23842028f, -1.1875769f,
- -1.6360713f, -1.067396f, -0.26068118f, -0.8875219f,
- -2.6774447f, 2.695186f, 0.24695344f, 1.9990565f,
- 3.5824666f, 0.47666448f, 0.65789056f, -0.017243065f,
- -0.6126662f, 2.524879f, 2.8079183f, -0.15984575f,
- -0.676962f, -1.3231902f, 1.8769542f, -1.0145831f,
- 0.5515303f, -3.3247204f, -0.24691795f, 1.1809818f,
- 1.2093118f, -0.010419865f, -0.99591357f, -1.6230432f,
- 0.8771637f, -1.9208481f, -0.5230363f, -1.0569421f,
- 1.9391465f, -1.5018989f, 0.619693f, -1.9048057f,
- -0.9227824f, -0.36192966f, -0.22694446f, -0.24379149f,
- -0.4067702f, -0.34610748f, -0.9923501f, -0.77705723f,
- -0.0009853527f, -0.37688854f, -0.776852f, -0.37581018f,
- -1.9605188f, -0.64409536f, -0.5738205f, -3.1400712f,
- 0.3320492f, 0.43254635f, -0.0035354185f, -0.6719218f,
- -0.926502f, -0.032768104f, -0.04971295f, -0.5552995f,
- -0.018605815f, -2.5080874f, -0.13922605f, 1.7658852f,
- 0.42939693f, -0.6135394f, -2.1230772f, -0.7608864f,
- -0.57843506f, 3.3582652f, -0.61548054f, 2.7247717f,
- 3.7546158f, -0.03409471f, -0.13595185f, -0.34578845f,
- -0.67870444f, -1.4947506f, -1.3164085f, 3.4100873f,
- 0.093954675f, 1.7208126f, -0.6166989f, -0.6116643f,
- -1.0145832f, -2.8206482f, 1.4302028f, 3.0292165f,
- -0.09834711f, -0.6374609f, 0.07149782f, 0.5765882f,
- 0.102815166f, -0.8535537f, -0.07866903f, 0.9224347f,
- 0.1510614f, 6.3740406f, -0.5133206f, -1.6909688f,
- 1.7916317f, -0.22555485f, 0.16524825f, 3.1690829f,
- -2.736666f, 9.350518f, 3.1371162f, 0.020126507f,
- -3.676105f, 4.1666055f, -0.4047929f, 0.20167847f,
- 0.5150774f, 1.6010872f, -0.87343454f, 2.412305f,
- -2.8023152f, 3.2993774f, 2.9413269f, -3.2535763f,
- 0.29641342f, -2.7840405f, -0.19238083f, -0.78970456f,
- 0.567947f, -0.8270295f, 3.2222836f, 4.295631f,
- -1.093286f, 0.535741f, -1.7261914f, 0.89259267f,
- 4.9060287f, 4.8939376f, 1.0492741f, -0.009679181f,
- -0.6677822f, -0.721829f, -0.5049348f, -2.1586604f,
- -3.0010731f, -0.27136847f, -2.3166244f, -0.702162f,
- -1.5530938f, -1.1480715f, -0.18300676f, -0.529f,
- 0.8063084f, -2.995926f, 0.614492f, 0.44163215f,
- -2.562075f, -2.6005373f, -0.8676621f, -3.3013902f,
- -2.623975f, 4.3853917f, 3.6256592f, -0.7181114f,
- 6.4060135f, 3.251851f, -0.048239868f, -0.16620544f,
- -0.5839832f, 6.5843935f, -2.486149f, -2.237813f,
- -2.5079067f, 2.7056777f, 0.34237513f, 0.7824124f,
- -1.88966f, -1.944232f, 0.44216013f, 4.036303f,
- -1.6080916f, 2.3627818f, 1.900416f, 0.45095327f,
- 0.24333869f, 3.6761482f, -1.4777291f, 0.15510459f,
- -2.257669f, -4.4669504f, -0.07188632f, -2.2194555f,
- -3.0235293f, 0.32475337f, -1.103671f, 4.3398824f,
- -0.9191056f, -3.0642724f, -1.2574879f, -3.1455894f,
- -1.9662267f, 0.23659022f, 0.14329006f, 0.5359271f,
- -0.9191079f, -2.0489485f, 0.28925517f, 0.827968f,
- -3.6470263f, -2.6294777f, -0.46330345f, -3.0973873f,
- -2.4565547f, 0.108173855f, 6.596422f, -0.14141813f,
- -0.4741837f, -0.1985697f, -0.09699895f, -0.11035193f,
- 1.0154678f, -0.14510183f, -0.16443849f, 0.82590324f,
- 1.116061f, -0.08892416f, -0.124580815f, -0.12858471f,
- -0.45412672f, -0.064000905f, -0.14463551f, -0.10814506f,
- -0.1790699f, -0.13321957f, -0.19641231f, -0.057502266f,
- -0.042905804f, -0.5139841f, -0.29002392f, -0.09648269f,
- -0.18417875f, -0.5594259f, 0.7168178f, -0.11294248f,
- 0.6899119f, -0.10207255f, -0.08235322f, 1.0525215f,
- 1.0312445f, -0.124251075f, -0.050824195f, -0.3201006f,
- -0.08155088f, -0.22957252f, -0.31184164f, -0.0013889447f,
- -0.062572055f, -0.05134762f, -0.1850486f, 0.61800605f,
- -0.2683062f, -0.21345456f, 0.0036186504f, 0.14318171f,
- -0.042290818f, -0.19069694f, -0.2615461f, -0.19045442f,
- -0.136215f, -0.13353212f, -0.1572102f, -0.07092364f,
- 0.009626709f, -0.09119088f, -0.17312771f, -0.4088422f,
- 0.13011202f, -0.1839305f, -0.07002457f, 0.027211098f,
- -0.2963829f, -0.14254493f, -0.3776302f, -0.06761943f,
- 0.7886867f, -0.02280448f, -0.107554585f, 0.006960107f,
- -0.12040246f, -0.02404508f, -0.13752218f, -0.10596393f,
- -0.053288367f, 1.2385032f, -0.017993411f, -0.3806937f,
- 0.62692755f, 0.09796916f, -0.20537733f, -0.30321175f,
- -0.04528263f, -0.09053077f, -0.4681605f, -0.17407142f,
- -0.030810809f, 0.7711909f, -0.1752287f, -0.06120469f,
- -0.055264045f, -0.19262041f, 0.44220966f, -0.17843856f,
- 1.278726f, -0.39852026f, -0.07956974f, -0.014364062f,
- 0.4705977f, -0.032584056f, -0.1448544f, -0.069566004f,
- -0.050343793f, -0.04554583f, -0.04851087f, -0.097843565f,
- 0.28362414f, -0.1625289f, 0.43600932f, -1.2975295f,
- 0.7553555f, -0.6710721f, -0.9371323f, 2.025563f,
- 1.263816f, 0.46647727f, 1.0153066f, 1.2219825f,
- 0.327534f, -0.8388161f, 0.3947068f, -0.45293882f,
- 1.0702896f, 1.7821149f, 0.094880916f, -0.17659046f,
- -1.1940084f, 0.401835f, 0.832864f, 0.35411814f,
- -0.34997427f, -0.60533667f, 1.8571347f, 0.034336727f,
- 1.2614901f, 0.03006006f, -0.56574374f, -0.65874934f,
- 0.53067416f, -0.62030536f, -1.2145782f, 0.15710889f,
- 2.7736666f, 1.3686463f, 2.582843f, -0.47224814f,
- -1.6839797f, 0.49678248f, -0.25336677f, -0.84914345f,
- -0.013612314f, 0.93902194f, -0.57736635f, -1.1828687f,
- 0.0008779036f, 0.6058149f, 0.26206043f, -0.6701685f,
- -1.6774621f, 0.1890693f, -2.7397547f, 3.0052128f,
- -0.3161035f, -1.3312308f, 0.16468093f, 2.9663906f,
- 0.16096821f, -0.39338356f, 1.9346528f, -1.5509659f,
- -2.3400023f, 2.6086476f, -0.6484281f, 2.9827735f,
- -1.0299317f, 1.3606236f, -0.831366f, -2.0445216f,
- -0.5842329f, -0.32113922f, -0.84443486f, 0.5993351f,
- -1.2907485f, -0.8407805f, -1.703484f, -0.14539656f,
- -0.18953882f, -0.06470153f, -0.46044034f, 2.8456488f,
- 0.7314515f, 1.335371f, 0.015935903f, 0.37556076f,
- -0.8115105f, -1.1210833f, 0.015227724f, 0.32487008f,
- -0.215859f, -0.40429384f, -1.3176293f, 0.3757031f,
- 1.3825502f, 0.06048043f, -0.30887425f, -0.6539518f,
- -1.4753624f, 0.32900742f, -2.0594075f, 1.8660148f,
- -1.1209099f, -1.0876486f, -2.087495f, -0.26549277f,
- -1.3610848f, 0.023393843f, -0.069958955f, -2.529243f,
- -3.1198032f, -1.5910124f, -0.058170523f, -3.1914997f,
- -0.9053399f, 1.4377562f, -0.47271946f, -1.4626653f,
- -3.427887f, -1.8872527f, -1.1912792f, 0.6396692f,
- 2.9715338f, -1.4961069f, 0.339724f, 0.4673081f,
- 1.0079231f, 0.9189841f, 6.8075356f, 0.066545f,
- -2.3275805f, -2.3001375f, 4.059756f, 1.6152073f,
- 0.6862858f, 3.2579951f, -0.334684f, -1.9250443f,
- -1.8336546f, -0.127782f, -0.88732654f, 0.3004779f,
- 0.06545991f, -2.1963155f, -1.7173853f, -2.8637278f,
- 0.688593f, -1.3410734f, -0.6436824f, -2.157338f,
- 0.09079807f, -0.62127507f, 1.065319f, -2.01478f,
- 0.5318923f, 0.08929781f, -0.62527883f, 1.8810998f,
- -2.4246767f, 1.8491658f, -3.8271775f, 2.08576f,
- -2.614427f, -3.8302588f, -0.41149485f, 5.7787313f,
- -1.5687293f, 0.7501196f, 0.48454118f, 1.6853702f,
- -2.9901445f, -1.1663042f, -1.197858f, -2.1180344f,
- 2.8749526f, -1.0725003f, 0.46016815f, 6.5800266f,
- -0.24610066f, 6.87114f, -3.4127464f, -0.113472305f,
- -1.8095498f, -2.6785762f, -0.48358938f, 2.978011f,
- 4.0447054f, 1.4942777f, -0.044783816f, -3.371482f,
- -1.9487543f, -0.51505494f, 0.7469106f, 8.363108f,
- 1.0411565f, 4.047047f, -0.7583502f, -0.8728304f,
- -0.7151937f, 1.0796925f, 5.5281463f, 5.4882693f,
- -0.26771906f, -2.035531f, -0.123675376f, 0.66257554f,
- 1.6588229f, 3.7671416f, -0.016601846f, -2.8202577f,
- -1.1763377f, -3.3184102f, 4.121679f, -3.7005587f,
- -2.8837144f, 2.0510082f, -0.31540278f, -3.380825f,
- -0.17323203f, -0.08300326f, -0.11099566f, 0.721641f,
- -0.07985058f, -0.14671811f, 0.4543802f, 0.29494032f,
- -0.060283843f, -0.08177182f, -0.10846794f, 0.06588641f,
- 0.008294579f, -0.06943126f, -0.1074572f, -0.076916255f,
- 0.009127525f, -0.14439234f, -0.16363983f, -0.13069935f,
- -0.10450848f, 0.0337002f, -0.13860424f, -0.1834899f,
- -0.034951575f, -0.005335836f, -0.107541196f, -0.1880678f,
- -0.11703551f, -0.13637741f, 0.42058423f, 0.5899595f,
- -0.09544835f, 0.26109836f, -0.1553875f, -0.079761796f,
- -0.20375884f, 0.44464344f, 0.0897332f, 0.14413528f,
- -0.086421326f, -0.12088981f, -0.13329725f, -0.09093634f,
- -0.1789273f, -0.034252964f, 0.1700528f, 0.089239866f,
- -0.06298791f, -0.1522783f, 0.008075548f, -0.053631548f,
- -0.082143724f, -0.09598651f, -0.04992954f, -0.0519648f,
- -0.05465122f, -0.15380432f, 0.61913484f, -0.0086838305f,
- -0.07681879f, -0.06183424f, -0.038134266f, -0.15837471f,
- -0.048885755f, -0.12904337f, -0.0776575f, 0.40771976f,
- -0.05419557f, -0.027348885f, -0.12207096f, -0.09592805f,
- -0.086163096f, -0.17631598f, -0.10428465f, -0.03047418f,
- 0.3168628f, -0.10641072f, 0.00046094088f, -0.13108766f,
- -0.077966824f, -0.15356168f, 0.48104313f, -0.03293454f,
- -0.10621737f, -0.07056999f, -0.15971632f, -0.11065052f,
- 0.541961f, -0.087616794f, -0.08556635f, -0.020134445f,
- -0.08751468f, 0.4889757f, -0.13535263f, 0.3037984f,
- -0.13966699f, -0.023192527f, 0.09289807f, 0.5020735f,
- -0.13647182f, -0.20726742f, -0.10974488f, -0.02618879f,
- -0.06006007f, -0.017293822f, -0.08975864f, 0.5154025f,
- -0.111082435f, -0.5126615f, 0.44030783f, -1.1293287f,
- 0.13742316f, 1.1037129f, -0.6347415f, -0.37061635f,
- 0.7707863f, -0.6487331f, -0.8461368f, -0.302882f,
- -0.08234444f, 1.6229373f, -0.25989532f, 0.9090884f,
- -0.34471855f, -0.0004797669f, 1.8702974f, -0.65129757f,
- -0.47116315f, 0.061635602f, 1.6233718f, -0.14590004f,
- -0.20701203f, -0.060958017f, 0.37516806f, -0.8421902f,
- 0.1968854f, -0.816971f, -0.69409436f, 0.58007497f,
- 1.2748722f, -0.3007688f, 0.38139462f, -0.3696006f,
- 0.11634078f, -1.1260606f, -0.32959443f, 0.5978667f,
- 0.2818116f, 0.16908754f, 2.155114f, 0.65574354f,
- -0.1851692f, -0.07361013f, 1.2941353f, 0.033873912f,
- 0.22704352f, 2.2627747f, 0.27739894f, -0.3368061f,
- 0.06386353f, 1.0289093f, -0.0775799f, -0.4547856f,
- -0.27260348f, -0.06037465f, -0.23095927f, -0.022860924f,
- 0.6619789f, 0.052822586f, -0.59699106f, -0.34257212f,
- -0.49849012f, -0.036985293f, -0.670026f, -0.8155501f,
- -0.26311976f, -0.38908067f, 0.010200739f, -0.58736956f,
- -0.68964565f, -0.53150064f, -0.003577f, -0.3585349f,
- 0.43870562f, -0.4583485f, -0.2793907f, -0.26005057f,
- 0.22803375f, -0.26217625f, 0.9116997f, 1.0939022f,
- 0.091696516f, -0.5368176f, -0.23000047f, -0.28249195f,
- -0.38627243f, 0.8926988f, 1.1076174f, -0.39162f,
- -0.19353102f, -0.28114784f, 0.45681587f, -1.2582151f,
- 0.24599458f, 0.40652773f, -0.4651858f, 0.62445825f,
- -0.31887978f, -0.2081309f, -0.7454648f, -0.55966777f,
- -0.6684211f, -0.34665832f, -0.7590547f, -0.5255204f,
- 0.09206679f, 0.24729201f, -0.5279801f, -0.012925246f,
- -0.058602765f, -0.46764433f, -0.84391654f, -0.8522623f,
- 0.0967769f, 0.30345958f, -0.9210882f, -0.5233845f,
- -0.67431164f, -0.42197514f, -0.017911652f, -0.7451851f,
- -0.9935131f, 0.025254657f, 0.0309502f, -0.27362216f,
- 1.029126f, -0.08798813f, 1.0611835f, 1.411428f,
- -0.48040253f, 1.6222134f, -0.44392744f, -0.21832049f,
- -0.25710788f, -0.325393f, -0.32778504f, -0.5226684f,
- 0.5069486f, -0.3441388f, 0.50055677f, 0.015011838f,
- 1.9979984f, -0.36452118f, -0.55350035f, 1.0567914f,
- -0.5498292f, -0.5289284f, -0.115745015f, 1.9305022f,
- 1.1787355f, 1.223733f, -0.6419038f, 0.8174759f,
- 0.96227086f, 0.06607478f, -0.4663329f, -1.055869f,
- -0.49595857f, -0.36716244f, 1.8954154f, -0.9650339f,
- -0.03012962f, 0.24230874f, -0.32971165f, -0.12273487f,
- -0.008465982f, 1.1262844f, 1.2923259f, -0.8415982f,
- -0.37549973f, 2.1383178f, 0.17815311f, 2.2756715f,
- -0.57213515f, -0.3533904f, -0.42059532f, -0.30543733f,
- -0.5592925f, 0.21112402f, -0.67932f, -0.38235822f,
- -0.5949453f, 0.024399174f, -0.3362657f, -0.46712145f,
- 0.11167116f, -0.34762675f, -0.7557856f, -0.726715f,
- 0.82988477f, 0.056542322f, -0.16631885f, 0.16711017f,
- 1.1998566f, -0.5755097f, -0.5310708f, -0.71621376f,
- -0.3424138f, 0.41551304f, -0.5351932f, 1.1734893f,
- -0.31848103f, -0.44463977f, 0.9994067f, -0.5762111f,
- 0.026003195f, -0.37087536f, 0.04848423f, -0.18870568f,
- -0.59083927f, -0.29078558f, -0.36046764f, -0.14385198f,
- -0.04232822f, 0.65527284f, -0.054409254f, -0.23989256f,
- -0.05581965f, -0.12718306f, 1.1674054f, -0.11652152f,
- -0.115093976f, 0.78027076f, 1.4505389f, -0.07671923f,
- -0.08385706f, -0.15020044f, -0.4681732f, -0.13740262f,
- -0.119233035f, -0.09698868f, -0.15214081f, -0.19047403f,
- -0.15190507f, -0.27501008f, -0.11004156f, -0.79624265f,
- -0.31570536f, -0.06276035f, -0.25543275f, -0.61689246f,
- 0.123865366f, -0.13753706f, 0.47764006f, -0.082168624f,
- -0.08383042f, 1.3566433f, 1.0176032f, -0.09321535f,
- 0.004591086f, -0.3944376f, -0.04770159f, -0.21715944f,
- -0.42091462f, -0.07205966f, -0.06603034f, -0.023770152f,
- -0.37433466f, 1.0748909f, -0.3038766f, -0.2673485f,
- 0.026832439f, 0.8313771f, -0.095182836f, -0.16063693f,
- -0.265459f, -0.16631603f, -0.12291935f, -0.14011316f,
- -0.13197228f, -0.12619472f, -0.001810381f, -0.108096726f,
- -0.10400829f, -0.028091958f, 0.8030141f, -0.20160158f,
- -0.0862033f, 0.032070283f, -0.3550813f, -0.12754512f,
- -0.4599432f, -0.061084166f, 0.7858428f, 0.0050876727f,
- -0.038406704f, -0.025493542f, -0.10458248f, -0.04501253f,
- -0.11215949f, -0.0952236f, -0.12959965f, 0.98049384f,
- -0.09359637f, -0.43173093f, 0.2206496f, -0.011917401f,
- -0.17692626f, -0.51228076f, -0.096125074f, -0.051105503f,
- -0.6991781f, -0.31170714f, -0.10355865f, 0.7551247f,
- -0.15086196f, -0.037409022f, -0.05988083f, -0.10191731f,
- 1.0527427f, -0.26677808f, 0.7727662f, -0.42774418f,
- -0.055291723f, -0.05853922f, 0.31635565f, -0.05528061f,
- -0.079174384f, -0.10046409f, -0.1289375f, 0.019888185f,
- -0.013222757f, -0.1353336f, 0.8954099f, -0.18134762f,
- 0.22058861f, -0.22418949f, -0.35238555f, -0.29311973f,
- -0.18108381f, -0.6064622f, 0.8315898f, 0.22761773f,
- -0.21101806f, -0.20159902f, -0.10482367f, -0.36709115f,
- -0.4711313f, -0.25834325f, -0.50967354f, -0.31682533f,
- -0.21385287f, -0.5191045f, 1.6553903f, -0.488967f,
- -0.37209827f, 0.93731064f, -0.21888545f, -0.44328544f,
- -0.114756316f, 0.80146873f, -0.30633408f, 0.11247094f,
- -0.23065028f, -0.1850106f, 0.82361305f, 0.7106545f,
- -0.17079563f, -0.0837649f, 1.340414f, -0.18765189f,
- -0.26010132f, -0.2428635f, -0.052606255f, -0.21788678f,
- -0.35129872f, 0.6656369f, 0.6513194f, 1.0280342f,
- -0.34833473f, -0.29212213f, 0.2903131f, -0.44710842f,
- -0.7021416f, -0.23706792f, -0.5312556f, -0.38086745f,
- -0.027064895f, -0.47758698f, 0.04132585f, 0.29436293f,
- 0.31574923f, -0.379388f, -0.16902813f, 0.15219006f,
- 0.8290071f, -0.24104306f, -0.36608306f, 1.6631153f,
- -0.24658677f, 1.3685281f, -0.34383288f, 0.8278092f,
- -0.24518588f, -0.24518858f, -0.23432626f, -0.08307593f,
- -0.004530473f, -0.263668f, 0.045109693f, -0.5312845f,
- 0.9582925f, -0.5977095f, -0.2247764f, 0.58210874f,
- -0.14683972f, -0.688769f, -0.2762419f, -0.67528164f,
- -0.37313277f, 0.0086481f, 1.6328578f, 0.08137278f,
- 0.8435546f, -0.37414545f, -0.4185464f, -0.16260293f,
- -0.0068811118f, -0.16556577f, 0.5586304f, 0.47520477f,
- 0.82800984f, -0.26337087f, 0.029157514f, -0.19173218f,
- -0.16435057f, -0.29105604f, -0.21925919f, -0.14505449f,
- -0.32620844f, -0.36587426f, 0.1305532f, 0.16136119f,
- -0.48372325f, -0.07302554f, -0.038514446f, -0.06893487f,
- 0.62562555f, -0.2224751f, -0.320659f, 1.4616518f,
- 0.92805713f, -0.12140492f, -0.13379206f, -0.1369827f,
- -0.14428614f, -0.15761143f, -0.16950347f, -0.24112737f,
- -0.17580011f, -0.35278577f, -0.2902182f, -0.36410254f,
- -0.24183492f, -0.4453837f, -0.05233908f, -0.1876269f,
- -0.19022295f, -0.35859466f, 0.8416624f, -0.052327648f,
- -0.48905995f, -0.08136738f, -0.08313782f, 1.2053908f,
- 1.6041623f, -0.2665826f, -0.038881253f, -0.22772491f,
- -0.14933865f, -0.16466421f, -0.30372486f, 0.118162125f,
- -0.06419293f, -0.07478123f, -0.5090851f, 1.1741855f,
- 0.48633936f, -0.25879902f, -0.06892507f, 0.36390755f,
- -0.3471244f, -0.27964225f, -0.35906568f, -0.23144278f,
- -0.3464108f, -0.15122184f, -0.090351395f, -0.14468575f,
- -0.03431735f, -0.14967062f, -0.01356159f, -0.39218643f,
- 0.57834494f, 0.66500014f, -0.0505107f, -0.25337842f,
- 0.30775324f, 0.016742093f, 0.48618084f, -0.037618905f,
- 1.3461097f, -0.09811143f, -0.24369381f, -0.13200566f,
- -0.12048303f, -0.1673676f, -0.127258f, -0.15769629f,
- -0.21129048f, 1.38494f, -0.17744677f, -0.3194939f,
- 0.38073868f, -0.12733546f, -0.34806007f, -0.20823872f,
- -0.053153295f, -0.002940521f, -0.5487624f, -0.1075523f,
- -0.0589661f, 1.175446f, -0.19456619f, 0.0010080942f,
- -0.015637659f, -0.1739057f, -0.50427943f, -0.21588883f,
- 0.45153087f, -0.19446373f, 0.019266991f, -0.003981454f,
- -0.49359244f, -0.14905944f, -0.17146894f, -0.106661305f,
- -0.198417f, -0.17525116f, -0.095929824f, -0.26834008f,
- 1.0058615f, -0.23429967f, 0.040529907f, 0.038205244f,
- -0.15268908f, -0.08186332f, 0.28610495f, -0.1275757f,
- 0.050253738f, 0.3646011f, -0.5826055f, -0.41036904f,
- -0.3154269f, 0.073431574f, 0.37918526f, -0.19884926f,
- -0.28968245f, 0.26174688f, 0.5201976f, 0.4607794f,
- -0.3397418f, -0.33759373f, 0.17974593f, 2.080864f,
- -0.101360425f, -0.41324872f, -0.27139044f, 0.15482679f,
- -0.19259454f, -0.1747993f, -0.1844215f, -0.15223673f,
- 0.32392186f, 1.2027926f, 0.25456187f, -0.15088692f,
- 0.17680977f, 0.16698575f, -0.54802287f, 0.21052909f,
- -0.3108912f, -0.41036084f, -0.3579507f, 2.0784936f,
- 0.380003f, -0.051957965f, -0.41089538f, 0.21500656f,
- -0.27499935f, 0.264372f, 0.6871389f, -0.09467806f,
- -0.3399597f, -0.34747532f, 0.7088418f, 0.052537076f,
- -0.24721101f, -0.16369951f, -0.11828458f, 0.056097638f,
- -0.04159997f, 0.8342725f, -0.0834893f, -0.06648207f,
- 0.08618652f, -0.3300772f, 0.19132355f, -0.3679496f,
- -0.3080271f, 0.21970709f, -0.41188154f, -0.26483026f,
- -0.058945f, -0.2781208f, -0.25228074f, 0.3520168f,
- -0.32230353f, -0.7943997f, -0.07697109f, -0.49047318f,
- -0.028809432f, 0.5658753f, -0.17700896f, 0.07906186f,
- 0.75946766f, -0.36316508f, 0.030014211f, -0.19491225f,
- -0.4709309f, -0.09845123f, 1.2575809f, 0.20134586f,
- 0.16377102f, -0.038371038f, -0.46857637f, -0.17536597f,
- -0.6770845f, 0.06788041f, 1.1212155f, -0.3376903f,
- 0.18461941f, -0.14580983f, -0.11377068f, -0.2078023f,
- -0.23233351f, -0.79860425f, -0.14343247f, -0.24623711f,
- -0.40345693f, 0.30729344f, -0.4423997f, -0.60307103f,
- 0.54671305f, -0.55009687f, 0.07589351f, 0.5003517f,
- -0.7346936f, 0.35341942f, 0.3922856f, -0.4410819f,
- -0.4291769f, -0.650295f, -0.05045492f, 0.18669297f,
- 0.07477671f, 0.9821308f, 0.053841364f, 0.2842187f,
- 1.6319436f, -0.6314829f, -0.3365943f, 0.4641924f,
- 1.7385277f, -0.57921445f, -0.2600456f, -0.013063881f,
- 0.2705586f, -0.36688662f, -0.0150037585f, -0.35781828f,
- -0.49316365f, 0.1065848f, 1.4056578f, 0.21879159f,
- 0.57957107f, -0.19300826f, -0.19623026f, -0.76556456f,
- 0.07410374f, 0.24344413f, 0.4605997f, 0.5005013f,
- 2.6289063f, 0.23954524f, -0.38371497f, -0.09373493f,
- -0.050067585f, -0.3127257f, 0.5315178f, 1.9248289f,
- -0.41725013f, -0.27278736f, 0.17447259f, 0.5813525f,
- -0.17277718f, -0.59817356f, -0.5509615f, 0.05147647f,
- -0.7803084f, 0.010708118f, 0.7206401f, -0.31789395f,
- -0.33752218f, -0.53948647f, -0.513326f, -0.47851893f,
- -0.3815853f, -0.26219833f, -0.03705869f, -0.44402257f,
- -0.16718943f, -0.27324772f, -0.47415218f, 0.47864813f,
- -0.105707765f, -0.83987796f, 1.1732035f, -0.3595552f,
- -0.42819718f, -0.2285939f, 0.7567983f, -0.31914973f,
- 0.3700291f, 1.0981029f, -0.6928537f, -0.54553497f,
- -0.21035656f, -0.533216f, -0.3849009f, 0.81624824f,
- 0.5600584f, 0.1831133f, -0.39730147f, -0.4435527f,
- -0.11680812f, -0.7412355f, 0.3844088f, 0.531445f,
- -0.04384877f, -0.04949477f, -0.18281394f, -0.17433757f,
- -0.98570246f, -0.18980242f, -0.46788183f, -0.18694119f,
- -0.34217545f, -0.29625362f, 0.14647612f, 0.2944423f,
- -0.04059854f, -0.042797677f, -0.040447593f, 0.20496269f,
- -0.047180545f, -0.069175765f, -0.07087523f, 0.08251723f,
- -0.05432551f, -0.053449515f, -0.053313795f, 0.46824607f,
- -0.06913385f, -0.0456337f, -0.043791164f, -0.057773624f,
- 0.66623855f, -0.07087287f, -0.00922363f, -0.044689324f,
- -0.014117791f, -0.012137435f, -0.06622802f, -0.10991529f,
- 0.61852545f, -0.18019423f, -0.04767864f, -0.08376738f,
- -0.06413797f, -0.044821363f, -0.1071103f, -0.089599945f,
- -0.06226665f, 0.4405927f, -0.08720438f, -0.048150882f,
- -0.0624771f, 0.12718469f, -0.054602604f, -0.272991f,
- -0.04048413f, 0.02608503f, -0.19375691f, -0.0069655925f,
- -0.10315154f, -0.027112078f, -0.01375855f, 0.82535124f,
- -0.039398864f, -0.08086898f, -0.053538814f, -0.06786823f,
- -0.04876256f, -0.043333557f, -0.054055687f, -0.05673124f,
- -0.05329543f, -0.06892506f, 0.028929617f, 0.5033463f,
- -0.01800739f, -0.057775326f, -0.08395803f, -0.026848814f,
- -0.05152927f, -0.007896721f, -0.05103176f, -0.0760586f,
- -0.042373348f, -0.046389166f, -0.0778958f, -0.034295324f,
- -0.0570254f, -0.05551554f, -0.070244975f, -0.15174226f,
- -0.033920687f, -0.049854387f, 0.38210255f, 0.7423302f,
- -0.04792178f, -0.05752201f, 0.117201306f, -0.092562415f,
- -0.05144671f, 0.096918f, -0.013160955f, -0.06518922f,
- -0.044445917f, -0.081485555f, -0.053429876f, -0.05319101f,
- -0.042740677f, 0.10117366f, -0.20642973f, 0.33122084f,
- -0.05468204f, -0.062182676f, -0.05183669f, 0.04205446f,
- -0.08074788f, -0.06880706f, -0.064128436f, -0.087072484f,
- -0.070263535f, -0.055503424f, -0.08816967f, 0.012761939f,
- -0.14788015f, -0.22453175f, 0.008989235f, -0.41011733f,
- 0.31345984f, -0.11501605f, -0.327632f, 0.11304607f,
- 0.8867641f, -0.051492743f, -0.10333785f, -0.20320679f,
- 0.036403608f, 0.3304602f, -0.14269972f, -0.08473164f,
- -0.24818338f, 0.40873855f, -0.29703322f, -0.21852578f,
- -0.2819331f, 0.19413649f, 0.45745033f, 0.42496106f,
- -0.34403703f, -0.3005676f, 0.03965856f, -0.26576588f,
- -0.19773868f, 0.0490203f, 0.0066664624f, 0.49169806f,
- 0.6864068f, -0.17138332f, 0.048986103f, -0.15625244f,
- -0.17113757f, -0.20445842f, 0.07331553f, 0.021341372f,
- -0.048371896f, -0.23592798f, -0.11344547f, 0.86376697f,
- 0.43957603f, -0.10809906f, -0.23888843f, 0.31366646f,
- 0.33656693f, -0.27703315f, -0.22802812f, -0.23959284f,
- -0.23887883f, -0.07602207f, 0.284528f, -0.18794201f,
- -0.05843593f, -0.29399794f, -0.31610468f, -0.1109023f,
- 0.8011532f, 0.6514893f, 0.3280405f, 0.060744148f,
- 0.05240765f, -0.14324643f, -0.15747368f, -0.11350801f,
- 0.2634951f, -0.046051294f, 0.24869385f, -0.31745687f,
- -0.22627227f, -0.22127461f, -0.3075701f, 0.020692613f,
- -0.3089254f, 0.090396024f, -0.062099233f, -0.1671331f,
- 0.34369415f, -0.18453473f, -0.18415035f, 0.32481843f,
- -0.08741628f, -0.14863881f, -0.20426407f, 0.01913964f,
- 0.33613735f, 0.3441304f, -0.2088197f, -0.12814619f,
- -0.22931996f, -0.1408002f, 0.5495765f, -0.12225401f,
- 0.007359206f, 0.057471797f, 0.07656357f, 0.5153447f,
- -0.23735607f, 0.2442902f, -0.19786134f, -0.3365418f,
- -0.27255824f, -0.09909286f, -0.14378521f, -0.24858516f,
- 0.5091243f, -0.13564901f, -3.245299f, -1.1912339f,
- -1.5289521f, 0.16151763f, 4.9045424f, 0.25709963f,
- 1.4951487f, 0.23266052f, -1.6892784f, -3.068757f,
- -0.50209016f, 0.9316227f, 4.997536f, 0.1061094f,
- -2.4949946f, -0.10037525f, 2.4121878f, -1.4631541f,
- -0.3324594f, -0.06186497f, 1.2831728f, 0.64376765f,
- -1.3154972f, 0.21338472f, -1.8146349f, 1.4129766f,
- -1.2752876f, -0.022180531f, -2.8027453f, -2.8453467f,
- 0.5692756f, 2.7974858f, 0.8500487f, 1.6284565f,
- -1.0991434f, -2.5127375f, 0.33721367f, 0.0027082858f,
- -1.4820509f, 0.31385076f, -0.4150593f, 1.8702142f,
- -0.27030388f, -0.91389763f, -1.8836881f, 3.2845933f,
- 0.05513706f, 0.89892817f, 2.8540893f, -1.4999993f,
- -1.1553653f, -0.34946877f, 4.7397685f, 1.5070848f,
- -0.6903917f, 2.5266705f, -1.3089688f, 0.79495645f,
- 1.5209175f, 1.1333238f, 1.9920139f, 1.9258175f,
- -1.7944716f, -1.3452908f, -2.6961935f, -1.0656224f,
- -1.8593614f, -0.5476769f, 0.03633222f, 0.95688343f,
- -2.447316f, -2.3480551f, 2.7326756f, -2.530356f,
- -0.952396f, -2.4171193f, 1.3509521f, -1.4576705f,
- 1.8520929f, -0.22570254f, -1.6826411f, 5.2720947f,
- 1.3245542f, -1.3714793f, -1.0851792f, 0.5311835f,
- 1.549658f, -1.6367525f, 0.84624714f, 1.3369805f,
- -1.7205912f, -1.9609661f, -0.6377163f, -0.17788577f,
- -0.7007213f, -0.07715741f, -0.42372888f, -0.9315095f,
- 7.23797f, -0.105585314f, 4.2943125f, -0.7835346f,
- -2.2969968f, 1.1141025f, -1.6180768f, -0.30560356f,
- -0.3862675f, -0.032402314f, -2.1212277f, 0.078392215f,
- -0.16521598f, -0.6035964f, -0.38191128f, -0.17787878f,
- -0.6144353f, 0.123869725f, -0.24507542f, -0.24742445f,
- -0.7477126f, -0.44756243f, -0.177043f, -0.33420303f,
- -0.11735774f, -0.4009535f, -0.38700426f, 0.27587178f,
- -0.43228167f, 2.7131128f, 0.09190635f, -0.21932778f,
- 1.6143534f, -0.2654939f, -0.44714773f, -0.07994861f,
- -0.28960356f, -0.43486804f, -0.39206252f, -0.116957426f,
- -0.2530939f, 0.6494995f, 0.23928085f, -0.23792729f,
- 0.23101127f, 1.8282894f, -0.5680688f, -0.577235f,
- 1.1908431f, -0.16988166f, -0.3580438f, -0.11627708f,
- 1.5197824f, 0.15340422f, 0.52793384f, -0.6730439f,
- -0.16870612f, -0.062429458f, -0.008101125f, -0.9055084f,
- -0.36481604f, -0.26692998f, -0.46513724f, 0.05610379f,
- -0.38172048f, -0.19575018f, 0.70506585f, 0.19917852f,
- -0.4142164f, 0.23309413f, 0.77455443f, 0.33563736f,
- -0.21902452f, -0.27097726f, 1.2680154f, -0.56145525f,
- 0.9026468f, -0.5430327f, 0.44730124f, -0.529221f,
- -0.19747362f, -0.37266108f, -0.32645473f, 0.23053531f,
- -0.22693978f, 0.093588464f, -1.0797266f, 1.1767545f,
- -0.43318924f, 0.2517889f, 0.090637f, -0.29850268f,
- -0.56445104f, 0.57575274f, -0.72089714f, -0.7249757f,
- -0.25968528f, 2.198722f, -0.18486099f, 0.6753446f,
- -0.4232694f, -0.64004606f, -0.120899655f, 0.010559382f,
- 0.5457508f, 0.26949048f, -0.005236931f, 1.7920914f,
- -0.475417f, -0.33803096f, -0.05582408f, -0.058706403f,
- -0.2371456f, -0.31356424f, -0.18099646f, -0.14208563f,
- -0.41984993f, 0.51836944f, 0.42272365f, -0.16671616f,
- -0.22016649f, -0.14923811f, -0.5074317f, -0.17680755f,
- -0.40554622f, -0.43397424f, 1.264255f, 0.1518495f,
- 0.06995534f, -0.34305996f, -0.06963886f, -0.49670815f,
- 0.28133988f, -0.25703022f, 0.7227783f, -0.3195184f,
- -0.048875216f, -0.14142594f, -0.46399066f, -0.39447963f,
- -0.0008344791f, 0.24314483f, -0.62095207f, -0.45817122f,
- 0.7393983f, 0.38031116f, -0.1596328f, -0.1463307f,
- -0.50726634f, -0.6133452f, 0.4469347f, 1.0184636f,
- -0.24785668f, 0.048282836f, 1.5973163f, -0.66892576f,
- 0.25036678f, -0.31332573f, 0.62061316f, 1.1460098f,
- 0.07578971f, 1.6241786f, 0.14715536f, 1.2062443f,
- -0.307872f, -0.35862413f, -0.19323158f, 0.5250353f,
- 0.35716543f, -1.0726534f, -0.43440923f, 1.3876629f,
- -0.10585265f, 0.29060143f, -0.61795026f, -0.29856816f,
- -0.22975394f, 0.29849267f, -0.00874027f, -0.020322684f,
- 0.7922271f, -0.7576335f, -1.2088797f, 1.3998377f,
- -0.32582644f, 1.0967755f, -0.4269805f, 0.23950922f,
- -0.31333762f, -0.32095957f, -0.049845412f, -0.53134775f,
- 0.051551837f, -0.051701836f, -0.31936094f, 0.3354468f,
- -0.46208447f, -0.17845109f, -0.14125003f, 0.39425957f,
- -0.19048546f, 1.9868296f, 0.81152546f, 0.38252142f,
- -0.75400084f, -0.18120265f, -0.17888172f, 0.50400364f,
- -0.1309107f, -0.18796755f, 0.19250429f, 0.23020199f,
- -0.17581862f, -0.05742674f, -0.1952111f, 0.24598727f,
- -0.23712078f, -0.4296746f, -0.58402926f, -0.039316624f,
- -0.72882444f, -0.78858924f, -0.41447774f, 0.20351675f,
- -0.7704349f, -0.33621782f, -0.3383659f, 0.032691874f,
- -0.16934952f, -0.24352922f, -0.31851542f, -0.15134709f,
- 0.31857806f, -0.25322625f, -0.43772027f, -0.18734159f,
- -0.10597676f, -0.022058459f, -0.2296591f, -0.20721552f,
- 1.3529408f, 0.15525767f, -0.1622505f, -0.32637468f,
- -0.24629782f, 0.12814896f, -0.02935834f, -0.10235083f,
- -0.22465947f, 0.58113456f, -0.05103887f, -0.13468279f,
- -0.14909361f, 1.5287113f, 0.03041098f, -0.13273127f,
- -0.12145952f, -0.18152356f, -0.12047647f, 0.1479561f,
- -0.12787062f, -0.20195413f, 0.31294462f, -0.10319268f,
- -0.01226993f, -0.23856184f, 0.6239147f, -0.17148331f,
- 0.10070919f, -0.19542357f, 0.0772341f, -0.16935667f,
- -0.0982206f, -0.18505546f, -0.14778551f, 0.053730592f,
- 0.61852473f, -0.13541919f, -0.15418907f, -0.087227225f,
- -0.14829311f, 0.011300039f, 0.27125487f, -0.017062986f,
- -0.12895101f, -0.18528885f, 0.084198885f, 0.06366007f,
- 0.49764603f, 0.052521266f, -0.13019457f, -0.2844229f,
- 0.105128855f, -0.11454917f, -0.029467165f, -0.19816968f,
- 0.11838083f, -0.12132282f, -0.05813574f, -0.20517965f,
- 0.052005302f, -0.22309324f, -0.18763962f, -0.1512213f,
- -0.27252072f, -0.15416846f, -0.034726135f, 1.3242531f,
- 0.19436003f, -0.095249206f, 0.04742789f, 0.5877795f,
- -0.21977587f, -0.10796353f, 0.01951647f, -0.09236035f,
- -0.020188438f, -0.12907504f, -0.0759335f, -0.0992999f,
- -0.07052849f, 0.0118155405f, 0.7353497f, -0.25112748f,
- 0.11379894f, 0.065584406f, -0.05140101f, 0.10486359f,
- 0.31202012f, 0.00075648236f, -0.31251296f, -0.19162326f,
- -0.07334564f, -0.16162606f, -0.008397013f, -0.10953661f,
- 0.37413213f, -0.29329303f, -0.13483322f, -0.087157674f,
- -0.1414993f, 0.36293188f, -0.077365525f, -0.058889244f,
- 0.6933942f, 0.7798331f, 0.0006423129f, -0.064900406f,
- -0.14452277f, -0.04202969f, -0.05203011f, -0.15337543f,
- -0.08432723f, -0.08888691f, -0.08501798f, -0.14186098f,
- 0.013705337f, -0.09448301f, -0.20667097f, -0.1525808f,
- -0.17037542f, -0.1889299f, -0.068081304f, 1.1223702f,
- -0.121421024f, 0.54473984f, -0.0675197f, -0.0357743f,
- 0.31095478f, 0.731297f, -0.07419969f, -0.110575296f,
- -0.00735562f, -0.14157827f, -0.104142256f, -0.099712715f,
- -0.053440474f, -0.02694751f, -0.08806683f, -0.09087669f,
- 0.5299541f, -0.18184939f, -0.11453918f, -0.043923747f,
- -0.13863699f, -0.07774883f, -0.17811935f, -0.15316765f,
- -0.12138996f, -0.10802095f, -0.1531291f, -0.123738974f,
- -0.06872527f, -0.038617752f, 0.0036967474f, -0.11477649f,
- -0.25002772f, -0.06963991f, -0.17045806f, -0.08056333f,
- -0.111335374f, -0.13165586f, -0.07643323f, -0.19555625f,
- -0.031543627f, 0.62567943f, -0.044530366f, -0.12247363f,
- -0.07139325f, -0.07843464f, -0.07858625f, -0.08715079f,
- -0.11833983f, -0.121456f, 0.71174717f, -0.123438045f,
- -0.031673517f, 0.86292565f, 0.018444004f, -0.1300011f,
- -0.0895384f, -0.039979607f, -0.05563136f, 0.21438977f,
- -0.10283492f, -0.108991094f, 0.6722651f, -0.15451415f,
- -0.12662004f, -0.0507189f, -0.0756128f, -0.07959021f,
- -0.14815152f, 1.0293078f, -0.19747162f, -0.06819196f,
- -0.002428406f, -0.089958675f, -0.02596365f, -0.059871987f,
- -0.05459467f, -0.16192438f, -0.062419496f, -0.06587693f,
- -0.06873645f, -0.15449865f, -0.17318359f, -0.09771136f,
- -0.12974001f, -0.16158895f, 0.5717358f, -0.084961236f,
- -0.20535624f, 0.66835976f, 1.0161799f, -0.1558599f,
- -0.23936029f, -0.13791527f, -0.3097434f, -0.2490493f,
- 0.1380676f, -0.16897154f, -0.21544302f, -0.19960313f,
- -0.17972241f, 0.3943813f, -0.0778712f, -0.59899986f,
- -0.28983125f, -0.08205691f, -0.08822119f, -0.45131156f,
- 0.86800086f, -0.22535664f, 0.07200955f, -0.1026807f,
- -0.048685025f, 1.0255252f, 0.76763743f, -0.16120912f,
- 0.039556596f, -0.389713f, -0.15134293f, -0.20939146f,
- -0.2918036f, 0.08898704f, 0.038115665f, -0.22908004f,
- -0.4331322f, 1.0230756f, -0.24633168f, -0.35295293f,
- -0.051516566f, 0.19455078f, -0.18248364f, -0.22296885f,
- -0.30026418f, -0.07623236f, -0.19211799f, -0.09799359f,
- -0.09209696f, -0.036637552f, 0.356805f, -0.053117793f,
- -0.22705856f, -0.40618965f, 0.5705956f, -0.26047406f,
- -0.21637812f, -0.013339814f, -0.27438784f, -0.22170164f,
- -0.11929372f, -0.19693728f, 0.69474965f, -0.030960916f,
- -0.12628467f, -0.13382345f, -0.15123132f, 0.088672295f,
- -0.13596475f, 0.164326f, -0.2019867f, 1.458202f,
- -0.101872616f, -0.19601718f, 0.75952166f, 0.21572715f,
- -0.15882525f, -0.22318351f, -0.2534998f, -0.21491852f,
- -0.26230225f, 0.56173944f, -0.110702686f, 0.68396103f,
- -0.22186047f, -0.18958181f, -0.11987422f, -0.06722981f,
- 0.12778792f, -0.064399615f, 0.97989243f, -0.23586623f,
- -0.08069462f, -0.0010315385f, -0.1719537f, -0.012315141f,
- -0.08250754f, -0.06021454f, 0.114225015f, 0.11865231f,
- -0.09657258f, -0.06537738f, 0.4504663f, -0.26785934f,
- -0.10235469f, -0.075759396f, -0.07054297f, 1.2110074f,
- -0.07061863f, -0.08933015f, 0.54954237f, 1.0307138f,
- -0.068557814f, -0.059410665f, -0.06769102f, -0.58891606f,
- -0.05246995f, -0.07119684f, -0.08103003f, -0.10400154f,
- 0.85750663f, -0.1390859f, -0.22020581f, -0.08931334f,
- -0.35933617f, -0.1972246f, -0.09530977f, -0.14093459f,
- -0.67032063f, -0.21704006f, -0.058517955f, -0.5665637f,
- -0.1281535f, -0.120371565f, 0.8486377f, 0.6411364f,
- -0.09280596f, 0.457275f, -0.25413463f, -0.06377763f,
- -0.11209956f, -0.02884178f, -0.15010571f, -0.18659404f,
- -0.024694812f, -0.34407377f, -0.36919597f, -0.22679013f,
- -0.2372479f, 0.043952387f, -0.50401086f, 0.7639725f,
- -0.19551939f, -0.16894297f, -0.1677511f, -0.10658592f,
- -0.1060187f, -0.044279702f, -0.015670788f, -0.09773509f,
- -0.06399716f, -0.14393358f, 1.2576314f, 0.4235474f,
- -0.20301124f, -0.03528202f, -0.1355831f, -0.16521452f,
- -0.0527055f, -0.28780988f, -0.05997327f, 0.51481605f,
- -0.06086098f, -0.015246202f, -0.0539663f, -0.09051841f,
- -0.09769993f, -0.089735694f, -0.097509034f, -0.12328916f,
- 0.47530642f, -0.11892531f, -0.6005966f, -0.3241989f,
- -0.07546579f, -0.17664188f, 0.014087174f, -0.16929017f,
- -0.046370506f, -0.13561389f, -0.272132f, -0.046227656f,
- 0.44147912f, -0.09785386f, -0.048593923f, -0.003284786f,
- -0.059394218f, 1.4754174f, -0.2888204f, 0.78984857f,
- -0.28734905f, -0.08479924f, -0.004636723f, 0.80763906f,
- -0.17035925f, -0.11411562f, -0.0762842f, -0.08651389f,
- -0.071440354f, 0.015643885f, -0.051476024f, 0.7643402f,
- -0.16943529f, 0.011345445f, -0.08891153f, -0.052557617f,
- 0.26705444f, -0.09469682f, -0.06776107f, -0.17638479f,
- 0.0630696f, -0.0034271907f, -0.16697036f, -0.16569479f,
- -0.3682001f, -0.1291228f, -0.095983595f, -0.022529334f,
- -0.10452861f, 1.7001331f, -0.079353444f, -0.18664107f,
- -0.14389287f, 0.04353066f, -0.0560203f, -0.07478566f,
- -0.0033112003f, -0.47947484f, 0.014632433f, -0.10710191f,
- -0.064760216f, 0.012801905f, -0.08180658f, -0.09241023f,
- -0.25078478f, -0.018902455f, 0.8840193f, -0.19376351f,
- -0.12960444f, -0.013035116f, 1.118523f, -0.0544304f,
- -0.3972602f, -0.019998621f, -0.3380094f, -0.111371726f,
- -0.043343227f, -0.2213873f, 0.04424602f, -0.12576413f,
- 1.506286f, -0.0897413f, -0.040794637f, -0.14579995f,
- -0.07401411f, -0.0017304615f, 0.15991105f, 0.034115303f,
- 0.0440068f, -0.11241661f, -0.12238829f, 1.0046353f,
- 0.53961504f, 0.049733274f, -0.008334865f, -0.16100205f,
- -0.083938025f, -0.018340373f, 0.06482727f, -0.035987567f,
- -0.033639822f, -0.01977621f, -0.021651529f, -0.06778101f,
- 0.032525707f, -0.038062885f, -0.10641182f, -0.11923008f,
- -0.094821f, -0.082849525f, -0.044251088f, -0.3824972f,
- -0.036742277f, -0.059902802f, -0.08896533f, 1.1182829f,
- -0.2264846f, -0.05697751f, 0.010650847f, -0.077441335f,
- -0.039505377f, -0.15571208f, -0.14941037f, 0.06451599f,
- -0.10244627f, -0.053960983f, 0.41937825f, -0.19016522f,
- -0.08008917f, -0.12804964f, -0.07465409f, -0.07377058f,
- -0.19266811f, -0.12705989f, -0.05468989f, -0.13751832f,
- -0.06601322f, -0.06967073f, -0.05613472f, -0.08222775f,
- 0.09842964f, -0.18202016f, 0.9719291f, -0.9605074f,
- 1.3041224f, -0.14020559f, -1.4811311f, -2.0811245f,
- 2.3640583f, 0.40449268f, -0.16163479f, -1.4063257f,
- -0.48765105f, -1.3489553f, 0.44178832f, -0.39033908f,
- 0.06560599f, -0.31315064f, -0.83860546f, -2.2927368f,
- -1.0197542f, -1.1673751f, 0.34102976f, -0.5099828f,
- -0.9062806f, -0.41826898f, -0.07899199f, 0.3020093f,
- -1.48184f, 0.49549717f, -1.2773638f, -1.1834196f,
- 0.30794093f, 0.19614439f, -1.4454066f, 0.26864353f,
- 0.2150737f, -0.0746981f, 1.6954122f, -0.4487219f,
- 2.1913898f, 0.2021409f, -0.95479226f, 0.28159273f,
- 0.1995765f, 4.7661767f, -1.004848f, -1.0664318f,
- 0.050063506f, 0.840685f, -2.0692844f, -0.9998814f,
- -1.9086826f, 3.9779139f, -1.4034246f, -2.0032165f,
- -1.4537735f, 0.50762624f, -2.0896795f, 4.6145577f,
- -0.20413534f, -0.47954664f, 2.521249f, 0.6062019f,
- 1.740758f, 1.927769f, 0.9709083f, 1.5494872f,
- 1.1175932f, 0.6624587f, -1.1561397f, 3.493652f,
- -1.8038423f, 0.19296078f, -2.2293491f, 0.431286f,
- -1.8893515f, -1.5012933f, -1.2859248f, 0.045345947f,
- -0.24211454f, 0.015721077f, -1.0361565f, 1.9696685f,
- 0.90345f, 5.135731f, 1.3166921f, -0.08507231f,
- -1.4349167f, 0.040652227f, -0.30495557f, 0.44607633f,
- 0.031085689f, 3.7755563f, 0.36520156f, -0.22037484f,
- -1.5164635f, 0.016279614f, -1.0388546f, 1.1043286f,
- -1.2963879f, -0.113141194f, 2.866515f, -0.7312846f,
- -0.1772449f, -1.6656997f, -1.7544036f, -1.3774694f,
- -1.8918678f, -0.1450955f, 2.1963058f, -1.6106536f,
- 1.33655f, -1.5638145f, 0.30115643f, 1.1317407f,
- -0.55019516f, -0.22022247f, 0.44315428f, -1.337033f,
- -0.7270047f, -1.2995815f, 1.3359796f, 0.4782822f,
- -1.1205715f, -0.86714613f, 0.19996111f, 2.7001843f,
- 1.6260332f, -0.5754341f, -1.0942969f, 1.127095f,
- 0.8381238f, -0.57431996f, -0.9415868f, -1.6031262f,
- 0.88113046f, -0.30649918f, -0.23661016f, -0.63865274f,
- -0.7844237f, 0.6314974f, 2.0199847f, -1.4281647f,
- 0.70913446f, -0.38169587f, 1.1782441f, -0.6256343f,
- 0.91615134f, -1.9045323f, -0.16516156f, -1.8683245f,
- -0.13481945f, 0.64892775f, 0.9287833f, -0.83114463f,
- -2.4184558f, 0.48531744f, 2.3095934f, -1.6845237f,
- -0.3090838f, 0.1799165f, -1.5352963f, -2.4078815f,
- 4.8967977f, 0.14869462f, -0.09572636f, -0.33383435f,
- -0.5949049f, 0.80603814f, 0.38996848f, 2.389732f,
- 4.014198f, -0.9102735f, -0.20097952f, -0.6240594f,
- 0.32043105f, 0.5798332f, 1.4729239f, -1.4526463f,
- 0.50372636f, -1.083919f, -1.0195409f, 1.1879421f,
- 1.3279735f, 0.20341627f, -1.0574157f, 0.14699669f,
- -0.65162057f, 0.10131359f, 0.09796517f, -0.9867372f,
- 1.7686611f, 0.4568632f, -1.3777184f, -0.8863136f,
- -0.4613887f, 0.45452824f, -1.1128137f, 0.9403414f,
- 1.2155539f, -2.0640922f, -0.8921756f, -0.76357573f,
- 0.20462166f, -0.12176533f, 0.03498355f, 2.0140905f,
- -0.02654717f, 2.836424f, -0.2221909f, -0.5731516f,
- -1.0601555f, -2.1659853f, 0.09905769f, -0.3439853f,
- 4.100672f, -1.5121605f, 0.09849167f, -0.87646085f,
- -0.111136384f, -0.104889356f, -0.05014449f, 0.39457378f,
- -0.15210126f, -0.17108227f, -0.16428243f, -0.2002392f,
- -0.051233843f, -0.08949435f, -0.12091427f, 0.91593456f,
- -0.035705578f, -0.066945754f, -0.1474205f, -0.09266059f,
- -0.05892251f, -0.149778f, -0.23232673f, -0.10602271f,
- 0.9968219f, -0.14138348f, -0.06936083f, -0.19514155f,
- 1.0167874f, -0.020545365f, -0.062177062f, -0.18730642f,
- -0.075956546f, -0.07873062f, -0.13472998f, -0.19694273f,
- -0.1413151f, 0.5729162f, -0.21285151f, -0.0693932f,
- -0.17932937f, 1.2719157f, -0.18683764f, -0.26044703f,
- -0.031743888f, -0.4024791f, -0.21357615f, -0.083720855f,
- -0.13725547f, -0.06609677f, 0.14386456f, 0.37324086f,
- -0.14319639f, -0.15043709f, -0.024624914f, -0.09385145f,
- 0.02749968f, -0.02932522f, -0.050599158f, -0.15031804f,
- -0.10035011f, -0.08419575f, 0.5777162f, 0.4855261f,
- -0.082711026f, -0.10434648f, -0.10569423f, -0.09437872f,
- -0.006950237f, -0.047804438f, -0.097741134f, -0.03303353f,
- -0.10242629f, -0.087633915f, -0.11747758f, -0.050410524f,
- -0.090035915f, -0.07960162f, -0.055126216f, -0.36965653f,
- -0.1757266f, -0.020901296f, 0.87457937f, -0.15669827f,
- -0.10502692f, -0.12274494f, 1.2394947f, -0.15655775f,
- -0.059713814f, -0.17499715f, -0.11583768f, -0.050382394f,
- -0.21015647f, -0.04734223f, -0.05658728f, 0.0039635748f,
- 0.0031890762f, 0.51761675f, -0.2395448f, -0.11037278f,
- -0.10058915f, -0.09338112f, 0.0016230643f, 0.023574904f,
- -0.038955446f, -0.14396134f, -0.069569126f, -0.13883293f,
- -0.09181525f, -0.08090619f, -0.12021277f, 1.0330266f,
- -0.18011452f, -0.62369055f, -0.2920753f, -0.6931994f,
- -0.30645648f, -0.3139592f, -0.82285327f, 0.51588845f,
- -0.349422f, -0.4559153f, -0.6218901f, -0.5103204f,
- -0.1289873f, -0.14264512f, -0.26198703f, -0.6393748f,
- -0.20794952f, 0.57319605f, -0.5651838f, 2.4235473f,
- -0.64623857f, -0.09467637f, 1.8164599f, -0.27368385f,
- -0.35187054f, -0.08355021f, -0.22373953f, -0.6552683f,
- -0.283254f, -0.041095946f, -0.2466717f, 0.14125533f,
- 0.71727103f, 0.27153027f, 0.25317675f, 2.6977787f,
- -0.31855386f, -0.3759294f, 1.39738f, -0.51017237f,
- -0.41965884f, 0.12688972f, 2.875362f, -0.15346207f,
- 1.0036538f, -0.40458167f, 0.27970842f, -0.24707556f,
- 0.35540432f, -0.92239666f, -0.7859637f, -0.3161192f,
- -0.08910922f, 0.50518274f, -0.46508598f, -0.25305846f,
- -0.035165913f, -0.1747246f, -0.4388896f, 0.26183718f,
- 0.5253126f, 1.0328488f, -0.34620264f, -0.3711456f,
- 1.8534541f, -0.50869757f, 1.2457058f, -0.7047106f,
- 0.34197384f, -0.3529088f, -0.15322655f, -0.65237683f,
- -0.20216657f, 0.019681666f, -0.17181961f, -0.27745932f,
- -1.241886f, 0.66032946f, -0.24949373f, 0.3927405f,
- 0.16877837f, 0.16039874f, -0.49430364f, 1.0915824f,
- -0.70935714f, -0.75256634f, -0.3009856f, 1.9325179f,
- -0.10564536f, 0.19487485f, -0.31264725f, -0.6866285f,
- -0.13135484f, -0.49288642f, 0.52192384f, -0.24431984f,
- 0.028270988f, 1.6549047f, -0.3358775f, 0.07113401f,
- -0.036938913f, -0.14924547f, -0.46250308f, -0.6942391f,
- -0.13806807f, -0.08317873f, -0.47304642f, -0.1281403f,
- -0.087259665f, -0.30522522f, 1.6027882f, -0.5613978f,
- 0.11076214f, -0.27589324f, -0.21729241f, -0.020644074f,
- -0.5164893f, 0.5054003f, -0.47465482f, 2.1533349f,
- -1.0864481f, -0.55951923f, -1.5577031f, -0.2645343f,
- -0.64681447f, 0.25689247f, 0.025855232f, -1.4391131f,
- 2.7548258f, 1.4863582f, -0.1351676f, 0.98432815f,
- -0.65866435f, -0.97661316f, 0.2329133f, 0.79723066f,
- -0.0018489559f, -0.17102855f, -0.4576234f, -0.25167796f,
- 0.34515464f, -0.8440354f, 0.61075425f, 0.25944033f,
- 1.1189648f, -1.3440421f, -0.0958045f, 0.44757172f,
- -0.72594976f, -0.64836633f, -0.67244023f, 0.36922187f,
- 1.2747396f, -1.2004762f, 2.1444612f, -0.615728f,
- -0.1255524f, -0.41248044f, -1.3187649f, 0.7603614f,
- 0.7813427f, -1.3790113f, -0.4381056f, -0.7349672f,
- 0.9042463f, -0.16406189f, -0.18849385f, -1.5374476f,
- -0.19039346f, 1.0306007f, -1.4052085f, -0.6525929f,
- -0.62341064f, 0.73989725f, 0.3481507f, -0.83256304f,
- 0.3068445f, -0.38798475f, -1.103294f, -0.3555676f,
- 1.3363026f, 0.9849113f, -0.6876954f, -0.90802985f,
- 1.8650116f, 1.0557324f, -0.0352106f, -1.4269882f,
- 0.14177598f, 1.4514097f, 1.4397967f, -1.0461154f,
- -1.0371615f, -0.31151894f, 0.12377833f, 1.2521765f,
- -0.30643767f, -0.60049444f, 1.8596792f, -0.52536917f,
- -0.86471415f, 0.08941699f, -0.5124482f, -0.06390591f,
- 2.9197335f, 0.32995132f, 1.8389039f, -0.91715276f,
- -1.1366767f, -0.3299336f, -0.05111315f, -0.66399235f,
- 1.0686489f, -0.60406506f, 0.42501464f, -0.53267515f,
- 0.42189658f, 0.2657667f, -0.38478637f, -0.08645458f,
- -0.04374973f, -0.063867524f, 0.6822525f, -0.05210039f,
- -0.10122476f, 0.29309976f, 0.6344114f, -0.059007373f,
- -0.0359099f, -0.057651114f, -0.27071208f, -0.031266343f,
- -0.04054569f, -0.049608227f, -0.089039676f, 1.2105701f,
- -0.1162568f, -0.06983139f, -0.054610692f, -0.3424015f,
- -0.049831256f, -0.07050186f, -0.12041467f, -0.28728804f,
- -0.32768747f, -0.07308633f, -0.15189658f, -0.09413232f,
- -0.0865263f, -0.081707045f, 0.37297848f, -0.075489275f,
- 0.38885728f, -0.15889736f, -0.10669298f, -0.09049859f,
- -0.1953331f, -0.15302676f, -0.23687571f, -0.034140423f,
- -0.066245764f, -0.34081912f, -0.09426792f, -0.15719053f,
- -0.0035768577f, -0.11787476f, 1.1321594f, -0.091698f,
- -0.14864595f, -0.1331058f, -0.09960044f, -0.10042248f,
- -0.05604097f, -0.050445624f, -0.06309626f, -0.06074875f,
- -0.11888379f, -0.012482802f, 0.48014227f, -0.08753145f,
- -0.057418f, -0.095484294f, -0.10720702f, -0.056207612f,
- -0.17539085f, -0.027924666f, 0.27055427f, -0.06372059f,
- -0.046468735f, -0.025884882f, -0.05841177f, -0.07008285f,
- -0.069944374f, -0.06402444f, -0.10493562f, 0.1530031f,
- -0.06836547f, -0.2623413f, 1.2362267f, -0.061330616f,
- -0.09346811f, -0.1800319f, -0.01993575f, -0.05367767f,
- -0.20938286f, -0.13639876f, -0.056863647f, 0.3824019f,
- -0.14025927f, -0.039430562f, -0.059403356f, -0.040872876f,
- 0.629803f, -0.22628377f, 1.2558321f, -0.24787372f,
- -0.058900908f, -0.021613749f, 0.49668673f, -0.05429184f,
- -0.08654042f, -0.052936967f, -0.16148743f, -0.10723116f,
- -0.056262f, -0.07733217f, -0.10597747f, -0.14584115f,
- 4.126005f, -1.3737936f, 0.505447f, -0.61871696f,
- -2.1536713f, 2.947685f, 2.7014863f, 0.5789645f,
- -0.61416715f, 0.8183447f, 0.6166154f, -1.8441716f,
- -0.86656713f, 2.3718634f, 4.777559f, -0.01243389f,
- 0.3079794f, -0.106462665f, -1.0099027f, -1.3127979f,
- -0.03641009f, -1.3070503f, 1.7737631f, -1.7738284f,
- 0.53287524f, -0.42178005f, -2.0871837f, 0.16168523f,
- 0.61747795f, 0.76331896f, 0.06375345f, -0.74360466f,
- -1.6927153f, 0.09801302f, 3.1651762f, -4.0228934f,
- 1.9782853f, -1.5761131f, 1.208026f, 1.2213858f,
- -0.39610523f, -1.4352458f, -0.2379441f, 2.2246761f,
- -0.9453562f, 0.45440844f, -0.2748808f, -0.27917594f,
- 0.65128386f, -0.93905747f, -0.0165632f, 5.035802f,
- -2.12304f, -1.3580655f, 0.22787978f, -0.11021391f,
- -0.35965788f, 3.8298934f, -0.15867953f, 0.29168066f,
- -0.3076679f, 1.1380439f, -2.4071805f, 0.9238268f,
- -1.3912697f, 2.525193f, -0.35439163f, 0.99712855f,
- -0.0038540508f, -2.9491937f, 0.64837766f, -0.17620893f,
- -0.39280537f, 4.125322f, -0.1583971f, -0.7610832f,
- -1.8775619f, -0.87618196f, -0.4430532f, 0.77355087f,
- 1.5560325f, 4.2132835f, 1.1709714f, 1.624895f,
- -1.4230671f, 0.16191396f, -1.8629397f, 0.4166738f,
- -0.49169895f, -1.8521188f, 0.26731843f, 2.0992804f,
- 0.74131477f, 0.1069209f, 0.552337f, 0.10810329f,
- -2.7347565f, -1.6338507f, -2.9757833f, 0.1821129f,
- -1.0168259f, -1.4762527f, 0.44346228f, -2.0594025f,
- -2.934834f, -3.2838492f, -1.184633f, 0.43024328f,
- -0.019096259f, -0.14869617f, -0.117009975f, -0.110570334f,
- 0.8647301f, -0.123348475f, -0.12483614f, 0.55670035f,
- 0.40646625f, -0.08339191f, -0.07834121f, -0.116660476f,
- -0.04437124f, -0.037353303f, -0.067018636f, -0.10867973f,
- -0.11123757f, 0.19433622f, -0.16784944f, -0.24003436f,
- -0.14822617f, -0.2224466f, -0.015992707f, -0.20979014f,
- -0.19534476f, -0.1898724f, -0.1535425f, -0.11095539f,
- -0.2653848f, -0.0998878f, -0.1455046f, 0.70457023f,
- 0.6194715f, -0.07311831f, 0.4455038f, -0.2164201f,
- -0.103374735f, -0.23283465f, 0.22398785f, 0.14824699f,
- 0.22428104f, -0.08755824f, -0.25903407f, -0.25446036f,
- -0.21255997f, -0.26410523f, 0.029969728f, -0.16078301f,
- 0.29610735f, -0.056622587f, -0.2009441f, -0.06323646f,
- -0.10113081f, -0.10323564f, -0.086397864f, -0.014919333f,
- -0.08627749f, -0.10313731f, -0.16897076f, 0.85682946f,
- 0.14586481f, -0.18786286f, -0.08517478f, -0.18465774f,
- -0.22847699f, -0.0980448f, -0.14550906f, -0.037886996f,
- 0.5343162f, -0.053841643f, 0.029718662f, -0.115420766f,
- -0.08960468f, -0.05286889f, -0.16412222f, -0.09200654f,
- 0.024468057f, 0.3630499f, -0.1060175f, -0.18014817f,
- -0.15324827f, -0.090690814f, -0.090701334f, 0.26945594f,
- -0.062629476f, -0.07793518f, -0.1548963f, -0.25746903f,
- -0.08969244f, 0.6182978f, -0.1526444f, -0.06757559f,
- 0.0014450494f, -0.10863841f, 0.9332397f, -0.032369677f,
- 0.66820496f, -0.27259716f, -0.041251846f, -0.054286f,
- 0.8568237f, -0.11410237f, -0.1640928f, -0.11433078f,
- 0.0022397423f, -0.01623185f, 0.015434197f, -0.1144938f,
- 0.52729917f, -0.2126782f, -0.16187222f, -0.246566f,
- -0.12248282f, 0.7303879f, -0.20143075f, -0.23768353f,
- -0.23441899f, -0.30329692f, -0.2506279f, -0.018646568f,
- -0.22851661f, 1.2844819f, 0.06781667f, -0.23747753f,
- -0.17863192f, -0.21952987f, -0.48246157f, -0.008562267f,
- -0.25360146f, -0.13661358f, 1.552987f, -0.26423633f,
- -0.13257408f, -0.12776904f, 1.3144999f, 0.08627982f,
- -0.035850234f, -0.39982617f, -0.052098528f, -0.11060063f,
- 0.41939333f, -0.26026508f, -0.16657025f, 0.1206325f,
- -0.34961885f, -0.054826126f, -0.34133708f, 1.4459549f,
- -0.23864195f, -0.020222949f, -0.07333486f, -0.5771169f,
- -0.009568401f, -0.19681467f, -0.12672418f, -0.05980478f,
- 1.8476572f, -0.24577081f, -0.12190224f, -0.2442869f,
- 0.049252566f, -0.13629021f, -0.040514268f, 0.17925495f,
- -0.062034685f, -0.1849317f, -0.11358312f, -0.10172698f,
- 0.9446131f, 0.16562442f, -0.19491026f, -0.17941609f,
- -0.31982478f, -0.17046635f, 0.08586028f, -0.07429665f,
- -0.23165697f, -0.08787684f, -0.1973874f, -0.26306096f,
- -0.17393872f, -0.15256724f, -0.122627534f, -0.15829489f,
- -0.00983339f, -0.3174479f, -0.24417453f, -0.02600512f,
- 1.1356714f, -0.2981443f, -0.17494412f, -0.15817814f,
- 1.6078972f, -0.23621f, -0.11377106f, -0.49928173f,
- -0.3234844f, -0.1494736f, -0.24845915f, -0.2039287f,
- -0.16364464f, 0.0168359f, 0.06725135f, 0.7382442f,
- -0.23020843f, -0.31486177f, -0.25221008f, -0.03588698f,
- 0.16115753f, 0.25539035f, -0.063854866f, -0.30056494f,
- -0.15167432f, -0.31642354f, -0.068927325f, -0.076218665f,
- -0.10718838f, 1.787798f, -0.27260852f, 0.25858885f,
- -0.63235015f, 0.5838243f, -0.0673346f, -0.5753086f,
- -0.018505258f, 0.9462911f, 0.1151819f, 0.77216065f,
- 0.4852327f, -0.23406394f, -0.119813874f, 0.1433661f,
- -1.4348992f, -0.9864391f, 0.38854912f, 0.53741056f,
- 0.27338785f, -0.38443452f, -0.02442926f, 0.26227468f,
- 0.12803645f, -0.5771076f, -0.47216472f, 0.918012f,
- 0.42962754f, 0.3832584f, -0.1613641f, -0.34304047f,
- -0.02860183f, 0.22163077f, 0.37713972f, 0.25007424f,
- 0.07488504f, 0.4936225f, 2.3848417f, 1.0030379f,
- 0.07177838f, -1.2636042f, -0.25417715f, -0.4918006f,
- 0.08024875f, 0.07808205f, 0.028140256f, -0.6779907f,
- -1.0512277f, 0.0040068757f, 0.19947502f, -0.051909477f,
- 1.1705585f, -1.2269709f, -0.96804196f, -1.2938447f,
- 1.5351703f, 0.33071744f, -0.5793508f, 0.24963358f,
- 1.6736469f, 0.04460499f, -0.013115169f, 0.6562637f,
- -1.1044872f, -1.0777781f, 2.0530052f, 0.47502688f,
- 1.133121f, -0.7104695f, 1.1446528f, -0.02184209f,
- -0.36479154f, -0.47640413f, 0.4993506f, -0.7988516f,
- -0.027324328f, -0.9632527f, -0.11482751f, -0.11837496f,
- 0.13583274f, -0.2857097f, 0.12366137f, 0.18509375f,
- -0.4360142f, 0.067776285f, 0.2062468f, -0.45000967f,
- -0.23320279f, -0.7420626f, -0.8415195f, 0.9243018f,
- 1.0987504f, -0.7379438f, -0.0030011672f, -0.46319467f,
- -0.18382926f, -0.7014263f, 0.28753683f, 1.2530656f,
- 0.36619943f, -0.7950992f, 0.052529708f, -0.4628477f,
- 0.08676829f, 0.21903767f, -0.76892185f, -1.0064294f,
- 0.4854178f, -0.8159195f, -0.0065633566f, 0.29343006f,
- -0.043619826f, -0.064363755f, -0.028349357f, 0.4329647f,
- -0.037410278f, -0.047216754f, 0.23846631f, 0.6060533f,
- -0.07387607f, -0.0055467132f, -0.07506254f, -0.3724712f,
- -0.08496749f, -0.06343463f, -0.050894115f, -0.08159883f,
- 1.5700276f, -0.07966396f, -0.0721691f, -0.03510076f,
- -0.33192447f, -0.06825663f, -0.10301199f, -0.0040602386f,
- -0.39641362f, -0.3493759f, -0.0396541f, -0.24073161f,
- -0.097736485f, -0.05425011f, -0.22161032f, 0.014415978f,
- -0.070919976f, 0.6757284f, -0.17084238f, -0.06601891f,
- -0.08315872f, 0.03940789f, -0.12548815f, -0.29373097f,
- -0.037545383f, 0.024817245f, -0.30738965f, -0.039499715f,
- -0.12900789f, 0.003186633f, -0.06790437f, 1.4662086f,
- -0.09590871f, -0.13988549f, -0.122115694f, -0.085693724f,
- -0.058907695f, -0.025398303f, -0.045756027f, -0.07290554f,
- -0.06992234f, -0.09475523f, -0.03734844f, 0.87235695f,
- -0.075554475f, -0.050172664f, -0.06280817f, -0.06520987f,
- -0.030238347f, -0.07126528f, -0.04465171f, 0.15219447f,
- -0.054859914f, -0.06883934f, -0.006976728f, -0.03891803f,
- -0.08154554f, -0.07069643f, -0.08793449f, -0.13288622f,
- 0.30713338f, -0.07759819f, -0.40991503f, 1.3721563f,
- -0.065356724f, -0.09183272f, -0.03765428f, -0.12268617f,
- -0.07101502f, -0.04101386f, -0.069715425f, -0.04982788f,
- 0.04678035f, -0.09414893f, -0.038697977f, -0.021795647f,
- -0.051103123f, 0.39087152f, -0.26495254f, 0.87261844f,
- -0.1571078f, -0.03502216f, -0.043577682f, -0.21313186f,
- -0.06661568f, -0.055641707f, -0.06907113f, -0.096542455f,
- -0.10537334f, -0.018608665f, -0.046379127f, -0.18360266f,
- -0.1662345f, 0.02337357f, -0.26000375f, -0.28905475f,
- 1.3496659f, -0.22964583f, -0.098266974f, 1.1996219f,
- 1.087669f, -0.058027063f, -0.13912152f, -0.20519798f,
- -0.52721655f, -0.031324036f, -0.099879645f, -0.026049774f,
- -0.0058400477f, 1.0091887f, -0.21780746f, -0.30156663f,
- -0.19742896f, 0.10277748f, -0.12187507f, -0.15681912f,
- -0.25462908f, -0.6596033f, -0.11390781f, -0.13630715f,
- -0.51931965f, -0.026614368f, -0.087260835f, 0.50421846f,
- 1.417726f, 0.028923621f, 0.04606391f, -0.07240226f,
- -0.05641594f, -0.0925304f, -0.19773883f, -0.032813463f,
- -0.045837667f, -0.06852246f, -0.34410343f, -0.35022762f,
- -0.30080637f, -0.20449074f, -0.10979042f, -0.39269742f,
- 0.69739527f, -0.14393063f, -0.2840563f, -0.0806964f,
- -0.026558217f, -0.27742323f, 0.23596384f, -0.010118631f,
- -0.09438231f, -0.090395f, -0.016479254f, 1.3676015f,
- -0.063370004f, -0.17152762f, -0.11304047f, -0.2373336f,
- -0.27425382f, -0.08159364f, -0.24812075f, -0.03652285f,
- 1.0636331f, -0.10971223f, -0.20597579f, -0.17180158f,
- -0.12247504f, -0.045866504f, -0.2971483f, -0.103307076f,
- -0.21300252f, 0.7881888f, -0.1276106f, -0.5512873f,
- -0.37657335f, -0.0756769f, 0.024527725f, 0.07255303f,
- -0.24256279f, -0.16072732f, -0.10699947f, -0.32001537f,
- 0.046835095f, 1.0956019f, -0.21162881f, -0.022842068f,
- -0.12874176f, -0.017946951f, 0.46909007f, -0.12175445f,
- 0.5762279f, -0.45956957f, -0.1155497f, 0.07528753f,
- 0.5209127f, -0.28299034f, -0.11192657f, -0.18188676f,
- -0.20346695f, -0.23405655f, 0.0018263332f, -0.06900475f,
- 0.98928386f, -0.1032318f, 0.7943079f, -0.10296667f,
- 0.1528694f, -0.017429005f, -0.08912449f, 0.059849445f,
- -0.33116958f, 0.39532647f, -0.115458615f, -0.33275798f,
- 0.055903304f, 0.7538145f, -0.15151209f, -0.21213596f,
- -0.3869062f, -0.43247876f, 0.20742665f, -0.8163298f,
- 0.16972902f, -0.6654283f, 1.2306634f, -0.24947192f,
- -0.9721728f, -0.98797554f, -0.01758408f, 0.040834554f,
- -1.2779448f, -0.047849193f, 0.020453766f, -0.013435129f,
- 0.24745983f, 0.43294817f, -0.26374334f, -0.32410428f,
- -0.4843424f, -0.9044888f, 1.3821169f, 0.21247242f,
- 0.52988386f, -0.24633074f, -0.34893113f, -0.8167556f,
- 1.3504026f, 1.1961095f, -0.37472767f, -0.4821731f,
- 0.8983119f, 0.5459976f, -0.8322348f, -0.21018064f,
- 2.449748f, -0.30762154f, -0.47759813f, 0.6691908f,
- -0.6697109f, -0.9707612f, 0.3678808f, -0.7445342f,
- -0.29005215f, 0.66983336f, 0.5882531f, 0.4996742f,
- 0.29126176f, -0.7027795f, -0.73797625f, -0.63940066f,
- 1.3781668f, -0.3261514f, -0.33049825f, -0.18306749f,
- 0.55334544f, -0.5422867f, -0.5495477f, -0.081013f,
- -0.79360425f, -0.5946021f, -0.007307336f, 0.24662226f,
- 0.032096032f, 0.0921787f, -0.99806327f, 0.10323808f,
- 0.6027454f, -0.5000915f, -0.6880701f, 0.6964381f,
- 0.2234721f, 1.1708686f, -0.6888065f, 0.79322684f,
- 0.83273214f, -0.61318123f, 0.013360714f, 0.24341565f,
- -0.2693994f, -0.27492386f, 1.0850515f, 0.18746513f,
- 0.59431875f, -0.27257144f, -0.60703343f, -0.9124788f,
- 0.6008793f, -0.31754592f, 1.057831f, 0.3699018f,
- 0.5398806f, 1.0988705f, -1.1292733f, -0.3074327f,
- -1.1300536f, -1.2522227f, 0.023405304f, -1.1886477f,
- -0.21345064f, 0.22908592f, -0.04530017f, -0.6293799f,
- 1.7991153f, 0.33668578f, 0.5132697f, -0.21141733f,
- -1.2331325f, -0.63967943f, 0.95205504f, 1.717454f,
- 0.78392684f, 0.91836727f, -0.0731118f, 0.4787609f,
- 1.3136084f, -0.7087907f, -0.58450836f, -0.04315367f,
- 0.12165644f, -0.17939436f, -0.20481847f, 0.23876137f,
- 0.08975318f, -0.061179385f, 0.09135538f, 1.5220723f,
- 0.4476242f, 1.0550866f, 1.3471088f, -0.8159768f,
- 1.097041f, -0.6994464f, -0.047490064f, -0.7329513f,
- 0.79526746f, -0.047979366f, 0.32816505f, -0.3584117f,
- -0.37722135f, -0.106397465f, 0.9067494f, -0.61957824f,
- 0.24281691f, -0.8053762f, -1.0736781f, -0.7767315f,
- -0.032618362f, 0.04744306f, -0.97261405f, -0.01131603f,
- -0.65011984f, 0.7190157f, 0.31551385f, 0.43060496f,
- 0.40894163f, -0.7532901f, 1.2835971f, 1.1880504f,
- 0.87641346f, 0.35588264f, 0.7526419f, -0.49411264f,
- -0.311993f, -0.64150393f, 0.1645438f, -1.0125742f,
- -0.9054503f, -0.67251843f, 0.009432172f, -0.30666104f,
- -0.5586923f, -0.3879944f, 0.1646208f, -0.7223302f,
- -0.9858424f, 0.76959103f, -1.4576128f, -0.011258384f,
- -0.24311237f, 0.4950574f, 0.04091115f, 0.6681543f,
- -0.07441837f, -0.8941136f, -0.81637096f, 1.0461206f,
- 0.28912717f, 0.34488702f, -0.041837372f, 1.2966393f,
- -0.2019743f, 0.5884714f, -0.060681064f, -0.6193485f,
- -0.34994918f, -0.22072166f, -0.36513928f, 0.11428003f,
- 0.5662077f, 0.21764329f, -0.027602268f, -0.533084f,
- -0.5968502f, -2.055697f, -1.4011999f, -0.3966605f,
- 0.4509709f, -0.21429186f, 0.7023455f, -0.08135605f,
- -0.5645556f, -0.70118827f, -0.7939776f, -0.39355534f,
- -0.25218266f, -1.3541262f, -1.7785782f, -0.13589737f,
- 0.5168833f, 3.9773743f, 2.8157532f, 0.13510092f,
- -0.16977347f, 2.1454089f, -2.537439f, -0.24115479f,
- 0.9273092f, 1.661281f, -1.6214036f, 0.66984636f,
- -1.8523711f, -1.4331208f, -0.18873818f, -0.38880453f,
- 3.6645267f, -0.29007298f, 0.93876386f, 1.1899122f,
- -2.3698165f, 0.24722114f, -0.9598018f, 0.25704414f,
- -1.1942923f, 3.828838f, 0.28199643f, -1.8131096f,
- -0.42812696f, 0.13482288f, 0.28033364f, -0.5409465f,
- 4.149899f, 2.8330035f, -1.1503857f, -1.2414765f,
- 0.70707655f, -1.4942186f, 1.2708098f, -0.47189438f,
- -0.3760618f, 0.89761865f, 0.7096096f, -0.31020987f,
- -1.9966033f, -0.6843431f, -0.9535729f, 2.7979314f,
- -1.4356277f, 2.1651514f, -0.2913939f, -0.19556893f,
- -0.4953571f, -1.1425344f, 1.182255f, -0.13919644f,
- 0.40038797f, -1.1995921f, -0.5492645f, 4.98672f,
- -0.7659426f, -1.1024445f, 0.038249046f, 0.7416046f,
- -1.7107042f, 0.4492214f, 0.6621817f, -0.8620133f,
- -0.4635242f, 0.78357285f, -0.1293914f, -0.6597372f,
- 0.87679935f, 1.7015358f, -1.4185355f, 0.27316028f,
- 1.814076f, 0.27587706f, -0.016711935f, 0.70361376f,
- 1.7508055f, -1.3950337f, 0.1020933f, 0.023907589f,
- -0.7096953f, -2.0496297f, -1.4667363f, 2.0315814f,
- -2.1048512f, -0.79188585f, -1.1807259f, -0.5058371f,
- -0.9444019f, -0.31993577f, -0.1831404f, -0.2539122f,
- 0.35714146f, -0.26808238f, -0.07343128f, 1.159885f,
- 0.86007166f, -0.20516634f, -0.16649866f, -0.13513543f,
- -0.1211902f, 0.19694655f, -0.10591638f, -0.3006611f,
- -0.106795f, 0.050538953f, -0.31596327f, -0.56428516f,
- -0.1594333f, -0.18651636f, 0.3328649f, 0.069822565f,
- -0.33092853f, -0.1741284f, 0.30681527f, -0.24945751f,
- -0.3929991f, -0.124887064f, -0.17677347f, 0.7279733f,
- 1.4258343f, -0.21443987f, -0.16343059f, 0.26011643f,
- -0.23746352f, -0.010301876f, -0.1985319f, -0.030832961f,
- 0.094482414f, -0.13585459f, -0.018153625f, 0.99235827f,
- 0.35702276f, -0.12284731f, -0.11316427f, 0.5252042f,
- 0.025356937f, -0.12705685f, -0.36490363f, -0.2369417f,
- 0.07913397f, -0.23100954f, 0.15334806f, -0.119554155f,
- -0.10051573f, -0.097724736f, -0.040701702f, -0.19195542f,
- 0.68109775f, 0.5399039f, -0.10624547f, -0.21743327f,
- 0.29037204f, -0.21057525f, 0.23407653f, -0.11857402f,
- 0.94072706f, -0.14618655f, -0.32997578f, -0.2625795f,
- -0.020604748f, -0.0871526f, -0.10488704f, -0.09796676f,
- -0.24324271f, 0.5189722f, -0.15328711f, -0.17590481f,
- 0.25788045f, -0.11697531f, 0.25108576f, 0.28022614f,
- 0.021316847f, -0.2027552f, -0.45825464f, -0.37307933f,
- 0.017684182f, 1.1548729f, -0.19486211f, -0.0373074f,
- 0.01717865f, -0.056164358f, -0.37091687f, -0.16289406f,
- -0.047129728f, -0.22570752f, -0.05407783f, 0.09012987f,
- -0.4036787f, -0.28426322f, -0.10294025f, -0.15010604f,
- -0.1627489f, -0.2694389f, -0.16387582f, -0.360517f,
- 1.0838335f, -0.19847086f, -0.2254619f, -1.4553335f,
- -0.34737024f, 0.78860104f, 0.1291029f, 0.31328943f,
- 0.70065993f, 0.44264525f, -0.8916678f, -0.5314618f,
- -0.79523766f, 0.17865847f, 1.1820059f, 4.835566f,
- -0.95432174f, 0.23105095f, 0.19135273f, -2.4513528f,
- 0.06288023f, 1.885861f, -0.9035218f, -0.2717242f,
- 1.1904439f, 1.3674346f, -1.2102153f, 1.1850327f,
- -2.2958279f, 0.7941754f, -1.1327101f, -1.1892879f,
- 1.3823837f, -0.29319838f, -0.27384135f, -0.092770845f,
- -0.8143662f, -2.0951185f, -0.35654223f, -0.89996016f,
- 0.56277794f, -0.09866943f, -2.5120494f, -0.90382916f,
- 0.4481719f, -1.2120091f, -0.8103948f, -0.85966986f,
- 0.40664482f, -1.8354276f, 0.6932004f, -1.7309313f,
- -0.030138213f, -0.85542774f, 2.7837174f, -2.4523842f,
- 1.9372519f, 3.9534113f, -0.14710556f, 0.3995087f,
- 0.13060151f, -0.28248915f, -0.21723771f, 1.5073292f,
- 1.4673326f, -1.0990741f, 0.57713825f, 0.38026735f,
- -1.5209591f, 0.36957225f, -0.103986524f, -1.6968786f,
- -0.7684305f, -0.38876063f, -1.0173011f, 0.9458165f,
- 0.7091334f, 0.27440497f, 1.5338695f, -1.0156522f,
- 0.5209477f, 0.00017650302f, -0.9071651f, 0.30348158f,
- -0.89213955f, -0.73093253f, 0.7807798f, -0.28388873f,
- 1.5388883f, -1.8810889f, 0.024846354f, -1.9505635f,
- 0.8587582f, -0.90404516f, 3.0393248f, 0.41239753f,
- 0.7892313f, 1.1487992f, -1.3984896f, -0.16443512f,
- 2.509318f, 0.7164784f, 2.0090797f, 0.71863705f,
- 0.18492602f, 0.9364924f, -0.8106378f, -0.24615106f,
- 0.12644978f, 0.20502613f, -1.5561018f, -0.02015707f,
- -0.052660204f, -0.01732582f, 0.3207005f, -0.018808944f,
- -0.048504185f, -0.14267303f, 0.6196863f, -0.04122218f,
- -0.021372234f, -0.06719991f, -0.47480106f, -0.09336627f,
- -0.04450634f, -0.024095973f, -0.07595494f, 1.8674698f,
- -0.11614929f, -0.04642479f, -0.05255919f, -0.34628424f,
- -0.023378596f, -0.09796662f, -0.055824976f, -0.4711787f,
- -0.37814218f, -0.049118865f, -0.21279463f, -0.052305087f,
- -0.03396593f, -0.18704194f, -0.17710142f, -0.052071095f,
- 0.80279577f, -0.22401766f, -0.048200663f, -0.074151434f,
- 0.036254782f, -0.102286756f, -0.3849185f, -0.042821705f,
- 0.017834114f, -0.35006884f, -0.03459188f, -0.12170211f,
- 0.02380601f, -0.060174562f, 1.7643809f, -0.037754253f,
- -0.10983929f, -0.111324206f, -0.07682653f, -0.024592418f,
- 0.03803556f, -0.060636908f, -0.05753025f, -0.08777779f,
- -0.12087049f, -0.03253242f, 1.049829f, -0.00973103f,
- -0.04444153f, -0.08836384f, -0.062039804f, 0.0038220473f,
- -0.042821404f, -0.030310666f, -0.10398547f, -0.019471943f,
- -0.020804303f, -0.015480241f, 0.0071063326f, -0.052927792f,
- -0.07660381f, -0.058048733f, -0.15229811f, 0.044796452f,
- -0.06666621f, -0.5017551f, 1.5041261f, -0.041469138f,
- -0.07973666f, 0.012160781f, -0.12834615f, -0.060830332f,
- 0.08659943f, -0.019152153f, -0.037566014f, -0.09699825f,
- -0.08609042f, -0.023337342f, -0.04786302f, -0.038762655f,
- 0.33806694f, -0.31974828f, 0.74388766f, -0.15557525f,
- -0.04938048f, -0.043124985f, -0.18380652f, -0.101221494f,
- -0.059529293f, -0.0803404f, -0.1201651f, -0.085988976f,
- -0.06185426f, -0.051829856f, -0.12365156f, -0.17118026f,
- -0.14155056f, -0.03724727f, -0.12638727f, 0.65982246f,
- -0.14207654f, -0.2252237f, 0.8803773f, 1.0605528f,
- -0.046033826f, -0.13203344f, -0.13171908f, -0.18901153f,
- -0.11265797f, -0.028357144f, -0.14216036f, -0.18473803f,
- -0.37552977f, -0.13095216f, 0.124476604f, -0.13489829f,
- -0.501426f, -0.26470262f, -0.18993425f, -0.21658267f,
- -0.39655218f, 1.1002159f, -0.111567914f, -0.23038474f,
- -0.046846442f, -0.050305292f, 1.1300807f, 1.2043511f,
- -0.11237803f, -0.007674603f, -0.33567917f, -0.15286061f,
- -0.2391021f, -0.2064995f, 0.016049484f, -0.004363752f,
- -0.08426822f, -0.42424807f, 1.1658065f, -0.14185534f,
- -0.25896272f, -0.050090328f, 0.1673014f, -0.33805653f,
- -0.26862815f, -0.35154867f, -0.12670705f, -0.18841591f,
- -0.12408739f, -0.15393421f, -0.080315486f, 0.10083426f,
- -0.06292314f, -0.16379169f, -0.40018424f, 0.44703454f,
- -0.0849194f, -0.09024191f, -0.037232142f, -0.21272998f,
- -0.0983739f, -0.18618804f, -0.042120185f, 0.99322945f,
- -0.026304534f, -0.11074725f, -0.09834382f, -0.16763702f,
- -0.08689693f, -0.123912916f, -0.17496309f, -0.15150623f,
- 1.5195305f, -0.093505085f, -0.21619889f, 0.5190154f,
- -0.0043342854f, -0.23828518f, -0.18410371f, -0.16071187f,
- -0.15246022f, -0.3779148f, 0.26794806f, -0.031370718f,
- 0.95792806f, -0.15066054f, -0.090490334f, -0.11405747f,
- -0.114949465f, -0.04139405f, -0.2070787f, 0.89261323f,
- -0.1498521f, -0.09693234f, -0.029644622f, -0.4215521f,
- 0.008417838f, -0.114441425f, -0.049776614f, -0.021241253f,
- 0.050790273f, -0.037640836f, -0.13923082f, 0.442476f,
- -0.19685364f, 0.012177438f, 0.06027103f, -0.063853286f,
- 0.588912f, -3.0158806f, -1.3394474f, 1.7988544f,
- -0.033771943f, -0.22343811f, -1.4129138f, 2.5263302f,
- 0.14572552f, -2.043105f, -0.6423654f, 2.2303705f,
- -1.4712714f, 0.031608734f, -0.48892573f, 0.83516484f,
- -1.5987827f, -0.6325425f, -0.92283964f, -0.96227825f,
- -1.8435585f, 0.23254856f, -0.86193156f, 3.9194448f,
- -0.2462824f, -0.74069774f, -0.8694584f, 0.39672926f,
- 1.5716318f, -1.2225273f, -0.46637538f, -0.4400155f,
- -2.2512114f, -1.1225107f, -0.92430437f, 7.4050713f,
- -0.8473275f, -0.22211778f, -1.5112329f, 0.4139986f,
- 3.1858294f, 1.3971294f, 4.4564843f, -0.013639613f,
- 0.12382826f, 1.5078381f, -2.022467f, 1.3741103f,
- 3.9634173f, -1.4116995f, -2.789967f, -1.1218382f,
- 0.14577016f, 2.7963104f, -1.6394333f, -0.18857166f,
- -0.067756735f, -2.786301f, -0.17138071f, -2.0785286f,
- -0.027784592f, -0.2642613f, 1.1654868f, 6.038364f,
- -1.2674339f, 2.7103252f, -0.4506905f, -0.30301833f,
- 1.1598749f, -2.104159f, -2.0009847f, 1.5302604f,
- -1.6313688f, -0.29242453f, -2.9391391f, -0.8905586f,
- -0.009929302f, -0.2845194f, 5.2032022f, 1.153006f,
- 1.9765222f, 0.7851708f, 0.11771458f, -0.36879456f,
- 4.484034f, -1.2667835f, 0.7654907f, -1.4870417f,
- 4.299161f, -1.5540909f, -0.20284301f, -1.4582276f,
- -0.08672579f, -0.55917096f, 0.6886523f, 1.0674518f,
- 0.039790317f, -1.2513094f, -1.0866015f, -1.8314213f,
- 0.5199547f, -1.7185869f, -3.2857106f, -1.8832563f,
- 0.1037472f, -1.7060268f, -0.05076745f, -0.07994873f,
- -0.036780197f, 0.68139046f, -0.055277977f, -0.14568262f,
- -0.20173816f, 0.44683662f, -0.09264355f, -0.057565056f,
- -0.062122166f, 0.34664658f, -0.028352989f, -0.05496297f,
- -0.06873552f, -0.0734672f, 0.47257972f, -0.06852021f,
- -0.071986206f, -0.068147466f, -0.1540667f, -0.07217195f,
- -0.037965007f, -0.109210454f, 0.38829637f, -0.11262617f,
- -0.034044918f, -0.13207647f, -0.06500092f, -0.059887104f,
- 0.15016815f, -0.20924711f, -0.09527844f, 0.39137018f,
- -0.10291641f, -0.03325783f, -0.12296614f, 0.16084212f,
- -0.12512666f, -0.15939322f, -0.043138936f, -0.12133825f,
- -0.12966003f, -0.027857162f, -0.14080913f, -0.03332221f,
- -0.13873687f, 0.7870729f, -0.056969374f, -0.104636304f,
- -0.091701515f, -0.11303102f, -0.05248342f, -0.0459913f,
- -0.036064956f, -0.054954626f, -0.05116502f, -0.07917429f,
- 0.4883563f, 0.17127214f, -0.029153353f, -0.06484722f,
- -0.08133466f, -0.04863243f, -0.037153266f, -0.051024593f,
- -0.053637423f, -0.09618227f, -0.04477661f, -0.015738202f,
- -0.074817576f, -0.02156336f, -0.085069366f, -0.08527638f,
- -0.055762187f, -0.16237386f, -0.08717563f, -0.07043387f,
- 0.3312195f, 0.030071005f, -0.05247387f, -0.06886114f,
- 0.07553516f, -0.07718527f, -0.0565996f, -0.09016154f,
- -0.05181494f, -0.062874086f, -0.1079532f, -0.08540191f,
- -0.016053699f, -0.0525994f, -0.050031506f, 1.008061f,
- -0.13814455f, 0.62750006f, -0.053964514f, -0.057953026f,
- -0.0063926675f, 0.56094235f, -0.10218362f, -0.11223865f,
- -0.05274499f, -0.13394342f, -0.10740515f, -0.03897008f,
- -0.070843324f, 0.038092665f, -0.17299186f, -0.12752308f,
- 0.23881839f, -0.51790214f, 0.79326254f, -0.15729508f,
- -0.21016672f, -0.20631771f, 0.2263359f, 0.41173717f,
- -0.66483593f, -0.5333051f, 0.18883683f, -0.632379f,
- -0.6120813f, 0.43652222f, -0.2771339f, -0.791001f,
- -0.32323858f, -0.37096873f, -0.67931247f, 0.28254616f,
- -0.3271453f, -0.11565296f, 0.30609113f, 0.25949842f,
- -0.30110687f, -0.54154694f, 1.0674555f, 0.08226783f,
- 0.0018812119f, 0.49544007f, -0.064442314f, -0.48237818f,
- 1.9469919f, -0.35304973f, 0.34439173f, 0.67417973f,
- 0.036053345f, 1.2879039f, 1.2753297f, -0.5752737f,
- -0.22762713f, -0.20075358f, -0.20431006f, 0.5818426f,
- -0.37286296f, 1.0944947f, 0.045438252f, -0.275765f,
- 0.07955403f, 0.11630594f, -0.11940744f, -0.26594225f,
- -0.6109489f, -0.45185408f, -0.43265736f, -0.52665234f,
- -0.061942883f, 0.12519217f, -0.24018225f, -0.24301043f,
- -0.433587f, 1.1143113f, -0.4735742f, -0.6882276f,
- -0.36540905f, -0.20940526f, -0.3738598f, 0.7745126f,
- 0.33298004f, -0.17328352f, -0.30040246f, 0.17599353f,
- -0.6783118f, -0.20748757f, 1.1885334f, -0.071344085f,
- -0.48721913f, 0.2005283f, -0.16030411f, -0.67381406f,
- -0.114189535f, -0.04346687f, 0.7038935f, -0.58234876f,
- -0.14524484f, -0.43074632f, 0.19191232f, -0.27378806f,
- 0.3845337f, -0.5239602f, -0.5354967f, -0.37448788f,
- 0.47740337f, 0.82667124f, -0.13896006f, -0.4503225f,
- -0.4909708f, -0.49294582f, 1.0801072f, -0.20568085f,
- 0.2758656f, -0.5232208f, 1.0327914f, 0.9122714f,
- -0.36928582f, 0.13230166f, 0.9935363f, 0.9079253f,
- -0.028208485f, -0.16605808f, -0.1070845f, 0.93964785f,
- -0.16769354f, -0.2861739f, -0.41968772f, 0.56413f,
- -0.056634355f, -0.103041016f, -0.17677246f, 0.73609835f,
- 0.025645176f, -0.05174855f, -0.10666964f, -0.10474967f,
- -0.045879718f, -0.076300025f, -0.09981791f, -0.118425116f,
- -0.29729098f, -0.17563002f, -0.039501198f, -0.18888026f,
- 0.82370704f, 0.39910454f, -0.018393725f, 2.2793627f,
- -0.08361429f, -0.10327012f, 0.94999754f, -0.33551815f,
- -0.19962744f, -0.31654677f, -0.27939358f, -0.14223509f,
- -0.17803831f, -0.29558507f, -0.1662225f, -0.14698975f,
- -0.06397015f, -0.2399918f, -0.34073636f, -0.1318729f,
- -0.26349428f, -0.05498705f, 0.040861398f, 0.5180858f,
- 0.003147372f, -0.070194475f, -0.049549587f, -0.10022253f,
- -0.122750916f, -0.04705392f, -0.037721284f, -0.08184907f,
- -0.14642331f, -0.07761883f, -0.4466526f, -0.34220713f,
- -0.123389274f, -0.035160508f, -0.16279401f, -0.19628863f,
- -0.12765814f, -0.22707555f, -0.15016326f, -0.3094086f,
- -0.021274254f, -0.10242139f, -0.19713081f, -0.050579853f,
- -0.13789901f, -0.07356587f, -0.1197805f, -0.26214343f,
- -0.2317842f, -0.10083648f, 0.7077057f, 0.5156403f,
- -0.046442922f, -0.0916964f, -0.3208123f, -0.12456388f,
- -0.071794204f, -0.251899f, -0.13152304f, -0.1516945f,
- -0.120079726f, -0.067234114f, -0.059363805f, -0.04103953f,
- -0.07305493f, 1.1960651f, -0.17044385f, 1.7061769f,
- -0.20306633f, -0.057240233f, -0.06370874f, 2.3744242f,
- -0.073189534f, -0.104550004f, -0.013507958f, -0.20941575f,
- -0.20530173f, -0.07176221f, -0.102969885f, -0.32471f,
- -0.28300065f, -0.27325994f, -0.20775306f, -0.41850773f,
- 0.1492381f, -0.15180662f, -0.24824038f, 0.7757363f,
- 0.62617457f, -0.15386881f, -0.20332478f, -0.24370745f,
- -0.03181661f, 0.34457853f, -0.15440315f, -0.32553214f,
- -0.21669565f, 0.8285096f, -0.13036437f, -0.59527445f,
- -0.27939108f, 0.13493893f, 0.8135861f, -0.12753645f,
- -0.409347f, -0.23041464f, 0.36402997f, -0.258753f,
- -0.3637811f, -0.21284111f, -0.1963733f, 0.49027961f,
- 1.33351f, 0.0012927396f, -0.1523869f, 0.34579697f,
- 0.07566766f, -0.096343726f, -0.12673503f, -0.17110693f,
- -0.12502946f, -0.10177344f, 0.4612645f, 0.695828f,
- 0.31907317f, -0.1504917f, -0.2896372f, -0.15999264f,
- 0.63271004f, -0.10779343f, -0.3664997f, -0.26462683f,
- -0.16801159f, -0.34536263f, 0.6553597f, -0.17361347f,
- -0.15056387f, -0.113197125f, -0.30485293f, -0.12670627f,
- 0.6537118f, 0.7282766f, -0.21054411f, -0.17251618f,
- 0.5568345f, -0.031712867f, 0.23223132f, -0.23445886f,
- 0.76398003f, -0.10763115f, -0.13661653f, -0.34704813f,
- -0.2557219f, -0.1768997f, -0.25019404f, -0.12512511f,
- -0.3191607f, 0.26065007f, -0.13158265f, -0.24717487f,
- 0.8367869f, -0.17537753f, 0.12581405f, 0.27331123f,
- -0.25464776f, -0.2845033f, -0.42102033f, -0.20292963f,
- 0.1497533f, 0.9912186f, -0.113312446f, 0.04811553f,
- -0.08705012f, -0.20253487f, -0.22212961f, -0.11502763f,
- 0.21691827f, 0.42015368f, -0.17904796f, 0.20119901f,
- -0.29428563f, -0.32353023f, -0.07885335f, -0.13168715f,
- -0.19446783f, -0.2606118f, -0.18607606f, -0.33099893f,
- 0.55501765f, -0.32108462f, -0.5035673f, -0.22446741f,
- -0.6550673f, 0.121899456f, 0.02170961f, -0.16113865f,
- 1.0350714f, 0.5645269f, 0.8715624f, -0.24232158f,
- -0.40491313f, -0.28037223f, 0.48954248f, -0.2674989f,
- -0.05894619f, -0.39794385f, 0.34665212f, 0.13443574f,
- -0.89208263f, -0.28754467f, 0.07583915f, 0.47142816f,
- -0.36703202f, -0.30829823f, 0.64655256f, 0.72610265f,
- -0.44970006f, -0.37071934f, -0.5350714f, -0.35649556f,
- 0.49435312f, 1.3067765f, -0.08894167f, -0.08103112f,
- 0.8074746f, -0.6476165f, 0.28123543f, -0.30810916f,
- 0.23237199f, 0.408107f, 0.08682405f, 1.0469713f,
- 0.6059259f, 0.09885036f, -0.047086637f, -0.7007549f,
- -0.2765364f, 0.5319014f, 0.74800617f, -0.45545438f,
- -0.040312093f, 0.46670905f, -0.15853956f, -0.21647212f,
- -0.3853696f, -0.022242887f, -0.10446228f, -0.039061416f,
- -0.26021853f, 0.40458167f, 0.17105667f, -0.6003792f,
- -0.6584481f, 0.9749734f, -0.377081f, 0.11536925f,
- -0.27493277f, 0.36423996f, -0.25829813f, -0.19704765f,
- -0.37196648f, -0.28491876f, -0.3427033f, -0.29912505f,
- -0.4281523f, 1.116663f, -0.14926377f, -0.2567903f,
- -0.2499715f, 0.85834f, -0.08666637f, 0.8051644f,
- 0.6530623f, 0.7682661f, -0.33835575f, -0.45248085f,
- -0.5680914f, 0.044924136f, 1.0017551f, 0.64123076f,
- 0.08064141f, -0.2594266f, 0.17317206f, -0.1705693f,
- -0.46661487f, 0.55057234f, 0.043618776f, -0.4478673f,
- 0.020550737f, -0.30283627f, -0.7052904f, -0.6581977f,
- -0.28858387f, -0.013536574f, -0.7244647f, -0.2719826f,
- -0.38110092f, 0.35431972f, -0.2801925f, -0.10223496f,
- -0.2177925f, -0.21874954f, 0.83285886f, -0.1607978f,
- -0.27856886f, 0.09410034f, 0.2999574f, 0.05428716f,
- -0.23122416f, -0.20242083f, 0.5882186f, 0.23393343f,
- -0.28207746f, -0.16335869f, -0.12460497f, -0.02888142f,
- -0.14237395f, -0.13647649f, 0.020138713f, 0.06481857f,
- -0.14320901f, -0.14913164f, -0.023940433f, 0.685426f,
- 0.5836354f, -0.15855084f, 1.506412f, -0.052390695f,
- -0.075348325f, 0.7876035f, 0.0812867f, -0.23010674f,
- -0.19136997f, -0.05013301f, -0.2011243f, -0.29382676f,
- -0.22566827f, -0.06926516f, 0.076358855f, -0.20401204f,
- -0.04024025f, -0.37823305f, -0.2038931f, -0.17308746f,
- -0.27407408f, -0.18983345f, 0.3397373f, -0.12516312f,
- -0.09861968f, 0.09500693f, -0.012361907f, 0.008031115f,
- -0.08376723f, -0.098810345f, -0.029550532f, -0.24977571f,
- -0.12131968f, -0.32527f, -0.39096254f, -0.00078782864f,
- -0.116087064f, -0.17319743f, -0.23122114f, -0.12560758f,
- -0.3135803f, -0.17617238f, 0.08686014f, -0.2417611f,
- -0.106949955f, -0.23414227f, 0.0010721607f, -0.22569674f,
- -0.25645536f, -0.28943005f, -0.21633558f, 0.36669824f,
- -0.014419214f, 0.5354415f, 0.5241396f, -0.008571644f,
- -0.13984253f, -0.19176625f, -0.048256997f, 0.021203691f,
- -0.18774831f, -0.21216394f, -0.18541026f, 0.24589358f,
- -0.11975394f, -0.06028734f, -0.06813112f, -0.0743396f,
- 0.527617f, -0.07678245f, 1.5490168f, -0.1168725f,
- -0.011056853f, -0.07891703f, 1.7298208f, -0.0821908f,
- -0.17766918f, 0.02367124f, -0.16507177f, -0.054402288f,
- 0.046942804f, 0.24873687f, -0.22794524f, -0.09480081f,
- -0.08969367f, -0.2172087f, -0.12793222f, -0.01675869f,
- -0.2191127f, -0.068642646f, 0.19541852f, -0.06391879f,
- -0.048862573f, -0.1256306f, -0.20950352f, -0.22867973f,
- -0.09445333f, -0.13311969f, -0.08643973f, -0.1542702f,
- 0.53952974f, -0.11045393f, -0.061346415f, -0.22807477f,
- 0.42117253f, -0.027685372f, -0.10813964f, 0.08410981f,
- -0.26968032f, 0.091250606f, -0.17592986f, -0.07664758f,
- -0.041770823f, -0.02709933f, -0.051027037f, -0.015922712f,
- -9.0643174e-05f, 0.5103915f, 0.09874553f, -0.05371079f,
- -0.15432684f, 1.8561924f, -0.19011249f, -0.21260978f,
- -0.05652085f, 0.00094711146f, -0.095782205f, -0.039844945f,
- -0.2538233f, 0.12010629f, -0.11097708f, 0.3721787f,
- -0.0047289636f, -0.055438235f, -0.07231152f, 0.017816635f,
- -0.021859026f, 0.10957266f, -0.03829221f, -0.0732374f,
- -0.10514873f, -0.09333681f, 1.0697588f, 0.412631f,
- -0.0020685866f, -0.057141382f, -0.1365956f, -0.043296985f,
- -0.014339845f, 0.022442155f, -0.13078754f, 0.15289932f,
- -0.15675797f, -0.007188728f, -0.08783015f, -0.12059504f,
- -0.1375521f, -0.054545246f, -0.05376028f, -0.2247827f,
- 0.06505213f, -0.09246503f, -0.34443027f, -0.09470883f,
- -0.09299522f, -0.14732671f, 1.8611257f, -0.29247165f,
- -0.22546507f, -0.06469463f, -0.19249399f, -0.06668498f,
- -0.029813614f, -0.32224512f, -0.12088292f, -0.02717201f,
- 0.07896612f, 0.99092466f, -0.15649559f, -0.07872213f,
- -0.15555833f, 0.023997782f, 0.026039606f, -0.24155249f,
- -0.20472853f, -0.07145196f, -0.17139508f, -0.029476162f,
- -0.037118003f, 0.013060803f, -0.03633099f, 0.15968244f,
- -0.047335435f, -0.14974122f, -0.18076645f, -0.07320965f,
- 0.60325944f, -0.17137338f, -0.13928482f, 0.2673727f,
- -0.018977638f, -0.093560934f, -0.047434382f, -0.19580632f,
- 0.04929631f, -0.0698642f, -0.12109533f, -0.14815043f,
- -0.13752608f, -0.1754619f, -0.053348165f, -0.0865307f,
- -0.06075337f, -0.31742916f, -0.07031745f, -0.111534275f,
- 0.04741698f, -0.019505251f, -0.094040714f, -0.17293905f,
- -0.35480776f, -0.052567355f, -0.00970664f, 0.964159f,
- 0.16396512f, -0.07309984f, 0.4015809f, -0.21574607f,
- 0.0724362f, -0.22185415f, 0.8757332f, -0.083578184f,
- 0.059160937f, -0.0834448f, -0.15556034f, -0.17660438f,
- -0.16141893f, -0.20786573f, 0.008121088f, 0.16070381f,
- -0.15062189f, -0.07837416f, -0.21095474f, -0.13263421f,
- -0.16583888f, -0.1243929f, -0.022103503f, -0.030256717f,
- -0.052948702f, -0.07325914f, -0.16629973f, 1.021488f,
- -0.019269763f, -0.08014162f, 0.015976705f, -0.035201505f,
- -0.14382407f, -0.15642816f, -0.038384892f, -0.073774055f,
- 0.34462845f, -0.19887063f, 0.043099947f, -0.1031538f,
- -0.15264122f, -0.037800714f, -0.22776355f, -0.021024125f,
- -0.080162056f, 0.42742535f, -0.096497126f, -0.02249597f,
- -0.18578373f, -0.14716503f, -0.1690867f, 0.6916396f,
- -0.23591924f, -0.089741014f, -0.11729504f, -0.16983598f,
- -0.20388864f, 0.21072438f, -0.19627728f, -0.15370475f,
- 0.012430356f, 0.04454207f, 1.4200885f, -0.13092187f,
- 0.39331606f, -0.15196547f, -0.037827194f, 0.018411828f,
- 0.9120159f, -0.14267978f, 0.0044335024f, -0.13580689f,
- 0.12935767f, -0.030593807f, -0.008250357f, 0.038667608f,
- 0.1926851f, -0.084554404f, 0.35277516f, -0.13339362f,
- 0.7079712f, -0.19534516f, -0.5591157f, -0.4160485f,
- -0.43863204f, -0.13580655f, 0.29325962f, -1.6218505f,
- 0.45227867f, 0.17176263f, -0.2401598f, 1.9380614f,
- -0.41462594f, -0.39875513f, 0.18359838f, -0.27282152f,
- 1.5252169f, -0.3559655f, -0.32141453f, -0.68657947f,
- -0.21707281f, 0.018570827f, -0.2500685f, 0.012555901f,
- -0.79171383f, -0.13699418f, 0.38630414f, 0.46799818f,
- -0.13528365f, -0.43527904f, -0.07762355f, 0.7241471f,
- -0.18855356f, -0.20240259f, -0.88328886f, 1.0893203f,
- -0.90006113f, -0.408817f, -0.7184536f, -0.44060287f,
- -0.1176669f, -0.23865001f, -0.6391108f, -0.16579266f,
- -0.20492677f, -0.08072082f, -0.735313f, -0.21379402f,
- 0.5054253f, -0.6575543f, -0.34470662f, -0.6356082f,
- 0.5218905f, -0.2648465f, 2.1024797f, -0.35464877f,
- 0.11287543f, 0.57458293f, -0.118205465f, -0.8263866f,
- -0.0024202578f, -0.27595353f, -0.71429956f, -0.040394463f,
- -1.4481316f, 1.0538948f, 2.2574856f, -1.0583372f,
- 0.058899023f, 0.29211482f, -0.2989984f, -0.7272656f,
- 0.6680416f, -1.1740354f, 2.531736f, 3.71478f,
- -0.036611952f, 0.11292269f, 0.6645881f, -0.5143057f,
- -0.5867287f, -1.0851696f, -0.68915653f, 0.10284501f,
- 1.7223685f, -0.20769694f, -0.9739635f, -0.85851663f,
- 0.07692705f, -0.48772994f, -1.1248629f, -0.17028826f,
- -1.2894279f, -0.05289317f, -0.098169334f, 2.4420857f,
- -0.097423404f, -0.13398808f, -0.32713696f, 0.7078527f,
- 1.494031f, 0.67352694f, 0.5289797f, 0.9325748f,
- 0.15060562f, 0.39385507f, -0.6640958f, -0.054847036f,
- -0.20265546f, -0.12844317f, 1.2023315f, -0.14840314f,
- -0.13903612f, 0.66828513f, 0.64257383f, -0.12419107f,
- -0.02326863f, -0.2743891f, -0.32749048f, -0.09000529f,
- -0.19731146f, -0.086874954f, -0.12923825f, -0.65745866f,
- -0.116239555f, -0.24549878f, 0.056695107f, -0.32980886f,
- -0.23800378f, -0.113621034f, 0.13140862f, -0.44813484f,
- -0.28874564f, -0.09346608f, 1.8302894f, -0.07114359f,
- -0.04271833f, 1.1727102f, 0.6237326f, -0.013261863f,
- -0.09568916f, -0.2723805f, -0.17664014f, -0.1755764f,
- -0.35358548f, -0.04244494f, 0.061646666f, -0.017860413f,
- -0.23570676f, -0.26793286f, -0.33668783f, -0.23537038f,
- -0.08226442f, 1.6065152f, -0.76973754f, -0.10331195f,
- -0.13286892f, -0.0967179f, 0.027047494f, -0.06139745f,
- 0.007603367f, -0.028837938f, 0.023311067f, -0.07501887f,
- -0.10887642f, 0.9857764f, -0.27108452f, -0.29078344f,
- -0.088334836f, -0.16737741f, -0.34889394f, -0.15408167f,
- -0.38602543f, -0.09839915f, 0.5769592f, -0.11604656f,
- -0.15565334f, -0.19263619f, -0.16473097f, -0.073759764f,
- -0.103603706f, 0.012884745f, -0.06322352f, 0.8086931f,
- -0.18353386f, -0.28095812f, -0.35401833f, -0.030269274f,
- -0.2302352f, -0.45802194f, -0.07767666f, -0.10663385f,
- -0.30296946f, -0.35562605f, -0.18616152f, 0.626868f,
- -0.180854f, 0.015734475f, 0.15911014f, -0.09229424f,
- 1.0280387f, -0.20217244f, 0.45183918f, -0.32049936f,
- -0.21864495f, -0.096961334f, 1.8583243f, -0.14255683f,
- -0.01943386f, -0.030820897f, -0.30211717f, -0.096925735f,
- -0.08156736f, 0.0057511474f, 0.6857976f, 0.030785263f
-};
-
-const int LangIdNNParams::kSoftmaxBiasNumRows[] = {109};
-
-const int LangIdNNParams::kSoftmaxBiasNumCols[] = {1};
-
-const float LangIdNNParams::kSoftmaxBiasWeights0[] = {
- 3.758343f, 2.6076148f, 2.177158f, -3.0010588f,
- 0.47663444f, 2.4189885f, -4.152534f, -3.3232126f,
- 2.0016637f, 2.3771925f, -2.944416f, -0.2086796f,
- 2.0137417f, -1.1879843f, 1.5142481f, 1.1063648f,
- -1.2048897f, 2.3889086f, -3.7796104f, -2.6228247f,
- -0.28567508f, -3.8649852f, 6.9404716f, 0.9941252f,
- -0.65013033f, -1.2380573f, 1.2005652f, -2.7463508f,
- 8.299182f, 8.19762f, -2.5483642f, -3.17054f,
- 1.2276528f, -2.5437324f, -2.665871f, 4.0784645f,
- 2.2515485f, -2.2679532f, 1.8698318f, -1.5543324f,
- 3.5213368f, -4.3062673f, -3.856432f, -4.7833767f,
- 3.1276455f, 0.8346448f, -2.6662865f, 0.08592484f,
- 3.2809117f, 1.5064548f, -1.0923159f, 2.1658738f,
- 0.5755793f, 0.6355702f, 5.7022915f, -1.5173566f,
- -2.8129232f, 3.053764f, -1.2314724f, -3.0010624f,
- 0.48004666f, 4.2867346f, 2.2346094f, -1.8046769f,
- 2.5744162f, -1.6004965f, 1.493111f, -0.69651955f,
- -1.6677547f, 0.14361238f, 0.911624f, 1.9728141f,
- -1.3759614f, 2.159548f, -1.397155f, 0.9662558f,
- -3.142051f, -2.6323624f, -4.1593995f, -3.087284f,
- 1.7011054f, -0.5936492f, -2.5036366f, 1.454121f,
- 2.5975542f, -2.3782952f, -3.3263144f, 2.0415537f,
- -2.2195582f, -0.7691635f, 0.6129155f, 0.34192497f,
- 0.28149304f, -2.656388f, -0.28585556f, -2.656856f,
- -4.2364836f, 0.63873714f, -0.40722623f, -2.4080284f,
- 3.229281f, 3.0439858f, -1.2252908f, -1.7254728f,
- 3.5457535f, 1.3855044f, 0.75270873f, -3.436203f,
- 2.3819335f
-};
-
-const int32 LangIdNNParams::kEmbeddingDimValues[] = {
- 16, 16, 8, 8, 16, 16
-};
-
-const int32 LangIdNNParams::kEmbeddingNumFeaturesValues[] = {
- 1, 1, 1, 1, 1, 1
-};
-
-const int32 LangIdNNParams::kEmbeddingFeaturesDomainSizeValues[] = {
- 1000, 5000, 12, 103, 5000, 100
-};
-
-const int32 LangIdNNParams::kConcatOffsetValues[] = {
- 0, 16, 32, 40, 48, 64
-};
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/lang_id_nn_params.h b/chromium/third_party/cld_3/src/src/lang_id_nn_params.h
deleted file mode 100755
index 890da7461f7..00000000000
--- a/chromium/third_party/cld_3/src/src/lang_id_nn_params.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef LANG_ID_NN_PARAMS_H_
-#define LANG_ID_NN_PARAMS_H_
-
-#include "base.h"
-#include "embedding_network_params.h"
-#include "float16.h"
-
-namespace chrome_lang_id {
-
-class LangIdNNParams : public EmbeddingNetworkParams {
- public:
- ~LangIdNNParams() override {}
-
- // Access methods for embeddings:
- int embeddings_size() const override { return 6; }
- int embeddings_num_rows(int i) const override {
- return kEmbeddingsNumRows[i];
- }
- int embeddings_num_cols(int i) const override {
- return kEmbeddingsNumCols[i];
- }
- const void *embeddings_weights(int i) const override {
- return embeddings_weights_[i];
- }
- QuantizationType embeddings_quant_type(int i) const override {
- return QuantizationType::UINT8;
- }
- const float16 *embeddings_quant_scales(int i) const override {
- return embeddings_quant_scales_[i];
- }
-
- // Access methods for hidden:
- int hidden_size() const override { return 1; }
- int hidden_num_rows(int i) const override { return kHiddenNumRows[i]; }
- int hidden_num_cols(int i) const override { return kHiddenNumCols[i]; }
- const void *hidden_weights(int i) const override {
- return hidden_weights_[i];
- }
-
- // Access methods for hidden_bias:
- int hidden_bias_size() const override { return 1; }
- int hidden_bias_num_rows(int i) const override {
- return kHiddenBiasNumRows[i];
- }
- int hidden_bias_num_cols(int i) const override {
- return kHiddenBiasNumCols[i];
- }
- const void *hidden_bias_weights(int i) const override {
- return hidden_bias_weights_[i];
- }
-
- // Access methods for softmax:
- int softmax_size() const override { return 1; }
- int softmax_num_rows(int i) const override { return kSoftmaxNumRows[i]; }
- int softmax_num_cols(int i) const override { return kSoftmaxNumCols[i]; }
- const void *softmax_weights(int i) const override {
- return softmax_weights_[i];
- }
-
- // Access methods for softmax_bias:
- int softmax_bias_size() const override { return 1; }
- int softmax_bias_num_rows(int i) const override {
- return kSoftmaxBiasNumRows[i];
- }
- int softmax_bias_num_cols(int i) const override {
- return kSoftmaxBiasNumCols[i];
- }
- const void *softmax_bias_weights(int i) const override {
- return softmax_bias_weights_[i];
- }
-
- // Access methods for embedding_dim:
- int embedding_dim_size() const override { return 6; }
- int32 embedding_dim(int i) const override { return kEmbeddingDimValues[i]; }
-
- // Access methods for embedding_num_features:
- int embedding_num_features_size() const override { return 6; }
- int32 embedding_num_features(int i) const override {
- return kEmbeddingNumFeaturesValues[i];
- }
-
- // Access methods for embedding_features_domain_size:
- int embedding_features_domain_size_size() const override { return 6; }
- int32 embedding_features_domain_size(int i) const override {
- return kEmbeddingFeaturesDomainSizeValues[i];
- }
-
- // Access methods for concat_offset:
- int concat_offset_size() const override { return 6; }
- int32 concat_offset(int i) const override { return kConcatOffsetValues[i]; }
-
- // Access methods for concat_layer_size:
- bool has_concat_layer_size() const override { return true; }
- int32 concat_layer_size() const override { return 80; }
-
- // Access methods for is_precomputed:
- bool has_is_precomputed() const override { return false; }
- bool is_precomputed() const override { return false; }
-
- private:
- // Private fields for embeddings:
- static const int kEmbeddingsNumRows[];
- static const int kEmbeddingsNumCols[];
- static const uint8 kEmbeddingsWeights0[];
- static const uint8 kEmbeddingsWeights1[];
- static const uint8 kEmbeddingsWeights2[];
- static const uint8 kEmbeddingsWeights3[];
- static const uint8 kEmbeddingsWeights4[];
- static const uint8 kEmbeddingsWeights5[];
- const void *embeddings_weights_[6] = {
- kEmbeddingsWeights0, kEmbeddingsWeights1, kEmbeddingsWeights2,
- kEmbeddingsWeights3, kEmbeddingsWeights4, kEmbeddingsWeights5};
- static const float16 kEmbeddingsQuantScales0[];
- static const float16 kEmbeddingsQuantScales1[];
- static const float16 kEmbeddingsQuantScales2[];
- static const float16 kEmbeddingsQuantScales3[];
- static const float16 kEmbeddingsQuantScales4[];
- static const float16 kEmbeddingsQuantScales5[];
- const float16 *embeddings_quant_scales_[6] = {
- kEmbeddingsQuantScales0, kEmbeddingsQuantScales1,
- kEmbeddingsQuantScales2, kEmbeddingsQuantScales3,
- kEmbeddingsQuantScales4, kEmbeddingsQuantScales5};
-
- // Private fields for hidden:
- static const int kHiddenNumRows[];
- static const int kHiddenNumCols[];
- static const float kHiddenWeights0[];
- const void *hidden_weights_[1] = {kHiddenWeights0};
-
- // Private fields for hidden_bias:
- static const int kHiddenBiasNumRows[];
- static const int kHiddenBiasNumCols[];
- static const float kHiddenBiasWeights0[];
- const void *hidden_bias_weights_[1] = {kHiddenBiasWeights0};
-
- // Private fields for softmax:
- static const int kSoftmaxNumRows[];
- static const int kSoftmaxNumCols[];
- static const float kSoftmaxWeights0[];
- const void *softmax_weights_[1] = {kSoftmaxWeights0};
-
- // Private fields for softmax_bias:
- static const int kSoftmaxBiasNumRows[];
- static const int kSoftmaxBiasNumCols[];
- static const float kSoftmaxBiasWeights0[];
- const void *softmax_bias_weights_[1] = {kSoftmaxBiasWeights0};
-
- // Private fields for embedding_dim:
- static const int32 kEmbeddingDimValues[];
-
- // Private fields for embedding_num_features:
- static const int32 kEmbeddingNumFeaturesValues[];
-
- // Private fields for embedding_features_domain_size:
- static const int32 kEmbeddingFeaturesDomainSizeValues[];
-
- // Private fields for concat_offset:
- static const int32 kConcatOffsetValues[];
-}; // class LangIdNNParams
-
-} // namespace chrome_lang_id
-
-#endif // LANG_ID_NN_PARAMS_H_
diff --git a/chromium/third_party/cld_3/src/src/language_identifier_features.cc b/chromium/third_party/cld_3/src/src/language_identifier_features.cc
deleted file mode 100644
index d006a32ec40..00000000000
--- a/chromium/third_party/cld_3/src/src/language_identifier_features.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "language_identifier_features.h"
-
-#include <sstream>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "base.h"
-#include "feature_extractor.h"
-#include "feature_types.h"
-#include "script_span/generated_ulscript.h"
-#include "script_span/getonescriptspan.h"
-#include "sentence_features.h"
-#include "task_context.h"
-#include "unicodetext.h"
-#include "utils.h"
-
-namespace chrome_lang_id {
-NumericFeatureType::NumericFeatureType(const string &name, FeatureValue size)
- : FeatureType(name), size_(size) {}
-
-string NumericFeatureType::GetFeatureValueName(FeatureValue value) const {
- return value < 0 ? "" : Int64ToString(value);
-}
-
-FeatureValue NumericFeatureType::GetDomainSize() const { return size_; }
-
-void ContinuousBagOfNgramsFunction::Setup(TaskContext *context) {
- // Parameters in the feature function descriptor.
- include_terminators_ = GetBoolParameter("include_terminators", false);
- include_spaces_ = GetBoolParameter("include_spaces", false);
- use_equal_ngram_weight_ = GetBoolParameter("use_equal_weight", false);
- ngram_id_dimension_ = GetIntParameter("id_dim", 10000);
- ngram_size_ = GetIntParameter("size", 3);
-}
-
-void ContinuousBagOfNgramsFunction::Init(TaskContext *context) {
- set_feature_type(new NumericFeatureType(name(), ngram_id_dimension_));
-}
-
-void ContinuousBagOfNgramsFunction::Evaluate(const WorkspaceSet &workspaces,
- const Sentence &sentence,
- FeatureVector *result) const {
- // Include terminators for each token. Tokens are discovered by splitting the
- // text on spaces.
- std::vector<string> chars;
- utils::GetUTF8Chars(sentence.text(), &chars);
- if (include_terminators_) {
- std::vector<string> new_chars{"^"};
- for (size_t index = 0; index < chars.size(); ++index) {
- if (chars.at(index) == " ") {
- new_chars.push_back("$");
- new_chars.push_back(" ");
- new_chars.push_back("^");
- } else {
- new_chars.push_back(chars.at(index));
- }
- }
- new_chars.push_back("$");
- chars.swap(new_chars);
- }
-
- // Find the char ngram counts.
- std::unordered_map<string, int> char_ngram_counts;
- int count_sum = 0;
- for (int start = 0; start <= static_cast<int>(chars.size()) - ngram_size_;
- ++start) {
- string char_ngram;
- int index;
- for (index = 0; index < ngram_size_; ++index) {
- const string &current_char = chars.at(start + index);
- if (current_char == " " && !include_spaces_) {
- break;
- }
- char_ngram.append(current_char);
- }
- if (index == ngram_size_) {
- char_ngram_counts[char_ngram]++;
- ++count_sum;
- }
- }
-
- // Populate the feature vector.
- const float equal_weight = 1.0 / char_ngram_counts.size();
- const float norm = static_cast<float>(count_sum);
- for (const auto &ngram_and_count : char_ngram_counts) {
- const float weight =
- use_equal_ngram_weight_ ? equal_weight : ngram_and_count.second / norm;
- FloatFeatureValue value(
- utils::Hash32WithDefaultSeed(ngram_and_count.first) %
- ngram_id_dimension_,
- weight);
- result->add(feature_type(), value.discrete_value);
- }
-}
-
-FeatureValue ScriptFeature::Compute(const WorkspaceSet &workspaces,
- const Sentence &sentence,
- const FeatureVector *result) const {
- const string &text = sentence.text();
- CLD2::ScriptScanner ss(text.c_str(), text.size(),
- /*is_plain_text=*/true);
-
- // GetOneScriptSpan() is called only once because of the assumption that the
- // input contains one script. This function also cleans up the input (e.g.,
- // removes digits, punctuation).
- // TODO(abakalov): Extract the clean-up and script detection code out of
- // GetOneScriptSpan() because we don't have to iterate over the whole text,
- // just look at the first codepoint after clean-up.
- CLD2::LangSpan script_span;
- ss.GetOneScriptSpan(&script_span);
- const CLD2::ULScript ulscript = script_span.ulscript;
- if (ulscript != CLD2::ULScript_Hani) {
- return ulscript;
- } else {
- // Out of the codepoints captured by ULScript_Hani, separately count those
- // in Hangul (Korean script) and those in a script other than Hangul.
- int num_hangul = 0;
- int num_non_hangul = 0;
- UnicodeText unicode_text;
- unicode_text.PointToUTF8(script_span.text, script_span.text_bytes);
- for (chrome_lang_id::char32 codepoint : unicode_text) {
- // If the current codepoint is space, continue.
- if (codepoint == 0x20) {
- continue;
- }
-
- // Check if the current codepoint is within the ranges associated with
- // Hangul.
- if ((codepoint >= 0x1100 && codepoint <= 0x11FF) || // Hangul Jamo
- (codepoint >= 0xA960 && codepoint <= 0xA97F) || // Jamo Extended A
- (codepoint >= 0xD7B0 && codepoint <= 0xD7FF) || // Jamo Extended B
- (codepoint >= 0x3130 && codepoint <= 0x318F) || // Compatibility Jamo
- (codepoint >= 0xFFA0 && codepoint <= 0xFFDC) || // Halfwidth Jamo
- (codepoint >= 0xAC00 && codepoint <= 0xD7AF)) { // Hangul Syllables
- num_hangul++;
- } else {
- num_non_hangul++;
- }
- }
-
- if (num_hangul > num_non_hangul) {
- return static_cast<FeatureValue>(CLD2::NUM_ULSCRIPTS);
- } else {
- return static_cast<FeatureValue>(CLD2::ULScript_Hani);
- }
- }
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/language_identifier_features.h b/chromium/third_party/cld_3/src/src/language_identifier_features.h
deleted file mode 100644
index 476ca00634b..00000000000
--- a/chromium/third_party/cld_3/src/src/language_identifier_features.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef LANGUAGE_IDENTIFIER_FEATURES_H_
-#define LANGUAGE_IDENTIFIER_FEATURES_H_
-
-#include <string>
-
-#include "feature_extractor.h"
-#include "feature_types.h"
-#include "script_span/generated_ulscript.h"
-#include "cld_3/protos/sentence.pb.h"
-#include "sentence_features.h"
-#include "task_context.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-
-// Feature type for numeric features.
-class NumericFeatureType : public FeatureType {
- public:
- // Initializes numeric feature.
- NumericFeatureType(const string &name, FeatureValue size);
-
- // Returns numeric feature value.
- string GetFeatureValueName(FeatureValue value) const override;
-
- // Returns the number of feature values.
- FeatureValue GetDomainSize() const override;
-
- private:
- FeatureValue size_;
-};
-
-// Class for computing continuous char ngram features.
-// Feature function descriptor parameters:
-// include_terminators(bool, false):
-// If 'true', then splits the text based on spaces to get tokens, adds "^"
-// to the beginning of each token, and adds "$" to the end of each token.
-// include_spaces(bool, false):
-// If 'true', then includes char ngrams containing spaces.
-// use_equal_weight(bool, false):
-// If 'true', then weighs each unique ngram by 1.0 / (number of unique
-// ngrams in the input). Otherwise, weighs each unique ngram by (ngram
-// count) / (total number of ngrams).
-// id_dim(int, 10000):
-// The integer id of each char ngram is computed as follows:
-// Hash32WithDefaultSeed(char ngram) % id_dim.
-// size(int, 3):
-// Only ngrams of this size will be extracted.
-class ContinuousBagOfNgramsFunction : public WholeSentenceFeature {
- public:
- void Setup(TaskContext *context) override;
- void Init(TaskContext *context) override;
-
- // Appends the features computed from the focus to the feature vector.
- void Evaluate(const WorkspaceSet &workspaces, const Sentence &sentence,
- FeatureVector *result) const override;
-
- private:
- // If 'true', then splits the text based on spaces to get tokens, adds "^" to
- // the beginning of each token, and adds "$" to the end of each token.
- bool include_terminators_;
-
- // If 'true', then includes char ngrams containing spaces.
- bool include_spaces_;
-
- // If 'true', then weighs each unique ngram by 1.0 / (number of unique ngrams
- // in the input). Otherwise, weighs each unique ngram by (ngram count) /
- // (total number of ngrams).
- bool use_equal_ngram_weight_;
-
- // The integer id of each char ngram is computed as follows:
- // Hash32WithDefaultSeed(char_ngram) % ngram_id_dimension_.
- int ngram_id_dimension_;
-
- // Only ngrams of size ngram_size_ will be extracted.
- int ngram_size_;
-};
-
-// Class for detecting the script of a piece of text. The list of supported
-// scripts is chrome_lang_id::CLD2::ULScript. This class uses the script
-// recognition code ported from CLD2. ULScript_Hani is split into non-Korean
-// script and Korean script (Hangul). In the former case, the function emits
-// ULScript_Hani. In the latter case, the function emits NUM_ULSCRIPTS. The
-// class assumes that the input is (1) interchange valid UTF8, and (2) contains
-// only one chrome_lang_id::CLD2::ULScript.
-class ScriptFeature : public WholeSentenceFeature {
- public:
- void Init(TaskContext *context) override {
- // The dimension is incremented by 1 because ULScript_Hani is split into two
- // as mentioned in the class description.
- set_feature_type(new NumericFeatureType(
- name(), chrome_lang_id::CLD2::NUM_ULSCRIPTS + 1));
- }
-
- // Computes the feature and saves it in the feature vector.
- FeatureValue Compute(const WorkspaceSet &workspaces, const Sentence &sentence,
- const FeatureVector *result) const override;
-};
-
-} // namespace chrome_lang_id
-
-#endif // LANGUAGE_IDENTIFIER_FEATURES_H_
diff --git a/chromium/third_party/cld_3/src/src/language_identifier_features_test.cc b/chromium/third_party/cld_3/src/src/language_identifier_features_test.cc
deleted file mode 100644
index 5835c8615de..00000000000
--- a/chromium/third_party/cld_3/src/src/language_identifier_features_test.cc
+++ /dev/null
@@ -1,260 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include <cmath>
-#include <iostream>
-#include <vector>
-
-#include "base.h"
-#include "feature_extractor.h"
-#include "language_identifier_features.h"
-#include "nnet_language_identifier.h"
-#include "script_span/generated_ulscript.h"
-#include "cld_3/protos/sentence.pb.h"
-#include "task_context.h"
-#include "utils.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-namespace language_identifier_features_test {
-
-static WholeSentenceFeature *cbog_factory() {
- return new ContinuousBagOfNgramsFunction;
-}
-
-static WholeSentenceFeature *sf_factory() { return new ScriptFeature; }
-
-// Class for calculating the feature weights and ids.
-class FeatureIdWeightCalculator {
- public:
- explicit FeatureIdWeightCalculator(TaskContext *context) {
- if (WholeSentenceFeature::registry() == nullptr) {
- // Create registry for our WholeSentenceFeature(s).
- RegisterableClass<WholeSentenceFeature>::CreateRegistry(
- "sentence feature function", "WholeSentenceFeature", __FILE__,
- __LINE__);
- }
-
- // Register our WholeSentenceFeature(s).
- // Register ContinuousBagOfNgramsFunction feature function.
- static WholeSentenceFeature::Registry::Registrar cbog_registrar(
- WholeSentenceFeature::registry(), "continuous-bag-of-ngrams",
- "ContinuousBagOfNgramsFunction", __FILE__, __LINE__, cbog_factory);
-
- // Register Script feature function.
- static WholeSentenceFeature::Registry::Registrar sf_registrar(
- WholeSentenceFeature::registry(), "script", "ScriptFeature", __FILE__,
- __LINE__, sf_factory);
-
- feature_extractor_.Setup(context);
- feature_extractor_.Init(context);
- }
-
- // Assumes that a single feature is specified and extracts it.
- void ExtractOnlyFeature(Sentence *sentence,
- std::vector<FeatureVector> *features) {
- CLD3_CHECK(features->size() == 1);
- WorkspaceSet workspace;
- workspace.Reset(workspace_registry_);
- feature_extractor_.Preprocess(&workspace, sentence);
- feature_extractor_.ExtractFeatures(workspace, *sentence, features);
- CLD3_CHECK(features->size() == 1);
- }
-
- // Returns a map from feature value id to feature value weight.
- std::unordered_map<int, float> GetFloatFeatureValIdsAndWeights(
- Sentence *sentence) {
- std::vector<FeatureVector> feature_vectors(1); // one feature space
- ExtractOnlyFeature(sentence, &feature_vectors);
- const FeatureVector &feature_vector = feature_vectors.at(0);
-
- // Save the (feature value id, feature value weight) pairs to a map.
- std::unordered_map<int, float> feature_id_weight;
- for (int index = 0; index < feature_vector.size(); ++index) {
- const FloatFeatureValue feature_value =
- FloatFeatureValue(feature_vector.value(index));
- feature_id_weight[feature_value.value.id] = feature_value.value.weight;
- }
- return feature_id_weight;
- }
-
- // Returns the feature value ids.
- std::set<int> GetFeatureValueIds(Sentence *sentence) {
- std::vector<FeatureVector> feature_vectors(1); // one feature space
- ExtractOnlyFeature(sentence, &feature_vectors);
- const FeatureVector &feature_vector = feature_vectors.at(0);
-
- std::set<int> ids;
- for (int index = 0; index < feature_vector.size(); ++index) {
- ids.insert(feature_vector.value(index));
- }
- return ids;
- }
-
- private:
- // The registry of shared workspaces in the feature extractor.
- WorkspaceRegistry workspace_registry_;
- LanguageIdEmbeddingFeatureExtractor feature_extractor_;
-};
-
-// Extracts features and checks that their ids and weights are correct.
-bool ExtractAndCheckFeatures(const string &features, const int id_dim,
- const std::vector<string> &expected_char_ngrams,
- const std::vector<float> &expected_weights,
- Sentence *sentence) {
- TaskContext context;
- context.SetParameter("language_identifier_features", features);
- FeatureIdWeightCalculator calc(&context);
-
- // Get the feature ids and the corresponding weights.
- const std::unordered_map<int, float> feature_id_weight =
- calc.GetFloatFeatureValIdsAndWeights(sentence);
- if (feature_id_weight.size() != expected_char_ngrams.size()) {
- std::cout << " Failure" << std::endl;
- std::cout << " Number of expected feature ids: "
- << expected_char_ngrams.size() << std::endl;
- std::cout << " Number of extracted feature ids: "
- << feature_id_weight.size() << std::endl;
- return false;
- }
-
- // Specifies how close two float values should be to be considered equal.
- const float epsilon = 0.0001f;
- bool test_successful = true;
- for (size_t i = 0; i < expected_char_ngrams.size(); ++i) {
- const int expected_id =
- utils::Hash32WithDefaultSeed(expected_char_ngrams.at(i)) % id_dim;
-
- // Check the ids and the weights.
- if (feature_id_weight.count(expected_id) == 0) {
- std::cout << " Failure" << std::endl;
- std::cout << " Feature id " << expected_id << " is missing" << std::endl;
- test_successful = false;
- } else {
- if (std::abs(feature_id_weight.at(expected_id) - expected_weights.at(i)) >
- epsilon) {
- std::cout << " Failure" << std::endl;
- std::cout << " Different weight for feature id " << expected_id
- << ": expected weight " << expected_weights.at(i)
- << ", actual weight " << feature_id_weight.at(expected_id)
- << std::endl;
- test_successful = false;
- }
- }
- }
-
- if (test_successful) {
- std::cout << " Success!" << std::endl;
- }
- return test_successful;
-}
-
-// Tests the case when ngram features get equal weight. Returns "true" if the
-// test is successful and "false" otherwise.
-bool TestExtractFeaturesWithEqualWeight() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- // The integer id of each char ngram is computed as follows:
- // utils::Hash32WithDefaultSeed(char ngram) % id_dim.
- const int id_dim = 100;
- const string features = "continuous-bag-of-ngrams(id_dim=" +
- std::to_string(id_dim) +
- ",size=2,include_terminators=true,include_" +
- "spaces=false,use_equal_weight=true)";
- Sentence sentence;
- sentence.set_text("aa aab");
- const std::vector<string> expected_char_ngrams{"ab", "b$", "^a", "aa", "a$"};
- const std::vector<float> expected_weights = {0.2f, 0.2f, 0.2f, 0.2f, 0.2f};
- return ExtractAndCheckFeatures(features, id_dim, expected_char_ngrams,
- expected_weights, &sentence);
-}
-
-// Tests the case when ngram features get weights equal to their normalized
-// counts. Returns "true" if the test is successful and "false" otherwise.
-bool TestExtractFeaturesWithNonEqualWeight() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- // The integer id of each char ngram is computed as follows:
- // utils::Hash32WithDefaultSeed(char ngram) % id_dim.
- const int id_dim = 100;
- const string features = "continuous-bag-of-ngrams(id_dim=" +
- std::to_string(id_dim) +
- ",size=2,include_terminators=true,include_" +
- "spaces=false,use_equal_weight=false)";
- Sentence sentence;
- sentence.set_text("aa aab");
- const std::vector<string> expected_char_ngrams{"ab", "b$", "^a", "aa", "a$"};
- const std::vector<float> expected_weights{0.1428f, 0.1428f, 0.2857f, 0.2857f,
- 0.1428f};
- return ExtractAndCheckFeatures(features, id_dim, expected_char_ngrams,
- expected_weights, &sentence);
-}
-
-// Tests the feature Script.
-bool TestScriptFeature() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- bool test_successful = true;
- TaskContext context;
- context.SetParameter("language_identifier_features", "script");
- FeatureIdWeightCalculator calc(&context);
-
- // Check the script of the English sentence.
- Sentence sentence;
- sentence.set_text("food");
- std::set<int> feature_val_ids = calc.GetFeatureValueIds(&sentence);
- if (feature_val_ids.size() != 1 ||
- feature_val_ids.count(chrome_lang_id::CLD2::ULScript_Latin) == 0) {
- test_successful = false;
- std::cout << " Failure for input: " << sentence.text() << std::endl;
- }
-
- // Check the script of a Chinese sentence.
- sentence.set_text("字");
- feature_val_ids = calc.GetFeatureValueIds(&sentence);
- if (feature_val_ids.size() != 1 ||
- feature_val_ids.count(chrome_lang_id::CLD2::ULScript_Hani) == 0) {
- test_successful = false;
- std::cout << " Failure for input: " << sentence.text() << std::endl;
- }
-
- // Check the script of a Korean sentence.
- sentence.set_text("워드");
- feature_val_ids = calc.GetFeatureValueIds(&sentence);
- if (feature_val_ids.size() != 1 ||
- feature_val_ids.count(chrome_lang_id::CLD2::NUM_ULSCRIPTS) == 0) {
- test_successful = false;
- std::cout << " Failure for input: " << sentence.text() << std::endl;
- }
-
- if (test_successful) {
- std::cout << " Success!" << std::endl;
- }
- return test_successful;
-}
-
-} // namespace language_identifier_features_test
-} // namespace chrome_lang_id
-
-// Runs the feature extraction tests.
-int main(int argc, char **argv) {
- const bool tests_successful =
- chrome_lang_id::language_identifier_features_test::
- TestExtractFeaturesWithEqualWeight() &&
- chrome_lang_id::language_identifier_features_test::
- TestExtractFeaturesWithNonEqualWeight() &&
- chrome_lang_id::language_identifier_features_test::TestScriptFeature();
- return tests_successful ? 0 : 1;
-}
diff --git a/chromium/third_party/cld_3/src/src/language_identifier_main.cc b/chromium/third_party/cld_3/src/src/language_identifier_main.cc
deleted file mode 100644
index b44f785bf23..00000000000
--- a/chromium/third_party/cld_3/src/src/language_identifier_main.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include <iostream>
-#include <string>
-
-#include "base.h"
-#include "nnet_language_identifier.h"
-
-using chrome_lang_id::NNetLanguageIdentifier;
-
-// Runs a neural net model for language identification.
-int main(int argc, char **argv) {
- NNetLanguageIdentifier lang_id(/*min_num_bytes=*/0,
- /*max_num_bytes=*/1000);
-
- const std::vector<std::string> texts{"This text is written in English.",
- "Text in deutscher Sprache verfasst."};
- for (const std::string &text : texts) {
- const NNetLanguageIdentifier::Result result = lang_id.FindLanguage(text);
- std::cout << "text: " << text << std::endl
- << " language: " << result.language << std::endl
- << " probability: " << result.probability << std::endl
- << " reliable: " << result.is_reliable << std::endl
- << " proportion: " << result.proportion << std::endl
- << std::endl;
- }
-
- const std::string &text =
- "This piece of text is in English. Този текст е на Български.";
- std::cout << "text: " << text << std::endl;
- const std::vector<NNetLanguageIdentifier::Result> results =
- lang_id.FindTopNMostFreqLangs(text, /*num_langs*/ 3);
- for (const NNetLanguageIdentifier::Result &result : results) {
- std::cout << " language: " << result.language << std::endl
- << " probability: " << result.probability << std::endl
- << " reliable: " << result.is_reliable << std::endl
- << " proportion: " << result.proportion << std::endl
- << std::endl;
- }
- return 0;
-}
diff --git a/chromium/third_party/cld_3/src/src/nnet_lang_id_test.cc b/chromium/third_party/cld_3/src/src/nnet_lang_id_test.cc
deleted file mode 100644
index 358fe1b8ff5..00000000000
--- a/chromium/third_party/cld_3/src/src/nnet_lang_id_test.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include <cmath>
-#include <iostream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base.h"
-#include "nnet_lang_id_test_data.h"
-#include "nnet_language_identifier.h"
-
-namespace chrome_lang_id {
-namespace nnet_lang_id_test {
-
-// Tests the model on all supported languages. Returns "true" if the test is
-// successful and "false" otherwise.
-// TODO(abakalov): Add a test for random input that should be labeled as
-// "unknown" due to low confidence.
-bool TestPredictions() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- // (gold language, sample text) pairs used for testing.
- const std::vector<std::pair<std::string, std::string>> gold_lang_text = {
- {"af", NNetLangIdTestData::kTestStrAF},
- {"ar", NNetLangIdTestData::kTestStrAR},
- {"az", NNetLangIdTestData::kTestStrAZ},
- {"be", NNetLangIdTestData::kTestStrBE},
- {"bg", NNetLangIdTestData::kTestStrBG},
- {"bn", NNetLangIdTestData::kTestStrBN},
- {"bs", NNetLangIdTestData::kTestStrBS},
- {"ca", NNetLangIdTestData::kTestStrCA},
- {"ceb", NNetLangIdTestData::kTestStrCEB},
- {"cs", NNetLangIdTestData::kTestStrCS},
- {"cy", NNetLangIdTestData::kTestStrCY},
- {"da", NNetLangIdTestData::kTestStrDA},
- {"de", NNetLangIdTestData::kTestStrDE},
- {"el", NNetLangIdTestData::kTestStrEL},
- {"en", NNetLangIdTestData::kTestStrEN},
- {"eo", NNetLangIdTestData::kTestStrEO},
- {"es", NNetLangIdTestData::kTestStrES},
- {"et", NNetLangIdTestData::kTestStrET},
- {"eu", NNetLangIdTestData::kTestStrEU},
- {"fa", NNetLangIdTestData::kTestStrFA},
- {"fi", NNetLangIdTestData::kTestStrFI},
- {"fil", NNetLangIdTestData::kTestStrFIL},
- {"fr", NNetLangIdTestData::kTestStrFR},
- {"ga", NNetLangIdTestData::kTestStrGA},
- {"gl", NNetLangIdTestData::kTestStrGL},
- {"gu", NNetLangIdTestData::kTestStrGU},
- {"ha", NNetLangIdTestData::kTestStrHA},
- {"hi", NNetLangIdTestData::kTestStrHI},
- {"hmn", NNetLangIdTestData::kTestStrHMN},
- {"hr", NNetLangIdTestData::kTestStrHR},
- {"ht", NNetLangIdTestData::kTestStrHT},
- {"hu", NNetLangIdTestData::kTestStrHU},
- {"hy", NNetLangIdTestData::kTestStrHY},
- {"id", NNetLangIdTestData::kTestStrID},
- {"ig", NNetLangIdTestData::kTestStrIG},
- {"is", NNetLangIdTestData::kTestStrIS},
- {"it", NNetLangIdTestData::kTestStrIT},
- {"iw", NNetLangIdTestData::kTestStrIW},
- {"ja", NNetLangIdTestData::kTestStrJA},
- {"jv", NNetLangIdTestData::kTestStrJV},
- {"ka", NNetLangIdTestData::kTestStrKA},
- {"kk", NNetLangIdTestData::kTestStrKK},
- {"km", NNetLangIdTestData::kTestStrKM},
- {"kn", NNetLangIdTestData::kTestStrKN},
- {"ko", NNetLangIdTestData::kTestStrKO},
- {"la", NNetLangIdTestData::kTestStrLA},
- {"lo", NNetLangIdTestData::kTestStrLO},
- {"lt", NNetLangIdTestData::kTestStrLT},
- {"lv", NNetLangIdTestData::kTestStrLV},
- {"mg", NNetLangIdTestData::kTestStrMG},
- {"mi", NNetLangIdTestData::kTestStrMI},
- {"mk", NNetLangIdTestData::kTestStrMK},
- {"ml", NNetLangIdTestData::kTestStrML},
- {"mn", NNetLangIdTestData::kTestStrMN},
- {"mr", NNetLangIdTestData::kTestStrMR},
- {"ms", NNetLangIdTestData::kTestStrMS},
- {"mt", NNetLangIdTestData::kTestStrMT},
- {"my", NNetLangIdTestData::kTestStrMY},
- {"ne", NNetLangIdTestData::kTestStrNE},
- {"nl", NNetLangIdTestData::kTestStrNL},
- {"no", NNetLangIdTestData::kTestStrNO},
- {"ny", NNetLangIdTestData::kTestStrNY},
- {"pa", NNetLangIdTestData::kTestStrPA},
- {"pl", NNetLangIdTestData::kTestStrPL},
- {"pt", NNetLangIdTestData::kTestStrPT},
- {"ro", NNetLangIdTestData::kTestStrRO},
- {"ru", NNetLangIdTestData::kTestStrRU},
- {"si", NNetLangIdTestData::kTestStrSI},
- {"sk", NNetLangIdTestData::kTestStrSK},
- {"sl", NNetLangIdTestData::kTestStrSL},
- {"so", NNetLangIdTestData::kTestStrSO},
- {"sq", NNetLangIdTestData::kTestStrSQ},
- {"sr", NNetLangIdTestData::kTestStrSR},
- {"st", NNetLangIdTestData::kTestStrST},
- {"su", NNetLangIdTestData::kTestStrSU},
- {"sv", NNetLangIdTestData::kTestStrSV},
- {"sw", NNetLangIdTestData::kTestStrSW},
- {"ta", NNetLangIdTestData::kTestStrTA},
- {"te", NNetLangIdTestData::kTestStrTE},
- {"tg", NNetLangIdTestData::kTestStrTG},
- {"th", NNetLangIdTestData::kTestStrTH},
- {"tr", NNetLangIdTestData::kTestStrTR},
- {"uk", NNetLangIdTestData::kTestStrUK},
- {"ur", NNetLangIdTestData::kTestStrUR},
- {"uz", NNetLangIdTestData::kTestStrUZ},
- {"vi", NNetLangIdTestData::kTestStrVI},
- {"yi", NNetLangIdTestData::kTestStrYI},
- {"yo", NNetLangIdTestData::kTestStrYO},
- {"zh", NNetLangIdTestData::kTestStrZH},
- {"zu", NNetLangIdTestData::kTestStrZU}};
-
- NNetLanguageIdentifier lang_id(/*min_num_bytes=*/0,
- /*max_num_bytes=*/1000);
-
- // Iterate over all the test instances, make predictions and check that they
- // are correct.
- int num_wrong = 0;
- for (const auto &test_instance : gold_lang_text) {
- const std::string &expected_lang = test_instance.first;
- const std::string &text = test_instance.second;
-
- const NNetLanguageIdentifier::Result result = lang_id.FindLanguage(text);
- if (result.language != expected_lang) {
- ++num_wrong;
- std::cout << " Misclassification: " << std::endl;
- std::cout << " Text: " << text << std::endl;
- std::cout << " Expected language: " << expected_lang << std::endl;
- std::cout << " Predicted language: " << result.language << std::endl;
- }
- }
-
- if (num_wrong == 0) {
- std::cout << " Success!" << std::endl;
- return true;
- } else {
- std::cout << " Failure: " << num_wrong << " wrong predictions"
- << std::endl;
- return false;
- }
-}
-
-// Tests the model on input containing multiple languages of different scripts.
-// Returns "true" if the test is successful and "false" otherwise.
-bool TestMultipleLanguagesInInput() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- // Text containing snippets in English and Bulgarian.
- const std::string text =
- "This piece of text is in English. Този текст е на Български.";
-
- // Expected language spans in the input text, corresponding respectively to
- // Bulgarian and English.
- const std::string expected_bg_span = " Този текст е на Български ";
- const std::string expected_en_span = " This piece of text is in English ";
- const float expected_byte_sum =
- static_cast<float>(expected_bg_span.size() + expected_en_span.size());
-
- // Number of languages to query for and the expected byte proportions.
- const int num_queried_langs = 3;
- const std::unordered_map<string, float> expected_lang_proportions{
- {"bg", expected_bg_span.size() / expected_byte_sum},
- {"en", expected_en_span.size() / expected_byte_sum},
- {NNetLanguageIdentifier::kUnknown, 0.0}};
-
- NNetLanguageIdentifier lang_id(/*min_num_bytes=*/0,
- /*max_num_bytes=*/1000);
- const std::vector<NNetLanguageIdentifier::Result> results =
- lang_id.FindTopNMostFreqLangs(text, num_queried_langs);
-
- if (results.size() != expected_lang_proportions.size()) {
- std::cout << " Failure" << std::endl;
- std::cout << " Wrong number of languages: expected "
- << expected_lang_proportions.size() << ", obtained "
- << results.size() << std::endl;
- return false;
- }
-
- // Iterate over the results and check that the correct proportions are
- // returned for the expected languages.
- const float epsilon = 0.00001f;
- for (const NNetLanguageIdentifier::Result &result : results) {
- if (expected_lang_proportions.count(result.language) == 0) {
- std::cout << " Failure" << std::endl;
- std::cout << " Incorrect language: " << result.language << std::endl;
- return false;
- }
- if (std::abs(result.proportion -
- expected_lang_proportions.at(result.language)) > epsilon) {
- std::cout << " Failure" << std::endl;
- std::cout << " Language " << result.language << ": expected proportion "
- << expected_lang_proportions.at(result.language) << ", got "
- << result.proportion << std::endl;
- return false;
- }
- }
- std::cout << " Success!" << std::endl;
- return true;
-}
-
-} // namespace nnet_lang_id_test
-} // namespace chrome_lang_id
-
-// Runs tests for the language identification model.
-int main(int argc, char **argv) {
- const bool tests_successful =
- chrome_lang_id::nnet_lang_id_test::TestPredictions() &&
- chrome_lang_id::nnet_lang_id_test::TestMultipleLanguagesInInput();
- return tests_successful ? 0 : 1;
-}
diff --git a/chromium/third_party/cld_3/src/src/nnet_lang_id_test_data.cc b/chromium/third_party/cld_3/src/src/nnet_lang_id_test_data.cc
deleted file mode 100644
index e221afcd897..00000000000
--- a/chromium/third_party/cld_3/src/src/nnet_lang_id_test_data.cc
+++ /dev/null
@@ -1,529 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "nnet_lang_id_test_data.h"
-
-namespace chrome_lang_id {
-
-const char *const NNetLangIdTestData::kTestStrAF =
- "Dit is 'n kort stukkie van die teks wat gebruik sal word vir die toets "
- "van die akkuraatheid van die nuwe benadering.";
-
-const char *const NNetLangIdTestData::kTestStrAR = "احتيالية بيع أي حساب";
-
-const char *const NNetLangIdTestData::kTestStrAZ =
- " a az qalıb breyn rinq intellektual oyunu üzrə yarışın zona mərhələləri "
- "keçirilib miq un qalıqlarının dənizdən çıxarılması davam edir məhəmməd "
- "peyğəmbərin karikaturalarını çap edən qəzetin baş redaktoru iş otağında "
- "ölüb";
-
-const char *const NNetLangIdTestData::kTestStrBE =
- " а друкаваць іх не было тэхнічна магчыма бліжэй за вільню тым самым часам "
- "нямецкае кіраўніцтва прапаноўвала апроч ўвядзення лацінкі яе";
-
-const char *const NNetLangIdTestData::kTestStrBG =
- " а дума попада в състояние на изпитание ключовите думи с предсказана "
- "малко под то изискване на страниците за търсене в";
-
-const char *const NNetLangIdTestData::kTestStrBN =
- "গ্যালারির ৩৮ বছর পূর্তিতে মূল্যছাড় অর্থনীতি বিএনপির ওয়াক আউট তপন"
- " চৌধুরী হারবাল অ্যাসোসিয়েশনের সভাপতি আন্তর্জাতিক পরামর্শক "
- "বোর্ড দিয়ে শরিয়াহ্ ইনন্ডেক্স করবে "
- "সিএসই মালিকপক্ষের কান্না, শ্রমিকের অনিশ্চয়তা মতিঝিলে সমাবেশ নিষিদ্ধ: "
- "এফবিসিসিআইয়ের ধন্যবাদ বিনোদন বিশেষ প্রতিবেদন বাংলালিংকের গ্র্যান্ডমাস্টার "
- "সিজন-৩ ব্রাজিলে বিশ্বকাপ ফুটবল আয়োজনবিরোধী বিক্ষোভ দেশের নিরাপত্তার"
- " চেয়ে অনেক বেশি সচেতন । প্রার্থীদের দক্ষতা ও যোগ্যতার"
- " পাশাপাশি তারা জাতীয় ইস্যুগুলোতে প্রাধান্য দিয়েছেন । ” পাঁচটি সিটিতে ২০"
- " লাখ ভোটারদের দিয়ে জাতীয় নির্বাচনে ৮ কোটি ভোটারদের"
- " সঙ্গে তুলনা করা যাবে কি একজন দর্শকের এমন প্রশ্নে জবাবে আব্দুল্লাহ "
- "আল নোমান বলেন , “ এই পাঁচটি সিটি কর্পোরেশন নির্বাচন দেশের পাঁচটি বড়"
- " বিভাগের প্রতিনিধিত্ব করছে । এছাড়া এখানকার ভোটার রা সবাই সচেতন । তারা";
-
-const char *const NNetLangIdTestData::kTestStrBS =
- "Novi predsjednik Mešihata Islamske zajednice u Srbiji (IZuS) i muftija "
- "dr. Mevlud ef. Dudić izjavio je u intervjuu za Anadolu Agency (AA) kako "
- "je uvjeren da će doći do vraćanja jedinstva među muslimanima i unutar "
- "Islamske zajednice na prostoru Sandžaka, te da je njegova ruka pružena za "
- "povratak svih u okrilje Islamske zajednice u Srbiji nakon skoro sedam "
- "godina podjela u tom dijelu Srbije. Dudić je za predsjednika Mešihata IZ "
- "u Srbiji izabran 4. januara, a zvanična inauguracija će biti obavljena u "
- "prvoj polovini februara. Kako se očekuje, prisustvovat će joj i "
- "reisu-l-ulema Islamske zajednice u Srbiji Husein ef. Kavazović koji će i "
- "zvanično promovirati Dudića u novog prvog čovjeka IZ u Srbiji. Dudić će "
- "danas boraviti u prvoj zvaničnoj posjeti reisu Kavazoviću, što je njegov "
- "privi simbolični potez nakon imenovanja. ";
-
-const char *const NNetLangIdTestData::kTestStrCA =
- "al final en un únic lloc nhorabona l correu electrònic està concebut com "
- "a eina de productivitat aleshores per què perdre el temps arxivant "
- "missatges per després intentar recordar on els veu desar i per què heu d "
- "eliminar missatges importants per l";
-
-const char *const NNetLangIdTestData::kTestStrCEB =
- "Ang Sugbo usa sa mga labing ugmad nga lalawigan sa nasod. Kini ang sentro "
- "sa komersyo, edukasyon ug industriya sa sentral ug habagatang dapit sa "
- "kapupod-an. Ang mipadayag sa Sugbo isip ikapito nga labing nindot nga "
- "pulo sa , ang nag-inusarang pulo sa Pilipinas nga napasidunggan sa maong "
- "magasin sukad pa sa tuig";
-
-const char *const NNetLangIdTestData::kTestStrCS =
- " a akci opakujte film uložen vykreslit gmail tokio smazat obsah adresáře "
- "nelze načíst systémový profil jednotky smoot okud používáte pro určení "
- "polokoule značky z západ nebo v východ používejte nezáporné hodnoty "
- "zeměpisné délky nelze";
-
-const char *const NNetLangIdTestData::kTestStrCY =
- " a chofrestru eich cyfrif ymwelwch a unwaith i chi greu eich cyfrif mi "
- "fydd yn cael ei hysbysu o ch cyfeiriad ebost newydd fel eich bod yn gallu "
- "cadw mewn cysylltiad drwy gmail os nad ydych chi wedi clywed yn barod am "
- "gmail mae n gwasanaeth gwebost";
-
-const char *const NNetLangIdTestData::kTestStrDA =
- " a z tallene og punktummer der er tilladte log ud angiv den ønskede "
- "adgangskode igen november gem personlige oplysninger kontrolspørgsmål det "
- "sidste tegn i dit brugernavn skal være et bogstav a z eller tal skriv de "
- "tegn du kan se i billedet nedenfor";
-
-const char *const NNetLangIdTestData::kTestStrDE =
- " abschnitt ordner aktivieren werden die ordnereinstellungen im "
- "farbabschnitt deaktiviert öchten sie wirklich fortfahren eldtypen angeben "
- "optional n diesem schritt geben sie für jedesfeld aus dem datenset den "
- "typ an ieser schritt ist optional eldtypen";
-
-const char *const NNetLangIdTestData::kTestStrEL =
- " ή αρνητική αναζήτηση λέξης κλειδιού καταστήστε τις μεμονωμένες λέξεις "
- "κλειδιά περισσότερο στοχοθετημένες με τη μετατροπή τους σε";
-
-const char *const NNetLangIdTestData::kTestStrEN =
- " a backup credit card by visiting your billing preferences page or visit "
- "the adwords help centre for more details https adwords google com support "
- "bin answer py answer hl en we were unable to process the payment of for "
- "your outstanding google adwords";
-
-const char *const NNetLangIdTestData::kTestStrEO =
- " a jarcento refoje per enmetado de koncerna pastro tiam de reformita "
- "konfesio ekde refoje ekzistis luteranaj komunumanoj tamen tiuj fondis "
- "propran komunumon nur en ambaŭ apartenis ekde al la evangela eklezio en "
- "prusio resp ties rejnlanda provinceklezio en";
-
-const char *const NNetLangIdTestData::kTestStrES =
- " a continuación haz clic en el botón obtener ruta también puedes "
- "desplazarte hasta el final de la página para cambiar tus opciones de "
- "búsqueda gráfico y detalles ésta es una lista de los vídeos que te "
- "recomendamos nuestras recomendaciones se basan";
-
-const char *const NNetLangIdTestData::kTestStrET =
- " a niipea kui sinu maksimaalne igakuine krediidi limiit on meie poolt "
- "heaks kiidetud on sinu kohustuseks see krediidilimiit";
-
-const char *const NNetLangIdTestData::kTestStrEU =
- " a den eraso bat honen kontra hortaz eragiketa bakarrik behar dituen "
- "eraso batek aes apurtuko luke nahiz eta oraingoz eraso bideraezina izan "
- "gaur egungo teknologiaren mugak direla eta oraingoz kezka hauek alde "
- "batera utzi daitezke orain arteko indar";
-
-const char *const NNetLangIdTestData::kTestStrFA =
- " آب خوردن عجله می کردند به جای باز ی کتک کاری می کردند و همه چيز مثل قبل "
- "بود فقط من ماندم و يک دنيا حرف و انتظار تا عاقبت رسيد احضاريه ی ای با";
-
-const char *const NNetLangIdTestData::kTestStrFI =
- " a joilla olet käynyt tämä kerro meille kuka ä olet ei tunnistettavia "
- "käyttötietoja kuten virheraportteja käytetään google desktopin "
- "parantamiseen etsi näyttää mukautettuja uutisia google desktop "
- "keskivaihto leikkaa voit kaksoisnapsauttaa";
-
-const char *const NNetLangIdTestData::kTestStrFIL =
- "Ito ay isang maikling piraso ng teksto na ito ay gagamitin para sa "
- "pagsubok ang kawastuhan ng mga bagong diskarte.";
-
-const char *const NNetLangIdTestData::kTestStrFR =
- " a accès aux collections et aux frontaux qui lui ont été attribués il "
- "peut consulter et modifier ses collections et exporter des configurations "
- "de collection toutefois il ne peut pas créer ni supprimer des collections "
- "enfin il a accès aux fonctions";
-
-const char *const NNetLangIdTestData::kTestStrGA =
- " a bhfuil na focail go léir i do cheist le fáil orthu ní gá ach focail "
- "breise a chur leis na cinn a cuardaíodh cheana chun an cuardach a "
- "bheachtú nó a chúngú má chuirtear focal breise isteach aimseofar fo aicme "
- "ar leith de na torthaí a fuarthas";
-
-const char *const NNetLangIdTestData::kTestStrGL =
- " debe ser como mínimo taranto tendas de venda polo miúdo cociñas "
- "servizos bordado canadá viaxes parques de vehículos de recreo hotel "
- "oriental habitación recibir unha postal no enderezo indicado "
- "anteriormente";
-
-const char *const NNetLangIdTestData::kTestStrGU =
- " આના પરિણામ પ્રમાણસર ફોન્ટ અવતરણ ચિન્હવાળા પાઠને છુપાવો બધા સમૂહો શોધાયા"
- " હાલનો જ સંદેશ વિષયની";
-
-const char *const NNetLangIdTestData::kTestStrHA =
- " a cikin a kan sakamako daga sakwannin a kan sakamako daga sakwannin daga "
- "ranar zuwa a kan sakamako daga guda daga ranar zuwa a kan sakamako daga "
- "shafukan daga ranar zuwa a kan sakamako daga guda a cikin last hour a kan "
- "sakamako daga guda daga kafar";
-
-const char *const NNetLangIdTestData::kTestStrHI =
- " ं ऐडवर्ड्स विज्ञापनों के अनुभव पर आधारित हैं और इनकी मदद से आपको अपने"
- " विज्ञापनों का अधिकतम लाभ";
-
-const char *const NNetLangIdTestData::kTestStrHMN =
- "Qhov no yog ib tug luv luv daim ntawv nyeem uas yuav siv tau rau kev soj "
- "ntsuam qhov tseeb ntawm tus tshiab mus kom ze.";
-
-const char *const NNetLangIdTestData::kTestStrHR =
- "Posljednja dva vladara su Kijaksar (Κυαξαρης; 625-585 prije Krista), "
- "fraortov sin koji će proširiti teritorij Medije i Astijag. Kijaksar je "
- "imao kćer ili unuku koja se zvala Amitis a postala je ženom "
- "Nabukodonosora II. kojoj je ovaj izgradio Viseće vrtove Babilona. "
- "Kijaksar je modernizirao svoju vojsku i uništio Ninivu 612. prije Krista. "
- "Naslijedio ga je njegov sin, posljednji medijski kralj, Astijag, kojega "
- "je detronizirao (srušio sa vlasti) njegov unuk Kir Veliki. Zemljom su "
- "zavladali Perzijanci. Hrvatska je zemlja situacija u Europi. Ona ima "
- "bogatu kulturu i ukusna jela.";
-
-const char *const NNetLangIdTestData::kTestStrHT =
- " ak pitit tout sosyete a chita se pou sa leta dwe pwoteje yo nimewo leta "
- "fèt pou li pwoteje tout paran ak pitit nan peyi a menm jan kit paran yo "
- "marye kit yo pa marye tout manman ki fè pitit leta fèt pou ba yo konkoul "
- "menm jan tou pou timoun piti ak pou";
-
-const char *const NNetLangIdTestData::kTestStrHU =
- " a felhasználóim a google azonosító szöveget ikor látják a felhasználóim "
- "a google azonosító szöveget felhasználók a google azonosító szöveget "
- "fogják látni minden tranzakció után ha a vásárlását regisztrációját "
- "oldalunk";
-
-const char *const NNetLangIdTestData::kTestStrHY =
- " ա յ եվ նա հիացած աչքերով նայում է հինգհարկանի շենքի տարօրինակ փոքրիկ "
- "քառակուսի պատուհաններին դեռ մենք շատ ենք հետամնաց ասում է նա այսպես է";
-
-const char *const NNetLangIdTestData::kTestStrID =
- "berdiri setelah pengurusnya yang berusia 83 tahun, Fayzrahman Satarov, "
- "mendeklarasikan diri sebagai nabi dan rumahnya sebagai negara Islam "
- "Satarov digambarkan sebagai mantan ulama Islam tahun 1970-an. "
- "Pengikutnya didorong membaca manuskripnya dan kebanyakan dilarang "
- "meninggalkan tempat persembunyian bawah tanah di dasar gedung delapan "
- "lantai mereka. Jaksa membuka penyelidikan kasus kriminal pada kelompok "
- "itu dan menyatakan akan membubarkan kelompok kalau tetap melakukan "
- "kegiatan ilegal seperti mencegah anggotanya mencari bantuan medis atau "
- "pendidikan. Sampai sekarang pihak berwajib belum melakukan penangkapan "
- "meskipun polisi mencurigai adanya tindak kekerasan pada anak. Pengadilan "
- "selanjutnya akan memutuskan apakah anak-anak diizinkan tetap tinggal "
- "dengan orang tua mereka. Kazan yang berada sekitar 800 kilometer di timur "
- "Moskow merupakan wilayah Tatarstan yang";
-
-const char *const NNetLangIdTestData::kTestStrIG =
- "Chineke bụ aha ọzọ ndï omenala Igbo kpọro Chukwu. Mgbe ndị bekee bịara, "
- "ha mee ya nke ndi Christian. N'echiche ndi ekpere chi Omenala Ndi Igbo, "
- "Christianity, Judaism, ma Islam, Chineke nwere ọtụtụ utu aha, ma nwee "
- "nanị otu aha. Ụzọ abụọ e si akpọ aha ahụ bụ Jehovah ma Ọ bụ Yahweh. Na "
- "ọtụtụ Akwụkwọ Nsọ, e wepụla aha Chineke ma jiri utu aha bụ Onyenwe Anyị "
- "ma ọ bụ Chineke dochie ya. Ma mgbe e dere akwụkwọ nsọ, aha ahụ bụ Jehova "
- "pụtara n’ime ya, ihe dị ka ugboro pụkụ asaa(7,000).";
-
-const char *const NNetLangIdTestData::kTestStrIS =
- " a afköst leitarorða þinna leitarorð neikvæð leitarorð auglýsingahópa "
- "byggja upp aðallista yfir ný leitarorð fyrir auglýsingahópana og skoða "
- "ítarleg gögn um árangur leitarorða eins og samkeppni auglýsenda og "
- "leitarmagn er krafist notkun";
-
-const char *const NNetLangIdTestData::kTestStrIT =
- " a causa di un intervento di manutenzione del sistema fino alle ore circa "
- "ora legale costa del pacifico del novembre le campagne esistenti "
- "continueranno a essere pubblicate come di consueto anche durante questo "
- "breve periodo di inattività ci scusiamo per";
-
-const char *const NNetLangIdTestData::kTestStrIW =
- " או לערוך את העדפות ההפצה אנא עקוב אחרי השלבים הבאים כנס לחשבון האישי שלך "
- "ב";
-
-const char *const NNetLangIdTestData::kTestStrJA =
- " このペ ジでは アカウントに指定された予算の履歴を一覧にしています "
- "それぞれの項目には 予算額と特定期間のステ タスが表示されます "
- "現在または今後の予算を設定するには";
-
-const char *const NNetLangIdTestData::kTestStrJV =
- "Iki Piece cendhak teks sing bakal digunakake kanggo Testing akurasi "
- "pendekatan anyar.";
-
-const char *const NNetLangIdTestData::kTestStrKA =
- " ა ბირთვიდან მიღებული ელემენტი მენდელეევის პერიოდულ სიტემაში "
- "გადაინაცვლებს ორი უჯრით";
-
-const char *const NNetLangIdTestData::kTestStrKK =
- " а билердің өзіне рұқсат берілмеген егер халық талап етсе ғана хан "
- "келісім берген өздеріңіз білесіздер қр қыл мыс тық кодексінде жазаның";
-
-const char *const NNetLangIdTestData::kTestStrKM =
- "នេះគឺជាបំណែកខ្លីនៃអត្ថបទដែលនឹងត្រូវបានប្រើសម្រាប់ការធ្វើតេស្តភាពត្រឹមត្រូវ"
- "នៃវិធីសាស្រ្តថ្មីនេះ។";
-
-const char *const NNetLangIdTestData::kTestStrKN =
- " ಂಠಯ್ಯನವರು ತುಮಕೂರು ಜಿಲ್ಲೆಯ ಚಿಕ್ಕನಾಯಕನಹಳ್ಳಿ ತಾಲ್ಲೂಕಿನ ತೀರ್ಥಪುರ ವೆಂಬ ಸಾಧಾರಣ"
- " ಹಳ್ಳಿಯ ಶ್ಯಾನುಭೋಗರ";
-
-const char *const NNetLangIdTestData::kTestStrKO =
- " 개별적으로 리포트 액세스 권한을 부여할 수 있습니다 액세스 권한 "
- "부여사용자에게 프로필 리포트에 액세스할 수 있는 권한을 부여하시려면 가용 "
- "프로필 상자에서 프로필 이름을 선택한 다음";
-
-const char *const NNetLangIdTestData::kTestStrLA =
- " a deo qui enim nocendi causa mentiri solet si iam consulendi causa "
- "mentiatur multum profecit sed aliud est quod per se ipsum laudabile "
- "proponitur aliud quod in deterioris comparatione praeponitur aliter enim "
- "gratulamur cum sanus est homo aliter cum melius";
-
-const char *const NNetLangIdTestData::kTestStrLO =
- " ກຫາທົ່ວທັງເວັບ ແລະໃນເວັບໄຮ້ສາຍ ທຳອິດໃຫ້ທຳການຊອກຫາກ່ອນ ຈາກນັ້ນ"
- " ໃຫ້ກົດປຸ່ມເມນູ ໃນໜ້າຜົນໄດ້";
-
-const char *const NNetLangIdTestData::kTestStrLT =
- " a išsijungia mano idėja dėl geriausio laiko po pastarųjų savo santykių "
- "pasimokiau penki dalykai be kurių negaliu gyventi mano miegamajame tu "
- "surasi ideali pora išsilavinimas aukštoji mokykla koledžas universitetas "
- "pagrindinis laipsnis metai";
-
-const char *const NNetLangIdTestData::kTestStrLV =
- " a gadskārtējā izpārdošana slēpošana jāņi atlaide izmaiņas trafikā kas "
- "saistītas ar sezonas izpārdošanu speciālajām atlaidēm u c ir parastas un "
- "atslēgvārdi kas ir populāri noteiktos laika posmos šajā laikā saņems "
- "lielāku klikšķu";
-
-const char *const NNetLangIdTestData::kTestStrMG =
- " amporisihin i ianao mba hijery ny dika teksta ranofotsiny an ity "
- "lahatsoratra ity tsy ilaina ny opérateur efa karohina daholo ny teny "
- "rehetra nosoratanao ampiasao anaovana dokambarotra i google telugu datin "
- "ny takelaka fikarohana sary renitakelak i";
-
-const char *const NNetLangIdTestData::kTestStrMI =
- " haere ki te kainga o o haere ki te kainga o o haere ki te kainga o te "
- "rapunga ahua o haere ki te kainga o ka tangohia he ki to rapunga kaore au "
- "mohio te tikanga whakatiki o te ra he whakaharuru te pai rapunga a te "
- "rapunga ahua a e kainga o nga awhina o te";
-
-const char *const NNetLangIdTestData::kTestStrMK =
- " гласовите коалицијата на вмро дпмне како партија со најмногу освоени "
- "гласови ќе добие евра а на сметката на коализијата за македонија";
-
-const char *const NNetLangIdTestData::kTestStrML =
- " ം അങ്ങനെ ഞങ്ങള് അവരുടെ മുമ്പില് നിന്നു ഔടും ഉടനെ നിങ്ങള് പതിയിരിപ്പില് "
- "നിന്നു എഴുന്നേറ്റു";
-
-const char *const NNetLangIdTestData::kTestStrMN =
- " а боловсронгуй болгох орон нутгийн ажил үйлсийг уялдуулж зохицуулах "
- "дүрэм журам боловсруулах орон нутгийн өмч хөрөнгө санхүүгийн";
-
-const char *const NNetLangIdTestData::kTestStrMR =
- "हैदराबाद उच्चार ऐका (सहाय्य·माहिती)तेलुगू: హైదరాబాదు , उर्दू:"
- " حیدر آباد हे भारतातील आंध्र प्रदेश राज्याच्या राजधानीचे शहर"
- " आहे. हैदराबादची लोकसंख्या ७७ लाख ४० हजार ३३४ आहे. मोत्यांचे शहर"
- " अशी एकेकाळी ओळख असलेल्या या शहराला ऐतिहासिक, सांस्कृतिक आणि "
- "स्थापत्यशास्त्रीय वारसा लाभला आहे. १९९० नंतर शिक्षण आणि माहिती तंत्रज्ञान"
- " त्याचप्रमाणे औषधनिर्मिती आणि जैवतंत्रज्ञान क्षेत्रातील उद्योगधंद्यांची"
- " वाढ शहरात झाली. दक्षिण मध्य भारतातील पर्यटन आणि तेलुगू चित्रपटनिर्मितीचे"
- " हैदराबाद हे केंद्र आहे";
-
-const char *const NNetLangIdTestData::kTestStrMS =
- "pengampunan beramai-ramai supaya mereka pulang ke rumah masing-masing. "
- "Orang-orang besarnya enggan mengiktiraf sultan yang dilantik oleh Belanda "
- "sebagai Yang DiPertuan Selangor. Orang ramai pula tidak mahu menjalankan "
- "perniagaan bijih timah dengan Belanda, selagi raja yang berhak tidak "
- "ditabalkan. Perdagang yang lain dibekukan terus kerana untuk membalas "
- "jasa beliau yang membantu Belanda menentang Riau, Johor dan Selangor. Di "
- "antara tiga orang Sultan juga dipandang oleh rakyat sebagai seorang "
- "sultan yang paling gigih. 1 | 2 SULTAN Sebagai ganti Sultan Ibrahim "
- "ditabalkan Raja Muhammad iaitu Raja Muda. Walaupun baginda bukan anak "
- "isteri pertama bergelar Sultan Muhammad bersemayam di Kuala Selangor "
- "juga. Pentadbiran baginda yang lemah itu menyebabkan Kuala Selangor "
- "menjadi sarang ioleh Cina di Lukut tidak diambil tindakan, sedangkan "
- "baginda sendiri banyak berhutang kepada 1";
-
-const char *const NNetLangIdTestData::kTestStrMT =
- " ata ikteb messaġġ lil indirizzi differenti billi tagħżilhom u tagħfas il "
- "buttuna ikteb żid numri tfittxijja tal kotba mur print home kotba minn "
- "pagni ghal pagna minn ghall ktieb ta aċċessa stieden habib iehor grazzi "
- "it tim tal gruppi google";
-
-const char *const NNetLangIdTestData::kTestStrMY =
- " တက္ကသုိလ္ မ္ဟ ပ္ရန္ လာ္ရပီးေနာက္ န္ဟစ္ အရ္ဝယ္ ဦးသန္ ့သည္ ပန္"
- " းတနော္ အမ္ယုိးသား ေက္ယာင္ း";
-
-const char *const NNetLangIdTestData::kTestStrNE =
- "अरू ठाऊँबाटपनि खुलेको छ यो खाता अर अरू ठाऊँबाटपनि खुलेको छ यो खाता अर ू";
-
-const char *const NNetLangIdTestData::kTestStrNL =
- " a als volgt te werk om een configuratiebestand te maken sitemap gen py "
- "ebruik filters om de s op te geven die moeten worden toegevoegd of "
- "uitgesloten op basis van de opmaaktaal elke sitemap mag alleen de s "
- "bevatten voor een bepaalde opmaaktaal dit";
-
-const char *const NNetLangIdTestData::kTestStrNO =
- " a er obligatorisk tidsforskyvning plassering av katalogsøk "
- "planinformasjon loggfilbane gruppenavn kontoinformasjon passord domene "
- "gruppeinformasjon alle kampanjesporing alternativ bruker grupper "
- "oppgaveplanlegger oppgavehistorikk kontosammendrag antall";
-
-const char *const NNetLangIdTestData::kTestStrNY =
- "Boma ndi gawo la dziko lomwe linapangidwa ndi cholinga chothandiza "
- "ntchito yolamulira. Kuŵalako kulikuunikabe mandita, Edipo nyima "
- "unalephera kugonjetsa kuŵalako.";
-
-const char *const NNetLangIdTestData::kTestStrPA =
- " ਂ ਦਿਨਾਂ ਵਿਚ ਭਾਈ ਸਾਹਿਬ ਦੀ ਬੁੱਚੜ ਗੋਬਿੰਦ ਰਾਮ ਨਾਲ ਅੜਫਸ ਚੱਲ ਰਹੀ ਸੀ ਗੋਬਿੰਦ"
- " ਰਾਮ ਨੇ ਭਾਈ ਸਾਹਿਬ ਦੀਆਂ ਭੈਣਾ";
-
-const char *const NNetLangIdTestData::kTestStrPL =
- " a australii będzie widział inne reklamy niż użytkownik z kanady "
- "kierowanie geograficzne sprawia że reklamy są lepiej dopasowane do "
- "użytkownika twojej strony oznacza to także że możesz nie zobaczyć "
- "wszystkich reklam które są wyświetlane na";
-
-const char *const NNetLangIdTestData::kTestStrPT =
- " a abit prevê que a entrada desses produtos estrangeiros no mercado "
- "têxtil e vestuário do brasil possa reduzir os preços em cerca de a partir "
- "de má notícia para os empresários que terão que lutar para garantir suas "
- "margens de lucro mas boa notícia";
-
-const char *const NNetLangIdTestData::kTestStrRO =
- " a anunţurilor reţineţi nu plătiţi pentru clicuri sau impresii ci numai "
- "atunci când pe site ul dvs survine o acţiune dorită site urile negative "
- "nu pot avea uri de destinaţie daţi instrucţiuni societăţii dvs bancare "
- "sau constructoare să";
-
-const char *const NNetLangIdTestData::kTestStrRU =
- " а неправильный формат идентификатора дн назад";
-
-const char *const NNetLangIdTestData::kTestStrSI =
- " අනුරාධ මිහිඳුකුල නමින් සකුරා ට ලිපියක් තැපෑලෙන් එවා තිබුණා කි "
- "් රස්ටි ෂෙල්ටන් ප ් රනාන්දු ද";
-
-const char *const NNetLangIdTestData::kTestStrSK =
- " a aktivovať reklamnú kampaň ak chcete kampaň pred spustením ešte "
- "prispôsobiť uložte ju ako šablónu a pokračujte v úprave vyberte si jednu "
- "z možností nižšie a kliknite na tlačidlo uložiť kampaň nastavenia kampane "
- "môžete ľubovoľne";
-
-const char *const NNetLangIdTestData::kTestStrSL =
- " adsense stanje prijave za google adsense google adsense račun je bil "
- "začasno zamrznjen pozdravljeni hvala za vaše zanimanje v google adsense "
- "po pregledu vaše prijavnice so naši strokovnjaki ugotovili da spletna "
- "stran ki je trenutno povezana z vašim";
-
-const char *const NNetLangIdTestData::kTestStrSO =
- " a oo maanta bogga koobaad ugu qoran yahey beesha caalamka laakiin si "
- "kata oo beesha caalamku ula guntato soomaaliya waxa aan shaki ku jirin in "
- "aakhirataanka dadka soomaalida oo kaliya ay yihiin ku soomaaliya ka saari "
- "kara dhibka ay ku jirto";
-
-const char *const NNetLangIdTestData::kTestStrSQ =
- " a do të kërkoni nga beogradi që të njohë pavarësinë e kosovës zoti thaçi "
- "prishtina është gati ta njoh pavarësinë e serbisë ndërsa natyrisht se do "
- "të kërkohet një gjë e tillë që edhe beogradi ta njoh shtetin e pavarur "
- "dhe sovran të";
-
-const char *const NNetLangIdTestData::kTestStrSR =
- "балчак балчак на мапи србије уреди демографија у насељу балчак живи "
- "пунолетна становника а просечна старост становништва износи година";
-
-const char *const NNetLangIdTestData::kTestStrST =
- " bang ba nang le thahasello matshwao a sehlooho thuto e thehilweng hodima "
- "diphetho ke tsela ya ho ruta le ho ithuta e totobatsang hantle seo "
- "baithuti ba lokelang ho se fihlella ntlhatheo eo e sebetsang ka yona ke "
- "ya hore titjhere o hlakisa pele seo";
-
-const char *const NNetLangIdTestData::kTestStrSU =
- "Nu ngatur kahirupan warga, keur kapentingan pamarentahan diatur ku RT, RW "
- "jeung Kepala Dusun, sedengkeun urusan adat dipupuhuan ku Kuncen jeung "
- "kepala adat. Sanajan Kampung Kuta teu pati anggang jeung lembur sejenna "
- "nu aya di wewengkon Desa Pasir Angin, tapi boh wangunan imah atawa "
- "tradisi kahirupan masarakatna nenggang ti nu lian.";
-
-const char *const NNetLangIdTestData::kTestStrSV =
- " a bort objekt från google desktop post äldst meny öretag dress etaljer "
- "alternativ för vad är inne yaste google skrivbord plugin program för "
- "nyheter google visa nyheter som är anpassade efter de artiklar som du "
- "läser om du till exempel läser";
-
-const char *const NNetLangIdTestData::kTestStrSW =
- " a ujumbe mpya jumla unda tafuta na angalia vikundi vya kujadiliana na "
- "kushiriki mawazo iliyopangwa kwa tarehe watumiaji wapya futa orodha hizi "
- "lugha hoja vishikanisho vilivyo dhaminiwa ujumbe sanaa na tamasha toka "
- "udhibitisho wa neno kwa haraka fikia";
-
-const char *const NNetLangIdTestData::kTestStrTA =
- " அங்கு ராஜேந்திர சோழனால் கட்டப்பட்ட பிரம்மாண்டமான சிவன் கோவில் ஒன்றும்"
- " உள்ளது தொகு";
-
-const char *const NNetLangIdTestData::kTestStrTE =
- " ఁ దనర జయించిన తత్వ మరసి చూడఁ దాన యగును రాజయోగి యిట్లు తేజరిల్లుచు నుండు "
- "విశ్వదాభిరామ వినర వేమ";
-
-const char *const NNetLangIdTestData::kTestStrTG =
- " адолат ва инсондӯстиро бар фашизм нажодпарастӣ ва адоват тарҷеҳ додааст "
- "чоп кунед ба дигарон фиристед чоп кунед ба дигарон фиристед";
-
-const char *const NNetLangIdTestData::kTestStrTH =
- " กฏในการค้นหา หรือหน้าเนื้อหา หากท่านเลือกลงโฆษณา "
- "ท่านอาจจะปรับต้องเพิ่มงบประมาณรายวันตา";
-
-const char *const NNetLangIdTestData::kTestStrTR =
- " a ayarlarınızı görmeniz ve yönetmeniz içindir eğer kampanyanız için "
- "günlük bütçenizi gözden geçirebileceğiniz yeri arıyorsanız kampanya "
- "yönetimi ne gidin kampanyanızı seçin ve kampanya ayarlarını düzenle yi "
- "tıklayın sunumu";
-
-const char *const NNetLangIdTestData::kTestStrUK =
- " а більший бюджет щоб забезпечити собі максимум прибутків від переходів "
- "відстежуйте свої об яви за датою географічним розташуванням";
-
-const char *const NNetLangIdTestData::kTestStrUR =
- " آپ کو کم سے کم ممکنہ رقم چارج کرتا ہے اس کی مثال کے طور پر فرض کریں اگر "
- "آپ کی زیادہ سے زیادہ قیمت فی کلِک امریکی ڈالر اور کلِک کرنے کی شرح ہو تو";
-
-const char *const NNetLangIdTestData::kTestStrUZ =
- " abadiylashtirildi aqsh ayol prezidentga tayyormi markaziy osiyo afg "
- "onistonga qanday yordam berishi mumkin ukrainada o zbekistonlik "
- "muhojirlar tazyiqdan shikoyat qilmoqda gruziya va ukraina hozircha natoga "
- "qabul qilinmaydi afg oniston o zbekistonni g";
-
-const char *const NNetLangIdTestData::kTestStrVI =
- " adsense cho nội dung nhà cung cấp dịch vụ di động xác minh tín"
- " dụng thay đổi nhãn kg các ô xem chi phí cho từ chối các đơn đặt"
- " hàng dạng cấp dữ liệu ác minh trang web của bạn để xem";
-
-const char *const NNetLangIdTestData::kTestStrYI =
- "אן פאנטאזיע ער איז באקאנט צים מערסטן פאר זיינע באַלאַדעס ער האָט געוווינט "
- "אין ווארשע יעס פאריס ליווערפול און לאנדאן סוף כל סוף איז ער";
-
-const char *const NNetLangIdTestData::kTestStrYO =
- " abinibi han ikawe alantakun le ni opolopo ede abinibi ti a to lesese bi "
- "eniyan to fe lo se fe lati se atunse jowo mo pe awon oju iwe itakunagbaye "
- "miran ti ako ni oniruru ede abinibi le faragba nipa atunse ninu se iwadi "
- "blogs ni ori itakun agbaye ti e ba";
-
-const char *const NNetLangIdTestData::kTestStrZH =
- "产品的简报和公告 提交该申请后无法进行更改 请确认您的选择是正确的 "
- "对于要提交的图书 我确认 我是版权所有者或已得到版权所有者的授权 "
- "要更改您的国家 地区 请在此表的最上端更改您的";
-
-const char *const NNetLangIdTestData::kTestStrZU =
- " ana engu uma inkinga iqhubeka siza ubike kwi isexwayiso ngenxa yephutha "
- "lomlekeleli sikwazi ukubuyisela emuva kuphela imiphumela engaqediwe "
- "ukuthola imiphumela eqediwe zama ukulayisha kabusha leli khasi emizuzwini "
- "engu uma inkinga iqhubeka siza uthumele";
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/nnet_lang_id_test_data.h b/chromium/third_party/cld_3/src/src/nnet_lang_id_test_data.h
deleted file mode 100644
index 7377f1daa89..00000000000
--- a/chromium/third_party/cld_3/src/src/nnet_lang_id_test_data.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef NNET_LANG_ID_TEST_DATA_H_
-#define NNET_LANG_ID_TEST_DATA_H_
-
-namespace chrome_lang_id {
-
-class NNetLangIdTestData {
- public:
- // Pieces of text in different languages.
- static const char *const kTestStrAF;
- static const char *const kTestStrAR;
- static const char *const kTestStrAZ;
- static const char *const kTestStrBE;
- static const char *const kTestStrBG;
- static const char *const kTestStrBN;
- static const char *const kTestStrBS;
- static const char *const kTestStrCA;
- static const char *const kTestStrCEB;
- static const char *const kTestStrCS;
- static const char *const kTestStrCY;
- static const char *const kTestStrDA;
- static const char *const kTestStrDE;
- static const char *const kTestStrEL;
- static const char *const kTestStrEN;
- static const char *const kTestStrEO;
- static const char *const kTestStrES;
- static const char *const kTestStrET;
- static const char *const kTestStrEU;
- static const char *const kTestStrFA;
- static const char *const kTestStrFI;
- static const char *const kTestStrFIL;
- static const char *const kTestStrFR;
- static const char *const kTestStrGA;
- static const char *const kTestStrGL;
- static const char *const kTestStrGU;
- static const char *const kTestStrHA;
- static const char *const kTestStrHI;
- static const char *const kTestStrHMN;
- static const char *const kTestStrHR;
- static const char *const kTestStrHT;
- static const char *const kTestStrHU;
- static const char *const kTestStrHY;
- static const char *const kTestStrID;
- static const char *const kTestStrIG;
- static const char *const kTestStrIS;
- static const char *const kTestStrIT;
- static const char *const kTestStrIW;
- static const char *const kTestStrJA;
- static const char *const kTestStrJV;
- static const char *const kTestStrKA;
- static const char *const kTestStrKK;
- static const char *const kTestStrKM;
- static const char *const kTestStrKN;
- static const char *const kTestStrKO;
- static const char *const kTestStrLA;
- static const char *const kTestStrLO;
- static const char *const kTestStrLT;
- static const char *const kTestStrLV;
- static const char *const kTestStrMG;
- static const char *const kTestStrMI;
- static const char *const kTestStrMK;
- static const char *const kTestStrML;
- static const char *const kTestStrMN;
- static const char *const kTestStrMR;
- static const char *const kTestStrMS;
- static const char *const kTestStrMT;
- static const char *const kTestStrMY;
- static const char *const kTestStrNE;
- static const char *const kTestStrNL;
- static const char *const kTestStrNO;
- static const char *const kTestStrNY;
- static const char *const kTestStrPA;
- static const char *const kTestStrPL;
- static const char *const kTestStrPT;
- static const char *const kTestStrRO;
- static const char *const kTestStrRU;
- static const char *const kTestStrSI;
- static const char *const kTestStrSK;
- static const char *const kTestStrSL;
- static const char *const kTestStrSO;
- static const char *const kTestStrSQ;
- static const char *const kTestStrSR;
- static const char *const kTestStrST;
- static const char *const kTestStrSU;
- static const char *const kTestStrSV;
- static const char *const kTestStrSW;
- static const char *const kTestStrTA;
- static const char *const kTestStrTE;
- static const char *const kTestStrTG;
- static const char *const kTestStrTH;
- static const char *const kTestStrTR;
- static const char *const kTestStrUK;
- static const char *const kTestStrUR;
- static const char *const kTestStrUZ;
- static const char *const kTestStrVI;
- static const char *const kTestStrYI;
- static const char *const kTestStrYO;
- static const char *const kTestStrZH;
- static const char *const kTestStrZU;
-};
-} // namespace chrome_lang_id
-
-#endif // NNET_LANG_ID_TEST_DATA_H_
diff --git a/chromium/third_party/cld_3/src/src/nnet_language_identifier.cc b/chromium/third_party/cld_3/src/src/nnet_language_identifier.cc
deleted file mode 100644
index abc395012be..00000000000
--- a/chromium/third_party/cld_3/src/src/nnet_language_identifier.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "nnet_language_identifier.h"
-
-#include <math.h>
-
-#include <algorithm>
-#include <limits>
-#include <string>
-
-#include "base.h"
-#include "embedding_network.h"
-#include "registry.h"
-#include "relevant_script_feature.h"
-#include "script_span/generated_ulscript.h"
-#include "script_span/getonescriptspan.h"
-#include "script_span/text_processing.h"
-#include "cld_3/protos/sentence.pb.h"
-#include "sentence_features.h"
-#include "task_context.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-namespace {
-
-// Struct for accumulating stats for a language as text subsequences of the same
-// script are processed.
-struct LangChunksStats {
- // Sum of probabilities across subsequences.
- float prob_sum = 0.0;
-
- // Total number of bytes corresponding to the language.
- int byte_sum = 0;
-
- // Number chunks corresponding to the language.
- int num_chunks = 0;
-};
-
-// Compares two pairs based on their values.
-bool OrderBySecondDescending(const std::pair<string, float> &x,
- const std::pair<string, float> &y) {
- if (x.second == y.second) {
- return x.first < y.first;
- } else {
- return x.second > y.second;
- }
-}
-
-// Returns "true" if the languge prediction is reliable based on the
-// probability, and "false" otherwise.
-bool ResultIsReliable(const string &language, float probability) {
- if (language == "hr" || language == "bs") {
- return (probability >= NNetLanguageIdentifier::kReliabilityHrBsThreshold);
- } else {
- return (probability >= NNetLanguageIdentifier::kReliabilityThreshold);
- }
-}
-
-// Finds the number of interchange-valid bytes to process.
-int FindNumValidBytesToProcess(const string &text) {
- // Check if the size of the input text can fit into an int. If not, focus on
- // the first std::numeric_limits<int>::max() bytes.
- const int doc_text_size =
- (text.size() < static_cast<size_t>(std::numeric_limits<int>::max()))
- ? static_cast<int>(text.size())
- : std::numeric_limits<int>::max();
-
- // Truncate the input text if it is too long and find the span containing
- // interchange-valid UTF8.
- const int num_valid_bytes = CLD2::SpanInterchangeValid(
- text.c_str(),
- std::min(NNetLanguageIdentifier::kMaxNumInputBytesToConsider,
- doc_text_size));
-
- return num_valid_bytes;
-}
-} // namespace
-
-const int NNetLanguageIdentifier::kMinNumBytesToConsider = 140;
-const int NNetLanguageIdentifier::kMaxNumBytesToConsider = 700;
-const int NNetLanguageIdentifier::kMaxNumInputBytesToConsider = 10000;
-const int NNetLanguageIdentifier::kNumSnippets = 5;
-const char NNetLanguageIdentifier::kUnknown[] = "und";
-const float NNetLanguageIdentifier::kReliabilityThreshold = 0.7f;
-const float NNetLanguageIdentifier::kReliabilityHrBsThreshold = 0.5f;
-
-const string LanguageIdEmbeddingFeatureExtractor::ArgPrefix() const {
- return "language_identifier";
-}
-
-NNetLanguageIdentifier::NNetLanguageIdentifier()
- : NNetLanguageIdentifier(kMinNumBytesToConsider, kMaxNumBytesToConsider) {}
-
-static WholeSentenceFeature *cbog_factory() {
- return new ContinuousBagOfNgramsFunction;
-}
-
-static WholeSentenceFeature *rsf_factory() { return new RelevantScriptFeature; }
-
-static WholeSentenceFeature *sf_factory() { return new ScriptFeature; }
-
-NNetLanguageIdentifier::NNetLanguageIdentifier(int min_num_bytes,
- int max_num_bytes)
- : num_languages_(TaskContextParams::GetNumLanguages()),
- network_(&nn_params_),
- min_num_bytes_(min_num_bytes),
- max_num_bytes_(max_num_bytes) {
- CLD3_CHECK(max_num_bytes_ > 0);
- CLD3_CHECK(min_num_bytes_ >= 0);
- CLD3_CHECK(min_num_bytes_ < max_num_bytes_);
-
- num_snippets_ = (max_num_bytes_ <= kNumSnippets) ? 1 : kNumSnippets;
- snippet_size_ = max_num_bytes_ / num_snippets_;
-
- if (WholeSentenceFeature::registry() == nullptr) {
- // Create registry for our WholeSentenceFeature(s).
- RegisterableClass<WholeSentenceFeature>::CreateRegistry(
- "sentence feature function", "WholeSentenceFeature", __FILE__,
- __LINE__);
- }
-
- // Register our WholeSentenceFeature(s).
- // Register ContinuousBagOfNgramsFunction feature function.
- static WholeSentenceFeature::Registry::Registrar cbog_registrar(
- WholeSentenceFeature::registry(), "continuous-bag-of-ngrams",
- "ContinuousBagOfNgramsFunction", __FILE__, __LINE__, cbog_factory);
-
- // Register RelevantScriptFeature feature function.
- static WholeSentenceFeature::Registry::Registrar rsf_registrar(
- WholeSentenceFeature::registry(), "continuous-bag-of-relevant-scripts",
- "RelevantScriptFeature", __FILE__, __LINE__, rsf_factory);
-
- // Register ScriptFeature feature function.
- static WholeSentenceFeature::Registry::Registrar sf_registrar(
- WholeSentenceFeature::registry(), "script", "ScriptFeature", __FILE__,
- __LINE__, sf_factory);
-
- // Get the model parameters, set up and initialize the model.
- TaskContext context;
- TaskContextParams::ToTaskContext(&context);
- Setup(&context);
- Init(&context);
-}
-
-NNetLanguageIdentifier::~NNetLanguageIdentifier() {}
-
-void NNetLanguageIdentifier::Setup(TaskContext *context) {
- feature_extractor_.Setup(context);
-}
-
-void NNetLanguageIdentifier::Init(TaskContext *context) {
- feature_extractor_.Init(context);
- feature_extractor_.RequestWorkspaces(&workspace_registry_);
-}
-
-void NNetLanguageIdentifier::GetFeatures(
- Sentence *sentence, std::vector<FeatureVector> *features) const {
- // Feature workspace set.
- WorkspaceSet workspace;
- workspace.Reset(workspace_registry_);
- feature_extractor_.Preprocess(&workspace, sentence);
- feature_extractor_.ExtractFeatures(workspace, *sentence, features);
-}
-
-// Returns the language name corresponding to the given id.
-string NNetLanguageIdentifier::GetLanguageName(int language_id) const {
- CLD3_CHECK(language_id >= 0);
- CLD3_CHECK(language_id < num_languages_);
- return TaskContextParams::language_names(language_id);
-}
-
-NNetLanguageIdentifier::Result NNetLanguageIdentifier::FindLanguage(
- const string &text) {
- const int num_valid_bytes = FindNumValidBytesToProcess(text);
-
- // Iterate over the input with ScriptScanner to clean up the text (e.g.,
- // removing digits, punctuation, brackets).
- // TODO(abakalov): Extract the code that does the clean-up out of
- // ScriptScanner.
- CLD2::ScriptScanner ss(text.c_str(), num_valid_bytes, /*is_plain_text=*/true);
- CLD2::LangSpan script_span;
- string cleaned;
- while (ss.GetOneScriptSpanLower(&script_span)) {
- // script_span has spaces at the beginning and the end, so there is no need
- // for a delimiter.
- cleaned.append(script_span.text, script_span.text_bytes);
- }
-
- if (static_cast<int>(cleaned.size()) < min_num_bytes_) {
- return Result();
- }
-
- // Copy to a vector because a non-const char* will be needed.
- std::vector<char> text_to_process;
- for (size_t i = 0; i < cleaned.size(); ++i) {
- text_to_process.push_back(cleaned[i]);
- }
- text_to_process.push_back('\0');
-
- // Remove repetitive chunks or ones containing mostly spaces.
- const int chunk_size = 0; // Use the default.
- char *text_begin = &text_to_process[0];
- const int new_length = CLD2::CheapSqueezeInplace(
- text_begin, text_to_process.size() - 1, chunk_size);
- if (new_length < min_num_bytes_) {
- return Result();
- }
-
- const string squeezed_text_to_process =
- SelectTextGivenBeginAndSize(text_begin, new_length);
- return FindLanguageOfValidUTF8(squeezed_text_to_process);
-}
-
-NNetLanguageIdentifier::Result NNetLanguageIdentifier::FindLanguageOfValidUTF8(
- const string &text) {
- // Create a Sentence storing the input text.
- Sentence sentence;
- sentence.set_text(text);
-
- // Predict language.
- // TODO(salcianu): reuse vector<FeatureVector>.
- std::vector<FeatureVector> features(feature_extractor_.NumEmbeddings());
- GetFeatures(&sentence, &features);
-
- EmbeddingNetwork::Vector scores;
- network_.ComputeFinalScores(features, &scores);
- int prediction_id = -1;
- float max_val = -std::numeric_limits<float>::infinity();
- for (size_t i = 0; i < scores.size(); ++i) {
- if (scores[i] > max_val) {
- prediction_id = i;
- max_val = scores[i];
- }
- }
-
- // Compute probability.
- Result result;
- float diff_sum = 0.0;
- for (size_t i = 0; i < scores.size(); ++i) {
- diff_sum += exp(scores[i] - max_val);
- }
- const float log_sum_exp = max_val + log(diff_sum);
- result.probability = exp(max_val - log_sum_exp);
-
- result.language = GetLanguageName(prediction_id);
- result.is_reliable = ResultIsReliable(result.language, result.probability);
- result.proportion = 1.0;
- return result;
-}
-
-std::vector<NNetLanguageIdentifier::Result>
-NNetLanguageIdentifier::FindTopNMostFreqLangs(const string &text,
- int num_langs) {
- std::vector<Result> results;
-
- // Truncate the input text if it is too long and find the span containing
- // interchange-valid UTF8.
- const int num_valid_bytes = FindNumValidBytesToProcess(text);
- if (num_valid_bytes == 0) {
- while (num_langs-- > 0) {
- results.emplace_back();
- }
- return results;
- }
-
- // Process each subsequence of the same script.
- CLD2::ScriptScanner ss(text.c_str(), num_valid_bytes, /*is_plain_text=*/true);
- CLD2::LangSpan script_span;
- std::unordered_map<string, LangChunksStats> lang_stats;
- int total_num_bytes = 0;
- Result result;
- string language;
- int chunk_size = 0; // Use the default.
- while (ss.GetOneScriptSpanLower(&script_span)) {
- const int num_original_span_bytes = script_span.text_bytes;
-
- // Remove repetitive chunks or ones containing mostly spaces.
- const int new_length = CLD2::CheapSqueezeInplace(
- script_span.text, script_span.text_bytes, chunk_size);
- script_span.text_bytes = new_length;
-
- if (script_span.text_bytes < min_num_bytes_) {
- continue;
- }
- total_num_bytes += num_original_span_bytes;
-
- const string selected_text = SelectTextGivenScriptSpan(script_span);
- result = FindLanguageOfValidUTF8(selected_text);
- language = result.language;
- lang_stats[language].byte_sum += num_original_span_bytes;
- lang_stats[language].prob_sum +=
- result.probability * num_original_span_bytes;
- lang_stats[language].num_chunks++;
- }
-
- // Sort the languages based on the number of bytes associated with them.
- // TODO(abakalov): Consider alternative possibly more efficient portable
- // approaches for finding the top N languages. Given that on average, there
- // aren't that many languages in the input, it's likely that the benefits will
- // be negligible (if any).
- std::vector<std::pair<string, float>> langs_and_byte_counts;
- for (const auto &entry : lang_stats) {
- langs_and_byte_counts.emplace_back(entry.first, entry.second.byte_sum);
- }
- std::sort(langs_and_byte_counts.begin(), langs_and_byte_counts.end(),
- OrderBySecondDescending);
-
- const float byte_sum = static_cast<float>(total_num_bytes);
- const int num_langs_to_save =
- std::min(num_langs, static_cast<int>(langs_and_byte_counts.size()));
- for (int indx = 0; indx < num_langs_to_save; ++indx) {
- Result result;
- const string &language = langs_and_byte_counts.at(indx).first;
- const LangChunksStats &stats = lang_stats.at(language);
- result.language = language;
- result.probability = stats.prob_sum / stats.byte_sum;
- result.proportion = stats.byte_sum / byte_sum;
- result.is_reliable = ResultIsReliable(language, result.probability);
- results.push_back(result);
- }
-
- int padding_size = num_langs - langs_and_byte_counts.size();
- while (padding_size-- > 0) {
- results.emplace_back();
- }
- return results;
-}
-
-string NNetLanguageIdentifier::SelectTextGivenScriptSpan(
- const CLD2::LangSpan &script_span) {
- return SelectTextGivenBeginAndSize(script_span.text, script_span.text_bytes);
-}
-
-string NNetLanguageIdentifier::SelectTextGivenBeginAndSize(
- const char *text_begin, int text_size) {
- string output_text;
-
- // If the size of the input is greater than the maxium number of bytes needed
- // for a prediction, then concatenate snippets that are equally spread out
- // throughout the input.
- if (text_size > max_num_bytes_) {
- const char *snippet_begin = nullptr;
- const char *snippet_end = text_begin;
-
- // Number of bytes between the snippets.
- const int num_skip_bytes =
- (text_size - max_num_bytes_) / (num_snippets_ + 1);
-
- for (int i = 0; i < num_snippets_; ++i) {
- // Using SpanInterchangeValid to find the offsets to ensure that we are
- // not splitting a character in two.
- const int actual_num_skip_bytes =
- CLD2::SpanInterchangeValid(snippet_end, num_skip_bytes);
- snippet_begin = snippet_end + actual_num_skip_bytes;
- const int actual_snippet_size =
- CLD2::SpanInterchangeValid(snippet_begin, snippet_size_);
- snippet_end = snippet_begin + actual_snippet_size;
- output_text.append(snippet_begin, actual_snippet_size);
- output_text.append(" ");
- }
- } else {
- output_text.append(text_begin, text_size);
- }
- return output_text;
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/nnet_language_identifier.h b/chromium/third_party/cld_3/src/src/nnet_language_identifier.h
deleted file mode 100644
index 820aba6ba85..00000000000
--- a/chromium/third_party/cld_3/src/src/nnet_language_identifier.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef NNET_LANGUAGE_IDENTIFIER_H_
-#define NNET_LANGUAGE_IDENTIFIER_H_
-
-#include <string>
-
-#include "base.h"
-#include "embedding_feature_extractor.h"
-#include "embedding_network.h"
-#include "lang_id_nn_params.h"
-#include "language_identifier_features.h"
-#include "script_span/getonescriptspan.h"
-#include "cld_3/protos/sentence.pb.h"
-#include "sentence_features.h"
-#include "task_context.h"
-#include "task_context_params.h"
-#include "cld_3/protos/task_spec.pb.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-
-// Specialization of the EmbeddingFeatureExtractor for extracting from
-// (Sentence, int).
-class LanguageIdEmbeddingFeatureExtractor
- : public EmbeddingFeatureExtractor<WholeSentenceExtractor, Sentence> {
- public:
- const string ArgPrefix() const override;
-};
-
-// Class for detecting the language of a document.
-class NNetLanguageIdentifier {
- public:
- // Information about a predicted language.
- struct Result {
- string language = kUnknown;
- float probability = 0.0; // Language probability.
- bool is_reliable = false; // Whether the prediction is reliable.
-
- // Proportion of bytes associated with the language. If FindLanguage is
- // called, this variable is set to 1.
- float proportion = 0.0;
- };
-
- NNetLanguageIdentifier();
- NNetLanguageIdentifier(int min_num_bytes, int max_num_bytes);
- ~NNetLanguageIdentifier();
-
- // Finds the most likely language for the given text, along with additional
- // information (e.g., probability). The prediction is based on the first N
- // bytes where N is the minumum between the number of interchange valid UTF8
- // bytes and max_num_bytes_. If N is less than min_num_bytes_ long, then this
- // function returns kUnknown.
- Result FindLanguage(const string &text);
-
- // Splits the input text (up to the first byte, if any, that is not
- // interchange valid UTF8) into spans based on the script, predicts a language
- // for each span, and returns a vector storing the top num_langs most frequent
- // languages along with additional information (e.g., proportions). The number
- // of bytes considered for each span is the minimum between the size of the
- // span and max_num_bytes_. If more languages are requested than what is
- // available in the input, then for those cases kUnknown is returned. Also, if
- // the size of the span is less than min_num_bytes_ long, then the span is
- // skipped. If the input text is too long, only the first
- // kMaxNumInputBytesToConsider bytes are processed.
- std::vector<Result> FindTopNMostFreqLangs(const string &text, int num_langs);
-
- // String returned when a language is unknown or prediction cannot be made.
- static const char kUnknown[];
-
- // Min number of bytes needed to make a prediction if the default constructor
- // is called.
- static const int kMinNumBytesToConsider;
-
- // Max number of bytes to consider to make a prediction if the default
- // constructor is called.
- static const int kMaxNumBytesToConsider;
-
- // Max number of input bytes to process.
- static const int kMaxNumInputBytesToConsider;
-
- // Predictions with probability greater than or equal to this threshold are
- // marked as reliable. This threshold was optimized on a set of text segments
- // extracted from wikipedia, and results in an overall precision, recall,
- // and f1 equal to 0.9760, 0.9624, and 0.9692, respectively.
- static const float kReliabilityThreshold;
-
- // Reliability threshold for the languages hr and bs.
- static const float kReliabilityHrBsThreshold;
-
- private:
- // Sets up and initializes the model.
- void Setup(TaskContext *context);
- void Init(TaskContext *context);
-
- // Extract features from sentence. On return, FeatureVector features[i]
- // contains the features for the embedding space #i.
- void GetFeatures(Sentence *sentence,
- std::vector<FeatureVector> *features) const;
-
- // Finds the most likely language for the given text. Assumes that the text is
- // interchange valid UTF8.
- Result FindLanguageOfValidUTF8(const string &text);
-
- // Returns the language name corresponding to the given id.
- string GetLanguageName(int language_id) const;
-
- // Concatenates snippets of text equally spread out throughout the input if
- // the size of the input is greater than the maximum number of bytes needed to
- // make a prediction. The resulting string is used for language
- // identification.
- string SelectTextGivenScriptSpan(const CLD2::LangSpan &script_span);
- string SelectTextGivenBeginAndSize(const char *text_begin, int text_size);
-
- // Number of languages.
- const int num_languages_;
-
- // Typed feature extractor for embeddings.
- LanguageIdEmbeddingFeatureExtractor feature_extractor_;
-
- // The registry of shared workspaces in the feature extractor.
- WorkspaceRegistry workspace_registry_;
-
- // Parameters for the neural networks.
- LangIdNNParams nn_params_;
-
- // Neural network to use for scoring.
- EmbeddingNetwork network_;
-
- // This feature function is not relevant to this class. Adding this variable
- // ensures that the features are linked.
- ContinuousBagOfNgramsFunction ngram_function_;
-
- // Minimum number of bytes needed to make a prediction. If the default
- // constructor is called, this variable is equal to kMinNumBytesToConsider.
- int min_num_bytes_;
-
- // Maximum number of bytes to use to make a prediction. If the default
- // constructor is called, this variable is equal to kMaxNumBytesToConsider.
- int max_num_bytes_;
-
- // Number of snippets to concatenate to produce the string used for language
- // identification. If max_num_bytes_ <= kNumSnippets (i.e., the maximum number
- // of bytes needed to make a prediction is smaller or equal to the number of
- // default snippets), then this variable is equal to 1. Otherwise, it is set
- // to kNumSnippets.
- int num_snippets_;
-
- // The string used to make a prediction is created by concatenating
- // num_snippets_ snippets of size snippet_size_ = (max_num_bytes_ /
- // num_snippets_) that are equaly spread out throughout the input.
- int snippet_size_;
-
- // Default number of snippets to concatenate to produce the string used for
- // language identification. For the actual number of snippets, see
- // num_snippets_.
- static const int kNumSnippets;
-};
-
-} // namespace chrome_lang_id
-
-#endif // NNET_LANGUAGE_IDENTIFIER_H_
diff --git a/chromium/third_party/cld_3/src/src/registry.cc b/chromium/third_party/cld_3/src/src/registry.cc
deleted file mode 100644
index a4567a22a7d..00000000000
--- a/chromium/third_party/cld_3/src/src/registry.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "registry.h"
-
-namespace chrome_lang_id {
-
-// Global list of all component registries.
-RegistryMetadata *global_registry_list = NULL;
-
-void RegistryMetadata::Register(RegistryMetadata *registry) {
- registry->set_link(global_registry_list);
- global_registry_list = registry;
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/registry.h b/chromium/third_party/cld_3/src/src/registry.h
deleted file mode 100644
index ff0426b1efd..00000000000
--- a/chromium/third_party/cld_3/src/src/registry.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Registry for component registration. These classes can be used for creating
-// registries of components conforming to the same interface. This is useful for
-// making a component-based architecture where the specific implementation
-// classes can be selected at runtime. There is support for both class-based and
-// instance based registries.
-//
-// Example:
-// function.h:
-//
-// class Function : public RegisterableInstance<Function> {
-// public:
-// virtual double Evaluate(double x) = 0;
-// };
-//
-// #define REGISTER_FUNCTION(type, component)
-// REGISTER_INSTANCE_COMPONENT(Function, type, component);
-//
-// function.cc:
-//
-// REGISTER_INSTANCE_REGISTRY("function", Function);
-//
-// class Cos : public Function {
-// public:
-// double Evaluate(double x) { return cos(x); }
-// };
-//
-// class Exp : public Function {
-// public:
-// double Evaluate(double x) { return exp(x); }
-// };
-//
-// REGISTER_FUNCTION("cos", Cos);
-// REGISTER_FUNCTION("exp", Exp);
-//
-// Function *f = Function::Lookup("cos");
-// double result = f->Evaluate(arg);
-
-#ifndef REGISTRY_H_
-#define REGISTRY_H_
-
-#include <string.h>
-
-#include <string>
-
-#include "base.h"
-
-namespace chrome_lang_id {
-
-// Component metadata with information about name, class, and code location.
-class ComponentMetadata {
- public:
- ComponentMetadata(const char *name, const char *class_name, const char *file,
- int line)
- : name_(name),
- class_name_(class_name),
- file_(file),
- line_(line),
- link_(NULL) {}
-
- // Getters.
- const char *name() const { return name_; }
- const char *class_name() const { return class_name_; }
- const char *file() const { return file_; }
- int line() const { return line_; }
-
- // Metadata objects can be linked in a list.
- ComponentMetadata *link() const { return link_; }
- void set_link(ComponentMetadata *link) { link_ = link; }
-
- private:
- // Component name.
- const char *name_;
-
- // Name of class for component.
- const char *class_name_;
-
- // Code file and location where the component was registered.
- const char *file_;
- int line_;
-
- // Link to next metadata object in list.
- ComponentMetadata *link_;
-};
-
-// The master registry contains all registered component registries. A registry
-// is not registered in the master registry until the first component of that
-// type is registered.
-class RegistryMetadata : public ComponentMetadata {
- public:
- RegistryMetadata(const char *name, const char *class_name, const char *file,
- int line)
- : ComponentMetadata(name, class_name, file, line) {}
-
- // Registers a component registry in the master registry.
- static void Register(RegistryMetadata *registry);
-};
-
-// Registry for components. An object can be registered with a type name in the
-// registry. The named instances in the registry can be returned using the
-// Lookup() method. The components in the registry are put into a linked list
-// of components. It is important that the component registry can be statically
-// initialized in order not to depend on initialization order.
-template <class T>
-struct ComponentRegistry {
- typedef ComponentRegistry<T> Self;
-
- // Component registration class.
- class Registrar : public ComponentMetadata {
- public:
- // Registers new component by linking itself into the component list of
- // the registry.
- Registrar(Self *registry, const char *type, const char *class_name,
- const char *file, int line, T *object)
- : ComponentMetadata(type, class_name, file, line), object_(object) {
- // Register registry in master registry if this is the first registered
- // component of this type.
- if (registry->components == NULL) {
- RegistryMetadata::Register(
- new RegistryMetadata(registry->name, registry->class_name,
- registry->file, registry->line));
- }
-
- // Register component in registry.
- set_link(registry->components);
- registry->components = this;
- }
-
- // Returns component type.
- const char *type() const { return name(); }
-
- // Returns component object.
- T *object() const { return object_; }
-
- // Returns the next component in the component list.
- Registrar *next() const { return static_cast<Registrar *>(link()); }
-
- private:
- // Component object.
- T *object_;
- };
-
- // Finds registrar for named component in registry.
- const Registrar *GetComponent(const char *type) const {
- Registrar *r = components;
- while (r != NULL && strcmp(type, r->type()) != 0) r = r->next();
- CLD3_DCHECK(r != nullptr);
-
- return r;
- }
-
- // Finds a named component in the registry.
- T *Lookup(const char *type) const { return GetComponent(type)->object(); }
- T *Lookup(const string &type) const { return Lookup(type.c_str()); }
-
- // Textual description of the kind of components in the registry.
- const char *name;
-
- // Base class name of component type.
- const char *class_name;
-
- // File and line where the registry is defined.
- const char *file;
- int line;
-
- // Linked list of registered components.
- Registrar *components;
-};
-
-// Base class for registerable class-based components.
-template <class T>
-class RegisterableClass {
- public:
- // Factory function type.
- typedef T *(Factory)();
-
- // Registry type.
- typedef ComponentRegistry<Factory> Registry;
-
- // Should be called before any call to Create() or registry(), i.e., before
- // using the registration mechanism to register and or instantiate subclasses
- // of T.
- static void CreateRegistry(
- const char *name,
- const char *class_name,
- const char *file,
- int line) {
- registry_ = new Registry();
- registry_->name = name;
- registry_->class_name = class_name;
- registry_->file = file;
- registry_->line = line;
- registry_->components = nullptr;
- }
-
- // Should be called when one is done using the registration mechanism for
- // class T.
- static void DeleteRegistry() {
- delete registry_;
- registry_ = nullptr;
- }
-
- // Creates a new component instance.
- static T *Create(const string &type) { return registry()->Lookup(type)(); }
-
- // Returns registry for class.
- static Registry *registry() { return registry_; }
-
- private:
- // Registry for class.
- static Registry *registry_;
-};
-
-// Base class for registerable instance-based components.
-template <class T>
-class RegisterableInstance {
- public:
- // Registry type.
- typedef ComponentRegistry<T> Registry;
-
- private:
- // Registry for class.
- static Registry registry_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // REGISTRY_H_
diff --git a/chromium/third_party/cld_3/src/src/relevant_script_feature.cc b/chromium/third_party/cld_3/src/src/relevant_script_feature.cc
deleted file mode 100644
index 0cb6d559ce4..00000000000
--- a/chromium/third_party/cld_3/src/src/relevant_script_feature.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "relevant_script_feature.h"
-
-#include <ctype.h>
-
-#include <string>
-
-#include "feature_extractor.h"
-#include "feature_types.h"
-#include "language_identifier_features.h"
-#include "script_detector.h"
-#include "cld_3/protos/sentence.pb.h"
-#include "sentence_features.h"
-#include "task_context.h"
-#include "utils.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-void RelevantScriptFeature::Setup(TaskContext *context) {
- // Nothing.
-}
-
-void RelevantScriptFeature::Init(TaskContext *context) {
- set_feature_type(new NumericFeatureType(name(), kNumRelevantScripts));
-}
-
-void RelevantScriptFeature::Evaluate(const WorkspaceSet &workspaces,
- const Sentence &sentence,
- FeatureVector *result) const {
- const string &text = sentence.text();
-
- // We expect kNumRelevantScripts to be small, so we stack-allocate the array
- // of counts. Still, if that changes, we want to find out.
- static_assert(
- kNumRelevantScripts < 25,
- "switch counts to vector<int>: too big for stack-allocated int[]");
-
- // counts[s] is the number of characters with script s.
- // Note: {} "value-initializes" the array to zero.
- int counts[kNumRelevantScripts]{};
- int total_count = 0;
- const char *const text_end = text.data() + text.size();
- for (const char *curr = text.data(); curr < text_end;
- curr += utils::OneCharLen(curr)) {
- const int num_bytes = utils::OneCharLen(curr);
-
- // If a partial UTF-8 character is encountered, break out of the loop.
- if (curr + num_bytes > text_end) {
- break;
- }
-
- // Skip spaces, numbers, punctuation, and all other non-alpha ASCII
- // characters: these characters are used in so many languages, they do not
- // communicate language-related information.
- if ((num_bytes == 1) && !isalpha(*curr)) {
- continue;
- }
- Script script = GetScript(curr, num_bytes);
- CLD3_DCHECK(script >= 0);
- CLD3_DCHECK(script < kNumRelevantScripts);
- counts[static_cast<int>(script)]++;
- total_count++;
- }
-
- for (int script_id = 0; script_id < kNumRelevantScripts; ++script_id) {
- int count = counts[script_id];
- if (count > 0) {
- const float weight = static_cast<float>(count) / total_count;
- FloatFeatureValue value(script_id, weight);
- result->add(feature_type(), value.discrete_value);
- }
- }
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/relevant_script_feature.h b/chromium/third_party/cld_3/src/src/relevant_script_feature.h
deleted file mode 100644
index ce808105769..00000000000
--- a/chromium/third_party/cld_3/src/src/relevant_script_feature.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef RELEVANT_SCRIPT_FEATURE_H_
-#define RELEVANT_SCRIPT_FEATURE_H_
-
-#include "feature_extractor.h"
-#include "cld_3/protos/sentence.pb.h"
-#include "sentence_features.h"
-#include "task_context.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-
-// Given a sentence, generates one FloatFeatureValue for each "relevant" Unicode
-// script (see below): each such feature indicates the script and the ratio of
-// UTF8 characters in that script, in the given sentence.
-//
-// What is a relevant script? Recognizing all 100+ Unicode scripts would
-// require too much code size and runtime. Instead, we focus only on a few
-// scripts that communicate a lot of language information: e.g., the use of
-// Hiragana characters almost always indicates Japanese, so Hiragana is a
-// "relevant" script for us. The Latin script is used by dozens of language, so
-// Latin is not relevant in this context.
-class RelevantScriptFeature : public WholeSentenceFeature {
- public:
- void Setup(TaskContext *context) override;
- void Init(TaskContext *context) override;
-
- // Appends the features computed from the sentence to the feature vector.
- void Evaluate(const WorkspaceSet &workspaces, const Sentence &sentence,
- FeatureVector *result) const override;
-};
-
-} // namespace chrome_lang_id
-
-#endif // RELEVANT_SCRIPT_FEATURE_H_
diff --git a/chromium/third_party/cld_3/src/src/relevant_script_feature_test.cc b/chromium/third_party/cld_3/src/src/relevant_script_feature_test.cc
deleted file mode 100644
index cfa56df6928..00000000000
--- a/chromium/third_party/cld_3/src/src/relevant_script_feature_test.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include <algorithm>
-#include <cmath>
-#include <iostream>
-#include <memory>
-
-#include "feature_extractor.h"
-#include "feature_types.h"
-#include "relevant_script_feature.h"
-#include "script_detector.h"
-#include "cld_3/protos/sentence.pb.h"
-#include "sentence_features.h"
-#include "task_context.h"
-#include "utils.h"
-#include "workspace.h"
-
-namespace chrome_lang_id {
-namespace relevant_script_feature_test {
-namespace {
-// Checks whether the expected and actual float feature values are within 0.0001
-// of each other.
-bool FeatureValuesNear(float expected_value, float actual_value) {
- return std::abs(expected_value - actual_value) < 0.0001;
-}
-
-// Checks whether two sets of feature values are within an acceptable amount of
-// each other.
-bool FeaturesNear(const string &test_input,
- const std::map<int, float> &expected_features,
- const std::map<int, float> &actual_features) {
- if (expected_features.size() != actual_features.size()) {
- std::cout << " Failure for input: " << test_input << std::endl;
- return false;
- }
-
- for (const auto &id_and_value : expected_features) {
- const int id = id_and_value.first;
- if (actual_features.count(id) == 0 ||
- !FeatureValuesNear(expected_features.at(id), actual_features.at(id))) {
- std::cout << " Failure for input: " << test_input << std::endl;
- return false;
- }
- }
- std::cout << " Success for input: " << test_input << std::endl;
- return true;
-}
-
-// Checks whether the set of features is empty.
-bool CheckFeaturesEmpty(const string &input,
- const std::map<int, float> &actual_features) {
- if (!actual_features.empty()) {
- std::cout << " Failure for input: " << input << std::endl;
- return false;
- } else {
- std::cout << " Success for input: " << input << std::endl;
- return true;
- }
-}
-} // namespace
-
-static WholeSentenceFeature *rsf_factory() { return new RelevantScriptFeature; }
-
-class RelevantScriptFeatureExtractor {
- public:
- RelevantScriptFeatureExtractor() {
- if (WholeSentenceFeature::registry() == nullptr) {
- // Create registry for our WholeSentenceFeature(s).
- RegisterableClass<WholeSentenceFeature>::CreateRegistry(
- "sentence feature function", "WholeSentenceFeature", __FILE__,
- __LINE__);
- }
-
- // Register our WholeSentenceFeature(s).
- // Register RelevantScriptFeature feature function.
- static WholeSentenceFeature::Registry::Registrar rsf_registrar(
- WholeSentenceFeature::registry(), "continuous-bag-of-relevant-scripts",
- "RelevantScriptFeature", __FILE__, __LINE__, rsf_factory);
-
- feature_extractor_.Parse("continuous-bag-of-relevant-scripts");
- TaskContext context;
- feature_extractor_.Setup(&context);
- feature_extractor_.Init(&context);
- feature_extractor_.RequestWorkspaces(&workspace_registry_);
- }
-
- // Returns "true" if feature extraction is successful, and "false" otherwise.
- bool Extract(const string &text, std::map<int, float> *float_features) {
- float_features->clear();
- if (text.empty()) {
- return true;
- }
- Sentence sentence;
- sentence.set_text(text);
- workspace_.Reset(workspace_registry_);
- feature_extractor_.Preprocess(&workspace_, &sentence);
- FeatureVector feature_vector;
- feature_extractor_.ExtractFeatures(workspace_, sentence, &feature_vector);
-
- for (int index = 0; index < feature_vector.size(); ++index) {
- const FloatFeatureValue value =
- FloatFeatureValue(feature_vector.value(index));
- if (float_features->count(value.value.id) != 0) {
- std::cout << " Failure: duplicate feature" << std::endl;
- return false;
- }
- float_features->emplace(value.value.id, value.value.weight);
- }
- return true;
- }
-
- private:
- WorkspaceSet workspace_;
- WholeSentenceExtractor feature_extractor_;
-
- // The registry of shared workspaces in the feature extractor.
- WorkspaceRegistry workspace_registry_;
-};
-
-bool TestCommonCases() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- RelevantScriptFeatureExtractor extractor;
- std::map<int, float> float_features;
- bool test_successful = true;
-
- string input = "just some plain text";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptOtherUtf8OneByte, 1.00}},
- float_features)) {
- test_successful = false;
- }
-
- input = "ヸヂ゠ヂ";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptKatakana, 1.00}},
- float_features)) {
- test_successful = false;
- }
-
- // 4 Latin letters mixed with 4 Katakana letters.
- input = "ヸtヂe゠xtヂ";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptOtherUtf8OneByte, 0.5},
- {chrome_lang_id::kScriptKatakana, 0.5}},
- float_features)) {
- test_successful = false;
- }
-
- input = "just some 121212%^^( ヸヂ゠ヂ text";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptOtherUtf8OneByte, 0.75},
- {chrome_lang_id::kScriptKatakana, 0.25}},
- float_features)) {
- test_successful = false;
- }
-
- return test_successful;
-}
-
-bool TestCornerCases() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- RelevantScriptFeatureExtractor extractor;
- std::map<int, float> float_features;
- bool test_successful = true;
-
- // Empty string.
- string input = "";
- if (!extractor.Extract(input, &float_features) ||
- !CheckFeaturesEmpty(input, float_features)) {
- test_successful = false;
- }
-
- // Only whitespaces.
- input = " ";
- if (!extractor.Extract(input, &float_features) ||
- !CheckFeaturesEmpty(input, float_features)) {
- test_successful = false;
- }
-
- // Only numbers and punctuation.
- input = "12----)(";
- if (!extractor.Extract(input, &float_features) ||
- !CheckFeaturesEmpty(input, float_features)) {
- test_successful = false;
- }
-
- // Only numbers, punctuation, and spaces.
- input = "12--- - ) ( ";
- if (!extractor.Extract(input, &float_features) ||
- !CheckFeaturesEmpty(input, float_features)) {
- test_successful = false;
- }
-
- // One UTF8 character by itself.
- input = "ゟ";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptHiragana, 1.00}},
- float_features)) {
- test_successful = false;
- }
-
- input = "ה";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptHebrew, 1.00}},
- float_features)) {
- test_successful = false;
- }
-
- // One UTF8 character with some numbers / punctuation / spaces: character at
- // one extremity or in the middle.
- input = "1234ゟ";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptHiragana, 1.00}},
- float_features)) {
- test_successful = false;
- }
-
- input = "ゟ12-(";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptHiragana, 1.00}},
- float_features)) {
- test_successful = false;
- }
-
- input = "8*1ゟ12----";
- if (!extractor.Extract(input, &float_features) ||
- !FeaturesNear(input, {{chrome_lang_id::kScriptHiragana, 1.00}},
- float_features)) {
- test_successful = false;
- }
-
- return test_successful;
-}
-
-} // namespace relevant_script_feature_test
-} // namespace chrome_lang_id
-
-// Runs the feature extraction tests.
-int main(int argc, char **argv) {
- const bool tests_successful =
- chrome_lang_id::relevant_script_feature_test::TestCommonCases() &&
- chrome_lang_id::relevant_script_feature_test::TestCornerCases();
- return tests_successful ? 0 : 1;
-}
diff --git a/chromium/third_party/cld_3/src/src/script_detector.h b/chromium/third_party/cld_3/src/src/script_detector.h
deleted file mode 100644
index b3c4f6a7d2c..00000000000
--- a/chromium/third_party/cld_3/src/src/script_detector.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef SCRIPT_DETECTOR_H_
-#define SCRIPT_DETECTOR_H_
-
-namespace chrome_lang_id {
-
-// Unicode scripts we care about. To get compact and fast code, we detect only
-// a few Unicode scripts that offer a strong indication about the language of
-// the text (e.g., Hiragana -> Japanese).
-enum Script {
- // Special value to indicate internal errors in the script detection code.
- kScriptError,
-
- // Special values for all Unicode scripts that we do not detect. One special
- // value for Unicode characters of 1, 2, 3, respectively 4 bytes (as we
- // already have that information, we use it). kScriptOtherUtf8OneByte means
- // ~Latin and kScriptOtherUtf8FourBytes means ~Han.
- kScriptOtherUtf8OneByte,
- kScriptOtherUtf8TwoBytes,
- kScriptOtherUtf8ThreeBytes,
- kScriptOtherUtf8FourBytes,
-
- kScriptGreek,
- kScriptCyrillic,
- kScriptHebrew,
- kScriptArabic,
- kScriptHangulJamo, // Used primarily for Korean.
- kScriptHiragana, // Used primarily for Japanese.
- kScriptKatakana, // Used primarily for Japanese.
-
- // Add new scripts here.
-
- // Do not add any script after kNumRelevantScripts. This value indicates the
- // number of elements in this enum Script (except this value) such that we can
- // easily iterate over the scripts.
- kNumRelevantScripts,
-};
-
-template <typename IntType>
-inline bool InRange(IntType value, IntType low, IntType hi) {
- return (value >= low) && (value <= hi);
-}
-
-// Returns Script for the UTF8 character that starts at address p.
-// Precondition: p points to a valid UTF8 character of num_bytes bytes.
-inline Script GetScript(const unsigned char *p, int num_bytes) {
- switch (num_bytes) {
- case 1:
- return kScriptOtherUtf8OneByte;
-
- case 2: {
- // 2-byte UTF8 characters have 11 bits of information. unsigned int has
- // at least 16 bits (http://en.cppreference.com/w/cpp/language/types) so
- // it's enough. It's also usually the fastest int type on the current
- // CPU, so it's better to use than int32.
- static const unsigned int kGreekStart = 0x370;
-
- // Commented out (unsued in the code): kGreekEnd = 0x3FF;
- static const unsigned int kCyrillicStart = 0x400;
- static const unsigned int kCyrillicEnd = 0x4FF;
- static const unsigned int kHebrewStart = 0x590;
-
- // Commented out (unsued in the code): kHebrewEnd = 0x5FF;
- static const unsigned int kArabicStart = 0x600;
- static const unsigned int kArabicEnd = 0x6FF;
- const unsigned int codepoint = ((p[0] & 0x1F) << 6) | (p[1] & 0x3F);
- if (codepoint > kCyrillicEnd) {
- if (codepoint >= kArabicStart) {
- if (codepoint <= kArabicEnd) {
- return kScriptArabic;
- }
- } else {
- // At this point, codepoint < kArabicStart = kHebrewEnd + 1, so
- // codepoint <= kHebrewEnd.
- if (codepoint >= kHebrewStart) {
- return kScriptHebrew;
- }
- }
- } else {
- if (codepoint >= kCyrillicStart) {
- return kScriptCyrillic;
- } else {
- // At this point, codepoint < kCyrillicStart = kGreekEnd + 1, so
- // codepoint <= kGreekEnd.
- if (codepoint >= kGreekStart) {
- return kScriptGreek;
- }
- }
- }
- return kScriptOtherUtf8TwoBytes;
- }
-
- case 3: {
- // 3-byte UTF8 characters have 16 bits of information. unsigned int has
- // at least 16 bits.
- static const unsigned int kHangulJamoStart = 0x1100;
- static const unsigned int kHangulJamoEnd = 0x11FF;
- static const unsigned int kHiraganaStart = 0x3041;
- static const unsigned int kHiraganaEnd = 0x309F;
-
- // Commented out (unsued in the code): kKatakanaStart = 0x30A0;
- static const unsigned int kKatakanaEnd = 0x30FF;
- const unsigned int codepoint =
- ((p[0] & 0x0F) << 12) | ((p[1] & 0x3F) << 6) | (p[2] & 0x3F);
- if (codepoint > kHiraganaEnd) {
- // On this branch, codepoint > kHiraganaEnd = kKatakanaStart - 1, so
- // codepoint >= kKatakanaStart.
- if (codepoint <= kKatakanaEnd) {
- return kScriptKatakana;
- }
- } else {
- if (codepoint >= kHiraganaStart) {
- return kScriptHiragana;
- } else {
- if (InRange(codepoint, kHangulJamoStart, kHangulJamoEnd)) {
- return kScriptHangulJamo;
- }
- }
- }
- return kScriptOtherUtf8ThreeBytes;
- }
-
- case 4:
- return kScriptOtherUtf8FourBytes;
-
- default:
- return kScriptError;
- }
-}
-
-// Returns Script for the UTF8 character that starts at address p. Similar to
-// the previous version of GetScript, except for "char" vs "unsigned char".
-// Most code works with "char *" pointers, ignoring the fact that char is
-// unsigned (by default) on most platforms, but signed on iOS. This code takes
-// care of making sure we always treat chars as unsigned.
-inline Script GetScript(const char *p, int num_bytes) {
- return GetScript(reinterpret_cast<const unsigned char *>(p), num_bytes);
-}
-
-} // namespace chrome_lang_id
-
-#endif // SCRIPT_DETECTOR_H_
diff --git a/chromium/third_party/cld_3/src/src/script_detector_test.cc b/chromium/third_party/cld_3/src/src/script_detector_test.cc
deleted file mode 100644
index 50bea8f351b..00000000000
--- a/chromium/third_party/cld_3/src/src/script_detector_test.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "script_detector.h"
-
-#include <iostream>
-
-#include "utils.h"
-
-namespace chrome_lang_id {
-namespace script_detector_test {
-
-Script GetScript(const char *p) {
- const int num_bytes = utils::OneCharLen(p);
- return chrome_lang_id::GetScript(p, num_bytes);
-}
-
-bool PrintAndReturnStatus(bool status) {
- if (status) {
- std::cout << " Success" << std::endl;
- return true;
- } else {
- std::cout << " Failure" << std::endl;
- return false;
- }
-}
-
-bool TestGreekScript() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- // The first two conditions check first / last character from the Greek and
- // Coptic script. The last two ones are negative tests.
- return PrintAndReturnStatus(
- kScriptGreek == GetScript("Ͱ") && kScriptGreek == GetScript("Ͽ") &&
- kScriptGreek == GetScript("δ") && kScriptGreek == GetScript("Θ") &&
- kScriptGreek == GetScript("Δ") && kScriptGreek != GetScript("a") &&
- kScriptGreek != GetScript("0"));
-}
-
-bool TestCyrillicScript() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
- return PrintAndReturnStatus(
- kScriptCyrillic == GetScript("Ѐ") && kScriptCyrillic == GetScript("ӿ") &&
- kScriptCyrillic == GetScript("ш") && kScriptCyrillic == GetScript("Б") &&
- kScriptCyrillic == GetScript("Ӱ"));
-}
-
-bool TestHebrewScript() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
- return PrintAndReturnStatus(
- kScriptHebrew == GetScript("֑") && kScriptHebrew == GetScript("״") &&
- kScriptHebrew == GetScript("ד") && kScriptHebrew == GetScript("ה") &&
- kScriptHebrew == GetScript("צ"));
-}
-
-bool TestArabicScript() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
- return PrintAndReturnStatus(kScriptArabic == GetScript("م") &&
- kScriptArabic == GetScript("خ"));
-}
-
-bool TestHangulJamoScript() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
- return PrintAndReturnStatus(kScriptHangulJamo == GetScript("ᄀ") &&
- kScriptHangulJamo == GetScript("ᇿ") &&
- kScriptHangulJamo == GetScript("ᄡ") &&
- kScriptHangulJamo == GetScript("ᆅ") &&
- kScriptHangulJamo == GetScript("ᅘ"));
-}
-
-bool TestHiraganaScript() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
- return PrintAndReturnStatus(kScriptHiragana == GetScript("ぁ") &&
- kScriptHiragana == GetScript("ゟ") &&
- kScriptHiragana == GetScript("こ") &&
- kScriptHiragana == GetScript("や") &&
- kScriptHiragana == GetScript("ぜ"));
-}
-
-bool TestKatakanaScript() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
- return PrintAndReturnStatus(kScriptKatakana == GetScript("゠") &&
- kScriptKatakana == GetScript("ヿ") &&
- kScriptKatakana == GetScript("ヂ") &&
- kScriptKatakana == GetScript("ザ") &&
- kScriptKatakana == GetScript("ヸ"));
-}
-
-bool TestOtherScripts() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
- bool test_successful = true;
-
- if (kScriptOtherUtf8OneByte != GetScript("^") ||
- kScriptOtherUtf8OneByte != GetScript("$")) {
- test_successful = false;
- }
-
- // Unrecognized 2-byte scripts. For info on the scripts mentioned below, see
- // http://www.unicode.org/charts/#scripts Note: the scripts below are uniquely
- // associated with a language. Still, the number of queries in those
- // languages is small and we didn't want to increase the code size and
- // latency, so (at least for now) we do not treat them specially.
- // The following three tests are, respectively, for Armenian, Syriac and
- // Thaana.
- if (kScriptOtherUtf8TwoBytes != GetScript("Ձ") ||
- kScriptOtherUtf8TwoBytes != GetScript("ܔ") ||
- kScriptOtherUtf8TwoBytes != GetScript("ށ")) {
- test_successful = false;
- }
-
- // Unrecognized 3-byte script: CJK Unified Ideographs: not uniquely associated
- // with a language.
- if (kScriptOtherUtf8ThreeBytes != GetScript("万") ||
- kScriptOtherUtf8ThreeBytes != GetScript("両")) {
- test_successful = false;
- }
-
- // Unrecognized 4-byte script: CJK Unified Ideographs Extension C. Note:
- // there is a nice UTF-8 encoder / decoder at https://mothereff.in/utf-8
- if (kScriptOtherUtf8FourBytes != GetScript("\xF0\xAA\x9C\x94")) {
- test_successful = false;
- }
-
- // Unrecognized 4-byte script: CJK Unified Ideographs Extension E
- if (kScriptOtherUtf8FourBytes != GetScript("\xF0\xAB\xA0\xB5") ||
- kScriptOtherUtf8FourBytes != GetScript("\xF0\xAC\xBA\xA1")) {
- test_successful = false;
- }
-
- return PrintAndReturnStatus(test_successful);
-}
-
-} // namespace script_detector_test
-} // namespace chrome_lang_id
-
-// Runs the feature extraction tests.
-int main(int argc, char **argv) {
- const bool tests_successful =
- chrome_lang_id::script_detector_test::TestGreekScript() &&
- chrome_lang_id::script_detector_test::TestCyrillicScript() &&
- chrome_lang_id::script_detector_test::TestHebrewScript() &&
- chrome_lang_id::script_detector_test::TestArabicScript() &&
- chrome_lang_id::script_detector_test::TestHangulJamoScript() &&
- chrome_lang_id::script_detector_test::TestHiraganaScript() &&
- chrome_lang_id::script_detector_test::TestKatakanaScript() &&
- chrome_lang_id::script_detector_test::TestOtherScripts();
-
- return tests_successful ? 0 : 1;
-}
diff --git a/chromium/third_party/cld_3/src/src/script_span/README.md b/chromium/third_party/cld_3/src/src/script_span/README.md
deleted file mode 100644
index 86578c1821b..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-The code in this directory identifies the scripts present in a given piece of
-text along with the corresponding spans. The code was copied from
-[CLD2](https://github.com/CLD2Owners/cld2) and was slightly refactored. It can
-be further simplified and cleaned up.
-
-
-
-
-
-
-
diff --git a/chromium/third_party/cld_3/src/src/script_span/fixunicodevalue.cc b/chromium/third_party/cld_3/src/src/script_span/fixunicodevalue.cc
deleted file mode 100644
index 373e5ee696a..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/fixunicodevalue.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Routine that maps a Unicode code point to an interchange-valid one
-//
-
-#include "fixunicodevalue.h"
-#include "integral_types.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-// Guarantees that the resulting output value is interchange valid
-// 00-FF; map to spaces or MS CP1252
-// D800-DFFF; surrogates
-// FDD0-FDEF; non-characters
-// xxFFFE-xxFFFF; non-characters
-char32 FixUnicodeValue(char32 uv) {
- uint32 uuv = static_cast<uint32>(uv);
- if (uuv < 0x0100) {
- return kMapFullMicrosoft1252OrSpace[uuv];
- }
- if (uuv < 0xD800) {
- return uv;
- }
- if ((uuv & ~0x0F) == 0xFDD0) { // non-characters
- return 0xFFFD;
- }
- if ((uuv & ~0x0F) == 0xFDE0) { // non-characters
- return 0xFFFD;
- }
- if ((uuv & 0x00FFFE) == 0xFFFE) { // non-characters
- return 0xFFFD;
- }
- if ((0xE000 <= uuv) && (uuv <= 0x10FFFF)) {
- return uv;
- }
- // surrogates and negative and > 0x10FFFF all land here
- return 0xFFFD;
-}
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/script_span/fixunicodevalue.h b/chromium/third_party/cld_3/src/src/script_span/fixunicodevalue.h
deleted file mode 100644
index ec90a9f6256..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/fixunicodevalue.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Routine that maps a Unicode code point to an interchange-valid one
-//
-// Table that maps MS CP1252 bytes 00-FF to their corresponding Unicode
-// code points. C0 and C1 control codes that are not interchange-valid
-// are mapped to spaces.
-
-
-#ifndef SCRIPT_SPAN_FIXUNICODEVALUE_H_
-#define SCRIPT_SPAN_FIXUNICODEVALUE_H_
-
-#include "integral_types.h" // for char32
-#include "port.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-// Map byte value 0000-00FF to char32
-// Maps C0 control codes (other than CR LF HT FF) to space [29 instances including DEL=0x7F]
-// Maps C1 control codes to CP1252 [27 instances] or space [5 instances]
-static const char32 kMapFullMicrosoft1252OrSpace[256] = {
- 0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20, 0x20,0x09,0x0a,0x20, 0x0c,0x0d,0x20,0x20, // 00
- 0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,
- 0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27, 0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
- 0x30,0x31,0x32,0x33, 0x34,0x35,0x36,0x37, 0x38,0x39,0x3a,0x3b, 0x3c,0x3d,0x3e,0x3f,
-
- 0x40,0x41,0x42,0x43, 0x44,0x45,0x46,0x47, 0x48,0x49,0x4a,0x4b, 0x4c,0x4d,0x4e,0x4f, // 40
- 0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x57, 0x58,0x59,0x5a,0x5b, 0x5c,0x5d,0x5e,0x5f,
- 0x60,0x61,0x62,0x63, 0x64,0x65,0x66,0x67, 0x68,0x69,0x6a,0x6b, 0x6c,0x6d,0x6e,0x6f,
- 0x70,0x71,0x72,0x73, 0x74,0x75,0x76,0x77, 0x78,0x79,0x7a,0x7b, 0x7c,0x7d,0x7e,0x20,
-
- 0x20ac,0x20,0x201a,0x0192, 0x201e,0x2026,0x2020,0x2021, // 80
- 0x02c6,0x2030,0x0160,0x2039, 0x0152,0x20,0x017d,0x20,
- 0x20,0x2018,0x2019,0x201c, 0x201d,0x2022,0x2013,0x2014,
- 0x02dc,0x2122,0x0161,0x203a, 0x0153,0x20,0x017e,0x0178,
- 0xa0,0xa1,0xa2,0xa3, 0xa4,0xa5,0xa6,0xa7, 0xa8,0xa9,0xaa,0xab, 0xac,0xad,0xae,0xaf, // A0
- 0xb0,0xb1,0xb2,0xb3, 0xb4,0xb5,0xb6,0xb7, 0xb8,0xb9,0xba,0xbb, 0xbc,0xbd,0xbe,0xbf,
-
- 0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf, // C0
- 0xd0,0xd1,0xd2,0xd3, 0xd4,0xd5,0xd6,0xd7, 0xd8,0xd9,0xda,0xdb, 0xdc,0xdd,0xde,0xdf,
- 0xe0,0xe1,0xe2,0xe3, 0xe4,0xe5,0xe6,0xe7, 0xe8,0xe9,0xea,0xeb, 0xec,0xed,0xee,0xef,
- 0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
-};
-
-// Guarantees that the resulting output value is interchange valid
-// 00-FF; map to spaces or MS CP1252
-// D800-DFFF; surrogates
-// FDD0-FDEF; non-characters
-// xxFFFE-xxFFFF; non-characters
-char32 FixUnicodeValue(char32 uv);
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_FIXUNICODEVALUE_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/generated_entities.cc b/chromium/third_party/cld_3/src/src/script_span/generated_entities.cc
deleted file mode 100644
index 3f3bacf178c..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/generated_entities.cc
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// generated_entities.cc
-// Machine generated. Do Not Edit.
-//
-// Declarations for HTML entities recognized by CLD2
-//
-#include "generated_ulscript.h" // for CharIntPair
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-// Alphabetical order for binary search
-extern const int kNameToEntitySize = 265;
-extern const CharIntPair kNameToEntity[kNameToEntitySize] = {
- {"AElig", 198},
- {"AMP", 38},
- {"Aacute", 193},
- {"Acirc", 194},
- {"Agrave", 192},
- {"Alpha", 913},
- {"Aring", 197},
- {"Atilde", 195},
- {"Auml", 196},
- {"Beta", 914},
- {"Ccaron", 268},
- {"Ccedil", 199},
- {"Chi", 935},
- {"Dagger", 8225},
- {"Delta", 916},
- {"ETH", 208},
- {"Eacute", 201},
- {"Ecaron", 282},
- {"Ecirc", 202},
- {"Egrave", 200},
- {"Epsilon", 917},
- {"Eta", 919},
- {"Euml", 203},
- {"GT", 62},
- {"Gamma", 915},
- {"Iacute", 205},
- {"Icirc", 206},
- {"Igrave", 204},
- {"Iota", 921},
- {"Iuml", 207},
- {"Kappa", 922},
- {"LT", 60},
- {"Lambda", 923},
- {"Mu", 924},
- {"Ntilde", 209},
- {"Nu", 925},
- {"OElig", 338},
- {"Oacute", 211},
- {"Ocirc", 212},
- {"Ograve", 210},
- {"Omega", 937},
- {"Omicron", 927},
- {"Oslash", 216},
- {"Otilde", 213},
- {"Ouml", 214},
- {"Phi", 934},
- {"Pi", 928},
- {"Prime", 8243},
- {"Psi", 936},
- {"QUOT", 34},
- {"Rcaron", 344},
- {"Rho", 929},
- {"Scaron", 352},
- {"Sigma", 931},
- {"THORN", 222},
- {"Tau", 932},
- {"Theta", 920},
- {"Uacute", 218},
- {"Ucirc", 219},
- {"Ugrave", 217},
- {"Upsilon", 933},
- {"Uuml", 220},
- {"Xi", 926},
- {"Yacute", 221},
- {"Yuml", 376},
- {"Zeta", 918},
- {"aacute", 225},
- {"acirc", 226},
- {"acute", 180},
- {"aelig", 230},
- {"agrave", 224},
- {"alefsym", 8501},
- {"alpha", 945},
- {"amp", 38},
- {"and", 8743},
- {"ang", 8736},
- {"apos", 39},
- {"aring", 229},
- {"asymp", 8776},
- {"atilde", 227},
- {"auml", 228},
- {"bdquo", 8222},
- {"beta", 946},
- {"brvbar", 166},
- {"bull", 8226},
- {"cap", 8745},
- {"ccaron", 269},
- {"ccedil", 231},
- {"cedil", 184},
- {"cent", 162},
- {"chi", 967},
- {"circ", 710},
- {"clubs", 9827},
- {"cong", 8773},
- {"copy", 169},
- {"crarr", 8629},
- {"cup", 8746},
- {"curren", 164},
- {"dArr", 8659},
- {"dagger", 8224},
- {"darr", 8595},
- {"deg", 176},
- {"delta", 948},
- {"diams", 9830},
- {"divide", 247},
- {"eacute", 233},
- {"ecaron", 283},
- {"ecirc", 234},
- {"egrave", 232},
- {"emdash", 8212},
- {"empty", 8709},
- {"emsp", 8195},
- {"endash", 8211},
- {"ensp", 8194},
- {"epsilon", 949},
- {"equiv", 8801},
- {"eta", 951},
- {"eth", 240},
- {"euml", 235},
- {"euro", 8364},
- {"exist", 8707},
- {"fnof", 402},
- {"forall", 8704},
- {"frac12", 189},
- {"frac14", 188},
- {"frac34", 190},
- {"frasl", 8260},
- {"gamma", 947},
- {"ge", 8805},
- {"gt", 62},
- {"hArr", 8660},
- {"harr", 8596},
- {"hearts", 9829},
- {"hellip", 8230},
- {"iacute", 237},
- {"icirc", 238},
- {"iexcl", 161},
- {"igrave", 236},
- {"image", 8465},
- {"infin", 8734},
- {"int", 8747},
- {"iota", 953},
- {"iquest", 191},
- {"isin", 8712},
- {"iuml", 239},
- {"kappa", 954},
- {"lArr", 8656},
- {"lambda", 955},
- {"lang", 9001},
- {"laquo", 171},
- {"larr", 8592},
- {"lceil", 8968},
- {"ldquo", 8220},
- {"le", 8804},
- {"lfloor", 8970},
- {"lowast", 8727},
- {"loz", 9674},
- {"lrm", 8206},
- {"lsaquo", 8249},
- {"lsquo", 8216},
- {"lt", 60},
- {"macr", 175},
- {"mdash", 8212},
- {"micro", 181},
- {"middot", 183},
- {"minus", 8722},
- {"mu", 956},
- {"nabla", 8711},
- {"nbsp", 160},
- {"ndash", 8211},
- {"ne", 8800},
- {"ni", 8715},
- {"not", 172},
- {"notin", 8713},
- {"nsub", 8836},
- {"ntilde", 241},
- {"nu", 957},
- {"oacute", 243},
- {"ocirc", 244},
- {"oelig", 339},
- {"ograve", 242},
- {"oline", 8254},
- {"omega", 969},
- {"omicron", 959},
- {"oplus", 8853},
- {"or", 8744},
- {"ordf", 170},
- {"ordm", 186},
- {"oslash", 248},
- {"otilde", 245},
- {"otimes", 8855},
- {"ouml", 246},
- {"para", 182},
- {"part", 8706},
- {"permil", 8240},
- {"perp", 8869},
- {"phi", 966},
- {"pi", 960},
- {"piv", 982},
- {"plusmn", 177},
- {"pound", 163},
- {"prime", 8242},
- {"prod", 8719},
- {"prop", 8733},
- {"psi", 968},
- {"quot", 34},
- {"rArr", 8658},
- {"radic", 8730},
- {"rang", 9002},
- {"raquo", 187},
- {"rarr", 8594},
- {"rcaron", 345},
- {"rceil", 8969},
- {"rdquo", 8221},
- {"real", 8476},
- {"reg", 174},
- {"rfloor", 8971},
- {"rho", 961},
- {"rlm", 8207},
- {"rsaquo", 8250},
- {"rsquo", 8217},
- {"sbquo", 8218},
- {"scaron", 353},
- {"sdot", 8901},
- {"sect", 167},
- {"shy", 173},
- {"sigma", 963},
- {"sigmaf", 962},
- {"sim", 8764},
- {"spades", 9824},
- {"sub", 8834},
- {"sube", 8838},
- {"sum", 8721},
- {"sup", 8835},
- {"sup1", 185},
- {"sup2", 178},
- {"sup3", 179},
- {"supe", 8839},
- {"szlig", 223},
- {"tau", 964},
- {"there4", 8756},
- {"theta", 952},
- {"thetasym", 977},
- {"thinsp", 8201},
- {"thorn", 254},
- {"tilde", 732},
- {"times", 215},
- {"trade", 8482},
- {"uArr", 8657},
- {"uacute", 250},
- {"uarr", 8593},
- {"ucirc", 251},
- {"ugrave", 249},
- {"uml", 168},
- {"upsih", 978},
- {"upsilon", 965},
- {"uuml", 252},
- {"weierp", 8472},
- {"xi", 958},
- {"yacute", 253},
- {"yen", 165},
- {"yuml", 255},
- {"zeta", 950},
- {"zwj", 8205},
- {"zwnj", 8204},
-};
-
-} // namespace CLD2
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/script_span/generated_ulscript.cc b/chromium/third_party/cld_3/src/src/script_span/generated_ulscript.cc
deleted file mode 100644
index 8a2b39b68f0..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/generated_ulscript.cc
+++ /dev/null
@@ -1,678 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// generated_ulscript.cc
-// Machine generated. Do Not Edit.
-//
-// Declarations for scripts recognized by CLD2
-//
-
-#include "generated_ulscript.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-// Subscripted by enum ULScript
-extern const int kULScriptToNameSize = 102;
-extern const char* const kULScriptToName[kULScriptToNameSize] = {
- "Common", // 0 Zyyy
- "Latin", // 1 Latn
- "Greek", // 2 Grek
- "Cyrillic", // 3 Cyrl
- "Armenian", // 4 Armn
- "Hebrew", // 5 Hebr
- "Arabic", // 6 Arab
- "Syriac", // 7 Syrc
- "Thaana", // 8 Thaa
- "Devanagari", // 9 Deva
- "Bengali", // 10 Beng
- "Gurmukhi", // 11 Guru
- "Gujarati", // 12 Gujr
- "Oriya", // 13 Orya
- "Tamil", // 14 Taml
- "Telugu", // 15 Telu
- "Kannada", // 16 Knda
- "Malayalam", // 17 Mlym
- "Sinhala", // 18 Sinh
- "Thai", // 19 Thai
- "Lao", // 20 Laoo
- "Tibetan", // 21 Tibt
- "Myanmar", // 22 Mymr
- "Georgian", // 23 Geor
- "Hani", // 24 Hani
- "Ethiopic", // 25 Ethi
- "Cherokee", // 26 Cher
- "Canadian_Aboriginal", // 27 Cans
- "Ogham", // 28 Ogam
- "Runic", // 29 Runr
- "Khmer", // 30 Khmr
- "Mongolian", // 31 Mong
- "", // 32
- "", // 33
- "Bopomofo", // 34 Bopo
- "", // 35
- "Yi", // 36 Yiii
- "Old_Italic", // 37 Ital
- "Gothic", // 38 Goth
- "Deseret", // 39 Dsrt
- "Inherited", // 40 Zinh
- "Tagalog", // 41 Tglg
- "Hanunoo", // 42 Hano
- "Buhid", // 43 Buhd
- "Tagbanwa", // 44 Tagb
- "Limbu", // 45 Limb
- "Tai_Le", // 46 Tale
- "Linear_B", // 47 Linb
- "Ugaritic", // 48 Ugar
- "Shavian", // 49 Shaw
- "Osmanya", // 50 Osma
- "Cypriot", // 51 Cprt
- "Braille", // 52 Brai
- "Buginese", // 53 Bugi
- "Coptic", // 54 Copt
- "New_Tai_Lue", // 55 Talu
- "Glagolitic", // 56 Glag
- "Tifinagh", // 57 Tfng
- "Syloti_Nagri", // 58 Sylo
- "Old_Persian", // 59 Xpeo
- "Kharoshthi", // 60 Khar
- "Balinese", // 61 Bali
- "Cuneiform", // 62 Xsux
- "Phoenician", // 63 Phnx
- "Phags_Pa", // 64 Phag
- "Nko", // 65 Nkoo
- "Sundanese", // 66 Sund
- "Lepcha", // 67 Lepc
- "Ol_Chiki", // 68 Olck
- "Vai", // 69 Vaii
- "Saurashtra", // 70 Saur
- "Kayah_Li", // 71 Kali
- "Rejang", // 72 Rjng
- "Lycian", // 73 Lyci
- "Carian", // 74 Cari
- "Lydian", // 75 Lydi
- "Cham", // 76 Cham
- "Tai_Tham", // 77 Lana
- "Tai_Viet", // 78 Tavt
- "Avestan", // 79 Avst
- "Egyptian_Hieroglyphs", // 80 Egyp
- "Samaritan", // 81 Samr
- "Lisu", // 82 Lisu
- "Bamum", // 83 Bamu
- "Javanese", // 84 Java
- "Meetei_Mayek", // 85 Mtei
- "Imperial_Aramaic", // 86 Armi
- "Old_South_Arabian", // 87 Sarb
- "Inscriptional_Parthian", // 88 Prti
- "Inscriptional_Pahlavi", // 89 Phli
- "Old_Turkic", // 90 Orkh
- "Kaithi", // 91 Kthi
- "Batak", // 92 Batk
- "Brahmi", // 93 Brah
- "Mandaic", // 94 Mand
- "Chakma", // 95 Cakm
- "Meroitic_Cursive", // 96 Merc
- "Meroitic_Hieroglyphs", // 97 Mero
- "Miao", // 98 Plrd
- "Sharada", // 99 Shrd
- "Sora_Sompeng", // 100 Sora
- "Takri", // 101 Takr
-};
-
-// Subscripted by enum ULScript
-extern const int kULScriptToCodeSize = 102;
-extern const char* const kULScriptToCode[kULScriptToCodeSize] = {
- "Zyyy", // 0 Common
- "Latn", // 1 Latin
- "Grek", // 2 Greek
- "Cyrl", // 3 Cyrillic
- "Armn", // 4 Armenian
- "Hebr", // 5 Hebrew
- "Arab", // 6 Arabic
- "Syrc", // 7 Syriac
- "Thaa", // 8 Thaana
- "Deva", // 9 Devanagari
- "Beng", // 10 Bengali
- "Guru", // 11 Gurmukhi
- "Gujr", // 12 Gujarati
- "Orya", // 13 Oriya
- "Taml", // 14 Tamil
- "Telu", // 15 Telugu
- "Knda", // 16 Kannada
- "Mlym", // 17 Malayalam
- "Sinh", // 18 Sinhala
- "Thai", // 19 Thai
- "Laoo", // 20 Lao
- "Tibt", // 21 Tibetan
- "Mymr", // 22 Myanmar
- "Geor", // 23 Georgian
- "Hani", // 24 Hani
- "Ethi", // 25 Ethiopic
- "Cher", // 26 Cherokee
- "Cans", // 27 Canadian_Aboriginal
- "Ogam", // 28 Ogham
- "Runr", // 29 Runic
- "Khmr", // 30 Khmer
- "Mong", // 31 Mongolian
- "", // 32
- "", // 33
- "Bopo", // 34 Bopomofo
- "", // 35
- "Yiii", // 36 Yi
- "Ital", // 37 Old_Italic
- "Goth", // 38 Gothic
- "Dsrt", // 39 Deseret
- "Zinh", // 40 Inherited
- "Tglg", // 41 Tagalog
- "Hano", // 42 Hanunoo
- "Buhd", // 43 Buhid
- "Tagb", // 44 Tagbanwa
- "Limb", // 45 Limbu
- "Tale", // 46 Tai_Le
- "Linb", // 47 Linear_B
- "Ugar", // 48 Ugaritic
- "Shaw", // 49 Shavian
- "Osma", // 50 Osmanya
- "Cprt", // 51 Cypriot
- "Brai", // 52 Braille
- "Bugi", // 53 Buginese
- "Copt", // 54 Coptic
- "Talu", // 55 New_Tai_Lue
- "Glag", // 56 Glagolitic
- "Tfng", // 57 Tifinagh
- "Sylo", // 58 Syloti_Nagri
- "Xpeo", // 59 Old_Persian
- "Khar", // 60 Kharoshthi
- "Bali", // 61 Balinese
- "Xsux", // 62 Cuneiform
- "Phnx", // 63 Phoenician
- "Phag", // 64 Phags_Pa
- "Nkoo", // 65 Nko
- "Sund", // 66 Sundanese
- "Lepc", // 67 Lepcha
- "Olck", // 68 Ol_Chiki
- "Vaii", // 69 Vai
- "Saur", // 70 Saurashtra
- "Kali", // 71 Kayah_Li
- "Rjng", // 72 Rejang
- "Lyci", // 73 Lycian
- "Cari", // 74 Carian
- "Lydi", // 75 Lydian
- "Cham", // 76 Cham
- "Lana", // 77 Tai_Tham
- "Tavt", // 78 Tai_Viet
- "Avst", // 79 Avestan
- "Egyp", // 80 Egyptian_Hieroglyphs
- "Samr", // 81 Samaritan
- "Lisu", // 82 Lisu
- "Bamu", // 83 Bamum
- "Java", // 84 Javanese
- "Mtei", // 85 Meetei_Mayek
- "Armi", // 86 Imperial_Aramaic
- "Sarb", // 87 Old_South_Arabian
- "Prti", // 88 Inscriptional_Parthian
- "Phli", // 89 Inscriptional_Pahlavi
- "Orkh", // 90 Old_Turkic
- "Kthi", // 91 Kaithi
- "Batk", // 92 Batak
- "Brah", // 93 Brahmi
- "Mand", // 94 Mandaic
- "Cakm", // 95 Chakma
- "Merc", // 96 Meroitic_Cursive
- "Mero", // 97 Meroitic_Hieroglyphs
- "Plrd", // 98 Miao
- "Shrd", // 99 Sharada
- "Sora", // 100 Sora_Sompeng
- "Takr", // 101 Takri
-};
-
-// Subscripted by enum ULScript
-extern const int kULScriptToCNameSize = 102;
-extern const char* const kULScriptToCName[kULScriptToCNameSize] = {
- "ULScript_Common", // 0 Zyyy
- "ULScript_Latin", // 1 Latn
- "ULScript_Greek", // 2 Grek
- "ULScript_Cyrillic", // 3 Cyrl
- "ULScript_Armenian", // 4 Armn
- "ULScript_Hebrew", // 5 Hebr
- "ULScript_Arabic", // 6 Arab
- "ULScript_Syriac", // 7 Syrc
- "ULScript_Thaana", // 8 Thaa
- "ULScript_Devanagari", // 9 Deva
- "ULScript_Bengali", // 10 Beng
- "ULScript_Gurmukhi", // 11 Guru
- "ULScript_Gujarati", // 12 Gujr
- "ULScript_Oriya", // 13 Orya
- "ULScript_Tamil", // 14 Taml
- "ULScript_Telugu", // 15 Telu
- "ULScript_Kannada", // 16 Knda
- "ULScript_Malayalam", // 17 Mlym
- "ULScript_Sinhala", // 18 Sinh
- "ULScript_Thai", // 19 Thai
- "ULScript_Lao", // 20 Laoo
- "ULScript_Tibetan", // 21 Tibt
- "ULScript_Myanmar", // 22 Mymr
- "ULScript_Georgian", // 23 Geor
- "ULScript_Hani", // 24 Hani
- "ULScript_Ethiopic", // 25 Ethi
- "ULScript_Cherokee", // 26 Cher
- "ULScript_Canadian_Aboriginal", // 27 Cans
- "ULScript_Ogham", // 28 Ogam
- "ULScript_Runic", // 29 Runr
- "ULScript_Khmer", // 30 Khmr
- "ULScript_Mongolian", // 31 Mong
- "ULScript_32", // 32
- "ULScript_33", // 33
- "ULScript_Bopomofo", // 34 Bopo
- "ULScript_35", // 35
- "ULScript_Yi", // 36 Yiii
- "ULScript_Old_Italic", // 37 Ital
- "ULScript_Gothic", // 38 Goth
- "ULScript_Deseret", // 39 Dsrt
- "ULScript_Inherited", // 40 Zinh
- "ULScript_Tagalog", // 41 Tglg
- "ULScript_Hanunoo", // 42 Hano
- "ULScript_Buhid", // 43 Buhd
- "ULScript_Tagbanwa", // 44 Tagb
- "ULScript_Limbu", // 45 Limb
- "ULScript_Tai_Le", // 46 Tale
- "ULScript_Linear_B", // 47 Linb
- "ULScript_Ugaritic", // 48 Ugar
- "ULScript_Shavian", // 49 Shaw
- "ULScript_Osmanya", // 50 Osma
- "ULScript_Cypriot", // 51 Cprt
- "ULScript_Braille", // 52 Brai
- "ULScript_Buginese", // 53 Bugi
- "ULScript_Coptic", // 54 Copt
- "ULScript_New_Tai_Lue", // 55 Talu
- "ULScript_Glagolitic", // 56 Glag
- "ULScript_Tifinagh", // 57 Tfng
- "ULScript_Syloti_Nagri", // 58 Sylo
- "ULScript_Old_Persian", // 59 Xpeo
- "ULScript_Kharoshthi", // 60 Khar
- "ULScript_Balinese", // 61 Bali
- "ULScript_Cuneiform", // 62 Xsux
- "ULScript_Phoenician", // 63 Phnx
- "ULScript_Phags_Pa", // 64 Phag
- "ULScript_Nko", // 65 Nkoo
- "ULScript_Sundanese", // 66 Sund
- "ULScript_Lepcha", // 67 Lepc
- "ULScript_Ol_Chiki", // 68 Olck
- "ULScript_Vai", // 69 Vaii
- "ULScript_Saurashtra", // 70 Saur
- "ULScript_Kayah_Li", // 71 Kali
- "ULScript_Rejang", // 72 Rjng
- "ULScript_Lycian", // 73 Lyci
- "ULScript_Carian", // 74 Cari
- "ULScript_Lydian", // 75 Lydi
- "ULScript_Cham", // 76 Cham
- "ULScript_Tai_Tham", // 77 Lana
- "ULScript_Tai_Viet", // 78 Tavt
- "ULScript_Avestan", // 79 Avst
- "ULScript_Egyptian_Hieroglyphs", // 80 Egyp
- "ULScript_Samaritan", // 81 Samr
- "ULScript_Lisu", // 82 Lisu
- "ULScript_Bamum", // 83 Bamu
- "ULScript_Javanese", // 84 Java
- "ULScript_Meetei_Mayek", // 85 Mtei
- "ULScript_Imperial_Aramaic", // 86 Armi
- "ULScript_Old_South_Arabian", // 87 Sarb
- "ULScript_Inscriptional_Parthian", // 88 Prti
- "ULScript_Inscriptional_Pahlavi", // 89 Phli
- "ULScript_Old_Turkic", // 90 Orkh
- "ULScript_Kaithi", // 91 Kthi
- "ULScript_Batak", // 92 Batk
- "ULScript_Brahmi", // 93 Brah
- "ULScript_Mandaic", // 94 Mand
- "ULScript_Chakma", // 95 Cakm
- "ULScript_Meroitic_Cursive", // 96 Merc
- "ULScript_Meroitic_Hieroglyphs", // 97 Mero
- "ULScript_Miao", // 98 Plrd
- "ULScript_Sharada", // 99 Shrd
- "ULScript_Sora_Sompeng", // 100 Sora
- "ULScript_Takri", // 101 Takr
-};
-
-// Subscripted by enum ULScript
-extern const int kULScriptToRtypeSize = 102;
-extern const ULScriptRType kULScriptToRtype[kULScriptToRtypeSize] = {
- RTypeNone, // 0 Zyyy
- RTypeMany, // 1 Latn
- RTypeOne, // 2 Grek
- RTypeMany, // 3 Cyrl
- RTypeOne, // 4 Armn
- RTypeMany, // 5 Hebr
- RTypeMany, // 6 Arab
- RTypeOne, // 7 Syrc
- RTypeOne, // 8 Thaa
- RTypeMany, // 9 Deva
- RTypeMany, // 10 Beng
- RTypeOne, // 11 Guru
- RTypeOne, // 12 Gujr
- RTypeOne, // 13 Orya
- RTypeOne, // 14 Taml
- RTypeOne, // 15 Telu
- RTypeOne, // 16 Knda
- RTypeOne, // 17 Mlym
- RTypeOne, // 18 Sinh
- RTypeOne, // 19 Thai
- RTypeOne, // 20 Laoo
- RTypeMany, // 21 Tibt
- RTypeOne, // 22 Mymr
- RTypeOne, // 23 Geor
- RTypeCJK, // 24 Hani
- RTypeMany, // 25 Ethi
- RTypeOne, // 26 Cher
- RTypeOne, // 27 Cans
- RTypeNone, // 28 Ogam
- RTypeNone, // 29 Runr
- RTypeOne, // 30 Khmr
- RTypeOne, // 31 Mong
- RTypeNone, // 32
- RTypeNone, // 33
- RTypeNone, // 34 Bopo
- RTypeNone, // 35
- RTypeNone, // 36 Yiii
- RTypeNone, // 37 Ital
- RTypeNone, // 38 Goth
- RTypeNone, // 39 Dsrt
- RTypeNone, // 40 Zinh
- RTypeOne, // 41 Tglg
- RTypeNone, // 42 Hano
- RTypeNone, // 43 Buhd
- RTypeNone, // 44 Tagb
- RTypeOne, // 45 Limb
- RTypeNone, // 46 Tale
- RTypeNone, // 47 Linb
- RTypeNone, // 48 Ugar
- RTypeNone, // 49 Shaw
- RTypeNone, // 50 Osma
- RTypeNone, // 51 Cprt
- RTypeNone, // 52 Brai
- RTypeNone, // 53 Bugi
- RTypeNone, // 54 Copt
- RTypeNone, // 55 Talu
- RTypeNone, // 56 Glag
- RTypeNone, // 57 Tfng
- RTypeNone, // 58 Sylo
- RTypeNone, // 59 Xpeo
- RTypeNone, // 60 Khar
- RTypeNone, // 61 Bali
- RTypeNone, // 62 Xsux
- RTypeNone, // 63 Phnx
- RTypeNone, // 64 Phag
- RTypeNone, // 65 Nkoo
- RTypeNone, // 66 Sund
- RTypeNone, // 67 Lepc
- RTypeNone, // 68 Olck
- RTypeNone, // 69 Vaii
- RTypeNone, // 70 Saur
- RTypeNone, // 71 Kali
- RTypeNone, // 72 Rjng
- RTypeNone, // 73 Lyci
- RTypeNone, // 74 Cari
- RTypeNone, // 75 Lydi
- RTypeNone, // 76 Cham
- RTypeNone, // 77 Lana
- RTypeNone, // 78 Tavt
- RTypeNone, // 79 Avst
- RTypeNone, // 80 Egyp
- RTypeNone, // 81 Samr
- RTypeNone, // 82 Lisu
- RTypeNone, // 83 Bamu
- RTypeNone, // 84 Java
- RTypeNone, // 85 Mtei
- RTypeNone, // 86 Armi
- RTypeNone, // 87 Sarb
- RTypeNone, // 88 Prti
- RTypeNone, // 89 Phli
- RTypeNone, // 90 Orkh
- RTypeNone, // 91 Kthi
- RTypeNone, // 92 Batk
- RTypeNone, // 93 Brah
- RTypeNone, // 94 Mand
- RTypeNone, // 95 Cakm
- RTypeNone, // 96 Merc
- RTypeNone, // 97 Mero
- RTypeNone, // 98 Plrd
- RTypeNone, // 99 Shrd
- RTypeNone, // 100 Sora
- RTypeNone, // 101 Takr
-};
-
-// Subscripted by enum ULScript
-extern const int kULScriptToDefaultLangSize = 102;
-
-// Alphabetical order for binary search
-extern const int kNameToULScriptSize = 105;
-extern const CharIntPair kNameToULScript[kNameToULScriptSize] = {
- {"Arabic", 6}, // Arab
- {"Armenian", 4}, // Armn
- {"Avestan", 79}, // Avst
- {"Balinese", 61}, // Bali
- {"Bamum", 83}, // Bamu
- {"Batak", 92}, // Batk
- {"Bengali", 10}, // Beng
- {"Bopomofo", 34}, // Bopo
- {"Brahmi", 93}, // Brah
- {"Braille", 52}, // Brai
- {"Buginese", 53}, // Bugi
- {"Buhid", 43}, // Buhd
- {"Canadian_Aboriginal", 27}, // Cans
- {"Carian", 74}, // Cari
- {"Chakma", 95}, // Cakm
- {"Cham", 76}, // Cham
- {"Cherokee", 26}, // Cher
- {"Common", 0}, // Zyyy
- {"Coptic", 54}, // Copt
- {"Cuneiform", 62}, // Xsux
- {"Cypriot", 51}, // Cprt
- {"Cyrillic", 3}, // Cyrl
- {"Deseret", 39}, // Dsrt
- {"Devanagari", 9}, // Deva
- {"Egyptian_Hieroglyphs", 80}, // Egyp
- {"Ethiopic", 25}, // Ethi
- {"Georgian", 23}, // Geor
- {"Glagolitic", 56}, // Glag
- {"Gothic", 38}, // Goth
- {"Greek", 2}, // Grek
- {"Gujarati", 12}, // Gujr
- {"Gurmukhi", 11}, // Guru
- {"Han", 24}, // Hant
- {"Han", 24}, // Hans
- {"Han", 24}, // Hani
- {"Hangul", 24}, // Hang
- {"Hani", 24}, // Hani
- {"Hanunoo", 42}, // Hano
- {"Hebrew", 5}, // Hebr
- {"Hiragana", 24}, // Hira
- {"Imperial_Aramaic", 86}, // Armi
- {"Inherited", 40}, // Zinh
- {"Inscriptional_Pahlavi", 89}, // Phli
- {"Inscriptional_Parthian", 88}, // Prti
- {"Javanese", 84}, // Java
- {"Kaithi", 91}, // Kthi
- {"Kannada", 16}, // Knda
- {"Katakana", 24}, // Kana
- {"Kayah_Li", 71}, // Kali
- {"Kharoshthi", 60}, // Khar
- {"Khmer", 30}, // Khmr
- {"Lao", 20}, // Laoo
- {"Latin", 1}, // Latn
- {"Lepcha", 67}, // Lepc
- {"Limbu", 45}, // Limb
- {"Linear_B", 47}, // Linb
- {"Lisu", 82}, // Lisu
- {"Lycian", 73}, // Lyci
- {"Lydian", 75}, // Lydi
- {"Malayalam", 17}, // Mlym
- {"Mandaic", 94}, // Mand
- {"Meetei_Mayek", 85}, // Mtei
- {"Meroitic_Cursive", 96}, // Merc
- {"Meroitic_Hieroglyphs", 97}, // Mero
- {"Miao", 98}, // Plrd
- {"Mongolian", 31}, // Mong
- {"Myanmar", 22}, // Mymr
- {"New_Tai_Lue", 55}, // Talu
- {"Nko", 65}, // Nkoo
- {"Ogham", 28}, // Ogam
- {"Ol_Chiki", 68}, // Olck
- {"Old_Italic", 37}, // Ital
- {"Old_Persian", 59}, // Xpeo
- {"Old_South_Arabian", 87}, // Sarb
- {"Old_Turkic", 90}, // Orkh
- {"Oriya", 13}, // Orya
- {"Osmanya", 50}, // Osma
- {"Phags_Pa", 64}, // Phag
- {"Phoenician", 63}, // Phnx
- {"Rejang", 72}, // Rjng
- {"Runic", 29}, // Runr
- {"Samaritan", 81}, // Samr
- {"Saurashtra", 70}, // Saur
- {"Sharada", 99}, // Shrd
- {"Shavian", 49}, // Shaw
- {"Sinhala", 18}, // Sinh
- {"Sora_Sompeng", 100}, // Sora
- {"Sundanese", 66}, // Sund
- {"Syloti_Nagri", 58}, // Sylo
- {"Syriac", 7}, // Syrc
- {"Tagalog", 41}, // Tglg
- {"Tagbanwa", 44}, // Tagb
- {"Tai_Le", 46}, // Tale
- {"Tai_Tham", 77}, // Lana
- {"Tai_Viet", 78}, // Tavt
- {"Takri", 101}, // Takr
- {"Tamil", 14}, // Taml
- {"Telugu", 15}, // Telu
- {"Thaana", 8}, // Thaa
- {"Thai", 19}, // Thai
- {"Tibetan", 21}, // Tibt
- {"Tifinagh", 57}, // Tfng
- {"Ugaritic", 48}, // Ugar
- {"Vai", 69}, // Vaii
- {"Yi", 36}, // Yiii
-};
-
-// Alphabetical order for binary search
-extern const int kCodeToULScriptSize = 105;
-extern const CharIntPair kCodeToULScript[kNameToULScriptSize] = {
- {"Arab", 6}, // Arab
- {"Armi", 86}, // Armi
- {"Armn", 4}, // Armn
- {"Avst", 79}, // Avst
- {"Bali", 61}, // Bali
- {"Bamu", 83}, // Bamu
- {"Batk", 92}, // Batk
- {"Beng", 10}, // Beng
- {"Bopo", 34}, // Bopo
- {"Brah", 93}, // Brah
- {"Brai", 52}, // Brai
- {"Bugi", 53}, // Bugi
- {"Buhd", 43}, // Buhd
- {"Cakm", 95}, // Cakm
- {"Cans", 27}, // Cans
- {"Cari", 74}, // Cari
- {"Cham", 76}, // Cham
- {"Cher", 26}, // Cher
- {"Copt", 54}, // Copt
- {"Cprt", 51}, // Cprt
- {"Cyrl", 3}, // Cyrl
- {"Deva", 9}, // Deva
- {"Dsrt", 39}, // Dsrt
- {"Egyp", 80}, // Egyp
- {"Ethi", 25}, // Ethi
- {"Geor", 23}, // Geor
- {"Glag", 56}, // Glag
- {"Goth", 38}, // Goth
- {"Grek", 2}, // Grek
- {"Gujr", 12}, // Gujr
- {"Guru", 11}, // Guru
- {"Hang", 24}, // Hang
- {"Hani", 24}, // Hani
- {"Hani", 24}, // Hani
- {"Hano", 42}, // Hano
- {"Hans", 24}, // Hans
- {"Hant", 24}, // Hant
- {"Hebr", 5}, // Hebr
- {"Hira", 24}, // Hira
- {"Ital", 37}, // Ital
- {"Java", 84}, // Java
- {"Kali", 71}, // Kali
- {"Kana", 24}, // Kana
- {"Khar", 60}, // Khar
- {"Khmr", 30}, // Khmr
- {"Knda", 16}, // Knda
- {"Kthi", 91}, // Kthi
- {"Lana", 77}, // Lana
- {"Laoo", 20}, // Laoo
- {"Latn", 1}, // Latn
- {"Lepc", 67}, // Lepc
- {"Limb", 45}, // Limb
- {"Linb", 47}, // Linb
- {"Lisu", 82}, // Lisu
- {"Lyci", 73}, // Lyci
- {"Lydi", 75}, // Lydi
- {"Mand", 94}, // Mand
- {"Merc", 96}, // Merc
- {"Mero", 97}, // Mero
- {"Mlym", 17}, // Mlym
- {"Mong", 31}, // Mong
- {"Mtei", 85}, // Mtei
- {"Mymr", 22}, // Mymr
- {"Nkoo", 65}, // Nkoo
- {"Ogam", 28}, // Ogam
- {"Olck", 68}, // Olck
- {"Orkh", 90}, // Orkh
- {"Orya", 13}, // Orya
- {"Osma", 50}, // Osma
- {"Phag", 64}, // Phag
- {"Phli", 89}, // Phli
- {"Phnx", 63}, // Phnx
- {"Plrd", 98}, // Plrd
- {"Prti", 88}, // Prti
- {"Rjng", 72}, // Rjng
- {"Runr", 29}, // Runr
- {"Samr", 81}, // Samr
- {"Sarb", 87}, // Sarb
- {"Saur", 70}, // Saur
- {"Shaw", 49}, // Shaw
- {"Shrd", 99}, // Shrd
- {"Sinh", 18}, // Sinh
- {"Sora", 100}, // Sora
- {"Sund", 66}, // Sund
- {"Sylo", 58}, // Sylo
- {"Syrc", 7}, // Syrc
- {"Tagb", 44}, // Tagb
- {"Takr", 101}, // Takr
- {"Tale", 46}, // Tale
- {"Talu", 55}, // Talu
- {"Taml", 14}, // Taml
- {"Tavt", 78}, // Tavt
- {"Telu", 15}, // Telu
- {"Tfng", 57}, // Tfng
- {"Tglg", 41}, // Tglg
- {"Thaa", 8}, // Thaa
- {"Thai", 19}, // Thai
- {"Tibt", 21}, // Tibt
- {"Ugar", 48}, // Ugar
- {"Vaii", 69}, // Vaii
- {"Xpeo", 59}, // Xpeo
- {"Xsux", 62}, // Xsux
- {"Yiii", 36}, // Yiii
- {"Zinh", 40}, // Zinh
- {"Zyyy", 0}, // Zyyy
-};
-
-} // namespace CLD2
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/script_span/generated_ulscript.h b/chromium/third_party/cld_3/src/src/script_span/generated_ulscript.h
deleted file mode 100644
index f2ce51dd16f..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/generated_ulscript.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// generated_ulscript.h
-// Machine generated. Do Not Edit.
-//
-// Declarations for scripts recognized by CLD2
-//
-
-#ifndef SCRIPT_SPAN_GENERATED_ULSCRIPT_H_
-#define SCRIPT_SPAN_GENERATED_ULSCRIPT_H_
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-typedef enum {RTypeNone = 0, RTypeOne, RTypeMany, RTypeCJK} ULScriptRType;
-
-typedef struct {const char* s; int i;} CharIntPair;
-
-typedef enum {
- ULScript_Common = 0, // Zyyy
- ULScript_Latin = 1, // Latn
- ULScript_Greek = 2, // Grek
- ULScript_Cyrillic = 3, // Cyrl
- ULScript_Armenian = 4, // Armn
- ULScript_Hebrew = 5, // Hebr
- ULScript_Arabic = 6, // Arab
- ULScript_Syriac = 7, // Syrc
- ULScript_Thaana = 8, // Thaa
- ULScript_Devanagari = 9, // Deva
- ULScript_Bengali = 10, // Beng
- ULScript_Gurmukhi = 11, // Guru
- ULScript_Gujarati = 12, // Gujr
- ULScript_Oriya = 13, // Orya
- ULScript_Tamil = 14, // Taml
- ULScript_Telugu = 15, // Telu
- ULScript_Kannada = 16, // Knda
- ULScript_Malayalam = 17, // Mlym
- ULScript_Sinhala = 18, // Sinh
- ULScript_Thai = 19, // Thai
- ULScript_Lao = 20, // Laoo
- ULScript_Tibetan = 21, // Tibt
- ULScript_Myanmar = 22, // Mymr
- ULScript_Georgian = 23, // Geor
- ULScript_Hani = 24, // Hani
- ULScript_Ethiopic = 25, // Ethi
- ULScript_Cherokee = 26, // Cher
- ULScript_Canadian_Aboriginal = 27, // Cans
- ULScript_Ogham = 28, // Ogam
- ULScript_Runic = 29, // Runr
- ULScript_Khmer = 30, // Khmr
- ULScript_Mongolian = 31, // Mong
- ULScript_32 = 32, //
- ULScript_33 = 33, //
- ULScript_Bopomofo = 34, // Bopo
- ULScript_35 = 35, //
- ULScript_Yi = 36, // Yiii
- ULScript_Old_Italic = 37, // Ital
- ULScript_Gothic = 38, // Goth
- ULScript_Deseret = 39, // Dsrt
- ULScript_Inherited = 40, // Zinh
- ULScript_Tagalog = 41, // Tglg
- ULScript_Hanunoo = 42, // Hano
- ULScript_Buhid = 43, // Buhd
- ULScript_Tagbanwa = 44, // Tagb
- ULScript_Limbu = 45, // Limb
- ULScript_Tai_Le = 46, // Tale
- ULScript_Linear_B = 47, // Linb
- ULScript_Ugaritic = 48, // Ugar
- ULScript_Shavian = 49, // Shaw
- ULScript_Osmanya = 50, // Osma
- ULScript_Cypriot = 51, // Cprt
- ULScript_Braille = 52, // Brai
- ULScript_Buginese = 53, // Bugi
- ULScript_Coptic = 54, // Copt
- ULScript_New_Tai_Lue = 55, // Talu
- ULScript_Glagolitic = 56, // Glag
- ULScript_Tifinagh = 57, // Tfng
- ULScript_Syloti_Nagri = 58, // Sylo
- ULScript_Old_Persian = 59, // Xpeo
- ULScript_Kharoshthi = 60, // Khar
- ULScript_Balinese = 61, // Bali
- ULScript_Cuneiform = 62, // Xsux
- ULScript_Phoenician = 63, // Phnx
- ULScript_Phags_Pa = 64, // Phag
- ULScript_Nko = 65, // Nkoo
- ULScript_Sundanese = 66, // Sund
- ULScript_Lepcha = 67, // Lepc
- ULScript_Ol_Chiki = 68, // Olck
- ULScript_Vai = 69, // Vaii
- ULScript_Saurashtra = 70, // Saur
- ULScript_Kayah_Li = 71, // Kali
- ULScript_Rejang = 72, // Rjng
- ULScript_Lycian = 73, // Lyci
- ULScript_Carian = 74, // Cari
- ULScript_Lydian = 75, // Lydi
- ULScript_Cham = 76, // Cham
- ULScript_Tai_Tham = 77, // Lana
- ULScript_Tai_Viet = 78, // Tavt
- ULScript_Avestan = 79, // Avst
- ULScript_Egyptian_Hieroglyphs = 80, // Egyp
- ULScript_Samaritan = 81, // Samr
- ULScript_Lisu = 82, // Lisu
- ULScript_Bamum = 83, // Bamu
- ULScript_Javanese = 84, // Java
- ULScript_Meetei_Mayek = 85, // Mtei
- ULScript_Imperial_Aramaic = 86, // Armi
- ULScript_Old_South_Arabian = 87, // Sarb
- ULScript_Inscriptional_Parthian = 88, // Prti
- ULScript_Inscriptional_Pahlavi = 89, // Phli
- ULScript_Old_Turkic = 90, // Orkh
- ULScript_Kaithi = 91, // Kthi
- ULScript_Batak = 92, // Batk
- ULScript_Brahmi = 93, // Brah
- ULScript_Mandaic = 94, // Mand
- ULScript_Chakma = 95, // Cakm
- ULScript_Meroitic_Cursive = 96, // Merc
- ULScript_Meroitic_Hieroglyphs = 97, // Mero
- ULScript_Miao = 98, // Plrd
- ULScript_Sharada = 99, // Shrd
- ULScript_Sora_Sompeng = 100, // Sora
- ULScript_Takri = 101, // Takr
- NUM_ULSCRIPTS
-} ULScript;
-
-#define UNKNOWN_ULSCRIPT ULScript_Common
-
-} // namespace CLD2
-} // namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_GENERATED_ULSCRIPT_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/getonescriptspan.cc b/chromium/third_party/cld_3/src/src/script_span/getonescriptspan.cc
deleted file mode 100644
index 4607bd8fc04..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/getonescriptspan.cc
+++ /dev/null
@@ -1,1109 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Author: dsites@google.com (Dick Sites)
-//
-
-
-#include "getonescriptspan.h"
-
-#include <string.h>
-
-#include "fixunicodevalue.h"
-#include "port.h"
-#include "utf8acceptinterchange.h"
-#include "utf8repl_lettermarklower.h"
-#include "utf8prop_lettermarkscriptnum.h"
-#include "utf8scannot_lettermarkspecial.h"
-#include "utf8statetable.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-// Alphabetical order for binary search, from
-// generated_entities.cc
-extern const int kNameToEntitySize;
-extern const CharIntPair kNameToEntity[];
-
-static const char kSpecialSymbol[256] = { // true for < > &
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,1,0,1,0,
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-};
-
-
-
-#define LT 0 // <
-#define GT 1 // >
-#define EX 2 // !
-#define HY 3 // -
-#define QU 4 // "
-#define AP 5 // '
-#define SL 6 // /
-#define S_ 7
-#define C_ 8
-#define R_ 9
-#define I_ 10
-#define P_ 11
-#define T_ 12
-#define Y_ 13
-#define L_ 14
-#define E_ 15
-#define CR 16 // <cr> or <lf>
-#define NL 17 // non-letter: ASCII whitespace, digit, punctuation
-#define PL 18 // possible letter, incl. &
-#define xx 19 // <unused>
-
-// Map byte to one of ~20 interesting categories for cheap tag parsing
-static const uint8 kCharToSub[256] = {
- NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,CR,NL, NL,CR,NL,NL,
- NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL,
- NL,EX,QU,NL, NL,NL,PL,AP, NL,NL,NL,NL, NL,HY,NL,SL,
- NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL, LT,NL,GT,NL,
-
- PL,PL,PL,C_, PL,E_,PL,PL, PL,I_,PL,PL, L_,PL,PL,PL,
- P_,PL,R_,S_, T_,PL,PL,PL, PL,Y_,PL,NL, NL,NL,NL,NL,
- PL,PL,PL,C_, PL,E_,PL,PL, PL,I_,PL,PL, L_,PL,PL,PL,
- P_,PL,R_,S_, T_,PL,PL,PL, PL,Y_,PL,NL, NL,NL,NL,NL,
-
- NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL,
- NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL,
- NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL,
- NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL, NL,NL,NL,NL,
-
- PL,PL,PL,PL, PL,PL,PL,PL, PL,PL,PL,PL, PL,PL,PL,PL,
- PL,PL,PL,PL, PL,PL,PL,PL, PL,PL,PL,PL, PL,PL,PL,PL,
- PL,PL,PL,PL, PL,PL,PL,PL, PL,PL,PL,PL, PL,PL,PL,PL,
- PL,PL,PL,PL, PL,PL,PL,PL, PL,PL,PL,PL, PL,PL,PL,PL,
-};
-
-#undef LT
-#undef GT
-#undef EX
-#undef HY
-#undef QU
-#undef AP
-#undef SL
-#undef S_
-#undef C_
-#undef R_
-#undef I_
-#undef P_
-#undef T_
-#undef Y_
-#undef L_
-#undef E_
-#undef CR
-#undef NL
-#undef PL
-#undef xx
-
-
-#define OK 0
-#define X_ 1
-
-
-static const int kMaxExitStateLettersMarksOnly = 1;
-static const int kMaxExitStateAllText = 2;
-
-
-// State machine to do cheap parse of non-letter strings incl. tags
-// advances <tag>
-// | |
-// advances <tag> ... </tag> for <script> <style>
-// | |
-// advances <!-- ... <tag> ... -->
-// | |
-// advances <tag
-// || (0)
-// advances <tag <tag2>
-// || (0)
-//
-// We start in state [0] at a non-letter and make at least one transition
-// When scanning for just letters, arriving back at state [0] or [1] exits
-// the state machine.
-// When scanning for any non-tag text, arriving at state [2] also exits
-static const uint8 kTagParseTbl_0[] = {
-// < > ! - " ' / S C R I P T Y L E CR NL PL xx
- 3, 2, 2, 2, 2, 2, 2,OK, OK,OK,OK,OK, OK,OK,OK,OK, 2, 2,OK,X_, // [0] OK exit state
- X_,X_,X_,X_, X_,X_,X_,X_, X_,X_,X_,X_, X_,X_,X_,X_, X_,X_,X_,X_, // [1] error exit state
- 3, 2, 2, 2, 2, 2, 2,OK, OK,OK,OK,OK, OK,OK,OK,OK, 2, 2,OK,X_, // [2] NL* [exit state]
- X_, 2, 4, 9, 10,11, 9,13, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,X_, // [3] <
- X_, 2, 9, 5, 10,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,X_, // [4] <!
- X_, 2, 9, 6, 10,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,X_, // [5] <!-
- 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,X_, // [6] <!--.*
- 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,X_, // [7] <!--.*-
- 6, 2, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,X_, // [8] <!--.*--
- X_, 2, 9, 9, 10,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,X_, // [9] <.*
- 10,10,10,10, 9,10,10,10, 10,10,10,10, 10,10,10,10, 12,10,10,X_, // [10] <.*"
- 11,11,11,11, 11, 9,11,11, 11,11,11,11, 11,11,11,11, 12,11,11,X_, // [11] <.*'
- X_, 2,12,12, 12,12,12,12, 12,12,12,12, 12,12,12,12, 12,12,12,X_, // [12] <.* no " '
-
-// < > ! - " ' / S C R I P T Y L E CR NL PL xx
- X_, 2, 9, 9, 10,11, 9, 9, 14, 9, 9, 9, 28, 9, 9, 9, 9, 9, 9,X_, // [13] <S
- X_, 2, 9, 9, 10,11, 9, 9, 9,15, 9, 9, 9, 9, 9, 9, 9, 9, 9,X_, // [14] <SC
- X_, 2, 9, 9, 10,11, 9, 9, 9, 9,16, 9, 9, 9, 9, 9, 9, 9, 9,X_, // [15] <SCR
- X_, 2, 9, 9, 10,11, 9, 9, 9, 9, 9,17, 9, 9, 9, 9, 9, 9, 9,X_, // [16] <SCRI
- X_, 2, 9, 9, 10,11, 9, 9, 9, 9, 9, 9, 18, 9, 9, 9, 9, 9, 9,X_, // [17] <SCRIP
- X_,19, 9, 9, 10,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 19,19, 9,X_, // [18] <SCRIPT
- 20,19,19,19, 19,19,19,19, 19,19,19,19, 19,19,19,19, 19,19,19,X_, // [19] <SCRIPT .*
- 19,19,19,19, 19,19,21,19, 19,19,19,19, 19,19,19,19, 19,19,19,X_, // [20] <SCRIPT .*<
- 19,19,19,19, 19,19,19,22, 19,19,19,19, 19,19,19,19, 21,21,19,X_, // [21] <SCRIPT .*</ allow SP CR LF
- 19,19,19,19, 19,19,19,19, 23,19,19,19, 19,19,19,19, 19,19,19,X_, // [22] <SCRIPT .*</S
- 19,19,19,19, 19,19,19,19, 19,24,19,19, 19,19,19,19, 19,19,19,X_, // [23] <SCRIPT .*</SC
- 19,19,19,19, 19,19,19,19, 19,19,25,19, 19,19,19,19, 19,19,19,X_, // [24] <SCRIPT .*</SCR
- 19,19,19,19, 19,19,19,19, 19,19,19,26, 19,19,19,19, 19,19,19,X_, // [25] <SCRIPT .*</SCRI
- 19,19,19,19, 19,19,19,19, 19,19,19,19, 27,19,19,19, 19,19,19,X_, // [26] <SCRIPT .*</SCRIP
- 19, 2,19,19, 19,19,19,19, 19,19,19,19, 19,19,19,19, 19,19,19,X_, // [27] <SCRIPT .*</SCRIPT
-
-// < > ! - " ' / S C R I P T Y L E CR NL PL xx
- X_, 2, 9, 9, 10,11, 9, 9, 9, 9, 9, 9, 9,29, 9, 9, 9, 9, 9,X_, // [28] <ST
- X_, 2, 9, 9, 10,11, 9, 9, 9, 9, 9, 9, 9, 9,30, 9, 9, 9, 9,X_, // [29] <STY
- X_, 2, 9, 9, 10,11, 9, 9, 9, 9, 9, 9, 9, 9, 9,31, 9, 9, 9,X_, // [30] <STYL
- X_,32, 9, 9, 10,11, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 32,32, 9,X_, // [31] <STYLE
- 33,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,X_, // [32] <STYLE .*
- 32,32,32,32, 32,32,34,32, 32,32,32,32, 32,32,32,32, 32,32,32,X_, // [33] <STYLE .*<
- 32,32,32,32, 32,32,32,35, 32,32,32,32, 32,32,32,32, 34,34,32,X_, // [34] <STYLE .*</ allow SP CR LF
- 32,32,32,32, 32,32,32,32, 32,32,32,32, 36,32,32,32, 32,32,32,X_, // [35] <STYLE .*</S
- 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,37,32,32, 32,32,32,X_, // [36] <STYLE .*</ST
- 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,38,32, 32,32,32,X_, // [37] <STYLE .*</STY
- 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,39, 32,32,32,X_, // [38] <STYLE .*</STYL
- 32, 2,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,32, 32,32,32,X_, // [39] <STYLE .*</STYLE
-};
-
-#undef OK
-#undef X_
-
-enum
-{
- UTFmax = 4, // maximum bytes per rune
- Runesync = 0x80, // cannot represent part of a UTF sequence (<)
- Runeself = 0x80, // rune and UTF sequences are the same (<)
- Runeerror = 0xFFFD, // decoding error in UTF
- Runemax = 0x10FFFF, // maximum rune value
-};
-
-// Debugging. Not thread safe.
-static char gDisplayPiece[32];
-const uint8 gCharlen[16] = {1,1,1,1, 1,1,1,1, 1,1,1,1, 2,2,3,4};
-char* DisplayPiece(const char* next_byte_, int byte_length_) {
- // Copy up to 8 UTF-8 chars to buffer
- int k = 0; // byte count
- int n = 0; // character count
- for (int i = 0; i < byte_length_; ++i) {
- char c = next_byte_[i];
- if ((c & 0xc0) != 0x80) {
- // Beginning of a UTF-8 character
- int charlen = gCharlen[static_cast<uint8>(c) >> 4];
- if (i + charlen > byte_length_) {break;} // Not enough room for full char
- if (k >= (32 - 7)) {break;} // Not necessarily enough room
- if (n >= 8) {break;} // Enough characters already
- ++n;
- }
- if (c == '<') {
- memcpy(&gDisplayPiece[k], "&lt;", 4); k += 4;
- } else if (c == '>') {
- memcpy(&gDisplayPiece[k], "&gt;", 4); k += 4;
- } else if (c == '&') {
- memcpy(&gDisplayPiece[k], "&amp;", 5); k += 5;
- } else if (c == '\'') {
- memcpy(&gDisplayPiece[k], "&apos;", 6); k += 6;
- } else if (c == '"') {
- memcpy(&gDisplayPiece[k], "&quot;", 6); k += 6;
- } else {
- gDisplayPiece[k++] = c;
- }
- }
- gDisplayPiece[k++] = '\0';
- return gDisplayPiece;
-}
-
-
-
-// runetochar copies (encodes) one rune, pointed to by r, to at most
-// UTFmax bytes starting at s and returns the number of bytes generated.
-int runetochar(char *str, const char32 *rune) {
- // Convert to unsigned for range check.
- unsigned long c;
-
- // 1 char 00-7F
- c = *rune;
- if(c <= 0x7F) {
- str[0] = static_cast<char>(c);
- return 1;
- }
-
- // 2 char 0080-07FF
- if(c <= 0x07FF) {
- str[0] = 0xC0 | static_cast<char>(c >> 1*6);
- str[1] = 0x80 | (c & 0x3F);
- return 2;
- }
-
- // Range check
- if (c > Runemax) {
- c = Runeerror;
- }
-
- // 3 char 0800-FFFF
- if (c <= 0xFFFF) {
- str[0] = 0xE0 | static_cast<char>(c >> 2*6);
- str[1] = 0x80 | ((c >> 1*6) & 0x3F);
- str[2] = 0x80 | (c & 0x3F);
- return 3;
- }
-
- // 4 char 10000-1FFFFF
- str[0] = 0xF0 | static_cast<char>(c >> 3*6);
- str[1] = 0x80 | ((c >> 2*6) & 0x3F);
- str[2] = 0x80 | ((c >> 1*6) & 0x3F);
- str[3] = 0x80 | (c & 0x3F);
- return 4;
-}
-
-
-
-// Useful for converting an entity to an ascii value.
-// RETURNS unicode value, or -1 if entity isn't valid. Don't include & or ;
-int LookupEntity(const char* entity_name, int entity_len) {
- // Make a C string
- if (entity_len >= 16) {return -1;} // All real entities are shorter
- char temp[16];
- memcpy(temp, entity_name, entity_len);
- temp[entity_len] = '\0';
- int match = BinarySearch(temp, 0, kNameToEntitySize, kNameToEntity);
- if (match >= 0) {return kNameToEntity[match].i;}
- return -1;
-}
-
-bool ascii_isdigit(char c) {
- return ('0' <= c) && (c <= '9');
-}
-bool ascii_isxdigit(char c) {
- if (('0' <= c) && (c <= '9')) {return true;}
- if (('a' <= c) && (c <= 'f')) {return true;}
- if (('A' <= c) && (c <= 'F')) {return true;}
- return false;
-}
-bool ascii_isalnum(char c) {
- if (('0' <= c) && (c <= '9')) {return true;}
- if (('a' <= c) && (c <= 'z')) {return true;}
- if (('A' <= c) && (c <= 'Z')) {return true;}
- return false;
-}
-int hex_digit_to_int(char c) {
- if (('0' <= c) && (c <= '9')) {return c - '0';}
- if (('a' <= c) && (c <= 'f')) {return c - 'a' + 10;}
- if (('A' <= c) && (c <= 'F')) {return c - 'A' + 10;}
- return 0;
-}
-
-static int32 strto32_base10(const char* nptr, const char* limit,
- const char **endptr) {
- *endptr = nptr;
- while (nptr < limit && *nptr == '0') {
- ++nptr;
- }
- if (nptr == limit || !ascii_isdigit(*nptr))
- return -1;
- const char* end_digits_run = nptr;
- while (end_digits_run < limit && ascii_isdigit(*end_digits_run)) {
- ++end_digits_run;
- }
- *endptr = end_digits_run;
- const int num_digits = end_digits_run - nptr;
- // kint32max == 2147483647.
- if (num_digits < 9 ||
- (num_digits == 10 && memcmp(nptr, "2147483647", 10) <= 0)) {
- int value = 0;
- for (; nptr < end_digits_run; ++nptr) {
- value *= 10;
- value += *nptr - '0';
- }
- // Overflow past the last valid unicode codepoint
- // (0x10ffff) is converted to U+FFFD by FixUnicodeValue().
- return FixUnicodeValue(value);
- } else {
- // Overflow: can't fit in an int32;
- // returns the replacement character 0xFFFD.
- return 0xFFFD;
- }
-}
-
-static int32 strto32_base16(const char* nptr, const char* limit,
- const char **endptr) {
- *endptr = nptr;
- while (nptr < limit && *nptr == '0') {
- ++nptr;
- }
- if (nptr == limit || !ascii_isxdigit(*nptr)) {
- return -1;
- }
- const char* end_xdigits_run = nptr;
- while (end_xdigits_run < limit && ascii_isxdigit(*end_xdigits_run)) {
- ++end_xdigits_run;
- }
- *endptr = end_xdigits_run;
- const int num_xdigits = end_xdigits_run - nptr;
- // kint32max == 0x7FFFFFFF.
- if (num_xdigits < 8 || (num_xdigits == 8 && nptr[0] < '8')) {
- int value = 0;
- for (; nptr < end_xdigits_run; ++nptr) {
- value <<= 4;
- value += hex_digit_to_int(*nptr);
- }
- // Overflow past the last valid unicode codepoint
- // (0x10ffff) is converted to U+FFFD by FixUnicodeValue().
- return FixUnicodeValue(value);
- } else {
- // Overflow: can't fit in an int32;
- // returns the replacement character 0xFFFD.
- return 0xFFFD;
- }
-}
-
-// Unescape the current character pointed to by src. SETS the number
-// of chars read for the conversion (in UTF8). If src isn't a valid entity,
-// just consume the & and RETURN -1. If src doesn't point to & -- which it
-// should -- set src_consumed to 0 and RETURN -1.
-int ReadEntity(const char* src, int srcn, int* src_consumed) {
- const char* const srcend = src + srcn;
-
- if (srcn == 0 || *src != '&') { // input should start with an ampersand
- *src_consumed = 0;
- return -1;
- }
- *src_consumed = 1; // we'll get the & at least
-
- // The standards are a bit unclear on when an entity ends. Certainly a ";"
- // ends one, but spaces probably do too. We follow the lead of both IE and
- // Netscape, which as far as we can tell end numeric entities (1st case below)
- // at any non-digit, and end character entities (2nd case) at any non-alnum.
- const char* entstart, *entend; // where the entity starts and ends
- entstart = src + 1; // read past the &
- int entval; // UCS2 value of the entity
- if ( *entstart == '#' ) { // -- 1st case: numeric entity
- if ( entstart + 2 >= srcend ) {
- return -1; // no way a legitimate number could fit
- } else if ( entstart[1] == 'x' || entstart[1] == 'X' ) { // hex numeric
- entval = strto32_base16(entstart + 2, srcend, &entend);
- } else { // decimal numeric entity
- entval = strto32_base10(entstart+1, srcend, &entend);
- }
- if (entval == -1 || entend > srcend) {
- return -1; // not entirely correct, but close enough
- }
- } else { // -- 2nd case: character entity
- for (entend = entstart;
- entend < srcend && ascii_isalnum(*entend);
- ++entend ) {
- // entity consists of alphanumeric chars
- }
- entval = LookupEntity(entstart, entend - entstart);
- if (entval < 0) {
- return -1; // not a legal entity name
- }
- // Now we do a strange-seeming IE6-compatibility check: if entval is
- // >= 256, it *must* be followed by a semicolon or it's not considered
- // an entity. The problem is lots of the newfangled entity names, like
- // "lang", also occur in URL CGI arguments: "/search?q=test&lang=en".
- // When these links are written in HTML, it would be really bad if the
- // "&lang" were treated as an entity, which is what the spec says
- // *should* happen (even when the HTML is inside an "A HREF" tag!)
- // IE ignores the spec for these new, high-value entities, so we do too.
- if ( entval >= 256 && !(entend < srcend && *entend == ';') ) {
- return -1; // make non-;-terminated entity illegal
- }
- }
-
- // Finally, figure out how much src was consumed
- if ( entend < srcend && *entend == ';' ) {
- entend++; // standard says ; terminator is special
- }
- *src_consumed = entend - src;
- return entval;
-}
-
-
-// Src points to '&'
-// Writes entity value to dst. Returns take(src), put(dst) byte counts
-void EntityToBuffer(const char* src, int len, char* dst,
- int* tlen, int* plen) {
- char32 entval = ReadEntity(src, len, tlen);
-
- // ReadEntity does this already: entval = FixUnicodeValue(entval);
-
- // Convert UTF-32 to UTF-8
- if (entval > 0) {
- *plen = runetochar(dst, &entval);
- } else {
- // Illegal entity; ignore the '&'
- *tlen = 1;
- *plen = 0;
- }
-}
-
-// Returns true if character is < > or &, none of which are letters
-bool inline IsSpecial(char c) {
- // Comparison (int != 0) is used to silence the warning:
- // 'const char': forcing value to bool
- if ((c & 0xe0) == 0x20) {
- return (kSpecialSymbol[static_cast<uint8>(c)] != 0);
- }
- return false;
-}
-
-// Quick Skip to next letter or < > & or to end of string (eos)
-// Always return is_letter for eos
-int ScanToLetterOrSpecial(const char* src, int len) {
- int bytes_consumed;
- StringPiece str(src, len);
- UTF8GenericScan(&utf8scannot_lettermarkspecial_obj, str, &bytes_consumed);
- return bytes_consumed;
-}
-
-
-
-
-// src points to non-letter, such as tag-opening '<'
-// Return length from here to next possible letter
-// On another < before >, return 1
-// advances <tag>
-// | |
-// advances <tag> ... </tag> for <script> <style>
-// | |
-// advances <!-- ... <tag> ... -->
-// | |
-// advances <tag
-// | | end of string
-// advances <tag <tag2>
-// ||
-int ScanToPossibleLetter(const char* isrc, int len, int max_exit_state) {
- const uint8* src = reinterpret_cast<const uint8*>(isrc);
- const uint8* srclimit = src + len;
- const uint8* tagParseTbl = kTagParseTbl_0;
- int e = 0;
- while (src < srclimit) {
- e = tagParseTbl[kCharToSub[*src++]];
- if (e <= max_exit_state) {
- // We overshot by one byte
- --src;
- break;
- }
- tagParseTbl = &kTagParseTbl_0[e * 20];
- }
-
- if (src >= srclimit) {
- // We fell off the end of the text.
- // It looks like the most common case for this is a truncated file, not
- // mismatched angle brackets. So we pretend that the last char was '>'
- return len;
- }
-
- // OK to be in state 0 or state 2 at exit
- if ((e != 0) && (e != 2)) {
- // Error, '<' followed by '<'
- // We want to back up to first <, then advance by one byte past it
- int offset = src - reinterpret_cast<const uint8*>(isrc);
-
- // Backscan to first '<' and return enough length to just get past it
- --offset; // back up over the second '<', which caused us to stop
- while ((0 < offset) && (isrc[offset] != '<')) {
- // Find the first '<', which is unmatched
- --offset;
- }
- // skip to just beyond first '<'
- return offset + 1;
- }
-
- return src - reinterpret_cast<const uint8*>(isrc);
-}
-
-// Returns mid if key found in lo <= mid < hi, else -1
-int BinarySearch(const char* key, int lo, int hi, const CharIntPair* cipair) {
- // binary search
- while (lo < hi) {
- int mid = (lo + hi) >> 1;
- if (strcmp(key, cipair[mid].s) < 0) {
- hi = mid;
- } else if (strcmp(key, cipair[mid].s) > 0) {
- lo = mid + 1;
- } else {
- return mid;
- }
- }
- return -1;
-}
-
-// Returns the length in bytes of the prefix of src that is all
-// interchange valid UTF-8
-int SpanInterchangeValid(const char* src, int byte_length) {
- int bytes_consumed;
- const UTF8ReplaceObj* st = &utf8acceptinterchange_obj;
- StringPiece str(src, byte_length);
- UTF8GenericScan(st, str, &bytes_consumed);
- return bytes_consumed;
-}
-
-ScriptScanner::ScriptScanner(const char* buffer,
- int buffer_length,
- bool is_plain_text)
- : start_byte_(buffer),
- next_byte_(buffer),
- byte_length_(buffer_length),
- is_plain_text_(is_plain_text),
- letters_marks_only_(true),
- one_script_only_(true),
- exit_state_(kMaxExitStateLettersMarksOnly) {
- script_buffer_ = new char[kMaxScriptBuffer];
- script_buffer_lower_ = new char[kMaxScriptLowerBuffer];
- map2original_.Clear(); // map from script_buffer_ to buffer
- map2uplow_.Clear(); // map from script_buffer_lower_ to script_buffer_
-}
-
-// Extended version to allow spans of any non-tag text and spans of mixed script
-ScriptScanner::ScriptScanner(const char* buffer,
- int buffer_length,
- bool is_plain_text,
- bool any_text,
- bool any_script)
- : start_byte_(buffer),
- next_byte_(buffer),
- byte_length_(buffer_length),
- is_plain_text_(is_plain_text),
- letters_marks_only_(!any_text),
- one_script_only_(!any_script),
- exit_state_(any_text ? kMaxExitStateAllText : kMaxExitStateLettersMarksOnly) {
- script_buffer_ = new char[kMaxScriptBuffer];
- script_buffer_lower_ = new char[kMaxScriptLowerBuffer];
- map2original_.Clear(); // map from script_buffer_ to buffer
- map2uplow_.Clear(); // map from script_buffer_lower_ to script_buffer_
-}
-
-
-ScriptScanner::~ScriptScanner() {
- delete[] script_buffer_;
- delete[] script_buffer_lower_;
-}
-
-
-
-
-// Get to the first real non-tag letter or entity that is a letter
-// Sets script of that letter
-// Return len if no more letters
-int ScriptScanner::SkipToFrontOfSpan(const char* src, int len, int* script) {
- int sc = UNKNOWN_ULSCRIPT;
- int skip = 0;
- int tlen, plen;
-
- // Do run of non-letters (tag | &NL | NL)*
- tlen = 0;
- while (skip < len) {
- // Do fast scan to next interesting byte
- // int oldskip = skip;
- skip += ScanToLetterOrSpecial(src + skip, len - skip);
-
- // Check for no more letters/specials
- if (skip >= len) {
- // All done
- *script = sc;
- return len;
- }
-
- // We are at a letter, nonletter, tag, or entity
- if (IsSpecial(src[skip]) && !is_plain_text_) {
- if (src[skip] == '<') {
- // Begining of tag; skip to end and go around again
- tlen = ScanToPossibleLetter(src + skip, len - skip,
- exit_state_);
- sc = 0;
- } else if (src[skip] == '>') {
- // Unexpected end of tag; skip it and go around again
- tlen = 1; // Over the >
- sc = 0;
- } else if (src[skip] == '&') {
- // Expand entity, no advance
- char temp[4];
- EntityToBuffer(src + skip, len - skip,
- temp, &tlen, &plen);
- if (plen > 0) {
- sc = GetUTF8LetterScriptNum(temp);
- }
- }
- } else {
- // Update 1..4 bytes
- tlen = UTF8OneCharLen(src + skip);
- sc = GetUTF8LetterScriptNum(src + skip);
- }
- if (sc != 0) {break;} // Letter found
- skip += tlen; // Else advance
- }
-
- *script = sc;
- return skip;
-}
-
-
-// These are for ASCII-only tag names
-// Compare one letter uplow to c, ignoring case of uplowp
-inline bool EqCase(char uplow, char c) {
- return (uplow | 0x20) == c;
-}
-
-// These are for ASCII-only tag names
-// Return true for space / < > etc. all less than 0x40
-inline bool NeqLetter(char c) {
- return c < 0x40;
-}
-
-// These are for ASCII-only tag names
-// Return true for space \n false for \r
-inline bool WS(char c) {
- return (c == ' ') || (c == '\n');
-}
-
-// Canonical CR or LF
-static const char LF = '\n';
-
-
-// The naive loop scans from next_byte_ to script_buffer_ until full.
-// But this can leave an awkward hard-to-identify short fragment at the
-// end of the input. We would prefer to make the next-to-last fragment
-// shorter and the last fragment longer.
-
-// Copy next run of non-tag characters to buffer [NUL terminated]
-// This just replaces tags with space or \n and removes entities.
-// Tags <br> <p> and <tr> are replaced with \n. Non-letter sequences
-// including \r or \n are replaced by \n. All other tags and skipped text
-// are replaced with ASCII space.
-//
-// Buffer ALWAYS has leading space and trailing space space space NUL
-bool ScriptScanner::GetOneTextSpan(LangSpan* span) {
- span->text = script_buffer_;
- span->text_bytes = 0;
- span->offset = next_byte_ - start_byte_;
- span->ulscript = UNKNOWN_ULSCRIPT;
- span->truncated = false;
-
- int put_soft_limit = kMaxScriptBytes - kWithinScriptTail;
- if ((kMaxScriptBytes <= byte_length_) &&
- (byte_length_ < (2 * kMaxScriptBytes))) {
- // Try to split the last two fragments in half
- put_soft_limit = byte_length_ / 2;
- }
-
- script_buffer_[0] = ' '; // Always a space at front of output
- script_buffer_[1] = '\0';
- int take = 0;
- int put = 1; // Start after the initial space
- int tlen = 0, plen = 0;
-
- if (byte_length_ <= 0) {
- return false; // No more text to be found
- }
-
- // Go over alternating spans of text and tags,
- // copying letters to buffer with single spaces for each run of non-letters
- bool last_byte_was_space = false;
- while (take < byte_length_) {
- char c = next_byte_[take];
- if (c == '\r') {c = LF;} // Canonical CR or LF
- if (c == '\n') {c = LF;} // Canonical CR or LF
-
- if (IsSpecial(c) && !is_plain_text_) {
- if (c == '<') {
- // Replace tag with space
- c = ' '; // for almost-full test below
- // or if <p> <br> <tr>, replace with \n
- if (take < (byte_length_ - 3)) {
- if (EqCase(next_byte_[take + 1], 'p') &&
- NeqLetter(next_byte_[take + 2])) {
- c = LF;
- }
- if (EqCase(next_byte_[take + 1], 'b') &&
- EqCase(next_byte_[take + 2], 'r') &&
- NeqLetter(next_byte_[take + 3])) {
- c = LF;
- }
- if (EqCase(next_byte_[take + 1], 't') &&
- EqCase(next_byte_[take + 2], 'r') &&
- NeqLetter(next_byte_[take + 3])) {
- c = LF;
- }
- }
- // Begining of tag; skip to end and go around again
- tlen = 1 + ScanToPossibleLetter(next_byte_ + take, byte_length_ - take,
- exit_state_);
- // Copy one byte, compressing spaces
- if (!last_byte_was_space || !WS(c)) {
- script_buffer_[put++] = c; // Advance dest
- last_byte_was_space = WS(c);
- }
- } else if (c == '>') {
- // Unexpected end of tag; copy it and go around again
- tlen = 1; // Over the >
- script_buffer_[put++] = c; // Advance dest
- } else if (c == '&') {
- // Expand entity, no advance
- EntityToBuffer(next_byte_ + take, byte_length_ - take,
- script_buffer_ + put, &tlen, &plen);
- put += plen; // Advance dest
- }
- take += tlen; // Advance source
- } else {
- // Copy one byte, compressing spaces
- if (!last_byte_was_space || !WS(c)) {
- script_buffer_[put++] = c; // Advance dest
- last_byte_was_space = WS(c);
- }
- ++take; // Advance source
- }
-
- if (WS(c) &&
- (put >= put_soft_limit)) {
- // Buffer is almost full
- span->truncated = true;
- break;
- }
- if (put >= kMaxScriptBytes) {
- // Buffer is completely full
- span->truncated = true;
- break;
- }
- }
-
- // Almost done. Back up to a character boundary if needed
- while ((0 < take) && ((next_byte_[take] & 0xc0) == 0x80)) {
- // Back up over continuation byte
- --take;
- --put;
- }
-
- // Update input position
- next_byte_ += take;
- byte_length_ -= take;
-
- // Put four more spaces/NUL. Worst case is abcd _ _ _ \0
- // kMaxScriptBytes | | put
- script_buffer_[put + 0] = ' ';
- script_buffer_[put + 1] = ' ';
- script_buffer_[put + 2] = ' ';
- script_buffer_[put + 3] = '\0';
-
- span->text_bytes = put; // Does not include the last four chars above
- return true;
-}
-
-
-// Copy next run of same-script non-tag letters to buffer [NUL terminated]
-// Buffer ALWAYS has leading space and trailing space space space NUL
-bool ScriptScanner::GetOneScriptSpan(LangSpan* span) {
- if (!letters_marks_only_) {
- // Return non-tag text, including punctuation and digits
- return GetOneTextSpan(span);
- }
-
- span->text = script_buffer_;
- span->text_bytes = 0;
- span->offset = next_byte_ - start_byte_;
- span->ulscript = UNKNOWN_ULSCRIPT;
- span->truncated = false;
-
- // struct timeval script_start, script_mid, script_end;
-
- int put_soft_limit = kMaxScriptBytes - kWithinScriptTail;
- if ((kMaxScriptBytes <= byte_length_) &&
- (byte_length_ < (2 * kMaxScriptBytes))) {
- // Try to split the last two fragments in half
- put_soft_limit = byte_length_ / 2;
- }
-
-
- int spanscript; // The script of this span
- int sc = UNKNOWN_ULSCRIPT; // The script of next character
- int tlen = 0;
- int plen = 0;
-
- script_buffer_[0] = ' '; // Always a space at front of output
- script_buffer_[1] = '\0';
- int take = 0;
- int put = 1; // Start after the initial space
-
- // Build offsets from span->text back to start_byte_ + span->offset
- // This mapping reflects deletion of non-letters, expansion of
- // entities, etc.
- map2original_.Clear();
- map2original_.Delete(span->offset); // So that MapBack(0) gives offset
-
- // Get to the first real non-tag letter or entity that is a letter
- int skip = SkipToFrontOfSpan(next_byte_, byte_length_, &spanscript);
- next_byte_ += skip;
- byte_length_ -= skip;
-
- if (skip != 1) {
- map2original_.Delete(skip);
- map2original_.Insert(1);
- } else {
- map2original_.Copy(1);
- }
- if (byte_length_ <= 0) {
- map2original_.Reset();
- return false; // No more letters to be found
- }
-
- // There is at least one letter, so we know the script for this span
- span->ulscript = (ULScript)spanscript;
-
-
- // Go over alternating spans of same-script letters and non-letters,
- // copying letters to buffer with single spaces for each run of non-letters
- while (take < byte_length_) {
- // Copy run of letters in same script (&LS | LS)*
- int letter_count = 0; // Keep track of word length
- bool need_break = false;
-
- while (take < byte_length_) {
- // We are at a letter, nonletter, tag, or entity
- if (IsSpecial(next_byte_[take]) && !is_plain_text_) {
- if (next_byte_[take] == '<') {
- // Begining of tag
- sc = 0;
- break;
- } else if (next_byte_[take] == '>') {
- // Unexpected end of tag
- sc = 0;
- break;
- } else if (next_byte_[take] == '&') {
- // Copy entity, no advance
- EntityToBuffer(next_byte_ + take, byte_length_ - take,
- script_buffer_ + put, &tlen, &plen);
- if (plen > 0) {
- sc = GetUTF8LetterScriptNum(script_buffer_ + put);
- }
- }
- } else {
- // Real letter, safely copy up to 4 bytes, increment by 1..4
- // Will update by 1..4 bytes at Advance, below
- tlen = plen = UTF8OneCharLen(next_byte_ + take);
- if (take < (byte_length_ - 3)) {
- // X86 fast case, does unaligned load/store
- UNALIGNED_STORE32(script_buffer_ + put,
- UNALIGNED_LOAD32(next_byte_ + take));
-
- } else {
- // Slow case, happens 1-3 times per input document
- memcpy(script_buffer_ + put, next_byte_ + take, plen);
- }
- sc = GetUTF8LetterScriptNum(next_byte_ + take);
- }
-
- // Allow continue across a single letter in a different script:
- // A B D = three scripts, c = common script, i = inherited script,
- // - = don't care, ( = take position before the += below
- // AAA(A- continue
- //
- // AAA(BA continue
- // AAA(BB break
- // AAA(Bc continue (breaks after B)
- // AAA(BD break
- // AAA(Bi break
- //
- // AAA(c- break
- //
- // AAA(i- continue
- //
-
- if ((sc != spanscript) && (sc != ULScript_Inherited)) {
- // Might need to break this script span
- if (sc == ULScript_Common) {
- need_break = true;
- } else {
- // Look at next following character, ignoring entity as Common
- int sc2 = GetUTF8LetterScriptNum(next_byte_ + take + tlen);
- if ((sc2 != ULScript_Common) && (sc2 != spanscript)) {
- // We found a non-trivial change of script
- if (one_script_only_) {
- need_break = true;
- }
- }
- }
- }
- if (need_break) {break;} // Non-letter or letter in wrong script
-
- take += tlen; // Advance
- put += plen; // Advance
-
- // Update the offset map to reflect take/put lengths
- if (tlen == plen) {
- map2original_.Copy(tlen);
- } else if (tlen < plen) {
- map2original_.Copy(tlen);
- map2original_.Insert(plen - tlen);
- } else { // plen < tlen
- map2original_.Copy(plen);
- map2original_.Delete(tlen - plen);
- }
-
- ++letter_count;
- if (put >= kMaxScriptBytes) {
- // Buffer is full
- span->truncated = true;
- break;
- }
- } // End while letters
-
- // Do run of non-letters (tag | &NL | NL)*
- while (take < byte_length_) {
- // Do fast scan to next interesting byte
- tlen = ScanToLetterOrSpecial(next_byte_ + take, byte_length_ - take);
- take += tlen;
- map2original_.Delete(tlen);
- if (take >= byte_length_) {break;} // Might have scanned to end
-
- // We are at a letter, nonletter, tag, or entity
- if (IsSpecial(next_byte_[take]) && !is_plain_text_) {
- if (next_byte_[take] == '<') {
- // Begining of tag; skip to end and go around again
- tlen = ScanToPossibleLetter(next_byte_ + take, byte_length_ - take,
- exit_state_);
- sc = 0;
- } else if (next_byte_[take] == '>') {
- // Unexpected end of tag; skip it and go around again
- tlen = 1; // Over the >
- sc = 0;
- } else if (next_byte_[take] == '&') {
- // Expand entity, no advance
- EntityToBuffer(next_byte_ + take, byte_length_ - take,
- script_buffer_ + put, &tlen, &plen);
- if (plen > 0) {
- sc = GetUTF8LetterScriptNum(script_buffer_ + put);
- }
- }
- } else {
- // Update 1..4
- tlen = UTF8OneCharLen(next_byte_ + take);
- sc = GetUTF8LetterScriptNum(next_byte_ + take);
- }
- if (sc != 0) {break;} // Letter found
- take += tlen; // Else advance
- map2original_.Delete(tlen);
- } // End while not-letters
-
- script_buffer_[put++] = ' ';
- map2original_.Insert(1);
-
- // Letter in wrong script ?
- if ((sc != spanscript) && (sc != ULScript_Inherited)) {break;}
- if (put >= put_soft_limit) {
- // Buffer is almost full
- span->truncated = true;
- break;
- }
- }
-
- // Almost done. Back up to a character boundary if needed
- while ((0 < take) && (take < byte_length_) &&
- ((next_byte_[take] & 0xc0) == 0x80)) {
- // Back up over continuation byte
- --take;
- --put;
- }
-
- // Update input position
- next_byte_ += take;
- byte_length_ -= take;
-
- // Put four more spaces/NUL. Worst case is abcd _ _ _ \0
- // kMaxScriptBytes | | put
- script_buffer_[put + 0] = ' ';
- script_buffer_[put + 1] = ' ';
- script_buffer_[put + 2] = ' ';
- script_buffer_[put + 3] = '\0';
- map2original_.Insert(4);
- map2original_.Reset();
-
- span->text_bytes = put; // Does not include the last four chars above
- return true;
-}
-
-// Force Latin, Cyrillic, Armenian, Greek scripts to be lowercase
-// List changes with each version of Unicode, so just always lowercase
-// Unicode 6.2.0:
-// ARMENIAN COPTIC CYRILLIC DESERET GEORGIAN GLAGOLITIC GREEK LATIN
-void ScriptScanner::LowerScriptSpan(LangSpan* span) {
- // If needed, lowercase all the text. If we do it sooner, might miss
- // lowercasing an entity such as &Aacute;
- // We only need to do this for Latn and Cyrl scripts
- map2uplow_.Clear();
- // Full Unicode lowercase of the entire buffer, including
- // four pad bytes off the end.
- // Ahhh. But the last byte 0x00 is not interchange-valid, so we do 3 pad
- // bytes and put the 0x00 in explicitly.
- // Build an offset map from script_buffer_lower_ back to script_buffer_
- int consumed, filled, changed;
- StringPiece istr(span->text, span->text_bytes + 3);
- StringPiece ostr(script_buffer_lower_, kMaxScriptLowerBuffer);
-
- UTF8GenericReplace(&utf8repl_lettermarklower_obj,
- istr, ostr, is_plain_text_,
- &consumed, &filled, &changed, &map2uplow_);
- script_buffer_lower_[filled] = '\0';
- span->text = script_buffer_lower_;
- span->text_bytes = filled - 3;
- map2uplow_.Reset();
-}
-
-// Copy next run of same-script non-tag letters to buffer [NUL terminated]
-// Force Latin, Cyrillic, Greek scripts to be lowercase
-// Buffer ALWAYS has leading space and trailing space space space NUL
-bool ScriptScanner::GetOneScriptSpanLower(LangSpan* span) {
- bool ok = GetOneScriptSpan(span);
- if (ok) {
- LowerScriptSpan(span);
- }
- return ok;
-}
-
-// Maps byte offset in most recent GetOneScriptSpan/Lower
-// span->text [0..text_bytes] into an additional byte offset from
-// span->offset, to get back to corresponding text in the original
-// input buffer.
-// text_offset must be the first byte
-// of a UTF-8 character, or just beyond the last character. Normally this
-// routine is called with the first byte of an interesting range and
-// again with the first byte of the following range.
-int ScriptScanner::MapBack(int text_offset) {
- return map2original_.MapBack(map2uplow_.MapBack(text_offset));
-}
-
-
-// Gets lscript number for letters; always returns
-// 0 (common script) for non-letters
-int GetUTF8LetterScriptNum(const char* src) {
- int srclen = UTF8OneCharLen(src);
- const uint8* usrc = reinterpret_cast<const uint8*>(src);
- return UTF8GenericPropertyTwoByte(&utf8prop_lettermarkscriptnum_obj,
- &usrc, &srclen);
-}
-
-} // namespace CLD2
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/script_span/getonescriptspan.h b/chromium/third_party/cld_3/src/src/script_span/getonescriptspan.h
deleted file mode 100644
index 1fa60adad46..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/getonescriptspan.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Author: dsites@google.com (Dick Sites)
-//
-
-
-#ifndef SCRIPT_SPAN_GETONESCRIPTSPAN_H_
-#define SCRIPT_SPAN_GETONESCRIPTSPAN_H_
-
-#include "generated_ulscript.h"
-#include "integral_types.h"
-#include "offsetmap.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-static const int kMaxScriptBuffer = 40960;
-static const int kMaxScriptLowerBuffer = (kMaxScriptBuffer * 3) / 2;
-static const int kMaxScriptBytes = kMaxScriptBuffer - 32; // Leave some room
-static const int kWithinScriptTail = 32; // Stop at word space in last
- // N bytes of script buffer
-
-typedef struct {
- char* text = nullptr; // Pointer to the span, somewhere
- int text_bytes = 0; // Number of bytes of text in the span
- int offset = 0; // Offset of start of span in original input buffer
- ULScript ulscript = UNKNOWN_ULSCRIPT; // Unicode Letters Script of this span
- bool truncated = false; // true if buffer filled up before a
- // different script or EOF was found
-} LangSpan;
-
-static inline bool IsContinuationByte(char c) {
- return static_cast<signed char>(c) < -64;
-}
-
-// Gets lscript number for letters; always returns
-// 0 (common script) for non-letters
-int GetUTF8LetterScriptNum(const char* src);
-
-// Update src pointer to point to next quadgram, +2..+5
-// Looks at src[0..4]
-const char* AdvanceQuad(const char* src);
-
-// Utility routine to search alphabetical tables
-int BinarySearch(const char* key, int lo, int hi, const CharIntPair* cipair);
-
-// Returns the length in bytes of the prefix of src that is all
-// interchange valid UTF-8
-int SpanInterchangeValid(const char* src, int byte_length);
-
-class ScriptScanner {
- public:
- ScriptScanner(const char* buffer, int buffer_length, bool is_plain_text);
- ScriptScanner(const char* buffer, int buffer_length, bool is_plain_text,
- bool any_text, bool any_script);
- ~ScriptScanner();
-
- // Copy next run of same-script non-tag letters to buffer [NUL terminated]
- bool GetOneScriptSpan(LangSpan* span);
-
- // Force Latin and Cyrillic scripts to be lowercase
- void LowerScriptSpan(LangSpan* span);
-
- // Copy next run of same-script non-tag letters to buffer [NUL terminated]
- // Force Latin and Cyrillic scripts to be lowercase
- bool GetOneScriptSpanLower(LangSpan* span);
-
- // Copy next run of non-tag characters to buffer [NUL terminated]
- // This just removes tags and removes entities
- // Buffer has leading space
- bool GetOneTextSpan(LangSpan* span);
-
- // Maps byte offset in most recent GetOneScriptSpan/Lower
- // span->text [0..text_bytes] into an additional byte offset from
- // span->offset, to get back to corresponding text in the original
- // input buffer.
- // text_offset must be the first byte
- // of a UTF-8 character, or just beyond the last character. Normally this
- // routine is called with the first byte of an interesting range and
- // again with the first byte of the following range.
- int MapBack(int text_offset);
-
- const char* GetBufferStart() {return start_byte_;};
-
- private:
- // Skip over tags and non-letters
- int SkipToFrontOfSpan(const char* src, int len, int* script);
-
- const char* start_byte_; // Starting byte of buffer to scan
- const char* next_byte_; // First unscanned byte
- int byte_length_; // Bytes left
-
- bool is_plain_text_; // true fo text, false for HTML
- char* script_buffer_; // Holds text with expanded entities
- char* script_buffer_lower_; // Holds lowercased text
- bool letters_marks_only_; // To distinguish scriptspan of one
- // letters/marks vs. any mixture of text
- bool one_script_only_; // To distinguish scriptspan of one
- // script vs. any mixture of scripts
- int exit_state_; // For tag parser kTagParseTbl_0, based
- // on letters_marks_only_
- public :
- // Expose for debugging
- OffsetMap map2original_; // map from script_buffer_ to buffer
- OffsetMap map2uplow_; // map from script_buffer_lower_ to script_buffer_
-};
-
-} // namespace CLD2
-} // namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_GETONESCRIPTSPAN_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/getonescriptspan_test.cc b/chromium/third_party/cld_3/src/src/script_span/getonescriptspan_test.cc
deleted file mode 100644
index cb22921f31d..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/getonescriptspan_test.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "getonescriptspan.h"
-
-#include <iostream>
-#include <vector>
-
-namespace chrome_lang_id {
-namespace CLD2 {
-namespace getonescriptspan_test {
-
-// Tests invalid and interchange-invalid input. Returns "true" if the test is
-// successful and "false" otherwise.
-bool TestInvalidUTF8Input() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
- const std::vector<std::string> invalid_strings{"\xC0\xA9",
- "\377\377\377\377"};
- const std::string gold_valid_prefix = "Some valid bytes followed by ";
-
- // Iterates over the invalid strings, inserts each of them in the middle of a
- // piece of text, and checks whether these strings are correctly identified.
- bool test_successful = true;
- for (size_t i = 0; i < invalid_strings.size(); ++i) {
- const std::string text = "Some valid bytes followed by " +
- invalid_strings.at(i) +
- " and then valid ones again.";
-
- const int num_valid_bytes = SpanInterchangeValid(text.c_str(), text.size());
- const std::string detected_valid_prefix(text.c_str(), num_valid_bytes);
- std::cout << " Testing input string at position " << i << std::endl;
- if (detected_valid_prefix == gold_valid_prefix) {
- std::cout << " Success!" << std::endl;
- } else {
- std::cout << " Failure" << std::endl;
- std::cout << " Gold: " << gold_valid_prefix << std::endl;
- std::cout << " Detected: " << detected_valid_prefix << std::endl;
- test_successful = false;
- }
- }
- return test_successful;
-}
-
-// Tests whether different scripts are correctly detected. Returns "true" if the
-// test is successful and "false" otherwise.
-bool TestScriptDetection() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- // Text containing a snippet in English, a snippet in Bulgarian, and a snippet
- // in English again.
- const std::string text =
- "Text in English. Текст на Български. Also text in English.";
- const std::vector<std::string> gold_script_spans{
- " Text in English ", " Текст на Български ", " Also text in English "};
-
- std::vector<std::string> detected_script_spans;
- ScriptScanner ss(text.c_str(), text.size(), /*is_plain_text=*/true);
- LangSpan script_span;
- while (ss.GetOneScriptSpan(&script_span)) {
- detected_script_spans.emplace_back(script_span.text,
- script_span.text_bytes);
- }
-
- if (detected_script_spans.size() != gold_script_spans.size()) {
- std::cout << " Failure" << std::endl;
- std::cout << " Number of gold spans " << gold_script_spans.size()
- << std::endl;
- std::cout << " Number of detected spans " << detected_script_spans.size()
- << std::endl;
- return false;
- }
- for (size_t i = 0; i < detected_script_spans.size(); ++i) {
- if (detected_script_spans.at(i) != gold_script_spans.at(i)) {
- std::cout << " Failure" << std::endl;
- std::cout << " Gold span: " << gold_script_spans.at(i) << std::endl;
- std::cout << " Detected span: " << detected_script_spans.at(i)
- << std::endl;
- return false;
- }
- }
- std::cout << " Success!" << std::endl;
- return true;
-}
-
-// Tests the case when the input string is truncated in such a way that a
-// character is split in two pieces. Returns "true" if the test is successful
-// and "false" otherwise.
-bool TestStringCut() {
- std::cout << "Running " << __FUNCTION__ << std::endl;
-
- // Text in Bulgarian (Cyrillic script).
- const std::string text = "Текст на Български";
-
- // The size of the first two words ("Текст на ") is 16, and size of the first
- // two words plus the first char of the third word ("Текст на Б") is 18, so a
- // threshold of 17 results in slicing the first char of the third word.
- const int first_two_words_size = 16;
- const int span_size = 17;
- const int num_valid_bytes = SpanInterchangeValid(text.c_str(), span_size);
- if (num_valid_bytes == first_two_words_size) {
- std::cout << " Success!" << std::endl;
- return true;
- } else {
- std::cout << " Failure" << std::endl;
- std::cout << " Size of gold interchange-valid span: "
- << first_two_words_size << std::endl;
- std::cout << " Size of detected span: " << num_valid_bytes << std::endl;
- return false;
- }
-}
-
-} // namespace getonescriptspan_test
-} // namespace CLD2
-} // namespace chrome_lang_id
-
-// Runs the functions above.
-int main(int argc, char **argv) {
- const bool tests_successful =
- chrome_lang_id::CLD2::getonescriptspan_test::TestInvalidUTF8Input() &&
- chrome_lang_id::CLD2::getonescriptspan_test::TestScriptDetection() &&
- chrome_lang_id::CLD2::getonescriptspan_test::TestStringCut();
- return tests_successful ? 0 : 1;
-}
diff --git a/chromium/third_party/cld_3/src/src/script_span/integral_types.h b/chromium/third_party/cld_3/src/src/script_span/integral_types.h
deleted file mode 100644
index 0845579715d..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/integral_types.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SCRIPT_SPAN_INTEGRAL_TYPES_H_
-#define SCRIPT_SPAN_INTEGRAL_TYPES_H_
-
-// Cheap version
-namespace chrome_lang_id {
-namespace CLD2 {
-
-typedef unsigned char uint8;
-typedef unsigned short uint16;
-typedef unsigned int uint32;
-typedef unsigned long long int uint64;
-
-typedef signed char int8;
-typedef signed short int16;
-typedef signed int int32;
-typedef signed long long int int64;
-
-typedef int32 char32;
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_INTEGRAL_TYPES_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/offsetmap.cc b/chromium/third_party/cld_3/src/src/script_span/offsetmap.cc
deleted file mode 100644
index 639fbe16d49..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/offsetmap.cc
+++ /dev/null
@@ -1,478 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Author: dsites@google.com (Dick Sites)
-//
-//
-
-#include "offsetmap.h"
-
-#include <string.h> // for strcmp
-#include <algorithm> // for min
-
-using namespace std;
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-// Constructor, destructor
-OffsetMap::OffsetMap() {
- Clear();
-}
-
-OffsetMap::~OffsetMap() {
-}
-
-// Clear the map
-// After:
-// next_diff_sub_ is 0
-// Windows are the a and a' ranges covered by diffs_[next_diff_sub_-1]
-// which is a fake range of width 0 mapping 0=>0
-void OffsetMap::Clear() {
- diffs_.clear();
- pending_op_ = COPY_OP;
- pending_length_ = 0;
- next_diff_sub_ = 0;
- current_lo_aoffset_ = 0;
- current_hi_aoffset_ = 0;
- current_lo_aprimeoffset_ = 0;
- current_hi_aprimeoffset_ = 0;
- current_diff_ = 0;
- max_aoffset_ = 0; // Largest seen so far
- max_aprimeoffset_ = 0; // Largest seen so far
-}
-
-static inline char OpPart(const char c) {
- return (c >> 6) & 3;
-}
-static inline char LenPart(const char c) {
- return c & 0x3f;
-}
-
-// Reset to offset 0
-void OffsetMap::Reset() {
- MaybeFlushAll();
-
- next_diff_sub_ = 0;
- current_lo_aoffset_ = 0;
- current_hi_aoffset_ = 0;
- current_lo_aprimeoffset_ = 0;
- current_hi_aprimeoffset_ = 0;
- current_diff_ = 0;
-}
-
-// Add to mapping from A to A', specifying how many next bytes are
-// identical in A and A'
-void OffsetMap::Copy(int bytes) {
- if (bytes == 0) {return;}
- max_aoffset_ += bytes; // Largest seen so far
- max_aprimeoffset_ += bytes; // Largest seen so far
- if (pending_op_ == COPY_OP) {
- pending_length_ += bytes;
- } else {
- Flush();
- pending_op_ = COPY_OP;
- pending_length_ = bytes;
- }
-}
-
-// Add to mapping from A to A', specifying how many next bytes are
-// inserted in A' while not advancing in A at all
-void OffsetMap::Insert(int bytes){
- if (bytes == 0) {return;}
- max_aprimeoffset_ += bytes; // Largest seen so far
- if (pending_op_ == INSERT_OP) {
- pending_length_ += bytes;
- } else if ((bytes == 1) &&
- (pending_op_ == DELETE_OP) && (pending_length_ == 1)) {
- // Special-case exactly delete(1) insert(1) +> copy(1);
- // all others backmap inserts to after deletes
- pending_op_ = COPY_OP;
- } else {
- Flush();
- pending_op_ = INSERT_OP;
- pending_length_ = bytes;
- }
-}
-
-// Add to mapping from A to A', specifying how many next bytes are
-// deleted from A while not advancing in A' at all
-void OffsetMap::Delete(int bytes){
- if (bytes == 0) {return;}
- max_aoffset_ += bytes; // Largest seen so far
- if (pending_op_ == DELETE_OP) {
- pending_length_ += bytes;
- } else if ((bytes == 1) &&
- (pending_op_ == INSERT_OP) && (pending_length_ == 1)) {
- // Special-case exactly insert(1) delete(1) => copy(1);
- // all others backmap deletes to after insertss
- pending_op_ = COPY_OP;
- } else {
- Flush();
- pending_op_ = DELETE_OP;
- pending_length_ = bytes;
- }
-}
-
-void OffsetMap::Flush() {
- if (pending_length_ == 0) {
- return;
- }
- // We may be emitting a copy op just after a copy op because +1 -1 cancelled
- // inbetween. If the lengths don't need a prefix byte, combine them
- if ((pending_op_ == COPY_OP) && !diffs_.empty()) {
- char c = diffs_[diffs_.size() - 1];
- MapOp prior_op = static_cast<MapOp>(OpPart(c));
- int prior_len = LenPart(c);
- if ((prior_op == COPY_OP) && ((prior_len + pending_length_) <= 0x3f)) {
- diffs_[diffs_.size() - 1] += pending_length_;
- pending_length_ = 0;
- return;
- }
- }
- if (pending_length_ > 0x3f) {
- bool non_zero_emitted = false;
- for (int shift = 30; shift > 0; shift -= 6) {
- int prefix = (pending_length_ >> shift) & 0x3f;
- if ((prefix > 0) || non_zero_emitted) {
- Emit(PREFIX_OP, prefix);
- non_zero_emitted = true;
- }
- }
- }
- Emit(pending_op_, pending_length_ & 0x3f);
- pending_length_ = 0;
-}
-
-
-// Add one more entry to copy one byte off the end, then flush
-void OffsetMap::FlushAll() {
- Copy(1);
- Flush();
-}
-
-// Flush all if necessary
-void OffsetMap::MaybeFlushAll() {
- if ((0 < pending_length_) || diffs_.empty()) {
- FlushAll();
- }
-}
-
-// Len may be 0, for example as the low piece of length=64
-void OffsetMap::Emit(MapOp op, int len) {
- char c = (static_cast<char>(op) << 6) | (len & 0x3f);
- diffs_.push_back(c);
-}
-
-//----------------------------------------------------------------------------//
-// The guts of the 2013 design //
-// If there are three ranges a b c in diffs_, we can be in one of five //
-// states: LEFT of a, in ranges a b c, or RIGHT of c //
-// In each state, there are windows A[Alo..Ahi), A'[A'lo..A'hi) and diffs_ //
-// position next_diff_sub_ //
-// There also are mapping constants max_aoffset_ and max_aprimeoffset_ //
-// If LEFT, Alo=Ahi=0, A'lo=A'hi=0 and next_diff_sub_=0 //
-// If RIGHT, Alo=Ahi=max_aoffset_, A'lo=A'hi=max_aprimeoffset_ and //
-// next_diff_sub_=diffs_.size() //
-// Otherwise, at least one of A[) and A'[) is non-empty and the first bytes //
-// correspond to each other. If range i is active, next_diff_sub_ is at //
-// the first byte of range i+1. Because of the length-prefix operator, //
-// an individual range item in diffs_ may be multiple bytes //
-// In all cases aprimeoffset = aoffset + current_diff_ //
-// i.e. current_diff_ = aprimeoffset - aoffset //
-// //
-// In the degenerate case of diffs_.empty(), there are only two states //
-// LEFT and RIGHT and the mapping is the identity mapping. //
-// The initial state is LEFT. //
-// It is an error to move left into LEFT or right into RIGHT, but the code //
-// below is robust in these cases. //
-//----------------------------------------------------------------------------//
-
-void OffsetMap::SetLeft() {
- current_lo_aoffset_ = 0;
- current_hi_aoffset_ = 0;
- current_lo_aprimeoffset_ = 0;
- current_hi_aprimeoffset_ = 0;
- current_diff_ = 0;
- next_diff_sub_ = 0;
-}
-
-void OffsetMap::SetRight() {
- current_lo_aoffset_ = max_aoffset_;
- current_hi_aoffset_ = max_aoffset_;
- current_lo_aprimeoffset_ = max_aprimeoffset_;
- current_hi_aprimeoffset_ = max_aprimeoffset_;
- current_diff_ = max_aprimeoffset_ - max_aoffset_;
- next_diff_sub_ = 0;
-}
-
-// Back up over previous range, 1..5 bytes
-// Return subscript at the beginning of that. Pins at 0
-int OffsetMap::Backup(int sub) {
- if (sub <= 0) {return 0;}
- --sub;
- while ((0 < sub) &&
- (static_cast<MapOp>(OpPart(diffs_[sub - 1]) == PREFIX_OP))) {
- --sub;
- }
- return sub;
-}
-
-// Parse next range, 1..5 bytes
-// Return subscript just off the end of that
-int OffsetMap::ParseNext(int sub, MapOp* op, int* length) {
- *op = PREFIX_OP;
- *length = 0;
- char c;
- while ((sub < static_cast<int>(diffs_.size())) && (*op == PREFIX_OP)) {
- c = diffs_[sub++];
- *op = static_cast<MapOp>(OpPart(c));
- int len = LenPart(c);
- *length = (*length << 6) + len;
- }
- // If mal-formed or in RIGHT, this will return with op = PREFIX_OP
- // Mal-formed can include a trailing prefix byte with no following op
- return sub;
-}
-
-// Parse previous range, 1..5 bytes
-// Return current subscript
-int OffsetMap::ParsePrevious(int sub, MapOp* op, int* length) {
- sub = Backup(sub);
- return ParseNext(sub, op, length);
-}
-
-// Move active window one range to the right
-// Return true if move was OK
-bool OffsetMap::MoveRight() {
- // If at last range or RIGHT, set to RIGHT, return error
- if (next_diff_sub_ >= static_cast<int>(diffs_.size())) {
- SetRight();
- return false;
- }
- // Actually OK to move right
- MapOp op;
- int length;
- bool retval = true;
- // If mal-formed or in RIGHT, this will return with op = PREFIX_OP
- next_diff_sub_ = ParseNext(next_diff_sub_, &op, &length);
-
- current_lo_aoffset_ = current_hi_aoffset_;
- current_lo_aprimeoffset_ = current_hi_aprimeoffset_;
- if (op == COPY_OP) {
- current_hi_aoffset_ = current_lo_aoffset_ + length;
- current_hi_aprimeoffset_ = current_lo_aprimeoffset_ + length;
- } else if (op == INSERT_OP) {
- current_hi_aoffset_ = current_lo_aoffset_ + 0;
- current_hi_aprimeoffset_ = current_lo_aprimeoffset_ + length;
- } else if (op == DELETE_OP) {
- current_hi_aoffset_ = current_lo_aoffset_ + length;
- current_hi_aprimeoffset_ = current_lo_aprimeoffset_ + 0;
- } else {
- SetRight();
- retval = false;
- }
- current_diff_ = current_lo_aprimeoffset_ - current_lo_aoffset_;
- return retval;
-}
-
-// Move active window one range to the left
-// Return true if move was OK
-bool OffsetMap::MoveLeft() {
- // If at first range or LEFT, set to LEFT, return error
- if (next_diff_sub_ <= 0) {
- SetLeft();
- return false;
- }
- // Back up over current active window
- next_diff_sub_ = Backup(next_diff_sub_);
- if (next_diff_sub_ <= 0) {
- SetLeft();
- return false;
- }
- // Actually OK to move left
- MapOp op;
- int length;
-
- // TODO(abakalov): 'retval' below is set but not used, which is suspicious.
- // Did the authors mean to return this variable, analogously to MoveRight()?
- // bool retval = true;
- // If mal-formed or in LEFT, this will return with op = PREFIX_OP
- next_diff_sub_ = ParsePrevious(next_diff_sub_, &op, &length);
-
- current_hi_aoffset_ = current_lo_aoffset_;
- current_hi_aprimeoffset_ = current_lo_aprimeoffset_;
- if (op == COPY_OP) {
- current_lo_aoffset_ = current_hi_aoffset_ - length;
- current_lo_aprimeoffset_ = current_hi_aprimeoffset_ - length;
- } else if (op == INSERT_OP) {
- current_lo_aoffset_ = current_hi_aoffset_ - 0;
- current_lo_aprimeoffset_ = current_hi_aprimeoffset_ - length;
- } else if (op == DELETE_OP) {
- current_lo_aoffset_ = current_hi_aoffset_ - length;
- current_lo_aprimeoffset_ = current_hi_aprimeoffset_ - 0;
- } else {
- SetLeft();
- // retval = false;
- }
- current_diff_ = current_lo_aprimeoffset_ - current_lo_aoffset_;
- return true;
-}
-
-// Map an offset in A' to the corresponding offset in A
-int OffsetMap::MapBack(int aprimeoffset){
- MaybeFlushAll();
- if (aprimeoffset < 0) {return 0;}
- if (max_aprimeoffset_ <= aprimeoffset) {
- return (aprimeoffset - max_aprimeoffset_) + max_aoffset_;
- }
-
- // If current_lo_aprimeoffset_ <= aprimeoffset < current_hi_aprimeoffset_,
- // use current mapping, else move window left/right
- bool ok = true;
- while (ok && (aprimeoffset < current_lo_aprimeoffset_)) {
- ok = MoveLeft();
- }
- while (ok && (current_hi_aprimeoffset_ <= aprimeoffset)) {
- ok = MoveRight();
- }
- // So now current_lo_aprimeoffset_ <= aprimeoffset < current_hi_aprimeoffset_
-
- int aoffset = aprimeoffset - current_diff_;
- if (aoffset >= current_hi_aoffset_) {
- // A' is in an insert region, all bytes of which backmap to A=hi_aoffset_
- aoffset = current_hi_aoffset_;
- }
- return aoffset;
-}
-
-// Map an offset in A to the corresponding offset in A'
-int OffsetMap::MapForward(int aoffset){
- MaybeFlushAll();
- if (aoffset < 0) {return 0;}
- if (max_aoffset_ <= aoffset) {
- return (aoffset - max_aoffset_) + max_aprimeoffset_;
- }
-
- // If current_lo_aoffset_ <= aoffset < current_hi_aoffset_,
- // use current mapping, else move window left/right
- bool ok = true;
- while (ok && (aoffset < current_lo_aoffset_)) {
- ok = MoveLeft();
- }
- while (ok && (current_hi_aoffset_ <= aoffset)) {
- ok = MoveRight();
- }
-
- int aprimeoffset = aoffset + current_diff_;
- if (aprimeoffset >= current_hi_aprimeoffset_) {
- // A is in a delete region, all bytes of which map to A'=hi_aprimeoffset_
- aprimeoffset = current_hi_aprimeoffset_;
- }
- return aprimeoffset;
-}
-
-
-// static
-bool OffsetMap::CopyInserts(OffsetMap* source, OffsetMap* dest) {
- bool ok = true;
- while (ok && (source->next_diff_sub_ !=
- static_cast<int>(source->diffs_.size()))) {
- ok = source->MoveRight();
- if (source->current_lo_aoffset_ != source->current_hi_aoffset_) {
- return false;
- }
- dest->Insert(
- source->current_hi_aprimeoffset_ - source->current_lo_aprimeoffset_);
- }
- return true;
-}
-
-// static
-bool OffsetMap::CopyDeletes(OffsetMap* source, OffsetMap* dest) {
- bool ok = true;
- while (ok && (source->next_diff_sub_ !=
- static_cast<int>(source->diffs_.size()))) {
- ok = source->MoveRight();
- if (source->current_lo_aprimeoffset_ != source->current_hi_aprimeoffset_) {
- return false;
- }
- dest->Delete(source->current_hi_aoffset_ - source->current_lo_aoffset_);
- }
- return true;
-}
-
-// static
-void OffsetMap::ComposeOffsetMap(
- OffsetMap* g, OffsetMap* f, OffsetMap* h) {
- h->Clear();
- f->Reset();
- g->Reset();
-
- int lo = 0;
- for (;;) {
- // Consume delete operations in f. This moves A without moving
- // A' and A''.
- if (lo >= g->current_hi_aoffset_ && CopyInserts(g, h)) {
- if (lo >= f->current_hi_aprimeoffset_ && CopyDeletes(f, h)) {
- // fprintf(stderr,
- // "ComposeOffsetMap ERROR, f is longer than g.<br>\n");
- }
-
- // FlushAll(), called by Reset(), MapForward() or MapBack(), has
- // added an extra COPY_OP to f and g, so this function has
- // composed an extra COPY_OP in h from those. To avoid
- // FlushAll() adds one more extra COPY_OP to h later, dispatch
- // Flush() right now.
- h->Flush();
- return;
- }
-
- // Consume insert operations in g. This moves A'' without moving A
- // and A'.
- if (lo >= f->current_hi_aprimeoffset_) {
- if (!CopyDeletes(f, h)) {
- // fprintf(stderr,
- // "ComposeOffsetMap ERROR, g is longer than f.<br>\n");
- }
- }
-
- // Compose one operation which moves A' from lo to hi.
- int hi = min(f->current_hi_aprimeoffset_, g->current_hi_aoffset_);
- if (f->current_lo_aoffset_ != f->current_hi_aoffset_ &&
- g->current_lo_aprimeoffset_ != g->current_hi_aprimeoffset_) {
- h->Copy(hi - lo);
- } else if (f->current_lo_aoffset_ != f->current_hi_aoffset_) {
- h->Delete(hi - lo);
- } else if (g->current_lo_aprimeoffset_ != g->current_hi_aprimeoffset_) {
- h->Insert(hi - lo);
- }
-
- lo = hi;
- }
-}
-
-// For testing only -- force a mapping
-void OffsetMap::StuffIt(const std::string& diffs,
- int max_aoffset, int max_aprimeoffset) {
- Clear();
- diffs_ = diffs;
- max_aoffset_ = max_aoffset;
- max_aprimeoffset_ = max_aprimeoffset;
-}
-
-
-} // namespace CLD2
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/script_span/offsetmap.h b/chromium/third_party/cld_3/src/src/script_span/offsetmap.h
deleted file mode 100644
index 9cfe4121991..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/offsetmap.h
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Author: dsites@google.com (Dick Sites)
-//
-
-#ifndef SCRIPT_SPAN_OFFSETMAP_H_
-#define SCRIPT_SPAN_OFFSETMAP_H_
-
-#include <string> // for string
-
-#include "integral_types.h" // for uint32
-
-// ***************************** OffsetMap **************************
-//
-// An OffsetMap object is a container for a mapping from offsets in one text
-// buffer A' to offsets in another text buffer A. It is most useful when A' is
-// built from A via substitutions that occasionally do not preserve byte length.
-//
-// A series of operators are used to build the correspondence map, then
-// calls can be made to map an offset in A' to an offset in A, or vice versa.
-// The map starts with offset 0 in A corresponding to offset 0 in A'.
-// The mapping is then built sequentially, adding on byte ranges that are
-// identical in A and A', byte ranges that are inserted in A', and byte ranges
-// that are deleted from A. All bytes beyond those specified when building the
-// map are assumed to correspond, i.e. a Copy(infinity) is assumed at the
-// end of the map.
-//
-// The internal data structure records positions at which bytes are added or
-// deleted. Using the map is O(1) when increasing the A' or A offset
-// monotonically, and O(n) when accessing random offsets, where n is the
-// number of differences.
-//
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-class OffsetMap {
- public:
- // Constructor, destructor
- OffsetMap();
- ~OffsetMap();
-
- // Clear the map
- void Clear();
-
- // Add to mapping from A to A', specifying how many next bytes correspond
- // in A and A'
- void Copy(int bytes);
-
- // Add to mapping from A to A', specifying how many next bytes are
- // inserted in A' while not advancing in A at all
- void Insert(int bytes);
-
- // Add to mapping from A to A', specifying how many next bytes are
- // deleted from A while not advancing in A' at all
- void Delete(int bytes);
-
- // [Finish building map,] Re-position to offset 0
- // This call is optional; MapForward and MapBack finish building the map
- // if necessary
- void Reset();
-
- // Map an offset in A' to the corresponding offset in A
- int MapBack(int aprimeoffset);
-
- // Map an offset in A to the corresponding offset in A'
- int MapForward(int aoffset);
-
- // h = ComposeOffsetMap(g, f), where f is a map from A to A', g is
- // from A' to A'' and h is from A to A''.
- //
- // Note that g->MoveForward(f->MoveForward(aoffset)) always equals
- // to h->MoveForward(aoffset), while
- // f->MoveBack(g->MoveBack(aprimeprimeoffset)) doesn't always equals
- // to h->MoveBack(aprimeprimeoffset). This happens when deletion in
- // f and insertion in g are at the same place. For example,
- //
- // A 1 2 3 4
- // ^ | ^ ^
- // | | / | f
- // v vv v
- // A' 1' 2' 3'
- // ^ ^^ ^
- // | | \ | g
- // v | v v
- // A'' 1'' 2'' 3'' 4''
- //
- // results in:
- //
- // A 1 2 3 4
- // ^ ^\ ^ ^
- // | | \ | | h
- // v | vv v
- // A'' 1'' 2'' 3'' 4''
- //
- // 2'' is mapped 3 in the former figure, while 2'' is mapped to 2 in
- // the latter figure.
- static void ComposeOffsetMap(OffsetMap* g, OffsetMap* f, OffsetMap* h);
-
- // For testing only -- force a mapping
- void StuffIt(const std::string& diffs, int max_aoffset, int max_aprimeoffset);
-
- private:
- enum MapOp {PREFIX_OP, COPY_OP, INSERT_OP, DELETE_OP};
-
- void Flush();
- void FlushAll();
- void MaybeFlushAll();
- void Emit(MapOp op, int len);
-
- void SetLeft();
- void SetRight();
-
- // Back up over previous range, 1..5 bytes
- // Return subscript at the beginning of that. Pins at 0
- int Backup(int sub);
-
- // Parse next range, 1..5 bytes
- // Return subscript just off the end of that
- int ParseNext(int sub, MapOp* op, int* length);
-
- // Parse previous range, 1..5 bytes
- // Return current subscript
- int ParsePrevious(int sub, MapOp* op, int* length);
-
- bool MoveRight(); // Returns true if OK
- bool MoveLeft(); // Returns true if OK
-
- // Copies insert operations from source to dest. Returns true if no
- // other operations are found.
- static bool CopyInserts(OffsetMap* source, OffsetMap* dest);
-
- // Copies delete operations from source to dest. Returns true if no other
- // operations are found.
- static bool CopyDeletes(OffsetMap* source, OffsetMap* dest);
-
- std::string diffs_;
- MapOp pending_op_;
- uint32 pending_length_;
-
- // Offsets in the ranges below correspond to each other, with A' = A + diff
- int next_diff_sub_;
- int current_lo_aoffset_;
- int current_hi_aoffset_;
- int current_lo_aprimeoffset_;
- int current_hi_aprimeoffset_;
- int current_diff_;
- int max_aoffset_;
- int max_aprimeoffset_;
-};
-
-} // namespace CLD2
-} // namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_OFFSETMAP_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/port.h b/chromium/third_party/cld_3/src/src/script_span/port.h
deleted file mode 100644
index 2b3bc515ae8..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/port.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// These are weird things we need to do to get this compiling on
-// random systems [subset].
-
-#ifndef SCRIPT_SPAN_PORT_H_
-#define SCRIPT_SPAN_PORT_H_
-
-#include <string.h> // for memcpy()
-
-#include "integral_types.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-// Portable handling of unaligned loads, stores, and copies.
-// On some platforms, like ARM, the copy functions can be more efficient
-// then a load and a store.
-
-#if defined(ARCH_PIII) || defined(ARCH_ATHLON) || defined(ARCH_K8) || defined(_ARCH_PPC)
-
-// x86 and x86-64 can perform unaligned loads/stores directly;
-// modern PowerPC hardware can also do unaligned integer loads and stores;
-// but note: the FPU still sends unaligned loads and stores to a trap handler!
-
-#define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
-#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
-#define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
-
-#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
-#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
-#define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
-
-#elif defined(__arm__) && \
- !defined(__ARM_ARCH_5__) && \
- !defined(__ARM_ARCH_5T__) && \
- !defined(__ARM_ARCH_5TE__) && \
- !defined(__ARM_ARCH_5TEJ__) && \
- !defined(__ARM_ARCH_6__) && \
- !defined(__ARM_ARCH_6J__) && \
- !defined(__ARM_ARCH_6K__) && \
- !defined(__ARM_ARCH_6Z__) && \
- !defined(__ARM_ARCH_6ZK__) && \
- !defined(__ARM_ARCH_6T2__) && \
- !defined(__ARM_ARCH_7__) && \
- !defined(__ARM_ARCH_7A__) && \
- !defined(__ARM_ARCH_7M__) && \
- !defined(__ARM_ARCH_7R__) && \
- !defined(__ARM_ARCH_8__) && \
- !defined(__ARM_ARCH_8A__)
-
-// ARMv7 and newer support native unaligned accesses, but only of 16-bit
-// and 32-bit values (not 64-bit); older versions either raise a fatal signal,
-// do an unaligned read and rotate the words around a bit, or do the reads very
-// slowly (trip through kernel mode). There's no simple #define that says just
-// “ARMv7 or higher”, so we have to filter away all ARMv5 and ARMv6
-// sub-architectures. Newer gcc (>= 4.6) set an __ARM_FEATURE_ALIGNED #define,
-// so in time, maybe we can move on to that.
-//
-// Note that even if a chipset supports unaligned access, it might not be
-// enabled in any given system, e.g.:
-// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/CIHCGCFD.html
-// Therefore, it's generally just not safe to allow unaligned access on any ARM
-// variant.
-//
-// This is a mess, but there's not much we can do about it.
-
-#define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
-#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
-
-#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
-#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
-
-// TODO(sesse): NEON supports unaligned 64-bit loads and stores.
-// See if that would be more efficient on platforms supporting it,
-// at least for copies.
-
-inline uint64 UNALIGNED_LOAD64(const void *p) {
- uint64 t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline void UNALIGNED_STORE64(void *p, uint64 v) {
- memcpy(p, &v, sizeof v);
-}
-
-#else
-
-#define NEED_ALIGNED_LOADS
-
-// These functions are provided for architectures that don't support
-// unaligned loads and stores.
-
-inline uint16 UNALIGNED_LOAD16(const void *p) {
- uint16 t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline uint32 UNALIGNED_LOAD32(const void *p) {
- uint32 t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline uint64 UNALIGNED_LOAD64(const void *p) {
- uint64 t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline void UNALIGNED_STORE16(void *p, uint16 v) {
- memcpy(p, &v, sizeof v);
-}
-
-inline void UNALIGNED_STORE32(void *p, uint32 v) {
- memcpy(p, &v, sizeof v);
-}
-
-inline void UNALIGNED_STORE64(void *p, uint64 v) {
- memcpy(p, &v, sizeof v);
-}
-
-#endif
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_PORT_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/stringpiece.h b/chromium/third_party/cld_3/src/src/script_span/stringpiece.h
deleted file mode 100644
index 8b80f81641b..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/stringpiece.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// A StringPiece points to part or all of a string, double-quoted string
-// literal, or other string-like object. A StringPiece does *not* own the
-// string to which it points. A StringPiece is not null-terminated. [subset]
-//
-
-#ifndef SCRIPT_SPAN_STRINGPIECE_H_
-#define SCRIPT_SPAN_STRINGPIECE_H_
-
-#include <string.h>
-#include <string>
-
-namespace chrome_lang_id {
-
-typedef int stringpiece_ssize_type;
-
-class StringPiece {
- private:
- const char* ptr_;
- stringpiece_ssize_type length_;
-
- public:
- // We provide non-explicit singleton constructors so users can pass
- // in a "const char*" or a "string" wherever a "StringPiece" is
- // expected.
- StringPiece() : ptr_(NULL), length_(0) {}
-
- StringPiece(const char* str) // NOLINT(runtime/explicit)
- : ptr_(str), length_(0) {
- if (str != NULL) {
- length_ = static_cast<stringpiece_ssize_type>(strlen(str));
- }
- }
-
- StringPiece(const std::string& str) // NOLINT(runtime/explicit)
- : ptr_(str.data()), length_(0) {
- length_ = static_cast<stringpiece_ssize_type>(str.size());
- }
-
- StringPiece(const char* offset, stringpiece_ssize_type len)
- : ptr_(offset), length_(len) {
- }
-
- void remove_prefix(stringpiece_ssize_type n) {
- ptr_ += n;
- length_ -= n;
- }
-
- void remove_suffix(stringpiece_ssize_type n) {
- length_ -= n;
- }
-
- // data() may return a pointer to a buffer with embedded NULs, and the
- // returned buffer may or may not be null terminated. Therefore it is
- // typically a mistake to pass data() to a routine that expects a NUL
- // terminated string.
- const char* data() const { return ptr_; }
- stringpiece_ssize_type size() const { return length_; }
- stringpiece_ssize_type length() const { return length_; }
- bool empty() const { return length_ == 0; }
-};
-
-class StringPiece;
-
-} // namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_STRINGPIECE_H__
diff --git a/chromium/third_party/cld_3/src/src/script_span/text_processing.cc b/chromium/third_party/cld_3/src/src/script_span/text_processing.cc
deleted file mode 100644
index ec64ffa8725..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/text_processing.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "text_processing.h"
-
-#include <stdio.h>
-#include <string.h>
-
-namespace chrome_lang_id {
-namespace CLD2 {
-namespace {
-
-static const int kMaxSpaceScan = 32; // Bytes
-
-int minint(int a, int b) { return (a < b) ? a : b; }
-
-// Counts number of spaces; a little faster than one-at-a-time
-// Doesn't count odd bytes at end
-int CountSpaces4(const char *src, int src_len) {
- int s_count = 0;
- for (int i = 0; i < (src_len & ~3); i += 4) {
- s_count += (src[i] == ' ');
- s_count += (src[i + 1] == ' ');
- s_count += (src[i + 2] == ' ');
- s_count += (src[i + 3] == ' ');
- }
- return s_count;
-}
-
-// This uses a cheap predictor to get a measure of compression, and
-// hence a measure of repetitiveness. It works on complete UTF-8 characters
-// instead of bytes, because three-byte UTF-8 Indic, etc. text compress highly
-// all the time when done with a byte-based count. Sigh.
-//
-// To allow running prediction across multiple chunks, caller passes in current
-// 12-bit hash value and int[4096] prediction table. Caller inits these to 0.
-//
-// Returns the number of *bytes* correctly predicted, increments by 1..4 for
-// each correctly-predicted character.
-//
-// NOTE: Overruns by up to three bytes. Not a problem with valid UTF-8 text
-//
-
-// TODO(dsites) make this use just one byte per UTF-8 char and incr by charlen
-
-int CountPredictedBytes(const char *isrc, int src_len, int *hash, int *tbl) {
- typedef unsigned char uint8;
-
- int p_count = 0;
- const uint8 *src = reinterpret_cast<const uint8 *>(isrc);
- const uint8 *srclimit = src + src_len;
- int local_hash = *hash;
-
- while (src < srclimit) {
- int c = src[0];
- int incr = 1;
-
- // Pick up one char and length
- if (c < 0xc0) {
- // One-byte or continuation byte: 00xxxxxx 01xxxxxx 10xxxxxx
- // Do nothing more
- } else if ((c & 0xe0) == 0xc0) {
- // Two-byte
- c = (c << 8) | src[1];
- incr = 2;
- } else if ((c & 0xf0) == 0xe0) {
- // Three-byte
- c = (c << 16) | (src[1] << 8) | src[2];
- incr = 3;
- } else {
- // Four-byte
- c = (c << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
- incr = 4;
- }
- src += incr;
-
- int p = tbl[local_hash]; // Prediction
- tbl[local_hash] = c; // Update prediction
- if (c == p) {
- p_count += incr; // Count bytes of good predictions
- }
-
- local_hash = ((local_hash << 4) ^ c) & 0xfff;
- }
- *hash = local_hash;
- return p_count;
-}
-
-// Backscan to word boundary, returning how many bytes n to go back
-// so that src - n is non-space ans src - n - 1 is space.
-// If not found in kMaxSpaceScan bytes, return 0..3 to a clean UTF-8 boundary
-int BackscanToSpace(const char *src, int limit) {
- int n = 0;
- limit = minint(limit, kMaxSpaceScan);
- while (n < limit) {
- if (src[-n - 1] == ' ') {
- return n;
- } // We are at _X
- ++n;
- }
- n = 0;
- while (n < limit) {
- if ((src[-n] & 0xc0) != 0x80) {
- return n;
- } // We are at char begin
- ++n;
- }
- return 0;
-}
-
-// Forwardscan to word boundary, returning how many bytes n to go forward
-// so that src + n is non-space ans src + n - 1 is space.
-// If not found in kMaxSpaceScan bytes, return 0..3 to a clean UTF-8 boundary
-int ForwardscanToSpace(const char *src, int limit) {
- int n = 0;
- limit = minint(limit, kMaxSpaceScan);
- while (n < limit) {
- if (src[n] == ' ') {
- return n + 1;
- } // We are at _X
- ++n;
- }
- n = 0;
- while (n < limit) {
- if ((src[n] & 0xc0) != 0x80) {
- return n;
- } // We are at char begin
- ++n;
- }
- return 0;
-}
-
-} // namespace
-
-// Must be exactly 4096 for cheap compressor.
-static const int kPredictionTableSize = 4096;
-static const int kChunksizeDefault = 48; // Squeeze 48-byte chunks
-static const int kSpacesThreshPercent = 30; // Squeeze if >=30% spaces
-static const int kPredictThreshPercent = 40; // Squeeze if >=40% predicted
-
-// Remove portions of text that have a high density of spaces, or that are
-// overly repetitive, squeezing the remaining text in-place to the front of the
-// input buffer.
-//
-// Squeezing looks at density of space/prediced chars in fixed-size chunks,
-// specified by chunksize. A chunksize <= 0 uses the default size of 48 bytes.
-//
-// Return the new, possibly-shorter length
-//
-// Result Buffer ALWAYS has leading space and trailing space space space NUL,
-// if input does
-//
-int CheapSqueezeInplace(char *isrc, int src_len, int ichunksize) {
- char *src = isrc;
- char *dst = src;
- char *srclimit = src + src_len;
- bool skipping = false;
-
- int hash = 0;
-
- // Allocate local prediction table.
- int *predict_tbl = new int[kPredictionTableSize];
- memset(predict_tbl, 0, kPredictionTableSize * sizeof(predict_tbl[0]));
-
- int chunksize = ichunksize;
- if (chunksize == 0) {
- chunksize = kChunksizeDefault;
- }
- int space_thresh = (chunksize * kSpacesThreshPercent) / 100;
- int predict_thresh = (chunksize * kPredictThreshPercent) / 100;
-
- while (src < srclimit) {
- int remaining_bytes = srclimit - src;
- int len = minint(chunksize, remaining_bytes);
-
- // Make len land us on a UTF-8 character boundary.
- // Ah. Also fixes mispredict because we could get out of phase
- // Loop always terminates at trailing space in buffer
- while ((src[len] & 0xc0) == 0x80) {
- ++len;
- } // Move past continuation bytes
-
- int space_n = CountSpaces4(src, len);
- int predb_n = CountPredictedBytes(src, len, &hash, predict_tbl);
- if ((space_n >= space_thresh) || (predb_n >= predict_thresh)) {
- // Skip the text
- if (!skipping) {
- // Keeping-to-skipping transition; do it at a space
- int n = BackscanToSpace(dst, static_cast<int>(dst - isrc));
- dst -= n;
- if (dst == isrc) {
- // Force a leading space if the first chunk is deleted
- *dst++ = ' ';
- }
- skipping = true;
- }
- } else {
- // Keep the text
- if (skipping) {
- // Skipping-to-keeping transition; do it at a space
- int n = ForwardscanToSpace(src, len);
- src += n;
- remaining_bytes -= n; // Shrink remaining length
- len -= n;
- skipping = false;
- }
-
- // "len" can be negative in some cases
- if (len > 0) {
- memmove(dst, src, len);
- dst += len;
- }
- }
- src += len;
- }
-
- if ((dst - isrc) < (src_len - 3)) {
- // Pad and make last char clean UTF-8 by putting following spaces
- dst[0] = ' ';
- dst[1] = ' ';
- dst[2] = ' ';
- dst[3] = '\0';
- } else if ((dst - isrc) < src_len) {
- // Make last char clean UTF-8 by putting following space off the end
- dst[0] = ' ';
- }
-
- // Deallocate local prediction table
- delete[] predict_tbl;
- return static_cast<int>(dst - isrc);
-}
-
-} // namespace CLD2
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/script_span/text_processing.h b/chromium/third_party/cld_3/src/src/script_span/text_processing.h
deleted file mode 100644
index 12c5ab8e20e..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/text_processing.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SCRIPT_SPAN_TEXT_PROCESSING_H_
-#define SCRIPT_SPAN_TEXT_PROCESSING_H_
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-// Remove portions of text that have a high density of spaces, or that are
-// overly repetitive, squeezing the remaining text in-place to the front
-// of the input buffer.
-// Return the new, possibly-shorter length
-int CheapSqueezeInplace(char *isrc, int srclen, int ichunksize);
-
-} // namespace CLD2
-} // namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_TEXT_PROCESSING_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/utf8acceptinterchange.h b/chromium/third_party/cld_3/src/src/script_span/utf8acceptinterchange.h
deleted file mode 100644
index 59adca85e0f..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/utf8acceptinterchange.h
+++ /dev/null
@@ -1,486 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Created by utf8tablebuilder version 2.9
-//
-// Rejects all codes that are not interchange-valid
-// Accepts all other UTF-8 codes 0000..10FFFF
-// Exit optimized -- exits after four times in state 0
-// All bytes are checked for structurally valid UTF-8
-// Table entries are absolute statetable subscripts
-
-#ifndef SCRIPT_SPAN_UTF8ACCEPTINTERCHANGE_H_
-#define SCRIPT_SPAN_UTF8ACCEPTINTERCHANGE_H_
-
-#include "integral_types.h"
-#include "utf8statetable.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-#define X__ (kExitIllegalStructure)
-#define RJ_ (kExitReject)
-#define S1_ (kExitReplace1)
-#define S2_ (kExitReplace2)
-#define S3_ (kExitReplace3)
-#define S21 (kExitReplace21)
-#define S31 (kExitReplace31)
-#define S32 (kExitReplace32)
-#define T1_ (kExitReplaceOffset1)
-#define T2_ (kExitReplaceOffset2)
-#define S11 (kExitReplace1S0)
-#define SP_ (kExitSpecial)
-#define D__ (kExitDoAgain)
-#define RJA (kExitRejectAlt)
-
-// Entire table has 17 state blocks of 256 entries each
-
-static const unsigned int utf8acceptinterchange_STATE0 = 0; // state[0]
-static const unsigned int utf8acceptinterchange_STATE0_SIZE = 1024; // =[4]
-static const unsigned int utf8acceptinterchange_TOTAL_SIZE = 4352;
-static const unsigned int utf8acceptinterchange_MAX_EXPAND_X4 = 0;
-static const unsigned int utf8acceptinterchange_SHIFT = 8;
-static const unsigned int utf8acceptinterchange_BYTES = 1;
-static const unsigned int utf8acceptinterchange_LOSUB = 0x20202020;
-static const unsigned int utf8acceptinterchange_HIADD = 0x01010101;
-
-static const uint8 utf8acceptinterchange[] = {
-// state[0] 0x000000 Byte 1
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 1, 1,RJ_, 1, 1,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,RJ_,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 10,
- 13, 15, 15, 15, 16,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[1] 0x000000 Byte 1
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 2, 2,RJ_, 2, 2,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,RJ_,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 10,
- 13, 15, 15, 15, 16,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[2] 0x000000 Byte 1
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 3, 3,RJ_, 3, 3,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,RJ_,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 10,
- 13, 15, 15, 15, 16,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[3] 0x000000 Byte 1
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,D__,D__,RJ_,D__,D__,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-D__,D__,D__,D__,D__,D__,D__,D__, D__,D__,D__,D__,D__,D__,D__,D__,
-D__,D__,D__,D__,D__,D__,D__,D__, D__,D__,D__,D__,D__,D__,D__,D__,
-
-D__,D__,D__,D__,D__,D__,D__,D__, D__,D__,D__,D__,D__,D__,D__,D__,
-D__,D__,D__,D__,D__,D__,D__,D__, D__,D__,D__,D__,D__,D__,D__,D__,
-D__,D__,D__,D__,D__,D__,D__,D__, D__,D__,D__,D__,D__,D__,D__,D__,
-D__,D__,D__,D__,D__,D__,D__,D__, D__,D__,D__,D__,D__,D__,D__,RJ_,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 10,
- 13, 15, 15, 15, 16,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[4] 0x0000c0 Byte 2 of 2
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[5] 0x000000 Byte 2 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[6] 0x001000 Byte 2 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[7] 0x000080 Byte 2 of 2
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[8] 0x00d000 Byte 2 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[9] 0x00d800 Byte 3 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[10] 0x00f000 Byte 2 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 11, 4, 4, 4, 4, 4, 4, 4, 12,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[11] 0x00fdc0 Byte 3 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[12] 0x00ffc0 Byte 3 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[13] 0x000000 Byte 2 of 4
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 14,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 14,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 14,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[14] 0x01f000 Byte 3 of 4
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 12,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[15] 0x040000 Byte 2 of 4
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 14,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 14,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 14,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 14,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[16] 0x100000 Byte 2 of 4
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 14,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-};
-
-// Remap base[0] = (del, add, string_offset)
-static const RemapEntry utf8acceptinterchange_remap_base[] = {
-{0,0,0} };
-
-// Remap string[0]
-static const unsigned char utf8acceptinterchange_remap_string[] = {
-0 };
-
-static const unsigned char utf8acceptinterchange_fast[256] = {
-1,1,1,1,1,1,1,1, 1,0,0,1,0,0,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,1,
-
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-
-};
-
-static const UTF8ScanObj utf8acceptinterchange_obj = {
- utf8acceptinterchange_STATE0,
- utf8acceptinterchange_STATE0_SIZE,
- utf8acceptinterchange_TOTAL_SIZE,
- utf8acceptinterchange_MAX_EXPAND_X4,
- utf8acceptinterchange_SHIFT,
- utf8acceptinterchange_BYTES,
- utf8acceptinterchange_LOSUB,
- utf8acceptinterchange_HIADD,
- utf8acceptinterchange,
- utf8acceptinterchange_remap_base,
- utf8acceptinterchange_remap_string,
- utf8acceptinterchange_fast
-};
-
-
-#undef X__
-#undef RJ_
-#undef S1_
-#undef S2_
-#undef S3_
-#undef S21
-#undef S31
-#undef S32
-#undef T1_
-#undef T2_
-#undef S11
-#undef SP_
-#undef D__
-#undef RJA
-
-// Table has 4608 bytes, Hash = 505C-3D29
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_UTF8ACCEPTINTERCHANGE_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/utf8prop_lettermarkscriptnum.h b/chromium/third_party/cld_3/src/src/script_span/utf8prop_lettermarkscriptnum.h
deleted file mode 100644
index 5ed3ec6905d..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/utf8prop_lettermarkscriptnum.h
+++ /dev/null
@@ -1,1631 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Created by utf8tablebuilder version 2.9
-//
-// Maps properties of all codes from file:
-// lettermarkscriptnum_6.2.0.txt
-// Accepts all other UTF-8 codes 0000..10FFFF
-// Space optimized
-//
-// ** ASSUMES INPUT IS STRUCTURALLY VALID UTF-8 **
-//
-// Table entries are absolute statetable subscripts
-// Table entries are two bytes each
-
-#ifndef SCRIPT_SPAN_UTF8PROP_LETTERMARKSCRIPTNUM_H_
-#define SCRIPT_SPAN_UTF8PROP_LETTERMARKSCRIPTNUM_H_
-
-#include "integral_types.h"
-#include "utf8statetable.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-#define X__ (kExitIllegalStructure_2)
-#define RJ_ (kExitReject_2)
-#define S1_ (kExitReplace1_2)
-#define S2_ (kExitReplace2_2)
-#define S3_ (kExitReplace3_2)
-#define S21 (kExitReplace21_2)
-#define S31 (kExitReplace31_2)
-#define S32 (kExitReplace32_2)
-#define T1_ (kExitReplaceOffset1_2)
-#define T2_ (kExitReplaceOffset2_2)
-#define S11 (kExitReplace1S0_2)
-#define SP_ (kExitSpecial_2)
-#define D__ (kExitDoAgain_2)
-#define RJA (kExitRejectAlt_2)
-
-// Entire table has 254 state blocks of 64 entries each
-
-static const unsigned int utf8prop_lettermarkscriptnum_STATE0 = 0; // state[0]
-static const unsigned int utf8prop_lettermarkscriptnum_STATE0_SIZE = 64; // =[1]
-static const unsigned int utf8prop_lettermarkscriptnum_TOTAL_SIZE = 16256;
-static const unsigned int utf8prop_lettermarkscriptnum_MAX_EXPAND_X4 = 0;
-static const unsigned int utf8prop_lettermarkscriptnum_SHIFT = 6;
-static const unsigned int utf8prop_lettermarkscriptnum_BYTES = 2;
-static const unsigned int utf8prop_lettermarkscriptnum_LOSUB = 0x80808080;
-static const unsigned int utf8prop_lettermarkscriptnum_HIADD = 0x00000000;
-
-static const unsigned short utf8prop_lettermarkscriptnum[] = {
-// state[0] 0x000000 Byte 1 (rows 0x-7x property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__, 6, 7, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14,
- 15, 15, 16, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 62,111,126,134,136,136,136, 136,137,139,136,136,165, 2,168,
-186, 4, 4,249, 5,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[2 + 2] 0x00e000 Byte 2 of 3
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[3 + 2] 0x001ac0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[4 + 2] 0x040000 Byte 2 of 4
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[5 + 2] 0x100000 Byte 2 of 4
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[6 + 2] 0x000080 Byte 2 of 2 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
-
-// state[7 + 2] 0x0000c0 Byte 2 of 2 (property)
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
-
-// state[8 + 2] 0x000100 Byte 2 of 2 (property)
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-// state[9 + 2] 0x000280 Byte 2 of 2 (property)
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
-
-// state[10 + 2] 0x0002c0 Byte 2 of 2 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[11 + 2] 0x000300 Byte 2 of 2 (property)
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
-
-// state[12 + 2] 0x000340 Byte 2 of 2 (property)
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 0, 0,
-
-// state[13 + 2] 0x000380 Byte 2 of 2 (property)
- 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 0, 2, 0, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[14 + 2] 0x0003c0 Byte 2 of 2 (property)
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[15 + 2] 0x000400 Byte 2 of 2 (property)
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[16 + 2] 0x000480 Byte 2 of 2 (property)
- 3, 3, 0, 3, 3, 40, 40, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[17 + 2] 0x000500 Byte 2 of 2 (property)
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-
-// state[18 + 2] 0x000540 Byte 2 of 2 (property)
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 0, 0, 4, 0, 0, 0, 0, 0, 0,
- 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-
-// state[19 + 2] 0x000580 Byte 2 of 2 (property)
- 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5,
-
-// state[20 + 2] 0x0005c0 Byte 2 of 2 (property)
- 0, 5, 5, 0, 5, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0,
- 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[21 + 2] 0x000600 Byte 2 of 2 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[22 + 2] 0x000640 Byte 2 of 2 (property)
- 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6,
- 40, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[23 + 2] 0x000680 Byte 2 of 2 (property)
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[24 + 2] 0x0006c0 Byte 2 of 2 (property)
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6, 6,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 0, 0, 6,
-
-// state[25 + 2] 0x000700 Byte 2 of 2 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-
-// state[26 + 2] 0x000740 Byte 2 of 2 (property)
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 7,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[27 + 2] 0x000780 Byte 2 of 2 (property)
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[28 + 2] 0x0007c0 Byte 2 of 2 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0,
-
-// state[29 + 2] 0x000000 Byte 2 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-
-// state[30 + 2] 0x000800 Byte 3 of 3 (property)
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[31 + 2] 0x000840 Byte 3 of 3 (property)
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[32 + 2] 0x000880 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[33 + 2] 0x0008c0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0,
-
-// state[34 + 2] 0x000900 Byte 3 of 3 (property)
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
-
-// state[35 + 2] 0x000940 Byte 3 of 3 (property)
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 40, 40, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 9, 9, 9, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 9, 9,
-
-// state[36 + 2] 0x000980 Byte 3 of 3 (property)
- 0, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 10,
- 10, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 10, 10, 10, 10, 10, 10,
- 10, 0, 10, 0, 0, 0, 10, 10, 10, 10, 0, 0, 10, 10, 10, 10,
-
-// state[37 + 2] 0x0009c0 Byte 3 of 3 (property)
- 10, 10, 10, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 10, 10, 0,
- 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, 10, 0, 10,
- 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[38 + 2] 0x000a00 Byte 3 of 3 (property)
- 0, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 11,
- 11, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 0, 11, 11, 11, 11, 11, 11,
- 11, 0, 11, 11, 0, 11, 11, 0, 11, 11, 0, 0, 11, 0, 11, 11,
-
-// state[39 + 2] 0x000a40 Byte 3 of 3 (property)
- 11, 11, 11, 0, 0, 0, 0, 11, 11, 0, 0, 11, 11, 11, 0, 0,
- 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 0, 11, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 11, 11, 11, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[40 + 2] 0x000a80 Byte 3 of 3 (property)
- 0, 12, 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 12,
- 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 0, 12, 12, 12, 12, 12, 12,
- 12, 0, 12, 12, 0, 12, 12, 12, 12, 12, 0, 0, 12, 12, 12, 12,
-
-// state[41 + 2] 0x000ac0 Byte 3 of 3 (property)
- 12, 12, 12, 12, 12, 12, 0, 12, 12, 12, 0, 12, 12, 12, 0, 0,
- 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[42 + 2] 0x000b00 Byte 3 of 3 (property)
- 0, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 13,
- 13, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 13, 13, 13, 13, 13, 13,
- 13, 0, 13, 13, 0, 13, 13, 13, 13, 13, 0, 0, 13, 13, 13, 13,
-
-// state[43 + 2] 0x000b40 Byte 3 of 3 (property)
- 13, 13, 13, 13, 13, 0, 0, 13, 13, 0, 0, 13, 13, 13, 0, 0,
- 0, 0, 0, 0, 0, 0, 13, 13, 0, 0, 0, 0, 13, 13, 0, 13,
- 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[44 + 2] 0x000b80 Byte 3 of 3 (property)
- 0, 0, 14, 14, 0, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14,
- 14, 0, 14, 14, 14, 14, 0, 0, 0, 14, 14, 0, 14, 0, 14, 14,
- 0, 0, 0, 14, 14, 0, 0, 0, 14, 14, 14, 0, 0, 0, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14,
-
-// state[45 + 2] 0x000bc0 Byte 3 of 3 (property)
- 14, 14, 14, 0, 0, 0, 14, 14, 14, 0, 14, 14, 14, 14, 0, 0,
- 14, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[46 + 2] 0x000c00 Byte 3 of 3 (property)
- 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15,
- 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15,
-
-// state[47 + 2] 0x000c40 Byte 3 of 3 (property)
- 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0,
- 0, 0, 0, 0, 0, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0,
- 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[48 + 2] 0x000c80 Byte 3 of 3 (property)
- 0, 0, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16,
- 16, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16,
-
-// state[49 + 2] 0x000cc0 Byte 3 of 3 (property)
- 16, 16, 16, 16, 16, 0, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0,
- 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, 0,
- 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[50 + 2] 0x000d00 Byte 3 of 3 (property)
- 0, 0, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 17, 17,
- 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17,
-
-// state[51 + 2] 0x000d40 Byte 3 of 3 (property)
- 17, 17, 17, 17, 17, 0, 17, 17, 17, 0, 17, 17, 17, 17, 17, 0,
- 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0,
- 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17,
-
-// state[52 + 2] 0x000d80 Byte 3 of 3 (property)
- 0, 0, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, 0, 0,
-
-// state[53 + 2] 0x000dc0 Byte 3 of 3 (property)
- 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 18, 0, 0, 0, 0, 18,
- 18, 18, 18, 18, 18, 0, 18, 0, 18, 18, 18, 18, 18, 18, 18, 18,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[54 + 2] 0x000e00 Byte 3 of 3 (property)
- 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0,
-
-// state[55 + 2] 0x000e40 Byte 3 of 3 (property)
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[56 + 2] 0x000e80 Byte 3 of 3 (property)
- 0, 20, 20, 0, 20, 0, 0, 20, 20, 0, 20, 0, 0, 20, 0, 0,
- 0, 0, 0, 0, 20, 20, 20, 20, 0, 20, 20, 20, 20, 20, 20, 20,
- 0, 20, 20, 20, 0, 20, 0, 20, 0, 0, 20, 20, 0, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 20, 20, 20, 0, 0,
-
-// state[57 + 2] 0x000ec0 Byte 3 of 3 (property)
- 20, 20, 20, 20, 20, 0, 20, 0, 20, 20, 20, 20, 20, 20, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 20,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[58 + 2] 0x000f00 Byte 3 of 3 (property)
- 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 21, 21, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 21, 0, 21, 0, 21, 0, 0, 0, 0, 21, 21,
-
-// state[59 + 2] 0x000f40 Byte 3 of 3 (property)
- 21, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0,
- 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-
-// state[60 + 2] 0x000f80 Byte 3 of 3 (property)
- 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 0, 0, 0,
-
-// state[61 + 2] 0x000fc0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[62 + 2] 0x001000 Byte 2 of 3
- 63, 64, 65, 66, 67, 67, 67, 67, 68, 69, 70, 71, 72, 73, 74, 75,
- 76, 77, 77, 77, 77, 77, 77, 77, 77, 78, 79, 80, 81, 82, 83, 84,
- 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 3, 96, 97, 98, 99,
-100,101, 3,102,103,104,105,106, 8, 8, 8, 8,107,108,109,110,
-
-// state[63 + 2] 0x001000 Byte 3 of 3 (property)
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-
-// state[64 + 2] 0x001040 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-
-// state[65 + 2] 0x001080 Byte 3 of 3 (property)
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 22, 22, 22, 0, 0,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-
-// state[66 + 2] 0x0010c0 Byte 3 of 3 (property)
- 23, 23, 23, 23, 23, 23, 0, 23, 0, 0, 0, 0, 0, 23, 0, 0,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 0, 23, 23, 23, 23,
-
-// state[67 + 2] 0x001100 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-
-// state[68 + 2] 0x001200 Byte 3 of 3 (property)
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-
-// state[69 + 2] 0x001240 Byte 3 of 3 (property)
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 0, 0,
- 25, 25, 25, 25, 25, 25, 25, 0, 25, 0, 25, 25, 25, 25, 0, 0,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-
-// state[70 + 2] 0x001280 Byte 3 of 3 (property)
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 0, 0,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 0, 25, 25, 25, 25, 0, 0, 25, 25, 25, 25, 25, 25, 25, 0,
-
-// state[71 + 2] 0x0012c0 Byte 3 of 3 (property)
- 25, 0, 25, 25, 25, 25, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-
-// state[72 + 2] 0x001300 Byte 3 of 3 (property)
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 0, 25, 25, 25, 25, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-
-// state[73 + 2] 0x001340 Byte 3 of 3 (property)
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 25, 25, 25,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[74 + 2] 0x001380 Byte 3 of 3 (property)
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-
-// state[75 + 2] 0x0013c0 Byte 3 of 3 (property)
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[76 + 2] 0x001400 Byte 3 of 3 (property)
- 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-
-// state[77 + 2] 0x001440 Byte 3 of 3 (property)
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-
-// state[78 + 2] 0x001640 Byte 3 of 3 (property)
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-
-// state[79 + 2] 0x001680 Byte 3 of 3 (property)
- 0, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 0, 0, 0, 0, 0,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-
-// state[80 + 2] 0x0016c0 Byte 3 of 3 (property)
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[81 + 2] 0x001700 Byte 3 of 3 (property)
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 0, 41, 41,
- 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[82 + 2] 0x001740 Byte 3 of 3 (property)
- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44,
- 44, 0, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[83 + 2] 0x001780 Byte 3 of 3 (property)
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-
-// state[84 + 2] 0x0017c0 Byte 3 of 3 (property)
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 0, 0, 0, 30, 0, 0, 0, 0, 30, 30, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[85 + 2] 0x001800 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 31, 31, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-
-// state[86 + 2] 0x001840 Byte 3 of 3 (property)
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[87 + 2] 0x001880 Byte 3 of 3 (property)
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 0, 0, 0, 0, 0,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-
-// state[88 + 2] 0x0018c0 Byte 3 of 3 (property)
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[89 + 2] 0x001900 Byte 3 of 3 (property)
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0,
-
-// state[90 + 2] 0x001940 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 0, 0,
- 46, 46, 46, 46, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[91 + 2] 0x001980 Byte 3 of 3 (property)
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
-
-// state[92 + 2] 0x0019c0 Byte 3 of 3 (property)
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[93 + 2] 0x001a00 Byte 3 of 3 (property)
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 0, 0, 0, 0,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
-
-// state[94 + 2] 0x001a40 Byte 3 of 3 (property)
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 0,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 0, 0, 77,
-
-// state[95 + 2] 0x001a80 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[96 + 2] 0x001b00 Byte 3 of 3 (property)
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
-
-// state[97 + 2] 0x001b40 Byte 3 of 3 (property)
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[98 + 2] 0x001b80 Byte 3 of 3 (property)
- 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 66,
-
-// state[99 + 2] 0x001bc0 Byte 3 of 3 (property)
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[100 + 2] 0x001c00 Byte 3 of 3 (property)
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[101 + 2] 0x001c40 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 67,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 0, 0,
-
-// state[102 + 2] 0x001cc0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 40, 40, 40, 0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 0, 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 0, 40, 0, 0,
- 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[103 + 2] 0x001d00 Byte 3 of 3 (property)
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-// state[104 + 2] 0x001d40 Byte 3 of 3 (property)
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
- 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1,
-
-// state[105 + 2] 0x001d80 Byte 3 of 3 (property)
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
-
-// state[106 + 2] 0x001dc0 Byte 3 of 3 (property)
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40,
-
-// state[107 + 2] 0x001f00 Byte 3 of 3 (property)
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[108 + 2] 0x001f40 Byte 3 of 3 (property)
- 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
-
-// state[109 + 2] 0x001f80 Byte 3 of 3 (property)
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0,
-
-// state[110 + 2] 0x001fc0 Byte 3 of 3 (property)
- 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
- 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
- 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
-
-// state[111 + 2] 0x002000 Byte 2 of 3
- 3,112,113,114,115,116,117, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-118,119,120,121,122,123,124,125, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[112 + 2] 0x002040 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-
-// state[113 + 2] 0x002080 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[114 + 2] 0x0020c0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[115 + 2] 0x002100 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[116 + 2] 0x002140 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[117 + 2] 0x002180 Byte 3 of 3 (property)
- 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[118 + 2] 0x002c00 Byte 3 of 3 (property)
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
-
-// state[119 + 2] 0x002c40 Byte 3 of 3 (property)
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-// state[120 + 2] 0x002c80 Byte 3 of 3 (property)
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
-
-// state[121 + 2] 0x002cc0 Byte 3 of 3 (property)
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[122 + 2] 0x002d00 Byte 3 of 3 (property)
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 0, 23, 0, 0, 0, 0, 0, 23, 0, 0,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
-
-// state[123 + 2] 0x002d40 Byte 3 of 3 (property)
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 0, 0, 0, 0, 0, 0, 0, 57,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57,
-
-// state[124 + 2] 0x002d80 Byte 3 of 3 (property)
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 0,
- 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 0,
-
-// state[125 + 2] 0x002dc0 Byte 3 of 3 (property)
- 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 0,
- 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 0,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[126 + 2] 0x003000 Byte 2 of 3
-127,128,129,130,131, 67,132,133, 3, 3, 3, 3, 3, 3, 3, 3,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-
-// state[127 + 2] 0x003000 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 24, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0,
-
-// state[128 + 2] 0x003040 Byte 3 of 3 (property)
- 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-
-// state[129 + 2] 0x003080 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 0, 0, 40, 40, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-
-// state[130 + 2] 0x0030c0 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 24, 24, 24,
-
-// state[131 + 2] 0x003100 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 0, 0,
- 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-
-// state[132 + 2] 0x003180 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0,
-
-// state[133 + 2] 0x0031c0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-
-// state[134 + 2] 0x004000 Byte 2 of 3
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67,135, 3, 67, 67, 67, 67, 67, 67, 67, 67,
-
-// state[135 + 2] 0x004d80 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[136 + 2] 0x005000 Byte 2 of 3
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-
-// state[137 + 2] 0x009000 Byte 2 of 3
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,138,
-
-// state[138 + 2] 0x009fc0 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[139 + 2] 0x00a000 Byte 2 of 3
-140,140,140,140,140,140,140,140, 140,140,140,140,140,140,140,140,
-140,140,141,142,143,143,143,143, 144,145,146,147,148, 8,149,150,
-151,152,153,154,155,156,157,158, 159,160,161,162,163, 3, 3,164,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-
-// state[140 + 2] 0x00a000 Byte 3 of 3 (property)
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-
-// state[141 + 2] 0x00a480 Byte 3 of 3 (property)
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[142 + 2] 0x00a4c0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 0, 0,
-
-// state[143 + 2] 0x00a500 Byte 3 of 3 (property)
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-
-// state[144 + 2] 0x00a600 Byte 3 of 3 (property)
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0, 0, 0,
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 69, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[145 + 2] 0x00a640 Byte 3 of 3 (property)
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3,
-
-// state[146 + 2] 0x00a680 Byte 3 of 3 (property)
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 3,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
-
-// state[147 + 2] 0x00a6c0 Byte 3 of 3 (property)
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 83, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[148 + 2] 0x00a700 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-// state[149 + 2] 0x00a780 Byte 3 of 3 (property)
- 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0,
- 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[150 + 2] 0x00a7c0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
-
-// state[151 + 2] 0x00a800 Byte 3 of 3 (property)
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[152 + 2] 0x00a840 Byte 3 of 3 (property)
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[153 + 2] 0x00a880 Byte 3 of 3 (property)
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-
-// state[154 + 2] 0x00a8c0 Byte 3 of 3 (property)
- 70, 70, 70, 70, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 9, 0, 0, 0, 0,
-
-// state[155 + 2] 0x00a900 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 0, 0,
- 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
-
-// state[156 + 2] 0x00a940 Byte 3 of 3 (property)
- 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 72, 72, 72, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0,
-
-// state[157 + 2] 0x00a980 Byte 3 of 3 (property)
- 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
-
-// state[158 + 2] 0x00a9c0 Byte 3 of 3 (property)
- 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[159 + 2] 0x00aa00 Byte 3 of 3 (property)
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[160 + 2] 0x00aa40 Byte 3 of 3 (property)
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 0, 0, 0, 22, 22, 0, 0, 0, 0,
-
-// state[161 + 2] 0x00aa80 Byte 3 of 3 (property)
- 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
- 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
- 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
- 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
-
-// state[162 + 2] 0x00aac0 Byte 3 of 3 (property)
- 78, 78, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 78, 78, 0, 0,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 0, 0, 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[163 + 2] 0x00ab00 Byte 3 of 3 (property)
- 0, 25, 25, 25, 25, 25, 25, 0, 0, 25, 25, 25, 25, 25, 25, 0,
- 0, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[164 + 2] 0x00abc0 Byte 3 of 3 (property)
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 0, 85, 85, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[165 + 2] 0x00d000 Byte 2 of 3
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,166,167,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[166 + 2] 0x00d780 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-
-// state[167 + 2] 0x00d7c0 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0,
-
-// state[168 + 2] 0x00f000 Byte 2 of 3
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 67, 67, 67, 67, 67,169, 67,170,171,172,173,174,
- 23, 23, 23, 23,175,176,177,178, 179,180, 23,181,182,183,184,185,
-
-// state[169 + 2] 0x00fa40 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-
-// state[170 + 2] 0x00fac0 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[171 + 2] 0x00fb00 Byte 3 of 3 (property)
- 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 0,
-
-// state[172 + 2] 0x00fb40 Byte 3 of 3 (property)
- 5, 5, 0, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[173 + 2] 0x00fb80 Byte 3 of 3 (property)
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[174 + 2] 0x00fbc0 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[175 + 2] 0x00fd00 Byte 3 of 3 (property)
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0,
-
-// state[176 + 2] 0x00fd40 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[177 + 2] 0x00fd80 Byte 3 of 3 (property)
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[178 + 2] 0x00fdc0 Byte 3 of 3 (property)
- 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0,
-
-// state[179 + 2] 0x00fe00 Byte 3 of 3 (property)
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[180 + 2] 0x00fe40 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[181 + 2] 0x00fec0 Byte 3 of 3 (property)
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0,
-
-// state[182 + 2] 0x00ff00 Byte 3 of 3 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
-
-// state[183 + 2] 0x00ff40 Byte 3 of 3 (property)
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-
-// state[184 + 2] 0x00ff80 Byte 3 of 3 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0,
-
-// state[185 + 2] 0x00ffc0 Byte 3 of 3 (property)
- 0, 0, 24, 24, 24, 24, 24, 24, 0, 0, 24, 24, 24, 24, 24, 24,
- 0, 0, 24, 24, 24, 24, 24, 24, 0, 0, 24, 24, 24, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[186 + 2] 0x000000 Byte 2 of 4
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-187,212,221,224, 2, 2,227, 2, 2, 2, 2,233, 2,235,239, 2,
-136,136,136,136,136,136,136,136, 136,136,243,245, 2, 2, 2,248,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[187 + 2] 0x010000 Byte 3 of 4
-188,189,190,191, 3, 3, 3,192, 3, 3,193,194,195,196,197,198,
-199,200,201, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-202,203, 3, 3,204, 3,205, 3, 206,207, 3, 3,208,209, 3, 3,
-210,211, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[188 + 2] 0x010000 Byte 4 of 4 (property)
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 47, 47, 0, 47,
-
-// state[189 + 2] 0x010040 Byte 4 of 4 (property)
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[190 + 2] 0x010080 Byte 4 of 4 (property)
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
-
-// state[191 + 2] 0x0100c0 Byte 4 of 4 (property)
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 0, 0, 0, 0, 0,
-
-// state[192 + 2] 0x0101c0 Byte 4 of 4 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0,
-
-// state[193 + 2] 0x010280 Byte 4 of 4 (property)
- 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 0, 0, 0,
- 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
- 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
-
-// state[194 + 2] 0x0102c0 Byte 4 of 4 (property)
- 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
- 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[195 + 2] 0x010300 Byte 4 of 4 (property)
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-
-// state[196 + 2] 0x010340 Byte 4 of 4 (property)
- 38, 0, 38, 38, 38, 38, 38, 38, 38, 38, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[197 + 2] 0x010380 Byte 4 of 4 (property)
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-
-// state[198 + 2] 0x0103c0 Byte 4 of 4 (property)
- 59, 59, 59, 59, 0, 0, 0, 0, 59, 59, 59, 59, 59, 59, 59, 59,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[199 + 2] 0x010400 Byte 4 of 4 (property)
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
-
-// state[200 + 2] 0x010440 Byte 4 of 4 (property)
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-
-// state[201 + 2] 0x010480 Byte 4 of 4 (property)
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[202 + 2] 0x010800 Byte 4 of 4 (property)
- 51, 51, 51, 51, 51, 51, 0, 0, 51, 0, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 0, 51, 51, 0, 0, 0, 51, 0, 0, 51,
-
-// state[203 + 2] 0x010840 Byte 4 of 4 (property)
- 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
- 86, 86, 86, 86, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[204 + 2] 0x010900 Byte 4 of 4 (property)
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 0, 0, 0, 0, 0, 0,
-
-// state[205 + 2] 0x010980 Byte 4 of 4 (property)
- 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0, 0, 0, 96, 96,
-
-// state[206 + 2] 0x010a00 Byte 4 of 4 (property)
- 60, 60, 60, 60, 0, 60, 60, 0, 0, 0, 0, 0, 60, 60, 60, 60,
- 60, 60, 60, 60, 0, 60, 60, 60, 0, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 0, 0, 0, 0, 60, 60, 60, 0, 0, 0, 0, 60,
-
-// state[207 + 2] 0x010a40 Byte 4 of 4 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 0, 0,
-
-// state[208 + 2] 0x010b00 Byte 4 of 4 (property)
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[209 + 2] 0x010b40 Byte 4 of 4 (property)
- 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
- 89, 89, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[210 + 2] 0x010c00 Byte 4 of 4 (property)
- 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
-
-// state[211 + 2] 0x010c40 Byte 4 of 4 (property)
- 90, 90, 90, 90, 90, 90, 90, 90, 90, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[212 + 2] 0x011000 Byte 3 of 4
-213,214,215,216,217, 3,218,219, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,220, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[213 + 2] 0x011000 Byte 4 of 4 (property)
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
-
-// state[214 + 2] 0x011040 Byte 4 of 4 (property)
- 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[215 + 2] 0x011080 Byte 4 of 4 (property)
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 0, 0, 0, 0,
-
-// state[216 + 2] 0x0110c0 Byte 4 of 4 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-100,100,100,100,100,100,100,100, 100,100,100,100,100,100,100,100,
-100,100,100,100,100,100,100,100, 100, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[217 + 2] 0x011100 Byte 4 of 4 (property)
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[218 + 2] 0x011180 Byte 4 of 4 (property)
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-
-// state[219 + 2] 0x0111c0 Byte 4 of 4 (property)
- 99, 99, 99, 99, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[220 + 2] 0x011680 Byte 4 of 4 (property)
-101,101,101,101,101,101,101,101, 101,101,101,101,101,101,101,101,
-101,101,101,101,101,101,101,101, 101,101,101,101,101,101,101,101,
-101,101,101,101,101,101,101,101, 101,101,101,101,101,101,101,101,
-101,101,101,101,101,101,101,101, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[221 + 2] 0x012000 Byte 3 of 4
-222,222,222,222,222,222,222,222, 222,222,222,222,222,223, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[222 + 2] 0x012000 Byte 4 of 4 (property)
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
-
-// state[223 + 2] 0x012340 Byte 4 of 4 (property)
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[224 + 2] 0x013000 Byte 3 of 4
-225,225,225,225,225,225,225,225, 225,225,225,225,225,225,225,225,
-226, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[225 + 2] 0x013000 Byte 4 of 4 (property)
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
-
-// state[226 + 2] 0x013400 Byte 4 of 4 (property)
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[227 + 2] 0x016000 Byte 3 of 4
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-228,228,228,228,228,228,228,228, 229, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,230,231,232, 3,
-
-// state[228 + 2] 0x016800 Byte 4 of 4 (property)
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
-
-// state[229 + 2] 0x016a00 Byte 4 of 4 (property)
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 0, 0, 0, 0, 0, 0, 0,
-
-// state[230 + 2] 0x016f00 Byte 4 of 4 (property)
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
-
-// state[231 + 2] 0x016f40 Byte 4 of 4 (property)
- 98, 98, 98, 98, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 0,
-
-// state[232 + 2] 0x016f80 Byte 4 of 4 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98,
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[233 + 2] 0x01b000 Byte 3 of 4
-234, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[234 + 2] 0x01b000 Byte 4 of 4 (property)
- 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[235 + 2] 0x01d000 Byte 3 of 4
- 3, 3, 3, 3, 3,236,237, 3, 3,238, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[236 + 2] 0x01d140 Byte 4 of 4 (property)
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 40,
-
-// state[237 + 2] 0x01d180 Byte 4 of 4 (property)
- 40, 40, 40, 0, 0, 40, 40, 40, 40, 40, 40, 40, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[238 + 2] 0x01d240 Byte 4 of 4 (property)
- 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[239 + 2] 0x01e000 Byte 3 of 4
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 240,241,242, 3, 3, 3, 3, 3,
-
-// state[240 + 2] 0x01ee00 Byte 4 of 4 (property)
- 6, 6, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 0, 6, 6, 0, 6, 0, 0, 6, 0, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 0, 6, 6, 6, 6, 0, 6, 0, 6, 0, 0, 0, 0,
-
-// state[241 + 2] 0x01ee40 Byte 4 of 4 (property)
- 0, 0, 6, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 6, 6,
- 0, 6, 6, 0, 6, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 6,
- 0, 6, 6, 0, 6, 0, 0, 6, 6, 6, 6, 0, 6, 6, 6, 6,
- 6, 6, 6, 0, 6, 6, 6, 6, 0, 6, 6, 6, 6, 0, 6, 0,
-
-// state[242 + 2] 0x01ee80 Byte 4 of 4 (property)
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0,
- 0, 6, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0,
-
-// state[243 + 2] 0x02a000 Byte 3 of 4
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,244, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
-
-// state[244 + 2] 0x02a6c0 Byte 4 of 4 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[245 + 2] 0x02b000 Byte 3 of 4
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,246, 67, 67, 67,
-247, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[246 + 2] 0x02b700 Byte 4 of 4 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[247 + 2] 0x02b800 Byte 4 of 4 (property)
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[248 + 2] 0x02f000 Byte 3 of 4
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 67, 67, 67, 67, 67, 67, 67, 67, 247, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[249 + 2] 0x0c0000 Byte 2 of 4
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-250, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[250 + 2] 0x0e0000 Byte 3 of 4
- 3, 3, 3, 3, 11, 11, 11,251, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[251 + 2] 0x0e01c0 Byte 4 of 4 (property)
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-};
-
-// Remap base[0] = (del, add, string_offset)
-static const RemapEntry utf8prop_lettermarkscriptnum_remap_base[] = {
-{0,0,0} };
-
-// Remap string[0]
-static const unsigned char utf8prop_lettermarkscriptnum_remap_string[] = {
-0 };
-
-static const UTF8PropObj_2 utf8prop_lettermarkscriptnum_obj = {
- utf8prop_lettermarkscriptnum_STATE0,
- utf8prop_lettermarkscriptnum_STATE0_SIZE,
- utf8prop_lettermarkscriptnum_TOTAL_SIZE,
- utf8prop_lettermarkscriptnum_MAX_EXPAND_X4,
- utf8prop_lettermarkscriptnum_SHIFT,
- utf8prop_lettermarkscriptnum_BYTES,
- utf8prop_lettermarkscriptnum_LOSUB,
- utf8prop_lettermarkscriptnum_HIADD,
- utf8prop_lettermarkscriptnum,
- utf8prop_lettermarkscriptnum_remap_base,
- utf8prop_lettermarkscriptnum_remap_string,
- NULL
-};
-
-
-#undef X__
-#undef RJ_
-#undef S1_
-#undef S2_
-#undef S3_
-#undef S21
-#undef S31
-#undef S32
-#undef T1_
-#undef T2_
-#undef S11
-#undef SP_
-#undef D__
-#undef RJA
-
-// Table has 32512 bytes, Hash = E250-03E6
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_UTF8PROP_LETTERMARKSCRIPTNUM_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/utf8repl_lettermarklower.h b/chromium/third_party/cld_3/src/src/script_span/utf8repl_lettermarklower.h
deleted file mode 100644
index adc59d4c0dc..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/utf8repl_lettermarklower.h
+++ /dev/null
@@ -1,758 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Created by utf8tablebuilder version 2.9
-//
-// Replaces all codes from file:
-// lettermarklower_6.2.0.txt
-// Accepts all other UTF-8 codes 0000..10FFFF
-// Space optimized
-//
-// ** ASSUMES INPUT IS STRUCTURALLY VALID UTF-8 **
-//
-// Table entries are absolute statetable subscripts
-
-#ifndef SCRIPT_SPAN_UTF8REPL_LETTERMARKLOWER_H_
-#define SCRIPT_SPAN_UTF8REPL_LETTERMARKLOWER_H_
-
-#include "integral_types.h"
-#include "utf8statetable.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-#define X__ (kExitIllegalStructure)
-#define RJ_ (kExitReject)
-#define S1_ (kExitReplace1)
-#define S2_ (kExitReplace2)
-#define S3_ (kExitReplace3)
-#define S21 (kExitReplace21)
-#define S31 (kExitReplace31)
-#define S32 (kExitReplace32)
-#define T1_ (kExitReplaceOffset1)
-#define T2_ (kExitReplaceOffset2)
-#define S11 (kExitReplace1S0)
-#define SP_ (kExitSpecial)
-#define D__ (kExitDoAgain)
-#define RJA (kExitRejectAlt)
-
-// Entire table has 111 state blocks of 64 entries each
-
-static const unsigned int utf8repl_lettermarklower_STATE0 = 0; // state[0]
-static const unsigned int utf8repl_lettermarklower_STATE0_SIZE = 320; // =[5]
-static const unsigned int utf8repl_lettermarklower_TOTAL_SIZE = 7104;
-static const unsigned int utf8repl_lettermarklower_MAX_EXPAND_X4 = 12;
-static const unsigned int utf8repl_lettermarklower_SHIFT = 6;
-static const unsigned int utf8repl_lettermarklower_BYTES = 1;
-static const unsigned int utf8repl_lettermarklower_LOSUB = 0x5b5b5b5b;
-static const unsigned int utf8repl_lettermarklower_HIADD = 0x00000000;
-
-static const uint8 utf8repl_lettermarklower[] = {
-// state[0] 0x000000 Byte 1
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
- 0,S11,S11,S11,S11,S11,S11,S11, S11,S11,S11,S11,S11,S11,S11,S11,
-S11,S11,S11,S11,S11,S11,S11,S11, S11,S11,S11, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__, 6, 11, 13, 16, 19, 22, 25, 28, 6, 6, 6, 31, 33, 36,
- 39, 42, 44, 46, 48, 51, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 54, 74, 8, 8, 8, 8, 8, 8, 8, 88, 8, 8, 8, 8,100,
-104, 9, 9, 9, 10,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x61,0x62,0x63,0x64,0x65,0x66,0x67, 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
-0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, 0x78,0x79,0x7a,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[6 + 2] 0x000080 Byte 2 of 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[7 + 2] 0x000000 Byte 2 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[8 + 2] 0x003000 Byte 2 of 3
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[9 + 2] 0x040000 Byte 2 of 4
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-
-// state[10 + 2] 0x100000 Byte 2 of 4
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[11 + 2] 0x0000c0 Byte 2 of 2
-S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
-S1_,S1_,S1_,S1_,S1_,S1_,S1_, 0, S1_,S1_,S1_,S1_,S1_,S1_,S1_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
-0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0x00, 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[13 + 2] 0x000100 Byte 2 of 2
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S21, 0,S1_, 0,S1_, 0,S1_, 0, 0,S1_, 0,S1_, 0,S1_, 0,S2_,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0x69,0x00,0xb3,0x00,0xb5,0x00,0xb7,0x00, 0x00,0xba,0x00,0xbc,0x00,0xbe,0x00,0x80,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,
-
-// state[16 + 2] 0x000140 Byte 2 of 2
- 0,S1_, 0,S1_, 0,S1_, 0,S1_, 0, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S2_,S1_, 0,S1_, 0,S1_, 0, 0,
-
-0x00,0x82,0x00,0x84,0x00,0x86,0x00,0x88, 0x00,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0xb1,0x00,0xb3,0x00,0xb5,0x00,0xb7,0x00, 0xbf,0xba,0x00,0xbc,0x00,0xbe,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[19 + 2] 0x000180 Byte 2 of 2
- 0,S2_,S1_, 0,S1_, 0,S2_,S1_, 0,S2_,S2_,S1_, 0, 0,S2_,S2_,
-S2_,S1_, 0,S2_,S2_, 0,S2_,S2_, S1_, 0, 0, 0,S2_,S2_, 0,S2_,
-S1_, 0,S1_, 0,S1_, 0,S2_,S1_, 0,S2_, 0, 0,S1_, 0,S2_,S1_,
- 0,S2_,S2_,S1_, 0,S1_, 0,S2_, S1_, 0, 0, 0,S1_, 0, 0, 0,
-
-0x00,0x93,0x83,0x00,0x85,0x00,0x94,0x88, 0x00,0x96,0x97,0x8c,0x00,0x00,0x9d,0x99,
-0x9b,0x92,0x00,0xa0,0xa3,0x00,0xa9,0xa8, 0x99,0x00,0x00,0x00,0xaf,0xb2,0x00,0xb5,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0x80,0xa8, 0x00,0x83,0x00,0x00,0xad,0x00,0x88,0xb0,
-0x00,0x8a,0x8b,0xb4,0x00,0xb6,0x00,0x92, 0xb9,0x00,0x00,0x00,0xbd,0x00,0x00,0x00,
-
-0x00,0xc9,0x00,0x00,0x00,0x00,0xc9,0x00, 0x00,0xc9,0xc9,0x00,0x00,0x00,0xc7,0xc9,
-0xc9,0x00,0x00,0xc9,0xc9,0x00,0xc9,0xc9, 0x00,0x00,0x00,0x00,0xc9,0xc9,0x00,0xc9,
-0x00,0x00,0x00,0x00,0x00,0x00,0xca,0x00, 0x00,0xca,0x00,0x00,0x00,0x00,0xca,0x00,
-0x00,0xca,0xca,0x00,0x00,0x00,0x00,0xca, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[22 + 2] 0x0001c0 Byte 2 of 2
- 0, 0, 0, 0,S1_,S1_, 0,S1_, S1_, 0,S1_,S1_, 0,S1_, 0,S1_,
- 0,S1_, 0,S1_, 0,S1_, 0,S1_, 0,S1_, 0,S1_, 0, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
- 0,S1_,S1_, 0,S1_, 0,S2_,S2_, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-
-0x00,0x00,0x00,0x00,0x86,0x86,0x00,0x89, 0x89,0x00,0x8c,0x8c,0x00,0x8e,0x00,0x90,
-0x00,0x92,0x00,0x94,0x00,0x96,0x00,0x98, 0x00,0x9a,0x00,0x9c,0x00,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0x00,0xb3,0xb3,0x00,0xb5,0x00,0x95,0xbf, 0xb9,0x00,0xbb,0x00,0xbd,0x00,0xbf,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0xc6,0xc6, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[25 + 2] 0x000200 Byte 2 of 2
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S2_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0, 0, 0, 0, 0, 0, 0,T1_,S1_, 0,S2_,T1_, 0,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0x9e,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0xb1,0x00,0xb3,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xbc,0x00,0x9a,0x01,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0xc6,0x00,0x00,
-
-// state[28 + 2] 0x000240 Byte 2 of 2
- 0,S1_, 0,S2_,S2_,S2_,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x00,0x82,0x00,0x80,0x89,0x8c,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0xc6,0xca,0xca,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[31 + 2] 0x000340 Byte 2 of 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-S1_, 0,S1_, 0, 0, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xb1,0x00,0xb3,0x00,0x00,0x00,0xb7,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[33 + 2] 0x000380 Byte 2 of 2
- 0, 0, 0, 0, 0, 0,S1_, 0, S1_,S1_,S1_, 0,S2_, 0,S2_,S2_,
- 0,S1_,S1_,S1_,S1_,S1_,S1_,S1_, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
-S2_,S2_, 0,S2_,S2_,S2_,S2_,S2_, S2_,S2_,S2_,S2_, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00, 0xad,0xae,0xaf,0x00,0x8c,0x00,0x8d,0x8e,
-0x00,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7, 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
-0x80,0x81,0x00,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x8a,0x8b,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xcf,0x00,0xcf,0xcf,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xcf,0xcf,0x00,0xcf,0xcf,0xcf,0xcf,0xcf, 0xcf,0xcf,0xcf,0xcf,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[36 + 2] 0x0003c0 Byte 2 of 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,S1_,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
- 0, 0, 0, 0,S2_, 0, 0,S1_, 0,S1_,S1_, 0, 0,S2_,S2_,S2_,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x97,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0x00,0x00,0x00,0x00,0xb8,0x00,0x00,0xb8, 0x00,0xb2,0xbb,0x00,0x00,0xbb,0xbc,0xbd,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0xce,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0xcd,0xcd,0xcd,
-
-// state[39 + 2] 0x000400 Byte 2 of 2
-S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_, S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_,
-S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
-S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_, S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
-0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7, 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
-0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, 0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1, 0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[42 + 2] 0x000440 Byte 2 of 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0xb1,0x00,0xb3,0x00,0xb5,0x00,0xb7,0x00, 0xb9,0x00,0xbb,0x00,0xbd,0x00,0xbf,0x00,
-
-// state[44 + 2] 0x000480 Byte 2 of 2
-S1_, 0, 0, 0, 0, 0, 0, 0, 0, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-
-0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0xb1,0x00,0xb3,0x00,0xb5,0x00,0xb7,0x00, 0xb9,0x00,0xbb,0x00,0xbd,0x00,0xbf,0x00,
-
-// state[46 + 2] 0x0004c0 Byte 2 of 2
-S1_,S1_, 0,S1_, 0,S1_, 0,S1_, 0,S1_, 0,S1_, 0,S1_, 0, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-
-0x8f,0x82,0x00,0x84,0x00,0x86,0x00,0x88, 0x00,0x8a,0x00,0x8c,0x00,0x8e,0x00,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0xb1,0x00,0xb3,0x00,0xb5,0x00,0xb7,0x00, 0xb9,0x00,0xbb,0x00,0xbd,0x00,0xbf,0x00,
-
-// state[48 + 2] 0x000500 Byte 2 of 2
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,S2_,S2_,S2_,S2_,S2_,S2_,S2_, S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7, 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5, 0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,0xd5,
-
-// state[51 + 2] 0x000540 Byte 2 of 2
-S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
-S2_,S2_,S2_,S2_,S2_,S2_,S2_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7, 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
-0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0xd6,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[54 + 2] 0x001000 Byte 2 of 3
- 6, 6, 55, 57, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 59, 59, 61, 59, 64, 66, 68, 71,
-
-// state[55 + 2] 0x001080 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-T1_,T1_,T1_,T1_,T1_,T1_,T1_,T1_, T1_,T1_,T1_,T1_,T1_,T1_,T1_,T1_,
-T1_,T1_,T1_,T1_,T1_,T1_,T1_,T1_, T1_,T1_,T1_,T1_,T1_,T1_,T1_,T1_,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,
-0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,
-
-// state[57 + 2] 0x0010c0 Byte 3 of 3
-T1_,T1_,T1_,T1_,T1_,T1_, 0,T1_, 0, 0, 0, 0, 0,T1_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x22,0x23,0x24,0x25,0x26,0x27,0x00,0x28, 0x00,0x00,0x00,0x00,0x00,0x29,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[59 + 2] 0x001e00 Byte 3 of 3
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0xb1,0x00,0xb3,0x00,0xb5,0x00,0xb7,0x00, 0xb9,0x00,0xbb,0x00,0xbd,0x00,0xbf,0x00,
-
-// state[61 + 2] 0x001e80 Byte 3 of 3
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0, 0,S32, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0xb1,0x00,0xb3,0x00,0xb5,0x00,0xb7,0x00, 0xb9,0x00,0xbb,0x00,0xbd,0x00,0xbf,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[64 + 2] 0x001f00 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x90,0x91,0x92,0x93,0x94,0x95,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
-
-// state[66 + 2] 0x001f40 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,S1_, 0,S1_, 0,S1_, 0,S1_,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x80,0x81,0x82,0x83,0x84,0x85,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x91,0x00,0x93,0x00,0x95,0x00,0x97,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[68 + 2] 0x001f80 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S2_,S2_,S1_, 0, 0, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xb0,0xb1,0xb0,0xb1,0xb3,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xbd,0xbd,0x00,0x00,0x00,0x00,
-
-// state[71 + 2] 0x001fc0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, S2_,S2_,S2_,S2_,S1_, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S2_,S2_, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, S1_,S1_,S2_,S2_,S1_, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, S2_,S2_,S2_,S2_,S1_, 0, 0, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xb2,0xb3,0xb4,0xb5,0x83,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x90,0x91,0xb6,0xb7,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xa0,0xa1,0xba,0xbb,0xa5,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xb8,0xb9,0xbc,0xbd,0xb3,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xbd,0xbd,0xbd,0xbd,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xbd,0xbd,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xbd,0xbd,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xbd,0xbd,0xbd,0xbd,0x00,0x00,0x00,0x00,
-
-// state[74 + 2] 0x002000 Byte 2 of 3
- 6, 6, 6, 6, 75, 6, 78, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 80, 83, 59, 86, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[75 + 2] 0x002100 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,S32, 0, 0, 0,S31,S32, 0, 0, 0, 0,
- 0, 0,S2_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x00, 0x00,0x00,0x6b,0xa5,0x00,0x00,0x00,0x00,
-0x00,0x00,0x8e,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x00, 0x00,0x00,0x00,0xc3,0x00,0x00,0x00,0x00,
-0x00,0x00,0x85,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[78 + 2] 0x002180 Byte 3 of 3
- 0, 0, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[80 + 2] 0x002c00 Byte 3 of 3
-S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
-S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_, S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_,
-S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_, S2_,S2_,S2_,S2_,S2_,S2_,S2_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7, 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
-0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
-0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,
-0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[83 + 2] 0x002c40 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-S1_, 0,S32,T1_,S32, 0, 0,S1_, 0,S1_, 0,S1_, 0,S32,S32,S32,
-S32, 0,S1_, 0, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0,S32,S32,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xa1,0x00,0xab,0x2a,0xbd,0x00,0x00,0xa8, 0x00,0xaa,0x00,0xac,0x00,0x91,0xb1,0x90,
-0x92,0x00,0xb3,0x00,0x00,0xb6,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xbf,0x80,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc9,0x00,0xc9,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0xc9,0xc9,0xc9,
-0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0xc9,
-
-// state[86 + 2] 0x002cc0 Byte 3 of 3
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0,S1_, 0,S1_, 0, 0,
- 0, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xac,0x00,0xae,0x00,0x00,
-0x00,0x00,0xb3,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[88 + 2] 0x00a000 Byte 2 of 3
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 89, 91, 6, 93, 95, 97, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[89 + 2] 0x00a640 Byte 3 of 3
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[91 + 2] 0x00a680 Byte 3 of 3
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[93 + 2] 0x00a700 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
- 0, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0x00,0x00,0xb3,0x00,0xb5,0x00,0xb7,0x00, 0xb9,0x00,0xbb,0x00,0xbd,0x00,0xbf,0x00,
-
-// state[95 + 2] 0x00a740 Byte 3 of 3
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S1_, 0,S1_, 0,S1_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,S1_, 0,S1_, 0,T1_,S1_, 0,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x89,0x00,0x8b,0x00,0x8d,0x00,0x8f,0x00,
-0x91,0x00,0x93,0x00,0x95,0x00,0x97,0x00, 0x99,0x00,0x9b,0x00,0x9d,0x00,0x9f,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xab,0x00,0xad,0x00,0xaf,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0xba,0x00,0xbc,0x00,0x2b,0xbf,0x00,
-
-// state[97 + 2] 0x00a780 Byte 3 of 3
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, 0, 0, 0,S1_, 0,S32, 0, 0,
-S1_, 0,S1_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-S1_, 0,S1_, 0,S1_, 0,S1_, 0, S1_, 0,S32, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0x81,0x00,0x83,0x00,0x85,0x00,0x87,0x00, 0x00,0x00,0x00,0x8c,0x00,0xa5,0x00,0x00,
-0x91,0x00,0x93,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xa1,0x00,0xa3,0x00,0xa5,0x00,0xa7,0x00, 0xa9,0x00,0xa6,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-// state[100 + 2] 0x00f000 Byte 2 of 3
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,101, 6, 6, 6,
-
-// state[101 + 2] 0x00ff00 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,S2_,S2_,S2_,S2_,S2_,S2_,S2_, S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_,
-S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_, S2_,S2_,S2_, 0, 0, 0, 0, 0,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
-0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, 0x98,0x99,0x9a,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, 0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,
-0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd,0xbd, 0xbd,0xbd,0xbd,0x00,0x00,0x00,0x00,0x00,
-
-// state[104 + 2] 0x000000 Byte 2 of 4
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-105, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-
-// state[105 + 2] 0x010000 Byte 3 of 4
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-106, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-
-// state[106 + 2] 0x010400 Byte 4 of 4
-S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_, S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_,
-S1_,S1_,S1_,S1_,S1_,S1_,S1_,S1_, S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_,
-S2_,S2_,S2_,S2_,S2_,S2_,S2_,S2_, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
-0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
-0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91,
-0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-};
-
-// Remap base[44] = (del, add, string_offset)
-static const RemapEntry utf8repl_lettermarklower_remap_base[] = {
-{2,3, 0}, {2,3, 3}, {3,3, 6}, {3,3, 9},
-{3,3, 12}, {3,3, 15}, {3,3, 18}, {3,3, 21},
-{3,3, 24}, {3,3, 27}, {3,3, 30}, {3,3, 33},
-{3,3, 36}, {3,3, 39}, {3,3, 42}, {3,3, 45},
-
-{3,3, 48}, {3,3, 51}, {3,3, 54}, {3,3, 57},
-{3,3, 60}, {3,3, 63}, {3,3, 66}, {3,3, 69},
-{3,3, 72}, {3,3, 75}, {3,3, 78}, {3,3, 81},
-{3,3, 84}, {3,3, 87}, {3,3, 90}, {3,3, 93},
-
-{3,3, 96}, {3,3, 99}, {3,3, 102}, {3,3, 105},
-{3,3, 108}, {3,3, 111}, {3,3, 114}, {3,3, 117},
-{3,3, 120}, {3,3, 123}, {3,3, 126}, {3,3, 129},
-{0,0,0} };
-
-// Remap string[132]
-static const unsigned char utf8repl_lettermarklower_remap_string[] = {
-0xe2,0xb1,0xa5,0xe2,0xb1,0xa6,0xe2,0xb4, 0x80,0xe2,0xb4,0x81,0xe2,0xb4,0x82,0xe2,
-0xb4,0x83,0xe2,0xb4,0x84,0xe2,0xb4,0x85, 0xe2,0xb4,0x86,0xe2,0xb4,0x87,0xe2,0xb4,
-0x88,0xe2,0xb4,0x89,0xe2,0xb4,0x8a,0xe2, 0xb4,0x8b,0xe2,0xb4,0x8c,0xe2,0xb4,0x8d,
-0xe2,0xb4,0x8e,0xe2,0xb4,0x8f,0xe2,0xb4, 0x90,0xe2,0xb4,0x91,0xe2,0xb4,0x92,0xe2,
-
-0xb4,0x93,0xe2,0xb4,0x94,0xe2,0xb4,0x95, 0xe2,0xb4,0x96,0xe2,0xb4,0x97,0xe2,0xb4,
-0x98,0xe2,0xb4,0x99,0xe2,0xb4,0x9a,0xe2, 0xb4,0x9b,0xe2,0xb4,0x9c,0xe2,0xb4,0x9d,
-0xe2,0xb4,0x9e,0xe2,0xb4,0x9f,0xe2,0xb4, 0xa0,0xe2,0xb4,0xa1,0xe2,0xb4,0xa2,0xe2,
-0xb4,0xa3,0xe2,0xb4,0xa4,0xe2,0xb4,0xa5, 0xe2,0xb4,0xa7,0xe2,0xb4,0xad,0xe1,0xb5,
-
-0xbd,0xe1,0xb5,0xb9,0 };
-
-static const unsigned char utf8repl_lettermarklower_fast[256] = {
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-
-0,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-
-};
-
-static const UTF8ReplaceObj utf8repl_lettermarklower_obj = {
- utf8repl_lettermarklower_STATE0,
- utf8repl_lettermarklower_STATE0_SIZE,
- utf8repl_lettermarklower_TOTAL_SIZE,
- utf8repl_lettermarklower_MAX_EXPAND_X4,
- utf8repl_lettermarklower_SHIFT,
- utf8repl_lettermarklower_BYTES,
- utf8repl_lettermarklower_LOSUB,
- utf8repl_lettermarklower_HIADD,
- utf8repl_lettermarklower,
- utf8repl_lettermarklower_remap_base,
- utf8repl_lettermarklower_remap_string,
- utf8repl_lettermarklower_fast
-};
-
-
-#undef X__
-#undef RJ_
-#undef S1_
-#undef S2_
-#undef S3_
-#undef S21
-#undef S31
-#undef S32
-#undef T1_
-#undef T2_
-#undef S11
-#undef SP_
-#undef D__
-#undef RJA
-
-// Table has 7668 bytes, Hash = 07A2-C4E3
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_UTF8REPL_LETTERMARKLOWER_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/utf8scannot_lettermarkspecial.h b/chromium/third_party/cld_3/src/src/script_span/utf8scannot_lettermarkspecial.h
deleted file mode 100644
index 2ddad2fb6af..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/utf8scannot_lettermarkspecial.h
+++ /dev/null
@@ -1,1455 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// Created by utf8tablebuilder version 2.9
-//
-// Rejects all codes from file:
-// lettermarkspecial_6.2.0.txt
-// Accepts all other UTF-8 codes 0000..10FFFF
-// Space optimized
-//
-// ** ASSUMES INPUT IS STRUCTURALLY VALID UTF-8 **
-//
-// Table entries are absolute statetable subscripts
-
-#ifndef SCRIPT_SPAN_UTF8SCANNOT_LETTERMARKSPECIAL_H_
-#define SCRIPT_SPAN_UTF8SCANNOT_LETTERMARKSPECIAL_H_
-
-#include "integral_types.h"
-#include "utf8statetable.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-#define X__ (kExitIllegalStructure)
-#define RJ_ (kExitReject)
-#define S1_ (kExitReplace1)
-#define S2_ (kExitReplace2)
-#define S3_ (kExitReplace3)
-#define S21 (kExitReplace21)
-#define S31 (kExitReplace31)
-#define S32 (kExitReplace32)
-#define T1_ (kExitReplaceOffset1)
-#define T2_ (kExitReplaceOffset2)
-#define S11 (kExitReplace1S0)
-#define SP_ (kExitSpecial)
-#define D__ (kExitDoAgain)
-#define RJA (kExitRejectAlt)
-
-// Entire table has 221 state blocks of 64 entries each
-
-static const unsigned int utf8scannot_lettermarkspecial_STATE0 = 0; // state[0]
-static const unsigned int utf8scannot_lettermarkspecial_STATE0_SIZE = 64; // =[1]
-static const unsigned int utf8scannot_lettermarkspecial_TOTAL_SIZE = 14144;
-static const unsigned int utf8scannot_lettermarkspecial_MAX_EXPAND_X4 = 0;
-static const unsigned int utf8scannot_lettermarkspecial_SHIFT = 6;
-static const unsigned int utf8scannot_lettermarkspecial_BYTES = 1;
-static const unsigned int utf8scannot_lettermarkspecial_LOSUB = 0x27272727;
-static const unsigned int utf8scannot_lettermarkspecial_HIADD = 0x44444444;
-
-static const uint8 utf8scannot_lettermarkspecial[] = {
-// state[0] 0x000000 Byte 1
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_, 0,RJ_, 0,
-
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-X__,X__, 6, 7, 8, 8, 8, 8, 8, 8, 8, 9, 8, 10, 11, 12,
- 8, 8, 13, 8, 14, 15, 16, 17, 18, 19, 8, 20, 21, 22, 23, 24,
- 25, 57, 95,110,117,118,118,118, 118,119,121,118,118,140, 2,143,
-159, 4, 4,216, 5,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[2 + 2] 0x00e000 Byte 2 of 3
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[3 + 2] 0x001ac0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[4 + 2] 0x040000 Byte 2 of 4
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[5 + 2] 0x100000 Byte 2 of 4
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-
-// state[6 + 2] 0x000080 Byte 2 of 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,RJ_, 0, 0, 0, 0,RJ_, 0, 0, 0, 0, 0,
-
-// state[7 + 2] 0x0000c0 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[8 + 2] 0x000100 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[9 + 2] 0x0002c0 Byte 2 of 2
-RJ_,RJ_, 0, 0, 0, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0,RJ_, 0,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[10 + 2] 0x000340 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
-
-// state[11 + 2] 0x000380 Byte 2 of 2
- 0, 0, 0, 0, 0, 0,RJ_, 0, RJ_,RJ_,RJ_, 0,RJ_, 0,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[12 + 2] 0x0003c0 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[13 + 2] 0x000480 Byte 2 of 2
-RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[14 + 2] 0x000500 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[15 + 2] 0x000540 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_, 0, 0, 0, 0, 0, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[16 + 2] 0x000580 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,
-
-// state[17 + 2] 0x0005c0 Byte 2 of 2
- 0,RJ_,RJ_, 0,RJ_,RJ_, 0,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[18 + 2] 0x000600 Byte 2 of 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[19 + 2] 0x000640 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[20 + 2] 0x0006c0 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_, 0, 0,RJ_,
-
-// state[21 + 2] 0x000700 Byte 2 of 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[22 + 2] 0x000740 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[23 + 2] 0x000780 Byte 2 of 2
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[24 + 2] 0x0007c0 Byte 2 of 2
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,RJ_, 0, 0, 0, 0, 0,
-
-// state[25 + 2] 0x000000 Byte 2 of 3
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
- 26, 27, 28, 29, 8, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
-
-// state[26 + 2] 0x000800 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[27 + 2] 0x000840 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[28 + 2] 0x000880 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[29 + 2] 0x0008c0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-
-// state[30 + 2] 0x000940 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[31 + 2] 0x000980 Byte 3 of 3
- 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,
-RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0,RJ_, 0, 0, 0,RJ_,RJ_, RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[32 + 2] 0x0009c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_, RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0,RJ_, 0, 0, 0, 0,RJ_,RJ_, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[33 + 2] 0x000a00 Byte 3 of 3
- 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0,RJ_,
-RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_, 0,RJ_,RJ_, 0, RJ_,RJ_, 0, 0,RJ_, 0,RJ_,RJ_,
-
-// state[34 + 2] 0x000a40 Byte 3 of 3
-RJ_,RJ_,RJ_, 0, 0, 0, 0,RJ_, RJ_, 0, 0,RJ_,RJ_,RJ_, 0, 0,
- 0,RJ_, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[35 + 2] 0x000a80 Byte 3 of 3
- 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,
-RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[36 + 2] 0x000ac0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, RJ_,RJ_, 0,RJ_,RJ_,RJ_, 0, 0,
-RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[37 + 2] 0x000b00 Byte 3 of 3
- 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,
-RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[38 + 2] 0x000b40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_, RJ_, 0, 0,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0,RJ_,RJ_, 0, 0, 0, 0,RJ_,RJ_, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[39 + 2] 0x000b80 Byte 3 of 3
- 0, 0,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,RJ_,RJ_, 0,RJ_, 0,RJ_,RJ_,
- 0, 0, 0,RJ_,RJ_, 0, 0, 0, RJ_,RJ_,RJ_, 0, 0, 0,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0, 0, 0,RJ_,RJ_,
-
-// state[40 + 2] 0x000bc0 Byte 3 of 3
-RJ_,RJ_,RJ_, 0, 0, 0,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_, 0, 0, 0, 0, 0, 0,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[41 + 2] 0x000c00 Byte 3 of 3
- 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0, 0,RJ_,RJ_,RJ_,
-
-// state[42 + 2] 0x000c40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0,RJ_,RJ_, 0, RJ_,RJ_, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[43 + 2] 0x000c80 Byte 3 of 3
- 0, 0,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[44 + 2] 0x000cc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[45 + 2] 0x000d00 Byte 3 of 3
- 0, 0,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,
-
-// state[46 + 2] 0x000d40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[47 + 2] 0x000d80 Byte 3 of 3
- 0, 0,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0, 0,
-
-// state[48 + 2] 0x000dc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,RJ_, 0, 0, 0, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[49 + 2] 0x000e00 Byte 3 of 3
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-
-// state[50 + 2] 0x000e40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[51 + 2] 0x000e80 Byte 3 of 3
- 0,RJ_,RJ_, 0,RJ_, 0, 0,RJ_, RJ_, 0,RJ_, 0, 0,RJ_, 0, 0,
- 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0,RJ_,RJ_,RJ_, 0,RJ_, 0,RJ_, 0, 0,RJ_,RJ_, 0,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0,RJ_,RJ_,RJ_, 0, 0,
-
-// state[52 + 2] 0x000ec0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[53 + 2] 0x000f00 Byte 3 of 3
-RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, RJ_,RJ_, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,RJ_, 0,RJ_, 0,RJ_, 0, 0, 0, 0,RJ_,RJ_,
-
-// state[54 + 2] 0x000f40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[55 + 2] 0x000f80 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-
-// state[56 + 2] 0x000fc0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[57 + 2] 0x001000 Byte 2 of 3
- 8, 21, 58, 59, 8, 8, 8, 8, 8, 60, 61, 62, 63, 64, 65, 66,
- 67, 8, 8, 8, 8, 8, 8, 8, 8, 68, 69, 70, 71, 72, 8, 73,
- 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 3, 8, 85, 86, 87,
- 75, 88, 3, 89, 8, 8, 8, 90, 8, 8, 8, 8, 91, 92, 93, 94,
-
-// state[58 + 2] 0x001080 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[59 + 2] 0x0010c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0, 0, 0, 0, 0,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[60 + 2] 0x001240 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[61 + 2] 0x001280 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-
-// state[62 + 2] 0x0012c0 Byte 3 of 3
-RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[63 + 2] 0x001300 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[64 + 2] 0x001340 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[65 + 2] 0x001380 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[66 + 2] 0x0013c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[67 + 2] 0x001400 Byte 3 of 3
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[68 + 2] 0x001640 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[69 + 2] 0x001680 Byte 3 of 3
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[70 + 2] 0x0016c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[71 + 2] 0x001700 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[72 + 2] 0x001740 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[73 + 2] 0x0017c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0,RJ_, 0, 0, 0, 0,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[74 + 2] 0x001800 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[75 + 2] 0x001840 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[76 + 2] 0x001880 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[77 + 2] 0x0018c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[78 + 2] 0x001900 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
-
-// state[79 + 2] 0x001940 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[80 + 2] 0x001980 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[81 + 2] 0x0019c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[82 + 2] 0x001a00 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[83 + 2] 0x001a40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,
-
-// state[84 + 2] 0x001a80 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[85 + 2] 0x001b40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[86 + 2] 0x001b80 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[87 + 2] 0x001bc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[88 + 2] 0x001c40 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-
-// state[89 + 2] 0x001cc0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[90 + 2] 0x001dc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[91 + 2] 0x001f00 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[92 + 2] 0x001f40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0,RJ_, 0,RJ_, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-
-// state[93 + 2] 0x001f80 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0,
-
-// state[94 + 2] 0x001fc0 Byte 3 of 3
- 0, 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
- 0, 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-
-// state[95 + 2] 0x002000 Byte 2 of 3
- 3, 96, 97, 98, 99,100,101, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-102,103, 8,104,105,106,107,108, 109, 3, 3, 3, 3, 3, 3, 3,
-
-// state[96 + 2] 0x002040 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,
-
-// state[97 + 2] 0x002080 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[98 + 2] 0x0020c0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[99 + 2] 0x002100 Byte 3 of 3
- 0, 0,RJ_, 0, 0, 0, 0,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0,RJ_, 0,RJ_, 0, RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[100 + 2] 0x002140 Byte 3 of 3
- 0, 0, 0, 0, 0,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0, 0, 0,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[101 + 2] 0x002180 Byte 3 of 3
- 0, 0, 0,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[102 + 2] 0x002c00 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[103 + 2] 0x002c40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[104 + 2] 0x002cc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[105 + 2] 0x002d00 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0, 0, 0, 0, 0,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[106 + 2] 0x002d40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,
-
-// state[107 + 2] 0x002d80 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-
-// state[108 + 2] 0x002dc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[109 + 2] 0x002e00 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[110 + 2] 0x003000 Byte 2 of 3
-111, 67,112,113,114, 8,115,116, 3, 3, 3, 3, 3, 3, 3, 3,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-
-// state[111 + 2] 0x003000 Byte 3 of 3
- 0, 0, 0, 0, 0,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,RJ_,RJ_, 0, 0, 0,
-
-// state[112 + 2] 0x003080 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[113 + 2] 0x0030c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[114 + 2] 0x003100 Byte 3 of 3
- 0, 0, 0, 0, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[115 + 2] 0x003180 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-
-// state[116 + 2] 0x0031c0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[117 + 2] 0x004000 Byte 2 of 3
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 77, 3, 8, 8, 8, 8, 8, 8, 8, 8,
-
-// state[118 + 2] 0x005000 Byte 2 of 3
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-
-// state[119 + 2] 0x009000 Byte 2 of 3
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,120,
-
-// state[120 + 2] 0x009fc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[121 + 2] 0x00a000 Byte 2 of 3
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8,120,122, 8, 8, 8, 8, 123,124,125,126,127, 8,128,129,
-130, 87, 8,131,132,133, 8,134, 135,136, 8,137,138, 3, 3,139,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-
-// state[122 + 2] 0x00a4c0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-
-// state[123 + 2] 0x00a600 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[124 + 2] 0x00a640 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,
-
-// state[125 + 2] 0x00a680 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[126 + 2] 0x00a6c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[127 + 2] 0x00a700 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[128 + 2] 0x00a780 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[129 + 2] 0x00a7c0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[130 + 2] 0x00a800 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[131 + 2] 0x00a8c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,RJ_, 0, 0, 0, 0,
-
-// state[132 + 2] 0x00a900 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[133 + 2] 0x00a940 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-
-// state[134 + 2] 0x00a9c0 Byte 3 of 3
-RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[135 + 2] 0x00aa00 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[136 + 2] 0x00aa40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,RJ_,RJ_, 0, 0, 0, 0,
-
-// state[137 + 2] 0x00aac0 Byte 3 of 3
-RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[138 + 2] 0x00ab00 Byte 3 of 3
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[139 + 2] 0x00abc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[140 + 2] 0x00d000 Byte 2 of 3
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,141,142,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[141 + 2] 0x00d780 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[142 + 2] 0x00d7c0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
-
-// state[143 + 2] 0x00f000 Byte 2 of 3
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 8, 8, 8, 8, 8,144, 8,145,146,147, 23,148,
- 8, 8, 8, 8,149, 21,150,151, 152,153, 8,154,155,156,157,158,
-
-// state[144 + 2] 0x00fa40 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[145 + 2] 0x00fac0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[146 + 2] 0x00fb00 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0,
-
-// state[147 + 2] 0x00fb40 Byte 3 of 3
-RJ_,RJ_, 0,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[148 + 2] 0x00fbc0 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[149 + 2] 0x00fd00 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-
-// state[150 + 2] 0x00fd80 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[151 + 2] 0x00fdc0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
-
-// state[152 + 2] 0x00fe00 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[153 + 2] 0x00fe40 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[154 + 2] 0x00fec0 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-
-// state[155 + 2] 0x00ff00 Byte 3 of 3
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-
-// state[156 + 2] 0x00ff40 Byte 3 of 3
- 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[157 + 2] 0x00ff80 Byte 3 of 3
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-
-// state[158 + 2] 0x00ffc0 Byte 3 of 3
- 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[159 + 2] 0x000000 Byte 2 of 4
-X__,X__,X__,X__,X__,X__,X__,X__, X__,X__,X__,X__,X__,X__,X__,X__,
-160,180,184,186, 2, 2,187, 2, 2, 2, 2,191, 2,193,208, 2,
-118,118,118,118,118,118,118,118, 118,118,212,214, 2, 2, 2,215,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[160 + 2] 0x010000 Byte 3 of 4
-161,162, 8,163, 3, 3, 3,164, 3, 3,165,166,167,168,169,170,
- 8, 8,171, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-172,173, 3, 3,174, 3,175, 3, 176,177, 3, 3, 77,178, 3, 3,
- 8,179, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[161 + 2] 0x010000 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0,RJ_,RJ_, 0,RJ_,
-
-// state[162 + 2] 0x010040 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[163 + 2] 0x0100c0 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0, 0, 0, 0, 0,
-
-// state[164 + 2] 0x0101c0 Byte 4 of 4
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_, 0, 0,
-
-// state[165 + 2] 0x010280 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[166 + 2] 0x0102c0 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[167 + 2] 0x010300 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[168 + 2] 0x010340 Byte 4 of 4
-RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[169 + 2] 0x010380 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[170 + 2] 0x0103c0 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[171 + 2] 0x010480 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[172 + 2] 0x010800 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, RJ_, 0, 0, 0,RJ_, 0, 0,RJ_,
-
-// state[173 + 2] 0x010840 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[174 + 2] 0x010900 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0, 0, 0, 0, 0,
-
-// state[175 + 2] 0x010980 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0,RJ_,RJ_,
-
-// state[176 + 2] 0x010a00 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, RJ_,RJ_,RJ_, 0, 0, 0, 0,RJ_,
-
-// state[177 + 2] 0x010a40 Byte 4 of 4
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0,
-
-// state[178 + 2] 0x010b40 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[179 + 2] 0x010c40 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[180 + 2] 0x011000 Byte 3 of 4
- 8,181,163,182, 66, 3, 8,183, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 75, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[181 + 2] 0x011040 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[182 + 2] 0x0110c0 Byte 4 of 4
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[183 + 2] 0x0111c0 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[184 + 2] 0x012000 Byte 3 of 4
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,185, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[185 + 2] 0x012340 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[186 + 2] 0x013000 Byte 3 of 4
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-185, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[187 + 2] 0x016000 Byte 3 of 4
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 8, 8, 8, 8, 8, 8, 8, 8, 188, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8,189,190, 3,
-
-// state[188 + 2] 0x016a00 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0, 0, 0, 0, 0, 0, 0,
-
-// state[189 + 2] 0x016f40 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-
-// state[190 + 2] 0x016f80 Byte 4 of 4
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[191 + 2] 0x01b000 Byte 3 of 4
-192, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[192 + 2] 0x01b000 Byte 4 of 4
-RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[193 + 2] 0x01d000 Byte 3 of 4
- 3, 3, 3, 3, 3,194,195, 3, 3,196, 3, 3, 3, 3, 3, 3,
- 8,197,198,199,200,201, 8, 8, 8, 8,202,203,204,205,206,207,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[194 + 2] 0x01d140 Byte 4 of 4
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,RJ_,RJ_,RJ_, RJ_,RJ_, 0, 0, 0,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[195 + 2] 0x01d180 Byte 4 of 4
-RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,RJ_,RJ_,RJ_,RJ_, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[196 + 2] 0x01d240 Byte 4 of 4
- 0, 0,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[197 + 2] 0x01d440 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[198 + 2] 0x01d480 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,
- 0, 0,RJ_, 0, 0,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0,RJ_, 0,RJ_,RJ_,RJ_,
-
-// state[199 + 2] 0x01d4c0 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[200 + 2] 0x01d500 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, RJ_,RJ_,RJ_, 0, 0,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0,
-
-// state[201 + 2] 0x01d540 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0, 0, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[202 + 2] 0x01d680 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[203 + 2] 0x01d6c0 Byte 4 of 4
-RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,
-
-// state[204 + 2] 0x01d700 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[205 + 2] 0x01d740 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[206 + 2] 0x01d780 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-
-// state[207 + 2] 0x01d7c0 Byte 4 of 4
-RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[208 + 2] 0x01e000 Byte 3 of 4
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 209,210,211, 3, 3, 3, 3, 3,
-
-// state[209 + 2] 0x01ee00 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0,RJ_,RJ_, 0,RJ_, 0, 0,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0,RJ_, 0, 0, 0, 0,
-
-// state[210 + 2] 0x01ee40 Byte 4 of 4
- 0, 0,RJ_, 0, 0, 0, 0,RJ_, 0,RJ_, 0,RJ_, 0,RJ_,RJ_,RJ_,
- 0,RJ_,RJ_, 0,RJ_, 0, 0,RJ_, 0,RJ_, 0,RJ_, 0,RJ_, 0,RJ_,
- 0,RJ_,RJ_, 0,RJ_, 0, 0,RJ_, RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_, 0,RJ_, 0,
-
-// state[211 + 2] 0x01ee80 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
- 0,RJ_,RJ_,RJ_, 0,RJ_,RJ_,RJ_, RJ_,RJ_, 0,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0,
-
-// state[212 + 2] 0x02a000 Byte 3 of 4
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,213, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-
-// state[213 + 2] 0x02a6c0 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// state[214 + 2] 0x02b000 Byte 3 of 4
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 66, 8, 8, 8,
-171, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[215 + 2] 0x02f000 Byte 3 of 4
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 8, 8, 8, 8, 8, 8, 8, 8, 171, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[216 + 2] 0x0c0000 Byte 2 of 4
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-217, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-
-// state[217 + 2] 0x0e0000 Byte 3 of 4
- 3, 3, 3, 3, 8, 8, 8,218, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-
-// state[218 + 2] 0x0e01c0 Byte 4 of 4
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
-RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_, RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,RJ_,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-};
-
-// Remap base[0] = (del, add, string_offset)
-static const RemapEntry utf8scannot_lettermarkspecial_remap_base[] = {
-{0,0,0} };
-
-// Remap string[0]
-static const unsigned char utf8scannot_lettermarkspecial_remap_string[] = {
-0 };
-
-static const unsigned char utf8scannot_lettermarkspecial_fast[256] = {
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,1,0, 0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0, 0,0,0,0,1,0,1,0,
-
-0,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,0,0,0,0,0,
-0,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,0,0,0,0,0,
-
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-
-};
-
-static const UTF8ScanObj utf8scannot_lettermarkspecial_obj = {
- utf8scannot_lettermarkspecial_STATE0,
- utf8scannot_lettermarkspecial_STATE0_SIZE,
- utf8scannot_lettermarkspecial_TOTAL_SIZE,
- utf8scannot_lettermarkspecial_MAX_EXPAND_X4,
- utf8scannot_lettermarkspecial_SHIFT,
- utf8scannot_lettermarkspecial_BYTES,
- utf8scannot_lettermarkspecial_LOSUB,
- utf8scannot_lettermarkspecial_HIADD,
- utf8scannot_lettermarkspecial,
- utf8scannot_lettermarkspecial_remap_base,
- utf8scannot_lettermarkspecial_remap_string,
- utf8scannot_lettermarkspecial_fast
-};
-
-
-#undef X__
-#undef RJ_
-#undef S1_
-#undef S2_
-#undef S3_
-#undef S21
-#undef S31
-#undef S32
-#undef T1_
-#undef T2_
-#undef S11
-#undef SP_
-#undef D__
-#undef RJA
-
-// Table has 14400 bytes, Hash = 9E4D-F2F2
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_UTF8SCANNOT_LETTERMARKSPECIAL_H_
diff --git a/chromium/third_party/cld_3/src/src/script_span/utf8statetable.cc b/chromium/third_party/cld_3/src/src/script_span/utf8statetable.cc
deleted file mode 100644
index 8fcfb1e8f9d..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/utf8statetable.cc
+++ /dev/null
@@ -1,1358 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// State Table follower for scanning UTF-8 strings without converting to
-// 32- or 16-bit Unicode values.
-//
-
-#ifdef COMPILER_MSVC
-// MSVC warns: warning C4309: 'initializing' : truncation of constant value
-// But the value is in fact not truncated. 0xFF still comes out 0xFF at
-// runtime.
-#pragma warning ( disable : 4309 )
-#endif
-
-#include "utf8statetable.h"
-
-#include <stdint.h> // for uintptr_t
-#include <string.h> // for NULL, memcpy, memmove
-
-#include "integral_types.h" // for uint8, uint32, int8
-#include "offsetmap.h"
-#include "port.h"
-#include "stringpiece.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-static const int kReplaceAndResumeFlag = 0x80; // Bit in del byte to distinguish
- // optional next-state field
- // after replacement text
-static const int kHtmlPlaintextFlag = 0x80; // Bit in add byte to distinguish
- // HTML replacement vs. plaintext
-
-/**
- * This code implements a little interpreter for UTF8 state
- * tables. There are three kinds of quite-similar state tables,
- * property, scanning, and replacement. Each state in one of
- * these tables consists of an array of 256 or 64 one-byte
- * entries. The state is subscripted by an incoming source byte,
- * and the entry either specifies the next state or specifies an
- * action. Space-optimized tables have full 256-entry states for
- * the first byte of a UTF-8 character, but only 64-entry states
- * for continuation bytes. Space-optimized tables may only be
- * used with source input that has been checked to be
- * structurally- (or stronger interchange-) valid.
- *
- * A property state table has an unsigned one-byte property for
- * each possible UTF-8 character. One-byte character properties
- * are in the state[0] array, while for other lengths the
- * state[0] array gives the next state, which contains the
- * property value for two-byte characters or yet another state
- * for longer ones. The code simply loads the right number of
- * next-state values, then returns the final byte as property
- * value. There are no actions specified in property tables.
- * States are typically shared for multi-byte UTF-8 characters
- * that all have the same property value.
- *
- * A scanning state table has entries that are either a
- * next-state specifier for bytes that are accepted by the
- * scanner, or an exit action for the last byte of each
- * character that is rejected by the scanner.
- *
- * Scanning long strings involves a tight loop that picks up one
- * byte at a time and follows next-state value back to state[0]
- * for each accepted UTF-8 character. Scanning stops at the end
- * of the string or at the first character encountered that has
- * an exit action such as "reject". Timing information is given
- * below.
- *
- * Since so much of Google's text is 7-bit-ASCII values
- * (approximately 94% of the bytes of web documents), the
- * scanning interpreter has two speed optimizations. One checks
- * 8 bytes at a time to see if they are all in the range lo..hi,
- * as specified in constants in the overall statetable object.
- * The check involves ORing together four 4-byte values that
- * overflow into the high bit of some byte when a byte is out of
- * range. For seven-bit-ASCII, lo is 0x20 and hi is 0x7E. This
- * loop is about 8x faster than the one-byte-at-a-time loop.
- *
- * If checking for exit bytes in the 0x00-0x1F and 7F range is
- * unneeded, an even faster loop just looks at the high bits of
- * 8 bytes at once, and is about 1.33x faster than the lo..hi
- * loop.
- *
- * Exit from the scanning routines backs up to the first byte of
- * the rejected character, so the text spanned is always a
- * complete number of UTF-8 characters. The normal scanning exit
- * is at the first rejected character, or at the end of the
- * input text. Scanning also exits on any detected ill-formed
- * character or at a special do-again action built into some
- * exit-optimized tables. The do-again action gets back to the
- * top of the scanning loop to retry eight-byte ASCII scans. It
- * is typically put into state tables after four seven-bit-ASCII
- * characters in a row are seen, to allow restarting the fast
- * scan after some slower processing of multi-byte characters.
- *
- * A replacement state table is similar to a scanning state
- * table but has more extensive actions. The default
- * byte-at-a-time loop copies one byte from source to
- * destination and goes to the next state. The replacement
- * actions overwrite 1-3 bytes of the destination with different
- * bytes, possibly shortening the output by 1 or 2 bytes. The
- * replacement bytes come from within the state table, from
- * dummy states inserted just after any state that contains a
- * replacement action. This gives a quick address calculation for
- * the replacement byte(s) and gives some cache locality.
- *
- * Additional replacement actions use one or two bytes from
- * within dummy states to index a side table of more-extensive
- * replacements. The side table specifies a length of 0..15
- * destination bytes to overwrite and a length of 0..127 bytes
- * to overwrite them with, plus the actual replacement bytes.
- *
- * This side table uses one extra bit to specify a pair of
- * replacements, the first to be used in an HTML context and the
- * second to be used in a plaintext context. This allows
- * replacements that are spelled with "&lt;" in the former
- * context and "<" in the latter.
- *
- * The side table also uses an extra bit to specify a non-zero
- * next state after a replacement. This allows a combination
- * replacement and state change, used to implement a limited
- * version of the Boyer-Moore algorithm for multi-character
- * replacement without backtracking. This is useful when there
- * are overlapping replacements, such as ch => x and also c =>
- * y, the latter to be used only if the character after c is not
- * h. in this case, the state[0] table's entry for c would
- * change c to y and also have a next-state of say n, and the
- * state[n] entry for h would specify a replacement of the two
- * bytes yh by x. No backtracking is needed.
- *
- * A replacement table may also include the exit actions of a
- * scanning state table, so some character sequences can
- * terminate early.
- *
- * During replacement, an optional data structure called an
- * offset map can be updated to reflect each change in length
- * between source and destination. This offset map can later be
- * used to map destination-string offsets to corresponding
- * source-string offsets or vice versa.
- *
- * The routines below also have variants in which state-table
- * entries are all two bytes instead of one byte. This allows
- * tables with more than 240 total states, but takes up twice as
- * much space per state.
- *
-**/
-
-// All intentional fallthroughs in breakpad are in this file, so define
-// this macro locally.
-// If you ever move this to a .h file, make sure it's defined in a
-// private header file: clang suggests the first macro expanding to
-// [[clang::fallthrough]] in its diagnostics, so if BP_FALLTHROUGH
-// is visible in code depending on breakpad, clang would suggest
-// BP_FALLTHROUGH for code depending on breakpad, instead of the
-// client code's own fallthrough macro.
-#if defined(__clang__)
-#define CLD_FALLTHROUGH [[clang::fallthrough]]
-#else
-#define CLD_FALLTHROUGH
-#endif
-
-// Return true if current Tbl pointer is within state0 range
-// Note that unsigned compare checks both ends of range simultaneously
-static inline bool InStateZero(const UTF8ScanObj* st, const uint8* Tbl) {
- const uint8* Tbl0 = &st->state_table[st->state0];
- return (static_cast<uint32>(Tbl - Tbl0) < st->state0_size);
-}
-
-static inline bool InStateZero_2(const UTF8ReplaceObj_2* st,
- const unsigned short int* Tbl) {
- const unsigned short int* Tbl0 = &st->state_table[st->state0];
- // Word difference, not byte difference
- return (static_cast<uint32>(Tbl - Tbl0) < st->state0_size);
-}
-
-// Look up property of one UTF-8 character and advance over it
-// Return 0 if input length is zero
-// Return 0 and advance one byte if input is ill-formed
-uint8 UTF8GenericProperty(const UTF8PropObj* st,
- const uint8** src,
- int* srclen) {
- if (*srclen <= 0) {
- return 0;
- }
-
- const uint8* lsrc = *src;
- const uint8* Tbl_0 = &st->state_table[st->state0];
- const uint8* Tbl = Tbl_0;
- int e;
- int eshift = st->entry_shift;
-
- // Short series of tests faster than switch, optimizes 7-bit ASCII
- unsigned char c = lsrc[0];
- if (static_cast<signed char>(c) >= 0) { // one byte
- e = Tbl[c];
- *src += 1;
- *srclen -= 1;
- } else if (((c & 0xe0) == 0xc0) && (*srclen >= 2)) { // two bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- *src += 2;
- *srclen -= 2;
- } else if (((c & 0xf0) == 0xe0) && (*srclen >= 3)) { // three bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[2]];
- *src += 3;
- *srclen -= 3;
- }else if (((c & 0xf8) == 0xf0) && (*srclen >= 4)) { // four bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[2]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[3]];
- *src += 4;
- *srclen -= 4;
- } else { // Ill-formed
- e = 0;
- *src += 1;
- *srclen -= 1;
- }
- return e;
-}
-
-bool UTF8HasGenericProperty(const UTF8PropObj& st, const char* src) {
- const uint8* lsrc = reinterpret_cast<const uint8*>(src);
- const uint8* Tbl_0 = &st.state_table[st.state0];
- const uint8* Tbl = Tbl_0;
- int e;
- int eshift = st.entry_shift;
-
- // Short series of tests faster than switch, optimizes 7-bit ASCII
- unsigned char c = lsrc[0];
- if (static_cast<signed char>(c) >= 0) { // one byte
- e = Tbl[c];
- } else if ((c & 0xe0) == 0xc0) { // two bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- } else if ((c & 0xf0) == 0xe0) { // three bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[2]];
- } else { // four bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[2]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[3]];
- }
-
- // Comparing against 0 to avoid a warning due to implicit conversion.
- return (e != 0);
-}
-
-
-// BigOneByte versions are needed for tables > 240 states, but most
-// won't need the TwoByte versions.
-// Internally, to next-to-last offset is multiplied by 16 and the last
-// offset is relative instead of absolute.
-// Look up property of one UTF-8 character and advance over it
-// Return 0 if input length is zero
-// Return 0 and advance one byte if input is ill-formed
-uint8 UTF8GenericPropertyBigOneByte(const UTF8PropObj* st,
- const uint8** src,
- int* srclen) {
- if (*srclen <= 0) {
- return 0;
- }
-
- const uint8* lsrc = *src;
- const uint8* Tbl_0 = &st->state_table[st->state0];
- const uint8* Tbl = Tbl_0;
- int e;
- int eshift = st->entry_shift;
-
- // Short series of tests faster than switch, optimizes 7-bit ASCII
- unsigned char c = lsrc[0];
- if (static_cast<signed char>(c) >= 0) { // one byte
- e = Tbl[c];
- *src += 1;
- *srclen -= 1;
- } else if (((c & 0xe0) == 0xc0) && (*srclen >= 2)) { // two bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- *src += 2;
- *srclen -= 2;
- } else if (((c & 0xf0) == 0xe0) && (*srclen >= 3)) { // three bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << (eshift + 4)]; // 16x the range
- e = (reinterpret_cast<const int8*>(Tbl))[lsrc[1]];
- Tbl = &Tbl[e << eshift]; // Relative +/-
- e = Tbl[lsrc[2]];
- *src += 3;
- *srclen -= 3;
- }else if (((c & 0xf8) == 0xf0) && (*srclen >= 4)) { // four bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << (eshift + 4)]; // 16x the range
- e = (reinterpret_cast<const int8*>(Tbl))[lsrc[2]];
- Tbl = &Tbl[e << eshift]; // Relative +/-
- e = Tbl[lsrc[3]];
- *src += 4;
- *srclen -= 4;
- } else { // Ill-formed
- e = 0;
- *src += 1;
- *srclen -= 1;
- }
- return e;
-}
-
-// BigOneByte versions are needed for tables > 240 states, but most
-// won't need the TwoByte versions.
-bool UTF8HasGenericPropertyBigOneByte(const UTF8PropObj& st, const char* src) {
- const uint8* lsrc = reinterpret_cast<const uint8*>(src);
- const uint8* Tbl_0 = &st.state_table[st.state0];
- const uint8* Tbl = Tbl_0;
- int e;
- int eshift = st.entry_shift;
-
- // Short series of tests faster than switch, optimizes 7-bit ASCII
- unsigned char c = lsrc[0];
- if (static_cast<signed char>(c) >= 0) { // one byte
- e = Tbl[c];
- } else if ((c & 0xe0) == 0xc0) { // two bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- } else if ((c & 0xf0) == 0xe0) { // three bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << (eshift + 4)]; // 16x the range
- e = (reinterpret_cast<const int8*>(Tbl))[lsrc[1]];
- Tbl = &Tbl[e << eshift]; // Relative +/-
- e = Tbl[lsrc[2]];
- } else { // four bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << (eshift + 4)]; // 16x the range
- e = (reinterpret_cast<const int8*>(Tbl))[lsrc[2]];
- Tbl = &Tbl[e << eshift]; // Relative +/-
- e = Tbl[lsrc[3]];
- }
-
- // Comparing against 0 to avoid implicit conversion and a warning.
- return (e != 0);
-}
-
-
-// TwoByte versions are needed for tables > 240 states
-// Look up property of one UTF-8 character and advance over it
-// Return 0 if input length is zero
-// Return 0 and advance one byte if input is ill-formed
-uint8 UTF8GenericPropertyTwoByte(const UTF8PropObj_2* st,
- const uint8** src,
- int* srclen) {
- if (*srclen <= 0) {
- return 0;
- }
-
- const uint8* lsrc = *src;
- const unsigned short* Tbl_0 = &st->state_table[st->state0];
- const unsigned short* Tbl = Tbl_0;
- int e;
- int eshift = st->entry_shift;
-
- // Short series of tests faster than switch, optimizes 7-bit ASCII
- unsigned char c = lsrc[0];
- if (static_cast<signed char>(c) >= 0) { // one byte
- e = Tbl[c];
- *src += 1;
- *srclen -= 1;
- } else if (((c & 0xe0) == 0xc0) && (*srclen >= 2)) { // two bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- *src += 2;
- *srclen -= 2;
- } else if (((c & 0xf0) == 0xe0) && (*srclen >= 3)) { // three bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[2]];
- *src += 3;
- *srclen -= 3;
- }else if (((c & 0xf8) == 0xf0) && (*srclen >= 4)) { // four bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[2]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[3]];
- *src += 4;
- *srclen -= 4;
- } else { // Ill-formed
- e = 0;
- *src += 1;
- *srclen -= 1;
- }
- return e;
-}
-
-// TwoByte versions are needed for tables > 240 states
-bool UTF8HasGenericPropertyTwoByte(const UTF8PropObj_2& st, const char* src) {
- const uint8* lsrc = reinterpret_cast<const uint8*>(src);
- const unsigned short* Tbl_0 = &st.state_table[st.state0];
- const unsigned short* Tbl = Tbl_0;
- int e;
- int eshift = st.entry_shift;
-
- // Short series of tests faster than switch, optimizes 7-bit ASCII
- unsigned char c = lsrc[0];
- if (static_cast<signed char>(c) >= 0) { // one byte
- e = Tbl[c];
- } else if ((c & 0xe0) == 0xc0) { // two bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- } else if ((c & 0xf0) == 0xe0) { // three bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[2]];
- } else { // four bytes
- e = Tbl[c];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[1]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[2]];
- Tbl = &Tbl_0[e << eshift];
- e = Tbl[lsrc[3]];
- }
-
- // Comparing against 0 to avoid implicit conversion and a warning.
- return (e != 0);
-}
-
-
-// Approximate speeds on 2.8 GHz Pentium 4:
-// GenericScan 1-byte loop 300 MB/sec *
-// GenericScan 4-byte loop 1200 MB/sec
-// GenericScan 8-byte loop 2400 MB/sec *
-// GenericScanFastAscii 4-byte loop 3000 MB/sec
-// GenericScanFastAscii 8-byte loop 3200 MB/sec *
-//
-// * Implemented below. FastAscii loop is memory-bandwidth constrained.
-
-// Scan a UTF-8 stringpiece based on state table.
-// Always scan complete UTF-8 characters
-// Set number of bytes scanned. Return reason for exiting
-int UTF8GenericScan(const UTF8ScanObj* st,
- const StringPiece& str,
- int* bytes_consumed) {
- int eshift = st->entry_shift; // 6 (space optimized) or 8
- // int nEntries = (1 << eshift); // 64 or 256 entries per state
-
- const uint8* isrc =
- reinterpret_cast<const uint8*>(str.data());
- const uint8* src = isrc;
- const int len = str.length();
- const uint8* srclimit = isrc + len;
- const uint8* srclimit8 = srclimit - 7;
- *bytes_consumed = 0;
- if (len == 0) return kExitOK;
-
- const uint8* Tbl_0 = &st->state_table[st->state0];
-
-DoAgain:
- // Do state-table scan
- int e = 0;
- uint8 c;
-
- // Do fast for groups of 8 identity bytes.
- // This covers a lot of 7-bit ASCII ~8x faster than the 1-byte loop,
- // including slowing slightly on cr/lf/ht
- //----------------------------
- const uint8* Tbl2 = &st->fast_state[0];
- uint32 losub = st->losub;
- uint32 hiadd = st->hiadd;
- while (src < srclimit8) {
- const uint32* src32 = reinterpret_cast<const uint32 *>(src);
- uint32 s0123 = UNALIGNED_LOAD32(&src32[0]);
- uint32 s4567 = UNALIGNED_LOAD32(&src32[1]);
- src += 8;
- // This is a fast range check for all bytes in [lowsub..0x80-hiadd)
- uint32 temp = (s0123 - losub) | (s0123 + hiadd) |
- (s4567 - losub) | (s4567 + hiadd);
- if ((temp & 0x80808080) != 0) {
- // We typically end up here on cr/lf/ht; src was incremented
- int e0123 = (Tbl2[src[-8]] | Tbl2[src[-7]]) |
- (Tbl2[src[-6]] | Tbl2[src[-5]]);
- if (e0123 != 0) {src -= 8; break;} // Exit on Non-interchange
- e0123 = (Tbl2[src[-4]] | Tbl2[src[-3]]) |
- (Tbl2[src[-2]] | Tbl2[src[-1]]);
- if (e0123 != 0) {src -= 4; break;} // Exit on Non-interchange
- // Else OK, go around again
- }
- }
- //----------------------------
-
- // Byte-at-a-time scan
- //----------------------------
- const uint8* Tbl = Tbl_0;
- while (src < srclimit) {
- c = *src;
- e = Tbl[c];
- src++;
- if (e >= kExitIllegalStructure) {break;}
- Tbl = &Tbl_0[e << eshift];
- }
- //----------------------------
-
-
- // Exit possibilities:
- // Some exit code, !state0, back up over last char
- // Some exit code, state0, back up one byte exactly
- // source consumed, !state0, back up over partial char
- // source consumed, state0, exit OK
- // For illegal byte in state0, avoid backup up over PREVIOUS char
- // For truncated last char, back up to beginning of it
-
- if (e >= kExitIllegalStructure) {
- // Back up over exactly one byte of rejected/illegal UTF-8 character
- src--;
- // Back up more if needed
- if (!InStateZero(st, Tbl)) {
- do {src--;} while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
- }
- } else if (!InStateZero(st, Tbl)) {
- // Back up over truncated UTF-8 character
- e = kExitIllegalStructure;
- do {src--;} while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
- } else {
- // Normal termination, source fully consumed
- e = kExitOK;
- }
-
- if (e == kExitDoAgain) {
- // Loop back up to the fast scan
- goto DoAgain;
- }
-
- *bytes_consumed = src - isrc;
- return e;
-}
-
-// Scan a UTF-8 stringpiece based on state table.
-// Always scan complete UTF-8 characters
-// Set number of bytes scanned. Return reason for exiting
-// OPTIMIZED for case of 7-bit ASCII 0000..007f all valid
-int UTF8GenericScanFastAscii(const UTF8ScanObj* st,
- const StringPiece& str,
- int* bytes_consumed) {
- const uint8* isrc =
- reinterpret_cast<const uint8*>(str.data());
- const uint8* src = isrc;
- const int len = str.length();
- const uint8* srclimit = isrc + len;
- const uint8* srclimit8 = srclimit - 7;
- *bytes_consumed = 0;
- if (len == 0) return kExitOK;
-
- int n;
- int rest_consumed;
- int exit_reason;
- do {
- // Skip 8 bytes of ASCII at a whack; no endianness issue
- while ((src < srclimit8) &&
- (((UNALIGNED_LOAD32(&reinterpret_cast<const uint32*>(src)[0]) |
- UNALIGNED_LOAD32(&reinterpret_cast<const uint32*>(src)[1]))
- & 0x80808080) == 0)) {
- src += 8;
- }
- // Run state table on the rest
- n = src - isrc;
- StringPiece str2(str.data() + n, str.length() - n);
- exit_reason = UTF8GenericScan(st, str2, &rest_consumed);
- src += rest_consumed;
- } while ( exit_reason == kExitDoAgain );
-
- *bytes_consumed = src - isrc;
- return exit_reason;
-}
-
-// Hack to change halfwidth katakana to match an old UTF8CharToLower()
-
-// Return number of src bytes skipped
-static int DoSpecialFixup(const unsigned char c,
- const unsigned char** srcp, const unsigned char* srclimit,
- unsigned char** dstp, unsigned char* dstlimit) {
- return 0;
-}
-
-
-// Scan a UTF-8 stringpiece based on state table, copying to output stringpiece
-// and doing text replacements.
-// DO NOT CALL DIRECTLY. Use UTF8GenericReplace() below
-// Needs caller to loop on kExitDoAgain
-static int UTF8GenericReplaceInternal(const UTF8ReplaceObj* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed,
- OffsetMap* offsetmap) {
- int eshift = st->entry_shift;
- int nEntries = (1 << eshift); // 64 or 256 entries per state
- const uint8* isrc = reinterpret_cast<const uint8*>(istr.data());
- const int ilen = istr.length();
- const uint8* copystart = isrc;
- const uint8* src = isrc;
- const uint8* srclimit = src + ilen;
- *bytes_consumed = 0;
- *bytes_filled = 0;
- *chars_changed = 0;
-
- const uint8* odst = reinterpret_cast<const uint8*>(ostr.data());
- const int olen = ostr.length();
- uint8* dst = const_cast<uint8*>(odst);
- uint8* dstlimit = dst + olen;
-
- int total_changed = 0;
-
- // Invariant condition during replacements:
- // remaining dst size >= remaining src size
- if ((dstlimit - dst) < (srclimit - src)) {
- if (offsetmap != NULL) {
- offsetmap->Copy(src - copystart);
- copystart = src;
- }
- return kExitDstSpaceFull;
- }
- const uint8* Tbl_0 = &st->state_table[st->state0];
-
- Do_state_table:
- // Do state-table scan, copying as we go
- const uint8* Tbl = Tbl_0;
- int e = 0;
- uint8 c = 0;
-
- Do_state_table_newe:
-
- //----------------------------
- while (src < srclimit) {
- c = *src;
- e = Tbl[c];
- *dst = c;
- src++;
- dst++;
- if (e >= kExitIllegalStructure) {break;}
- Tbl = &Tbl_0[e << eshift];
- }
- //----------------------------
-
- // Exit possibilities:
- // Replacement code, do the replacement and loop
- // Some other exit code, state0, back up one byte exactly
- // Some other exit code, !state0, back up over last char
- // source consumed, state0, exit OK
- // source consumed, !state0, back up over partial char
- // For illegal byte in state0, avoid backup up over PREVIOUS char
- // For truncated last char, back up to beginning of it
-
- if (e >= kExitIllegalStructure) {
- // Switch on exit code; most loop back to top
- int offset = 0;
- switch (e) {
- // These all make the output string the same size or shorter
- // No checking needed
- case kExitReplace31: // del 2, add 1 bytes to change
- dst -= 2;
- if (offsetmap != NULL) {
- offsetmap->Copy(src - copystart - 2);
- offsetmap->Delete(2);
- copystart = src;
- }
- dst[-1] = (unsigned char)Tbl[c + (nEntries * 1)];
- total_changed++;
- goto Do_state_table;
- case kExitReplace32: // del 3, add 2 bytes to change
- dst--;
- if (offsetmap != NULL) {
- offsetmap->Copy(src - copystart - 1);
- offsetmap->Delete(1);
- copystart = src;
- }
- dst[-2] = (unsigned char)Tbl[c + (nEntries * 2)];
- dst[-1] = (unsigned char)Tbl[c + (nEntries * 1)];
- total_changed++;
- goto Do_state_table;
- case kExitReplace21: // del 2, add 1 bytes to change
- dst--;
- if (offsetmap != NULL) {
- offsetmap->Copy(src - copystart - 1);
- offsetmap->Delete(1);
- copystart = src;
- }
- dst[-1] = (unsigned char)Tbl[c + (nEntries * 1)];
- total_changed++;
- goto Do_state_table;
- case kExitReplace3: // update 3 bytes to change
- dst[-3] = (unsigned char)Tbl[c + (nEntries * 3)];
- CLD_FALLTHROUGH;
- case kExitReplace2: // update 2 bytes to change
- dst[-2] = (unsigned char)Tbl[c + (nEntries * 2)];
- CLD_FALLTHROUGH;
- case kExitReplace1: // update 1 byte to change
- dst[-1] = (unsigned char)Tbl[c + (nEntries * 1)];
- total_changed++;
- goto Do_state_table;
- case kExitReplace1S0: // update 1 byte to change, 256-entry state
- dst[-1] = (unsigned char)Tbl[c + (256 * 1)];
- total_changed++;
- goto Do_state_table;
- // These can make the output string longer than the input
- case kExitReplaceOffset2:
- if ((nEntries != 256) && InStateZero(st, Tbl)) {
- // For space-optimized table, we need multiples of 256 bytes
- // in state0 and multiples of nEntries in other states
- offset += ((unsigned char)Tbl[c + (256 * 2)] << 8);
- } else {
- offset += ((unsigned char)Tbl[c + (nEntries * 2)] << 8);
- }
- CLD_FALLTHROUGH;
- case kExitSpecial: // Apply special fixups [read: hacks]
- case kExitReplaceOffset1:
- if ((nEntries != 256) && InStateZero(st, Tbl)) {
- // For space-optimized table, we need multiples of 256 bytes
- // in state0 and multiples of nEntries in other states
- offset += (unsigned char)Tbl[c + (256 * 1)];
- } else {
- offset += (unsigned char)Tbl[c + (nEntries * 1)];
- }
- {
- const RemapEntry* re = &st->remap_base[offset];
- int del_len = re->delete_bytes & ~kReplaceAndResumeFlag;
- int add_len = re->add_bytes & ~kHtmlPlaintextFlag;
-
- // Special-case non-HTML replacement of five sensitive entities
- // &quot; &amp; &apos; &lt; &gt;
- // 0022 0026 0027 003c 003e
- // A replacement creating one of these is expressed as a pair of
- // entries, one for HTML output and one for plaintext output.
- // The first of the pair has the high bit of add_bytes set.
- if (re->add_bytes & kHtmlPlaintextFlag) {
- // Use this entry for plain text
- if (!is_plain_text) {
- // Use very next entry for HTML text (same back/delete length)
- re = &st->remap_base[offset + 1];
- add_len = re->add_bytes & ~kHtmlPlaintextFlag;
- }
- }
-
- int string_offset = re->bytes_offset;
- // After the replacement, need (dstlimit - newdst) >= (srclimit - src)
- uint8* newdst = dst - del_len + add_len;
- if ((dstlimit - newdst) < (srclimit - src)) {
- // Won't fit; don't do the replacement. Caller may realloc and retry
- e = kExitDstSpaceFull;
- break; // exit, backing up over this char for later retry
- }
- dst -= del_len;
- memcpy(dst, &st->remap_string[string_offset], add_len);
- dst += add_len;
- total_changed++;
- if (offsetmap != NULL) {
- if (add_len > del_len) {
- offsetmap->Copy(src - copystart);
- offsetmap->Insert(add_len - del_len);
- copystart = src;
- } else if (add_len < del_len) {
- offsetmap->Copy(src - copystart + add_len - del_len);
- offsetmap->Delete(del_len - add_len);
- copystart = src;
- }
- }
- if (re->delete_bytes & kReplaceAndResumeFlag) {
- // There is a non-zero target state at the end of the
- // replacement string
- e = st->remap_string[string_offset + add_len];
- Tbl = &Tbl_0[e << eshift];
- goto Do_state_table_newe;
- }
- }
- if (e == kExitRejectAlt) {break;}
- if (e != kExitSpecial) {goto Do_state_table;}
-
- // case kExitSpecial: // Apply special fixups [read: hacks]
- // In this routine, do either UTF8CharToLower()
- // fullwidth/halfwidth mapping or
- // voiced mapping or
- // semi-voiced mapping
-
- // First, do EXIT_REPLACE_OFFSET1 action (above)
- // Second: do additional code fixup
- {
- int srcdel = DoSpecialFixup(c, &src, srclimit, &dst, dstlimit);
- if (offsetmap != NULL) {
- if (srcdel != 0) {
- offsetmap->Copy(src - copystart - srcdel);
- offsetmap->Delete(srcdel);
- copystart = src;
- }
- }
- }
- goto Do_state_table;
-
- case kExitIllegalStructure: // structurally illegal byte; quit
- case kExitReject: // NUL or illegal code encountered; quit
- case kExitRejectAlt: // Apply replacement, then exit
- default: // and all other exits
- break;
- } // End switch (e)
-
- // Exit possibilities:
- // Some other exit code, state0, back up one byte exactly
- // Some other exit code, !state0, back up over last char
-
- // Back up over exactly one byte of rejected/illegal UTF-8 character
- src--;
- dst--;
- // Back up more if needed
- if (!InStateZero(st, Tbl)) {
- do {src--;dst--;} while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
- }
- } else if (!InStateZero(st, Tbl)) {
- // src >= srclimit, !state0
- // Back up over truncated UTF-8 character
- e = kExitIllegalStructure;
- do {src--; dst--;} while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
- } else {
- // src >= srclimit, state0
- // Normal termination, source fully consumed
- e = kExitOK;
- }
-
- if (offsetmap != NULL) {
- if (src > copystart) {
- offsetmap->Copy(src - copystart);
- copystart = src;
- }
- }
-
- // Possible return values here:
- // kExitDstSpaceFull caller may realloc and retry from middle
- // kExitIllegalStructure caller my overwrite/truncate
- // kExitOK all done and happy
- // kExitReject caller may overwrite/truncate
- // kExitDoAgain LOOP NOT DONE; caller must retry from middle
- // (may do fast ASCII loop first)
- // kExitPlaceholder -unused-
- // kExitNone -unused-
- *bytes_consumed = src - isrc;
- *bytes_filled = dst - odst;
- *chars_changed = total_changed;
- return e;
-}
-
-// TwoByte versions are needed for tables > 240 states, such
-// as the table for full Unicode 4.1 canonical + compatibility mapping
-
-// Scan a UTF-8 stringpiece based on state table with two-byte entries,
-// copying to output stringpiece
-// and doing text replacements.
-// DO NOT CALL DIRECTLY. Use UTF8GenericReplace() below
-// Needs caller to loop on kExitDoAgain
-static int UTF8GenericReplaceInternalTwoByte(const UTF8ReplaceObj_2* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed,
- OffsetMap* offsetmap) {
- int eshift = st->entry_shift;
- int nEntries = (1 << eshift); // 64 or 256 entries per state
- const uint8* isrc = reinterpret_cast<const uint8*>(istr.data());
- const int ilen = istr.length();
- const uint8* copystart = isrc;
- const uint8* src = isrc;
- const uint8* srclimit = src + ilen;
- *bytes_consumed = 0;
- *bytes_filled = 0;
- *chars_changed = 0;
-
- const uint8* odst = reinterpret_cast<const uint8*>(ostr.data());
- const int olen = ostr.length();
- uint8* dst = const_cast<uint8*>(odst);
- uint8* dstlimit = dst + olen;
-
- *chars_changed = 0;
-
- int total_changed = 0;
-
- // Invariant condition during replacements:
- // remaining dst size >= remaining src size
- if ((dstlimit - dst) < (srclimit - src)) {
- if (offsetmap != NULL) {
- offsetmap->Copy(src - copystart);
- copystart = src;
- }
- return kExitDstSpaceFull_2;
- }
- const unsigned short* Tbl_0 = &st->state_table[st->state0];
-
- Do_state_table_2:
- // Do state-table scan, copying as we go
- const unsigned short* Tbl = Tbl_0;
- int e = 0;
- uint8 c = 0;
-
- Do_state_table_newe_2:
-
- //----------------------------
- while (src < srclimit) {
- c = *src;
- e = Tbl[c];
- *dst = c;
- src++;
- dst++;
- if (e >= kExitIllegalStructure_2) {break;}
- Tbl = &Tbl_0[e << eshift];
- }
- //----------------------------
-
- // Exit possibilities:
- // Replacement code, do the replacement and loop
- // Some other exit code, state0, back up one byte exactly
- // Some other exit code, !state0, back up over last char
- // source consumed, state0, exit OK
- // source consumed, !state0, back up over partial char
- // For illegal byte in state0, avoid backup up over PREVIOUS char
- // For truncated last char, back up to beginning of it
-
- if (e >= kExitIllegalStructure_2) {
- // Switch on exit code; most loop back to top
- int offset = 0;
- switch (e) {
- // These all make the output string the same size or shorter
- // No checking needed
- case kExitReplace31_2: // del 2, add 1 bytes to change
- dst -= 2;
- if (offsetmap != NULL) {
- offsetmap->Copy(src - copystart - 2);
- offsetmap->Delete(2);
- copystart = src;
- }
- dst[-1] = (unsigned char)(Tbl[c + (nEntries * 1)] & 0xff);
- total_changed++;
- goto Do_state_table_2;
- case kExitReplace32_2: // del 3, add 2 bytes to change
- dst--;
- if (offsetmap != NULL) {
- offsetmap->Copy(src - copystart - 1);
- offsetmap->Delete(1);
- copystart = src;
- }
- dst[-2] = (unsigned char)(Tbl[c + (nEntries * 1)] >> 8 & 0xff);
- dst[-1] = (unsigned char)(Tbl[c + (nEntries * 1)] & 0xff);
- total_changed++;
- goto Do_state_table_2;
- case kExitReplace21_2: // del 2, add 1 bytes to change
- dst--;
- if (offsetmap != NULL) {
- offsetmap->Copy(src - copystart - 1);
- offsetmap->Delete(1);
- copystart = src;
- }
- dst[-1] = (unsigned char)(Tbl[c + (nEntries * 1)] & 0xff);
- total_changed++;
- goto Do_state_table_2;
- case kExitReplace3_2: // update 3 bytes to change
- dst[-3] = (unsigned char)(Tbl[c + (nEntries * 2)] & 0xff);
- CLD_FALLTHROUGH;
- case kExitReplace2_2: // update 2 bytes to change
- dst[-2] = (unsigned char)(Tbl[c + (nEntries * 1)] >> 8 & 0xff);
- CLD_FALLTHROUGH;
- case kExitReplace1_2: // update 1 byte to change
- dst[-1] = (unsigned char)(Tbl[c + (nEntries * 1)] & 0xff);
- total_changed++;
- goto Do_state_table_2;
- case kExitReplace1S0_2: // update 1 byte to change, 256-entry state
- dst[-1] = (unsigned char)(Tbl[c + (256 * 1)] & 0xff);
- total_changed++;
- goto Do_state_table_2;
- // These can make the output string longer than the input
- case kExitReplaceOffset2_2:
- if ((nEntries != 256) && InStateZero_2(st, Tbl)) {
- // For space-optimized table, we need multiples of 256 bytes
- // in state0 and multiples of nEntries in other states
- offset += ((unsigned char)(Tbl[c + (256 * 1)] >> 8 & 0xff) << 8);
- } else {
- offset += ((unsigned char)(Tbl[c + (nEntries * 1)] >> 8 & 0xff) << 8);
- }
- CLD_FALLTHROUGH;
- case kExitReplaceOffset1_2:
- if ((nEntries != 256) && InStateZero_2(st, Tbl)) {
- // For space-optimized table, we need multiples of 256 bytes
- // in state0 and multiples of nEntries in other states
- offset += (unsigned char)(Tbl[c + (256 * 1)] & 0xff);
- } else {
- offset += (unsigned char)(Tbl[c + (nEntries * 1)] & 0xff);
- }
- {
- const RemapEntry* re = &st->remap_base[offset];
- int del_len = re->delete_bytes & ~kReplaceAndResumeFlag;
- int add_len = re->add_bytes & ~kHtmlPlaintextFlag;
- // Special-case non-HTML replacement of five sensitive entities
- // &quot; &amp; &apos; &lt; &gt;
- // 0022 0026 0027 003c 003e
- // A replacement creating one of these is expressed as a pair of
- // entries, one for HTML output and one for plaintext output.
- // The first of the pair has the high bit of add_bytes set.
- if (re->add_bytes & kHtmlPlaintextFlag) {
- // Use this entry for plain text
- if (!is_plain_text) {
- // Use very next entry for HTML text (same back/delete length)
- re = &st->remap_base[offset + 1];
- add_len = re->add_bytes & ~kHtmlPlaintextFlag;
- }
- }
-
- // After the replacement, need (dstlimit - dst) >= (srclimit - src)
- int string_offset = re->bytes_offset;
- // After the replacement, need (dstlimit - newdst) >= (srclimit - src)
- uint8* newdst = dst - del_len + add_len;
- if ((dstlimit - newdst) < (srclimit - src)) {
- // Won't fit; don't do the replacement. Caller may realloc and retry
- e = kExitDstSpaceFull_2;
- break; // exit, backing up over this char for later retry
- }
- dst -= del_len;
- memcpy(dst, &st->remap_string[string_offset], add_len);
- dst += add_len;
- if (offsetmap != NULL) {
- if (add_len > del_len) {
- offsetmap->Copy(src - copystart);
- offsetmap->Insert(add_len - del_len);
- copystart = src;
- } else if (add_len < del_len) {
- offsetmap->Copy(src - copystart + add_len - del_len);
- offsetmap->Delete(del_len - add_len);
- copystart = src;
- }
- }
- if (re->delete_bytes & kReplaceAndResumeFlag) {
- // There is a two-byte non-zero target state at the end of the
- // replacement string
- uint8 c1 = st->remap_string[string_offset + add_len];
- uint8 c2 = st->remap_string[string_offset + add_len + 1];
- e = (c1 << 8) | c2;
- Tbl = &Tbl_0[e << eshift];
- total_changed++;
- goto Do_state_table_newe_2;
- }
- }
- total_changed++;
- if (e == kExitRejectAlt_2) {break;}
- goto Do_state_table_2;
-
- case kExitSpecial_2: // NO special fixups [read: hacks]
- case kExitIllegalStructure_2: // structurally illegal byte; quit
- case kExitReject_2: // NUL or illegal code encountered; quit
- // and all other exits
- default:
- break;
- } // End switch (e)
-
- // Exit possibilities:
- // Some other exit code, state0, back up one byte exactly
- // Some other exit code, !state0, back up over last char
-
- // Back up over exactly one byte of rejected/illegal UTF-8 character
- src--;
- dst--;
- // Back up more if needed
- if (!InStateZero_2(st, Tbl)) {
- do {src--;dst--;} while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
- }
- } else if (!InStateZero_2(st, Tbl)) {
- // src >= srclimit, !state0
- // Back up over truncated UTF-8 character
- e = kExitIllegalStructure_2;
-
- do {src--; dst--;} while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
- } else {
- // src >= srclimit, state0
- // Normal termination, source fully consumed
- e = kExitOK_2;
- }
-
- if (offsetmap != NULL) {
- if (src > copystart) {
- offsetmap->Copy(src - copystart);
- copystart = src;
- }
- }
-
-
- // Possible return values here:
- // kExitDstSpaceFull_2 caller may realloc and retry from middle
- // kExitIllegalStructure_2 caller my overwrite/truncate
- // kExitOK_2 all done and happy
- // kExitReject_2 caller may overwrite/truncate
- // kExitDoAgain_2 LOOP NOT DONE; caller must retry from middle
- // (may do fast ASCII loop first)
- // kExitPlaceholder_2 -unused-
- // kExitNone_2 -unused-
- *bytes_consumed = src - isrc;
- *bytes_filled = dst - odst;
- *chars_changed = total_changed;
- return e;
-}
-
-
-// Scan a UTF-8 stringpiece based on state table, copying to output stringpiece
-// and doing text replacements.
-// Also writes an optional OffsetMap. Pass NULL to skip writing one.
-// Always scan complete UTF-8 characters
-// Set number of bytes consumed from input, number filled to output.
-// Return reason for exiting
-int UTF8GenericReplace(const UTF8ReplaceObj* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed,
- OffsetMap* offsetmap) {
- StringPiece local_istr(istr.data(), istr.length());
- StringPiece local_ostr(ostr.data(), ostr.length());
- int total_consumed = 0;
- int total_filled = 0;
- int total_changed = 0;
- int local_bytes_consumed, local_bytes_filled, local_chars_changed;
- int e;
- do {
- e = UTF8GenericReplaceInternal(st,
- local_istr, local_ostr, is_plain_text,
- &local_bytes_consumed, &local_bytes_filled,
- &local_chars_changed,
- offsetmap);
- local_istr.remove_prefix(local_bytes_consumed);
- local_ostr.remove_prefix(local_bytes_filled);
- total_consumed += local_bytes_consumed;
- total_filled += local_bytes_filled;
- total_changed += local_chars_changed;
- } while ( e == kExitDoAgain );
- *bytes_consumed = total_consumed;
- *bytes_filled = total_filled;
- *chars_changed = total_changed;
- return e;
-}
-
-// Older version without offsetmap
-int UTF8GenericReplace(const UTF8ReplaceObj* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed) {
- return UTF8GenericReplace(st,
- istr,
- ostr,
- is_plain_text,
- bytes_consumed,
- bytes_filled,
- chars_changed,
- NULL);
-}
-
-// Older version without is_plain_text or offsetmap
-int UTF8GenericReplace(const UTF8ReplaceObj* st,
- const StringPiece& istr,
- StringPiece& ostr,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed) {
- bool is_plain_text = false;
- return UTF8GenericReplace(st,
- istr,
- ostr,
- is_plain_text,
- bytes_consumed,
- bytes_filled,
- chars_changed,
- NULL);
-}
-
-// Scan a UTF-8 stringpiece based on state table with two-byte entries,
-// copying to output stringpiece
-// and doing text replacements.
-// Also writes an optional OffsetMap. Pass NULL to skip writing one.
-// Always scan complete UTF-8 characters
-// Set number of bytes consumed from input, number filled to output.
-// Return reason for exiting
-int UTF8GenericReplaceTwoByte(const UTF8ReplaceObj_2* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed,
- OffsetMap* offsetmap) {
- StringPiece local_istr(istr.data(), istr.length());
- StringPiece local_ostr(ostr.data(), ostr.length());
- int total_consumed = 0;
- int total_filled = 0;
- int total_changed = 0;
- int local_bytes_consumed, local_bytes_filled, local_chars_changed;
- int e;
- do {
- e = UTF8GenericReplaceInternalTwoByte(st,
- local_istr, local_ostr, is_plain_text,
- &local_bytes_consumed,
- &local_bytes_filled,
- &local_chars_changed,
- offsetmap);
- local_istr.remove_prefix(local_bytes_consumed);
- local_ostr.remove_prefix(local_bytes_filled);
- total_consumed += local_bytes_consumed;
- total_filled += local_bytes_filled;
- total_changed += local_chars_changed;
- } while ( e == kExitDoAgain_2 );
- *bytes_consumed = total_consumed;
- *bytes_filled = total_filled;
- *chars_changed = total_changed;
-
- return e - kExitOK_2 + kExitOK;
-}
-
-// Older version without offsetmap
-int UTF8GenericReplaceTwoByte(const UTF8ReplaceObj_2* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed) {
- return UTF8GenericReplaceTwoByte(st,
- istr,
- ostr,
- is_plain_text,
- bytes_consumed,
- bytes_filled,
- chars_changed,
- NULL);
-}
-
-// Older version without is_plain_text or offsetmap
-int UTF8GenericReplaceTwoByte(const UTF8ReplaceObj_2* st,
- const StringPiece& istr,
- StringPiece& ostr,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed) {
- bool is_plain_text = false;
- return UTF8GenericReplaceTwoByte(st,
- istr,
- ostr,
- is_plain_text,
- bytes_consumed,
- bytes_filled,
- chars_changed,
- NULL);
-}
-
-
-
-// Adjust a stringpiece to encompass complete UTF-8 characters.
-// The data pointer will be increased by 0..3 bytes to get to a character
-// boundary, and the length will then be decreased by 0..3 bytes
-// to encompass the last complete character.
-void UTF8TrimToChars(StringPiece* istr) {
- const char* src = istr->data();
- int len = istr->length();
- // Exit if empty string
- if (len == 0) {
- return;
- }
-
- // Exit on simple, common case
- if ( ((src[0] & 0xc0) != 0x80) &&
- (static_cast<signed char>(src[len - 1]) >= 0) ) {
- // First byte is not a continuation and last byte is 7-bit ASCII -- done
- return;
- }
-
- // Adjust the back end, len > 0
- const char* srclimit = src + len;
- // Backscan over any ending continuation bytes to find last char start
- const char* s = srclimit - 1; // Last byte of the string
- while ((src <= s) && ((*s & 0xc0) == 0x80)) {
- s--;
- }
- // Include entire last char if it fits
- if (src <= s) {
- int last_char_len = UTF8OneCharLen(s);
- if (s + last_char_len <= srclimit) {
- // Last char fits, so include it, else exclude it
- s += last_char_len;
- }
- }
- if (s != srclimit) {
- // s is one byte beyond the last full character, if any
- istr->remove_suffix(srclimit - s);
- // Exit if now empty string
- if (istr->length() == 0) {
- return;
- }
- }
-
- // Adjust the front end, len > 0
- len = istr->length();
- srclimit = src + len;
- s = src; // First byte of the string
- // Scan over any beginning continuation bytes to find first char start
- while ((s < srclimit) && ((*s & 0xc0) == 0x80)) {
- s++;
- }
- if (s != src) {
- // s is at the first full character, if any
- istr->remove_prefix(s - src);
- }
-}
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/script_span/utf8statetable.h b/chromium/third_party/cld_3/src/src/script_span/utf8statetable.h
deleted file mode 100644
index 5817c410ba1..00000000000
--- a/chromium/third_party/cld_3/src/src/script_span/utf8statetable.h
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//
-// State Table follower for scanning UTF-8 strings without converting to
-// 32- or 16-bit Unicode values.
-//
-// Author: dsites@google.com (Dick Sites)
-//
-
-#ifndef SCRIPT_SPAN_UTF8STATETABLE_H_
-#define SCRIPT_SPAN_UTF8STATETABLE_H_
-
-#include <string>
-
-#include "integral_types.h" // for uint8, uint32, uint16
-#include "stringpiece.h"
-
-namespace chrome_lang_id {
-namespace CLD2 {
-
-class OffsetMap;
-
-
-// These four-byte entries compactly encode how many bytes 0..255 to delete
-// in making a string replacement, how many bytes to add 0..255, and the offset
-// 0..64k-1 of the replacement string in remap_string.
-struct RemapEntry {
- uint8 delete_bytes;
- uint8 add_bytes;
- uint16 bytes_offset;
-};
-
-// Exit type codes for state tables. All but the first get stuffed into
-// signed one-byte entries. The first is only generated by executable code.
-// To distinguish from next-state entries, these must be contiguous and
-// all <= kExitNone
-typedef enum {
- kExitDstSpaceFull = 239,
- kExitIllegalStructure, // 240
- kExitOK, // 241
- kExitReject, // ...
- kExitReplace1,
- kExitReplace2,
- kExitReplace3,
- kExitReplace21,
- kExitReplace31,
- kExitReplace32,
- kExitReplaceOffset1,
- kExitReplaceOffset2,
- kExitReplace1S0,
- kExitSpecial,
- kExitDoAgain,
- kExitRejectAlt,
- kExitNone // 255
-} ExitReason;
-
-typedef enum {
- kExitDstSpaceFull_2 = 32767, // 0x7fff
- kExitIllegalStructure_2, // 32768 0x8000
- kExitOK_2, // 32769 0x8001
- kExitReject_2, // ...
- kExitReplace1_2,
- kExitReplace2_2,
- kExitReplace3_2,
- kExitReplace21_2,
- kExitReplace31_2,
- kExitReplace32_2,
- kExitReplaceOffset1_2,
- kExitReplaceOffset2_2,
- kExitReplace1S0_2,
- kExitSpecial_2,
- kExitDoAgain_2,
- kExitRejectAlt_2,
- kExitNone_2 // 32783 0x800f
-} ExitReason_2;
-
-
-// This struct represents one entire state table. The three initialized byte
-// areas are state_table, remap_base, and remap_string. state0 and state0_size
-// give the byte offset and length within state_table of the initial state --
-// table lookups are expected to start and end in this state, but for
-// truncated UTF-8 strings, may end in a different state. These allow a quick
-// test for that condition. entry_shift is 8 for tables subscripted by a full
-// byte value and 6 for space-optimized tables subscripted by only six
-// significant bits in UTF-8 continuation bytes.
-typedef struct {
- const uint32 state0;
- const uint32 state0_size;
- const uint32 total_size;
- const int max_expand;
- const int entry_shift;
- const int bytes_per_entry;
- const uint32 losub;
- const uint32 hiadd;
- const uint8* state_table;
- const RemapEntry* remap_base;
- const uint8* remap_string;
- const uint8* fast_state;
-} UTF8StateMachineObj;
-
-// Near-duplicate declaration for tables with two-byte entries
-typedef struct {
- const uint32 state0;
- const uint32 state0_size;
- const uint32 total_size;
- const int max_expand;
- const int entry_shift;
- const int bytes_per_entry;
- const uint32 losub;
- const uint32 hiadd;
- const unsigned short* state_table;
- const RemapEntry* remap_base;
- const uint8* remap_string;
- const uint8* fast_state;
-} UTF8StateMachineObj_2;
-
-
-typedef UTF8StateMachineObj UTF8PropObj;
-typedef UTF8StateMachineObj UTF8ScanObj;
-typedef UTF8StateMachineObj UTF8ReplaceObj;
-typedef UTF8StateMachineObj_2 UTF8PropObj_2;
-typedef UTF8StateMachineObj_2 UTF8ReplaceObj_2;
-// NOT IMPLEMENTED typedef UTF8StateMachineObj_2 UTF8ScanObj_2;
-
-
-// Look up property of one UTF-8 character and advance over it
-// Return 0 if input length is zero
-// Return 0 and advance one byte if input is ill-formed
-uint8 UTF8GenericProperty(const UTF8PropObj* st,
- const uint8** src,
- int* srclen);
-
-// Look up property of one UTF-8 character (assumed to be valid).
-// (This is a faster version of UTF8GenericProperty.)
-bool UTF8HasGenericProperty(const UTF8PropObj& st, const char* src);
-
-
-// BigOneByte versions are needed for tables > 240 states, but most
-// won't need the TwoByte versions.
-
-// Look up property of one UTF-8 character and advance over it
-// Return 0 if input length is zero
-// Return 0 and advance one byte if input is ill-formed
-uint8 UTF8GenericPropertyBigOneByte(const UTF8PropObj* st,
- const uint8** src,
- int* srclen);
-
-
-// TwoByte versions are needed for tables > 240 states that don't fit onto
-// BigOneByte -- rare ultimate fallback
-
-// Look up property of one UTF-8 character (assumed to be valid).
-// (This is a faster version of UTF8GenericProperty.)
-bool UTF8HasGenericPropertyBigOneByte(const UTF8PropObj& st, const char* src);
-
-// Look up property of one UTF-8 character and advance over it
-// Return 0 if input length is zero
-// Return 0 and advance one byte if input is ill-formed
-uint8 UTF8GenericPropertyTwoByte(const UTF8PropObj_2* st,
- const uint8** src,
- int* srclen);
-
-// Look up property of one UTF-8 character (assumed to be valid).
-// (This is a faster version of UTF8GenericProperty.)
-bool UTF8HasGenericPropertyTwoByte(const UTF8PropObj_2& st, const char* src);
-
-// Scan a UTF-8 stringpiece based on a state table.
-// Always scan complete UTF-8 characters
-// Set number of bytes scanned. Return reason for exiting
-int UTF8GenericScan(const UTF8ScanObj* st,
- const StringPiece& str,
- int* bytes_consumed);
-
-
-
-// Scan a UTF-8 stringpiece based on state table, copying to output stringpiece
-// and doing text replacements.
-// Always scan complete UTF-8 characters
-// Set number of bytes consumed from input, number filled to output.
-// Return reason for exiting
-// Also writes an optional OffsetMap. Pass NULL to skip writing one.
-int UTF8GenericReplace(const UTF8ReplaceObj* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed,
- OffsetMap* offsetmap);
-
-// Older version without offsetmap
-int UTF8GenericReplace(const UTF8ReplaceObj* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed);
-
-// Older version without is_plain_text or offsetmap
-int UTF8GenericReplace(const UTF8ReplaceObj* st,
- const StringPiece& istr,
- StringPiece& ostr,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed);
-
-
-// TwoByte version is needed for tables > about 256 states, such
-// as the table for full Unicode 4.1 canonical + compatibility mapping
-
-// Scan a UTF-8 stringpiece based on state table with two-byte entries,
-// copying to output stringpiece
-// and doing text replacements.
-// Always scan complete UTF-8 characters
-// Set number of bytes consumed from input, number filled to output.
-// Return reason for exiting
-// Also writes an optional OffsetMap. Pass NULL to skip writing one.
-int UTF8GenericReplaceTwoByte(const UTF8ReplaceObj_2* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed,
- OffsetMap* offsetmap);
-
-// Older version without offsetmap
-int UTF8GenericReplaceTwoByte(const UTF8ReplaceObj_2* st,
- const StringPiece& istr,
- StringPiece& ostr,
- bool is_plain_text,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed);
-
-// Older version without is_plain_text or offsetmap
-int UTF8GenericReplaceTwoByte(const UTF8ReplaceObj_2* st,
- const StringPiece& istr,
- StringPiece& ostr,
- int* bytes_consumed,
- int* bytes_filled,
- int* chars_changed);
-
-
-static const unsigned char kUTF8LenTbl[256] = {
- 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
-
- 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,
- 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4
-};
-
-inline int UTF8OneCharLen(const char* in) {
- return kUTF8LenTbl[*reinterpret_cast<const uint8*>(in)];
-}
-
-// Adjust a stringpiece to encompass complete UTF-8 characters.
-// The data pointer will be increased by 0..3 bytes to get to a character
-// boundary, and the length will then be decreased by 0..3 bytes
-// to encompass the last complete character.
-// This is useful especially when a UTF-8 string must be put into a fixed-
-// maximum-size buffer cleanly, such as a MySQL buffer.
-void UTF8TrimToChars(StringPiece* istr);
-
-} // End namespace CLD2
-} // End namespace chrome_lang_id
-
-#endif // SCRIPT_SPAN_UTF8STATETABLE_H_
diff --git a/chromium/third_party/cld_3/src/src/sentence.proto b/chromium/third_party/cld_3/src/src/sentence.proto
deleted file mode 100644
index a5b71db6c44..00000000000
--- a/chromium/third_party/cld_3/src/src/sentence.proto
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Protocol buffer specification for sentence analysis.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package chrome_lang_id;
-
-// A Sentence contains the raw text contents of a sentence, as well as an
-// analysis.
-message Sentence {
- // Identifier for sentence.
- optional string id = 1;
-
- // Raw text contents of the sentence.
- optional string text = 2;
-
- // Tokenization of the sentence.
- repeated Token token = 3;
-
- extensions 1000 to max;
-}
-
-// A sentence token marks a span of bytes in the sentence text as a token
-// or word.
-message Token {
- // Token word form.
- required string word = 1;
-
- // Start position of token in text.
- required int32 start = 2;
-
- // End position of token in text. Gives index of last byte, not one past
- // the last byte. If token came from lexer, excludes any trailing HTML tags.
- required int32 end = 3;
-
- // Head of this token in the dependency tree: the id of the token which has an
- // arc going to this one. If it is the root token of a sentence, then it is
- // set to -1.
- optional int32 head = 4 [default = -1];
-
- // Part-of-speech tag for token.
- optional string tag = 5;
-
- // Coarse-grained word category for token.
- optional string category = 6;
-
- // Label for dependency relation between this token and its head.
- optional string label = 7;
-
- // Break level for tokens that indicates how it was separated from the
- // previous token in the text.
- enum BreakLevel {
- NO_BREAK = 0; // No separation between tokens.
- SPACE_BREAK = 1; // Tokens separated by space.
- LINE_BREAK = 2; // Tokens separated by line break.
- SENTENCE_BREAK = 3; // Tokens separated by sentence break.
- }
-
- optional BreakLevel break_level = 8 [default = SPACE_BREAK];
-
- extensions 1000 to max;
-}
diff --git a/chromium/third_party/cld_3/src/src/sentence_features.cc b/chromium/third_party/cld_3/src/src/sentence_features.cc
deleted file mode 100644
index cae6e368c87..00000000000
--- a/chromium/third_party/cld_3/src/src/sentence_features.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "sentence_features.h"
-
-#include "registry.h"
-
-namespace chrome_lang_id {
-
-// Declare registry for the whole Sentence feature functions. NOTE: this is not
-// yet set to anything meaningful. It will be set so in NNetLanguageIdentifier
-// constructor, *before* we use any feature.
-template <>
-WholeSentenceFeature::Registry
- *RegisterableClass<WholeSentenceFeature>::registry_ = nullptr;
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/sentence_features.h b/chromium/third_party/cld_3/src/src/sentence_features.h
deleted file mode 100644
index 165bfd5f1a3..00000000000
--- a/chromium/third_party/cld_3/src/src/sentence_features.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Features that operate on Sentence objects. Most features are defined
-// in this header so they may be re-used via composition into other more
-// advanced feature classes.
-
-#ifndef SENTENCE_FEATURES_H_
-#define SENTENCE_FEATURES_H_
-
-#include "feature_extractor.h"
-#include "cld_3/protos/sentence.pb.h"
-
-namespace chrome_lang_id {
-
-// Feature function that extracts features for the full Sentence.
-typedef FeatureFunction<Sentence> WholeSentenceFeature;
-
-typedef FeatureExtractor<Sentence> WholeSentenceExtractor;
-
-} // namespace chrome_lang_id
-
-#endif // SENTENCE_FEATURES_H_
diff --git a/chromium/third_party/cld_3/src/src/simple_adder.h b/chromium/third_party/cld_3/src/src/simple_adder.h
deleted file mode 100644
index f70665eff78..00000000000
--- a/chromium/third_party/cld_3/src/src/simple_adder.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef SIMPLE_ADDER_H_
-#define SIMPLE_ADDER_H_
-
-#include "base.h"
-
-namespace chrome_lang_id {
-
-// Class for adding (possibly) scaled arrays.
-class SimpleAdder {
- public:
- static constexpr const int kNumFloatsPerBatch = 1;
-
- CLD3_ATTRIBUTE_ALWAYS_INLINE SimpleAdder(float *dest, int num_floats)
- : dest_(dest), num_floats_(num_floats) {}
-
- CLD3_ATTRIBUTE_ALWAYS_INLINE ~SimpleAdder() {
- // Should call Finalize function before destruction.
- CLD3_DCHECK(dest_ == nullptr);
- }
-
- // Caller must call this function before calling deconstruct this object.
- CLD3_ATTRIBUTE_ALWAYS_INLINE void Finalize() { dest_ = nullptr; }
-
- CLD3_ATTRIBUTE_ALWAYS_INLINE void LazyAdd(const float *source) const {
- AddImpl(source, num_floats_, dest_);
- }
-
- CLD3_ATTRIBUTE_ALWAYS_INLINE void LazyScaleAdd(const float *source,
- const float scale) const {
- ScaleAddImpl(source, num_floats_, scale, dest_);
- }
-
- // Simple fast while loop to implement dest += source.
- CLD3_ATTRIBUTE_ALWAYS_INLINE static void AddImpl(
- const float *__restrict source, uint32 size, float *__restrict dest) {
- for (uint32 i = 0; i < size; ++i) {
- dest[i] += source[i];
- }
- }
-
- // Simple fast while loop to implement dest += scale * source.
- CLD3_ATTRIBUTE_ALWAYS_INLINE static void ScaleAddImpl(
- const float *__restrict source, uint32 size, const float scale,
- float *__restrict dest) {
- for (uint32 i = 0; i < size; ++i) {
- dest[i] += source[i] * scale;
- }
- }
-
- private:
- float *dest_;
- int num_floats_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // SIMPLE_ADDER_H_
diff --git a/chromium/third_party/cld_3/src/src/task_context.cc b/chromium/third_party/cld_3/src/src/task_context.cc
deleted file mode 100644
index 4f9636882f4..00000000000
--- a/chromium/third_party/cld_3/src/src/task_context.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "task_context.h"
-
-#include "utils.h"
-
-namespace chrome_lang_id {
-
-TaskContext::TaskContext() {}
-
-TaskContext::~TaskContext() {}
-
-TaskInput *TaskContext::GetInput(const string &name) {
- // Return existing input if it exists.
- for (int i = 0; i < spec_.input_size(); ++i) {
- if (spec_.input(i).name() == name) return spec_.mutable_input(i);
- }
-
- // Create new input.
- TaskInput *input = spec_.add_input();
- input->set_name(name);
- return input;
-}
-
-TaskInput *TaskContext::GetInput(const string &name, const string &file_format,
- const string &record_format) {
- TaskInput *input = GetInput(name);
- if (!file_format.empty()) {
- bool found = false;
- for (int i = 0; i < input->file_format_size(); ++i) {
- if (input->file_format(i) == file_format) found = true;
- }
- if (!found) input->add_file_format(file_format);
- }
- if (!record_format.empty()) {
- bool found = false;
- for (int i = 0; i < input->record_format_size(); ++i) {
- if (input->record_format(i) == record_format) found = true;
- }
- if (!found) input->add_record_format(record_format);
- }
- return input;
-}
-
-void TaskContext::SetParameter(const string &name, const string &value) {
- // If the parameter already exists update the value.
- for (int i = 0; i < spec_.parameter_size(); ++i) {
- if (spec_.parameter(i).name() == name) {
- spec_.mutable_parameter(i)->set_value(value);
- return;
- }
- }
-
- // Add new parameter.
- TaskSpec::Parameter *param = spec_.add_parameter();
- param->set_name(name);
- param->set_value(value);
-}
-
-string TaskContext::GetParameter(const string &name) const {
- // First try to find parameter in task specification.
- for (int i = 0; i < spec_.parameter_size(); ++i) {
- if (spec_.parameter(i).name() == name) return spec_.parameter(i).value();
- }
-
- // Parameter not found, return empty string.
- return "";
-}
-
-int TaskContext::GetIntParameter(const string &name) const {
- string value = GetParameter(name);
- return utils::ParseUsing<int>(value, 0, utils::ParseInt32);
-}
-
-bool TaskContext::GetBoolParameter(const string &name) const {
- string value = GetParameter(name);
- return value == "true";
-}
-
-double TaskContext::GetFloatParameter(const string &name) const {
- string value = GetParameter(name);
- return utils::ParseUsing<double>(value, .0, utils::ParseDouble);
-}
-
-string TaskContext::Get(const string &name, const char *defval) const {
- // First try to find parameter in task specification.
- for (int i = 0; i < spec_.parameter_size(); ++i) {
- if (spec_.parameter(i).name() == name) return spec_.parameter(i).value();
- }
-
- // Parameter not found, return default value.
- return defval;
-}
-
-string TaskContext::Get(const string &name, const string &defval) const {
- return Get(name, defval.c_str());
-}
-
-int TaskContext::Get(const string &name, int defval) const {
- string value = Get(name, "");
- return utils::ParseUsing<int>(value, defval, utils::ParseInt32);
-}
-
-double TaskContext::Get(const string &name, double defval) const {
- string value = Get(name, "");
- return utils::ParseUsing<double>(value, defval, utils::ParseDouble);
-}
-
-bool TaskContext::Get(const string &name, bool defval) const {
- string value = Get(name, "");
- return value.empty() ? defval : value == "true";
-}
-
-string TaskContext::InputFile(const TaskInput &input) {
- CLD3_CHECK(input.part_size() == 1);
- return input.part(0).file_pattern();
-}
-
-bool TaskContext::Supports(const TaskInput &input, const string &file_format,
- const string &record_format) {
- // Check file format.
- if (input.file_format_size() > 0) {
- bool found = false;
- for (int i = 0; i < input.file_format_size(); ++i) {
- if (input.file_format(i) == file_format) {
- found = true;
- break;
- }
- }
- if (!found) return false;
- }
-
- // Check record format.
- if (input.record_format_size() > 0) {
- bool found = false;
- for (int i = 0; i < input.record_format_size(); ++i) {
- if (input.record_format(i) == record_format) {
- found = true;
- break;
- }
- }
- if (!found) return false;
- }
-
- return true;
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/task_context.h b/chromium/third_party/cld_3/src/src/task_context.h
deleted file mode 100644
index d3a5eb6c066..00000000000
--- a/chromium/third_party/cld_3/src/src/task_context.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef TASK_CONTEXT_H_
-#define TASK_CONTEXT_H_
-
-#include <string>
-#include <vector>
-
-#include "base.h"
-#include "cld_3/protos/task_spec.pb.h"
-
-namespace chrome_lang_id {
-
-// A task context holds configuration information for a task. It is basically a
-// wrapper around a TaskSpec protocol buffer.
-class TaskContext {
- public:
- TaskContext();
- ~TaskContext();
-
- // Returns the underlying task specification protocol buffer for the context.
- const TaskSpec &spec() const { return spec_; }
- TaskSpec *mutable_spec() { return &spec_; }
-
- // Returns a named input descriptor for the task. A new input is created if
- // the task context does not already have an input with that name.
- TaskInput *GetInput(const string &name);
- TaskInput *GetInput(const string &name, const string &file_format,
- const string &record_format);
-
- // Sets task parameter.
- void SetParameter(const string &name, const string &value);
-
- // Returns task parameter. If the parameter is not in the task configuration
- // the (default) value of the corresponding command line flag is returned.
- string GetParameter(const string &name) const;
- int GetIntParameter(const string &name) const;
- bool GetBoolParameter(const string &name) const;
- double GetFloatParameter(const string &name) const;
-
- // Returns task parameter. If the parameter is not in the task configuration
- // the default value is returned. Parameters retrieved using these methods
- // don't need to be defined with a DEFINE_*() macro.
- string Get(const string &name, const string &defval) const;
- string Get(const string &name, const char *defval) const;
- int Get(const string &name, int defval) const;
- double Get(const string &name, double defval) const;
- bool Get(const string &name, bool defval) const;
-
- // Returns input file name for a single-file task input.
- static string InputFile(const TaskInput &input);
-
- // Returns true if task input supports the file and record format.
- static bool Supports(const TaskInput &input, const string &file_format,
- const string &record_format);
-
- private:
- // Underlying task specification protocol buffer.
- TaskSpec spec_;
-
- // Vector of parameters required by this task. These must be specified in the
- // task rather than relying on default values.
- std::vector<string> required_parameters_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // TASK_CONTEXT_H_
diff --git a/chromium/third_party/cld_3/src/src/task_context_params.cc b/chromium/third_party/cld_3/src/src/task_context_params.cc
deleted file mode 100644
index 27cf89d36bb..00000000000
--- a/chromium/third_party/cld_3/src/src/task_context_params.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// This file contains the hard-coded parameters from the training workflow. If
-// you update the binary model, you may need to update the variables below as
-// well.
-
-#include "task_context_params.h"
-
-#include "task_context.h"
-
-namespace chrome_lang_id {
-
-void TaskContextParams::ToTaskContext(TaskContext *context) {
- context->SetParameter("language_identifier_features",
- kLanguageIdentifierFeatures);
- context->SetParameter("language_identifier_embedding_names",
- kLanguageIdentifierEmbeddingNames);
- context->SetParameter("language_identifier_embedding_dims",
- kLanguageIdentifierEmbeddingDims);
-}
-
-int TaskContextParams::GetNumLanguages() {
- int i = 0;
- while (kLanguageNames[i] != nullptr) {
- i++;
- }
- return i;
-}
-
-const char *const TaskContextParams::kLanguageNames[] = {
- "eo", "co", "eu", "ta", "de", "mt", "ps", "te", "su", "uz", "zh-Latn", "ne",
- "nl", "sw", "sq", "hmn", "ja", "no", "mn", "so", "ko", "kk", "sl", "ig",
- "mr", "th", "zu", "ml", "hr", "bs", "lo", "sd", "cy", "hy", "uk", "pt",
- "lv", "iw", "cs", "vi", "jv", "be", "km", "mk", "tr", "fy", "am", "zh",
- "da", "sv", "fi", "ht", "af", "la", "id", "fil", "sm", "ca", "el", "ka",
- "sr", "it", "sk", "ru", "ru-Latn", "bg", "ny", "fa", "haw", "gl", "et",
- "ms", "gd", "bg-Latn", "ha", "is", "ur", "mi", "hi", "bn", "hi-Latn", "fr",
- "yi", "hu", "xh", "my", "tg", "ro", "ar", "lb", "el-Latn", "st", "ceb",
- "kn", "az", "si", "ky", "mg", "en", "gu", "es", "pl", "ja-Latn", "ga", "lt",
- "sn", "yo", "pa", "ku",
-
- // last element must be nullptr
- nullptr,
-};
-
-const char TaskContextParams::kLanguageIdentifierFeatures[] =
- "continuous-bag-of-ngrams(include_terminators=true,include_spaces=false,"
- "use_equal_weight=false,id_dim=1000,size=2);continuous-bag-of-ngrams("
- "include_terminators=true,include_spaces=false,use_equal_weight=false,id_"
- "dim=5000,size=4);continuous-bag-of-relevant-scripts;script;continuous-bag-"
- "of-ngrams(include_terminators=true,include_spaces=false,use_equal_weight="
- "false,id_dim=5000,size=3);continuous-bag-of-ngrams(include_terminators="
- "true,include_spaces=false,use_equal_weight=false,id_dim=100,size=1)";
-
-const char TaskContextParams::kLanguageIdentifierEmbeddingNames[] =
- "bigrams;quadgrams;relevant-scripts;text-script;trigrams;unigrams";
-
-const char TaskContextParams::kLanguageIdentifierEmbeddingDims[] =
- "16;16;8;8;16;16";
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/task_context_params.h b/chromium/third_party/cld_3/src/src/task_context_params.h
deleted file mode 100644
index 95d865b3be5..00000000000
--- a/chromium/third_party/cld_3/src/src/task_context_params.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef TASK_CONTEXT_PARAMS_H_
-#define TASK_CONTEXT_PARAMS_H_
-
-#include <string>
-
-#include "base.h"
-#include "task_context.h"
-
-namespace chrome_lang_id {
-
-// Encapsulates the TaskContext specifying only the parameters for the model.
-// The model weights are loaded statically.
-class TaskContextParams {
- public:
- // Gets the name of the i'th language.
- static const char *language_names(int i) { return kLanguageNames[i]; }
-
- // Saves the parameters to the given TaskContext.
- static void ToTaskContext(TaskContext *context);
-
- // Gets the number of languages.
- static int GetNumLanguages();
-
- private:
- // Names of all the languages.
- static const char *const kLanguageNames[];
-
- // Features in FML format.
- static const char kLanguageIdentifierFeatures[];
-
- // Names of the embedding spaces.
- static const char kLanguageIdentifierEmbeddingNames[];
-
- // Dimensions of the embedding spaces.
- static const char kLanguageIdentifierEmbeddingDims[];
-};
-} // namespace chrome_lang_id
-
-#endif // TASK_CONTEXT_PARAMS_H_
diff --git a/chromium/third_party/cld_3/src/src/task_spec.proto b/chromium/third_party/cld_3/src/src/task_spec.proto
deleted file mode 100644
index b91bb1261ca..00000000000
--- a/chromium/third_party/cld_3/src/src/task_spec.proto
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// LINT: ALLOW_GROUPS
-// Protocol buffer specifications for task configuration.
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package chrome_lang_id;
-
-// Task input descriptor.
-message TaskInput {
- // Name of input resource.
- required string name = 1;
-
- // Name of stage responsible of creating this resource.
- optional string creator = 2;
-
- // File format for resource.
- repeated string file_format = 3;
-
- // Record format for resource.
- repeated string record_format = 4;
-
- // Is this resource multi-file?
- optional bool multi_file = 5 [default = false];
-
- // An input can consist of multiple file sets.
- repeated group Part = 6 {
- // File pattern for file set.
- optional string file_pattern = 7;
-
- // File format for file set.
- optional string file_format = 8;
-
- // Record format for file set.
- optional string record_format = 9;
- }
-}
-
-// Task output descriptor.
-message TaskOutput {
- // Name of output resource.
- required string name = 1;
-
- // File format for output resource.
- optional string file_format = 2;
-
- // Record format for output resource.
- optional string record_format = 3;
-
- // Number of shards in output. If it is different from zero this output is
- // sharded. If the number of shards is set to -1 this means that the output is
- // sharded, but the number of shard is unknown. The files are then named
- // 'base-*-of-*'.
- optional int32 shards = 4 [default = 0];
-
- // Base file name for output resource. If this is not set by the task
- // component it is set to a default value by the workflow engine.
- optional string file_base = 5;
-
- // Optional extension added to the file name.
- optional string file_extension = 6;
-}
-
-// A task specification is used for describing executing parameters.
-message TaskSpec {
- // Name of task.
- optional string task_name = 1;
-
- // Workflow task type.
- optional string task_type = 2;
-
- // Task parameters.
- repeated group Parameter = 3 {
- required string name = 4;
- optional string value = 5;
- }
-
- // Task inputs.
- repeated TaskInput input = 6;
-
- // Task outputs.
- repeated TaskOutput output = 7;
-}
diff --git a/chromium/third_party/cld_3/src/src/unicodetext.cc b/chromium/third_party/cld_3/src/src/unicodetext.cc
deleted file mode 100644
index 67f52a0981f..00000000000
--- a/chromium/third_party/cld_3/src/src/unicodetext.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (C) 2006 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Author: Jim Meehan
-
-#include "unicodetext.h"
-
-#include "base.h"
-#include "utils.h"
-
-namespace chrome_lang_id {
-
-// *************** Data representation **********
-// Note: the copy constructor is undefined.
-
-void UnicodeText::Repr::PointTo(const char *data, int size) {
- if (ours_ && data_) delete[] data_; // If we owned the old buffer, free it.
- data_ = const_cast<char *>(data);
- size_ = size;
- capacity_ = size;
- ours_ = false;
-}
-
-// *************** UnicodeText ******************
-
-UnicodeText::UnicodeText() {}
-
-UnicodeText &UnicodeText::PointToUTF8(const char *buffer, int byte_length) {
- repr_.PointTo(buffer, byte_length);
- return *this;
-}
-
-UnicodeText::~UnicodeText() {}
-
-// ******************* UnicodeText::const_iterator *********************
-
-// The implementation of const_iterator would be nicer if it
-// inherited from boost::iterator_facade
-// (http://boost.org/libs/iterator/doc/iterator_facade.html).
-
-UnicodeText::const_iterator::const_iterator() : it_(0) {}
-
-UnicodeText::const_iterator &UnicodeText::const_iterator::operator=(
- const const_iterator &other) {
- if (&other != this) it_ = other.it_;
- return *this;
-}
-
-UnicodeText::const_iterator UnicodeText::begin() const {
- return const_iterator(repr_.data_);
-}
-
-UnicodeText::const_iterator UnicodeText::end() const {
- return const_iterator(repr_.data_ + repr_.size_);
-}
-
-char32 UnicodeText::const_iterator::operator*() const {
- // (We could call chartorune here, but that does some
- // error-checking, and we're guaranteed that our data is valid
- // UTF-8. Also, we expect this routine to be called very often. So
- // for speed, we do the calculation ourselves.)
-
- // Convert from UTF-8
- unsigned char byte1 = static_cast<unsigned char>(it_[0]);
- if (byte1 < 0x80) return byte1;
-
- unsigned char byte2 = static_cast<unsigned char>(it_[1]);
- if (byte1 < 0xE0) return ((byte1 & 0x1F) << 6) | (byte2 & 0x3F);
-
- unsigned char byte3 = static_cast<unsigned char>(it_[2]);
- if (byte1 < 0xF0) {
- return ((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F);
- }
-
- unsigned char byte4 = static_cast<unsigned char>(it_[3]);
- return ((byte1 & 0x07) << 18) | ((byte2 & 0x3F) << 12) |
- ((byte3 & 0x3F) << 6) | (byte4 & 0x3F);
-}
-
-UnicodeText::const_iterator &UnicodeText::const_iterator::operator++() {
- it_ += chrome_lang_id::utils::OneCharLen(it_);
- return *this;
-}
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/unicodetext.h b/chromium/third_party/cld_3/src/src/unicodetext.h
deleted file mode 100644
index e53c870fe7e..00000000000
--- a/chromium/third_party/cld_3/src/src/unicodetext.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (C) 2006 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Author: Jim Meehan
-
-#ifndef UNICODETEXT_H_
-#define UNICODETEXT_H_
-
-#include <iterator>
-#include <utility>
-
-#include "base.h"
-
-namespace chrome_lang_id {
-
-// ***************************** UnicodeText **************************
-//
-// A UnicodeText object is a wrapper around a sequence of Unicode
-// codepoint values that allows iteration over these values.
-//
-// The internal representation of the text is UTF-8. Since UTF-8 is a
-// variable-width format, UnicodeText does not provide random access
-// to the text, and changes to the text are permitted only at the end.
-//
-// The UnicodeText class defines a const_iterator. The dereferencing
-// operator (*) returns a codepoint (int32). The iterator is a
-// read-only iterator. It becomes invalid if the text is changed.
-//
-// Codepoints are integers in the range [0, 0xD7FF] or [0xE000,
-// 0x10FFFF], but UnicodeText has the additional restriction that it
-// can contain only those characters that are valid for interchange on
-// the Web. This excludes all of the control codes except for carriage
-// return, line feed, and horizontal tab. It also excludes
-// non-characters, but codepoints that are in the Private Use regions
-// are allowed, as are codepoints that are unassigned. (See the
-// Unicode reference for details.)
-//
-// MEMORY MANAGEMENT:
-//
-// PointToUTF8(buffer, size) creates an alias pointing to buffer.
-//
-// The purpose of an alias is to avoid making an unnecessary copy of a
-// UTF-8 buffer while still providing access to the Unicode values
-// within that text through iterators. The lifetime of an alias must not
-// exceed the lifetime of the buffer from which it was constructed.
-//
-// Aliases should be used with care. If the source from which an alias
-// was created is freed, or if the contents are changed, while the
-// alias is still in use, fatal errors could result. But it can be
-// quite useful to have a UnicodeText "window" through which to see a
-// UTF-8 buffer without having to pay the price of making a copy.
-
-// TODO(abakalov): Consider merging this class with the script detection
-// code in the directory script_span.
-class UnicodeText {
- public:
- class const_iterator;
-
- UnicodeText(); // Create an empty text.
- ~UnicodeText();
-
- class const_iterator {
- typedef const_iterator CI;
-
- public:
- // Iterators are default-constructible.
- const_iterator();
-
- // It's safe to make multiple passes over a UnicodeText.
- const_iterator(const const_iterator &other);
- const_iterator &operator=(const const_iterator &other);
-
- char32 operator*() const; // Dereference
-
- const_iterator &operator++(); // Advance (++iter)
-
- friend bool operator==(const CI &lhs, const CI &rhs) {
- return lhs.it_ == rhs.it_;
- }
- friend bool operator!=(const CI &lhs, const CI &rhs) {
- return !(lhs == rhs);
- }
-
- private:
- friend class UnicodeText;
- explicit const_iterator(const char *it) : it_(it) {}
-
- const char *it_;
- };
-
- const_iterator begin() const;
- const_iterator end() const;
-
- // x.PointToUTF8(buf,len) changes x so that it points to buf
- // ("becomes an alias"). It does not take ownership or copy buf.
- // This function assumes that the input is interchange valid UTF8.
- UnicodeText &PointToUTF8(const char *utf8_buffer, int byte_length);
-
- private:
- friend class const_iterator;
-
- class Repr { // A byte-string.
- public:
- char *data_;
- int size_;
- int capacity_;
- bool ours_; // Do we own data_?
-
- Repr() : data_(NULL), size_(0), capacity_(0), ours_(true) {}
- ~Repr() {
- if (ours_) delete[] data_;
- }
-
- void clear();
- void reserve(int capacity);
- void resize(int size);
-
- void append(const char *bytes, int byte_length);
- void Copy(const char *data, int size);
- void TakeOwnershipOf(char *data, int size, int capacity);
- void PointTo(const char *data, int size);
-
- private:
- Repr &operator=(const Repr &);
- Repr(const Repr &other);
- };
-
- Repr repr_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // UNICODETEXT_H_
diff --git a/chromium/third_party/cld_3/src/src/utils.cc b/chromium/third_party/cld_3/src/src/utils.cc
deleted file mode 100644
index 3268a9bd094..00000000000
--- a/chromium/third_party/cld_3/src/src/utils.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "utils.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-
-#include "script_span/stringpiece.h"
-
-namespace chrome_lang_id {
-namespace utils {
-
-bool ParseInt32(const char *c_str, int *value) {
- char *temp;
- *value = strtol(c_str, &temp, 0); // NOLINT
- return (*temp == '\0');
-}
-
-bool ParseDouble(const char *c_str, double *value) {
- char *temp;
- *value = strtod(c_str, &temp);
- return (*temp == '\0');
-}
-
-static char hex_char[] = "0123456789abcdef";
-
-string CEscape(const string &src) {
- string dest;
-
- for (unsigned char c : src) {
- switch (c) {
- case '\n':
- dest.append("\\n");
- break;
- case '\r':
- dest.append("\\r");
- break;
- case '\t':
- dest.append("\\t");
- break;
- case '\"':
- dest.append("\\\"");
- break;
- case '\'':
- dest.append("\\'");
- break;
- case '\\':
- dest.append("\\\\");
- break;
- default:
- // Note that if we emit \xNN and the src character after that is a hex
- // digit then that digit must be escaped too to prevent it being
- // interpreted as part of the character code by C.
- if ((c >= 0x80) || !isprint(c)) {
- dest.append("\\");
- dest.push_back(hex_char[c / 64]);
- dest.push_back(hex_char[(c % 64) / 8]);
- dest.push_back(hex_char[c % 8]);
- } else {
- dest.push_back(c);
- break;
- }
- }
- }
-
- return dest;
-}
-
-std::vector<string> Split(const string &text, char delim) {
- std::vector<string> result;
- size_t token_start = 0;
- if (!text.empty()) {
- for (size_t i = 0; i < text.size() + 1; i++) {
- if ((i == text.size()) || (text[i] == delim)) {
- result.push_back(string(text.data() + token_start, i - token_start));
- token_start = i + 1;
- }
- }
- }
- return result;
-}
-
-int RemoveLeadingWhitespace(StringPiece *text) {
- int count = 0;
- const char *ptr = text->data();
- while (count < text->size() && isspace(*ptr)) {
- count++;
- ptr++;
- }
- text->remove_prefix(count);
- return count;
-}
-
-int RemoveTrailingWhitespace(StringPiece *text) {
- int count = 0;
- const char *ptr = text->data() + text->size() - 1;
- while (count < text->size() && isspace(*ptr)) {
- ++count;
- --ptr;
- }
- text->remove_suffix(count);
- return count;
-}
-
-int RemoveWhitespaceContext(StringPiece *text) {
- // use RemoveLeadingWhitespace() and RemoveTrailingWhitespace() to do the job
- return RemoveLeadingWhitespace(text) + RemoveTrailingWhitespace(text);
-}
-
-namespace {
-// Lower-level versions of Get... that read directly from a character buffer
-// without any bounds checking.
-inline uint32 DecodeFixed32(const char *ptr) {
- return ((static_cast<uint32>(static_cast<unsigned char>(ptr[0]))) |
- (static_cast<uint32>(static_cast<unsigned char>(ptr[1])) << 8) |
- (static_cast<uint32>(static_cast<unsigned char>(ptr[2])) << 16) |
- (static_cast<uint32>(static_cast<unsigned char>(ptr[3])) << 24));
-}
-
-// 0xff is in case char is signed.
-static inline uint32 ByteAs32(char c) { return static_cast<uint32>(c) & 0xff; }
-} // namespace
-
-uint32 Hash32(const char *data, size_t n, uint32 seed) {
- // 'm' and 'r' are mixing constants generated offline.
- // They're not really 'magic', they just happen to work well.
- const uint32 m = 0x5bd1e995;
- const int r = 24;
-
- // Initialize the hash to a 'random' value
- uint32 h = static_cast<uint32>(seed ^ n);
-
- // Mix 4 bytes at a time into the hash
- while (n >= 4) {
- uint32 k = DecodeFixed32(data);
- k *= m;
- k ^= k >> r;
- k *= m;
- h *= m;
- h ^= k;
- data += 4;
- n -= 4;
- }
-
- // Handle the last few bytes of the input array
- if (n == 3) {
- h ^= ByteAs32(data[2]) << 16;
- h ^= ByteAs32(data[1]) << 8;
- h ^= ByteAs32(data[0]);
- h *= m;
- } else if (n == 2) {
- h ^= ByteAs32(data[1]) << 8;
- h ^= ByteAs32(data[0]);
- h *= m;
- } else if (n == 1) {
- h ^= ByteAs32(data[0]);
- h *= m;
- }
-
- // Do a few final mixes of the hash to ensure the last few
- // bytes are well-incorporated.
- h ^= h >> 13;
- h *= m;
- h ^= h >> 15;
- return h;
-}
-
-uint32 Hash32WithDefaultSeed(const string &input) {
- return Hash32(input.data(), input.size(), 0xBEEF);
-}
-
-PunctuationUtil::CharacterRange PunctuationUtil::kPunctuation[] = {
- {33, 35}, {37, 42}, {44, 47}, {58, 59},
- {63, 64}, {91, 93}, {95, 95}, {123, 123},
- {125, 125}, {161, 161}, {171, 171}, {183, 183},
- {187, 187}, {191, 191}, {894, 894}, {903, 903},
- {1370, 1375}, {1417, 1418}, {1470, 1470}, {1472, 1472},
- {1475, 1475}, {1478, 1478}, {1523, 1524}, {1548, 1549},
- {1563, 1563}, {1566, 1567}, {1642, 1645}, {1748, 1748},
- {1792, 1805}, {2404, 2405}, {2416, 2416}, {3572, 3572},
- {3663, 3663}, {3674, 3675}, {3844, 3858}, {3898, 3901},
- {3973, 3973}, {4048, 4049}, {4170, 4175}, {4347, 4347},
- {4961, 4968}, {5741, 5742}, {5787, 5788}, {5867, 5869},
- {5941, 5942}, {6100, 6102}, {6104, 6106}, {6144, 6154},
- {6468, 6469}, {6622, 6623}, {6686, 6687}, {8208, 8231},
- {8240, 8259}, {8261, 8273}, {8275, 8286}, {8317, 8318},
- {8333, 8334}, {9001, 9002}, {9140, 9142}, {10088, 10101},
- {10181, 10182}, {10214, 10219}, {10627, 10648}, {10712, 10715},
- {10748, 10749}, {11513, 11516}, {11518, 11519}, {11776, 11799},
- {11804, 11805}, {12289, 12291}, {12296, 12305}, {12308, 12319},
- {12336, 12336}, {12349, 12349}, {12448, 12448}, {12539, 12539},
- {64830, 64831}, {65040, 65049}, {65072, 65106}, {65108, 65121},
- {65123, 65123}, {65128, 65128}, {65130, 65131}, {65281, 65283},
- {65285, 65290}, {65292, 65295}, {65306, 65307}, {65311, 65312},
- {65339, 65341}, {65343, 65343}, {65371, 65371}, {65373, 65373},
- {65375, 65381}, {65792, 65793}, {66463, 66463}, {68176, 68184},
- {-1, -1}};
-
-void NormalizeDigits(string *form) {
- for (size_t i = 0; i < form->size(); ++i) {
- if ((*form)[i] >= '0' && (*form)[i] <= '9') (*form)[i] = '9';
- }
-}
-
-void GetUTF8Chars(const string &text, std::vector<string> *chars) {
- const char *start = text.c_str();
- const char *end = text.c_str() + text.size();
- while (start < end) {
- int char_length = UTF8FirstLetterNumBytes(start);
- chars->emplace_back(start, char_length);
- start += char_length;
- }
-}
-
-int UTF8FirstLetterNumBytes(const char *utf8_str) {
- if (*utf8_str == '\0') return 0;
- return OneCharLen(utf8_str);
-}
-
-int OneCharLen(const char *src) {
- // On most platforms, char is unsigned by default, but iOS is an exception.
- // The cast below makes sure we always interpret *src as an unsigned char.
- return "\1\1\1\1\1\1\1\1\1\1\1\1\2\2\3\4"
- [(*(reinterpret_cast<const unsigned char *>(src)) & 0xFF) >> 4];
-}
-
-} // namespace utils
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/utils.h b/chromium/third_party/cld_3/src/src/utils.h
deleted file mode 100644
index 60845cb4bb3..00000000000
--- a/chromium/third_party/cld_3/src/src/utils.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#ifndef UTILS_H_
-#define UTILS_H_
-
-#include <stddef.h>
-#include <functional>
-#include <initializer_list>
-#include <string>
-#include <vector>
-
-#include "base.h"
-#include "script_span/stringpiece.h"
-
-namespace chrome_lang_id {
-namespace utils {
-
-bool ParseInt32(const char *c_str, int *value);
-bool ParseDouble(const char *c_str, double *value);
-
-template <typename T>
-T ParseUsing(const string &str, std::function<bool(const char *, T *)> func) {
- T value;
- func(str.c_str(), &value);
- return value;
-}
-
-template <typename T>
-T ParseUsing(const string &str, T defval,
- std::function<bool(const char *, T *)> func) {
- return str.empty() ? defval : ParseUsing<T>(str, func);
-}
-
-string CEscape(const string &src);
-
-std::vector<string> Split(const string &text, char delim);
-
-int RemoveLeadingWhitespace(StringPiece *text);
-
-int RemoveTrailingWhitespace(StringPiece *text);
-
-int RemoveWhitespaceContext(StringPiece *text);
-
-uint32 Hash32(const char *data, size_t n, uint32 seed);
-
-uint32 Hash32WithDefaultSeed(const string &input);
-
-// Deletes all the elements in an STL container and clears the container. This
-// function is suitable for use with a vector, set, hash_set, or any other STL
-// container which defines sensible begin(), end(), and clear() methods.
-// If container is NULL, this function is a no-op.
-template <typename T>
-void STLDeleteElements(T *container) {
- if (!container) return;
- auto it = container->begin();
- while (it != container->end()) {
- auto temp = it;
- ++it;
- delete *temp;
- }
- container->clear();
-}
-
-class PunctuationUtil {
- public:
- // Unicode character ranges for punctuation characters according to CoNLL.
- struct CharacterRange {
- int first;
- int last;
- };
- static CharacterRange kPunctuation[];
-
- // Returns true if Unicode character is a punctuation character.
- static bool IsPunctuation(int u) {
- int i = 0;
- while (kPunctuation[i].first > 0) {
- if (u < kPunctuation[i].first) return false;
- if (u <= kPunctuation[i].last) return true;
- ++i;
- }
- return false;
- }
-
- // Determine if tag is a punctuation tag.
- static bool IsPunctuationTag(const string &tag) {
- for (size_t i = 0; i < tag.length(); ++i) {
- int c = tag[i];
- if (c != ',' && c != ':' && c != '.' && c != '\'' && c != '`') {
- return false;
- }
- }
- return true;
- }
-
- // Returns true if tag is non-empty and has only punctuation or parens
- // symbols.
- static bool IsPunctuationTagOrParens(const string &tag) {
- if (tag.empty()) return false;
- for (size_t i = 0; i < tag.length(); ++i) {
- int c = tag[i];
- if (c != '(' && c != ')' && c != ',' && c != ':' && c != '.' &&
- c != '\'' && c != '`') {
- return false;
- }
- }
- return true;
- }
-};
-
-void NormalizeDigits(string *form);
-
-// Takes a text and convert it into a vector, where each element is a utf8
-// character.
-void GetUTF8Chars(const string &text, std::vector<string> *chars);
-
-// Returns the number of bytes in the first UTF-8 char at the beginning
-// of the string. It is assumed that the string is valid UTF-8. If
-// the first byte of the string is null, return 0 (for backwards
-// compatibility only; this use is discouraged).
-int UTF8FirstLetterNumBytes(const char *in_buf);
-
-// Returns the length (number of bytes) of the Unicode code point starting at
-// src, based on inspecting just that one byte. Preconditions: src != NULL,
-// *src can be read, and *src is not '\0', and src points to a well-formed UTF-8
-// string.
-int OneCharLen(const char *src);
-
-} // namespace utils
-} // namespace chrome_lang_id
-
-#endif // UTILS_H_
diff --git a/chromium/third_party/cld_3/src/src/workspace.cc b/chromium/third_party/cld_3/src/src/workspace.cc
deleted file mode 100644
index e48b5116068..00000000000
--- a/chromium/third_party/cld_3/src/src/workspace.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-#include "workspace.h"
-
-#include "base.h"
-
-namespace chrome_lang_id {
-
-WorkspaceSet::WorkspaceSet() {}
-
-WorkspaceSet::~WorkspaceSet() { Reset(WorkspaceRegistry()); }
-
-WorkspaceRegistry::WorkspaceRegistry() {}
-
-WorkspaceRegistry::~WorkspaceRegistry() {}
-
-string WorkspaceRegistry::DebugString() const {
- string str;
- for (auto &it : workspace_names_) {
- const string &type_name = workspace_types_.at(it.first);
- for (size_t index = 0; index < it.second.size(); ++index) {
- const string &workspace_name = it.second[index];
- str += "\n ";
- str += type_name;
- str += " :: ";
- str += workspace_name;
- }
- }
- return str;
-}
-
-VectorIntWorkspace::~VectorIntWorkspace() {}
-
-VectorIntWorkspace::VectorIntWorkspace(int size) : elements_(size) {}
-
-VectorIntWorkspace::VectorIntWorkspace(int size, int value)
- : elements_(size, value) {}
-
-VectorIntWorkspace::VectorIntWorkspace(const std::vector<int> &elements)
- : elements_(elements) {}
-
-string VectorIntWorkspace::TypeName() { return "Vector"; }
-
-VectorVectorIntWorkspace::~VectorVectorIntWorkspace() {}
-
-VectorVectorIntWorkspace::VectorVectorIntWorkspace(int size)
- : elements_(size) {}
-
-string VectorVectorIntWorkspace::TypeName() { return "VectorVector"; }
-
-} // namespace chrome_lang_id
diff --git a/chromium/third_party/cld_3/src/src/workspace.h b/chromium/third_party/cld_3/src/src/workspace.h
deleted file mode 100644
index d31e9ca6792..00000000000
--- a/chromium/third_party/cld_3/src/src/workspace.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/* Copyright 2016 Google Inc. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Notes on thread-safety: All of the classes here are thread-compatible. More
-// specifically, the registry machinery is thread-safe, as long as each thread
-// performs feature extraction on a different Sentence object.
-
-#ifndef WORKSPACE_H_
-#define WORKSPACE_H_
-
-#include <stddef.h>
-#include <string>
-#include <typeindex>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "base.h"
-
-namespace chrome_lang_id {
-
-// A base class for shared workspaces. Derived classes implement a static member
-// function TypeName() which returns a human readable string name for the class.
-class Workspace {
- public:
- // Polymorphic destructor.
- virtual ~Workspace() {}
-
- protected:
- // Create an empty workspace.
- Workspace() {}
-
- private:
- CLD3_DISALLOW_COPY_AND_ASSIGN(Workspace);
-};
-
-// A registry that keeps track of workspaces.
-class WorkspaceRegistry {
- public:
- // Create an empty registry.
- WorkspaceRegistry();
- ~WorkspaceRegistry();
-
- const std::unordered_map<std::type_index, std::vector<std::string>>
- &WorkspaceNames() const {
- return workspace_names_;
- }
-
- // Returns a string describing the registered workspaces.
- string DebugString() const;
-
- private:
- // Workspace type names, indexed as workspace_types_[typeid].
- std::unordered_map<std::type_index, string> workspace_types_;
-
- // Workspace names, indexed as workspace_names_[typeid][workspace].
- std::unordered_map<std::type_index, std::vector<string>> workspace_names_;
-
- CLD3_DISALLOW_COPY_AND_ASSIGN(WorkspaceRegistry);
-};
-
-// A typed collected of workspaces. The workspaces are indexed according to an
-// external WorkspaceRegistry. If the WorkspaceSet is const, the contents are
-// also immutable.
-class WorkspaceSet {
- public:
- WorkspaceSet();
- ~WorkspaceSet();
-
- void Reset(const WorkspaceRegistry &registry) {
- // Deallocate current workspaces.
- for (auto &it : workspaces_) {
- for (size_t index = 0; index < it.second.size(); ++index) {
- delete it.second[index];
- }
- }
- workspaces_.clear();
-
- // Allocate space for new workspaces.
- for (auto &it : registry.WorkspaceNames()) {
- workspaces_[it.first].resize(it.second.size());
- }
- }
-
- private:
- // The set of workspaces, indexed as workspaces_[typeid][index].
- std::unordered_map<std::type_index, std::vector<Workspace *>> workspaces_;
-};
-
-// A workspace that wraps around a single int.
-class SingletonIntWorkspace : public Workspace {
- public:
- // Default-initializes the int value.
- SingletonIntWorkspace() {}
-
- // Initializes the int with the given value.
- explicit SingletonIntWorkspace(int value) : value_(value) {}
-
- // Returns the name of this type of workspace.
- static string TypeName() { return "SingletonInt"; }
-
- // Returns the int value.
- int get() const { return value_; }
-
- // Sets the int value.
- void set(int value) { value_ = value; }
-
- private:
- // The enclosed int.
- int value_ = 0;
-};
-
-// A workspace that wraps around a vector of int.
-class VectorIntWorkspace : public Workspace {
- public:
- // Creates a vector of the given size.
- explicit VectorIntWorkspace(int size);
-
- // Creates a vector initialized with the given array.
- explicit VectorIntWorkspace(const std::vector<int> &elements);
-
- // Creates a vector of the given size, with each element initialized to the
- // given value.
- VectorIntWorkspace(int size, int value);
-
- ~VectorIntWorkspace() override;
-
- // Returns the name of this type of workspace.
- static string TypeName();
-
- // Returns the i'th element.
- int element(int i) const { return elements_[i]; }
-
- // Sets the i'th element.
- void set_element(int i, int value) { elements_[i] = value; }
-
- private:
- // The enclosed vector.
- std::vector<int> elements_;
-};
-
-// A workspace that wraps around a vector of vector of int.
-class VectorVectorIntWorkspace : public Workspace {
- public:
- // Creates a vector of empty vectors of the given size.
- explicit VectorVectorIntWorkspace(int size);
- ~VectorVectorIntWorkspace() override;
-
- // Returns the name of this type of workspace.
- static string TypeName();
-
- // Returns the i'th vector of elements.
- const std::vector<int> &elements(int i) const { return elements_[i]; }
-
- // Mutable access to the i'th vector of elements.
- std::vector<int> *mutable_elements(int i) { return &(elements_[i]); }
-
- private:
- // The enclosed vector of vector of elements.
- std::vector<std::vector<int>> elements_;
-};
-
-} // namespace chrome_lang_id
-
-#endif // WORKSPACE_H_
diff --git a/chromium/third_party/expat/fuzz/OWNERS b/chromium/third_party/expat/fuzz/OWNERS
deleted file mode 100644
index 7ab46b14cbd..00000000000
--- a/chromium/third_party/expat/fuzz/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-mmoroz@chromium.org
-ochang@chromium.org
diff --git a/chromium/third_party/expat/fuzz/expat_xml_parse_fuzzer.cc b/chromium/third_party/expat/fuzz/expat_xml_parse_fuzzer.cc
deleted file mode 100644
index b4120713633..00000000000
--- a/chromium/third_party/expat/fuzz/expat_xml_parse_fuzzer.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "third_party/expat/files/lib/expat.h"
-
-#include <vector>
-
-std::vector<const char*> kEncodings = {{"UTF-16", "UTF-8", "ISO-8859-1",
- "US-ASCII", "UTF-16BE", "UTF-16LE",
- "INVALIDENCODING"}};
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- const char* dataPtr = reinterpret_cast<const char*>(data);
-
- for (int use_ns = 0; use_ns <= 1; ++use_ns) {
- for (auto enc : kEncodings) {
- XML_Parser parser =
- use_ns ? XML_ParserCreateNS(enc, '\n') : XML_ParserCreate(enc);
- XML_Parse(parser, dataPtr, size, true);
- XML_ParserFree(parser);
- }
- }
-
- return 0;
-}
diff --git a/chromium/third_party/feed/README.chromium b/chromium/third_party/feed/README.chromium
index 42bafb91516..a8b26095e4b 100644
--- a/chromium/third_party/feed/README.chromium
+++ b/chromium/third_party/feed/README.chromium
@@ -2,7 +2,7 @@ Name: Feed
Short name: feed
URL: https://chromium.googlesource.com/feed
Version: 0
-Revision: d6031f504fcff6f34c4847f110a695fa54e90a9b
+Revision: 4cadd26bb73d8a74ec59fc6f8e7ed114d4c8e0ef
License: Apache 2.0
License File: LICENSE
Security Critical: yes
diff --git a/chromium/third_party/ffmpeg/libavformat/isom.h b/chromium/third_party/ffmpeg/libavformat/isom.h
index e6296639496..69452cae8e5 100644
--- a/chromium/third_party/ffmpeg/libavformat/isom.h
+++ b/chromium/third_party/ffmpeg/libavformat/isom.h
@@ -87,6 +87,7 @@ typedef struct MOVAtom {
struct MOVParseTableEntry;
typedef struct MOVFragment {
+ int found_tfhd;
unsigned track_id;
uint64_t base_data_offset;
uint64_t moof_offset;
diff --git a/chromium/third_party/ffmpeg/libavformat/mov.c b/chromium/third_party/ffmpeg/libavformat/mov.c
index 048f7ed1a6f..96bb58b580a 100644
--- a/chromium/third_party/ffmpeg/libavformat/mov.c
+++ b/chromium/third_party/ffmpeg/libavformat/mov.c
@@ -1370,6 +1370,9 @@ static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index,
static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
+ // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd.
+ c->fragment.found_tfhd = 0;
+
if (!c->has_looked_for_mfra && c->use_mfra_for > 0) {
c->has_looked_for_mfra = 1;
if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
@@ -2719,8 +2722,11 @@ static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int in
if (mov_stsc_index_valid(index, sc->stsc_count))
chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first;
- else
+ else {
+ // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak.
+ av_assert0(sc->stsc_data[index].first <= sc->chunk_count);
chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1);
+ }
return sc->stsc_data[index].count * (int64_t)chunk_count;
}
@@ -4198,6 +4204,13 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
c->trak_index = -1;
+ // Here stsc refers to a chunk not described in stco. This is technically invalid,
+ // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples).
+ if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) {
+ sc->stsc_count = 0;
+ av_freep(&sc->stsc_data);
+ }
+
/* sanity checks */
if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
(!sc->sample_size && !sc->sample_count))) ||
@@ -4206,7 +4219,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
st->index);
return 0;
}
- if (sc->chunk_count && sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
+ if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) {
av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n",
st->index);
return AVERROR_INVALIDDATA;
@@ -4575,6 +4588,8 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
MOVTrackExt *trex = NULL;
int flags, track_id, i;
+ c->fragment.found_tfhd = 1;
+
avio_r8(pb); /* version */
flags = avio_rb24(pb);
@@ -4710,6 +4725,11 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
AVIndexEntry *new_entries;
MOVFragmentStreamInfo * frag_stream_info;
+ if (!frag->found_tfhd) {
+ av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n");
+ return AVERROR_INVALIDDATA;
+ }
+
for (i = 0; i < c->fc->nb_streams; i++) {
if (c->fc->streams[i]->id == frag->track_id) {
st = c->fc->streams[i];
diff --git a/chromium/third_party/google_android_play_core/LICENSE b/chromium/third_party/google_android_play_core/LICENSE
deleted file mode 100644
index bee4082880f..00000000000
--- a/chromium/third_party/google_android_play_core/LICENSE
+++ /dev/null
@@ -1,147 +0,0 @@
-Terms and conditions
-
-This is the Android Software Development Kit License Agreement
-
-1. Introduction
-
-1.1 The Android Software Development Kit (referred to in the License Agreement as the "SDK" and specifically including the Android system files, packaged APIs, and Google APIs add-ons) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the SDK.
-
-1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
-
-1.3 A "compatible implementation" means any Android device that (i) complies with the Android Compatibility Definition document, which can be found at the Android compatibility website (http://source.android.com/compatibility) and which may be updated from time to time; and (ii) successfully passes the Android Compatibility Test Suite (CTS).
-
-1.4 "Google" means Google LLC, a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
-
-
-2. Accepting this License Agreement
-
-2.1 In order to use the SDK, you must first agree to the License Agreement. You may not use the SDK if you do not accept the License Agreement.
-
-2.2 By clicking to accept, you hereby agree to the terms of the License Agreement.
-
-2.3 You may not use the SDK and may not accept the License Agreement if you are a person barred from receiving the SDK under the laws of the United States or other countries, including the country in which you are resident or from which you use the SDK.
-
-2.4 If you are agreeing to be bound by the License Agreement on behalf of your employer or other entity, you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the SDK on behalf of your employer or other entity.
-
-
-3. SDK License from Google
-
-3.1 Subject to the terms of the License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the SDK solely to develop applications for compatible implementations of Android.
-
-3.2 You may not use this SDK to develop applications for other platforms (including non-compatible implementations of Android) or to develop another SDK. You are of course free to develop applications for other platforms, including non-compatible implementations of Android, provided that this SDK is not used for that purpose.
-
-3.3 You agree that Google or third parties own all legal right, title and interest in and to the SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
-
-3.4 You may not use the SDK for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the SDK or any part of the SDK.
-
-3.5 Use, reproduction and distribution of components of the SDK licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement.
-
-3.6 You agree that the form and nature of the SDK that Google provides may change without prior notice to you and that future versions of the SDK may be incompatible with applications developed on previous versions of the SDK. You agree that Google may stop (permanently or temporarily) providing the SDK (or any features within the SDK) to you or to users generally at Google's sole discretion, without prior notice to you.
-
-3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
-
-3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the SDK.
-
-
-4. Use of the SDK by You
-
-4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the SDK, including any intellectual property rights that subsist in those applications.
-
-4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) the License Agreement and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
-
-4.3 You agree that if you use the SDK to develop applications for general public users, you will protect the privacy and legal rights of those users. If the users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If the user provides your application with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, the user has given you permission to do so.
-
-4.4 You agree that you will not engage in any activity with the SDK, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of any third party including, but not limited to, Google or any mobile communications carrier.
-
-4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
-
-4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
-
-
-5. Your Developer Credentials
-
-5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
-
-
-6. Privacy and Information
-
-6.1 In order to continually innovate and improve the SDK, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the SDK are being used and how they are being used. Before any of this information is collected, the SDK will notify you and seek your consent. If you withhold consent, the information will not be collected.
-
-6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in accordance with Google's Privacy Policy.
-
-
-7. Third Party Applications
-
-7.1 If you use the SDK to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
-
-7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
-
-7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party. In that case, the License Agreement does not affect your legal relationship with these third parties.
-
-
-8. Using Android APIs
-
-8.1 Google Data APIs
-
-8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
-
-8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
-
-
-9. Terminating this License Agreement
-
-9.1 The License Agreement will continue to apply until terminated by either you or Google as set out below.
-
-9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the SDK and any relevant developer credentials.
-
-9.3 Google may at any time, terminate the License Agreement with you if:
-(A) you have breached any provision of the License Agreement; or
-(B) Google is required to do so by law; or
-(C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated its relationship with Google or ceased to offer certain parts of the SDK to you; or
-(D) Google decides to no longer provide the SDK or certain parts of the SDK to users in the country in which you are resident or from which you use the service, or the provision of the SDK or certain SDK services to you by Google is, in Google's sole discretion, no longer commercially viable.
-
-9.4 When the License Agreement comes to an end, all of the legal rights, obligations and liabilities that you and Google have benefited from, been subject to (or which have accrued over time whilst the License Agreement has been in force) or which are expressed to continue indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall continue to apply to such rights, obligations and liabilities indefinitely.
-
-
-10. DISCLAIMER OF WARRANTIES
-
-10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
-
-10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE.
-
-10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-
-
-11. LIMITATION OF LIABILITY
-
-11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
-
-
-12. Indemnification
-
-12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you with the License Agreement.
-
-
-13. Changes to the License Agreement
-
-13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK. When these changes are made, Google will make a new version of the License Agreement available on the website where the SDK is made available.
-
-
-14. General Legal Terms
-
-14.1 The License Agreement constitutes the whole legal agreement between you and Google and governs your use of the SDK (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the SDK.
-
-14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
-
-14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
-
-14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
-
-14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
-
-14.6 The rights granted in the License Agreement may not be assigned or transferred by either you or Google without the prior written approval of the other party. Neither you nor Google shall be permitted to delegate their responsibilities or obligations under the License Agreement without the prior written approval of the other party.
-
-14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
-
-
-December 9, 2016
diff --git a/chromium/third_party/google_android_play_core/OWNERS b/chromium/third_party/google_android_play_core/OWNERS
deleted file mode 100644
index b18865e9e42..00000000000
--- a/chromium/third_party/google_android_play_core/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-agrieve@chromium.org
-tiborg@chromium.org
diff --git a/chromium/third_party/google_android_play_core/README.chromium b/chromium/third_party/google_android_play_core/README.chromium
deleted file mode 100644
index e3b3bb17e00..00000000000
--- a/chromium/third_party/google_android_play_core/README.chromium
+++ /dev/null
@@ -1,14 +0,0 @@
-Name: Goole Android Play Core
-Short Name: Play Core
-URL: https://developers.google.com/android/guides/setup
-Version: 1.3.7
-License: Android Software Development Kit License
-License File: LICENSE
-Security Critical: yes
-
-Description:
-
-
-Local Modifications:
-- Unproguarded verification API.
-- Unproguarded inline update API.
diff --git a/chromium/third_party/google_android_play_core/cipd.yaml b/chromium/third_party/google_android_play_core/cipd.yaml
deleted file mode 100644
index 92671aa7808..00000000000
--- a/chromium/third_party/google_android_play_core/cipd.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# To create CIPD package run the following command.
-# cipd create --pkg-def cipd.yaml -tag version:1.3.7-cr1
-package: chromium/third_party/android_deps/libs/com_google_android_play_core_verification
-description: ""
-data:
-- file: core-1.3.7.aar \ No newline at end of file
diff --git a/chromium/third_party/google_android_play_core/com_google_android_play_core.info b/chromium/third_party/google_android_play_core/com_google_android_play_core.info
deleted file mode 100644
index a2ebd4a87ea..00000000000
--- a/chromium/third_party/google_android_play_core/com_google_android_play_core.info
+++ /dev/null
@@ -1,13 +0,0 @@
-# Generated by //build/android/gyp/aar.py
-# To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
-
-aidl = [ ]
-assets = [ ]
-has_classes_jar = true
-has_native_libraries = false
-has_proguard_flags = false
-has_r_text_file = false
-is_manifest_empty = true
-resources = [ ]
-subjar_tuples = [ ]
-subjars = [ ]
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/harfbuzz_fuzzer.cc b/chromium/third_party/harfbuzz-ng/fuzz/harfbuzz_fuzzer.cc
deleted file mode 100644
index 771c9b2cc3d..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/harfbuzz_fuzzer.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <hb.h>
-#include <hb-ot.h>
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- const char* dataPtr = reinterpret_cast<const char*>(data);
- hb_blob_t* blob = hb_blob_create(dataPtr, size, HB_MEMORY_MODE_READONLY, NULL,
- NULL);
- hb_face_t* face = hb_face_create(blob, 0);
- hb_font_t* font = hb_font_create(face);
- hb_ot_font_set_funcs(font);
- hb_font_set_scale(font, 12, 12);
-
- {
- const char text[] = "ABCDEXYZ123@_%&)*$!";
- hb_buffer_t* buffer = hb_buffer_create();
- hb_buffer_add_utf8(buffer, text, -1, 0, -1);
- hb_buffer_guess_segment_properties(buffer);
- hb_shape(font, buffer, NULL, 0);
- hb_buffer_destroy(buffer);
- }
-
- uint32_t text32[16] = { 0 };
- if (size > sizeof(text32)) {
- memcpy(text32, data + size - sizeof(text32), sizeof(text32));
- hb_buffer_t* buffer = hb_buffer_create();
- size_t text32len = sizeof(text32) / sizeof(text32[0]);
- hb_buffer_add_utf32(buffer, text32, text32len, 0, -1);
- hb_buffer_guess_segment_properties(buffer);
- hb_shape(font, buffer, NULL, 0);
- hb_buffer_destroy(buffer);
- }
-
- hb_font_destroy(font);
- hb_face_destroy(face);
- hb_blob_destroy(blob);
- return 0;
-}
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/0509e80afb379d16560e9e47bdd7d888bebdebc6.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/0509e80afb379d16560e9e47bdd7d888bebdebc6.ttf
deleted file mode 100644
index 20360311092..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/0509e80afb379d16560e9e47bdd7d888bebdebc6.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/051d92f8bc6ff724511b296c27623f824de256e9.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/051d92f8bc6ff724511b296c27623f824de256e9.ttf
deleted file mode 100644
index 419f8f3db0b..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/051d92f8bc6ff724511b296c27623f824de256e9.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/07f054357ff8638bac3711b422a1e31180bba863.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/07f054357ff8638bac3711b422a1e31180bba863.ttf
deleted file mode 100644
index fcd4f3232e9..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/07f054357ff8638bac3711b422a1e31180bba863.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/191826b9643e3f124d865d617ae609db6a2ce203.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/191826b9643e3f124d865d617ae609db6a2ce203.ttf
deleted file mode 100644
index dbc6e268117..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/191826b9643e3f124d865d617ae609db6a2ce203.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf
deleted file mode 100644
index c71e85a8422..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1a6f1687b7a221f9f2c834b0b360d3c8463b6daf.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c04a16f32a39c26c851b7fc014d2e8d298ba2b8.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c04a16f32a39c26c851b7fc014d2e8d298ba2b8.ttf
deleted file mode 100644
index 26d19ade280..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c04a16f32a39c26c851b7fc014d2e8d298ba2b8.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf
deleted file mode 100644
index 213e7cedb96..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c2c3fc37b2d4c3cb2ef726c6cdaaabd4b7f3eb9.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c2fb74c1b2aa173262734c1f616148f1648cfd6.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c2fb74c1b2aa173262734c1f616148f1648cfd6.ttf
deleted file mode 100644
index 72106585f0d..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/1c2fb74c1b2aa173262734c1f616148f1648cfd6.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/205edd09bd3d141cc9580f650109556cc28b22cb.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/205edd09bd3d141cc9580f650109556cc28b22cb.ttf
deleted file mode 100644
index 4e0ce0a48c5..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/205edd09bd3d141cc9580f650109556cc28b22cb.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/226bc2deab3846f1a682085f70c67d0421014144.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/226bc2deab3846f1a682085f70c67d0421014144.ttf
deleted file mode 100644
index 70c0c0a8393..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/226bc2deab3846f1a682085f70c67d0421014144.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/270b89df543a7e48e206a2d830c0e10e5265c630.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/270b89df543a7e48e206a2d830c0e10e5265c630.ttf
deleted file mode 100644
index fc2264917ab..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/270b89df543a7e48e206a2d830c0e10e5265c630.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttf
deleted file mode 100644
index 0d677a873c8..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/298c9e1d955f10f6f72c6915c3c6ff9bf9695cec.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/3511ff5c1647150595846ac414c595cccac34f18.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/3511ff5c1647150595846ac414c595cccac34f18.ttf
deleted file mode 100644
index 789abf7a825..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/3511ff5c1647150595846ac414c595cccac34f18.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/37033cc5cf37bb223d7355153016b6ccece93b28.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/37033cc5cf37bb223d7355153016b6ccece93b28.ttf
deleted file mode 100644
index 14defeb7b5f..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/37033cc5cf37bb223d7355153016b6ccece93b28.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/375d6ae32a3cbe52fbf81a4e5777e3377675d5a3.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/375d6ae32a3cbe52fbf81a4e5777e3377675d5a3.ttf
deleted file mode 100644
index b284c986445..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/375d6ae32a3cbe52fbf81a4e5777e3377675d5a3.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/43979b90b2dd929723cf4fe1715990bcb9c9a56b.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/43979b90b2dd929723cf4fe1715990bcb9c9a56b.ttf
deleted file mode 100644
index a5c0156c10e..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/43979b90b2dd929723cf4fe1715990bcb9c9a56b.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/43ef465752be9af900745f72fe29cb853a1401a5.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/43ef465752be9af900745f72fe29cb853a1401a5.ttf
deleted file mode 100644
index 649c156a9b0..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/43ef465752be9af900745f72fe29cb853a1401a5.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/45855bc8d46332b39c4ab9e2ee1a26b1f896da6b.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/45855bc8d46332b39c4ab9e2ee1a26b1f896da6b.ttf
deleted file mode 100644
index 6ef470c894b..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/45855bc8d46332b39c4ab9e2ee1a26b1f896da6b.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/49c9f7485c1392fa09a1b801bc2ffea79275f22e.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/49c9f7485c1392fa09a1b801bc2ffea79275f22e.ttf
deleted file mode 100644
index ea1326d2ab3..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/49c9f7485c1392fa09a1b801bc2ffea79275f22e.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf
deleted file mode 100644
index dfaead72b4e..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/4cce528e99f600ed9c25a2b69e32eb94a03b4ae8.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/5028afb650b1bb718ed2131e872fbcce57828fff.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/5028afb650b1bb718ed2131e872fbcce57828fff.ttf
deleted file mode 100644
index 8fb2f16264f..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/5028afb650b1bb718ed2131e872fbcce57828fff.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/56cfd0e18d07f41c38e9598545a6d369127fc6f9.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/56cfd0e18d07f41c38e9598545a6d369127fc6f9.ttf
deleted file mode 100644
index 4795238b890..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/56cfd0e18d07f41c38e9598545a6d369127fc6f9.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/57a9d9f83020155cbb1d2be1f43d82388cbecc88.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/57a9d9f83020155cbb1d2be1f43d82388cbecc88.ttf
deleted file mode 100644
index 746fc60389a..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/57a9d9f83020155cbb1d2be1f43d82388cbecc88.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8.ttf
deleted file mode 100644
index 9b4d23f5a68..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/5a5daf5eb5a4db77a2baa3ad9c7a6ed6e0655fa8.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/641bd9db850193064d17575053ae2bf8ec149ddc.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/641bd9db850193064d17575053ae2bf8ec149ddc.ttf
deleted file mode 100644
index 66cefd4d8c9..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/641bd9db850193064d17575053ae2bf8ec149ddc.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/6466d38c62e73a39202435a4f73bf5d6acbb73c0.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/6466d38c62e73a39202435a4f73bf5d6acbb73c0.ttf
deleted file mode 100644
index 33c4229cb1c..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/6466d38c62e73a39202435a4f73bf5d6acbb73c0.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/6ff0fbead4462d9f229167b4e6839eceb8465058.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/6ff0fbead4462d9f229167b4e6839eceb8465058.ttf
deleted file mode 100644
index 67be5258327..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/6ff0fbead4462d9f229167b4e6839eceb8465058.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttf
deleted file mode 100644
index eb5c50c664e..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/706c5d7b625f207bc0d874c67237aad6f1e9cd6f.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/757ebd573617a24aa9dfbf0b885c54875c6fe06b.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/757ebd573617a24aa9dfbf0b885c54875c6fe06b.ttf
deleted file mode 100644
index bbe22370ae6..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/757ebd573617a24aa9dfbf0b885c54875c6fe06b.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7a37dc4d5bf018456aea291cee06daf004c0221c.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7a37dc4d5bf018456aea291cee06daf004c0221c.ttf
deleted file mode 100644
index a5787a8c0d2..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7a37dc4d5bf018456aea291cee06daf004c0221c.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7e14e7883ed152baa158b80e207b66114c823a8b.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7e14e7883ed152baa158b80e207b66114c823a8b.ttf
deleted file mode 100644
index 27efd7c90ee..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7e14e7883ed152baa158b80e207b66114c823a8b.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7ef276fc886ea502a03b9b0e5c8b547d5dc2b61c.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7ef276fc886ea502a03b9b0e5c8b547d5dc2b61c.ttf
deleted file mode 100644
index fb4534abf4a..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/7ef276fc886ea502a03b9b0e5c8b547d5dc2b61c.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8099955657a54e9ee38a6ba1d6f950ce58e3cc25.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8099955657a54e9ee38a6ba1d6f950ce58e3cc25.ttf
deleted file mode 100644
index 6bb13bd58ca..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8099955657a54e9ee38a6ba1d6f950ce58e3cc25.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf
deleted file mode 100644
index b728b277ce5..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/813c2f8e5512187fd982417a7fb4286728e6f4a8.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8240789f6d12d4cfc4b5e8e6f246c3701bcf861f.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8240789f6d12d4cfc4b5e8e6f246c3701bcf861f.ttf
deleted file mode 100644
index 8eed14d94e0..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8240789f6d12d4cfc4b5e8e6f246c3701bcf861f.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8454d22037f892e76614e1645d066689a0200e61.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8454d22037f892e76614e1645d066689a0200e61.ttf
deleted file mode 100644
index 2cbb67a42c6..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8454d22037f892e76614e1645d066689a0200e61.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf
deleted file mode 100644
index 875c6998db0..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/8a9fea2a7384f2116e5b84a9b31f83be7850ce21.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a34a7b00f22ffb5fd7eef6933b81c7e71bc2cdfb.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a34a7b00f22ffb5fd7eef6933b81c7e71bc2cdfb.ttf
deleted file mode 100644
index 74fceec894a..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a34a7b00f22ffb5fd7eef6933b81c7e71bc2cdfb.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a919b33197965846f21074b24e30250d67277bce.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a919b33197965846f21074b24e30250d67277bce.ttf
deleted file mode 100644
index d2f116efa26..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a919b33197965846f21074b24e30250d67277bce.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a98e908e2ed21b22228ea59ebcc0f05034c86f2e.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a98e908e2ed21b22228ea59ebcc0f05034c86f2e.ttf
deleted file mode 100644
index 8bbddb12b67..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/a98e908e2ed21b22228ea59ebcc0f05034c86f2e.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2.ttf
deleted file mode 100644
index 500276df5bc..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/b9e2aaa0d75fcef6971ec3a96d806ba4a6b31fe2.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/bb0c53752e85c3d28973ebc913287b8987d3dfe8.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/bb0c53752e85c3d28973ebc913287b8987d3dfe8.ttf
deleted file mode 100644
index 3b7c4707431..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/bb0c53752e85c3d28973ebc913287b8987d3dfe8.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/bb9473d2403488714043bcfb946c9f78b86ad627.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/bb9473d2403488714043bcfb946c9f78b86ad627.ttf
deleted file mode 100644
index b16dae6c575..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/bb9473d2403488714043bcfb946c9f78b86ad627.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/c4e48b0886ef460f532fb49f00047ec92c432ec0.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/c4e48b0886ef460f532fb49f00047ec92c432ec0.ttf
deleted file mode 100644
index 99cda1697f5..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/c4e48b0886ef460f532fb49f00047ec92c432ec0.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/cc5f3d2d717fb6bd4dfae1c16d48a2cb8e12233b.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/cc5f3d2d717fb6bd4dfae1c16d48a2cb8e12233b.ttf
deleted file mode 100644
index a48d2a6811c..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/cc5f3d2d717fb6bd4dfae1c16d48a2cb8e12233b.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/d629e7fedc0b350222d7987345fe61613fa3929a.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/d629e7fedc0b350222d7987345fe61613fa3929a.ttf
deleted file mode 100644
index e674a78b6ef..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/d629e7fedc0b350222d7987345fe61613fa3929a.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/df768b9c257e0c9c35786c47cae15c46571d56be.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/df768b9c257e0c9c35786c47cae15c46571d56be.ttf
deleted file mode 100644
index c6d8b18e7f0..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/df768b9c257e0c9c35786c47cae15c46571d56be.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/e207635780b42f898d58654b65098763e340f5c7.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/e207635780b42f898d58654b65098763e340f5c7.ttf
deleted file mode 100644
index d91df5726b3..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/e207635780b42f898d58654b65098763e340f5c7.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf
deleted file mode 100644
index 629c470c2c4..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/ef86fe710cfea877bbe0dbb6946a1f88d0661031.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf
deleted file mode 100644
index 1dbadde4115..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f22416c692720a7d46fadf4af99f4c9e094f00b9.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f499fbc23865022234775c43503bba2e63978fe1.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f499fbc23865022234775c43503bba2e63978fe1.ttf
deleted file mode 100644
index 3c6059344ad..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f499fbc23865022234775c43503bba2e63978fe1.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f518eb6f6b5eec2946c9fbbbde44e45d46f5e2ac.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f518eb6f6b5eec2946c9fbbbde44e45d46f5e2ac.ttf
deleted file mode 100644
index 039f5e8ae53..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/f518eb6f6b5eec2946c9fbbbde44e45d46f5e2ac.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fab39d60d758cb586db5a504f218442cd1395725.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fab39d60d758cb586db5a504f218442cd1395725.ttf
deleted file mode 100644
index 451ed0477a4..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fab39d60d758cb586db5a504f218442cd1395725.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fbb6c84c9e1fe0c39e152fbe845e51fd81f6748e.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fbb6c84c9e1fe0c39e152fbe845e51fd81f6748e.ttf
deleted file mode 100644
index d49432dd824..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fbb6c84c9e1fe0c39e152fbe845e51fd81f6748e.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fcdcffbdf1c4c97c05308d7600e4c283eb47dbca.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fcdcffbdf1c4c97c05308d7600e4c283eb47dbca.ttf
deleted file mode 100644
index c4e0253cb87..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/fcdcffbdf1c4c97c05308d7600e4c283eb47dbca.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/ffa0f5d2d9025486d8469d8b1fdd983e7632499b.ttf b/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/ffa0f5d2d9025486d8469d8b1fdd983e7632499b.ttf
deleted file mode 100644
index 224dbc63b26..00000000000
--- a/chromium/third_party/harfbuzz-ng/fuzz/seed_corpus/ffa0f5d2d9025486d8469d8b1fdd983e7632499b.ttf
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/DEPS b/chromium/third_party/hunspell/fuzz/DEPS
deleted file mode 100644
index 5cd0867c848..00000000000
--- a/chromium/third_party/hunspell/fuzz/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+base",
-]
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/02a25363e79f11115132055fb880773b325f6aef b/chromium/third_party/hunspell/fuzz/bdict_corpus/02a25363e79f11115132055fb880773b325f6aef
deleted file mode 100644
index fcc9164729f..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/02a25363e79f11115132055fb880773b325f6aef
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/0883e336027e9e21911a277a9d8fa4c1b9490edd b/chromium/third_party/hunspell/fuzz/bdict_corpus/0883e336027e9e21911a277a9d8fa4c1b9490edd
deleted file mode 100644
index 85061f68ff1..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/0883e336027e9e21911a277a9d8fa4c1b9490edd
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/0c70b309d63d09ac033b8c80abff19457c93772a b/chromium/third_party/hunspell/fuzz/bdict_corpus/0c70b309d63d09ac033b8c80abff19457c93772a
deleted file mode 100644
index 3214dd01e8f..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/0c70b309d63d09ac033b8c80abff19457c93772a
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/0d78b77395c09c9db65dc76b276944154e9cf91b b/chromium/third_party/hunspell/fuzz/bdict_corpus/0d78b77395c09c9db65dc76b276944154e9cf91b
deleted file mode 100644
index 172db848692..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/0d78b77395c09c9db65dc76b276944154e9cf91b
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/0df4db3e331d781458ed7f5e5326812ba22a980f b/chromium/third_party/hunspell/fuzz/bdict_corpus/0df4db3e331d781458ed7f5e5326812ba22a980f
deleted file mode 100644
index c5407b59e26..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/0df4db3e331d781458ed7f5e5326812ba22a980f
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/142541422e926a0e54acfe3c00292d7ae269c9f5 b/chromium/third_party/hunspell/fuzz/bdict_corpus/142541422e926a0e54acfe3c00292d7ae269c9f5
deleted file mode 100644
index 4c07dbdb3d2..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/142541422e926a0e54acfe3c00292d7ae269c9f5
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/1f2216ed82922b16e3cf2194fbe320c1d0f31831 b/chromium/third_party/hunspell/fuzz/bdict_corpus/1f2216ed82922b16e3cf2194fbe320c1d0f31831
deleted file mode 100644
index 1090895275e..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/1f2216ed82922b16e3cf2194fbe320c1d0f31831
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/2051fd638bbbd568fe55066340f4827f1b60014e b/chromium/third_party/hunspell/fuzz/bdict_corpus/2051fd638bbbd568fe55066340f4827f1b60014e
deleted file mode 100644
index d0439eb9df6..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/2051fd638bbbd568fe55066340f4827f1b60014e
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/28ed3a797da3c48c309a4ef792147f3c56cfec40 b/chromium/third_party/hunspell/fuzz/bdict_corpus/28ed3a797da3c48c309a4ef792147f3c56cfec40
deleted file mode 100644
index f46d387bf94..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/28ed3a797da3c48c309a4ef792147f3c56cfec40
+++ /dev/null
@@ -1 +0,0 @@
-( \ No newline at end of file
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/29a708fe3eea419ee8fa22f66fa60e60ccae4398 b/chromium/third_party/hunspell/fuzz/bdict_corpus/29a708fe3eea419ee8fa22f66fa60e60ccae4398
deleted file mode 100644
index e4f8e6d7b21..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/29a708fe3eea419ee8fa22f66fa60e60ccae4398
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/2fb325875fb0367f26affb28f1b0fbf8ead43b48 b/chromium/third_party/hunspell/fuzz/bdict_corpus/2fb325875fb0367f26affb28f1b0fbf8ead43b48
deleted file mode 100644
index 152711b3845..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/2fb325875fb0367f26affb28f1b0fbf8ead43b48
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/3a9cb078ca19ad92faa8695bf15bb6138386a713 b/chromium/third_party/hunspell/fuzz/bdict_corpus/3a9cb078ca19ad92faa8695bf15bb6138386a713
deleted file mode 100644
index ef4216dffaa..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/3a9cb078ca19ad92faa8695bf15bb6138386a713
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/3d922153192cbf2238450647127e88ec294576ce b/chromium/third_party/hunspell/fuzz/bdict_corpus/3d922153192cbf2238450647127e88ec294576ce
deleted file mode 100644
index ea6a90f40aa..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/3d922153192cbf2238450647127e88ec294576ce
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/9bee55d2991f5c3b673c541152afa6b1d1c6521c b/chromium/third_party/hunspell/fuzz/bdict_corpus/9bee55d2991f5c3b673c541152afa6b1d1c6521c
deleted file mode 100644
index ef7cdd4422b..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/9bee55d2991f5c3b673c541152afa6b1d1c6521c
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/9deab6c08f36bbebfd65ee52fa031d8834ad886e b/chromium/third_party/hunspell/fuzz/bdict_corpus/9deab6c08f36bbebfd65ee52fa031d8834ad886e
deleted file mode 100644
index 76a24932ea0..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/9deab6c08f36bbebfd65ee52fa031d8834ad886e
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/b56dab34aac0c0f9863cd5e7a17bebab99389d9d b/chromium/third_party/hunspell/fuzz/bdict_corpus/b56dab34aac0c0f9863cd5e7a17bebab99389d9d
deleted file mode 100644
index e977087d165..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/b56dab34aac0c0f9863cd5e7a17bebab99389d9d
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/bbf0c58cdbc56d84118b2c6ccda1521497d07dea b/chromium/third_party/hunspell/fuzz/bdict_corpus/bbf0c58cdbc56d84118b2c6ccda1521497d07dea
deleted file mode 100644
index 058558c338f..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/bbf0c58cdbc56d84118b2c6ccda1521497d07dea
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/bd81796eafc329a45ea7d76ab6b85a2f27334b1e b/chromium/third_party/hunspell/fuzz/bdict_corpus/bd81796eafc329a45ea7d76ab6b85a2f27334b1e
deleted file mode 100644
index f77658011b3..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/bd81796eafc329a45ea7d76ab6b85a2f27334b1e
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/cf670ba4a6e5d9871e334f67b137cec5efe3785b b/chromium/third_party/hunspell/fuzz/bdict_corpus/cf670ba4a6e5d9871e334f67b137cec5efe3785b
deleted file mode 100644
index 2feab022d7b..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/cf670ba4a6e5d9871e334f67b137cec5efe3785b
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/e168bd974f8f0bc25219207694e3a1e9d53458c3 b/chromium/third_party/hunspell/fuzz/bdict_corpus/e168bd974f8f0bc25219207694e3a1e9d53458c3
deleted file mode 100644
index f82428389c7..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/e168bd974f8f0bc25219207694e3a1e9d53458c3
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/e8576db25f36cfc9c26570f098fd8c83cd92a68a b/chromium/third_party/hunspell/fuzz/bdict_corpus/e8576db25f36cfc9c26570f098fd8c83cd92a68a
deleted file mode 100644
index dedcac7d598..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/e8576db25f36cfc9c26570f098fd8c83cd92a68a
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/edb7834459dd9eb4b19e48ed1c9ba73d20c4c4e8 b/chromium/third_party/hunspell/fuzz/bdict_corpus/edb7834459dd9eb4b19e48ed1c9ba73d20c4c4e8
deleted file mode 100644
index e0ffb7cba7d..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/edb7834459dd9eb4b19e48ed1c9ba73d20c4c4e8
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/en-US-7-1.bdic b/chromium/third_party/hunspell/fuzz/bdict_corpus/en-US-7-1.bdic
deleted file mode 100644
index afa6ab7d6aa..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/en-US-7-1.bdic
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/en-US-8-0.bdic b/chromium/third_party/hunspell/fuzz/bdict_corpus/en-US-8-0.bdic
deleted file mode 100644
index 3ae74fdbd42..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/en-US-8-0.bdic
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/f95048cdc0fc231dd712bad106578a9eeecd869b b/chromium/third_party/hunspell/fuzz/bdict_corpus/f95048cdc0fc231dd712bad106578a9eeecd869b
deleted file mode 100644
index a35ba236968..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/f95048cdc0fc231dd712bad106578a9eeecd869b
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_corpus/fda69541054125551c41ab3e591e0482405ca2dc b/chromium/third_party/hunspell/fuzz/bdict_corpus/fda69541054125551c41ab3e591e0482405ca2dc
deleted file mode 100644
index bae0b6977a0..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_corpus/fda69541054125551c41ab3e591e0482405ca2dc
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/hunspell/fuzz/bdict_fuzzer.cc b/chromium/third_party/hunspell/fuzz/bdict_fuzzer.cc
deleted file mode 100644
index 28ee27b7f52..00000000000
--- a/chromium/third_party/hunspell/fuzz/bdict_fuzzer.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "third_party/hunspell/google/bdict.h"
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- hunspell::BDict::Verify(reinterpret_cast<const char*>(data), size);
- return 0;
-}
diff --git a/chromium/third_party/hunspell/fuzz/hunspell.dict b/chromium/third_party/hunspell/fuzz/hunspell.dict
deleted file mode 100644
index 27d57019812..00000000000
--- a/chromium/third_party/hunspell/fuzz/hunspell.dict
+++ /dev/null
@@ -1,8296 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This is a dictionary for the fuzzer, not a spellcheck dictionary.
-# It has been manually generated from:
-# third_party/hunspell/tests/suggestiontest/List_of_common_misspellings.txt
-
-"abandonned"
-"abandoned"
-"aberation"
-"aberration"
-"abilties"
-"abilities"
-"abilty"
-"ability"
-"abondon"
-"abandon"
-"abondoned"
-"abandoned"
-"abondoning"
-"abandoning"
-"abondons"
-"abandons"
-"aborigene"
-"aborigine"
-"abortificant"
-"abortifacient"
-"abreviated"
-"abbreviated"
-"abreviation"
-"abbreviation"
-"abritrary"
-"arbitrary"
-"absense"
-"absence"
-"absolutly"
-"absolutely"
-"absorbsion"
-"absorption"
-"absorbtion"
-"absorption"
-"abundacies"
-"abundances"
-"abundancies"
-"abundances"
-"abundunt"
-"abundant"
-"abutts"
-"abuts"
-"acadamy"
-"academy"
-"acadmic"
-"academic"
-"accademic"
-"academic"
-"accademy"
-"academy"
-"acccused"
-"accused"
-"accelleration"
-"acceleration"
-"accension"
-"accession,"
-"ascension"
-"acceptence"
-"acceptance"
-"acceptible"
-"acceptable"
-"accessable"
-"accessible"
-"accidentaly"
-"accidentally"
-"accidently"
-"accidentally"
-"acclimitization"
-"acclimatization"
-"acommodate"
-"accommodate"
-"accomadate"
-"accommodate"
-"accomadated"
-"accommodated"
-"accomadates"
-"accommodates"
-"accomadating"
-"accommodating"
-"accomadation"
-"accommodation"
-"accomadations"
-"accommodations"
-"accomdate"
-"accommodate"
-"accomodate"
-"accommodate"
-"accomodated"
-"accommodated"
-"accomodates"
-"accommodates"
-"accomodating"
-"accommodating"
-"accomodation"
-"accommodation"
-"accomodations"
-"accommodations"
-"accompanyed"
-"accompanied"
-"accordeon"
-"accordion"
-"accordian"
-"accordion"
-"accoring"
-"according"
-"accoustic"
-"acoustic"
-"accquainted"
-"acquainted"
-"accross"
-"across"
-"accussed"
-"accused"
-"acedemic"
-"academic"
-"acheive"
-"achieve"
-"acheived"
-"achieved"
-"acheivement"
-"achievement"
-"acheivements"
-"achievements"
-"acheives"
-"achieves"
-"acheiving"
-"achieving"
-"acheivment"
-"achievement"
-"acheivments"
-"achievements"
-"achievment"
-"achievement"
-"achievments"
-"achievements"
-"achive"
-"achieve,"
-"archive"
-"achived"
-"achieved,"
-"archived"
-"achivement"
-"achievement"
-"achivements"
-"achievements"
-"acknowldeged"
-"acknowledged"
-"acknowledgeing"
-"acknowledging"
-"ackward"
-"awkward,"
-"backward"
-"acomplish"
-"accomplish"
-"acomplished"
-"accomplished"
-"acomplishment"
-"accomplishment"
-"acomplishments"
-"accomplishments"
-"acording"
-"according"
-"acordingly"
-"accordingly"
-"acquaintence"
-"acquaintance"
-"acquaintences"
-"acquaintances"
-"acquiantence"
-"acquaintance"
-"acquiantences"
-"acquaintances"
-"acquited"
-"acquitted"
-"activites"
-"activities"
-"activly"
-"actively"
-"actualy"
-"actually"
-"acuracy"
-"accuracy"
-"acused"
-"accused"
-"acustom"
-"accustom"
-"acustommed"
-"accustomed"
-"adavanced"
-"advanced"
-"adbandon"
-"abandon"
-"additinally"
-"additionally"
-"additionaly"
-"additionally"
-"addmission"
-"admission"
-"addopt"
-"adopt"
-"addopted"
-"adopted"
-"addoptive"
-"adoptive"
-"addres"
-"address,"
-"adders"
-"addresable"
-"addressable"
-"addresed"
-"addressed"
-"addresing"
-"addressing"
-"addressess"
-"addresses"
-"addtion"
-"addition"
-"addtional"
-"additional"
-"adecuate"
-"adequate"
-"adhearing"
-"adhering"
-"adherance"
-"adherence"
-"admendment"
-"amendment"
-"admininistrative"
-"administrative"
-"adminstered"
-"administered"
-"adminstrate"
-"administrate"
-"adminstration"
-"administration"
-"adminstrative"
-"administrative"
-"adminstrator"
-"administrator"
-"admissability"
-"admissibility"
-"admissable"
-"admissible"
-"admited"
-"admitted"
-"admitedly"
-"admittedly"
-"adn"
-"and"
-"adolecent"
-"adolescent"
-"adquire"
-"acquire"
-"adquired"
-"acquired"
-"adquires"
-"acquires"
-"adquiring"
-"acquiring"
-"adres"
-"address"
-"adresable"
-"addressable"
-"adresing"
-"addressing"
-"adress"
-"address"
-"adressable"
-"addressable"
-"adressed"
-"addressed"
-"adressing"
-"addressing,"
-"dressing"
-"adventrous"
-"adventurous"
-"advertisment"
-"advertisement"
-"advertisments"
-"advertisements"
-"advesary"
-"adversary"
-"adviced"
-"advised"
-"aeriel"
-"aerial"
-"aeriels"
-"aerials"
-"afair"
-"affair"
-"afficianados"
-"aficionados"
-"afficionado"
-"aficionado"
-"afficionados"
-"aficionados"
-"affilate"
-"affiliate"
-"affilliate"
-"affiliate"
-"affort"
-"afford,"
-"effort"
-"aforememtioned"
-"aforementioned"
-"againnst"
-"against"
-"agains"
-"against"
-"agaisnt"
-"against"
-"aganist"
-"against"
-"aggaravates"
-"aggravates"
-"aggreed"
-"agreed"
-"aggreement"
-"agreement"
-"aggregious"
-"egregious"
-"aggresive"
-"aggressive"
-"agian"
-"again"
-"agianst"
-"against"
-"agin"
-"again"
-"agina"
-"again,"
-"angina"
-"aginst"
-"against"
-"agravate"
-"aggravate"
-"agre"
-"agree"
-"agred"
-"agreed"
-"agreeement"
-"agreement"
-"agreemnt"
-"agreement"
-"agregate"
-"aggregate"
-"agregates"
-"aggregates"
-"agreing"
-"agreeing"
-"agression"
-"aggression"
-"agressive"
-"aggressive"
-"agressively"
-"aggressively"
-"agressor"
-"aggressor"
-"agricuture"
-"agriculture"
-"agrieved"
-"aggrieved"
-"ahev"
-"have"
-"ahppen"
-"happen"
-"ahve"
-"have"
-"aicraft"
-"aircraft"
-"aiport"
-"airport"
-"airbourne"
-"airborne"
-"aircaft"
-"aircraft"
-"aircrafts"
-"aircraft"
-"airporta"
-"airports"
-"airrcraft"
-"aircraft"
-"aisian"
-"asian"
-"albiet"
-"albeit"
-"alchohol"
-"alcohol"
-"alchoholic"
-"alcoholic"
-"alchol"
-"alcohol"
-"alcholic"
-"alcoholic"
-"alcohal"
-"alcohol"
-"alcoholical"
-"alcoholic"
-"aledge"
-"allege"
-"aledged"
-"alleged"
-"aledges"
-"alleges"
-"alege"
-"allege"
-"aleged"
-"alleged"
-"alegience"
-"allegiance"
-"algebraical"
-"algebraic"
-"algorhitms"
-"algorithms"
-"algoritm"
-"algorithm"
-"algoritms"
-"algorithms"
-"alientating"
-"alienating"
-"alledge"
-"allege"
-"alledged"
-"alleged"
-"alledgedly"
-"allegedly"
-"alledges"
-"alleges"
-"allegedely"
-"allegedly"
-"allegedy"
-"allegedly"
-"allegely"
-"allegedly"
-"allegence"
-"allegiance"
-"allegience"
-"allegiance"
-"allign"
-"align"
-"alligned"
-"aligned"
-"alliviate"
-"alleviate"
-"allopone"
-"allophone"
-"allopones"
-"allophones"
-"allready"
-"already"
-"allthough"
-"although"
-"alltime"
-"all-time"
-"alltogether"
-"altogether"
-"almsot"
-"almost"
-"alochol"
-"alcohol"
-"alomst"
-"almost"
-"alot"
-"a"
-"lot,"
-"allot"
-"alotted"
-"allotted"
-"alowed"
-"allowed"
-"alowing"
-"allowing"
-"alreayd"
-"already"
-"alse"
-"else"
-"alsot"
-"also"
-"alternitives"
-"alternatives"
-"altho"
-"although"
-"althought"
-"although"
-"altough"
-"although"
-"alusion"
-"allusion,"
-"illusion"
-"alwasy"
-"always"
-"alwyas"
-"always"
-"amalgomated"
-"amalgamated"
-"amatuer"
-"amateur"
-"amature"
-"armature,"
-"amateur"
-"amendmant"
-"amendment"
-"amerliorate"
-"ameliorate"
-"amke"
-"make"
-"amking"
-"making"
-"ammend"
-"amend"
-"ammended"
-"amended"
-"ammendment"
-"amendment"
-"ammendments"
-"amendments"
-"ammount"
-"amount"
-"ammused"
-"amused"
-"amoung"
-"among"
-"amoungst"
-"amongst"
-"amung"
-"among"
-"analagous"
-"analogous"
-"analitic"
-"analytic"
-"analogeous"
-"analogous"
-"anarchim"
-"anarchism"
-"anarchistm"
-"anarchism"
-"anbd"
-"and"
-"ancestory"
-"ancestry"
-"ancilliary"
-"ancillary"
-"androgenous"
-"androgynous"
-"androgeny"
-"androgyny"
-"anihilation"
-"annihilation"
-"aniversary"
-"anniversary"
-"annoint"
-"anoint"
-"annointed"
-"anointed"
-"annointing"
-"anointing"
-"annoints"
-"anoints"
-"annouced"
-"announced"
-"annualy"
-"annually"
-"annuled"
-"annulled"
-"anohter"
-"another"
-"anomolies"
-"anomalies"
-"anomolous"
-"anomalous"
-"anomoly"
-"anomaly"
-"anonimity"
-"anonymity"
-"anounced"
-"announced"
-"ansalisation"
-"nasalisation"
-"ansalization"
-"nasalization"
-"ansestors"
-"ancestors"
-"antartic"
-"antarctic"
-"anthromorphization"
-"anthropomorphization"
-"anual"
-"annual,"
-"anal"
-"anulled"
-"annulled"
-"anwsered"
-"answered"
-"anyhwere"
-"anywhere"
-"anyother"
-"any"
-"other"
-"anytying"
-"anything"
-"aparent"
-"apparent"
-"aparment"
-"apartment"
-"apenines"
-"apennines,"
-"Apennines"
-"aplication"
-"application"
-"aplied"
-"applied"
-"apolegetics"
-"apologetics"
-"apon"
-"upon,"
-"apron"
-"apparant"
-"apparent"
-"apparantly"
-"apparently"
-"appart"
-"apart"
-"appartment"
-"apartment"
-"appartments"
-"apartments"
-"appealling"
-"appealing,"
-"appalling"
-"appeareance"
-"appearance"
-"appearence"
-"appearance"
-"appearences"
-"appearances"
-"appenines"
-"apennines,"
-"Apennines"
-"apperance"
-"appearance"
-"apperances"
-"appearances"
-"applicaiton"
-"application"
-"applicaitons"
-"applications"
-"appologies"
-"apologies"
-"appology"
-"apology"
-"apprearance"
-"appearance"
-"apprieciate"
-"appreciate"
-"approachs"
-"approaches"
-"appropiate"
-"appropriate"
-"appropraite"
-"appropriate"
-"appropropiate"
-"appropriate"
-"approproximate"
-"approximate"
-"approxamately"
-"approximately"
-"approxiately"
-"approximately"
-"approximitely"
-"approximately"
-"aprehensive"
-"apprehensive"
-"apropriate"
-"appropriate"
-"aproximate"
-"approximate"
-"aproximately"
-"approximately"
-"aquaintance"
-"acquaintance"
-"aquainted"
-"acquainted"
-"aquiantance"
-"acquaintance"
-"aquire"
-"acquire"
-"aquired"
-"acquired"
-"aquiring"
-"acquiring"
-"aquisition"
-"acquisition"
-"aquitted"
-"acquitted"
-"aranged"
-"arranged"
-"arangement"
-"arrangement"
-"arbitarily"
-"arbitrarily"
-"arbitary"
-"arbitrary"
-"archaelogists"
-"archaeologists"
-"archaelogy"
-"archaeology"
-"archaoelogy"
-"archeology,"
-"archaeology"
-"archaology"
-"archeology,"
-"archaeology"
-"archeaologist"
-"archeologist,"
-"archaeologist"
-"archeaologists"
-"archeologists,"
-"archaeologists"
-"archetect"
-"architect"
-"archetects"
-"architects"
-"archetectural"
-"architectural"
-"archetecturally"
-"architecturally"
-"archetecture"
-"architecture"
-"archiac"
-"archaic"
-"archictect"
-"architect"
-"archimedian"
-"archimedean"
-"architechturally"
-"architecturally"
-"architechture"
-"architecture"
-"architechtures"
-"architectures"
-"architectual"
-"architectural"
-"archtype"
-"archetype"
-"archtypes"
-"archetypes"
-"aready"
-"already"
-"areodynamics"
-"aerodynamics"
-"argubly"
-"arguably"
-"arguement"
-"argument"
-"arguements"
-"arguments"
-"arised"
-"arose"
-"arival"
-"arrival"
-"armamant"
-"armament"
-"armistace"
-"armistice"
-"aroud"
-"around"
-"arrangment"
-"arrangement"
-"arrangments"
-"arrangements"
-"arround"
-"around"
-"artical"
-"article"
-"artice"
-"article"
-"articel"
-"article"
-"artifical"
-"artificial"
-"artifically"
-"artificially"
-"artillary"
-"artillery"
-"arund"
-"around"
-"asetic"
-"ascetic"
-"asign"
-"assign"
-"aslo"
-"also"
-"asociated"
-"associated"
-"asorbed"
-"absorbed"
-"asphyxation"
-"asphyxiation"
-"assasin"
-"assassin"
-"assasinate"
-"assassinate"
-"assasinated"
-"assassinated"
-"assasinates"
-"assassinates"
-"assasination"
-"assassination"
-"assasinations"
-"assassinations"
-"assasined"
-"assassinated"
-"assasins"
-"assassins"
-"assassintation"
-"assassination"
-"assemple"
-"assemble"
-"assertation"
-"assertion"
-"asside"
-"aside"
-"assisnate"
-"assassinate"
-"assit"
-"assist"
-"assitant"
-"assistant"
-"assocation"
-"association"
-"assoicate"
-"associate"
-"assoicated"
-"associated"
-"assoicates"
-"associates"
-"assosication"
-"assassination"
-"asssassans"
-"assassins"
-"assualt"
-"assault"
-"assualted"
-"assaulted"
-"assymetric"
-"asymmetric"
-"assymetrical"
-"asymmetrical"
-"asteriod"
-"asteroid"
-"asthetic"
-"aesthetic"
-"asthetical"
-"aesthetical"
-"asthetically"
-"aesthetically"
-"asume"
-"assume"
-"aswell"
-"as"
-"well"
-"atain"
-"attain"
-"atempting"
-"attempting"
-"atheistical"
-"atheistic"
-"athenean"
-"athenian"
-"atheneans"
-"athenians"
-"athiesm"
-"atheism"
-"athiest"
-"atheist"
-"atorney"
-"attorney"
-"atribute"
-"attribute"
-"atributed"
-"attributed"
-"atributes"
-"attributes"
-"attaindre"
-"attainder,"
-"attained"
-"attemp"
-"attempt"
-"attemped"
-"attempted"
-"attemt"
-"attempt"
-"attemted"
-"attempted"
-"attemting"
-"attempting"
-"attemts"
-"attempts"
-"attendence"
-"attendance"
-"attendent"
-"attendant"
-"attendents"
-"attendants"
-"attened"
-"attended"
-"attension"
-"attention"
-"attitide"
-"attitude"
-"attributred"
-"attributed"
-"attrocities"
-"atrocities"
-"audeince"
-"audience"
-"auromated"
-"automated"
-"austrailia"
-"Australia"
-"austrailian"
-"Australian"
-"auther"
-"author"
-"authobiographic"
-"autobiographic"
-"authobiography"
-"autobiography"
-"authorative"
-"authoritative"
-"authorites"
-"authorities"
-"authorithy"
-"authority"
-"authoritiers"
-"authorities"
-"authoritive"
-"authoritative"
-"authrorities"
-"authorities"
-"autochtonous"
-"autochthonous"
-"autoctonous"
-"autochthonous"
-"automaticly"
-"automatically"
-"automibile"
-"automobile"
-"automonomous"
-"autonomous"
-"autor"
-"author"
-"autority"
-"authority"
-"auxilary"
-"auxiliary"
-"auxillaries"
-"auxiliaries"
-"auxillary"
-"auxiliary"
-"auxilliaries"
-"auxiliaries"
-"auxilliary"
-"auxiliary"
-"availablity"
-"availability"
-"availaible"
-"available"
-"availble"
-"available"
-"availiable"
-"available"
-"availible"
-"available"
-"avalable"
-"available"
-"avalance"
-"avalanche"
-"avaliable"
-"available"
-"avation"
-"aviation"
-"avengence"
-"a"
-"vengeance"
-"averageed"
-"averaged"
-"avilable"
-"available"
-"awared"
-"awarded"
-"awya"
-"away"
-"baceause"
-"because"
-"backgorund"
-"background"
-"backrounds"
-"backgrounds"
-"bakc"
-"back"
-"banannas"
-"bananas"
-"bandwith"
-"bandwidth"
-"bankrupcy"
-"bankruptcy"
-"banruptcy"
-"bankruptcy"
-"baout"
-"about,"
-"bout"
-"basicaly"
-"basically"
-"basicly"
-"basically"
-"bcak"
-"back"
-"beachead"
-"beachhead"
-"beacuse"
-"because"
-"beastiality"
-"bestiality"
-"beatiful"
-"beautiful"
-"beaurocracy"
-"bureaucracy"
-"beaurocratic"
-"bureaucratic"
-"beautyfull"
-"beautiful"
-"becamae"
-"became"
-"becasue"
-"because"
-"beccause"
-"because"
-"becomeing"
-"becoming"
-"becomming"
-"becoming"
-"becouse"
-"because"
-"becuase"
-"because"
-"bedore"
-"before"
-"befoer"
-"before"
-"beggin"
-"begin,"
-"begging"
-"begginer"
-"beginner"
-"begginers"
-"beginners"
-"beggining"
-"beginning"
-"begginings"
-"beginnings"
-"beggins"
-"begins"
-"begining"
-"beginning"
-"beginnig"
-"beginning"
-"behavour"
-"behavior,"
-"behaviour"
-"beleagured"
-"beleaguered"
-"beleif"
-"belief"
-"beleive"
-"believe"
-"beleived"
-"believed"
-"beleives"
-"believes"
-"beleiving"
-"believing"
-"beligum"
-"belgium"
-"belive"
-"believe"
-"belived"
-"believed"
-"belives"
-"believes,"
-"beliefs"
-"belligerant"
-"belligerent"
-"bellweather"
-"bellwether"
-"bemusemnt"
-"bemusement"
-"beneficary"
-"beneficiary"
-"beng"
-"being"
-"benificial"
-"beneficial"
-"benifit"
-"benefit"
-"benifits"
-"benefits"
-"bergamont"
-"bergamot"
-"Bernouilli"
-"Bernoulli"
-"beseige"
-"besiege"
-"beseiged"
-"besieged"
-"beseiging"
-"besieging"
-"betwen"
-"between"
-"beween"
-"between"
-"bewteen"
-"between"
-"bilateraly"
-"bilaterally"
-"billingualism"
-"bilingualism"
-"binominal"
-"binomial"
-"bizzare"
-"bizarre"
-"blaim"
-"blame"
-"blaimed"
-"blamed"
-"blessure"
-"blessing"
-"Blitzkreig"
-"Blitzkrieg"
-"boaut"
-"bout,"
-"boat,"
-"about"
-"bodydbuilder"
-"bodybuilder"
-"bombardement"
-"bombardment"
-"bombarment"
-"bombardment"
-"bondary"
-"boundary"
-"Bonnano"
-"Bonanno"
-"borke"
-"broke"
-"boundry"
-"boundary"
-"bouyancy"
-"buoyancy"
-"bouyant"
-"buoyant"
-"boyant"
-"buoyant"
-"Brasillian"
-"Brazilian"
-"breakthough"
-"breakthrough"
-"breakthroughts"
-"breakthroughs"
-"breif"
-"brief"
-"breifly"
-"briefly"
-"brethen"
-"brethren"
-"bretheren"
-"brethren"
-"briliant"
-"brilliant"
-"brillant"
-"brilliant"
-"brimestone"
-"brimstone"
-"Britian"
-"Britain"
-"Brittish"
-"British"
-"broacasted"
-"broadcast"
-"broadacasting"
-"broadcasting"
-"broady"
-"broadly"
-"Buddah"
-"Buddha"
-"buisness"
-"business"
-"buisnessman"
-"businessman"
-"buoancy"
-"buoyancy"
-"buring"
-"burying,"
-"burning,"
-"burin,"
-"during"
-"burried"
-"buried"
-"busineses"
-"business,"
-"businesses"
-"busness"
-"business"
-"bussiness"
-"business"
-"cacuses"
-"caucuses"
-"cahracters"
-"characters"
-"calaber"
-"caliber"
-"calander"
-"calendar,"
-"calender,"
-"colander"
-"calculs"
-"calculus"
-"calenders"
-"calendars"
-"caligraphy"
-"calligraphy"
-"caluclate"
-"calculate"
-"caluclated"
-"calculated"
-"caluculate"
-"calculate"
-"caluculated"
-"calculated"
-"calulate"
-"calculate"
-"calulated"
-"calculated"
-"Cambrige"
-"Cambridge"
-"camoflage"
-"camouflage"
-"campain"
-"campaign"
-"campains"
-"campaigns"
-"candadate"
-"candidate"
-"candiate"
-"candidate"
-"candidiate"
-"candidate"
-"cannister"
-"canister"
-"cannisters"
-"canisters"
-"cannnot"
-"cannot"
-"cannonical"
-"canonical"
-"cannotation"
-"connotation"
-"cannotations"
-"connotations"
-"cant"
-"cannot,"
-"can"
-"not,"
-"can't"
-"caost"
-"coast"
-"caperbility"
-"capability"
-"Capetown"
-"Cape"
-"Town"
-"capible"
-"capable"
-"captial"
-"capital"
-"captued"
-"captured"
-"capturd"
-"captured"
-"carachter"
-"character"
-"caracterized"
-"characterized"
-"carcas"
-"carcass,"
-"Caracas"
-"carefull"
-"careful"
-"careing"
-"caring"
-"carismatic"
-"charismatic"
-"Carmalite"
-"Carmelite"
-"carmel"
-"caramel,"
-"carmel-by-the-sea"
-"carniverous"
-"carnivorous"
-"carreer"
-"career"
-"carrers"
-"careers"
-"Carribbean"
-"Caribbean"
-"Carribean"
-"Caribbean"
-"cartdridge"
-"cartridge"
-"Carthagian"
-"Carthaginian"
-"carthographer"
-"cartographer"
-"cartilege"
-"cartilage"
-"cartilidge"
-"cartilage"
-"cartrige"
-"cartridge"
-"casette"
-"cassette"
-"casion"
-"caisson"
-"cassawory"
-"cassowary"
-"cassowarry"
-"cassowary"
-"casulaties"
-"casualties"
-"casulaty"
-"casualty"
-"catagories"
-"categories"
-"catagorized"
-"categorized"
-"catagory"
-"category"
-"catergorize"
-"categorize"
-"catergorized"
-"categorized"
-"Cataline"
-"Catiline,"
-"Catalina"
-"cathlic"
-"catholic"
-"catholocism"
-"catholicism"
-"catterpilar"
-"caterpillar"
-"catterpilars"
-"caterpillars"
-"cattleship"
-"battleship"
-"causalities"
-"casualties"
-"Ceasar"
-"Caesar"
-"Celcius"
-"Celsius"
-"cellpading"
-"cellpadding"
-"cementary"
-"cemetery"
-"cemetarey"
-"cemetery"
-"cemetaries"
-"cemeteries"
-"cemetary"
-"cemetery"
-"cencus"
-"census"
-"censur"
-"censor,"
-"censure"
-"cententenial"
-"centennial"
-"centruies"
-"centuries"
-"centruy"
-"century"
-"ceratin"
-"certain,"
-"keratin"
-"cerimonial"
-"ceremonial"
-"cerimonies"
-"ceremonies"
-"cerimonious"
-"ceremonious"
-"cerimony"
-"ceremony"
-"ceromony"
-"ceremony"
-"certainity"
-"certainty"
-"certian"
-"certain"
-"cervial"
-"cervical,"
-"servile,"
-"serval"
-"chalenging"
-"challenging"
-"challange"
-"challenge"
-"challanged"
-"challenged"
-"challege"
-"challenge"
-"Champange"
-"Champagne"
-"changable"
-"changeable"
-"charachter"
-"character"
-"charactor"
-"character"
-"charachters"
-"characters"
-"charactersistic"
-"characteristic"
-"charactors"
-"characters"
-"charasmatic"
-"charismatic"
-"charaterized"
-"characterized"
-"chariman"
-"chairman"
-"charistics"
-"characteristics"
-"chasr"
-"chaser,"
-"chase"
-"cheif"
-"chief"
-"chemcial"
-"chemical"
-"chemcially"
-"chemically"
-"chemestry"
-"chemistry"
-"chemicaly"
-"chemically"
-"childbird"
-"childbirth"
-"childen"
-"children"
-"choosen"
-"chosen"
-"chracter"
-"character"
-"chuch"
-"church"
-"churchs"
-"churches"
-"Cincinatti"
-"Cincinnati"
-"Cincinnatti"
-"Cincinnati"
-"circulaton"
-"circulation"
-"circumsicion"
-"circumcision"
-"circut"
-"circuit"
-"ciricuit"
-"circuit"
-"ciriculum"
-"curriculum"
-"civillian"
-"civilian"
-"claer"
-"clear"
-"claerer"
-"clearer"
-"claerly"
-"clearly"
-"claimes"
-"claims"
-"clas"
-"class"
-"clasic"
-"classic"
-"clasical"
-"classical"
-"clasically"
-"classically"
-"cleareance"
-"clearance"
-"clera"
-"clear,"
-"sclera"
-"clincial"
-"clinical"
-"clinicaly"
-"clinically"
-"cmo"
-"com"
-"cmoputer"
-"computer"
-"co-incided"
-"coincided"
-"coctail"
-"cocktail"
-"coform"
-"conform"
-"cognizent"
-"cognizant"
-"coincedentally"
-"coincidentally"
-"colaborations"
-"collaborations"
-"colateral"
-"collateral"
-"colelctive"
-"collective"
-"collaberative"
-"collaborative"
-"collecton"
-"collection"
-"collegue"
-"colleague"
-"collegues"
-"colleagues"
-"collonade"
-"colonnade"
-"collonies"
-"colonies"
-"collony"
-"colony"
-"collosal"
-"colossal"
-"colonizators"
-"colonizers"
-"comander"
-"commander,"
-"commandeer"
-"comando"
-"commando"
-"comandos"
-"commandos"
-"comany"
-"company"
-"comapany"
-"company"
-"comback"
-"comeback"
-"combanations"
-"combinations"
-"combinatins"
-"combinations"
-"combusion"
-"combustion"
-"comdemnation"
-"condemnation"
-"comemmorates"
-"commemorates"
-"comemoretion"
-"commemoration"
-"comision"
-"commission"
-"comisioned"
-"commissioned"
-"comisioner"
-"commissioner"
-"comisioning"
-"commissioning"
-"comisions"
-"commissions"
-"comission"
-"commission"
-"comissioned"
-"commissioned"
-"comissioner"
-"commissioner"
-"comissioning"
-"commissioning"
-"comissions"
-"commissions"
-"comited"
-"committed"
-"comiting"
-"committing"
-"comitted"
-"committed"
-"comittee"
-"committee"
-"comitting"
-"committing"
-"commandoes"
-"commandos"
-"commedic"
-"comedic"
-"commemerative"
-"commemorative"
-"commemmorate"
-"commemorate"
-"commemmorating"
-"commemorating"
-"commerical"
-"commercial"
-"commerically"
-"commercially"
-"commericial"
-"commercial"
-"commericially"
-"commercially"
-"commerorative"
-"commemorative"
-"comming"
-"coming"
-"comminication"
-"communication"
-"commision"
-"commission"
-"commisioned"
-"commissioned"
-"commisioner"
-"commissioner"
-"commisioning"
-"commissioning"
-"commisions"
-"commissions"
-"commited"
-"committed"
-"commitee"
-"committee"
-"commiting"
-"committing"
-"committe"
-"committee"
-"committment"
-"commitment"
-"committments"
-"commitments"
-"commmemorated"
-"commemorated"
-"commongly"
-"commonly"
-"commonweath"
-"commonwealth"
-"commuications"
-"communications"
-"commuinications"
-"communications"
-"communciation"
-"communication"
-"communiation"
-"communication"
-"communites"
-"communities"
-"compability"
-"compatibility"
-"comparision"
-"comparison"
-"comparisions"
-"comparisons"
-"comparitive"
-"comparative"
-"comparitively"
-"comparatively"
-"compatabilities"
-"compatibilities"
-"compatability"
-"compatibility"
-"compatable"
-"compatible"
-"compatablities"
-"compatibilities"
-"compatablity"
-"compatibility"
-"compatiable"
-"compatible"
-"compatiblities"
-"compatibilities"
-"compatiblity"
-"compatibility"
-"compeitions"
-"competitions"
-"compensantion"
-"compensation"
-"competance"
-"competence"
-"competant"
-"competent"
-"competative"
-"competitive"
-"competion"
-"competition,"
-"completion"
-"competitiion"
-"competition"
-"competive"
-"competitive"
-"competiveness"
-"competitiveness"
-"comphrehensive"
-"comprehensive"
-"compitent"
-"competent"
-"completedthe"
-"completed"
-"the"
-"completelyl"
-"completely"
-"completetion"
-"completion"
-"complier"
-"compiler"
-"componant"
-"component"
-"comprable"
-"comparable"
-"comprimise"
-"compromise"
-"compulsary"
-"compulsory"
-"compulsery"
-"compulsory"
-"computarized"
-"computerized"
-"concensus"
-"consensus"
-"concider"
-"consider"
-"concidered"
-"considered"
-"concidering"
-"considering"
-"conciders"
-"considers"
-"concieted"
-"conceited"
-"concieved"
-"conceived"
-"concious"
-"conscious"
-"conciously"
-"consciously"
-"conciousness"
-"consciousness"
-"condamned"
-"condemned"
-"condemmed"
-"condemned"
-"condidtion"
-"condition"
-"condidtions"
-"conditions"
-"conditionsof"
-"conditions"
-"of"
-"conected"
-"connected"
-"conection"
-"connection"
-"conesencus"
-"consensus"
-"confidental"
-"confidential"
-"confidentally"
-"confidentially"
-"confids"
-"confides"
-"configureable"
-"configurable"
-"confortable"
-"comfortable"
-"congradulations"
-"congratulations"
-"congresional"
-"congressional"
-"conived"
-"connived"
-"conjecutre"
-"conjecture"
-"conjuction"
-"conjunction"
-"Conneticut"
-"Connecticut"
-"conotations"
-"connotations"
-"conquerd"
-"conquered"
-"conquerer"
-"conqueror"
-"conquerers"
-"conquerors"
-"conqured"
-"conquered"
-"conscent"
-"consent"
-"consciouness"
-"consciousness"
-"consdider"
-"consider"
-"consdidered"
-"considered"
-"consdiered"
-"considered"
-"consectutive"
-"consecutive"
-"consenquently"
-"consequently"
-"consentrate"
-"concentrate"
-"consentrated"
-"concentrated"
-"consentrates"
-"concentrates"
-"consept"
-"concept"
-"consequentually"
-"consequently"
-"consequeseces"
-"consequences"
-"consern"
-"concern"
-"conserned"
-"concerned"
-"conserning"
-"concerning"
-"conservitive"
-"conservative"
-"consiciousness"
-"consciousness"
-"consicousness"
-"consciousness"
-"considerd"
-"considered"
-"consideres"
-"considered"
-"consious"
-"conscious"
-"consistant"
-"consistent"
-"consistantly"
-"consistently"
-"consituencies"
-"constituencies"
-"consituency"
-"constituency"
-"consituted"
-"constituted"
-"consitution"
-"constitution"
-"consitutional"
-"constitutional"
-"consolodate"
-"consolidate"
-"consolodated"
-"consolidated"
-"consonent"
-"consonant"
-"consonents"
-"consonants"
-"consorcium"
-"consortium"
-"conspiracys"
-"conspiracies"
-"conspiriator"
-"conspirator"
-"constaints"
-"constraints"
-"constanly"
-"constantly"
-"constarnation"
-"consternation"
-"constatn"
-"constant"
-"constinually"
-"continually"
-"constituant"
-"constituent"
-"constituants"
-"constituents"
-"constituion"
-"constitution"
-"constituional"
-"constitutional"
-"consttruction"
-"construction"
-"constuction"
-"construction"
-"consulant"
-"consultant"
-"consumate"
-"consummate"
-"consumated"
-"consummated"
-"contaiminate"
-"contaminate"
-"containes"
-"contains"
-"contamporaries"
-"contemporaries"
-"contamporary"
-"contemporary"
-"contempoary"
-"contemporary"
-"contemporaneus"
-"contemporaneous"
-"contempory"
-"contemporary"
-"contendor"
-"contender"
-"contined"
-"continued"
-"continous"
-"continuous"
-"continously"
-"continuously"
-"continueing"
-"continuing"
-"contravercial"
-"controversial"
-"contraversy"
-"controversy"
-"contributer"
-"contributor"
-"contributers"
-"contributors"
-"contritutions"
-"contributions"
-"controled"
-"controlled"
-"controling"
-"controlling"
-"controll"
-"control"
-"controlls"
-"controls"
-"controvercial"
-"controversial"
-"controvercy"
-"controversy"
-"controveries"
-"controversies"
-"controversal"
-"controversial"
-"controversey"
-"controversy"
-"controvertial"
-"controversial"
-"controvery"
-"controversy"
-"contruction"
-"construction"
-"conveinent"
-"convenient"
-"convenant"
-"covenant"
-"convential"
-"conventional"
-"convertables"
-"convertibles"
-"convertion"
-"conversion"
-"conveyer"
-"conveyor"
-"conviced"
-"convinced"
-"convienient"
-"convenient"
-"coordiantion"
-"coordination"
-"coorperation"
-"cooperation,"
-"corporation"
-"coorperations"
-"corporations"
-"copmetitors"
-"competitors"
-"coputer"
-"computer"
-"copywrite"
-"copyright"
-"coridal"
-"cordial"
-"cornmitted"
-"committed"
-"corosion"
-"corrosion"
-"corparate"
-"corporate"
-"corperations"
-"corporations"
-"correcters"
-"correctors"
-"correponding"
-"corresponding"
-"correposding"
-"corresponding"
-"correspondant"
-"correspondent"
-"correspondants"
-"correspondents"
-"corridoors"
-"corridors"
-"corrispond"
-"correspond"
-"corrispondant"
-"correspondent"
-"corrispondants"
-"correspondents"
-"corrisponded"
-"corresponded"
-"corrisponding"
-"corresponding"
-"corrisponds"
-"corresponds"
-"costitution"
-"constitution"
-"coucil"
-"council"
-"coudl"
-"could,"
-"cloud"
-"councellor"
-"councillor,"
-"counselor,"
-"councilor"
-"councellors"
-"councillors,"
-"counselors,"
-"councilors"
-"counries"
-"countries"
-"countains"
-"contains"
-"countires"
-"countries"
-"coururier"
-"courier,"
-"couturier"
-"coverted"
-"converted,"
-"covered,"
-"coveted"
-"cpoy"
-"coy,"
-"copy"
-"creaeted"
-"created"
-"creedence"
-"credence"
-"critereon"
-"criterion"
-"criterias"
-"criteria"
-"criticists"
-"critics"
-"critising"
-"criticising,"
-"criticizing"
-"critisising"
-"criticising"
-"critisism"
-"criticism"
-"critisisms"
-"criticisms"
-"critisize"
-"criticise,"
-"criticize"
-"critisized"
-"criticised,"
-"criticized"
-"critisizes"
-"criticises,"
-"criticizes"
-"critisizing"
-"criticising,"
-"criticizing"
-"critized"
-"criticized"
-"critizing"
-"criticizing"
-"crockodiles"
-"crocodiles"
-"crowm"
-"crown"
-"crtical"
-"critical"
-"crticised"
-"criticised"
-"crucifiction"
-"crucifixion"
-"crusies"
-"cruises"
-"crystalisation"
-"crystallisation"
-"culiminating"
-"culminating"
-"cumulatative"
-"cumulative"
-"curch"
-"church"
-"curcuit"
-"circuit"
-"currenly"
-"currently"
-"curriculem"
-"curriculum"
-"cxan"
-"cyan"
-"cyclinder"
-"cylinder"
-"dael"
-"deal,"
-"dial,"
-"dahl"
-"dalmation"
-"dalmatian"
-"damenor"
-"demeanor"
-"Dardenelles"
-"Dardanelles"
-"dacquiri"
-"daiquiri"
-"debateable"
-"debatable"
-"decendant"
-"descendant"
-"decendants"
-"descendants"
-"decendent"
-"descendant"
-"decendents"
-"descendants"
-"decideable"
-"decidable"
-"decidely"
-"decidedly"
-"decieved"
-"deceived"
-"decison"
-"decision"
-"decomissioned"
-"decommissioned"
-"decomposit"
-"decompose"
-"decomposited"
-"decomposed"
-"decompositing"
-"decomposing"
-"decomposits"
-"decomposes"
-"decress"
-"decrees"
-"decribe"
-"describe"
-"decribed"
-"described"
-"decribes"
-"describes"
-"decribing"
-"describing"
-"dectect"
-"detect"
-"defendent"
-"defendant"
-"defendents"
-"defendants"
-"deffensively"
-"defensively"
-"deffine"
-"define"
-"deffined"
-"defined"
-"definance"
-"defiance"
-"definate"
-"definite"
-"definately"
-"definitely"
-"definatly"
-"definitely"
-"definetly"
-"definitely"
-"definining"
-"defining"
-"definit"
-"definite"
-"definitly"
-"definitely"
-"definiton"
-"definition"
-"defintion"
-"definition"
-"degrate"
-"degrade"
-"delagates"
-"delegates"
-"delapidated"
-"dilapidated"
-"delerious"
-"delirious"
-"delevopment"
-"development"
-"deliberatly"
-"deliberately"
-"delusionally"
-"delusively"
-"demenor"
-"demeanor"
-"demographical"
-"demographic"
-"demolision"
-"demolition"
-"demorcracy"
-"democracy"
-"demostration"
-"demonstration"
-"denegrating"
-"denigrating"
-"densly"
-"densely"
-"deparment"
-"department"
-"deparments"
-"departments"
-"deparmental"
-"departmental"
-"dependance"
-"dependence"
-"dependancy"
-"dependency"
-"dependant"
-"dependent"
-"deram"
-"dram,"
-"dream"
-"deriviated"
-"derived"
-"derivitive"
-"derivative"
-"derogitory"
-"derogatory"
-"descendands"
-"descendants"
-"descibed"
-"described"
-"descision"
-"decision"
-"descisions"
-"decisions"
-"descriibes"
-"describes"
-"descripters"
-"descriptors"
-"descripton"
-"description"
-"desctruction"
-"destruction"
-"descuss"
-"discuss"
-"desgined"
-"designed"
-"deside"
-"decide"
-"desigining"
-"designing"
-"desinations"
-"destinations"
-"desintegrated"
-"disintegrated"
-"desintegration"
-"disintegration"
-"desireable"
-"desirable"
-"desitned"
-"destined"
-"desktiop"
-"desktop"
-"desorder"
-"disorder"
-"desoriented"
-"disoriented"
-"desparate"
-"desperate,"
-"disparate"
-"despatched"
-"dispatched"
-"despict"
-"depict"
-"despiration"
-"desperation"
-"dessicated"
-"desiccated"
-"dessigned"
-"designed"
-"destablized"
-"destabilized"
-"destory"
-"destroy"
-"detailled"
-"detailed"
-"detatched"
-"detached"
-"deteoriated"
-"deteriorated"
-"deteriate"
-"deteriorate"
-"deterioriating"
-"deteriorating"
-"determinining"
-"determining"
-"detremental"
-"detrimental"
-"devasted"
-"devastated"
-"develope"
-"develop"
-"developement"
-"development"
-"developped"
-"developed"
-"develpment"
-"development"
-"devels"
-"delves"
-"devestated"
-"devastated"
-"devestating"
-"devastating"
-"devide"
-"divide"
-"devided"
-"divided"
-"devistating"
-"devastating"
-"devolopement"
-"development"
-"diablical"
-"diabolical"
-"diamons"
-"diamonds"
-"diaster"
-"disaster"
-"dichtomy"
-"dichotomy"
-"diconnects"
-"disconnects"
-"dicover"
-"discover"
-"dicovered"
-"discovered"
-"dicovering"
-"discovering"
-"dicovers"
-"discovers"
-"dicovery"
-"discovery"
-"dicussed"
-"discussed"
-"didnt"
-"didn't"
-"diea"
-"idea,"
-"die"
-"dieing"
-"dying,"
-"dyeing"
-"dieties"
-"deities"
-"diety"
-"deity"
-"diferent"
-"different"
-"diferrent"
-"different"
-"differentiatiations"
-"differentiations"
-"differnt"
-"different"
-"difficulity"
-"difficulty"
-"diffrent"
-"different"
-"dificulties"
-"difficulties"
-"dificulty"
-"difficulty"
-"dimenions"
-"dimensions"
-"dimention"
-"dimension"
-"dimentional"
-"dimensional"
-"dimentions"
-"dimensions"
-"dimesnional"
-"dimensional"
-"diminuitive"
-"diminutive"
-"diosese"
-"diocese"
-"diphtong"
-"diphthong"
-"diphtongs"
-"diphthongs"
-"diplomancy"
-"diplomacy"
-"dipthong"
-"diphthong"
-"dipthongs"
-"diphthongs"
-"dirived"
-"derived"
-"disagreeed"
-"disagreed"
-"disapeared"
-"disappeared"
-"disapointing"
-"disappointing"
-"disappearred"
-"disappeared"
-"disaproval"
-"disapproval"
-"disasterous"
-"disastrous"
-"disatisfaction"
-"dissatisfaction"
-"disatisfied"
-"dissatisfied"
-"disatrous"
-"disastrous"
-"discontentment"
-"discontent"
-"discribe"
-"describe"
-"discribed"
-"described"
-"discribes"
-"describes"
-"discribing"
-"describing"
-"disctinction"
-"distinction"
-"disctinctive"
-"distinctive"
-"disemination"
-"dissemination"
-"disenchanged"
-"disenchanted"
-"disiplined"
-"disciplined"
-"disobediance"
-"disobedience"
-"disobediant"
-"disobedient"
-"disolved"
-"dissolved"
-"disover"
-"discover"
-"dispair"
-"despair"
-"disparingly"
-"disparagingly"
-"dispence"
-"dispense"
-"dispenced"
-"dispensed"
-"dispencing"
-"dispensing"
-"dispicable"
-"despicable"
-"dispite"
-"despite"
-"dispostion"
-"disposition"
-"disproportiate"
-"disproportionate"
-"disputandem"
-"disputandum"
-"disricts"
-"districts"
-"dissagreement"
-"disagreement"
-"dissapear"
-"disappear"
-"dissapearance"
-"disappearance"
-"dissapeared"
-"disappeared"
-"dissapearing"
-"disappearing"
-"dissapears"
-"disappears"
-"dissappear"
-"disappear"
-"dissappears"
-"disappears"
-"dissappointed"
-"disappointed"
-"dissarray"
-"disarray"
-"dissobediance"
-"disobedience"
-"dissobediant"
-"disobedient"
-"dissobedience"
-"disobedience"
-"dissobedient"
-"disobedient"
-"distiction"
-"distinction"
-"distingish"
-"distinguish"
-"distingished"
-"distinguished"
-"distingishes"
-"distinguishes"
-"distingishing"
-"distinguishing"
-"distingquished"
-"distinguished"
-"distrubution"
-"distribution"
-"distruction"
-"destruction"
-"distructive"
-"destructive"
-"ditributed"
-"distributed"
-"diversed"
-"diverse,"
-"diverged"
-"divice"
-"device"
-"divison"
-"division"
-"divisons"
-"divisions"
-"doccument"
-"document"
-"doccumented"
-"documented"
-"doccuments"
-"documents"
-"docrines"
-"doctrines"
-"doctines"
-"doctrines"
-"documenatry"
-"documentary"
-"doens"
-"does"
-"doesnt"
-"doesn't"
-"doign"
-"doing"
-"dominaton"
-"domination"
-"dominent"
-"dominant"
-"dominiant"
-"dominant"
-"donig"
-"doing"
-"dosen't"
-"doesn't"
-"doub"
-"doubt,"
-"daub"
-"doulbe"
-"double"
-"dowloads"
-"downloads"
-"dramtic"
-"dramatic"
-"draughtman"
-"draughtsman"
-"Dravadian"
-"Dravidian"
-"dreasm"
-"dreams"
-"driectly"
-"directly"
-"drnik"
-"drink"
-"druming"
-"drumming"
-"drummless"
-"drumless"
-"dupicate"
-"duplicate"
-"durig"
-"during"
-"durring"
-"during"
-"duting"
-"during"
-"dyas"
-"dryas"
-"eahc"
-"each"
-"ealier"
-"earlier"
-"earlies"
-"earliest"
-"earnt"
-"earned"
-"ecclectic"
-"eclectic"
-"eceonomy"
-"economy"
-"ecidious"
-"deciduous"
-"eclispe"
-"eclipse"
-"ecomonic"
-"economic"
-"ect"
-"etc"
-"eearly"
-"early"
-"efel"
-"evil"
-"effeciency"
-"efficiency"
-"effecient"
-"efficient"
-"effeciently"
-"efficiently"
-"efficency"
-"efficiency"
-"efficent"
-"efficient"
-"efficently"
-"efficiently"
-"efford"
-"effort,"
-"afford"
-"effords"
-"efforts,"
-"affords"
-"effulence"
-"effluence"
-"eigth"
-"eighth,"
-"eight"
-"eiter"
-"either"
-"elction"
-"election"
-"electic"
-"eclectic,"
-"electric"
-"electon"
-"election,"
-"electron"
-"electrial"
-"electrical"
-"electricly"
-"electrically"
-"electricty"
-"electricity"
-"elementay"
-"elementary"
-"eleminated"
-"eliminated"
-"eleminating"
-"eliminating"
-"eles"
-"eels"
-"eletricity"
-"electricity"
-"elicided"
-"elicited"
-"eligable"
-"eligible"
-"elimentary"
-"elementary"
-"ellected"
-"elected"
-"elphant"
-"elephant"
-"embarass"
-"embarrass"
-"embarassed"
-"embarrassed"
-"embarassing"
-"embarrassing"
-"embarassment"
-"embarrassment"
-"embargos"
-"embargoes"
-"embarras"
-"embarrass"
-"embarrased"
-"embarrassed"
-"embarrasing"
-"embarrassing"
-"embarrasment"
-"embarrassment"
-"embezelled"
-"embezzled"
-"emblamatic"
-"emblematic"
-"eminate"
-"emanate"
-"eminated"
-"emanated"
-"emision"
-"emission"
-"emited"
-"emitted"
-"emiting"
-"emitting"
-"emition"
-"emission,"
-"emotion"
-"emmediately"
-"immediately"
-"emmigrated"
-"emigrated"
-"emminent"
-"eminent,"
-"imminent"
-"emminently"
-"eminently"
-"emmisaries"
-"emissaries"
-"emmisarries"
-"emissaries"
-"emmisarry"
-"emissary"
-"emmisary"
-"emissary"
-"emmision"
-"emission"
-"emmisions"
-"emissions"
-"emmited"
-"emitted"
-"emmiting"
-"emitting"
-"emmitted"
-"emitted"
-"emmitting"
-"emitting"
-"emnity"
-"enmity"
-"emperical"
-"empirical"
-"emphaised"
-"emphasised"
-"emphsis"
-"emphasis"
-"emphysyma"
-"emphysema"
-"empirial"
-"empirical,"
-"imperial"
-"emprisoned"
-"imprisoned"
-"enameld"
-"enameled"
-"enchancement"
-"enhancement"
-"encouraing"
-"encouraging"
-"encryptiion"
-"encryption"
-"encylopedia"
-"encyclopedia"
-"endevors"
-"endeavors"
-"endevour"
-"endeavour"
-"endig"
-"ending"
-"endolithes"
-"endoliths"
-"enduce"
-"induce"
-"ened"
-"need"
-"enflamed"
-"inflamed"
-"enforceing"
-"enforcing"
-"engagment"
-"engagement"
-"engeneer"
-"engineer"
-"engeneering"
-"engineering"
-"engieneer"
-"engineer"
-"engieneers"
-"engineers"
-"enlargment"
-"enlargement"
-"enlargments"
-"enlargements"
-"Enlish"
-"English,"
-"enlist"
-"enourmous"
-"enormous"
-"enourmously"
-"enormously"
-"ensconsed"
-"ensconced"
-"entaglements"
-"entanglements"
-"enteratinment"
-"entertainment"
-"entitity"
-"entity"
-"entitlied"
-"entitled"
-"entrepeneur"
-"entrepreneur"
-"entrepeneurs"
-"entrepreneurs"
-"enviorment"
-"environment"
-"enviormental"
-"environmental"
-"enviormentally"
-"environmentally"
-"enviorments"
-"environments"
-"enviornment"
-"environment"
-"enviornmental"
-"environmental"
-"enviornmentalist"
-"environmentalist"
-"enviornmentally"
-"environmentally"
-"enviornments"
-"environments"
-"enviroment"
-"environment"
-"enviromental"
-"environmental"
-"enviromentalist"
-"environmentalist"
-"enviromentally"
-"environmentally"
-"enviroments"
-"environments"
-"envolutionary"
-"evolutionary"
-"envrionments"
-"environments"
-"enxt"
-"next"
-"epidsodes"
-"episodes"
-"epsiode"
-"episode"
-"equialent"
-"equivalent"
-"equilibium"
-"equilibrium"
-"equilibrum"
-"equilibrium"
-"equiped"
-"equipped"
-"equippment"
-"equipment"
-"equitorial"
-"equatorial"
-"equivelant"
-"equivalent"
-"equivelent"
-"equivalent"
-"equivilant"
-"equivalent"
-"equivilent"
-"equivalent"
-"equivlalent"
-"equivalent"
-"erally"
-"orally,"
-"really"
-"eratic"
-"erratic"
-"eratically"
-"erratically"
-"eraticly"
-"erratically"
-"erested"
-"arrested,"
-"erected"
-"errupted"
-"erupted"
-"esential"
-"essential"
-"esitmated"
-"estimated"
-"esle"
-"else"
-"especialy"
-"especially"
-"essencial"
-"essential"
-"essense"
-"essence"
-"essentail"
-"essential"
-"essentialy"
-"essentially"
-"essentual"
-"essential"
-"essesital"
-"essential"
-"estabishes"
-"establishes"
-"establising"
-"establishing"
-"ethnocentricm"
-"ethnocentrism"
-"ethose"
-"those,"
-"ethos"
-"Europian"
-"European"
-"Europians"
-"Europeans"
-"Eurpean"
-"European"
-"Eurpoean"
-"European"
-"evenhtually"
-"eventually"
-"eventally"
-"eventually"
-"eventially"
-"eventually"
-"eventualy"
-"eventually"
-"everthing"
-"everything"
-"everytime"
-"every"
-"time"
-"everyting"
-"everything"
-"eveyr"
-"every"
-"evidentally"
-"evidently"
-"exagerate"
-"exaggerate"
-"exagerated"
-"exaggerated"
-"exagerates"
-"exaggerates"
-"exagerating"
-"exaggerating"
-"exagerrate"
-"exaggerate"
-"exagerrated"
-"exaggerated"
-"exagerrates"
-"exaggerates"
-"exagerrating"
-"exaggerating"
-"examinated"
-"examined"
-"exampt"
-"exempt"
-"exapansion"
-"expansion"
-"excact"
-"exact"
-"excange"
-"exchange"
-"excecute"
-"execute"
-"excecuted"
-"executed"
-"excecutes"
-"executes"
-"excecuting"
-"executing"
-"excecution"
-"execution"
-"excedded"
-"exceeded"
-"excelent"
-"excellent"
-"excell"
-"excel"
-"excellance"
-"excellence"
-"excellant"
-"excellent"
-"excells"
-"excels"
-"excercise"
-"exercise"
-"exchanching"
-"exchanging"
-"excisted"
-"existed"
-"exculsivly"
-"exclusively"
-"execising"
-"exercising"
-"exection"
-"execution"
-"exectued"
-"executed"
-"exeedingly"
-"exceedingly"
-"exelent"
-"excellent"
-"exellent"
-"excellent"
-"exemple"
-"example"
-"exept"
-"except"
-"exeptional"
-"exceptional"
-"exerbate"
-"exacerbate"
-"exerbated"
-"exacerbated"
-"exerciese"
-"exercises"
-"exerpt"
-"excerpt"
-"exerpts"
-"excerpts"
-"exersize"
-"exercise"
-"exerternal"
-"external"
-"exhalted"
-"exalted"
-"exhibtion"
-"exhibition"
-"exibition"
-"exhibition"
-"exibitions"
-"exhibitions"
-"exicting"
-"exciting"
-"exinct"
-"extinct"
-"existance"
-"existence"
-"existant"
-"existent"
-"existince"
-"existence"
-"exliled"
-"exiled"
-"exludes"
-"excludes"
-"exmaple"
-"example"
-"exonorate"
-"exonerate"
-"exoskelaton"
-"exoskeleton"
-"expalin"
-"explain"
-"expeced"
-"expected"
-"expecially"
-"especially"
-"expeditonary"
-"expeditionary"
-"expeiments"
-"experiments"
-"expell"
-"expel"
-"expells"
-"expels"
-"experiance"
-"experience"
-"experianced"
-"experienced"
-"expiditions"
-"expeditions"
-"expierence"
-"experience"
-"explaination"
-"explanation"
-"explaning"
-"explaining"
-"explictly"
-"explicitly"
-"exploititive"
-"exploitative"
-"explotation"
-"exploitation"
-"expropiated"
-"expropriated"
-"expropiation"
-"expropriation"
-"exressed"
-"expressed"
-"extemely"
-"extremely"
-"extention"
-"extension"
-"extentions"
-"extensions"
-"extered"
-"exerted"
-"extermist"
-"extremist"
-"extint"
-"extinct,"
-"extant"
-"extradiction"
-"extradition"
-"extraterrestial"
-"extraterrestrial"
-"extraterrestials"
-"extraterrestrials"
-"extravagent"
-"extravagant"
-"extrememly"
-"extremely"
-"extremeophile"
-"extremophile"
-"extremly"
-"extremely"
-"extrordinarily"
-"extraordinarily"
-"extrordinary"
-"extraordinary"
-"eyar"
-"year,"
-"eyas"
-"eyars"
-"years,"
-"eyas"
-"eyasr"
-"years,"
-"eyas"
-"faciliate"
-"facilitate"
-"faciliated"
-"facilitated"
-"faciliates"
-"facilitates"
-"facilites"
-"facilities"
-"facillitate"
-"facilitate"
-"facinated"
-"fascinated"
-"facist"
-"fascist"
-"familes"
-"families"
-"familliar"
-"familiar"
-"famoust"
-"famous"
-"fanatism"
-"fanaticism"
-"Farenheit"
-"Fahrenheit"
-"fatc"
-"fact"
-"faught"
-"fought"
-"favoutrable"
-"favourable"
-"feasable"
-"feasible"
-"Febuary"
-"February"
-"fedreally"
-"federally"
-"feromone"
-"pheromone"
-"fertily"
-"fertility"
-"fianite"
-"finite"
-"fianlly"
-"finally"
-"ficticious"
-"fictitious"
-"fictious"
-"fictitious"
-"fidn"
-"find"
-"fiel"
-"feel,"
-"field,"
-"file,"
-"phial"
-"fiels"
-"feels,"
-"fields,"
-"files,"
-"phials"
-"fiercly"
-"fiercely"
-"fightings"
-"fighting"
-"filiament"
-"filament"
-"fimilies"
-"families"
-"finacial"
-"financial"
-"finaly"
-"finally"
-"financialy"
-"financially"
-"firends"
-"friends"
-"firts"
-"flirts,"
-"first"
-"fisionable"
-"fissionable"
-"flamable"
-"flammable"
-"flawess"
-"flawless"
-"fleed"
-"fled,"
-"freed"
-"Flemmish"
-"Flemish"
-"florescent"
-"fluorescent"
-"flourescent"
-"fluorescent"
-"fluorish"
-"flourish"
-"follwoing"
-"following"
-"folowing"
-"following"
-"fomed"
-"formed"
-"fomr"
-"from,"
-"form"
-"fonetic"
-"phonetic"
-"fontrier"
-"fontier"
-"foootball"
-"football"
-"forbad"
-"forbade"
-"forbiden"
-"forbidden"
-"foreward"
-"foreword"
-"forfiet"
-"forfeit"
-"forhead"
-"forehead"
-"foriegn"
-"foreign"
-"Formalhaut"
-"Fomalhaut"
-"formallize"
-"formalize"
-"formallized"
-"formalized"
-"formaly"
-"formally"
-"formelly"
-"formerly"
-"formidible"
-"formidable"
-"formost"
-"foremost"
-"forsaw"
-"foresaw"
-"forseeable"
-"foreseeable"
-"fortelling"
-"foretelling"
-"forunner"
-"forerunner"
-"foucs"
-"focus"
-"foudn"
-"found"
-"fougth"
-"fought"
-"foundaries"
-"foundries"
-"foundary"
-"foundry"
-"Foundland"
-"Newfoundland"
-"fourties"
-"forties"
-"fourty"
-"forty"
-"fouth"
-"fourth"
-"foward"
-"forward"
-"fucntion"
-"function"
-"fucntioning"
-"functioning"
-"Fransiscan"
-"Franciscan"
-"Fransiscans"
-"Franciscans"
-"freind"
-"friend"
-"freindly"
-"friendly"
-"frequentily"
-"frequently"
-"frome"
-"from"
-"fromed"
-"formed"
-"froniter"
-"frontier"
-"fufill"
-"fulfill"
-"fufilled"
-"fulfilled"
-"fulfiled"
-"fulfilled"
-"fundametal"
-"fundamental"
-"fundametals"
-"fundamentals"
-"funguses"
-"fungi"
-"funtion"
-"function"
-"furuther"
-"further"
-"futher"
-"further"
-"futhermore"
-"furthermore"
-"futhroc"
-"futhark,"
-"futhorc"
-"gae"
-"game,"
-"Gael,"
-"gale"
-"galatic"
-"galactic"
-"Galations"
-"Galatians"
-"gallaxies"
-"galaxies"
-"galvinized"
-"galvanized"
-"Gameboy"
-"Game"
-"Boy"
-"ganerate"
-"generate"
-"ganes"
-"games"
-"ganster"
-"gangster"
-"garantee"
-"guarantee"
-"garanteed"
-"guaranteed"
-"garantees"
-"guarantees"
-"garnison"
-"garrison"
-"gauarana"
-"guarana"
-"gaurantee"
-"guarantee"
-"gauranteed"
-"guaranteed"
-"gaurantees"
-"guarantees"
-"gaurd"
-"guard,"
-"gourd"
-"gaurentee"
-"guarantee"
-"gaurenteed"
-"guaranteed"
-"gaurentees"
-"guarantees"
-"geneological"
-"genealogical"
-"geneologies"
-"genealogies"
-"geneology"
-"genealogy"
-"generaly"
-"generally"
-"generatting"
-"generating"
-"genialia"
-"genitalia"
-"geographicial"
-"geographical"
-"geometrician"
-"geometer"
-"geometricians"
-"geometers"
-"gerat"
-"great"
-"Ghandi"
-"Gandhi"
-"glight"
-"flight"
-"gnawwed"
-"gnawed"
-"godess"
-"goddess"
-"godesses"
-"goddesses"
-"Godounov"
-"Godunov"
-"gogin"
-"going,"
-"Gauguin"
-"goign"
-"going"
-"gonig"
-"going"
-"Gothenberg"
-"Gothenburg"
-"Gottleib"
-"Gottlieb"
-"gouvener"
-"governor"
-"govement"
-"government"
-"govenment"
-"government"
-"govenrment"
-"government"
-"goverance"
-"governance"
-"goverment"
-"government"
-"govermental"
-"governmental"
-"governer"
-"governor"
-"governmnet"
-"government"
-"govorment"
-"government"
-"govormental"
-"governmental"
-"govornment"
-"government"
-"gracefull"
-"graceful"
-"graet"
-"great"
-"grafitti"
-"graffiti"
-"gramatically"
-"grammatically"
-"grammaticaly"
-"grammatically"
-"grammer"
-"grammar"
-"grat"
-"great"
-"gratuitious"
-"gratuitous"
-"greatful"
-"grateful"
-"greatfully"
-"gratefully"
-"greif"
-"grief"
-"gridles"
-"griddles"
-"gropu"
-"group"
-"grwo"
-"grow"
-"Guaduloupe"
-"Guadalupe,"
-"Guadeloupe"
-"Guadulupe"
-"Guadalupe,"
-"Guadeloupe"
-"guage"
-"gauge"
-"guarentee"
-"guarantee"
-"guarenteed"
-"guaranteed"
-"guarentees"
-"guarantees"
-"Guatamala"
-"Guatemala"
-"Guatamalan"
-"Guatemalan"
-"guerilla"
-"guerrilla"
-"guerillas"
-"guerrillas"
-"guerrila"
-"guerrilla"
-"guerrilas"
-"guerrillas"
-"guidence"
-"guidance"
-"Guilia"
-"Giulia"
-"Guilio"
-"Giulio"
-"Guiness"
-"Guinness"
-"Guiseppe"
-"Giuseppe"
-"gunanine"
-"guanine"
-"gurantee"
-"guarantee"
-"guranteed"
-"guaranteed"
-"gurantees"
-"guarantees"
-"guttaral"
-"guttural"
-"gutteral"
-"guttural"
-"habaeus"
-"habeas"
-"habeus"
-"habeas"
-"Habsbourg"
-"Habsburg"
-"haemorrage"
-"haemorrhage"
-"haev"
-"have,"
-"heave"
-"Hallowean"
-"Hallowe'en,"
-"Halloween"
-"halp"
-"help"
-"hapen"
-"happen"
-"hapened"
-"happened"
-"hapening"
-"happening"
-"happend"
-"happened"
-"happended"
-"happened"
-"happenned"
-"happened"
-"harased"
-"harassed"
-"harases"
-"harasses"
-"harasment"
-"harassment"
-"harasments"
-"harassments"
-"harassement"
-"harassment"
-"harras"
-"harass"
-"harrased"
-"harassed"
-"harrases"
-"harasses"
-"harrasing"
-"harassing"
-"harrasment"
-"harassment"
-"harrasments"
-"harassments"
-"harrassed"
-"harassed"
-"harrasses"
-"harassed"
-"harrassing"
-"harassing"
-"harrassment"
-"harassment"
-"harrassments"
-"harassments"
-"hasnt"
-"hasn't"
-"haviest"
-"heaviest"
-"headquater"
-"headquarter"
-"headquarer"
-"headquarter"
-"headquatered"
-"headquartered"
-"headquaters"
-"headquarters"
-"healthercare"
-"healthcare"
-"heared"
-"heard"
-"heathy"
-"healthy"
-"Heidelburg"
-"Heidelberg"
-"heigher"
-"higher"
-"heirarchy"
-"hierarchy"
-"heiroglyphics"
-"hieroglyphics"
-"helment"
-"helmet"
-"helpfull"
-"helpful"
-"helpped"
-"helped"
-"hemmorhage"
-"hemorrhage"
-"herad"
-"heard,"
-"Hera"
-"heridity"
-"heredity"
-"heroe"
-"hero"
-"heros"
-"heroes"
-"hertzs"
-"hertz"
-"hesistant"
-"hesitant"
-"heterogenous"
-"heterogeneous"
-"hieght"
-"height"
-"hierachical"
-"hierarchical"
-"hierachies"
-"hierarchies"
-"hierachy"
-"hierarchy"
-"hierarcical"
-"hierarchical"
-"hierarcy"
-"hierarchy"
-"hieroglph"
-"hieroglyph"
-"hieroglphs"
-"hieroglyphs"
-"higer"
-"higher"
-"higest"
-"highest"
-"higway"
-"highway"
-"hillarious"
-"hilarious"
-"himselv"
-"himself"
-"hinderance"
-"hindrance"
-"hinderence"
-"hindrance"
-"hindrence"
-"hindrance"
-"hipopotamus"
-"hippopotamus"
-"hismelf"
-"himself"
-"histocompatability"
-"histocompatibility"
-"historicians"
-"historians"
-"hitsingles"
-"hit"
-"singles"
-"holliday"
-"holiday"
-"homestate"
-"home"
-"state"
-"homogeneize"
-"homogenize"
-"homogeneized"
-"homogenized"
-"honory"
-"honorary"
-"horrifing"
-"horrifying"
-"hosited"
-"hoisted"
-"hospitible"
-"hospitable"
-"hounour"
-"honour"
-"housr"
-"hours,"
-"house"
-"howver"
-"however"
-"hsitorians"
-"historians"
-"hstory"
-"history"
-"hten"
-"then,"
-"hen,"
-"the"
-"htere"
-"there,"
-"here"
-"htey"
-"they"
-"htikn"
-"think"
-"hting"
-"thing"
-"htink"
-"think"
-"htis"
-"this"
-"humer"
-"humor,"
-"humour"
-"humerous"
-"humorous,"
-"humerus"
-"huminoid"
-"humanoid"
-"humoural"
-"humoral"
-"humurous"
-"humorous"
-"husban"
-"husband"
-"hvae"
-"have"
-"hvaing"
-"having"
-"hvea"
-"have,"
-"heave"
-"hwihc"
-"which"
-"hwile"
-"while"
-"hwole"
-"whole"
-"hydogen"
-"hydrogen"
-"hydropile"
-"hydrophile"
-"hydropilic"
-"hydrophilic"
-"hydropobe"
-"hydrophobe"
-"hydropobic"
-"hydrophobic"
-"hygeine"
-"hygiene"
-"hypocracy"
-"hypocrisy"
-"hypocrasy"
-"hypocrisy"
-"hypocricy"
-"hypocrisy"
-"hypocrit"
-"hypocrite"
-"hypocrits"
-"hypocrites"
-"iconclastic"
-"iconoclastic"
-"idaeidae"
-"idea"
-"idaes"
-"ideas"
-"idealogies"
-"ideologies"
-"idealogy"
-"ideology"
-"identicial"
-"identical"
-"identifers"
-"identifiers"
-"ideosyncratic"
-"idiosyncratic"
-"idesa"
-"ideas,"
-"ides"
-"idiosyncracy"
-"idiosyncrasy"
-"Ihaca"
-"Ithaca"
-"illegimacy"
-"illegitimacy"
-"illegitmate"
-"illegitimate"
-"illess"
-"illness"
-"illiegal"
-"illegal"
-"illution"
-"illusion"
-"ilness"
-"illness"
-"ilogical"
-"illogical"
-"imagenary"
-"imaginary"
-"imagin"
-"imagine"
-"imaginery"
-"imaginary,"
-"imagery"
-"imanent"
-"eminent,"
-"imminent"
-"imcomplete"
-"incomplete"
-"imediately"
-"immediately"
-"imense"
-"immense"
-"imigrant"
-"emigrant,"
-"immigrant"
-"imigrated"
-"emigrated,"
-"immigrated"
-"imigration"
-"emigration,"
-"immigration"
-"iminent"
-"eminent,"
-"imminent,"
-"immanent"
-"immediatley"
-"immediately"
-"immediatly"
-"immediately"
-"immidately"
-"immediately"
-"immidiately"
-"immediately"
-"immitate"
-"imitate"
-"immitated"
-"imitated"
-"immitating"
-"imitating"
-"immitator"
-"imitator"
-"immunosupressant"
-"immunosuppressant"
-"impecabbly"
-"impeccably"
-"impedence"
-"impedance"
-"implamenting"
-"implementing"
-"impliment"
-"implement"
-"implimented"
-"implemented"
-"imploys"
-"employs"
-"importamt"
-"important"
-"imprioned"
-"imprisoned"
-"imprisonned"
-"imprisoned"
-"improvision"
-"improvisation"
-"improvments"
-"improvements"
-"inablility"
-"inability"
-"inaccessable"
-"inaccessible"
-"inadiquate"
-"inadequate"
-"inadquate"
-"inadequate"
-"inadvertant"
-"inadvertent"
-"inadvertantly"
-"inadvertently"
-"inagurated"
-"inaugurated"
-"inaguration"
-"inauguration"
-"inappropiate"
-"inappropriate"
-"inaugures"
-"inaugurates"
-"inbalance"
-"imbalance"
-"inbalanced"
-"imbalanced"
-"inbetween"
-"between"
-"incarcirated"
-"incarcerated"
-"incidentially"
-"incidentally"
-"incidently"
-"incidentally"
-"inclreased"
-"increased"
-"includ"
-"include"
-"includng"
-"including"
-"incompatabilities"
-"incompatibilities"
-"incompatability"
-"incompatibility"
-"incompatable"
-"incompatible"
-"incompatablities"
-"incompatibilities"
-"incompatablity"
-"incompatibility"
-"incompatiblities"
-"incompatibilities"
-"incompatiblity"
-"incompatibility"
-"incompetance"
-"incompetence"
-"incompetant"
-"incompetent"
-"incomptable"
-"incompatible"
-"incomptetent"
-"incompetent"
-"inconsistant"
-"inconsistent"
-"incorperation"
-"incorporation"
-"incorportaed"
-"incorporated"
-"incorprates"
-"incorporates"
-"incorruptable"
-"incorruptible"
-"incramentally"
-"incrementally"
-"increadible"
-"incredible"
-"incredable"
-"incredible"
-"inctroduce"
-"introduce"
-"inctroduced"
-"introduced"
-"incuding"
-"including"
-"incunabla"
-"incunabula"
-"indefinately"
-"indefinitely"
-"indefineable"
-"undefinable"
-"indefinitly"
-"indefinitely"
-"indentical"
-"identical"
-"indepedantly"
-"independently"
-"indepedence"
-"independence"
-"independance"
-"independence"
-"independant"
-"independent"
-"independantly"
-"independently"
-"independece"
-"independence"
-"independendet"
-"independent"
-"indictement"
-"indictment"
-"indigineous"
-"indigenous"
-"indipendence"
-"independence"
-"indipendent"
-"independent"
-"indipendently"
-"independently"
-"indespensible"
-"indispensable"
-"indespensable"
-"indispensable"
-"indispensible"
-"indispensable"
-"indisputible"
-"indisputable"
-"indisputibly"
-"indisputably"
-"indite"
-"indict"
-"individualy"
-"individually"
-"indpendent"
-"independent"
-"indpendently"
-"independently"
-"indulgue"
-"indulge"
-"indutrial"
-"industrial"
-"indviduals"
-"individuals"
-"inefficienty"
-"inefficiently"
-"inevatible"
-"inevitable"
-"inevitible"
-"inevitable"
-"inevititably"
-"inevitably"
-"infalability"
-"infallibility"
-"infallable"
-"infallible"
-"infectuous"
-"infectious"
-"infered"
-"inferred"
-"infilitrate"
-"infiltrate"
-"infilitrated"
-"infiltrated"
-"infilitration"
-"infiltration"
-"infinit"
-"infinite"
-"inflamation"
-"inflammation"
-"influencial"
-"influential"
-"influented"
-"influenced"
-"infomation"
-"information"
-"informtion"
-"information"
-"infrantryman"
-"infantryman"
-"infrigement"
-"infringement"
-"ingenius"
-"ingenious"
-"ingreediants"
-"ingredients"
-"inhabitans"
-"inhabitants"
-"inherantly"
-"inherently"
-"inheritage"
-"heritage,"
-"inheritance"
-"inheritence"
-"inheritance"
-"inital"
-"initial"
-"initally"
-"initially"
-"initation"
-"initiation"
-"initiaitive"
-"initiative"
-"inlcuding"
-"including"
-"inmigrant"
-"immigrant"
-"inmigrants"
-"immigrants"
-"innoculated"
-"inoculated"
-"inocence"
-"innocence"
-"inofficial"
-"unofficial"
-"inot"
-"into"
-"inpeach"
-"impeach"
-"inpolite"
-"impolite"
-"inprisonment"
-"imprisonment"
-"inproving"
-"improving"
-"insectiverous"
-"insectivorous"
-"insensative"
-"insensitive"
-"inseperable"
-"inseparable"
-"insistance"
-"insistence"
-"insitution"
-"institution"
-"insitutions"
-"institutions"
-"inspite"
-"in"
-"spite,"
-"inspire"
-"instade"
-"instead"
-"instatance"
-"instance"
-"institue"
-"institute"
-"instuction"
-"instruction"
-"instuments"
-"instruments"
-"instutionalized"
-"institutionalized"
-"instutions"
-"intuitions"
-"insurence"
-"insurance"
-"intelectual"
-"intellectual"
-"inteligence"
-"intelligence"
-"inteligent"
-"intelligent"
-"intenational"
-"international"
-"intepretation"
-"interpretation"
-"intepretator"
-"interpretor"
-"interational"
-"international"
-"interbread"
-"interbreed,"
-"interbred"
-"interchangable"
-"interchangeable"
-"interchangably"
-"interchangeably"
-"intercontinetal"
-"intercontinental"
-"intered"
-"interred,"
-"interned"
-"interelated"
-"interrelated"
-"interferance"
-"interference"
-"interfereing"
-"interfering"
-"intergrated"
-"integrated"
-"intergration"
-"integration"
-"interm"
-"interim"
-"internation"
-"international"
-"interpet"
-"interpret"
-"interrim"
-"interim"
-"interrugum"
-"interregnum"
-"intertaining"
-"entertaining"
-"interupt"
-"interrupt"
-"intervines"
-"intervenes"
-"intevene"
-"intervene"
-"intial"
-"initial"
-"intially"
-"initially"
-"intrduced"
-"introduced"
-"intrest"
-"interest"
-"introdued"
-"introduced"
-"intruduced"
-"introduced"
-"intrusted"
-"entrusted"
-"intutive"
-"intuitive"
-"intutively"
-"intuitively"
-"inudstry"
-"industry"
-"inumerable"
-"enumerable,"
-"innumerable"
-"inventer"
-"inventor"
-"invertibrates"
-"invertebrates"
-"investingate"
-"investigate"
-"involvment"
-"involvement"
-"irelevent"
-"irrelevant"
-"iresistable"
-"irresistible"
-"iresistably"
-"irresistibly"
-"iresistible"
-"irresistible"
-"iresistibly"
-"irresistibly"
-"iritable"
-"irritable"
-"iritated"
-"irritated"
-"ironicly"
-"ironically"
-"irregardless"
-"regardless"
-"irrelevent"
-"irrelevant"
-"irreplacable"
-"irreplaceable"
-"irresistable"
-"irresistible"
-"irresistably"
-"irresistibly"
-"isnt"
-"isn't"
-"Israelies"
-"Israelis"
-"issueing"
-"issuing"
-"itnroduced"
-"introduced"
-"iunior"
-"junior"
-"iwll"
-"will"
-"iwth"
-"with"
-"Japanes"
-"Japanese"
-"jaques"
-"jacques"
-"jeapardy"
-"jeopardy"
-"jewllery"
-"jewellery"
-"Johanine"
-"Johannine"
-"Jospeh"
-"Joseph"
-"jouney"
-"journey"
-"journied"
-"journeyed"
-"journies"
-"journeys"
-"jstu"
-"just"
-"jsut"
-"just"
-"Juadaism"
-"Judaism"
-"Juadism"
-"Judaism"
-"judical"
-"judicial"
-"judisuary"
-"judiciary"
-"juducial"
-"judicial"
-"juristiction"
-"jurisdiction"
-"juristictions"
-"jurisdictions"
-"kindergarden"
-"kindergarten"
-"klenex"
-"kleenex"
-"knifes"
-"knives"
-"knive"
-"knife"
-"knowlege"
-"knowledge"
-"knowlegeable"
-"knowledgeable"
-"knwo"
-"know"
-"knwos"
-"knows"
-"konw"
-"know"
-"konws"
-"knows"
-"kwno"
-"know"
-"labatory"
-"lavatory,"
-"laboratory"
-"labled"
-"labelled,"
-"labeled"
-"labratory"
-"laboratory"
-"laguage"
-"language"
-"laguages"
-"languages"
-"larg"
-"large"
-"largst"
-"largest"
-"larrry"
-"larry"
-"lastr"
-"last"
-"lattitude"
-"latitude"
-"launchs"
-"launch"
-"launhed"
-"launched"
-"lavae"
-"larvae"
-"layed"
-"laid"
-"lazyness"
-"laziness"
-"leaded"
-"led"
-"leage"
-"league"
-"leanr"
-"lean,"
-"learn,"
-"leaner"
-"leathal"
-"lethal"
-"lefted"
-"left"
-"legitamate"
-"legitimate"
-"legitmate"
-"legitimate"
-"leibnitz"
-"leibniz"
-"lenght"
-"length"
-"leran"
-"learn"
-"lerans"
-"learns"
-"lieuenant"
-"lieutenant"
-"leutenant"
-"lieutenant"
-"levetate"
-"levitate"
-"levetated"
-"levitated"
-"levetates"
-"levitates"
-"levetating"
-"levitating"
-"levle"
-"level"
-"liasion"
-"liaison"
-"liason"
-"liaison"
-"liasons"
-"liaisons"
-"libary"
-"library"
-"libell"
-"libel"
-"libguistic"
-"linguistic"
-"libguistics"
-"linguistics"
-"libitarianisn"
-"libertarianism"
-"lible"
-"libel,"
-"liable"
-"lieing"
-"lying"
-"liek"
-"like"
-"liekd"
-"liked"
-"liesure"
-"leisure"
-"lieved"
-"lived"
-"liftime"
-"lifetime"
-"lightyear"
-"light"
-"year"
-"lightyears"
-"light"
-"years"
-"likelyhood"
-"likelihood"
-"linnaena"
-"linnaean"
-"lippizaner"
-"lipizzaner"
-"liquify"
-"liquefy"
-"liscense"
-"license,"
-"licence"
-"lisence"
-"license,"
-"licence"
-"lisense"
-"license,"
-"licence"
-"listners"
-"listeners"
-"litature"
-"literature"
-"literture"
-"literature"
-"littel"
-"little"
-"litterally"
-"literally"
-"liuke"
-"like"
-"livley"
-"lively"
-"lmits"
-"limits"
-"loev"
-"love"
-"lonelyness"
-"loneliness"
-"longitudonal"
-"longitudinal"
-"lonley"
-"lonely"
-"lonly"
-"lonely,"
-"only"
-"loosing"
-"losing"
-"lotharingen"
-"lothringen"
-"lsat"
-"last"
-"lukid"
-"likud"
-"lveo"
-"love"
-"lvoe"
-"love"
-"Lybia"
-"Libya"
-"mackeral"
-"mackerel"
-"magasine"
-"magazine"
-"magincian"
-"magician"
-"magnificient"
-"magnificent"
-"magolia"
-"magnolia"
-"mailny"
-"mainly"
-"maintainance"
-"maintenance"
-"maintainence"
-"maintenance"
-"maintance"
-"maintenance"
-"maintenence"
-"maintenance"
-"maintinaing"
-"maintaining"
-"maintioned"
-"mentioned"
-"majoroty"
-"majority"
-"maked"
-"marked,"
-"made"
-"makse"
-"makes"
-"Malcom"
-"Malcolm"
-"maltesian"
-"Maltese"
-"mamal"
-"mammal"
-"mamalian"
-"mammalian"
-"managable"
-"manageable,"
-"manageably"
-"managment"
-"management"
-"manisfestations"
-"manifestations"
-"manoeuverability"
-"maneuverability"
-"manouver"
-"maneuver,"
-"manoeuvre"
-"manouverability"
-"maneuverability,"
-"manoeuvrability,"
-"manoeuverability"
-"manouverable"
-"maneuverable,"
-"manoeuvrable"
-"manouvers"
-"maneuvers,"
-"manoeuvres"
-"mantained"
-"maintained"
-"manuever"
-"maneuver,"
-"manoeuvre"
-"manuevers"
-"maneuvers,"
-"manoeuvres"
-"manufacturedd"
-"manufactured"
-"manufature"
-"manufacture"
-"manufatured"
-"manufactured"
-"manufaturing"
-"manufacturing"
-"manuver"
-"maneuver"
-"mariage"
-"marriage"
-"marjority"
-"majority"
-"markes"
-"marks"
-"marketting"
-"marketing"
-"marmelade"
-"marmalade"
-"marrage"
-"marriage"
-"marraige"
-"marriage"
-"marrtyred"
-"martyred"
-"marryied"
-"married"
-"Massachussets"
-"Massachusetts"
-"Massachussetts"
-"Massachusetts"
-"massmedia"
-"mass"
-"media"
-"masterbation"
-"masturbation"
-"mataphysical"
-"metaphysical"
-"materalists"
-"materialist"
-"mathamatics"
-"mathematics"
-"mathematican"
-"mathematician"
-"mathematicas"
-"mathematics"
-"matheticians"
-"mathematicians"
-"mathmatically"
-"mathematically"
-"mathmatician"
-"mathematician"
-"mathmaticians"
-"mathematicians"
-"mccarthyst"
-"mccarthyist"
-"mchanics"
-"mechanics"
-"meaninng"
-"meaning"
-"mear"
-"wear,"
-"mere,"
-"mare"
-"mechandise"
-"merchandise"
-"medacine"
-"medicine"
-"medeival"
-"medieval"
-"medevial"
-"medieval"
-"mediciney"
-"mediciny"
-"medievel"
-"medieval"
-"mediterainnean"
-"mediterranean"
-"Mediteranean"
-"Mediterranean"
-"meerkrat"
-"meerkat"
-"melieux"
-"milieux"
-"membranaphone"
-"membranophone"
-"memeber"
-"member"
-"menally"
-"mentally"
-"meranda"
-"veranda,"
-"Miranda"
-"mercentile"
-"mercantile"
-"messanger"
-"messenger"
-"messenging"
-"messaging"
-"metalic"
-"metallic"
-"metalurgic"
-"metallurgic"
-"metalurgical"
-"metallurgical"
-"metalurgy"
-"metallurgy"
-"metamorphysis"
-"metamorphosis"
-"metaphoricial"
-"metaphorical"
-"meterologist"
-"meteorologist"
-"meterology"
-"meteorology"
-"methaphor"
-"metaphor"
-"methaphors"
-"metaphors"
-"Michagan"
-"Michigan"
-"micoscopy"
-"microscopy"
-"midwifes"
-"midwives"
-"mileau"
-"milieu"
-"milennia"
-"millennia"
-"milennium"
-"millennium"
-"mileu"
-"milieu"
-"miliary"
-"military"
-"milion"
-"million"
-"miliraty"
-"military"
-"millenia"
-"millennia"
-"millenial"
-"millennial"
-"millenialism"
-"millennialism"
-"millenium"
-"millennium"
-"millepede"
-"millipede"
-"millioniare"
-"millionaire"
-"millitary"
-"military"
-"millon"
-"million"
-"miltary"
-"military"
-"minature"
-"miniature"
-"minerial"
-"mineral"
-"miniscule"
-"minuscule"
-"ministery"
-"ministry"
-"minstries"
-"ministries"
-"minstry"
-"ministry"
-"minumum"
-"minimum"
-"mirrorred"
-"mirrored"
-"miscelaneous"
-"miscellaneous"
-"miscellanious"
-"miscellaneous"
-"miscellanous"
-"miscellaneous"
-"mischeivous"
-"mischievous"
-"mischevious"
-"mischievous"
-"mischievious"
-"mischievous"
-"misdameanor"
-"misdemeanor"
-"misdameanors"
-"misdemeanors"
-"misdemenor"
-"misdemeanor"
-"misdemenors"
-"misdemeanors"
-"misfourtunes"
-"misfortunes"
-"misile"
-"missile"
-"Misouri"
-"Missouri"
-"mispell"
-"misspell"
-"mispelled"
-"misspelled"
-"mispelling"
-"misspelling"
-"missen"
-"mizzen"
-"Missisipi"
-"Mississippi"
-"Missisippi"
-"Mississippi"
-"missle"
-"missile"
-"missonary"
-"missionary"
-"misterious"
-"mysterious"
-"mistery"
-"mystery"
-"misteryous"
-"mysterious"
-"mkae"
-"make"
-"mkaes"
-"makes"
-"mkaing"
-"making"
-"mkea"
-"make"
-"moderm"
-"modem"
-"modle"
-"model"
-"moent"
-"moment"
-"moeny"
-"money"
-"mohammedans"
-"muslims"
-"moil"
-"mohel"
-"moleclues"
-"molecules"
-"momento"
-"memento"
-"monestaries"
-"monasteries"
-"monestary"
-"monastery,"
-"monetary"
-"monickers"
-"monikers"
-"monolite"
-"monolithic"
-"Monserrat"
-"Montserrat"
-"montains"
-"mountains"
-"montanous"
-"mountainous"
-"monts"
-"months"
-"montypic"
-"monotypic"
-"moreso"
-"more,"
-"more"
-"so"
-"morgage"
-"mortgage"
-"Morisette"
-"Morissette"
-"Morrisette"
-"Morissette"
-"morroccan"
-"moroccan"
-"morrocco"
-"morocco"
-"morroco"
-"morocco"
-"mosture"
-"moisture"
-"motiviated"
-"motivated"
-"mounth"
-"month"
-"movei"
-"movie"
-"movment"
-"movement"
-"mroe"
-"more"
-"mucuous"
-"mucous"
-"muder"
-"murder"
-"mudering"
-"murdering"
-"muhammadan"
-"muslim"
-"multicultralism"
-"multiculturalism"
-"multipled"
-"multiplied"
-"multiplers"
-"multipliers"
-"munbers"
-"numbers"
-"muncipalities"
-"municipalities"
-"muncipality"
-"municipality"
-"munnicipality"
-"municipality"
-"muscels"
-"mussels,"
-"muscles"
-"muscial"
-"musical"
-"muscician"
-"musician"
-"muscicians"
-"musicians"
-"mutiliated"
-"mutilated"
-"myraid"
-"myriad"
-"mysef"
-"myself"
-"mysogynist"
-"misogynist"
-"mysogyny"
-"misogyny"
-"mysterous"
-"mysterious"
-"Mythraic"
-"Mithraic"
-"naieve"
-"naive"
-"Napoleonian"
-"Napoleonic"
-"naturaly"
-"naturally"
-"naturely"
-"naturally"
-"naturual"
-"natural"
-"naturually"
-"naturally"
-"Nazereth"
-"Nazareth"
-"neccesarily"
-"necessarily"
-"neccesary"
-"necessary"
-"neccessarily"
-"necessarily"
-"neccessary"
-"necessary"
-"neccessities"
-"necessities"
-"necesarily"
-"necessarily"
-"necesary"
-"necessary"
-"necessiate"
-"necessitate"
-"neglible"
-"negligible"
-"negligable"
-"negligible"
-"negociate"
-"negotiate"
-"negociation"
-"negotiation"
-"negociations"
-"negotiations"
-"negotation"
-"negotiation"
-"neice"
-"niece,"
-"nice"
-"neigborhood"
-"neighborhood"
-"neigbour"
-"neighbour,"
-"neighbor"
-"neigbourhood"
-"neighbourhood"
-"neigbouring"
-"neighbouring,"
-"neighboring"
-"neigbours"
-"neighbours,"
-"neighbors"
-"neolitic"
-"neolithic"
-"nessasarily"
-"necessarily"
-"nessecary"
-"necessary"
-"nestin"
-"nesting"
-"neverthless"
-"nevertheless"
-"newletters"
-"newsletters"
-"Newyorker"
-"New"
-"Yorker"
-"nickle"
-"nickel"
-"nightfa;;"
-"nightfall"
-"nightime"
-"nighttime"
-"nineth"
-"ninth"
-"ninteenth"
-"nineteenth"
-"ninties"
-"1990s"
-"ninty"
-"ninety"
-"nkow"
-"know"
-"nkwo"
-"know"
-"nmae"
-"name"
-"noncombatents"
-"noncombatants"
-"nonsence"
-"nonsense"
-"nontheless"
-"nonetheless"
-"noone"
-"no"
-"one"
-"norhern"
-"northern"
-"northen"
-"northern"
-"northereastern"
-"northeastern"
-"notabley"
-"notably"
-"noteable"
-"notable"
-"noteably"
-"notably"
-"noteriety"
-"notoriety"
-"noth"
-"north"
-"nothern"
-"northern"
-"noticable"
-"noticeable"
-"noticably"
-"noticeably"
-"noticeing"
-"noticing"
-"noticible"
-"noticeable"
-"notwhithstanding"
-"notwithstanding"
-"noveau"
-"nouveau"
-"nowdays"
-"nowadays"
-"nowe"
-"now"
-"nto"
-"not"
-"nucular"
-"nuclear"
-"nuculear"
-"nuclear"
-"nuisanse"
-"nuisance"
-"Nullabour"
-"Nullarbor"
-"numberous"
-"numerous"
-"Nuremburg"
-"Nuremberg"
-"nusance"
-"nuisance"
-"nutritent"
-"nutrient"
-"nutritents"
-"nutrients"
-"nuturing"
-"nurturing"
-"obediance"
-"obedience"
-"obediant"
-"obedient"
-"obession"
-"obsession"
-"obssessed"
-"obsessed"
-"obstacal"
-"obstacle"
-"obstancles"
-"obstacles"
-"obstruced"
-"obstructed"
-"ocasion"
-"occasion"
-"ocasional"
-"occasional"
-"ocasionally"
-"occasionally"
-"ocasionaly"
-"occasionally"
-"ocasioned"
-"occasioned"
-"ocasions"
-"occasions"
-"ocassion"
-"occasion"
-"ocassional"
-"occasional"
-"ocassionally"
-"occasionally"
-"ocassionaly"
-"occasionally"
-"ocassioned"
-"occasioned"
-"ocassions"
-"occasions"
-"occaison"
-"occasion"
-"occassion"
-"occasion"
-"occassional"
-"occasional"
-"occassionally"
-"occasionally"
-"occassionaly"
-"occasionally"
-"occassioned"
-"occasioned"
-"occassions"
-"occasions"
-"occationally"
-"occasionally"
-"occour"
-"occur"
-"occurance"
-"occurrence"
-"occurances"
-"occurrences"
-"occured"
-"occurred"
-"occurence"
-"occurrence"
-"occurences"
-"occurrences"
-"occuring"
-"occurring"
-"occurr"
-"occur"
-"occurrance"
-"occurrence"
-"occurrances"
-"occurrences"
-"octohedra"
-"octahedra"
-"octohedral"
-"octahedral"
-"octohedron"
-"octahedron"
-"ocuntries"
-"countries"
-"ocuntry"
-"country"
-"ocurr"
-"occur"
-"ocurrance"
-"occurrence"
-"ocurred"
-"occurred"
-"ocurrence"
-"occurrence"
-"offcers"
-"officers"
-"offcially"
-"officially"
-"offereings"
-"offerings"
-"offical"
-"official"
-"officals"
-"officials"
-"offically"
-"officially"
-"officaly"
-"officially"
-"officialy"
-"officially"
-"offred"
-"offered"
-"oftenly"
-"often"
-"oging"
-"going,"
-"ogling"
-"omision"
-"omission"
-"omited"
-"omitted"
-"omiting"
-"omitting"
-"omlette"
-"omelette"
-"ommision"
-"omission"
-"ommited"
-"omitted"
-"ommiting"
-"omitting"
-"ommitted"
-"omitted"
-"ommitting"
-"omitting"
-"omniverous"
-"omnivorous"
-"omniverously"
-"omnivorously"
-"omre"
-"more"
-"onot"
-"note,"
-"not"
-"onyl"
-"only"
-"openess"
-"openness"
-"oponent"
-"opponent"
-"oportunity"
-"opportunity"
-"opose"
-"oppose"
-"oposite"
-"opposite"
-"oposition"
-"opposition"
-"oppenly"
-"openly"
-"oppinion"
-"opinion"
-"opponant"
-"opponent"
-"oppononent"
-"opponent"
-"oppositition"
-"opposition"
-"oppossed"
-"opposed"
-"opprotunity"
-"opportunity"
-"opression"
-"oppression"
-"opressive"
-"oppressive"
-"opthalmic"
-"ophthalmic"
-"opthalmologist"
-"ophthalmologist"
-"opthalmology"
-"ophthalmology"
-"opthamologist"
-"ophthalmologist"
-"optmizations"
-"optimizations"
-"optomism"
-"optimism"
-"orded"
-"ordered"
-"organim"
-"organism"
-"organiztion"
-"organization"
-"orgin"
-"origin,"
-"organ"
-"orginal"
-"original"
-"orginally"
-"originally"
-"orginize"
-"organise"
-"oridinarily"
-"ordinarily"
-"origanaly"
-"originally"
-"originall"
-"original,"
-"originally"
-"originaly"
-"originally"
-"originially"
-"originally"
-"originnally"
-"originally"
-"origional"
-"original"
-"orignally"
-"originally"
-"orignially"
-"originally"
-"otehr"
-"other"
-"ouevre"
-"oeuvre"
-"overshaddowed"
-"overshadowed"
-"overthere"
-"over"
-"there"
-"overwelming"
-"overwhelming"
-"overwheliming"
-"overwhelming"
-"owrk"
-"work"
-"owudl"
-"would"
-"oxigen"
-"oxygen"
-"oximoron"
-"oxymoron"
-"paide"
-"paid"
-"paitience"
-"patience"
-"palce"
-"place,"
-"palace"
-"paleolitic"
-"paleolithic"
-"paliamentarian"
-"parliamentarian"
-"Palistian"
-"Palestinian"
-"Palistinian"
-"Palestinian"
-"Palistinians"
-"Palestinians"
-"pallete"
-"palette"
-"pamflet"
-"pamphlet"
-"pamplet"
-"pamphlet"
-"pantomine"
-"pantomime"
-"Papanicalou"
-"Papanicolaou"
-"paralel"
-"parallel"
-"paralell"
-"parallel"
-"paralelly"
-"parallelly"
-"paralely"
-"parallelly"
-"parallely"
-"parallelly"
-"paranthesis"
-"parenthesis"
-"paraphenalia"
-"paraphernalia"
-"parellels"
-"parallels"
-"parituclar"
-"particular"
-"parliment"
-"parliament"
-"parrakeets"
-"parakeets"
-"parralel"
-"parallel"
-"parrallel"
-"parallel"
-"parrallell"
-"parallel"
-"parrallelly"
-"parallelly"
-"parrallely"
-"parallelly"
-"partialy"
-"partially"
-"particually"
-"particularly"
-"particualr"
-"particular"
-"particuarly"
-"particularly"
-"particularily"
-"particularly"
-"particulary"
-"particularly"
-"pary"
-"party"
-"pased"
-"passed"
-"pasengers"
-"passengers"
-"passerbys"
-"passersby"
-"pasttime"
-"pastime"
-"pastural"
-"pastoral"
-"paticular"
-"particular"
-"pattented"
-"patented"
-"pavillion"
-"pavilion"
-"payed"
-"paid"
-"peacefuland"
-"peaceful"
-"and"
-"peageant"
-"pageant"
-"peculure"
-"peculiar"
-"pedestrain"
-"pedestrian"
-"peice"
-"piece"
-"Peloponnes"
-"Peloponnesus"
-"penatly"
-"penalty"
-"penerator"
-"penetrator"
-"penisula"
-"peninsula"
-"penisular"
-"peninsular"
-"penninsula"
-"peninsula"
-"penninsular"
-"peninsular"
-"pennisula"
-"peninsula"
-"pensinula"
-"peninsula"
-"peom"
-"poem"
-"peoms"
-"poems"
-"peopel"
-"people"
-"peotry"
-"poetry"
-"perade"
-"parade"
-"percepted"
-"perceived"
-"percieve"
-"perceive"
-"percieved"
-"perceived"
-"perenially"
-"perennially"
-"perfomers"
-"performers"
-"performence"
-"performance"
-"performes"
-"performed,"
-"performs"
-"perhasp"
-"perhaps"
-"perheaps"
-"perhaps"
-"perhpas"
-"perhaps"
-"peripathetic"
-"peripatetic"
-"peristent"
-"persistent"
-"perjery"
-"perjury"
-"perjorative"
-"pejorative"
-"permanant"
-"permanent"
-"permenant"
-"permanent"
-"permenantly"
-"permanently"
-"permissable"
-"permissible"
-"perogative"
-"prerogative"
-"peronal"
-"personal"
-"perosnality"
-"personality"
-"perphas"
-"perhaps"
-"perpindicular"
-"perpendicular"
-"perseverence"
-"perseverance"
-"persistance"
-"persistence"
-"persistant"
-"persistent"
-"personel"
-"personnel,"
-"personal"
-"personell"
-"personnel"
-"personnell"
-"personnel"
-"persuded"
-"persuaded"
-"persue"
-"pursue"
-"persued"
-"pursued"
-"persuing"
-"pursuing"
-"persuit"
-"pursuit"
-"persuits"
-"pursuits"
-"pertubation"
-"perturbation"
-"pertubations"
-"perturbations"
-"pessiary"
-"pessary"
-"petetion"
-"petition"
-"Pharoah"
-"Pharaoh"
-"phenomenom"
-"phenomenon"
-"phenomenonal"
-"phenomenal"
-"phenomenonly"
-"phenomenally"
-"phenomonenon"
-"phenomenon"
-"phenomonon"
-"phenomenon"
-"phenonmena"
-"phenomena"
-"Philipines"
-"Philippines"
-"philisopher"
-"philosopher"
-"philisophical"
-"philosophical"
-"philisophy"
-"philosophy"
-"Phillipine"
-"Philippine"
-"Phillipines"
-"Philippines"
-"Phillippines"
-"Philippines"
-"phillosophically"
-"philosophically"
-"philospher"
-"philosopher"
-"philosphies"
-"philosophies"
-"philosphy"
-"philosophy"
-"Phonecian"
-"Phoenecian"
-"phongraph"
-"phonograph"
-"phylosophical"
-"philosophical"
-"physicaly"
-"physically"
-"pich"
-"pitch"
-"pilgrimmage"
-"pilgrimage"
-"pilgrimmages"
-"pilgrimages"
-"pinapple"
-"pineapple"
-"pinnaple"
-"pineapple"
-"pinoneered"
-"pioneered"
-"plagarism"
-"plagiarism"
-"planation"
-"plantation"
-"planed"
-"planned"
-"plantiff"
-"plaintiff"
-"plateu"
-"plateau"
-"plausable"
-"plausible"
-"playright"
-"playwright"
-"playwrite"
-"playwright"
-"playwrites"
-"playwrights"
-"pleasent"
-"pleasant"
-"plebicite"
-"plebiscite"
-"plesant"
-"pleasant"
-"poeoples"
-"peoples"
-"poety"
-"poetry"
-"poisin"
-"poison"
-"polical"
-"political"
-"polinator"
-"pollinator"
-"polinators"
-"pollinators"
-"politican"
-"politician"
-"politicans"
-"politicians"
-"poltical"
-"political"
-"polute"
-"pollute"
-"poluted"
-"polluted"
-"polutes"
-"pollutes"
-"poluting"
-"polluting"
-"polution"
-"pollution"
-"polyphonyic"
-"polyphonic"
-"polysaccaride"
-"polysaccharide"
-"polysaccharid"
-"polysaccharide"
-"pomegranite"
-"pomegranate"
-"pomotion"
-"promotion"
-"poportional"
-"proportional"
-"popoulation"
-"population"
-"popularaty"
-"popularity"
-"populare"
-"popular"
-"populer"
-"popular"
-"portayed"
-"portrayed"
-"portraing"
-"portraying"
-"Portugese"
-"Portuguese"
-"portuguease"
-"portuguese"
-"posess"
-"possess"
-"posessed"
-"possessed"
-"posesses"
-"possesses"
-"posessing"
-"possessing"
-"posession"
-"possession"
-"posessions"
-"possessions"
-"posion"
-"poison"
-"positon"
-"position,"
-"positron"
-"possable"
-"possible"
-"possably"
-"possibly"
-"posseses"
-"possesses"
-"possesing"
-"possessing"
-"possesion"
-"possession"
-"possessess"
-"possesses"
-"possibile"
-"possible"
-"possibilty"
-"possibility"
-"possiblility"
-"possibility"
-"possiblilty"
-"possibility"
-"possiblities"
-"possibilities"
-"possiblity"
-"possibility"
-"possition"
-"position"
-"Postdam"
-"Potsdam"
-"posthomous"
-"posthumous"
-"postion"
-"position"
-"postive"
-"positive"
-"potatos"
-"potatoes"
-"portait"
-"portrait"
-"potrait"
-"portrait"
-"potrayed"
-"portrayed"
-"poulations"
-"populations"
-"poverful"
-"powerful"
-"poweful"
-"powerful"
-"powerfull"
-"powerful"
-"practial"
-"practical"
-"practially"
-"practically"
-"practicaly"
-"practically"
-"practicioner"
-"practitioner"
-"practicioners"
-"practitioners"
-"practicly"
-"practically"
-"practioner"
-"practitioner"
-"practioners"
-"practitioners"
-"prairy"
-"prairie"
-"prarie"
-"prairie"
-"praries"
-"prairies"
-"pratice"
-"practice"
-"preample"
-"preamble"
-"precedessor"
-"predecessor"
-"preceed"
-"precede"
-"preceeded"
-"preceded"
-"preceeding"
-"preceding"
-"preceeds"
-"precedes"
-"precentage"
-"percentage"
-"precice"
-"precise"
-"precisly"
-"precisely"
-"precurser"
-"precursor"
-"predecesors"
-"predecessors"
-"predicatble"
-"predictable"
-"predicitons"
-"predictions"
-"predomiantly"
-"predominately"
-"prefered"
-"preferred"
-"prefering"
-"preferring"
-"preferrably"
-"preferably"
-"pregancies"
-"pregnancies"
-"preiod"
-"period"
-"preliferation"
-"proliferation"
-"premeire"
-"premiere"
-"premeired"
-"premiered"
-"premillenial"
-"premillennial"
-"preminence"
-"preeminence"
-"premission"
-"permission"
-"Premonasterians"
-"Premonstratensians"
-"preocupation"
-"preoccupation"
-"prepair"
-"prepare"
-"prepartion"
-"preparation"
-"prepatory"
-"preparatory"
-"preperation"
-"preparation"
-"preperations"
-"preparations"
-"preriod"
-"period"
-"presedential"
-"presidential"
-"presense"
-"presence"
-"presidenital"
-"presidential"
-"presidental"
-"presidential"
-"presitgious"
-"prestigious"
-"prespective"
-"perspective"
-"prestigeous"
-"prestigious"
-"prestigous"
-"prestigious"
-"presumabely"
-"presumably"
-"presumibly"
-"presumably"
-"pretection"
-"protection"
-"prevelant"
-"prevalent"
-"preverse"
-"perverse"
-"previvous"
-"previous"
-"pricipal"
-"principal"
-"priciple"
-"principle"
-"priestood"
-"priesthood"
-"primarly"
-"primarily"
-"primative"
-"primitive"
-"primatively"
-"primitively"
-"primatives"
-"primitives"
-"primordal"
-"primordial"
-"priveledges"
-"privileges"
-"privelege"
-"privilege"
-"priveleged"
-"privileged"
-"priveleges"
-"privileges"
-"privelige"
-"privilege"
-"priveliged"
-"privileged"
-"priveliges"
-"privileges"
-"privelleges"
-"privileges"
-"privilage"
-"privilege"
-"priviledge"
-"privilege"
-"priviledges"
-"privileges"
-"privledge"
-"privilege"
-"privte"
-"private"
-"probabilaty"
-"probability"
-"probablistic"
-"probabilistic"
-"probablly"
-"probably"
-"probalibity"
-"probability"
-"probaly"
-"probably"
-"probelm"
-"problem"
-"proccess"
-"process"
-"proccessing"
-"processing"
-"procede"
-"proceed,"
-"precede"
-"proceded"
-"proceeded,"
-"preceded"
-"procedes"
-"proceeds,"
-"precedes"
-"procedger"
-"procedure"
-"proceding"
-"proceeding,"
-"preceding"
-"procedings"
-"proceedings"
-"proceedure"
-"procedure"
-"proces"
-"process"
-"processer"
-"processor"
-"proclaimation"
-"proclamation"
-"proclamed"
-"proclaimed"
-"proclaming"
-"proclaiming"
-"proclomation"
-"proclamation"
-"profesion"
-"profusion,"
-"profession"
-"profesor"
-"professor"
-"professer"
-"professor"
-"proffesed"
-"professed"
-"proffesion"
-"profession"
-"proffesional"
-"professional"
-"proffesor"
-"professor"
-"profilic"
-"prolific"
-"progessed"
-"progressed"
-"programable"
-"programmable"
-"progrom"
-"pogrom,"
-"program"
-"progroms"
-"pogroms,"
-"programs"
-"prohabition"
-"prohibition"
-"prologomena"
-"prolegomena"
-"prominance"
-"prominence"
-"prominant"
-"prominent"
-"prominantly"
-"prominently"
-"prominately"
-"prominently,"
-"predominately"
-"promiscous"
-"promiscuous"
-"promotted"
-"promoted"
-"pronomial"
-"pronominal"
-"pronouced"
-"pronounced"
-"pronounched"
-"pronounced"
-"pronounciation"
-"pronunciation"
-"proove"
-"prove"
-"prooved"
-"proved"
-"prophacy"
-"prophecy"
-"propietary"
-"proprietary"
-"propmted"
-"prompted"
-"propoganda"
-"propaganda"
-"propogate"
-"propagate"
-"propogates"
-"propagates"
-"propogation"
-"propagation"
-"propostion"
-"proposition"
-"propotions"
-"proportions"
-"propper"
-"proper"
-"propperly"
-"properly"
-"proprietory"
-"proprietary"
-"proseletyzing"
-"proselytizing"
-"protaganist"
-"protagonist"
-"protaganists"
-"protagonists"
-"protocal"
-"protocol"
-"protoganist"
-"protagonist"
-"protrayed"
-"portrayed"
-"protruberance"
-"protuberance"
-"protruberances"
-"protuberances"
-"prouncements"
-"pronouncements"
-"provacative"
-"provocative"
-"provded"
-"provided"
-"provicial"
-"provincial"
-"provinicial"
-"provincial"
-"provisonal"
-"provisional"
-"provisiosn"
-"provision"
-"proximty"
-"proximity"
-"pseudononymous"
-"pseudonymous"
-"pseudonyn"
-"pseudonym"
-"psuedo"
-"pseudo"
-"psycology"
-"psychology"
-"psyhic"
-"psychic"
-"publicaly"
-"publicly"
-"puchasing"
-"purchasing"
-"Pucini"
-"Puccini"
-"Puertorrican"
-"Puerto"
-"Rican"
-"Puertorricans"
-"Puerto"
-"Ricans"
-"pumkin"
-"pumpkin"
-"puritannical"
-"puritanical"
-"purposedly"
-"purposely"
-"purpotedly"
-"purportedly"
-"pursuade"
-"persuade"
-"pursuaded"
-"persuaded"
-"pursuades"
-"persuades"
-"pususading"
-"persuading"
-"puting"
-"putting"
-"pwoer"
-"power"
-"pyscic"
-"psychic"
-"qtuie"
-"quite,"
-"quiet"
-"quantaty"
-"quantity"
-"quantitiy"
-"quantity"
-"quarantaine"
-"quarantine"
-"Queenland"
-"Queensland"
-"questonable"
-"questionable"
-"quicklyu"
-"quickly"
-"quinessential"
-"quintessential"
-"quitted"
-"quit"
-"quizes"
-"quizzes"
-"qutie"
-"quite,"
-"quiet"
-"rabinnical"
-"rabbinical"
-"racaus"
-"raucous"
-"radiactive"
-"radioactive"
-"radify"
-"ratify"
-"raelly"
-"really"
-"rarified"
-"rarefied"
-"reaccurring"
-"recurring"
-"reacing"
-"reaching"
-"reacll"
-"recall"
-"readmition"
-"readmission"
-"realitvely"
-"relatively"
-"realsitic"
-"realistic"
-"realtions"
-"relations"
-"realy"
-"really"
-"realyl"
-"really"
-"reasearch"
-"research"
-"rebiulding"
-"rebuilding"
-"rebllions"
-"rebellions"
-"rebounce"
-"rebound"
-"reccomend"
-"recommend"
-"reccomendations"
-"recommendations"
-"reccomended"
-"recommended"
-"reccomending"
-"recommending"
-"reccommend"
-"recommend"
-"reccommended"
-"recommended"
-"reccommending"
-"recommending"
-"reccuring"
-"recurring"
-"receeded"
-"receded"
-"receeding"
-"receding"
-"receivedfrom"
-"received"
-"from"
-"recepient"
-"recipient"
-"recepients"
-"recipients"
-"receving"
-"receiving"
-"rechargable"
-"rechargeable"
-"reched"
-"reached"
-"recide"
-"reside"
-"recided"
-"resided"
-"recident"
-"resident"
-"recidents"
-"residents"
-"reciding"
-"residing"
-"reciepents"
-"recipients"
-"reciept"
-"receipt"
-"recieve"
-"receive"
-"recieved"
-"received"
-"reciever"
-"receiver"
-"recievers"
-"receivers"
-"recieves"
-"receives"
-"recieving"
-"receiving"
-"recipiant"
-"recipient"
-"recipiants"
-"recipients"
-"recived"
-"received"
-"recivership"
-"receivership"
-"recogise"
-"recognise"
-"recogize"
-"recognize"
-"recomend"
-"recommend"
-"recomended"
-"recommended"
-"recomending"
-"recommending"
-"recomends"
-"recommends"
-"recommedations"
-"recommendations"
-"reconaissance"
-"reconnaissance"
-"reconcilation"
-"reconciliation"
-"reconized"
-"recognized"
-"reconnaissence"
-"reconnaissance"
-"recontructed"
-"reconstructed"
-"recordproducer"
-"record"
-"producer"
-"recquired"
-"required"
-"recrational"
-"recreational"
-"recrod"
-"record"
-"recuiting"
-"recruiting"
-"recuring"
-"recurring"
-"recurrance"
-"recurrence"
-"rediculous"
-"ridiculous"
-"reedeming"
-"redeeming"
-"reenforced"
-"reinforced"
-"refect"
-"reflect"
-"refedendum"
-"referendum"
-"referal"
-"referral"
-"refered"
-"referred"
-"referiang"
-"referring"
-"refering"
-"referring"
-"refernces"
-"references"
-"referrence"
-"reference"
-"referrs"
-"refers"
-"reffered"
-"referred"
-"refference"
-"reference"
-"refrence"
-"reference"
-"refrences"
-"references"
-"refrers"
-"refers"
-"refridgeration"
-"refrigeration"
-"refridgerator"
-"refrigerator"
-"refromist"
-"reformist"
-"refusla"
-"refusal"
-"regardes"
-"regards"
-"regluar"
-"regular"
-"reguarly"
-"regularly"
-"regulaion"
-"regulation"
-"regulaotrs"
-"regulators"
-"regularily"
-"regularly"
-"rehersal"
-"rehearsal"
-"reicarnation"
-"reincarnation"
-"reigining"
-"reigning"
-"reknown"
-"renown"
-"reknowned"
-"renowned"
-"rela"
-"real"
-"relaly"
-"really"
-"relatiopnship"
-"relationship"
-"relativly"
-"relatively"
-"relected"
-"reelected"
-"releive"
-"relieve"
-"releived"
-"relieved"
-"releiver"
-"reliever"
-"releses"
-"releases"
-"relevence"
-"relevance"
-"relevent"
-"relevant"
-"reliablity"
-"reliability"
-"relient"
-"reliant"
-"religeous"
-"religious"
-"religous"
-"religious"
-"religously"
-"religiously"
-"relinqushment"
-"relinquishment"
-"relitavely"
-"relatively"
-"relized"
-"realised,"
-"realized"
-"relpacement"
-"replacement"
-"remaing"
-"remaining"
-"remeber"
-"remember"
-"rememberable"
-"memorable"
-"rememberance"
-"remembrance"
-"remembrence"
-"remembrance"
-"remenant"
-"remnant"
-"remenicent"
-"reminiscent"
-"reminent"
-"remnant"
-"reminescent"
-"reminiscent"
-"reminscent"
-"reminiscent"
-"reminsicent"
-"reminiscent"
-"rendevous"
-"rendezvous"
-"rendezous"
-"rendezvous"
-"renedered"
-"rende"
-"renewl"
-"renewal"
-"rentors"
-"renters"
-"reoccurrence"
-"recurrence"
-"reorganision"
-"reorganisation"
-"repatition"
-"repetition,"
-"repartition"
-"repentence"
-"repentance"
-"repentent"
-"repentant"
-"repeteadly"
-"repeatedly"
-"repetion"
-"repetition"
-"repid"
-"rapid"
-"reponse"
-"response"
-"reponsible"
-"responsible"
-"reportadly"
-"reportedly"
-"represantative"
-"representative"
-"representive"
-"representative"
-"representives"
-"representatives"
-"reproducable"
-"reproducible"
-"reprtoire"
-"repertoire"
-"repsectively"
-"respectively"
-"reptition"
-"repetition"
-"requirment"
-"requirement"
-"requred"
-"required"
-"resaurant"
-"restaurant"
-"resembelance"
-"resemblance"
-"resembes"
-"resembles"
-"resemblence"
-"resemblance"
-"resevoir"
-"reservoir"
-"resignement"
-"resignment"
-"resistable"
-"resistible"
-"resistence"
-"resistance"
-"resistent"
-"resistant"
-"respectivly"
-"respectively"
-"responce"
-"response"
-"responibilities"
-"responsibilities"
-"responisble"
-"responsible"
-"responnsibilty"
-"responsibility"
-"responsability"
-"responsibility"
-"responsibile"
-"responsible"
-"responsibilites"
-"responsibilities"
-"responsiblity"
-"responsibility"
-"ressemblance"
-"resemblance"
-"ressemble"
-"resemble"
-"ressembled"
-"resembled"
-"ressemblence"
-"resemblance"
-"ressembling"
-"resembling"
-"resssurecting"
-"resurrecting"
-"ressurect"
-"resurrect"
-"ressurected"
-"resurrected"
-"ressurection"
-"resurrection"
-"ressurrection"
-"resurrection"
-"restaraunt"
-"restaurant"
-"restaraunteur"
-"restaurateur"
-"restaraunteurs"
-"restaurateurs"
-"restaraunts"
-"restaurants"
-"restauranteurs"
-"restaurateurs"
-"restauration"
-"restoration"
-"restauraunt"
-"restaurant"
-"resteraunt"
-"restaurant"
-"resteraunts"
-"restaurants"
-"resticted"
-"restricted"
-"restraunt"
-"restraint,"
-"restaurant"
-"resturant"
-"restaurant"
-"resturaunt"
-"restaurant"
-"resurecting"
-"resurrecting"
-"retalitated"
-"retaliated"
-"retalitation"
-"retaliation"
-"retreive"
-"retrieve"
-"returnd"
-"returned"
-"revaluated"
-"reevaluated"
-"reveral"
-"reversal"
-"reversable"
-"reversible"
-"revolutionar"
-"revolutionary"
-"rewitten"
-"rewritten"
-"rewriet"
-"rewrite"
-"rhymme"
-"rhyme"
-"rhythem"
-"rhythm"
-"rhythim"
-"rhythm"
-"rhytmic"
-"rhythmic"
-"rigeur"
-"rigueur,"
-"rigour,"
-"rigor"
-"rigourous"
-"rigorous"
-"rininging"
-"ringing"
-"rised"
-"rose"
-"Rockerfeller"
-"Rockefeller"
-"rococco"
-"rococo"
-"rocord"
-"record"
-"roomate"
-"roommate"
-"rougly"
-"roughly"
-"rucuperate"
-"recuperate"
-"rudimentatry"
-"rudimentary"
-"rulle"
-"rule"
-"runing"
-"running"
-"runnung"
-"running"
-"russina"
-"Russian"
-"Russion"
-"Russian"
-"rwite"
-"write"
-"rythem"
-"rhythm"
-"rythim"
-"rhythm"
-"rythm"
-"rhythm"
-"rythmic"
-"rhythmic"
-"rythyms"
-"rhythms"
-"sacrafice"
-"sacrifice"
-"sacreligious"
-"sacrilegious"
-"sacrifical"
-"sacrificial"
-"saftey"
-"safety"
-"safty"
-"safety"
-"salery"
-"salary"
-"sanctionning"
-"sanctioning"
-"sandwhich"
-"sandwich"
-"Sanhedrim"
-"Sanhedrin"
-"santioned"
-"sanctioned"
-"sargant"
-"sergeant"
-"sargeant"
-"sergeant"
-"sasy"
-"says,"
-"sassy"
-"satelite"
-"satellite"
-"satelites"
-"satellites"
-"Saterday"
-"Saturday"
-"Saterdays"
-"Saturdays"
-"satisfactority"
-"satisfactorily"
-"satric"
-"satiric"
-"satrical"
-"satirical"
-"satrically"
-"satirically"
-"sattelite"
-"satellite"
-"sattelites"
-"satellites"
-"saught"
-"sought"
-"saveing"
-"saving"
-"saxaphone"
-"saxophone"
-"scaleable"
-"scalable"
-"scandanavia"
-"Scandinavia"
-"scaricity"
-"scarcity"
-"scavanged"
-"scavenged"
-"schedual"
-"schedule"
-"scholarhip"
-"scholarship"
-"scholarstic"
-"scholastic,"
-"scholarly"
-"scientfic"
-"scientific"
-"scientifc"
-"scientific"
-"scientis"
-"scientist"
-"scince"
-"science"
-"scinece"
-"science"
-"scirpt"
-"script"
-"scoll"
-"scroll"
-"screenwrighter"
-"screenwriter"
-"scrutinity"
-"scrutiny"
-"scuptures"
-"sculptures"
-"seach"
-"search"
-"seached"
-"searched"
-"seaches"
-"searches"
-"secceeded"
-"seceded,"
-"succeeded"
-"seceed"
-"succeed,"
-"secede"
-"seceeded"
-"succeeded,"
-"seceded"
-"secratary"
-"secretary"
-"secretery"
-"secretary"
-"sedereal"
-"sidereal"
-"seeked"
-"sought"
-"segementation"
-"segmentation"
-"seguoys"
-"segues"
-"seige"
-"siege"
-"seing"
-"seeing"
-"seinor"
-"senior"
-"seldomly"
-"seldom"
-"senarios"
-"scenarios"
-"sence"
-"sense"
-"senstive"
-"sensitive"
-"sensure"
-"censure"
-"seperate"
-"separate"
-"seperated"
-"separated"
-"seperately"
-"separately"
-"seperates"
-"separates"
-"seperating"
-"separating"
-"seperation"
-"separation"
-"seperatism"
-"separatism"
-"seperatist"
-"separatist"
-"sepina"
-"subpoena"
-"sepulchure"
-"sepulchre,"
-"sepulcher"
-"sepulcre"
-"sepulchre,"
-"sepulcher"
-"sergent"
-"sergeant"
-"settelement"
-"settlement"
-"settlment"
-"settlement"
-"severeal"
-"several"
-"severley"
-"severely"
-"severly"
-"severely"
-"sevice"
-"service"
-"shaddow"
-"shadow"
-"shamen"
-"shaman,"
-"shamans"
-"sheat"
-"sheath,"
-"sheet,"
-"cheat"
-"sheild"
-"shield"
-"sherif"
-"sheriff"
-"shineing"
-"shining"
-"shiped"
-"shipped"
-"shiping"
-"shipping"
-"shopkeeepers"
-"shopkeepers"
-"shorly"
-"shortly"
-"shortwhile"
-"short"
-"while"
-"shoudl"
-"should"
-"shoudln"
-"should,"
-"shouldn't"
-"shouldnt"
-"shouldn't"
-"shreak"
-"shriek"
-"shrinked"
-"shrunk"
-"sicne"
-"since"
-"sideral"
-"sidereal"
-"sieze"
-"seize,"
-"size"
-"siezed"
-"seized,"
-"sized"
-"siezing"
-"seizing,"
-"sizing"
-"siezure"
-"seizure"
-"siezures"
-"seizures"
-"siginificant"
-"significant"
-"signficant"
-"significant"
-"signficiant"
-"significant"
-"signfies"
-"signifies"
-"signifantly"
-"significantly"
-"significently"
-"significantly"
-"signifigant"
-"significant"
-"signifigantly"
-"significantly"
-"signitories"
-"signatories"
-"signitory"
-"signatory"
-"similarily"
-"similarly"
-"similiar"
-"similar"
-"similiarity"
-"similarity"
-"similiarly"
-"similarly"
-"simmilar"
-"similar"
-"simpley"
-"simply"
-"simplier"
-"simpler"
-"simultanous"
-"simultaneous"
-"simultanously"
-"simultaneously"
-"sincerley"
-"sincerely"
-"singsog"
-"singsong"
-"sinse"
-"sines,"
-"since"
-"Sionist"
-"Zionist"
-"Sionists"
-"Zionists"
-"Sixtin"
-"Sistine"
-"Skagerak"
-"Skagerrak"
-"skateing"
-"skating"
-"slaugterhouses"
-"slaughterhouses"
-"slowy"
-"slowly"
-"smae"
-"same"
-"smealting"
-"smelting"
-"smoe"
-"some"
-"sneeks"
-"sneaks"
-"snese"
-"sneeze"
-"socalism"
-"socialism"
-"socities"
-"societies"
-"soem"
-"some"
-"sofware"
-"software"
-"sohw"
-"show"
-"soilders"
-"soldiers"
-"solatary"
-"solitary"
-"soley"
-"solely"
-"soliders"
-"soldiers"
-"soliliquy"
-"soliloquy"
-"soluable"
-"soluble"
-"somene"
-"someone"
-"somtimes"
-"sometimes"
-"somwhere"
-"somewhere"
-"sophicated"
-"sophisticated"
-"sorceror"
-"sorcerer"
-"sorrounding"
-"surrounding"
-"sotry"
-"story"
-"sotyr"
-"satyr,"
-"story"
-"soudn"
-"sound"
-"soudns"
-"sounds"
-"sould"
-"could,"
-"should,"
-"sold"
-"sountrack"
-"soundtrack"
-"sourth"
-"south"
-"sourthern"
-"southern"
-"souvenier"
-"souvenir"
-"souveniers"
-"souvenirs"
-"soveits"
-"soviets"
-"sovereignity"
-"sovereignty"
-"soverign"
-"sovereign"
-"soverignity"
-"sovereignty"
-"soverignty"
-"sovereignty"
-"spainish"
-"Spanish"
-"speach"
-"speech"
-"specfic"
-"specific"
-"speciallized"
-"specialised,"
-"specialized"
-"specif"
-"specific,"
-"specify"
-"specifiying"
-"specifying"
-"speciman"
-"specimen"
-"spectauclar"
-"spectacular"
-"spectaulars"
-"spectaculars"
-"spects"
-"aspects,"
-"expects"
-"spectum"
-"spectrum"
-"speices"
-"species"
-"spendour"
-"splendour"
-"spermatozoan"
-"spermatozoon"
-"spoace"
-"space"
-"sponser"
-"sponsor"
-"sponsered"
-"sponsored"
-"spontanous"
-"spontaneous"
-"sponzored"
-"sponsored"
-"spoonfulls"
-"spoonfuls"
-"sppeches"
-"speeches"
-"spreaded"
-"spread"
-"sprech"
-"speech"
-"spred"
-"spread"
-"spriritual"
-"spiritual"
-"spritual"
-"spiritual"
-"sqaure"
-"square"
-"stablility"
-"stability"
-"stainlees"
-"stainless"
-"staion"
-"station"
-"standars"
-"standards"
-"stange"
-"strange"
-"startegic"
-"strategic"
-"startegies"
-"strategies"
-"startegy"
-"strategy"
-"stateman"
-"statesman"
-"statememts"
-"statements"
-"statment"
-"statement"
-"steriods"
-"steroids"
-"sterotypes"
-"stereotypes"
-"stilus"
-"stylus"
-"stingent"
-"stringent"
-"stiring"
-"stirring"
-"stirrs"
-"stirs"
-"stlye"
-"style"
-"stong"
-"strong"
-"stopry"
-"story"
-"storeis"
-"stories"
-"storise"
-"stories"
-"stornegst"
-"strongest"
-"stoyr"
-"story"
-"stpo"
-"stop"
-"stradegies"
-"strategies"
-"stradegy"
-"strategy"
-"strat"
-"start,"
-"strata"
-"stratagically"
-"strategically"
-"streemlining"
-"streamlining"
-"stregth"
-"strength"
-"strenghen"
-"strengthen"
-"strenghened"
-"strengthened"
-"strenghening"
-"strengthening"
-"strenght"
-"strength"
-"strenghten"
-"strengthen"
-"strenghtened"
-"strengthened"
-"strenghtening"
-"strengthening"
-"strengtened"
-"strengthened"
-"strenous"
-"strenuous"
-"strictist"
-"strictest"
-"strikely"
-"strikingly"
-"strnad"
-"strand"
-"stroy"
-"story,"
-"destroy"
-"structual"
-"structural"
-"stubborness"
-"stubbornness"
-"stucture"
-"structure"
-"stuctured"
-"structured"
-"studdy"
-"study"
-"studing"
-"studying"
-"stuggling"
-"struggling"
-"sturcture"
-"structure"
-"subcatagories"
-"subcategories"
-"subcatagory"
-"subcategory"
-"subconsiously"
-"subconsciously"
-"subjudgation"
-"subjugation"
-"submachne"
-"submachine"
-"subpecies"
-"subspecies"
-"subsidary"
-"subsidiary"
-"subsiduary"
-"subsidiary"
-"subsquent"
-"subsequent"
-"subsquently"
-"subsequently"
-"substace"
-"substance"
-"substancial"
-"substantial"
-"substatial"
-"substantial"
-"substituded"
-"substituted"
-"substract"
-"subtract"
-"substracted"
-"subtracted"
-"substracting"
-"subtracting"
-"substraction"
-"subtraction"
-"substracts"
-"subtracts"
-"subtances"
-"substances"
-"subterranian"
-"subterranean"
-"suburburban"
-"suburban"
-"succceeded"
-"succeeded"
-"succcesses"
-"successes"
-"succedded"
-"succeeded"
-"succeded"
-"succeeded"
-"succeds"
-"succeeds"
-"succesful"
-"successful"
-"succesfully"
-"successfully"
-"succesfuly"
-"successfully"
-"succesion"
-"succession"
-"succesive"
-"successive"
-"successfull"
-"successful"
-"successully"
-"successfully"
-"succsess"
-"success"
-"succsessfull"
-"successful"
-"suceed"
-"succeed"
-"suceeded"
-"succeeded"
-"suceeding"
-"succeeding"
-"suceeds"
-"succeeds"
-"sucesful"
-"successful"
-"sucesfully"
-"successfully"
-"sucesfuly"
-"successfully"
-"sucesion"
-"succession"
-"sucess"
-"success"
-"sucesses"
-"successes"
-"sucessful"
-"successful"
-"sucessfull"
-"successful"
-"sucessfully"
-"successfully"
-"sucessfuly"
-"successfully"
-"sucession"
-"succession"
-"sucessive"
-"successive"
-"sucessor"
-"successor"
-"sucessot"
-"successor"
-"sucide"
-"suicide"
-"sucidial"
-"suicidal"
-"sufferage"
-"suffrage"
-"sufferred"
-"suffered"
-"sufferring"
-"suffering"
-"sufficent"
-"sufficient"
-"sufficently"
-"sufficiently"
-"sumary"
-"summary"
-"sunglases"
-"sunglasses"
-"suop"
-"soup"
-"superceeded"
-"superseded"
-"superintendant"
-"superintendent"
-"suphisticated"
-"sophisticated"
-"suplimented"
-"supplemented"
-"supose"
-"suppose"
-"suposed"
-"supposed"
-"suposedly"
-"supposedly"
-"suposes"
-"supposes"
-"suposing"
-"supposing"
-"supplamented"
-"supplemented"
-"suppliementing"
-"supplementing"
-"suppoed"
-"supposed"
-"supposingly"
-"supposedly"
-"suppy"
-"supply"
-"supress"
-"suppress"
-"supressed"
-"suppressed"
-"supresses"
-"suppresses"
-"supressing"
-"suppressing"
-"suprise"
-"surprise"
-"suprised"
-"surprised"
-"suprising"
-"surprising"
-"suprisingly"
-"surprisingly"
-"suprize"
-"surprise"
-"suprized"
-"surprised"
-"suprizing"
-"surprising"
-"suprizingly"
-"surprisingly"
-"surfce"
-"surface"
-"surley"
-"surly,"
-"surely"
-"suround"
-"surround"
-"surounded"
-"surrounded"
-"surounding"
-"surrounding"
-"suroundings"
-"surroundings"
-"surounds"
-"surrounds"
-"surplanted"
-"supplanted"
-"surpress"
-"suppress"
-"surpressed"
-"suppressed"
-"surprize"
-"surprise"
-"surprized"
-"surprised"
-"surprizing"
-"surprising"
-"surprizingly"
-"surprisingly"
-"surrended"
-"surrounded,"
-"surrendered"
-"surrepetitious"
-"surreptitious"
-"surrepetitiously"
-"surreptitiously"
-"surreptious"
-"surreptitious"
-"surreptiously"
-"surreptitiously"
-"surronded"
-"surrounded"
-"surrouded"
-"surrounded"
-"surrouding"
-"surrounding"
-"surrundering"
-"surrendering"
-"surveilence"
-"surveillance"
-"surveill"
-"surveil"
-"surveyer"
-"surveyor"
-"surviver"
-"survivor"
-"survivers"
-"survivors"
-"survivied"
-"survived"
-"suseptable"
-"susceptible"
-"suseptible"
-"susceptible"
-"suspention"
-"suspension"
-"swaer"
-"swear"
-"swaers"
-"swears"
-"swepth"
-"swept"
-"swiming"
-"swimming"
-"syas"
-"says"
-"symetrical"
-"symmetrical"
-"symetrically"
-"symmetrically"
-"symetry"
-"symmetry"
-"symettric"
-"symmetric"
-"symmetral"
-"symmetric"
-"symmetricaly"
-"symmetrically"
-"synagouge"
-"synagogue"
-"syncronization"
-"synchronization"
-"synonomous"
-"synonymous"
-"synonymns"
-"synonyms"
-"synphony"
-"symphony"
-"syphyllis"
-"syphilis"
-"sypmtoms"
-"symptoms"
-"syrap"
-"syrup"
-"sysmatically"
-"systematically"
-"sytem"
-"system"
-"sytle"
-"style"
-"tabacco"
-"tobacco"
-"tahn"
-"than"
-"taht"
-"that"
-"talekd"
-"talked"
-"targetted"
-"targeted"
-"targetting"
-"targeting"
-"tast"
-"taste"
-"tath"
-"that"
-"tattooes"
-"tattoos"
-"taxanomic"
-"taxonomic"
-"taxanomy"
-"taxonomy"
-"teached"
-"taught"
-"techician"
-"technician"
-"techicians"
-"technicians"
-"techiniques"
-"techniques"
-"technitian"
-"technician"
-"technnology"
-"technology"
-"technolgy"
-"technology"
-"teh"
-"the"
-"tehy"
-"they"
-"telelevision"
-"television"
-"televsion"
-"television"
-"telphony"
-"telephony"
-"temerature"
-"temperature"
-"temparate"
-"temperate"
-"temperarily"
-"temporarily"
-"temperment"
-"temperament"
-"tempertaure"
-"temperature"
-"temperture"
-"temperature"
-"temprary"
-"temporary"
-"tenacle"
-"tentacle"
-"tenacles"
-"tentacles"
-"tendacy"
-"tendency"
-"tendancies"
-"tendencies"
-"tendancy"
-"tendency"
-"tennisplayer"
-"tennis"
-"player"
-"tepmorarily"
-"temporarily"
-"terrestial"
-"terrestrial"
-"terriories"
-"territories"
-"terriory"
-"territory"
-"territorist"
-"terrorist"
-"territoy"
-"territory"
-"terroist"
-"terrorist"
-"testiclular"
-"testicular"
-"tghe"
-"the"
-"thast"
-"that,"
-"that's"
-"theather"
-"theater,"
-"theatre"
-"theese"
-"these"
-"theif"
-"thief"
-"theives"
-"thieves"
-"themselfs"
-"themselves"
-"themslves"
-"themselves"
-"ther"
-"there,"
-"their,"
-"the"
-"therafter"
-"thereafter"
-"therby"
-"thereby"
-"theri"
-"their"
-"thgat"
-"that"
-"thge"
-"the"
-"thier"
-"their"
-"thign"
-"thing"
-"thigns"
-"things"
-"thigsn"
-"things"
-"thikn"
-"think"
-"thikning"
-"thinking,"
-"thickening"
-"thikns"
-"thinks"
-"thiunk"
-"think"
-"thn"
-"then"
-"thna"
-"than"
-"thne"
-"then"
-"thnig"
-"thing"
-"thnigs"
-"things"
-"thoughout"
-"throughout"
-"threatend"
-"threatened"
-"threatning"
-"threatening"
-"threee"
-"three"
-"threshhold"
-"threshold"
-"thrid"
-"third"
-"throrough"
-"thorough"
-"throughly"
-"thoroughly"
-"throught"
-"thought,"
-"through,"
-"throughout"
-"througout"
-"throughout"
-"thru"
-"through"
-"thsi"
-"this"
-"thsoe"
-"those"
-"thta"
-"that"
-"thyat"
-"that"
-"tiem"
-"time,"
-"Tim"
-"tihkn"
-"think"
-"tihs"
-"this"
-"timne"
-"time"
-"tiome"
-"time,"
-"tome"
-"tje"
-"the"
-"tjhe"
-"the"
-"tjpanishad"
-"upanishad"
-"tkae"
-"take"
-"tkaes"
-"takes"
-"tkaing"
-"taking"
-"tlaking"
-"talking"
-"tobbaco"
-"tobacco"
-"todays"
-"today's"
-"todya"
-"today"
-"toghether"
-"together"
-"tolerence"
-"tolerance"
-"Tolkein"
-"Tolkien"
-"tomatos"
-"tomatoes"
-"tommorow"
-"tomorrow"
-"tommorrow"
-"tomorrow"
-"tongiht"
-"tonight"
-"toriodal"
-"toroidal"
-"tormenters"
-"tormentors"
-"torpeados"
-"torpedoes"
-"torpedos"
-"torpedoes"
-"tothe"
-"to"
-"the"
-"toubles"
-"troubles"
-"tounge"
-"tongue"
-"tourch"
-"torch,"
-"touch"
-"towords"
-"towards"
-"towrad"
-"toward"
-"tradionally"
-"traditionally"
-"traditionaly"
-"traditionally"
-"traditionnal"
-"traditional"
-"traditition"
-"tradition"
-"tradtionally"
-"traditionally"
-"trafficed"
-"trafficked"
-"trafficing"
-"trafficking"
-"trafic"
-"traffic"
-"trancendent"
-"transcendent"
-"trancending"
-"transcending"
-"tranform"
-"transform"
-"tranformed"
-"transformed"
-"transcendance"
-"transcendence"
-"transcendant"
-"transcendent"
-"transcendentational"
-"transcendental"
-"transcripting"
-"transcribing,"
-"transcription"
-"transending"
-"transcending"
-"transesxuals"
-"transsexuals"
-"transfered"
-"transferred"
-"transfering"
-"transferring"
-"transformaton"
-"transformation"
-"transistion"
-"transition"
-"translater"
-"translator"
-"translaters"
-"translators"
-"transmissable"
-"transmissible"
-"transporation"
-"transportation"
-"tremelo"
-"tremolo"
-"tremelos"
-"tremolos"
-"triguered"
-"triggered"
-"triology"
-"trilogy"
-"troling"
-"trolling"
-"troup"
-"troupe"
-"troups"
-"troupes,"
-"troops"
-"truely"
-"truly"
-"trustworthyness"
-"trustworthiness"
-"turnk"
-"turnkey,"
-"trunk"
-"Tuscon"
-"Tucson"
-"tust"
-"trust"
-"twelth"
-"twelfth"
-"twon"
-"town"
-"twpo"
-"two"
-"tyhat"
-"that"
-"tyhe"
-"they"
-"typcial"
-"typical"
-"typicaly"
-"typically"
-"tyranies"
-"tyrannies"
-"tyrany"
-"tyranny"
-"tyrranies"
-"tyrannies"
-"tyrrany"
-"tyranny"
-"ubiquitious"
-"ubiquitous"
-"uise"
-"use"
-"Ukranian"
-"Ukrainian"
-"ultimely"
-"ultimately"
-"unacompanied"
-"unaccompanied"
-"unahppy"
-"unhappy"
-"unanymous"
-"unanimous"
-"unathorised"
-"unauthorised"
-"unavailible"
-"unavailable"
-"unballance"
-"unbalance"
-"unbeleivable"
-"unbelievable"
-"uncertainity"
-"uncertainty"
-"unchallengable"
-"unchallengeable"
-"unchangable"
-"unchangeable"
-"uncompetive"
-"uncompetitive"
-"unconcious"
-"unconscious"
-"unconciousness"
-"unconsciousness"
-"unconfortability"
-"discomfort"
-"uncontitutional"
-"unconstitutional"
-"unconvential"
-"unconventional"
-"undecideable"
-"undecidable"
-"understoon"
-"understood"
-"undesireable"
-"undesirable"
-"undetecable"
-"undetectable"
-"undoubtely"
-"undoubtedly"
-"undreground"
-"underground"
-"uneccesary"
-"unnecessary"
-"unecessary"
-"unnecessary"
-"unequalities"
-"inequalities"
-"unforetunately"
-"unfortunately"
-"unforgetable"
-"unforgettable"
-"unforgiveable"
-"unforgivable"
-"unfortunatley"
-"unfortunately"
-"unfortunatly"
-"unfortunately"
-"unfourtunately"
-"unfortunately"
-"unihabited"
-"uninhabited"
-"unilateraly"
-"unilaterally"
-"unilatreal"
-"unilateral"
-"unilatreally"
-"unilaterally"
-"uninterruped"
-"uninterrupted"
-"uninterupted"
-"uninterrupted"
-"UnitesStates"
-"UnitedStates"
-"univeral"
-"universal"
-"univeristies"
-"universities"
-"univeristy"
-"university"
-"universtiy"
-"university"
-"univesities"
-"universities"
-"univesity"
-"university"
-"unkown"
-"unknown"
-"unlikey"
-"unlikely"
-"unmanouverable"
-"unmaneuverable,"
-"unmanoeuvrable"
-"unmistakeably"
-"unmistakably"
-"unneccesarily"
-"unnecessarily"
-"unneccesary"
-"unnecessary"
-"unneccessarily"
-"unnecessarily"
-"unneccessary"
-"unnecessary"
-"unnecesarily"
-"unnecessarily"
-"unnecesary"
-"unnecessary"
-"unoffical"
-"unofficial"
-"unoperational"
-"nonoperational"
-"unoticeable"
-"unnoticeable"
-"unplease"
-"displease"
-"unplesant"
-"unpleasant"
-"unprecendented"
-"unprecedented"
-"unprecidented"
-"unprecedented"
-"unrepentent"
-"unrepentant"
-"unrepetant"
-"unrepentant"
-"unrepetent"
-"unrepentant"
-"unsed"
-"used,"
-"unused,"
-"unsaid"
-"unsubstanciated"
-"unsubstantiated"
-"unsuccesful"
-"unsuccessful"
-"unsuccesfully"
-"unsuccessfully"
-"unsuccessfull"
-"unsuccessful"
-"unsucesful"
-"unsuccessful"
-"unsucesfuly"
-"unsuccessfully"
-"unsucessful"
-"unsuccessful"
-"unsucessfull"
-"unsuccessful"
-"unsucessfully"
-"unsuccessfully"
-"unsuprised"
-"unsurprised"
-"unsuprising"
-"unsurprising"
-"unsuprisingly"
-"unsurprisingly"
-"unsuprized"
-"unsurprised"
-"unsuprizing"
-"unsurprising"
-"unsuprizingly"
-"unsurprisingly"
-"unsurprized"
-"unsurprised"
-"unsurprizing"
-"unsurprising"
-"unsurprizingly"
-"unsurprisingly"
-"untill"
-"until"
-"untranslateable"
-"untranslatable"
-"unuseable"
-"unusable"
-"unusuable"
-"unusable"
-"unviersity"
-"university"
-"unwarrented"
-"unwarranted"
-"unweildly"
-"unwieldy"
-"unwieldly"
-"unwieldy"
-"upcomming"
-"upcoming"
-"upgradded"
-"upgraded"
-"usally"
-"usually"
-"useage"
-"usage"
-"usefull"
-"useful"
-"usefuly"
-"usefully"
-"useing"
-"using"
-"usualy"
-"usually"
-"ususally"
-"usually"
-"vaccum"
-"vacuum"
-"vaccume"
-"vacuum"
-"vacinity"
-"vicinity"
-"vaguaries"
-"vagaries"
-"vaieties"
-"varieties"
-"vailidty"
-"validity"
-"valetta"
-"valletta"
-"valuble"
-"valuable"
-"valueable"
-"valuable"
-"varations"
-"variations"
-"varient"
-"variant"
-"variey"
-"variety"
-"varing"
-"varying"
-"varities"
-"varieties"
-"varity"
-"variety"
-"vasall"
-"vassal"
-"vasalls"
-"vassals"
-"vegatarian"
-"vegetarian"
-"vegitable"
-"vegetable"
-"vegitables"
-"vegetables"
-"vegtable"
-"vegetable"
-"vehicule"
-"vehicle"
-"vell"
-"well"
-"venemous"
-"venomous"
-"vengance"
-"vengeance"
-"vengence"
-"vengeance"
-"verfication"
-"verification"
-"verison"
-"version"
-"verisons"
-"versions"
-"vermillion"
-"vermilion"
-"versitilaty"
-"versatility"
-"versitlity"
-"versatility"
-"vetween"
-"between"
-"veyr"
-"very"
-"vigeur"
-"vigueur,"
-"vigour,"
-"vigor"
-"vigilence"
-"vigilance"
-"vigourous"
-"vigorous"
-"villian"
-"villain"
-"villification"
-"vilification"
-"villify"
-"vilify"
-"villin"
-"villi,"
-"villain,"
-"villein"
-"vincinity"
-"vicinity"
-"violentce"
-"violence"
-"virutal"
-"virtual"
-"virtualy"
-"virtually"
-"virutally"
-"virtually"
-"visable"
-"visible"
-"visably"
-"visibly"
-"visting"
-"visiting"
-"vistors"
-"visitors"
-"vitories"
-"victories"
-"volcanoe"
-"volcano"
-"voleyball"
-"volleyball"
-"volontary"
-"voluntary"
-"volonteer"
-"volunteer"
-"volonteered"
-"volunteered"
-"volonteering"
-"volunteering"
-"volonteers"
-"volunteers"
-"volounteer"
-"volunteer"
-"volounteered"
-"volunteered"
-"volounteering"
-"volunteering"
-"volounteers"
-"volunteers"
-"vreity"
-"variety"
-"vrey"
-"very"
-"vriety"
-"variety"
-"vulnerablility"
-"vulnerability"
-"vyer"
-"very"
-"vyre"
-"very"
-"waht"
-"what"
-"wanna"
-"want"
-"to"
-"warantee"
-"warranty"
-"wardobe"
-"wardrobe"
-"warrent"
-"warrant"
-"warrriors"
-"warriors"
-"wasnt"
-"wasn't"
-"wass"
-"was"
-"watn"
-"want"
-"wayword"
-"wayward"
-"weaponary"
-"weaponry"
-"weas"
-"was"
-"wehn"
-"when"
-"weild"
-"wield,"
-"wild"
-"weilded"
-"wielded"
-"wendsay"
-"Wednesday"
-"wensday"
-"Wednesday"
-"wereabouts"
-"whereabouts"
-"whant"
-"want"
-"whants"
-"wants"
-"whcih"
-"which"
-"wheras"
-"whereas"
-"wherease"
-"whereas"
-"whereever"
-"wherever"
-"whic"
-"which"
-"whihc"
-"which"
-"whith"
-"with"
-"whlch"
-"which"
-"whn"
-"when"
-"wholey"
-"wholly"
-"wholy"
-"wholly,"
-"holy"
-"whta"
-"what"
-"whther"
-"whether"
-"wich"
-"which,"
-"witch"
-"widesread"
-"widespread"
-"wief"
-"wife"
-"wierd"
-"weird"
-"wiew"
-"view"
-"wih"
-"with"
-"wiht"
-"with"
-"wille"
-"will"
-"willingless"
-"willingness"
-"wirting"
-"writing"
-"withdrawl"
-"withdrawal,"
-"withdraw"
-"witheld"
-"withheld"
-"withing"
-"within"
-"withold"
-"withhold"
-"witht"
-"with"
-"witn"
-"with"
-"wiull"
-"will"
-"wnat"
-"want"
-"wnated"
-"wanted"
-"wnats"
-"wants"
-"wohle"
-"whole"
-"wokr"
-"work"
-"wokring"
-"working"
-"wonderfull"
-"wonderful"
-"workststion"
-"workstation"
-"worls"
-"world"
-"wordlwide"
-"worldwide"
-"worshipper"
-"worshiper"
-"worshipping"
-"worshiping"
-"worstened"
-"worsened"
-"woudl"
-"would"
-"wresters"
-"wrestlers"
-"wriet"
-"write"
-"writen"
-"written"
-"wroet"
-"wrote"
-"wrok"
-"work"
-"wroking"
-"working"
-"ws"
-"was"
-"wtih"
-"with"
-"wupport"
-"support"
-"xenophoby"
-"xenophobia"
-"yaching"
-"yachting"
-"yatch"
-"yacht"
-"yeasr"
-"years"
-"yeild"
-"yield"
-"yeilding"
-"yielding"
-"Yementite"
-"Yemenite,"
-"Yemeni"
-"yearm"
-"year"
-"yera"
-"year"
-"yeras"
-"years"
-"yersa"
-"years"
-"youseff"
-"yousef"
-"youself"
-"yourself"
-"ytou"
-"you"
-"yuo"
-"you"
-"joo"
-"you"
-"zeebra"
-"zebra"
diff --git a/chromium/third_party/hunspell/fuzz/hunspell_fuzzer.cc b/chromium/third_party/hunspell/fuzz/hunspell_fuzzer.cc
deleted file mode 100644
index 7efda6c254a..00000000000
--- a/chromium/third_party/hunspell/fuzz/hunspell_fuzzer.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string>
-
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "third_party/hunspell/src/hunspell/hunspell.hxx"
-#include "third_party/hunspell/fuzz/hunspell_fuzzer_hunspell_dictionary.h"
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- if (!size)
- return 0;
-
- static Hunspell* hunspell = new Hunspell(kHunspellDictionary,
- sizeof(kHunspellDictionary));
-
- std::string data_string(reinterpret_cast<const char*>(data), size);
-
- // hunspell is not handling invalid UTF8. To avoid that, do the same thing
- // Chromium does - convert to UTF16, and back to UTF8. Valid UTF8 guaranteed.
- base::string16 utf16_string = base::UTF8ToUTF16(data_string);
- data_string = base::UTF16ToUTF8(utf16_string);
-
- hunspell->spell(data_string);
-
- std::vector<std::string> suggestions =
- hunspell->suggest(data_string);
-
- return 0;
-}
diff --git a/chromium/third_party/hunspell/fuzz/hunspell_fuzzer_hunspell_dictionary.h b/chromium/third_party/hunspell/fuzz/hunspell_fuzzer_hunspell_dictionary.h
deleted file mode 100644
index b6f73c1886a..00000000000
--- a/chromium/third_party/hunspell/fuzz/hunspell_fuzzer_hunspell_dictionary.h
+++ /dev/null
@@ -1,37212 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_HUNSPELL_FUZZ_HUNSPELL_FUZZER_HUNSPELL_DICTIONARY_H_
-#define THIRD_PARTY_HUNSPELL_FUZZ_HUNSPELL_FUZZER_HUNSPELL_DICTIONARY_H_
-
-// The following dictionary has been taken from
-// "third_party/hunspell_dictionaries/en_US-7-1.bdic".
-// The license block is:
-
-/* ***** BEGIN LICENSE BLOCK *****
-* Version: GPL 2.0/LGPL 2.1/MPL 1.1 tri-license
-*
-* The contents of this software may be used under the terms of
-* the GNU General Public License Version 2 or later (the "GPL"), or
-* the GNU Lesser General Public License Version 2.1 or later (the "LGPL",
-* see COPYING.LGPL) or (excepting the LGPLed GNU gettext library in the
-* intl/ directory) the Mozilla Public License Version 1.1 or later
-* (the "MPL", see COPYING.MPL).
-*
-* Software distributed under these licenses is distributed on an "AS IS" basis,
-* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the licences
-* for the specific language governing rights and limitations under the licenses.
-*
-* ***** END LICENSE BLOCK ***** */
-
-
-// TODO(mmoroz): Add other dictionaries. https://crbug.com/584819.
-static const unsigned char kHunspellDictionary[] = {
- 0x42, 0x44, 0x69, 0x63, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x96, 0x36, 0x00, 0x00, 0xc8, 0x79, 0xec, 0xc1, 0xf1, 0xac, 0x2b, 0x63,
- 0xda, 0x5f, 0xcd, 0x10, 0x60, 0x13, 0x28, 0xa4, 0x32, 0x00, 0x00, 0x00,
- 0x6b, 0x2f, 0x00, 0x00, 0xab, 0x33, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00,
- 0x0a, 0x0a, 0x41, 0x46, 0x20, 0x31, 0x33, 0x36, 0x30, 0x00, 0x41, 0x46,
- 0x20, 0x6e, 0x6d, 0x00, 0x41, 0x46, 0x20, 0x70, 0x74, 0x00, 0x41, 0x46,
- 0x20, 0x6e, 0x31, 0x00, 0x41, 0x46, 0x20, 0x70, 0x00, 0x41, 0x46, 0x20,
- 0x74, 0x63, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4e, 0x52, 0x00, 0x41, 0x46, 0x20, 0x47,
- 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4e, 0x54, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x48, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x5a, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4a, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x54, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x52, 0x5a, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4e,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x52, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x56, 0x00,
- 0x41, 0x46, 0x20, 0x58, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4e, 0x58, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4e, 0x52, 0x42, 0x00, 0x41, 0x46, 0x20,
- 0x42, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x53, 0x4d, 0x52, 0x00, 0x41, 0x46,
- 0x20, 0x50, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x4e, 0x47, 0x4a,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x47, 0x42, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x5a, 0x52, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d,
- 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x52, 0x4d, 0x5a, 0x00, 0x41, 0x46,
- 0x20, 0x5a, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x44, 0x54, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x4e,
- 0x58, 0x54, 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x59, 0x00, 0x41, 0x46,
- 0x20, 0x4c, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4c, 0x47, 0x44,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4c, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x55, 0x59, 0x00, 0x41, 0x46, 0x20, 0x55, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x53, 0x47, 0x4e, 0x58, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4e, 0x44,
- 0x53, 0x58, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x59, 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x49, 0x45, 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20, 0x59, 0x50, 0x00, 0x41,
- 0x46, 0x20, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x58,
- 0x47, 0x4e, 0x56, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x54, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x4e, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47,
- 0x56, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x50, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x58, 0x47, 0x4e, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x54, 0x50, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x53, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x53, 0x44, 0x52, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x59, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x4d, 0x59,
- 0x54, 0x4e, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x47, 0x44, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x52, 0x5a, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x50, 0x59, 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x50, 0x4d, 0x44, 0x59,
- 0x00, 0x41, 0x46, 0x20, 0x45, 0x47, 0x56, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4e, 0x58, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x42, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x49, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x49, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x59, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x53, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53,
- 0x4c, 0x47, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d, 0x44, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x44, 0x53, 0x42, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x49, 0x59, 0x00, 0x41, 0x46, 0x20,
- 0x50, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x4d, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x42, 0x4c, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x54, 0x52, 0x00, 0x41, 0x46, 0x20, 0x41, 0x47, 0x53, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x5a, 0x47, 0x42, 0x44, 0x52, 0x53, 0x4c, 0x00, 0x41, 0x46,
- 0x20, 0x50, 0x54, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x44,
- 0x47, 0x56, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x49, 0x43, 0x41, 0x4e, 0x47, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20,
- 0x49, 0x43, 0x41, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x49, 0x4b, 0x59, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20, 0x50, 0x4d,
- 0x59, 0x54, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x5a, 0x47, 0x56,
- 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x52, 0x42, 0x5a,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x47, 0x56, 0x4d, 0x44, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x50, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x44, 0x47, 0x4c,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4e, 0x56, 0x58, 0x44, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x47, 0x44, 0x53, 0x4c, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x58, 0x44, 0x53, 0x47, 0x4e,
- 0x56, 0x00, 0x41, 0x46, 0x20, 0x42, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x00, 0x41, 0x46, 0x20, 0x4c, 0x44, 0x53, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x47, 0x56, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4c, 0x44, 0x53, 0x4d,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x45, 0x44, 0x53, 0x4d, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x45, 0x59, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x4d,
- 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x52, 0x59, 0x54, 0x00, 0x41,
- 0x46, 0x20, 0x4c, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x4c, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x42, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x47, 0x44, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x45, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x45, 0x47, 0x4e,
- 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x47, 0x44, 0x53, 0x42, 0x00, 0x41, 0x46, 0x20, 0x45, 0x47, 0x53,
- 0x44, 0x00, 0x41, 0x46, 0x20, 0x52, 0x5a, 0x00, 0x41, 0x46, 0x20, 0x44,
- 0x53, 0x4d, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x4d, 0x47,
- 0x4e, 0x58, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x58, 0x47, 0x4e, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x47, 0x4e, 0x44, 0x53, 0x58, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x42, 0x4c, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x00,
- 0x41, 0x46, 0x20, 0x45, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x53, 0x44,
- 0x4c, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x4a, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x52,
- 0x53, 0x4d, 0x5a, 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x4d, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x50, 0x54, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4e,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x56, 0x00, 0x41, 0x46, 0x20,
- 0x47, 0x4d, 0x44, 0x59, 0x50, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x47,
- 0x4d, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x49, 0x55, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x4c, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53,
- 0x58, 0x47, 0x4e, 0x56, 0x00, 0x41, 0x46, 0x20, 0x41, 0x44, 0x53, 0x47,
- 0x4e, 0x00, 0x41, 0x46, 0x20, 0x4c, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x47, 0x4c, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x44, 0x53, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x47, 0x44, 0x42, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x53, 0x4d, 0x59, 0x47, 0x4e, 0x56, 0x58, 0x00, 0x41, 0x46, 0x20,
- 0x4c, 0x4d, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x5a, 0x47,
- 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4e, 0x56, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x42, 0x4c, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x53, 0x47, 0x42, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x44, 0x52,
- 0x53, 0x58, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x43, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x50,
- 0x4d, 0x52, 0x59, 0x54, 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x4c, 0x5a, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x47, 0x44, 0x4c, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d, 0x44,
- 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x53, 0x44,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x45, 0x41, 0x4d, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x58, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x41, 0x4e, 0x58, 0x47, 0x44,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x4c, 0x53, 0x56, 0x47, 0x44,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x47, 0x44, 0x4c, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x59, 0x4e, 0x56, 0x50, 0x00, 0x41, 0x46, 0x20, 0x47, 0x42, 0x4d,
- 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x49, 0x00, 0x41, 0x46, 0x20,
- 0x50, 0x59, 0x47, 0x4e, 0x58, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44,
- 0x53, 0x58, 0x59, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x49, 0x59, 0x50,
- 0x54, 0x00, 0x41, 0x46, 0x20, 0x50, 0x5a, 0x54, 0x47, 0x56, 0x4d, 0x44,
- 0x52, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x42, 0x00, 0x41,
- 0x46, 0x20, 0x45, 0x41, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x45, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x47, 0x53, 0x4c, 0x00, 0x41, 0x46, 0x20,
- 0x41, 0x45, 0x53, 0x44, 0x4c, 0x47, 0x00, 0x41, 0x46, 0x20, 0x45, 0x47,
- 0x4d, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x47, 0x4d, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x59, 0x47, 0x4e, 0x50, 0x44, 0x53, 0x58, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x44, 0x53, 0x42, 0x4c, 0x00, 0x41, 0x46, 0x20,
- 0x47, 0x42, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x4e, 0x53,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x4e, 0x58, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x44, 0x52, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45,
- 0x47, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x53, 0x21, 0x00, 0x41,
- 0x46, 0x20, 0x45, 0x44, 0x53, 0x47, 0x4e, 0x56, 0x00, 0x41, 0x46, 0x20,
- 0x42, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x4d, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x50, 0x59, 0x54, 0x52, 0x00, 0x41, 0x46, 0x20, 0x42,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x44, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x49, 0x50,
- 0x59, 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x56, 0x44, 0x42, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x53, 0x4d, 0x47, 0x4e, 0x56, 0x42, 0x58, 0x00, 0x41,
- 0x46, 0x20, 0x52, 0x59, 0x54, 0x00, 0x41, 0x46, 0x20, 0x55, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x59, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x53, 0x44, 0x47, 0x42, 0x00, 0x41, 0x46, 0x20, 0x45, 0x44, 0x47, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x55, 0x50, 0x00, 0x41, 0x46, 0x20, 0x52, 0x59,
- 0x50, 0x54, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4a, 0x53, 0x4d, 0x00, 0x41,
- 0x46, 0x20, 0x4b, 0x44, 0x54, 0x00, 0x41, 0x46, 0x20, 0x54, 0x47, 0x44,
- 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4a, 0x5a, 0x47, 0x4d,
- 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x52, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x52, 0x5a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x5a, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x50, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x59, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x5a, 0x52, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x47, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x4c, 0x00, 0x41,
- 0x46, 0x20, 0x50, 0x54, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x42,
- 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x55, 0x44, 0x53, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x54, 0x47, 0x50, 0x44, 0x52, 0x59, 0x00, 0x41,
- 0x46, 0x20, 0x52, 0x54, 0x00, 0x41, 0x46, 0x20, 0x52, 0x54, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x45, 0x53, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x44,
- 0x52, 0x53, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x4d, 0x44,
- 0x52, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x42, 0x4d, 0x44, 0x52,
- 0x00, 0x41, 0x46, 0x20, 0x45, 0x43, 0x55, 0x54, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x44,
- 0x52, 0x53, 0x50, 0x59, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x47, 0x4d, 0x44, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x44, 0x52, 0x5a, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x43, 0x53, 0x47,
- 0x44, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x4d, 0x52, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x47, 0x4a, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x45,
- 0x43, 0x00, 0x41, 0x46, 0x20, 0x54, 0x50, 0x53, 0x4d, 0x52, 0x00, 0x41,
- 0x46, 0x20, 0x45, 0x43, 0x55, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x53,
- 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x43, 0x44, 0x53, 0x4c, 0x54,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x43, 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x5a, 0x47, 0x4e, 0x58, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4b,
- 0x41, 0x43, 0x47, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x5a, 0x47,
- 0x53, 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4c, 0x44, 0x52, 0x53,
- 0x4d, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x52, 0x54, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x5a, 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x5a, 0x47, 0x42, 0x4a, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x54, 0x50,
- 0x52, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x42, 0x4d, 0x4e,
- 0x52, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x47, 0x58, 0x4e, 0x44, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x4e, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x47, 0x44, 0x53, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x4d,
- 0x5a, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x52, 0x50, 0x54, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x59,
- 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x4c,
- 0x00, 0x41, 0x46, 0x20, 0x4e, 0x52, 0x5a, 0x47, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x55, 0x4d, 0x00, 0x41,
- 0x46, 0x20, 0x45, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x45, 0x55, 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x44, 0x47, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x42, 0x53, 0x5a, 0x47, 0x4d, 0x52, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x44, 0x47, 0x4c, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4c,
- 0x53, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x52, 0x5a, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x58, 0x44,
- 0x53, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x44, 0x52,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x42, 0x4a, 0x47, 0x4d, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x48, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x55, 0x47,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x00, 0x41,
- 0x46, 0x20, 0x43, 0x53, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x4d,
- 0x52, 0x59, 0x54, 0x53, 0x00, 0x41, 0x46, 0x20, 0x50, 0x58, 0x54, 0x47,
- 0x4d, 0x44, 0x4e, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x53,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d, 0x47, 0x44, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x54, 0x47, 0x50, 0x4d, 0x44, 0x52, 0x59, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x44, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x50,
- 0x5a, 0x54, 0x47, 0x4d, 0x44, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x55, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x50, 0x54, 0x4d, 0x52,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x50, 0x54, 0x47, 0x44, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x52, 0x53, 0x50, 0x4d, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x54, 0x47, 0x50, 0x4d, 0x44, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x50, 0x54, 0x47, 0x44, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x54,
- 0x52, 0x50, 0x00, 0x41, 0x46, 0x20, 0x44, 0x4d, 0x00, 0x41, 0x46, 0x20,
- 0x55, 0x53, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x44,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x48, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x53, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x49, 0x41, 0x55,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x52, 0x5a, 0x47, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x55, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x47, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x4d, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x53, 0x4d, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x47, 0x4d, 0x44, 0x4e, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x50,
- 0x4d, 0x59, 0x44, 0x54, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x44,
- 0x52, 0x5a, 0x47, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x44, 0x47, 0x53, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x44, 0x59, 0x47, 0x50, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d,
- 0x44, 0x48, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d, 0x5a, 0x47, 0x52,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x42,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x52, 0x5a, 0x47, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x43, 0x53, 0x44, 0x54, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x43,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x53, 0x50, 0x4e, 0x52, 0x59, 0x58, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x53, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x52, 0x59,
- 0x54, 0x47, 0x50, 0x00, 0x41, 0x46, 0x20, 0x50, 0x52, 0x4d, 0x54, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4d, 0x48, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d,
- 0x4e, 0x52, 0x59, 0x58, 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x41, 0x4d,
- 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x5a, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x52, 0x4d, 0x50, 0x54, 0x00, 0x41, 0x46, 0x20,
- 0x53, 0x4e, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x50,
- 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x52, 0x50, 0x59, 0x54, 0x00, 0x41,
- 0x46, 0x20, 0x52, 0x4d, 0x54, 0x00, 0x41, 0x46, 0x20, 0x41, 0x4d, 0x44,
- 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x47, 0x4a, 0x00,
- 0x41, 0x46, 0x20, 0x43, 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x4d, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x52, 0x5a, 0x47, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x49, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x52, 0x5a,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x21, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d,
- 0x21, 0x00, 0x41, 0x46, 0x20, 0x43, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x44, 0x47, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x52, 0x5a, 0x47, 0x53, 0x42, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x53,
- 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x52, 0x5a, 0x54, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x52, 0x53, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x43, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x53, 0x5a, 0x00, 0x41,
- 0x46, 0x20, 0x54, 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x55, 0x53,
- 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x53, 0x4d, 0x52, 0x00,
- 0x41, 0x46, 0x20, 0x49, 0x45, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4c, 0x44, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x47, 0x4e, 0x56, 0x44, 0x53, 0x58, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x53, 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x50,
- 0x47, 0x44, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x50, 0x53, 0x54, 0x47,
- 0x4d, 0x44, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x55, 0x54, 0x52, 0x00,
- 0x41, 0x46, 0x20, 0x43, 0x5a, 0x52, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x4c, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x47, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x42, 0x5a, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x43, 0x53, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x44, 0x53, 0x58, 0x47, 0x4e, 0x00, 0x41, 0x46,
- 0x20, 0x55, 0x41, 0x00, 0x41, 0x46, 0x20, 0x41, 0x44, 0x53, 0x4d, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x47, 0x4e, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x53, 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x53,
- 0x44, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x49, 0x4d, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x4a, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4c,
- 0x44, 0x53, 0x4a, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x47,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x4d, 0x5a, 0x52, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x50, 0x4d, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47,
- 0x4a, 0x4c, 0x4d, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4a,
- 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x54, 0x50, 0x52, 0x00, 0x41,
- 0x46, 0x20, 0x5a, 0x47, 0x4a, 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x46, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x43, 0x4d, 0x47, 0x44,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x46, 0x41, 0x47, 0x53, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x42, 0x44, 0x52, 0x53, 0x4d, 0x5a, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x43, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x53, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x47, 0x4e, 0x58, 0x44, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x4b, 0x41, 0x46, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x49,
- 0x46, 0x56, 0x54, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4d, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x53, 0x44, 0x47, 0x4d, 0x00, 0x41,
- 0x46, 0x20, 0x50, 0x58, 0x54, 0x4e, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20,
- 0x50, 0x54, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x58, 0x4d, 0x4e, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x21, 0x00, 0x41, 0x46, 0x20, 0x54, 0x4d,
- 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x50, 0x5a, 0x54, 0x47,
- 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x54, 0x52, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x49, 0x41, 0x47, 0x53, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x49, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x43, 0x4b, 0x45, 0x41,
- 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x43, 0x53, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x58, 0x44, 0x53, 0x4e, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x43, 0x41, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x41, 0x43, 0x53, 0x44, 0x47,
- 0x4e, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4a, 0x50, 0x5a, 0x54, 0x47, 0x44,
- 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x54, 0x50, 0x52, 0x00,
- 0x41, 0x46, 0x20, 0x4a, 0x50, 0x54, 0x47, 0x4d, 0x44, 0x52, 0x59, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x42, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x5a, 0x47, 0x42, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x52, 0x53, 0x4d, 0x59, 0x54, 0x47, 0x4a, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x45, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x52, 0x59,
- 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x47, 0x4a, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x43, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x58, 0x44, 0x52, 0x53, 0x4e, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x52, 0x53, 0x5a, 0x47, 0x4e, 0x56, 0x00, 0x41, 0x46, 0x20, 0x55,
- 0x41, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x59, 0x54,
- 0x50, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x47, 0x56, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x43, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x43, 0x41,
- 0x47, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x47, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x4a, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x52, 0x5a, 0x47, 0x4a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44,
- 0x47, 0x56, 0x00, 0x41, 0x46, 0x20, 0x49, 0x4d, 0x5a, 0x47, 0x52, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x45, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x53,
- 0x4d, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x4c,
- 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x44, 0x53, 0x4c, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x53, 0x44, 0x42, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x47, 0x4e, 0x56, 0x44, 0x53, 0x58, 0x00, 0x41, 0x46, 0x20, 0x41, 0x43,
- 0x53, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x41, 0x55, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x49, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x50, 0x52, 0x59,
- 0x54, 0x00, 0x41, 0x46, 0x20, 0x58, 0x44, 0x53, 0x4d, 0x47, 0x4e, 0x00,
- 0x41, 0x46, 0x20, 0x54, 0x47, 0x53, 0x4d, 0x44, 0x52, 0x59, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x42, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x42, 0x44,
- 0x53, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x59, 0x54, 0x47, 0x4e,
- 0x58, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x44, 0x53, 0x58,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x43, 0x47, 0x53, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x59, 0x47, 0x4e, 0x58, 0x44, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x47, 0x4d, 0x44, 0x42, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x44, 0x52, 0x5a, 0x47, 0x42, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x55, 0x4d,
- 0x44, 0x00, 0x41, 0x46, 0x20, 0x45, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x52, 0x50, 0x59, 0x54, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x49, 0x59,
- 0x50, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x50, 0x4d, 0x59, 0x47, 0x4e,
- 0x58, 0x00, 0x41, 0x46, 0x20, 0x56, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4e,
- 0x58, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x47, 0x56, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x44, 0x47, 0x56, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x42,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x4c, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x53, 0x44, 0x47, 0x56, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x58, 0x4d,
- 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x56, 0x4d, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x44, 0x52, 0x5a, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x44,
- 0x56, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x59, 0x50, 0x00, 0x41,
- 0x46, 0x20, 0x49, 0x50, 0x59, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x41, 0x49,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x41, 0x44, 0x53, 0x47, 0x4e, 0x56, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x56, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x43,
- 0x41, 0x44, 0x56, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x43, 0x41, 0x4d,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20,
- 0x4b, 0x00, 0x41, 0x46, 0x20, 0x42, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x59, 0x47, 0x4e, 0x58, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x42, 0x4c, 0x44, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x41, 0x43, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x47,
- 0x4e, 0x56, 0x00, 0x41, 0x46, 0x20, 0x45, 0x53, 0x4c, 0x4d, 0x44, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x58, 0x47, 0x4e, 0x44, 0x00, 0x41, 0x46, 0x20,
- 0x55, 0x43, 0x00, 0x41, 0x46, 0x20, 0x53, 0x42, 0x44, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x52, 0x59, 0x5a, 0x54, 0x47, 0x50, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44,
- 0x53, 0x4d, 0x59, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4a, 0x53,
- 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x45, 0x41, 0x53, 0x47, 0x44, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x55, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x58, 0x59, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x59, 0x54, 0x47,
- 0x56, 0x53, 0x42, 0x50, 0x00, 0x41, 0x46, 0x20, 0x58, 0x44, 0x53, 0x4d,
- 0x47, 0x4e, 0x56, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x59, 0x50, 0x53,
- 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x59, 0x47, 0x53, 0x4a,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x5a, 0x47, 0x52, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x4a, 0x4d, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x41,
- 0x53, 0x4d, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x56, 0x44,
- 0x00, 0x41, 0x46, 0x20, 0x55, 0x43, 0x47, 0x53, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x44, 0x47, 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d,
- 0x44, 0x59, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x55, 0x47, 0x44,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x50, 0x4d, 0x59, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x47, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x4d,
- 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x59, 0x5a,
- 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x4a, 0x4d, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x53, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x4d, 0x59, 0x50, 0x00, 0x41, 0x46, 0x20, 0x50, 0x52, 0x53, 0x4d, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x49, 0x43, 0x47, 0x4d, 0x53, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x4b, 0x41, 0x44, 0x53, 0x47, 0x4e, 0x56, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x47, 0x53, 0x42, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52,
- 0x59, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46, 0x20, 0x41, 0x55, 0x47, 0x54,
- 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x5a, 0x54, 0x52, 0x00, 0x41, 0x46, 0x20, 0x52, 0x4d, 0x59, 0x54,
- 0x50, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x5a, 0x47, 0x4a, 0x44, 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x47, 0x4d, 0x44, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x42, 0x44,
- 0x53, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x59, 0x54, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x53, 0x4d, 0x47, 0x56, 0x00, 0x41, 0x46, 0x20,
- 0x4b, 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x5a, 0x47, 0x42, 0x44,
- 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x4d, 0x00, 0x41, 0x46, 0x20,
- 0x46, 0x41, 0x59, 0x00, 0x41, 0x46, 0x20, 0x45, 0x41, 0x59, 0x00, 0x41,
- 0x46, 0x20, 0x46, 0x45, 0x47, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x54,
- 0x53, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x58, 0x47, 0x4a, 0x00,
- 0x41, 0x46, 0x20, 0x54, 0x00, 0x41, 0x46, 0x20, 0x53, 0x50, 0x58, 0x5a,
- 0x54, 0x47, 0x4d, 0x44, 0x4e, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x47, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x50, 0x58, 0x54, 0x4d, 0x4e,
- 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x4d, 0x5a, 0x47,
- 0x56, 0x00, 0x41, 0x46, 0x20, 0x58, 0x54, 0x4d, 0x4e, 0x52, 0x59, 0x00,
- 0x41, 0x46, 0x20, 0x50, 0x58, 0x54, 0x4e, 0x52, 0x00, 0x41, 0x46, 0x20,
- 0x53, 0x4a, 0x5a, 0x47, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x53, 0x50,
- 0x54, 0x4d, 0x52, 0x59, 0x48, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d, 0x5a,
- 0x52, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x42, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x47, 0x4e, 0x56, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x47, 0x56, 0x44, 0x00, 0x41, 0x46, 0x20, 0x53, 0x50, 0x58, 0x54,
- 0x4d, 0x4e, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x44, 0x47, 0x56, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x50,
- 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x49, 0x59, 0x56, 0x50, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x47, 0x56, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x47,
- 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x44, 0x52, 0x00, 0x41, 0x46,
- 0x20, 0x58, 0x59, 0x56, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x53,
- 0x50, 0x00, 0x41, 0x46, 0x20, 0x54, 0x4d, 0x52, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x49, 0x53, 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x49, 0x4d,
- 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x46, 0x47, 0x44, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x42, 0x5a, 0x47, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x50,
- 0x44, 0x53, 0x59, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x59, 0x4e, 0x50,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x47, 0x56, 0x42, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x53, 0x47, 0x44, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d,
- 0x44, 0x47, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x58, 0x5a, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x59, 0x47, 0x4e, 0x56, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x50, 0x53, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x59,
- 0x54, 0x52, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x44, 0x47, 0x56, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x47, 0x4c, 0x00, 0x41, 0x46, 0x20,
- 0x50, 0x59, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4c, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x4c, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53,
- 0x4d, 0x5a, 0x47, 0x42, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x42, 0x00, 0x41,
- 0x46, 0x20, 0x49, 0x59, 0x54, 0x56, 0x50, 0x00, 0x41, 0x46, 0x20, 0x47,
- 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x5a, 0x54, 0x47, 0x44, 0x52,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x58, 0x59, 0x4e, 0x50, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x52, 0x53, 0x4d, 0x59, 0x5a, 0x54, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x53, 0x4c, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52,
- 0x53, 0x50, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4a, 0x4d, 0x52,
- 0x48, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x54, 0x47, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x46, 0x41, 0x55, 0x00, 0x41, 0x46, 0x20, 0x49, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x50, 0x54, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x44, 0x42, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x58, 0x47, 0x44,
- 0x4e, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x5a, 0x47, 0x53, 0x4a,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x55, 0x47, 0x53, 0x44, 0x4d, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x4d, 0x52, 0x42, 0x4a, 0x5a, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x47, 0x53, 0x4a, 0x44, 0x00, 0x41, 0x46, 0x20, 0x53, 0x54, 0x4d,
- 0x4e, 0x52, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x54, 0x47, 0x44, 0x52, 0x53,
- 0x4d, 0x59, 0x00, 0x41, 0x46, 0x20, 0x43, 0x4b, 0x49, 0x46, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x4a, 0x5a, 0x47, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x52, 0x50, 0x54, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x41, 0x47, 0x4e, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4a, 0x5a,
- 0x47, 0x52, 0x00, 0x41, 0x46, 0x20, 0x46, 0x44, 0x53, 0x54, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x4d, 0x44, 0x59, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52,
- 0x5a, 0x54, 0x47, 0x4a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x44, 0x59,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x45, 0x44, 0x53, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x5a, 0x52, 0x00, 0x41, 0x46, 0x20, 0x55, 0x52, 0x54, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x5a, 0x47, 0x42, 0x53, 0x4e, 0x52, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x43, 0x53, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x5a, 0x47, 0x4a, 0x44, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4d, 0x50, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52,
- 0x53, 0x5a, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x47, 0x4e,
- 0x56, 0x58, 0x00, 0x41, 0x46, 0x20, 0x59, 0x47, 0x4e, 0x44, 0x53, 0x50,
- 0x58, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4e, 0x44, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4c, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x44, 0x47, 0x4c, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x41, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x44, 0x47, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x54,
- 0x47, 0x50, 0x44, 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53,
- 0x4c, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x53, 0x5a, 0x47, 0x4d,
- 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x45, 0x4c, 0x44, 0x47, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x56, 0x53, 0x4a, 0x4d, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x47, 0x44, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x4c,
- 0x44, 0x00, 0x41, 0x46, 0x20, 0x45, 0x47, 0x44, 0x53, 0x4c, 0x00, 0x41,
- 0x46, 0x20, 0x45, 0x41, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x47,
- 0x42, 0x4c, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x41, 0x44, 0x47, 0x53,
- 0x4c, 0x00, 0x41, 0x46, 0x20, 0x44, 0x4c, 0x53, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x44, 0x53, 0x4c, 0x47, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47,
- 0x44, 0x52, 0x53, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4c, 0x44, 0x52,
- 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x47, 0x4e, 0x42, 0x58,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x42, 0x5a, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x50, 0x53, 0x47, 0x44, 0x59, 0x00, 0x41, 0x46, 0x20, 0x59,
- 0x4e, 0x00, 0x41, 0x46, 0x20, 0x43, 0x44, 0x53, 0x47, 0x4e, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x45, 0x53, 0x44, 0x47, 0x4c, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x52, 0x53, 0x5a, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x52, 0x59, 0x54, 0x47, 0x53, 0x4a, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x52, 0x59, 0x54, 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x53, 0x50, 0x44,
- 0x52, 0x59, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x42, 0x53, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x42, 0x44, 0x52, 0x53, 0x4c, 0x5a, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x53, 0x42, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x42,
- 0x58, 0x47, 0x4e, 0x56, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x44,
- 0x53, 0x58, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x42, 0x47, 0x53, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x58, 0x4d, 0x4e, 0x56, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x53, 0x4d, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53,
- 0x5a, 0x47, 0x4e, 0x58, 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x42, 0x44,
- 0x00, 0x41, 0x46, 0x20, 0x49, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x47, 0x42, 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x53,
- 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x47, 0x56, 0x4d,
- 0x44, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x44, 0x52,
- 0x42, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x42, 0x44, 0x52, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x4e, 0x42, 0x58, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x43, 0x49, 0x41, 0x56, 0x54, 0x52, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x43, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x59, 0x54,
- 0x47, 0x4a, 0x50, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x50, 0x59, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x4e, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47,
- 0x53, 0x4a, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x4d,
- 0x5a, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x5a,
- 0x47, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x54, 0x47,
- 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x55, 0x41, 0x47, 0x44, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x53, 0x50, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20,
- 0x53, 0x4d, 0x44, 0x47, 0x42, 0x00, 0x41, 0x46, 0x20, 0x43, 0x53, 0x4d,
- 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x46, 0x58, 0x44, 0x53, 0x47, 0x4e,
- 0x00, 0x41, 0x46, 0x20, 0x46, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x52, 0x5a, 0x54, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x43, 0x44, 0x52,
- 0x5a, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x46, 0x43, 0x4d, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x46, 0x4b, 0x47, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x52, 0x5a, 0x56, 0x53, 0x00, 0x41, 0x46, 0x20, 0x54, 0x50, 0x4d,
- 0x52, 0x00, 0x41, 0x46, 0x20, 0x49, 0x53, 0x4d, 0x52, 0x5a, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x4c, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x43, 0x00,
- 0x41, 0x46, 0x20, 0x43, 0x41, 0x4b, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x49, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x52, 0x42, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x49, 0x47, 0x4e,
- 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x4d, 0x52, 0x5a, 0x47, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x46, 0x00, 0x41, 0x46, 0x20, 0x43, 0x41, 0x46,
- 0x54, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x53, 0x4a,
- 0x4d, 0x44, 0x52, 0x48, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x53, 0x4a,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x59, 0x50, 0x54, 0x47,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x41, 0x4d, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x5a, 0x47, 0x42, 0x4a, 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x4a, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x4a,
- 0x4d, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x54, 0x47, 0x4d, 0x44,
- 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x54, 0x47, 0x4d, 0x44, 0x52,
- 0x59, 0x50, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d, 0x44, 0x53, 0x59, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x43, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53,
- 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x54, 0x47, 0x42, 0x44, 0x52,
- 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x41, 0x55, 0x53, 0x47, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x52, 0x5a, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x48, 0x00, 0x41, 0x46, 0x20, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x44, 0x47, 0x53, 0x42, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4a, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x5a, 0x52, 0x50, 0x00, 0x41, 0x46, 0x20, 0x52,
- 0x53, 0x42, 0x5a, 0x00, 0x41, 0x46, 0x20, 0x41, 0x43, 0x47, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x4d, 0x5a, 0x47, 0x56, 0x4a,
- 0x00, 0x41, 0x46, 0x20, 0x42, 0x52, 0x53, 0x5a, 0x47, 0x50, 0x00, 0x41,
- 0x46, 0x20, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x43, 0x41, 0x49,
- 0x46, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x43, 0x46, 0x41, 0x53,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x46, 0x49, 0x41, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x44, 0x53, 0x47, 0x4e, 0x58, 0x00, 0x41, 0x46, 0x20, 0x44,
- 0x52, 0x53, 0x4e, 0x5a, 0x47, 0x58, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x52, 0x59, 0x5a, 0x54, 0x47, 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x44, 0x52, 0x59, 0x54, 0x47, 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x46,
- 0x53, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x45, 0x44, 0x53, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x59, 0x54, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x55, 0x41, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x59, 0x53,
- 0x5a, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x4e, 0x52, 0x59, 0x58,
- 0x5a, 0x54, 0x00, 0x41, 0x46, 0x20, 0x55, 0x50, 0x54, 0x52, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x58, 0x47, 0x4d, 0x44, 0x4e, 0x00, 0x41, 0x46, 0x20,
- 0x49, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x53, 0x59,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x43, 0x55, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x5a, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x4d, 0x47, 0x44, 0x52, 0x5a, 0x21, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x21, 0x00, 0x41, 0x46, 0x20, 0x4c, 0x44, 0x47, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x5a, 0x54, 0x47, 0x53, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x54, 0x50, 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20,
- 0x5a, 0x54, 0x52, 0x50, 0x00, 0x41, 0x46, 0x20, 0x43, 0x41, 0x49, 0x46,
- 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x49, 0x46, 0x4b, 0x53, 0x4d,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x4e, 0x58, 0x56, 0x42, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x59, 0x54, 0x47, 0x44, 0x52, 0x53, 0x50, 0x00, 0x41, 0x46,
- 0x20, 0x47, 0x4c, 0x4d, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x54, 0x53,
- 0x50, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x44, 0x4a, 0x47, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x43, 0x41, 0x56, 0x4e, 0x47, 0x53, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x46, 0x59, 0x00, 0x41, 0x46, 0x20, 0x54, 0x47, 0x44, 0x52,
- 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x4d, 0x44, 0x59, 0x00,
- 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4a, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x47, 0x44, 0x53, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x50, 0x54, 0x52, 0x53,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x4d, 0x52, 0x48, 0x5a, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x47, 0x53, 0x42, 0x4c, 0x00, 0x41, 0x46, 0x20,
- 0x45, 0x50, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x5a, 0x53, 0x42,
- 0x00, 0x41, 0x46, 0x20, 0x43, 0x41, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x58, 0x4d, 0x47, 0x4e, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x49,
- 0x53, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x52, 0x59, 0x50,
- 0x54, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d, 0x44, 0x59, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x4d, 0x44, 0x42, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44,
- 0x52, 0x53, 0x4d, 0x5a, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52,
- 0x53, 0x4d, 0x59, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46, 0x20, 0x47, 0x50,
- 0x53, 0x4d, 0x44, 0x52, 0x59, 0x54, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47,
- 0x4a, 0x53, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x44, 0x59, 0x50, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x4d, 0x52, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x5a, 0x47, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x50,
- 0x54, 0x47, 0x4d, 0x44, 0x52, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x47, 0x4d, 0x44, 0x52, 0x4a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x48,
- 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4a, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x45, 0x4d, 0x44,
- 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x52, 0x53, 0x58, 0x5a, 0x47,
- 0x56, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x53, 0x48, 0x00, 0x41, 0x46, 0x20,
- 0x49, 0x53, 0x42, 0x00, 0x41, 0x46, 0x20, 0x49, 0x54, 0x47, 0x44, 0x52,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x44, 0x52, 0x53, 0x4a, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4a,
- 0x4d, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4a, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x44, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x52,
- 0x59, 0x58, 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x41, 0x4d, 0x44, 0x53,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x4e, 0x58, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x52, 0x48, 0x5a, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55,
- 0x54, 0x52, 0x50, 0x00, 0x41, 0x46, 0x20, 0x41, 0x48, 0x47, 0x4a, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x4d, 0x50, 0x54, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x4e, 0x52, 0x58, 0x00, 0x41, 0x46, 0x20, 0x58, 0x53, 0x4d,
- 0x4e, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x59, 0x5a, 0x54, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x50, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d,
- 0x44, 0x52, 0x59, 0x5a, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x4d,
- 0x44, 0x52, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x59, 0x54, 0x52, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x52, 0x4a, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x44, 0x52, 0x59, 0x50, 0x53, 0x54, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x55, 0x52, 0x50, 0x54, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x5a,
- 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x50, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a,
- 0x54, 0x47, 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x45, 0x59, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x45, 0x53, 0x47, 0x4d, 0x44, 0x42, 0x00, 0x41,
- 0x46, 0x20, 0x50, 0x53, 0x4d, 0x59, 0x00, 0x41, 0x46, 0x20, 0x53, 0x59,
- 0x50, 0x00, 0x41, 0x46, 0x20, 0x53, 0x54, 0x4d, 0x52, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x4d, 0x52, 0x59, 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x43,
- 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x5a, 0x54,
- 0x47, 0x4a, 0x50, 0x00, 0x41, 0x46, 0x20, 0x43, 0x47, 0x4e, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x5a, 0x47, 0x4e, 0x44, 0x52, 0x53, 0x58, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x5a, 0x54, 0x47, 0x44, 0x52, 0x53, 0x50, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x53, 0x42, 0x4a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x42, 0x53, 0x4d,
- 0x56, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x42, 0x4c, 0x44, 0x52, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x4c, 0x44, 0x00, 0x41, 0x46, 0x20,
- 0x42, 0x53, 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x47, 0x42, 0x4d,
- 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x42, 0x53, 0x4d,
- 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x53, 0x47, 0x56, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x42, 0x44, 0x53, 0x4c, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x47, 0x4e, 0x56, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x44,
- 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x54, 0x47, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x58, 0x47, 0x4e, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x42, 0x00, 0x41, 0x46, 0x20, 0x44, 0x47, 0x56, 0x00, 0x41, 0x46, 0x20,
- 0x5a, 0x54, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x47, 0x4e, 0x42, 0x00,
- 0x41, 0x46, 0x20, 0x58, 0x4d, 0x47, 0x4e, 0x56, 0x44, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x47, 0x4d, 0x52, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x55,
- 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52, 0x59, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x58, 0x4d, 0x5a, 0x47, 0x4e, 0x44, 0x52, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x45, 0x56, 0x4e, 0x47, 0x53, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x41, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x59, 0x54, 0x56, 0x52,
- 0x00, 0x41, 0x46, 0x20, 0x45, 0x53, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x45,
- 0x53, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x47, 0x44, 0x4c, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x47, 0x4e,
- 0x44, 0x53, 0x58, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x44, 0x47, 0x4c,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x58, 0x47, 0x4e, 0x56, 0x44, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x54, 0x52, 0x4d, 0x50, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x46, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x46, 0x4d, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x52, 0x53, 0x4d, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x46, 0x49, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x58, 0x47, 0x44, 0x53,
- 0x4e, 0x00, 0x41, 0x46, 0x20, 0x49, 0x46, 0x47, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x44, 0x52, 0x59, 0x53, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46,
- 0x20, 0x4a, 0x4d, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x55, 0x52, 0x54, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53, 0x42, 0x5a, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x44, 0x59, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x55,
- 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x58, 0x54, 0x47, 0x4a,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x4d, 0x44, 0x4e, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x49, 0x41, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x5a, 0x54,
- 0x47, 0x44, 0x52, 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x42, 0x53, 0x4d,
- 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53, 0x47, 0x4a,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x4b, 0x47, 0x4d, 0x53, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x52, 0x53, 0x50, 0x4d, 0x59, 0x54, 0x00, 0x41, 0x46, 0x20,
- 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x53, 0x47, 0x42,
- 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x50, 0x54, 0x47, 0x44, 0x52, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x54,
- 0x52, 0x59, 0x50, 0x00, 0x41, 0x46, 0x20, 0x41, 0x49, 0x43, 0x53, 0x47,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x4e, 0x52, 0x53, 0x5a, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53, 0x54, 0x47, 0x4a, 0x50,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x55, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x52, 0x53, 0x54, 0x00, 0x41, 0x46, 0x20, 0x43, 0x58, 0x4d,
- 0x4e, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x43, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x53, 0x59, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x4d, 0x59, 0x00,
- 0x41, 0x46, 0x20, 0x4a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x53, 0x5a,
- 0x47, 0x4d, 0x44, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x4a,
- 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x43, 0x41, 0x53, 0x54, 0x47, 0x44,
- 0x00, 0x41, 0x46, 0x20, 0x45, 0x4d, 0x47, 0x44, 0x53, 0x54, 0x00, 0x41,
- 0x46, 0x20, 0x55, 0x50, 0x52, 0x54, 0x00, 0x41, 0x46, 0x20, 0x43, 0x53,
- 0x5a, 0x47, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x59,
- 0x53, 0x50, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x5a, 0x47, 0x44,
- 0x52, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x43, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x47,
- 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x4e, 0x53, 0x4a, 0x58,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d, 0x44, 0x52, 0x5a, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x54, 0x52, 0x50, 0x00, 0x41, 0x46, 0x20, 0x41, 0x54, 0x47, 0x44,
- 0x53, 0x42, 0x00, 0x41, 0x46, 0x20, 0x41, 0x55, 0x47, 0x53, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x45, 0x41, 0x47, 0x4e, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x59, 0x5a, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x44, 0x53, 0x54,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x52, 0x58, 0x00, 0x41, 0x46, 0x20,
- 0x55, 0x44, 0x53, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x55, 0x47, 0x53,
- 0x44, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x52, 0x53, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x59, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x42, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x5a, 0x54, 0x47, 0x4d, 0x44, 0x52, 0x59, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x45, 0x54, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x52,
- 0x53, 0x59, 0x50, 0x54, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x41, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x53, 0x4d, 0x47, 0x42, 0x00, 0x41, 0x46, 0x20,
- 0x5a, 0x47, 0x58, 0x44, 0x52, 0x53, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x4e, 0x53, 0x58, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x50, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x55, 0x53, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x47,
- 0x53, 0x42, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x4d, 0x5a, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x44, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x58, 0x4d, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x5a, 0x47,
- 0x42, 0x53, 0x00, 0x41, 0x46, 0x20, 0x59, 0x54, 0x47, 0x44, 0x52, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x48, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x52, 0x59, 0x4a, 0x50, 0x53, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4a, 0x53, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x41, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x42, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x59, 0x54, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x52, 0x59, 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53,
- 0x5a, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x48, 0x53, 0x4d, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x5a, 0x47, 0x4e, 0x44, 0x52, 0x53, 0x58, 0x00, 0x41, 0x46, 0x20,
- 0x50, 0x44, 0x52, 0x53, 0x4d, 0x59, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x53, 0x42, 0x4d, 0x59, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4a, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x45, 0x44, 0x53, 0x47, 0x56, 0x00, 0x41, 0x46, 0x20,
- 0x47, 0x44, 0x4a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x43, 0x44, 0x52, 0x53,
- 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d, 0x47, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4d,
- 0x44, 0x52, 0x53, 0x42, 0x00, 0x41, 0x46, 0x20, 0x43, 0x4b, 0x48, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x54, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x47, 0x53, 0x4a, 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59,
- 0x47, 0x4e, 0x50, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53,
- 0x58, 0x5a, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x58, 0x54, 0x50, 0x4e,
- 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x4a, 0x53, 0x5a,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53, 0x4e, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x4b, 0x43, 0x58, 0x53, 0x56, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x4b,
- 0x43, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x45, 0x41, 0x53, 0x47, 0x4d, 0x44,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x4d, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x42,
- 0x00, 0x41, 0x46, 0x20, 0x4e, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x58, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x47, 0x44, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x59, 0x54, 0x47, 0x44, 0x52, 0x53, 0x50, 0x42, 0x00, 0x41, 0x46,
- 0x20, 0x49, 0x4b, 0x54, 0x48, 0x00, 0x41, 0x46, 0x20, 0x50, 0x54, 0x47,
- 0x4d, 0x44, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x59,
- 0x53, 0x50, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x52, 0x59, 0x50,
- 0x58, 0x54, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x47, 0x50, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x54, 0x4d, 0x52, 0x59, 0x50, 0x00, 0x41,
- 0x46, 0x20, 0x52, 0x53, 0x50, 0x4d, 0x54, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x43, 0x47, 0x4e, 0x56, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x46, 0x43,
- 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x46, 0x43, 0x53, 0x44, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x4e, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x54, 0x47, 0x50, 0x44, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x47, 0x56, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x58, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x52, 0x53, 0x59, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x42, 0x4c, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x54, 0x52,
- 0x59, 0x4c, 0x50, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x44, 0x52,
- 0x4a, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x54, 0x4d, 0x4e, 0x52, 0x50, 0x00, 0x41, 0x46, 0x20, 0x53, 0x58,
- 0x4d, 0x4e, 0x50, 0x00, 0x41, 0x46, 0x20, 0x50, 0x59, 0x54, 0x47, 0x44,
- 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x54, 0x47, 0x4a, 0x50, 0x4d,
- 0x44, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x59, 0x4e,
- 0x58, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x41, 0x4d, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x45, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x44, 0x53, 0x47,
- 0x4e, 0x00, 0x41, 0x46, 0x20, 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x4a, 0x47, 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x4a, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x48, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4c,
- 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x48,
- 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x5a, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x53, 0x4e, 0x47, 0x58, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x52,
- 0x58, 0x54, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x44, 0x52,
- 0x53, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x4a, 0x4d, 0x44,
- 0x52, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x54, 0x47, 0x50, 0x44, 0x52,
- 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x4a, 0x4d, 0x44, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x42, 0x4a, 0x00,
- 0x41, 0x46, 0x20, 0x52, 0x5a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47,
- 0x4d, 0x44, 0x52, 0x42, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53,
- 0x42, 0x58, 0x5a, 0x47, 0x4e, 0x56, 0x00, 0x41, 0x46, 0x20, 0x49, 0x4d,
- 0x53, 0x54, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x47, 0x42, 0x4c, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x4d, 0x5a, 0x00, 0x41, 0x46, 0x20,
- 0x47, 0x4d, 0x44, 0x4a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x44, 0x53,
- 0x4e, 0x58, 0x00, 0x41, 0x46, 0x20, 0x50, 0x58, 0x59, 0x4e, 0x00, 0x41,
- 0x46, 0x20, 0x50, 0x54, 0x47, 0x44, 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x52, 0x53, 0x4a, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x4d, 0x44, 0x52, 0x48, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x47,
- 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x4c, 0x00, 0x41, 0x46,
- 0x20, 0x54, 0x47, 0x50, 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x45, 0x41, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x58, 0x47, 0x4d, 0x44,
- 0x4e, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x47, 0x4d, 0x44, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x45, 0x55, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52,
- 0x5a, 0x47, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x55, 0x54, 0x59, 0x50,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x47, 0x44, 0x53, 0x42, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x47, 0x44, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d,
- 0x44, 0x4e, 0x53, 0x00, 0x41, 0x46, 0x20, 0x43, 0x41, 0x45, 0x47, 0x44,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x53, 0x47, 0x4d, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x43, 0x41, 0x4b, 0x45, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x45, 0x4b, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x43, 0x4b, 0x45,
- 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x56, 0x47, 0x53, 0x44,
- 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x53, 0x4a, 0x00,
- 0x41, 0x46, 0x20, 0x4b, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x58,
- 0x4d, 0x59, 0x47, 0x4e, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52,
- 0x53, 0x59, 0x54, 0x47, 0x4e, 0x50, 0x00, 0x41, 0x46, 0x20, 0x42, 0x47,
- 0x56, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x59, 0x47, 0x44, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x42, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x47, 0x53,
- 0x4c, 0x00, 0x41, 0x46, 0x20, 0x53, 0x56, 0x4d, 0x00, 0x41, 0x46, 0x20,
- 0x4c, 0x4d, 0x44, 0x52, 0x59, 0x5a, 0x47, 0x53, 0x42, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x43, 0x47, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x54, 0x47,
- 0x44, 0x52, 0x53, 0x4d, 0x50, 0x00, 0x41, 0x46, 0x20, 0x44, 0x42, 0x53,
- 0x47, 0x56, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x59, 0x53, 0x5a,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x44, 0x52, 0x59, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x58, 0x4d, 0x59, 0x54, 0x4e, 0x52, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x47, 0x44, 0x53, 0x42, 0x4a, 0x00, 0x41, 0x46, 0x20,
- 0x41, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x50, 0x59,
- 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x47, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x43, 0x41, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x50, 0x53,
- 0x4d, 0x44, 0x52, 0x59, 0x5a, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x44, 0x47, 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x42, 0x00, 0x41,
- 0x46, 0x20, 0x5a, 0x54, 0x47, 0x44, 0x52, 0x53, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x4d, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53,
- 0x4d, 0x59, 0x47, 0x00, 0x41, 0x46, 0x20, 0x45, 0x47, 0x58, 0x4e, 0x44,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x42, 0x00,
- 0x41, 0x46, 0x20, 0x49, 0x46, 0x41, 0x4d, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x53, 0x4d, 0x44, 0x52, 0x5a, 0x47, 0x42, 0x4a, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x4e, 0x52, 0x59, 0x58, 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x4d, 0x44, 0x4e, 0x52, 0x59, 0x58, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46,
- 0x20, 0x49, 0x45, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x49, 0x41, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x53, 0x58, 0x4e, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x54, 0x47, 0x4a, 0x50, 0x4d, 0x44, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x5a, 0x47, 0x4d, 0x44, 0x4a, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x59, 0x54, 0x47, 0x50, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x54, 0x4d, 0x52, 0x53, 0x59, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x58,
- 0x4d, 0x5a, 0x47, 0x4e, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4a,
- 0x4d, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x53,
- 0x4d, 0x59, 0x54, 0x47, 0x56, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47,
- 0x4d, 0x52, 0x42, 0x4a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x54, 0x4d, 0x52,
- 0x59, 0x50, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4a, 0x44, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x47, 0x42, 0x00, 0x41, 0x46, 0x20,
- 0x4c, 0x53, 0x4d, 0x44, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x58,
- 0x4e, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x52, 0x5a,
- 0x42, 0x00, 0x41, 0x46, 0x20, 0x53, 0x5a, 0x4d, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x5a, 0x00, 0x41, 0x46, 0x20, 0x44, 0x59, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x43, 0x44, 0x53, 0x47, 0x4e, 0x56, 0x00, 0x41, 0x46, 0x20, 0x42,
- 0x44, 0x53, 0x47, 0x4c, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x58,
- 0x5a, 0x47, 0x4e, 0x56, 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x4d, 0x59,
- 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x42, 0x5a, 0x52, 0x00, 0x41, 0x46,
- 0x20, 0x50, 0x44, 0x53, 0x47, 0x4e, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d,
- 0x44, 0x53, 0x42, 0x00, 0x41, 0x46, 0x20, 0x4c, 0x44, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x52, 0x42, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x45, 0x53, 0x47,
- 0x56, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x44, 0x42, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x5a, 0x56, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4a, 0x53,
- 0x44, 0x00, 0x41, 0x46, 0x20, 0x54, 0x4d, 0x52, 0x53, 0x59, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x4a, 0x00, 0x41, 0x46,
- 0x20, 0x53, 0x58, 0x54, 0x4d, 0x4e, 0x52, 0x00, 0x41, 0x46, 0x20, 0x4a,
- 0x4d, 0x5a, 0x47, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x4e, 0x52,
- 0x00, 0x41, 0x46, 0x20, 0x4b, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44,
- 0x4e, 0x52, 0x59, 0x58, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46, 0x20, 0x50,
- 0x53, 0x4d, 0x44, 0x52, 0x59, 0x5a, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x52, 0x50, 0x4e, 0x54, 0x00, 0x41, 0x46, 0x20, 0x4e, 0x59, 0x58, 0x42,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x54, 0x50, 0x52, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x59, 0x54, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47,
- 0x4d, 0x44, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x41, 0x42, 0x4d, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x43, 0x54, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x49, 0x59, 0x54, 0x52, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4a, 0x4d,
- 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53,
- 0x4d, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x55, 0x53, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x43, 0x44, 0x53, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53,
- 0x4a, 0x4d, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x43, 0x4b, 0x49, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x46, 0x53, 0x4d, 0x44, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x54, 0x52, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x41, 0x55, 0x53, 0x44,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x4d, 0x44, 0x42, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x4c, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x59, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x47, 0x56, 0x4d, 0x44, 0x59, 0x00, 0x41, 0x46, 0x20,
- 0x58, 0x4e, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45, 0x53, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x59, 0x54, 0x47, 0x4e, 0x56, 0x50,
- 0x00, 0x41, 0x46, 0x20, 0x43, 0x53, 0x47, 0x56, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x5a, 0x47, 0x4d, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x58, 0x4d,
- 0x59, 0x47, 0x4e, 0x56, 0x44, 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x58,
- 0x4e, 0x44, 0x00, 0x41, 0x46, 0x20, 0x41, 0x46, 0x00, 0x41, 0x46, 0x20,
- 0x46, 0x41, 0x43, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x49,
- 0x53, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4a, 0x5a, 0x47, 0x52, 0x53,
- 0x00, 0x41, 0x46, 0x20, 0x45, 0x54, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x59, 0x50, 0x52, 0x00, 0x41, 0x46, 0x20, 0x54, 0x50, 0x4d, 0x52,
- 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x4e, 0x52, 0x59, 0x53,
- 0x50, 0x58, 0x5a, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53, 0x50, 0x54, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x4c, 0x53, 0x00, 0x41, 0x46, 0x20, 0x52, 0x54, 0x21,
- 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x4d, 0x52, 0x53, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x58, 0x54, 0x47, 0x4d, 0x44, 0x4e, 0x52, 0x59, 0x53, 0x50,
- 0x00, 0x41, 0x46, 0x20, 0x4a, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x4a,
- 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x53,
- 0x42, 0x47, 0x00, 0x41, 0x46, 0x20, 0x54, 0x47, 0x44, 0x52, 0x53, 0x4d,
- 0x59, 0x00, 0x41, 0x46, 0x20, 0x50, 0x58, 0x54, 0x47, 0x44, 0x4e, 0x52,
- 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4d, 0x44, 0x59, 0x53, 0x4a,
- 0x00, 0x41, 0x46, 0x20, 0x41, 0x46, 0x43, 0x47, 0x44, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x4d, 0x52, 0x59, 0x53, 0x54, 0x00, 0x41, 0x46, 0x20, 0x54,
- 0x52, 0x53, 0x4d, 0x50, 0x00, 0x41, 0x46, 0x20, 0x49, 0x59, 0x54, 0x00,
- 0x41, 0x46, 0x20, 0x42, 0x5a, 0x47, 0x4d, 0x44, 0x52, 0x59, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x50, 0x4d, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x42, 0x5a, 0x47, 0x4d, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x53,
- 0x48, 0x00, 0x41, 0x46, 0x20, 0x43, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20,
- 0x52, 0x4d, 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x5a, 0x47, 0x53,
- 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x50, 0x58, 0x5a, 0x54, 0x47, 0x4d,
- 0x44, 0x4e, 0x52, 0x59, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x5a,
- 0x47, 0x4a, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x59,
- 0x5a, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46, 0x20, 0x50, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x52, 0x59, 0x54, 0x47, 0x53, 0x50, 0x00, 0x41, 0x46,
- 0x20, 0x54, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x52, 0x54,
- 0x50, 0x00, 0x41, 0x46, 0x20, 0x50, 0x44, 0x52, 0x59, 0x54, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x59, 0x5a, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x44, 0x52, 0x59, 0x50, 0x54, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x46, 0x53, 0x44, 0x47, 0x4d, 0x00, 0x41, 0x46, 0x20, 0x50, 0x53,
- 0x4d, 0x52, 0x59, 0x54, 0x00, 0x41, 0x46, 0x20, 0x41, 0x58, 0x4e, 0x00,
- 0x41, 0x46, 0x20, 0x41, 0x45, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x54,
- 0x52, 0x53, 0x50, 0x00, 0x41, 0x46, 0x20, 0x46, 0x41, 0x53, 0x47, 0x44,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x53, 0x52, 0x5a, 0x47, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x58, 0x4e, 0x5a, 0x44, 0x52, 0x53, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x4a, 0x53, 0x4d, 0x44, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x42, 0x53, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x49, 0x46, 0x41,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x49, 0x53, 0x47, 0x44, 0x00, 0x41, 0x46,
- 0x20, 0x43, 0x53, 0x44, 0x52, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x5a,
- 0x47, 0x42, 0x53, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53,
- 0x50, 0x4d, 0x59, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d, 0x5a,
- 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x54, 0x47, 0x4d,
- 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x52, 0x4a, 0x5a,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x49, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x54, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d,
- 0x52, 0x4a, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x52, 0x59, 0x50, 0x5a,
- 0x54, 0x00, 0x41, 0x46, 0x20, 0x41, 0x53, 0x4d, 0x44, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x53, 0x4a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52,
- 0x53, 0x4d, 0x59, 0x47, 0x4e, 0x4c, 0x58, 0x00, 0x41, 0x46, 0x20, 0x50,
- 0x44, 0x52, 0x53, 0x59, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d,
- 0x48, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4d, 0x44, 0x4e, 0x52, 0x59,
- 0x50, 0x58, 0x54, 0x47, 0x00, 0x41, 0x46, 0x20, 0x49, 0x54, 0x47, 0x53,
- 0x44, 0x00, 0x41, 0x46, 0x20, 0x54, 0x53, 0x4d, 0x52, 0x59, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x59, 0x50, 0x53, 0x00, 0x41, 0x46, 0x20, 0x46, 0x41,
- 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x52, 0x59, 0x5a, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x47, 0x53, 0x44, 0x48, 0x00, 0x41, 0x46, 0x20,
- 0x4d, 0x5a, 0x47, 0x52, 0x53, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x50, 0x4d,
- 0x59, 0x00, 0x41, 0x46, 0x20, 0x47, 0x4a, 0x4d, 0x53, 0x00, 0x41, 0x46,
- 0x20, 0x55, 0x41, 0x53, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x47, 0x56,
- 0x53, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x54, 0x4c, 0x50, 0x52, 0x00,
- 0x41, 0x46, 0x20, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x4d, 0x58, 0x4e, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53, 0x42, 0x5a, 0x47, 0x56, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x47, 0x53, 0x42, 0x00, 0x41, 0x46, 0x20, 0x47,
- 0x53, 0x44, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x58, 0x4d, 0x4e, 0x00, 0x41,
- 0x46, 0x20, 0x53, 0x44, 0x42, 0x47, 0x00, 0x41, 0x46, 0x20, 0x54, 0x47,
- 0x53, 0x4d, 0x44, 0x52, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x53, 0x52,
- 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x53, 0x4d, 0x52, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x58, 0x54, 0x53, 0x4d, 0x4e, 0x52, 0x59, 0x50, 0x00, 0x41,
- 0x46, 0x20, 0x54, 0x47, 0x53, 0x4d, 0x44, 0x52, 0x4a, 0x00, 0x41, 0x46,
- 0x20, 0x50, 0x54, 0x53, 0x4d, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x54,
- 0x47, 0x4d, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x4e,
- 0x58, 0x47, 0x42, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x41, 0x43, 0x53, 0x44,
- 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x49, 0x4d, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x42, 0x59, 0x5a, 0x54, 0x47, 0x44, 0x52, 0x53, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x53, 0x5a, 0x52, 0x00, 0x41, 0x46, 0x20, 0x54, 0x52,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x52, 0x53, 0x42, 0x4a, 0x00,
- 0x41, 0x46, 0x20, 0x44, 0x53, 0x4d, 0x48, 0x00, 0x41, 0x46, 0x20, 0x41,
- 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4c, 0x53, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x42, 0x4d, 0x48, 0x00, 0x41, 0x46, 0x20, 0x49, 0x45, 0x46, 0x44,
- 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x53, 0x4d, 0x59, 0x54,
- 0x47, 0x4e, 0x58, 0x50, 0x00, 0x41, 0x46, 0x20, 0x49, 0x43, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x46, 0x4b, 0x00, 0x41, 0x46, 0x20, 0x41, 0x4b, 0x46,
- 0x43, 0x44, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x43, 0x46, 0x00, 0x41,
- 0x46, 0x20, 0x50, 0x4d, 0x4e, 0x52, 0x59, 0x58, 0x54, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x52, 0x4a, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x59, 0x53,
- 0x50, 0x00, 0x41, 0x46, 0x20, 0x53, 0x52, 0x42, 0x5a, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x44, 0x52, 0x53, 0x4d, 0x54, 0x47, 0x50, 0x00, 0x41, 0x46,
- 0x20, 0x41, 0x55, 0x53, 0x44, 0x00, 0x41, 0x46, 0x20, 0x53, 0x4e, 0x52,
- 0x59, 0x50, 0x58, 0x54, 0x00, 0x41, 0x46, 0x20, 0x45, 0x44, 0x52, 0x5a,
- 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x5a, 0x47, 0x4a, 0x44,
- 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x59, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x49, 0x5a, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41, 0x46, 0x20,
- 0x46, 0x45, 0x41, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4a, 0x00, 0x41,
- 0x46, 0x20, 0x58, 0x54, 0x47, 0x4d, 0x44, 0x4e, 0x52, 0x59, 0x50, 0x00,
- 0x41, 0x46, 0x20, 0x43, 0x46, 0x53, 0x47, 0x44, 0x4d, 0x00, 0x41, 0x46,
- 0x20, 0x4a, 0x47, 0x53, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20, 0x4a, 0x44,
- 0x52, 0x53, 0x4d, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x43, 0x45, 0x4b,
- 0x46, 0x41, 0x53, 0x00, 0x41, 0x46, 0x20, 0x45, 0x46, 0x41, 0x43, 0x4b,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x46, 0x43, 0x4b, 0x4d, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x5a, 0x47, 0x53, 0x4d, 0x44, 0x52, 0x42, 0x00, 0x41, 0x46,
- 0x20, 0x49, 0x53, 0x4d, 0x59, 0x00, 0x41, 0x46, 0x20, 0x41, 0x47, 0x53,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x41, 0x47, 0x53, 0x4d, 0x44, 0x00, 0x41,
- 0x46, 0x20, 0x46, 0x53, 0x00, 0x41, 0x46, 0x20, 0x46, 0x50, 0x59, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x54, 0x47, 0x44, 0x52, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x4d, 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46,
- 0x20, 0x44, 0x52, 0x50, 0x54, 0x00, 0x41, 0x46, 0x20, 0x44, 0x52, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x53, 0x47, 0x42, 0x4a, 0x00, 0x41, 0x46, 0x20,
- 0x44, 0x59, 0x00, 0x41, 0x46, 0x20, 0x41, 0x47, 0x44, 0x53, 0x4e, 0x00,
- 0x41, 0x46, 0x20, 0x42, 0x53, 0x5a, 0x47, 0x44, 0x52, 0x00, 0x41, 0x46,
- 0x20, 0x50, 0x42, 0x00, 0x41, 0x46, 0x20, 0x50, 0x54, 0x00, 0x41, 0x46,
- 0x20, 0x4a, 0x53, 0x4d, 0x44, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x45,
- 0x44, 0x53, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20, 0x53, 0x44, 0x59, 0x47,
- 0x00, 0x41, 0x46, 0x20, 0x4a, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x46, 0x44, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x41, 0x46, 0x4e, 0x47,
- 0x4d, 0x53, 0x44, 0x58, 0x00, 0x41, 0x46, 0x20, 0x41, 0x46, 0x49, 0x4d,
- 0x53, 0x00, 0x41, 0x46, 0x20, 0x49, 0x4c, 0x44, 0x47, 0x53, 0x00, 0x41,
- 0x46, 0x20, 0x59, 0x54, 0x50, 0x52, 0x00, 0x41, 0x46, 0x20, 0x41, 0x43,
- 0x4d, 0x47, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x4b, 0x47, 0x44, 0x53,
- 0x4d, 0x00, 0x41, 0x46, 0x20, 0x46, 0x49, 0x4b, 0x41, 0x53, 0x4d, 0x00,
- 0x41, 0x46, 0x20, 0x49, 0x44, 0x53, 0x4d, 0x47, 0x00, 0x41, 0x46, 0x20,
- 0x43, 0x47, 0x56, 0x44, 0x53, 0x00, 0x41, 0x46, 0x20, 0x44, 0x4e, 0x58,
- 0x54, 0x47, 0x56, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x52, 0x54, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x47, 0x50, 0x44, 0x59, 0x00, 0x41, 0x46, 0x20, 0x4d,
- 0x44, 0x59, 0x53, 0x50, 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x44, 0x52,
- 0x59, 0x48, 0x5a, 0x54, 0x47, 0x53, 0x00, 0x41, 0x46, 0x20, 0x42, 0x4d,
- 0x44, 0x52, 0x53, 0x5a, 0x47, 0x00, 0x41, 0x46, 0x20, 0x44, 0x4a, 0x53,
- 0x47, 0x00, 0x41, 0x46, 0x20, 0x50, 0x4e, 0x52, 0x59, 0x58, 0x54, 0x00,
- 0x41, 0x46, 0x20, 0x4d, 0x52, 0x42, 0x4a, 0x53, 0x5a, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x41, 0x47, 0x44, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x50,
- 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x4e, 0x52, 0x53, 0x58,
- 0x54, 0x47, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47, 0x44, 0x52, 0x4a,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x53, 0x5a, 0x00, 0x41, 0x46,
- 0x20, 0x4d, 0x52, 0x59, 0x53, 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x55,
- 0x41, 0x53, 0x47, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x59, 0x54, 0x47, 0x44,
- 0x52, 0x53, 0x00, 0x41, 0x46, 0x20, 0x41, 0x44, 0x4a, 0x53, 0x47, 0x00,
- 0x41, 0x46, 0x20, 0x55, 0x54, 0x50, 0x00, 0x41, 0x46, 0x20, 0x5a, 0x47,
- 0x44, 0x52, 0x53, 0x4d, 0x4a, 0x00, 0x41, 0x46, 0x20, 0x53, 0x54, 0x47,
- 0x4d, 0x50, 0x44, 0x52, 0x59, 0x00, 0x41, 0x46, 0x20, 0x52, 0x53, 0x54,
- 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x52, 0x54, 0x47, 0x50, 0x53, 0x00,
- 0x41, 0x46, 0x20, 0x4a, 0x53, 0x47, 0x4d, 0x44, 0x00, 0x41, 0x46, 0x20,
- 0x54, 0x4d, 0x52, 0x00, 0x41, 0x46, 0x20, 0x44, 0x4e, 0x58, 0x54, 0x47,
- 0x4a, 0x00, 0x41, 0x46, 0x20, 0x4d, 0x44, 0x48, 0x53, 0x47, 0x00, 0x41,
- 0x46, 0x20, 0x6d, 0x00, 0x41, 0x46, 0x20, 0x31, 0x32, 0x00, 0x41, 0x46,
- 0x20, 0x2f, 0x31, 0x30, 0x31, 0x00, 0x41, 0x46, 0x20, 0x31, 0x34, 0x00,
- 0x41, 0x46, 0x20, 0x33, 0x30, 0x00, 0x00, 0x50, 0x46, 0x58, 0x20, 0x41,
- 0x20, 0x59, 0x20, 0x31, 0x00, 0x50, 0x46, 0x58, 0x20, 0x41, 0x20, 0x30,
- 0x20, 0x72, 0x65, 0x20, 0x2e, 0x00, 0x50, 0x46, 0x58, 0x20, 0x49, 0x20,
- 0x59, 0x20, 0x31, 0x00, 0x50, 0x46, 0x58, 0x20, 0x49, 0x20, 0x30, 0x20,
- 0x69, 0x6e, 0x20, 0x2e, 0x00, 0x50, 0x46, 0x58, 0x20, 0x55, 0x20, 0x59,
- 0x20, 0x31, 0x00, 0x50, 0x46, 0x58, 0x20, 0x55, 0x20, 0x30, 0x20, 0x75,
- 0x6e, 0x20, 0x2e, 0x00, 0x50, 0x46, 0x58, 0x20, 0x43, 0x20, 0x59, 0x20,
- 0x31, 0x00, 0x50, 0x46, 0x58, 0x20, 0x43, 0x20, 0x30, 0x20, 0x64, 0x65,
- 0x20, 0x2e, 0x00, 0x50, 0x46, 0x58, 0x20, 0x45, 0x20, 0x59, 0x20, 0x31,
- 0x00, 0x50, 0x46, 0x58, 0x20, 0x45, 0x20, 0x30, 0x20, 0x64, 0x69, 0x73,
- 0x20, 0x2e, 0x00, 0x50, 0x46, 0x58, 0x20, 0x46, 0x20, 0x59, 0x20, 0x31,
- 0x00, 0x50, 0x46, 0x58, 0x20, 0x46, 0x20, 0x30, 0x20, 0x63, 0x6f, 0x6e,
- 0x20, 0x2e, 0x00, 0x50, 0x46, 0x58, 0x20, 0x4b, 0x20, 0x59, 0x20, 0x31,
- 0x00, 0x50, 0x46, 0x58, 0x20, 0x4b, 0x20, 0x30, 0x20, 0x70, 0x72, 0x6f,
- 0x20, 0x2e, 0x00, 0x53, 0x46, 0x58, 0x20, 0x56, 0x20, 0x4e, 0x20, 0x32,
- 0x00, 0x53, 0x46, 0x58, 0x20, 0x56, 0x20, 0x65, 0x20, 0x69, 0x76, 0x65,
- 0x20, 0x65, 0x00, 0x53, 0x46, 0x58, 0x20, 0x56, 0x20, 0x30, 0x20, 0x69,
- 0x76, 0x65, 0x20, 0x5b, 0x5e, 0x65, 0x5d, 0x00, 0x53, 0x46, 0x58, 0x20,
- 0x4e, 0x20, 0x59, 0x20, 0x33, 0x00, 0x53, 0x46, 0x58, 0x20, 0x4e, 0x20,
- 0x65, 0x20, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x00, 0x53, 0x46, 0x58, 0x20,
- 0x4e, 0x20, 0x79, 0x20, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
- 0x79, 0x00, 0x53, 0x46, 0x58, 0x20, 0x4e, 0x20, 0x30, 0x20, 0x65, 0x6e,
- 0x20, 0x5b, 0x5e, 0x65, 0x79, 0x5d, 0x00, 0x53, 0x46, 0x58, 0x20, 0x58,
- 0x20, 0x59, 0x20, 0x33, 0x00, 0x53, 0x46, 0x58, 0x20, 0x58, 0x20, 0x65,
- 0x20, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x65, 0x00, 0x53, 0x46, 0x58, 0x20,
- 0x58, 0x20, 0x79, 0x20, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x20, 0x79, 0x00, 0x53, 0x46, 0x58, 0x20, 0x58, 0x20, 0x30, 0x20, 0x65,
- 0x6e, 0x73, 0x20, 0x5b, 0x5e, 0x65, 0x79, 0x5d, 0x00, 0x53, 0x46, 0x58,
- 0x20, 0x48, 0x20, 0x4e, 0x20, 0x32, 0x00, 0x53, 0x46, 0x58, 0x20, 0x48,
- 0x20, 0x79, 0x20, 0x69, 0x65, 0x74, 0x68, 0x20, 0x79, 0x00, 0x53, 0x46,
- 0x58, 0x20, 0x48, 0x20, 0x30, 0x20, 0x74, 0x68, 0x20, 0x5b, 0x5e, 0x79,
- 0x5d, 0x00, 0x53, 0x46, 0x58, 0x20, 0x59, 0x20, 0x59, 0x20, 0x31, 0x00,
- 0x53, 0x46, 0x58, 0x20, 0x59, 0x20, 0x30, 0x20, 0x6c, 0x79, 0x20, 0x2e,
- 0x00, 0x53, 0x46, 0x58, 0x20, 0x47, 0x20, 0x59, 0x20, 0x32, 0x00, 0x53,
- 0x46, 0x58, 0x20, 0x47, 0x20, 0x65, 0x20, 0x69, 0x6e, 0x67, 0x20, 0x65,
- 0x00, 0x53, 0x46, 0x58, 0x20, 0x47, 0x20, 0x30, 0x20, 0x69, 0x6e, 0x67,
- 0x20, 0x5b, 0x5e, 0x65, 0x5d, 0x00, 0x53, 0x46, 0x58, 0x20, 0x4a, 0x20,
- 0x59, 0x20, 0x32, 0x00, 0x53, 0x46, 0x58, 0x20, 0x4a, 0x20, 0x65, 0x20,
- 0x69, 0x6e, 0x67, 0x73, 0x20, 0x65, 0x00, 0x53, 0x46, 0x58, 0x20, 0x4a,
- 0x20, 0x30, 0x20, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x5b, 0x5e, 0x65, 0x5d,
- 0x00, 0x53, 0x46, 0x58, 0x20, 0x44, 0x20, 0x59, 0x20, 0x34, 0x00, 0x53,
- 0x46, 0x58, 0x20, 0x44, 0x20, 0x30, 0x20, 0x64, 0x20, 0x65, 0x00, 0x53,
- 0x46, 0x58, 0x20, 0x44, 0x20, 0x79, 0x20, 0x69, 0x65, 0x64, 0x20, 0x5b,
- 0x5e, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58,
- 0x20, 0x44, 0x20, 0x30, 0x20, 0x65, 0x64, 0x20, 0x5b, 0x5e, 0x65, 0x79,
- 0x5d, 0x00, 0x53, 0x46, 0x58, 0x20, 0x44, 0x20, 0x30, 0x20, 0x65, 0x64,
- 0x20, 0x5b, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53, 0x46,
- 0x58, 0x20, 0x54, 0x20, 0x4e, 0x20, 0x34, 0x00, 0x53, 0x46, 0x58, 0x20,
- 0x54, 0x20, 0x30, 0x20, 0x73, 0x74, 0x20, 0x65, 0x00, 0x53, 0x46, 0x58,
- 0x20, 0x54, 0x20, 0x79, 0x20, 0x69, 0x65, 0x73, 0x74, 0x20, 0x5b, 0x5e,
- 0x61, 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58, 0x20,
- 0x54, 0x20, 0x30, 0x20, 0x65, 0x73, 0x74, 0x20, 0x5b, 0x61, 0x65, 0x69,
- 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58, 0x20, 0x54, 0x20, 0x30,
- 0x20, 0x65, 0x73, 0x74, 0x20, 0x5b, 0x5e, 0x65, 0x79, 0x5d, 0x00, 0x53,
- 0x46, 0x58, 0x20, 0x52, 0x20, 0x59, 0x20, 0x34, 0x00, 0x53, 0x46, 0x58,
- 0x20, 0x52, 0x20, 0x30, 0x20, 0x72, 0x20, 0x65, 0x00, 0x53, 0x46, 0x58,
- 0x20, 0x52, 0x20, 0x79, 0x20, 0x69, 0x65, 0x72, 0x20, 0x5b, 0x5e, 0x61,
- 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58, 0x20, 0x52,
- 0x20, 0x30, 0x20, 0x65, 0x72, 0x20, 0x5b, 0x61, 0x65, 0x69, 0x6f, 0x75,
- 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58, 0x20, 0x52, 0x20, 0x30, 0x20, 0x65,
- 0x72, 0x20, 0x5b, 0x5e, 0x65, 0x79, 0x5d, 0x00, 0x53, 0x46, 0x58, 0x20,
- 0x5a, 0x20, 0x59, 0x20, 0x34, 0x00, 0x53, 0x46, 0x58, 0x20, 0x5a, 0x20,
- 0x30, 0x20, 0x72, 0x73, 0x20, 0x65, 0x00, 0x53, 0x46, 0x58, 0x20, 0x5a,
- 0x20, 0x79, 0x20, 0x69, 0x65, 0x72, 0x73, 0x20, 0x5b, 0x5e, 0x61, 0x65,
- 0x69, 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58, 0x20, 0x5a, 0x20,
- 0x30, 0x20, 0x65, 0x72, 0x73, 0x20, 0x5b, 0x61, 0x65, 0x69, 0x6f, 0x75,
- 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58, 0x20, 0x5a, 0x20, 0x30, 0x20, 0x65,
- 0x72, 0x73, 0x20, 0x5b, 0x5e, 0x65, 0x79, 0x5d, 0x00, 0x53, 0x46, 0x58,
- 0x20, 0x53, 0x20, 0x59, 0x20, 0x34, 0x00, 0x53, 0x46, 0x58, 0x20, 0x53,
- 0x20, 0x79, 0x20, 0x69, 0x65, 0x73, 0x20, 0x5b, 0x5e, 0x61, 0x65, 0x69,
- 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58, 0x20, 0x53, 0x20, 0x30,
- 0x20, 0x73, 0x20, 0x5b, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x79, 0x00,
- 0x53, 0x46, 0x58, 0x20, 0x53, 0x20, 0x30, 0x20, 0x65, 0x73, 0x20, 0x5b,
- 0x73, 0x78, 0x7a, 0x68, 0x5d, 0x00, 0x53, 0x46, 0x58, 0x20, 0x53, 0x20,
- 0x30, 0x20, 0x73, 0x20, 0x5b, 0x5e, 0x73, 0x78, 0x7a, 0x68, 0x79, 0x5d,
- 0x00, 0x53, 0x46, 0x58, 0x20, 0x50, 0x20, 0x59, 0x20, 0x33, 0x00, 0x53,
- 0x46, 0x58, 0x20, 0x50, 0x20, 0x79, 0x20, 0x69, 0x6e, 0x65, 0x73, 0x73,
- 0x20, 0x5b, 0x5e, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53,
- 0x46, 0x58, 0x20, 0x50, 0x20, 0x30, 0x20, 0x6e, 0x65, 0x73, 0x73, 0x20,
- 0x5b, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x79, 0x00, 0x53, 0x46, 0x58,
- 0x20, 0x50, 0x20, 0x30, 0x20, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x5b, 0x5e,
- 0x79, 0x5d, 0x00, 0x53, 0x46, 0x58, 0x20, 0x4d, 0x20, 0x59, 0x20, 0x31,
- 0x00, 0x53, 0x46, 0x58, 0x20, 0x4d, 0x20, 0x30, 0x20, 0x27, 0x73, 0x20,
- 0x2e, 0x00, 0x53, 0x46, 0x58, 0x20, 0x42, 0x20, 0x59, 0x20, 0x33, 0x00,
- 0x53, 0x46, 0x58, 0x20, 0x42, 0x20, 0x30, 0x20, 0x61, 0x62, 0x6c, 0x65,
- 0x20, 0x5b, 0x5e, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x00, 0x53, 0x46,
- 0x58, 0x20, 0x42, 0x20, 0x30, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x65,
- 0x65, 0x00, 0x53, 0x46, 0x58, 0x20, 0x42, 0x20, 0x65, 0x20, 0x61, 0x62,
- 0x6c, 0x65, 0x20, 0x5b, 0x5e, 0x61, 0x65, 0x69, 0x6f, 0x75, 0x5d, 0x65,
- 0x00, 0x53, 0x46, 0x58, 0x20, 0x4c, 0x20, 0x59, 0x20, 0x31, 0x00, 0x53,
- 0x46, 0x58, 0x20, 0x4c, 0x20, 0x30, 0x20, 0x6d, 0x65, 0x6e, 0x74, 0x20,
- 0x2e, 0x00, 0x00, 0x61, 0x00, 0x65, 0x69, 0x00, 0x65, 0x69, 0x00, 0x61,
- 0x00, 0x61, 0x00, 0x65, 0x79, 0x00, 0x65, 0x79, 0x00, 0x61, 0x00, 0x61,
- 0x69, 0x00, 0x69, 0x65, 0x00, 0x69, 0x65, 0x00, 0x61, 0x69, 0x00, 0x61,
- 0x6c, 0x6f, 0x74, 0x00, 0x61, 0x20, 0x6c, 0x6f, 0x74, 0x00, 0x61, 0x72,
- 0x65, 0x00, 0x61, 0x69, 0x72, 0x00, 0x61, 0x72, 0x65, 0x00, 0x65, 0x61,
- 0x72, 0x00, 0x61, 0x72, 0x65, 0x00, 0x65, 0x69, 0x72, 0x00, 0x61, 0x69,
- 0x72, 0x00, 0x61, 0x72, 0x65, 0x00, 0x61, 0x69, 0x72, 0x00, 0x65, 0x72,
- 0x65, 0x00, 0x65, 0x72, 0x65, 0x00, 0x61, 0x69, 0x72, 0x00, 0x65, 0x72,
- 0x65, 0x00, 0x65, 0x61, 0x72, 0x00, 0x65, 0x72, 0x65, 0x00, 0x65, 0x69,
- 0x72, 0x00, 0x65, 0x61, 0x72, 0x00, 0x61, 0x72, 0x65, 0x00, 0x65, 0x61,
- 0x72, 0x00, 0x61, 0x69, 0x72, 0x00, 0x65, 0x61, 0x72, 0x00, 0x65, 0x72,
- 0x65, 0x00, 0x65, 0x69, 0x72, 0x00, 0x61, 0x72, 0x65, 0x00, 0x65, 0x69,
- 0x72, 0x00, 0x65, 0x72, 0x65, 0x00, 0x63, 0x68, 0x00, 0x74, 0x65, 0x00,
- 0x74, 0x65, 0x00, 0x63, 0x68, 0x00, 0x63, 0x68, 0x00, 0x74, 0x69, 0x00,
- 0x74, 0x69, 0x00, 0x63, 0x68, 0x00, 0x63, 0x68, 0x00, 0x74, 0x75, 0x00,
- 0x74, 0x75, 0x00, 0x63, 0x68, 0x00, 0x63, 0x68, 0x00, 0x73, 0x00, 0x73,
- 0x00, 0x63, 0x68, 0x00, 0x63, 0x68, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x63,
- 0x68, 0x00, 0x66, 0x00, 0x70, 0x68, 0x00, 0x70, 0x68, 0x00, 0x66, 0x00,
- 0x67, 0x68, 0x00, 0x66, 0x00, 0x66, 0x00, 0x67, 0x68, 0x00, 0x69, 0x00,
- 0x69, 0x67, 0x68, 0x00, 0x69, 0x67, 0x68, 0x00, 0x69, 0x00, 0x69, 0x00,
- 0x75, 0x79, 0x00, 0x75, 0x79, 0x00, 0x69, 0x00, 0x69, 0x00, 0x65, 0x65,
- 0x00, 0x65, 0x65, 0x00, 0x69, 0x00, 0x6a, 0x00, 0x64, 0x69, 0x00, 0x64,
- 0x69, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0x67, 0x67, 0x00, 0x67, 0x67, 0x00,
- 0x6a, 0x00, 0x6a, 0x00, 0x67, 0x65, 0x00, 0x67, 0x65, 0x00, 0x6a, 0x00,
- 0x73, 0x00, 0x74, 0x69, 0x00, 0x74, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00,
- 0x63, 0x69, 0x00, 0x63, 0x69, 0x00, 0x73, 0x00, 0x6b, 0x00, 0x63, 0x63,
- 0x00, 0x63, 0x63, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x71, 0x75, 0x00, 0x71,
- 0x75, 0x00, 0x6b, 0x00, 0x6b, 0x77, 0x00, 0x71, 0x75, 0x00, 0x6f, 0x00,
- 0x65, 0x61, 0x75, 0x00, 0x65, 0x61, 0x75, 0x00, 0x6f, 0x00, 0x6f, 0x00,
- 0x65, 0x77, 0x00, 0x65, 0x77, 0x00, 0x6f, 0x00, 0x6f, 0x6f, 0x00, 0x65,
- 0x77, 0x00, 0x65, 0x77, 0x00, 0x6f, 0x6f, 0x00, 0x65, 0x77, 0x00, 0x75,
- 0x69, 0x00, 0x75, 0x69, 0x00, 0x65, 0x77, 0x00, 0x6f, 0x6f, 0x00, 0x75,
- 0x69, 0x00, 0x75, 0x69, 0x00, 0x6f, 0x6f, 0x00, 0x65, 0x77, 0x00, 0x75,
- 0x00, 0x75, 0x00, 0x65, 0x77, 0x00, 0x6f, 0x6f, 0x00, 0x75, 0x00, 0x75,
- 0x00, 0x6f, 0x6f, 0x00, 0x75, 0x00, 0x6f, 0x65, 0x00, 0x6f, 0x65, 0x00,
- 0x75, 0x00, 0x75, 0x00, 0x69, 0x65, 0x75, 0x00, 0x69, 0x65, 0x75, 0x00,
- 0x75, 0x00, 0x75, 0x65, 0x00, 0x65, 0x77, 0x00, 0x65, 0x77, 0x00, 0x75,
- 0x65, 0x00, 0x75, 0x66, 0x66, 0x00, 0x6f, 0x75, 0x67, 0x68, 0x00, 0x6f,
- 0x6f, 0x00, 0x69, 0x65, 0x75, 0x00, 0x69, 0x65, 0x75, 0x00, 0x6f, 0x6f,
- 0x00, 0x69, 0x65, 0x72, 0x00, 0x65, 0x61, 0x72, 0x00, 0x65, 0x61, 0x72,
- 0x00, 0x69, 0x65, 0x72, 0x00, 0x65, 0x61, 0x72, 0x00, 0x61, 0x69, 0x72,
- 0x00, 0x61, 0x69, 0x72, 0x00, 0x65, 0x61, 0x72, 0x00, 0x77, 0x00, 0x71,
- 0x75, 0x00, 0x71, 0x75, 0x00, 0x77, 0x00, 0x7a, 0x00, 0x73, 0x73, 0x00,
- 0x73, 0x73, 0x00, 0x7a, 0x00, 0x73, 0x68, 0x75, 0x6e, 0x00, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x73, 0x68, 0x75, 0x6e, 0x00, 0x73, 0x69, 0x6f, 0x6e,
- 0x00, 0x73, 0x68, 0x75, 0x6e, 0x00, 0x63, 0x69, 0x6f, 0x6e, 0x00, 0x73,
- 0x69, 0x7a, 0x65, 0x00, 0x63, 0x69, 0x73, 0x65, 0x00, 0x00, 0x54, 0x52,
- 0x59, 0x20, 0x65, 0x73, 0x69, 0x61, 0x6e, 0x72, 0x74, 0x6f, 0x6c, 0x63,
- 0x64, 0x75, 0x67, 0x6d, 0x70, 0x68, 0x62, 0x79, 0x66, 0x76, 0x6b, 0x77,
- 0x7a, 0x45, 0x53, 0x49, 0x41, 0x4e, 0x52, 0x54, 0x4f, 0x4c, 0x43, 0x44,
- 0x55, 0x47, 0x4d, 0x50, 0x48, 0x42, 0x59, 0x46, 0x56, 0x4b, 0x57, 0x5a,
- 0x27, 0x00, 0x49, 0x43, 0x4f, 0x4e, 0x56, 0x20, 0x31, 0x00, 0x49, 0x43,
- 0x4f, 0x4e, 0x56, 0x20, 0xe2, 0x80, 0x99, 0x20, 0x27, 0x00, 0x4e, 0x4f,
- 0x53, 0x55, 0x47, 0x47, 0x45, 0x53, 0x54, 0x20, 0x21, 0x00, 0x43, 0x4f,
- 0x4d, 0x50, 0x4f, 0x55, 0x4e, 0x44, 0x4d, 0x49, 0x4e, 0x20, 0x31, 0x00,
- 0x4f, 0x4e, 0x4c, 0x59, 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x55,
- 0x4e, 0x44, 0x20, 0x63, 0x00, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x55, 0x4e,
- 0x44, 0x52, 0x55, 0x4c, 0x45, 0x20, 0x32, 0x00, 0x43, 0x4f, 0x4d, 0x50,
- 0x4f, 0x55, 0x4e, 0x44, 0x52, 0x55, 0x4c, 0x45, 0x20, 0x6e, 0x2a, 0x31,
- 0x74, 0x00, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x55, 0x4e, 0x44, 0x52, 0x55,
- 0x4c, 0x45, 0x20, 0x6e, 0x2a, 0x6d, 0x70, 0x00, 0x57, 0x4f, 0x52, 0x44,
- 0x43, 0x48, 0x41, 0x52, 0x53, 0x20, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
- 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0xc2, 0x30, 0x4b, 0xc5, 0x37, 0x00,
- 0x00, 0xd0, 0x37, 0x00, 0x00, 0xe1, 0x37, 0x00, 0x00, 0xf2, 0x37, 0x00,
- 0x00, 0x03, 0x38, 0x00, 0x00, 0x0e, 0x38, 0x00, 0x00, 0x19, 0x38, 0x00,
- 0x00, 0x24, 0x38, 0x00, 0x00, 0x2f, 0x38, 0x00, 0x00, 0x3a, 0x38, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x38, 0x00, 0x00, 0x34, 0x52, 0x00,
- 0x00, 0xb3, 0x6b, 0x00, 0x00, 0x24, 0x89, 0x00, 0x00, 0x98, 0x98, 0x00,
- 0x00, 0x51, 0xa4, 0x00, 0x00, 0x96, 0xae, 0x00, 0x00, 0x2f, 0xbe, 0x00,
- 0x00, 0x05, 0xcf, 0x00, 0x00, 0xba, 0xd6, 0x00, 0x00, 0x80, 0xdf, 0x00,
- 0x00, 0x57, 0xeb, 0x00, 0x00, 0xd6, 0xfb, 0x00, 0x00, 0xb9, 0x1a, 0x01,
- 0x00, 0x72, 0x26, 0x01, 0x00, 0x3f, 0x2e, 0x01, 0x00, 0xd0, 0x41, 0x01,
- 0x00, 0x77, 0x43, 0x01, 0x00, 0xe3, 0x51, 0x01, 0x00, 0xc3, 0x6f, 0x01,
- 0x00, 0xe5, 0x80, 0x01, 0x00, 0x54, 0x84, 0x01, 0x00, 0x12, 0x8b, 0x01,
- 0x00, 0x72, 0x95, 0x01, 0x00, 0x49, 0x96, 0x01, 0x00, 0x3e, 0x99, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x5a, 0x9c, 0x01, 0x00, 0x6a, 0xf1, 0x01, 0x00, 0x5b, 0x3c, 0x02,
- 0x00, 0xfd, 0xbc, 0x02, 0x00, 0x32, 0x04, 0x03, 0x00, 0xe9, 0x40, 0x03,
- 0x00, 0x40, 0x7a, 0x03, 0x00, 0x73, 0xa5, 0x03, 0x00, 0x30, 0xdb, 0x03,
- 0x00, 0x76, 0x14, 0x04, 0x00, 0x1d, 0x20, 0x04, 0x00, 0x72, 0x2a, 0x04,
- 0x00, 0x93, 0x52, 0x04, 0x00, 0x2f, 0x9e, 0x04, 0x00, 0x94, 0xc5, 0x04,
- 0x00, 0xf3, 0xea, 0x04, 0x00, 0x8a, 0x59, 0x05, 0x00, 0xb6, 0x5f, 0x05,
- 0x00, 0x96, 0x97, 0x05, 0x00, 0x73, 0x2e, 0x06, 0x00, 0x04, 0x74, 0x06,
- 0x00, 0x2d, 0x8d, 0x06, 0x00, 0x3c, 0xa3, 0x06, 0x00, 0xb2, 0xc6, 0x06,
- 0x00, 0x19, 0xc8, 0x06, 0x00, 0x00, 0xcc, 0x06, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x01, 0x40, 0x02, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x73,
- 0x02, 0x74, 0x06, 0x00, 0x03, 0x40, 0x04, 0x74, 0x00, 0x40, 0x05, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x06, 0x00, 0x01, 0x40, 0x04,
- 0x64, 0x00, 0x40, 0x05, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74,
- 0x06, 0x00, 0x01, 0x40, 0x04, 0x64, 0x00, 0x40, 0x05, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x01, 0x40, 0x02, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x01, 0x40, 0x02, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x01, 0x40, 0x02, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x01, 0x40, 0x02, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x01, 0x40, 0x02, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x01, 0x40, 0x02, 0x68, 0x00, 0xc1, 0x41, 0x3a, 0x79, 0x00, 0x7b, 0x00,
- 0x84, 0x00, 0x99, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0xf3, 0x00, 0xf5, 0x00, 0xf7, 0x00,
- 0x04, 0x01, 0x12, 0x01, 0x16, 0x01, 0x00, 0x00, 0x33, 0x01, 0x3c, 0x01,
- 0x55, 0x01, 0x00, 0x00, 0x6c, 0x01, 0x75, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x8c, 0x01, 0xa5, 0x01, 0x76, 0x02, 0x35, 0x03, 0x70, 0x04,
- 0xc6, 0x04, 0x35, 0x05, 0xe6, 0x05, 0x1b, 0x06, 0x57, 0x06, 0x5c, 0x06,
- 0x94, 0x06, 0x24, 0x0b, 0x8d, 0x0c, 0x00, 0x00, 0x81, 0x10, 0x63, 0x11,
- 0xa4, 0x11, 0xeb, 0x14, 0x7d, 0x16, 0x80, 0x17, 0xda, 0x18, 0x00, 0x00,
- 0x4e, 0x19, 0x5b, 0x19, 0x8f, 0x19, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x41,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x41, 0x02, 0x43, 0x04,
- 0x4d, 0x06, 0x53, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06,
- 0x00, 0x00, 0xe4, 0x00, 0x00, 0x41, 0x02, 0x4c, 0x06, 0x54, 0x0a, 0x00,
- 0x07, 0x45, 0x4c, 0x44, 0x00, 0x40, 0x07, 0x55, 0x00, 0xe2, 0x00, 0x00,
- 0x48, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x43, 0x02, 0x44,
- 0x04, 0x50, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe7,
- 0x00, 0x00, 0x41, 0x02, 0x42, 0x07, 0x43, 0x09, 0x44, 0x0b, 0x4e, 0x0f,
- 0x54, 0x11, 0x00, 0x00, 0x40, 0x00, 0x49, 0x4b, 0x00, 0x00, 0x00, 0x00,
- 0x07, 0x40, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x44, 0x02, 0x00, 0x06, 0x40, 0x07, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe3, 0x00, 0x00, 0x41, 0x02, 0x44, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x07, 0xe2, 0x53, 0x00, 0x5a, 0x04, 0x40, 0x08, 0x49, 0x00, 0x40, 0x07,
- 0x55, 0x53, 0x00, 0x40, 0x07, 0x4c, 0x00, 0xe6, 0x00, 0x00, 0x42, 0x02,
- 0x43, 0x04, 0x49, 0x06, 0x4f, 0x0c, 0x52, 0x0e, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x41, 0x00,
- 0x43, 0x04, 0x4c, 0x09, 0x50, 0x0b, 0x40, 0x00, 0x50, 0x00, 0x40, 0x06,
- 0x49, 0x49, 0x00, 0x00, 0x07, 0x40, 0x00, 0x43, 0x41, 0x00, 0xe3, 0x4d,
- 0x00, 0x50, 0x02, 0x56, 0x0e, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x49, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x41, 0x00, 0x4f, 0x05, 0x40,
- 0x07, 0x43, 0x53, 0x00, 0x40, 0x07, 0x4c, 0x00, 0xe2, 0x00, 0x00, 0x54,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x63, 0x00, 0x6c, 0x06, 0x72, 0x0d,
- 0x40, 0x07, 0x68, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x79, 0x61, 0x68,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xea, 0x62, 0x00, 0x64, 0x1c, 0x65,
- 0x21, 0x69, 0x58, 0x6e, 0x71, 0x6f, 0x76, 0x72, 0x7f, 0x73, 0x95, 0x75,
- 0x9c, 0x79, 0xa1, 0xe3, 0x61, 0x00, 0x6f, 0x0e, 0x79, 0x13, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x00,
- 0x40, 0x07, 0x74, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x75, 0x6c, 0x00,
- 0xe4, 0x00, 0x00, 0x42, 0x02, 0x6c, 0x09, 0x72, 0x1c, 0x00, 0x07, 0x40,
- 0x00, 0x6f, 0x6f, 0x6b, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x65, 0x65, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x74, 0x68, 0x79, 0x00, 0xe3, 0x64, 0x00, 0x67, 0x06,
- 0x6c, 0x0c, 0x40, 0x07, 0x6a, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x69,
- 0x6c, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0x40, 0x09, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x68, 0x00, 0x6d, 0x05, 0x40, 0x07, 0x61, 0x6d, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6c,
- 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x6a, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0xea,
- 0x00, 0x00, 0x44, 0x02, 0x61, 0x0c, 0x63, 0x1d, 0x65, 0x2e, 0x68, 0x35,
- 0x6f, 0x5f, 0x72, 0x71, 0x74, 0x82, 0x75, 0x9d, 0x00, 0x07, 0x40, 0x00,
- 0x62, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x64, 0x00, 0x70,
- 0x05, 0x40, 0x07, 0x69, 0x61, 0x00, 0x40, 0x07, 0x75, 0x6c, 0x63, 0x6f,
- 0x00, 0xe2, 0x65, 0x00, 0x72, 0x08, 0x40, 0x07, 0x6e, 0x74, 0x75, 0x72,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x76, 0x65, 0x64, 0x6f,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x1c, 0x40, 0x07, 0x65, 0x61,
- 0x6e, 0x00, 0xe3, 0x62, 0x00, 0x72, 0x04, 0x73, 0x0a, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x07, 0x6e, 0x61, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x6c, 0x6c, 0x65, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x08,
- 0x40, 0x07, 0x63, 0x61, 0x67, 0x75, 0x61, 0x00, 0x40, 0x07, 0x74, 0x61,
- 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x08, 0x40, 0x00, 0x70, 0x6f, 0x6c, 0x69,
- 0x73, 0x00, 0x40, 0x07, 0x78, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x06, 0x6f,
- 0x0c, 0x73, 0x10, 0x40, 0x07, 0x65, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x76,
- 0x65, 0x58, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x66, 0x00,
- 0x72, 0x04, 0x40, 0x07, 0x66, 0x00, 0x40, 0x09, 0x61, 0x00, 0xfb, 0x61,
- 0x00, 0x00, 0x64, 0x1f, 0x00, 0x65, 0x46, 0x00, 0x68, 0x72, 0x00, 0x69,
- 0x78, 0x00, 0x6b, 0x9d, 0x00, 0x6c, 0xa3, 0x00, 0x6d, 0xa8, 0x00, 0x6f,
- 0xb7, 0x00, 0x72, 0xd3, 0x00, 0x76, 0xfe, 0x00, 0xe4, 0x00, 0x00, 0x6d,
- 0x02, 0x6e, 0x0b, 0x72, 0x14, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x06, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x07, 0xe4, 0x54, 0x00, 0x61, 0x06, 0x65, 0x0b, 0x69, 0x12,
- 0x40, 0x07, 0x68, 0x69, 0x73, 0x00, 0x40, 0x07, 0x6d, 0x73, 0x00, 0x40,
- 0x07, 0x72, 0x6c, 0x65, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x1a, 0xe3,
- 0x61, 0x00, 0x65, 0x0c, 0x69, 0x0e, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x64, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x75, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x61, 0x72, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x05, 0x40, 0x07, 0x61, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x69,
- 0x6e, 0x73, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x72, 0x61, 0x6c, 0x74, 0x79, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x12, 0xe2, 0x66, 0x00, 0x70, 0x09, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x68, 0x00, 0x40, 0x09,
- 0x69, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x08, 0x40, 0x09, 0x6e, 0x61,
- 0x6c, 0x69, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x13, 0xe2, 0x6e, 0x00,
- 0x74, 0x09, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6e, 0x6e, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x12, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x07, 0x6c,
- 0x00, 0xe6, 0x67, 0x00, 0x6c, 0x06, 0x6e, 0x0d, 0x6f, 0x1d, 0x72, 0x23,
- 0x73, 0x2b, 0x40, 0x07, 0x65, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x66, 0x72,
- 0x69, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x6c, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x6f, 0x66, 0x6c, 0x6f, 0x74, 0x00, 0xe2, 0x63, 0x00,
- 0x6f, 0x15, 0xe2, 0x68, 0x00, 0x75, 0x07, 0x40, 0x07, 0x79, 0x6c, 0x75,
- 0x73, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x70, 0x69, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x70, 0x00, 0xe2, 0x67, 0x00, 0x72, 0x1d, 0xe1, 0x68, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x61, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x25, 0x00, 0x00, 0xe2, 0x63,
- 0x00, 0x6b, 0x0c, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x05, 0x40,
- 0x07, 0x6e, 0x73, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x67,
- 0x2b, 0x69, 0x30, 0x6c, 0x37, 0x6e, 0x3d, 0x72, 0x4d, 0x75, 0x6e, 0x00,
- 0x07, 0xe4, 0x6d, 0x00, 0x6e, 0x08, 0x73, 0x0c, 0x74, 0x1b, 0x40, 0x07,
- 0x65, 0x6d, 0x6e, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x61, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x7a, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x68, 0x61, 0x00, 0x40, 0x07, 0x69, 0x65, 0x00, 0x40,
- 0x00, 0x6c, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x61, 0x69, 0x61, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x73, 0x00, 0x77, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2,
- 0x63, 0x00, 0x70, 0x06, 0x40, 0x07, 0x6f, 0x6c, 0x61, 0x00, 0xe1, 0x70,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x61,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x0d, 0x73, 0x25, 0x40, 0x00, 0x73, 0x63,
- 0x61, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x65, 0x73, 0x00, 0xe3, 0x6c, 0x00,
- 0x6e, 0x05, 0x72, 0x0c, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x61,
- 0x6c, 0x64, 0x6f, 0x00, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x07, 0x74,
- 0x69, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x6d, 0x04, 0x72, 0x27, 0x40, 0x07,
- 0x62, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1a, 0xe1, 0x64, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x08, 0x00, 0x07, 0x40, 0x07, 0x62, 0x61, 0x64,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x6a, 0x61, 0x64, 0x00, 0x40, 0x07, 0x64,
- 0x00, 0x40, 0x07, 0x69, 0x6d, 0x61, 0x6e, 0x00, 0xe7, 0x64, 0x00, 0x6b,
- 0x04, 0x6c, 0x09, 0x6d, 0x0f, 0x6e, 0x14, 0x72, 0x18, 0x73, 0x28, 0x40,
- 0x07, 0x61, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x65,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x65, 0x00, 0x40, 0x07, 0x75, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x06, 0x40, 0x09, 0x61, 0x6c, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x68, 0x61, 0x00, 0x40, 0x07, 0x61, 0x78,
- 0x00, 0xe5, 0x62, 0x00, 0x68, 0x05, 0x69, 0x0e, 0x6b, 0x23, 0x72, 0x28,
- 0x40, 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x74, 0x6f, 0x76,
- 0x61, 0x00, 0xe3, 0x68, 0x00, 0x74, 0x06, 0x76, 0x0a, 0x40, 0x07, 0x69,
- 0x74, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x61, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xc1, 0x61, 0x1a,
- 0x39, 0x00, 0x3b, 0x00, 0x9f, 0x00, 0x09, 0x01, 0x55, 0x01, 0x80, 0x01,
- 0xfd, 0x01, 0x2b, 0x02, 0x7a, 0x02, 0x8b, 0x02, 0x00, 0x00, 0xdd, 0x02,
- 0xe3, 0x02, 0x59, 0x03, 0x89, 0x03, 0x9b, 0x03, 0xa1, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0xe5, 0x03, 0x04, 0x04, 0x49, 0x04, 0x4f, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x71, 0x04, 0x87, 0x04, 0x00, 0x07, 0xe7, 0x00, 0x00, 0x62,
- 0x02, 0x64, 0x1b, 0x6d, 0x21, 0x6e, 0x32, 0x72, 0x3b, 0x73, 0x46, 0x00,
- 0x08, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x09,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x06, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x64, 0x69, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x00, 0x00, 0x67, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x64, 0x6f,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x63, 0x00, 0xe1, 0x6b, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09,
- 0xe4, 0x61, 0x00, 0x65, 0x1a, 0x69, 0x3e, 0x75, 0x57, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x79, 0x0c, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0xe2,
- 0x65, 0x00, 0x72, 0x02, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x0b, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0xe3,
- 0x67, 0x00, 0x6f, 0x09, 0x72, 0x0d, 0x40, 0x07, 0x65, 0x6e, 0x73, 0x69,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6f, 0x00,
- 0x40, 0x07, 0x71, 0x75, 0x65, 0x72, 0x71, 0x75, 0x65, 0x00, 0xe7, 0x61,
- 0x00, 0x65, 0x07, 0x69, 0x0e, 0x6d, 0x21, 0x6f, 0x27, 0x75, 0x32, 0x79,
- 0x37, 0x40, 0x07, 0x74, 0x72, 0x61, 0x7a, 0x00, 0x40, 0x07, 0x73, 0x74,
- 0x69, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x6e, 0x08, 0x40, 0x07, 0x69, 0x61,
- 0x64, 0x65, 0x73, 0x00, 0x40, 0x07, 0x64, 0x6f, 0x72, 0x00, 0x40, 0x07,
- 0x65, 0x6e, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x74, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e,
- 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x6f, 0x1b, 0x72, 0x1d, 0x40,
- 0x07, 0x6e, 0x00, 0xe3, 0x62, 0x00, 0x6e, 0x07, 0x72, 0x09, 0x40, 0x07,
- 0x61, 0x72, 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6d, 0x69,
- 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe7, 0x63, 0x00,
- 0x69, 0x02, 0x6a, 0x09, 0x6d, 0x1e, 0x70, 0x25, 0x75, 0x2a, 0x78, 0x39,
- 0x00, 0x07, 0x40, 0x07, 0x63, 0x68, 0x65, 0x6d, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x62, 0x65, 0x72, 0x74,
- 0x00, 0x40, 0x07, 0x70, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x61, 0x6e, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x24, 0x69, 0x28, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x09, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x16, 0xe2, 0x6e, 0x00, 0x72, 0x0d,
- 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x6f,
- 0x00, 0x40, 0x07, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x6f, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
- 0xe3, 0x65, 0x00, 0x69, 0x1d, 0x6f, 0x2d, 0xe2, 0x6e, 0x00, 0x72, 0x05,
- 0x40, 0x07, 0x69, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0xe1, 0x65, 0x00, 0xe2, 0x62, 0x00, 0x72, 0x04, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe1,
- 0x71, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6e,
- 0x04, 0x40, 0x06, 0x6e, 0x00, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x6d, 0x62, 0x72, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x00,
- 0xe7, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x67, 0x13, 0x6e, 0x1b, 0x6f,
- 0x1f, 0x73, 0x24, 0x00, 0x07, 0x40, 0x00, 0x61, 0x62, 0x61, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07,
- 0x68, 0x69, 0x65, 0x72, 0x69, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07,
- 0x74, 0x68, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x02, 0x6f, 0x06, 0x73, 0x0a,
- 0x74, 0x0e, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x61, 0x69, 0x72, 0x00, 0x40, 0x07,
- 0x61, 0x69, 0x64, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x14, 0x68, 0x47, 0x69,
- 0x50, 0x73, 0x5c, 0x79, 0x63, 0xe2, 0x68, 0x00, 0x6e, 0x0d, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x62, 0x61, 0x64, 0x00, 0x00,
- 0x07, 0xe2, 0x67, 0x00, 0x6e, 0x1b, 0xe2, 0x68, 0x00, 0x72, 0x12, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07,
- 0x65, 0x73, 0x00, 0x00, 0x06, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x00, 0x00,
- 0x64, 0x02, 0x74, 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07,
- 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x07, 0x74, 0x61, 0x74, 0x65, 0x00, 0x40, 0x07, 0x73, 0x6f,
- 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x11, 0x6f, 0x18, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x74, 0x06, 0x00, 0x07, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x07, 0x67, 0x68, 0x74, 0x79, 0x00, 0xe2, 0x68, 0x00,
- 0x72, 0x05, 0x40, 0x07, 0x61, 0x64, 0x00, 0x40, 0x07, 0x61, 0x76, 0x69,
- 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x05, 0x40, 0x07,
- 0x61, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x6b, 0x00, 0x40, 0x07, 0x6e, 0x7a,
- 0x6f, 0x00, 0xe5, 0x65, 0x00, 0x68, 0x05, 0x69, 0x30, 0x6f, 0x35, 0x73,
- 0x37, 0x40, 0x07, 0x72, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6f,
- 0x15, 0x40, 0x07, 0x72, 0x64, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x05, 0x40,
- 0x07, 0x63, 0x61, 0x00, 0x40, 0x07, 0x61, 0x74, 0x7a, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x61,
- 0x00, 0x6f, 0x0f, 0x74, 0x13, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x06, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x70, 0x00,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x1c, 0x69, 0x21,
- 0x6d, 0x29, 0x6f, 0x2e, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x0f, 0x00,
- 0x07, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x72, 0x04, 0x00, 0x07, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x69, 0x72, 0x61, 0x00, 0x40, 0x07, 0x65, 0x61,
- 0x00, 0x40, 0x07, 0x70, 0x6c, 0x61, 0x6e, 0x6f, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x64, 0x73, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x64, 0x72, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x19, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x65,
- 0x05, 0x6f, 0x09, 0x40, 0x07, 0x64, 0x6f, 0x00, 0x40, 0x07, 0x7a, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x68, 0x65, 0x69, 0x6d, 0x65, 0x72,
- 0x00, 0xff, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x5b, 0x00, 0x65,
- 0x60, 0x00, 0x68, 0xce, 0x00, 0x69, 0xdf, 0x00, 0x6d, 0xf0, 0x00, 0x6f,
- 0xf5, 0x00, 0x70, 0x00, 0x01, 0x72, 0x0f, 0x01, 0x73, 0x17, 0x01, 0x74,
- 0x20, 0x01, 0x75, 0x26, 0x01, 0x77, 0x34, 0x01, 0x79, 0x39, 0x01, 0x00,
- 0x0a, 0xe7, 0x64, 0x00, 0x6c, 0x0c, 0x6e, 0x11, 0x70, 0x16, 0x72, 0x1d,
- 0x74, 0x2a, 0x7a, 0x38, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x75,
- 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x61, 0x00, 0x40, 0x07, 0x64,
- 0x61, 0x00, 0x40, 0x00, 0x65, 0x64, 0x69, 0x61, 0x00, 0xe2, 0x69, 0x00,
- 0x75, 0x06, 0x40, 0x07, 0x6c, 0x6c, 0x6f, 0x00, 0x00, 0x07, 0xe2, 0x65,
- 0x00, 0x69, 0x07, 0x40, 0x07, 0x72, 0x61, 0x73, 0x75, 0x00, 0x00, 0x07,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe4,
- 0x6c, 0x00, 0x6e, 0x05, 0x72, 0x13, 0x73, 0x5f, 0x40, 0x07, 0x69, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x74,
- 0x65, 0x70, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x07, 0x40, 0x07, 0x73, 0x69,
- 0x61, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x2c, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x04, 0x00, 0x09, 0x00, 0x07, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x09,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x0b, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x07, 0x72, 0x69, 0x63, 0x00,
- 0x40, 0x07, 0x72, 0x73, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x67, 0x02, 0x73,
- 0x06, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x68, 0x00, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6f,
- 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x72, 0x6f,
- 0x00, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x07, 0x69, 0x74, 0x73, 0x61,
- 0x72, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x00, 0x40,
- 0x07, 0x72, 0x61, 0x6b, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x07, 0x40, 0x07,
- 0x64, 0x73, 0x65, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x79, 0x00,
- 0x00, 0x07, 0xfc, 0x61, 0x00, 0x00, 0x63, 0x7b, 0x00, 0x64, 0x84, 0x00,
- 0x67, 0x42, 0x01, 0x69, 0x33, 0x02, 0x6b, 0x4b, 0x02, 0x6e, 0x51, 0x02,
- 0x6f, 0xb1, 0x02, 0x73, 0xb8, 0x02, 0x74, 0xd1, 0x02, 0x75, 0xc4, 0x03,
- 0x7a, 0xca, 0x03, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x63, 0x13, 0x68, 0x22,
- 0x6c, 0x28, 0x6e, 0x2f, 0x73, 0x35, 0x74, 0x46, 0x78, 0x5f, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x65, 0x08, 0x40, 0x07, 0x70, 0x74, 0x69, 0x73, 0x74,
- 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x69,
- 0x6d, 0x00, 0x40, 0x07, 0x65, 0x63, 0x74, 0x73, 0x00, 0x40, 0x07, 0x69,
- 0x61, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x05, 0x40, 0x07, 0x7a, 0x69,
- 0x00, 0x40, 0x07, 0x61, 0x73, 0x69, 0x61, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x67, 0x6f, 0x72, 0x61, 0x73, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x72, 0x61,
- 0x67, 0x65, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x1f, 0x68, 0x3c, 0x6f, 0x41,
- 0x72, 0x53, 0x79, 0xaf, 0xe2, 0x6c, 0x00, 0x6d, 0x15, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe3,
- 0x61, 0x00, 0x72, 0x04, 0x73, 0x14, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x00, 0x07, 0x40, 0x00, 0x72, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x23, 0x6f, 0x35, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x04, 0x73, 0x06, 0x74, 0x08, 0x77, 0x0d, 0x00,
- 0x09, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x74, 0x69, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x61, 0x6d, 0x70, 0x6f, 0x69, 0x6e, 0x69, 0x6d, 0x65, 0x72, 0x69,
- 0x6e, 0x61, 0x00, 0xe3, 0x69, 0x00, 0x6d, 0x04, 0x70, 0x14, 0x40, 0x07,
- 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x07, 0x63, 0x68, 0x65,
- 0x00, 0x40, 0x07, 0x64, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x76, 0x00, 0x00,
- 0x07, 0xe8, 0x61, 0x00, 0x65, 0x05, 0x69, 0x53, 0x6b, 0x57, 0x6c, 0x5c,
- 0x6f, 0xb7, 0x73, 0xcc, 0x75, 0xd3, 0x40, 0x07, 0x72, 0x61, 0x00, 0xe2,
- 0x6c, 0x00, 0x76, 0x44, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x69,
- 0x08, 0x6f, 0x30, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe5,
- 0x61, 0x00, 0x63, 0x02, 0x6e, 0x0b, 0x71, 0x14, 0x74, 0x19, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x65, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x07, 0x6f, 0x39, 0x40,
- 0x00, 0x69, 0x73, 0x00, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00,
- 0x07, 0xe2, 0x61, 0x00, 0x69, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x73, 0x6d, 0x00, 0xe2, 0x73, 0x00,
- 0x7a, 0x04, 0x40, 0x09, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x07, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x62, 0x65, 0x00, 0xe2, 0x6c, 0x00,
- 0x72, 0x0c, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x09, 0x40, 0x06, 0x61, 0x00, 0x40, 0x07, 0x74, 0x72, 0x6f, 0x6d,
- 0x00, 0xe2, 0x69, 0x00, 0x73, 0x06, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x00,
- 0x00, 0x07, 0xe3, 0x61, 0x00, 0x62, 0x08, 0x74, 0x0d, 0x40, 0x07, 0x6b,
- 0x63, 0x68, 0x61, 0x6b, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x61, 0x72, 0x61, 0x00, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x31, 0x69, 0x3d, 0x6d, 0x41, 0x75, 0x48, 0x00, 0x07, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x6d, 0x13, 0x70, 0x15, 0x00, 0x07, 0xe1, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x6f, 0x00, 0x75, 0x06, 0x40, 0x07,
- 0x6c, 0x69, 0x73, 0x00, 0x40, 0x07, 0x72, 0x6e, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x72, 0x69, 0x65, 0x00, 0x40, 0x06, 0x6e,
- 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x69,
- 0x6c, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x0f, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x31, 0x69, 0x45, 0x6f,
- 0x93, 0x77, 0xda, 0xe3, 0x65, 0x00, 0x6e, 0x05, 0x72, 0x0f, 0x40, 0x07,
- 0x75, 0x73, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f,
- 0x00, 0xe2, 0x63, 0x00, 0x65, 0x12, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x05, 0x40, 0x07, 0x6e,
- 0x79, 0x00, 0x40, 0x00, 0x6f, 0x70, 0x6f, 0x63, 0x65, 0x6e, 0x65, 0x00,
- 0xe6, 0x63, 0x00, 0x65, 0x08, 0x67, 0x0e, 0x6c, 0x1c, 0x6f, 0x2d, 0x70,
- 0x32, 0x40, 0x06, 0x68, 0x72, 0x69, 0x73, 0x74, 0x00, 0x40, 0x07, 0x74,
- 0x61, 0x6d, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40, 0x07, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x73, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x63, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x00, 0x64, 0x65, 0x73, 0x00, 0xe3, 0x66, 0x00, 0x69, 0x09, 0x6e,
- 0x1b, 0x40, 0x07, 0x61, 0x67, 0x61, 0x73, 0x74, 0x61, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x74, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x79,
- 0x1a, 0x00, 0x07, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x6e, 0x02, 0x6f, 0x07,
- 0x75, 0x09, 0x00, 0x07, 0x40, 0x07, 0x75, 0x73, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x72, 0x70, 0x00, 0x40, 0x07, 0x62, 0x69, 0x73,
- 0x00, 0x40, 0x07, 0x61, 0x63, 0x00, 0xe8, 0x61, 0x00, 0x65, 0x21, 0x68,
- 0x2a, 0x69, 0x33, 0x6f, 0x37, 0x70, 0x6d, 0x72, 0xbe, 0x75, 0xc9, 0xe3,
- 0x63, 0x00, 0x6c, 0x05, 0x74, 0x10, 0x40, 0x06, 0x68, 0x65, 0x00, 0x40,
- 0x07, 0x61, 0x63, 0x68, 0x69, 0x63, 0x6f, 0x6c, 0x61, 0x00, 0x40, 0x00,
- 0x6f, 0x73, 0x61, 0x75, 0x72, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x6e,
- 0x69, 0x6e, 0x65, 0x73, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x64, 0x69, 0x74,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x14, 0xe2,
- 0x61, 0x00, 0x72, 0x08, 0x40, 0x07, 0x6c, 0x79, 0x70, 0x73, 0x65, 0x00,
- 0x40, 0x07, 0x79, 0x70, 0x68, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x08, 0x40, 0x07, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00,
- 0xe3, 0x61, 0x00, 0x6c, 0x2a, 0x6f, 0x41, 0xe1, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x1c, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x06, 0x6f, 0x73, 0x61,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x74, 0x08, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x65, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x6d, 0x61, 0x74, 0x74, 0x6f, 0x78, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x07, 0x6c, 0x65,
- 0x69, 0x75, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x1c,
- 0xe2, 0x66, 0x00, 0x72, 0x07, 0x40, 0x07, 0x72, 0x65, 0x73, 0x68, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x09, 0x73, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x04, 0x74, 0x0f, 0x40,
- 0x07, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x73, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x69, 0x6e, 0x65, 0x00, 0xc1, 0x61, 0x19,
- 0x37, 0x00, 0x39, 0x00, 0xda, 0x00, 0xea, 0x00, 0x32, 0x01, 0x41, 0x01,
- 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00, 0x98, 0x01, 0x1e, 0x02, 0x24, 0x02,
- 0x53, 0x02, 0x6d, 0x02, 0xcc, 0x02, 0xef, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xf3, 0x02, 0x00, 0x00, 0x04, 0x03, 0x3d, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x42, 0x03, 0x00, 0x07, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x63,
- 0x2d, 0x66, 0x33, 0x67, 0x38, 0x6c, 0x47, 0x6d, 0x49, 0x70, 0x57, 0x72,
- 0x6b, 0x75, 0x70, 0x77, 0x79, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x79, 0x22, 0x00, 0x06, 0xe4, 0x61, 0x00, 0x63, 0x09, 0x64, 0x0b, 0x73,
- 0x13, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07,
- 0x40, 0x00, 0x6f, 0x70, 0x73, 0x69, 0x73, 0x00, 0x40, 0x09, 0x74, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x61, 0x74,
- 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07,
- 0x61, 0x79, 0x61, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x63, 0x05, 0x40,
- 0x07, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x61, 0x74, 0x00, 0x40, 0x07, 0x63,
- 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe2,
- 0x69, 0x00, 0x72, 0x07, 0x40, 0x07, 0x74, 0x72, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x12, 0x74, 0x32, 0xe1, 0x64,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0xe3, 0x62, 0x00, 0x65, 0x06, 0x6d, 0x08, 0x40, 0x07, 0x61,
- 0x6c, 0x64, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x64, 0x65, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x75, 0x04, 0x40, 0x07, 0x63, 0x00, 0x40, 0x07, 0x72,
- 0x75, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x00, 0x62, 0x69,
- 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x71, 0x00, 0x73, 0x07, 0x40,
- 0x07, 0x75, 0x69, 0x70, 0x61, 0x00, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x6f,
- 0x25, 0x75, 0x3e, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x69, 0x0d, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x09, 0x61, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x73, 0x10, 0x00,
- 0x06, 0xe2, 0x61, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x75, 0x74, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe6, 0x61, 0x00,
- 0x65, 0x14, 0x6f, 0x1d, 0x73, 0x23, 0x75, 0x58, 0x7a, 0x5c, 0xe3, 0x64,
- 0x00, 0x6c, 0x05, 0x6e, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x73, 0x6d, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x09, 0x40, 0x07, 0x73, 0x74, 0x6f, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x61, 0x00, 0x69, 0x08, 0x6f, 0x0e, 0x40, 0x07, 0x72, 0x63, 0x68,
- 0x75, 0x73, 0x00, 0x40, 0x07, 0x64, 0x65, 0x73, 0x00, 0xe2, 0x70, 0x00,
- 0x74, 0x08, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x65, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x75, 0x6e, 0x61, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x68, 0x14,
- 0x77, 0x1e, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x73, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x69,
- 0x67, 0x68, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x07, 0x6e,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x26, 0x69,
- 0x38, 0x6f, 0x3f, 0x73, 0x4c, 0xe2, 0x67, 0x00, 0x6e, 0x11, 0xe2, 0x65,
- 0x00, 0x6e, 0x07, 0x40, 0x06, 0x64, 0x64, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x61, 0x63, 0x00, 0xe2, 0x64, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x07, 0x6e, 0x69, 0x75, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x75,
- 0x04, 0x40, 0x07, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x74,
- 0x72, 0x6f, 0x6e, 0x67, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x04, 0x6f, 0x09,
- 0x75, 0x14, 0x40, 0x07, 0x62, 0x00, 0x40, 0x07, 0x65, 0x6d, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07,
- 0x6c, 0x66, 0x6f, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x68, 0x00, 0x6f,
- 0x08, 0x40, 0x07, 0x65, 0x6e, 0x69, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0b, 0x68, 0x11, 0x69, 0x23,
- 0x75, 0x27, 0x00, 0x07, 0x40, 0x07, 0x78, 0x65, 0x72, 0x78, 0x65, 0x73,
- 0x00, 0x40, 0x07, 0x6d, 0x69, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x00, 0x40, 0x07,
- 0x62, 0x61, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0xfe, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x63, 0x07, 0x00, 0x67, 0x1b, 0x00, 0x68, 0x21, 0x00,
- 0x69, 0x84, 0x00, 0x6d, 0xa4, 0x00, 0x6f, 0xaa, 0x00, 0x70, 0xaf, 0x00,
- 0x71, 0xcf, 0x00, 0x73, 0xd6, 0x00, 0x74, 0x10, 0x01, 0x75, 0x5a, 0x01,
- 0x77, 0x62, 0x01, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x61, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x6c, 0x61, 0x00, 0x40,
- 0x07, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00,
- 0xe9, 0x61, 0x00, 0x63, 0x06, 0x65, 0x0d, 0x67, 0x0f, 0x69, 0x16, 0x6b,
- 0x1d, 0x6c, 0x31, 0x6d, 0x3d, 0x75, 0x45, 0x40, 0x07, 0x6e, 0x74, 0x69,
- 0x00, 0x40, 0x07, 0x72, 0x6f, 0x66, 0x74, 0x00, 0x00, 0x07, 0x40, 0x00,
- 0x61, 0x62, 0x61, 0x74, 0x00, 0x40, 0x07, 0x6b, 0x61, 0x67, 0x61, 0x00,
- 0xe2, 0x65, 0x00, 0x68, 0x08, 0x40, 0x07, 0x6e, 0x61, 0x7a, 0x69, 0x6d,
- 0x00, 0x40, 0x07, 0x61, 0x62, 0x61, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6c,
- 0x65, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x62, 0x61, 0x6e, 0x69, 0x70,
- 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6d, 0x16, 0xe4, 0x00, 0x00, 0x67,
- 0x02, 0x6e, 0x06, 0x74, 0x08, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x00, 0x00,
- 0x09, 0x40, 0x06, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6f, 0x76, 0x00, 0x40,
- 0x07, 0x61, 0x72, 0x61, 0x00, 0x40, 0x07, 0x6b, 0x61, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x13, 0xe3, 0x6c, 0x00, 0x6e, 0x04, 0x72, 0x06, 0x40, 0x07,
- 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x67, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x64, 0x69, 0x73, 0x6b, 0x65, 0x00, 0x40, 0x07, 0x75, 0x69, 0x74, 0x68,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x13, 0x69, 0x1a, 0x79, 0x1f, 0xe2, 0x64,
- 0x00, 0x6d, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x65, 0x00, 0x40, 0x00, 0x6d, 0x62, 0x6c, 0x79, 0x00,
- 0x40, 0x07, 0x73, 0x69, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe4,
- 0x61, 0x00, 0x6f, 0x15, 0x72, 0x27, 0x75, 0x3a, 0xe3, 0x69, 0x00, 0x6e,
- 0x05, 0x72, 0x09, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x74, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6b, 0x68, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x54, 0x75, 0x72, 0x66, 0x00, 0x40, 0x07, 0x72, 0x69, 0x61, 0x73,
- 0x00, 0x40, 0x07, 0x6e, 0x63, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x68, 0x2c, 0x6b, 0x70, 0x6c,
- 0x84, 0x6d, 0xa7, 0x72, 0xac, 0x74, 0xc2, 0x77, 0xea, 0x00, 0x06, 0xe5,
- 0x63, 0x00, 0x68, 0x06, 0x6c, 0x0e, 0x72, 0x15, 0x74, 0x19, 0x40, 0x07,
- 0x61, 0x6d, 0x61, 0x00, 0x40, 0x07, 0x75, 0x61, 0x6c, 0x70, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x6e, 0x74, 0x61, 0x00, 0x40, 0x07, 0x69, 0x00, 0x40,
- 0x07, 0x75, 0x72, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x21, 0x6c, 0x38,
- 0xe2, 0x62, 0x00, 0x6e, 0x14, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x63, 0x00, 0x6b, 0x04, 0x40, 0x07, 0x61, 0x00, 0x40, 0x06, 0x61, 0x6e,
- 0x00, 0x40, 0x00, 0x61, 0x73, 0x69, 0x75, 0x73, 0x00, 0xe1, 0x6e, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x02, 0x69, 0x04, 0x73, 0x09, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x09, 0x6f, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x6e, 0x00, 0x73, 0x19, 0xe1, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x63, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x6f, 0x09, 0x40, 0x07, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x70, 0x6f, 0x73, 0x00, 0xe4,
- 0x69, 0x00, 0x6c, 0x12, 0x6e, 0x17, 0x75, 0x19, 0xe2, 0x63, 0x00, 0x6c,
- 0x09, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x65, 0x65, 0x00, 0x00, 0x00, 0x40, 0x07, 0x63,
- 0x6b, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xf8, 0x00, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x63, 0x08, 0x00, 0x64, 0x10, 0x00, 0x67, 0x39,
- 0x00, 0x72, 0x7d, 0x00, 0x73, 0xb7, 0x00, 0x74, 0x3b, 0x01, 0x00, 0x07,
- 0x40, 0x07, 0x72, 0x65, 0x79, 0x00, 0x40, 0x07, 0x6b, 0x6c, 0x61, 0x6e,
- 0x64, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04, 0x72, 0x0f, 0x75, 0x1a, 0x40,
- 0x07, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x07, 0x62, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x73, 0x07, 0x75, 0x0e, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x62, 0x75, 0x72, 0x67, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x0b, 0x75, 0x1a, 0x00, 0x09, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x08, 0x69, 0x27, 0x6f, 0x2c,
- 0x40, 0x07, 0x6e, 0x67, 0x7a, 0x65, 0x62, 0x00, 0xe2, 0x6c, 0x00, 0x6f,
- 0x12, 0xe1, 0x69, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x02, 0x75, 0x04, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x6d, 0x79, 0x63,
- 0x69, 0x6e, 0x00, 0x40, 0x07, 0x67, 0x61, 0x00, 0x40, 0x07, 0x72, 0x61,
- 0x00, 0xe3, 0x63, 0x00, 0x73, 0x08, 0x74, 0x0d, 0x40, 0x07, 0x68, 0x77,
- 0x69, 0x74, 0x7a, 0x00, 0x40, 0x09, 0x69, 0x65, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x0e, 0x72, 0x12, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x69, 0x74, 0x7a, 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x3b, 0x6f, 0x47, 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x12, 0x6f, 0x1e, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x69, 0x00,
- 0x70, 0x04, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x69, 0x74, 0x68, 0x65,
- 0x63, 0x75, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x75, 0x6d, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x0e, 0x69, 0x39, 0x6f, 0x5b, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x6e,
- 0x02, 0x72, 0x09, 0x73, 0x1d, 0x00, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6e,
- 0x65, 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x05, 0x79, 0x0b, 0x40, 0x07, 0x75,
- 0x73, 0x00, 0x40, 0x07, 0x6f, 0x65, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x74, 0x61, 0x00, 0xe5, 0x63, 0x00, 0x67, 0x07, 0x6c, 0x0d, 0x6f, 0x11,
- 0x73, 0x15, 0x40, 0x07, 0x65, 0x6e, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x6e,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x72, 0x00, 0x00,
- 0x07, 0xe2, 0x67, 0x00, 0x6e, 0x07, 0x40, 0x07, 0x61, 0x64, 0x72, 0x6f,
- 0x00, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x75, 0x04, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x05, 0x6d, 0x0a, 0x72,
- 0x10, 0x75, 0x18, 0x79, 0x20, 0x40, 0x07, 0x6c, 0x61, 0x00, 0x40, 0x07,
- 0x72, 0x73, 0x00, 0x40, 0x07, 0x61, 0x72, 0x61, 0x00, 0x40, 0x07, 0x73,
- 0x68, 0x69, 0x72, 0x65, 0x00, 0x40, 0x07, 0x72, 0x76, 0x65, 0x64, 0x61,
- 0x00, 0x40, 0x07, 0x75, 0x62, 0x69, 0x64, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x15, 0x6f, 0x33, 0x74, 0x3f, 0xe2, 0x6e, 0x00, 0x7a, 0x0b, 0xe2, 0x61,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x65,
- 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6a, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x72, 0x00, 0x76,
- 0x05, 0x40, 0x07, 0x65, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6c,
- 0x0e, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xc1, 0x41, 0x39, 0x77,
- 0x00, 0x79, 0x00, 0x85, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc,
- 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc9, 0x00, 0xcb, 0x00, 0x00, 0x00, 0xd6,
- 0x00, 0xd8, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x0b, 0x15, 0x0c, 0x5b,
- 0x0d, 0x6d, 0x0d, 0x6f, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x0e, 0x00,
- 0x00, 0x00, 0x00, 0x09, 0x12, 0x00, 0x00, 0x91, 0x16, 0x95, 0x16, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x19, 0x00, 0x0c, 0xe2, 0x00, 0x00,
- 0x53, 0x02, 0x00, 0x07, 0x40, 0x06, 0x49, 0x43, 0x00, 0xe5, 0x00, 0x00,
- 0x42, 0x02, 0x43, 0x04, 0x51, 0x06, 0x53, 0x08, 0x00, 0x07, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x73, 0x00, 0x00, 0x07, 0x40, 0x00, 0x46, 0x00, 0xe3, 0x41, 0x00,
- 0x4f, 0x02, 0x54, 0x06, 0x00, 0x00, 0x40, 0x00, 0x53, 0x00, 0x40, 0x00,
- 0x4e, 0x45, 0x54, 0x00, 0x40, 0x06, 0x54, 0x00, 0xe2, 0x00, 0x00, 0x57,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x4f, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x45, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x41,
- 0x02, 0x44, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0xe2, 0x55, 0x00,
- 0x57, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x4f, 0x42, 0x00, 0xc1,
- 0x61, 0x19, 0x37, 0x00, 0x39, 0x00, 0x4f, 0x00, 0x85, 0x00, 0xd6, 0x00,
- 0xe6, 0x00, 0xf4, 0x00, 0xfa, 0x00, 0x12, 0x01, 0x57, 0x01, 0x00, 0x00,
- 0x6c, 0x01, 0x97, 0x01, 0x38, 0x02, 0x46, 0x02, 0xdd, 0x02, 0xe3, 0x02,
- 0x00, 0x00, 0xf8, 0x02, 0x7c, 0x04, 0xc6, 0x04, 0xf8, 0x04, 0x2b, 0x05,
- 0x00, 0x00, 0x40, 0x05, 0x46, 0x05, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x73, 0x74, 0x00, 0xe3, 0x62, 0x00, 0x65, 0x0f, 0x79,
- 0x13, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40,
- 0x07, 0x74, 0x74, 0x00, 0x40, 0x09, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0xe6, 0x61, 0x00, 0x63, 0x0e, 0x68, 0x28, 0x6b, 0x2a, 0x6f, 0x2f, 0x74,
- 0x33, 0xe2, 0x6c, 0x00, 0x72, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07,
- 0x64, 0x69, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x08, 0x75,
- 0x0c, 0x40, 0x07, 0x6e, 0x61, 0x6c, 0x69, 0x61, 0x00, 0x40, 0x00, 0x63,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x75, 0x73, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x07, 0x40, 0x00, 0x72,
- 0x69, 0x6f, 0x6c, 0x00, 0x40, 0x07, 0x69, 0x61, 0x00, 0xe2, 0x65, 0x00,
- 0x6c, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x73,
- 0x00, 0xe2, 0x64, 0x00, 0x7a, 0x07, 0x40, 0x09, 0x65, 0x6b, 0x65, 0x72,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x66, 0x69, 0x6e, 0x00, 0xe3, 0x67, 0x00,
- 0x68, 0x06, 0x75, 0x0c, 0x40, 0x07, 0x69, 0x65, 0x73, 0x00, 0x40, 0x07,
- 0x64, 0x61, 0x64, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x34, 0x72, 0x38, 0xe3, 0x27, 0x00, 0x6d, 0x0e, 0x73, 0x29, 0xe2,
- 0x69, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x68,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x11, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x73,
- 0x08, 0x00, 0x06, 0x40, 0x00, 0x69, 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40,
- 0x09, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x69, 0x6e, 0x00, 0xe3, 0x6b, 0x00, 0x6c, 0x05, 0x72,
- 0x0a, 0x40, 0x07, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40,
- 0x07, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x1a, 0xe2, 0x6c, 0x00, 0x72,
- 0x06, 0x40, 0x07, 0x69, 0x74, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xeb, 0x61,
- 0x00, 0x62, 0x12, 0x64, 0x17, 0x65, 0x25, 0x66, 0x2c, 0x69, 0x32, 0x6b,
- 0x3f, 0x6c, 0x56, 0x74, 0x62, 0x75, 0x7b, 0x7a, 0x85, 0xe2, 0x6e, 0x00,
- 0x74, 0x08, 0x40, 0x07, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x77,
- 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x00, 0x40, 0x07,
- 0x61, 0x72, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6f, 0x75, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x68, 0x0c, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x61, 0x73, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x64, 0x00, 0xe2,
- 0x68, 0x00, 0x69, 0x07, 0x40, 0x07, 0x61, 0x7a, 0x61, 0x72, 0x00, 0xe2,
- 0x63, 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x65, 0x00,
- 0x40, 0x07, 0x63, 0x68, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x61, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x62, 0x05, 0x40, 0x07, 0x6b, 0x6f,
- 0x00, 0x40, 0x07, 0x69, 0x00, 0xe8, 0x61, 0x00, 0x63, 0x05, 0x64, 0x15,
- 0x67, 0x1b, 0x6a, 0x52, 0x6b, 0x64, 0x6e, 0x68, 0x74, 0x7a, 0x40, 0x07,
- 0x63, 0x68, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x05, 0x40, 0x00, 0x72, 0x70,
- 0x00, 0x40, 0x07, 0x6f, 0x66, 0x74, 0x00, 0x40, 0x07, 0x75, 0x6e, 0x67,
- 0x00, 0xe5, 0x61, 0x00, 0x6b, 0x07, 0x6c, 0x0c, 0x6f, 0x24, 0x75, 0x28,
- 0x40, 0x07, 0x6c, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6b, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x75,
- 0x09, 0x40, 0x07, 0x72, 0x6d, 0x61, 0x73, 0x69, 0x6e, 0x00, 0x40, 0x07,
- 0x6c, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40,
- 0x07, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x07, 0x73, 0x74, 0x65, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x09,
- 0x40, 0x07, 0x74, 0x6f, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0xfe, 0x61, 0x00, 0x00, 0x62, 0x0f, 0x00, 0x63, 0x5e,
- 0x00, 0x64, 0x79, 0x00, 0x65, 0x7f, 0x00, 0x6b, 0x85, 0x00, 0x6c, 0x93,
- 0x00, 0x6e, 0x98, 0x00, 0x6f, 0xcc, 0x00, 0x71, 0xd1, 0x00, 0x72, 0xdc,
- 0x00, 0x74, 0x17, 0x01, 0x75, 0x4a, 0x01, 0x79, 0x4f, 0x01, 0xe2, 0x62,
- 0x00, 0x63, 0x06, 0x40, 0x07, 0x62, 0x61, 0x73, 0x00, 0x40, 0x07, 0x6b,
- 0x00, 0xe6, 0x61, 0x00, 0x65, 0x2c, 0x69, 0x30, 0x6f, 0x34, 0x72, 0x39,
- 0x75, 0x3d, 0xe2, 0x64, 0x00, 0x72, 0x0e, 0xe2, 0x69, 0x00, 0x6f, 0x05,
- 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe4, 0x61, 0x00,
- 0x65, 0x02, 0x6f, 0x08, 0x79, 0x0e, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x6c,
- 0x61, 0x00, 0x40, 0x07, 0x73, 0x73, 0x61, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x75, 0x72, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0x40, 0x07, 0x64, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x6c,
- 0x07, 0x40, 0x07, 0x6c, 0x6f, 0x6e, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x79,
- 0x00, 0x40, 0x07, 0x6f, 0x77, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1a, 0x75,
- 0x29, 0xe3, 0x62, 0x00, 0x72, 0x0b, 0x75, 0x0f, 0xe2, 0x61, 0x00, 0x79,
- 0x04, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x64, 0x00, 0x40,
- 0x07, 0x6c, 0x00, 0xe3, 0x73, 0x00, 0x74, 0x02, 0x79, 0x06, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07,
- 0x64, 0x61, 0x00, 0x40, 0x07, 0x75, 0x69, 0x73, 0x69, 0x6d, 0x65, 0x74,
- 0x6f, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0c, 0x69, 0x19, 0x6f,
- 0x1d, 0x79, 0x21, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x71, 0x75, 0x69, 0x6c,
- 0x6c, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x6c, 0x1b, 0x6f, 0x21, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x64,
- 0x00, 0x6f, 0x04, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x6d, 0x65, 0x77,
- 0x00, 0x40, 0x07, 0x65, 0x74, 0x74, 0x00, 0xe2, 0x6b, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x63, 0x68, 0x00, 0x40, 0x07, 0x73,
- 0x68, 0x6e, 0x69, 0x6b, 0x6f, 0x76, 0x00, 0xe8, 0x65, 0x00, 0x68, 0x04,
- 0x69, 0x08, 0x71, 0x11, 0x72, 0x16, 0x73, 0x1a, 0x74, 0x29, 0x75, 0x30,
- 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x6c,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x09, 0x75, 0x65, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74,
- 0x65, 0x72, 0x72, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x74, 0x6f, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0xe7, 0x61, 0x00,
- 0x65, 0x05, 0x68, 0x09, 0x69, 0x11, 0x6d, 0x17, 0x74, 0x1c, 0x75, 0x21,
- 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x73,
- 0x68, 0x65, 0x62, 0x61, 0x00, 0x40, 0x07, 0x73, 0x74, 0x61, 0x00, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x00, 0x00, 0x07, 0xe4,
- 0x64, 0x00, 0x65, 0x1e, 0x68, 0x22, 0x6d, 0x28, 0xe3, 0x65, 0x00, 0x6f,
- 0x08, 0x72, 0x0e, 0x40, 0x07, 0x6c, 0x61, 0x69, 0x72, 0x65, 0x00, 0x40,
- 0x07, 0x75, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x61, 0x72,
- 0x64, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x75, 0x73, 0x00,
- 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x74, 0x65, 0x72, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x06, 0x6c, 0x1f,
- 0x6f, 0x24, 0x72, 0x2a, 0x77, 0x31, 0x40, 0x00, 0x6d, 0x6f, 0x6e, 0x00,
- 0xe3, 0x72, 0x00, 0x73, 0x02, 0x75, 0x0e, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x78,
- 0x00, 0x40, 0x07, 0x6f, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x6e, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x75, 0x74, 0x68, 0x00, 0x40, 0x07, 0x61, 0x74, 0x63,
- 0x68, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39, 0x00, 0x00, 0x00, 0xe6,
- 0x00, 0x1d, 0x01, 0x2a, 0x01, 0x00, 0x00, 0x68, 0x01, 0x6d, 0x01, 0x7c,
- 0x01, 0x00, 0x00, 0x98, 0x01, 0x9e, 0x01, 0x00, 0x00, 0x67, 0x02, 0x3f,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x46, 0x03, 0xcc, 0x04, 0xec, 0x04, 0x42,
- 0x05, 0x48, 0x05, 0x00, 0x00, 0x00, 0x00, 0x64, 0x05, 0x00, 0x0d, 0xe7,
- 0x63, 0x00, 0x64, 0x04, 0x6e, 0x09, 0x72, 0x0b, 0x73, 0x2c, 0x74, 0x32,
- 0x75, 0x60, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x00, 0x00,
- 0x07, 0xe2, 0x64, 0x00, 0x6e, 0x15, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x73,
- 0x08, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6c,
- 0x65, 0x79, 0x00, 0x40, 0x07, 0x61, 0x69, 0x73, 0x65, 0x00, 0x40, 0x07,
- 0x6c, 0x65, 0x79, 0x00, 0xe3, 0x6c, 0x00, 0x72, 0x11, 0x74, 0x23, 0xe1,
- 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x69,
- 0x61, 0x00, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe3, 0x63, 0x00, 0x78, 0x04,
- 0x7a, 0x06, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x79, 0x00, 0xe6, 0x00, 0x00, 0x66, 0x02, 0x6a, 0x08, 0x6d, 0x10, 0x72,
- 0x23, 0x76, 0x2b, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x74, 0x00, 0x40,
- 0x07, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x09,
- 0x40, 0x07, 0x72, 0x63, 0x68, 0x61, 0x69, 0x73, 0x00, 0x40, 0x07, 0x6e,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x67, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07,
- 0x6f, 0x69, 0x72, 0x00, 0xe3, 0x68, 0x00, 0x6b, 0x06, 0x71, 0x28, 0x40,
- 0x07, 0x74, 0x65, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x68, 0x12,
- 0x79, 0x17, 0x00, 0x0e, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x00, 0x61, 0x6d,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x75, 0x65, 0x72, 0x65, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x06, 0x75, 0x69, 0x6e, 0x00,
- 0xe6, 0x62, 0x00, 0x63, 0x04, 0x66, 0x0a, 0x6c, 0x12, 0x72, 0x1a, 0x74,
- 0x21, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x68, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x61, 0x72, 0x6f, 0x6e, 0x69, 0x00, 0x40, 0x07, 0x7a, 0x65, 0x62,
- 0x75, 0x62, 0x00, 0x40, 0x07, 0x62, 0x6f, 0x68, 0x6d, 0x00, 0xe2, 0x68,
- 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6f, 0x76, 0x65, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x64,
- 0x00, 0x6a, 0x0a, 0x72, 0x10, 0x40, 0x07, 0x65, 0x72, 0x62, 0x65, 0x63,
- 0x6b, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x75,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x79, 0x00, 0xec, 0x61, 0x00, 0x65,
- 0x10, 0x66, 0x14, 0x67, 0x1a, 0x69, 0x36, 0x6b, 0x44, 0x6c, 0x49, 0x6d,
- 0x80, 0x6f, 0x91, 0x73, 0x9b, 0x74, 0xa4, 0x75, 0xaa, 0xe3, 0x00, 0x00,
- 0x72, 0x02, 0x75, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x73, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x72, 0x0f, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x75,
- 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07, 0x61,
- 0x64, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x7a, 0x05, 0x40, 0x07, 0x64, 0x61,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x15, 0x69, 0x23, 0x6f, 0x28, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x6d, 0x02, 0x74, 0x06, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00,
- 0x40, 0x07, 0x72, 0x69, 0x78, 0x00, 0xe2, 0x65, 0x00, 0x76, 0x04, 0x40,
- 0x07, 0x6b, 0x00, 0x40, 0x07, 0x75, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x69,
- 0x00, 0x40, 0x07, 0x77, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x70,
- 0x04, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x09,
- 0x72, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x61,
- 0x7a, 0x7a, 0x61, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x65, 0x00, 0x40,
- 0x07, 0x73, 0x68, 0x69, 0x00, 0xec, 0x00, 0x00, 0x61, 0x02, 0x63, 0x0b,
- 0x64, 0x12, 0x65, 0x1f, 0x67, 0x4c, 0x69, 0x63, 0x6a, 0x7d, 0x6e, 0x84,
- 0x73, 0x96, 0x74, 0x9b, 0x7a, 0xb0, 0x00, 0x07, 0x40, 0x07, 0x63, 0x65,
- 0x72, 0x72, 0x61, 0x66, 0x00, 0x40, 0x07, 0x68, 0x6c, 0x65, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x78,
- 0x00, 0xe3, 0x64, 0x00, 0x6c, 0x15, 0x74, 0x1a, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x09, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x75, 0x78, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x68, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0x40, 0x07, 0x61, 0x7a, 0x69, 0x00, 0xe2, 0x6e, 0x00,
- 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x6d, 0x69, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x79,
- 0x09, 0x40, 0x07, 0x74, 0x74, 0x00, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x68, 0x00, 0x6c, 0x05, 0x6f, 0x0a,
- 0x40, 0x07, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64,
- 0x72, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x77, 0x75, 0x6c, 0x66, 0x00,
- 0xfc, 0x62, 0x00, 0x00, 0x65, 0x05, 0x00, 0x67, 0x15, 0x00, 0x69, 0x3c,
- 0x00, 0x6b, 0x47, 0x00, 0x6c, 0x67, 0x00, 0x6d, 0x88, 0x00, 0x6e, 0xa1,
- 0x00, 0x72, 0x13, 0x01, 0x74, 0x1c, 0x01, 0x79, 0x55, 0x01, 0x7a, 0x59,
- 0x01, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x06, 0x40,
- 0x07, 0x69, 0x63, 0x65, 0x00, 0x40, 0x07, 0x74, 0x61, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x6d, 0x14, 0x73, 0x19, 0x00, 0x0a, 0xe2, 0x6e, 0x00,
- 0x72, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x63, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x67, 0x00,
- 0xe2, 0x65, 0x00, 0x73, 0x06, 0x40, 0x07, 0x6c, 0x65, 0x79, 0x00, 0xe1,
- 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0xe3, 0x6e, 0x00, 0x6f, 0x0b, 0x74, 0x0f, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x0f, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x7a,
- 0x00, 0x40, 0x07, 0x7a, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x00,
- 0x06, 0x40, 0x06, 0x61, 0x6e, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x30, 0x65, 0x36, 0x68, 0x3b, 0x69, 0x42, 0x6f, 0x53, 0x73, 0x5a, 0x00,
- 0x07, 0xe4, 0x64, 0x00, 0x6e, 0x10, 0x72, 0x15, 0x79, 0x21, 0xe2, 0x65,
- 0x00, 0x69, 0x06, 0x40, 0x07, 0x74, 0x74, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x65, 0x00, 0x40, 0x07, 0x6b, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x07, 0x61, 0x63, 0x68, 0x00, 0x40, 0x00, 0x73, 0x65, 0x00, 0x40, 0x07,
- 0x61, 0x72, 0x64, 0x74, 0x00, 0xe3, 0x63, 0x00, 0x65, 0x04, 0x6e, 0x06,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07,
- 0x75, 0x6c, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x74, 0x65, 0x69, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x04, 0x68, 0x0d, 0x69, 0x11, 0x72, 0x1e, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x73, 0x6d, 0x61, 0x6e, 0x6e, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6c, 0x6f, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07,
- 0x65, 0x6c, 0x69, 0x75, 0x73, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x19, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x0e, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6d,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x07, 0xe4, 0x65, 0x00, 0x68, 0x09, 0x73, 0x33, 0x74, 0x37, 0x40,
- 0x07, 0x6c, 0x67, 0x65, 0x75, 0x73, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x07, 0x6c, 0x13, 0x75, 0x1a, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64,
- 0x61, 0x00, 0x40, 0x07, 0x65, 0x68, 0x65, 0x6d, 0x00, 0x40, 0x07, 0x6e,
- 0x65, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79,
- 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x61, 0x68, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x06, 0x40, 0x00, 0x64,
- 0x67, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x07, 0x79, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x06,
- 0x75, 0x0c, 0x40, 0x07, 0x72, 0x61, 0x74, 0x00, 0x40, 0x07, 0x70, 0x61,
- 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x0f, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65,
- 0x00, 0x40, 0x07, 0x6f, 0x00, 0xff, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x62, 0x14, 0x00, 0x63, 0x30, 0x00, 0x64, 0x32, 0x00, 0x65, 0x40, 0x00,
- 0x67, 0x46, 0x00, 0x6b, 0x57, 0x00, 0x6c, 0x5b, 0x00, 0x6d, 0x82, 0x00,
- 0x6f, 0x88, 0x00, 0x72, 0x8d, 0x00, 0x73, 0xb8, 0x00, 0x74, 0xff, 0x00,
- 0x7a, 0x09, 0x01, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x08, 0x40, 0x07,
- 0x79, 0x73, 0x74, 0x6f, 0x6b, 0x00, 0x40, 0x07, 0x63, 0x61, 0x00, 0xe4,
- 0x00, 0x00, 0x53, 0x02, 0x54, 0x0a, 0x6c, 0x0f, 0x00, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x6f, 0x6d, 0x79, 0x00, 0x40, 0x07, 0x65, 0x58, 0x00, 0x40,
- 0x09, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40, 0x07,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x63, 0x65,
- 0x00, 0xe2, 0x66, 0x00, 0x67, 0x06, 0x40, 0x07, 0x6f, 0x6f, 0x74, 0x00,
- 0x40, 0x07, 0x6c, 0x65, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe2, 0x62,
- 0x00, 0x6c, 0x0b, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6f, 0x00,
- 0x00, 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x0e, 0x00, 0x10, 0xe2,
- 0x65, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x67, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x69, 0x6e, 0x69, 0x00, 0x40, 0x07, 0x6b, 0x6f, 0x00,
- 0xe4, 0x64, 0x00, 0x6b, 0x0d, 0x6d, 0x17, 0x6f, 0x20, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x79, 0x65, 0x00, 0x40, 0x07,
- 0x65, 0x6e, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x69, 0x6e,
- 0x67, 0x68, 0x61, 0x6d, 0x00, 0x00, 0x07, 0xe5, 0x63, 0x00, 0x68, 0x11,
- 0x6d, 0x1f, 0x71, 0x30, 0x73, 0x37, 0xe1, 0x61, 0x00, 0xe1, 0x79, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2,
- 0x6b, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x65, 0x6b, 0x00, 0x40, 0x07, 0x70,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x6b, 0x04,
- 0x40, 0x07, 0x6b, 0x00, 0x00, 0x07, 0x40, 0x07, 0x75, 0x69, 0x63, 0x6b,
- 0x00, 0x40, 0x07, 0x61, 0x75, 0x00, 0x40, 0x07, 0x54, 0x6f, 0x72, 0x72,
- 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x52, 0x00, 0x65, 0x06, 0x40, 0x07, 0x61,
- 0x74, 0x65, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x08,
- 0x40, 0x07, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x00, 0x40, 0x07, 0x72, 0x6b,
- 0x00, 0x00, 0x07, 0xf7, 0x61, 0x00, 0x00, 0x65, 0xa4, 0x00, 0x69, 0xb6,
- 0x00, 0x6f, 0xc7, 0x00, 0x75, 0x38, 0x01, 0x76, 0x5a, 0x01, 0x79, 0x5e,
- 0x01, 0xe6, 0x63, 0x00, 0x69, 0x53, 0x6b, 0x5e, 0x6e, 0x62, 0x74, 0x8b,
- 0x76, 0x8f, 0xe1, 0x6b, 0x00, 0xe6, 0x42, 0x00, 0x62, 0x07, 0x66, 0x17,
- 0x70, 0x26, 0x73, 0x2c, 0x77, 0x3d, 0x40, 0x07, 0x65, 0x72, 0x72, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x75, 0x06, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00,
- 0x40, 0x07, 0x72, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07,
- 0x65, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x6f,
- 0x6c, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x06, 0x40, 0x07, 0x69, 0x72, 0x74,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c,
- 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x6b, 0x13, 0x74, 0x1c, 0xe2,
- 0x61, 0x00, 0x68, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40,
- 0x07, 0x72, 0x64, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x73, 0x68,
- 0x69, 0x70, 0x00, 0x40, 0x07, 0x79, 0x72, 0x65, 0x00, 0x40, 0x07, 0x7a,
- 0x00, 0x40, 0x07, 0x61, 0x74, 0x73, 0x6b, 0x79, 0x00, 0xe2, 0x6e, 0x00,
- 0x76, 0x07, 0x40, 0x07, 0x68, 0x65, 0x69, 0x6d, 0x00, 0x40, 0x07, 0x69,
- 0x6e, 0x73, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x68, 0x00,
- 0x40, 0x07, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x00, 0xe5, 0x63, 0x00, 0x65,
- 0x10, 0x67, 0x1b, 0x6e, 0x23, 0x6f, 0x33, 0xe2, 0x68, 0x00, 0x6b, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x62, 0x75, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x6d, 0x66, 0x6f, 0x6e, 0x74, 0x65, 0x69, 0x6e, 0x00, 0x40, 0x07,
- 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x6d,
- 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x66, 0x0c, 0x69, 0x13,
- 0x73, 0x1c, 0x00, 0x0e, 0x40, 0x07, 0x65, 0x72, 0x67, 0x00, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x64, 0x61, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x62, 0x75, 0x72, 0x79,
- 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x65, 0x08, 0x00, 0x00, 0x40, 0x07,
- 0x68, 0x65, 0x72, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x07, 0x40, 0x07, 0x65,
- 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x74, 0x68, 0x00, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x07, 0x74, 0x68, 0x65, 0x00, 0xc0, 0x61, 0x19,
- 0x35, 0x00, 0x43, 0x00, 0x60, 0x00, 0x69, 0x00, 0x8d, 0x00, 0x00, 0x00,
- 0xb6, 0x00, 0xc5, 0x00, 0xde, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xec, 0x00,
- 0x56, 0x01, 0x5c, 0x01, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01,
- 0x4f, 0x02, 0x90, 0x02, 0xab, 0x02, 0xda, 0x02, 0xe0, 0x02, 0x00, 0x00,
- 0x0f, 0x03, 0xe2, 0x64, 0x00, 0x73, 0x07, 0x40, 0x00, 0x69, 0x63, 0x65,
- 0x61, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0xe2,
- 0x69, 0x00, 0x79, 0x0f, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x74, 0x04, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x63,
- 0x61, 0x63, 0x63, 0x69, 0x6f, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x18, 0xe1,
- 0x69, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x08, 0x40, 0x07, 0x68, 0x61, 0x72,
- 0x6d, 0x61, 0x00, 0x40, 0x07, 0x61, 0x74, 0x74, 0x76, 0x61, 0x00, 0x40,
- 0x00, 0x65, 0x69, 0x61, 0x6e, 0x00, 0xe4, 0x69, 0x00, 0x6f, 0x05, 0x72,
- 0x17, 0x74, 0x19, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x68, 0x69, 0x75, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x72, 0x74, 0x00, 0x40, 0x07, 0x74,
- 0x61, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x12, 0xe1, 0x6d, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6e,
- 0x67, 0x6c, 0x65, 0x73, 0x00, 0xe6, 0x65, 0x00, 0x69, 0x05, 0x6c, 0x1d,
- 0x6f, 0x25, 0x73, 0x2b, 0x74, 0x4d, 0x40, 0x07, 0x79, 0x6e, 0x00, 0xe1,
- 0x76, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x07, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40,
- 0x07, 0x79, 0x77, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x67, 0x6e, 0x61,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x16, 0xe1, 0x76, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6b, 0x00, 0x73, 0x02, 0x00, 0x06, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6d, 0x61,
- 0x6e, 0x6e, 0x00, 0x40, 0x07, 0x62, 0x61, 0x79, 0x00, 0xe6, 0x61, 0x00,
- 0x64, 0x15, 0x68, 0x17, 0x69, 0x20, 0x6e, 0x2f, 0x6f, 0x4a, 0xe2, 0x70,
- 0x00, 0x76, 0x07, 0x40, 0x07, 0x61, 0x72, 0x74, 0x65, 0x00, 0x40, 0x07,
- 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6f,
- 0x65, 0x66, 0x66, 0x65, 0x72, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x06, 0x40,
- 0x07, 0x61, 0x63, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x10, 0x00, 0x0e, 0xe2, 0x72, 0x00, 0x76, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x07, 0xe4, 0x6b, 0x00, 0x6c, 0x05, 0x6e, 0x13, 0x74, 0x17, 0x40,
- 0x07, 0x65, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x68, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0xe9, 0x64, 0x00,
- 0x65, 0x15, 0x67, 0x1a, 0x69, 0x32, 0x6b, 0x36, 0x6c, 0x38, 0x6e, 0x3e,
- 0x6f, 0x49, 0x75, 0x5a, 0xe2, 0x65, 0x00, 0x6f, 0x0c, 0xe2, 0x61, 0x00,
- 0x6e, 0x05, 0x40, 0x07, 0x75, 0x78, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x61, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x6c, 0x0a, 0x00, 0x06, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x61,
- 0x00, 0x40, 0x07, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x75, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x00, 0xe2, 0x62, 0x00, 0x64, 0x07, 0x40, 0x07,
- 0x75, 0x64, 0x75, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x00, 0x07,
- 0xe6, 0x63, 0x00, 0x65, 0x04, 0x6e, 0x06, 0x70, 0x15, 0x74, 0x1c, 0x77,
- 0x2e, 0x40, 0x07, 0x68, 0x00, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07,
- 0x6f, 0x72, 0x75, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x65, 0x6c, 0x6c, 0x00, 0xe3, 0x6f, 0x00, 0x73, 0x04, 0x74, 0x0b,
- 0x40, 0x00, 0x78, 0x00, 0x40, 0x07, 0x77, 0x61, 0x6e, 0x61, 0x00, 0x40,
- 0x07, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x69, 0x00, 0xe2, 0x6c, 0x00, 0x72,
- 0x0e, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x7a, 0x00, 0xe2, 0x62, 0x00, 0x6e, 0x0e, 0xe2, 0x61, 0x00, 0x6f,
- 0x05, 0x40, 0x07, 0x6b, 0x69, 0x00, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07,
- 0x65, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x00, 0x40, 0x07, 0x61, 0x72, 0x79,
- 0x00, 0xe4, 0x64, 0x00, 0x65, 0x07, 0x69, 0x1d, 0x6d, 0x21, 0x40, 0x07,
- 0x69, 0x74, 0x63, 0x68, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x04, 0x72, 0x06,
- 0x40, 0x07, 0x6c, 0x00, 0x00, 0x07, 0xe2, 0x73, 0x00, 0x79, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0xe3, 0x64, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x00, 0x07, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x65, 0x5f, 0x01, 0x69, 0xf3, 0x01, 0x6e, 0x21, 0x03, 0x6f, 0x25, 0x03,
- 0x75, 0xcd, 0x03, 0x79, 0x3f, 0x04, 0x7a, 0x62, 0x04, 0x00, 0x11, 0xfd,
- 0x62, 0x00, 0x00, 0x63, 0x06, 0x00, 0x64, 0x0e, 0x00, 0x67, 0x4f, 0x00,
- 0x68, 0x53, 0x00, 0x69, 0x8c, 0x00, 0x6d, 0x98, 0x00, 0x6e, 0x9f, 0x00,
- 0x71, 0xe7, 0x00, 0x73, 0xec, 0x00, 0x74, 0xfd, 0x00, 0x79, 0x10, 0x01,
- 0x7a, 0x12, 0x01, 0x40, 0x07, 0x6f, 0x69, 0x73, 0x00, 0x40, 0x00, 0x6b,
- 0x6e, 0x65, 0x6c, 0x6c, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08,
- 0x66, 0x0e, 0x6c, 0x14, 0x73, 0x1f, 0x79, 0x30, 0x00, 0x12, 0x40, 0x07,
- 0x75, 0x72, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x07,
- 0x6f, 0x72, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0x00, 0x07, 0xe2, 0x68, 0x00, 0x74, 0x05, 0x40, 0x07, 0x61, 0x77,
- 0x00, 0x40, 0x07, 0x72, 0x65, 0x65, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x73, 0x2b, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6e, 0x09, 0x70, 0x1b, 0x00,
- 0x09, 0x40, 0x07, 0x75, 0x70, 0x74, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x06,
- 0x6d, 0x00, 0x40, 0x07, 0x75, 0x74, 0x72, 0x61, 0x00, 0x00, 0x07, 0xe2,
- 0x6c, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x6c, 0x65, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x70, 0x74, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x64,
- 0x06, 0x74, 0x3d, 0x00, 0x07, 0x40, 0x07, 0x68, 0x00, 0xe5, 0x65, 0x00,
- 0x69, 0x16, 0x6f, 0x1f, 0x74, 0x28, 0x79, 0x2a, 0xe2, 0x69, 0x00, 0x6e,
- 0x04, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x75, 0x72, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x08, 0x40, 0x07, 0x73,
- 0x6c, 0x61, 0x76, 0x61, 0x00, 0x40, 0x07, 0x61, 0x69, 0x6e, 0x00, 0x00,
- 0x07, 0xe3, 0x69, 0x00, 0x6f, 0x0f, 0x7a, 0x13, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x00,
- 0xe8, 0x61, 0x00, 0x63, 0x17, 0x6d, 0x2a, 0x6e, 0x2f, 0x73, 0x5a, 0x74,
- 0x5e, 0x77, 0x6d, 0x7a, 0x7c, 0xe2, 0x6b, 0x00, 0x74, 0x08, 0x40, 0x07,
- 0x73, 0x70, 0x65, 0x61, 0x72, 0x00, 0x40, 0x00, 0x68, 0x61, 0x6c, 0x79,
- 0x7a, 0x65, 0x72, 0x00, 0xe2, 0x68, 0x00, 0x6b, 0x04, 0x40, 0x07, 0x74,
- 0x00, 0x40, 0x07, 0x65, 0x6e, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x6e, 0x00, 0xe3, 0x64, 0x00, 0x6e, 0x0c, 0x74, 0x19, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x74, 0x06, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x68,
- 0x6e, 0x65, 0x76, 0x00, 0xf9, 0x61, 0x00, 0x00, 0x63, 0x12, 0x00, 0x64,
- 0x16, 0x00, 0x65, 0x57, 0x00, 0x67, 0x59, 0x00, 0x6c, 0x8d, 0x00, 0x6e,
- 0x92, 0x00, 0x73, 0x99, 0x00, 0x74, 0xa9, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x6e, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x67, 0x08, 0x40,
- 0x07, 0x6c, 0x76, 0x65, 0x69, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x2a,
- 0xe4, 0x70, 0x00, 0x72, 0x06, 0x73, 0x08, 0x74, 0x0a, 0x40, 0x07, 0x6f,
- 0x72, 0x74, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6f, 0x02,
- 0x74, 0x07, 0x00, 0x07, 0x40, 0x07, 0x77, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x00,
- 0x06, 0xe4, 0x61, 0x00, 0x67, 0x07, 0x68, 0x0b, 0x69, 0x1f, 0x40, 0x07,
- 0x64, 0x6f, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x6f, 0x00, 0x40, 0x07,
- 0x6b, 0x6c, 0x65, 0x79, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x06, 0x40, 0x07,
- 0x61, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x00, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x21, 0x6e, 0x3a, 0x6f, 0x3f, 0x74, 0x43, 0x00, 0x06,
- 0xe2, 0x69, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x73, 0x06,
- 0x40, 0x06, 0x69, 0x73, 0x6d, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x13, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x79,
- 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07,
- 0x6e, 0x0b, 0x00, 0x14, 0x40, 0x06, 0x6e, 0x79, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe8, 0x61,
- 0x00, 0x62, 0x07, 0x63, 0x28, 0x6b, 0x2c, 0x6e, 0x31, 0x6f, 0x4f, 0x73,
- 0x62, 0x77, 0x64, 0x40, 0x06, 0x64, 0x77, 0x61, 0x79, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6b, 0x00, 0x40,
- 0x07, 0x61, 0x77, 0x00, 0xe3, 0x73, 0x00, 0x74, 0x05, 0x78, 0x15, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x73, 0x61, 0x75, 0x72, 0x75, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x6b,
- 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x02, 0x73, 0x07, 0x00, 0x09, 0x40, 0x07,
- 0x79, 0x6e, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x04, 0x73, 0x15, 0x00, 0x15, 0x00, 0x07, 0xe3,
- 0x61, 0x00, 0x65, 0x04, 0x6e, 0x06, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x08,
- 0x40, 0x07, 0x67, 0x00, 0xe2, 0x68, 0x00, 0x76, 0x06, 0x40, 0x07, 0x69,
- 0x72, 0x74, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0xe7, 0x62,
- 0x00, 0x63, 0x06, 0x65, 0x13, 0x6d, 0x19, 0x6e, 0x1f, 0x73, 0x51, 0x74,
- 0x58, 0x40, 0x07, 0x65, 0x63, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x6b, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x00, 0x67, 0x65,
- 0x6c, 0x00, 0x40, 0x07, 0x6d, 0x65, 0x6c, 0x00, 0xe4, 0x65, 0x00, 0x68,
- 0x19, 0x6f, 0x20, 0x73, 0x22, 0xe2, 0x69, 0x00, 0x6c, 0x0b, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x07, 0x6c,
- 0x65, 0x73, 0x63, 0x68, 0x69, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x64, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x77, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x07,
- 0x73, 0x65, 0x6c, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x0c, 0x6e, 0x10, 0x6f,
- 0x16, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x7a, 0x69, 0x6e, 0x73, 0x6b, 0x69,
- 0x00, 0x40, 0x07, 0x75, 0x00, 0xc0, 0x62, 0x17, 0x31, 0x00, 0x36, 0x00,
- 0x7d, 0x00, 0xb1, 0x00, 0xb7, 0x00, 0xcd, 0x00, 0x00, 0x00, 0xdf, 0x00,
- 0xe4, 0x00, 0xed, 0x00, 0x01, 0x01, 0x57, 0x01, 0x5d, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x9f, 0x01, 0x6c, 0x02, 0x89, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x9f, 0x02, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2,
- 0x68, 0x00, 0x6b, 0x25, 0xe3, 0x61, 0x00, 0x65, 0x10, 0x77, 0x18, 0xe2,
- 0x6e, 0x00, 0x72, 0x05, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x74, 0x00, 0x40, 0x07, 0x6e, 0x77, 0x61, 0x6c, 0x64, 0x00, 0x40,
- 0x07, 0x61, 0x6c, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x0a,
- 0x6e, 0x0f, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x68, 0x61, 0x6d, 0x00,
- 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x64, 0x09, 0x77, 0x23, 0x00, 0x07, 0x40, 0x07, 0x70,
- 0x65, 0x73, 0x74, 0x00, 0xe2, 0x68, 0x00, 0x79, 0x13, 0xe2, 0x61, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x69, 0x73, 0x65,
- 0x72, 0x00, 0x40, 0x00, 0x6e, 0x6f, 0x73, 0x00, 0xe2, 0x66, 0x00, 0x6f,
- 0x0c, 0xe2, 0x61, 0x00, 0x79, 0x05, 0x40, 0x07, 0x6c, 0x6f, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x7a, 0x06, 0x40,
- 0x07, 0x74, 0x74, 0x69, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x61, 0x00,
- 0x40, 0x07, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x75, 0x6d, 0x62, 0x75, 0x72,
- 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe5, 0x61,
- 0x00, 0x66, 0x07, 0x67, 0x0e, 0x6c, 0x32, 0x74, 0x44, 0x40, 0x07, 0x77,
- 0x61, 0x79, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x63, 0x68, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x05, 0x40, 0x07, 0x69, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2,
- 0x6f, 0x00, 0x77, 0x05, 0x40, 0x07, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x69,
- 0x6e, 0x6b, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x6e, 0x00,
- 0x40, 0x07, 0x70, 0x70, 0x6f, 0x00, 0xe7, 0x63, 0x00, 0x64, 0x05, 0x69,
- 0x1b, 0x6b, 0x1f, 0x73, 0x24, 0x75, 0x29, 0x79, 0x2e, 0x40, 0x07, 0x68,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x74,
- 0x06, 0x40, 0x07, 0x61, 0x6e, 0x6b, 0x00, 0x40, 0x07, 0x61, 0x67, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0xeb, 0x62, 0x00, 0x63, 0x10, 0x67, 0x14, 0x6b, 0x3e, 0x6c, 0x4e, 0x6d,
- 0x5d, 0x6e, 0x69, 0x72, 0x7f, 0x73, 0x93, 0x74, 0x97, 0x75, 0xa2, 0xe2,
- 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x6e, 0x6b, 0x00, 0x40, 0x07, 0x72,
- 0x72, 0x79, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x0b,
- 0x75, 0x11, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x07, 0x79, 0x6e, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x00,
- 0x06, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x61, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x73,
- 0x05, 0x40, 0x07, 0x74, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x64, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x06, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x75, 0x67, 0x68,
- 0x73, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x68, 0x04, 0x40, 0x07, 0x68, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6e, 0x07, 0x00, 0x07, 0x40, 0x07, 0x64, 0x6f, 0x00,
- 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x05, 0x40,
- 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x66, 0x69, 0x6e, 0x67,
- 0x65, 0x72, 0x73, 0x00, 0x40, 0x07, 0x74, 0x65, 0x68, 0x75, 0x64, 0x65,
- 0x00, 0xe4, 0x62, 0x00, 0x65, 0x06, 0x72, 0x0b, 0x7a, 0x20, 0x40, 0x07,
- 0x6c, 0x6f, 0x73, 0x00, 0x40, 0x07, 0x72, 0x73, 0x00, 0xe2, 0x64, 0x00,
- 0x6f, 0x02, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x04, 0x40,
- 0x09, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xc1, 0x41, 0x3a, 0x79, 0x00,
- 0x7b, 0x00, 0x9c, 0x00, 0xa9, 0x00, 0xb4, 0x00, 0xc1, 0x00, 0xc5, 0x00,
- 0xd2, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xdf, 0x00, 0xe8, 0x00, 0x03, 0x01, 0x00, 0x00, 0x18, 0x01,
- 0x1c, 0x01, 0x20, 0x01, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x18, 0x09, 0x00, 0x00, 0x1a, 0x09,
- 0x1c, 0x09, 0x53, 0x0a, 0x00, 0x00, 0x55, 0x0a, 0x98, 0x10, 0x00, 0x00,
- 0x00, 0x00, 0x4b, 0x11, 0x16, 0x13, 0x00, 0x00, 0x21, 0x13, 0xea, 0x19,
- 0x00, 0x00, 0xee, 0x19, 0xc6, 0x1b, 0xcd, 0x1b, 0xec, 0x1b, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xb2, 0x1c, 0x31, 0x1d, 0x00, 0x06, 0xe7, 0x00,
- 0x00, 0x44, 0x02, 0x49, 0x04, 0x4d, 0x06, 0x50, 0x08, 0x52, 0x0a, 0x54,
- 0x0e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x45, 0x00, 0x40, 0x00, 0x56, 0x00, 0xe3, 0x00, 0x00, 0x43, 0x02,
- 0x53, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x54, 0x00, 0x55,
- 0x04, 0x40, 0x00, 0x56, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x43, 0x02,
- 0x54, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x4f, 0x00,
- 0xe3, 0x00, 0x00, 0x43, 0x02, 0x4f, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x00, 0x49, 0x00, 0xe2, 0x41, 0x00, 0x44, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe2, 0x4e, 0x00, 0x53, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe4,
- 0x00, 0x00, 0x42, 0x02, 0x44, 0x07, 0x4c, 0x09, 0x00, 0x07, 0x40, 0x06,
- 0x4f, 0x4c, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x41, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe5, 0x41, 0x00, 0x49, 0x02, 0x4f, 0x04, 0x52, 0x06, 0x55,
- 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x06, 0x54, 0x00, 0x40, 0x07, 0x54, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x53, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xc1, 0x62, 0x18, 0x35,
- 0x00, 0x37, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x76, 0x00, 0x00, 0x00, 0x91,
- 0x00, 0x9d, 0x00, 0xa4, 0x00, 0xc7, 0x00, 0x00, 0x00, 0xcc, 0x00, 0xbd,
- 0x01, 0x8f, 0x02, 0x00, 0x00, 0x74, 0x03, 0x00, 0x00, 0x03, 0x04, 0x25,
- 0x06, 0xec, 0x06, 0x90, 0x07, 0xb4, 0x07, 0x00, 0x00, 0xc6, 0x07, 0xcc,
- 0x07, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x6f, 0x07, 0x72, 0x0b, 0x40, 0x07,
- 0x72, 0x6e, 0x65, 0x74, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x04, 0x69, 0x09, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x72, 0x61,
- 0x00, 0x40, 0x07, 0x6e, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40,
- 0x00, 0x74, 0x74, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x7a, 0x06, 0x40, 0x07,
- 0x6c, 0x61, 0x63, 0x00, 0x00, 0x07, 0xe3, 0x64, 0x00, 0x72, 0x06, 0x73,
- 0x0f, 0x40, 0x07, 0x6d, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x70, 0x68, 0x69,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x61, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x6f,
- 0x6b, 0x69, 0x61, 0x00, 0xe5, 0x61, 0x00, 0x63, 0x07, 0x6e, 0x0c, 0x72,
- 0x0e, 0x74, 0x12, 0x40, 0x07, 0x70, 0x68, 0x61, 0x73, 0x00, 0x40, 0x07,
- 0x6f, 0x73, 0x00, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x6c,
- 0x69, 0x6e, 0x00, 0x40, 0x09, 0x75, 0x6e, 0x00, 0xeb, 0x00, 0x00, 0x61,
- 0x02, 0x63, 0x07, 0x64, 0x0e, 0x65, 0x27, 0x67, 0x35, 0x68, 0x3b, 0x69,
- 0x41, 0x6c, 0x73, 0x6f, 0xa3, 0x76, 0xaa, 0x00, 0x07, 0x40, 0x07, 0x69,
- 0x73, 0x00, 0x40, 0x07, 0x75, 0x74, 0x74, 0x61, 0x00, 0xe2, 0x65, 0x00,
- 0x77, 0x0e, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0xe2, 0x62,
- 0x00, 0x64, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x69, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x72, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x75, 0x6e, 0x00,
- 0xe4, 0x00, 0x00, 0x62, 0x02, 0x66, 0x07, 0x67, 0x23, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x75, 0x6c,
- 0x61, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x18, 0xe4, 0x67, 0x00, 0x68, 0x06,
- 0x6f, 0x0b, 0x73, 0x0d, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x6f, 0x02,
- 0x73, 0x07, 0x00, 0x07, 0x40, 0x07, 0x70, 0x65, 0x00, 0x40, 0x07, 0x74,
- 0x6f, 0x00, 0x40, 0x07, 0x6f, 0x63, 0x61, 0x6e, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x05, 0x69, 0x0a, 0x40, 0x07, 0x72, 0x79, 0x00, 0x40, 0x07, 0x72,
- 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xe9, 0x61, 0x00,
- 0x62, 0x06, 0x64, 0x3d, 0x65, 0x42, 0x69, 0x81, 0x6f, 0x90, 0x70, 0x96,
- 0x72, 0xb7, 0x75, 0xbb, 0x40, 0x07, 0x63, 0x68, 0x6f, 0x00, 0xe2, 0x6f,
- 0x00, 0x72, 0x12, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x69, 0x00,
- 0xe2, 0x61, 0x00, 0x64, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x68, 0x69, 0x72, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe3, 0x6c,
- 0x00, 0x6d, 0x18, 0x72, 0x1f, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07,
- 0xe2, 0x70, 0x00, 0x74, 0x0a, 0x40, 0x07, 0x61, 0x72, 0x64, 0x61, 0x6c,
- 0x69, 0x73, 0x00, 0x00, 0x09, 0x40, 0x09, 0x62, 0x65, 0x72, 0x74, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x02, 0x00, 0x07, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x61, 0x6e,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x73, 0x00, 0xe4, 0x61,
- 0x00, 0x62, 0x08, 0x69, 0x0e, 0x6f, 0x14, 0x40, 0x07, 0x6e, 0x65, 0x6c,
- 0x6c, 0x61, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6e,
- 0x61, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x62, 0x4d, 0x63, 0x54,
- 0x64, 0x61, 0x6e, 0x7c, 0x6f, 0x89, 0x74, 0x95, 0x75, 0xcd, 0x00, 0x07,
- 0xe5, 0x61, 0x00, 0x64, 0x0f, 0x6c, 0x2c, 0x72, 0x33, 0x76, 0x39, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x74,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x04, 0x00, 0x00, 0x00,
- 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x74, 0x74,
- 0x6f, 0x00, 0x40, 0x07, 0x69, 0x65, 0x73, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x61, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x72, 0x72, 0x61, 0x00, 0xe2, 0x65,
- 0x00, 0x75, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe3,
- 0x61, 0x00, 0x69, 0x05, 0x79, 0x12, 0x40, 0x07, 0x63, 0x65, 0x00, 0xe2,
- 0x63, 0x00, 0x64, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x70, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x75, 0x73, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x0a, 0x6f, 0x12, 0x72, 0x25,
- 0x75, 0x2b, 0x40, 0x07, 0x62, 0x72, 0x69, 0x67, 0x69, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x72, 0x62, 0x75, 0x72, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x72,
- 0x0c, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x74, 0x65, 0x00, 0xe8, 0x61, 0x00, 0x65, 0x09, 0x68, 0x2a, 0x69,
- 0x2c, 0x6f, 0x4b, 0x72, 0x58, 0x74, 0x6c, 0x75, 0x6e, 0x40, 0x07, 0x62,
- 0x6c, 0x61, 0x6e, 0x63, 0x61, 0x00, 0xe3, 0x6b, 0x00, 0x6c, 0x02, 0x74,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x77, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x73, 0x00, 0x74, 0x08, 0x40, 0x07,
- 0x74, 0x72, 0x61, 0x6e, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x65, 0x00,
- 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x6f, 0x72, 0x6e, 0x00, 0x00, 0x00, 0xe2,
- 0x63, 0x00, 0x6c, 0x06, 0x40, 0x07, 0x68, 0x69, 0x6e, 0x00, 0x40, 0x07,
- 0x65, 0x74, 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0x55, 0x00, 0x00, 0x00,
- 0x76, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x0f, 0x01, 0x3a, 0x01, 0x5e, 0x01,
- 0x8d, 0x01, 0x00, 0x00, 0xb1, 0x01, 0xda, 0x01, 0xdf, 0x01, 0x16, 0x02,
- 0x1b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0xe3, 0x00, 0x00, 0x63,
- 0x02, 0x76, 0x11, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x73,
- 0x05, 0x40, 0x07, 0x6c, 0x61, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x67,
- 0x67, 0x69, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x05,
- 0x72, 0x0f, 0x40, 0x07, 0x6f, 0x79, 0x00, 0x40, 0x07, 0x69, 0x66, 0x65,
- 0x72, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x07, 0x75, 0x6e, 0x64, 0x75, 0x6d,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x06, 0x6f, 0x11, 0x40, 0x07, 0x6e, 0x61,
- 0x73, 0x00, 0xe2, 0x66, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x66, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x7a, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0b, 0x40,
- 0x07, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x00, 0x07,
- 0xe3, 0x62, 0x00, 0x6e, 0x0d, 0x73, 0x11, 0xe2, 0x00, 0x00, 0x62, 0x02,
- 0x00, 0x09, 0x40, 0x09, 0x65, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x73, 0x61, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04,
- 0x69, 0x09, 0x6f, 0x15, 0x73, 0x1e, 0x74, 0x2c, 0x79, 0x31, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x00, 0x07, 0xe2, 0x62, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x61,
- 0x64, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x16, 0xe2, 0x6c, 0x00, 0x6e, 0x0f, 0xe3, 0x61, 0x00, 0x6c,
- 0x02, 0x6f, 0x06, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0x00,
- 0x07, 0xe2, 0x63, 0x00, 0x6e, 0x07, 0x40, 0x07, 0x68, 0x61, 0x65, 0x6c,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0d, 0x6f, 0x19,
- 0xe2, 0x70, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6f, 0x6e,
- 0x00, 0xe2, 0x67, 0x00, 0x79, 0x05, 0x40, 0x07, 0x69, 0x65, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x04, 0x79, 0x1f, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6e, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x02, 0x67, 0x04, 0x69, 0x0a, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x18, 0xe1, 0x74, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x74, 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x6f,
- 0x1b, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x7a, 0x61, 0x00, 0xe2, 0x65, 0x00,
- 0x6c, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x16, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x6f, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x0d, 0x69, 0x21, 0x77, 0x26, 0xe2,
- 0x72, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x09, 0x6e, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x72, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x07, 0x73,
- 0x6f, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x00, 0x07, 0xe8, 0x61, 0x00,
- 0x63, 0x22, 0x65, 0x29, 0x68, 0x32, 0x69, 0x34, 0x70, 0x38, 0x73, 0x46,
- 0x74, 0x7a, 0xe3, 0x62, 0x00, 0x6c, 0x08, 0x6e, 0x0c, 0x40, 0x07, 0x6c,
- 0x61, 0x6e, 0x63, 0x61, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x64, 0x00,
- 0x6f, 0x05, 0x40, 0x07, 0x72, 0x61, 0x00, 0x40, 0x06, 0x76, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x64, 0x65, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x0f, 0xe2, 0x6e, 0x00, 0x74, 0x06, 0x40, 0x06,
- 0x64, 0x72, 0x61, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe5, 0x64, 0x00, 0x65,
- 0x04, 0x6e, 0x06, 0x6f, 0x0a, 0x75, 0x11, 0x40, 0x07, 0x79, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x70, 0x65, 0x69, 0x61, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe5, 0x61, 0x00, 0x69, 0x07, 0x6c, 0x18, 0x6f,
- 0x21, 0x72, 0x25, 0x40, 0x07, 0x6e, 0x65, 0x64, 0x61, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x05, 0x40, 0x00, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x6f, 0x00, 0x40, 0x07, 0x65, 0x72, 0x65, 0x61, 0x67, 0x68, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x65,
- 0x73, 0x00, 0x00, 0x07, 0xe8, 0x61, 0x00, 0x65, 0x20, 0x68, 0x2a, 0x69,
- 0x6c, 0x6f, 0x73, 0x73, 0x75, 0x74, 0x8a, 0x75, 0x8c, 0xe2, 0x6c, 0x00,
- 0x77, 0x16, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x6f, 0x09, 0x40, 0x06, 0x6e,
- 0x00, 0x40, 0x07, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x61, 0x00,
- 0x40, 0x07, 0x62, 0x61, 0x00, 0x40, 0x07, 0x72, 0x70, 0x69, 0x6c, 0x6c,
- 0x61, 0x72, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x04, 0x6c, 0x13, 0x6f, 0x19,
- 0x72, 0x2e, 0x79, 0x33, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x65, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x09, 0x73,
- 0x6d, 0x00, 0x40, 0x07, 0x79, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6c,
- 0x69, 0x6e, 0x65, 0x00, 0x00, 0x07, 0xe1, 0x6b, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x6c, 0x75, 0x73, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x18, 0xe1, 0x73, 0x00, 0xe3,
- 0x69, 0x00, 0x6f, 0x05, 0x75, 0x0a, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40,
- 0x00, 0x69, 0x64, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x08, 0x40, 0x07, 0x6e, 0x64, 0x69, 0x73, 0x68,
- 0x00, 0x40, 0x07, 0x75, 0x72, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x00,
- 0xe3, 0x65, 0x00, 0x6d, 0x06, 0x75, 0x0b, 0x40, 0x07, 0x6e, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x73, 0x04, 0x40,
- 0x06, 0x61, 0x00, 0x40, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfd,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x0b, 0x00, 0x63, 0x1a, 0x00,
- 0x64, 0x3b, 0x00, 0x6c, 0x41, 0x00, 0x6e, 0x74, 0x00, 0x70, 0x9b, 0x00,
- 0x72, 0xae, 0x00, 0x73, 0xd5, 0x00, 0x74, 0xee, 0x00, 0x79, 0xf3, 0x00,
- 0x7a, 0x08, 0x01, 0x00, 0x07, 0x40, 0x07, 0x75, 0x73, 0x65, 0x73, 0x63,
- 0x75, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07,
- 0x6c, 0x69, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x04, 0x79, 0x08, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x72, 0x69, 0x63, 0x00, 0xe5, 0x65, 0x00, 0x69,
- 0x06, 0x6c, 0x11, 0x73, 0x17, 0x74, 0x1d, 0x40, 0x07, 0x73, 0x74, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x69, 0x6e, 0x69, 0x00, 0x40, 0x07, 0x69, 0x75, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06, 0x63, 0x00, 0xe2,
- 0x6f, 0x00, 0x74, 0x07, 0x40, 0x07, 0x7a, 0x6f, 0x69, 0x63, 0x00, 0xe3,
- 0x61, 0x00, 0x69, 0x07, 0x72, 0x0f, 0x40, 0x07, 0x75, 0x72, 0x75, 0x73,
- 0x00, 0x40, 0x00, 0x67, 0x72, 0x61, 0x64, 0x65, 0x00, 0x40, 0x00, 0x61,
- 0x6c, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x75,
- 0x04, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe4, 0x62, 0x00,
- 0x65, 0x07, 0x66, 0x14, 0x76, 0x16, 0x40, 0x07, 0x65, 0x72, 0x75, 0x73,
- 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x06, 0x40, 0x07, 0x6b, 0x6f, 0x76, 0x00,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x74, 0x65, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x73, 0x0f, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x61,
- 0x00, 0x40, 0x07, 0x75, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x73, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x6e, 0x65, 0x00, 0x00, 0x07,
- 0xf9, 0x00, 0x00, 0x00, 0x27, 0x02, 0x00, 0x61, 0x07, 0x00, 0x65, 0x76,
- 0x02, 0x69, 0xbd, 0x03, 0x6c, 0xb7, 0x04, 0x6f, 0xbc, 0x04, 0x72, 0xee,
- 0x04, 0x75, 0xe3, 0x05, 0x00, 0x17, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xfe,
- 0x62, 0x00, 0x00, 0x64, 0x06, 0x00, 0x67, 0x1a, 0x00, 0x69, 0x20, 0x00,
- 0x6c, 0x32, 0x00, 0x6d, 0x56, 0x00, 0x6e, 0x81, 0x00, 0x70, 0xfe, 0x00,
- 0x72, 0x35, 0x01, 0x73, 0xce, 0x01, 0x74, 0xda, 0x01, 0x75, 0x1d, 0x02,
- 0x76, 0x37, 0x02, 0x79, 0x3c, 0x02, 0x40, 0x07, 0x6c, 0x69, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x77, 0x07, 0x00, 0x07, 0x40, 0x09, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x61, 0x6c,
- 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x07,
- 0x6e, 0x79, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe3, 0x64, 0x00, 0x6c,
- 0x0f, 0x6d, 0x17, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x67, 0x65,
- 0x72, 0x00, 0x40, 0x00, 0x65, 0x72, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x70,
- 0x13, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x06,
- 0x40, 0x07, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6f,
- 0x06, 0x40, 0x07, 0x61, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x69,
- 0x6f, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x63, 0x02, 0x64, 0x18, 0x65, 0x4c,
- 0x67, 0x55, 0x74, 0x69, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x6f, 0x72, 0x73, 0x76, 0x69,
- 0x6c, 0x6c, 0x65, 0x00, 0xe4, 0x69, 0x00, 0x6c, 0x07, 0x6f, 0x0c, 0x72,
- 0x10, 0x40, 0x07, 0x67, 0x61, 0x72, 0x68, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x67,
- 0x02, 0x73, 0x09, 0x00, 0x07, 0x40, 0x07, 0x75, 0x70, 0x74, 0x61, 0x00,
- 0x40, 0x07, 0x65, 0x6b, 0x68, 0x61, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x73, 0x08,
- 0x00, 0x07, 0x40, 0x07, 0x68, 0x75, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x61,
- 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x79, 0x00, 0xe4, 0x6c, 0x00, 0x6d,
- 0x14, 0x70, 0x19, 0x75, 0x25, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x71, 0x75, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x71, 0x75, 0x69,
- 0x64, 0x64, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x6c, 0x74, 0x65, 0x70,
- 0x65, 0x63, 0x00, 0xe8, 0x62, 0x00, 0x64, 0x06, 0x69, 0x0e, 0x6c, 0x13,
- 0x6d, 0x56, 0x6f, 0x65, 0x74, 0x72, 0x79, 0x81, 0x40, 0x07, 0x72, 0x61,
- 0x79, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x6e, 0x61, 0x79, 0x00, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x22, 0x6f, 0x26, 0xe4, 0x6d,
- 0x00, 0x6e, 0x07, 0x73, 0x0b, 0x79, 0x17, 0x40, 0x07, 0x61, 0x67, 0x6e,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x77, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x06, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x61, 0x69, 0x73, 0x00,
- 0x00, 0x07, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x62, 0x64, 0x69, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0xe3, 0x65, 0x00, 0x68, 0x0b, 0x74, 0x10, 0x40, 0x07, 0x61, 0x75, 0x62,
- 0x72, 0x69, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x15, 0xe2, 0x68, 0x00, 0x6e, 0x09, 0x40, 0x07, 0x6f,
- 0x6f, 0x63, 0x68, 0x65, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x67, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x05, 0x40, 0x07, 0x65,
- 0x79, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x05,
- 0x74, 0x0b, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x63, 0x65, 0x79,
- 0x00, 0x40, 0x07, 0x61, 0x75, 0x71, 0x75, 0x61, 0x00, 0x40, 0x07, 0x65,
- 0x7a, 0x00, 0x40, 0x07, 0x65, 0x66, 0x73, 0x6b, 0x79, 0x00, 0xfd, 0x00,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x64, 0x13, 0x00, 0x65, 0x19, 0x00, 0x6b,
- 0x36, 0x00, 0x6c, 0x4b, 0x00, 0x6d, 0x5e, 0x00, 0x6e, 0x65, 0x00, 0x6f,
- 0x7e, 0x00, 0x72, 0x83, 0x00, 0x73, 0xc2, 0x00, 0x76, 0xf2, 0x00, 0x79,
- 0x18, 0x01, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x79, 0x61, 0x00, 0x40, 0x07, 0x64,
- 0x61, 0x72, 0x00, 0xe3, 0x72, 0x00, 0x74, 0x0c, 0x76, 0x11, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x73, 0x00, 0x40, 0x07,
- 0x6f, 0x73, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x61, 0x6e, 0x00, 0xe2, 0x73, 0x00, 0x79, 0x05, 0x40, 0x07,
- 0x65, 0x61, 0x00, 0x40, 0x07, 0x61, 0x62, 0x69, 0x6e, 0x73, 0x6b, 0x00,
- 0x40, 0x07, 0x50, 0x6f, 0x72, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x67, 0x06, 0x6e, 0x0b, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07,
- 0x64, 0x75, 0x00, 0x40, 0x07, 0x61, 0x69, 0x00, 0x40, 0x07, 0x70, 0x73,
- 0x00, 0xe5, 0x69, 0x00, 0x6e, 0x09, 0x6f, 0x26, 0x72, 0x2c, 0x79, 0x30,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x65, 0x00,
- 0x6f, 0x06, 0x40, 0x07, 0x6e, 0x6b, 0x6f, 0x00, 0xe2, 0x62, 0x00, 0x6d,
- 0x05, 0x40, 0x07, 0x79, 0x6c, 0x00, 0x40, 0x07, 0x79, 0x72, 0x64, 0x69,
- 0x6e, 0x00, 0x40, 0x09, 0x6b, 0x65, 0x65, 0x00, 0x40, 0x07, 0x79, 0x00,
- 0x40, 0x07, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x08, 0x74, 0x0e, 0x40,
- 0x07, 0x70, 0x65, 0x61, 0x6b, 0x65, 0x00, 0x40, 0x07, 0x69, 0x72, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02,
- 0x74, 0x09, 0x00, 0x07, 0x40, 0x07, 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x07, 0x72, 0x0c, 0x79,
- 0x1b, 0x40, 0x07, 0x6c, 0x69, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x74,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x65,
- 0x74, 0x00, 0x00, 0x07, 0x00, 0x07, 0x40, 0x06, 0x65, 0x6e, 0x6e, 0x65,
- 0x00, 0xee, 0x00, 0x00, 0x61, 0x02, 0x62, 0x08, 0x63, 0x14, 0x68, 0x44,
- 0x6c, 0x4c, 0x6d, 0x5a, 0x6e, 0x70, 0x70, 0x92, 0x71, 0xb1, 0x72, 0xb8,
- 0x73, 0xbe, 0x74, 0xcf, 0x76, 0xd8, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x74,
- 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68,
- 0x61, 0x00, 0xe3, 0x61, 0x00, 0x6b, 0x1c, 0x6c, 0x23, 0xe2, 0x67, 0x00,
- 0x6e, 0x0e, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x09, 0x61, 0x73, 0x61, 0x77, 0x00, 0x40, 0x07, 0x65, 0x74,
- 0x73, 0x00, 0x40, 0x09, 0x75, 0x61, 0x68, 0x75, 0x61, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00,
- 0xe3, 0x62, 0x00, 0x65, 0x08, 0x75, 0x0d, 0x40, 0x07, 0x6f, 0x72, 0x61,
- 0x7a, 0x6f, 0x00, 0x40, 0x09, 0x72, 0x61, 0x00, 0x00, 0x07, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x0f, 0x6f, 0x14, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x70,
- 0x07, 0x40, 0x07, 0x77, 0x79, 0x61, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x6e, 0x00, 0x77, 0x07, 0x40, 0x07, 0x64, 0x61, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x61, 0x00, 0x40, 0x07, 0x75, 0x69, 0x74, 0x61, 0x00, 0x40, 0x07,
- 0x69, 0x63, 0x6f, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6f,
- 0x6c, 0x6d, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x75, 0x00, 0x40, 0x07, 0x74,
- 0x61, 0x67, 0x6f, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x61, 0x73, 0x00, 0x40,
- 0x07, 0x6f, 0x65, 0x00, 0xe6, 0x63, 0x00, 0x69, 0x06, 0x6d, 0x08, 0x6e,
- 0x0e, 0x70, 0x16, 0x75, 0x23, 0x40, 0x06, 0x74, 0x61, 0x77, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x73, 0x6b, 0x79, 0x00, 0x40, 0x07, 0x67, 0x71, 0x69,
- 0x6e, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0xe4, 0x65, 0x00, 0x69, 0x07, 0x6f,
- 0xa1, 0x79, 0xd1, 0x40, 0x07, 0x74, 0x69, 0x65, 0x6e, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe8, 0x00, 0x00, 0x61,
- 0x02, 0x63, 0x04, 0x65, 0x0c, 0x69, 0x1e, 0x6c, 0x4b, 0x6d, 0x51, 0x6f,
- 0x6e, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x68, 0x75, 0x72, 0x63, 0x68,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x05, 0x40, 0x09, 0x6f,
- 0x6d, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x19, 0x6e, 0x1b, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe1,
- 0x69, 0x00, 0xe2, 0x64, 0x00, 0x6d, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40,
- 0x09, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x04, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2, 0x6d, 0x00, 0x6e,
- 0x23, 0xe1, 0x65, 0x00, 0xe1, 0x62, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x05,
- 0x6f, 0x0b, 0x40, 0x09, 0x73, 0x65, 0x00, 0x40, 0x09, 0x61, 0x64, 0x65,
- 0x00, 0xe2, 0x6f, 0x00, 0x78, 0x04, 0x40, 0x09, 0x6b, 0x00, 0x00, 0x09,
- 0x40, 0x00, 0x69, 0x63, 0x6c, 0x65, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe3,
- 0x6c, 0x00, 0x6f, 0x05, 0x74, 0x0c, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x73, 0x74, 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x00, 0xe6,
- 0x63, 0x00, 0x6b, 0x04, 0x6d, 0x0a, 0x6e, 0x10, 0x72, 0x14, 0x76, 0x31,
- 0x40, 0x07, 0x6b, 0x00, 0x40, 0x07, 0x63, 0x68, 0x69, 0x00, 0x40, 0x07,
- 0x61, 0x73, 0x68, 0x00, 0x40, 0x07, 0x67, 0x00, 0xe2, 0x63, 0x00, 0x72,
- 0x0f, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x69, 0x67, 0x75, 0x65, 0x72, 0x61,
- 0x00, 0x40, 0x07, 0x61, 0x73, 0x68, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02,
- 0x63, 0x08, 0x64, 0x0e, 0x6d, 0x10, 0x6e, 0x17, 0x70, 0x53, 0x72, 0x58,
- 0x73, 0x5d, 0x74, 0x62, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x73, 0x00,
- 0x40, 0x07, 0x65, 0x72, 0x6f, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x62,
- 0x75, 0x65, 0x00, 0xe4, 0x63, 0x00, 0x64, 0x09, 0x65, 0x18, 0x67, 0x2c,
- 0x40, 0x07, 0x69, 0x6e, 0x6e, 0x61, 0x74, 0x69, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x08, 0x40, 0x09, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x00, 0x00, 0x07,
- 0xe2, 0x6d, 0x00, 0x72, 0x09, 0x40, 0x07, 0x61, 0x53, 0x63, 0x6f, 0x70,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x61, 0x00, 0x40, 0x07, 0x75, 0x6c,
- 0x61, 0x72, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x00, 0x40, 0x07, 0x63, 0x65,
- 0x00, 0x40, 0x07, 0x63, 0x6f, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x12, 0x72,
- 0x24, 0x79, 0x2a, 0xe2, 0x55, 0x00, 0x62, 0x07, 0x40, 0x07, 0x4c, 0x69,
- 0x6b, 0x65, 0x00, 0x40, 0x07, 0x61, 0x73, 0x65, 0x00, 0xe2, 0x62, 0x00,
- 0x67, 0x06, 0x40, 0x07, 0x61, 0x6e, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x6f,
- 0x75, 0x70, 0x00, 0x40, 0x07, 0x6f, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x73,
- 0x65, 0x61, 0x72, 0x63, 0x68, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x65, 0xca, 0x00, 0x69, 0x28, 0x01, 0x6f, 0x67, 0x01, 0x79, 0x97,
- 0x01, 0x00, 0x18, 0xe6, 0x69, 0x00, 0x6e, 0x1b, 0x70, 0x20, 0x72, 0x31,
- 0x75, 0x6f, 0x79, 0xaf, 0xe2, 0x62, 0x00, 0x72, 0x07, 0x40, 0x07, 0x6f,
- 0x72, 0x6e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x04, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x63, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x74, 0x07, 0x40, 0x07, 0x79, 0x72, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x02, 0x69, 0x17,
- 0x6b, 0x25, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe2,
- 0x63, 0x00, 0x64, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07,
- 0x73, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x04, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x26,
- 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x6e, 0x02, 0x6f, 0x06,
- 0x75, 0x08, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x09, 0x00, 0x07, 0x40,
- 0x07, 0x77, 0x69, 0x74, 0x7a, 0x00, 0x40, 0x07, 0x75, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4,
- 0x61, 0x00, 0x6d, 0x08, 0x6f, 0x3f, 0x76, 0x4d, 0x40, 0x07, 0x72, 0x61,
- 0x73, 0x69, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x24, 0x73,
- 0x29, 0x00, 0x19, 0xe1, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x06, 0x74,
- 0x08, 0x40, 0x07, 0x65, 0x61, 0x75, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x73, 0x07, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x70, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x74, 0x72, 0x61,
- 0x00, 0x40, 0x07, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0xe5, 0x62, 0x00,
- 0x66, 0x06, 0x6e, 0x1c, 0x6f, 0x2e, 0x76, 0x30, 0x40, 0x07, 0x75, 0x72,
- 0x6e, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00,
- 0xe5, 0x72, 0x00, 0x73, 0x0e, 0x74, 0x14, 0x75, 0x19, 0x76, 0x20, 0xe2,
- 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x73, 0x00, 0x40, 0x07, 0x78,
- 0x00, 0x40, 0x07, 0x75, 0x72, 0x65, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x00,
- 0x40, 0x07, 0x73, 0x65, 0x61, 0x75, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00,
- 0xe2, 0x64, 0x00, 0x74, 0x11, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x61, 0x6c, 0x65, 0x00, 0x40, 0x07,
- 0x65, 0x6d, 0x6e, 0x65, 0x73, 0x74, 0x72, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x00, 0x07, 0x40, 0x00, 0x72, 0x00, 0xc1, 0x62, 0x19, 0x37,
- 0x00, 0x39, 0x00, 0x45, 0x00, 0x77, 0x00, 0x00, 0x00, 0x80, 0x00, 0x86,
- 0x00, 0x8c, 0x00, 0x99, 0x00, 0x00, 0x00, 0xaf, 0x00, 0xb3, 0x00, 0xa2,
- 0x01, 0x43, 0x02, 0x0e, 0x04, 0x47, 0x04, 0x00, 0x00, 0xb8, 0x04, 0x02,
- 0x06, 0x29, 0x06, 0x50, 0x06, 0x99, 0x06, 0xa1, 0x06, 0xbe, 0x06, 0xc0,
- 0x06, 0xc2, 0x06, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x62, 0x05, 0x40, 0x07,
- 0x69, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x68, 0x00, 0x6b, 0x1f, 0x74, 0x25,
- 0xe3, 0x61, 0x00, 0x69, 0x08, 0x72, 0x13, 0x40, 0x07, 0x62, 0x61, 0x6d,
- 0x62, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x61, 0x75, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x66, 0x65, 0x79, 0x00, 0x40, 0x07,
- 0x6e, 0x61, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x09, 0x40, 0x07,
- 0x62, 0x61, 0x74, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x07, 0x74, 0x72, 0x65,
- 0x61, 0x75, 0x00, 0x40, 0x06, 0x65, 0x00, 0xeb, 0x00, 0x00, 0x62, 0x02,
- 0x64, 0x0e, 0x65, 0x17, 0x66, 0x39, 0x67, 0x3e, 0x69, 0x44, 0x6c, 0x48,
- 0x6f, 0x64, 0x74, 0xb1, 0x75, 0xbe, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x79,
- 0x05, 0x40, 0x07, 0x72, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x46, 0x75,
- 0x73, 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06,
- 0x72, 0x0b, 0x74, 0x12, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x64, 0x67, 0x65, 0x00, 0x40, 0x07,
- 0x74, 0x65, 0x00, 0x40, 0x07, 0x61, 0x78, 0x00, 0x40, 0x07, 0x61, 0x74,
- 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40,
- 0x07, 0x65, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe6, 0x00,
- 0x00, 0x67, 0x02, 0x6d, 0x07, 0x6e, 0x1d, 0x72, 0x1f, 0x73, 0x39, 0x00,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x0c, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x09, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x65,
- 0x75, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x6e, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69,
- 0x00, 0x75, 0x0b, 0xe2, 0x61, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x09, 0x63, 0x0d, 0x64, 0x13, 0x69, 0x17, 0x6d, 0x1f, 0x6f, 0x4e, 0x70,
- 0x62, 0x74, 0x88, 0x00, 0x00, 0x40, 0x09, 0x6e, 0x63, 0x68, 0x65, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x73, 0x74, 0x00, 0x40, 0x00,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x00, 0xe2, 0x6f,
- 0x00, 0x75, 0x12, 0xe1, 0x6e, 0x00, 0xe2, 0x73, 0x00, 0x77, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x04, 0x40, 0x06, 0x6e, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6e,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x74, 0x04, 0x75, 0x09,
- 0x40, 0x07, 0x71, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x53, 0x00,
- 0x74, 0x07, 0x40, 0x07, 0x65, 0x72, 0x76, 0x65, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x65, 0x00, 0xfc,
- 0x61, 0x00, 0x00, 0x63, 0x0c, 0x00, 0x64, 0x31, 0x00, 0x65, 0x44, 0x00,
- 0x66, 0x4c, 0x00, 0x67, 0x88, 0x00, 0x6c, 0xde, 0x00, 0x6e, 0xe3, 0x00,
- 0x72, 0x25, 0x01, 0x73, 0x33, 0x01, 0x74, 0x7e, 0x01, 0x77, 0xa1, 0x01,
- 0xe2, 0x6b, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x72, 0x79, 0x00, 0x00, 0x07,
- 0xe2, 0x65, 0x00, 0x6f, 0x11, 0xe2, 0x70, 0x00, 0x74, 0x07, 0x40, 0x07,
- 0x63, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x61, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x00,
- 0x07, 0xe2, 0x69, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x63,
- 0x00, 0x40, 0x07, 0x72, 0x63, 0x65, 0x74, 0x00, 0x40, 0x07, 0x73, 0x74,
- 0x6f, 0x67, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x19, 0xe1, 0x64, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x0f, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x73, 0x6d, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x72, 0x0f, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x67, 0x00, 0x73, 0x21, 0x76, 0x32,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6f, 0x6e, 0x61,
- 0x6c, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x20, 0x6f, 0x24, 0x00, 0x0e, 0xe3, 0x63,
- 0x00, 0x6d, 0x08, 0x72, 0x0e, 0x40, 0x07, 0x74, 0x69, 0x63, 0x75, 0x74,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x6c, 0x00, 0x72,
- 0x05, 0x74, 0x09, 0x40, 0x07, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x65, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x74, 0x0a,
- 0x75, 0x3e, 0x40, 0x00, 0x72, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x26, 0xe2, 0x62, 0x00, 0x6e, 0x05, 0x40, 0x07,
- 0x6c, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x70, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x74, 0x75, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6f, 0x00, 0xe2, 0x69,
- 0x00, 0x72, 0x17, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6c, 0x00, 0x40, 0x07, 0x65, 0x72, 0x61, 0x73, 0x00, 0x40, 0x07, 0x61,
- 0x79, 0x00, 0xe4, 0x6b, 0x00, 0x6c, 0x09, 0x70, 0x18, 0x72, 0x2c, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x64, 0x67, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe5,
- 0x61, 0x00, 0x65, 0x09, 0x6c, 0x34, 0x70, 0x42, 0x74, 0x61, 0x40, 0x07,
- 0x63, 0x61, 0x62, 0x61, 0x6e, 0x61, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x06,
- 0x72, 0x0e, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x68, 0x61,
- 0x67, 0x65, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x6e, 0x64, 0x00,
- 0x40, 0x07, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x15, 0xe1, 0x72, 0x00,
- 0xe2, 0x66, 0x00, 0x74, 0x07, 0x40, 0x07, 0x69, 0x65, 0x6c, 0x64, 0x00,
- 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x00, 0x40,
- 0x07, 0x69, 0x63, 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x37, 0x00, 0x52, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a,
- 0x00, 0x00, 0x00, 0x9b, 0x00, 0x9d, 0x00, 0xa4, 0x00, 0xaa, 0x00, 0xef,
- 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0f, 0x01, 0x21, 0x01, 0x00,
- 0x00, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x07, 0xe3,
- 0x65, 0x00, 0x69, 0x06, 0x6f, 0x0f, 0x40, 0x07, 0x6c, 0x69, 0x61, 0x00,
- 0x40, 0x07, 0x6c, 0x6c, 0x65, 0x72, 0x61, 0x73, 0x00, 0x40, 0x07, 0x62,
- 0x61, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x75, 0x00, 0xe2, 0x6e,
- 0x00, 0x6f, 0x2a, 0xe4, 0x61, 0x00, 0x65, 0x02, 0x6e, 0x04, 0x74, 0x08,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe1, 0x6c, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6e, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x00, 0x00, 0x40, 0x07, 0x65, 0x6f, 0x6e, 0x65, 0x00,
- 0x40, 0x07, 0x61, 0x63, 0x6b, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x1d, 0x77,
- 0x2a, 0xe2, 0x69, 0x00, 0x6c, 0x06, 0x40, 0x07, 0x6c, 0x6c, 0x65, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x0b, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40,
- 0x07, 0x67, 0x00, 0x40, 0x09, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x06, 0x40, 0x07, 0x61, 0x64,
- 0x6f, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x07, 0x40,
- 0x07, 0x67, 0x67, 0x69, 0x6f, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6c, 0x04, 0x40, 0x09,
- 0x73, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x07, 0x75, 0x0d, 0x40, 0x07, 0x6c, 0x6c, 0x69, 0x73, 0x00, 0x40, 0x07,
- 0x74, 0x74, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0xe3, 0x62,
- 0x00, 0x73, 0x04, 0x74, 0x0a, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x61,
- 0x63, 0x6b, 0x00, 0xe3, 0x63, 0x00, 0x65, 0x04, 0x6e, 0x0a, 0x40, 0x07,
- 0x6f, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x6f, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0xe4, 0x65, 0x00, 0x6f, 0x02, 0x73, 0x12, 0x74, 0x19, 0x00, 0x07,
- 0xe2, 0x6e, 0x00, 0x70, 0x05, 0x40, 0x07, 0x6f, 0x75, 0x00, 0x40, 0x07,
- 0x61, 0x78, 0x69, 0x00, 0x40, 0x07, 0x77, 0x6f, 0x6c, 0x64, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe5, 0x6c, 0x00, 0x6e, 0x0f, 0x70, 0x18, 0x72,
- 0x1f, 0x73, 0x37, 0xe2, 0x6f, 0x00, 0x74, 0x05, 0x40, 0x07, 0x6d, 0x62,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x09, 0x63, 0x69, 0x6c, 0x6c,
- 0x6f, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x69, 0x6e, 0x00, 0xe3, 0x62,
- 0x00, 0x72, 0x05, 0x74, 0x0b, 0x40, 0x07, 0x65, 0x74, 0x00, 0x40, 0x07,
- 0x69, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x79, 0x00, 0x40, 0x07,
- 0x74, 0x65, 0x61, 0x75, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x72, 0x79,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x6c, 0x0a, 0x70, 0x0f, 0x40, 0x07,
- 0x72, 0x64, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x75, 0x6d, 0x65, 0x6c, 0x00, 0x40, 0x00, 0x6c, 0x00, 0xf7, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x65, 0x49, 0x00, 0x69, 0xab, 0x00, 0x6f, 0xe5,
- 0x00, 0x75, 0x73, 0x01, 0x79, 0xae, 0x01, 0x00, 0x11, 0xe7, 0x62, 0x00,
- 0x66, 0x05, 0x69, 0x09, 0x6e, 0x0d, 0x74, 0x20, 0x77, 0x25, 0x79, 0x2c,
- 0x40, 0x07, 0x62, 0x65, 0x00, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x67,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6d, 0x07, 0x40, 0x07, 0x63, 0x68,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x66, 0x6f, 0x72, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe7, 0x61, 0x00, 0x63,
- 0x11, 0x65, 0x15, 0x69, 0x1e, 0x6f, 0x26, 0x73, 0x31, 0x74, 0x3e, 0xe1,
- 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6b,
- 0x02, 0x00, 0x1a, 0x00, 0x06, 0x40, 0x07, 0x67, 0x68, 0x74, 0x6f, 0x6e,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x07,
- 0xe2, 0x73, 0x00, 0x74, 0x06, 0x40, 0x07, 0x69, 0x64, 0x61, 0x00, 0x00,
- 0x07, 0xe2, 0x61, 0x00, 0x65, 0x0e, 0xe2, 0x63, 0x00, 0x6e, 0x07, 0x40,
- 0x07, 0x65, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x06, 0x00, 0x07, 0xe4, 0x63,
- 0x00, 0x6d, 0x0d, 0x6f, 0x1c, 0x73, 0x22, 0xe2, 0x68, 0x00, 0x6b, 0x06,
- 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x6c, 0x6f, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x6f, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x61, 0x00, 0xe8, 0x61, 0x00, 0x63,
- 0x16, 0x65, 0x23, 0x6d, 0x29, 0x6e, 0x41, 0x6f, 0x56, 0x73, 0x5c, 0x77,
- 0x71, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2,
- 0x65, 0x00, 0x6b, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x74, 0x74, 0x00,
- 0x40, 0x07, 0x73, 0x75, 0x73, 0x00, 0xe1, 0x77, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe3, 0x69, 0x00, 0x6b, 0x04, 0x75,
- 0x0a, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x74, 0x65, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x6b, 0x65, 0x73, 0x00, 0xe2, 0x62, 0x00,
- 0x73, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x52, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x06, 0x40, 0x07, 0x65, 0x79, 0x00, 0xe5, 0x63, 0x00, 0x69, 0x0a, 0x73,
- 0x1b, 0x78, 0x2c, 0x7a, 0x2e, 0x40, 0x09, 0x69, 0x66, 0x69, 0x78, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x6b, 0x00, 0x73, 0x08, 0x40, 0x07, 0x73, 0x68,
- 0x61, 0x6e, 0x6b, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x08, 0x40, 0x00, 0x64, 0x65, 0x73, 0x27, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x70, 0x00, 0x73, 0x09, 0x40, 0x07,
- 0x74, 0x6f, 0x7a, 0x6f, 0x69, 0x63, 0x00, 0x40, 0x07, 0x74, 0x61, 0x6c,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x6b, 0x61, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x68, 0x0b, 0x72, 0x12, 0x00, 0x00, 0x40, 0x07, 0x73, 0x69, 0x70,
- 0x68, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x6c, 0x68, 0x75, 0x00, 0x40,
- 0x00, 0x6c, 0x00, 0xec, 0x00, 0x00, 0x62, 0x02, 0x63, 0x0e, 0x69, 0x17,
- 0x6c, 0x20, 0x6d, 0x33, 0x6e, 0x51, 0x70, 0x64, 0x72, 0x69, 0x73, 0x9c,
- 0x76, 0xa2, 0x7a, 0xa8, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x68, 0x75, 0x6c, 0x61,
- 0x69, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x69, 0x6e, 0x61, 0x72, 0x74, 0x00,
- 0xe2, 0x62, 0x00, 0x6c, 0x09, 0x40, 0x07, 0x65, 0x72, 0x74, 0x73, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe2, 0x62, 0x00, 0x6d, 0x12,
- 0xe2, 0x65, 0x00, 0x72, 0x08, 0x40, 0x07, 0x72, 0x6c, 0x61, 0x6e, 0x64,
- 0x00, 0x40, 0x07, 0x69, 0x61, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40,
- 0x07, 0x69, 0x6e, 0x67, 0x68, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x69, 0x64,
- 0x00, 0xe4, 0x61, 0x00, 0x69, 0x06, 0x72, 0x13, 0x74, 0x1f, 0x40, 0x07,
- 0x63, 0x61, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x69, 0x62, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0x00, 0x16, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x69, 0x65, 0x72, 0x00, 0x40, 0x07, 0x63, 0x6f, 0x00, 0xe7, 0x62, 0x00,
- 0x63, 0x06, 0x67, 0x22, 0x6d, 0x28, 0x6e, 0x31, 0x70, 0x38, 0x72, 0x51,
- 0x40, 0x07, 0x65, 0x6c, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x06, 0x40, 0x07, 0x64, 0x65, 0x73, 0x00, 0xe1, 0x70, 0x00, 0xe2,
- 0x65, 0x00, 0x73, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x75, 0x73, 0x00, 0x40, 0x07, 0x62, 0x65, 0x6c, 0x69, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x74, 0x68, 0x69, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x75, 0x0d, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x05, 0x75, 0x14, 0x40, 0x07, 0x6e, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x63, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x33,
- 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x73, 0x27, 0x00, 0x07,
- 0xe1, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x76, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x79, 0x00, 0xc1, 0x41, 0x3a, 0x79,
- 0x00, 0x7b, 0x00, 0x88, 0x00, 0x8d, 0x00, 0x8f, 0x00, 0x9c, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xa9, 0x00, 0xb2, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xb6, 0x00, 0xc5, 0x00, 0xc9, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xeb, 0x00, 0xf8, 0x00, 0xfc, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x0d, 0x08, 0x55,
- 0x0a, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x0a, 0x65, 0x0a, 0x80, 0x0a, 0x00,
- 0x00, 0x00, 0x00, 0xc2, 0x0c, 0x5a, 0x0d, 0x00, 0x00, 0x63, 0x0d, 0x21,
- 0x0f, 0x31, 0x0f, 0x00, 0x00, 0x42, 0x0f, 0x5b, 0x0f, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x52, 0x02, 0x54, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x4d, 0x53, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x53, 0x02,
- 0x54, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x08, 0xe3, 0x00, 0x00, 0x41,
- 0x02, 0x43, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe2, 0x00, 0x00,
- 0x53, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x43,
- 0x00, 0x44, 0x04, 0x5a, 0x06, 0x40, 0x00, 0x41, 0x00, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x07, 0x41, 0x00, 0xe6, 0x41, 0x00, 0x42, 0x02, 0x44, 0x04,
- 0x45, 0x06, 0x53, 0x08, 0x54, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x54, 0x02, 0x00,
- 0x06, 0x00, 0x00, 0xe2, 0x54, 0x00, 0x70, 0x02, 0x00, 0x00, 0x40, 0x07,
- 0x61, 0x63, 0x65, 0x00, 0x40, 0x00, 0x50, 0x00, 0x40, 0x00, 0x49, 0x00,
- 0xe2, 0x44, 0x00, 0x52, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x49, 0x00, 0xc0, 0x63, 0x17, 0x31,
- 0x00, 0x40, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x57, 0x00, 0x69, 0x00, 0x70,
- 0x00, 0x00, 0x00, 0x7f, 0x00, 0x97, 0x00, 0xdb, 0x00, 0x0d, 0x01, 0x00,
- 0x00, 0x92, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x6f, 0x02, 0x79,
- 0x02, 0x8c, 0x02, 0xc2, 0x02, 0x00, 0x00, 0xdc, 0x02, 0xe2, 0x68, 0x00,
- 0x72, 0x05, 0x40, 0x07, 0x61, 0x75, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x73, 0x6d, 0x00, 0x40, 0x07, 0x64, 0x61, 0x6c, 0x75, 0x73, 0x00, 0xe2,
- 0x75, 0x00, 0x77, 0x07, 0x40, 0x07, 0x65, 0x72, 0x72, 0x65, 0x00, 0x40,
- 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6d, 0x65, 0x79, 0x00,
- 0xe2, 0x6d, 0x00, 0x73, 0x06, 0x40, 0x07, 0x6c, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0xe6, 0x61, 0x00, 0x65, 0x04, 0x69, 0x0d, 0x6c, 0x18,
- 0x6d, 0x1d, 0x74, 0x32, 0x40, 0x00, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x73, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4,
- 0x61, 0x00, 0x65, 0x07, 0x69, 0x09, 0x6f, 0x1c, 0x40, 0x07, 0x73, 0x63,
- 0x75, 0x73, 0x00, 0x00, 0x14, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x6f, 0x08,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x6c, 0x65, 0x73, 0x00, 0x00,
- 0x07, 0xea, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0b, 0x67, 0x17, 0x69, 0x21,
- 0x6e, 0x42, 0x6f, 0x4d, 0x73, 0x52, 0x74, 0x56, 0x75, 0x61, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x06, 0x40, 0x07, 0x61, 0x77, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04,
- 0x73, 0x16, 0x40, 0x07, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x73, 0x06, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x6b, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe1,
- 0x62, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x68, 0x6e, 0x65, 0x00, 0xee, 0x62, 0x00, 0x63,
- 0x04, 0x64, 0x08, 0x65, 0x12, 0x66, 0x1b, 0x69, 0x20, 0x6a, 0x33, 0x6c,
- 0x3c, 0x6e, 0x4f, 0x72, 0x55, 0x74, 0x7a, 0x76, 0x92, 0x77, 0x97, 0x79,
- 0xb6, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x72, 0x00, 0xe4, 0x00, 0x00,
- 0x6e, 0x02, 0x6f, 0x04, 0x75, 0x06, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x69, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x6c,
- 0x6c, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x10, 0x6f, 0x14, 0x79, 0x18, 0xe2,
- 0x6c, 0x00, 0x6e, 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x77, 0x00, 0x40,
- 0x07, 0x6c, 0x00, 0xe2, 0x68, 0x00, 0x6d, 0x02, 0x00, 0x07, 0xe1, 0x6f,
- 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x74, 0x68, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x73, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0x00, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x00, 0x61, 0x6d, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x6d, 0x08, 0x40, 0x07,
- 0x68, 0x65, 0x72, 0x74, 0x79, 0x00, 0x40, 0x07, 0x69, 0x65, 0x72, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x04, 0x69, 0x12, 0x79, 0x2b, 0x40, 0x07, 0x6f,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x70, 0x6f,
- 0x72, 0x74, 0x00, 0xe3, 0x64, 0x00, 0x65, 0x0c, 0x73, 0x10, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x00, 0x07, 0x00, 0x06, 0xe4, 0x65, 0x00, 0x6b, 0x04, 0x6e,
- 0x0a, 0x73, 0x0c, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x73,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x74, 0x06, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0xc0, 0x47, 0x32, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xa4, 0x00, 0xe6,
- 0x00, 0x1c, 0x01, 0x24, 0x01, 0x35, 0x01, 0x3a, 0x01, 0x00, 0x00, 0x3f,
- 0x01, 0x5c, 0x01, 0x00, 0x00, 0x63, 0x01, 0x51, 0x02, 0xb5, 0x02, 0x09,
- 0x03, 0x0d, 0x03, 0x00, 0x00, 0x11, 0x03, 0x3e, 0x03, 0x6b, 0x03, 0x72,
- 0x03, 0x96, 0x03, 0xbe, 0x03, 0xda, 0x03, 0x40, 0x07, 0x65, 0x6e, 0x65,
- 0x72, 0x65, 0x73, 0x00, 0xe3, 0x64, 0x00, 0x6c, 0x07, 0x6e, 0x0e, 0x40,
- 0x07, 0x68, 0x65, 0x61, 0x64, 0x00, 0x40, 0x07, 0x54, 0x69, 0x6d, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x64, 0x04, 0x6e, 0x09, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x72, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe6, 0x62, 0x00, 0x69,
- 0x0b, 0x6f, 0x10, 0x72, 0x29, 0x73, 0x2d, 0x75, 0x2f, 0xe2, 0x69, 0x00,
- 0x79, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0xe2, 0x72, 0x00, 0x75, 0x0c, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x68, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65,
- 0x74, 0x00, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x73,
- 0x79, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x63, 0x13, 0x65, 0x1f, 0x6b,
- 0x26, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x74, 0x07, 0x40, 0x07, 0x6f, 0x67,
- 0x75, 0x65, 0x00, 0x40, 0x07, 0x75, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x06, 0x6d, 0x62,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6b,
- 0x69, 0x6e, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x06, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x73, 0x00, 0xe4, 0x64, 0x00, 0x6d, 0x05,
- 0x72, 0x0a, 0x74, 0x10, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x73, 0x00, 0x40, 0x07, 0x64, 0x72, 0x65, 0x00, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x75, 0x73, 0x00, 0xec, 0x00, 0x00, 0x61, 0x02,
- 0x62, 0x39, 0x65, 0x3f, 0x67, 0x44, 0x68, 0x4a, 0x69, 0x4e, 0x6c, 0x7a,
- 0x6d, 0x83, 0x6f, 0xa3, 0x70, 0xbb, 0x74, 0xd1, 0x00, 0x07, 0xe3, 0x63,
- 0x00, 0x6e, 0x11, 0x77, 0x1c, 0xe1, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x75,
- 0x05, 0x40, 0x07, 0x69, 0x78, 0x00, 0x40, 0x07, 0x7a, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x09, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x74, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x64, 0x6f, 0x00, 0x40, 0x07,
- 0x69, 0x00, 0xe5, 0x61, 0x00, 0x62, 0x02, 0x63, 0x07, 0x6c, 0x0e, 0x75,
- 0x1d, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x69, 0x6f,
- 0x75, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x65, 0x0e,
- 0x6f, 0x12, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x76, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x69,
- 0x63, 0x6f, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x06, 0x40, 0x07, 0x74, 0x74,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x6e, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09,
- 0x69, 0x22, 0x6f, 0x27, 0x70, 0x51, 0x00, 0x1c, 0x40, 0x07, 0x76, 0x65,
- 0x6e, 0x64, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x05, 0x40, 0x07, 0x6f, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x69, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00,
- 0x73, 0x1c, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0e, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00,
- 0x40, 0x07, 0x74, 0x75, 0x73, 0x00, 0x40, 0x07, 0x74, 0x68, 0x65, 0x6e,
- 0x65, 0x73, 0x00, 0x40, 0x07, 0x73, 0x65, 0x79, 0x00, 0xe8, 0x61, 0x00,
- 0x65, 0x0b, 0x67, 0x1a, 0x69, 0x1c, 0x6d, 0x28, 0x6e, 0x2e, 0x74, 0x39,
- 0x76, 0x3e, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x00, 0x69,
- 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x61, 0x00, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x72, 0x6b, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x70, 0x00, 0xe5, 0x62, 0x00, 0x65, 0x04, 0x69, 0x08,
- 0x6d, 0x0d, 0x72, 0x12, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x6b, 0x00,
- 0x40, 0x07, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x63, 0x00, 0x64, 0x04, 0x40, 0x07, 0x6b, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x08, 0x65, 0x10, 0x69, 0x16, 0x6d,
- 0x1c, 0x40, 0x07, 0x61, 0x72, 0x74, 0x65, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x6d, 0x6f, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x72, 0x65, 0x74, 0x00, 0x40,
- 0x07, 0x72, 0x65, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x64, 0x00, 0x40,
- 0x07, 0x72, 0x6f, 0x69, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x73, 0x09, 0x40, 0x07, 0x72, 0x6f, 0x6e, 0x6f, 0x6d, 0x79, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x09, 0x6f,
- 0x12, 0x40, 0x07, 0x6e, 0x61, 0x67, 0x61, 0x72, 0x69, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x0c, 0x69, 0x10, 0xe2, 0x72, 0x00, 0x79, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x74,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x08, 0x40, 0x07, 0x64, 0x72, 0x69,
- 0x6e, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x6b, 0x00, 0x75, 0x04, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6c, 0x61,
- 0x67, 0x69, 0x72, 0x69, 0x00, 0xc1, 0x43, 0x36, 0x71, 0x00, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00,
- 0x00, 0x00, 0xbf, 0x00, 0xfe, 0x00, 0x15, 0x01, 0x00, 0x00, 0x35, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00,
- 0x70, 0x01, 0x80, 0x01, 0xc5, 0x01, 0x00, 0x00, 0xcb, 0x01, 0xee, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x1d, 0x02, 0x23, 0x02, 0x00, 0x06,
- 0x40, 0x07, 0x61, 0x70, 0x72, 0x69, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x67,
- 0x67, 0x69, 0x6f, 0x00, 0xe5, 0x67, 0x00, 0x6c, 0x08, 0x6e, 0x0a, 0x73,
- 0x22, 0x7a, 0x2f, 0x40, 0x07, 0x68, 0x69, 0x6c, 0x65, 0x76, 0x00, 0x00,
- 0x07, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x6e, 0x04, 0x00, 0x07, 0x00, 0x07,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x00, 0x40, 0x09, 0x6f, 0x72,
- 0x61, 0x00, 0x00, 0x07, 0xe2, 0x6b, 0x00, 0x74, 0x31, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x1c, 0x73, 0x23, 0x00, 0x19, 0xe2, 0x6e, 0x00, 0x72,
- 0x0f, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x61, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x06,
- 0x72, 0x08, 0x40, 0x07, 0x72, 0x6f, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x69, 0x6b, 0x73, 0x6f, 0x6e, 0x00, 0xe4, 0x66, 0x00, 0x67, 0x0a, 0x6d,
- 0x0e, 0x74, 0x10, 0x40, 0x07, 0x65, 0x6e, 0x62, 0x61, 0x6b, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x6f, 0x00, 0x00, 0x07, 0x40, 0x07, 0x72, 0x69, 0x63,
- 0x68, 0x00, 0xe2, 0x67, 0x00, 0x69, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe2,
- 0x6b, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x73, 0x74, 0x72, 0x61, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0xe2, 0x62, 0x00, 0x6c, 0x06, 0x40, 0x09, 0x65, 0x72,
- 0x74, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x05, 0x6f, 0x0c, 0x40, 0x07, 0x72,
- 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x09, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x00, 0x07, 0xe5, 0x63, 0x00, 0x67, 0x09, 0x6e, 0x10,
- 0x70, 0x2e, 0x72, 0x38, 0x40, 0x07, 0x6c, 0x65, 0x74, 0x69, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x6e,
- 0x02, 0x79, 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x70, 0x65, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x06, 0x69, 0x0e, 0x6b, 0x16, 0x00, 0x00, 0x40, 0x07, 0x63,
- 0x00, 0x40, 0x07, 0x63, 0x74, 0x67, 0x6f, 0x76, 0x00, 0x40, 0x07, 0x63,
- 0x68, 0x6c, 0x65, 0x74, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6e, 0x02,
- 0x72, 0x15, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00,
- 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x40,
- 0x07, 0x61, 0x65, 0x6c, 0x69, 0x00, 0xe2, 0x58, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x69, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x1a, 0x00, 0x07, 0xe1, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x08, 0x00, 0x07, 0x40, 0x07, 0x72,
- 0x61, 0x74, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x00, 0x40, 0x07,
- 0x69, 0x74, 0x72, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0e, 0x40, 0x07,
- 0x70, 0x72, 0x6f, 0x70, 0x65, 0x74, 0x72, 0x6f, 0x76, 0x73, 0x6b, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x74, 0x65, 0x72, 0x00, 0xc0, 0x62, 0x18, 0x33,
- 0x00, 0x4a, 0x00, 0x5e, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0xa1, 0x00, 0xed,
- 0x00, 0x5a, 0x01, 0x78, 0x01, 0x00, 0x00, 0x7f, 0x01, 0xdc, 0x01, 0xe6,
- 0x01, 0xf2, 0x01, 0x28, 0x02, 0x2d, 0x02, 0x00, 0x00, 0x3d, 0x02, 0xe3,
- 0x62, 0x00, 0x65, 0x05, 0x72, 0x0c, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40,
- 0x07, 0x72, 0x6d, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x77, 0x00, 0xe3, 0x67, 0x00, 0x6f, 0x0c, 0x73,
- 0x11, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x07, 0x6d, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x00, 0xe4, 0x62, 0x00, 0x65, 0x04, 0x6c, 0x06,
- 0x6f, 0x11, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x79,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x72, 0x65, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x07, 0x40, 0x07, 0x73, 0x64, 0x61, 0x79,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x35, 0xe2, 0x67, 0x00, 0x69, 0x0c, 0xe2,
- 0x6f, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x7a, 0x00, 0xe3,
- 0x63, 0x00, 0x6f, 0x14, 0x71, 0x18, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6b,
- 0x0b, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09,
- 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x65, 0x00, 0x40,
- 0x07, 0x69, 0x61, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x28,
- 0x69, 0x2e, 0x6e, 0x36, 0x6f, 0x5a, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x68,
- 0x02, 0x6c, 0x07, 0x74, 0x16, 0x00, 0x07, 0x40, 0x07, 0x75, 0x65, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x40, 0x07,
- 0x74, 0x73, 0x6b, 0x00, 0x40, 0x07, 0x7a, 0x65, 0x74, 0x74, 0x69, 0x00,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x69, 0x13, 0x79, 0x17, 0x00,
- 0x0e, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x06, 0x00, 0x07,
- 0x40, 0x07, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x76, 0x61, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x10, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x74, 0x74,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x62, 0x75, 0x72, 0x79, 0x00,
- 0x40, 0x07, 0x70, 0x6c, 0x65, 0x72, 0x00, 0xe7, 0x61, 0x00, 0x63, 0x02,
- 0x65, 0x07, 0x69, 0x0c, 0x6f, 0x22, 0x73, 0x33, 0x74, 0x3f, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x73, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe4, 0x61,
- 0x00, 0x63, 0x04, 0x73, 0x06, 0x74, 0x08, 0x40, 0x07, 0x6e, 0x00, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x07, 0x61, 0x00, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x74, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe2, 0x68, 0x00, 0x6d, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07,
- 0x75, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x65, 0x76, 0x73, 0x6b,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x62, 0x0b, 0x67, 0x13, 0x72, 0x29, 0xe2,
- 0x6c, 0x00, 0x79, 0x04, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x6c, 0x65, 0x64, 0x61, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x73, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe7, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x46, 0x69, 0x6f, 0x6f, 0x76, 0x75, 0x7d, 0x79,
- 0x83, 0x00, 0x00, 0xe5, 0x63, 0x00, 0x6b, 0x17, 0x6d, 0x1b, 0x6e, 0x2d,
- 0x76, 0x31, 0xe2, 0x6f, 0x00, 0x75, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x61,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x62, 0x07, 0x40, 0x06,
- 0x6d, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x75, 0x69, 0x65, 0x00, 0x40,
- 0x07, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x64, 0x69, 0x61, 0x6e, 0x00, 0xe5,
- 0x61, 0x00, 0x69, 0x0a, 0x73, 0x10, 0x77, 0x16, 0x79, 0x18, 0x40, 0x07,
- 0x6d, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x00, 0x40, 0x07, 0x73, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x64, 0x65, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x66, 0x75, 0x73, 0x00, 0x40, 0x07, 0x73, 0x74, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x70, 0x62, 0x6f, 0x78, 0x00, 0x40, 0x07, 0x64, 0x67, 0x65, 0x00,
- 0x40, 0x07, 0x64, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x63, 0x68, 0x75, 0x62,
- 0x62, 0x61, 0x00, 0xc1, 0x50, 0x27, 0x53, 0x00, 0x55, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x60, 0x00, 0x85, 0x00,
- 0x8c, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00,
- 0x00, 0x00, 0x9f, 0x00, 0xa3, 0x00, 0xb2, 0x00, 0xd3, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x63, 0x01, 0x93, 0x01, 0x00, 0x00,
- 0xb6, 0x01, 0x00, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x74, 0x00, 0x40, 0x07,
- 0x6e, 0x65, 0x00, 0xe5, 0x61, 0x00, 0x63, 0x04, 0x68, 0x09, 0x6c, 0x0d,
- 0x72, 0x12, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x65, 0x6b, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x76,
- 0x6e, 0x69, 0x6b, 0x00, 0x40, 0x07, 0x68, 0x61, 0x6d, 0x70, 0x00, 0x40,
- 0x07, 0x6c, 0x65, 0x79, 0x00, 0x40, 0x07, 0x66, 0x79, 0x00, 0x40, 0x07,
- 0x73, 0x62, 0x75, 0x72, 0x67, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x6c,
- 0x00, 0x75, 0x05, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x74, 0x68,
- 0x00, 0xe3, 0x61, 0x00, 0x62, 0x04, 0x70, 0x13, 0x40, 0x07, 0x73, 0x00,
- 0xe2, 0x6c, 0x00, 0x6f, 0x08, 0x40, 0x07, 0x65, 0x64, 0x6f, 0x72, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe8, 0x61,
- 0x00, 0x62, 0x05, 0x63, 0x0a, 0x64, 0x0f, 0x65, 0x14, 0x6b, 0x1a, 0x6c,
- 0x20, 0x6e, 0x25, 0x40, 0x07, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x61, 0x72,
- 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x65, 0x00, 0x40,
- 0x07, 0x64, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x72, 0x6b, 0x00, 0x40,
- 0x07, 0x61, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe6, 0x61, 0x00, 0x62, 0x1b, 0x65, 0x20, 0x68, 0x29, 0x6b, 0x2e,
- 0x6f, 0x35, 0xe2, 0x63, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x65, 0x6c, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x72,
- 0x00, 0x78, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6d, 0x00,
- 0x40, 0x07, 0x68, 0x65, 0x69, 0x6d, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x68, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe4, 0x65,
- 0x00, 0x68, 0x02, 0x73, 0x09, 0x74, 0x12, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x62, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x64, 0x6f, 0x72, 0x66,
- 0x00, 0xe3, 0x62, 0x00, 0x69, 0x08, 0x79, 0x0c, 0x40, 0x07, 0x75, 0x73,
- 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe1, 0x63,
- 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00,
- 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61,
- 0x6c, 0x69, 0x65, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07,
- 0x6e, 0x61, 0x00, 0x40, 0x07, 0x72, 0x61, 0x6b, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x06, 0x40, 0x07, 0x79, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x67, 0x68,
- 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x73, 0x0b, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x0b, 0x40, 0x07, 0x72, 0x7a,
- 0x68, 0x69, 0x6e, 0x73, 0x6b, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x61,
- 0x72, 0x69, 0x61, 0x00, 0xc1, 0x43, 0x38, 0x75, 0x00, 0x77, 0x00, 0x94,
- 0x00, 0x9d, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xba, 0x00, 0xbe, 0x00, 0xc2, 0x00, 0xcb, 0x00, 0xcf, 0x00, 0xd3,
- 0x00, 0x00, 0x00, 0xd7, 0x00, 0xe0, 0x00, 0xfc, 0x00, 0x09, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x9b,
- 0x01, 0xd2, 0x01, 0x23, 0x02, 0xda, 0x02, 0xe1, 0x02, 0xf9, 0x02, 0x1d,
- 0x03, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x60, 0x05, 0xd5,
- 0x05, 0xab, 0x06, 0xb2, 0x06, 0x51, 0x07, 0x5a, 0x07, 0x5f, 0x08, 0x56,
- 0x09, 0xb7, 0x09, 0x9c, 0x0a, 0x34, 0x0b, 0x3a, 0x0b, 0x93, 0x0b, 0xa9,
- 0x0b, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x47, 0x02, 0x4d, 0x04, 0x4e, 0x0e,
- 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x41, 0x53, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x78, 0x74, 0x00, 0xe2, 0x50, 0x00, 0x54,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xe3, 0x43, 0x00, 0x47, 0x02, 0x4f, 0x04,
- 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x43, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe2, 0x4c, 0x00, 0x54, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x47, 0x00, 0x40, 0x07, 0x46, 0x00, 0xe2, 0x00, 0x00, 0x54, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x07, 0x45, 0x00, 0x40, 0x00, 0x45, 0x00, 0x40,
- 0x07, 0x41, 0x00, 0xe2, 0x00, 0x00, 0x41, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xe5, 0x45, 0x00, 0x4c, 0x02, 0x50, 0x04, 0x52, 0x0d, 0x54, 0x0f, 0x00,
- 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x41, 0x02, 0x44, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00,
- 0x40, 0x08, 0x41, 0x00, 0xe4, 0x6b, 0x00, 0x72, 0x06, 0x73, 0x4e, 0x74,
- 0x79, 0x40, 0x07, 0x69, 0x6e, 0x73, 0x00, 0xe4, 0x68, 0x00, 0x6c, 0x06,
- 0x6e, 0x1f, 0x70, 0x3d, 0x40, 0x07, 0x61, 0x72, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x0d, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x68, 0x12, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x61, 0x72, 0x64, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe5, 0x00,
- 0x00, 0x65, 0x02, 0x6d, 0x0e, 0x6f, 0x13, 0x77, 0x17, 0x00, 0x0f, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x1d, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6f,
- 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x17,
- 0x72, 0x2c, 0xe2, 0x6e, 0x00, 0x72, 0x0e, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x7a, 0x65, 0x72, 0x00, 0x40, 0x07, 0x74,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x05, 0x40, 0x07, 0x63, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x6f, 0x00, 0xe4, 0x63, 0x00, 0x6f, 0x0c, 0x73, 0x1c, 0x75, 0x23, 0x40,
- 0x07, 0x6c, 0x65, 0x73, 0x69, 0x61, 0x73, 0x74, 0x65, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x50, 0x61, 0x70, 0x65,
- 0x72, 0x73, 0x00, 0x40, 0x00, 0x74, 0x61, 0x73, 0x79, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x06, 0x69, 0x0b, 0x00, 0x07, 0x40, 0x06, 0x6e,
- 0x00, 0x40, 0x00, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0xeb,
- 0x00, 0x00, 0x61, 0x02, 0x64, 0x06, 0x65, 0x1f, 0x67, 0x23, 0x69, 0x34,
- 0x6d, 0x4c, 0x6e, 0x65, 0x73, 0x69, 0x75, 0x6e, 0x77, 0x75, 0x00, 0x1e,
- 0x40, 0x06, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x02, 0x79, 0x10, 0x00,
- 0x07, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x67, 0x74,
- 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6f, 0x00, 0xe3, 0x6e, 0x00, 0x73, 0x08, 0x74, 0x0d, 0x40, 0x07, 0x62,
- 0x75, 0x72, 0x67, 0x68, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x68, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x64,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x64, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00,
- 0x40, 0x07, 0x61, 0x72, 0x64, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x1a,
- 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x73, 0x09, 0x00, 0x06, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x00, 0x07,
- 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x79, 0x6f, 0x72, 0x65, 0x00, 0xe2, 0x66, 0x00,
- 0x72, 0x05, 0x40, 0x07, 0x69, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05,
- 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x67, 0x00,
- 0x79, 0x04, 0x40, 0x07, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x07, 0x40, 0x09, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x6f, 0x67, 0x79, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x6c, 0x08, 0x40, 0x07, 0x6e, 0x62, 0x65, 0x72, 0x67,
- 0x00, 0x40, 0x07, 0x69, 0x63, 0x68, 0x00, 0xe6, 0x63, 0x00, 0x66, 0x08,
- 0x6c, 0x0e, 0x6e, 0x14, 0x72, 0x1c, 0x73, 0x20, 0x40, 0x07, 0x68, 0x6d,
- 0x61, 0x6e, 0x6e, 0x00, 0x40, 0x07, 0x66, 0x65, 0x6c, 0x00, 0x40, 0x07,
- 0x65, 0x65, 0x6e, 0x00, 0x40, 0x09, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x16, 0xe1, 0x6e, 0x00,
- 0xe2, 0x68, 0x00, 0x73, 0x07, 0x40, 0x07, 0x6f, 0x77, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x74, 0x65, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0xc0, 0x61, 0x19, 0x35, 0x00, 0x54, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x72,
- 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf9, 0x00, 0x39, 0x01, 0x48, 0x01, 0x57, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x6a, 0x01, 0x6f, 0x01, 0x8c, 0x01, 0x9b, 0x01, 0x9f, 0x01, 0xb9,
- 0x01, 0x00, 0x00, 0xc7, 0x01, 0xe4, 0x69, 0x00, 0x6d, 0x05, 0x6e, 0x07,
- 0x73, 0x0c, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6f,
- 0x72, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x70, 0x6c, 0x61, 0x73, 0x74, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x02, 0x72, 0x0d, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x0f, 0x6e,
- 0x15, 0xe2, 0x6e, 0x00, 0x7a, 0x05, 0x40, 0x07, 0x6f, 0x72, 0x00, 0x40,
- 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x74, 0x72, 0x61, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02,
- 0x6a, 0x06, 0x6e, 0x0b, 0x6f, 0x10, 0x73, 0x14, 0x7a, 0x35, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x68, 0x00, 0x40, 0x07, 0x6f,
- 0x72, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0d, 0x68,
- 0x16, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x74,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x02, 0x69, 0x10, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6d, 0x65, 0x72, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x6e,
- 0x02, 0x6f, 0x09, 0x73, 0x15, 0x00, 0x07, 0x40, 0x07, 0x67, 0x74, 0x6f,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x6f, 0x06, 0x00, 0x07, 0x40, 0x07,
- 0x72, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74,
- 0x68, 0x00, 0x40, 0x07, 0x72, 0x61, 0x00, 0xe3, 0x68, 0x00, 0x69, 0x05,
- 0x79, 0x0a, 0x40, 0x07, 0x69, 0x6d, 0x00, 0x40, 0x07, 0x73, 0x65, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x6f, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02,
- 0x69, 0x09, 0x00, 0x07, 0x40, 0x07, 0x76, 0x69, 0x65, 0x72, 0x00, 0xe2,
- 0x65, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x6e, 0x69, 0x6e, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0xe4, 0x61, 0x00, 0x6e, 0x02, 0x72, 0x04, 0x73, 0x08, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x6f, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x64, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x6d, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x1e, 0x6d, 0x4a, 0x6f, 0x65, 0xe2,
- 0x63, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x75, 0x65,
- 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x73, 0x00, 0x79, 0x05, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x18, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x04, 0x79, 0x0d, 0x00, 0x07, 0x00, 0x07, 0xe2,
- 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x65,
- 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x00, 0x63, 0x65,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0d, 0x79, 0x12, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x75, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x74,
- 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x72, 0x79, 0x00, 0xe9, 0x63, 0x00,
- 0x64, 0x07, 0x67, 0x24, 0x69, 0x74, 0x6b, 0x86, 0x6f, 0x8c, 0x72, 0x97,
- 0x74, 0xae, 0x76, 0xb8, 0x40, 0x07, 0x61, 0x72, 0x74, 0x61, 0x00, 0xe3,
- 0x4e, 0x00, 0x6f, 0x06, 0x79, 0x0f, 0x40, 0x07, 0x6f, 0x74, 0x65, 0x00,
- 0x40, 0x00, 0x63, 0x72, 0x69, 0x6e, 0x6f, 0x6c, 0x00, 0x40, 0x07, 0x6d,
- 0x69, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x6c,
- 0x0e, 0x00, 0x07, 0x40, 0x07, 0x64, 0x67, 0x65, 0x74, 0x00, 0x40, 0x07,
- 0x6c, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x6e, 0x64,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02,
- 0x77, 0x0f, 0x00, 0x1f, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe3, 0x64, 0x00, 0x66, 0x02, 0x77, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x74, 0x6f, 0x6b, 0x00, 0x40, 0x07, 0x69, 0x64, 0x75, 0x00,
- 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40, 0x07, 0x68, 0x00, 0x00, 0x07, 0xe2,
- 0x69, 0x00, 0x6f, 0x0e, 0xe2, 0x63, 0x00, 0x71, 0x04, 0x40, 0x07, 0x6f,
- 0x00, 0x40, 0x07, 0x75, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x00, 0x40, 0x07, 0x69, 0x72,
- 0x6f, 0x66, 0x61, 0x63, 0x74, 0x73, 0x00, 0x40, 0x07, 0x63, 0x65, 0x6e,
- 0x65, 0x00, 0xe4, 0x63, 0x00, 0x68, 0x05, 0x69, 0x21, 0x73, 0x82, 0x40,
- 0x07, 0x6f, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x11, 0xe1, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x07, 0x61, 0x69, 0x6d, 0x00, 0xe5, 0x63, 0x00, 0x6d,
- 0x1d, 0x6e, 0x26, 0x70, 0x2d, 0x73, 0x34, 0xe2, 0x74, 0x00, 0x75, 0x07,
- 0x40, 0x07, 0x65, 0x74, 0x75, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65,
- 0x00, 0x75, 0x05, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x65, 0x74, 0x68, 0x69, 0x75, 0x73, 0x00, 0x40, 0x07, 0x69,
- 0x6f, 0x6e, 0x73, 0x00, 0x40, 0x06, 0x68, 0x61, 0x6e, 0x79, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x18, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40,
- 0x09, 0x61, 0x6e, 0x00, 0x40, 0x00, 0x6c, 0x65, 0x00, 0xe2, 0x6f, 0x00,
- 0x74, 0x09, 0xe2, 0x6d, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x75, 0x6c, 0x65, 0x75,
- 0x73, 0x00, 0xed, 0x00, 0x00, 0x61, 0x02, 0x65, 0x20, 0x68, 0x38, 0x69,
- 0x3e, 0x6c, 0x9c, 0x6d, 0xa6, 0x6e, 0xaa, 0x6f, 0xd3, 0x72, 0xd7, 0x73,
- 0xdc, 0x76, 0xe0, 0x77, 0xe5, 0x00, 0x07, 0xe2, 0x73, 0x00, 0x74, 0x06,
- 0x40, 0x07, 0x6d, 0x75, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x68, 0x65, 0x6e, 0x65, 0x73,
- 0x00, 0xe3, 0x62, 0x00, 0x63, 0x05, 0x77, 0x0b, 0x40, 0x07, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x74, 0x6f, 0x72, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x6e,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00, 0xe7, 0x63, 0x00, 0x64, 0x27,
- 0x65, 0x2e, 0x6b, 0x30, 0x6e, 0x39, 0x73, 0x3b, 0x74, 0x3d, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x68, 0x04, 0x6b, 0x06, 0x73, 0x16, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x04, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x6f, 0x6e,
- 0x00, 0x40, 0x07, 0x61, 0x6e, 0x75, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x09, 0xe1,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x65, 0x6e, 0x6d, 0x65, 0x79,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x02,
- 0x69, 0x18, 0x73, 0x1c, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x74, 0x00,
- 0x40, 0x09, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x07, 0x49, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe8,
- 0x61, 0x00, 0x63, 0x04, 0x6b, 0x25, 0x6d, 0x2b, 0x70, 0x34, 0x71, 0x56,
- 0x73, 0x63, 0x74, 0x85, 0x40, 0x07, 0x75, 0x00, 0xe2, 0x68, 0x00, 0x6f,
- 0x14, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x63, 0x68, 0x69, 0x61, 0x00, 0x40, 0x00, 0x6e,
- 0x64, 0x69, 0x64, 0x6f, 0x00, 0x40, 0x09, 0x69, 0x6d, 0x6f, 0x00, 0x40,
- 0x07, 0x65, 0x72, 0x61, 0x6c, 0x64, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x16, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x74,
- 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x6e, 0x6f, 0x7a, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00,
- 0x07, 0x40, 0x09, 0x69, 0x72, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x19,
- 0xe3, 0x6e, 0x00, 0x71, 0x09, 0x78, 0x10, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x69, 0x62, 0x6f, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x0c, 0x68, 0x39,
- 0x6f, 0x3e, 0x72, 0x50, 0x40, 0x00, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x6d,
- 0x65, 0x6e, 0x74, 0x00, 0xe4, 0x62, 0x00, 0x6c, 0x05, 0x72, 0x15, 0x73,
- 0x22, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x02, 0x00,
- 0x07, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x68, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x7a, 0x79, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0x40, 0x07, 0x61, 0x64, 0x61, 0x00, 0xe5, 0x68, 0x00, 0x6e, 0x37, 0x6f,
- 0x3b, 0x72, 0x3f, 0x74, 0x52, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x1b,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x0c, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x64, 0x00, 0x40, 0x07, 0x6e,
- 0x65, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe2,
- 0x72, 0x00, 0x73, 0x05, 0x40, 0x07, 0x69, 0x61, 0x00, 0x40, 0x07, 0x63,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0xeb, 0x00, 0x00, 0x63, 0x02,
- 0x67, 0x26, 0x6b, 0x40, 0x6c, 0x49, 0x6d, 0x54, 0x6e, 0x5d, 0x70, 0x63,
- 0x72, 0x6c, 0x73, 0xbd, 0x74, 0xc7, 0x00, 0x07, 0xe2, 0x68, 0x00, 0x6c,
- 0x1a, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x63, 0x00, 0x40, 0x07, 0x69, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe3, 0x61, 0x00,
- 0x65, 0x02, 0x6f, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x09,
- 0x61, 0x72, 0x79, 0x6f, 0x74, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x69, 0x64,
- 0x65, 0x73, 0x00, 0x40, 0x07, 0x69, 0x63, 0x65, 0x00, 0x40, 0x07, 0x68,
- 0x72, 0x61, 0x74, 0x65, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x14, 0x6f, 0x1c, 0x79, 0x3f, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x09, 0x40, 0x07, 0x70, 0x69, 0x64, 0x65, 0x73, 0x00, 0xe3, 0x00, 0x00,
- 0x64, 0x02, 0x70, 0x0a, 0x00, 0x09, 0x40, 0x06, 0x6f, 0x6c, 0x6c, 0x61,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x07, 0x64, 0x69,
- 0x63, 0x65, 0x00, 0x40, 0x07, 0x74, 0x61, 0x63, 0x68, 0x69, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x70, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x40, 0x69, 0x84, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe3, 0x00,
- 0x00, 0x67, 0x02, 0x73, 0x24, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x69, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x05, 0x73, 0x0e, 0x40,
- 0x00, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x76, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02,
- 0x6e, 0x07, 0x72, 0x0c, 0x00, 0x07, 0x40, 0x07, 0x79, 0x6e, 0x00, 0x40,
- 0x07, 0x6b, 0x69, 0x00, 0xe4, 0x52, 0x00, 0x65, 0x07, 0x67, 0x1c, 0x74,
- 0x24, 0x40, 0x07, 0x65, 0x61, 0x64, 0x79, 0x00, 0xe2, 0x73, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x61, 0x64, 0x65, 0x73,
- 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x74, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0xe5, 0x63,
- 0x00, 0x65, 0x2a, 0x6f, 0x33, 0x70, 0x42, 0x78, 0x49, 0xe3, 0x61, 0x00,
- 0x65, 0x08, 0x68, 0x1b, 0x40, 0x07, 0x6c, 0x69, 0x62, 0x75, 0x72, 0x00,
- 0xe2, 0x64, 0x00, 0x6c, 0x06, 0x40, 0x07, 0x72, 0x69, 0x6e, 0x00, 0x40,
- 0x06, 0x6c, 0x65, 0x6e, 0x63, 0x79, 0x00, 0x40, 0x00, 0x65, 0x71, 0x75,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x72, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x00,
- 0xe2, 0x63, 0x00, 0x64, 0x05, 0x40, 0x07, 0x65, 0x74, 0x00, 0x40, 0x07,
- 0x75, 0x73, 0x00, 0x40, 0x07, 0x65, 0x64, 0x69, 0x61, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x72, 0x04, 0x73, 0x08, 0x40, 0x07,
- 0x6b, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x63, 0x6b,
- 0x00, 0xe2, 0x65, 0x00, 0x72, 0x07, 0x40, 0x07, 0x6b, 0x69, 0x65, 0x6c,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0xc1, 0x41, 0x35, 0x6f, 0x00, 0x71, 0x00,
- 0x7a, 0x00, 0x7e, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x95, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, 0xa8, 0x00,
- 0xaa, 0x00, 0xaf, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00,
- 0xcf, 0x00, 0xd3, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0xfc, 0x04, 0xe3, 0x05, 0x00, 0x00, 0xe5, 0x05, 0x00, 0x00, 0x00, 0x00,
- 0xd4, 0x06, 0x00, 0x00, 0x00, 0x00, 0x82, 0x09, 0x00, 0x20, 0xe2, 0x41,
- 0x00, 0x51, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x07, 0x49, 0x00, 0x40,
- 0x00, 0x43, 0x00, 0xe4, 0x00, 0x00, 0x41, 0x02, 0x49, 0x04, 0x52, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x43, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x41, 0x00, 0xe2, 0x43, 0x00, 0x46, 0x04, 0x40, 0x07, 0x41, 0x00, 0x40,
- 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x06, 0x40, 0x07, 0x4d, 0x41, 0x00,
- 0xe2, 0x46, 0x00, 0x52, 0x04, 0x40, 0x00, 0x4c, 0x00, 0x40, 0x07, 0x54,
- 0x52, 0x41, 0x4e, 0x00, 0x40, 0x00, 0x4f, 0x00, 0xe2, 0x46, 0x00, 0x4c,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x49, 0x43, 0x00, 0x40, 0x00, 0x43, 0x00,
- 0x40, 0x08, 0x44, 0x00, 0xe2, 0x44, 0x00, 0x49, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x57, 0x00, 0xe2, 0x00, 0x00, 0x49, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xc0, 0x62, 0x18, 0x33, 0x00, 0x43, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x51,
- 0x00, 0x57, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92,
- 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb,
- 0x00, 0x20, 0x01, 0x30, 0x01, 0x54, 0x01, 0x99, 0x01, 0xa2, 0x01, 0x00,
- 0x00, 0xa8, 0x01, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07, 0x72, 0x67,
- 0x65, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x62, 0x6f,
- 0x6f, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x69, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x68, 0x65, 0x69, 0x74, 0x00,
- 0xe3, 0x72, 0x00, 0x73, 0x08, 0x74, 0x1b, 0x40, 0x07, 0x62, 0x61, 0x6e,
- 0x6b, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x62, 0x61, 0x64, 0x00, 0x40, 0x07,
- 0x68, 0x00, 0xe5, 0x61, 0x00, 0x6b, 0x06, 0x6c, 0x1b, 0x73, 0x23, 0x77,
- 0x2a, 0x40, 0x07, 0x73, 0x68, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x70, 0x69, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x74, 0x61, 0x66, 0x66, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0xe6, 0x61, 0x00, 0x67, 0x06, 0x6c, 0x0a, 0x6d, 0x0f,
- 0x72, 0x14, 0x73, 0x34, 0x40, 0x07, 0x64, 0x61, 0x79, 0x00, 0x40, 0x07,
- 0x6f, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x10, 0x6f, 0x15, 0xe2, 0x67, 0x00, 0x6b, 0x05,
- 0x40, 0x07, 0x75, 0x74, 0x00, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x77, 0x00, 0x40, 0x07, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x62, 0x69, 0x6e,
- 0x64, 0x65, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x68, 0x08, 0x69,
- 0x0d, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x64, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x18, 0x73, 0x21, 0xe1,
- 0x6b, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x74, 0x6c, 0x65, 0x72, 0x6f, 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x75, 0x0f, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6e,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x00, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x64, 0x00, 0x40, 0x07,
- 0x6b, 0x65, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x64, 0x10, 0x6c, 0x3d, 0x6e, 0x6f,
- 0x72, 0x7b, 0x79, 0xf2, 0x7a, 0xf9, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x07, 0x40, 0x06, 0x75, 0x61, 0x72, 0x79, 0x00, 0xe4, 0x00,
- 0x00, 0x45, 0x02, 0x65, 0x06, 0x73, 0x22, 0x00, 0x06, 0x40, 0x07, 0x78,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0f, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x74, 0x00,
- 0x40, 0x07, 0x63, 0x6f, 0x00, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x06,
- 0x6c, 0x25, 0x40, 0x07, 0x63, 0x69, 0x61, 0x00, 0xe3, 0x63, 0x00, 0x70,
- 0x12, 0x78, 0x16, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6e, 0x69, 0x00, 0xe2, 0x67, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe7, 0x62, 0x00,
- 0x64, 0x05, 0x67, 0x0d, 0x6c, 0x1e, 0x6d, 0x29, 0x6e, 0x34, 0x72, 0x4c,
- 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x61, 0x6e, 0x64,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x68,
- 0x65, 0x74, 0x74, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x07,
- 0x74, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07,
- 0x7a, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x65, 0x0c, 0x69, 0x11, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x6d,
- 0x61, 0x6e, 0x00, 0x00, 0x07, 0xfe, 0x61, 0x00, 0x00, 0x62, 0x04, 0x00,
- 0x63, 0x19, 0x00, 0x64, 0x1f, 0x00, 0x65, 0x2a, 0x00, 0x67, 0x3c, 0x00,
- 0x6a, 0x4d, 0x00, 0x6c, 0x5b, 0x00, 0x6e, 0x7f, 0x00, 0x6f, 0xd0, 0x00,
- 0x72, 0xd5, 0x00, 0x73, 0xe9, 0x00, 0x74, 0xfd, 0x00, 0x7a, 0x23, 0x01,
- 0x40, 0x07, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x08, 0x40, 0x07, 0x72,
- 0x67, 0x6c, 0x61, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x63, 0x63, 0x69,
- 0x00, 0x40, 0x07, 0x68, 0x74, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04,
- 0x40, 0x07, 0x6c, 0x00, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x69, 0x00, 0x73, 0x05, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40, 0x07, 0x72, 0x6f, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x6f, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0xe4, 0x69, 0x00, 0x6c, 0x07,
- 0x6d, 0x0e, 0x6f, 0x15, 0x40, 0x09, 0x70, 0x69, 0x6e, 0x6f, 0x00, 0x40,
- 0x07, 0x6d, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x07, 0x53, 0x70, 0x6f, 0x74,
- 0x00, 0x40, 0x07, 0x66, 0x61, 0x78, 0x00, 0xe4, 0x63, 0x00, 0x64, 0x04,
- 0x6c, 0x18, 0x6e, 0x26, 0x40, 0x07, 0x68, 0x00, 0xe2, 0x41, 0x00, 0x4c,
- 0x0a, 0x40, 0x07, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x73, 0x00, 0x40,
- 0x07, 0x61, 0x77, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x6e,
- 0x64, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65,
- 0x0e, 0x69, 0x14, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x67, 0x61, 0x64, 0x6f,
- 0x74, 0x74, 0x69, 0x72, 0x00, 0x40, 0x07, 0x67, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x73, 0x68, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x66, 0x00, 0x73, 0x05, 0x40, 0x07, 0x6f, 0x78, 0x00, 0x40, 0x07,
- 0x74, 0x6f, 0x6e, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x68, 0x06, 0x6b, 0x0b,
- 0x40, 0x07, 0x68, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x00,
- 0x07, 0xe2, 0x63, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x68, 0x00, 0xe3, 0x67,
- 0x00, 0x70, 0x08, 0x72, 0x11, 0x40, 0x07, 0x65, 0x72, 0x61, 0x6c, 0x64,
- 0x00, 0x40, 0x07, 0x61, 0x74, 0x72, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x07,
- 0x6f, 0x79, 0x00, 0x40, 0x07, 0x65, 0x61, 0x75, 0x00, 0xe5, 0x61, 0x00,
- 0x65, 0x30, 0x69, 0x56, 0x6f, 0x72, 0x79, 0xd7, 0xe4, 0x00, 0x00, 0x6e,
- 0x02, 0x74, 0x13, 0x75, 0x20, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x64, 0x06,
- 0x40, 0x07, 0x67, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x73, 0x00,
- 0xe2, 0x68, 0x00, 0x74, 0x06, 0x40, 0x00, 0x65, 0x61, 0x64, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x62, 0x65, 0x72, 0x74, 0x00, 0xe3, 0x69, 0x00, 0x6d,
- 0x08, 0x74, 0x18, 0x40, 0x07, 0x73, 0x63, 0x68, 0x65, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07, 0x67, 0x00, 0x40,
- 0x07, 0x68, 0x00, 0x40, 0x07, 0x63, 0x68, 0x65, 0x72, 0x00, 0xe2, 0x63,
- 0x00, 0x6e, 0x05, 0x40, 0x07, 0x6b, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x65,
- 0x73, 0x00, 0xe5, 0x00, 0x00, 0x72, 0x02, 0x73, 0x4a, 0x77, 0x50, 0x79,
- 0x56, 0x00, 0x07, 0xe5, 0x61, 0x00, 0x65, 0x02, 0x69, 0x18, 0x73, 0x34,
- 0x79, 0x3b, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x73, 0x0f, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00,
- 0x00, 0x07, 0xe2, 0x64, 0x00, 0x6e, 0x13, 0xe2, 0x61, 0x00, 0x69, 0x09,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x06, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x68, 0x65, 0x69, 0x6d,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x69, 0x65, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x73, 0x00, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x6e, 0x00,
- 0x00, 0x07, 0xec, 0x63, 0x00, 0x6b, 0x04, 0x6c, 0x0a, 0x6d, 0x20, 0x6e,
- 0x29, 0x6f, 0x2e, 0x72, 0x36, 0x73, 0x95, 0x74, 0xa3, 0x75, 0xaa, 0x77,
- 0xce, 0x78, 0xd4, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x6b, 0x65, 0x72,
- 0x00, 0xe3, 0x65, 0x00, 0x67, 0x04, 0x73, 0x0a, 0x40, 0x07, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x72, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6d, 0x00, 0x40,
- 0x07, 0x61, 0x6c, 0x68, 0x61, 0x75, 0x74, 0x00, 0x40, 0x07, 0x64, 0x61,
- 0x00, 0x40, 0x07, 0x73, 0x62, 0x61, 0x6c, 0x6c, 0x00, 0xe7, 0x62, 0x00,
- 0x64, 0x05, 0x65, 0x07, 0x6d, 0x23, 0x72, 0x3c, 0x73, 0x42, 0x74, 0x48,
- 0x40, 0x07, 0x65, 0x73, 0x00, 0x00, 0x07, 0xe3, 0x6d, 0x00, 0x73, 0x05,
- 0x78, 0x13, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x0e, 0x40, 0x07, 0x72, 0x00, 0x00, 0x07, 0xe2,
- 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x63, 0x61, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x73, 0x74, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x00, 0xe2, 0x73, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x6f, 0x6d, 0x61, 0x74, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x07, 0x40, 0x07,
- 0x61, 0x75, 0x6c, 0x74, 0x00, 0xe3, 0x69, 0x00, 0x6e, 0x05, 0x74, 0x0d,
- 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x79, 0x72, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x68, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x72, 0x00, 0x00,
- 0x09, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0xed, 0x00, 0x69,
- 0xdb, 0x01, 0x6f, 0x3a, 0x02, 0x75, 0x89, 0x02, 0x79, 0x8f, 0x02, 0x00,
- 0x20, 0xe5, 0x67, 0x00, 0x6e, 0x08, 0x73, 0xc8, 0x75, 0xcd, 0x7a, 0xda,
- 0x40, 0x07, 0x6f, 0x6e, 0x61, 0x72, 0x64, 0x00, 0xe6, 0x00, 0x00, 0x63,
- 0x02, 0x67, 0x5b, 0x6b, 0x62, 0x6e, 0xad, 0x7a, 0xb1, 0x00, 0x07, 0xe4,
- 0x65, 0x00, 0x69, 0x12, 0x6b, 0x32, 0x6f, 0x34, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x09, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x00, 0x07,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x70, 0x0e, 0x00, 0x07, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x00, 0x68,
- 0x69, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x69, 0x73, 0x00, 0xe6,
- 0x00, 0x00, 0x65, 0x02, 0x66, 0x11, 0x69, 0x2c, 0x6c, 0x37, 0x73, 0x3c,
- 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x74, 0x65, 0x69, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40, 0x07,
- 0x72, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x0e, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x68, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x14, 0x40, 0x00, 0x65, 0x69,
- 0x6e, 0x00, 0x40, 0x07, 0x69, 0x65, 0x72, 0x00, 0xe9, 0x64, 0x00, 0x65,
- 0x42, 0x69, 0x77, 0x6d, 0x7c, 0x6e, 0x82, 0x6f, 0xb1, 0x73, 0xb5, 0x75,
- 0xc3, 0x79, 0xd2, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x64, 0x04, 0x65, 0x0f,
- 0x72, 0x28, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe3, 0x00, 0x00, 0x6b, 0x02, 0x74, 0x04, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe4, 0x42, 0x00,
- 0x6d, 0x05, 0x74, 0x20, 0x77, 0x26, 0x40, 0x07, 0x53, 0x44, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x07, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x40, 0x06,
- 0x79, 0x00, 0x40, 0x07, 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x72,
- 0x65, 0x00, 0x40, 0x07, 0x64, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x74,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02,
- 0x77, 0x0f, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04,
- 0x40, 0x07, 0x6c, 0x00, 0x00, 0x07, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe6, 0x00, 0x00, 0x64, 0x02, 0x65,
- 0x07, 0x67, 0x23, 0x73, 0x34, 0x74, 0x49, 0x00, 0x07, 0x40, 0x06, 0x61,
- 0x79, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x13, 0xe2, 0x61, 0x00, 0x6d, 0x09,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x06, 0x64, 0x00, 0xe2, 0x67, 0x00, 0x69, 0x04, 0x40,
- 0x07, 0x61, 0x00, 0x40, 0x07, 0x64, 0x61, 0x69, 0x72, 0x65, 0x00, 0xe3,
- 0x62, 0x00, 0x63, 0x05, 0x69, 0x09, 0x40, 0x07, 0x65, 0x65, 0x00, 0x40,
- 0x07, 0x6f, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x7a,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe6, 0x62, 0x00, 0x64, 0x08, 0x69, 0x0c,
- 0x6d, 0x14, 0x6e, 0x18, 0x73, 0x32, 0x40, 0x07, 0x69, 0x73, 0x68, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x73, 0x73, 0x61, 0x72,
- 0x74, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x50, 0x00, 0x65, 0x06, 0x40, 0x07, 0x61, 0x67,
- 0x65, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6c, 0x74, 0x00,
- 0x40, 0x07, 0x6e, 0x7a, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0xea, 0x63, 0x00, 0x65, 0x05, 0x67, 0x0c, 0x6a, 0x12,
- 0x6b, 0x31, 0x6c, 0x44, 0x6e, 0x71, 0x72, 0x81, 0x73, 0x95, 0x7a, 0x9b,
- 0x40, 0x07, 0x68, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x65, 0x73, 0x00,
- 0x40, 0x07, 0x67, 0x65, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe4, 0x00, 0x00,
- 0x74, 0x02, 0x77, 0x07, 0x79, 0x0d, 0x00, 0x07, 0x40, 0x07, 0x73, 0x75,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x61, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x61,
- 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x05, 0x40, 0x07, 0x6b,
- 0x61, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x61, 0x00, 0xe4, 0x61, 0x00, 0x62,
- 0x05, 0x6c, 0x0d, 0x74, 0x1f, 0x40, 0x07, 0x6e, 0x69, 0x00, 0x40, 0x07,
- 0x72, 0x69, 0x67, 0x68, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x64, 0x07, 0x40, 0x07,
- 0x66, 0x75, 0x74, 0x69, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x69, 0x00,
- 0x74, 0x05, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x77, 0x61, 0x6e,
- 0x67, 0x6c, 0x65, 0x72, 0x00, 0x40, 0x07, 0x68, 0x75, 0x6e, 0x00, 0xe2,
- 0x68, 0x00, 0x7a, 0x05, 0x40, 0x07, 0x6f, 0x75, 0x00, 0x40, 0x07, 0x62,
- 0x75, 0x73, 0x74, 0x65, 0x72, 0x00, 0xc1, 0x41, 0x39, 0x77, 0x00, 0x79,
- 0x00, 0x88, 0x00, 0x8a, 0x00, 0x8e, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x9b, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3,
- 0x00, 0xc2, 0x00, 0xcb, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4,
- 0x00, 0xe8, 0x00, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x04, 0x98,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x35, 0x06, 0x6d, 0x06, 0x00, 0x00, 0xf4,
- 0x07, 0xf6, 0x07, 0xa4, 0x08, 0xa9, 0x08, 0xcb, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x32, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x0d, 0x00, 0x00, 0x63,
- 0x0f, 0x00, 0x00, 0x93, 0x0f, 0x00, 0x21, 0xe3, 0x00, 0x00, 0x4f, 0x02,
- 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x54, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x43, 0x00, 0x40, 0x07, 0x50, 0x00, 0xe2, 0x00, 0x00, 0x44,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x51, 0x00, 0x7a, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe3, 0x00, 0x00, 0x46, 0x02, 0x47, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x00, 0x4f, 0x00, 0xe3, 0x00, 0x00, 0x41, 0x02, 0x54, 0x06,
- 0x00, 0x07, 0x40, 0x00, 0x54, 0x00, 0x00, 0x07, 0xe2, 0x50, 0x00, 0x55,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x50, 0x00, 0xe5, 0x00, 0x00,
- 0x41, 0x02, 0x4f, 0x04, 0x53, 0x06, 0x55, 0x08, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x41, 0x00, 0x40, 0x07,
- 0x45, 0x00, 0xe2, 0x00, 0x00, 0x49, 0x02, 0x00, 0x00, 0x00, 0x07, 0xc1,
- 0x41, 0x3a, 0x79, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00,
- 0xb9, 0x00, 0xbf, 0x00, 0xc6, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00,
- 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0xd1, 0x01, 0x1d, 0x02,
- 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x62, 0x02, 0xf2, 0x02, 0x13, 0x03,
- 0x38, 0x03, 0x71, 0x03, 0x76, 0x03, 0x00, 0x00, 0x7c, 0x03, 0x87, 0x03,
- 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x6c, 0x00, 0x6f, 0x04, 0x72,
- 0x1b, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x0c, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x04, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x72, 0x75, 0x78, 0x00, 0x40, 0x07,
- 0x73, 0x64, 0x65, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x63, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x06, 0x40, 0x07, 0x72, 0x69, 0x6e, 0x00, 0x00, 0x07,
- 0xe4, 0x61, 0x00, 0x6c, 0x02, 0x6d, 0x04, 0x6e, 0x09, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x62, 0x6f, 0x72, 0x6f, 0x75, 0x67, 0x68,
- 0x00, 0xe8, 0x61, 0x00, 0x62, 0x30, 0x65, 0x38, 0x69, 0x41, 0x6c, 0x5c,
- 0x6f, 0x97, 0x73, 0x9c, 0x76, 0xa5, 0xe4, 0x68, 0x00, 0x70, 0x05, 0x74,
- 0x0c, 0x78, 0x23, 0x40, 0x06, 0x61, 0x64, 0x00, 0x40, 0x07, 0x61, 0x67,
- 0x6f, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x61, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x72, 0x61, 0x69, 0x74,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2,
- 0x62, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x04, 0x6f, 0x06, 0x40, 0x06, 0x6e, 0x00, 0x00, 0x07,
- 0x00, 0x07, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x69, 0x0f, 0x6f,
- 0x1e, 0x75, 0x2a, 0x00, 0x07, 0x40, 0x07, 0x67, 0x68, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x67, 0x6f, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x06, 0x73, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x77, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x79, 0x00, 0x40, 0x07, 0x70,
- 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0x40, 0x07, 0x77, 0x6f, 0x72, 0x74,
- 0x68, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x6e, 0x69,
- 0x00, 0x40, 0x07, 0x73, 0x74, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x62,
- 0x09, 0x65, 0x1e, 0x6f, 0x3f, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00,
- 0x00, 0x07, 0xe2, 0x69, 0x00, 0x6c, 0x0c, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00, 0xe4,
- 0x42, 0x00, 0x43, 0x06, 0x46, 0x0c, 0x53, 0x12, 0x40, 0x07, 0x61, 0x73,
- 0x65, 0x00, 0x40, 0x07, 0x75, 0x62, 0x65, 0x00, 0x40, 0x07, 0x41, 0x51,
- 0x73, 0x00, 0x40, 0x07, 0x70, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x77, 0x00,
- 0xe5, 0x64, 0x00, 0x65, 0x18, 0x67, 0x1e, 0x74, 0x2c, 0x79, 0x31, 0xe2,
- 0x61, 0x00, 0x68, 0x05, 0x40, 0x07, 0x6c, 0x66, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x73, 0x68, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x79, 0x00,
- 0x40, 0x07, 0x6d, 0x65, 0x64, 0x65, 0x00, 0x00, 0x07, 0xef, 0x62, 0x00,
- 0x63, 0x04, 0x64, 0x09, 0x65, 0x0f, 0x66, 0x14, 0x67, 0x26, 0x69, 0x2e,
- 0x6c, 0x36, 0x6d, 0x3c, 0x6e, 0x41, 0x72, 0x46, 0x74, 0x62, 0x76, 0x66,
- 0x79, 0x6b, 0x7a, 0x6d, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x61,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x07, 0x74, 0x68, 0x00,
- 0xe2, 0x69, 0x00, 0x75, 0x06, 0x40, 0x07, 0x65, 0x6c, 0x64, 0x00, 0x40,
- 0x07, 0x6e, 0x6b, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x74, 0x75,
- 0x61, 0x00, 0x40, 0x07, 0x62, 0x61, 0x6c, 0x64, 0x69, 0x00, 0x40, 0x07,
- 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x79, 0x13, 0x40, 0x07, 0x74,
- 0x74, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6b, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07,
- 0x65, 0x79, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x63, 0x00,
- 0x73, 0x06, 0x74, 0x0b, 0x40, 0x07, 0x6f, 0x6e, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0x40, 0x00, 0x72, 0x6f, 0x65, 0x6e, 0x74, 0x65, 0x72,
- 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x00, 0xe5, 0x65, 0x00, 0x6c, 0x04, 0x6f,
- 0x0a, 0x73, 0x11, 0x75, 0x16, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x07, 0x72, 0x61, 0x64, 0x65, 0x00, 0x40, 0x07,
- 0x62, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe4, 0x67, 0x00, 0x6c, 0x06,
- 0x73, 0x12, 0x74, 0x21, 0x40, 0x07, 0x75, 0x69, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x6d, 0x61, 0x00, 0x40,
- 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x61,
- 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x74, 0x65, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x73, 0x6b, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x66, 0x02,
- 0x00, 0x68, 0x08, 0x00, 0x69, 0x18, 0x00, 0x6c, 0x1e, 0x00, 0x6d, 0x2f,
- 0x00, 0x6e, 0x35, 0x00, 0x6f, 0x93, 0x00, 0x72, 0xd2, 0x00, 0x73, 0x44,
- 0x01, 0x74, 0x4b, 0x01, 0x77, 0x6a, 0x01, 0x00, 0x07, 0x40, 0x07, 0x66,
- 0x65, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x06, 0x40, 0x07, 0x6e, 0x6e,
- 0x61, 0x00, 0x40, 0x07, 0x69, 0x67, 0x00, 0x40, 0x07, 0x67, 0x65, 0x72,
- 0x00, 0xe2, 0x62, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x76, 0x69, 0x65, 0x68,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x69, 0x00,
- 0xe7, 0x00, 0x00, 0x42, 0x02, 0x61, 0x08, 0x65, 0x13, 0x67, 0x38, 0x6f,
- 0x3e, 0x74, 0x42, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x6b, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x00, 0xe5, 0x00,
- 0x00, 0x49, 0x02, 0x73, 0x06, 0x74, 0x0b, 0x76, 0x0d, 0x00, 0x07, 0x40,
- 0x07, 0x44, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x76, 0x65, 0x00, 0x40,
- 0x07, 0x68, 0x69, 0x73, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe2, 0x6f, 0x00,
- 0x72, 0x04, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00,
- 0x00, 0x66, 0x02, 0x72, 0x09, 0x00, 0x07, 0x40, 0x07, 0x66, 0x72, 0x65,
- 0x79, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x15, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x6f, 0x00, 0x74, 0x05, 0x40, 0x07,
- 0x77, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x09,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x61,
- 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x62, 0x22, 0x65, 0x27, 0x69, 0x29,
- 0x6d, 0x2f, 0x6f, 0x44, 0x72, 0x4b, 0x73, 0x4f, 0x74, 0x56, 0x00, 0x07,
- 0xe2, 0x6c, 0x00, 0x72, 0x0f, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x74, 0x6f, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x06, 0x00, 0x09,
- 0x40, 0x07, 0x63, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x69, 0x6d, 0x6f,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x68, 0x77, 0x69, 0x6e, 0x00,
- 0x40, 0x07, 0x72, 0x75, 0x64, 0x65, 0x00, 0x40, 0x06, 0x74, 0x61, 0x70,
- 0x6f, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x09, 0x40, 0x07, 0x73, 0x65, 0x6d,
- 0x61, 0x6e, 0x65, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x62, 0x75, 0x72, 0x67, 0x00, 0x40, 0x07, 0x75,
- 0x72, 0x7a, 0x74, 0x72, 0x61, 0x6d, 0x69, 0x6e, 0x65, 0x72, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x22, 0x69, 0x27, 0xe3, 0x6e, 0x00, 0x74, 0x0f, 0x7a,
- 0x13, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x76, 0x61,
- 0x6e, 0x69, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x62,
- 0x65, 0x6c, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0xfc, 0x61, 0x00, 0x00, 0x62,
- 0x1d, 0x00, 0x64, 0x3c, 0x00, 0x65, 0x4a, 0x00, 0x6c, 0x5a, 0x00, 0x6e,
- 0xdc, 0x00, 0x6f, 0x14, 0x01, 0x72, 0x2f, 0x01, 0x73, 0x38, 0x01, 0x74,
- 0x45, 0x01, 0x75, 0x4b, 0x01, 0x7a, 0x5e, 0x01, 0xe3, 0x63, 0x00, 0x6e,
- 0x09, 0x75, 0x10, 0x40, 0x07, 0x6f, 0x6d, 0x65, 0x74, 0x74, 0x69, 0x00,
- 0x40, 0x07, 0x6e, 0x69, 0x6e, 0x69, 0x00, 0x40, 0x07, 0x71, 0x75, 0x65,
- 0x00, 0xe3, 0x62, 0x00, 0x72, 0x0b, 0x73, 0x13, 0xe2, 0x6f, 0x00, 0x73,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6c, 0x74,
- 0x61, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6c,
- 0x00, 0x6e, 0x06, 0x40, 0x07, 0x67, 0x75, 0x64, 0x00, 0x40, 0x07, 0x61,
- 0x68, 0x00, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x62, 0x04, 0x63, 0x16, 0x64,
- 0x1e, 0x65, 0x22, 0x67, 0x2d, 0x6c, 0x35, 0x6d, 0x61, 0x00, 0x07, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x68, 0x72, 0x69,
- 0x73, 0x74, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04,
- 0x40, 0x07, 0x64, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6d, 0x65, 0x73,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x12, 0x00, 0x07, 0xe2,
- 0x73, 0x00, 0x74, 0x06, 0x40, 0x07, 0x70, 0x69, 0x65, 0x00, 0x40, 0x07,
- 0x74, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x67, 0x09, 0xe2, 0x6d, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x65, 0x00,
- 0xe5, 0x61, 0x00, 0x67, 0x02, 0x6e, 0x11, 0x6f, 0x15, 0x73, 0x17, 0x00,
- 0x07, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x69, 0x63, 0x68, 0x00, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0xe2, 0x62,
- 0x00, 0x75, 0x0f, 0xe2, 0x65, 0x00, 0x75, 0x05, 0x40, 0x07, 0x72, 0x67,
- 0x00, 0x40, 0x07, 0x72, 0x67, 0x00, 0x00, 0x07, 0xe3, 0x72, 0x00, 0x74,
- 0x08, 0x76, 0x0d, 0x40, 0x07, 0x67, 0x69, 0x6f, 0x6e, 0x65, 0x00, 0x40,
- 0x07, 0x74, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x6e, 0x69, 0x00, 0x40,
- 0x07, 0x61, 0x75, 0x64, 0x6f, 0x75, 0x78, 0x00, 0xe2, 0x65, 0x00, 0x68,
- 0x06, 0x40, 0x07, 0x6c, 0x6c, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x48,
- 0x75, 0x62, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x07, 0x40, 0x07, 0x69, 0x61,
- 0x6e, 0x69, 0x00, 0x40, 0x07, 0x65, 0x70, 0x70, 0x65, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x42, 0x6f, 0x76, 0xe3,
- 0x64, 0x00, 0x73, 0x10, 0x78, 0x37, 0xe2, 0x73, 0x00, 0x79, 0x07, 0x40,
- 0x09, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe5, 0x65,
- 0x00, 0x67, 0x04, 0x73, 0x09, 0x74, 0x0b, 0x77, 0x14, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6f, 0x77, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e,
- 0x62, 0x75, 0x72, 0x79, 0x00, 0x40, 0x06, 0x65, 0x67, 0x69, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x06, 0x40, 0x07,
- 0x73, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6c, 0x10, 0x6e,
- 0x17, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x69, 0x76, 0x65, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x72, 0x00,
- 0x75, 0x05, 0x76, 0x25, 0x40, 0x07, 0x69, 0x61, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x68, 0x69, 0x72, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x62, 0x48, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x18, 0xe1, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x00, 0x50, 0x47,
- 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0x37, 0x00, 0x00, 0x00, 0x3b, 0x00,
- 0x8d, 0x00, 0xb0, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc6, 0x00, 0x39, 0x01, 0x59, 0x01, 0x7f, 0x01, 0xc6, 0x01,
- 0x00, 0x00, 0xcc, 0x01, 0x20, 0x02, 0x26, 0x02, 0x47, 0x02, 0x5b, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x00,
- 0xeb, 0x00, 0x00, 0x61, 0x02, 0x64, 0x07, 0x65, 0x0d, 0x68, 0x11, 0x69,
- 0x17, 0x6f, 0x1c, 0x73, 0x20, 0x74, 0x27, 0x75, 0x2e, 0x7a, 0x34, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00,
- 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x61, 0x64, 0x00, 0x40, 0x07,
- 0x76, 0x61, 0x00, 0x40, 0x07, 0x74, 0x00, 0x40, 0x06, 0x70, 0x65, 0x65,
- 0x64, 0x00, 0x40, 0x07, 0x68, 0x61, 0x61, 0x62, 0x00, 0x40, 0x07, 0x6e,
- 0x6f, 0x76, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x61, 0x00, 0xe3, 0x62,
- 0x00, 0x72, 0x07, 0x74, 0x0d, 0x40, 0x07, 0x62, 0x65, 0x6c, 0x73, 0x00,
- 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x05, 0x40, 0x07, 0x6c, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x66,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00,
- 0x40, 0x07, 0x61, 0x6e, 0x69, 0x61, 0x00, 0xe5, 0x61, 0x00, 0x63, 0x04,
- 0x64, 0x0b, 0x67, 0x55, 0x69, 0x62, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x64, 0x61, 0x00, 0xe7, 0x61, 0x00, 0x62, 0x02, 0x65, 0x08,
- 0x69, 0x0c, 0x6d, 0x20, 0x73, 0x25, 0x77, 0x2c, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x72, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x6c,
- 0x02, 0x6e, 0x09, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x63, 0x6b, 0x73, 0x00,
- 0x40, 0x07, 0x67, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6d,
- 0x69, 0x74, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x06, 0x40, 0x07, 0x74,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x74, 0x68, 0x61, 0x00, 0x40, 0x07, 0x61, 0x74,
- 0x68, 0x00, 0xe4, 0x65, 0x00, 0x6f, 0x04, 0x70, 0x0b, 0x75, 0x11, 0x40,
- 0x07, 0x7a, 0x00, 0x40, 0x07, 0x72, 0x72, 0x61, 0x68, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x73, 0x00, 0x40, 0x07, 0x6c, 0x6b, 0x61, 0x00, 0xe2, 0x64,
- 0x00, 0x7a, 0x0b, 0x40, 0x07, 0x77, 0x61, 0x6e, 0x61, 0x6c, 0x61, 0x6e,
- 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x09, 0xe2, 0x73, 0x00, 0x7a, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
- 0xe3, 0x64, 0x00, 0x67, 0x33, 0x6c, 0x38, 0xe6, 0x00, 0x00, 0x61, 0x02,
- 0x6d, 0x07, 0x72, 0x0c, 0x77, 0x12, 0x79, 0x20, 0x00, 0x07, 0x40, 0x07,
- 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x63,
- 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x07,
- 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x61, 0x72, 0x00, 0x40, 0x07,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x61, 0x67, 0x6f, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x68, 0x65, 0x72, 0x00, 0xe5, 0x62, 0x00, 0x64, 0x08, 0x65, 0x1f,
- 0x67, 0x2c, 0x6b, 0x45, 0x40, 0x07, 0x61, 0x63, 0x68, 0x65, 0x76, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x0e, 0xe2, 0x61, 0x00, 0x6d, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x6e, 0x02, 0x79, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x7a, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6c, 0x61,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x70, 0x65, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x68, 0x07, 0x40, 0x07, 0x62, 0x6f, 0x72, 0x67, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x73, 0x0a, 0x00, 0x07, 0x40, 0x07,
- 0x6d, 0x00, 0x40, 0x09, 0x63, 0x00, 0x00, 0x00, 0xe3, 0x64, 0x00, 0x6c,
- 0x04, 0x6e, 0x08, 0x40, 0x06, 0x61, 0x00, 0x40, 0x07, 0x64, 0x00, 0x40,
- 0x07, 0x6f, 0x64, 0x00, 0x40, 0x00, 0x65, 0x72, 0x6e, 0x6f, 0x72, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65,
- 0x9f, 0x00, 0x69, 0x84, 0x01, 0x6f, 0xbe, 0x01, 0x75, 0xf0, 0x01, 0x00,
- 0x22, 0xeb, 0x62, 0x00, 0x63, 0x05, 0x64, 0x2d, 0x66, 0x31, 0x68, 0x41,
- 0x69, 0x50, 0x6d, 0x5f, 0x6e, 0x6f, 0x73, 0x7b, 0x76, 0x7f, 0x79, 0x84,
- 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x65, 0x06, 0x69, 0x13,
- 0x40, 0x07, 0x68, 0x75, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0xe2, 0x66, 0x00, 0x74, 0x06, 0x40, 0x07, 0x69, 0x61, 0x73, 0x00,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x47, 0x65, 0x6e, 0x65, 0x73, 0x00, 0xe2,
- 0x6d, 0x00, 0x70, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x69, 0x61,
- 0x6e, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x05, 0x40, 0x07, 0x64, 0x61,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00,
- 0x00, 0x07, 0xe7, 0x63, 0x00, 0x65, 0x06, 0x67, 0x6a, 0x6e, 0x8a, 0x73,
- 0xb4, 0x74, 0xba, 0x79, 0xd4, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00, 0xe5,
- 0x63, 0x00, 0x6b, 0x04, 0x6c, 0x06, 0x6e, 0x0b, 0x72, 0x57, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x06, 0x40, 0x07, 0x65, 0x79, 0x00, 0xe6, 0x00, 0x00,
- 0x65, 0x02, 0x6c, 0x04, 0x70, 0x18, 0x73, 0x1f, 0x77, 0x39, 0x00, 0x06,
- 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07,
- 0x65, 0x61, 0x63, 0x65, 0x00, 0xe3, 0x62, 0x00, 0x6c, 0x06, 0x70, 0x0e,
- 0x40, 0x07, 0x6f, 0x72, 0x6f, 0x00, 0x40, 0x07, 0x65, 0x65, 0x76, 0x65,
- 0x73, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x63, 0x68,
- 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x6f, 0x04, 0x00, 0x07,
- 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0b, 0xe2, 0x61,
- 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe3,
- 0x61, 0x00, 0x64, 0x18, 0x6f, 0x1d, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6e, 0x04, 0x40, 0x09, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00, 0x40,
- 0x07, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x68, 0x61, 0x6d, 0x00, 0xe4,
- 0x61, 0x00, 0x63, 0x02, 0x65, 0x08, 0x7a, 0x0c, 0x00, 0x07, 0x40, 0x07,
- 0x68, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x6b, 0x79,
- 0x00, 0x00, 0x07, 0xe5, 0x65, 0x00, 0x66, 0x04, 0x6d, 0x1d, 0x6e, 0x28,
- 0x73, 0x2d, 0x40, 0x07, 0x67, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x6d, 0x04,
- 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x63, 0x68, 0x00, 0x00,
- 0x07, 0xe6, 0x6d, 0x00, 0x70, 0x06, 0x73, 0x0c, 0x74, 0x15, 0x76, 0x1b,
- 0x7a, 0x20, 0x40, 0x07, 0x79, 0x6b, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x75,
- 0x73, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x69, 0x75, 0x73, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x6e, 0x79, 0x00, 0xe4, 0x6d, 0x00, 0x6e, 0x06, 0x73, 0x16, 0x79, 0x18,
- 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x07, 0x77, 0x61, 0x6c, 0x64, 0x00, 0x00, 0x07,
- 0x40, 0x06, 0x65, 0x72, 0x65, 0x00, 0xc0, 0x61, 0x1a, 0x37, 0x00, 0x00,
- 0x00, 0xd6, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
- 0x00, 0x0e, 0x01, 0x61, 0x01, 0x00, 0x00, 0x81, 0x01, 0x93, 0x01, 0x99,
- 0x01, 0xa0, 0x01, 0xa7, 0x01, 0x00, 0x00, 0xac, 0x01, 0xb2, 0x01, 0xce,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x01, 0x01,
- 0x02, 0xe7, 0x64, 0x00, 0x6c, 0x34, 0x6d, 0x3d, 0x6e, 0x4b, 0x72, 0x5f,
- 0x74, 0x70, 0x79, 0x88, 0xe2, 0x61, 0x00, 0x65, 0x27, 0xe1, 0x6c, 0x00,
- 0xe4, 0x61, 0x00, 0x63, 0x07, 0x71, 0x0e, 0x75, 0x16, 0x40, 0x07, 0x6a,
- 0x61, 0x72, 0x61, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x61, 0x6c, 0x00, 0x40,
- 0x07, 0x75, 0x69, 0x76, 0x69, 0x72, 0x00, 0x40, 0x07, 0x70, 0x65, 0x00,
- 0x40, 0x07, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x61,
- 0x74, 0x69, 0x72, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x6e, 0x69, 0x61, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x74, 0x07,
- 0x40, 0x07, 0x7a, 0x68, 0x6f, 0x75, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x61,
- 0x6d, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x6e, 0x69,
- 0x00, 0x40, 0x07, 0x69, 0x65, 0x72, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x61, 0x71,
- 0x75, 0x69, 0x6c, 0x00, 0x40, 0x07, 0x63, 0x69, 0x00, 0xe3, 0x6c, 0x00,
- 0x72, 0x05, 0x76, 0x1c, 0x40, 0x07, 0x70, 0x68, 0x00, 0xe2, 0x6e, 0x00,
- 0x72, 0x06, 0x40, 0x09, 0x73, 0x65, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x72,
- 0x61, 0x00, 0x40, 0x07, 0x67, 0x65, 0x6e, 0x68, 0x65, 0x69, 0x6d, 0x00,
- 0xe6, 0x61, 0x00, 0x64, 0x05, 0x6c, 0x09, 0x6e, 0x1c, 0x79, 0x3b, 0x7a,
- 0x41, 0x40, 0x07, 0x6e, 0x61, 0x00, 0x40, 0x00, 0x6f, 0x00, 0xe2, 0x64,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x66, 0x6f, 0x72, 0x64, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x6d, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x14, 0xe2, 0x61,
- 0x00, 0x76, 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09,
- 0x40, 0x07, 0x65, 0x72, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x61, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x72, 0x12, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x6e, 0x77, 0x61, 0x6c, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x04, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x76, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x62, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x74, 0x68, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x66, 0x65, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x74,
- 0x61, 0x00, 0x40, 0x07, 0x6b, 0x68, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x76, 0x00, 0xe3, 0x00, 0x00,
- 0x6f, 0x02, 0x75, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00,
- 0xe3, 0x65, 0x00, 0x68, 0x08, 0x69, 0x0e, 0x40, 0x07, 0x6e, 0x62, 0x65,
- 0x72, 0x67, 0x00, 0x40, 0x07, 0x72, 0x69, 0x65, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x72, 0x65, 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x73, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x07, 0x79, 0x25, 0x40, 0x07, 0x6c, 0x69, 0x6f, 0x72, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x70,
- 0x73, 0x79, 0x00, 0xc1, 0x42, 0x39, 0x77, 0x00, 0x79, 0x00, 0x00, 0x00,
- 0x7d, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x90, 0x00, 0x94, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0xaa, 0x00,
- 0xae, 0x00, 0xb7, 0x00, 0xb9, 0x00, 0xc2, 0x00, 0xd1, 0x00, 0xe2, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x05, 0x9e, 0x09, 0xa0, 0x09,
- 0x00, 0x00, 0xa2, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x0b,
- 0x00, 0x00, 0xb1, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x00,
- 0xf1, 0x0e, 0xf5, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x10,
- 0xd4, 0x10, 0x00, 0x07, 0x40, 0x07, 0x4f, 0x00, 0xe3, 0x44, 0x00, 0x4d,
- 0x02, 0x54, 0x06, 0x00, 0x00, 0x40, 0x00, 0x49, 0x00, 0x40, 0x00, 0x56,
- 0x00, 0x00, 0x07, 0x40, 0x00, 0x53, 0x00, 0xe2, 0x00, 0x00, 0x56, 0x02,
- 0x00, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x4f, 0x02, 0x53, 0x04, 0x00,
- 0x00, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x56, 0x00, 0xe2, 0x00, 0x00,
- 0x56, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x48,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x42, 0x02, 0x54, 0x06,
- 0x00, 0x00, 0x40, 0x07, 0x43, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x4d,
- 0x02, 0x54, 0x06, 0x00, 0x00, 0x40, 0x07, 0x4c, 0x00, 0x40, 0x00, 0x50,
- 0x00, 0x40, 0x07, 0x44, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x64, 0x00, 0x69, 0x00,
- 0x89, 0x00, 0x8d, 0x00, 0x00, 0x00, 0xb3, 0x00, 0xc2, 0x00, 0x36, 0x01,
- 0xdd, 0x01, 0x00, 0x00, 0x76, 0x02, 0x00, 0x00, 0x7e, 0x02, 0x60, 0x03,
- 0x88, 0x03, 0xb6, 0x03, 0xd1, 0x03, 0xf1, 0x03, 0x00, 0x00, 0x28, 0x04,
- 0x6a, 0x04, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x6b, 0x6b, 0x75, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x04, 0x72, 0x08, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69,
- 0x7a, 0x00, 0xe4, 0x61, 0x00, 0x67, 0x04, 0x69, 0x09, 0x75, 0x13, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x69, 0x00, 0x40, 0x07, 0x6f, 0x67,
- 0x72, 0x61, 0x70, 0x68, 0x61, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0xe4, 0x64, 0x00, 0x66, 0x04, 0x70, 0x08, 0x74, 0x0f, 0x40,
- 0x06, 0x61, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x6e,
- 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x09, 0x6e, 0x00, 0xe2, 0x6b, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x61,
- 0x00, 0x40, 0x07, 0x75, 0x79, 0x74, 0x00, 0xe7, 0x00, 0x00, 0x64, 0x02,
- 0x65, 0x08, 0x69, 0x1a, 0x6c, 0x20, 0x6f, 0x56, 0x73, 0x5a, 0x00, 0x06,
- 0x40, 0x07, 0x61, 0x6e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x79,
- 0x09, 0x00, 0x07, 0x40, 0x07, 0x6b, 0x61, 0x6c, 0x61, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x66, 0x61, 0x78, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x6d, 0x15, 0x6f, 0x1b, 0x73, 0x22, 0x00, 0x07, 0x40, 0x07, 0x79,
- 0x00, 0xe2, 0x62, 0x00, 0x65, 0x08, 0x40, 0x07, 0x75, 0x72, 0x74, 0x6f,
- 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x72, 0x6b, 0x00, 0x40, 0x09,
- 0x77, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x61, 0x74, 0x74, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x79, 0x00, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x62, 0x0b, 0x68, 0x11,
- 0x69, 0x17, 0x6c, 0x41, 0x6d, 0x4e, 0x70, 0x7e, 0x73, 0x8f, 0x00, 0x07,
- 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x09, 0x75,
- 0x72, 0x67, 0x00, 0x40, 0x07, 0x75, 0x6e, 0x67, 0x00, 0xe2, 0x6c, 0x00,
- 0x74, 0x20, 0xe3, 0x63, 0x00, 0x6c, 0x05, 0x74, 0x07, 0x40, 0x07, 0x61,
- 0x72, 0x00, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x69, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x74, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0a, 0x6f, 0x1b, 0x75,
- 0x20, 0x40, 0x07, 0x72, 0x73, 0x6b, 0x6a, 0x6f, 0x6c, 0x64, 0x00, 0xe2,
- 0x72, 0x00, 0x74, 0x08, 0x40, 0x07, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x00,
- 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x72,
- 0x61, 0x62, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x07, 0x40, 0x07, 0x68,
- 0x69, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x75,
- 0x6e, 0x00, 0xea, 0x00, 0x00, 0x63, 0x02, 0x64, 0x08, 0x65, 0x13, 0x67,
- 0x17, 0x6b, 0x26, 0x6e, 0x28, 0x6f, 0x3c, 0x73, 0x55, 0x75, 0x6b, 0x00,
- 0x06, 0x40, 0x07, 0x6f, 0x63, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04,
- 0x40, 0x07, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x75,
- 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x75,
- 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x68,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x62, 0x61, 0x6c, 0x00, 0xe2,
- 0x69, 0x00, 0x76, 0x02, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x0b, 0x00, 0x14, 0xe2, 0x6c, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6b,
- 0x00, 0xe2, 0x61, 0x00, 0x6b, 0x02, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x07, 0x73, 0x62, 0x75, 0x72, 0x67, 0x00, 0xeb, 0x61, 0x00, 0x62, 0x05,
- 0x64, 0x0a, 0x67, 0x1d, 0x6c, 0x26, 0x6d, 0x46, 0x6f, 0x4b, 0x70, 0x50,
- 0x72, 0x5b, 0x74, 0x9d, 0x76, 0xbd, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40,
- 0x07, 0x69, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0c, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x72, 0x65, 0x61, 0x76, 0x65, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x04, 0x6f, 0x15, 0x40, 0x07, 0x6e, 0x00, 0xe3, 0x6d, 0x00, 0x71, 0x02,
- 0x79, 0x08, 0x00, 0x07, 0x40, 0x07, 0x75, 0x69, 0x6e, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x77, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6c,
- 0x64, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x07, 0x72, 0x00, 0x00,
- 0x06, 0xe4, 0x65, 0x00, 0x69, 0x05, 0x6f, 0x32, 0x79, 0x37, 0x40, 0x07,
- 0x6c, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x6e, 0x0c, 0x73, 0x13, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x67, 0x74, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6f, 0x08,
- 0x00, 0x07, 0x40, 0x07, 0x75, 0x72, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x64, 0x73, 0x00, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x65, 0x02,
- 0x66, 0x04, 0x6c, 0x0a, 0x6d, 0x10, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x6f, 0x72, 0x64, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x72, 0x64,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0xe5, 0x62, 0x00, 0x69, 0x05, 0x6b, 0x0b,
- 0x73, 0x11, 0x74, 0x16, 0x40, 0x07, 0x72, 0x6f, 0x00, 0x40, 0x07, 0x64,
- 0x69, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x73, 0x00, 0xe4, 0x66, 0x00,
- 0x68, 0x07, 0x73, 0x0e, 0x74, 0x16, 0x40, 0x07, 0x69, 0x65, 0x6c, 0x64,
- 0x00, 0x40, 0x07, 0x61, 0x77, 0x61, 0x79, 0x00, 0x40, 0x07, 0x68, 0x65,
- 0x70, 0x75, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07, 0x72,
- 0x61, 0x73, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x70, 0x00, 0x73, 0x08,
- 0x40, 0x07, 0x74, 0x6d, 0x61, 0x6e, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x64,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x66, 0x66, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x0e, 0x6f, 0x12, 0xe2, 0x6e, 0x00, 0x72, 0x04, 0x40, 0x09,
- 0x61, 0x00, 0x40, 0x07, 0x74, 0x69, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40,
- 0x07, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6b,
- 0x13, 0x74, 0x26, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x69,
- 0x00, 0x73, 0x0c, 0xe1, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x72, 0x6e, 0x65,
- 0x00, 0xe6, 0x00, 0x00, 0x64, 0x02, 0x65, 0x0d, 0x6e, 0x16, 0x73, 0x1b,
- 0x77, 0x1d, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x00, 0x07, 0xe2, 0x6b, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x05,
- 0x40, 0x07, 0x72, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x04, 0x40, 0x07,
- 0x64, 0x00, 0x40, 0x07, 0x74, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x04,
- 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x69, 0x74, 0x74, 0x00, 0xc1, 0x61,
- 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x61, 0x00, 0x9c, 0x00, 0x00, 0x00, 0xb2,
- 0x00, 0xb6, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x3b, 0x01, 0xed, 0x01, 0xf6, 0x01, 0x00, 0x00, 0x5b, 0x02, 0x00,
- 0x00, 0x7b, 0x02, 0xc8, 0x03, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08,
- 0x04, 0x00, 0x00, 0x18, 0x04, 0x2b, 0x04, 0x00, 0x07, 0xe4, 0x64, 0x00,
- 0x72, 0x02, 0x74, 0x07, 0x76, 0x15, 0x00, 0x07, 0x40, 0x07, 0x73, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x0e, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x69, 0x73, 0x69, 0x64, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x72, 0x0d, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0e,
- 0x69, 0x1a, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x06, 0x6d, 0x00, 0xe1, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x64, 0x65, 0x73, 0x00, 0xe3, 0x61,
- 0x00, 0x74, 0x05, 0x75, 0x0a, 0x40, 0x07, 0x74, 0x65, 0x00, 0x40, 0x07,
- 0x6f, 0x72, 0x00, 0x40, 0x07, 0x62, 0x61, 0x00, 0x40, 0x07, 0x70, 0x00,
- 0x40, 0x07, 0x6e, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x72, 0x61, 0x00, 0xe5, 0x64, 0x00, 0x66, 0x19,
- 0x6d, 0x1f, 0x6e, 0x26, 0x73, 0x49, 0xe2, 0x65, 0x00, 0x69, 0x12, 0xe2,
- 0x67, 0x00, 0x6c, 0x06, 0x40, 0x07, 0x67, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x62, 0x65, 0x72, 0x67, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x74, 0x7a,
- 0x00, 0x40, 0x07, 0x6c, 0x69, 0x63, 0x68, 0x00, 0xe4, 0x65, 0x00, 0x6c,
- 0x0c, 0x72, 0x12, 0x7a, 0x18, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x69, 0x6e, 0x00, 0x40,
- 0x07, 0x69, 0x63, 0x68, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6d, 0x08,
- 0x40, 0x07, 0x6e, 0x62, 0x65, 0x72, 0x67, 0x00, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0xe8, 0x65, 0x00, 0x67, 0x10, 0x69, 0x14, 0x6c, 0x2c, 0x6d, 0x76,
- 0x6f, 0x7e, 0x73, 0x84, 0x76, 0x8b, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x00, 0xe2, 0x63, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x70, 0x00, 0x73, 0x07, 0x40, 0x07, 0x6f, 0x6c, 0x69, 0x73, 0x00,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6d, 0x40, 0xe3, 0x6e, 0x00, 0x72, 0x30,
- 0x73, 0x32, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe3, 0x63, 0x00,
- 0x73, 0x02, 0x7a, 0x14, 0x00, 0x07, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x63, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x70, 0x6f, 0x6e, 0x74, 0x00, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x6c, 0x74, 0x7a, 0x00,
- 0x40, 0x07, 0x69, 0x73, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x6b, 0x69,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x07, 0x69, 0x6e, 0x67, 0x77, 0x61, 0x79, 0x00, 0xe6, 0x63, 0x00, 0x64,
- 0x04, 0x6c, 0x26, 0x6e, 0x2b, 0x72, 0x32, 0x73, 0x4a, 0x40, 0x07, 0x68,
- 0x00, 0xe2, 0x65, 0x00, 0x72, 0x07, 0x40, 0x07, 0x72, 0x73, 0x6f, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x0c, 0xe1, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x79, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x11, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6b, 0x08, 0x00,
- 0x07, 0x40, 0x07, 0x74, 0x74, 0x61, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe2,
- 0x6c, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe3, 0x62, 0x00, 0x68, 0x06, 0x70, 0x0f, 0x40, 0x07, 0x75, 0x72,
- 0x6e, 0x00, 0x40, 0x07, 0x61, 0x65, 0x73, 0x74, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x6c, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, 0x00, 0xfd, 0x61, 0x00,
- 0x00, 0x62, 0x21, 0x00, 0x63, 0x30, 0x00, 0x64, 0x4d, 0x00, 0x65, 0x52,
- 0x00, 0x69, 0x61, 0x00, 0x6d, 0x69, 0x00, 0x6e, 0xa6, 0x00, 0x6f, 0xae,
- 0x00, 0x72, 0xbe, 0x00, 0x73, 0xd9, 0x00, 0x74, 0xf6, 0x00, 0x7a, 0x15,
- 0x01, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6b, 0x14, 0x00, 0x07, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07,
- 0x74, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x05, 0x40, 0x07, 0x72, 0x74, 0x00, 0x40, 0x07, 0x72, 0x74,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x6e, 0x65, 0x75, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04,
- 0x40, 0x00, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2,
- 0x66, 0x00, 0x72, 0x06, 0x40, 0x06, 0x6f, 0x72, 0x64, 0x00, 0x40, 0x07,
- 0x6f, 0x00, 0x40, 0x07, 0x62, 0x65, 0x72, 0x74, 0x6f, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x12, 0x69, 0x16, 0x6f, 0x2c, 0xe2, 0x6e, 0x00, 0x70, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x68, 0x72, 0x6f, 0x64, 0x69, 0x74, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x05, 0x40, 0x07,
- 0x69, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x67, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x00, 0x40,
- 0x07, 0x61, 0x6e, 0x64, 0x65, 0x7a, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x75, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x00, 0x15, 0x40, 0x07, 0x72, 0x61,
- 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x6b, 0x00, 0x40, 0x07,
- 0x67, 0x00, 0xe3, 0x63, 0x00, 0x65, 0x06, 0x68, 0x0a, 0x40, 0x07, 0x68,
- 0x65, 0x6c, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6c,
- 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x66, 0x00, 0x7a, 0x0b,
- 0x40, 0x07, 0x6f, 0x72, 0x64, 0x73, 0x68, 0x69, 0x72, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x70, 0x72, 0x75, 0x6e,
- 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x09, 0x40, 0x07, 0x67, 0x6f, 0x76,
- 0x69, 0x6e, 0x61, 0x00, 0x00, 0x07, 0xe5, 0x68, 0x00, 0x69, 0x06, 0x70,
- 0x0b, 0x73, 0x12, 0x74, 0x22, 0x40, 0x07, 0x76, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x65, 0x72, 0x75, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x69, 0x65, 0x00, 0xe2, 0x69,
- 0x00, 0x6c, 0x05, 0x40, 0x07, 0x74, 0x74, 0x00, 0x40, 0x07, 0x65, 0x74,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x77, 0x08, 0x40, 0x07, 0x72, 0x64, 0x61,
- 0x68, 0x6c, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xe2, 0x62, 0x00,
- 0x65, 0x08, 0x40, 0x07, 0x6f, 0x6c, 0x6c, 0x61, 0x68, 0x00, 0x40, 0x07,
- 0x6b, 0x69, 0x61, 0x68, 0x00, 0x00, 0x07, 0x00, 0x07, 0xfc, 0x61, 0x00,
- 0x00, 0x62, 0x12, 0x00, 0x63, 0x2a, 0x00, 0x65, 0x3f, 0x00, 0x67, 0x49,
- 0x00, 0x6c, 0x88, 0x00, 0x6d, 0xe2, 0x00, 0x6e, 0x06, 0x01, 0x70, 0x5a,
- 0x01, 0x72, 0x83, 0x01, 0x73, 0xa6, 0x01, 0x74, 0xc2, 0x01, 0xe2, 0x6c,
- 0x00, 0x77, 0x06, 0x40, 0x07, 0x65, 0x61, 0x68, 0x00, 0x40, 0x07, 0x61,
- 0x74, 0x68, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe1, 0x6b, 0x00, 0xe3, 0x6d, 0x00, 0x6f, 0x05,
- 0x73, 0x09, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6b, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x6f, 0x6e, 0x79, 0x6d, 0x75, 0x73, 0x00, 0xe3,
- 0x61, 0x00, 0x67, 0x0b, 0x68, 0x11, 0x40, 0x00, 0x73, 0x68, 0x69, 0x6f,
- 0x73, 0x61, 0x6b, 0x61, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x73, 0x00, 0xe3,
- 0x42, 0x00, 0x6c, 0x06, 0x6e, 0x1a, 0x40, 0x07, 0x65, 0x61, 0x6d, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00,
- 0x73, 0x04, 0x40, 0x06, 0x72, 0x00, 0x00, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe6, 0x61, 0x00, 0x62, 0x0e, 0x64, 0x14, 0x66, 0x23, 0x6c,
- 0x2a, 0x74, 0x48, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40,
- 0x07, 0x6f, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x62, 0x72, 0x61, 0x6e,
- 0x64, 0x00, 0x40, 0x07, 0x69, 0x67, 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x07, 0x73, 0x0b, 0x00, 0x07, 0x40, 0x07, 0x72, 0x79,
- 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x62, 0x6f, 0x72, 0x6f, 0x75,
- 0x67, 0x68, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6d,
- 0x19, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x73, 0x04, 0x00, 0x06, 0x00, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x65, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x64,
- 0x07, 0x65, 0x42, 0x74, 0x46, 0x40, 0x07, 0x79, 0x61, 0x6e, 0x61, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x12, 0x75, 0x14, 0xe2, 0x6d, 0x00, 0x6e, 0x06,
- 0x40, 0x07, 0x69, 0x74, 0x68, 0x00, 0x40, 0x07, 0x62, 0x75, 0x72, 0x67,
- 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x06,
- 0x40, 0x06, 0x73, 0x6d, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x70, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x08, 0x40, 0x07, 0x72, 0x63, 0x68, 0x75, 0x73, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x63,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6d, 0x00, 0xe3, 0x62,
- 0x00, 0x68, 0x06, 0x73, 0x0c, 0x40, 0x07, 0x75, 0x6d, 0x69, 0x00, 0x40,
- 0x07, 0x69, 0x74, 0x6f, 0x00, 0x40, 0x07, 0x68, 0x69, 0x6d, 0x61, 0x00,
- 0xe2, 0x70, 0x00, 0x73, 0x15, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x63, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x07, 0x6c,
- 0x61, 0x00, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x63, 0x06, 0x6c, 0x0e, 0x74,
- 0x13, 0x40, 0x07, 0x63, 0x68, 0x69, 0x00, 0x40, 0x07, 0x68, 0x63, 0x6f,
- 0x63, 0x6b, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x06, 0x69, 0x74,
- 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x67, 0x00, 0xc1, 0x62, 0x18, 0x35,
- 0x00, 0x37, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x00, 0x00, 0x69, 0x00, 0x87,
- 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0xe5, 0x00, 0x96,
- 0x01, 0xa7, 0x01, 0xff, 0x01, 0x30, 0x02, 0x00, 0x00, 0x53, 0x02, 0xad,
- 0x02, 0xb8, 0x02, 0xd4, 0x02, 0x05, 0x03, 0x0e, 0x03, 0x00, 0x00, 0x32,
- 0x03, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x62, 0x05, 0x40, 0x07, 0x72, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6b, 0x6e, 0x65, 0x79, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65,
- 0x00, 0x6b, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe2, 0x66, 0x00, 0x73, 0x10, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x6d, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x74, 0x61, 0x64, 0x74, 0x65, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x77, 0x0c, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x74, 0x68, 0x00, 0x40, 0x07, 0x61, 0x72, 0x74, 0x73, 0x00, 0xe3,
- 0x65, 0x00, 0x68, 0x22, 0x6f, 0x27, 0xe1, 0x6e, 0x00, 0xe3, 0x6c, 0x00,
- 0x73, 0x06, 0x7a, 0x0f, 0x40, 0x07, 0x6f, 0x68, 0x65, 0x00, 0x40, 0x07,
- 0x74, 0x61, 0x75, 0x66, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x6c,
- 0x65, 0x72, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x6b,
- 0x61, 0x6d, 0x00, 0xe2, 0x6b, 0x00, 0x75, 0x07, 0x40, 0x07, 0x61, 0x69,
- 0x64, 0x6f, 0x00, 0x40, 0x07, 0x73, 0x61, 0x69, 0x00, 0xe9, 0x62, 0x00,
- 0x63, 0x06, 0x64, 0x0c, 0x69, 0x18, 0x6c, 0x28, 0x6d, 0x6d, 0x6f, 0x7a,
- 0x73, 0x8d, 0x74, 0x9c, 0x40, 0x07, 0x65, 0x69, 0x6e, 0x00, 0x40, 0x07,
- 0x6f, 0x6d, 0x62, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe2, 0x64, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x61,
- 0x79, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x61, 0x00, 0x65,
- 0x11, 0x69, 0x1e, 0x6f, 0x27, 0x79, 0x2d, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x23, 0x40, 0x07, 0x72, 0x00,
- 0xe2, 0x72, 0x00, 0x79, 0x06, 0x40, 0x07, 0x69, 0x74, 0x68, 0x00, 0x00,
- 0x07, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x77, 0x61, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x06, 0x40, 0x07, 0x75, 0x73, 0x74, 0x00, 0x40, 0x07, 0x6e, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40,
- 0x06, 0x69, 0x6e, 0x00, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x63, 0x00, 0xe7,
- 0x00, 0x00, 0x64, 0x02, 0x65, 0x18, 0x67, 0x2a, 0x69, 0x2c, 0x6f, 0x32,
- 0x73, 0x44, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x07, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x09,
- 0x00, 0x07, 0xe2, 0x63, 0x00, 0x79, 0x06, 0x40, 0x07, 0x6b, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x77, 0x65, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x61, 0x72, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x06, 0x40, 0x07, 0x75,
- 0x6c, 0x75, 0x00, 0x40, 0x00, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07,
- 0x68, 0x75, 0x00, 0xe6, 0x64, 0x00, 0x6b, 0x02, 0x70, 0x0e, 0x73, 0x13,
- 0x74, 0x19, 0x76, 0x1f, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x16, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x69, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x73, 0x00, 0x40,
- 0x09, 0x65, 0x72, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x0d, 0x6b, 0x0f, 0x70,
- 0x15, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6c,
- 0x6c, 0x00, 0x00, 0x06, 0x40, 0x07, 0x69, 0x6e, 0x73, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0xe6, 0x61, 0x00, 0x6d, 0x15, 0x6e, 0x22, 0x6f, 0x35,
- 0x74, 0x3c, 0x75, 0x49, 0xe2, 0x63, 0x00, 0x74, 0x0b, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x6f,
- 0x00, 0xe2, 0x65, 0x00, 0x75, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07,
- 0x7a, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x65, 0x0a, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x00, 0x07, 0x40, 0x07, 0x77,
- 0x69, 0x74, 0x7a, 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x61, 0x00, 0x00, 0x06, 0xe3, 0x6d, 0x00, 0x70,
- 0x06, 0x74, 0x0d, 0x40, 0x07, 0x61, 0x69, 0x6c, 0x00, 0x40, 0x07, 0x6f,
- 0x69, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x6f, 0x74, 0x00,
- 0xe4, 0x64, 0x00, 0x67, 0x06, 0x73, 0x0d, 0x79, 0x20, 0x40, 0x07, 0x69,
- 0x6e, 0x69, 0x00, 0x40, 0x07, 0x68, 0x74, 0x6f, 0x6e, 0x00, 0xe3, 0x65,
- 0x00, 0x6d, 0x02, 0x74, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x6e, 0x68, 0x6e, 0x6d,
- 0x00, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x05, 0x72, 0x18, 0x40, 0x07, 0x72, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6c, 0x02, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x00, 0x61, 0x68, 0x00, 0x40, 0x07,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x68, 0x67, 0x61, 0x72, 0x00,
- 0x40, 0x00, 0x73, 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0x3a, 0x00, 0x59,
- 0x00, 0x5d, 0x00, 0x72, 0x00, 0x7e, 0x00, 0x8d, 0x00, 0x00, 0x00, 0xb0,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0xc9, 0x00, 0xf8, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x01, 0x5a, 0x01, 0x7f, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x01, 0x9c, 0x01, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe2, 0x62, 0x00, 0x65, 0x0e, 0xe2, 0x61, 0x00, 0x6c, 0x05,
- 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6b,
- 0x00, 0xe2, 0x64, 0x00, 0x73, 0x0b, 0x40, 0x00, 0x65, 0x72, 0x73, 0x66,
- 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x72,
- 0x00, 0x79, 0x05, 0x40, 0x07, 0x74, 0x61, 0x00, 0x00, 0x07, 0xe1, 0x66,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0xe4, 0x67, 0x00, 0x68, 0x06, 0x6f, 0x11, 0x75, 0x13, 0x40, 0x07,
- 0x69, 0x6e, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40,
- 0x07, 0x73, 0x00, 0x00, 0x07, 0x40, 0x09, 0x65, 0x6e, 0x6f, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x7a, 0x69, 0x6c,
- 0x6f, 0x70, 0x6f, 0x74, 0x63, 0x68, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x6c,
- 0x00, 0xe5, 0x62, 0x00, 0x65, 0x11, 0x6d, 0x13, 0x70, 0x18, 0x76, 0x1f,
- 0xe2, 0x65, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x72, 0x74, 0x6f, 0x00, 0x40,
- 0x07, 0x6c, 0x64, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0x40, 0x06, 0x68, 0x72, 0x65, 0x79, 0x00, 0x40, 0x07, 0x65, 0x65, 0x00,
- 0xe4, 0x00, 0x00, 0x67, 0x02, 0x73, 0x18, 0x74, 0x1f, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x70,
- 0x65, 0x6c, 0x6c, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c,
- 0x0e, 0x73, 0x13, 0x00, 0x0e, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07,
- 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0xe3, 0x6c, 0x00, 0x6f, 0x05, 0x73,
- 0x09, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x74, 0x19, 0x00, 0x07, 0xe2,
- 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x69, 0x00, 0x72, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x74, 0x65, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x74, 0x09, 0x75, 0x0e, 0x40, 0x07,
- 0x68, 0x69, 0x6e, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x65, 0x79, 0x00, 0x40, 0x07, 0x67, 0x65,
- 0x6e, 0x73, 0x00, 0xe5, 0x61, 0x00, 0x64, 0x06, 0x6d, 0x1d, 0x70, 0x22,
- 0x75, 0x2a, 0x40, 0x07, 0x64, 0x65, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x72,
- 0x0e, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x62,
- 0x61, 0x64, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00,
- 0x40, 0x07, 0x65, 0x72, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x64,
- 0x61, 0x69, 0x00, 0x00, 0x07, 0xc1, 0x27, 0x54, 0xad, 0x00, 0xaf, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xca, 0x00, 0xd9, 0x00, 0xe2, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00,
- 0xfc, 0x00, 0xfe, 0x00, 0x2c, 0x01, 0x3f, 0x01, 0x43, 0x01, 0x57, 0x01,
- 0x59, 0x01, 0x66, 0x01, 0x79, 0x01, 0x7b, 0x01, 0x7f, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0xa9, 0x01, 0xdf, 0x01,
- 0x13, 0x02, 0x31, 0x02, 0x00, 0x00, 0x38, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x5d, 0x02, 0x68, 0x02, 0x77, 0x02, 0xbf, 0x02, 0xf3, 0x02, 0xb4, 0x04,
- 0xdf, 0x04, 0xf4, 0x04, 0x0e, 0x05, 0xd0, 0x05, 0xe7, 0x06, 0x00, 0x00,
- 0x3c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x74, 0x07, 0x79, 0x07, 0x00, 0x07,
- 0xe4, 0x64, 0x00, 0x6c, 0x02, 0x6d, 0x06, 0x76, 0x08, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x65, 0x00, 0x00, 0x00, 0x40,
- 0x07, 0x4d, 0x00, 0xe3, 0x42, 0x00, 0x43, 0x04, 0x55, 0x06, 0x40, 0x06,
- 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x45, 0x02, 0x00,
- 0x06, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x44, 0x02, 0x45, 0x04, 0x54, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x45, 0x00, 0x40, 0x07, 0x46, 0x00,
- 0x40, 0x07, 0x45, 0x41, 0x00, 0x00, 0x00, 0xe5, 0x44, 0x00, 0x46, 0x15,
- 0x48, 0x17, 0x4e, 0x1b, 0x4f, 0x21, 0xe1, 0x62, 0x00, 0xe3, 0x00, 0x00,
- 0x50, 0x02, 0x54, 0x07, 0x00, 0x07, 0x40, 0x07, 0x72, 0x6f, 0x00, 0x40,
- 0x07, 0x56, 0x00, 0x00, 0x07, 0x40, 0x00, 0x4f, 0x00, 0x40, 0x00, 0x53,
- 0x48, 0x4f, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x47, 0x02, 0x52, 0x04,
- 0x53, 0x08, 0x00, 0x00, 0x00, 0x07, 0x40, 0x00, 0x49, 0x00, 0x00, 0x00,
- 0x40, 0x07, 0x55, 0x00, 0xe3, 0x00, 0x00, 0x41, 0x02, 0x4f, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x07, 0xe3, 0x41, 0x00, 0x43, 0x02, 0x53, 0x04, 0x00, 0x06, 0x00,
- 0x00, 0x00, 0x07, 0xe4, 0x42, 0x00, 0x4f, 0x04, 0x50, 0x06, 0x53, 0x08,
- 0x40, 0x00, 0x4e, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x44, 0x00, 0xe2, 0x00, 0x00, 0x46, 0x02, 0x00, 0x06, 0x00,
- 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x67, 0x09, 0x6e, 0x0d, 0x70, 0x0f,
- 0x00, 0x00, 0x40, 0x07, 0x63, 0x6f, 0x63, 0x61, 0x00, 0x40, 0x07, 0x6f,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x74, 0x75, 0x73, 0x00, 0xe6, 0x61,
- 0x00, 0x65, 0x06, 0x69, 0x18, 0x6c, 0x1d, 0x6f, 0x22, 0x73, 0x24, 0x40,
- 0x07, 0x64, 0x61, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x7a, 0x61, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0e, 0xe2, 0x68, 0x00,
- 0x72, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x13,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x06, 0x00, 0x06, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x07, 0x79, 0x61, 0x73, 0x75, 0x00, 0xe3, 0x6e, 0x00,
- 0x6f, 0x13, 0x75, 0x17, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x05,
- 0x40, 0x07, 0x69, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x73, 0x73, 0x75, 0x00, 0x40, 0x07,
- 0x73, 0x73, 0x65, 0x6c, 0x6d, 0x65, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x68, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x61, 0x74, 0x6f, 0x6e, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x02, 0x69, 0x07, 0x6c, 0x0c, 0x79, 0x35, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x61, 0x64, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x75, 0x19, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x07, 0x6d, 0x69, 0x6e,
- 0x61, 0x74, 0x69, 0x00, 0x40, 0x07, 0x75, 0x73, 0x68, 0x69, 0x6e, 0x00,
- 0xe5, 0x65, 0x00, 0x68, 0x06, 0x6d, 0x0d, 0x6f, 0x14, 0x75, 0x25, 0x40,
- 0x07, 0x6c, 0x64, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x65, 0x70, 0x00,
- 0x40, 0x00, 0x75, 0x6e, 0x6f, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x06,
- 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63,
- 0x04, 0x00, 0x64, 0x21, 0x00, 0x65, 0xb2, 0x00, 0x66, 0xbb, 0x00, 0x67,
- 0xc5, 0x00, 0x6e, 0x04, 0x01, 0x6f, 0x18, 0x01, 0x71, 0x1d, 0x01, 0x73,
- 0x28, 0x01, 0x74, 0x44, 0x01, 0x75, 0x80, 0x01, 0x76, 0x91, 0x01, 0x00,
- 0x07, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x68, 0x04, 0x6f, 0x09,
- 0x00, 0x00, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72,
- 0x70, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x64, 0x00, 0xe7, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x0d, 0x6f, 0x43, 0x72, 0x78, 0x75, 0x7c, 0x79, 0x80, 0x00,
- 0x00, 0x40, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x27, 0x72, 0x2b, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x14, 0x00, 0x09, 0xe3,
- 0x00, 0x00, 0x6e, 0x02, 0x70, 0x04, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07,
- 0x6f, 0x6c, 0x69, 0x73, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x15, 0x72,
- 0x2a, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0x40, 0x07, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x73, 0x00,
- 0x7a, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x74, 0x72, 0x69,
- 0x65, 0x76, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x1d, 0x72, 0x25, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x43, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x6e,
- 0x65, 0x63, 0x74, 0x00, 0x40, 0x00, 0x65, 0x77, 0x6f, 0x6f, 0x64, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x08, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x07,
- 0x40, 0x07, 0x63, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x62, 0x72, 0x75,
- 0x63, 0x6b, 0x00, 0x40, 0x07, 0x6e, 0x75, 0x00, 0x40, 0x07, 0x75, 0x69,
- 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0xe2, 0x67, 0x00, 0x6d, 0x06, 0x40, 0x07,
- 0x72, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x74, 0x69, 0x63, 0x00, 0xe2,
- 0x65, 0x00, 0x6c, 0x35, 0xe2, 0x6c, 0x00, 0x72, 0x0c, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x74, 0x00, 0xe3, 0x50, 0x00,
- 0x6e, 0x05, 0x70, 0x18, 0x40, 0x07, 0x72, 0x6f, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x0a, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x65, 0x00,
- 0x40, 0x06, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0xe2,
- 0x69, 0x00, 0x6b, 0x04, 0x40, 0x09, 0x74, 0x00, 0x40, 0x07, 0x74, 0x69,
- 0x74, 0x75, 0x74, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x6e, 0x02, 0x77, 0x18, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40,
- 0x07, 0x73, 0x63, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x04, 0x40, 0x09,
- 0x6e, 0x00, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x06, 0x00, 0x09, 0xe2, 0x68, 0x00, 0x73, 0x09, 0x40, 0x07, 0x69,
- 0x67, 0x65, 0x6e, 0x69, 0x61, 0x00, 0x40, 0x00, 0x77, 0x69, 0x63, 0x68,
- 0x00, 0xe3, 0x61, 0x00, 0x62, 0x07, 0x75, 0x0c, 0x40, 0x07, 0x6c, 0x75,
- 0x69, 0x74, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x69, 0x74,
- 0x6f, 0x73, 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x65, 0x20, 0x69, 0x2f,
- 0x6b, 0x62, 0x6d, 0x69, 0x6f, 0x6d, 0x72, 0x84, 0x74, 0x8d, 0x76, 0x93,
- 0x77, 0xa6, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x71, 0x0e, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x06, 0x61, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x6c,
- 0x00, 0x6e, 0x06, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x0e, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x74, 0x73, 0x6b, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0xe1, 0x71, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40, 0x06, 0x6e, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x77, 0x61, 0x64, 0x64, 0x79, 0x00, 0x40,
- 0x07, 0x69, 0x73, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x67, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x6e, 0x00, 0xed, 0x61, 0x00, 0x63, 0x26, 0x66, 0x2e,
- 0x68, 0x35, 0x69, 0x55, 0x6c, 0x67, 0x6d, 0xa6, 0x6f, 0xb6, 0x70, 0xbc,
- 0x72, 0xc2, 0x73, 0xdd, 0x74, 0xef, 0x75, 0xf7, 0xe3, 0x61, 0x00, 0x62,
- 0x04, 0x69, 0x1a, 0x40, 0x07, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x68, 0x00, 0x40, 0x07,
- 0x61, 0x72, 0x69, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x61, 0x68, 0x61, 0x6e,
- 0x00, 0xe4, 0x65, 0x00, 0x69, 0x08, 0x6d, 0x0c, 0x74, 0x12, 0x40, 0x07,
- 0x72, 0x77, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07,
- 0x61, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0xe3, 0x61, 0x00,
- 0x64, 0x04, 0x73, 0x09, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x72, 0x6f,
- 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x08, 0x6f, 0x18, 0x00, 0x09, 0x40, 0x07, 0x62, 0x61,
- 0x64, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x07, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00,
- 0x63, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07,
- 0x6c, 0x64, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40, 0x07, 0x65,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x62,
- 0x75, 0x6c, 0x00, 0x40, 0x07, 0x7a, 0x75, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x68, 0x38, 0x6f, 0x4a, 0x00, 0x00, 0xe3, 0x69, 0x00, 0x6c, 0x05,
- 0x73, 0x2a, 0x40, 0x07, 0x70, 0x75, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x79, 0x1c, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x07, 0x00, 0x06, 0x40,
- 0x00, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x63, 0x61,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe4, 0x61, 0x00,
- 0x65, 0x13, 0x6f, 0x17, 0x79, 0x2d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x65,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40, 0x00,
- 0x72, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x61, 0x6e,
- 0x00, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x72, 0x00, 0xe5, 0x61,
- 0x00, 0x68, 0x19, 0x6d, 0x20, 0x6f, 0x25, 0x76, 0x29, 0xe2, 0x61, 0x00,
- 0x6e, 0x04, 0x40, 0x07, 0x6b, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x67, 0x00,
- 0x6d, 0x04, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07,
- 0x65, 0x76, 0x73, 0x6b, 0x00, 0x40, 0x07, 0x69, 0x72, 0x00, 0x40, 0x07,
- 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x74, 0x69, 0x61, 0x00, 0xfd, 0x00,
- 0x00, 0x00, 0x43, 0x02, 0x00, 0x44, 0x06, 0x00, 0x46, 0x08, 0x00, 0x50,
- 0x0c, 0x00, 0x56, 0x17, 0x00, 0x61, 0x19, 0x00, 0x65, 0xd0, 0x02, 0x69,
- 0xc0, 0x04, 0x6f, 0x20, 0x05, 0x70, 0x28, 0x07, 0x72, 0x2c, 0x07, 0x75,
- 0x2e, 0x07, 0x00, 0x20, 0x40, 0x00, 0x53, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x4b, 0x00, 0xe2, 0x00, 0x00, 0x45, 0x02, 0x00, 0x00, 0x40, 0x00, 0x47,
- 0x00, 0x00, 0x00, 0xfe, 0x63, 0x00, 0x00, 0x67, 0x98, 0x00, 0x68, 0xb1,
- 0x00, 0x69, 0xb9, 0x00, 0x6b, 0xd5, 0x00, 0x6d, 0xe2, 0x00, 0x6e, 0x2a,
- 0x01, 0x70, 0xba, 0x01, 0x72, 0xe0, 0x01, 0x73, 0x0e, 0x02, 0x74, 0x24,
- 0x02, 0x76, 0x2a, 0x02, 0x78, 0x4b, 0x02, 0x79, 0x53, 0x02, 0xe5, 0x6b,
- 0x00, 0x6c, 0x33, 0x6f, 0x38, 0x71, 0x65, 0x75, 0x87, 0xe5, 0x00, 0x00,
- 0x69, 0x02, 0x6c, 0x06, 0x73, 0x0b, 0x79, 0x26, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x07, 0x79, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x76, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x79, 0x6e, 0x00, 0xe1, 0x62, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x07, 0x73, 0x16, 0x00, 0x06, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07,
- 0x72, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x0e, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x7a, 0x7a, 0x69, 0x00, 0xe3, 0x67, 0x00, 0x69, 0x05, 0x75,
- 0x0d, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x67,
- 0x69, 0x72, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x04, 0x70, 0x10, 0x40, 0x07,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x6d, 0x00, 0x40, 0x07, 0x75, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06,
- 0x40, 0x07, 0x72, 0x74, 0x61, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x65,
- 0x20, 0x69, 0x38, 0xe4, 0x61, 0x00, 0x69, 0x04, 0x6c, 0x13, 0x72, 0x15,
- 0x40, 0x07, 0x6c, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x00, 0x07, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x6c, 0x02, 0x73, 0x04, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x77, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe8, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x0e, 0x69, 0x2e, 0x6a, 0x4e, 0x6e, 0x56, 0x73, 0x61, 0x75,
- 0x73, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x74, 0x0e, 0x00, 0x07,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe4,
- 0x63, 0x00, 0x65, 0x04, 0x6e, 0x06, 0x73, 0x0a, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x72, 0x79, 0x00, 0x40, 0x07, 0x61, 0x77, 0x65,
- 0x65, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x73,
- 0x05, 0x40, 0x06, 0x72, 0x79, 0x00, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x6f, 0x11, 0x75, 0x18, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x09, 0x73, 0x65, 0x00, 0x40, 0x07,
- 0x6e, 0x69, 0x63, 0x61, 0x00, 0x40, 0x07, 0x72, 0x61, 0x00, 0xe4, 0x65,
- 0x00, 0x6c, 0x04, 0x72, 0x0c, 0x76, 0x20, 0x40, 0x07, 0x64, 0x00, 0x40,
- 0x07, 0x73, 0x62, 0x65, 0x72, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x0b,
- 0xe2, 0x64, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x00, 0x40,
- 0x07, 0x64, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0xe3, 0x6d, 0x00, 0x6f,
- 0x06, 0x70, 0x0a, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6b, 0x61, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x17, 0xe3, 0x00, 0x00, 0x53, 0x02, 0x6e, 0x0a,
- 0x00, 0x06, 0x40, 0x07, 0x63, 0x72, 0x69, 0x70, 0x74, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61,
- 0x72, 0x74, 0x65, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x63, 0x16,
- 0x6e, 0x25, 0x73, 0x29, 0x00, 0x07, 0xe2, 0x70, 0x00, 0x77, 0x06, 0x40,
- 0x07, 0x75, 0x72, 0x61, 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x65, 0x6e,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xfe, 0x61, 0x00, 0x00, 0x64, 0x3b, 0x00, 0x65, 0x44, 0x00,
- 0x66, 0x50, 0x00, 0x68, 0x89, 0x00, 0x6b, 0x9f, 0x00, 0x6c, 0xa5, 0x00,
- 0x6e, 0xac, 0x00, 0x70, 0xea, 0x00, 0x72, 0xf2, 0x00, 0x73, 0x6c, 0x01,
- 0x74, 0x92, 0x01, 0x77, 0x98, 0x01, 0x7a, 0xbe, 0x01, 0xe1, 0x6e, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x08, 0x6e, 0x13, 0x00, 0x07, 0x40,
- 0x07, 0x74, 0x74, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x70, 0x00, 0x76, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x73, 0x00, 0xe1, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x72, 0x24, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x73,
- 0x04, 0x79, 0x16, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x07, 0x79, 0x00,
- 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe2, 0x73, 0x00, 0x76, 0x09, 0x40, 0x07,
- 0x68, 0x61, 0x70, 0x68, 0x61, 0x74, 0x00, 0x40, 0x07, 0x61, 0x68, 0x00,
- 0x40, 0x07, 0x79, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x6f, 0x66, 0x74,
- 0x00, 0xe4, 0x69, 0x00, 0x6b, 0x06, 0x6e, 0x0c, 0x73, 0x30, 0x40, 0x07,
- 0x66, 0x65, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x73, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x79, 0x19, 0x00, 0x07, 0x40, 0x07, 0x72,
- 0x00, 0xe3, 0x65, 0x00, 0x66, 0x02, 0x6e, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x67, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x74, 0x68, 0x61, 0x68, 0x00, 0xe8,
- 0x61, 0x00, 0x65, 0x05, 0x69, 0x1e, 0x6d, 0x2a, 0x6f, 0x31, 0x72, 0x46,
- 0x73, 0x5c, 0x75, 0x61, 0x40, 0x07, 0x6c, 0x64, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x63, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x6f, 0x00, 0x40, 0x07,
- 0x61, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x62, 0x00, 0x6c, 0x06, 0x6d, 0x0a,
- 0x40, 0x07, 0x6f, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x02, 0x79, 0x0d, 0x00, 0x07, 0xe2,
- 0x64, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x00, 0x00, 0x07,
- 0x40, 0x09, 0x65, 0x79, 0x00, 0x40, 0x07, 0x73, 0x61, 0x6c, 0x65, 0x6d,
- 0x00, 0xe2, 0x73, 0x00, 0x75, 0x16, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x04, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x61, 0x00, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x73, 0x04, 0x40, 0x09, 0x74,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x77, 0x61, 0x79, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x14, 0x72, 0x19, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x73,
- 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x09,
- 0x73, 0x00, 0x40, 0x24, 0x73, 0x68, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x06, 0x65, 0x62, 0x65, 0x6c, 0x00, 0xe6, 0x61, 0x00, 0x64, 0x05, 0x6c,
- 0x0a, 0x6d, 0x1f, 0x6e, 0x39, 0x76, 0x4d, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x64, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x08, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x65, 0x7a, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x79, 0x04, 0x40, 0x07, 0x68, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x72, 0x6f, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39,
- 0x00, 0x58, 0x00, 0x61, 0x00, 0x7f, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x9c,
- 0x00, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x01, 0x00,
- 0x00, 0x1c, 0x01, 0x56, 0x01, 0x5c, 0x01, 0x00, 0x00, 0x62, 0x01, 0x7d,
- 0x01, 0x00, 0x00, 0xdb, 0x01, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xec,
- 0x01, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x71, 0x14, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x69, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x65, 0x06,
- 0x6b, 0x0c, 0x40, 0x07, 0x73, 0x74, 0x61, 0x00, 0x40, 0x07, 0x6c, 0x79,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x79,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x79, 0x04,
- 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6a, 0x61, 0x6b, 0x61,
- 0x72, 0x74, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x21, 0xe1, 0x6e, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x00, 0x07,
- 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x75, 0x72, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x15, 0x6e, 0x19, 0x73, 0x24, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x74, 0x06,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x73, 0x05, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x24, 0x69, 0x28, 0x73,
- 0x2a, 0x00, 0x07, 0xe3, 0x68, 0x00, 0x73, 0x09, 0x74, 0x0b, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x68, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x6d, 0x6c, 0x61, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x6e, 0x00,
- 0xe2, 0x64, 0x00, 0x67, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x3b, 0x69, 0x46, 0x75, 0x51,
- 0xe3, 0x00, 0x00, 0x66, 0x02, 0x70, 0x12, 0x00, 0x07, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x61,
- 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x75,
- 0x12, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x68, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6e,
- 0x10, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x00, 0x07, 0xfb, 0x61, 0x00, 0x00, 0x62, 0x1a, 0x00, 0x64,
- 0x1f, 0x00, 0x67, 0x6f, 0x00, 0x6c, 0x79, 0x00, 0x6e, 0xca, 0x00, 0x70,
- 0x0a, 0x01, 0x72, 0x11, 0x01, 0x73, 0x21, 0x01, 0x74, 0x40, 0x01, 0x76,
- 0x47, 0x01, 0xe2, 0x6e, 0x00, 0x72, 0x10, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x74, 0x61, 0x00, 0x40,
- 0x07, 0x65, 0x7a, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x00, 0xe7, 0x61, 0x00,
- 0x64, 0x25, 0x65, 0x27, 0x67, 0x30, 0x69, 0x35, 0x73, 0x3a, 0x79, 0x3f,
- 0xe4, 0x65, 0x00, 0x68, 0x04, 0x69, 0x06, 0x73, 0x1a, 0x40, 0x00, 0x6f,
- 0x00, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x6d, 0x00, 0x00,
- 0x09, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0x40, 0x07, 0x74, 0x68, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x67, 0x65, 0x72, 0x6e, 0x61,
- 0x75, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x3d,
- 0x79, 0x44, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x16, 0x6f, 0x28, 0x75, 0x2a, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6e, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x69, 0x61, 0x72, 0x64, 0x00, 0x00, 0x06,
- 0xe6, 0x00, 0x00, 0x65, 0x02, 0x67, 0x0d, 0x69, 0x21, 0x6b, 0x2c, 0x6f,
- 0x31, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x07,
- 0x75, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x69, 0x08, 0x00, 0x07, 0x40,
- 0x07, 0x72, 0x61, 0x75, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x74, 0x65, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x07, 0x40, 0x07, 0x73, 0x73, 0x69, 0x63, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00,
- 0x6e, 0x04, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x6c, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x61, 0x6c, 0x00,
- 0xc1, 0x42, 0x38, 0x75, 0x00, 0x77, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x7b, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x87,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x8d, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00, 0x85, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x05, 0xee,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x07, 0x01, 0x08, 0x07, 0x08, 0x97,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0xad, 0x09, 0xcf, 0x0a, 0x00, 0x00, 0xd9,
- 0x0a, 0x00, 0x00, 0x8f, 0x0b, 0x00, 0x00, 0xb1, 0x0b, 0x00, 0x25, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x07, 0x43, 0x00, 0x40, 0x07, 0x42, 0x00, 0x40,
- 0x00, 0x41, 0x00, 0x40, 0x07, 0x4b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0x61, 0x1a, 0x37, 0x00, 0x3c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x55, 0x00, 0x5e, 0x00, 0x64, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xbf, 0x00, 0xec, 0x00, 0x45, 0x01,
- 0x4e, 0x01, 0x00, 0x00, 0x54, 0x01, 0xdb, 0x01, 0xf9, 0x01, 0x84, 0x02,
- 0x00, 0x00, 0xa2, 0x02, 0x00, 0x00, 0xb6, 0x02, 0xc5, 0x02, 0x40, 0x07,
- 0x62, 0x61, 0x00, 0x40, 0x07, 0x75, 0x6c, 0x00, 0xe1, 0x6b, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x71, 0x75, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x73, 0x68, 0x69, 0x6d, 0x61,
- 0x00, 0x40, 0x07, 0x6c, 0x75, 0x61, 0x00, 0xe3, 0x66, 0x00, 0x73, 0x06,
- 0x74, 0x0b, 0x40, 0x07, 0x65, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x6c, 0x69, 0x6e, 0x00, 0xe6, 0x61, 0x00, 0x62, 0x1d,
- 0x65, 0x1f, 0x67, 0x26, 0x69, 0x2f, 0x6d, 0x31, 0xe3, 0x68, 0x00, 0x6d,
- 0x06, 0x73, 0x0d, 0x40, 0x07, 0x61, 0x72, 0x69, 0x00, 0x40, 0x07, 0x61,
- 0x7a, 0x6f, 0x6f, 0x00, 0x40, 0x07, 0x68, 0x6e, 0x69, 0x6b, 0x6f, 0x76,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x76, 0x61, 0x6c, 0x61, 0x00, 0x40, 0x07,
- 0x6f, 0x6f, 0x72, 0x6c, 0x69, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x79,
- 0x6b, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x02, 0x65, 0x0a, 0x70, 0x13, 0x00,
- 0x07, 0x40, 0x07, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x00, 0x40, 0x07, 0x68,
- 0x61, 0x6d, 0x65, 0x68, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40,
- 0x07, 0x6c, 0x61, 0x00, 0x40, 0x07, 0x63, 0x68, 0x65, 0x61, 0x00, 0xe9,
- 0x00, 0x00, 0x63, 0x02, 0x64, 0x0d, 0x65, 0x1f, 0x6e, 0x21, 0x6f, 0x27,
- 0x70, 0x29, 0x73, 0x2e, 0x74, 0x3a, 0x00, 0x06, 0x40, 0x07, 0x68, 0x65,
- 0x6e, 0x6a, 0x75, 0x6e, 0x67, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06,
- 0x40, 0x07, 0x68, 0x61, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x73, 0x6b, 0x79,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x64, 0x61, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x75, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x73, 0x69, 0x75, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x6f, 0x73, 0x69, 0x00, 0xe8, 0x61, 0x00, 0x65, 0x27,
- 0x69, 0x3c, 0x6c, 0x4c, 0x6e, 0x5c, 0x6f, 0x64, 0x72, 0x6d, 0x79, 0x72,
- 0xe5, 0x00, 0x00, 0x63, 0x02, 0x67, 0x07, 0x6b, 0x0e, 0x6d, 0x15, 0x00,
- 0x07, 0x40, 0x07, 0x68, 0x69, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x61,
- 0x00, 0x40, 0x07, 0x6f, 0x72, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x7a,
- 0x6f, 0x76, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x6d, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x04, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x66, 0x66, 0x00, 0x40, 0x07, 0x61, 0x74,
- 0x61, 0x6b, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x6f, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x04, 0x68, 0x08, 0x70, 0x0e, 0x40, 0x07, 0x69, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x06, 0x6d, 0x69, 0x72, 0x00, 0x40, 0x07, 0x61,
- 0x72, 0x6f, 0x76, 0x00, 0xe7, 0x65, 0x00, 0x68, 0x0c, 0x69, 0x5d, 0x6d,
- 0x68, 0x6f, 0x6d, 0x72, 0x74, 0x79, 0x7a, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x79, 0x6e, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x07,
- 0x69, 0x18, 0x6c, 0x25, 0x6d, 0x2b, 0x72, 0x32, 0x79, 0x40, 0x40, 0x07,
- 0x72, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x06, 0x40, 0x07, 0x77, 0x61, 0x72, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x75, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x00, 0x40, 0x07, 0x61, 0x69, 0x00, 0x40, 0x07, 0x77, 0x69,
- 0x63, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x61, 0x00, 0x00, 0x07, 0xe3,
- 0x61, 0x00, 0x66, 0x04, 0x6e, 0x0a, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07,
- 0x6d, 0x61, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x64, 0x04, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x73,
- 0x06, 0x40, 0x07, 0x61, 0x74, 0x61, 0x00, 0x40, 0x07, 0x61, 0x6b, 0x69,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6b, 0x00, 0x6e, 0x16,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x7a, 0x61, 0x6b, 0x69, 0x73,
- 0x00, 0x00, 0x07, 0xfe, 0x61, 0x00, 0x00, 0x63, 0x0e, 0x00, 0x65, 0x12,
- 0x00, 0x69, 0x23, 0x00, 0x6c, 0x39, 0x00, 0x6d, 0x6c, 0x00, 0x6e, 0x83,
- 0x00, 0x6f, 0x07, 0x01, 0x70, 0x15, 0x01, 0x72, 0x1b, 0x01, 0x74, 0x52,
- 0x01, 0x76, 0x5b, 0x01, 0x77, 0x79, 0x01, 0x79, 0x7f, 0x01, 0xe1, 0x74,
- 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6b, 0x00, 0xe2, 0x6e, 0x00, 0x77, 0x05, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6e, 0x00, 0xe3, 0x6c, 0x00,
- 0x73, 0x06, 0x74, 0x0b, 0x40, 0x07, 0x6c, 0x6f, 0x72, 0x00, 0x40, 0x07,
- 0x68, 0x61, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe3, 0x6c, 0x00, 0x73, 0x22,
- 0x76, 0x27, 0xe4, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x12, 0x79, 0x17, 0xe2,
- 0x72, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x67, 0x67, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x70, 0x07, 0x40, 0x07, 0x72, 0x6f, 0x76, 0x6f, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe6, 0x00, 0x00,
- 0x64, 0x02, 0x6d, 0x18, 0x6e, 0x1e, 0x74, 0x3f, 0x79, 0x5e, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x72, 0x05, 0x40, 0x07, 0x6c, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x63, 0x6b, 0x00, 0x40, 0x07,
- 0x6f, 0x72, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x69, 0x11, 0x79,
- 0x16, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x74, 0x68, 0x00, 0x00,
- 0x07, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x75, 0x06, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f,
- 0x10, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x04, 0x00, 0x07, 0x00, 0x06,
- 0x40, 0x07, 0x74, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x67, 0x00,
- 0x6b, 0x04, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x75, 0x6b, 0x00, 0x40,
- 0x07, 0x6c, 0x65, 0x72, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0c,
- 0x6d, 0x0e, 0x6e, 0x13, 0x6f, 0x15, 0x72, 0x1b, 0x40, 0x07, 0x6c, 0x61,
- 0x00, 0x40, 0x07, 0x6e, 0x73, 0x6b, 0x79, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x69, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x75, 0x61, 0x63, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x79, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x00, 0xe4, 0x65, 0x00,
- 0x69, 0x04, 0x6c, 0x08, 0x6f, 0x0d, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x72, 0x6b, 0x69,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x70, 0x69, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe7, 0x61,
- 0x00, 0x6d, 0x45, 0x6f, 0x4a, 0x72, 0x6e, 0x75, 0x78, 0x77, 0x86, 0x79,
- 0x8f, 0xe7, 0x62, 0x00, 0x63, 0x09, 0x6c, 0x14, 0x6e, 0x19, 0x72, 0x1b,
- 0x79, 0x2b, 0x7a, 0x31, 0x40, 0x07, 0x61, 0x72, 0x6f, 0x76, 0x73, 0x6b,
- 0x00, 0x40, 0x07, 0x68, 0x61, 0x74, 0x75, 0x72, 0x69, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x69, 0x64, 0x00, 0x00, 0x07, 0xe2, 0x6b, 0x00, 0x74, 0x05,
- 0x40, 0x07, 0x6f, 0x76, 0x00, 0x40, 0x07, 0x6f, 0x75, 0x6d, 0x00, 0x40,
- 0x07, 0x79, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0xe3, 0x69, 0x00, 0x6d, 0x10, 0x72, 0x17, 0xe2, 0x6b,
- 0x00, 0x73, 0x06, 0x40, 0x07, 0x68, 0x6f, 0x69, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x69, 0x6e, 0x69, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x61, 0x00, 0x40, 0x07, 0x75, 0x73, 0x68, 0x63, 0x68, 0x65, 0x76,
- 0x00, 0xe2, 0x66, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x75, 0x00, 0x40, 0x07,
- 0x6e, 0x61, 0x00, 0x40, 0x07, 0x61, 0x72, 0x69, 0x7a, 0x6d, 0x69, 0x00,
- 0x40, 0x07, 0x62, 0x65, 0x72, 0x00, 0xff, 0x63, 0x00, 0x00, 0x64, 0x08,
- 0x00, 0x65, 0x0c, 0x00, 0x67, 0x27, 0x00, 0x6a, 0x2d, 0x00, 0x6b, 0x33,
- 0x00, 0x6c, 0x39, 0x00, 0x6d, 0x55, 0x00, 0x6e, 0x70, 0x00, 0x6f, 0xab,
- 0x00, 0x70, 0xb0, 0x00, 0x72, 0xbd, 0x00, 0x73, 0x33, 0x01, 0x74, 0x58,
- 0x01, 0x77, 0x7d, 0x01, 0x40, 0x07, 0x6b, 0x61, 0x70, 0x6f, 0x6f, 0x00,
- 0x40, 0x07, 0x64, 0x00, 0xe4, 0x6c, 0x00, 0x72, 0x02, 0x74, 0x0c, 0x76,
- 0x10, 0x00, 0x07, 0x40, 0x07, 0x6b, 0x65, 0x67, 0x61, 0x61, 0x72, 0x64,
- 0x00, 0x40, 0x07, 0x68, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6c, 0x69,
- 0x00, 0x40, 0x07, 0x69, 0x6a, 0x69, 0x00, 0x40, 0x07, 0x75, 0x79, 0x75,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x06, 0x72, 0x10, 0x40, 0x07, 0x75, 0x65,
- 0x61, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x6a, 0x61, 0x72, 0x6f, 0x00,
- 0x40, 0x07, 0x6f, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0xe4, 0x67, 0x00, 0x6b,
- 0x18, 0x6e, 0x1e, 0x73, 0x23, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x77, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6f, 0x27, 0x73, 0x00, 0x40,
- 0x07, 0x65, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x07, 0x61, 0x73, 0x61, 0x00, 0x40, 0x09, 0x77, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6e, 0x67,
- 0x00, 0xe7, 0x62, 0x00, 0x63, 0x04, 0x67, 0x17, 0x69, 0x33, 0x6b, 0x45,
- 0x6f, 0x5d, 0x73, 0x61, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x68, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x6f, 0x66, 0x66, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00,
- 0x7a, 0x06, 0x40, 0x07, 0x74, 0x61, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x6e, 0x06,
- 0x40, 0x07, 0x61, 0x74, 0x69, 0x00, 0x40, 0x07, 0x79, 0x61, 0x67, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x70, 0x08, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x61, 0x74, 0x72, 0x69, 0x63, 0x6b,
- 0x00, 0x40, 0x07, 0x76, 0x00, 0x40, 0x07, 0x74, 0x65, 0x6e, 0x00, 0xe4,
- 0x61, 0x00, 0x68, 0x08, 0x6c, 0x0f, 0x73, 0x14, 0x40, 0x07, 0x6e, 0x67,
- 0x61, 0x6e, 0x69, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x76, 0x00, 0x40,
- 0x07, 0x65, 0x76, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x63, 0x0b, 0x74, 0x13, 0x00, 0x07, 0x40,
- 0x07, 0x6b, 0x79, 0x75, 0x73, 0x68, 0x75, 0x00, 0x40, 0x07, 0x68, 0x65,
- 0x6e, 0x65, 0x72, 0x00, 0xe2, 0x73, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x6e, 0x69, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x16, 0x69, 0x2b, 0x6f, 0x50, 0xe2, 0x6e, 0x00, 0x75, 0x0d, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x65, 0x78, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe3, 0x63, 0x00, 0x6d, 0x0e, 0x6e, 0x12, 0xe1, 0x6b, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x09, 0x6e, 0x64, 0x69, 0x6b, 0x65, 0x00, 0x40, 0x07, 0x61,
- 0x72, 0x74, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x05, 0x67, 0x0c, 0x69, 0x16,
- 0x6f, 0x34, 0x75, 0x6c, 0x40, 0x07, 0x70, 0x70, 0x00, 0x40, 0x07, 0x73,
- 0x73, 0x65, 0x74, 0x00, 0x40, 0x07, 0x77, 0x61, 0x72, 0x72, 0x65, 0x79,
- 0x65, 0x00, 0xe3, 0x63, 0x00, 0x65, 0x0c, 0x67, 0x12, 0x40, 0x07, 0x6b,
- 0x65, 0x72, 0x62, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x07, 0x76,
- 0x65, 0x6c, 0x00, 0x40, 0x07, 0x68, 0x74, 0x00, 0xe4, 0x70, 0x00, 0x73,
- 0x04, 0x77, 0x0a, 0x78, 0x21, 0x40, 0x07, 0x66, 0x00, 0x40, 0x07, 0x73,
- 0x6f, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x64, 0x00,
- 0x73, 0x0a, 0x40, 0x07, 0x67, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x6d, 0x00,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x76, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69,
- 0x6c, 0x6c, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x06, 0x40, 0x07, 0x73,
- 0x65, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xc0, 0x62, 0x16, 0x2f, 0x00, 0x33, 0x00, 0x41, 0x00,
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x76, 0x00, 0x7d, 0x00,
- 0x00, 0x00, 0x82, 0x00, 0x88, 0x00, 0x92, 0x00, 0xa5, 0x00, 0xab, 0x00,
- 0x00, 0x00, 0xb1, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00,
- 0x0f, 0x01, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x62, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x15, 0xe3, 0x63, 0x00, 0x6b, 0x08, 0x6c, 0x0a, 0x40, 0x07, 0x68, 0x72,
- 0x6f, 0x6d, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07,
- 0x61, 0x6b, 0x00, 0x40, 0x07, 0x73, 0x74, 0x6c, 0x65, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6e, 0x6f, 0x6f, 0x72, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x7a, 0x75, 0x6d, 0x69, 0x00, 0x40, 0x07, 0x61, 0x6b,
- 0x00, 0x40, 0x07, 0x79, 0x6d, 0x61, 0x00, 0x40, 0x07, 0x6d, 0x75, 0x6e,
- 0x69, 0x7a, 0x6d, 0x61, 0x00, 0xe2, 0x67, 0x00, 0x72, 0x09, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x64, 0x00,
- 0x40, 0x07, 0x6e, 0x74, 0x7a, 0x00, 0x40, 0x07, 0x70, 0x65, 0x6c, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x0e, 0x6e, 0x1a, 0x79, 0x21, 0x7a, 0x23, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x07, 0x62, 0x65, 0x72, 0x67, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x79, 0x62, 0x73, 0x6b, 0x69, 0x00, 0xe4, 0x63, 0x00, 0x6f, 0x08, 0x73,
- 0x0d, 0x79, 0x13, 0x40, 0x07, 0x69, 0x75, 0x73, 0x6b, 0x6f, 0x00, 0x40,
- 0x07, 0x76, 0x6f, 0x00, 0x40, 0x07, 0x75, 0x74, 0x68, 0x00, 0x40, 0x07,
- 0x67, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x66, 0x61, 0x78, 0x00, 0x40, 0x07,
- 0x6c, 0x6f, 0x6f, 0x6e, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x65, 0x3a, 0x00, 0x69, 0x6f, 0x00, 0x6f, 0xc9, 0x00, 0x75, 0xe9, 0x00,
- 0x79, 0x05, 0x01, 0x00, 0x07, 0xe4, 0x66, 0x00, 0x6b, 0x04, 0x6d, 0x13,
- 0x73, 0x18, 0x40, 0x07, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40,
- 0x07, 0x74, 0x6f, 0x61, 0x00, 0x40, 0x07, 0x77, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x64, 0x00, 0x79,
- 0x05, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x61, 0x72, 0x73, 0x6b,
- 0x00, 0xe3, 0x62, 0x00, 0x6d, 0x04, 0x73, 0x29, 0x40, 0x07, 0x73, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x73, 0x74, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x06, 0x40,
- 0x07, 0x67, 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x74, 0x16,
- 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x75, 0x72, 0x74, 0x69, 0x00, 0xe5, 0x61,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x6f, 0x1e, 0x79, 0x25, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x04, 0x00, 0x07,
- 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x70, 0x68, 0x65, 0x72, 0x00, 0x00, 0x07,
- 0xe4, 0x63, 0x00, 0x67, 0x02, 0x6e, 0x07, 0x70, 0x0f, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x6f, 0x74, 0x6b, 0x69, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x70,
- 0x13, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x70, 0x00,
- 0x40, 0x07, 0x73, 0x74, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x68, 0x61, 0x74,
- 0x72, 0x69, 0x79, 0x61, 0x00, 0xec, 0x61, 0x00, 0x62, 0x05, 0x68, 0x15,
- 0x69, 0x19, 0x6c, 0x22, 0x6e, 0x2a, 0x6f, 0x31, 0x72, 0x3b, 0x73, 0x6a,
- 0x74, 0x6f, 0x77, 0x76, 0x7a, 0x88, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe2,
- 0x6c, 0x00, 0x72, 0x05, 0x40, 0x07, 0x61, 0x69, 0x00, 0x40, 0x07, 0x69,
- 0x63, 0x6b, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x62, 0x79, 0x73,
- 0x68, 0x65, 0x76, 0x00, 0x40, 0x07, 0x74, 0x68, 0x75, 0x6d, 0x6d, 0x00,
- 0x40, 0x07, 0x6d, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6d, 0x69, 0x6e,
- 0x74, 0x61, 0x6e, 0x67, 0x00, 0xe3, 0x64, 0x00, 0x6f, 0x16, 0x74, 0x1d,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x68,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x61, 0x77, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x63, 0x68, 0x00, 0x40, 0x07, 0x75,
- 0x7a, 0x6f, 0x76, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6b, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x6b,
- 0x00, 0x6e, 0x07, 0x40, 0x07, 0x69, 0x75, 0x74, 0x6c, 0x00, 0xe3, 0x00,
- 0x00, 0x67, 0x02, 0x7a, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6a, 0x75, 0x00,
- 0x40, 0x09, 0x61, 0x61, 0x00, 0xe5, 0x00, 0x00, 0x6c, 0x02, 0x6f, 0x06,
- 0x72, 0x0b, 0x75, 0x15, 0x00, 0x0d, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07,
- 0x74, 0x6f, 0x00, 0x40, 0x07, 0x67, 0x79, 0x7a, 0x73, 0x74, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x73, 0x68, 0x75, 0x00, 0xc1, 0x27, 0x53, 0xab, 0x00,
- 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0xe1, 0x00, 0xe5, 0x00, 0xf2, 0x00,
- 0xf6, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x17, 0x01, 0x1b, 0x01, 0x20, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x38, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xdc, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x08,
- 0x3e, 0x08, 0x45, 0x0b, 0x00, 0x00, 0x4f, 0x0b, 0x00, 0x00, 0x62, 0x0b,
- 0x64, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x0d, 0x00, 0x00, 0xe4, 0x0d,
- 0xed, 0x0d, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x0f, 0x00, 0x14,
- 0xe3, 0x41, 0x00, 0x45, 0x07, 0x4f, 0x0f, 0x40, 0x07, 0x6d, 0x6f, 0x75,
- 0x72, 0x00, 0x40, 0x00, 0x6e, 0x66, 0x61, 0x6e, 0x74, 0x00, 0xe2, 0x72,
- 0x00, 0x75, 0x06, 0x40, 0x07, 0x65, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x76,
- 0x65, 0x72, 0x74, 0x75, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x4e, 0x02,
- 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x4a, 0x00, 0xe3, 0x00, 0x00, 0x44,
- 0x02, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x43,
- 0x00, 0x40, 0x07, 0x44, 0x00, 0xe2, 0x00, 0x00, 0x42, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x54, 0x00, 0x40, 0x00, 0x46, 0x4f, 0x00, 0xe3, 0x00, 0x00,
- 0x42, 0x02, 0x44, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x40, 0x00,
- 0x47, 0x00, 0x40, 0x00, 0x47, 0x4f, 0x00, 0xe3, 0x00, 0x00, 0x47, 0x02,
- 0x4e, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0xe2, 0x41, 0x00, 0x44,
- 0x04, 0x40, 0x00, 0x54, 0x00, 0x00, 0x07, 0x40, 0x00, 0x4e, 0x00, 0xc1,
- 0x62, 0x19, 0x37, 0x00, 0x39, 0x00, 0x5e, 0x00, 0x72, 0x00, 0x00, 0x00,
- 0x92, 0x00, 0xa5, 0x00, 0xc3, 0x00, 0xc9, 0x00, 0xce, 0x00, 0xd3, 0x00,
- 0x00, 0x00, 0x04, 0x01, 0x58, 0x01, 0x01, 0x02, 0x1a, 0x02, 0x00, 0x00,
- 0x31, 0x02, 0x71, 0x02, 0x8d, 0x02, 0xeb, 0x02, 0x3c, 0x03, 0x67, 0x03,
- 0x00, 0x00, 0x80, 0x03, 0x8f, 0x03, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x72, 0x06, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x06, 0x40, 0x00, 0x61, 0x6e, 0x00, 0xe3, 0x65, 0x00,
- 0x68, 0x04, 0x79, 0x0b, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x69, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x6f, 0x00, 0x79, 0x0e, 0xe2, 0x67,
- 0x00, 0x6e, 0x04, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x09, 0x68, 0x69, 0x70,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x08, 0x40, 0x07, 0x79, 0x65, 0x74, 0x74,
- 0x65, 0x00, 0x40, 0x07, 0x74, 0x74, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72,
- 0x04, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x07, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x6f, 0x73, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x17, 0x6f,
- 0x1d, 0x73, 0x22, 0xe3, 0x69, 0x00, 0x72, 0x06, 0x77, 0x0a, 0x40, 0x07,
- 0x73, 0x68, 0x61, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x6f,
- 0x64, 0x00, 0x40, 0x07, 0x73, 0x68, 0x61, 0x00, 0x40, 0x07, 0x74, 0x61,
- 0x00, 0x40, 0x07, 0x68, 0x6d, 0x69, 0x00, 0xe4, 0x61, 0x00, 0x62, 0x1b,
- 0x65, 0x3b, 0x6f, 0x46, 0xe3, 0x69, 0x00, 0x72, 0x05, 0x7a, 0x10, 0x40,
- 0x06, 0x73, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6b, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x6f, 0x07, 0x72, 0x10, 0x00, 0x07, 0x40, 0x07, 0x72, 0x74, 0x00, 0x40,
- 0x07, 0x72, 0x67, 0x68, 0x69, 0x6e, 0x69, 0x00, 0x40, 0x07, 0x75, 0x73,
- 0x63, 0x6f, 0x00, 0x40, 0x00, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x00, 0xe9, 0x61, 0x00, 0x63, 0x09,
- 0x64, 0x2d, 0x65, 0x51, 0x67, 0x53, 0x6b, 0x7a, 0x6e, 0x86, 0x73, 0x8a,
- 0x7a, 0x90, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2,
- 0x61, 0x00, 0x65, 0x13, 0xe1, 0x73, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x06,
- 0x40, 0x07, 0x69, 0x72, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x6f, 0x02, 0x72, 0x06, 0x73, 0x0a, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x74, 0x00, 0x40, 0x07, 0x65, 0x69, 0x6e, 0x65, 0x72, 0x00, 0x00,
- 0x07, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x0a, 0x6d, 0x18, 0x00, 0x07,
- 0x40, 0x07, 0x72, 0x68, 0x61, 0x6e, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x05, 0x40, 0x07, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07,
- 0x75, 0x69, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x75, 0x00, 0xe4, 0x00, 0x00, 0x63,
- 0x02, 0x73, 0x08, 0x74, 0x0a, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6f, 0x6e,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x69, 0x61, 0x6e, 0x00, 0xe2, 0x6c, 0x00,
- 0x70, 0x10, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x0e, 0x64, 0x00, 0x00, 0x06, 0xe6, 0x61, 0x00, 0x64,
- 0x0c, 0x65, 0x12, 0x6f, 0x17, 0x72, 0x1e, 0x73, 0x22, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x64, 0x6f, 0x00, 0x40, 0x07, 0x75, 0x73,
- 0x73, 0x65, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x6f, 0x06, 0x00, 0x14, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x73, 0x06, 0x40, 0x07, 0x61, 0x75, 0x78, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x68,
- 0x0e, 0x69, 0x13, 0x6f, 0x2a, 0x72, 0x38, 0x76, 0x3e, 0x00, 0x07, 0x40,
- 0x07, 0x73, 0x68, 0x61, 0x00, 0x40, 0x07, 0x72, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x61, 0x6d, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x0d, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x6f, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x06, 0x40, 0x07,
- 0x68, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x79, 0x05, 0x40, 0x07, 0x79, 0x61,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x62, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x09, 0xe4, 0x64, 0x00, 0x65, 0x0b, 0x6e, 0x0d, 0x72, 0x16, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x0e, 0x40, 0x07, 0x72, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x64, 0x72, 0x6f, 0x6d, 0x61, 0x74, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x0c, 0x69, 0x22, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x69, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x63, 0x02, 0x74, 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3,
- 0x61, 0x00, 0x65, 0x04, 0x6f, 0x13, 0x40, 0x07, 0x6c, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe2, 0x69, 0x00, 0x6e, 0x07, 0x40, 0x07, 0x73, 0x69, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x72, 0x06, 0x73,
- 0x0d, 0x40, 0x07, 0x6e, 0x64, 0x61, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x63,
- 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x06,
- 0x40, 0x07, 0x6d, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x73, 0x00, 0xc1, 0x61, 0x18, 0x35, 0x00, 0x37, 0x00, 0x92, 0x00,
- 0x00, 0x00, 0xb7, 0x00, 0xc6, 0x00, 0xe5, 0x00, 0xe9, 0x00, 0x12, 0x01,
- 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01, 0x64, 0x01, 0x7e, 0x01,
- 0xe2, 0x01, 0x44, 0x02, 0x00, 0x00, 0x59, 0x02, 0x67, 0x02, 0xa8, 0x02,
- 0x00, 0x00, 0xd9, 0x02, 0x19, 0x03, 0x2d, 0x03, 0x00, 0x06, 0xe8, 0x00,
- 0x00, 0x63, 0x02, 0x64, 0x06, 0x68, 0x0e, 0x6b, 0x10, 0x6e, 0x15, 0x72,
- 0x30, 0x76, 0x40, 0x00, 0x07, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x62,
- 0x65, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x79, 0x00,
- 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6a, 0x02, 0x79, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x77,
- 0x6f, 0x72, 0x74, 0x68, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x11, 0x6c, 0x18,
- 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x73, 0x65,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x67, 0x75, 0x65, 0x00,
- 0x40, 0x07, 0x61, 0x6e, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x62, 0x65, 0x72, 0x67, 0x00, 0xe4, 0x00, 0x00,
- 0x64, 0x02, 0x75, 0x06, 0x77, 0x10, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x77, 0x65, 0x6e, 0x68, 0x6f, 0x65, 0x6b, 0x00, 0x40, 0x07,
- 0x61, 0x72, 0x64, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe5, 0x43, 0x00, 0x65,
- 0x04, 0x68, 0x11, 0x6f, 0x17, 0x72, 0x19, 0x40, 0x07, 0x6f, 0x00, 0xe2,
- 0x6e, 0x00, 0x72, 0x06, 0x40, 0x07, 0x64, 0x72, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x72, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x65,
- 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x00, 0xe7, 0x62, 0x00, 0x63, 0x06,
- 0x64, 0x14, 0x66, 0x19, 0x67, 0x1b, 0x6c, 0x1f, 0x70, 0x23, 0x40, 0x07,
- 0x6e, 0x69, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40,
- 0x06, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x7a,
- 0x69, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0b, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x07, 0x40, 0x07, 0x69, 0x74, 0x72, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x72, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x69, 0x61,
- 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x69, 0x0d, 0x6e, 0x2b, 0x6f, 0x36,
- 0x74, 0x4c, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x69,
- 0x08, 0x00, 0x07, 0x40, 0x07, 0x72, 0x61, 0x64, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x6f, 0x00,
- 0x79, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x72, 0x06, 0x00, 0x07, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x26, 0x40, 0x07, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x06,
- 0x70, 0x47, 0x00, 0x06, 0x40, 0x07, 0x61, 0x00, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x63, 0x15, 0x65, 0x1e, 0x69, 0x22, 0x6f, 0x30, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x76, 0x61, 0x6c,
- 0x6c, 0x6f, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x69, 0x00, 0x6b, 0x06,
- 0x75, 0x0a, 0x40, 0x07, 0x64, 0x75, 0x73, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x6c,
- 0x04, 0x6f, 0x11, 0x73, 0x17, 0x74, 0x25, 0x00, 0x07, 0x00, 0x07, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x74, 0x68, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40,
- 0x07, 0x70, 0x73, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x72,
- 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x64, 0x65, 0x00, 0xe4,
- 0x61, 0x00, 0x68, 0x02, 0x69, 0x0b, 0x74, 0x1a, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x74, 0x05,
- 0x40, 0x07, 0x69, 0x61, 0x00, 0x40, 0x07, 0x69, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x6d, 0x61, 0x6e, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0c, 0x79, 0x35, 0x40, 0x07, 0x6e,
- 0x74, 0x00, 0x40, 0x07, 0x73, 0x71, 0x75, 0x65, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x6e, 0x09, 0x74, 0x0d, 0x00, 0x06, 0x40, 0x07, 0x74, 0x68,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x72, 0x06,
- 0x74, 0x0a, 0x40, 0x07, 0x63, 0x75, 0x73, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2,
- 0x6e, 0x00, 0x73, 0x06, 0x40, 0x07, 0x73, 0x6b, 0x79, 0x00, 0x00, 0x07,
- 0xe3, 0x69, 0x00, 0x6d, 0x14, 0x75, 0x1a, 0xe2, 0x6e, 0x00, 0x73, 0x07,
- 0x40, 0x07, 0x67, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x4e, 0x65, 0x78,
- 0x69, 0x73, 0x00, 0x40, 0x07, 0x61, 0x72, 0x6b, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x73, 0x61, 0x00, 0x40,
- 0x07, 0x74, 0x73, 0x65, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x63, 0x5c, 0x00, 0x64, 0x68, 0x00, 0x65, 0x6d, 0x00, 0x6c, 0xbf, 0x00,
- 0x6d, 0x24, 0x01, 0x6e, 0x5b, 0x01, 0x6f, 0xd9, 0x01, 0x70, 0xdf, 0x01,
- 0x73, 0x0a, 0x02, 0x74, 0x49, 0x02, 0x76, 0x73, 0x02, 0x7a, 0xc6, 0x02,
- 0x00, 0x12, 0xe4, 0x62, 0x00, 0x65, 0x04, 0x72, 0x1d, 0x79, 0x45, 0x40,
- 0x07, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40,
- 0x07, 0x63, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0xe4, 0x61, 0x00, 0x65, 0x02, 0x69, 0x16, 0x6f,
- 0x1b, 0x00, 0x09, 0xe2, 0x4f, 0x00, 0x76, 0x08, 0x40, 0x07, 0x66, 0x66,
- 0x69, 0x63, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0x40,
- 0x07, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x68, 0x74,
- 0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x61,
- 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x63, 0x19, 0x67, 0x3f, 0x75, 0x43,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x66, 0x07, 0x40, 0x07, 0x72, 0x6d, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x72, 0x61, 0x75, 0x6d, 0x69, 0x6c, 0x63, 0x68,
- 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x27, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe5,
- 0x61, 0x00, 0x69, 0x02, 0x6c, 0x27, 0x6f, 0x51, 0x79, 0x58, 0x00, 0x07,
- 0xe3, 0x61, 0x00, 0x74, 0x10, 0x75, 0x14, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x68, 0x00, 0x40, 0x07, 0x6f, 0x6b, 0x61, 0x6c, 0x61, 0x6e, 0x69,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x21, 0x00, 0x07, 0xe3, 0x61,
- 0x00, 0x65, 0x04, 0x70, 0x06, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe1,
- 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x09, 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x77,
- 0x65, 0x00, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x62, 0x02, 0x6f, 0x18, 0x70,
- 0x28, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x6f, 0x06, 0x75, 0x08, 0x40, 0x07,
- 0x75, 0x67, 0x68, 0x00, 0x00, 0x00, 0x40, 0x07, 0x72, 0x67, 0x65, 0x72,
- 0x00, 0xe2, 0x67, 0x00, 0x75, 0x05, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x70, 0x6f, 0x00, 0xea,
- 0x00, 0x00, 0x61, 0x02, 0x63, 0x04, 0x64, 0x1b, 0x6b, 0x40, 0x6e, 0x47,
- 0x6f, 0x4e, 0x74, 0x55, 0x75, 0x5a, 0x77, 0x63, 0x00, 0x07, 0x00, 0x07,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x09, 0x40, 0x07, 0x68, 0x69, 0x72, 0x65, 0x00, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x04, 0x73, 0x0b, 0x79, 0x18, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x67, 0x68, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x64, 0x49, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x65, 0x75,
- 0x73, 0x00, 0x40, 0x07, 0x74, 0x79, 0x70, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe2, 0x73, 0x00, 0x78, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40,
- 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x6c, 0x00, 0xe4,
- 0x69, 0x00, 0x70, 0x09, 0x73, 0x16, 0x74, 0x1d, 0x40, 0x07, 0x7a, 0x7a,
- 0x61, 0x6e, 0x65, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6d, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x6e, 0x6e, 0x00, 0x40, 0x07, 0x63, 0x6f, 0x6d, 0x62,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x62, 0x02, 0x73,
- 0x07, 0x74, 0x0f, 0x7a, 0x30, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x6a, 0x6f, 0x75, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x6d,
- 0x0f, 0x6f, 0x16, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x69, 0x61,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe2, 0x68, 0x00,
- 0x74, 0x18, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x23, 0x6f, 0x42, 0x79, 0x48,
- 0xe2, 0x4a, 0x00, 0x72, 0x09, 0x40, 0x07, 0x6f, 0x75, 0x72, 0x6e, 0x61,
- 0x6c, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40, 0x07,
- 0x6f, 0x6c, 0x00, 0x40, 0x06, 0x64, 0x6c, 0x69, 0x61, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe1, 0x67, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x69, 0x61, 0x00,
- 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x7a, 0x04, 0x00, 0x07, 0x00,
- 0x07, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x09, 0x40, 0x07, 0x77, 0x65, 0x6c, 0x6c, 0x79, 0x6e, 0x00,
- 0x40, 0x07, 0x79, 0x64, 0x00, 0x00, 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00,
- 0x3b, 0x00, 0x46, 0x00, 0x71, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x8c, 0x00,
- 0x9c, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xb0, 0x00, 0xb4, 0x00, 0xd6, 0x00,
- 0xf3, 0x00, 0x36, 0x01, 0x3f, 0x01, 0x00, 0x00, 0x44, 0x01, 0xb9, 0x01,
- 0xbb, 0x01, 0xd6, 0x01, 0x2c, 0x02, 0x45, 0x02, 0x00, 0x00, 0x6b, 0x02,
- 0x40, 0x06, 0x66, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x63, 0x68, 0x65,
- 0x76, 0x73, 0x6b, 0x79, 0x00, 0xe2, 0x68, 0x00, 0x6b, 0x08, 0x40, 0x07,
- 0x69, 0x6e, 0x76, 0x61, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x68, 0x0b, 0x77,
- 0x11, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x65, 0x65, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00,
- 0xe2, 0x67, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0xe1,
- 0x77, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x73, 0x04, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x74, 0x65, 0x63, 0x68, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x67,
- 0x72, 0x69, 0x6e, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x02,
- 0x6c, 0x07, 0x00, 0x07, 0x40, 0x07, 0x74, 0x61, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x05, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x07, 0x62, 0x72, 0x69,
- 0x67, 0x69, 0x64, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x65, 0x16, 0xe1, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x79, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe4, 0x00,
- 0x00, 0x64, 0x02, 0x67, 0x13, 0x6e, 0x35, 0x00, 0x07, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x13, 0x40, 0x07,
- 0x72, 0x00, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x73, 0x0a, 0x75, 0x12, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x00, 0x40, 0x07, 0x74,
- 0x72, 0x65, 0x65, 0x74, 0x00, 0x40, 0x00, 0x65, 0x75, 0x69, 0x6c, 0x00,
- 0x40, 0x07, 0x69, 0x65, 0x00, 0x40, 0x07, 0x6b, 0x53, 0x6d, 0x61, 0x72,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x7a, 0x00, 0xe6, 0x61, 0x00, 0x64, 0x0c,
- 0x65, 0x19, 0x69, 0x48, 0x6e, 0x51, 0x72, 0x55, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0x40, 0x06, 0x68, 0x69, 0x70, 0x00, 0xe3, 0x6c, 0x00,
- 0x6e, 0x05, 0x74, 0x23, 0x40, 0x07, 0x65, 0x69, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x04, 0x74, 0x06, 0x7a, 0x0a, 0x00, 0x07, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x74, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x06, 0x69, 0x08, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x74,
- 0x09, 0x00, 0x07, 0x40, 0x06, 0x61, 0x72, 0x69, 0x6f, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe5, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x08, 0x72, 0x40, 0x76, 0x46, 0x00, 0x07, 0x40, 0x07,
- 0x6c, 0x6c, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x07, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x69, 0x06, 0x76, 0x1f, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09,
- 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x64, 0x65, 0x73, 0x00, 0x40, 0x07, 0x72, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x09, 0x00, 0x07, 0x40,
- 0x07, 0x72, 0x61, 0x66, 0x74, 0x00, 0x40, 0x07, 0x61, 0x63, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x6c, 0x1a, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x06,
- 0x72, 0x0d, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x62, 0x72,
- 0x61, 0x75, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x64,
- 0x73, 0x00, 0xe3, 0x61, 0x00, 0x64, 0x05, 0x6f, 0x07, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x61, 0x00, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x61, 0x1a, 0x39,
- 0x00, 0x3b, 0x00, 0x49, 0x00, 0x69, 0x00, 0xdc, 0x00, 0xf5, 0x00, 0xfb,
- 0x00, 0x11, 0x01, 0x00, 0x00, 0x1f, 0x01, 0x00, 0x00, 0x31, 0x01, 0x35,
- 0x01, 0x44, 0x01, 0x4b, 0x01, 0x00, 0x00, 0x4f, 0x01, 0x00, 0x00, 0x67,
- 0x01, 0x6c, 0x01, 0x7e, 0x01, 0x00, 0x00, 0x9d, 0x01, 0x00, 0x00, 0xa1,
- 0x01, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x64,
- 0x00, 0x6e, 0x04, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00,
- 0x62, 0x0a, 0x75, 0x10, 0x40, 0x07, 0x76, 0x69, 0x74, 0x63, 0x68, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x6d, 0x62,
- 0x61, 0x73, 0x68, 0x69, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x04, 0x69, 0x06,
- 0x6b, 0x4a, 0x72, 0x50, 0x79, 0x64, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07,
- 0xe8, 0x61, 0x00, 0x65, 0x10, 0x66, 0x14, 0x6c, 0x19, 0x6e, 0x24, 0x6f,
- 0x29, 0x74, 0x2b, 0x75, 0x2f, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x64, 0x61, 0x00, 0x00, 0x07,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x6f,
- 0x77, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07,
- 0xe3, 0x64, 0x00, 0x68, 0x06, 0x77, 0x0d, 0x40, 0x09, 0x69, 0x74, 0x65,
- 0x00, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x69, 0x67,
- 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x68,
- 0x00, 0x77, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x73, 0x61, 0x00, 0x40, 0x07,
- 0x61, 0x66, 0x66, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x73, 0x69, 0x00, 0xe2, 0x67, 0x00, 0x73, 0x04,
- 0x40, 0x07, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x02, 0x75, 0x06,
- 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x65,
- 0x72, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x0f,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x63, 0x61, 0x6c,
- 0x69, 0x61, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x69, 0x61, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x6b, 0x61, 0x00, 0x40, 0x07,
- 0x74, 0x61, 0x6e, 0x69, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x73, 0x6d,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe1,
- 0x62, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x67, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x27, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x76, 0x00,
- 0xeb, 0x58, 0x00, 0x61, 0x02, 0x63, 0x0a, 0x64, 0x20, 0x65, 0x2f, 0x6c,
- 0x34, 0x6d, 0x3d, 0x6e, 0x48, 0x6f, 0x79, 0x72, 0x85, 0x73, 0x89, 0x00,
- 0x07, 0x40, 0x00, 0x6c, 0x6c, 0x70, 0x75, 0x72, 0x00, 0xe3, 0x6f, 0x00,
- 0x72, 0x04, 0x75, 0x08, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x72, 0x67, 0x75, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07,
- 0x6c, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe4,
- 0x63, 0x00, 0x64, 0x04, 0x65, 0x0f, 0x6e, 0x15, 0x40, 0x07, 0x68, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x74, 0x74, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x06, 0x6f, 0x0f, 0x40,
- 0x07, 0x6e, 0x6b, 0x6f, 0x00, 0x40, 0x07, 0x73, 0x74, 0x72, 0x61, 0x74,
- 0x61, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xc1, 0x41, 0x39, 0x77, 0x00, 0x79,
- 0x00, 0x84, 0x00, 0x8d, 0x00, 0x96, 0x00, 0x9f, 0x00, 0xaa, 0x00, 0xae,
- 0x00, 0xb2, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5,
- 0x00, 0xd7, 0x00, 0xd9, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xef, 0x00, 0xf3,
- 0x00, 0x04, 0x01, 0x00, 0x00, 0x0d, 0x01, 0x11, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x0d, 0x1b, 0x0d, 0xfb, 0x0e, 0xfd,
- 0x0e, 0x4c, 0x13, 0x52, 0x13, 0x00, 0x00, 0x5b, 0x13, 0x00, 0x00, 0x62,
- 0x17, 0x64, 0x17, 0x69, 0x17, 0x6d, 0x17, 0x7d, 0x17, 0x00, 0x00, 0x00,
- 0x00, 0x55, 0x1c, 0x57, 0x1c, 0x62, 0x1c, 0x64, 0x1c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x48, 0x1e, 0x00, 0x28, 0xe2, 0x00, 0x00, 0x53, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x48, 0x00, 0xe2, 0x00, 0x00, 0x41, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x49, 0x02, 0x00, 0x00, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x54, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x47, 0x02, 0x00, 0x00, 0x40, 0x08, 0x4f, 0x00, 0x40, 0x07, 0x41, 0x00,
- 0x40, 0x07, 0x4d, 0x00, 0x40, 0x00, 0x7a, 0x00, 0xe6, 0x00, 0x00, 0x41,
- 0x02, 0x44, 0x04, 0x50, 0x08, 0x52, 0x0c, 0x54, 0x10, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x07, 0x49, 0x00, 0x40, 0x00, 0x53, 0x00, 0x40, 0x00, 0x56,
- 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x4f, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x43, 0x00, 0xe2, 0x00, 0x00, 0x45, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x47, 0x00, 0x40, 0x07, 0x49, 0x00, 0xe4, 0x00, 0x00,
- 0x47, 0x02, 0x54, 0x04, 0x57, 0x06, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x56, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x50, 0x00, 0x00, 0x00, 0xc0, 0x61, 0x1a, 0x37, 0x00, 0x3d, 0x00,
- 0x4a, 0x00, 0xa0, 0x01, 0x19, 0x02, 0x2a, 0x02, 0x39, 0x02, 0xbf, 0x02,
- 0x12, 0x03, 0x6b, 0x03, 0x8f, 0x03, 0x9f, 0x03, 0xcf, 0x04, 0xec, 0x04,
- 0x26, 0x06, 0x3f, 0x06, 0x00, 0x00, 0x5d, 0x06, 0xaa, 0x09, 0x46, 0x0a,
- 0xbe, 0x0a, 0x4c, 0x0b, 0x00, 0x00, 0x51, 0x0b, 0x71, 0x0b, 0xbf, 0x0b,
- 0x40, 0x07, 0x6c, 0x6f, 0x78, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x04, 0x40,
- 0x07, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x00, 0xc1, 0x41, 0x39, 0x77, 0x00,
- 0x79, 0x00, 0x81, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0xaa, 0x00, 0xb0, 0x00, 0x00, 0x00,
- 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x0a, 0x01, 0x00, 0x00,
- 0x1a, 0x01, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x07, 0x40, 0x07, 0x72, 0x74,
- 0x68, 0x75, 0x72, 0x00, 0x40, 0x07, 0x72, 0x69, 0x64, 0x65, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x61, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x65, 0x69, 0x73,
- 0x68, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x74, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x75, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x6e, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x73, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x09, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x7a, 0x69, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x63, 0x00, 0x77, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6c,
- 0x6c, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6d,
- 0x65, 0x64, 0x69, 0x61, 0x00, 0x40, 0x07, 0x6d, 0x62, 0x61, 0x00, 0x00,
- 0x07, 0xe8, 0x61, 0x00, 0x64, 0x18, 0x65, 0x25, 0x67, 0x45, 0x69, 0x49,
- 0x6f, 0x4f, 0x72, 0x55, 0x75, 0x62, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00,
- 0x72, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x07, 0x78, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x05,
- 0x40, 0x06, 0x72, 0x61, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x06, 0x79, 0x0b,
- 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x73, 0x6f, 0x6e,
- 0x00, 0x40, 0x06, 0x6e, 0x6e, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x72, 0x61,
- 0x69, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x72, 0x6c, 0x69, 0x6e, 0x63, 0x6b, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x6f, 0x00, 0xeb, 0x64,
- 0x00, 0x65, 0x15, 0x67, 0x2c, 0x68, 0x31, 0x69, 0x37, 0x6e, 0x43, 0x6f,
- 0x4e, 0x72, 0x57, 0x73, 0x5e, 0x75, 0x66, 0x79, 0x6a, 0xe1, 0x61, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x63, 0x00, 0x40, 0x07, 0x69, 0x65, 0x00, 0x40, 0x07,
- 0x72, 0x65, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x40,
- 0x07, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x69, 0x74, 0x6f, 0x67, 0x6f, 0x72,
- 0x73, 0x6b, 0x00, 0xe2, 0x67, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x74, 0x74, 0x65, 0x00, 0x40, 0x07, 0x61, 0x79, 0x73,
- 0x61, 0x79, 0x00, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x61, 0x72, 0x00,
- 0xe5, 0x61, 0x00, 0x64, 0x33, 0x66, 0x37, 0x69, 0x3d, 0x6c, 0x43, 0xe4,
- 0x62, 0x00, 0x72, 0x09, 0x76, 0x12, 0x79, 0x18, 0x40, 0x07, 0x68, 0x61,
- 0x72, 0x61, 0x74, 0x61, 0x00, 0x40, 0x07, 0x61, 0x73, 0x68, 0x74, 0x72,
- 0x61, 0x00, 0x40, 0x07, 0x69, 0x72, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x74, 0x00, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x6f, 0x75, 0x7a, 0x00,
- 0x40, 0x06, 0x63, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe8,
- 0x00, 0x00, 0x64, 0x02, 0x67, 0x0b, 0x6c, 0x11, 0x6d, 0x1f, 0x6e, 0x30,
- 0x73, 0x3c, 0x74, 0x41, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x66, 0x6f,
- 0x72, 0x6d, 0x00, 0x40, 0x07, 0x72, 0x65, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x6c, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x69,
- 0x64, 0x65, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x29, 0x00, 0x07, 0x40, 0x07, 0x69, 0x65, 0x00, 0x40, 0x07, 0x72,
- 0x65, 0x79, 0x61, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x08, 0x75,
- 0x16, 0x00, 0x00, 0x40, 0x00, 0x73, 0x74, 0x79, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x72, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x72,
- 0x69, 0x6f, 0x73, 0x00, 0x40, 0x07, 0x72, 0x00, 0xfa, 0x61, 0x00, 0x00,
- 0x63, 0x6e, 0x00, 0x64, 0x74, 0x00, 0x65, 0x96, 0x00, 0x69, 0x98, 0x00,
- 0x6c, 0xbb, 0x00, 0x6f, 0xd5, 0x00, 0x70, 0xe2, 0x00, 0x72, 0xeb, 0x00,
- 0x74, 0xf1, 0x00, 0xe7, 0x62, 0x00, 0x63, 0x0b, 0x67, 0x18, 0x6d, 0x1e,
- 0x70, 0x23, 0x77, 0x29, 0x79, 0x37, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x68, 0x04, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x61, 0x73, 0x79, 0x00,
- 0x40, 0x07, 0x75, 0x64, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x70, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x06, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x12, 0x00, 0x09, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x6e, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6d, 0x00,
- 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x6c, 0x6d, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x16, 0xe1, 0x76, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x09, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x64, 0x6f, 0x00, 0x00, 0x07, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x06, 0x6e, 0x0a, 0x00, 0x07, 0x40, 0x06,
- 0x6e, 0x00, 0x40, 0x07, 0x75, 0x00, 0xe2, 0x64, 0x00, 0x6f, 0x04, 0x40,
- 0x07, 0x61, 0x00, 0x40, 0x07, 0x77, 0x73, 0x6b, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x06, 0x40, 0x07, 0x72, 0x6d, 0x65, 0x00, 0xe2, 0x6d, 0x00,
- 0x72, 0x06, 0x40, 0x07, 0x61, 0x72, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00,
- 0xe2, 0x6e, 0x00, 0x72, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x07, 0x6c, 0x61, 0x71, 0x75, 0x65, 0x74, 0x00, 0x40, 0x07,
- 0x61, 0x75, 0x78, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x68, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x06, 0x61, 0x6e, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x0d, 0x6f, 0x11, 0xe2, 0x6c, 0x00, 0x74, 0x06,
- 0x40, 0x07, 0x75, 0x6b, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x72, 0x65, 0x00, 0xff, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x63, 0x18, 0x00, 0x64, 0x4d, 0x00, 0x65, 0x85, 0x00, 0x66, 0x89, 0x00,
- 0x67, 0x8f, 0x00, 0x68, 0x93, 0x00, 0x69, 0x9b, 0x00, 0x6c, 0xc3, 0x00,
- 0x6e, 0xc8, 0x00, 0x73, 0xdc, 0x00, 0x74, 0xec, 0x00, 0x75, 0xfb, 0x00,
- 0x78, 0x0a, 0x01, 0x00, 0x07, 0xe3, 0x67, 0x00, 0x6d, 0x05, 0x73, 0x09,
- 0x40, 0x07, 0x75, 0x61, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x73,
- 0x65, 0x68, 0x00, 0xe3, 0x68, 0x00, 0x69, 0x22, 0x75, 0x27, 0xe2, 0x65,
- 0x00, 0x75, 0x07, 0x40, 0x07, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x69,
- 0x00, 0x40, 0x09, 0x6e, 0x69, 0x61, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x65,
- 0x0f, 0x69, 0x1f, 0x72, 0x25, 0x79, 0x2b, 0xe2, 0x6c, 0x00, 0x72, 0x05,
- 0x40, 0x07, 0x61, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x61, 0x00, 0x62, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x6f,
- 0x74, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x6f, 0x00, 0x40, 0x07, 0x65, 0x6c,
- 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x72, 0x65,
- 0x64, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x06, 0x61, 0x74, 0x74, 0x61,
- 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x09, 0x74, 0x0d, 0x00,
- 0x07, 0x40, 0x07, 0x68, 0x65, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x62, 0x00, 0x75, 0x04, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x6c, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0xe3,
- 0x00, 0x00, 0x68, 0x02, 0x69, 0x08, 0x00, 0x2a, 0x40, 0x07, 0x65, 0x69,
- 0x6d, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x66, 0x00, 0x6f, 0x07,
- 0x40, 0x07, 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x6c, 0x06, 0x40, 0x07, 0x67, 0x6e, 0x61, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x72, 0x0e, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0x00, 0x06, 0x40, 0x09, 0x69, 0x00, 0xe3, 0x51, 0x00, 0x70,
- 0x07, 0x75, 0x12, 0x40, 0x07, 0x75, 0x65, 0x73, 0x74, 0x00, 0x40, 0x07,
- 0x6c, 0x65, 0x74, 0x68, 0x6f, 0x72, 0x70, 0x65, 0x00, 0x40, 0x07, 0x74,
- 0x6f, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39, 0x00, 0x00, 0x00, 0x5f,
- 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x1f,
- 0x01, 0xba, 0x01, 0xcb, 0x01, 0xe7, 0x01, 0x23, 0x02, 0x29, 0x02, 0x2d,
- 0x02, 0x34, 0x02, 0x39, 0x02, 0x5f, 0x02, 0x71, 0x02, 0xab, 0x02, 0x00,
- 0x00, 0xe7, 0x02, 0x00, 0x00, 0xf9, 0x02, 0x12, 0x03, 0x00, 0x06, 0xe3,
- 0x00, 0x00, 0x63, 0x02, 0x74, 0x09, 0x00, 0x07, 0x40, 0x07, 0x61, 0x69,
- 0x62, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0xe3, 0x61,
- 0x00, 0x69, 0x02, 0x6f, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x68, 0x21, 0x69, 0x23, 0x6f, 0x39,
- 0x75, 0x48, 0x79, 0x54, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40,
- 0x07, 0x75, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07, 0x6f, 0x0b,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x00, 0x00,
- 0x07, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0d, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x00, 0x00,
- 0x07, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x73, 0x06, 0x00, 0x09, 0x40, 0x07,
- 0x69, 0x00, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x75, 0x6b, 0x00, 0xe6,
- 0x61, 0x00, 0x65, 0x18, 0x69, 0x23, 0x6f, 0x27, 0x72, 0x30, 0x75, 0x41,
- 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x74, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x69, 0x74, 0x65,
- 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x62, 0x23, 0x63, 0x28, 0x65, 0x2e,
- 0x6c, 0x3a, 0x6e, 0x3f, 0x6f, 0x4c, 0x73, 0x55, 0x74, 0x6a, 0x75, 0x78,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x6e, 0x0b, 0x6f, 0x0f, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x61, 0x00, 0x40, 0x07,
- 0x79, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x04, 0x73, 0x08, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x61,
- 0x00, 0x7a, 0x05, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0xe2, 0x70, 0x00, 0x73, 0x05, 0x40, 0x00, 0x6f, 0x6c, 0x00, 0x00, 0x07,
- 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x68, 0x06,
- 0x6f, 0x0b, 0x73, 0x0f, 0x00, 0x06, 0x40, 0x07, 0x62, 0x00, 0x40, 0x07,
- 0x61, 0x6d, 0x00, 0x40, 0x07, 0x76, 0x00, 0x00, 0x07, 0xe5, 0x61, 0x00,
- 0x62, 0x02, 0x65, 0x17, 0x69, 0x22, 0x6f, 0x26, 0x00, 0x07, 0xe1, 0x6f,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x67, 0x68, 0x00, 0xe2, 0x6e, 0x00, 0x79, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6e,
- 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x61,
- 0x72, 0x61, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x74,
- 0x65, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x13, 0xe3, 0x73, 0x00, 0x74, 0x05, 0x7a, 0x0a, 0x40, 0x07,
- 0x61, 0x73, 0x00, 0x40, 0x07, 0x74, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x73,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x07, 0x40, 0x07, 0x6b, 0x65, 0x73, 0x68, 0x00, 0x40, 0x07, 0x6f,
- 0x74, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x68, 0x1f,
- 0x00, 0x09, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x09, 0x69,
- 0x73, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c,
- 0x00, 0xe5, 0x61, 0x00, 0x65, 0x02, 0x68, 0x06, 0x69, 0x0a, 0x79, 0x2f,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x61,
- 0x00, 0x6e, 0x09, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x69, 0x08, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x7a, 0x00, 0x40, 0x07, 0x71, 0x75, 0x65, 0x00, 0x00,
- 0x07, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x69, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40, 0x00, 0x6e, 0x00, 0xe2,
- 0x6d, 0x00, 0x74, 0x02, 0x00, 0x06, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x11, 0x6c, 0x18, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x6c, 0x6c, 0x65, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x11, 0xe1, 0x6e,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x0e, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x75, 0x00, 0xe7, 0x61, 0x00, 0x63, 0x12,
- 0x65, 0x19, 0x68, 0x31, 0x6f, 0x37, 0x73, 0x4c, 0x74, 0x76, 0xe3, 0x64,
- 0x00, 0x69, 0x04, 0x72, 0x06, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x79, 0x6b, 0x00, 0x40, 0x07, 0x61, 0x67, 0x6e, 0x69, 0x00, 0xe2,
- 0x66, 0x00, 0x72, 0x07, 0x40, 0x07, 0x69, 0x65, 0x6c, 0x64, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x05, 0x40, 0x07, 0x74, 0x69, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x68, 0x61, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x17, 0x00, 0x09, 0xe2,
- 0x63, 0x00, 0x73, 0x0a, 0x40, 0x07, 0x68, 0x75, 0x73, 0x65, 0x74, 0x74,
- 0x73, 0x00, 0x40, 0x07, 0x6f, 0x69, 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x79,
- 0x05, 0x40, 0x07, 0x65, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x43, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40,
- 0x07, 0x61, 0x72, 0x64, 0x00, 0x00, 0x07, 0xe3, 0x68, 0x00, 0x69, 0x2f,
- 0x74, 0x3e, 0xe3, 0x4d, 0x00, 0x65, 0x04, 0x69, 0x1d, 0x40, 0x07, 0x4c,
- 0x00, 0xe2, 0x72, 0x00, 0x77, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00,
- 0x07, 0xe2, 0x6c, 0x00, 0x73, 0x05, 0x40, 0x07, 0x64, 0x61, 0x00, 0x40,
- 0x07, 0x73, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x68, 0x10, 0x69,
- 0x26, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x68, 0x6f, 0x72, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe1, 0x77,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x73, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe6, 0x64, 0x00, 0x67, 0x09,
- 0x69, 0x0f, 0x70, 0x11, 0x72, 0x1a, 0x73, 0x7c, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x68, 0x61, 0x6d, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x73, 0x73, 0x61, 0x6e, 0x74, 0x00, 0xe5, 0x61,
- 0x00, 0x65, 0x02, 0x69, 0x07, 0x6f, 0x47, 0x79, 0x52, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x04, 0x6e, 0x0f, 0x74,
- 0x13, 0x40, 0x07, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x12, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x75, 0x04,
- 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x77, 0x13, 0x00, 0x07, 0xe2, 0x6d, 0x00, 0x6e, 0x08,
- 0x40, 0x07, 0x69, 0x6c, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x0b, 0x66, 0x0f, 0x6e, 0x20, 0x6f, 0x26, 0x70, 0x28, 0x72, 0x2e, 0x73,
- 0x32, 0x74, 0x34, 0x00, 0x2b, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06,
- 0x00, 0x09, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x05, 0x40,
- 0x07, 0x69, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x61, 0x72, 0x64, 0x00, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x6c, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x67, 0x00,
- 0xe4, 0x61, 0x00, 0x64, 0x16, 0x6f, 0x1a, 0x7a, 0x1f, 0xe3, 0x6d, 0x00,
- 0x72, 0x04, 0x74, 0x09, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x69, 0x6e,
- 0x00, 0x40, 0x07, 0x6c, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x6c, 0x61, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x69, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x09, 0x70, 0x0e, 0x00, 0x07, 0x40, 0x07, 0x62,
- 0x61, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x00, 0x40, 0x00, 0x73,
- 0x00, 0xff, 0x41, 0x00, 0x00, 0x42, 0x0f, 0x00, 0x43, 0x16, 0x00, 0x44,
- 0x93, 0x00, 0x45, 0xba, 0x00, 0x46, 0xc1, 0x00, 0x47, 0xd6, 0x00, 0x49,
- 0x01, 0x01, 0x4b, 0x16, 0x01, 0x4c, 0x49, 0x01, 0x4d, 0x6c, 0x01, 0x4e,
- 0x7e, 0x01, 0x50, 0x9b, 0x01, 0x51, 0xa4, 0x01, 0x56, 0xab, 0x01, 0xe2,
- 0x64, 0x00, 0x66, 0x05, 0x40, 0x07, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x65,
- 0x65, 0x00, 0x40, 0x07, 0x72, 0x69, 0x64, 0x65, 0x00, 0xe5, 0x61, 0x00,
- 0x6c, 0x35, 0x6f, 0x4d, 0x72, 0x64, 0x75, 0x69, 0xe4, 0x69, 0x00, 0x6c,
- 0x04, 0x6e, 0x08, 0x72, 0x0c, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6c,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x68, 0x00, 0x6e,
- 0x0f, 0x79, 0x14, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x00,
- 0x07, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x75, 0x0c, 0x40, 0x07, 0x69, 0x6e,
- 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x65,
- 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x07, 0x79, 0x0e, 0x40, 0x07, 0x6e, 0x65,
- 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6d, 0x69, 0x63, 0x6b, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x79, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x6f, 0x75, 0x67,
- 0x68, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6e, 0x69, 0x65,
- 0x6c, 0x00, 0xe2, 0x6e, 0x00, 0x77, 0x10, 0xe2, 0x61, 0x00, 0x6e, 0x05,
- 0x40, 0x07, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x40,
- 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x72, 0x6f, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x06, 0x40, 0x07, 0x64, 0x65,
- 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0xe3, 0x65, 0x00,
- 0x6f, 0x04, 0x75, 0x14, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x76, 0x00, 0x77,
- 0x06, 0x40, 0x07, 0x65, 0x72, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0xe2, 0x66, 0x00, 0x69, 0x06, 0x40, 0x07, 0x66, 0x65, 0x79, 0x00, 0x40,
- 0x07, 0x72, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x6f,
- 0x00, 0x79, 0x05, 0x40, 0x07, 0x73, 0x68, 0x00, 0x40, 0x07, 0x72, 0x65,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x69, 0x11, 0x6e, 0x23, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x7a,
- 0x69, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x05, 0x40,
- 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x69,
- 0x67, 0x68, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x09, 0x75, 0x16, 0x40,
- 0x07, 0x75, 0x67, 0x68, 0x6c, 0x69, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x68,
- 0x61, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x07, 0x68, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x13, 0xe2, 0x6d, 0x00, 0x75, 0x06, 0x40, 0x07, 0x61, 0x72, 0x61,
- 0x00, 0x40, 0x07, 0x67, 0x68, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x69,
- 0x6c, 0x00, 0x40, 0x07, 0x68, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x75, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x69, 0x67, 0x68,
- 0x00, 0x00, 0x07, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39, 0x00, 0x00, 0x00,
- 0x59, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00,
- 0xd0, 0x00, 0xe9, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x9f, 0x01, 0xb0, 0x01,
- 0x00, 0x00, 0x83, 0x02, 0x00, 0x00, 0xa1, 0x02, 0x58, 0x03, 0xcd, 0x03,
- 0x17, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x04, 0x38, 0x04, 0x00, 0x00,
- 0xe3, 0x64, 0x00, 0x67, 0x10, 0x6e, 0x15, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x6f, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x77, 0x73, 0x00, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x63, 0x61,
- 0x00, 0xe5, 0x61, 0x00, 0x65, 0x04, 0x69, 0x11, 0x6c, 0x4a, 0x75, 0x50,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x69, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x0d, 0x6e, 0x21,
- 0x74, 0x25, 0xe2, 0x00, 0x00, 0x57, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69,
- 0x6b, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0d, 0xe2, 0x69, 0x00, 0x72,
- 0x04, 0x40, 0x06, 0x64, 0x00, 0x40, 0x06, 0x65, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x00, 0x40, 0x09, 0x65, 0x72, 0x72, 0x61, 0x6e, 0x65, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x73, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x68, 0x06, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe4, 0x65, 0x00, 0x67, 0x04,
- 0x6a, 0x0a, 0x72, 0x0e, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x68, 0x65,
- 0x6e, 0x00, 0x40, 0x07, 0x69, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x61,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x67, 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02,
- 0x62, 0x20, 0x63, 0x2e, 0x65, 0x44, 0x69, 0x4b, 0x6c, 0x6a, 0x6f, 0x6f,
- 0x70, 0x74, 0x74, 0x7c, 0x76, 0x81, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x12, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x75,
- 0x72, 0x6e, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x7a, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x64, 0x65,
- 0x6b, 0x00, 0x40, 0x07, 0x6e, 0x64, 0x65, 0x7a, 0x00, 0xe2, 0x6e, 0x00,
- 0x73, 0x05, 0x40, 0x07, 0x64, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x0c,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x65, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x64,
- 0x79, 0x00, 0x40, 0x07, 0x6f, 0x6d, 0x65, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x6c,
- 0x00, 0x6e, 0x05, 0x40, 0x07, 0x6c, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x6c,
- 0x00, 0x70, 0x06, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x68,
- 0x69, 0x73, 0x00, 0xec, 0x61, 0x00, 0x63, 0x07, 0x64, 0x16, 0x65, 0x4d,
- 0x67, 0x62, 0x6b, 0x67, 0x6e, 0x7f, 0x6f, 0x8f, 0x73, 0xa0, 0x74, 0xa4,
- 0x75, 0xae, 0x7a, 0xb4, 0x40, 0x07, 0x6e, 0x64, 0x65, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x6b, 0x05, 0x40, 0x07, 0x75, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x23, 0xe2, 0x6c, 0x00, 0x7a, 0x1c,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x73, 0x0c, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x76, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x73,
- 0x6f, 0x68, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x7a, 0x06, 0x40,
- 0x07, 0x69, 0x6e, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x6c, 0x00,
- 0x73, 0x0e, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x75, 0x73, 0x00,
- 0x40, 0x07, 0x6b, 0x00, 0x00, 0x07, 0x40, 0x00, 0x7a, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x0e, 0xe2, 0x6c, 0x00, 0x72, 0x07, 0x40, 0x07, 0x69,
- 0x6e, 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x69,
- 0x74, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x07, 0x40, 0x07, 0x69, 0x6e,
- 0x65, 0x65, 0x00, 0x40, 0x07, 0x74, 0x69, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x68, 0x6f, 0x6c, 0x61, 0x74, 0x75, 0x6d, 0x00, 0x40, 0x07,
- 0x68, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x65, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f,
- 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x00, 0x40, 0x07, 0x68, 0x65,
- 0x6c, 0x65, 0x73, 0x00, 0xe9, 0x61, 0x00, 0x63, 0x04, 0x65, 0x42, 0x69,
- 0x49, 0x6c, 0x4e, 0x6f, 0x5f, 0x72, 0x69, 0x74, 0x8d, 0x76, 0x9f, 0x40,
- 0x07, 0x6b, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x0e, 0x69, 0x1a, 0x6b, 0x1e,
- 0x75, 0x20, 0xe2, 0x64, 0x00, 0x74, 0x04, 0x40, 0x07, 0x6f, 0x00, 0x40,
- 0x07, 0x6f, 0x72, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x05, 0x40, 0x07, 0x65,
- 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0xe1, 0x72,
- 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x68, 0x72, 0x6f,
- 0x6d, 0x65, 0x00, 0x00, 0x06, 0x40, 0x07, 0x64, 0x69, 0x74, 0x68, 0x00,
- 0x40, 0x07, 0x6e, 0x6f, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x06,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07,
- 0x76, 0x69, 0x6e, 0x67, 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe5,
- 0x61, 0x00, 0x63, 0x04, 0x6c, 0x08, 0x6d, 0x0c, 0x74, 0x12, 0x40, 0x07,
- 0x6d, 0x00, 0x40, 0x07, 0x6b, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07,
- 0x61, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe2, 0x68, 0x00, 0x6f,
- 0x09, 0x40, 0x07, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x6d, 0x0b,
- 0x6f, 0x10, 0x73, 0x40, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x69, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe3, 0x6c, 0x00, 0x70,
- 0x08, 0x7a, 0x23, 0x40, 0x07, 0x69, 0x74, 0x68, 0x69, 0x63, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0x40, 0x07, 0x6f, 0x69, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x0b, 0x40, 0x07, 0x72, 0x73, 0x63, 0x68, 0x6d, 0x69, 0x64, 0x74, 0x00,
- 0xe1, 0x61, 0x00, 0xe3, 0x65, 0x00, 0x68, 0x04, 0x6e, 0x0d, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x1b, 0x74, 0x3a, 0xe3,
- 0x63, 0x00, 0x6c, 0x06, 0x6d, 0x0d, 0x40, 0x07, 0x61, 0x66, 0x65, 0x00,
- 0x40, 0x07, 0x6c, 0x69, 0x63, 0x61, 0x00, 0x40, 0x07, 0x75, 0x63, 0x69,
- 0x6c, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x12, 0xe1, 0x64, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x06, 0x00,
- 0x06, 0x40, 0x07, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x6e, 0x69, 0x63, 0x68, 0x00, 0x40, 0x07, 0x73, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x0b, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x69, 0x00, 0x00,
- 0x09, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x62, 0x02, 0x73, 0x08, 0x00, 0x09, 0x40, 0x07, 0x65, 0x65, 0x72, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x75, 0x6d, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xff, 0x47, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x63, 0x19, 0x00, 0x64, 0xdc, 0x00, 0x67, 0x29, 0x01, 0x6b, 0x2f, 0x01,
- 0x6c, 0x44, 0x01, 0x6d, 0x02, 0x02, 0x6e, 0x0e, 0x02, 0x6f, 0xc6, 0x02,
- 0x72, 0xcd, 0x02, 0x73, 0x07, 0x03, 0x74, 0x77, 0x03, 0x78, 0xce, 0x03,
- 0x7a, 0xd4, 0x03, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x70, 0x06,
- 0x00, 0x07, 0x40, 0x09, 0x69, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x63, 0x69,
- 0x64, 0x75, 0x73, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x0d, 0x6b, 0x7b, 0x6d,
- 0x90, 0x72, 0x95, 0xe2, 0x68, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x62, 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x14, 0x69,
- 0x49, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x6c, 0x04, 0x40, 0x07, 0x6c, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x0a, 0x69, 0x0c, 0x6c, 0x10, 0x6f, 0x14, 0x73, 0x18, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x62, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x64, 0x02, 0x69, 0x07, 0x00, 0x07, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0x40, 0x00, 0x74, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x79, 0x0a, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x61, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x6e, 0x00, 0x73, 0x15, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x66, 0x74, 0x00, 0xe5, 0x61, 0x00, 0x64, 0x04,
- 0x65, 0x0c, 0x6c, 0x21, 0x77, 0x27, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07,
- 0x6c, 0x65, 0x74, 0x6f, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x72, 0x6e, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x0e, 0x72, 0x6e, 0x00,
- 0x40, 0x07, 0x75, 0x65, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x68, 0x02, 0x6f,
- 0x08, 0x00, 0x07, 0x40, 0x07, 0x61, 0x69, 0x6c, 0x00, 0x40, 0x07, 0x79,
- 0x61, 0x6e, 0x00, 0xeb, 0x61, 0x00, 0x64, 0x17, 0x65, 0x1d, 0x66, 0x21,
- 0x6b, 0x27, 0x6c, 0x2c, 0x6e, 0x63, 0x6f, 0x67, 0x71, 0x75, 0x74, 0x7f,
- 0x77, 0x9f, 0xe2, 0x67, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x72, 0x6f, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x65,
- 0x00, 0x40, 0x07, 0x72, 0x65, 0x64, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x07, 0x6f, 0x72, 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x0d, 0x69, 0x16, 0x73, 0x2a, 0x00, 0x2b, 0xe2,
- 0x72, 0x00, 0x79, 0x04, 0x40, 0x07, 0x64, 0x00, 0x00, 0x07, 0xe2, 0x72,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x63, 0x00, 0x65, 0x06,
- 0x6b, 0x08, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x76, 0x69, 0x63, 0x00, 0x40,
- 0x07, 0x75, 0x65, 0x74, 0x6f, 0x61, 0x73, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x07, 0x40, 0x07, 0x61, 0x64, 0x65, 0x73, 0x00, 0xe2, 0x6e, 0x00,
- 0x77, 0x0b, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x63,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x75, 0x6b, 0x65, 0x65,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x61,
- 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x64, 0x09, 0x65, 0x1d, 0x67, 0x23,
- 0x6e, 0x2e, 0x6f, 0x61, 0x73, 0x81, 0x74, 0x8d, 0x75, 0x93, 0x00, 0x07,
- 0x40, 0x07, 0x6d, 0x6f, 0x74, 0x6f, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x06,
- 0x79, 0x0b, 0x40, 0x07, 0x6e, 0x61, 0x6f, 0x00, 0x40, 0x07, 0x72, 0x6f,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x72, 0x76, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x28, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x08, 0x73, 0x0d,
- 0x40, 0x07, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x00, 0x40, 0x07, 0x6c, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00, 0xe4,
- 0x61, 0x00, 0x6c, 0x04, 0x73, 0x09, 0x74, 0x0b, 0x40, 0x09, 0x6e, 0x00,
- 0x40, 0x07, 0x74, 0x61, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x75, 0x72, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6b, 0x61,
- 0x00, 0xe2, 0x69, 0x00, 0x74, 0x04, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07,
- 0x65, 0x6d, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x63, 0x65, 0x6e, 0x65, 0x00,
- 0xe6, 0x00, 0x00, 0x61, 0x02, 0x66, 0x1c, 0x69, 0x21, 0x6f, 0x26, 0x7a,
- 0x28, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x6e, 0x0c,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x61, 0x75, 0x00, 0x40, 0x07, 0x68, 0x00,
- 0x40, 0x07, 0x64, 0x61, 0x00, 0x40, 0x07, 0x61, 0x6b, 0x00, 0x40, 0x07,
- 0x61, 0x6d, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6d, 0x00, 0xe3, 0x6b,
- 0x00, 0x73, 0x06, 0x74, 0x4c, 0x40, 0x07, 0x69, 0x74, 0x6f, 0x00, 0xe4,
- 0x00, 0x00, 0x69, 0x02, 0x6f, 0x27, 0x79, 0x3b, 0x00, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x07, 0x75,
- 0x67, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x07, 0xe4, 0x61, 0x00,
- 0x65, 0x08, 0x72, 0x0c, 0x79, 0x12, 0x40, 0x07, 0x73, 0x73, 0x69, 0x6e,
- 0x69, 0x00, 0x40, 0x00, 0x72, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x07, 0xe6, 0x63, 0x00, 0x66, 0x16, 0x68, 0x1c, 0x73, 0x2e, 0x74,
- 0x37, 0x7a, 0x46, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x72, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x61, 0x74, 0x65, 0x73,
- 0x00, 0x40, 0x07, 0x75, 0x62, 0x69, 0x73, 0x68, 0x69, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x08, 0x40, 0x07, 0x72, 0x72, 0x61, 0x6e, 0x64, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x74, 0x65, 0x63, 0x00, 0x40,
- 0x07, 0x61, 0x72, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x40,
- 0x08, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6d, 0x6f, 0x73, 0x79, 0x6e, 0x65, 0x00, 0xc1, 0x62, 0x19, 0x37, 0x00,
- 0x39, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x63, 0x00, 0x00, 0x00, 0x6c, 0x00,
- 0x7d, 0x00, 0xda, 0x00, 0xf2, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x69, 0x01,
- 0x70, 0x01, 0x0e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x38, 0x03, 0x0d, 0x04,
- 0x43, 0x04, 0x6b, 0x04, 0x00, 0x00, 0xa9, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0xaf, 0x04, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x75, 0x0c, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x74,
- 0x75, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07, 0x73, 0x74, 0x6f,
- 0x00, 0x40, 0x07, 0x67, 0x6c, 0x69, 0x61, 0x6e, 0x69, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x75, 0x08,
- 0x40, 0x07, 0x64, 0x69, 0x73, 0x68, 0x75, 0x00, 0x40, 0x09, 0x6c, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x40, 0x6f, 0x46, 0xe4, 0x63, 0x00, 0x6d, 0x04,
- 0x76, 0x2f, 0x77, 0x33, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6d,
- 0x04, 0x40, 0x07, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x64, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06,
- 0x73, 0x6d, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x6b, 0x00, 0x40,
- 0x00, 0x67, 0x61, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x76, 0x69, 0x63, 0x69, 0x63, 0x00, 0xe2, 0x72, 0x00,
- 0x73, 0x04, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x76, 0x00, 0x40, 0x06, 0x61,
- 0x76, 0x65, 0x00, 0xe6, 0x64, 0x00, 0x69, 0x26, 0x6c, 0x34, 0x6e, 0x43,
- 0x6f, 0x48, 0x75, 0x5d, 0xe2, 0x61, 0x00, 0x6f, 0x12, 0xe1, 0x76, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x05, 0x40,
- 0x07, 0x72, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x72, 0x00, 0xe3, 0x63, 0x00, 0x6b, 0x04, 0x74, 0x09, 0x40,
- 0x07, 0x68, 0x00, 0x40, 0x07, 0x61, 0x69, 0x00, 0x40, 0x07, 0x6f, 0x76,
- 0x00, 0x40, 0x07, 0x63, 0x63, 0x61, 0x73, 0x00, 0x40, 0x07, 0x62, 0x61,
- 0x73, 0x61, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x64, 0x14,
- 0x00, 0x65, 0x2a, 0x00, 0x67, 0x3f, 0x00, 0x69, 0x63, 0x00, 0x6b, 0x71,
- 0x00, 0x6d, 0x73, 0x00, 0x6f, 0x7a, 0x00, 0x72, 0x84, 0x00, 0x73, 0x93,
- 0x00, 0x74, 0xa5, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00,
- 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x72, 0x0b, 0xe2, 0x6c, 0x00, 0x79, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x06, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00, 0xe3, 0x67,
- 0x00, 0x72, 0x08, 0x74, 0x0c, 0x40, 0x06, 0x61, 0x73, 0x71, 0x75, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x12, 0x00, 0x06, 0xe2, 0x61,
- 0x00, 0x63, 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0x00, 0x07, 0x40, 0x00, 0x69, 0x64, 0x00, 0xe2, 0x63, 0x00, 0x71, 0x04,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x75, 0x65, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x6f, 0x75, 0x74, 0x68, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x61, 0x68,
- 0x65, 0x6c, 0x61, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x76, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x69, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06,
- 0x40, 0x07, 0x6e, 0x74, 0x6f, 0x00, 0x40, 0x06, 0x67, 0x6e, 0x6f, 0x72,
- 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x63, 0x20, 0x65, 0x26, 0x67, 0x78,
- 0x69, 0x8d, 0x6f, 0x95, 0x70, 0x9a, 0x72, 0xa2, 0x73, 0xb3, 0x79, 0xbb,
- 0x00, 0x07, 0xe3, 0x67, 0x00, 0x69, 0x05, 0x6e, 0x0b, 0x40, 0x07, 0x75,
- 0x65, 0x00, 0x40, 0x07, 0x67, 0x6e, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x61, 0x6c,
- 0x6d, 0x00, 0xe6, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x16, 0x73, 0x1c, 0x76,
- 0x2e, 0x7a, 0x3f, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x65, 0x79, 0x00, 0xe2, 0x71, 0x00, 0x73, 0x07,
- 0x40, 0x07, 0x75, 0x69, 0x65, 0x75, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x69,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07, 0x72, 0x64, 0x69, 0x00,
- 0x40, 0x07, 0x64, 0x65, 0x6f, 0x00, 0x40, 0x07, 0x75, 0x6d, 0x61, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x6c, 0x00, 0x6d, 0x07, 0x40, 0x07, 0x66, 0x69,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x79, 0x00, 0x40, 0x07, 0x63,
- 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x40, 0x07, 0x79, 0x61, 0x00, 0x40, 0x07,
- 0x65, 0x6c, 0x69, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x63, 0x68, 0x65, 0x74, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x00, 0x40,
- 0x07, 0x65, 0x72, 0x72, 0x61, 0x74, 0x00, 0x00, 0x07, 0xe4, 0x64, 0x00,
- 0x67, 0x04, 0x6e, 0x06, 0x72, 0x11, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07,
- 0x73, 0x68, 0x00, 0xec, 0x61, 0x00, 0x64, 0x1d, 0x65, 0x23, 0x67, 0x2e,
- 0x69, 0x33, 0x6c, 0x4d, 0x6d, 0x52, 0x6f, 0x64, 0x70, 0x7f, 0x72, 0x8e,
- 0x73, 0xa5, 0x74, 0xa9, 0xe3, 0x6c, 0x00, 0x6e, 0x05, 0x76, 0x07, 0x40,
- 0x07, 0x65, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x72,
- 0x65, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6f, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x6e, 0x06,
- 0x73, 0x08, 0x74, 0x0d, 0x40, 0x07, 0x72, 0x74, 0x79, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x65,
- 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0x40, 0x06, 0x73, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x63,
- 0x02, 0x6e, 0x10, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x04, 0x40, 0x06, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x05, 0x40, 0x07, 0x75, 0x73, 0x00,
- 0x00, 0x07, 0xe2, 0x69, 0x00, 0x6f, 0x0e, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x77,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x08,
- 0x00, 0x07, 0x40, 0x07, 0x6d, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe6, 0x61, 0x00, 0x63, 0x05, 0x65, 0x0a, 0x6c, 0x1e, 0x73, 0x23, 0x75,
- 0x25, 0x40, 0x07, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6f, 0x77, 0x00, 0xe2,
- 0x6c, 0x00, 0x73, 0x0d, 0xe2, 0x65, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x79, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0xe3, 0x6f, 0x00, 0x72, 0x1a, 0x74,
- 0x1f, 0xe2, 0x72, 0x00, 0x77, 0x11, 0xe2, 0x6f, 0x00, 0x73, 0x05, 0x40,
- 0x07, 0x6c, 0x61, 0x00, 0x40, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x00, 0x07, 0xe4, 0x6c,
- 0x00, 0x6e, 0x06, 0x73, 0x1e, 0x74, 0x28, 0x40, 0x07, 0x74, 0x6f, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x69, 0x0a, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x00, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x07, 0x73, 0x6f, 0x72, 0x67, 0x73, 0x6b, 0x79, 0x00, 0xe2,
- 0x68, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x67, 0x6c, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x1e, 0xe2,
- 0x6d, 0x00, 0x72, 0x15, 0xe1, 0x62, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63,
- 0x00, 0x71, 0x05, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x65,
- 0x00, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x00, 0x00,
- 0x06, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08, 0x40, 0x00, 0x72, 0x00,
- 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x62, 0x07, 0x00, 0x65, 0x0e, 0x00,
- 0x67, 0x20, 0x00, 0x68, 0x26, 0x00, 0x69, 0x4b, 0x00, 0x6a, 0x4f, 0x00,
- 0x6c, 0x54, 0x00, 0x6d, 0x9a, 0x00, 0x6e, 0xaa, 0x00, 0x70, 0xda, 0x00,
- 0x72, 0xe0, 0x00, 0x73, 0x4b, 0x01, 0x74, 0xa2, 0x01, 0x7a, 0xab, 0x01,
- 0x40, 0x07, 0x77, 0x69, 0x79, 0x61, 0x00, 0x40, 0x07, 0x61, 0x72, 0x61,
- 0x6b, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x6c, 0x65, 0x72,
- 0x00, 0x40, 0x09, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x62,
- 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x6d, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06,
- 0x73, 0x6d, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x69, 0x62, 0x00,
- 0xe4, 0x64, 0x00, 0x6c, 0x05, 0x72, 0x28, 0x74, 0x2f, 0x40, 0x07, 0x65,
- 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x6e, 0x00, 0x72, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe3, 0x67, 0x00, 0x6b, 0x05, 0x6e, 0x0a, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x63, 0x73, 0x00, 0xe2, 0x62,
- 0x00, 0x66, 0x05, 0x40, 0x07, 0x61, 0x69, 0x00, 0x40, 0x07, 0x6f, 0x72,
- 0x64, 0x00, 0xe5, 0x63, 0x00, 0x69, 0x12, 0x6f, 0x17, 0x72, 0x1b, 0x73,
- 0x1f, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x75, 0x73, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x63, 0x68, 0x00,
- 0x40, 0x07, 0x7a, 0x00, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x74, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x70, 0x65, 0x74, 0x00, 0xe7, 0x61, 0x00, 0x63,
- 0x0d, 0x64, 0x1d, 0x69, 0x23, 0x6d, 0x37, 0x70, 0x3e, 0x72, 0x43, 0xe2,
- 0x73, 0x00, 0x74, 0x06, 0x40, 0x07, 0x61, 0x6b, 0x69, 0x00, 0x00, 0x07,
- 0xe2, 0x68, 0x00, 0x69, 0x07, 0x40, 0x07, 0x69, 0x73, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x63, 0x68, 0x00, 0xe3, 0x65,
- 0x00, 0x6c, 0x04, 0x6e, 0x09, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x6c,
- 0x6f, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x73, 0x6b,
- 0x00, 0x40, 0x07, 0x68, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x04, 0x75,
- 0x08, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x77, 0x00, 0x40, 0x07, 0x6d,
- 0x62, 0x69, 0x64, 0x67, 0x65, 0x65, 0x00, 0xe7, 0x63, 0x00, 0x65, 0x18,
- 0x68, 0x1a, 0x69, 0x22, 0x6b, 0x27, 0x6c, 0x2e, 0x73, 0x33, 0xe2, 0x61,
- 0x00, 0x6f, 0x04, 0x40, 0x07, 0x74, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x05, 0x40, 0x07, 0x74, 0x65, 0x00, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x72, 0x72, 0x61, 0x66, 0x00, 0x40, 0x07, 0x61, 0x6c,
- 0x00, 0x40, 0x07, 0x6f, 0x67, 0x65, 0x65, 0x00, 0x40, 0x09, 0x69, 0x6d,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x06, 0x40, 0x07, 0x69,
- 0x6e, 0x69, 0x00, 0x40, 0x07, 0x67, 0x73, 0x6b, 0x79, 0x00, 0x40, 0x07,
- 0x73, 0x75, 0x68, 0x69, 0x74, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6b, 0x00, 0x00, 0x07, 0xe9, 0x43, 0x00, 0x53, 0x0f, 0x59,
- 0x1e, 0x61, 0x25, 0x63, 0x2c, 0x65, 0x43, 0x6c, 0x48, 0x72, 0x55, 0x73,
- 0x74, 0x40, 0x07, 0x61, 0x72, 0x65, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x65, 0x72, 0x00, 0xe2, 0x51, 0x00, 0x70, 0x04, 0x40, 0x07, 0x4c,
- 0x00, 0x40, 0x07, 0x61, 0x63, 0x65, 0x00, 0x40, 0x07, 0x61, 0x68, 0x6f,
- 0x6f, 0x00, 0x40, 0x07, 0x6e, 0x6d, 0x61, 0x72, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe5, 0x61, 0x00, 0x64, 0x02, 0x6e, 0x07, 0x6f, 0x0b, 0x74,
- 0x0f, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe3, 0x6f, 0x00,
- 0x70, 0x05, 0x74, 0x0b, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x07, 0x61,
- 0x63, 0x65, 0x00, 0x00, 0x07, 0xc1, 0x27, 0x53, 0xab, 0x00, 0xad, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xb7, 0x00, 0xe1, 0x00, 0xf2, 0x00, 0x01, 0x01, 0x03, 0x01,
- 0x0c, 0x01, 0x19, 0x01, 0x1e, 0x01, 0x27, 0x01, 0x33, 0x01, 0x00, 0x00,
- 0x35, 0x01, 0x3a, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x48, 0x01, 0x00, 0x00,
- 0x51, 0x01, 0x5e, 0x01, 0x6f, 0x01, 0x00, 0x00, 0x71, 0x01, 0x73, 0x01,
- 0x00, 0x00, 0x7c, 0x01, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x01, 0x2e, 0x04, 0x00, 0x00,
- 0x30, 0x04, 0x3f, 0x04, 0x00, 0x00, 0xdc, 0x06, 0x00, 0x00, 0xef, 0x06,
- 0x00, 0x00, 0xe6, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x08,
- 0x3f, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0b,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0b, 0x00, 0x20, 0x40, 0x00,
- 0x44, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x00, 0xe4, 0x41, 0x00, 0x46,
- 0x05, 0x53, 0x0a, 0x54, 0x1d, 0x40, 0x07, 0x43, 0x50, 0x00, 0x40, 0x07,
- 0x54, 0x41, 0x00, 0xe3, 0x41, 0x00, 0x43, 0x02, 0x44, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x41, 0x52, 0x00, 0x40, 0x07, 0x41, 0x51, 0x00, 0x40, 0x07,
- 0x4f, 0x00, 0xe4, 0x00, 0x00, 0x41, 0x02, 0x43, 0x04, 0x53, 0x06, 0x00,
- 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x41, 0x02,
- 0x4f, 0x06, 0x00, 0x00, 0x40, 0x07, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x48, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe3, 0x00, 0x00,
- 0x43, 0x02, 0x4c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x4f, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x00, 0x07,
- 0xe2, 0x48, 0x00, 0x4d, 0x02, 0x00, 0x00, 0x40, 0x00, 0x42, 0x59, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x52, 0x42, 0x00, 0x00, 0x00, 0xe2, 0x52, 0x00,
- 0x57, 0x05, 0x40, 0x07, 0x41, 0x44, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x52, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x41, 0x02, 0x43,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x41, 0x02,
- 0x43, 0x04, 0x46, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x54, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0xe3, 0x00, 0x00, 0x43, 0x02, 0x53, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x45, 0x00, 0x00, 0x00, 0xc1, 0x62, 0x19, 0x37, 0x00, 0x39,
- 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x7e,
- 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0xcd,
- 0x00, 0x1e, 0x01, 0x23, 0x01, 0x00, 0x00, 0x60, 0x01, 0xa1, 0x01, 0xce,
- 0x01, 0x2c, 0x02, 0x46, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
- 0x02, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x73, 0x63,
- 0x6f, 0x00, 0x40, 0x07, 0x6b, 0x6f, 0x76, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x04, 0x75, 0x0f, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x6f,
- 0x07, 0x70, 0x0c, 0x79, 0x11, 0x40, 0x07, 0x73, 0x61, 0x6b, 0x69, 0x00,
- 0x40, 0x07, 0x79, 0x61, 0x00, 0x40, 0x07, 0x75, 0x72, 0x00, 0x00, 0x07,
- 0xe1, 0x75, 0x00, 0xe2, 0x61, 0x00, 0x6d, 0x05, 0x40, 0x09, 0x74, 0x6c,
- 0x00, 0x00, 0x07, 0xe3, 0x70, 0x00, 0x72, 0x06, 0x73, 0x12, 0x40, 0x07,
- 0x61, 0x75, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x62, 0x69, 0x00, 0x40, 0x07, 0x6d, 0x69, 0x74, 0x68, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x07, 0x40, 0x07, 0x74, 0x68,
- 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe9, 0x00, 0x00, 0x61, 0x02,
- 0x63, 0x06, 0x65, 0x13, 0x6a, 0x19, 0x6e, 0x1f, 0x6f, 0x24, 0x73, 0x29,
- 0x74, 0x2e, 0x00, 0x07, 0x40, 0x07, 0x6b, 0x00, 0xe2, 0x68, 0x00, 0x79,
- 0x06, 0x40, 0x07, 0x61, 0x6e, 0x67, 0x00, 0x00, 0x07, 0x40, 0x07, 0x74,
- 0x74, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x69,
- 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6b, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x75, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x63,
- 0x6b, 0x65, 0x74, 0x00, 0x40, 0x07, 0x6d, 0x69, 0x00, 0xe6, 0x61, 0x00,
- 0x68, 0x02, 0x69, 0x09, 0x6c, 0x0e, 0x6f, 0x13, 0x73, 0x2a, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x61, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x07, 0x63, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00, 0xe5, 0x63,
- 0x00, 0x6d, 0x08, 0x6e, 0x0e, 0x72, 0x13, 0x75, 0x31, 0x40, 0x07, 0x69,
- 0x73, 0x73, 0x75, 0x73, 0x00, 0x40, 0x07, 0x61, 0x64, 0x61, 0x00, 0x40,
- 0x07, 0x69, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x74, 0x6f, 0x00, 0xe3, 0x64, 0x00, 0x68, 0x05, 0x73, 0x19, 0x40, 0x07,
- 0x61, 0x71, 0x00, 0xe3, 0x00, 0x00, 0x75, 0x02, 0x76, 0x06, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x75, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0xe6, 0x00, 0x00, 0x61, 0x02, 0x63, 0x18, 0x65, 0x1e, 0x68, 0x20, 0x69,
- 0x36, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x73, 0x0c, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x68, 0x61,
- 0x00, 0x40, 0x07, 0x68, 0x65, 0x7a, 0x00, 0x00, 0x14, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x06,
- 0x40, 0x07, 0x65, 0x6c, 0x00, 0x00, 0x07, 0xe2, 0x6f, 0x00, 0x76, 0x10,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x69, 0x64, 0x65, 0x00, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0xe3, 0x67,
- 0x00, 0x72, 0x08, 0x74, 0x0c, 0x40, 0x07, 0x61, 0x68, 0x79, 0x64, 0x65,
- 0x00, 0x40, 0x07, 0x75, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x75, 0x73, 0x00,
- 0xe3, 0x61, 0x00, 0x72, 0x1f, 0x79, 0x29, 0xe2, 0x6a, 0x00, 0x72, 0x0e,
- 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6c, 0x6f, 0x76, 0x61, 0x00,
- 0x00, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x13, 0x69, 0x17, 0xe1, 0x72, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x6d, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x6a, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x00,
- 0xc1, 0x57, 0x22, 0x49, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x59, 0x00, 0x75, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xb3,
- 0x00, 0xbc, 0x00, 0xed, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x01, 0x28, 0x01, 0x00, 0x00, 0x3a, 0x01, 0x4d, 0x01, 0x00, 0x00, 0x6b,
- 0x01, 0x82, 0x01, 0xb0, 0x01, 0xff, 0x01, 0x05, 0x02, 0x33, 0x02, 0x88,
- 0x02, 0x00, 0x07, 0xe1, 0x53, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x02, 0x70, 0x0c,
- 0x00, 0x07, 0x40, 0x06, 0x64, 0x65, 0x72, 0x74, 0x68, 0x61, 0x6c, 0x00,
- 0x40, 0x07, 0x6f, 0x6c, 0x69, 0x74, 0x61, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x72, 0x02, 0x75, 0x1b, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x6b, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x63, 0x68, 0x61,
- 0x64, 0x6e, 0x65, 0x7a, 0x7a, 0x61, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0x40,
- 0x07, 0x65, 0x72, 0x74, 0x69, 0x74, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x72,
- 0x04, 0x40, 0x07, 0x76, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x6f, 0x0c,
- 0x40, 0x09, 0x73, 0x73, 0x00, 0x40, 0x00, 0x74, 0x75, 0x64, 0x65, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x73, 0x0a, 0x00, 0x09, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x06, 0x64, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00,
- 0x72, 0x07, 0x40, 0x07, 0x6d, 0x69, 0x61, 0x68, 0x00, 0x40, 0x07, 0x75,
- 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe3, 0x64, 0x00, 0x6c, 0x04, 0x73, 0x13,
- 0x40, 0x07, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x06, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6f, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x62, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x75, 0x74, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x69,
- 0x73, 0x00, 0xe2, 0x67, 0x00, 0x6c, 0x06, 0x40, 0x07, 0x65, 0x6e, 0x65,
- 0x00, 0x40, 0x00, 0x69, 0x74, 0x68, 0x69, 0x63, 0x00, 0xe2, 0x61, 0x00,
- 0x74, 0x13, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0x00, 0x09, 0x40, 0x07, 0x75,
- 0x6e, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x66, 0x05, 0x6f, 0x07, 0x75, 0x09,
- 0x40, 0x07, 0x69, 0x64, 0x00, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x64,
- 0x61, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x06, 0x74, 0x0f, 0x40, 0x07, 0x61,
- 0x66, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x72, 0x6f, 0x64, 0x65, 0x00,
- 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x75, 0x73, 0x00,
- 0xe6, 0x42, 0x00, 0x66, 0x05, 0x68, 0x0b, 0x73, 0x28, 0x74, 0x2f, 0x7a,
- 0x34, 0x40, 0x07, 0x53, 0x44, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x78, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0x00, 0x07, 0x40, 0x07, 0x63, 0x61, 0x70, 0x65, 0x00,
- 0x40, 0x07, 0x69, 0x65, 0x00, 0x40, 0x07, 0x61, 0x68, 0x75, 0x61, 0x6c,
- 0x63, 0x6f, 0x79, 0x6f, 0x74, 0x6c, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x6c,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x1c, 0x73, 0x20, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x69, 0x09,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x00, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x6b, 0x79, 0x00, 0xe7,
- 0x61, 0x00, 0x63, 0x05, 0x66, 0x0d, 0x6d, 0x18, 0x70, 0x1d, 0x73, 0x23,
- 0x74, 0x34, 0x40, 0x07, 0x72, 0x6b, 0x00, 0x40, 0x07, 0x61, 0x73, 0x74,
- 0x6c, 0x65, 0x00, 0x40, 0x1f, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e,
- 0x64, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x74,
- 0x00, 0xe2, 0x76, 0x00, 0x77, 0x06, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x65, 0x6b, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0xe3, 0x54, 0x00, 0x69, 0x05, 0x74, 0x09, 0x40, 0x07, 0x61, 0x67, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00, 0xe2, 0x61, 0x00,
- 0x75, 0x08, 0x40, 0x07, 0x6c, 0x69, 0x65, 0x6d, 0x61, 0x00, 0x40, 0x07,
- 0x79, 0x65, 0x6e, 0x00, 0xc1, 0x61, 0x18, 0x35, 0x00, 0x37, 0x00, 0x47,
- 0x00, 0x4f, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x1d, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x4c, 0x01, 0x54, 0x01, 0x7b, 0x01, 0x7f, 0x01, 0x8e,
- 0x01, 0xa4, 0x01, 0xa9, 0x01, 0x00, 0x00, 0xbe, 0x01, 0xd1, 0x01, 0xe5,
- 0x01, 0xe9, 0x01, 0xed, 0x01, 0x00, 0x00, 0xf2, 0x01, 0x00, 0x07, 0xe2,
- 0x67, 0x00, 0x6d, 0x06, 0x40, 0x07, 0x61, 0x72, 0x61, 0x00, 0x40, 0x07,
- 0x65, 0x79, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x75, 0x6e, 0x67, 0x00, 0xe6,
- 0x61, 0x00, 0x63, 0x1e, 0x65, 0x24, 0x68, 0x2f, 0x6b, 0x55, 0x6f, 0x75,
- 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6c, 0x6f, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x72, 0x65, 0x6e, 0x00, 0xe1, 0x6c,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x73, 0x06, 0x40, 0x07, 0x73, 0x00,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x0b, 0x6f, 0x11, 0x00, 0x07,
- 0x40, 0x07, 0x6c, 0x6f, 0x64, 0x65, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61,
- 0x75, 0x73, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x73, 0x00, 0xe4, 0x62, 0x00,
- 0x64, 0x05, 0x6c, 0x0c, 0x73, 0x1c, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40,
- 0x07, 0x65, 0x6d, 0x75, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x09, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x69, 0x61, 0x00, 0xe4, 0x62, 0x00, 0x6c, 0x06, 0x74, 0x0c, 0x76, 0x14,
- 0x40, 0x07, 0x75, 0x68, 0x72, 0x00, 0x40, 0x07, 0x73, 0x65, 0x6e, 0x00,
- 0x40, 0x07, 0x7a, 0x73, 0x63, 0x68, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x68, 0x20, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65,
- 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x74, 0x69, 0x6e, 0x67, 0x61, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x69, 0x6e, 0x73, 0x6b, 0x79, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x02, 0x6b, 0x07, 0x6f, 0x12, 0x00, 0x07, 0x40, 0x07, 0x74, 0x61, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x69, 0x00, 0x00, 0x07, 0xe2,
- 0x6c, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x61, 0x69, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40, 0x07, 0x74, 0x7a,
- 0x00, 0x40, 0x07, 0x6f, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x74,
- 0x08, 0x00, 0x07, 0x40, 0x07, 0x76, 0x65, 0x68, 0x00, 0x40, 0x07, 0x65,
- 0x6e, 0x64, 0x6f, 0x00, 0x40, 0x07, 0x62, 0x65, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x76, 0x08, 0x40,
- 0x07, 0x6e, 0x62, 0x65, 0x72, 0x67, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x61,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x73, 0x08, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x61, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x75, 0x6d, 0x61, 0x68, 0x00, 0xc1,
- 0x44, 0x36, 0x71, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x78, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00,
- 0xb1, 0x00, 0xbd, 0x00, 0xc1, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xcb, 0x00, 0xb5, 0x01, 0xcc, 0x01, 0xd6, 0x01, 0xe9, 0x01, 0x00, 0x00,
- 0x3d, 0x02, 0x44, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x7a, 0x00, 0x40,
- 0x07, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x0f, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x0d, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x07, 0x69, 0x00, 0x40, 0x07, 0x69, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x74, 0x6b, 0x61, 0x00, 0xec, 0x61,
- 0x00, 0x62, 0x02, 0x64, 0x14, 0x65, 0x19, 0x66, 0x1e, 0x69, 0x24, 0x6d,
- 0x2a, 0x70, 0x44, 0x72, 0x4b, 0x73, 0x50, 0x74, 0x6b, 0x77, 0xb6, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x09, 0x69, 0x63, 0x00,
- 0x40, 0x07, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x6b, 0x00, 0x40,
- 0x07, 0x65, 0x67, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x09, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x61, 0x6e,
- 0x74, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6b, 0x14,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x65,
- 0x00, 0x68, 0x04, 0x6f, 0x40, 0x40, 0x07, 0x6c, 0x00, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x0a, 0x72, 0x1a, 0x73, 0x27, 0x77, 0x29, 0x00, 0x07,
- 0x40, 0x07, 0x6d, 0x70, 0x74, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x72,
- 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x72, 0x00,
- 0xe2, 0x6f, 0x00, 0x75, 0x04, 0x40, 0x07, 0x70, 0x00, 0x40, 0x07, 0x70,
- 0x00, 0x00, 0x00, 0x40, 0x06, 0x65, 0x73, 0x74, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x69, 0x0d, 0x00, 0x00,
- 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x67, 0x69, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x63, 0x68, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x08, 0x40, 0x07, 0x65,
- 0x72, 0x61, 0x74, 0x75, 0x00, 0x40, 0x07, 0x72, 0x61, 0x64, 0x61, 0x6d,
- 0x75, 0x73, 0x00, 0x40, 0x07, 0x74, 0x69, 0x6e, 0x67, 0x68, 0x61, 0x6d,
- 0x00, 0xe2, 0x61, 0x00, 0x6d, 0x09, 0x40, 0x07, 0x6b, 0x63, 0x68, 0x6f,
- 0x74, 0x74, 0x00, 0x40, 0x07, 0x65, 0x61, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x0f, 0x67, 0x16, 0x6f, 0x1d, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x69, 0x73, 0x00, 0x40, 0x09,
- 0x6d, 0x62, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6f, 0x64, 0x00,
- 0xe3, 0x63, 0x00, 0x6b, 0x12, 0x73, 0x1c, 0xe1, 0x61, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x00,
- 0x00, 0x40, 0x07, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x00, 0x40,
- 0x07, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x00, 0x40, 0x07, 0x7a, 0x65,
- 0x6d, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x65, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0xe6, 0x62, 0x00, 0x6b, 0x0f, 0x6d,
- 0x18, 0x6e, 0x1f, 0x72, 0x34, 0x74, 0x48, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x75, 0x61, 0x6c, 0x6f, 0x66, 0x61, 0x00, 0x40, 0x07, 0x62, 0x65, 0x72,
- 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x6b, 0x0a, 0x40, 0x07, 0x76,
- 0x75, 0x74, 0x00, 0x40, 0x07, 0x7a, 0x00, 0x40, 0x07, 0x69, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x79, 0x07, 0x40, 0x07, 0x62, 0x65, 0x72,
- 0x67, 0x00, 0x40, 0x07, 0x65, 0x76, 0x00, 0x40, 0x07, 0x72, 0x61, 0x53,
- 0x77, 0x65, 0x65, 0x74, 0x00, 0xe3, 0x51, 0x00, 0x61, 0x06, 0x65, 0x0b,
- 0x40, 0x07, 0x75, 0x69, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x61, 0x00, 0x40,
- 0x07, 0x72, 0x65, 0x72, 0x65, 0x00, 0xc1, 0x27, 0x54, 0xad, 0x00, 0xaf,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x2a, 0x01, 0x2e, 0x01, 0x30, 0x01, 0x34, 0x01, 0x36,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x4c,
- 0x01, 0x00, 0x00, 0x4e, 0x01, 0x52, 0x01, 0x00, 0x00, 0x54, 0x01, 0x00,
- 0x00, 0x59, 0x01, 0x5b, 0x01, 0x6c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xa8, 0x01, 0xdd,
- 0x01, 0x4b, 0x02, 0x8d, 0x02, 0xac, 0x02, 0xcc, 0x02, 0xf3, 0x02, 0x04,
- 0x03, 0x09, 0x03, 0x10, 0x03, 0x7e, 0x03, 0x60, 0x04, 0x9d, 0x04, 0xfe,
- 0x04, 0x03, 0x05, 0x00, 0x00, 0x5d, 0x05, 0x8c, 0x06, 0x21, 0x07, 0x49,
- 0x07, 0x5e, 0x07, 0x63, 0x07, 0x72, 0x07, 0x00, 0x00, 0xa4, 0x07, 0x00,
- 0x06, 0xe8, 0x42, 0x00, 0x43, 0x07, 0x44, 0x26, 0x48, 0x2f, 0x4b, 0x41,
- 0x4e, 0x49, 0x52, 0x5b, 0x54, 0x63, 0x40, 0x07, 0x72, 0x69, 0x65, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x73, 0x65, 0x79, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40,
- 0x07, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x6e,
- 0x6e, 0x65, 0x6c, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07,
- 0x72, 0x61, 0x00, 0x40, 0x07, 0x67, 0x67, 0x69, 0x6e, 0x73, 0x00, 0x40,
- 0x07, 0x65, 0x65, 0x66, 0x66, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x75, 0x72, 0x6b, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x53, 0x00, 0x00, 0x00, 0x40, 0x00,
- 0x52, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x44, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x53, 0x02, 0x00, 0x00, 0x40, 0x07, 0x41, 0x00,
- 0x00, 0x00, 0x00, 0x2c, 0x40, 0x07, 0x42, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x45, 0x43, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x48, 0x02, 0x65, 0x06,
- 0x00, 0x07, 0x40, 0x07, 0x41, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe4, 0x00,
- 0x00, 0x42, 0x02, 0x43, 0x04, 0x4f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x00, 0x48, 0x00, 0xe4, 0x68, 0x00, 0x6b, 0x04, 0x74, 0x15,
- 0x78, 0x1a, 0x40, 0x07, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x05, 0x40, 0x07, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x61, 0x63, 0x61, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x1d, 0x00, 0x07, 0xe2, 0x64, 0x00, 0x6d, 0x06,
- 0x40, 0x07, 0x69, 0x61, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x07, 0x40, 0x00, 0x61, 0x72, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0xe4, 0x63, 0x00, 0x65, 0x20, 0x68, 0x3b, 0x74, 0x40,
- 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x64, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x09, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x69, 0x00, 0x73, 0x04, 0x75, 0x0a, 0x40, 0x07, 0x61,
- 0x00, 0x40, 0x00, 0x69, 0x64, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x07, 0x6f, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x18, 0x00,
- 0x07, 0xe1, 0x76, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x09,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x06, 0x62, 0x65, 0x72, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x18, 0x6f, 0x21,
- 0x79, 0x25, 0xe4, 0x6c, 0x00, 0x72, 0x04, 0x73, 0x06, 0x74, 0x0b, 0x40,
- 0x07, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x61, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x6d, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x75, 0x00, 0x79, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0xe2,
- 0x64, 0x00, 0x72, 0x13, 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x74, 0x65, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x66, 0x06, 0x40,
- 0x07, 0x6c, 0x69, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x08, 0x40, 0x07,
- 0x6e, 0x62, 0x61, 0x63, 0x68, 0x00, 0x40, 0x07, 0x63, 0x65, 0x4d, 0x61,
- 0x78, 0x00, 0xe4, 0x62, 0x00, 0x64, 0x09, 0x69, 0x0e, 0x6c, 0x14, 0x40,
- 0x07, 0x6f, 0x6d, 0x6f, 0x73, 0x68, 0x6f, 0x00, 0x40, 0x07, 0x65, 0x6e,
- 0x00, 0x40, 0x07, 0x6c, 0x76, 0x79, 0x00, 0x40, 0x07, 0x65, 0x74, 0x68,
- 0x6f, 0x72, 0x70, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x65, 0x00, 0x40, 0x06, 0x69, 0x62, 0x77, 0x61, 0x00, 0xe6, 0x61,
- 0x00, 0x65, 0x07, 0x68, 0x1e, 0x69, 0x25, 0x6c, 0x3a, 0x74, 0x56, 0x40,
- 0x00, 0x79, 0x61, 0x6d, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x66, 0x09, 0x40,
- 0x07, 0x63, 0x68, 0x6f, 0x62, 0x65, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6e,
- 0x6f, 0x6b, 0x65, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x73, 0x6b, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x77, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x62, 0x65, 0x72, 0x66, 0x65, 0x73, 0x74, 0x00,
- 0xe9, 0x61, 0x00, 0x64, 0x16, 0x65, 0x3d, 0x67, 0x4f, 0x69, 0x53, 0x6c,
- 0x84, 0x6d, 0x89, 0x73, 0x98, 0x79, 0xa5, 0xe4, 0x00, 0x00, 0x66, 0x02,
- 0x6a, 0x04, 0x76, 0x0b, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x77,
- 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe4, 0x65, 0x00, 0x66, 0x08, 0x73, 0x0f,
- 0x75, 0x18, 0x40, 0x07, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x00, 0x40, 0x07,
- 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x6d, 0x6f, 0x62, 0x69, 0x6c,
- 0x65, 0x00, 0x40, 0x07, 0x76, 0x61, 0x69, 0x00, 0xe2, 0x68, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6b, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x67, 0x00, 0x6e, 0x08, 0x76,
- 0x0a, 0x40, 0x07, 0x6f, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x00, 0x07, 0xe2,
- 0x65, 0x00, 0x69, 0x10, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x04, 0x00,
- 0x0e, 0x00, 0x07, 0x40, 0x07, 0x74, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x69, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40, 0x07, 0x63, 0x00, 0x40, 0x07, 0x74,
- 0x65, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x69,
- 0x00, 0x75, 0x1b, 0xe2, 0x61, 0x00, 0x63, 0x0d, 0xe3, 0x00, 0x00, 0x64,
- 0x02, 0x6e, 0x04, 0x00, 0x06, 0x00, 0x09, 0x00, 0x09, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe4, 0x61,
- 0x00, 0x64, 0x1e, 0x6e, 0x26, 0x73, 0x30, 0xe4, 0x68, 0x00, 0x6e, 0x04,
- 0x72, 0x0d, 0x79, 0x0f, 0x40, 0x09, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x79, 0x61, 0x64,
- 0x00, 0x40, 0x07, 0x75, 0x72, 0x6d, 0x61, 0x6e, 0x00, 0x40, 0x00, 0x69,
- 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x6b, 0x00, 0xe6,
- 0x61, 0x00, 0x65, 0x07, 0x69, 0x22, 0x6f, 0x27, 0x73, 0x35, 0x74, 0x3c,
- 0x40, 0x07, 0x73, 0x73, 0x69, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x67, 0x04,
- 0x69, 0x0f, 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x09, 0x64, 0x61, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x09,
- 0x64, 0x61, 0x67, 0x61, 0x00, 0x40, 0x07, 0x61, 0x67, 0x65, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x72, 0x74, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x04, 0x68, 0x2c,
- 0x70, 0x3f, 0x72, 0x4a, 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x6c, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0xe4, 0x42, 0x00, 0x4f, 0x05, 0x55, 0x0d, 0x56, 0x12,
- 0x40, 0x07, 0x53, 0x44, 0x00, 0x40, 0x07, 0x66, 0x66, 0x69, 0x63, 0x65,
- 0x00, 0x40, 0x07, 0x52, 0x4c, 0x00, 0x40, 0x07, 0x69, 0x65, 0x77, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6c, 0x69, 0x61, 0x00, 0x40,
- 0x07, 0x75, 0x63, 0x68, 0x75, 0x73, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x68,
- 0x65, 0x69, 0x6d, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x68, 0x00, 0xfd,
- 0x61, 0x00, 0x00, 0x62, 0x23, 0x00, 0x64, 0x2a, 0x00, 0x65, 0x34, 0x00,
- 0x69, 0x5d, 0x00, 0x6b, 0x93, 0x00, 0x6c, 0x99, 0x00, 0x70, 0xb4, 0x00,
- 0x72, 0xc5, 0x00, 0x74, 0xc7, 0x00, 0x76, 0xde, 0x00, 0x77, 0xed, 0x00,
- 0x79, 0x02, 0x01, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6e, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x6a, 0x06,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x74, 0x61,
- 0x64, 0x00, 0x40, 0x07, 0x69, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6f,
- 0x76, 0x69, 0x63, 0x69, 0x61, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02,
- 0x6f, 0x18, 0x73, 0x1a, 0x00, 0x17, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x06, 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x73, 0x00,
- 0xe5, 0x65, 0x00, 0x6e, 0x11, 0x6f, 0x1d, 0x79, 0x21, 0x7a, 0x25, 0xe1,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x09, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x63, 0x6f, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x62, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x79, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x06, 0x6f, 0x0c, 0x79, 0x10, 0x40, 0x07, 0x6e,
- 0x64, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x73, 0x00, 0x40, 0x09, 0x6e,
- 0x00, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40,
- 0x07, 0x75, 0x73, 0x00, 0x40, 0x07, 0x63, 0x00, 0x00, 0x07, 0xe3, 0x65,
- 0x00, 0x68, 0x05, 0x69, 0x0c, 0x40, 0x07, 0x67, 0x61, 0x00, 0x40, 0x00,
- 0x6f, 0x64, 0x6f, 0x78, 0x00, 0x40, 0x07, 0x7a, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x65, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x7a,
- 0x61, 0x00, 0xec, 0x00, 0x00, 0x61, 0x02, 0x62, 0x0f, 0x63, 0x28, 0x67,
- 0x37, 0x68, 0x3d, 0x69, 0x4d, 0x6c, 0x53, 0x6d, 0x57, 0x74, 0x5c, 0x76,
- 0x6f, 0x77, 0x76, 0x00, 0x07, 0xe2, 0x67, 0x00, 0x6b, 0x04, 0x40, 0x09,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40,
- 0x07, 0x72, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x61, 0x00, 0x40, 0x07,
- 0x6f, 0x6f, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x6b, 0x05, 0x40, 0x07, 0x77,
- 0x61, 0x00, 0x40, 0x07, 0x6f, 0x73, 0x68, 0x00, 0x40, 0x07, 0x72, 0x69,
- 0x73, 0x00, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2,
- 0x72, 0x00, 0x77, 0x08, 0x40, 0x07, 0x6f, 0x67, 0x6f, 0x74, 0x68, 0x00,
- 0x40, 0x07, 0x61, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x64, 0x6f,
- 0x00, 0x40, 0x07, 0x61, 0x6c, 0x64, 0x00, 0xe3, 0x68, 0x00, 0x69, 0x07,
- 0x74, 0x0b, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x77, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x0b, 0x40, 0x07, 0x67, 0x61, 0x64, 0x6f, 0x75, 0x67,
- 0x6f, 0x75, 0x00, 0x40, 0x09, 0x6a, 0x61, 0x00, 0x40, 0x07, 0x69, 0x64,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x06, 0x00, 0x07, 0xe6, 0x66, 0x00, 0x6c, 0x06, 0x6e, 0x0b, 0x6f,
- 0x11, 0x75, 0x18, 0x79, 0x1c, 0x40, 0x06, 0x6f, 0x72, 0x64, 0x00, 0x40,
- 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07,
- 0x6e, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x63,
- 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x79,
- 0x11, 0x7a, 0x1b, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe1, 0x6b, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x61,
- 0x6e, 0x64, 0x69, 0x61, 0x73, 0x00, 0x40, 0x07, 0x69, 0x65, 0x00, 0xc1,
- 0x41, 0x39, 0x77, 0x00, 0x79, 0x00, 0x90, 0x00, 0x99, 0x00, 0xae, 0x00,
- 0xcc, 0x00, 0xd5, 0x00, 0xd9, 0x00, 0x00, 0x00, 0xe2, 0x00, 0xe6, 0x00,
- 0x00, 0x00, 0xeb, 0x00, 0xef, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x01, 0x01,
- 0x00, 0x00, 0x0a, 0x01, 0x23, 0x01, 0x2c, 0x01, 0x00, 0x00, 0x39, 0x01,
- 0x3d, 0x01, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0x7e, 0x05,
- 0x00, 0x00, 0x80, 0x05, 0x82, 0x05, 0x59, 0x08, 0x00, 0x00, 0x6c, 0x08,
- 0xe2, 0x09, 0x00, 0x00, 0x5c, 0x0b, 0x61, 0x0b, 0x3b, 0x0c, 0x00, 0x00,
- 0x3d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0f, 0xc6, 0x11, 0xef, 0x11,
- 0x11, 0x12, 0x0d, 0x13, 0x00, 0x00, 0x00, 0x00, 0x11, 0x13, 0x00, 0x14,
- 0xe4, 0x00, 0x00, 0x43, 0x02, 0x52, 0x04, 0x53, 0x08, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x08, 0x43, 0x00, 0x40, 0x00, 0x43, 0x41, 0x4c, 0x00, 0xe2,
- 0x53, 0x00, 0x58, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x42,
- 0x02, 0x4d, 0x04, 0x50, 0x0a, 0x00, 0x06, 0x00, 0x00, 0x40, 0x00, 0x43,
- 0x49, 0x41, 0x00, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x41, 0x02, 0x46, 0x06,
- 0x51, 0x0f, 0x54, 0x11, 0x00, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x54, 0x02, 0x00, 0x00, 0x00, 0x07, 0x40, 0x00, 0x43, 0x00,
- 0xe2, 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x4e,
- 0x00, 0x40, 0x00, 0x27, 0x73, 0x00, 0x40, 0x07, 0x4f, 0x00, 0xe2, 0x00,
- 0x00, 0x53, 0x02, 0x00, 0x2c, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x57, 0x02,
- 0x00, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x53, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe4, 0x00, 0x00, 0x43, 0x02, 0x4e, 0x04, 0x4f, 0x0e, 0x00, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x77, 0x73, 0x77, 0x69, 0x72, 0x65, 0x00,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x54, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x41, 0x02, 0x4f, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x07, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x61, 0x19, 0x37,
- 0x00, 0x39, 0x00, 0x3d, 0x00, 0x51, 0x00, 0x76, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x91, 0x00, 0xa6, 0x00, 0xad, 0x00, 0x00, 0x00, 0xc1, 0x00, 0xd9,
- 0x00, 0x84, 0x01, 0x9f, 0x01, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x16,
- 0x02, 0x1b, 0x03, 0x5b, 0x03, 0xe0, 0x03, 0x06, 0x04, 0x29, 0x04, 0x00,
- 0x00, 0x2f, 0x04, 0x00, 0x07, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00,
- 0x73, 0x0b, 0xe2, 0x6f, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6d,
- 0x00, 0x40, 0x07, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x02, 0x69, 0x08,
- 0x6b, 0x16, 0x00, 0x07, 0x40, 0x07, 0x65, 0x63, 0x6f, 0x00, 0xe2, 0x66,
- 0x00, 0x6e, 0x05, 0x40, 0x07, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6f, 0x00,
- 0x40, 0x07, 0x61, 0x72, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69,
- 0x0e, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x72, 0x65, 0x77, 0x73,
- 0x6b, 0x69, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x07, 0x6c, 0x09, 0x40, 0x07, 0x6e, 0x69, 0x6e, 0x69, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x69, 0x61, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x76, 0x69,
- 0x00, 0xe3, 0x67, 0x00, 0x6e, 0x04, 0x75, 0x08, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0x40, 0x06, 0x74, 0x65, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe6, 0x61, 0x00,
- 0x65, 0x04, 0x69, 0x5d, 0x6c, 0x6e, 0x6d, 0x75, 0x6f, 0x98, 0x40, 0x07,
- 0x75, 0x00, 0xe5, 0x6d, 0x00, 0x6f, 0x07, 0x72, 0x2a, 0x73, 0x2f, 0x79,
- 0x4c, 0x40, 0x07, 0x62, 0x61, 0x6e, 0x67, 0x00, 0xe4, 0x63, 0x00, 0x67,
- 0x06, 0x6c, 0x0c, 0x7a, 0x14, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x69, 0x74, 0x68, 0x69, 0x63,
- 0x00, 0x40, 0x07, 0x6f, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6d, 0x6f, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x0f, 0xe1, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x69, 0x6e, 0x61, 0x00, 0x00, 0x07, 0xe2, 0x6b, 0x00, 0x73, 0x05,
- 0x40, 0x07, 0x69, 0x72, 0x00, 0x40, 0x07, 0x61, 0x64, 0x65, 0x73, 0x00,
- 0x40, 0x07, 0x61, 0x64, 0x69, 0x6f, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x10,
- 0x79, 0x17, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x76, 0x65,
- 0x00, 0x40, 0x07, 0x72, 0x61, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x72, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x70, 0x0c, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x61, 0x00, 0x40, 0x07, 0x72, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x73, 0x00, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x64, 0x1e, 0x67, 0x24,
- 0x6b, 0x2a, 0x6d, 0x32, 0x73, 0x3a, 0x74, 0x3e, 0x7a, 0x5b, 0x00, 0x07,
- 0xe2, 0x6d, 0x00, 0x73, 0x10, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x61, 0x00, 0x40, 0x07,
- 0x61, 0x65, 0x61, 0x00, 0x40, 0x07, 0x68, 0x75, 0x72, 0x73, 0x74, 0x00,
- 0x40, 0x07, 0x75, 0x6e, 0x6a, 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x68, 0x12, 0xe2, 0x67, 0x00, 0x6c, 0x07, 0x40, 0x07,
- 0x72, 0x75, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x65, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x75,
- 0x61, 0x00, 0xeb, 0x61, 0x00, 0x63, 0x57, 0x65, 0x5f, 0x69, 0x64, 0x6b,
- 0x73, 0x6c, 0x92, 0x6d, 0x9b, 0x6e, 0xaf, 0x72, 0xc0, 0x73, 0xcc, 0x74,
- 0xdc, 0xe6, 0x63, 0x00, 0x64, 0x12, 0x67, 0x18, 0x6c, 0x2c, 0x6d, 0x34,
- 0x6e, 0x46, 0xe2, 0x65, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x73, 0x75,
- 0x73, 0x00, 0x40, 0x07, 0x65, 0x74, 0x65, 0x00, 0x40, 0x00, 0x69, 0x73,
- 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x08,
- 0x79, 0x6d, 0x70, 0x69, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40,
- 0x07, 0x72, 0x69, 0x62, 0x6f, 0x00, 0x40, 0x07, 0x75, 0x6e, 0x74, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x68, 0x65, 0x65, 0x73, 0x69, 0x00,
- 0x40, 0x07, 0x74, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x6d, 0x0d, 0x73, 0x12, 0x00, 0x2b, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x07, 0x40, 0x00, 0x69, 0x64,
- 0x65, 0x73, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x09, 0x73, 0x73, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6c, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x68,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x66, 0x61, 0x6c, 0x00,
- 0x40, 0x07, 0x6e, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x06, 0x40, 0x07, 0x6e, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe5,
- 0x61, 0x00, 0x63, 0x07, 0x71, 0x0c, 0x73, 0x13, 0x74, 0x23, 0x40, 0x07,
- 0x64, 0x65, 0x6e, 0x61, 0x00, 0x40, 0x06, 0x61, 0x6c, 0x00, 0x40, 0x07,
- 0x75, 0x61, 0x6c, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06,
- 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x76, 0x65, 0x72, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x72, 0x00, 0x75, 0x06, 0x40, 0x07, 0x6e, 0x61, 0x6b, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x1a, 0x68, 0x36,
- 0x6e, 0x3b, 0x72, 0x3f, 0x73, 0x58, 0x74, 0x5c, 0x00, 0x07, 0xe1, 0x67,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe4, 0x00,
- 0x00, 0x6c, 0x02, 0x6e, 0x04, 0x72, 0x0d, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x6d, 0x00, 0x40, 0x07, 0x73, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x02, 0x69, 0x04,
- 0x6b, 0x08, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x79, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x07, 0x6f, 0x09, 0x79,
- 0x0d, 0x40, 0x07, 0x72, 0x73, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x04, 0x69, 0x0a, 0x00, 0x2a, 0x00, 0x07, 0x40, 0x07, 0x74, 0x74,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x65, 0x00,
- 0x67, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6c, 0x08, 0x40,
- 0x07, 0x72, 0x6f, 0x74, 0x74, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x76,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x04, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x6e, 0x65, 0x65, 0x00, 0xe2,
- 0x50, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0x00, 0x07, 0xc0, 0x61, 0x15, 0x2d, 0x00, 0x00, 0x00,
- 0x5d, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
- 0x98, 0x00, 0x00, 0x00, 0xa5, 0x00, 0xba, 0x00, 0xd2, 0x00, 0xda, 0x00,
- 0x8d, 0x01, 0x93, 0x01, 0xa6, 0x01, 0xac, 0x01, 0x7d, 0x02, 0x85, 0x02,
- 0xd0, 0x02, 0xe4, 0x62, 0x00, 0x63, 0x06, 0x6c, 0x0a, 0x72, 0x0e, 0x40,
- 0x07, 0x6f, 0x64, 0x79, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0xe3, 0x6c, 0x00, 0x73, 0x0b, 0x79, 0x10, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x00, 0x07, 0xe3, 0x68, 0x00, 0x6b, 0x06, 0x6f, 0x14, 0x40, 0x07, 0x6f,
- 0x72, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x70, 0x61, 0x68, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x72,
- 0x6f, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x67,
- 0x08, 0x00, 0x07, 0x40, 0x09, 0x73, 0x75, 0x73, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6e,
- 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x40, 0x06, 0x73, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x70, 0x6f, 0x6e, 0x6e, 0x65, 0x73, 0x65, 0x00, 0x40,
- 0x07, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02,
- 0x64, 0x04, 0x65, 0x0d, 0x6e, 0x14, 0x73, 0x59, 0x74, 0x61, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x65, 0x63, 0x6b, 0x69, 0x00, 0x40,
- 0x07, 0x6c, 0x6f, 0x70, 0x65, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x04, 0x69, 0x08, 0x73, 0x10, 0x79, 0x2e, 0x7a, 0x30, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x74, 0x6f, 0x6e,
- 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x6f,
- 0x69, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x63, 0x6f, 0x6c, 0x61, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x15, 0x69, 0x37, 0xe3, 0x67, 0x00, 0x74, 0x05, 0x78,
- 0x0c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x75, 0x63, 0x68,
- 0x00, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x73, 0x6d,
- 0x00, 0x40, 0x06, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x72, 0x69, 0x61, 0x00,
- 0xe3, 0x69, 0x00, 0x73, 0x04, 0x79, 0x08, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x69, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x75, 0x6f, 0x74,
- 0x00, 0xec, 0x63, 0x00, 0x65, 0x16, 0x69, 0x23, 0x6b, 0x37, 0x6c, 0x3d,
- 0x6d, 0x3f, 0x6e, 0x54, 0x6f, 0x59, 0x72, 0x62, 0x73, 0x6e, 0x74, 0xa7,
- 0x75, 0xab, 0xe3, 0x68, 0x00, 0x69, 0x07, 0x79, 0x0d, 0x40, 0x07, 0x65,
- 0x72, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x76, 0x61, 0x6c, 0x00, 0x00, 0x07,
- 0xe2, 0x6c, 0x00, 0x7a, 0x06, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x00, 0x00,
- 0x07, 0xe1, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x73, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69,
- 0x6e, 0x73, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x09,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x6c, 0x6f, 0x79, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x64, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x65,
- 0x72, 0x00, 0x00, 0x16, 0xe3, 0x65, 0x00, 0x68, 0x20, 0x69, 0x26, 0xe3,
- 0x69, 0x00, 0x70, 0x04, 0x75, 0x15, 0x40, 0x07, 0x64, 0x00, 0xe2, 0x68,
- 0x00, 0x6f, 0x06, 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6c,
- 0x69, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x07, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x76, 0x02, 0x00, 0x07,
- 0x40, 0x09, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x61, 0x77, 0x61,
- 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x72, 0x2f, 0x74, 0x3e, 0x40,
- 0x07, 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x2d, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x73, 0x0b, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72,
- 0x6f, 0x75, 0x67, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x06,
- 0x00, 0x14, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x63, 0x68,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x67, 0x65, 0x6f, 0x74, 0x00,
- 0xe3, 0x61, 0x00, 0x63, 0x04, 0x69, 0x06, 0x40, 0x07, 0x6d, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x7a, 0x65, 0x72, 0x00, 0xf7, 0x44, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x65, 0x54, 0x00, 0x69, 0x6f, 0x00, 0x6f, 0xef, 0x00, 0x72,
- 0x52, 0x01, 0x79, 0x59, 0x01, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x6e, 0x10,
- 0x72, 0x1a, 0xe2, 0x64, 0x00, 0x74, 0x05, 0x40, 0x07, 0x72, 0x61, 0x00,
- 0x40, 0x07, 0x68, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x6f, 0x7a,
- 0x6f, 0x69, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0f, 0xe1, 0x6f, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x11, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0xe3, 0x6b, 0x00, 0x6c, 0x05, 0x6e, 0x0a,
- 0x40, 0x07, 0x64, 0x61, 0x00, 0x40, 0x07, 0x70, 0x73, 0x00, 0x40, 0x07,
- 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x64, 0x00, 0x6c,
- 0x06, 0x70, 0x74, 0x40, 0x07, 0x69, 0x61, 0x73, 0x00, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x62, 0x0c, 0x65, 0x10, 0x69, 0x16, 0x6c, 0x4a, 0x00, 0x12,
- 0x40, 0x07, 0x64, 0x65, 0x6c, 0x70, 0x68, 0x69, 0x61, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x07, 0x6d, 0x6f, 0x6e, 0x00, 0xe2, 0x70, 0x00, 0x73,
- 0x28, 0xe3, 0x00, 0x00, 0x70, 0x02, 0x73, 0x1f, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6e, 0x05, 0x40, 0x07,
- 0x6e, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6e, 0x65, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x10, 0xe1, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x73, 0x04, 0x00, 0x06, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x70, 0x73, 0x00, 0xe3, 0x62, 0x00, 0x65, 0x05, 0x74, 0x27, 0x40,
- 0x07, 0x6f, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x0f, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe2, 0x62, 0x00, 0x73, 0x08, 0x40, 0x07,
- 0x75, 0x63, 0x6b, 0x65, 0x74, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x05, 0x40,
- 0x07, 0x6f, 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x79, 0x67, 0x69,
- 0x61, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x69, 0x73, 0x00, 0xfc, 0x61, 0x00,
- 0x00, 0x63, 0x14, 0x00, 0x65, 0x50, 0x00, 0x6b, 0x70, 0x00, 0x6c, 0x74,
- 0x00, 0x6e, 0xa2, 0x00, 0x70, 0xe7, 0x00, 0x72, 0xed, 0x00, 0x73, 0x02,
- 0x01, 0x74, 0x22, 0x01, 0x75, 0x4a, 0x01, 0x7a, 0x4e, 0x01, 0xe3, 0x66,
- 0x00, 0x67, 0x02, 0x6e, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x74, 0x00,
- 0x40, 0x07, 0x6f, 0x6c, 0x61, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x06, 0x6b,
- 0x0f, 0x74, 0x31, 0x40, 0x07, 0x73, 0x73, 0x6f, 0x00, 0x40, 0x07, 0x61,
- 0x64, 0x69, 0x6c, 0x6c, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x66, 0x0f, 0x77,
- 0x15, 0xe2, 0x72, 0x00, 0x74, 0x06, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x64, 0x00, 0x40, 0x07,
- 0x69, 0x63, 0x6b, 0x00, 0x00, 0x07, 0xe2, 0x64, 0x00, 0x72, 0x07, 0x40,
- 0x07, 0x6d, 0x6f, 0x6e, 0x74, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x0f, 0x67,
- 0x17, 0x6c, 0x1d, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6d, 0x61, 0x79,
- 0x6f, 0x00, 0x40, 0x06, 0x72, 0x69, 0x6d, 0x00, 0x40, 0x07, 0x73, 0x62,
- 0x75, 0x72, 0x79, 0x00, 0xe7, 0x61, 0x00, 0x63, 0x07, 0x64, 0x0c, 0x6b,
- 0x11, 0x6f, 0x19, 0x74, 0x2c, 0x79, 0x31, 0x40, 0x07, 0x74, 0x75, 0x62,
- 0x6f, 0x00, 0x40, 0x07, 0x75, 0x73, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00,
- 0x40, 0x07, 0x65, 0x72, 0x74, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x63, 0x00, 0x68, 0x06, 0x40, 0x07, 0x68, 0x69, 0x6f, 0x00, 0x40, 0x07,
- 0x65, 0x74, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x00, 0x69, 0x6e,
- 0x00, 0x40, 0x07, 0x70, 0x69, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x65,
- 0x00, 0x6e, 0x05, 0x40, 0x07, 0x75, 0x73, 0x00, 0x40, 0x07, 0x64, 0x65,
- 0x6c, 0x6c, 0x6f, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x02, 0x69, 0x07, 0x73,
- 0x11, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x73, 0x74,
- 0x72, 0x61, 0x74, 0x75, 0x73, 0x00, 0x40, 0x07, 0x61, 0x72, 0x6f, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x07, 0x40, 0x07, 0x61, 0x69, 0x72, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x73, 0x07, 0x00, 0x06, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0x40, 0x07, 0x75,
- 0x72, 0x67, 0x68, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x72,
- 0x72, 0x6f, 0x00, 0x40, 0x00, 0x77, 0x79, 0x00, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x84, 0x69, 0xa5, 0x75, 0xb5, 0x79, 0xc5, 0x00, 0x00, 0xe6,
- 0x63, 0x00, 0x6e, 0x08, 0x73, 0x1e, 0x74, 0x27, 0x75, 0x55, 0x79, 0x5b,
- 0x40, 0x09, 0x65, 0x6d, 0x61, 0x72, 0x6b, 0x00, 0xe3, 0x63, 0x00, 0x6f,
- 0x04, 0x74, 0x06, 0x40, 0x07, 0x6b, 0x00, 0x00, 0x00, 0x40, 0x07, 0x61,
- 0x67, 0x65, 0x6e, 0x65, 0x74, 0x00, 0x40, 0x07, 0x74, 0x69, 0x63, 0x69,
- 0x6e, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x68, 0x05, 0x6f, 0x07, 0x74, 0x21,
- 0x40, 0x07, 0x65, 0x61, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x07, 0x74, 0x75, 0x73, 0x00, 0xe3, 0x53, 0x00, 0x62, 0x09,
- 0x74, 0x0e, 0x40, 0x07, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x6f, 0x79, 0x00, 0x40, 0x07, 0x65, 0x78, 0x00, 0xe2, 0x69, 0x00,
- 0x78, 0x14, 0xe2, 0x61, 0x00, 0x73, 0x06, 0x40, 0x07, 0x64, 0x65, 0x73,
- 0x00, 0x40, 0x07, 0x74, 0x6f, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x40, 0x09,
- 0x69, 0x67, 0x6c, 0x61, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x06, 0x63, 0x65, 0x6e, 0x65, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x72, 0x63, 0x68, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x00, 0x00, 0x07,
- 0xc1, 0x63, 0x18, 0x35, 0x00, 0x37, 0x00, 0x54, 0x00, 0x70, 0x00, 0x00,
- 0x00, 0x72, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x9f, 0x00, 0xa6,
- 0x00, 0x54, 0x01, 0x96, 0x01, 0xbe, 0x01, 0xcf, 0x01, 0x00, 0x00, 0x03,
- 0x02, 0x5a, 0x02, 0x7f, 0x02, 0xb2, 0x02, 0x00, 0x00, 0xc1, 0x02, 0x00,
- 0x00, 0xea, 0x02, 0xf1, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x09,
- 0x40, 0x07, 0x68, 0x6f, 0x6e, 0x74, 0x61, 0x73, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07,
- 0xe3, 0x67, 0x00, 0x68, 0x08, 0x75, 0x10, 0x40, 0x07, 0x6f, 0x72, 0x69,
- 0x63, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x65, 0x74, 0x7a, 0x00, 0x40,
- 0x07, 0x6e, 0x6b, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x00, 0xe4, 0x6e,
- 0x00, 0x72, 0x07, 0x73, 0x14, 0x74, 0x1a, 0x40, 0x07, 0x63, 0x61, 0x72,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x74, 0x00, 0x40,
- 0x07, 0x74, 0x00, 0x40, 0x07, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x69,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6d, 0x6f, 0x6e, 0x00, 0xea, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x21, 0x69, 0x23, 0x6b, 0x33, 0x6c, 0x35, 0x6f,
- 0x59, 0x73, 0x5b, 0x74, 0x67, 0x79, 0x6d, 0x00, 0x12, 0xe2, 0x6e, 0x00,
- 0x72, 0x0c, 0xe2, 0x64, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6b,
- 0x69, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x09, 0x69, 0x64, 0x00, 0x00, 0x06, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x68, 0x00, 0x40, 0x07, 0x62, 0x75, 0x72, 0x6f, 0x00, 0x00, 0x07,
- 0xe4, 0x61, 0x00, 0x6f, 0x05, 0x75, 0x0a, 0x79, 0x0e, 0x40, 0x07, 0x72,
- 0x64, 0x00, 0x40, 0x07, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x78, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x6e, 0x61, 0x00,
- 0x00, 0x07, 0xe1, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x07, 0x61, 0x76, 0x61, 0x00, 0xe3, 0x68, 0x00, 0x6e,
- 0x08, 0x70, 0x1d, 0x40, 0x07, 0x79, 0x6d, 0x6e, 0x69, 0x61, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x68, 0x65,
- 0x6d, 0x75, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x18, 0x70, 0x1d, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x64,
- 0x6f, 0x75, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0b, 0xe2, 0x61, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x69, 0x0b,
- 0x40, 0x07, 0x68, 0x61, 0x72, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x6b, 0x00, 0xe3, 0x68, 0x00, 0x6c, 0x02, 0x6e, 0x06, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe4, 0x65, 0x00, 0x6f, 0x0b,
- 0x70, 0x16, 0x73, 0x24, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x00, 0x40, 0x07, 0x63, 0x61, 0x74, 0x65, 0x70, 0x65, 0x74,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x73, 0x00, 0x40, 0x07, 0x69, 0x63, 0x6c, 0x65, 0x00, 0xe4,
- 0x66, 0x00, 0x72, 0x07, 0x73, 0x0d, 0x74, 0x13, 0x40, 0x07, 0x69, 0x72,
- 0x69, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x6d, 0x61, 0x00, 0x40, 0x07, 0x63,
- 0x68, 0x65, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x0a,
- 0x6f, 0x10, 0x73, 0x12, 0x75, 0x1a, 0x00, 0x0e, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x07, 0x40, 0x07, 0x69, 0x64, 0x6f,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x53, 0x02, 0x67, 0x0a, 0x00, 0x07, 0x40,
- 0x07, 0x63, 0x72, 0x69, 0x70, 0x74, 0x00, 0x40, 0x07, 0x72, 0x65, 0x53,
- 0x51, 0x4c, 0x00, 0xe4, 0x65, 0x00, 0x6f, 0x07, 0x73, 0x0d, 0x74, 0x13,
- 0x40, 0x07, 0x6d, 0x6b, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x63,
- 0x00, 0x40, 0x07, 0x64, 0x61, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0a,
- 0x73, 0x0e, 0x40, 0x07, 0x77, 0x61, 0x74, 0x6f, 0x6d, 0x69, 0x65, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40,
- 0x07, 0x64, 0x00, 0x40, 0x07, 0x73, 0x69, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x68, 0x1d, 0xe2, 0x6c, 0x00, 0x72, 0x04, 0x40, 0x07, 0x6c, 0x00, 0xe2,
- 0x50, 0x00, 0x73, 0x0d, 0xe2, 0x43, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x69, 0x6e, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x74, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x61, 0x6e, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x50,
- 0x00, 0x69, 0xd6, 0x00, 0x6f, 0x2d, 0x01, 0x75, 0x40, 0x02, 0x79, 0x77,
- 0x02, 0x00, 0x07, 0xe8, 0x64, 0x00, 0x65, 0x09, 0x67, 0x12, 0x69, 0x17,
- 0x6b, 0x1b, 0x74, 0x21, 0x76, 0x2f, 0x78, 0x34, 0xe2, 0x61, 0x00, 0x6f,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x74, 0x6f, 0x72, 0x69, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x75, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x72, 0x69, 0x74, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x07, 0x40, 0x07,
- 0x68, 0x65, 0x74, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x64, 0x61, 0x00,
- 0x40, 0x07, 0x69, 0x74, 0x65, 0x6c, 0x65, 0x73, 0x00, 0xe6, 0x61, 0x00,
- 0x63, 0x08, 0x6d, 0x12, 0x6e, 0x25, 0x73, 0x34, 0x74, 0x72, 0x40, 0x07,
- 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x62, 0x72,
- 0x69, 0x61, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e,
- 0x67, 0x65, 0x72, 0x00, 0x40, 0x07, 0x73, 0x6c, 0x69, 0x64, 0x00, 0xe2,
- 0x73, 0x00, 0x74, 0x04, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x69, 0x63,
- 0x65, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x63, 0x23, 0x6c, 0x29, 0x74,
- 0x2e, 0x00, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x73, 0x6d, 0x00,
- 0x40, 0x07, 0x6f, 0x74, 0x74, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x69, 0x61, 0x00, 0xe9,
- 0x61, 0x00, 0x62, 0x04, 0x63, 0x0b, 0x65, 0x0f, 0x6e, 0x17, 0x73, 0x30,
- 0x75, 0x38, 0x76, 0x3c, 0x78, 0x42, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07,
- 0x69, 0x6c, 0x6f, 0x66, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x73,
- 0x74, 0x6c, 0x65, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x0c, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x07, 0x70, 0x65, 0x00, 0x40, 0x07, 0x63, 0x69, 0x6c, 0x6c,
- 0x61, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x61, 0x74, 0x65, 0x00,
- 0x00, 0x00, 0xec, 0x51, 0x00, 0x63, 0x07, 0x66, 0x2f, 0x68, 0x31, 0x6b,
- 0x3b, 0x6d, 0x43, 0x70, 0x5c, 0x73, 0x6d, 0x74, 0x85, 0x75, 0xbd, 0x76,
- 0xcc, 0x7a, 0xf5, 0x40, 0x07, 0x75, 0x65, 0x73, 0x74, 0x00, 0xe3, 0x72,
- 0x00, 0x74, 0x17, 0x79, 0x1c, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x00, 0x00, 0x40, 0x00, 0x69, 0x62, 0x69, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x66, 0x69, 0x65, 0x76, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x68, 0x06, 0x40, 0x07, 0x63, 0x69, 0x61, 0x00, 0x40, 0x00,
- 0x65, 0x74, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x70,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x08, 0x40, 0x07, 0x67,
- 0x6f, 0x72, 0x61, 0x73, 0x00, 0xe3, 0x72, 0x00, 0x73, 0x08, 0x75, 0x20,
- 0x40, 0x07, 0x6f, 0x7a, 0x6f, 0x69, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x06, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe2, 0x64, 0x00, 0x73, 0x06, 0x40, 0x07, 0x68, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x18, 0x6f, 0x20, 0xe2, 0x6e,
- 0x00, 0x72, 0x0e, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x09, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x00, 0x62, 0x73, 0x00, 0x40, 0x06,
- 0x64, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x07, 0x40, 0x09, 0x61, 0x63,
- 0x00, 0xe4, 0x64, 0x00, 0x69, 0x15, 0x73, 0x1a, 0x74, 0x2c, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x07, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x74, 0x74, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x11, 0x79, 0x1c, 0xe1, 0x6c, 0x00, 0xe2,
- 0x6d, 0x00, 0x74, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0x40, 0x09, 0x75, 0x64, 0x6f, 0x6d, 0x6f, 0x6e, 0x61, 0x73, 0x00,
- 0x40, 0x07, 0x63, 0x68, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f,
- 0x06, 0x00, 0x07, 0x40, 0x07, 0x68, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x05, 0x40, 0x07, 0x69,
- 0x63, 0x00, 0x00, 0x06, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x65,
- 0x1f, 0x67, 0x35, 0x6c, 0x40, 0x6e, 0x5a, 0x72, 0x78, 0x73, 0xb6, 0x74,
- 0xd3, 0x7a, 0xe1, 0x00, 0x07, 0x40, 0x07, 0x4d, 0x65, 0x64, 0x00, 0xe2,
- 0x63, 0x00, 0x6b, 0x06, 0x40, 0x07, 0x69, 0x6e, 0x69, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x74, 0x00, 0xe2, 0x62,
- 0x00, 0x72, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x00, 0x74, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x68,
- 0x04, 0x40, 0x07, 0x74, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x69, 0x06,
- 0x6c, 0x0d, 0x40, 0x07, 0x73, 0x6b, 0x69, 0x00, 0x40, 0x07, 0x74, 0x7a,
- 0x65, 0x72, 0x00, 0x40, 0x09, 0x6d, 0x61, 0x6e, 0x00, 0xe3, 0x63, 0x00,
- 0x69, 0x04, 0x6a, 0x08, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x63, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0xe5, 0x61, 0x00, 0x63, 0x05, 0x64, 0x0b, 0x69, 0x10,
- 0x75, 0x2f, 0x40, 0x07, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c,
- 0x00, 0x40, 0x07, 0x75, 0x65, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x02, 0x74,
- 0x06, 0x00, 0x09, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x73, 0x6d,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x68, 0x08,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x6b, 0x00, 0x74,
- 0x05, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x00, 0xe2, 0x69,
- 0x00, 0x6e, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x00,
- 0x40, 0x07, 0x6f, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe7, 0x67, 0x00, 0x6c,
- 0x11, 0x6d, 0x15, 0x6e, 0x17, 0x6f, 0x1e, 0x72, 0x2f, 0x74, 0x47, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x63, 0x68, 0x6f, 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x08, 0x40, 0x07,
- 0x67, 0x79, 0x61, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65,
- 0x00, 0x72, 0x0d, 0xe2, 0x6e, 0x00, 0x78, 0x06, 0x40, 0x07, 0x65, 0x65,
- 0x73, 0x00, 0x00, 0x09, 0x40, 0x07, 0x68, 0x69, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x17, 0x6f, 0x1c, 0xe1, 0x67, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x73, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x41, 0x02, 0x00, 0x42,
- 0x04, 0x00, 0x43, 0x06, 0x00, 0x45, 0x08, 0x00, 0x4d, 0x0c, 0x00, 0x57,
- 0x0e, 0x00, 0x61, 0x15, 0x00, 0x69, 0x3f, 0x00, 0x6f, 0x52, 0x00, 0x75,
- 0x56, 0x00, 0x77, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x00, 0x44, 0x00, 0x00, 0x00, 0x40, 0x00, 0x45, 0x52, 0x54,
- 0x59, 0x00, 0xe4, 0x64, 0x00, 0x65, 0x07, 0x6e, 0x0c, 0x74, 0x12, 0x40,
- 0x07, 0x64, 0x61, 0x66, 0x69, 0x00, 0x40, 0x07, 0x64, 0x61, 0x00, 0x40,
- 0x07, 0x74, 0x61, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x6e, 0x00, 0x71,
- 0x07, 0x40, 0x07, 0x67, 0x64, 0x61, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x68,
- 0x61, 0x72, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65,
- 0x41, 0x00, 0x69, 0x97, 0x00, 0x6d, 0x09, 0x01, 0x6f, 0x0f, 0x01, 0xe6,
- 0x61, 0x00, 0x6b, 0x07, 0x6f, 0x19, 0x73, 0x1e, 0x74, 0x26, 0x79, 0x2f,
- 0x40, 0x07, 0x6c, 0x75, 0x64, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x73, 0x6d,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6d, 0x6f, 0x64,
- 0x6f, 0x00, 0x40, 0x07, 0x65, 0x72, 0x6e, 0x61, 0x72, 0x79, 0x00, 0x40,
- 0x07, 0x6c, 0x65, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x63, 0x14, 0x65,
- 0x1a, 0x6e, 0x31, 0x74, 0x37, 0x7a, 0x42, 0x00, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x69, 0x73, 0x00, 0x40, 0x07, 0x68, 0x75, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x74, 0x69,
- 0x6e, 0x00, 0x40, 0x07, 0x7a, 0x61, 0x6c, 0x63, 0x6f, 0x61, 0x74, 0x6c,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe6, 0x63, 0x00, 0x6e, 0x24, 0x72,
- 0x41, 0x73, 0x48, 0x74, 0x4f, 0x78, 0x53, 0xe1, 0x6b, 0x00, 0xe4, 0x4c,
- 0x00, 0x4d, 0x06, 0x54, 0x0b, 0x6c, 0x11, 0x40, 0x07, 0x69, 0x73, 0x74,
- 0x00, 0x40, 0x07, 0x69, 0x78, 0x00, 0x40, 0x07, 0x69, 0x6d, 0x65, 0x00,
- 0x40, 0x07, 0x69, 0x6e, 0x6b, 0x73, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x04,
- 0x74, 0x06, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x6f,
- 0x07, 0x40, 0x07, 0x6c, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x69, 0x6e, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0x40, 0x07, 0x72, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x73, 0x65, 0x74,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x74, 0x00, 0xc1, 0x41, 0x39, 0x77, 0x00,
- 0x79, 0x00, 0x82, 0x00, 0x86, 0x00, 0x95, 0x00, 0x9e, 0x00, 0xa9, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc9, 0x00, 0xd2, 0x00, 0xe3, 0x00, 0x00, 0x00, 0xe5, 0x00,
- 0xe7, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x51, 0x03, 0x00, 0x00, 0x53, 0x03,
- 0x55, 0x03, 0x2e, 0x06, 0x00, 0x00, 0x30, 0x06, 0xa6, 0x06, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x08, 0x44, 0x08, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x0c, 0xce, 0x0c, 0x00, 0x00,
- 0x2d, 0x0e, 0x46, 0x0e, 0x48, 0x0e, 0x00, 0x07, 0xe2, 0x46, 0x00, 0x4d,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x00, 0x49, 0x00, 0xe3, 0x00, 0x00,
- 0x41, 0x02, 0x4d, 0x04, 0x00, 0x00, 0x00, 0x07, 0x40, 0x00, 0x50, 0x00,
- 0xe2, 0x00, 0x00, 0x41, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x49, 0x00,
- 0x4d, 0x04, 0x40, 0x00, 0x54, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x43,
- 0x02, 0x44, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xe4, 0x00, 0x00,
- 0x46, 0x02, 0x50, 0x04, 0x53, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x43, 0x00, 0xe2, 0x00, 0x00, 0x41, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe3, 0x46, 0x00, 0x4d, 0x04, 0x54, 0x06, 0x40, 0x00, 0x4c, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x46,
- 0x00, 0x49, 0x05, 0x56, 0x07, 0x40, 0x00, 0x53, 0x52, 0x00, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x46,
- 0x4d, 0x00, 0x00, 0x06, 0xc1, 0x62, 0x18, 0x35, 0x00, 0x37, 0x00, 0x5e,
- 0x00, 0x8c, 0x00, 0x95, 0x00, 0x97, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xaf,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, 0xc5, 0x00, 0x33, 0x01, 0x79,
- 0x01, 0x7e, 0x01, 0x9a, 0x01, 0x00, 0x00, 0xa0, 0x01, 0xfa, 0x01, 0x0a,
- 0x02, 0x0e, 0x02, 0x13, 0x02, 0x00, 0x00, 0x1d, 0x02, 0x00, 0x07, 0xe3,
- 0x61, 0x00, 0x65, 0x04, 0x69, 0x1c, 0x40, 0x07, 0x74, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x24, 0xe3, 0x61, 0x00, 0x65, 0x05,
- 0x6d, 0x13, 0x40, 0x07, 0x65, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x69, 0x6e, 0x6f, 0x66, 0x66, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00,
- 0x40, 0x07, 0x63, 0x6c, 0x69, 0x66, 0x66, 0x65, 0x00, 0x00, 0x07, 0xe2,
- 0x61, 0x00, 0x66, 0x05, 0x40, 0x07, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x6c,
- 0x65, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x72, 0x6f, 0x6b, 0x00, 0x40,
- 0x07, 0x6e, 0x69, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x70, 0x06, 0x40,
- 0x07, 0x69, 0x67, 0x68, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe5, 0x61, 0x00,
- 0x62, 0x2f, 0x69, 0x33, 0x6f, 0x41, 0x73, 0x51, 0xe5, 0x00, 0x00, 0x64,
- 0x02, 0x6b, 0x0e, 0x6e, 0x17, 0x79, 0x1e, 0x00, 0x07, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x72,
- 0x69, 0x73, 0x68, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x75, 0x6a, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x61, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x7a, 0x00, 0x00,
- 0x07, 0xe2, 0x6e, 0x00, 0x73, 0x09, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x73, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3,
- 0x64, 0x00, 0x67, 0x2a, 0x6b, 0x30, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x0e, 0x69, 0x13, 0x6f, 0x15, 0x79, 0x1b, 0x00, 0x07, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c,
- 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x70, 0x68, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75,
- 0x6c, 0x00, 0xe3, 0x68, 0x00, 0x70, 0x06, 0x75, 0x0e, 0x40, 0x07, 0x61,
- 0x65, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x40,
- 0x07, 0x6e, 0x7a, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x75, 0x65, 0x6c, 0x00,
- 0xe4, 0x61, 0x00, 0x6d, 0x16, 0x70, 0x1e, 0x74, 0x25, 0xe1, 0x6c, 0x00,
- 0xe2, 0x67, 0x00, 0x68, 0x07, 0x40, 0x07, 0x65, 0x74, 0x68, 0x69, 0x00,
- 0x40, 0x07, 0x61, 0x67, 0x75, 0x65, 0x00, 0x40, 0x07, 0x75, 0x73, 0x73,
- 0x65, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x74, 0x69, 0x6e, 0x00, 0xe1, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x66, 0x07, 0x00, 0x00, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x73, 0x6d, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x05, 0x40,
- 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x69, 0x66, 0x66, 0x00, 0x40, 0x07,
- 0x6c, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x70,
- 0x69, 0x6e, 0x64, 0x69, 0x00, 0xe5, 0x00, 0x00, 0x42, 0x02, 0x62, 0x07,
- 0x6c, 0x0d, 0x6d, 0x14, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x75, 0x72, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x69, 0x67, 0x68, 0x00,
- 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40, 0x07, 0x6e, 0x64, 0x00, 0x40, 0x07,
- 0x6e, 0x64, 0x6f, 0x00, 0x00, 0x07, 0x00, 0x00, 0xc1, 0x50, 0x2a, 0x59,
- 0x00, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
- 0x00, 0x90, 0x00, 0xa6, 0x00, 0xbd, 0x00, 0xe7, 0x00, 0x00, 0x01, 0x15,
- 0x01, 0x42, 0x01, 0x4b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88,
- 0x01, 0xac, 0x01, 0x00, 0x00, 0xe8, 0x01, 0x1c, 0x02, 0x00, 0x00, 0x23,
- 0x02, 0x48, 0x02, 0x4f, 0x02, 0x70, 0x02, 0x00, 0x00, 0xad, 0x02, 0xaf,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x45, 0x63, 0x00, 0xe4, 0x64, 0x00, 0x67,
- 0x06, 0x6c, 0x1a, 0x73, 0x20, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6d, 0x69, 0x63, 0x73, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x72,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x6b, 0x05, 0x40, 0x07, 0x63, 0x61,
- 0x00, 0x40, 0x07, 0x61, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x07, 0x66, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x64, 0x00, 0x65, 0x05, 0x66, 0x0c,
- 0x67, 0x12, 0x6d, 0x19, 0x40, 0x07, 0x69, 0x74, 0x00, 0x40, 0x07, 0x65,
- 0x6d, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x64, 0x00, 0x40, 0x07,
- 0x72, 0x61, 0x76, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x64, 0x00, 0xe4,
- 0x62, 0x00, 0x64, 0x05, 0x73, 0x07, 0x76, 0x0b, 0x40, 0x07, 0x6f, 0x6b,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00,
- 0xe2, 0x6f, 0x00, 0x75, 0x0a, 0x40, 0x09, 0x72, 0x6d, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x67, 0x69, 0x6f, 0x00, 0xe4, 0x67, 0x00,
- 0x69, 0x05, 0x6f, 0x1a, 0x75, 0x1e, 0x40, 0x07, 0x69, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6c, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x71, 0x75, 0x69,
- 0x73, 0x74, 0x00, 0xe4, 0x63, 0x00, 0x64, 0x12, 0x6c, 0x14, 0x6e, 0x19,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x74, 0x61, 0x67, 0x27, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x79,
- 0x00, 0xe2, 0x61, 0x00, 0x68, 0x06, 0x40, 0x07, 0x6c, 0x64, 0x6f, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x72, 0x64, 0x74, 0x00, 0x40,
- 0x07, 0x6c, 0x64, 0x00, 0xe4, 0x61, 0x00, 0x62, 0x07, 0x69, 0x0f, 0x75,
- 0x17, 0x40, 0x07, 0x72, 0x71, 0x75, 0x65, 0x00, 0x40, 0x07, 0x72, 0x61,
- 0x6e, 0x64, 0x74, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x21, 0x6f, 0x2a, 0xe4,
- 0x00, 0x00, 0x69, 0x02, 0x73, 0x0b, 0x75, 0x13, 0x00, 0x07, 0x40, 0x06,
- 0x73, 0x73, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x00, 0x63, 0x65, 0x6e,
- 0x63, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x75, 0x0f, 0x00,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x73, 0x6d, 0x00, 0x40, 0x09, 0x75, 0x69,
- 0x65, 0x6d, 0x00, 0xe3, 0x69, 0x00, 0x74, 0x09, 0x75, 0x13, 0x40, 0x00,
- 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x72, 0x65, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x43, 0x6f, 0x64, 0x65, 0x00, 0xe3,
- 0x62, 0x00, 0x6e, 0x05, 0x74, 0x0b, 0x40, 0x07, 0x65, 0x6e, 0x00, 0x40,
- 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x05, 0x40, 0x07,
- 0x72, 0x73, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x04, 0x6c, 0x2f, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x6c, 0x00,
- 0x72, 0x18, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06,
- 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe3,
- 0x65, 0x00, 0x6b, 0x04, 0x6e, 0x0c, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07,
- 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x0c, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x6f, 0x00, 0x40,
- 0x07, 0x6c, 0x64, 0x73, 0x00, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x1c, 0x6f, 0x38, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x65, 0x02, 0x69,
- 0x04, 0x6e, 0x0b, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x61,
- 0x75, 0x00, 0x40, 0x07, 0x69, 0x73, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x6e,
- 0x07, 0x40, 0x07, 0x6e, 0x6e, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00,
- 0xe2, 0x64, 0x00, 0x6e, 0x25, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x73, 0x06, 0x20, 0x08, 0x07, 0x00, 0xff, 0xff, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x61, 0x00, 0x00, 0x07, 0xff, 0x62, 0x00, 0x00, 0x63, 0x0a, 0x00,
- 0x64, 0x90, 0x00, 0x65, 0x9c, 0x00, 0x67, 0xbe, 0x00, 0x6c, 0xea, 0x00,
- 0x6d, 0xf7, 0x00, 0x6e, 0xfe, 0x00, 0x6f, 0x0e, 0x01, 0x70, 0x17, 0x01,
- 0x73, 0x1d, 0x01, 0x74, 0x29, 0x01, 0x76, 0x3c, 0x01, 0x79, 0x63, 0x01,
- 0x7a, 0x69, 0x01, 0x40, 0x07, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70,
- 0x00, 0xe5, 0x61, 0x00, 0x65, 0x06, 0x68, 0x08, 0x6b, 0x50, 0x6f, 0x79,
- 0x40, 0x07, 0x72, 0x64, 0x6f, 0x00, 0x00, 0x07, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x1a, 0x69, 0x21, 0x6d, 0x25, 0x74, 0x2b, 0x00, 0x07, 0xe1,
- 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x6c, 0x69, 0x65, 0x75, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x04, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6f, 0x66, 0x65, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x12, 0x6f, 0x16, 0x79, 0x1c, 0x00, 0x07, 0xe2, 0x6e, 0x00,
- 0x79, 0x09, 0x40, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x76, 0x65, 0x72, 0x00, 0x00,
- 0x07, 0x00, 0x07, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40, 0x07, 0x6c, 0x65,
- 0x00, 0x00, 0x07, 0xe4, 0x66, 0x00, 0x6c, 0x0a, 0x6d, 0x0c, 0x73, 0x12,
- 0x40, 0x07, 0x65, 0x6e, 0x73, 0x74, 0x61, 0x68, 0x6c, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x6e, 0x6e, 0x00, 0x40, 0x09, 0x6c, 0x69, 0x6e, 0x67,
- 0x00, 0xe5, 0x61, 0x00, 0x65, 0x02, 0x67, 0x06, 0x68, 0x0a, 0x6f, 0x0e,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0xe2, 0x62, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x65, 0x72, 0x74,
- 0x6f, 0x00, 0x40, 0x07, 0x65, 0x74, 0x74, 0x6f, 0x00, 0xe2, 0x65, 0x00,
- 0x6b, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07,
- 0x62, 0x61, 0x75, 0x64, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x6f,
- 0x06, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x65, 0x79, 0x00,
- 0x40, 0x07, 0x6f, 0x72, 0x67, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x6f, 0x00,
- 0xe2, 0x61, 0x00, 0x7a, 0x0c, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x65, 0x04,
- 0x69, 0x1a, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x64, 0x65, 0x00, 0x40, 0x09, 0x65, 0x72, 0x61, 0x00, 0x40, 0x07,
- 0x61, 0x64, 0x68, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x00, 0x00, 0x07, 0xc0,
- 0x61, 0x1a, 0x37, 0x00, 0x46, 0x00, 0xd3, 0x00, 0x36, 0x01, 0x98, 0x01,
- 0x00, 0x00, 0xa6, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xc5, 0x01,
- 0xc9, 0x01, 0x14, 0x02, 0x85, 0x02, 0xb5, 0x02, 0x00, 0x00, 0xcb, 0x02,
- 0xd4, 0x02, 0xe3, 0x02, 0xd6, 0x03, 0x0d, 0x04, 0x30, 0x04, 0x3c, 0x04,
- 0x5b, 0x04, 0x6e, 0x04, 0x7f, 0x04, 0xe2, 0x63, 0x00, 0x6e, 0x04, 0x40,
- 0x07, 0x68, 0x00, 0x40, 0x07, 0x6f, 0x6b, 0x65, 0x00, 0xe8, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x19, 0x69, 0x53, 0x6c, 0x6c, 0x73, 0x71, 0x74, 0x76,
- 0x79, 0x78, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x79, 0x10, 0xe2, 0x65, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00,
- 0x07, 0x00, 0x07, 0xe2, 0x72, 0x00, 0x73, 0x24, 0xe2, 0x73, 0x00, 0x74,
- 0x05, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6f,
- 0x04, 0x73, 0x06, 0x00, 0x09, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x70,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x65, 0x72, 0x72, 0x65,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x73, 0x73, 0x69,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x68, 0x04, 0x6b,
- 0x2b, 0x40, 0x07, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0e, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40, 0x07, 0x62, 0x65, 0x61, 0x75, 0x00,
- 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x73, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c,
- 0x65, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00, 0xe7, 0x00, 0x00, 0x65,
- 0x02, 0x66, 0x0b, 0x69, 0x11, 0x6e, 0x16, 0x77, 0x1a, 0x79, 0x20, 0x00,
- 0x07, 0x40, 0x07, 0x66, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x6f, 0x72, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x00, 0x06, 0xe8, 0x00, 0x00,
- 0x64, 0x02, 0x65, 0x0c, 0x67, 0x13, 0x69, 0x22, 0x6e, 0x26, 0x6f, 0x2b,
- 0x72, 0x31, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x62, 0x65, 0x72, 0x72,
- 0x79, 0x00, 0x40, 0x07, 0x72, 0x69, 0x63, 0x6b, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x6c,
- 0x66, 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe3, 0x63, 0x00, 0x67, 0x04, 0x71,
- 0x10, 0x40, 0x07, 0x6b, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x7a, 0x00, 0x40, 0x07, 0x75, 0x65, 0x7a, 0x00, 0xe2,
- 0x67, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x00, 0x74, 0x67, 0x65, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x6c, 0x00, 0x72, 0x05, 0x74, 0x0e, 0x40,
- 0x07, 0x69, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x73, 0x00, 0x40, 0x07, 0x75, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x16, 0x6c, 0x1a, 0x6f, 0x34, 0x76, 0x3a, 0xe2,
- 0x69, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x64, 0x73, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x78,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0e, 0x40, 0x07, 0x6e, 0x64,
- 0x00, 0x40, 0x07, 0x72, 0x62, 0x6c, 0x61, 0x64, 0x65, 0x00, 0x40, 0x07,
- 0x6e, 0x73, 0x00, 0x40, 0x07, 0x64, 0x65, 0x78, 0x00, 0x40, 0x07, 0x61,
- 0x61, 0x67, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x45, 0x6d, 0x54,
- 0x6e, 0x59, 0x75, 0x5e, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe7, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x09, 0x6f, 0x15, 0x73, 0x1e, 0x74, 0x27, 0x79, 0x2f,
- 0x00, 0x09, 0x40, 0x09, 0x73, 0x71, 0x75, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x00, 0x00,
- 0x76, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x00, 0x69, 0x63, 0x69, 0x73, 0x6d, 0x00, 0x00,
- 0x06, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x72, 0x04, 0x00, 0x06, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x65,
- 0x79, 0x00, 0x40, 0x07, 0x6c, 0x75, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x64, 0x07, 0x6e, 0x0b, 0x73, 0x16, 0x74, 0x1d, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x74, 0x61, 0x64,
- 0x74, 0x00, 0x40, 0x00, 0x67, 0x65, 0x6e, 0x00, 0xe3, 0x6e, 0x00, 0x73,
- 0x05, 0x74, 0x0d, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x65, 0x76,
- 0x65, 0x6c, 0x74, 0x00, 0x00, 0x07, 0x40, 0x06, 0x75, 0x65, 0x66, 0x6f,
- 0x72, 0x74, 0x00, 0xe2, 0x73, 0x00, 0x79, 0x08, 0x40, 0x07, 0x63, 0x68,
- 0x61, 0x63, 0x68, 0x00, 0x00, 0x07, 0xe8, 0x61, 0x00, 0x63, 0x3e, 0x65,
- 0x43, 0x69, 0x99, 0x6c, 0xa9, 0x73, 0xae, 0x74, 0xc2, 0x77, 0xdc, 0xe4,
- 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x24, 0x72, 0x30, 0x00, 0x07, 0xe3, 0x65,
- 0x00, 0x69, 0x04, 0x79, 0x17, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6f,
- 0x00, 0x40, 0x07, 0x6f, 0x65, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x63,
- 0x0d, 0x6c, 0x14, 0x6d, 0x19, 0x6e, 0x2a, 0x74, 0x42, 0x00, 0x07, 0xe2,
- 0x6e, 0x00, 0x75, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x72, 0x61, 0x6e, 0x73, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0xe3, 0x62, 0x00, 0x64, 0x06, 0x7a, 0x0a, 0x40, 0x07,
- 0x65, 0x72, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x77, 0x65,
- 0x69, 0x67, 0x00, 0x40, 0x07, 0x74, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x65,
- 0x09, 0x40, 0x07, 0x72, 0x75, 0x63, 0x69, 0x61, 0x6e, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x79, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x08,
- 0x00, 0x07, 0x40, 0x07, 0x74, 0x74, 0x69, 0x00, 0x40, 0x07, 0x6e, 0x69,
- 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x05, 0x72, 0x09, 0x40, 0x07, 0x6e, 0x64,
- 0x00, 0x40, 0x07, 0x76, 0x00, 0x40, 0x07, 0x6f, 0x70, 0x6f, 0x76, 0x69,
- 0x63, 0x68, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0xe3, 0x61, 0x00,
- 0x68, 0x07, 0x74, 0x1c, 0x40, 0x07, 0x72, 0x69, 0x61, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x6b, 0x02, 0x73, 0x06, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x00,
- 0x40, 0x07, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x77,
- 0x07, 0x40, 0x07, 0x72, 0x64, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x69,
- 0x6c, 0x65, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x72, 0x06, 0x73, 0x0b, 0x74,
- 0x12, 0x40, 0x07, 0x75, 0x6c, 0x74, 0x00, 0x40, 0x07, 0x6b, 0x65, 0x00,
- 0x40, 0x07, 0x73, 0x65, 0x61, 0x75, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x64,
- 0x67, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x16, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6c, 0x0b, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05,
- 0x40, 0x07, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x06, 0x79, 0x0a, 0x40, 0x07, 0x6e, 0x6e, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x63, 0x06,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07,
- 0x65, 0x6c, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x65, 0x00, 0xfd, 0x00, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x63, 0x47, 0x00, 0x64, 0x4e, 0x00, 0x66, 0x6d,
- 0x00, 0x68, 0x72, 0x00, 0x69, 0x76, 0x00, 0x6b, 0x7a, 0x00, 0x6d, 0x82,
- 0x00, 0x6e, 0x9c, 0x00, 0x70, 0xae, 0x00, 0x73, 0xb4, 0x00, 0x74, 0x08,
- 0x01, 0x00, 0x0d, 0xe5, 0x61, 0x00, 0x62, 0x07, 0x65, 0x10, 0x69, 0x1c,
- 0x79, 0x38, 0x40, 0x07, 0x69, 0x79, 0x61, 0x74, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x6d, 0x61, 0x69, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe3, 0x63, 0x00, 0x6b, 0x05, 0x6e,
- 0x07, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x69, 0x6e, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x68, 0x62, 0x61, 0x68, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x0e,
- 0xe1, 0x6c, 0x00, 0xe2, 0x66, 0x00, 0x70, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72,
- 0x64, 0x00, 0x40, 0x07, 0x75, 0x73, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x7a, 0x00, 0x40, 0x07, 0x65, 0x79, 0x73, 0x65, 0x72, 0x00, 0xe2,
- 0x70, 0x00, 0x73, 0x0e, 0x40, 0x07, 0x65, 0x6c, 0x73, 0x74, 0x69, 0x6c,
- 0x74, 0x73, 0x6b, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x66, 0x65, 0x6c, 0x64,
- 0x00, 0xe2, 0x6e, 0x00, 0x79, 0x08, 0x40, 0x07, 0x79, 0x6d, 0x65, 0x64,
- 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x74,
- 0x00, 0xe4, 0x68, 0x00, 0x6b, 0x14, 0x73, 0x19, 0x74, 0x3e, 0xe3, 0x00,
- 0x00, 0x64, 0x02, 0x6d, 0x07, 0x00, 0x07, 0x40, 0x07, 0x69, 0x65, 0x00,
- 0x40, 0x07, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x0e, 0x6f, 0x1a, 0x00, 0x07, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x00, 0x07,
- 0xe2, 0x62, 0x00, 0x79, 0x06, 0x40, 0x07, 0x65, 0x6c, 0x74, 0x00, 0x00,
- 0x07, 0xe4, 0x61, 0x00, 0x67, 0x04, 0x68, 0x0a, 0x6c, 0x1f, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x0a, 0x00, 0x07, 0x40, 0x07, 0x72, 0x66, 0x6f, 0x72, 0x64,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x64, 0x67, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x79, 0x12, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
- 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x64, 0x06, 0x75, 0x15,
- 0x00, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x62, 0x00, 0x65, 0x06, 0x40,
- 0x07, 0x65, 0x72, 0x67, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6b,
- 0x79, 0x75, 0x00, 0xc1, 0x41, 0x3a, 0x79, 0x00, 0x7b, 0x00, 0xa2, 0x00,
- 0xa6, 0x00, 0xb1, 0x00, 0xba, 0x00, 0xca, 0x00, 0xcc, 0x00, 0x00, 0x00,
- 0xd1, 0x00, 0xd6, 0x00, 0xd8, 0x00, 0xda, 0x00, 0xde, 0x00, 0xe3, 0x00,
- 0xe8, 0x00, 0x02, 0x01, 0x0d, 0x01, 0x11, 0x01, 0x15, 0x01, 0x2e, 0x01,
- 0x3d, 0x01, 0x48, 0x01, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5c, 0x01, 0x5f, 0x06, 0x61, 0x06, 0x00, 0x00, 0x86, 0x09, 0x00, 0x00,
- 0x5e, 0x0c, 0x62, 0x0c, 0xae, 0x0f, 0xdb, 0x11, 0xe5, 0x11, 0x14, 0x12,
- 0xa3, 0x12, 0x0e, 0x13, 0x67, 0x13, 0x2f, 0x15, 0x9e, 0x16, 0xb5, 0x16,
- 0x00, 0x00, 0xd0, 0x16, 0x1a, 0x1a, 0x7a, 0x1c, 0xa9, 0x1c, 0x00, 0x00,
- 0x60, 0x1d, 0xca, 0x1d, 0x00, 0x14, 0xe8, 0x00, 0x00, 0x43, 0x02, 0x4c,
- 0x04, 0x4d, 0x08, 0x50, 0x0a, 0x52, 0x0c, 0x53, 0x10, 0x54, 0x14, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x07, 0x54, 0x00, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x53, 0x00, 0x40, 0x00, 0x45, 0x00, 0x00, 0x00, 0x40, 0x00, 0x41,
- 0x00, 0xe2, 0x00, 0x00, 0x53, 0x02, 0x00, 0x07, 0x40, 0x07, 0x49, 0x00,
- 0xe2, 0x00, 0x00, 0x49, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00,
- 0x41, 0x02, 0x43, 0x07, 0x00, 0x07, 0x40, 0x00, 0x54, 0x4f, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x07, 0x4d, 0x4c, 0x00, 0x40, 0x07, 0x44, 0x53,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x52, 0x00, 0x40, 0x07, 0x45,
- 0x73, 0x00, 0x40, 0x07, 0x50, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x42, 0x02,
- 0x50, 0x04, 0x53, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x43, 0x00,
- 0x46, 0x04, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x4c, 0x00,
- 0x40, 0x00, 0x4f, 0x00, 0xe6, 0x00, 0x00, 0x41, 0x02, 0x45, 0x04, 0x53,
- 0x06, 0x54, 0x08, 0x57, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x44, 0x02, 0x4f, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x4c, 0x00, 0xe2, 0x53, 0x00, 0x56,
- 0x04, 0x40, 0x07, 0x45, 0x00, 0x00, 0x00, 0x40, 0x07, 0x4e, 0x00, 0xe2,
- 0x00, 0x00, 0x41, 0x02, 0x00, 0x07, 0xe2, 0x4b, 0x00, 0x54, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0x51, 0x00, 0x8a, 0x00,
- 0xba, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xf1, 0x00, 0x0d, 0x01, 0x25, 0x01,
- 0x00, 0x00, 0x33, 0x01, 0x5a, 0x01, 0x1f, 0x02, 0xae, 0x02, 0x00, 0x00,
- 0x72, 0x03, 0x00, 0x00, 0x83, 0x03, 0x08, 0x04, 0x4a, 0x04, 0x83, 0x04,
- 0xb4, 0x04, 0xe8, 0x04, 0xee, 0x04, 0xfd, 0x04, 0xe3, 0x62, 0x00, 0x72,
- 0x02, 0x74, 0x0f, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x63, 0x68, 0x69, 0x00,
- 0xe3, 0x62, 0x00, 0x69, 0x12, 0x72, 0x26, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0xe2, 0x6b, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x61, 0x00, 0xe4, 0x61, 0x00,
- 0x63, 0x08, 0x68, 0x1a, 0x72, 0x1e, 0x40, 0x07, 0x6a, 0x61, 0x77, 0x65,
- 0x61, 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x0b, 0x40, 0x07, 0x61, 0x72, 0x6f,
- 0x6d, 0x79, 0x63, 0x65, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x6f, 0x00, 0xe5, 0x61, 0x00,
- 0x64, 0x04, 0x65, 0x13, 0x69, 0x15, 0x72, 0x19, 0x40, 0x07, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07, 0x63,
- 0x65, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0xe2,
- 0x61, 0x00, 0x65, 0x06, 0x40, 0x07, 0x76, 0x69, 0x64, 0x00, 0x40, 0x07,
- 0x77, 0x61, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x05, 0x40, 0x07, 0x61, 0x77, 0x00, 0x40,
- 0x09, 0x74, 0x61, 0x72, 0x69, 0x75, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x0f, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x67, 0x00, 0x70,
- 0x05, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe4, 0x61,
- 0x00, 0x68, 0x04, 0x69, 0x1a, 0x73, 0x1c, 0x40, 0x07, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x76, 0x00, 0x00, 0x07, 0x00,
- 0x07, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x65, 0x22, 0x69, 0x2e, 0x6b, 0x4e,
- 0x6c, 0x50, 0x6f, 0x62, 0x74, 0x71, 0x76, 0x76, 0x77, 0xa3, 0x79, 0xa9,
- 0x00, 0x12, 0xe4, 0x64, 0x00, 0x6d, 0x0b, 0x73, 0x10, 0x7a, 0x12, 0xe2,
- 0x69, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x69, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x72, 0x00, 0xe2, 0x6d,
- 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x6f, 0x00, 0xe2, 0x6e,
- 0x00, 0x73, 0x0e, 0xe2, 0x61, 0x00, 0x67, 0x04, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2, 0x62, 0x00, 0x68, 0x06, 0x40, 0x07,
- 0x75, 0x72, 0x79, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x69, 0x00, 0x75,
- 0x04, 0x79, 0x09, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0xe2, 0x6d, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x07, 0x69, 0x6b, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x64, 0x00, 0x74, 0x1f, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x69, 0x0b, 0x00, 0x07, 0x40,
- 0x06, 0x6e, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40, 0x09, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x07, 0x65, 0x65, 0x6e,
- 0x00, 0x40, 0x07, 0x75, 0x74, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x6d,
- 0x26, 0x6f, 0x31, 0x70, 0x4b, 0x73, 0x51, 0x75, 0x6e, 0x00, 0x07, 0xe2,
- 0x6e, 0x00, 0x72, 0x06, 0x40, 0x07, 0x74, 0x68, 0x61, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x04, 0x6b, 0x0a, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x09, 0x74, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0xe3, 0x61,
- 0x00, 0x73, 0x09, 0x79, 0x0e, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x06, 0x40, 0x07, 0x65, 0x74, 0x00, 0x40, 0x07, 0x65, 0x64, 0x00,
- 0x40, 0x07, 0x73, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x75,
- 0x11, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x74, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xeb, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06,
- 0x63, 0x08, 0x64, 0x16, 0x66, 0x46, 0x67, 0x59, 0x68, 0x64, 0x6b, 0x6c,
- 0x73, 0x7a, 0x74, 0x81, 0x00, 0x07, 0x40, 0x00, 0x61, 0x00, 0x00, 0x07,
- 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x7a, 0x00,
- 0x00, 0x07, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x69, 0x0d, 0x6f,
- 0x15, 0x72, 0x1b, 0x79, 0x1f, 0x00, 0x2e, 0x40, 0x07, 0x75, 0x72, 0x67,
- 0x00, 0x40, 0x07, 0x72, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x73, 0x74,
- 0x61, 0x00, 0x40, 0x07, 0x76, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x64, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x7a, 0x65, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x0e, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x64,
- 0x72, 0x69, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6b, 0x72, 0x69, 0x74,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x13, 0x69, 0x19, 0x6f, 0x1f, 0xe3, 0x00,
- 0x00, 0x6e, 0x02, 0x79, 0x06, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x61, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x72, 0x69, 0x61, 0x00, 0x40,
- 0x07, 0x61, 0x67, 0x6f, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x70, 0x00,
- 0xe2, 0x68, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x72,
- 0x6f, 0x00, 0xe7, 0x61, 0x00, 0x62, 0x3b, 0x64, 0x42, 0x67, 0x49, 0x6e,
- 0x5f, 0x6f, 0x65, 0x74, 0x6b, 0xe9, 0x00, 0x00, 0x63, 0x02, 0x67, 0x07,
- 0x68, 0x0e, 0x6a, 0x10, 0x6e, 0x16, 0x73, 0x18, 0x74, 0x1e, 0x77, 0x23,
- 0x00, 0x07, 0x40, 0x09, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x73, 0x73,
- 0x61, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x76, 0x6f, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x74, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x76, 0x00, 0x40,
- 0x07, 0x61, 0x6b, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x65, 0x73, 0x00, 0x40,
- 0x07, 0x69, 0x6e, 0x69, 0x61, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x6f,
- 0x0b, 0x40, 0x07, 0x73, 0x73, 0x6f, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x66, 0x66, 0x00, 0x40, 0x07,
- 0x79, 0x61, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x00, 0xe4, 0x68, 0x00, 0x6b, 0x04, 0x71, 0x20, 0x73, 0x28,
- 0x40, 0x07, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x63, 0x00, 0x6f, 0x08, 0x40, 0x07, 0x68, 0x65, 0x77,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x75, 0x61,
- 0x74, 0x63, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6e,
- 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x75, 0x18, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x05,
- 0x40, 0x09, 0x61, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6c, 0x69, 0x61, 0x00, 0xe5, 0x64, 0x00, 0x6c, 0x04, 0x6e,
- 0x06, 0x73, 0x17, 0x74, 0x1e, 0x40, 0x09, 0x69, 0x00, 0x00, 0x07, 0xe1,
- 0x64, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x05, 0x40, 0x07, 0x72, 0x73, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x73, 0x75, 0x72, 0x65, 0x00, 0x40,
- 0x00, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x0f,
- 0x6f, 0x14, 0xe2, 0x67, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x07, 0x6e, 0x61, 0x68, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x00, 0xe2, 0x6e,
- 0x00, 0x79, 0x08, 0x40, 0x07, 0x61, 0x72, 0x6f, 0x6c, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40,
- 0x07, 0x79, 0x65, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72,
- 0x73, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x68,
- 0x4e, 0x00, 0x69, 0xbc, 0x01, 0x6f, 0xe4, 0x01, 0x72, 0x96, 0x02, 0x75,
- 0xe3, 0x02, 0x79, 0xf0, 0x02, 0x00, 0x07, 0xe3, 0x6c, 0x00, 0x6e, 0x04,
- 0x72, 0x26, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x76,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x07, 0x00, 0x09, 0xe3, 0x61, 0x00, 0x62, 0x08, 0x6c, 0x11, 0x40,
- 0x07, 0x6d, 0x6f, 0x75, 0x63, 0x68, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6f,
- 0x75, 0x67, 0x68, 0x00, 0x40, 0x07, 0x61, 0x74, 0x74, 0x69, 0x00, 0xf9,
- 0x65, 0x00, 0x00, 0x69, 0x2e, 0x00, 0x6c, 0x52, 0x00, 0x6d, 0x70, 0x00,
- 0x6e, 0x76, 0x00, 0x6f, 0x92, 0x00, 0x72, 0xa9, 0x00, 0x75, 0xc9, 0x00,
- 0x77, 0x06, 0x01, 0xe5, 0x61, 0x00, 0x64, 0x04, 0x68, 0x09, 0x6c, 0x13,
- 0x6e, 0x1a, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40,
- 0x07, 0x65, 0x72, 0x61, 0x7a, 0x61, 0x64, 0x65, 0x00, 0x40, 0x07, 0x6c,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x63, 0x74, 0x61, 0x64, 0x79,
- 0x00, 0xe4, 0x61, 0x00, 0x63, 0x0a, 0x6c, 0x0e, 0x6e, 0x14, 0x40, 0x07,
- 0x70, 0x61, 0x72, 0x65, 0x6c, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x6b, 0x00,
- 0x40, 0x07, 0x6c, 0x65, 0x72, 0x00, 0x40, 0x07, 0x64, 0x6c, 0x65, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0x40, 0x07, 0x73, 0x69, 0x6e, 0x67,
- 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x07, 0x40, 0x07, 0x6d, 0x61,
- 0x6e, 0x6e, 0x00, 0x40, 0x07, 0x7a, 0x00, 0x40, 0x07, 0x69, 0x64, 0x74,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe2, 0x62, 0x00, 0x75, 0x05, 0x40,
- 0x07, 0x65, 0x6c, 0x00, 0x40, 0x07, 0x7a, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x69, 0x64, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x70, 0x08, 0x40, 0x07,
- 0x6e, 0x62, 0x65, 0x72, 0x67, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x68, 0x61,
- 0x75, 0x65, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x08, 0x40, 0x07, 0x65,
- 0x66, 0x66, 0x65, 0x72, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x08, 0x40, 0x07,
- 0x69, 0x6e, 0x67, 0x65, 0x72, 0x00, 0x40, 0x07, 0x64, 0x65, 0x72, 0x00,
- 0xe4, 0x62, 0x00, 0x6c, 0x06, 0x6d, 0x11, 0x79, 0x22, 0x40, 0x07, 0x65,
- 0x72, 0x74, 0x00, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x7a, 0x00,
- 0x00, 0x07, 0xe2, 0x61, 0x00, 0x70, 0x05, 0x40, 0x07, 0x6e, 0x6e, 0x00,
- 0x40, 0x07, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x6b, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x24, 0x69, 0x36, 0xe1, 0x72, 0x00, 0xe2,
- 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x7a, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6b, 0x0b, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x67, 0x67, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x6f, 0x70, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x70,
- 0x07, 0x40, 0x07, 0x74, 0x7a, 0x65, 0x72, 0x00, 0x40, 0x07, 0x70, 0x65,
- 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x05, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x70, 0x1e, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73,
- 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6f, 0x00, 0xe3, 0x70, 0x00,
- 0x72, 0x0d, 0x74, 0x26, 0xe2, 0x65, 0x00, 0x75, 0x04, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x70, 0x00, 0x73, 0x0e, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x63, 0x02, 0x69,
- 0x2e, 0x6c, 0x32, 0x73, 0x38, 0x74, 0x5d, 0x00, 0x06, 0xe1, 0x68, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x09, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x64, 0x00, 0xe2, 0x6d, 0x00, 0x77, 0x0d, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x0d, 0x00,
- 0x07, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x07, 0x68, 0x00,
- 0x40, 0x07, 0x64, 0x61, 0x6c, 0x65, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x11,
- 0x69, 0x1c, 0x6f, 0x36, 0x75, 0x3c, 0xe2, 0x62, 0x00, 0x6e, 0x06, 0x40,
- 0x09, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x65, 0x6e, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x61,
- 0x00, 0x62, 0x06, 0x70, 0x0c, 0x40, 0x07, 0x62, 0x69, 0x6e, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x06, 0x74, 0x75, 0x72, 0x65, 0x00,
- 0x40, 0x07, 0x6f, 0x67, 0x65, 0x00, 0x40, 0x07, 0x67, 0x67, 0x73, 0x00,
- 0xe2, 0x64, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x65, 0x79,
- 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x05, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe1,
- 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39, 0x00,
- 0x5c, 0x00, 0x65, 0x00, 0x94, 0x00, 0xa1, 0x00, 0x00, 0x00, 0xb1, 0x00,
- 0x00, 0x00, 0xcc, 0x00, 0xe2, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x42, 0x01,
- 0x74, 0x01, 0xd0, 0x01, 0xd5, 0x01, 0x03, 0x02, 0x0a, 0x02, 0x00, 0x00,
- 0x5d, 0x02, 0x6c, 0x02, 0x7a, 0x02, 0xa5, 0x02, 0xab, 0x02, 0xbc, 0x02,
- 0x00, 0x0d, 0xe5, 0x62, 0x00, 0x67, 0x06, 0x6e, 0x0c, 0x72, 0x0e, 0x74,
- 0x12, 0x40, 0x07, 0x6f, 0x72, 0x67, 0x00, 0x40, 0x07, 0x72, 0x61, 0x6d,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x74, 0x6c, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x73, 0x74, 0x69, 0x61, 0x6e, 0x00, 0xe4, 0x00,
- 0x00, 0x6f, 0x02, 0x72, 0x08, 0x75, 0x20, 0x00, 0x00, 0x40, 0x07, 0x6e,
- 0x61, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x61, 0x74,
- 0x00, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x61, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x62,
- 0x00, 0x67, 0x06, 0x40, 0x07, 0x65, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x65,
- 0x72, 0x00, 0xe4, 0x61, 0x00, 0x6f, 0x02, 0x72, 0x08, 0x75, 0x0c, 0x00,
- 0x07, 0x40, 0x07, 0x76, 0x69, 0x61, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x07, 0x6e, 0x64, 0x6f, 0x00, 0xe2, 0x6b, 0x00, 0x6e, 0x04, 0x40, 0x07,
- 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x66, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x6c, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x67, 0x00, 0xe8, 0x61, 0x00,
- 0x65, 0x07, 0x69, 0x29, 0x6a, 0x2d, 0x6b, 0x32, 0x6c, 0x38, 0x6d, 0x3e,
- 0x7a, 0x42, 0x40, 0x07, 0x73, 0x73, 0x69, 0x65, 0x00, 0xe3, 0x63, 0x00,
- 0x6e, 0x07, 0x75, 0x0b, 0x40, 0x07, 0x74, 0x72, 0x69, 0x63, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x04, 0x40,
- 0x07, 0x64, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x07, 0x75, 0x6b, 0x00, 0x40, 0x07, 0x69, 0x72, 0x6b, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x73, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x69,
- 0x63, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x07, 0x74, 0x26, 0x40, 0x07,
- 0x72, 0x61, 0x6e, 0x67, 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x06, 0x74, 0x0d,
- 0x40, 0x09, 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x69, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x63, 0x00,
- 0x40, 0x07, 0x65, 0x78, 0x00, 0xe7, 0x61, 0x00, 0x64, 0x05, 0x65, 0x0a,
- 0x67, 0x25, 0x69, 0x2b, 0x6e, 0x30, 0x73, 0x43, 0x40, 0x09, 0x74, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x67, 0x04, 0x40,
- 0x09, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0x40, 0x07, 0x68,
- 0x6f, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x09, 0x40, 0x07, 0x63, 0x68, 0x65, 0x72, 0x69, 0x62, 0x00, 0x40, 0x07,
- 0x74, 0x74, 0x00, 0x40, 0x07, 0x75, 0x72, 0x72, 0x6f, 0x75, 0x6e, 0x64,
- 0x00, 0x40, 0x07, 0x75, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x6f,
- 0x09, 0x74, 0x0d, 0x00, 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x69, 0x00,
- 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x75, 0x09, 0x00,
- 0x07, 0x40, 0x09, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x67,
- 0x69, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x75, 0x6f, 0x79, 0x61, 0x00, 0xe6,
- 0x61, 0x00, 0x62, 0x02, 0x65, 0x15, 0x67, 0x25, 0x70, 0x32, 0x72, 0x38,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x67, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x74, 0x69,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07,
- 0x6f, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x00, 0xe3, 0x00,
- 0x00, 0x68, 0x02, 0x6f, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x72, 0x00, 0x73, 0x05, 0x40, 0x07, 0x61, 0x74, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x09, 0x69, 0x17, 0x72, 0x1d,
- 0x40, 0x07, 0x73, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x07, 0x6c, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07,
- 0x61, 0x72, 0x64, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05,
- 0x40, 0x07, 0x6e, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe3, 0x63, 0x00,
- 0x66, 0x09, 0x6d, 0x0f, 0x40, 0x07, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x75, 0x72,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0xf8, 0x61, 0x00, 0x00, 0x63, 0xfe, 0x00,
- 0x65, 0x09, 0x01, 0x69, 0x44, 0x02, 0x6f, 0xb3, 0x02, 0x72, 0xf1, 0x02,
- 0x75, 0x16, 0x03, 0x79, 0x1b, 0x03, 0xea, 0x63, 0x00, 0x66, 0x09, 0x6b,
- 0x0f, 0x6e, 0x37, 0x70, 0x65, 0x72, 0x6b, 0x73, 0xad, 0x75, 0xb2, 0x76,
- 0xc4, 0x77, 0xd3, 0x40, 0x07, 0x6b, 0x6c, 0x65, 0x74, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x66, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe6, 0x61,
- 0x00, 0x65, 0x02, 0x67, 0x04, 0x6b, 0x0a, 0x6e, 0x10, 0x74, 0x1b, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x68, 0x61, 0x69, 0x00, 0x40, 0x07, 0x61,
- 0x72, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x75, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x69, 0x72,
- 0x6f, 0x00, 0xe7, 0x65, 0x00, 0x69, 0x08, 0x6c, 0x17, 0x6d, 0x1d, 0x6f,
- 0x21, 0x70, 0x25, 0x72, 0x2e, 0x40, 0x07, 0x50, 0x6f, 0x69, 0x6e, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x66, 0x06, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x61,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x75, 0x05,
- 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x68, 0x61,
- 0x72, 0x61, 0x6e, 0x73, 0x6b, 0x79, 0x00, 0xfc, 0x61, 0x00, 0x00, 0x62,
- 0x02, 0x00, 0x65, 0x0e, 0x00, 0x66, 0x1e, 0x00, 0x69, 0x26, 0x00, 0x6c,
- 0x2b, 0x00, 0x6e, 0x57, 0x00, 0x6f, 0x76, 0x00, 0x70, 0x7a, 0x00, 0x72,
- 0x92, 0x00, 0x74, 0xee, 0x00, 0x76, 0x03, 0x01, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x00, 0xe2, 0x6e,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x63,
- 0x6b, 0x00, 0x40, 0x07, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x07,
- 0x6c, 0x61, 0x00, 0xe5, 0x62, 0x00, 0x64, 0x04, 0x69, 0x09, 0x6c, 0x0d,
- 0x74, 0x1c, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x06, 0x00, 0x07,
- 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x79, 0x0a, 0x7a, 0x10, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x64, 0x6f, 0x61, 0x68, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x68, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe3, 0x61,
- 0x00, 0x68, 0x05, 0x70, 0x0b, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x64, 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00, 0xe9, 0x61,
- 0x00, 0x65, 0x10, 0x69, 0x14, 0x6c, 0x20, 0x6d, 0x26, 0x70, 0x2b, 0x72,
- 0x2f, 0x77, 0x3f, 0x79, 0x45, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6f,
- 0x64, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x09, 0x40,
- 0x07, 0x64, 0x6e, 0x61, 0x64, 0x7a, 0x65, 0x00, 0x00, 0x07, 0xe9, 0x27,
- 0x00, 0x65, 0x06, 0x69, 0x0c, 0x6a, 0x11, 0x6b, 0x1c, 0x6c, 0x22, 0x6e,
- 0x31, 0x72, 0x4a, 0x76, 0x58, 0x40, 0x07, 0x69, 0x74, 0x65, 0x00, 0x40,
- 0x07, 0x6c, 0x64, 0x73, 0x00, 0x40, 0x09, 0x74, 0x65, 0x00, 0x40, 0x07,
- 0x69, 0x61, 0x7a, 0x68, 0x75, 0x61, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f,
- 0x6b, 0x75, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x6f, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x09, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x6c, 0x04,
- 0x40, 0x07, 0x7a, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x61,
- 0x00, 0xe4, 0x63, 0x00, 0x70, 0x07, 0x72, 0x0f, 0x73, 0x1f, 0x40, 0x07,
- 0x6b, 0x6c, 0x65, 0x79, 0x00, 0x40, 0x07, 0x7a, 0x69, 0x6c, 0x6c, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6f, 0x72, 0x6e, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x06, 0x40, 0x06,
- 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6b, 0x6f, 0x76, 0x69, 0x74,
- 0x63, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0f, 0x6f, 0x15, 0xe2, 0x6b,
- 0x00, 0x76, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x70, 0x6f, 0x72, 0x74,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x07, 0x70, 0x73, 0x68,
- 0x69, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xc1, 0x61, 0x16,
- 0x31, 0x00, 0x33, 0x00, 0x42, 0x00, 0x65, 0x00, 0x77, 0x00, 0x8e, 0x00,
- 0x00, 0x00, 0xb5, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x00,
- 0x0f, 0x01, 0x34, 0x01, 0x7a, 0x01, 0xeb, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0xf6, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0x00, 0x07,
- 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x73, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x1a, 0xe2, 0x6c, 0x00, 0x72,
- 0x06, 0x40, 0x07, 0x69, 0x75, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07,
- 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x64,
- 0x02, 0x6e, 0x0b, 0x00, 0x07, 0x40, 0x07, 0x68, 0x61, 0x72, 0x74, 0x68,
- 0x61, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0xe3, 0x67, 0x00, 0x6d, 0x08,
- 0x72, 0x0e, 0x40, 0x07, 0x66, 0x72, 0x69, 0x65, 0x64, 0x00, 0x40, 0x07,
- 0x65, 0x6e, 0x73, 0x00, 0xe2, 0x70, 0x00, 0x72, 0x08, 0x40, 0x07, 0x69,
- 0x6e, 0x73, 0x6b, 0x69, 0x00, 0x40, 0x00, 0x61, 0x73, 0x00, 0xe3, 0x69,
- 0x00, 0x6d, 0x08, 0x75, 0x16, 0x40, 0x07, 0x73, 0x6d, 0x75, 0x6e, 0x64,
- 0x00, 0xe2, 0x65, 0x00, 0x75, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x64, 0x00, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x07, 0x61, 0x6e,
- 0x6f, 0x75, 0x6b, 0x00, 0xe3, 0x68, 0x00, 0x6b, 0x10, 0x6f, 0x22, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x07, 0x40, 0x00, 0x73, 0x6d,
- 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0x40, 0x07, 0x72,
- 0x73, 0x6b, 0x79, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x75, 0x0a, 0x76,
- 0x11, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x73, 0x69, 0x61, 0x00, 0x40,
- 0x06, 0x72, 0x69, 0x61, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x00, 0xe5, 0x65, 0x00, 0x6d, 0x06, 0x6f, 0x17,
- 0x70, 0x23, 0x73, 0x39, 0x40, 0x07, 0x6e, 0x6f, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6e, 0x74, 0x61, 0x6c, 0x00, 0x40, 0x07,
- 0x6e, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0xe2, 0x73, 0x00, 0x79, 0x0f, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x07, 0xe7, 0x61, 0x00, 0x62, 0x0c, 0x63, 0x11, 0x64, 0x18,
- 0x67, 0x26, 0x68, 0x53, 0x6b, 0x5b, 0xe2, 0x69, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x61, 0x00, 0x40, 0x07, 0x61, 0x64, 0x00, 0x40,
- 0x07, 0x6c, 0x61, 0x69, 0x72, 0x00, 0xe2, 0x62, 0x00, 0x68, 0x05, 0x40,
- 0x07, 0x61, 0x64, 0x00, 0x40, 0x07, 0x69, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x17, 0x68, 0x1b, 0x6c, 0x1d, 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x65, 0x73, 0x65,
- 0x00, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x67, 0x00, 0xe2, 0x6e, 0x00, 0x75,
- 0x02, 0x00, 0x00, 0x40, 0x07, 0x78, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x75, 0x73, 0x00, 0xe2, 0x74, 0x00, 0x79, 0x06,
- 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x65, 0x00, 0x75, 0x05, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x65, 0x6c, 0x6c, 0x61, 0x6e, 0x64, 0x00,
- 0xe3, 0x69, 0x00, 0x6f, 0x10, 0x79, 0x16, 0xe2, 0x6e, 0x00, 0x70, 0x06,
- 0x40, 0x07, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x07, 0x70, 0x79, 0x00, 0x40,
- 0x07, 0x70, 0x6a, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x02, 0x70, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x62, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe4,
- 0x61, 0x00, 0x69, 0x30, 0x6f, 0x36, 0x75, 0x7f, 0xe4, 0x63, 0x00, 0x73,
- 0x08, 0x74, 0x0f, 0x76, 0x14, 0x40, 0x07, 0x6b, 0x77, 0x61, 0x72, 0x65,
- 0x00, 0x40, 0x07, 0x68, 0x64, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x06, 0x00, 0x06, 0x40, 0x07,
- 0x63, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x63, 0x00, 0x40, 0x07, 0x6e, 0x6b,
- 0x79, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x0c, 0x76, 0x11, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x16, 0xe1, 0x6b, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x00, 0x09, 0x40, 0x07, 0x72, 0x70, 0x65, 0x65, 0x00, 0xe7, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x0e, 0x6f, 0x36, 0x75, 0x51, 0x79,
- 0x56, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x74, 0x61,
- 0x6e, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x07, 0x40, 0x07, 0x6e, 0x6f,
- 0x66, 0x66, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x6b, 0x00, 0x6c, 0x05,
- 0x40, 0x07, 0x65, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x06, 0x40, 0x07,
- 0x6e, 0x73, 0x6b, 0x00, 0x40, 0x07, 0x65, 0x74, 0x74, 0x00, 0x40, 0x07,
- 0x74, 0x73, 0x00, 0x40, 0x00, 0x72, 0x6e, 0x61, 0x00, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x11, 0x69, 0x1e, 0x6f, 0x2f, 0x79, 0x46, 0x00, 0x07,
- 0xe2, 0x6b, 0x00, 0x70, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x70,
- 0x6c, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x64, 0x00,
- 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x64, 0x07, 0x40, 0x07, 0x6b,
- 0x65, 0x72, 0x73, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2, 0x6f, 0x00,
- 0x77, 0x05, 0x40, 0x07, 0x70, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x6c, 0x74, 0x00, 0x40, 0x07, 0x64, 0x65,
- 0x72, 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x5c,
- 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x72, 0x00, 0xa0, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x19,
- 0x01, 0x00, 0x00, 0x46, 0x01, 0x4e, 0x01, 0x52, 0x01, 0x56, 0x01, 0xad,
- 0x01, 0xb3, 0x01, 0x00, 0x00, 0xb9, 0x01, 0x40, 0x07, 0x76, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x72, 0x08, 0x00, 0x00, 0x40, 0x07, 0x72,
- 0x72, 0x6f, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x63, 0x00, 0xe2, 0x64,
- 0x00, 0x6f, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x07, 0x69, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x08, 0x6f, 0x0c, 0x7a, 0x18, 0x00, 0x07, 0x40, 0x07, 0x72,
- 0x69, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x05,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x68, 0x65, 0x6e,
- 0x69, 0x74, 0x73, 0x79, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x6d, 0x16, 0x6f,
- 0x1a, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40,
- 0x07, 0x65, 0x00, 0x40, 0x07, 0x7a, 0x61, 0x00, 0xe9, 0x00, 0x00, 0x64,
- 0x02, 0x67, 0x11, 0x69, 0x21, 0x6a, 0x25, 0x6e, 0x29, 0x6f, 0x2d, 0x74,
- 0x32, 0x79, 0x37, 0x00, 0x07, 0xe2, 0x68, 0x00, 0x72, 0x06, 0x40, 0x07,
- 0x65, 0x69, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x04, 0x40, 0x07, 0x69, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x79, 0x00,
- 0x40, 0x07, 0x72, 0x61, 0x00, 0x40, 0x07, 0x61, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x68, 0x00, 0x77, 0x22,
- 0xe2, 0x69, 0x00, 0x6f, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x69, 0x74, 0x68, 0x00, 0x40, 0x07, 0x62, 0x6f, 0x6e, 0x6e, 0x65, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe4, 0x70, 0x00, 0x72,
- 0x0c, 0x73, 0x16, 0x74, 0x1a, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x6f, 0x75,
- 0x76, 0x6f, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x63, 0x65, 0x66, 0x6f, 0x72,
- 0x67, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x0a, 0x73, 0x1e, 0x77, 0x20, 0x00, 0x07, 0x40,
- 0x07, 0x6d, 0x70, 0x74, 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x72, 0x05,
- 0x79, 0x0b, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x06, 0x6e, 0x65, 0x72,
- 0x00, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x65, 0x73, 0x74, 0x00, 0x40,
- 0x07, 0x69, 0x65, 0x74, 0x00, 0x40, 0x07, 0x65, 0x74, 0x6f, 0x00, 0xe2,
- 0x69, 0x00, 0x75, 0x06, 0x40, 0x07, 0x6e, 0x6b, 0x61, 0x00, 0x40, 0x07,
- 0x7a, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x64, 0x00,
- 0x68, 0xbf, 0x00, 0x69, 0xc5, 0x00, 0x6f, 0x12, 0x01, 0x72, 0x21, 0x01,
- 0x75, 0x47, 0x01, 0x00, 0x00, 0xe7, 0x61, 0x00, 0x63, 0x05, 0x68, 0x0b,
- 0x69, 0x0f, 0x6d, 0x13, 0x6e, 0x15, 0x72, 0x33, 0x40, 0x07, 0x74, 0x7a,
- 0x00, 0x40, 0x07, 0x6b, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x69, 0x09,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x69, 0x73, 0x68, 0x00, 0xe2, 0x61, 0x00,
- 0x73, 0x05, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe3,
- 0x63, 0x00, 0x6b, 0x02, 0x74, 0x06, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6e, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x75, 0x73, 0x00, 0x00, 0x09, 0xe4, 0x61, 0x00, 0x65, 0x05,
- 0x6e, 0x09, 0x72, 0x4d, 0x40, 0x07, 0x72, 0x73, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0xe3, 0x63, 0x00, 0x67, 0x16, 0x73, 0x2b, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x16, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x72,
- 0x79, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x78, 0x00, 0xe6, 0x63, 0x00, 0x65,
- 0x04, 0x6c, 0x0c, 0x6e, 0x13, 0x72, 0x1f, 0x74, 0x30, 0x40, 0x07, 0x61,
- 0x00, 0x40, 0x07, 0x6c, 0x62, 0x65, 0x72, 0x67, 0x00, 0x40, 0x07, 0x6c,
- 0x61, 0x6e, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x78, 0x05, 0x40, 0x07, 0x7a,
- 0x61, 0x00, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x72, 0x61, 0x70, 0x68, 0x00, 0xe2, 0x73, 0x00,
- 0x7a, 0x09, 0x40, 0x07, 0x62, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x00, 0x00,
- 0x07, 0xe2, 0x63, 0x00, 0x6b, 0x04, 0x40, 0x07, 0x6b, 0x00, 0x40, 0x07,
- 0x61, 0x6e, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x1a,
- 0xe2, 0x67, 0x00, 0x74, 0x13, 0xe2, 0x66, 0x00, 0x73, 0x07, 0x40, 0x07,
- 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x74, 0x65, 0x65, 0x6e, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x6b, 0x00, 0xe2, 0x00, 0x00,
- 0x75, 0x02, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6e,
- 0x74, 0x6f, 0x00, 0x40, 0x07, 0x62, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x76, 0x07, 0x40, 0x07, 0x61, 0x67,
- 0x61, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6a, 0x61, 0x79, 0x61, 0x00, 0xf8,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0xd4, 0x00, 0x69, 0xc5, 0x01,
- 0x6f, 0xef, 0x01, 0x72, 0x66, 0x02, 0x75, 0xda, 0x02, 0x79, 0x12, 0x03,
- 0x00, 0x00, 0xec, 0x00, 0x00, 0x63, 0x02, 0x65, 0x18, 0x66, 0x1c, 0x69,
- 0x23, 0x6c, 0x2d, 0x6d, 0x4f, 0x6e, 0x56, 0x70, 0x85, 0x72, 0x8b, 0x74,
- 0xa6, 0x75, 0xb2, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x0d,
- 0x40, 0x07, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x66, 0x6f, 0x72,
- 0x64, 0x00, 0x40, 0x07, 0x72, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x17, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x67,
- 0x02, 0x69, 0x08, 0x00, 0x07, 0x40, 0x07, 0x72, 0x61, 0x64, 0x00, 0x40,
- 0x07, 0x73, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x66, 0x6f, 0x72, 0x64, 0x00, 0xe6, 0x00, 0x00, 0x64, 0x02, 0x66, 0x08,
- 0x69, 0x0e, 0x6c, 0x18, 0x74, 0x1d, 0x00, 0x07, 0x40, 0x07, 0x69, 0x73,
- 0x68, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x64, 0x00, 0x40, 0x07, 0x73, 0x6c,
- 0x61, 0x76, 0x73, 0x6b, 0x79, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x73, 0x00, 0xe3, 0x62,
- 0x00, 0x6b, 0x07, 0x72, 0x12, 0x40, 0x07, 0x75, 0x63, 0x6b, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x07, 0x62, 0x61, 0x63, 0x68, 0x00, 0xed, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x0a, 0x66, 0x0f, 0x69, 0x20, 0x6c, 0x4a, 0x6e, 0x4f, 0x70,
- 0x5f, 0x72, 0x8a, 0x74, 0xa2, 0x75, 0xa8, 0x76, 0xae, 0x77, 0xd0, 0x00,
- 0x00, 0x40, 0x07, 0x64, 0x69, 0x63, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x6c,
- 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe5, 0x00,
- 0x00, 0x62, 0x02, 0x65, 0x08, 0x6d, 0x11, 0x77, 0x17, 0x00, 0x0e, 0x40,
- 0x07, 0x65, 0x63, 0x6b, 0x00, 0xe2, 0x6d, 0x00, 0x72, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x74, 0x7a, 0x00, 0x40, 0x07, 0x61, 0x79,
- 0x00, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x06, 0x40,
- 0x07, 0x68, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x06, 0x40, 0x07,
- 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x04, 0x00,
- 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x73, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x62, 0x65, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x19, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0x40, 0x07, 0x61, 0x72, 0x74, 0x00, 0xe5, 0x65, 0x00,
- 0x6c, 0x08, 0x6d, 0x0e, 0x6e, 0x14, 0x72, 0x18, 0x40, 0x07, 0x67, 0x6c,
- 0x69, 0x74, 0x7a, 0x00, 0x40, 0x06, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x69,
- 0x6e, 0x67, 0x00, 0xe8, 0x63, 0x00, 0x69, 0x1e, 0x6b, 0x2d, 0x6c, 0x32,
- 0x6e, 0x46, 0x70, 0x57, 0x75, 0x5e, 0x77, 0x62, 0xe1, 0x6b, 0x00, 0xe2,
- 0x68, 0x00, 0x74, 0x11, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x75,
- 0x73, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x6d, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x09, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x68, 0x6e, 0x61, 0x79, 0x61, 0x00,
- 0x40, 0x07, 0x70, 0x69, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x68, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x67, 0x65, 0x00, 0x40,
- 0x07, 0x70, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x3e, 0x69, 0x46, 0x6f, 0x5b, 0xe5,
- 0x62, 0x00, 0x64, 0x04, 0x73, 0x1e, 0x75, 0x26, 0x76, 0x2b, 0x40, 0x07,
- 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x00,
- 0x40, 0x07, 0x73, 0x73, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x73, 0x6b, 0x79,
- 0x00, 0x40, 0x07, 0x69, 0x73, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x63, 0x00,
- 0x6e, 0x08, 0x40, 0x07, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07,
- 0x64, 0x62, 0x65, 0x72, 0x67, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x07, 0x40,
- 0x07, 0x62, 0x6f, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x67, 0x00, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x64, 0x07, 0x6d, 0x10, 0x74, 0x1a, 0x79, 0x22, 0x00,
- 0x07, 0x40, 0x09, 0x72, 0x74, 0x00, 0x40, 0x07, 0x65, 0x62, 0x61, 0x6b,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x62, 0x6c, 0x65, 0x55, 0x70, 0x6f, 0x6e,
- 0x00, 0x40, 0x07, 0x74, 0x67, 0x61, 0x72, 0x74, 0x00, 0x40, 0x07, 0x76,
- 0x65, 0x73, 0x61, 0x6e, 0x74, 0x00, 0xe3, 0x67, 0x00, 0x72, 0x06, 0x78,
- 0x16, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x66,
- 0x00, 0x6e, 0x06, 0x40, 0x06, 0x6f, 0x61, 0x6d, 0x00, 0x00, 0x07, 0x00,
- 0x07, 0xc0, 0x61, 0x1a, 0x37, 0x00, 0x3d, 0x00, 0x43, 0x00, 0x54, 0x00,
- 0x7f, 0x00, 0x92, 0x00, 0x00, 0x00, 0xa8, 0x00, 0xaf, 0x00, 0x00, 0x00,
- 0xb1, 0x00, 0xc1, 0x00, 0xe3, 0x00, 0x2b, 0x01, 0x87, 0x01, 0x8c, 0x01,
- 0x00, 0x00, 0xbd, 0x01, 0xec, 0x01, 0x1f, 0x02, 0x00, 0x00, 0x32, 0x02,
- 0x36, 0x02, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x02, 0x40, 0x07, 0x72, 0x65,
- 0x7a, 0x00, 0x40, 0x07, 0x61, 0x72, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0f, 0x6f, 0x19, 0x72, 0x1e, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65,
- 0x00, 0x40, 0x07, 0x74, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0x40,
- 0x07, 0x6b, 0x75, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x74,
- 0x02, 0x7a, 0x0a, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x69, 0x75, 0x73,
- 0x00, 0x00, 0x07, 0xe2, 0x66, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6f, 0x6c,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6d,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x74, 0x6f, 0x00, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x6b, 0x06, 0x40, 0x07, 0x72, 0x6e, 0x6f, 0x00, 0x40, 0x00, 0x6f,
- 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x07, 0x6c, 0x0e, 0x40, 0x07, 0x77,
- 0x65, 0x73, 0x69, 0x00, 0x40, 0x07, 0x69, 0x6d, 0x61, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x76, 0x61, 0x6e, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x12, 0x6d, 0x24, 0x6e, 0x33, 0x74, 0x38, 0xe1,
- 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0xe6, 0x00, 0x00, 0x62, 0x02, 0x64, 0x12, 0x67, 0x30, 0x6b, 0x32, 0x6e,
- 0x38, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40,
- 0x07, 0x6d, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x11,
- 0xe3, 0x6e, 0x00, 0x73, 0x06, 0x79, 0x08, 0x40, 0x07, 0x65, 0x73, 0x65,
- 0x00, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x72, 0x6c, 0x61, 0x6e, 0x64,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x73, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x0b, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x07, 0x76, 0x61, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x69,
- 0x00, 0xe2, 0x65, 0x00, 0x74, 0x2a, 0xe1, 0x72, 0x00, 0xe5, 0x62, 0x00,
- 0x66, 0x06, 0x67, 0x0c, 0x69, 0x12, 0x6d, 0x17, 0x40, 0x07, 0x6f, 0x77,
- 0x6c, 0x00, 0x40, 0x07, 0x75, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x6c, 0x75,
- 0x65, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0x00, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x0d, 0x79, 0x24, 0xe2, 0x62, 0x00,
- 0x74, 0x06, 0x40, 0x07, 0x61, 0x79, 0x61, 0x00, 0x00, 0x07, 0xe1, 0x6e,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x61,
- 0x00, 0xe4, 0x61, 0x00, 0x69, 0x17, 0x71, 0x1b, 0x73, 0x25, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6e, 0x04, 0x00, 0x07, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x07, 0x75, 0x65, 0x68, 0x61, 0x6e, 0x6e, 0x61, 0x00, 0x40,
- 0x07, 0x65, 0x78, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x09, 0x40, 0x07, 0x65,
- 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x65, 0x65, 0x00, 0xe5, 0x61,
- 0x00, 0x65, 0x06, 0x68, 0x0c, 0x75, 0x11, 0x79, 0x16, 0x40, 0x07, 0x6e,
- 0x6e, 0x65, 0x00, 0x40, 0x07, 0x74, 0x74, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x75, 0x00, 0x40, 0x07, 0x6b, 0x69, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x65, 0x08, 0x40, 0x07, 0x6c, 0x62, 0x61, 0x72, 0x64, 0x00, 0xe2, 0x6e,
- 0x00, 0x72, 0x14, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x73, 0x08, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x6c, 0x69, 0x00, 0x40, 0x00, 0x6b, 0x61, 0x00, 0x40,
- 0x00, 0x64, 0x6c, 0x6f, 0x76, 0x73, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x3e, 0x69, 0x71, 0xe4, 0x68, 0x00, 0x6d, 0x06, 0x6e, 0x0f, 0x7a, 0x25,
- 0x40, 0x06, 0x69, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x6d, 0x65, 0x72, 0x64,
- 0x61, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x22, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x16, 0x00, 0x17, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f,
- 0x72, 0x67, 0x00, 0x40, 0x07, 0x73, 0x68, 0x00, 0xe2, 0x6e, 0x00, 0x74,
- 0x05, 0x40, 0x07, 0x65, 0x79, 0x00, 0x00, 0x07, 0xe4, 0x66, 0x00, 0x6e,
- 0x04, 0x73, 0x15, 0x74, 0x24, 0x40, 0x07, 0x74, 0x00, 0xe2, 0x62, 0x00,
- 0x64, 0x07, 0x40, 0x07, 0x75, 0x72, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x07, 0x69, 0x72, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x00, 0x40, 0x07, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0xe7,
- 0x62, 0x00, 0x64, 0x05, 0x6b, 0x0b, 0x6c, 0x10, 0x6d, 0x28, 0x6e, 0x3a,
- 0x72, 0x3f, 0x40, 0x07, 0x69, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x07, 0x40, 0x07, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x62, 0x07, 0x40,
- 0x07, 0x6e, 0x74, 0x65, 0x63, 0x00, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x67, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x07, 0x40, 0x07,
- 0x63, 0x75, 0x73, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x63,
- 0x02, 0x6e, 0x04, 0x00, 0x07, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x69, 0x00,
- 0x79, 0x07, 0x40, 0x07, 0x6c, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x6d,
- 0x62, 0x6f, 0x72, 0x73, 0x6b, 0x61, 0x00, 0xc1, 0x27, 0x53, 0xab, 0x00,
- 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xc7, 0x00,
- 0xd0, 0x00, 0x00, 0x00, 0x04, 0x01, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x0d, 0x01, 0x11, 0x01, 0x15, 0x01, 0x17, 0x01, 0x20, 0x01, 0x00, 0x00,
- 0x26, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x01,
- 0x33, 0x01, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x01, 0x68, 0x04,
- 0x76, 0x04, 0x00, 0x00, 0x88, 0x04, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x06,
- 0xd9, 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a, 0x96, 0x0a, 0x00, 0x00,
- 0x98, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x83, 0x0c, 0xa1, 0x0e, 0x00, 0x00,
- 0xd9, 0x0e, 0x00, 0x00, 0x79, 0x10, 0x00, 0x00, 0xcb, 0x10, 0x00, 0x2f,
- 0x40, 0x07, 0x61, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x52, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x50, 0x00, 0xe2, 0x00, 0x00, 0x41, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x44, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3,
- 0x46, 0x00, 0x4c, 0x04, 0x53, 0x22, 0x40, 0x00, 0x4c, 0x00, 0xe1, 0x4e,
- 0x00, 0xe1, 0x45, 0x00, 0xe1, 0x54, 0x00, 0xe2, 0x00, 0x00, 0x54, 0x02,
- 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x4c, 0x00, 0x4f, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x4c, 0x00, 0x40, 0x00, 0x49, 0x46, 0x00, 0x40, 0x00, 0x43, 0x00,
- 0x40, 0x07, 0x4f, 0x00, 0x40, 0x07, 0x43, 0x00, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x54, 0x02, 0x00, 0x00, 0x00, 0x07, 0x40, 0x00, 0x45, 0x46, 0x4c,
- 0x00, 0x40, 0x00, 0x4d, 0x00, 0xe2, 0x00, 0x00, 0x41, 0x02, 0x00, 0x06,
- 0x00, 0x00, 0xe3, 0x41, 0x00, 0x58, 0x02, 0x69, 0x04, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x07, 0x6b, 0x69, 0x00, 0x00, 0x00, 0xc1, 0x62, 0x18, 0x35,
- 0x00, 0x37, 0x00, 0x63, 0x00, 0x73, 0x00, 0x80, 0x00, 0x8e, 0x00, 0x92,
- 0x00, 0xa8, 0x00, 0xc2, 0x00, 0x05, 0x01, 0x0f, 0x01, 0x19, 0x01, 0x7d,
- 0x01, 0xea, 0x01, 0x5c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x02, 0xd1,
- 0x02, 0x00, 0x03, 0x11, 0x03, 0x00, 0x00, 0x17, 0x03, 0x00, 0x00, 0x1d,
- 0x03, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x18, 0x72, 0x1e,
- 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x06, 0x63, 0x6f, 0x00, 0x40, 0x07,
- 0x68, 0x61, 0x00, 0x40, 0x09, 0x72, 0x6e, 0x61, 0x63, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x74, 0x68, 0x61, 0x00, 0x40, 0x09, 0x69, 0x7a, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x74, 0x75, 0x73, 0x00, 0x40, 0x07,
- 0x6d, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x7a, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x68, 0x69, 0x6b, 0x00, 0xe2, 0x67, 0x00, 0x6a, 0x04, 0x40, 0x07, 0x75,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe3, 0x61,
- 0x00, 0x6f, 0x06, 0x75, 0x0b, 0x40, 0x06, 0x6c, 0x6f, 0x67, 0x00, 0x40,
- 0x07, 0x72, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x11, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe5, 0x63,
- 0x00, 0x6e, 0x07, 0x70, 0x12, 0x77, 0x20, 0x79, 0x32, 0x40, 0x07, 0x68,
- 0x75, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e,
- 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x69, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0x40,
- 0x07, 0x75, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x6b, 0x69, 0x73, 0x74,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x6d, 0x61, 0x6b, 0x61, 0x6e,
- 0x00, 0xe4, 0x62, 0x00, 0x69, 0x05, 0x6c, 0x15, 0x6d, 0x43, 0x40, 0x07,
- 0x6f, 0x74, 0x00, 0xe2, 0x62, 0x00, 0x65, 0x05, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x73, 0x69, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x09,
- 0x65, 0x10, 0x69, 0x20, 0x40, 0x07, 0x68, 0x61, 0x73, 0x73, 0x65, 0x65,
- 0x00, 0x40, 0x07, 0x68, 0x69, 0x65, 0x66, 0x00, 0xe1, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00,
- 0x40, 0x07, 0x6e, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x05, 0x69, 0x1b,
- 0x6d, 0x2a, 0x70, 0x47, 0x72, 0x53, 0x77, 0x57, 0x40, 0x07, 0x72, 0x61,
- 0x00, 0xe2, 0x6b, 0x00, 0x72, 0x04, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x61,
- 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x6b, 0x02, 0x6c, 0x06, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00,
- 0x00, 0x09, 0xe4, 0x61, 0x00, 0x69, 0x05, 0x75, 0x0e, 0x79, 0x12, 0x40,
- 0x07, 0x6e, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x7a, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x78, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x6f, 0x72, 0x74, 0x68, 0x00, 0xe8, 0x63, 0x00, 0x65, 0x06, 0x67,
- 0x0a, 0x69, 0x24, 0x6e, 0x30, 0x74, 0x41, 0x79, 0x48, 0x7a, 0x4c, 0x40,
- 0x07, 0x72, 0x65, 0x64, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x08, 0x73, 0x0d, 0x40, 0x07, 0x6e, 0x79, 0x69, 0x6b, 0x61, 0x00,
- 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x61, 0x00, 0xe2,
- 0x65, 0x00, 0x68, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x75,
- 0x73, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x09, 0x00, 0x09, 0xe7, 0x61, 0x00, 0x62, 0x1b,
- 0x67, 0x21, 0x69, 0x26, 0x6b, 0x2a, 0x74, 0x3e, 0x7a, 0x4e, 0xe4, 0x00,
- 0x00, 0x6e, 0x02, 0x77, 0x09, 0x7a, 0x0d, 0x00, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6e, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x65, 0x64,
- 0x00, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x74, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x07, 0x40, 0x07, 0x6e,
- 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40, 0x07, 0x72, 0x79, 0x00, 0x40, 0x07,
- 0x66, 0x66, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe3, 0x68, 0x00,
- 0x6d, 0x0d, 0x73, 0x26, 0xe2, 0x61, 0x00, 0x6b, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x65,
- 0x04, 0x75, 0x06, 0x40, 0x09, 0x72, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6d,
- 0x00, 0x40, 0x09, 0x72, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x79,
- 0x00, 0x40, 0x07, 0x6c, 0x6f, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x73, 0x69, 0x00, 0xe2, 0x00, 0x00,
- 0x68, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x69, 0x6b, 0x6f, 0x76, 0x73,
- 0x6b, 0x79, 0x00, 0xc1, 0x58, 0x21, 0x47, 0x00, 0x49, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x93, 0x00, 0x00, 0x00,
- 0x9e, 0x00, 0xa4, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xb5, 0x00, 0x06, 0x01, 0x15, 0x01, 0x48, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x53, 0x01, 0xc8, 0x01, 0xe6, 0x01, 0xf9, 0x01, 0x0d, 0x02, 0x00, 0x00,
- 0x12, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x00, 0xe2,
- 0x68, 0x00, 0x75, 0x2b, 0xe2, 0x52, 0x00, 0x6e, 0x0a, 0x40, 0x07, 0x65,
- 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x10,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0x40, 0x07,
- 0x6c, 0x6f, 0x72, 0x00, 0x40, 0x07, 0x72, 0x61, 0x74, 0x69, 0x00, 0x40,
- 0x07, 0x6d, 0x73, 0x65, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x6c, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x00, 0x40, 0x00,
- 0x72, 0x61, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x3a, 0x75, 0x45, 0xe3,
- 0x50, 0x00, 0x6d, 0x1b, 0x74, 0x2d, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x54, 0x00, 0x74, 0x05, 0x40,
- 0x00, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x63, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x68, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x79, 0x70, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x0e, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x67, 0x75,
- 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x40,
- 0x07, 0x61, 0x72, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x23, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x79, 0x16, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x06, 0x6e, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x63, 0x68,
- 0x74, 0x69, 0x74, 0x6c, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x69, 0x68,
- 0x75, 0x61, 0x63, 0x61, 0x6e, 0x00, 0xe6, 0x65, 0x00, 0x69, 0x18, 0x6b,
- 0x1a, 0x70, 0x1f, 0x72, 0x29, 0x74, 0x61, 0xe2, 0x6e, 0x00, 0x73, 0x05,
- 0x40, 0x07, 0x63, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6b, 0x6f, 0x76, 0x61, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x6c, 0x00, 0x40, 0x07, 0x73, 0x69, 0x63, 0x68, 0x6f, 0x72, 0x65, 0x00,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x14, 0x69, 0x22, 0x79, 0x2b, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x69, 0x61,
- 0x72, 0x79, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x04, 0x73, 0x08, 0x40, 0x07,
- 0x6f, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x68, 0x02, 0x6f, 0x07, 0x00, 0x07, 0x40, 0x07, 0x79, 0x73, 0x00, 0x40,
- 0x07, 0x6e, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x63, 0x00,
- 0x40, 0x07, 0x65, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0xe3, 0x63, 0x00, 0x6e, 0x04, 0x73, 0x06, 0x40, 0x07, 0x6f, 0x00, 0x00,
- 0x09, 0x00, 0x07, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x6c,
- 0x00, 0x69, 0x38, 0x01, 0x6f, 0x4f, 0x01, 0x72, 0xb0, 0x01, 0x75, 0xc2,
- 0x01, 0x00, 0x07, 0xe8, 0x63, 0x00, 0x64, 0x08, 0x69, 0x15, 0x6c, 0x22,
- 0x6d, 0x2f, 0x6e, 0x34, 0x72, 0x49, 0x74, 0x52, 0x40, 0x07, 0x6b, 0x65,
- 0x72, 0x61, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x75, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06,
- 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00,
- 0xe3, 0x68, 0x00, 0x6b, 0x02, 0x74, 0x0c, 0x00, 0x07, 0x40, 0x09, 0x73,
- 0x67, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x70, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x63, 0x68, 0x65, 0x72,
- 0x00, 0xe8, 0x61, 0x00, 0x62, 0x02, 0x69, 0x07, 0x6c, 0x0d, 0x6d, 0x12,
- 0x6f, 0x1d, 0x72, 0x50, 0x73, 0x81, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73,
- 0x00, 0x40, 0x07, 0x6c, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x00,
- 0x40, 0x07, 0x69, 0x73, 0x74, 0x6f, 0x63, 0x6c, 0x65, 0x73, 0x00, 0xe3,
- 0x63, 0x00, 0x64, 0x08, 0x73, 0x25, 0x40, 0x07, 0x72, 0x69, 0x74, 0x75,
- 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x0f, 0xe3, 0x61,
- 0x00, 0x65, 0x02, 0x69, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x63,
- 0x00, 0x40, 0x07, 0x69, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x70, 0x68,
- 0x79, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x07, 0x6d, 0x13, 0x6f, 0x24, 0x40,
- 0x07, 0x76, 0x61, 0x64, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe2, 0x70, 0x00,
- 0x73, 0x07, 0x40, 0x07, 0x79, 0x6c, 0x61, 0x65, 0x00, 0x00, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x70, 0x05, 0x73, 0x13, 0x40, 0x07,
- 0x75, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x6f, 0x00, 0x79, 0x13, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x6b, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x00, 0x00,
- 0x07, 0xe2, 0x65, 0x00, 0x6d, 0x04, 0x40, 0x07, 0x75, 0x00, 0xe2, 0x62,
- 0x00, 0x70, 0x04, 0x40, 0x07, 0x75, 0x00, 0x40, 0x00, 0x68, 0x75, 0x00,
- 0xe3, 0x6d, 0x00, 0x72, 0x27, 0x74, 0x56, 0xe4, 0x61, 0x00, 0x69, 0x04,
- 0x70, 0x13, 0x73, 0x19, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x63, 0x00, 0x40,
- 0x07, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x09, 0x6e, 0x0e, 0x6f, 0x14, 0x70, 0x1e, 0x00,
- 0x07, 0x40, 0x07, 0x7a, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x61, 0x75,
- 0x00, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x67, 0x68,
- 0x62, 0x72, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x68,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x63, 0x02,
- 0x6c, 0x0b, 0x6e, 0x0f, 0x72, 0x19, 0x74, 0x3d, 0x00, 0x00, 0x40, 0x07,
- 0x79, 0x64, 0x69, 0x64, 0x65, 0x73, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x07, 0x64, 0x65, 0x72, 0x62, 0x69, 0x72, 0x64, 0x00, 0xe4, 0x00, 0x00,
- 0x62, 0x02, 0x6d, 0x07, 0x73, 0x15, 0x00, 0x08, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x64, 0x00, 0x40, 0x06, 0x64, 0x61, 0x79, 0x00, 0x40, 0x07, 0x6d,
- 0x6f, 0x73, 0x65, 0x00, 0xc1, 0x61, 0x14, 0x2d, 0x00, 0x2f, 0x00, 0x3c,
- 0x00, 0x5b, 0x00, 0x75, 0x00, 0x79, 0x00, 0x82, 0x00, 0x89, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x96, 0x00, 0xaf, 0x00, 0xf7,
- 0x00, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00, 0x46, 0x01, 0x68, 0x01, 0x76,
- 0x01, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6a, 0x69, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x0c,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x75, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0xe2,
- 0x6b, 0x00, 0x6f, 0x0b, 0x40, 0x07, 0x65, 0x74, 0x6d, 0x61, 0x73, 0x74,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x64, 0x65, 0x72, 0x6f, 0x67, 0x61,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x6e, 0x6d, 0x65,
- 0x6e, 0x00, 0x40, 0x07, 0x66, 0x61, 0x6e, 0x79, 0x00, 0x40, 0x07, 0x72,
- 0x69, 0x73, 0x00, 0x40, 0x07, 0x75, 0x61, 0x6e, 0x61, 0x00, 0xe2, 0x6c,
- 0x00, 0x73, 0x0f, 0xe2, 0x69, 0x00, 0x6d, 0x05, 0x40, 0x07, 0x63, 0x68,
- 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x74, 0x00, 0xe6,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x09, 0x6d, 0x19, 0x6f, 0x1d, 0x75, 0x2d,
- 0x00, 0x07, 0x40, 0x07, 0x75, 0x6b, 0x74, 0x75, 0x00, 0xe2, 0x73, 0x00,
- 0x78, 0x09, 0x40, 0x07, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x02, 0x74, 0x04,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x68, 0x79, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x00, 0xe5,
- 0x61, 0x00, 0x67, 0x02, 0x6b, 0x04, 0x73, 0x1a, 0x74, 0x23, 0x00, 0x07,
- 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x62, 0x00, 0x74,
- 0x06, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6f, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x6c, 0x74, 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x07, 0x6f,
- 0x72, 0x65, 0x74, 0x74, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x63, 0x00, 0x72, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x6f, 0x65, 0x00,
- 0x40, 0x07, 0x61, 0x72, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6f,
- 0x0c, 0x40, 0x00, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x73, 0x69, 0x61, 0x73,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x61, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x69, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x13, 0x6f,
- 0x22, 0x75, 0x24, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x63, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x63, 0x61,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x08, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x6f, 0x63, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x69, 0x74, 0x00, 0x00, 0x07, 0xc0, 0x62, 0x18, 0x33, 0x00,
- 0x45, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x75, 0x00, 0x79, 0x00, 0x9a, 0x00, 0xc2, 0x00, 0xf9, 0x00,
- 0x00, 0x00, 0x24, 0x01, 0x00, 0x00, 0x38, 0x01, 0x9a, 0x01, 0xb5, 0x01,
- 0xb9, 0x01, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x00, 0xd3, 0x01, 0xe3, 0x61,
- 0x00, 0x69, 0x05, 0x79, 0x09, 0x40, 0x07, 0x67, 0x6f, 0x00, 0x40, 0x07,
- 0x74, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x71, 0x08, 0x40, 0x07, 0x6e,
- 0x74, 0x69, 0x6e, 0x73, 0x00, 0x40, 0x07, 0x75, 0x65, 0x76, 0x69, 0x6c,
- 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x73, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe3, 0x61, 0x00, 0x75,
- 0x04, 0x79, 0x0b, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x67, 0x61, 0x77,
- 0x61, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x74, 0x65, 0x00, 0xe5, 0x65, 0x00, 0x6b, 0x05, 0x73, 0x0b,
- 0x74, 0x11, 0x79, 0x16, 0x40, 0x09, 0x64, 0x6f, 0x00, 0x40, 0x07, 0x69,
- 0x65, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x63, 0x00, 0x40, 0x07, 0x61, 0x74, 0x74, 0x69, 0x00, 0xe7, 0x00, 0x00,
- 0x61, 0x02, 0x62, 0x06, 0x6c, 0x0d, 0x6d, 0x12, 0x70, 0x1d, 0x73, 0x24,
- 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x75, 0x67, 0x68,
- 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6b, 0x69, 0x6e, 0x73, 0x00,
- 0x40, 0x07, 0x6b, 0x00, 0xe4, 0x67, 0x00, 0x69, 0x0c, 0x74, 0x15, 0x79,
- 0x19, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x09, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe3,
- 0x65, 0x00, 0x69, 0x05, 0x73, 0x09, 0x40, 0x07, 0x6b, 0x61, 0x00, 0x40,
- 0x07, 0x78, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe7, 0x61, 0x00, 0x6f, 0x0c,
- 0x71, 0x12, 0x72, 0x1b, 0x74, 0x3b, 0x76, 0x4a, 0x79, 0x51, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07,
- 0x6e, 0x74, 0x6f, 0x00, 0x40, 0x07, 0x75, 0x65, 0x6d, 0x61, 0x64, 0x61,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x11, 0x40, 0x07, 0x6e, 0x63,
- 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x63, 0x65, 0x6c, 0x6c, 0x69, 0x00, 0xe2, 0x6f, 0x00,
- 0x75, 0x05, 0x40, 0x07, 0x6c, 0x61, 0x00, 0x40, 0x07, 0x67, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x6c, 0x64, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x63, 0x00,
- 0x68, 0x10, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x6e, 0x69, 0x00, 0x40, 0x07, 0x69, 0x62, 0x61, 0x00,
- 0x40, 0x07, 0x6f, 0x00, 0x40, 0x07, 0x6c, 0x6f, 0x75, 0x73, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x65, 0x6e, 0x64, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x06, 0x40,
- 0x07, 0x62, 0x65, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x61, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x92,
- 0x00, 0x69, 0xdf, 0x00, 0x6f, 0x74, 0x01, 0x75, 0xc0, 0x01, 0xe8, 0x63,
- 0x00, 0x66, 0x16, 0x69, 0x1e, 0x6a, 0x26, 0x6d, 0x2b, 0x6e, 0x32, 0x70,
- 0x6b, 0x76, 0x72, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x0d, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x00, 0x40, 0x07, 0x6c,
- 0x77, 0x61, 0x79, 0x73, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x61, 0x64, 0x6f, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0xe3, 0x63, 0x00, 0x76, 0x0a, 0x79, 0x10, 0x40, 0x07, 0x61, 0x75, 0x63,
- 0x61, 0x73, 0x69, 0x61, 0x00, 0x40, 0x07, 0x61, 0x61, 0x6c, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x40, 0x06, 0x70, 0x69, 0x73, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x6c, 0x74, 0x61, 0x00,
- 0xe7, 0x61, 0x00, 0x62, 0x07, 0x6b, 0x0f, 0x6e, 0x15, 0x6f, 0x23, 0x76,
- 0x25, 0x79, 0x3c, 0x40, 0x06, 0x73, 0x75, 0x72, 0x79, 0x00, 0x40, 0x07,
- 0x6c, 0x69, 0x6e, 0x6b, 0x61, 0x00, 0x40, 0x07, 0x6b, 0x69, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x07, 0x6f, 0x0c, 0x40,
- 0x07, 0x6c, 0x79, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x6f, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0x07, 0xe9, 0x61, 0x00, 0x63, 0x13, 0x64, 0x18,
- 0x65, 0x1e, 0x6d, 0x24, 0x6e, 0x2b, 0x70, 0x4d, 0x73, 0x6f, 0x74, 0x7d,
- 0xe2, 0x6e, 0x00, 0x73, 0x08, 0x40, 0x07, 0x67, 0x75, 0x6c, 0x75, 0x6d,
- 0x00, 0x40, 0x07, 0x73, 0x69, 0x63, 0x00, 0x40, 0x07, 0x69, 0x61, 0x00,
- 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x73, 0x74, 0x65, 0x00,
- 0x40, 0x07, 0x75, 0x72, 0x74, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0xe2, 0x64, 0x00, 0x74, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6e,
- 0x00, 0x40, 0x06, 0x79, 0x00, 0xe4, 0x41, 0x00, 0x69, 0x09, 0x6f, 0x10,
- 0x70, 0x15, 0x40, 0x07, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x00, 0x40,
- 0x07, 0x74, 0x61, 0x6b, 0x61, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x04, 0x40, 0x07, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe8, 0x62,
- 0x00, 0x69, 0x08, 0x6a, 0x0e, 0x6c, 0x13, 0x6e, 0x1a, 0x70, 0x22, 0x74,
- 0x2a, 0x79, 0x30, 0x40, 0x07, 0x72, 0x69, 0x61, 0x6e, 0x64, 0x00, 0x40,
- 0x07, 0x6c, 0x75, 0x73, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x6c, 0x6f, 0x70, 0x65, 0x00, 0x40, 0x07, 0x64, 0x68, 0x65, 0x69, 0x6d,
- 0x00, 0x40, 0x07, 0x69, 0x63, 0x61, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x73,
- 0x6b, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x73, 0x00, 0xe7, 0x63, 0x00, 0x64, 0x06, 0x66, 0x12, 0x6a, 0x19, 0x6d,
- 0x20, 0x73, 0x33, 0x74, 0x3b, 0x40, 0x07, 0x6b, 0x65, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x05, 0x40, 0x07, 0x61, 0x75, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x66, 0x61, 0x75, 0x74, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x6f,
- 0x00, 0xe3, 0x61, 0x00, 0x62, 0x04, 0x70, 0x0a, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x07, 0x75, 0x6c, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x74, 0x50,
- 0x61, 0x73, 0x73, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe3, 0x69, 0x00, 0x6f,
- 0x21, 0x77, 0x2b, 0xe3, 0x6d, 0x00, 0x6f, 0x08, 0x74, 0x12, 0x40, 0x07,
- 0x73, 0x68, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x6b, 0x6f, 0x76,
- 0x73, 0x6b, 0x79, 0x00, 0x40, 0x07, 0x73, 0x69, 0x68, 0x61, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x6b, 0x68, 0x61, 0x70, 0x61, 0x00, 0x40, 0x07,
- 0x61, 0x6e, 0x61, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62,
- 0x12, 0x00, 0x63, 0x18, 0x00, 0x64, 0x2f, 0x00, 0x65, 0x34, 0x00, 0x6c,
- 0x47, 0x00, 0x6d, 0x62, 0x00, 0x6e, 0x66, 0x00, 0x70, 0x99, 0x00, 0x72,
- 0xb3, 0x00, 0x73, 0x08, 0x01, 0x74, 0x42, 0x01, 0x76, 0x61, 0x01, 0x00,
- 0x07, 0xe2, 0x6d, 0x00, 0x72, 0x06, 0x40, 0x07, 0x6f, 0x74, 0x75, 0x00,
- 0x40, 0x07, 0x65, 0x67, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x00, 0xe3,
- 0x6b, 0x00, 0x73, 0x05, 0x75, 0x0a, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x00, 0x40, 0x06,
- 0x6f, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x79, 0x00, 0xe3, 0x61,
- 0x00, 0x6c, 0x05, 0x73, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x61, 0x73,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x67, 0x00, 0x69, 0x11, 0x6e, 0x27,
- 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x00, 0x09, 0x40, 0x07, 0x65, 0x79, 0x00, 0xe3, 0x69, 0x00, 0x70,
- 0x02, 0x75, 0x0b, 0x00, 0x07, 0x40, 0x07, 0x65, 0x72, 0x77, 0x61, 0x72,
- 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x61, 0x74, 0x6f, 0x00, 0xe5, 0x67,
- 0x00, 0x69, 0x07, 0x6b, 0x13, 0x6e, 0x40, 0x70, 0x45, 0x40, 0x07, 0x65,
- 0x6e, 0x65, 0x76, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0f, 0x6d,
- 0x1a, 0x00, 0x06, 0xe2, 0x73, 0x00, 0x79, 0x06, 0x40, 0x07, 0x74, 0x61,
- 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40,
- 0x07, 0x68, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe3,
- 0x63, 0x00, 0x6b, 0x26, 0x73, 0x2d, 0xe2, 0x61, 0x00, 0x6f, 0x1d, 0xe3,
- 0x6c, 0x00, 0x6e, 0x07, 0x72, 0x10, 0x40, 0x07, 0x6f, 0x6f, 0x73, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x09,
- 0x6f, 0x72, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x67,
- 0x65, 0x65, 0x00, 0x40, 0x07, 0x61, 0x75, 0x64, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x6f, 0x0c, 0x73, 0x0e, 0x75, 0x12, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x6b, 0x68, 0x61, 0x6d, 0x65, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x69, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x75,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x25, 0x70, 0x47, 0x40, 0x07, 0x69,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00,
- 0x75, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe4, 0x6c,
- 0x00, 0x6e, 0x04, 0x74, 0x0b, 0x7a, 0x11, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x6b, 0x69, 0x65, 0x73, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x7a, 0x6c, 0x65, 0x72, 0x73, 0x00, 0x00, 0x00, 0xe6, 0x00,
- 0x00, 0x63, 0x02, 0x6c, 0x07, 0x6e, 0x16, 0x72, 0x28, 0x73, 0x45, 0x00,
- 0x07, 0x40, 0x07, 0x68, 0x6f, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00,
- 0x72, 0x05, 0x40, 0x07, 0x6f, 0x6c, 0x00, 0x00, 0x07, 0xe1, 0x64, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6f, 0x09, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x06, 0x40, 0x00,
- 0x65, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xc1, 0x41, 0x3a, 0x79, 0x00, 0x7b, 0x00, 0x84, 0x00, 0x88, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x95, 0x00, 0x97, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00,
- 0xb4, 0x00, 0x00, 0x00, 0xc1, 0x00, 0xcd, 0x00, 0x17, 0x01, 0x00, 0x00,
- 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x22, 0x01, 0x33, 0x01, 0x46, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x50, 0x01,
- 0x00, 0x00, 0x65, 0x01, 0x76, 0x01, 0x83, 0x01, 0x9b, 0x01, 0xcf, 0x01,
- 0xd7, 0x01, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x75, 0x02, 0xff, 0x02,
- 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x54, 0x03, 0x00, 0x07, 0xe2, 0x52, 0x00, 0x57, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x53, 0x00, 0x40, 0x07, 0x4c, 0x41, 0x00, 0x40, 0x06,
- 0x4f, 0x00, 0x40, 0x07, 0x46, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x45, 0x02, 0x49, 0x08, 0x00, 0x07, 0x40, 0x07, 0x53, 0x43, 0x4f,
- 0x00, 0xe2, 0x43, 0x00, 0x58, 0x05, 0x40, 0x07, 0x45, 0x46, 0x00, 0x00,
- 0x07, 0xe3, 0x43, 0x00, 0x49, 0x02, 0x53, 0x04, 0x00, 0x00, 0x00, 0x07,
- 0x00, 0x07, 0xe1, 0x4c, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08,
- 0x00, 0x00, 0xeb, 0x00, 0x00, 0x41, 0x02, 0x42, 0x0b, 0x43, 0x0d, 0x44,
- 0x11, 0x49, 0x15, 0x4d, 0x19, 0x4e, 0x1d, 0x4f, 0x1f, 0x50, 0x21, 0x53,
- 0x2a, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x46, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x47, 0x00, 0x40, 0x07, 0x41, 0x00, 0x40, 0x00,
- 0x41, 0x00, 0x40, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x53, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x52, 0x02,
- 0x00, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x43, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x75, 0x06, 0x40, 0x07, 0x6e, 0x67,
- 0x69, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x75, 0x00, 0xe2, 0x61, 0x00, 0x63,
- 0x07, 0x40, 0x07, 0x79, 0x61, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x65, 0x6c,
- 0x6c, 0x6f, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x61,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x67,
- 0x00, 0x74, 0x06, 0x40, 0x07, 0x68, 0x75, 0x72, 0x00, 0x40, 0x07, 0x6c,
- 0x65, 0x67, 0x00, 0x40, 0x07, 0x75, 0x6e, 0x67, 0x70, 0x61, 0x6e, 0x64,
- 0x61, 0x6e, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x06, 0x61, 0x6e, 0x00, 0xe3, 0x73, 0x00, 0x74, 0x06, 0x79, 0x1a, 0x40,
- 0x07, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x6d, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x75, 0x65, 0x64, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x73, 0x08, 0x40, 0x07, 0x6e, 0x6f, 0x76, 0x73,
- 0x6b, 0x00, 0x40, 0x07, 0x73, 0x65, 0x73, 0x00, 0x40, 0x07, 0x62, 0x72,
- 0x69, 0x65, 0x6c, 0x00, 0xe4, 0x64, 0x00, 0x67, 0x09, 0x69, 0x0f, 0x75,
- 0x68, 0x40, 0x07, 0x65, 0x72, 0x77, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x07,
- 0x61, 0x76, 0x61, 0x00, 0xe7, 0x50, 0x00, 0x63, 0x06, 0x6c, 0x0c, 0x6f,
- 0x13, 0x72, 0x22, 0x74, 0x29, 0x78, 0x48, 0x40, 0x07, 0x72, 0x6f, 0x74,
- 0x00, 0x40, 0x07, 0x6f, 0x64, 0x65, 0x00, 0x40, 0x07, 0x65, 0x76, 0x65,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x73, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x79, 0x61, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x15, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x09, 0x73, 0x6d, 0x00, 0x00, 0x07, 0x00, 0x08, 0x40, 0x07, 0x6b,
- 0x61, 0x6c, 0x68, 0x61, 0x69, 0x00, 0xe4, 0x61, 0x00, 0x64, 0x0a, 0x6a,
- 0x10, 0x74, 0x16, 0x40, 0x07, 0x6e, 0x69, 0x73, 0x68, 0x61, 0x64, 0x73,
- 0x00, 0x40, 0x07, 0x69, 0x6b, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x68, 0x6e,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x1d, 0x64, 0x22, 0x65, 0x26, 0x69, 0x2a, 0x71, 0x3b, 0x73, 0x43, 0x75,
- 0x59, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x09, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x75, 0x04, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x75, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04,
- 0x73, 0x08, 0x40, 0x07, 0x68, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x75, 0x68, 0x61, 0x72, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x75,
- 0x02, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe2, 0x67, 0x00, 0x6d, 0x14, 0xe1,
- 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x07, 0x71, 0x69, 0x00,
- 0xe2, 0x65, 0x00, 0x74, 0x06, 0x40, 0x09, 0x6e, 0x65, 0x74, 0x00, 0x40,
- 0x07, 0x69, 0x6e, 0x6f, 0x76, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x0e, 0x6f,
- 0x10, 0x72, 0x22, 0x76, 0x33, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x06, 0xe1, 0x70, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x06, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07, 0x63, 0x68,
- 0x74, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x6f, 0x00, 0x40, 0x07, 0x69, 0x64,
- 0x00, 0xe2, 0x62, 0x00, 0x69, 0x14, 0xe1, 0x65, 0x00, 0xe1, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x74, 0x61,
- 0x6e, 0x00, 0x00, 0x06, 0xc1, 0x41, 0x35, 0x6f, 0x00, 0x71, 0x00, 0x00,
- 0x00, 0x87, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x98, 0x00, 0xa1, 0x00, 0xaa,
- 0x00, 0xb3, 0x00, 0xc3, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc9, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x02, 0x5c, 0x02, 0x00,
- 0x00, 0xce, 0x03, 0x00, 0x00, 0xd5, 0x03, 0x00, 0x00, 0x00, 0x00, 0xd4,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x9a, 0x06, 0x9c, 0x06, 0x00, 0x07, 0xe3, 0x00, 0x00,
- 0x54, 0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x52, 0x00, 0xe3,
- 0x00, 0x00, 0x54, 0x02, 0x55, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x41, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x46, 0x00, 0x53, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x50, 0x02, 0x53, 0x04, 0x00, 0x07,
- 0x00, 0x06, 0x40, 0x00, 0x54, 0x41, 0x00, 0x00, 0x00, 0x40, 0x07, 0x46,
- 0x00, 0x40, 0x00, 0x41, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x4f, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x4c, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x6c, 0x0f, 0x00, 0x6e, 0xb3, 0x00, 0x72, 0x09, 0x01, 0x73, 0x21,
- 0x01, 0x74, 0x3a, 0x01, 0x75, 0x41, 0x01, 0x7a, 0x59, 0x01, 0x00, 0x07,
- 0xe2, 0x65, 0x00, 0x75, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x7a,
- 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x64, 0x08, 0x65, 0x0d, 0x68, 0x53,
- 0x69, 0x5a, 0x6b, 0x5f, 0x6c, 0x66, 0x6f, 0x77, 0x70, 0x7c, 0x76, 0x85,
- 0x00, 0x07, 0x40, 0x07, 0x72, 0x69, 0x65, 0x00, 0x40, 0x07, 0x65, 0x7a,
- 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x2a, 0xe3, 0x63, 0x00, 0x74, 0x05, 0x7a,
- 0x1c, 0x40, 0x06, 0x69, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x04, 0x00,
- 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x75, 0x65, 0x6c, 0x61, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x10, 0xe2, 0x61, 0x00, 0x65, 0x09, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x6c, 0x6c, 0x61, 0x00, 0x40, 0x09, 0x75, 0x6d, 0x00, 0x40,
- 0x06, 0x79, 0x72, 0x69, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6a, 0x00,
- 0x74, 0x04, 0x40, 0x00, 0x6f, 0x00, 0x40, 0x07, 0x74, 0x61, 0x00, 0x40,
- 0x07, 0x69, 0x73, 0x00, 0x40, 0x07, 0x61, 0x72, 0x61, 0x69, 0x73, 0x6f,
- 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0xe7, 0x00, 0x00,
- 0x63, 0x02, 0x64, 0x10, 0x65, 0x32, 0x67, 0x38, 0x75, 0x3a, 0x7a, 0x40,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x75,
- 0x76, 0x65, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x6f, 0x0c, 0x79,
- 0x14, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x07, 0x72, 0x62, 0x69, 0x6c, 0x74,
- 0x00, 0x40, 0x07, 0x65, 0x75, 0x76, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6b,
- 0x65, 0x00, 0x40, 0x07, 0x73, 0x73, 0x61, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x74, 0x75, 0x00, 0x40, 0x07, 0x65, 0x74, 0x74, 0x69, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x07, 0x67, 0x0c, 0x40, 0x07, 0x6e, 0x61, 0x73, 0x69,
- 0x00, 0x40, 0x07, 0x73, 0x65, 0x00, 0x40, 0x07, 0x61, 0x73, 0x00, 0xe3,
- 0x65, 0x00, 0x71, 0x07, 0x73, 0x0d, 0x40, 0x06, 0x6c, 0x69, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x75, 0x65, 0x7a, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00,
- 0x40, 0x07, 0x69, 0x63, 0x61, 0x6e, 0x00, 0xe2, 0x62, 0x00, 0x67, 0x05,
- 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x6e,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x71, 0x75, 0x65,
- 0x7a, 0x00, 0x40, 0x07, 0x61, 0x74, 0x61, 0x00, 0xf7, 0x62, 0x00, 0x00,
- 0x64, 0x06, 0x00, 0x67, 0x15, 0x00, 0x6c, 0x2a, 0x00, 0x6e, 0x60, 0x00,
- 0x72, 0xa8, 0x00, 0x73, 0x2f, 0x01, 0x40, 0x07, 0x6c, 0x65, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x40, 0x07,
- 0x74, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x09, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x69, 0x74, 0x65, 0x00,
- 0xe5, 0x61, 0x00, 0x63, 0x17, 0x65, 0x1c, 0x6d, 0x20, 0x76, 0x24, 0xe3,
- 0x00, 0x00, 0x73, 0x02, 0x7a, 0x09, 0x00, 0x07, 0x40, 0x07, 0x71, 0x75,
- 0x65, 0x7a, 0x00, 0x40, 0x07, 0x71, 0x75, 0x65, 0x7a, 0x00, 0x40, 0x09,
- 0x72, 0x6f, 0x00, 0x40, 0x07, 0x7a, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x65, 0x65, 0x74, 0x61, 0x00, 0xe5, 0x65, 0x00, 0x69, 0x20, 0x6e,
- 0x25, 0x74, 0x27, 0x75, 0x2e, 0xe2, 0x74, 0x00, 0x7a, 0x06, 0x40, 0x06,
- 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x07, 0x63, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6c,
- 0x69, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe8, 0x61, 0x00, 0x64, 0x0d, 0x69,
- 0x1c, 0x6c, 0x22, 0x6d, 0x29, 0x6e, 0x44, 0x6f, 0x57, 0x73, 0x6d, 0xe2,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x75, 0x7a, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x75, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x07, 0x7a, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61,
- 0x69, 0x6e, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x65,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x27, 0x40, 0x07, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x04, 0x6f, 0x06, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x69, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0x40, 0x07, 0x63, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x69, 0x6c, 0x6c, 0x65, 0x73, 0x00, 0xe4, 0x61, 0x00,
- 0x70, 0x07, 0x74, 0x19, 0x75, 0x1d, 0x40, 0x07, 0x6c, 0x69, 0x75, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x75, 0x07, 0x40, 0x07, 0x73, 0x69, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x63, 0x63, 0x69, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x76, 0x69, 0x75, 0x73, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x75, 0x70,
- 0x00, 0xfd, 0x61, 0x00, 0x00, 0x63, 0x0f, 0x00, 0x64, 0x72, 0x00, 0x65,
- 0x77, 0x00, 0x6a, 0xb9, 0x00, 0x6b, 0xd4, 0x00, 0x6c, 0xda, 0x00, 0x6e,
- 0x0d, 0x01, 0x6f, 0x32, 0x01, 0x72, 0x40, 0x01, 0x73, 0x6a, 0x01, 0x74,
- 0xa0, 0x01, 0x76, 0xb1, 0x01, 0xe2, 0x63, 0x00, 0x67, 0x05, 0x40, 0x07,
- 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x72, 0x61, 0x00, 0xe6, 0x00, 0x00, 0x65,
- 0x02, 0x68, 0x08, 0x6b, 0x0c, 0x6f, 0x25, 0x74, 0x2b, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x74, 0x65, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x69, 0x00,
- 0x73, 0x09, 0x79, 0x10, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x62, 0x75, 0x72, 0x67, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x64, 0x69, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x20, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x61, 0x00, 0x40,
- 0x07, 0x61, 0x6c, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x18, 0xe2, 0x6e, 0x00,
- 0x74, 0x0c, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x65, 0x00, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x65, 0x00, 0xe3, 0x63, 0x00,
- 0x6d, 0x06, 0x6e, 0x0c, 0x40, 0x07, 0x6f, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x69, 0x6e, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x77, 0x07,
- 0x40, 0x07, 0x61, 0x67, 0x61, 0x72, 0x00, 0x40, 0x07, 0x61, 0x64, 0x61,
- 0x00, 0x40, 0x09, 0x69, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x6c, 0x02,
- 0x6d, 0x19, 0x6e, 0x1d, 0x79, 0x23, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f,
- 0x0e, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x65,
- 0x61, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x69, 0x75, 0x73, 0x00, 0x40, 0x07, 0x75, 0x69, 0x00, 0xe3, 0x63,
- 0x00, 0x64, 0x0e, 0x73, 0x19, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x65, 0x6d, 0x69,
- 0x61, 0x74, 0x72, 0x69, 0x78, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74,
- 0x00, 0xe2, 0x67, 0x00, 0x6f, 0x21, 0xe2, 0x69, 0x00, 0x6f, 0x1a, 0xe3,
- 0x65, 0x00, 0x6c, 0x02, 0x6e, 0x04, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x00, 0x06, 0x40, 0x07, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x68, 0x0d,
- 0x69, 0x12, 0x74, 0x27, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x6e, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x75, 0x00, 0xe1, 0x67,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x75, 0x6c, 0x61,
- 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x04, 0x75, 0x06, 0x40, 0x07, 0x6d, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69,
- 0x10, 0x40, 0x07, 0x6c, 0x64, 0x69, 0x00, 0x40, 0x07, 0x6b, 0x61, 0x6e,
- 0x61, 0x6e, 0x64, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x6e, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe3,
- 0x64, 0x00, 0x6d, 0x19, 0x73, 0x20, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0xe2, 0x6d, 0x00, 0x76, 0x05, 0x40, 0x07, 0x69, 0x72, 0x00, 0x40,
- 0x07, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x63,
- 0x6b, 0x00, 0x40, 0x07, 0x69, 0x63, 0x00, 0xe7, 0x49, 0x00, 0x64, 0x04,
- 0x67, 0x0c, 0x6c, 0x11, 0x6e, 0x5f, 0x72, 0x6f, 0x79, 0x81, 0x40, 0x00,
- 0x50, 0x00, 0x40, 0x07, 0x61, 0x66, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x75, 0x65, 0x00, 0xe7, 0x63, 0x00, 0x64, 0x06, 0x67, 0x0e, 0x6b, 0x1c,
- 0x73, 0x25, 0x74, 0x2c, 0x76, 0x3b, 0x40, 0x07, 0x6b, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x65, 0x6d, 0x6f, 0x72, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x67, 0x72, 0x61, 0x64, 0x00, 0x40, 0x07,
- 0x73, 0x77, 0x61, 0x67, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x65, 0x61,
- 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe2, 0x64, 0x00,
- 0x6e, 0x04, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x65, 0x67, 0x75, 0x74,
- 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x7a, 0x68,
- 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x67, 0x65,
- 0x72, 0x00, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x74,
- 0x74, 0x6f, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x67, 0x05, 0x40, 0x07, 0x61,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x06, 0x74,
- 0x65, 0x00, 0xc1, 0x41, 0x39, 0x77, 0x00, 0x79, 0x00, 0x00, 0x00, 0x8e,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x94,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x9a, 0x00, 0x00,
- 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0xa4, 0x00, 0x00,
- 0x00, 0xa8, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0xb3, 0x04, 0x76, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f,
- 0x08, 0x00, 0x00, 0x71, 0x08, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x09, 0x00,
- 0x00, 0x00, 0x00, 0xf9, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
- 0x0a, 0x00, 0x30, 0xe4, 0x00, 0x00, 0x43, 0x02, 0x53, 0x04, 0x54, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x50, 0x00, 0x40, 0x07, 0x53, 0x00,
- 0x00, 0x00, 0x40, 0x07, 0x4f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x44, 0x00,
- 0x40, 0x07, 0x57, 0x00, 0x00, 0x00, 0x40, 0x07, 0x57, 0x00, 0x40, 0x00,
- 0x4f, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x49, 0x02, 0x57, 0x0b, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x49, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x53, 0x02, 0x00, 0x00, 0x40, 0x00, 0x49, 0x57, 0x59,
- 0x47, 0x00, 0xff, 0x62, 0x00, 0x00, 0x63, 0x06, 0x00, 0x64, 0x0f, 0x00,
- 0x67, 0x13, 0x00, 0x68, 0x28, 0x00, 0x69, 0x2f, 0x00, 0x6b, 0x3e, 0x00,
- 0x6c, 0x4b, 0x00, 0x6e, 0x19, 0x01, 0x72, 0x35, 0x01, 0x73, 0x83, 0x01,
- 0x74, 0xbb, 0x01, 0x75, 0x0d, 0x02, 0x76, 0x12, 0x02, 0x79, 0x16, 0x02,
- 0x40, 0x07, 0x61, 0x73, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x61, 0x62, 0x69, 0x00, 0xe2,
- 0x6b, 0x00, 0x74, 0x06, 0x40, 0x07, 0x69, 0x6b, 0x69, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6d,
- 0x61, 0x6e, 0x00, 0xe9, 0x64, 0x00, 0x65, 0x33, 0x67, 0x3f, 0x6b, 0x46,
- 0x6c, 0x54, 0x6d, 0x82, 0x70, 0x88, 0x73, 0x9e, 0x74, 0xa2, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x68, 0x19, 0x6f, 0x1f, 0x00, 0x14, 0xe2, 0x6d, 0x00,
- 0x6e, 0x05, 0x40, 0x07, 0x61, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x69,
- 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x66,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x65, 0x65, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6d,
- 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x16, 0x6f, 0x1a, 0x73, 0x1f, 0x00,
- 0x2b, 0x40, 0x07, 0x63, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x08, 0x40,
- 0x07, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x07, 0x61, 0x72,
- 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40, 0x07, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x72, 0x67, 0x69, 0x73, 0x6e, 0x61, 0x63, 0x68, 0x74, 0x00,
- 0x40, 0x07, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x0e, 0x00,
- 0x13, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x64, 0x08, 0x67, 0x0c,
- 0x6b, 0x0e, 0x40, 0x07, 0x6d, 0x61, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6c, 0x00, 0xe9, 0x63, 0x00,
- 0x64, 0x07, 0x65, 0x09, 0x68, 0x0b, 0x69, 0x10, 0x6e, 0x15, 0x72, 0x1a,
- 0x73, 0x1f, 0x77, 0x24, 0x40, 0x07, 0x72, 0x61, 0x66, 0x74, 0x00, 0x00,
- 0x07, 0x00, 0x15, 0x40, 0x07, 0x6f, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0x40,
- 0x07, 0x61, 0x77, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x69,
- 0x72, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x06, 0x73, 0x28, 0x40, 0x07,
- 0x74, 0x63, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1,
- 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x6e, 0x00, 0xe5,
- 0x65, 0x00, 0x6b, 0x27, 0x73, 0x2d, 0x74, 0x32, 0x75, 0x42, 0xe1, 0x72,
- 0x00, 0xe5, 0x62, 0x00, 0x66, 0x06, 0x67, 0x0c, 0x6c, 0x12, 0x73, 0x17,
- 0x40, 0x07, 0x75, 0x72, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x64, 0x00,
- 0x40, 0x07, 0x61, 0x74, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x69, 0x6e, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x07, 0x00, 0x06, 0x40, 0x07, 0x61,
- 0x75, 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x69, 0x00, 0x40, 0x07, 0x67,
- 0x68, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xfb,
- 0x61, 0x00, 0x00, 0x62, 0x06, 0x00, 0x64, 0x42, 0x00, 0x65, 0x62, 0x00,
- 0x68, 0x67, 0x00, 0x69, 0x70, 0x00, 0x6c, 0xad, 0x00, 0x6e, 0x00, 0x01,
- 0x73, 0x13, 0x01, 0x79, 0x71, 0x01, 0x7a, 0x77, 0x01, 0x40, 0x07, 0x76,
- 0x65, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x42, 0x02, 0x53, 0x09, 0x62, 0x11,
- 0x65, 0x13, 0x73, 0x1f, 0x00, 0x0e, 0x40, 0x00, 0x6f, 0x61, 0x72, 0x64,
- 0x00, 0x40, 0x07, 0x70, 0x68, 0x65, 0x72, 0x65, 0x00, 0x00, 0x07, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2,
- 0x68, 0x00, 0x74, 0x06, 0x40, 0x07, 0x6f, 0x74, 0x73, 0x00, 0x40, 0x09,
- 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x67, 0x08, 0x6e, 0x0f,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x77, 0x6f,
- 0x6f, 0x64, 0x00, 0x40, 0x09, 0x65, 0x73, 0x64, 0x61, 0x79, 0x00, 0x40,
- 0x07, 0x6b, 0x73, 0x00, 0x40, 0x07, 0x72, 0x6d, 0x61, 0x63, 0x68, 0x74,
- 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x0c, 0x6e, 0x10, 0x73, 0x17,
- 0x7a, 0x29, 0x00, 0x07, 0x40, 0x07, 0x72, 0x73, 0x74, 0x72, 0x61, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x62, 0x65, 0x72, 0x67,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x75, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e,
- 0x6e, 0x00, 0xe4, 0x63, 0x00, 0x64, 0x04, 0x6c, 0x09, 0x73, 0x2a, 0x40,
- 0x07, 0x68, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x0e, 0x73, 0x16, 0x40, 0x07, 0x6e, 0x64, 0x00, 0xe2, 0x72,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x67, 0x74,
- 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x6d,
- 0x02, 0x77, 0x0f, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x61, 0x6e,
- 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x79, 0x07, 0x40,
- 0x07, 0x6c, 0x6c, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x6c,
- 0x04, 0x73, 0x15, 0x74, 0x22, 0x40, 0x07, 0x6b, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x78, 0x00, 0x40,
- 0x07, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x6d, 0x11,
- 0x6f, 0x1a, 0x70, 0x1e, 0x00, 0x06, 0x40, 0x1f, 0x72, 0x6e, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x07, 0x69,
- 0x6e, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x68, 0x61, 0x6c, 0x69, 0x61, 0x00, 0x40, 0x07, 0x64, 0x65, 0x6e, 0x00,
- 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x07, 0x69, 0x31,
- 0x40, 0x07, 0x72, 0x74, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x14,
- 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x73, 0x05, 0x40, 0x07, 0x65, 0x73,
- 0x00, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe5, 0x67, 0x00, 0x70, 0x02, 0x72, 0x08, 0x73, 0x10, 0x74, 0x17,
- 0x00, 0x06, 0x40, 0x07, 0x70, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x70,
- 0x6f, 0x6f, 0x6c, 0x00, 0x40, 0x07, 0x74, 0x6c, 0x65, 0x72, 0x00, 0xe8,
- 0x61, 0x00, 0x65, 0x06, 0x66, 0x34, 0x6c, 0x3b, 0x6d, 0x40, 0x6e, 0x45,
- 0x73, 0x4a, 0x74, 0x52, 0x40, 0x07, 0x6b, 0x65, 0x72, 0x00, 0xe4, 0x00,
- 0x00, 0x66, 0x02, 0x68, 0x09, 0x6c, 0x20, 0x00, 0x06, 0x40, 0x07, 0x69,
- 0x65, 0x6c, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6f, 0x0a, 0x40,
- 0x07, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x64, 0x00, 0x40, 0x07, 0x72,
- 0x73, 0x65, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x69, 0x65,
- 0x6c, 0x64, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x09, 0x75, 0x6e, 0x64, 0x61,
- 0x79, 0x00, 0x40, 0x07, 0x69, 0x65, 0x72, 0x00, 0xfb, 0x46, 0x00, 0x00,
- 0x63, 0x08, 0x00, 0x65, 0x17, 0x00, 0x67, 0x32, 0x00, 0x69, 0x42, 0x00,
- 0x6b, 0x44, 0x00, 0x6c, 0x9d, 0x00, 0x6d, 0xd2, 0x01, 0x6e, 0xe4, 0x01,
- 0x73, 0x8b, 0x02, 0x74, 0xb5, 0x02, 0x60, 0x07, 0x69, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xe2, 0x63, 0x00, 0x68, 0x04, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x07, 0x69, 0x74, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x05, 0x40, 0x07,
- 0x61, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x74, 0x68, 0x61, 0x6c, 0x00, 0xe2, 0x67, 0x00, 0x6e,
- 0x06, 0x40, 0x07, 0x69, 0x6e, 0x73, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0x00, 0x07, 0xe2, 0x69, 0x00, 0x74, 0x4b, 0xe8, 0x50, 0x00, 0x62, 0x09,
- 0x6c, 0x10, 0x6d, 0x17, 0x6e, 0x1e, 0x70, 0x24, 0x71, 0x2b, 0x73, 0x32,
- 0x40, 0x07, 0x61, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x40, 0x07, 0x6f,
- 0x6f, 0x6b, 0x73, 0x00, 0x40, 0x00, 0x65, 0x61, 0x6b, 0x73, 0x00, 0x40,
- 0x07, 0x65, 0x64, 0x69, 0x61, 0x00, 0x40, 0x07, 0x65, 0x77, 0x73, 0x00,
- 0x40, 0x07, 0x65, 0x64, 0x69, 0x61, 0x00, 0x40, 0x07, 0x75, 0x6f, 0x74,
- 0x65, 0x00, 0x40, 0x07, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6e, 0x61, 0x72, 0x79, 0x00, 0xfb, 0x62, 0x00, 0x00, 0x63,
- 0x22, 0x00, 0x64, 0x27, 0x00, 0x65, 0x37, 0x00, 0x66, 0x40, 0x00, 0x68,
- 0x59, 0x00, 0x6b, 0x6e, 0x00, 0x6c, 0x91, 0x00, 0x6d, 0xdc, 0x00, 0x73,
- 0xf1, 0x00, 0x74, 0x03, 0x01, 0xe2, 0x65, 0x00, 0x75, 0x11, 0xe1, 0x72,
- 0x00, 0xe2, 0x66, 0x00, 0x74, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x63, 0x65,
- 0x00, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x78, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x0e, 0x00, 0x07,
- 0xe2, 0x73, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x6f, 0x00,
- 0x72, 0x05, 0x40, 0x07, 0x72, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d,
- 0xe2, 0x72, 0x00, 0x73, 0x06, 0x40, 0x07, 0x73, 0x6f, 0x6e, 0x00, 0x00,
- 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x16, 0x69, 0x1e, 0x79, 0x3e, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6d, 0x02,
- 0x72, 0x09, 0x00, 0x07, 0x40, 0x07, 0x65, 0x74, 0x74, 0x65, 0x00, 0x40,
- 0x07, 0x64, 0x00, 0x40, 0x07, 0x6d, 0x73, 0x74, 0x61, 0x64, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x15, 0x73, 0x17, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x61, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x00, 0x07, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x00,
- 0xe2, 0x6f, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x68,
- 0x69, 0x72, 0x65, 0x00, 0xe2, 0x62, 0x00, 0x73, 0x08, 0x40, 0x07, 0x6c,
- 0x65, 0x64, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0xe9, 0x63,
- 0x00, 0x64, 0x15, 0x65, 0x45, 0x66, 0x4b, 0x69, 0x5a, 0x6b, 0x61, 0x6e,
- 0x66, 0x73, 0x7e, 0x74, 0x84, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x6c, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x65,
- 0x72, 0x00, 0xe6, 0x62, 0x00, 0x65, 0x09, 0x68, 0x0d, 0x6f, 0x13, 0x73,
- 0x18, 0x77, 0x1d, 0x40, 0x07, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x78, 0x00, 0x40, 0x07, 0x6f, 0x65, 0x6b, 0x00, 0x40, 0x07,
- 0x77, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x00, 0x40, 0x07, 0x61, 0x72,
- 0x64, 0x00, 0x40, 0x07, 0x73, 0x61, 0x70, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x64, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x66, 0x72, 0x65, 0x64, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x07, 0x40, 0x07, 0x62, 0x61, 0x67, 0x6f, 0x00, 0xe2,
- 0x65, 0x00, 0x70, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x67, 0x00, 0x40,
- 0x07, 0x74, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x05, 0x40, 0x07,
- 0x72, 0x73, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x70, 0x00, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x65, 0x21, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x74, 0x65,
- 0x00, 0x00, 0x07, 0xe2, 0x74, 0x00, 0x77, 0x11, 0xe2, 0x00, 0x00, 0x67,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e,
- 0x00, 0x40, 0x07, 0x61, 0x74, 0x65, 0x72, 0x73, 0x72, 0x61, 0x6e, 0x64,
- 0x00, 0x00, 0x07, 0xf9, 0x62, 0x00, 0x00, 0x64, 0x07, 0x00, 0x6c, 0x10,
- 0x00, 0x6e, 0x58, 0x00, 0x6f, 0x71, 0x00, 0x72, 0xd6, 0x00, 0x74, 0x23,
- 0x01, 0x76, 0x28, 0x01, 0x7a, 0x2e, 0x01, 0x40, 0x07, 0x65, 0x67, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x65, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe4,
- 0x66, 0x00, 0x6c, 0x15, 0x73, 0x2e, 0x76, 0x33, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x66, 0x04, 0x67, 0x06, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x07, 0x61, 0x6e, 0x67, 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x08, 0x40, 0x07,
- 0x6e, 0x67, 0x6f, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x65,
- 0x63, 0x72, 0x61, 0x66, 0x74, 0x00, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40,
- 0x00, 0x65, 0x72, 0x68, 0x61, 0x6d, 0x70, 0x74, 0x6f, 0x6e, 0x00, 0xe2,
- 0x64, 0x00, 0x67, 0x12, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x61, 0x00, 0x00, 0x07,
- 0xe4, 0x64, 0x00, 0x6c, 0x32, 0x73, 0x51, 0x74, 0x57, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x68, 0x07, 0x72, 0x0d, 0x73, 0x12, 0x77, 0x1f, 0x00, 0x06,
- 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x07, 0x75, 0x6c, 0x6c, 0x00, 0x40,
- 0x07, 0x6f, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00, 0xe4,
- 0x66, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x77, 0x0f, 0x00, 0x07, 0x40, 0x07,
- 0x74, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x6f, 0x6e, 0x67, 0x00, 0x40,
- 0x07, 0x6f, 0x72, 0x74, 0x68, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x1d, 0x6b, 0x31,
- 0x6c, 0x37, 0x6d, 0x3e, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x68, 0x69, 0x72, 0x65, 0x00, 0xe2, 0x50, 0x00,
- 0x73, 0x07, 0x40, 0x07, 0x72, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x77,
- 0x6f, 0x72, 0x74, 0x68, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x64, 0x43, 0x61, 0x74, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6b, 0x61, 0x00, 0xe2, 0x6e, 0x00,
- 0x7a, 0x06, 0x40, 0x07, 0x69, 0x61, 0x6b, 0x00, 0x40, 0x07, 0x65, 0x63,
- 0x6b, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x08, 0x69, 0x0c, 0x6f, 0x1d, 0x40,
- 0x07, 0x6e, 0x67, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x74, 0x00, 0x40,
- 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x63, 0x6c, 0x61, 0x77, 0x00, 0xe3,
- 0x00, 0x00, 0x68, 0x02, 0x72, 0x07, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x7a, 0x65, 0x72, 0x00, 0xe6, 0x61,
- 0x00, 0x63, 0x05, 0x65, 0x19, 0x6c, 0x1e, 0x6e, 0x23, 0x6f, 0x27, 0x40,
- 0x07, 0x74, 0x74, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x08, 0x40, 0x07, 0x65,
- 0x72, 0x6c, 0x65, 0x79, 0x00, 0x40, 0x07, 0x69, 0x66, 0x66, 0x65, 0x00,
- 0x40, 0x07, 0x74, 0x68, 0x00, 0x40, 0x07, 0x69, 0x65, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x06, 0x74, 0x65, 0x00, 0xee, 0x00, 0x00, 0x45, 0x02, 0x4c,
- 0x09, 0x4d, 0x0b, 0x53, 0x0f, 0x58, 0x11, 0x61, 0x15, 0x62, 0x38, 0x65,
- 0x3d, 0x68, 0x6c, 0x69, 0x72, 0x6d, 0xa3, 0x6f, 0xa8, 0x75, 0xb3, 0x00,
- 0x07, 0x40, 0x07, 0x6d, 0x61, 0x63, 0x73, 0x00, 0x00, 0x07, 0x40, 0x00,
- 0x4c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x4c, 0x00, 0xe2, 0x6e, 0x00, 0x76,
- 0x18, 0xe2, 0x61, 0x00, 0x74, 0x0b, 0xe2, 0x64, 0x00, 0x78, 0x04, 0x40,
- 0x07, 0x75, 0x00, 0x00, 0x07, 0x40, 0x07, 0x68, 0x69, 0x70, 0x70, 0x65,
- 0x00, 0x40, 0x07, 0x69, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x78, 0x00,
- 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x1a, 0x00, 0x06, 0xe3, 0x61, 0x00,
- 0x69, 0x06, 0x6f, 0x0a, 0x40, 0x07, 0x6b, 0x69, 0x73, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x07, 0x70, 0x68, 0x6f, 0x6e, 0x00, 0xe2, 0x6f, 0x00,
- 0x78, 0x04, 0x40, 0x09, 0x78, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40,
- 0x07, 0x6f, 0x73, 0x61, 0x00, 0xe5, 0x27, 0x00, 0x61, 0x05, 0x6d, 0x13,
- 0x6e, 0x1a, 0x6f, 0x1f, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe2, 0x6e, 0x00,
- 0x6f, 0x02, 0x00, 0x06, 0x40, 0x07, 0x70, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x07, 0x65, 0x6e, 0x65, 0x73, 0x00, 0x40, 0x07, 0x67, 0x75, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x6e, 0x75, 0x00, 0x40, 0x09, 0x61, 0x73, 0x00, 0x40,
- 0x07, 0x63, 0x68, 0x69, 0x70, 0x69, 0x6c, 0x6c, 0x69, 0x00, 0x40, 0x07,
- 0x7a, 0x68, 0x6f, 0x75, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x4d, 0x02, 0x00,
- 0x54, 0x15, 0x00, 0x57, 0x17, 0x00, 0x61, 0x24, 0x00, 0x62, 0xf6, 0x00,
- 0x65, 0xf8, 0x00, 0x67, 0x89, 0x01, 0x69, 0x93, 0x01, 0x6d, 0x9b, 0x01,
- 0x6f, 0xa0, 0x01, 0x70, 0x3b, 0x02, 0x75, 0x4e, 0x02, 0x76, 0xb3, 0x02,
- 0x00, 0x07, 0xe3, 0x43, 0x00, 0x48, 0x04, 0x4d, 0x08, 0x40, 0x07, 0x41,
- 0x00, 0x40, 0x00, 0x41, 0x00, 0x40, 0x00, 0x56, 0x00, 0x00, 0x00, 0xe2,
- 0x43, 0x00, 0x48, 0x04, 0x40, 0x07, 0x41, 0x00, 0x40, 0x00, 0x41, 0x00,
- 0xea, 0x63, 0x00, 0x68, 0x04, 0x6b, 0x1a, 0x6c, 0x32, 0x6d, 0x47, 0x6e,
- 0x66, 0x6f, 0x88, 0x71, 0x99, 0x72, 0x9e, 0x74, 0xaf, 0x40, 0x07, 0x63,
- 0x00, 0xe3, 0x6f, 0x00, 0x74, 0x04, 0x77, 0x0a, 0x40, 0x07, 0x6f, 0x00,
- 0x40, 0x07, 0x7a, 0x65, 0x65, 0x00, 0x40, 0x07, 0x65, 0x68, 0x00, 0xe2,
- 0x69, 0x00, 0x75, 0x05, 0x40, 0x07, 0x6d, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6b, 0x00, 0xe4,
- 0x65, 0x00, 0x6f, 0x02, 0x74, 0x06, 0x75, 0x0a, 0x00, 0x07, 0x40, 0x07,
- 0x77, 0x00, 0x40, 0x07, 0x61, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f,
- 0x0f, 0xe2, 0x67, 0x00, 0x68, 0x06, 0x40, 0x07, 0x61, 0x74, 0x61, 0x00,
- 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x75, 0x73, 0x73, 0x6f, 0x75, 0x6b,
- 0x72, 0x6f, 0x00, 0xe2, 0x67, 0x00, 0x6b, 0x12, 0xe3, 0x00, 0x00, 0x6f,
- 0x02, 0x74, 0x06, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x7a,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x40, 0x06, 0x65,
- 0x00, 0xe2, 0x62, 0x00, 0x75, 0x06, 0x40, 0x07, 0x61, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x6e, 0x64, 0x65, 0x00, 0x40, 0x07, 0x75, 0x69, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x6c,
- 0x61, 0x76, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x72,
- 0x6f, 0x00, 0x40, 0x07, 0x73, 0x00, 0x00, 0x07, 0xe8, 0x61, 0x00, 0x6b,
- 0x0e, 0x6c, 0x1b, 0x6d, 0x3f, 0x6e, 0x57, 0x72, 0x5e, 0x73, 0x6e, 0x76,
- 0x75, 0xe2, 0x67, 0x00, 0x74, 0x05, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x07, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62,
- 0x75, 0x72, 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x19, 0xe1, 0x6f, 0x00,
- 0xe1, 0x77, 0x00, 0xe2, 0x6b, 0x00, 0x73, 0x07, 0x40, 0x07, 0x6e, 0x69,
- 0x66, 0x65, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x73, 0x69, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x69, 0x73, 0x65, 0x69, 0x00, 0xe2,
- 0x65, 0x00, 0x6b, 0x06, 0x40, 0x07, 0x76, 0x61, 0x6e, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x69, 0x61, 0x00, 0x40, 0x07,
- 0x74, 0x75, 0x73, 0x68, 0x65, 0x6e, 0x6b, 0x6f, 0x00, 0x40, 0x07, 0x67,
- 0x64, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x00, 0x40, 0x07, 0x64, 0x64, 0x69,
- 0x73, 0x68, 0x00, 0x40, 0x07, 0x69, 0x72, 0x00, 0xe7, 0x64, 0x00, 0x6b,
- 0x04, 0x6c, 0x22, 0x6e, 0x29, 0x72, 0x36, 0x73, 0x5c, 0x75, 0x70, 0x40,
- 0x07, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x0c, 0x40, 0x07, 0x61, 0x70,
- 0x61, 0x74, 0x61, 0x77, 0x70, 0x68, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x68,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x6d, 0x61, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x64, 0x61, 0x00, 0xe2, 0x67, 0x00, 0x6b, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x72, 0x73, 0x00, 0xe2, 0x6b, 0x00, 0x75, 0x1c, 0xe4, 0x00,
- 0x00, 0x69, 0x02, 0x73, 0x06, 0x74, 0x0d, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x09, 0x68, 0x69, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x77,
- 0x6e, 0x00, 0x40, 0x07, 0x62, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x07,
- 0x40, 0x07, 0x6d, 0x69, 0x74, 0x65, 0x00, 0x40, 0x07, 0x61, 0x72, 0x69,
- 0x61, 0x6e, 0x00, 0xe2, 0x54, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x75, 0x62,
- 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x6f, 0x77, 0x6e, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x05,
- 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x61, 0x6e, 0x74,
- 0x69, 0x00, 0xe8, 0x61, 0x00, 0x63, 0x04, 0x67, 0x0b, 0x6b, 0x31, 0x6c,
- 0x36, 0x6d, 0x46, 0x6e, 0x4a, 0x72, 0x50, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x61, 0x74, 0x61, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x76,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40,
- 0x09, 0x69, 0x64, 0x65, 0x00, 0x40, 0x06, 0x61, 0x00, 0x40, 0x07, 0x6e,
- 0x61, 0x6e, 0x00, 0x40, 0x07, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x0c,
- 0xe2, 0x73, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x00,
- 0x40, 0x07, 0x6e, 0x6e, 0x65, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x44, 0x02,
- 0x00, 0x61, 0x08, 0x00, 0x65, 0xc2, 0x00, 0x68, 0x4d, 0x01, 0x69, 0x86,
- 0x01, 0x6e, 0x00, 0x02, 0x6f, 0x02, 0x02, 0x72, 0x6a, 0x02, 0x73, 0x6c,
- 0x02, 0x75, 0x76, 0x02, 0x77, 0xc6, 0x02, 0x79, 0xda, 0x02, 0x7a, 0xed,
- 0x02, 0x00, 0x31, 0x40, 0x07, 0x4e, 0x65, 0x74, 0x00, 0xe7, 0x63, 0x00,
- 0x67, 0x1c, 0x69, 0x22, 0x6d, 0x31, 0x6e, 0x61, 0x70, 0x76, 0x72, 0x98,
- 0xe1, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x61, 0x68, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x72, 0x79, 0x00, 0x40, 0x07, 0x72, 0x65, 0x62, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x61, 0x6e,
- 0x00, 0xe3, 0x62, 0x00, 0x65, 0x1d, 0x6f, 0x24, 0xe3, 0x65, 0x00, 0x69,
- 0x05, 0x6f, 0x11, 0x40, 0x07, 0x7a, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x69,
- 0x00, 0x40, 0x07, 0x6e, 0x68, 0x6f, 0x66, 0x00, 0x40, 0x07, 0x72, 0x61,
- 0x00, 0xe3, 0x65, 0x00, 0x75, 0x02, 0x7a, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x63, 0x6b, 0x00, 0x40, 0x07, 0x69, 0x62, 0x61, 0x72, 0x00, 0xe3, 0x61,
- 0x00, 0x6f, 0x05, 0x70, 0x17, 0x40, 0x07, 0x74, 0x61, 0x00, 0xe2, 0x72,
- 0x00, 0x74, 0x08, 0x40, 0x07, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x63, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x75, 0x73, 0x74,
- 0x72, 0x61, 0x00, 0xeb, 0x61, 0x00, 0x62, 0x0b, 0x63, 0x12, 0x64, 0x1b,
- 0x66, 0x2c, 0x6b, 0x36, 0x6c, 0x3a, 0x6e, 0x47, 0x70, 0x57, 0x73, 0x6c,
- 0x75, 0x70, 0x60, 0x89, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0x07, 0x00, 0xff,
- 0xff, 0x40, 0x07, 0x65, 0x64, 0x65, 0x65, 0x00, 0x40, 0x07, 0x68, 0x61,
- 0x72, 0x69, 0x61, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x07, 0x40, 0x07,
- 0x6b, 0x69, 0x61, 0x68, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x66, 0x69, 0x72, 0x65, 0x6c, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0xe2, 0x69, 0x00, 0x6d, 0x04, 0x40, 0x07, 0x67, 0x00, 0x40, 0x07, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x6f, 0x07, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x79,
- 0x07, 0x40, 0x07, 0x6e, 0x69, 0x61, 0x68, 0x00, 0x40, 0x07, 0x72, 0x75,
- 0x73, 0x00, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe6, 0x61,
- 0x00, 0x64, 0x0b, 0x65, 0x12, 0x69, 0x1b, 0x6f, 0x22, 0x75, 0x26, 0xe2,
- 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x67, 0x00, 0x00, 0x07, 0x40, 0x00,
- 0x61, 0x6e, 0x6f, 0x76, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x7a, 0x68, 0x6f,
- 0x75, 0x00, 0x40, 0x07, 0x76, 0x61, 0x67, 0x6f, 0x00, 0x40, 0x07, 0x75,
- 0x00, 0x40, 0x07, 0x6b, 0x6f, 0x76, 0x00, 0xe8, 0x62, 0x00, 0x65, 0x04,
- 0x66, 0x17, 0x67, 0x1b, 0x6d, 0x20, 0x6e, 0x44, 0x6f, 0x4d, 0x70, 0x63,
- 0x40, 0x07, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x66, 0x00, 0x6c, 0x06,
- 0x40, 0x07, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x66, 0x00, 0x40, 0x07, 0x67, 0x79, 0x00, 0xe2, 0x62, 0x00, 0x6d,
- 0x17, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x77, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x00,
- 0x40, 0x07, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x66, 0x61,
- 0x6e, 0x64, 0x65, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0x00, 0x06, 0x40, 0x07, 0x6c, 0x6f, 0x63, 0x00, 0x00, 0x07, 0xe6,
- 0x65, 0x00, 0x6c, 0x02, 0x6d, 0x19, 0x70, 0x1e, 0x72, 0x22, 0x73, 0x56,
- 0x00, 0x07, 0xe3, 0x61, 0x00, 0x6c, 0x02, 0x6f, 0x0b, 0x00, 0x07, 0x40,
- 0x07, 0x76, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x66, 0x74,
- 0x00, 0x40, 0x07, 0x62, 0x61, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x6e,
- 0x00, 0x6f, 0x02, 0x72, 0x29, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x73, 0x6d, 0x00, 0x40, 0x07,
- 0x6f, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x00, 0x00, 0x07, 0x40, 0x07, 0x69,
- 0x67, 0x6d, 0x6f, 0x6e, 0x64, 0x79, 0x00, 0xe5, 0x62, 0x00, 0x6b, 0x21,
- 0x6c, 0x26, 0x6e, 0x36, 0x72, 0x3f, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x09, 0x40, 0x07, 0x67, 0x65,
- 0x6e, 0x75, 0x62, 0x69, 0x00, 0x40, 0x07, 0x63, 0x68, 0x61, 0x6d, 0x61,
- 0x6c, 0x69, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x40, 0x00, 0x61, 0x6e, 0x64, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x69,
- 0x63, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6e, 0x67,
- 0x6c, 0x69, 0x00, 0x40, 0x07, 0x72, 0x79, 0x6b, 0x69, 0x6e, 0x00, 0xe2,
- 0x72, 0x00, 0x75, 0x06, 0x40, 0x07, 0x74, 0x65, 0x63, 0x00, 0x40, 0x07,
- 0x67, 0x61, 0x6e, 0x6f, 0x76, 0x00, 0x40, 0x00, 0x7a, 0x00, 0xc1, 0x61,
- 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x4a, 0x00, 0x4a, 0x06, 0xae, 0x0d, 0x04,
- 0x14, 0x04, 0x15, 0xaf, 0x17, 0x69, 0x1a, 0x8d, 0x1a, 0xe8, 0x1c, 0xf4,
- 0x1c, 0x07, 0x1d, 0x9f, 0x23, 0xdd, 0x28, 0xe4, 0x35, 0xf5, 0x35, 0xe7,
- 0x3b, 0x72, 0x3c, 0xb6, 0x43, 0x11, 0x4a, 0x8f, 0x4d, 0xeb, 0x51, 0x78,
- 0x53, 0x67, 0x54, 0xbc, 0x54, 0xe9, 0x54, 0x00, 0x08, 0xe2, 0x68, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x40, 0x06, 0x64, 0x76, 0x61, 0x72, 0x6b, 0x00,
- 0xff, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x7b, 0x00, 0x64, 0xb8,
- 0x00, 0x65, 0x04, 0x01, 0x68, 0x56, 0x01, 0x69, 0x7f, 0x01, 0x6a, 0x9e,
- 0x01, 0x6c, 0xe0, 0x01, 0x6e, 0x1b, 0x02, 0x6f, 0x4d, 0x02, 0x72, 0x0f,
- 0x03, 0x73, 0x97, 0x03, 0x75, 0x55, 0x05, 0x79, 0xba, 0x05, 0x00, 0x32,
- 0xe6, 0x63, 0x00, 0x66, 0x0b, 0x6c, 0x0f, 0x6e, 0x15, 0x73, 0x2b, 0x74,
- 0x50, 0xe2, 0x6b, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x09, 0x73, 0x00,
- 0x40, 0x00, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x33, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x68,
- 0x0d, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x00, 0x35, 0x40,
- 0x36, 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x74, 0x11, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6d, 0x04, 0x00, 0x34, 0x00,
- 0x37, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x69, 0x72,
- 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x0f, 0x72, 0x13, 0xe3, 0x00, 0x00, 0x73,
- 0x02, 0x79, 0x06, 0x00, 0x06, 0x40, 0x09, 0x73, 0x00, 0x00, 0x09, 0x40,
- 0x09, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x76,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x08, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x15, 0x75, 0x27, 0xe1, 0x63, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x39, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x61, 0x6c, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x6f, 0x0b, 0x00, 0x3a, 0x40, 0x09, 0x65, 0x00, 0x40, 0x06, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x72, 0x04, 0x74,
- 0x27, 0x79, 0x42, 0x40, 0x00, 0x6d, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x00, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x08, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x09, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x63, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x12, 0xe2, 0x64,
- 0x00, 0x6e, 0x02, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x3b, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x64, 0x00,
- 0x6c, 0x14, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x08, 0x40, 0x07, 0x6e,
- 0x63, 0x65, 0x00, 0x00, 0x3c, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x3d,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x1a, 0xe1, 0x63, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x00, 0x3e,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x12, 0xe1, 0x74, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe4, 0x61,
- 0x00, 0x65, 0x1d, 0x6f, 0x26, 0x75, 0x2b, 0xe2, 0x74, 0x00, 0x7a, 0x14,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x40, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, 0x6f,
- 0x6d, 0x00, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x15, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe7,
- 0x61, 0x00, 0x64, 0x05, 0x6c, 0x09, 0x6d, 0x31, 0x72, 0x57, 0x75, 0x97,
- 0x76, 0xa2, 0x40, 0x00, 0x72, 0x64, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x0b, 0x68, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x62, 0x00, 0x74, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x38,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x69, 0x00, 0x6e, 0x14, 0x74, 0x1a,
- 0xe1, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x06, 0x40, 0x00, 0x69, 0x6e,
- 0x67, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x43, 0xe2, 0x6f, 0x00,
- 0x76, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe2, 0x6e, 0x00,
- 0x74, 0x04, 0x40, 0x3a, 0x64, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x61, 0x72, 0x64,
- 0x00, 0xe5, 0x61, 0x00, 0x65, 0x30, 0x69, 0x36, 0x6f, 0x49, 0x75, 0x6a,
- 0xe3, 0x63, 0x00, 0x64, 0x09, 0x73, 0x0d, 0x40, 0x07, 0x61, 0x64, 0x61,
- 0x62, 0x72, 0x61, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x44, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x61, 0x73, 0x74, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x65, 0x00, 0x6d, 0x02, 0x00, 0x3a, 0x40, 0x09, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x61, 0x00, 0x67, 0x04, 0x40, 0x00, 0x64, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x70,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x46, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00,
- 0x65, 0x31, 0x00, 0x69, 0x77, 0x00, 0x6f, 0x7e, 0x00, 0x74, 0xef, 0x00,
- 0x75, 0x86, 0x01, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x6f, 0x17,
- 0x40, 0x47, 0x73, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x48,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6e, 0x04, 0x40, 0x47, 0x6c,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x6d, 0x11, 0x00, 0x49, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x68, 0x65, 0x00, 0xe2, 0x6c, 0x00,
- 0x72, 0x30, 0xe2, 0x75, 0x00, 0x76, 0x27, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4a, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x3a,
- 0x65, 0x00, 0xe2, 0x62, 0x00, 0x70, 0x24, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x08, 0x69, 0x16, 0x00, 0x4b, 0x40, 0x00, 0x6e, 0x63, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00,
- 0x00, 0x06, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x11, 0x69, 0x36, 0x72, 0x4a, 0xe1,
- 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x4c,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x19, 0xe1, 0x69, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x00, 0xe2, 0x61, 0x00, 0x75, 0x2c, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x12, 0x6e, 0x17, 0x00, 0x4e, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x0f, 0x00, 0x46,
- 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x09, 0x74, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x6e, 0x00, 0x73, 0x14,
- 0x74, 0x3b, 0x7a, 0x58, 0xe1, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x3b,
- 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x72, 0x06,
- 0x00, 0x4f, 0x40, 0x00, 0x73, 0x00, 0x00, 0x09, 0xe1, 0x76, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x74, 0x08, 0x00, 0x50,
- 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x7a, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00,
- 0xff, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x3f, 0x00, 0x65, 0x67,
- 0x03, 0x68, 0xd0, 0x03, 0x69, 0x15, 0x04, 0x6b, 0x41, 0x04, 0x6d, 0x72,
- 0x04, 0x6e, 0x76, 0x04, 0x6f, 0x7a, 0x04, 0x71, 0xae, 0x04, 0x72, 0x53,
- 0x05, 0x74, 0x04, 0x06, 0x75, 0xdb, 0x06, 0x79, 0x27, 0x07, 0x00, 0x00,
- 0xe3, 0x63, 0x00, 0x64, 0x05, 0x6e, 0x2f, 0x40, 0x09, 0x69, 0x61, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79,
- 0x1b, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x40,
- 0x09, 0x61, 0x6e, 0x00, 0x00, 0x06, 0x40, 0x09, 0x74, 0x68, 0x75, 0x73,
- 0x00, 0xf7, 0x65, 0x00, 0x00, 0x69, 0xc8, 0x00, 0x6c, 0xdf, 0x00, 0x6f,
- 0x24, 0x01, 0x72, 0x26, 0x02, 0x74, 0x5b, 0x02, 0x75, 0x5d, 0x02, 0xe5,
- 0x64, 0x00, 0x6c, 0x04, 0x6e, 0x22, 0x70, 0x48, 0x73, 0x84, 0x40, 0x0b,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x51, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x75, 0x06, 0x00, 0x47, 0x40, 0x37, 0x64, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x2e, 0x00, 0x52, 0xe3, 0x62,
- 0x00, 0x6e, 0x1a, 0x74, 0x1f, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x07, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x37, 0x40, 0x06, 0x63, 0x65, 0x00,
- 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x73,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x20, 0x00, 0x47, 0xe2, 0x62,
- 0x00, 0x6f, 0x15, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x54,
- 0x40, 0x55, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05,
- 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x00, 0x06, 0xe1, 0x64, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x56, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x11, 0xe2,
- 0x69, 0x00, 0x6d, 0x04, 0x40, 0x55, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x6d, 0x00, 0x76, 0x24, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0xe2, 0x6f,
- 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x06, 0x69,
- 0x74, 0x79, 0x00, 0xe5, 0x6c, 0x00, 0x6d, 0x06, 0x72, 0x71, 0x73, 0xa3,
- 0x75, 0xa7, 0x40, 0x06, 0x61, 0x64, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x70,
- 0x20, 0xe1, 0x6f, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x45, 0xe2, 0x6e, 0x00, 0x6f,
- 0x04, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x6c, 0x1f, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x15, 0xe3, 0x65,
- 0x00, 0x6d, 0x04, 0x73, 0x0a, 0x40, 0x37, 0x64, 0x00, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x3a, 0xe1, 0x69, 0x00,
- 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x68, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x00, 0x58, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x10, 0x00, 0x59, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x6e, 0x00,
- 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x59, 0x74,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x37, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x22, 0x69, 0x26, 0x00, 0x5a, 0xe2, 0x62, 0x00, 0x6e,
- 0x10, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0x40, 0x37, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x09, 0x40, 0x37, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x5b, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x75, 0x25, 0xe2, 0x64, 0x00, 0x74, 0x1a, 0xe1, 0x69, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x00, 0x5b, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x09, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x09, 0x6c, 0x00,
- 0x00, 0x0b, 0x00, 0x00, 0xe4, 0x6c, 0x00, 0x6d, 0x1b, 0x72, 0x39, 0x73,
- 0x6a, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0x40, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x61,
- 0x00, 0x73, 0x19, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x53, 0x79, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5c, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4,
- 0x61, 0x00, 0x65, 0x1a, 0x69, 0x23, 0x74, 0x28, 0xe1, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x0d, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x3a, 0x40, 0x37, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x25,
- 0x00, 0x5e, 0xe1, 0x62, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x3a,
- 0x74, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x0d, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0xe4, 0x61, 0x00, 0x69, 0x13, 0x6f, 0x17, 0x79, 0x25, 0xe2, 0x6d,
- 0x00, 0x74, 0x0a, 0x40, 0x07, 0x69, 0x6e, 0x6f, 0x70, 0x68, 0x65, 0x6e,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6e,
- 0x65, 0x00, 0xe5, 0x65, 0x00, 0x69, 0x0b, 0x6f, 0x2b, 0x72, 0x2f, 0x79,
- 0x38, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5e, 0x40, 0x09, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x6e, 0x17, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x00, 0x5f, 0x40, 0x06, 0x65, 0x6e,
- 0x74, 0x00, 0x00, 0x07, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x00,
- 0x40, 0x00, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x00, 0x00, 0x60, 0xe1,
- 0x64, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x13, 0x75, 0x19, 0x00,
- 0x56, 0xe3, 0x63, 0x00, 0x66, 0x02, 0x74, 0x06, 0x00, 0x00, 0x40, 0x0b,
- 0x79, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x73, 0x69, 0x73, 0x00,
- 0x40, 0x00, 0x6c, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x77, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x11, 0xe3, 0x00, 0x00,
- 0x64, 0x02, 0x6d, 0x04, 0x00, 0x3a, 0x00, 0x37, 0x40, 0x09, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0xe4, 0x6c, 0x00, 0x6e, 0x06, 0x72, 0x0c, 0x75,
- 0x10, 0x40, 0x09, 0x79, 0x74, 0x65, 0x00, 0x40, 0x09, 0x69, 0x74, 0x65,
- 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06,
- 0x00, 0x08, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x2c, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x18, 0x00, 0x61, 0xe1, 0x6e,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x37, 0x64, 0x00,
- 0xe4, 0x65, 0x00, 0x72, 0x1b, 0x73, 0x2b, 0x74, 0x4d, 0xe1, 0x73, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3a, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x62, 0x40, 0x07,
- 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0xe3, 0x61, 0x00,
- 0x65, 0x04, 0x69, 0x08, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x0c, 0x6f, 0x48,
- 0x79, 0x95, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x09, 0x67,
- 0x65, 0x00, 0xe2, 0x64, 0x00, 0x6d, 0x14, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6e, 0x07, 0x00, 0x63, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x16, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x07, 0xe4, 0x62, 0x00, 0x6e, 0x21, 0x70, 0x26, 0x73, 0x38, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x40, 0x09, 0x79, 0x6d,
- 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6f, 0x62, 0x69, 0x61,
- 0x00, 0x40, 0x09, 0x6c, 0x69, 0x73, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x02,
- 0x00, 0x00, 0x40, 0x06, 0x69, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x07, 0x40, 0x00, 0x6d, 0x69, 0x64, 0x65, 0x00, 0x40, 0x09,
- 0x63, 0x00, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x69, 0x06, 0x6f, 0x7a, 0x72,
- 0x7e, 0x75, 0x84, 0x00, 0x64, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x6e, 0x00,
- 0x6f, 0x10, 0x76, 0x20, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x69, 0x04, 0x00,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x75, 0x6d, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x15, 0x69, 0x2c, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x66, 0x40, 0x67, 0x6f, 0x6e, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x6e, 0x06, 0x73,
- 0x0c, 0x00, 0x68, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x09, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00,
- 0x65, 0x73, 0x00, 0x00, 0x53, 0x40, 0x69, 0x72, 0x00, 0x40, 0x09, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x6c, 0x00, 0x72, 0x1e, 0x74,
- 0x2a, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe2, 0x74, 0x00, 0x7a,
- 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe2, 0x69, 0x00, 0x79, 0x05,
- 0x40, 0x00, 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0xe4, 0x69, 0x00, 0x6d, 0x05, 0x70, 0x0a, 0x74, 0x33, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe2, 0x72, 0x00, 0x75,
- 0x09, 0x40, 0x07, 0x65, 0x73, 0x73, 0x75, 0x72, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x06, 0x73, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x6a, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x08, 0x40, 0x07,
- 0x6c, 0x6f, 0x76, 0x69, 0x72, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x64, 0x44, 0x00, 0x65, 0xca, 0x00, 0x68, 0x1b, 0x01,
- 0x69, 0x54, 0x01, 0x6a, 0x7b, 0x01, 0x6d, 0x3d, 0x02, 0x6f, 0x45, 0x03,
- 0x72, 0xd3, 0x03, 0x73, 0x19, 0x04, 0x75, 0x37, 0x04, 0x76, 0xbf, 0x04,
- 0x77, 0x1e, 0x06, 0x7a, 0x24, 0x06, 0x00, 0x06, 0xe3, 0x67, 0x00, 0x6d,
- 0x0b, 0x70, 0x11, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x09,
- 0x6f, 0x00, 0x40, 0x12, 0x61, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x15, 0x69, 0x19, 0x00, 0x6b, 0xe2, 0x62,
- 0x00, 0x74, 0x08, 0x40, 0x07, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40,
- 0x09, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x6f,
- 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x1b, 0x6c, 0x49, 0x72,
- 0x4d, 0x75, 0x74, 0x00, 0x6c, 0xe2, 0x6e, 0x00, 0x72, 0x12, 0xe1, 0x64,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x75, 0x04, 0x00, 0x09, 0x00, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x74, 0x0f, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x6d, 0x40, 0x06, 0x6f,
- 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06,
- 0x65, 0x0c, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x62, 0x6c,
- 0x65, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00, 0x37, 0x00, 0x06, 0x40,
- 0x0b, 0x63, 0x65, 0x00, 0xe3, 0x6e, 0x00, 0x70, 0x1b, 0x71, 0x2b, 0xe2,
- 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x44,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x53, 0x79, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5c, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x15, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x6e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x08, 0x6f, 0x0c, 0x70, 0x10, 0x40, 0x00, 0x62, 0x61, 0x74,
- 0x69, 0x63, 0x00, 0x40, 0x09, 0x75, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x78, 0x00, 0x40, 0x00, 0x73, 0x65,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x16, 0x6f, 0x2d, 0x75, 0x49,
- 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b, 0xe1, 0x63,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x09, 0xe2, 0x69, 0x00,
- 0x75, 0x04, 0x40, 0x0b, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x6f, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0xe5, 0x64, 0x00, 0x6e, 0x2c, 0x72, 0x31, 0x73, 0x3f, 0x74, 0x5d,
- 0xe2, 0x67, 0x00, 0x69, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x70, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0x40, 0x09, 0x63, 0x74,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x0b, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x08, 0x6d, 0x0c, 0x00, 0x71, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x69, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x61,
- 0x6e, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x69, 0x08, 0x6f, 0xd5,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe5, 0x6e, 0x00, 0x72,
- 0x3a, 0x73, 0x6c, 0x74, 0x98, 0x78, 0xb5, 0xe2, 0x00, 0x00, 0x69, 0x06,
- 0x20, 0x09, 0x08, 0x00, 0xff, 0xff, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x72, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00, 0x73,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x3b, 0x65,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1d, 0x69, 0x26,
- 0xe3, 0x62, 0x00, 0x6c, 0x05, 0x74, 0x10, 0x40, 0x00, 0x6c, 0x79, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x74,
- 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x62, 0x00, 0x6f, 0x15, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x54, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x75, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x76, 0xe3, 0x61,
- 0x00, 0x65, 0x06, 0x69, 0x0a, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0x40,
- 0x3b, 0x64, 0x00, 0x40, 0x77, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x0b, 0x40, 0x06, 0x75, 0x72, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x10, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x78, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x06, 0x70, 0x20,
- 0x72, 0x3d, 0x00, 0x07, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x06, 0xe1, 0x74,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x00, 0x79,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x06,
- 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x1c, 0x69, 0x25, 0x6e, 0x2a,
- 0xe2, 0x62, 0x00, 0x74, 0x11, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x74, 0x00,
- 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d,
- 0x06, 0x00, 0x34, 0x40, 0x37, 0x64, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x27, 0x6f, 0x2c, 0xe1, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x18, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe2, 0x27, 0x00, 0x65, 0x04, 0x40, 0x00,
- 0x73, 0x00, 0x00, 0x07, 0x40, 0x00, 0x72, 0x67, 0x69, 0x63, 0x00, 0x40,
- 0x00, 0x66, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x62, 0x00, 0x70, 0x0c, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x7a, 0x40, 0x09, 0x6e, 0x74, 0x00, 0x40, 0x06,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6d, 0x6b, 0xe2, 0x61,
- 0x00, 0x74, 0x1d, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x68, 0x3c, 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x1c, 0x6f, 0x27, 0x79, 0x2c, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x42, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x72, 0x00,
- 0x73, 0x02, 0x00, 0x06, 0x40, 0x09, 0x73, 0x00, 0x40, 0x00, 0x75, 0x73,
- 0x00, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xe1, 0x62, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xf6, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x65, 0x2f, 0x00, 0x69, 0xf5, 0x00, 0x6f, 0x37,
- 0x01, 0x74, 0x4a, 0x01, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x10, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x7b,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x7c, 0x40, 0x7d,
- 0x75, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x54, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x75, 0x0a, 0x00, 0x06, 0x40, 0x3b, 0x74, 0x69,
- 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x17,
- 0x6f, 0x23, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x7e, 0x00,
- 0x07, 0xe2, 0x6f, 0x00, 0x73, 0x05, 0x40, 0x00, 0x6d, 0x65, 0x00, 0x00,
- 0x09, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x62, 0x00, 0x73,
- 0x0c, 0x74, 0x34, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x56,
- 0x61, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x1c, 0xe1, 0x72,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x00,
- 0x06, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7f, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6f, 0x24, 0x00, 0x2c, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x15,
- 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6d, 0x04, 0x72, 0x0a, 0x00, 0x80, 0x00,
- 0x37, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x06, 0x72, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x63, 0x00,
- 0x73, 0x04, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x18, 0x6f,
- 0x2d, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00,
- 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6d, 0x04, 0x72, 0x0a, 0x00, 0x81,
- 0x00, 0x36, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x82, 0x65, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x61, 0x72, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe3, 0x67,
- 0x00, 0x72, 0x05, 0x73, 0xcb, 0x40, 0x07, 0x69, 0x73, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x15, 0x6f, 0x2b, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x56, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x09,
- 0xe5, 0x62, 0x00, 0x64, 0x2b, 0x67, 0x56, 0x6e, 0x5c, 0x73, 0x7a, 0xe2,
- 0x61, 0x00, 0x69, 0x12, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xe1, 0x63,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0xe2, 0x72, 0x00, 0x79, 0x06, 0x40,
- 0x09, 0x6f, 0x6d, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00,
- 0x07, 0x40, 0x08, 0x72, 0x61, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x00, 0x00,
- 0x07, 0xe2, 0x6f, 0x00, 0x70, 0x04, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x07,
- 0x61, 0x63, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1,
- 0x63, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x73, 0x0d, 0x00,
- 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0x00, 0x07, 0xf8, 0x61, 0x00, 0x00, 0x66, 0x04, 0x00, 0x67, 0x5a, 0x01,
- 0x69, 0x60, 0x01, 0x6c, 0x79, 0x01, 0x6f, 0x91, 0x01, 0x72, 0xc4, 0x01,
- 0x74, 0xd3, 0x01, 0x40, 0x00, 0x72, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x65,
- 0x1e, 0x00, 0x69, 0x64, 0x00, 0x6c, 0xcf, 0x00, 0x6f, 0xff, 0x00, 0x72,
- 0x35, 0x01, 0xe2, 0x62, 0x00, 0x69, 0x15, 0xe2, 0x69, 0x00, 0x6c, 0x07,
- 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x72,
- 0x3b, 0xe1, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65,
- 0x0d, 0x69, 0x11, 0x00, 0x83, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x36, 0x64, 0x00, 0xe2, 0x6e, 0x00, 0x6f,
- 0x04, 0x40, 0x3b, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x73, 0x07, 0x00, 0x84, 0x40, 0x3b, 0x74, 0x65, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x65, 0x6e, 0x74, 0x00, 0xe6, 0x61, 0x00, 0x64, 0x06, 0x6c,
- 0x0d, 0x6e, 0x39, 0x72, 0x3f, 0x78, 0x5c, 0x40, 0x0b, 0x6e, 0x63, 0x65,
- 0x00, 0x40, 0x06, 0x61, 0x76, 0x69, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe3, 0x00,
- 0x00, 0x27, 0x02, 0x64, 0x06, 0x00, 0x85, 0x40, 0x00, 0x73, 0x00, 0x00,
- 0x37, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x84, 0x00, 0x00, 0x40, 0x06, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x4b, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x69, 0x6e, 0x00, 0x40,
- 0x86, 0x65, 0x00, 0x00, 0x59, 0xe3, 0x61, 0x00, 0x69, 0x06, 0x75, 0x18,
- 0x40, 0x07, 0x74, 0x75, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x06, 0x6f, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x72, 0x00, 0xe2, 0x64, 0x00, 0x65,
- 0x1a, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x87, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x00, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40,
- 0x00, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x88, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x79, 0x00, 0x40, 0x59, 0x6e, 0x74,
- 0x00, 0x40, 0x09, 0x68, 0x61, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x65, 0x09,
- 0x72, 0x0e, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x61, 0x64, 0x6f, 0x00, 0x40,
- 0x00, 0x6c, 0x64, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x6f,
- 0x05, 0x75, 0x0a, 0x40, 0x00, 0x6d, 0x65, 0x00, 0x40, 0x00, 0x61, 0x74,
- 0x00, 0x40, 0x00, 0x74, 0x74, 0x65, 0x72, 0x00, 0xe3, 0x6f, 0x00, 0x72,
- 0x04, 0x75, 0x28, 0x40, 0x00, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x6d,
- 0x00, 0x73, 0x0b, 0x74, 0x11, 0x40, 0x00, 0x65, 0x6e, 0x74, 0x69, 0x6f,
- 0x6e, 0x65, 0x64, 0x00, 0x40, 0x00, 0x61, 0x69, 0x64, 0x00, 0x40, 0x00,
- 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x00, 0x40, 0x00, 0x6c, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x05, 0x40, 0x37, 0x69, 0x64, 0x00, 0x40, 0x00, 0x73,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x89, 0xe1, 0x72, 0x00,
- 0xeb, 0x62, 0x00, 0x63, 0x1e, 0x65, 0x24, 0x67, 0x2c, 0x69, 0x32, 0x6c,
- 0x39, 0x6d, 0x4a, 0x6e, 0x64, 0x73, 0x6a, 0x74, 0x7c, 0x77, 0x8f, 0xe2,
- 0x69, 0x00, 0x75, 0x12, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09,
- 0x72, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0x40,
- 0x09, 0x66, 0x66, 0x65, 0x63, 0x74, 0x00, 0x40, 0x06, 0x6c, 0x6f, 0x77,
- 0x00, 0x40, 0x09, 0x6d, 0x61, 0x67, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x66, 0x00, 0x76, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x06, 0x40, 0x09, 0x6b,
- 0x65, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6e, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x76, 0x65, 0x00, 0x40, 0x06,
- 0x63, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x06, 0x40, 0x06, 0x73, 0x74,
- 0x65, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x05, 0x40, 0x08, 0x72, 0x64, 0x00, 0x40, 0x09, 0x72, 0x64,
- 0x00, 0xfa, 0x61, 0x00, 0x00, 0x65, 0x27, 0x00, 0x67, 0x74, 0x00, 0x68,
- 0x39, 0x01, 0x69, 0x3f, 0x01, 0x6c, 0x76, 0x01, 0x6e, 0x8d, 0x01, 0x6f,
- 0xa8, 0x01, 0x72, 0xec, 0x01, 0x75, 0x97, 0x02, 0xe5, 0x69, 0x00, 0x70,
- 0x0e, 0x72, 0x12, 0x74, 0x14, 0x76, 0x18, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe5,
- 0x00, 0x00, 0x69, 0x02, 0x6c, 0x14, 0x6e, 0x2a, 0x72, 0x3b, 0x00, 0x8a,
- 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x00, 0x67, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x04, 0x74, 0x08, 0x40,
- 0x06, 0x79, 0x00, 0x40, 0x06, 0x61, 0x00, 0x00, 0x69, 0x40, 0x07, 0x61,
- 0x74, 0x75, 0x6d, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x3b, 0xe2, 0x6f, 0x00,
- 0x75, 0x1b, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8b,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x38, 0x69, 0x74, 0x6f, 0x7a, 0xe2, 0x6e, 0x00, 0x76, 0x19, 0xe1, 0x64,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x35, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x51,
- 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x67, 0x00, 0x73, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8d, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x19, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x3a, 0x65, 0x76, 0x65, 0x00, 0x00, 0x00, 0x40, 0x00, 0x61,
- 0x73, 0x74, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x0c, 0x74, 0x10, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07,
- 0x67, 0x00, 0xe2, 0x61, 0x00, 0x70, 0x15, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x70, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x05, 0x6f, 0x0c, 0x40, 0x00, 0x61, 0x6d, 0x00, 0x40, 0x00,
- 0x74, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x77, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6e, 0x04, 0x72, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x15, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40,
- 0x08, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe4, 0x61, 0x00, 0x65,
- 0x18, 0x69, 0x45, 0x6f, 0x80, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x16, 0x6d, 0x1b, 0x00, 0x8e, 0xe1, 0x62, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x07, 0x40, 0x84, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x8f, 0x40, 0x8f, 0x6e, 0x67, 0x00, 0x40, 0x90, 0x65, 0x6e,
- 0x74, 0x00, 0xe2, 0x62, 0x00, 0x63, 0x0a, 0x40, 0x09, 0x75, 0x73, 0x69,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x0f, 0x69, 0x11, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x09, 0x73, 0x74,
- 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x18, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0b, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x64, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x63, 0x04, 0x65, 0x0a,
- 0x6f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x68, 0x6f, 0x6f, 0x00,
- 0xe2, 0x61, 0x00, 0x6d, 0x04, 0x40, 0x00, 0x64, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x79, 0x00, 0xf8, 0x64, 0x00, 0x00, 0x67, 0x10, 0x00, 0x6c, 0x18,
- 0x00, 0x6d, 0x2d, 0x00, 0x6e, 0x4a, 0x00, 0x72, 0x4f, 0x00, 0x73, 0x38,
- 0x02, 0x74, 0x3d, 0x02, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x2c, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x06, 0x00, 0x37, 0x40, 0x09, 0x72, 0x65,
- 0x74, 0x74, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x08, 0x00,
- 0x91, 0x40, 0x06, 0x72, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x2c, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x27, 0x74, 0x00, 0xff,
- 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x63, 0x2c, 0x00, 0x64, 0x52, 0x00,
- 0x66, 0x76, 0x00, 0x67, 0x9e, 0x00, 0x68, 0xa4, 0x00, 0x69, 0xaa, 0x00,
- 0x6c, 0xbf, 0x00, 0x6d, 0xfc, 0x00, 0x70, 0x10, 0x01, 0x73, 0x28, 0x01,
- 0x74, 0x71, 0x01, 0x77, 0x82, 0x01, 0x79, 0xb9, 0x01, 0x00, 0x92, 0xe5,
- 0x61, 0x00, 0x65, 0x0b, 0x6f, 0x0f, 0x72, 0x15, 0x75, 0x1b, 0xe2, 0x67,
- 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x06, 0x65, 0x00, 0x40, 0x08, 0x64,
- 0x00, 0x40, 0x00, 0x72, 0x6e, 0x65, 0x00, 0x40, 0x47, 0x75, 0x73, 0x68,
- 0x00, 0x40, 0x09, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x1a, 0xe1, 0x66, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x08, 0x77, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x04, 0x40, 0x08, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x70, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x69, 0x05,
- 0x6c, 0x0b, 0x6f, 0x10, 0x72, 0x15, 0x40, 0x06, 0x72, 0x65, 0x00, 0x40,
- 0x06, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x77, 0x00, 0x40, 0x06,
- 0x69, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40,
- 0x00, 0x75, 0x6e, 0x73, 0x00, 0x40, 0x06, 0x65, 0x61, 0x64, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69,
- 0x1c, 0x6f, 0x31, 0xe2, 0x73, 0x00, 0x74, 0x10, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x74, 0x65, 0x72, 0x73, 0x00, 0xe2, 0x66, 0x00, 0x6e, 0x04,
- 0x40, 0x93, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x94, 0x00, 0x07, 0x40, 0x06, 0x63, 0x6b, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x0b, 0xe2, 0x69, 0x00, 0x6e, 0x04, 0x40, 0x95, 0x6c, 0x00, 0x00,
- 0x07, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x0e, 0xe1, 0x61,
- 0x00, 0xe2, 0x6e, 0x00, 0x79, 0x04, 0x40, 0x09, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x06, 0x72, 0x74, 0x00, 0xe4, 0x68, 0x00, 0x69, 0x0d, 0x70, 0x20,
- 0x74, 0x2f, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x70, 0x00, 0x40,
- 0x08, 0x77, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x05, 0x40, 0x07, 0x63, 0x65, 0x00, 0x40, 0x00, 0x65, 0x64,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6b, 0x00, 0x70, 0x04,
- 0x40, 0x09, 0x65, 0x00, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe2, 0x67, 0x00,
- 0x6d, 0x05, 0x40, 0x00, 0x68, 0x74, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x0c, 0xe2, 0x76, 0x00, 0x79, 0x05, 0x40, 0x07, 0x65,
- 0x73, 0x00, 0x00, 0x09, 0xe2, 0x6d, 0x00, 0x72, 0x0d, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x5d, 0x00, 0x96, 0x40, 0x09, 0x6c, 0x65,
- 0x00, 0x40, 0x09, 0x63, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00,
- 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x05, 0x40, 0x00, 0x62, 0x6f, 0x00, 0x00,
- 0x00, 0xc0, 0x61, 0x17, 0x31, 0x00, 0x68, 0x00, 0xba, 0x00, 0xfd, 0x00,
- 0x2c, 0x01, 0x70, 0x01, 0x82, 0x01, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00,
- 0x72, 0x02, 0xae, 0x02, 0x80, 0x04, 0x00, 0x00, 0xb8, 0x04, 0x01, 0x05,
- 0x00, 0x00, 0x71, 0x05, 0x82, 0x05, 0x86, 0x05, 0x53, 0x06, 0x8a, 0x06,
- 0x92, 0x06, 0xe4, 0x62, 0x00, 0x63, 0x08, 0x72, 0x15, 0x73, 0x2c, 0x40,
- 0x07, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x6b, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x59, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40,
- 0x3b, 0x67, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x14, 0x69, 0x19, 0x75, 0x28, 0x00, 0x06, 0xe2, 0x63,
- 0x00, 0x74, 0x06, 0x40, 0x06, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x09, 0x72,
- 0x6f, 0x73, 0x73, 0x00, 0x40, 0x00, 0x69, 0x74, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x00, 0x09,
- 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x97,
- 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x12,
- 0xe1, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x68, 0x00, 0x76, 0x23, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0xe2, 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x6d,
- 0x02, 0x77, 0x0f, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x68, 0x09, 0x6d, 0x10, 0x72, 0x16,
- 0x77, 0x26, 0x00, 0x98, 0x40, 0x00, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x40,
- 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x06, 0x62, 0x69, 0x63, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x99, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x72, 0x06, 0x40, 0x07, 0x6c, 0x66, 0x61, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x63, 0x6f, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0d, 0x6f, 0x2d, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x6c, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe1,
- 0x62, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe9, 0x61, 0x00,
- 0x62, 0x04, 0x65, 0x08, 0x67, 0x2f, 0x6b, 0x50, 0x6d, 0x54, 0x70, 0x70,
- 0x76, 0x78, 0x79, 0x80, 0x40, 0x59, 0x73, 0x00, 0x40, 0x59, 0x69, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x18, 0x00, 0x9a,
- 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x9b, 0x6c, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x73, 0x74, 0x00, 0xe2, 0x68, 0x00, 0x6e, 0x04, 0x40, 0x0b, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x0b, 0x00, 0x9c, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x37, 0x00, 0x09, 0x40, 0x69, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x37, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x12, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x47, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x79, 0x00, 0x40, 0x00, 0x68, 0x61,
- 0x74, 0x69, 0x63, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x2c, 0x79, 0x31, 0xe1, 0x6c,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x1f, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6e,
- 0x06, 0x7a, 0x12, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x3a, 0x65,
- 0x00, 0x40, 0x06, 0x69, 0x64, 0x00, 0x40, 0x00, 0x78, 0x79, 0x00, 0x40,
- 0x09, 0x64, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x06,
- 0x00, 0x69, 0xbb, 0x00, 0x6f, 0xef, 0x00, 0x73, 0x60, 0x01, 0x75, 0x67,
- 0x01, 0x79, 0xb7, 0x01, 0x00, 0x07, 0x40, 0x0b, 0x79, 0x00, 0xe5, 0x67,
- 0x00, 0x6c, 0x4d, 0x72, 0x59, 0x76, 0x89, 0x79, 0x9e, 0xe5, 0x61, 0x00,
- 0x65, 0x07, 0x69, 0x10, 0x6f, 0x17, 0x72, 0x35, 0x40, 0x09, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x0b, 0x00, 0x3b,
- 0x40, 0x09, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00,
- 0x06, 0xe2, 0x65, 0x00, 0x6f, 0x06, 0x40, 0x09, 0x74, 0x74, 0x6f, 0x00,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40, 0x06, 0x69,
- 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0e, 0x79, 0x24,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x63, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x74, 0x00,
- 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x77, 0x02, 0x00, 0x09, 0x40, 0x06, 0x61, 0x79, 0x00, 0xe3,
- 0x61, 0x00, 0x67, 0x06, 0x74, 0x0d, 0x40, 0x06, 0x6e, 0x63, 0x65, 0x00,
- 0x40, 0x09, 0x61, 0x74, 0x6f, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x9d, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x3b, 0x65, 0x00, 0xe5, 0x63, 0x00, 0x74, 0x1c, 0x76, 0x39, 0x77, 0x3e,
- 0x79, 0x5b, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x9e, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x74,
- 0x08, 0x00, 0x9f, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x83, 0xe2,
- 0x62, 0x00, 0x6e, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x37, 0x00, 0x00, 0x40, 0x06, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x59, 0x40, 0x37, 0x64, 0x00, 0x40, 0x07, 0x70, 0x69,
- 0x63, 0x65, 0x00, 0xe4, 0x64, 0x00, 0x72, 0x04, 0x73, 0x1b, 0x76, 0x37,
- 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0xa0, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40,
- 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x06, 0x6d, 0x00, 0x00,
- 0xa1, 0xe4, 0x61, 0x00, 0x69, 0x06, 0x6f, 0x0d, 0x73, 0x21, 0x40, 0x06,
- 0x6e, 0x61, 0x63, 0x00, 0x40, 0x00, 0x67, 0x68, 0x74, 0x79, 0x00, 0xe2,
- 0x6e, 0x00, 0x73, 0x0b, 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0x07, 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe6, 0x65, 0x00,
- 0x66, 0x02, 0x68, 0x06, 0x6e, 0x0a, 0x6f, 0x28, 0x75, 0x38, 0x00, 0x06,
- 0x40, 0x00, 0x74, 0x00, 0x40, 0x09, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0xe2, 0x68,
- 0x00, 0x69, 0x06, 0x40, 0x00, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x00, 0x64,
- 0x65, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x64, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x68, 0x07, 0x69, 0x62, 0x00, 0x06, 0x40, 0x09, 0x63,
- 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6e, 0x34,
- 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe2, 0x63, 0x00, 0x7a, 0x0b, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x3f, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x08, 0x6e,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x00, 0x61, 0x64, 0x79,
- 0x00, 0x40, 0x00, 0x67, 0x68, 0x74, 0x00, 0x40, 0x00, 0x6f, 0x00, 0xe7,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x13, 0x68, 0x5f, 0x69, 0x66, 0x6f, 0x88,
- 0x72, 0x97, 0x00, 0x08, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x69, 0x65, 0x63, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x63, 0x12, 0x65, 0x1a, 0x6e, 0x1e, 0x00,
- 0xa2, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00, 0x40,
- 0x09, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00, 0xa3, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x86, 0x65, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x00, 0x6f, 0x75, 0x67, 0x68, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x07, 0x40, 0x09, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x4d, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6f, 0x64, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x65, 0x74, 0x68, 0x65, 0x72, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x17, 0x00, 0x06,
- 0xe1, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x02, 0x75, 0x07, 0x00, 0x07,
- 0x40, 0x00, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x09, 0x75, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x08, 0x65, 0x6f, 0x6c,
- 0x61, 0x72, 0x00, 0x40, 0x00, 0x61, 0x79, 0x73, 0x00, 0xfc, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x62, 0xc7, 0x00, 0x65, 0x1d, 0x02, 0x69, 0xa3,
- 0x02, 0x6d, 0x12, 0x03, 0x6e, 0x3d, 0x03, 0x6f, 0x8b, 0x03, 0x70, 0x2c,
- 0x04, 0x74, 0xe4, 0x04, 0x75, 0xe6, 0x04, 0x79, 0x07, 0x05, 0x00, 0x17,
- 0xe6, 0x6c, 0x00, 0x6e, 0x1f, 0x72, 0x38, 0x73, 0x5e, 0x74, 0x62, 0x7a,
- 0x90, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x12, 0x79, 0x18, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07,
- 0x74, 0x74, 0x6f, 0x00, 0x40, 0x09, 0x6c, 0x6c, 0x69, 0x73, 0x00, 0x40,
- 0x0b, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x24, 0xe1, 0x75, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00,
- 0xe2, 0x68, 0x00, 0x6d, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0x40, 0x00, 0x72, 0x79,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0d, 0x6f, 0x12, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0xa4, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x61, 0x6e, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x65, 0x2e, 0x00,
- 0x69, 0x3e, 0x00, 0x6c, 0xc2, 0x00, 0x72, 0xce, 0x00, 0x75, 0xe3, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x6f, 0x00, 0x72, 0x17, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x73, 0x07, 0x00, 0x06, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x09,
- 0x68, 0x69, 0x70, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x07, 0x40, 0x07, 0x72, 0x69,
- 0x73, 0x00, 0xe6, 0x61, 0x00, 0x64, 0x06, 0x65, 0x21, 0x67, 0x2d, 0x74,
- 0x3f, 0x76, 0x60, 0x40, 0x09, 0x6e, 0x63, 0x65, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x78, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x07, 0x40,
- 0x07, 0x72, 0x69, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xe1, 0x75, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x74, 0x79,
- 0x00, 0x40, 0x36, 0x75, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x09, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x3b, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5,
- 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2,
- 0x6c, 0x00, 0x73, 0x4e, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x33,
- 0xe2, 0x63, 0x00, 0x74, 0x2c, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6d,
- 0x02, 0x77, 0x0f, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x8c,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe2, 0x63,
- 0x00, 0x68, 0x06, 0x40, 0x82, 0x61, 0x64, 0x65, 0x00, 0x00, 0x59, 0xe4,
- 0x6c, 0x00, 0x6e, 0x1b, 0x72, 0x4b, 0x74, 0x76, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0xa6, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x64, 0x15, 0x69, 0x22, 0x00, 0x22, 0xe1, 0x62,
- 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0xa7,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe2,
- 0x63, 0x00, 0x69, 0x10, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x35, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x75, 0x6d, 0x00, 0x40, 0x06, 0x68, 0x79, 0x73, 0x74,
- 0x00, 0xe7, 0x61, 0x00, 0x63, 0x18, 0x64, 0x33, 0x67, 0x4b, 0x6e, 0x4f,
- 0x73, 0x58, 0x74, 0x5c, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07,
- 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x73, 0x04, 0x00, 0x00, 0x00, 0x09, 0xe2, 0x68, 0x00, 0x74, 0x06, 0x40,
- 0x00, 0x69, 0x70, 0x73, 0x00, 0x00, 0x00, 0x40, 0x09, 0x6f, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x07, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x06, 0x75, 0x1b, 0x40,
- 0x06, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x6d, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x1c, 0xe1, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x10,
- 0xe2, 0x61, 0x00, 0x63, 0x09, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07,
- 0x00, 0x09, 0x00, 0x06, 0x40, 0xa1, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe3,
- 0x63, 0x00, 0x6e, 0x1c, 0x74, 0x1e, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x00, 0x09,
- 0x40, 0x00, 0x69, 0x63, 0x00, 0xe6, 0x65, 0x00, 0x6b, 0x15, 0x6e, 0x17,
- 0x72, 0x27, 0x75, 0x7f, 0x78, 0x8a, 0xe1, 0x62, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x00, 0x00, 0x40,
- 0x00, 0x63, 0x00, 0x00, 0x00, 0xe2, 0x67, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x40, 0x06, 0x69, 0x6c, 0x6c, 0x61, 0x64, 0x6f, 0x00, 0xe4, 0x61, 0x00,
- 0x6f, 0x0f, 0x70, 0x22, 0x74, 0x3b, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0xa8, 0xe2, 0x6e, 0x00, 0x72, 0x04, 0x40, 0x59, 0x74, 0x00, 0x00, 0x09,
- 0x40, 0x00, 0x69, 0x63, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x00, 0xe6, 0x00,
- 0x00, 0x65, 0x02, 0x68, 0x19, 0x69, 0x57, 0x6c, 0x60, 0x75, 0x8a, 0x00,
- 0x56, 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x73, 0x07, 0x40,
- 0x07, 0x67, 0x65, 0x00, 0x00, 0x09, 0x40, 0x09, 0x61, 0x6e, 0x64, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x28, 0x40, 0x06, 0x74, 0x61, 0x6d,
- 0x69, 0x6e, 0x65, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x11, 0xe1, 0x69, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x3b, 0x75,
- 0x73, 0x00, 0x40, 0x06, 0x68, 0x65, 0x61, 0x74, 0x65, 0x72, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0x40, 0x00, 0x63, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x60, 0xe2, 0x66, 0x00, 0x74, 0x18, 0xe2,
- 0x69, 0x00, 0x79, 0x11, 0xe2, 0x63, 0x00, 0x65, 0x08, 0x40, 0x07, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x00, 0xa9, 0x40,
- 0x06, 0x75, 0x64, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x04, 0x40, 0x09,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x39, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x05, 0x40, 0x09, 0x65,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x34, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x6e, 0x67,
- 0x00, 0xe2, 0x67, 0x00, 0x6c, 0x07, 0x40, 0x00, 0x64, 0x61, 0x6c, 0x61,
- 0x00, 0x40, 0x07, 0x61, 0x73, 0x65, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00,
- 0x39, 0x00, 0x00, 0x00, 0xdd, 0x01, 0x7d, 0x02, 0xc2, 0x02, 0x00, 0x00,
- 0x64, 0x03, 0x55, 0x04, 0x5e, 0x04, 0x00, 0x00, 0x0a, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0x2c, 0x05, 0x36, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xc4, 0x06, 0xe9, 0x06, 0x88, 0x0c, 0x8c, 0x0c, 0x00, 0x00, 0x91, 0x0c,
- 0xb1, 0x0c, 0x00, 0xaa, 0xf8, 0x62, 0x00, 0x00, 0x63, 0x08, 0x00, 0x65,
- 0x3c, 0x00, 0x67, 0x5c, 0x00, 0x6c, 0x62, 0x00, 0x70, 0x07, 0x01, 0x72,
- 0x1b, 0x01, 0x74, 0x4c, 0x01, 0x40, 0x07, 0x6f, 0x6c, 0x69, 0x73, 0x6d,
- 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x29, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x06, 0x6e, 0x64, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x62, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x40, 0x09, 0x72, 0x61, 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02,
- 0x6f, 0x14, 0x79, 0x4b, 0x00, 0x3b, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0xe1, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x10, 0x75, 0x23,
- 0x79, 0x27, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x7a, 0x05, 0x40, 0x3b, 0x61,
- 0x6c, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0x00, 0x06, 0xe3, 0x73, 0x00, 0x74, 0x21,
- 0x7a, 0x36, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x12, 0x74, 0x16, 0x40,
- 0x09, 0x6e, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x73, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x77, 0x40, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06,
- 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x06, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xab, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x63, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x24, 0xe2,
- 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x07, 0xe2, 0x68, 0x00, 0x6f, 0x16, 0xe1, 0x65, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40, 0x3a,
- 0x69, 0x7a, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1a,
- 0xe3, 0x63, 0x00, 0x73, 0x0b, 0x7a, 0x0f, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x40, 0x3a,
- 0x65, 0x00, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x68, 0x21, 0x69, 0x7a, 0xe1,
- 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x79, 0x09, 0x40, 0x3b, 0x6c,
- 0x00, 0x40, 0x09, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe2,
- 0x72, 0x00, 0x76, 0x4d, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x6d,
- 0x0c, 0x70, 0x19, 0x77, 0x2d, 0x00, 0x55, 0x40, 0x09, 0x67, 0x65, 0x00,
- 0x40, 0x09, 0x74, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6f, 0x00,
- 0x72, 0x06, 0x40, 0x00, 0x70, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x73, 0x6f,
- 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x13, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xac, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x6c, 0x61, 0x72, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x08, 0x72, 0x0e, 0x00, 0x00, 0x40, 0x06, 0x6e, 0x74, 0x65,
- 0x00, 0x40, 0x06, 0x72, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x67,
- 0x00, 0x69, 0x22, 0xe2, 0x65, 0x00, 0x79, 0x0e, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x05, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x06, 0x64, 0x00, 0xe6, 0x63, 0x00, 0x6d, 0x14, 0x6e, 0x3d,
- 0x73, 0x41, 0x75, 0x8c, 0x77, 0x93, 0xe1, 0x64, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x3b, 0x6c, 0x00,
- 0x00, 0x09, 0xe2, 0x69, 0x00, 0x6f, 0x14, 0xe2, 0x61, 0x00, 0x63, 0x02,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x07, 0x40, 0x06, 0x65, 0x74,
- 0x65, 0x72, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74,
- 0x1f, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x07, 0xe1,
- 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe3,
- 0x63, 0x00, 0x73, 0x02, 0x7a, 0x06, 0x00, 0x06, 0x40, 0x09, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x0b, 0x40, 0x06, 0x72, 0x79, 0x73, 0x6d, 0x00, 0x00, 0x00, 0xe7,
- 0x65, 0x00, 0x69, 0x29, 0x6c, 0x46, 0x6f, 0x93, 0x72, 0xa3, 0x73, 0xaf,
- 0x75, 0xbe, 0xe2, 0x6c, 0x00, 0x72, 0x22, 0xe3, 0x00, 0x00, 0x66, 0x02,
- 0x69, 0x08, 0x00, 0x09, 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x07, 0x00, 0x3b, 0x00, 0x59, 0xe2, 0x6e, 0x00, 0x6f, 0x04,
- 0x40, 0x07, 0x61, 0x00, 0xe2, 0x70, 0x00, 0x73, 0x08, 0x40, 0x06, 0x6c,
- 0x61, 0x73, 0x74, 0x79, 0x00, 0x40, 0x06, 0x70, 0x65, 0x72, 0x6d, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x16, 0x6f, 0x2f, 0x40, 0x00, 0x69,
- 0x73, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x77, 0x04, 0x00, 0xa5, 0x00,
- 0x07, 0x40, 0x09, 0x6f, 0x72, 0x6d, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x10,
- 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x08, 0x6d, 0x00,
- 0x40, 0x0b, 0x65, 0x00, 0x40, 0x07, 0x67, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x08, 0x6c, 0x65, 0x00,
- 0x40, 0x08, 0x6e, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x04, 0x40, 0x09,
- 0x61, 0x00, 0x40, 0x00, 0x74, 0x75, 0x72, 0x61, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x60, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6f, 0x6d, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x05, 0x40, 0x59, 0x73, 0x68, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x72, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x00, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x79, 0x64, 0x72, 0x6f, 0x75, 0x73, 0x00, 0xe4, 0x6c, 0x00,
- 0x6d, 0x06, 0x6f, 0x80, 0x73, 0x8e, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x4d, 0x69, 0x4f, 0x6f, 0x64, 0x75, 0x6b, 0xe3,
- 0x64, 0x00, 0x6c, 0x16, 0x74, 0x23, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x06, 0x40, 0x09, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0xad, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x75, 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x18,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x9e, 0x00, 0x3b, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x63, 0x00, 0x40, 0x06, 0x73, 0x69, 0x74, 0x79, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x74, 0x06, 0x00, 0x07, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x74, 0x65,
- 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x74,
- 0x08, 0x00, 0x09, 0x40, 0x09, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x09, 0xe5,
- 0x61, 0x00, 0x65, 0x0f, 0x69, 0x2d, 0x6f, 0x59, 0x75, 0xaa, 0xe1, 0x6c,
- 0x00, 0xe2, 0x69, 0x00, 0x73, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00,
- 0x07, 0xe3, 0x61, 0x00, 0x6c, 0x04, 0x78, 0x09, 0x40, 0x0b, 0x6c, 0x00,
- 0x40, 0x09, 0x69, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x59,
- 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x68, 0x00, 0x76, 0x1e,
- 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x65, 0x72, 0x73, 0x61,
- 0x72, 0x79, 0x00, 0xe3, 0x74, 0x00, 0x75, 0x18, 0x79, 0x36, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0x9d, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02,
- 0x6d, 0x04, 0x72, 0x0a, 0x00, 0xae, 0x00, 0x37, 0x40, 0x09, 0x65, 0x6e,
- 0x74, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x00,
- 0x0b, 0x40, 0x09, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0xe4, 0x61, 0x00, 0x69, 0x10, 0x6c, 0x1f, 0x6e, 0x42, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0x40, 0x00, 0x7a, 0x65, 0x64,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x05, 0x40, 0x06, 0x6e,
- 0x74, 0x00, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x06, 0x6d,
- 0x14, 0x00, 0x9f, 0x40, 0x00, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x06, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe7, 0x64, 0x00, 0x69, 0x13, 0x6d, 0x26, 0x6e, 0x38, 0x70, 0x51,
- 0x72, 0x59, 0x74, 0x79, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x07, 0x00,
- 0x09, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0x40, 0x09, 0x6e, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0xaf,
- 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x6f, 0x00, 0x79, 0x05, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x00, 0x06,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x08, 0xe1, 0x6d, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x68, 0x65, 0x6c, 0x65, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x09, 0x6b, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x06, 0x40,
- 0x06, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63,
- 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x00, 0x68, 0x65, 0x72, 0x00, 0xe1,
- 0x77, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x08, 0x70, 0x0c, 0x00, 0xb0, 0x40, 0x37, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x08, 0x68, 0x6f, 0x6e, 0x65, 0x00,
- 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x45, 0x00, 0x68, 0xcd,
- 0x00, 0x69, 0x7c, 0x01, 0x6c, 0x60, 0x05, 0x6f, 0x65, 0x05, 0x72, 0x7a,
- 0x05, 0x73, 0x7f, 0x05, 0x00, 0xb1, 0xe3, 0x63, 0x00, 0x67, 0x05, 0x72,
- 0x35, 0x40, 0x06, 0x69, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x1e, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x40, 0x00, 0x63, 0x74, 0x69, 0x63,
- 0x00, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x62, 0x08, 0x63, 0x10, 0x64, 0x31,
- 0x69, 0x44, 0x6c, 0x49, 0x6e, 0x4f, 0x72, 0x66, 0x00, 0x06, 0x40, 0x09,
- 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x65, 0x6c, 0x6c, 0x75, 0x6d, 0x00,
- 0xe2, 0x65, 0x00, 0x68, 0x14, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x06, 0x40, 0x06, 0x61, 0x6d, 0x62, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x05, 0x40, 0x0b, 0x74, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x75, 0x76,
- 0x69, 0x61, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f,
- 0x70, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x06, 0x40, 0x00, 0x74, 0x61,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06,
- 0x00, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6f, 0x72, 0x00,
- 0x40, 0x09, 0x6f, 0x6d, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e,
- 0x72, 0x2b, 0xe2, 0x6d, 0x00, 0x72, 0x02, 0x00, 0x09, 0x00, 0x09, 0x40,
- 0x06, 0x6c, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0d, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40,
- 0x06, 0x74, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00,
- 0x6f, 0x0d, 0xe2, 0x63, 0x00, 0x78, 0x06, 0x40, 0x07, 0x69, 0x74, 0x65,
- 0x00, 0x00, 0x07, 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe4, 0x63, 0x00,
- 0x69, 0x09, 0x6c, 0x0d, 0x6d, 0x28, 0x40, 0x00, 0x65, 0x6e, 0x74, 0x72,
- 0x69, 0x63, 0x00, 0x40, 0x09, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40,
- 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x6f,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x1c, 0xe3, 0x63, 0x00, 0x73, 0x0d, 0x7a, 0x11, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x07, 0x6d, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0xc1, 0x61, 0x17, 0x33, 0x00, 0x35, 0x00, 0x61, 0x00, 0x7e, 0x00, 0x45,
- 0x01, 0x00, 0x00, 0x68, 0x01, 0x7c, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0xb8, 0x01, 0xbf, 0x01, 0xd4, 0x01, 0x12, 0x02, 0x1b, 0x02, 0x24,
- 0x02, 0xae, 0x02, 0xe1, 0x02, 0xea, 0x02, 0x66, 0x03, 0x00, 0x00, 0xa6,
- 0x03, 0xdf, 0x03, 0x00, 0x06, 0xe2, 0x62, 0x00, 0x69, 0x1e, 0xe1, 0x6f,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0x40, 0x00, 0x72, 0x63, 0x72, 0x61, 0x66, 0x74,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x0a, 0x6f, 0x11, 0x40, 0x09, 0x63, 0x74,
- 0x65, 0x72, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x6f, 0x74, 0x69, 0x63,
- 0x00, 0x40, 0x06, 0x64, 0x79, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x09, 0x6b, 0x2c, 0x6c, 0x3a, 0x6f, 0x7b, 0x79, 0xa1, 0x00, 0x09, 0x40,
- 0x00, 0x6e, 0x63, 0x65, 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x51, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x08,
- 0x6f, 0x31, 0x40, 0x00, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x00, 0xe2, 0x6d,
- 0x00, 0x6e, 0x20, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x16, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x09, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x00, 0x63, 0x6b, 0x77, 0x69, 0x73, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x6d, 0x09, 0x40, 0x09, 0x67, 0x75, 0x6c, 0x61, 0x6e,
- 0x74, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x19, 0xe2, 0x6d, 0x00, 0x70, 0x0a, 0x40,
- 0x00, 0x6f, 0x63, 0x72, 0x61, 0x74, 0x69, 0x63, 0x00, 0x40, 0x09, 0x72,
- 0x65, 0x73, 0x73, 0x61, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x74, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x72, 0x08, 0x40, 0x09, 0x73, 0x63, 0x69, 0x73, 0x74,
- 0x00, 0x40, 0x07, 0x65, 0x65, 0x7a, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06,
- 0x73, 0x74, 0x61, 0x6d, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x6f,
- 0x63, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40, 0x00, 0x62, 0x6f,
- 0x72, 0x00, 0x40, 0x06, 0x67, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x00,
- 0xe3, 0x61, 0x00, 0x69, 0x1d, 0x6f, 0x32, 0xe3, 0x63, 0x00, 0x6c, 0x08,
- 0x74, 0x10, 0x40, 0x09, 0x61, 0x73, 0x73, 0x61, 0x72, 0x00, 0x40, 0x00,
- 0x61, 0x72, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00,
- 0xe2, 0x63, 0x00, 0x73, 0x09, 0x40, 0x00, 0x72, 0x6f, 0x62, 0x69, 0x61,
- 0x6c, 0x00, 0x40, 0x00, 0x73, 0x69, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x79, 0x00, 0x40, 0x00, 0x75, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x00, 0x40,
- 0x09, 0x78, 0x69, 0x64, 0x61, 0x6e, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x2b, 0x68, 0x45, 0x6f, 0x56, 0xe3, 0x72, 0x00, 0x73, 0x08, 0x74, 0x14,
- 0x40, 0x06, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x00, 0x09, 0xe1, 0x68, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x06, 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0x00, 0x06,
- 0xe1, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x70, 0x07, 0x40,
- 0x00, 0x6e, 0x6e, 0x65, 0x6c, 0x00, 0x40, 0x06, 0x69, 0x72, 0x61, 0x6e,
- 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0x40, 0x86, 0x6c, 0x00, 0xe3, 0x64, 0x00, 0x6c, 0x14,
- 0x76, 0x1d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x08, 0x6c, 0x00, 0xe2,
- 0x61, 0x00, 0x73, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x00,
- 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x72, 0x74,
- 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x22, 0x69, 0x24,
- 0xe2, 0x72, 0x00, 0x74, 0x19, 0xe2, 0x69, 0x00, 0x79, 0x12, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x73, 0x6d, 0x00, 0x00, 0x06, 0x40, 0x0b, 0x65, 0x00, 0x00, 0x5e,
- 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x08, 0x72, 0x68, 0x69, 0x6e, 0x75,
- 0x6d, 0x00, 0xe6, 0x63, 0x00, 0x65, 0x08, 0x6c, 0x4c, 0x6f, 0x54, 0x70,
- 0x5b, 0x75, 0x65, 0x40, 0x00, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x00, 0xe4,
- 0x6d, 0x00, 0x6e, 0x14, 0x70, 0x19, 0x72, 0x36, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0x40, 0x00, 0x73, 0x65, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x05, 0x40, 0x07, 0x69, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x40, 0x09, 0x75, 0x6d, 0x00, 0x40, 0x00, 0x61, 0x76, 0x65,
- 0x72, 0x79, 0x00, 0x40, 0x3b, 0x63, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x09,
- 0x61, 0x73, 0x6d, 0x6f, 0x64, 0x69, 0x63, 0x00, 0x40, 0x00, 0x62, 0x6d,
- 0x61, 0x72, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x68, 0x05, 0x6f,
- 0x2b, 0x72, 0x31, 0x40, 0x00, 0x6e, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x73, 0x00, 0x74, 0x0d, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x09,
- 0x78, 0x69, 0x6e, 0x00, 0x40, 0x00, 0x75, 0x73, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x10, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40,
- 0x09, 0x6e, 0x00, 0x40, 0x00, 0x6d, 0x00, 0xe2, 0x72, 0x00, 0x76, 0x11,
- 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40, 0x09, 0x6c, 0x00, 0x60, 0x09, 0x73,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0x40, 0x09, 0x69, 0x73, 0x65, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x69, 0x73, 0x74, 0x00, 0x40, 0x00, 0x61, 0x72, 0x00,
- 0x40, 0xb2, 0x65, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x79, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x00, 0x75,
- 0x73, 0x00, 0x40, 0x00, 0x75, 0x6d, 0x00, 0x40, 0x60, 0x79, 0x00, 0x40,
- 0x09, 0x73, 0x00, 0x40, 0x09, 0x69, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x68, 0x08, 0x6d,
- 0x0d, 0x6f, 0x13, 0x70, 0x18, 0x74, 0x1f, 0x77, 0x2f, 0x00, 0x00, 0x40,
- 0x06, 0x6f, 0x64, 0x79, 0x00, 0x40, 0x00, 0x6f, 0x77, 0x00, 0x40, 0x00,
- 0x6f, 0x72, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x6c,
- 0x61, 0x63, 0x65, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x06, 0x40, 0x06, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6d, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x68,
- 0x04, 0x69, 0x0a, 0x40, 0x08, 0x79, 0x00, 0x40, 0x00, 0x65, 0x72, 0x65,
- 0x00, 0x40, 0x00, 0x73, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xfa,
- 0x61, 0x00, 0x00, 0x65, 0x4a, 0x00, 0x68, 0x6e, 0x00, 0x69, 0xca, 0x00,
- 0x6c, 0xf0, 0x00, 0x6f, 0x00, 0x01, 0x70, 0x1f, 0x02, 0x72, 0x9c, 0x05,
- 0x73, 0xb3, 0x05, 0x74, 0xb7, 0x05, 0xe3, 0x63, 0x00, 0x72, 0x04, 0x74,
- 0x1c, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x68,
- 0x02, 0x6d, 0x08, 0x00, 0x00, 0x40, 0x07, 0x65, 0x69, 0x64, 0x00, 0x40,
- 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x1d, 0xe2, 0x65,
- 0x00, 0x79, 0x16, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x6c,
- 0x02, 0x72, 0x08, 0x78, 0x19, 0x00, 0x5e, 0x40, 0x00, 0x69, 0x6b, 0x65,
- 0x00, 0xe2, 0x69, 0x00, 0x74, 0x06, 0x40, 0x09, 0x74, 0x69, 0x66, 0x00,
- 0x40, 0x06, 0x75, 0x72, 0x65, 0x00, 0x00, 0x09, 0xe5, 0x61, 0x00, 0x65,
- 0x0f, 0x69, 0x20, 0x6f, 0x24, 0x72, 0x47, 0xe1, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x6c,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x40,
- 0x06, 0x6e, 0x00, 0x40, 0x09, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x6f, 0x64, 0x69, 0x73,
- 0x69, 0x61, 0x63, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x0f, 0x65, 0x14, 0x73,
- 0x19, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73,
- 0x74, 0x00, 0x00, 0x06, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x63,
- 0x65, 0x00, 0x40, 0x3b, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x06, 0x40,
- 0x00, 0x6e, 0x74, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x62, 0x00, 0xf6, 0x63,
- 0x00, 0x00, 0x67, 0x31, 0x00, 0x6c, 0x36, 0x00, 0x70, 0x76, 0x00, 0x73,
- 0xa7, 0x00, 0x74, 0xe5, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x17, 0xe1, 0x6c,
- 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe1, 0x79, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x07, 0x00, 0x3b, 0x40, 0x09, 0x65, 0x65, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x08, 0x40, 0x3b, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x00,
- 0xe1, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x16, 0x79, 0x27, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x37, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x73,
- 0x02, 0x7a, 0x06, 0x00, 0x06, 0x40, 0x09, 0x74, 0x00, 0x40, 0x0b, 0x65,
- 0x00, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x74, 0x12, 0xe1, 0x65, 0x00, 0xe2,
- 0x63, 0x00, 0x78, 0x06, 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0x40, 0x06,
- 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0d, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x6c, 0x15,
- 0x6f, 0x25, 0x72, 0x2b, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x0b, 0x7a, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40,
- 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x00, 0x6c, 0x69, 0x63, 0x00, 0x40,
- 0x09, 0x6f, 0x70, 0x68, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00,
- 0xe3, 0x63, 0x00, 0x67, 0x06, 0x6f, 0x0a, 0x40, 0x06, 0x61, 0x72, 0x79,
- 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xf7, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x65, 0x49, 0x00, 0x6c, 0xf5, 0x00, 0x6f, 0x87,
- 0x01, 0x72, 0xf7, 0x01, 0x75, 0x4a, 0x03, 0x00, 0x06, 0xe2, 0x6c, 0x00,
- 0x72, 0x17, 0xe2, 0x6c, 0x00, 0x6f, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x0b, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f, 0x73, 0x61,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x12, 0x69, 0x1d, 0xe1, 0x74, 0x00, 0xe2,
- 0x63, 0x00, 0x75, 0x06, 0x40, 0x08, 0x68, 0x69, 0x6b, 0x00, 0x40, 0x09,
- 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x55, 0x40, 0x3b, 0x74,
- 0x00, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x6c,
- 0x34, 0x6e, 0x4f, 0x72, 0x80, 0x74, 0x87, 0xe3, 0x6c, 0x00, 0x72, 0x0c,
- 0x73, 0x19, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x59, 0x40, 0x36, 0x6e,
- 0x67, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0xb3, 0x40, 0xb4, 0x6e,
- 0x63, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72,
- 0x08, 0x00, 0x80, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0xe1,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0xb5, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07,
- 0x69, 0x0f, 0x00, 0x0b, 0x40, 0x06, 0x67, 0x65, 0x00, 0x40, 0x06, 0x63,
- 0x74, 0x6f, 0x6d, 0x79, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x0f, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x74, 0x69, 0x73,
- 0x00, 0x00, 0x09, 0x40, 0x0b, 0x74, 0x61, 0x69, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x17, 0x69, 0x31, 0x79, 0x87, 0xe1, 0x75, 0x00,
- 0xe2, 0x64, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3f,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x6a,
- 0x02, 0x73, 0x08, 0x74, 0x0f, 0x00, 0x09, 0x40, 0x07, 0x61, 0x63, 0x6b,
- 0x00, 0x40, 0x07, 0x61, 0x75, 0x63, 0x65, 0x00, 0x00, 0x09, 0xe4, 0x61,
- 0x00, 0x63, 0x06, 0x65, 0x37, 0x71, 0x3b, 0x40, 0x06, 0x6e, 0x63, 0x65,
- 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x62, 0x00, 0x6e, 0x15, 0x74, 0x19, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x00, 0x40, 0x06, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x75, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x1a, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x00, 0xb6, 0xe3, 0x69, 0x00, 0x72, 0x27, 0x73, 0x40, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x00, 0xb7,
- 0x40, 0x06, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x90, 0x40, 0x77, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0xb8, 0x40, 0x75, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xb9, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x06, 0x65, 0x00, 0xf4, 0x61, 0x00, 0x00, 0x65, 0x18,
- 0x00, 0x69, 0xa1, 0x00, 0x6f, 0xa6, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x69, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0xab, 0x00, 0x09, 0xe3, 0x63, 0x00, 0x68, 0x40,
- 0x6e, 0x69, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74,
- 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00,
- 0x54, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x16, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x00, 0x9d, 0x00, 0x37, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x64, 0x00, 0x73, 0x02, 0x00, 0x0b, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x5e, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00,
- 0x40, 0x0b, 0x73, 0x65, 0x00, 0xe5, 0x61, 0x00, 0x62, 0x13, 0x70, 0x2b,
- 0x76, 0x58, 0x78, 0x79, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0xba, 0x40, 0xbb, 0x62, 0x6c, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x84, 0x00, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x11, 0x6f, 0x16, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6e,
- 0x04, 0x00, 0xbc, 0x00, 0x37, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x0c, 0x69, 0x15, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x84, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x83, 0x00, 0x37,
- 0x40, 0x7d, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0xbd, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00,
- 0x00, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x06, 0x40, 0x09, 0x63, 0x6f, 0x74,
- 0x00, 0xe2, 0x6e, 0x00, 0x70, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6f, 0x73,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x6e, 0x0d, 0x00, 0xbe, 0x40, 0x00, 0x72, 0x00, 0x40, 0x06, 0x74, 0x75,
- 0x64, 0x65, 0x00, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x75, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x61, 0x69, 0x71, 0xe9, 0x00, 0x00, 0x63, 0x02,
- 0x6c, 0x0b, 0x6d, 0x11, 0x6e, 0x19, 0x70, 0x1f, 0x72, 0x26, 0x74, 0x2c,
- 0x76, 0x49, 0x00, 0x06, 0x40, 0x07, 0x75, 0x6c, 0x74, 0x75, 0x72, 0x65,
- 0x00, 0x40, 0x09, 0x75, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x61, 0x72, 0x69,
- 0x6e, 0x65, 0x00, 0x40, 0x09, 0x61, 0x75, 0x74, 0x00, 0x40, 0x82, 0x6c,
- 0x61, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x11, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73,
- 0x08, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x40,
- 0x08, 0x74, 0x00, 0x40, 0x07, 0x69, 0x74, 0x00, 0xe2, 0x64, 0x00, 0x6f,
- 0x06, 0x40, 0x09, 0x75, 0x63, 0x74, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0xe2, 0x66, 0x00, 0x6c, 0x05, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x69, 0x6e, 0x65, 0x00, 0xc0, 0x58, 0x22, 0x47, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x4c, 0x00, 0x7c, 0x00, 0x02, 0x01, 0x7b, 0x02, 0xa1, 0x02, 0x00,
- 0x00, 0xbe, 0x02, 0x00, 0x00, 0x32, 0x03, 0x00, 0x00, 0xae, 0x03, 0x00,
- 0x00, 0xb0, 0x03, 0x00, 0x00, 0x5c, 0x04, 0xb2, 0x04, 0x00, 0x00, 0xba,
- 0x04, 0x8e, 0x05, 0xbd, 0x05, 0x33, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x40, 0x07, 0x69, 0x76, 0x00, 0xe2, 0x62, 0x00, 0x63,
- 0x13, 0xe2, 0x65, 0x00, 0x69, 0x07, 0x40, 0x09, 0x73, 0x71, 0x75, 0x65,
- 0x00, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x64, 0x00, 0x40,
- 0x00, 0x70, 0x68, 0x6f, 0x62, 0x69, 0x61, 0x00, 0xe3, 0x69, 0x00, 0x6f,
- 0x58, 0x75, 0x79, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe4, 0x67, 0x00, 0x6d, 0x12, 0x72,
- 0x18, 0x74, 0x2e, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x75,
- 0x04, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x5d, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x76, 0x10, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x74, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x75, 0x6d, 0x00, 0x40, 0x06, 0x69,
- 0x74, 0x61, 0x65, 0x00, 0x40, 0x09, 0x74, 0x75, 0x73, 0x00, 0xf4, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x68, 0x0f, 0x00, 0x74, 0x67, 0x01, 0x00,
- 0x2c, 0xe2, 0x64, 0x00, 0x6e, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x4b, 0x00,
- 0x64, 0x66, 0x00, 0x65, 0x9b, 0x00, 0x66, 0xc2, 0x00, 0x69, 0xc9, 0x00,
- 0x6e, 0x31, 0x01, 0x77, 0x37, 0x01, 0x00, 0xbf, 0xe3, 0x65, 0x00, 0x69,
- 0x21, 0x6e, 0x3c, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73,
- 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07,
- 0xe2, 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0x00, 0x09, 0x40, 0x09, 0x67, 0x65, 0x6c, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x40, 0x06, 0x69, 0x63, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x07, 0x75, 0x1e, 0x40, 0x06, 0x61, 0x63, 0x6f,
- 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x00,
- 0x09, 0xe2, 0x63, 0x00, 0x6b, 0x07, 0x40, 0x09, 0x68, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x06, 0x74, 0x0f,
- 0x40, 0x06, 0x65, 0x6d, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0xe1, 0x79, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0x40, 0x09, 0x69, 0x65,
- 0x6e, 0x64, 0x00, 0xe4, 0x65, 0x00, 0x70, 0x0b, 0x74, 0x13, 0x76, 0x4d,
- 0x40, 0x00, 0x70, 0x69, 0x73, 0x63, 0x6f, 0x70, 0x61, 0x6c, 0x00, 0x40,
- 0x09, 0x65, 0x6c, 0x61, 0x67, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x2f,
- 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x75,
- 0x14, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xe1, 0x72, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x09, 0x40,
- 0x06, 0x61, 0x76, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x06,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x5e, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x79, 0x00, 0x40, 0x09,
- 0x69, 0x63, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x05, 0x75, 0x09, 0x40, 0x3b,
- 0x6e, 0x74, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6e, 0x0b,
- 0x00, 0xc0, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe2,
- 0x27, 0x00, 0x61, 0x04, 0x40, 0x00, 0x74, 0x00, 0x00, 0x09, 0xe5, 0x00,
- 0x00, 0x65, 0x02, 0x6f, 0x07, 0x75, 0x16, 0x79, 0x64, 0x00, 0x09, 0x40,
- 0x07, 0x6e, 0x74, 0x00, 0xe3, 0x6e, 0x00, 0x73, 0x02, 0x74, 0x06, 0x00,
- 0x07, 0x40, 0x06, 0x79, 0x00, 0x00, 0x09, 0xe3, 0x61, 0x00, 0x65, 0x0f,
- 0x6d, 0x18, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x9b, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f,
- 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x09, 0x6c, 0x65, 0x00, 0xe5, 0x61, 0x00, 0x64, 0x02, 0x67,
- 0x0e, 0x73, 0x13, 0x74, 0x4d, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00, 0x68, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x74, 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3c,
- 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00,
- 0x07, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x00, 0x06,
- 0xee, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x62, 0x32, 0x63, 0x38, 0x65,
- 0x3f, 0x66, 0x43, 0x68, 0x48, 0x69, 0x4e, 0x6c, 0x56, 0x6f, 0x64, 0x70,
- 0x82, 0x72, 0x87, 0x79, 0x8d, 0x00, 0xc1, 0x40, 0x00, 0x73, 0x00, 0xe3,
- 0x64, 0x00, 0x6d, 0x0d, 0x74, 0x1f, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x06, 0x6c, 0x6c, 0x6f, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xc2, 0x00,
- 0x00, 0x40, 0x09, 0x75, 0x72, 0x65, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x64,
- 0x00, 0x40, 0x09, 0x68, 0x61, 0x69, 0x72, 0x00, 0x40, 0x37, 0x64, 0x00,
- 0x40, 0x09, 0x75, 0x6c, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x73, 0x74, 0x69, 0x63, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04,
- 0x40, 0x09, 0x74, 0x00, 0x40, 0x08, 0x61, 0x64, 0x00, 0xe1, 0x72, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0b, 0x79, 0x10, 0x00, 0xc3, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0x40, 0x00, 0x61, 0x6c,
- 0x00, 0x00, 0x06, 0x40, 0x09, 0x69, 0x74, 0x00, 0x40, 0x06, 0x65, 0x73,
- 0x74, 0x00, 0x00, 0x06, 0xe3, 0x6d, 0x00, 0x73, 0x37, 0x75, 0x3b, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x68, 0x00,
- 0x69, 0x18, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x70, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x6e,
- 0x00, 0x73, 0x04, 0x40, 0x00, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6c, 0x00, 0x00, 0x0b, 0x40, 0x09, 0x65, 0x67, 0x67, 0x69,
- 0x6f, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x4b, 0x68, 0x59, 0x69,
- 0x7a, 0x6f, 0x88, 0x00, 0x00, 0xe4, 0x69, 0x00, 0x6e, 0x13, 0x73, 0x3c,
- 0x79, 0x3e, 0xe1, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0xc4, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x67, 0x00,
- 0x74, 0x22, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x16,
- 0x00, 0xc5, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x27, 0x02, 0x00, 0x65, 0x40, 0x8f, 0x73, 0x00, 0x00, 0x06,
- 0x00, 0x00, 0x00, 0x09, 0x00, 0xc6, 0xe2, 0x61, 0x00, 0x73, 0x05, 0x40,
- 0x07, 0x72, 0x73, 0x00, 0x40, 0xc7, 0x74, 0x00, 0xe1, 0x79, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x0b, 0xe3, 0x67, 0x00, 0x77, 0x1f,
- 0x79, 0x34, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x68, 0x02, 0x72, 0x08, 0x00, 0x09, 0x40, 0x09, 0x65, 0x61, 0x64, 0x00,
- 0x40, 0x07, 0x6f, 0x6f, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x14, 0x6f, 0x19, 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x07, 0x63,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x06, 0x73, 0x74, 0x00, 0xf9, 0x00, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x66, 0x29, 0x00, 0x68, 0x3c, 0x00, 0x69, 0x75,
- 0x00, 0x6c, 0x38, 0x01, 0x73, 0x4e, 0x01, 0x77, 0x52, 0x01, 0x79, 0x58,
- 0x01, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1d, 0xe2,
- 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x6c, 0x00, 0x73,
- 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x63, 0x6c, 0x65, 0x72, 0x6f,
- 0x73, 0x69, 0x73, 0x00, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0f, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07,
- 0xe2, 0x70, 0x00, 0x73, 0x05, 0x40, 0x09, 0x6f, 0x64, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x79, 0x06, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x00, 0x00, 0xe5, 0x63,
- 0x00, 0x66, 0x3b, 0x6c, 0x68, 0x6e, 0x88, 0x73, 0x8e, 0xe3, 0x68, 0x00,
- 0x6c, 0x06, 0x75, 0x0a, 0x40, 0x06, 0x6f, 0x6b, 0x65, 0x00, 0x40, 0xb2,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x63, 0x00, 0x72,
- 0x04, 0x74, 0x06, 0x40, 0x54, 0x79, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xc8, 0x40, 0x53, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x05, 0x40, 0x06, 0x63, 0x74, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x94, 0x00, 0x07, 0xe1,
- 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x04,
- 0x40, 0x09, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x72,
- 0x14, 0x00, 0x09, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x54, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x60, 0x79, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x6b, 0x00, 0x00, 0x96, 0xe2,
- 0x67, 0x00, 0x6d, 0x06, 0x40, 0x00, 0x75, 0x6c, 0x61, 0x00, 0x00, 0x06,
- 0x40, 0x09, 0x6c, 0x00, 0xfe, 0x61, 0x00, 0x00, 0x62, 0x04, 0x00, 0x63,
- 0x0c, 0x00, 0x65, 0x8d, 0x00, 0x68, 0xbd, 0x00, 0x69, 0xf2, 0x00, 0x6b,
- 0x0d, 0x01, 0x6c, 0x25, 0x01, 0x6f, 0x34, 0x01, 0x70, 0x3b, 0x01, 0x73,
- 0xe0, 0x01, 0x74, 0x3f, 0x04, 0x75, 0xca, 0x05, 0x79, 0xd1, 0x05, 0x40,
- 0x00, 0x70, 0x00, 0x40, 0x07, 0x65, 0x73, 0x74, 0x6f, 0x73, 0x00, 0xe3,
- 0x65, 0x00, 0x6f, 0x63, 0x72, 0x67, 0xe3, 0x6e, 0x00, 0x72, 0x29, 0x74,
- 0x42, 0xe3, 0x64, 0x00, 0x73, 0x1a, 0x74, 0x20, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x4b, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x40, 0x09,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0xc9, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x00, 0x09, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x62, 0x00, 0x70, 0x04, 0x40, 0xca, 0x65,
- 0x00, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x70, 0x00, 0x78,
- 0x16, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe8, 0x00, 0x00, 0x61,
- 0x02, 0x63, 0x08, 0x6c, 0x0d, 0x6f, 0x12, 0x72, 0x17, 0x74, 0x1c, 0x79,
- 0x22, 0x00, 0xcb, 0x40, 0x36, 0x6d, 0x65, 0x64, 0x00, 0x40, 0x09, 0x61,
- 0x6e, 0x00, 0x40, 0x09, 0x61, 0x72, 0x00, 0x40, 0x00, 0x72, 0x65, 0x00,
- 0x40, 0x09, 0x61, 0x6d, 0x00, 0x40, 0x06, 0x72, 0x61, 0x79, 0x00, 0x00,
- 0x60, 0xe2, 0x64, 0x00, 0x6e, 0x04, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40,
- 0x06, 0x74, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x00,
- 0x7a, 0x40, 0x00, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x77, 0x02,
- 0x00, 0x37, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x00, 0x6e,
- 0x74, 0x00, 0x40, 0x00, 0x65, 0x70, 0x00, 0x40, 0x00, 0x63, 0x69, 0x61,
- 0x6c, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x16, 0x68, 0x33, 0x69,
- 0x61, 0x00, 0xcc, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x06, 0x40,
- 0x07, 0x67, 0x75, 0x73, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x65, 0x00, 0xe3,
- 0x63, 0x00, 0x6e, 0x04, 0x72, 0x06, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07,
- 0xe2, 0x69, 0x00, 0x73, 0x05, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x09,
- 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x05, 0x79, 0x0b, 0x40,
- 0x55, 0x6c, 0x74, 0x00, 0x40, 0x06, 0x64, 0x65, 0x6c, 0x00, 0xe1, 0x78,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x02, 0x72, 0x0a, 0x00, 0x09, 0x40,
- 0x09, 0x69, 0x73, 0x74, 0x72, 0x61, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1b,
- 0x69, 0x1d, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x8d, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0x00, 0x0b, 0x40, 0x09, 0x6e, 0x00, 0xf9,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x52, 0x00, 0x68, 0x09, 0x01,
- 0x69, 0x0f, 0x01, 0x6e, 0xb1, 0x01, 0x6f, 0xb3, 0x01, 0x74, 0x07, 0x02,
- 0x75, 0x09, 0x02, 0x00, 0x09, 0xe4, 0x69, 0x00, 0x73, 0x18, 0x75, 0x37,
- 0x79, 0x3c, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0xca,
- 0xe2, 0x62, 0x00, 0x6e, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0xcd, 0x6c,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72,
- 0x00, 0xe6, 0x6d, 0x00, 0x6e, 0x4b, 0x72, 0x4f, 0x73, 0x7a, 0x74, 0x90,
- 0x76, 0x92, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x0e, 0x79, 0x13, 0x40, 0x06, 0x67, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0xce, 0x00, 0x09, 0x40, 0x00, 0x65, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x75, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x59, 0x74, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x79, 0xe2, 0x6f, 0x00, 0x76, 0x0c,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02,
- 0x6f, 0x08, 0x00, 0x9c, 0x40, 0x65, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0xcf, 0x6f, 0x6c, 0x65, 0x00, 0xe5, 0x64,
- 0x00, 0x67, 0x20, 0x6d, 0x5d, 0x73, 0x75, 0x7a, 0x93, 0xe1, 0x75, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x27,
- 0x02, 0x61, 0x06, 0x65, 0x16, 0x6d, 0x23, 0x6f, 0x29, 0x00, 0x9c, 0x40,
- 0x00, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x65,
- 0x00, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x64, 0x00, 0x65, 0x02,
- 0x72, 0x04, 0x00, 0x37, 0x00, 0x07, 0x00, 0x09, 0x40, 0x69, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x10, 0x00, 0x59, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x06, 0x40, 0x37, 0x64, 0x00,
- 0x40, 0x09, 0x65, 0x00, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x2c, 0x72,
- 0x3d, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x00, 0x00, 0x27, 0x02,
- 0x00, 0xd0, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x84, 0x00, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x35,
- 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x6d,
- 0x05, 0x72, 0x1f, 0x40, 0x0b, 0x67, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x70,
- 0x02, 0x00, 0xd1, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x06, 0x40, 0x65, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x00, 0x4b, 0x00, 0x86, 0xf7, 0x61, 0x00, 0x00, 0x65, 0x07,
- 0x00, 0x68, 0x21, 0x00, 0x69, 0x41, 0x00, 0x6f, 0x5f, 0x00, 0x72, 0x93,
- 0x00, 0x75, 0x62, 0x01, 0x40, 0x07, 0x74, 0x69, 0x6e, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x6f, 0x09, 0x00,
- 0xd2, 0x40, 0x59, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x40, 0x09, 0x69, 0x64,
- 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x67, 0x00,
- 0x72, 0x17, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x06, 0x6d,
- 0x00, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x1d, 0xe1, 0x69, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x07,
- 0x00, 0x58, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x0b, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x19,
- 0x6f, 0x36, 0xe4, 0x64, 0x00, 0x6b, 0x06, 0x6c, 0x0c, 0x79, 0x0e, 0x40,
- 0x00, 0x64, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x65, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x56, 0xe3, 0x6c, 0x00, 0x6e,
- 0x28, 0x70, 0x6a, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x62, 0x65,
- 0x00, 0xe1, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x12, 0x40,
- 0x06, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x1f,
- 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00,
- 0x08, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x07, 0xe1, 0x6d, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x04, 0x79, 0x12, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00,
- 0x07, 0xe1, 0x68, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x73, 0x09, 0x40,
- 0x00, 0x6c, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xd3, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6e, 0x64, 0x65, 0x72, 0x00,
- 0xe3, 0x6c, 0x00, 0x6d, 0x05, 0x6e, 0x4d, 0x40, 0x06, 0x75, 0x6d, 0x00,
- 0xe2, 0x6d, 0x00, 0x70, 0x1e, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x06, 0xe1,
- 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x07, 0x40, 0x00,
- 0x61, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0x40, 0x3b, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xfc,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x2b, 0x00, 0x68, 0x38, 0x00,
- 0x69, 0xb3, 0x00, 0x6c, 0xc2, 0x00, 0x6d, 0xc7, 0x00, 0x6f, 0xf4, 0x00,
- 0x72, 0x49, 0x01, 0x74, 0xa2, 0x01, 0x77, 0x49, 0x03, 0x79, 0x51, 0x03,
- 0x00, 0x00, 0xe2, 0x76, 0x00, 0x78, 0x18, 0xe1, 0x69, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x00, 0x40, 0x06, 0x69, 0x65, 0x72, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x3e, 0x6c, 0x44, 0x77, 0x6c, 0xe2, 0x69, 0x00, 0x72, 0x15, 0xe1, 0x73,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x07, 0x69,
- 0x73, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0x40, 0x00, 0x72, 0x73, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08,
- 0x73, 0x0d, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x00,
- 0x73, 0x6d, 0x00, 0x00, 0x07, 0x40, 0x00, 0x61, 0x72, 0x74, 0x00, 0xe2,
- 0x6c, 0x00, 0x73, 0x04, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00, 0x68, 0x6f,
- 0x6f, 0x00, 0x40, 0x09, 0x61, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x00, 0x07, 0xe4, 0x6c, 0x00, 0x6d, 0x04, 0x6e, 0x29, 0x70,
- 0x4a, 0x40, 0x09, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0xe2, 0x63, 0x00, 0x7a, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x07, 0x65,
- 0x6e, 0x74, 0x00, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x22, 0xe3, 0x61,
- 0x00, 0x6f, 0x09, 0x75, 0x17, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x76, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x63, 0x75,
- 0x6c, 0x61, 0x72, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x63, 0x00, 0x70,
- 0x1f, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x68, 0x00, 0x69,
- 0x04, 0x40, 0x5e, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xf8, 0x61,
- 0x00, 0x00, 0x65, 0x69, 0x00, 0x69, 0xf5, 0x00, 0x6e, 0x20, 0x01, 0x6f,
- 0x22, 0x01, 0x72, 0x29, 0x01, 0x75, 0x87, 0x01, 0x79, 0x8c, 0x01, 0xe3,
- 0x63, 0x00, 0x69, 0x34, 0x72, 0x60, 0xe2, 0x68, 0x00, 0x6b, 0x24, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x6d, 0x0b, 0x00, 0x9c, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x00, 0xd4, 0x00, 0x37, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6e,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x64, 0x15, 0x6d, 0x1a, 0x00, 0x4b,
- 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0x40, 0x37, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0xe3, 0x6d, 0x00, 0x6e,
- 0x11, 0x73, 0x6e, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x27, 0x02, 0x00, 0xd5, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x64, 0x00, 0x74,
- 0x20, 0x75, 0x44, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x10, 0x00, 0xd6,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00,
- 0x00, 0x06, 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00, 0x37, 0x00, 0x06, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0c, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x53, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0xd7, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x09, 0x00, 0x7a, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x37, 0x64, 0x00, 0xe3, 0x63, 0x00, 0x72, 0x02, 0x74, 0x06, 0x00,
- 0x06, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0x00,
- 0x00, 0x40, 0x09, 0x72, 0x6e, 0x65, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x2d, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x07, 0x00, 0xd8, 0x40, 0x09, 0x6e, 0x74, 0x00, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x36, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x62,
- 0x00, 0x74, 0x21, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0xd9, 0x00, 0x37, 0xe2,
- 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x86, 0x65, 0x00,
- 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x3a, 0x6e, 0x65, 0x00, 0x00,
- 0x00, 0x40, 0x00, 0x69, 0x74, 0x74, 0x65, 0x72, 0x00, 0x40, 0x3b, 0x70,
- 0x69, 0x63, 0x61, 0x6c, 0x00, 0xfa, 0x62, 0x00, 0x00, 0x63, 0x12, 0x00,
- 0x64, 0x2a, 0x00, 0x67, 0xec, 0x00, 0x6b, 0x44, 0x01, 0x6e, 0x46, 0x01,
- 0x72, 0x54, 0x01, 0x73, 0x8f, 0x01, 0x74, 0xed, 0x01, 0x78, 0x28, 0x04,
- 0xe2, 0x65, 0x00, 0x75, 0x08, 0x40, 0x08, 0x72, 0x67, 0x69, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x72, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x55, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x22, 0xe1,
- 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe4, 0x62, 0x00,
- 0x65, 0x15, 0x6f, 0x1b, 0x74, 0x71, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x09, 0x00, 0x54, 0x40, 0x09, 0x6e, 0x63, 0x65, 0x00, 0xe6, 0x00, 0x00,
- 0x6c, 0x02, 0x6d, 0x1d, 0x70, 0x24, 0x74, 0x2b, 0x76, 0x31, 0x00, 0x09,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2,
- 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x65, 0x74, 0x65, 0x72, 0x00, 0x40, 0x06,
- 0x68, 0x69, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x61, 0x70, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x59, 0x40, 0x2c, 0x6f, 0x6e,
- 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x07, 0x00,
- 0x09, 0x40, 0x06, 0x75, 0x6d, 0x00, 0x00, 0x00, 0xe4, 0x65, 0x00, 0x68,
- 0x04, 0x6d, 0x08, 0x75, 0x31, 0x40, 0x09, 0x72, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x15, 0x00, 0x4c, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x09, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x63, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x06, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x09, 0x69, 0x1b, 0x6f,
- 0x2d, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x00, 0x3b, 0xe3, 0x69,
- 0x00, 0x6f, 0x02, 0x75, 0x07, 0x00, 0x00, 0x40, 0x06, 0x6c, 0x65, 0x00,
- 0x40, 0x00, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x04,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00, 0x40, 0x06,
- 0x72, 0x61, 0x00, 0xe3, 0x63, 0x00, 0x70, 0x1b, 0x74, 0x3e, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x39, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x72, 0x0f, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0xda, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x00, 0x61, 0x6c,
- 0x00, 0xf5, 0x65, 0x00, 0x00, 0x68, 0x05, 0x00, 0x69, 0xb1, 0x00, 0x6f,
- 0xc0, 0x00, 0x75, 0x1a, 0x02, 0x40, 0x09, 0x75, 0x72, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x37, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x1f, 0x00, 0x9b,
- 0xe2, 0x6c, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x45, 0x00, 0x37,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x72,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x73, 0x5e, 0x00, 0x2c,
- 0x40, 0x09, 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x74, 0x04, 0x7a, 0x3b,
- 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x30, 0xe2, 0x72, 0x00,
- 0x74, 0x15, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x4b, 0x00, 0x37, 0x40, 0x07, 0x68, 0x69,
- 0x70, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x69, 0x63, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x63, 0x39, 0x00, 0x64, 0x79, 0x00, 0x67, 0x81, 0x00, 0x69, 0x96, 0x00,
- 0x6d, 0xae, 0x00, 0x6e, 0xfd, 0x00, 0x70, 0x15, 0x01, 0x73, 0x24, 0x01,
- 0x77, 0x30, 0x01, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x06,
- 0x68, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x04, 0x79, 0x12, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x06,
- 0xe3, 0x6c, 0x00, 0x6f, 0x06, 0x72, 0x0f, 0x40, 0x09, 0x61, 0x76, 0x65,
- 0x00, 0x40, 0x00, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x20, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x00, 0x73, 0x73, 0x00, 0x40, 0x06, 0x69, 0x64, 0x61, 0x63, 0x74, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x2f, 0x00, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x39, 0xe2, 0x6b, 0x00, 0x74, 0x05, 0x40, 0x06, 0x65, 0x72, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x24, 0x00, 0x42, 0xe4, 0x63, 0x00,
- 0x6f, 0x0d, 0x73, 0x11, 0x7a, 0x15, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x07, 0x6d, 0x00, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe2,
- 0x62, 0x00, 0x74, 0x06, 0x40, 0x5e, 0x69, 0x6c, 0x65, 0x00, 0x40, 0x00,
- 0x69, 0x76, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x69,
- 0x00, 0x6f, 0x04, 0x79, 0x09, 0x40, 0x00, 0x63, 0x00, 0x40, 0x3b, 0x75,
- 0x73, 0x00, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x73, 0x06, 0x40, 0x06, 0x6c,
- 0x6f, 0x74, 0x00, 0x40, 0xa1, 0x79, 0x00, 0x40, 0x00, 0x75, 0x67, 0x67,
- 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x6b,
- 0x65, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x07, 0x40, 0x06, 0x69, 0x61,
- 0x72, 0x79, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x64, 0x55, 0x00, 0x65, 0x59, 0x00, 0x67, 0xa1, 0x00, 0x69, 0xa3, 0x00,
- 0x6f, 0x01, 0x01, 0x75, 0x6b, 0x01, 0x00, 0x89, 0xe6, 0x69, 0x00, 0x6c,
- 0x1d, 0x72, 0x25, 0x73, 0x38, 0x74, 0x3c, 0x75, 0x41, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x9a, 0xe1, 0x62, 0x00, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0xdb, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x37,
- 0x65, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40,
- 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x09, 0x61,
- 0x72, 0x00, 0x40, 0x00, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x70, 0x00, 0xe3,
- 0x00, 0x00, 0x6e, 0x02, 0x72, 0x17, 0x00, 0x00, 0xe2, 0x67, 0x00, 0x75,
- 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00,
- 0x07, 0x40, 0x09, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x72, 0x05, 0x73, 0x13,
- 0x74, 0x1f, 0x40, 0xdc, 0x67, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0xb5, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x00,
- 0x00, 0xe4, 0x61, 0x00, 0x64, 0x2c, 0x6f, 0x38, 0x74, 0x4a, 0xe3, 0x6e,
- 0x00, 0x72, 0x02, 0x74, 0x06, 0x00, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe3,
- 0x69, 0x00, 0x6f, 0x05, 0x72, 0x09, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x05, 0x40,
- 0x00, 0x65, 0x73, 0x00, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07,
- 0x40, 0x07, 0x61, 0x6d, 0x69, 0x6e, 0x6f, 0x73, 0x69, 0x73, 0x00, 0xe4,
- 0x63, 0x00, 0x69, 0x20, 0x75, 0x4b, 0x77, 0x50, 0xe1, 0x61, 0x00, 0xe2,
- 0x64, 0x00, 0x74, 0x04, 0x40, 0x06, 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x1d, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0xdd, 0xe2, 0x62, 0x00, 0x6e, 0x0c, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x37, 0x40, 0x07, 0x63,
- 0x65, 0x00, 0x40, 0x07, 0x64, 0x75, 0x70, 0x6f, 0x69, 0x73, 0x00, 0x40,
- 0x3a, 0x63, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x00,
- 0xde, 0x40, 0x90, 0x6c, 0x00, 0x40, 0x3b, 0x64, 0x00, 0x40, 0x3b, 0x6e,
- 0x63, 0x75, 0x6c, 0x61, 0x72, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x4a, 0x66, 0x77, 0x68, 0x9a, 0x6b, 0xa0, 0x6c, 0xb9, 0x6e, 0xbb, 0x6f,
- 0xc7, 0x72, 0xd6, 0x00, 0x00, 0xe5, 0x69, 0x00, 0x6b, 0x04, 0x72, 0x1a,
- 0x73, 0x37, 0x79, 0x3b, 0x40, 0x0b, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x4b, 0x40, 0x06, 0x6e, 0x67, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x0b, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x59, 0x40, 0x08, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0xdf, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x68, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07,
- 0x00, 0x5e, 0x40, 0x00, 0x67, 0x68, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13,
- 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x72, 0x75, 0x63,
- 0x6b, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6c,
- 0x02, 0x6e, 0x10, 0x00, 0x3e, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x69, 0x6c, 0x65, 0x00, 0xe1, 0x77, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0xe0, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0xe1, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6b,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x00, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x2f,
- 0x6f, 0x3f, 0x00, 0x47, 0xe3, 0x61, 0x00, 0x6f, 0x04, 0x73, 0x24, 0x40,
- 0x3b, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x72, 0x65, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x06, 0x40, 0x06,
- 0x6f, 0x74, 0x6c, 0x00, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x26, 0xe2,
- 0x68, 0x00, 0x74, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x69, 0x06, 0x75, 0x1b, 0x40, 0x06,
- 0x6c, 0x65, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x06, 0x72, 0x65, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39,
- 0x00, 0x18, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x21, 0x10, 0x35, 0x1c, 0x00,
- 0x00, 0x37, 0x1c, 0x3d, 0x1c, 0x00, 0x00, 0xc1, 0x24, 0xc3, 0x24, 0x00,
- 0x00, 0x00, 0x00, 0x12, 0x2d, 0xfd, 0x37, 0x00, 0x00, 0x06, 0x38, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x41, 0x00, 0x00, 0x00, 0x00, 0x62, 0x4a, 0x6b,
- 0x4a, 0x00, 0xe2, 0xc0, 0x61, 0x1a, 0x37, 0x00, 0x39, 0x00, 0x9f, 0x00,
- 0x01, 0x04, 0x00, 0x00, 0x74, 0x04, 0x8e, 0x04, 0xf6, 0x04, 0xff, 0x04,
- 0x00, 0x00, 0x47, 0x05, 0x78, 0x05, 0x2a, 0x07, 0x3f, 0x07, 0x17, 0x09,
- 0x1d, 0x09, 0x00, 0x00, 0x58, 0x09, 0xb0, 0x0c, 0x2c, 0x0e, 0x74, 0x0f,
- 0x00, 0x00, 0x88, 0x0f, 0x00, 0x00, 0xa9, 0x0f, 0xc5, 0x0f, 0x00, 0x2c,
- 0xe5, 0x62, 0x00, 0x65, 0x0f, 0x6f, 0x18, 0x75, 0x1d, 0x79, 0x24, 0xe1,
- 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x00, 0x09, 0x40,
- 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x73, 0x68, 0x6b, 0x61, 0x00, 0xe4,
- 0x00, 0x00, 0x68, 0x02, 0x69, 0x08, 0x73, 0x0d, 0x00, 0xe3, 0x40, 0x07,
- 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xf6, 0x63, 0x00, 0x00, 0x68, 0x3c,
- 0x00, 0x69, 0x55, 0x00, 0x6b, 0x6d, 0x00, 0x6f, 0xf7, 0x02, 0x74, 0xfb,
- 0x02, 0xe3, 0x61, 0x00, 0x68, 0x14, 0x79, 0x33, 0xe2, 0x6c, 0x00, 0x72,
- 0x0a, 0x40, 0x06, 0x61, 0x75, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x40,
- 0x07, 0x61, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x09, 0x00,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6f,
- 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x05, 0x75, 0x07, 0x40, 0x00, 0x72, 0x79, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39, 0x00, 0x3f, 0x00, 0x7f,
- 0x00, 0xa2, 0x00, 0xb8, 0x00, 0xbc, 0x00, 0xcd, 0x00, 0xf0, 0x00, 0x0f,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x3d, 0x01, 0x00, 0x00, 0x60, 0x01, 0x6f, 0x01, 0x2e, 0x02, 0x3e,
- 0x02, 0x00, 0x00, 0x42, 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0xe4, 0x40,
- 0x09, 0x63, 0x68, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x06, 0x6f, 0x20,
- 0x72, 0x2e, 0x40, 0x08, 0x6e, 0x63, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x74, 0x0b, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0xe5, 0x00, 0x07, 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x6e, 0x05, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x09, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x68, 0x00,
- 0x6c, 0x05, 0x6f, 0x17, 0x40, 0x00, 0x61, 0x74, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x3a, 0x6d, 0x62, 0x00, 0xe3, 0x61, 0x00, 0x6f,
- 0x05, 0x72, 0x0a, 0x40, 0x0b, 0x74, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x72,
- 0x00, 0x40, 0x09, 0x6f, 0x70, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x65, 0x00, 0x72, 0x05, 0x40, 0x06, 0x6c, 0x64, 0x00, 0x40,
- 0x82, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x07, 0x40, 0x07, 0x6d, 0x6d,
- 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe6, 0x40, 0x07,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x16, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x3b, 0x00, 0x07, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6f, 0x0a, 0x40, 0x09, 0x73,
- 0x68, 0x00, 0x40, 0x00, 0x73, 0x73, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x67, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x18,
- 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x7a, 0x64, 0x61, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x40, 0x08, 0x6f, 0x6d, 0x00, 0xe6, 0x63, 0x00,
- 0x65, 0x0b, 0x69, 0x10, 0x6c, 0x15, 0x70, 0x47, 0x74, 0x55, 0x40, 0x07,
- 0x72, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x61,
- 0x74, 0x00, 0x40, 0x06, 0x64, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x1a,
- 0xe2, 0x70, 0x00, 0x73, 0x11, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x68, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xe8, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x69, 0x05, 0x40, 0x5e, 0x63, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe3,
- 0x61, 0x00, 0x6f, 0x20, 0x72, 0x3e, 0xe3, 0x62, 0x00, 0x67, 0x11, 0x69,
- 0x15, 0xe1, 0x62, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x08,
- 0x72, 0x00, 0xe2, 0x70, 0x00, 0x72, 0x15, 0xe2, 0x00, 0x00, 0x70, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x0e, 0xe2, 0x65, 0x00, 0x74, 0x04, 0x40, 0x08, 0x74, 0x00, 0x40, 0x09,
- 0x63, 0x68, 0x00, 0x40, 0x82, 0x6b, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x72,
- 0x05, 0x40, 0x07, 0x6c, 0x6b, 0x00, 0x40, 0x7a, 0x61, 0x63, 0x6b, 0x00,
- 0x40, 0x09, 0x70, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x20, 0xe3, 0x72, 0x00,
- 0x73, 0x10, 0x74, 0x14, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0xe9, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x68, 0x00,
- 0x40, 0x06, 0x65, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06,
- 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x09, 0x6f, 0x1a,
- 0x75, 0x3e, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00,
- 0x6c, 0x00, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x00, 0xe8, 0x00, 0x00, 0x64,
- 0x02, 0x65, 0x16, 0x67, 0x18, 0x69, 0x24, 0x6c, 0x2b, 0x6d, 0x32, 0x6e,
- 0x5c, 0x00, 0xea, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x72, 0x00, 0x73,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x09, 0x65, 0x00, 0x00,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xeb, 0x00,
- 0xec, 0x40, 0x07, 0x6e, 0x61, 0x67, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6e,
- 0x64, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x69, 0x08, 0x6f, 0x0f,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x74,
- 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xed, 0x00, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x00, 0xee, 0x40, 0x07, 0x65,
- 0x6e, 0x74, 0x00, 0x00, 0x07, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0a,
- 0x66, 0x0e, 0x67, 0x13, 0x70, 0x40, 0x75, 0x52, 0x00, 0x06, 0x40, 0x06,
- 0x74, 0x65, 0x6c, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x09,
- 0x75, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x09, 0x79, 0x22,
- 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x00, 0x64, 0x00, 0xe3, 0x65, 0x00,
- 0x6c, 0x02, 0x6e, 0x06, 0x00, 0x07, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0xef,
- 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0xeb, 0x00, 0x07, 0x40, 0x09, 0x65, 0x74, 0x74, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x06, 0xe4, 0x6c,
- 0x00, 0x72, 0x35, 0x74, 0x39, 0x7a, 0x3b, 0xe5, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x6f, 0x15, 0x73, 0x1a, 0x00, 0xf0, 0x40, 0x08, 0x79, 0x00,
- 0xe2, 0x66, 0x00, 0x77, 0x04, 0x40, 0x08, 0x66, 0x00, 0x40, 0x09, 0x69,
- 0x63, 0x6b, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x09, 0x6e, 0x00, 0x00, 0x93, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x65,
- 0x00, 0x6c, 0x1c, 0x73, 0x22, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04,
- 0x73, 0x0d, 0x00, 0x7e, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0x40, 0x09, 0x68, 0x6f, 0x70, 0x00, 0x40, 0x07, 0x61,
- 0x76, 0x61, 0x00, 0x40, 0x07, 0x68, 0x65, 0x65, 0x73, 0x68, 0x00, 0xfb,
- 0x61, 0x00, 0x00, 0x62, 0x26, 0x00, 0x63, 0x2b, 0x00, 0x64, 0x31, 0x00,
- 0x65, 0x5c, 0x00, 0x6b, 0x80, 0x00, 0x6c, 0x89, 0x00, 0x6d, 0x4e, 0x01,
- 0x6f, 0x60, 0x01, 0x73, 0x66, 0x01, 0x75, 0x7b, 0x01, 0xe3, 0x63, 0x00,
- 0x6c, 0x07, 0x6e, 0x0e, 0x40, 0x09, 0x6c, 0x61, 0x76, 0x61, 0x00, 0x40,
- 0x09, 0x61, 0x69, 0x6b, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x06, 0x6f, 0x61, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x79, 0x00, 0xe6, 0x00,
- 0x00, 0x65, 0x02, 0x66, 0x0a, 0x6e, 0x11, 0x72, 0x17, 0x79, 0x1c, 0x00,
- 0xf2, 0x40, 0x07, 0x72, 0x64, 0x61, 0x73, 0x68, 0x00, 0x40, 0x00, 0x61,
- 0x63, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x69, 0x63, 0x00, 0x00, 0x08, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x66, 0x06,
- 0x72, 0x19, 0x00, 0x7e, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x93,
- 0x00, 0xf3, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x63, 0x1d, 0x65, 0x23, 0x67,
- 0x39, 0x69, 0x4f, 0x6f, 0x64, 0x70, 0x7a, 0x72, 0x93, 0x73, 0x99, 0x79,
- 0xa2, 0x00, 0x93, 0xe2, 0x64, 0x00, 0x73, 0x12, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x72, 0x07, 0x00, 0x06, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x95, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x63, 0x6b, 0x00,
- 0xe2, 0x72, 0x00, 0x74, 0x06, 0x40, 0x06, 0x69, 0x6e, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x05, 0x6f, 0x0a, 0x40, 0x09, 0x6d, 0x65, 0x00, 0x40, 0x08,
- 0x72, 0x6c, 0x00, 0x40, 0x08, 0x77, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x08, 0x00, 0x07, 0xe2, 0x6f, 0x00, 0x74, 0x0f, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x93, 0x40, 0x09, 0x73, 0x74,
- 0x00, 0x00, 0x2c, 0xe3, 0x61, 0x00, 0x6c, 0x05, 0x6f, 0x0c, 0x40, 0x09,
- 0x72, 0x6b, 0x00, 0x40, 0x09, 0x61, 0x79, 0x65, 0x72, 0x00, 0x40, 0x09,
- 0x69, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6d, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x3a, 0x00, 0xf3, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0x00, 0x40, 0x2c, 0x6f, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x79, 0x09, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0xf4, 0x40, 0x07, 0x6e, 0x65, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x72, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x61, 0x64, 0x65,
- 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00,
- 0x00, 0x7a, 0x02, 0x00, 0x06, 0x40, 0x3a, 0x6c, 0x65, 0x00, 0xfe, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x64, 0x17, 0x00, 0x65, 0xb4, 0x00, 0x67,
- 0xc0, 0x00, 0x69, 0xcb, 0x00, 0x6a, 0xe9, 0x00, 0x6b, 0xf8, 0x00, 0x6e,
- 0x3f, 0x01, 0x71, 0x5d, 0x01, 0x73, 0x77, 0x01, 0x74, 0x7d, 0x01, 0x79,
- 0xa3, 0x01, 0x7a, 0xa8, 0x01, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6e, 0x0c,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x79, 0x00,
- 0x40, 0x06, 0x61, 0x00, 0xec, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x62,
- 0x14, 0x65, 0x19, 0x69, 0x28, 0x6c, 0x36, 0x6d, 0x3e, 0x6f, 0x46, 0x73,
- 0x4d, 0x77, 0x65, 0x79, 0x82, 0x00, 0xf5, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x67, 0x00, 0x6e, 0x04, 0x40, 0x5e, 0x65, 0x00, 0x40, 0x09, 0x6e, 0x61,
- 0x00, 0x40, 0x09, 0x6f, 0x78, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x75, 0x00,
- 0xe2, 0x00, 0x00, 0x78, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x08, 0x65, 0x61, 0x64, 0x65, 0x72, 0x00, 0x40, 0x06, 0x61, 0x73, 0x74,
- 0x65, 0x72, 0x00, 0x40, 0x06, 0x6c, 0x65, 0x65, 0x72, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x06, 0x40, 0x06, 0x67, 0x6f, 0x6e, 0x00, 0xe1, 0x64, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xf6, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x75, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0xf7,
- 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0xe2,
- 0x68, 0x00, 0x74, 0x0d, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x35, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x73, 0x74,
- 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x65, 0x0e, 0x69, 0x12,
- 0x6e, 0x17, 0x72, 0x1d, 0x00, 0xf8, 0x40, 0x06, 0x6f, 0x6f, 0x6b, 0x00,
- 0x40, 0x06, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x74, 0x65, 0x00, 0xe2, 0x6f, 0x00,
- 0x75, 0x05, 0x40, 0x93, 0x6c, 0x6c, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x93, 0x40, 0x06, 0x79, 0x00,
- 0xe4, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e, 0x73, 0x13, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x09, 0x63, 0x6b, 0x00, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x74, 0x06, 0x00, 0xc3,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x68, 0x65,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x12, 0xe1, 0x6d, 0x00, 0xe2, 0x00,
- 0x00, 0x77, 0x02, 0x00, 0x06, 0x40, 0x06, 0x65, 0x69, 0x67, 0x68, 0x74,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x95, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x61,
- 0x69, 0x00, 0x40, 0x06, 0x62, 0x61, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x08, 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x1c, 0xe2,
- 0x6d, 0x00, 0x74, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x08, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72,
- 0x04, 0x00, 0x3f, 0x00, 0x37, 0x00, 0x07, 0xc1, 0x27, 0x53, 0xab, 0x00,
- 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00,
- 0x3b, 0x01, 0x43, 0x01, 0x4e, 0x01, 0x94, 0x01, 0x9f, 0x01, 0xc9, 0x01,
- 0xe4, 0x01, 0x00, 0x00, 0xfa, 0x01, 0x1c, 0x02, 0x21, 0x02, 0x39, 0x02,
- 0x6d, 0x02, 0x00, 0x00, 0xc8, 0x02, 0xcd, 0x02, 0x00, 0x00, 0x3a, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x03, 0x00, 0xf9,
- 0x40, 0x00, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x42, 0x69,
- 0x6a, 0x77, 0x79, 0x00, 0xfa, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x33, 0xe5, 0x61, 0x00, 0x63, 0x0f, 0x73, 0x1c, 0x74, 0x20, 0x7a, 0x24,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09,
- 0x73, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x6d, 0x00, 0x40, 0x06, 0x79, 0x00,
- 0x40, 0x3a, 0x65, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe3, 0x63, 0x00,
- 0x6c, 0x05, 0x72, 0x0e, 0x40, 0x5e, 0x75, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x06, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73,
- 0x06, 0x00, 0xec, 0x40, 0x06, 0x79, 0x00, 0x40, 0x09, 0x68, 0x6f, 0x70,
- 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x08, 0x40, 0x06, 0x75, 0x72,
- 0x61, 0x74, 0x65, 0x00, 0x40, 0x07, 0x69, 0x72, 0x65, 0x00, 0x40, 0x06,
- 0x61, 0x72, 0x6f, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x63, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x66, 0x08,
- 0x68, 0x18, 0x6c, 0x2b, 0x6e, 0x33, 0x00, 0xfb, 0x40, 0xfc, 0x61, 0x63,
- 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40, 0x3b, 0x63, 0x65, 0x64,
- 0x00, 0x40, 0xfc, 0x6f, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x00, 0x6e, 0x64, 0x65, 0x64, 0x00, 0x40, 0x00, 0x61, 0x64, 0x65, 0x64,
- 0x00, 0x40, 0x00, 0x65, 0x67, 0x67, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0xfd, 0x40, 0x06,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x82, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3,
- 0x73, 0x00, 0x74, 0x05, 0x75, 0x0b, 0x40, 0x09, 0x74, 0x61, 0x00, 0x40,
- 0x09, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe3, 0x00, 0x00,
- 0x27, 0x02, 0x65, 0x06, 0x00, 0xff, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x72, 0x0e, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0x00, 0x06, 0x40, 0x07, 0x65, 0x79, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x0b, 0x79, 0x0f, 0xe2, 0x69, 0x00, 0x6e, 0x04,
- 0x40, 0x09, 0x64, 0x00, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00, 0x00, 0xf3,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x73, 0x0c, 0x79, 0x23, 0x00,
- 0x06, 0x40, 0xb2, 0x63, 0x6c, 0x65, 0x00, 0x40, 0x08, 0x79, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xd6, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06,
- 0x61, 0x72, 0x64, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x22, 0x71, 0x4f, 0xe1,
- 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x09,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x07, 0x69, 0x1b, 0x79, 0x20, 0x00, 0x09, 0x40, 0x09,
- 0x67, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x09, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x09, 0x40, 0x06, 0x79, 0x00, 0x40,
- 0x00, 0x61, 0x6c, 0x00, 0x00, 0x06, 0x40, 0x07, 0x75, 0x65, 0x00, 0x40,
- 0x06, 0x75, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x15, 0x69, 0x38, 0x6f,
- 0x59, 0xe2, 0x63, 0x00, 0x67, 0x0c, 0xe2, 0x6b, 0x00, 0x75, 0x02, 0x00,
- 0x55, 0x40, 0x06, 0x64, 0x61, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe5, 0x00,
- 0x00, 0x64, 0x02, 0x6c, 0x04, 0x6e, 0x06, 0x74, 0x13, 0x01, 0x01, 0x01,
- 0x02, 0x00, 0x95, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x03, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x74, 0x65, 0x00, 0xe5, 0x63, 0x00,
- 0x65, 0x06, 0x6e, 0x0a, 0x6f, 0x0e, 0x73, 0x10, 0x40, 0x82, 0x61, 0x64,
- 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0x41, 0x04, 0x67, 0x00, 0x00, 0x06,
- 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x77, 0x04, 0x40,
- 0x09, 0x6d, 0x00, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72,
- 0x06, 0x40, 0x06, 0x64, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x01, 0x05, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xf8,
- 0x61, 0x00, 0x00, 0x65, 0x15, 0x00, 0x68, 0x6a, 0x00, 0x69, 0x8b, 0x00,
- 0x6b, 0xc3, 0x00, 0x71, 0xe8, 0x00, 0x73, 0xed, 0x00, 0x74, 0x28, 0x01,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x3b, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0xe7, 0x00, 0x00,
- 0x27, 0x02, 0x62, 0x06, 0x6c, 0x16, 0x6d, 0x29, 0x6e, 0x3e, 0x72, 0x44,
- 0x01, 0x06, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40,
- 0x06, 0x6c, 0x6c, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x05, 0x79, 0x0a, 0x40, 0x00, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x6e, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x01, 0x07, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x66, 0x02, 0x69, 0x15, 0x00, 0x59, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe4, 0x63, 0x00, 0x6c, 0x0d,
- 0x6e, 0x21, 0x73, 0x2d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40, 0x09, 0x61, 0x00, 0x40, 0x09, 0x6b,
- 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x09, 0x40, 0x09, 0x75, 0x6c,
- 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x5b, 0xe1, 0x74,
- 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x72, 0x08, 0x77, 0x0c, 0x00, 0x06,
- 0x40, 0x09, 0x61, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07,
- 0x6f, 0x72, 0x6b, 0x00, 0x40, 0x08, 0x75, 0x65, 0x00, 0xe5, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6f, 0x14, 0x77, 0x2a, 0x00, 0x09, 0x40, 0x06,
- 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x05, 0x40, 0x09, 0x65, 0x74, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x73,
- 0x74, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x24, 0x69, 0x2d, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe1, 0x64,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x13, 0x00, 0x09, 0xe1, 0x7a,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x0b, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x08,
- 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x65, 0x06, 0x00, 0x68, 0x08, 0x00, 0x69, 0x7a, 0x00, 0x6d,
- 0x86, 0x00, 0x6f, 0x93, 0x00, 0x73, 0x97, 0x00, 0x74, 0xa7, 0x00, 0x00,
- 0x06, 0x40, 0x47, 0x68, 0x00, 0x01, 0x09, 0xeb, 0x00, 0x00, 0x65, 0x02,
- 0x68, 0x12, 0x69, 0x19, 0x6d, 0x1e, 0x6f, 0x23, 0x72, 0x27, 0x73, 0x37,
- 0x74, 0x39, 0x77, 0x3e, 0x79, 0x45, 0x00, 0xc3, 0xe3, 0x00, 0x00, 0x72,
- 0x02, 0x74, 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x00, 0x69, 0x63, 0x00,
- 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x61, 0x74, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x6f, 0x00,
- 0xe2, 0x62, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x6d,
- 0x00, 0x00, 0x00, 0x40, 0x09, 0x75, 0x62, 0x00, 0x40, 0x00, 0x61, 0x74,
- 0x65, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x70, 0x07, 0x40,
- 0x06, 0x61, 0x70, 0x68, 0x65, 0x00, 0x40, 0x09, 0x68, 0x65, 0x72, 0x65,
- 0x00, 0xe2, 0x6b, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x07, 0x74, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe5, 0x61,
- 0x00, 0x65, 0x07, 0x69, 0x21, 0x6c, 0x26, 0x79, 0x78, 0x40, 0x06, 0x6c,
- 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x64, 0x00, 0x6e, 0x02, 0x72, 0x04, 0x00,
- 0x00, 0x00, 0x95, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x06, 0x01, 0x0a,
- 0x40, 0x07, 0x72, 0x00, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1,
- 0x65, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x64, 0x07, 0x66, 0x17, 0x67,
- 0x28, 0x6d, 0x30, 0x72, 0x36, 0x73, 0x38, 0x01, 0x0b, 0x40, 0x09, 0x78,
- 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x05, 0x40, 0x06, 0x72, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x06, 0x40,
- 0x09, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x74, 0x00, 0x40,
- 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x68, 0x69, 0x70, 0x00, 0x00, 0xf3, 0xe3,
- 0x62, 0x00, 0x64, 0x05, 0x78, 0x07, 0x40, 0x06, 0x6c, 0x65, 0x00, 0x00,
- 0x06, 0x40, 0x07, 0x69, 0x74, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x6c, 0x1a,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x06, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x01, 0x0c, 0x00, 0x93, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6f, 0x09, 0x00,
- 0x2c, 0x40, 0x06, 0x65, 0x72, 0x72, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x75,
- 0x05, 0x40, 0x2c, 0x65, 0x74, 0x00, 0x00, 0x09, 0xe3, 0x61, 0x00, 0x69,
- 0x05, 0x6f, 0x0d, 0x40, 0x06, 0x61, 0x72, 0x00, 0x40, 0x08, 0x6c, 0x6c,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x6f, 0x6b, 0x61, 0x00, 0x40, 0x00,
- 0x6c, 0x00, 0x40, 0x00, 0x72, 0x6d, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00,
- 0x3b, 0x00, 0xf6, 0x01, 0xfb, 0x01, 0x42, 0x02, 0x75, 0x03, 0x2c, 0x04,
- 0xab, 0x04, 0x7a, 0x05, 0x0c, 0x06, 0x19, 0x06, 0x00, 0x00, 0x20, 0x06,
- 0xa3, 0x07, 0xcb, 0x07, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x08, 0xf1, 0x08,
- 0x76, 0x09, 0xc4, 0x0a, 0x00, 0x00, 0x87, 0x0b, 0xa1, 0x0b, 0x00, 0x00,
- 0x03, 0x0c, 0x0f, 0x0c, 0x00, 0x00, 0xfb, 0x63, 0x00, 0x00, 0x64, 0x31,
- 0x00, 0x67, 0x47, 0x00, 0x6b, 0x4c, 0x00, 0x6d, 0x57, 0x00, 0x6e, 0x59,
- 0x00, 0x72, 0x90, 0x00, 0x73, 0xe6, 0x00, 0x74, 0xfe, 0x00, 0x75, 0x51,
- 0x01, 0x76, 0x94, 0x01, 0xe2, 0x68, 0x00, 0x6f, 0x28, 0xe5, 0x00, 0x00,
- 0x63, 0x02, 0x66, 0x0a, 0x68, 0x11, 0x77, 0x17, 0x00, 0x47, 0x40, 0x06,
- 0x6f, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x40, 0x00, 0x72, 0x6f, 0x6e, 0x74,
- 0x00, 0x40, 0x09, 0x65, 0x61, 0x64, 0x00, 0x40, 0x07, 0x65, 0x61, 0x72,
- 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07,
- 0x79, 0x0b, 0x00, 0x93, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0x00, 0xf3, 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x01, 0x0d, 0x40, 0x07, 0x72, 0x00, 0x00, 0x93, 0xe6, 0x00, 0x00,
- 0x62, 0x02, 0x66, 0x07, 0x69, 0x0e, 0x70, 0x12, 0x73, 0x18, 0x00, 0x93,
- 0x40, 0x09, 0x61, 0x67, 0x00, 0x40, 0x08, 0x65, 0x61, 0x73, 0x74, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x65, 0x00, 0xe2, 0x70,
- 0x00, 0x74, 0x07, 0x40, 0x08, 0x72, 0x6f, 0x75, 0x74, 0x00, 0x40, 0x09,
- 0x61, 0x6c, 0x6b, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x64, 0x11, 0x65,
- 0x1e, 0x69, 0x22, 0x6c, 0x3b, 0x73, 0x41, 0x01, 0x0e, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x37,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x55, 0x40, 0x00, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07,
- 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00,
- 0x40, 0x09, 0x6b, 0x69, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x09, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x0f, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x08, 0x69, 0x11, 0x6e, 0x43, 0x01, 0x10, 0x40, 0x37, 0x62, 0x6c, 0x65,
- 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0xe3, 0x66,
- 0x00, 0x6e, 0x21, 0x74, 0x25, 0xe2, 0x69, 0x00, 0x79, 0x1a, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x74,
- 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00,
- 0x01, 0x11, 0x40, 0x07, 0x67, 0x00, 0x40, 0x06, 0x75, 0x64, 0x65, 0x00,
- 0x40, 0x09, 0x69, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x08, 0x79, 0x31, 0x00, 0x09, 0x40,
- 0x3b, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x66, 0x06, 0x40, 0x06,
- 0x69, 0x61, 0x6e, 0x00, 0xe3, 0x69, 0x00, 0x75, 0x11, 0x79, 0x15, 0xe2,
- 0x63, 0x00, 0x65, 0x08, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x01, 0x12, 0x00, 0x06,
- 0x40, 0x93, 0x65, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x70, 0x00, 0xe5, 0x61,
- 0x00, 0x6b, 0x14, 0x6c, 0x1f, 0x6f, 0x25, 0x71, 0x34, 0xe3, 0x6c, 0x00,
- 0x6d, 0x04, 0x75, 0x08, 0x40, 0xad, 0x6d, 0x00, 0x40, 0x00, 0x65, 0x00,
- 0x40, 0x00, 0x73, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06,
- 0x40, 0x5b, 0x6e, 0x00, 0x40, 0x0b, 0x6f, 0x75, 0x64, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x08, 0x40, 0x36, 0x6e, 0x67,
- 0x00, 0x40, 0x08, 0x75, 0x65, 0x72, 0x65, 0x6c, 0x00, 0xfe, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x62, 0x21, 0x00, 0x63, 0x26, 0x00, 0x64, 0x3b,
- 0x00, 0x65, 0x4e, 0x00, 0x66, 0x6a, 0x00, 0x68, 0x72, 0x00, 0x69, 0x78,
- 0x00, 0x6c, 0x97, 0x00, 0x70, 0x9c, 0x00, 0x72, 0xaa, 0x00, 0x73, 0xd2,
- 0x00, 0x74, 0x02, 0x01, 0x00, 0x06, 0xe2, 0x75, 0x00, 0x7a, 0x04, 0x40,
- 0xad, 0x62, 0x00, 0xe1, 0x7a, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0x13, 0x40, 0x07, 0x65, 0x6e, 0x74,
- 0x00, 0x40, 0x06, 0x75, 0x67, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x08, 0x40,
- 0x08, 0x61, 0x6d, 0x62, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x68,
- 0x65, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x63,
- 0x00, 0x76, 0x04, 0x40, 0xad, 0x6b, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x06, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x00, 0x40, 0x08,
- 0x65, 0x61, 0x64, 0x00, 0xe2, 0x6d, 0x00, 0x7a, 0x15, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x0b, 0x65, 0x6e, 0x00, 0x40,
- 0x06, 0x61, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x6e,
- 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x07, 0x6f,
- 0x0e, 0x40, 0x0b, 0x67, 0x67, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x64, 0x64,
- 0x65, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x04, 0x6f, 0x08, 0x40, 0x06,
- 0x6b, 0x00, 0x40, 0x06, 0x6c, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe4, 0x69,
- 0x00, 0x6f, 0x15, 0x70, 0x1a, 0x74, 0x21, 0xe2, 0x64, 0x00, 0x74, 0x04,
- 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0x40,
- 0x08, 0x65, 0x72, 0x00, 0x40, 0x06, 0x72, 0x65, 0x00, 0x40, 0x06, 0x72,
- 0x65, 0x61, 0x64, 0x00, 0x40, 0x06, 0x65, 0x61, 0x64, 0x00, 0x40, 0x06,
- 0x69, 0x6d, 0x65, 0x00, 0xed, 0x00, 0x00, 0x62, 0x02, 0x63, 0x09, 0x66,
- 0x18, 0x68, 0x45, 0x6b, 0x4b, 0x6c, 0x62, 0x6e, 0x68, 0x70, 0x6a, 0x72,
- 0x75, 0x73, 0x7e, 0x74, 0x84, 0x76, 0x97, 0x01, 0x14, 0x40, 0x07, 0x72,
- 0x65, 0x61, 0x64, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x09, 0x40, 0x09, 0x75, 0x74, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02,
- 0x63, 0x0a, 0x69, 0x10, 0x73, 0x17, 0x79, 0x1e, 0x00, 0x93, 0x40, 0x06,
- 0x75, 0x72, 0x67, 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x6b, 0x65, 0x00,
- 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x74, 0x65, 0x61,
- 0x6b, 0x00, 0x01, 0x15, 0x40, 0x09, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x69,
- 0x6e, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfa,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x60, 0x40, 0x07, 0x77, 0x61, 0x78, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02,
- 0x72, 0x06, 0x00, 0x06, 0x40, 0x82, 0x65, 0x00, 0x40, 0x08, 0x6f, 0x6f,
- 0x74, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x05,
- 0x69, 0x0a, 0x6f, 0x22, 0x72, 0x52, 0x75, 0x59, 0x41, 0x16, 0x6c, 0x6c,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x67, 0x00, 0x72, 0x15, 0x75,
- 0x25, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x40, 0x00, 0x61, 0x6e,
- 0x64, 0x00, 0x40, 0x72, 0x6c, 0x00, 0x40, 0x5b, 0x69, 0x65, 0x6e, 0x64,
- 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x35, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0b, 0x67, 0x23, 0x69,
- 0x3f, 0x6f, 0x57, 0x72, 0x73, 0x75, 0x8f, 0x00, 0x08, 0xe2, 0x6e, 0x00,
- 0x74, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x08, 0x72,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0c, 0x69,
- 0x10, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x01, 0x17, 0x00,
- 0x07, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe2, 0x6e,
- 0x00, 0x74, 0x0b, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x06,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x00, 0x65,
- 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x3a, 0x6d, 0x65, 0x00,
- 0xe1, 0x64, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x3a, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x69, 0x00, 0x6d, 0x24, 0x6e,
- 0x26, 0xe2, 0x6c, 0x00, 0x6e, 0x1b, 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe3,
- 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x01, 0x18, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0x00, 0x09, 0x00, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x37, 0x69, 0x5e,
- 0x6f, 0x71, 0xe2, 0x6c, 0x00, 0x76, 0x0c, 0xe2, 0x66, 0x00, 0x76, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x65, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x0b, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x06, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe4, 0x61, 0x00,
- 0x6c, 0x04, 0x6d, 0x08, 0x73, 0x1a, 0x40, 0x72, 0x64, 0x00, 0x40, 0x00,
- 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x74, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x0e,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x19, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x3a, 0x76, 0x65, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x67, 0x00, 0x40, 0x7a, 0x65, 0x77,
- 0x65, 0x6c, 0x00, 0xfa, 0x61, 0x00, 0x00, 0x63, 0x13, 0x00, 0x65, 0x17,
- 0x00, 0x66, 0x1f, 0x00, 0x69, 0x24, 0x00, 0x6c, 0x75, 0x00, 0x6f, 0x30,
- 0x01, 0x74, 0x4d, 0x01, 0x75, 0x59, 0x01, 0x79, 0x5e, 0x01, 0xe3, 0x62,
- 0x00, 0x74, 0x05, 0x79, 0x0a, 0x40, 0x7a, 0x6f, 0x72, 0x00, 0x40, 0x3b,
- 0x65, 0x64, 0x00, 0x00, 0x0b, 0x40, 0x59, 0x68, 0x00, 0x40, 0xad, 0x61,
- 0x67, 0x75, 0x65, 0x72, 0x00, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x74, 0x36, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x76, 0x0b, 0x01, 0x1a,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01, 0x1b, 0x00, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x0f, 0x69, 0x18, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x01, 0x1c, 0x01, 0x1d, 0x40, 0x37, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0x78, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02,
- 0x62, 0x0a, 0x65, 0x0f, 0x68, 0x31, 0x69, 0x36, 0x6d, 0x6f, 0x6f, 0x7c,
- 0x77, 0x80, 0x79, 0x88, 0x00, 0x93, 0x40, 0x07, 0x64, 0x6f, 0x6e, 0x6e,
- 0x61, 0x00, 0x40, 0x06, 0x6f, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02,
- 0x74, 0x04, 0x00, 0x09, 0x00, 0x77, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x6f, 0x70, 0x00, 0xe3, 0x63,
- 0x00, 0x67, 0x12, 0x6e, 0x2e, 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x86, 0x40, 0x77, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x55, 0x77, 0x00,
- 0x40, 0x09, 0x65, 0x74, 0x68, 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x62, 0x08, 0x66, 0x10, 0x00, 0xa1, 0x40, 0x82, 0x63, 0x68, 0x65,
- 0x00, 0x40, 0x06, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x75,
- 0x6c, 0x00, 0xe3, 0x6e, 0x00, 0x76, 0x0f, 0x77, 0x14, 0xe1, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x1e, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x65, 0x64, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02,
- 0x00, 0x93, 0x40, 0x06, 0x61, 0x79, 0x00, 0x40, 0x09, 0x67, 0x61, 0x00,
- 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x05, 0x75,
- 0x0a, 0x40, 0x0b, 0x72, 0x65, 0x00, 0x40, 0x72, 0x61, 0x6e, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6d, 0x04,
- 0x00, 0x34, 0x00, 0x3b, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe7, 0x63,
- 0x00, 0x64, 0x10, 0x65, 0x1f, 0x69, 0xb1, 0x74, 0xd2, 0x75, 0xdf, 0x7a,
- 0xe4, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x59, 0x40,
- 0x09, 0x61, 0x72, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x06,
- 0x01, 0x1f, 0x40, 0x07, 0x72, 0x00, 0x00, 0x60, 0xe4, 0x61, 0x00, 0x64,
- 0x05, 0x66, 0x25, 0x76, 0x72, 0x40, 0x00, 0x74, 0x68, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0d,
- 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x06, 0x6e,
- 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x1c, 0xe1,
- 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x05, 0x72, 0x09,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x09, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x25, 0xe2, 0x65, 0x00, 0x69,
- 0x12, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x61, 0x00, 0xe2, 0x6c,
- 0x00, 0x72, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x79, 0x00, 0x00, 0x2c, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x67,
- 0x00, 0xe2, 0x68, 0x00, 0x6e, 0x06, 0x40, 0x3b, 0x74, 0x65, 0x64, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x3b, 0x40, 0x00, 0x6e,
- 0x74, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x3a, 0x6d, 0x62,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x79, 0x0a, 0x40, 0x07, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x0f, 0xe1, 0x74, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01, 0x20, 0x00, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0xea, 0x61, 0x00, 0x65, 0x05, 0x67, 0x25, 0x69,
- 0x27, 0x6b, 0x2e, 0x6d, 0x3c, 0x72, 0x3e, 0x73, 0x4e, 0x74, 0x54, 0x79,
- 0x60, 0x40, 0x0b, 0x74, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x66, 0x13, 0x74,
- 0x17, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x58, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x74, 0x00,
- 0x00, 0x09, 0x00, 0x06, 0x40, 0x07, 0x62, 0x65, 0x72, 0x69, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x08, 0x40, 0x07, 0x6c, 0x69, 0x75, 0x6d,
- 0x00, 0x00, 0x06, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0xa1, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00, 0x40, 0x00, 0x65, 0x72, 0x6b,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xec, 0x00,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x40,
- 0x07, 0x69, 0x75, 0x6d, 0x00, 0xf6, 0x65, 0x00, 0x00, 0x69, 0x2e, 0x00,
- 0x6d, 0x46, 0x00, 0x6f, 0x56, 0x00, 0x70, 0x7a, 0x00, 0x74, 0xb3, 0x00,
- 0xe2, 0x65, 0x00, 0x74, 0x1c, 0xe2, 0x63, 0x00, 0x6d, 0x15, 0xe1, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xe5, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x00, 0x3a, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x64,
- 0x00, 0x65, 0x04, 0x40, 0x08, 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe2, 0x65,
- 0x00, 0x69, 0x05, 0x40, 0x3a, 0x61, 0x72, 0x00, 0x40, 0x0b, 0x72, 0x63,
- 0x68, 0x00, 0xe3, 0x6d, 0x00, 0x74, 0x02, 0x75, 0x17, 0x00, 0x09, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x67, 0x68,
- 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x11, 0x6f, 0x23, 0xe2, 0x6e, 0x00,
- 0x74, 0x06, 0x40, 0x3a, 0x67, 0x6c, 0x65, 0x00, 0x40, 0xad, 0x74, 0x65,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x04, 0x41, 0x21, 0x6b, 0x00, 0x40,
- 0x00, 0x74, 0x61, 0x63, 0x6c, 0x65, 0x64, 0x00, 0xe1, 0x6b, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe5,
- 0x00, 0x00, 0x69, 0x02, 0x6f, 0x31, 0x72, 0x3f, 0x73, 0x66, 0x00, 0x93,
- 0xe2, 0x61, 0x00, 0x72, 0x15, 0xe2, 0x6c, 0x00, 0x72, 0x0c, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x06,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1,
- 0x77, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x72, 0x40, 0x06, 0x6c,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0c, 0x6f, 0x1b, 0xe1, 0x77, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7a, 0x00, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x64, 0x00, 0x65, 0x05, 0x40, 0x00, 0x65, 0x6e, 0x00, 0x01, 0x21, 0x40,
- 0x00, 0x64, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x63, 0x15, 0x65, 0x1a,
- 0x68, 0x1e, 0x69, 0x2f, 0x6f, 0x3d, 0x72, 0x4b, 0x74, 0x7f, 0x77, 0x9f,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x06, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3c, 0x00, 0x00, 0x40, 0x00, 0x68,
- 0x61, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x41,
- 0x21, 0x6e, 0x6b, 0x00, 0x40, 0x00, 0x75, 0x67, 0x68, 0x74, 0x00, 0xe2,
- 0x64, 0x00, 0x6d, 0x04, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x00, 0xe2, 0x6b, 0x00, 0x6f, 0x05, 0x40, 0x0b, 0x65, 0x6e, 0x00, 0x40,
- 0x00, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x14, 0xe1, 0x79, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x00, 0x4c, 0x40, 0x06, 0x6c, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x06, 0x73, 0x0a, 0x01, 0x20, 0x40, 0x06, 0x6c,
- 0x00, 0x40, 0x07, 0x64, 0x00, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x10,
- 0x6f, 0x15, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0x22,
- 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x65, 0x6e,
- 0x00, 0x40, 0x00, 0x78, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x76, 0x0d, 0x79,
- 0x11, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x59, 0x40, 0x06, 0x61, 0x67,
- 0x65, 0x00, 0x40, 0x08, 0x79, 0x00, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x68,
- 0x0d, 0x69, 0x17, 0xe2, 0x69, 0x00, 0x72, 0x04, 0x40, 0x72, 0x6c, 0x00,
- 0x40, 0x0b, 0x65, 0x00, 0x40, 0x00, 0x69, 0x73, 0x6b, 0x65, 0x72, 0x65,
- 0x64, 0x00, 0xe3, 0x67, 0x00, 0x6c, 0x06, 0x74, 0x23, 0x40, 0x00, 0x67,
- 0x65, 0x64, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x07, 0x01, 0x23, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x07, 0x00, 0x35, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x64, 0x00, 0x40, 0x09,
- 0x65, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x61, 0x6a, 0x69, 0x00, 0xc1,
- 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x5b, 0x00, 0xaf, 0x00, 0x55, 0x01,
- 0x94, 0x01, 0xae, 0x01, 0xe1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x81, 0x02,
- 0x90, 0x02, 0xa3, 0x02, 0x9c, 0x03, 0xc9, 0x03, 0x45, 0x04, 0x05, 0x06,
- 0x00, 0x00, 0x5c, 0x06, 0x3e, 0x07, 0xa8, 0x07, 0x00, 0x00, 0x33, 0x08,
- 0x67, 0x08, 0x00, 0x00, 0x6f, 0x08, 0x77, 0x08, 0x01, 0x24, 0xe3, 0x6e,
- 0x00, 0x73, 0x07, 0x74, 0x12, 0x40, 0x3b, 0x6e, 0x75, 0x61, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x59, 0x40, 0x37, 0x64, 0x00, 0x40,
- 0x06, 0x68, 0x6c, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x75,
- 0x46, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe2, 0x63,
- 0x00, 0x6f, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe2, 0x67, 0x00, 0x70,
- 0x27, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x12, 0x40, 0x09, 0x72, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b,
- 0x6c, 0x00, 0x00, 0x06, 0x40, 0x06, 0x68, 0x69, 0x6c, 0x65, 0x00, 0x40,
- 0x00, 0x6c, 0x6f, 0x75, 0x73, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x2e, 0x6b,
- 0x55, 0x6f, 0x66, 0x75, 0x79, 0x79, 0x80, 0xe2, 0x6d, 0x00, 0x72, 0x18,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0xe1, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0x40, 0x09,
- 0x6e, 0x61, 0x74, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x70, 0x19, 0xe1, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x05,
- 0x40, 0x06, 0x72, 0x79, 0x00, 0x40, 0x06, 0x69, 0x61, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfe, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x76, 0x06, 0x40, 0x00, 0x61,
- 0x76, 0x65, 0x00, 0x40, 0x00, 0x65, 0x78, 0x00, 0x40, 0x09, 0x73, 0x70,
- 0x69, 0x64, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x65, 0x21, 0x69,
- 0x2a, 0x01, 0x25, 0xe4, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0f, 0x79, 0x14,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x08, 0x00, 0x09, 0x40, 0x3b, 0x72, 0x65, 0x63,
- 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x13,
- 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40,
- 0x86, 0x6c, 0x00, 0x40, 0x09, 0x6d, 0x00, 0x00, 0x07, 0xe3, 0x66, 0x00,
- 0x6f, 0x02, 0x75, 0x14, 0x00, 0x5b, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07,
- 0xe1, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe8, 0x00, 0x00, 0x61, 0x02, 0x67, 0x18, 0x68, 0x33, 0x6d, 0x61, 0x6e,
- 0x76, 0x6f, 0x7c, 0x77, 0x8a, 0x00, 0x5d, 0xe1, 0x6d, 0x00, 0xe3, 0x69,
- 0x00, 0x6f, 0x05, 0x79, 0x0a, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x00,
- 0x75, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x72,
- 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x73, 0x02, 0x00, 0x09, 0x40, 0x00, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x6f,
- 0x20, 0x74, 0x25, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x06, 0x72, 0x6e, 0x00, 0x00, 0x09, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xb2, 0x40, 0x06, 0x79, 0x00, 0x40,
- 0x09, 0x69, 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x00,
- 0x00, 0x78, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x09, 0x6e,
- 0x69, 0x00, 0xe7, 0x61, 0x00, 0x62, 0x12, 0x65, 0x19, 0x67, 0x1b, 0x69,
- 0x1f, 0x6b, 0x58, 0x6c, 0x63, 0xe2, 0x62, 0x00, 0x74, 0x06, 0x40, 0x09,
- 0x69, 0x61, 0x6c, 0x00, 0x40, 0x3b, 0x65, 0x72, 0x61, 0x6c, 0x00, 0x40,
- 0x08, 0x65, 0x72, 0x72, 0x79, 0x00, 0x00, 0x07, 0x40, 0x09, 0x65, 0x00,
- 0xe3, 0x6e, 0x00, 0x6f, 0x18, 0x72, 0x2b, 0xe1, 0x67, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x56, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x00, 0x75, 0x62, 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x01, 0x27, 0x40, 0x07, 0x72, 0x00, 0xe8, 0x00, 0x00, 0x62,
- 0x02, 0x65, 0x09, 0x66, 0x0d, 0x68, 0x13, 0x69, 0x19, 0x6f, 0x5e, 0x79,
- 0x6a, 0x01, 0x28, 0x40, 0x09, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x59,
- 0x74, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x64, 0x00, 0x40, 0x08, 0x6f, 0x6f,
- 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x6e, 0x0f, 0x6f, 0x20, 0xe1, 0x72, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07,
- 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x67, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x74, 0x08, 0x01, 0x29, 0x40, 0x06, 0x69, 0x72, 0x65, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1,
- 0x77, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x06, 0x40, 0x08, 0x61, 0x6e, 0x00, 0xe3,
- 0x62, 0x00, 0x65, 0x04, 0x6f, 0x1e, 0x40, 0x09, 0x6f, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x07, 0x6d, 0x00,
- 0x40, 0x06, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x00, 0xe7, 0x00, 0x00, 0x61,
- 0x02, 0x64, 0x07, 0x67, 0x2f, 0x6d, 0x38, 0x6e, 0x45, 0x6f, 0x5b, 0x00,
- 0x06, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x65,
- 0x06, 0x69, 0x12, 0x77, 0x17, 0x01, 0x2a, 0x40, 0x00, 0x73, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06, 0x40,
- 0x09, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x65, 0x64, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x02, 0x00, 0xb2, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x06, 0x69, 0x0a, 0x40, 0x06, 0x63, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x07, 0x40,
- 0x09, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x40, 0x06, 0x69, 0x61, 0x6c, 0x00,
- 0xfe, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x64, 0x2a, 0x00, 0x65, 0x55,
- 0x00, 0x66, 0x5d, 0x00, 0x67, 0x67, 0x00, 0x69, 0x92, 0x00, 0x6c, 0x9e,
- 0x00, 0x6d, 0xc3, 0x00, 0x6e, 0xd5, 0x00, 0x70, 0xec, 0x00, 0x72, 0x1d,
- 0x01, 0x73, 0x31, 0x01, 0x74, 0x62, 0x01, 0x00, 0x06, 0xe1, 0x68, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x56, 0x61, 0x6c, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09, 0x40, 0x07, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x1c, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x09, 0x40,
- 0x07, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x00, 0xa8, 0x40, 0x07,
- 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x00, 0x40, 0x07, 0x74, 0x68,
- 0x69, 0x63, 0x73, 0x00, 0x40, 0x07, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79,
- 0x12, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x06, 0x40, 0x09, 0x6e,
- 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14,
- 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x65, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x40, 0x00, 0x64, 0x69,
- 0x63, 0x61, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x07, 0xe3, 0x68, 0x00, 0x69, 0x22, 0x73, 0x26, 0xe1, 0x79,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1,
- 0x63, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x73, 0x09, 0x40, 0x00, 0x6c,
- 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x09, 0x63, 0x00,
- 0x40, 0xa1, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x08, 0x40, 0x08, 0x61,
- 0x63, 0x74, 0x6f, 0x72, 0x00, 0x40, 0x09, 0x79, 0x74, 0x68, 0x6d, 0x00,
- 0xe3, 0x65, 0x00, 0x70, 0x07, 0x79, 0x0e, 0x40, 0x08, 0x6e, 0x73, 0x6f,
- 0x72, 0x00, 0x40, 0x06, 0x68, 0x65, 0x72, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x2a, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x06, 0x20, 0x07, 0x00, 0x00, 0xff, 0xff, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x06, 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x25, 0x6c, 0x33, 0x6f,
- 0x39, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x73,
- 0x00, 0x74, 0x13, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x00, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe5, 0x61, 0x00, 0x63, 0x07,
- 0x64, 0x0b, 0x65, 0x8a, 0x74, 0x90, 0x40, 0x00, 0x63, 0x69, 0x61, 0x6c,
- 0x00, 0x40, 0x59, 0x68, 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x63, 0x1c,
- 0x65, 0x22, 0x68, 0x26, 0x69, 0x2d, 0x6c, 0x3c, 0x73, 0x4c, 0x77, 0x5b,
- 0x79, 0x64, 0x00, 0xfa, 0xe2, 0x61, 0x00, 0x72, 0x0f, 0xe1, 0x74, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0xb1, 0x61, 0x69, 0x6e, 0x00, 0x40, 0x08, 0x61, 0x67, 0x65, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xb2, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6b, 0x00, 0x6d, 0x04, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40,
- 0x07, 0x65, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x61,
- 0x74, 0x63, 0x68, 0x65, 0x72, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x74, 0x74, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe7, 0x00, 0x00,
- 0x64, 0x02, 0x65, 0x07, 0x6d, 0x0b, 0x70, 0x11, 0x72, 0x18, 0x73, 0x28,
- 0x01, 0x2b, 0x40, 0x09, 0x61, 0x79, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x09, 0x61, 0x72, 0x6b, 0x00, 0x40, 0x09, 0x6c, 0x61, 0x63, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x09, 0x74, 0x65, 0x00, 0x40, 0x09,
- 0x67, 0x68, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x77, 0x40,
- 0x06, 0x6f, 0x6e, 0x65, 0x00, 0xe7, 0x63, 0x00, 0x65, 0x06, 0x68, 0x35,
- 0x6d, 0x47, 0x6f, 0x4d, 0x71, 0x51, 0x74, 0x56, 0x40, 0x06, 0x75, 0x69,
- 0x74, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x15, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x72, 0x40, 0x09, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x69, 0x63, 0x00, 0x40, 0x07, 0x75, 0x74, 0x68,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x75, 0x65, 0x00, 0x40, 0x09,
- 0x72, 0x6f, 0x00, 0xe7, 0x00, 0x00, 0x63, 0x02, 0x65, 0x26, 0x69, 0x2f,
- 0x6d, 0x34, 0x74, 0x39, 0x75, 0x69, 0x01, 0x2c, 0xe2, 0x68, 0x00, 0x6f,
- 0x1a, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x59, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x0c, 0x40, 0x06, 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x94, 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x08,
- 0x61, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x29, 0xe2, 0x6e, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x73, 0x0e, 0x01, 0x2d,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x09, 0x65, 0x65, 0x74,
- 0x00, 0x00, 0x60, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x11, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x76, 0x05, 0x40,
- 0x00, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x06, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x00, 0x40, 0x00,
- 0x65, 0x61, 0x72, 0x6c, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x07, 0x40, 0x3b, 0x72, 0x72, 0x65, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x64, 0x7b, 0x02, 0x65, 0x7f, 0x02, 0x69, 0x45,
- 0x03, 0x6f, 0x2e, 0x04, 0x75, 0xba, 0x06, 0x76, 0x32, 0x08, 0x01, 0x20,
- 0xfb, 0x62, 0x00, 0x00, 0x63, 0x34, 0x00, 0x64, 0x2c, 0x01, 0x67, 0x38,
- 0x01, 0x68, 0x4d, 0x01, 0x6d, 0x56, 0x01, 0x6e, 0x98, 0x01, 0x72, 0xe2,
- 0x01, 0x73, 0xee, 0x01, 0x74, 0x29, 0x02, 0x7a, 0x45, 0x02, 0xe2, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x23, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x72,
- 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe1, 0x6b, 0x00, 0xc1, 0x61, 0x14, 0x2d, 0x00, 0x2f, 0x00,
- 0x36, 0x00, 0x55, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x68, 0x00,
- 0x6f, 0x00, 0x75, 0x00, 0x82, 0x00, 0x00, 0x00, 0x88, 0x00, 0x96, 0x00,
- 0xaa, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x00,
- 0xd2, 0x00, 0x01, 0x2e, 0x40, 0x09, 0x6d, 0x6f, 0x6f, 0x72, 0x00, 0xe4,
- 0x61, 0x00, 0x65, 0x05, 0x69, 0x0b, 0x6f, 0x10, 0x40, 0x93, 0x6c, 0x6c,
- 0x00, 0x41, 0x2f, 0x72, 0x72, 0x79, 0x00, 0x40, 0x06, 0x72, 0x64, 0x00,
- 0x40, 0x09, 0x61, 0x72, 0x64, 0x00, 0x40, 0x08, 0x75, 0x72, 0x72, 0x61,
- 0x6e, 0x74, 0x00, 0x41, 0x20, 0x6e, 0x00, 0x40, 0x00, 0x61, 0x63, 0x65,
- 0x00, 0x40, 0x06, 0x75, 0x61, 0x72, 0x64, 0x00, 0x40, 0x09, 0x65, 0x61,
- 0x64, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07, 0x67, 0x00, 0x40,
- 0x00, 0x68, 0x00, 0x40, 0x55, 0x61, 0x63, 0x6b, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x08, 0x67, 0x00, 0x40, 0x47, 0x73, 0x74, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x12, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x61, 0x6b, 0x65, 0x00, 0xe2,
- 0x68, 0x00, 0x6f, 0x06, 0x40, 0x06, 0x6f, 0x72, 0x6e, 0x00, 0xe1, 0x70,
- 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x64,
- 0x00, 0x65, 0x05, 0x40, 0x09, 0x65, 0x72, 0x00, 0x00, 0xb2, 0xe2, 0x00,
- 0x00, 0x67, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6d, 0x39, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x77, 0x18, 0x01, 0x30, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x5d, 0x40, 0x00, 0x6f, 0x00, 0xe3, 0x63,
- 0x00, 0x64, 0x0e, 0x6b, 0x30, 0xe2, 0x68, 0x00, 0x6d, 0x02, 0x00, 0x0b,
- 0x40, 0x09, 0x61, 0x6e, 0x67, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6e, 0x15, 0x00, 0x63, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x58, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06,
- 0x01, 0x31, 0x40, 0x59, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x82, 0x40, 0x2c, 0x65, 0x79, 0x00,
- 0xe3, 0x65, 0x00, 0x70, 0x02, 0x74, 0x22, 0x00, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x09, 0x79,
- 0x0e, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0x40, 0x3b,
- 0x75, 0x73, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x06,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x66, 0x66, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x68, 0x10, 0x00, 0x08, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x00, 0x3b, 0x40, 0x2c,
- 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x09, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x55, 0x6e, 0x00, 0x40, 0x00, 0x67,
- 0x00, 0xe7, 0x61, 0x00, 0x65, 0x45, 0x6d, 0x67, 0x6e, 0x7b, 0x73, 0x8f,
- 0x74, 0xb0, 0x77, 0xb5, 0xe4, 0x63, 0x00, 0x6b, 0x13, 0x72, 0x20, 0x74,
- 0x3a, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x46, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x79, 0x11, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0x00,
- 0x59, 0xe2, 0x64, 0x00, 0x70, 0x12, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x00, 0xe5, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x59, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x63, 0x00, 0x64, 0x04,
- 0x40, 0x3a, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40,
- 0x07, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x12, 0x01, 0x32, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x00, 0x63, 0x68, 0x00, 0x00, 0x00, 0xe8, 0x67, 0x00, 0x6d, 0x05,
- 0x6e, 0x1a, 0x70, 0x66, 0x73, 0x68, 0x74, 0x9d, 0x76, 0xcc, 0x7a, 0xd1,
- 0x40, 0xc3, 0x68, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x70, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x73,
- 0x68, 0x00, 0xe4, 0x64, 0x00, 0x69, 0x2a, 0x6b, 0x2c, 0x74, 0x37, 0xe6,
- 0x00, 0x00, 0x65, 0x02, 0x66, 0x06, 0x69, 0x0c, 0x6e, 0x11, 0x73, 0x17,
- 0x01, 0x33, 0x40, 0x07, 0x72, 0x00, 0x40, 0x2c, 0x6f, 0x6c, 0x64, 0x00,
- 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x3a, 0x69, 0x64, 0x65, 0x00, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xc3, 0x40, 0x2f, 0x72, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x09, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x73, 0x00, 0x74,
- 0x1a, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x79, 0x07, 0x00, 0x59, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x00,
- 0x00, 0xe2, 0x68, 0x00, 0x7a, 0x1c, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00,
- 0x6e, 0x02, 0x72, 0x08, 0x73, 0x0a, 0x00, 0xd3, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x1c, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6b, 0x02, 0x00, 0x59, 0x40, 0x09, 0x72, 0x69, 0x65, 0x67, 0x00,
- 0x40, 0x08, 0x65, 0x74, 0x00, 0x40, 0x06, 0x7a, 0x61, 0x72, 0x64, 0x00,
- 0xfb, 0x61, 0x00, 0x00, 0x62, 0x10, 0x00, 0x63, 0x25, 0x00, 0x67, 0x7f,
- 0x00, 0x6b, 0xa1, 0x00, 0x6e, 0xad, 0x00, 0x6f, 0xc8, 0x00, 0x73, 0xc2,
- 0x01, 0x74, 0xd4, 0x01, 0x75, 0x00, 0x02, 0x77, 0x05, 0x02, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x3f, 0x40, 0x00, 0x61, 0x72,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x6b, 0x02, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x61,
- 0x06, 0x62, 0x1b, 0x65, 0x32, 0x68, 0x36, 0x01, 0x34, 0x40, 0x00, 0x73,
- 0x00, 0xe2, 0x64, 0x00, 0x67, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x61, 0x64, 0x00, 0x40,
- 0x09, 0x75, 0x73, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x72, 0x15,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f,
- 0x6c, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x73, 0x68, 0x00, 0xe1, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x04, 0x6e, 0x09, 0x01, 0x35, 0x00, 0x09, 0x40, 0x00, 0x73, 0x68, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x64, 0x00, 0x6d, 0xdd, 0x70,
- 0xe8, 0xea, 0x00, 0x00, 0x62, 0x02, 0x63, 0x14, 0x68, 0x1e, 0x69, 0x25,
- 0x6c, 0x34, 0x6d, 0x5a, 0x73, 0x62, 0x74, 0xa1, 0x79, 0xc6, 0x00, 0x59,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x75, 0x72, 0x64, 0x6c,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x1c, 0xe2, 0x73, 0x00, 0x74, 0x10,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x00,
- 0xe3, 0x68, 0x00, 0x74, 0x0d, 0x75, 0x24, 0xe2, 0x65, 0x00, 0x6f, 0x04,
- 0x40, 0x07, 0x64, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x6f,
- 0x05, 0x72, 0x0a, 0x40, 0xb1, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x63, 0x6b,
- 0x00, 0x40, 0x06, 0x65, 0x61, 0x6d, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x15, 0x01, 0x36, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3,
- 0x40, 0x07, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x63, 0x02, 0x74, 0x0e, 0x00, 0x06, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0x60, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x6f, 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x40, 0x82, 0x73, 0x65, 0x00, 0xee,
- 0x00, 0x00, 0x65, 0x02, 0x66, 0x06, 0x67, 0x0b, 0x68, 0x10, 0x6a, 0x1f,
- 0x6c, 0x24, 0x6e, 0x2a, 0x6f, 0x2c, 0x70, 0x31, 0x74, 0x37, 0x75, 0x3e,
- 0x79, 0x42, 0x7a, 0x44, 0x01, 0x37, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06,
- 0x6c, 0x79, 0x00, 0x40, 0x09, 0x75, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x05, 0x40, 0x09, 0x72, 0x64, 0x00, 0x40, 0x08, 0x6c, 0x65, 0x00, 0x40,
- 0x00, 0x6f, 0x62, 0x00, 0x40, 0x08, 0x61, 0x6d, 0x70, 0x00, 0x00, 0x00,
- 0x40, 0x06, 0x75, 0x74, 0x00, 0x40, 0x06, 0x69, 0x70, 0x65, 0x00, 0x40,
- 0x09, 0x6f, 0x72, 0x63, 0x68, 0x00, 0x40, 0x09, 0x70, 0x00, 0x00, 0x60,
- 0x40, 0xf3, 0x79, 0x00, 0xf8, 0x62, 0x00, 0x00, 0x64, 0x12, 0x00, 0x65,
- 0x19, 0x00, 0x66, 0xba, 0x00, 0x69, 0xd0, 0x00, 0x6e, 0xdd, 0x00, 0x72,
- 0x08, 0x01, 0x73, 0x33, 0x01, 0xe1, 0x62, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x95, 0x00, 0x00, 0x40,
- 0x55, 0x67, 0x65, 0x6f, 0x6e, 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x66,
- 0x2d, 0x67, 0x33, 0x69, 0x43, 0x6a, 0x48, 0x6e, 0x5a, 0x70, 0x69, 0x73,
- 0x7a, 0x74, 0x8a, 0x01, 0x38, 0xe3, 0x65, 0x00, 0x69, 0x0e, 0x6f, 0x13,
- 0xe2, 0x6c, 0x00, 0x72, 0x04, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x06, 0x72,
- 0x79, 0x00, 0x40, 0x09, 0x72, 0x64, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x06,
- 0x40, 0x06, 0x6e, 0x65, 0x74, 0x00, 0x40, 0x06, 0x74, 0x6c, 0x65, 0x00,
- 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40,
- 0x09, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x73, 0x73, 0x00, 0x40, 0x00,
- 0x73, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x63, 0x6b,
- 0x65, 0x74, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x40, 0x09, 0x73, 0x65, 0x00,
- 0xe2, 0x6f, 0x00, 0x72, 0x06, 0x40, 0x09, 0x69, 0x6e, 0x74, 0x00, 0x40,
- 0x55, 0x69, 0x6e, 0x74, 0x00, 0xe2, 0x74, 0x00, 0x79, 0x09, 0x40, 0x06,
- 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0x00, 0x09, 0xe1,
- 0x66, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x01, 0x39, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6e, 0x00,
- 0x73, 0x04, 0x40, 0x07, 0x67, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe2, 0x64,
- 0x00, 0x74, 0x19, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x08, 0x00, 0xfe, 0x40, 0x09, 0x75, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x3a, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x72, 0x04,
- 0x74, 0x20, 0x00, 0x06, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79,
- 0x13, 0x40, 0x00, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x0b,
- 0xe2, 0x68, 0x00, 0x74, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3,
- 0x40, 0x07, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x6f, 0x06, 0x79, 0x0b, 0x00, 0xe7, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x00, 0x40, 0x00, 0x64, 0x00,
- 0xc0, 0x61, 0x1a, 0x37, 0x00, 0xe0, 0x00, 0x69, 0x01, 0x75, 0x01, 0x00,
- 0x00, 0xe9, 0x01, 0xf7, 0x01, 0x60, 0x02, 0x7b, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xc6, 0x02, 0x61, 0x03, 0xc2, 0x03, 0xb0, 0x04, 0xeb, 0x06, 0x00,
- 0x00, 0x00, 0x07, 0xa2, 0x07, 0xdd, 0x07, 0x7c, 0x08, 0xd5, 0x09, 0xe4,
- 0x09, 0x72, 0x0a, 0xa7, 0x0a, 0xe7, 0x0a, 0xe4, 0x00, 0x00, 0x72, 0x02,
- 0x73, 0x3a, 0x74, 0x5d, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x06, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x72, 0x1a, 0x77, 0x20,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6f, 0x75, 0x73,
- 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x09, 0x61, 0x6c,
- 0x6b, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x66, 0x06,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe8, 0x00, 0x00, 0x65, 0x02, 0x68, 0x06, 0x69, 0x0d, 0x6c, 0x12,
- 0x6d, 0x18, 0x73, 0x25, 0x79, 0x2c, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x08, 0x6f, 0x61, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x77, 0x61, 0x69,
- 0x6e, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00, 0xe7, 0x00, 0x00, 0x62,
- 0x02, 0x63, 0x2d, 0x6f, 0x32, 0x73, 0x39, 0x74, 0x6d, 0x77, 0x73, 0x00,
- 0x06, 0xe4, 0x65, 0x00, 0x69, 0x04, 0x6c, 0x10, 0x79, 0x14, 0x40, 0x00,
- 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09,
- 0x00, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x40, 0x06, 0x6f, 0x78, 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x74,
- 0x00, 0x40, 0x06, 0x6c, 0x69, 0x6e, 0x6b, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x64, 0x00, 0x69, 0x1a, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x06, 0x61, 0x69, 0x6c, 0x00, 0x40, 0x09, 0x68, 0x69, 0x74, 0x65,
- 0x00, 0xe2, 0x63, 0x00, 0x6b, 0x05, 0x40, 0x07, 0x69, 0x65, 0x00, 0x00,
- 0x07, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0a, 0x67, 0x15, 0x69, 0x19,
- 0x6b, 0x26, 0x79, 0x2b, 0x00, 0x2c, 0x40, 0x00, 0x63, 0x69, 0x6f, 0x75,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08, 0x40, 0x09, 0x61,
- 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x04, 0x40, 0x09,
- 0x65, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x00, 0xe5,
- 0x00, 0x00, 0x62, 0x02, 0x67, 0x1c, 0x73, 0x23, 0x77, 0x29, 0x00, 0x1a,
- 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x75, 0x61, 0x72, 0x64, 0x00, 0x40, 0x06, 0x75,
- 0x69, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0xe1, 0x66, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x08, 0x6e, 0x00, 0x00, 0x00, 0xe8,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x67, 0x1b, 0x69, 0x33, 0x6f, 0x37,
- 0x75, 0x44, 0x79, 0x48, 0x00, 0x06, 0x00, 0x00, 0xe1, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x59, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04,
- 0x6c, 0x09, 0x79, 0x0d, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x0b, 0x65, 0x00, 0x00, 0x60, 0x40, 0x09, 0x65, 0x00, 0xe2,
- 0x6e, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x00, 0x73, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe3,
- 0x6c, 0x00, 0x6e, 0x21, 0x73, 0x25, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xe4, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x70, 0x09, 0x00,
- 0x07, 0x40, 0x06, 0x61, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6c, 0x61,
- 0x74, 0x65, 0x00, 0x40, 0x0b, 0x6b, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe9, 0x61, 0x00, 0x64, 0x02, 0x65, 0x17, 0x69, 0x22, 0x6c,
- 0x36, 0x6f, 0x5c, 0x73, 0x62, 0x74, 0x71, 0x75, 0x84, 0x00, 0x06, 0xe3,
- 0x00, 0x00, 0x66, 0x02, 0x6e, 0x08, 0x00, 0x63, 0x41, 0x3c, 0x61, 0x63,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x6f, 0x0b,
- 0x00, 0x06, 0x40, 0x08, 0x72, 0x64, 0x00, 0x40, 0x59, 0x78, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x69, 0x00, 0x73, 0x05, 0x40, 0x08,
- 0x6e, 0x67, 0x00, 0x00, 0x00, 0x40, 0x07, 0x67, 0x6e, 0x61, 0x00, 0xe2,
- 0x68, 0x00, 0x74, 0x05, 0x40, 0x00, 0x69, 0x65, 0x00, 0x40, 0x59, 0x65,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x68, 0x06, 0x01, 0x3d, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x08, 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x73,
- 0x00, 0xe1, 0x62, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x38, 0x70,
- 0x3c, 0x73, 0x43, 0x00, 0xe4, 0xe2, 0x72, 0x00, 0x73, 0x17, 0xe1, 0x64,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x07, 0x00, 0xaf, 0x40, 0x09,
- 0x65, 0x72, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x00, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0xe2, 0x68,
- 0x00, 0x69, 0x06, 0x40, 0x06, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x08, 0x74,
- 0x65, 0x00, 0xef, 0x61, 0x00, 0x62, 0x06, 0x63, 0x0b, 0x64, 0x0f, 0x65,
- 0x62, 0x66, 0x8d, 0x67, 0x93, 0x68, 0x9c, 0x69, 0xa3, 0x6b, 0xb2, 0x6e,
- 0xb4, 0x6f, 0xbf, 0x73, 0xc4, 0x75, 0xc9, 0x79, 0xcd, 0x40, 0x09, 0x6e,
- 0x7a, 0x61, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x08, 0x65, 0x00,
- 0xe7, 0x00, 0x00, 0x61, 0x02, 0x68, 0x07, 0x69, 0x0f, 0x6d, 0x14, 0x73,
- 0x21, 0x77, 0x31, 0x00, 0x93, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x09,
- 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe6,
- 0x00, 0x00, 0x68, 0x02, 0x6c, 0x08, 0x72, 0x0e, 0x73, 0x10, 0x79, 0x18,
- 0x00, 0x7e, 0x40, 0xb1, 0x65, 0x61, 0x64, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x07, 0x40, 0x08, 0x68, 0x61, 0x6b, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x61, 0x72, 0x64, 0x00, 0x40, 0x09, 0x69, 0x72, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x93, 0x00, 0x09, 0x40, 0x07, 0x6f,
- 0x6d, 0x69, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x06, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x6f, 0x00, 0x01, 0x3e, 0xe2, 0x65, 0x00,
- 0x79, 0x04, 0x40, 0x09, 0x74, 0x00, 0x00, 0x60, 0x40, 0x09, 0x62, 0x6f,
- 0x00, 0x40, 0x07, 0x61, 0x69, 0x00, 0x40, 0x09, 0x73, 0x00, 0x00, 0x96,
- 0xfd, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x64, 0x0b, 0x00, 0x67, 0x10,
- 0x00, 0x68, 0x42, 0x00, 0x6b, 0x47, 0x00, 0x6c, 0x1c, 0x01, 0x6d, 0x1e,
- 0x01, 0x6e, 0x33, 0x01, 0x72, 0x60, 0x01, 0x73, 0x7a, 0x01, 0x74, 0x88,
- 0x01, 0x7a, 0x03, 0x02, 0x01, 0x3f, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x93, 0x00, 0x06, 0x40, 0x09, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x17, 0xe2, 0x72, 0x00, 0x79, 0x02, 0x00, 0x08, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x07, 0x00, 0xb2,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x00, 0x40, 0x59,
- 0x6f, 0x6f, 0x00, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x63, 0x21, 0x65, 0x27,
- 0x69, 0x2c, 0x6b, 0x3d, 0x6c, 0x54, 0x6d, 0x59, 0x70, 0x7c, 0x73, 0x83,
- 0x77, 0xb8, 0x01, 0x28, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x06, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40,
- 0x09, 0x61, 0x73, 0x65, 0x00, 0x40, 0x09, 0x6e, 0x64, 0x00, 0xe3, 0x65,
- 0x00, 0x6e, 0x02, 0x73, 0x06, 0x00, 0x09, 0x40, 0x07, 0x67, 0x00, 0x40,
- 0x00, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x70, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x65, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x17,
- 0xe2, 0x6b, 0x00, 0x72, 0x0e, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x2c, 0x6b, 0x00, 0x40,
- 0x06, 0x62, 0x69, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x6c, 0x61, 0x74, 0x65,
- 0x00, 0xe3, 0x65, 0x00, 0x68, 0x07, 0x74, 0x1f, 0x40, 0x09, 0x6c, 0x6c,
- 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x0f, 0xe1, 0x6c, 0x00, 0xe2,
- 0x66, 0x00, 0x76, 0x02, 0x00, 0x07, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40,
- 0x06, 0x70, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x08, 0x6c, 0x6c,
- 0x00, 0x40, 0x09, 0x72, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x6d, 0x00,
- 0x00, 0x09, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x65, 0x07, 0x00, 0xfa, 0x40,
- 0x09, 0x6f, 0x78, 0x00, 0x40, 0x55, 0x72, 0x61, 0x6e, 0x67, 0x00, 0xe3,
- 0x00, 0x00, 0x64, 0x02, 0x69, 0x21, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe2,
- 0x63, 0x00, 0x67, 0x05, 0x40, 0x07, 0x6b, 0x73, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0xa5, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00,
- 0xe8, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x65, 0x0d, 0x68, 0x11, 0x6c,
- 0x1a, 0x73, 0x47, 0x79, 0x68, 0x01, 0x40, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x06, 0x6c, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05,
- 0x40, 0x08, 0x63, 0x65, 0x00, 0xe2, 0x67, 0x00, 0x73, 0x1a, 0xe2, 0x00,
- 0x00, 0x67, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x00, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x60, 0xe2, 0x00, 0x00, 0x70, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe9, 0x61, 0x00, 0x64, 0x04, 0x65, 0x27, 0x69,
- 0x3f, 0x6e, 0x44, 0x6f, 0x4d, 0x72, 0x63, 0x73, 0x7b, 0x7a, 0x8a, 0x40,
- 0x07, 0x78, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x05, 0x40,
- 0x09, 0x6c, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x59, 0xe2,
- 0x61, 0x00, 0x69, 0x05, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x6e,
- 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x68, 0x07, 0x72, 0x0d, 0x00,
- 0x7e, 0x40, 0x07, 0x6f, 0x6d, 0x00, 0x40, 0x08, 0x6f, 0x6c, 0x65, 0x00,
- 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x01, 0x41, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x07, 0xe1,
- 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x77, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x01, 0x42, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x05, 0x40, 0x07, 0x68, 0x74, 0x00,
- 0x40, 0x08, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x6f, 0x69, 0x00, 0xe3, 0x68,
- 0x00, 0x6f, 0x02, 0x73, 0x14, 0x00, 0x07, 0xe1, 0x6d, 0x00, 0xe3, 0x00,
- 0x00, 0x27, 0x02, 0x79, 0x06, 0x01, 0x43, 0x40, 0x00, 0x73, 0x00, 0x00,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x17, 0x01, 0x44, 0xe3, 0x6c,
- 0x00, 0x6e, 0x04, 0x73, 0x0a, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x00, 0xf4, 0xe7, 0x00, 0x00,
- 0x61, 0x02, 0x63, 0x20, 0x68, 0x2e, 0x6e, 0x4e, 0x74, 0x53, 0x75, 0x7c,
- 0x00, 0x08, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63,
- 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b,
- 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x01, 0x45, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x73, 0x09, 0x00, 0x2c, 0x40, 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe2,
- 0x6c, 0x00, 0x6f, 0x14, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02,
- 0x72, 0x08, 0x00, 0x7e, 0x40, 0x09, 0x65, 0x63, 0x6b, 0x00, 0x00, 0x07,
- 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x2c, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6e,
- 0x00, 0x73, 0x05, 0x40, 0x00, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x6d, 0x00,
- 0xfb, 0x64, 0x00, 0x00, 0x66, 0x06, 0x00, 0x67, 0x0d, 0x00, 0x69, 0x2a,
- 0x00, 0x6c, 0x42, 0x00, 0x6e, 0x59, 0x00, 0x71, 0xe5, 0x00, 0x72, 0xeb,
- 0x00, 0x73, 0x0c, 0x01, 0x74, 0x18, 0x01, 0x7a, 0x30, 0x01, 0x40, 0x06,
- 0x6f, 0x69, 0x72, 0x00, 0x40, 0x06, 0x66, 0x61, 0x6e, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x68, 0x0b, 0x40, 0x09, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c,
- 0x65, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x74, 0x04, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x09, 0x40, 0x06, 0x62, 0x61, 0x69, 0x73, 0x73, 0x65, 0x00,
- 0x40, 0x09, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0xe2, 0x73, 0x00, 0x76, 0x02, 0x00, 0x00, 0x40, 0x06, 0x61,
- 0x72, 0x64, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x21, 0x74, 0x50, 0xe3, 0x65,
- 0x00, 0x69, 0x09, 0x79, 0x18, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e,
- 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x07, 0x6c, 0x10, 0x01, 0x46, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe2,
- 0x6e, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x16, 0x79,
- 0x2c, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x66, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0x40,
- 0x06, 0x75, 0x65, 0x74, 0x00, 0xe2, 0x62, 0x00, 0x67, 0x05, 0x40, 0x06,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x00, 0x74, 0x72, 0x6f, 0x70, 0x68, 0x65, 0x64, 0x6f,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x08, 0x00, 0x09, 0x40,
- 0x06, 0x71, 0x75, 0x65, 0x00, 0x40, 0x09, 0x6e, 0x6e, 0x69, 0x65, 0x72,
- 0x65, 0x00, 0x40, 0x09, 0x6f, 0x75, 0x6b, 0x69, 0x00, 0xe2, 0x69, 0x00,
- 0x76, 0x05, 0x40, 0x06, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x65, 0x72, 0x00,
- 0xe7, 0x00, 0x00, 0x64, 0x02, 0x65, 0x1f, 0x6c, 0x2c, 0x6d, 0x5b, 0x73,
- 0x68, 0x77, 0x7a, 0x01, 0x05, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe3, 0x64,
- 0x00, 0x6c, 0x02, 0x72, 0x04, 0x00, 0x37, 0x00, 0x06, 0x00, 0x07, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x66, 0x15, 0x69, 0x1a, 0x00, 0xfe, 0xe2, 0x67,
- 0x00, 0x72, 0x0c, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x65, 0x64, 0x00, 0x00, 0x07, 0x40, 0x06, 0x75, 0x6c, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2,
- 0x70, 0x00, 0x74, 0x06, 0x40, 0x06, 0x72, 0x69, 0x74, 0x00, 0x40, 0x06,
- 0x72, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x77, 0x00, 0xe8, 0x00,
- 0x00, 0x63, 0x02, 0x65, 0x07, 0x69, 0x0b, 0x6c, 0x10, 0x72, 0x16, 0x77,
- 0x1c, 0x79, 0x22, 0x01, 0x47, 0x40, 0x06, 0x61, 0x72, 0x00, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65,
- 0x00, 0x40, 0x08, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64,
- 0x00, 0x00, 0xf3, 0xe6, 0x00, 0x00, 0x63, 0x02, 0x66, 0x08, 0x68, 0x10,
- 0x69, 0x16, 0x73, 0x29, 0x00, 0x06, 0x40, 0x93, 0x6f, 0x74, 0x74, 0x00,
- 0x40, 0x09, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x6f, 0x6f,
- 0x64, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x65,
- 0x6e, 0x62, 0x65, 0x72, 0x72, 0x79, 0x00, 0x40, 0x09, 0x6f, 0x00, 0xe2,
- 0x6d, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x61, 0x00, 0x00,
- 0x65, 0x69, 0x02, 0x69, 0x82, 0x04, 0x6f, 0xb9, 0x06, 0x72, 0x22, 0x09,
- 0x75, 0x24, 0x09, 0xff, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x64, 0x43,
- 0x00, 0x65, 0x5a, 0x00, 0x67, 0x5c, 0x00, 0x69, 0x88, 0x00, 0x6b, 0x24,
- 0x01, 0x6d, 0x3b, 0x01, 0x6e, 0x4a, 0x01, 0x73, 0x7e, 0x01, 0x74, 0xb9,
- 0x01, 0x76, 0xcd, 0x01, 0x77, 0xf5, 0x01, 0x79, 0x17, 0x02, 0x7a, 0x19,
- 0x02, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x6b, 0x17, 0x74, 0x38, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x72, 0x07, 0x00, 0xa5, 0x40, 0x09, 0x65, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x59, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x79, 0x07, 0x00, 0x06, 0x40, 0x08, 0x77, 0x6c, 0x00, 0x40, 0x00,
- 0x63, 0x61, 0x72, 0x64, 0x69, 0x61, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00,
- 0x67, 0x02, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x65, 0x10, 0x69, 0x19, 0xe2,
- 0x64, 0x00, 0x72, 0x07, 0x40, 0x06, 0x6f, 0x63, 0x69, 0x6f, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x64, 0x00, 0x6c, 0x0c, 0x6e, 0x11,
- 0x73, 0x8f, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x59, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x00, 0xe9, 0x00, 0x00, 0x63, 0x02,
- 0x69, 0x1a, 0x6c, 0x21, 0x70, 0x27, 0x73, 0x2e, 0x74, 0x46, 0x77, 0x4e,
- 0x79, 0x69, 0x00, 0x59, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x3b, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x77, 0x65, 0x72, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x65, 0x61, 0x73, 0x65, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x73, 0x00, 0x76, 0x0f, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3a, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x65, 0x00, 0x00,
- 0x96, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x82, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02,
- 0x64, 0x12, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x59, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x0b, 0x79, 0x10, 0x00, 0xc3, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x37, 0x00, 0x07, 0x40, 0x3a, 0x73, 0x68, 0x00, 0x00, 0xa1, 0xe2,
- 0x68, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x63, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x08,
- 0x79, 0x1e, 0x00, 0x09, 0x40, 0x09, 0x72, 0x69, 0x65, 0x00, 0xe3, 0x65,
- 0x00, 0x6c, 0x05, 0x6e, 0x09, 0x40, 0x09, 0x72, 0x65, 0x00, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe3, 0x00,
- 0x00, 0x74, 0x02, 0x77, 0x06, 0x00, 0x06, 0x40, 0xf3, 0x79, 0x00, 0x40,
- 0x06, 0x75, 0x72, 0x73, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x6f,
- 0x18, 0x75, 0x1a, 0x40, 0x07, 0x64, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x6e,
- 0x02, 0x72, 0x08, 0x01, 0x48, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0x00, 0x06, 0x40, 0x06, 0x72, 0x61, 0x00, 0xe2, 0x6c,
- 0x00, 0x6e, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x49, 0x40, 0x07,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0x01, 0x4a, 0xe2, 0x65,
- 0x00, 0x69, 0x18, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x0f, 0x01, 0x4b,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x4c, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x65, 0x72, 0x00, 0xf6, 0x61, 0x00, 0x00,
- 0x64, 0x73, 0x01, 0x65, 0x75, 0x01, 0x74, 0xb6, 0x01, 0x76, 0xbd, 0x01,
- 0x77, 0xec, 0x01, 0xf6, 0x63, 0x00, 0x00, 0x64, 0x04, 0x00, 0x6b, 0x55,
- 0x00, 0x6d, 0xd6, 0x00, 0x73, 0xd8, 0x00, 0x74, 0x13, 0x01, 0x40, 0x59,
- 0x68, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x63, 0x1a, 0x66, 0x21, 0x6c,
- 0x28, 0x74, 0x2e, 0x77, 0x3a, 0x01, 0x4d, 0xe2, 0x61, 0x00, 0x6f, 0x07,
- 0x40, 0x06, 0x73, 0x6b, 0x65, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x78, 0x05,
- 0x40, 0x06, 0x72, 0x64, 0x00, 0x00, 0x09, 0x40, 0x09, 0x72, 0x75, 0x6d,
- 0x62, 0x00, 0x40, 0x06, 0x72, 0x75, 0x69, 0x74, 0x00, 0x40, 0x09, 0x69,
- 0x6e, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x00, 0xeb,
- 0x00, 0x00, 0x61, 0x02, 0x64, 0x17, 0x65, 0x1d, 0x66, 0x21, 0x6e, 0x31,
- 0x6f, 0x37, 0x70, 0x3c, 0x74, 0x44, 0x75, 0x5f, 0x77, 0x63, 0x01, 0x4e,
- 0xe3, 0x62, 0x00, 0x67, 0x05, 0x77, 0x09, 0x40, 0x09, 0x6c, 0x65, 0x00,
- 0x40, 0x09, 0x65, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0x40, 0x09, 0x6f,
- 0x77, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x05,
- 0x40, 0x55, 0x73, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x74, 0x00, 0x40,
- 0x00, 0x65, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x75, 0x74, 0x00, 0x40, 0x00,
- 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x70,
- 0x00, 0x40, 0x06, 0x61, 0x74, 0x65, 0x72, 0x00, 0x00, 0x09, 0xe1, 0x74,
- 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x66, 0x08, 0x70, 0x16, 0x73, 0x1d,
- 0x77, 0x25, 0x00, 0x2c, 0x40, 0x09, 0x6f, 0x6e, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x3c, 0x64, 0x00,
- 0x40, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x00, 0x40, 0x06, 0x74, 0x72, 0x6f,
- 0x6b, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x6b, 0x00, 0xe1, 0x68, 0x00,
- 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x69, 0x12, 0x6c, 0x17, 0x73,
- 0x2d, 0x74, 0x2f, 0x79, 0x37, 0x01, 0x4f, 0x40, 0x3f, 0x6c, 0x79, 0x7a,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x40, 0x3b, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x00,
- 0x00, 0xf3, 0x00, 0x54, 0xe3, 0x63, 0x00, 0x64, 0x04, 0x7a, 0x16, 0x40,
- 0x09, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x50,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x53, 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x0c, 0x79, 0x1b, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x5e, 0x40,
- 0x06, 0x61, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0x40, 0x00, 0x68,
- 0x72, 0x65, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x1c, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe2, 0x61, 0x00, 0x74, 0x05, 0x40, 0x06, 0x72, 0x79, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x70, 0x0e, 0x00, 0xfe,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0x40, 0x06, 0x75, 0x62, 0x00, 0xfc, 0x62, 0x00, 0x00, 0x63, 0x13, 0x00,
- 0x64, 0x4e, 0x00, 0x65, 0xa5, 0x00, 0x67, 0xde, 0x00, 0x6c, 0x33, 0x01,
- 0x6d, 0x5d, 0x01, 0x6e, 0x8a, 0x01, 0x6f, 0xc2, 0x01, 0x71, 0xc8, 0x01,
- 0x73, 0xd0, 0x01, 0x74, 0xf4, 0x01, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x7e, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe1, 0x6b, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x69, 0x07, 0x6c,
- 0x0b, 0x77, 0x1f, 0x79, 0x25, 0x00, 0x2c, 0x40, 0x06, 0x61, 0x74, 0x00,
- 0x40, 0x08, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x04, 0x67, 0x1b, 0x6c, 0x3b, 0x40, 0x06, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x73, 0x09, 0x00, 0x06, 0x40, 0x06,
- 0x72, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x09, 0x6d, 0x61, 0x69, 0x64, 0x00,
- 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x68, 0x08, 0x77, 0x0e,
- 0x00, 0x5e, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x65, 0x61,
- 0x64, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x64, 0x02, 0x77, 0x04, 0x00, 0x5e, 0x00, 0x37, 0x40, 0x08,
- 0x61, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x72, 0x30, 0x00, 0x29,
- 0xe7, 0x00, 0x00, 0x27, 0x02, 0x63, 0x06, 0x65, 0x0c, 0x69, 0x10, 0x6c,
- 0x15, 0x6e, 0x19, 0x01, 0x51, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x61,
- 0x73, 0x65, 0x00, 0x40, 0x00, 0x72, 0x00, 0x41, 0x52, 0x6e, 0x67, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x68, 0x2a, 0x00, 0x09, 0xe2, 0x64, 0x00,
- 0x6e, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x65,
- 0x72, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x10, 0x73,
- 0x16, 0x01, 0x53, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01,
- 0x54, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x86, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02,
- 0x6c, 0x07, 0x6d, 0x0d, 0x73, 0x1b, 0x00, 0x09, 0x40, 0x00, 0x75, 0x6c,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x74,
- 0x6f, 0x6e, 0x65, 0x00, 0xe6, 0x64, 0x00, 0x65, 0x05, 0x67, 0x07, 0x69,
- 0x12, 0x6b, 0x19, 0x79, 0x29, 0x41, 0x3c, 0x6c, 0x65, 0x00, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x55, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0x06, 0x40, 0x07, 0x61, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x00, 0x00, 0xf4,
- 0x40, 0x06, 0x63, 0x68, 0x65, 0x00, 0x40, 0x09, 0x75, 0x65, 0x74, 0x74,
- 0x65, 0x00, 0xe2, 0x6b, 0x00, 0x74, 0x13, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x6e, 0x06, 0x01, 0x56, 0x40, 0x06, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x5e,
- 0x00, 0x60, 0xe2, 0x63, 0x00, 0x74, 0x06, 0x40, 0x07, 0x68, 0x65, 0x73,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x01, 0x57, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xfd, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x63, 0x77, 0x00, 0x67, 0x99, 0x00, 0x69, 0xa6, 0x00,
- 0x6b, 0xb4, 0x00, 0x6c, 0xe4, 0x00, 0x6d, 0xe9, 0x00, 0x6e, 0x00, 0x01,
- 0x6f, 0x5f, 0x01, 0x74, 0xac, 0x01, 0x75, 0xd8, 0x01, 0x77, 0xf1, 0x01,
- 0x01, 0x58, 0xe2, 0x63, 0x00, 0x64, 0x04, 0x40, 0x47, 0x68, 0x00, 0xe8,
- 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x65, 0x2b, 0x6c, 0x2f, 0x6d, 0x35,
- 0x6e, 0x3d, 0x73, 0x43, 0x01, 0x59, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x6c, 0x18, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x5a, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x68, 0x00, 0x41,
- 0x20, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x00, 0x69,
- 0x6e, 0x64, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3,
- 0x68, 0x00, 0x69, 0x06, 0x77, 0x0b, 0x40, 0x06, 0x65, 0x65, 0x74, 0x00,
- 0x40, 0x82, 0x64, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x64, 0x00, 0xe3,
- 0x61, 0x00, 0x63, 0x05, 0x68, 0x0b, 0x40, 0x5e, 0x64, 0x65, 0x00, 0x40,
- 0x07, 0x6f, 0x6c, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x06, 0x40, 0x06,
- 0x74, 0x74, 0x65, 0x00, 0x40, 0x09, 0x72, 0x65, 0x00, 0xe2, 0x61, 0x00,
- 0x75, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x1a, 0x00, 0x00,
- 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6e, 0x0b, 0x00, 0x3e, 0x40, 0x3b, 0x65,
- 0x61, 0x72, 0x74, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x2c, 0x40, 0x09, 0x67, 0x65, 0x00,
- 0x40, 0x08, 0x6c, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x64, 0x00, 0x6e,
- 0x0b, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x74, 0x3a, 0x7a, 0x54, 0xe3,
- 0x00, 0x00, 0x68, 0x02, 0x6f, 0x24, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x75,
- 0x19, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x74, 0x06, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x06, 0x40, 0x06, 0x75, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40, 0x09, 0x73, 0x00, 0x40,
- 0x5e, 0x65, 0x00, 0xe4, 0x63, 0x00, 0x64, 0x04, 0x6b, 0x2a, 0x6d, 0x36,
- 0x40, 0x09, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6d,
- 0x13, 0x79, 0x19, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x12, 0x67, 0x00, 0x40, 0x09,
- 0x61, 0x72, 0x65, 0x00, 0x01, 0x5c, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x2c, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x40, 0x09, 0x74, 0x69, 0x63, 0x6b, 0x00, 0xe1, 0x68, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x73, 0x20, 0x00, 0x13, 0xe2, 0x6c, 0x00, 0x72,
- 0x02, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6c, 0x08, 0x00, 0x12,
- 0x40, 0x09, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0xe2, 0x67, 0x00, 0x68, 0x0e, 0xe1, 0x68, 0x00,
- 0xe2, 0x61, 0x00, 0x74, 0x04, 0x40, 0x06, 0x6d, 0x00, 0x00, 0x00, 0x40,
- 0x06, 0x61, 0x68, 0x61, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6e, 0x08,
- 0x73, 0x3b, 0x00, 0x09, 0x41, 0x5d, 0x65, 0x61, 0x74, 0x00, 0xe6, 0x00,
- 0x00, 0x66, 0x02, 0x69, 0x09, 0x6e, 0x14, 0x6f, 0x1a, 0x73, 0x1f, 0x01,
- 0x5e, 0x40, 0x00, 0x69, 0x65, 0x6c, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x73,
- 0x02, 0x00, 0x09, 0x40, 0x00, 0x68, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0x40, 0x09, 0x74, 0x6f, 0x6e, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0x00, 0x00, 0xe4, 0x69, 0x00, 0x6e, 0x1e, 0x73, 0x39, 0x74, 0x79,
- 0xe3, 0x6e, 0x00, 0x73, 0x02, 0x74, 0x15, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x00, 0x7a, 0xe3, 0x63, 0x00, 0x65, 0x04, 0x74,
- 0x12, 0x40, 0x47, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x68, 0x00,
- 0x71, 0x28, 0xe4, 0x00, 0x00, 0x6f, 0x02, 0x73, 0x07, 0x77, 0x0f, 0x00,
- 0x47, 0x40, 0x06, 0x66, 0x66, 0x00, 0x40, 0x08, 0x74, 0x72, 0x6f, 0x6b,
- 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x04, 0x40, 0x07,
- 0x64, 0x00, 0x40, 0x07, 0x6b, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x5f, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x21, 0x69, 0x23, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40,
- 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xc1, 0x62, 0x19, 0x37, 0x00, 0x39, 0x00, 0x63, 0x00, 0x0c,
- 0x01, 0x00, 0x00, 0x4c, 0x01, 0x8d, 0x01, 0x00, 0x00, 0xd6, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x02, 0x6d, 0x03, 0xef, 0x03, 0x75, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x8d, 0x04, 0x32, 0x06, 0x47, 0x07, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x22, 0x08, 0x27, 0x08, 0x41, 0x08, 0x00, 0x00, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x6f, 0x18, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x0c, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x5e, 0x40,
- 0x07, 0x75, 0x6d, 0x00, 0x01, 0x60, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x63, 0x00, 0x6b, 0x08, 0x6f, 0x8c,
- 0x40, 0x93, 0x61, 0x6e, 0x65, 0x65, 0x72, 0x00, 0xea, 0x00, 0x00, 0x61,
- 0x02, 0x62, 0x08, 0x65, 0x0f, 0x6c, 0x24, 0x72, 0x36, 0x73, 0x3b, 0x74,
- 0x50, 0x77, 0x61, 0x79, 0x68, 0x00, 0x55, 0x40, 0x06, 0x72, 0x6f, 0x6f,
- 0x00, 0x40, 0x09, 0x6f, 0x61, 0x72, 0x64, 0x00, 0xe2, 0x74, 0x00, 0x79,
- 0x0c, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x93, 0x40, 0x09, 0x75, 0x6c,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x27,
- 0x02, 0x72, 0x06, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0x00, 0x09, 0x40,
- 0x07, 0x61, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x04, 0x6b, 0x09, 0x40,
- 0x09, 0x77, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x00, 0x40, 0x09, 0x69, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x06, 0x40, 0x00, 0x65, 0x74, 0x68, 0x00,
- 0x40, 0x20, 0x6f, 0x74, 0x68, 0x00, 0x40, 0x07, 0x68, 0x65, 0x61, 0x74,
- 0x00, 0x40, 0x06, 0x62, 0x61, 0x6c, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x67,
- 0x14, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x08, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x1c, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x09, 0x00, 0x3a, 0x40,
- 0x09, 0x69, 0x67, 0x61, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x93, 0x40, 0x00, 0x72, 0x79, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x66,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x13, 0x6f, 0x1c, 0x01, 0x61,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x2f, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x2c,
- 0x01, 0x62, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x07, 0x00, 0x06, 0x40, 0x07, 0x72, 0x79, 0x00, 0x40, 0x00,
- 0x73, 0x68, 0x00, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x62, 0x0c,
- 0x67, 0x12, 0x6c, 0x30, 0x00, 0xaa, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06,
- 0x62, 0x6f, 0x6f, 0x00, 0x40, 0x06, 0x65, 0x61, 0x72, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x10, 0x79, 0x15, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x01, 0x63,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2c, 0x00, 0x00, 0x41, 0x63, 0x6e,
- 0x67, 0x00, 0x01, 0x64, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x7e, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x18,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x75, 0x0b, 0x01, 0x65, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x70, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x66, 0x40, 0x00, 0x6e, 0x00, 0xf7,
- 0x62, 0x00, 0x00, 0x67, 0x0c, 0x00, 0x69, 0x15, 0x00, 0x6b, 0x2e, 0x00,
- 0x6c, 0x48, 0x00, 0x72, 0x4a, 0x01, 0x77, 0x50, 0x01, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x09, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x5e, 0x00, 0xf3, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x08, 0x40, 0x07, 0x72, 0x65, 0x78, 0x69, 0x61, 0x00, 0xe2, 0x61,
- 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x68, 0x02,
- 0x69, 0x08, 0x79, 0x0f, 0x00, 0x55, 0x40, 0x09, 0x65, 0x61, 0x64, 0x00,
- 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xec, 0x00, 0x00,
- 0x64, 0x02, 0x65, 0x2b, 0x66, 0x42, 0x68, 0x6e, 0x69, 0x95, 0x6f, 0xae,
- 0x70, 0xb3, 0x72, 0xb8, 0x73, 0xbe, 0x77, 0xe1, 0x79, 0xe7, 0x00, 0x55,
- 0xe1, 0x6f, 0x00, 0xe2, 0x67, 0x00, 0x7a, 0x15, 0xe2, 0x00, 0x00, 0x67,
- 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x70, 0x06, 0x00, 0x06, 0x40, 0x55, 0x6e, 0x00, 0x40, 0x7a, 0x72,
- 0x6f, 0x6f, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x22, 0xe2, 0x67, 0x00,
- 0x6e, 0x18, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x01, 0x67, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x63, 0x68, 0x00, 0x40, 0x09, 0x6f, 0x67, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x1d, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xb2, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x72, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x63, 0x6b, 0x00, 0x40, 0x06, 0x65,
- 0x6e, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0xcf,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x01, 0x68,
- 0x01, 0x69, 0x41, 0x68, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x68, 0x69, 0x70,
- 0x00, 0x00, 0x5e, 0x40, 0x09, 0x75, 0x73, 0x68, 0x00, 0x40, 0x09, 0x61,
- 0x72, 0x6b, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x66, 0x1e, 0x6d, 0x20,
- 0x70, 0x39, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40, 0x08, 0x67,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x72, 0x07, 0x01,
- 0x4b, 0x40, 0x06, 0x65, 0x65, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x0f, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe7,
- 0x00, 0x00, 0x65, 0x02, 0x68, 0x06, 0x69, 0x08, 0x6b, 0x0f, 0x74, 0x14,
- 0x79, 0x2d, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01,
- 0x0c, 0xe8, 0x00, 0x00, 0x63, 0x02, 0x64, 0x12, 0x67, 0x17, 0x69, 0x40,
- 0x6b, 0x45, 0x6e, 0x65, 0x74, 0x69, 0x00, 0x06, 0xe2, 0x68, 0x00, 0x6f,
- 0x09, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x47, 0x00, 0xf3, 0x00, 0x2c,
- 0x40, 0x5e, 0x6c, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08,
- 0x68, 0x0c, 0x6c, 0x12, 0x00, 0x55, 0x40, 0x09, 0x6c, 0x6f, 0x77, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x06,
- 0x6f, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x68, 0x0a,
- 0x75, 0x11, 0x01, 0x6a, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x6b, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x55, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0x00, 0x3b, 0xfe, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x64, 0x0d,
- 0x00, 0x65, 0x2d, 0x00, 0x67, 0x70, 0x00, 0x69, 0xcb, 0x00, 0x6b, 0xd0,
- 0x00, 0x6c, 0xd4, 0x00, 0x6e, 0xf5, 0x00, 0x70, 0x2f, 0x01, 0x71, 0x31,
- 0x01, 0x72, 0x35, 0x01, 0x73, 0x55, 0x01, 0x79, 0x78, 0x01, 0x00, 0x56,
- 0xe2, 0x6c, 0x00, 0x73, 0x04, 0x40, 0x5e, 0x65, 0x00, 0x00, 0x07, 0xe2,
- 0x65, 0x00, 0x6f, 0x16, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02,
- 0x73, 0x06, 0x01, 0x3d, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x6d,
- 0x65, 0x00, 0x40, 0x07, 0x63, 0x6b, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x75,
- 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x7a, 0x0d, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x0b, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x68, 0x0d, 0x6c, 0x1c, 0x6f,
- 0x3f, 0x75, 0x48, 0x00, 0xe6, 0xe2, 0x6f, 0x00, 0x72, 0x04, 0x40, 0x3a,
- 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x06, 0x00,
- 0x13, 0x40, 0x07, 0x72, 0x00, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1c,
- 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x70, 0x07, 0x79, 0x0e,
- 0x00, 0x09, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0x40, 0x00, 0x72, 0x6f, 0x6f,
- 0x66, 0x00, 0x00, 0x06, 0x00, 0x3a, 0x40, 0x06, 0x6d, 0x61, 0x73, 0x74,
- 0x65, 0x72, 0x00, 0x40, 0x06, 0x6e, 0x64, 0x79, 0x00, 0x40, 0x65, 0x61,
- 0x6c, 0x00, 0x40, 0x08, 0x61, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x06, 0x69, 0x0d, 0x79, 0x14, 0x00, 0xb2, 0x40, 0x07, 0x70, 0x00, 0x40,
- 0x82, 0x73, 0x71, 0x75, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x15, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c,
- 0x6f, 0x1d, 0x74, 0x2b, 0x01, 0x6c, 0x40, 0x06, 0x62, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6f, 0x00,
- 0x75, 0x05, 0x40, 0x09, 0x73, 0x65, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00,
- 0x00, 0x00, 0x55, 0x40, 0x08, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x55, 0x40, 0x09, 0x74, 0x6f, 0x00, 0xe2, 0x00, 0x00,
- 0x77, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40,
- 0x07, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x14, 0x74, 0x1a, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x72, 0x04, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x06, 0x00, 0x06, 0x40, 0x07, 0x74, 0x69, 0x73, 0x00,
- 0x01, 0x25, 0x00, 0xab, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x65, 0x0d, 0x67,
- 0x11, 0x68, 0x17, 0x69, 0x68, 0x6b, 0xb9, 0x6c, 0xc4, 0x73, 0xca, 0x74,
- 0xcc, 0x79, 0xe1, 0x00, 0x69, 0xe2, 0x6f, 0x00, 0x79, 0x04, 0x40, 0x06,
- 0x79, 0x00, 0x00, 0x06, 0x40, 0x00, 0x64, 0x00, 0x40, 0x09, 0x69, 0x72,
- 0x6c, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6d, 0x15, 0x77,
- 0x2b, 0x79, 0x42, 0x01, 0x6d, 0x40, 0x93, 0x6c, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x65, 0x0d, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00, 0x01, 0x15, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x41, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x6c, 0x02,
- 0x6d, 0x08, 0x70, 0x15, 0x77, 0x1d, 0x00, 0x09, 0x40, 0x00, 0x69, 0x6b,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x4c, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x08, 0x6f, 0x61, 0x64,
- 0x00, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x79, 0x0a,
- 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x40, 0x5e, 0x65, 0x00, 0x01, 0x6e,
- 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6e, 0x08, 0x77, 0x0e, 0x01, 0x6f, 0x40,
- 0x06, 0x6f, 0x64, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x6f, 0x72, 0x6b, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x63, 0x07,
- 0x6c, 0x1d, 0x74, 0x22, 0x01, 0x70, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x71, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2f, 0x00, 0x06, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x70, 0x6f, 0x75, 0x72,
- 0x99, 0x79, 0x9f, 0x00, 0xfe, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04,
- 0x00, 0x06, 0x00, 0x77, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x66,
- 0x17, 0x6d, 0x3d, 0x6e, 0x43, 0x73, 0x48, 0x79, 0x50, 0x00, 0x2f, 0x40,
- 0x09, 0x61, 0x6c, 0x6c, 0x00, 0xe2, 0x72, 0x00, 0x75, 0x06, 0x40, 0x00,
- 0x65, 0x61, 0x6d, 0x00, 0x40, 0x06, 0x70, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x04, 0x6c, 0x1b, 0x40, 0x07, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x00, 0x07, 0x40, 0xa1, 0x79, 0x00, 0x40, 0x07,
- 0x69, 0x6c, 0x6b, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0x40, 0x07, 0x63,
- 0x6f, 0x74, 0x63, 0x68, 0x00, 0x01, 0x72, 0x40, 0x77, 0x6e, 0x67, 0x00,
- 0xe2, 0x63, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x6b, 0x00, 0xe4, 0x00, 0x00,
- 0x27, 0x02, 0x68, 0x06, 0x77, 0x0c, 0x01, 0x73, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x5e, 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x64, 0x00,
- 0x40, 0x47, 0x65, 0x73, 0x73, 0x00, 0x00, 0x08, 0x40, 0x00, 0x6f, 0x6d,
- 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x6f, 0x0c, 0x01, 0x74,
- 0x40, 0x06, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06,
- 0x75, 0x74, 0x00, 0xe1, 0x7a, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x07, 0x6b, 0x0b, 0x77, 0x11, 0x00, 0xe7, 0x40, 0x09, 0x72, 0x64, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x69, 0x6c, 0x6c, 0x00, 0x40, 0x06,
- 0x6f, 0x72, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xea, 0x00, 0x00, 0x65, 0x02, 0x67, 0x04, 0x6c, 0x0a, 0x70, 0x18,
- 0x72, 0x41, 0x73, 0x4d, 0x74, 0x56, 0x77, 0x5a, 0x7a, 0x68, 0x00, 0x07,
- 0x00, 0x06, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x04, 0x40, 0x06, 0x77, 0x00, 0x40, 0x06, 0x6e, 0x65, 0x00, 0xe3, 0x61,
- 0x00, 0x6c, 0x15, 0x72, 0x1a, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x59,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0x40, 0x07, 0x61, 0x79, 0x00, 0x40, 0x09, 0x6f, 0x64, 0x75,
- 0x63, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x08, 0x40, 0x06,
- 0x61, 0x64, 0x00, 0x40, 0x09, 0x74, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x00,
- 0x40, 0x09, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x74, 0x69,
- 0x6e, 0x65, 0x00, 0xc1, 0x44, 0x37, 0x73, 0x00, 0x75, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x07, 0x17,
- 0x00, 0x00, 0x09, 0x17, 0xbb, 0x1b, 0xbd, 0x1b, 0xbf, 0x1b, 0x68, 0x2c,
- 0x00, 0x00, 0x04, 0x30, 0x06, 0x30, 0x04, 0x39, 0x06, 0x39, 0x10, 0x39,
- 0xd1, 0x6d, 0x00, 0x00, 0xde, 0x6d, 0x00, 0x00, 0x08, 0x79, 0x15, 0x79,
- 0x00, 0x00, 0xd6, 0x7e, 0x00, 0x00, 0xdf, 0x7e, 0x83, 0x80, 0x01, 0x75,
- 0x40, 0x00, 0x4e, 0x41, 0x00, 0xc1, 0x62, 0x18, 0x35, 0x00, 0x37, 0x00,
- 0x07, 0x01, 0x5b, 0x01, 0xe0, 0x01, 0xe7, 0x01, 0x25, 0x02, 0x57, 0x02,
- 0x5d, 0x02, 0x7b, 0x02, 0x9c, 0x02, 0xac, 0x02, 0x21, 0x05, 0x72, 0x06,
- 0x00, 0x00, 0x6d, 0x09, 0x00, 0x00, 0x69, 0x0b, 0xb6, 0x10, 0x56, 0x12,
- 0x12, 0x15, 0xf2, 0x15, 0x77, 0x16, 0x00, 0x00, 0x79, 0x16, 0x00, 0x00,
- 0xe9, 0x00, 0x00, 0x61, 0x02, 0x62, 0x26, 0x64, 0x3f, 0x69, 0x47, 0x6c,
- 0x7d, 0x6f, 0x95, 0x72, 0xae, 0x73, 0xb6, 0x01, 0x24, 0xe3, 0x6c, 0x00,
- 0x6e, 0x14, 0x72, 0x18, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x07, 0x00,
- 0x09, 0x40, 0x00, 0x27, 0x73, 0x00, 0x40, 0x09, 0x65, 0x72, 0x6f, 0x00,
- 0x40, 0x06, 0x61, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe4, 0x61, 0x00,
- 0x65, 0x05, 0x69, 0x09, 0x79, 0x0e, 0x40, 0x09, 0x67, 0x65, 0x00, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06, 0x40, 0x06,
- 0x72, 0x69, 0x76, 0x65, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x6d, 0x02,
- 0x72, 0x16, 0x77, 0x1a, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x6b, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00,
- 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x67, 0x08, 0x00, 0x82,
- 0x41, 0x76, 0x61, 0x73, 0x74, 0x00, 0x40, 0x09, 0x72, 0x61, 0x6d, 0x00,
- 0xe2, 0x63, 0x00, 0x6f, 0x06, 0x40, 0x06, 0x68, 0x6f, 0x6e, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x05, 0x40, 0x07, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0x40, 0x06, 0x69, 0x6f, 0x6c, 0x65, 0x74, 0x00, 0x40, 0x06, 0x74,
- 0x61, 0x6e, 0x64, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x04, 0x6b, 0x17, 0x6f,
- 0x26, 0x74, 0x3e, 0x40, 0x09, 0x6f, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00,
- 0x00, 0x70, 0x02, 0x74, 0x07, 0x00, 0x82, 0x40, 0x06, 0x6f, 0x74, 0x00,
- 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x05, 0x40, 0x00,
- 0x75, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x75, 0x02, 0x00, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x64, 0x17, 0x65,
- 0x39, 0x67, 0x4d, 0x6d, 0x59, 0x72, 0x5f, 0x75, 0x63, 0x00, 0x06, 0xe1,
- 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x17, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0xb2, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0d, 0xe2,
- 0x63, 0x00, 0x7a, 0x04, 0x40, 0x1a, 0x65, 0x00, 0x40, 0x06, 0x61, 0x00,
- 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f,
- 0x00, 0x07, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x09, 0x65, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x06, 0x73, 0x75, 0x72, 0x61, 0x00,
- 0xe3, 0x65, 0x00, 0x66, 0x18, 0x74, 0x32, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x09, 0x72, 0x69, 0x61,
- 0x00, 0x40, 0x08, 0x65, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xaa, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x06, 0x40, 0x00, 0x74, 0x65, 0x64, 0x00, 0x00, 0x07, 0x40, 0x09, 0x61,
- 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x25, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x5e, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x0b, 0x6e,
- 0x0f, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08,
- 0x75, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x74, 0x00, 0xe4, 0x6d,
- 0x00, 0x72, 0x05, 0x73, 0x09, 0x74, 0x0f, 0x40, 0x09, 0x61, 0x6e, 0x00,
- 0x40, 0x09, 0x6e, 0x00, 0x40, 0x06, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x69, 0x66, 0x66, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x01, 0x77, 0x40, 0x07,
- 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x5e, 0x40,
- 0x06, 0x61, 0x6c, 0x6b, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x63, 0x36, 0x00, 0x64, 0xb6, 0x00, 0x65, 0xbc, 0x00, 0x66, 0xd1, 0x00,
- 0x69, 0xde, 0x00, 0x6b, 0x55, 0x01, 0x6c, 0x57, 0x01, 0x6d, 0xe5, 0x01,
- 0x6f, 0xf2, 0x01, 0x75, 0x08, 0x02, 0x76, 0x3a, 0x02, 0x79, 0x3e, 0x02,
- 0x00, 0x00, 0xe2, 0x62, 0x00, 0x6d, 0x10, 0xe2, 0x61, 0x00, 0x6f, 0x05,
- 0x40, 0x09, 0x73, 0x68, 0x00, 0x40, 0x06, 0x6f, 0x73, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x05, 0x40, 0x06, 0x72, 0x69, 0x00, 0xe2, 0x6e, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x05, 0x40,
- 0x3b, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x69, 0x08, 0x75,
- 0x3e, 0x40, 0x00, 0x72, 0x65, 0x6f, 0x75, 0x73, 0x00, 0xe5, 0x66, 0x00,
- 0x6d, 0x19, 0x6e, 0x1f, 0x74, 0x23, 0x75, 0x27, 0xe3, 0x65, 0x00, 0x69,
- 0x07, 0x79, 0x10, 0x40, 0x00, 0x72, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x07,
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x42, 0x40, 0x5e, 0x69,
- 0x6e, 0x65, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x07, 0x6d, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x2b, 0x75,
- 0x2d, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x54, 0x6c, 0x65, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x09, 0x6f, 0x16, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x01,
- 0x78, 0x00, 0x3b, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00,
- 0x40, 0x75, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x06, 0x65, 0x72, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x55, 0x72, 0x00, 0x40,
- 0x00, 0x72, 0x27, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6b, 0x69, 0x6e, 0x00, 0xe5, 0x62, 0x00, 0x63, 0x21, 0x66,
- 0x2f, 0x70, 0x38, 0x73, 0x51, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x39, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6e, 0x69, 0x75, 0x6d,
- 0x00, 0xe2, 0x65, 0x00, 0x68, 0x04, 0x40, 0x93, 0x72, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x73, 0x07, 0x00, 0x07, 0x40, 0x09, 0x74, 0x65, 0x00,
- 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x08, 0x00, 0x07, 0x00, 0x93, 0xe7, 0x00, 0x00, 0x61, 0x02,
- 0x62, 0x0e, 0x65, 0x14, 0x69, 0x1d, 0x6f, 0x51, 0x75, 0x7b, 0x01, 0x79,
- 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x65, 0x00,
- 0x40, 0x09, 0x61, 0x63, 0x6b, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x09, 0xe3, 0x67, 0x00, 0x6e, 0x24, 0x6f, 0x28, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x04, 0x79, 0x0f, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x63, 0x00,
- 0x73, 0x02, 0x00, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0x40, 0x06,
- 0x67, 0x00, 0x40, 0x09, 0x70, 0x65, 0x00, 0xe3, 0x73, 0x00, 0x75, 0x06,
- 0x77, 0x16, 0x40, 0x06, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x01, 0x7a, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x15, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x47, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x7b,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00,
- 0xe3, 0x63, 0x00, 0x65, 0x02, 0x66, 0x04, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x04,
- 0x40, 0x09, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1f, 0xe2, 0x61, 0x00,
- 0x6f, 0x15, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x00, 0x75, 0x73, 0x00, 0x00, 0x06, 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x70,
- 0x00, 0x78, 0x05, 0x40, 0x09, 0x73, 0x6f, 0x00, 0x00, 0x09, 0xf9, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x0c, 0x00, 0x63, 0x29, 0x00, 0x65,
- 0x31, 0x00, 0x69, 0x84, 0x00, 0x6f, 0x99, 0x00, 0x70, 0xb4, 0x00, 0x73,
- 0x2e, 0x01, 0x00, 0x06, 0x40, 0x07, 0x72, 0x61, 0x64, 0x65, 0x72, 0x69,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x72, 0x11, 0x40, 0x47, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06,
- 0x6d, 0x00, 0x40, 0x07, 0x69, 0x63, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x64,
- 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6f, 0x16, 0x72, 0x18,
- 0x00, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6c, 0x08, 0x00, 0x09, 0x40,
- 0x00, 0x61, 0x69, 0x72, 0x00, 0x40, 0x09, 0x69, 0x61, 0x00, 0x00, 0x09,
- 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x09,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6d, 0x00, 0x72, 0x0d, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00,
- 0x6b, 0x00, 0xe2, 0x6b, 0x00, 0x73, 0x0a, 0x40, 0x00, 0x6e, 0x69, 0x63,
- 0x6b, 0x65, 0x72, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5,
- 0x00, 0x07, 0xeb, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x3b, 0x66,
- 0x3f, 0x67, 0x45, 0x68, 0x4d, 0x69, 0x52, 0x73, 0x57, 0x75, 0x5d, 0x79,
- 0x61, 0x00, 0xff, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6e, 0x11,
- 0xe1, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01,
- 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06,
- 0x6c, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x06, 0x69, 0x72, 0x65, 0x00, 0x40, 0x06,
- 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x69, 0x74, 0x65, 0x00, 0x40, 0x09,
- 0x73, 0x00, 0x00, 0x60, 0x40, 0x06, 0x68, 0x61, 0x66, 0x74, 0x00, 0xfe,
- 0x00, 0x00, 0x00, 0x27, 0x02, 0x00, 0x61, 0x06, 0x00, 0x63, 0x39, 0x00,
- 0x64, 0x77, 0x00, 0x65, 0x0d, 0x01, 0x69, 0x1f, 0x01, 0x6b, 0x2e, 0x01,
- 0x6e, 0x40, 0x01, 0x6f, 0xc5, 0x01, 0x73, 0x11, 0x02, 0x74, 0x15, 0x02,
- 0x76, 0xab, 0x02, 0x79, 0xcb, 0x02, 0x01, 0x5b, 0x40, 0x00, 0x74, 0x00,
- 0xe4, 0x6c, 0x00, 0x70, 0x18, 0x72, 0x1c, 0x73, 0x25, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x09, 0x65,
- 0x00, 0xe2, 0x64, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06, 0x40, 0x07,
- 0x74, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x09, 0x6e, 0x00,
- 0xe2, 0x6c, 0x00, 0x72, 0x24, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06,
- 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x07, 0x69,
- 0x0b, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x75, 0x73, 0x00, 0xe5, 0x65, 0x00, 0x69, 0x17, 0x6c, 0x42,
- 0x6f, 0x79, 0x79, 0x7d, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x6d, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6e,
- 0x1b, 0x00, 0x3e, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x74, 0x06, 0x00, 0x00,
- 0x40, 0x06, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x72, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65,
- 0x00, 0xe6, 0x00, 0x00, 0x6c, 0x02, 0x70, 0x11, 0x72, 0x18, 0x73, 0x1a,
- 0x77, 0x21, 0x00, 0xa5, 0xe1, 0x69, 0x00, 0xe2, 0x67, 0x00, 0x74, 0x05,
- 0x40, 0x07, 0x68, 0x74, 0x00, 0x00, 0x00, 0x40, 0x07, 0x6f, 0x77, 0x65,
- 0x72, 0x00, 0x00, 0x07, 0x40, 0x09, 0x74, 0x69, 0x63, 0x6b, 0x00, 0x40,
- 0x06, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x66, 0x02, 0x00, 0xa1, 0x40, 0x00, 0x6c, 0x6f, 0x73, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x72, 0x09, 0x00, 0x06, 0x40, 0x09, 0x72, 0x61,
- 0x6b, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x09,
- 0x65, 0x00, 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x59, 0x40, 0x00, 0x75,
- 0x73, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x06, 0x69, 0x1a, 0x6f, 0x5d, 0x79,
- 0x78, 0x40, 0x09, 0x62, 0x69, 0x73, 0x00, 0xe3, 0x64, 0x00, 0x6c, 0x02,
- 0x72, 0x09, 0x00, 0x00, 0x40, 0x07, 0x6c, 0x6f, 0x6e, 0x69, 0x00, 0x40,
- 0x06, 0x79, 0x00, 0xe3, 0x62, 0x00, 0x6c, 0x2c, 0x6e, 0x30, 0xe1, 0x61,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2,
- 0x73, 0x00, 0x7a, 0x0c, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x37, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe2, 0x6e,
- 0x00, 0x74, 0x14, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x62, 0x07, 0x00, 0x59,
- 0x40, 0x82, 0x64, 0x65, 0x00, 0x40, 0x06, 0x61, 0x6c, 0x6c, 0x00, 0x00,
- 0x00, 0x01, 0x7c, 0xe5, 0x65, 0x00, 0x6c, 0x14, 0x6e, 0x18, 0x6f, 0x37,
- 0x70, 0x3d, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xb2, 0xe2, 0x6e, 0x00,
- 0x73, 0x04, 0x40, 0x00, 0x67, 0x00, 0x40, 0x06, 0x74, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe2, 0x63, 0x00,
- 0x7a, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x3a, 0x64,
- 0x6c, 0x65, 0x00, 0x40, 0xa1, 0x79, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe6,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x3f, 0x69, 0x5a, 0x6f, 0x6b,
- 0x01, 0x7d, 0x40, 0x00, 0x73, 0x00, 0xe4, 0x62, 0x00, 0x6c, 0x06, 0x6e,
- 0x0d, 0x74, 0x2c, 0x40, 0x00, 0x69, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x6f,
- 0x75, 0x70, 0x65, 0x00, 0xe1, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x09, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x52, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x05, 0x40,
- 0x09, 0x6c, 0x65, 0x00, 0x40, 0x55, 0x65, 0x76, 0x65, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x6e, 0x02, 0x72, 0x15, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x6d, 0x06, 0x01, 0x7e, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x00, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x73, 0x08, 0x00, 0x82, 0x40, 0x06, 0x61, 0x63,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72,
- 0x00, 0x41, 0x7f, 0x6f, 0x6e, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x65, 0x68, 0x00, 0x69, 0x79, 0x00, 0x6c, 0xf6, 0x00, 0x6f, 0xfb,
- 0x00, 0x70, 0x04, 0x01, 0x72, 0x1c, 0x01, 0x73, 0x3f, 0x01, 0x74, 0x77,
- 0x01, 0x01, 0x80, 0xe3, 0x62, 0x00, 0x63, 0x23, 0x72, 0x58, 0xe2, 0x69,
- 0x00, 0x6c, 0x15, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x53,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x54, 0xe1, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe4, 0x61, 0x00, 0x69, 0x06, 0x6f, 0x0b, 0x79, 0x0f, 0x40, 0x07, 0x6e,
- 0x63, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40, 0x06, 0x72, 0x00,
- 0x00, 0x53, 0x40, 0x55, 0x69, 0x73, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x72, 0x02, 0x73, 0x04, 0x00, 0x06, 0x00, 0xec, 0x40, 0x07, 0x6b, 0x69,
- 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x15, 0xe1, 0x6c, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x6f, 0x43, 0x75, 0x47, 0xe2,
- 0x6c, 0x00, 0x74, 0x38, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x81, 0xe2,
- 0x73, 0x00, 0x7a, 0x1e, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0xab,
- 0x41, 0x82, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x6c, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x01, 0x83, 0x40, 0x75, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x00, 0x09, 0xe3, 0x65, 0x00,
- 0x69, 0x04, 0x75, 0x09, 0x41, 0x84, 0x64, 0x00, 0x41, 0x84, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x63, 0x63, 0x69, 0x6e, 0x6f, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x69, 0x00, 0x74,
- 0x0e, 0x75, 0x1c, 0xe2, 0x63, 0x00, 0x7a, 0x05, 0x40, 0x06, 0x75, 0x6d,
- 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x06,
- 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x04, 0x69, 0x06, 0x40, 0x00, 0x72, 0x00, 0x00, 0x5e, 0x40,
- 0x3a, 0x7a, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x13, 0x6f,
- 0x52, 0x75, 0x56, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x2c, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x17, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x2c, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x15, 0x69, 0x17, 0xe1, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x00, 0x06, 0x40, 0x06, 0x74, 0x79,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0x41, 0x85, 0x72, 0x65, 0x00, 0xc1, 0x61,
- 0x19, 0x37, 0x00, 0x39, 0x00, 0x82, 0x00, 0x16, 0x01, 0x4b, 0x01, 0x09,
- 0x02, 0x98, 0x02, 0x9e, 0x02, 0xac, 0x02, 0xb1, 0x02, 0xfa, 0x02, 0x00,
- 0x00, 0x15, 0x03, 0x1b, 0x03, 0x21, 0x03, 0x7d, 0x03, 0xbe, 0x03, 0x00,
- 0x00, 0x2f, 0x04, 0x8c, 0x04, 0xa2, 0x04, 0x00, 0x00, 0x2c, 0x05, 0x00,
- 0x00, 0x00, 0x00, 0x46, 0x05, 0x01, 0x5b, 0xe6, 0x66, 0x00, 0x6d, 0x04,
- 0x70, 0x16, 0x74, 0x1c, 0x76, 0x1e, 0x77, 0x37, 0x40, 0x09, 0x65, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x40, 0x06, 0x61, 0x63, 0x65, 0x00,
- 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x06, 0x61, 0x72, 0x79, 0x00, 0x40,
- 0x06, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x79, 0x00, 0xe4, 0x69, 0x00, 0x6f,
- 0x0d, 0x73, 0x6b, 0x75, 0x6d, 0xe2, 0x64, 0x00, 0x6e, 0x04, 0x40, 0x06,
- 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe6, 0x68, 0x00, 0x6c, 0x09, 0x6e,
- 0x0e, 0x72, 0x40, 0x78, 0x48, 0x79, 0x4f, 0x40, 0x06, 0x79, 0x64, 0x72,
- 0x61, 0x74, 0x65, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x1a, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x74, 0x07, 0x40,
- 0x00, 0x65, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01,
- 0x86, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x66, 0x00, 0x7a, 0x08, 0x40,
- 0x00, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x0b, 0x65, 0x00, 0x40,
- 0x07, 0x75, 0x6e, 0x64, 0x75, 0x6d, 0x00, 0x40, 0x00, 0x79, 0x6c, 0x69,
- 0x63, 0x00, 0x00, 0x09, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x12, 0xe1,
- 0x63, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40,
- 0x00, 0x6c, 0x61, 0x72, 0x00, 0x40, 0x06, 0x65, 0x74, 0x6f, 0x72, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x09, 0x73, 0x73, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x67, 0x00, 0x6d, 0x1c, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0x40, 0x09, 0x61, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x62, 0x11,
- 0x65, 0x18, 0x68, 0x1c, 0x69, 0x24, 0x73, 0x98, 0x01, 0x87, 0xe1, 0x6d,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x00,
- 0x08, 0x40, 0x07, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x08, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0xe5, 0x61, 0x00, 0x65,
- 0x04, 0x67, 0x06, 0x6e, 0x0b, 0x6f, 0x10, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x08, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40, 0x56, 0x61, 0x6c, 0x00, 0xe6,
- 0x00, 0x00, 0x67, 0x02, 0x6c, 0x1b, 0x6d, 0x2d, 0x70, 0x37, 0x76, 0x42,
- 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x70,
- 0x02, 0x00, 0x06, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x00, 0x79,
- 0x6f, 0x70, 0x61, 0x74, 0x68, 0x79, 0x00, 0x40, 0x00, 0x75, 0x6c, 0x6d,
- 0x6f, 0x6e, 0x61, 0x72, 0x79, 0x00, 0x40, 0x00, 0x61, 0x73, 0x63, 0x75,
- 0x6c, 0x61, 0x72, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe6, 0x40,
- 0x07, 0x72, 0x00, 0xe9, 0x00, 0x00, 0x65, 0x02, 0x66, 0x1c, 0x67, 0x46,
- 0x6c, 0x4d, 0x72, 0x63, 0x73, 0x65, 0x74, 0x69, 0x77, 0x76, 0x00, 0x06,
- 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x72, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x55, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0xe2, 0x72, 0x00, 0x75, 0x05, 0x40, 0x00, 0x65, 0x65, 0x00,
- 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x10, 0x00, 0x3e,
- 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x69, 0x76,
- 0x65, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x07, 0x40, 0x47, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x09, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x72,
- 0x6e, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09,
- 0x6f, 0x70, 0x00, 0xe7, 0x62, 0x00, 0x63, 0x05, 0x65, 0x1d, 0x6c, 0x21,
- 0x6e, 0x27, 0x6f, 0x2b, 0x73, 0x30, 0x40, 0x06, 0x6f, 0x75, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x82, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x06, 0x6c, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x67,
- 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x70, 0x72, 0x6f,
- 0x64, 0x6f, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x88, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x61, 0x64,
- 0x00, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x1d,
- 0x69, 0x24, 0x79, 0x51, 0xe3, 0x67, 0x00, 0x6c, 0x04, 0x74, 0x10, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0x41, 0x89, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x6c,
- 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04,
- 0x40, 0x09, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02,
- 0x6f, 0x04, 0x00, 0x00, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x06, 0xe5, 0x62, 0x00, 0x6c, 0x02, 0x6d, 0x0d, 0x74, 0x0f,
- 0x75, 0x1d, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0x59, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x07,
- 0x6e, 0x65, 0x00, 0x40, 0x06, 0x64, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x06, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02,
- 0x72, 0x04, 0x00, 0x7e, 0x00, 0x06, 0x00, 0x07, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x06, 0x69, 0x51, 0x6f, 0x53, 0x75, 0x60, 0x00, 0xfa, 0x40,
- 0x09, 0x6c, 0x00, 0xe4, 0x6c, 0x00, 0x6e, 0x02, 0x72, 0x12, 0x74, 0x14,
- 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x55,
- 0x72, 0x00, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x69, 0x22, 0x00, 0x55, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x67, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe2, 0x6f, 0x00, 0x72,
- 0x04, 0x40, 0x2c, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x25, 0x79, 0x31, 0x40, 0x09,
- 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x12, 0x6f, 0x16, 0xe1, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x06, 0x40, 0x08,
- 0x61, 0x79, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x63, 0x07, 0x6f, 0x0c, 0x01, 0x8a, 0x40, 0x06,
- 0x6c, 0x6c, 0x00, 0x40, 0x08, 0x6f, 0x74, 0x00, 0xe2, 0x75, 0x00, 0x76,
- 0x04, 0x40, 0x00, 0x74, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe9, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x07, 0x68, 0x10, 0x69, 0x17, 0x6c, 0x2e, 0x6f, 0x34, 0x72,
- 0x69, 0x77, 0x70, 0x00, 0xfa, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe2, 0x6c,
- 0x00, 0x72, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x06, 0x6f, 0x72, 0x73,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x6f, 0x75, 0x73,
- 0x00, 0x40, 0x06, 0x6f, 0x61, 0x64, 0x00, 0xe3, 0x67, 0x00, 0x6e, 0x1d,
- 0x6f, 0x1f, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x08, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x00, 0x63, 0x00, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x09, 0x73, 0x74, 0x00,
- 0x40, 0x09, 0x69, 0x64, 0x67, 0x65, 0x00, 0x40, 0x59, 0x68, 0x65, 0x65,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x10, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x01, 0x8b, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x08, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x61, 0x74, 0x69, 0x64, 0x00, 0xf9,
- 0x61, 0x00, 0x00, 0x63, 0x0b, 0x00, 0x65, 0x1b, 0x00, 0x68, 0x62, 0x00,
- 0x69, 0x95, 0x00, 0x6b, 0xa1, 0x00, 0x73, 0xac, 0x00, 0x74, 0xdd, 0x00,
- 0x75, 0x52, 0x01, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x00, 0x40, 0x09,
- 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x04, 0x40, 0x5e,
- 0x65, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x64,
- 0x08, 0x68, 0x0a, 0x69, 0x12, 0x6c, 0x16, 0x6d, 0x1c, 0x77, 0x22, 0x01,
- 0x8c, 0x40, 0x08, 0x6f, 0x6f, 0x6b, 0x00, 0x00, 0x37, 0x40, 0x72, 0x61,
- 0x72, 0x64, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x09, 0x6f,
- 0x61, 0x64, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x27, 0x40, 0x07, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x65, 0x11,
- 0x69, 0x15, 0x6c, 0x1a, 0x6d, 0x20, 0x00, 0x59, 0xe2, 0x61, 0x00, 0x6f,
- 0x05, 0x40, 0x07, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x6f, 0x6b, 0x00, 0x40,
- 0x09, 0x77, 0x00, 0x40, 0x95, 0x65, 0x72, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x65, 0x72, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x67, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05,
- 0x69, 0x15, 0x6f, 0x19, 0x40, 0x06, 0x76, 0x61, 0x00, 0xe2, 0x72, 0x00,
- 0x74, 0x06, 0x40, 0x5e, 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x74, 0x65,
- 0x00, 0x40, 0x09, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x77, 0x04, 0x40, 0x06,
- 0x6b, 0x00, 0x40, 0x06, 0x61, 0x72, 0x79, 0x00, 0xe7, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x11, 0x69, 0x24, 0x6c, 0x45, 0x6f, 0x49, 0x72, 0x54, 0x01,
- 0x8d, 0xe2, 0x6e, 0x00, 0x77, 0x05, 0x40, 0x09, 0x65, 0x74, 0x00, 0x40,
- 0x09, 0x61, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x0a, 0x01,
- 0x8e, 0x40, 0x00, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x07, 0xe2,
- 0x67, 0x00, 0x6e, 0x18, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x75, 0x67, 0x00, 0x40, 0x82, 0x65, 0x00,
- 0xe2, 0x66, 0x00, 0x72, 0x04, 0x40, 0x06, 0x66, 0x00, 0x00, 0x09, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x51,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x16, 0xe1, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x08, 0x01, 0x8f, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72, 0x06, 0x00, 0x06, 0x40,
- 0x00, 0x63, 0x00, 0x40, 0x07, 0x79, 0x00, 0xff, 0x00, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x62, 0xdf, 0x00, 0x63, 0xee, 0x00, 0x65, 0x32, 0x01, 0x66,
- 0x9d, 0x01, 0x67, 0xa3, 0x01, 0x68, 0xa8, 0x01, 0x69, 0x08, 0x02, 0x6b,
- 0x0d, 0x02, 0x6c, 0x12, 0x02, 0x6e, 0x18, 0x02, 0x73, 0x39, 0x02, 0x74,
- 0x3f, 0x02, 0x77, 0x88, 0x02, 0x00, 0x06, 0xe8, 0x63, 0x00, 0x66, 0x24,
- 0x6c, 0x2c, 0x6d, 0x79, 0x70, 0x80, 0x72, 0x86, 0x73, 0x94, 0x74, 0xba,
- 0xe2, 0x6c, 0x00, 0x6f, 0x1a, 0xe1, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x09, 0x40,
- 0x00, 0x6c, 0x00, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x6d, 0x62, 0x00,
- 0x40, 0x09, 0x61, 0x6c, 0x71, 0x75, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x6f,
- 0x11, 0x70, 0x1f, 0x79, 0x23, 0xe1, 0x70, 0x00, 0xe2, 0x73, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x69, 0x63, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x05, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x06, 0x61, 0x00, 0xe3, 0x73, 0x00, 0x74, 0x11, 0x7a, 0x16, 0xe3,
- 0x65, 0x00, 0x69, 0x04, 0x74, 0x08, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x00, 0x09, 0x40, 0x07, 0x69, 0x63, 0x00, 0x40, 0x0b, 0x65,
- 0x00, 0x40, 0x06, 0x61, 0x72, 0x61, 0x6e, 0x00, 0x40, 0x59, 0x75, 0x6c,
- 0x74, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x05, 0x40, 0x09, 0x63, 0x74, 0x00,
- 0x40, 0x07, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x06,
- 0x61, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x05, 0x40, 0x95, 0x6c, 0x6c,
- 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x6d, 0x0b, 0x70, 0x11,
- 0x77, 0x23, 0x79, 0x29, 0x01, 0x90, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x68, 0x06, 0x40, 0x00, 0x6e, 0x6e, 0x79, 0x00, 0x40, 0x06, 0x72, 0x61,
- 0x73, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x64, 0x00, 0x00, 0xf3, 0xe3,
- 0x63, 0x00, 0x67, 0x18, 0x72, 0x3d, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0x00, 0x06, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x18, 0xe2, 0x63, 0x00, 0x7a, 0x05, 0x40, 0x3b,
- 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x00, 0x06, 0xe5, 0x00, 0x00, 0x63, 0x02,
- 0x65, 0x0a, 0x70, 0x0e, 0x77, 0x16, 0x01, 0x91, 0x40, 0x00, 0x6f, 0x72,
- 0x6e, 0x65, 0x72, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x69, 0x6c,
- 0x6c, 0x61, 0x72, 0x00, 0x40, 0x2c, 0x61, 0x75, 0x6c, 0x00, 0x40, 0x09,
- 0x69, 0x73, 0x68, 0x00, 0x40, 0x07, 0x75, 0x74, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x1a, 0x6f, 0x37, 0xe1, 0x72, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0d,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x06, 0x69, 0x63, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x06, 0x40,
- 0x06, 0x72, 0x61, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x3a, 0x7a, 0x65, 0x00, 0xe2,
- 0x64, 0x00, 0x6c, 0x0b, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x09, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x18, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00,
- 0x70, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x70, 0x00, 0x40, 0x08,
- 0x75, 0x69, 0x74, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x05, 0x69, 0x10, 0x6c,
- 0x25, 0x79, 0x3c, 0x40, 0x06, 0x69, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x40, 0x08, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x01, 0x92, 0x40, 0x06, 0x61, 0x6c, 0x6b, 0x00, 0xe6,
- 0x63, 0x00, 0x64, 0x05, 0x67, 0x0a, 0x6c, 0x0f, 0x73, 0x30, 0x74, 0x93,
- 0x40, 0x47, 0x75, 0x73, 0x00, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x37,
- 0x68, 0x74, 0x00, 0xe3, 0x64, 0x00, 0x69, 0x06, 0x6b, 0x0f, 0x40, 0x09,
- 0x72, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x21, 0x74, 0x42, 0xe2, 0x6c, 0x00, 0x74, 0x0c,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x79, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x08, 0x77,
- 0x13, 0x00, 0xa5, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x61, 0x79,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x08, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x17, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe1, 0x6f, 0x00, 0xe2, 0x6e,
- 0x00, 0x75, 0x0c, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x2c, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x5c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x2c,
- 0x69, 0x57, 0x6f, 0x77, 0xe1, 0x6c, 0x00, 0xe3, 0x63, 0x00, 0x69, 0x06,
- 0x72, 0x0b, 0x40, 0x09, 0x61, 0x64, 0x65, 0x00, 0x40, 0x56, 0x65, 0x72,
- 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6d, 0x06, 0x72, 0x13, 0x00, 0x7e, 0x40,
- 0x09, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x09, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x6c, 0x04,
- 0x6e, 0x0f, 0x74, 0x13, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x01, 0x93, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x67, 0x00, 0x41,
- 0x94, 0x79, 0x00, 0x40, 0x72, 0x72, 0x74, 0x00, 0x00, 0x2c, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x75, 0x08, 0x01, 0x82, 0x40, 0x07, 0x6e, 0x6e, 0x65,
- 0x00, 0x40, 0x09, 0x73, 0x65, 0x00, 0x00, 0x00, 0xfb, 0x61, 0x00, 0x00,
- 0x63, 0x2b, 0x00, 0x64, 0x3d, 0x00, 0x69, 0x57, 0x00, 0x6c, 0x72, 0x00,
- 0x6d, 0x56, 0x01, 0x6e, 0x78, 0x01, 0x70, 0xff, 0x02, 0x72, 0x07, 0x03,
- 0x73, 0x54, 0x04, 0x74, 0x88, 0x04, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x08, 0x01, 0x95, 0x40, 0x09, 0x69,
- 0x72, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x75, 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04,
- 0x69, 0x0d, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01,
- 0x96, 0x00, 0x09, 0x40, 0x06, 0x6c, 0x6c, 0x61, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x0c, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x67, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x08, 0x69, 0x6a, 0x6c, 0x7d, 0x40, 0x07, 0x6e,
- 0x64, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x62, 0x00, 0x72, 0x38, 0x73, 0x4c,
- 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x2f, 0x00, 0x08, 0xe2, 0x61, 0x00,
- 0x69, 0x23, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00,
- 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x0d, 0xe2, 0x61, 0x00, 0x74, 0x04, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x6d, 0x0b, 0x6f,
- 0x11, 0x70, 0x1f, 0x75, 0x26, 0x00, 0xb1, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x40, 0x06, 0x61, 0x74, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x70, 0x02, 0x00, 0x09, 0x40, 0x07, 0x68, 0x61, 0x6e, 0x65, 0x00,
- 0x40, 0x09, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x04, 0x6f, 0x12, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x69, 0x00, 0x73, 0x04, 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x14, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x75, 0x06, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0x40, 0x06, 0x65, 0x72, 0x79, 0x00, 0xf3, 0x6f,
- 0x00, 0x00, 0x73, 0x28, 0x00, 0x74, 0x7a, 0x00, 0xe2, 0x62, 0x00, 0x74,
- 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe3, 0x65, 0x00, 0x6f, 0x04, 0x75, 0x38, 0x40, 0x09, 0x72, 0x00, 0xe1,
- 0x72, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x73, 0x22, 0x00,
- 0x55, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00,
- 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x68,
- 0x69, 0x70, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x0c, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0x97, 0x00, 0x07, 0x00, 0x47, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x0f, 0x69, 0x4d, 0x72, 0x83, 0x75, 0xe7, 0x00,
- 0x0f, 0xe2, 0x75, 0x00, 0x76, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06,
- 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x1a, 0xe2, 0x61, 0x00, 0x6e, 0x0f,
- 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x61, 0x6e,
- 0x00, 0x00, 0x06, 0x40, 0x86, 0x69, 0x61, 0x6c, 0x00, 0xe4, 0x00, 0x00,
- 0x62, 0x02, 0x66, 0x09, 0x70, 0x0f, 0x00, 0x2f, 0x40, 0x06, 0x6f, 0x61,
- 0x72, 0x64, 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x00, 0x40, 0x09, 0x69,
- 0x65, 0x63, 0x65, 0x00, 0xe4, 0x67, 0x00, 0x6c, 0x11, 0x6d, 0x18, 0x70,
- 0x27, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x6d, 0x04,
- 0x40, 0x00, 0x65, 0x00, 0x00, 0x06, 0x40, 0x09, 0x69, 0x74, 0x65, 0x72,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40,
- 0x09, 0x65, 0x72, 0x00, 0x40, 0x06, 0x65, 0x64, 0x65, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x33, 0x6f, 0x5b, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x56, 0xe3, 0x73, 0x00, 0x74, 0x09, 0x7a, 0x0d, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x41, 0x52, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0x98, 0x00, 0x09, 0xe3, 0x66, 0x00, 0x70,
- 0x11, 0x73, 0x18, 0xe1, 0x75, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x5e, 0x40, 0x3b, 0x65, 0x74,
- 0x61, 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09,
- 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06,
- 0x6f, 0x6e, 0x00, 0x00, 0x06, 0x40, 0x00, 0x68, 0x61, 0x6c, 0x69, 0x63,
- 0x00, 0xf7, 0x61, 0x00, 0x00, 0x65, 0x1f, 0x00, 0x69, 0xa9, 0x00, 0x6d,
- 0xb6, 0x00, 0x74, 0xbb, 0x00, 0x75, 0x19, 0x01, 0x76, 0x20, 0x01, 0xe1,
- 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x10, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x06, 0x40, 0x06, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0x40, 0x09, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x62, 0x04, 0x6d,
- 0x49, 0x76, 0x79, 0x40, 0x09, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x13,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40,
- 0x00, 0x72, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x17,
- 0x75, 0x22, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x74, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x76, 0x61, 0x73, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x00,
- 0x40, 0x09, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6e,
- 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1c, 0xe2, 0x61,
- 0x00, 0x6f, 0x04, 0x40, 0x56, 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x36, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x06, 0x40, 0x09, 0x69, 0x73, 0x69, 0x61, 0x65, 0x00,
- 0xe2, 0x73, 0x00, 0x75, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x6d,
- 0x00, 0x40, 0x07, 0x65, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x13, 0x00, 0x08, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x36, 0x41, 0x99, 0x79, 0x00, 0xe2, 0x66, 0x00, 0x74,
- 0x2d, 0xe2, 0x69, 0x00, 0x79, 0x26, 0xe2, 0x61, 0x00, 0x63, 0x0f, 0xe1,
- 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x01, 0x9a, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x75,
- 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x53, 0x00, 0x00, 0x40, 0x07, 0x6c, 0x65, 0x61, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x73, 0x00, 0x00, 0x07, 0xe3, 0x61,
- 0x00, 0x69, 0x07, 0x73, 0x0c, 0x40, 0x09, 0x72, 0x65, 0x61, 0x6e, 0x00,
- 0x40, 0x07, 0x75, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x07, 0x70, 0x0c,
- 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x41, 0x9b, 0x6f, 0x6e, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x08, 0x74, 0x00, 0x40, 0x09, 0x6f,
- 0x6c, 0x00, 0x40, 0x09, 0x61, 0x63, 0x65, 0x61, 0x6e, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x94, 0x05,
- 0x67, 0x4b, 0x08, 0x69, 0x54, 0x08, 0x6c, 0xf4, 0x0b, 0x6d, 0x77, 0x0c,
- 0x6f, 0x79, 0x0c, 0x72, 0x40, 0x0e, 0x75, 0x3b, 0x0f, 0x79, 0x82, 0x10,
- 0x01, 0x9c, 0xfd, 0x64, 0x00, 0x00, 0x66, 0x02, 0x00, 0x67, 0x16, 0x00,
- 0x69, 0x1c, 0x00, 0x6c, 0x80, 0x00, 0x6d, 0xd6, 0x00, 0x6e, 0x39, 0x01,
- 0x6f, 0x34, 0x02, 0x70, 0x4e, 0x02, 0x72, 0xd6, 0x02, 0x73, 0x7a, 0x04,
- 0x74, 0xd0, 0x04, 0x75, 0x34, 0x05, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x66,
- 0x02, 0x00, 0x0b, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x59, 0x40, 0x09,
- 0x6e, 0x63, 0x68, 0x00, 0x40, 0x95, 0x72, 0x69, 0x6e, 0x00, 0xe3, 0x6e,
- 0x00, 0x72, 0x12, 0x73, 0x59, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x73, 0x06,
- 0x01, 0x34, 0x40, 0x00, 0x73, 0x00, 0x40, 0x55, 0x61, 0x77, 0x00, 0xe5,
- 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x08, 0x70, 0x21, 0x77, 0x29, 0x00, 0x59,
- 0x40, 0x09, 0x69, 0x66, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x06, 0x68,
- 0x69, 0x70, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x72, 0x73,
- 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0xe5, 0x63, 0x00, 0x65, 0x08, 0x69, 0x0c, 0x6b, 0x11, 0x6c,
- 0x2c, 0x40, 0x07, 0x65, 0x64, 0x6f, 0x6e, 0x79, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x40, 0x06, 0x63, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x69,
- 0x09, 0x79, 0x10, 0x00, 0x59, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64, 0x00,
- 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe2, 0x65, 0x00,
- 0x69, 0x16, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x00, 0x7e, 0x00, 0x37, 0x00, 0x07,
- 0x40, 0x07, 0x73, 0x00, 0xe4, 0x62, 0x00, 0x65, 0x22, 0x6f, 0x29, 0x70,
- 0x38, 0xe2, 0x65, 0x00, 0x72, 0x18, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x6d, 0x08, 0x00, 0xb1, 0x40, 0x09, 0x61, 0x69, 0x6e, 0x00,
- 0x40, 0x09, 0x61, 0x69, 0x64, 0x00, 0x40, 0x07, 0x61, 0x79, 0x00, 0x40,
- 0x06, 0x6c, 0x65, 0x6f, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6d, 0x04, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x09, 0x69, 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x08, 0x01, 0x9d, 0x40, 0x09, 0x67, 0x6e, 0x65, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x59, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00, 0xe6, 0x63, 0x00, 0x64, 0x44,
- 0x67, 0x55, 0x6e, 0xaa, 0x73, 0xc8, 0x74, 0xcd, 0xe4, 0x65, 0x00, 0x69,
- 0x2e, 0x72, 0x35, 0x79, 0x39, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x23,
- 0x00, 0x82, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x6f, 0x05, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40,
- 0x06, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0x01, 0x0c, 0xe2, 0x65, 0x00, 0x6c, 0x07, 0x40, 0x06, 0x6c,
- 0x69, 0x65, 0x72, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x4b, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x64, 0x25, 0x6c, 0x27, 0x6f,
- 0x36, 0x72, 0x3c, 0x00, 0xa5, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c,
- 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x00, 0x37, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40,
- 0x3b, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x76,
- 0x65, 0x72, 0x00, 0x00, 0x07, 0x40, 0x37, 0x6e, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x95, 0xe1,
- 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x12, 0x00, 0xc3, 0xe3, 0x72, 0x00, 0x75, 0x02, 0x79,
- 0x07, 0x00, 0x07, 0x40, 0x09, 0x73, 0x65, 0x00, 0x00, 0x06, 0x40, 0x09,
- 0x63, 0x6c, 0x65, 0x65, 0x72, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe7, 0x00, 0x00, 0x61,
- 0x02, 0x62, 0x18, 0x65, 0x1e, 0x6c, 0x48, 0x70, 0x62, 0x74, 0x74, 0x00,
- 0x06, 0xe2, 0x72, 0x00, 0x74, 0x06, 0x40, 0x06, 0x72, 0x61, 0x6c, 0x00,
- 0xe2, 0x69, 0x00, 0x74, 0x02, 0x00, 0x08, 0x40, 0x08, 0x69, 0x00, 0x40,
- 0x09, 0x6f, 0x6f, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x04, 0x72, 0x06,
- 0x40, 0x06, 0x75, 0x00, 0x00, 0x09, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x00, 0x55, 0x40, 0x07, 0x67,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x09, 0x00, 0x37, 0xe2,
- 0x61, 0x00, 0x65, 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x63, 0x02, 0x00, 0x09, 0x40, 0x06, 0x79, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x08, 0x40, 0x06, 0x65, 0x72, 0x00,
- 0xfe, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x5b, 0x00, 0x63, 0x62,
- 0x00, 0x64, 0x68, 0x00, 0x67, 0x76, 0x00, 0x69, 0x8e, 0x00, 0x6c, 0xe5,
- 0x00, 0x6d, 0x0f, 0x01, 0x72, 0x29, 0x01, 0x73, 0x37, 0x01, 0x74, 0x3c,
- 0x01, 0x77, 0x64, 0x01, 0x79, 0x77, 0x01, 0x00, 0x06, 0xe3, 0x62, 0x00,
- 0x63, 0x06, 0x64, 0x4e, 0x40, 0x09, 0x61, 0x6e, 0x63, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x66, 0x02,
- 0x69, 0x07, 0x6c, 0x30, 0x00, 0x09, 0x40, 0x00, 0x75, 0x6c, 0x00, 0xe2,
- 0x73, 0x00, 0x7a, 0x16, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x37, 0x6c, 0x6c,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0x40, 0x0b, 0x72, 0x6f, 0x69, 0x6c, 0x00, 0x40, 0x09, 0x6f,
- 0x61, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x06,
- 0x6e, 0x6e, 0x61, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x64, 0x08, 0x72, 0x0a, 0x01, 0x9e, 0x40, 0x77, 0x62, 0x6c, 0x65,
- 0x00, 0x00, 0x37, 0x00, 0x06, 0xe5, 0x6c, 0x00, 0x6e, 0x04, 0x6f, 0x0a,
- 0x73, 0x19, 0x74, 0x2b, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06,
- 0x40, 0x09, 0x65, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x09, 0x69, 0x63, 0x00, 0xe2,
- 0x61, 0x00, 0x79, 0x1a, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x37, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x69,
- 0x21, 0xe2, 0x64, 0x00, 0x74, 0x04, 0x40, 0x08, 0x79, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72, 0x07, 0x00,
- 0x06, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x08,
- 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x0b, 0x00,
- 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x72, 0x1a, 0x00, 0x59, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x37, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x01, 0x40,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x65, 0x75,
- 0x73, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x01, 0x3b,
- 0xe5, 0x65, 0x00, 0x6d, 0x09, 0x73, 0x0b, 0x74, 0x10, 0x75, 0x45, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07,
- 0x69, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x13, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0xd3, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x72, 0x40, 0x07,
- 0x73, 0x73, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x14, 0xe1, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x01, 0x18, 0x40, 0x06, 0x65, 0x6e,
- 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x62, 0x6c,
- 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x1a, 0x74, 0x20, 0x00,
- 0x06, 0xe2, 0x61, 0x00, 0x6c, 0x0c, 0xe1, 0x75, 0x00, 0xe2, 0x00, 0x00,
- 0x78, 0x02, 0x00, 0x06, 0x00, 0x00, 0x40, 0x06, 0x61, 0x69, 0x6e, 0x65,
- 0x00, 0x40, 0x08, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x1d,
- 0x79, 0x32, 0xe3, 0x64, 0x00, 0x6c, 0x02, 0x72, 0x04, 0x00, 0x00, 0x00,
- 0x09, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x65, 0x07, 0x00, 0xfe, 0x40, 0x09,
- 0x6f, 0x78, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x01, 0x92, 0xe2, 0x66, 0x00, 0x76, 0x07, 0x40,
- 0x59, 0x66, 0x65, 0x75, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xfb, 0x61, 0x00, 0x00, 0x63, 0x30, 0x00, 0x64, 0xa0, 0x00, 0x65, 0xa6,
- 0x00, 0x66, 0x92, 0x01, 0x6d, 0x94, 0x01, 0x6e, 0xe5, 0x01, 0x72, 0xec,
- 0x01, 0x73, 0x21, 0x02, 0x76, 0x65, 0x02, 0x77, 0x7d, 0x02, 0xe2, 0x70,
- 0x00, 0x74, 0x20, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x6f, 0x0c,
- 0x73, 0x0e, 0x01, 0x9f, 0x41, 0x20, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x40, 0x09, 0x6b, 0x61, 0x74, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6b,
- 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x65, 0x10, 0x6c, 0x29, 0x6d, 0x2f,
- 0x6f, 0x35, 0x70, 0x42, 0x72, 0x49, 0x73, 0x4f, 0x75, 0x54, 0x00, 0xc7,
- 0xe1, 0x6f, 0x00, 0xe2, 0x6f, 0x00, 0x78, 0x04, 0x40, 0x06, 0x6b, 0x00,
- 0x00, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0xe3, 0x00, 0x00,
- 0x62, 0x02, 0x73, 0x09, 0x00, 0x55, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64,
- 0x00, 0x00, 0x07, 0x40, 0x09, 0x69, 0x73, 0x74, 0x00, 0x40, 0x82, 0x61,
- 0x74, 0x65, 0x00, 0xe2, 0x66, 0x00, 0x75, 0x04, 0x40, 0x06, 0x66, 0x00,
- 0x40, 0x06, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0x40,
- 0x09, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x00, 0x75, 0x6d, 0x00, 0x40, 0x09,
- 0x70, 0x00, 0x40, 0x07, 0x64, 0x61, 0x72, 0x00, 0xe5, 0x6b, 0x00, 0x70,
- 0x22, 0x72, 0x24, 0x73, 0x8d, 0x74, 0xd2, 0xe4, 0x00, 0x00, 0x62, 0x02,
- 0x69, 0x08, 0x79, 0x17, 0x00, 0x59, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x92, 0x00, 0x59, 0xe6, 0x00, 0x00, 0x65, 0x02,
- 0x66, 0x06, 0x69, 0x29, 0x6c, 0x3c, 0x79, 0x5a, 0x00, 0xc3, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6c,
- 0x02, 0x6e, 0x10, 0x00, 0x3e, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x04, 0x6f, 0x0a, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x73, 0x06, 0x40, 0x06, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x92, 0xe3, 0x65, 0x00, 0x69, 0x35, 0x79, 0x3c, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x63, 0x14, 0x70, 0x24, 0x00, 0x82, 0xe2, 0x6f,
- 0x00, 0x75, 0x06, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00, 0x40, 0x06, 0x72,
- 0x67, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x05, 0x40, 0x06, 0x6b,
- 0x65, 0x00, 0x40, 0x07, 0x6f, 0x74, 0x68, 0x00, 0x40, 0x07, 0x61, 0x72,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01,
- 0x92, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x1e, 0x75, 0x42, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x56,
- 0x61, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x07,
- 0x40, 0x00, 0x75, 0x74, 0x69, 0x63, 0x00, 0x00, 0x07, 0x40, 0x07, 0x72,
- 0x67, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0xe6, 0x69,
- 0x00, 0x6f, 0x05, 0x72, 0x0a, 0x74, 0x0e, 0x75, 0x10, 0x76, 0x23, 0x40,
- 0x3a, 0x73, 0x68, 0x00, 0x40, 0x09, 0x6f, 0x74, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0x00, 0x07, 0xe1, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe2, 0x63, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x69, 0x6c, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x1d, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x6d, 0x09, 0x00, 0x07, 0x40, 0x09, 0x6f, 0x61, 0x72, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x66, 0x0b, 0x6e, 0x10, 0x79, 0x15,
- 0x00, 0xb2, 0x40, 0x06, 0x72, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40,
- 0x06, 0x75, 0x6c, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0x00, 0x60, 0xe3,
- 0x61, 0x00, 0x69, 0x07, 0x72, 0x0c, 0x40, 0x06, 0x6c, 0x69, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x6f, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x79, 0x0d, 0x00, 0xfa, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x61, 0x16, 0x31,
- 0x00, 0x33, 0x00, 0x00, 0x00, 0x3d, 0x00, 0xba, 0x00, 0xc6, 0x00, 0xed,
- 0x00, 0x02, 0x01, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
- 0x01, 0xef, 0x01, 0x29, 0x02, 0x00, 0x00, 0x89, 0x02, 0x00, 0x00, 0xc7,
- 0x02, 0x1a, 0x03, 0x2b, 0x03, 0x00, 0x00, 0x75, 0x03, 0x00, 0x06, 0x40,
- 0x07, 0x72, 0x6f, 0x73, 0x63, 0x75, 0x72, 0x6f, 0x00, 0xe7, 0x00, 0x00,
- 0x61, 0x02, 0x68, 0x13, 0x6b, 0x17, 0x6c, 0x5f, 0x6e, 0x63, 0x6f, 0x69,
- 0x01, 0xa0, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x09, 0x40, 0x06, 0x79, 0x00, 0x40, 0x09, 0x69, 0x00, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x70, 0x32, 0x77, 0x37, 0x01, 0xa1,
- 0x40, 0x06, 0x64, 0x65, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe5, 0x00, 0x00,
- 0x66, 0x02, 0x68, 0x08, 0x70, 0x11, 0x73, 0x16, 0x00, 0x2f, 0x40, 0x07,
- 0x65, 0x65, 0x64, 0x00, 0x40, 0x00, 0x65, 0x61, 0x72, 0x74, 0x65, 0x64,
- 0x00, 0x40, 0x07, 0x6f, 0x78, 0x00, 0x41, 0xa2, 0x68, 0x69, 0x74, 0x00,
- 0x40, 0x06, 0x65, 0x61, 0x00, 0x40, 0x07, 0x65, 0x65, 0x64, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x72,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0xe1, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x74, 0x07,
- 0x01, 0xa3, 0x40, 0x07, 0x6f, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x68, 0x69, 0x70, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x65,
- 0x72, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x65, 0x72, 0x00,
- 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x75, 0x61, 0x68, 0x75, 0x61,
- 0x00, 0xe4, 0x62, 0x00, 0x64, 0x07, 0x69, 0x9a, 0x6c, 0xa5, 0x40, 0x06,
- 0x6c, 0x61, 0x69, 0x6e, 0x00, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x63, 0x21,
- 0x68, 0x27, 0x69, 0x2d, 0x6c, 0x40, 0x6d, 0x5d, 0x70, 0x74, 0x72, 0x7b,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x08, 0x40, 0x07, 0x61, 0x72, 0x69,
- 0x6e, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x61,
- 0x72, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x64, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x13, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6b, 0x65, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x08, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0xad, 0x72, 0x6f,
- 0x6f, 0x66, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x6e, 0x15, 0x79, 0x1b, 0x01, 0xa4, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73,
- 0x00, 0x00, 0x3b, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe3,
- 0x65, 0x00, 0x6e, 0x20, 0x70, 0x25, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0xa5, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x04, 0x00, 0x07, 0x00, 0x09,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x00, 0x40, 0x09, 0x65, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x6e, 0x7a, 0x65, 0x65, 0x00, 0xeb, 0x00, 0x00,
- 0x61, 0x02, 0x63, 0x0f, 0x65, 0x17, 0x6b, 0x19, 0x6c, 0x1b, 0x6e, 0x21,
- 0x6f, 0x2f, 0x73, 0x31, 0x74, 0x38, 0x77, 0x44, 0x00, 0x06, 0xe2, 0x00,
- 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0x40,
- 0x09, 0x68, 0x69, 0x6c, 0x6c, 0x61, 0x00, 0x00, 0x09, 0x00, 0x59, 0x40,
- 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x09, 0x40, 0x09, 0x74,
- 0x72, 0x61, 0x70, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x07, 0x00, 0xf3, 0x40, 0x08, 0x61, 0x67, 0x00, 0xe5, 0x00, 0x00,
- 0x62, 0x02, 0x6d, 0x09, 0x6f, 0x0f, 0x70, 0x16, 0x00, 0x06, 0x40, 0x00,
- 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x06, 0x75, 0x6e, 0x6b, 0x00, 0x40,
- 0x08, 0x6c, 0x61, 0x74, 0x61, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79,
- 0x14, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x6e, 0x02, 0x00, 0x00, 0x40, 0x08, 0x67, 0x00, 0x00, 0x08, 0xe3,
- 0x6f, 0x00, 0x70, 0x37, 0x72, 0x47, 0xe2, 0x67, 0x00, 0x70, 0x08, 0x40,
- 0x07, 0x72, 0x61, 0x70, 0x68, 0x79, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x0f,
- 0xe1, 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74,
- 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x63, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x07, 0x00, 0x59, 0x40, 0x00,
- 0x6c, 0x79, 0x00, 0x00, 0x96, 0x40, 0x59, 0x75, 0x70, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40,
- 0x07, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x69, 0x20, 0x6f, 0x2f,
- 0x74, 0x35, 0x00, 0x06, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x00, 0x75, 0x73,
- 0x00, 0x40, 0x00, 0x73, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x72, 0x6c,
- 0x69, 0x6e, 0x67, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x20, 0x79, 0x22,
- 0xe1, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x13, 0xe1,
- 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0b,
- 0xe2, 0x61, 0x00, 0x6f, 0x18, 0xe1, 0x6d, 0x00, 0xe1, 0x79, 0x00, 0xe1,
- 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x09, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x64,
- 0x04, 0x69, 0x0a, 0x6f, 0x29, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x04, 0x40, 0x09, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x00,
- 0x00, 0x66, 0x02, 0x70, 0x19, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x0d,
- 0x40, 0x06, 0x75, 0x6f, 0x72, 0x6f, 0x63, 0x61, 0x72, 0x62, 0x6f, 0x6e,
- 0x00, 0x40, 0x93, 0x72, 0x6d, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x06, 0x40,
- 0x07, 0x79, 0x6c, 0x6c, 0x00, 0x40, 0x09, 0x61, 0x73, 0x74, 0x00, 0x00,
- 0x00, 0xfa, 0x63, 0x00, 0x00, 0x69, 0x33, 0x00, 0x6b, 0x52, 0x00, 0x6c,
- 0x68, 0x00, 0x6d, 0xa5, 0x00, 0x6f, 0xa9, 0x00, 0x70, 0xc5, 0x00, 0x72,
- 0x05, 0x01, 0x73, 0x90, 0x01, 0x77, 0x9c, 0x01, 0xe3, 0x00, 0x00, 0x6b,
- 0x02, 0x6f, 0x11, 0x00, 0x08, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x59,
- 0x40, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x00, 0xe2, 0x68, 0x00, 0x6c,
- 0x07, 0x40, 0x06, 0x6f, 0x6c, 0x69, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe2,
- 0x63, 0x00, 0x72, 0x04, 0x41, 0xa5, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x6d, 0x07, 0x00, 0x09, 0x40, 0x09, 0x6f, 0x79, 0x00, 0x40, 0x06,
- 0x61, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x72, 0x0a, 0x00, 0xa5, 0x40, 0x06, 0x68, 0x65, 0x72, 0x72,
- 0x79, 0x00, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x72, 0x1c,
- 0x73, 0x2b, 0xe1, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x08, 0x40, 0x00, 0x63, 0x74, 0x6f, 0x6d, 0x79, 0x00,
- 0x40, 0x00, 0x74, 0x69, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x04, 0x00, 0x07, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07, 0x74,
- 0x65, 0x72, 0x6f, 0x6c, 0x00, 0x40, 0xc3, 0x70, 0x00, 0xe1, 0x73, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x10, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xe5, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01,
- 0x92, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x70, 0x09, 0x73, 0x30, 0x00, 0x06,
- 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x79, 0x1e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x55, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x01, 0x92, 0x40, 0x06,
- 0x74, 0x69, 0x63, 0x6b, 0x00, 0xe7, 0x61, 0x00, 0x64, 0x0c, 0x65, 0x1e,
- 0x69, 0x5d, 0x6f, 0x64, 0x74, 0x69, 0x75, 0x78, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x86, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x04, 0x00, 0x09, 0x00,
- 0x07, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70,
- 0x00, 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x73,
- 0x16, 0x79, 0x18, 0x01, 0x54, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x06, 0x73, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x09, 0x69, 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x59, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x93, 0x40, 0x09, 0x65, 0x72, 0x00,
- 0xe3, 0x69, 0x00, 0x6f, 0x2c, 0x79, 0xdb, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x0f, 0x6f, 0x14,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x40, 0x40, 0x09,
- 0x6e, 0x67, 0x00, 0x40, 0x37, 0x61, 0x6e, 0x00, 0x40, 0x00, 0x6c, 0x6f,
- 0x67, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x49, 0xe4, 0x61, 0x00, 0x65,
- 0x25, 0x69, 0x27, 0x6f, 0x2c, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x14, 0xe2, 0x63, 0x00, 0x6e, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x40, 0x00, 0x67,
- 0x72, 0x61, 0x70, 0x68, 0x79, 0x00, 0x00, 0x82, 0x40, 0x07, 0x75, 0x6d,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe2, 0x69, 0x00,
- 0x6f, 0x1e, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x08,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe3, 0x67, 0x00, 0x6c,
- 0x15, 0x6d, 0x30, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2,
- 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x00, 0x06, 0x40, 0x06, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x69,
- 0x73, 0x00, 0x40, 0x09, 0x74, 0x68, 0x65, 0x6d, 0x75, 0x6d, 0x00, 0xf9,
- 0x62, 0x00, 0x00, 0x63, 0x15, 0x00, 0x66, 0x2b, 0x00, 0x67, 0x31, 0x00,
- 0x6b, 0x46, 0x00, 0x6d, 0x4b, 0x00, 0x6e, 0x78, 0x00, 0x72, 0x9b, 0x00,
- 0x74, 0x17, 0x01, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x06, 0xe2, 0x69,
- 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92,
- 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6c, 0x08, 0x00, 0x59,
- 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x82, 0x65, 0x00, 0x40, 0x00,
- 0x66, 0x65, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x09, 0x6b, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x70,
- 0x24, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x19, 0x40, 0x00,
- 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00,
- 0x96, 0x00, 0x09, 0xe3, 0x64, 0x00, 0x6b, 0x05, 0x74, 0x17, 0x40, 0x0b,
- 0x65, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x59,
- 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0x40, 0x72, 0x65,
- 0x72, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x50, 0x6e, 0x6a, 0xe1, 0x68, 0x00,
- 0xe5, 0x00, 0x00, 0x67, 0x02, 0x6d, 0x13, 0x77, 0x20, 0x79, 0x3c, 0x00,
- 0x09, 0xe1, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07,
- 0x40, 0x09, 0x72, 0x64, 0x65, 0x6e, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x06, 0x61, 0x72, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x6e, 0x02, 0x7a,
- 0x07, 0x00, 0x09, 0x40, 0x09, 0x65, 0x79, 0x00, 0x40, 0x07, 0x70, 0x61,
- 0x68, 0x00, 0x40, 0x07, 0x6d, 0x65, 0x00, 0xfb, 0x61, 0x00, 0x00, 0x63,
- 0x0e, 0x00, 0x64, 0x40, 0x00, 0x67, 0x51, 0x00, 0x6c, 0x6c, 0x00, 0x6e,
- 0x83, 0x00, 0x70, 0xf4, 0x00, 0x72, 0x08, 0x01, 0x73, 0xaf, 0x02, 0x74,
- 0xb6, 0x02, 0x76, 0x30, 0x03, 0xe2, 0x62, 0x00, 0x6f, 0x07, 0x40, 0x06,
- 0x61, 0x74, 0x74, 0x61, 0x00, 0x00, 0x08, 0xe2, 0x61, 0x00, 0x65, 0x1b,
- 0xe2, 0x64, 0x00, 0x74, 0x04, 0x40, 0x09, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x05, 0x40, 0x00, 0x65, 0x73,
- 0x00, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x08, 0x40, 0x00,
- 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x08, 0x00, 0x09, 0x40, 0x09, 0x74, 0x74, 0x65, 0x00, 0x40,
- 0x09, 0x6c, 0x6c, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x07, 0x40, 0x07,
- 0x6e, 0x74, 0x72, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe4, 0x63, 0x00, 0x64, 0x17, 0x65, 0x1c, 0x6e,
- 0x56, 0xe2, 0x68, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x59, 0x40, 0x06, 0x6e, 0x61, 0x00, 0x40, 0x06, 0x75, 0x72, 0x65, 0x00,
- 0x40, 0x59, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x69,
- 0x00, 0x6f, 0x04, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x04, 0x79, 0x08, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x63,
- 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x6d, 0x05, 0x40,
- 0x07, 0x61, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01,
- 0x98, 0x40, 0x00, 0x73, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00,
- 0x71, 0x76, 0x01, 0x72, 0x7b, 0x01, 0x00, 0x00, 0xf3, 0x61, 0x00, 0x00,
- 0x6c, 0x0d, 0x00, 0x75, 0x19, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x82, 0x00, 0x09, 0xf4, 0x69, 0x00, 0x00, 0x6c,
- 0x2d, 0x00, 0x6d, 0x5c, 0x00, 0x73, 0x42, 0x01, 0xe1, 0x74, 0x00, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x6f, 0x06, 0x72, 0x19, 0x79, 0x1d, 0x00, 0x55,
- 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74,
- 0x14, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0xe2, 0x74, 0x00, 0x7a,
- 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0xab, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0xe7, 0x63, 0x00, 0x66, 0x19, 0x6c, 0x3b, 0x6e,
- 0x56, 0x70, 0x74, 0x73, 0x7b, 0x76, 0xc2, 0xe1, 0x69, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x01,
- 0x26, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6c,
- 0x18, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6c,
- 0x00, 0x40, 0x09, 0x65, 0x78, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x76, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x45, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x6f, 0x6c, 0x61, 0x72, 0x00, 0xe3, 0x63,
- 0x00, 0x70, 0x16, 0x74, 0x2b, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x62, 0x00, 0x70, 0x04, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x09, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x82, 0x65, 0x00, 0x40, 0x3b, 0x69, 0x61, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3a, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x09, 0x40, 0x09, 0x75, 0x65,
- 0x00, 0xe3, 0x68, 0x00, 0x69, 0x12, 0x75, 0x14, 0xe1, 0x6f, 0x00, 0xe2,
- 0x73, 0x00, 0x74, 0x05, 0x40, 0x07, 0x69, 0x73, 0x00, 0x40, 0x06, 0x69,
- 0x63, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x09, 0x74, 0x65,
- 0x72, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x12, 0x69, 0x1d,
- 0x72, 0x41, 0x79, 0x60, 0x00, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x05, 0x40,
- 0x09, 0x65, 0x6c, 0x00, 0x40, 0x69, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x27, 0x02, 0x01, 0xa6, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x66, 0x00,
- 0x7a, 0x06, 0x40, 0x00, 0x69, 0x65, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x06, 0x00, 0x09, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe3, 0x69, 0x00,
- 0x6f, 0x04, 0x75, 0x14, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40, 0x07, 0x6c, 0x6c, 0x61, 0x00,
- 0x40, 0x09, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x69, 0x64, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x76, 0x3d,
- 0x40, 0x09, 0x74, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x09, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x36, 0xe3, 0x61, 0x00, 0x74, 0x04, 0x7a, 0x08, 0x40, 0x09, 0x6e, 0x00,
- 0x41, 0xa7, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x0b, 0x00,
- 0x37, 0x40, 0x07, 0x69, 0x65, 0x73, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x65, 0xe5, 0x02, 0x69, 0x42, 0x04, 0x6f, 0xf0,
- 0x05, 0x75, 0xf9, 0x07, 0x76, 0xb7, 0x08, 0x78, 0xc3, 0x08, 0x00, 0x00,
- 0xfe, 0x63, 0x00, 0x00, 0x64, 0x04, 0x00, 0x69, 0x11, 0x00, 0x6d, 0x56,
- 0x00, 0x6e, 0xb9, 0x00, 0x70, 0x24, 0x01, 0x71, 0x5b, 0x01, 0x72, 0x60,
- 0x01, 0x73, 0x9c, 0x01, 0x74, 0x43, 0x02, 0x75, 0x49, 0x02, 0x76, 0x77,
- 0x02, 0x77, 0x92, 0x02, 0x79, 0x9d, 0x02, 0x40, 0x59, 0x6b, 0x00, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x37, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00,
- 0xe2, 0x6d, 0x00, 0x72, 0x26, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06,
- 0x65, 0x14, 0x01, 0xa8, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x6e,
- 0x05, 0x40, 0x77, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x37, 0x01, 0xa9, 0xe1, 0x76, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x09, 0xe5, 0x00, 0x00,
- 0x62, 0x02, 0x6d, 0x1a, 0x6f, 0x3c, 0x70, 0x4b, 0x00, 0x06, 0xe2, 0x61,
- 0x00, 0x65, 0x05, 0x40, 0x09, 0x6b, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x04, 0x79, 0x19, 0x40, 0x00, 0x64, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40,
- 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x96, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x6f, 0x02, 0x00, 0x59, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x59, 0x40, 0x09, 0x6f, 0x77, 0x6e, 0x00,
- 0xe6, 0x00, 0x00, 0x64, 0x02, 0x67, 0x0b, 0x6b, 0x21, 0x6e, 0x23, 0x73,
- 0x39, 0x00, 0x06, 0x40, 0x3b, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0xc3, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x00, 0x59,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x77, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x70, 0x09, 0x74, 0x28, 0x00, 0x06, 0x40, 0x55,
- 0x6f, 0x61, 0x72, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x15, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x09,
- 0x40, 0x08, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x72, 0x61, 0x70, 0x00, 0x40, 0x09, 0x75, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x74, 0x00, 0xe4, 0x66, 0x00, 0x6e,
- 0x10, 0x6f, 0x22, 0x74, 0x26, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07,
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x01, 0xaa, 0xe1, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06,
- 0x73, 0x74, 0x00, 0x40, 0x55, 0x6e, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3,
- 0x68, 0x00, 0x70, 0x02, 0x73, 0x0d, 0x00, 0x59, 0xe2, 0x00, 0x00, 0x27,
- 0x02, 0x01, 0x34, 0x40, 0x00, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x69, 0x02,
- 0x6c, 0x6a, 0x6d, 0x70, 0x72, 0x76, 0x77, 0x7c, 0x79, 0x82, 0x00, 0x59,
- 0xe3, 0x63, 0x00, 0x66, 0x19, 0x6e, 0x5b, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x06, 0x00, 0x09, 0x40, 0x12, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x69, 0x00, 0x79,
- 0x3b, 0xe3, 0x61, 0x00, 0x63, 0x06, 0x65, 0x1e, 0x40, 0x00, 0x62, 0x6c,
- 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01, 0xab,
- 0x00, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x0f, 0xe3, 0x00, 0x00, 0x27, 0x02,
- 0x73, 0x06, 0x00, 0x37, 0x40, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x09,
- 0x01, 0xac, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x5d, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x09, 0x61, 0x74, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6f,
- 0x6d, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0x01, 0x3b, 0x40, 0x59,
- 0x74, 0x65, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04,
- 0x74, 0x06, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x62, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x65, 0x0f, 0xe2, 0x68,
- 0x00, 0x6c, 0x06, 0x40, 0x06, 0x6f, 0x72, 0x64, 0x00, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0xff,
- 0x40, 0x00, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00,
- 0x07, 0x40, 0x00, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0xf7, 0x61, 0x00, 0x00, 0x66,
- 0x98, 0x00, 0x6d, 0xa1, 0x00, 0x6e, 0xc4, 0x00, 0x72, 0xc9, 0x00, 0x76,
- 0x2c, 0x01, 0x77, 0x45, 0x01, 0xe4, 0x6e, 0x00, 0x72, 0x3e, 0x74, 0x7a,
- 0x76, 0x7c, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x0b, 0x6e,
- 0x19, 0x73, 0x1f, 0x75, 0x2b, 0x01, 0xad, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0xdb, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0xae, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07,
- 0x40, 0x09, 0x70, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x68, 0x08, 0x69,
- 0x10, 0x6e, 0x24, 0x77, 0x2a, 0x01, 0xaf, 0x40, 0x06, 0x6e, 0x63, 0x65,
- 0x00, 0x40, 0x00, 0x65, 0x61, 0x64, 0x65, 0x64, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0x40, 0x06,
- 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x08, 0x61, 0x79, 0x00, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40,
- 0x09, 0x67, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x00, 0x09, 0xe2, 0x61,
- 0x00, 0x65, 0x06, 0x40, 0x09, 0x74, 0x69, 0x73, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x53, 0x79, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0x40, 0x08, 0x6e, 0x65, 0x00, 0x40, 0x59, 0x63,
- 0x68, 0x00, 0xe4, 0x65, 0x00, 0x67, 0x08, 0x69, 0x34, 0x6b, 0x4d, 0x40,
- 0x06, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x00, 0xe1, 0x79, 0x00, 0xe3, 0x00,
- 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40,
- 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x59, 0x40,
- 0x07, 0x68, 0x69, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x10, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x63, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x09, 0x73, 0x00, 0x00, 0x93, 0xfb, 0x63, 0x00, 0x00,
- 0x65, 0x14, 0x00, 0x66, 0x26, 0x00, 0x69, 0x4e, 0x00, 0x6d, 0x50, 0x00,
- 0x6e, 0xb4, 0x00, 0x6f, 0x02, 0x01, 0x70, 0x24, 0x01, 0x71, 0x47, 0x01,
- 0x74, 0x6b, 0x01, 0x78, 0x8a, 0x01, 0xe2, 0x68, 0x00, 0x6b, 0x04, 0x40,
- 0xb2, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0xb0, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x09, 0x40, 0x09, 0x6c, 0x65, 0x00, 0xe1, 0x66, 0x00, 0xe3,
- 0x00, 0x00, 0x68, 0x02, 0x74, 0x19, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x6f, 0x70, 0x00,
- 0x00, 0x00, 0xe3, 0x61, 0x00, 0x62, 0x49, 0x65, 0x5b, 0xe3, 0x63, 0x00,
- 0x74, 0x12, 0x78, 0x40, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06,
- 0x40, 0x07, 0x72, 0x69, 0x63, 0x00, 0x40, 0x00, 0x63, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x12, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x07, 0x00, 0x47, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0xb1, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe4, 0x63, 0x00, 0x67, 0x0e, 0x69,
- 0x25, 0x6b, 0x3a, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x66, 0x06,
- 0x79, 0x0c, 0x01, 0x67, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x69, 0x6c,
- 0x6d, 0x00, 0x00, 0xf3, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x06, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73,
- 0x07, 0x00, 0x08, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x00,
- 0x00, 0x62, 0x02, 0x70, 0x09, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x61, 0x72,
- 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x06, 0x40, 0x06, 0x6e, 0x67, 0x00, 0xe1, 0x75, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x05, 0x40, 0x00, 0x65,
- 0x73, 0x00, 0x00, 0x09, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x62, 0x24,
- 0x00, 0x63, 0x2a, 0x00, 0x64, 0x49, 0x00, 0x67, 0x60, 0x00, 0x69, 0x7b,
- 0x00, 0x6d, 0x97, 0x00, 0x6e, 0x9b, 0x00, 0x70, 0xaa, 0x00, 0x73, 0xbf,
- 0x00, 0x74, 0x03, 0x01, 0x75, 0x5b, 0x01, 0x76, 0x8b, 0x01, 0x77, 0xb2,
- 0x01, 0x79, 0xcf, 0x01, 0xe2, 0x63, 0x00, 0x6b, 0x0c, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe3, 0x00, 0x00,
- 0x27, 0x02, 0x72, 0x06, 0x01, 0x73, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09,
- 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x2c, 0x62, 0x65, 0x72, 0x00, 0xe2, 0x68,
- 0x00, 0x6b, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02,
- 0x00, 0x2c, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x73, 0x65, 0x00,
- 0x40, 0x06, 0x72, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x68, 0x08,
- 0x00, 0x09, 0x40, 0x00, 0x69, 0x73, 0x68, 0x00, 0x40, 0x09, 0x6f, 0x70,
- 0x70, 0x65, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x67, 0x06, 0x01,
- 0x43, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x37,
- 0x64, 0x00, 0x40, 0x37, 0x6e, 0x67, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6f,
- 0x00, 0x74, 0x06, 0x40, 0x07, 0x6e, 0x6e, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x72, 0x04, 0x40, 0x2c, 0x72, 0x00, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40,
- 0x7a, 0x70, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x6b, 0x06, 0x40, 0x00,
- 0x6c, 0x00, 0x00, 0x5e, 0x00, 0x2c, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x33, 0x75, 0x38, 0xe7, 0x00,
- 0x00, 0x66, 0x02, 0x6d, 0x0a, 0x6e, 0x13, 0x6f, 0x19, 0x74, 0x1e, 0x75,
- 0x20, 0x01, 0xb2, 0x40, 0x00, 0x69, 0x73, 0x74, 0x65, 0x64, 0x00, 0x40,
- 0x00, 0x6f, 0x75, 0x74, 0x68, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x09, 0x75, 0x74, 0x00, 0x00, 0x2c, 0x40, 0x06, 0x70,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x90, 0x72, 0x65, 0x00, 0xe4,
- 0x00, 0x00, 0x68, 0x02, 0x74, 0x3c, 0x75, 0x4a, 0x00, 0x09, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x22, 0x73, 0x2f, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0xf1, 0xe3, 0x68, 0x00, 0x6c, 0x07, 0x70, 0x0d, 0x40,
- 0x09, 0x6f, 0x72, 0x73, 0x65, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00,
- 0x40, 0x06, 0x69, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x07, 0x67, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x72, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x29, 0xe6, 0x00, 0x00, 0x62,
- 0x02, 0x65, 0x09, 0x69, 0x0d, 0x6c, 0x14, 0x79, 0x1a, 0x00, 0x2c, 0x40,
- 0x06, 0x75, 0x72, 0x73, 0x74, 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x01,
- 0x15, 0x00, 0x2c, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72,
- 0x04, 0x00, 0x94, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07,
- 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x65, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x2c, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x72, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe7,
- 0x62, 0x00, 0x63, 0x44, 0x65, 0x48, 0x6d, 0x55, 0x6e, 0x79, 0x73, 0x8f,
- 0x74, 0x95, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x66, 0x1d, 0x68, 0x2c, 0x6c,
- 0x33, 0x00, 0x09, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0f, 0x40, 0x00,
- 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40,
- 0x00, 0x65, 0x74, 0x00, 0x40, 0x20, 0x6f, 0x74, 0x00, 0x40, 0x06, 0x6f,
- 0x75, 0x73, 0x65, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x2c,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x82, 0x40, 0x00, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x70, 0x00, 0x73, 0x09, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x2c, 0x00, 0x60, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x3b, 0xe2, 0x67, 0x00, 0x6b, 0x02, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x79, 0x06, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x00,
- 0x60, 0x40, 0x47, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x59, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x47, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x69, 0x00,
- 0x76, 0x11, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x76, 0x04, 0x78, 0x06, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x69,
- 0x64, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00,
- 0x3b, 0x00, 0x7b, 0x01, 0xce, 0x01, 0x01, 0x03, 0xb5, 0x03, 0x47, 0x04,
- 0x8a, 0x04, 0x2f, 0x05, 0xa1, 0x05, 0x00, 0x00, 0x25, 0x06, 0x29, 0x06,
- 0xf6, 0x09, 0x05, 0x13, 0xad, 0x26, 0xa8, 0x27, 0xa3, 0x28, 0xc1, 0x28,
- 0xed, 0x2c, 0x43, 0x2e, 0xdb, 0x2e, 0x1e, 0x33, 0x99, 0x33, 0x6a, 0x34,
- 0x80, 0x34, 0x9a, 0x34, 0x01, 0xb3, 0xf9, 0x63, 0x00, 0x00, 0x64, 0x27,
- 0x00, 0x67, 0x2f, 0x00, 0x6c, 0x53, 0x00, 0x72, 0xa9, 0x00, 0x73, 0xc2,
- 0x00, 0x74, 0xe7, 0x00, 0x75, 0x03, 0x01, 0x78, 0x0a, 0x01, 0xe1, 0x68,
- 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x08, 0x77, 0x15, 0x00, 0x47,
- 0x40, 0x08, 0x6f, 0x61, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x6b,
- 0x00, 0x40, 0x09, 0x6a, 0x75, 0x74, 0x6f, 0x72, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x09, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe5, 0x00, 0x00,
- 0x65, 0x02, 0x66, 0x1d, 0x69, 0x2d, 0x6d, 0x45, 0x00, 0x55, 0xe1, 0x73,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x09, 0x63, 0x65, 0x00, 0x40,
- 0x08, 0x65, 0x6c, 0x64, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x08, 0x69, 0x6e, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x7a, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x67, 0x0a,
- 0x6c, 0x11, 0x01, 0x5b, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x08, 0x75, 0x61, 0x72, 0x64, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x72, 0x07, 0x74, 0x0d, 0x01, 0xb5,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x6f, 0x6f, 0x6d, 0x00, 0x40,
- 0x06, 0x61, 0x69, 0x6c, 0x00, 0x40, 0x55, 0x74, 0x68, 0x6f, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x4b, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x3b,
- 0x67, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x62, 0x07, 0x6e, 0x25, 0x72,
- 0x2a, 0x77, 0x2e, 0x00, 0x06, 0x40, 0x07, 0x6c, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x6c, 0x04, 0x40, 0x08, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00,
- 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x06, 0x74,
- 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x08, 0x75, 0x74, 0x00, 0x40, 0x06, 0x61,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x00, 0x64, 0x00, 0x00,
- 0xf3, 0xf5, 0x61, 0x00, 0x00, 0x63, 0x0c, 0x00, 0x68, 0x25, 0x00, 0x6b,
- 0x44, 0x00, 0x6f, 0x0d, 0x01, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x75, 0x02, 0x79, 0x06,
- 0x00, 0x08, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x67, 0x00, 0x78, 0x05, 0x40,
- 0x00, 0x65, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x07, 0x6e, 0x65, 0x61, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0xed, 0x00, 0x00, 0x61, 0x02, 0x63, 0x23, 0x65, 0x34, 0x66, 0x43,
- 0x69, 0x5b, 0x6c, 0x6a, 0x6e, 0x7b, 0x70, 0x80, 0x72, 0x85, 0x73, 0x8c,
- 0x74, 0xa6, 0x79, 0xac, 0x00, 0x55, 0xe3, 0x64, 0x00, 0x6d, 0x04, 0x74,
- 0x0b, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x61, 0x6d, 0x69, 0x65, 0x00,
- 0xe2, 0x6f, 0x00, 0x72, 0x04, 0x40, 0x06, 0x6f, 0x00, 0x40, 0x06, 0x69,
- 0x63, 0x65, 0x00, 0xe2, 0x68, 0x00, 0x72, 0x07, 0x40, 0x08, 0x61, 0x66,
- 0x65, 0x72, 0x00, 0x40, 0x06, 0x6f, 0x77, 0x00, 0xe2, 0x72, 0x00, 0x79,
- 0x05, 0x40, 0x06, 0x65, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x01, 0x7f, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06,
- 0x40, 0x06, 0x68, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x06, 0x65, 0x79, 0x00,
- 0x40, 0x06, 0x69, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x63, 0x68, 0x00,
- 0xe2, 0x63, 0x00, 0x75, 0x06, 0x40, 0x06, 0x6f, 0x6d, 0x62, 0x00, 0xe2,
- 0x63, 0x00, 0x72, 0x06, 0x40, 0xcf, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x09, 0x61, 0x69, 0x6c, 0x00, 0x00, 0xf4, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x6e, 0x04, 0x6f, 0x09, 0x00, 0x09, 0x00, 0x06, 0x40,
- 0x06, 0x75, 0x74, 0x00, 0x40, 0x2c, 0x6e, 0x00, 0xea, 0x00, 0x00, 0x61,
- 0x02, 0x64, 0x04, 0x65, 0x18, 0x66, 0x52, 0x67, 0x58, 0x69, 0x5d, 0x6f,
- 0x87, 0x70, 0x8f, 0x73, 0x96, 0x00, 0x06, 0x00, 0x09, 0xe3, 0x65, 0x00,
- 0x69, 0x04, 0x6c, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe7, 0x00, 0x00, 0x27, 0x02, 0x63, 0x06,
- 0x69, 0x08, 0x70, 0x0d, 0x72, 0x27, 0x78, 0x29, 0x01, 0xb6, 0x40, 0x00,
- 0x73, 0x00, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x06, 0x01,
- 0x52, 0x00, 0x07, 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0xe2, 0x63, 0x00, 0x66, 0x0d, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x11, 0xe2, 0x63, 0x00, 0x65, 0x08, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x01, 0xb7, 0x60, 0x09, 0x6e, 0x00,
- 0x08, 0x00, 0xff, 0xff, 0x40, 0x09, 0x69, 0x65, 0x63, 0x65, 0x00, 0x40,
- 0x00, 0x77, 0x61, 0x6c, 0x6c, 0x6f, 0x70, 0x00, 0xe7, 0x64, 0x00, 0x66,
- 0x24, 0x6c, 0x2e, 0x71, 0x39, 0x72, 0x3f, 0x76, 0x55, 0x78, 0x5a, 0xe2,
- 0x00, 0x00, 0x75, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0x40,
- 0x09, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x00, 0x40, 0x86, 0x75, 0x61,
- 0x6c, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x01, 0xb8, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x56, 0x61, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x1b, 0xe1, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3a, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x00, 0x40, 0x00, 0x65, 0x6e, 0x73, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x66,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x37, 0xe2, 0x65, 0x00, 0x72, 0x26, 0xe5,
- 0x00, 0x00, 0x63, 0x02, 0x68, 0x08, 0x6d, 0x0f, 0x70, 0x16, 0x00, 0x06,
- 0x40, 0x06, 0x61, 0x6b, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65,
- 0x00, 0x40, 0x06, 0x61, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x06, 0x40, 0x09, 0x61, 0x6d,
- 0x00, 0x40, 0x2c, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x10,
- 0x6e, 0x2b, 0x77, 0x93, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b, 0xe1, 0x74, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x9d, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe3,
- 0x61, 0x00, 0x69, 0x0b, 0x6f, 0x42, 0xe2, 0x63, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x74, 0x00, 0x7a, 0x1a, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x75, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x3b, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x6e, 0x05, 0x40, 0x00, 0x6c, 0x65,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x75, 0x65, 0x00, 0x00, 0x00,
- 0xe2, 0x6d, 0x00, 0x73, 0x05, 0x40, 0x06, 0x65, 0x6e, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x68, 0x65, 0x65,
- 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1f, 0x6f, 0x60, 0xe1, 0x62, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x5b, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09, 0x74, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x69, 0x00, 0x72, 0x04, 0x73, 0x1e, 0x40,
- 0x06, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3a, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x53, 0x00, 0x07, 0x00, 0x5c, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x09, 0x40, 0x06, 0x74, 0x00, 0xe5, 0x66, 0x00, 0x6c,
- 0x1c, 0x6e, 0x27, 0x72, 0x6a, 0x74, 0x6c, 0xe2, 0x00, 0x00, 0x66, 0x02,
- 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x75, 0x09, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x5e, 0x72, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x27, 0x02, 0x01, 0xb9, 0x40, 0x77, 0x73, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x63, 0x07, 0x65, 0x2b, 0x73, 0x2f, 0x00, 0xfe, 0x40,
- 0x06, 0x67, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3a, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x75, 0x72,
- 0x61, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x82, 0x65, 0x00,
- 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x64, 0x0f, 0x00, 0x65, 0x27,
- 0x00, 0x69, 0x3a, 0x00, 0x6c, 0x5b, 0x00, 0x6f, 0x20, 0x02, 0x74, 0x85,
- 0x03, 0x75, 0x91, 0x03, 0x00, 0x08, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x09, 0x40, 0x06, 0x64, 0x65, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02,
- 0x6e, 0x0b, 0x01, 0xba, 0x40, 0x00, 0x6c, 0x6f, 0x6f, 0x64, 0x65, 0x64,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x73, 0x00, 0x75, 0x06,
- 0x79, 0x0a, 0x40, 0x07, 0x6c, 0x61, 0x77, 0x00, 0x40, 0x09, 0x73, 0x00,
- 0x00, 0x08, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x73, 0x0d, 0x74, 0x13, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x07, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x09, 0x65, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0xf6,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x9c, 0x00, 0x69, 0x25, 0x01,
- 0x6f, 0x46, 0x01, 0x75, 0x99, 0x01, 0x00, 0x00, 0xe5, 0x62, 0x00, 0x67,
- 0x31, 0x70, 0x3d, 0x72, 0x4d, 0x74, 0x66, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x1a, 0x00, 0x9d, 0xe2, 0x6f, 0x00, 0x76, 0x0f, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x74, 0x00,
- 0x40, 0x3b, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x82, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00,
- 0xe4, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08, 0x6c, 0x0a, 0x00, 0x2c, 0x40,
- 0x06, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x06, 0x40, 0x00, 0x65, 0x73, 0x73,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x19, 0x6f, 0x1e, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x8c, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x12, 0x40, 0x00, 0x7a, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x06, 0x65,
- 0x5f, 0x67, 0x63, 0x40, 0x09, 0x67, 0x75, 0x65, 0x00, 0xe1, 0x74, 0x00,
- 0xe5, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x69, 0x14, 0x6f, 0x47, 0x01,
- 0xbb, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x37, 0x40, 0x00, 0x79, 0x00, 0xe3, 0x62, 0x00, 0x6f, 0x05,
- 0x76, 0x09, 0x40, 0x06, 0x6c, 0x65, 0x00, 0x40, 0x69, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2,
- 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0xe1, 0x61, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x06, 0x74, 0x08, 0x40,
- 0x07, 0x69, 0x74, 0x79, 0x00, 0x00, 0x09, 0x40, 0x00, 0x65, 0x00, 0xe3,
- 0x64, 0x00, 0x65, 0x04, 0x73, 0x14, 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x94, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07,
- 0x00, 0x06, 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x69,
- 0x12, 0x71, 0x20, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x8d, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x75, 0x02, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1e, 0xe3,
- 0x61, 0x00, 0x65, 0x0f, 0x75, 0x13, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x73, 0x6d, 0x00, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x09, 0x6d, 0x00, 0x00, 0x07, 0xe2, 0x64, 0x00, 0x73, 0x04,
- 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xf5, 0x67, 0x00, 0x00,
- 0x6e, 0x05, 0x00, 0x70, 0x6c, 0x00, 0x72, 0x72, 0x00, 0x73, 0x30, 0x01,
- 0x40, 0x06, 0x6e, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x14,
- 0x6e, 0x4a, 0x6f, 0x50, 0x79, 0x58, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x73,
- 0x0b, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00,
- 0x00, 0x00, 0xe3, 0x61, 0x00, 0x73, 0x16, 0x7a, 0x1a, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x06, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x41, 0xbc, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0xbd, 0x00, 0x09, 0x40, 0xb2, 0x61, 0x64,
- 0x65, 0x00, 0x40, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x79, 0x00, 0x00, 0x06,
- 0x40, 0x06, 0x68, 0x6f, 0x6e, 0x00, 0xe9, 0x00, 0x00, 0x27, 0x02, 0x61,
- 0x06, 0x62, 0x1e, 0x65, 0x37, 0x66, 0x49, 0x69, 0x71, 0x6c, 0x90, 0x77,
- 0xa6, 0x01, 0xbe, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04,
- 0x40, 0x06, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x84, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x72, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x64, 0x00, 0xe3,
- 0x00, 0x00, 0x27, 0x02, 0x73, 0x06, 0x00, 0x37, 0x40, 0x00, 0x73, 0x00,
- 0x00, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x13, 0xe1, 0x73, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x6e, 0x00, 0x73, 0x06, 0x7a,
- 0x0a, 0x40, 0x00, 0x67, 0x27, 0x73, 0x00, 0x40, 0x08, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x3a, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x08, 0x61, 0x79, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x11, 0xe3, 0x61, 0x00,
- 0x69, 0x04, 0x75, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x05, 0x40, 0x06, 0x6d, 0x79, 0x00,
- 0x40, 0x07, 0x75, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x73, 0x68, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x62, 0x00, 0x6e,
- 0x06, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x06, 0x00, 0xb1, 0x40, 0x00, 0x72, 0x00, 0x40, 0x06, 0x73, 0x74,
- 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x16, 0x00, 0x65,
- 0xa6, 0x00, 0x66, 0x06, 0x01, 0x69, 0x59, 0x01, 0x6d, 0x7e, 0x01, 0x70,
- 0x81, 0x04, 0x72, 0xdd, 0x08, 0x01, 0xbf, 0xe3, 0x00, 0x00, 0x6b, 0x02,
- 0x74, 0x07, 0x00, 0x09, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6f,
- 0x73, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x1c, 0x69, 0x25,
- 0x6f, 0x59, 0x75, 0x5b, 0x01, 0xc0, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x07, 0x01, 0xc1, 0x40, 0x06, 0x6e, 0x74, 0x00, 0x40,
- 0x07, 0x76, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x37, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x13, 0x67, 0x26, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x08, 0x72, 0x69, 0x63, 0x00, 0xe4, 0x00,
- 0x00, 0x27, 0x02, 0x64, 0x06, 0x72, 0x08, 0x00, 0xab, 0x40, 0x00, 0x73,
- 0x00, 0x00, 0x37, 0x00, 0x09, 0x40, 0x07, 0x73, 0x00, 0x00, 0x06, 0xe1,
- 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe3, 0x62, 0x00, 0x6f,
- 0x10, 0x76, 0x14, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08, 0x6c, 0x29,
- 0x72, 0x37, 0x73, 0x3c, 0x74, 0x44, 0x75, 0x46, 0x01, 0xc2, 0x40, 0x09,
- 0x61, 0x63, 0x6b, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x13, 0x79, 0x18, 0xe3,
- 0x61, 0x00, 0x63, 0x04, 0x65, 0x06, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x00,
- 0x40, 0x09, 0x6e, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x77, 0x6e, 0x00, 0x00,
- 0x06, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x15, 0x40, 0x00, 0x27, 0x73, 0x00, 0x40, 0x06, 0x74, 0x69,
- 0x62, 0x6c, 0x65, 0x00, 0x00, 0x06, 0x40, 0x06, 0x70, 0x70, 0x61, 0x6e,
- 0x63, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x0e, 0x79, 0x4a, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01, 0xc3, 0x40, 0x00, 0x73, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x1c, 0x69, 0x20, 0x6c, 0x25, 0x01, 0xc4, 0xe1, 0x62, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x37, 0x40, 0x09, 0x72,
- 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0xf3, 0xe3, 0x63, 0x00, 0x6e, 0x16, 0x74, 0x1a, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x67, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x31,
- 0x00, 0x69, 0xfb, 0x00, 0x6f, 0xb0, 0x01, 0x75, 0x50, 0x02, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0xe1, 0x64, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x07, 0x6d, 0x12, 0x6f, 0x18, 0x01, 0xc5, 0x40,
- 0x09, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x0b, 0x72,
- 0x00, 0x00, 0x07, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x06, 0xe3,
- 0x6d, 0x00, 0x6e, 0x1e, 0x72, 0x95, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x40, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0xe4, 0x63, 0x00, 0x64, 0x1c, 0x73, 0x3c, 0x74, 0x53, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0xc6, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x01, 0xc7, 0xe2, 0x62, 0x00, 0x74,
- 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40,
- 0x00, 0x6c, 0x65, 0x00, 0x40, 0x5c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x95, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x3a, 0x40, 0x06, 0x72, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x61, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0xe2, 0x73,
- 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe4, 0x65, 0x00,
- 0x6e, 0x02, 0x73, 0x08, 0x74, 0x59, 0x00, 0x06, 0x40, 0x3a, 0x67, 0x6c,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x15, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0xc8, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x13, 0xe1, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x07, 0x00, 0x06, 0x40, 0x06, 0x61,
- 0x74, 0x00, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00,
- 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x0c, 0x01, 0xc9, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x08, 0x69, 0x72, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x6d, 0x02, 0x74, 0x08, 0x00, 0x76, 0x40, 0x09, 0x65, 0x6e,
- 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x38, 0x40, 0x06, 0x6c,
- 0x00, 0xe3, 0x64, 0x00, 0x65, 0x02, 0x72, 0x2b, 0x01, 0xca, 0xe3, 0x00,
- 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x00, 0x08, 0x40, 0x77, 0x6e, 0x67, 0x00, 0xe3, 0x64,
- 0x00, 0x6e, 0x31, 0x74, 0x93, 0xe3, 0x65, 0x00, 0x69, 0x0b, 0x6f, 0x25,
- 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01, 0xcb, 0x40, 0x00, 0x73, 0x00, 0xe3,
- 0x66, 0x00, 0x6f, 0x0a, 0x74, 0x0f, 0x40, 0x00, 0x69, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0x40, 0x06, 0x72, 0x65, 0x00, 0xe8, 0x00, 0x00, 0x27, 0x02, 0x61,
- 0x06, 0x65, 0x17, 0x6e, 0x1b, 0x70, 0x21, 0x73, 0x28, 0x77, 0x35, 0x01,
- 0xcc, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x74,
- 0x05, 0x40, 0x08, 0x74, 0x79, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x6c, 0x61,
- 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6e, 0x73, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x0d, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x69, 0x6f,
- 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x74, 0xe3, 0x61, 0x00, 0x65, 0x04,
- 0x69, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x01, 0xcd, 0xe5, 0x63, 0x00, 0x6f,
- 0x3d, 0x71, 0x41, 0x73, 0x46, 0x74, 0x58, 0xe1, 0x61, 0x00, 0xe3, 0x62,
- 0x00, 0x6e, 0x15, 0x74, 0x19, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54,
- 0x00, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x0f, 0x01, 0xc8, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x37, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x06, 0x75, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40,
- 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x19, 0xe1, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x0d, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x01, 0x97, 0x00, 0x07, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x65, 0xf1, 0x00, 0x69, 0x9e, 0x01, 0x6c, 0xb6, 0x01, 0x6f, 0xb6,
- 0x02, 0x72, 0x25, 0x03, 0x74, 0xaf, 0x03, 0x75, 0xb8, 0x03, 0x01, 0x17,
- 0xe5, 0x63, 0x00, 0x6e, 0x1d, 0x72, 0x46, 0x73, 0xa5, 0x74, 0xc1, 0xe1,
- 0x74, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x6f, 0x0d, 0x01,
- 0xce, 0x40, 0x00, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x22, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x77, 0x0e,
- 0x01, 0xcf, 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x68, 0x69,
- 0x70, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0x00, 0x06, 0xe4, 0x61, 0x00,
- 0x65, 0x20, 0x69, 0x22, 0x74, 0x28, 0xe2, 0x62, 0x00, 0x74, 0x15, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x54, 0x40, 0x86, 0x69, 0x76,
- 0x65, 0x00, 0x01, 0xd0, 0x40, 0x09, 0x73, 0x6f, 0x6e, 0x00, 0xe1, 0x6d,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x59, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x3b, 0x74, 0x65, 0x00,
- 0xe2, 0x69, 0x00, 0x72, 0x18, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c,
- 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x01, 0x89, 0x00, 0x54, 0x40, 0x09, 0x69, 0x6f, 0x74, 0x00, 0xe5,
- 0x65, 0x00, 0x6c, 0x04, 0x6e, 0x19, 0x72, 0x4f, 0x74, 0x53, 0x40, 0x06,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x11, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05,
- 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x8c, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x72, 0x79, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x25, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3a, 0xe2, 0x63, 0x00,
- 0x74, 0x17, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x53, 0x00, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00,
- 0x53, 0x00, 0x5c, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x19, 0xe2,
- 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x01, 0x4b, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x65, 0x47, 0x69, 0xa4, 0x79,
- 0xf5, 0xe2, 0x63, 0x00, 0x69, 0x16, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x3b, 0xe2, 0x6e, 0x00, 0x73, 0x16, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x07, 0x74, 0x0b, 0x00, 0x4c, 0x40, 0x09, 0x6e, 0x74,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0xe4, 0x63, 0x00, 0x6d, 0x06, 0x74, 0x1b, 0x78, 0x36, 0x40, 0x00, 0x74,
- 0x65, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x93, 0x40, 0x00, 0x72, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x04,
- 0x01, 0xd1, 0x00, 0x37, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x81, 0xe2, 0x6f,
- 0x00, 0x74, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0xb2, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe3, 0x61, 0x00,
- 0x63, 0x0e, 0x6d, 0x35, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe2, 0x61, 0x00, 0x69, 0x16, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x0b, 0x00, 0x3b, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x55, 0x40, 0x37, 0x72, 0x79, 0x00, 0x01, 0xd2, 0xe6, 0x00, 0x00, 0x6e,
- 0x02, 0x72, 0x08, 0x73, 0x18, 0x74, 0x4d, 0x75, 0x51, 0x00, 0x08, 0x40,
- 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x01, 0x23, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe4, 0x65, 0x00,
- 0x69, 0x10, 0x74, 0x25, 0x75, 0x27, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72,
- 0x07, 0x01, 0xd3, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x09, 0xe1, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x01, 0xd4, 0x41, 0x52,
- 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x00, 0x93, 0x40, 0x84, 0x72,
- 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0xd5, 0x40, 0x37, 0x64, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x77, 0x6f, 0x7c, 0xe2, 0x68, 0x00, 0x73, 0x48, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x02, 0x00, 0x7a,
- 0xe1, 0x69, 0x00, 0xe3, 0x62, 0x00, 0x6f, 0x15, 0x76, 0x21, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x54, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x53, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0x8f, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x73, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x69, 0x0a, 0x6f,
- 0x18, 0x01, 0x98, 0x40, 0x00, 0x73, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe2,
- 0x62, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x41, 0x52, 0x6e,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x0b, 0x73, 0x65, 0x00, 0x40, 0x82,
- 0x6d, 0x69, 0x73, 0x65, 0x00, 0x40, 0x09, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
- 0x72, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x30, 0x74, 0x38, 0xe1, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x19, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x06, 0x40, 0x06, 0x63,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x17, 0x69, 0x3d,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xab, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x07, 0x00, 0x09, 0x40, 0x00, 0x74, 0x65, 0x00, 0xe1, 0x7a, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x0b, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x56, 0x40, 0x07,
- 0x68, 0x69, 0x70, 0x00, 0xc1, 0x63, 0x17, 0x33, 0x00, 0x35, 0x00, 0xfe,
- 0x02, 0x21, 0x04, 0x2c, 0x04, 0x8b, 0x06, 0x00, 0x00, 0xbc, 0x07, 0xde,
- 0x07, 0x55, 0x08, 0x00, 0x00, 0x57, 0x08, 0x5c, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0xe1, 0x08, 0x00, 0x00, 0x14, 0x09, 0x78, 0x0d, 0xc6, 0x11, 0xdb,
- 0x11, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x13, 0x01, 0x2f, 0xf8, 0x61, 0x00,
- 0x00, 0x65, 0x2d, 0x00, 0x68, 0x64, 0x01, 0x69, 0x73, 0x01, 0x6c, 0xba,
- 0x01, 0x6f, 0xe9, 0x01, 0x72, 0x2b, 0x02, 0x75, 0x48, 0x02, 0xe2, 0x74,
- 0x00, 0x76, 0x18, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x26, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x69,
- 0x1b, 0x00, 0x6e, 0x4d, 0x00, 0x70, 0x77, 0x00, 0x72, 0xb2, 0x00, 0x73,
- 0x03, 0x01, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x0b,
- 0x01, 0xd6, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x74, 0x00, 0x76, 0x17, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0xb1, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x0f, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x54, 0x00, 0x54, 0x00, 0xa8, 0xe1, 0x74, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x8b, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75, 0x13, 0x00,
- 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x7a, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a,
- 0xe2, 0x6e, 0x00, 0x74, 0x16, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x73, 0x0b, 0x01, 0xd7, 0x40, 0x36, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x67, 0x0a,
- 0x69, 0x10, 0x6d, 0x1d, 0x6f, 0x25, 0x01, 0xd8, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x3b, 0x64, 0x00, 0x40, 0x08, 0x6f, 0x65, 0x72, 0x00, 0xe2, 0x6e,
- 0x00, 0x7a, 0x04, 0x40, 0x93, 0x61, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x40,
- 0x09, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x06, 0xe1, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe3, 0x69, 0x00, 0x6c, 0x05, 0x72, 0x07, 0x40, 0x09, 0x72, 0x65, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73,
- 0x06, 0x00, 0x07, 0x40, 0x08, 0x65, 0x00, 0x00, 0x00, 0xe3, 0x65, 0x00,
- 0x6c, 0x06, 0x73, 0x29, 0x40, 0x09, 0x72, 0x67, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x57, 0x40, 0x75, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xd9, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x75,
- 0x05, 0x40, 0x06, 0x76, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x04, 0x40,
- 0x3a, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40,
- 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01,
- 0xda, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x63, 0x00, 0x6d, 0x0f,
- 0x72, 0x17, 0x75, 0x33, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x7a, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x86, 0x69, 0x74, 0x61,
- 0x6e, 0x74, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x07, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x06, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x40, 0x06, 0x72, 0x73, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xdb, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x62, 0x00, 0x70, 0x12, 0x72,
- 0x2c, 0x73, 0x50, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x05, 0x40, 0x07, 0x67, 0x65, 0x00, 0x00, 0x09, 0xe1, 0x69, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x13, 0xe2,
- 0x64, 0x00, 0x6e, 0x02, 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xdc, 0x40, 0x06, 0x6f,
- 0x6e, 0x00, 0xf4, 0x65, 0x00, 0x00, 0x69, 0x63, 0x00, 0x6f, 0xa0, 0x00,
- 0x75, 0xc8, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x22, 0x73, 0x42, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x14, 0x00, 0xd6, 0xe1, 0x74,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x01, 0xdd, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x01, 0x4b, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x64, 0x00, 0x73, 0x06, 0x40, 0x3b, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x67, 0x00, 0x6d, 0x04, 0x74,
- 0x0a, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x27,
- 0x02, 0x61, 0x06, 0x65, 0x0a, 0x69, 0x13, 0x00, 0x61, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x56, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37,
- 0x00, 0x06, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x6c, 0x02,
- 0x6d, 0x09, 0x6e, 0x17, 0x72, 0x1b, 0x00, 0x06, 0x40, 0x06, 0x65, 0x6e,
- 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09,
- 0x6e, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x00, 0x06, 0xe2,
- 0x63, 0x00, 0x69, 0x45, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x01, 0xde, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x6f, 0x29, 0x72, 0x2d, 0x01, 0xdf,
- 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe3, 0x62, 0x00, 0x6f, 0x10, 0x76,
- 0x14, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x69,
- 0x74, 0x79, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65,
- 0x31, 0x00, 0x69, 0xcf, 0x00, 0x6c, 0x8f, 0x01, 0x6f, 0xc6, 0x01, 0x72,
- 0xf6, 0x01, 0x75, 0x20, 0x02, 0x00, 0x00, 0xe1, 0x62, 0x00, 0xe3, 0x00,
- 0x00, 0x62, 0x02, 0x75, 0x10, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01,
- 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x1f, 0x72,
- 0x35, 0x73, 0x6b, 0x74, 0x8e, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x0f,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x72, 0x0e, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x6e, 0x02,
- 0x00, 0x06, 0x41, 0x7f, 0x63, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0c,
- 0x69, 0x15, 0xe2, 0x62, 0x00, 0x6c, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00,
- 0x00, 0x07, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04,
- 0x6f, 0x15, 0x40, 0x3b, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x06, 0x6c, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x07, 0x74, 0x69, 0x00, 0xe5, 0x64, 0x00, 0x67,
- 0x48, 0x6e, 0x60, 0x72, 0x70, 0x73, 0x92, 0xe3, 0x61, 0x00, 0x65, 0x0f,
- 0x69, 0x3c, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x09, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x24,
- 0x01, 0x4b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02,
- 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x08,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x22, 0xe1, 0x65, 0x00, 0xe2, 0x64,
- 0x00, 0x6d, 0x02, 0x00, 0x37, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe1,
- 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x14, 0x00, 0xd5, 0xe1,
- 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x65, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x72, 0x79, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x1a, 0x75, 0x1f, 0xe2, 0x67, 0x00, 0x74, 0x09, 0x40, 0x09, 0x72, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x26,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x93, 0x63, 0x74, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65,
- 0x00, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x11, 0x01, 0xe0, 0xe2, 0x62, 0x00, 0x6e, 0x05, 0x40,
- 0x37, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x63, 0x65, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40,
- 0x07, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x72, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x13, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x89, 0x00, 0x3b, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xf4,
- 0x61, 0x00, 0x00, 0x65, 0x02, 0x00, 0x6c, 0x34, 0x00, 0x72, 0x52, 0x00,
- 0x00, 0x2c, 0xe3, 0x61, 0x00, 0x72, 0x10, 0x73, 0x1c, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0xe1, 0x40, 0x07, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x65, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xe2, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x01, 0xe3, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x26, 0x75, 0xac, 0xe1, 0x74, 0x00, 0xe2, 0x73, 0x00, 0x75,
- 0x02, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x45, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x67, 0x00, 0x73, 0x36,
- 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x39, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe5, 0x00, 0x00,
- 0x69, 0x02, 0x6d, 0x09, 0x70, 0x16, 0x77, 0x2a, 0x00, 0x09, 0x40, 0x00,
- 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6f, 0x00,
- 0x72, 0x06, 0x40, 0x00, 0x70, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x73, 0x6f,
- 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x0e, 0x6f, 0x13, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x41, 0xa7, 0x74, 0x79, 0x00, 0x40,
- 0x00, 0x75, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x66, 0x0b, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x00, 0x75,
- 0x73, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x17, 0x75, 0x1d, 0xe1, 0x63, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x82, 0x40, 0x00, 0x69, 0x6e,
- 0x74, 0x00, 0xe3, 0x67, 0x00, 0x6e, 0x16, 0x72, 0x37, 0xe1, 0x61, 0x00,
- 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x3b, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xe4, 0xe1, 0x76, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x02, 0x69, 0x04, 0x00, 0x06, 0x00, 0x06, 0x40, 0x07,
- 0x74, 0x69, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00,
- 0x07, 0x01, 0xe5, 0x40, 0x00, 0x61, 0x6e, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x3a, 0x6f, 0x60, 0x75, 0x75, 0xe2, 0x63, 0x00, 0x64, 0x33, 0xe1, 0x74,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x6f, 0x21,
- 0x01, 0xe6, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x37, 0x64, 0x00,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0xd2, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0x00, 0x00, 0xe3, 0x6e, 0x00, 0x70, 0x04, 0x76, 0x0b, 0x40, 0x00,
- 0x67, 0x00, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x06, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x74, 0x08, 0x40, 0x06,
- 0x73, 0x73, 0x65, 0x75, 0x72, 0x00, 0x40, 0x00, 0x61, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0x40, 0x00, 0x62, 0x69, 0x61, 0x6c, 0x00, 0xe1, 0x75, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x22, 0xe2, 0x72, 0x00, 0x73, 0x19, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x08, 0x6f, 0x0c, 0x00, 0xd5, 0x40, 0x37, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x75, 0x74, 0x00, 0x40, 0x06, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x72, 0x00,
- 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x21, 0x00, 0x65, 0x7e,
- 0x00, 0x69, 0x36, 0x01, 0x6f, 0xbc, 0x01, 0x70, 0x32, 0x02, 0x74, 0x7e,
- 0x02, 0x75, 0xae, 0x03, 0x00, 0x3a, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x06, 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0xe2, 0x69, 0x00, 0x72, 0x4f, 0xe2, 0x65, 0x00, 0x6f, 0x29, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x08, 0x40, 0x00, 0x65, 0x6c, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0xe7, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xdb, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x07, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe4, 0x63,
- 0x00, 0x6e, 0x2f, 0x71, 0x44, 0x72, 0x62, 0xe2, 0x72, 0x00, 0x75, 0x23,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x9e, 0x00, 0x37, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0x40,
- 0x3b, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0e, 0xe1,
- 0x75, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00,
- 0x09, 0x00, 0x2c, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0x40, 0x5c, 0x61, 0x6c, 0x00, 0xe1, 0x76, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x05, 0x40, 0x06, 0x63, 0x79,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x25, 0xe3, 0x6f, 0x00, 0x73, 0x16, 0x76,
- 0x1a, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1,
- 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40,
- 0x07, 0x6d, 0x00, 0x40, 0x86, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x05,
- 0x40, 0x08, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0x06, 0xe3, 0x64, 0x00, 0x67, 0x45, 0x73, 0x5b, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x34, 0x00, 0x61,
- 0xe2, 0x62, 0x00, 0x74, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x54, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0xe8, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01, 0xe9,
- 0x00, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6d, 0x06, 0x00, 0xd5, 0x40, 0x09, 0x65, 0x00, 0x40, 0x09,
- 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x6f, 0x15, 0x00, 0x7a, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x09, 0x01, 0xa7, 0x00, 0x5c, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0xe4, 0x6c, 0x00, 0x6d, 0x46, 0x6e, 0x4b, 0x72,
- 0x5c, 0xe2, 0x61, 0x00, 0x69, 0x19, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40,
- 0x54, 0x6c, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x1f,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f,
- 0x0e, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x01, 0x26, 0x00, 0x37, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x3b, 0x67, 0x00, 0x40,
- 0x07, 0x6d, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x56, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x07,
- 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x07, 0x40, 0x09, 0x63, 0x74, 0x75,
- 0x73, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x19, 0xe1, 0x75, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0xd7, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x1b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x3b, 0x61, 0x6c, 0x00, 0x00, 0xed, 0xf5, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x65, 0x22, 0x00, 0x69, 0x39, 0x00, 0x72, 0x95, 0x00, 0x00, 0x09,
- 0xe2, 0x62, 0x00, 0x6e, 0x10, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x06,
- 0x65, 0x00, 0x40, 0x06, 0x6c, 0x61, 0x72, 0x79, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x53, 0x79, 0x00, 0x00, 0x86, 0xe2, 0x6c, 0x00, 0x72,
- 0x09, 0x40, 0x06, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x70, 0x00, 0x74, 0x12,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x65, 0x00,
- 0x74, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06,
- 0x79, 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0xea, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x19,
- 0x00, 0x75, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86,
- 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x00, 0x6d, 0x00, 0x40, 0xdb, 0x79,
- 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x11, 0x75, 0x29, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x04, 0x40, 0x37, 0x64,
- 0x00, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x01, 0xeb, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x06, 0x65, 0x52, 0x40, 0x00,
- 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02,
- 0x69, 0x06, 0x6f, 0x3c, 0x01, 0xec, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x21, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x06, 0x01, 0xed, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0xaa, 0x40, 0x00, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x72, 0x00, 0x00, 0x0b, 0xe2, 0x6c,
- 0x00, 0x6d, 0x43, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x73, 0x0d, 0x74, 0x13,
- 0x01, 0xee, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x01, 0xef, 0x40, 0x06, 0x65,
- 0x00, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0xad, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x06, 0x79, 0x00, 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x06, 0x6d, 0x24, 0x70, 0x36, 0x40, 0x06, 0x62, 0x6c, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x01, 0xf0, 0x00, 0x37,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x01, 0xf1, 0x00,
- 0x37, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x00, 0xf8, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x64, 0x90, 0x00, 0x65, 0x92, 0x00, 0x69, 0x9c, 0x01,
- 0x6f, 0x15, 0x02, 0x72, 0x34, 0x02, 0x75, 0xff, 0x03, 0x00, 0x00, 0xe4,
- 0x63, 0x00, 0x67, 0x10, 0x69, 0x2d, 0x6d, 0x5a, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0xd5, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00,
- 0x09, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6d, 0x1d, 0x01, 0xf2, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x6f, 0x0e, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x01, 0xf3, 0x00, 0x37,
- 0x41, 0x52, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x00, 0x00, 0xe5,
- 0x6d, 0x00, 0x6e, 0x71, 0x72, 0xbc, 0x73, 0xc5, 0x78, 0xdf, 0xe2, 0x6e,
- 0x00, 0x70, 0x02, 0x00, 0x7a, 0xe3, 0x6c, 0x00, 0x6f, 0x1a, 0x74, 0x35,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01,
- 0xf4, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x56,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75, 0x11,
- 0x00, 0x07, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x05, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x12, 0x6c, 0x2c, 0x6d, 0x30,
- 0x01, 0xf5, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00,
- 0x75, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x84, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x6d, 0x69, 0x6e, 0x6f,
- 0x75, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0e, 0xe2,
- 0x62, 0x00, 0x6e, 0x05, 0x40, 0x54, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x3a, 0xe2, 0x67, 0x00, 0x6e, 0x12, 0xe1, 0x75, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00,
- 0xe3, 0x65, 0x00, 0x67, 0x17, 0x75, 0x28, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x53, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0x40, 0x06, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x00, 0x56, 0xe5,
- 0x61, 0x00, 0x65, 0x18, 0x69, 0x1a, 0x6f, 0x1f, 0x75, 0x24, 0xe4, 0x00,
- 0x00, 0x6c, 0x02, 0x6e, 0x04, 0x74, 0x09, 0x00, 0x00, 0x00, 0x3b, 0x40,
- 0xd2, 0x63, 0x65, 0x00, 0x40, 0xd2, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x83,
- 0x40, 0x90, 0x74, 0x79, 0x00, 0x40, 0x7d, 0x75, 0x73, 0x00, 0x40, 0x07,
- 0x6d, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0xed, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x73, 0x74, 0x00, 0xf4, 0x61, 0x00,
- 0x00, 0x65, 0x24, 0x01, 0x69, 0x2c, 0x01, 0x6f, 0x6d, 0x01, 0xfa, 0x62,
- 0x00, 0x00, 0x63, 0x13, 0x00, 0x64, 0x50, 0x00, 0x66, 0x79, 0x00, 0x69,
- 0x7f, 0x00, 0x6c, 0xa1, 0x00, 0x70, 0xa6, 0x00, 0x72, 0xb8, 0x00, 0x73,
- 0xee, 0x00, 0x76, 0xf2, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x73,
- 0x04, 0x40, 0x07, 0x64, 0x00, 0x40, 0x08, 0x73, 0x6f, 0x6f, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x74, 0x16, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75, 0x16, 0x00, 0x2f,
- 0xe3, 0x62, 0x00, 0x6c, 0x05, 0x6f, 0x09, 0x40, 0x00, 0x6c, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0x40, 0x08, 0x6e, 0x00, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x16, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x7a, 0x40, 0x06, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0x40, 0x09, 0x74, 0x69, 0x6e,
- 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x08, 0x6c, 0x6f, 0x77, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x09, 0xe1, 0x64, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x74, 0x6f, 0x00, 0xe2, 0x74, 0x00, 0x75, 0x06, 0x40, 0x06, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x3b, 0x6e, 0x74, 0x61, 0x6c, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x2f, 0xe5, 0x61, 0x00, 0x65, 0x0f, 0x6c, 0x14, 0x6e, 0x18, 0x77,
- 0x1e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x69, 0x73, 0x65,
- 0x00, 0x00, 0x6e, 0x40, 0x55, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x0b, 0x40, 0x06, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x74, 0x65, 0x6d, 0x70, 0x73, 0x00, 0xe3, 0x62,
- 0x00, 0x74, 0x20, 0x76, 0x26, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x01, 0xf6, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00,
- 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06,
- 0x40, 0x09, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x76, 0x28, 0xe3, 0x00, 0x00, 0x27,
- 0x02, 0x6c, 0x06, 0x00, 0xaa, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x06, 0x69, 0x0f, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x01, 0xf7, 0x00, 0x09, 0x41, 0x63, 0x6e, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0c, 0xe2,
- 0x69, 0x00, 0x79, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3a, 0x40, 0x54, 0x62, 0x6c, 0x65, 0x00,
- 0xe2, 0x6d, 0x00, 0x73, 0x25, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe1, 0x63,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00,
- 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x00,
- 0x6f, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01,
- 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x07, 0x40,
- 0x06, 0x64, 0x72, 0x75, 0x6d, 0x00, 0x40, 0x09, 0x62, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x21, 0x00, 0x69, 0x3f,
- 0x01, 0x6f, 0x80, 0x01, 0x75, 0xa1, 0x01, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3a, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09,
- 0x65, 0x00, 0x00, 0x06, 0xf5, 0x63, 0x00, 0x00, 0x6e, 0x23, 0x00, 0x72,
- 0x7d, 0x00, 0x78, 0xef, 0x00, 0x79, 0xfb, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x17, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x40, 0x08, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x74, 0x1a, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xab, 0x00, 0x09, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x41, 0x89,
- 0x65, 0x00, 0x00, 0x5c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2,
- 0x63, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6c, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x19, 0x00, 0x06, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x36, 0xe2, 0x74, 0x00, 0x7a, 0x04,
- 0x40, 0xdb, 0x79, 0x00, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x08, 0x65, 0x72,
- 0x00, 0xe3, 0x67, 0x00, 0x73, 0x11, 0x74, 0x40, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0x00,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x28, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x00, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x3b,
- 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x69, 0x0f, 0x00, 0x61, 0x40,
- 0x00, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x06,
- 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x6f, 0x08, 0x01, 0xf8, 0x41, 0x7f, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x0f, 0x76, 0x25, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x95, 0x40, 0x09, 0x6f, 0x6e, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x00, 0x0b, 0x00, 0x37, 0x40, 0x36, 0x6e, 0x67, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe3, 0x6b, 0x00, 0x6c, 0x04,
- 0x79, 0x18, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x09, 0x6f,
- 0x6e, 0x00, 0x00, 0x2c, 0xe1, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x70, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x00, 0x07, 0xe7, 0x00, 0x00, 0x6b,
- 0x02, 0x6c, 0x4c, 0x6e, 0x6c, 0x70, 0x79, 0x72, 0xb9, 0x74, 0xe1, 0x00,
- 0x95, 0xe8, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x65, 0x0c, 0x68, 0x1c,
- 0x69, 0x23, 0x6f, 0x2e, 0x77, 0x33, 0x01, 0xf9, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x09, 0x6f, 0x6f, 0x6b, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x06, 0x40, 0x08,
- 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x06,
- 0x40, 0x07, 0x67, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0x40, 0x06, 0x61,
- 0x72, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x0b,
- 0x6e, 0x0f, 0x01, 0xfa, 0x40, 0x06, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0xcf, 0x40, 0x09, 0x6b, 0x69, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfe, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x2f, 0xe2, 0x67, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x1b, 0x01, 0xf4, 0xe2,
- 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x01, 0x8f, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x6f, 0x0e, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x01, 0xfb, 0x00, 0x37, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x06, 0x65, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x10, 0x69, 0x12, 0x70, 0x3b, 0x72, 0x66, 0x73, 0x6a, 0x74, 0x6e,
- 0x75, 0x73, 0x79, 0x94, 0x01, 0xfc, 0xe2, 0x63, 0x00, 0x79, 0x07, 0x40,
- 0x00, 0x65, 0x74, 0x69, 0x63, 0x00, 0x00, 0x07, 0x00, 0x09, 0xe4, 0x65,
- 0x00, 0x6c, 0x04, 0x6e, 0x09, 0x6f, 0x0d, 0x40, 0x06, 0x72, 0x00, 0x40,
- 0x06, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x67, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x21, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x70, 0x08, 0x79, 0x0f,
- 0x00, 0x06, 0x40, 0x06, 0x65, 0x61, 0x64, 0x00, 0x40, 0x07, 0x6c, 0x61,
- 0x74, 0x65, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0xa6, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe8, 0x00, 0x00, 0x27,
- 0x02, 0x62, 0x06, 0x63, 0x0c, 0x69, 0x27, 0x6c, 0x2c, 0x72, 0x32, 0x77,
- 0x39, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6b,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x00, 0x65,
- 0x66, 0x74, 0x00, 0x40, 0x95, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x09,
- 0x72, 0x69, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40, 0x3b, 0x73, 0x68, 0x00,
- 0xc1, 0x61, 0x16, 0x31, 0x00, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x44,
- 0x00, 0x9d, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00,
- 0x00, 0xcb, 0x00, 0x00, 0x00, 0xec, 0x00, 0xfa, 0x00, 0xb4, 0x01, 0xef,
- 0x01, 0x00, 0x00, 0x77, 0x02, 0xbf, 0x03, 0xd5, 0x03, 0x05, 0x04, 0x25,
- 0x04, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x05, 0x40, 0x06, 0x6c, 0x65,
- 0x00, 0x00, 0x06, 0x40, 0x06, 0x65, 0x6c, 0x00, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x07, 0x6c, 0x28, 0x6f, 0x2e, 0x75, 0x3a, 0x01, 0xfd, 0x40,
- 0x07, 0x67, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x0f, 0x74, 0x16, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0x40, 0x09, 0x6c, 0x65, 0x72, 0x61, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x76, 0x02,
- 0x00, 0x2c, 0x40, 0x07, 0x61, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00,
- 0x07, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x0d, 0x73, 0x0f, 0x00, 0xa5,
- 0x40, 0x08, 0x69, 0x67, 0x69, 0x6f, 0x6e, 0x69, 0x73, 0x74, 0x00, 0x00,
- 0x07, 0x40, 0x09, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x00, 0x40,
- 0x06, 0x69, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x00, 0xe5,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x0b, 0x73, 0x0f, 0x01, 0xfe,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x67, 0x65, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x2c, 0x63, 0x72, 0x65, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x09, 0x40, 0x06, 0x72, 0x61, 0x6e, 0x74, 0x00, 0xeb, 0x00,
- 0x00, 0x62, 0x02, 0x63, 0x12, 0x65, 0x21, 0x66, 0x41, 0x69, 0x65, 0x6d,
- 0x7a, 0x72, 0x80, 0x73, 0x85, 0x75, 0x99, 0x79, 0xa1, 0x00, 0xfe, 0xe2,
- 0x61, 0x00, 0x72, 0x05, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x65,
- 0x61, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x04, 0x40, 0x09, 0x62, 0x00,
- 0x40, 0x08, 0x61, 0x6b, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x72, 0x09, 0x74,
- 0x17, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0xec, 0x40, 0x06, 0x74, 0x6f, 0x6e, 0x65, 0x00,
- 0x00, 0x06, 0xe2, 0x69, 0x00, 0x6c, 0x06, 0x40, 0x08, 0x65, 0x6c, 0x64,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x6b, 0x65, 0x73, 0x00,
- 0xe2, 0x75, 0x00, 0x77, 0x04, 0x40, 0x00, 0x72, 0x00, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x04, 0x6e, 0x08, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x65, 0x61, 0x6c, 0x00, 0x40, 0x55, 0x6f, 0x77, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x04, 0x40, 0x06, 0x6b,
- 0x00, 0x40, 0x07, 0x63, 0x68, 0x00, 0x40, 0x09, 0x63, 0x6f, 0x70, 0x69,
- 0x61, 0x00, 0x01, 0x0c, 0xe2, 0x6c, 0x00, 0x6e, 0x11, 0xe1, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09, 0x40, 0x06,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x17, 0xe4, 0x00, 0x00, 0x6c, 0x02,
- 0x72, 0x04, 0x74, 0x08, 0x00, 0x06, 0x00, 0x09, 0x40, 0x06, 0x79, 0x00,
- 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x6f, 0x02, 0x73, 0x3b, 0x75, 0x53,
- 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1f, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x74, 0x04, 0x00, 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x01, 0xff, 0xe2, 0x6f, 0x00, 0x73, 0x04, 0x40, 0x53, 0x6e,
- 0x00, 0x40, 0x00, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x6d, 0x04, 0x00, 0x09, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2,
- 0x6c, 0x00, 0x73, 0x11, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x65, 0x1a, 0x00, 0x69, 0x9f, 0x00, 0x6f, 0xab, 0x00, 0x75,
- 0xf3, 0x00, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x35, 0x73, 0x56, 0xe1,
- 0x74, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6e, 0x1d, 0x6f,
- 0x23, 0x02, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0e,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x6c, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x02, 0x01, 0x00, 0x37,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x09, 0x65,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x10, 0x00, 0x7a, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x06,
- 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40, 0x06,
- 0x6f, 0x72, 0x00, 0x00, 0x08, 0xe3, 0x62, 0x00, 0x64, 0x2d, 0x73, 0x31,
- 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x01, 0xc8, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0x40, 0x0b, 0x65,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x56, 0x65, 0x00, 0xe2, 0x67, 0x00, 0x70, 0x12, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x51, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6e, 0x1b, 0x02, 0x02, 0xe2, 0x62, 0x00, 0x6f, 0x10, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x54, 0x65,
- 0x00, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x0d, 0xe2, 0x67, 0x00, 0x69, 0x04, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x93, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0b, 0xe2, 0x67, 0x00, 0x78, 0x04, 0x40, 0x09, 0x65, 0x00, 0x00,
- 0x07, 0xe2, 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x00, 0x6c, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6c,
- 0x00, 0x6e, 0x02, 0x00, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x6e, 0x00,
- 0x73, 0x06, 0x40, 0x07, 0x64, 0x75, 0x6d, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x74, 0x74, 0x65, 0x00,
- 0xf7, 0x00, 0x00, 0x00, 0x68, 0x02, 0x00, 0x69, 0x04, 0x00, 0x6d, 0x24,
- 0x00, 0x70, 0xcd, 0x00, 0x73, 0xde, 0x00, 0x74, 0xf9, 0x00, 0x00, 0x07,
- 0x00, 0x3a, 0xe2, 0x67, 0x00, 0x6e, 0x17, 0xe1, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x09, 0x00, 0x48, 0x40, 0x06, 0x74, 0x6f, 0x72,
- 0x79, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x34, 0x6f, 0x44, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x17, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x00,
- 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe5, 0x67, 0x00, 0x6c, 0x12, 0x6e, 0x2d, 0x70, 0x33, 0x73, 0x51,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00,
- 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x06, 0x40, 0x06, 0x61,
- 0x75, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x00, 0x09, 0xe2,
- 0x6c, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x61, 0x79, 0x00, 0x40, 0x95, 0x6e,
- 0x73, 0x6f, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x5b, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x6c, 0x1a, 0x75, 0x28, 0x02, 0x03, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe1, 0x6d, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00,
- 0x07, 0x40, 0x08, 0x65, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x0a, 0x69, 0x22, 0x74, 0x2a, 0x79, 0x83, 0x00, 0x06, 0x40, 0x09, 0x6e,
- 0x67, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09,
- 0xe2, 0x69, 0x00, 0x6d, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x69,
- 0x6e, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x06, 0x6c, 0x6c, 0x69, 0x6f, 0x6e,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x13, 0x6f, 0x17, 0xe2, 0x67, 0x00, 0x72,
- 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x04, 0x00,
- 0x07, 0x00, 0x06, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe6, 0x00,
- 0x00, 0x6d, 0x02, 0x73, 0x17, 0x74, 0x1d, 0x77, 0x23, 0x79, 0x29, 0x00,
- 0x93, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09,
- 0x65, 0x65, 0x64, 0x00, 0x40, 0x09, 0x61, 0x69, 0x6c, 0x00, 0x40, 0x06,
- 0x6f, 0x6f, 0x64, 0x00, 0x00, 0x00, 0x40, 0x09, 0x6c, 0x65, 0x64, 0x6f,
- 0x6e, 0x00, 0xf8, 0x63, 0x00, 0x00, 0x67, 0x10, 0x00, 0x6c, 0x22, 0x00,
- 0x6e, 0x4b, 0x00, 0x70, 0x24, 0x03, 0x72, 0x54, 0x03, 0x73, 0x09, 0x04,
- 0x74, 0x18, 0x04, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x47, 0x40, 0x08, 0x74, 0x74, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x04,
- 0x40, 0x06, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x2f, 0x00,
- 0x00, 0xe4, 0x64, 0x00, 0x65, 0x13, 0x69, 0x17, 0x6f, 0x1b, 0xe3, 0x00,
- 0x00, 0x27, 0x02, 0x6e, 0x07, 0x00, 0x00, 0x40, 0x00, 0x76, 0x65, 0x00,
- 0x40, 0x00, 0x27, 0x74, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x09, 0x6d, 0x62, 0x00, 0xf3, 0x63, 0x00, 0x00, 0x73, 0x3f,
- 0x00, 0x74, 0x60, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe5, 0x00,
- 0x00, 0x6d, 0x02, 0x6f, 0x0f, 0x70, 0x13, 0x77, 0x1b, 0x00, 0x09, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x06, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6f, 0x10, 0x02, 0x05, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x64,
- 0x11, 0x00, 0x65, 0x17, 0x00, 0x6c, 0x02, 0x02, 0x72, 0x08, 0x02, 0x79,
- 0x4c, 0x02, 0x02, 0x06, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x00, 0x40, 0x09, 0x6f, 0x77, 0x6e,
- 0x00, 0xf4, 0x64, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x72, 0x19, 0x00, 0x73,
- 0xda, 0x01, 0x00, 0x37, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x83, 0x40,
- 0x00, 0x73, 0x00, 0xff, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x28,
- 0x00, 0x63, 0x3b, 0x00, 0x65, 0x5b, 0x00, 0x66, 0x76, 0x00, 0x69, 0x9b,
- 0x00, 0x6d, 0xbd, 0x00, 0x6f, 0xdc, 0x00, 0x70, 0xf3, 0x00, 0x72, 0x2d,
- 0x01, 0x73, 0x54, 0x01, 0x74, 0x7e, 0x01, 0x76, 0x85, 0x01, 0x77, 0x8b,
- 0x01, 0x00, 0xd2, 0xe3, 0x63, 0x00, 0x72, 0x0f, 0x74, 0x18, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x07, 0x40, 0x09, 0x6f, 0x6e,
- 0x00, 0x40, 0x08, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x59,
- 0x74, 0x61, 0x63, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x08, 0x40, 0x82,
- 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x08, 0x61, 0x73, 0x74, 0x00,
- 0xe2, 0x6c, 0x00, 0x75, 0x13, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x95,
- 0x69, 0x6d, 0x00, 0x40, 0x00, 0x63, 0x6b, 0x77, 0x69, 0x73, 0x65, 0x00,
- 0x40, 0x06, 0x6c, 0x74, 0x75, 0x72, 0x65, 0x00, 0xe3, 0x64, 0x00, 0x73,
- 0x02, 0x78, 0x0c, 0x00, 0x00, 0x40, 0x07, 0x70, 0x69, 0x6f, 0x6e, 0x61,
- 0x67, 0x65, 0x00, 0x40, 0x08, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x08, 0x6f, 0x19, 0x40, 0x00, 0x63, 0x74, 0x75, 0x61,
- 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x69, 0x6c, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x67, 0x00, 0x73, 0x02, 0x74, 0x0c, 0x00, 0x00,
- 0x40, 0x06, 0x75, 0x72, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x6c, 0x6c, 0x69, 0x67, 0x65, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x0c, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x07, 0x00, 0x59, 0xe2, 0x61, 0x00, 0x6e, 0x07, 0x40, 0x06, 0x73, 0x75,
- 0x72, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x66, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x07, 0x40, 0x06, 0x73, 0x69, 0x76,
- 0x65, 0x00, 0x00, 0x06, 0xe4, 0x61, 0x00, 0x65, 0x0d, 0x6f, 0x16, 0x72,
- 0x26, 0xe2, 0x6e, 0x00, 0x72, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0x40, 0x00, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x55, 0x74, 0x00, 0x40,
- 0x82, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0x40, 0x06, 0x72, 0x79, 0x00, 0xe3, 0x69, 0x00, 0x70, 0x1a, 0x75, 0x1e,
- 0xe2, 0x67, 0x00, 0x6e, 0x11, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x95, 0x40, 0x09, 0x74, 0x75, 0x72, 0x65, 0x00, 0x41, 0x2f,
- 0x6b, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x00, 0x6e, 0x6b, 0x00, 0x40,
- 0x09, 0x65, 0x6e, 0x6f, 0x72, 0x00, 0x40, 0xad, 0x61, 0x69, 0x6c, 0x00,
- 0x40, 0x09, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x09, 0x73, 0x00,
- 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40,
- 0x00, 0x66, 0x69, 0x65, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x73,
- 0x0f, 0x77, 0x15, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09, 0x69, 0x64, 0x65, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x64, 0x65, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x06, 0x40, 0x00, 0x69,
- 0x64, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x6c, 0x08,
- 0x6f, 0x21, 0x00, 0x76, 0x40, 0x00, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x65,
- 0x00, 0x69, 0x0f, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x74, 0x06, 0x02, 0x08,
- 0x40, 0x00, 0x73, 0x00, 0x00, 0x09, 0x40, 0x06, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x67, 0x20, 0x69, 0x27, 0x73, 0x2c,
- 0x74, 0x48, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08,
- 0x65, 0x74, 0x74, 0x65, 0x00, 0x40, 0x47, 0x65, 0x72, 0x00, 0xe1, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x72, 0x08, 0x77, 0x0a, 0x02, 0x09,
- 0x40, 0x08, 0x6f, 0x6f, 0x6b, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6f, 0x72,
- 0x6b, 0x00, 0xe8, 0x00, 0x00, 0x65, 0x02, 0x68, 0x25, 0x69, 0x2c, 0x6c,
- 0x31, 0x72, 0x3f, 0x73, 0x45, 0x79, 0x4b, 0x02, 0x0a, 0xe2, 0x6f, 0x00,
- 0x73, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x7d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x79, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x00, 0x90, 0x40, 0x09, 0x6f, 0x75,
- 0x73, 0x65, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0x40, 0x09,
- 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00, 0x40, 0x09,
- 0x61, 0x72, 0x64, 0x00, 0xe2, 0x63, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6f,
- 0x75, 0x73, 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0xe1, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x0e, 0x74,
- 0x51, 0x79, 0x6b, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0x40, 0x47, 0x6e, 0x74, 0x00, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06,
- 0x69, 0x13, 0x6c, 0x24, 0x74, 0x29, 0x02, 0x0b, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x67, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x09, 0x6c,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x27, 0x00, 0x73, 0x04,
- 0x40, 0x00, 0x73, 0x00, 0x00, 0x00, 0x40, 0x09, 0x65, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x02, 0x0c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x7a, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x06, 0xed, 0x00, 0x00, 0x61, 0x02, 0x62, 0x1e, 0x63,
- 0x33, 0x65, 0x3c, 0x67, 0x40, 0x68, 0x46, 0x6c, 0x5c, 0x6d, 0x70, 0x6f,
- 0x7d, 0x70, 0x84, 0x72, 0xa2, 0x73, 0xa7, 0x01, 0x05, 0xe1, 0x72, 0x00,
- 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07, 0x00, 0x56,
- 0x40, 0x07, 0x63, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x6f, 0x0a, 0x40, 0x09, 0x6c, 0x6c,
- 0x00, 0x40, 0x09, 0x72, 0x64, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x09,
- 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x00, 0x41, 0x20, 0x72, 0x00, 0x40,
- 0x09, 0x69, 0x72, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0a,
- 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x72, 0x64, 0x00, 0x40, 0x09,
- 0x64, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x0d, 0xe2, 0x63,
- 0x00, 0x6e, 0x04, 0x40, 0x09, 0x6b, 0x00, 0x40, 0x07, 0x67, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x09, 0x72, 0x6b, 0x65, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x04,
- 0x75, 0x0f, 0x40, 0x08, 0x74, 0x00, 0xe2, 0x6b, 0x00, 0x78, 0x04, 0x40,
- 0x09, 0x65, 0x00, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x63, 0x68, 0x65, 0x72,
- 0x00, 0x40, 0x06, 0x69, 0x65, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x05, 0x40,
- 0x08, 0x65, 0x64, 0x00, 0x40, 0x06, 0x69, 0x70, 0x00, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x73, 0x08, 0x00, 0x0b, 0x40, 0x09, 0x6f, 0x6d, 0x62, 0x00,
- 0x40, 0x09, 0x77, 0x61, 0x69, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x6e, 0x02,
- 0x6f, 0x08, 0x70, 0x0d, 0x00, 0x46, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x74, 0x65, 0x00, 0x40, 0x06, 0x75, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x0f, 0x79, 0x1e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x7a, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x02, 0x0e,
- 0xe3, 0x64, 0x00, 0x6c, 0x02, 0x73, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf6, 0x61, 0x00, 0x00, 0x65, 0x8c, 0x02, 0x69, 0xff, 0x04, 0x6f,
- 0x6d, 0x06, 0x75, 0xd7, 0x08, 0x79, 0x4a, 0x0a, 0xff, 0x62, 0x00, 0x00,
- 0x63, 0x47, 0x00, 0x64, 0x8c, 0x00, 0x66, 0x91, 0x00, 0x67, 0xeb, 0x00,
- 0x69, 0x00, 0x01, 0x6d, 0x09, 0x01, 0x6e, 0x37, 0x01, 0x70, 0x87, 0x01,
- 0x73, 0xc0, 0x01, 0x74, 0xd4, 0x01, 0x76, 0xe0, 0x01, 0x77, 0x04, 0x02,
- 0x79, 0x2a, 0x02, 0x7a, 0x44, 0x02, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x67,
- 0x29, 0x6c, 0x30, 0x77, 0x36, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x79, 0x1e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x40, 0x07,
- 0x72, 0x61, 0x73, 0x73, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00, 0x40,
- 0x00, 0x69, 0x73, 0x65, 0x00, 0xe1, 0x6b, 0x00, 0xe7, 0x00, 0x00, 0x64,
- 0x02, 0x65, 0x08, 0x68, 0x18, 0x6c, 0x1e, 0x70, 0x2a, 0x75, 0x2f, 0x02,
- 0x0f, 0x40, 0x09, 0x6f, 0x77, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x6a, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x63, 0x6b, 0x00, 0x40,
- 0x09, 0x65, 0x61, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0x10,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f, 0x74, 0x00, 0x40, 0x06,
- 0x70, 0x00, 0x40, 0x5e, 0x6c, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00,
- 0x00, 0x69, 0x02, 0x73, 0x11, 0x79, 0x4c, 0x00, 0x2c, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x6d, 0x00, 0x70, 0x19, 0x77, 0x21, 0xe2, 0x61, 0x00, 0x65, 0x10,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x68, 0x69, 0x70, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x6f,
- 0x70, 0x6c, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00,
- 0xf4, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09, 0xe2, 0x69, 0x00, 0x79,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0x40, 0x07,
- 0x67, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02,
- 0x70, 0x15, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x2c, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe5, 0x62, 0x00, 0x65, 0x07, 0x69, 0x09,
- 0x6b, 0x16, 0x6e, 0x41, 0x40, 0x06, 0x65, 0x72, 0x72, 0x79, 0x00, 0x00,
- 0x5e, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06,
- 0x6d, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x69, 0x08, 0x73, 0x17, 0x79,
- 0x1e, 0x00, 0x2c, 0x40, 0x06, 0x61, 0x73, 0x65, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x68, 0x61, 0x66, 0x74, 0x00, 0x01, 0x0c, 0x40, 0x1a, 0x79,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x70, 0x04, 0x73, 0x21, 0x00, 0x09,
- 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x14, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x01,
- 0x64, 0x40, 0x00, 0x67, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0x07, 0x40, 0x09, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x68,
- 0x00, 0x73, 0x02, 0x00, 0x47, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x7e, 0x00, 0x2f, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69,
- 0x18, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x11,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x12, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6c,
- 0x07, 0x00, 0x09, 0x40, 0x06, 0x61, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x73, 0x06, 0x79, 0x0d, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x06, 0x70, 0x61, 0x63, 0x65, 0x00, 0x01, 0x72, 0xe3, 0x00, 0x00, 0x66,
- 0x02, 0x6f, 0x08, 0x00, 0x08, 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x08, 0x61, 0x00, 0x00, 0x95, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x5e, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x02, 0x13,
- 0xfc, 0x61, 0x00, 0x00, 0x63, 0x9b, 0x00, 0x64, 0xa0, 0x00, 0x65, 0x1e,
- 0x01, 0x6d, 0x4d, 0x01, 0x6e, 0x81, 0x01, 0x6f, 0x99, 0x01, 0x70, 0xa8,
- 0x01, 0x73, 0xbc, 0x01, 0x74, 0xed, 0x01, 0x76, 0x18, 0x02, 0x77, 0x28,
- 0x02, 0xe4, 0x6b, 0x00, 0x6d, 0x1a, 0x73, 0x42, 0x74, 0x46, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x2c, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0e, 0x79, 0x1d, 0x01, 0x5b, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x15, 0x42, 0x14, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x3a, 0x75, 0x3e, 0x02, 0x15, 0xe2, 0x6f, 0x00, 0x76, 0x1c,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x69, 0x06, 0x00, 0x65,
- 0x41, 0xef, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x02, 0x12, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x06, 0x72, 0x65, 0x00,
- 0x40, 0x06, 0x68, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x1a,
- 0x6f, 0x51, 0x75, 0x53, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x63, 0x00,
- 0x74, 0x04, 0x7a, 0x0a, 0x40, 0x07, 0x65, 0x00, 0x40, 0x93, 0x69, 0x61,
- 0x6c, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x15, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x54, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x6f, 0x08, 0x77, 0x0c, 0x02, 0x16, 0x40, 0x8f, 0x62, 0x6c, 0x79,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x5d, 0x6f, 0x72, 0x74, 0x68, 0x79,
- 0x00, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x53, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x5c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4,
- 0x64, 0x00, 0x6b, 0x02, 0x6c, 0x04, 0x70, 0x06, 0x00, 0x06, 0x00, 0x06,
- 0x00, 0x06, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x79, 0x15, 0x01,
- 0x67, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe2, 0x61,
- 0x00, 0x65, 0x2d, 0xe2, 0x69, 0x00, 0x74, 0x05, 0x40, 0x07, 0x6e, 0x73,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x39, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0b, 0xe2,
- 0x61, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x09, 0x6d, 0x00, 0x00, 0x06,
- 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40,
- 0x82, 0x6f, 0x74, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x74, 0x02, 0x75, 0x04,
- 0x00, 0x06, 0x00, 0x00, 0x40, 0x00, 0x73, 0x63, 0x75, 0x6c, 0x61, 0x72,
- 0x00, 0xe3, 0x63, 0x00, 0x73, 0x11, 0x74, 0x13, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x04, 0x41, 0x82, 0x6f, 0x00, 0x00,
- 0x09, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x0a, 0x00, 0x2c,
- 0x40, 0x00, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x08, 0x6f, 0x1e, 0x40, 0x00, 0x63,
- 0x65, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x06, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x00,
- 0x75, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x6e, 0x65, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x06, 0x40, 0x06, 0x73, 0x73, 0x65, 0x00, 0x40, 0x09, 0x63, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x12, 0x00, 0x55, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72,
- 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xf9, 0x62, 0x00, 0x00, 0x63, 0x21, 0x00, 0x65, 0x39,
- 0x00, 0x6b, 0x3d, 0x00, 0x6d, 0x42, 0x00, 0x6e, 0x88, 0x00, 0x70, 0xa6,
- 0x00, 0x73, 0xcd, 0x00, 0x74, 0x09, 0x01, 0xe2, 0x00, 0x00, 0x62, 0x02,
- 0x00, 0x09, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0e, 0x40, 0x07, 0x67,
- 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x2c, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0x17,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x65, 0x79,
- 0x00, 0xe4, 0x65, 0x00, 0x69, 0x02, 0x70, 0x36, 0x73, 0x38, 0x00, 0x06,
- 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x17, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x41, 0x98, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73,
- 0x74, 0x00, 0x00, 0x07, 0x00, 0x2c, 0x40, 0x2c, 0x6f, 0x6e, 0x00, 0xe3,
- 0x67, 0x00, 0x6b, 0x04, 0x6f, 0x10, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x5e, 0x00, 0xf3, 0x40, 0x06,
- 0x6c, 0x69, 0x6e, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x70, 0x04, 0x40, 0x00,
- 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe3, 0x00,
- 0x00, 0x72, 0x02, 0x77, 0x04, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x00, 0x61,
- 0x72, 0x65, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x04, 0x70, 0x08, 0x73, 0x2b, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x69, 0x09, 0x6e, 0x10, 0x79, 0x16,
- 0x02, 0x18, 0x40, 0x08, 0x72, 0x65, 0x61, 0x64, 0x00, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c,
- 0x40, 0x59, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x11, 0x74, 0x3d, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x71,
- 0x22, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x06, 0x40, 0x36,
- 0x6c, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x09, 0x6d, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0x40,
- 0x82, 0x75, 0x65, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xfd, 0x61, 0x00,
- 0x00, 0x63, 0x0c, 0x00, 0x66, 0x44, 0x00, 0x69, 0x48, 0x00, 0x6e, 0x50,
- 0x00, 0x6f, 0x63, 0x00, 0x70, 0x92, 0x00, 0x71, 0xb4, 0x00, 0x72, 0xc8,
- 0x00, 0x73, 0xcc, 0x00, 0x74, 0xca, 0x01, 0x75, 0xe3, 0x01, 0x77, 0x03,
- 0x02, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2c, 0x00,
- 0xf3, 0xe4, 0x68, 0x00, 0x6b, 0x18, 0x6f, 0x24, 0x75, 0x2b, 0xe1, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01,
- 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0xb1, 0x40, 0x07, 0x72, 0x79, 0x00, 0x40, 0x06,
- 0x64, 0x69, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x73, 0x00, 0x41, 0x55, 0x74,
- 0x00, 0x40, 0x09, 0x73, 0x73, 0x61, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x6b, 0x00, 0x6e, 0x1f, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6e, 0x12, 0x00, 0x2c, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x63, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x65, 0x63, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40,
- 0x07, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x70, 0x08, 0x00, 0x09,
- 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x65,
- 0x00, 0xe2, 0x69, 0x00, 0x73, 0x05, 0x40, 0x09, 0x65, 0x72, 0x00, 0xef,
- 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x63, 0x44, 0x65, 0x68, 0x66, 0x6c,
- 0x68, 0x72, 0x69, 0x79, 0x6c, 0x7e, 0x6e, 0x82, 0x6f, 0x88, 0x70, 0x8e,
- 0x72, 0x9f, 0x74, 0xb1, 0x77, 0xb7, 0x02, 0x19, 0x40, 0x00, 0x73, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x04, 0x6f, 0x09, 0x72, 0x27, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x09, 0x61, 0x6d, 0x00, 0xe2, 0x6e, 0x00, 0x77, 0x05, 0x40,
- 0x07, 0x65, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00, 0x00, 0x42, 0x1a,
- 0x64, 0x00, 0xe2, 0x68, 0x00, 0x75, 0x06, 0x40, 0x2c, 0x65, 0x63, 0x6b,
- 0x00, 0xe2, 0x72, 0x00, 0x74, 0x07, 0x40, 0x09, 0x72, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40, 0x00, 0x69, 0x6e,
- 0x67, 0x00, 0x40, 0x00, 0x72, 0x00, 0x40, 0x09, 0x69, 0x72, 0x65, 0x00,
- 0x40, 0x0b, 0x61, 0x74, 0x63, 0x68, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x76, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x09, 0x74,
- 0x63, 0x68, 0x00, 0x40, 0x06, 0x65, 0x63, 0x65, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x09, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x77, 0x6e, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x05, 0x6f, 0x12, 0x40, 0x09, 0x6c, 0x6b, 0x00, 0xe2, 0x6e, 0x00,
- 0x73, 0x04, 0x40, 0x09, 0x64, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x09,
- 0x72, 0x64, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x06, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x70, 0x04, 0x74, 0x14, 0x40,
- 0x59, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x72, 0x00, 0x02, 0x1b, 0x40, 0x09, 0x6f, 0x6e, 0x00,
- 0xe5, 0x00, 0x00, 0x62, 0x02, 0x64, 0x07, 0x66, 0x1a, 0x6e, 0x29, 0x00,
- 0x55, 0x40, 0x09, 0x61, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x66,
- 0x06, 0x00, 0x2c, 0x40, 0x37, 0x64, 0x00, 0x40, 0x7a, 0x75, 0x6e, 0x64,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x65, 0x74, 0x00, 0x40,
- 0x06, 0x6f, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x2c, 0x40,
- 0x37, 0x64, 0x00, 0xfc, 0x63, 0x00, 0x00, 0x64, 0x30, 0x00, 0x65, 0x5a,
- 0x00, 0x66, 0x74, 0x00, 0x69, 0x80, 0x00, 0x6c, 0x8f, 0x00, 0x6d, 0x95,
- 0x00, 0x6e, 0xd4, 0x00, 0x70, 0xec, 0x00, 0x73, 0xf2, 0x00, 0x74, 0x47,
- 0x01, 0x78, 0x4c, 0x01, 0xe1, 0x69, 0x00, 0xe3, 0x61, 0x00, 0x62, 0x04,
- 0x66, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe3,
- 0x69, 0x00, 0x6f, 0x0f, 0x79, 0x14, 0xe1, 0x78, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72,
- 0x6d, 0x00, 0x00, 0x3a, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x65, 0x06, 0x69,
- 0x13, 0x00, 0x07, 0x40, 0x60, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x02, 0x1c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x6c,
- 0x00, 0x74, 0x13, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x08, 0x00, 0xe0,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00, 0x00, 0x06,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x1b, 0x00, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x7e, 0x00, 0x07, 0x40, 0x09, 0x6c, 0x65, 0x72, 0x00, 0xe3, 0x62, 0x00,
- 0x6d, 0x1d, 0x70, 0x2b, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x79, 0x14, 0x02,
- 0x0a, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x82, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0x00, 0x60, 0xe2, 0x69, 0x00,
- 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe2,
- 0x65, 0x00, 0x6c, 0x04, 0x40, 0x09, 0x74, 0x00, 0x40, 0x82, 0x65, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79,
- 0x09, 0x02, 0x1d, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x3b,
- 0x40, 0x09, 0x70, 0x65, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0f, 0x68,
- 0x11, 0x74, 0x23, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x0f, 0x79, 0x1e, 0x00,
- 0x2c, 0xe2, 0x63, 0x00, 0x6c, 0x06, 0x40, 0x06, 0x65, 0x61, 0x6e, 0x00,
- 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x3b, 0x40, 0x09, 0x63, 0x68, 0x00,
- 0x00, 0x09, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x6f, 0x08, 0x70, 0x3c, 0x73,
- 0x7c, 0x02, 0x1e, 0x40, 0x06, 0x61, 0x62, 0x79, 0x00, 0xe3, 0x67, 0x00,
- 0x6e, 0x15, 0x73, 0x24, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00,
- 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x00, 0x00, 0x40, 0x07, 0x75, 0x72, 0x67, 0x65, 0x72, 0x79,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x12, 0x00,
- 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x02, 0x00, 0x06, 0xe1, 0x68, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x08, 0x40, 0x06, 0x72, 0x00, 0x40,
- 0x00, 0x63, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0xe2, 0x69, 0x00,
- 0x6f, 0x17, 0xe2, 0x6e, 0x00, 0x7a, 0x04, 0x40, 0x00, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0xab, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00, 0x63,
- 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x63,
- 0x48, 0x00, 0x64, 0x6c, 0x00, 0x65, 0x86, 0x00, 0x66, 0x88, 0x00, 0x69,
- 0x8c, 0x00, 0x6c, 0x93, 0x00, 0x6d, 0x4b, 0x01, 0x6e, 0xc9, 0x01, 0x70,
- 0xee, 0x01, 0x72, 0x3e, 0x02, 0x73, 0x53, 0x04, 0x74, 0xf3, 0x04, 0x00,
- 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x0a, 0x69, 0x13, 0x6f, 0x36,
- 0x01, 0x05, 0x40, 0x09, 0x79, 0x68, 0x6f, 0x6c, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe3, 0x63, 0x00, 0x73, 0x11,
- 0x74, 0x1a, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x06, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x40, 0x08, 0x69, 0x64, 0x00, 0xe2,
- 0x6b, 0x00, 0x75, 0x18, 0xe1, 0x6f, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x0e,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x47, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x06, 0x40, 0x06, 0x6d, 0x62, 0x65, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x64, 0x02, 0x67, 0x0e, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x5e, 0x00, 0x60, 0x42, 0x1f, 0x65, 0x6c,
- 0x00, 0x00, 0x5e, 0x40, 0x55, 0x66, 0x00, 0x40, 0x06, 0x73, 0x69, 0x6e,
- 0x65, 0x00, 0xe7, 0x69, 0x00, 0x6c, 0x07, 0x6d, 0x09, 0x6f, 0x21, 0x70,
- 0x27, 0x74, 0x49, 0x76, 0xa3, 0x40, 0x00, 0x6e, 0x61, 0x72, 0x79, 0x00,
- 0x00, 0x55, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x26, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x06, 0x74, 0x74, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x72,
- 0x18, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00,
- 0x00, 0x40, 0x06, 0x69, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75,
- 0x3e, 0x00, 0x09, 0xe2, 0x73, 0x00, 0x76, 0x09, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe3, 0x62, 0x00, 0x72,
- 0x05, 0x74, 0x0b, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x20, 0x09, 0x08, 0x00,
- 0xff, 0xff, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x02, 0x20, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x3b, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x82, 0x00, 0x37,
- 0x40, 0x09, 0x65, 0x72, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x69,
- 0x2d, 0x6d, 0x31, 0x75, 0x43, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x72, 0x20,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x7a, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x75,
- 0x73, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x08, 0x40,
- 0x09, 0x72, 0x62, 0x75, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x07, 0x6f, 0x09, 0x75, 0x20,
- 0x40, 0x3b, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00,
- 0x75, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe3, 0x65, 0x00, 0x6e, 0x08, 0x74, 0x1c, 0x40, 0x07, 0x69, 0x66, 0x6f,
- 0x72, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x08, 0x40,
- 0x07, 0x69, 0x6e, 0x67, 0x75, 0x73, 0x00, 0x42, 0x21, 0x67, 0x00, 0x00,
- 0xcf, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x09, 0x66, 0x0f, 0x69, 0x14,
- 0x6f, 0x23, 0x70, 0x28, 0x72, 0x3a, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x61,
- 0x72, 0x64, 0x00, 0x40, 0x09, 0x61, 0x6b, 0x65, 0x00, 0x40, 0x06, 0x75,
- 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0xb1, 0x6c, 0x61, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x08, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xfd, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x62, 0x47, 0x00, 0x64, 0x65, 0x00, 0x65, 0x70,
- 0x00, 0x66, 0x8c, 0x00, 0x69, 0x91, 0x00, 0x6c, 0xc8, 0x00, 0x6d, 0xfa,
- 0x00, 0x72, 0x03, 0x01, 0x73, 0x54, 0x01, 0x74, 0x92, 0x01, 0x76, 0xbe,
- 0x01, 0x00, 0x56, 0xe4, 0x62, 0x00, 0x63, 0x08, 0x72, 0x13, 0x74, 0x17,
- 0x40, 0x07, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x79,
- 0x04, 0x40, 0x00, 0x6f, 0x00, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x02, 0x22, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x23, 0x40, 0x00, 0x61, 0x6c, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x55, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x05, 0x40, 0x00, 0x64, 0x65, 0x00,
- 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x09, 0x40, 0x3a, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x64, 0x06,
- 0x72, 0x08, 0x74, 0x0a, 0x02, 0x24, 0x40, 0x00, 0x73, 0x00, 0x00, 0x37,
- 0x02, 0x25, 0x40, 0x07, 0x74, 0x61, 0x67, 0x65, 0x00, 0x40, 0x06, 0x65,
- 0x77, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x09, 0x6f, 0x0b, 0x75, 0x2a, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0xe3, 0x00,
- 0x00, 0x73, 0x02, 0x75, 0x08, 0x00, 0x06, 0x40, 0x06, 0x69, 0x74, 0x79,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe5, 0x00, 0x00,
- 0x27, 0x02, 0x65, 0x06, 0x69, 0x0f, 0x79, 0x25, 0x01, 0xfe, 0x40, 0x00,
- 0x73, 0x00, 0xe2, 0x72, 0x00, 0x77, 0x02, 0x00, 0x06, 0x00, 0x06, 0xe2,
- 0x63, 0x00, 0x6e, 0x05, 0x40, 0x5e, 0x75, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0x01, 0x15, 0x40,
- 0x86, 0x75, 0x64, 0x67, 0x65, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x20, 0x79, 0x3b, 0x40, 0x09, 0x6e, 0x74, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe3, 0x00,
- 0x00, 0x27, 0x02, 0x73, 0x06, 0x02, 0x26, 0x40, 0x00, 0x73, 0x00, 0x00,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x5e, 0x40,
- 0x93, 0x6f, 0x6d, 0x62, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x1a,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x02, 0x22, 0x00, 0x3b, 0xe1, 0x76, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x02, 0x27, 0x40, 0x00,
- 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11,
- 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x5d, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x6e, 0x19, 0x73, 0x1f, 0x01, 0xb4, 0xe1, 0x69, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x0d, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0x13, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0x00, 0x59, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0xa1, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x24, 0x79, 0x26, 0xe2, 0x63,
- 0x00, 0x74, 0x19, 0xe1, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x75, 0x72, 0x65, 0x00, 0x00, 0x5e,
- 0x00, 0xf3, 0xe4, 0x68, 0x00, 0x70, 0x0c, 0x73, 0x21, 0x74, 0x32, 0xe2,
- 0x69, 0x00, 0x79, 0x05, 0x40, 0x47, 0x6f, 0x6e, 0x00, 0x00, 0xf3, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x06, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x27,
- 0x02, 0x65, 0x06, 0x02, 0x28, 0x40, 0x00, 0x73, 0x00, 0x40, 0x4d, 0x64,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x72, 0x64, 0x00, 0xe2,
- 0x64, 0x00, 0x6d, 0x1e, 0xe2, 0x69, 0x00, 0x79, 0x17, 0xe1, 0x61, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x00, 0x07, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x11, 0x68, 0x15, 0x69, 0x1c, 0x00, 0x0f, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00,
- 0x00, 0x37, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65,
- 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xea, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x13, 0x65, 0x19, 0x69, 0x30, 0x6c, 0x3c, 0x6f, 0x56, 0x74, 0x63, 0x75,
- 0x84, 0x77, 0x88, 0x02, 0x29, 0xe2, 0x6e, 0x00, 0x77, 0x07, 0x40, 0x00,
- 0x65, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0x40, 0x09,
- 0x61, 0x63, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x6e, 0x02, 0x73, 0x08, 0x79,
- 0x0c, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x60, 0x79,
- 0x00, 0x00, 0x08, 0xe2, 0x63, 0x00, 0x65, 0x05, 0x40, 0x09, 0x6c, 0x65,
- 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x09, 0x73, 0x73,
- 0x00, 0xe2, 0x72, 0x00, 0x74, 0x09, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x66, 0x00, 0x75, 0x04, 0x40, 0x06,
- 0x66, 0x00, 0x40, 0x06, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x04, 0x69,
- 0x0b, 0x6c, 0x10, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x72, 0x6f, 0x61,
- 0x74, 0x00, 0x40, 0x86, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x66, 0x69,
- 0x73, 0x68, 0x00, 0x40, 0x06, 0x70, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x6d,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x61,
- 0x00, 0x00, 0x62, 0x0f, 0x00, 0x63, 0x62, 0x00, 0x67, 0xbe, 0x00, 0x6c,
- 0xc4, 0x00, 0x6d, 0xdd, 0x00, 0x6e, 0xf2, 0x00, 0x70, 0x13, 0x01, 0x73,
- 0x1a, 0x01, 0x74, 0x38, 0x01, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x64, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x49, 0xe1, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x63, 0x09, 0x6e,
- 0x0f, 0x70, 0x24, 0x73, 0x2a, 0x00, 0x00, 0x40, 0x08, 0x75, 0x6c, 0x6c,
- 0x79, 0x00, 0x40, 0x08, 0x61, 0x66, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x08, 0x00, 0x07, 0x40, 0x06, 0x75, 0x6e, 0x6b, 0x00, 0xe2,
- 0x65, 0x00, 0x70, 0x04, 0x40, 0x00, 0x78, 0x00, 0x40, 0x09, 0x61, 0x63,
- 0x65, 0x00, 0x40, 0x06, 0x72, 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x06, 0x69, 0x08, 0x6f, 0x1c, 0x40, 0x09, 0x6d, 0x65, 0x6e,
- 0x00, 0x01, 0x85, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe4,
- 0x6d, 0x00, 0x6e, 0x07, 0x70, 0x12, 0x74, 0x25, 0x40, 0x09, 0x65, 0x74,
- 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x63, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x0c, 0xe2, 0x64, 0x00, 0x73, 0x05,
- 0x40, 0x09, 0x69, 0x61, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x09, 0x72,
- 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x65, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x00, 0x69, 0x63, 0x61, 0x6c, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x15,
- 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x06,
- 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x09, 0x73,
- 0x75, 0x72, 0x65, 0x00, 0x40, 0x09, 0x72, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x08, 0x00, 0x09, 0x40,
- 0x09, 0x69, 0x6e, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x69, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe4, 0x6b, 0x00, 0x6c,
- 0x12, 0x70, 0x24, 0x73, 0x3b, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x09, 0xe1,
- 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06,
- 0x73, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x63, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe2,
- 0x6e, 0x00, 0x73, 0x04, 0x40, 0x06, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0xc1, 0x27, 0x54, 0xad, 0x00, 0xaf, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0xcf, 0x05, 0xd8, 0x05,
- 0xda, 0x05, 0xec, 0x05, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1e, 0xdc, 0x1e,
- 0x7a, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x33,
- 0x65, 0x3c, 0x00, 0x00, 0x6e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x19, 0x42,
- 0x00, 0x00, 0xe0, 0x45, 0x00, 0x00, 0x29, 0x46, 0x33, 0x47, 0x02, 0x2a,
- 0xe2, 0x41, 0x00, 0x45, 0x08, 0x40, 0x07, 0x72, 0x65, 0x7a, 0x7a, 0x6f,
- 0x00, 0x40, 0x07, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00,
- 0xc0, 0x62, 0x19, 0x35, 0x00, 0x5d, 0x00, 0x85, 0x00, 0xae, 0x00, 0xc2,
- 0x00, 0xea, 0x00, 0x11, 0x01, 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x93,
- 0x01, 0xba, 0x01, 0x58, 0x02, 0x00, 0x00, 0xde, 0x02, 0x00, 0x00, 0xee,
- 0x02, 0x7e, 0x03, 0xbe, 0x03, 0x18, 0x04, 0x60, 0x04, 0x71, 0x04, 0x00,
- 0x00, 0x87, 0x04, 0xe4, 0x04, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x06,
- 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6c, 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe3, 0x65, 0x00,
- 0x68, 0x02, 0x74, 0x10, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x73, 0x02, 0x00,
- 0x09, 0x40, 0x09, 0x68, 0x75, 0x6e, 0x64, 0x00, 0xe1, 0x79, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x09, 0x63,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x64, 0x11, 0x6f, 0x15, 0x00, 0x06,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x09, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x63, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x16, 0xe3, 0x69, 0x00, 0x6f, 0x07,
- 0x79, 0x0d, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x64,
- 0x69, 0x6c, 0x00, 0x00, 0x96, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x63,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6f,
- 0x07, 0x75, 0x12, 0x00, 0x08, 0x40, 0x09, 0x65, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x08, 0x40, 0x00, 0x73, 0x00, 0x40, 0x5e, 0x65,
- 0x72, 0x72, 0x65, 0x6f, 0x74, 0x79, 0x70, 0x65, 0x00, 0x40, 0x09, 0x6c,
- 0x69, 0x61, 0x00, 0xe5, 0x6c, 0x00, 0x6e, 0x0e, 0x71, 0x27, 0x72, 0x2e,
- 0x73, 0x68, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x6e, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x02, 0x0e, 0x40, 0x09, 0x75, 0x69, 0x72, 0x69, 0x00,
- 0xe1, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x07, 0x77, 0x1b,
- 0x01, 0x2f, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0b,
- 0xe2, 0x69, 0x00, 0x6e, 0x04, 0x40, 0x09, 0x64, 0x00, 0x00, 0x07, 0x40,
- 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x6c, 0x02,
- 0x6d, 0x18, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x61, 0x00,
- 0x65, 0x06, 0x40, 0x09, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x00, 0x3f, 0x40, 0x09, 0x61, 0x74, 0x69, 0x61, 0x6e, 0x00, 0xe7, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x23, 0x6d, 0x25, 0x6e, 0x39, 0x70, 0x56, 0x73,
- 0x77, 0x00, 0x06, 0xe2, 0x67, 0x00, 0x73, 0x18, 0xe1, 0x65, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x64, 0x08, 0x73, 0x0a, 0x00, 0x82, 0x40, 0x00,
- 0x62, 0x6c, 0x65, 0x00, 0x00, 0x37, 0x00, 0x07, 0x40, 0x55, 0x6b, 0x00,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0xe2,
- 0x6e, 0x00, 0x74, 0x04, 0x40, 0x00, 0x67, 0x00, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x12, 0x00, 0xf0, 0xe2, 0x62, 0x00, 0x74, 0x05,
- 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x42,
- 0x2b, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x14, 0x02, 0x2c,
- 0xe2, 0x6e, 0x00, 0x72, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0x2d,
- 0x40, 0x07, 0x72, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x0f, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x66,
- 0x02, 0x00, 0x09, 0x40, 0x06, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x6e, 0x00,
- 0xe6, 0x63, 0x00, 0x64, 0x13, 0x67, 0x3c, 0x69, 0x60, 0x6b, 0x65, 0x73,
- 0x72, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0xa5, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe5, 0x65, 0x00, 0x69,
- 0x0d, 0x6c, 0x12, 0x72, 0x16, 0x79, 0x1c, 0xe2, 0x6c, 0x00, 0x72, 0x06,
- 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x0b, 0x66, 0x79,
- 0x00, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x07, 0x75, 0x66, 0x66, 0x00, 0x01,
- 0x72, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x11, 0x01, 0x27, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x3b, 0x75, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00,
- 0x07, 0x40, 0x09, 0x73, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x63, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x65, 0x75, 0x73,
- 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x04, 0x40, 0x60,
- 0x72, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe6, 0x65, 0x00, 0x69, 0x29, 0x6b,
- 0x2e, 0x6c, 0x59, 0x6e, 0x5f, 0x74, 0x6f, 0xe4, 0x00, 0x00, 0x64, 0x02,
- 0x72, 0x19, 0x73, 0x1b, 0x00, 0x7e, 0xe1, 0x65, 0x00, 0xe1, 0x76, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x09, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0x40, 0x00, 0x61, 0x79, 0x00,
- 0x40, 0x12, 0x6e, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x10,
- 0x6e, 0x14, 0x72, 0x1a, 0x02, 0x2e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x02, 0x2d, 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6d, 0x00,
- 0x40, 0x09, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xfa, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x60, 0x00, 0x07, 0xe3, 0x00,
- 0x00, 0x62, 0x02, 0x65, 0x09, 0x00, 0xfa, 0x40, 0x09, 0x6f, 0x61, 0x72,
- 0x64, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x23, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x09, 0x69, 0x0d, 0x00, 0xc3, 0x40, 0x06,
- 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6b, 0x00,
- 0x6e, 0x04, 0x40, 0x09, 0x69, 0x00, 0x40, 0x3b, 0x67, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x86, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x22, 0x69, 0x48, 0x75, 0x4d, 0xe4, 0x00, 0x00, 0x62, 0x02,
- 0x73, 0x08, 0x74, 0x0f, 0x00, 0x00, 0x40, 0x06, 0x61, 0x73, 0x65, 0x00,
- 0x40, 0x09, 0x68, 0x65, 0x65, 0x74, 0x00, 0x60, 0x09, 0x79, 0x70, 0x65,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08,
- 0x6c, 0x0a, 0x72, 0x19, 0x02, 0x2f, 0x40, 0x08, 0x6f, 0x6f, 0x6b, 0x00,
- 0x00, 0x37, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x73, 0x73, 0x00,
- 0x40, 0x82, 0x6e, 0x65, 0x00, 0x00, 0x07, 0x40, 0x09, 0x76, 0x65, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe4, 0x62, 0x00, 0x67, 0x0b, 0x6e, 0x12, 0x70,
- 0x39, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x56, 0x68, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6c, 0x07, 0x00, 0x0b, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x68, 0x69, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x08, 0x40, 0x09, 0x6e,
- 0x70, 0x6f, 0x72, 0x74, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x64, 0x00,
- 0x6e, 0x0f, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x3f, 0x00, 0x07, 0x00, 0x93, 0xe6, 0x00, 0x00, 0x62, 0x02,
- 0x63, 0x11, 0x64, 0x17, 0x6c, 0x2e, 0x74, 0x4a, 0x00, 0x06, 0xe2, 0x65,
- 0x00, 0x72, 0x04, 0x40, 0x09, 0x64, 0x00, 0x40, 0x07, 0x65, 0x61, 0x6b,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x12, 0xe1,
- 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x69, 0x6d, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x7a, 0x09, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x00, 0x5e, 0x00, 0x3b, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x7a,
- 0x41, 0xef, 0x64, 0x00, 0x41, 0xef, 0x6e, 0x67, 0x00, 0xc0, 0x61, 0x1a,
- 0x37, 0x00, 0x89, 0x01, 0x68, 0x02, 0xa8, 0x05, 0xfd, 0x05, 0x3d, 0x06,
- 0xf9, 0x08, 0x29, 0x09, 0x4a, 0x09, 0x80, 0x09, 0x00, 0x00, 0x9b, 0x09,
- 0x75, 0x0b, 0xb9, 0x0d, 0x14, 0x0f, 0x3f, 0x0f, 0x00, 0x00, 0x32, 0x11,
- 0x55, 0x12, 0xa1, 0x15, 0x41, 0x17, 0x52, 0x17, 0x76, 0x18, 0xa8, 0x18,
- 0x00, 0x00, 0xd6, 0x18, 0xf8, 0x63, 0x00, 0x00, 0x64, 0x12, 0x00, 0x66,
- 0x7c, 0x00, 0x6c, 0x9a, 0x00, 0x6e, 0xbc, 0x00, 0x72, 0xd0, 0x00, 0x74,
- 0xf6, 0x00, 0x76, 0x34, 0x01, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40, 0x09, 0x73, 0x73, 0x00, 0xe7,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x11, 0x68, 0x15, 0x6c, 0x1b, 0x70, 0x3a,
- 0x77, 0x55, 0x02, 0x30, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x61,
- 0x74, 0x00, 0x40, 0x06, 0x6c, 0x74, 0x00, 0x40, 0xed, 0x6e, 0x00, 0x40,
- 0x7a, 0x65, 0x61, 0x64, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x11, 0x79, 0x16,
- 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x40, 0x07, 0x73, 0x00, 0x40, 0x95, 0x63, 0x6b, 0x00, 0x01, 0x92,
- 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6e, 0x11, 0x02, 0x31, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0xed, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x12, 0x74, 0x17,
- 0x02, 0x32, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x06, 0x68, 0x69, 0x70, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x07, 0x00, 0x07, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe5, 0x00, 0x00,
- 0x65, 0x02, 0x6e, 0x07, 0x74, 0x0d, 0x79, 0x19, 0x02, 0x33, 0x40, 0x08,
- 0x73, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0xe1,
- 0x68, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x10, 0x73, 0x1f, 0x74,
- 0x21, 0x77, 0x27, 0x00, 0x12, 0xe2, 0x65, 0x00, 0x6c, 0x04, 0x40, 0x06,
- 0x64, 0x00, 0x40, 0x09, 0x6f, 0x77, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05,
- 0x40, 0x3b, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6b, 0x65, 0x00, 0x00, 0x00,
- 0x40, 0x09, 0x72, 0x61, 0x70, 0x00, 0x40, 0x09, 0x61, 0x74, 0x63, 0x68,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x4e, 0x69, 0x56, 0x6f, 0x79, 0x72, 0x99, 0x74, 0xab, 0x75, 0xb6, 0x00,
- 0x06, 0xe4, 0x63, 0x00, 0x72, 0x05, 0x74, 0x18, 0x75, 0x2b, 0x40, 0x09,
- 0x6c, 0x65, 0x00, 0xe2, 0x6b, 0x00, 0x6d, 0x08, 0x40, 0x07, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x34, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x47, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00,
- 0x09, 0x40, 0x06, 0x79, 0x00, 0x40, 0x09, 0x6e, 0x74, 0x75, 0x72, 0x65,
- 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x1c, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x79, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x06, 0x00, 0xfc,
- 0xe2, 0x6e, 0x00, 0x75, 0x16, 0xe1, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x0b, 0x63, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x08, 0x40, 0x00, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x09, 0x72,
- 0x00, 0xe2, 0x67, 0x00, 0x74, 0x06, 0x40, 0x08, 0x67, 0x65, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0xec, 0x40, 0x06, 0x6e, 0x74, 0x65,
- 0x00, 0xf7, 0x61, 0x00, 0x00, 0x65, 0x77, 0x00, 0x69, 0x12, 0x01, 0x6b,
- 0xa1, 0x01, 0x6c, 0xbd, 0x01, 0x6f, 0x32, 0x02, 0x72, 0xc4, 0x02, 0xe8,
- 0x64, 0x00, 0x66, 0x1a, 0x67, 0x2a, 0x6c, 0x2f, 0x6d, 0x31, 0x70, 0x39,
- 0x74, 0x50, 0x79, 0x64, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x09, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x00, 0x86, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00,
- 0x09, 0x40, 0x3a, 0x65, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x00, 0x40, 0x09,
- 0x6f, 0x6e, 0x00, 0x00, 0x09, 0x40, 0x07, 0x70, 0x6d, 0x65, 0x6e, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x45, 0x40, 0x09, 0x72, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40,
- 0x08, 0x74, 0x65, 0x00, 0x40, 0x06, 0x6e, 0x00, 0x00, 0xed, 0xe6, 0x61,
- 0x00, 0x64, 0x06, 0x69, 0x0c, 0x6c, 0x3e, 0x6e, 0x5c, 0x70, 0x6f, 0x40,
- 0x07, 0x73, 0x65, 0x64, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2,
- 0x74, 0x00, 0x76, 0x1a, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x09, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0x34, 0x00, 0x09, 0x40, 0x3b, 0x6e, 0x67,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x04,
- 0x74, 0x0a, 0x41, 0xa7, 0x79, 0x00, 0x40, 0x06, 0x69, 0x61, 0x6c, 0x00,
- 0x00, 0x5c, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe6, 0x62, 0x00,
- 0x64, 0x05, 0x6c, 0x21, 0x6d, 0x28, 0x70, 0x54, 0x73, 0x5e, 0x40, 0x09,
- 0x65, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x75, 0x0f, 0x40, 0x37,
- 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x74, 0x00,
- 0x3b, 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x09, 0x69, 0x74, 0x65,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x21, 0xe2, 0x6c, 0x00, 0x74, 0x10,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x7a, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0x40, 0xbb,
- 0x68, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x76, 0x0c, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x53, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0xd7, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x63,
- 0x02, 0x68, 0x09, 0x6c, 0x0f, 0x00, 0x93, 0x40, 0x08, 0x68, 0x61, 0x69,
- 0x72, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x08, 0x65, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x46, 0x69, 0x4e, 0xe2, 0x6d, 0x00, 0x72, 0x15,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x1a, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0d, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x02,
- 0x35, 0x00, 0x37, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
- 0x00, 0xe2, 0x6e, 0x00, 0x76, 0x15, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x7e, 0x00, 0x07, 0x40, 0x06, 0x69, 0x74, 0x79, 0x00, 0xe5, 0x6c, 0x00,
- 0x6e, 0x15, 0x72, 0x31, 0x75, 0x7e, 0x79, 0x85, 0xe1, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x06,
- 0x67, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x67, 0x00, 0x73, 0x09, 0x40, 0x09,
- 0x65, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x74, 0x72, 0x75,
- 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x69, 0x73, 0x6d, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x6f, 0x2d, 0x75, 0x40, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x1d, 0x02, 0x36, 0xe3, 0x6e, 0x00, 0x6f,
- 0x04, 0x76, 0x10, 0x40, 0x07, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x5c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x6d, 0x00, 0x40, 0x5e, 0x70, 0x61, 0x67, 0x65, 0x00, 0x00, 0x59, 0xe3,
- 0x65, 0x00, 0x69, 0x42, 0x79, 0x51, 0xe4, 0x61, 0x00, 0x65, 0x07, 0x6d,
- 0x13, 0x70, 0x27, 0x40, 0x3b, 0x73, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0xb2, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x07, 0x64, 0x65, 0x00,
- 0x40, 0x07, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x0b, 0x40, 0x00,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x23, 0xe1, 0x63,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x4b, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe1, 0x63, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x74, 0x08, 0x00, 0x0b, 0x40, 0x00, 0x62,
- 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x37, 0xe3, 0x62,
- 0x00, 0x6f, 0x05, 0x76, 0x09, 0x40, 0x06, 0x6c, 0x65, 0x00, 0x40, 0x06,
- 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe5, 0x64, 0x00, 0x6a, 0x02, 0x6d,
- 0x07, 0x70, 0x09, 0x72, 0x1c, 0x00, 0xed, 0x40, 0x09, 0x61, 0x79, 0x00,
- 0x01, 0x40, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x02, 0x38, 0x40,
- 0xed, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0xe2, 0x6b, 0x00, 0x74, 0x05, 0x40, 0x07, 0x69,
- 0x6e, 0x00, 0x40, 0x08, 0x61, 0x6c, 0x6b, 0x65, 0x72, 0x00, 0xfb, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x57, 0x00, 0x66, 0x49, 0x01, 0x69,
- 0x57, 0x01, 0x6c, 0xeb, 0x01, 0x6f, 0x24, 0x02, 0x72, 0x59, 0x02, 0x74,
- 0x85, 0x02, 0x75, 0x92, 0x02, 0x79, 0x98, 0x02, 0x02, 0x39, 0xe4, 0x63,
- 0x00, 0x6c, 0x10, 0x6d, 0x25, 0x75, 0x45, 0xe1, 0x65, 0x00, 0xe2, 0x6d,
- 0x00, 0x72, 0x06, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x06, 0xe1,
- 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x12, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x3f, 0x00, 0x07, 0x40, 0x06, 0x6c, 0x74, 0x65, 0x72, 0x00, 0xe4,
- 0x61, 0x00, 0x63, 0x21, 0x6e, 0x5b, 0x72, 0xbe, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x0b, 0x00, 0xfe, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x37, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x74, 0x0f, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x1b, 0x02, 0x3a, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x02, 0x3b, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe3, 0x64, 0x00, 0x65, 0x0e, 0x73, 0x19, 0xe2, 0x61,
- 0x00, 0x65, 0x05, 0x40, 0x06, 0x6e, 0x74, 0x00, 0x40, 0x37, 0x64, 0x00,
- 0x40, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x1d, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x02, 0x22, 0xe1,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x62, 0x00,
- 0x76, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54,
- 0x00, 0x54, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xea,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x12, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x3b, 0x69, 0x61, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x08,
- 0x40, 0x09, 0x6c, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x74, 0x00, 0xe5, 0x61, 0x00, 0x62, 0x05, 0x63, 0x25, 0x6c, 0x3d,
- 0x6e, 0x45, 0x40, 0x3b, 0x6e, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6f, 0x6e, 0x00, 0x40,
- 0x08, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x0e, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x00,
- 0x00, 0x00, 0x06, 0x40, 0x07, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x06, 0x69, 0x13, 0x40, 0x9b, 0x62, 0x6c, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x00, 0x4b, 0x00, 0x37, 0x00,
- 0x09, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x02, 0x3c, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x0c, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x75, 0x00, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1c,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x02, 0x3d, 0x40, 0x09, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe3, 0x67, 0x00, 0x6c, 0x06, 0x72, 0x27, 0x40,
- 0x06, 0x67, 0x65, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x06, 0x6d, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x18, 0xe2, 0x75, 0x00, 0x79, 0x0e, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x4c, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61,
- 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x04, 0x41, 0x20, 0x6b, 0x00, 0x40,
- 0x09, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x63,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6e, 0x63, 0x74, 0x00,
- 0x00, 0x0b, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x1b, 0x00, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x18, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x22, 0x64, 0x65, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x06, 0x40, 0x06, 0x74, 0x6f, 0x72, 0x00, 0x60, 0x07,
- 0x67, 0x65, 0x6e, 0x61, 0x73, 0x65, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe5,
- 0x63, 0x00, 0x66, 0x05, 0x67, 0x15, 0x73, 0x19, 0x74, 0x27, 0x40, 0x09,
- 0x65, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x02, 0x3e, 0x40, 0x0b, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63,
- 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x0b, 0x40,
- 0x3b, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xf9, 0x61, 0x00, 0x00,
- 0x65, 0x04, 0x00, 0x66, 0x46, 0x00, 0x69, 0x56, 0x00, 0x6c, 0x74, 0x01,
- 0x70, 0x76, 0x01, 0x74, 0x7f, 0x01, 0x75, 0x83, 0x01, 0x76, 0xb2, 0x01,
- 0x42, 0x3f, 0x79, 0x00, 0xe3, 0x63, 0x00, 0x67, 0x1d, 0x74, 0x23, 0xe1,
- 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x0c, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0xed, 0x61, 0x74, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x0e, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x45, 0x40, 0x00,
- 0x69, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61, 0x72,
- 0x65, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x63, 0x1e, 0x00,
- 0x67, 0x5a, 0x00, 0x6d, 0x6e, 0x00, 0x6e, 0x77, 0x00, 0x71, 0xa2, 0x00,
- 0x72, 0xbc, 0x00, 0x76, 0xdb, 0x00, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x02, 0x40, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x21, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x41, 0xa7,
- 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x73, 0x08,
- 0x00, 0x5c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x73, 0x65,
- 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x66, 0x04, 0x40,
- 0x3b, 0x64, 0x00, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0x40, 0x00, 0x69, 0x6e,
- 0x61, 0x74, 0x6f, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x71, 0x12, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x51, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x00, 0x56,
- 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3a, 0x40, 0x00,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x13, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11, 0x01, 0xf9,
- 0xe2, 0x62, 0x00, 0x6e, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x40, 0x07,
- 0x63, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x06,
- 0x00, 0x06, 0x40, 0x09, 0x68, 0x69, 0x6e, 0x69, 0x75, 0x6d, 0x00, 0x40,
- 0x09, 0x61, 0x00, 0xe4, 0x64, 0x00, 0x67, 0x04, 0x73, 0x08, 0x78, 0x22,
- 0x40, 0x0b, 0x65, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f,
- 0x00, 0x07, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x58, 0x00, 0x69, 0x82, 0x00,
- 0x6f, 0xc7, 0x00, 0x75, 0xf9, 0x01, 0xe3, 0x67, 0x00, 0x6e, 0x2d, 0x72,
- 0x3c, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe3, 0x69, 0x00, 0x75, 0x10,
- 0x79, 0x1e, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0x00, 0x07, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x59, 0x40, 0x37, 0x6e, 0x67,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x6e, 0x0e, 0x73, 0x1e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x0b, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x3b, 0x64, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x09, 0x6e, 0x65, 0x00, 0xe5, 0x67, 0x00, 0x6a, 0x13, 0x6d, 0x19, 0x73,
- 0x2f, 0x74, 0x33, 0xe1, 0x6f, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x00, 0x09, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x6f, 0x68, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00,
- 0x00, 0x07, 0x40, 0x82, 0x65, 0x00, 0x40, 0x09, 0x61, 0x73, 0x73, 0x65,
- 0x00, 0xf8, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x64, 0x38, 0x00, 0x67,
- 0x3c, 0x00, 0x6c, 0x69, 0x00, 0x6e, 0x7b, 0x00, 0x74, 0x09, 0x01, 0x75,
- 0x14, 0x01, 0x00, 0xec, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0xe2, 0x63, 0x00, 0x7a, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x37, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x00,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x18, 0x40, 0x06, 0x72,
- 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00,
- 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe1,
- 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x3a, 0x68, 0x00, 0x40,
- 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0d,
- 0x6f, 0x33, 0x73, 0x3a, 0x00, 0x09, 0x40, 0x07, 0x74, 0x69, 0x7a, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x0e, 0x7a, 0x1b,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x06, 0x6c, 0x6f, 0x67,
- 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x62, 0x00, 0x74, 0x15, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x00, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x1b, 0x00, 0x40, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x02, 0x41, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0xed, 0x40, 0x00,
- 0x63, 0x00, 0x40, 0x00, 0x6e, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x07,
- 0x40, 0x06, 0x63, 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x72, 0x0f, 0x02, 0x42, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x0d,
- 0x40, 0x06, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00,
- 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x64, 0x29, 0x00, 0x67, 0x30, 0x00, 0x69, 0x35, 0x00, 0x6f, 0x86,
- 0x00, 0x73, 0xc0, 0x00, 0x74, 0xd7, 0x00, 0x75, 0x11, 0x01, 0x79, 0x3a,
- 0x01, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x0e, 0x40,
- 0x00, 0x6f, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x00, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x01, 0x20, 0x40, 0x06, 0x72, 0x69, 0x74, 0x65,
- 0x00, 0x40, 0x07, 0x75, 0x65, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x17, 0x67,
- 0x1b, 0x6d, 0x30, 0x74, 0x32, 0x7a, 0x3f, 0xe2, 0x62, 0x00, 0x6c, 0x10,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x00, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x37, 0x65, 0x00, 0x00, 0x09, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x09, 0x40, 0x00, 0x72,
- 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09,
- 0x65, 0x6e, 0x00, 0xe3, 0x6d, 0x00, 0x74, 0x0c, 0x75, 0x14, 0x40, 0x00,
- 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x40, 0x00,
- 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x07, 0x40,
- 0x09, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x78, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0xd3, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x75, 0x2c, 0x02, 0x43, 0x40,
- 0x3b, 0x6c, 0x00, 0xe4, 0x66, 0x00, 0x6e, 0x07, 0x73, 0x09, 0x74, 0x17,
- 0x40, 0x06, 0x72, 0x69, 0x63, 0x65, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x41, 0x89, 0x72, 0x65, 0x00, 0xe3, 0x63,
- 0x00, 0x64, 0x0a, 0x6e, 0x18, 0x40, 0x0b, 0x6c, 0x65, 0x61, 0x72, 0x69,
- 0x7a, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x06, 0x63, 0x69, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x3f, 0xe1, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x06, 0x6e, 0x74, 0x00,
- 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07,
- 0xf8, 0x61, 0x00, 0x00, 0x65, 0x41, 0x00, 0x69, 0x77, 0x00, 0x6c, 0x93,
- 0x00, 0x6f, 0xd2, 0x00, 0x72, 0x13, 0x01, 0x74, 0xb2, 0x01, 0x75, 0xbe,
- 0x01, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x6d, 0x04,
- 0x75, 0x2f, 0x40, 0x07, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x7a, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x0b, 0x40, 0x06, 0x72, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x18, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c,
- 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x37, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x53, 0x00, 0x06, 0x02, 0x44,
- 0xe2, 0x63, 0x00, 0x6c, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x0b, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x74,
- 0x6f, 0x72, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x0f, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x72, 0x00, 0x79, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x00,
- 0x62, 0x6c, 0x79, 0x00, 0x00, 0xd1, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0x9c, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x06,
- 0x73, 0x21, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x07, 0x6d, 0x0b, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0xc7,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06,
- 0xe4, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x86, 0x6f, 0x8b, 0xe1, 0x76, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x06, 0x74, 0x79, 0x00,
- 0xe3, 0x63, 0x00, 0x64, 0x35, 0x73, 0x3d, 0xe2, 0x61, 0x00, 0x69, 0x1e,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00, 0x42,
- 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe4,
- 0x61, 0x00, 0x69, 0x05, 0x6f, 0x18, 0x75, 0x1c, 0x40, 0x06, 0x6e, 0x74,
- 0x00, 0xe3, 0x6e, 0x00, 0x6f, 0x04, 0x76, 0x08, 0x40, 0x3b, 0x67, 0x00,
- 0x40, 0x06, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x00, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40,
- 0x0b, 0x76, 0x65, 0x00, 0x40, 0x00, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69,
- 0x6e, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x07, 0x69,
- 0x09, 0x79, 0x0e, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a,
- 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x00, 0x06, 0xf8, 0x61, 0x00, 0x00, 0x62,
- 0x22, 0x00, 0x65, 0x26, 0x00, 0x69, 0x3e, 0x00, 0x6d, 0x86, 0x00, 0x6f,
- 0xbf, 0x00, 0x72, 0xe5, 0x00, 0x76, 0xfe, 0x00, 0xe2, 0x69, 0x00, 0x6e,
- 0x14, 0xe1, 0x6c, 0x00, 0xe2, 0x6c, 0x00, 0x6d, 0x06, 0x40, 0x06, 0x65,
- 0x75, 0x72, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x67,
- 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x64,
- 0x00, 0x73, 0x04, 0x76, 0x27, 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x19, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x13, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x09, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x00, 0x00, 0x22, 0xe2, 0x61,
- 0x00, 0x69, 0x30, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x06, 0x40, 0x07, 0x74, 0x69, 0x73, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2,
- 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00,
- 0xe3, 0x63, 0x00, 0x65, 0x04, 0x6e, 0x09, 0x40, 0x06, 0x6b, 0x00, 0x40,
- 0x06, 0x72, 0x65, 0x00, 0x40, 0x06, 0x67, 0x65, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x09, 0x73, 0x68, 0x00, 0xfa, 0x61,
- 0x00, 0x00, 0x63, 0x2e, 0x00, 0x65, 0x9b, 0x00, 0x69, 0xf3, 0x00, 0x6b,
- 0x8b, 0x01, 0x6f, 0x9e, 0x01, 0x70, 0xbe, 0x01, 0x73, 0x6b, 0x02, 0x74,
- 0x93, 0x02, 0x75, 0x0c, 0x03, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x7a,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x0b, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x72, 0x1f,
- 0x00, 0x00, 0x40, 0x07, 0x6e, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x02, 0x45, 0x40, 0x09,
- 0x6e, 0x74, 0x00, 0x40, 0x00, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x3e,
- 0xe2, 0x62, 0x00, 0x70, 0x14, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x54,
- 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x46, 0x00,
- 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x19, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08,
- 0x72, 0x00, 0x00, 0x0b, 0xe3, 0x63, 0x00, 0x6c, 0x15, 0x72, 0x1e, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x63,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x74, 0x00, 0x76, 0x20, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x49, 0x40, 0x07, 0x72, 0x00, 0xe2,
- 0x66, 0x00, 0x6f, 0x0a, 0x40, 0x00, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x36, 0x64, 0x00, 0x40, 0x37, 0x6e, 0x67, 0x00, 0xe5, 0x63, 0x00, 0x64,
- 0x21, 0x67, 0x38, 0x72, 0x57, 0x73, 0x89, 0xe1, 0x63, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40,
- 0x07, 0x6d, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x11, 0x00, 0xd5, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x1d, 0x6f, 0x26, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c,
- 0x07, 0x40, 0xdb, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x37, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x22, 0x00, 0x37, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0x40, 0x7a, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x74, 0x07, 0x00,
- 0x06, 0x40, 0x1c, 0x6c, 0x6c, 0x00, 0x40, 0x06, 0x6f, 0x70, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x47, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x12,
- 0x69, 0x42, 0x6f, 0x63, 0xe1, 0x69, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x0e, 0xe1, 0x6f, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x48, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x63,
- 0x00, 0x73, 0x12, 0x74, 0x16, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6e, 0x08,
- 0x74, 0x21, 0x40, 0x07, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x3b, 0xe1,
- 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x06, 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x08, 0x40,
- 0x08, 0x75, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x29, 0xe2, 0x6e, 0x00,
- 0x74, 0x12, 0xe3, 0x61, 0x00, 0x65, 0x07, 0x79, 0x09, 0x40, 0x06, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x17, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x0e, 0xe1, 0x79, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x01, 0x27, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x6d, 0xe3, 0x62,
- 0x00, 0x6f, 0x10, 0x76, 0x14, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x54, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x07, 0x40, 0x07,
- 0x74, 0x75, 0x64, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00,
- 0x00, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x2b, 0x00, 0x68, 0x18, 0x01,
- 0x6f, 0x31, 0x01, 0x72, 0x68, 0x01, 0xe2, 0x63, 0x00, 0x69, 0x10, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0xa7, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d,
- 0x06, 0x00, 0x34, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74,
- 0x00, 0xe4, 0x63, 0x00, 0x6e, 0x2b, 0x72, 0x3a, 0x73, 0xce, 0xe1, 0x74,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x6f, 0x19,
- 0x02, 0x49, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x37, 0x64, 0x00,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0xcc, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x67,
- 0x02, 0x69, 0x08, 0x6d, 0x20, 0x72, 0x6d, 0x00, 0x50, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x07, 0x6e, 0x74,
- 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x14, 0x69, 0x2a, 0xe3,
- 0x62, 0x00, 0x6e, 0x05, 0x74, 0x09, 0x40, 0x54, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02,
- 0x72, 0x0d, 0x00, 0x4b, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x37, 0x40,
- 0x00, 0x79, 0x00, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x12, 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x37, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40,
- 0x00, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x58, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2,
- 0x6e, 0x00, 0x78, 0x18, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x39, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x47, 0xe1,
- 0x66, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x57, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40,
- 0xed, 0x63, 0x74, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x14, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x75, 0x73, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x69,
- 0x75, 0x6d, 0x00, 0xf4, 0x61, 0x00, 0x00, 0x65, 0x26, 0x00, 0x69, 0x55,
- 0x00, 0x6f, 0xc7, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00,
- 0x42, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x0b, 0x02, 0x4a,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x06, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x65, 0x40, 0x3b, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x29, 0x6f, 0x58,
- 0xe2, 0x6e, 0x00, 0x74, 0x10, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x8b, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x37, 0x67,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x15,
- 0x72, 0x1b, 0x74, 0x1f, 0x02, 0x4b, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4,
- 0x69, 0x00, 0x6c, 0x04, 0x74, 0x14, 0x75, 0x33, 0x40, 0x00, 0x64, 0x00,
- 0xe2, 0x75, 0x00, 0x76, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00,
- 0x65, 0x02, 0x00, 0x3b, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x06, 0x6c, 0x00, 0xe2,
- 0x72, 0x00, 0x74, 0x02, 0x00, 0x7a, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x7f, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02,
- 0x63, 0x09, 0x64, 0x0f, 0x69, 0x15, 0x6c, 0x1c, 0x79, 0x21, 0x00, 0x07,
- 0x40, 0x06, 0x65, 0x72, 0x72, 0x79, 0x00, 0x40, 0x06, 0x6c, 0x61, 0x77,
- 0x00, 0x40, 0x06, 0x72, 0x6f, 0x70, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x61, 0x70, 0x00, 0x00, 0xf4, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x72, 0x20, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x6f, 0x73, 0x65, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x06, 0x40, 0x00, 0x72, 0x6d, 0x61, 0x00, 0xe2, 0x74,
- 0x00, 0x77, 0x04, 0x40, 0x06, 0x69, 0x00, 0x00, 0x09, 0xc0, 0x61, 0x1a,
- 0x37, 0x00, 0x58, 0x02, 0x64, 0x02, 0x33, 0x03, 0xa0, 0x03, 0xfb, 0x03,
- 0xa8, 0x04, 0x89, 0x05, 0x00, 0x00, 0x00, 0x00, 0x90, 0x05, 0x9c, 0x05,
- 0x57, 0x06, 0x05, 0x07, 0xa4, 0x07, 0xd6, 0x07, 0x00, 0x00, 0x9f, 0x08,
- 0x54, 0x09, 0xd2, 0x12, 0x0e, 0x13, 0x21, 0x13, 0x00, 0x00, 0x7c, 0x14,
- 0x00, 0x00, 0x85, 0x14, 0xfb, 0x62, 0x00, 0x00, 0x63, 0x29, 0x00, 0x64,
- 0x43, 0x00, 0x65, 0x48, 0x00, 0x67, 0x5e, 0x00, 0x6c, 0xcf, 0x00, 0x6d,
- 0x2b, 0x01, 0x70, 0x6c, 0x01, 0x72, 0x9f, 0x01, 0x73, 0xb3, 0x01, 0x74,
- 0xd6, 0x01, 0xe2, 0x65, 0x00, 0x6f, 0x10, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x07, 0x73, 0x00, 0x40, 0x06, 0x63, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x65,
- 0x6d, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe3, 0x6e, 0x00, 0x6f, 0x31, 0x72, 0x37, 0xe1, 0x6f, 0x00, 0xe1, 0x73,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x74, 0x06, 0x00, 0x3a, 0x40, 0x07,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x08, 0x73, 0x0d, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x56, 0x6e, 0x61,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x65, 0x16, 0x69, 0x1a, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x27,
- 0x6f, 0x2c, 0x79, 0x3a, 0x01, 0x61, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x06, 0x40, 0x00, 0x6c,
- 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00,
- 0x06, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x08, 0x6e, 0x67, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x0d, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x6f, 0x25, 0x00, 0x00,
- 0x40, 0x00, 0x6e, 0x74, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x72, 0x04, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x06,
- 0x40, 0x09, 0x61, 0x63, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x68,
- 0x0a, 0x40, 0x06, 0x73, 0x6f, 0x6e, 0x00, 0x40, 0x2c, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x72, 0x07, 0x40, 0x00, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0xe3, 0x69, 0x00,
- 0x72, 0x05, 0x79, 0x0b, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x07, 0x68,
- 0x65, 0x61, 0x00, 0x00, 0x06, 0xe2, 0x70, 0x00, 0x74, 0x06, 0x40, 0x00,
- 0x6f, 0x72, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x73,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x63, 0x00, 0xe3, 0x68, 0x00, 0x6f, 0x07, 0x72, 0x1c, 0x40,
- 0x07, 0x65, 0x72, 0x6d, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x0b, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00,
- 0x69, 0x63, 0x00, 0x40, 0x06, 0x69, 0x62, 0x65, 0x00, 0xe2, 0x62, 0x00,
- 0x73, 0x05, 0x40, 0x5e, 0x6c, 0x65, 0x00, 0x00, 0x07, 0xe6, 0x65, 0x00,
- 0x68, 0x0d, 0x69, 0x25, 0x6b, 0x33, 0x6f, 0x54, 0x74, 0x75, 0xe3, 0x00,
- 0x00, 0x73, 0x02, 0x79, 0x04, 0x00, 0x0b, 0x00, 0x54, 0x00, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x6f, 0x00, 0x79, 0x05, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe1,
- 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x68, 0x0b, 0x79, 0x11, 0x02, 0x4c,
- 0xe2, 0x72, 0x00, 0x79, 0x02, 0x01, 0x20, 0x00, 0x06, 0x40, 0x08, 0x65,
- 0x61, 0x64, 0x00, 0x40, 0x08, 0x62, 0x69, 0x72, 0x64, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x2e, 0x75, 0x40, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x8b, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73,
- 0x07, 0x00, 0x06, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x68, 0x69,
- 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x40, 0x06, 0x72, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00,
- 0xe7, 0x00, 0x00, 0x61, 0x02, 0x64, 0x1b, 0x67, 0x41, 0x6e, 0x4a, 0x6f,
- 0x4f, 0x73, 0x5a, 0x01, 0xca, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x1c, 0xe2,
- 0x65, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x71, 0x75,
- 0x61, 0x74, 0x00, 0x40, 0x00, 0x6d, 0x73, 0x00, 0x40, 0x08, 0x65, 0x72,
- 0x69, 0x64, 0x6f, 0x6f, 0x00, 0x40, 0x00, 0x27, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0xe5, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x0b, 0x73, 0x1e, 0x74, 0x23,
- 0x00, 0x1a, 0x40, 0x09, 0x65, 0x63, 0x74, 0x72, 0x69, 0x63, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x2c, 0x65, 0x6c, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x1d, 0x00, 0xfe, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00,
- 0x07, 0x40, 0x09, 0x74, 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x66, 0x00, 0xe5,
- 0x00, 0x00, 0x65, 0x06, 0x69, 0x48, 0x72, 0x70, 0x75, 0x85, 0x20, 0x4c,
- 0x09, 0x00, 0xff, 0xff, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x01, 0x20, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x0c, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x53, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x5c, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x00, 0x57, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x64, 0x12, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x3b, 0x00, 0x06, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x3b, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0xad, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x02, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x67, 0x44, 0x69, 0x5c, 0x6e, 0x8e,
- 0x72, 0xae, 0x00, 0x06, 0xe2, 0x72, 0x00, 0x73, 0x06, 0x40, 0x07, 0x61,
- 0x74, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x01, 0xc1, 0x40, 0x37, 0x64, 0x00, 0xe3, 0x62, 0x00, 0x6f, 0x10,
- 0x76, 0x1c, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74,
- 0x79, 0x00, 0x40, 0x54, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x53, 0x00, 0x00, 0x40, 0x08, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xe2, 0x63,
- 0x00, 0x74, 0x05, 0x40, 0x08, 0x61, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x10, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x3b, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b,
- 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x0c, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x37, 0x65, 0x64, 0x00, 0x00, 0x3a, 0xe2, 0x61, 0x00, 0x79,
- 0x05, 0x40, 0x06, 0x72, 0x79, 0x00, 0x01, 0xa7, 0xe2, 0x61, 0x00, 0x65,
- 0x0f, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x43, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x00,
- 0x79, 0x64, 0x72, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x82,
- 0x40, 0x08, 0x61, 0x74, 0x00, 0xe6, 0x61, 0x00, 0x64, 0x42, 0x65, 0x46,
- 0x69, 0x6f, 0x6c, 0x83, 0x75, 0x98, 0xe2, 0x70, 0x00, 0x74, 0x1a, 0xe1,
- 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x07, 0x69, 0x09, 0x6f, 0x0e, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00,
- 0x40, 0x08, 0x6f, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x05, 0x40, 0x09, 0x6d,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00,
- 0xe2, 0x68, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x06, 0x40, 0x3a, 0x61, 0x6c, 0x6c,
- 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x38, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe7, 0x00, 0x00, 0x65, 0x02, 0x69, 0x28, 0x6d, 0x62, 0x6e, 0x7b, 0x70,
- 0x81, 0x77, 0x8d, 0x02, 0x4e, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x09,
- 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x06, 0x00, 0x06, 0x40, 0x00, 0x6c,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x31,
- 0xe2, 0x69, 0x00, 0x75, 0x11, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x0b, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x65,
- 0x00, 0x74, 0x06, 0x40, 0x06, 0x6e, 0x64, 0x6f, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe3, 0x64,
- 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x37, 0x00, 0x06, 0x40, 0x00, 0x74,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x5e, 0x00, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x65, 0x64, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x06, 0x67, 0x16, 0x6b, 0x56, 0x6e, 0x5f, 0x6f, 0x85, 0x74, 0x8c, 0x01,
- 0x05, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x04,
- 0x00, 0x08, 0x00, 0x07, 0x40, 0x09, 0x74, 0x65, 0x00, 0xe8, 0x00, 0x00,
- 0x62, 0x02, 0x68, 0x07, 0x69, 0x0b, 0x6c, 0x1a, 0x6f, 0x1e, 0x75, 0x29,
- 0x79, 0x2d, 0x00, 0x2f, 0x40, 0x09, 0x61, 0x74, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x73, 0x00, 0x01,
- 0x15, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x1d, 0x01, 0x64, 0xe2, 0x65,
- 0x00, 0x69, 0x1c, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x74, 0x02, 0x77, 0x08, 0x00, 0x2c, 0x40, 0x07, 0x69, 0x6d, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x73, 0x61, 0x75, 0x72, 0x00, 0x00, 0x07, 0xe4, 0x63, 0x00,
- 0x64, 0x11, 0x72, 0x15, 0x78, 0x1b, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x09, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x06, 0x61, 0x6d, 0x61, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x64, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x06, 0xe7,
- 0x00, 0x00, 0x68, 0x02, 0x6c, 0x18, 0x6f, 0x5c, 0x70, 0x61, 0x73, 0x78,
- 0x74, 0x9f, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x06, 0x40, 0x07, 0x72, 0x69, 0x61, 0x00, 0x40, 0x06, 0x6e,
- 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe3, 0x69, 0x00, 0x6d, 0x04, 0x70, 0x35,
- 0x40, 0x06, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02,
- 0x74, 0x06, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x04, 0x00, 0x09, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x0d,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x37, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0x40, 0x00, 0x69, 0x61, 0x00, 0x40, 0x06,
- 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x00, 0xf3, 0xe2, 0x6f, 0x00, 0x74, 0x1c, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x08, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40,
- 0x06, 0x69, 0x63, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x07, 0x40, 0x00,
- 0x72, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe6, 0x65, 0x00, 0x67,
- 0x73, 0x69, 0x77, 0x6b, 0x7f, 0x6e, 0x81, 0x74, 0x86, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x66, 0x67, 0x02, 0x4f, 0xe1, 0x74, 0x00, 0xe6, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6c, 0x29, 0x6e, 0x2d, 0x6f, 0x33, 0x02, 0x50,
- 0x40, 0x00, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x1a, 0xe1, 0x6e, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x06, 0x73, 0x0c, 0x00, 0x53, 0x40,
- 0x00, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x53, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x73,
- 0x0c, 0x79, 0x12, 0x00, 0x09, 0x40, 0x06, 0x74, 0x65, 0x00, 0x40, 0x00,
- 0x61, 0x6c, 0x00, 0x40, 0x06, 0x68, 0x69, 0x70, 0x00, 0x00, 0x06, 0x40,
- 0x00, 0x75, 0x6c, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x67, 0x69,
- 0x62, 0x6c, 0x65, 0x00, 0x00, 0x09, 0x40, 0x06, 0x64, 0x6c, 0x00, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x69, 0x08, 0x79, 0x17, 0x00, 0x07, 0x40, 0x08,
- 0x61, 0x6c, 0x6c, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x6f, 0xc1, 0x61, 0x19,
- 0x37, 0x00, 0x39, 0x00, 0x87, 0x00, 0xc8, 0x00, 0xfb, 0x02, 0x10, 0x03,
- 0x2f, 0x03, 0x4d, 0x03, 0x9f, 0x03, 0x2d, 0x04, 0x90, 0x04, 0xc9, 0x04,
- 0xd6, 0x04, 0xdd, 0x04, 0x00, 0x00, 0x23, 0x05, 0x3c, 0x05, 0x67, 0x06,
- 0x7e, 0x06, 0xba, 0x06, 0xd8, 0x07, 0x6e, 0x09, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x75, 0x09, 0x00, 0x07, 0xe5, 0x62, 0x00, 0x6d, 0x13, 0x70,
- 0x1d, 0x72, 0x28, 0x73, 0x2f, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x02, 0x51, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x17, 0x62, 0x69, 0x67, 0x75, 0x61, 0x74, 0x65, 0x00, 0x40, 0x3b,
- 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x6d,
- 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x08, 0x40, 0x00, 0x65,
- 0x6d, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x3b, 0x72, 0x6f, 0x75, 0x73, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x14, 0x75, 0x1e, 0xe2, 0x6e, 0x00, 0x72, 0x08,
- 0x40, 0x07, 0x64, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x6d, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x6c, 0x69, 0x65, 0x76, 0x69, 0x6e, 0x67,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x51, 0x40,
- 0x09, 0x65, 0x6e, 0x74, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x68, 0x2c, 0x00, 0x69, 0x34, 0x00, 0x6c, 0x6c, 0x00, 0x6f, 0x7e, 0x00,
- 0x72, 0x6c, 0x01, 0x75, 0xf4, 0x01, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x17, 0x00, 0x33, 0xe2,
- 0x62, 0x00, 0x6e, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x54, 0x00, 0x00, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x37, 0x61, 0x72, 0x67, 0x65, 0x64, 0x00, 0xe1, 0x70,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x06, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x00, 0x5e, 0x00, 0x37, 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x3a, 0x00, 0x37,
- 0xe9, 0x00, 0x00, 0x67, 0x02, 0x6c, 0x0a, 0x6d, 0x14, 0x6e, 0x51, 0x72,
- 0x85, 0x74, 0x99, 0x75, 0xa1, 0x76, 0xc1, 0x00, 0x15, 0x40, 0x06, 0x72,
- 0x61, 0x70, 0x68, 0x79, 0x00, 0x40, 0x08, 0x6f, 0x72, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe3, 0x62, 0x00, 0x66, 0x1e, 0x6d, 0x30, 0xe1, 0x6f,
- 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x75, 0x02, 0x01, 0x20, 0x40, 0x07, 0x72, 0x65, 0x00, 0x41, 0x20,
- 0x6f, 0x64, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x09, 0x73, 0x25, 0x40,
- 0x3b, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x3b, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x3b, 0x40, 0x06, 0x68, 0x65, 0x71, 0x75, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x0b, 0x00, 0xd5, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x09, 0x00, 0x65, 0xe2, 0x65,
- 0x00, 0x69, 0x4c, 0xe3, 0x65, 0x00, 0x70, 0x10, 0x74, 0x21, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7f, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x06, 0x79, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x52, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x53, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04,
- 0x40, 0x00, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00,
- 0x42, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x37, 0x67, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09,
- 0x00, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x0b, 0x40, 0x07, 0x73, 0x69, 0x76,
- 0x65, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x09, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x06, 0x6e, 0x74, 0x00, 0x40,
- 0x06, 0x6f, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x2c, 0x40, 0x3b, 0x75, 0x6c,
- 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x77,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x91, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x72,
- 0x0b, 0x40, 0x06, 0x67, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x07, 0x61, 0x6e, 0x63, 0x68, 0x69, 0x73, 0x65, 0x6d, 0x65, 0x6e,
- 0x74, 0x00, 0xe3, 0x6f, 0x00, 0x72, 0x0a, 0x75, 0x26, 0x40, 0x07, 0x72,
- 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x73, 0x0f, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0xed, 0x00, 0x37, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x3b, 0x64, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0xe9, 0x00, 0x00, 0x61, 0x02, 0x63, 0x18, 0x65, 0x2d, 0x70, 0x4f, 0x72,
- 0x54, 0x74, 0x59, 0x77, 0x60, 0x79, 0x79, 0x00, 0x47, 0xe2, 0x62, 0x00,
- 0x72, 0x07, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x6d,
- 0x6f, 0x6e, 0x69, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x76, 0x0a, 0x40, 0x3b, 0x72,
- 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x6f, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x67, 0x00,
- 0x40, 0x09, 0x6f, 0x77, 0x65, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x72,
- 0x00, 0x73, 0x04, 0x74, 0x0a, 0x40, 0x07, 0x65, 0x00, 0x40, 0x09, 0x68,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x00, 0x00, 0xe2, 0x6c,
- 0x00, 0x6e, 0x1f, 0xe1, 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x02, 0x53, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x66,
- 0x00, 0x74, 0x18, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x09, 0x6e, 0x74, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x1c, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x05,
- 0x40, 0x00, 0x76, 0x65, 0x00, 0x40, 0x00, 0x72, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x09, 0x40, 0x09, 0x74, 0x74, 0x65, 0x00, 0x40,
- 0x0b, 0x6f, 0x64, 0x67, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1e, 0x69,
- 0x37, 0xe3, 0x6c, 0x00, 0x6e, 0x02, 0x79, 0x0c, 0x00, 0x3b, 0x40, 0x07,
- 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x2c, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x02, 0x54, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x73, 0x73,
- 0x69, 0x76, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x05,
- 0x40, 0x3b, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x69, 0x7a, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xf7, 0x61, 0x00, 0x00, 0x65, 0x2f, 0x00,
- 0x69, 0x80, 0x00, 0x6c, 0x86, 0x00, 0x6f, 0x8f, 0x00, 0x72, 0xbb, 0x00,
- 0x75, 0xd8, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x23, 0xe1, 0x61, 0x00, 0xe2,
- 0x67, 0x00, 0x74, 0x17, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x02, 0x51, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40, 0x09, 0x63, 0x68, 0x65,
- 0x72, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x15, 0x72, 0x35, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x0f, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x40,
- 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x74,
- 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x06,
- 0x40, 0x07, 0x6c, 0x00, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x0b, 0x72, 0x69, 0x74, 0x00, 0x40, 0x07, 0x65, 0x61, 0x73, 0x75, 0x72,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0c, 0x69, 0x10,
- 0x73, 0x17, 0xe2, 0x62, 0x00, 0x6c, 0x05, 0x40, 0x06, 0x6c, 0x65, 0x00,
- 0x00, 0x06, 0x40, 0x54, 0x64, 0x00, 0x41, 0xa7, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6f,
- 0x00, 0xe3, 0x6f, 0x00, 0x70, 0x04, 0x76, 0x0f, 0x40, 0x06, 0x66, 0x00,
- 0x40, 0x00, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x40,
- 0x22, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x28, 0xe3,
- 0x62, 0x00, 0x6e, 0x0c, 0x74, 0x10, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x54, 0x00, 0x54, 0x40, 0x09, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x06, 0x40,
- 0x3b, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x02, 0x55,
- 0x00, 0x37, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x65,
- 0x00, 0x73, 0x04, 0x40, 0x95, 0x74, 0x00, 0x40, 0x09, 0x69, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x1d, 0xe2, 0x67, 0x00, 0x70,
- 0x09, 0x40, 0x00, 0x61, 0x72, 0x64, 0x66, 0x75, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x05, 0x40, 0x07, 0x69, 0x72, 0x00, 0x42, 0x56, 0x74, 0x65,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x01, 0xeb, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40,
- 0x3b, 0x65, 0x00, 0xf4, 0x65, 0x00, 0x00, 0x69, 0x61, 0x00, 0x6f, 0xa7,
- 0x00, 0x75, 0xff, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x04, 0x6d, 0x06, 0x6e,
- 0x37, 0x72, 0x4d, 0x40, 0x7a, 0x74, 0x00, 0x00, 0x00, 0xe2, 0x62, 0x00,
- 0x69, 0x17, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x07,
- 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00,
- 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x73,
- 0x00, 0x74, 0x06, 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x74, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe4, 0x64, 0x00, 0x6d, 0x11, 0x6e, 0x27,
- 0x70, 0x2b, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x00, 0x72, 0x00, 0x40, 0x08,
- 0x74, 0x75, 0x64, 0x65, 0x00, 0x40, 0x00, 0x67, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x15, 0x6e, 0x40, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x75, 0x00, 0x76, 0x1a,
- 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x54, 0x6c, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x48, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x4b,
- 0x00, 0x37, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x64,
- 0x00, 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x00, 0x69, 0x76, 0x65,
- 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x21, 0x00, 0x69,
- 0x33, 0x00, 0x6f, 0xa9, 0x00, 0x72, 0xbb, 0x00, 0x75, 0x5b, 0x01, 0x00,
- 0x00, 0xe4, 0x66, 0x00, 0x6c, 0x04, 0x6e, 0x06, 0x73, 0x11, 0x40, 0x06,
- 0x66, 0x00, 0x00, 0x3b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x5e, 0x65,
- 0x00, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x6e,
- 0x06, 0x40, 0x07, 0x70, 0x65, 0x72, 0x00, 0x40, 0x06, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x1c, 0xe1, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0xcc, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe2,
- 0x63, 0x00, 0x67, 0x31, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x6e, 0x1f, 0x02, 0x57, 0x40, 0x00, 0x72, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x53, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08,
- 0x00, 0x87, 0x40, 0x54, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x37, 0x64, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02,
- 0x58, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x26, 0x69,
- 0x3f, 0xe3, 0x63, 0x00, 0x69, 0x15, 0x75, 0x19, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x20, 0x40, 0x3b, 0x64, 0x00,
- 0x40, 0x08, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00, 0x67,
- 0x68, 0x74, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x00, 0x00,
- 0x66, 0x02, 0x69, 0x07, 0x01, 0x20, 0x40, 0x00, 0x75, 0x6c, 0x00, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x62, 0x00, 0x63, 0x47, 0xe1, 0x75, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x24, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x02, 0x36, 0x00, 0x37, 0xe2, 0x6f, 0x00, 0x76, 0x12,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x75,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x73, 0x06, 0x00, 0x76, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x08, 0x68, 0x69, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x27, 0x02, 0x00, 0x76, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x62, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69,
- 0x11, 0x00, 0x48, 0x40, 0x06, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40,
- 0x07, 0x6e, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x61, 0x62,
- 0x69, 0x63, 0x00, 0xe6, 0x63, 0x00, 0x68, 0x04, 0x72, 0x15, 0x73, 0x20,
- 0x74, 0x24, 0x7a, 0x2d, 0x40, 0x47, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x00, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x02, 0x00, 0x2c, 0x00,
- 0x06, 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x06, 0x40,
- 0x09, 0x74, 0x69, 0x63, 0x00, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0xf7, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x13, 0x00, 0x69, 0xa2, 0x00, 0x6f,
- 0x1d, 0x01, 0x75, 0x3b, 0x01, 0x76, 0x41, 0x01, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x6e, 0x08, 0x00, 0x09, 0x40, 0x00, 0x65, 0x6e, 0x74,
- 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x6f, 0x02, 0x59,
- 0xe4, 0x00, 0x00, 0x67, 0x02, 0x73, 0x17, 0x74, 0x53, 0x00, 0x07, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3a, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x5a, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe3, 0x66, 0x00, 0x6f, 0x10, 0x74, 0x1f, 0xe2, 0x69, 0x00,
- 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x42, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x7a, 0x40, 0x07, 0x63, 0x75, 0x6c, 0x69, 0x74, 0x69, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x09, 0x01,
- 0xe1, 0x40, 0x09, 0x74, 0x75, 0x72, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0xe3, 0x64, 0x00, 0x6e, 0x16, 0x73, 0x36, 0xe1, 0x65, 0x00,
- 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x04, 0x72, 0x08, 0x02, 0x55, 0x00,
- 0x37, 0x40, 0x09, 0x64, 0x00, 0x00, 0x07, 0xe4, 0x61, 0x00, 0x65, 0x07,
- 0x67, 0x10, 0x69, 0x12, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x02, 0x5b, 0x00, 0x07, 0x00, 0x07, 0x40, 0x06,
- 0x74, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x35, 0xe3, 0x62, 0x00, 0x6f,
- 0x10, 0x76, 0x1e, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0x40, 0x54, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x17, 0xe1, 0x63,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x04, 0x02,
- 0x5c, 0x00, 0x09, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x06, 0x40,
- 0x0b, 0x6c, 0x67, 0x65, 0x00, 0x40, 0x5e, 0x79, 0x00, 0x40, 0x07, 0x69,
- 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x02, 0x5d, 0x40, 0x09, 0x65, 0x6c, 0x6c,
- 0x61, 0x62, 0x61, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x41,
- 0x00, 0x6c, 0x00, 0x20, 0x01, 0x52, 0x01, 0x70, 0x01, 0x74, 0x01, 0x00,
- 0x00, 0x7f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x02, 0x1c, 0x03, 0xd3,
- 0x03, 0x3a, 0x04, 0x2e, 0x05, 0x00, 0x00, 0x78, 0x05, 0xc5, 0x05, 0xfa,
- 0x05, 0x3b, 0x06, 0xd9, 0x06, 0x01, 0x07, 0xae, 0x08, 0xb6, 0x08, 0xc7,
- 0x08, 0x02, 0x5e, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe4, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x17, 0x72, 0x1e, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x67,
- 0x02, 0x00, 0x06, 0x00, 0x00, 0x40, 0x09, 0x72, 0x6d, 0x61, 0x6e, 0x00,
- 0x40, 0x00, 0x6f, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x6b,
- 0x16, 0x74, 0x43, 0x75, 0x76, 0x00, 0x06, 0x40, 0x06, 0x6e, 0x74, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x73, 0x0c,
- 0x77, 0x12, 0x79, 0x1a, 0x00, 0xfe, 0x40, 0x2c, 0x74, 0x00, 0x40, 0x08,
- 0x61, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x69, 0x64, 0x65, 0x00, 0x40, 0x09,
- 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00,
- 0xe2, 0x6f, 0x00, 0x72, 0x15, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x2c, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x0c, 0xe2, 0x69, 0x00, 0x6c, 0x05, 0x40, 0x09, 0x72, 0x65, 0x00, 0x00,
- 0x00, 0x00, 0x09, 0xe2, 0x64, 0x00, 0x6d, 0x07, 0x40, 0x06, 0x72, 0x61,
- 0x6d, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11, 0x00, 0x59, 0xe2, 0x72, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x37, 0x64, 0x00, 0xe3, 0x64, 0x00, 0x67, 0x15, 0x6f, 0x29, 0xe2,
- 0x65, 0x00, 0x6c, 0x0c, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x2c, 0x00, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x0d, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x04, 0x00, 0x7e, 0x00, 0x08,
- 0x00, 0x07, 0x00, 0xf3, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73,
- 0x04, 0x00, 0x06, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6b, 0x02, 0x6e, 0x07,
- 0x01, 0xca, 0x40, 0x09, 0x69, 0x6e, 0x00, 0x40, 0x00, 0x27, 0x74, 0x00,
- 0x40, 0x72, 0x66, 0x00, 0xed, 0x00, 0x00, 0x63, 0x02, 0x65, 0x15, 0x66,
- 0x22, 0x67, 0x33, 0x68, 0x5f, 0x69, 0x66, 0x6c, 0x6a, 0x6d, 0x8c, 0x6e,
- 0xb4, 0x73, 0xbc, 0x74, 0xcc, 0x77, 0xea, 0x00, 0x06, 0xe1, 0x61, 0x00,
- 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x06, 0x63,
- 0x68, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x72, 0x65, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x67, 0x00, 0x73,
- 0x05, 0x40, 0x06, 0x68, 0x74, 0x00, 0x40, 0x09, 0x68, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x17, 0x6f, 0x1c, 0x79, 0x21, 0xe2, 0x64, 0x00, 0x72, 0x0d,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x42,
- 0x5f, 0x6e, 0x65, 0x00, 0x01, 0x64, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x18, 0xe1, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x6b, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x00, 0x61, 0x70, 0x70,
- 0x65, 0x72, 0x00, 0xe2, 0x62, 0x00, 0x6c, 0x06, 0x40, 0x08, 0x6f, 0x64,
- 0x79, 0x00, 0x40, 0x08, 0x65, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x06, 0x79, 0x00, 0x41, 0x99, 0x67, 0x00, 0xe7, 0x64, 0x00, 0x65,
- 0x07, 0x6c, 0x27, 0x6d, 0x45, 0x6f, 0x4a, 0x70, 0x61, 0x74, 0x67, 0x40,
- 0x07, 0x72, 0x75, 0x6d, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x66,
- 0x06, 0x02, 0x45, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x68, 0x06, 0x6f, 0x0d, 0x79,
- 0x11, 0x00, 0x55, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73,
- 0x65, 0x00, 0x40, 0x93, 0x70, 0x00, 0x00, 0x06, 0x40, 0x06, 0x65, 0x6e,
- 0x00, 0xe2, 0x6d, 0x00, 0x72, 0x06, 0x40, 0x07, 0x69, 0x74, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x3b, 0x75, 0x73, 0x00,
- 0x40, 0x09, 0x68, 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x40, 0x40, 0x06, 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x82, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x1f, 0x00, 0x06, 0xe2, 0x6c, 0x00,
- 0x74, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x57, 0x00, 0x37, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x13,
- 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x5e, 0x40, 0x00, 0x61, 0x72, 0x79, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x2d,
- 0x69, 0x3f, 0x6f, 0x44, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x56, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x72, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x63, 0x00, 0x78, 0x05, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x5b, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe9,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x19, 0x67, 0x1b, 0x6b, 0x26,
- 0x6e, 0x2b, 0x6f, 0x4b, 0x75, 0x4f, 0x00, 0x06, 0x40, 0x00, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x02, 0x60, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x55, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x65, 0x79,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x11, 0x40, 0x00, 0x64, 0x00,
- 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x00, 0x67, 0x00, 0x40, 0x00, 0x68,
- 0x00, 0x40, 0x09, 0x62, 0x72, 0x6f, 0x6f, 0x6b, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x00, 0x74, 0x73, 0x00, 0xe5, 0x64, 0x00, 0x68, 0x28, 0x6c,
- 0x30, 0x6d, 0x37, 0x72, 0x55, 0xe2, 0x61, 0x00, 0x6c, 0x10, 0xe2, 0x64,
- 0x00, 0x68, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x72, 0x07,
- 0x00, 0x7e, 0x40, 0x06, 0x75, 0x67, 0x00, 0x00, 0x07, 0x40, 0x06, 0x69,
- 0x63, 0x6b, 0x65, 0x79, 0x00, 0x40, 0x00, 0x61, 0x6c, 0x6c, 0x79, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x55, 0xe3, 0x61, 0x00, 0x64, 0x06,
- 0x74, 0x0b, 0x40, 0x09, 0x79, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x79,
- 0x00, 0x40, 0x08, 0x65, 0x72, 0x00, 0xea, 0x00, 0x00, 0x27, 0x02, 0x62,
- 0x06, 0x6a, 0x0c, 0x6b, 0x12, 0x6d, 0x2e, 0x70, 0x40, 0x73, 0x50, 0x77,
- 0x74, 0x79, 0x79, 0x02, 0x61, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x65,
- 0x6c, 0x6c, 0x00, 0x40, 0x08, 0x61, 0x6d, 0x62, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x07, 0x40, 0x09, 0x65, 0x70, 0x65, 0x72, 0x00, 0xe1, 0x6f, 0x00,
- 0xe2, 0x62, 0x00, 0x63, 0x02, 0x00, 0x09, 0x40, 0x08, 0x6b, 0x65, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x09, 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x06,
- 0x40, 0x06, 0x61, 0x74, 0x65, 0x00, 0x40, 0x08, 0x73, 0x74, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x18, 0xe1, 0x70, 0x00, 0xe2, 0x00,
- 0x00, 0x70, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x70, 0x00, 0x40,
- 0x06, 0x61, 0x79, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x0d, 0x69, 0x1a, 0x70, 0x36, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72,
- 0x02, 0x79, 0x04, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x0b, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x08, 0x65, 0x6c, 0x67, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x00,
- 0xe4, 0x6b, 0x00, 0x6d, 0x09, 0x73, 0x3d, 0x79, 0x42, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x09, 0x00, 0xf3, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x10, 0x69, 0x14, 0x6f, 0x23, 0x00, 0xe6, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x06,
- 0x6f, 0x72, 0x79, 0x00, 0x40, 0x07, 0x75, 0x73, 0x65, 0x00, 0x40, 0x3b,
- 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe6, 0x61, 0x00, 0x65, 0x05, 0x68, 0x07,
- 0x69, 0x09, 0x73, 0x11, 0x74, 0x26, 0x40, 0x06, 0x67, 0x65, 0x00, 0x00,
- 0x82, 0x00, 0x00, 0x40, 0x06, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x68, 0x02, 0x69, 0x09, 0x01, 0x4b, 0x40, 0x08, 0x6f, 0x75,
- 0x73, 0x65, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x00, 0x00, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x63, 0x0f, 0x65, 0x14, 0x69, 0x1d, 0x74, 0x22, 0x01,
- 0x05, 0xe2, 0x67, 0x00, 0x72, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x06,
- 0x64, 0x00, 0x40, 0x06, 0x6f, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x08, 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x00, 0xf3, 0xe5, 0x62, 0x00, 0x63, 0x64, 0x67, 0x69, 0x72, 0x82,
- 0x73, 0x8f, 0xe2, 0x6c, 0x00, 0x74, 0x30, 0xe3, 0x65, 0x00, 0x6f, 0x22,
- 0x79, 0x27, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x68, 0x06, 0x73, 0x0e, 0x74,
- 0x15, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x65, 0x61, 0x64,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x70, 0x65, 0x61, 0x6b, 0x00, 0x00, 0x09,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02,
- 0x66, 0x06, 0x69, 0x19, 0x6c, 0x1e, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0x40, 0x3b, 0x65, 0x73, 0x73, 0x00, 0x40, 0x5e, 0x68, 0x65, 0x00, 0xe1,
- 0x68, 0x00, 0xe4, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x07, 0x79, 0x0b, 0x00,
- 0x07, 0x40, 0x06, 0x75, 0x74, 0x00, 0x40, 0xf3, 0x79, 0x00, 0x00, 0x60,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x1e, 0xe3, 0x00,
- 0x00, 0x63, 0x02, 0x74, 0x11, 0x00, 0x09, 0xe1, 0x6f, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x08, 0x00, 0x06, 0x40, 0x47,
- 0x61, 0x69, 0x6c, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0xf6, 0x61, 0x00,
- 0x00, 0x64, 0x06, 0x00, 0x65, 0x1c, 0x00, 0x6e, 0x25, 0x00, 0x72, 0x8a,
- 0x01, 0x73, 0x8e, 0x01, 0x40, 0x09, 0x67, 0x65, 0x72, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x02, 0x62, 0xe2, 0x6c, 0x00, 0x72,
- 0x02, 0x00, 0x2c, 0x00, 0x2c, 0xc1, 0x62, 0x18, 0x35, 0x00, 0x37, 0x00,
- 0x3d, 0x00, 0x43, 0x00, 0x4a, 0x00, 0x4e, 0x00, 0x5e, 0x00, 0x65, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0xa1, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xb8, 0x00, 0xd2, 0x00, 0x2b, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x63, 0x01, 0x00, 0xfe,
- 0x40, 0x06, 0x65, 0x61, 0x74, 0x00, 0x40, 0x00, 0x61, 0x73, 0x74, 0x00,
- 0x40, 0x09, 0x72, 0x61, 0x66, 0x74, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x05, 0x40, 0x26, 0x6c, 0x6c, 0x00, 0x40, 0x00, 0x65,
- 0x6c, 0x64, 0x00, 0x40, 0x5e, 0x72, 0x61, 0x64, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x1c, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x6c, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x02, 0x63, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00,
- 0x61, 0x72, 0x6b, 0x65, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x05, 0x40,
- 0x3a, 0x61, 0x79, 0x00, 0x40, 0x09, 0x75, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x65, 0x00, 0xe2, 0x67, 0x00, 0x76,
- 0x05, 0x40, 0x00, 0x68, 0x74, 0x00, 0x40, 0x00, 0x65, 0x72, 0x00, 0xe6,
- 0x63, 0x00, 0x68, 0x06, 0x69, 0x0c, 0x70, 0x21, 0x74, 0x27, 0x77, 0x46,
- 0x40, 0x00, 0x61, 0x6c, 0x65, 0x00, 0x40, 0x5b, 0x69, 0x66, 0x74, 0x00,
- 0xe2, 0x64, 0x00, 0x7a, 0x04, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x0b, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f,
- 0x75, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x14, 0xe3, 0x67, 0x00, 0x69,
- 0x04, 0x74, 0x09, 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x72, 0x73, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x65, 0x61, 0x6d, 0x00, 0x40, 0x09,
- 0x69, 0x6e, 0x67, 0x00, 0xe4, 0x69, 0x00, 0x6f, 0x05, 0x72, 0x0a, 0x75,
- 0x1b, 0x40, 0x07, 0x6d, 0x65, 0x00, 0x40, 0x07, 0x77, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x64,
- 0x64, 0x65, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x05, 0x40, 0x08, 0x72, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x64, 0x00,
- 0x00, 0xf3, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x40, 0x06, 0x6f, 0x6c, 0x6f, 0x67,
- 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x0b, 0x79, 0x10, 0x02, 0x64, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x00, 0x0d, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0xf4, 0xe2, 0x69,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x65,
- 0xe1, 0x01, 0x69, 0xe4, 0x02, 0x6f, 0xb2, 0x03, 0x75, 0x9c, 0x04, 0x79,
- 0x73, 0x05, 0xfe, 0x62, 0x00, 0x00, 0x63, 0x1d, 0x00, 0x66, 0x2e, 0x00,
- 0x67, 0x95, 0x00, 0x69, 0xd4, 0x00, 0x6b, 0xfa, 0x00, 0x6d, 0xfe, 0x00,
- 0x6e, 0x39, 0x01, 0x70, 0x3d, 0x01, 0x73, 0x50, 0x01, 0x74, 0x66, 0x01,
- 0x75, 0x72, 0x01, 0x77, 0x7d, 0x01, 0x79, 0xb4, 0x01, 0xe3, 0x00, 0x00,
- 0x62, 0x02, 0x6e, 0x10, 0x02, 0x41, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00,
- 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6d, 0x61, 0x00,
- 0x40, 0x00, 0x6e, 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe6, 0x00,
- 0x00, 0x27, 0x02, 0x65, 0x06, 0x69, 0x0f, 0x73, 0x24, 0x79, 0x55, 0x00,
- 0xd5, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00, 0x06,
- 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe2,
- 0x6d, 0x00, 0x77, 0x19, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x69, 0x70,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x00, 0xf4, 0xe5, 0x00, 0x00, 0x67, 0x02, 0x6e, 0x14, 0x6f, 0x19, 0x73,
- 0x2e, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x60, 0x40, 0x06, 0x65,
- 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x0c, 0xe2, 0x00, 0x00, 0x66, 0x02,
- 0x00, 0x06, 0x40, 0x06, 0x6c, 0x79, 0x00, 0x40, 0x2c, 0x6e, 0x00, 0x40,
- 0x08, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x62, 0x07, 0x65, 0x0e, 0x70, 0x12, 0x01, 0x5b, 0x40, 0x07, 0x67,
- 0x65, 0x00, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x09, 0x69, 0x70, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0xe1, 0x69, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x11, 0x7a, 0x15, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x00, 0x07, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x00,
- 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00, 0x40, 0x08, 0x67, 0x68, 0x74,
- 0x62, 0x6f, 0x61, 0x72, 0x64, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x65,
- 0x13, 0x69, 0x17, 0x6c, 0x1c, 0x6e, 0x1e, 0x73, 0x20, 0x02, 0x65, 0xe2,
- 0x61, 0x00, 0x72, 0x05, 0x40, 0x09, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x69,
- 0x64, 0x67, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x00, 0x2c, 0x00, 0x77, 0x40, 0x09, 0x74, 0x72, 0x69, 0x6e, 0x67,
- 0x00, 0x00, 0x09, 0xe6, 0x61, 0x00, 0x64, 0x9c, 0x67, 0xab, 0x6e, 0xaf,
- 0x73, 0xb4, 0x77, 0xf4, 0xe3, 0x64, 0x00, 0x6d, 0x2d, 0x72, 0x7b, 0xe4,
- 0x00, 0x00, 0x66, 0x02, 0x6c, 0x15, 0x6e, 0x1c, 0x00, 0x2c, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x63, 0x6b, 0x73, 0x00,
- 0x40, 0x09, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x00, 0xe7, 0x00, 0x00, 0x62,
- 0x02, 0x65, 0x08, 0x69, 0x11, 0x6c, 0x20, 0x77, 0x36, 0x79, 0x3d, 0x01,
- 0x5b, 0x40, 0x09, 0x6f, 0x61, 0x74, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x37, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05,
- 0x69, 0x0a, 0x40, 0x07, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x6b, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x6c, 0x64, 0x00,
- 0x01, 0x15, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x15, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x0b, 0x63, 0x68, 0x00, 0xe1, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x07, 0x69, 0x0b, 0x6d, 0x1a, 0x79, 0x2e, 0x02, 0x66, 0x40, 0x07,
- 0x67, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe1, 0x61,
- 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x01, 0x92, 0x00, 0x77, 0xe8, 0x62,
- 0x00, 0x65, 0x19, 0x66, 0x1d, 0x6c, 0x3a, 0x6e, 0x52, 0x70, 0x68, 0x76,
- 0x81, 0x7a, 0xae, 0xe2, 0x62, 0x00, 0x6c, 0x0f, 0xe1, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40,
- 0x09, 0x65, 0x74, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x77, 0x0b, 0x01, 0x5b, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x08, 0x65, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64,
- 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x01,
- 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x61, 0x73, 0x74, 0x65, 0x72,
- 0x00, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x02,
- 0x67, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79,
- 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0x00, 0x60,
- 0xe1, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x0d, 0x72, 0x0f,
- 0x73, 0x11, 0x77, 0x18, 0x01, 0x14, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xfa, 0x40, 0x07, 0x72, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x06, 0x68,
- 0x61, 0x66, 0x74, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0xe1, 0x7a, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x82, 0x00, 0x00,
- 0xeb, 0x67, 0x00, 0x69, 0x05, 0x6c, 0x09, 0x6d, 0x24, 0x6e, 0x2c, 0x6f,
- 0x30, 0x70, 0x49, 0x73, 0x92, 0x75, 0x96, 0x76, 0x9c, 0x77, 0xa8, 0x40,
- 0x06, 0x75, 0x65, 0x00, 0x40, 0x08, 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x6e, 0x07, 0x79, 0x0d, 0x01, 0x15, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40,
- 0x06, 0x65, 0x64, 0x61, 0x72, 0x79, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe2,
- 0x6c, 0x00, 0x70, 0x02, 0x00, 0x2c, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79,
- 0x09, 0x00, 0x95, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92,
- 0xe6, 0x00, 0x00, 0x6b, 0x02, 0x6c, 0x08, 0x6f, 0x0d, 0x70, 0x12, 0x73,
- 0x2f, 0x00, 0x09, 0x40, 0x09, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x06, 0x65,
- 0x74, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0xe1, 0x6e, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07,
- 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x73, 0x00, 0x40, 0x06, 0x67, 0x68, 0x74, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x94, 0x00, 0x07, 0xe2,
- 0x6e, 0x00, 0x73, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x68, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00,
- 0x82, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe8, 0x62, 0x00, 0x64, 0x1a, 0x67,
- 0x2b, 0x69, 0x59, 0x6d, 0x68, 0x6e, 0x9a, 0x70, 0xbb, 0x74, 0xbf, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x09, 0x6e, 0x67,
- 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x82, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x73,
- 0x20, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x15, 0x40, 0x00,
- 0x64, 0x00, 0xe3, 0x65, 0x00, 0x6e, 0x02, 0x73, 0x06, 0x00, 0x06, 0x40,
- 0x00, 0x67, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x00, 0x40, 0x09, 0x74,
- 0x6f, 0x72, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02,
- 0x6c, 0x08, 0x6d, 0x0d, 0x73, 0x20, 0x00, 0x09, 0x40, 0x06, 0x65, 0x61,
- 0x74, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x00, 0xe1, 0x6b, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x02, 0x69, 0x40, 0x09, 0x72,
- 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x07,
- 0x68, 0x65, 0x72, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06,
- 0x6e, 0x0a, 0x73, 0x10, 0x77, 0x12, 0x02, 0x6a, 0x40, 0x06, 0x64, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00,
- 0x40, 0x07, 0x61, 0x6c, 0x6c, 0x00, 0xc0, 0x61, 0x16, 0x2f, 0x00, 0x46,
- 0x00, 0x86, 0x00, 0x02, 0x01, 0x13, 0x01, 0x37, 0x01, 0x4a, 0x01, 0x56,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x58, 0x01, 0x67, 0x01, 0x97, 0x01, 0x0a,
- 0x02, 0x65, 0x02, 0x95, 0x02, 0x00, 0x00, 0xe6, 0x02, 0x2a, 0x03, 0x8f,
- 0x03, 0x00, 0x00, 0xc2, 0x03, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x07, 0x6d, 0x00,
- 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x69, 0x1c, 0x00,
- 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x68,
- 0x09, 0x6b, 0x15, 0x74, 0x49, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x73, 0x00,
- 0x00, 0x06, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x13, 0x70, 0x19, 0x77,
- 0x1f, 0x79, 0x25, 0x00, 0x55, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06,
- 0x6c, 0x6c, 0x00, 0x40, 0x00, 0x61, 0x72, 0x64, 0x73, 0x00, 0x40, 0x06,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x73, 0x00, 0x40, 0x07,
- 0x65, 0x65, 0x64, 0x00, 0x01, 0x72, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x69,
- 0x06, 0x6c, 0x1b, 0x02, 0x6b, 0x41, 0xef, 0x73, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0x40, 0x00, 0x67, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x67, 0x04, 0x00, 0x95, 0x00, 0x09, 0x40,
- 0x07, 0x65, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x14,
- 0x74, 0x19, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x02,
- 0x6c, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x09,
- 0x6e, 0x61, 0x00, 0x00, 0x09, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xfe, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x40, 0x09, 0x75, 0x74, 0x00,
- 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x09,
- 0x40, 0x06, 0x6f, 0x6d, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x0f, 0x79, 0x27,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x74, 0x00, 0x40, 0x09, 0x6d,
- 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6e, 0x07, 0x79, 0x0d,
- 0x02, 0x6d, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x00, 0x00, 0x37, 0xe4, 0x62, 0x00, 0x64, 0x36, 0x6d, 0x3b,
- 0x70, 0x3f, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x66, 0x08, 0x6e, 0x0f, 0x6f,
- 0x15, 0x73, 0x17, 0x77, 0x1f, 0x00, 0xe0, 0x40, 0x06, 0x65, 0x6c, 0x6c,
- 0x00, 0x40, 0x7a, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x08, 0x40, 0x00, 0x74, 0x72, 0x75, 0x63, 0x6b, 0x00,
- 0x40, 0x06, 0x61, 0x69, 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x75, 0x6d,
- 0x00, 0x40, 0x06, 0x79, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x09,
- 0x73, 0x0f, 0x79, 0x1e, 0x00, 0xfe, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x05,
- 0x40, 0x08, 0x74, 0x65, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0x00, 0x96,
- 0xe7, 0x00, 0x00, 0x63, 0x02, 0x64, 0x06, 0x65, 0x0f, 0x67, 0x11, 0x6b,
- 0x2d, 0x6e, 0x2f, 0x00, 0x06, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x65,
- 0x72, 0x68, 0x65, 0x61, 0x64, 0x00, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x08, 0x68, 0x0d, 0x00, 0x55, 0x40, 0x09, 0x72, 0x65, 0x65,
- 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x69, 0x6c, 0x6c, 0x00,
- 0x00, 0x55, 0xe3, 0x65, 0x00, 0x69, 0x0f, 0x6f, 0x14, 0xe3, 0x64, 0x00,
- 0x72, 0x02, 0x73, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02,
- 0x70, 0x23, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x07,
- 0x40, 0x00, 0x69, 0x6d, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x09,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x6d,
- 0x00, 0x40, 0x08, 0x6f, 0x6c, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x09,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0x00, 0x09, 0xe1,
- 0x63, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x1e, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x0b, 0x6f, 0x10, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x02, 0x6e,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x75, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x05, 0x40, 0x00, 0x75,
- 0x73, 0x00, 0x00, 0x07, 0xe5, 0x61, 0x00, 0x65, 0x27, 0x69, 0x2c, 0x73,
- 0x31, 0x75, 0x35, 0xe3, 0x62, 0x00, 0x6e, 0x15, 0x74, 0x1a, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x63, 0x65, 0x00,
- 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x6d, 0x00,
- 0xe2, 0x6b, 0x00, 0x74, 0x12, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xea,
- 0x00, 0x00, 0x62, 0x02, 0x63, 0x07, 0x65, 0x0d, 0x69, 0x11, 0x6c, 0x18,
- 0x6d, 0x1e, 0x70, 0x2b, 0x73, 0x30, 0x79, 0x37, 0x00, 0xfe, 0x40, 0x06,
- 0x69, 0x6e, 0x00, 0x40, 0x08, 0x61, 0x72, 0x74, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40, 0x08, 0x68, 0x65,
- 0x65, 0x74, 0x00, 0x00, 0xf4, 0xe4, 0x63, 0x00, 0x65, 0x04, 0x69, 0x0a,
- 0x79, 0x28, 0x40, 0x00, 0x68, 0x00, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x66, 0x06, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0x40, 0x06, 0x65, 0x74,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x19, 0x69, 0x3b, 0xe1, 0x72, 0x00, 0xe1,
- 0x66, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x93, 0xe1, 0x73, 0x00,
- 0xe2, 0x68, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00,
- 0x6c, 0x04, 0x40, 0x06, 0x62, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x12, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x02, 0x6f, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x54, 0x40, 0x3a, 0x6e, 0x64, 0x6c,
- 0x65, 0x00, 0xe7, 0x61, 0x00, 0x62, 0x06, 0x65, 0x1a, 0x69, 0x33, 0x6b,
- 0x38, 0x6e, 0x3c, 0x73, 0x7f, 0x40, 0x00, 0x64, 0x69, 0x63, 0x00, 0xe1,
- 0x62, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02,
- 0x72, 0x07, 0x73, 0x09, 0x00, 0x7e, 0x40, 0x77, 0x6e, 0x67, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x74, 0x75, 0x66, 0x66, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x73,
- 0x2d, 0xe2, 0x69, 0x00, 0x6f, 0x26, 0xe3, 0x63, 0x00, 0x73, 0x0f, 0x74,
- 0x13, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x09, 0x40, 0x3b,
- 0x6c, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x74,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00, 0x63, 0x00, 0x00, 0x06,
- 0xe5, 0x65, 0x00, 0x66, 0x08, 0x6c, 0x28, 0x70, 0x42, 0x74, 0x6a, 0x40,
- 0x07, 0x6e, 0x74, 0x65, 0x72, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x06, 0x40,
- 0x06, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x68, 0x12, 0x72, 0x19,
- 0xe1, 0x70, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x07, 0x69, 0x61,
- 0x00, 0x40, 0x09, 0x69, 0x63, 0x00, 0x40, 0x00, 0x61, 0x67, 0x69, 0x61,
- 0x00, 0x40, 0x07, 0x6f, 0x73, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x00, 0x6f,
- 0x6e, 0x69, 0x61, 0x00, 0x00, 0x00, 0xc1, 0x27, 0x53, 0xab, 0x00, 0xad,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x26, 0x03, 0x56,
- 0x03, 0x33, 0x05, 0x97, 0x06, 0xb8, 0x06, 0x4c, 0x08, 0x76, 0x09, 0x78,
- 0x09, 0x05, 0x0a, 0x44, 0x0a, 0x48, 0x0a, 0x6e, 0x0f, 0xba, 0x14, 0xd4,
- 0x1f, 0x03, 0x20, 0x0e, 0x22, 0x87, 0x23, 0x77, 0x25, 0xed, 0x27, 0x88,
- 0x29, 0xc1, 0x2a, 0x40, 0x2d, 0x4c, 0x2d, 0xf3, 0x3b, 0x02, 0x70, 0xe1,
- 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x6f, 0x6b,
- 0x00, 0x40, 0x07, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x00, 0x40,
- 0x07, 0x75, 0x73, 0x69, 0x63, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x63, 0x02,
- 0x00, 0x67, 0x06, 0x00, 0x72, 0x27, 0x00, 0x73, 0x75, 0x01, 0x74, 0xe9,
- 0x01, 0x76, 0x08, 0x02, 0x00, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe2, 0x65,
- 0x00, 0x6c, 0x10, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x63, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x09, 0x00, 0x09, 0xfd, 0x00, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x62, 0x08, 0x00, 0x64, 0x0d, 0x00, 0x66, 0x13, 0x00, 0x6c,
- 0x18, 0x00, 0x6d, 0x38, 0x00, 0x6e, 0x47, 0x00, 0x70, 0x71, 0x00, 0x72,
- 0x89, 0x00, 0x73, 0x8f, 0x00, 0x74, 0xa3, 0x00, 0x77, 0x19, 0x01, 0x02,
- 0x71, 0x40, 0x06, 0x63, 0x68, 0x65, 0x00, 0x40, 0x06, 0x75, 0x64, 0x00,
- 0x40, 0x06, 0x72, 0x75, 0x6d, 0x00, 0x40, 0x06, 0x75, 0x6c, 0x00, 0xe5,
- 0x00, 0x00, 0x64, 0x02, 0x69, 0x07, 0x6f, 0x0e, 0x79, 0x13, 0x00, 0x09,
- 0x40, 0x06, 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x62, 0x65, 0x00, 0x00, 0xf4, 0xe2, 0x61, 0x00, 0x75, 0x05,
- 0x40, 0x2c, 0x72, 0x6b, 0x00, 0x40, 0x06, 0x66, 0x66, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x1d, 0x02, 0x72, 0xe3, 0x64, 0x00, 0x72, 0x02,
- 0x73, 0x04, 0x00, 0x37, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x02, 0x12, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x73, 0x00, 0xe3, 0x68, 0x00, 0x69, 0x06, 0x6c, 0x0c, 0x40,
- 0x09, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x08, 0x65, 0x63, 0x65, 0x00, 0x40,
- 0x06, 0x75, 0x67, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x68,
- 0x00, 0x70, 0x05, 0x40, 0x07, 0x6f, 0x74, 0x00, 0x40, 0x00, 0x6c, 0x69,
- 0x74, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xea, 0x00, 0x00,
- 0x27, 0x02, 0x62, 0x06, 0x65, 0x0d, 0x69, 0x1d, 0x6c, 0x24, 0x71, 0x30,
- 0x73, 0x37, 0x77, 0x46, 0x79, 0x5c, 0x02, 0x73, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x00, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x77, 0x02, 0x00, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x09, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0x40, 0x06, 0x75, 0x61, 0x6b, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x37, 0x40, 0x00, 0x61, 0x6b,
- 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x08, 0x72,
- 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x6b, 0x00, 0x6d, 0x02, 0x00, 0x09,
- 0x00, 0x09, 0x00, 0xf4, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x07, 0x78,
- 0x00, 0x40, 0x06, 0x67, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x11, 0x74, 0x26,
- 0x79, 0x5d, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x04, 0x02, 0x74, 0x00,
- 0x06, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x37, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0xdb, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x09, 0x77,
- 0x28, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x6d, 0x06, 0x02, 0x75, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x00, 0x6f, 0x73, 0x74, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x67, 0x02, 0x02, 0x76, 0x40, 0x00, 0x6f, 0x69, 0x6e, 0x67,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x02, 0x77, 0x40, 0x06,
- 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x37, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0xe1, 0x64, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00,
- 0x08, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x62, 0x00, 0x6f,
- 0x02, 0x75, 0x07, 0x00, 0x2c, 0x40, 0x06, 0x6e, 0x79, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x0e,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x3b, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xf8, 0x63, 0x00, 0x00,
- 0x68, 0x53, 0x00, 0x6c, 0x90, 0x00, 0x6f, 0xdb, 0x00, 0x72, 0x71, 0x01,
- 0x73, 0x75, 0x01, 0x75, 0x97, 0x01, 0x7a, 0xbe, 0x01, 0xe2, 0x65, 0x00,
- 0x6c, 0x23, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08,
- 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x74, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x06, 0x6f, 0x0f, 0x40, 0x06, 0x6c, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x6e,
- 0x6f, 0x64, 0x65, 0x72, 0x6d, 0x00, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x65,
- 0x06, 0x69, 0x0a, 0x6c, 0x0e, 0x73, 0x18, 0x02, 0x78, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x77, 0x73, 0x00, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07, 0x6f,
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0xe4, 0x61, 0x00,
- 0x65, 0x0b, 0x69, 0x2b, 0x6f, 0x3c, 0xe2, 0x69, 0x00, 0x74, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08,
- 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x73, 0x6d,
- 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x5e, 0x65,
- 0x00, 0x40, 0x07, 0x69, 0x63, 0x00, 0x40, 0x06, 0x67, 0x75, 0x65, 0x00,
- 0xe5, 0x63, 0x00, 0x6c, 0x06, 0x6e, 0x2b, 0x73, 0x6b, 0x74, 0x73, 0x40,
- 0x07, 0x69, 0x64, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73,
- 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x07, 0x79, 0x2d, 0x40,
- 0x00, 0x74, 0x72, 0x69, 0x63, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x0f, 0x7a,
- 0x13, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x08, 0x40, 0x36,
- 0x6c, 0x00, 0x00, 0x07, 0x40, 0x06, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x00, 0x06, 0x40, 0x09,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x75, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x08, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x63, 0x00, 0x73, 0x0e, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x3b,
- 0x6c, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x07, 0x65, 0x6d, 0x61, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x64, 0x09, 0x00, 0x65, 0x0d, 0x00, 0x67, 0x1e, 0x00, 0x69, 0x4d, 0x00,
- 0x75, 0xe4, 0x00, 0x02, 0x79, 0x40, 0x00, 0x6d, 0x61, 0x6d, 0x65, 0x00,
- 0x40, 0x5e, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x6d, 0x08, 0x40, 0x07, 0x77,
- 0x65, 0x69, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x11, 0x79, 0x26, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x77, 0x04, 0x02,
- 0x7a, 0x00, 0x07, 0x40, 0x00, 0x69, 0x73, 0x65, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40,
- 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0x00, 0xf4, 0xe4, 0x62, 0x00, 0x63,
- 0x1c, 0x66, 0x20, 0x74, 0x48, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x02, 0x7b, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x17, 0xe2, 0x63, 0x00, 0x65, 0x0e, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x06, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x7c,
- 0x40, 0x37, 0x6e, 0x67, 0x00, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06,
- 0x65, 0x0c, 0x69, 0x10, 0x6f, 0x15, 0x01, 0xf9, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x09,
- 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73,
- 0x14, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x56, 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x40, 0x07, 0x68,
- 0x69, 0x70, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x5b, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x52, 0x00, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x10, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x54,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x30, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x01, 0xea, 0x00, 0x37, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x11, 0x73, 0x16, 0x00, 0x75, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x08, 0x73,
- 0x74, 0x00, 0x40, 0x08, 0x73, 0x74, 0x00, 0x00, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0x00, 0xa8, 0x40, 0x07, 0x61, 0x69, 0x6e, 0x6d, 0x65, 0x6e, 0x74,
- 0x00, 0xe3, 0x6b, 0x00, 0x6c, 0x02, 0x72, 0x04, 0x00, 0x00, 0x00, 0x06,
- 0xe1, 0x69, 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x02, 0x6e, 0x06, 0x00, 0xf3,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xf1, 0x66,
- 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x15, 0x00,
- 0x69, 0xa0, 0x00, 0x6c, 0xcf, 0x00, 0x6f, 0x12, 0x01, 0x72, 0x35, 0x01,
- 0x75, 0x3e, 0x01, 0x00, 0xad, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x58, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00,
- 0xe5, 0x63, 0x00, 0x6d, 0x2d, 0x6e, 0x43, 0x72, 0x48, 0x74, 0x70, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75, 0x15, 0x01, 0xc1, 0xe1,
- 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xd7,
- 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00,
- 0x74, 0x02, 0x00, 0x5c, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40, 0x06, 0x64, 0x69, 0x00, 0xe2,
- 0x65, 0x00, 0x76, 0x05, 0x40, 0x00, 0x6e, 0x74, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x3b, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x67, 0x26,
- 0xe2, 0x61, 0x00, 0x69, 0x10, 0xe1, 0x63, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x06, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x53, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x53, 0x79, 0x00,
- 0x00, 0x5c, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x1d, 0xe1,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x09, 0xe1,
- 0x69, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6d,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x79, 0x00, 0xe2, 0x6c, 0x00,
- 0x73, 0x14, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x02, 0x7d, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x67, 0x28,
- 0x00, 0x6c, 0x5f, 0x00, 0x6f, 0x68, 0x00, 0x72, 0xf1, 0x00, 0xe2, 0x64,
- 0x00, 0x6c, 0x02, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73,
- 0x6d, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x63, 0x0a, 0x68, 0x0f, 0x6e,
- 0x15, 0x70, 0x1a, 0x73, 0x21, 0x00, 0x95, 0x40, 0x09, 0x65, 0x61, 0x74,
- 0x65, 0x72, 0x00, 0x40, 0x06, 0x75, 0x70, 0x00, 0x40, 0x06, 0x65, 0x61,
- 0x64, 0x00, 0x40, 0x07, 0x6f, 0x67, 0x00, 0x40, 0x09, 0x6c, 0x61, 0x6e,
- 0x74, 0x00, 0x40, 0x06, 0x68, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x06, 0x61,
- 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x69,
- 0x28, 0x6d, 0x47, 0x74, 0x5c, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x00, 0x09, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00,
- 0x09, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe3, 0x67, 0x00, 0x73, 0x19, 0x74, 0x1d, 0xe1, 0x69, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x73, 0x00, 0x00, 0x06, 0x00, 0x00, 0xe5, 0x64, 0x00, 0x67, 0x13, 0x6e,
- 0x67, 0x73, 0x72, 0x74, 0x7c, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x77, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x68, 0x09, 0x40, 0x08, 0x6e, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x68, 0x1b,
- 0x69, 0x24, 0x79, 0x36, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x01, 0x29, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x01, 0x58,
- 0x40, 0x07, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x69, 0x75, 0x6d, 0x00, 0x40,
- 0x08, 0x74, 0x65, 0x64, 0x64, 0x66, 0x6f, 0x64, 0x00, 0x40, 0x00, 0x68,
- 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x22, 0xe1, 0x63, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x7a, 0x40, 0x09, 0x6f,
- 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xfd, 0x61,
- 0x00, 0x00, 0x62, 0x7d, 0x00, 0x64, 0x90, 0x00, 0x65, 0xbb, 0x00, 0x66,
- 0x69, 0x03, 0x69, 0x7b, 0x03, 0x6b, 0xf4, 0x03, 0x6c, 0xf6, 0x03, 0x6d,
- 0x34, 0x04, 0x6f, 0x36, 0x04, 0x73, 0xa1, 0x04, 0x75, 0xb2, 0x04, 0x76,
- 0xeb, 0x04, 0xe5, 0x62, 0x00, 0x6e, 0x23, 0x70, 0x2c, 0x73, 0x31, 0x74,
- 0x5f, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02,
- 0x7e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x3a, 0x73,
- 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x11, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x74,
- 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00, 0xe2,
- 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x3a, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x57,
- 0x00, 0x3b, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x77,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x2c, 0x40, 0x07, 0x6f, 0x6f,
- 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x1f, 0xe2, 0x72, 0x00, 0x73, 0x16,
- 0xe3, 0x00, 0x00, 0x62, 0x02, 0x63, 0x09, 0x00, 0x56, 0x40, 0x06, 0x65,
- 0x72, 0x72, 0x79, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0x40, 0x00, 0x69, 0x74, 0x63, 0x68, 0x00, 0xf6, 0x63, 0x00,
- 0x00, 0x65, 0xef, 0x01, 0x67, 0xfa, 0x01, 0x6d, 0x22, 0x02, 0x70, 0x41,
- 0x02, 0x76, 0x63, 0x02, 0xf1, 0x74, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00,
- 0x27, 0x02, 0x00, 0x61, 0x06, 0x00, 0x69, 0x0c, 0x00, 0x6f, 0x24, 0x00,
- 0x72, 0x39, 0x00, 0x00, 0x64, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x62,
- 0x6c, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0f, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x69, 0x40, 0x72, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x09, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x3b, 0x40, 0x09, 0x65, 0x00,
- 0xf2, 0x69, 0x00, 0x00, 0x6f, 0x37, 0x00, 0xe2, 0x63, 0x00, 0x66, 0x1a,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x08, 0x40, 0x3b, 0x6c,
- 0x00, 0xe2, 0x61, 0x00, 0x74, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x11, 0xe2, 0x63, 0x00, 0x65, 0x08,
- 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x02, 0x7f, 0xf9, 0x63, 0x00, 0x00, 0x64, 0x40, 0x00, 0x65, 0x50, 0x00,
- 0x6c, 0x8e, 0x00, 0x6d, 0xaf, 0x00, 0x6e, 0xe4, 0x00, 0x70, 0x05, 0x01,
- 0x73, 0x0c, 0x01, 0x74, 0x3f, 0x01, 0xe2, 0x61, 0x00, 0x75, 0x2c, 0xe1,
- 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x70,
- 0x02, 0x00, 0x09, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x79,
- 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x61, 0x6d, 0x69, 0x63,
- 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x6d, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00,
- 0x69, 0x02, 0x73, 0x06, 0x79, 0x08, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00,
- 0x00, 0x00, 0x00, 0x07, 0xe2, 0x6f, 0x00, 0x79, 0x07, 0x40, 0x06, 0x67,
- 0x69, 0x73, 0x74, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x07, 0x69,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x29, 0xe1, 0x67, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe2, 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x00, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x0e, 0x00,
- 0x08, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x79,
- 0x00, 0x00, 0x07, 0x40, 0x3a, 0x6c, 0x61, 0x74, 0x65, 0x00, 0xe3, 0x63,
- 0x00, 0x68, 0x11, 0x74, 0x17, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07,
- 0x6f, 0x63, 0x6b, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00,
- 0x07, 0x40, 0x09, 0x79, 0x70, 0x65, 0x00, 0x40, 0x00, 0x6d, 0x6f, 0x73,
- 0x79, 0x6e, 0x61, 0x72, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x0e, 0x79,
- 0x1f, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x53, 0x65,
- 0x00, 0x00, 0x5c, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x06, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00,
- 0x3b, 0x40, 0x00, 0x79, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0xe2, 0x61, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x73, 0x69, 0x73, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x17, 0x00, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x01, 0x26,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x73, 0x02, 0x74, 0x04, 0x01, 0x58, 0x00, 0x08, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x68, 0x00, 0xe7, 0x63, 0x00, 0x64, 0x14, 0x67, 0x18,
- 0x6d, 0x2e, 0x73, 0x4c, 0x74, 0x52, 0x78, 0x65, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x7a, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74,
- 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x01, 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x08, 0x72, 0x00,
- 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x09, 0x40, 0x06, 0x69, 0x72, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe1, 0x70, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x1e, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x06, 0x00, 0x09, 0x40, 0x07, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x06,
- 0xe5, 0x63, 0x00, 0x64, 0x22, 0x6e, 0x27, 0x70, 0x3c, 0x71, 0x4c, 0xe1,
- 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x07, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x06, 0x65,
- 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x51, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x00, 0x40, 0x00, 0x68,
- 0x65, 0x72, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x18, 0x73, 0x1c, 0xe1,
- 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x00, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0xfb, 0x00, 0x00, 0x00,
- 0x27, 0x02, 0x00, 0x61, 0x06, 0x00, 0x62, 0x75, 0x00, 0x63, 0x89, 0x02,
- 0x65, 0x9b, 0x02, 0x66, 0xf0, 0x02, 0x69, 0xf2, 0x02, 0x6f, 0x65, 0x03,
- 0x70, 0xc7, 0x03, 0x75, 0xe5, 0x04, 0x00, 0x08, 0x40, 0x00, 0x73, 0x00,
- 0xe4, 0x63, 0x00, 0x69, 0x15, 0x6e, 0x19, 0x73, 0x4b, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x2c, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x63, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01,
- 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x65, 0x89, 0x00, 0x69, 0xdc,
- 0x00, 0x6c, 0xf5, 0x00, 0x6f, 0x30, 0x01, 0x72, 0x7f, 0x01, 0xe5, 0x6c,
- 0x00, 0x6e, 0x0e, 0x72, 0x1e, 0x73, 0x72, 0x74, 0x77, 0xe1, 0x6d, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x27, 0x40, 0x07, 0x72, 0x00, 0xe1,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x80, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0xe3, 0x67, 0x00, 0x6b, 0x0e, 0x72, 0x2a, 0xe1, 0x6f,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x2f, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x01, 0xbe, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x84, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6d, 0x0b, 0x00, 0x35,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x06, 0x73, 0x79, 0x00, 0x40, 0x00, 0x74, 0x6c,
- 0x65, 0x64, 0x00, 0xe4, 0x64, 0x00, 0x6c, 0x15, 0x72, 0x2e, 0x7a, 0x30,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x34, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x06,
- 0xe1, 0x7a, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x6d, 0x02, 0x72, 0x08, 0x01, 0x77, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00,
- 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x35, 0x40, 0x07, 0x65,
- 0x6e, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x16, 0xe1, 0x7a, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0xaf,
- 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0xe5, 0x64, 0x00, 0x6c, 0x0e, 0x73, 0x29, 0x75, 0x37, 0x77,
- 0x3f, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x84, 0x6d, 0x65, 0x6e, 0x74,
- 0x00, 0x00, 0xce, 0xe2, 0x64, 0x00, 0x69, 0x05, 0x40, 0x72, 0x65, 0x6e,
- 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x09, 0x6d, 0x00, 0x40, 0x00,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x63, 0x68,
- 0x75, 0x72, 0x65, 0x00, 0x40, 0x5b, 0x65, 0x72, 0x00, 0xe3, 0x61, 0x00,
- 0x6f, 0x1b, 0x79, 0x4f, 0xe2, 0x63, 0x00, 0x73, 0x10, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x5e, 0x40, 0x00, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x09, 0x75, 0x72, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x69, 0x08,
- 0x40, 0x09, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x6c,
- 0x15, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x79, 0x06, 0x00, 0xd6, 0x40, 0x07, 0x72, 0x00, 0x00, 0x06, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x6f, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1,
- 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x1d, 0x00, 0x06, 0xe1,
- 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63,
- 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00,
- 0x00, 0x07, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x1a, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x11, 0x74, 0x49, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x7a, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe4, 0x61, 0x00, 0x67, 0x05, 0x69, 0x1f, 0x79, 0x2d, 0x40, 0x09,
- 0x6c, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0xab, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x75, 0x00, 0x06, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x75,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x73, 0x00, 0x00, 0x07, 0x40, 0x06, 0x69,
- 0x63, 0x00, 0x00, 0x08, 0xe5, 0x67, 0x00, 0x6e, 0x1f, 0x72, 0x30, 0x73,
- 0x3c, 0x74, 0x4e, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x15, 0xe2,
- 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x06, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65,
- 0x00, 0x00, 0x3b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x09,
- 0x74, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4,
- 0x00, 0x00, 0x6a, 0x02, 0x6c, 0x06, 0x74, 0x19, 0x00, 0x06, 0x40, 0x00,
- 0x69, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x07, 0x40, 0x09, 0x69, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x09, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x73, 0xe3, 0x63, 0x00, 0x6f, 0x05, 0x76, 0x2e, 0x40,
- 0x06, 0x6f, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x6c, 0x19, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x36, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x0b, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x65,
- 0x00, 0xf9, 0x61, 0x00, 0x00, 0x65, 0x1a, 0x00, 0x68, 0x20, 0x00, 0x69,
- 0x58, 0x00, 0x6c, 0x7e, 0x00, 0x6f, 0xc1, 0x00, 0x72, 0xdf, 0x00, 0x74,
- 0xe5, 0x00, 0x79, 0xfb, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x06, 0x79, 0x0b, 0x40, 0x00, 0x74, 0x69, 0x63, 0x00,
- 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x00, 0x07, 0x40, 0x09, 0x72, 0x6f, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x79, 0x2c, 0xe2, 0x73, 0x00, 0x74, 0x14, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x73, 0x00, 0x7a,
- 0x02, 0x00, 0x07, 0x40, 0x4b, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x37, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x40, 0x07, 0x73, 0x65, 0x6d, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2,
- 0x61, 0x00, 0x6f, 0x09, 0x40, 0x06, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74,
- 0x00, 0xe1, 0x79, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65,
- 0x0c, 0x6d, 0x15, 0x02, 0x81, 0x40, 0x00, 0x73, 0x00, 0x40, 0x37, 0x62,
- 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x06,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x02, 0x82, 0x00, 0x00, 0xe2, 0x72, 0x00, 0x77, 0x06, 0x40,
- 0x06, 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x02, 0x83, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x02, 0x84, 0x40, 0x07, 0x72, 0x65, 0x61, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x73, 0x15, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x02, 0x7d, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x66, 0x00, 0x6f, 0x18, 0xe2, 0x69, 0x00, 0x79, 0x11, 0xe2, 0x63, 0x00,
- 0x65, 0x08, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x72, 0x00, 0x01, 0x12, 0x40, 0x09, 0x6e, 0x00, 0xc1, 0x61, 0x1a, 0x39,
- 0x00, 0x3b, 0x00, 0x00, 0x00, 0x80, 0x00, 0x7c, 0x02, 0x0b, 0x04, 0x5e,
- 0x04, 0xd5, 0x04, 0x7c, 0x05, 0x95, 0x05, 0xb8, 0x05, 0x00, 0x00, 0xe4,
- 0x05, 0x66, 0x06, 0x83, 0x06, 0xa2, 0x06, 0xcc, 0x06, 0xd3, 0x06, 0xec,
- 0x06, 0x29, 0x07, 0xb4, 0x07, 0x0e, 0x0a, 0x59, 0x0a, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x07, 0x0b, 0x00, 0x06, 0xe3, 0x62, 0x00, 0x63, 0x0f,
- 0x6d, 0x1f, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x02, 0x85, 0x40, 0x65, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x16, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x77, 0x06,
- 0x02, 0x86, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00,
- 0x40, 0x5b, 0x72, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65,
- 0x44, 0x00, 0x68, 0x62, 0x00, 0x69, 0xa8, 0x00, 0x6c, 0xc9, 0x00, 0x6f,
- 0xed, 0x00, 0x72, 0x3e, 0x01, 0x75, 0x81, 0x01, 0x79, 0xa1, 0x01, 0x00,
- 0x00, 0xe3, 0x6d, 0x00, 0x70, 0x10, 0x73, 0x2b, 0xe1, 0x70, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x01, 0x23, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x45, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0x78, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00,
- 0x07, 0xe2, 0x61, 0x00, 0x69, 0x3a, 0xe2, 0x69, 0x00, 0x6e, 0x04, 0x40,
- 0x72, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x6d, 0x0b, 0x72, 0x1d, 0x02, 0x87, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x84, 0x00, 0x00, 0x40, 0x09,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6c, 0x61, 0x64, 0x61, 0x00, 0xe2,
- 0x70, 0x00, 0x72, 0x06, 0x40, 0x5b, 0x68, 0x65, 0x72, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x02, 0x51, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x6f, 0x07, 0x00, 0x00, 0x40, 0x09, 0x76, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x75, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x0b, 0x00, 0x37, 0x40, 0x06, 0x72, 0x65, 0x00, 0xe4, 0x64, 0x00, 0x6d,
- 0x0c, 0x72, 0x1c, 0x75, 0x20, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x70, 0x05, 0x40, 0x09,
- 0x75, 0x6d, 0x00, 0x40, 0x0b, 0x61, 0x73, 0x73, 0x00, 0x40, 0x5e, 0x65,
- 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x06, 0x40, 0x95, 0x74, 0x65, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x58, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x6f, 0x00, 0x75, 0x16, 0x79, 0x2a,
- 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x35, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x72, 0x40,
- 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x72, 0x40, 0x00, 0x6f, 0x6e, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x0e, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x88, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x09, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x63,
- 0x02, 0x73, 0x25, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x06, 0x40, 0x06, 0x63, 0x61, 0x6c, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02,
- 0x00, 0x09, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x01, 0x23, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xfb, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x65, 0x1b, 0x00, 0x67, 0x51, 0x00, 0x69, 0x57, 0x00,
- 0x6c, 0x64, 0x00, 0x6d, 0x7a, 0x00, 0x6f, 0x80, 0x00, 0x70, 0x43, 0x01,
- 0x75, 0x4a, 0x01, 0x77, 0x67, 0x01, 0x02, 0x88, 0xe1, 0x6e, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x02, 0x89, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x61, 0x00,
- 0x6d, 0x1e, 0xe2, 0x72, 0x00, 0x76, 0x14, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6d, 0x07, 0x02, 0x8a, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x95, 0x6f, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x40, 0x08, 0x61, 0x6d, 0x65, 0x00, 0xe2, 0x6e, 0x00,
- 0x76, 0x04, 0x40, 0x07, 0x67, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x73,
- 0x74, 0x00, 0xe7, 0x63, 0x00, 0x67, 0x30, 0x6d, 0x38, 0x72, 0x59, 0x73,
- 0x78, 0x74, 0x90, 0x77, 0xa7, 0xe2, 0x61, 0x00, 0x72, 0x09, 0x40, 0x00,
- 0x72, 0x64, 0x69, 0x74, 0x69, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09,
- 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x3b, 0x65, 0x6e, 0x6f, 0x75, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x04, 0x75, 0x0a, 0x40, 0x00, 0x6c, 0x00,
- 0x40, 0x00, 0x73, 0x69, 0x73, 0x00, 0x40, 0x00, 0x6d, 0x00, 0xe2, 0x70,
- 0x00, 0x73, 0x06, 0x40, 0x07, 0x68, 0x69, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x00, 0x80, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x70, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x06, 0x00, 0x09, 0x40,
- 0x00, 0x63, 0x00, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x6c, 0x00, 0x72, 0x06, 0x40, 0x00, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x00,
- 0x6d, 0x69, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x91, 0x40,
- 0x09, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x69, 0x6e, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00, 0x3a, 0xe2, 0x61, 0x00, 0x65, 0x0f,
- 0xe2, 0x62, 0x00, 0x6e, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00, 0x40, 0x07,
- 0x63, 0x65, 0x00, 0x00, 0x52, 0x40, 0x00, 0x61, 0x79, 0x73, 0x00, 0xe2,
- 0x6d, 0x00, 0x72, 0x09, 0xe2, 0x61, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00,
- 0x06, 0xe2, 0x67, 0x00, 0x76, 0x2e, 0xe3, 0x65, 0x00, 0x69, 0x16, 0x79,
- 0x25, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1,
- 0x7a, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f,
- 0x00, 0x07, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x19, 0x6f, 0x20, 0x72, 0x4c, 0xe1, 0x65, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x01, 0x13, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x5e, 0x6c, 0x61,
- 0x64, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x04, 0x40, 0x5b, 0x64, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x64,
- 0x08, 0x6d, 0x0a, 0x72, 0x10, 0x00, 0x80, 0x40, 0x37, 0x62, 0x6c, 0x65,
- 0x00, 0x00, 0x37, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x02, 0x8b, 0x40, 0x84, 0x65, 0x6e, 0x74, 0x00, 0xe6, 0x61, 0x00,
- 0x65, 0x1c, 0x69, 0x23, 0x6f, 0x3f, 0x72, 0x55, 0x75, 0x87, 0xe1, 0x67,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02,
- 0x8c, 0x40, 0xd2, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x6c,
- 0x79, 0x00, 0x40, 0x5b, 0x6e, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x55, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x1a, 0xe2, 0x6d, 0x00, 0x76, 0x02, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x91, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x35, 0x40, 0x07, 0x65, 0x6e, 0x74,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x02, 0x80, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x80, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x09, 0x40, 0x06, 0x6d, 0x62, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x04, 0x40, 0x5b, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x6d, 0x08, 0x02, 0x8d, 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x06,
- 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x22, 0xe1, 0x72, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6d,
- 0x08, 0x72, 0x0e, 0x00, 0x80, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40,
- 0x09, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0xe3, 0x67, 0x00, 0x73, 0x1f,
- 0x76, 0x41, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x02, 0x8a, 0x40,
- 0x37, 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x02, 0x8e, 0x40, 0x06, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0xe1, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x13, 0xe1, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x51, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x16,
- 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x02, 0x51, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07,
- 0x69, 0x00, 0xe2, 0x72, 0x00, 0x75, 0x20, 0xe1, 0x6d, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x67, 0x68, 0x00, 0x40, 0x3a, 0x6c, 0x61,
- 0x6e, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x08, 0x72, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x6c, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x10, 0x6f, 0x23, 0xe2,
- 0x67, 0x00, 0x70, 0x04, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x3a, 0x74, 0x75,
- 0x72, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x58, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x8f, 0x40,
- 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe7, 0x63, 0x00, 0x65, 0x07, 0x68, 0x0e,
- 0x69, 0x2e, 0x6c, 0x3d, 0x6e, 0x53, 0x75, 0x69, 0x40, 0x3a, 0x6f, 0x6e,
- 0x63, 0x65, 0x00, 0x40, 0x06, 0x6d, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x13, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x35, 0x40, 0x07, 0x65, 0x6e, 0x74,
- 0x00, 0x40, 0x72, 0x75, 0x64, 0x00, 0xe2, 0x67, 0x00, 0x6c, 0x04, 0x40,
- 0x09, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x67, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02,
- 0x51, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x58, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00, 0x3a,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07,
- 0xf7, 0x61, 0x00, 0x00, 0x65, 0x37, 0x00, 0x68, 0x90, 0x00, 0x69, 0xee,
- 0x00, 0x6f, 0x31, 0x01, 0x72, 0x6d, 0x01, 0x77, 0x3e, 0x02, 0xe2, 0x69,
- 0x00, 0x6e, 0x10, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02,
- 0x51, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x90, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x84, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x05, 0x40, 0x06,
- 0x74, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x70, 0x0e, 0x74, 0x23,
- 0x01, 0x40, 0xe2, 0x63, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x07, 0x69,
- 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x01, 0x7f, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x6d, 0x0b, 0x02, 0x91, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x12, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x72,
- 0x00, 0x75, 0x2b, 0xe2, 0x61, 0x00, 0x6f, 0x13, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0x13, 0x40, 0x07, 0x65,
- 0x6e, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x01, 0x13, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3a, 0xe1, 0x61, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x37, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3, 0x63, 0x00, 0x72,
- 0x17, 0x74, 0x25, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x01, 0x13, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x3b,
- 0x40, 0x07, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x79, 0x10, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x51, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0x00, 0x06, 0xe2, 0x6d, 0x00, 0x75, 0x30, 0xe2, 0x62, 0x00, 0x6f,
- 0x0d, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x51, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61,
- 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0x40, 0x06, 0x72, 0x61,
- 0x67, 0x65, 0x00, 0xe6, 0x27, 0x00, 0x61, 0x07, 0x65, 0x4e, 0x6f, 0xa5,
- 0x75, 0xaa, 0x79, 0xaf, 0x40, 0x00, 0x61, 0x63, 0x74, 0x65, 0x00, 0xe3,
- 0x69, 0x00, 0x6e, 0x05, 0x70, 0x23, 0x40, 0x07, 0x6c, 0x73, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x17, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x7b, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x70, 0x08,
- 0x00, 0x9f, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x13, 0x6e, 0x15, 0x70, 0x28, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x79, 0x07, 0x00, 0xad, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0x00, 0x06, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x02, 0x51, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07,
- 0x00, 0x06, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x68, 0x69, 0x70,
- 0x00, 0x40, 0x07, 0x70, 0x79, 0x00, 0x40, 0x5b, 0x73, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x70, 0x02, 0x77, 0x09, 0x00, 0x65, 0x40, 0x08, 0x68, 0x6f,
- 0x6e, 0x65, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0x40, 0x3a, 0x69, 0x6e,
- 0x65, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x25, 0x72, 0x3d, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40,
- 0x00, 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x69, 0x73, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x28, 0x6f, 0x95,
- 0x79, 0x99, 0xe2, 0x6c, 0x00, 0x6e, 0x1e, 0xe1, 0x6f, 0x00, 0xe1, 0x70,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x0b, 0x02, 0x92, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x74,
- 0x00, 0x40, 0x7a, 0x6f, 0x6d, 0x00, 0xe4, 0x61, 0x00, 0x6f, 0x0f, 0x72,
- 0x22, 0x73, 0x55, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x37, 0x00, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x26,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x00, 0x06, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x0b, 0x67,
- 0x65, 0x00, 0x40, 0x72, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1,
- 0x79, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x00,
- 0x74, 0x69, 0x63, 0x00, 0x00, 0x06, 0xe3, 0x6c, 0x00, 0x6e, 0x06, 0x73,
- 0x08, 0x40, 0x00, 0x69, 0x61, 0x6e, 0x00, 0x00, 0x06, 0xe1, 0x69, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x08, 0x40, 0x00, 0x63, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x65, 0x07, 0x00,
- 0x68, 0x0b, 0x00, 0x69, 0x2c, 0x00, 0x6f, 0xcc, 0x01, 0x73, 0xf1, 0x01,
- 0x40, 0x06, 0x75, 0x6c, 0x65, 0x74, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x64, 0x00, 0x6d, 0x07, 0x40, 0x07, 0x72, 0x69, 0x6e,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x3b, 0xf8, 0x63, 0x00, 0x00,
- 0x64, 0x21, 0x00, 0x67, 0x79, 0x00, 0x6c, 0xac, 0x00, 0x6e, 0xc8, 0x00,
- 0x70, 0xd2, 0x00, 0x73, 0xd9, 0x00, 0x74, 0x48, 0x01, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x75, 0x09, 0x00, 0x09, 0x40, 0x09, 0x6e, 0x74, 0x65, 0x72,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0x40, 0x09, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x4d, 0xe2,
- 0x6d, 0x00, 0x72, 0x33, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x6f, 0x0d,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c,
- 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x08, 0x72, 0x61, 0x6c, 0x00, 0xe2, 0x6c,
- 0x00, 0x72, 0x08, 0x40, 0x09, 0x6f, 0x74, 0x74, 0x69, 0x73, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x0e, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x61, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x68, 0x00,
- 0xe3, 0x00, 0x00, 0x73, 0x02, 0x79, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x07, 0xe2, 0x65, 0x00, 0x6f, 0x11, 0xe1, 0x70, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x69, 0x63, 0x00, 0x40,
- 0x09, 0x67, 0x75, 0x65, 0x00, 0x40, 0x07, 0x65, 0x70, 0x68, 0x72, 0x69,
- 0x6e, 0x65, 0x00, 0x40, 0x06, 0x68, 0x61, 0x6e, 0x79, 0x00, 0xe3, 0x63,
- 0x00, 0x6f, 0x1a, 0x74, 0x34, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x61, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x04, 0x74, 0x06, 0x40, 0x07, 0x79,
- 0x00, 0x00, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3, 0x65, 0x00,
- 0x6c, 0x22, 0x6f, 0x26, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04,
- 0x40, 0x00, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00,
- 0x00, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x79,
- 0x00, 0xe3, 0x61, 0x00, 0x68, 0x0f, 0x6f, 0x29, 0xe1, 0x70, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x10, 0xe1, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x00,
- 0x06, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x0b, 0x7a, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x12, 0x78, 0x1a, 0xe1,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x07, 0x40,
- 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x79, 0x6d, 0x6f, 0x75, 0x73,
- 0x00, 0x40, 0x5e, 0x79, 0x00, 0x40, 0x06, 0x69, 0x6c, 0x6f, 0x6e, 0x00,
- 0xf1, 0x75, 0x00, 0x00, 0xf3, 0x61, 0x00, 0x00, 0x65, 0x68, 0x00, 0x69,
- 0x95, 0x00, 0xe4, 0x62, 0x00, 0x6c, 0x15, 0x6e, 0x3a, 0x74, 0x42, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x02, 0x0a, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x53, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0x40, 0x07, 0x69,
- 0x6d, 0x69, 0x74, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x02, 0x93, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe2, 0x72,
- 0x00, 0x73, 0x05, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x6d,
- 0x00, 0x40, 0x06, 0x6e, 0x6e, 0x65, 0x00, 0xe6, 0x64, 0x00, 0x6c, 0x09,
- 0x6e, 0x1e, 0x70, 0x33, 0x74, 0x5f, 0x76, 0x7d, 0x40, 0x3b, 0x69, 0x73,
- 0x74, 0x61, 0x6e, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x08, 0x40, 0x06,
- 0x74, 0x65, 0x72, 0x61, 0x6c, 0x00, 0x40, 0x84, 0x62, 0x72, 0x69, 0x75,
- 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x06, 0xe2, 0x63, 0x00,
- 0x78, 0x07, 0x40, 0x00, 0x74, 0x69, 0x61, 0x6c, 0x00, 0x00, 0x09, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x6d, 0x07, 0x6f, 0x0d, 0x70, 0x13, 0x00, 0x76,
- 0x40, 0x09, 0x67, 0x65, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40,
- 0x07, 0x69, 0x73, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x41, 0x84,
- 0x64, 0x00, 0x40, 0x77, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x17,
- 0xe2, 0x62, 0x00, 0x74, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x54, 0x00, 0x54, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x01,
- 0xa7, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x1b, 0x00, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00, 0x86, 0xe1,
- 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x0d, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x36, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x62, 0x43, 0x00, 0x65, 0x49, 0x00, 0x67, 0x85, 0x00, 0x6d, 0xbe, 0x00,
- 0x6f, 0xc4, 0x00, 0x72, 0x12, 0x01, 0x73, 0x54, 0x01, 0x75, 0x6c, 0x01,
- 0x79, 0xa5, 0x01, 0x01, 0x63, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x73, 0x27,
- 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x62, 0x00, 0x74, 0x05, 0x40, 0x54, 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x09, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x02, 0x94, 0x00, 0x07, 0x40, 0x06, 0x72, 0x65, 0x00, 0x40, 0x07,
- 0x69, 0x75, 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x27, 0x6d,
- 0x2d, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e,
- 0x0f, 0x6f, 0x15, 0x02, 0x95, 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x69, 0x74, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0xe4,
- 0x00, 0x00, 0x6e, 0x02, 0x73, 0x1f, 0x74, 0x27, 0x00, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x72, 0x6f, 0x6c, 0x00, 0x00,
- 0x07, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x64, 0x00, 0x67, 0x0d,
- 0x73, 0x15, 0x74, 0x25, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3a, 0x40,
- 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x6f, 0x75, 0x73,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x0e, 0x00, 0x08, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x73, 0x6d,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x2d, 0x00, 0xad, 0xe2, 0x6e,
- 0x00, 0x74, 0x09, 0xe2, 0x64, 0x00, 0x74, 0x02, 0x00, 0x06, 0x00, 0x54,
- 0xe3, 0x61, 0x00, 0x69, 0x02, 0x75, 0x12, 0x00, 0x06, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x07, 0x40, 0x3b,
- 0x65, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x74, 0x05,
- 0x40, 0x09, 0x74, 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x68, 0x69, 0x6c, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x11,
- 0x70, 0x23, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x7a,
- 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0x96, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xe2, 0x40,
- 0x09, 0x6f, 0x6e, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x09, 0x40, 0x07, 0x69,
- 0x70, 0x65, 0x6c, 0x61, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x06, 0x40, 0x06, 0x79, 0x74,
- 0x65, 0x00, 0x40, 0x00, 0x79, 0x63, 0x69, 0x6e, 0x00, 0xf6, 0x63, 0x00,
- 0x00, 0x6f, 0xe6, 0x00, 0x70, 0x1f, 0x01, 0x71, 0x7e, 0x01, 0x73, 0x85,
- 0x01, 0x74, 0xbf, 0x01, 0xe5, 0x61, 0x00, 0x68, 0x8f, 0x6f, 0xb4, 0x72,
- 0xb9, 0x75, 0xca, 0xe3, 0x6c, 0x00, 0x70, 0x30, 0x72, 0x70, 0xe3, 0x61,
- 0x00, 0x6c, 0x1f, 0x6f, 0x24, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x11, 0x02, 0x97, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x01, 0x52, 0x00, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x93, 0x6f, 0x70, 0x00, 0x40, 0x08, 0x70, 0x65, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x05, 0x69, 0x16, 0x6f, 0x22, 0x40, 0x09, 0x64, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x04, 0x00, 0xa4, 0x00, 0x09, 0x40,
- 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x08, 0x73, 0x74, 0x00,
- 0x00, 0x00, 0xe3, 0x67, 0x00, 0x6f, 0x05, 0x70, 0x0a, 0x40, 0x09, 0x6f,
- 0x74, 0x00, 0x40, 0x09, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x6d, 0x65, 0x6e,
- 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1c, 0xe1, 0x74, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x06, 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x40,
- 0x7a, 0x77, 0x00, 0x40, 0x2c, 0x72, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x08, 0x40, 0x09, 0x74, 0x6f, 0x69, 0x72, 0x65, 0x00, 0x40, 0x06, 0x77,
- 0x00, 0xe2, 0x64, 0x00, 0x74, 0x04, 0x40, 0x06, 0x6f, 0x00, 0x40, 0x06,
- 0x63, 0x68, 0x65, 0x6f, 0x6e, 0x00, 0xe2, 0x70, 0x00, 0x74, 0x1b, 0xe1,
- 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x05, 0x75, 0x07, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x15, 0x69, 0x1c,
- 0x6c, 0x24, 0x6f, 0x2c, 0x72, 0x3d, 0x79, 0x4c, 0x00, 0x00, 0xe2, 0x64,
- 0x00, 0x6c, 0x08, 0x40, 0x09, 0x72, 0x69, 0x6c, 0x6c, 0x65, 0x00, 0x40,
- 0x47, 0x69, 0x65, 0x72, 0x00, 0x40, 0x3b, 0x63, 0x69, 0x61, 0x6c, 0x00,
- 0x40, 0x07, 0x6f, 0x6e, 0x61, 0x67, 0x65, 0x00, 0x40, 0x09, 0x61, 0x6e,
- 0x61, 0x64, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x00, 0x0b, 0xe2, 0x65, 0x00,
- 0x69, 0x06, 0x40, 0x09, 0x73, 0x73, 0x6f, 0x00, 0x40, 0x07, 0x74, 0x00,
- 0x00, 0x3a, 0x40, 0x06, 0x75, 0x69, 0x72, 0x65, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x15, 0xe1, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x01, 0x89, 0x40, 0x00, 0x79, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x2e,
- 0x69, 0x39, 0x6f, 0x5b, 0x72, 0x62, 0x75, 0x91, 0xe2, 0x62, 0x00, 0x74,
- 0x25, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x98, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xc2,
- 0x00, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x41,
- 0xc4, 0x6d, 0x00, 0x00, 0x06, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x62, 0x00, 0x74, 0x05, 0x40, 0x54, 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0x8d, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x00, 0x70, 0x70, 0x65, 0x6c, 0x00, 0xe3, 0x61,
- 0x00, 0x6f, 0x16, 0x75, 0x24, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x78, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x00, 0xe2, 0x67, 0x00, 0x75, 0x05, 0x40, 0x07, 0x65, 0x6e,
- 0x00, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40, 0x06, 0x61,
- 0x72, 0x79, 0x00, 0xf7, 0x61, 0x00, 0x00, 0x63, 0x02, 0x00, 0x65, 0x1b,
- 0x00, 0x68, 0x3b, 0x00, 0x69, 0x29, 0x01, 0x75, 0x5c, 0x01, 0x79, 0x61,
- 0x01, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x02, 0x99, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x10, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00,
- 0xe6, 0x61, 0x00, 0x65, 0x0e, 0x69, 0x1d, 0x6e, 0x2f, 0x6f, 0xb0, 0x79,
- 0xd2, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40,
- 0x07, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x73, 0x06, 0x00, 0x06, 0x40, 0x36, 0x6c, 0x00, 0x00, 0x07,
- 0xe2, 0x69, 0x00, 0x6f, 0x17, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x08, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0xe3, 0x63, 0x00, 0x67, 0x1a, 0x6c, 0x43, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6d,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x14, 0x40, 0x08, 0x72, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b,
- 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x6c, 0x00,
- 0x73, 0x1b, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40,
- 0x09, 0x74, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe2, 0x6f,
- 0x00, 0x71, 0x26, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40,
- 0x00, 0x74, 0x65, 0x64, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x0e, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x00, 0x00, 0x06, 0x40, 0x07, 0x75, 0x65, 0x74, 0x74, 0x65,
- 0x00, 0x40, 0x06, 0x64, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00,
- 0x40, 0x06, 0x74, 0x00, 0x00, 0x06, 0xf7, 0x63, 0x00, 0x00, 0x67, 0x2b,
- 0x00, 0x6c, 0x4f, 0x00, 0x6e, 0x7b, 0x00, 0x70, 0x8d, 0x00, 0x72, 0xe1,
- 0x00, 0x74, 0xf8, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x17, 0x6c, 0x1c, 0xe1,
- 0x6c, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40, 0x5e,
- 0x72, 0x65, 0x00, 0x40, 0x00, 0x69, 0x64, 0x65, 0x61, 0x6e, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x73, 0x0d, 0x00, 0x08, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe1,
- 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1f, 0xe2, 0x73,
- 0x00, 0x7a, 0x0e, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x3f, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x23, 0xe1, 0x6d, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x72,
- 0x0d, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00,
- 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6b, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x70, 0x02, 0x00, 0x09, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00,
- 0xe2, 0x65, 0x00, 0x68, 0x07, 0x40, 0x00, 0x63, 0x74, 0x69, 0x63, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x13, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x06, 0x40, 0x07, 0x73, 0x69, 0x61, 0x00, 0x40, 0x3a, 0x7a, 0x65, 0x00,
- 0x40, 0x07, 0x6e, 0x69, 0x63, 0x73, 0x00, 0xf4, 0x61, 0x00, 0x00, 0x65,
- 0xdf, 0x00, 0x69, 0xae, 0x01, 0x6f, 0x29, 0x02, 0xe6, 0x63, 0x00, 0x64,
- 0x1b, 0x6c, 0x27, 0x6e, 0x40, 0x70, 0x98, 0x73, 0xb6, 0xe1, 0x75, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x01, 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x78, 0x40, 0x75, 0x6f, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x17, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x16, 0x7a, 0x28, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x56, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63,
- 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x65, 0x00, 0x65,
- 0xe6, 0x00, 0x00, 0x68, 0x02, 0x69, 0x0a, 0x6e, 0x0f, 0x73, 0x15, 0x74,
- 0x1b, 0x02, 0x9a, 0x40, 0x3b, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x69, 0x15, 0x75,
- 0x1a, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x36, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x64, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x0c, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40,
- 0x0b, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x67, 0x02, 0x6c, 0x13, 0x6d, 0x1c,
- 0x79, 0x22, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x06, 0x40, 0x06, 0x61,
- 0x64, 0x65, 0x00, 0x40, 0x06, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x86, 0x61,
- 0x73, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x65, 0x00,
- 0xe7, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08, 0x6f, 0x0d, 0x70, 0x12, 0x74,
- 0x19, 0x77, 0x20, 0x00, 0x00, 0x40, 0x07, 0x6f, 0x64, 0x79, 0x00, 0x40,
- 0x00, 0x61, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x6c,
- 0x61, 0x63, 0x65, 0x00, 0x40, 0x07, 0x68, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x68, 0x65, 0x72, 0x65, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x0f, 0x6c,
- 0x20, 0x6e, 0x50, 0x73, 0x55, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x7a, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x82, 0x65, 0x00, 0x00,
- 0x3b, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6c, 0x13, 0x6e, 0x21, 0x02, 0x9b,
- 0xe1, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x3a, 0x63, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00,
- 0x6b, 0x16, 0x6c, 0x1a, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x3b,
- 0x65, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x75, 0x00, 0x76, 0x1f, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x07, 0x40, 0x00, 0x72, 0x79,
- 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x94, 0x00, 0x07, 0xfc, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0xe9, 0x00, 0x65, 0x6f, 0x03, 0x66,
- 0x61, 0x04, 0x68, 0x6a, 0x04, 0x69, 0x21, 0x05, 0x6f, 0x8d, 0x05, 0x70,
- 0x46, 0x06, 0x71, 0xa1, 0x0a, 0x74, 0xc0, 0x0a, 0x75, 0x1c, 0x0e, 0x00,
- 0x09, 0xe6, 0x62, 0x00, 0x63, 0x06, 0x67, 0x47, 0x6c, 0x6f, 0x6d, 0x80,
- 0x73, 0xb0, 0x40, 0x09, 0x79, 0x74, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x74,
- 0x18, 0xe1, 0x72, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x17, 0x02, 0x9c, 0xe3, 0x6e,
- 0x00, 0x6f, 0x04, 0x74, 0x08, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x07, 0x75, 0x64, 0x65, 0x00, 0x40, 0x53, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x01, 0x26, 0x00, 0x3b, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x7a, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x70, 0x1a, 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x4b, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x82, 0x00, 0x37, 0xe1, 0x70,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x57, 0x00, 0x3b, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xf8, 0x61, 0x00, 0x00, 0x65, 0x1b, 0x00, 0x68,
- 0xa6, 0x00, 0x69, 0xc8, 0x00, 0x6c, 0x15, 0x01, 0x6f, 0x73, 0x01, 0x72,
- 0xae, 0x01, 0x75, 0x03, 0x02, 0xe1, 0x76, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x39, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe5, 0x65, 0x00, 0x6c,
- 0x0f, 0x70, 0x3f, 0x72, 0x6c, 0x73, 0x71, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0xad, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x73, 0x23, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x17,
- 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06, 0x00, 0x3b, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x72, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xad, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x02, 0x9d, 0xe2, 0x62, 0x00,
- 0x6c, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x36, 0x40, 0x00, 0x73, 0x6d, 0x00, 0x40, 0x55, 0x70, 0x74, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xe4, 0x40, 0x3b,
- 0x76, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x16, 0xe1, 0x6e, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x5e,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x71, 0x75, 0x65, 0x72,
- 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01,
- 0xcd, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1b, 0x69,
- 0x30, 0xe2, 0x62, 0x00, 0x74, 0x10, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6d, 0x04, 0x72,
- 0x0a, 0x02, 0x9e, 0x00, 0x3b, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x00,
- 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x75,
- 0x20, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x6d, 0x04, 0x40, 0x72, 0x6d, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x64, 0x00,
- 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00,
- 0x76, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0x8f, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x72, 0x21, 0xe1, 0x6d, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x39, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x46, 0xe3, 0x6d, 0x00, 0x73,
- 0x14, 0x74, 0x28, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x09, 0x65, 0x00, 0x00, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x02,
- 0x69, 0x04, 0x6f, 0x09, 0x00, 0x07, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0x40, 0x3b, 0x63, 0x69, 0x61, 0x74,
- 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x6c, 0x00, 0x72, 0x1c, 0x73, 0x46, 0xe1,
- 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00,
- 0x76, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x09, 0x73, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x0f, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x54, 0x00, 0x54, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x02, 0x9f,
- 0x00, 0x37, 0xe5, 0x63, 0x00, 0x67, 0x61, 0x6d, 0x87, 0x72, 0xbf, 0x75,
- 0xe2, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x75, 0x22, 0x00, 0x09, 0xe1, 0x61,
- 0x00, 0xe2, 0x62, 0x00, 0x74, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x19, 0x72, 0x1d, 0x02, 0xa0, 0xe2, 0x6f, 0x00, 0x76,
- 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x27, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x05, 0x40, 0x00, 0x65, 0x73, 0x00,
- 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0d, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x24,
- 0xe2, 0x61, 0x00, 0x69, 0x0c, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x06, 0x00, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x02, 0xa1,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x5b, 0x40, 0x06, 0x6f, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x12, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x7a, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x74, 0x00, 0x40, 0x42, 0x6f, 0x6c, 0x69, 0x61, 0x74, 0x65,
- 0x00, 0xe4, 0x61, 0x00, 0x69, 0x40, 0x6f, 0x89, 0x75, 0x9d, 0xe2, 0x6c,
- 0x00, 0x75, 0x0e, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x6d, 0xe3, 0x62, 0x00, 0x6f, 0x05, 0x76,
- 0x09, 0x40, 0x54, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x62, 0x00, 0x6c, 0x2c, 0xe1, 0x69, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x1b, 0x00, 0x59, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1,
- 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40,
- 0x06, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x7a, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0xe4, 0x67, 0x00, 0x6c, 0x27, 0x73, 0x2b, 0x74,
- 0x61, 0xe2, 0x65, 0x00, 0x75, 0x13, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x00, 0x75, 0x73, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x7a, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x00, 0x09, 0x00, 0x55, 0xe8, 0x62, 0x00, 0x64, 0x09, 0x67, 0x0e, 0x6e,
- 0x16, 0x70, 0x32, 0x72, 0x3a, 0x73, 0x69, 0x74, 0x7e, 0x40, 0x07, 0x69,
- 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x00, 0x40, 0x09, 0x75, 0x73, 0x00, 0x40,
- 0x00, 0x65, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x09, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x00, 0xe2, 0x62, 0x00, 0x63, 0x17,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x6d, 0x02, 0x74, 0x04,
- 0x00, 0x3a, 0x00, 0x06, 0x00, 0x06, 0xe2, 0x6b, 0x00, 0x70, 0x09, 0x40,
- 0x06, 0x65, 0x6c, 0x65, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x68, 0x65,
- 0x72, 0x65, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x08, 0x40, 0x00, 0x65, 0x72,
- 0x6d, 0x69, 0x63, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x0e, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xf8, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x65, 0x88, 0x00, 0x69, 0xdc, 0x01, 0x6c, 0x10,
- 0x02, 0x6f, 0xf3, 0x02, 0x72, 0x90, 0x03, 0x75, 0x13, 0x04, 0x00, 0x00,
- 0xe2, 0x6e, 0x00, 0x74, 0x51, 0xe2, 0x64, 0x00, 0x73, 0x0c, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x02, 0xa2, 0x40, 0x09, 0x72, 0x61, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x02, 0xa3, 0xe3, 0x62, 0x00, 0x6f, 0x05, 0x76, 0x22,
- 0x40, 0x00, 0x6c, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x07, 0x00, 0x07, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72, 0x14, 0x00, 0x08, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0xa4, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xf5, 0x63, 0x00, 0x00, 0x64, 0x3d, 0x00, 0x6c, 0x98, 0x00,
- 0x6e, 0xad, 0x00, 0x72, 0xe2, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x6f, 0x18, 0x00, 0xad, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b, 0x40, 0x06,
- 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e,
- 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x65,
- 0x00, 0x74, 0x21, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x17, 0xe3,
- 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x53, 0x00, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x53, 0x00, 0x56,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0xa5,
- 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x0c, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x16, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x02,
- 0xa6, 0x40, 0x06, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x74, 0x75, 0x72,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x76, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xda, 0x40, 0x53,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x49, 0xe2, 0x65, 0x00,
- 0x6d, 0x21, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x13, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x02, 0xa7, 0x00, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x0f, 0x00, 0xe7, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x3b,
- 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6e, 0x07, 0x02, 0x0c, 0x40, 0x07, 0x73, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x16, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x07, 0x79, 0x10, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x3a, 0x00, 0x37, 0x00, 0x07, 0xe4, 0x61,
- 0x00, 0x65, 0x30, 0x69, 0x37, 0x6f, 0x65, 0xe2, 0x69, 0x00, 0x6e, 0x16,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x01, 0xf9,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0x40, 0x09, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x16, 0xe2, 0x62,
- 0x00, 0x74, 0x05, 0x40, 0x54, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe4, 0x64, 0x00, 0x69, 0x04, 0x72, 0x2c, 0x73, 0x50, 0x40, 0x0b, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x15, 0x02,
- 0xa8, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x37, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x12, 0xe1, 0x74,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x00,
- 0x3f, 0x00, 0x37, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x02, 0x0c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x00, 0x00,
- 0x6e, 0x02, 0x72, 0x22, 0x73, 0x39, 0x75, 0x81, 0x00, 0x09, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x3b,
- 0x40, 0x00, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x09, 0x02, 0xa9, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x09, 0x74, 0x22,
- 0x75, 0x3a, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x5e, 0x00, 0x37, 0xe1,
- 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6f, 0x6e, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x09, 0x72, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x3f, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x5d, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x77, 0x49, 0x02, 0xaa, 0x40, 0x37, 0x64, 0x00,
- 0xe3, 0x62, 0x00, 0x6f, 0x05, 0x76, 0x2c, 0x40, 0x54, 0x6c, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x17, 0x00, 0x06,
- 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x3b, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x79, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x51,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x6c, 0x00,
- 0x6e, 0x07, 0x72, 0x0c, 0x40, 0x09, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x40,
- 0x0b, 0x67, 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x38, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x07,
- 0x00, 0x69, 0xea, 0x00, 0x6f, 0x37, 0x01, 0x72, 0x7a, 0x01, 0x00, 0x00,
- 0x40, 0x00, 0x6e, 0x74, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x3f, 0x72, 0x94,
- 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x1c, 0x69, 0x1e, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe1, 0x7a,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x0b, 0xe4, 0x64, 0x00, 0x73, 0x0b, 0x74, 0x38, 0x75, 0x3a,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0xab, 0x40, 0x07, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe3, 0x62, 0x00, 0x6f, 0x05, 0x76, 0x13, 0x40, 0x00, 0x6c,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x69, 0x00, 0x6d, 0x05, 0x6e, 0x23, 0x40,
- 0x09, 0x6f, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe1,
- 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0xe2, 0x6e, 0x00, 0x72, 0x33, 0xe2, 0x63, 0x00,
- 0x67, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x0b,
- 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08,
- 0x02, 0xac, 0x40, 0x54, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x6c, 0x00,
- 0x72, 0x15, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x5b, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x0b,
- 0x00, 0x13, 0x40, 0x3b, 0x74, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x35, 0x01, 0x69,
- 0x5c, 0x01, 0x6f, 0x90, 0x01, 0x75, 0xa6, 0x01, 0xfc, 0x00, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x64, 0x2f, 0x00, 0x6a, 0x41, 0x00, 0x6c, 0x4b, 0x00,
- 0x6d, 0x52, 0x00, 0x6e, 0x65, 0x00, 0x6f, 0x6c, 0x00, 0x70, 0x91, 0x00,
- 0x73, 0xa9, 0x00, 0x74, 0xb2, 0x00, 0x76, 0xe7, 0x00, 0x00, 0x06, 0xe3,
- 0x65, 0x00, 0x74, 0x09, 0x75, 0x1b, 0x40, 0x00, 0x6c, 0x6c, 0x75, 0x6c,
- 0x61, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x55,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x72,
- 0x72, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0xad, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x75, 0x64, 0x69, 0x63, 0x69, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x65, 0x67, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x08,
- 0x40, 0x00, 0x72, 0x69, 0x74, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x72, 0x61,
- 0x6c, 0x00, 0x40, 0x3b, 0x65, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40, 0x00, 0x72, 0x65, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00,
- 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0x40, 0x09, 0x73,
- 0x74, 0x72, 0x69, 0x61, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x1a, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x74, 0x04, 0x7a, 0x06, 0x40, 0x09, 0x65,
- 0x00, 0x00, 0x3b, 0x40, 0x09, 0x61, 0x00, 0x40, 0x00, 0x68, 0x69, 0x63,
- 0x75, 0x6c, 0x61, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x6a, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x09, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x63, 0x00, 0x6e,
- 0x19, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x54, 0x6c,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x06, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0xb1, 0xe2, 0x64,
- 0x00, 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe4,
- 0x62, 0x00, 0x64, 0x17, 0x6c, 0x25, 0x72, 0x3e, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x7a, 0xe2, 0x6e, 0x00, 0x74, 0x04,
- 0x40, 0x3b, 0x74, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x62,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x11, 0x00, 0x06, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x06, 0x74, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xec, 0x00, 0x00, 0x62,
- 0x02, 0x64, 0x11, 0x66, 0x1a, 0x67, 0x1f, 0x69, 0x26, 0x6c, 0x2b, 0x6f,
- 0x4e, 0x70, 0x65, 0x73, 0x6c, 0x74, 0x85, 0x77, 0x96, 0x00, 0x1a, 0xe2,
- 0x61, 0x00, 0x72, 0x05, 0x40, 0x59, 0x6c, 0x6c, 0x00, 0x40, 0x06, 0x6f,
- 0x77, 0x00, 0x40, 0x06, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x72, 0x00, 0x40,
- 0x06, 0x75, 0x6c, 0x00, 0x40, 0x09, 0x6c, 0x61, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x10, 0x40,
- 0x09, 0x73, 0x68, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x00, 0x73,
- 0x00, 0x00, 0x06, 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x40, 0x09,
- 0x65, 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x69, 0x65, 0x63, 0x65, 0x00, 0xe3, 0x69, 0x00,
- 0x6f, 0x06, 0x74, 0x0b, 0x40, 0x07, 0x67, 0x68, 0x74, 0x00, 0x40, 0x09,
- 0x72, 0x65, 0x00, 0x40, 0x07, 0x72, 0x61, 0x69, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x06, 0x40, 0x00, 0x65, 0x74, 0x68, 0x00, 0x40, 0x07, 0x6f,
- 0x74, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x73, 0x68,
- 0x00, 0x40, 0x09, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xfd, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x65, 0x89, 0x08, 0x66, 0xcc, 0x0d, 0x69, 0xce,
- 0x0d, 0x6a, 0x5c, 0x16, 0x6c, 0x62, 0x16, 0x6f, 0x23, 0x20, 0x70, 0xc4,
- 0x2b, 0x72, 0xc8, 0x2b, 0x74, 0x6f, 0x34, 0x75, 0x78, 0x34, 0x77, 0x26,
- 0x39, 0x02, 0xae, 0xc1, 0x62, 0x19, 0x37, 0x00, 0x39, 0x00, 0x71, 0x00,
- 0x9b, 0x01, 0xc0, 0x01, 0xc6, 0x01, 0xca, 0x01, 0x00, 0x00, 0xeb, 0x01,
- 0xab, 0x02, 0xbd, 0x02, 0xcf, 0x02, 0xa6, 0x03, 0xfb, 0x03, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe5, 0x04, 0xef, 0x05, 0xb6, 0x06, 0xc0, 0x07,
- 0x38, 0x08, 0x69, 0x08, 0x77, 0x08, 0x79, 0x08, 0x7b, 0x08, 0x00, 0x07,
- 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x06, 0x75, 0x28, 0x00, 0x00, 0x40,
- 0x1a, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x3b, 0x6c, 0x6f, 0x75, 0x73, 0x00, 0xf6, 0x61, 0x00, 0x00,
- 0x65, 0x05, 0x00, 0x69, 0x4e, 0x00, 0x73, 0x83, 0x00, 0x74, 0x9e, 0x00,
- 0x75, 0x11, 0x01, 0x40, 0x06, 0x64, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x27,
- 0x02, 0x63, 0x06, 0x6c, 0x1b, 0x74, 0x21, 0x02, 0xaf, 0x40, 0x00, 0x73,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0xe1,
- 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00,
- 0x6c, 0x04, 0x6e, 0x2a, 0x40, 0x56, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x3b, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x15, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x00, 0x06, 0x40, 0x06,
- 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x1a,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x2d,
- 0x75, 0x65, 0x00, 0x09, 0xe2, 0x6f, 0x00, 0x74, 0x1f, 0xe2, 0x6e, 0x00,
- 0x75, 0x16, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x69, 0x6f, 0x75, 0x73, 0x00, 0xe3,
- 0x69, 0x00, 0x72, 0x04, 0x74, 0x2c, 0x40, 0x06, 0x64, 0x00, 0xe4, 0x00,
- 0x00, 0x27, 0x02, 0x69, 0x06, 0x79, 0x1d, 0x00, 0xd5, 0x40, 0x00, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x7a, 0x04, 0x40, 0x09, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b,
- 0x00, 0x06, 0x40, 0x06, 0x75, 0x6d, 0x00, 0x40, 0x3b, 0x61, 0x6c, 0x00,
- 0x40, 0x06, 0x6c, 0x74, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x65,
- 0x15, 0x69, 0x17, 0x00, 0x95, 0xe2, 0x69, 0x00, 0x79, 0x0c, 0xe1, 0x73,
- 0x00, 0xe2, 0x68, 0x00, 0x74, 0x02, 0x00, 0x5d, 0x00, 0x09, 0x00, 0x5d,
- 0x00, 0x09, 0x40, 0x37, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x72, 0x69, 0x65,
- 0x00, 0x40, 0x72, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x6f, 0x16,
- 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x09, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x74, 0x00, 0x41, 0x25,
- 0x74, 0x00, 0xe5, 0x65, 0x00, 0x6c, 0x06, 0x6e, 0x1f, 0x72, 0x3e, 0x74,
- 0x72, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02,
- 0x6c, 0x07, 0x75, 0x0b, 0x01, 0xb5, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0x40, 0x06, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0xf3, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6e, 0x0b, 0x02, 0x18,
- 0x40, 0x00, 0x65, 0x61, 0x72, 0x74, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x67, 0x02, 0x69, 0x0a, 0x6e, 0x0f,
- 0x77, 0x15, 0x79, 0x1a, 0x02, 0xb0, 0x40, 0x09, 0x72, 0x6f, 0x75, 0x6e,
- 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x61, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x06, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00,
- 0x00, 0x66, 0x02, 0x6c, 0x1f, 0x73, 0x35, 0x00, 0x07, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x6e, 0x06, 0x73, 0x0c,
- 0x02, 0xb1, 0x40, 0x00, 0x73, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x06,
- 0x72, 0x00, 0xe4, 0x63, 0x00, 0x6c, 0x17, 0x73, 0x6e, 0x74, 0xbc, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x06,
- 0x01, 0x24, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x12, 0x69, 0x18, 0x6f, 0x3b, 0x02, 0xb2, 0xe1,
- 0x63, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x3b, 0x6f, 0x75, 0x73,
- 0x00, 0x00, 0x06, 0x40, 0x00, 0x61, 0x63, 0x6b, 0x00, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x54, 0xe3, 0x66, 0x00, 0x75,
- 0x04, 0x77, 0x08, 0x40, 0x06, 0x66, 0x00, 0x40, 0x07, 0x74, 0x00, 0x00,
- 0x2c, 0xe2, 0x65, 0x00, 0x69, 0x1c, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x6e,
- 0x08, 0x74, 0x0e, 0x00, 0x7f, 0x40, 0x06, 0x6f, 0x6f, 0x64, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x74, 0x6f, 0x00, 0xe3, 0x65,
- 0x00, 0x66, 0x02, 0x74, 0x22, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x79, 0x19,
- 0xe3, 0x61, 0x00, 0x63, 0x06, 0x65, 0x0e, 0x40, 0x00, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x02, 0xa5, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0xb3, 0x40, 0x3b, 0x6e, 0x67,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0b, 0x6f, 0x49, 0xe2, 0x00, 0x00, 0x27,
- 0x02, 0x00, 0xfc, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x2f,
- 0x73, 0x33, 0xe2, 0x69, 0x00, 0x79, 0x28, 0xe1, 0x61, 0x00, 0xe2, 0x6c,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86,
- 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0xdb, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x00,
- 0x06, 0x40, 0x06, 0x65, 0x00, 0x40, 0x3a, 0x68, 0x00, 0x40, 0x5c, 0x75,
- 0x73, 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x62, 0x1d, 0x63, 0x22, 0x64,
- 0x66, 0x66, 0x75, 0x67, 0x7b, 0x6c, 0x7d, 0x6e, 0x84, 0x74, 0x96, 0x7a,
- 0xcd, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x06, 0x40, 0x3b, 0x6c,
- 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x06, 0x6f, 0x79, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x32, 0xe5, 0x61, 0x00, 0x65, 0x06, 0x66, 0x0a, 0x6c,
- 0x1d, 0x6e, 0x21, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x02,
- 0xb4, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06,
- 0x40, 0x09, 0x6e, 0x67, 0x6f, 0x00, 0x40, 0x00, 0x6d, 0x00, 0x40, 0x06,
- 0x61, 0x72, 0x65, 0x00, 0x00, 0xb2, 0x40, 0x06, 0x69, 0x67, 0x68, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe2, 0x69,
- 0x00, 0x73, 0x04, 0x40, 0x09, 0x6c, 0x00, 0xe3, 0x69, 0x00, 0x74, 0x11,
- 0x79, 0x22, 0xe3, 0x61, 0x00, 0x73, 0x02, 0x7a, 0x06, 0x00, 0x06, 0x40,
- 0x08, 0x74, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00,
- 0x00, 0x5e, 0x40, 0x09, 0x69, 0x6e, 0x65, 0x00, 0xea, 0x00, 0x00, 0x61,
- 0x02, 0x63, 0x18, 0x65, 0x25, 0x69, 0x32, 0x6d, 0x46, 0x6f, 0x83, 0x72,
- 0x85, 0x73, 0xa6, 0x74, 0xce, 0x00, 0x00, 0xe2, 0x64, 0x00, 0x77, 0x0c,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x41, 0x20, 0x7a, 0x65, 0x00,
- 0x40, 0x00, 0x61, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x3b, 0x63, 0x61, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00,
- 0x82, 0x40, 0x06, 0x65, 0x6c, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40, 0x00, 0x65, 0x6f,
- 0x75, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x68, 0x06, 0x69, 0x16,
- 0x6c, 0x1b, 0x73, 0x21, 0x79, 0x28, 0x02, 0xb5, 0x40, 0x07, 0x72, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6e, 0x64, 0x00, 0x40, 0x06,
- 0x75, 0x73, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x61,
- 0x6e, 0x64, 0x00, 0x40, 0x09, 0x74, 0x65, 0x61, 0x64, 0x00, 0x40, 0x09,
- 0x61, 0x72, 0x64, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x69, 0x11, 0x6f,
- 0x16, 0xe1, 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40,
- 0x2c, 0x77, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x07, 0x40, 0x00, 0x65, 0x69,
- 0x6e, 0x67, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0x55, 0xe2, 0x65, 0x00, 0x69, 0x16, 0xe2, 0x72, 0x00, 0x73, 0x0d,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x73, 0x74,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0xe3, 0x63,
- 0x00, 0x68, 0x3f, 0x74, 0x6c, 0xe1, 0x69, 0x00, 0xe4, 0x61, 0x00, 0x63,
- 0x02, 0x6e, 0x07, 0x73, 0x21, 0x00, 0x06, 0x40, 0x06, 0x6c, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x39, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11,
- 0x69, 0x15, 0x02, 0xa8, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x37, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x09, 0x73, 0x74, 0x61, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x12,
- 0x69, 0x27, 0x6e, 0x43, 0x02, 0xb6, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00,
- 0x6c, 0x04, 0x40, 0x06, 0x6b, 0x00, 0x40, 0x06, 0x6c, 0x00, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x02, 0xb7, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x65, 0x73, 0x73, 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x62, 0x33,
- 0x65, 0x39, 0x68, 0x53, 0x69, 0x97, 0x6e, 0xa9, 0x73, 0xaf, 0x74, 0xb3,
- 0x75, 0xd2, 0x77, 0xef, 0x02, 0xb8, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0xe2, 0x73, 0x00, 0x74, 0x1e, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x07, 0x61, 0x63, 0x6b,
- 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x09, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x27, 0xe2, 0x61, 0x00, 0x72,
- 0x04, 0x40, 0xb2, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6c, 0x08,
- 0x00, 0xfd, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x05, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x73, 0x73, 0x00, 0xe1,
- 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x08, 0x02, 0xb9, 0x40,
- 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x47, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x08, 0x6f, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0f, 0x79, 0x16, 0xe3, 0x6e,
- 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x02, 0x0e, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe5, 0x63, 0x00, 0x6c, 0x05,
- 0x6e, 0x53, 0x76, 0x5c, 0x78, 0x6b, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe1,
- 0x74, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x69, 0x19, 0x6c, 0x28, 0x79,
- 0x3e, 0x02, 0xba, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02,
- 0x00, 0x08, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x11,
- 0x01, 0xc4, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x37, 0x00, 0x37, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x00, 0x59,
- 0x02, 0x29, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x0b,
- 0x00, 0x37, 0xc0, 0x61, 0x1a, 0x37, 0x00, 0xf2, 0x00, 0xf9, 0x00, 0x34,
- 0x01, 0x7c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x02, 0x8b, 0x02, 0xdb, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x16, 0x03, 0x19, 0x04, 0x5a, 0x04, 0xe5, 0x04, 0x08,
- 0x05, 0x28, 0x05, 0x00, 0x00, 0x35, 0x05, 0x37, 0x05, 0xe4, 0x6c, 0x00,
- 0x72, 0x05, 0x73, 0x3f, 0x74, 0x5e, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe4,
- 0x00, 0x00, 0x66, 0x02, 0x6c, 0x15, 0x73, 0x2b, 0x00, 0x55, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe2, 0x69, 0x00,
- 0x74, 0x18, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x9b,
- 0x00, 0x00, 0x00, 0x2c, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x75, 0x3a, 0x00,
- 0x09, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02,
- 0x6c, 0x17, 0x77, 0x1d, 0x79, 0x25, 0x00, 0x93, 0xe2, 0x65, 0x00, 0x72,
- 0x08, 0x40, 0x07, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x61,
- 0x69, 0x6e, 0x65, 0x64, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00, 0x60, 0xe1, 0x72, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x5e, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x72, 0x69, 0x6c, 0x65, 0x00, 0xe4,
- 0x61, 0x00, 0x65, 0x04, 0x6b, 0x08, 0x75, 0x0f, 0x40, 0x00, 0x6c, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x4d, 0x6c, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x11,
- 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x6f, 0x3c, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x23, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x56, 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0xbb,
- 0x42, 0xbc, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x61, 0x00, 0xe5, 0x00,
- 0x00, 0x62, 0x02, 0x64, 0x19, 0x6c, 0x42, 0x74, 0x5c, 0x00, 0x06, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0xf4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe5, 0x00,
- 0x00, 0x62, 0x02, 0x65, 0x10, 0x69, 0x14, 0x6c, 0x19, 0x02, 0x65, 0xe1,
- 0x61, 0x00, 0xe2, 0x63, 0x00, 0x67, 0x04, 0x40, 0x07, 0x6b, 0x00, 0x00,
- 0x06, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x6f, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x67, 0x06, 0x69, 0x0c,
- 0x02, 0x65, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x6f, 0x64, 0x00,
- 0x40, 0x12, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe3, 0x67, 0x00, 0x6e, 0x0e,
- 0x73, 0x12, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x7a,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x2c, 0x74, 0x00, 0x40, 0x60, 0x74, 0x79,
- 0x00, 0xe5, 0x64, 0x00, 0x69, 0x07, 0x6c, 0x33, 0x6f, 0x67, 0x74, 0x7b,
- 0x40, 0x07, 0x73, 0x70, 0x61, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x23,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x0f, 0x79,
- 0x14, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x51, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x01, 0xa7, 0x40,
- 0x06, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x0e, 0x02, 0xbd,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0x40, 0x07, 0x69, 0x6f, 0x00,
- 0xe1, 0x77, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x73, 0x0f, 0x00, 0x06,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x79, 0x08, 0x00, 0x06, 0x40, 0x00, 0x6f, 0x75, 0x73,
- 0x00, 0x00, 0x06, 0x00, 0x55, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x15,
- 0x6f, 0x3b, 0x75, 0x41, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x6e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe3, 0x6e, 0x00, 0x73, 0x0c,
- 0x7a, 0x15, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x56, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40,
- 0x3a, 0x65, 0x00, 0x40, 0x00, 0x72, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x64, 0x15, 0x65, 0x20, 0x6e, 0x2b,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x7e, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x02, 0xbe, 0x41, 0x52, 0x72, 0x00, 0x40, 0x07, 0x73, 0x74,
- 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6c, 0x00,
- 0xe8, 0x61, 0x00, 0x6d, 0x04, 0x6e, 0x2f, 0x6f, 0x38, 0x72, 0x5a, 0x74,
- 0xa1, 0x75, 0xd0, 0x76, 0xd5, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x21, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x09, 0x69, 0x0d, 0x02, 0xbf, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x07, 0x75, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00,
- 0xf3, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13,
- 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe5,
- 0x65, 0x00, 0x69, 0x04, 0x6f, 0x08, 0x75, 0x1b, 0x79, 0x20, 0x40, 0x95,
- 0x74, 0x00, 0x40, 0x00, 0x63, 0x00, 0xe2, 0x6d, 0x00, 0x75, 0x0a, 0x40,
- 0x00, 0x61, 0x67, 0x6e, 0x65, 0x74, 0x69, 0x63, 0x00, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x09, 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6d,
- 0x08, 0x00, 0x5e, 0x40, 0x06, 0x6f, 0x61, 0x74, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x54, 0xe2,
- 0x74, 0x00, 0x7a, 0x04, 0x40, 0x53, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x64,
- 0x02, 0x72, 0x04, 0x01, 0x4b, 0x00, 0x37, 0x00, 0x07, 0x40, 0x06, 0x6c,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0e, 0x6f, 0x12, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b, 0x40,
- 0x3b, 0x64, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x02,
- 0x02, 0xc0, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x69, 0x0a, 0x6f,
- 0x2a, 0x02, 0xc1, 0x40, 0x00, 0x6c, 0x00, 0x40, 0xec, 0x72, 0x00, 0xe1,
- 0x76, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x11, 0x40, 0x06, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x59, 0x6f, 0x6e, 0x00,
- 0xe7, 0x61, 0x00, 0x63, 0x09, 0x65, 0x1e, 0x69, 0x20, 0x6c, 0x51, 0x74,
- 0x57, 0x75, 0x78, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x4b,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x00, 0x82, 0xe2,
- 0x64, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00,
- 0x40, 0x09, 0x6f, 0x63, 0x6b, 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x0e, 0x75,
- 0x12, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01, 0x3d, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x63, 0x63, 0x69,
- 0x6e, 0x65, 0x00, 0x40, 0x09, 0x73, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x55, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xb1, 0xe1, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0xc2, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x7a, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x00, 0xc0, 0x61, 0x1a, 0x37, 0x00,
- 0x64, 0x00, 0xf2, 0x00, 0x55, 0x01, 0x99, 0x01, 0x2a, 0x02, 0x77, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x02, 0x00, 0x00,
- 0x28, 0x04, 0x96, 0x05, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x05, 0x0d, 0x07,
- 0xec, 0x07, 0x00, 0x00, 0x37, 0x08, 0x00, 0x00, 0x3b, 0x08, 0x00, 0x00,
- 0x7c, 0x08, 0xe3, 0x6e, 0x00, 0x73, 0x13, 0x74, 0x24, 0xe1, 0x63, 0x00,
- 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x04, 0x01, 0x52,
- 0x00, 0x09, 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x00, 0x09, 0xe5,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x15, 0x72, 0x37, 0x75, 0x70, 0x00, 0x23,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00,
- 0x00, 0x62, 0x02, 0x66, 0x09, 0x67, 0x0f, 0x00, 0x07, 0x40, 0x07, 0x6f,
- 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x00, 0x40, 0x07,
- 0x6c, 0x61, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x20, 0xe2, 0x6c,
- 0x00, 0x6e, 0x19, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x69, 0x00, 0x73, 0x04, 0x75,
- 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0x40, 0x00,
- 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x72, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x68, 0x00,
- 0x6b, 0x09, 0x74, 0x1c, 0x75, 0x56, 0xe2, 0x65, 0x00, 0x75, 0x02, 0x00,
- 0x06, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x01, 0x15, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe3, 0x6f, 0x00, 0x74, 0x25, 0x76, 0x2c, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x3b, 0x69,
- 0x6f, 0x75, 0x73, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe4, 0x64, 0x00, 0x65, 0x1d, 0x67, 0x24, 0x75, 0x33, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x13, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x04,
- 0x00, 0x7e, 0x00, 0x07, 0x40, 0x00, 0x74, 0x69, 0x63, 0x6b, 0x73, 0x00,
- 0x00, 0x60, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x93, 0x00, 0x00,
- 0x40, 0x06, 0x63, 0x69, 0x61, 0x72, 0x79, 0x00, 0xe6, 0x00, 0x00, 0x66,
- 0x02, 0x6c, 0x0e, 0x6e, 0x50, 0x72, 0x5f, 0x73, 0x7f, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x09, 0x40, 0x09, 0x6f, 0x6d, 0x00, 0xe1,
- 0x64, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0b, 0x73, 0x10, 0x77,
- 0x20, 0x02, 0xc3, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x53,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x13, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0x40, 0x3b, 0x73, 0x68, 0x00, 0xe3, 0x63, 0x00, 0x69,
- 0x10, 0x79, 0x17, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x7f, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x15, 0x40, 0x06, 0x74, 0x61, 0x00, 0xe2, 0x65, 0x00,
- 0x74, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xeb, 0x00, 0x07, 0xe4,
- 0x65, 0x00, 0x68, 0x19, 0x69, 0x22, 0x79, 0x34, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x01, 0x29, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x12, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x01, 0x58, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x6d, 0x1f, 0x75, 0x25, 0x02,
- 0xc4, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x69,
- 0x0c, 0x01, 0x67, 0x40, 0x00, 0x61, 0x63, 0x6b, 0x00, 0x41, 0x89, 0x72,
- 0x00, 0x40, 0x53, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x13, 0x69, 0x26, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x42, 0xbc, 0x6e,
- 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x68, 0x06,
- 0x02, 0x28, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x65, 0x61, 0x64, 0x00,
- 0x40, 0x09, 0x6e, 0x65, 0x00, 0xf9, 0x61, 0x00, 0x00, 0x62, 0x18, 0x00,
- 0x63, 0x1e, 0x00, 0x65, 0x22, 0x00, 0x69, 0x3d, 0x00, 0x6c, 0x87, 0x00,
- 0x6d, 0xb2, 0x00, 0x6f, 0xe1, 0x00, 0x74, 0xe3, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x09, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x09, 0x65,
- 0x72, 0x74, 0x00, 0x40, 0x3a, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02,
- 0x6e, 0x06, 0x72, 0x0c, 0x74, 0x0e, 0x02, 0xc6, 0x42, 0xc5, 0x73, 0x00,
- 0x40, 0x08, 0x61, 0x6d, 0x65, 0x00, 0x01, 0x82, 0x00, 0x00, 0xe4, 0x61,
- 0x00, 0x62, 0x04, 0x67, 0x1e, 0x6e, 0x33, 0x40, 0x00, 0x6c, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x1a, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x27, 0x00, 0x73, 0x04, 0x40, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0xe5, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x69, 0x13, 0x79, 0x1e, 0x02,
- 0xc7, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x74, 0x04,
- 0x00, 0x37, 0x00, 0x09, 0x00, 0x55, 0xe2, 0x6e, 0x00, 0x70, 0x04, 0x40,
- 0x06, 0x67, 0x00, 0x00, 0x55, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x69, 0x02,
- 0x6d, 0x09, 0x6f, 0x10, 0x73, 0x19, 0x79, 0x20, 0x00, 0x55, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x6b, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x00, 0x40, 0x09, 0x74,
- 0x72, 0x69, 0x70, 0x00, 0x01, 0x92, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x68,
- 0x13, 0x72, 0x2d, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02,
- 0xc8, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2,
- 0x00, 0x00, 0x27, 0x02, 0x02, 0xc9, 0x40, 0x00, 0x73, 0x00, 0x40, 0x53,
- 0x6f, 0x6e, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x6e,
- 0x00, 0x64, 0x72, 0x00, 0x65, 0x8e, 0x00, 0x67, 0xbd, 0x00, 0x69, 0x00,
- 0x01, 0x6b, 0x45, 0x01, 0x6e, 0x47, 0x01, 0x00, 0x2b, 0xe3, 0x67, 0x00,
- 0x6c, 0x0f, 0x6e, 0x37, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x04, 0x00, 0x56, 0x00, 0x09, 0xe3, 0x73, 0x00, 0x74, 0x04, 0x7a,
- 0x08, 0x40, 0x06, 0x74, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1,
- 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x00, 0x00, 0x27, 0x02,
- 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0c, 0x6e,
- 0x10, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x3b, 0x00,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x67, 0x00, 0x40, 0x09, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x02, 0xca, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x6c, 0x06,
- 0x6e, 0x0a, 0x72, 0x10, 0x73, 0x14, 0x02, 0xcc, 0x42, 0xcb, 0x73, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x75,
- 0x79, 0x00, 0xe2, 0x70, 0x00, 0x73, 0x05, 0x40, 0x00, 0x75, 0x6e, 0x00,
- 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe8, 0x00,
- 0x00, 0x62, 0x02, 0x69, 0x09, 0x6c, 0x0e, 0x6d, 0x14, 0x6e, 0x1a, 0x70,
- 0x20, 0x74, 0x27, 0x01, 0x6b, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x08, 0x61, 0x72, 0x6b, 0x00, 0x40, 0x06, 0x61, 0x69, 0x6c, 0x00, 0x40,
- 0x93, 0x72, 0x69, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x69, 0x70, 0x00, 0xe4,
- 0x61, 0x00, 0x63, 0x04, 0x73, 0x1b, 0x74, 0x38, 0x40, 0x09, 0x6c, 0x00,
- 0xe2, 0x61, 0x00, 0x6b, 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe2,
- 0x00, 0x00, 0x68, 0x02, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x65,
- 0x06, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x37, 0x00, 0x09, 0x40, 0x5c, 0x65, 0x00, 0x00, 0x55, 0xe2, 0x65,
- 0x00, 0x79, 0x04, 0x40, 0x00, 0x64, 0x00, 0x00, 0x00, 0x40, 0x09, 0x72,
- 0x69, 0x63, 0x65, 0x74, 0x00, 0xf5, 0x00, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x6d, 0x1d, 0x01, 0x73, 0x3b, 0x01, 0x74, 0x53, 0x01, 0x02, 0xcd, 0xef,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x07, 0x63, 0x3a, 0x64, 0x43, 0x66, 0x49,
- 0x67, 0x6d, 0x68, 0x74, 0x6c, 0x7b, 0x6d, 0x82, 0x70, 0x8f, 0x72, 0xb0,
- 0x73, 0xb2, 0x74, 0xcb, 0x77, 0xdc, 0x00, 0x09, 0x40, 0x06, 0x72, 0x6d,
- 0x00, 0xe4, 0x61, 0x00, 0x6f, 0x05, 0x72, 0x10, 0x75, 0x26, 0x40, 0x09,
- 0x6c, 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x78, 0x04, 0x42, 0xce, 0x62, 0x00,
- 0x00, 0x09, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0a, 0x40, 0x06, 0x6e,
- 0x64, 0x00, 0x40, 0x06, 0x61, 0x6b, 0x00, 0x40, 0x06, 0x63, 0x6b, 0x00,
- 0x40, 0x06, 0x67, 0x00, 0x40, 0x06, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x61, 0x6d, 0x70, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x1b,
- 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x02, 0x17, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x08, 0x75, 0x61, 0x72,
- 0x64, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x27, 0x69,
- 0x67, 0x68, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x6c, 0x00, 0x6f, 0x0e, 0x72, 0x14,
- 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40, 0x06, 0x63, 0x65, 0x00, 0x40, 0x09,
- 0x67, 0x00, 0x40, 0x07, 0x77, 0x65, 0x72, 0x00, 0x40, 0x3a, 0x6f, 0x6f,
- 0x66, 0x00, 0x00, 0x07, 0xe3, 0x63, 0x00, 0x69, 0x07, 0x74, 0x0c, 0x40,
- 0x08, 0x72, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x09, 0x64, 0x65, 0x00, 0x40,
- 0x09, 0x6f, 0x72, 0x6d, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x75,
- 0x04, 0x40, 0x09, 0x70, 0x00, 0x40, 0x09, 0x63, 0x6b, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x0e, 0xe2, 0x6c, 0x00, 0x74, 0x04, 0x40, 0x09, 0x6c, 0x00,
- 0x40, 0x07, 0x65, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x04, 0x40, 0x07,
- 0x64, 0x00, 0x40, 0x06, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6e,
- 0x09, 0x77, 0x0f, 0x02, 0xcf, 0x40, 0x06, 0x6d, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x68, 0x08, 0x00, 0x56,
- 0x40, 0x06, 0x6f, 0x72, 0x6e, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x64, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe4, 0x63, 0x00, 0x68, 0x05, 0x73, 0x8e, 0x74, 0xa5, 0x40, 0x86, 0x61,
- 0x6c, 0x00, 0xec, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x65, 0x0e, 0x68,
- 0x29, 0x69, 0x2f, 0x6d, 0x44, 0x6e, 0x4c, 0x70, 0x51, 0x74, 0x57, 0x77,
- 0x5d, 0x79, 0x6e, 0x00, 0xe7, 0x40, 0x06, 0x6f, 0x77, 0x6c, 0x00, 0x40,
- 0x06, 0x61, 0x6b, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x6d,
- 0x02, 0x79, 0x0f, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x6f,
- 0x6b, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0x40,
- 0x09, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00,
- 0x40, 0x09, 0x6f, 0x6e, 0x64, 0x00, 0x40, 0x72, 0x61, 0x69, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0x01, 0x3b, 0xe2, 0x69, 0x00, 0x75, 0x0d,
- 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0xd4, 0x6e,
- 0x00, 0x40, 0x06, 0x72, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x69,
- 0x11, 0x75, 0x19, 0x00, 0x09, 0xe2, 0x69, 0x00, 0x75, 0x06, 0x40, 0x09,
- 0x67, 0x68, 0x74, 0x00, 0x40, 0x06, 0x6c, 0x00, 0x40, 0x07, 0x63, 0x75,
- 0x66, 0x66, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x75, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x66, 0x02,
- 0x6c, 0x15, 0x6d, 0x19, 0x6e, 0x1f, 0x74, 0x25, 0x02, 0xd0, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x08, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0f, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x01, 0x84, 0x00,
- 0x09, 0x40, 0x00, 0x74, 0x00, 0x40, 0x56, 0x6e, 0x67, 0x00, 0x40, 0xeb,
- 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x19, 0x69, 0x22, 0x74,
- 0x30, 0x02, 0xd1, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01,
- 0xc8, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x3b, 0x00, 0x07, 0xe2,
- 0x6e, 0x00, 0x74, 0x05, 0x40, 0x07, 0x67, 0x73, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x09, 0x75, 0x72, 0x65, 0x00, 0xe1, 0x7a, 0x00, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x79, 0x06, 0x00, 0x47, 0x40, 0x5e, 0x65, 0x00, 0x00,
- 0xf3, 0x40, 0x06, 0x6f, 0x72, 0x64, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x65, 0x8d, 0x03, 0x69, 0x6f, 0x04, 0x6f, 0xb9, 0x05, 0x74,
- 0x8c, 0x07, 0x75, 0x8e, 0x07, 0x79, 0xff, 0x08, 0x02, 0xd2, 0xc0, 0x62,
- 0x18, 0x33, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73,
- 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x21,
- 0x01, 0x9d, 0x01, 0x00, 0x00, 0xca, 0x01, 0x00, 0x00, 0xec, 0x01, 0xfa,
- 0x01, 0x59, 0x02, 0x29, 0x03, 0x3b, 0x03, 0x6a, 0x03, 0x87, 0x03, 0x89,
- 0x03, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69,
- 0x08, 0x79, 0x17, 0x40, 0x5b, 0x72, 0x67, 0x61, 0x73, 0x74, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x15, 0xe2, 0x63, 0x00, 0x6b, 0x12, 0xe1, 0x69, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x65, 0x02, 0x67, 0x2a,
- 0x6d, 0x38, 0x6f, 0x45, 0x70, 0x49, 0x72, 0x4f, 0x73, 0x65, 0x00, 0x09,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x19, 0xe3,
- 0x00, 0x00, 0x6e, 0x02, 0x74, 0x06, 0x00, 0x00, 0x40, 0x08, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x37, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x00, 0x40,
- 0x06, 0x6f, 0x6c, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x3b, 0xe2, 0x68, 0x00, 0x74, 0x05, 0x40, 0x06, 0x69, 0x70,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x66, 0x66, 0x00, 0x40,
- 0x09, 0x6e, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x93, 0x00,
- 0x06, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x79, 0x0b, 0x00, 0x07,
- 0x00, 0x5e, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x3b, 0xe5,
- 0x61, 0x00, 0x62, 0x05, 0x65, 0x35, 0x69, 0x55, 0x6d, 0x5b, 0x40, 0x00,
- 0x67, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x12, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x00, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0x00, 0x3b, 0xe4, 0x00, 0x00, 0x6e, 0x02, 0x70, 0x07, 0x74, 0x0e,
- 0x02, 0xd3, 0x40, 0x09, 0x63, 0x6f, 0x00, 0x40, 0x72, 0x72, 0x6f, 0x6f,
- 0x66, 0x00, 0x40, 0x06, 0x68, 0x72, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x6e, 0x67, 0x6f, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6b, 0x06, 0x6e, 0x11,
- 0x00, 0x09, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xfa, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x93, 0x40, 0x07, 0x74, 0x74, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x6a, 0x02, 0x70, 0x08, 0x00, 0x09, 0x40, 0x09, 0x61,
- 0x63, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x5e, 0x40, 0x06, 0x70, 0x00,
- 0xe2, 0x68, 0x00, 0x6b, 0x58, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x11,
- 0x65, 0x20, 0x67, 0x24, 0x69, 0x29, 0x6c, 0x3e, 0x79, 0x45, 0x02, 0xd4,
- 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40, 0x06, 0x63, 0x6b, 0x00, 0x40, 0x06,
- 0x6c, 0x62, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40, 0x06, 0x72, 0x64,
- 0x00, 0x40, 0x06, 0x62, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06,
- 0x75, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07,
- 0x40, 0x09, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00, 0xf4, 0x00, 0x06, 0xeb,
- 0x00, 0x00, 0x62, 0x02, 0x63, 0x18, 0x66, 0x1d, 0x69, 0x33, 0x6c, 0x39,
- 0x6d, 0x47, 0x6e, 0x4d, 0x74, 0x53, 0x75, 0x92, 0x77, 0xaa, 0x00, 0x44,
- 0xe3, 0x65, 0x00, 0x6f, 0x04, 0x72, 0x09, 0x40, 0x06, 0x64, 0x00, 0x40,
- 0x06, 0x61, 0x74, 0x00, 0x40, 0x00, 0x65, 0x61, 0x64, 0x00, 0x40, 0x06,
- 0x61, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x6f, 0x0a, 0x40, 0x00,
- 0x65, 0x74, 0x00, 0x40, 0x09, 0x73, 0x68, 0x00, 0x40, 0xb1, 0x6f, 0x74,
- 0x00, 0x40, 0x06, 0x72, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05,
- 0x40, 0x07, 0x6e, 0x64, 0x00, 0x40, 0x08, 0x74, 0x00, 0x40, 0x08, 0x61,
- 0x74, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x27, 0x6f, 0x34, 0xe4, 0x64, 0x00, 0x6e, 0x02, 0x72, 0x04, 0x73,
- 0x1a, 0x00, 0x00, 0x00, 0x7a, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x79, 0x0b, 0x00, 0xd6, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67,
- 0x00, 0x00, 0x07, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04,
- 0x40, 0x00, 0x67, 0x00, 0x40, 0x00, 0x68, 0x00, 0x40, 0x06, 0x70, 0x00,
- 0xe2, 0x6c, 0x00, 0x73, 0x11, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x06,
- 0x72, 0x6d, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x47, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x66, 0x06, 0x69, 0x0b,
- 0x6c, 0x10, 0x73, 0x16, 0x01, 0x6d, 0x40, 0x37, 0x64, 0x00, 0x40, 0x00,
- 0x75, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x55, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x14, 0x00, 0x72, 0xe7, 0x61, 0x00, 0x63, 0x1c, 0x64, 0x20,
- 0x65, 0x32, 0x73, 0x7f, 0x77, 0x98, 0x78, 0x9a, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x70, 0x10, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x06,
- 0x67, 0x00, 0x40, 0x08, 0x74, 0x65, 0x00, 0x40, 0x08, 0x69, 0x74, 0x00,
- 0x40, 0x93, 0x6b, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x04,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x67, 0x00, 0xe4, 0x00,
- 0x00, 0x63, 0x02, 0x69, 0x1b, 0x74, 0x20, 0x00, 0x08, 0xe3, 0x65, 0x00,
- 0x69, 0x09, 0x79, 0x10, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x17, 0x02, 0xd5,
- 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x70,
- 0x06, 0x79, 0x0b, 0x02, 0xd6, 0x40, 0x60, 0x79, 0x00, 0x40, 0x09, 0x6f,
- 0x74, 0x00, 0x00, 0xf3, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x74, 0x2a, 0x00, 0x69, 0x40, 0x00, 0x64, 0x00, 0xe3, 0x62, 0x00,
- 0x6e, 0x15, 0x6f, 0x19, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00,
- 0x54, 0x40, 0x00, 0x67, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x69,
- 0x6d, 0x65, 0x00, 0xf9, 0x62, 0x00, 0x00, 0x63, 0x0e, 0x00, 0x65, 0x1c,
- 0x00, 0x67, 0x20, 0x00, 0x6d, 0x40, 0x00, 0x6e, 0x79, 0x00, 0x70, 0x97,
- 0x00, 0x72, 0xeb, 0x00, 0x74, 0x19, 0x01, 0x40, 0x06, 0x62, 0x65, 0x72,
- 0x74, 0x69, 0x67, 0x69, 0x62, 0x62, 0x65, 0x74, 0x00, 0xe1, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfa, 0x40, 0xec, 0x72, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00,
- 0x69, 0x02, 0x6c, 0x09, 0x79, 0x0f, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe2,
- 0x66, 0x00, 0x73, 0x1e, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x3b, 0xe3, 0x63, 0x00, 0x67,
- 0x04, 0x74, 0x06, 0x40, 0x59, 0x68, 0x00, 0x00, 0x2a, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x79, 0x08, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x63, 0x6b, 0x00,
- 0x00, 0x60, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x70, 0x20, 0x00, 0x09, 0xe1,
- 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0e, 0x69, 0x1d,
- 0x79, 0x22, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x3b, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00,
- 0x00, 0x00, 0x09, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x00, 0x08, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x79, 0x22,
- 0x00, 0x93, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x6e, 0x00, 0x75, 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xfb, 0x61, 0x00,
- 0x00, 0x63, 0x0e, 0x00, 0x65, 0x1d, 0x00, 0x67, 0x1f, 0x00, 0x6f, 0x39,
- 0x00, 0x70, 0x93, 0x00, 0x72, 0xc5, 0x00, 0x73, 0x0a, 0x01, 0x74, 0x16,
- 0x01, 0x75, 0x2f, 0x01, 0x77, 0x64, 0x01, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x00, 0x09, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40,
- 0x09, 0x6e, 0x67, 0x00, 0xe3, 0x64, 0x00, 0x72, 0x30, 0x7a, 0x4f, 0xe5,
- 0x00, 0x00, 0x67, 0x02, 0x6c, 0x08, 0x70, 0x17, 0x77, 0x1e, 0x02, 0xd7,
- 0x40, 0x09, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x67, 0x00,
- 0x74, 0x05, 0x40, 0x47, 0x68, 0x74, 0x00, 0x00, 0x00, 0x40, 0x09, 0x6c,
- 0x61, 0x69, 0x6e, 0x00, 0x40, 0x09, 0x61, 0x74, 0x65, 0x72, 0x00, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x69, 0x09, 0x77, 0x0e, 0x00, 0x2c, 0x40, 0x09,
- 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x61, 0x6c, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe3, 0x00,
- 0x00, 0x68, 0x02, 0x70, 0x09, 0x00, 0x09, 0x40, 0x09, 0x6f, 0x75, 0x73,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x19, 0x40, 0x00, 0x64,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x02, 0x13,
- 0xe3, 0x61, 0x00, 0x65, 0x09, 0x69, 0x24, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x06, 0x00, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x14, 0xe1, 0x63, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x53, 0x65, 0x00, 0x00, 0x54, 0x00, 0x06, 0xe3, 0x64, 0x00, 0x6e, 0x0d,
- 0x73, 0x0f, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x06, 0x40, 0x06, 0x74, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x47, 0x00, 0xf3, 0xe3, 0x61, 0x00,
- 0x69, 0x07, 0x73, 0x0d, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40,
- 0x09, 0x6c, 0x6c, 0x61, 0x00, 0x40, 0x07, 0x61, 0x6d, 0x00, 0xe3, 0x6e,
- 0x00, 0x72, 0x13, 0x74, 0x23, 0xe2, 0x63, 0x00, 0x64, 0x09, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x5e, 0x00, 0x00, 0x40, 0x47, 0x65, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x07, 0x00, 0x2c, 0x40, 0x59, 0x73,
- 0x68, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40,
- 0x07, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x65, 0x09, 0x6e, 0x42,
- 0x00, 0x55, 0x40, 0x06, 0x68, 0x61, 0x72, 0x74, 0x00, 0xe1, 0x72, 0x00,
- 0xe7, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x69, 0x0b, 0x6c, 0x1a, 0x70,
- 0x20, 0x79, 0x25, 0x02, 0xd8, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x65,
- 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07,
- 0x73, 0x73, 0x00, 0x00, 0x08, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x6f, 0x74, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x63, 0x17, 0x00, 0x65, 0x2f, 0x00, 0x66,
- 0x41, 0x00, 0x69, 0x56, 0x00, 0x6b, 0x65, 0x00, 0x6d, 0x6e, 0x00, 0x6e,
- 0x7a, 0x00, 0x6f, 0x8a, 0x00, 0x72, 0xf5, 0x00, 0x73, 0xfa, 0x00, 0x74,
- 0x06, 0x01, 0x76, 0x2b, 0x01, 0x78, 0x31, 0x01, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x39, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x09, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00,
- 0x3b, 0xe1, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00,
- 0x2c, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0xf3, 0xe2, 0x65,
- 0x00, 0x6d, 0x02, 0x00, 0x06, 0x40, 0x3a, 0x6f, 0x78, 0x00, 0xe2, 0x67,
- 0x00, 0x6b, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2c,
- 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x1b, 0x6f, 0x40,
- 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3a, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x00, 0xe3, 0x64, 0x00, 0x6e, 0x16, 0x74, 0x1a, 0xe2, 0x61,
- 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x08, 0x40, 0x09, 0x61,
- 0x72, 0x62, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63,
- 0x00, 0x40, 0xa1, 0x72, 0x79, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x02, 0x02,
- 0xd9, 0x40, 0x47, 0x65, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x74,
- 0x0f, 0x00, 0x5e, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07, 0x67, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x47, 0x00, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x89, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xec, 0x00, 0x00, 0x61, 0x02,
- 0x62, 0x08, 0x63, 0x1c, 0x65, 0x25, 0x69, 0x29, 0x6c, 0x2e, 0x6f, 0x40,
- 0x70, 0x46, 0x73, 0x57, 0x74, 0x72, 0x77, 0x78, 0x02, 0xda, 0x40, 0x00,
- 0x77, 0x61, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x79, 0x06, 0x40, 0x00, 0x6f,
- 0x77, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x09, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00, 0x07, 0x40, 0x00, 0x65, 0x73, 0x00,
- 0x40, 0x09, 0x76, 0x65, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x70, 0x00,
- 0x73, 0x05, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x08, 0x74, 0x00, 0xe3,
- 0x68, 0x00, 0x70, 0x06, 0x77, 0x0c, 0x40, 0x08, 0x65, 0x65, 0x74, 0x00,
- 0x40, 0x59, 0x65, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x61, 0x74, 0x74, 0x65,
- 0x72, 0x00, 0x40, 0x08, 0x72, 0x61, 0x70, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x04, 0x68, 0x0b, 0x40, 0x06, 0x79, 0x00, 0x40, 0x06, 0x69, 0x67, 0x68,
- 0x74, 0x00, 0x40, 0x09, 0x65, 0x65, 0x6c, 0x00, 0xc0, 0x61, 0x19, 0x35,
- 0x00, 0x4e, 0x00, 0x63, 0x00, 0x80, 0x00, 0x86, 0x00, 0x00, 0x00, 0x88,
- 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0xa5,
- 0x01, 0xbc, 0x01, 0xee, 0x01, 0x76, 0x03, 0x00, 0x00, 0x9a, 0x03, 0x39,
- 0x0a, 0x00, 0x00, 0x65, 0x0a, 0x00, 0x00, 0x33, 0x0b, 0x37, 0x0b, 0x9c,
- 0x0b, 0xe2, 0x6c, 0x00, 0x6d, 0x02, 0x00, 0x55, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x09, 0x00, 0x55, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0xf4, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x06, 0x64, 0x65, 0x72, 0x00, 0x00, 0x06,
- 0xe6, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x67, 0x0d, 0x68, 0x2f, 0x79,
- 0x35, 0x00, 0xaa, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x75, 0x6e,
- 0x64, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x19, 0x41, 0x63, 0x64,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x01, 0x63, 0x00, 0xf4,
- 0x40, 0x09, 0x6f, 0x72, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe3, 0x62, 0x00, 0x6c, 0x05, 0x73,
- 0x07, 0x40, 0x06, 0x6c, 0x65, 0x00, 0x00, 0x55, 0x40, 0x7a, 0x74, 0x00,
- 0xe5, 0x00, 0x00, 0x64, 0x02, 0x69, 0x22, 0x6b, 0x32, 0x6c, 0x84, 0x00,
- 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x0c, 0x6f, 0x10,
- 0x02, 0xdb, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x77, 0x61, 0x79, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x75, 0x74, 0x00, 0xe3, 0x61, 0x00,
- 0x63, 0x05, 0x6f, 0x07, 0x40, 0x07, 0x67, 0x65, 0x00, 0x00, 0x00, 0x00,
- 0x06, 0xe5, 0x00, 0x00, 0x6c, 0x02, 0x73, 0x1a, 0x74, 0x3c, 0x77, 0x42,
- 0x00, 0x09, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x09,
- 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1b, 0xe1, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x96,
- 0x40, 0x09, 0x61, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0xe4,
- 0x00, 0x00, 0x69, 0x02, 0x6f, 0x08, 0x79, 0x23, 0x00, 0x00, 0x40, 0x09,
- 0x63, 0x6c, 0x65, 0x00, 0xe1, 0x77, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x75, 0x0b, 0x01, 0x42, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x08, 0x70, 0x00, 0x00, 0x06, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x5b, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x74,
- 0x20, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x07, 0x6e, 0x0b, 0x75, 0x11,
- 0x01, 0xb4, 0x40, 0x09, 0x6e, 0x74, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x09, 0x40, 0x09, 0x6e, 0x65, 0x6c, 0x00, 0xf5, 0x00,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x64, 0x07, 0x00, 0x6c, 0x1b, 0x00, 0x74,
- 0x6e, 0x00, 0x00, 0x00, 0x40, 0x00, 0x61, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x73, 0x06, 0x00, 0x09, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06,
- 0x74, 0x75, 0x66, 0x66, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x68, 0x07,
- 0x69, 0x26, 0x70, 0x39, 0x73, 0x40, 0x00, 0x55, 0x40, 0x06, 0x72, 0x79,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe1, 0x73, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0x40, 0x07,
- 0x63, 0x61, 0x70, 0x00, 0xee, 0x00, 0x00, 0x61, 0x02, 0x62, 0x07, 0x66,
- 0x24, 0x68, 0x2a, 0x69, 0x39, 0x6c, 0x44, 0x6d, 0x6f, 0x6e, 0x7c, 0x70,
- 0x82, 0x72, 0xa4, 0x73, 0xb3, 0x77, 0xdc, 0x79, 0xeb, 0x02, 0xb5, 0x40,
- 0x07, 0x67, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x11, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0xdc, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x06, 0x69, 0x64, 0x67, 0x65, 0x00, 0x40, 0x09, 0x61,
- 0x6c, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6c, 0x6c,
- 0x00, 0x40, 0x09, 0x6c, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x6f, 0x14,
- 0x40, 0x00, 0x73, 0x73, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x06, 0x40, 0x07,
- 0x68, 0x74, 0x73, 0x00, 0x40, 0x09, 0x67, 0x00, 0xe2, 0x63, 0x00, 0x6f,
- 0x06, 0x40, 0x06, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x00, 0x73, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0x40, 0x82, 0x6f, 0x74, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x0f,
- 0x72, 0x15, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x08, 0x61, 0x74, 0x65, 0x00, 0x40,
- 0x06, 0x69, 0x6e, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x09,
- 0x63, 0x65, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe4, 0x69, 0x00, 0x6c,
- 0x04, 0x6f, 0x0d, 0x74, 0x12, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x6f,
- 0x67, 0x67, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x72, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x70, 0x00, 0x40, 0x06, 0x6f, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x61, 0x72, 0x00, 0x40,
- 0x07, 0x72, 0x6b, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00,
- 0x06, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x07, 0x72, 0x79, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xc1, 0x61, 0x17, 0x33, 0x00, 0x35,
- 0x00, 0x4c, 0x00, 0x93, 0x00, 0xcb, 0x00, 0xcd, 0x00, 0x6d, 0x03, 0x82,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x04, 0x42, 0x04, 0x48,
- 0x04, 0x39, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
- 0x05, 0x9a, 0x05, 0x78, 0x06, 0x00, 0x00, 0x7c, 0x06, 0x02, 0xdd, 0xe3,
- 0x00, 0x00, 0x67, 0x02, 0x79, 0x0e, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x2c, 0xe4, 0x61,
- 0x00, 0x65, 0x05, 0x69, 0x18, 0x6f, 0x30, 0x40, 0x00, 0x64, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x01,
- 0x25, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x6e, 0x00, 0x42, 0xde, 0x6e, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65,
- 0x00, 0x6e, 0x02, 0x00, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x24, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x66, 0x04, 0x70, 0x17, 0x00,
- 0x5e, 0x00, 0x37, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0xdf, 0xc1, 0x61, 0x17, 0x33, 0x00,
- 0x35, 0x00, 0x3a, 0x00, 0x53, 0x00, 0x89, 0x00, 0x00, 0x00, 0x8f, 0x00,
- 0xb8, 0x00, 0xd5, 0x00, 0xe4, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x1e, 0x01,
- 0x33, 0x01, 0x4e, 0x01, 0x76, 0x01, 0x7e, 0x01, 0x96, 0x01, 0x9f, 0x01,
- 0xa7, 0x01, 0x45, 0x02, 0x00, 0x00, 0x66, 0x02, 0x79, 0x02, 0x00, 0x09,
- 0x40, 0x95, 0x72, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09,
- 0x61, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02,
- 0xe0, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x17, 0x6f,
- 0x29, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x6c, 0x06, 0x02, 0xdc, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x65, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x02, 0x00,
- 0x3a, 0x40, 0x09, 0x72, 0x65, 0x00, 0x40, 0x06, 0x75, 0x72, 0x74, 0x00,
- 0x40, 0x72, 0x6f, 0x6f, 0x6d, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x07, 0x69,
- 0x0c, 0x6f, 0x13, 0x72, 0x18, 0x40, 0x09, 0x74, 0x68, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x65, 0x74, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x6f, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x74, 0x00, 0xe2,
- 0x6f, 0x00, 0x72, 0x11, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x00,
- 0x1c, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x59, 0x6f,
- 0x75, 0x6e, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x09, 0x6e,
- 0x64, 0x00, 0x40, 0x09, 0x61, 0x64, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x02, 0xe1, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x77, 0x00, 0xe1, 0x77, 0x00, 0xe3,
- 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x09, 0x00, 0x3c, 0x40, 0x07, 0x65, 0x64,
- 0x67, 0x65, 0x00, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x09,
- 0x40, 0x06, 0x67, 0x00, 0x40, 0x09, 0x6d, 0x62, 0x00, 0x40, 0x09, 0x63,
- 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0b, 0x6f, 0x0f, 0xe2, 0x6e, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x40, 0x09, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x00, 0x73, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x05, 0x73, 0x0a,
- 0x40, 0xb2, 0x6d, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00,
- 0x09, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x40, 0xad, 0x72,
- 0x64, 0x61, 0x69, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6c, 0x0c,
- 0x40, 0x09, 0x72, 0x74, 0x00, 0x40, 0x06, 0x72, 0x73, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x79, 0x00, 0x40, 0x09, 0x75, 0x61, 0x72, 0x74, 0x65,
- 0x72, 0x00, 0x40, 0x09, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x00, 0xe6, 0x61,
- 0x00, 0x65, 0x0b, 0x68, 0x2a, 0x69, 0x44, 0x6b, 0x5c, 0x74, 0x61, 0xe2,
- 0x69, 0x00, 0x77, 0x04, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x00, 0xe1, 0x65,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x6e, 0x0d, 0x72, 0x0f,
- 0x02, 0xe2, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x00, 0x37, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40, 0x0b,
- 0x64, 0x6f, 0x77, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02,
- 0x00, 0x08, 0x40, 0x3a, 0x65, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x20, 0x40,
- 0x07, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x00,
- 0xe6, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x15, 0x6c, 0x19, 0x72,
- 0x1f, 0x02, 0xe3, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x04,
- 0x40, 0x5b, 0x6c, 0x00, 0x41, 0xbc, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x79, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x06, 0x68, 0x0b, 0x6f, 0x13, 0x40, 0x5e, 0x73,
- 0x74, 0x65, 0x00, 0x40, 0x3c, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6f, 0x75,
- 0x67, 0x68, 0x74, 0x00, 0x40, 0x00, 0x6c, 0x64, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x6f, 0x72, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6f, 0x0a, 0x40,
- 0x3a, 0x72, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x74, 0x00, 0xe2, 0x6d, 0x00,
- 0x72, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x09, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x95, 0x40,
- 0x06, 0x72, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x4d, 0x6f,
- 0x7f, 0xe2, 0x74, 0x00, 0x76, 0x06, 0x40, 0x7a, 0x68, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x0b, 0x02,
- 0xe4, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe3, 0x00,
- 0x00, 0x66, 0x02, 0x74, 0x15, 0x00, 0x08, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x37, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x6e, 0x00, 0x76, 0x04, 0x40,
- 0x07, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x1d, 0x40, 0x37,
- 0x62, 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x0e, 0x02,
- 0xe5, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x73,
- 0x00, 0x00, 0x07, 0x40, 0x37, 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x6e, 0x0b, 0x74, 0x0f, 0x02, 0xe6, 0xe2, 0x72, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x00, 0x40, 0x37, 0x65, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x66,
- 0x02, 0x6c, 0x07, 0x00, 0x55, 0x40, 0x06, 0x75, 0x6c, 0x00, 0x40, 0x09,
- 0x69, 0x66, 0x74, 0x00, 0x40, 0x3b, 0x6f, 0x72, 0x6e, 0x00, 0xe8, 0x00,
- 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x6a, 0x66, 0x7c, 0x69, 0x85, 0x6c,
- 0x9e, 0x75, 0xb4, 0x02, 0xe7, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x74, 0x41, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x69,
- 0x0a, 0x00, 0x56, 0x40, 0x07, 0x65, 0x68, 0x79, 0x64, 0x65, 0x00, 0xe4,
- 0x6e, 0x00, 0x73, 0x02, 0x74, 0x0b, 0x7a, 0x17, 0x00, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x69, 0x00, 0x79, 0x05,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x53, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x74, 0x07, 0x00, 0x98, 0x42, 0xe8, 0x6f, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x77, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x02, 0xe9, 0x40, 0x00, 0x79, 0x00, 0x40, 0x00, 0x69, 0x74, 0x74,
- 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00, 0x64, 0x02, 0x00, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x74, 0x06, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x09, 0x6f, 0x0e, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x02, 0xea,
- 0x00, 0x37, 0x40, 0x75, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x6f, 0x0f, 0x77, 0x1d,
- 0x79, 0x33, 0xe1, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3c, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6b, 0x00, 0x74,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05,
- 0x41, 0x21, 0x61, 0x72, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6e,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x74, 0x68, 0x69, 0x61, 0x00,
- 0xe8, 0x00, 0x00, 0x65, 0x02, 0x68, 0x04, 0x69, 0x32, 0x6e, 0x74, 0x72,
- 0x7b, 0x75, 0x81, 0x79, 0xcb, 0x00, 0x09, 0x00, 0x06, 0xe3, 0x63, 0x00,
- 0x72, 0x08, 0x77, 0x21, 0x40, 0x07, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x69, 0x74, 0x68, 0x00, 0xe4, 0x65, 0x00, 0x66, 0x0f,
- 0x73, 0x2c, 0x74, 0x33, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x16,
- 0xe2, 0x63, 0x00, 0x65, 0x08, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0x02, 0xeb,
- 0x40, 0x00, 0x73, 0x69, 0x6d, 0x6f, 0x00, 0x40, 0x07, 0x75, 0x64, 0x65,
- 0x00, 0x40, 0x86, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x09, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6e, 0x1d, 0xe1, 0x74, 0x00, 0xe2, 0x6f,
- 0x00, 0x79, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x36, 0x74, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x01, 0x58, 0x40, 0x06, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x19, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6e, 0x06, 0x02, 0xec, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6e, 0x74, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x22, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x7a, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b,
- 0x40, 0xad, 0x65, 0x72, 0x00, 0xe4, 0x67, 0x00, 0x6c, 0x05, 0x6e, 0x24,
- 0x72, 0x6a, 0x40, 0x00, 0x68, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x6d, 0x07, 0x6e, 0x10, 0x02, 0xed, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40,
- 0x00, 0x6f, 0x75, 0x74, 0x68, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x27, 0xe5, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x09, 0x6c, 0x12, 0x72, 0x18, 0x02, 0xee, 0x40, 0x06, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x59,
- 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x68, 0x02, 0x00, 0x06, 0x40, 0x09, 0x65, 0x61, 0x64, 0x00,
- 0xe5, 0x00, 0x00, 0x66, 0x02, 0x70, 0x08, 0x73, 0x10, 0x74, 0x29, 0x01,
- 0x29, 0x40, 0x00, 0x6f, 0x6c, 0x64, 0x00, 0x40, 0x06, 0x6f, 0x73, 0x74,
- 0x65, 0x72, 0x00, 0xe3, 0x63, 0x00, 0x6f, 0x06, 0x71, 0x0b, 0x40, 0x07,
- 0x6f, 0x72, 0x65, 0x00, 0x40, 0x06, 0x6d, 0x65, 0x00, 0x40, 0x00, 0x75,
- 0x61, 0x72, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x19, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x01, 0x58, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x12, 0x00, 0x00, 0x40, 0x55, 0x6c, 0x00, 0xe7,
- 0x00, 0x00, 0x66, 0x02, 0x67, 0x08, 0x68, 0x0f, 0x69, 0x27, 0x74, 0x36,
- 0x79, 0x54, 0x00, 0x59, 0x40, 0x07, 0x69, 0x72, 0x65, 0x00, 0x40, 0x06,
- 0x6c, 0x6f, 0x76, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x0e, 0xe2, 0x6c,
- 0x00, 0x75, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x06, 0x6e, 0x64, 0x00,
- 0x40, 0x3c, 0x6e, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x00, 0xf4, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x00, 0x73,
- 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0xf7, 0x01, 0x69,
- 0x76, 0x04, 0x6f, 0x2a, 0x06, 0x75, 0xc4, 0x07, 0x79, 0x86, 0x08, 0x00,
- 0x00, 0xfa, 0x63, 0x00, 0x00, 0x67, 0x40, 0x00, 0x69, 0x8a, 0x00, 0x6d,
- 0xa0, 0x00, 0x6e, 0xb8, 0x00, 0x70, 0x40, 0x01, 0x74, 0x45, 0x01, 0x75,
- 0x92, 0x01, 0x79, 0xc5, 0x01, 0x7a, 0xd0, 0x01, 0xe3, 0x61, 0x00, 0x6b,
- 0x04, 0x74, 0x06, 0x40, 0x09, 0x73, 0x00, 0x00, 0x7a, 0xe3, 0x61, 0x00,
- 0x69, 0x04, 0x75, 0x27, 0x40, 0x06, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x6e, 0x00, 0x75, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x01, 0xa7, 0x40,
- 0x3b, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x82, 0x72, 0x65, 0x00,
- 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x11, 0x72, 0x30, 0x00, 0x08, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0xf3, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x59, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65, 0x00,
- 0x00, 0x3b, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x08,
- 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00,
- 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x77, 0x06,
- 0x00, 0x7e, 0x00, 0x37, 0x00, 0x07, 0x40, 0x06, 0x6f, 0x72, 0x6b, 0x00,
- 0xe4, 0x63, 0x00, 0x67, 0x34, 0x6b, 0x4a, 0x74, 0x6c, 0xe4, 0x00, 0x00,
- 0x68, 0x02, 0x69, 0x1e, 0x6f, 0x23, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06,
- 0x72, 0x08, 0x02, 0xef, 0x40, 0x00, 0x73, 0x00, 0x00, 0x06, 0x00, 0x06,
- 0x40, 0x07, 0x75, 0x6d, 0x00, 0x40, 0x00, 0x70, 0x68, 0x6f, 0x6e, 0x65,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07,
- 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe4,
- 0x00, 0x00, 0x66, 0x02, 0x69, 0x0a, 0x6e, 0x13, 0x02, 0x18, 0x40, 0x09,
- 0x75, 0x72, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x6e,
- 0x73, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x70, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x72, 0x2f, 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0xe2, 0x74, 0x00,
- 0x7a, 0x04, 0x41, 0x94, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00,
- 0x00, 0x09, 0xe2, 0x64, 0x00, 0x67, 0x29, 0xe4, 0x00, 0x00, 0x27, 0x02,
- 0x73, 0x06, 0x75, 0x0c, 0x00, 0x08, 0x40, 0x00, 0x73, 0x00, 0x40, 0x08,
- 0x74, 0x65, 0x72, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0x40, 0x00, 0x68, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01, 0x6a,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x82, 0x7a, 0x6c, 0x65, 0x00, 0xf8, 0x61,
- 0x00, 0x00, 0x63, 0x21, 0x00, 0x65, 0x30, 0x00, 0x69, 0x72, 0x01, 0x6e,
- 0x86, 0x01, 0x71, 0xb3, 0x01, 0x73, 0xe1, 0x01, 0x74, 0x2d, 0x02, 0xe1,
- 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x15, 0x00, 0x2c, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf3, 0xe1, 0x6b, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x5e, 0x00, 0x00, 0xfc,
- 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x64, 0x21, 0x00, 0x68, 0x37, 0x00,
- 0x69, 0x52, 0x00, 0x6c, 0x57, 0x00, 0x6d, 0x7f, 0x00, 0x70, 0x96, 0x00,
- 0x73, 0x9d, 0x00, 0x74, 0xbf, 0x00, 0x77, 0xd9, 0x00, 0x7a, 0xfa, 0x00,
- 0x02, 0xf0, 0xe3, 0x61, 0x00, 0x69, 0x05, 0x6f, 0x09, 0x40, 0x82, 0x73,
- 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x06, 0x40,
- 0x06, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x6d, 0x00,
- 0x6f, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05,
- 0x40, 0x00, 0x6e, 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x01, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x12, 0xe1, 0x6e, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e,
- 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xd6, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0e,
- 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x6e, 0x72,
- 0x79, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x68, 0x6f, 0x6e, 0x65,
- 0x00, 0xe2, 0x69, 0x00, 0x74, 0x04, 0x40, 0x08, 0x61, 0x00, 0xe3, 0x61,
- 0x00, 0x6f, 0x08, 0x79, 0x0d, 0x40, 0x00, 0x6e, 0x64, 0x69, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe1,
- 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6b, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe3, 0x61, 0x00, 0x68, 0x0f, 0x69, 0x15, 0xe2, 0x72, 0x00, 0x79,
- 0x08, 0x60, 0x09, 0x65, 0x00, 0x07, 0x00, 0xff, 0xff, 0x00, 0x09, 0x40,
- 0x72, 0x65, 0x65, 0x6c, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x06, 0x69, 0x15, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x27, 0x02, 0x72, 0x06, 0x02, 0xf1, 0x40, 0x00, 0x73, 0x00,
- 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x27, 0x73, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xfe, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x63, 0x00, 0x65, 0x04, 0x7a, 0x1a,
- 0x40, 0x00, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x3b, 0x65, 0x64, 0x00,
- 0x00, 0x1a, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x0c, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x53, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x02, 0xf2, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07,
- 0xe2, 0x63, 0x00, 0x68, 0x0e, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02,
- 0x6d, 0x14, 0x6e, 0x21, 0x77, 0x27, 0x02, 0xf3, 0xe2, 0x6e, 0x00, 0x74,
- 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0x2d, 0x40, 0x07, 0x72, 0x00,
- 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x61,
- 0x74, 0x65, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x73, 0x15, 0x74,
- 0x1a, 0x77, 0x28, 0x00, 0x09, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x61, 0x77, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b,
- 0x00, 0xfc, 0x61, 0x00, 0x00, 0x63, 0x13, 0x00, 0x64, 0x4c, 0x00, 0x65,
- 0x51, 0x00, 0x67, 0xa1, 0x00, 0x6c, 0x06, 0x01, 0x6e, 0x12, 0x01, 0x70,
- 0x23, 0x01, 0x73, 0x2a, 0x01, 0x74, 0x4e, 0x01, 0x76, 0x5a, 0x01, 0x7a,
- 0x7d, 0x01, 0xe2, 0x62, 0x00, 0x72, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x06, 0xe2, 0x61, 0x00,
- 0x74, 0x20, 0xe2, 0x73, 0x00, 0x74, 0x15, 0xe1, 0x73, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x1a, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x67, 0x65, 0x00, 0xe3,
- 0x64, 0x00, 0x6e, 0x07, 0x7a, 0x45, 0x40, 0x09, 0x63, 0x61, 0x6b, 0x65,
- 0x00, 0xe1, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x6c, 0x06, 0x73,
- 0x2c, 0x01, 0x43, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05,
- 0x79, 0x14, 0x40, 0x00, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x27, 0x02, 0x02, 0xf4, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x68,
- 0x69, 0x70, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02,
- 0x67, 0x07, 0x68, 0x15, 0x69, 0x43, 0x00, 0x08, 0x40, 0x09, 0x74, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x66,
- 0x11, 0x02, 0xf5, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01,
- 0x20, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x00,
- 0x3e, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0xb1, 0x00, 0x60,
- 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x02,
- 0xf6, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x70, 0x65, 0x72, 0x79, 0x00,
- 0xe2, 0x6b, 0x00, 0x73, 0x1a, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11,
- 0x00, 0x7a, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x3b, 0x40, 0x08, 0x6f, 0x6e, 0x00,
- 0xe2, 0x74, 0x00, 0x7a, 0x05, 0x40, 0x47, 0x65, 0x72, 0x00, 0x00, 0x07,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x06, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x7a, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x79, 0x06, 0x02, 0xf7, 0x40,
- 0x82, 0x65, 0x00, 0x00, 0x60, 0xfb, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00,
- 0x67, 0x10, 0x00, 0x6c, 0x3d, 0x00, 0x6d, 0x65, 0x00, 0x6e, 0x67, 0x00,
- 0x73, 0xd5, 0x00, 0x74, 0x1a, 0x01, 0x75, 0x33, 0x01, 0x77, 0x3a, 0x01,
- 0x7a, 0x6c, 0x01, 0x00, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x27,
- 0x02, 0x02, 0xf8, 0x40, 0x00, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02,
- 0x6d, 0x08, 0x73, 0x1d, 0x00, 0x09, 0x40, 0x08, 0x69, 0x6e, 0x67, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x0c, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x07,
- 0x40, 0x0b, 0x63, 0x68, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x70,
- 0x61, 0x77, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00,
- 0x00, 0x6b, 0x02, 0x73, 0x15, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x64,
- 0x00, 0x74, 0x02, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06,
- 0x62, 0x11, 0x69, 0x18, 0x77, 0x54, 0x02, 0xee, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x67, 0x00, 0x6c, 0x04, 0x40, 0x09, 0x65, 0x00, 0x00, 0x3b, 0x42,
- 0xf9, 0x65, 0x6e, 0x63, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x2f, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0xe2, 0x6d, 0x00,
- 0x77, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09,
- 0x70, 0x69, 0x65, 0x63, 0x65, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00,
- 0xe2, 0x68, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x27, 0x02,
- 0x62, 0x06, 0x69, 0x1c, 0x79, 0x31, 0x02, 0xd8, 0x40, 0x00, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x74,
- 0x04, 0x00, 0x00, 0x01, 0x7f, 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05,
- 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0x01, 0x92, 0xe1, 0x68, 0x00,
- 0xe4, 0x00, 0x00, 0x69, 0x02, 0x73, 0x09, 0x79, 0x0b, 0x00, 0x2f, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x01, 0x92, 0x40, 0x07,
- 0x66, 0x72, 0x6f, 0x75, 0x00, 0xe3, 0x61, 0x00, 0x6e, 0x13, 0x7a, 0x15,
- 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x2c, 0xe2, 0x69, 0x00,
- 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0xca, 0x01, 0x84, 0xe5, 0x63, 0x00, 0x67, 0x12,
- 0x69, 0x24, 0x6d, 0x7e, 0x73, 0x91, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x05, 0x40, 0x3a, 0x66, 0x79, 0x00, 0x40, 0x07, 0x73, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe7, 0x00, 0x00,
- 0x63, 0x02, 0x65, 0x08, 0x66, 0x0e, 0x69, 0x21, 0x6c, 0x30, 0x79, 0x46,
- 0x00, 0x2c, 0x40, 0x09, 0x61, 0x6b, 0x65, 0x00, 0x40, 0x08, 0x72, 0x65,
- 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6e, 0x00,
- 0x6f, 0x06, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92,
- 0xe1, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x07, 0x00, 0x06,
- 0x40, 0x00, 0x73, 0x68, 0x00, 0x00, 0x60, 0xe1, 0x74, 0x00, 0xe2, 0x72,
- 0x00, 0x75, 0x1a, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x51, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x09, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0xa1, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x00, 0x02, 0xfa, 0xfc, 0x63, 0x00, 0x00, 0x64, 0x1e, 0x00,
- 0x65, 0x2c, 0x00, 0x67, 0x42, 0x00, 0x68, 0x62, 0x00, 0x6c, 0x68, 0x00,
- 0x6d, 0xe9, 0x00, 0x6e, 0x31, 0x01, 0x72, 0x84, 0x02, 0x73, 0x7a, 0x03,
- 0x74, 0x06, 0x04, 0x7a, 0x64, 0x04, 0xe2, 0x68, 0x00, 0x6b, 0x06, 0x40,
- 0x09, 0x73, 0x69, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x68, 0x06,
- 0x02, 0xfb, 0x42, 0xfc, 0x72, 0x00, 0x41, 0xa2, 0x65, 0x61, 0x64, 0x00,
- 0xe2, 0x64, 0x00, 0x67, 0x05, 0x40, 0x5e, 0x6c, 0x65, 0x00, 0x40, 0x5e,
- 0x65, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x06, 0x40, 0x09, 0x72, 0x65, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01, 0xf9, 0x40, 0x00, 0x73, 0x00,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x67, 0x06, 0x69, 0x0a, 0x75, 0x11, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x09, 0x74,
- 0x69, 0x76, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x72, 0x65,
- 0x72, 0x00, 0xe5, 0x63, 0x00, 0x66, 0x06, 0x6c, 0x29, 0x6d, 0x48, 0x73,
- 0x60, 0x40, 0x09, 0x72, 0x75, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6d,
- 0x0b, 0x02, 0xfd, 0x40, 0x37, 0x64, 0x00, 0x40, 0x37, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65,
- 0x08, 0x6e, 0x0c, 0x79, 0x12, 0x02, 0xfe, 0x40, 0x09, 0x61, 0x63, 0x6b,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x18, 0x69, 0x1a, 0x79, 0x3b, 0x00, 0x08,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x00, 0x82,
- 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x09, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x00, 0xf3, 0xf9,
- 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x64, 0x37, 0x00, 0x65, 0x89, 0x00,
- 0x66, 0xa1, 0x00, 0x67, 0xa7, 0x00, 0x69, 0xe4, 0x00, 0x6b, 0xec, 0x00,
- 0x6e, 0xfe, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x55,
- 0xe2, 0x6c, 0x00, 0x72, 0x19, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b,
- 0xe2, 0x73, 0x00, 0x74, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x00, 0x08, 0x40, 0x08, 0x79, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x27, 0x69, 0x2b, 0x72, 0x30, 0x01, 0x61, 0xe1,
- 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56,
- 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x0b, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x08, 0x61, 0x69,
- 0x72, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x04, 0x6f, 0x23, 0x75, 0x30, 0x40,
- 0x00, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x63, 0x07, 0x00, 0x00,
- 0x40, 0x09, 0x6c, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe2, 0x69,
- 0x00, 0x75, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x06, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x55, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe3, 0x65, 0x00, 0x69, 0x0f, 0x79, 0x1e,
- 0xe3, 0x6c, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x55, 0x00, 0x00, 0x40,
- 0x00, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02,
- 0xff, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x69, 0x12, 0x6c, 0x18, 0x6e,
- 0x3d, 0x6f, 0x6c, 0x72, 0x70, 0x74, 0x98, 0x79, 0xdb, 0x7a, 0xdd, 0x00,
- 0x06, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6c, 0x6f, 0x77, 0x00,
- 0x40, 0xab, 0x73, 0x68, 0x00, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x27, 0x02, 0x6f, 0x06, 0x01, 0xfe, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x6e, 0x00, 0x75, 0x04, 0x40, 0x06, 0x67, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xec, 0x00, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x00, 0x40, 0x06, 0x63,
- 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x16, 0xe1, 0x68, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xab, 0x40, 0x37, 0x64, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x73, 0x00, 0x40, 0x07, 0x75, 0x72, 0x65, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x19, 0x79, 0x1d,
- 0x40, 0x00, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x47, 0x77, 0x00, 0x03, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x2b,
- 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x1f, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x6d, 0x08, 0x00, 0x5b, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe1,
- 0x6f, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40,
- 0x00, 0x74, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x17, 0x73, 0x42, 0x74, 0x6d, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06,
- 0x6c, 0x08, 0x03, 0x01, 0x40, 0x77, 0x73, 0x00, 0x00, 0x06, 0x40, 0x06,
- 0x61, 0x67, 0x65, 0x00, 0xe3, 0x62, 0x00, 0x6c, 0x10, 0x6f, 0x20, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x05, 0x40, 0x06, 0x65, 0x72,
- 0x00, 0x40, 0x09, 0x61, 0x64, 0x65, 0x00, 0x43, 0x02, 0x6e, 0x00, 0xe5,
- 0x00, 0x00, 0x62, 0x02, 0x69, 0x0a, 0x70, 0x19, 0x79, 0x1e, 0x00, 0x47,
- 0x40, 0x09, 0x75, 0x64, 0x67, 0x65, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x6e,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x06, 0x6f, 0x74, 0x00, 0x01, 0x3b, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2,
- 0x61, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x3b, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x11, 0x75,
- 0x15, 0x7a, 0x51, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x06, 0x6e, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x1d, 0x00, 0x09,
- 0xe2, 0x73, 0x00, 0x74, 0x12, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x40,
- 0x06, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07,
- 0x00, 0x3a, 0xe1, 0x7a, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x69, 0x08,
- 0x79, 0x17, 0x00, 0x47, 0x40, 0x08, 0x61, 0x6c, 0x6c, 0x00, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x96, 0xe2, 0x64, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xfd, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x1e, 0x07, 0x68, 0x82,
- 0x0d, 0x69, 0x24, 0x0e, 0x6c, 0xac, 0x10, 0x6d, 0x33, 0x15, 0x6e, 0x3f,
- 0x15, 0x6f, 0x8a, 0x15, 0x72, 0xdd, 0x1a, 0x74, 0xae, 0x25, 0x75, 0xb0,
- 0x25, 0x79, 0x15, 0x2a, 0x03, 0x03, 0xc0, 0x62, 0x19, 0x35, 0x00, 0x00,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0xc8, 0x00, 0xdb, 0x00, 0x00, 0x00, 0xfa,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x01, 0x42, 0x02, 0xe0, 0x02, 0x00,
- 0x00, 0x72, 0x03, 0x00, 0x00, 0x7b, 0x03, 0xbc, 0x04, 0xb3, 0x05, 0x24,
- 0x06, 0x90, 0x06, 0xa4, 0x06, 0x00, 0x00, 0xc9, 0x06, 0xd6, 0x06, 0xe6,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x0a, 0x65, 0x2c, 0x66, 0x34, 0x6c, 0x3a,
- 0x00, 0x06, 0x40, 0x06, 0x72, 0x64, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x04, 0x6c, 0x13, 0x79, 0x17, 0x40, 0x00, 0x64, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0x40, 0x5e, 0x65, 0x00, 0x00, 0xf4, 0x40, 0x06, 0x72, 0x64,
- 0x69, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x65, 0x73, 0x74, 0x00, 0x40, 0x1a,
- 0x65, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x64, 0x09, 0x66, 0x1c, 0x67,
- 0x21, 0x6f, 0x32, 0x00, 0x08, 0x40, 0x06, 0x62, 0x6f, 0x75, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6c, 0x79, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x06, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x6e, 0x69, 0x75,
- 0x6d, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfe,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x67, 0x04, 0x00, 0x06, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x04, 0x6c, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x6c, 0x05, 0x6e, 0x09, 0x74,
- 0x3a, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe5, 0x00,
- 0x00, 0x27, 0x02, 0x65, 0x06, 0x66, 0x0a, 0x73, 0x0f, 0x01, 0xf9, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x3b, 0x75, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe5, 0x40, 0x07, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xe6, 0x40, 0x07, 0x72, 0x00, 0xe7, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x15, 0x6c, 0x26, 0x6f, 0x98, 0x75, 0xab, 0x76,
- 0xbd, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x78, 0x08, 0x00, 0x09,
- 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe3, 0x00,
- 0x00, 0x27, 0x02, 0x6e, 0x06, 0x00, 0x76, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x07, 0x61, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x62, 0x13, 0x65, 0x1c,
- 0x69, 0x34, 0x6f, 0x4d, 0x73, 0x5c, 0x00, 0x55, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x56, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x09, 0x6c, 0x61, 0x64, 0x64, 0x65, 0x72, 0x00, 0xe3, 0x6f,
- 0x00, 0x72, 0x04, 0x79, 0x0f, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x04, 0x40, 0x09, 0x61, 0x00, 0x00, 0x06, 0x00, 0x06, 0xe3, 0x6d,
- 0x00, 0x75, 0x08, 0x76, 0x0c, 0x40, 0x06, 0x61, 0x75, 0x66, 0x72, 0x79,
- 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40, 0xad, 0x61, 0x6e, 0x74, 0x00, 0xe3,
- 0x6e, 0x00, 0x70, 0x02, 0x77, 0x04, 0x00, 0x06, 0x00, 0x2c, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x09, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0xe3, 0x6f, 0x00,
- 0x72, 0x04, 0x73, 0x08, 0x40, 0x06, 0x74, 0x00, 0x40, 0x00, 0x65, 0x00,
- 0x40, 0x09, 0x68, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01, 0x20, 0x00, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x1b, 0xe3, 0x63, 0x00,
- 0x73, 0x02, 0x7a, 0x06, 0x00, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a,
- 0x40, 0x09, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe6, 0x62, 0x00, 0x65,
- 0x22, 0x69, 0x63, 0x6d, 0x7c, 0x75, 0x8b, 0x79, 0x8f, 0xe3, 0x69, 0x00,
- 0x6c, 0x04, 0x6f, 0x17, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x2c, 0x6c, 0x00, 0xe6, 0x00, 0x00, 0x63, 0x02,
- 0x6b, 0x08, 0x6e, 0x10, 0x73, 0x16, 0x74, 0x29, 0x03, 0x04, 0x40, 0x09,
- 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x65, 0x65, 0x70, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x09, 0x40,
- 0x07, 0x61, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x00, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x67, 0x0d, 0x00, 0x06,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x00, 0x00,
- 0x07, 0xe3, 0x61, 0x00, 0x6f, 0x02, 0x79, 0x06, 0x00, 0x06, 0x40, 0x07,
- 0x6e, 0x00, 0x00, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0xf4, 0xe5, 0x64,
- 0x00, 0x67, 0x05, 0x6a, 0x70, 0x6e, 0x74, 0x74, 0x79, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x0b, 0x70, 0x30, 0x72,
- 0x37, 0x73, 0x49, 0x77, 0x57, 0x00, 0x55, 0x40, 0x07, 0x75, 0x73, 0x74,
- 0x65, 0x72, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x6e,
- 0x64, 0x00, 0xe3, 0x61, 0x00, 0x6e, 0x02, 0x6f, 0x06, 0x00, 0x00, 0x40,
- 0x00, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x6c, 0x61, 0x6e, 0x6b, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00,
- 0x5e, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x02, 0x00, 0x08, 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x61, 0x79,
- 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe2, 0x6c,
- 0x00, 0x72, 0x05, 0x40, 0x09, 0x65, 0x74, 0x00, 0x40, 0x06, 0x79, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x95, 0x00, 0x09, 0xfd, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x62, 0x07, 0x00, 0x63, 0x2d, 0x00, 0x64, 0x32,
- 0x00, 0x66, 0x50, 0x00, 0x67, 0x56, 0x00, 0x69, 0x6f, 0x00, 0x6c, 0x82,
- 0x00, 0x6d, 0x9a, 0x00, 0x6e, 0xa0, 0x00, 0x72, 0xd2, 0x00, 0x74, 0x14,
- 0x01, 0x02, 0xc4, 0x40, 0x5e, 0x67, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x6c, 0x1b, 0x00, 0x55, 0xe2, 0x67, 0x00, 0x6e, 0x0f, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40, 0x00, 0x61, 0x6e,
- 0x00, 0x40, 0x06, 0x7a, 0x6f, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x40, 0x06,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61,
- 0x00, 0x6e, 0x02, 0x00, 0x09, 0x40, 0x07, 0x67, 0x00, 0x40, 0x09, 0x69,
- 0x73, 0x68, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x08, 0x6f, 0x0c, 0x40, 0x00,
- 0x6e, 0x74, 0x75, 0x61, 0x6e, 0x00, 0x40, 0x5e, 0x65, 0x00, 0x40, 0x06,
- 0x79, 0x6c, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x05, 0x40, 0x55, 0x6e, 0x64, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x07, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x72,
- 0x00, 0x74, 0x02, 0x00, 0x5b, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x11, 0x03, 0x05, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x1a, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04,
- 0x6f, 0x0a, 0x75, 0x19, 0x40, 0x06, 0x74, 0x00, 0x40, 0x47, 0x73, 0x6f,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xed, 0x00, 0x00, 0x27, 0x02, 0x62,
- 0x06, 0x65, 0x0b, 0x68, 0x11, 0x6b, 0x1f, 0x6c, 0x24, 0x6d, 0x2b, 0x6f,
- 0x38, 0x70, 0x51, 0x73, 0x53, 0x74, 0x6a, 0x77, 0xd5, 0x00, 0xaa, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x06, 0x61, 0x67, 0x00, 0x40, 0x00, 0x6f, 0x75,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x47, 0x40, 0x08, 0x6c,
- 0x64, 0x65, 0x72, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0x40, 0x09, 0x69,
- 0x67, 0x68, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x68, 0x00, 0x6c, 0x05, 0x6d, 0x0b,
- 0x40, 0x07, 0x6f, 0x6c, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0x40,
- 0x08, 0x65, 0x74, 0x65, 0x72, 0x00, 0x00, 0x55, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x79, 0x0e, 0xe2, 0x64, 0x00, 0x73, 0x02, 0x01, 0x63, 0x00, 0x00,
- 0x41, 0x63, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0xe1, 0x72, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x0c, 0xe2, 0x63, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x07,
- 0x69, 0x73, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x1e, 0x6e, 0x2a, 0x70, 0x49,
- 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x74, 0x69, 0x73, 0x00, 0x40,
- 0x00, 0x6c, 0x6f, 0x67, 0x79, 0x00, 0x40, 0x00, 0x6e, 0x74, 0x65, 0x73,
- 0x74, 0x69, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x10, 0x00, 0x08, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00,
- 0x07, 0x40, 0x06, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x73,
- 0x00, 0xe3, 0x65, 0x00, 0x68, 0x4e, 0x6f, 0x66, 0xe7, 0x00, 0x00, 0x61,
- 0x02, 0x63, 0x0e, 0x68, 0x25, 0x6b, 0x2c, 0x70, 0x34, 0x77, 0x3a, 0x00,
- 0x82, 0xe1, 0x75, 0x00, 0xe2, 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x09, 0x65, 0x65, 0x70,
- 0x65, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x73, 0x74, 0x00, 0x40, 0x09, 0x61,
- 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x00, 0xe4, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x1e, 0x67,
- 0x34, 0x6e, 0x38, 0x7a, 0x4f, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x14, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x08, 0x01, 0x5f, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x69, 0x65, 0x00, 0x00, 0x06, 0xe2,
- 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0x40, 0x5e, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x07, 0x01,
- 0x15, 0x40, 0x09, 0x65, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe2, 0x65, 0x00, 0x6f, 0x09, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x09, 0x74, 0x74,
- 0x65, 0x00, 0xe3, 0x64, 0x00, 0x6b, 0x02, 0x70, 0x1c, 0x00, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x72, 0xe2, 0x6c, 0x00, 0x6e,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01,
- 0x15, 0x00, 0x72, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0x06, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x29, 0x70, 0x31, 0x75,
- 0x38, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x06, 0x72, 0x0b, 0x74, 0x0d,
- 0x00, 0xa5, 0x40, 0x06, 0x6f, 0x00, 0x40, 0x09, 0x6c, 0x65, 0x00, 0x00,
- 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x82, 0x40, 0x09, 0x72, 0x00, 0x40, 0x08, 0x6c, 0x6c, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x61, 0x63, 0x68, 0x6f, 0x00, 0x40, 0x72, 0x6d,
- 0x70, 0x00, 0xfe, 0x61, 0x00, 0x00, 0x63, 0x28, 0x00, 0x64, 0x2d, 0x00,
- 0x65, 0x33, 0x00, 0x69, 0x5b, 0x00, 0x6c, 0x61, 0x00, 0x6d, 0xb2, 0x00,
- 0x6e, 0xe0, 0x00, 0x6f, 0x5a, 0x03, 0x72, 0xe2, 0x04, 0x73, 0xad, 0x05,
- 0x74, 0x12, 0x06, 0x77, 0x2d, 0x06, 0x79, 0x33, 0x06, 0xe1, 0x72, 0x00,
- 0xe5, 0x00, 0x00, 0x62, 0x02, 0x69, 0x07, 0x73, 0x0c, 0x77, 0x13, 0x00,
- 0x55, 0x40, 0x09, 0x6f, 0x78, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40,
- 0x09, 0x68, 0x69, 0x66, 0x74, 0x00, 0x40, 0x06, 0x68, 0x65, 0x65, 0x6c,
- 0x00, 0x40, 0x06, 0x6b, 0x6f, 0x00, 0x40, 0x00, 0x64, 0x69, 0x74, 0x00,
- 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6b, 0x07, 0x73, 0x10, 0x7a, 0x18, 0x01,
- 0x1a, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x09, 0x00, 0xf3, 0x60, 0x07, 0x65, 0x00, 0x00, 0x00, 0xff, 0xff, 0x40,
- 0x09, 0x65, 0x72, 0x00, 0x40, 0x07, 0x73, 0x68, 0x61, 0x00, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x63, 0x17, 0x64, 0x1c, 0x69, 0x28, 0x6c, 0x36, 0x00,
- 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x07,
- 0x61, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03, 0x07, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x02, 0x00, 0x00, 0x40, 0x07,
- 0x6e, 0x69, 0x74, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02,
- 0x73, 0x20, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40,
- 0x00, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0x40, 0x09,
- 0x74, 0x6f, 0x6e, 0x65, 0x00, 0xf8, 0x64, 0x00, 0x00, 0x65, 0x0f, 0x00,
- 0x69, 0xf5, 0x00, 0x6e, 0x49, 0x01, 0x6f, 0x57, 0x01, 0x72, 0x84, 0x01,
- 0x74, 0x88, 0x01, 0x75, 0x2d, 0x02, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40,
- 0x09, 0x72, 0x6d, 0x65, 0x00, 0x40, 0xb2, 0x72, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x72, 0x20, 0x73, 0xb2, 0x74, 0xbd, 0x00, 0x09, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e,
- 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x09,
- 0x74, 0x00, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x69, 0x60, 0x6f, 0x70, 0xe3,
- 0x00, 0x00, 0x6c, 0x02, 0x74, 0x37, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x73, 0x28, 0x00, 0x56, 0xe3, 0x73, 0x00, 0x74, 0x0d, 0x7a, 0x11,
- 0xe2, 0x73, 0x00, 0x74, 0x06, 0x40, 0x09, 0x69, 0x6d, 0x6f, 0x00, 0x00,
- 0x09, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x07, 0x68, 0x69, 0x70,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x17, 0x03, 0x08, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x01,
- 0xbc, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0xe2, 0x73, 0x00, 0x75, 0x06, 0x40, 0x06, 0x69, 0x74,
- 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x08, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x73, 0x0d, 0x00, 0x08, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe6,
- 0x61, 0x00, 0x63, 0x0f, 0x65, 0x17, 0x69, 0x19, 0x74, 0x1b, 0x75, 0x43,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03, 0x09, 0x42, 0xbc,
- 0x74, 0x79, 0x00, 0x40, 0x00, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x12, 0x6f, 0x17, 0xe1, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x06, 0x03, 0x09, 0x40, 0x07,
- 0x61, 0x00, 0x00, 0x07, 0x40, 0x09, 0x76, 0x65, 0x00, 0x40, 0x00, 0x75,
- 0x72, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x00, 0x40, 0x09, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x06, 0x20, 0x09, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x15, 0x6c, 0x2a, 0x72,
- 0x80, 0x00, 0x69, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x6c, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x4f,
- 0xe5, 0x00, 0x00, 0x66, 0x02, 0x6d, 0x14, 0x6e, 0x2b, 0x77, 0x31, 0x03,
- 0x0a, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x0e,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x12, 0x40, 0x37,
- 0x79, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x13, 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07,
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x57, 0x00, 0x06, 0xe3,
- 0x66, 0x00, 0x69, 0x18, 0x73, 0x2b, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x72, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x07, 0xf9, 0x63, 0x00, 0x00, 0x64, 0x33, 0x00, 0x65, 0x4f,
- 0x00, 0x67, 0x5c, 0x00, 0x6c, 0x87, 0x00, 0x6d, 0xa8, 0x00, 0x70, 0xec,
- 0x00, 0x73, 0x29, 0x01, 0x74, 0x53, 0x01, 0xe3, 0x61, 0x00, 0x65, 0x06,
- 0x68, 0x22, 0x40, 0x3a, 0x63, 0x68, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x6d, 0x69, 0x73, 0x74, 0x72, 0x79, 0x00, 0xe1, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x74, 0x0d, 0x00, 0x06, 0xe2, 0x69,
- 0x00, 0x79, 0x04, 0x40, 0x06, 0x63, 0x00, 0x00, 0x07, 0x40, 0x00, 0x69,
- 0x63, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69,
- 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04,
- 0x79, 0x12, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x06, 0xe1, 0x6f,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00,
- 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x1c, 0x00, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x72, 0x04, 0x40, 0x00, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c,
- 0x00, 0x00, 0x06, 0xe2, 0x68, 0x00, 0x6f, 0x1e, 0xe1, 0x79, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x04, 0x73, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40, 0x00,
- 0x6c, 0x00, 0x00, 0x07, 0xe2, 0x74, 0x00, 0x79, 0x0b, 0x40, 0x00, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x72, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x09, 0x40, 0x00, 0x72, 0x6f, 0x6e,
- 0x6f, 0x75, 0x73, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x63, 0x00, 0xe7,
- 0x61, 0x00, 0x62, 0x07, 0x69, 0x0c, 0x6d, 0x2b, 0x6f, 0x6f, 0x72, 0x96,
- 0x75, 0xb7, 0x40, 0x09, 0x6e, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x09, 0x69,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07,
- 0x00, 0x08, 0x40, 0x08, 0x61, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x11, 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x75, 0x6d, 0x00, 0xe2, 0x63, 0x00,
- 0x6e, 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe2, 0x6c,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61,
- 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x79, 0x00, 0xe1,
- 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x59,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6e, 0x64, 0x00, 0xe2, 0x74,
- 0x00, 0x75, 0x57, 0xe3, 0x61, 0x00, 0x69, 0x27, 0x75, 0x42, 0xe3, 0x6c,
- 0x00, 0x70, 0x04, 0x74, 0x08, 0x40, 0x08, 0x74, 0x00, 0x40, 0x09, 0x6f,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x82, 0x40, 0x00, 0x6e, 0x64, 0x68, 0x65,
- 0x69, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x74, 0x08, 0x75, 0x0e,
- 0x00, 0x08, 0x40, 0x06, 0x77, 0x61, 0x79, 0x00, 0x40, 0x00, 0x69, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x70, 0x00, 0x40, 0x06, 0x67, 0x61, 0x77, 0x00,
- 0x40, 0x06, 0x73, 0x65, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1b, 0x6f,
- 0x3c, 0xe2, 0x73, 0x00, 0x74, 0x14, 0xe1, 0x74, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x01, 0x92, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x72, 0x02, 0x74, 0x08, 0x00,
- 0x00, 0x40, 0x09, 0x6b, 0x69, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x0b, 0x7a, 0x65,
- 0x00, 0xe2, 0x73, 0x00, 0x75, 0x3d, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x77, 0x10, 0x02, 0x0a, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe1, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x16, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x09,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xe5, 0x00, 0x07, 0x40, 0x00, 0x65,
- 0x6e, 0x00, 0x40, 0x00, 0x74, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xfd, 0x61, 0x00, 0x00, 0x62, 0x12, 0x00, 0x64, 0x43, 0x00, 0x66, 0x5c,
- 0x00, 0x67, 0x60, 0x00, 0x6c, 0xd3, 0x00, 0x6d, 0x00, 0x01, 0x6e, 0x53,
- 0x01, 0x72, 0xc0, 0x01, 0x73, 0x24, 0x02, 0x74, 0x28, 0x02, 0x76, 0x31,
- 0x02, 0x7a, 0x51, 0x02, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x06, 0x40, 0x09, 0x73, 0x73, 0x00, 0xe3, 0x62,
- 0x00, 0x65, 0x23, 0x6c, 0x25, 0xe2, 0x65, 0x00, 0x6f, 0x13, 0xe2, 0x72,
- 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x07,
- 0x73, 0x68, 0x00, 0x00, 0x59, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x73, 0x00, 0x00, 0x82, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4,
- 0x40, 0x55, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x67, 0x45, 0x6f,
- 0x65, 0x00, 0x06, 0xe5, 0x62, 0x00, 0x68, 0x0e, 0x6e, 0x15, 0x70, 0x2b,
- 0x77, 0x32, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40,
- 0x09, 0x74, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x74, 0x7a, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x69,
- 0x78, 0x65, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x74, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x04, 0x6c, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x7e, 0x00, 0x07, 0x00, 0xf3, 0x40, 0x06, 0x6c, 0x6f, 0x00, 0xe3,
- 0x64, 0x00, 0x6c, 0x12, 0x74, 0x24, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x6f, 0x02,
- 0x00, 0x08, 0x40, 0x08, 0x6e, 0x00, 0x00, 0x09, 0xe5, 0x62, 0x00, 0x63,
- 0x06, 0x6c, 0x1e, 0x6d, 0x23, 0x70, 0x3f, 0x40, 0x07, 0x61, 0x6c, 0x73,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x40, 0x07, 0x72, 0x79,
- 0x00, 0x40, 0x95, 0x65, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02,
- 0x79, 0x06, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x55, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x67, 0x02,
- 0x6b, 0x33, 0x6e, 0x44, 0x6f, 0x52, 0x73, 0x5a, 0x00, 0x06, 0xe3, 0x65,
- 0x00, 0x68, 0x1d, 0x69, 0x22, 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x62,
- 0x02, 0x73, 0x09, 0x79, 0x0f, 0x03, 0x0b, 0x40, 0x07, 0x72, 0x65, 0x61,
- 0x64, 0x00, 0x40, 0x06, 0x6e, 0x61, 0x70, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x61, 0x6d, 0x00, 0x40, 0x07, 0x76, 0x69, 0x74, 0x69, 0x73, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x72, 0x6d, 0x6f, 0x75,
- 0x73, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x64,
- 0x06, 0x6c, 0x17, 0x6f, 0x47, 0x74, 0x49, 0x40, 0x09, 0x66, 0x66, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x00, 0x4c, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x68,
- 0x0a, 0x69, 0x10, 0x79, 0x23, 0x00, 0x09, 0x40, 0x09, 0x72, 0x69, 0x65,
- 0x6e, 0x64, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x64, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe2, 0x00, 0x00, 0x68,
- 0x02, 0x00, 0x55, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x07, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x08, 0x00,
- 0x08, 0xe1, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x62, 0x08, 0x6e,
- 0x0e, 0x72, 0x10, 0x03, 0x0c, 0x40, 0x09, 0x77, 0x61, 0x79, 0x00, 0x40,
- 0x09, 0x61, 0x63, 0x6b, 0x00, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x6d, 0x00,
- 0x7a, 0x04, 0x40, 0x06, 0x6f, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00,
- 0xf6, 0x61, 0x00, 0x00, 0x65, 0x6f, 0x01, 0x69, 0xc3, 0x01, 0x6f, 0x6d,
- 0x02, 0x75, 0xb9, 0x03, 0x79, 0x50, 0x04, 0xf8, 0x63, 0x00, 0x00, 0x64,
- 0x33, 0x00, 0x6d, 0x8e, 0x00, 0x6e, 0xb9, 0x00, 0x72, 0xd9, 0x00, 0x73,
- 0xe5, 0x00, 0x75, 0x3b, 0x01, 0x7a, 0x42, 0x01, 0xe2, 0x65, 0x00, 0x69,
- 0x12, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x08, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x13,
- 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x3b, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe6,
- 0x00, 0x00, 0x64, 0x02, 0x65, 0x14, 0x69, 0x16, 0x6e, 0x42, 0x73, 0x48,
- 0x02, 0x41, 0xe1, 0x65, 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x02, 0x73, 0x04,
- 0x00, 0x0b, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x00, 0x06, 0xe2, 0x61,
- 0x00, 0x6f, 0x15, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x61, 0x6c, 0x00,
- 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x02, 0x75, 0x04, 0x00, 0x06,
- 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x00, 0xe2, 0x72, 0x00, 0x75, 0x1b, 0xe2, 0x69, 0x00, 0x6f, 0x11, 0xe1,
- 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x59, 0x72,
- 0x00, 0xe3, 0x63, 0x00, 0x64, 0x04, 0x73, 0x17, 0x40, 0x5e, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x75, 0x06, 0x00, 0x06, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x5e, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x6e, 0x00,
- 0x73, 0x06, 0x40, 0x07, 0x6f, 0x73, 0x74, 0x00, 0xe7, 0x00, 0x00, 0x62,
- 0x02, 0x66, 0x19, 0x68, 0x1e, 0x69, 0x25, 0x77, 0x34, 0x79, 0x3a, 0x00,
- 0x47, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x77, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x75, 0x6c, 0x00, 0x40, 0x08, 0x6f, 0x75, 0x73, 0x65, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0x00, 0xf4, 0x40,
- 0x07, 0x63, 0x6f, 0x6d, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x5e, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07,
- 0x67, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1a, 0x6e, 0x34, 0xe2, 0x6d, 0x00,
- 0x6e, 0x02, 0x01, 0x62, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01,
- 0x42, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x66, 0x02, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0xe2, 0x68, 0x00, 0x69,
- 0x09, 0x40, 0x00, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x00, 0x40, 0x00,
- 0x64, 0x00, 0xe6, 0x62, 0x00, 0x64, 0x1d, 0x6d, 0x30, 0x6e, 0x4c, 0x73,
- 0x50, 0x74, 0x73, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6e, 0x10, 0x00, 0x3e,
- 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x12, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xb5, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x82, 0x73, 0x65, 0x00, 0x40, 0x2c, 0x74, 0x00, 0xe2,
- 0x73, 0x00, 0x74, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x65,
- 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x47, 0x00, 0x3a, 0xe3, 0x63,
- 0x00, 0x74, 0x04, 0x7a, 0x1a, 0x40, 0x59, 0x68, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x79, 0x07, 0x00, 0x47,
- 0x40, 0x00, 0x74, 0x69, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x07, 0x00, 0x60, 0xfa, 0x61, 0x00, 0x00, 0x62, 0x17, 0x00, 0x63,
- 0x7d, 0x00, 0x6f, 0x88, 0x00, 0x70, 0xa5, 0x00, 0x72, 0xb0, 0x00, 0x73,
- 0xd1, 0x00, 0x74, 0xff, 0x00, 0x76, 0x0f, 0x01, 0x77, 0x13, 0x01, 0xe2,
- 0x6d, 0x00, 0x74, 0x06, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x28, 0x75, 0x49, 0x00, 0x55, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe2, 0x73, 0x00, 0x7a, 0x09,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x04, 0x69, 0x06, 0x40, 0x00, 0x72, 0x00, 0x00, 0x09,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x6b, 0x65, 0x6e, 0x73, 0x70, 0x69,
- 0x65, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79,
- 0x11, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x3b, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1a,
- 0xe2, 0x66, 0x00, 0x6f, 0x10, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07,
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0x0d, 0x40, 0x5c, 0x75,
- 0x73, 0x00, 0x00, 0x5e, 0xe1, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x07, 0x6f, 0x16, 0x79, 0x1e, 0x00, 0x47, 0x40, 0x06, 0x72, 0x79,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x6c, 0x69, 0x61, 0x00,
- 0x03, 0x0e, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x6c, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x77, 0x0b, 0x00, 0xfe, 0x40, 0xec, 0x72,
- 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x6d, 0x00,
- 0xe5, 0x63, 0x00, 0x65, 0x10, 0x69, 0x1d, 0x6d, 0x2b, 0x74, 0x48, 0xe2,
- 0x61, 0x00, 0x6f, 0x06, 0x40, 0x00, 0x67, 0x6f, 0x6e, 0x00, 0x40, 0x07,
- 0x73, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x79, 0x04, 0x00, 0x82,
- 0x00, 0x37, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x6e,
- 0x10, 0x00, 0x3e, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x11, 0x74, 0x18, 0x00, 0x97, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x00, 0x75, 0x73,
- 0x00, 0x40, 0x3b, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x04, 0x6f, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x79, 0x07, 0x00, 0x09,
- 0x40, 0x3b, 0x75, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x70, 0x1b,
- 0xe2, 0x65, 0x00, 0x6f, 0x10, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x07, 0x67,
- 0x65, 0x6e, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x69, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x1d,
- 0x6f, 0x23, 0x75, 0x40, 0xe4, 0x72, 0x00, 0x73, 0x0c, 0x74, 0x10, 0x77,
- 0x12, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2c, 0x00,
- 0x60, 0x40, 0x47, 0x68, 0x00, 0x00, 0x09, 0x00, 0x72, 0x40, 0x07, 0x69,
- 0x73, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x06, 0x40, 0x00, 0x63, 0x68,
- 0x69, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x63, 0x00,
- 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x68, 0x00, 0x00, 0x06, 0xc1, 0x61,
- 0x17, 0x33, 0x00, 0x35, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x10, 0x01, 0xde,
- 0x01, 0xe7, 0x01, 0xec, 0x01, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x02, 0x00, 0x00, 0x93, 0x02, 0xf1, 0x02, 0xce, 0x03, 0x00,
- 0x00, 0xd4, 0x03, 0x4f, 0x04, 0x8c, 0x04, 0xab, 0x04, 0xf3, 0x04, 0x4f,
- 0x05, 0x03, 0x0f, 0xe3, 0x64, 0x00, 0x6c, 0x02, 0x74, 0x61, 0x00, 0x55,
- 0xe8, 0x00, 0x00, 0x69, 0x02, 0x6b, 0x06, 0x6c, 0x1d, 0x6d, 0x23, 0x70,
- 0x38, 0x73, 0x3e, 0x74, 0x46, 0x00, 0x09, 0x40, 0x06, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x09, 0x6f, 0x73, 0x74, 0x00, 0x40, 0x08, 0x63, 0x6f, 0x72,
- 0x65, 0x72, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x68, 0x06, 0x73, 0x0c, 0x00, 0x09, 0x40, 0x06,
- 0x65, 0x00, 0x40, 0x09, 0x65, 0x72, 0x64, 0x00, 0x40, 0x09, 0x6b, 0x69,
- 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x2d, 0x73, 0x3a, 0x00,
- 0x06, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6c, 0x0e, 0xe2, 0x64, 0x00, 0x74,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x0a, 0x00, 0x7e, 0x40, 0x07,
- 0x79, 0x67, 0x6f, 0x6f, 0x6b, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x08, 0x40, 0x00, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x00, 0x40, 0x08,
- 0x6f, 0x70, 0x70, 0x65, 0x72, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x63,
- 0x09, 0x64, 0x21, 0x66, 0x44, 0x68, 0x59, 0x6c, 0x68, 0x6d, 0x93, 0x70,
- 0x9b, 0x73, 0xa3, 0x00, 0x06, 0x40, 0x00, 0x77, 0x66, 0x75, 0x6c, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x19, 0xe2, 0x6d, 0x00, 0x75, 0x0c, 0xe2, 0x6d,
- 0x00, 0x6e, 0x05, 0x40, 0x00, 0x69, 0x74, 0x00, 0x00, 0xfc, 0x40, 0x09,
- 0x67, 0x68, 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x73, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x07, 0x40, 0x06, 0x74, 0x68, 0x65, 0x72, 0x00, 0x40,
- 0x00, 0x72, 0x73, 0x61, 0x6b, 0x65, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x05, 0x40, 0x07, 0x61, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x64, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x13, 0x79, 0x22, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x6b, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0xdb,
- 0x65, 0x73, 0x73, 0x00, 0x02, 0x76, 0x40, 0x06, 0x6f, 0x74, 0x68, 0x65,
- 0x72, 0x00, 0x40, 0x06, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x6f, 0x05, 0x70, 0x09, 0x40, 0x06, 0x6e, 0x64, 0x00, 0x40, 0x06,
- 0x6e, 0x00, 0x40, 0x00, 0x65, 0x65, 0x64, 0x00, 0xe2, 0x72, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe1, 0x67,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x5e, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x07, 0x67,
- 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe3, 0x64, 0x00, 0x66, 0x68, 0x6c,
- 0x73, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x65, 0x19, 0x66, 0x28, 0x6d, 0x40,
- 0x73, 0x46, 0x00, 0x97, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x05, 0x40,
- 0x07, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x60, 0x40, 0x07, 0x6f, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe3, 0x65, 0x00,
- 0x6e, 0x05, 0x73, 0x0a, 0x40, 0x08, 0x6c, 0x64, 0x00, 0x40, 0x09, 0x63,
- 0x68, 0x00, 0x40, 0x09, 0x68, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x06, 0x40, 0x08, 0x77, 0x6f, 0x67, 0x00, 0x00, 0x06, 0xe8, 0x61, 0x00,
- 0x64, 0x0e, 0x65, 0x20, 0x67, 0x29, 0x6b, 0x2b, 0x6e, 0x2d, 0x6f, 0x31,
- 0x7a, 0x49, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x02, 0x75, 0x00, 0x07, 0x00, 0x55, 0x00, 0x08, 0x40,
- 0x00, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x00, 0xeb, 0x00, 0x00, 0x62, 0x02,
- 0x64, 0x07, 0x65, 0x4d, 0x66, 0x51, 0x67, 0x6b, 0x69, 0x77, 0x6b, 0x85,
- 0x6e, 0x87, 0x70, 0x89, 0x73, 0x8b, 0x00, 0x07, 0x40, 0x06, 0x65, 0x72,
- 0x00, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x68, 0x07, 0x69, 0x10, 0x6c, 0x15,
- 0x6e, 0x19, 0x73, 0x29, 0x77, 0x2b, 0x79, 0x31, 0x02, 0x41, 0x40, 0x09,
- 0x79, 0x65, 0x00, 0x40, 0x00, 0x65, 0x61, 0x72, 0x74, 0x65, 0x64, 0x00,
- 0x40, 0x00, 0x73, 0x68, 0x00, 0x40, 0x60, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x40, 0x00, 0x67, 0x68, 0x74,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x00, 0x00, 0x06, 0x40,
- 0x00, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x69, 0x08, 0x79, 0x0f,
- 0x00, 0x55, 0x40, 0x06, 0x61, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x15, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x5e, 0x00, 0x08, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x00, 0x09, 0x00, 0x09, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x73, 0x13, 0x00,
- 0x5e, 0xe2, 0x65, 0x00, 0x75, 0x06, 0x40, 0x06, 0x72, 0x72, 0x79, 0x00,
- 0x40, 0x07, 0x6d, 0x70, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x08, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x68, 0x65, 0x72, 0x00, 0xe7, 0x65, 0x00, 0x67, 0x02, 0x69,
- 0x2b, 0x6d, 0x41, 0x70, 0x64, 0x73, 0x66, 0x79, 0x6a, 0x00, 0x82, 0xe2,
- 0x65, 0x00, 0x6f, 0x20, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x6f, 0x06, 0x02,
- 0xef, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x0b, 0xe2, 0x6c, 0x00,
- 0x79, 0x04, 0x40, 0x09, 0x61, 0x00, 0x00, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x18, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x40, 0x00, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x09, 0x40, 0x07, 0x65, 0x00, 0x00, 0xf4, 0xe4, 0x68, 0x00,
- 0x6c, 0x0c, 0x70, 0x12, 0x73, 0x17, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x09, 0x77, 0x6b, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x65, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x07,
- 0x6d, 0x65, 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x79, 0x06, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x00, 0x00, 0xe4, 0x00,
- 0x00, 0x63, 0x02, 0x68, 0x07, 0x74, 0x0b, 0x00, 0x00, 0x40, 0x08, 0x68,
- 0x61, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x67, 0x06, 0x6c, 0x12,
- 0x72, 0x18, 0x74, 0x34, 0x40, 0x08, 0x63, 0x68, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x09,
- 0x61, 0x73, 0x68, 0x00, 0xe2, 0x64, 0x00, 0x6d, 0x09, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x06, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40,
- 0x06, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0x60, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x74, 0x53,
- 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x11, 0x6d, 0x1c, 0x6f, 0x30, 0x03, 0x10, 0xe2, 0x62, 0x00,
- 0x6e, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x63, 0x65, 0x00,
- 0xe2, 0x64, 0x00, 0x73, 0x02, 0x00, 0x37, 0x40, 0x09, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x00,
- 0x00, 0x40, 0x55, 0x6e, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x65, 0x96, 0x04, 0x69, 0x1c, 0x06, 0x6f, 0x9f, 0x07, 0x75, 0xeb, 0x09,
- 0x00, 0x00, 0xfe, 0x62, 0x00, 0x00, 0x63, 0x1e, 0x00, 0x64, 0x72, 0x00,
- 0x66, 0xcf, 0x00, 0x68, 0xee, 0x00, 0x69, 0xf3, 0x00, 0x6d, 0x0c, 0x01,
- 0x6e, 0x3f, 0x01, 0x70, 0xb3, 0x02, 0x73, 0x1a, 0x03, 0x74, 0x45, 0x03,
- 0x76, 0xbe, 0x03, 0x79, 0x40, 0x04, 0x7a, 0x5d, 0x04, 0xe2, 0x00, 0x00,
- 0x62, 0x02, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x00, 0x60, 0xe3, 0x65, 0x00, 0x69, 0x32, 0x6b, 0x48, 0xe3, 0x00,
- 0x00, 0x66, 0x02, 0x6c, 0x15, 0x00, 0x7c, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0x11, 0x40, 0x84, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x36, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x6c, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11, 0x69, 0x24,
- 0x75, 0x2a, 0x03, 0x12, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x45, 0x41, 0x52, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02,
- 0x64, 0x06, 0x72, 0x08, 0x03, 0x13, 0x40, 0x00, 0x73, 0x00, 0x00, 0x37,
- 0x00, 0x07, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x6c, 0x00, 0x74, 0x14, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x00,
- 0x4d, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0x14, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x66, 0x00, 0x74, 0x0f, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x61, 0x6d, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x79, 0x09, 0x03, 0x15, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x96, 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x6f, 0x1d, 0x70, 0x25, 0x02, 0x23,
- 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40, 0x36, 0x69, 0x63,
- 0x61, 0x6c, 0x00, 0x40, 0x09, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0x40,
- 0x09, 0x75, 0x73, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x64,
- 0x07, 0x00, 0x67, 0xf4, 0x00, 0x69, 0xf8, 0x00, 0x6e, 0x06, 0x01, 0x6f,
- 0x0a, 0x01, 0x74, 0x0f, 0x01, 0x75, 0x31, 0x01, 0x00, 0x08, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0xec, 0x00, 0x00, 0x61, 0x02, 0x63, 0x0e, 0x64, 0x26,
- 0x65, 0x41, 0x66, 0x50, 0x69, 0x58, 0x6d, 0x86, 0x6e, 0x94, 0x70, 0xae,
- 0x73, 0xbe, 0x75, 0xcd, 0x03, 0x16, 0xe2, 0x6d, 0x00, 0x75, 0x02, 0x00,
- 0x09, 0x40, 0x09, 0x6e, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00,
- 0x75, 0x0b, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x06, 0x40, 0x06, 0x79,
- 0x00, 0x40, 0x06, 0x67, 0x68, 0x74, 0x65, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x75, 0x04, 0x00, 0x00, 0x00, 0x09, 0x40, 0x07, 0x72, 0x00,
- 0x43, 0x17, 0x61, 0x74, 0x68, 0x65, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6f,
- 0x1a, 0xe1, 0x6f, 0x00, 0xe1, 0x71, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00,
- 0x09, 0x40, 0x86, 0x74, 0x68, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x0f, 0xe2, 0x70, 0x00, 0x73, 0x06, 0x40, 0x09, 0x68, 0x65, 0x77, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x09, 0x65, 0x63, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09, 0x40, 0x09, 0x65, 0x6e,
- 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40,
- 0x93, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x6e, 0x63, 0x6c, 0x65, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x07,
- 0x6c, 0x61, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x0b, 0x73, 0x0f,
- 0x01, 0x5b, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x07, 0x6d, 0x61, 0x6e, 0x73, 0x68, 0x69, 0x70,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1d, 0xe2, 0x72, 0x00,
- 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x00, 0x09, 0xe4, 0x65, 0x00, 0x68, 0x1e, 0x6e, 0x54, 0x70,
- 0x59, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x73, 0x09, 0x76, 0x0f, 0x00, 0x06,
- 0x40, 0x09, 0x72, 0x75, 0x69, 0x74, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x74,
- 0x00, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02,
- 0x6f, 0x16, 0x73, 0x2b, 0x00, 0x2f, 0xe2, 0x63, 0x00, 0x74, 0x0b, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x09, 0x65, 0x6c, 0x00, 0x40, 0x82, 0x6c, 0x65, 0x00, 0xe2,
- 0x70, 0x00, 0x73, 0x02, 0x03, 0x18, 0xe5, 0x00, 0x00, 0x68, 0x02, 0x6c,
- 0x0a, 0x72, 0x10, 0x79, 0x17, 0x00, 0x47, 0x40, 0x09, 0x6f, 0x70, 0x70,
- 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x6f,
- 0x6f, 0x74, 0x73, 0x00, 0x00, 0x60, 0xe3, 0x65, 0x00, 0x69, 0x1e, 0x75,
- 0x52, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x72, 0x15, 0x03, 0x19, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xe7, 0x40,
- 0xdb, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe4, 0x66, 0x00, 0x6e, 0x1a,
- 0x73, 0x23, 0x74, 0x25, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x51, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00,
- 0x08, 0x00, 0x12, 0x00, 0x00, 0x40, 0x53, 0x75, 0x64, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x13, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe4, 0x61, 0x00, 0x65, 0x06,
- 0x69, 0x41, 0x79, 0x77, 0x40, 0x09, 0x6d, 0x65, 0x6e, 0x00, 0xe6, 0x00,
- 0x00, 0x64, 0x02, 0x6c, 0x0a, 0x6e, 0x0c, 0x73, 0x18, 0x79, 0x28, 0x03,
- 0x1a, 0x40, 0x06, 0x69, 0x67, 0x67, 0x65, 0x72, 0x00, 0x00, 0xfd, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x73, 0x00, 0xe2,
- 0x69, 0x00, 0x74, 0x05, 0x40, 0x09, 0x64, 0x65, 0x00, 0x40, 0x06, 0x6f,
- 0x6e, 0x65, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00, 0xe3, 0x64, 0x00,
- 0x6d, 0x02, 0x74, 0x09, 0x00, 0x00, 0x40, 0x09, 0x65, 0x74, 0x65, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x79, 0x1f, 0xe2, 0x73, 0x00, 0x74, 0x02, 0x00,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c,
- 0x00, 0x00, 0x07, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x69, 0x09,
- 0x6e, 0x0e, 0x02, 0xb6, 0x40, 0x06, 0x65, 0x61, 0x72, 0x64, 0x00, 0x40,
- 0x00, 0x73, 0x68, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xf9, 0x61,
- 0x00, 0x00, 0x62, 0x4b, 0x00, 0x65, 0x4f, 0x00, 0x67, 0x06, 0x01, 0x6d,
- 0x25, 0x01, 0x6e, 0x2b, 0x01, 0x70, 0x45, 0x01, 0x77, 0x5a, 0x01, 0x79,
- 0x5c, 0x01, 0xe2, 0x73, 0x00, 0x74, 0x26, 0xe3, 0x65, 0x00, 0x69, 0x0e,
- 0x79, 0x1d, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x7e, 0x40, 0x07, 0x61,
- 0x69, 0x6e, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe4, 0x00, 0x00,
- 0x63, 0x02, 0x68, 0x08, 0x6e, 0x11, 0x03, 0x16, 0x40, 0x06, 0x6f, 0x61,
- 0x74, 0x00, 0x40, 0x00, 0x65, 0x61, 0x72, 0x74, 0x65, 0x64, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe3, 0x64, 0x00,
- 0x6e, 0x1a, 0x74, 0x9e, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00,
- 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xec, 0x00, 0x00, 0x62, 0x02, 0x65,
- 0x11, 0x66, 0x16, 0x67, 0x25, 0x68, 0x36, 0x69, 0x47, 0x6d, 0x4c, 0x6e,
- 0x52, 0x72, 0x58, 0x73, 0x5e, 0x77, 0x65, 0x03, 0x1b, 0xe2, 0x61, 0x00,
- 0x65, 0x05, 0x40, 0x09, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x6c, 0x74, 0x00,
- 0x40, 0x07, 0x72, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x06, 0x40, 0x00,
- 0x65, 0x6c, 0x64, 0x00, 0x40, 0x08, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x72,
- 0x05, 0x40, 0x09, 0x67, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x63, 0x65, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x72, 0x00, 0x75, 0x04, 0x40, 0x06, 0x6e,
- 0x00, 0x40, 0x06, 0x73, 0x65, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0x40,
- 0x07, 0x61, 0x69, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x06, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x77, 0x61, 0x72, 0x64, 0x00,
- 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x03, 0x1c, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6c, 0x69, 0x6e,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x08, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x00, 0x77, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x40, 0x06, 0x6f,
- 0x75, 0x6e, 0x64, 0x00, 0xfb, 0x62, 0x00, 0x00, 0x64, 0x06, 0x00, 0x65,
- 0x30, 0x00, 0x66, 0x60, 0x00, 0x6c, 0x70, 0x00, 0x6d, 0x7c, 0x00, 0x6e,
- 0xb1, 0x00, 0x70, 0xe2, 0x00, 0x73, 0x00, 0x01, 0x74, 0x26, 0x01, 0x7a,
- 0x52, 0x01, 0x40, 0x08, 0x62, 0x6c, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64,
- 0x02, 0x69, 0x15, 0x6c, 0x1b, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x06, 0x40, 0x06, 0x61, 0x6b,
- 0x65, 0x00, 0x40, 0x06, 0x72, 0x6f, 0x6e, 0x00, 0x40, 0xb1, 0x6f, 0x63,
- 0x6b, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00, 0x06, 0xe3, 0x61, 0x00,
- 0x65, 0x06, 0x6f, 0x0f, 0x40, 0x09, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x06,
- 0x6e, 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x02, 0x1f, 0x00, 0x09, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x07, 0x69, 0x09, 0x6d, 0x10, 0x6e, 0x1e, 0x79, 0x24, 0x03, 0x1d, 0x40,
- 0x5e, 0x63, 0x65, 0x00, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x3b, 0xe4,
- 0x00, 0x00, 0x64, 0x02, 0x67, 0x16, 0x6e, 0x1a, 0x00, 0x09, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x73, 0x06, 0x03, 0x1e, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x09, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x70, 0x0b, 0x00, 0xe7, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x03, 0x1f, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x74, 0x0e, 0xe2,
- 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0xf4, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x06, 0x00, 0x12, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x09, 0x69, 0x6c, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x73,
- 0x02, 0x74, 0x04, 0x00, 0x09, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x79, 0x18, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0xe1,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0xf4, 0xe1, 0x7a, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x3a, 0x01, 0x72, 0xfd, 0x61, 0x00, 0x00, 0x63,
- 0x09, 0x00, 0x67, 0x18, 0x00, 0x69, 0x35, 0x00, 0x6b, 0x39, 0x00, 0x6d,
- 0x4e, 0x00, 0x6f, 0x54, 0x00, 0x70, 0x86, 0x00, 0x73, 0x92, 0x00, 0x74,
- 0xb3, 0x00, 0x75, 0xe3, 0x00, 0x76, 0xc5, 0x01, 0x77, 0xea, 0x01, 0xe2,
- 0x6e, 0x00, 0x74, 0x02, 0x00, 0x93, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x67, 0x02, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x0c, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6b,
- 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6d, 0x65, 0x74, 0x00, 0xe2,
- 0x6d, 0x00, 0x76, 0x24, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x73,
- 0x0b, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x82, 0x00,
- 0xf3, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0xe3, 0x62, 0x00, 0x67, 0x06, 0x73, 0x0d, 0x40, 0x09, 0x65, 0x61,
- 0x6b, 0x00, 0x40, 0x07, 0x72, 0x61, 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x03, 0x20, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x74, 0x19, 0xe1, 0x73, 0x00, 0xe1, 0x71, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x0c, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x0b, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x00, 0x60, 0xe5, 0x63,
- 0x00, 0x6e, 0x1d, 0x70, 0xa9, 0x73, 0xc9, 0x74, 0xd5, 0xe1, 0x68, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x59, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0xf4, 0xe1, 0x64, 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x63, 0x0c,
- 0x65, 0x21, 0x68, 0x25, 0x69, 0x2a, 0x6c, 0x2f, 0x6e, 0x35, 0x73, 0x3a,
- 0x77, 0x64, 0x03, 0x21, 0x40, 0x09, 0x72, 0x65, 0x61, 0x6b, 0x69, 0x6e,
- 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x3b, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x75, 0x74, 0x00,
- 0xe4, 0x68, 0x00, 0x6b, 0x06, 0x6d, 0x0e, 0x77, 0x1b, 0x40, 0x08, 0x65,
- 0x65, 0x74, 0x00, 0x40, 0x08, 0x65, 0x65, 0x70, 0x65, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x06, 0x65, 0x6c, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40,
- 0x07, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x72, 0x6b, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x77, 0x11, 0x02, 0x86, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x09, 0x40, 0x07, 0x67, 0x00,
- 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x93, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c,
- 0x06, 0x00, 0x3f, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe6, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6c, 0x0b, 0x6e, 0x16, 0x74, 0x21, 0x03, 0x22,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x54, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x75,
- 0x02, 0x01, 0x66, 0x40, 0x09, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0xe6, 0x62, 0x00, 0x64, 0x37,
- 0x65, 0x46, 0x66, 0x71, 0x6d, 0x81, 0x6e, 0xaf, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x73, 0x29, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x1e,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40,
- 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x01, 0x3b, 0x40, 0x07, 0x74, 0x61,
- 0x6b, 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x82, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x73,
- 0x0e, 0x00, 0x08, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03, 0x23, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x46, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x70, 0x0f, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0x19, 0x00,
- 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x06, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x0c, 0xe3, 0x67, 0x00, 0x69, 0x09, 0x74, 0x0e, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0xf3, 0x40, 0x06, 0x6f, 0x6e, 0x00,
- 0x00, 0x93, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0x62, 0x9d, 0x00, 0x65,
- 0xaa, 0x00, 0x66, 0xfb, 0x00, 0x69, 0x09, 0x01, 0x6c, 0xd3, 0x01, 0x6d,
- 0x1e, 0x02, 0x6e, 0x7c, 0x02, 0x70, 0x6a, 0x03, 0x72, 0x6f, 0x03, 0x73,
- 0x82, 0x03, 0x74, 0xc7, 0x03, 0x76, 0x17, 0x04, 0x79, 0x23, 0x04, 0x7a,
- 0x25, 0x04, 0xe4, 0x63, 0x00, 0x6e, 0x08, 0x72, 0x14, 0x76, 0x90, 0x40,
- 0x07, 0x61, 0x6d, 0x6f, 0x6c, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05,
- 0x40, 0x07, 0x6e, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x64, 0x26,
- 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe3, 0x65,
- 0x00, 0x6f, 0x0f, 0x79, 0x13, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0xb2, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x00, 0xa1, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x68, 0x0b, 0x69, 0x12, 0x72,
- 0x25, 0x73, 0x34, 0x00, 0xfa, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x3b,
- 0x00, 0x07, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x07,
- 0x68, 0x69, 0x70, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x69,
- 0x6c, 0x00, 0x40, 0x06, 0x6f, 0x6d, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x06, 0x61, 0x00, 0x40, 0x00, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x6f, 0x72,
- 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x08, 0x40, 0x06, 0x72,
- 0x69, 0x6c, 0x6c, 0x61, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x1d, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x74, 0x06, 0x77, 0x0e, 0x02, 0xa8, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x5e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x00, 0x40, 0x07, 0x6f,
- 0x72, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x68, 0x0c, 0x72, 0x13,
- 0x00, 0x93, 0x60, 0x09, 0x6f, 0x6f, 0x6b, 0x00, 0x00, 0x00, 0xff, 0xff,
- 0x40, 0x08, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x08, 0x6f, 0x6f, 0x6d,
- 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40,
- 0x55, 0x77, 0x00, 0xe5, 0x64, 0x00, 0x6c, 0x30, 0x6e, 0xa4, 0x73, 0xa9,
- 0x74, 0xad, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x07, 0x6e, 0x63, 0x65,
- 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08, 0x6c, 0x0a, 0x70, 0x10,
- 0x72, 0x16, 0x00, 0x7e, 0x40, 0x06, 0x6f, 0x6f, 0x6b, 0x00, 0x00, 0x37,
- 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0xe4, 0x64, 0x00, 0x65, 0x13, 0x6c, 0x37, 0x74, 0x49, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x68, 0x06, 0x00, 0x0f, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x09, 0x61, 0x6c, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c,
- 0x07, 0x00, 0x07, 0x40, 0x00, 0x75, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x06, 0x40,
- 0x08, 0x6d, 0x6f, 0x74, 0x00, 0x40, 0x5e, 0x74, 0x69, 0x6e, 0x65, 0x00,
- 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x11, 0x79, 0x17, 0x00, 0x07, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0x40, 0x09,
- 0x65, 0x61, 0x00, 0x40, 0x90, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x73, 0x74,
- 0x00, 0xe6, 0x61, 0x00, 0x63, 0x04, 0x64, 0x08, 0x66, 0x0d, 0x6c, 0x0f,
- 0x70, 0x33, 0x40, 0x06, 0x67, 0x00, 0x40, 0x09, 0x68, 0x00, 0x40, 0x09,
- 0x65, 0x6e, 0x00, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x79, 0x19, 0x00, 0x47, 0x40, 0x09, 0x74, 0x00, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7,
- 0x40, 0x07, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x64, 0x1d, 0x6d,
- 0x23, 0x70, 0x35, 0x73, 0x3c, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x6f, 0x05,
- 0x40, 0x08, 0x6c, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x06,
- 0x00, 0x06, 0x40, 0x06, 0x6c, 0x00, 0x40, 0x08, 0x74, 0x00, 0x40, 0x06,
- 0x72, 0x6f, 0x70, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x60, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xb2, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x66, 0x08, 0x67, 0x25, 0x6b,
- 0x2e, 0x6d, 0x37, 0x6e, 0x4c, 0x70, 0x79, 0x72, 0x8c, 0x73, 0xa3, 0x77,
- 0xd1, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x61, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x67, 0x00, 0x72, 0x11, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xe6, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x40, 0x07, 0x61, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x14, 0x79, 0x19,
- 0xe3, 0x64, 0x00, 0x6c, 0x02, 0x72, 0x04, 0x00, 0x00, 0x00, 0x09, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x63,
- 0x6b, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x69, 0x00, 0x77, 0x05, 0x40, 0x07,
- 0x6e, 0x74, 0x00, 0x40, 0x07, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x68, 0x00, 0x6c,
- 0x0d, 0x6d, 0x15, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x70, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x61, 0x6c, 0x65, 0x00,
- 0x40, 0x06, 0x70, 0x79, 0x00, 0xe3, 0x67, 0x00, 0x6e, 0x05, 0x75, 0x0a,
- 0x40, 0x82, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x65, 0x79, 0x00, 0x00, 0x09,
- 0xe3, 0x68, 0x00, 0x73, 0x16, 0x74, 0x21, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x79, 0x0b, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0x00, 0x60, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x43, 0x24,
- 0x74, 0x00, 0x00, 0x3a, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x09, 0x6f,
- 0x0e, 0x79, 0x10, 0x03, 0x25, 0x40, 0x00, 0x74, 0x6f, 0x72, 0x79, 0x00,
- 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x00, 0xf3, 0xe4, 0x00, 0x00,
- 0x6c, 0x02, 0x73, 0x18, 0x74, 0x1c, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0xf3, 0x79, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x15, 0x75, 0x1a, 0x79, 0x20, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x2c, 0x40, 0x09, 0x6e,
- 0x69, 0x70, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72,
- 0x61, 0x6c, 0x00, 0x00, 0xf3, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x08,
- 0x40, 0x08, 0x6f, 0x72, 0x00, 0x00, 0x93, 0xe1, 0x7a, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00,
- 0x07, 0xe5, 0x6d, 0x00, 0x6e, 0x4d, 0x70, 0x7a, 0x72, 0xa8, 0x76, 0xe7,
- 0xe4, 0x00, 0x00, 0x6b, 0x02, 0x6e, 0x09, 0x73, 0x3e, 0x00, 0x06, 0x40,
- 0x09, 0x68, 0x61, 0x6e, 0x61, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x28, 0xe1,
- 0x73, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x05, 0x40, 0x09, 0x75, 0x6d, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x73, 0x70, 0x65, 0x72, 0x6d, 0x00, 0x40,
- 0x08, 0x6c, 0x69, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00,
- 0x00, 0x07, 0xe3, 0x00, 0x00, 0x70, 0x02, 0x73, 0x15, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00,
- 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x74, 0x00, 0x75, 0x05, 0x79,
- 0x09, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x00, 0x06,
- 0xe3, 0x61, 0x00, 0x66, 0x15, 0x6f, 0x1d, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x61, 0x6c, 0x63, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x63, 0x00, 0x40, 0x82, 0x65, 0x00, 0xc1, 0x27, 0x53, 0xab, 0x00,
- 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x07, 0x0e, 0x0d, 0x0e, 0x59, 0x1a, 0x5b, 0x1a, 0x00, 0x00,
- 0x66, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1e, 0x00, 0x00,
- 0x03, 0x1f, 0xe9, 0x2b, 0x00, 0x00, 0xeb, 0x2b, 0x00, 0x00, 0xed, 0x2b,
- 0xff, 0x2b, 0x00, 0x00, 0x90, 0x30, 0x00, 0x00, 0x94, 0x30, 0x03, 0x26,
- 0x40, 0x00, 0x6d, 0x00, 0xc1, 0x62, 0x19, 0x37, 0x00, 0x39, 0x00, 0xb6,
- 0x00, 0x02, 0x01, 0x00, 0x00, 0x1c, 0x01, 0x29, 0x01, 0x81, 0x01, 0x88,
- 0x01, 0xc6, 0x02, 0xdc, 0x02, 0xe0, 0x02, 0x42, 0x04, 0xd4, 0x04, 0x00,
- 0x00, 0x77, 0x07, 0x00, 0x00, 0xec, 0x07, 0xf7, 0x0a, 0x4f, 0x0b, 0xf1,
- 0x0b, 0x58, 0x0c, 0x7c, 0x0c, 0x00, 0x00, 0xb3, 0x0c, 0x06, 0x0d, 0x03,
- 0x27, 0xe2, 0x65, 0x00, 0x69, 0x1e, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x06,
- 0xe2, 0x6c, 0x00, 0x74, 0x08, 0x40, 0x06, 0x69, 0x6d, 0x65, 0x6e, 0x74,
- 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x75, 0x1f, 0x03, 0x28,
- 0x40, 0x00, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x08, 0x40, 0x07, 0x69,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1e, 0xe2, 0x6c,
- 0x00, 0x74, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x6b, 0x07, 0x40,
- 0x06, 0x65, 0x6e, 0x64, 0x61, 0x00, 0xe8, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x6c, 0x13, 0x6e, 0x17, 0x73, 0x1c, 0x74, 0x21, 0x77, 0x29, 0x00,
- 0xfe, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07,
- 0x67, 0x00, 0x40, 0x00, 0x68, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x2c,
- 0x65, 0x79, 0x00, 0x40, 0x06, 0x61, 0x77, 0x00, 0x40, 0x08, 0x69, 0x76,
- 0x69, 0x73, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0xe4, 0x00,
- 0x00, 0x64, 0x02, 0x6e, 0x08, 0x73, 0x0d, 0x00, 0x00, 0x40, 0x06, 0x6f,
- 0x63, 0x6b, 0x00, 0x40, 0x00, 0x27, 0x74, 0x00, 0x40, 0x00, 0x74, 0x00,
- 0xe2, 0x6e, 0x00, 0x74, 0x06, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0x00,
- 0x09, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x69, 0x34, 0x00, 0x06, 0xe3, 0x61,
- 0x00, 0x69, 0x13, 0x6c, 0x1f, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x09, 0x00, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x69, 0x75, 0x6d, 0x00,
- 0xf3, 0x6b, 0x00, 0x00, 0x6c, 0x04, 0x00, 0x72, 0x1e, 0x00, 0x40, 0x07,
- 0x75, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x55, 0xe1, 0x74, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x04, 0x40, 0x09, 0x65, 0x00,
- 0x40, 0x09, 0x6d, 0x00, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x63, 0x33, 0x64,
- 0x42, 0x67, 0x67, 0x69, 0x6d, 0x6c, 0x74, 0x6e, 0x8b, 0x70, 0x90, 0x73,
- 0x9f, 0x79, 0xfd, 0x00, 0xb2, 0xe2, 0x61, 0x00, 0x72, 0x0d, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x08, 0x64, 0x00, 0xe2,
- 0x65, 0x00, 0x75, 0x15, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x09, 0x73, 0x68, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x06, 0x40,
- 0x07, 0x6f, 0x74, 0x68, 0x00, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x6f, 0x00,
- 0x72, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x14, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x08,
- 0x72, 0x69, 0x70, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x73, 0x73, 0x00, 0xe2, 0x6b, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06,
- 0x65, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x05, 0x40,
- 0x09, 0x63, 0x65, 0x00, 0x00, 0x06, 0xe3, 0x62, 0x00, 0x70, 0x1b, 0x74,
- 0x45, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x17, 0xe1, 0x69, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x04, 0x40, 0x08, 0x79, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe1, 0x79,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x01, 0x3b, 0xe2, 0x00, 0x00, 0x6a, 0x02, 0x00,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x07, 0x40, 0x00,
- 0x73, 0x00, 0x00, 0x06, 0x40, 0x09, 0x65, 0x00, 0xfb, 0x61, 0x00, 0x00,
- 0x62, 0x04, 0x00, 0x63, 0x0a, 0x00, 0x65, 0x10, 0x00, 0x66, 0x12, 0x00,
- 0x69, 0x75, 0x00, 0x6c, 0x8c, 0x00, 0x6f, 0x08, 0x01, 0x74, 0x18, 0x01,
- 0x76, 0x36, 0x01, 0x79, 0x3a, 0x01, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x06,
- 0x65, 0x72, 0x64, 0x00, 0x40, 0x00, 0x79, 0x6f, 0x6e, 0x00, 0x03, 0x29,
- 0xe6, 0x00, 0x00, 0x62, 0x02, 0x68, 0x08, 0x70, 0x27, 0x74, 0x3a, 0x77,
- 0x49, 0x00, 0x07, 0x40, 0x06, 0x61, 0x63, 0x6b, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6d, 0x65, 0x00, 0x40, 0x09, 0x6e,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x06, 0x75, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x69,
- 0x73, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x1a, 0x6f, 0x20, 0x75,
- 0x32, 0x77, 0x6a, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x6a, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x59, 0x61, 0x72, 0x6b, 0x00, 0xe2,
- 0x6f, 0x00, 0x77, 0x02, 0x03, 0x2a, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x3a, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x16, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06, 0x63,
- 0x00, 0x40, 0x06, 0x61, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x6e,
- 0x07, 0x00, 0x55, 0x40, 0x06, 0x65, 0x6e, 0x00, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x12, 0x00, 0xfe, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0xec, 0x40, 0x08, 0x65, 0x63, 0x6b, 0x00, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x40, 0x09, 0x61, 0x72,
- 0x64, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x16, 0x6d, 0x1b, 0x70,
- 0x59, 0x73, 0x6a, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x0f, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x09, 0x65, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x29, 0x6f,
- 0x2e, 0x79, 0x33, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe5, 0x00,
- 0x00, 0x65, 0x02, 0x68, 0x06, 0x6c, 0x0c, 0x74, 0x12, 0x03, 0x2b, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x06, 0x65, 0x61, 0x64, 0x00, 0x40, 0x06, 0x6f,
- 0x63, 0x6b, 0x00, 0x40, 0x09, 0x6f, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x63, 0x6b, 0x00, 0x00, 0x60, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x59, 0x40, 0x37, 0x64,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x09, 0x72,
- 0x00, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x41, 0x2f, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xf4, 0x64, 0x00, 0x00, 0x67, 0x29, 0x02, 0x6b,
- 0x75, 0x02, 0x73, 0x91, 0x02, 0xc1, 0x27, 0x53, 0xab, 0x00, 0xad, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0xdd, 0x00,
- 0x00, 0x00, 0x03, 0x01, 0x07, 0x01, 0x0c, 0x01, 0x11, 0x01, 0x20, 0x01,
- 0x00, 0x00, 0x61, 0x01, 0x6b, 0x01, 0x7e, 0x01, 0x00, 0x00, 0x98, 0x01,
- 0xa6, 0x01, 0x00, 0x00, 0xac, 0x01, 0xb2, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xed, 0x01, 0x00, 0x00, 0x15, 0x02, 0x01, 0xfe, 0x40, 0x00,
- 0x73, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x13, 0x6f, 0x18, 0x72, 0x1d, 0xe3,
- 0x67, 0x00, 0x6c, 0x02, 0x72, 0x06, 0x00, 0x06, 0x40, 0x09, 0x6c, 0x00,
- 0x40, 0x06, 0x72, 0x6f, 0x77, 0x00, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0x40,
- 0x09, 0x6f, 0x6b, 0x00, 0x40, 0x08, 0x61, 0x6b, 0x65, 0x00, 0xe4, 0x61,
- 0x00, 0x6c, 0x0c, 0x72, 0x12, 0x75, 0x18, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x06, 0x00, 0x09, 0x40, 0x09, 0x61, 0x73, 0x70,
- 0x00, 0x40, 0x2c, 0x61, 0x66, 0x74, 0x00, 0x40, 0x55, 0x66, 0x66, 0x00,
- 0x40, 0x5d, 0x64, 0x00, 0x40, 0x06, 0x75, 0x6c, 0x00, 0x40, 0x06, 0x75,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6c, 0x64, 0x00,
- 0x40, 0x09, 0x6c, 0x64, 0x00, 0xe4, 0x63, 0x00, 0x6c, 0x28, 0x6e, 0x2c,
- 0x77, 0x32, 0xe2, 0x61, 0x00, 0x72, 0x1d, 0xe1, 0x70, 0x00, 0xe2, 0x00,
- 0x00, 0x70, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x61, 0x66, 0x74, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0x40, 0x09,
- 0x65, 0x72, 0x63, 0x68, 0x69, 0x65, 0x66, 0x00, 0xe1, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x72, 0x07, 0x00, 0xa5, 0x40, 0x09, 0x61, 0x72,
- 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01,
- 0xa1, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x75, 0x00, 0x76, 0x04, 0x40, 0x06,
- 0x74, 0x00, 0x40, 0x08, 0x65, 0x72, 0x00, 0x40, 0x0b, 0x69, 0x63, 0x6b,
- 0x00, 0x40, 0x09, 0x61, 0x69, 0x6c, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x04,
- 0x68, 0x08, 0x6f, 0x0e, 0x70, 0x21, 0x74, 0x28, 0x40, 0x06, 0x77, 0x00,
- 0x40, 0x06, 0x74, 0x00, 0x43, 0x2c, 0x61, 0x6b, 0x65, 0x00, 0xe1, 0x6d,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xd3, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x72, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x0e, 0xe2,
- 0x72, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6b, 0x00, 0x40, 0x00, 0x65, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x05,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x01, 0x7c, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x64,
- 0x06, 0x65, 0x0b, 0x69, 0x0f, 0x6d, 0x14, 0x6e, 0x21, 0x6f, 0x27, 0x75,
- 0x35, 0x02, 0x6c, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x67, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09,
- 0x61, 0x69, 0x6c, 0x00, 0xe2, 0x75, 0x00, 0x76, 0x04, 0x40, 0x06, 0x74,
- 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x09, 0x70, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x11, 0x00, 0xe6, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x03, 0x2d, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02,
- 0x6c, 0x1e, 0x70, 0x3b, 0x00, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x7a, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x13, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x69, 0x64, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x19, 0x79, 0x28, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x03, 0x2e, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x37, 0x79, 0x00, 0x40, 0xdb, 0x65, 0x73,
- 0x73, 0x00, 0x02, 0x76, 0xfe, 0x61, 0x00, 0x00, 0x62, 0x21, 0x00, 0x64,
- 0x3f, 0x00, 0x65, 0x4a, 0x01, 0x69, 0x7b, 0x01, 0x6b, 0x81, 0x01, 0x6c,
- 0x83, 0x01, 0x6d, 0x9d, 0x01, 0x6e, 0x2f, 0x02, 0x70, 0x43, 0x02, 0x72,
- 0x86, 0x02, 0x73, 0xb5, 0x02, 0x74, 0xc5, 0x02, 0x76, 0xc7, 0x02, 0xe2,
- 0x6e, 0x00, 0x73, 0x06, 0x40, 0x82, 0x67, 0x75, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x00, 0x80, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x07, 0x40, 0x06, 0x6e, 0x67, 0x65, 0x72, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x59, 0x40, 0x08, 0x61, 0x73, 0x74, 0x65,
- 0x72, 0x00, 0xec, 0x00, 0x00, 0x62, 0x02, 0x63, 0x23, 0x65, 0x34, 0x68,
- 0x47, 0x69, 0x81, 0x6c, 0x98, 0x6e, 0x9f, 0x73, 0xa5, 0x74, 0xc0, 0x77,
- 0xce, 0x79, 0xf0, 0x03, 0x2f, 0xe2, 0x61, 0x00, 0x6f, 0x0d, 0xe2, 0x63,
- 0x00, 0x6c, 0x04, 0x40, 0x09, 0x6b, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x05, 0x40, 0x07, 0x72, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x72, 0x00, 0x76, 0x04, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x02, 0x2d, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37,
- 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x09, 0x74, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x13, 0xe1, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x68, 0x00, 0x6c, 0x06, 0x6e, 0x0a, 0x40, 0x07, 0x6f, 0x6f, 0x64,
- 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x69, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x63, 0x00, 0x68, 0x09, 0x74, 0x0e, 0x40, 0x00, 0x72, 0x61, 0x62,
- 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x69, 0x70, 0x00, 0x40, 0x06, 0x61,
- 0x6e, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x63, 0x6b,
- 0x00, 0x40, 0x06, 0x70, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x05, 0x6f, 0x0b,
- 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x00, 0x72, 0x65, 0x64, 0x00, 0xe2,
- 0x6f, 0x00, 0x72, 0x04, 0x40, 0x06, 0x64, 0x00, 0x40, 0x00, 0x6b, 0x69,
- 0x6e, 0x67, 0x00, 0x00, 0x96, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x14,
- 0x6d, 0x26, 0x00, 0x82, 0xe2, 0x65, 0x00, 0x72, 0x05, 0x40, 0x09, 0x6c,
- 0x6c, 0x00, 0x40, 0x00, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x65, 0x64, 0x00, 0x00, 0x06, 0x40, 0x08, 0x63, 0x6f, 0x74, 0x00,
- 0x00, 0x72, 0xe2, 0x65, 0x00, 0x6f, 0x07, 0x40, 0x06, 0x71, 0x75, 0x69,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06,
- 0x40, 0x07, 0x79, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x66, 0x06, 0x6c,
- 0x19, 0x6f, 0x2f, 0x00, 0x55, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x4e, 0xe5, 0x63,
- 0x00, 0x65, 0x13, 0x6f, 0x17, 0x75, 0x2a, 0x7a, 0x2e, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x3f, 0x00, 0x07, 0x00, 0x84, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0xf1, 0x40, 0x00,
- 0x73, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x73, 0x18, 0x79,
- 0x36, 0x00, 0x55, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x05, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x06, 0xe4, 0x69, 0x00,
- 0x6f, 0x0e, 0x75, 0x12, 0x79, 0x24, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40,
- 0x09, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x2c, 0x77, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0xed, 0x00, 0x00, 0x01, 0x4b, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x07, 0xe5, 0x68, 0x00, 0x6e, 0x13, 0x70, 0x18, 0x73, 0x1a,
- 0x74, 0x28, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x74, 0x07, 0x03, 0x30, 0x40,
- 0x07, 0x73, 0x68, 0x00, 0x40, 0x06, 0x61, 0x67, 0x00, 0x40, 0x00, 0x27,
- 0x74, 0x00, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x5e, 0x65,
- 0x00, 0x40, 0x06, 0x63, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x0b, 0x79, 0x1a, 0x03, 0x31, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06,
- 0x01, 0x20, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe8, 0x00, 0x00, 0x62, 0x02,
- 0x63, 0x10, 0x65, 0x45, 0x70, 0x6d, 0x72, 0x72, 0x73, 0x77, 0x74, 0x7e,
- 0x01, 0x05, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x08, 0x6e, 0x64, 0x00,
- 0x40, 0x09, 0x78, 0x00, 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02,
- 0x65, 0x08, 0x69, 0x1d, 0x77, 0x22, 0x00, 0x47, 0x40, 0x09, 0x61, 0x63,
- 0x6b, 0x00, 0xe4, 0x63, 0x00, 0x64, 0x04, 0x72, 0x06, 0x74, 0x0a, 0x40,
- 0x06, 0x6b, 0x00, 0x00, 0x37, 0x40, 0x06, 0x79, 0x00, 0x00, 0x06, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x61, 0x79, 0x00, 0xe4, 0x00, 0x00,
- 0x66, 0x02, 0x6d, 0x15, 0x72, 0x1d, 0x00, 0x09, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x00, 0x00,
- 0x07, 0x40, 0x08, 0x69, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x64, 0x00, 0x40,
- 0x08, 0x74, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe5, 0x62, 0x00, 0x67, 0x06, 0x6c, 0x22, 0x6e, 0x3b, 0x74, 0x56,
- 0x40, 0x06, 0x65, 0x72, 0x6b, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x0b, 0x00, 0xfe, 0x40, 0x07, 0x67,
- 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x65, 0x72, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x65, 0x75, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x1b, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x0d, 0x01, 0x7f, 0xe2, 0x00,
- 0x00, 0x27, 0x02, 0x00, 0x06, 0x40, 0x00, 0x74, 0x00, 0x40, 0x06, 0x73,
- 0x61, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x63, 0x00, 0xe4, 0x00, 0x00, 0x6b,
- 0x02, 0x73, 0x22, 0x74, 0x27, 0x00, 0x95, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x09, 0x68, 0x6f,
- 0x72, 0x6e, 0x00, 0xe7, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x08, 0x6d, 0x0e,
- 0x72, 0x1e, 0x73, 0x2e, 0x77, 0x3e, 0x00, 0x95, 0x40, 0x06, 0x6f, 0x63,
- 0x6b, 0x00, 0x40, 0x06, 0x6f, 0x66, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x07, 0x40, 0x00, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x77, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x64, 0x04, 0x40, 0x09, 0x6b, 0x00,
- 0x40, 0x09, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x05, 0x40, 0x09, 0x65,
- 0x64, 0x00, 0x40, 0x06, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x00, 0x69, 0x72,
- 0x65, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x12, 0x69, 0x29, 0x6d, 0x3e, 0x79,
- 0x43, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x2c, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02,
- 0x72, 0x0e, 0x02, 0x7a, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x40,
- 0x09, 0x75, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73,
- 0x00, 0x00, 0x07, 0x40, 0x00, 0x61, 0x74, 0x00, 0x00, 0xf4, 0x40, 0x00,
- 0x71, 0x72, 0x73, 0x00, 0xc1, 0x27, 0x53, 0xab, 0x00, 0xad, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xe8, 0x04, 0x39,
- 0x05, 0x8f, 0x05, 0xd2, 0x05, 0xef, 0x05, 0x00, 0x00, 0x0d, 0x06, 0x00,
- 0x00, 0x00, 0x00, 0x5c, 0x06, 0x7c, 0x07, 0x61, 0x08, 0x00, 0x00, 0xae,
- 0x08, 0x00, 0x00, 0x09, 0x09, 0x46, 0x0b, 0x80, 0x0b, 0xd6, 0x0b, 0x00,
- 0x00, 0xf9, 0x0b, 0x04, 0x0c, 0x40, 0x0c, 0x00, 0x07, 0xe2, 0x64, 0x00,
- 0x6c, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0xf6, 0x64, 0x00, 0x00,
- 0x6c, 0xf9, 0x01, 0x70, 0x45, 0x02, 0x72, 0x47, 0x02, 0x74, 0x55, 0x03,
- 0x76, 0xc4, 0x03, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39, 0x00, 0x3f, 0x00,
- 0x69, 0x00, 0x82, 0x00, 0x89, 0x00, 0x8d, 0x00, 0x94, 0x00, 0x9a, 0x00,
- 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x00, 0x08, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x29, 0x01, 0x40, 0x01, 0x5b, 0x01, 0x6a, 0x01, 0xc8, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0xd1, 0x01, 0x00, 0x00, 0xf7, 0x01, 0x01, 0xc0,
- 0x40, 0x09, 0x63, 0x68, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x18, 0x75,
- 0x1e, 0xe1, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x02, 0x00, 0x09, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x08, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x61, 0x72, 0x64, 0x00, 0x40, 0x3a, 0x74, 0x74, 0x00,
- 0xe3, 0x61, 0x00, 0x68, 0x05, 0x6f, 0x0c, 0x40, 0x08, 0x73, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x65, 0x73, 0x65, 0x00, 0x40, 0x08, 0x75, 0x6e, 0x74,
- 0x00, 0x40, 0x09, 0x72, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x00, 0x69, 0x72, 0x73, 0x74, 0x00, 0x40, 0x07, 0x65, 0x61, 0x72,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0xe4, 0x61, 0x00, 0x65, 0x0d, 0x69, 0x12, 0x6f, 0x28, 0xe2, 0x6d,
- 0x00, 0x6e, 0x04, 0x40, 0x09, 0x70, 0x00, 0x40, 0x09, 0x64, 0x00, 0x40,
- 0x00, 0x73, 0x73, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x68,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5,
- 0x00, 0x07, 0xe2, 0x63, 0x00, 0x6e, 0x04, 0x40, 0x09, 0x6b, 0x00, 0x40,
- 0x00, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0d, 0x69, 0x11, 0xe2, 0x6e,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x09, 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x68, 0x00, 0x69, 0x06, 0x40, 0x09, 0x6f, 0x6e, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x63, 0x65, 0x00, 0x00, 0x06, 0xe1,
- 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x7a,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00,
- 0x40, 0x07, 0x6f, 0x6d, 0x00, 0xe5, 0x63, 0x00, 0x65, 0x12, 0x68, 0x16,
- 0x6d, 0x27, 0x74, 0x34, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x66,
- 0x00, 0x76, 0x02, 0x00, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x04, 0x40, 0x06, 0x70, 0x00, 0x40,
- 0x06, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x6f,
- 0x0d, 0x72, 0x12, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x6c, 0x00,
- 0x40, 0x06, 0x64, 0x00, 0x40, 0x06, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x6f,
- 0x6e, 0x67, 0x00, 0x40, 0x08, 0x65, 0x61, 0x63, 0x68, 0x65, 0x72, 0x00,
- 0xe3, 0x61, 0x00, 0x69, 0x15, 0x6f, 0x1a, 0xe3, 0x69, 0x00, 0x74, 0x06,
- 0x79, 0x0c, 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x73, 0x00, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x72,
- 0x64, 0x00, 0x00, 0xf4, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x74, 0x0b, 0x03,
- 0x32, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0xe1, 0x68,
- 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x66, 0x08, 0x69, 0x1b, 0x79, 0x2a,
- 0x00, 0x07, 0x40, 0x00, 0x61, 0x72, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x37, 0x79, 0x00,
- 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x03, 0x33, 0x00, 0x55, 0xe7, 0x00,
- 0x00, 0x64, 0x02, 0x65, 0x04, 0x69, 0x08, 0x6b, 0x0d, 0x73, 0x12, 0x74,
- 0x26, 0x03, 0x34, 0x01, 0xca, 0x40, 0x06, 0x72, 0x00, 0x40, 0x75, 0x6e,
- 0x67, 0x00, 0x40, 0x5b, 0x65, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x76, 0x40,
- 0x00, 0x73, 0x00, 0xed, 0x00, 0x00, 0x61, 0x02, 0x62, 0x08, 0x65, 0x29,
- 0x66, 0x2d, 0x68, 0x33, 0x69, 0x4e, 0x6c, 0x5d, 0x72, 0x7a, 0x73, 0x83,
- 0x74, 0xa3, 0x77, 0xaa, 0x79, 0xbc, 0x00, 0x06, 0x40, 0x09, 0x63, 0x68,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x72, 0x05, 0x75, 0x15, 0x40, 0x09, 0x61,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x41, 0x25, 0x61, 0x6b, 0x00,
- 0x40, 0x00, 0x6b, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x6e, 0x00, 0x40,
- 0xf5, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x6c, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x72, 0x02, 0x73, 0x07, 0x00, 0x07, 0x40, 0x08, 0x75, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x09, 0x6e, 0x64,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x65, 0x6e,
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x13, 0xe1, 0x63,
- 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x72, 0x69, 0x6e, 0x67, 0x73,
- 0x00, 0x40, 0x09, 0x68, 0x72, 0x6f, 0x62, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x08, 0x40, 0x00, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f,
- 0x64, 0x00, 0x03, 0x35, 0xe8, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x68,
- 0x18, 0x69, 0x44, 0x70, 0x49, 0x73, 0x50, 0x77, 0x58, 0x01, 0xf9, 0x40,
- 0x00, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x0b, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x37, 0x40, 0x00, 0x79, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x73, 0x23, 0x03, 0x36, 0xe2, 0x6e, 0x00, 0x72, 0x1a, 0xe3,
- 0x00, 0x00, 0x64, 0x02, 0x69, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x6d,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x68, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x72, 0x6f, 0x6f, 0x66, 0x00, 0x40, 0x07, 0x74, 0x72, 0x6f, 0x6b, 0x65,
- 0x00, 0x40, 0x08, 0x61, 0x76, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x22,
- 0x79, 0x31, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x19, 0x00, 0x7e, 0xe4,
- 0x00, 0x00, 0x6c, 0x02, 0x73, 0x06, 0x77, 0x08, 0x00, 0x56, 0x40, 0x60,
- 0x79, 0x00, 0x00, 0x07, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00, 0x00, 0x07,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x73, 0x0b, 0x77, 0x10,
- 0x02, 0x0e, 0x40, 0x00, 0x65, 0x61, 0x72, 0x74, 0x65, 0x64, 0x00, 0x40,
- 0x00, 0x65, 0x74, 0x00, 0x40, 0x09, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00,
- 0xe2, 0x6b, 0x00, 0x74, 0x1a, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x05,
- 0x6f, 0x15, 0x40, 0x06, 0x72, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3,
- 0x67, 0x00, 0x6d, 0x06, 0x72, 0x0d, 0x40, 0x06, 0x72, 0x61, 0x6d, 0x00,
- 0x40, 0x09, 0x65, 0x74, 0x65, 0x72, 0x00, 0x00, 0x2c, 0xe2, 0x67, 0x00,
- 0x6f, 0x36, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x72, 0x21,
- 0x00, 0x7e, 0xe1, 0x6f, 0x00, 0xe2, 0x67, 0x00, 0x70, 0x02, 0x00, 0x09,
- 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00,
- 0x6f, 0x02, 0x00, 0x07, 0x40, 0x06, 0x77, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xe3,
- 0x64, 0x00, 0x68, 0x2a, 0x6c, 0x2f, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x66,
- 0x06, 0x6c, 0x0b, 0x00, 0x55, 0x40, 0x37, 0x64, 0x00, 0x40, 0x3b, 0x75,
- 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x2c, 0x61, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x55,
- 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x79, 0x11, 0x00, 0x55, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe2,
- 0x65, 0x00, 0x69, 0x14, 0xe1, 0x6d, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00, 0x63, 0x00, 0x00, 0x07,
- 0x40, 0x06, 0x72, 0x61, 0x00, 0xe5, 0x66, 0x00, 0x67, 0x05, 0x6e, 0x16,
- 0x72, 0x2c, 0x73, 0x40, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x03, 0x37, 0x41, 0x20,
- 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x07, 0x00, 0x09, 0x40, 0x09, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x2c, 0x74, 0x00,
- 0xf7, 0x64, 0x00, 0x00, 0x69, 0x02, 0x00, 0x6c, 0x4c, 0x00, 0x6d, 0x97,
- 0x00, 0x6f, 0xb4, 0x00, 0x70, 0xb8, 0x00, 0x76, 0x06, 0x01, 0x00, 0x00,
- 0xe5, 0x63, 0x00, 0x6f, 0x16, 0x70, 0x2b, 0x75, 0x39, 0x78, 0x3d, 0xe3,
- 0x61, 0x00, 0x65, 0x04, 0x6f, 0x08, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x93, 0x70, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x09, 0x40, 0x00, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x63, 0x00, 0x40,
- 0x06, 0x72, 0x6f, 0x70, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40,
- 0x08, 0x64, 0x00, 0x40, 0x09, 0x72, 0x74, 0x00, 0x40, 0x07, 0x6d, 0x00,
- 0x00, 0x07, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x65, 0x0d, 0x68,
- 0x14, 0x69, 0x1a, 0x6f, 0x33, 0x75, 0x35, 0x00, 0x07, 0x40, 0x00, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x09, 0x61, 0x74, 0x00, 0x40, 0x07, 0x62, 0x6f,
- 0x72, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x65, 0x00, 0xe2, 0x6f, 0x00,
- 0x73, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x76, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x06,
- 0x00, 0x09, 0x40, 0xb1, 0x74, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x66, 0x06, 0x69, 0x19, 0x6c,
- 0x1e, 0x6d, 0x3b, 0x02, 0xb5, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x36, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x13, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6e,
- 0x65, 0x00, 0x40, 0x06, 0x61, 0x74, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00,
- 0xe9, 0x00, 0x00, 0x61, 0x02, 0x65, 0x33, 0x69, 0x35, 0x6c, 0x59, 0x6d,
- 0x68, 0x6f, 0x7b, 0x70, 0xc8, 0x73, 0xca, 0x00, 0x06, 0xe1, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14,
- 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0x00, 0x07,
- 0xe1, 0x73, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6e, 0x65, 0x00, 0x40, 0x06,
- 0x63, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x67,
- 0x00, 0x70, 0x08, 0x72, 0x20, 0x73, 0x3e, 0x40, 0x07, 0x6c, 0x6f, 0x62,
- 0x69, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00,
- 0x07, 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x0e, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x82,
- 0x40, 0x00, 0x63, 0x00, 0x40, 0x09, 0x69, 0x64, 0x00, 0x40, 0x09, 0x74,
- 0x61, 0x74, 0x00, 0x00, 0x14, 0x40, 0x47, 0x74, 0x69, 0x74, 0x63, 0x68,
- 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x6e, 0x33, 0x70, 0x37, 0x74, 0x3d,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x68, 0x1c, 0xe2, 0x00, 0x00, 0x66, 0x02,
- 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x74, 0x00, 0x77,
- 0x04, 0x40, 0x00, 0x68, 0x00, 0x40, 0x00, 0x61, 0x72, 0x64, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x2c, 0x61, 0x00, 0x40, 0xad, 0x65, 0x63, 0x6b,
- 0x00, 0x40, 0x00, 0x61, 0x69, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x70,
- 0x24, 0x74, 0x32, 0x00, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x05, 0x40, 0x07,
- 0x69, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0c, 0xe2, 0x63, 0x00, 0x74,
- 0x02, 0x00, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0x40, 0x08, 0x63, 0x79,
- 0x74, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x67, 0x00, 0x74,
- 0x11, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x68, 0x6c, 0x6f, 0x6e,
- 0x00, 0xfd, 0x61, 0x00, 0x00, 0x62, 0x1d, 0x00, 0x63, 0x6c, 0x00, 0x64,
- 0x74, 0x00, 0x65, 0x91, 0x00, 0x69, 0x22, 0x01, 0x6d, 0x36, 0x01, 0x6e,
- 0x80, 0x01, 0x6f, 0x9d, 0x01, 0x70, 0xd3, 0x01, 0x72, 0xf5, 0x01, 0x73,
- 0x0b, 0x02, 0x74, 0x11, 0x02, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x72, 0x0a, 0x00, 0x2c, 0x40, 0x37,
- 0x64, 0x00, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x20, 0x00, 0x09, 0xe3, 0x63, 0x00, 0x67, 0x07,
- 0x6c, 0x0b, 0x40, 0x00, 0x65, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x08, 0x40, 0x09, 0x73, 0x74,
- 0x00, 0xe2, 0x63, 0x00, 0x76, 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe1,
- 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x00, 0x75, 0x6c, 0x65, 0x61, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x06, 0x00, 0xfe, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x13, 0x64, 0x17, 0x69, 0x29, 0x6f, 0x3a, 0x73, 0x43, 0x74, 0x47, 0x75,
- 0x67, 0x77, 0x76, 0x00, 0x07, 0xe2, 0x62, 0x00, 0x66, 0x06, 0x40, 0x08,
- 0x6f, 0x75, 0x74, 0x00, 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x79,
- 0x05, 0x40, 0x00, 0x72, 0x79, 0x00, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x66, 0x74, 0x65, 0x72,
- 0x00, 0xe2, 0x66, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06,
- 0x79, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0e, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x66, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x65, 0x00, 0xe2, 0x6e,
- 0x00, 0x70, 0x05, 0x40, 0x00, 0x74, 0x6f, 0x00, 0x40, 0x00, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x69, 0x74, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x62, 0x00, 0x67, 0x05, 0x40, 0x54, 0x6c, 0x65, 0x00, 0x40,
- 0x09, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x20, 0x69, 0x34, 0xe1, 0x70,
- 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b,
- 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0x40, 0x09, 0x67, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe3,
- 0x00, 0x00, 0x6c, 0x02, 0x74, 0x04, 0x00, 0x06, 0x00, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x6e, 0x2b, 0x00, 0x07, 0x40, 0x00, 0x73,
- 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x11, 0x73, 0x1a, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x00, 0x06, 0x40, 0x07,
- 0x6d, 0x00, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x6c, 0x66, 0x00, 0x40, 0x07, 0x7a, 0x00, 0xe2, 0x69,
- 0x00, 0x73, 0x2f, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00,
- 0x74, 0x10, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x00, 0x3b, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x38, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x36, 0x67, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x67, 0x11,
- 0x73, 0x29, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x78, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x78,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x86, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00,
- 0x09, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x48, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x59, 0xe4, 0x64, 0x00, 0x67, 0x09, 0x6d, 0x21, 0x6e, 0x28,
- 0x40, 0x08, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x00, 0xe2, 0x6f, 0x00,
- 0x72, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x6d, 0x00, 0x40, 0x06, 0x65,
- 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x00, 0x00, 0x40, 0x06, 0x61, 0x79, 0x00, 0x00, 0x00, 0xe2, 0x74,
- 0x00, 0x77, 0x02, 0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0xc1, 0x61, 0x19,
- 0x37, 0x00, 0x39, 0x00, 0x3f, 0x00, 0x71, 0x00, 0xa3, 0x00, 0xeb, 0x00,
- 0x00, 0x00, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x01, 0x15, 0x02,
- 0x28, 0x02, 0x84, 0x02, 0x91, 0x02, 0x00, 0x00, 0xf7, 0x02, 0x00, 0x00,
- 0x72, 0x03, 0xa9, 0x03, 0x3f, 0x04, 0x00, 0x00, 0x91, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x95, 0x04, 0x00, 0x1b, 0x40, 0x09, 0x74, 0x75, 0x73, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x24, 0x40, 0x09, 0x63, 0x68, 0x69,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x09, 0x73, 0x63, 0x75,
- 0x73, 0x00, 0xe2, 0x63, 0x00, 0x6b, 0x1b, 0xe2, 0x6f, 0x00, 0x75, 0x12,
- 0xe1, 0x75, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x01, 0x20, 0x00, 0x00, 0x40, 0x95, 0x70, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x6f, 0x06, 0x00, 0x09, 0x40, 0x06, 0x79, 0x00, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x65, 0x07, 0x69,
- 0x3a, 0x00, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x62, 0x08, 0x6f, 0x0f, 0x72, 0x26, 0x02, 0x7a, 0x40, 0x06, 0x77,
- 0x61, 0x79, 0x00, 0x40, 0x00, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe1, 0x75,
- 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x09, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72, 0x07, 0x00,
- 0x08, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x1e, 0xe1,
- 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x0e, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x3b, 0x6c, 0x00, 0x00, 0x06, 0xe1, 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x79, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x73, 0x06, 0x00, 0x07, 0x40, 0x09, 0x63, 0x00, 0x00, 0x00, 0xe1,
- 0x68, 0x00, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x63, 0x1e, 0x66, 0x25, 0x68,
- 0x2e, 0x6c, 0x4a, 0x6e, 0x74, 0x72, 0x7a, 0x73, 0x80, 0x74, 0x82, 0x77,
- 0x88, 0x03, 0x38, 0xe3, 0x61, 0x00, 0x6f, 0x05, 0x72, 0x10, 0x40, 0x06,
- 0x6c, 0x6c, 0x00, 0xe2, 0x72, 0x00, 0x79, 0x04, 0x40, 0x00, 0x6e, 0x00,
- 0x00, 0x09, 0x40, 0x06, 0x6f, 0x77, 0x00, 0x40, 0x09, 0x68, 0x61, 0x69,
- 0x72, 0x00, 0x40, 0x00, 0x61, 0x6c, 0x75, 0x74, 0x69, 0x6e, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x11, 0xe1, 0x6e, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe6, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x64, 0x00, 0x00, 0x00, 0x40,
- 0x3a, 0x61, 0x69, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62,
- 0x00, 0x63, 0x02, 0x00, 0x00, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x00, 0xe4, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xa5, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00,
- 0x6c, 0x22, 0x74, 0x53, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x69, 0x09, 0x6f, 0x10, 0x73,
- 0x15, 0x74, 0x1b, 0x79, 0x20, 0x00, 0x09, 0x40, 0x06, 0x69, 0x6c, 0x6c,
- 0x79, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x63,
- 0x6b, 0x00, 0x40, 0x06, 0x69, 0x64, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x70,
- 0x00, 0x01, 0x0c, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08,
- 0x40, 0x00, 0x65, 0x6c, 0x66, 0x00, 0xe3, 0x64, 0x00, 0x67, 0x3a, 0x74,
- 0x48, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x10, 0x71, 0x16, 0x72, 0x1f,
- 0x73, 0x26, 0x00, 0xe6, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xed, 0x40, 0x37, 0x64, 0x00, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00,
- 0x40, 0x09, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0x00, 0x40, 0x06, 0x61,
- 0x6e, 0x63, 0x65, 0x00, 0x40, 0x07, 0x69, 0x67, 0x68, 0x74, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0xf1, 0x40, 0x00, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfe, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00,
- 0xe6, 0x00, 0x00, 0x62, 0x02, 0x68, 0x1b, 0x6e, 0x24, 0x70, 0x2a, 0x73,
- 0x68, 0x03, 0x39, 0xe2, 0x61, 0x00, 0x6f, 0x0f, 0xe1, 0x74, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x09, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x75, 0x67, 0x67, 0x65, 0x72, 0x73,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x0f,
- 0x6f, 0x1a, 0x79, 0x33, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x70,
- 0x09, 0x00, 0x06, 0x40, 0x06, 0x72, 0x6f, 0x6d, 0x65, 0x00, 0x40, 0x09,
- 0x6f, 0x74, 0x61, 0x6d, 0x75, 0x73, 0x00, 0x00, 0x00, 0x40, 0x09, 0x74,
- 0x65, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x07, 0x73, 0x1a, 0x40, 0x00,
- 0x67, 0x61, 0x6e, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x6c, 0x06,
- 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x67, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x73,
- 0x00, 0x74, 0x02, 0x00, 0x47, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x09,
- 0x72, 0x66, 0x00, 0x00, 0x40, 0x09, 0x6d, 0x69, 0x6e, 0x65, 0x00, 0xe3,
- 0x67, 0x00, 0x6c, 0x06, 0x72, 0x18, 0x40, 0x09, 0x72, 0x61, 0x6d, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x79, 0x37, 0xe3,
- 0x61, 0x00, 0x63, 0x04, 0x6f, 0x16, 0x40, 0x09, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04,
- 0x40, 0x09, 0x72, 0x00, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x68, 0x2a, 0x74,
- 0x3b, 0x00, 0x06, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65,
- 0x06, 0x68, 0x0a, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x82, 0x65, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40, 0x00,
- 0x6d, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39, 0x00, 0x8d, 0x00, 0xf2,
- 0x00, 0x08, 0x01, 0x18, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x85,
- 0x01, 0x00, 0x00, 0x92, 0x01, 0xb4, 0x01, 0xa8, 0x02, 0x01, 0x05, 0xd4,
- 0x05, 0x96, 0x06, 0x00, 0x00, 0xee, 0x06, 0x3d, 0x09, 0x02, 0x0a, 0xcb,
- 0x0a, 0x58, 0x0c, 0x74, 0x0c, 0x00, 0x00, 0xd1, 0x0c, 0x03, 0x3a, 0xe3,
- 0x67, 0x00, 0x72, 0x05, 0x78, 0x42, 0x40, 0x09, 0x69, 0x65, 0x00, 0xe5,
- 0x64, 0x00, 0x66, 0x12, 0x69, 0x19, 0x73, 0x20, 0x79, 0x30, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x03, 0x3b, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x72, 0x6f, 0x73, 0x74, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x03, 0x3c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x3b,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe5,
- 0x00, 0x00, 0x62, 0x02, 0x67, 0x2e, 0x6e, 0x36, 0x6f, 0x58, 0x00, 0x06,
- 0xe3, 0x69, 0x00, 0x6c, 0x04, 0x79, 0x10, 0x40, 0x08, 0x74, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x68, 0x02, 0x69, 0x09, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x72,
- 0x73, 0x65, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x62,
- 0x6c, 0x69, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x93, 0x69,
- 0x6c, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x08,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x00, 0x09, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x73, 0x06, 0x00, 0x47, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x68, 0x6f,
- 0x70, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40, 0x06, 0x65,
- 0x70, 0x6f, 0x64, 0x67, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x64,
- 0x08, 0x69, 0x0e, 0x72, 0x13, 0x00, 0x06, 0x40, 0x06, 0x61, 0x6b, 0x65,
- 0x00, 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x00, 0x07, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x62, 0x06, 0x67, 0x0c, 0x73,
- 0x22, 0x74, 0x29, 0x77, 0x38, 0x00, 0x06, 0x40, 0x06, 0x6e, 0x00, 0x40,
- 0x06, 0x61, 0x63, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x00, 0x67, 0x00, 0x40,
- 0x3b, 0x68, 0x00, 0x40, 0x06, 0x68, 0x65, 0x61, 0x64, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x04, 0x41, 0x1a, 0x65, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x61, 0x73, 0x68, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x04,
- 0x40, 0x5b, 0x6b, 0x00, 0x40, 0x93, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x75, 0x17, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x0b, 0x00, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe8, 0x64, 0x00, 0x65, 0x34, 0x69,
- 0x3d, 0x6c, 0x78, 0x6d, 0xa0, 0x6f, 0xa6, 0x73, 0xd5, 0x79, 0xe1, 0xe6,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x10, 0x6f, 0x15, 0x75, 0x23,
- 0x03, 0x3d, 0x40, 0x08, 0x6c, 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x75, 0x00,
- 0x76, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x82, 0x00, 0x00,
- 0xe3, 0x64, 0x00, 0x6e, 0x14, 0x73, 0x1a, 0xe1, 0x61, 0x00, 0xe1, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x2c, 0x40, 0x08, 0x61, 0x6b,
- 0x65, 0x72, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3,
- 0x65, 0x00, 0x6f, 0x04, 0x79, 0x14, 0x40, 0x55, 0x72, 0x00, 0xe1, 0x77,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x06, 0x40, 0x09, 0x6f,
- 0x63, 0x6b, 0x00, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0xe2, 0x63, 0x00,
- 0x67, 0x07, 0x40, 0x06, 0x61, 0x75, 0x73, 0x74, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe1, 0x68,
- 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x73, 0x06, 0x79, 0x08, 0x00, 0x07,
- 0x40, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x00, 0x40, 0x2c, 0x65, 0x72, 0x00, 0x03, 0x3f, 0xf5, 0x61,
- 0x00, 0x00, 0x62, 0x05, 0x00, 0x65, 0x13, 0x00, 0x69, 0x6a, 0x01, 0x6f,
- 0xae, 0x01, 0x40, 0x09, 0x67, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x75, 0x04,
- 0x40, 0x09, 0x65, 0x00, 0x40, 0x06, 0x72, 0x67, 0x00, 0xfd, 0x00, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x63, 0x10, 0x00, 0x67, 0x18, 0x00, 0x6c, 0x1f,
- 0x00, 0x6d, 0x51, 0x00, 0x6f, 0x6b, 0x00, 0x70, 0xa9, 0x00, 0x72, 0xaf,
- 0x00, 0x73, 0xbb, 0x00, 0x74, 0x03, 0x01, 0x77, 0x09, 0x01, 0x79, 0x22,
- 0x01, 0x03, 0x40, 0xe1, 0x6f, 0x00, 0xe2, 0x64, 0x00, 0x79, 0x04, 0x40,
- 0x06, 0x79, 0x00, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
- 0x00, 0x40, 0x00, 0x72, 0x6f, 0x77, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x18, 0x79, 0x27, 0x40, 0x09, 0x6e, 0x64, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0x41, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6b, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe1, 0x61,
- 0x00, 0xe2, 0x64, 0x00, 0x6b, 0x04, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe3, 0x70, 0x00, 0x73, 0x1c, 0x77, 0x31, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x73, 0x06, 0x79,
- 0x08, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe1,
- 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x07,
- 0x69, 0x73, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0x40, 0x09, 0x6e, 0x65,
- 0x72, 0x00, 0x40, 0x09, 0x61, 0x67, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0xec, 0x40, 0x09, 0x6f, 0x6d, 0x00, 0xe4, 0x63, 0x00, 0x69,
- 0x0a, 0x70, 0x1d, 0x74, 0x22, 0x40, 0x07, 0x68, 0x6f, 0x6f, 0x6c, 0x69,
- 0x6e, 0x67, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x75, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x11, 0xe1, 0x61, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x09, 0x65, 0x74, 0x63, 0x68, 0x00, 0x40, 0x09, 0x6f, 0x77,
- 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x05, 0x72, 0x0a, 0x40, 0x08, 0x72,
- 0x64, 0x00, 0x43, 0x42, 0x72, 0x6b, 0x00, 0x40, 0x06, 0x65, 0x63, 0x6b,
- 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x7b, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe4, 0x63, 0x00, 0x65, 0x11, 0x6c, 0x1c, 0x6e,
- 0x29, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x06, 0x40, 0x00,
- 0x74, 0x69, 0x63, 0x00, 0x00, 0x06, 0xe3, 0x69, 0x00, 0x6f, 0x04, 0x79,
- 0x09, 0x40, 0x06, 0x64, 0x00, 0x40, 0x08, 0x69, 0x64, 0x00, 0x00, 0x07,
- 0xe7, 0x00, 0x00, 0x65, 0x02, 0x67, 0x0a, 0x6c, 0x49, 0x6e, 0x51, 0x70,
- 0x56, 0x73, 0x71, 0x00, 0x09, 0x40, 0x00, 0x72, 0x6f, 0x74, 0x69, 0x63,
- 0x00, 0xe2, 0x65, 0x00, 0x72, 0x28, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0f, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x61,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x67, 0x6f, 0x75, 0x73, 0x00,
- 0x40, 0x06, 0x79, 0x6d, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x62, 0x00, 0x6e, 0x0c, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x78, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe5,
- 0x00, 0x00, 0x63, 0x02, 0x65, 0x07, 0x6b, 0x72, 0x6f, 0x81, 0x03, 0x43,
- 0x40, 0x09, 0x68, 0x6f, 0x00, 0xe4, 0x00, 0x00, 0x72, 0x02, 0x73, 0x04,
- 0x79, 0x16, 0x00, 0x09, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x79, 0x06, 0x03, 0x44, 0x40, 0x00, 0x72, 0x00, 0x00, 0x84,
- 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x07, 0x64, 0x0d, 0x6c, 0x12, 0x6d,
- 0x1a, 0x70, 0x2e, 0x73, 0x33, 0x00, 0x93, 0x40, 0x06, 0x65, 0x65, 0x00,
- 0x40, 0x47, 0x6f, 0x6d, 0x62, 0x00, 0x40, 0x06, 0x65, 0x77, 0x00, 0x40,
- 0x07, 0x6f, 0x63, 0x75, 0x73, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x08, 0x6f, 0x74, 0x00, 0x40, 0x06, 0x75, 0x63,
- 0x6b, 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x06, 0x00,
- 0xe7, 0x40, 0x07, 0x72, 0x00, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x2c, 0x69, 0x35, 0x03, 0x45, 0xe2, 0x62, 0x00,
- 0x72, 0x11, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x07, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x8f, 0xe2, 0x69, 0x00, 0x79, 0x0d,
- 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x09, 0x6d,
- 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x06,
- 0x40, 0x09, 0x66, 0x69, 0x63, 0x00, 0xeb, 0x63, 0x00, 0x64, 0x04, 0x65,
- 0x24, 0x66, 0x28, 0x6b, 0x2a, 0x6c, 0x5b, 0x70, 0x73, 0x72, 0x7e, 0x73,
- 0x83, 0x74, 0x8a, 0x76, 0x9f, 0x40, 0x07, 0x68, 0x00, 0xe5, 0x00, 0x00,
- 0x69, 0x02, 0x6c, 0x06, 0x6f, 0x0b, 0x77, 0x0f, 0x00, 0x47, 0x40, 0x09,
- 0x65, 0x00, 0x40, 0x06, 0x75, 0x6d, 0x00, 0x40, 0x47, 0x6f, 0x00, 0x40,
- 0x72, 0x69, 0x6e, 0x6b, 0x00, 0x40, 0x07, 0x79, 0x00, 0x00, 0xe7, 0xe7,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x12, 0x75, 0x16, 0x77, 0x1a,
- 0x79, 0x20, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x09, 0x70, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x6d, 0x00, 0x00, 0x07,
- 0xe1, 0x69, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x47, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x00, 0x61, 0x79, 0x00, 0x40, 0x06, 0x65, 0x67, 0x6f, 0x77, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0xe2, 0x6e, 0x00, 0x72, 0x07, 0x40,
- 0x06, 0x61, 0x6e, 0x6e, 0x79, 0x00, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2,
- 0x72, 0x00, 0x73, 0x02, 0x00, 0x3a, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x70, 0x34, 0x73, 0x47, 0x00, 0x93, 0xe3, 0x00, 0x00, 0x66, 0x02,
- 0x6c, 0x15, 0x00, 0x09, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x03, 0x46, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x47, 0x63, 0x6f, 0x74, 0x63, 0x68, 0x00,
- 0xfa, 0x61, 0x00, 0x00, 0x64, 0x02, 0x00, 0x65, 0x06, 0x00, 0x69, 0x0e,
- 0x00, 0x6d, 0x23, 0x00, 0x6e, 0x34, 0x00, 0x6f, 0x66, 0x00, 0x72, 0x93,
- 0x00, 0x73, 0xe7, 0x00, 0x74, 0xf5, 0x01, 0x00, 0x09, 0x40, 0x5e, 0x65,
- 0x00, 0x40, 0x06, 0x68, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe1, 0x7a, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0x40, 0x56, 0x61, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x06, 0xe6,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x0a, 0x6c, 0x0e, 0x70, 0x1d, 0x79, 0x23,
- 0x00, 0xb2, 0x40, 0x07, 0x6c, 0x65, 0x6e, 0x64, 0x65, 0x00, 0x40, 0x09,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x6b, 0x65, 0x00, 0x40, 0x09, 0x69, 0x70, 0x65, 0x00, 0x00,
- 0x60, 0xe2, 0x6c, 0x00, 0x73, 0x21, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x63, 0x6f, 0x70, 0x65, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x08, 0x6f, 0x49, 0x40, 0x3b, 0x6e, 0x64, 0x6f, 0x75, 0x73,
- 0x00, 0xe3, 0x62, 0x00, 0x64, 0x17, 0x66, 0x19, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xe2, 0x69, 0x00,
- 0x79, 0x10, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3a, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72, 0x00, 0xf2, 0x65,
- 0x00, 0x00, 0x69, 0xf9, 0x00, 0xed, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06,
- 0x66, 0x14, 0x68, 0x23, 0x6c, 0x32, 0x6d, 0x4e, 0x70, 0x67, 0x72, 0x77,
- 0x73, 0x7f, 0x74, 0x9a, 0x77, 0xac, 0x79, 0xdc, 0x00, 0xf1, 0x40, 0x00,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x63, 0x6b, 0x00,
- 0x40, 0x08, 0x78, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x05,
- 0x40, 0x07, 0x73, 0x68, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x69, 0x05,
- 0x40, 0x07, 0x69, 0x72, 0x00, 0x40, 0x07, 0x64, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x12, 0xe1, 0x75, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x73,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x61, 0x79,
- 0x00, 0x40, 0x07, 0x77, 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x64, 0x69,
- 0x73, 0x68, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x41,
- 0x68, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x1a, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x05, 0x40,
- 0x06, 0x69, 0x6c, 0x00, 0x40, 0x00, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x00,
- 0xe2, 0x68, 0x00, 0x6f, 0x1b, 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00, 0xe2,
- 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x07, 0x40, 0x00, 0x74,
- 0x6f, 0x72, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x0f, 0x69, 0x11, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0x40, 0x08, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x09,
- 0x73, 0x74, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x06, 0x69, 0x13, 0x70, 0x22,
- 0x74, 0x70, 0x40, 0x06, 0x6e, 0x6e, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x82, 0x40, 0x08, 0x69, 0x70, 0x65, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x07,
- 0xe3, 0x00, 0x00, 0x68, 0x02, 0x69, 0x0c, 0x00, 0x00, 0x40, 0x00, 0x6f,
- 0x6c, 0x69, 0x70, 0x61, 0x73, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x09, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x6c, 0x0c,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x54,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x74, 0x00, 0x7a, 0x04,
- 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x07, 0x69, 0x21, 0x6c, 0x3a, 0x00, 0x47, 0x40, 0x09, 0x67, 0x65, 0x00,
- 0xe2, 0x6c, 0x00, 0x73, 0x11, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x06,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x47,
- 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x86,
- 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x65, 0x73,
- 0x00, 0x00, 0x06, 0x40, 0x09, 0x65, 0x72, 0x00, 0xec, 0x00, 0x00, 0x62,
- 0x02, 0x63, 0x19, 0x65, 0x1f, 0x66, 0x2e, 0x68, 0x34, 0x6b, 0x5c, 0x6c,
- 0x61, 0x6e, 0x70, 0x70, 0x76, 0x73, 0x85, 0x74, 0x91, 0x03, 0x47, 0xe3,
- 0x65, 0x00, 0x6c, 0x04, 0x6f, 0x0c, 0x40, 0x09, 0x64, 0x00, 0x40, 0x00,
- 0x6f, 0x6f, 0x64, 0x65, 0x64, 0x00, 0x40, 0x09, 0x78, 0x00, 0x40, 0x06,
- 0x61, 0x6b, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x55, 0x6f, 0x6f, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x1d, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x1a, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x06, 0x75, 0x73, 0x65, 0x00, 0x40, 0x08, 0x65, 0x79, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6b, 0x02, 0x00, 0x09, 0x00,
- 0x08, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x06,
- 0x40, 0x06, 0x61, 0x74, 0x65, 0x00, 0x40, 0x08, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x68, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6f, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x0f, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00,
- 0x08, 0x40, 0x00, 0x67, 0x00, 0xf3, 0x6e, 0x00, 0x00, 0x72, 0x04, 0x00,
- 0x73, 0x16, 0x00, 0x40, 0x93, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02,
- 0x69, 0x09, 0x00, 0x86, 0x40, 0x09, 0x6c, 0x61, 0x73, 0x73, 0x00, 0x00,
- 0x06, 0xf2, 0x65, 0x00, 0x00, 0x69, 0x61, 0x01, 0xfd, 0x00, 0x00, 0x00,
- 0x27, 0x02, 0x00, 0x62, 0x06, 0x00, 0x63, 0x49, 0x00, 0x66, 0x68, 0x00,
- 0x68, 0x75, 0x00, 0x6b, 0x93, 0x00, 0x6c, 0xaa, 0x00, 0x6d, 0xb2, 0x00,
- 0x70, 0xe8, 0x00, 0x72, 0x02, 0x01, 0x74, 0x08, 0x01, 0x77, 0x0d, 0x01,
- 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x12, 0xe3,
- 0x61, 0x00, 0x75, 0x04, 0x79, 0x09, 0x40, 0x06, 0x74, 0x00, 0x40, 0x00,
- 0x6e, 0x64, 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x6f, 0x18, 0xe1, 0x61,
- 0x00, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00,
- 0xe8, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6b,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x15, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3a, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x61, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x75,
- 0x04, 0x40, 0x06, 0x79, 0x00, 0x40, 0x06, 0x6c, 0x00, 0xe2, 0x6f, 0x00,
- 0x75, 0x11, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x01, 0x24, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x73, 0x62, 0x61,
- 0x6e, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x70, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x69, 0x67, 0x68, 0x74, 0x73, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x19, 0x69, 0x1d, 0x6f, 0x26, 0xe4, 0x69, 0x00, 0x6e, 0x04,
- 0x73, 0x06, 0x74, 0x0c, 0x40, 0x06, 0x64, 0x00, 0x00, 0x07, 0x40, 0x08,
- 0x74, 0x65, 0x72, 0x00, 0x40, 0x08, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x08, 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x74,
- 0x68, 0x65, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x07, 0x72, 0x0d, 0x40,
- 0x06, 0x72, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x74, 0x00,
- 0x40, 0x00, 0x6f, 0x75, 0x64, 0x00, 0x40, 0x00, 0x6f, 0x6f, 0x6d, 0x00,
- 0x40, 0x06, 0x6f, 0x70, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x12, 0x6f, 0x20,
- 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x04, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x04, 0x40,
- 0x12, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40, 0x07, 0x72, 0x6b,
- 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x72, 0x04, 0x00, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x5b, 0x40, 0x07, 0x72, 0x61, 0x66, 0x74, 0x00, 0xe9, 0x00,
- 0x00, 0x27, 0x02, 0x62, 0x0d, 0x64, 0x13, 0x65, 0x26, 0x69, 0x2c, 0x6c,
- 0x33, 0x73, 0x3e, 0x74, 0x46, 0x00, 0x06, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x65, 0x69, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x79, 0x0c, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x76, 0x65, 0x72,
- 0x00, 0x40, 0x06, 0x74, 0x7a, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x65, 0x76,
- 0x65, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x73, 0x68, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe3, 0x00, 0x00, 0x6d,
- 0x02, 0x74, 0x06, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x07, 0x70,
- 0x64, 0x00, 0xff, 0x61, 0x00, 0x00, 0x62, 0x08, 0x00, 0x63, 0x28, 0x00,
- 0x64, 0x4e, 0x00, 0x65, 0x54, 0x00, 0x66, 0x56, 0x00, 0x67, 0x73, 0x00,
- 0x68, 0x97, 0x00, 0x6c, 0x99, 0x00, 0x6d, 0xb9, 0x00, 0x6e, 0xb0, 0x02,
- 0x72, 0x5f, 0x03, 0x73, 0xd4, 0x03, 0x74, 0x46, 0x04, 0x7a, 0x51, 0x04,
- 0x40, 0x06, 0x72, 0x61, 0x63, 0x68, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x62,
- 0x02, 0x63, 0x0d, 0x72, 0x12, 0x00, 0x06, 0xe2, 0x75, 0x00, 0x79, 0x04,
- 0x40, 0x06, 0x62, 0x00, 0x00, 0x06, 0x40, 0x06, 0x61, 0x70, 0x00, 0x40,
- 0x07, 0x69, 0x73, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x09,
- 0x40, 0x06, 0x65, 0x62, 0x65, 0x72, 0x72, 0x79, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x93, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x5e, 0x64, 0x6c, 0x65, 0x00,
- 0x00, 0x1a, 0xe1, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11,
- 0x00, 0x47, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x67, 0x0f, 0x03, 0x48, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00,
- 0x6b, 0x02, 0x6c, 0x04, 0x00, 0x09, 0x03, 0x2a, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x0a, 0x00, 0xe7, 0x40, 0x06, 0x62, 0x61, 0x6c, 0x6f, 0x6f,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x62, 0x86, 0x00, 0x64, 0xbb, 0x00, 0x65, 0xcc, 0x00, 0x69, 0xe0, 0x00,
- 0x6d, 0x36, 0x01, 0x6f, 0x6e, 0x01, 0x70, 0xbc, 0x01, 0x75, 0xd4, 0x01,
- 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0f,
- 0x6b, 0x63, 0x6e, 0x69, 0x6f, 0x6f, 0x03, 0x49, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x73, 0x00,
- 0x74, 0x12, 0x7a, 0x38, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x18, 0x79, 0x1d, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0x01, 0xa7,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x41, 0x52, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0x4a, 0x00, 0x06, 0x40, 0x07, 0x69,
- 0x6e, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x69,
- 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x18, 0xe2, 0x65, 0x00, 0x79, 0x11,
- 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x08, 0x03, 0x4b, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x67, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x07,
- 0x40, 0x09, 0x6e, 0x67, 0x65, 0x72, 0x00, 0x40, 0x07, 0x75, 0x6d, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x75, 0x06, 0x40, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x6c,
- 0x2e, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x23, 0x00, 0x3b, 0xe2, 0x66,
- 0x00, 0x74, 0x18, 0xe2, 0x69, 0x00, 0x79, 0x11, 0xe2, 0x63, 0x00, 0x65,
- 0x08, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x41, 0x52, 0x72,
- 0x00, 0x01, 0xb6, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x17, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x38, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b,
- 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x09, 0x6f, 0x1c, 0x75, 0x2b, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x00, 0x40, 0x06, 0x69, 0x72, 0x64, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x07, 0x40,
- 0x00, 0x67, 0x6f, 0x75, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x09, 0x6c, 0x0e, 0x6f, 0x24, 0x00, 0x2c, 0x40, 0x00, 0x73, 0x71, 0x75,
- 0x65, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x62, 0x02, 0x68, 0x08, 0x00, 0x47, 0x40, 0xb2, 0x61,
- 0x63, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01, 0x20, 0x00, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x10, 0x67, 0x3e, 0x6b,
- 0x69, 0x74, 0x78, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x47, 0x40, 0xb1, 0x61, 0x63, 0x6b, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x74, 0x08, 0x77,
- 0x14, 0x01, 0x58, 0x40, 0x00, 0x6f, 0x6c, 0x64, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x65,
- 0x69, 0x67, 0x68, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x06,
- 0x72, 0x0c, 0x00, 0x00, 0x40, 0x2c, 0x72, 0x00, 0x40, 0x00, 0x76, 0x65,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x06, 0x01, 0x71, 0x41, 0x20, 0x72,
- 0x00, 0x00, 0xf3, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x72, 0x0b,
- 0x73, 0x11, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe4,
- 0x64, 0x00, 0x6c, 0x16, 0x72, 0x28, 0x74, 0x4c, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe3, 0x61, 0x00, 0x69, 0x0c, 0x79, 0x1b, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0xec, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x65, 0x06,
- 0x40, 0x09, 0x61, 0x6e, 0x65, 0x00, 0x40, 0x36, 0x64, 0x00, 0x00, 0x5e,
- 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x15, 0x03, 0x2a, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe5, 0x62, 0x00, 0x68,
- 0x23, 0x6b, 0x25, 0x73, 0x45, 0x74, 0x50, 0xe1, 0x61, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x0f, 0x00,
- 0x59, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x07, 0x79, 0x00, 0x00, 0x47, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x79, 0x15, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x02, 0x13, 0xe2, 0x61, 0x00, 0x79, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x6c, 0x06, 0x40, 0x07, 0x6e, 0x67,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x06, 0x40, 0x09, 0x68,
- 0x00, 0xe1, 0x7a, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x2f, 0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0xf9,
- 0x61, 0x00, 0x00, 0x62, 0x18, 0x00, 0x64, 0x3f, 0x00, 0x65, 0xdc, 0x01,
- 0x67, 0xe1, 0x01, 0x69, 0x12, 0x02, 0x6d, 0x17, 0x02, 0x70, 0x3e, 0x02,
- 0x73, 0xd1, 0x04, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x73, 0x00, 0x7a, 0x04,
- 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xf1, 0x72, 0x00, 0x00, 0xf2, 0x61,
- 0x00, 0x00, 0x6f, 0x46, 0x00, 0xe4, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x0e,
- 0x75, 0x23, 0x00, 0x06, 0xe2, 0x67, 0x00, 0x74, 0x05, 0x40, 0x06, 0x65,
- 0x61, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x00, 0x00,
- 0x27, 0x02, 0x03, 0x4c, 0x40, 0x00, 0x73, 0x00, 0x41, 0x52, 0x6f, 0x6e,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x07, 0xfd, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x64, 0x20,
- 0x00, 0x65, 0x3b, 0x00, 0x66, 0x64, 0x00, 0x67, 0x6a, 0x00, 0x6c, 0x8d,
- 0x00, 0x6d, 0xb7, 0x00, 0x70, 0xca, 0x00, 0x73, 0x09, 0x01, 0x74, 0x11,
- 0x01, 0x75, 0x1a, 0x01, 0x78, 0x1e, 0x01, 0x00, 0x07, 0xe3, 0x61, 0x00,
- 0x65, 0x07, 0x6f, 0x10, 0x40, 0x09, 0x72, 0x62, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x70, 0x68, 0x61, 0x6c, 0x75, 0x73, 0x00, 0x40, 0x09, 0x64, 0x6f,
- 0x6e, 0x65, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x09, 0x6f, 0x69, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x6f, 0x11, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x01, 0x98, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x75, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x0f, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07,
- 0xe2, 0x73, 0x00, 0x7a, 0x0d, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x68, 0x00, 0x6c, 0x18, 0x6f, 0x1e,
- 0xe1, 0x6f, 0x00, 0xe2, 0x62, 0x00, 0x6e, 0x0c, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x65, 0x00,
- 0x40, 0xa1, 0x61, 0x6e, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x40, 0x07, 0x70, 0x68,
- 0x65, 0x72, 0x65, 0x00, 0x40, 0x07, 0x68, 0x65, 0x72, 0x61, 0x70, 0x79,
- 0x00, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x69, 0x64, 0x65, 0x00, 0x40,
- 0x06, 0x6e, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x23, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x63,
- 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x37, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x6d,
- 0x65, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65,
- 0x00, 0x6e, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x06, 0x00, 0x47, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6b,
- 0x00, 0xf4, 0x65, 0x00, 0x00, 0x68, 0x39, 0x01, 0x6e, 0x55, 0x01, 0x6f,
- 0xa8, 0x01, 0xf2, 0x00, 0x00, 0x00, 0x72, 0x02, 0x00, 0x03, 0x4d, 0xfb,
- 0x61, 0x00, 0x00, 0x62, 0x18, 0x00, 0x63, 0x2d, 0x00, 0x67, 0x37, 0x00,
- 0x69, 0x41, 0x00, 0x6c, 0x4c, 0x00, 0x6d, 0x52, 0x00, 0x70, 0x64, 0x00,
- 0x73, 0x74, 0x00, 0x74, 0xa8, 0x00, 0x76, 0xed, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x69, 0x04, 0x00, 0x06,
- 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x40, 0x3b, 0x72, 0x69, 0x74, 0x69,
- 0x63, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x6c, 0x79, 0x63, 0x65, 0x6d, 0x69,
- 0x61, 0x00, 0x40, 0x00, 0x6e, 0x66, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x95, 0x69, 0x6e, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x08, 0x72, 0x6b, 0x65, 0x74, 0x00, 0x40, 0x07, 0x64, 0x69, 0x61,
- 0x00, 0x40, 0x00, 0x61, 0x72, 0x61, 0x74, 0x68, 0x79, 0x72, 0x6f, 0x69,
- 0x64, 0x69, 0x73, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x70, 0x29, 0xe1, 0x6e,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x74, 0x79, 0x00, 0x40, 0x08, 0x61, 0x63, 0x65, 0x00, 0xe3, 0x65, 0x00,
- 0x68, 0x1c, 0x72, 0x37, 0xe2, 0x6e, 0x00, 0x78, 0x13, 0xe1, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x74, 0x00, 0xe1, 0x79, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40,
- 0x5e, 0x6f, 0x70, 0x68, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x47, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x01, 0xcd, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x73,
- 0x00, 0x74, 0x0d, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x18, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x08, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe3, 0x63, 0x00,
- 0x73, 0x0d, 0x7a, 0x16, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x00, 0x09, 0x40, 0x0b, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x63,
- 0x0e, 0x64, 0x47, 0x67, 0x4f, 0x74, 0x6a, 0x00, 0x09, 0x40, 0x00, 0x6c,
- 0x6c, 0x65, 0x72, 0x67, 0x65, 0x6e, 0x69, 0x63, 0x00, 0xe2, 0x68, 0x00,
- 0x72, 0x1b, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74,
- 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x3b, 0x63, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x65, 0x72, 0x6d, 0x69,
- 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x68, 0x07, 0x40, 0x09,
- 0x6e, 0x75, 0x73, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x14, 0x79, 0x3c,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00,
- 0x75, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x72, 0x00, 0x73,
- 0x06, 0x74, 0x1a, 0x40, 0x07, 0x6d, 0x69, 0x61, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x02, 0x00,
- 0x07, 0x40, 0x3a, 0x65, 0x00, 0x40, 0x3b, 0x69, 0x63, 0x61, 0x6c, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x07, 0x6f, 0x70, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe2, 0x63, 0x00,
- 0x73, 0x07, 0x40, 0x06, 0x74, 0x6f, 0x6d, 0x79, 0x00, 0x40, 0x00, 0x69,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x73, 0x06, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07,
- 0xc1, 0x50, 0x29, 0x57, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x75, 0x00, 0x91, 0x00, 0xb7, 0x00, 0x8f, 0x01, 0x00,
- 0x00, 0x61, 0x03, 0x76, 0x03, 0x00, 0x00, 0xf5, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0xfe, 0x03, 0x81, 0x05, 0xd1, 0x10, 0xcc, 0x32, 0x33, 0x33, 0x00,
- 0x00, 0x3a, 0x33, 0x49, 0x37, 0x86, 0x38, 0x00, 0x00, 0x34, 0x39, 0x00,
- 0x00, 0x44, 0x39, 0x01, 0x43, 0xe3, 0x61, 0x00, 0x68, 0x04, 0x6f, 0x0a,
- 0x40, 0x07, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07,
- 0x64, 0x00, 0x40, 0x07, 0x75, 0x6e, 0x65, 0x73, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x62, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75, 0x0b, 0x00, 0x09,
- 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x09, 0x73,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x75, 0x16, 0x40, 0x09, 0x78, 0x00,
- 0xe2, 0x64, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6d, 0x00, 0x00, 0x09, 0x40, 0x07, 0x70, 0x72, 0x6f, 0x66,
- 0x65, 0x6e, 0x00, 0xe7, 0x65, 0x00, 0x68, 0x49, 0x69, 0x6a, 0x6b, 0x86,
- 0x6f, 0x8a, 0x74, 0xc2, 0x79, 0xc7, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x62,
- 0x06, 0x63, 0x2c, 0x6d, 0x31, 0x03, 0x4a, 0x40, 0x00, 0x73, 0x00, 0xe3,
- 0x65, 0x00, 0x6f, 0x05, 0x72, 0x17, 0x40, 0x06, 0x72, 0x67, 0x00, 0xe3,
- 0x61, 0x00, 0x75, 0x04, 0x78, 0x09, 0x40, 0x06, 0x74, 0x00, 0x40, 0x00,
- 0x6e, 0x64, 0x00, 0x00, 0x09, 0x40, 0x06, 0x65, 0x61, 0x6b, 0x65, 0x72,
- 0x00, 0x40, 0x06, 0x61, 0x70, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73,
- 0x74, 0x00, 0x00, 0x07, 0xe3, 0x63, 0x00, 0x6c, 0x05, 0x6e, 0x09, 0x40,
- 0x06, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x06, 0x40, 0xf3, 0x79, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x06, 0x00, 0x09,
- 0x40, 0x00, 0x63, 0x00, 0xe2, 0x63, 0x00, 0x67, 0x1b, 0xe1, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00,
- 0x40, 0x07, 0x72, 0x61, 0x70, 0x68, 0x79, 0x00, 0x40, 0x07, 0x75, 0x73,
- 0x00, 0x01, 0x92, 0xf6, 0x00, 0x00, 0x00, 0x65, 0x02, 0x00, 0x69, 0xd9,
- 0x00, 0x6c, 0x52, 0x01, 0x6f, 0x66, 0x01, 0x79, 0xa2, 0x01, 0x00, 0x56,
- 0xe5, 0x61, 0x00, 0x6d, 0x3f, 0x6e, 0x4e, 0x6f, 0x8b, 0x73, 0xca, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x56, 0xe2, 0x73, 0x00, 0x7a, 0x1e, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x3a, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6f,
- 0x74, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe4,
- 0x63, 0x00, 0x66, 0x05, 0x6b, 0x25, 0x74, 0x2a, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x19, 0xe3, 0x61, 0x00, 0x63, 0x06, 0x65,
- 0x0e, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x37, 0x64, 0x00, 0x03, 0x4e, 0x40, 0x08, 0x69,
- 0x74, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x67, 0x00, 0x6c, 0x19, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x02, 0x00, 0x06,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe3, 0x69, 0x00, 0x75, 0x0e, 0x79,
- 0x12, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0x40, 0x09, 0x65, 0x00, 0x00, 0x06, 0x00, 0x07, 0xe1,
- 0x6f, 0x00, 0xe5, 0x63, 0x00, 0x6d, 0x04, 0x70, 0x21, 0x73, 0x29, 0x74,
- 0x54, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x37, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x00,
- 0x61, 0x74, 0x68, 0x69, 0x63, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x08, 0x03, 0x4f,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x21, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x72, 0x04, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x6f,
- 0x05, 0x79, 0x0a, 0x40, 0x09, 0x73, 0x73, 0x00, 0x40, 0x00, 0x75, 0x73,
- 0x00, 0x00, 0x07, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x79,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe3, 0x6c,
- 0x00, 0x6e, 0x05, 0x75, 0x72, 0x40, 0x06, 0x6f, 0x6f, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x06, 0x6f, 0x24, 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0f, 0x40, 0x00, 0x62,
- 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x4b, 0x00, 0x09,
- 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe3, 0x62, 0x00, 0x6d, 0x0c, 0x72, 0x1f,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40,
- 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x15,
- 0xe2, 0x6d, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x75, 0x73, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x00, 0x0b, 0x40,
- 0x09, 0x61, 0x6e, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xf4, 0x65, 0x00, 0x00, 0x69, 0x13, 0x00, 0x6b, 0x1e, 0x00,
- 0x6c, 0x20, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x02, 0x75, 0x08, 0x00, 0x00,
- 0x40, 0x07, 0x74, 0x69, 0x73, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x00, 0x06, 0xf6,
- 0x00, 0x00, 0x00, 0x65, 0x02, 0x00, 0x69, 0x49, 0x00, 0x6e, 0x9c, 0x00,
- 0x6f, 0xa2, 0x00, 0x75, 0xbd, 0x00, 0x02, 0x7b, 0xe1, 0x67, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x0f, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x86, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x15,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe4, 0x62, 0x00, 0x63, 0x18,
- 0x6d, 0x2b, 0x74, 0x34, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x86, 0x65, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x24, 0xe1, 0x69, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x17, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x51, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b,
- 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x00, 0x52, 0xe4, 0x00, 0x00, 0x69,
- 0x02, 0x6f, 0x14, 0x74, 0x19, 0x01, 0xdc, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xd2, 0x40, 0x06, 0x73, 0x74,
- 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x1d, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f,
- 0x00, 0x70, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x3b, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x62, 0x59, 0x00,
- 0x69, 0xaf, 0x00, 0x6d, 0xe5, 0x00, 0x70, 0x4b, 0x03, 0xe2, 0x67, 0x00,
- 0x6d, 0x52, 0xe3, 0x65, 0x00, 0x69, 0x0b, 0x6f, 0x40, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x5e, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x2b, 0xe4, 0x62, 0x00, 0x6c, 0x0c, 0x72, 0x0e, 0x74,
- 0x12, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00,
- 0x37, 0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x36, 0x65, 0x00, 0x03,
- 0x50, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00,
- 0x00, 0x09, 0xe5, 0x61, 0x00, 0x65, 0x08, 0x69, 0x23, 0x72, 0x32, 0x75,
- 0x47, 0x40, 0x1a, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe2, 0x63, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x06, 0x79, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x6f, 0x09, 0x40, 0x07, 0x63, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x67, 0x6c, 0x69, 0x6f, 0x00,
- 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62,
- 0x00, 0x74, 0x05, 0x40, 0x54, 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x1b, 0x02, 0x7d, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x72, 0x00, 0xf5, 0x61,
- 0x00, 0x00, 0x65, 0x6d, 0x00, 0x69, 0xe9, 0x00, 0x6f, 0x1a, 0x01, 0x75,
- 0xbe, 0x01, 0xe3, 0x63, 0x00, 0x6e, 0x1c, 0x74, 0x32, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x3b, 0xe2,
- 0x65, 0x00, 0x75, 0x20, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x00,
- 0x3e, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe5, 0x61, 0x00, 0x64, 0x1b, 0x6d, 0x42, 0x6e, 0x4a,
- 0x72, 0x59, 0xe1, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x0c, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x65,
- 0x73, 0x00, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x6f, 0x72,
- 0x69, 0x61, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x73, 0xe2, 0x62, 0x00, 0x6f, 0x05, 0x40, 0x00,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x1b,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x06, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe5, 0x62, 0x00, 0x64,
- 0x24, 0x6c, 0x3e, 0x72, 0x50, 0x76, 0x7e, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe2, 0x74, 0x00, 0x7a,
- 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3f, 0xe1, 0x65, 0x00, 0xe2, 0x72,
- 0x00, 0x73, 0x06, 0x40, 0x3b, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x3b, 0x00, 0x07, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x0f, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86,
- 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x3a, 0x65,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07,
- 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x72, 0x74, 0x76, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x19, 0x00, 0x00, 0xe2, 0x74, 0x00, 0x7a,
- 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe3, 0x64, 0x00, 0x67, 0x20,
- 0x6c, 0x2a, 0xe1, 0x65, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x00, 0x40, 0x08,
- 0x6c, 0x6f, 0x62, 0x75, 0x6c, 0x69, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73, 0x0b,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40,
- 0x09, 0x74, 0x00, 0x00, 0x07, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0xdd, 0x00, 0x69, 0x75,
- 0x03, 0x6c, 0xb9, 0x03, 0x6f, 0x8e, 0x04, 0x72, 0x90, 0x05, 0x75, 0x6d,
- 0x07, 0x00, 0x2b, 0xe7, 0x63, 0x00, 0x69, 0x04, 0x6c, 0x1a, 0x6e, 0x42,
- 0x72, 0x47, 0x73, 0x63, 0x74, 0xb4, 0x40, 0x2c, 0x74, 0x00, 0xe1, 0x72,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x02, 0x83, 0x40, 0x37,
- 0x64, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x02, 0x70, 0x0f, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x51,
- 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x7a, 0x65, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x7a, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x48, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x08, 0x40, 0x00, 0x62,
- 0x6c, 0x79, 0x00, 0x03, 0x51, 0xe3, 0x62, 0x00, 0x6f, 0x15, 0x76, 0x1b,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6e,
- 0x65, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0x40, 0x07, 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x04, 0x74, 0x06, 0x40, 0x09,
- 0x65, 0x00, 0x00, 0x07, 0x00, 0x3b, 0xf7, 0x61, 0x00, 0x00, 0x63, 0x21,
- 0x00, 0x64, 0x5d, 0x00, 0x6c, 0x88, 0x00, 0x6e, 0xa2, 0x00, 0x72, 0xe0,
- 0x00, 0x74, 0x56, 0x02, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x08, 0x6d, 0x0c, 0x03, 0x52, 0x40, 0x37, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x63, 0x00, 0x75, 0x1b, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0f, 0x40, 0x07, 0x6e, 0x63,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x3a, 0x00, 0x37, 0xe1,
- 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x64,
- 0x00, 0x65, 0x02, 0x69, 0x23, 0x00, 0x7a, 0xe1, 0x74, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07,
- 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0xf8, 0x61, 0x00, 0x00, 0x63, 0x07, 0x00, 0x66, 0x31, 0x00, 0x69, 0x52,
- 0x00, 0x6d, 0xbb, 0x00, 0x73, 0xfa, 0x00, 0x74, 0x1c, 0x01, 0x76, 0x56,
- 0x01, 0x40, 0x56, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x62, 0x00, 0x76,
- 0x15, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x02, 0x12,
- 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4,
- 0x61, 0x00, 0x6c, 0x2b, 0x6f, 0x38, 0x73, 0x4b, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x03, 0x53, 0x40, 0x07,
- 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x14, 0x69, 0x2f, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1,
- 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74,
- 0x02, 0x00, 0x3b, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x51,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x75, 0x14, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x72,
- 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x3b, 0x69, 0x6f, 0x75,
- 0x73, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x07, 0x67, 0x6f, 0x00,
- 0xe2, 0x6f, 0x00, 0x73, 0x1b, 0xe2, 0x73, 0x00, 0x75, 0x06, 0x40, 0x07,
- 0x69, 0x74, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x09, 0xe4, 0x65,
- 0x00, 0x6e, 0x05, 0x6f, 0x18, 0x73, 0x2b, 0x40, 0x06, 0x74, 0x79, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0x78, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x51, 0x69,
- 0x7a, 0x6f, 0xa1, 0x79, 0xc8, 0xe3, 0x63, 0x00, 0x6e, 0x1b, 0x75, 0x2c,
- 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x03,
- 0x54, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x06,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x12, 0x03, 0x55, 0xe2,
- 0x62, 0x00, 0x74, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x3a, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x64,
- 0x00, 0x72, 0x04, 0x73, 0x10, 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x3a, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x00, 0x65,
- 0x00, 0x01, 0x26, 0xe7, 0x6c, 0x00, 0x6e, 0x1c, 0x72, 0x26, 0x73, 0x64,
- 0x74, 0xbc, 0x75, 0xd2, 0x76, 0xd7, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x63, 0x00, 0x40, 0x09,
- 0x64, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x18, 0x75, 0x1c, 0x03, 0x56, 0xe2, 0x6e,
- 0x00, 0x74, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x3b, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x07, 0x40, 0x3b,
- 0x74, 0x65, 0x00, 0x00, 0x0b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x09, 0x73, 0x22, 0x74, 0x3d, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xab, 0x00, 0x09, 0xe2, 0x6e, 0x00, 0x74, 0x0e, 0xe1, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x37, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x06, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x08, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x6f,
- 0x02, 0x75, 0x06, 0x00, 0x06, 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x72,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x3b,
- 0x40, 0x72, 0x6e, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x58, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xf5, 0x61, 0x00,
- 0x00, 0x65, 0x35, 0x00, 0x69, 0xff, 0x00, 0x6f, 0x2e, 0x01, 0x75, 0xb9,
- 0x01, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x6c, 0x15, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x00, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe3, 0x63, 0x00, 0x67, 0x2e, 0x73,
- 0x5a, 0xe2, 0x61, 0x00, 0x69, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x52,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x15, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x06,
- 0x40, 0x06, 0x72, 0x69, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x03, 0x57, 0x40, 0x37, 0x64, 0x00, 0xe3, 0x62, 0x00, 0x6f, 0x10,
- 0x76, 0x3a, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74,
- 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x0b, 0x02, 0x9d, 0x40, 0x07, 0x62, 0x69, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x07, 0x73, 0x15, 0x40,
- 0x06, 0x61, 0x74, 0x75, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x91, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0xe4, 0x62, 0x00, 0x6d, 0x1b, 0x70, 0x21, 0x76, 0x31,
- 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x06, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x06, 0x70, 0x74, 0x75, 0x00, 0xe2, 0x65, 0x00,
- 0x72, 0x04, 0x40, 0x3b, 0x72, 0x00, 0x40, 0x06, 0x69, 0x65, 0x74, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6d,
- 0x04, 0x03, 0x58, 0x00, 0x37, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x11, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe2, 0x61, 0x00,
- 0x65, 0x17, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe1, 0x64,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe6, 0x64, 0x00, 0x67, 0x11, 0x6c,
- 0x1f, 0x6e, 0x42, 0x72, 0x48, 0x74, 0x54, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x48, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0x59,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0xda, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0x5a, 0xc1, 0x61, 0x17,
- 0x33, 0x00, 0x35, 0x00, 0x15, 0x01, 0x33, 0x01, 0x7c, 0x05, 0x23, 0x09,
- 0xd2, 0x0a, 0xf0, 0x0d, 0x9d, 0x0e, 0x62, 0x0f, 0xef, 0x0f, 0x27, 0x10,
- 0x61, 0x10, 0x70, 0x10, 0x7f, 0x10, 0x60, 0x11, 0x00, 0x00, 0x9d, 0x11,
- 0xfc, 0x11, 0x02, 0x12, 0xcc, 0x16, 0xb0, 0x1f, 0xce, 0x1f, 0xf5, 0x21,
- 0x00, 0x65, 0xe9, 0x63, 0x00, 0x64, 0x13, 0x6c, 0x3a, 0x6d, 0x59, 0x6e,
- 0x61, 0x70, 0x87, 0x72, 0x93, 0x73, 0x9e, 0x75, 0xa5, 0xe2, 0x63, 0x00,
- 0x74, 0x08, 0x40, 0x08, 0x75, 0x72, 0x61, 0x63, 0x79, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x76, 0x08, 0x40, 0x08, 0x71,
- 0x75, 0x61, 0x63, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x69, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x61, 0x74, 0x61, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0xda, 0xe2, 0x6d, 0x00, 0x74, 0x16, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00,
- 0x40, 0x3b, 0x70, 0x72, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x74, 0x65, 0x00,
- 0x40, 0x3b, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x00, 0x40,
- 0x00, 0x6d, 0x75, 0x63, 0x68, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x07, 0x40,
- 0x00, 0x69, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x6f,
- 0x00, 0x72, 0x13, 0xe3, 0x61, 0x00, 0x75, 0x05, 0x78, 0x0a, 0x40, 0x09,
- 0x72, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x64, 0x00, 0x00, 0x09, 0x40, 0x08,
- 0x65, 0x65, 0x64, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65,
- 0x7d, 0x00, 0x68, 0xd9, 0x00, 0x69, 0xee, 0x00, 0x6c, 0x7b, 0x01, 0x6f,
- 0xda, 0x01, 0x72, 0x21, 0x03, 0x75, 0x86, 0x03, 0x03, 0x5b, 0xe4, 0x6c,
- 0x00, 0x6e, 0x0a, 0x70, 0x31, 0x72, 0x3b, 0x40, 0x00, 0x63, 0x75, 0x6c,
- 0x61, 0x62, 0x6c, 0x79, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x1a, 0xe1, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0x40, 0x06, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x0b, 0x61, 0x63,
- 0x69, 0x74, 0x61, 0x74, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x18, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x01, 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x06, 0x40, 0x3a, 0x69, 0x6e, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0x5c, 0x40, 0x75, 0x6f, 0x6e,
- 0x00, 0xe3, 0x6e, 0x00, 0x70, 0x26, 0x73, 0x2d, 0xe3, 0x64, 0x00, 0x73,
- 0x07, 0x74, 0x0b, 0x40, 0x06, 0x69, 0x61, 0x72, 0x79, 0x00, 0x40, 0x82,
- 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x27, 0x02, 0x01, 0xc3, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x06, 0x40, 0x3b,
- 0x61, 0x6e, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x07, 0xe1,
- 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00,
- 0x6f, 0x02, 0x77, 0x08, 0x00, 0x47, 0x40, 0x00, 0x61, 0x74, 0x65, 0x00,
- 0x40, 0x06, 0x6f, 0x72, 0x6d, 0x00, 0xe5, 0x64, 0x00, 0x6e, 0x1a, 0x70,
- 0x38, 0x73, 0x4c, 0x74, 0x72, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0x40, 0x86, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x1b, 0x00, 0x40, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x72, 0x06, 0x40, 0x09, 0x65, 0x6e, 0x74,
- 0x00, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x09, 0x75, 0x31,
- 0x00, 0x00, 0x40, 0x00, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x15, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x84,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x83, 0x40, 0x00, 0x73,
- 0x00, 0xe2, 0x64, 0x00, 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xf4, 0x67, 0x00, 0x00, 0x6d, 0x07, 0x00, 0x6e, 0x55, 0x00,
- 0x72, 0xdc, 0x00, 0x40, 0x09, 0x6e, 0x69, 0x74, 0x6f, 0x00, 0xe3, 0x62,
- 0x00, 0x6d, 0x0a, 0x70, 0x28, 0x40, 0x00, 0x75, 0x73, 0x74, 0x69, 0x62,
- 0x6c, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x10, 0xe1, 0x64, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0xed, 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00,
- 0x40, 0x00, 0x6e, 0x69, 0x63, 0x61, 0x64, 0x6f, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x0b, 0x6c, 0x12, 0x40, 0x08, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0x40, 0x09, 0x74, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b,
- 0x65, 0x74, 0x65, 0x00, 0xe5, 0x63, 0x00, 0x67, 0x0d, 0x73, 0x29, 0x74,
- 0x3c, 0x76, 0x72, 0x40, 0x07, 0x65, 0x69, 0x76, 0x61, 0x62, 0x69, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x74,
- 0x08, 0x40, 0x00, 0x6c, 0x61, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x3b, 0x61,
- 0x6e, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x1c, 0x72, 0x23, 0xe1, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x00, 0x6e, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x6f,
- 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x6c, 0x79, 0x00, 0x40, 0xed, 0x65,
- 0x6e, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x70, 0x00, 0x72, 0x26,
- 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x16, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x9e, 0x00, 0x37, 0x40, 0x75, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x61,
- 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x75, 0x23, 0x40, 0x3b, 0x63,
- 0x74, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x70, 0x74,
- 0x69, 0x62, 0x6c, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x32, 0x75, 0x54,
- 0xe2, 0x61, 0x00, 0x6d, 0x07, 0x40, 0x3b, 0x73, 0x69, 0x6e, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0xb1, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00,
- 0x40, 0x06, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x62,
- 0x00, 0x6c, 0x1e, 0x6d, 0x3b, 0x6e, 0x4f, 0x72, 0x66, 0xe2, 0x61, 0x00,
- 0x75, 0x15, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40,
- 0x09, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x70, 0x12, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x3a, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x62, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06,
- 0x79, 0x00, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40,
- 0x07, 0x6d, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x11, 0x72, 0x17,
- 0x73, 0x25, 0x03, 0x5d, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x75, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xf6, 0x00, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x69, 0x11, 0x01, 0x6f, 0x84, 0x02, 0x75, 0xd2,
- 0x02, 0x77, 0x8e, 0x03, 0x00, 0x00, 0xe9, 0x62, 0x00, 0x65, 0x16, 0x66,
- 0x1a, 0x6c, 0x5c, 0x6d, 0x6e, 0x6e, 0x8d, 0x73, 0xa8, 0x74, 0xc2, 0x78,
- 0xe8, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1b, 0x69, 0x33, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x00, 0x6e, 0x61, 0x62, 0x6c, 0x79, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00,
- 0x74, 0x10, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x02, 0xa1, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x07, 0x75, 0x0c, 0x40, 0x09, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x41, 0x20, 0x72, 0x65,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x0a, 0x40, 0x00, 0x72, 0x69, 0x62, 0x61,
- 0x62, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x72, 0x75, 0x63, 0x74, 0x69, 0x62,
- 0x6c, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x62, 0x00,
- 0x63, 0x05, 0x74, 0x09, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09,
- 0x00, 0xc3, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0xf8, 0x63, 0x00, 0x00, 0x65, 0x35, 0x00, 0x67, 0x37, 0x00, 0x72,
- 0x67, 0x00, 0x73, 0x6d, 0x00, 0x74, 0xee, 0x00, 0x75, 0xf2, 0x00, 0x76,
- 0xf6, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1d, 0x74, 0x21, 0xe1, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00, 0x73, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x56, 0x65, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0xc9, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x08, 0xe3, 0x65, 0x00,
- 0x6e, 0x15, 0x6f, 0x27, 0xe1, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x6f, 0x04,
- 0x74, 0x09, 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00,
- 0x56, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x3b, 0x74,
- 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x3b, 0x65,
- 0x63, 0x74, 0x00, 0xe4, 0x63, 0x00, 0x70, 0x2a, 0x73, 0x4e, 0x74, 0x6a,
- 0xe2, 0x69, 0x00, 0x72, 0x08, 0x40, 0x00, 0x70, 0x6c, 0x69, 0x6e, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe2, 0x65, 0x00, 0x74, 0x04, 0x40,
- 0x3b, 0x74, 0x00, 0x40, 0x08, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x3b, 0x6d,
- 0x69, 0x6e, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x00, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x00,
- 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x61, 0x62, 0x6c, 0x79, 0x00,
- 0x40, 0x0b, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x55, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c,
- 0x00, 0x74, 0x3e, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe3, 0x73,
- 0x00, 0x74, 0x1e, 0x7a, 0x22, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x69, 0x62, 0x6c, 0x79, 0x00,
- 0xe3, 0x63, 0x00, 0x6c, 0x1e, 0x6d, 0x2f, 0xe1, 0x74, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x62, 0x00, 0x63, 0x18, 0x6c,
- 0x50, 0x73, 0x68, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x11, 0xe3, 0x00, 0x00, 0x6d,
- 0x02, 0x72, 0x08, 0x01, 0x18, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x00,
- 0x07, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x03, 0x5e,
- 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3a,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x3b, 0xe1,
- 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x3e, 0xe2, 0x61,
- 0x00, 0x6f, 0x26, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x06, 0x41, 0x21, 0x65, 0x6c, 0x6c, 0x00, 0xfa, 0x62, 0x00, 0x00,
- 0x64, 0x18, 0x00, 0x66, 0x1f, 0x00, 0x6c, 0x48, 0x00, 0x70, 0x83, 0x00,
- 0x71, 0x9c, 0x00, 0x72, 0xa5, 0x00, 0x73, 0xc3, 0x00, 0x76, 0xe9, 0x00,
- 0x78, 0x0a, 0x01, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x86, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x69, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x66,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x18, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x63, 0x69, 0x65, 0x6e,
- 0x63, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x07, 0x75, 0x1c, 0x40, 0x00,
- 0x73, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x09,
- 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x09,
- 0x00, 0x3e, 0x40, 0x07, 0x74, 0x75, 0x64, 0x65, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x08, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x0e, 0x00, 0x3e,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x18, 0xe1,
- 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x69, 0x6d, 0x61, 0x62, 0x6c, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c,
- 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x05, 0x6f, 0x10,
- 0x70, 0x2e, 0x74, 0x71, 0x40, 0x3b, 0x63, 0x74, 0x00, 0x40, 0x00, 0x61,
- 0x75, 0x73, 0x74, 0x69, 0x62, 0x6c, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x00,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x10, 0x6c, 0x17, 0x72, 0x20, 0xe2,
- 0x64, 0x00, 0x72, 0x07, 0x40, 0x00, 0x69, 0x65, 0x6e, 0x74, 0x00, 0x40,
- 0x3b, 0x74, 0x00, 0x40, 0x00, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00,
- 0x69, 0x63, 0x61, 0x62, 0x6c, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x62, 0x00, 0x76, 0x05,
- 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x72,
- 0x69, 0x63, 0x61, 0x62, 0x6c, 0x79, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x65, 0x78, 0x00, 0x69, 0x0c, 0x01, 0x6c, 0x7c, 0x01, 0x6f,
- 0x27, 0x02, 0x72, 0x88, 0x02, 0x75, 0xe6, 0x02, 0x03, 0x5f, 0xe5, 0x6c,
- 0x00, 0x6d, 0x08, 0x6e, 0x0c, 0x72, 0x44, 0x74, 0x56, 0x40, 0x00, 0x6c,
- 0x69, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72,
- 0x11, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x6c, 0x06, 0x40, 0x09, 0x69, 0x64,
- 0x65, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x63, 0x00, 0x6c,
- 0x2a, 0x72, 0x34, 0x73, 0x7a, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x00, 0xb3, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x6f, 0x00,
- 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x65, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x69, 0x63, 0x69, 0x74, 0x6f, 0x75, 0x73, 0x00, 0xe4, 0x65, 0x00,
- 0x69, 0x12, 0x6e, 0x24, 0x72, 0x2f, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40,
- 0x3b, 0x6c, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x0b, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe5, 0x64, 0x00, 0x6c, 0x12, 0x6e, 0x1b, 0x72, 0x4d, 0x78, 0x63, 0xe1,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x08, 0x74, 0x79, 0x00, 0x40, 0x06, 0x74, 0x72, 0x61, 0x74, 0x6f,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x0e, 0x75, 0x1c, 0x79, 0x21, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x18,
- 0x40, 0x56, 0x69, 0x6d, 0x61, 0x6c, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0x40, 0x07, 0x64,
- 0x65, 0x00, 0x00, 0x06, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x07, 0x00, 0x00, 0x40, 0x06, 0x72, 0x79, 0x00, 0x40, 0x06, 0x74,
- 0x79, 0x00, 0x00, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x49, 0x69, 0x67, 0x6f,
- 0x79, 0x75, 0x7d, 0xe2, 0x6d, 0x00, 0x74, 0x23, 0xe2, 0x65, 0x00, 0x6d,
- 0x02, 0x00, 0x3a, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40,
- 0x00, 0x6c, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06,
- 0x69, 0x08, 0x40, 0x06, 0x62, 0x6c, 0x65, 0x00, 0x03, 0x60, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x84, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x7a, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xe2, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x77, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x74, 0x0c, 0x7a, 0x12, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x82, 0x00, 0x37, 0x40, 0x3b, 0x69,
- 0x61, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe4, 0x00, 0x00, 0x6d, 0x02,
- 0x72, 0x0b, 0x74, 0x4e, 0x00, 0x07, 0x40, 0x06, 0x65, 0x72, 0x63, 0x69,
- 0x61, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x35, 0x02, 0x39, 0xe3, 0x6c, 0x00, 0x6e, 0x02, 0x74, 0x06, 0x00, 0x3b,
- 0x40, 0x06, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0e,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x84, 0x40, 0x00,
- 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x07,
- 0x61, 0x69, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x36, 0x69, 0x4d, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x07, 0x00, 0x00,
- 0x40, 0x07, 0x65, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x06, 0x40, 0x00,
- 0x6e, 0x69, 0x63, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x06, 0xe1, 0x71, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x40, 0x09, 0x6e, 0x67,
- 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x15, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x0b, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x65, 0x72,
- 0x00, 0xe5, 0x65, 0x00, 0x6c, 0x50, 0x6f, 0x58, 0x72, 0x5c, 0x75, 0x9b,
- 0xe2, 0x6e, 0x00, 0x73, 0x3c, 0xe2, 0x69, 0x00, 0x75, 0x16, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x06, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x7a, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x6e,
- 0x6f, 0x6f, 0x6b, 0x00, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x2a, 0xe2, 0x69, 0x00, 0x74, 0x04, 0x40, 0x1c, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40,
- 0x3b, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x07,
- 0x40, 0x09, 0x69, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40,
- 0x00, 0x69, 0x6e, 0x61, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x52, 0x69,
- 0x87, 0x75, 0xaa, 0xe3, 0x62, 0x00, 0x6c, 0x21, 0x72, 0x41, 0xe1, 0x69,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x10, 0x01,
- 0x20, 0xe2, 0x62, 0x00, 0x6e, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x17,
- 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x05, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x00, 0x6d, 0x6f, 0x6e, 0x69, 0x6f, 0x75, 0x73,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3a, 0x40, 0x3b, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x6f, 0x14, 0x00, 0x88, 0xe1, 0x6e, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x84,
- 0x00, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0xad,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x06, 0x00, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3b, 0x00, 0x3b, 0xe3,
- 0x6d, 0x00, 0x71, 0x14, 0x74, 0x29, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x61, 0x62, 0x6c,
- 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x6f, 0x00, 0x79, 0x05, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00,
- 0x74, 0x25, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xfd, 0xe2, 0x73, 0x00,
- 0x7a, 0x04, 0x40, 0x00, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x3a, 0x01, 0xca, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x16, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x03, 0x61, 0x00, 0x37, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x75,
- 0x18, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x7a, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe3, 0x00, 0x00,
- 0x64, 0x02, 0x72, 0x04, 0x01, 0x4b, 0x00, 0x37, 0x00, 0x07, 0x40, 0x00,
- 0x6f, 0x75, 0x73, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x69, 0x08, 0x6a,
- 0x0f, 0x6c, 0x14, 0x73, 0x1a, 0x77, 0x21, 0x79, 0x27, 0x00, 0x20, 0x40,
- 0x06, 0x6c, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x65, 0x74, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x74, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x65, 0x6c, 0x6c, 0x00,
- 0x00, 0xf4, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x6e, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06,
- 0x74, 0x65, 0x00, 0x40, 0x00, 0x73, 0x74, 0x00, 0xe7, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x1c, 0x69, 0x4f, 0x6b, 0x5a, 0x6f, 0x62, 0x75, 0xb0, 0x03,
- 0x62, 0xe2, 0x72, 0x00, 0x74, 0x05, 0x40, 0x07, 0x64, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x6d, 0x00, 0x73, 0x06, 0x76,
- 0x17, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x70, 0x05,
- 0x40, 0x06, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x72, 0x69, 0x6e, 0x67, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x67, 0x00, 0x00, 0x00, 0x40, 0x09, 0x65, 0x65, 0x70, 0x65, 0x72,
- 0x00, 0xe2, 0x63, 0x00, 0x76, 0x29, 0xe2, 0x65, 0x00, 0x75, 0x0e, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x86, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x73, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x06,
- 0x40, 0x06, 0x6e, 0x64, 0x6f, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x79,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x70, 0x18, 0x72, 0x22,
- 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x4b, 0x40, 0x09, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x65, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x64,
- 0x00, 0x67, 0x08, 0x40, 0x3b, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x00, 0x40,
- 0x00, 0x61, 0x6e, 0x69, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x72, 0x00, 0x73, 0x17, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x2d, 0x00, 0x07, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x23, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x75, 0x73, 0x68, 0x00, 0xf9,
- 0x61, 0x00, 0x00, 0x63, 0x22, 0x00, 0x65, 0x6b, 0x00, 0x68, 0x17, 0x01,
- 0x69, 0x1d, 0x01, 0x6f, 0xb1, 0x01, 0x70, 0x1e, 0x02, 0x74, 0x70, 0x02,
- 0x75, 0xce, 0x03, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x42, 0x2b, 0x65, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x79,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x18, 0xe2, 0x62, 0x00,
- 0x70, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x2d,
- 0x00, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0xe7, 0x61, 0x00, 0x63, 0x04, 0x6d, 0x39, 0x6e, 0x51, 0x70,
- 0x6e, 0x72, 0x77, 0x74, 0x96, 0x40, 0x06, 0x6d, 0x00, 0xe2, 0x74, 0x00,
- 0x75, 0x2b, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x76, 0x11, 0xe1, 0x69,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c,
- 0x00, 0x00, 0x09, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x02, 0x00, 0x09, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x3b, 0x72,
- 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x00,
- 0x74, 0x65, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x65,
- 0x00, 0x40, 0x3b, 0x69, 0x76, 0x65, 0x00, 0x40, 0x09, 0x61, 0x72, 0x61,
- 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02,
- 0x69, 0x06, 0x00, 0x61, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0x40,
- 0x00, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x65, 0x00,
- 0xe5, 0x64, 0x00, 0x67, 0x24, 0x6e, 0x3d, 0x70, 0x58, 0x73, 0x6a, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x94, 0x00,
- 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x68, 0x00, 0x6e, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x75, 0x6c, 0x00, 0x40, 0x07, 0x69, 0x61, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x01, 0xc8, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x10, 0x00, 0x5b, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0xe4, 0x66, 0x00, 0x6c, 0x05, 0x6d, 0x34, 0x75,
- 0x4d, 0x40, 0x00, 0x61, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x75, 0x12, 0x76,
- 0x21, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x62, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08,
- 0x65, 0x6e, 0x63, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x0f, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x00, 0x63, 0x68, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x23, 0xe1, 0x63,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0x4b, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x09, 0x40, 0x09, 0x74, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x17, 0x69, 0x1b, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x37,
- 0x6e, 0x67, 0x00, 0xf5, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x62,
- 0x00, 0x69, 0x67, 0x00, 0x72, 0xe6, 0x00, 0x00, 0x00, 0xe5, 0x62, 0x00,
- 0x6c, 0x08, 0x6e, 0x23, 0x72, 0x4f, 0x74, 0x51, 0x40, 0x08, 0x69, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x07,
- 0x6d, 0x0b, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x43, 0x63, 0x72,
- 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0xed, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x0a, 0x03,
- 0x64, 0x40, 0x3b, 0x6e, 0x65, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3a, 0x40, 0x08,
- 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x40, 0x4b, 0x65, 0x00, 0x40, 0x00, 0x61,
- 0x64, 0x00, 0xe4, 0x67, 0x00, 0x6c, 0x18, 0x6e, 0x21, 0x74, 0x3a, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x07, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75, 0x07, 0x01, 0xe4, 0x40,
- 0x3b, 0x76, 0x65, 0x00, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x03, 0x65, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe2, 0x00, 0x00,
- 0x75, 0x02, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x2d, 0xe1, 0x74, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6f, 0x1d, 0x01, 0xe2, 0x40,
- 0x37, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x3b,
- 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x47, 0xe2, 0x6c,
- 0x00, 0x74, 0x14, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe2, 0x73,
- 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x62, 0x00, 0x66, 0x0b, 0x6c, 0x26,
- 0x70, 0x60, 0x72, 0x78, 0x40, 0x00, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61,
- 0x74, 0x65, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x23, 0x74,
- 0x27, 0xe2, 0x72, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x06, 0x67, 0x13, 0x6d,
- 0x29, 0x72, 0x34, 0x40, 0x06, 0x6e, 0x63, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x64, 0x02, 0x72, 0x04, 0x02, 0x35, 0x00, 0x06, 0x00, 0x07, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x09, 0x40, 0x00, 0x6f, 0x75,
- 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06, 0x73, 0x74,
- 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x11, 0x00, 0x69,
- 0xdc, 0x06, 0x6c, 0x16, 0x07, 0x6f, 0x18, 0x07, 0x72, 0x43, 0x07, 0x75,
- 0xa5, 0x08, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x67, 0x04, 0x40, 0x00, 0x74,
- 0x00, 0x40, 0x09, 0x6c, 0x69, 0x6f, 0x00, 0xf5, 0x67, 0x00, 0x00, 0x6c,
- 0x39, 0x00, 0x6e, 0xa0, 0x00, 0x72, 0x06, 0x01, 0x73, 0x98, 0x06, 0xe3,
- 0x65, 0x00, 0x72, 0x04, 0x75, 0x2b, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x1d, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x56, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x0b, 0x03, 0x66, 0x63, 0x67, 0x6f, 0x6e, 0x00,
- 0xb4, 0x00, 0xff, 0xff, 0x40, 0x00, 0x72, 0x00, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0x40, 0x06, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x27, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x75, 0x02, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40,
- 0x07, 0x6d, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x18, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x3b, 0x40, 0x07,
- 0x69, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x37, 0x00, 0x37, 0xe3, 0x64, 0x00, 0x73, 0x05, 0x74, 0x3f, 0x40, 0x06,
- 0x65, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0x68, 0xe3, 0x66,
- 0x00, 0x74, 0x18, 0x76, 0x1c, 0xe2, 0x69, 0x00, 0x79, 0x11, 0xe2, 0x63,
- 0x00, 0x65, 0x08, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0x02, 0x7c, 0x40, 0x08, 0x79, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x44, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x13, 0x02, 0x12, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40,
- 0x36, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xc1, 0x61, 0x17,
- 0x33, 0x00, 0x35, 0x00, 0x57, 0x00, 0x68, 0x00, 0x47, 0x01, 0xa6, 0x01,
- 0xbe, 0x01, 0xf0, 0x01, 0x00, 0x00, 0x0b, 0x02, 0x16, 0x02, 0x00, 0x00,
- 0x2f, 0x02, 0xa2, 0x02, 0x17, 0x03, 0x97, 0x03, 0x9f, 0x03, 0x00, 0x00,
- 0x20, 0x04, 0xa9, 0x04, 0x13, 0x05, 0x1a, 0x05, 0x21, 0x05, 0x72, 0x05,
- 0x03, 0x69, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x02, 0x07, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x00, 0x74, 0x79, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00,
- 0x00, 0x40, 0x3c, 0x64, 0x00, 0xe5, 0x65, 0x00, 0x68, 0x39, 0x69, 0x64,
- 0x6f, 0x69, 0x75, 0xcb, 0xe3, 0x64, 0x00, 0x70, 0x04, 0x73, 0x19, 0x40,
- 0x0b, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x59, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6f, 0x6e,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x5e, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x00, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x74, 0x79,
- 0x00, 0xe4, 0x6c, 0x00, 0x6d, 0x0a, 0x6e, 0x2f, 0x75, 0x53, 0x40, 0x00,
- 0x6c, 0x65, 0x67, 0x69, 0x61, 0x74, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x6e, 0x00,
- 0x74, 0x15, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x72,
- 0x73, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x3a, 0xe2, 0x6e, 0x00, 0x70, 0x0e, 0x40, 0x00,
- 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x0b, 0x40, 0x00, 0x72, 0x74, 0x6d, 0x65, 0x6e,
- 0x74, 0x61, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x3b, 0xe2, 0x63, 0x00, 0x73, 0x0f, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x59, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x63, 0x69, 0x70, 0x6c, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x03, 0x6a, 0x40, 0x37, 0x64, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x0e, 0x69, 0x26, 0xe2, 0x63, 0x00, 0x69, 0x04, 0x40,
- 0x82, 0x65, 0x00, 0x40, 0x00, 0x74, 0x68, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x0c, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x0b, 0x40,
- 0x07, 0x63, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x0b, 0x6c, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x09, 0x40, 0x00, 0x6c, 0x61, 0x63, 0x74,
- 0x69, 0x63, 0x00, 0x40, 0x00, 0x76, 0x65, 0x72, 0x6e, 0x6d, 0x65, 0x6e,
- 0x74, 0x61, 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40,
- 0x06, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40,
- 0x06, 0x6f, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x0d, 0x69, 0x1d, 0x6f,
- 0x39, 0x75, 0x63, 0xe2, 0x63, 0x00, 0x72, 0x04, 0x40, 0x0b, 0x65, 0x00,
- 0x40, 0x72, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40, 0x3a, 0x76,
- 0x65, 0x00, 0x40, 0x07, 0x6b, 0x69, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x0b, 0x6b, 0x10, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x01,
- 0x32, 0x40, 0x00, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x3a,
- 0xe2, 0x63, 0x00, 0x70, 0x19, 0xe2, 0x6b, 0x00, 0x75, 0x02, 0x00, 0x59,
- 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0x40, 0x82, 0x64, 0x65, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x13, 0x69, 0x45, 0xe1, 0x72, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x06, 0x61, 0x67, 0x65, 0x00, 0x00,
- 0x0b, 0xe3, 0x64, 0x00, 0x6e, 0x13, 0x7a, 0x1f, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x40,
- 0x86, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x84, 0x00, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02, 0x00,
- 0x00, 0x00, 0x09, 0xe4, 0x6e, 0x00, 0x73, 0x10, 0x74, 0x17, 0x78, 0x1e,
- 0xe2, 0x61, 0x00, 0x67, 0x06, 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0x40,
- 0x3a, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x40,
- 0x3b, 0x74, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x0b, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x51, 0x69, 0x62, 0x6d, 0x67, 0x73, 0x6d, 0x03, 0x6b, 0xe2,
- 0x6c, 0x00, 0x74, 0x18, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03, 0x6c, 0xe1,
- 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x0b, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x56, 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x00, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe3, 0x63, 0x00, 0x65, 0x06, 0x74,
- 0x08, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x00, 0x00, 0x06, 0x00, 0x00, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09,
- 0x68, 0x69, 0x70, 0x00, 0x40, 0x00, 0x66, 0x66, 0x69, 0x63, 0x65, 0x00,
- 0xe4, 0x65, 0x00, 0x6c, 0x16, 0x6f, 0x28, 0x72, 0x4d, 0xe2, 0x6e, 0x00,
- 0x72, 0x09, 0x40, 0x57, 0x65, 0x74, 0x72, 0x61, 0x74, 0x65, 0x00, 0x40,
- 0x00, 0x73, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e,
- 0x00, 0x79, 0x08, 0x40, 0x00, 0x65, 0x74, 0x61, 0x72, 0x79, 0x00, 0x00,
- 0x07, 0xe2, 0x6c, 0x00, 0x73, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x15, 0x00, 0x79, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x76, 0x04, 0x40, 0x69, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x09, 0xe5, 0x61, 0x00,
- 0x65, 0x07, 0x69, 0x36, 0x6f, 0x3b, 0x75, 0x66, 0x40, 0x00, 0x63, 0x69,
- 0x61, 0x6c, 0x00, 0xe3, 0x64, 0x00, 0x67, 0x02, 0x6c, 0x08, 0x00, 0x8f,
- 0x40, 0x06, 0x6e, 0x75, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x26, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x09, 0x68, 0x69,
- 0x70, 0x00, 0x40, 0x8f, 0x6e, 0x67, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x02,
- 0x7d, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x86,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0x06, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x6f,
- 0x6e, 0x00, 0xe4, 0x63, 0x00, 0x65, 0x0b, 0x70, 0x2a, 0x74, 0x3f, 0x40,
- 0x00, 0x68, 0x6f, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x00, 0xe3, 0x63,
- 0x00, 0x73, 0x0f, 0x78, 0x16, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x0b, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x73, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0c, 0x40, 0x09, 0x74,
- 0x65, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x61, 0x72, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6c, 0x00,
- 0x40, 0x0b, 0x77, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x72, 0x62, 0x61,
- 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x69, 0x2a, 0x6f, 0x40, 0x40,
- 0x06, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00,
- 0x0b, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x77, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00,
- 0x09, 0x00, 0x07, 0x40, 0x00, 0x63, 0x61, 0x6c, 0x69, 0x63, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x04, 0x6f, 0x0a, 0x40, 0x00, 0x72, 0x00, 0x40, 0x3c,
- 0x61, 0x76, 0x65, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x0d, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x15, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x03, 0x6d, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x42, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x78, 0x08, 0x40,
- 0x06, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x63, 0x00, 0x69, 0x78, 0x00, 0x6f,
- 0xbb, 0x00, 0x75, 0x25, 0x01, 0xe6, 0x63, 0x00, 0x6d, 0x09, 0x6e, 0x1e,
- 0x73, 0x3e, 0x75, 0x45, 0x76, 0x4e, 0x40, 0x00, 0x72, 0x61, 0x6e, 0x69,
- 0x61, 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x05, 0x40,
- 0x00, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x63, 0x75, 0x6c, 0x61, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40, 0x09, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x86, 0x40, 0x00, 0x74, 0x61,
- 0x74, 0x65, 0x00, 0x40, 0x00, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x65, 0x00,
- 0x41, 0x81, 0x65, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0xe3, 0x63, 0x00, 0x67, 0x10, 0x6e, 0x26,
- 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00,
- 0x40, 0x3b, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe5, 0x00, 0x00, 0x64, 0x02, 0x69, 0x28, 0x73, 0x2c, 0x76, 0x4c, 0x00,
- 0x06, 0xe1, 0x75, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02,
- 0x00, 0x4b, 0xe2, 0x69, 0x00, 0x6f, 0x0f, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0x40, 0x06, 0x74, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x43, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x3b, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x06, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0xb2, 0xe2, 0x64,
- 0x00, 0x73, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01,
- 0x4b, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40,
- 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xe2, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x08, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6e, 0x00,
- 0x72, 0x15, 0xe1, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x01, 0x26, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0xf4, 0x61, 0x00, 0x00, 0x65, 0x52, 0x00, 0x69, 0x18,
- 0x01, 0x6f, 0xda, 0x01, 0xe4, 0x64, 0x00, 0x6c, 0x0c, 0x72, 0x32, 0x73,
- 0x39, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00,
- 0x07, 0xe2, 0x69, 0x00, 0x75, 0x0f, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x03, 0x17, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6e, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0xe6, 0x63, 0x00, 0x69, 0x07, 0x6e, 0x24, 0x72, 0x55, 0x73,
- 0x60, 0x74, 0xa3, 0x40, 0x07, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x68, 0x00, 0x6c, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0xed, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x1b, 0x01, 0xbb, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x69, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x09, 0x00, 0x5e, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x56, 0x65,
- 0x00, 0x00, 0x2c, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6d,
- 0x2d, 0x6f, 0x33, 0x03, 0x6e, 0xe2, 0x67, 0x00, 0x74, 0x20, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x01,
- 0xc8, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0x40, 0x09, 0x75, 0x72, 0x65, 0x00,
- 0x40, 0xc2, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe5, 0x64, 0x00, 0x67,
- 0x19, 0x6e, 0x4f, 0x6f, 0x68, 0x74, 0x87, 0xe1, 0x69, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x14, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x02, 0x00, 0x42, 0x40, 0x08, 0x72, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0xab, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40,
- 0x00, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00,
- 0x74, 0x10, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74,
- 0x79, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x17, 0x69, 0x24, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0x40, 0x06, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x65, 0x04, 0x00,
- 0x5e, 0x00, 0x37, 0x00, 0x06, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x6b,
- 0x00, 0x6c, 0x04, 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x75, 0x00, 0x76, 0x22,
- 0xe2, 0x6e, 0x00, 0x74, 0x17, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x5d, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x78, 0x40, 0x06, 0x65, 0x6e,
- 0x74, 0x00, 0x43, 0x6c, 0x61, 0x72, 0x64, 0x00, 0xe4, 0x63, 0x00, 0x64,
- 0x05, 0x6e, 0x1b, 0x74, 0x5a, 0x40, 0x00, 0x74, 0x6c, 0x00, 0xe1, 0x69,
- 0x00, 0xe3, 0x64, 0x00, 0x6e, 0x04, 0x7a, 0x08, 0x40, 0x06, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x6f, 0x1e, 0x01, 0x99, 0xe2, 0x63, 0x00, 0x7a, 0x02, 0x00, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0xdb, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xf1, 0x00, 0x09, 0xe1, 0x73, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x40,
- 0x09, 0x61, 0x00, 0x40, 0x06, 0x65, 0x63, 0x61, 0x63, 0x00, 0xf6, 0x61,
- 0x00, 0x00, 0x65, 0x33, 0x00, 0x69, 0x46, 0x00, 0x6b, 0x72, 0x00, 0x6f,
- 0x8f, 0x00, 0x72, 0xf5, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x1e, 0xe1, 0x63,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07,
- 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x66,
- 0x02, 0x6e, 0x07, 0x00, 0x07, 0x40, 0x00, 0x75, 0x6c, 0x00, 0x40, 0x00,
- 0x69, 0x63, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x25, 0xe2, 0x65, 0x00, 0x69,
- 0x1b, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x3b, 0x40, 0x07, 0x75, 0x6d, 0x00, 0x00, 0x09, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x5b, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe7, 0x00, 0x00, 0x63, 0x02,
- 0x69, 0x08, 0x6d, 0x1c, 0x73, 0x34, 0x77, 0x3b, 0x79, 0x52, 0x00, 0x47,
- 0x40, 0x09, 0x6c, 0x61, 0x64, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x0b, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07,
- 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x08,
- 0x00, 0x00, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x05, 0x40, 0x07, 0x72, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x04,
- 0x40, 0x09, 0x64, 0x00, 0x40, 0x07, 0x6b, 0x00, 0x00, 0x06, 0xf4, 0x61,
- 0x00, 0x00, 0x65, 0x35, 0x00, 0x69, 0x93, 0x02, 0x75, 0xe8, 0x02, 0xe2,
- 0x64, 0x00, 0x74, 0x15, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0xfa, 0x63, 0x00, 0x00, 0x64, 0x50, 0x00, 0x66,
- 0x82, 0x00, 0x67, 0x9a, 0x00, 0x6c, 0xbd, 0x00, 0x6d, 0xef, 0x00, 0x70,
- 0x14, 0x01, 0x73, 0x72, 0x01, 0x74, 0xdf, 0x01, 0x76, 0xfd, 0x01, 0xe2,
- 0x6c, 0x00, 0x6f, 0x0a, 0x40, 0x00, 0x61, 0x69, 0x6d, 0x61, 0x62, 0x6c,
- 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x76, 0x24, 0xe1, 0x63, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x18,
- 0xe1, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x61, 0x00,
- 0x75, 0x09, 0x40, 0x00, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x86, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x19, 0xe1, 0x76, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x09,
- 0x00, 0x3b, 0xe1, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x6e, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x18, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x76, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe3,
- 0x61, 0x00, 0x6c, 0x15, 0x72, 0x1f, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x61, 0x63, 0x65, 0x61, 0x62, 0x6c, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x18, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x69, 0x00,
- 0x6f, 0x18, 0x70, 0x38, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02,
- 0x52, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x08, 0x40, 0x00, 0x63, 0x74, 0x69, 0x76, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62,
- 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x28, 0xe1, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x73, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x69, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x67,
- 0x00, 0x74, 0x19, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40,
- 0x00, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x62, 0x00, 0x6e, 0x15,
- 0x74, 0x19, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c, 0xe2, 0x6e,
- 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1,
- 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x3d,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xf8, 0x63, 0x00, 0x00, 0x69, 0x15, 0x00,
- 0x6c, 0x1e, 0x00, 0x6d, 0x41, 0x00, 0x6e, 0x4a, 0x00, 0x6f, 0x4f, 0x00,
- 0x73, 0xf9, 0x00, 0x74, 0x10, 0x01, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x13, 0x00, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x0f, 0x40, 0x07,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x01, 0x52, 0x00, 0x00, 0x40, 0x00, 0x27, 0x74,
- 0x00, 0xe5, 0x62, 0x00, 0x6c, 0x11, 0x6d, 0x37, 0x73, 0x75, 0x74, 0x7d,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x02, 0xa4, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x6f, 0x31,
- 0xe2, 0x72, 0x00, 0x74, 0x12, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00,
- 0x07, 0x40, 0x00, 0x72, 0x70, 0x68, 0x69, 0x63, 0x00, 0x40, 0x00, 0x63,
- 0x65, 0x6c, 0x65, 0x73, 0x00, 0xe3, 0x68, 0x00, 0x6f, 0x06, 0x72, 0x14,
- 0x40, 0x06, 0x65, 0x72, 0x6d, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00, 0x6f, 0x70,
- 0x69, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40,
- 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x85,
- 0x00, 0x09, 0xe1, 0x68, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x75,
- 0x05, 0x40, 0x00, 0x61, 0x6e, 0x00, 0x40, 0x09, 0x73, 0x00, 0xe7, 0x00,
- 0x00, 0x27, 0x02, 0x61, 0x0d, 0x63, 0x36, 0x65, 0x4b, 0x69, 0x80, 0x73,
- 0x99, 0x01, 0x99, 0xe2, 0x64, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x13, 0x00, 0x06,
- 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x47, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x15, 0xe2, 0x6d, 0x00, 0x72, 0x18, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x03, 0x6f,
- 0x40, 0x75, 0x6f, 0x6e, 0x00, 0x40, 0x08, 0x72, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00,
- 0x72, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x00,
- 0x65, 0x6c, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x79, 0x07, 0x00,
- 0x37, 0x40, 0x06, 0x72, 0x79, 0x00, 0x00, 0x1a, 0x00, 0x00, 0xf9, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0xa8, 0x02, 0x65, 0xac, 0x02, 0x67,
- 0x39, 0x04, 0x69, 0x3b, 0x04, 0x6f, 0x65, 0x05, 0x70, 0x8d, 0x08, 0x75,
- 0x92, 0x08, 0x02, 0xcb, 0xc0, 0x62, 0x19, 0x35, 0x00, 0x5e, 0x00, 0xd5,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x44, 0x01, 0x5f, 0x01, 0x90, 0x01, 0x00, 0x00, 0xb9,
- 0x01, 0x00, 0x00, 0xd8, 0x01, 0x06, 0x02, 0x16, 0x02, 0x1a, 0x02, 0x42,
- 0x02, 0x4f, 0x02, 0x00, 0x00, 0x70, 0x02, 0x9a, 0x02, 0xe3, 0x00, 0x00,
- 0x62, 0x02, 0x6f, 0x1e, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x12, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01,
- 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0xe3, 0x61, 0x00, 0x6b, 0x08, 0x71, 0x69, 0x40, 0x09, 0x72,
- 0x61, 0x6e, 0x64, 0x61, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x62, 0x0d,
- 0x64, 0x13, 0x65, 0x18, 0x68, 0x1c, 0x6b, 0x24, 0x70, 0x38, 0x72, 0x3d,
- 0x73, 0x45, 0x00, 0x55, 0xe2, 0x6c, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40,
- 0x09, 0x73, 0x00, 0x40, 0xb1, 0x6f, 0x6f, 0x74, 0x00, 0x40, 0x09, 0x61,
- 0x77, 0x00, 0x40, 0xb1, 0x74, 0x00, 0x40, 0x09, 0x61, 0x6d, 0x6d, 0x65,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00, 0x76,
- 0x04, 0x40, 0x82, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40, 0x09,
- 0x6f, 0x74, 0x00, 0x40, 0x09, 0x61, 0x62, 0x62, 0x69, 0x74, 0x00, 0x40,
- 0x09, 0x74, 0x72, 0x61, 0x77, 0x00, 0x40, 0x07, 0x75, 0x61, 0x72, 0x64,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x69, 0x0f, 0x00,
- 0x82, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x74, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02,
- 0x75, 0x1c, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x10, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x46, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40, 0x06, 0x61, 0x72, 0x00, 0xe1,
- 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x12, 0x68, 0x16, 0x00,
- 0xfe, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40,
- 0x06, 0x65, 0x61, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x6f,
- 0x75, 0x73, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40, 0x09, 0x70,
- 0x65, 0x6e, 0x6f, 0x00, 0xe2, 0x70, 0x00, 0x75, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0x40, 0x09, 0x73, 0x69, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02,
- 0x6d, 0x18, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x09, 0x00,
- 0x09, 0x40, 0x07, 0x6c, 0x61, 0x79, 0x61, 0x00, 0x40, 0x09, 0x72, 0x65,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0xe2, 0x67, 0x00, 0x69,
- 0x0f, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x7e, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x61, 0x6c,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x18, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x82, 0xe5, 0x00, 0x00, 0x64,
- 0x02, 0x66, 0x0b, 0x67, 0x10, 0x72, 0x15, 0x00, 0x06, 0x40, 0x06, 0x69,
- 0x6e, 0x69, 0x65, 0x72, 0x65, 0x00, 0x40, 0x09, 0x75, 0x6c, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x06, 0x40,
- 0x06, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x40, 0x09,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x06, 0x40, 0x5e,
- 0x69, 0x63, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00,
- 0x93, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x40, 0x06, 0x6c, 0x69, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02,
- 0x6c, 0x14, 0x00, 0x93, 0xe2, 0x6f, 0x00, 0x72, 0x05, 0x40, 0x5e, 0x6e,
- 0x65, 0x00, 0x40, 0x09, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x08,
- 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x77, 0x08, 0x00,
- 0x06, 0x40, 0x06, 0x69, 0x72, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01,
- 0x4b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x7a,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x47, 0x00, 0x60, 0x40, 0x00,
- 0x74, 0x00, 0xfb, 0x61, 0x00, 0x00, 0x65, 0x20, 0x00, 0x6a, 0x37, 0x00,
- 0x6c, 0x4c, 0x00, 0x6d, 0x7f, 0x00, 0x6e, 0x84, 0x00, 0x6f, 0x92, 0x00,
- 0x72, 0xaa, 0x00, 0x73, 0x05, 0x01, 0x74, 0x1a, 0x01, 0x77, 0x54, 0x01,
- 0xe2, 0x6c, 0x00, 0x6e, 0x12, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x3b, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe3, 0x70, 0x00, 0x72,
- 0x02, 0x7a, 0x0e, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x47,
- 0x40, 0x12, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6e,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x02, 0x75, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02,
- 0x79, 0x04, 0x00, 0x3a, 0x00, 0x08, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x66,
- 0x08, 0x6c, 0x0e, 0x72, 0x14, 0x00, 0xa1, 0x40, 0x09, 0x65, 0x61, 0x6e,
- 0x00, 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65,
- 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x6c, 0x00, 0x40, 0x0b, 0x6d, 0x79, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x09, 0x74, 0x00,
- 0x00, 0x06, 0xe1, 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x0b, 0x7a, 0x65, 0x00,
- 0x00, 0x07, 0xe5, 0x65, 0x00, 0x6b, 0x07, 0x6f, 0x30, 0x72, 0x37, 0x73,
- 0x4b, 0x40, 0x09, 0x6d, 0x69, 0x61, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x69,
- 0x02, 0x77, 0x17, 0x79, 0x1e, 0x00, 0x47, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40,
- 0x07, 0x73, 0x73, 0x00, 0x40, 0x00, 0x61, 0x74, 0x65, 0x72, 0x00, 0x03,
- 0x70, 0x40, 0x08, 0x62, 0x6f, 0x61, 0x6d, 0x00, 0xe1, 0x79, 0x00, 0xe2,
- 0x62, 0x00, 0x63, 0x07, 0x40, 0x00, 0x75, 0x69, 0x6c, 0x74, 0x00, 0x40,
- 0x08, 0x61, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x79, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x6c, 0x02, 0x70,
- 0x09, 0x73, 0x0f, 0x74, 0x14, 0x00, 0x06, 0x40, 0x06, 0x69, 0x6e, 0x65,
- 0x72, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x74, 0x00, 0x40, 0x07, 0x61, 0x6d,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x12, 0x40, 0x00, 0x64, 0x00,
- 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x00, 0x67, 0x00, 0x40, 0x47, 0x6f,
- 0x6e, 0x00, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x72, 0x06, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x06, 0x79, 0x00, 0x00, 0x00, 0xf9, 0x62, 0x00, 0x00, 0x66, 0x19, 0x00,
- 0x67, 0x25, 0x00, 0x68, 0x60, 0x00, 0x6c, 0x72, 0x00, 0x6d, 0x76, 0x00,
- 0x6e, 0x88, 0x00, 0x74, 0xcf, 0x00, 0x76, 0x0a, 0x01, 0xe3, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x10, 0x00, 0x93, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x09, 0xe1, 0x66,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06, 0xe4, 0x00,
- 0x00, 0x27, 0x02, 0x67, 0x06, 0x73, 0x2d, 0x00, 0x76, 0x40, 0x00, 0x73,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x12, 0x6c, 0x17, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x77, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0xd5, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x77, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x5e, 0x00, 0x00, 0x40, 0x2c, 0x61, 0x77, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06,
- 0x73, 0x74, 0x00, 0x40, 0x47, 0x74, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x04,
- 0x40, 0x5e, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x77, 0x65, 0x65, 0x64,
- 0x00, 0xe5, 0x67, 0x00, 0x6b, 0x26, 0x6e, 0x28, 0x72, 0x31, 0x78, 0x3a,
- 0xe2, 0x6c, 0x00, 0x6f, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x5e,
- 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x63, 0x00, 0x00, 0x3a, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x00,
- 0x07, 0x40, 0x06, 0x69, 0x6b, 0x69, 0x73, 0x68, 0x61, 0x00, 0x00, 0x47,
- 0xe2, 0x6e, 0x00, 0x74, 0x05, 0x40, 0x06, 0x65, 0x79, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x62, 0x00, 0x73, 0x20, 0x79, 0x22, 0xe1,
- 0x75, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x07, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x07, 0x00, 0xf3, 0x40,
- 0x82, 0x65, 0x00, 0xc0, 0x62, 0x18, 0x33, 0x00, 0x91, 0x00, 0xec, 0x00,
- 0xf4, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x18, 0x01, 0x32, 0x01, 0x67, 0x01,
- 0x6d, 0x01, 0x93, 0x01, 0x00, 0x00, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xd2, 0x01, 0xe7, 0x01, 0x01, 0x02, 0x7e, 0x02,
- 0x93, 0x02, 0x00, 0x00, 0x9f, 0x02, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x68,
- 0x15, 0x6c, 0x1d, 0x73, 0x33, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x68, 0x00, 0x77,
- 0x06, 0x40, 0x08, 0x61, 0x72, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0xe3, 0x6b, 0x00, 0x6f, 0x14, 0x75, 0x2e, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x73, 0x06, 0x00, 0x09, 0x40, 0x93, 0x79, 0x00,
- 0x40, 0x09, 0x74, 0x72, 0x61, 0x70, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x07, 0x68, 0x70, 0x75, 0x72, 0x73, 0x00, 0x40, 0x08, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6c,
- 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x09, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x61, 0x6b, 0x65, 0x00, 0xe2, 0x6e, 0x00,
- 0x73, 0x2c, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x74, 0x12, 0x03,
- 0x71, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x03, 0x72, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x6c, 0x06,
- 0x00, 0x88, 0x40, 0x00, 0x73, 0x00, 0x42, 0xcb, 0x79, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0x40, 0x00, 0x6f, 0x62, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x0d, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x79, 0x04, 0x00, 0xa5, 0x00, 0x07,
- 0x00, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x0b, 0xe2, 0x72, 0x00, 0x73, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x3b, 0x67, 0x00, 0xe2, 0x6c,
- 0x00, 0x74, 0x28, 0xe2, 0x69, 0x00, 0x79, 0x21, 0xe4, 0x66, 0x00, 0x6c,
- 0x0a, 0x6e, 0x0e, 0x74, 0x14, 0x40, 0x06, 0x69, 0x63, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0x02, 0x84, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x71, 0x75, 0x69, 0x6c,
- 0x00, 0xe2, 0x68, 0x00, 0x74, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x82, 0x6c, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x09, 0x6e, 0x67, 0x00,
- 0xe4, 0x6c, 0x00, 0x6e, 0x04, 0x72, 0x10, 0x73, 0x5f, 0x40, 0x06, 0x65,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x82, 0x00,
- 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x26, 0x6f, 0x43, 0xe1,
- 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x00, 0x09, 0x40,
- 0x07, 0x73, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63,
- 0x00, 0xe1, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x00,
- 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x08, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09,
- 0x00, 0x60, 0xe6, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x25, 0x6f, 0x3b, 0x72,
- 0x4e, 0x73, 0x75, 0x00, 0x93, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe3,
- 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x10, 0x00, 0x3e, 0xe1, 0x65, 0x00, 0xe2,
- 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x1d, 0xe1, 0x64, 0x00, 0xe3, 0x64, 0x00, 0x65, 0x05, 0x69, 0x0e,
- 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0x73,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x64, 0x65, 0x00,
- 0x40, 0x06, 0x74, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x00, 0x65, 0x67, 0x00,
- 0xfe, 0x62, 0x00, 0x00, 0x64, 0x1e, 0x00, 0x67, 0x9f, 0x00, 0x69, 0xe2,
- 0x00, 0x6a, 0x06, 0x01, 0x6b, 0x16, 0x01, 0x6c, 0x1d, 0x01, 0x6d, 0x2d,
- 0x01, 0x6e, 0x65, 0x01, 0x72, 0xc9, 0x01, 0x73, 0x4c, 0x02, 0x74, 0x90,
- 0x02, 0x76, 0xa9, 0x02, 0x78, 0xb1, 0x02, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x3b, 0x74, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0xe4, 0x64, 0x00, 0x67, 0x05, 0x69, 0x39, 0x6f, 0x76, 0x40, 0x0b,
- 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x1b, 0xe4, 0x00, 0x00, 0x27,
- 0x02, 0x6d, 0x06, 0x73, 0x0c, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x00, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x12, 0xe1, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0x40, 0x07, 0x72, 0x65, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x0b, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x79,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x01, 0xda, 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe4, 0x00,
- 0x00, 0x66, 0x02, 0x67, 0x07, 0x75, 0x34, 0x00, 0x06, 0x40, 0x09, 0x75,
- 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0e, 0x6c, 0x13, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x40, 0x06, 0x6e, 0x61, 0x75, 0x74, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xa5, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40,
- 0x06, 0x6c, 0x61, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x79, 0x18, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x96, 0xe2, 0x69, 0x00, 0x75, 0x06, 0x40, 0x07,
- 0x74, 0x73, 0x75, 0x00, 0x40, 0x09, 0x62, 0x65, 0x00, 0x40, 0x09, 0x65,
- 0x62, 0x6f, 0x78, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x70,
- 0x00, 0x40, 0x00, 0x65, 0x6e, 0x6e, 0x65, 0x00, 0xe2, 0x62, 0x00, 0x70,
- 0x0b, 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x82, 0x65, 0x00, 0x00, 0x06,
- 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x73, 0x15, 0x79, 0x1b, 0x00,
- 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x75, 0x69,
- 0x74, 0x00, 0x01, 0x3b, 0xe6, 0x00, 0x00, 0x63, 0x02, 0x67, 0x18, 0x69,
- 0x1d, 0x6b, 0x2b, 0x74, 0x53, 0x00, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x43, 0x74, 0x6f, 0x6e, 0x00,
- 0x43, 0x72, 0x72, 0x65, 0x00, 0x40, 0x09, 0x6c, 0x65, 0x00, 0xe2, 0x6f,
- 0x00, 0x70, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x15, 0x79, 0x19, 0x00, 0xe7, 0xe2,
- 0x72, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x47, 0x40, 0x09, 0x65, 0x72, 0x00, 0x41, 0xa5, 0x65, 0x00, 0x40, 0x09,
- 0x61, 0x72, 0x64, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe3, 0x69, 0x00, 0x6f,
- 0x4f, 0x79, 0x53, 0xe2, 0x64, 0x00, 0x73, 0x11, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c,
- 0x00, 0xe3, 0x64, 0x00, 0x70, 0x1d, 0x74, 0x27, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c,
- 0x00, 0x40, 0x07, 0x72, 0x75, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x01, 0xa7, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6e, 0x34, 0x00, 0xe0, 0xe2, 0x63, 0x00, 0x66, 0x04,
- 0x41, 0x89, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x22, 0xe3, 0x61, 0x00,
- 0x63, 0x0f, 0x65, 0x17, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x37, 0x40, 0x07, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x37, 0x64, 0x00, 0x03, 0x75, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x74, 0x04, 0x00, 0x06,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x69, 0x6c, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3a, 0x40, 0x06,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xc1, 0x48, 0x30, 0x65, 0x00, 0x67, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x74, 0x00, 0xb0, 0x01, 0xb5, 0x01, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00,
- 0x52, 0x03, 0x54, 0x03, 0x62, 0x03, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x07,
- 0x8b, 0x07, 0x8d, 0x07, 0x77, 0x09, 0xeb, 0x09, 0x00, 0x00, 0xef, 0x09,
- 0x00, 0x00, 0x29, 0x0a, 0x2b, 0x0a, 0x4c, 0x0a, 0x53, 0x0a, 0x03, 0x76,
- 0x40, 0x00, 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xfe, 0x62, 0x00, 0x00, 0x64, 0x18, 0x00, 0x66, 0x1f, 0x00, 0x68,
- 0x42, 0x00, 0x69, 0x48, 0x00, 0x6c, 0x4e, 0x00, 0x6d, 0x81, 0x00, 0x6e,
- 0x89, 0x00, 0x6f, 0x9d, 0x00, 0x70, 0xa3, 0x00, 0x72, 0xb6, 0x00, 0x74,
- 0xe4, 0x00, 0x79, 0xf6, 0x00, 0x7a, 0x0c, 0x01, 0xe3, 0x62, 0x00, 0x6f,
- 0x07, 0x75, 0x0c, 0x40, 0x00, 0x61, 0x6c, 0x61, 0x68, 0x00, 0x40, 0x00,
- 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x6b, 0x69, 0x00, 0x40, 0x09, 0x64, 0x69,
- 0x73, 0x68, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6b, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40, 0x09, 0x68, 0x00, 0x40, 0x09, 0x63,
- 0x68, 0x00, 0x40, 0x08, 0x75, 0x6e, 0x61, 0x00, 0x40, 0x09, 0x73, 0x65,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0xe1, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x69, 0x6b, 0x61, 0x7a, 0x65,
- 0x00, 0xe3, 0x61, 0x00, 0x67, 0x02, 0x6a, 0x09, 0x00, 0x00, 0x40, 0x09,
- 0x61, 0x72, 0x6f, 0x6f, 0x00, 0x40, 0x00, 0x69, 0x00, 0x40, 0x07, 0x6c,
- 0x69, 0x6e, 0x00, 0xe3, 0x6f, 0x00, 0x70, 0x04, 0x75, 0x08, 0x40, 0x07,
- 0x6b, 0x00, 0x40, 0x06, 0x61, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe3, 0x61,
- 0x00, 0x6d, 0x1a, 0x74, 0x25, 0xe3, 0x6b, 0x00, 0x6f, 0x05, 0x74, 0x0a,
- 0x40, 0x07, 0x75, 0x6c, 0x00, 0x40, 0x09, 0x6b, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x79,
- 0x07, 0x40, 0x00, 0x6b, 0x61, 0x6e, 0x61, 0x00, 0x40, 0x06, 0x64, 0x69,
- 0x64, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x0f, 0xe1, 0x6b, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x47,
- 0x40, 0x06, 0x6f, 0x6f, 0x00, 0x40, 0x00, 0x70, 0x73, 0x00, 0x00, 0x00,
- 0xfb, 0x62, 0x00, 0x00, 0x64, 0x05, 0x00, 0x65, 0x0d, 0x00, 0x67, 0x48,
- 0x00, 0x6c, 0x4a, 0x00, 0x6e, 0x56, 0x00, 0x70, 0x74, 0x00, 0x72, 0x7d,
- 0x00, 0x73, 0xbe, 0x00, 0x74, 0xc5, 0x00, 0x79, 0xeb, 0x00, 0x40, 0x06,
- 0x61, 0x62, 0x00, 0x40, 0x00, 0x67, 0x65, 0x72, 0x65, 0x65, 0x00, 0xe3,
- 0x6c, 0x00, 0x6e, 0x0d, 0x70, 0x1a, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00,
- 0x47, 0x40, 0x72, 0x61, 0x75, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x03, 0x77, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x73, 0x0b, 0x02, 0x17, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x61, 0x6b, 0x65, 0x00, 0x00, 0x06,
- 0xe2, 0x70, 0x00, 0x76, 0x02, 0x00, 0x07, 0x40, 0x06, 0x69, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x6f, 0x15, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x64, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x93, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0x00, 0x00, 0xe6, 0x61, 0x00, 0x62, 0x12, 0x63, 0x19, 0x66, 0x20,
- 0x6e, 0x28, 0x6f, 0x2d, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6e,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x00, 0x69, 0x73, 0x00, 0x40, 0x00,
- 0x73, 0x69, 0x64, 0x65, 0x00, 0x40, 0x06, 0x68, 0x69, 0x65, 0x66, 0x00,
- 0x40, 0x08, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x65, 0x6c,
- 0x00, 0x40, 0x07, 0x73, 0x65, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x74, 0x72,
- 0x65, 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x0e, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40, 0x07, 0x70, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x06, 0x40,
- 0x06, 0x72, 0x75, 0x6d, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x67, 0x2a,
- 0x68, 0x2f, 0x6e, 0x35, 0x70, 0x47, 0x73, 0x64, 0x77, 0x77, 0x00, 0x93,
- 0xe2, 0x69, 0x00, 0x6f, 0x08, 0x40, 0x08, 0x6e, 0x64, 0x69, 0x6e, 0x67,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x05, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x00, 0x40, 0x09, 0x6f,
- 0x6c, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x75, 0x04, 0x40, 0x06, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x05, 0x40, 0x09,
- 0x6e, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x6b, 0x65, 0x00, 0x40, 0x09, 0x6f,
- 0x72, 0x64, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6b, 0x00, 0x6e,
- 0x04, 0x40, 0x06, 0x69, 0x00, 0x00, 0x09, 0xfe, 0x62, 0x00, 0x00, 0x63,
- 0x37, 0x00, 0x64, 0x74, 0x00, 0x65, 0xce, 0x00, 0x6b, 0xe3, 0x00, 0x6c,
- 0xe7, 0x00, 0x6d, 0x66, 0x01, 0x6e, 0x6c, 0x01, 0x6f, 0xe1, 0x02, 0x70,
- 0xe6, 0x02, 0x72, 0x00, 0x03, 0x73, 0x06, 0x03, 0x74, 0x2c, 0x03, 0x77,
- 0x8d, 0x03, 0xe3, 0x62, 0x00, 0x69, 0x1a, 0x6f, 0x2b, 0xe2, 0x6c, 0x00,
- 0x75, 0x04, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x7a, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6d, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3f,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x73, 0x68, 0x00, 0xe1, 0x6b, 0x00,
- 0xe6, 0x00, 0x00, 0x62, 0x02, 0x65, 0x1b, 0x6f, 0x1f, 0x73, 0x24, 0x79,
- 0x2b, 0x00, 0xe7, 0xe2, 0x61, 0x00, 0x6f, 0x0d, 0xe2, 0x63, 0x00, 0x6c,
- 0x04, 0x40, 0x06, 0x6b, 0x00, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x00, 0x78,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x66, 0x66,
- 0x00, 0x40, 0x09, 0x74, 0x61, 0x6e, 0x64, 0x00, 0x00, 0xf3, 0xe4, 0x00,
- 0x00, 0x64, 0x02, 0x6e, 0x25, 0x73, 0x4b, 0x00, 0x06, 0xe3, 0x65, 0x00,
- 0x69, 0x09, 0x6f, 0x1a, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00,
- 0x06, 0xe3, 0x65, 0x00, 0x6e, 0x02, 0x73, 0x06, 0x00, 0x06, 0x40, 0x00,
- 0x67, 0x00, 0x40, 0x00, 0x68, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65,
- 0x1d, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x08, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00,
- 0x09, 0x40, 0x09, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x07,
- 0x6b, 0x69, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x09, 0x00,
- 0x00, 0x40, 0x08, 0x65, 0x00, 0xe4, 0x6c, 0x00, 0x6e, 0x21, 0x6f, 0x23,
- 0x74, 0x6b, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x6a,
- 0x11, 0x03, 0x78, 0x40, 0x06, 0x65, 0x65, 0x72, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x79, 0x00, 0x00,
- 0x47, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x67, 0x0f, 0x68, 0x15,
- 0x6c, 0x1c, 0x6d, 0x23, 0x74, 0x2a, 0x77, 0x2f, 0x00, 0x09, 0x40, 0x06,
- 0x79, 0x74, 0x65, 0x00, 0x40, 0x06, 0x79, 0x63, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x72, 0x61, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x72, 0x74, 0x7a, 0x00,
- 0x40, 0x09, 0x69, 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x65, 0x74, 0x65,
- 0x72, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x74, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x03, 0x79, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x09, 0x6f, 0x6e, 0x6f, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x64, 0x07, 0x00, 0x65, 0x93, 0x00, 0x66, 0xc8, 0x00, 0x67, 0xda,
- 0x00, 0x6b, 0x0e, 0x01, 0x73, 0x28, 0x01, 0x00, 0x07, 0x40, 0x00, 0x73,
- 0x65, 0x00, 0xe9, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x08, 0x68,
- 0x25, 0x6c, 0x44, 0x6e, 0x5e, 0x72, 0x72, 0x73, 0x77, 0x01, 0xcc, 0x40,
- 0x00, 0x73, 0x00, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6e,
- 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x11,
- 0x00, 0x4b, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07,
- 0x73, 0x73, 0x00, 0x00, 0x07, 0x03, 0x7a, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xdb, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x07, 0x65, 0x64, 0x00, 0x00, 0x00, 0xe3, 0x00,
- 0x00, 0x6d, 0x02, 0x74, 0x17, 0x00, 0x08, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x08, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe7, 0x00, 0x00,
- 0x64, 0x02, 0x66, 0x07, 0x6c, 0x0f, 0x6d, 0x13, 0x70, 0x1a, 0x73, 0x1f,
- 0x00, 0x86, 0x40, 0x06, 0x6f, 0x6d, 0x00, 0x40, 0x06, 0x69, 0x73, 0x68,
- 0x65, 0x72, 0x00, 0x40, 0xf3, 0x79, 0x00, 0x40, 0x08, 0x61, 0x6b, 0x65,
- 0x72, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x69, 0x70,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x47, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x92, 0xe4, 0x66, 0x00, 0x68, 0x06, 0x6d, 0x0b, 0x77, 0x18,
- 0x40, 0x07, 0x6f, 0x6c, 0x6b, 0x00, 0x40, 0x07, 0x69, 0x70, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x73, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x55, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x73, 0x63, 0x68, 0x00, 0xe2, 0x6d, 0x00, 0x73,
- 0x05, 0x40, 0x07, 0x65, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f,
- 0x06, 0x03, 0x7b, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x66, 0x00, 0x67, 0x04,
- 0x40, 0x06, 0x66, 0x00, 0x40, 0x08, 0x72, 0x61, 0x6d, 0x00, 0xe6, 0x00,
- 0x00, 0x63, 0x02, 0x65, 0x20, 0x68, 0x22, 0x73, 0x24, 0x74, 0x33, 0x00,
- 0x93, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x77, 0x08, 0x00, 0x06, 0x40, 0x09, 0x74, 0x74, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0x00, 0x09, 0x00, 0x07, 0xe1,
- 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x13, 0x79, 0x18, 0xe2, 0x64, 0x00,
- 0x6e, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x73, 0x68, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe1,
- 0x69, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x09, 0x40, 0x09, 0x72,
- 0x75, 0x69, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x75,
- 0x32, 0x00, 0x00, 0x40, 0x08, 0x78, 0x6f, 0x6e, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x07, 0x40,
- 0x00, 0x72, 0x61, 0x63, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0xe3, 0x64, 0x00, 0x67, 0x05, 0x74, 0x09, 0x40, 0x0b,
- 0x67, 0x65, 0x00, 0x41, 0x1a, 0x65, 0x00, 0xe1, 0x7a, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x3b, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x65, 0x33, 0x00, 0x69, 0x82, 0x00, 0x6f, 0x01, 0x01, 0x75, 0xae,
- 0x01, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x70, 0x0e, 0x76, 0x15, 0xe1, 0x6b,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x0f, 0x40, 0xed, 0x72, 0x00,
- 0x40, 0x09, 0x73, 0x61, 0x63, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0b,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x3b, 0x73, 0x68, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0e, 0x6c, 0x3b, 0x77,
- 0x44, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x27, 0x40,
- 0x07, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x69, 0x1d, 0x6c, 0x22,
- 0x00, 0xb2, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x01, 0x21,
- 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0xe6,
- 0x63, 0x00, 0x66, 0x26, 0x67, 0x2a, 0x73, 0x47, 0x74, 0x4b, 0x76, 0x6d,
- 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x6b, 0x17, 0xe1, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x73, 0x0b, 0x00, 0x08, 0x40, 0x07, 0x6f, 0x63,
- 0x6b, 0x65, 0x72, 0x73, 0x00, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x61, 0x63,
- 0x6b, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6c, 0x08, 0x03, 0x7c, 0x40, 0x09, 0x6f,
- 0x6f, 0x64, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x74, 0x02, 0x77, 0x15, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x61, 0x72,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0xe5, 0x62, 0x00, 0x63, 0x12, 0x6c,
- 0x49, 0x74, 0x4d, 0x77, 0x6e, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x09,
- 0xe2, 0x6c, 0x00, 0x79, 0x04, 0x40, 0x00, 0x79, 0x00, 0x00, 0x60, 0xe1,
- 0x6b, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x64, 0x09, 0x65, 0x0f, 0x6f,
- 0x13, 0x77, 0x20, 0x00, 0xfa, 0x40, 0x00, 0x62, 0x6f, 0x75, 0x74, 0x00,
- 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x66,
- 0x00, 0x75, 0x04, 0x40, 0x06, 0x66, 0x00, 0x40, 0x06, 0x74, 0x00, 0x40,
- 0x06, 0x75, 0x72, 0x73, 0x74, 0x00, 0x40, 0x06, 0x6c, 0x00, 0xe3, 0x00,
- 0x00, 0x68, 0x02, 0x74, 0x08, 0x00, 0x09, 0x40, 0x06, 0x6f, 0x6c, 0x65,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x60, 0xe4, 0x00, 0x00, 0x69, 0x02,
- 0x6c, 0x07, 0x6e, 0x29, 0x03, 0x5d, 0x43, 0x7d, 0x6e, 0x67, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2,
- 0x63, 0x00, 0x72, 0x20, 0xe1, 0x6b, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x68, 0x0a, 0x00, 0x5e, 0x40, 0x08,
- 0x75, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x65, 0x61, 0x64, 0x00,
- 0x40, 0x93, 0x6c, 0x00, 0xe8, 0x61, 0x00, 0x68, 0x0b, 0x6c, 0x29, 0x6f,
- 0x2d, 0x70, 0x4c, 0x72, 0x52, 0x73, 0x57, 0x77, 0x5d, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x06, 0x61, 0x00, 0x00, 0x08, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x09, 0x61, 0x00, 0xe1, 0x6b, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x0a, 0x79, 0x11, 0x00, 0x09, 0x40, 0x06, 0x62, 0x75,
- 0x72, 0x72, 0x61, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01,
- 0x92, 0x40, 0x09, 0x65, 0x63, 0x6b, 0x00, 0x40, 0x00, 0x6d, 0x61, 0x00,
- 0x40, 0x3a, 0x68, 0x65, 0x72, 0x00, 0x40, 0x59, 0x74, 0x6f, 0x77, 0x00,
- 0x40, 0x00, 0x68, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x0d, 0x6f, 0x12, 0x79,
- 0x2a, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40, 0x06, 0x6c, 0x00, 0x41, 0x69,
- 0x74, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x02, 0x6f, 0x04, 0x75, 0x08, 0x00, 0x07, 0x00, 0x16, 0x40,
- 0x00, 0x72, 0x00, 0x40, 0x00, 0x72, 0x00, 0x40, 0x07, 0x70, 0x74, 0x6f,
- 0x6e, 0x00, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x06, 0x6d, 0x13, 0x40,
- 0x06, 0x68, 0x65, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x7a, 0x04, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x06, 0x75, 0x00, 0x40, 0x09, 0x71, 0x75, 0x61, 0x74,
- 0x00, 0x40, 0x59, 0x65, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, 0xfd, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x46, 0x0a, 0x65, 0x4f, 0x0a, 0x67,
- 0x82, 0x11, 0x69, 0x84, 0x11, 0x6c, 0x71, 0x1b, 0x6f, 0x85, 0x1b, 0x74,
- 0x60, 0x23, 0x75, 0x64, 0x23, 0x76, 0x17, 0x27, 0x78, 0x23, 0x27, 0x79,
- 0x45, 0x27, 0x03, 0x7e, 0xc1, 0x62, 0x19, 0x37, 0x00, 0x39, 0x00, 0xda,
- 0x00, 0xb4, 0x01, 0x21, 0x02, 0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x5c,
- 0x02, 0x00, 0x00, 0x76, 0x02, 0x00, 0x00, 0x8f, 0x02, 0xa9, 0x03, 0x00,
- 0x00, 0x3a, 0x05, 0x00, 0x00, 0xb5, 0x05, 0x67, 0x06, 0xd2, 0x06, 0x9d,
- 0x07, 0x82, 0x08, 0xd5, 0x08, 0x76, 0x09, 0x93, 0x09, 0x1e, 0x0a, 0x00,
- 0x07, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x1d, 0x6f, 0x35, 0x75, 0x6e,
- 0x79, 0x75, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02,
- 0x65, 0x06, 0x6c, 0x0a, 0x00, 0xd5, 0x40, 0x00, 0x73, 0x00, 0x40, 0x37,
- 0x64, 0x00, 0x45, 0x4d, 0x65, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x09,
- 0x75, 0x0d, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40,
- 0x00, 0x65, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x72, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x09, 0x69, 0x0d, 0x73, 0x23, 0x01, 0x5b, 0x40,
- 0x06, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x61, 0x76,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72, 0x6e, 0x75, 0x6d, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x07, 0x40,
- 0x00, 0x6e, 0x65, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x65, 0x02, 0x68,
- 0x32, 0x6b, 0x49, 0x6f, 0x6b, 0x71, 0x81, 0x72, 0x87, 0x74, 0x8e, 0x75,
- 0xb4, 0x79, 0xc3, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x72, 0x06,
- 0x77, 0x18, 0x01, 0x34, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x72, 0x6b, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x79, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40,
- 0x00, 0x73, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0d, 0x6c,
- 0x11, 0x00, 0x47, 0x40, 0x3b, 0x64, 0x61, 0x69, 0x73, 0x69, 0x63, 0x61,
- 0x6c, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x00, 0x75, 0x73, 0x74, 0x65,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0x40, 0x59, 0x75, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6f, 0x73, 0x73, 0x65,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x14, 0x6f, 0x18, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07,
- 0x73, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0xf3, 0xe6, 0x00, 0x00, 0x64,
- 0x02, 0x65, 0x16, 0x69, 0x1f, 0x6c, 0x24, 0x79, 0x28, 0x03, 0x7f, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x95, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0x40, 0x5d, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x08, 0x00, 0x37, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x5e, 0x65,
- 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x66, 0x10, 0x6c, 0x18, 0x73, 0x27,
- 0x00, 0x06, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x06, 0x72, 0x64, 0x00,
- 0x40, 0x09, 0x67, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x37, 0x6b, 0x65, 0x00, 0x40, 0x09,
- 0x76, 0x65, 0x00, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00, 0x40, 0x07, 0x74,
- 0x72, 0x69, 0x6c, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x67, 0x06,
- 0x6e, 0x1b, 0x6f, 0x23, 0x00, 0x0f, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x05, 0x69, 0x09, 0x40, 0x86, 0x72, 0x64, 0x00, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x69, 0x61, 0x70,
- 0x70, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe4, 0x64, 0x00, 0x6e,
- 0x02, 0x72, 0x04, 0x74, 0x0d, 0x03, 0x80, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x00, 0x09, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x73, 0x09, 0x00, 0x09, 0x40, 0x08,
- 0x72, 0x6f, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x69, 0x64, 0x65, 0x00, 0xf7,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x0f, 0x00, 0x65, 0x5e, 0x00,
- 0x69, 0x8f, 0x00, 0x6d, 0xb0, 0x00, 0x70, 0xbe, 0x00, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x06, 0x65, 0x72, 0x79, 0x00,
- 0xe6, 0x00, 0x00, 0x61, 0x02, 0x64, 0x10, 0x65, 0x14, 0x6b, 0x2d, 0x73,
- 0x32, 0x00, 0x47, 0xe2, 0x64, 0x00, 0x73, 0x04, 0x40, 0x09, 0x61, 0x00,
- 0x40, 0x0b, 0x74, 0x65, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe2, 0x6e, 0x00,
- 0x6f, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00,
- 0x3b, 0x40, 0x00, 0x73, 0x61, 0x75, 0x72, 0x75, 0x73, 0x00, 0x40, 0x06,
- 0x69, 0x6e, 0x00, 0xe2, 0x6b, 0x00, 0x77, 0x05, 0x40, 0x06, 0x69, 0x6e,
- 0x00, 0x40, 0x00, 0x6f, 0x6f, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02,
- 0x6e, 0x09, 0x03, 0x81, 0x40, 0x09, 0x72, 0x61, 0x69, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x74, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x03, 0x82, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c,
- 0x79, 0x00, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x61, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x72, 0x04, 0x74, 0x06, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x86,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02,
- 0x6c, 0x09, 0x6f, 0x20, 0x70, 0x25, 0x72, 0x2b, 0x73, 0x30, 0x00, 0x09,
- 0x40, 0x07, 0x6c, 0x61, 0x63, 0x6b, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x67,
- 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x13, 0x40, 0x07, 0x72, 0x00, 0x40, 0x93, 0x6f, 0x6e, 0x00, 0x40,
- 0x06, 0x6f, 0x73, 0x74, 0x00, 0x40, 0x09, 0x65, 0x79, 0x00, 0x40, 0x06,
- 0x68, 0x61, 0x64, 0x65, 0x00, 0xf9, 0x61, 0x00, 0x00, 0x63, 0x04, 0x00,
- 0x64, 0x14, 0x00, 0x65, 0x00, 0x01, 0x67, 0x02, 0x01, 0x6b, 0x3e, 0x01,
- 0x6f, 0x58, 0x01, 0x74, 0x5e, 0x01, 0x79, 0x6f, 0x01, 0x40, 0x06, 0x69,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x04, 0x00,
- 0x7e, 0x00, 0x07, 0x00, 0x06, 0xea, 0x00, 0x00, 0x61, 0x02, 0x66, 0x06,
- 0x68, 0x15, 0x69, 0x2c, 0x6c, 0x31, 0x6d, 0x61, 0x6f, 0x78, 0x73, 0x98,
- 0x77, 0xd1, 0x03, 0x83, 0x40, 0x06, 0x75, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x05, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0a, 0x6f, 0x0f,
- 0x75, 0x1e, 0x40, 0x06, 0x64, 0x79, 0x00, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x6e, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x06, 0x40, 0x00,
- 0x6b, 0x65, 0x64, 0x00, 0x40, 0x09, 0x64, 0x00, 0x40, 0x09, 0x62, 0x62,
- 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0d, 0xe2, 0x72, 0x00, 0x73,
- 0x04, 0x40, 0x09, 0x6b, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40, 0x08, 0x6e,
- 0x65, 0x00, 0xe1, 0x77, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x10, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x68, 0x69, 0x70, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0xe3, 0x63,
- 0x00, 0x6c, 0x12, 0x6d, 0x25, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe1,
- 0x69, 0x00, 0xe2, 0x64, 0x00, 0x70, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x00, 0x01, 0x7f, 0x00, 0x08, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64,
- 0x00, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x05, 0x69, 0x07, 0x6f, 0x1d, 0x40, 0x09, 0x67, 0x65, 0x00,
- 0x00, 0x09, 0xe2, 0x64, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3a, 0x68, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x3b,
- 0x75, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x09, 0x79, 0x0f,
- 0x01, 0xb4, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0xf4, 0x40, 0x07, 0x6c, 0x69, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x68, 0x05, 0x40, 0x09, 0x72, 0x6e, 0x00, 0x40, 0x07, 0x61,
- 0x6e, 0x75, 0x6d, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00, 0xea, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x27, 0x64, 0x2e, 0x65, 0x33, 0x69, 0x37, 0x70,
- 0x44, 0x73, 0x57, 0x74, 0x5b, 0x77, 0x60, 0x00, 0x06, 0xe1, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x14, 0xe1, 0x63, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00,
- 0x63, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x79, 0x00, 0x40, 0x06,
- 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x06, 0x6f, 0x67, 0x00, 0x40, 0x06,
- 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x06, 0x40, 0x06, 0x61, 0x72, 0x79,
- 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x74,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x43, 0x84,
- 0x65, 0x00, 0x40, 0x06, 0x6f, 0x70, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x67,
- 0x00, 0xe8, 0x62, 0x00, 0x63, 0x07, 0x64, 0x24, 0x67, 0x33, 0x69, 0x5f,
- 0x6b, 0x64, 0x76, 0x71, 0x79, 0x81, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64,
- 0x00, 0xe2, 0x65, 0x00, 0x68, 0x16, 0xe1, 0x6e, 0x00, 0xe3, 0x69, 0x00,
- 0x6f, 0x05, 0x79, 0x0a, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x00, 0x75,
- 0x73, 0x00, 0x00, 0x06, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79,
- 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x00, 0xf3, 0xe3, 0x65, 0x00,
- 0x69, 0x1e, 0x6f, 0x23, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x6e, 0x0b, 0x73,
- 0x11, 0x03, 0x85, 0x40, 0x00, 0x65, 0x61, 0x72, 0x74, 0x65, 0x64, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00,
- 0x73, 0x68, 0x00, 0x00, 0x06, 0x40, 0x06, 0x61, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x47, 0x40, 0x06, 0x70, 0x75, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04, 0x00, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x78, 0x16, 0xe2,
- 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40, 0x00, 0x6c,
- 0x00, 0x00, 0x00, 0x40, 0x07, 0x74, 0x69, 0x73, 0x00, 0x00, 0x07, 0xe6,
- 0x61, 0x00, 0x63, 0x06, 0x65, 0x25, 0x68, 0x2e, 0x73, 0x3a, 0x74, 0x52,
- 0x40, 0x09, 0x67, 0x6e, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x01, 0x6d, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x75, 0x64, 0x65, 0x00, 0x00, 0x2c, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x03, 0x7c, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe7, 0x00,
- 0x00, 0x63, 0x02, 0x65, 0x17, 0x68, 0x4a, 0x69, 0x65, 0x72, 0x95, 0x74,
- 0x9b, 0x00, 0x08, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x6b,
- 0x06, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x65, 0x79, 0x00,
- 0xe6, 0x00, 0x00, 0x63, 0x02, 0x6e, 0x09, 0x72, 0x1b, 0x73, 0x20, 0x78,
- 0x24, 0x03, 0x3c, 0x40, 0x09, 0x6f, 0x6d, 0x65, 0x72, 0x00, 0xe3, 0x63,
- 0x00, 0x65, 0x04, 0x74, 0x09, 0x40, 0x07, 0x79, 0x00, 0x40, 0x07, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x43, 0x7c, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x74,
- 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x12, 0x00, 0xe7,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0xec, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x05, 0x74,
- 0x09, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1,
- 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x40, 0x09, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0x86,
- 0x00, 0x12, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x77,
- 0x02, 0x00, 0xb2, 0x40, 0x06, 0x6f, 0x72, 0x6b, 0x00, 0xe4, 0x64, 0x00,
- 0x67, 0x1e, 0x6e, 0x4f, 0x72, 0xbf, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x03,
- 0x87, 0xe3, 0x62, 0x00, 0x6e, 0x05, 0x74, 0x0a, 0x40, 0x00, 0x6c, 0x79,
- 0x00, 0x40, 0x07, 0x75, 0x6d, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x79, 0x00,
- 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x73, 0x1c,
- 0x74, 0x1e, 0x03, 0x88, 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x12, 0x40,
- 0x06, 0x74, 0x6f, 0x63, 0x6b, 0x00, 0x00, 0x00, 0x40, 0x07, 0x65, 0x72,
- 0x00, 0xe2, 0x63, 0x00, 0x64, 0x15, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x70, 0x06, 0x00, 0xc7, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06,
- 0x61, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x16, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x4c, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x40, 0x06, 0x74, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x05, 0x79,
- 0x0b, 0x40, 0x09, 0x73, 0x73, 0x00, 0x40, 0x09, 0x6d, 0x61, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x06, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6c,
- 0x13, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x00, 0x06, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x2a, 0x69, 0x37, 0x00, 0x5b, 0xe4, 0x00, 0x00,
- 0x67, 0x02, 0x6c, 0x06, 0x74, 0x0d, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x06, 0x69, 0x65, 0x72, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x00,
- 0x06, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x08, 0x40, 0x06, 0x64, 0x65,
- 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x03, 0x89, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xea, 0x00, 0x00,
- 0x62, 0x02, 0x66, 0x1c, 0x67, 0x2f, 0x6c, 0x36, 0x6d, 0x4c, 0x6e, 0x6a,
- 0x72, 0x78, 0x73, 0x81, 0x79, 0x87, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0xb1, 0x40,
- 0xdb, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x69, 0x76, 0x65, 0x72, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x15, 0xe2, 0x6b, 0x00, 0x6e, 0x0e, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x07,
- 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x63, 0x69,
- 0x75, 0x6d, 0x00, 0x40, 0x09, 0x75, 0x69, 0x74, 0x00, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x09, 0x6e, 0x0e, 0x03,
- 0x8a, 0x40, 0x09, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x12, 0x6d, 0x2e, 0x6f, 0x3b, 0x70, 0x4f, 0x75, 0x63, 0x77, 0x67,
- 0x03, 0x8b, 0xe2, 0x62, 0x00, 0x77, 0x06, 0x40, 0x08, 0x6f, 0x75, 0x74,
- 0x00, 0x40, 0x07, 0x61, 0x79, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x12, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x82, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x74, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3,
- 0x66, 0x00, 0x75, 0x04, 0x76, 0x08, 0x40, 0x06, 0x66, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6f,
- 0x00, 0x72, 0x06, 0x40, 0x00, 0x70, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x73,
- 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x82, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x01, 0x6f, 0x40, 0x07, 0x6f,
- 0x6e, 0x65, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x08, 0x00,
- 0x00, 0xc0, 0x61, 0x18, 0x33, 0x00, 0x00, 0x00, 0xbd, 0x01, 0x14, 0x02,
- 0x23, 0x02, 0x56, 0x02, 0x88, 0x02, 0x00, 0x00, 0x2a, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x68, 0x04, 0x9f, 0x04, 0x16, 0x05, 0x3e, 0x05,
- 0x00, 0x00, 0x00, 0x00, 0x6e, 0x05, 0xaa, 0x05, 0x31, 0x06, 0x59, 0x06,
- 0xdc, 0x06, 0xec, 0x06, 0xfc, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x64,
- 0x06, 0x00, 0x66, 0x2c, 0x00, 0x67, 0x55, 0x00, 0x6b, 0x5a, 0x00, 0x6e,
- 0x73, 0x00, 0x70, 0x87, 0x00, 0x72, 0xb2, 0x00, 0x73, 0xd5, 0x00, 0x74,
- 0x1b, 0x01, 0x76, 0x3d, 0x01, 0x00, 0x06, 0x40, 0x3a, 0x68, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x1a, 0x03, 0x8c, 0xe1, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x6c, 0x02, 0x73, 0x08, 0x00, 0x07, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x68, 0x69, 0x70, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x07, 0x73, 0x15, 0x79, 0x1c,
- 0x00, 0x47, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x73,
- 0x00, 0x74, 0x04, 0x40, 0x00, 0x73, 0x00, 0x00, 0x59, 0x40, 0x09, 0x74,
- 0x61, 0x6c, 0x6b, 0x00, 0x00, 0xf3, 0x40, 0x5e, 0x75, 0x65, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x79, 0x0e, 0x00, 0x47, 0x40, 0x09,
- 0x67, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x03, 0x8d, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x66, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x0e, 0x74, 0x15, 0x03, 0x8e, 0xe2, 0x64, 0x00, 0x72, 0x05, 0x40, 0x00,
- 0x6c, 0x79, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x27, 0x73, 0x00,
- 0x00, 0x00, 0xe3, 0x65, 0x00, 0x68, 0x27, 0x74, 0x32, 0xe4, 0x00, 0x00,
- 0x62, 0x02, 0x68, 0x08, 0x72, 0x1c, 0x01, 0x85, 0x40, 0x06, 0x61, 0x63,
- 0x6b, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x01, 0x71, 0x40, 0x07, 0x72, 0x00, 0x00, 0x06,
- 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x00, 0x69, 0x73, 0x65, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x6e, 0x08, 0x79, 0x0e, 0x00, 0x09, 0x40, 0x07, 0x74, 0x74,
- 0x65, 0x00, 0x40, 0x09, 0x65, 0x63, 0x6b, 0x00, 0x00, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x1d, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x14, 0x03, 0x19,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x93, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67,
- 0x73, 0x00, 0xe3, 0x68, 0x00, 0x69, 0x28, 0x74, 0x2f, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0xe7, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02,
- 0x79, 0x15, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x74, 0x68, 0x69, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x75,
- 0x05, 0x40, 0x09, 0x72, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0xa5, 0x00, 0x07, 0x40,
- 0x06, 0x68, 0x69, 0x70, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x94, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x63,
- 0x02, 0x6b, 0x06, 0x72, 0x08, 0x77, 0x1a, 0x00, 0x94, 0x40, 0x47, 0x68,
- 0x00, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x2f,
- 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe1, 0x61, 0x00,
- 0xe2, 0x72, 0x00, 0x79, 0x04, 0x40, 0x06, 0x64, 0x00, 0x00, 0x07, 0xe1,
- 0x74, 0x00, 0xe6, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x0e, 0x6f, 0x14, 0x77,
- 0x1a, 0x79, 0x20, 0x03, 0x8f, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0x40,
- 0x06, 0x76, 0x65, 0x72, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00, 0x00,
- 0x06, 0xfb, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x67, 0x00, 0x67,
- 0x8e, 0x00, 0x68, 0xaa, 0x00, 0x69, 0xb0, 0x00, 0x6c, 0x45, 0x01, 0x6d,
- 0x4b, 0x01, 0x72, 0x58, 0x01, 0x75, 0x5e, 0x01, 0x77, 0x6f, 0x01, 0x00,
- 0x06, 0xe3, 0x63, 0x00, 0x6c, 0x04, 0x74, 0x45, 0x40, 0x06, 0x79, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x00, 0x56, 0x40, 0x07, 0x73,
- 0x65, 0x00, 0xe3, 0x73, 0x00, 0x74, 0x1a, 0x7a, 0x1e, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x10,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x03, 0x90, 0x00, 0x09, 0x43, 0x91, 0x6f,
- 0x6e, 0x27, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x6e, 0x00, 0x72, 0x19, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x00,
- 0x40, 0x07, 0x64, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x04, 0x79, 0x13, 0x40, 0x00, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x09, 0x01,
- 0x15, 0x40, 0x09, 0x6f, 0x72, 0x6e, 0x00, 0xe4, 0x62, 0x00, 0x6f, 0x15,
- 0x73, 0x2d, 0x74, 0x57, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6e, 0x07, 0x00,
- 0x06, 0x40, 0x06, 0x72, 0x79, 0x00, 0x40, 0x06, 0x61, 0x69, 0x72, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x75, 0x13, 0x01, 0xf4, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x06, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x15, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x03, 0x92, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a,
- 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6d,
- 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40,
- 0x08, 0x72, 0x6d, 0x65, 0x72, 0x00, 0x40, 0x07, 0x72, 0x6b, 0x00, 0xe3,
- 0x00, 0x00, 0x73, 0x02, 0x74, 0x22, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x77, 0x0a,
- 0x03, 0x93, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x65, 0x61, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00, 0x09, 0x00,
- 0x09, 0xe3, 0x6d, 0x00, 0x6f, 0x10, 0x75, 0x2c, 0xe3, 0x61, 0x00, 0x65,
- 0x02, 0x69, 0x04, 0x00, 0x08, 0x03, 0x94, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x67, 0x07, 0x79, 0x0e,
- 0x00, 0x06, 0x40, 0x06, 0x64, 0x65, 0x00, 0x40, 0x00, 0x72, 0x61, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe5, 0x64, 0x00, 0x67,
- 0x0b, 0x69, 0x3d, 0x73, 0x5b, 0x74, 0x5d, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xe8, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x73, 0x15, 0x77, 0x17, 0x79,
- 0x1d, 0x00, 0x1e, 0x40, 0xed, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x69, 0x73, 0x65, 0x00, 0x01, 0x0c, 0xe2, 0x65, 0x00, 0x74,
- 0x13, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x3b, 0x40, 0x00, 0x69, 0x76,
- 0x65, 0x00, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x06, 0x00,
- 0x00, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x00, 0xe3, 0x6e, 0x00, 0x70, 0x06,
- 0x74, 0x1b, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06,
- 0x40, 0x09, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x72, 0x64, 0x00, 0xe3,
- 0x65, 0x00, 0x72, 0x04, 0x74, 0x1e, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x08, 0x40, 0x09, 0x63, 0x68, 0x61, 0x75, 0x6e, 0x00, 0xe2,
- 0x73, 0x00, 0x75, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe3,
- 0x62, 0x00, 0x69, 0x15, 0x73, 0x1a, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07,
- 0x73, 0x6d, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6f, 0x0b, 0x03, 0x36, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x09,
- 0x00, 0xed, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x09, 0x00, 0x09, 0xe5,
- 0x00, 0x00, 0x64, 0x02, 0x68, 0x08, 0x74, 0x2c, 0x75, 0x78, 0x01, 0xa7,
- 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00,
- 0x72, 0x02, 0x00, 0x3b, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x10,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x3b, 0x75,
- 0x40, 0xe1, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x65, 0x10, 0x68,
- 0x19, 0x69, 0x1f, 0x70, 0x24, 0x00, 0xc3, 0xe1, 0x6f, 0x00, 0xe2, 0x6d,
- 0x00, 0x78, 0x04, 0x40, 0x08, 0x62, 0x00, 0x00, 0x08, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0x40, 0x09, 0x65, 0x61, 0x64, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x72, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x08, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x63, 0x65, 0x00, 0x40, 0x06,
- 0x70, 0x00, 0xe2, 0x63, 0x00, 0x6b, 0x08, 0x40, 0x08, 0x6f, 0x74, 0x6f,
- 0x6d, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x0f, 0xe1, 0x6d, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40,
- 0x09, 0x63, 0x79, 0x74, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x52, 0x79,
- 0x7a, 0xe3, 0x65, 0x00, 0x6c, 0x02, 0x72, 0x33, 0x00, 0x06, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x68, 0x06, 0x6e, 0x22, 0x03, 0x95, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x93, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x27, 0x02, 0x03, 0x4a, 0x40, 0x00, 0x73, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x07, 0x74, 0x0b, 0x40, 0x09, 0x74, 0x68, 0x61, 0x6e,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x0f, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x00, 0x07, 0x00, 0x7e, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0xe0, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x08, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x37, 0xe2,
- 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x67, 0x00, 0x6e,
- 0x27, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x12, 0x40, 0x09, 0x72, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x61,
- 0x1a, 0x37, 0x00, 0x6c, 0x00, 0x4a, 0x01, 0xcc, 0x01, 0xe4, 0x01, 0x1b,
- 0x02, 0xd0, 0x02, 0x00, 0x00, 0x9e, 0x03, 0x00, 0x00, 0xa0, 0x03, 0x1c,
- 0x04, 0x3b, 0x04, 0x31, 0x05, 0x9a, 0x06, 0xc7, 0x06, 0x11, 0x07, 0x71,
- 0x07, 0x7a, 0x07, 0xd7, 0x07, 0x00, 0x00, 0x41, 0x09, 0x00, 0x00, 0xe5,
- 0x09, 0x00, 0x00, 0xe7, 0x09, 0xe3, 0x62, 0x00, 0x69, 0x1e, 0x72, 0x2c,
- 0xe2, 0x69, 0x00, 0x6c, 0x15, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x65, 0x73, 0x00,
- 0x00, 0x75, 0x40, 0x77, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x02, 0x00, 0x0b, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x09, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x09, 0x65, 0x0e, 0x69, 0x82, 0x72, 0x9d, 0x00,
- 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x12, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f,
- 0x06, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x74, 0x43, 0xe2, 0x6c, 0x00, 0x74, 0x2c, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6e, 0x1f, 0x00, 0x44, 0xe3, 0x73, 0x00, 0x74, 0x04,
- 0x7a, 0x08, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x02, 0x97, 0x41, 0x52, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0xe3, 0x61, 0x00, 0x69, 0x07, 0x79, 0x0c, 0x40, 0x06, 0x72, 0x69, 0x61,
- 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x65, 0x00, 0x00, 0x06, 0xe1, 0x64, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x11, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x09,
- 0xe2, 0x61, 0x00, 0x65, 0x1d, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x13, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x68, 0x69, 0x70, 0x00, 0x00, 0x06, 0xe1, 0x74,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x73,
- 0x74, 0x00, 0x00, 0x06, 0xe5, 0x65, 0x00, 0x68, 0x5b, 0x69, 0x60, 0x6b,
- 0x64, 0x6f, 0x70, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0xe3, 0x63,
- 0x00, 0x73, 0x1d, 0x74, 0x2d, 0xe3, 0x65, 0x00, 0x69, 0x0d, 0x6f, 0x12,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x04, 0x05, 0x4e, 0x00, 0x09, 0x05,
- 0x4f, 0x45, 0x4f, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x65, 0x04, 0x00, 0x82, 0x00, 0x37,
- 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06,
- 0x74, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x65, 0x6e, 0x00, 0x40, 0x3b, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x03, 0x96, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x72, 0x69, 0x63,
- 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6c, 0x07, 0x6f, 0x0d, 0x00,
- 0x06, 0x40, 0x00, 0x65, 0x64, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x09, 0xe6, 0x00, 0x00, 0x64, 0x02, 0x66, 0x04, 0x67, 0x06, 0x6e,
- 0x0a, 0x75, 0x0c, 0x00, 0x1a, 0x00, 0x0e, 0x00, 0xf3, 0x40, 0x06, 0x65,
- 0x00, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x74, 0x9e, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x66, 0x20, 0x67, 0x27, 0x6c,
- 0x2e, 0x72, 0x5a, 0x73, 0x5c, 0x74, 0x7f, 0x77, 0x85, 0x00, 0x29, 0xe4,
- 0x65, 0x00, 0x6c, 0x05, 0x6f, 0x0b, 0x75, 0x10, 0x40, 0x08, 0x6c, 0x74,
- 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x09, 0x61, 0x74, 0x00,
- 0x40, 0x09, 0x6f, 0x79, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x6d, 0x73, 0x00,
- 0x40, 0x06, 0x75, 0x61, 0x72, 0x64, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x13,
- 0x6f, 0x20, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6b, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x70, 0x11, 0x74, 0x16,
- 0xe1, 0x76, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x61, 0x6e, 0x00, 0x40, 0x06,
- 0x79, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x69, 0x6d, 0x65, 0x00, 0x40, 0x09,
- 0x6f, 0x72, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x06, 0x00,
- 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x66, 0x66, 0x00, 0xe3, 0x61,
- 0x00, 0x68, 0x1e, 0x6e, 0xb7, 0xe2, 0x6d, 0x00, 0x74, 0x06, 0x40, 0x09,
- 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x75, 0x07, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x82, 0x72, 0x65, 0x00, 0xe1,
- 0x74, 0x00, 0xeb, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x66, 0x1c, 0x68,
- 0x22, 0x69, 0x50, 0x6c, 0x57, 0x6e, 0x5b, 0x70, 0x6a, 0x73, 0x71, 0x77,
- 0x77, 0x03, 0x97, 0x41, 0x63, 0x73, 0x00, 0xe3, 0x64, 0x00, 0x6e, 0x02,
- 0x72, 0x0d, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xd6, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0x06, 0x40, 0x20, 0x61, 0x63, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x23, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x05,
- 0x40, 0x00, 0x65, 0x64, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x75, 0x73, 0x65, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x27, 0x73, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x40, 0xb2, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00,
- 0x40, 0x06, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x06, 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x07, 0x74, 0x65, 0x00,
- 0x00, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1f, 0x69, 0x70, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x26, 0x72,
- 0x3e, 0x77, 0x40, 0x03, 0x98, 0xe2, 0x69, 0x00, 0x79, 0x1d, 0xe2, 0x68,
- 0x00, 0x6e, 0x12, 0xe1, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xdb, 0x00, 0x00, 0x40, 0xdb, 0x65,
- 0x73, 0x73, 0x00, 0x03, 0x99, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x5b,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xdb, 0x40, 0x00, 0x73, 0x00, 0x00, 0x00, 0x40, 0x00, 0x69, 0x73, 0x65,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x6c, 0x04, 0x6f,
- 0x0e, 0x74, 0x10, 0x79, 0x12, 0x40, 0x06, 0x63, 0x00, 0x40, 0x00, 0x69,
- 0x70, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x00, 0x00, 0x08, 0x00, 0x47, 0x00,
- 0x06, 0xe7, 0x62, 0x00, 0x65, 0x23, 0x69, 0x57, 0x6e, 0xa9, 0x6f, 0xab,
- 0x70, 0xb9, 0x79, 0xe5, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x12, 0x6f,
- 0x18, 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0xf1, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x07, 0x72, 0x0e,
- 0x73, 0x14, 0x79, 0x25, 0x00, 0x82, 0x40, 0x06, 0x64, 0x65, 0x00, 0x40,
- 0x07, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x06, 0x69, 0x63, 0x6b, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x06, 0x40, 0x00, 0x61, 0x6c, 0x65, 0x00, 0x40,
- 0x07, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x08, 0xe1, 0x74, 0x00, 0xe6, 0x00,
- 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x1b, 0x69, 0x27, 0x6c, 0x2c, 0x03,
- 0x9a, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01, 0x52,
- 0x00, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x40, 0x00, 0x27,
- 0x73, 0x00, 0x40, 0x08, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x3a, 0xe2, 0x00, 0x00, 0x75, 0x02,
- 0x00, 0x09, 0x40, 0x09, 0x73, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6e, 0x1d, 0x03, 0x9b, 0x40, 0x09, 0x74, 0x00,
- 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x00, 0x3e,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf3, 0xfb, 0x61, 0x00, 0x00, 0x63,
- 0x05, 0x00, 0x64, 0x0c, 0x00, 0x65, 0x11, 0x00, 0x67, 0x85, 0x00, 0x69,
- 0xe6, 0x00, 0x6b, 0xf5, 0x00, 0x6e, 0x16, 0x01, 0x6f, 0x1b, 0x01, 0x73,
- 0x28, 0x01, 0x74, 0x2e, 0x01, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x06,
- 0x68, 0x70, 0x69, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x00, 0xea, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x23, 0x64, 0x2b, 0x66, 0x2d, 0x6d, 0x33, 0x6e,
- 0x40, 0x72, 0x49, 0x73, 0x4b, 0x75, 0x5b, 0x03, 0x9c, 0xe4, 0x67, 0x00,
- 0x6c, 0x04, 0x6d, 0x06, 0x72, 0x0c, 0x40, 0x09, 0x65, 0x00, 0x00, 0x3b,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x09, 0x61, 0x63, 0x6b, 0x65,
- 0x72, 0x00, 0x00, 0x37, 0x40, 0x00, 0x65, 0x65, 0x64, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6d,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x09, 0x70, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6f,
- 0x1d, 0x75, 0x28, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x01, 0x91, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0x40, 0x3b, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1,
- 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0xe2, 0x6d, 0x00, 0x6e, 0x06,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x67, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x6d, 0x07, 0x75, 0x14, 0x03, 0x9d, 0x40, 0x09, 0x67,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x09, 0x70, 0x00, 0x40, 0x09, 0x65, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x40, 0x07, 0x65, 0x75, 0x6d,
- 0x00, 0x40, 0x07, 0x65, 0x65, 0x64, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02,
- 0x65, 0x06, 0x73, 0x0a, 0x79, 0x0c, 0x03, 0x9e, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x09, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x60, 0xe1, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x68, 0x07, 0x69, 0x10, 0x00, 0x09, 0x40, 0x09,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x61, 0x72, 0x74, 0x65, 0x64, 0x00,
- 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe6, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x06,
- 0x70, 0x10, 0x72, 0x1b, 0x73, 0x36, 0x00, 0x06, 0x40, 0x06, 0x64, 0x00,
- 0x40, 0x07, 0x73, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x04, 0x40, 0x00, 0x64, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x03, 0x9f, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x47, 0x74, 0x69, 0x63, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02,
- 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x18, 0x6f, 0x4e, 0xe2, 0x66, 0x00,
- 0x75, 0x0f, 0xe2, 0x61, 0x00, 0x79, 0x08, 0x40, 0x07, 0x63, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x64, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x17, 0x00, 0x09, 0xe1, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x45, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0x40, 0x55, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe4, 0x6c, 0x00, 0x70, 0x04, 0x73, 0x0f, 0x74,
- 0x15, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x1b, 0x6c, 0x20, 0x03, 0xa0, 0xe3, 0x64, 0x00,
- 0x6e, 0x02, 0x72, 0x0d, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x03,
- 0xa1, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x69, 0x61, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xfa, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x07, 0x00, 0x65,
- 0x0c, 0x00, 0x68, 0x52, 0x00, 0x69, 0xb1, 0x00, 0x6d, 0xea, 0x00, 0x6f,
- 0xef, 0x00, 0x74, 0xf5, 0x00, 0x75, 0x30, 0x01, 0x02, 0x75, 0x40, 0x06,
- 0x6e, 0x79, 0x00, 0x40, 0x09, 0x68, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe4, 0x63,
- 0x00, 0x6c, 0x04, 0x72, 0x11, 0x74, 0x1f, 0x40, 0x07, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x02, 0x12, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x5d, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x75, 0x04, 0x00, 0x56, 0x00,
- 0x07, 0x40, 0x07, 0x72, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x15, 0x6f,
- 0x1a, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x73, 0x08, 0x01, 0x5f, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0x40, 0x07,
- 0x75, 0x6d, 0x00, 0xe2, 0x67, 0x00, 0x73, 0x31, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x73, 0x16, 0x79, 0x18, 0x03, 0xa2, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x06, 0x70,
- 0x68, 0x65, 0x72, 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x1b, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x75, 0x73, 0x00, 0x40, 0x07, 0x74, 0x65, 0x73,
- 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x1e, 0x6f, 0x2e, 0xe1, 0x72, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x09, 0x65, 0x0e, 0x00, 0xe7, 0x40, 0x09,
- 0x74, 0x65, 0x75, 0x72, 0x00, 0x40, 0x09, 0x75, 0x67, 0x00, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0xa3,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x72, 0x61, 0x6c, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2,
- 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x65, 0x13, 0x69, 0x92, 0xe1, 0x62,
- 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0x40, 0x37, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x21,
- 0x72, 0x23, 0x73, 0x65, 0x77, 0x6c, 0x03, 0xa4, 0xe3, 0x69, 0x00, 0x6f,
- 0x11, 0x79, 0x16, 0xe2, 0x68, 0x00, 0x6e, 0x06, 0x40, 0x06, 0x6f, 0x6f,
- 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08, 0x6e, 0x67,
- 0x00, 0x01, 0x0c, 0x00, 0x5b, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x69, 0x06,
- 0x77, 0x13, 0x79, 0x23, 0x00, 0x08, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x73, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe2,
- 0x6f, 0x00, 0x75, 0x05, 0x40, 0x09, 0x72, 0x74, 0x00, 0x40, 0x07, 0x72,
- 0x73, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0x82, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x41, 0x52, 0x6e, 0x00, 0x41, 0x63, 0x6e, 0x00, 0x40,
- 0x07, 0x74, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x00, 0x61, 0x72, 0x65, 0x00,
- 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x3b, 0x40, 0x09, 0x67, 0x00, 0x01,
- 0xef, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x61, 0x00, 0x40,
- 0x06, 0x6f, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00, 0xd4, 0x00,
- 0x25, 0x01, 0x10, 0x02, 0x00, 0x00, 0x4a, 0x02, 0x67, 0x02, 0x00, 0x00,
- 0x39, 0x03, 0x00, 0x00, 0x00, 0x00, 0x72, 0x03, 0x00, 0x00, 0xb3, 0x03,
- 0xa4, 0x04, 0x3b, 0x05, 0x6f, 0x05, 0x97, 0x05, 0xd5, 0x05, 0xfb, 0x05,
- 0x1b, 0x06, 0xbb, 0x06, 0x2d, 0x07, 0xa5, 0x07, 0xa7, 0x07, 0xd4, 0x07,
- 0x00, 0x00, 0xe6, 0x64, 0x00, 0x66, 0x22, 0x6d, 0x2d, 0x6e, 0x36, 0x74,
- 0x55, 0x76, 0x87, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x0c,
- 0x69, 0x10, 0x03, 0xa5, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x62, 0x6c,
- 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x27, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x60, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x73, 0x06, 0x77, 0x10, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x68, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x6f, 0x72, 0x64, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x0b, 0x73, 0x10, 0x01, 0x8b, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0xe6,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x06, 0x65, 0x27, 0x6f, 0x29, 0x73, 0x3e,
- 0x00, 0xb1, 0x40, 0x00, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79,
- 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xa1, 0x40, 0x09,
- 0x73, 0x74, 0x00, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x3a, 0x7a, 0x65, 0x00,
- 0x00, 0x06, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0xe5, 0x61, 0x00, 0x69,
- 0x5f, 0x6b, 0x61, 0x6f, 0xa3, 0x75, 0xc8, 0xe3, 0x6c, 0x00, 0x74, 0x34,
- 0x76, 0x52, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x68, 0x04, 0x69, 0x0a, 0x00,
- 0x56, 0x00, 0x09, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0xe3, 0x73, 0x00,
- 0x74, 0x08, 0x7a, 0x0c, 0x40, 0x09, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x13, 0x03, 0xa6, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x27, 0x02, 0x00, 0x90, 0x40, 0x77, 0x73, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x06, 0x6f, 0x72, 0x65, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x65,
- 0x02, 0x6a, 0x0b, 0x6f, 0x10, 0x73, 0x15, 0x75, 0x31, 0x03, 0x7b, 0xe2,
- 0x72, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x61, 0x77,
- 0x00, 0x40, 0x09, 0x75, 0x74, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x12, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x65, 0x70, 0x00, 0x40, 0x09,
- 0x70, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x18, 0x00, 0x08, 0xe1,
- 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x06, 0x65,
- 0x65, 0x64, 0x00, 0xe3, 0x6d, 0x00, 0x73, 0x02, 0x74, 0x0b, 0x00, 0x08,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x09, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x18, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x09, 0x6e, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0xd3, 0x00, 0x07, 0xe1, 0x6e,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00,
- 0x47, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0xea, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x26, 0x65, 0x2c, 0x67, 0x2e, 0x69, 0x52, 0x6a, 0x90, 0x6f, 0x95, 0x72,
- 0xb2, 0x79, 0xbb, 0x00, 0x06, 0xe2, 0x6e, 0x00, 0x72, 0x08, 0x40, 0x06,
- 0x62, 0x65, 0x72, 0x72, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6b, 0x00, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x14, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x06, 0x40, 0x06, 0x65, 0x61,
- 0x64, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x40, 0x07, 0x67,
- 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x1d, 0x73, 0x1f, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x11, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x09, 0x61, 0x6e,
- 0x00, 0x00, 0x08, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x08, 0x40, 0x3b, 0x6c,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x61, 0x6d, 0x00, 0xe5, 0x00, 0x00, 0x66,
- 0x02, 0x6e, 0x06, 0x74, 0x08, 0x75, 0x0e, 0x00, 0x09, 0x40, 0x08, 0x66,
- 0x00, 0x00, 0x08, 0x40, 0x06, 0x79, 0x70, 0x65, 0x00, 0x40, 0x08, 0x74,
- 0x00, 0x40, 0x07, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x00, 0x00, 0xf3,
- 0xe2, 0x6e, 0x00, 0x74, 0x1c, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x09,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x48,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00,
- 0x6c, 0x05, 0x40, 0x06, 0x61, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02,
- 0x6f, 0x08, 0x79, 0x0c, 0x00, 0x3a, 0x40, 0x06, 0x70, 0x6f, 0x70, 0x00,
- 0x40, 0xad, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08, 0xe1,
- 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x31, 0xe4, 0x00, 0x00, 0x6c, 0x02,
- 0x72, 0x10, 0x73, 0x12, 0x03, 0xa7, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0x00, 0x07, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xea, 0x00, 0x00, 0x27,
- 0x02, 0x62, 0x06, 0x65, 0x14, 0x68, 0x21, 0x69, 0x41, 0x73, 0x63, 0x74,
- 0x94, 0x75, 0x9a, 0x77, 0xa0, 0x03, 0xa8, 0x40, 0x00, 0x73, 0x00, 0xe1,
- 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x77, 0x04, 0x40, 0x09, 0x74, 0x00, 0x00,
- 0x09, 0xe2, 0x72, 0x00, 0x76, 0x02, 0x00, 0x00, 0x40, 0x07, 0x69, 0x74,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x0d, 0xe2, 0x69, 0x00, 0x6e, 0x04,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x64, 0x00, 0xe2, 0x72, 0x00, 0x75,
- 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x08, 0x73, 0x65, 0x00, 0xe3, 0x6e,
- 0x00, 0x73, 0x04, 0x74, 0x08, 0x40, 0x86, 0x67, 0x00, 0x40, 0x00, 0x68,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x3b, 0x6e, 0x61, 0x6c, 0x00, 0xe3, 0x68, 0x00, 0x69,
- 0x19, 0x74, 0x21, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x67, 0x68, 0x74, 0x65, 0x64, 0x00,
- 0x40, 0x00, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69,
- 0x6d, 0x65, 0x00, 0x40, 0x06, 0x65, 0x75, 0x72, 0x00, 0x40, 0x00, 0x61,
- 0x79, 0x73, 0x00, 0xe8, 0x00, 0x00, 0x66, 0x02, 0x6b, 0x11, 0x6d, 0x32,
- 0x6e, 0x34, 0x70, 0x43, 0x73, 0x54, 0x74, 0x74, 0x00, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x6f, 0x0d, 0x75, 0x12,
- 0x00, 0xe7, 0x40, 0x09, 0x6c, 0x69, 0x6b, 0x65, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x09, 0x75, 0x74, 0x00, 0x40, 0x00, 0x70, 0x00, 0x00, 0x47,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x06, 0x00, 0x09, 0x40, 0x07, 0x65,
- 0x00, 0x01, 0x64, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x79, 0x08, 0x00, 0x47,
- 0x40, 0x09, 0x6f, 0x6c, 0x65, 0x00, 0x00, 0xf3, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x03, 0xa9, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x06, 0x03, 0xaa,
- 0x40, 0x00, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x03, 0xab, 0x40,
- 0x07, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00,
- 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x70, 0x04, 0x73, 0x12, 0x00, 0x08, 0x00, 0x82, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe6, 0x64, 0x00, 0x65, 0x1d, 0x67,
- 0x1f, 0x69, 0x27, 0x6e, 0x2b, 0x72, 0x2d, 0xe3, 0x00, 0x00, 0x6c, 0x02,
- 0x73, 0x10, 0x03, 0x7c, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0x40, 0x06, 0x68, 0x69, 0x70, 0x00,
- 0x00, 0x07, 0x40, 0x06, 0x6e, 0x65, 0x74, 0x74, 0x65, 0x00, 0x40, 0x09,
- 0x73, 0x00, 0x00, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x09, 0x73, 0x0e, 0x74, 0x1b, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0xac,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe4, 0x00,
- 0x00, 0x69, 0x02, 0x74, 0x07, 0x75, 0x13, 0x00, 0x06, 0x40, 0x06, 0x6f,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x72, 0x79, 0x00,
- 0x00, 0x07, 0x40, 0x09, 0x73, 0x00, 0xe8, 0x63, 0x00, 0x64, 0x05, 0x67,
- 0x3e, 0x6e, 0x4a, 0x72, 0x59, 0x73, 0x5b, 0x74, 0x7e, 0x76, 0x8a, 0x40,
- 0x00, 0x68, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x68, 0x02, 0x6d, 0x0a, 0x6e,
- 0x1f, 0x73, 0x25, 0x01, 0xb4, 0x40, 0x06, 0x61, 0x69, 0x6c, 0x65, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x20, 0x00, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x70, 0x65, 0x61, 0x6b, 0x65, 0x72,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xa5, 0x00, 0x07, 0x00, 0x3a, 0xe3, 0x65, 0x00, 0x69, 0x0b, 0x79,
- 0x1a, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x03, 0x4a, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x92, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x4d, 0x73, 0x68, 0x00, 0x40, 0xb2, 0x65, 0x72, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x14, 0x69, 0x66, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x00, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x64, 0x0f, 0x6c, 0x11,
- 0x6d, 0x2d, 0x72, 0x35, 0x73, 0x37, 0x79, 0x3d, 0x03, 0xad, 0x40, 0x06,
- 0x69, 0x72, 0x64, 0x00, 0x40, 0x07, 0x68, 0x69, 0x6c, 0x64, 0x00, 0x00,
- 0x37, 0xe4, 0x65, 0x00, 0x69, 0x05, 0x6f, 0x0c, 0x79, 0x11, 0x40, 0x00,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00,
- 0x72, 0x6e, 0x00, 0x02, 0x0e, 0x40, 0x07, 0x61, 0x6b, 0x69, 0x6e, 0x67,
- 0x00, 0x00, 0x07, 0x40, 0x00, 0x69, 0x63, 0x6b, 0x00, 0x00, 0x08, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x64, 0x17, 0x65,
- 0x1d, 0x69, 0x35, 0x6c, 0x3a, 0x6e, 0x63, 0x03, 0xae, 0xe2, 0x6f, 0x00,
- 0x72, 0x0b, 0xe2, 0x72, 0x00, 0x79, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x00,
- 0x09, 0x40, 0x06, 0x6f, 0x77, 0x00, 0x40, 0x07, 0x6f, 0x77, 0x6e, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6d, 0x08, 0x00, 0xed,
- 0x40, 0x07, 0x61, 0x73, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00,
- 0x40, 0x00, 0x73, 0x68, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x11, 0x79, 0x20,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x0f, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x66, 0x00, 0x6e, 0x04, 0x40, 0x06,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x74, 0x12, 0x03, 0xaf, 0x40,
- 0x00, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x65, 0x73,
- 0x00, 0x00, 0x84, 0x40, 0x06, 0x65, 0x6e, 0x67, 0x65, 0x00, 0x40, 0x00,
- 0x64, 0x00, 0xff, 0x61, 0x00, 0x00, 0x62, 0x04, 0x00, 0x63, 0x46, 0x00,
- 0x64, 0xc0, 0x00, 0x66, 0xe3, 0x00, 0x67, 0xe7, 0x00, 0x6b, 0x3d, 0x01,
- 0x6c, 0x59, 0x01, 0x6d, 0x6c, 0x01, 0x6e, 0x17, 0x02, 0x70, 0x86, 0x02,
- 0x72, 0x94, 0x02, 0x73, 0xbb, 0x02, 0x74, 0x23, 0x03, 0x78, 0x44, 0x03,
- 0x40, 0x09, 0x75, 0x00, 0xe3, 0x62, 0x00, 0x65, 0x05, 0x72, 0x07, 0x40,
- 0x86, 0x65, 0x72, 0x00, 0x00, 0x82, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x1b, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x74,
- 0x05, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe4, 0x69,
- 0x00, 0x6b, 0x17, 0x72, 0x39, 0x75, 0x59, 0xe1, 0x64, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6e, 0x07, 0x00, 0x4d, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c,
- 0x11, 0x79, 0x17, 0x00, 0x47, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x37,
- 0x79, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0x02, 0xf4, 0xe2, 0x61, 0x00, 0x65, 0x19, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07,
- 0xe1, 0x62, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x1c, 0xe1, 0x63, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40,
- 0x3a, 0x66, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x67, 0x04, 0x68, 0x1e,
- 0x73, 0x24, 0x75, 0x2a, 0x00, 0x06, 0x00, 0x08, 0xe3, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x0e, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x08,
- 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x61, 0x69, 0x6c, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x77, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6c, 0x00,
- 0x75, 0x0c, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x47, 0x40, 0x06, 0x62,
- 0x79, 0x00, 0x00, 0x08, 0xe4, 0x62, 0x00, 0x69, 0x44, 0x6d, 0x79, 0x70,
- 0x7e, 0xe2, 0x61, 0x00, 0x65, 0x0b, 0xe2, 0x67, 0x00, 0x72, 0x04, 0x40,
- 0x07, 0x6f, 0x00, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x6a, 0x0b, 0x6d, 0x11, 0x79, 0x1e, 0x00, 0xfe, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x61, 0x63,
- 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x72, 0x64, 0x00, 0xe1, 0x6e, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6f, 0x1c, 0x40, 0x06, 0x72, 0x79, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2,
- 0x73, 0x00, 0x75, 0x06, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0x40, 0x3b,
- 0x73, 0x00, 0x40, 0x09, 0x6f, 0x78, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x0a, 0x79, 0x19, 0x00, 0xcb, 0x40, 0x08, 0x63, 0x74, 0x6f, 0x6d,
- 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x06, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x68, 0x00, 0x01, 0x3b, 0xe4, 0x61, 0x00, 0x63, 0x12,
- 0x67, 0x46, 0x6b, 0x5f, 0xe3, 0x63, 0x00, 0x72, 0x04, 0x74, 0x06, 0x40,
- 0x06, 0x79, 0x00, 0x00, 0x00, 0x40, 0x06, 0x69, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x07, 0x72, 0x1a, 0x74, 0x20,
- 0x00, 0x59, 0x40, 0x08, 0x6f, 0x78, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x40, 0x06, 0x74, 0x74,
- 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x09, 0x69, 0x6d,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x66, 0x04, 0x00, 0x47, 0x00,
- 0x06, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x09, 0x73, 0x68, 0x00, 0x40,
- 0x08, 0x6c, 0x00, 0x40, 0x09, 0x68, 0x65, 0x61, 0x64, 0x00, 0xe2, 0x69,
- 0x00, 0x75, 0x05, 0x40, 0x09, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe5, 0x63, 0x00, 0x65, 0x04, 0x67, 0x06, 0x69, 0x0a, 0x6b, 0x1a, 0x40,
- 0x59, 0x68, 0x00, 0x00, 0x82, 0x40, 0x00, 0x79, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x4b, 0xe3, 0x63, 0x00, 0x68, 0x19, 0x74, 0x26, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x03, 0xb0, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe6, 0x00, 0x00, 0x65, 0x02, 0x66, 0x12, 0x69, 0x17, 0x72, 0x26, 0x79,
- 0x2c, 0x03, 0x9d, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x75, 0x6c, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x96, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x6e, 0x69, 0x73, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x6e, 0x02, 0x74, 0x08, 0x00, 0x09, 0x40, 0x06, 0x69, 0x73,
- 0x74, 0x00, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x34, 0xe2, 0x61, 0x00, 0x6f, 0x1c,
- 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x3b, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x06, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe2, 0x69, 0x00, 0x76, 0x11, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x76,
- 0x04, 0x78, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe7,
- 0x63, 0x00, 0x65, 0x11, 0x69, 0x13, 0x6d, 0x18, 0x6e, 0x42, 0x72, 0x5e,
- 0x73, 0x8c, 0xe2, 0x65, 0x00, 0x68, 0x05, 0x40, 0x09, 0x75, 0x6d, 0x00,
- 0x40, 0x08, 0x67, 0x61, 0x74, 0x65, 0x00, 0x00, 0x15, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x6f, 0x08, 0x00, 0x07, 0x40, 0x06, 0x74, 0x69, 0x63, 0x00, 0xe3,
- 0x63, 0x00, 0x69, 0x06, 0x6d, 0x0a, 0x40, 0x06, 0x79, 0x74, 0x65, 0x00,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x78,
- 0x15, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01,
- 0x8b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x09,
- 0x40, 0x09, 0x69, 0x72, 0x64, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x06, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x6f,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x73, 0x00, 0xc1,
- 0x52, 0x28, 0x55, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xa2, 0x15, 0xa7, 0x15, 0x27, 0x23, 0x30, 0x23,
- 0x00, 0x00, 0x3f, 0x23, 0x00, 0x00, 0xc7, 0x33, 0xcb, 0x33, 0xcd, 0x33,
- 0xd8, 0x33, 0xf7, 0x33, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, 0x35, 0x42,
- 0x4c, 0x42, 0x5c, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x4a,
- 0x03, 0xb1, 0x40, 0x00, 0x4e, 0x41, 0x00, 0xc1, 0x27, 0x54, 0xad, 0x00,
- 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xb4, 0x00, 0xf1, 0x01, 0xa2, 0x02, 0xb5, 0x02, 0xcb, 0x02, 0x4f, 0x04,
- 0x90, 0x04, 0xa6, 0x05, 0x0c, 0x06, 0x50, 0x06, 0x8f, 0x08, 0xf5, 0x08,
- 0x00, 0x00, 0xf8, 0x0c, 0x00, 0x00, 0x27, 0x0d, 0x75, 0x10, 0x39, 0x12,
- 0x26, 0x14, 0x54, 0x14, 0x64, 0x14, 0x81, 0x14, 0xca, 0x14, 0x39, 0x15,
- 0x01, 0x58, 0x40, 0x00, 0x61, 0x6d, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x65, 0x41, 0x00, 0x68, 0x5a, 0x00, 0x6b, 0x9c, 0x00, 0x72,
- 0xb9, 0x00, 0x00, 0x93, 0xe5, 0x62, 0x00, 0x64, 0x05, 0x71, 0x1d, 0x72,
- 0x22, 0x77, 0x32, 0x40, 0x00, 0x72, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x7a, 0x02, 0x00, 0x06, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x09, 0x75, 0x65,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x69,
- 0x00, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x07, 0x6f, 0x37, 0x00, 0x07, 0x40, 0x06, 0x74, 0x65, 0x00,
- 0xe2, 0x6e, 0x00, 0x73, 0x26, 0xe3, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x1a,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x39, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0xb2, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x07, 0x6d, 0x6f, 0x00,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x06, 0x72, 0x65, 0x6c,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x04, 0x40, 0x06, 0x77,
- 0x00, 0x40, 0x09, 0x6f, 0x73, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05,
- 0x40, 0x07, 0x6d, 0x65, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x1a,
- 0x65, 0x20, 0x6c, 0x3e, 0x6e, 0x44, 0x70, 0x46, 0x73, 0x4e, 0x00, 0x06,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07,
- 0x40, 0x06, 0x6f, 0x73, 0x6d, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07,
- 0x40, 0x08, 0x6f, 0x67, 0x79, 0x00, 0x00, 0x09, 0x40, 0x00, 0x68, 0x61,
- 0x67, 0x65, 0x73, 0x00, 0x40, 0x00, 0x63, 0x6f, 0x70, 0x69, 0x63, 0x00,
- 0xea, 0x00, 0x00, 0x61, 0x02, 0x63, 0x0e, 0x64, 0x13, 0x65, 0x36, 0x68,
- 0x47, 0x6d, 0x4e, 0x6e, 0x5b, 0x72, 0x61, 0x77, 0x89, 0x02, 0x12, 0xe1,
- 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40,
- 0x09, 0x61, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x19, 0xe3, 0x6e, 0x00,
- 0x72, 0x0c, 0x73, 0x0e, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x72, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0x00, 0x09, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0xca, 0x40, 0x09,
- 0x6f, 0x69, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x75,
- 0x73, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x1d, 0xe1, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73,
- 0x04, 0x00, 0x09, 0x00, 0x08, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x67, 0x61,
- 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x6c, 0x00,
- 0x73, 0x08, 0x40, 0x06, 0x73, 0x74, 0x72, 0x6f, 0x6d, 0x00, 0x40, 0x06,
- 0x74, 0x72, 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02,
- 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02, 0x00, 0x00,
- 0x00, 0x07, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x09, 0x00,
- 0x67, 0x15, 0x00, 0x69, 0x24, 0x00, 0x6d, 0x6e, 0x00, 0x6e, 0x72, 0x00,
- 0x70, 0x5f, 0x01, 0x75, 0x64, 0x01, 0x00, 0x06, 0x40, 0x06, 0x7a, 0x69,
- 0x6e, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x09, 0x40, 0x07,
- 0x74, 0x61, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x73,
- 0x24, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x6b, 0x0b,
- 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x07, 0x40, 0x3b, 0x72,
- 0x69, 0x61, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x1e, 0x69, 0x87, 0x6f, 0xd8, 0x75, 0xde, 0xe2,
- 0x6e, 0x00, 0x74, 0x15, 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0e, 0xe1, 0x69,
- 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x37, 0x00, 0x09, 0xe4, 0x63, 0x00,
- 0x73, 0x0d, 0x74, 0x11, 0x7a, 0x15, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe2, 0x62, 0x00, 0x74,
- 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x41, 0x52, 0x69, 0x6f, 0x6e, 0x00,
- 0x01, 0x98, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x73, 0x09, 0x00, 0x06, 0x40,
- 0x06, 0x65, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x70, 0x68, 0x65, 0x72,
- 0x65, 0x00, 0xe3, 0x66, 0x00, 0x6c, 0x2a, 0x74, 0x44, 0xe2, 0x69, 0x00,
- 0x79, 0x23, 0xe2, 0x63, 0x00, 0x65, 0x1a, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x40, 0x07, 0x72,
- 0x00, 0x03, 0xb3, 0xe1, 0x6f, 0x00, 0xe1, 0x71, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x00, 0x40, 0x06, 0x75, 0x64, 0x65, 0x00, 0x40,
- 0x09, 0x6c, 0x69, 0x61, 0x00, 0x40, 0x09, 0x6d, 0x00, 0x40, 0x09, 0x69,
- 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x2d, 0xe2,
- 0x72, 0x00, 0x74, 0x23, 0xe2, 0x61, 0x00, 0x69, 0x18, 0xe2, 0x6a, 0x00,
- 0x6e, 0x0f, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x69, 0x00, 0x40, 0x06, 0x73,
- 0x68, 0x69, 0x00, 0x40, 0x06, 0x6d, 0x61, 0x00, 0xe2, 0x67, 0x00, 0x75,
- 0x06, 0x40, 0x06, 0x61, 0x6e, 0x79, 0x00, 0x40, 0x09, 0x74, 0x00, 0xf6,
- 0x64, 0x00, 0x00, 0x6c, 0x32, 0x00, 0x6d, 0x7e, 0x00, 0x6e, 0x80, 0x00,
- 0x73, 0xf6, 0x00, 0x7a, 0xff, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73,
- 0x22, 0x03, 0xb4, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00,
- 0x12, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6f, 0x0a, 0x40, 0x07, 0x69, 0x72,
- 0x00, 0x40, 0x06, 0x61, 0x64, 0x00, 0x40, 0x07, 0x6f, 0x64, 0x00, 0x40,
- 0x06, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x00, 0xe8, 0x00, 0x00, 0x62,
- 0x02, 0x65, 0x16, 0x69, 0x1a, 0x6c, 0x1f, 0x6d, 0x24, 0x73, 0x31, 0x74,
- 0x37, 0x03, 0x78, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x67, 0x00,
- 0xe2, 0x6d, 0x00, 0x78, 0x04, 0x40, 0xad, 0x62, 0x00, 0x00, 0x09, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x74,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x08, 0x68, 0x6f, 0x74, 0x00, 0x40, 0x00, 0x6f, 0x00,
- 0x00, 0x3a, 0xe6, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x09, 0x6d, 0x18, 0x73,
- 0x1e, 0x74, 0x40, 0x00, 0x86, 0x40, 0x06, 0x72, 0x61, 0x6d, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x82,
- 0x6e, 0x65, 0x00, 0x40, 0x09, 0x61, 0x73, 0x74, 0x00, 0xe3, 0x61, 0x00,
- 0x70, 0x05, 0x74, 0x0c, 0x40, 0x09, 0x69, 0x6c, 0x00, 0x40, 0x09, 0x72,
- 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x04, 0x40, 0x09, 0x79,
- 0x00, 0x40, 0x2c, 0x65, 0x61, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x16,
- 0x6f, 0x1e, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x02, 0xac, 0x40, 0x00, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x07, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x06, 0x70, 0x00,
- 0x40, 0x09, 0x6f, 0x6e, 0x65, 0x74, 0x74, 0x65, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x1d, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x10, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x06, 0xe2,
- 0x6c, 0x00, 0x72, 0x06, 0x40, 0x07, 0x69, 0x63, 0x61, 0x00, 0xe4, 0x00,
- 0x00, 0x64, 0x02, 0x65, 0x08, 0x69, 0x0e, 0x00, 0xfd, 0x40, 0x09, 0x6f,
- 0x6d, 0x6f, 0x00, 0x40, 0x09, 0x74, 0x74, 0x65, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x79, 0x18, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x73, 0x6d, 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x30,
- 0xe7, 0x00, 0x00, 0x27, 0x02, 0x6f, 0x06, 0x72, 0x0c, 0x73, 0x0e, 0x75,
- 0x15, 0x77, 0x19, 0x02, 0xf1, 0x40, 0x77, 0x73, 0x00, 0x40, 0x09, 0x76,
- 0x65, 0x72, 0x00, 0x00, 0x06, 0x40, 0x06, 0x68, 0x69, 0x66, 0x74, 0x00,
- 0x40, 0x09, 0x70, 0x00, 0x40, 0x08, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x09, 0x00, 0x07, 0xfb, 0x61, 0x00, 0x00, 0x63, 0x8e, 0x00, 0x65, 0x97,
- 0x00, 0x66, 0xfb, 0x00, 0x69, 0x2a, 0x01, 0x6c, 0x81, 0x01, 0x6e, 0xaf,
- 0x01, 0x6f, 0xc8, 0x01, 0x70, 0xdf, 0x01, 0x74, 0xe9, 0x01, 0x77, 0x17,
- 0x02, 0xe7, 0x63, 0x00, 0x64, 0x07, 0x69, 0x4e, 0x6d, 0x53, 0x70, 0x59,
- 0x72, 0x62, 0x74, 0x78, 0x40, 0x07, 0x68, 0x69, 0x74, 0x65, 0x00, 0xe4,
- 0x6a, 0x00, 0x6d, 0x18, 0x72, 0x26, 0x79, 0x3c, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x69, 0x6e,
- 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0x40, 0x07,
- 0x73, 0x65, 0x00, 0x40, 0x09, 0x75, 0x74, 0x65, 0x00, 0x40, 0x06, 0x72,
- 0x6f, 0x70, 0x69, 0x73, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x6b, 0x0c, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x07, 0x65, 0x79, 0x00, 0x40, 0x07, 0x68, 0x69, 0x6f, 0x6e, 0x00, 0x40,
- 0x09, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x64,
- 0x02, 0x66, 0x0b, 0x6e, 0x3c, 0x76, 0x42, 0x03, 0xb5, 0x40, 0x06, 0x69,
- 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x14, 0xe1,
- 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0xe3, 0x65, 0x00, 0x6f, 0x09, 0x75, 0x1f, 0x40, 0x07, 0x61, 0x73, 0x61,
- 0x6e, 0x63, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x47, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3,
- 0x63, 0x00, 0x67, 0x1d, 0x6e, 0x3c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x10, 0x00, 0x3a, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x00,
- 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x48, 0x40, 0x07,
- 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x6f, 0x21, 0x00,
- 0x09, 0x40, 0x06, 0x72, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x13, 0xe1,
- 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74,
- 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0x00, 0x09, 0x40, 0x09, 0x77, 0x00,
- 0xe2, 0x6f, 0x00, 0x75, 0x0a, 0x40, 0x00, 0x75, 0x72, 0x69, 0x73, 0x68,
- 0x65, 0x64, 0x00, 0x40, 0x07, 0x74, 0x72, 0x69, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x64, 0x0a, 0x40, 0x07, 0x63, 0x6c, 0x75, 0x73,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x6f, 0x75, 0x73, 0x00,
- 0x40, 0x06, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x65, 0x00, 0xe5, 0x00,
- 0x00, 0x65, 0x02, 0x6f, 0x06, 0x72, 0x0b, 0x79, 0x21, 0x00, 0x47, 0x40,
- 0x09, 0x64, 0x00, 0x40, 0x07, 0x73, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x35,
- 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x60, 0x40, 0x07, 0x61, 0x72,
- 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x62, 0x04, 0x6d, 0x0d, 0x00,
- 0x08, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x00, 0x93,
- 0xe3, 0x61, 0x00, 0x6f, 0x20, 0x79, 0x47, 0xe3, 0x00, 0x00, 0x6c, 0x02,
- 0x72, 0x15, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x00, 0x79, 0x00, 0xe3, 0x67, 0x00, 0x6e, 0x12, 0x74, 0x14, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x02, 0x00, 0x09, 0x40,
- 0x07, 0x68, 0x79, 0x00, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0xc1, 0x27, 0x53, 0xab,
- 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x02, 0x01, 0x5b, 0x01, 0x81, 0x01, 0x86, 0x01, 0xd1,
- 0x01, 0xf1, 0x01, 0x00, 0x00, 0x8c, 0x02, 0x98, 0x02, 0x00, 0x00, 0xae,
- 0x02, 0xf1, 0x02, 0x09, 0x03, 0x10, 0x03, 0x00, 0x00, 0x15, 0x03, 0x40,
- 0x03, 0xa0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x03,
- 0xb6, 0x42, 0xcb, 0x73, 0x00, 0xe4, 0x63, 0x00, 0x67, 0x05, 0x6e, 0x3f,
- 0x74, 0x43, 0x40, 0x5e, 0x6c, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x6d, 0x15, 0x72, 0x1b, 0x02, 0x91, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x37, 0x65, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x07, 0x00, 0x07, 0x40, 0x08, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x61, 0x00, 0x40, 0x06, 0x65,
- 0x65, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x23, 0x6f, 0x35, 0x72, 0x3b, 0xe4,
- 0x6c, 0x00, 0x6d, 0x04, 0x72, 0x09, 0x74, 0x0e, 0x40, 0x06, 0x61, 0x00,
- 0x40, 0x09, 0x75, 0x73, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x02, 0x00, 0x5e, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x62,
- 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00,
- 0x6c, 0x61, 0x72, 0x00, 0x40, 0x09, 0x6c, 0x69, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x05, 0x69, 0x09, 0x40, 0x09, 0x6b, 0x65, 0x00, 0x40, 0x06,
- 0x6c, 0x00, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02,
- 0x75, 0x06, 0x00, 0xb2, 0x40, 0x07, 0x65, 0x00, 0xe1, 0x76, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x03, 0xb7,
- 0x40, 0x07, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75,
- 0x6c, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x0d, 0x69, 0x1e, 0x6c, 0x25, 0x6f,
- 0x29, 0x72, 0x34, 0x79, 0x3a, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x73, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74,
- 0x04, 0x03, 0xb8, 0x00, 0x07, 0x40, 0x08, 0x6f, 0x75, 0x74, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0xa5, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x6f,
- 0x76, 0x65, 0x00, 0x01, 0x3b, 0xe3, 0x61, 0x00, 0x6f, 0x07, 0x75, 0x14,
- 0x40, 0x0b, 0x6e, 0x64, 0x6c, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x04,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x64, 0x00, 0x40, 0x06, 0x6e, 0x74,
- 0x00, 0xe7, 0x61, 0x00, 0x63, 0x12, 0x66, 0x30, 0x6b, 0x52, 0x6c, 0x57,
- 0x6f, 0x5b, 0x70, 0x5f, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x75, 0x08, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x82, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x18, 0xe1, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x09, 0x03, 0x7c,
- 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x06, 0x40, 0x59, 0x6c,
- 0x64, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40,
- 0x09, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00, 0x40, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x6e, 0x64, 0x00, 0x00, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6b, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x7c, 0xe3, 0x61,
- 0x00, 0x65, 0x02, 0x69, 0x23, 0x00, 0x07, 0xe3, 0x64, 0x00, 0x71, 0x02,
- 0x72, 0x08, 0x00, 0x37, 0x40, 0x06, 0x75, 0x69, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6c, 0x07, 0x03, 0xb9, 0x40, 0x06, 0x73, 0x6d, 0x00,
- 0x40, 0x37, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x37, 0x67,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x72, 0x07, 0x40, 0x06,
- 0x65, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x6f, 0x77, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x75, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x13,
- 0x6c, 0x18, 0x40, 0x09, 0x72, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x03, 0xba, 0x40, 0x07, 0x76, 0x61, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x02, 0x69, 0x2e, 0x6c, 0x43, 0x72, 0x51, 0x00,
- 0x06, 0xe2, 0x6c, 0x00, 0x73, 0x25, 0xe3, 0x00, 0x00, 0x70, 0x02, 0x73,
- 0x09, 0x00, 0x09, 0x40, 0x06, 0x69, 0x65, 0x63, 0x65, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x00, 0xe2, 0x6c, 0x00,
- 0x73, 0x05, 0x40, 0x06, 0x6c, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x27, 0x02, 0x00, 0x83, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x61, 0x00,
- 0xe5, 0x61, 0x00, 0x66, 0x04, 0x6d, 0x26, 0x72, 0x4a, 0x73, 0x4e, 0x40,
- 0x86, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x07, 0x40, 0x06, 0x73,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x82, 0x65, 0x00, 0x40, 0x09, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x00, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x6c, 0x06, 0x6d, 0x0a,
- 0x70, 0x11, 0x00, 0x76, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x65, 0x00,
- 0x40, 0x06, 0x61, 0x6b, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x77, 0x00, 0x09, 0x40, 0x08, 0x6e,
- 0x67, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x83, 0x00, 0x9c,
- 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xfb,
- 0x00, 0x6b, 0x01, 0x72, 0x01, 0x05, 0x02, 0x1e, 0x02, 0x00, 0x00, 0x3e,
- 0x02, 0x00, 0x00, 0x43, 0x02, 0x77, 0x02, 0xb9, 0x02, 0xe6, 0x02, 0x00,
- 0x00, 0x35, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x03, 0x00,
- 0x08, 0xe5, 0x62, 0x00, 0x63, 0x0f, 0x73, 0x13, 0x74, 0x1b, 0x75, 0x2f,
- 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0x00, 0x06, 0x40, 0x09, 0x61, 0x00, 0x40, 0x09, 0x63, 0x68, 0x69,
- 0x6e, 0x6f, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x24, 0x40, 0x07, 0x72, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3f, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x82, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x09, 0xe3, 0x61, 0x00, 0x65, 0x13, 0x69, 0x15, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x09, 0x61, 0x00, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x02, 0xde, 0xe2, 0x61, 0x00, 0x7a, 0x02, 0x00, 0x07, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x0b, 0xe7, 0x61, 0x00, 0x67, 0x0c, 0x6a, 0x12, 0x6d, 0x19, 0x6e, 0x1e,
- 0x6f, 0x4b, 0x74, 0x53, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x40,
- 0x09, 0x68, 0x69, 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x00, 0x40, 0x07,
- 0x75, 0x61, 0x6e, 0x61, 0x00, 0x40, 0x06, 0x62, 0x61, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x1f, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x72, 0x06, 0x74, 0x0a,
- 0x00, 0x09, 0x40, 0x5e, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0xeb, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x65, 0x74,
- 0x74, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x3b, 0x6c, 0x00,
- 0x40, 0x00, 0x6d, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x61, 0x6d, 0x00,
- 0xe7, 0x00, 0x00, 0x64, 0x02, 0x65, 0x08, 0x69, 0x53, 0x6b, 0x58, 0x73,
- 0x64, 0x75, 0x80, 0x03, 0x30, 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0xe3,
- 0x64, 0x00, 0x72, 0x0b, 0x74, 0x0d, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x37, 0x40, 0x00, 0x79, 0x00, 0x00, 0x09, 0xe5, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x15, 0x69, 0x20, 0x70, 0x25, 0x03, 0xbb, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40,
- 0x37, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x06, 0x72, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6c, 0x61, 0x63,
- 0x65, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x10, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x09, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40, 0x06, 0x73, 0x70,
- 0x69, 0x6b, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x6c,
- 0x61, 0x64, 0x65, 0x00, 0xe3, 0x72, 0x00, 0x73, 0x06, 0x74, 0x0b, 0x40,
- 0x00, 0x65, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0x00, 0x09,
- 0x40, 0x55, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x16, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x73, 0x04, 0x74, 0x08, 0x00, 0x09,
- 0x00, 0x06, 0x40, 0x09, 0x73, 0x00, 0x40, 0x07, 0x72, 0x79, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x74, 0x65, 0x00, 0xe4, 0x65, 0x00,
- 0x69, 0x04, 0x6f, 0x33, 0x79, 0x37, 0x40, 0x37, 0x64, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x20, 0x6e, 0x24, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x65,
- 0x00, 0x40, 0x06, 0x64, 0x00, 0x40, 0x00, 0x67, 0x00, 0x40, 0x09, 0x77,
- 0x00, 0x00, 0x4b, 0xe2, 0x68, 0x00, 0x75, 0x21, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x6c, 0x06, 0x6d, 0x0c, 0x79, 0x14, 0x00, 0x09, 0x40, 0x2c, 0x6c,
- 0x00, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x61, 0x6c, 0x6c,
- 0x6f, 0x77, 0x00, 0x00, 0xf3, 0x40, 0x09, 0x70, 0x69, 0x61, 0x6c, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x12, 0x79, 0x37, 0x03, 0xb4, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x00, 0x69,
- 0x74, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x09, 0xe2, 0x6c, 0x00, 0x6e,
- 0x02, 0x00, 0x3b, 0x00, 0x08, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x67, 0x06,
- 0x69, 0x0c, 0x00, 0x09, 0x40, 0x09, 0x74, 0x00, 0x40, 0x09, 0x61, 0x6c,
- 0x65, 0x00, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x55, 0x40, 0x07, 0x6f, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x55, 0x40, 0x3b, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x69, 0x70, 0x61, 0x6e, 0x00, 0xf8, 0x63, 0x00, 0x00,
- 0x65, 0x2f, 0x00, 0x68, 0x33, 0x00, 0x6b, 0x44, 0x00, 0x6f, 0x55, 0x00,
- 0x71, 0x92, 0x00, 0x73, 0xb1, 0x00, 0x74, 0xef, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x6f, 0x07, 0x75, 0x0b, 0x00, 0x00, 0x40, 0x59, 0x72, 0x61,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6e, 0x00, 0x73, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0x40, 0x00, 0x6d, 0x00, 0x40, 0x06, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x75, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x09, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06,
- 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x63,
- 0x00, 0x6e, 0x27, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72,
- 0x06, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09,
- 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x10, 0x69, 0x1e, 0x03, 0x57, 0xe2, 0x63, 0x00, 0x67, 0x05, 0x40, 0x82,
- 0x72, 0x65, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x72,
- 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x66, 0x00,
- 0x76, 0x02, 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x65,
- 0x02, 0x68, 0x56, 0x69, 0x5c, 0x6f, 0x82, 0x75, 0x90, 0x00, 0xb2, 0xe2,
- 0x63, 0x00, 0x72, 0x07, 0x40, 0x06, 0x74, 0x6f, 0x6d, 0x79, 0x00, 0xea,
- 0x00, 0x00, 0x27, 0x02, 0x63, 0x06, 0x66, 0x0d, 0x6c, 0x12, 0x6d, 0x16,
- 0x70, 0x1c, 0x73, 0x23, 0x77, 0x2b, 0x79, 0x31, 0x01, 0xf9, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x08, 0x6c, 0x61, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x75,
- 0x6c, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x93, 0x69, 0x6e, 0x64, 0x00,
- 0x40, 0x09, 0x69, 0x65, 0x63, 0x65, 0x00, 0x40, 0x06, 0x74, 0x72, 0x6f,
- 0x6b, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x6b, 0x00, 0x00, 0x07, 0x40,
- 0x09, 0x65, 0x61, 0x64, 0x00, 0xe3, 0x63, 0x00, 0x66, 0x16, 0x74, 0x1a,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x66, 0x00, 0x40, 0x00, 0x69, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x69, 0x05,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x64, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63,
- 0x08, 0x00, 0x65, 0x65, 0x00, 0x68, 0xc7, 0x00, 0x69, 0xf3, 0x00, 0x72,
- 0x05, 0x01, 0x74, 0x75, 0x01, 0x75, 0x97, 0x01, 0x7a, 0xb7, 0x01, 0x00,
- 0xfa, 0x40, 0x06, 0x64, 0x6f, 0x72, 0x00, 0xe1, 0x68, 0x00, 0xe8, 0x00,
- 0x00, 0x62, 0x02, 0x65, 0x10, 0x69, 0x14, 0x6c, 0x19, 0x6d, 0x28, 0x73,
- 0x3c, 0x77, 0x43, 0x00, 0x69, 0xe1, 0x6f, 0x00, 0xe2, 0x6f, 0x00, 0x78,
- 0x04, 0x40, 0x06, 0x6b, 0x00, 0x00, 0x09, 0x40, 0x37, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x63, 0x6b, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6b,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x09, 0x74, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x07,
- 0x6f, 0x6f, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x79, 0x59, 0x00,
- 0x09, 0xe2, 0x69, 0x00, 0x6e, 0x44, 0xe2, 0x61, 0x00, 0x65, 0x3b, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0xe2, 0x73, 0x00,
- 0x7a, 0x1e, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x07,
- 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0x00, 0x08, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73,
- 0x23, 0x00, 0x07, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x73,
- 0x09, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00, 0x07,
- 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x67, 0x04, 0x73, 0x06,
- 0x40, 0x06, 0x65, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x6f,
- 0x67, 0xe4, 0x61, 0x00, 0x63, 0x1c, 0x6d, 0x4a, 0x78, 0x5c, 0xe1, 0x72,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x73, 0x06, 0x79, 0x08, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x00,
- 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x75, 0x12, 0x40, 0x00, 0x73,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c,
- 0x00, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x00, 0x61, 0x6c, 0x00, 0x00, 0x07, 0x00, 0x07, 0x40, 0x86, 0x6e, 0x00,
- 0xe4, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e, 0x72, 0x13, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x7e, 0x00, 0x2f, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x11, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x03,
- 0xbc, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe3, 0x00, 0x00,
- 0x68, 0x02, 0x74, 0x0b, 0x01, 0x58, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x64, 0x00, 0x6c, 0x06, 0x6e, 0x11,
- 0x73, 0x17, 0x76, 0x1f, 0x40, 0x00, 0x6c, 0x69, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x7a, 0x64,
- 0x65, 0x72, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x75, 0x6d, 0x00, 0x40,
- 0x07, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00,
- 0x06, 0x40, 0x06, 0x69, 0x63, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02,
- 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x59, 0xe3, 0x00, 0x00, 0x6c, 0x02,
- 0x6d, 0x17, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x72, 0x04, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x79,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x75, 0x17, 0x00, 0x06,
- 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x06, 0x6d,
- 0x00, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x64, 0x06, 0x66, 0x0b, 0x68, 0x1b,
- 0x6e, 0x20, 0x6f, 0x25, 0x70, 0x52, 0x73, 0x58, 0x00, 0x07, 0x40, 0x06,
- 0x65, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x6f,
- 0x00, 0x79, 0x06, 0x40, 0x09, 0x77, 0x65, 0x72, 0x00, 0x00, 0x06, 0x40,
- 0x07, 0x65, 0x6d, 0x00, 0x40, 0x00, 0x27, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x6e, 0x02, 0x72, 0x0a, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x61, 0x69, 0x73,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x10, 0x00, 0x06, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x09, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x00,
- 0x40, 0x00, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40,
- 0x09, 0x72, 0x6b, 0x61, 0x00, 0x40, 0x00, 0x73, 0x65, 0x00, 0xc1, 0x61,
- 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x00, 0x00, 0xb4, 0x01, 0x04, 0x02, 0x19,
- 0x03, 0x00, 0x00, 0x5f, 0x03, 0x1e, 0x04, 0x20, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x32, 0x04, 0x3c, 0x05, 0xef, 0x05, 0x8f, 0x07, 0x00, 0x00, 0x00,
- 0x00, 0x93, 0x07, 0x39, 0x09, 0x3d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x5c,
- 0x0d, 0x69, 0x0d, 0x00, 0x00, 0x6f, 0x0d, 0x03, 0xbd, 0xf6, 0x64, 0x00,
- 0x00, 0x67, 0x17, 0x00, 0x6c, 0x2a, 0x00, 0x6e, 0x59, 0x00, 0x73, 0xd4,
- 0x00, 0x74, 0x1e, 0x01, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0xe1,
- 0x77, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x40, 0x09, 0x61,
- 0x72, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00,
- 0x00, 0x69, 0x02, 0x74, 0x09, 0x79, 0x0f, 0x00, 0x09, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x69, 0x6d, 0x65, 0x00, 0xe3, 0x00,
- 0x00, 0x62, 0x02, 0x6d, 0x07, 0x01, 0x92, 0x40, 0x06, 0x75, 0x67, 0x00,
- 0x40, 0x00, 0x6f, 0x75, 0x74, 0x68, 0x65, 0x64, 0x00, 0xe7, 0x00, 0x00,
- 0x64, 0x02, 0x69, 0x15, 0x6e, 0x51, 0x74, 0x57, 0x77, 0x63, 0x79, 0x6a,
- 0x03, 0xbe, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x92, 0x40, 0x07, 0x6e, 0x67, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x02, 0x00, 0x07, 0xe1, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02,
- 0x6c, 0x15, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x37, 0x40, 0x07,
- 0x6d, 0x65, 0x00, 0x40, 0x07, 0x68, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x06,
- 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x75, 0x0d, 0x00, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x04, 0x40, 0x07, 0x73, 0x00, 0x00, 0xf3, 0xe1, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02,
- 0x64, 0x06, 0x6c, 0x08, 0x6d, 0x0e, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00,
- 0x00, 0x37, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x65, 0x6e,
- 0x74, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x68, 0x08, 0x69, 0x0e, 0x6c,
- 0x15, 0x70, 0x2e, 0x79, 0x37, 0x00, 0x09, 0x40, 0x09, 0x61, 0x6c, 0x6c,
- 0x00, 0x40, 0x09, 0x65, 0x61, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x73, 0x73, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x65, 0x73, 0x00, 0x40, 0x07, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x00,
- 0x01, 0x92, 0xe2, 0x63, 0x00, 0x68, 0x04, 0x40, 0x06, 0x61, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe3, 0x63, 0x00, 0x73,
- 0x0f, 0x7a, 0x29, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x09,
- 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xf5, 0x61,
- 0x00, 0x00, 0x64, 0x17, 0x00, 0x69, 0x2e, 0x00, 0x6c, 0xea, 0x00, 0x75,
- 0xef, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07,
- 0x00, 0x06, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x06, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02,
- 0x73, 0x04, 0x00, 0x3f, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00,
- 0xe6, 0x61, 0x00, 0x63, 0x28, 0x65, 0x6a, 0x6f, 0x7f, 0x74, 0x91, 0x75,
- 0xab, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x04, 0x74, 0x06, 0x00, 0x06,
- 0x03, 0xbf, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x0e, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x57, 0x00, 0x37, 0x40, 0x75, 0x6f, 0x6e,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x29,
- 0x6f, 0x37, 0x00, 0x06, 0xe5, 0x69, 0x00, 0x6c, 0x04, 0x6d, 0x06, 0x72,
- 0x0c, 0x74, 0x10, 0x40, 0x07, 0x64, 0x00, 0x00, 0x56, 0x40, 0x07, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x09, 0x00, 0x09, 0xe1,
- 0x76, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x06, 0x74,
- 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x02, 0x7d, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x3b, 0x65, 0x00, 0x40, 0x09, 0x6d, 0x00, 0x40, 0x09, 0x65, 0x79,
- 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x05, 0x40, 0x06, 0x6c, 0x61, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe4,
- 0x64, 0x00, 0x6b, 0x02, 0x72, 0x0f, 0x74, 0x18, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0xe0, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x06, 0x73, 0x63, 0x68, 0x61, 0x75, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x75, 0x16, 0x03, 0xc0, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x68, 0x02, 0x00, 0x07, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65,
- 0x00, 0x60, 0x09, 0x70, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x08, 0xea, 0x00, 0x00, 0x62, 0x02, 0x63, 0x18, 0x64,
- 0x2a, 0x68, 0x3f, 0x6c, 0x46, 0x70, 0x81, 0x73, 0x92, 0x74, 0x98, 0x77,
- 0x9d, 0x00, 0x00, 0xe3, 0x69, 0x00, 0x75, 0x04, 0x79, 0x0a, 0x40, 0x06,
- 0x74, 0x00, 0x40, 0x07, 0x63, 0x6b, 0x73, 0x00, 0x40, 0x09, 0x74, 0x65,
- 0x00, 0xe2, 0x68, 0x00, 0x79, 0x07, 0x40, 0x09, 0x75, 0x72, 0x63, 0x68,
- 0x00, 0x40, 0x06, 0x63, 0x6c, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x65, 0x72, 0x74, 0x7a, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x15, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x73, 0x06, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x15, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x6c, 0x69, 0x73, 0x00, 0xe2, 0x68,
- 0x00, 0x69, 0x06, 0x40, 0x5e, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x78,
- 0x65, 0x6c, 0x00, 0x40, 0x08, 0x74, 0x61, 0x72, 0x00, 0x40, 0x06, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x61, 0x74, 0x74, 0x00, 0x00, 0x00, 0xe1, 0x6f,
- 0x00, 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x07, 0x69, 0x73, 0x00, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0xe7, 0x61, 0x00, 0x64, 0x3a, 0x65, 0x3c, 0x69,
- 0x40, 0x6c, 0x58, 0x6f, 0x8c, 0x74, 0xe8, 0xe2, 0x6d, 0x00, 0x6e, 0x06,
- 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x63, 0x00, 0x67, 0x19, 0x69,
- 0x1d, 0x6f, 0x21, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x09, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07,
- 0x00, 0x08, 0x00, 0x07, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x06, 0x6d, 0x61, 0x00, 0x00, 0x47, 0x40, 0x06, 0x65, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0xa6, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x1f, 0xe1, 0x66, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x77, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x3a, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x55, 0xe3, 0x69, 0x00, 0x72,
- 0x25, 0x79, 0x4c, 0xe2, 0x63, 0x00, 0x6f, 0x0d, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0xe3,
- 0x00, 0x00, 0x27, 0x02, 0x64, 0x06, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0xe4, 0x62, 0x00, 0x65, 0x35, 0x6f,
- 0x41, 0x73, 0xa3, 0xe2, 0x65, 0x00, 0x72, 0x1e, 0xe1, 0x72, 0x00, 0xe4,
- 0x00, 0x00, 0x27, 0x02, 0x6c, 0x06, 0x73, 0x0c, 0x03, 0xc1, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x09, 0x69, 0x73, 0x74, 0x00, 0x40, 0x06, 0x68, 0x69,
- 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x08, 0x40, 0x09, 0x74, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x72, 0x06, 0x00, 0x09, 0x40, 0x09, 0x72, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x2a, 0x79, 0x4c, 0xe2, 0x62, 0x00, 0x6e, 0x1f, 0xe2, 0x69, 0x00,
- 0x6c, 0x11, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x37, 0x00, 0x00, 0x40, 0x09, 0x64, 0x75, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x7a, 0x0f, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x3a, 0x7a, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x00, 0x06, 0x40, 0x08,
- 0x61, 0x68, 0x69, 0x62, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x64, 0x22, 0x00, 0x66, 0x6a, 0x00, 0x68, 0x7c, 0x00, 0x69, 0x83, 0x00,
- 0x6f, 0xb9, 0x00, 0x73, 0xe1, 0x00, 0x74, 0x37, 0x01, 0x75, 0x7f, 0x01,
- 0x00, 0x07, 0xe2, 0x63, 0x00, 0x67, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x82, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x09, 0x40, 0x09, 0x69, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x16, 0x69, 0x25, 0x00, 0xe7, 0xe1, 0x63, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x05, 0x40, 0x3b, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x08, 0x40, 0x07,
- 0x65, 0x76, 0x69, 0x75, 0x6d, 0x00, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x6e,
- 0x11, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x79, 0x00, 0x00, 0x06, 0x40, 0x07, 0x67, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x61, 0x64, 0x65, 0x6e, 0x00, 0xe3,
- 0x61, 0x00, 0x6e, 0x04, 0x73, 0x21, 0x40, 0x86, 0x6c, 0x00, 0xe2, 0x67,
- 0x00, 0x78, 0x16, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x61, 0x00, 0x73,
- 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07, 0x74, 0x69, 0x73,
- 0x00, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x70, 0x00, 0x72, 0x14, 0xe1, 0x61,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe5, 0x63, 0x00,
- 0x65, 0x04, 0x74, 0x13, 0x75, 0x2f, 0x77, 0x45, 0x40, 0x09, 0x68, 0x00,
- 0xe2, 0x72, 0x00, 0x73, 0x08, 0x40, 0x00, 0x76, 0x61, 0x6e, 0x74, 0x73,
- 0x00, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x40,
- 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x61, 0x72, 0x00, 0xe4,
- 0x61, 0x00, 0x68, 0x17, 0x69, 0x2a, 0x6f, 0x3b, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40,
- 0x06, 0x74, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x74, 0x65,
- 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x95, 0x40, 0x37, 0x64, 0x00, 0x40, 0x47, 0x72, 0x00, 0x00,
- 0x09, 0x40, 0x47, 0x77, 0x00, 0xf6, 0x63, 0x00, 0x00, 0x65, 0xab, 0x00,
- 0x67, 0xd4, 0x00, 0x69, 0xe9, 0x00, 0x6d, 0x48, 0x01, 0x72, 0x5c, 0x01,
- 0xe6, 0x61, 0x00, 0x65, 0x18, 0x68, 0x2f, 0x69, 0x67, 0x75, 0x87, 0x79,
- 0x9c, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x6d,
- 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x06, 0x40, 0x06, 0x61, 0x72, 0x79, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x0b, 0x7a, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x19, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x03, 0xc2, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x66, 0x00, 0x6c,
- 0x05, 0x40, 0x36, 0x75, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0b,
- 0xe2, 0x61, 0x00, 0x63, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x03, 0xc3, 0xe1, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x09, 0x6e, 0x73, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe3, 0x64, 0x00, 0x6e, 0x06, 0x74, 0x12,
- 0x40, 0x09, 0x69, 0x61, 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x6f, 0x05, 0x40,
- 0x09, 0x75, 0x65, 0x00, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x6f, 0x0b, 0x01, 0x82, 0x40, 0x37, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x14, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x40, 0x00,
- 0x69, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0b, 0xe2, 0x69, 0x00,
- 0x6e, 0x04, 0x40, 0x06, 0x64, 0x00, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x17, 0xe3, 0x6c, 0x00, 0x6d, 0x04, 0x6e, 0x0a,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0x3b, 0xe1,
- 0x61, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe9, 0x61, 0x00, 0x63, 0x02,
- 0x64, 0x1b, 0x68, 0x32, 0x6d, 0x34, 0x6f, 0x56, 0x71, 0x88, 0x73, 0x8f,
- 0x74, 0xeb, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x00,
- 0x6d, 0x65, 0x73, 0x00, 0x40, 0x00, 0x6d, 0x6f, 0x69, 0x73, 0x65, 0x6c,
- 0x6c, 0x65, 0x73, 0x00, 0x00, 0x47, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x69, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x02, 0x7a, 0x06, 0x00, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x3f, 0x00, 0x07, 0xe4, 0x6d, 0x00, 0x6e, 0x15, 0x73, 0x17, 0x74,
- 0x1f, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06,
- 0x40, 0x06, 0x70, 0x68, 0x65, 0x72, 0x65, 0x00, 0x40, 0x07, 0x68, 0x65,
- 0x6c, 0x69, 0x6f, 0x6d, 0x61, 0x00, 0x40, 0x06, 0x75, 0x69, 0x74, 0x65,
- 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x1b, 0x6d, 0x47,
- 0x79, 0x4d, 0x00, 0x47, 0x40, 0x82, 0x67, 0x65, 0x00, 0xe2, 0x69, 0x00,
- 0x6e, 0x09, 0x40, 0x00, 0x67, 0x6e, 0x65, 0x75, 0x72, 0x73, 0x00, 0x40,
- 0x06, 0x67, 0x65, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x13, 0x6c, 0x19,
- 0x6e, 0x1d, 0xe2, 0x68, 0x00, 0x6e, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0x40, 0x00, 0x75,
- 0x72, 0x73, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x61, 0x74, 0x65, 0x00, 0x00, 0x96, 0x40, 0x09, 0x69,
- 0x7a, 0x6f, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x79,
- 0x01, 0x68, 0xf4, 0x01, 0x69, 0x84, 0x02, 0x72, 0xa9, 0x02, 0x74, 0xf6,
- 0x02, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x63, 0x2d,
- 0x00, 0x64, 0x47, 0x00, 0x6c, 0x51, 0x00, 0x6d, 0xaa, 0x00, 0x70, 0xd4,
- 0x00, 0x73, 0x08, 0x01, 0x74, 0x2c, 0x01, 0x00, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe4, 0x63, 0x00, 0x73, 0x0d, 0x74,
- 0x11, 0x7a, 0x15, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x6d, 0x00, 0x40, 0x06, 0x65, 0x00,
- 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x70,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x75, 0x06, 0x40, 0x06, 0x6c, 0x00,
- 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0x60, 0x09, 0x61, 0x74, 0x61, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x0b, 0x77,
- 0x35, 0x00, 0xb1, 0x40, 0x09, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00,
- 0xe2, 0x69, 0x00, 0x75, 0x04, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73,
- 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x03, 0x42,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x0b, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6d,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40,
- 0x07, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x18, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x73,
- 0x04, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x73, 0x00, 0x74, 0x14, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x73, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x02, 0x00, 0x07, 0x40, 0x3a,
- 0x65, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x17,
- 0xe1, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x75,
- 0x06, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x6f,
- 0x24, 0x72, 0x70, 0x00, 0xa5, 0xe1, 0x70, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x18, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x74, 0x0d, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x04, 0x40, 0x06, 0x64, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00,
- 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07, 0x00, 0xec, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x26, 0x6f, 0x2c, 0x73, 0x7d, 0x79, 0x7f, 0x00, 0x00,
- 0xe3, 0x64, 0x00, 0x6d, 0x06, 0x6e, 0x12, 0x40, 0x07, 0x6f, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x70, 0x68, 0x65, 0x74, 0x61, 0x6d, 0x69, 0x6e, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x00,
- 0x40, 0x00, 0x6e, 0x6b, 0x73, 0x00, 0xe4, 0x64, 0x00, 0x74, 0x35, 0x75,
- 0x3e, 0x78, 0x44, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x18, 0x00, 0x09,
- 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06,
- 0x40, 0x3b, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x06, 0x40, 0x00, 0x72, 0x65,
- 0x78, 0x61, 0x74, 0x65, 0x00, 0x40, 0x00, 0x67, 0x68, 0x74, 0x00, 0x40,
- 0x00, 0x79, 0x00, 0x00, 0x00, 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x63, 0x00,
- 0x65, 0x1c, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x24, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x15, 0x00, 0x08, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x3b, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x0b,
- 0x7a, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x70, 0x08, 0x00, 0x06,
- 0x40, 0x09, 0x6f, 0x6d, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x61, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x73, 0x04, 0x00, 0x93, 0x00, 0x3a, 0x00, 0x07, 0x40,
- 0x00, 0x69, 0x63, 0x6f, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x07, 0x40, 0x09, 0x6e, 0x69, 0x6e, 0x65, 0x00, 0x00, 0x06, 0xe2, 0x67,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x08, 0xe3, 0x00, 0x00, 0x6d, 0x02,
- 0x72, 0x06, 0x00, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x00, 0xc1, 0x61,
- 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x12, 0x02, 0x5b,
- 0x03, 0x5f, 0x03, 0x63, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4,
- 0x03, 0xd0, 0x03, 0xde, 0x05, 0x33, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xd6, 0x08, 0x28, 0x09, 0xe4, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x5a, 0x10, 0x00, 0x00, 0x72, 0x10, 0x00, 0x1e, 0x40, 0x09, 0x73,
- 0x6d, 0x61, 0x00, 0xf5, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x04,
- 0x00, 0x6b, 0x06, 0x00, 0x72, 0x11, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x08, 0x40, 0x09, 0x79, 0x00,
- 0xf1, 0x6f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x63,
- 0x3e, 0x00, 0x64, 0x73, 0x00, 0x65, 0x78, 0x00, 0x66, 0xa8, 0x00, 0x67,
- 0xcb, 0x00, 0x6c, 0xd3, 0x00, 0x6d, 0xe3, 0x00, 0x6e, 0x15, 0x01, 0x6f,
- 0x17, 0x01, 0x70, 0x21, 0x01, 0x73, 0x36, 0x01, 0x77, 0x6b, 0x01, 0x00,
- 0x06, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x72, 0x2d, 0x00, 0x09, 0xe2, 0x61,
- 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40,
- 0x09, 0x74, 0x00, 0x00, 0x07, 0x40, 0x06, 0x65, 0x77, 0x65, 0x72, 0x79,
- 0x00, 0xe3, 0x68, 0x00, 0x69, 0x05, 0x6f, 0x0d, 0x40, 0x09, 0x69, 0x70,
- 0x00, 0x40, 0x06, 0x72, 0x63, 0x75, 0x69, 0x74, 0x00, 0xe3, 0x64, 0x00,
- 0x6d, 0x04, 0x73, 0x0c, 0x40, 0x00, 0x65, 0x00, 0x40, 0x09, 0x70, 0x75,
- 0x74, 0x65, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x6f, 0x74, 0x00, 0xe2,
- 0x63, 0x00, 0x6c, 0x0a, 0x40, 0x07, 0x6f, 0x6e, 0x6f, 0x6d, 0x69, 0x63,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xe2,
- 0x69, 0x00, 0x6c, 0x15, 0xe3, 0x62, 0x00, 0x63, 0x05, 0x6c, 0x0a, 0x40,
- 0x09, 0x65, 0x72, 0x00, 0x40, 0x07, 0x68, 0x65, 0x00, 0x40, 0x59, 0x6d,
- 0x00, 0x40, 0x00, 0x6f, 0x70, 0x70, 0x69, 0x65, 0x73, 0x00, 0x40, 0x06,
- 0x72, 0x6f, 0x6f, 0x76, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x06, 0x40,
- 0x09, 0x67, 0x68, 0x74, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x19, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01, 0x13, 0x40, 0x07,
- 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6f,
- 0x00, 0x72, 0x07, 0x40, 0x06, 0x72, 0x69, 0x74, 0x65, 0x00, 0x00, 0x09,
- 0x00, 0x09, 0x40, 0x09, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x00,
- 0xe2, 0x68, 0x00, 0x72, 0x06, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00, 0x40,
- 0x09, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x00, 0xe3, 0x63, 0x00,
- 0x65, 0x1f, 0x75, 0x26, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x79, 0x10, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07, 0x40,
- 0x09, 0x63, 0x6f, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x72, 0x67, 0x65, 0x72,
- 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x03, 0xb2, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00,
- 0xff, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x64, 0x07, 0x00, 0x66, 0x4a,
- 0x00, 0x67, 0x51, 0x00, 0x69, 0x5d, 0x00, 0x6c, 0x5f, 0x00, 0x6d, 0x6e,
- 0x00, 0x6e, 0x74, 0x00, 0x70, 0x7b, 0x00, 0x72, 0x82, 0x00, 0x73, 0x90,
- 0x00, 0x74, 0xd6, 0x00, 0x77, 0xe5, 0x00, 0x79, 0x15, 0x01, 0x00, 0x00,
- 0x40, 0x07, 0x69, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x6c, 0x08,
- 0x79, 0x38, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6d, 0x08, 0x77, 0x1c, 0x01, 0x7f,
- 0x40, 0x06, 0x72, 0x6f, 0x77, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x6f,
- 0x08, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x73,
- 0x74, 0x00, 0x40, 0x09, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00, 0x06,
- 0x40, 0x89, 0x69, 0x65, 0x6c, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x06, 0x00, 0x09, 0x00, 0x09, 0xe2, 0x61, 0x00,
- 0x69, 0x05, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x66, 0x65, 0x00,
- 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0x40, 0x07, 0x69, 0x67, 0x68, 0x74,
- 0x00, 0x40, 0x09, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x62, 0x00, 0x66, 0x02, 0x00, 0x09, 0x40, 0x09, 0x66, 0x00, 0xe5, 0x65,
- 0x00, 0x68, 0x08, 0x69, 0x22, 0x74, 0x27, 0x75, 0x34, 0x40, 0x09, 0x63,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00, 0xe2,
- 0x6d, 0x00, 0x73, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x40, 0x00, 0x7a, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x61, 0x6d,
- 0x00, 0x40, 0x07, 0x6d, 0x6d, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x05, 0x40, 0x09, 0x72, 0x6d, 0x00, 0x40, 0x07, 0x77, 0x6e, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x04, 0x69, 0x09, 0x40, 0x09, 0x79, 0x00, 0x40, 0x09,
- 0x65, 0x6b, 0x00, 0xe3, 0x66, 0x00, 0x6e, 0x0e, 0x76, 0x14, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x82, 0x40, 0x06, 0x79, 0x00,
- 0x40, 0x07, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40,
- 0x09, 0x65, 0x61, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x3a, 0x66,
- 0x00, 0xe3, 0x68, 0x00, 0x6e, 0x2b, 0x72, 0x34, 0xe1, 0x74, 0x00, 0xe5,
- 0x00, 0x00, 0x27, 0x02, 0x69, 0x07, 0x6e, 0x16, 0x79, 0x1b, 0x00, 0x07,
- 0x40, 0x00, 0x76, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x27, 0x74,
- 0x00, 0x01, 0x3b, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x74, 0x74, 0x65, 0x00,
- 0xe1, 0x61, 0x00, 0xe3, 0x69, 0x00, 0x6e, 0x05, 0x74, 0x09, 0x40, 0x09,
- 0x6e, 0x65, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x4b, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x09, 0x64, 0x6f, 0x00,
- 0x00, 0x82, 0xfc, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x07, 0x00,
- 0x64, 0x0b, 0x00, 0x65, 0x1e, 0x00, 0x66, 0x3f, 0x00, 0x69, 0x41, 0x00,
- 0x6b, 0xae, 0x00, 0x6c, 0xf5, 0x00, 0x6f, 0xd5, 0x01, 0x71, 0xdd, 0x01,
- 0x74, 0xe7, 0x01, 0x00, 0x0f, 0x40, 0x06, 0x64, 0x79, 0x00, 0x40, 0x00,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x03, 0xc4, 0x40,
- 0x2c, 0x77, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x70, 0x07, 0x72, 0x0d, 0x73, 0x0f, 0x00, 0x09, 0x40, 0x06,
- 0x67, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40,
- 0x09, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x74,
- 0x04, 0x40, 0x06, 0x75, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x48, 0xe3, 0x6e,
- 0x00, 0x72, 0x0b, 0x74, 0x3d, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x86, 0xe2, 0x69, 0x00, 0x79, 0x2b, 0xe3, 0x6c, 0x00,
- 0x73, 0x04, 0x7a, 0x16, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x63, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x41, 0x52, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x03, 0x4a, 0x00, 0x07, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe7, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6d, 0x0d, 0x73, 0x21, 0x77, 0x30, 0x79, 0x36,
- 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0b, 0xe2, 0x69, 0x00, 0x6e, 0x04, 0x40,
- 0x09, 0x64, 0x00, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x68, 0x00,
- 0x6f, 0x06, 0x40, 0x06, 0x61, 0x6b, 0x65, 0x00, 0x40, 0x09, 0x70, 0x00,
- 0x40, 0x06, 0x65, 0x65, 0x64, 0x00, 0x00, 0xf4, 0xe8, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x07, 0x69, 0x2a, 0x70, 0xa8, 0x72, 0xae, 0x73, 0xb4, 0x77,
- 0xc7, 0x03, 0xc5, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe3, 0x6e, 0x00, 0x72,
- 0x18, 0x74, 0x1a, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00,
- 0x75, 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x09, 0x6d, 0x00, 0x00, 0x07, 0x00, 0x07, 0xe9, 0x61, 0x00, 0x62, 0x05,
- 0x67, 0x0a, 0x6c, 0x10, 0x6d, 0x17, 0x6e, 0x1e, 0x6f, 0x31, 0x70, 0x5d,
- 0x73, 0x63, 0x40, 0x09, 0x72, 0x64, 0x00, 0x40, 0x09, 0x61, 0x72, 0x00,
- 0x40, 0x09, 0x72, 0x61, 0x6d, 0x00, 0x40, 0x09, 0x69, 0x74, 0x65, 0x72,
- 0x00, 0x40, 0x09, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x0c, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00,
- 0x07, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x74,
- 0x16, 0x03, 0xc6, 0xe1, 0x69, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x08, 0x73, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x06, 0x65, 0x64, 0x65, 0x00, 0x40, 0x06, 0x65, 0x63, 0x6f, 0x6e, 0x64,
- 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x61, 0x63, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x05, 0x40, 0x06, 0x6e,
- 0x65, 0x00, 0x40, 0x09, 0x65, 0x61, 0x6d, 0x00, 0x40, 0x06, 0x72, 0x69,
- 0x67, 0x68, 0x74, 0x00, 0x40, 0x08, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x06, 0x75, 0x65, 0x74, 0x6f, 0x61, 0x73, 0x74, 0x00, 0x00, 0x47,
- 0xe3, 0x65, 0x00, 0x69, 0x26, 0x6f, 0x49, 0xe3, 0x00, 0x00, 0x6f, 0x02,
- 0x74, 0x1a, 0x00, 0x82, 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0xec, 0x00, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe1, 0x63, 0x00,
- 0xe3, 0x00, 0x00, 0x6b, 0x02, 0x72, 0x15, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x06, 0x73, 0x61,
- 0x00, 0xfe, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x12, 0x00, 0x64,
- 0x26, 0x00, 0x65, 0x79, 0x00, 0x67, 0xc8, 0x00, 0x69, 0xd3, 0x00, 0x6b,
- 0xc7, 0x01, 0x6e, 0xc9, 0x01, 0x6f, 0xdb, 0x01, 0x73, 0xf3, 0x01, 0x74,
- 0x14, 0x02, 0x75, 0x2a, 0x02, 0x78, 0x76, 0x02, 0x00, 0x00, 0xe2, 0x72,
- 0x00, 0x74, 0x05, 0x40, 0x09, 0x65, 0x74, 0x00, 0x40, 0x00, 0x6f, 0x72,
- 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08,
- 0x00, 0x7e, 0x40, 0x07, 0x65, 0x61, 0x74, 0x00, 0x00, 0x07, 0xe7, 0x00,
- 0x00, 0x27, 0x02, 0x62, 0x06, 0x65, 0x12, 0x66, 0x16, 0x6c, 0x29, 0x73,
- 0x3f, 0x03, 0xc7, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x67, 0x67,
- 0x6c, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x00, 0x40, 0x5d, 0x64, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x65, 0x74, 0x00, 0xe4, 0x00, 0x00,
- 0x66, 0x02, 0x72, 0x09, 0x73, 0x32, 0x03, 0xc8, 0x40, 0x06, 0x69, 0x65,
- 0x6c, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0xe1, 0x67, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61,
- 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x74, 0x00, 0x77,
- 0x07, 0x40, 0x07, 0x72, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x65, 0x65,
- 0x70, 0x65, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x79, 0x04, 0x40, 0x3a, 0x65,
- 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x62, 0x29, 0x63, 0x3d,
- 0x66, 0x54, 0x6d, 0x5e, 0x6e, 0x94, 0x6f, 0x98, 0x73, 0x9c, 0x76, 0xda,
- 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40,
- 0x09, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x75, 0x09,
- 0x40, 0x08, 0x72, 0x00, 0x40, 0x06, 0x6b, 0x65, 0x00, 0x40, 0x09, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x09, 0xe2, 0x62, 0x00, 0x6d, 0x02, 0x00,
- 0x08, 0x00, 0x09, 0x40, 0x06, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x6c, 0x6f, 0x70, 0x70, 0x69, 0x65, 0x73, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x18, 0x75, 0x29, 0x00, 0x06, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x7a, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a,
- 0x40, 0x09, 0x6d, 0x00, 0x40, 0x07, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe3, 0x65, 0x00, 0x6b, 0x07, 0x74, 0x0d, 0x40, 0x07, 0x72, 0x69, 0x65,
- 0x73, 0x00, 0x40, 0x09, 0x69, 0x72, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72,
- 0x0f, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x93, 0x40,
- 0x00, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x0f, 0xe2, 0x6e, 0x00,
- 0x74, 0x04, 0x40, 0x09, 0x74, 0x00, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x06, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x6f, 0x09, 0x40, 0x09, 0x73, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x00, 0x40,
- 0x06, 0x77, 0x00, 0xe2, 0x72, 0x00, 0x78, 0x0c, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x2c, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x07, 0x69, 0x64,
- 0x69, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0xe2, 0x65,
- 0x00, 0x72, 0x04, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x79, 0x0b, 0x00, 0xe7, 0x40,
- 0x07, 0x67, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x00, 0xf3, 0xe3, 0x65,
- 0x00, 0x73, 0x0b, 0x74, 0x18, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09,
- 0x64, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x09, 0x40,
- 0x09, 0x75, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x1c, 0xe3, 0x00,
- 0x00, 0x6d, 0x02, 0x6e, 0x0f, 0x03, 0xc9, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x09, 0xe5, 0x61, 0x00, 0x65, 0x19, 0x72, 0x1b, 0x74,
- 0x20, 0x79, 0x45, 0xe2, 0x63, 0x00, 0x67, 0x10, 0xe2, 0x6c, 0x00, 0x75,
- 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x3b, 0x6c, 0x6f, 0x75, 0x73, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0x00, 0x82, 0x40, 0x95, 0x6f, 0x72, 0x00, 0xe1,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x15, 0x00, 0x07, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0xf3, 0xc0, 0x61, 0x15, 0x2d, 0x00, 0xf2, 0x00, 0x14, 0x01, 0x20,
- 0x02, 0x93, 0x02, 0xbf, 0x02, 0x07, 0x03, 0x48, 0x03, 0x83, 0x03, 0xcd,
- 0x03, 0x00, 0x00, 0xe3, 0x03, 0x10, 0x04, 0x33, 0x04, 0x43, 0x04, 0x7c,
- 0x04, 0xc9, 0x04, 0xe0, 0x04, 0x25, 0x05, 0xdd, 0x05, 0x88, 0x06, 0xe4,
- 0x64, 0x00, 0x6c, 0x15, 0x6e, 0x37, 0x70, 0x6e, 0xe2, 0x64, 0x00, 0x76,
- 0x07, 0x40, 0x3a, 0x72, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x65, 0x6e,
- 0x74, 0x75, 0x72, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x15, 0xe1, 0x67,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x69, 0x61, 0x6e,
- 0x63, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x05, 0x40, 0x09, 0x72, 0x79,
- 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x18, 0x00, 0x06, 0xe2, 0x63,
- 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x70,
- 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x10, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40,
- 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x38, 0xe2, 0x65,
- 0x00, 0x6f, 0x16, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x64, 0x00, 0x73, 0x02, 0x00, 0xad, 0x40, 0x09, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x26, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x67, 0x00, 0x68, 0x08,
- 0x40, 0x00, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x76, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x07, 0x6f,
- 0x72, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x3c, 0x68, 0x61, 0x69,
- 0x8c, 0x6f, 0x9f, 0x72, 0xf0, 0x75, 0xf7, 0x00, 0x00, 0xe3, 0x6c, 0x00,
- 0x72, 0x1f, 0x73, 0x2f, 0xe2, 0x63, 0x00, 0x6c, 0x18, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x09, 0x61, 0x67, 0x65,
- 0x00, 0x00, 0x0b, 0x41, 0x21, 0x74, 0x00, 0xe2, 0x67, 0x00, 0x6c, 0x0a,
- 0x40, 0x07, 0x65, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x06,
- 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x69,
- 0x06, 0x40, 0x06, 0x6e, 0x63, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x66,
- 0x00, 0x76, 0x02, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x6d,
- 0x00, 0x6e, 0x0d, 0x75, 0x45, 0x40, 0x00, 0x6d, 0x75, 0x6e, 0x69, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x14, 0x73,
- 0x1a, 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x70, 0x05, 0x40, 0x0b, 0x76,
- 0x65, 0x00, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x55, 0x75,
- 0x63, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x75, 0x00,
- 0xe2, 0x63, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x0b, 0x40, 0x47, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x65, 0x61, 0x6e,
- 0x74, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x1f, 0x6f,
- 0x54, 0xe3, 0x61, 0x00, 0x65, 0x0c, 0x6d, 0x10, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x01, 0x76, 0x00, 0x00, 0x40, 0x09, 0x64, 0x00,
- 0x40, 0x09, 0x65, 0x61, 0x6e, 0x6f, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x64,
- 0x17, 0x72, 0x19, 0xe1, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x07,
- 0x73, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x7a, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6e, 0x0b, 0x03, 0x94,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x16, 0x79,
- 0x1e, 0x03, 0xca, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40,
- 0x07, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe3, 0x65, 0x00,
- 0x69, 0x15, 0x6f, 0x39, 0xe1, 0x61, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x07,
- 0x40, 0x07, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x08, 0x75, 0x72, 0x65,
- 0x00, 0xe3, 0x6c, 0x00, 0x72, 0x04, 0x74, 0x08, 0x40, 0x0b, 0x65, 0x00,
- 0x40, 0x82, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x72, 0x74, 0x75, 0x6e, 0x65, 0x00, 0xe3, 0x69, 0x00,
- 0x6f, 0x07, 0x75, 0x20, 0x40, 0x09, 0x76, 0x69, 0x6e, 0x67, 0x00, 0xe1,
- 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x02, 0x83, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40,
- 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x3a,
- 0x00, 0x3b, 0xe4, 0x61, 0x00, 0x65, 0x0d, 0x69, 0x1c, 0x6d, 0x2c, 0xe2,
- 0x6e, 0x00, 0x70, 0x06, 0x40, 0x3a, 0x64, 0x6c, 0x65, 0x00, 0x00, 0x06,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x3c, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x08, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x61, 0x73, 0x68,
- 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x09, 0x40, 0x0b, 0x65, 0x6e, 0x74, 0x69,
- 0x66, 0x79, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x17, 0xe1, 0x6f, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x72,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x5b, 0x40, 0x06, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x65, 0x00, 0x6d, 0x02, 0x00, 0x3a, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x12, 0xe3, 0x62, 0x00, 0x69, 0x05, 0x79,
- 0x09, 0x40, 0xad, 0x65, 0x6c, 0x00, 0x40, 0x00, 0x64, 0x00, 0x00, 0x3c,
- 0xe2, 0x61, 0x00, 0x64, 0x0f, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x3c, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x16, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x07,
- 0x65, 0x6e, 0x74, 0x00, 0x40, 0x59, 0x63, 0x68, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x05, 0x40, 0x0b, 0x6d, 0x65, 0x00, 0x40, 0x09, 0x6d, 0x65, 0x72,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x0f, 0xe1, 0x6d, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07,
- 0xe1, 0x6e, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x11, 0x79, 0x16, 0xe1, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x63, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x6c,
- 0x00, 0x72, 0x1a, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x79, 0x10, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x35, 0x40, 0x07, 0x65,
- 0x6e, 0x74, 0x00, 0x00, 0x59, 0xe2, 0x69, 0x00, 0x6f, 0x0f, 0xe2, 0x6e,
- 0x00, 0x73, 0x04, 0x40, 0x59, 0x74, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x07, 0x40, 0x3a, 0x75,
- 0x6e, 0x63, 0x65, 0x00, 0x40, 0x06, 0x6e, 0x63, 0x69, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x82, 0xe2, 0x65, 0x00, 0x75, 0x3b, 0xe2, 0x61, 0x00, 0x70, 0x0f,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03, 0xcb, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x05, 0x40, 0x55, 0x72, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x0b, 0x40,
- 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x82, 0x6c, 0x65, 0x00, 0xe9,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x0a, 0x68, 0x0e, 0x69, 0x20,
- 0x70, 0x4e, 0x74, 0x85, 0x75, 0xa1, 0x03, 0xcc, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x90, 0x6c, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x0b,
- 0x00, 0x00, 0xe3, 0x6c, 0x00, 0x6f, 0x0e, 0x76, 0x23, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x00, 0x69, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x23, 0xe3, 0x61, 0x00, 0x6c, 0x04, 0x6e, 0x13,
- 0x40, 0x3c, 0x6b, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x03, 0xcd, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x02,
- 0x00, 0x3c, 0x00, 0x00, 0xe1, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x13,
- 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x01,
- 0x13, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x70, 0x00, 0x40,
- 0x09, 0x73, 0x00, 0xe9, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x1d,
- 0x69, 0x23, 0x6c, 0x38, 0x6f, 0x3f, 0x72, 0x44, 0x79, 0x8d, 0x03, 0xce,
- 0x40, 0x00, 0x73, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06,
- 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03,
- 0xcf, 0x00, 0x3b, 0x40, 0x00, 0x72, 0x27, 0x73, 0x00, 0xe3, 0x6c, 0x00,
- 0x6d, 0x04, 0x6e, 0x08, 0x40, 0x00, 0x79, 0x00, 0x40, 0x0b, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65, 0x74, 0x6f, 0x65,
- 0x00, 0x40, 0x00, 0x6f, 0x6b, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x10, 0x69,
- 0x29, 0x75, 0x2e, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x73, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x10,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0xfd, 0x40, 0x07,
- 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40, 0x09, 0x61, 0x6c,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02,
- 0x00, 0x47, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02,
- 0x01, 0x0c, 0x40, 0x3c, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x2b, 0xe1,
- 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x12, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03, 0xd0, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x00, 0x6f, 0x64, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x09, 0x6f, 0x25, 0x74, 0x62, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xeb, 0x00, 0x2f, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x57, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x73,
- 0x24, 0x74, 0x31, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x03, 0xb4, 0x40, 0x07, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x74, 0x0b, 0x03, 0xd1, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37,
- 0x00, 0x07, 0x40, 0x06, 0x75, 0x72, 0x65, 0x00, 0xe1, 0x7a, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09,
- 0x40, 0x06, 0x61, 0x73, 0x74, 0x00, 0x40, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b,
- 0x00, 0x4d, 0x00, 0xa8, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27,
- 0x02, 0x34, 0x02, 0x3a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x02, 0x70,
- 0x03, 0xc2, 0x03, 0xb3, 0x07, 0x84, 0x08, 0x00, 0x00, 0xc7, 0x08, 0xa6,
- 0x0a, 0xec, 0x0a, 0xa8, 0x0c, 0xd9, 0x0d, 0x11, 0x0e, 0x1c, 0x0e, 0x00,
- 0x00, 0x21, 0x0e, 0x03, 0xd2, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x00, 0xb2, 0xe5,
- 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x69, 0x14, 0x73, 0x4a, 0x00, 0xaa,
- 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x41, 0x63, 0x64,
- 0x00, 0x41, 0x63, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x15, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01,
- 0x52, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0x4a, 0x00, 0x06,
- 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0xe3, 0x63, 0x00, 0x68, 0x07, 0x6b,
- 0x0b, 0x40, 0x06, 0x61, 0x73, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0e, 0x01, 0x4b, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x6e, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x3b, 0x40, 0x06,
- 0x69, 0x72, 0x64, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x64,
- 0x11, 0x00, 0x65, 0x1f, 0x00, 0x69, 0xba, 0x00, 0x75, 0xfb, 0x00, 0x03,
- 0xd3, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x08, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x6c, 0x02, 0x6d,
- 0x1c, 0x72, 0x1e, 0x73, 0x84, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x6c, 0x0b, 0x03, 0xd4, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe2,
- 0x61, 0x00, 0x6e, 0x20, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0d,
- 0x6f, 0x12, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0xd5, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x34, 0x00, 0x44, 0xe3, 0x73, 0x00,
- 0x74, 0x12, 0x7a, 0x16, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x3b, 0x00, 0x07, 0xe3, 0x63, 0x00, 0x66, 0x05, 0x73, 0x2a,
- 0x40, 0x06, 0x75, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1e, 0xe3, 0x61,
- 0x00, 0x63, 0x06, 0x65, 0x0e, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40,
- 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x37, 0x00, 0x07, 0x03, 0xd6, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6c,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x23, 0x6f, 0x25, 0x75, 0x27, 0xe2, 0x72,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x11,
- 0x03, 0x4c, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x01, 0x52, 0x00, 0x00, 0x40, 0x09, 0x72, 0x00, 0x00, 0x09, 0x00,
- 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x67, 0x00, 0x75, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x06, 0x6c, 0x00, 0x40, 0x07, 0x61, 0x69, 0x72, 0x00,
- 0xe5, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x07, 0x72, 0x09, 0x73, 0x0d, 0x00,
- 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0x00, 0x47, 0x40, 0x06, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x10, 0x75, 0x16,
- 0x03, 0xd7, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x54,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x7a, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe6,
- 0x61, 0x00, 0x64, 0x0d, 0x65, 0x36, 0x6c, 0x86, 0x74, 0xc2, 0x79, 0xcd,
- 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x65, 0x73,
- 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x09, 0x69, 0x0d, 0x79, 0x1c,
- 0x03, 0xd8, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0xec, 0x72,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73,
- 0x73, 0x00, 0x00, 0x07, 0x01, 0x92, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x68,
- 0x1e, 0x73, 0x24, 0x00, 0x09, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x00, 0x06, 0x40, 0x06, 0x69,
- 0x6c, 0x6c, 0x00, 0xe2, 0x6b, 0x00, 0x74, 0x05, 0x40, 0x07, 0x69, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x00, 0x4c, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37,
- 0x00, 0x07, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x75, 0x15, 0x79, 0x24, 0x00,
- 0x09, 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0xd9, 0xe1, 0x73, 0x00, 0xe2,
- 0x63, 0x00, 0x6b, 0x05, 0x40, 0x00, 0x61, 0x6e, 0x00, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x06, 0x40, 0x5e, 0x6f, 0x64, 0x64, 0x6c,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x03, 0x8c, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x62, 0x64, 0x65, 0x6e, 0x75, 0x6d, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x6d, 0x47, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x1f, 0x75, 0x32, 0x00, 0x09,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x5d, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0x40, 0x06, 0x79, 0x00, 0xf9, 0x61, 0x00, 0x00,
- 0x65, 0x66, 0x00, 0x67, 0xc5, 0x00, 0x69, 0xf2, 0x00, 0x6b, 0x23, 0x01,
- 0x6f, 0x4b, 0x01, 0x73, 0x4f, 0x03, 0x74, 0xa5, 0x03, 0x75, 0xbe, 0x03,
- 0xe3, 0x72, 0x00, 0x73, 0x37, 0x75, 0x59, 0xe1, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x73, 0x24, 0x79, 0x26, 0x00, 0x07,
- 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x00, 0x00,
- 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x06, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0x40, 0x00, 0x72, 0x61, 0x6c, 0x00, 0xe2, 0x74, 0x00, 0x79, 0x26, 0xe2,
- 0x61, 0x00, 0x69, 0x1c, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x12,
- 0xe2, 0x6c, 0x00, 0x73, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x41, 0x98, 0x7a, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x0f, 0x6d, 0x17, 0x00, 0xb1,
- 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x67, 0x00, 0x40, 0x08, 0x78,
- 0x00, 0x40, 0x06, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x04, 0x72, 0x21,
- 0x40, 0x55, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x13, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0x08, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40,
- 0x09, 0x69, 0x64, 0x00, 0x40, 0x09, 0x73, 0x65, 0x00, 0x40, 0x06, 0x65,
- 0x6c, 0x00, 0xe4, 0x65, 0x00, 0x6b, 0x04, 0x73, 0x09, 0x74, 0x12, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06,
- 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x2c, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x13, 0x73, 0x18,
- 0x00, 0x09, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x55,
- 0x40, 0x06, 0x68, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00,
- 0x40, 0x06, 0x68, 0x6f, 0x6f, 0x64, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x64, 0x55, 0x00, 0x67, 0x67, 0x00, 0x6c, 0xab, 0x00, 0x6d,
- 0xdf, 0x00, 0x6e, 0x03, 0x01, 0x70, 0x0e, 0x01, 0x72, 0x54, 0x01, 0x73,
- 0x5a, 0x01, 0x74, 0x76, 0x01, 0x75, 0xc9, 0x01, 0x78, 0xd6, 0x01, 0x00,
- 0x07, 0xe4, 0x68, 0x00, 0x6c, 0x16, 0x6f, 0x23, 0x75, 0x44, 0xe1, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06,
- 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x6f,
- 0x02, 0x00, 0x1a, 0x40, 0x00, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0b, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x40, 0x06, 0x74, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x72, 0x16, 0xe1,
- 0x6d, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x05, 0x79, 0x0a, 0x40, 0x09, 0x73,
- 0x74, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00,
- 0xe2, 0x6d, 0x00, 0x70, 0x15, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x1e, 0xe2, 0x6e, 0x00, 0x74, 0x07,
- 0x40, 0x09, 0x67, 0x75, 0x61, 0x6c, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x73, 0x06, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x06, 0x73,
- 0x74, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1b, 0xe1,
- 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x6c, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x75, 0x63, 0x6c, 0x65,
- 0x6f, 0x73, 0x69, 0x73, 0x00, 0xe3, 0x68, 0x00, 0x6c, 0x07, 0x6f, 0x0d,
- 0x40, 0x00, 0x6f, 0x6e, 0x69, 0x63, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x28, 0xe2, 0x73, 0x00,
- 0x7a, 0x0e, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00,
- 0x07, 0x00, 0x06, 0x40, 0x09, 0x61, 0x69, 0x6c, 0x00, 0xe1, 0x79, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x04, 0x40, 0x00, 0x63, 0x00, 0x40, 0x09, 0x65,
- 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x1b, 0xe1, 0x65, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x6e, 0x00,
- 0xe4, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x12, 0x79, 0x25, 0x00, 0x09, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07,
- 0x40, 0x00, 0x6e, 0x73, 0x61, 0x74, 0x75, 0x72, 0x61, 0x74, 0x65, 0x64,
- 0x00, 0x40, 0x09, 0x69, 0x64, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x09,
- 0x6f, 0x19, 0x74, 0x2a, 0x40, 0x07, 0x69, 0x67, 0x6e, 0x65, 0x75, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x75, 0x72, 0x00, 0x40,
- 0x06, 0x6e, 0x6f, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x72, 0x04, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06,
- 0x40, 0x65, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x75, 0x06, 0x40,
- 0x06, 0x69, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x68, 0x05, 0x40, 0x06, 0x67, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02,
- 0x73, 0x06, 0x00, 0x12, 0x40, 0x06, 0x79, 0x00, 0x00, 0x00, 0xe1, 0x6d,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0xe7, 0x00, 0x00,
- 0x63, 0x02, 0x64, 0x10, 0x6e, 0x2a, 0x72, 0xa1, 0x73, 0xbc, 0x74, 0xc0,
- 0x00, 0x93, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3,
- 0x40, 0x07, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00,
- 0x09, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x6c,
- 0x08, 0x73, 0x31, 0x77, 0x66, 0x00, 0x47, 0x40, 0x09, 0x65, 0x61, 0x6d,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x73, 0x73, 0x00, 0xe2,
- 0x67, 0x00, 0x74, 0x18, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x68, 0x06, 0x74,
- 0x1e, 0x40, 0x06, 0x61, 0x70, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0f,
- 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0xeb, 0x00, 0x07, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x05,
- 0x40, 0x09, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x75, 0x63, 0x6b, 0x00, 0x40,
- 0x09, 0x61, 0x6c, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x69, 0x07,
- 0x6c, 0x0c, 0x03, 0x96, 0x40, 0x08, 0x65, 0x6e, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x3a, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x13, 0x70, 0x27, 0x00,
- 0xfa, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x79, 0x06, 0x00, 0x09,
- 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x0b, 0xe2,
- 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00,
- 0x68, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x74, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xfc, 0x61, 0x00,
- 0x00, 0x62, 0x6b, 0x00, 0x64, 0x85, 0x00, 0x65, 0x96, 0x00, 0x67, 0xb2,
- 0x00, 0x69, 0xb7, 0x00, 0x6e, 0xbe, 0x00, 0x6f, 0xca, 0x00, 0x70, 0xfd,
- 0x00, 0x72, 0x43, 0x01, 0x73, 0x48, 0x01, 0x74, 0x4d, 0x01, 0xe5, 0x69,
- 0x00, 0x6c, 0x05, 0x73, 0x52, 0x74, 0x56, 0x79, 0x5e, 0x40, 0x06, 0x6e,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x00, 0x56, 0x00,
- 0x07, 0xe3, 0x73, 0x00, 0x74, 0x1a, 0x7a, 0x26, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x05, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0xdb, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x41, 0x52, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x01, 0x98, 0x00, 0x09, 0x40, 0x09, 0x73, 0x00, 0x40,
- 0x06, 0x6f, 0x72, 0x69, 0x75, 0x6d, 0x00, 0x00, 0x06, 0xe1, 0x69, 0x00,
- 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x00, 0x3e,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x56, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07, 0x6f,
- 0x09, 0x73, 0x0f, 0x00, 0x09, 0x40, 0x00, 0x73, 0x68, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x76, 0x65, 0x72, 0x00, 0x00, 0x07, 0x40, 0x09, 0x75, 0x65,
- 0x00, 0x40, 0x00, 0x62, 0x75, 0x6e, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x03, 0xc0, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x63, 0x00, 0x6e,
- 0x05, 0x73, 0x1c, 0x40, 0x07, 0x63, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x68, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x10, 0x6f, 0x20, 0x73,
- 0x36, 0x00, 0xed, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0xe2, 0x65, 0x00, 0x67, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40,
- 0x00, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x6f,
- 0x77, 0x00, 0x40, 0x09, 0x65, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x67, 0x1f,
- 0x69, 0x3d, 0x75, 0x5e, 0xe2, 0x6c, 0x00, 0x72, 0x0c, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x86, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x00, 0x00,
- 0x62, 0x02, 0x00, 0x47, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x0f, 0xe3, 0x00,
- 0x00, 0x27, 0x02, 0x65, 0x06, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x00,
- 0x09, 0x40, 0x09, 0x72, 0x00, 0xe3, 0x63, 0x00, 0x66, 0x06, 0x73, 0x16,
- 0x40, 0x09, 0x69, 0x61, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40,
- 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x02, 0x3e, 0x40, 0x5e,
- 0x65, 0x00, 0x40, 0x06, 0x61, 0x72, 0x79, 0x00, 0xe6, 0x61, 0x00, 0x65,
- 0x05, 0x68, 0x09, 0x71, 0x0b, 0x73, 0x26, 0x74, 0x37, 0x40, 0x09, 0x69,
- 0x63, 0x00, 0x40, 0x5b, 0x79, 0x00, 0x00, 0x3a, 0xe1, 0x75, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x79, 0x08, 0x00, 0x09, 0x40, 0x06, 0x61, 0x63,
- 0x6b, 0x00, 0x00, 0x60, 0x00, 0x12, 0xf7, 0x00, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x68, 0x15, 0x00, 0x69, 0x74, 0x00, 0x6c, 0xf2, 0x00, 0x6f, 0x09,
- 0x01, 0x74, 0x92, 0x01, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x6c,
- 0x06, 0x74, 0x08, 0x03, 0xda, 0x40, 0x00, 0x73, 0x00, 0x00, 0x06, 0x00,
- 0x06, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x73, 0x54, 0x00, 0x07,
- 0x40, 0x59, 0x61, 0x6c, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe5, 0x00, 0x00,
- 0x62, 0x02, 0x66, 0x09, 0x68, 0x20, 0x6c, 0x26, 0x03, 0x7c, 0x40, 0x06,
- 0x6f, 0x61, 0x72, 0x64, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0xcf, 0x72, 0x00, 0x41,
- 0x68, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x05, 0x69, 0x0a, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x00,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00,
- 0xe4, 0x66, 0x00, 0x6c, 0x02, 0x6f, 0x0e, 0x76, 0x3b, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x08, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1,
- 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x0b, 0x03,
- 0xdb, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x28, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6f, 0x1a, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x03, 0x4a, 0x00, 0x37, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x09, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x07, 0x40, 0x09,
- 0x72, 0x6f, 0x73, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x63, 0x11,
- 0x69, 0x33, 0x6d, 0x4a, 0x77, 0x6b, 0x00, 0x93, 0xe2, 0x69, 0x00, 0x6f,
- 0x05, 0x40, 0x82, 0x6b, 0x65, 0x00, 0x40, 0x09, 0x61, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x79, 0x0b, 0xe2, 0x64, 0x00, 0x72, 0x04, 0x40, 0x09, 0x65,
- 0x00, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x5e, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe2, 0x73, 0x00,
- 0x7a, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe3, 0x61, 0x00, 0x65,
- 0x04, 0x6f, 0x08, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x61, 0x79, 0x00, 0xe2, 0x6c,
- 0x00, 0x6f, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xf5, 0x65, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x72, 0x66, 0x00, 0x73, 0x95, 0x00, 0x74, 0xdc, 0x00, 0x00, 0x09,
- 0xe2, 0x64, 0x00, 0x74, 0x02, 0x00, 0x93, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x3e, 0x69, 0x4f, 0x03, 0xdc, 0xe2, 0x62, 0x00, 0x69, 0x05, 0x40,
- 0x00, 0x6c, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02,
- 0x6f, 0x14, 0x73, 0x19, 0x74, 0x1f, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x06, 0x69, 0x64, 0x65,
- 0x00, 0x40, 0x06, 0x6f, 0x70, 0x00, 0xe3, 0x62, 0x00, 0x64, 0x06, 0x72,
- 0x08, 0x40, 0x09, 0x61, 0x6e, 0x6b, 0x00, 0x00, 0x37, 0x00, 0x09, 0x40,
- 0x06, 0x6e, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x66, 0x0b, 0x69, 0x1e, 0x01, 0x27, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x29, 0x73, 0x30, 0x79, 0x3c,
- 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x04, 0x00, 0x7e, 0x00, 0x07, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x08, 0x6b, 0x61, 0x00, 0x00, 0x82,
- 0x00, 0x96, 0xe2, 0x68, 0x00, 0x6f, 0x3c, 0xe7, 0x00, 0x00, 0x66, 0x02,
- 0x69, 0x07, 0x70, 0x0e, 0x73, 0x15, 0x77, 0x17, 0x79, 0x2b, 0x00, 0xec,
- 0x40, 0x09, 0x75, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x69, 0x65, 0x63, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x09, 0x68, 0x00, 0x40, 0x00, 0x65,
- 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x96, 0x40, 0x07, 0x6e, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x06, 0x69, 0x1b, 0x40, 0x06, 0x62, 0x6c, 0x65, 0x00,
- 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6d, 0x04, 0x72, 0x0a, 0x03, 0xdd, 0x00,
- 0x37, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x75, 0xe2, 0x65, 0x00,
- 0x6e, 0x0d, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40, 0x06, 0x6f,
- 0x65, 0x72, 0x00, 0x40, 0x3b, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x69, 0x65, 0x00, 0x40,
- 0x07, 0x7a, 0x61, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x67, 0x06, 0x68, 0x08, 0x00, 0x00, 0x40, 0x00, 0x67, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x73, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x63, 0x18, 0x35, 0x00,
- 0x37, 0x00, 0x81, 0x00, 0xfe, 0x00, 0x17, 0x01, 0x39, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x82, 0x01, 0x8c, 0x01, 0x92, 0x01, 0x2d, 0x04, 0x7c, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x04, 0x62, 0x05, 0x0f, 0x07,
- 0xd2, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x07,
- 0x00, 0x06, 0xe5, 0x68, 0x00, 0x69, 0x02, 0x6b, 0x19, 0x6f, 0x36, 0x75,
- 0x3b, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x6f, 0x75,
- 0x73, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x79, 0x14, 0x00, 0x47, 0xe1,
- 0x61, 0x00, 0xe1, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x01, 0x4b, 0x00, 0x07, 0x00, 0x60, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x64, 0x02, 0x66, 0x2c, 0x67,
- 0x3b, 0x70, 0x42, 0x72, 0x48, 0x73, 0x4e, 0x00, 0x07, 0xe3, 0x69, 0x00,
- 0x6c, 0x0f, 0x79, 0x21, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x68, 0x02, 0x00, 0x82, 0x40, 0x00, 0x65, 0x61, 0x64, 0x65, 0x64,
- 0x00, 0x01, 0x36, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x70, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0x00, 0x09, 0x40, 0x06, 0x75, 0x61, 0x72, 0x64,
- 0x00, 0x40, 0x08, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6d,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x04,
- 0x40, 0x09, 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x6e, 0x00,
- 0x73, 0x07, 0x7a, 0x0c, 0x40, 0x07, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40,
- 0x00, 0x6c, 0x69, 0x00, 0x40, 0x09, 0x7a, 0x69, 0x6e, 0x00, 0xe2, 0x66,
- 0x00, 0x74, 0x19, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x06, 0x00, 0x47,
- 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x3f, 0x00, 0x07, 0x40, 0x06, 0x69, 0x00, 0xe5, 0x00, 0x00, 0x66,
- 0x02, 0x67, 0x07, 0x73, 0x32, 0x77, 0x38, 0x00, 0x06, 0x40, 0x09, 0x75,
- 0x6c, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x09, 0x6c, 0x1c, 0x79, 0x20, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe3,
- 0x65, 0x00, 0x67, 0x05, 0x73, 0x07, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x40, 0x09, 0x65, 0x00, 0x00, 0x96, 0x40, 0x09, 0x68,
- 0x6f, 0x74, 0x00, 0x40, 0x09, 0x75, 0x6d, 0x70, 0x00, 0x40, 0x00, 0x61,
- 0x68, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x00, 0x40, 0x09, 0x6c, 0x75, 0x6b,
- 0x00, 0xf7, 0x61, 0x00, 0x00, 0x62, 0x14, 0x00, 0x63, 0x1b, 0x00, 0x65,
- 0x24, 0x00, 0x69, 0x3c, 0x00, 0x6c, 0x4f, 0x00, 0x74, 0x8b, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x65, 0x72, 0x72,
- 0x79, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x02, 0x00, 0x59, 0x00, 0x93, 0xe3,
- 0x00, 0x00, 0x73, 0x02, 0x74, 0x0b, 0x00, 0x09, 0x40, 0x09, 0x6b, 0x69,
- 0x6e, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x09, 0x65, 0x65, 0x72, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x0e, 0x69, 0x19, 0x00, 0x3a, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x00, 0x09, 0xe2, 0x67, 0x00, 0x6f, 0x11, 0xe1, 0x61, 0x00,
- 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40, 0x07, 0x61, 0x77, 0x6e,
- 0x79, 0x00, 0x40, 0xb1, 0x6e, 0x00, 0xf1, 0x69, 0x00, 0x00, 0xfd, 0x00,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x64, 0x34, 0x00, 0x66, 0x53, 0x00, 0x6c,
- 0x8a, 0x00, 0x6d, 0xc5, 0x00, 0x6e, 0xdc, 0x00, 0x70, 0xe6, 0x00, 0x72,
- 0x69, 0x01, 0x73, 0x71, 0x01, 0x74, 0x83, 0x01, 0x76, 0xab, 0x01, 0x79,
- 0xc8, 0x01, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x05, 0x75, 0x0d, 0x40,
- 0x00, 0x73, 0x74, 0x00, 0x40, 0x00, 0x6c, 0x6f, 0x72, 0x65, 0x64, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6d, 0x00,
- 0x73, 0x0b, 0x40, 0x00, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
- 0x00, 0x40, 0x00, 0x63, 0x69, 0x70, 0x6c, 0x69, 0x6e, 0x61, 0x72, 0x79,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x2d, 0xe3, 0x63, 0x00, 0x6d, 0x07, 0x72,
- 0x0d, 0x40, 0x00, 0x65, 0x74, 0x65, 0x64, 0x00, 0x40, 0x00, 0x69, 0x6c,
- 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x72, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x13, 0x69, 0x19, 0xe2, 0x74, 0x00, 0x79, 0x07, 0x40, 0x3b, 0x65, 0x72,
- 0x61, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x72, 0x65, 0x64, 0x00, 0x40, 0x00,
- 0x76, 0x65, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06,
- 0x40, 0x07, 0x64, 0x69, 0x61, 0x00, 0x40, 0x06, 0x6c, 0x6c, 0x69, 0x6f,
- 0x6e, 0x61, 0x69, 0x72, 0x65, 0x00, 0x40, 0x06, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x61, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x6c, 0x06, 0x72, 0x55, 0x75,
- 0x72, 0x40, 0x00, 0x72, 0x74, 0x79, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x06,
- 0x69, 0x18, 0x79, 0x44, 0x40, 0x07, 0x79, 0x65, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x78, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x65, 0x23, 0xe2, 0x61, 0x00,
- 0x69, 0x19, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09, 0x64, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x03, 0xde, 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00, 0x72, 0x70, 0x6f,
- 0x73, 0x65, 0x00, 0x40, 0x00, 0x61, 0x63, 0x69, 0x61, 0x6c, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x67, 0x65, 0x00,
- 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x12, 0xe1, 0x73,
- 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3c, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x08, 0x69, 0x0e, 0x40, 0x00, 0x72, 0x69, 0x61, 0x74, 0x65, 0x00,
- 0x40, 0x06, 0x72, 0x73, 0x65, 0x00, 0x40, 0x09, 0x74, 0x61, 0x6d, 0x69,
- 0x6e, 0x00, 0x40, 0x00, 0x65, 0x61, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x62,
- 0x02, 0x6d, 0x1a, 0x70, 0x42, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x04, 0x00, 0xa5, 0x00, 0x07,
- 0x40, 0x07, 0x79, 0x70, 0x65, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0c,
- 0x79, 0x1f, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09,
- 0x00, 0x07, 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07,
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x42, 0x00, 0x06, 0x40,
- 0x07, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x64, 0x18, 0x67, 0x1e,
- 0x69, 0x20, 0x00, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6b, 0x07, 0x00, 0x0b, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x06, 0x69,
- 0x6e, 0x00, 0x43, 0x6c, 0x61, 0x6e, 0x65, 0x00, 0x00, 0x3a, 0xe3, 0x63,
- 0x00, 0x66, 0x18, 0x74, 0x2f, 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56,
- 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x3b, 0x40, 0x55, 0x69, 0x6f, 0x6e, 0x00, 0xe6, 0x61,
- 0x00, 0x64, 0x0f, 0x69, 0x2e, 0x6b, 0x33, 0x6d, 0x4d, 0x72, 0x6c, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06, 0x73,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6f, 0x0d, 0x00, 0xc3, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x09, 0x73, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x00, 0x6e,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x09, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x96, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x6f, 0x0b, 0x01, 0x93, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x61, 0x69, 0x6e, 0x00, 0xf8, 0x63, 0x00, 0x00, 0x65, 0x5c, 0x00,
- 0x68, 0x6e, 0x00, 0x69, 0x88, 0x00, 0x6b, 0xe0, 0x00, 0x6c, 0x33, 0x01,
- 0x73, 0x38, 0x01, 0x74, 0x47, 0x01, 0xe3, 0x61, 0x00, 0x6c, 0x0e, 0x75,
- 0x32, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x1d, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x6d, 0x09, 0x00, 0x82, 0x40, 0x00, 0x6f, 0x75, 0x6e, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x17, 0xe2,
- 0x72, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x75, 0x72, 0x65, 0x00, 0x40, 0x00,
- 0x73, 0x00, 0xe3, 0x00, 0x00, 0x74, 0x02, 0x75, 0x07, 0x03, 0xdf, 0x40,
- 0x09, 0x74, 0x65, 0x00, 0x40, 0x09, 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x69,
- 0x02, 0x72, 0x09, 0x79, 0x0f, 0x00, 0xe7, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x95, 0x6f, 0x6f, 0x6d, 0x00, 0x00, 0x96, 0xe2, 0x63,
- 0x00, 0x6e, 0x4f, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x15, 0x6f, 0x28,
- 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04,
- 0x00, 0x86, 0x00, 0x09, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x56, 0x40, 0x07,
- 0x68, 0x69, 0x70, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40,
- 0x00, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0x40, 0x12,
- 0x67, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x69, 0x25, 0x6d, 0x32, 0x6f,
- 0x39, 0x72, 0x3d, 0x79, 0x42, 0x00, 0x07, 0xe3, 0x67, 0x00, 0x6c, 0x02,
- 0x74, 0x0a, 0x00, 0x09, 0x40, 0x09, 0x6c, 0x75, 0x6e, 0x67, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x07, 0x00, 0x09, 0x40, 0x09, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x65, 0x6c, 0x6f,
- 0x6e, 0x00, 0x40, 0x14, 0x78, 0x00, 0x40, 0x09, 0x61, 0x74, 0x00, 0x00,
- 0xef, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79,
- 0x06, 0x00, 0x47, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x60, 0xe7, 0x00, 0x00,
- 0x27, 0x02, 0x61, 0x07, 0x65, 0x24, 0x69, 0x28, 0x6e, 0x37, 0x79, 0x3c,
- 0x01, 0x71, 0x40, 0x00, 0x76, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x0e,
- 0x72, 0x12, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0xb2,
- 0x40, 0xb1, 0x6f, 0x00, 0x40, 0x09, 0x67, 0x00, 0x40, 0x07, 0x64, 0x00,
- 0x40, 0xec, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x27, 0x74, 0x00,
- 0x00, 0x96, 0xe5, 0x61, 0x00, 0x65, 0x3a, 0x69, 0x47, 0x74, 0x77, 0x75,
- 0xa6, 0xe4, 0x62, 0x00, 0x67, 0x10, 0x6e, 0x15, 0x74, 0x19, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x40, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x03, 0xe0, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x18, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x05, 0x79, 0x0a,
- 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x00, 0xa1,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x17, 0x00, 0x09, 0xe1, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x93, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x6f, 0x70, 0x73, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x09, 0x6d, 0x75, 0x75, 0x00, 0xe2,
- 0x61, 0x00, 0x7a, 0x04, 0x40, 0x00, 0x6b, 0x00, 0xe3, 0x69, 0x00, 0x6c,
- 0x05, 0x79, 0x09, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x5e, 0x65, 0x00,
- 0x00, 0x5d, 0xfa, 0x00, 0x00, 0x00, 0x53, 0x02, 0x00, 0x63, 0x09, 0x00,
- 0x65, 0x21, 0x00, 0x6e, 0x29, 0x00, 0x6f, 0x2d, 0x00, 0x72, 0x62, 0x00,
- 0x73, 0x80, 0x00, 0x74, 0xe1, 0x00, 0x78, 0x23, 0x01, 0x00, 0x00, 0x40,
- 0x00, 0x69, 0x6d, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x69,
- 0x73, 0x00, 0x40, 0x09, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x70, 0x19, 0xe1,
- 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x6d, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe4,
- 0x69, 0x00, 0x6d, 0x05, 0x72, 0x0c, 0x74, 0x10, 0x40, 0x06, 0x61, 0x64,
- 0x00, 0x40, 0x09, 0x69, 0x64, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x68, 0x00,
- 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x74, 0x07,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x66, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x20,
- 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x16, 0xe1, 0x6f, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe3, 0x63, 0x00, 0x66,
- 0x12, 0x71, 0x22, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x06,
- 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x09, 0x41, 0x52, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x02,
- 0x97, 0x40, 0x07, 0x75, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00,
- 0x69, 0x02, 0x6f, 0x10, 0x73, 0x34, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14,
- 0xe3, 0x63, 0x00, 0x73, 0x05, 0x7a, 0x09, 0x40, 0x00, 0x61, 0x6c, 0x00,
- 0x40, 0x06, 0x74, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x00, 0x06, 0x00, 0x00,
- 0x40, 0x00, 0x6f, 0x6d, 0x61, 0x74, 0x6f, 0x73, 0x69, 0x73, 0x00, 0xf7,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0xae, 0x04, 0x69, 0x77, 0x0d,
- 0x6f, 0xed, 0x10, 0x75, 0xfd, 0x23, 0x79, 0x00, 0x27, 0x03, 0xe1, 0xc0,
- 0x61, 0x19, 0x35, 0x00, 0x39, 0x00, 0x54, 0x00, 0x74, 0x00, 0x79, 0x00,
- 0x7b, 0x00, 0x7f, 0x00, 0xa1, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xd3, 0x00,
- 0x00, 0x00, 0xe6, 0x00, 0x45, 0x01, 0x00, 0x00, 0x72, 0x01, 0x00, 0x00,
- 0xcb, 0x01, 0x86, 0x02, 0xdf, 0x02, 0xe0, 0x03, 0x47, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x9e, 0x04, 0x40, 0x08, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x6f, 0x10, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x62, 0x00, 0xe3,
- 0x65, 0x00, 0x68, 0x06, 0x72, 0x0a, 0x40, 0x06, 0x6c, 0x6c, 0x65, 0x00,
- 0x40, 0x06, 0x6f, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x06, 0x69, 0x72, 0x00,
- 0x00, 0x00, 0x40, 0xf3, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x77,
- 0x15, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x61, 0x72, 0x65, 0x00, 0x00, 0x00, 0xe4, 0x61, 0x00, 0x66, 0x04, 0x6c,
- 0x06, 0x76, 0x14, 0x40, 0x06, 0x64, 0x00, 0x00, 0x09, 0xe2, 0x00, 0x00,
- 0x62, 0x02, 0x00, 0x47, 0x40, 0x09, 0x72, 0x75, 0x73, 0x68, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0xda, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe7, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x64,
- 0x0c, 0x6c, 0x26, 0x70, 0x32, 0x73, 0x39, 0x00, 0x4b, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x37, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x05, 0x40, 0x3b, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x09, 0x6c,
- 0x61, 0x74, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x70, 0x05, 0x40, 0x06, 0x6b,
- 0x65, 0x00, 0x60, 0x09, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, 0xff, 0xff,
- 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe4, 0x00, 0x00,
- 0x62, 0x02, 0x73, 0x07, 0x74, 0x0f, 0x00, 0x00, 0x40, 0x08, 0x6f, 0x74,
- 0x00, 0x40, 0x06, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x65,
- 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x00, 0xe8, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x07, 0x68, 0x09, 0x6b, 0x1f, 0x6c, 0x24, 0x6f, 0x2a,
- 0x70, 0x31, 0x00, 0x06, 0x40, 0x47, 0x6c, 0x6d, 0x00, 0x00, 0x09, 0xe1,
- 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x69,
- 0x6e, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6c, 0x65,
- 0x6f, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x01, 0x72, 0xe5, 0x63, 0x00, 0x6b, 0x6d, 0x72, 0x76, 0x77, 0xa8, 0x79,
- 0xae, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x26, 0x00, 0x09, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x15, 0xe1, 0x73, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x6c,
- 0x00, 0x73, 0x14, 0x74, 0x21, 0xe1, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe2,
- 0x73, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x69, 0x63,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x7a, 0x02, 0x00, 0x06,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x0b, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x1d, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x0f, 0x01, 0xc8, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x77, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0xe2, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x09, 0x68, 0x61, 0x6c, 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00,
- 0x63, 0x21, 0x74, 0x32, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x56, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x3a, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x75, 0x65, 0x00, 0x00, 0x77, 0xe3, 0x69, 0x00, 0x75, 0x0f, 0x79,
- 0x17, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x72, 0x74, 0x69, 0x75, 0x6d, 0x00,
- 0x00, 0x96, 0xe6, 0x61, 0x00, 0x63, 0x04, 0x69, 0x08, 0x6c, 0x74, 0x74,
- 0x76, 0x75, 0x92, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe2,
- 0x6f, 0x00, 0x76, 0x5b, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x68, 0x43, 0x77, 0x49, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x86, 0xe3, 0x73, 0x00, 0x74, 0x1e, 0x7a, 0x22, 0xe2,
- 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0x4a, 0x40,
- 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x00, 0x69, 0x64, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x06, 0x74, 0x79, 0x00, 0x00,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x13, 0x40, 0x59, 0x72, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x96, 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x41, 0x69, 0x4c, 0xe1, 0x6c, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x69,
- 0x06, 0x6e, 0x2b, 0x73, 0x31, 0x02, 0xb1, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x73, 0x00, 0x7a, 0x12, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a,
- 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x27,
- 0x02, 0x00, 0xaa, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x08, 0xe3, 0x67, 0x00, 0x73, 0x20,
- 0x74, 0x4e, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x11, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe1, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x13, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x3b, 0x6e, 0x67,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x63, 0x00, 0x6c, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x75,
- 0x73, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x04, 0x69, 0x0d, 0x76, 0x46, 0x79,
- 0x4a, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09,
- 0x00, 0x06, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74,
- 0x10, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x13,
- 0x00, 0x57, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x08, 0x79, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06,
- 0x40, 0x09, 0x61, 0x79, 0x65, 0x72, 0x00, 0xc0, 0x27, 0x52, 0xa7, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x1a, 0x01, 0x45, 0x01,
- 0x00, 0x00, 0x21, 0x02, 0x8e, 0x02, 0xad, 0x02, 0x00, 0x00, 0x8b, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0xc1, 0x03, 0xc7, 0x03, 0x00, 0x00, 0xe3, 0x03,
- 0xa8, 0x04, 0x00, 0x00, 0xfa, 0x04, 0x50, 0x05, 0x66, 0x05, 0xe3, 0x05,
- 0x0f, 0x07, 0x37, 0x07, 0xbe, 0x08, 0x40, 0x00, 0x65, 0x72, 0x00, 0xe4,
- 0x6e, 0x00, 0x70, 0x0a, 0x72, 0x0c, 0x74, 0x4e, 0x40, 0x09, 0x64, 0x65,
- 0x72, 0x74, 0x68, 0x61, 0x6c, 0x00, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x62,
- 0x02, 0x6e, 0x06, 0x73, 0x0c, 0x03, 0xe3, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x06, 0x40, 0x00,
- 0x6f, 0x72, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x04, 0x40, 0x00, 0x65,
- 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x68, 0x06, 0x6e, 0x08, 0x03,
- 0xe4, 0x40, 0xed, 0x6e, 0x00, 0x00, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x0d,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x65, 0x00, 0x6b,
- 0x30, 0x72, 0x67, 0x74, 0xc1, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x0f, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05,
- 0x40, 0x37, 0x6c, 0x79, 0x00, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe3, 0x61,
- 0x00, 0x6f, 0x05, 0x79, 0x0a, 0x40, 0x3a, 0x74, 0x65, 0x00, 0x40, 0x00,
- 0x75, 0x73, 0x00, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08,
- 0x69, 0x11, 0x6c, 0x16, 0x74, 0x25, 0x00, 0x47, 0x40, 0x08, 0x61, 0x6e,
- 0x64, 0x00, 0x40, 0x09, 0x72, 0x63, 0x68, 0x69, 0x65, 0x66, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x43, 0xdf, 0x63,
- 0x65, 0x00, 0x40, 0x09, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x69, 0x65, 0x00,
- 0xe1, 0x6f, 0x00, 0xe5, 0x6c, 0x00, 0x6d, 0x06, 0x70, 0x1a, 0x73, 0x3a,
- 0x74, 0x47, 0x40, 0x07, 0x6f, 0x67, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0x00, 0x07, 0xe2, 0x68, 0x00, 0x6f, 0x15, 0xe1, 0x69, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x00, 0x00, 0x08, 0x40, 0x09, 0x6c, 0x69, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02,
- 0x66, 0x06, 0x69, 0x0b, 0x6c, 0x12, 0x6e, 0x50, 0x79, 0x55, 0x00, 0x47,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x70, 0x02,
- 0x73, 0x09, 0x77, 0x19, 0x00, 0x82, 0x40, 0x07, 0x6f, 0x69, 0x6e, 0x74,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6d, 0x00, 0x72,
- 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x07, 0x6b, 0x00, 0x40, 0x00, 0x27, 0x74, 0x00, 0x00,
- 0x96, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x6c, 0x34, 0x6f, 0x82, 0x72, 0xbc, 0x00, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0x7d, 0xe2, 0x6f, 0x00, 0x76, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x03, 0xe5, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x73,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x20, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x66, 0x02, 0x00, 0x93, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x12, 0xe2, 0x65, 0x00, 0x6e,
- 0x02, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x3b, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x10, 0xe2, 0x69, 0x00, 0x6c, 0x07,
- 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x77, 0x65, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x11, 0x00, 0x9e, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x07, 0x40, 0x07, 0x74, 0x75,
- 0x64, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x64, 0x00, 0xe2, 0x67, 0x00, 0x74, 0x2b, 0xe1, 0x68, 0x00, 0xe3, 0x00,
- 0x00, 0x62, 0x02, 0x73, 0x1f, 0x00, 0x2f, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6c, 0x08, 0x02, 0x0a, 0x40, 0x06,
- 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x68, 0x65, 0x72, 0x00, 0x40, 0x06, 0x73, 0x6f,
- 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x6f, 0x64,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x5b, 0x6c,
- 0x63, 0x6e, 0x76, 0x70, 0x8b, 0xe2, 0x6c, 0x00, 0x6f, 0x21, 0xe1, 0x61,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x1e,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x08, 0x40, 0x06, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00,
- 0x40, 0x07, 0x79, 0x6d, 0x69, 0x75, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x07, 0x40, 0x00, 0x74, 0x68, 0x69, 0x63, 0x00, 0x40, 0x06, 0x67, 0x69,
- 0x73, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0xe1, 0x74,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09,
- 0xe3, 0x68, 0x00, 0x6c, 0x10, 0x72, 0x22, 0xe2, 0x69, 0x00, 0x79, 0x06,
- 0x40, 0x00, 0x6c, 0x69, 0x61, 0x00, 0x40, 0x09, 0x74, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x69, 0x63, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x00, 0xe4,
- 0x65, 0x00, 0x68, 0x07, 0x6f, 0x26, 0x74, 0x41, 0x40, 0x07, 0x6e, 0x74,
- 0x68, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x06, 0x77, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x07, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63,
- 0x00, 0x40, 0x07, 0x75, 0x6e, 0x69, 0x75, 0x6d, 0x00, 0xe2, 0x64, 0x00,
- 0x76, 0x09, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0xf3, 0xe4,
- 0x65, 0x00, 0x69, 0x23, 0x6f, 0x2a, 0x79, 0x3d, 0xe3, 0x00, 0x00, 0x27,
- 0x02, 0x6c, 0x06, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x47, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x02, 0xe0, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe6, 0x00, 0x00,
- 0x62, 0x02, 0x68, 0x11, 0x69, 0x2d, 0x74, 0x36, 0x77, 0x5b, 0x00, 0x06,
- 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6c, 0x6c, 0x00, 0x40, 0x09,
- 0x6f, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x6d, 0x02, 0x77, 0x08, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00,
- 0x40, 0x07, 0x6f, 0x72, 0x6c, 0x64, 0x00, 0x40, 0x08, 0x71, 0x75, 0x65,
- 0x74, 0x74, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6c, 0x0e, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x08, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x82, 0x40,
- 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x93, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xf2, 0x72, 0x00, 0x00, 0x74, 0xd5, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x30, 0x6f, 0x3f, 0xe2, 0x6c, 0x00, 0x73, 0x13, 0xe2, 0x00, 0x00,
- 0x67, 0x02, 0x00, 0x3b, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02,
- 0x00, 0x07, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63,
- 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe4, 0x6c, 0x00, 0x6e, 0x1b,
- 0x73, 0x26, 0x74, 0x65, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0xe4, 0x63, 0x00, 0x65, 0x10, 0x69,
- 0x14, 0x75, 0x18, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x00, 0x40, 0x09, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0d, 0xe2, 0x6f, 0x00, 0x72, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00, 0xe2, 0x69, 0x00,
- 0x72, 0x10, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x73, 0x6d,
- 0x69, 0x74, 0x74, 0x65, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72,
- 0x06, 0x00, 0x00, 0x40, 0x55, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x33,
- 0x6f, 0x38, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56,
- 0xe3, 0x73, 0x00, 0x74, 0x09, 0x7a, 0x0d, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x01, 0x4b, 0x00, 0x07, 0x40, 0x06, 0x6e, 0x6f, 0x00, 0x40, 0x06,
- 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x1b, 0x75, 0x1d, 0xe1, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x74, 0x08, 0x00, 0x00, 0x40, 0x00, 0x6f,
- 0x72, 0x65, 0x00, 0x40, 0x00, 0x68, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x62, 0x02,
- 0x00, 0x63, 0x10, 0x00, 0x65, 0x17, 0x00, 0x66, 0x1b, 0x00, 0x6c, 0x2e,
- 0x00, 0x6e, 0x3e, 0x00, 0x73, 0x44, 0x00, 0x74, 0x60, 0x01, 0x03, 0xe6,
- 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x06, 0x72,
- 0x6e, 0x00, 0x40, 0x06, 0x6f, 0x6d, 0x65, 0x72, 0x00, 0x40, 0x06, 0x6c,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x08, 0x40, 0x00, 0x6e, 0x67, 0x6c, 0x65,
- 0x64, 0x00, 0x40, 0x00, 0x75, 0x6e, 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x08, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x77, 0x65, 0x64, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xef, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x09, 0x63, 0x0e, 0x64, 0x22, 0x66, 0x2a, 0x67, 0x31, 0x68, 0x41, 0x6c,
- 0x48, 0x6d, 0x50, 0x70, 0x5d, 0x72, 0xa1, 0x73, 0xba, 0x77, 0xc1, 0x79,
- 0xfb, 0x00, 0x07, 0x40, 0x08, 0x67, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06,
- 0x6f, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x24, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x06, 0x65, 0x61, 0x6c, 0x65, 0x72, 0x00, 0x40, 0x08, 0x6c, 0x61, 0x73,
- 0x68, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40, 0x06, 0x72, 0x6c, 0x00,
- 0x40, 0x09, 0x6f, 0x75, 0x70, 0x00, 0x40, 0x08, 0x6f, 0x75, 0x6e, 0x64,
- 0x00, 0x40, 0x09, 0x65, 0x74, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x32, 0x72, 0x37, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x09, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x61, 0x6b, 0x00,
- 0x40, 0x07, 0x69, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x0f, 0xe2,
- 0x61, 0x00, 0x65, 0x06, 0x40, 0x08, 0x64, 0x65, 0x72, 0x00, 0x40, 0x09,
- 0x6c, 0x00, 0x40, 0x09, 0x6f, 0x6d, 0x00, 0x40, 0x06, 0x74, 0x61, 0x6e,
- 0x64, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x07, 0x6f, 0x0d, 0x40, 0x06, 0x65,
- 0x6b, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x72, 0x65, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x72, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x5d,
- 0x00, 0x60, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0x40, 0x09, 0x6e,
- 0x00, 0xe2, 0x74, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x09, 0x73, 0x00,
- 0xc0, 0x61, 0x18, 0x33, 0x00, 0x39, 0x00, 0x4f, 0x00, 0x00, 0x00, 0xa0,
- 0x00, 0xa5, 0x00, 0xb7, 0x00, 0xe5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x02, 0x05, 0x02, 0x34, 0x02, 0xa8, 0x02, 0xaf, 0x02, 0x00,
- 0x00, 0xdd, 0x02, 0xe4, 0x02, 0xe9, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x74, 0x03, 0x40, 0x07, 0x63, 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x62, 0x02, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe4, 0x65, 0x00, 0x68, 0x13,
- 0x6b, 0x17, 0x6f, 0x41, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x08, 0x00,
- 0xd3, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x17, 0x6e, 0x1b,
- 0x00, 0xe7, 0xe2, 0x6c, 0x00, 0x72, 0x0e, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x64, 0x65, 0x6f, 0x6e, 0x00, 0x00, 0x2f, 0x40,
- 0x08, 0x65, 0x00, 0x40, 0x5e, 0x61, 0x6d, 0x65, 0x00, 0x40, 0x07, 0x74,
- 0x69, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x63, 0x65, 0x00, 0xe2, 0x66, 0x00,
- 0x74, 0x09, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x60, 0x79, 0x00, 0xf2, 0x67, 0x00, 0x00, 0x68, 0x34, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x1d, 0x6c, 0x21, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x7a, 0x14,
- 0x00, 0x08, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x56,
- 0x40, 0x07, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x41, 0x69,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0xf3, 0xec, 0x00, 0x00,
- 0x63, 0x02, 0x64, 0x2f, 0x66, 0x36, 0x67, 0x3c, 0x68, 0x42, 0x69, 0x48,
- 0x6c, 0x56, 0x6d, 0x6e, 0x73, 0x80, 0x74, 0xaa, 0x77, 0xb0, 0x00, 0x56,
- 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40, 0x06, 0x70, 0x00, 0xe2, 0x6f, 0x00,
- 0x75, 0x07, 0x40, 0x07, 0x74, 0x68, 0x65, 0x73, 0x00, 0xe1, 0x62, 0x00,
- 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x6c, 0x00, 0x40, 0x06,
- 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x77, 0x6b, 0x00, 0xe2, 0x65,
- 0x00, 0x6e, 0x02, 0x00, 0x06, 0x40, 0x06, 0x67, 0x61, 0x6c, 0x65, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x0e, 0xe2, 0x66, 0x00, 0x67, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x08, 0x68, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe3, 0x68, 0x00, 0x70, 0x0f, 0x74,
- 0x14, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x06, 0x64, 0x65, 0x00, 0x40,
- 0x06, 0x72, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x74, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x05, 0x40, 0x06, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x63, 0x6b, 0x00,
- 0x40, 0x07, 0x69, 0x6d, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x19, 0xe1,
- 0x74, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x07, 0x61, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x07, 0xe2, 0x62, 0x00, 0x72, 0x25, 0xe4, 0x69, 0x00, 0x6c, 0x02, 0x75,
- 0x16, 0x79, 0x1a, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0x92, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0x00, 0x00, 0x40, 0x09, 0x6f, 0x64, 0x00,
- 0xe5, 0x63, 0x00, 0x65, 0x09, 0x6a, 0x55, 0x6e, 0x59, 0x74, 0x5d, 0x40,
- 0x06, 0x6f, 0x6d, 0x70, 0x6f, 0x6f, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x70,
- 0x02, 0x74, 0x11, 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69,
- 0x19, 0x79, 0x2b, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x01, 0x58, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x03, 0xc6,
- 0x40, 0x06, 0x61, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x62, 0x69,
- 0x75, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0xe4, 0x65,
- 0x00, 0x69, 0x09, 0x6c, 0x18, 0x79, 0x1c, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05,
- 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x09, 0x65, 0x00, 0x01,
- 0x92, 0x40, 0x07, 0x76, 0x61, 0x6e, 0x61, 0x00, 0x40, 0x07, 0x65, 0x69,
- 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x70, 0x06, 0x72, 0x21, 0x77, 0x7b,
- 0x00, 0x2b, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x27,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x0f, 0x6f, 0x22, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x02, 0xa4, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x0a,
- 0x40, 0x07, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x67, 0x0d, 0x00, 0x00, 0x40,
- 0x07, 0x65, 0x6c, 0x6c, 0x75, 0x6c, 0x6f, 0x73, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x6c, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x07, 0x79, 0x63, 0x65, 0x72,
- 0x69, 0x6e, 0x00, 0x40, 0x09, 0x69, 0x74, 0x00, 0x00, 0x59, 0xc1, 0x62,
- 0x19, 0x37, 0x00, 0x39, 0x00, 0x94, 0x00, 0xab, 0x00, 0xe4, 0x00, 0x00,
- 0x00, 0xed, 0x00, 0xf3, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x01, 0x97, 0x01, 0x6e, 0x0f, 0xad, 0x0f, 0x00, 0x00, 0xb1,
- 0x0f, 0x81, 0x10, 0x04, 0x11, 0x4d, 0x12, 0x75, 0x12, 0xd5, 0x12, 0x03,
- 0x13, 0x00, 0x00, 0x0a, 0x13, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x62, 0x02,
- 0x65, 0x07, 0x69, 0x0e, 0x6c, 0x15, 0x6f, 0x49, 0x03, 0x6c, 0x40, 0x0b,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x07,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x6d,
- 0x02, 0x6e, 0x0f, 0x77, 0x15, 0x03, 0xe7, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x64,
- 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0x00,
- 0x09, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x64, 0x06, 0x65, 0x1e, 0x75, 0x20,
- 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04, 0x6c,
- 0x09, 0x79, 0x0d, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x65, 0x00, 0x00, 0x00, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x72, 0x00, 0x00, 0x09, 0xe2, 0x6c,
- 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x00, 0x40, 0x09, 0x67, 0x69, 0x6e,
- 0x00, 0x40, 0x00, 0x6f, 0x77, 0x00, 0xe1, 0x73, 0x00, 0xe4, 0x65, 0x00,
- 0x69, 0x26, 0x6f, 0x35, 0x79, 0x3a, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6d,
- 0x18, 0x00, 0x5e, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x09, 0x61, 0x6b, 0x65, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x6d, 0x65, 0x00, 0x00, 0x96, 0xe3, 0x61, 0x00, 0x65, 0x0e, 0x69,
- 0x19, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x63, 0x00, 0x40, 0x09, 0x6e, 0x63, 0x6c, 0x61, 0x74, 0x75, 0x72,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x2b, 0xe2, 0x6c,
- 0x00, 0x74, 0x02, 0x00, 0x3b, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x19,
- 0x03, 0xe8, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x27, 0x02, 0x01, 0x82, 0x40, 0x77, 0x73, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0x41, 0x82, 0x72, 0x00, 0x40, 0x09, 0x65, 0x00, 0xc1, 0x61, 0x1a,
- 0x39, 0x00, 0x3b, 0x00, 0x62, 0x01, 0xa7, 0x01, 0xb2, 0x03, 0x91, 0x04,
- 0x76, 0x05, 0x15, 0x06, 0x30, 0x06, 0x52, 0x06, 0x1f, 0x07, 0x00, 0x00,
- 0x3a, 0x07, 0x6a, 0x07, 0xc8, 0x07, 0x02, 0x08, 0x83, 0x08, 0x00, 0x00,
- 0xd5, 0x09, 0xfd, 0x0a, 0x87, 0x0c, 0x26, 0x0d, 0x42, 0x0d, 0xb4, 0x0d,
- 0x00, 0x00, 0xc7, 0x0d, 0xd1, 0x0d, 0x00, 0x00, 0xfa, 0x62, 0x00, 0x00,
- 0x63, 0x16, 0x00, 0x64, 0x3b, 0x00, 0x67, 0x78, 0x00, 0x6c, 0x96, 0x00,
- 0x70, 0xc3, 0x00, 0x73, 0xce, 0x00, 0x74, 0xd9, 0x00, 0x75, 0xf0, 0x00,
- 0x76, 0xfb, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x08, 0x40, 0x00, 0x61, 0x73,
- 0x69, 0x76, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x62, 0x65, 0x6e, 0x74,
- 0x00, 0xe4, 0x61, 0x00, 0x63, 0x08, 0x69, 0x12, 0x74, 0x16, 0x40, 0x00,
- 0x64, 0x65, 0x6d, 0x69, 0x63, 0x00, 0x40, 0x07, 0x65, 0x70, 0x74, 0x61,
- 0x6e, 0x63, 0x65, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x09, 0x69, 0x76,
- 0x65, 0x00, 0xe4, 0x64, 0x00, 0x68, 0x09, 0x6a, 0x11, 0x6d, 0x26, 0x40,
- 0x00, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x69, 0x76, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x07, 0x40, 0x00, 0x63,
- 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x00, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69,
- 0x76, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x0f, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x09, 0x40, 0x09, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00,
- 0x69, 0x09, 0x6c, 0x1e, 0x40, 0x00, 0x6f, 0x68, 0x6f, 0x6c, 0x69, 0x63,
- 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00,
- 0x65, 0x72, 0x67, 0x69, 0x63, 0x00, 0x40, 0x09, 0x70, 0x65, 0x61, 0x72,
- 0x61, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x61,
- 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x08, 0x40, 0x00, 0x6c,
- 0x65, 0x74, 0x69, 0x63, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x64, 0x61, 0x6e,
- 0x63, 0x65, 0x00, 0x40, 0x00, 0x74, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x69, 0x6c, 0x69,
- 0x74, 0x79, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x06, 0x69, 0x1f, 0x72, 0x27,
- 0x75, 0x31, 0x40, 0x00, 0x73, 0x69, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x09, 0x65, 0x76, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x69, 0x67, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x6e,
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x61, 0x6b, 0x61, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x00, 0x72, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x00,
- 0xf7, 0x61, 0x00, 0x00, 0x65, 0x15, 0x00, 0x68, 0x17, 0x00, 0x6c, 0x39,
- 0x00, 0x6f, 0x4e, 0x00, 0x72, 0xb2, 0x01, 0x75, 0xdd, 0x01, 0xe2, 0x6c,
- 0x00, 0x6e, 0x07, 0x40, 0x00, 0x6f, 0x72, 0x69, 0x63, 0x00, 0x40, 0x00,
- 0x63, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x61, 0x00,
- 0xe2, 0x6c, 0x00, 0x72, 0x11, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x40, 0x00,
- 0x67, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x08,
- 0x40, 0x09, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x6e, 0x69,
- 0x63, 0x61, 0x6c, 0x00, 0xf5, 0x6c, 0x00, 0x00, 0x6d, 0x0b, 0x00, 0x6e,
- 0x8c, 0x00, 0x6f, 0x32, 0x01, 0x72, 0x3d, 0x01, 0x40, 0x00, 0x6c, 0x65,
- 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02,
- 0x6d, 0x1f, 0x70, 0x3f, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x75, 0x0f, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x09, 0x6e,
- 0x74, 0x00, 0x40, 0x00, 0x73, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x08, 0x75, 0x0f, 0x40, 0x09, 0x72, 0x63, 0x69, 0x61,
- 0x6c, 0x00, 0x40, 0x3b, 0x74, 0x74, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x6e,
- 0x69, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x15,
- 0x72, 0x27, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6e, 0x00, 0x74,
- 0x04, 0x40, 0x00, 0x67, 0x00, 0x40, 0x00, 0x69, 0x76, 0x65, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x40,
- 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x68, 0x65, 0x6e, 0x64,
- 0x69, 0x6e, 0x67, 0x00, 0xe5, 0x64, 0x00, 0x66, 0x17, 0x73, 0x3b, 0x74,
- 0x53, 0x76, 0x91, 0xe1, 0x75, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe1,
- 0x69, 0x00, 0xe3, 0x6e, 0x00, 0x73, 0x04, 0x74, 0x0d, 0x40, 0x00, 0x67,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x09, 0x40, 0x00, 0x63, 0x75, 0x74,
- 0x69, 0x76, 0x65, 0x00, 0x40, 0x00, 0x72, 0x75, 0x63, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x08, 0x72, 0x10, 0x40, 0x00, 0x67,
- 0x69, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x00, 0x6e, 0x75, 0x6f, 0x75, 0x73,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x18, 0xe1, 0x62, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0x40, 0x00, 0x76, 0x65, 0x72, 0x73,
- 0x69, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x72, 0x74, 0x69, 0x62, 0x6c,
- 0x65, 0x00, 0x40, 0x07, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x06,
- 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x76, 0x65, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x06, 0x79, 0x19, 0x40, 0x00, 0x64, 0x69, 0x74,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x07, 0x40, 0x06, 0x69, 0x6e, 0x61, 0x6c,
- 0x00, 0x40, 0x00, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x73, 0x74,
- 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x0a,
- 0x40, 0x00, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x00,
- 0x74, 0x6f, 0x64, 0x69, 0x61, 0x6c, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x06,
- 0x69, 0x7a, 0x72, 0xba, 0x40, 0x00, 0x69, 0x72, 0x79, 0x00, 0xe7, 0x64,
- 0x00, 0x6c, 0x0a, 0x6d, 0x12, 0x6e, 0x1c, 0x70, 0x2a, 0x73, 0x45, 0x74,
- 0x5b, 0x40, 0x07, 0x75, 0x63, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x69, 0x76, 0x65, 0x72, 0x79, 0x00, 0x40, 0x00, 0x6f, 0x63, 0x72,
- 0x61, 0x74, 0x69, 0x63, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x69, 0x6e, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x0b,
- 0x40, 0x00, 0x72, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x00, 0x40,
- 0x00, 0x65, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x07, 0x40, 0x00, 0x72, 0x69, 0x70, 0x74, 0x00, 0x40, 0x00,
- 0x72, 0x75, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x00, 0x61, 0x63,
- 0x68, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00,
- 0xe3, 0x69, 0x00, 0x6c, 0x0a, 0x72, 0x12, 0x40, 0x00, 0x70, 0x6c, 0x69,
- 0x6e, 0x61, 0x72, 0x79, 0x00, 0x40, 0x07, 0x6f, 0x73, 0x75, 0x72, 0x65,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x08, 0x79, 0x0f, 0x40, 0x00, 0x6d, 0x61, 0x74, 0x69, 0x63,
- 0x00, 0x40, 0x09, 0x6e, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x00, 0x69, 0x6e,
- 0x67, 0x00, 0xeb, 0x00, 0x00, 0x64, 0x02, 0x66, 0x0e, 0x6c, 0x18, 0x6d,
- 0x3e, 0x6e, 0x44, 0x71, 0x5a, 0x73, 0x65, 0x74, 0x78, 0x76, 0x81, 0x78,
- 0x87, 0x00, 0x00, 0x40, 0x00, 0x75, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x61, 0x6c, 0x00, 0x40, 0x00, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x00, 0x73, 0x74, 0x69, 0x63,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x00, 0x40, 0x00, 0x70, 0x74, 0x79, 0x00, 0xe2, 0x66, 0x00,
- 0x74, 0x0b, 0x40, 0x00, 0x6f, 0x72, 0x63, 0x65, 0x61, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x06, 0x69, 0x74, 0x79, 0x00, 0x40, 0x09, 0x75, 0x69, 0x76,
- 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x73, 0x00, 0x75, 0x09, 0x40,
- 0x00, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x63, 0x68,
- 0x00, 0x40, 0x00, 0x68, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x65, 0x6e, 0x74, 0x00, 0xe4, 0x63, 0x00, 0x65, 0x18, 0x69, 0x1e, 0x70,
- 0x35, 0xe2, 0x68, 0x00, 0x6c, 0x0b, 0x40, 0x00, 0x61, 0x6e, 0x67, 0x65,
- 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x75, 0x73, 0x69, 0x76, 0x65,
- 0x00, 0x40, 0x07, 0x6d, 0x70, 0x74, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0x40, 0x09, 0x6c, 0x6f, 0x73, 0x69,
- 0x76, 0x65, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x29, 0x69, 0x31, 0x6c, 0x4b,
- 0x6f, 0x77, 0x72, 0x7c, 0x75, 0x85, 0xe3, 0x63, 0x00, 0x64, 0x07, 0x74,
- 0x0d, 0x40, 0x00, 0x74, 0x75, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x69, 0x6e,
- 0x67, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x74, 0x06, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x72, 0x72, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0xe4, 0x61, 0x00,
- 0x6f, 0x09, 0x75, 0x12, 0x79, 0x1d, 0x40, 0x00, 0x6d, 0x6d, 0x61, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x00, 0x77, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x00, 0x63, 0x74, 0x75, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x64, 0x00, 0x40, 0x00,
- 0x65, 0x65, 0x7a, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6e, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x0d, 0x40,
- 0x00, 0x76, 0x65, 0x72, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x61, 0x6e, 0x75, 0x6c, 0x61, 0x72, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x0a, 0x75, 0x15, 0x40, 0x00, 0x7a, 0x61, 0x72, 0x64, 0x6f, 0x75,
- 0x73, 0x00, 0x40, 0x00, 0x72, 0x65, 0x64, 0x69, 0x74, 0x61, 0x72, 0x79,
- 0x00, 0x40, 0x00, 0x6d, 0x61, 0x6e, 0x00, 0xe4, 0x64, 0x00, 0x6e, 0x0a,
- 0x72, 0xb3, 0x73, 0xbe, 0x40, 0x00, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
- 0x6c, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x09, 0x66, 0x21, 0x74, 0x52, 0x76,
- 0x96, 0x40, 0x00, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x75, 0x0a, 0x40, 0x00, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74,
- 0x00, 0x40, 0x00, 0x73, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x6c, 0x09, 0x40, 0x00, 0x63, 0x74, 0x69, 0x6f, 0x75, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x17, 0xe2, 0x6d, 0x00, 0x74, 0x09, 0x40, 0x00,
- 0x6d, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x00, 0x40, 0x00, 0x69, 0x6f, 0x6e,
- 0x61, 0x72, 0x79, 0x00, 0x40, 0x00, 0x63, 0x74, 0x65, 0x64, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x34, 0xe2, 0x6c, 0x00, 0x72, 0x0a, 0x40, 0x09, 0x6c,
- 0x65, 0x63, 0x74, 0x75, 0x61, 0x6c, 0x00, 0xe3, 0x63, 0x00, 0x66, 0x0c,
- 0x76, 0x15, 0x40, 0x00, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x61, 0x62, 0x6c,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x78, 0x69,
- 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x61, 0x73, 0x69,
- 0x76, 0x65, 0x00, 0x40, 0x00, 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6e,
- 0x67, 0x00, 0x40, 0x00, 0x73, 0x75, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x67, 0x00, 0x69, 0x09, 0x40, 0x00, 0x6d, 0x65, 0x6e,
- 0x74, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x63, 0x69, 0x61, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x10, 0xe2, 0x67, 0x00, 0x74, 0x05, 0x40, 0x00, 0x61,
- 0x6c, 0x00, 0x40, 0x00, 0x68, 0x61, 0x6c, 0x00, 0xe3, 0x6e, 0x00, 0x74,
- 0x06, 0x76, 0x0e, 0x40, 0x00, 0x65, 0x61, 0x72, 0x00, 0x40, 0x00, 0x65,
- 0x72, 0x61, 0x72, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x16, 0x69, 0x33, 0xe2, 0x67, 0x00, 0x6c, 0x08, 0x40,
- 0x00, 0x6e, 0x65, 0x74, 0x69, 0x63, 0x00, 0x40, 0x00, 0x69, 0x67, 0x6e,
- 0x61, 0x6e, 0x74, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x06, 0x40, 0x09, 0x62,
- 0x65, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x06, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe2, 0x67, 0x00,
- 0x6c, 0x09, 0x40, 0x00, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x72,
- 0x04, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x13, 0x75, 0x1e, 0xe2, 0x72, 0x00, 0x74, 0x08, 0x40, 0x06, 0x63,
- 0x6f, 0x74, 0x69, 0x63, 0x00, 0x40, 0x09, 0x69, 0x76, 0x65, 0x00, 0x40,
- 0x00, 0x67, 0x6f, 0x74, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x63,
- 0x00, 0x6d, 0x07, 0x40, 0x00, 0x6c, 0x65, 0x61, 0x72, 0x00, 0x40, 0x00,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x00, 0xe4, 0x62, 0x00, 0x63, 0x34,
- 0x66, 0x51, 0x70, 0x5a, 0xe3, 0x6a, 0x00, 0x6c, 0x09, 0x73, 0x13, 0x40,
- 0x00, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x00, 0x69, 0x67,
- 0x61, 0x74, 0x6f, 0x72, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x76, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x75, 0x00, 0xe2, 0x70, 0x00, 0x72, 0x0a, 0x40, 0x00, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x72, 0x65, 0x6e, 0x63, 0x65,
- 0x00, 0x40, 0x00, 0x66, 0x69, 0x63, 0x69, 0x61, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x06, 0x40, 0x00, 0x6e, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0xf7, 0x61, 0x00, 0x00, 0x65, 0x4d, 0x00, 0x68,
- 0x7e, 0x00, 0x6c, 0x87, 0x00, 0x6f, 0xa2, 0x00, 0x72, 0xcd, 0x00, 0x75,
- 0x27, 0x01, 0xe2, 0x72, 0x00, 0x79, 0x38, 0xe3, 0x61, 0x00, 0x65, 0x07,
- 0x74, 0x0c, 0x40, 0x09, 0x6c, 0x6c, 0x65, 0x6c, 0x00, 0x40, 0x09, 0x69,
- 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x18, 0xe1, 0x69,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04,
- 0x40, 0x09, 0x74, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x61, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6d, 0x05, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x66,
- 0x00, 0x69, 0x19, 0x73, 0x22, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6e, 0x63, 0x65,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x73, 0x68, 0x61, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x3b, 0x79, 0x73,
- 0x69, 0x63, 0x61, 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x69, 0x00, 0x6c,
- 0x09, 0x72, 0x1e, 0x40, 0x00, 0x73, 0x6f, 0x6e, 0x6f, 0x75, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x08, 0x40, 0x00, 0x74, 0x69, 0x63, 0x61, 0x6c,
- 0x00, 0x40, 0x00, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6f,
- 0x75, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0a, 0x6f, 0x24, 0x40, 0x00,
- 0x63, 0x74, 0x69, 0x63, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x6a, 0x00, 0x73,
- 0x0a, 0x40, 0x00, 0x75, 0x64, 0x69, 0x63, 0x69, 0x61, 0x6c, 0x00, 0x40,
- 0x00, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x64,
- 0x00, 0x66, 0x09, 0x6c, 0x1c, 0x40, 0x00, 0x75, 0x63, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0a, 0x40, 0x06, 0x73, 0x73, 0x69,
- 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x40, 0xc0, 0x74, 0x00, 0x40, 0x07, 0x69,
- 0x66, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x62, 0x00,
- 0x6e, 0x06, 0x40, 0x00, 0x6c, 0x69, 0x63, 0x00, 0x40, 0x00, 0x69, 0x73,
- 0x68, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xf4, 0x61, 0x00, 0x00, 0x65, 0x1e,
- 0x00, 0x68, 0x0c, 0x01, 0x69, 0x15, 0x01, 0xe3, 0x63, 0x00, 0x64, 0x06,
- 0x6e, 0x11, 0x40, 0x00, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x69, 0x6f,
- 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x00, 0x64, 0x6f, 0x6d,
- 0x00, 0xe9, 0x61, 0x00, 0x63, 0x08, 0x64, 0x4a, 0x66, 0x54, 0x6c, 0x6b,
- 0x6e, 0x74, 0x70, 0x7d, 0x73, 0x8d, 0x74, 0xd1, 0x40, 0x00, 0x63, 0x74,
- 0x69, 0x76, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x1c, 0x75, 0x33, 0xe1,
- 0x70, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40, 0x00, 0x69,
- 0x6e, 0x67, 0x00, 0xe2, 0x67, 0x00, 0x76, 0x09, 0x40, 0x07, 0x6e, 0x69,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x72, 0x61, 0x62, 0x6c,
- 0x65, 0x00, 0x40, 0x00, 0x72, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x65, 0x65, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x75,
- 0x09, 0x40, 0x00, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00,
- 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x69, 0x67, 0x69,
- 0x6f, 0x75, 0x73, 0x00, 0x40, 0x00, 0x65, 0x77, 0x61, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x00, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x35, 0xe2, 0x64,
- 0x00, 0x73, 0x1c, 0xe2, 0x65, 0x00, 0x75, 0x12, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x61,
- 0x6c, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65,
- 0x00, 0x40, 0x09, 0x75, 0x72, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40,
- 0x00, 0x79, 0x74, 0x68, 0x6d, 0x69, 0x63, 0x00, 0x40, 0x00, 0x67, 0x69,
- 0x64, 0x00, 0xfb, 0x61, 0x00, 0x00, 0x63, 0x09, 0x00, 0x65, 0x2a, 0x00,
- 0x6b, 0x83, 0x00, 0x6c, 0x88, 0x00, 0x6d, 0x8d, 0x00, 0x6f, 0xa1, 0x00,
- 0x70, 0xa8, 0x00, 0x74, 0xe4, 0x00, 0x75, 0x30, 0x01, 0x79, 0x5c, 0x01,
- 0x40, 0x00, 0x6c, 0x61, 0x72, 0x69, 0x65, 0x64, 0x00, 0xe3, 0x68, 0x00,
- 0x69, 0x09, 0x6f, 0x13, 0x40, 0x00, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64,
- 0x00, 0x40, 0x00, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x63, 0x00, 0x40,
- 0x00, 0x72, 0x69, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x63, 0x08, 0x67,
- 0x1b, 0x6e, 0x25, 0x78, 0x3f, 0x40, 0x00, 0x73, 0x6f, 0x6e, 0x61, 0x6c,
- 0x00, 0xe2, 0x74, 0x00, 0x75, 0x08, 0x40, 0x00, 0x61, 0x72, 0x69, 0x61,
- 0x6e, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00, 0x40, 0x00, 0x72, 0x65,
- 0x67, 0x61, 0x74, 0x65, 0x64, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x74, 0x05, 0x40, 0x3b, 0x61,
- 0x6c, 0x00, 0x40, 0x00, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x75,
- 0x05, 0x40, 0x00, 0x73, 0x74, 0x00, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40,
- 0x00, 0x69, 0x64, 0x00, 0x40, 0x00, 0x69, 0x70, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x63, 0x69, 0x61, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x2e, 0xe2, 0x61, 0x00, 0x63, 0x07, 0x40, 0x00,
- 0x6b, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x66,
- 0x15, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x04,
- 0x40, 0x09, 0x74, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x69, 0x63, 0x00, 0x40, 0x06, 0x72, 0x69, 0x74, 0x75, 0x61, 0x6c, 0x00,
- 0xe4, 0x61, 0x00, 0x69, 0x1b, 0x6f, 0x20, 0x72, 0x24, 0xe3, 0x69, 0x00,
- 0x6e, 0x07, 0x72, 0x0e, 0x40, 0x00, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x64, 0x61, 0x72, 0x64, 0x00, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x63, 0x6b, 0x00, 0x40, 0x00, 0x70, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x08, 0x75, 0x0f, 0x40, 0x00, 0x74, 0x65, 0x67, 0x69, 0x63, 0x00,
- 0x40, 0x00, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x63, 0x74, 0x75,
- 0x72, 0x61, 0x6c, 0x00, 0xe4, 0x63, 0x00, 0x70, 0x0a, 0x72, 0x11, 0x73,
- 0x19, 0x40, 0x00, 0x63, 0x65, 0x73, 0x73, 0x69, 0x76, 0x65, 0x00, 0x40,
- 0x2a, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x40, 0x00, 0x67, 0x69, 0x63, 0x61,
- 0x6c, 0x00, 0x40, 0x00, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x6d, 0x70, 0x61, 0x74, 0x68, 0x69, 0x7a, 0x65, 0x72, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x17, 0x68, 0x2c, 0x6f, 0x50, 0x72, 0x56, 0xe2,
- 0x72, 0x00, 0x78, 0x0b, 0x40, 0x00, 0x6e, 0x69, 0x73, 0x68, 0x61, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x00, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x63,
- 0x00, 0x6e, 0x09, 0x40, 0x00, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x75, 0x72, 0x65, 0x64, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0a,
- 0x72, 0x12, 0x40, 0x00, 0x61, 0x74, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x61,
- 0x74, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x78, 0x69, 0x63,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x28, 0x6f, 0x2f, 0xe2, 0x64, 0x00, 0x6e,
- 0x0a, 0x40, 0x00, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x66, 0x00, 0x70, 0x09, 0x40, 0x00, 0x65, 0x72, 0x61,
- 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x00, 0x76, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x70, 0x69, 0x63,
- 0x61, 0x6c, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x12, 0xe1, 0x69, 0x00, 0xe2,
- 0x66, 0x00, 0x6f, 0x06, 0x40, 0x00, 0x6f, 0x72, 0x6d, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x13,
- 0x6f, 0x3c, 0xe2, 0x6e, 0x00, 0x72, 0x08, 0x40, 0x00, 0x6f, 0x6d, 0x6f,
- 0x75, 0x73, 0x00, 0x40, 0x00, 0x62, 0x61, 0x6c, 0x00, 0xe3, 0x61, 0x00,
- 0x6f, 0x06, 0x72, 0x1a, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x40, 0x00, 0x75, 0x6c, 0x65, 0x6e,
- 0x74, 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x12, 0x74, 0x1a, 0xe1, 0x61, 0x00,
- 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x00, 0x69, 0x6f, 0x6e,
- 0x61, 0x6c, 0x00, 0x40, 0x00, 0x61, 0x74, 0x69, 0x6c, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x06, 0x40, 0x09, 0x69, 0x74, 0x65, 0x00,
- 0x40, 0x00, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x65,
- 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x72, 0x6f, 0x00,
- 0xe4, 0x64, 0x00, 0x6b, 0x05, 0x6e, 0x14, 0x73, 0x32, 0x40, 0x82, 0x6c,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x06, 0x00, 0x09, 0x40,
- 0x00, 0x65, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x74, 0x07,
- 0x00, 0x07, 0x40, 0x07, 0x61, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x64,
- 0x00, 0x6d, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02,
- 0x6d, 0x0b, 0x74, 0x41, 0x00, 0x00, 0x40, 0x00, 0x65, 0x61, 0x73, 0x74,
- 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe2, 0x6c,
- 0x00, 0x74, 0x24, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x69, 0x06, 0x00, 0x12,
- 0x40, 0x07, 0x79, 0x00, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x3a, 0x40, 0x00, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x68, 0x00,
- 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x09, 0x77, 0x4f, 0x00, 0x27, 0x40,
- 0x00, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x21, 0xe1,
- 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x77, 0x0e,
- 0x00, 0x13, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x12,
- 0x00, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x6c,
- 0x02, 0x6e, 0x06, 0x00, 0x12, 0x40, 0x06, 0x79, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6d, 0x06, 0x02, 0x75, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00,
- 0x6f, 0x73, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x08, 0x72,
- 0x64, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x77, 0x0e, 0x00, 0x27, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x12, 0x00, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00, 0xe5,
- 0x65, 0x00, 0x68, 0x2d, 0x69, 0x38, 0x74, 0x47, 0x79, 0x76, 0xe5, 0x00,
- 0x00, 0x62, 0x02, 0x63, 0x11, 0x64, 0x17, 0x67, 0x1d, 0x00, 0x82, 0xe2,
- 0x61, 0x00, 0x6c, 0x04, 0x40, 0x08, 0x67, 0x00, 0x40, 0x09, 0x65, 0x65,
- 0x64, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x5e, 0x69, 0x76,
- 0x65, 0x00, 0x40, 0x06, 0x61, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x72, 0x1d, 0xe1, 0x6c, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x04,
- 0x40, 0x09, 0x6c, 0x00, 0x40, 0x09, 0x6d, 0x00, 0x01, 0x15, 0xf8, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x48, 0x00, 0x65, 0x4c, 0x00, 0x68,
- 0x93, 0x00, 0x69, 0xa9, 0x00, 0x6f, 0x04, 0x01, 0x77, 0x19, 0x01, 0x00,
- 0x22, 0xe3, 0x62, 0x00, 0x72, 0x15, 0x74, 0x33, 0xe2, 0x69, 0x00, 0x6c,
- 0x07, 0x40, 0x06, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x06, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x17, 0xe2, 0x61,
- 0x00, 0x7a, 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x43, 0xe9, 0x6f, 0x6e, 0x00, 0x40,
- 0x59, 0x68, 0x00, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x6c, 0x0c,
- 0x70, 0x11, 0x77, 0x20, 0x03, 0xea, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09,
- 0x6f, 0x6f, 0x6b, 0x00, 0x40, 0x08, 0x65, 0x74, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x64, 0x00, 0x70, 0x02, 0x00, 0x08, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x5d, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x6e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x63, 0x00, 0x66, 0x26, 0x6f, 0x46, 0xe1, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x11, 0x64, 0x18, 0x00, 0x82, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x00,
- 0x40, 0x08, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x00, 0x37, 0xe2, 0x69, 0x00,
- 0x79, 0x19, 0xe3, 0x61, 0x00, 0x63, 0x06, 0x65, 0x0e, 0x40, 0x00, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0xa9, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x3b, 0x75, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0d, 0x40, 0x00, 0x74,
- 0x68, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x08,
- 0x72, 0x6b, 0x00, 0xe4, 0x67, 0x00, 0x6e, 0x05, 0x72, 0x07, 0x73, 0x1d,
- 0x40, 0x09, 0x61, 0x74, 0x00, 0x02, 0x23, 0xe1, 0x69, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x58, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x09,
- 0x69, 0x49, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x32, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x08, 0x6c,
- 0x1f, 0x74, 0x23, 0x00, 0x06, 0x40, 0x06, 0x74, 0x74, 0x65, 0x00, 0xe2,
- 0x73, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x09,
- 0x61, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00,
- 0x09, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65, 0x00,
- 0x40, 0x09, 0x69, 0x61, 0x74, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02,
- 0x68, 0x0f, 0x69, 0x15, 0x72, 0x1a, 0x74, 0x1f, 0x00, 0x07, 0xe2, 0x64,
- 0x00, 0x79, 0x06, 0x40, 0x07, 0x61, 0x79, 0x73, 0x00, 0x00, 0x08, 0x40,
- 0x07, 0x65, 0x72, 0x65, 0x00, 0x40, 0x00, 0x73, 0x65, 0x00, 0x40, 0x00,
- 0x61, 0x70, 0x00, 0x00, 0x00, 0x40, 0x00, 0x69, 0x6f, 0x75, 0x73, 0x00,
- 0x40, 0x09, 0x7a, 0x6c, 0x65, 0x00, 0xff, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x62, 0x08, 0x00, 0x63, 0x21, 0x00, 0x64, 0x72, 0x00, 0x67, 0x91,
- 0x00, 0x69, 0xa2, 0x00, 0x6b, 0xaa, 0x00, 0x6c, 0xae, 0x00, 0x6d, 0xd1,
- 0x00, 0x6e, 0x8e, 0x01, 0x70, 0xa2, 0x01, 0x72, 0xa9, 0x01, 0x74, 0x05,
- 0x02, 0x7a, 0xc3, 0x02, 0x00, 0x06, 0x40, 0xb2, 0x6e, 0x63, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x62, 0x02, 0x69, 0x0d, 0x00, 0x06, 0xe2, 0x69, 0x00,
- 0x79, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x60, 0x40, 0x00, 0x6c, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x13,
- 0x6f, 0x1c, 0x75, 0x3e, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x01, 0xef, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x6c, 0x00, 0x6e,
- 0x0b, 0x73, 0x0d, 0x74, 0x13, 0xe2, 0x69, 0x00, 0x75, 0x02, 0x00, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x00, 0x06, 0x40, 0x00, 0x69, 0x64, 0x65, 0x00,
- 0x40, 0x00, 0x69, 0x64, 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x65,
- 0x00, 0x67, 0x02, 0x69, 0x06, 0x01, 0xa5, 0x40, 0xa1, 0x65, 0x00, 0xe2,
- 0x73, 0x00, 0x74, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x67, 0x07, 0x40, 0x00,
- 0x74, 0x6f, 0x72, 0x79, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0x40, 0x09,
- 0x73, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x08, 0xe2, 0x66, 0x00, 0x74,
- 0x10, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x03, 0xeb, 0x40, 0x07, 0x79, 0x00, 0xe4, 0x62, 0x00,
- 0x65, 0x2b, 0x69, 0x84, 0x73, 0xad, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e,
- 0x1e, 0x03, 0xec, 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65,
- 0x06, 0x6c, 0x0a, 0x00, 0xd5, 0x40, 0x00, 0x73, 0x00, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x26, 0x6f, 0x34, 0xe4,
- 0x62, 0x00, 0x63, 0x05, 0x6c, 0x09, 0x74, 0x0b, 0x40, 0x54, 0x6c, 0x65,
- 0x00, 0x40, 0x53, 0x79, 0x00, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x3b, 0x6c, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x12, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0x40, 0x3b, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x06, 0x40,
- 0x00, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x09, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0x40, 0x06, 0x74, 0x00, 0x40,
- 0x09, 0x6b, 0x75, 0x6c, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6e,
- 0x07, 0x00, 0x06, 0x40, 0x06, 0x69, 0x6f, 0x00, 0x40, 0x06, 0x65, 0x72,
- 0x79, 0x00, 0x40, 0x09, 0x74, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x45, 0xe3, 0x65, 0x00, 0x69, 0x33, 0x6c, 0x38, 0xe4, 0x00, 0x00,
- 0x6c, 0x02, 0x6d, 0x09, 0x72, 0x0f, 0x00, 0xa5, 0x40, 0x00, 0x69, 0x6e,
- 0x67, 0x73, 0x00, 0x40, 0x09, 0x61, 0x69, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe8, 0x00, 0x00, 0x63, 0x02, 0x68, 0x14,
- 0x6d, 0x25, 0x70, 0x33, 0x72, 0x39, 0x73, 0x85, 0x74, 0x8c, 0x00, 0x06,
- 0xe2, 0x61, 0x00, 0x72, 0x05, 0x40, 0x08, 0x73, 0x65, 0x00, 0x40, 0x09,
- 0x61, 0x63, 0x6b, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06, 0x40,
- 0x09, 0x74, 0x63, 0x68, 0x00, 0x40, 0x08, 0x75, 0x73, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x67, 0x04, 0x40, 0x06, 0x74, 0x00, 0x00,
- 0x06, 0x40, 0x06, 0x69, 0x63, 0x6b, 0x00, 0xe1, 0x69, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x02, 0x6d, 0x07, 0x74, 0x0d, 0x00, 0x06, 0x40, 0x09, 0x6e,
- 0x74, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x76, 0x27, 0xe2, 0x6e, 0x00, 0x75, 0x12, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x06, 0x00, 0x07, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06,
- 0x73, 0x74, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40,
- 0x09, 0x68, 0x65, 0x6c, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79,
- 0x18, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x08, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x00, 0x00, 0xf4, 0xe1, 0x7a, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe3, 0x62, 0x00,
- 0x6c, 0x06, 0x6d, 0x15, 0x40, 0x08, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00,
- 0x07, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x6f, 0x06, 0x73, 0x22, 0x00, 0x07, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x08, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07,
- 0x00, 0x06, 0x00, 0x00, 0xc1, 0x27, 0x54, 0xad, 0x00, 0xaf, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x54, 0x01, 0xb1, 0x05, 0x47,
- 0x07, 0xd5, 0x07, 0xfe, 0x07, 0x9a, 0x09, 0xc0, 0x09, 0xdd, 0x09, 0x00,
- 0x00, 0x53, 0x0a, 0x67, 0x0a, 0x14, 0x0b, 0x11, 0x0c, 0x6e, 0x0d, 0x9a,
- 0x0d, 0x00, 0x00, 0x74, 0x10, 0x84, 0x14, 0xad, 0x15, 0xe8, 0x15, 0x05,
- 0x1b, 0x6c, 0x24, 0xa2, 0x24, 0x4c, 0x25, 0x53, 0x25, 0x00, 0x00, 0xe2,
- 0x63, 0x00, 0x65, 0x07, 0x40, 0x00, 0x6c, 0x6f, 0x63, 0x6b, 0x00, 0x40,
- 0x00, 0x72, 0x00, 0xe5, 0x66, 0x00, 0x6b, 0x1a, 0x72, 0x25, 0x73, 0x59,
- 0x74, 0x66, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x26, 0x40,
- 0x07, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x73, 0x08, 0x00, 0x93,
- 0x40, 0x06, 0x6f, 0x63, 0x6b, 0x00, 0xe2, 0x6d, 0x00, 0x77, 0x0d, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x63,
- 0x02, 0x68, 0x08, 0x6d, 0x11, 0x73, 0x17, 0x00, 0x26, 0x40, 0x06, 0x61,
- 0x6b, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x07, 0x65, 0x61, 0x6c, 0x00, 0x00, 0x07, 0xfd, 0x00, 0x00, 0x00,
- 0x62, 0x02, 0x00, 0x64, 0x0b, 0x00, 0x65, 0x2d, 0x00, 0x66, 0x74, 0x00,
- 0x69, 0x8f, 0x00, 0x6a, 0xa3, 0x00, 0x6c, 0x12, 0x01, 0x6e, 0xbc, 0x01,
- 0x6f, 0xdb, 0x01, 0x73, 0xe7, 0x01, 0x74, 0xa6, 0x03, 0x76, 0x03, 0x04,
- 0x00, 0x08, 0x40, 0x09, 0x6c, 0x69, 0x67, 0x61, 0x74, 0x6f, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x64, 0x00,
- 0x69, 0x14, 0x6c, 0x28, 0x73, 0x2e, 0x79, 0x3a, 0xe1, 0x69, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x84,
- 0x65, 0x00, 0x00, 0x7d, 0xe1, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x00,
- 0x40, 0x09, 0x69, 0x73, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x02, 0xef, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00,
- 0x09, 0x40, 0x06, 0x61, 0x72, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x75, 0x50, 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6f, 0x3d, 0x03, 0xed, 0xe3, 0x66, 0x00, 0x6f, 0x04,
- 0x76, 0x1d, 0x42, 0x3e, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0xc0, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x12, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x69, 0x0f, 0x6f, 0x95, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x03, 0xee, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x67, 0x00, 0x71,
- 0x2e, 0x74, 0x48, 0x76, 0x60, 0xe3, 0x61, 0x00, 0x65, 0x20, 0x69, 0x22,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x8c,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x00, 0x00, 0x83, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x02, 0x12, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x6e, 0x00, 0x75, 0x02, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6e,
- 0x00, 0x71, 0x04, 0x40, 0x09, 0x67, 0x00, 0x40, 0x07, 0x75, 0x79, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x78, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x09, 0x73, 0x74, 0x00, 0xf5, 0x63, 0x00, 0x00, 0x65,
- 0x3a, 0x00, 0x69, 0xdb, 0x00, 0x6f, 0xe2, 0x00, 0x74, 0x09, 0x01, 0xe2,
- 0x65, 0x00, 0x75, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0xda, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x15, 0x69, 0x17, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x00, 0x06, 0x03, 0xef, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe3, 0x71, 0x00,
- 0x72, 0x26, 0x73, 0x6d, 0xe1, 0x75, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1c,
- 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x76, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x32, 0xe3, 0x62, 0x00, 0x6e, 0x05, 0x74, 0x10, 0x40, 0x00, 0x6c,
- 0x79, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0x00,
- 0x3b, 0xe2, 0x69, 0x00, 0x6f, 0x11, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x02,
- 0x94, 0x00, 0x37, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x01, 0xde, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0x46, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x64, 0x69, 0x61, 0x6e, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x18, 0xe1, 0x63, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3a, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0x40, 0x0b, 0x65, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x06, 0x69, 0x28, 0x72, 0x3b, 0x40, 0x09, 0x63,
- 0x6c, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x73, 0x0b,
- 0x00, 0x08, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00,
- 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x79, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x75,
- 0x1f, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x02, 0x3d, 0x40,
- 0x37, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x16, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x61,
- 0x00, 0x72, 0x1b, 0x75, 0x43, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x6d, 0x08, 0x03, 0xf0, 0x40, 0x37, 0x62, 0x6c,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x04, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x02, 0xb1, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03,
- 0x3c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06,
- 0x40, 0x06, 0x72, 0x73, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x0f, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xf7, 0x61, 0x00,
- 0x00, 0x63, 0x07, 0x00, 0x65, 0xc3, 0x00, 0x68, 0x17, 0x01, 0x6b, 0x22,
- 0x01, 0x74, 0x27, 0x01, 0x75, 0x6f, 0x01, 0x40, 0x09, 0x72, 0x69, 0x6e,
- 0x61, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x17, 0x6c, 0x20, 0x75, 0x3c, 0xe1,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x59, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06,
- 0x64, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x64,
- 0x00, 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3,
- 0x6c, 0x00, 0x70, 0x16, 0x72, 0x53, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x69, 0x28, 0x79, 0x34, 0xe2,
- 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x75, 0x40, 0x3b, 0x6c,
- 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x06, 0x00, 0xab, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x76,
- 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x77,
- 0x40, 0x06, 0x63, 0x65, 0x00, 0x40, 0x77, 0x6e, 0x67, 0x00, 0xe2, 0x61,
- 0x00, 0x6c, 0x4a, 0xe1, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x67,
- 0x09, 0x69, 0x10, 0x6f, 0x14, 0x00, 0x06, 0x40, 0x06, 0x72, 0x6f, 0x6e,
- 0x74, 0x00, 0x40, 0x00, 0x6f, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x63,
- 0x00, 0xe2, 0x67, 0x00, 0x6c, 0x1d, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79,
- 0x08, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00, 0x63, 0x00, 0x00, 0x07, 0x40,
- 0x07, 0x6f, 0x67, 0x79, 0x00, 0x40, 0x09, 0x6f, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x1d, 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x65,
- 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x29, 0x6f, 0x2d, 0xe4, 0x67, 0x00,
- 0x6c, 0x11, 0x6e, 0x13, 0x76, 0x17, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x00,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x09,
- 0x00, 0x09, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x67, 0x00, 0x70, 0x0a, 0x40,
- 0x06, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x09, 0x75,
- 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe6, 0x61, 0x00, 0x64, 0x09,
- 0x65, 0x31, 0x69, 0x33, 0x6f, 0x4f, 0x79, 0x7a, 0x40, 0x06, 0x6c, 0x69,
- 0x73, 0x71, 0x75, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x69, 0x08,
- 0x6d, 0x0d, 0x6e, 0x13, 0x73, 0x19, 0x03, 0xf1, 0x40, 0x06, 0x61, 0x6c,
- 0x6c, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0x00, 0x06, 0xe2,
- 0x6f, 0x00, 0x75, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x6d, 0x00, 0xe2, 0x6d, 0x00, 0x72, 0x07, 0x40, 0x09, 0x65, 0x74,
- 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x0b, 0x6f, 0x11,
- 0x00, 0xb2, 0x40, 0x00, 0x66, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x00, 0x40,
- 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x09,
- 0x73, 0x73, 0x65, 0x79, 0x00, 0xe3, 0x64, 0x00, 0x6e, 0x07, 0x75, 0x1c,
- 0x40, 0x00, 0x69, 0x70, 0x61, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6c,
- 0x00, 0x70, 0x06, 0x40, 0x07, 0x6f, 0x67, 0x79, 0x00, 0x40, 0x06, 0x68,
- 0x69, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x76, 0x72, 0x65, 0x00, 0xf3, 0x00,
- 0x00, 0x00, 0x66, 0x02, 0x00, 0x74, 0x71, 0x01, 0x00, 0x00, 0xfa, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x06, 0x00, 0x65, 0x0c, 0x00, 0x68,
- 0x5f, 0x00, 0x69, 0x7f, 0x00, 0x6c, 0xee, 0x00, 0x70, 0xfd, 0x00, 0x73,
- 0x04, 0x01, 0x74, 0x49, 0x01, 0x03, 0xf2, 0x40, 0x07, 0x6c, 0x00, 0x40,
- 0x09, 0x65, 0x61, 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x3a, 0xe3, 0x63,
- 0x00, 0x64, 0x04, 0x73, 0x0f, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x3f, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00,
- 0x27, 0x02, 0x6e, 0x06, 0x73, 0x0c, 0x00, 0xd7, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x53, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x74, 0x07, 0x03, 0xf3, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x6f, 0x72, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x63, 0x00, 0x6e, 0x60, 0x73, 0x64, 0xe2, 0x65, 0x00, 0x69, 0x13,
- 0xe3, 0x00, 0x00, 0x68, 0x02, 0x72, 0x0a, 0x00, 0xeb, 0x40, 0x06, 0x6f,
- 0x6c, 0x64, 0x65, 0x72, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x30,
- 0xe3, 0x6c, 0x00, 0x6e, 0x1a, 0x74, 0x1e, 0xe4, 0x00, 0x00, 0x64, 0x02,
- 0x65, 0x07, 0x69, 0x0c, 0x00, 0x86, 0x40, 0x07, 0x6f, 0x6d, 0x00, 0x40,
- 0x00, 0x73, 0x65, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x3a, 0x40, 0x09, 0x72, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x67, 0x00, 0x40,
- 0x00, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6e, 0x65,
- 0x00, 0x40, 0x7a, 0x61, 0x64, 0x00, 0x40, 0x06, 0x72, 0x69, 0x6e, 0x74,
- 0x00, 0xe5, 0x65, 0x00, 0x68, 0x10, 0x69, 0x20, 0x70, 0x2d, 0x74, 0x34,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x04,
- 0x40, 0x09, 0x74, 0x00, 0x40, 0x1c, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x74,
- 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x72,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x61, 0x67, 0x65, 0x00, 0x40, 0x00,
- 0x72, 0x61, 0x63, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x74, 0x13,
- 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x60,
- 0x40, 0x00, 0x69, 0x6d, 0x65, 0x73, 0x00, 0x40, 0x00, 0x69, 0x6d, 0x65,
- 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x09, 0x40, 0x00, 0x73, 0x68, 0x00,
- 0x40, 0x09, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x6f, 0x10, 0x73,
- 0x12, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0x40, 0x09,
- 0x65, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00,
- 0x6b, 0x02, 0x6c, 0x04, 0x6e, 0x5f, 0x00, 0x00, 0x00, 0x08, 0xe7, 0x00,
- 0x00, 0x63, 0x02, 0x66, 0x1d, 0x69, 0x24, 0x6d, 0x2b, 0x73, 0x38, 0x79,
- 0x4a, 0x00, 0x93, 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40, 0x08, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x08, 0x69, 0x65, 0x6c, 0x64,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6b, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x09, 0x00, 0x07, 0x01, 0x15, 0xe2, 0x6b, 0x00, 0x74, 0x02, 0x00, 0x47,
- 0x40, 0x06, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x0b,
- 0xe2, 0x70, 0x00, 0x79, 0x04, 0x40, 0x06, 0x69, 0x00, 0x03, 0x2a, 0x40,
- 0x09, 0x61, 0x00, 0xe4, 0x64, 0x00, 0x65, 0x22, 0x66, 0x50, 0x69, 0x59,
- 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x0d, 0x73, 0x13, 0x03, 0xf4, 0xe2,
- 0x65, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x00, 0x68, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x6f, 0x15, 0x00, 0x98, 0xe2, 0x67, 0x00, 0x6e, 0x08,
- 0x40, 0x00, 0x69, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x09, 0x64, 0x65,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x07, 0x40, 0x07, 0x61,
- 0x72, 0x67, 0x61, 0x72, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x61, 0x63,
- 0x74, 0x6f, 0x72, 0x79, 0x00, 0xe2, 0x67, 0x00, 0x76, 0x42, 0xe2, 0x61,
- 0x00, 0x6f, 0x26, 0xe1, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00,
- 0xe4, 0x00, 0x00, 0x69, 0x02, 0x73, 0x10, 0x79, 0x12, 0x00, 0x07, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x00, 0x00, 0x00, 0x00, 0x06, 0xe2, 0x6e, 0x00, 0x70, 0x0c, 0x40, 0x08,
- 0x75, 0x63, 0x6c, 0x65, 0x6f, 0x74, 0x69, 0x64, 0x65, 0x00, 0x40, 0x06,
- 0x6f, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x62,
- 0x02, 0x65, 0x1b, 0x69, 0x39, 0x6e, 0x7a, 0x00, 0xcc, 0xe1, 0x75, 0x00,
- 0xe1, 0x64, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x67,
- 0x00, 0x6c, 0x04, 0x6e, 0x15, 0x40, 0x06, 0x61, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40, 0x09,
- 0x65, 0x00, 0x00, 0x07, 0xe4, 0x63, 0x00, 0x6e, 0x06, 0x73, 0x1c, 0x74,
- 0x23, 0x40, 0x09, 0x72, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x73, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x69, 0x00,
- 0xe4, 0x62, 0x00, 0x70, 0x05, 0x73, 0x35, 0x76, 0x4c, 0x40, 0x09, 0x75,
- 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x14, 0xe1, 0x74, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02,
- 0x00, 0x09, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xfd, 0x00, 0x00,
- 0x00, 0x63, 0x02, 0x00, 0x65, 0x2e, 0x00, 0x67, 0x63, 0x00, 0x69, 0x6a,
- 0x00, 0x6c, 0x7d, 0x00, 0x6f, 0x9b, 0x00, 0x72, 0xc3, 0x00, 0x73, 0xc9,
- 0x00, 0x74, 0x02, 0x01, 0x75, 0x27, 0x01, 0x77, 0x2b, 0x01, 0x79, 0x31,
- 0x01, 0x00, 0x3b, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x07, 0xe3, 0x67,
- 0x00, 0x6c, 0x06, 0x6d, 0x18, 0x40, 0x06, 0x65, 0x6e, 0x65, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06,
- 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe5,
- 0x00, 0x00, 0x6e, 0x02, 0x72, 0x08, 0x73, 0x1e, 0x74, 0x24, 0x03, 0xf5,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x6c, 0x66, 0x00, 0x40, 0x00,
- 0x69, 0x6d, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x69, 0x6e, 0x67, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x6b, 0x69, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x00, 0x6e, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00,
- 0x74, 0x09, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0x43, 0x2a, 0x75, 0x73, 0x68, 0x00, 0xe6, 0x63,
- 0x00, 0x65, 0x07, 0x68, 0x0b, 0x69, 0x11, 0x6c, 0x1e, 0x74, 0x26, 0x40,
- 0x00, 0x72, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x09, 0x74, 0x00, 0x40, 0x00,
- 0x6f, 0x72, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x04, 0x40, 0x00, 0x65,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x09, 0x61, 0x75, 0x67, 0x68, 0x74,
- 0x00, 0x40, 0x00, 0x61, 0x67, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe3, 0x00,
- 0x00, 0x67, 0x02, 0x6c, 0x08, 0x00, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x79,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06,
- 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x09, 0x73, 0x00,
- 0x40, 0x00, 0x61, 0x72, 0x64, 0x00, 0x40, 0x09, 0x78, 0x00, 0xe5, 0x64,
- 0x00, 0x68, 0x06, 0x6d, 0x0f, 0x70, 0x14, 0x7a, 0x18, 0x40, 0x07, 0x6c,
- 0x65, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xed, 0x00, 0x00,
- 0x40, 0x00, 0x70, 0x68, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x82, 0x00, 0x60, 0xfa, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x63, 0x40, 0x00, 0x65, 0x46, 0x00, 0x68, 0x02, 0x01, 0x69, 0x2f,
- 0x01, 0x6f, 0x59, 0x01, 0x70, 0x60, 0x01, 0x74, 0x12, 0x02, 0x75, 0xa3,
- 0x02, 0x00, 0x2c, 0xe3, 0x63, 0x00, 0x6c, 0x06, 0x71, 0x24, 0x40, 0x07,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0xe1,
- 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0xf6, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08, 0x6f, 0x64, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x6e, 0x02, 0x72, 0x63, 0x00, 0x08, 0xe8, 0x00, 0x00, 0x63,
- 0x02, 0x65, 0x08, 0x68, 0x11, 0x69, 0x37, 0x6e, 0x3c, 0x73, 0x42, 0x77,
- 0x4a, 0x03, 0xf7, 0x40, 0x00, 0x61, 0x73, 0x74, 0x00, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0xe2, 0x61, 0x00, 0x65, 0x19, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x61, 0x72, 0x74, 0x65, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x47, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6e, 0x07, 0x74, 0x0b, 0x00,
- 0x09, 0x40, 0x54, 0x6c, 0x65, 0x00, 0x40, 0x08, 0x64, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x28, 0x02, 0x7d, 0xe3, 0x63, 0x00, 0x6f, 0x0d,
- 0x76, 0x1b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x07, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x06, 0x74, 0x74, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x04, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73,
- 0x74, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x6e, 0x05, 0x75, 0x1f, 0x40,
- 0x06, 0x74, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x51, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x74, 0x65, 0x64, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x09,
- 0x73, 0x73, 0x75, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x72, 0x63,
- 0x00, 0x00, 0xe3, 0x6e, 0x00, 0x72, 0x06, 0x73, 0x3d, 0x40, 0x06, 0x65,
- 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x5c, 0xe2, 0x73, 0x00, 0x74, 0x1e,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x3a, 0x00, 0x37,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0xf8, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x2c, 0xe1, 0x73, 0x00, 0xe1,
- 0x73, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x1b, 0x01, 0xde, 0xe2,
- 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x72, 0x00, 0x5b,
- 0xe3, 0x63, 0x00, 0x6d, 0x16, 0x6f, 0x5b, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x06, 0x73, 0x0b, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06,
- 0x61, 0x6e, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x69, 0x09, 0x75, 0x3a,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x3b, 0xe2, 0x73, 0x00,
- 0x7a, 0x1e, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0xf9, 0x40, 0x06,
- 0x6d, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x2c,
- 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73,
- 0x74, 0x00, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x73, 0x11, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x3b, 0x00, 0x09, 0xff, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62,
- 0x64, 0x00, 0x63, 0x88, 0x00, 0x64, 0xc2, 0x00, 0x65, 0x4a, 0x01, 0x67,
- 0x57, 0x01, 0x69, 0x08, 0x02, 0x6d, 0xa6, 0x02, 0x6e, 0xac, 0x02, 0x6f,
- 0x1d, 0x03, 0x70, 0x35, 0x03, 0x72, 0x4a, 0x03, 0x74, 0x4f, 0x03, 0x7a,
- 0xde, 0x03, 0x00, 0x00, 0xe4, 0x63, 0x00, 0x6c, 0x0f, 0x6e, 0x11, 0x74,
- 0x31, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00,
- 0x6c, 0x61, 0x72, 0x00, 0x00, 0x86, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x75, 0x12, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x72, 0x07, 0x02, 0x7b, 0x40,
- 0x09, 0x64, 0x65, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x06, 0x74, 0x61,
- 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x51, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x79, 0x0e, 0x00, 0x06, 0xe2, 0x63, 0x00, 0x6f, 0x05, 0x40, 0x3b, 0x61,
- 0x6c, 0x00, 0x00, 0x09, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0xe2, 0x63, 0x00, 0x74, 0x07, 0x40, 0x00, 0x75, 0x6c, 0x61, 0x72,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x00, 0xfe, 0x40, 0x06,
- 0x6c, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00,
- 0x08, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x28, 0x40, 0x06, 0x72, 0x64,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x74, 0x04, 0x00, 0x09, 0x00, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x64, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x13, 0x69, 0x39, 0x6e,
- 0x71, 0x75, 0x78, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x91, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x61,
- 0x00, 0x72, 0x04, 0x40, 0x06, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6c, 0x08, 0x03, 0xfa, 0x40, 0x00, 0x6e, 0x67, 0x73, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x07, 0x40, 0x84, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x6e,
- 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe4, 0x6c, 0x00, 0x6e, 0x02, 0x72,
- 0x07, 0x74, 0x1d, 0x00, 0x06, 0x40, 0x06, 0x63, 0x65, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x02, 0x7b, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x03, 0xb4, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x61, 0x6e,
- 0x63, 0x65, 0x00, 0x40, 0x07, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x67,
- 0x02, 0x00, 0x06, 0x40, 0x07, 0x61, 0x6e, 0x6f, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x9e, 0x79, 0xa6, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x73,
- 0x89, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x65, 0x06, 0x69, 0x0c, 0x7a, 0x7a,
- 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0x40, 0x09, 0x6c, 0x6c, 0x65, 0x00,
- 0xe3, 0x63, 0x00, 0x73, 0x0d, 0x7a, 0x3e, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0x40, 0x54, 0x6c, 0x6c, 0x79, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x17, 0x6d, 0x1b, 0x74, 0x26, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x00, 0x09, 0xe2, 0x61, 0x00,
- 0x65, 0x17, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x40, 0x3b, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x00, 0xb3, 0x00, 0x37,
- 0x00, 0x09, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00, 0x61, 0x73,
- 0x74, 0x69, 0x63, 0x00, 0x00, 0x06, 0xe5, 0x65, 0x00, 0x66, 0x48, 0x67,
- 0x4e, 0x6f, 0x89, 0x73, 0x8e, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x09,
- 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x2d,
- 0x03, 0xfb, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x0c, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x08, 0x73, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x03, 0xfc, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xc2, 0x00, 0x00, 0x40, 0x00, 0x65,
- 0x72, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x69, 0x63, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x00, 0x40, 0x07, 0x6d, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe2,
- 0x6c, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06,
- 0x6c, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x6f, 0x6c,
- 0x75, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x32, 0x69, 0x43, 0xe2, 0x6d, 0x00,
- 0x74, 0x1d, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x93, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x0c, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x2c, 0x40,
- 0x09, 0x67, 0x65, 0x00, 0x40, 0x09, 0x69, 0x73, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x6f, 0x00, 0xe3, 0x64, 0x00, 0x67, 0x2d, 0x70, 0x67, 0xe1, 0x6f,
- 0x00, 0xe2, 0x6e, 0x00, 0x78, 0x1c, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe3, 0x61, 0x00, 0x63, 0x02, 0x73, 0x0b, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x06, 0xe2, 0x6f, 0x00, 0x72, 0x15,
- 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x79, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x10, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x08, 0x00, 0x07, 0x40, 0x09, 0x74, 0x00, 0x40, 0x07, 0x6f, 0x00,
- 0xf6, 0x63, 0x00, 0x00, 0x69, 0x4a, 0x00, 0x6d, 0x4f, 0x00, 0x70, 0x68,
- 0x00, 0x73, 0x6e, 0x00, 0x74, 0x84, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x30,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x1d, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x39, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x06, 0x00, 0x00, 0x40, 0x09, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x65,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x75, 0x6d, 0x00,
- 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x07, 0x69, 0x73, 0x00, 0x40, 0x00,
- 0x69, 0x63, 0x00, 0x40, 0x06, 0x72, 0x65, 0x79, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x02, 0x3e, 0xe3, 0x65, 0x00, 0x6c, 0x69,
- 0x72, 0x6e, 0xe2, 0x6e, 0x00, 0x6f, 0x2e, 0xe2, 0x73, 0x00, 0x74, 0x12,
- 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00,
- 0x07, 0x40, 0x3b, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x70, 0x0b, 0x40, 0x07,
- 0x72, 0x74, 0x68, 0x72, 0x69, 0x74, 0x69, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x19, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x69,
- 0x02, 0x73, 0x06, 0x79, 0x08, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x00, 0x00, 0x07, 0x40, 0x07, 0x72, 0x6f, 0x73, 0x69, 0x73, 0x00, 0x40,
- 0x08, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x13, 0xe1, 0x63, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6d, 0x00,
- 0x40, 0x0b, 0x65, 0x00, 0x40, 0x09, 0x63, 0x68, 0x00, 0xe3, 0x68, 0x00,
- 0x69, 0x1f, 0x74, 0x25, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x77, 0x02, 0x03, 0xfd, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00,
- 0x73, 0x65, 0x00, 0x40, 0x00, 0x72, 0x6c, 0x64, 0x6c, 0x79, 0x00, 0x40,
- 0x00, 0x6f, 0x73, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x09, 0x6d, 0x61, 0x6e, 0x00, 0xf8, 0x62, 0x00, 0x00,
- 0x63, 0x09, 0x00, 0x67, 0x0d, 0x00, 0x6e, 0x1f, 0x00, 0x72, 0x24, 0x00,
- 0x73, 0x33, 0x00, 0x74, 0x41, 0x00, 0x7a, 0x00, 0x05, 0x40, 0x09, 0x6c,
- 0x69, 0x65, 0x74, 0x74, 0x65, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x27, 0x74, 0x00, 0x40, 0x09, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x08, 0x40, 0x00, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3f, 0x40, 0x07,
- 0x72, 0x00, 0xc1, 0x61, 0x17, 0x33, 0x00, 0x35, 0x00, 0x44, 0x00, 0xa2,
- 0x00, 0xda, 0x00, 0x33, 0x01, 0x47, 0x01, 0xaf, 0x01, 0x03, 0x02, 0x1e,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x23, 0x02, 0x7a, 0x02, 0x97, 0x02, 0x00,
- 0x00, 0x9f, 0x02, 0x00, 0x00, 0x15, 0x03, 0x75, 0x03, 0x59, 0x04, 0x00,
- 0x00, 0x67, 0x04, 0x6d, 0x04, 0x03, 0xfe, 0xe2, 0x67, 0x00, 0x72, 0x04,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x0b, 0x67, 0x75, 0x65, 0x00, 0xe5, 0x61,
- 0x00, 0x69, 0x10, 0x6f, 0x20, 0x72, 0x3b, 0x75, 0x41, 0xe2, 0x63, 0x00,
- 0x6c, 0x04, 0x40, 0x09, 0x6b, 0x00, 0x40, 0x3a, 0x61, 0x6e, 0x63, 0x65,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x08, 0x40,
- 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x75, 0x0d, 0x78, 0x12,
- 0xe2, 0x72, 0x00, 0x73, 0x04, 0x40, 0x09, 0x64, 0x00, 0x40, 0x3a, 0x74,
- 0x00, 0x40, 0x00, 0x6e, 0x64, 0x00, 0x00, 0x09, 0x40, 0x09, 0x65, 0x61,
- 0x6b, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x08, 0x40, 0x09, 0x6c, 0x64, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x6c,
- 0x05, 0x6f, 0x0b, 0x72, 0x10, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x3a,
- 0x61, 0x73, 0x73, 0x00, 0x40, 0x09, 0x6d, 0x65, 0x00, 0xe2, 0x6f, 0x00,
- 0x79, 0x18, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x06, 0x6e,
- 0x67, 0x00, 0x00, 0x06, 0xe4, 0x61, 0x00, 0x69, 0x06, 0x6f, 0x15, 0x72,
- 0x3b, 0x40, 0x00, 0x74, 0x65, 0x64, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x02,
- 0x00, 0x00, 0x40, 0x0b, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x6e, 0x06, 0x6f, 0x0a, 0x00, 0x1c, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x08, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x0c, 0xe1, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3c, 0x00, 0x00, 0x40, 0x00, 0x77, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x6d, 0x00, 0x77, 0x06, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0x40,
- 0x07, 0x65, 0x61, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x0d, 0x6c, 0x44,
- 0x6f, 0x52, 0xe2, 0x63, 0x00, 0x6c, 0x04, 0x40, 0x0b, 0x65, 0x00, 0x40,
- 0x08, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x67, 0x11, 0x74, 0x16, 0xe1, 0x6c,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x24, 0x40,
- 0x07, 0x72, 0x00, 0x41, 0x21, 0x68, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x05, 0x40, 0xad, 0x6e, 0x6b, 0x00, 0x40, 0x09, 0x77, 0x00,
- 0xe2, 0x75, 0x00, 0x78, 0x06, 0x40, 0x00, 0x67, 0x68, 0x74, 0x00, 0x00,
- 0x0b, 0xe3, 0x6f, 0x00, 0x72, 0x0b, 0x75, 0x2e, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x03, 0xff, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04,
- 0x40, 0x00, 0x77, 0x00, 0xe1, 0x77, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02,
- 0x74, 0x04, 0x04, 0x00, 0x00, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x05, 0x40,
- 0x0b, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x08, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x10, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x75, 0x73, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00,
- 0x65, 0x30, 0x69, 0x34, 0x6f, 0x41, 0x79, 0x46, 0xe5, 0x69, 0x00, 0x6e,
- 0x04, 0x73, 0x1d, 0x77, 0x21, 0x79, 0x23, 0x40, 0x00, 0x64, 0x00, 0xe1,
- 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x3a, 0x74, 0x00, 0x00, 0x93, 0x02, 0x1a, 0x40, 0x06, 0x74, 0x00,
- 0xe2, 0x6e, 0x00, 0x76, 0x04, 0x40, 0x82, 0x65, 0x00, 0x40, 0x0b, 0x65,
- 0x00, 0x40, 0x09, 0x6f, 0x6b, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x12, 0xe2, 0x6e, 0x00, 0x74, 0x08, 0x40, 0x0b,
- 0x65, 0x75, 0x76, 0x65, 0x72, 0x00, 0x40, 0x0b, 0x63, 0x68, 0x00, 0x40,
- 0x00, 0x64, 0x65, 0x64, 0x00, 0x40, 0x3a, 0x75, 0x6d, 0x62, 0x65, 0x72,
- 0x00, 0xe6, 0x61, 0x00, 0x65, 0x10, 0x6c, 0x18, 0x6f, 0x32, 0x72, 0x49,
- 0x75, 0x51, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x0b, 0x65, 0x00, 0x40,
- 0x09, 0x69, 0x65, 0x6e, 0x74, 0x00, 0x40, 0xad, 0x72, 0x66, 0x6f, 0x72,
- 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x79, 0x10, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x04, 0x01, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x00, 0x0b, 0xe3, 0x69, 0x00, 0x73, 0x05, 0x75, 0x09, 0x40,
- 0x72, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x74, 0x00, 0x40, 0x09, 0x72, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x3a, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4,
- 0x61, 0x00, 0x65, 0x23, 0x69, 0x2f, 0x75, 0x47, 0xe3, 0x63, 0x00, 0x67,
- 0x04, 0x6e, 0x13, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x82, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x47, 0x63, 0x68, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x05,
- 0x40, 0x09, 0x65, 0x72, 0x00, 0xe2, 0x67, 0x00, 0x68, 0x05, 0x40, 0x06,
- 0x65, 0x72, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x08, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe9,
- 0x63, 0x00, 0x65, 0x06, 0x68, 0x11, 0x69, 0x28, 0x6b, 0x3d, 0x6d, 0x43,
- 0x6f, 0x49, 0x70, 0x64, 0x74, 0x93, 0x40, 0x0b, 0x6f, 0x72, 0x65, 0x00,
- 0xe2, 0x6c, 0x00, 0x74, 0x04, 0x40, 0x3c, 0x6c, 0x00, 0x00, 0x06, 0xe2,
- 0x69, 0x00, 0x6f, 0x05, 0x40, 0x3c, 0x6e, 0x65, 0x00, 0xe2, 0x6e, 0x00,
- 0x75, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x0b, 0x74, 0x00, 0xe2, 0x64,
- 0x00, 0x7a, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0xeb, 0x00, 0x07, 0x40, 0x09, 0x65, 0x00, 0x40, 0x09, 0x69, 0x72, 0x74,
- 0x00, 0x40, 0x0b, 0x61, 0x72, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x3a, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x65,
- 0x00, 0x6f, 0x0c, 0x72, 0x22, 0xe1, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x74,
- 0x02, 0x01, 0x21, 0x00, 0x00, 0xe1, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x3c, 0x65, 0x61, 0x64, 0x00, 0xe2, 0x61, 0x00,
- 0x72, 0x16, 0xe3, 0x6e, 0x00, 0x74, 0x07, 0x79, 0x0d, 0x40, 0x3b, 0x64,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x72,
- 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x3a, 0x74, 0x63, 0x68, 0x00, 0xe1,
- 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x0b, 0x6f, 0x74, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05,
- 0x69, 0x1d, 0x6f, 0x39, 0x42, 0xde, 0x72, 0x64, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x04, 0x40, 0x3c, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xed, 0x00, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x68, 0x02, 0x74, 0x04, 0x00, 0x08, 0x00, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x6b, 0x02, 0x6e, 0x04, 0x00,
- 0x00, 0x00, 0xe7, 0x00, 0x00, 0x40, 0x09, 0x6f, 0x00, 0xf5, 0x61, 0x00,
- 0x00, 0x65, 0x25, 0x00, 0x69, 0x1e, 0x09, 0x6f, 0x31, 0x09, 0x75, 0x36,
- 0x09, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x04, 0x74, 0x10, 0x00, 0x00,
- 0x00, 0x09, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x61, 0x6e, 0x00,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0xee, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xf2, 0x6e, 0x00, 0x00, 0x72, 0x1e, 0x00, 0xe4, 0x00, 0x00,
- 0x62, 0x02, 0x70, 0x08, 0x77, 0x0f, 0x00, 0x09, 0x40, 0x06, 0x69, 0x72,
- 0x64, 0x00, 0x40, 0x00, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0x40, 0x00, 0x61,
- 0x72, 0x65, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00, 0xd5, 0x00,
- 0x5c, 0x01, 0x2f, 0x02, 0xb9, 0x02, 0x5e, 0x03, 0xa4, 0x03, 0xec, 0x03,
- 0x28, 0x04, 0x4c, 0x04, 0x51, 0x04, 0x57, 0x04, 0xc1, 0x04, 0xf0, 0x04,
- 0x01, 0x05, 0x1f, 0x05, 0xba, 0x05, 0xc5, 0x05, 0x2d, 0x06, 0xd7, 0x07,
- 0x47, 0x08, 0x4c, 0x08, 0x6a, 0x08, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x08,
- 0x00, 0x86, 0xe9, 0x62, 0x00, 0x63, 0x1a, 0x67, 0x36, 0x6c, 0x47, 0x6d,
- 0x53, 0x6e, 0x5d, 0x72, 0x65, 0x74, 0x73, 0x77, 0x83, 0xe1, 0x75, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2,
- 0x68, 0x00, 0x74, 0x15, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x76,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00,
- 0x07, 0x01, 0xeb, 0xe2, 0x65, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x72, 0x65, 0x73, 0x73, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x00, 0x62, 0x69,
- 0x74, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x00, 0x78, 0x69, 0x6f, 0x75,
- 0x73, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x07, 0x40, 0x00, 0x68, 0x69, 0x6e,
- 0x67, 0x00, 0x00, 0xad, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x65, 0x6e, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x3a, 0x65, 0x00,
- 0xe6, 0x61, 0x00, 0x65, 0x08, 0x69, 0x1a, 0x6c, 0x30, 0x6f, 0x36, 0x75,
- 0x5f, 0x40, 0x82, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3c, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x0d, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x00, 0x6f, 0x77, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x6c, 0x05,
- 0x6f, 0x09, 0x72, 0x0d, 0x75, 0x18, 0x40, 0x00, 0x72, 0x64, 0x00, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x72, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x67, 0x68, 0x74, 0x00,
- 0xe3, 0x69, 0x00, 0x72, 0x0c, 0x79, 0x12, 0xe1, 0x6c, 0x00, 0xe2, 0x64,
- 0x00, 0x74, 0x02, 0x01, 0x21, 0x00, 0x00, 0x40, 0xad, 0x64, 0x65, 0x6e,
- 0x00, 0x00, 0x3c, 0xe5, 0x61, 0x00, 0x68, 0x37, 0x6c, 0x3e, 0x6f, 0x4e,
- 0x72, 0xa9, 0xe5, 0x6d, 0x00, 0x70, 0x04, 0x72, 0x19, 0x73, 0x20, 0x75,
- 0x24, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x07, 0x40, 0x07,
- 0x63, 0x69, 0x74, 0x79, 0x00, 0x40, 0x3a, 0x74, 0x61, 0x6c, 0x69, 0x7a,
- 0x65, 0x00, 0x40, 0x00, 0x65, 0x66, 0x75, 0x6c, 0x00, 0x41, 0x7f, 0x74,
- 0x00, 0x40, 0x00, 0x74, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x5e, 0x61,
- 0x72, 0x67, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x63, 0x00, 0x75, 0x04,
- 0x40, 0xed, 0x6b, 0x00, 0x40, 0x5b, 0x64, 0x00, 0xe4, 0x61, 0x00, 0x6d,
- 0x04, 0x6e, 0x26, 0x6f, 0x4e, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x70, 0x02, 0x00, 0x3c, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x66, 0x00, 0x73, 0x17,
- 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x40,
- 0x72, 0x6b, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x08, 0x40, 0x00, 0x74, 0x69,
- 0x63, 0x61, 0x6c, 0x00, 0xe1, 0x77, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x7a, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe5, 0x65,
- 0x00, 0x69, 0x1f, 0x6f, 0x23, 0x72, 0x3a, 0x75, 0x63, 0xe3, 0x63, 0x00,
- 0x70, 0x08, 0x76, 0x11, 0x40, 0x3a, 0x6f, 0x72, 0x61, 0x74, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x7a, 0x65,
- 0x6c, 0x6f, 0x70, 0x00, 0x40, 0x00, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x6e, 0x06, 0x73, 0x0a, 0x00, 0x1c, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x12,
- 0x69, 0x1d, 0xe2, 0x66, 0x00, 0x77, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3c, 0x00, 0x00, 0xe2, 0x73, 0x00, 0x77,
- 0x04, 0x40, 0x59, 0x73, 0x00, 0x00, 0x00, 0x40, 0x06, 0x76, 0x65, 0x00,
- 0xe2, 0x62, 0x00, 0x65, 0x15, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x06,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x00, 0x00, 0xe5, 0x61, 0x00, 0x6d, 0x0c, 0x6e, 0x31, 0x73,
- 0x3e, 0x78, 0x59, 0xe2, 0x67, 0x00, 0x74, 0x05, 0x40, 0x00, 0x65, 0x72,
- 0x00, 0x04, 0x02, 0xe2, 0x6f, 0x00, 0x70, 0x09, 0x40, 0x00, 0x74, 0x69,
- 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x02, 0x00, 0x07,
- 0x40, 0x0b, 0x65, 0x00, 0x40, 0x00, 0x74, 0x68, 0x75, 0x73, 0x69, 0x61,
- 0x73, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x01, 0x86, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x63, 0x00, 0x65,
- 0x06, 0x70, 0x20, 0x74, 0x32, 0x40, 0x3a, 0x69, 0x74, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x06, 0x40, 0x0b, 0x69, 0x73, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x7a, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x02,
- 0x00, 0x0b, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x72, 0x65, 0x6e, 0x64,
- 0x00, 0xe5, 0x65, 0x00, 0x69, 0x0b, 0x6c, 0x10, 0x6f, 0x31, 0x75, 0x36,
- 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x3c, 0x64, 0x00, 0x40,
- 0x72, 0x6c, 0x6c, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x0a, 0x79,
- 0x16, 0x40, 0x00, 0x77, 0x00, 0x40, 0x09, 0x67, 0x68, 0x74, 0x00, 0xe1,
- 0x77, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x47, 0x00, 0x00, 0x00,
- 0x3c, 0x40, 0x00, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x72, 0x1a, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40, 0x3a, 0x6c, 0x69, 0x7a, 0x65,
- 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x6f,
- 0x09, 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x40, 0x00, 0x77, 0x00, 0xe2, 0x75,
- 0x00, 0x77, 0x05, 0x40, 0x00, 0x6e, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x6e,
- 0x02, 0x74, 0x04, 0x04, 0x03, 0x00, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x19, 0x75, 0x30, 0xe3, 0x6e, 0x00, 0x73, 0x09, 0x75,
- 0x0e, 0xe2, 0x64, 0x00, 0x67, 0x02, 0x00, 0xb2, 0x03, 0x2a, 0x40, 0x00,
- 0x74, 0x79, 0x00, 0x40, 0x47, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x64,
- 0x00, 0x72, 0x02, 0x74, 0x0b, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x01, 0x21, 0x00, 0x00, 0x00, 0x3a, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x0b,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0x40,
- 0xad, 0x6f, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6c, 0x6c, 0x00, 0xe5, 0x61,
- 0x00, 0x65, 0x3b, 0x69, 0x40, 0x6f, 0x44, 0x79, 0x5d, 0xe6, 0x64, 0x00,
- 0x69, 0x05, 0x6e, 0x0e, 0x70, 0x12, 0x72, 0x27, 0x79, 0x2c, 0x40, 0x00,
- 0x65, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x00, 0x67, 0x65, 0x00, 0x01, 0x2f, 0x40, 0x00, 0x61, 0x66,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x6e, 0x04, 0x6f, 0x08,
- 0x72, 0x0c, 0x40, 0x59, 0x64, 0x00, 0x40, 0x00, 0x67, 0x00, 0x40, 0x59,
- 0x6b, 0x00, 0x40, 0x09, 0x64, 0x00, 0x01, 0x21, 0xe3, 0x61, 0x00, 0x6f,
- 0x1c, 0x75, 0x23, 0xe2, 0x6e, 0x00, 0x73, 0x11, 0xe1, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x7a, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x64, 0x65, 0x73,
- 0x74, 0x00, 0x40, 0x08, 0x63, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63,
- 0x00, 0x67, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x09, 0x68, 0x74, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe4, 0x61, 0x00, 0x6c, 0x1d, 0x6f,
- 0x22, 0x72, 0x51, 0xe4, 0x69, 0x00, 0x72, 0x04, 0x73, 0x0e, 0x79, 0x12,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61,
- 0x72, 0x00, 0x40, 0x09, 0x73, 0x00, 0x00, 0x3c, 0x40, 0x0b, 0x61, 0x79,
- 0x00, 0xe2, 0x70, 0x00, 0x77, 0x18, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x7a, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0d, 0x6f, 0x1a, 0x40, 0x3a, 0x69,
- 0x73, 0x65, 0x00, 0x40, 0x00, 0x63, 0x69, 0x73, 0x65, 0x00, 0xe2, 0x63,
- 0x00, 0x6e, 0x04, 0x40, 0x3a, 0x65, 0x00, 0x40, 0x2c, 0x74, 0x00, 0xe2,
- 0x64, 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65,
- 0x00, 0x74, 0x02, 0x00, 0x0b, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x41,
- 0xe2, 0x65, 0x63, 0x74, 0x00, 0x40, 0x00, 0x75, 0x61, 0x6c, 0x69, 0x66,
- 0x69, 0x65, 0x64, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x0b, 0x69, 0x2d, 0x6f,
- 0x42, 0x75, 0x47, 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x0b,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x66, 0x16, 0xe1, 0x63, 0x00, 0xe2, 0x68,
- 0x00, 0x74, 0x02, 0x00, 0x0b, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x7a,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x64, 0x00,
- 0xe2, 0x64, 0x00, 0x70, 0x0c, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40, 0x00,
- 0x65, 0x6e, 0x00, 0x01, 0x7f, 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x64,
- 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00,
- 0xf9, 0x61, 0x00, 0x00, 0x65, 0x0f, 0x00, 0x68, 0x58, 0x00, 0x69, 0x7a,
- 0x00, 0x6c, 0xaa, 0x00, 0x6f, 0xba, 0x00, 0x70, 0xbf, 0x00, 0x74, 0xf5,
- 0x00, 0x75, 0x65, 0x01, 0xe2, 0x6d, 0x00, 0x77, 0x08, 0x40, 0x00, 0x70,
- 0x6c, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x02,
- 0x6c, 0x16, 0x6e, 0x1a, 0x78, 0x39, 0x00, 0x08, 0xe4, 0x00, 0x00, 0x69,
- 0x02, 0x6e, 0x07, 0x72, 0x09, 0x04, 0x04, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x00, 0x00, 0x00, 0x07, 0x40, 0x3c, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x05, 0x40, 0x3a, 0x6f, 0x77, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x02, 0x74, 0x06, 0x00, 0x09,
- 0x40, 0x3c, 0x74, 0x00, 0x00, 0x00, 0xe3, 0x67, 0x00, 0x6d, 0x05, 0x7a,
- 0x25, 0x40, 0x06, 0x68, 0x74, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x04, 0x05, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x70, 0x04, 0x40, 0x3c, 0x70, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00,
- 0x6c, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x2b, 0xe2, 0x63, 0x00, 0x6e,
- 0x1d, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe2, 0x64, 0x00, 0x74, 0x02, 0x01,
- 0x21, 0x00, 0x00, 0x40, 0x3c, 0x65, 0x61, 0x64, 0x00, 0xe6, 0x61, 0x00,
- 0x65, 0x1f, 0x69, 0x37, 0x6f, 0x40, 0x72, 0x45, 0x75, 0x5c, 0xe3, 0x66,
- 0x00, 0x74, 0x06, 0x79, 0x16, 0x40, 0x00, 0x66, 0x65, 0x64, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x58, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x00, 0x00, 0x3a, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x3a, 0x6d, 0x75, 0x6c, 0x61, 0x74,
- 0x65, 0x00, 0x40, 0xad, 0x63, 0x6b, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x06,
- 0x75, 0x0b, 0x40, 0x0b, 0x74, 0x63, 0x68, 0x00, 0x40, 0x00, 0x63, 0x74,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x66, 0x66, 0x65, 0x64,
- 0x00, 0xe3, 0x62, 0x00, 0x70, 0x12, 0x73, 0x18, 0xe2, 0x73, 0x00, 0x74,
- 0x08, 0x40, 0x3a, 0x63, 0x72, 0x69, 0x62, 0x65, 0x00, 0x40, 0x00, 0x6c,
- 0x65, 0x00, 0x40, 0x0b, 0x70, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x70, 0x69,
- 0x63, 0x69, 0x6f, 0x75, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x68,
- 0x15, 0x69, 0x3d, 0x6f, 0x4a, 0x75, 0x57, 0x00, 0x3b, 0xe2, 0x6b, 0x00,
- 0x78, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3c,
- 0x00, 0x00, 0x00, 0x0b, 0xe3, 0x69, 0x00, 0x6f, 0x05, 0x72, 0x0c, 0x41,
- 0x21, 0x6e, 0x6b, 0x00, 0x40, 0x00, 0x75, 0x67, 0x68, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x77, 0x00, 0xe1, 0x77, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x01, 0x25, 0x00, 0x00, 0xe2, 0x6d, 0x00, 0x72,
- 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x6e, 0x00,
- 0x6f, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x6b, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x09, 0x00, 0x3a, 0x40, 0x5e,
- 0x73, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x14, 0xe1, 0x6c, 0x00, 0xe1,
- 0x75, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x08, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x09, 0x65, 0x77, 0x00, 0xe5, 0x65, 0x00,
- 0x68, 0x12, 0x69, 0x27, 0x6f, 0x2e, 0x72, 0x33, 0xe2, 0x65, 0x00, 0x69,
- 0x07, 0x40, 0x3b, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x67, 0x68,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x5b, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40,
- 0x7a, 0x6e, 0x74, 0x65, 0x72, 0x00, 0x40, 0x59, 0x72, 0x6b, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02,
- 0x00, 0x3c, 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe2, 0x74, 0x00, 0x75, 0x04,
- 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x67, 0x68, 0x74, 0x00, 0x40, 0x00,
- 0x65, 0x61, 0x6c, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x70, 0x06,
- 0x40, 0x06, 0x75, 0x63, 0x74, 0x00, 0x40, 0x00, 0x61, 0x72, 0x6f, 0x75,
- 0x73, 0x00, 0x40, 0x09, 0x69, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6d, 0x1a,
- 0xe2, 0x61, 0x00, 0x65, 0x13, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x00, 0x09, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04, 0x6e,
- 0x16, 0x00, 0x00, 0x00, 0x3a, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x00, 0x06, 0x40, 0x09, 0x74, 0x00, 0x40, 0x3b, 0x73, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xf5, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x09, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe7, 0x00,
- 0x00, 0x62, 0x02, 0x63, 0x11, 0x66, 0x17, 0x69, 0x1d, 0x74, 0x56, 0x79,
- 0x5c, 0x00, 0x14, 0xe2, 0x6c, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x6f, 0x6f,
- 0x64, 0x00, 0x40, 0x09, 0x77, 0x00, 0x40, 0x06, 0x61, 0x72, 0x74, 0x00,
- 0x40, 0x06, 0x6f, 0x72, 0x64, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x15, 0x69, 0x17, 0xe3, 0x6e, 0x00, 0x73, 0x04, 0x74, 0x08, 0x40,
- 0x09, 0x74, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x09, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0x40, 0x08, 0x61, 0x69, 0x6c, 0x00, 0xe3, 0x61, 0x00,
- 0x67, 0x0b, 0x6d, 0x27, 0x40, 0x07, 0x63, 0x65, 0x74, 0x79, 0x6c, 0x65,
- 0x6e, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x06, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xc1, 0x48, 0x33, 0x6b, 0x00,
- 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0xb2, 0x13, 0xb6, 0x13, 0xb8, 0x13,
- 0x5e, 0x24, 0x6c, 0x24, 0x78, 0x24, 0xd8, 0x2b, 0x42, 0x33, 0x47, 0x33,
- 0x64, 0x33, 0xd6, 0x3a, 0xd8, 0x3a, 0x20, 0x3b, 0x2b, 0x49, 0x00, 0x00,
- 0x38, 0x49, 0x3e, 0x64, 0xa0, 0x66, 0xc7, 0x66, 0xc8, 0x6d, 0xcc, 0x6d,
- 0x00, 0x00, 0xd0, 0x6d, 0x91, 0x6e, 0x04, 0x06, 0x00, 0x00, 0xc1, 0x62,
- 0x18, 0x35, 0x00, 0x37, 0x00, 0x47, 0x00, 0x22, 0x01, 0x5e, 0x01, 0x00,
- 0x00, 0x6c, 0x01, 0xc1, 0x01, 0xc3, 0x01, 0x9b, 0x02, 0x00, 0x00, 0xad,
- 0x02, 0xb7, 0x04, 0xde, 0x04, 0x00, 0x00, 0xae, 0x06, 0x00, 0x00, 0x9c,
- 0x07, 0xf5, 0x0d, 0x8f, 0x0f, 0x15, 0x12, 0x51, 0x12, 0x7e, 0x12, 0x00,
- 0x00, 0xb6, 0x12, 0x01, 0x58, 0xe2, 0x6c, 0x00, 0x75, 0x05, 0x40, 0x07,
- 0x75, 0x6d, 0x00, 0x40, 0x07, 0x6c, 0x75, 0x6d, 0x00, 0xe6, 0x65, 0x00,
- 0x68, 0x20, 0x69, 0x36, 0x6b, 0x74, 0x74, 0xca, 0x79, 0xcc, 0xe5, 0x00,
- 0x00, 0x6d, 0x02, 0x72, 0x09, 0x73, 0x0b, 0x79, 0x13, 0x00, 0xa5, 0x40,
- 0x06, 0x61, 0x6b, 0x65, 0x72, 0x00, 0x00, 0x07, 0x40, 0x06, 0x65, 0x74,
- 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x64, 0x00,
- 0x73, 0x06, 0x40, 0x09, 0x65, 0x72, 0x6d, 0x00, 0x40, 0x09, 0x61, 0x6e,
- 0x64, 0x72, 0x61, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x34,
- 0xe3, 0x63, 0x00, 0x65, 0x17, 0x73, 0x1b, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00,
- 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0x04, 0x07, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x61,
- 0x06, 0x65, 0x22, 0x69, 0x2b, 0x73, 0x41, 0x03, 0xa5, 0x40, 0x00, 0x73,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe3, 0x00, 0x00,
- 0x27, 0x02, 0x72, 0x06, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x00, 0x06,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x09,
- 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x27, 0x00, 0x68,
- 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00,
- 0x40, 0x09, 0x61, 0x64, 0x64, 0x6c, 0x65, 0x00, 0x00, 0x09, 0x00, 0xf3,
- 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6c, 0x29, 0x72, 0x2f, 0x00, 0x06, 0xe5,
- 0x65, 0x00, 0x69, 0x04, 0x6c, 0x09, 0x6f, 0x15, 0x79, 0x1a, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x55, 0x63, 0x6b, 0x00,
- 0x00, 0x06, 0x40, 0x47, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x06, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x09, 0x6c,
- 0x61, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x32, 0x6f, 0x47, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73,
- 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x62, 0x13, 0x72, 0x18, 0x00,
- 0xa5, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x6f, 0x79, 0x00, 0x00,
- 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09,
- 0x64, 0x61, 0x00, 0x00, 0x00, 0xe5, 0x64, 0x00, 0x6c, 0x02, 0x6e, 0x0e,
- 0x72, 0xad, 0x73, 0xc7, 0x01, 0xca, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00,
- 0x09, 0x40, 0x06, 0x75, 0x6c, 0x00, 0xe6, 0x00, 0x00, 0x66, 0x02, 0x6b,
- 0x25, 0x6c, 0x3c, 0x73, 0x52, 0x74, 0x5b, 0x00, 0x47, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x10, 0x00, 0x4d,
- 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x12, 0x74, 0x61, 0x6b, 0x69, 0x6e,
- 0x67, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x18, 0x69, 0x21, 0x77,
- 0x26, 0x04, 0x08, 0xe3, 0x61, 0x00, 0x6f, 0x05, 0x72, 0x09, 0x40, 0x00,
- 0x6c, 0x6c, 0x00, 0x40, 0x09, 0x78, 0x00, 0x40, 0x09, 0x75, 0x73, 0x68,
- 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x12, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x6b, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x77, 0x0b, 0x03, 0x30, 0x40, 0x37, 0x64, 0x00,
- 0x40, 0x08, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x73, 0x65, 0x00, 0x40,
- 0x06, 0x6c, 0x65, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xfb,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x70, 0x00, 0x66, 0xcf, 0x00,
- 0x69, 0xd5, 0x00, 0x6c, 0x14, 0x01, 0x6d, 0x63, 0x01, 0x6f, 0x95, 0x01,
- 0x70, 0x9c, 0x01, 0x73, 0xd3, 0x01, 0x74, 0xd7, 0x01, 0x00, 0x56, 0xe6,
- 0x63, 0x00, 0x64, 0x04, 0x6e, 0x09, 0x74, 0x10, 0x76, 0x50, 0x7a, 0x55,
- 0x40, 0x09, 0x65, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x00, 0x40, 0x06, 0x71,
- 0x75, 0x69, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x22, 0x69, 0x24, 0xe2,
- 0x62, 0x00, 0x6c, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x03, 0xc2, 0xe2,
- 0x61, 0x00, 0x6e, 0x04, 0x40, 0x3b, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x05, 0x40, 0x09, 0x74, 0x65, 0x00, 0x00, 0x09, 0x40, 0x95, 0x65, 0x72,
- 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x6e, 0x08, 0x6f, 0x0e, 0x74, 0x4f,
- 0x04, 0x09, 0x40, 0x09, 0x61, 0x63, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe3, 0x67, 0x00, 0x6c, 0x17, 0x6e, 0x1f, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x04, 0x40, 0x09, 0x72, 0x00, 0x00, 0x07, 0x40, 0x00, 0x69, 0x74,
- 0x68, 0x69, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05,
- 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x06, 0x74, 0x65, 0x00,
- 0x40, 0x06, 0x72, 0x65, 0x79, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x11, 0x73,
- 0x2c, 0xe2, 0x6f, 0x00, 0x70, 0x05, 0x40, 0x07, 0x6e, 0x79, 0x00, 0x40,
- 0x09, 0x73, 0x65, 0x73, 0x74, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x14, 0xe1,
- 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x68, 0x05, 0x40, 0x06, 0x64, 0x65, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x62, 0x09, 0x65, 0x11, 0x69, 0x15, 0x6f, 0x3e, 0x00, 0x47,
- 0x40, 0x07, 0x64, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x09, 0x65, 0x61, 0x72,
- 0x65, 0x72, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x64, 0x17,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0xf4, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x69,
- 0x0d, 0x74, 0x1e, 0x79, 0x23, 0x00, 0x47, 0x40, 0x00, 0x74, 0x65, 0x00,
- 0x40, 0x06, 0x74, 0x74, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x06, 0x6f, 0x70, 0x00, 0x00, 0x60, 0x40, 0x09, 0x6d, 0x69, 0x6e, 0x6f,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x1d, 0xe2, 0x62, 0x00, 0x74, 0x0c, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0xa1, 0x79, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x15, 0xe1, 0x70, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x04, 0x68, 0x08, 0x40, 0x07, 0x73, 0x00, 0x40, 0x3a, 0x72, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x09, 0x40, 0x09, 0x65, 0x72, 0x00, 0xfd, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x63, 0x21, 0x00, 0x64, 0x53, 0x00, 0x65, 0x7a, 0x00,
- 0x67, 0xa2, 0x00, 0x68, 0xa4, 0x00, 0x69, 0xbc, 0x00, 0x6e, 0xd8, 0x00,
- 0x6f, 0xee, 0x00, 0x70, 0x09, 0x01, 0x73, 0x10, 0x01, 0x74, 0x14, 0x01,
- 0x00, 0x06, 0xe3, 0x63, 0x00, 0x6d, 0x0d, 0x74, 0x11, 0xe2, 0x65, 0x00,
- 0x68, 0x04, 0x40, 0x06, 0x61, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x09,
- 0x61, 0x00, 0x40, 0x08, 0x65, 0x6c, 0x6c, 0x61, 0x00, 0xe3, 0x61, 0x00,
- 0x68, 0x05, 0x72, 0x0f, 0x40, 0x5e, 0x6b, 0x65, 0x00, 0x40, 0x00, 0x72,
- 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x73, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x00, 0x69, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x02, 0x00, 0x06, 0xe2, 0x6d, 0x00, 0x72, 0x10, 0xe2,
- 0x69, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x63, 0x00, 0x40, 0x07, 0x6e, 0x69,
- 0x75, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfe, 0x40, 0x07,
- 0x72, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6c, 0x09, 0x73, 0x1d, 0x02,
- 0x25, 0x40, 0x06, 0x79, 0x72, 0x69, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x04, 0x0a, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07, 0x67, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0x00, 0x00, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x6b, 0x02, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79,
- 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00, 0x67, 0x00, 0xe2, 0x70,
- 0x00, 0x72, 0x05, 0x40, 0x06, 0x6c, 0x79, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63,
- 0x00, 0x40, 0x07, 0x69, 0x70, 0x65, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00,
- 0xe9, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0a, 0x68, 0x14, 0x69, 0x39, 0x6f,
- 0x3d, 0x72, 0x5c, 0x73, 0x60, 0x79, 0x66, 0x00, 0x47, 0x40, 0x07, 0x6c,
- 0x6f, 0x6f, 0x6e, 0x73, 0x00, 0x40, 0x08, 0x63, 0x68, 0x6e, 0x69, 0x63,
- 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x15, 0x72,
- 0x19, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06,
- 0x6e, 0x00, 0x00, 0x09, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x08, 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x82, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x06, 0x75, 0x69, 0x74,
- 0x00, 0xe3, 0x68, 0x00, 0x6c, 0x06, 0x77, 0x0d, 0x40, 0x07, 0x6f, 0x73,
- 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x06, 0x61,
- 0x69, 0x73, 0x74, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x2b, 0x69,
- 0xa1, 0x6f, 0xbf, 0x70, 0xc5, 0x72, 0xc9, 0x79, 0xcf, 0x00, 0x06, 0xe5,
- 0x00, 0x00, 0x63, 0x02, 0x6c, 0x06, 0x72, 0x08, 0x79, 0x1a, 0x00, 0x09,
- 0x40, 0x06, 0x79, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x7a, 0x00,
- 0xe1, 0x7a, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x09, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe9, 0x00, 0x00, 0x62, 0x02,
- 0x63, 0x20, 0x65, 0x26, 0x67, 0x2a, 0x68, 0x30, 0x6c, 0x47, 0x77, 0x4d,
- 0x79, 0x5e, 0x00, 0xfa, 0xe2, 0x61, 0x00, 0x6f, 0x0d, 0xe2, 0x63, 0x00,
- 0x72, 0x04, 0x40, 0x06, 0x6b, 0x00, 0x40, 0x08, 0x6b, 0x00, 0xe2, 0x61,
- 0x00, 0x79, 0x05, 0x40, 0x07, 0x72, 0x64, 0x00, 0x00, 0x06, 0x40, 0x08,
- 0x6c, 0x69, 0x70, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x69, 0x72,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x07,
- 0x40, 0x09, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x07, 0x72, 0x6b, 0x00,
- 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x15, 0xe1, 0x6c, 0x00, 0xe1, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x04, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x09, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x73,
- 0x65, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6b, 0x61, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xc1, 0x61, 0x16, 0x31, 0x00, 0x33, 0x00, 0xcc, 0x02, 0xd2,
- 0x02, 0xe8, 0x02, 0x11, 0x03, 0x84, 0x03, 0x00, 0x00, 0x00, 0x00, 0x8a,
- 0x03, 0x00, 0x00, 0xca, 0x03, 0xed, 0x03, 0x36, 0x04, 0x00, 0x00, 0x3f,
- 0x04, 0x00, 0x00, 0x8c, 0x04, 0xa0, 0x04, 0xcd, 0x04, 0x10, 0x05, 0x00,
- 0x00, 0x53, 0x06, 0x04, 0x0b, 0xfe, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x63, 0x19, 0x00, 0x64, 0x38, 0x00, 0x66, 0x7b, 0x00, 0x67, 0x81, 0x00,
- 0x6b, 0xa6, 0x00, 0x6c, 0xac, 0x00, 0x6d, 0x05, 0x01, 0x6e, 0x65, 0x01,
- 0x70, 0x83, 0x01, 0x71, 0xe6, 0x01, 0x73, 0xec, 0x01, 0x74, 0x36, 0x02,
- 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x65, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63,
- 0x00, 0xe2, 0x65, 0x00, 0x68, 0x08, 0x40, 0x08, 0x74, 0x61, 0x6d, 0x6f,
- 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x5e, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x6f, 0x2c, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07,
- 0xe2, 0x67, 0x00, 0x73, 0x10, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x00, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe1,
- 0x78, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x3b, 0x63,
- 0x61, 0x6c, 0x00, 0x40, 0x07, 0x66, 0x69, 0x6e, 0x00, 0xe3, 0x6c, 0x00,
- 0x6f, 0x08, 0x72, 0x0c, 0x40, 0x00, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xec, 0x00, 0x00, 0x40, 0x06,
- 0x65, 0x65, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x6c, 0x06, 0x79, 0x2d, 0x40,
- 0x09, 0x67, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x09,
- 0x78, 0x00, 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x6f, 0x0b, 0x00, 0x93, 0x40, 0x37, 0x64, 0x00, 0x40, 0x09, 0x73, 0x6d,
- 0x00, 0x40, 0x06, 0x67, 0x72, 0x61, 0x6d, 0x00, 0xe3, 0x73, 0x00, 0x74,
- 0x0d, 0x7a, 0x12, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x06, 0x69, 0x63, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x3a, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x36, 0x6f, 0x3f, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x64,
- 0x0e, 0x74, 0x1f, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x09, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x72, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00,
- 0x40, 0x06, 0x6c, 0x69, 0x74, 0x61, 0x72, 0x79, 0x00, 0xe1, 0x75, 0x00,
- 0xe2, 0x6e, 0x00, 0x72, 0x0e, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x63,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00, 0x06, 0xe1, 0x6f, 0x00,
- 0xe2, 0x69, 0x00, 0x72, 0x10, 0xe2, 0x61, 0x00, 0x64, 0x09, 0xe2, 0x00,
- 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x09, 0x00, 0x06, 0x40, 0x00, 0x6d,
- 0x61, 0x6c, 0x00, 0xe5, 0x65, 0x00, 0x68, 0x04, 0x6c, 0x18, 0x72, 0x2a,
- 0x73, 0x37, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x09, 0x40,
- 0x07, 0x72, 0x6e, 0x61, 0x6c, 0x69, 0x61, 0x00, 0x40, 0x5e, 0x61, 0x73,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x66,
- 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x79, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x07, 0x75, 0x61, 0x74, 0x00,
- 0xe5, 0x61, 0x00, 0x63, 0x08, 0x69, 0x11, 0x6f, 0x2f, 0x79, 0x33, 0x40,
- 0x00, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x64,
- 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x09,
- 0x6c, 0x00, 0x40, 0x08, 0x6d, 0x70, 0x61, 0x74, 0x68, 0x65, 0x74, 0x69,
- 0x63, 0x00, 0xe3, 0x68, 0x00, 0x72, 0x11, 0x79, 0x29, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x6f, 0x69,
- 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x73, 0x06, 0x04, 0x0c, 0x40, 0x07, 0x72, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x70, 0x68, 0x6f, 0x69, 0x64, 0x00, 0x40, 0x3a,
- 0x6f, 0x69, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x04, 0x40, 0x59, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x06, 0x65, 0x6e,
- 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x05, 0x40, 0x08, 0x65, 0x72, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11, 0x04, 0x0d,
- 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x37, 0x00, 0x37, 0x40, 0x07, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x67, 0x02,
- 0x6e, 0x09, 0x72, 0x5b, 0x73, 0x5d, 0x00, 0x08, 0x40, 0x07, 0x6f, 0x72,
- 0x69, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x68,
- 0x0d, 0x69, 0x41, 0x00, 0x59, 0xe2, 0x67, 0x00, 0x6c, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x2a, 0xe2, 0x73, 0x00,
- 0x74, 0x14, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x73, 0x00, 0x7a, 0x02, 0x00, 0x07, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x6f, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x08, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x09, 0x61, 0x69, 0x74, 0x00, 0xe6, 0x61, 0x00, 0x65,
- 0x0c, 0x6d, 0x12, 0x6e, 0x1a, 0x73, 0x1e, 0x74, 0x2f, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x74,
- 0x61, 0x6c, 0x00, 0x40, 0x09, 0x75, 0x74, 0x75, 0x65, 0x6c, 0x00, 0x40,
- 0x07, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x09, 0x6f, 0x6e, 0x65, 0x72, 0x00, 0x40, 0x90, 0x79, 0x00,
- 0xe6, 0x00, 0x00, 0x61, 0x02, 0x69, 0x04, 0x6c, 0x09, 0x77, 0x0f, 0x79,
- 0x14, 0x00, 0x47, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x61, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0x00, 0x00, 0xe4,
- 0x61, 0x00, 0x65, 0x0c, 0x69, 0x10, 0x6f, 0x35, 0xe2, 0x6e, 0x00, 0x79,
- 0x05, 0x40, 0x07, 0x63, 0x65, 0x00, 0x00, 0x59, 0x40, 0x59, 0x79, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x72,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00,
- 0x00, 0xe2, 0x72, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x00, 0x69, 0x67, 0x69, 0x61, 0x6e, 0x61, 0x00, 0xe4, 0x63, 0x00,
- 0x64, 0x18, 0x6c, 0x24, 0x78, 0x30, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0x00, 0xa1, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x82, 0x00, 0x09, 0xe1, 0x79, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x47, 0x40, 0x07, 0x79, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x04, 0x6f, 0x1e, 0x79, 0x22, 0x40, 0x00, 0x64, 0x00, 0xe2,
- 0x63, 0x00, 0x6e, 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0x40, 0x00, 0x67,
- 0x00, 0x40, 0x59, 0x74, 0x00, 0x00, 0xa1, 0xe5, 0x65, 0x00, 0x69, 0x09,
- 0x6c, 0x1f, 0x6e, 0x24, 0x6f, 0x29, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x03,
- 0xf9, 0x00, 0x09, 0xe1, 0x6d, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x65, 0x79, 0x00, 0x40, 0x09, 0x69, 0x70, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x09, 0x67,
- 0x65, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x27, 0x02, 0x00, 0x61, 0x06, 0x00,
- 0x65, 0x19, 0x00, 0x68, 0x1f, 0x00, 0x69, 0x2c, 0x00, 0x6c, 0xe8, 0x00,
- 0x6e, 0xec, 0x00, 0x6f, 0xff, 0x00, 0x72, 0x04, 0x01, 0x75, 0x0b, 0x01,
- 0x77, 0x14, 0x01, 0x79, 0x19, 0x01, 0x03, 0x4a, 0x40, 0x00, 0x73, 0x00,
- 0xe1, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72,
- 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x07, 0x40, 0x06, 0x72, 0x72, 0x65,
- 0x00, 0x40, 0x07, 0x65, 0x6e, 0x6f, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69,
- 0x73, 0x00, 0xe5, 0x61, 0x00, 0x63, 0x0f, 0x6e, 0x8a, 0x73, 0x8e, 0x74,
- 0xa1, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0xe3, 0x69, 0x00, 0x6c, 0x36, 0x75, 0x47, 0xe1,
- 0x70, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x23, 0x6c, 0x28, 0xe2, 0x6e, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0x40, 0x07, 0x61, 0x6c,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x62,
- 0x02, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x61, 0x72, 0x64, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x1e, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x56, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x3a, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x67, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06,
- 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x59, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00,
- 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x47, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00, 0x40, 0x00, 0x6f,
- 0x6b, 0x00, 0x40, 0x06, 0x69, 0x64, 0x67, 0x65, 0x00, 0x40, 0x07, 0x72,
- 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x61, 0x79, 0x00, 0x00,
- 0xa1, 0x40, 0x09, 0x65, 0x6e, 0x75, 0x00, 0xf4, 0x63, 0x00, 0x00, 0x68,
- 0x0e, 0x00, 0x73, 0x12, 0x00, 0x74, 0xde, 0x00, 0xe2, 0x61, 0x00, 0x68,
- 0x04, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x06,
- 0x61, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x62, 0x1b, 0x65, 0x21, 0x69,
- 0x46, 0x6b, 0x9f, 0x70, 0xa4, 0x77, 0xb5, 0x00, 0x07, 0xe2, 0x62, 0x00,
- 0x67, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x77, 0x02, 0x00, 0x09, 0x40, 0x09, 0x61, 0x79, 0x00, 0x40, 0x09,
- 0x6f, 0x6f, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x04, 0x72,
- 0x0a, 0x04, 0x0e, 0x00, 0x09, 0x40, 0x06, 0x67, 0x65, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x73, 0x06, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00,
- 0x40, 0x00, 0x62, 0x79, 0x00, 0xe4, 0x6d, 0x00, 0x6e, 0x02, 0x6f, 0x06,
- 0x76, 0x27, 0x00, 0x00, 0x40, 0x12, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x66, 0x07, 0x6c, 0x0f, 0x00, 0x84, 0x40, 0x7d,
- 0x74, 0x65, 0x00, 0x40, 0x06, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x40,
- 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0x8f, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x09,
- 0x65, 0x79, 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x07, 0x40, 0x08, 0x72, 0x61,
- 0x73, 0x65, 0x00, 0x40, 0x09, 0x72, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x72,
- 0x64, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x69, 0x40, 0x6f,
- 0x61, 0x72, 0x76, 0x75, 0x82, 0x79, 0x9c, 0x00, 0x69, 0x00, 0x06, 0xe5,
- 0x00, 0x00, 0x62, 0x02, 0x6c, 0x09, 0x72, 0x0b, 0x75, 0x0f, 0x00, 0x5e,
- 0x40, 0x07, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x00, 0x09, 0x40, 0x09, 0x6e,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x64, 0x02, 0x72, 0x04, 0x00, 0x3f, 0x00, 0x37, 0x00, 0x07, 0xe5,
- 0x63, 0x00, 0x65, 0x05, 0x6c, 0x07, 0x6d, 0x0c, 0x6e, 0x10, 0x40, 0x09,
- 0x68, 0x65, 0x00, 0x00, 0x00, 0x40, 0x09, 0x6c, 0x65, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x05, 0x40, 0x07,
- 0x6d, 0x69, 0x00, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x05, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x5e, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x03, 0x0e, 0xf9, 0x00, 0x00,
- 0x00, 0x63, 0x02, 0x00, 0x65, 0x2f, 0x00, 0x68, 0x8e, 0x00, 0x69, 0xff,
- 0x00, 0x6f, 0x38, 0x01, 0x72, 0x3d, 0x01, 0x73, 0x48, 0x02, 0x74, 0x4c,
- 0x02, 0x00, 0x06, 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x11, 0x77, 0x17, 0x79, 0x1d, 0x00, 0xc6, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00,
- 0x75, 0x6c, 0x69, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x6b, 0x00, 0x01, 0x92,
- 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x11, 0x72, 0x15, 0x00, 0x09, 0xe1,
- 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09,
- 0x00, 0x00, 0x43, 0x17, 0x74, 0x00, 0xe2, 0x66, 0x00, 0x6e, 0x0a, 0x40,
- 0x09, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x61, 0x73, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x1f, 0x6f, 0x24, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x08, 0x40, 0x00, 0x63, 0x00, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0x40, 0x09, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe7,
- 0x00, 0x00, 0x65, 0x02, 0x66, 0x18, 0x6c, 0x20, 0x6f, 0x26, 0x73, 0x5b,
- 0x77, 0x5d, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0xe3, 0x67, 0x00, 0x6c, 0x11, 0x73, 0x2c, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x09, 0x61, 0x79, 0x00, 0xe4, 0x65, 0x00, 0x6e, 0x1d, 0x6f, 0x26, 0x73,
- 0x28, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x04, 0x0f, 0x40, 0x00,
- 0x72, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x06, 0x40, 0x08, 0x73, 0x65, 0x72, 0x69, 0x65,
- 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0xf3, 0x65, 0x00, 0x00, 0x69, 0x0c,
- 0x00, 0x6f, 0x7a, 0x00, 0x40, 0x00, 0x73, 0x66, 0x61, 0x6d, 0x69, 0x6c,
- 0x69, 0x61, 0x73, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x23, 0x6d, 0x33, 0x6f,
- 0x45, 0xe1, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x73, 0x0d, 0x79, 0x0f, 0x00, 0x07, 0xe2, 0x6c, 0x00,
- 0x74, 0x02, 0x00, 0x00, 0x40, 0x09, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x64, 0x04, 0x40, 0x06, 0x6e, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x63, 0x00, 0x73,
- 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x37, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x39, 0x6f,
- 0x7c, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x10, 0x77, 0x1d, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x0c, 0x79, 0x22, 0x00, 0x09, 0x40,
- 0x09, 0x67, 0x65, 0x00, 0x40, 0x09, 0x73, 0x73, 0x00, 0xe1, 0x7a, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f,
- 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x10, 0x79, 0x15, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x55, 0x00, 0x2c,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe4, 0x63, 0x00, 0x6e, 0x06,
- 0x70, 0x15, 0x73, 0x2f, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00,
- 0xf3, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6d, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x11,
- 0x6c, 0x20, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6d, 0x04, 0x00, 0x4b, 0x00,
- 0x37, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x06,
- 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x67, 0x00, 0x40, 0x08,
- 0x6f, 0x76, 0x61, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x04, 0x70,
- 0x2a, 0x00, 0x93, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x73, 0x19,
- 0x00, 0x47, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6b, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x09, 0x68, 0x6f, 0x70, 0x00, 0x40, 0x09, 0x61, 0x77, 0x00,
- 0xed, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x63, 0x0c, 0x64, 0x13, 0x65,
- 0x18, 0x6c, 0x25, 0x6d, 0x2b, 0x6f, 0x3c, 0x70, 0x4f, 0x72, 0x56, 0x73,
- 0x5c, 0x77, 0x62, 0x04, 0x10, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x61,
- 0x63, 0x6b, 0x00, 0x40, 0x09, 0x68, 0x65, 0x63, 0x6b, 0x00, 0x40, 0x09,
- 0x61, 0x79, 0x00, 0xe3, 0x64, 0x00, 0x65, 0x02, 0x72, 0x04, 0x00, 0x00,
- 0x00, 0x06, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x61, 0x64, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x06, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x65,
- 0x6e, 0x74, 0x00, 0xe3, 0x66, 0x00, 0x6c, 0x04, 0x75, 0x08, 0x40, 0x09,
- 0x66, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x09, 0x74, 0x00, 0x40, 0x08,
- 0x68, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x6c, 0x00, 0x40,
- 0x06, 0x6c, 0x69, 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x72,
- 0x04, 0x40, 0x06, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0x00, 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0x15, 0x01, 0x24, 0x01,
- 0xb2, 0x01, 0xd9, 0x02, 0x00, 0x00, 0x7c, 0x03, 0x00, 0x00, 0x9a, 0x03,
- 0xa2, 0x03, 0xbe, 0x03, 0xdf, 0x03, 0x26, 0x04, 0x2e, 0x04, 0x98, 0x06,
- 0xb2, 0x06, 0x00, 0x00, 0x0f, 0x07, 0xb9, 0x0e, 0x5f, 0x0f, 0x00, 0x00,
- 0x00, 0x00, 0x88, 0x10, 0x00, 0x00, 0xa0, 0x10, 0xea, 0x00, 0x00, 0x63,
- 0x02, 0x66, 0x79, 0x68, 0x7f, 0x6b, 0x84, 0x6c, 0x8d, 0x6e, 0x8f, 0x72,
- 0x94, 0x73, 0xa4, 0x74, 0xc2, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x68, 0x62,
- 0x6f, 0x6b, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x66, 0x11, 0x6b, 0x24, 0x6d,
- 0x3b, 0x74, 0x4f, 0x00, 0x06, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x70, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x69, 0x6d, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00,
- 0x60, 0x40, 0x09, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x6f, 0x77, 0x6c, 0x00,
- 0x40, 0x09, 0x65, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x47,
- 0x00, 0x00, 0x03, 0x30, 0x40, 0x09, 0x75, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x86, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x93, 0x00,
- 0xf3, 0xe2, 0x61, 0x00, 0x68, 0x11, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x06, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x07, 0x00, 0x60, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x82, 0x00, 0x00, 0xe6, 0x61, 0x00, 0x63, 0x04,
- 0x6b, 0x27, 0x73, 0x33, 0x74, 0x35, 0x75, 0x49, 0x40, 0x06, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x17, 0xe1, 0x69, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0xe7, 0x40, 0x00, 0x73, 0x68, 0x00, 0x00,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x09, 0xe2, 0x63, 0x00, 0x6e, 0x02, 0x00,
- 0x00, 0x00, 0x07, 0x40, 0x09, 0x72, 0x61, 0x6c, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x2c, 0xe2, 0x61, 0x00, 0x69, 0x15, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x00,
- 0x69, 0x61, 0x72, 0x79, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x64, 0x51, 0x00,
- 0x65, 0x60, 0x00, 0x69, 0xa4, 0x00, 0x6f, 0xed, 0x00, 0x75, 0x0d, 0x01,
- 0xe3, 0x67, 0x00, 0x6c, 0x21, 0x6e, 0x2a, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe3, 0x69, 0x00, 0x75, 0x0e, 0x79, 0x12, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x93, 0x00,
- 0x08, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72, 0x12, 0x00,
- 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07,
- 0xe2, 0x72, 0x00, 0x73, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe1,
- 0x74, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x04, 0x40, 0x09, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe4, 0x61, 0x00, 0x63,
- 0x1c, 0x67, 0x34, 0x6d, 0x3a, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07,
- 0x00, 0x08, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x61, 0x00,
- 0x75, 0x04, 0x40, 0x06, 0x62, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x82, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0xb2, 0x72,
- 0x65, 0x65, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x6d, 0x00,
- 0x70, 0x07, 0x40, 0x09, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x08, 0x40, 0x00, 0x61, 0x00, 0x40, 0x09, 0x6e, 0x63, 0x6c, 0x65, 0x00,
- 0xe9, 0x00, 0x00, 0x69, 0x02, 0x6b, 0x07, 0x6c, 0x14, 0x6e, 0x2b, 0x70,
- 0x2d, 0x72, 0x4e, 0x76, 0x69, 0x77, 0x83, 0x04, 0x11, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x47, 0x40, 0x07, 0x62,
- 0x6f, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0b, 0x03, 0x2b,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x00, 0x09, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x06, 0x68,
- 0x0a, 0x73, 0x10, 0x00, 0xe7, 0x40, 0x00, 0x6f, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x68, 0x6f, 0x77,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x6c, 0x0c, 0x00, 0x2f,
- 0x40, 0x06, 0x67, 0x65, 0x00, 0x40, 0x09, 0x73, 0x73, 0x00, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x5e, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x09, 0x65, 0x00, 0x40, 0x08, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02,
- 0x67, 0x09, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x61, 0x72, 0x64, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x67, 0x6e, 0x6f, 0x69, 0x72, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x56, 0x65,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x16, 0x00, 0x09, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x06, 0x40, 0x00, 0x73, 0x65, 0x73, 0x00,
- 0x40, 0x06, 0x65, 0x73, 0x65, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe7, 0x61,
- 0x00, 0x66, 0x06, 0x69, 0x08, 0x6c, 0x0e, 0x6d, 0x25, 0x74, 0x2a, 0x76,
- 0x2c, 0x40, 0x00, 0x67, 0x69, 0x63, 0x00, 0x00, 0x07, 0x40, 0x09, 0x63,
- 0x61, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x75, 0x0a, 0x40, 0x07,
- 0x67, 0x72, 0x61, 0x00, 0x40, 0x59, 0x74, 0x00, 0x40, 0x00, 0x63, 0x69,
- 0x64, 0x00, 0x40, 0x08, 0x65, 0x74, 0x00, 0x00, 0x47, 0xe1, 0x69, 0x00,
- 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x07, 0x6d,
- 0x69, 0x63, 0x61, 0x6e, 0x00, 0xc1, 0x61, 0x15, 0x2f, 0x00, 0x31, 0x00,
- 0x00, 0x00, 0x59, 0x00, 0x6c, 0x00, 0x92, 0x00, 0xc4, 0x00, 0xcc, 0x00,
- 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x24, 0x01, 0x38, 0x01, 0x3f, 0x01,
- 0x58, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x01,
- 0xd3, 0x01, 0x24, 0x02, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x1e, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x74, 0x13, 0x00, 0x00, 0xe1, 0x7a, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x3a, 0x40, 0x06, 0x79, 0x00, 0x40, 0x09, 0x63, 0x65, 0x00, 0xe3, 0x65,
- 0x00, 0x68, 0x02, 0x69, 0x08, 0x00, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x74,
- 0x00, 0x44, 0x12, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07,
- 0x75, 0x0c, 0x03, 0x4a, 0x40, 0x09, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x6e,
- 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40, 0x00,
- 0x75, 0x73, 0x00, 0x40, 0x09, 0x6d, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x10, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0x7d, 0xe2, 0x6e, 0x00, 0x6f,
- 0x04, 0x40, 0x3b, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x08, 0x72,
- 0x69, 0x65, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x75, 0x69, 0x6e, 0x00, 0xe5,
- 0x63, 0x00, 0x6c, 0x08, 0x6e, 0x0c, 0x73, 0x21, 0x74, 0x23, 0x40, 0x07,
- 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0xe1, 0x61, 0x00, 0xe2, 0x6c,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0x40, 0x06, 0x69, 0x67, 0x68, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0xe5, 0x61, 0x00, 0x65, 0x05, 0x69, 0x09, 0x6f, 0x18, 0x79, 0x1c,
- 0x40, 0x09, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x64, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x06, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x67, 0x00,
- 0x40, 0x09, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x6f, 0x07, 0x40, 0x09, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40,
- 0x00, 0x72, 0x74, 0x68, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0xb0, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x68, 0x43, 0x00,
- 0x00, 0xe4, 0x63, 0x00, 0x67, 0x05, 0x6d, 0x1d, 0x74, 0x24, 0x40, 0x09,
- 0x6c, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x0e, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06,
- 0x61, 0x6d, 0x00, 0x40, 0x06, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x74,
- 0x65, 0x00, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65,
- 0x00, 0xe4, 0x63, 0x00, 0x6c, 0x05, 0x6d, 0x0e, 0x72, 0x20, 0x40, 0x07,
- 0x68, 0x65, 0x00, 0x40, 0x06, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x16, 0xe1,
- 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe2,
- 0x6e, 0x00, 0x70, 0x10, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x79, 0x07, 0x00,
- 0x09, 0x40, 0x07, 0x67, 0x65, 0x00, 0x00, 0x06, 0x40, 0x82, 0x6c, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x70, 0x02, 0x73, 0x41, 0x74, 0x46, 0x00, 0x06,
- 0xe3, 0x65, 0x00, 0x69, 0x27, 0x79, 0x36, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x6d, 0x08, 0x6f, 0x0e, 0x79,
- 0x13, 0x00, 0x59, 0x40, 0x06, 0x6f, 0x72, 0x6e, 0x00, 0x40, 0x06, 0x69,
- 0x6e, 0x74, 0x00, 0x40, 0x09, 0x6e, 0x69, 0x00, 0x00, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x00, 0x01, 0x92, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x63, 0x00, 0x64, 0x02, 0x00, 0x09, 0x40, 0x08, 0x65, 0x00, 0xc0, 0x61,
- 0x16, 0x2f, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x3b, 0x01, 0x4f, 0x01, 0x9f,
- 0x01, 0x73, 0x02, 0x79, 0x02, 0x7f, 0x02, 0xeb, 0x03, 0x01, 0x04, 0x00,
- 0x00, 0x1b, 0x04, 0xd7, 0x04, 0xf6, 0x04, 0x09, 0x05, 0x86, 0x05, 0x00,
- 0x00, 0x8f, 0x05, 0xe1, 0x06, 0x45, 0x07, 0x59, 0x07, 0xe2, 0x64, 0x00,
- 0x6d, 0x0a, 0x40, 0x07, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x00,
- 0xe1, 0x62, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x45,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe6, 0x61, 0x00,
- 0x65, 0x05, 0x68, 0x6f, 0x69, 0x7c, 0x6f, 0x93, 0x75, 0xae, 0x40, 0x09,
- 0x6c, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6e, 0x0f, 0x70, 0x25, 0xe1, 0x76,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0xd1, 0x00,
- 0x37, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00,
- 0x09, 0x40, 0x06, 0x67, 0x65, 0x00, 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x31, 0xe3, 0x62, 0x00, 0x6f, 0x0c,
- 0x76, 0x1a, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x59, 0x40, 0x00, 0x6e, 0x63,
- 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x75, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x00, 0x65,
- 0x00, 0xe2, 0x69, 0x00, 0x75, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe4, 0x67, 0x00,
- 0x6d, 0x1f, 0x6e, 0x37, 0x73, 0x3e, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00,
- 0x09, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00,
- 0x00, 0x40, 0x56, 0x6e, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x74, 0x72,
- 0x6f, 0x69, 0x6b, 0x61, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x44, 0x6f, 0x54,
- 0x75, 0x93, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x04, 0x6e, 0x2f, 0x03, 0xe2, 0x00, 0x09, 0xe2, 0x62, 0x00,
- 0x6f, 0x10, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74,
- 0x79, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00,
- 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x0f, 0x6d, 0x13,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x51, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x12, 0x00, 0xd6, 0xe2, 0x6e, 0x00, 0x74, 0x05, 0x40, 0x06, 0x63,
- 0x65, 0x00, 0x40, 0x00, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x37, 0x00, 0x07, 0xe3, 0x6d, 0x00, 0x6e, 0x13, 0x73, 0x2b,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05,
- 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x00, 0x40, 0x00, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x61, 0x00, 0x40, 0x00, 0x61, 0x70, 0x73,
- 0x00, 0xfb, 0x63, 0x00, 0x00, 0x67, 0x25, 0x00, 0x68, 0x2a, 0x00, 0x6c,
- 0x3e, 0x00, 0x6d, 0x4a, 0x00, 0x6e, 0x51, 0x00, 0x6f, 0x67, 0x00, 0x70,
- 0xa4, 0x00, 0x73, 0xde, 0x00, 0x74, 0x1c, 0x01, 0x77, 0x3a, 0x01, 0xe1,
- 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe3,
- 0x61, 0x00, 0x74, 0x09, 0x75, 0x0e, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x69, 0x73, 0x00, 0x40, 0x07, 0x6d, 0x00,
- 0x40, 0x06, 0x65, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x93, 0x40, 0x3b, 0x75, 0x73,
- 0x00, 0x40, 0x06, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x06, 0x40, 0x00, 0x74, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x6f, 0x17, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x06, 0x00, 0x00, 0x40, 0x56, 0x6c, 0x00, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x08,
- 0x40, 0x09, 0x74, 0x65, 0x74, 0x69, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x72,
- 0x0e, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x04, 0x40, 0x86, 0x6c,
- 0x00, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x04, 0x74, 0x08, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x00, 0x69, 0x63, 0x00, 0xe3, 0x63, 0x00, 0x68, 0x06, 0x74, 0x13,
- 0x40, 0x06, 0x6f, 0x70, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x01,
- 0xf0, 0x40, 0x09, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x1a,
- 0xe1, 0x6c, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0d, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x69,
- 0x63, 0x00, 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40,
- 0x00, 0x6c, 0x00, 0x40, 0x09, 0x6d, 0x00, 0x40, 0x07, 0x74, 0x69, 0x73,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x40,
- 0x06, 0x6b, 0x6c, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00,
- 0x07, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x47,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x92, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x30,
- 0x69, 0x54, 0x75, 0xa0, 0x00, 0x47, 0xe3, 0x66, 0x00, 0x6c, 0x07, 0x6e,
- 0x11, 0x40, 0x07, 0x72, 0x6f, 0x73, 0x74, 0x00, 0x60, 0x09, 0x69, 0x6e,
- 0x6b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07,
- 0x00, 0x07, 0x00, 0x56, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x10,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x2d, 0xe1, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe3, 0x62, 0x00, 0x6f, 0x0c, 0x76, 0x10, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x3a, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x72, 0x00, 0x78,
- 0x08, 0x40, 0x09, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x82, 0x69,
- 0x64, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x60, 0xe2, 0x6e, 0x00, 0x74,
- 0x21, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x56, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x72,
- 0x00, 0x75, 0x18, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x13, 0xe2, 0x6c, 0x00, 0x74,
- 0x02, 0x00, 0x56, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x78, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x0b, 0x40,
- 0x3b, 0x64, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x06, 0x75, 0x69,
- 0x73, 0x69, 0x74, 0x65, 0x00, 0xf6, 0x65, 0x00, 0x00, 0x69, 0x30, 0x00,
- 0x6e, 0x5c, 0x00, 0x6f, 0x65, 0x00, 0x70, 0xbd, 0x00, 0x75, 0x0b, 0x01,
- 0xe2, 0x63, 0x00, 0x76, 0x18, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x51, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x06, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x3a,
- 0xe3, 0x66, 0x00, 0x6d, 0x07, 0x73, 0x0d, 0x40, 0x07, 0x6c, 0x61, 0x67,
- 0x65, 0x00, 0x40, 0x06, 0x6d, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x5b, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x40, 0x00, 0x69, 0x63,
- 0x6b, 0x65, 0x74, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x34, 0x6e, 0x47, 0x03, 0x63, 0xe5, 0x00, 0x00, 0x62, 0x02,
- 0x65, 0x07, 0x67, 0x09, 0x6c, 0x0d, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x65,
- 0x00, 0x00, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x74, 0x0f, 0x00, 0x86, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0x43, 0x4a, 0x65, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x66, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x04, 0x13, 0x40, 0x07, 0x65, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0e, 0xe2, 0x63, 0x00, 0x78, 0x07, 0x40, 0x09, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x28, 0xe2, 0x61, 0x00,
- 0x75, 0x14, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74,
- 0x05, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00, 0x75, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x0b, 0xe1, 0x61, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x10, 0xe1,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x00, 0x74, 0x00,
- 0x37, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40,
- 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x07, 0x6e, 0x31, 0x75, 0x37, 0x00, 0xe0, 0x40, 0xad, 0x69, 0x6e,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x14, 0xe1, 0x63, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x05, 0x40, 0x3b, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x72, 0x00, 0x73, 0x17, 0xe1, 0x62, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x09, 0x00, 0x72, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x07, 0x73, 0x69, 0x73, 0x00, 0xe2,
- 0x6b, 0x00, 0x73, 0x04, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x0b, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x21, 0x00, 0x08, 0xe2, 0x64, 0x00, 0x73, 0x04, 0x40, 0x3a, 0x65,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x1f, 0xe2, 0x65, 0x00, 0x69, 0x0d,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x14, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x93, 0xe5, 0x65, 0x00, 0x6b, 0x05, 0x6f, 0x1b, 0x73,
- 0x1d, 0x74, 0x54, 0x40, 0x09, 0x74, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x69,
- 0x05, 0x40, 0x08, 0x72, 0x79, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x36,
- 0x6f, 0x3a, 0x01, 0x71, 0x40, 0xed, 0x72, 0x00, 0xe3, 0x63, 0x00, 0x66,
- 0x06, 0x6c, 0x0e, 0x40, 0x09, 0x69, 0x64, 0x65, 0x00, 0x40, 0x00, 0x65,
- 0x72, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x82, 0x65, 0x00,
- 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x15, 0x00,
- 0x65, 0x1b, 0x00, 0x69, 0x1f, 0x00, 0x72, 0x41, 0x00, 0x74, 0x9c, 0x00,
- 0x75, 0xf5, 0x00, 0x00, 0x0f, 0xe3, 0x62, 0x00, 0x6c, 0x06, 0x72, 0x08,
- 0x40, 0x09, 0x79, 0x74, 0x65, 0x00, 0x00, 0xb1, 0x40, 0x09, 0x64, 0x00,
- 0x40, 0x06, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0xec, 0x72, 0x00, 0xe2, 0x6f,
- 0x00, 0x74, 0x05, 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x04, 0x6f, 0x16, 0x40, 0x09, 0x6c, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x61,
- 0x00, 0x79, 0x08, 0x40, 0x07, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x3a, 0xe3, 0x63, 0x00, 0x64, 0x0a, 0x6c, 0x12, 0x40, 0x06, 0x68, 0x65,
- 0x6d, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x6c, 0x61,
- 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x6f, 0x0d, 0x00,
- 0x07, 0x40, 0x07, 0x74, 0x75, 0x6d, 0x00, 0x40, 0x07, 0x75, 0x6d, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73, 0x74,
- 0x00, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x50, 0x40, 0x00,
- 0x64, 0x00, 0xe5, 0x63, 0x00, 0x66, 0x06, 0x6c, 0x2d, 0x6e, 0x31, 0x73,
- 0x3d, 0x40, 0x09, 0x6f, 0x61, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69,
- 0x10, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x00, 0x07, 0x40, 0x3b, 0x68, 0x00, 0x00, 0x96, 0xe2, 0x6c, 0x00, 0x6e,
- 0x11, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x40, 0x09, 0x69, 0x61, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x74, 0x0a, 0x00, 0x06, 0x40, 0x06,
- 0x65, 0x00, 0x40, 0x06, 0x74, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x6f, 0x74, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00,
- 0x40, 0x09, 0x6e, 0x6e, 0x69, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x53, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x51, 0x4c, 0x00, 0xf8, 0x61, 0x00, 0x00, 0x65,
- 0x46, 0x01, 0x69, 0xc5, 0x01, 0x6c, 0xe0, 0x02, 0x6f, 0x35, 0x03, 0x70,
- 0x1c, 0x06, 0x72, 0x21, 0x06, 0x79, 0x79, 0x06, 0xf7, 0x65, 0x00, 0x00,
- 0x67, 0x06, 0x00, 0x6c, 0x14, 0x00, 0x6e, 0x41, 0x00, 0x72, 0x76, 0x00,
- 0x73, 0x1f, 0x01, 0x74, 0x2e, 0x01, 0x40, 0x09, 0x74, 0x6f, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x08, 0x40, 0x06, 0x63, 0x79, 0x74,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x16, 0xe1, 0x6e, 0x00, 0xe2, 0x67,
- 0x00, 0x78, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x09, 0xe2, 0x69, 0x00, 0x75, 0x09, 0xe2, 0x00,
- 0x00, 0x63, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x29, 0xe1, 0x73, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe2, 0x67, 0x00, 0x6c,
- 0x15, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x63, 0x02, 0x00, 0x09, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x00, 0x00,
- 0x40, 0x06, 0x6d, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x0f, 0x6d, 0x20, 0x79,
- 0x80, 0xe1, 0x6f, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05,
- 0x40, 0x00, 0x69, 0x63, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x1b,
- 0x6f, 0x20, 0x79, 0x4b, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00,
- 0x09, 0x40, 0x06, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x09, 0x73, 0x74, 0x00,
- 0xe2, 0x6c, 0x00, 0x70, 0x1f, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73,
- 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x07,
- 0x40, 0x09, 0x6f, 0x65, 0x69, 0x61, 0x00, 0x00, 0x06, 0xe1, 0x6e, 0x00,
- 0xe2, 0x67, 0x00, 0x78, 0x16, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x61,
- 0x00, 0x73, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07, 0x74,
- 0x69, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x5e, 0x40, 0x06, 0x75, 0x74, 0x00, 0x00, 0x00, 0xe4, 0x61,
- 0x00, 0x6e, 0x07, 0x72, 0x6c, 0x77, 0x74, 0x40, 0x09, 0x73, 0x61, 0x6e,
- 0x74, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x08, 0x74, 0x55, 0x40, 0x07, 0x63,
- 0x65, 0x74, 0x69, 0x6e, 0x00, 0xe4, 0x62, 0x00, 0x6c, 0x0a, 0x6d, 0x0c,
- 0x74, 0x3e, 0x40, 0x07, 0x61, 0x72, 0x62, 0x69, 0x74, 0x61, 0x6c, 0x00,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0xe1, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00,
- 0x00, 0x3b, 0xe2, 0x6c, 0x00, 0x6e, 0x13, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x79, 0x70, 0x65, 0x00, 0x40, 0x00,
- 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6d, 0x6f,
- 0x6e, 0x65, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x6c, 0x06, 0x00, 0x73, 0x00, 0x01, 0x00, 0x06, 0x40, 0x06, 0x6c, 0x00,
- 0xe5, 0x61, 0x00, 0x68, 0x63, 0x69, 0x6d, 0x6f, 0x8d, 0x74, 0xea, 0xe2,
- 0x6e, 0x00, 0x74, 0x46, 0xe2, 0x64, 0x00, 0x74, 0x18, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x3f,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x16, 0xe2, 0x63, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x74, 0x00,
- 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x0b, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x09, 0x74, 0x00,
- 0x00, 0x07, 0x40, 0x06, 0x61, 0x72, 0x6d, 0x6f, 0x6e, 0x69, 0x63, 0x00,
- 0xe2, 0x70, 0x00, 0x73, 0x06, 0x40, 0x09, 0x70, 0x69, 0x63, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe3, 0x64, 0x00, 0x6c,
- 0x09, 0x73, 0x24, 0x40, 0x06, 0x65, 0x6e, 0x64, 0x72, 0x6f, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2,
- 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x20, 0x40, 0x09, 0x72, 0x00, 0xe2,
- 0x63, 0x00, 0x7a, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x3b, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01,
- 0x4b, 0x00, 0x07, 0x00, 0x06, 0x40, 0x09, 0x65, 0x72, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0x2d, 0x40, 0x07, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x45, 0xe2, 0x62, 0x00, 0x67, 0x20, 0xe2, 0x69,
- 0x00, 0x6f, 0x06, 0x40, 0x07, 0x74, 0x69, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x00, 0x73, 0x74, 0x00, 0x00, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x78, 0x04, 0x40, 0x07, 0x6d, 0x00, 0x00,
- 0x07, 0xf6, 0x62, 0x00, 0x00, 0x65, 0x0c, 0x00, 0x6e, 0x1a, 0x00, 0x6f,
- 0xdb, 0x00, 0x73, 0xe0, 0x00, 0x74, 0x3d, 0x01, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x63, 0x02, 0x00, 0x09, 0x00, 0x09, 0xe2, 0x62, 0x00, 0x6e,
- 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x09, 0x69, 0x78, 0x00, 0xe4, 0x65,
- 0x00, 0x69, 0x5f, 0x6f, 0x7b, 0x79, 0xb6, 0xe6, 0x00, 0x00, 0x63, 0x02,
- 0x6d, 0x08, 0x70, 0x1f, 0x74, 0x26, 0x79, 0x44, 0x00, 0x5e, 0x40, 0x08,
- 0x61, 0x72, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x40, 0x00, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x08, 0x73,
- 0x0d, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x61,
- 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x11, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x67,
- 0x00, 0x6c, 0x1b, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x06, 0x00, 0x07,
- 0x40, 0x00, 0x63, 0x00, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b,
- 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0x04, 0x15, 0x40,
- 0x00, 0x65, 0x79, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x05, 0x40, 0x09, 0x74, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x0c, 0x40, 0x00, 0x69, 0x65, 0x73, 0x74, 0x65, 0x72, 0x61, 0x73, 0x65,
- 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x19, 0x6f, 0x1d, 0x75, 0x22,
- 0x79, 0x26, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x3b, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xf1, 0x6f, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x63, 0x08, 0x00, 0x65, 0x21, 0x00, 0x66, 0x64, 0x00, 0x67, 0x6f, 0x00,
- 0x6a, 0xb8, 0x00, 0x6d, 0xd9, 0x00, 0x6e, 0xe0, 0x00, 0x73, 0xe2, 0x00,
- 0x74, 0x38, 0x01, 0x00, 0x93, 0x40, 0x72, 0x6f, 0x6d, 0x62, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0xe1, 0x70, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x65, 0x72, 0x00, 0x00, 0x7e,
- 0xe2, 0x6c, 0x00, 0x6e, 0x1f, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x76, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x04, 0x16,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x69,
- 0x73, 0x68, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x16, 0xe1,
- 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x73, 0x16, 0x79, 0x18, 0x03, 0xa2, 0x40, 0x07, 0x72, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x00, 0x77, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0x40, 0x09, 0x65, 0x74, 0x65, 0x72, 0x00, 0x00,
- 0x09, 0xe3, 0x65, 0x00, 0x74, 0x0a, 0x79, 0x2b, 0x40, 0x00, 0x6e, 0x73,
- 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x74, 0x06, 0x00, 0x06, 0x40, 0x00, 0x63,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0e, 0xe1, 0x69, 0x00, 0xe2,
- 0x73, 0x00, 0x7a, 0x02, 0x00, 0x07, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x00,
- 0x69, 0x63, 0x00, 0xe2, 0x72, 0x00, 0x79, 0x14, 0xe1, 0x6f, 0x00, 0xe1,
- 0x70, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6d, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x00, 0x42, 0x42, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x2f, 0xe1, 0x73,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x20, 0x40, 0x00, 0x6c, 0x00,
- 0xe4, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x6f, 0x0c, 0x00, 0x4b, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x08, 0x6f, 0x6f, 0x6b, 0x00, 0x40, 0x07, 0x6c,
- 0x6f, 0x67, 0x79, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00,
- 0x6e, 0x07, 0x40, 0x00, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x6c, 0x00,
- 0x73, 0x20, 0xe3, 0x61, 0x00, 0x6f, 0x0e, 0x75, 0x15, 0xe2, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x00, 0x40, 0x06, 0x74, 0x65, 0x72, 0x79, 0x00, 0x40,
- 0x07, 0x67, 0x65, 0x6e, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x6f, 0x39, 0x71, 0x96,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x11, 0x6b, 0x1e, 0x73, 0x2c, 0x00,
- 0x06, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0x40,
- 0x00, 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x73, 0x04, 0x40, 0x06, 0x6e,
- 0x00, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x07, 0xe4, 0x00, 0x00,
- 0x67, 0x02, 0x6c, 0x14, 0x74, 0x39, 0x00, 0x08, 0xe2, 0x6e, 0x00, 0x72,
- 0x06, 0x40, 0x06, 0x6f, 0x6d, 0x79, 0x00, 0x40, 0x07, 0x61, 0x70, 0x68,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x09, 0x75, 0x65, 0x00, 0xc1,
- 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x76, 0x00, 0x8b, 0x00, 0x84, 0x01,
- 0x9a, 0x01, 0x07, 0x02, 0x0d, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xc6, 0x02, 0xdb, 0x02, 0x9c, 0x03, 0xc9, 0x03, 0x13, 0x05, 0x2e, 0x05,
- 0x83, 0x05, 0x9b, 0x05, 0xd5, 0x05, 0x25, 0x06, 0x00, 0x00, 0x1b, 0x07,
- 0x00, 0x00, 0x2c, 0x07, 0x00, 0x00, 0x3d, 0x07, 0x04, 0x17, 0xe3, 0x6e,
- 0x00, 0x73, 0x29, 0x7a, 0x2f, 0xe2, 0x69, 0x00, 0x6f, 0x10, 0xe1, 0x73,
- 0x00, 0xe2, 0x73, 0x00, 0x74, 0x06, 0x40, 0x06, 0x69, 0x6d, 0x6f, 0x00,
- 0x00, 0x09, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x09, 0x00, 0x06, 0x40,
- 0x06, 0x6f, 0x72, 0x74, 0x65, 0x00, 0x40, 0x08, 0x61, 0x00, 0x40, 0x09,
- 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x7a, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x63,
- 0x27, 0x6b, 0x39, 0x6e, 0x7a, 0x6f, 0x9a, 0x73, 0x9e, 0x74, 0xa0, 0x00,
- 0x06, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x07, 0x72, 0x0c, 0x79, 0x14,
- 0x00, 0x07, 0x40, 0x09, 0x6f, 0x72, 0x00, 0x40, 0x00, 0x74, 0x65, 0x00,
- 0x40, 0x00, 0x65, 0x73, 0x71, 0x75, 0x65, 0x00, 0x40, 0x00, 0x75, 0x6e,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x08, 0x40, 0x07, 0x6c, 0x69, 0x6c,
- 0x6c, 0x69, 0x00, 0x40, 0x09, 0x6c, 0x6f, 0x00, 0xe8, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x06, 0x69, 0x18, 0x6c, 0x1e, 0x70, 0x22, 0x75, 0x2a, 0x79,
- 0x2e, 0x03, 0x2b, 0x40, 0x59, 0x78, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x0b,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6c, 0x00, 0x00,
- 0xc3, 0x40, 0x07, 0x6e, 0x67, 0x73, 0x00, 0x40, 0x82, 0x65, 0x00, 0x40,
- 0x06, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x40, 0x09, 0x70, 0x00, 0x00,
- 0x96, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0x00, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x20, 0xe2, 0x67, 0x00, 0x72,
- 0x15, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x86,
- 0x69, 0x61, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x82, 0xe1, 0x71, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x0c, 0xe1, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x82, 0x00, 0x00, 0x40, 0x09, 0x69, 0x6e,
- 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x69, 0x36, 0x72, 0x3b,
- 0x74, 0x4e, 0x7a, 0x52, 0x00, 0x06, 0x40, 0x09, 0x61, 0x6c, 0x64, 0x00,
- 0xe2, 0x65, 0x00, 0x72, 0x23, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x77, 0x08,
- 0x00, 0x5e, 0x40, 0x00, 0x65, 0x61, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x13,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x75, 0x73, 0x74, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x04, 0x18, 0x40, 0x12, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x00, 0x6f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x69,
- 0x63, 0x00, 0x40, 0x15, 0x66, 0x6c, 0x65, 0x00, 0xe9, 0x00, 0x00, 0x65,
- 0x02, 0x67, 0x15, 0x68, 0x4d, 0x6c, 0x69, 0x6d, 0x6e, 0x70, 0x85, 0x73,
- 0x8a, 0x74, 0xa0, 0x04, 0x19, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x68, 0x02, 0x00, 0x09, 0x40, 0x5e, 0x6f, 0x6c, 0x65, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x0b, 0x79, 0x24, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x40, 0x08, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40,
- 0x00, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02,
- 0x01, 0x72, 0x40, 0x47, 0x61, 0x63, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x65, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0xb2, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x00, 0xe3, 0x6b, 0x00,
- 0x74, 0x05, 0x77, 0x09, 0x40, 0x09, 0x69, 0x6e, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0x40, 0x00, 0x69, 0x6c, 0x6c, 0x00, 0x40, 0x09, 0x61, 0x69, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00,
- 0xa5, 0x00, 0x07, 0x40, 0x06, 0x74, 0x61, 0x66, 0x66, 0x00, 0xe8, 0x61,
- 0x00, 0x63, 0x0d, 0x65, 0x14, 0x66, 0x1f, 0x67, 0x37, 0x69, 0x4c, 0x6c,
- 0x51, 0x6f, 0x9f, 0xe2, 0x66, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x09,
- 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x68, 0x61, 0x72, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x75, 0x02, 0x03, 0xdf, 0x40, 0x09, 0x70, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x00,
- 0x3f, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x09, 0x67, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x62, 0x15, 0x69, 0x1a, 0x6f, 0x1f, 0x00,
- 0x47, 0xe2, 0x67, 0x00, 0x72, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0xb2, 0x40, 0x09, 0x6f, 0x78,
- 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x72, 0x04, 0x77,
- 0x08, 0x40, 0x08, 0x6b, 0x00, 0x40, 0xa1, 0x79, 0x00, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x73, 0x08, 0x00, 0x59, 0x40, 0x09, 0x61, 0x73, 0x65, 0x00,
- 0x40, 0x09, 0x6c, 0x69, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x68, 0x02, 0x01, 0x4a, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x06, 0x70, 0x0d, 0x40, 0x09, 0x6e, 0x74, 0x6f, 0x00,
- 0x40, 0x09, 0x65, 0x6e, 0x74, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x6c, 0x09, 0x03, 0x17, 0x40, 0x09, 0x72, 0x6e, 0x65, 0x6c, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x1a, 0x00, 0xf3, 0xc1, 0x61, 0x19, 0x37,
- 0x00, 0x39, 0x00, 0x48, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x63, 0x00, 0x83,
- 0x00, 0x8c, 0x00, 0x8e, 0x00, 0x9d, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xd6, 0x00, 0xf8, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x16, 0x01, 0x29, 0x01, 0x32, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00,
- 0x00, 0x3d, 0x01, 0x00, 0x06, 0xe2, 0x66, 0x00, 0x74, 0x06, 0x40, 0x09,
- 0x6f, 0x72, 0x65, 0x00, 0x40, 0x09, 0x61, 0x00, 0x40, 0x07, 0x61, 0x6c,
- 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x68, 0x04, 0x75, 0x06, 0x40, 0x09, 0x72,
- 0x00, 0x00, 0x59, 0x40, 0x09, 0x73, 0x68, 0x69, 0x6f, 0x6e, 0x00, 0xe5,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x77, 0x0d, 0x79, 0x13, 0x00, 0x4b,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x70, 0x70, 0x6c, 0x65, 0x00, 0x40,
- 0x08, 0x6f, 0x6f, 0x64, 0x00, 0x00, 0x00, 0x40, 0x06, 0x65, 0x61, 0x74,
- 0x68, 0x65, 0x72, 0x00, 0x00, 0xec, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40,
- 0x06, 0x61, 0x64, 0x00, 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x0b, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0x40, 0x2c, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07,
- 0x6e, 0x12, 0x6f, 0x18, 0x04, 0x1a, 0x40, 0x07, 0x79, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x00, 0x68, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x09, 0xe4, 0x61, 0x00, 0x65, 0x0e, 0x69,
- 0x12, 0x79, 0x17, 0xe2, 0x63, 0x00, 0x74, 0x05, 0x40, 0x06, 0x6c, 0x65,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x37, 0x6e,
- 0x67, 0x00, 0x00, 0x08, 0xe2, 0x63, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x68,
- 0x6c, 0x65, 0x00, 0x00, 0x09, 0xe2, 0x6f, 0x00, 0x72, 0x06, 0x40, 0x93,
- 0x69, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x69, 0x63, 0x6b, 0x00, 0xe2, 0x65,
- 0x00, 0x74, 0x07, 0x40, 0x06, 0x74, 0x74, 0x65, 0x72, 0x00, 0x40, 0x1a,
- 0x72, 0x69, 0x70, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09,
- 0x00, 0x09, 0x40, 0x09, 0x70, 0x00, 0x40, 0x95, 0x68, 0x65, 0x65, 0x6c,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06,
- 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x06, 0x40, 0x93, 0x65, 0x65, 0x72,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x22,
- 0x70, 0x2d, 0x73, 0x42, 0x00, 0xfa, 0xe5, 0x00, 0x00, 0x6c, 0x02, 0x72,
- 0x08, 0x74, 0x0a, 0x77, 0x0f, 0x00, 0x09, 0x40, 0x06, 0x69, 0x6e, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x74, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x72,
- 0x6b, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x07, 0x67, 0x00, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0x00, 0x00, 0x40, 0x06,
- 0x71, 0x75, 0x65, 0x61, 0x6b, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x3b, 0x00, 0x82, 0xe2, 0x61, 0x00, 0x6f, 0x1d, 0xe3,
- 0x63, 0x00, 0x6e, 0x04, 0x74, 0x09, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06,
- 0x68, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40, 0x3b,
- 0x63, 0x61, 0x6c, 0x00, 0xe3, 0x67, 0x00, 0x73, 0x04, 0x75, 0x0a, 0x40,
- 0x07, 0x69, 0x00, 0x40, 0x07, 0x68, 0x6b, 0x69, 0x00, 0x40, 0x5e, 0x65,
- 0x74, 0x74, 0x65, 0x00, 0xe4, 0x63, 0x00, 0x6d, 0x0a, 0x73, 0x10, 0x74,
- 0x1c, 0x40, 0x00, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x00, 0x40,
- 0x06, 0x69, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0xc3,
- 0x40, 0x08, 0x69, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x07, 0x69, 0x09,
- 0x6f, 0x19, 0x40, 0x06, 0x63, 0x68, 0x69, 0x6f, 0x00, 0x00, 0x08, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x40, 0x00, 0x61,
- 0x74, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x06, 0x00, 0x06,
- 0xeb, 0x00, 0x00, 0x61, 0x02, 0x63, 0x0e, 0x65, 0x3d, 0x66, 0x53, 0x68,
- 0x59, 0x69, 0x7a, 0x6f, 0xab, 0x74, 0xaf, 0x75, 0xcb, 0x79, 0xd3, 0x00,
- 0x06, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x09, 0x40, 0x06, 0x61, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x0a, 0x66,
- 0x0e, 0x6d, 0x14, 0x00, 0xe7, 0x40, 0x07, 0x6c, 0x65, 0x6e, 0x64, 0x65,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x47, 0x6f, 0x72, 0x6b, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x61, 0x6c, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x79,
- 0x16, 0x00, 0x07, 0x40, 0x08, 0x61, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6e,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0xf4, 0xe3, 0x61, 0x00, 0x66, 0x0f, 0x6c, 0x14, 0xe1, 0x62, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x3b, 0x75, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0c, 0x69,
- 0x10, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x08, 0x40, 0x09, 0x63, 0x65,
- 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x69, 0x74, 0x61, 0x72, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0xa1, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x55, 0x40, 0x00, 0x6c, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x07, 0x40, 0x09, 0x6c, 0x00,
- 0x40, 0x09, 0x65, 0x00, 0xe1, 0x7a, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0b,
- 0x69, 0x11, 0xe2, 0x00, 0x00, 0x7a, 0x02, 0x00, 0x09, 0x40, 0x07, 0x7a,
- 0x00, 0x40, 0x06, 0x72, 0x69, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x00,
- 0x07, 0x40, 0x00, 0x27, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x74,
- 0x0e, 0x77, 0x10, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x72, 0x63, 0x00, 0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0xf7,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0xec, 0x03, 0x69, 0x10, 0x05,
- 0x6f, 0x5b, 0x05, 0x75, 0xec, 0x05, 0x79, 0x4f, 0x07, 0x00, 0x00, 0xfa,
- 0x63, 0x00, 0x00, 0x67, 0x92, 0x00, 0x69, 0xc2, 0x00, 0x6e, 0x48, 0x01,
- 0x71, 0xf2, 0x01, 0x73, 0xf7, 0x01, 0x74, 0x3e, 0x02, 0x75, 0xc7, 0x02,
- 0x79, 0xec, 0x02, 0x7a, 0xc7, 0x03, 0xe4, 0x61, 0x00, 0x65, 0x1c, 0x69,
- 0x6e, 0x6b, 0x84, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x2c, 0x64, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe9, 0x00, 0x00, 0x27, 0x02,
- 0x62, 0x06, 0x64, 0x0a, 0x68, 0x0c, 0x6b, 0x14, 0x6d, 0x28, 0x6e, 0x2e,
- 0x72, 0x3d, 0x00, 0xc5, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x00,
- 0x00, 0x37, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x44, 0x1b, 0x65, 0x6e, 0x74, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x06, 0x00, 0x08, 0x00, 0x06, 0xe2, 0x64, 0x00, 0x6e, 0x0c, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00,
- 0x67, 0x73, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x75,
- 0x27, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x1a,
- 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b,
- 0x00, 0x07, 0x00, 0x07, 0x40, 0x5e, 0x65, 0x00, 0xe4, 0x63, 0x00, 0x64,
- 0x04, 0x6e, 0x06, 0x74, 0x7b, 0x40, 0x00, 0x65, 0x00, 0x00, 0x09, 0xe5,
- 0x00, 0x00, 0x63, 0x02, 0x6e, 0x30, 0x73, 0x36, 0x74, 0x56, 0x02, 0x9b,
- 0xe2, 0x68, 0x00, 0x6c, 0x06, 0x40, 0x00, 0x61, 0x6e, 0x74, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe3, 0x6d, 0x00, 0x6f, 0x0d, 0x70, 0x12, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6f, 0x6b, 0x65, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x98, 0xe2, 0x66, 0x00, 0x76, 0x04,
- 0x40, 0x06, 0x66, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x00, 0x55, 0xe7, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x06, 0x67, 0x35, 0x6b, 0x46, 0x6e, 0x59, 0x74,
- 0x6c, 0x01, 0x00, 0x40, 0x00, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02,
- 0x6c, 0x06, 0x72, 0x0c, 0x74, 0x0e, 0x01, 0x98, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x09, 0x6f, 0x61, 0x64, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x06, 0x75, 0x6d, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x74, 0x07, 0x00, 0x55, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x06, 0x40, 0x08, 0x6e, 0x67,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x15, 0x69, 0x19, 0x6c, 0x1e,
- 0x02, 0xb5, 0xe3, 0x69, 0x00, 0x72, 0x04, 0x74, 0x06, 0x40, 0x06, 0x6e,
- 0x00, 0x00, 0x00, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00,
- 0x40, 0x06, 0x75, 0x65, 0x00, 0xe3, 0x68, 0x00, 0x6d, 0x02, 0x74, 0x06,
- 0x00, 0x47, 0x40, 0x07, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x17, 0xe1,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x65, 0x09, 0x00, 0xfa, 0x40,
- 0x07, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x63,
- 0x00, 0x71, 0x14, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x74,
- 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x40,
- 0x00, 0x75, 0x65, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x66, 0x1f, 0x69,
- 0x25, 0x6f, 0x49, 0x74, 0x57, 0x79, 0x6a, 0x04, 0x1c, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x66, 0x06, 0x6c, 0x0b, 0x6e, 0x10, 0x00, 0x09, 0x40, 0x2c,
- 0x75, 0x00, 0x40, 0x06, 0x75, 0x6c, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00,
- 0x00, 0x07, 0x40, 0x93, 0x6f, 0x72, 0x6d, 0x00, 0xe2, 0x6e, 0x00, 0x74,
- 0x0b, 0xe2, 0x67, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x6f,
- 0x05, 0x40, 0x00, 0x69, 0x63, 0x00, 0x40, 0x93, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x70, 0x02, 0x73, 0x07,
- 0x00, 0x07, 0x40, 0x09, 0x75, 0x73, 0x00, 0x00, 0x00, 0xe2, 0x64, 0x00,
- 0x73, 0x05, 0x40, 0x06, 0x69, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62,
- 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x1b, 0x65, 0x37, 0x66, 0x3b, 0x67, 0x57, 0x68,
- 0x79, 0x6c, 0x80, 0x6d, 0x86, 0x6f, 0x8c, 0x70, 0x91, 0x72, 0x96, 0x73,
- 0x9c, 0x74, 0xa4, 0x77, 0xb4, 0x04, 0x1d, 0xe2, 0x62, 0x00, 0x63, 0x05,
- 0x44, 0x1e, 0x6c, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x5b, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x05, 0x6f, 0x0a, 0x40, 0x09, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x6c, 0x6c,
- 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x04, 0x40, 0x09, 0x6b, 0x00, 0x00, 0x06,
- 0x40, 0x06, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x07, 0x40, 0x06, 0x6c,
- 0x6c, 0x6f, 0x77, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x69, 0x00, 0x6f,
- 0x05, 0x72, 0x0a, 0x40, 0x09, 0x72, 0x6c, 0x00, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x6e, 0x00, 0x70, 0x04,
- 0x40, 0x06, 0x64, 0x00, 0x00, 0x08, 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65,
- 0x00, 0x40, 0x09, 0x69, 0x73, 0x74, 0x00, 0x40, 0x09, 0x61, 0x74, 0x65,
- 0x00, 0x40, 0x06, 0x66, 0x66, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x00, 0x40,
- 0x06, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x08, 0x63, 0x68, 0x6f, 0x6f, 0x6c,
- 0x00, 0xe2, 0x68, 0x00, 0x69, 0x06, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x6d, 0x65, 0x00, 0x40, 0x06, 0x72, 0x69, 0x67, 0x68, 0x74,
- 0x00, 0x40, 0x09, 0x61, 0x00, 0xf9, 0x61, 0x00, 0x00, 0x62, 0x68, 0x00,
- 0x63, 0x8b, 0x00, 0x64, 0x9c, 0x00, 0x6e, 0xa1, 0x00, 0x6f, 0xdf, 0x00,
- 0x74, 0xe6, 0x00, 0x75, 0xed, 0x00, 0x78, 0x03, 0x01, 0xe4, 0x00, 0x00,
- 0x64, 0x02, 0x73, 0x14, 0x74, 0x5d, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x04, 0x1f, 0x40, 0x07, 0x72, 0x00, 0x40, 0x12, 0x6e,
- 0x67, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x1f, 0x69, 0x21, 0x75, 0x26, 0xe1,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06,
- 0x72, 0x0c, 0x04, 0x20, 0x40, 0x00, 0x72, 0x00, 0x40, 0xdb, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x79, 0x00, 0x02, 0xef, 0x42, 0xde, 0x6e, 0x67,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x00, 0x62,
- 0x6c, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x04, 0x21, 0x40, 0x00,
- 0x75, 0x6c, 0x00, 0x00, 0x55, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x06,
- 0x69, 0x12, 0x00, 0x08, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40, 0x09, 0x73, 0x63,
- 0x69, 0x74, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x09, 0x6d, 0x00, 0x40, 0x5e, 0x67,
- 0x65, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x05, 0x74, 0x1c, 0x75, 0x31, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0xe2, 0x70, 0x00, 0x74, 0x0c, 0x40, 0x06, 0x6f,
- 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x72, 0x79, 0x00, 0x40, 0x06, 0x75,
- 0x64, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x06, 0x79, 0x0c, 0x40, 0x00,
- 0x6f, 0x75, 0x73, 0x00, 0x40, 0x3b, 0x66, 0x75, 0x6c, 0x00, 0x00, 0x07,
- 0x40, 0x08, 0x6d, 0x00, 0x40, 0x09, 0x6e, 0x61, 0x73, 0x6d, 0x00, 0x40,
- 0x07, 0x68, 0x6f, 0x72, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x07, 0x73, 0x79, 0x00, 0x40, 0x09, 0x75, 0x73, 0x00, 0xe5, 0x61, 0x00,
- 0x65, 0x20, 0x67, 0x25, 0x6d, 0x2a, 0x6e, 0x31, 0xe2, 0x62, 0x00, 0x6e,
- 0x10, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x3b, 0x40, 0x07, 0x72, 0x73, 0x00, 0x40, 0x2c, 0x68,
- 0x74, 0x00, 0x40, 0x08, 0x73, 0x6f, 0x6c, 0x6c, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe8, 0x64, 0x00, 0x6e, 0x1a, 0x70, 0x1e, 0x73, 0x33, 0x74, 0x39, 0x76,
- 0x53, 0x77, 0x58, 0x79, 0x75, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x08,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x09, 0x40, 0x08, 0x6e, 0x67, 0x00, 0x41, 0x4b, 0x6b, 0x00, 0xe2,
- 0x00, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x69, 0x76,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x6d, 0x02, 0x73, 0x0f, 0x00, 0x59, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09, 0x68, 0x61, 0x72,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x08, 0x40, 0x00, 0x73,
- 0x00, 0xf9, 0x63, 0x00, 0x00, 0x67, 0x1d, 0x00, 0x6d, 0x46, 0x00, 0x6e,
- 0x9a, 0x00, 0x70, 0xc0, 0x00, 0x72, 0xc9, 0x00, 0x73, 0x01, 0x01, 0x74,
- 0x19, 0x01, 0x76, 0x41, 0x01, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x11, 0x00, 0x47, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe5, 0x00,
- 0x00, 0x27, 0x02, 0x67, 0x06, 0x68, 0x14, 0x69, 0x1a, 0x01, 0x43, 0x40,
- 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x37, 0x64, 0x00,
- 0x40, 0x37, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x6f, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x6e, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x62, 0x07, 0x65, 0x1e,
- 0x6d, 0x20, 0x70, 0x36, 0x79, 0x43, 0x00, 0x59, 0x40, 0x07, 0x67, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0b, 0x03, 0xc5, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x0f, 0xe3, 0x72, 0x00, 0x73, 0x02,
- 0x74, 0x06, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x00, 0x93, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0x77, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0xf3, 0xe3, 0x64, 0x00, 0x67, 0x11, 0x6b, 0x1d, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfa, 0x40,
- 0x07, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x7e, 0x00, 0x07, 0x00, 0x47, 0x40, 0x06, 0x65, 0x72, 0x66, 0x65, 0x63,
- 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe3, 0x73, 0x00, 0x74, 0x12, 0x7a, 0x16, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe2, 0x00,
- 0x00, 0x68, 0x02, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x79, 0x08,
- 0x03, 0xc4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf3, 0xe1, 0x6f,
- 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x1a, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07, 0x69, 0x75,
- 0x6d, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x77,
- 0x02, 0x04, 0x22, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x00, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x16, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2,
- 0x63, 0x00, 0x6e, 0x1a, 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x63,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x75, 0x06, 0x40, 0x00, 0x6c, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x69, 0x61, 0x00, 0xc0,
- 0x61, 0x18, 0x33, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x8a, 0x00, 0xc4, 0x00,
- 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0xa6, 0x01,
- 0xba, 0x01, 0x79, 0x05, 0xe1, 0x05, 0x6e, 0x06, 0xd3, 0x06, 0x00, 0x00,
- 0xaf, 0x07, 0x63, 0x09, 0x36, 0x0c, 0x47, 0x0d, 0xab, 0x0d, 0xb2, 0x0d,
- 0x09, 0x0e, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x2f,
- 0x00, 0x59, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x66, 0x08,
- 0x6b, 0x0d, 0x00, 0x2c, 0x40, 0x06, 0x6f, 0x6f, 0x6b, 0x00, 0x40, 0x06,
- 0x75, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00,
- 0x76, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x40,
- 0x55, 0x61, 0x72, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x64, 0x08,
- 0x69, 0x16, 0x00, 0x06, 0x40, 0x06, 0x61, 0x73, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe2, 0x61, 0x00, 0x75, 0x12, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40,
- 0x06, 0x6d, 0x00, 0xe3, 0x6d, 0x00, 0x73, 0x02, 0x74, 0x06, 0x00, 0x09,
- 0x40, 0x07, 0x79, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x69,
- 0x0e, 0x72, 0x1c, 0x00, 0x09, 0x40, 0x09, 0x73, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x09, 0x73, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x08, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40,
- 0x06, 0x72, 0x6f, 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6e, 0x16,
- 0x73, 0x78, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b,
- 0xe3, 0x63, 0x00, 0x73, 0x07, 0x74, 0x0f, 0x40, 0x06, 0x69, 0x61, 0x6e,
- 0x61, 0x00, 0x40, 0x06, 0x65, 0x74, 0x74, 0x69, 0x61, 0x00, 0xe6, 0x00,
- 0x00, 0x62, 0x02, 0x65, 0x09, 0x69, 0x12, 0x6c, 0x27, 0x79, 0x3d, 0x00,
- 0xe7, 0x40, 0x00, 0x6c, 0x61, 0x6e, 0x6b, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x3b, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x60, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x82, 0xe1, 0x6e, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6f, 0x0b, 0x00, 0xe4, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x75, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x79,
- 0x04, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x09, 0x00, 0x60, 0xf9, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x65, 0x23, 0x00, 0x69, 0x5c, 0x00, 0x6b, 0x2b,
- 0x01, 0x6c, 0x2f, 0x01, 0x6f, 0x9c, 0x01, 0x74, 0xb3, 0x01, 0x79, 0xc7,
- 0x01, 0x00, 0x93, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x41, 0x52, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0x4a,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x63, 0x07, 0x6d, 0x0c, 0x73, 0x28, 0x00,
- 0x09, 0x40, 0x0b, 0x78, 0x65, 0x00, 0x40, 0x09, 0x61, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06,
- 0x73, 0x0b, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x73, 0x74,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x74, 0x61, 0x72, 0x00, 0xe4, 0x63, 0x00,
- 0x6f, 0x46, 0x73, 0x57, 0x74, 0x6a, 0xe2, 0x65, 0x00, 0x79, 0x29, 0xe3,
- 0x00, 0x00, 0x6d, 0x02, 0x77, 0x0f, 0x00, 0x5e, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6d, 0x0a, 0x00,
- 0x06, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x40, 0x08, 0x61,
- 0x6b, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09, 0x40,
- 0x07, 0x79, 0x65, 0x6c, 0x69, 0x74, 0x69, 0x73, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x37, 0x00, 0x07, 0xe4, 0x62, 0x00, 0x65, 0x06, 0x69, 0x1a, 0x79,
- 0x51, 0x40, 0x09, 0x75, 0x72, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02,
- 0x73, 0x08, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x73, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x06, 0x6b, 0x1d, 0x6f, 0x23, 0x73, 0x25, 0x00, 0x08, 0x40, 0x3b, 0x6c,
- 0x00, 0xe2, 0x61, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0x4a,
- 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x06,
- 0x40, 0x47, 0x61, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0f, 0x69,
- 0x13, 0x73, 0x39, 0x75, 0x3f, 0x04, 0x23, 0xe2, 0x63, 0x00, 0x72, 0x04,
- 0x40, 0x09, 0x6b, 0x00, 0x40, 0x08, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe2, 0x6e, 0x00, 0x77, 0x1c, 0xe2, 0x61, 0x00, 0x67, 0x15, 0xe1, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0x00, 0x07, 0x40, 0x06, 0x6f,
- 0x67, 0x00, 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x05, 0x69, 0x12, 0x40, 0x09, 0x6e, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x02, 0x7f, 0x00, 0x37, 0x00, 0x07,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07,
- 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x06, 0x69, 0x73, 0x65, 0x00, 0x40,
- 0x07, 0x75, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x09, 0x40, 0x09, 0x72,
- 0x67, 0x65, 0x69, 0x73, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6e, 0x00,
- 0xfd, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x2c, 0x00, 0x65, 0x34,
- 0x00, 0x67, 0x48, 0x00, 0x68, 0x8c, 0x00, 0x6d, 0xa2, 0x00, 0x6e, 0xee,
- 0x00, 0x70, 0x05, 0x01, 0x73, 0x33, 0x01, 0x74, 0x66, 0x01, 0x75, 0x94,
- 0x01, 0x76, 0xad, 0x01, 0x00, 0x00, 0xe3, 0x63, 0x00, 0x6d, 0x0b, 0x6e,
- 0x11, 0x40, 0x00, 0x72, 0x79, 0x6c, 0x61, 0x6d, 0x69, 0x64, 0x65, 0x00,
- 0x40, 0x08, 0x6f, 0x72, 0x79, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x6f, 0x00, 0x79, 0x05, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x07,
- 0x40, 0x06, 0x6c, 0x69, 0x6e, 0x69, 0x63, 0x00, 0xe2, 0x73, 0x00, 0x74,
- 0x06, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x68, 0x79, 0x6c,
- 0x65, 0x6e, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x6c, 0x16, 0x6f, 0x1b, 0x72,
- 0x29, 0xe1, 0x6d, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x05, 0x79, 0x0a, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x07, 0x40,
- 0x06, 0x6f, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xec, 0x00, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x0f, 0x6f, 0x2e, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x63, 0x00, 0x7a, 0x02, 0x00,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x0b, 0xe1, 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00, 0x75,
- 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x07, 0x40, 0x09, 0x6d, 0x69, 0x61,
- 0x6c, 0x00, 0x40, 0x09, 0x63, 0x6c, 0x65, 0x6f, 0x74, 0x69, 0x64, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x68, 0x0a, 0x72, 0x1b, 0x00, 0x09,
- 0x40, 0x09, 0x70, 0x74, 0x69, 0x64, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x6e, 0x65, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x74, 0x09, 0x79, 0x11, 0x00, 0x00, 0x40, 0x00,
- 0x6d, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x07, 0x79, 0x72, 0x65, 0x6e, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62,
- 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x04, 0x40, 0x00, 0x63, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x08, 0x40, 0x09, 0x63, 0x68, 0x6e,
- 0x69, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6e, 0x15, 0xe1,
- 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00, 0x65, 0x00,
- 0xe2, 0x6e, 0x00, 0x72, 0x0b, 0x41, 0x1a, 0x73, 0x61, 0x74, 0x75, 0x72,
- 0x61, 0x74, 0x65, 0x00, 0x40, 0x09, 0x65, 0x74, 0x68, 0x61, 0x6e, 0x65,
- 0x00, 0x40, 0x00, 0x69, 0x6e, 0x79, 0x6c, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x11, 0x6d, 0x1b, 0x70, 0x26, 0x00, 0x08, 0xe2, 0x64, 0x00,
- 0x6e, 0x04, 0x40, 0x5e, 0x65, 0x00, 0x40, 0x06, 0x64, 0x65, 0x72, 0x00,
- 0x40, 0x09, 0x67, 0x72, 0x61, 0x6e, 0x61, 0x74, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x04, 0x40, 0x93, 0x6c, 0x00, 0x00, 0x08, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x6f, 0x11, 0x00, 0x07, 0xe2, 0x64, 0x00, 0x6e, 0x06, 0x40,
- 0xb1, 0x6f, 0x75, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x00, 0xe3, 0x6d, 0x00,
- 0x73, 0x02, 0x75, 0x08, 0x00, 0x06, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe7, 0x63, 0x00, 0x64, 0x0f, 0x65, 0x39, 0x67,
- 0x3b, 0x69, 0x46, 0x74, 0x4c, 0x79, 0x71, 0xe3, 0x65, 0x00, 0x68, 0x02,
- 0x79, 0x06, 0x00, 0x0b, 0x40, 0x06, 0x6f, 0x00, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6f, 0x06, 0x01, 0x27, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x0b, 0x40, 0x07, 0x65, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x1b, 0xe1, 0x66, 0x00, 0xe2, 0x66, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74,
- 0x02, 0x00, 0x3b, 0x40, 0x5e, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0xa1, 0x40, 0x09, 0x61, 0x69, 0x6c,
- 0x00, 0xe8, 0x00, 0x00, 0x63, 0x02, 0x64, 0x06, 0x66, 0x0b, 0x68, 0x17,
- 0x6c, 0x20, 0x70, 0x35, 0x72, 0x37, 0x00, 0x5b, 0x40, 0x47, 0x68, 0x00,
- 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09,
- 0x40, 0x08, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xec,
- 0x00, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x08, 0x00, 0x59, 0x40,
- 0x09, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x08, 0x69, 0x64, 0x65, 0x00, 0x00,
- 0x59, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x68, 0x07, 0x6e, 0x0e, 0x03, 0x8a,
- 0x40, 0x07, 0x6f, 0x79, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe9, 0x00, 0x00, 0x63, 0x02, 0x65,
- 0x08, 0x67, 0x0a, 0x69, 0x0f, 0x6c, 0x16, 0x6f, 0x23, 0x70, 0x29, 0x75,
- 0x5d, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x72, 0x6e, 0x00, 0x00, 0x09, 0x40,
- 0x06, 0x75, 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x6a, 0x61, 0x79, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x06, 0x76, 0x65, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x0c, 0x69,
- 0x19, 0x79, 0x1e, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x09, 0x40, 0x08,
- 0x6f, 0x6d, 0x00, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x74, 0x04, 0x00, 0x00,
- 0x00, 0x06, 0x00, 0x08, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x63, 0x6b, 0x00, 0xe2, 0x6c,
- 0x00, 0x70, 0x65, 0xe3, 0x61, 0x00, 0x69, 0x3f, 0x6f, 0x4b, 0xe3, 0x63,
- 0x00, 0x72, 0x04, 0x74, 0x22, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0xdb, 0x79,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x3a, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0xe3, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x01, 0x52, 0x00,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x09, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x09, 0xf9, 0x63,
- 0x00, 0x00, 0x65, 0x1e, 0x00, 0x67, 0x20, 0x00, 0x6b, 0x24, 0x00, 0x6e,
- 0x33, 0x00, 0x6f, 0x6a, 0x00, 0x70, 0x85, 0x00, 0x72, 0xa3, 0x00, 0x74,
- 0xb6, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x07, 0x69, 0x09, 0x75, 0x0e, 0x40,
- 0x06, 0x6c, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x65,
- 0x00, 0x40, 0x06, 0x70, 0x69, 0x6e, 0x65, 0x00, 0x00, 0x82, 0x40, 0x06,
- 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x06, 0x00, 0x27, 0x40,
- 0x07, 0x72, 0x00, 0x01, 0x64, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04,
- 0x79, 0x14, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07,
- 0xe2, 0x73, 0x00, 0x75, 0x06, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x13, 0xe1, 0x79, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x00, 0x74, 0x69, 0x63,
- 0x00, 0x00, 0x07, 0x40, 0x82, 0x69, 0x73, 0x65, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x64, 0x00, 0x6e, 0x05, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x06,
- 0x67, 0x65, 0x72, 0x00, 0xec, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x63,
- 0x23, 0x65, 0x2b, 0x66, 0x51, 0x68, 0x58, 0x69, 0x5e, 0x6c, 0x7c, 0x6d,
- 0x90, 0x72, 0x99, 0x75, 0xc2, 0x04, 0x24, 0x40, 0x77, 0x73, 0x00, 0xe3,
- 0x62, 0x00, 0x67, 0x10, 0x6c, 0x14, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40,
- 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x5e,
- 0x65, 0x00, 0x00, 0x06, 0x40, 0x09, 0x75, 0x6c, 0x6c, 0x69, 0x73, 0x00,
- 0xe2, 0x6e, 0x00, 0x72, 0x13, 0xe2, 0x64, 0x00, 0x74, 0x02, 0x00, 0x5b,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x3e, 0x75, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x65, 0x40, 0x06, 0x6f, 0x75, 0x73,
- 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x69, 0x6f, 0x00, 0x40, 0x09, 0x6f,
- 0x6c, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x65, 0x0e, 0x6f, 0x13, 0xe1, 0x6f,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x09, 0x72, 0x65, 0x00, 0x44, 0x25, 0x6e, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x04, 0x79, 0x0b, 0x40, 0x09, 0x74, 0x00, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x15, 0x40, 0x09, 0x61, 0x6e, 0x74, 0x65, 0x61,
- 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x16, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75, 0x07, 0x00, 0x09, 0x40, 0x06,
- 0x73, 0x74, 0x00, 0x40, 0x07, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x5b, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x63,
- 0x61, 0x00, 0xf6, 0x65, 0x00, 0x00, 0x68, 0x15, 0x00, 0x69, 0x17, 0x00,
- 0x73, 0x66, 0x00, 0x74, 0xbd, 0x00, 0x79, 0xbe, 0x02, 0xe4, 0x00, 0x00,
- 0x27, 0x02, 0x72, 0x06, 0x75, 0x08, 0x04, 0x26, 0x40, 0x77, 0x73, 0x00,
- 0x04, 0x27, 0x40, 0x06, 0x72, 0x00, 0x00, 0x60, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x72, 0x40, 0x01, 0xde, 0xe2, 0x6f, 0x00, 0x76,
- 0x1b, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x69,
- 0x0a, 0x04, 0x28, 0x41, 0xef, 0x6c, 0x00, 0x41, 0xef, 0x64, 0x00, 0x41,
- 0xef, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x44, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x08, 0x40, 0x09,
- 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x32, 0x75, 0x4a,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x1b, 0x04, 0x29, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x65, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x02, 0x12, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x72, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x06,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xc1, 0x61, 0x17, 0x33, 0x00, 0x35,
- 0x00, 0x40, 0x00, 0x4d, 0x00, 0x75, 0x00, 0x90, 0x00, 0x00, 0x00, 0xa7,
- 0x00, 0xb1, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x00, 0xf4,
- 0x00, 0x5d, 0x01, 0x6f, 0x01, 0x7a, 0x01, 0x00, 0x00, 0x00, 0x00, 0xac,
- 0x01, 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0xe8, 0x01, 0x04, 0x2a, 0xe2,
- 0x67, 0x00, 0x6c, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x04, 0x40, 0x08, 0x67, 0x00, 0x40, 0x08, 0x78, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x72, 0x64, 0x00, 0xe3, 0x64, 0x00,
- 0x6c, 0x04, 0x6e, 0x0c, 0x40, 0x08, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x6e,
- 0x69, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x73, 0x6f, 0x6e, 0x61, 0x6e, 0x74,
- 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x3a, 0x74, 0x65,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x6f, 0x72, 0x61, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x07, 0xe2, 0x6f, 0x00, 0x74, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x72, 0x61, 0x64, 0x75, 0x61,
- 0x74, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x75, 0x06, 0x79, 0x0d, 0x40, 0x00,
- 0x73, 0x74, 0x65, 0x00, 0x40, 0x3b, 0x6d, 0x6f, 0x75, 0x73, 0x00, 0x40,
- 0x00, 0x70, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x00, 0xe3, 0x65, 0x00, 0x6c,
- 0x02, 0x6e, 0x08, 0x00, 0x08, 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x64, 0x00, 0x67, 0x0a, 0x40, 0x00, 0x75, 0x73, 0x74, 0x72, 0x69, 0x61,
- 0x6c, 0x00, 0x00, 0x07, 0x40, 0x06, 0x75, 0x64, 0x65, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x13, 0x69, 0x30, 0x6f, 0x39, 0xe3, 0x6e, 0x00, 0x72, 0x02,
- 0x73, 0x06, 0x00, 0x07, 0x40, 0x2c, 0x6b, 0x00, 0x40, 0x09, 0x74, 0x65,
- 0x72, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x10, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x70, 0x61, 0x75, 0x73, 0x61, 0x6c, 0x00, 0x40,
- 0x00, 0x69, 0x64, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x09, 0x73, 0x74, 0x72,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x1c, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x09, 0x40, 0x06, 0x74, 0x65, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x73,
- 0x00, 0x74, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x61, 0x6c,
- 0x00, 0x40, 0x00, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00,
- 0xe3, 0x61, 0x00, 0x6f, 0x0f, 0x72, 0x22, 0xe2, 0x69, 0x00, 0x72, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x74, 0x75, 0x6d, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x02, 0x51, 0x40,
- 0x06, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x64, 0x69, 0x61,
- 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x65, 0x07, 0x40, 0x06, 0x72, 0x69, 0x70,
- 0x74, 0x00, 0x40, 0x06, 0x61, 0x73, 0x6f, 0x6e, 0x00, 0xe2, 0x6c, 0x00,
- 0x72, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x01, 0xcd, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x04, 0x69, 0x06, 0x40, 0x00, 0x6c, 0x00, 0x01, 0x01, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x72, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x00, 0x06, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x62, 0x34,
- 0x65, 0x46, 0x66, 0x78, 0x68, 0x7d, 0x69, 0xa9, 0x6c, 0xae, 0x70, 0xb4,
- 0x73, 0xc4, 0x74, 0xd5, 0x01, 0x82, 0xe3, 0x62, 0x00, 0x73, 0x10, 0x74,
- 0x1d, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x68, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x06, 0x40, 0x1a, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x69, 0x6c, 0x65,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x3b, 0x40,
- 0x09, 0x74, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x0c,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0x40, 0x06, 0x74, 0x79, 0x00,
- 0x40, 0x0b, 0x65, 0x00, 0x40, 0x06, 0x75, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x12, 0xe2, 0x61, 0x00, 0x72, 0x04, 0x40, 0x06, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x2c, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6f,
- 0x0c, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40, 0x09, 0x65, 0x72, 0x00, 0x00,
- 0x7e, 0x40, 0x06, 0x6b, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x09,
- 0x75, 0x63, 0x6b, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x65,
- 0x00, 0x40, 0x06, 0x75, 0x72, 0x72, 0x69, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x15, 0x79, 0x1a, 0x40, 0x07,
- 0x67, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x95, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x02, 0x13, 0xe6, 0x63, 0x00, 0x66, 0x04, 0x6c, 0x0f, 0x6e, 0x28, 0x72,
- 0x4a, 0x74, 0x4c, 0x40, 0x47, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02,
- 0x00, 0x08, 0x40, 0x08, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x06, 0x72, 0x0b, 0x40, 0x09, 0x72, 0x65, 0x72, 0x00, 0x40, 0x5e,
- 0x63, 0x65, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x63, 0x00, 0x64, 0x04,
- 0x40, 0x5e, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x69,
- 0x0b, 0x04, 0x2b, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x67, 0x65, 0x00,
- 0x40, 0x06, 0x6e, 0x67, 0x00, 0x01, 0x32, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x74, 0x79,
- 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x65, 0x11, 0x77, 0x49, 0x00, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x95, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x66,
- 0x08, 0x68, 0x0d, 0x6c, 0x14, 0x00, 0x47, 0x40, 0x09, 0x6f, 0x61, 0x74,
- 0x00, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x93, 0x6f, 0x77, 0x00, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x65, 0x53, 0x01, 0x69, 0x01, 0x0c, 0x6f, 0x0e, 0x0f, 0x75,
- 0x8d, 0x1a, 0x79, 0xee, 0x1a, 0x00, 0x00, 0xfb, 0x63, 0x00, 0x00, 0x65,
- 0x48, 0x00, 0x67, 0x5d, 0x00, 0x69, 0x82, 0x00, 0x6c, 0xb0, 0x00, 0x6d,
- 0xb6, 0x00, 0x6e, 0xb8, 0x00, 0x73, 0xe1, 0x00, 0x74, 0xec, 0x00, 0x77,
- 0x15, 0x01, 0x79, 0x19, 0x01, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x35, 0xe3, 0x61, 0x00, 0x65, 0x21, 0x75, 0x2a, 0xe2,
- 0x62, 0x00, 0x6c, 0x10, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x56, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x03, 0xb2, 0x00, 0x37, 0x40, 0x06, 0x6d, 0x00, 0x40, 0x06, 0x69,
- 0x6f, 0x6e, 0x65, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x61,
- 0x6e, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x09, 0xe2, 0x72, 0x00, 0x73, 0x05, 0x40, 0x06, 0x69, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x7c, 0xe1,
- 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x5d, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0x00, 0x09, 0xe3, 0x63, 0x00,
- 0x67, 0x13, 0x6b, 0x15, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x00,
- 0x3a, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x06, 0x74, 0x65,
- 0x72, 0x00, 0x40, 0x07, 0x65, 0x6f, 0x64, 0x79, 0x6d, 0x69, 0x75, 0x6d,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x66, 0x0b, 0x74, 0x11, 0x00, 0x08,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x06, 0x61,
- 0x6c, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x47, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x3f, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x66,
- 0x02, 0x00, 0x07, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0xc0, 0x61, 0x1a, 0x37,
- 0x00, 0x00, 0x00, 0x93, 0x00, 0x25, 0x02, 0x5c, 0x03, 0xaf, 0x03, 0x5b,
- 0x04, 0x76, 0x04, 0x00, 0x00, 0xba, 0x04, 0xe8, 0x04, 0xf6, 0x04, 0x2a,
- 0x05, 0xc3, 0x05, 0xde, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x13, 0x07, 0x51,
- 0x07, 0x80, 0x09, 0x00, 0x00, 0x1a, 0x0a, 0xa1, 0x0a, 0x00, 0x00, 0xa6,
- 0x0a, 0xa8, 0x0a, 0xe5, 0x63, 0x00, 0x64, 0x1a, 0x6d, 0x26, 0x72, 0x2c,
- 0x73, 0x48, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06,
- 0x79, 0x0c, 0x01, 0x18, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x00, 0xf3, 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x73, 0x63, 0x65,
- 0x6e, 0x63, 0x65, 0x00, 0x40, 0x82, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x00, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x00, 0xf6,
- 0x61, 0x00, 0x00, 0x65, 0x51, 0x00, 0x69, 0x79, 0x00, 0x6c, 0xe8, 0x00,
- 0x6f, 0xfa, 0x00, 0x75, 0x6a, 0x01, 0xe4, 0x6e, 0x00, 0x72, 0x13, 0x73,
- 0x2c, 0x75, 0x30, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6c, 0x00,
- 0x72, 0x02, 0x00, 0x2c, 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0xe2, 0x64, 0x00, 0x70, 0x15, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3a, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x06, 0x40, 0x06, 0x72, 0x00, 0xe4, 0x6e, 0x00, 0x6f, 0x05,
- 0x70, 0x20, 0x73, 0x4b, 0x40, 0x09, 0x63, 0x74, 0x00, 0xe2, 0x73, 0x00,
- 0x75, 0x06, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x15, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x04, 0x2c, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x0f, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x2d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75,
- 0x00, 0xe2, 0x64, 0x00, 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x63, 0x00, 0x67, 0x1f, 0x6c, 0x38, 0x6e,
- 0x40, 0x6f, 0x61, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13, 0xe1,
- 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40,
- 0x00, 0x6f, 0x6e, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x64, 0x14,
- 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x70, 0x05, 0x40, 0x0b, 0x76, 0x65,
- 0x00, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x55, 0x69, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0xad, 0x6b, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x06, 0x00, 0x00, 0xf4, 0x61, 0x00, 0x00, 0x65, 0x1c, 0x00,
- 0x69, 0x84, 0x00, 0x6f, 0x0a, 0x01, 0xe2, 0x74, 0x00, 0x77, 0x13, 0xe2,
- 0x65, 0x00, 0x6f, 0x02, 0x00, 0x3a, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe4, 0x63,
- 0x00, 0x66, 0x13, 0x73, 0x1a, 0x74, 0x3b, 0xe1, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x73, 0x05, 0x40, 0x0b, 0x73, 0x65, 0x00, 0x40, 0x06, 0x73, 0x6f,
- 0x72, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x64, 0x00, 0xe2, 0x69, 0x00,
- 0x74, 0x08, 0x40, 0x0b, 0x67, 0x6e, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe4, 0x63, 0x00, 0x67, 0x57, 0x6c,
- 0x5d, 0x73, 0x66, 0xe2, 0x61, 0x00, 0x74, 0x26, 0xe3, 0x62, 0x00, 0x6d,
- 0x05, 0x74, 0x0b, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x65, 0x6e,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0x59, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x1a, 0x6f, 0x1f, 0x04, 0x2e, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0xdb, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x37, 0x40, 0x06, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x0b, 0x65, 0x73, 0x74, 0x00,
- 0x40, 0x06, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x0b, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6d, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74,
- 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0x44, 0x2f, 0x65, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x34, 0x78, 0x36, 0xe2,
- 0x69, 0x00, 0x70, 0x18, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x06, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x01, 0xeb, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x3b, 0x65, 0x00, 0x00, 0x3a, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x72, 0x40, 0x07, 0x6e,
- 0x63, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x42, 0x69, 0x8f,
- 0x6f, 0x9c, 0x00, 0x00, 0xe3, 0x62, 0x00, 0x63, 0x2f, 0x74, 0x33, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x72, 0x10, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x5e,
- 0x65, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x79, 0x00, 0xe2, 0x63, 0x00, 0x72,
- 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x06, 0x40,
- 0x09, 0x72, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x6d,
- 0x1a, 0x72, 0x20, 0x04, 0x30, 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40,
- 0x3b, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe2, 0x67, 0x00, 0x78, 0x06, 0x40, 0x0b, 0x75, 0x72, 0x65, 0x00,
- 0x00, 0x47, 0x40, 0xad, 0x72, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x05,
- 0x40, 0x06, 0x6d, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x00, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x10, 0x75, 0x37, 0xe2, 0x61, 0x00, 0x6e, 0x04, 0x40, 0xad,
- 0x74, 0x00, 0x40, 0x00, 0x73, 0x69, 0x6c, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x14, 0xe2, 0x61, 0x00, 0x63, 0x04, 0x40, 0x08, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07,
- 0x40, 0x00, 0x6d, 0x61, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x67, 0x00, 0x69, 0x0d, 0xe2, 0x65, 0x00, 0x6d, 0x02, 0x00, 0x0b,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x82, 0x00, 0x37, 0x40,
- 0x00, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x67,
- 0x61, 0x72, 0x74, 0x65, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x0d, 0x75,
- 0x28, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x0e, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x06, 0x6e, 0x61, 0x72, 0x79, 0x00, 0x40, 0x00, 0x65,
- 0x72, 0x61, 0x74, 0x65, 0x00, 0x40, 0x09, 0x64, 0x65, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x12, 0x69, 0x4a, 0x6f, 0x71, 0xe2, 0x72, 0x00, 0x74, 0x07,
- 0x40, 0x00, 0x69, 0x74, 0x61, 0x6c, 0x00, 0x40, 0x3b, 0x75, 0x72, 0x65,
- 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x2a, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0xe2, 0x63, 0x00, 0x74, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x57, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x00, 0x73, 0x74, 0x72, 0x75, 0x61, 0x6c, 0x00, 0xe4, 0x65, 0x00,
- 0x73, 0x14, 0x75, 0x18, 0x78, 0x1c, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x73, 0x04, 0x00, 0x93, 0x00, 0x09, 0x40, 0x09, 0x68, 0x69,
- 0x70, 0x00, 0x40, 0x5e, 0x65, 0x00, 0x40, 0x06, 0x6d, 0x00, 0x00, 0x0b,
- 0xe2, 0x6c, 0x00, 0x6e, 0x05, 0x40, 0x06, 0x61, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x06,
- 0x40, 0x3b, 0x74, 0x61, 0x6c, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x06, 0x40, 0x00, 0x69, 0x61, 0x6c, 0x00, 0xe3, 0x63,
- 0x00, 0x70, 0x17, 0x72, 0x21, 0xe1, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x70, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x00, 0x65, 0x72, 0x61, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0x40, 0x0b, 0x64, 0x61, 0x69, 0x6e, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x6f, 0x58, 0x70, 0xc0, 0x75, 0xd2, 0x00, 0x09, 0xe4, 0x63,
- 0x00, 0x69, 0x11, 0x72, 0x15, 0x79, 0x40, 0xe1, 0x6b, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x05, 0x40, 0x3a, 0x67, 0x65, 0x00, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x12, 0xe1, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x0b, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0xdf, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x04, 0x31, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00,
- 0xe2, 0x6e, 0x00, 0x73, 0x20, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x3b, 0x40, 0x0b, 0x65,
- 0x00, 0xe3, 0x69, 0x00, 0x73, 0x17, 0x74, 0x34, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x0b, 0xe2,
- 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x37, 0x67, 0x00, 0x40, 0x06, 0x6e, 0x00,
- 0x40, 0x3b, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x01, 0x72, 0xe2, 0x62, 0x00, 0x63, 0x1a, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x06, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x09, 0x75, 0x65, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x30,
- 0xe3, 0x63, 0x00, 0x67, 0x06, 0x71, 0x20, 0x40, 0xad, 0x6f, 0x72, 0x64,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x72, 0x04, 0x40, 0x5b, 0x72, 0x00, 0x40, 0x07, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x75, 0x69, 0x73, 0x69, 0x74, 0x65, 0x00,
- 0x40, 0x06, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0xfb, 0x00, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x62, 0x07, 0x00, 0x63, 0x24, 0x00, 0x65, 0x73,
- 0x00, 0x68, 0xf5, 0x00, 0x69, 0x0e, 0x01, 0x6f, 0x37, 0x01, 0x73, 0x3c,
- 0x01, 0x74, 0x92, 0x01, 0x75, 0xb7, 0x01, 0x00, 0x00, 0x40, 0x82, 0x67,
- 0x65, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x06, 0x40, 0x07,
- 0x70, 0x69, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x06, 0xe3, 0x68, 0x00, 0x69, 0x14,
- 0x72, 0x25, 0xe1, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x0f, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x3b, 0xe1, 0x69, 0x00, 0xe2, 0x62, 0x00, 0x70, 0x04, 0x40,
- 0x3a, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x04,
- 0x32, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x3b,
- 0x65, 0x00, 0xe4, 0x61, 0x00, 0x6e, 0x06, 0x72, 0x3d, 0x74, 0x6c, 0x40,
- 0x06, 0x73, 0x6f, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06,
- 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x12, 0x69, 0x16, 0x6d,
- 0x1d, 0x04, 0x33, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x79,
- 0x00, 0x40, 0x65, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x06, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00,
- 0xe1, 0x76, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1e, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x97, 0x00, 0x07, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x05, 0x75, 0x0a, 0x40, 0x00,
- 0x6e, 0x6b, 0x00, 0x40, 0x3c, 0x6e, 0x6b, 0x00, 0x40, 0x00, 0x6e, 0x6b,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x1c, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x61, 0x6c,
- 0x00, 0x40, 0x07, 0x75, 0x6d, 0x00, 0x40, 0x72, 0x72, 0x74, 0x00, 0xe6,
- 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x69, 0x0f, 0x6d, 0x1a, 0x75, 0x27,
- 0x04, 0x34, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x08, 0x40, 0x56,
- 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x5e, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x98, 0x00,
- 0x06, 0xe2, 0x69, 0x00, 0x6f, 0x1e, 0xe2, 0x64, 0x00, 0x67, 0x0c, 0x40,
- 0x07, 0x69, 0x67, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00,
- 0x00, 0x06, 0xe2, 0x6d, 0x00, 0x70, 0x3a, 0xe3, 0x61, 0x00, 0x65, 0x06,
- 0x70, 0x08, 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0x00, 0x87, 0xe1, 0x74,
- 0x00, 0xe2, 0x69, 0x00, 0x75, 0x0d, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40,
- 0x06, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3a, 0x40, 0x09, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x04, 0x72, 0x68, 0x74,
- 0x6e, 0x7a, 0x8a, 0x40, 0x00, 0x78, 0x00, 0xe5, 0x65, 0x00, 0x6e, 0x04,
- 0x72, 0x3b, 0x73, 0x51, 0x78, 0x55, 0x40, 0x09, 0x6e, 0x00, 0xe3, 0x64,
- 0x00, 0x73, 0x0b, 0x74, 0x17, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x4c,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0xba, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x36, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x69, 0x00, 0x6d, 0x04, 0x6e, 0x06,
- 0x40, 0x06, 0x74, 0x00, 0x00, 0x00, 0x40, 0x3b, 0x61, 0x74, 0x75, 0x72,
- 0x61, 0x6c, 0x00, 0x40, 0x72, 0x74, 0x00, 0x40, 0x09, 0x74, 0x00, 0x40,
- 0x08, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x15, 0xe3, 0x66,
- 0x00, 0x6c, 0x04, 0x6e, 0x08, 0x40, 0x0b, 0x79, 0x00, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x04, 0x35, 0x40, 0x09, 0x65,
- 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x3c, 0x69, 0x68, 0x00,
- 0x00, 0xe3, 0x69, 0x00, 0x6c, 0x04, 0x72, 0x15, 0x40, 0x72, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x12,
- 0x04, 0x36, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x37, 0x6c, 0x65, 0x00,
- 0x40, 0x09, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x04,
- 0x73, 0x09, 0x40, 0xe7, 0x77, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40,
- 0x09, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x61, 0x72, 0x00, 0x00, 0x59,
- 0x40, 0x08, 0x7a, 0x69, 0x65, 0x00, 0xfc, 0x61, 0x00, 0x00, 0x63, 0x06,
- 0x00, 0x64, 0x51, 0x00, 0x65, 0x60, 0x00, 0x67, 0x8e, 0x00, 0x6d, 0xab,
- 0x00, 0x6e, 0x57, 0x01, 0x6f, 0xd1, 0x01, 0x73, 0x05, 0x02, 0x74, 0x45,
- 0x02, 0x76, 0x4b, 0x02, 0x7a, 0xa3, 0x02, 0x40, 0x00, 0x70, 0x69, 0x63,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x17, 0x6b, 0x25, 0xe4, 0x00, 0x00, 0x27,
- 0x02, 0x6c, 0x06, 0x79, 0x0c, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x00, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72,
- 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6c, 0x06, 0x04, 0x37, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x82, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02,
- 0x00, 0x82, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x68, 0x07,
- 0x6c, 0x0d, 0x00, 0x56, 0x40, 0x09, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6f,
- 0x6f, 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xea, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x21, 0x69, 0x31, 0x6d, 0x50, 0x6e, 0x5e, 0x6f,
- 0x64, 0x70, 0x8a, 0x72, 0x8c, 0x75, 0x92, 0x04, 0x38, 0xe4, 0x63, 0x00,
- 0x6c, 0x04, 0x72, 0x06, 0x74, 0x12, 0x40, 0x07, 0x79, 0x00, 0x00, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x06,
- 0x40, 0x09, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x76, 0x04, 0x00,
- 0x09, 0x00, 0x07, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe2, 0x6e, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x0c, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x67, 0x00, 0x72, 0x1a, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x3b, 0x64, 0x69, 0x61, 0x6c,
- 0x00, 0x00, 0x3a, 0x40, 0x06, 0x6f, 0x73, 0x65, 0x00, 0x40, 0x08, 0x6c,
- 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x4a, 0xe2, 0x65, 0x00, 0x69, 0x22,
- 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6c, 0x07, 0x73, 0x15, 0x00, 0x56, 0x40,
- 0x06, 0x6f, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0x40, 0x09, 0x73, 0x00, 0xe1, 0x70,
- 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x0f, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x56, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x1a, 0x00, 0x37, 0xe6, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x6d, 0x11, 0x6f, 0x19, 0x03, 0x30,
- 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x06,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x75, 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x08, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x79, 0x22, 0x00, 0x09, 0x40, 0x09,
- 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x11, 0xe1,
- 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x00, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0x00, 0x06, 0x00, 0x06, 0xe4, 0x6d, 0x00, 0x6f,
- 0x0d, 0x73, 0x1b, 0x74, 0x31, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x0f, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x00,
- 0x40, 0x00, 0x68, 0x65, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x30, 0x69,
- 0x34, 0x79, 0x4d, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x04, 0x39,
- 0x40, 0x06, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x7a, 0x04, 0x41, 0x82, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x3a, 0x40, 0x06, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x0f, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x64, 0x02, 0x00, 0x5e, 0x00, 0x37, 0x00, 0x00, 0x01, 0x64, 0xe1, 0x65,
- 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x66, 0x04, 0x77, 0x22, 0x00, 0x82,
- 0x00, 0x77, 0xe1, 0x69, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x74, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xc1, 0x62, 0x17, 0x33, 0x00,
- 0x35, 0x00, 0xc8, 0x00, 0x89, 0x01, 0x00, 0x00, 0xf5, 0x01, 0x39, 0x03,
- 0x03, 0x04, 0x00, 0x00, 0x35, 0x04, 0x63, 0x04, 0x6d, 0x04, 0xde, 0x04,
- 0xac, 0x05, 0x0a, 0x06, 0x28, 0x06, 0x00, 0x00, 0xdc, 0x07, 0xf9, 0x07,
- 0x19, 0x09, 0x4d, 0x0a, 0x51, 0x0a, 0x47, 0x0b, 0x60, 0x0b, 0x00, 0x06,
- 0xe5, 0x61, 0x00, 0x65, 0x4d, 0x69, 0x4f, 0x6c, 0x54, 0x6f, 0x75, 0xe2,
- 0x62, 0x00, 0x74, 0x23, 0xe2, 0x69, 0x00, 0x6c, 0x15, 0xe1, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x06, 0x40, 0x00, 0x74, 0x69,
- 0x63, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x06, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x14, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0d, 0x00,
- 0x27, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x00, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x04, 0x3a, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x09, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x6c, 0x60,
- 0x72, 0x75, 0x74, 0xa4, 0x75, 0xa9, 0x00, 0x00, 0x40, 0x07, 0x69, 0x6e,
- 0x65, 0x00, 0xe3, 0x64, 0x00, 0x65, 0x11, 0x73, 0x24, 0xe1, 0x75, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00,
- 0x00, 0x06, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07,
- 0x02, 0xe0, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x07, 0xe1, 0x73, 0x00,
- 0xe5, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x69, 0x0a, 0x6f, 0x1b, 0x00,
- 0x4b, 0x40, 0x00, 0x73, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0xed, 0x40, 0x09,
- 0x6c, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x09, 0x40,
- 0x09, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x76, 0x69,
- 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x24, 0xe1, 0x73, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x41, 0xdc, 0x61, 0x74,
- 0x65, 0x00, 0x40, 0x59, 0x6f, 0x72, 0x00, 0x40, 0x07, 0x72, 0x65, 0x6d,
- 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x75, 0x23, 0x00,
- 0x09, 0xe1, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x0f, 0x79, 0x15, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x06, 0xe1, 0x63,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0f, 0x74, 0x15, 0xe3, 0x00, 0x00, 0x27,
- 0x02, 0x72, 0x06, 0x04, 0x3b, 0x40, 0x00, 0x73, 0x00, 0x00, 0x75, 0x40,
- 0x77, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x65, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x36, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65,
- 0x25, 0x00, 0x66, 0x7b, 0x00, 0x69, 0x80, 0x00, 0x6c, 0xdc, 0x00, 0x6f,
- 0xf2, 0x00, 0x75, 0x0f, 0x01, 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x07, 0x69, 0x14, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x3c, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x32, 0x40, 0x3b, 0x64, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe2, 0x73,
- 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x00, 0x06, 0x40, 0x3b, 0x61,
- 0x6c, 0x00, 0x40, 0x06, 0x68, 0x69, 0x70, 0x00, 0x40, 0x59, 0x65, 0x72,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x14, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00,
- 0x00, 0x86, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x1a, 0x6c, 0x34, 0x04,
- 0x3d, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00,
- 0x37, 0xe2, 0x65, 0x00, 0x72, 0x0f, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x55, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f,
- 0x6c, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x40, 0x56, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x75, 0x05,
- 0x40, 0x00, 0x6d, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x6e, 0x00, 0x73, 0x07, 0x40, 0x06, 0x64, 0x69, 0x74, 0x79, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x27, 0x72,
- 0x68, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x0d, 0xe2, 0x69, 0x00, 0x79,
- 0x06, 0x40, 0x06, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x07, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x07, 0x40, 0x07, 0x72, 0x6f, 0x6e, 0x65, 0x00,
- 0x40, 0x08, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x08, 0x40, 0x00, 0x74,
- 0x68, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x04, 0x74, 0x08, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x45,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x2e, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x04, 0x3e,
- 0xe3, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x18, 0xe2, 0x62, 0x00, 0x74, 0x05,
- 0x40, 0x09, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x03, 0x91, 0x00, 0x09, 0x40, 0x06, 0x6e, 0x67, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03,
- 0x57, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x8f, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x1a, 0x02, 0x3d, 0xe2,
- 0x6f, 0x00, 0x76, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x1a, 0x00, 0x59, 0xe2, 0x6c,
- 0x00, 0x6f, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x00, 0x61, 0x72, 0x79, 0x6f, 0x74, 0x69, 0x63, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x1c, 0x6f, 0x57, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x08, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe2,
- 0x66, 0x00, 0x78, 0x2a, 0xe2, 0x65, 0x00, 0x69, 0x15, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x67,
- 0x00, 0x6e, 0x05, 0x40, 0x06, 0x75, 0x65, 0x00, 0x40, 0x06, 0x67, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x14,
- 0x6f, 0x52, 0x70, 0x77, 0x75, 0xa3, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x74,
- 0x06, 0x40, 0x82, 0x61, 0x64, 0x65, 0x00, 0x40, 0x07, 0x68, 0x69, 0x75,
- 0x6d, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x11, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b,
- 0xe4, 0x63, 0x00, 0x65, 0x12, 0x69, 0x14, 0x73, 0x19, 0xe1, 0x75, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x3b,
- 0x75, 0x73, 0x00, 0x00, 0x5e, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x6f, 0x72, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x74, 0x09, 0x00,
- 0x07, 0x40, 0x06, 0x74, 0x6f, 0x72, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x54, 0x00, 0x07, 0x40, 0x00,
- 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x0b, 0x6e, 0x1a, 0x04, 0x3f, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x37, 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x07, 0x67,
- 0x00, 0x40, 0x07, 0x75, 0x64, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe5, 0x65, 0x00, 0x67, 0x0d,
- 0x6f, 0x1a, 0x74, 0x44, 0x75, 0x48, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0xb2, 0x40, 0x09, 0x6f, 0x72, 0x6e, 0x00, 0xe2, 0x6d, 0x00, 0x75,
- 0x07, 0x40, 0x07, 0x69, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6d, 0x08,
- 0x00, 0x58, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x00, 0x6f, 0x00, 0x40, 0x09, 0x6e, 0x63, 0x69, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x04, 0x40, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x55, 0x40, 0x07, 0x72, 0x00, 0xfa,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x36, 0x00, 0x68, 0x70, 0x00,
- 0x69, 0xc6, 0x00, 0x6f, 0xf6, 0x00, 0x70, 0x30, 0x01, 0x72, 0x3e, 0x01,
- 0x75, 0x7b, 0x01, 0x79, 0x91, 0x01, 0x00, 0x09, 0xe1, 0x67, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x17, 0xe1, 0x64, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x09,
- 0x74, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00,
- 0xe3, 0x6c, 0x00, 0x6e, 0x21, 0x72, 0x28, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x08, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x0e, 0x40, 0x09, 0x6e,
- 0x74, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x73, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x02, 0x21, 0x40, 0x1a, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x33, 0xe3, 0x63, 0x00, 0x73, 0x04, 0x74, 0x10, 0x40, 0x06,
- 0x79, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07, 0x65, 0x72, 0x00,
- 0x00, 0x7e, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x00, 0x06, 0x40,
- 0x09, 0x73, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x63, 0x00, 0x78, 0x06, 0x40, 0x06, 0x74, 0x69, 0x63, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe2, 0x6e, 0x00, 0x74, 0x08, 0x40, 0x07, 0x71, 0x75, 0x69, 0x74, 0x79,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x16, 0xe1, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00,
- 0xe3, 0x6e, 0x00, 0x72, 0x06, 0x73, 0x2e, 0x40, 0x06, 0x65, 0x6e, 0x74,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x90, 0xe2, 0x6c, 0x00, 0x74,
- 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0xde, 0x40, 0x00, 0x74, 0x79,
- 0x00, 0x40, 0x7d, 0x65, 0x00, 0x40, 0x09, 0x61, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe5, 0x61, 0x00,
- 0x69, 0x05, 0x6f, 0x0a, 0x72, 0x21, 0x79, 0x27, 0x40, 0x06, 0x72, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x73, 0x07, 0x00, 0x06, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40,
- 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40,
- 0x00, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x3a, 0x74, 0x65,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0xed, 0x65, 0x00, 0xf7, 0x61, 0x00, 0x00,
- 0x63, 0x13, 0x00, 0x65, 0x3b, 0x00, 0x6f, 0x7e, 0x00, 0x70, 0x83, 0x00,
- 0x74, 0xb9, 0x00, 0x79, 0x08, 0x01, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x07, 0x72, 0x0e, 0x40, 0x06, 0x6e, 0x69,
- 0x75, 0x6d, 0x00, 0x40, 0x07, 0x75, 0x74, 0x74, 0x6f, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x62, 0x00, 0x70, 0x04, 0x41, 0x20, 0x65, 0x00, 0x40, 0x09,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x1a,
- 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x8c, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x5e, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x6d, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07,
- 0x40, 0x06, 0x64, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x72,
- 0x1b, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x75,
- 0x0b, 0x02, 0x3a, 0x40, 0x3b, 0x76, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x09, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00,
- 0xad, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe4,
- 0x61, 0x00, 0x68, 0x05, 0x69, 0x1f, 0x72, 0x34, 0x40, 0x09, 0x74, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0d, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00,
- 0x69, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x86, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x51, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0xf3, 0xf5, 0x61, 0x00, 0x00,
- 0x65, 0x16, 0x00, 0x6f, 0x96, 0x00, 0x72, 0xe7, 0x00, 0x75, 0x0a, 0x01,
- 0xe2, 0x63, 0x00, 0x67, 0x09, 0x40, 0x07, 0x74, 0x69, 0x6e, 0x69, 0x75,
- 0x6d, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x69, 0x73, 0x74, 0x00, 0xe5, 0x61,
- 0x00, 0x63, 0x04, 0x67, 0x50, 0x69, 0x5c, 0x73, 0x60, 0x40, 0x00, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6f,
- 0x31, 0x01, 0xeb, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x16,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x09, 0x74, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x06, 0x00, 0x08, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x08, 0x74, 0x00,
- 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x63, 0x00, 0x6e, 0x05, 0x70,
- 0x07, 0x74, 0x1e, 0x7a, 0x31, 0x40, 0x09, 0x6f, 0x6c, 0x00, 0x00, 0x06,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0xe1,
- 0x79, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x7f,
- 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x00, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40, 0xed, 0x63, 0x74,
- 0x00, 0xe2, 0x64, 0x00, 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x09,
- 0x6e, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x09,
- 0x65, 0x00, 0x00, 0x00, 0x40, 0xda, 0x64, 0x00, 0xe5, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x15, 0x69, 0x46, 0x6f, 0x9e, 0x04, 0x41, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x04, 0x72,
- 0x21, 0x00, 0xc1, 0x00, 0x37, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x64, 0x08,
- 0x69, 0x0d, 0x00, 0x37, 0x40, 0x06, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x3b,
- 0x62, 0x69, 0x61, 0x6c, 0x00, 0xe3, 0x64, 0x00, 0x6e, 0x27, 0x73, 0x43,
- 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x04, 0x72, 0x19,
- 0x01, 0x4b, 0x00, 0x37, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x56, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x07,
- 0x40, 0x3b, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe4, 0x63, 0x00,
- 0x6b, 0x23, 0x6c, 0x3a, 0x73, 0x40, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x08, 0x75, 0x72, 0x00, 0xe1, 0x76,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe3, 0x00,
- 0x00, 0x64, 0x02, 0x72, 0x04, 0x01, 0x4b, 0x00, 0x37, 0x00, 0x07, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x07, 0x00, 0x09, 0x40,
- 0x07, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40,
- 0x07, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x18, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x0b, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x00, 0x06, 0xe3, 0x64,
- 0x00, 0x6e, 0x3a, 0x72, 0x46, 0xe2, 0x65, 0x00, 0x69, 0x22, 0xe3, 0x00,
- 0x00, 0x6e, 0x02, 0x72, 0x17, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40,
- 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0xa5, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x04,
- 0x42, 0xf7, 0x61, 0x00, 0x00, 0x65, 0x1a, 0x00, 0x68, 0x6c, 0x00, 0x69,
- 0x71, 0x00, 0x6f, 0x82, 0x00, 0x73, 0x8b, 0x00, 0x79, 0x8f, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x06, 0x65, 0x72, 0x79,
- 0x00, 0xe2, 0x70, 0x00, 0x75, 0x1b, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x08, 0x73, 0x74, 0x00, 0x00, 0x00, 0xe1, 0x64, 0x00,
- 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x79, 0x26, 0x00, 0x08, 0xe3, 0x00, 0x00,
- 0x6e, 0x02, 0x73, 0x14, 0x00, 0x08, 0xe1, 0x79, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0x40, 0x09, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x40,
- 0x09, 0x61, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x74, 0x61, 0x63, 0x6f, 0x73, 0x69, 0x73, 0x00, 0x40, 0x07, 0x72,
- 0x69, 0x61, 0x73, 0x69, 0x73, 0x00, 0x40, 0x00, 0x74, 0x00, 0xf1, 0x63,
- 0x00, 0x00, 0xf1, 0x68, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x69, 0x26, 0x00, 0x6f, 0x4e, 0x00, 0x73, 0xa3, 0x01, 0x00, 0x47,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x63, 0x18, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x0b, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x3b, 0x6c, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62,
- 0x44, 0x00, 0x64, 0x4c, 0x00, 0x67, 0x53, 0x00, 0x6b, 0x5a, 0x00, 0x6c,
- 0x72, 0x00, 0x6d, 0x8d, 0x00, 0x6e, 0x95, 0x00, 0x70, 0xb1, 0x00, 0x73,
- 0xe5, 0x00, 0x74, 0xfa, 0x00, 0x00, 0x06, 0xe2, 0x63, 0x00, 0x6e, 0x07,
- 0x40, 0x00, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x79, 0x00, 0xe3, 0x73, 0x00, 0x74, 0x11, 0x7a, 0x22, 0xe3,
- 0x65, 0x00, 0x69, 0x04, 0x74, 0x08, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x3a, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x62, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x72,
- 0x61, 0x6d, 0x61, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x69, 0x63, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74,
- 0x05, 0x40, 0x00, 0x69, 0x73, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63,
- 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x65, 0x74, 0x72, 0x69, 0x63, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x22, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x06, 0x73, 0x0d, 0x79, 0x0f,
- 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00, 0x6c, 0x6f, 0x67, 0x79,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0x40, 0x00, 0x61, 0x72, 0x6d, 0x61, 0x63,
- 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x06, 0x00, 0x08, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x6d, 0x61, 0x74,
- 0x69, 0x63, 0x00, 0xe3, 0x68, 0x00, 0x69, 0x18, 0x72, 0x28, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x06, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x40, 0x09, 0x6f, 0x70, 0x69, 0x63, 0x00, 0x00, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x0b, 0x6f, 0x16, 0x01, 0x63, 0x40, 0x09,
- 0x72, 0x6d, 0x69, 0x67, 0x61, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x6f, 0x64,
- 0x61, 0x63, 0x74, 0x79, 0x6c, 0x00, 0x40, 0x06, 0x6d, 0x61, 0x69, 0x6e,
- 0x65, 0x00, 0xff, 0x62, 0x00, 0x00, 0x63, 0x98, 0x00, 0x64, 0xbf, 0x00,
- 0x65, 0xff, 0x00, 0x66, 0x24, 0x01, 0x67, 0x4f, 0x01, 0x6b, 0x98, 0x01,
- 0x6c, 0xa3, 0x01, 0x6d, 0x5c, 0x02, 0x6e, 0x91, 0x02, 0x70, 0x97, 0x03,
- 0x72, 0xe0, 0x03, 0x73, 0x8b, 0x05, 0x74, 0x2e, 0x06, 0x7a, 0xb9, 0x06,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x2d, 0x6c, 0x36, 0x00, 0x06, 0xe2,
- 0x72, 0x00, 0x73, 0x0e, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x2f, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x0f, 0x6c, 0x22, 0x00, 0x75, 0xe2, 0x6e,
- 0x00, 0x74, 0x02, 0x00, 0x69, 0x40, 0x65, 0x69, 0x6f, 0x6e, 0x00, 0xe3,
- 0x73, 0x00, 0x74, 0x04, 0x7a, 0x08, 0x40, 0x09, 0x74, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe1, 0x68,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x11, 0x00, 0x4b,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6b,
- 0x02, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x00,
- 0x40, 0x2f, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4,
- 0x00, 0x00, 0x64, 0x02, 0x65, 0x18, 0x67, 0x29, 0x00, 0x08, 0xe2, 0x69,
- 0x00, 0x6c, 0x05, 0x40, 0x06, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x5e, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6d,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x0c, 0xe2, 0x62, 0x00, 0x72, 0x05, 0x40, 0x06, 0x6c, 0x6f,
- 0x00, 0xe2, 0x69, 0x00, 0x70, 0x0f, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00, 0x65,
- 0x72, 0x61, 0x6c, 0x00, 0xe1, 0x66, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02,
- 0x65, 0x08, 0x69, 0x0c, 0x79, 0x1b, 0x00, 0xc3, 0x40, 0x06, 0x61, 0x6c,
- 0x6c, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x6e, 0x1d, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74,
- 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x6b, 0x02, 0x00, 0x82, 0x40, 0x00, 0x61, 0x00, 0xe7,
- 0x63, 0x00, 0x65, 0x20, 0x6c, 0x22, 0x6d, 0x4e, 0x70, 0x56, 0x73, 0x76,
- 0x76, 0x90, 0xe1, 0x68, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x0b,
- 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x6f, 0x15, 0x00, 0xc3, 0x40,
- 0x09, 0x61, 0x63, 0x6b, 0x00, 0xe3, 0x72, 0x00, 0x74, 0x02, 0x79, 0x04,
- 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0xe2, 0x75, 0x00, 0x76, 0x04, 0x40,
- 0x09, 0x74, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x6e,
- 0x61, 0x72, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x77, 0x0f, 0x79,
- 0x15, 0x00, 0x59, 0xe2, 0x6e, 0x00, 0x74, 0x06, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x01, 0x15,
- 0xe2, 0x61, 0x00, 0x65, 0x13, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x04, 0x43, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0xe4, 0x61, 0x00, 0x69, 0x02, 0x6d, 0x07, 0x70,
- 0x0c, 0x00, 0x09, 0x40, 0x06, 0x63, 0x65, 0x00, 0x40, 0x5b, 0x65, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6b, 0x14, 0x00, 0xc3, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x63,
- 0x6b, 0x65, 0x6c, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x00, 0xea, 0x00, 0x00,
- 0x63, 0x02, 0x64, 0x77, 0x67, 0x88, 0x69, 0x99, 0x6b, 0xc9, 0x6e, 0xcb,
- 0x73, 0xde, 0x74, 0xe4, 0x79, 0xef, 0x00, 0x06, 0xe2, 0x68, 0x00, 0x74,
- 0x25, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x07, 0x6c, 0x12, 0x79, 0x18,
- 0x00, 0xe7, 0x40, 0x08, 0x61, 0x67, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x04,
- 0x40, 0x09, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x08, 0x69, 0x6e, 0x65, 0x00,
- 0x00, 0x60, 0xe2, 0x69, 0x00, 0x75, 0x20, 0xe1, 0x6c, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x07, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x1d, 0xe2, 0x6c, 0x00, 0x74,
- 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0x00, 0x3b, 0xe3, 0x6e, 0x00, 0x73, 0x06, 0x74, 0x23, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x6d, 0x0b, 0x00, 0xa7, 0x40, 0x37, 0x64, 0x00, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x69,
- 0x76, 0x65, 0x00, 0x02, 0x42, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xc3, 0x40, 0x07, 0x72, 0x00, 0x01, 0x3b, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x15, 0x70, 0x19, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c,
- 0x04, 0x74, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x40, 0x3a, 0x65,
- 0x00, 0x40, 0x09, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x19, 0x79, 0x1e,
- 0xe2, 0x64, 0x00, 0x74, 0x02, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x72, 0x07, 0x00, 0x09, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xfc, 0x62, 0x00, 0x00,
- 0x63, 0x07, 0x00, 0x64, 0x1c, 0x00, 0x65, 0x21, 0x00, 0x67, 0x44, 0x00,
- 0x69, 0x6e, 0x00, 0x6c, 0xc4, 0x00, 0x70, 0xd7, 0x00, 0x72, 0x20, 0x01,
- 0x73, 0x22, 0x01, 0x75, 0x52, 0x01, 0x76, 0x66, 0x01, 0x40, 0x00, 0x6c,
- 0x69, 0x6e, 0x64, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x55, 0x00,
- 0x07, 0x40, 0x07, 0x61, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65,
- 0x08, 0x6e, 0x14, 0x00, 0xd3, 0x40, 0x06, 0x72, 0x65, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0xb2, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1c, 0xe1, 0x74,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x76, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe4,
- 0x66, 0x00, 0x6e, 0x18, 0x73, 0x1c, 0x74, 0x2e, 0xe2, 0x69, 0x00, 0x79,
- 0x11, 0xe2, 0x63, 0x00, 0x65, 0x08, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x01, 0x12, 0x40, 0x09, 0x65, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x18, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x63, 0x00,
- 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x00,
- 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x59, 0x40, 0x06,
- 0x65, 0x75, 0x00, 0x40, 0x5b, 0x69, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6f,
- 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0xa5, 0x40, 0x00, 0x73, 0x68,
- 0x00, 0xe2, 0x72, 0x00, 0x73, 0x0e, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x2c, 0x40, 0x3b, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x66, 0x02, 0x6c, 0x15, 0x04, 0x44, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x4d, 0x65, 0x73, 0x73, 0x00, 0x00, 0x59, 0xe2,
- 0x65, 0x00, 0x75, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00,
- 0x07, 0xe3, 0x61, 0x00, 0x65, 0x0e, 0x69, 0x17, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0x40, 0x06, 0x74, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x16,
- 0xe1, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x08, 0x00, 0x3a,
- 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07,
- 0x65, 0x77, 0x00, 0xe5, 0x00, 0x00, 0x68, 0x02, 0x69, 0x4b, 0x73, 0x6c,
- 0x74, 0x87, 0x00, 0x07, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x65,
- 0x18, 0x69, 0x1c, 0x6f, 0x2b, 0x70, 0x31, 0x79, 0x36, 0x00, 0xc3, 0x40,
- 0x08, 0x69, 0x6b, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x68, 0x05, 0x40, 0x06,
- 0x72, 0x74, 0x00, 0x40, 0x08, 0x61, 0x69, 0x72, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x76, 0x65, 0x72, 0x00, 0x40, 0x08,
- 0x69, 0x6e, 0x00, 0x01, 0x3b, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x66, 0x07, 0x01, 0x72, 0x40, 0x09, 0x61, 0x74, 0x00, 0x40,
- 0x3a, 0x6f, 0x6f, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x72, 0x00, 0x00, 0x06, 0xe7, 0x00,
- 0x00, 0x61, 0x02, 0x6f, 0x09, 0x72, 0x0e, 0x73, 0x4d, 0x74, 0x52, 0x7a,
- 0x7a, 0x01, 0xa7, 0x40, 0x00, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x09,
- 0x75, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x36, 0xe2, 0x66, 0x00, 0x73,
- 0x1d, 0xe2, 0x61, 0x00, 0x79, 0x16, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0x00, 0x0b, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x09, 0x63, 0x68, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x18, 0x79, 0x1d, 0x00, 0xc3, 0xe3, 0x64,
- 0x00, 0x65, 0x02, 0x72, 0x04, 0x00, 0x54, 0x00, 0x09, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x03, 0xa2, 0x40, 0x07, 0x72, 0x00, 0x40, 0x54, 0x6e, 0x67,
- 0x00, 0x00, 0xa1, 0x00, 0x08, 0xe1, 0x7a, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x00, 0xee, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0x40, 0x00, 0x74, 0x00, 0x40,
- 0x5b, 0x6e, 0x00, 0xe7, 0x65, 0x00, 0x67, 0x0e, 0x6c, 0x13, 0x6f, 0x2f,
- 0x72, 0x37, 0x74, 0xaa, 0x78, 0xb0, 0x40, 0x00, 0x6c, 0x6f, 0x6e, 0x65,
- 0x70, 0x68, 0x72, 0x69, 0x74, 0x69, 0x73, 0x00, 0x40, 0x06, 0x6d, 0x79,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x06, 0xe2,
- 0x69, 0x00, 0x75, 0x09, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x72, 0x72, 0x68, 0x65, 0x61,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x14, 0x69, 0x16, 0x6f, 0x2f, 0xe1, 0x6d,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x95, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0xe2, 0x6d, 0x00, 0x74,
- 0x08, 0x40, 0x09, 0x69, 0x64, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x6d, 0x00,
- 0x74, 0x15, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1,
- 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06,
- 0x00, 0x08, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x06, 0x68, 0x6f,
- 0x6e, 0x00, 0x00, 0x09, 0x40, 0x00, 0x61, 0x7a, 0x7a, 0x00, 0xf5, 0x00,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x74, 0x04, 0x00, 0x75, 0x0d, 0x00, 0x77,
- 0x15, 0x06, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0xf4, 0x61, 0x00, 0x00, 0x65, 0xa2, 0x02, 0x69, 0x8b,
- 0x03, 0x6f, 0x94, 0x05, 0xff, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x64,
- 0x11, 0x00, 0x66, 0xe6, 0x00, 0x67, 0xea, 0x00, 0x68, 0xf1, 0x00, 0x69,
- 0xf6, 0x00, 0x6b, 0x0d, 0x01, 0x6c, 0x16, 0x01, 0x6e, 0x57, 0x01, 0x72,
- 0xa8, 0x01, 0x73, 0x42, 0x02, 0x74, 0x51, 0x02, 0x76, 0x58, 0x02, 0x79,
- 0x67, 0x02, 0x00, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x59, 0x40, 0x07, 0x72, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x09, 0xe4, 0x61, 0x00, 0x65, 0x33, 0x69, 0x49, 0x75, 0x8c, 0xe3,
- 0x6e, 0x00, 0x70, 0x16, 0x74, 0x1e, 0xe2, 0x67, 0x00, 0x74, 0x0f, 0xe2,
- 0x6c, 0x00, 0x75, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x61,
- 0x72, 0x00, 0x00, 0x09, 0x40, 0x00, 0x68, 0x6f, 0x6e, 0x69, 0x63, 0x00,
- 0xe2, 0x69, 0x00, 0x75, 0x04, 0x40, 0x09, 0x63, 0x00, 0x40, 0x00, 0x72,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x61, 0x00, 0x75, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x6d, 0x00,
- 0xe4, 0x63, 0x00, 0x6c, 0x06, 0x70, 0x1f, 0x76, 0x34, 0x40, 0x09, 0x65,
- 0x70, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x08, 0x40, 0x06, 0x74, 0x65,
- 0x72, 0x61, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0xa1, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x67,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65,
- 0x00, 0x6c, 0x0e, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x82, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x86, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x59, 0x66, 0x00, 0x40, 0x06, 0x6d, 0x69,
- 0x72, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x6e,
- 0x02, 0x00, 0x59, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x7f, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x82, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x6d, 0x30, 0xe2, 0x66, 0x00,
- 0x74, 0x1d, 0xe2, 0x69, 0x00, 0x79, 0x16, 0xe2, 0x63, 0x00, 0x65, 0x08,
- 0x40, 0x84, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x37, 0x00, 0x06, 0x04, 0x45, 0xe2, 0x61, 0x00, 0x79, 0x07,
- 0x40, 0x3b, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe3, 0x64, 0x00,
- 0x67, 0x06, 0x74, 0x0a, 0x40, 0x06, 0x61, 0x72, 0x79, 0x00, 0x40, 0x08,
- 0x6f, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x02, 0x75, 0x35, 0x00, 0x00, 0xe2,
- 0x66, 0x00, 0x74, 0x20, 0xe2, 0x69, 0x00, 0x79, 0x19, 0xe3, 0x61, 0x00,
- 0x63, 0x06, 0x65, 0x0e, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x01, 0x12,
- 0xe2, 0x61, 0x00, 0x79, 0x07, 0x40, 0x3b, 0x74, 0x69, 0x76, 0x65, 0x00,
- 0x00, 0x06, 0x40, 0x07, 0x6d, 0x00, 0xe4, 0x61, 0x00, 0x6b, 0x08, 0x72,
- 0x0a, 0x74, 0x37, 0x40, 0x82, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x00, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x79, 0x26, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x73, 0x06, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x5e, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x6f, 0x4d, 0x7a, 0x4f, 0x00, 0x09, 0xe2, 0x72, 0x00,
- 0x74, 0x44, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08, 0x66, 0x0e, 0x6c,
- 0x15, 0x6d, 0x19, 0x73, 0x21, 0x00, 0xfd, 0x40, 0x59, 0x61, 0x63, 0x6b,
- 0x00, 0x40, 0x09, 0x65, 0x63, 0x6b, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x61,
- 0x6c, 0x00, 0x40, 0x06, 0x79, 0x00, 0x40, 0x09, 0x61, 0x73, 0x74, 0x65,
- 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x66, 0x00, 0x76,
- 0x04, 0x40, 0x07, 0x66, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x06,
- 0x00, 0x09, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x68, 0x04, 0x69, 0x06, 0x40,
- 0x09, 0x72, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x40, 0x09, 0x72, 0x61, 0x69,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x47, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09,
- 0x40, 0x08, 0x69, 0x64, 0x65, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x19, 0x6c,
- 0x36, 0x6e, 0x3a, 0x72, 0x5b, 0x73, 0x7b, 0x75, 0xd6, 0xe1, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe2, 0x6e,
- 0x00, 0x72, 0x0b, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x03, 0x17, 0x40, 0xf3,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0xe2, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x0b, 0x6c, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x6c, 0x0c, 0x04, 0x46,
- 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x75, 0x00, 0x79, 0x19, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x5e,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x74, 0x0a, 0x00, 0x00, 0x40, 0x09, 0x64,
- 0x69, 0x6c, 0x6c, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x04, 0x47, 0x40, 0x00, 0x64, 0x00, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40,
- 0x00, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x11, 0x69, 0x1a, 0x6e, 0x1f, 0x04, 0x48, 0xe1, 0x62, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x37, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x07, 0x40, 0x12, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x61, 0x69, 0x72, 0x65, 0x00, 0x40, 0x47, 0x65, 0x00, 0xfe,
- 0x62, 0x00, 0x00, 0x63, 0x12, 0x00, 0x64, 0x5e, 0x00, 0x65, 0x60, 0x00,
- 0x66, 0xa0, 0x00, 0x6c, 0xa4, 0x00, 0x6e, 0xbd, 0x00, 0x70, 0x1b, 0x01,
- 0x72, 0x38, 0x01, 0x73, 0x5e, 0x01, 0x74, 0x65, 0x01, 0x76, 0x8f, 0x01,
- 0x78, 0x9e, 0x01, 0x7a, 0xb7, 0x01, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07,
- 0xe2, 0x68, 0x00, 0x6b, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe7, 0x00, 0x00,
- 0x65, 0x02, 0x66, 0x06, 0x69, 0x0c, 0x6c, 0x10, 0x6e, 0x16, 0x73, 0x1c,
- 0x04, 0x49, 0x41, 0x20, 0x6e, 0x00, 0x40, 0x00, 0x69, 0x72, 0x65, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6d, 0x65, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x05, 0x74, 0x0c, 0x40,
- 0x09, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x6c, 0x76, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x65, 0x70, 0x00, 0x00, 0x09, 0xe2, 0x73, 0x00, 0x74, 0x14, 0xe1,
- 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe5, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x6e, 0x0b, 0x75, 0x11, 0x04, 0x4a, 0x41, 0x20, 0x6e, 0x00,
- 0x40, 0x00, 0x73, 0x6d, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x04, 0x44, 0x4b, 0x65, 0x00, 0x00, 0x09, 0x40, 0x08,
- 0x66, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe7, 0x00, 0x00, 0x63, 0x02, 0x65, 0x06, 0x69, 0x08,
- 0x6f, 0x0d, 0x73, 0x11, 0x74, 0x15, 0x00, 0x08, 0x40, 0x06, 0x65, 0x00,
- 0x00, 0x08, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x75, 0x21, 0x00, 0x06,
- 0xe2, 0x73, 0x00, 0x74, 0x18, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40,
- 0x3b, 0x69, 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe1, 0x70, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x82, 0x00,
- 0x09, 0xe3, 0x00, 0x00, 0x70, 0x02, 0x73, 0x10, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x6b, 0x0b, 0x74,
- 0x1d, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x04, 0x4c, 0x40, 0x00, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x2c, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0x00, 0x06, 0x40, 0x06, 0x6c, 0x69,
- 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x65, 0x09, 0x74, 0x0b,
- 0x00, 0x08, 0x40, 0x09, 0x6c, 0x61, 0x69, 0x6d, 0x00, 0x00, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x06, 0x69, 0x0a, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2c, 0x00, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x7a, 0x02, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69,
- 0x0d, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x00, 0x00, 0x06,
- 0x00, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x0b, 0x72,
- 0x11, 0x74, 0x1f, 0x02, 0xdd, 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0x00, 0x2c, 0x40, 0x00, 0x64, 0x61, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x75,
- 0x05, 0x40, 0x54, 0x74, 0x65, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x19, 0x69, 0x24, 0x00, 0x22, 0xe3, 0x00, 0x00,
- 0x62, 0x02, 0x74, 0x0a, 0x00, 0x06, 0x40, 0x07, 0x69, 0x6c, 0x69, 0x74,
- 0x79, 0x00, 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x27,
- 0x02, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x06,
- 0x40, 0x00, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x6e, 0x74, 0x00, 0x40,
- 0x00, 0x65, 0x72, 0x74, 0x79, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x63, 0xe1, 0x09, 0x64, 0xe6, 0x09, 0x65, 0xe8, 0x09, 0x68, 0xf0,
- 0x27, 0x69, 0x50, 0x29, 0x6d, 0xcd, 0x2d, 0x6f, 0xcf, 0x2d, 0x70, 0xfb,
- 0x33, 0x74, 0x04, 0x34, 0x75, 0x0d, 0x34, 0x79, 0xb4, 0x37, 0x00, 0x08,
- 0xc0, 0x62, 0x19, 0x35, 0x00, 0x82, 0x00, 0x44, 0x01, 0x00, 0x00, 0xe0,
- 0x02, 0x17, 0x03, 0x92, 0x03, 0x94, 0x03, 0x76, 0x04, 0x85, 0x04, 0x9f,
- 0x04, 0xa4, 0x04, 0x61, 0x05, 0x00, 0x00, 0x58, 0x06, 0x00, 0x00, 0x3e,
- 0x07, 0x6d, 0x07, 0xa5, 0x07, 0xe4, 0x08, 0x1b, 0x09, 0x8e, 0x09, 0x00,
- 0x00, 0xac, 0x09, 0xb7, 0x09, 0xe2, 0x62, 0x00, 0x69, 0x32, 0xe3, 0x65,
- 0x00, 0x69, 0x04, 0x6c, 0x27, 0x40, 0x59, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x6e, 0x02, 0x74, 0x1a, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40,
- 0x07, 0x74, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x59, 0x40, 0x09, 0x65, 0x00,
- 0xe2, 0x64, 0x00, 0x65, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe7, 0x63,
- 0x00, 0x65, 0x0a, 0x69, 0x44, 0x6b, 0x7c, 0x6f, 0x9f, 0x71, 0xa7, 0x79,
- 0xb1, 0x60, 0x08, 0x6f, 0x6f, 0x6e, 0x00, 0x07, 0x00, 0xff, 0xff, 0xe8,
- 0x00, 0x00, 0x63, 0x02, 0x67, 0x0a, 0x68, 0x10, 0x6d, 0x17, 0x72, 0x1b,
- 0x74, 0x1d, 0x77, 0x24, 0x00, 0xa5, 0x40, 0x06, 0x6f, 0x75, 0x72, 0x73,
- 0x65, 0x00, 0x40, 0x08, 0x6f, 0x65, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x72,
- 0x73, 0x65, 0x00, 0x40, 0x09, 0x65, 0x00, 0x00, 0x07, 0x40, 0x09, 0x72,
- 0x61, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00, 0xe4, 0x61, 0x00,
- 0x6c, 0x16, 0x6e, 0x1a, 0x73, 0x26, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x09, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x59,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x2c, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6e, 0x74, 0x65, 0x75, 0x72, 0x00,
- 0x40, 0x06, 0x75, 0x65, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x00, 0x01, 0x0c,
- 0xf5, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x64, 0x13, 0x00, 0x69, 0x19,
- 0x00, 0x6f, 0x88, 0x01, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x06, 0x40, 0x06, 0x63, 0x6f, 0x70, 0x65, 0x00, 0x40,
- 0x00, 0x6c, 0x65, 0x64, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x63, 0x26, 0x00,
- 0x69, 0x52, 0x00, 0x6f, 0x54, 0x00, 0x73, 0x4f, 0x01, 0x75, 0x53, 0x01,
- 0xe3, 0x6c, 0x00, 0x6e, 0x02, 0x74, 0x0d, 0x00, 0x56, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x21, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x56, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x07,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x07, 0x68, 0x69, 0x6f, 0x00, 0x00, 0x00,
- 0xea, 0x00, 0x00, 0x61, 0x02, 0x63, 0x1a, 0x67, 0x22, 0x69, 0x3d, 0x6c,
- 0x46, 0x6d, 0x58, 0x70, 0x7c, 0x73, 0x83, 0x74, 0x9e, 0x00, 0x55, 0xe1,
- 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x07, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe1, 0x68, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x04, 0x40, 0x06, 0x72, 0x00, 0x00, 0x07, 0x40, 0x09,
- 0x73, 0x6f, 0x74, 0x6f, 0x70, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00,
- 0x07, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x6e,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x09,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x07, 0x40, 0x06, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x6f,
- 0x06, 0x75, 0x0c, 0x40, 0x07, 0x6f, 0x70, 0x79, 0x00, 0x40, 0x06, 0x6e,
- 0x64, 0x65, 0x00, 0x40, 0x00, 0x72, 0x67, 0x65, 0x72, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x68, 0x2b, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x67,
- 0x00, 0x70, 0x19, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x79, 0x04, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x07, 0x40, 0x09, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40,
- 0x09, 0x68, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x20, 0xe2, 0x69, 0x00,
- 0x6c, 0x17, 0xe2, 0x61, 0x00, 0x73, 0x02, 0x00, 0x07, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xea,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x11, 0x65, 0x16, 0x67, 0x18, 0x69, 0x3a,
- 0x6c, 0x3f, 0x6f, 0x44, 0x74, 0x49, 0x77, 0x57, 0x00, 0x93, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x09, 0x40, 0x09, 0x75, 0x66, 0x66, 0x69, 0x6e,
- 0x00, 0x40, 0x07, 0x61, 0x67, 0x00, 0x00, 0x09, 0xe3, 0x61, 0x00, 0x65,
- 0x02, 0x69, 0x16, 0x00, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x6e,
- 0x02, 0x79, 0x08, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0xf3, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x04, 0x40, 0x08, 0x67, 0x00, 0x40, 0x07, 0x6d, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x65, 0x64, 0x00, 0x40, 0x00, 0x72,
- 0x74, 0x00, 0x00, 0x00, 0xe5, 0x64, 0x00, 0x6c, 0x0b, 0x6d, 0x66, 0x6e,
- 0x6c, 0x73, 0xc5, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07,
- 0x72, 0x00, 0xe7, 0x00, 0x00, 0x27, 0x02, 0x63, 0x06, 0x69, 0x0c, 0x6c,
- 0x11, 0x72, 0x17, 0x77, 0x32, 0x01, 0x98, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x08, 0x61, 0x72, 0x64, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x65, 0x72, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xfa, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x79,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07, 0x65,
- 0x6e, 0x74, 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x63, 0x07, 0x64, 0x0d,
- 0x66, 0x13, 0x6d, 0x19, 0x70, 0x2d, 0x73, 0x34, 0x77, 0x3b, 0x79, 0x42,
- 0x00, 0x59, 0x40, 0x06, 0x6f, 0x77, 0x00, 0x40, 0x06, 0x6f, 0x61, 0x74,
- 0x00, 0x40, 0x06, 0x72, 0x6f, 0x70, 0x00, 0x40, 0x06, 0x61, 0x6c, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x72,
- 0x6f, 0x6f, 0x66, 0x00, 0x40, 0x09, 0x74, 0x6f, 0x72, 0x6d, 0x00, 0x40,
- 0x07, 0x61, 0x74, 0x65, 0x72, 0x00, 0x00, 0xf3, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x06,
- 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x82,
- 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x5e, 0x6c, 0x79, 0x00,
- 0xe9, 0x00, 0x00, 0x62, 0x02, 0x65, 0x35, 0x69, 0x3b, 0x6a, 0x52, 0x6d,
- 0x57, 0x70, 0x65, 0x72, 0x86, 0x73, 0xa1, 0x00, 0x06, 0xe2, 0x6c, 0x00,
- 0x75, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0x19,
- 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x6b, 0x69, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x66, 0x02, 0x00,
- 0x07, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x04, 0x4d, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x01, 0x76, 0xe3, 0x67, 0x00, 0x6e, 0x04,
- 0x72, 0x0f, 0x40, 0x5e, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x06, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x00, 0x68, 0x61, 0x63, 0x6b, 0x6c, 0x65, 0x00, 0xe8, 0x00, 0x00,
- 0x63, 0x02, 0x64, 0x41, 0x65, 0x78, 0x67, 0x7c, 0x6b, 0xa9, 0x73, 0xc3,
- 0x74, 0xdb, 0x00, 0x77, 0xe3, 0x68, 0x00, 0x69, 0x12, 0x6f, 0x29, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x6e, 0x07, 0x00, 0x5d, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02,
- 0x6f, 0x09, 0x79, 0x2c, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x13, 0x00,
- 0xe9, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0xf4, 0x40, 0x09, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x1b, 0x79, 0x22, 0x02, 0x75, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x66, 0x06,
- 0x72, 0x0e, 0x01, 0x98, 0x40, 0x00, 0x73, 0x00, 0x40, 0x08, 0x69, 0x6e,
- 0x64, 0x65, 0x72, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0xf4, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07, 0x6e, 0x0b,
- 0x04, 0x4e, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x5b,
- 0x63, 0x6b, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xfa, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x04, 0x4f,
- 0x40, 0x07, 0x72, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65, 0x24, 0x69,
- 0x35, 0x70, 0x5e, 0x73, 0xa9, 0x74, 0xb3, 0x00, 0xfa, 0xe1, 0x63, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02,
- 0x73, 0x04, 0x00, 0x09, 0x00, 0x07, 0x40, 0x07, 0x65, 0x65, 0x64, 0x00,
- 0xe4, 0x64, 0x00, 0x65, 0x14, 0x6e, 0x18, 0x73, 0x1c, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x6e, 0x07, 0x01, 0x2d, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x65,
- 0x00, 0x40, 0x06, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x20, 0x6f, 0x25,
- 0x72, 0x37, 0xe3, 0x64, 0x00, 0x6c, 0x02, 0x72, 0x17, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x09, 0x40, 0x08, 0x75, 0x72, 0x00, 0x40, 0x06, 0x6f,
- 0x63, 0x68, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x63, 0x61,
- 0x6c, 0x6c, 0x69, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x6e, 0x02, 0x6f,
- 0x08, 0x75, 0x0c, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x08, 0x72, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00,
- 0x09, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x25, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x66, 0x07, 0x6e, 0x16, 0x04, 0x50, 0x40, 0x09,
- 0x69, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x08, 0x40, 0x07, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x74, 0x79, 0x00, 0xe4, 0x63, 0x00, 0x68, 0x05, 0x70, 0x18,
- 0x74, 0x2a, 0x40, 0x56, 0x61, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x6e, 0x06, 0x04, 0x51, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x79, 0x09, 0x00, 0x59, 0x40,
- 0x06, 0x65, 0x72, 0x72, 0x79, 0x00, 0x00, 0xf3, 0x40, 0x00, 0x65, 0x72,
- 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x0c, 0x00, 0x63,
- 0x11, 0x00, 0x65, 0x17, 0x00, 0x68, 0x2d, 0x00, 0x69, 0x3f, 0x00, 0x6c,
- 0xc3, 0x00, 0x74, 0xd3, 0x00, 0x00, 0x06, 0x40, 0x07, 0x74, 0x6f, 0x75,
- 0x69, 0x6c, 0x6c, 0x65, 0x00, 0x40, 0x08, 0x61, 0x67, 0x00, 0x40, 0x59,
- 0x68, 0x65, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x70, 0x04, 0x72,
- 0x0b, 0x04, 0x52, 0x00, 0x37, 0x40, 0x08, 0x61, 0x79, 0x65, 0x72, 0x00,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40, 0x00, 0x72, 0x00, 0x40,
- 0x06, 0x6b, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0xe3, 0x66, 0x00, 0x6e,
- 0x18, 0x6f, 0x1c, 0xe2, 0x69, 0x00, 0x79, 0x11, 0xe2, 0x63, 0x00, 0x65,
- 0x08, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x01, 0x12, 0x40, 0x07, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02,
- 0x6e, 0x1a, 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x2f, 0xe1,
- 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x00, 0x56, 0x00,
- 0x09, 0xe3, 0x73, 0x00, 0x74, 0x12, 0x7a, 0x16, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x63, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x69, 0x00, 0xe2,
- 0x6b, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00,
- 0xe6, 0x61, 0x00, 0x65, 0x04, 0x69, 0x0d, 0x6c, 0x12, 0x72, 0x3c, 0x79,
- 0x41, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x23,
- 0xe5, 0x00, 0x00, 0x62, 0x02, 0x72, 0x09, 0x73, 0x0b, 0x74, 0x12, 0x03,
- 0x19, 0x40, 0xb1, 0x72, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x07, 0x40, 0x06,
- 0x6e, 0x61, 0x6b, 0x65, 0x00, 0x40, 0x06, 0x72, 0x61, 0x70, 0x00, 0x00,
- 0x00, 0x40, 0x06, 0x61, 0x70, 0x00, 0x00, 0xf3, 0xe2, 0x63, 0x00, 0x6e,
- 0x16, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x3b, 0xe3, 0x61, 0x00, 0x65, 0x13, 0x69, 0x3a, 0xe1, 0x67,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00,
- 0x7e, 0x00, 0x07, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x14,
- 0x04, 0x53, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x69, 0x06, 0x00, 0xf1, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x08, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x47, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe3, 0x6e, 0x00, 0x6f,
- 0x09, 0x73, 0x0e, 0xe2, 0x65, 0x00, 0x67, 0x02, 0x00, 0x06, 0x00, 0x07,
- 0x40, 0x06, 0x6c, 0x69, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x6d, 0x0b, 0x01, 0x18, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe4, 0x00,
- 0x00, 0x62, 0x02, 0x68, 0x09, 0x6e, 0x0f, 0x01, 0xa0, 0x40, 0x00, 0x6f,
- 0x6e, 0x65, 0x64, 0x00, 0x40, 0x07, 0x69, 0x64, 0x65, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x02, 0x7a, 0x12, 0x00, 0x0b,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x09, 0x40, 0x09,
- 0x61, 0x63, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x59, 0x40,
- 0x07, 0x61, 0x74, 0x61, 0x7a, 0x7a, 0x00, 0x40, 0x00, 0x70, 0x74, 0x00,
- 0x00, 0x00, 0xc1, 0x61, 0x17, 0x33, 0x00, 0x35, 0x00, 0xc8, 0x01, 0x39,
- 0x02, 0x89, 0x06, 0x27, 0x08, 0x65, 0x08, 0x84, 0x0a, 0x5a, 0x0c, 0xbf,
- 0x0c, 0x47, 0x0d, 0x00, 0x00, 0x95, 0x0d, 0x38, 0x0f, 0xb3, 0x10, 0x89,
- 0x11, 0x97, 0x11, 0x05, 0x15, 0x57, 0x15, 0x73, 0x15, 0xc9, 0x19, 0x00,
- 0x00, 0xea, 0x1b, 0xbd, 0x1d, 0x04, 0x54, 0xf8, 0x63, 0x00, 0x00, 0x64,
- 0x3b, 0x00, 0x66, 0x89, 0x00, 0x6c, 0x97, 0x00, 0x6d, 0x08, 0x01, 0x70,
- 0x13, 0x01, 0x72, 0x1e, 0x01, 0x73, 0x3c, 0x01, 0xe3, 0x68, 0x00, 0x71,
- 0x0d, 0x74, 0x14, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x03, 0x87, 0x40, 0x37,
- 0x62, 0x6c, 0x65, 0x00, 0x40, 0x3a, 0x75, 0x69, 0x72, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x01, 0xdc, 0x40, 0x06, 0x6e, 0x74,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x07, 0x40, 0x06, 0x6e, 0x61, 0x72, 0x79,
- 0x00, 0x40, 0x00, 0x69, 0x74, 0x79, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x0b, 0x69, 0x1b, 0x6d, 0x30, 0x6f, 0x38, 0x79, 0x3d, 0x04, 0x55,
- 0x40, 0x06, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x06, 0x68, 0x69, 0x70,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0x40, 0x00,
- 0x69, 0x74, 0x74, 0x65, 0x64, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0x01,
- 0x6f, 0x40, 0x00, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x48, 0x6e, 0x4a,
- 0x70, 0x50, 0x74, 0x59, 0x04, 0x56, 0xe3, 0x73, 0x00, 0x74, 0x1e, 0x7a,
- 0x2a, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x37, 0x40, 0x37, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0xdb, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x52, 0x00, 0x37, 0x00, 0x09, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x6f, 0x6c, 0x69, 0x74, 0x69, 0x6b, 0x00, 0xe2, 0x6f, 0x00,
- 0x79, 0x04, 0x40, 0x09, 0x72, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x3f, 0x40, 0x07, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6d,
- 0x09, 0x77, 0x0f, 0x00, 0x59, 0x40, 0x09, 0x75, 0x61, 0x72, 0x64, 0x00,
- 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00,
- 0xe2, 0x6f, 0x00, 0x73, 0x31, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x1c, 0x69, 0x20, 0x01, 0xb1, 0xe1, 0x62, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0xdf, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x00, 0x37, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x75, 0x72, 0x69, 0x6e,
- 0x67, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x05, 0x69, 0x2c, 0x6f, 0x43, 0x75,
- 0x48, 0x40, 0x07, 0x74, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e,
- 0x00, 0x75, 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x64, 0x00,
- 0x72, 0x0d, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x08, 0x40, 0x00, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x07, 0x74, 0x68, 0x00, 0x40, 0x7a, 0x69, 0x6c,
- 0x00, 0xe3, 0x69, 0x00, 0x6b, 0x05, 0x74, 0x11, 0x41, 0x21, 0x6c, 0x64,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40, 0x3b, 0x6e, 0x67,
- 0x00, 0x40, 0x09, 0x74, 0x61, 0x6c, 0x00, 0xff, 0x00, 0x00, 0x00, 0x27,
- 0x02, 0x00, 0x61, 0x06, 0x00, 0x63, 0x4f, 0x00, 0x64, 0x53, 0x00, 0x65,
- 0x55, 0x00, 0x68, 0x00, 0x01, 0x69, 0x08, 0x01, 0x6b, 0x76, 0x01, 0x6c,
- 0xa0, 0x01, 0x6f, 0xc4, 0x01, 0x72, 0xda, 0x02, 0x74, 0x50, 0x03, 0x75,
- 0xbb, 0x03, 0x79, 0x0c, 0x04, 0x00, 0x07, 0x40, 0x00, 0x64, 0x00, 0xe3,
- 0x6c, 0x00, 0x6e, 0x1d, 0x70, 0x2e, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x7a, 0x40, 0x06, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x74, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x08, 0x65, 0x00, 0x00, 0x00, 0xe4, 0x69, 0x00, 0x6e, 0x29, 0x70,
- 0x3f, 0x73, 0x7e, 0xe2, 0x70, 0x00, 0x76, 0x04, 0x40, 0x2c, 0x74, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x62, 0x6c, 0x65, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x35, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x61, 0x00,
- 0x69, 0x06, 0x6f, 0x31, 0x40, 0x06, 0x63, 0x6c, 0x65, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x0f, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03, 0x57, 0xe2, 0x6f, 0x00, 0x76, 0x11,
- 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x79, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x65,
- 0x72, 0x63, 0x68, 0x65, 0x00, 0xe3, 0x64, 0x00, 0x70, 0x15, 0x74, 0x47,
- 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x72, 0x08, 0x00, 0x06, 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x13, 0xe2,
- 0x6c, 0x00, 0x74, 0x02, 0x00, 0x56, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x17, 0xe2, 0x6c, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x09, 0x69,
- 0x76, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x16,
- 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x04, 0x57, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x09, 0x75, 0x18, 0x40, 0x07, 0x6d, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x40, 0x98, 0x73, 0x65,
- 0x00, 0xf6, 0x67, 0x00, 0x00, 0x6d, 0x26, 0x00, 0x6e, 0x51, 0x00, 0x72,
- 0xce, 0x00, 0x75, 0xe4, 0x00, 0x76, 0xf0, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x62,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x04, 0x58, 0x00, 0x37, 0xe2, 0x62,
- 0x00, 0x70, 0x0a, 0x40, 0x00, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x5e, 0x6e, 0x73, 0x65, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x00, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0xed, 0xe6, 0x00, 0x00, 0x63, 0x02, 0x64, 0x17,
- 0x66, 0x1d, 0x6e, 0x40, 0x73, 0x56, 0x00, 0x08, 0xe1, 0x69, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x87, 0x40, 0x08, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x69, 0x74, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x10, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c,
- 0x65, 0x00, 0x40, 0x00, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0xfc, 0xe2, 0x61,
- 0x00, 0x6f, 0x0a, 0x40, 0x09, 0x69, 0x73, 0x73, 0x61, 0x6e, 0x63, 0x65,
- 0x00, 0x40, 0x72, 0x69, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x01, 0xdc, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x09, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe2, 0x70, 0x00, 0x72,
- 0x02, 0x01, 0x20, 0x40, 0x07, 0x73, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x06, 0x40, 0x37, 0x62, 0x6c, 0x65,
- 0x00, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x14, 0x75, 0x36, 0xe1, 0x61,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09, 0x74, 0x00, 0x40, 0x00,
- 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x72, 0x79, 0x00, 0xe2, 0x64, 0x00, 0x69, 0x1e, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d,
- 0x06, 0x04, 0x59, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74,
- 0x00, 0xe4, 0x61, 0x00, 0x69, 0x19, 0x6f, 0x4e, 0x75, 0x5e, 0xe2, 0x6c,
- 0x00, 0x6e, 0x02, 0x00, 0x3b, 0xe1, 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x75,
- 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00, 0xe3,
- 0x66, 0x00, 0x6c, 0x20, 0x74, 0x28, 0xe2, 0x69, 0x00, 0x79, 0x19, 0xe3,
- 0x61, 0x00, 0x63, 0x06, 0x65, 0x0e, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x04, 0x5a, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x00, 0x40, 0x07,
- 0x75, 0x64, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x06, 0x40, 0x06, 0x6d, 0x00,
- 0xe4, 0x6d, 0x00, 0x70, 0x07, 0x72, 0x1f, 0x73, 0x44, 0x40, 0x00, 0x62,
- 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0xa6, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x18, 0x00,
- 0x08, 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00,
- 0x00, 0x40, 0x06, 0x63, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x08, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x06, 0x62, 0x6c,
- 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00,
- 0x39, 0x00, 0x51, 0x00, 0x6b, 0x00, 0x83, 0x00, 0x9c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xc5, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x00,
- 0x00, 0x00, 0xf1, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x34, 0x01,
- 0x39, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00,
- 0x9a, 0x01, 0x00, 0x6e, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x7a, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x06, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40, 0x06, 0x72,
- 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x09, 0x61, 0x73, 0x74,
- 0x00, 0x40, 0x00, 0x63, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x04, 0x75,
- 0x09, 0x40, 0x06, 0x70, 0x00, 0x40, 0x06, 0x61, 0x74, 0x00, 0x40, 0x08,
- 0x72, 0x72, 0x61, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe3,
- 0x6e, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x0e,
- 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x04, 0x5b, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00,
- 0x40, 0xb1, 0x65, 0x61, 0x64, 0x00, 0xe3, 0x72, 0x00, 0x73, 0x09, 0x76,
- 0x11, 0x40, 0x00, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0xed,
- 0x74, 0x72, 0x69, 0x63, 0x74, 0x00, 0x40, 0x0b, 0x69, 0x64, 0x65, 0x00,
- 0x40, 0x07, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x63, 0x00, 0x73, 0x04, 0x40, 0x06, 0x6b, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x75, 0x13, 0x00, 0x1c, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x00, 0xe2, 0x62, 0x00, 0x6e, 0x10, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x01, 0xcf, 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0x40,
- 0x7a, 0x64, 0x00, 0x41, 0x21, 0x61, 0x77, 0x00, 0x40, 0x06, 0x6b, 0x69,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x3c, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x74, 0x0f, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x40,
- 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x09, 0x60, 0x07,
- 0x73, 0x65, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x6f, 0x00, 0x76, 0x0f,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x73, 0x74, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79,
- 0x00, 0x00, 0x3b, 0x40, 0x06, 0x6f, 0x6f, 0x64, 0x00, 0x41, 0x1a, 0x65,
- 0x00, 0xe6, 0x64, 0x00, 0x66, 0x0e, 0x6b, 0x19, 0x6c, 0x1b, 0x76, 0x26,
- 0x78, 0x2a, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0xf4, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0x59, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01, 0x34,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x1c, 0x65, 0x00, 0x40, 0x7a, 0x70, 0x6f,
- 0x72, 0x74, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x0a,
- 0x00, 0x66, 0x70, 0x00, 0x69, 0x7e, 0x00, 0x6c, 0xab, 0x00, 0x6f, 0xf5,
- 0x00, 0x72, 0x34, 0x01, 0x75, 0xad, 0x01, 0x04, 0x5c, 0x40, 0x72, 0x73,
- 0x68, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x12, 0xe1, 0x74,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x06, 0x72, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x2f, 0x00,
- 0x22, 0xe2, 0x65, 0x00, 0x6e, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x1a, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x04, 0x74,
- 0x09, 0x40, 0x82, 0x65, 0x00, 0x40, 0x09, 0x75, 0x6d, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe3, 0x61,
- 0x00, 0x65, 0x04, 0x69, 0x0d, 0x40, 0x06, 0x6c, 0x00, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x04, 0x74, 0x1f, 0x40, 0xd4, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe3, 0x64, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x00, 0x37,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x06, 0x00, 0x08, 0x40, 0x00, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x12, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01,
- 0x26, 0x40, 0x00, 0x6f, 0x6e, 0x61, 0x72, 0x79, 0x00, 0xe2, 0x63, 0x00,
- 0x78, 0x1d, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x0f,
- 0x01, 0xeb, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40,
- 0x3b, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05,
- 0x40, 0x56, 0x76, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x6f, 0x67, 0x79, 0x00,
- 0xe1, 0x72, 0x00, 0xe3, 0x67, 0x00, 0x6d, 0x04, 0x74, 0x2f, 0x40, 0x3a,
- 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x19, 0x69, 0x1d, 0x04,
- 0x5d, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x74, 0x07, 0x01,
- 0xdc, 0x40, 0x06, 0x72, 0x79, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x08, 0x73, 0x74, 0x00, 0x40, 0x0b, 0x69,
- 0x66, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x1f, 0x69, 0x4b, 0xe2, 0x63,
- 0x00, 0x69, 0x16, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x02, 0x07, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x79,
- 0x00, 0x40, 0x93, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6d, 0x0b, 0x01, 0x77, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00,
- 0x07, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0xe6, 0x67, 0x00, 0x6c, 0x0c, 0x6e, 0x20, 0x72,
- 0x24, 0x73, 0x2f, 0x74, 0x34, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x06, 0x00, 0x06, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x00, 0x40, 0x22, 0x64, 0x00, 0x40, 0x09, 0x62, 0x69, 0x73, 0x68, 0x6d,
- 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x01, 0xf0, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x65, 0x3f, 0x00, 0x67, 0x69, 0x00, 0x69, 0x6e, 0x00, 0x6e, 0xeb,
- 0x00, 0x72, 0xf1, 0x00, 0x75, 0x4c, 0x01, 0x00, 0x00, 0xe3, 0x6c, 0x00,
- 0x72, 0x14, 0x74, 0x28, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x09, 0x04,
- 0x5e, 0x40, 0x07, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x07, 0x61, 0x00,
- 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x73, 0x08, 0x01, 0xc4,
- 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x68, 0x00, 0x74,
- 0x05, 0x40, 0x72, 0x65, 0x72, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe2, 0x6e,
- 0x00, 0x78, 0x1c, 0xe2, 0x63, 0x00, 0x65, 0x04, 0x40, 0x06, 0x79, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x79, 0x00, 0x41, 0xdc, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02,
- 0x00, 0x07, 0x00, 0x08, 0x40, 0x07, 0x61, 0x65, 0x00, 0xe4, 0x63, 0x00,
- 0x6d, 0x06, 0x6f, 0x2b, 0x73, 0x44, 0x40, 0x09, 0x69, 0x64, 0x65, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x55,
- 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x09, 0x73,
- 0x6d, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x0e, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x59, 0x40, 0x37, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x79, 0x13, 0xe3, 0x6e, 0x00, 0x72, 0x04, 0x74, 0x06,
- 0x40, 0x09, 0x74, 0x00, 0x00, 0x09, 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x61, 0x6e, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x41, 0x6f, 0x46, 0xe2, 0x73, 0x00, 0x74, 0x0f, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x03, 0x57, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x66, 0x02, 0x74, 0x07, 0x00, 0x06, 0x40, 0x3b, 0x75, 0x6c,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x13, 0xe1, 0x62, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x3c, 0x6e, 0x64,
- 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x6e, 0x00, 0x70, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x00, 0x72, 0xe2, 0x6c, 0x00, 0x72, 0x51, 0xe1, 0x61, 0x00, 0xe2,
- 0x72, 0x00, 0x74, 0x1e, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe2,
- 0x74, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe3, 0x65,
- 0x00, 0x69, 0x09, 0x6f, 0x18, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x04, 0x5f,
- 0x00, 0x37, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x01, 0x52, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x09, 0x00, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x3b, 0x69, 0x55, 0x75, 0x57, 0xe2, 0x62, 0x00, 0x6e, 0x32, 0xe3, 0x00,
- 0x00, 0x62, 0x02, 0x69, 0x10, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0xa6, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x40, 0x7a, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x73,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x00, 0xed, 0x40, 0x09,
- 0x6c, 0x00, 0x40, 0x37, 0x64, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe4, 0x67, 0x00, 0x6d, 0x04, 0x6e, 0x20, 0x74, 0x77, 0x40, 0x47,
- 0x6e, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x04, 0x60,
- 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x66,
- 0x08, 0x69, 0x21, 0x73, 0x2b, 0x00, 0xed, 0x40, 0x07, 0x65, 0x65, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x34, 0x40, 0x06, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x00, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x00,
- 0xe2, 0x74, 0x00, 0x75, 0x14, 0xe1, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x74,
- 0x04, 0x41, 0x20, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x6d, 0x65, 0x6e, 0x74,
- 0x00, 0x40, 0x00, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x41, 0xdc, 0x65,
- 0x72, 0x61, 0x74, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x12, 0x75, 0x2c,
- 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x95, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x63, 0x00,
- 0x6e, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x04, 0x18, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x06, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x76, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xf7,
- 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x7b, 0x00, 0x69, 0xcf, 0x00,
- 0x6f, 0x6d, 0x01, 0x75, 0x74, 0x01, 0x79, 0x8b, 0x01, 0x00, 0x00, 0xe3,
- 0x74, 0x00, 0x78, 0x54, 0x79, 0x70, 0xe2, 0x65, 0x00, 0x69, 0x12, 0xe3,
- 0x00, 0x00, 0x64, 0x02, 0x72, 0x09, 0x04, 0x61, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x6f, 0x00, 0x76, 0x16, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x06, 0x00, 0x07, 0x40, 0x00,
- 0x6c, 0x00, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x86, 0xe2, 0x73, 0x00, 0x74, 0x12, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x08, 0x40, 0x00,
- 0x63, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x11, 0x01, 0x4b, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09, 0x74, 0x00,
- 0x40, 0x06, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x00, 0xfc,
- 0xe4, 0x61, 0x00, 0x67, 0x0f, 0x6e, 0x15, 0x76, 0x35, 0xe1, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x22, 0x00, 0x37,
- 0x40, 0x42, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x5b, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x3b,
- 0xe7, 0x61, 0x00, 0x63, 0x25, 0x65, 0x27, 0x67, 0x3a, 0x6e, 0x5f, 0x71,
- 0x7f, 0x73, 0x86, 0xe2, 0x62, 0x00, 0x6e, 0x15, 0xe2, 0x69, 0x00, 0x6c,
- 0x07, 0x40, 0xdb, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x37, 0x00, 0x37, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x00, 0x00, 0x09, 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00,
- 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00,
- 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe3, 0x6e, 0x00, 0x73, 0x02,
- 0x75, 0x08, 0x00, 0x06, 0x40, 0x00, 0x69, 0x74, 0x79, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xea, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x71, 0x02, 0x00, 0x3a, 0xe1, 0x75, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x78, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x06,
- 0x75, 0x61, 0x72, 0x79, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x02, 0x00, 0x59,
- 0x00, 0x5b, 0x40, 0x22, 0x63, 0x61, 0x74, 0x65, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x00, 0x0b, 0xf7, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x49, 0x00, 0x69, 0x79, 0x00, 0x6e,
- 0xd6, 0x00, 0x6f, 0xdc, 0x00, 0x75, 0x4a, 0x01, 0x00, 0x07, 0xe4, 0x69,
- 0x00, 0x6e, 0x0f, 0x70, 0x13, 0x72, 0x1a, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x5b, 0x40, 0x59, 0x65, 0x72, 0x00, 0x40, 0x5b,
- 0x64, 0x00, 0x40, 0x00, 0x70, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x6b, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x16, 0x00, 0x22, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x64, 0x00,
- 0x6d, 0x0e, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x00, 0x61, 0x62, 0x6c,
- 0x65, 0x00, 0x00, 0xa1, 0xe1, 0x62, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x0e,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x20, 0x40, 0x37,
- 0x64, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe4, 0x6e, 0x00,
- 0x73, 0x25, 0x74, 0x35, 0x78, 0x52, 0xe2, 0x64, 0x00, 0x69, 0x05, 0x40,
- 0x07, 0x65, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x0b, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x09, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69,
- 0x0a, 0x40, 0x06, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x37, 0x6e, 0x67, 0x00, 0x00, 0x3a, 0x40, 0x09, 0x61, 0x6e, 0x74, 0x00,
- 0xe6, 0x64, 0x00, 0x6c, 0x05, 0x6e, 0x09, 0x72, 0x22, 0x74, 0x4c, 0x76,
- 0x5c, 0x40, 0x0b, 0x65, 0x6c, 0x00, 0x40, 0x5b, 0x64, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e,
- 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x07,
- 0x00, 0x07, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x04, 0x62, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61,
- 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x70,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe7, 0x61, 0x00, 0x64, 0x1a, 0x65, 0x42,
- 0x6e, 0x65, 0x6f, 0x72, 0x74, 0xab, 0x75, 0xbc, 0xe3, 0x69, 0x00, 0x6c,
- 0x09, 0x73, 0x0b, 0x40, 0x09, 0x73, 0x73, 0x61, 0x6e, 0x63, 0x65, 0x00,
- 0x00, 0x00, 0x40, 0x08, 0x63, 0x65, 0x6e, 0x63, 0x65, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x1a, 0x00, 0x3c, 0xe2, 0x72, 0x00, 0x7a, 0x0c,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x1f, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x59, 0x76, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x09, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0xe2, 0x67, 0x00, 0x77, 0x13, 0xe2, 0x61, 0x00, 0x65, 0x05,
- 0x40, 0x5e, 0x64, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x52, 0x40, 0x09, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07, 0x74, 0x00, 0x40, 0x07,
- 0x6e, 0x00, 0xe3, 0x75, 0x00, 0x76, 0x16, 0x77, 0x2e, 0xe1, 0x6e, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0x78, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x8c, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x20, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x00, 0xc3, 0x40, 0x06, 0x6c, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x6e, 0x63, 0x69, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe2, 0x70, 0x00, 0x72, 0x05, 0x40, 0x7a, 0x65, 0x6e,
- 0x00, 0x40, 0x3a, 0x67, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x65, 0x6a, 0x00, 0x68, 0x28, 0x01, 0x6c, 0x33, 0x01, 0x6f, 0x9c, 0x01,
- 0x72, 0xcd, 0x01, 0x74, 0x9d, 0x02, 0x75, 0xaf, 0x02, 0x00, 0x06, 0xe3,
- 0x69, 0x00, 0x72, 0x23, 0x74, 0x49, 0xe2, 0x6e, 0x00, 0x72, 0x04, 0x40,
- 0x0b, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x04, 0x63,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x1c, 0xe2, 0x62,
- 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09,
- 0x00, 0x07, 0x40, 0x07, 0x65, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x01, 0xcd, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x6c, 0x2b,
- 0x6e, 0x47, 0x72, 0x5f, 0x74, 0x7e, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x11, 0x69, 0x1a, 0x01, 0xb1, 0xe1, 0x62, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x00, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x3b, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69,
- 0x0b, 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x40, 0x06, 0x74, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x7a, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe2, 0x63, 0x00, 0x74, 0x09, 0x40, 0x08,
- 0x75, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x69,
- 0x00, 0x72, 0x05, 0x40, 0x09, 0x72, 0x65, 0x00, 0x40, 0x06, 0x79, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00,
- 0x76, 0x17, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x41, 0x20, 0x6f, 0x74, 0x6f, 0x67, 0x72,
- 0x61, 0x70, 0x68, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x11, 0x69, 0x43, 0xe2,
- 0x63, 0x00, 0x6e, 0x08, 0x40, 0x00, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x00,
- 0x40, 0xad, 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x16, 0xe1, 0x69, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0x34, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x64, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x6f, 0x07, 0x00, 0x38, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x08, 0x72,
- 0x00, 0xe2, 0x72, 0x00, 0x73, 0x1a, 0xe1, 0x74, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x05, 0x6f, 0x09, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x3b, 0x64,
- 0x00, 0x40, 0x00, 0x72, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x06, 0x40, 0x00, 0x66, 0x75, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x6f, 0x72,
- 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x70, 0x6f, 0x8d, 0xe2, 0x68, 0x00,
- 0x73, 0x2e, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x73,
- 0x02, 0x00, 0x72, 0xe1, 0x69, 0x00, 0xe2, 0x62, 0x00, 0x6f, 0x15, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x73, 0x28, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x17, 0x00, 0x0b, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x06, 0x40, 0x00, 0x6e, 0x61, 0x6c,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x4d, 0x65,
- 0x00, 0xe3, 0x65, 0x00, 0x6d, 0x05, 0x73, 0x0b, 0x40, 0x5e, 0x76, 0x65,
- 0x00, 0x40, 0x95, 0x61, 0x6e, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x06, 0x6c, 0x00, 0x01, 0x25, 0xe5, 0x61, 0x00, 0x62, 0x12, 0x64,
- 0x18, 0x67, 0x21, 0x76, 0x2b, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x66, 0x02, 0x04, 0x65, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0x40,
- 0x09, 0x61, 0x74, 0x65, 0x00, 0x40, 0x00, 0x75, 0x63, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0x40, 0x00, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x3b, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x61, 0x6e, 0x00,
- 0xe6, 0x62, 0x00, 0x64, 0x17, 0x67, 0x32, 0x6c, 0x46, 0x72, 0x65, 0x74,
- 0x6d, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x08, 0x40, 0x07, 0x6e, 0x69, 0x73, 0x6d, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x09, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x0b, 0x63, 0x68, 0x61, 0x73,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x1b, 0xe2, 0x62, 0x00, 0x74, 0x10,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x8f, 0x79, 0x00, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x03, 0xb2, 0x00, 0x3b, 0xe1, 0x75, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x05, 0x42, 0x58, 0x73, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x72,
- 0x04, 0x73, 0x14, 0x74, 0x26, 0x40, 0x06, 0x6d, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x04, 0x66, 0x40, 0x09, 0x65, 0x6e, 0x74,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x01, 0xa1, 0x40, 0xec, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x01,
- 0x4b, 0x00, 0x37, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x75, 0x0f, 0xe2, 0x61,
- 0x00, 0x63, 0x04, 0x41, 0x21, 0x64, 0x00, 0x40, 0x0b, 0x6f, 0x72, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0xf9, 0x61, 0x00,
- 0x00, 0x63, 0x04, 0x00, 0x65, 0x25, 0x00, 0x68, 0xa5, 0x00, 0x69, 0xae,
- 0x00, 0x6f, 0x60, 0x01, 0x70, 0xeb, 0x01, 0x74, 0xc1, 0x02, 0x75, 0xc0,
- 0x03, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x10, 0xe2, 0x6e,
- 0x00, 0x73, 0x04, 0x40, 0x7a, 0x64, 0x00, 0x40, 0x07, 0x73, 0x69, 0x6f,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e,
- 0x00, 0x07, 0xe6, 0x61, 0x00, 0x6c, 0x04, 0x6d, 0x08, 0x6e, 0x0e, 0x72,
- 0x37, 0x74, 0x6c, 0x40, 0x22, 0x6c, 0x00, 0x41, 0x21, 0x6c, 0x00, 0x40,
- 0x3a, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6d, 0x15, 0x00, 0x33, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x70,
- 0x00, 0x76, 0x06, 0x40, 0x07, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x61, 0x00,
- 0x65, 0x07, 0x69, 0x17, 0x6f, 0x1c, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x36, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x06,
- 0x69, 0x72, 0x00, 0x40, 0x00, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x00, 0xe6, 0x64, 0x00, 0x67, 0x38,
- 0x6c, 0x4b, 0x6e, 0x64, 0x73, 0x6a, 0x74, 0x98, 0xe2, 0x65, 0x00, 0x75,
- 0x1d, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x06, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x09, 0x75,
- 0x0b, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06,
- 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07,
- 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x3b, 0x64, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x3b,
- 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x10, 0x6c, 0x16, 0x6f, 0x1c, 0x01, 0x5b, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x37,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0x40,
- 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe4, 0x6c, 0x00, 0x6e, 0x2c, 0x72, 0x4a,
- 0x75, 0x52, 0xe4, 0x64, 0x00, 0x65, 0x02, 0x75, 0x04, 0x76, 0x17, 0x00,
- 0x00, 0x00, 0x3a, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x04, 0x67, 0x00, 0x37, 0xe1, 0x61,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40,
- 0x06, 0x65, 0x00, 0x00, 0x3b, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x0b,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x6e, 0x00, 0x72, 0x0f, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x5b, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x49, 0x6c, 0x6c, 0x6f, 0x86, 0x00,
- 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x3e, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x66, 0x1a, 0x69, 0x2d, 0x04, 0x68, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x3b, 0x76, 0x65, 0x00, 0x40, 0x5b, 0x6c, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x19, 0xe1, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0x01, 0x20, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x3b, 0xe1, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x0c, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x5b, 0x40, 0x06, 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0xe2, 0x62, 0x00, 0x76, 0x15, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x06, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x01, 0xe7, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe7, 0x00,
- 0x00, 0x61, 0x02, 0x66, 0x20, 0x69, 0x43, 0x6c, 0x60, 0x6f, 0x76, 0x72,
- 0x95, 0x00, 0x6d, 0xe2, 0x74, 0x00, 0x75, 0x04, 0x40, 0x0b, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x06, 0x74, 0x00, 0x40, 0x09, 0x65, 0x75, 0x72, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x10, 0x00, 0x3e,
- 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x74, 0x00, 0x76,
- 0x08, 0x40, 0x07, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x13, 0xe1, 0x74, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x06,
- 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x11, 0x6f,
- 0x43, 0x75, 0x48, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x74, 0x04, 0x40, 0x37, 0x64, 0x00, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x6e,
- 0x29, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01,
- 0xe2, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x41, 0x21, 0x67, 0x00, 0x40, 0x06,
- 0x6f, 0x6d, 0x00, 0x40, 0x06, 0x63, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67,
- 0x00, 0xe5, 0x6c, 0x00, 0x6d, 0x0f, 0x70, 0x1d, 0x72, 0x23, 0x73, 0x4e,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x95, 0x40, 0x06,
- 0x6e, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x70, 0x02, 0x00, 0x5e, 0x40, 0x09,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x3a, 0x70, 0x6c, 0x79, 0x00, 0xe2,
- 0x67, 0x00, 0x72, 0x11, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x09, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0xad, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0xf9, 0x61, 0x00, 0x00, 0x63, 0x5d, 0x00, 0x65, 0x61,
- 0x00, 0x68, 0x8a, 0x00, 0x69, 0x9b, 0x00, 0x6f, 0xee, 0x00, 0x72, 0xf3,
- 0x00, 0x73, 0xea, 0x01, 0x75, 0xf0, 0x01, 0xe4, 0x69, 0x00, 0x6b, 0x15,
- 0x6c, 0x19, 0x72, 0x35, 0xe2, 0x6c, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x65,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xd6, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x1c, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x02, 0x7d, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe1, 0x64, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11, 0x01, 0x5b, 0xe2, 0x6e, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x3a, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x6e,
- 0x05, 0x40, 0x3c, 0x63, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x42, 0x1a, 0x6e, 0x6b, 0x00, 0x40,
- 0x00, 0x75, 0x67, 0x68, 0x74, 0x00, 0xe3, 0x63, 0x00, 0x6e, 0x2a, 0x72,
- 0x3c, 0xe2, 0x65, 0x00, 0x75, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0xe1, 0x6c, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x09,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x00, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x02, 0x00, 0x06, 0x40,
- 0x09, 0x65, 0x6e, 0x74, 0x00, 0x40, 0xec, 0x72, 0x74, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x24, 0x69, 0x36, 0x6f, 0x66, 0xe2, 0x63, 0x00, 0x69, 0x1b,
- 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x0b, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x04, 0x69, 0xe2, 0x6c, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40,
- 0x08, 0x6e, 0x00, 0x40, 0x72, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x04,
- 0x40, 0xfc, 0x64, 0x00, 0x40, 0x09, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x62, 0x00, 0x65, 0x16, 0xe1, 0x75, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x09, 0x6e, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x06, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x55, 0x00,
- 0x07, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x66, 0x0a, 0x67, 0x2b, 0x72, 0x4a,
- 0x73, 0x52, 0x76, 0x72, 0x00, 0x09, 0x40, 0x3b, 0x63, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x0b,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x3a, 0x64, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x43, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x6f, 0x63, 0x6b, 0x65,
- 0x74, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x03, 0x57, 0xe2, 0x6f, 0x00,
- 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x86, 0x65, 0x00, 0x40, 0x09,
- 0x69, 0x72, 0x75, 0x73, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x61, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40, 0x06,
- 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0xf7, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x65, 0x0a, 0x00, 0x69, 0xe2, 0x00, 0x6f, 0x49, 0x01,
- 0x75, 0xa1, 0x01, 0x76, 0xaf, 0x01, 0x04, 0x6a, 0x40, 0x07, 0x6d, 0x70,
- 0x69, 0x6e, 0x67, 0x00, 0xe6, 0x61, 0x00, 0x69, 0x15, 0x6c, 0x1b, 0x6e,
- 0x35, 0x72, 0x43, 0x74, 0xc4, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x04, 0x6b, 0x40, 0x37, 0x64, 0x00, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x09, 0x72, 0x0d, 0x03, 0x78, 0x40, 0x06, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x67,
- 0x00, 0x75, 0x04, 0x40, 0x82, 0x65, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00,
- 0xe5, 0x62, 0x00, 0x65, 0x1c, 0x69, 0x3c, 0x73, 0x40, 0x74, 0x69, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3a, 0xe3, 0x63,
- 0x00, 0x64, 0x04, 0x74, 0x06, 0x40, 0x5e, 0x65, 0x00, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40,
- 0x09, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x69, 0x08,
- 0x00, 0x07, 0x40, 0x06, 0x6c, 0x00, 0x00, 0x3b, 0xe1, 0x62, 0x00, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x00, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0xad, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x6d,
- 0x65, 0x6e, 0x74, 0x00, 0xe3, 0x6c, 0x00, 0x73, 0x14, 0x76, 0x36, 0xe1,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x00, 0xae, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x09, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe3, 0x61, 0x00, 0x65, 0x16, 0x69, 0x18,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x73,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0x00, 0x3a,
- 0x40, 0x07, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3,
- 0x63, 0x00, 0x6b, 0x07, 0x6c, 0x0b, 0x40, 0x00, 0x61, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe3, 0x74, 0x00, 0x75, 0x0c, 0x76, 0x33,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xed, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x06, 0x40, 0x06, 0x72,
- 0x79, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x74, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x40, 0x07,
- 0x73, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x1e,
- 0x69, 0x2f, 0x6f, 0x34, 0x72, 0x3a, 0xe2, 0x72, 0x00, 0x73, 0x15, 0xe2,
- 0x64, 0x00, 0x6d, 0x0e, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x37, 0x6e, 0x67, 0x00, 0x00, 0xad, 0x40, 0x0b, 0x68, 0x00,
- 0xe2, 0x61, 0x00, 0x64, 0x05, 0x40, 0x3c, 0x76, 0x65, 0x00, 0x40, 0x00,
- 0x64, 0x69, 0x6e, 0x67, 0x00, 0x42, 0x56, 0x6e, 0x64, 0x00, 0x40, 0x00,
- 0x75, 0x6e, 0x64, 0x00, 0x41, 0x7f, 0x69, 0x74, 0x65, 0x00, 0xf6, 0x61,
- 0x00, 0x00, 0x65, 0x27, 0x00, 0x69, 0x97, 0x00, 0x6f, 0xd8, 0x00, 0x75,
- 0x12, 0x01, 0x79, 0x19, 0x01, 0xe1, 0x70, 0x00, 0xe1, 0x73, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63,
- 0x00, 0x7a, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x00, 0x40, 0x0b, 0x65, 0x00, 0x00, 0x06, 0xe6, 0x61, 0x00, 0x6e,
- 0x02, 0x6f, 0x08, 0x73, 0x0f, 0x74, 0x14, 0x75, 0x32, 0x00, 0x09, 0x40,
- 0x07, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x06, 0x73, 0x74, 0x61, 0x74, 0x00,
- 0x40, 0x09, 0x75, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06,
- 0x00, 0x07, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0xe1,
- 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x79, 0x25, 0x00, 0x07, 0xe1,
- 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x16, 0xe2, 0x63, 0x00, 0x73, 0x0d,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x00, 0x69, 0x64, 0x00, 0x00, 0x00,
- 0xe2, 0x6e, 0x00, 0x7a, 0x36, 0xe3, 0x65, 0x00, 0x69, 0x08, 0x6f, 0x0e,
- 0x40, 0x06, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x74, 0x69,
- 0x73, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x70, 0x09, 0x76, 0x11, 0x00,
- 0x09, 0x40, 0x09, 0x65, 0x72, 0x6f, 0x73, 0x00, 0x40, 0x00, 0x6c, 0x61,
- 0x73, 0x74, 0x79, 0x00, 0x40, 0x09, 0x69, 0x72, 0x75, 0x73, 0x00, 0x40,
- 0x09, 0x6f, 0x6d, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6d, 0x16,
- 0x00, 0x06, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x75, 0x6d, 0x00,
- 0x40, 0x06, 0x64, 0x65, 0x6e, 0x64, 0x72, 0x6f, 0x6e, 0x00, 0xe1, 0x62,
- 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0x40,
- 0x09, 0x73, 0x00, 0x40, 0x09, 0x62, 0x61, 0x72, 0x62, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x14, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73,
- 0x04, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0xe1,
- 0x68, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b,
- 0x6c, 0x00, 0xff, 0x61, 0x00, 0x00, 0x62, 0x04, 0x00, 0x63, 0x42, 0x00,
- 0x64, 0x94, 0x00, 0x66, 0x16, 0x01, 0x67, 0x58, 0x01, 0x6c, 0x2c, 0x02,
- 0x6d, 0x35, 0x02, 0x6e, 0x56, 0x02, 0x6f, 0xb4, 0x02, 0x70, 0xd0, 0x02,
- 0x73, 0x40, 0x03, 0x74, 0x9e, 0x03, 0x76, 0xdc, 0x03, 0x79, 0x4a, 0x04,
- 0x40, 0x09, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x62, 0x13, 0x6f,
- 0x2c, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x6f, 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x07, 0x66,
- 0x6c, 0x61, 0x76, 0x69, 0x6e, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x09, 0x6b,
- 0x16, 0x6f, 0x39, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x6c, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x72, 0x0e, 0x73, 0x14, 0x00, 0x59,
- 0xe1, 0x74, 0x00, 0xe2, 0x73, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0xf3,
- 0x40, 0x07, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x68, 0x61, 0x77, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x06, 0x40, 0x59, 0x68, 0x65, 0x74, 0x00, 0x40,
- 0x07, 0x74, 0x61, 0x00, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x65, 0x1e, 0x67,
- 0x3a, 0x69, 0x4e, 0x00, 0x08, 0xe4, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0a,
- 0x6c, 0x0f, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x02, 0x04, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x73, 0x08, 0x00,
- 0x07, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x68, 0x69, 0x70,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00,
- 0x82, 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x00, 0x00, 0x00, 0xe2, 0x63, 0x00,
- 0x6e, 0x20, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x02, 0x00, 0x82, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x67, 0x00, 0xe4, 0x65, 0x00, 0x66, 0x02, 0x6c, 0x15, 0x74, 0x37, 0x00,
- 0x60, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x06, 0x00, 0x59, 0x40, 0x5e,
- 0x65, 0x00, 0x40, 0x07, 0x61, 0x66, 0x66, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x18, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x0f, 0x00, 0xa5, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x59, 0xe7, 0x00, 0x00, 0x61,
- 0x02, 0x67, 0x09, 0x68, 0x1c, 0x69, 0x89, 0x6d, 0xa0, 0x6f, 0xa8, 0x00,
- 0x06, 0x40, 0x07, 0x74, 0x6f, 0x6e, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe9, 0x00, 0x00, 0x65, 0x02, 0x66,
- 0x1e, 0x69, 0x31, 0x6d, 0x3d, 0x6e, 0x43, 0x6f, 0x49, 0x73, 0x4b, 0x77,
- 0x51, 0x03, 0x9b, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x06, 0x00, 0xdf, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0x00, 0x06, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x40, 0x3a, 0x69, 0x7a, 0x65, 0x00, 0x40, 0x08,
- 0x61, 0x72, 0x64, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6e, 0x07, 0x00, 0x3e, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x61, 0x72, 0x6f, 0x6c, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x02, 0x00, 0x0b, 0x00,
- 0x09, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04, 0x6d, 0x0a, 0x00, 0x93,
- 0x00, 0x09, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x64,
- 0x00, 0x67, 0x02, 0x6b, 0x4f, 0x73, 0x51, 0x00, 0x09, 0xe8, 0x00, 0x00,
- 0x65, 0x02, 0x67, 0x06, 0x6c, 0x0b, 0x6d, 0x22, 0x73, 0x2a, 0x74, 0x30,
- 0x77, 0x36, 0x04, 0x6d, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x69, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x61, 0x00, 0x74, 0x06, 0x40,
- 0x09, 0x64, 0x65, 0x72, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6b, 0x65, 0x00,
- 0x40, 0x09, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07, 0x69, 0x64,
- 0x65, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x72,
- 0x6d, 0x00, 0x00, 0x09, 0x40, 0x82, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6f, 0x0b, 0x00, 0xc3, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x4d, 0x75, 0x73, 0x00,
- 0xe8, 0x00, 0x00, 0x61, 0x02, 0x63, 0x09, 0x65, 0x0f, 0x6f, 0x28, 0x70,
- 0x36, 0x73, 0x54, 0x74, 0x59, 0x04, 0x6e, 0x40, 0x00, 0x72, 0x69, 0x61,
- 0x6e, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x20, 0xe2, 0x64,
- 0x00, 0x73, 0x02, 0x00, 0x37, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x66, 0x00,
- 0x73, 0x04, 0x40, 0x06, 0x66, 0x00, 0x40, 0x82, 0x74, 0x65, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x09, 0x6c, 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x5e, 0x00, 0x00, 0x40, 0x06, 0x61, 0x77, 0x00, 0x40, 0x09,
- 0x69, 0x64, 0x65, 0x00, 0xe6, 0x65, 0x00, 0x69, 0x0d, 0x6b, 0x26, 0x6f,
- 0x40, 0x71, 0x46, 0x73, 0x4b, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x04,
- 0x04, 0x6f, 0x00, 0x00, 0x00, 0x07, 0xe2, 0x62, 0x00, 0x6e, 0x10, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x40, 0x07, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x79, 0x11, 0x00, 0x59, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0x40, 0x09, 0x74,
- 0x74, 0x6f, 0x00, 0x40, 0x00, 0x75, 0x65, 0x00, 0x40, 0x08, 0x6f, 0x6c,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x75, 0x02, 0x7a, 0x33, 0x00, 0x09, 0xe1,
- 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56,
- 0xe2, 0x73, 0x00, 0x7a, 0x1a, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07,
- 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00,
- 0x40, 0xf3, 0x79, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x16, 0x69,
- 0x57, 0x75, 0x5d, 0x04, 0x70, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x72, 0x06, 0x00, 0x47, 0x40, 0x37, 0x64, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x2f, 0x01, 0x98, 0xe4, 0x00,
- 0x00, 0x62, 0x02, 0x66, 0x17, 0x73, 0x1e, 0x00, 0x07, 0xe3, 0x61, 0x00,
- 0x65, 0x05, 0x6f, 0x09, 0x40, 0x06, 0x6e, 0x6b, 0x00, 0x40, 0x09, 0x64,
- 0x00, 0x40, 0x06, 0x61, 0x74, 0x00, 0x40, 0x00, 0x72, 0x6f, 0x6e, 0x74,
- 0x00, 0x40, 0x09, 0x69, 0x64, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x65, 0x72, 0x61, 0x00,
- 0x40, 0x09, 0x6c, 0x65, 0x74, 0x00, 0x40, 0x09, 0x61, 0x6c, 0x00, 0x00,
- 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0xea, 0x00, 0x59, 0x01, 0xab, 0x01,
- 0xc1, 0x01, 0x00, 0x00, 0xd7, 0x01, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x24, 0x02, 0x7b, 0x02, 0xd7, 0x02, 0xdc, 0x02, 0x7d, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x8d, 0x03, 0xff, 0x03, 0xc3, 0x04, 0xb1, 0x05,
- 0xbd, 0x05, 0x00, 0x00, 0x0c, 0x06, 0xe6, 0x63, 0x00, 0x64, 0x04, 0x6d,
- 0x6d, 0x6e, 0x7f, 0x72, 0x81, 0x73, 0x93, 0x40, 0x59, 0x68, 0x00, 0xe8,
- 0x00, 0x00, 0x62, 0x02, 0x68, 0x11, 0x69, 0x18, 0x6b, 0x1c, 0x72, 0x22,
- 0x73, 0x2a, 0x77, 0x40, 0x01, 0x89, 0xe2, 0x65, 0x00, 0x6c, 0x04, 0x40,
- 0x06, 0x64, 0x00, 0x40, 0x47, 0x6f, 0x63, 0x6b, 0x00, 0x40, 0x06, 0x6f,
- 0x75, 0x73, 0x65, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6c,
- 0x6c, 0x00, 0x40, 0x06, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x00, 0xe3, 0x68,
- 0x00, 0x69, 0x05, 0x74, 0x0a, 0x40, 0x06, 0x6f, 0x77, 0x00, 0x40, 0x06,
- 0x64, 0x65, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x04, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x6b, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x68, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x00, 0x3f, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00,
- 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x04, 0x2a, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02,
- 0x65, 0x1c, 0x69, 0x27, 0x6f, 0x2b, 0x75, 0x4f, 0x00, 0x08, 0xe2, 0x65,
- 0x00, 0x69, 0x10, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x83, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x09, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x06, 0x40, 0x5b, 0x61, 0x6c,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe2, 0x63, 0x00,
- 0x7a, 0x09, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0x40,
- 0x0b, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0xe0, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6b,
- 0x00, 0x6f, 0x48, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x62, 0x0a, 0x65, 0x11,
- 0x66, 0x2a, 0x69, 0x30, 0x79, 0x37, 0x00, 0xc3, 0x40, 0x07, 0x62, 0x69,
- 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe2,
- 0x72, 0x00, 0x74, 0x09, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x08, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x47, 0x40, 0x07, 0x79, 0x00,
- 0x40, 0x06, 0x61, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x3b, 0x40, 0x07, 0x63, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x6f, 0x06, 0x00, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6e,
- 0x08, 0x00, 0x06, 0x40, 0x06, 0x75, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x74,
- 0x67, 0x65, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x04, 0x40, 0x0b, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x72,
- 0x06, 0x04, 0x71, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x02, 0x00,
- 0x0b, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x3f, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x6c, 0x02, 0x00, 0x09, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x69,
- 0x26, 0x6d, 0x38, 0x6f, 0x3d, 0x01, 0xc0, 0x40, 0x06, 0x61, 0x63, 0x6b,
- 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x73, 0x0b, 0x00,
- 0x07, 0x40, 0x00, 0x6c, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x6b, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x7a, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x08, 0x6f, 0x70, 0x00, 0x40, 0x06, 0x76, 0x65, 0x72, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x46, 0x70, 0x4a, 0xe2, 0x69, 0x00, 0x6e, 0x05,
- 0x40, 0x09, 0x6e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x74, 0x0e,
- 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5,
- 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x08, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2,
- 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x3a, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x64, 0x6f,
- 0x00, 0xe6, 0x64, 0x00, 0x66, 0x02, 0x6b, 0x23, 0x6d, 0x35, 0x73, 0x64,
- 0x74, 0x72, 0x00, 0x09, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c,
- 0x0b, 0x74, 0x11, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x70,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x07, 0x00, 0x55, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02,
- 0x66, 0x0e, 0x69, 0x13, 0x6d, 0x1a, 0x79, 0x20, 0x00, 0xfe, 0xe2, 0x72,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x06, 0x74, 0x65, 0x00, 0x40, 0x06,
- 0x75, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x61, 0x74, 0x65, 0x00, 0x00, 0xf4, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x6b, 0x06, 0x6c, 0x0b, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x06, 0x69, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04,
- 0x40, 0x5d, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x79, 0x09, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0xf3, 0xe5, 0x61,
- 0x00, 0x65, 0x05, 0x69, 0x42, 0x74, 0x57, 0x79, 0x65, 0x40, 0x06, 0x72,
- 0x79, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x62, 0x07, 0x6d, 0x15, 0x74,
- 0x1b, 0x77, 0x20, 0x00, 0x09, 0x40, 0x00, 0x74, 0x65, 0x00, 0xe1, 0x75,
- 0x00, 0xe2, 0x64, 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x09, 0x68, 0x00,
- 0x40, 0x07, 0x61, 0x72, 0x79, 0x00, 0x40, 0x06, 0x74, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x74, 0x65, 0x72, 0x00, 0x40, 0x09,
- 0x6f, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x2c, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x75,
- 0x6d, 0x00, 0x00, 0xf4, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x3f, 0x67,
- 0x41, 0x69, 0x46, 0x6f, 0x4f, 0x74, 0x69, 0x75, 0x95, 0x00, 0x06, 0xe3,
- 0x00, 0x00, 0x72, 0x02, 0x74, 0x06, 0x00, 0x08, 0x40, 0x06, 0x79, 0x00,
- 0xe4, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x11, 0x6f, 0x22, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x38, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00,
- 0x00, 0x07, 0x40, 0x07, 0x75, 0x74, 0x00, 0x40, 0x06, 0x73, 0x73, 0x65,
- 0x72, 0x69, 0x65, 0x00, 0xe3, 0x67, 0x00, 0x72, 0x09, 0x74, 0x0b, 0x40,
- 0x09, 0x72, 0x61, 0x76, 0x75, 0x72, 0x65, 0x00, 0x00, 0x06, 0x40, 0x09,
- 0x69, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x18, 0x77,
- 0x1d, 0xe3, 0x64, 0x00, 0x6e, 0x02, 0x72, 0x0f, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x46, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x08, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x65, 0x69, 0x6c, 0x65,
- 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x04, 0x6e, 0x09, 0x00, 0x5d, 0x00, 0x09, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe7, 0x65, 0x00, 0x67,
- 0x02, 0x6c, 0x4c, 0x6e, 0x53, 0x73, 0x9a, 0x74, 0xaf, 0x78, 0xdd, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x68, 0x02, 0x00, 0x5e, 0xe7, 0x00, 0x00, 0x61,
- 0x02, 0x63, 0x07, 0x65, 0x0d, 0x68, 0x11, 0x6e, 0x18, 0x73, 0x28, 0x04,
- 0x72, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x00, 0x61, 0x73, 0x74, 0x00,
- 0x40, 0xed, 0x6e, 0x00, 0x40, 0x82, 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x04, 0x40, 0x59, 0x6b, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6f, 0x64, 0x00, 0x40, 0x07, 0x65, 0x74, 0x74, 0x65, 0x00, 0xe1, 0x64,
- 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x68, 0x17, 0x69, 0x1e,
- 0x6e, 0x23, 0x75, 0x29, 0x77, 0x2d, 0x04, 0x73, 0x40, 0x06, 0x62, 0x6f,
- 0x75, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x08, 0x40, 0x09, 0x79, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00,
- 0x40, 0x00, 0x73, 0x68, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x70, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x6d, 0x00, 0xe2, 0x65, 0x00,
- 0x74, 0x02, 0x00, 0x3a, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x7a, 0x40,
- 0x06, 0x62, 0x6f, 0x75, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x18, 0x00, 0xe6, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x69, 0x06, 0x72, 0x0b,
- 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00,
- 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x86, 0x40,
- 0x0b, 0x7a, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x62,
- 0x06, 0x64, 0x0c, 0x65, 0x2c, 0x69, 0x35, 0x6c, 0x3a, 0x00, 0xfa, 0x40,
- 0x08, 0x6e, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x13,
- 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x2c,
- 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x6f, 0x63, 0x6b,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x74, 0x07, 0x00, 0x56, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x07, 0x65, 0x73, 0x00, 0x00, 0x06, 0xe2, 0x6d, 0x00,
- 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0xfe, 0x62, 0x00, 0x00, 0x63, 0x95, 0x00, 0x64, 0xbb,
- 0x00, 0x65, 0x07, 0x01, 0x66, 0x21, 0x01, 0x67, 0x3e, 0x01, 0x69, 0x69,
- 0x01, 0x6c, 0x81, 0x01, 0x6d, 0x94, 0x01, 0x6e, 0x20, 0x02, 0x70, 0x8f,
- 0x02, 0x72, 0xaf, 0x02, 0x73, 0xb4, 0x02, 0x74, 0x28, 0x03, 0xe9, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x07, 0x64, 0x54, 0x65, 0x5a, 0x69, 0x66, 0x6c,
- 0x77, 0x72, 0x7b, 0x79, 0x80, 0x00, 0x06, 0x40, 0x06, 0x74, 0x6f, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x2d, 0x6c, 0x42, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x79, 0x1b, 0x00,
- 0x06, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07,
- 0x72, 0x00, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x08, 0x67,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x47, 0x00,
- 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x40, 0x07, 0x6c, 0x61, 0x00, 0xe2,
- 0x63, 0x00, 0x64, 0x06, 0x40, 0x00, 0x75, 0x6e, 0x64, 0x00, 0x40, 0x07,
- 0x69, 0x75, 0x6d, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x69, 0x63,
- 0x00, 0x01, 0x64, 0xe3, 0x68, 0x00, 0x6b, 0x05, 0x74, 0x18, 0x40, 0x00,
- 0x65, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x75, 0x08, 0x00, 0x72,
- 0x40, 0x09, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40, 0x00,
- 0x69, 0x6f, 0x6e, 0x73, 0x00, 0xe3, 0x64, 0x00, 0x65, 0x20, 0x69, 0x2d,
- 0xe3, 0x65, 0x00, 0x69, 0x10, 0x79, 0x17, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x6c, 0x02, 0x00, 0x06, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x03, 0x3c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x00, 0x00,
- 0x66, 0x02, 0x00, 0x5e, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x66, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07, 0x01, 0x17, 0x40,
- 0x86, 0x61, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x5e, 0x00, 0x37, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x67, 0x06, 0x72,
- 0x1d, 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x64,
- 0x00, 0x72, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x63, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x06, 0x61, 0x74, 0x00, 0xe1,
- 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x09, 0x00, 0x55, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0x7a, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x69,
- 0x20, 0x6d, 0x43, 0x6f, 0x5c, 0x70, 0x6e, 0x00, 0x06, 0xe3, 0x61, 0x00,
- 0x6c, 0x02, 0x75, 0x0e, 0x00, 0x2c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02,
- 0x10, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x73, 0x74, 0x69, 0x6f,
- 0x75, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00,
- 0x74, 0x04, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x40, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x3b,
- 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x79, 0x10, 0x40, 0x5e, 0x67,
- 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00,
- 0x2c, 0x40, 0x06, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x75, 0x06, 0x00, 0x86, 0x40, 0x5e, 0x65, 0x00, 0x40, 0x09,
- 0x73, 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x64, 0x1b, 0x65, 0x21, 0x67,
- 0x23, 0x69, 0x25, 0x6c, 0x29, 0x6e, 0x2e, 0x6f, 0x45, 0x74, 0x4a, 0x77,
- 0x53, 0x00, 0x65, 0xe3, 0x62, 0x00, 0x72, 0x06, 0x77, 0x0d, 0x40, 0x09,
- 0x6f, 0x75, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0x40,
- 0x09, 0x61, 0x79, 0x00, 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x09,
- 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00,
- 0x06, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0x40, 0x06,
- 0x66, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0xf3,
- 0x40, 0x06, 0x61, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x74, 0x13,
- 0x40, 0x06, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x82, 0x75, 0x72, 0x65,
- 0x00, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe5, 0x65, 0x00, 0x68, 0x02, 0x6b,
- 0x11, 0x73, 0x13, 0x74, 0x18, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x79, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x00, 0x00, 0x00, 0x09,
- 0x40, 0x06, 0x65, 0x74, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x31,
- 0x70, 0x3d, 0x79, 0x44, 0x00, 0x55, 0xe2, 0x63, 0x00, 0x6e, 0x24, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x69, 0x18, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x74,
- 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x0b, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x02, 0xd3, 0x00, 0x07, 0x40, 0x7a, 0x72, 0x6f, 0x6f, 0x66, 0x00,
- 0x04, 0x74, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x68, 0x09, 0x74, 0x39, 0x00,
- 0x06, 0x40, 0x06, 0x62, 0x61, 0x67, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x6c,
- 0x15, 0xe2, 0x6e, 0x00, 0x72, 0x06, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00,
- 0x40, 0x07, 0x66, 0x6f, 0x72, 0x64, 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x00, 0xf3, 0x40, 0x07, 0x65, 0x00, 0xc1, 0x61, 0x19, 0x37, 0x00, 0x39,
- 0x00, 0xa4, 0x0b, 0xaa, 0x0b, 0x00, 0x00, 0x9e, 0x17, 0xfb, 0x27, 0xfd,
- 0x27, 0x02, 0x28, 0xb3, 0x34, 0x00, 0x00, 0x9b, 0x3c, 0xce, 0x3f, 0x7d,
- 0x46, 0xe1, 0x48, 0xe3, 0x4c, 0xc2, 0x56, 0xbe, 0x63, 0x7b, 0x65, 0x84,
- 0x65, 0x88, 0x65, 0xa9, 0x7b, 0xcc, 0x8e, 0xd3, 0x8e, 0x00, 0x00, 0xe7,
- 0x92, 0x04, 0x75, 0xc0, 0x62, 0x18, 0x33, 0x00, 0x69, 0x00, 0x5a, 0x01,
- 0x00, 0x00, 0xf8, 0x01, 0x3c, 0x02, 0x8b, 0x02, 0x90, 0x02, 0x00, 0x00,
- 0x17, 0x03, 0x1b, 0x03, 0x39, 0x05, 0x94, 0x05, 0x00, 0x00, 0x69, 0x07,
- 0x00, 0x00, 0xef, 0x07, 0x8e, 0x08, 0xb0, 0x08, 0x07, 0x0a, 0x7c, 0x0a,
- 0xf2, 0x0a, 0x30, 0x0b, 0x59, 0x0b, 0xe5, 0x62, 0x00, 0x65, 0x09, 0x6c,
- 0x0d, 0x6f, 0x11, 0x72, 0x27, 0x40, 0x06, 0x61, 0x74, 0x69, 0x63, 0x61,
- 0x6c, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x00, 0x09, 0x40, 0x5e,
- 0x67, 0x65, 0x00, 0x40, 0x06, 0x75, 0x72, 0x00, 0x40, 0x09, 0x61, 0x00,
- 0xe6, 0x00, 0x00, 0x63, 0x02, 0x65, 0x1a, 0x68, 0x23, 0x6b, 0x2f, 0x72,
- 0x4b, 0x00, 0x06, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x00, 0x72, 0x64, 0x6f, 0x74, 0x61, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x06, 0x00, 0x06,
- 0xe4, 0x00, 0x00, 0x63, 0x02, 0x66, 0x09, 0x69, 0x0e, 0x04, 0x12, 0x40,
- 0x07, 0x6c, 0x6f, 0x74, 0x68, 0x00, 0x40, 0x09, 0x75, 0x6c, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x1b, 0x69, 0x2b, 0x6f,
- 0x65, 0x75, 0x8a, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x66,
- 0x00, 0x6c, 0x12, 0x73, 0x25, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00,
- 0x79, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x73,
- 0x07, 0x40, 0x09, 0x6c, 0x69, 0x61, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6d,
- 0x00, 0xe7, 0x00, 0x00, 0x64, 0x02, 0x65, 0x36, 0x68, 0x3a, 0x69, 0x3e,
- 0x6e, 0x5f, 0x6f, 0x65, 0x00, 0x4d, 0xe2, 0x65, 0x00, 0x6c, 0x0f, 0xe3,
- 0x6e, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x7a, 0x00, 0x00, 0x40, 0x00,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06,
- 0x72, 0x0b, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x61, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x08, 0x00, 0x00, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x08, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x63, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x66, 0x2c, 0x40, 0x93,
- 0x72, 0x69, 0x00, 0xe5, 0x00, 0x00, 0x67, 0x02, 0x6b, 0x09, 0x6e, 0x12,
- 0x74, 0x18, 0x04, 0x76, 0x40, 0x2c, 0x75, 0x61, 0x72, 0x64, 0x00, 0x40,
- 0x07, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x07, 0x40,
- 0x09, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe6,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x1a, 0x67, 0x28, 0x6f, 0x3a, 0x75, 0x3c,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x09, 0xe1, 0x69, 0x00,
- 0xe2, 0x6f, 0x00, 0x74, 0x05, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x04, 0x77, 0x40, 0x07, 0x72,
- 0x75, 0x73, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0x00, 0x07,
- 0x40, 0x09, 0x61, 0x72, 0x6f, 0x00, 0x40, 0x09, 0x69, 0x62, 0x00, 0xe4,
- 0x64, 0x00, 0x6c, 0x02, 0x6e, 0x52, 0x74, 0x7a, 0x00, 0x37, 0xe7, 0x00,
- 0x00, 0x62, 0x02, 0x63, 0x24, 0x66, 0x2b, 0x69, 0x31, 0x6f, 0x36, 0x70,
- 0x3a, 0x04, 0x78, 0xe1, 0x6f, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00,
- 0x74, 0x15, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x02, 0xdc, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00,
- 0x09, 0x40, 0x07, 0x6c, 0x6f, 0x74, 0x68, 0x00, 0x40, 0x09, 0x69, 0x73,
- 0x68, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40,
- 0x09, 0x6c, 0x61, 0x6e, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x68, 0x02, 0x6c, 0x08, 0x03, 0xb9, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6b, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0x40, 0x00,
- 0x68, 0x00, 0x40, 0x07, 0x65, 0x00, 0xfa, 0x61, 0x00, 0x00, 0x65, 0x49,
- 0x00, 0x69, 0xc0, 0x00, 0x6c, 0xfd, 0x00, 0x6d, 0x14, 0x01, 0x6f, 0x33,
- 0x01, 0x73, 0x3e, 0x01, 0x74, 0x42, 0x01, 0x75, 0x9c, 0x01, 0x76, 0xd2,
- 0x01, 0xe6, 0x61, 0x00, 0x62, 0x04, 0x63, 0x09, 0x64, 0x28, 0x6d, 0x2a,
- 0x72, 0x38, 0x40, 0x2c, 0x6d, 0x00, 0x40, 0x37, 0x6c, 0x65, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0x00, 0x09, 0xe2, 0x61, 0x00, 0x69,
- 0x07, 0x40, 0x06, 0x6e, 0x64, 0x65, 0x72, 0x00, 0x00, 0x06, 0x40, 0x1a,
- 0x79, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x08, 0x04, 0x79, 0x40,
- 0x08, 0x6f, 0x6f, 0x6d, 0x00, 0xe7, 0x63, 0x00, 0x67, 0x07, 0x6c, 0x0d,
- 0x6d, 0x13, 0x70, 0x2c, 0x72, 0x40, 0x77, 0x46, 0x40, 0x06, 0x6c, 0x65,
- 0x72, 0x6b, 0x00, 0x40, 0x06, 0x69, 0x72, 0x6c, 0x00, 0x40, 0x06, 0x61,
- 0x64, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x06,
- 0x40, 0x07, 0x70, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x73, 0x6f, 0x6e, 0x00,
- 0x40, 0x08, 0x6f, 0x6f, 0x6d, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0xe3, 0x65, 0x00, 0x6e, 0x0e, 0x76, 0x1a, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x56, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x74, 0x06, 0x00, 0x07, 0x40, 0x00,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x10, 0xe1, 0x77, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0xf4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x5e, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x6f,
- 0x02, 0x00, 0x09, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x09, 0x61, 0x00, 0xea,
- 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x63, 0x0b, 0x65, 0x13, 0x69, 0x1c,
- 0x70, 0x2d, 0x73, 0x34, 0x77, 0x3c, 0x79, 0x43, 0x04, 0x7a, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x09, 0x6f, 0x78, 0x00, 0x40, 0x06, 0x65, 0x6c, 0x6c,
- 0x61, 0x72, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x40, 0x07, 0x73, 0x00, 0x40, 0x07, 0x65, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x06, 0x68, 0x61, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x07, 0x61, 0x74,
- 0x65, 0x72, 0x00, 0x00, 0xf4, 0xe2, 0x62, 0x00, 0x74, 0x08, 0x40, 0x54,
- 0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x22, 0xe2,
- 0x72, 0x00, 0x74, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x05, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xe3,
- 0x61, 0x00, 0x65, 0x1b, 0x6f, 0x24, 0xe2, 0x67, 0x00, 0x74, 0x10, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x5e, 0x40, 0x00, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x09, 0xe7, 0x61, 0x00, 0x62,
- 0x07, 0x65, 0x0b, 0x69, 0x1c, 0x6f, 0x23, 0x70, 0x31, 0x75, 0x46, 0x40,
- 0x07, 0x72, 0x69, 0x75, 0x6d, 0x00, 0x40, 0x47, 0x61, 0x00, 0xe3, 0x00,
- 0x00, 0x6e, 0x02, 0x79, 0x08, 0x03, 0xfd, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x00, 0x40, 0x08, 0x7a, 0x64, 0x61, 0x74, 0x00, 0xe2, 0x73,
- 0x00, 0x76, 0x04, 0x40, 0x08, 0x61, 0x00, 0x40, 0x06, 0x61, 0x72, 0x00,
- 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0x19, 0x00, 0x07, 0x40, 0x06, 0x72,
- 0x61, 0x69, 0x00, 0xf8, 0x61, 0x00, 0x00, 0x63, 0x09, 0x00, 0x64, 0x6b,
- 0x00, 0x65, 0x47, 0x01, 0x67, 0x54, 0x01, 0x69, 0x7d, 0x01, 0x6b, 0xad,
- 0x01, 0x73, 0xaf, 0x01, 0x40, 0x06, 0x74, 0x6f, 0x72, 0x69, 0x75, 0x6d,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x4e, 0xe4, 0x66, 0x00,
- 0x6d, 0x10, 0x6f, 0x33, 0x74, 0x41, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40,
- 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0x0d, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x16, 0xe1, 0x6f, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x95, 0x40, 0x37, 0x64, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x6d, 0x05, 0x40, 0x06, 0x72, 0x79,
- 0x00, 0x00, 0x06, 0xed, 0x00, 0x00, 0x61, 0x02, 0x62, 0x12, 0x63, 0x58,
- 0x65, 0x60, 0x68, 0x64, 0x69, 0x69, 0x6c, 0x70, 0x6d, 0x82, 0x70, 0x8f,
- 0x73, 0xa6, 0x77, 0xb9, 0x79, 0xbf, 0x00, 0xc3, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x77, 0x02, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00,
- 0xe3, 0x61, 0x00, 0x6c, 0x27, 0x6f, 0x3b, 0xe3, 0x67, 0x00, 0x6e, 0x1a,
- 0x72, 0x1e, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6b, 0x00, 0x00, 0x06, 0xe1, 0x61,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x78, 0x00, 0x40, 0x09,
- 0x61, 0x73, 0x74, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06,
- 0x6f, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40,
- 0x09, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x59,
- 0x70, 0x65, 0x72, 0x00, 0xe2, 0x70, 0x00, 0x74, 0x05, 0x40, 0x09, 0x65,
- 0x72, 0x00, 0x00, 0x08, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e,
- 0x00, 0x72, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x06, 0x6d, 0x00, 0x40,
- 0x47, 0x69, 0x63, 0x68, 0x00, 0x00, 0xf4, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x04, 0x7b, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x66,
- 0x02, 0x72, 0x09, 0x75, 0x0e, 0x00, 0x08, 0x40, 0x07, 0x72, 0x6f, 0x69,
- 0x64, 0x00, 0x40, 0x07, 0x69, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x00, 0x72, 0x79, 0x00, 0x00,
- 0x3b, 0xe1, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x1f, 0x79, 0x24, 0xe2,
- 0x72, 0x00, 0x74, 0x14, 0xe2, 0x69, 0x00, 0x79, 0x0d, 0xe2, 0x61, 0x00,
- 0x75, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x06, 0x6d, 0x00, 0x00, 0x9b,
- 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0x00,
- 0x53, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x72, 0x69, 0x66, 0x00, 0xe7, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x17, 0x70,
- 0x26, 0x72, 0x4f, 0x73, 0x69, 0x77, 0x71, 0x00, 0x06, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x73, 0x04, 0x74, 0x06, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40,
- 0x00, 0x73, 0x73, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe4, 0x65, 0x00,
- 0x68, 0x09, 0x69, 0x0f, 0x79, 0x1e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0x00, 0x08, 0x40, 0x06, 0x69, 0x72, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00,
- 0x01, 0x0c, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x75, 0x63, 0x6b, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0xea, 0x61, 0x00, 0x63, 0x04, 0x64,
- 0x43, 0x67, 0x63, 0x69, 0x67, 0x6b, 0x69, 0x6e, 0x6d, 0x6f, 0x72, 0x73,
- 0x77, 0x74, 0x82, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x1d,
- 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x70, 0x04, 0x40, 0x09,
- 0x61, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x69, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6e, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x65, 0x00, 0x00, 0x09,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x08, 0x69, 0x65, 0x00, 0x40, 0x06, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x61, 0x70, 0x61, 0x72, 0x69, 0x6c, 0x6c, 0x61,
- 0x00, 0x40, 0x3b, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x68, 0x00,
- 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x93, 0x79,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x79, 0x09, 0x00, 0x59, 0x40, 0x09,
- 0x66, 0x72, 0x61, 0x73, 0x00, 0x00, 0xf3, 0xfa, 0x00, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x63, 0x25, 0x00, 0x65, 0x2b, 0x00, 0x69, 0x3f, 0x00, 0x6f,
- 0xed, 0x00, 0x72, 0xf2, 0x00, 0x73, 0xf7, 0x00, 0x75, 0xfd, 0x00, 0x79,
- 0x21, 0x01, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x79, 0x1c, 0xe1, 0x69, 0x00,
- 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x3b, 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x09, 0x00, 0x00, 0x40, 0x09, 0x68, 0x65, 0x6c, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6c, 0x06, 0x00, 0x0b, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x5e,
- 0x6c, 0x69, 0x74, 0x65, 0x00, 0xe6, 0x61, 0x00, 0x65, 0x16, 0x6e, 0x1b,
- 0x72, 0x2c, 0x73, 0x4d, 0x76, 0x9d, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40,
- 0x54, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe3, 0x00, 0x00,
- 0x77, 0x02, 0x79, 0x08, 0x00, 0x07, 0x40, 0x06, 0x6f, 0x6f, 0x64, 0x00,
- 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe3, 0x63, 0x00,
- 0x73, 0x0b, 0x7a, 0x0f, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe1,
- 0x66, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x29, 0x79, 0x2e, 0xe1, 0x63, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0f, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x84, 0x00, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x37, 0x6c, 0x79, 0x00,
- 0x00, 0x37, 0x40, 0x37, 0x65, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x02, 0xef, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x37, 0x40, 0x00, 0x79, 0x00, 0x40, 0x00, 0x61, 0x00, 0x40,
- 0x07, 0x72, 0x69, 0x00, 0x40, 0x06, 0x61, 0x70, 0x00, 0x40, 0x08, 0x75,
- 0x6d, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x16, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x57, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x69,
- 0x6e, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe2, 0x61, 0x00, 0x63, 0x06, 0x40, 0x07, 0x73, 0x69, 0x73, 0x00,
- 0x00, 0x00, 0xe6, 0x63, 0x00, 0x65, 0x28, 0x6e, 0x31, 0x72, 0x3d, 0x73,
- 0x4d, 0x74, 0x53, 0xe3, 0x65, 0x00, 0x69, 0x10, 0x79, 0x1f, 0xe3, 0x00,
- 0x00, 0x70, 0x02, 0x72, 0x07, 0x00, 0xa5, 0x40, 0x06, 0x61, 0x6e, 0x00,
- 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0x40, 0x07, 0x72, 0x6b, 0x72,
- 0x61, 0x75, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x02, 0x00, 0x47, 0x40,
- 0x55, 0x65, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x61,
- 0x6e, 0x00, 0x40, 0x06, 0x70, 0x6f, 0x64, 0x00, 0x40, 0x09, 0x61, 0x67,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x00, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe5,
- 0x61, 0x00, 0x65, 0x26, 0x69, 0x33, 0x6f, 0x48, 0x76, 0x67, 0xe2, 0x67,
- 0x00, 0x6e, 0x16, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72,
- 0x08, 0x03, 0x1a, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09, 0x61, 0x00, 0x00, 0x06,
- 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x04, 0x7c, 0x00, 0x37, 0x00,
- 0x07, 0xe2, 0x6e, 0x00, 0x6f, 0x0c, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x69,
- 0x00, 0x72, 0x04, 0x79, 0x16, 0x40, 0x00, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x79, 0x09, 0x00, 0x47, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x03, 0x0e, 0x00, 0x09, 0x44, 0x7d, 0x79, 0x00, 0xe7, 0x00, 0x00,
- 0x62, 0x02, 0x64, 0x12, 0x66, 0x18, 0x68, 0x1d, 0x6d, 0x24, 0x79, 0x2a,
- 0x00, 0x93, 0xe2, 0x6f, 0x00, 0x75, 0x06, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x00, 0x40, 0x09, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x75, 0x73, 0x74, 0x00,
- 0x40, 0x06, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x73, 0x65, 0x00,
- 0x40, 0x09, 0x69, 0x6c, 0x6c, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x6f, 0x0a, 0x00, 0x09, 0x40, 0x06, 0x66, 0x72,
- 0x61, 0x67, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x73, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x69, 0x06, 0x04,
- 0x7e, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x6a, 0x63, 0x74, 0x00, 0xf9, 0x61, 0x00, 0x00, 0x65, 0xbe, 0x02, 0x68,
- 0x18, 0x03, 0x69, 0x8f, 0x05, 0x6c, 0x10, 0x06, 0x6f, 0x30, 0x06, 0x72,
- 0x5e, 0x07, 0x75, 0xc6, 0x0a, 0x79, 0xd2, 0x0b, 0xfb, 0x62, 0x00, 0x00,
- 0x64, 0x39, 0x00, 0x66, 0x3b, 0x00, 0x67, 0x53, 0x00, 0x6c, 0x5f, 0x00,
- 0x6d, 0xbc, 0x00, 0x6e, 0xe7, 0x00, 0x70, 0x65, 0x01, 0x72, 0x90, 0x01,
- 0x74, 0x2e, 0x02, 0x76, 0x87, 0x02, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x69,
- 0x25, 0x72, 0x2a, 0x00, 0x09, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x09,
- 0x79, 0x18, 0x40, 0x09, 0x72, 0x64, 0x00, 0x40, 0x00, 0x64, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0x96, 0x40, 0x07, 0x65, 0x73, 0x00, 0x40, 0x00, 0x6f,
- 0x75, 0x73, 0x00, 0x00, 0x09, 0xe1, 0x66, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x25,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08,
- 0x40, 0x00, 0x65, 0x64, 0x00, 0xe7, 0x61, 0x00, 0x64, 0x0c, 0x65, 0x0e,
- 0x69, 0x27, 0x6c, 0x2e, 0x70, 0x3c, 0x79, 0x4c, 0xe2, 0x72, 0x00, 0x77,
- 0x02, 0x00, 0x08, 0x40, 0x09, 0x61, 0x67, 0x00, 0x00, 0x47, 0xe4, 0x00,
- 0x00, 0x27, 0x02, 0x6c, 0x06, 0x6e, 0x0c, 0x01, 0x98, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40,
- 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x95, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xe7, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x07,
- 0x00, 0xf4, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x70, 0x15, 0x00, 0x09, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00,
- 0x08, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x01, 0x71, 0x40, 0xec, 0x72, 0x00, 0x00, 0x07, 0xe5, 0x00, 0x00,
- 0x64, 0x02, 0x6e, 0x2c, 0x73, 0x3f, 0x74, 0x45, 0x00, 0x09, 0xe2, 0x61,
- 0x00, 0x69, 0x20, 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6d,
- 0x07, 0x6f, 0x0f, 0x00, 0x06, 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x40, 0x06,
- 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40,
- 0x07, 0x75, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x6c, 0x15, 0x6e, 0x19, 0x79, 0x1f, 0x04, 0x7f, 0x40, 0x00, 0x72, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x02, 0x62, 0xe2, 0x65, 0x00, 0x75, 0x13, 0xe1, 0x67, 0x00, 0xe2,
- 0x6f, 0x00, 0x72, 0x05, 0x40, 0x93, 0x61, 0x74, 0x00, 0x40, 0x09, 0x61,
- 0x63, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x72, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0xeb, 0x00,
- 0x00, 0x61, 0x02, 0x63, 0x06, 0x65, 0x1d, 0x66, 0x34, 0x69, 0x36, 0x6c,
- 0x57, 0x70, 0x67, 0x72, 0x72, 0x76, 0x80, 0x79, 0x85, 0x00, 0x59, 0x40,
- 0x06, 0x62, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x74,
- 0x79, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6d, 0x08, 0x00, 0x09, 0x40,
- 0x09, 0x72, 0x6f, 0x77, 0x00, 0x41, 0x25, 0x6f, 0x6e, 0x67, 0x65, 0x72,
- 0x00, 0x00, 0x47, 0xe3, 0x66, 0x00, 0x6c, 0x10, 0x6e, 0x14, 0xe2, 0x69,
- 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x03, 0xeb, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6e, 0x61, 0x00,
- 0x40, 0x07, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x41,
- 0x20, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0xf4,
- 0xe4, 0x00, 0x00, 0x68, 0x02, 0x6f, 0x08, 0x74, 0x1e, 0x00, 0x09, 0x40,
- 0x3b, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x00, 0x63, 0x61, 0x6c,
- 0x00, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x24, 0x79, 0x29, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x69, 0x09,
- 0x73, 0x0e, 0x01, 0xfc, 0x40, 0xb1, 0x72, 0x61, 0x69, 0x6e, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x68, 0x6f, 0x74, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f,
- 0x00, 0x07, 0xe2, 0x6e, 0x00, 0x70, 0x4f, 0xe4, 0x61, 0x00, 0x65, 0x11,
- 0x69, 0x1c, 0x74, 0x2c, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x0b, 0x01, 0x07, 0x40,
- 0x37, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0xfa, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x65, 0x0e, 0x00, 0x69, 0x68, 0x00, 0x6c, 0xb2, 0x00,
- 0x6d, 0xdc, 0x00, 0x6e, 0x0c, 0x01, 0x6f, 0x3f, 0x01, 0x75, 0x3f, 0x02,
- 0x77, 0x54, 0x02, 0x00, 0x00, 0x40, 0x00, 0x64, 0x65, 0x6e, 0x66, 0x72,
- 0x65, 0x75, 0x64, 0x65, 0x00, 0xe3, 0x64, 0x00, 0x6d, 0x1c, 0x72, 0x4e,
- 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00,
- 0x27, 0x02, 0x64, 0x06, 0x72, 0x08, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00,
- 0x00, 0x37, 0x00, 0x08, 0xe2, 0x61, 0x00, 0x65, 0x24, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe2,
- 0x63, 0x00, 0x7a, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x09, 0x7a, 0x6f, 0x00, 0xe3,
- 0x6c, 0x00, 0x73, 0x07, 0x7a, 0x1b, 0x40, 0x09, 0x6c, 0x69, 0x6e, 0x67,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x06, 0x40, 0x06, 0x74, 0x69, 0x63, 0x00, 0x00, 0x07, 0xe1, 0x6f, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x70, 0x06, 0x00, 0x06, 0x40, 0x09, 0x64,
- 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0xe2, 0x65, 0x00, 0x6f, 0x20, 0xe2, 0x6d, 0x00, 0x70, 0x06, 0x40,
- 0x06, 0x69, 0x65, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x06,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x63, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x12,
- 0x75, 0x24, 0xe1, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x7a, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x60, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6f, 0x06, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x41, 0x4b, 0x7a,
- 0x65, 0x00, 0x40, 0x09, 0x63, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x10,
- 0x6f, 0x17, 0xe2, 0x70, 0x00, 0x75, 0x05, 0x40, 0x07, 0x70, 0x73, 0x00,
- 0x40, 0x06, 0x7a, 0x65, 0x72, 0x00, 0x40, 0x06, 0x74, 0x7a, 0x65, 0x6c,
- 0x00, 0xe2, 0x6f, 0x00, 0x7a, 0x04, 0x40, 0x09, 0x6b, 0x00, 0xe2, 0x00,
- 0x00, 0x7a, 0x02, 0x00, 0x09, 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe2, 0x6c,
- 0x00, 0x6f, 0x32, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x0d, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x86, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x08, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00,
- 0x40, 0x00, 0x73, 0x6d, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0xbf, 0xef, 0x00,
- 0x00, 0x62, 0x02, 0x63, 0x16, 0x64, 0x2e, 0x65, 0x34, 0x66, 0x38, 0x67,
- 0x40, 0x68, 0x46, 0x69, 0x4d, 0x6b, 0x52, 0x6d, 0x57, 0x72, 0x85, 0x74,
- 0x8b, 0x77, 0x94, 0x79, 0x9a, 0x00, 0x93, 0xe2, 0x61, 0x00, 0x6f, 0x04,
- 0x40, 0x09, 0x67, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x04, 0x40, 0x06, 0x6b,
- 0x00, 0x00, 0x09, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x65, 0x6e, 0x00, 0x40, 0x00, 0x61, 0x79, 0x73, 0x00, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x06, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x00, 0x40, 0x06, 0x69,
- 0x72, 0x6c, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x08, 0x69, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x20, 0xe3, 0x72, 0x00, 0x73, 0x0f, 0x74, 0x15, 0xe1, 0x6d, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x73, 0x68, 0x00, 0x40,
- 0x09, 0x74, 0x65, 0x72, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x73,
- 0x74, 0x72, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6d, 0x00,
- 0x40, 0x09, 0x65, 0x61, 0x63, 0x68, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6f,
- 0x72, 0x6b, 0x00, 0x40, 0x06, 0x61, 0x72, 0x64, 0x00, 0x40, 0x06, 0x65,
- 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x62,
- 0x02, 0x00, 0x59, 0x40, 0x09, 0x6f, 0x6f, 0x6d, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x61, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65, 0x14, 0x6d, 0x3f,
- 0x6e, 0x46, 0x6f, 0x68, 0x73, 0x6c, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x43, 0x72,
- 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x66, 0x00, 0x73, 0x13, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x37, 0x40,
- 0x37, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x74, 0x00, 0x40, 0x06, 0x69,
- 0x74, 0x61, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x0b, 0x73, 0x6f, 0x72, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x0d, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xf9, 0x66, 0x00, 0x00,
- 0x6c, 0x15, 0x00, 0x6e, 0x2d, 0x00, 0x6f, 0x38, 0x00, 0x70, 0x54, 0x00,
- 0x72, 0x58, 0x00, 0x74, 0xc5, 0x00, 0x75, 0xd4, 0x00, 0x77, 0x09, 0x01,
- 0xe1, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x00, 0xe7,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x61, 0x77, 0x00, 0xe2, 0x64, 0x00,
- 0x69, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x6d, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x6f, 0x73, 0x69, 0x73, 0x00, 0xe2, 0x63, 0x00,
- 0x65, 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x09, 0xe2, 0x70, 0x00, 0x74,
- 0x0c, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x47, 0x40, 0x09, 0x75, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x82, 0x65, 0x00, 0xe5, 0x62, 0x00, 0x63, 0x07, 0x65, 0x15, 0x6e,
- 0x4a, 0x70, 0x5c, 0x40, 0x00, 0x75, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00,
- 0xe6, 0x00, 0x00, 0x62, 0x02, 0x63, 0x09, 0x6b, 0x0f, 0x6c, 0x17, 0x72,
- 0x26, 0x00, 0xa5, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x09,
- 0x61, 0x72, 0x64, 0x00, 0x40, 0x09, 0x65, 0x65, 0x70, 0x65, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x73, 0x73, 0x00, 0x40, 0x08,
- 0x6e, 0x65, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x66, 0x06,
- 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0x40,
- 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x47, 0x00, 0x00, 0xe3, 0x6e, 0x00, 0x72,
- 0x07, 0x74, 0x18, 0x40, 0x09, 0x64, 0x72, 0x65, 0x6c, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x67, 0x06, 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x5e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x07, 0x00, 0xe7,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x61, 0x73, 0x74, 0x65, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x00, 0x47, 0xf5, 0x61,
- 0x00, 0x00, 0x65, 0xf5, 0x00, 0x69, 0x9f, 0x01, 0x6f, 0x19, 0x02, 0x75,
- 0x7a, 0x02, 0xe6, 0x62, 0x00, 0x67, 0x12, 0x6d, 0x24, 0x70, 0x50, 0x74,
- 0x97, 0x77, 0xcc, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x67, 0x02, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x79, 0x04, 0x40, 0xf3, 0x79,
- 0x00, 0x00, 0x60, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6d, 0x17, 0x00, 0x08,
- 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x72,
- 0x06, 0x01, 0x34, 0x40, 0x00, 0x73, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe7,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x68, 0x11, 0x69, 0x17, 0x70, 0x1b,
- 0x79, 0x32, 0x03, 0xc5, 0x40, 0x06, 0x6f, 0x6f, 0x6b, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x06, 0x65, 0x61, 0x70,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x00, 0x60, 0x40, 0x06, 0x61, 0x72, 0x64, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x68, 0x00, 0xe6, 0x00, 0x00, 0x63, 0x02, 0x65, 0x08, 0x69,
- 0x0c, 0x70, 0x1b, 0x79, 0x20, 0x00, 0x59, 0x40, 0x08, 0x61, 0x72, 0x64,
- 0x00, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08, 0x61, 0x64,
- 0x00, 0x01, 0x0c, 0xe2, 0x6c, 0x00, 0x6e, 0x09, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x2c, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe3, 0x61, 0x00, 0x65, 0x15,
- 0x77, 0x71, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe4,
- 0x00, 0x00, 0x63, 0x02, 0x64, 0x0e, 0x6e, 0x10, 0x00, 0xb2, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0x60, 0x00, 0x08,
- 0xe5, 0x00, 0x00, 0x69, 0x02, 0x70, 0x07, 0x73, 0x0d, 0x77, 0x21, 0x04,
- 0x80, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6c, 0x61, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x68, 0x06, 0x40, 0x00, 0x76, 0x65, 0x72, 0x00, 0x60,
- 0x09, 0x6f, 0x74, 0x00, 0x08, 0x00, 0xff, 0xff, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe7, 0x00, 0x00, 0x27, 0x02,
- 0x62, 0x06, 0x64, 0x0c, 0x69, 0x14, 0x77, 0x1b, 0x79, 0x21, 0x00, 0xf1,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x61, 0x6c, 0x6c, 0x00, 0x40, 0x09,
- 0x72, 0x69, 0x76, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x6f, 0x72, 0x6d, 0x00, 0x01, 0x0c, 0xe4, 0x62, 0x00,
- 0x6d, 0x25, 0x70, 0x3e, 0x76, 0x6a, 0xe3, 0x61, 0x00, 0x62, 0x04, 0x65,
- 0x13, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x27,
- 0x02, 0x04, 0x81, 0x40, 0x00, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x6d, 0x02,
- 0x70, 0x08, 0x73, 0x0a, 0x00, 0x09, 0x40, 0x82, 0x61, 0x67, 0x65, 0x00,
- 0x00, 0x7a, 0x40, 0x55, 0x68, 0x61, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x75, 0x06, 0x77, 0x14,
- 0x04, 0x82, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x09, 0x40, 0x06, 0x72, 0x69,
- 0x74, 0x65, 0x72, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x65, 0x72, 0x00, 0xe7,
- 0x64, 0x00, 0x66, 0x02, 0x67, 0x14, 0x6c, 0x16, 0x6f, 0x25, 0x74, 0x2a,
- 0x75, 0x3c, 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x08,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x95, 0x40, 0x08,
- 0x61, 0x72, 0x00, 0x40, 0x09, 0x67, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x75,
- 0x09, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x6d, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x00, 0x60,
- 0xe6, 0x62, 0x00, 0x66, 0x1e, 0x6d, 0x3b, 0x6e, 0x7f, 0x70, 0x8e, 0x74,
- 0xb8, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x79, 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0xe1, 0x66, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15,
- 0xe4, 0x00, 0x00, 0x68, 0x02, 0x6d, 0x14, 0x70, 0x29, 0x00, 0x08, 0xe1,
- 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x05, 0x69, 0x09,
- 0x40, 0x08, 0x67, 0x65, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe3, 0x00, 0x00, 0x74, 0x02, 0x79, 0x09, 0x00, 0x5b, 0x40,
- 0x3b, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x47, 0x00, 0x06, 0xe2,
- 0x6c, 0x00, 0x75, 0x04, 0x40, 0x82, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6f, 0x00, 0xe2, 0x73, 0x00, 0x75, 0x06, 0x40, 0x07, 0x69, 0x74, 0x79,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0xb1, 0x40,
- 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x05, 0x79, 0x0a, 0x40, 0x08, 0x65, 0x72, 0x00, 0x40,
- 0x0b, 0x7a, 0x65, 0x00, 0x00, 0x07, 0xe9, 0x62, 0x00, 0x64, 0x04, 0x66,
- 0x19, 0x6c, 0x27, 0x6d, 0x6c, 0x70, 0x8c, 0x72, 0x92, 0x74, 0xd5, 0x7a,
- 0xf4, 0x40, 0x47, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x47,
- 0x40, 0x82, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x70, 0x1a, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x0e, 0x00, 0xe7, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe4, 0x00, 0x00, 0x6f, 0x02, 0x72, 0x06, 0x75, 0x0c, 0x00,
- 0x5b, 0x40, 0x06, 0x72, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00,
- 0x5e, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6d, 0x07, 0x00, 0x09, 0x40, 0x09,
- 0x61, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x60, 0x40, 0x55, 0x70,
- 0x65, 0x72, 0x00, 0xe3, 0x66, 0x00, 0x72, 0x09, 0x76, 0x30, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x20,
- 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xa1, 0xe2, 0x69,
- 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x04, 0x83, 0xe2, 0x63,
- 0x00, 0x74, 0x07, 0x40, 0x06, 0x68, 0x65, 0x6f, 0x6e, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x82, 0x40,
- 0x07, 0x75, 0x74, 0x74, 0x00, 0x40, 0x60, 0x7a, 0x79, 0x00, 0x40, 0x5e,
- 0x74, 0x68, 0x65, 0x00, 0xc0, 0x61, 0x18, 0x33, 0x00, 0x26, 0x02, 0x41,
- 0x02, 0xd6, 0x03, 0x8a, 0x04, 0x00, 0x00, 0x3e, 0x05, 0x00, 0x00, 0xa6,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x31, 0x07, 0x57, 0x09, 0x00,
- 0x00, 0x5d, 0x0b, 0x17, 0x0c, 0x7e, 0x0c, 0x96, 0x0e, 0xb7, 0x0e, 0x00,
- 0x00, 0x2c, 0x0f, 0xa3, 0x0f, 0xcb, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x62,
- 0x02, 0x00, 0x63, 0x21, 0x00, 0x66, 0x28, 0x00, 0x67, 0x53, 0x00, 0x68,
- 0x63, 0x00, 0x6c, 0x6a, 0x00, 0x6d, 0x8a, 0x00, 0x6e, 0xbf, 0x00, 0x70,
- 0xc4, 0x00, 0x72, 0xd4, 0x00, 0x73, 0x08, 0x01, 0x74, 0x73, 0x01, 0x77,
- 0x8d, 0x01, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x09, 0x40,
- 0x06, 0x64, 0x00, 0x40, 0x09, 0x72, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x72,
- 0x05, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x65, 0x00, 0x40,
- 0x06, 0x6f, 0x61, 0x73, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x6c, 0x11, 0x6f,
- 0x17, 0x72, 0x1c, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x6f,
- 0x72, 0x00, 0x40, 0x07, 0x6f, 0x64, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x74,
- 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x06, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x6c, 0x6c, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x73, 0x65, 0x00,
- 0xe5, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x0b, 0x73, 0x0f, 0x04,
- 0x84, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x6e, 0x74, 0x00, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x07, 0x6b, 0x69, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x6c, 0x12, 0x6f, 0x18, 0x73, 0x1e, 0x79, 0x26, 0x04, 0x23, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68,
- 0x69, 0x70, 0x00, 0x40, 0x3b, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x75,
- 0x6e, 0x74, 0x00, 0x40, 0x09, 0x74, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0xf3, 0x40, 0x06, 0x63, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x06, 0x40,
- 0x06, 0x61, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x72, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x63, 0x02, 0x69, 0x28, 0x00, 0x59, 0xe1, 0x68, 0x00, 0xe5, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x6c, 0x11, 0x04, 0x85, 0x40,
- 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x75, 0x72, 0x00, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0xe4, 0x63, 0x00, 0x68, 0x06, 0x69, 0x15, 0x6f, 0x2e, 0x40,
- 0x06, 0x61, 0x70, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x06,
- 0x6c, 0x6c, 0x00, 0x40, 0x06, 0x72, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x64,
- 0x10, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x1f, 0x69, 0x23, 0x04, 0x86, 0xe2,
- 0x62, 0x00, 0x6c, 0x0c, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x37, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40,
- 0x00, 0x74, 0x79, 0x00, 0x40, 0x37, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x69, 0x06, 0x6d, 0x0b, 0x01, 0x34,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x61,
- 0x74, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x18, 0x6f, 0x1d, 0xe4, 0x6c,
- 0x00, 0x72, 0x04, 0x74, 0x08, 0x79, 0x0d, 0x40, 0x09, 0x6c, 0x00, 0x40,
- 0x09, 0x64, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x00, 0x06, 0x40, 0x09,
- 0x65, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x5d, 0xe3, 0x61, 0x00, 0x6f, 0x08, 0x75, 0x10, 0x40, 0x00, 0x63,
- 0x65, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x07, 0x72, 0x72, 0x68, 0x65, 0x61,
- 0x00, 0x40, 0x00, 0x6d, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x27, 0x02, 0x00,
- 0x61, 0x06, 0x00, 0x65, 0x16, 0x00, 0x6c, 0x37, 0x00, 0x6f, 0x53, 0x00,
- 0x72, 0x85, 0x00, 0x74, 0xdf, 0x00, 0x75, 0x33, 0x01, 0x79, 0x74, 0x01,
- 0x00, 0x06, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x06, 0x74, 0x00, 0x40, 0x00, 0x65, 0x75, 0x72, 0x73, 0x00, 0xe2, 0x64,
- 0x00, 0x73, 0x04, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x64,
- 0x00, 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11,
- 0x68, 0x15, 0x6d, 0x1b, 0x04, 0x87, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x00, 0x06, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x00, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x08, 0x65, 0x6e, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x23, 0x69, 0x25, 0x6f, 0x3e,
- 0x04, 0x88, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0c, 0xe1, 0x61,
- 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x09, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x06, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x04,
- 0x89, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x69, 0x1e, 0x6f, 0x47, 0x01, 0x89, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x00, 0x06, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11, 0x69,
- 0x15, 0x04, 0x8a, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x07, 0x73, 0x6d, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x90, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x29,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x03, 0xef, 0x00, 0x37, 0x41, 0xa7, 0x74, 0x79, 0x00,
- 0x00, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x26, 0x67, 0x2e, 0x69, 0x37, 0x75,
- 0x6c, 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69,
- 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x8b, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x1f, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x09, 0xe2, 0x72, 0x00, 0x74, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73,
- 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x32, 0xe2, 0x65, 0x00, 0x74, 0x09, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe2, 0x69, 0x00, 0x72,
- 0x19, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x6f, 0x75,
- 0x73, 0x00, 0xea, 0x00, 0x00, 0x64, 0x02, 0x69, 0x4c, 0x6b, 0x51, 0x6d,
- 0x5c, 0x6e, 0x78, 0x70, 0x7a, 0x72, 0x86, 0x73, 0x95, 0x74, 0x9a, 0x00,
- 0x94, 0xe9, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06, 0x63, 0x0b, 0x65, 0x11,
- 0x69, 0x1a, 0x6c, 0x21, 0x70, 0x30, 0x79, 0x35, 0x00, 0x4b, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x09, 0x65, 0x64, 0x00, 0x40, 0x09, 0x61, 0x73, 0x65,
- 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x06, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f, 0x64,
- 0x00, 0x01, 0x15, 0x40, 0x08, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xe5, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6c, 0x07, 0x00, 0x0b, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x07, 0x40, 0xdb, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x02, 0x76, 0x00,
- 0x37, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x0b, 0x40, 0x07, 0x67, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x75, 0x63,
- 0x6b, 0x65, 0x72, 0x00, 0x40, 0x2c, 0x61, 0x77, 0x00, 0x40, 0x3a, 0x68,
- 0x65, 0x00, 0xe4, 0x66, 0x00, 0x6d, 0x07, 0x72, 0x24, 0x75, 0x50, 0x40,
- 0x08, 0x61, 0x75, 0x6c, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x00, 0x95,
- 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x02, 0x97, 0x00,
- 0x37, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x01, 0x52, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x82, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x67,
- 0x00, 0x6e, 0x12, 0x73, 0x1e, 0x7a, 0x81, 0xe1, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x05, 0x40, 0x06, 0x75, 0x72, 0x00, 0x40, 0x06, 0x6f, 0x72,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00,
- 0x07, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x10, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xe2, 0x67, 0x00, 0x6c, 0x25, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x73, 0x0a, 0x79, 0x0c, 0x00, 0x27, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09,
- 0x74, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x75, 0x02, 0x00, 0x0b, 0x40,
- 0x09, 0x72, 0x65, 0x00, 0xe6, 0x64, 0x00, 0x65, 0x05, 0x66, 0x74, 0x6c,
- 0xb2, 0x74, 0xd4, 0x76, 0xda, 0x40, 0x00, 0x6f, 0x6d, 0x00, 0xe2, 0x63,
- 0x00, 0x6e, 0x46, 0xe2, 0x63, 0x00, 0x74, 0x08, 0x40, 0x00, 0x69, 0x6f,
- 0x6e, 0x61, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6d, 0x17, 0x6e,
- 0x24, 0x6f, 0x2a, 0x04, 0x8c, 0xe2, 0x6f, 0x00, 0x76, 0x04, 0x40, 0x06,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x75, 0x6d, 0x00, 0xe1,
- 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x09, 0x72, 0x00, 0x00,
- 0x07, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x19, 0x73, 0x2f, 0x00, 0x07,
- 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x06, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0xe7, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x61,
- 0x6d, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x06, 0x04, 0x8d,
- 0x40, 0x07, 0x72, 0x00, 0xe3, 0x66, 0x00, 0x74, 0x04, 0x75, 0x0a, 0x40,
- 0x09, 0x66, 0x00, 0x40, 0x3a, 0x61, 0x70, 0x65, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x40, 0x09, 0x7a, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05,
- 0x40, 0x09, 0x67, 0x65, 0x00, 0x40, 0x00, 0x73, 0x00, 0xf6, 0x61, 0x00,
- 0x00, 0x62, 0x2d, 0x00, 0x65, 0x35, 0x00, 0x69, 0x42, 0x00, 0x6f, 0x03,
- 0x02, 0x70, 0x0a, 0x02, 0xe2, 0x6e, 0x00, 0x70, 0x21, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x08, 0x73, 0x0d, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0x00, 0x07, 0x40, 0x5e, 0x68, 0x6f, 0x72, 0x65,
- 0x00, 0x40, 0x65, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x6e, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0xc1, 0x61,
- 0x19, 0x37, 0x00, 0x39, 0x00, 0x56, 0x00, 0x5d, 0x00, 0xa5, 0x00, 0x00,
- 0x00, 0xbc, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xdb, 0x00, 0xe4, 0x00, 0xfe, 0x00, 0x1b, 0x01, 0x52,
- 0x01, 0x5a, 0x01, 0x63, 0x01, 0x7e, 0x01, 0x00, 0x00, 0xaa, 0x01, 0xb1,
- 0x01, 0x00, 0x00, 0xb9, 0x01, 0x00, 0x09, 0xe3, 0x6e, 0x00, 0x72, 0x07,
- 0x75, 0x0c, 0x40, 0x3b, 0x6e, 0x75, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x69,
- 0x64, 0x00, 0x40, 0x09, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x00,
- 0x40, 0x08, 0x72, 0x65, 0x76, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x15,
- 0xe1, 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x05, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x73, 0x17,
- 0xe1, 0x75, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x05, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x00, 0x63, 0x69, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x09,
- 0x40, 0x07, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x74,
- 0x61, 0x63, 0x68, 0x65, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x09, 0x73, 0x74, 0x00, 0x40, 0x08, 0x6c, 0x6f, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x74, 0x68, 0x6c, 0x79, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x07, 0x00, 0x09, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00, 0x06,
- 0xe2, 0x66, 0x00, 0x74, 0x09, 0x40, 0x00, 0x66, 0x69, 0x63, 0x69, 0x61,
- 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x08, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x72, 0x0a, 0x40, 0x00,
- 0x72, 0x6d, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x08, 0x6f, 0x0f, 0x40, 0x00, 0x63, 0x69, 0x6f, 0x75, 0x73, 0x00, 0x40,
- 0x00, 0x76, 0x61, 0x74, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00,
- 0x08, 0x40, 0x06, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00,
- 0x40, 0x08, 0x75, 0x61, 0x76, 0x65, 0x72, 0x00, 0x40, 0x00, 0x65, 0x74,
- 0x69, 0x72, 0x65, 0x64, 0x00, 0xe3, 0x6b, 0x00, 0x6f, 0x08, 0x77, 0x0e,
- 0x40, 0x00, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x00, 0x40, 0x00, 0x6c, 0x69,
- 0x64, 0x00, 0x40, 0x00, 0x65, 0x65, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x72,
- 0x05, 0x40, 0x06, 0x6e, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x15, 0xe2,
- 0x69, 0x00, 0x6e, 0x06, 0x40, 0x09, 0x6c, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x70, 0x69,
- 0x63, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x6f, 0x77, 0x65, 0x6c, 0x00, 0x40,
- 0x06, 0x65, 0x65, 0x6b, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x65, 0x61, 0x72,
- 0x6c, 0x79, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x6e, 0x61, 0x00, 0x40, 0x09,
- 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x00, 0xf8, 0x61, 0x00, 0x00, 0x64,
- 0x19, 0x00, 0x65, 0x2b, 0x00, 0x69, 0x42, 0x00, 0x6e, 0x62, 0x00, 0x6f,
- 0x66, 0x00, 0x73, 0x79, 0x00, 0x74, 0x75, 0x01, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x02, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6f, 0x06, 0x00, 0xe5, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09,
- 0x66, 0x66, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07,
- 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x04,
- 0x00, 0x09, 0x00, 0x06, 0x40, 0x06, 0x74, 0x61, 0x00, 0xe5, 0x61, 0x00,
- 0x65, 0x2f, 0x69, 0x4c, 0x6f, 0xb6, 0x75, 0xc2, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x09, 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x82, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x62, 0x00, 0x74, 0x2e, 0xe2, 0x69, 0x00, 0x6c, 0x15, 0xe1, 0x6c,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x53, 0xe2, 0x65, 0x00, 0x79, 0x0d,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x54, 0xe1, 0x69, 0x00, 0xe2, 0x76, 0x00, 0x7a, 0x21, 0xe2,
- 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x12, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x05, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x53, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x41, 0x52, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0x4a, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x17, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x3b, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x07,
- 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x15, 0x72, 0x6b, 0x02, 0x60, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x82, 0x65, 0x00, 0x40, 0x3b, 0x69, 0x6f,
- 0x75, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x6d, 0x0e, 0x6e, 0x4a, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x53, 0x65, 0x00, 0x00, 0x54,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0xe3, 0x73, 0x00, 0x74, 0x09, 0x7a, 0x0d, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b,
- 0x40, 0x09, 0x65, 0x6c, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe5, 0x61, 0x00,
- 0x69, 0x4e, 0x73, 0x52, 0x74, 0x57, 0x75, 0x98, 0xe2, 0x6c, 0x00, 0x72,
- 0x02, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x15, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x54, 0xe3, 0x65, 0x00, 0x69,
- 0x0d, 0x6f, 0x1f, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x8e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x07, 0x61, 0x00, 0x40, 0x07, 0x69, 0x73, 0x00, 0xe4,
- 0x61, 0x00, 0x65, 0x09, 0x69, 0x0d, 0x75, 0x26, 0xe2, 0x00, 0x00, 0x6c,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x74, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x61,
- 0x00, 0x6d, 0x0b, 0x40, 0x09, 0x67, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x61,
- 0x6e, 0x00, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x59, 0x72, 0x00, 0x40, 0x00,
- 0x61, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x3e, 0x6f, 0x54, 0xe3, 0x6c, 0x00, 0x6e, 0x02, 0x73, 0x19,
- 0x00, 0x06, 0xe2, 0x63, 0x00, 0x74, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0xa5, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x43, 0x09, 0x69, 0x61, 0x6c,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x7a, 0x72,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0c,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xb1, 0x40, 0x00, 0x65, 0x64, 0x00,
- 0x40, 0x00, 0x75, 0x72, 0x00, 0x40, 0x09, 0x69, 0x61, 0x00, 0xfb, 0x61,
- 0x00, 0x00, 0x65, 0x21, 0x00, 0x66, 0x60, 0x00, 0x67, 0x6c, 0x00, 0x69,
- 0x7b, 0x00, 0x6d, 0xd5, 0x00, 0x6f, 0xe7, 0x00, 0x70, 0xff, 0x00, 0x72,
- 0x14, 0x01, 0x75, 0x2d, 0x01, 0x76, 0x31, 0x01, 0xe2, 0x67, 0x00, 0x70,
- 0x06, 0x40, 0x09, 0x6c, 0x69, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x02,
- 0x00, 0x06, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x06, 0x00, 0x07, 0x40,
- 0x00, 0x63, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x60,
- 0xe4, 0x61, 0x00, 0x64, 0x05, 0x65, 0x1d, 0x69, 0x2a, 0x40, 0x82, 0x64,
- 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x05, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x5f, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6e, 0x74, 0x00, 0xe6,
- 0x61, 0x00, 0x65, 0x1b, 0x66, 0x1f, 0x67, 0x21, 0x6e, 0x36, 0x6f, 0x3a,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0xe1, 0x7a,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x0b, 0x40, 0x07, 0x73, 0x00, 0x00, 0x09, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0xe3,
- 0x6c, 0x00, 0x74, 0x06, 0x75, 0x0d, 0x40, 0x07, 0x6f, 0x67, 0x79, 0x00,
- 0x40, 0x00, 0x6f, 0x6e, 0x69, 0x6e, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x04, 0x8f, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00, 0x40, 0x09, 0x6d,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x05, 0x69, 0x1b, 0x6f, 0xa0, 0x40, 0x09,
- 0x6e, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x72, 0x06, 0x04, 0x91,
- 0x44, 0x90, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00,
- 0x08, 0xe5, 0x63, 0x00, 0x65, 0x4c, 0x6c, 0x52, 0x6e, 0x5e, 0x74, 0x6c,
- 0xe2, 0x65, 0x00, 0x69, 0x42, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x64, 0x15,
- 0x6d, 0x17, 0x77, 0x24, 0x00, 0xd2, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x65,
- 0x00, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x74, 0x74, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x27, 0x00, 0x73, 0x04, 0x40, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0xe2, 0x6f, 0x00, 0x75, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x64,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x6f, 0x0a, 0x40, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x00,
- 0x40, 0x09, 0x74, 0x6f, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x71, 0x05, 0x73,
- 0x14, 0x40, 0x06, 0x6d, 0x65, 0x00, 0x40, 0x09, 0x75, 0x69, 0x63, 0x65,
- 0x6e, 0x74, 0x65, 0x6e, 0x6e, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x69,
- 0x6f, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x73, 0x13,
- 0x74, 0x25, 0x75, 0x64, 0x04, 0x92, 0x40, 0x09, 0x61, 0x63, 0x6b, 0x00,
- 0x40, 0x09, 0x6d, 0x79, 0x6b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0xe2,
- 0x63, 0x00, 0x71, 0x06, 0x40, 0x06, 0x72, 0x65, 0x77, 0x00, 0x40, 0x08,
- 0x75, 0x61, 0x72, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0b,
- 0x6c, 0x10, 0x04, 0x93, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00, 0x09, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00,
- 0x27, 0x02, 0x6d, 0x06, 0x72, 0x18, 0x03, 0x8e, 0x40, 0x00, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x75, 0x00, 0x00, 0x00, 0x06, 0x40, 0x09, 0x70, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x46, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x01, 0x29, 0xe4, 0x65, 0x00, 0x68, 0x19, 0x69, 0x22, 0x79, 0x34,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x01,
- 0x58, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0x01, 0x58, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x0e, 0x69, 0x1b, 0x04, 0x94, 0xe2, 0x6c, 0x00, 0x6e, 0x02, 0x00, 0x12,
- 0x40, 0x06, 0x63, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x95,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x69, 0x16, 0x6e, 0x1b, 0x01, 0x40,
- 0x40, 0x07, 0x67, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x09, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x00, 0x77, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x69, 0x0d, 0x6c, 0x27,
- 0x6f, 0x2d, 0x70, 0x42, 0x74, 0x47, 0x75, 0x6b, 0x79, 0x7d, 0x00, 0x59,
- 0x40, 0x06, 0x67, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x00, 0xe3,
- 0x6c, 0x00, 0x6e, 0x04, 0x73, 0x0a, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x09, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73,
- 0x74, 0x00, 0x00, 0x07, 0x40, 0x09, 0x6f, 0x74, 0x00, 0xe5, 0x61, 0x00,
- 0x65, 0x05, 0x69, 0x09, 0x6f, 0x0e, 0x75, 0x12, 0x40, 0x06, 0x6e, 0x74,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x6e, 0x00, 0x40, 0x06, 0x70, 0x6c, 0x65, 0x74, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0x00, 0x96, 0x00, 0x00, 0x40, 0x00, 0x6d, 0x6c, 0x00,
- 0xfb, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x3d, 0x03, 0x68, 0xe3,
- 0x04, 0x69, 0xe5, 0x04, 0x6f, 0x4c, 0x07, 0x70, 0xda, 0x0a, 0x72, 0xde,
- 0x0a, 0x74, 0xc0, 0x0b, 0x75, 0xc6, 0x0b, 0x79, 0x6d, 0x0c, 0x00, 0x00,
- 0xc0, 0x62, 0x18, 0x33, 0x00, 0x4c, 0x00, 0x64, 0x00, 0x00, 0x00, 0x9d,
- 0x00, 0xa1, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x07,
- 0x01, 0x33, 0x01, 0xd7, 0x01, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x40,
- 0x02, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x1e, 0x03, 0x35, 0x03, 0x00,
- 0x00, 0x39, 0x03, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x96, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x47, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01, 0x34,
- 0x40, 0x00, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x6f,
- 0x19, 0x79, 0x2c, 0x04, 0x78, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73,
- 0x73, 0x00, 0x00, 0x07, 0xe1, 0x77, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02,
- 0x79, 0x07, 0x00, 0x93, 0x40, 0x0b, 0x6f, 0x78, 0x00, 0x00, 0xf3, 0x01,
- 0x15, 0x40, 0x47, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x13, 0x40, 0x00, 0x64, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0x01, 0x92, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x22, 0x79, 0x31, 0xe6, 0x00, 0x00, 0x64,
- 0x02, 0x6e, 0x08, 0x6f, 0x0a, 0x72, 0x0f, 0x75, 0x11, 0x02, 0x04, 0x40,
- 0x06, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x37, 0x40, 0x09, 0x75, 0x74, 0x00,
- 0x00, 0x07, 0x40, 0x09, 0x70, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe4,
- 0x65, 0x00, 0x6c, 0x02, 0x6f, 0x1d, 0x74, 0x21, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x6f, 0x02, 0x00, 0x00, 0xe2, 0x74, 0x00, 0x77, 0x02, 0x00, 0x09,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x96, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x6d, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02,
- 0x62, 0x1f, 0x65, 0x36, 0x6d, 0x70, 0x70, 0x7e, 0x72, 0x8f, 0x00, 0x59,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x63,
- 0x00, 0x73, 0x02, 0x00, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x69, 0x63, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x0c, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x82, 0x00, 0x07, 0x40, 0x00,
- 0x6c, 0x69, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x1d, 0x00,
- 0x09, 0xe2, 0x61, 0x00, 0x75, 0x06, 0x40, 0x3b, 0x63, 0x65, 0x64, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x6f,
- 0x63, 0x6b, 0x00, 0xe5, 0x27, 0x00, 0x64, 0x04, 0x67, 0x08, 0x6b, 0x0e,
- 0x74, 0x10, 0x40, 0x00, 0x74, 0x00, 0x40, 0x08, 0x79, 0x00, 0x40, 0x3a,
- 0x68, 0x61, 0x69, 0x00, 0x00, 0x09, 0xe2, 0x75, 0x00, 0x79, 0x05, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40,
- 0x06, 0x6f, 0x77, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x27,
- 0x02, 0x64, 0x06, 0x6c, 0x08, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x00,
- 0x37, 0xe3, 0x65, 0x00, 0x69, 0x13, 0x79, 0x1a, 0xe1, 0x73, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96,
- 0xe5, 0x64, 0x00, 0x65, 0x02, 0x69, 0x59, 0x6b, 0x65, 0x70, 0x72, 0x00,
- 0x09, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x63, 0x08, 0x68, 0x2b, 0x72, 0x42,
- 0x77, 0x44, 0x00, 0xa5, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02,
- 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x08, 0x6e, 0x67, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x61, 0x72, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x47, 0x40,
- 0x07, 0x6b, 0x69, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x14,
- 0x6e, 0x1f, 0x73, 0x25, 0x04, 0x97, 0xe2, 0x6e, 0x00, 0x72, 0x0b, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x01, 0xf9, 0x40, 0x09, 0x72, 0x00, 0x00, 0x07,
- 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x00, 0x68, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x59, 0x40,
- 0x00, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe3,
- 0x00, 0x00, 0x6e, 0x02, 0x72, 0x04, 0x03, 0x9c, 0x00, 0x37, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x09, 0xfe,
- 0x00, 0x00, 0x00, 0x27, 0x02, 0x00, 0x61, 0x0d, 0x00, 0x62, 0x3e, 0x00,
- 0x64, 0x4d, 0x00, 0x65, 0x5a, 0x00, 0x69, 0xc8, 0x00, 0x6b, 0xe4, 0x00,
- 0x6c, 0xe9, 0x00, 0x6d, 0x36, 0x01, 0x6e, 0x3c, 0x01, 0x70, 0x45, 0x01,
- 0x72, 0x5d, 0x01, 0x77, 0x72, 0x01, 0x00, 0x1a, 0xe2, 0x64, 0x00, 0x6c,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0xe4, 0x66, 0x00, 0x72, 0x02,
- 0x74, 0x0d, 0x76, 0x24, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x04, 0x73, 0x09, 0x04, 0x98, 0x01, 0x34, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x00, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x05, 0x40, 0x09, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x65, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x64, 0x02, 0x00, 0x09, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00,
- 0xe4, 0x6e, 0x00, 0x70, 0x09, 0x72, 0x44, 0x74, 0x51, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0x00, 0x60, 0xe6, 0x00, 0x00, 0x64, 0x02, 0x66,
- 0x07, 0x68, 0x0d, 0x69, 0x15, 0x73, 0x28, 0x00, 0x07, 0x40, 0x09, 0x6f,
- 0x67, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x64, 0x00, 0x40, 0x09, 0x65, 0x72,
- 0x64, 0x65, 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x6b, 0x69, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0x99,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6c,
- 0x07, 0x03, 0x2a, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x6b,
- 0x65, 0x00, 0xe2, 0x6b, 0x00, 0x6c, 0x13, 0xe2, 0x64, 0x00, 0x68, 0x05,
- 0x40, 0x09, 0x6f, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0x40, 0x08, 0x61, 0x00, 0x40, 0x06, 0x65, 0x6c, 0x00, 0xe4,
- 0x66, 0x00, 0x6c, 0x02, 0x74, 0x33, 0x76, 0x38, 0x00, 0x07, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x66, 0x1a, 0x03, 0x9d, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x6b, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x72,
- 0x00, 0x73, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x09, 0x68, 0x00, 0x40,
- 0x59, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x45, 0x50, 0x61, 0x6c, 0x65, 0x00, 0x40, 0x06,
- 0x61, 0x6e, 0x69, 0x67, 0x61, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x2c, 0x40, 0x09, 0x73, 0x73, 0x00, 0xe3, 0x62, 0x00, 0x69, 0x05,
- 0x72, 0x0a, 0x40, 0x06, 0x65, 0x74, 0x00, 0x40, 0x06, 0x66, 0x66, 0x00,
- 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x0b, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x61, 0x00, 0x00, 0x62, 0x06, 0x00, 0x65, 0x21,
- 0x00, 0x66, 0x26, 0x00, 0x69, 0x5b, 0x00, 0x6c, 0x62, 0x00, 0x6d, 0x88,
- 0x00, 0x6e, 0xad, 0x00, 0x70, 0x09, 0x01, 0x72, 0x9f, 0x01, 0x74, 0xfd,
- 0x01, 0x76, 0x2f, 0x02, 0x40, 0x07, 0x74, 0x73, 0x75, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0x40, 0x55, 0x6c, 0x64, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00,
- 0x69, 0x02, 0x6c, 0x11, 0x79, 0x27, 0x00, 0x59, 0xe2, 0x6c, 0x00, 0x6e,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0x40,
- 0x08, 0x74, 0x61, 0x6b, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x17, 0x04, 0x78, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6d,
- 0x02, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x10, 0x79, 0x15, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2c,
- 0x00, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x5e, 0xe9, 0x00, 0x00,
- 0x62, 0x02, 0x64, 0x08, 0x65, 0x0d, 0x67, 0x16, 0x69, 0x25, 0x6e, 0x2c,
- 0x73, 0x3e, 0x79, 0x47, 0x00, 0xc3, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00,
- 0x40, 0x06, 0x69, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09,
- 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x5e, 0x65, 0x00, 0x40,
- 0x07, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x00, 0x3a, 0x40, 0x07, 0x70, 0x6c, 0x69, 0x6e,
- 0x74, 0x73, 0x00, 0x01, 0x3b, 0xea, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06,
- 0x6c, 0x28, 0x6d, 0x2e, 0x6f, 0x47, 0x70, 0x4e, 0x73, 0x61, 0x77, 0x68,
- 0x79, 0x7b, 0x04, 0x9a, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x6f, 0x00, 0x75,
- 0x06, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x61, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x06, 0x74, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x75, 0x00,
- 0x00, 0x40, 0x09, 0x77, 0x6e, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x77, 0x00, 0x06, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x68, 0x61, 0x70, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x59, 0x63, 0x6b, 0x00, 0x40,
- 0x09, 0x67, 0x68, 0x74, 0x00, 0x40, 0x06, 0x61, 0x72, 0x64, 0x00, 0xe4,
- 0x65, 0x00, 0x6b, 0x02, 0x72, 0x0d, 0x74, 0x19, 0x00, 0x09, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x3f, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x04, 0x78, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe8, 0x00, 0x00,
- 0x66, 0x02, 0x69, 0x09, 0x6c, 0x0e, 0x73, 0x14, 0x74, 0x1c, 0x77, 0x22,
- 0x79, 0x29, 0x00, 0x59, 0x40, 0x06, 0x72, 0x6f, 0x6e, 0x74, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x6c, 0x65, 0x65, 0x76, 0x65, 0x00, 0x40, 0x06, 0x61, 0x69, 0x6c, 0x00,
- 0x40, 0x09, 0x61, 0x69, 0x73, 0x74, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00,
- 0x66, 0x02, 0x68, 0x09, 0x6c, 0x0f, 0x74, 0x15, 0x01, 0x69, 0x41, 0x68,
- 0x61, 0x63, 0x65, 0x64, 0x00, 0x41, 0xa2, 0x65, 0x61, 0x64, 0x00, 0x41,
- 0x68, 0x6f, 0x61, 0x64, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09,
- 0x41, 0x68, 0x64, 0x00, 0x41, 0x68, 0x6e, 0x67, 0x00, 0x04, 0x9b, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x01, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x2f, 0x00, 0x00, 0xfd, 0x61, 0x00, 0x00, 0x63, 0x09,
- 0x00, 0x64, 0x27, 0x00, 0x65, 0x44, 0x00, 0x67, 0x85, 0x00, 0x6e, 0x97,
- 0x00, 0x6f, 0x9b, 0x00, 0x70, 0xbf, 0x00, 0x72, 0x3b, 0x01, 0x74, 0x10,
- 0x02, 0x75, 0x32, 0x02, 0x76, 0x5e, 0x02, 0x77, 0x74, 0x02, 0xe2, 0x6c,
- 0x00, 0x74, 0x02, 0x00, 0x59, 0x00, 0x09, 0xe1, 0x6b, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x06, 0x70, 0x0b, 0x00, 0xc3, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x72, 0x6f, 0x6f, 0x66,
- 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x37, 0xe2, 0x69, 0x00, 0x79,
- 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x57, 0xe7, 0x00, 0x00, 0x68, 0x02, 0x69,
- 0x08, 0x6c, 0x0d, 0x6d, 0x13, 0x73, 0x1a, 0x74, 0x2c, 0x00, 0x09, 0x40,
- 0x59, 0x6f, 0x72, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x61, 0x63, 0x65, 0x00, 0x40, 0x06, 0x61, 0x6b, 0x65, 0x72, 0x00, 0xe2,
- 0x68, 0x00, 0x74, 0x06, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x06,
- 0x72, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72, 0x65, 0x65, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x07, 0x74, 0x65, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x6b, 0x02, 0x74, 0x04, 0x00, 0x0b, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x6f, 0x0b, 0x04, 0x9c, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x75, 0x74, 0x00, 0xe8, 0x00, 0x00,
- 0x61, 0x02, 0x66, 0x0a, 0x6b, 0x29, 0x6c, 0x31, 0x70, 0x4c, 0x74, 0x5f,
- 0x77, 0x65, 0x00, 0x09, 0x40, 0x08, 0x68, 0x6f, 0x6c, 0x69, 0x63, 0x00,
- 0xe2, 0x69, 0x00, 0x72, 0x14, 0xe1, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x08, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x08, 0x6f, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x65, 0x65, 0x70,
- 0x65, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x4c, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x61, 0x6c, 0x6b, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x6e,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x15, 0x74, 0x1a, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x6c, 0x08, 0x00, 0x82, 0x40, 0x06, 0x69, 0x72, 0x64, 0x00, 0x40,
- 0x09, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xed, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x07, 0x63, 0x0e, 0x65, 0x36, 0x66, 0x45, 0x68,
- 0x4b, 0x69, 0x5a, 0x6c, 0x5f, 0x6e, 0x65, 0x73, 0x6b, 0x77, 0x91, 0x79,
- 0x97, 0x04, 0x9d, 0x40, 0x09, 0x67, 0x65, 0x00, 0x40, 0x07, 0x72, 0x65,
- 0x61, 0x64, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x05, 0x6f, 0x0c, 0x72, 0x13,
- 0x75, 0x19, 0x40, 0x09, 0x6b, 0x65, 0x00, 0x40, 0x3a, 0x61, 0x6e, 0x67,
- 0x65, 0x00, 0x40, 0x09, 0x6d, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x75,
- 0x73, 0x74, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x04, 0x9e, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x61, 0x6c, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x20, 0x6e,
- 0x64, 0x00, 0x40, 0x09, 0x72, 0x6e, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00,
- 0x40, 0x72, 0x69, 0x73, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x74, 0x1c, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x6f,
- 0x70, 0x00, 0x40, 0x09, 0x61, 0x76, 0x65, 0x00, 0x00, 0x06, 0xe2, 0x00,
- 0x00, 0x67, 0x02, 0x00, 0x09, 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x74,
- 0x1c, 0xe1, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65, 0x07, 0x6e,
- 0x0b, 0x00, 0x00, 0x40, 0x00, 0x76, 0x65, 0x00, 0x40, 0x55, 0x72, 0x00,
- 0x40, 0x00, 0x27, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3,
- 0x40, 0x07, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x82, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x47, 0x40, 0x06, 0x75,
- 0x6c, 0x00, 0xc1, 0x62, 0x18, 0x35, 0x00, 0x37, 0x00, 0x45, 0x00, 0x4b,
- 0x00, 0x51, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x77, 0x00, 0x8c,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0xae, 0x00, 0xb0, 0x00, 0xb5,
- 0x00, 0x00, 0x00, 0xc6, 0x00, 0xcc, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x9f, 0xe2, 0x69, 0x00,
- 0x6f, 0x04, 0x40, 0x07, 0x7a, 0x00, 0x40, 0x55, 0x61, 0x74, 0x00, 0x40,
- 0x82, 0x61, 0x73, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x77, 0x6e, 0x00, 0xe1,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x70, 0x02, 0x79, 0x09, 0x00, 0x2f, 0x40,
- 0x00, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x72,
- 0x05, 0x40, 0x09, 0x72, 0x6c, 0x00, 0x40, 0x08, 0x6f, 0x75, 0x6e, 0x64,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0x40, 0x00,
- 0x75, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x10,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x68, 0x69, 0x70, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x40, 0x06,
- 0x66, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x06, 0x40, 0x06, 0x65, 0x63,
- 0x65, 0x00, 0x40, 0x06, 0x61, 0x63, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6f,
- 0x6d, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x60, 0x09, 0x69, 0x6d, 0x65, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0x01, 0x3b, 0x40, 0x00, 0x74, 0x00, 0xe5, 0x61, 0x00, 0x65,
- 0x0f, 0x69, 0x49, 0x6f, 0x9f, 0x75, 0xa4, 0xe2, 0x6e, 0x00, 0x70, 0x04,
- 0x40, 0x00, 0x6b, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x6c, 0x00, 0xe2, 0x64,
- 0x00, 0x77, 0x1a, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x69, 0x0f,
- 0x00, 0x09, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xe0, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe7, 0x65, 0x00, 0x66,
- 0x04, 0x6b, 0x08, 0x6c, 0x0c, 0x6d, 0x20, 0x6e, 0x24, 0x76, 0x37, 0x40,
- 0x47, 0x6b, 0x00, 0x40, 0x07, 0x74, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1,
- 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x79, 0x08, 0x02, 0x5d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0xe7, 0x70, 0x00, 0xe2,
- 0x65, 0x00, 0x6b, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x04,
- 0xa0, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x6e, 0x04, 0x00, 0x0b, 0x00, 0x5b, 0x00, 0x00, 0x40, 0x59,
- 0x75, 0x64, 0x00, 0xe3, 0x62, 0x00, 0x67, 0x13, 0x6e, 0x28, 0xe2, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x05, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0x00, 0xf3, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x17, 0x6b, 0x00, 0x40, 0x09, 0x69, 0x63, 0x6b, 0x00,
- 0xe6, 0x63, 0x00, 0x64, 0x0c, 0x66, 0x12, 0x6e, 0x2d, 0x73, 0x46, 0x74,
- 0x4a, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x59, 0x00,
- 0x08, 0x40, 0x47, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x72, 0x09, 0x04,
- 0x43, 0x40, 0x06, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x00, 0x06, 0xe3, 0x00,
- 0x00, 0x6e, 0x02, 0x74, 0x10, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x03, 0x24, 0x40,
- 0x3a, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x65, 0x08, 0x6f, 0x0d,
- 0x74, 0x1a, 0x00, 0x08, 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x07,
- 0x79, 0x65, 0x00, 0xe2, 0x66, 0x00, 0x75, 0x04, 0x40, 0x06, 0x66, 0x00,
- 0x40, 0x06, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0f, 0x6c, 0x14, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x2c, 0x40, 0x09, 0x75,
- 0x67, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x63, 0x02, 0x00, 0x5e, 0x40, 0x59, 0x6f, 0x63, 0x6b, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x6e, 0x0d, 0x73, 0x13, 0x04, 0xa1, 0xe2, 0x72,
- 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x06, 0x74, 0x65, 0x72, 0x00, 0xff, 0x62, 0x00,
- 0x00, 0x63, 0x24, 0x00, 0x64, 0x95, 0x00, 0x65, 0x8e, 0x01, 0x66, 0xb0,
- 0x01, 0x67, 0xc3, 0x01, 0x6c, 0xf0, 0x02, 0x6d, 0xd4, 0x03, 0x6e, 0xf7,
- 0x04, 0x70, 0x3f, 0x06, 0x72, 0x60, 0x06, 0x73, 0x8f, 0x06, 0x74, 0xcf,
- 0x06, 0x78, 0x2a, 0x07, 0x7a, 0x8c, 0x07, 0xe3, 0x69, 0x00, 0x6c, 0x07,
- 0x79, 0x0d, 0x40, 0x06, 0x6c, 0x61, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x69,
- 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02,
- 0x6b, 0x10, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x65,
- 0x0f, 0x69, 0x1e, 0x6c, 0x29, 0x6e, 0x32, 0x6f, 0x38, 0x72, 0x43, 0x04,
- 0xa2, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x08, 0x79, 0x00, 0x40, 0x06,
- 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x20,
- 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00,
- 0xf3, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6d, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0xe9, 0x6c, 0xee, 0xed, 0x00, 0x00, 0x27, 0x02,
- 0x61, 0x06, 0x62, 0x0b, 0x63, 0x22, 0x6b, 0x27, 0x6c, 0x2d, 0x6d, 0x45,
- 0x70, 0x52, 0x72, 0x59, 0x73, 0x5f, 0x74, 0xa9, 0x77, 0xb0, 0x00, 0x4b,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x72, 0x6d, 0x00, 0xe3, 0x61, 0x00,
- 0x6f, 0x04, 0x75, 0x0a, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x61, 0x72,
- 0x64, 0x00, 0x40, 0x07, 0x72, 0x6e, 0x73, 0x00, 0x40, 0x06, 0x61, 0x72,
- 0x00, 0x40, 0x06, 0x69, 0x63, 0x6b, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0e,
- 0xe2, 0x67, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x68, 0x74, 0x00, 0x40, 0x5e,
- 0x65, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09, 0x69, 0x65,
- 0x63, 0x65, 0x00, 0x40, 0x00, 0x65, 0x61, 0x6c, 0x00, 0xe5, 0x61, 0x00,
- 0x68, 0x07, 0x70, 0x0c, 0x74, 0x16, 0x77, 0x39, 0x40, 0x09, 0x64, 0x64,
- 0x6c, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x77, 0x00, 0x40, 0x00, 0x6c, 0x69,
- 0x74, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x18, 0xe1,
- 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x5e, 0x6f, 0x6b, 0x65, 0x00, 0x40, 0x5e, 0x69, 0x70, 0x65, 0x00, 0x40,
- 0x2c, 0x72, 0x61, 0x63, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x12, 0xe2,
- 0x6c, 0x00, 0x79, 0x09, 0xe2, 0x6b, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x00,
- 0x09, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x6e, 0x64, 0x65, 0x72, 0x00,
- 0x40, 0x09, 0x6e, 0x67, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe5, 0x67, 0x00,
- 0x6e, 0x04, 0x72, 0x09, 0x73, 0x0e, 0x76, 0x13, 0x40, 0x09, 0x65, 0x00,
- 0x40, 0x07, 0x6e, 0x61, 0x00, 0x40, 0x09, 0x72, 0x61, 0x00, 0x40, 0x09,
- 0x74, 0x61, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x3f, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37,
- 0x00, 0x07, 0xf3, 0x68, 0x00, 0x00, 0x6d, 0x41, 0x00, 0x6e, 0x45, 0x00,
- 0xe3, 0x00, 0x00, 0x73, 0x02, 0x74, 0x04, 0x00, 0xec, 0x00, 0x00, 0xe5,
- 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07, 0x72, 0x13, 0x73, 0x19, 0x04, 0xa3,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x05, 0x40, 0x00,
- 0x73, 0x73, 0x00, 0x01, 0x7c, 0x40, 0x00, 0x65, 0x61, 0x64, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x00, 0x09, 0x40, 0x09, 0x61, 0x00, 0xe9, 0x00, 0x00,
- 0x27, 0x02, 0x61, 0x06, 0x62, 0x55, 0x65, 0x5c, 0x69, 0x69, 0x6f, 0x9f,
- 0x70, 0xc1, 0x75, 0xc7, 0x04, 0xa4, 0x41, 0x63, 0x73, 0x00, 0xe3, 0x67,
- 0x00, 0x6c, 0x04, 0x74, 0x39, 0x40, 0x07, 0x65, 0x00, 0xe5, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6c, 0x17, 0x6d, 0x1d, 0x04, 0x37, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x69, 0x6e, 0x67,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x05, 0x40, 0x06, 0x72, 0x79, 0x00,
- 0x40, 0x09, 0x72, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x72, 0x64, 0x00,
- 0xe3, 0x64, 0x00, 0x72, 0x02, 0x74, 0x04, 0x00, 0x37, 0x01, 0x07, 0x00,
- 0x09, 0xe2, 0x66, 0x00, 0x6e, 0x23, 0xe2, 0x69, 0x00, 0x79, 0x1c, 0xe1,
- 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63,
- 0x00, 0x74, 0x04, 0x40, 0x53, 0x65, 0x00, 0x00, 0x5c, 0x40, 0x07, 0x69,
- 0x6f, 0x6e, 0x00, 0x01, 0xaa, 0xe1, 0x67, 0x00, 0xe2, 0x27, 0x00, 0x73,
- 0x04, 0x41, 0x63, 0x73, 0x00, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x04, 0x69, 0x06, 0x03, 0x72, 0x00, 0x06, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x02, 0x00, 0x09, 0x00, 0x00, 0x40, 0x95, 0x6f, 0x73, 0x74, 0x00, 0x40,
- 0x09, 0x70, 0x00, 0xe9, 0x61, 0x00, 0x65, 0x05, 0x68, 0x1b, 0x69, 0x24,
- 0x6b, 0x52, 0x6c, 0x7e, 0x6f, 0x90, 0x74, 0x92, 0x76, 0x9b, 0x40, 0x07,
- 0x67, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x0c, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x04,
- 0xa5, 0x40, 0x5e, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x00, 0xe1, 0x63,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0b, 0x6f, 0x11, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x75, 0x73,
- 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0x40, 0x07, 0x69, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x69,
- 0x02, 0x73, 0x11, 0x77, 0x19, 0x79, 0x1f, 0x00, 0x97, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x09, 0x6f, 0x72,
- 0x6d, 0x00, 0x01, 0x3b, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00,
- 0x09, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x04, 0xa6, 0x00, 0x09,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0x60, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x73, 0x08, 0x77, 0x1d,
- 0x79, 0x23, 0x00, 0x59, 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0xe1, 0x6d,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65,
- 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x69, 0x02, 0x00, 0x6d, 0x2a,
- 0x00, 0x6f, 0x2f, 0x00, 0x70, 0x3e, 0x00, 0x75, 0xb9, 0x00, 0x00, 0x08,
- 0xe2, 0x61, 0x00, 0x6c, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x0f, 0x69, 0x11, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x3b, 0x40, 0x90, 0x74, 0x79, 0x00, 0x00, 0x09, 0x40, 0x84, 0x74,
- 0x75, 0x64, 0x65, 0x00, 0x40, 0x59, 0x65, 0x72, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x00, 0x07,
- 0xe3, 0x61, 0x00, 0x65, 0x07, 0x6c, 0x16, 0x40, 0x00, 0x74, 0x69, 0x63,
- 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x59,
- 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x22, 0x79, 0x55,
- 0xe5, 0x00, 0x00, 0x6d, 0x02, 0x6e, 0x0a, 0x74, 0x10, 0x78, 0x15, 0x01,
- 0x3b, 0x40, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0xe3, 0x63,
- 0x00, 0x66, 0x06, 0x73, 0x16, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x04, 0x4d, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x2f, 0x74,
- 0x35, 0xe2, 0x63, 0x00, 0x74, 0x0e, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x75, 0x02, 0x00, 0x00, 0x40, 0x08, 0x6d, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x11, 0x03, 0xfc, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x84, 0x00, 0x00, 0x40, 0xd2, 0x72, 0x00,
- 0x40, 0x59, 0x61, 0x73, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x63, 0x02,
- 0x00, 0x65, 0x1f, 0x00, 0x66, 0x37, 0x00, 0x67, 0x4a, 0x00, 0x69, 0xba,
- 0x00, 0x6b, 0xc1, 0x00, 0x6c, 0xdc, 0x00, 0x6e, 0xe2, 0x00, 0x6f, 0xf5,
- 0x00, 0x75, 0xfc, 0x00, 0x00, 0x65, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x04, 0xa7, 0x00, 0x00, 0x40, 0x53, 0x74, 0x79, 0x00, 0xe3,
- 0x00, 0x00, 0x63, 0x02, 0x77, 0x08, 0x00, 0x09, 0x40, 0x09, 0x75, 0x72,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x09, 0x69, 0x19, 0x6c, 0x1e, 0x73, 0x46, 0x75, 0x4c, 0x04, 0xa8, 0x40,
- 0x08, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72,
- 0x07, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x6e, 0x02, 0x73,
- 0x08, 0x74, 0x0a, 0x04, 0xa9, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x72, 0x06, 0x00, 0x08, 0x40, 0x06,
- 0x6e, 0x00, 0x40, 0x06, 0x65, 0x65, 0x00, 0x40, 0x2c, 0x6f, 0x6e, 0x67,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x56, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x00,
- 0x73, 0x74, 0x65, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08,
- 0x68, 0x0c, 0x04, 0xaa, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6c,
- 0x6f, 0x67, 0x79, 0x00, 0xe2, 0x6f, 0x00, 0x73, 0x0f, 0xe2, 0x73, 0x00,
- 0x75, 0x06, 0x40, 0x07, 0x69, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x08, 0x00, 0x09, 0x40, 0x07, 0x74,
- 0x69, 0x73, 0x00, 0x40, 0x00, 0x69, 0x64, 0x61, 0x6c, 0x00, 0xe3, 0x00,
- 0x00, 0x68, 0x02, 0x70, 0x07, 0x00, 0x06, 0x40, 0x59, 0x6f, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02,
- 0x6c, 0x0b, 0x6f, 0x11, 0x72, 0x17, 0x03, 0xba, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x01, 0x95, 0x00, 0x07, 0x40, 0x06, 0x6f, 0x69, 0x6e, 0x00, 0x40,
- 0x06, 0x63, 0x63, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00,
- 0x68, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x73,
- 0x06, 0x74, 0x14, 0x00, 0x09, 0x40, 0x07, 0x6c, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x07, 0x40, 0x00, 0x66, 0x69, 0x65, 0x64, 0x00, 0x01, 0x64, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6c, 0x08,
- 0x00, 0x65, 0x40, 0x09, 0x6f, 0x6f, 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x5d, 0xe6, 0x00,
- 0x00, 0x61, 0x02, 0x63, 0x11, 0x65, 0x16, 0x74, 0x22, 0x75, 0x30, 0x00,
- 0x08, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x6d, 0x02, 0x00, 0x82, 0x40, 0x06, 0x61, 0x70, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x6c, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x70, 0x08,
- 0x73, 0x0f, 0x74, 0x18, 0x04, 0xab, 0x40, 0x00, 0x6f, 0x6c, 0x64, 0x00,
- 0x40, 0x09, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x07, 0x68, 0x6f, 0x6f,
- 0x74, 0x65, 0x72, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x19, 0x69, 0x22, 0x79,
- 0x34, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x01, 0x58, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x01, 0x58, 0xe4, 0x61, 0x00, 0x65, 0x06,
- 0x69, 0x1b, 0x7a, 0x20, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x27, 0x02, 0x6f, 0x06, 0x72, 0x0a, 0x00, 0x4b, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x00, 0x66, 0x00, 0x00, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x7e, 0x6c, 0x65, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x65, 0x3a, 0x00,
- 0x69, 0xcf, 0x00, 0x6f, 0x54, 0x02, 0x75, 0x59, 0x02, 0x79, 0x8d, 0x02,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x29,
- 0xe3, 0x00, 0x00, 0x62, 0x02, 0x72, 0x20, 0x00, 0xa5, 0xe1, 0x6f, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe7, 0x64,
- 0x00, 0x65, 0x08, 0x69, 0x0c, 0x6c, 0x10, 0x70, 0x23, 0x74, 0x3e, 0x77,
- 0x73, 0x40, 0x82, 0x61, 0x64, 0x64, 0x6c, 0x65, 0x00, 0x40, 0x27, 0x74,
- 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x06, 0x00, 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07,
- 0x73, 0x6d, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe6, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x70, 0x1b, 0x79, 0x20, 0x00, 0xe7,
- 0x40, 0x08, 0x6f, 0x6f, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x08, 0x61, 0x64, 0x00, 0x00, 0xf4, 0xe3, 0x00, 0x00, 0x62,
- 0x02, 0x65, 0x08, 0x00, 0xfe, 0x40, 0x08, 0x61, 0x6c, 0x64, 0x00, 0x40,
- 0x2f, 0x72, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x64, 0x07,
- 0x00, 0x65, 0x23, 0x00, 0x66, 0x27, 0x00, 0x69, 0x35, 0x00, 0x6c, 0x3a,
- 0x00, 0x6d, 0x71, 0x00, 0x6e, 0xa7, 0x00, 0x70, 0x02, 0x01, 0x72, 0x1c,
- 0x01, 0x74, 0x29, 0x01, 0x76, 0x52, 0x01, 0x00, 0xfa, 0x40, 0x08, 0x6f,
- 0x62, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x70, 0x10, 0x00, 0x09, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x08, 0x61, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x66,
- 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x40, 0x00, 0x65, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x66, 0x00, 0x6c, 0x07, 0x40, 0x00,
- 0x75, 0x6c, 0x6c, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06,
- 0x66, 0x0f, 0x04, 0xac, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x64, 0x00, 0x74,
- 0x02, 0x00, 0x37, 0x00, 0x06, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x36, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x70, 0x15, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00,
- 0x7a, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe7, 0x00, 0x00, 0x63, 0x02, 0x66,
- 0x08, 0x68, 0x17, 0x6c, 0x1d, 0x6e, 0x23, 0x74, 0x3f, 0x00, 0x09, 0x40,
- 0x07, 0x61, 0x72, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x06, 0x40, 0x09,
- 0x69, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x65, 0x61,
- 0x64, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x04, 0x79, 0x13, 0x40, 0x00, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x04, 0xad,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x00, 0x67, 0x68, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x2c, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x06, 0x40, 0xc3, 0x69, 0x73,
- 0x68, 0x00, 0x00, 0x2c, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe3,
- 0x65, 0x00, 0x69, 0x04, 0x6c, 0x17, 0x40, 0xad, 0x72, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08, 0x65, 0x00, 0xe2, 0x65, 0x00,
- 0x76, 0x02, 0x01, 0x4b, 0x40, 0x5e, 0x79, 0x00, 0x40, 0x06, 0x61, 0x6c,
- 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x02, 0x6e, 0x29, 0x00, 0x08, 0xe3, 0x64,
- 0x00, 0x6b, 0x09, 0x6c, 0x14, 0x40, 0x07, 0x75, 0x67, 0x67, 0x65, 0x72,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xd6, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x06, 0x40, 0x09, 0x61, 0x70,
- 0x00, 0x40, 0x2c, 0x6b, 0x00, 0xe8, 0x00, 0x00, 0x63, 0x02, 0x64, 0x07,
- 0x6a, 0x20, 0x6c, 0x3b, 0x72, 0x53, 0x73, 0x5b, 0x77, 0x64, 0x01, 0x2f,
- 0x40, 0x06, 0x61, 0x70, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x04, 0xae,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00,
- 0x69, 0x05, 0x40, 0x93, 0x72, 0x6b, 0x00, 0xe2, 0x67, 0x00, 0x6e, 0x05,
- 0x40, 0x09, 0x68, 0x74, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x95, 0x6f,
- 0x63, 0x6b, 0x65, 0x74, 0x00, 0x40, 0x06, 0x63, 0x72, 0x61, 0x70, 0x65,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x05, 0x40, 0x08, 0x72, 0x64, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xf6, 0x61, 0x00, 0x00,
- 0x65, 0xad, 0x01, 0x69, 0x07, 0x03, 0x6f, 0x64, 0x04, 0x75, 0xa1, 0x05,
- 0x79, 0x8f, 0x06, 0xff, 0x62, 0x00, 0x00, 0x63, 0x15, 0x00, 0x67, 0x34,
- 0x00, 0x69, 0x51, 0x00, 0x6b, 0x55, 0x00, 0x6c, 0x59, 0x00, 0x6d, 0x5e,
- 0x00, 0x6e, 0x78, 0x00, 0x70, 0xb4, 0x00, 0x73, 0xe8, 0x00, 0x74, 0xf6,
- 0x00, 0x75, 0x16, 0x01, 0x76, 0x39, 0x01, 0x77, 0x6b, 0x01, 0x79, 0x6d,
- 0x01, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6b,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x0b, 0x73, 0x11, 0x04, 0xaf,
- 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x01, 0x20, 0x00, 0x07, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x68, 0x10,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x65, 0x61, 0x70, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x0b, 0x65, 0x00, 0x43, 0x24, 0x6f, 0x6d, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe3, 0x64, 0x00, 0x67, 0x18, 0x74, 0x21, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x06, 0x00, 0xa5, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0xf3, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x77, 0x07,
- 0x03, 0x24, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x73, 0x65,
- 0x00, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x68, 0x08, 0x70, 0x0f, 0x73, 0x22,
- 0x00, 0x09, 0x40, 0x00, 0x61, 0x73, 0x68, 0x00, 0x40, 0x00, 0x61, 0x70,
- 0x70, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x74, 0x69, 0x63, 0x6b, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x68, 0x04, 0x74, 0x09, 0x00, 0x55, 0x00, 0x06, 0x40, 0x7a, 0x65, 0x72,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x40,
- 0x56, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x68,
- 0x06, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x75, 0x73,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x1a, 0xe3, 0x00, 0x00, 0x68, 0x02,
- 0x72, 0x0a, 0x00, 0x7e, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2f, 0x00, 0x07, 0xe1, 0x73, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x04, 0xb0, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xf8, 0x61, 0x00, 0x00, 0x64, 0x30, 0x00, 0x65, 0x5e, 0x00, 0x69, 0xfc,
- 0x00, 0x6e, 0x0f, 0x01, 0x70, 0x2c, 0x01, 0x75, 0x30, 0x01, 0x77, 0x3f,
- 0x01, 0xe1, 0x7a, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x15, 0x79, 0x24, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe2, 0x67, 0x00,
- 0x6c, 0x02, 0x00, 0x08, 0x40, 0x08, 0x6c, 0x00, 0xe2, 0x6c, 0x00, 0x6e,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01,
- 0x0c, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x67, 0x15, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x68,
- 0x02, 0x00, 0x5e, 0x40, 0x95, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x00, 0xe4,
- 0x6b, 0x00, 0x70, 0x0d, 0x74, 0x7c, 0x76, 0x85, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x01, 0x56, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe7, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6c, 0x15, 0x6f, 0x2b, 0x77, 0x31, 0x79, 0x53,
- 0x01, 0x67, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x76, 0x65, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x18, 0xe1, 0x6c, 0x00, 0xe1, 0x6b, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x48, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x61, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x68, 0x02, 0x01, 0x15, 0x40, 0x09, 0x65, 0x61, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x2c, 0x00, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x1a, 0x40, 0x00, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02,
- 0x74, 0x04, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x06, 0xe1, 0x64, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07,
- 0x01, 0x0c, 0x40, 0x3a, 0x7a, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x15, 0x00, 0x00, 0x00, 0x55, 0xf8, 0x63,
- 0x00, 0x00, 0x64, 0x21, 0x00, 0x67, 0x39, 0x00, 0x6d, 0x4c, 0x00, 0x6e,
- 0x8d, 0x00, 0x70, 0xb0, 0x00, 0x74, 0x19, 0x01, 0x76, 0x3f, 0x01, 0xe2,
- 0x65, 0x00, 0x6b, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x04, 0xb1, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x73, 0x04, 0x03, 0x73,
- 0x00, 0x07, 0x40, 0x09, 0x68, 0x6f, 0x77, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x18, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x6c, 0x0b,
- 0x6d, 0x11, 0x6e, 0x2a, 0x79, 0x30, 0x04, 0xb2, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x0f, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00,
- 0x00, 0x00, 0x08, 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe2, 0x67, 0x00, 0x6b,
- 0x15, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x73, 0x08, 0x01, 0x25, 0x40, 0x08,
- 0x61, 0x63, 0x6b, 0x00, 0x40, 0x06, 0x68, 0x6f, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x01, 0x21, 0x00, 0xf3, 0xe6, 0x00, 0x00, 0x63, 0x02,
- 0x6b, 0x12, 0x70, 0x18, 0x73, 0x46, 0x77, 0x57, 0x00, 0x09, 0xe2, 0x61,
- 0x00, 0x6f, 0x05, 0x40, 0x09, 0x73, 0x65, 0x00, 0x40, 0x09, 0x76, 0x65,
- 0x72, 0x00, 0x40, 0x09, 0x6e, 0x6f, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x1e, 0x79, 0x23, 0x40, 0x09, 0x67, 0x65, 0x00, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09,
- 0x00, 0x06, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x05, 0x40,
- 0x00, 0x6f, 0x64, 0x00, 0x40, 0x06, 0x72, 0x65, 0x61, 0x6d, 0x00, 0x40,
- 0x06, 0x61, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x74, 0x11, 0x00,
- 0x09, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x93, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x72,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x95, 0x65, 0x72, 0x00, 0xfa,
- 0x62, 0x00, 0x00, 0x65, 0x21, 0x00, 0x67, 0x23, 0x00, 0x6f, 0x4c, 0x00,
- 0x70, 0x50, 0x00, 0x73, 0x81, 0x00, 0x74, 0x85, 0x00, 0x75, 0xba, 0x00,
- 0x76, 0xdd, 0x00, 0x77, 0xf8, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x10, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x47, 0x00, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x67, 0x14,
- 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x70, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x70, 0x04, 0x73, 0x26, 0x00,
- 0x55, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x19, 0x40, 0x00,
- 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00,
- 0x96, 0x00, 0x07, 0x40, 0x3a, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02,
- 0x74, 0x20, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x73, 0x15, 0x00,
- 0x07, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe2, 0x63, 0x00, 0x67, 0x12, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x79, 0x06, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x00, 0x60, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0xec, 0x00, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x56,
- 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x96, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x64, 0x09, 0x6e, 0x0f, 0x70,
- 0x15, 0x04, 0xb3, 0x40, 0x08, 0x6f, 0x61, 0x63, 0x68, 0x00, 0x40, 0x06,
- 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x6f, 0x6b, 0x65, 0x00, 0xe9, 0x64, 0x00, 0x65, 0x0c, 0x67, 0x0e, 0x69,
- 0x43, 0x6d, 0x48, 0x6e, 0x8d, 0x72, 0x96, 0x73, 0xb3, 0x74, 0xc8, 0xe1,
- 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0xf3, 0x00,
- 0x82, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09, 0xe3, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x0e, 0x40, 0x09, 0x72, 0x64, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x00,
- 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x5e, 0x63, 0x65, 0x00, 0xe6,
- 0x00, 0x00, 0x62, 0x02, 0x64, 0x14, 0x6c, 0x19, 0x6d, 0x1f, 0x70, 0x36,
- 0x00, 0x09, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x95, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x67,
- 0x00, 0x40, 0x09, 0x6f, 0x72, 0x64, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x79, 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0x00, 0x2c, 0xe2, 0x67, 0x00, 0x6b,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x70, 0x02, 0x72, 0x04,
- 0x00, 0x09, 0x00, 0x2c, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x07, 0xe1, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x09, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x73, 0x68, 0x00,
- 0x00, 0xf3, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0xb4, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65, 0xaf, 0x00, 0x69, 0xe2,
- 0x00, 0x6f, 0x3a, 0x01, 0x75, 0xf4, 0x01, 0xe5, 0x63, 0x00, 0x6c, 0x0e,
- 0x72, 0x45, 0x73, 0x87, 0x74, 0x9b, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6c, 0x00, 0xe5,
- 0x00, 0x00, 0x68, 0x02, 0x69, 0x19, 0x6e, 0x1e, 0x70, 0x24, 0x04, 0xb5,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x08, 0x72, 0x00, 0x40, 0x08, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x73, 0x68, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x6f, 0x78, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x04, 0x40, 0xf3, 0x79, 0x00,
- 0xe7, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x70, 0x0c, 0x73, 0x13, 0x77,
- 0x15, 0x79, 0x1c, 0x04, 0x4a, 0x41, 0x20, 0x6e, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x06, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x07,
- 0x40, 0x09, 0x61, 0x74, 0x63, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x61, 0x6e, 0x74, 0x73, 0x00, 0xe1, 0x68, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x75, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x06, 0x70, 0x00, 0x40, 0x09, 0x74, 0x65, 0x72, 0x69, 0x6e,
- 0x67, 0x00, 0xe2, 0x61, 0x00, 0x6c, 0x0c, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x2c, 0x00, 0xf3, 0xe2, 0x6c, 0x00, 0x74, 0x12,
- 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x2c, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01,
- 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe4, 0x64, 0x00, 0x6c, 0x06, 0x72, 0x1f,
- 0x74, 0x2a, 0x40, 0x09, 0x67, 0x65, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x04, 0x69, 0x0d, 0x40, 0x07, 0x78, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x5e, 0x00, 0x06, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00,
- 0x6b, 0x04, 0x40, 0x59, 0x68, 0x00, 0x00, 0x2c, 0xe3, 0x65, 0x00, 0x68,
- 0x02, 0x74, 0x19, 0x01, 0x21, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x73, 0x0a,
- 0x79, 0x0c, 0x00, 0x07, 0x40, 0x07, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe7, 0x63, 0x00,
- 0x67, 0x0f, 0x6b, 0x1a, 0x6c, 0x64, 0x6f, 0x6a, 0x72, 0x95, 0x74, 0x9f,
- 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09, 0x40, 0xf3,
- 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x32, 0x79, 0x41, 0xe6, 0x00, 0x00,
- 0x68, 0x02, 0x6c, 0x09, 0x72, 0x0f, 0x73, 0x11, 0x79, 0x23, 0x00, 0x7e,
- 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x07, 0xe2, 0x63, 0x00, 0x74, 0x07, 0x40, 0x06, 0x72, 0x65,
- 0x65, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x63, 0x6b, 0x00, 0x00, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x00, 0x07, 0x00, 0xf4, 0x40, 0x93, 0x64, 0x65, 0x72, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x0c, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x47, 0x00, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e,
- 0x06, 0x73, 0x0c, 0x04, 0xb6, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x06, 0x67, 0x61, 0x73, 0x62, 0x6f,
- 0x72, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x02, 0x00, 0x00, 0x40, 0x95,
- 0x65, 0x72, 0x00, 0xe4, 0x64, 0x00, 0x67, 0x0c, 0x72, 0x3e, 0x74, 0x42,
- 0xe1, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x5e, 0x00, 0x60,
- 0xe3, 0x00, 0x00, 0x67, 0x02, 0x6e, 0x25, 0x00, 0x3e, 0xe2, 0x65, 0x00,
- 0x6c, 0x0b, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x08, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x3b, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x04, 0x01, 0x69, 0x47,
- 0x01, 0x6f, 0xce, 0x01, 0x75, 0x8d, 0x03, 0xe9, 0x63, 0x00, 0x66, 0x04,
- 0x67, 0x10, 0x69, 0x25, 0x6b, 0x29, 0x70, 0x4d, 0x72, 0xa5, 0x74, 0xd1,
- 0x7a, 0xe2, 0x40, 0x2c, 0x6b, 0x00, 0xe2, 0x66, 0x00, 0x75, 0x05, 0x40,
- 0x5e, 0x6c, 0x65, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x2c, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x1d,
- 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x08, 0x73, 0x0e, 0x00, 0x5e, 0x40,
- 0x09, 0x69, 0x74, 0x65, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00, 0x40,
- 0x00, 0x6b, 0x69, 0x6e, 0x00, 0x00, 0xf3, 0xe5, 0x00, 0x00, 0x27, 0x02,
- 0x64, 0x06, 0x70, 0x0e, 0x73, 0x47, 0x01, 0x43, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x06, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x79, 0x30, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x09,
- 0xe3, 0x6c, 0x00, 0x6e, 0x04, 0x73, 0x10, 0x40, 0x00, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x37, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x3b, 0x40, 0x06, 0x68, 0x6f, 0x74, 0x00, 0xe4,
- 0x65, 0x00, 0x66, 0x02, 0x6b, 0x04, 0x6c, 0x0d, 0x00, 0x5e, 0x00, 0x7a,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x08, 0x00, 0x60, 0xe4, 0x00, 0x00,
- 0x27, 0x02, 0x69, 0x06, 0x79, 0x0b, 0x01, 0x73, 0x40, 0x00, 0x73, 0x00,
- 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x00, 0x60, 0xe1, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x7a, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79,
- 0x00, 0x00, 0x60, 0xe2, 0x61, 0x00, 0x65, 0x29, 0xe1, 0x6b, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x79, 0x1b, 0x01, 0x5b, 0x40, 0x07,
- 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x3b, 0x01,
- 0x3b, 0xe2, 0x72, 0x00, 0x7a, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x04,
- 0x80, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe6, 0x63,
- 0x00, 0x64, 0x0e, 0x66, 0x12, 0x70, 0x31, 0x74, 0x5e, 0x76, 0x69, 0xe1,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xd6, 0x40, 0x2f, 0x72,
- 0x00, 0x40, 0xda, 0x65, 0x00, 0xe2, 0x66, 0x00, 0x74, 0x15, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x6c, 0x06, 0x79, 0x0a, 0x01, 0x5b, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x5e, 0x65, 0x00, 0x00, 0xf3, 0x40, 0x06, 0x65, 0x72, 0x00,
- 0xe4, 0x00, 0x00, 0x65, 0x02, 0x70, 0x0b, 0x73, 0x22, 0x00, 0xfe, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x79, 0x0e, 0xe2, 0x64, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0xf3, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x09, 0x40, 0x47, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0x40, 0x07, 0x72,
- 0x00, 0xf7, 0x62, 0x00, 0x00, 0x67, 0x28, 0x00, 0x6f, 0x3d, 0x00, 0x72,
- 0x7c, 0x00, 0x74, 0xaf, 0x00, 0x75, 0xcc, 0x00, 0x77, 0xd0, 0x00, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x69, 0x05, 0x79,
- 0x18, 0x40, 0x07, 0x72, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0xf3, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x08, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe5, 0x64, 0x00, 0x6b, 0x02, 0x70, 0x07, 0x74, 0x16, 0x7a, 0x30, 0x00,
- 0x06, 0x40, 0x47, 0x65, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79,
- 0x06, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x00, 0x60, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x79, 0x11, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0x40,
- 0x5e, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6b, 0x09, 0x74, 0x21, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xc3, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x09, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0x40,
- 0x06, 0x74, 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x64, 0x46, 0x66, 0x57,
- 0x69, 0x6f, 0x6c, 0x76, 0x6d, 0x7c, 0x70, 0x92, 0x73, 0x98, 0x79, 0xc2,
- 0x00, 0x55, 0xe4, 0x61, 0x00, 0x69, 0x0d, 0x6c, 0x12, 0x6f, 0x19, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x95, 0x6c, 0x00, 0x40, 0x06, 0x6b, 0x00,
- 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x09, 0x6f, 0x77, 0x65, 0x72, 0x00,
- 0xe2, 0x61, 0x00, 0x75, 0x18, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6e, 0x64, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x66, 0x74, 0x00, 0x40,
- 0x06, 0x70, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x05, 0x6c, 0x0b, 0x40, 0x06,
- 0x6c, 0x6c, 0x00, 0x40, 0x06, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x06, 0x61,
- 0x6b, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00,
- 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x04, 0x6f, 0x08, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x5e, 0x62, 0x69, 0x6c,
- 0x65, 0x00, 0x40, 0x93, 0x6c, 0x6f, 0x77, 0x00, 0xe3, 0x68, 0x00, 0x74,
- 0x18, 0x75, 0x1e, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x72, 0x6d, 0x00, 0x40, 0x06, 0x69,
- 0x74, 0x00, 0x01, 0x0c, 0xe3, 0x62, 0x00, 0x66, 0x15, 0x67, 0x30, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x66, 0x00, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x07, 0x6c, 0x0b, 0x04, 0xb7, 0x40, 0x09,
- 0x6f, 0x78, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x82, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x67, 0x02, 0x6e, 0x21, 0x02, 0x41, 0xe3, 0x65, 0x00, 0x69,
- 0x0f, 0x6c, 0x14, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x82, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xc1, 0x61, 0x1a,
- 0x39, 0x00, 0x3b, 0x00, 0x7b, 0x00, 0xb7, 0x00, 0x9c, 0x01, 0xda, 0x01,
- 0xe0, 0x01, 0x47, 0x02, 0x00, 0x00, 0x60, 0x02, 0x86, 0x02, 0x00, 0x00,
- 0x9d, 0x02, 0x8b, 0x04, 0x67, 0x05, 0x19, 0x06, 0x58, 0x06, 0x00, 0x00,
- 0xed, 0x06, 0x00, 0x00, 0xb0, 0x07, 0xbd, 0x07, 0x92, 0x09, 0xb6, 0x09,
- 0x00, 0x00, 0xcb, 0x09, 0xd8, 0x09, 0x00, 0x00, 0xe3, 0x6b, 0x00, 0x70,
- 0x0c, 0x72, 0x37, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x6b, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x69, 0x07, 0x73, 0x0e,
- 0x79, 0x1e, 0x00, 0x55, 0x40, 0x09, 0x6f, 0x78, 0x00, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x74, 0x00, 0x75, 0x06, 0x40, 0x07, 0x6f,
- 0x6e, 0x65, 0x00, 0x40, 0x07, 0x64, 0x73, 0x00, 0x01, 0x15, 0x00, 0x55,
- 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x10, 0x72, 0x20, 0x00, 0x06, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x3b, 0x6e, 0x67,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0xb8, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x65, 0x00, 0x71,
- 0x05, 0x40, 0x53, 0x74, 0x79, 0x00, 0x40, 0x06, 0x75, 0x65, 0x74, 0x00,
- 0xe4, 0x00, 0x00, 0x63, 0x02, 0x69, 0x07, 0x6b, 0xca, 0x00, 0x00, 0x40,
- 0x07, 0x65, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x4c, 0x6f, 0x5a, 0xe2,
- 0x62, 0x00, 0x6c, 0x15, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x06, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0xe3, 0x73, 0x00, 0x74,
- 0x12, 0x7a, 0x16, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x65,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x3a, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x04, 0x40,
- 0x00, 0x6c, 0x00, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x6c, 0x22, 0x70, 0x3d,
- 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00,
- 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00,
- 0x07, 0xe2, 0x61, 0x00, 0x6f, 0x0f, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x55, 0xe2, 0x74, 0x00, 0x79, 0x02, 0x00, 0x06, 0x40, 0x06, 0x65,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x64, 0x04, 0x69, 0x17, 0x6f, 0x1c,
- 0x00, 0x06, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00,
- 0x6e, 0x02, 0x00, 0x00, 0x00, 0x3b, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x07, 0x75, 0x6d, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0d,
- 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x0b, 0x65,
- 0x00, 0x00, 0x07, 0x40, 0x00, 0x76, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00,
- 0x74, 0x02, 0x00, 0x09, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x1a, 0x65,
- 0x21, 0x68, 0x2f, 0x6e, 0x38, 0x77, 0x3e, 0x79, 0x4d, 0x03, 0x2f, 0xe2,
- 0x61, 0x00, 0x6f, 0x0d, 0xe2, 0x63, 0x00, 0x6c, 0x04, 0x40, 0x00, 0x6b,
- 0x00, 0x40, 0x09, 0x6c, 0x00, 0x40, 0x00, 0x75, 0x6e, 0x64, 0x00, 0x40,
- 0x00, 0x6f, 0x76, 0x65, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x01, 0x54, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x65, 0x61,
- 0x72, 0x74, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x06, 0x6f,
- 0x64, 0x00, 0x00, 0x06, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe3, 0x67, 0x00, 0x6c, 0x0f, 0x72, 0x1a,
- 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x55, 0x40, 0x37,
- 0x64, 0x00, 0x40, 0x06, 0x65, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x64, 0x1d, 0x00, 0x65, 0x43, 0x00, 0x69, 0x96, 0x00, 0x6f, 0x6a,
- 0x01, 0x73, 0x76, 0x01, 0x75, 0x7d, 0x01, 0x76, 0xad, 0x01, 0x00, 0x06,
- 0xe2, 0x63, 0x00, 0x72, 0x04, 0x40, 0x5e, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40,
- 0x07, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x10, 0x00, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x05, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x03, 0x7c, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x08,
- 0x6d, 0x0c, 0x6e, 0x42, 0x04, 0xb9, 0x40, 0x06, 0x69, 0x73, 0x6d, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x07, 0x6e, 0x24, 0x00, 0x63, 0x40, 0x07, 0x73, 0x73, 0x00, 0xe3,
- 0x66, 0x00, 0x74, 0x04, 0x7a, 0x08, 0x40, 0x3a, 0x79, 0x00, 0x40, 0x06,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x6f, 0x69, 0x64, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x3a, 0x6c, 0x75, 0x70,
- 0x92, 0x74, 0xa7, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x09, 0x6f, 0x0d, 0x75, 0x24, 0x00, 0x0b, 0x40, 0x06,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x72, 0x00,
- 0x75, 0x02, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x64, 0x65,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x09, 0x6e, 0x26, 0x75, 0x2c,
- 0x04, 0xba, 0x40, 0x07, 0x72, 0x69, 0x74, 0x79, 0x00, 0xe3, 0x00, 0x00,
- 0x66, 0x02, 0x74, 0x12, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40,
- 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0xd9, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x71, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x0d, 0xe2, 0x65, 0x00, 0x7a, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x00, 0x69,
- 0x63, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x18, 0xe2, 0x69, 0x00, 0x72, 0x05,
- 0x40, 0x09, 0x72, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x02, 0x7b, 0x40, 0x07, 0x64, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x55, 0x40, 0x09, 0x73, 0x74, 0x00,
- 0x40, 0x09, 0x74, 0x69, 0x63, 0x65, 0x00, 0xe2, 0x62, 0x00, 0x74, 0x10,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x09, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe3, 0x00, 0x00,
- 0x27, 0x02, 0x73, 0x06, 0x04, 0xbb, 0x40, 0x00, 0x73, 0x00, 0x00, 0x00,
- 0x44, 0xbc, 0x6f, 0x6e, 0x27, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06,
- 0x40, 0x9b, 0x62, 0x6c, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6e,
- 0x04, 0x72, 0x0f, 0x02, 0x8c, 0x00, 0x37, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x53, 0x79, 0x00, 0x01, 0x89, 0x00, 0x06, 0xe4, 0x61, 0x00, 0x62,
- 0x06, 0x65, 0x21, 0x6e, 0x9f, 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0xe2,
- 0x65, 0x00, 0x72, 0x10, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x65, 0x72,
- 0x6f, 0x00, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08, 0x68, 0x0d, 0x6f,
- 0x12, 0x70, 0x17, 0x72, 0x1e, 0x74, 0x44, 0x77, 0x54, 0x00, 0x00, 0x40,
- 0x06, 0x6f, 0x64, 0x79, 0x00, 0x40, 0x00, 0x61, 0x79, 0x00, 0x40, 0x00,
- 0x6f, 0x77, 0x00, 0x40, 0x09, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x61,
- 0x63, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x06, 0x40,
- 0x55, 0x75, 0x6c, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x06, 0x40, 0x06,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x6d, 0x65, 0x00, 0xe2, 0x61, 0x00,
- 0x68, 0x04, 0x40, 0x08, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x08, 0x74, 0x00, 0x40, 0x00, 0x72, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x1b, 0xe1, 0x6d, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02,
- 0x00, 0x07, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x00,
- 0xe7, 0x00, 0x00, 0x61, 0x02, 0x67, 0x15, 0x69, 0x60, 0x6e, 0x64, 0x6f,
- 0x6f, 0x73, 0x97, 0x00, 0x06, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0xe2, 0x61, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x06, 0x6e, 0x61, 0x00,
- 0xe5, 0x00, 0x00, 0x62, 0x02, 0x66, 0x11, 0x73, 0x17, 0x77, 0x29, 0x00,
- 0x09, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x72, 0x64, 0x00, 0x40,
- 0x06, 0x6f, 0x6b, 0x00, 0x40, 0x06, 0x65, 0x73, 0x74, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x09,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04,
- 0x40, 0x06, 0x74, 0x00, 0x00, 0x06, 0xe2, 0x67, 0x00, 0x72, 0x06, 0x40,
- 0x06, 0x72, 0x61, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00,
- 0x6f, 0x66, 0x62, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x00, 0xe2, 0x6e,
- 0x00, 0x74, 0x02, 0x00, 0xf3, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x79, 0x2f,
- 0x00, 0x07, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0b, 0x73, 0x10, 0x00,
- 0xe7, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x07, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00,
- 0xf3, 0xe5, 0x00, 0x00, 0x68, 0x02, 0x6f, 0x56, 0x70, 0x72, 0x72, 0x84,
- 0x00, 0x06, 0xe2, 0x69, 0x00, 0x6f, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x72, 0x26,
- 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x00, 0x00, 0x64, 0x02, 0x02, 0xa4, 0x00, 0x37, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x63, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x66, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79,
- 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0xf3,
- 0x40, 0x09, 0x61, 0x6e, 0x6f, 0x00, 0xe8, 0x62, 0x00, 0x63, 0x05, 0x64,
- 0x1d, 0x65, 0x30, 0x67, 0x45, 0x6f, 0x4b, 0x72, 0x52, 0x74, 0x8d, 0x40,
- 0x06, 0x65, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x0b, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x09,
- 0x73, 0x00, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x68, 0x02, 0x6e, 0x08, 0x04, 0xbd, 0x40, 0x09, 0x65, 0x61,
- 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x68, 0x75,
- 0x6d, 0x00, 0x40, 0x06, 0x72, 0x69, 0x74, 0x79, 0x00, 0xe4, 0x65, 0x00,
- 0x69, 0x04, 0x6f, 0x13, 0x79, 0x30, 0x40, 0x06, 0x6c, 0x00, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x2c, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x04, 0x69, 0x0d, 0x04, 0xbe, 0x00, 0x00, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x37, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x1a, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x06, 0x40, 0x00, 0x69, 0x73, 0x68, 0x00, 0xfc, 0x00,
- 0x00, 0x00, 0x27, 0x02, 0x00, 0x66, 0x0b, 0x00, 0x67, 0x11, 0x00, 0x6b,
- 0x21, 0x00, 0x6c, 0x23, 0x00, 0x6e, 0x4d, 0x00, 0x70, 0xc8, 0x00, 0x72,
- 0xd8, 0x00, 0x73, 0x11, 0x01, 0x74, 0x20, 0x01, 0x76, 0xa9, 0x01, 0x01,
- 0x58, 0x40, 0x00, 0x77, 0x65, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x06,
- 0x66, 0x6c, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02,
- 0x74, 0x04, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x37, 0x00, 0x08, 0xe4, 0x00,
- 0x00, 0x66, 0x02, 0x6c, 0x15, 0x6d, 0x1b, 0x00, 0x09, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x3e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08,
- 0x61, 0x74, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02,
- 0x62, 0x09, 0x63, 0x1f, 0x65, 0x26, 0x69, 0x2a, 0x6c, 0x2f, 0x6e, 0x35,
- 0x70, 0x3b, 0x73, 0x53, 0x74, 0x5a, 0x04, 0x3f, 0x40, 0x08, 0x6c, 0x69,
- 0x6b, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x6f, 0x09, 0x40, 0x08,
- 0x72, 0x00, 0x40, 0x08, 0x74, 0x65, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64,
- 0x00, 0x40, 0x08, 0x68, 0x65, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x0b,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x63, 0x61, 0x70, 0x65, 0x00,
- 0x40, 0x06, 0x72, 0x61, 0x63, 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02,
- 0x79, 0x07, 0x00, 0x55, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x00, 0xf3, 0xe6,
- 0x00, 0x00, 0x63, 0x02, 0x64, 0x06, 0x69, 0x1b, 0x6e, 0x20, 0x70, 0x26,
- 0x02, 0xed, 0x41, 0x85, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x09, 0x75, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x08, 0x40, 0x09, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x5e, 0xe1,
- 0x68, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x09, 0x70, 0x4b, 0x77,
- 0x50, 0x00, 0x07, 0x40, 0x00, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe2, 0x61,
- 0x00, 0x72, 0x21, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x77, 0x0e, 0x00, 0x27, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x12, 0x00, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x6d, 0x06, 0x00, 0x0f, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00,
- 0x6f, 0x73, 0x74, 0x00, 0x40, 0x06, 0x61, 0x77, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x05, 0x40, 0x09, 0x72, 0x64, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x77, 0x0e, 0x00, 0x27, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x12, 0x00, 0x00, 0x40, 0x08,
- 0x61, 0x72, 0x64, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x69, 0x72, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x1a, 0xe1, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x6e, 0x0a, 0x01, 0x40, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x06, 0x72, 0x00, 0x00, 0x77, 0xe2, 0x00, 0x00, 0x62,
- 0x02, 0x00, 0x07, 0x40, 0x09, 0x65, 0x61, 0x6e, 0x00, 0x40, 0x00, 0x7a,
- 0x6c, 0x65, 0x64, 0x00, 0xf9, 0x61, 0x00, 0x00, 0x65, 0x3b, 0x02, 0x68,
- 0x5d, 0x05, 0x69, 0x9e, 0x05, 0x6c, 0x99, 0x07, 0x6f, 0xab, 0x08, 0x72,
- 0xf5, 0x0a, 0x75, 0x3b, 0x0c, 0x79, 0xbc, 0x0c, 0xfd, 0x00, 0x00, 0x00,
- 0x63, 0x02, 0x00, 0x64, 0xa2, 0x00, 0x67, 0xc7, 0x00, 0x6b, 0xcf, 0x00,
- 0x6d, 0xd3, 0x00, 0x6e, 0xed, 0x00, 0x72, 0x31, 0x01, 0x73, 0xaf, 0x01,
- 0x74, 0xd6, 0x01, 0x76, 0x08, 0x02, 0x77, 0x0d, 0x02, 0x79, 0x11, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x64, 0xe9, 0x00, 0x00, 0x63, 0x02,
- 0x66, 0x09, 0x6d, 0x11, 0x70, 0x1e, 0x72, 0x24, 0x73, 0x26, 0x77, 0x35,
- 0x79, 0x4f, 0x00, 0x7e, 0x40, 0x09, 0x72, 0x61, 0x66, 0x74, 0x00, 0x40,
- 0x09, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x6f, 0x72,
- 0x74, 0x00, 0x00, 0x07, 0xe2, 0x68, 0x00, 0x75, 0x05, 0x40, 0x06, 0x69,
- 0x70, 0x00, 0x40, 0x06, 0x69, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05,
- 0x40, 0x93, 0x6c, 0x6b, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x00, 0xe4,
- 0x61, 0x00, 0x65, 0x04, 0x6e, 0x0f, 0x6f, 0x1b, 0x40, 0x00, 0x6c, 0x00,
- 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0xe1,
- 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x14, 0xe3,
- 0x00, 0x00, 0x66, 0x02, 0x77, 0x07, 0x00, 0x5e, 0x40, 0x09, 0x75, 0x6c,
- 0x00, 0x40, 0x07, 0x6f, 0x72, 0x6b, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x05,
- 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x68, 0x65, 0x74,
- 0x74, 0x69, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe6, 0x00, 0x00,
- 0x64, 0x02, 0x67, 0x07, 0x69, 0x13, 0x6b, 0x18, 0x6e, 0x24, 0x00, 0x09,
- 0x40, 0x07, 0x65, 0x78, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x5e, 0x00, 0x00, 0x40, 0x06, 0x65, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x01, 0x62, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x69, 0x17,
- 0x6b, 0x1c, 0x72, 0x33, 0x73, 0x53, 0x74, 0x6a, 0x00, 0x09, 0xe3, 0x00,
- 0x00, 0x6e, 0x02, 0x72, 0x08, 0x03, 0x1a, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x69, 0x62, 0x73, 0x00, 0x40, 0x36, 0x6e, 0x67, 0x00,
- 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x79, 0x0e, 0x02, 0x0a, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x00, 0xf3, 0xe3,
- 0x65, 0x00, 0x69, 0x04, 0x6f, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe1, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02, 0x00,
- 0x06, 0x40, 0x08, 0x61, 0x77, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x00, 0xe2,
- 0x6d, 0x00, 0x74, 0x1d, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0xe1,
- 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x06, 0x69,
- 0x63, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x68, 0x04, 0x69, 0x08, 0x74,
- 0x0d, 0x75, 0x20, 0x00, 0x09, 0x00, 0x06, 0x40, 0x06, 0x65, 0x00, 0x40,
- 0x3b, 0x61, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x93, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x6c, 0x61, 0x00, 0x40, 0x20, 0x69, 0x6e, 0x00, 0x40, 0x2c, 0x6e,
- 0x00, 0x00, 0x72, 0xf8, 0x61, 0x00, 0x00, 0x63, 0x48, 0x00, 0x64, 0x89,
- 0x01, 0x65, 0x8b, 0x01, 0x6c, 0x17, 0x02, 0x6e, 0xa4, 0x02, 0x72, 0xc7,
- 0x02, 0x77, 0xfe, 0x02, 0xe2, 0x6b, 0x00, 0x72, 0x1f, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x04, 0xbf, 0xe2, 0x61, 0x00, 0x72, 0x05, 0x40, 0x06, 0x73,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x07, 0x40, 0x08, 0x68,
- 0x6f, 0x6e, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x67, 0x08, 0x68,
- 0x0d, 0x6d, 0x13, 0x00, 0x2c, 0x40, 0x59, 0x69, 0x73, 0x68, 0x00, 0x40,
- 0x00, 0x75, 0x6e, 0x00, 0x40, 0x59, 0x65, 0x61, 0x64, 0x00, 0x40, 0x07,
- 0x69, 0x6e, 0x74, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x69, 0x02, 0x00, 0x6b,
- 0x94, 0x00, 0x73, 0x9f, 0x00, 0x74, 0xa1, 0x00, 0x75, 0x0b, 0x01, 0x00,
- 0x09, 0xe5, 0x61, 0x00, 0x65, 0x2c, 0x66, 0x35, 0x6d, 0x6f, 0x6f, 0x74,
- 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x74, 0x1e, 0x00, 0x56,
- 0xe2, 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x08,
- 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x06, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x31,
- 0x00, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x06, 0x65, 0x24, 0x40, 0x00, 0x62,
- 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x12, 0x00, 0x09,
- 0xe2, 0x6c, 0x00, 0x74, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x37, 0x64,
- 0x00, 0x04, 0xc0, 0x40, 0x06, 0x65, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x2c, 0x40, 0x82,
- 0x65, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00, 0x65, 0x27, 0x72, 0x2b, 0xe2,
- 0x63, 0x00, 0x74, 0x17, 0xe2, 0x6c, 0x00, 0x75, 0x0c, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0x40, 0x86, 0x6c,
- 0x61, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x3a, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x69, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x09, 0x75,
- 0x2d, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x6d,
- 0x00, 0x73, 0x07, 0x40, 0x09, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x79, 0x06, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x00, 0x07, 0x40, 0x07,
- 0x6d, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x02, 0x6f, 0x0f, 0x00, 0x9d, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40, 0x09, 0x72,
- 0x00, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x64, 0x31, 0xe1, 0x68, 0x00, 0xe4,
- 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07, 0x77, 0x1d, 0x00, 0x09, 0x40, 0x3a,
- 0x66, 0x79, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x08, 0x72, 0x69, 0x74, 0x65, 0x72, 0x00, 0xe9, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x6f, 0x21, 0x73, 0x29, 0x75, 0x2f,
- 0x77, 0x33, 0x79, 0x41, 0x01, 0x67, 0x40, 0x06, 0x6f, 0x61, 0x74, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0x40, 0x09, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x00, 0x40, 0x06, 0x74,
- 0x65, 0x72, 0x00, 0x40, 0x09, 0x70, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x06, 0x79, 0x00, 0x40, 0x07, 0x6c, 0x6c, 0x00, 0x01, 0x92, 0xe3,
- 0x65, 0x00, 0x6c, 0x21, 0x75, 0x72, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2,
- 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x00, 0x07, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x63, 0x1e, 0x64, 0x35,
- 0x65, 0x3b, 0x69, 0x3f, 0x04, 0xc1, 0xe2, 0x69, 0x00, 0x6f, 0x11, 0xe1,
- 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe5,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x75, 0x6e, 0x64, 0x00, 0xe1, 0x68,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x4c, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x6f,
- 0x77, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x64, 0x00, 0x74,
- 0x1c, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x74, 0x0b, 0x04, 0xc2,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x68,
- 0x72, 0x69, 0x66, 0x74, 0x00, 0x00, 0x37, 0xe1, 0x6d, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x19, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x7a, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x02,
- 0x00, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00,
- 0x00, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfe, 0x40, 0x07, 0x72,
- 0x00, 0xe3, 0x61, 0x00, 0x65, 0x07, 0x69, 0x2a, 0x40, 0x09, 0x67, 0x6e,
- 0x75, 0x6d, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x08, 0x00, 0x06, 0x40, 0x3b, 0x63, 0x61, 0x6c, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x6c, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x06, 0x40, 0x09,
- 0x74, 0x65, 0x72, 0x00, 0x00, 0x09, 0xfb, 0x63, 0x00, 0x00, 0x64, 0x25,
- 0x00, 0x65, 0x3b, 0x00, 0x66, 0x3f, 0x00, 0x67, 0x4b, 0x00, 0x6b, 0x50,
- 0x00, 0x6c, 0x62, 0x00, 0x6e, 0x80, 0x00, 0x72, 0xfc, 0x00, 0x74, 0x79,
- 0x01, 0x76, 0xd7, 0x01, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x75,
- 0x13, 0x79, 0x18, 0x00, 0x08, 0x00, 0x5e, 0xe2, 0x6c, 0x00, 0x6e, 0x04,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x6c, 0x65, 0x00, 0x01, 0x0c, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x77, 0x02, 0x79, 0x07, 0x00, 0x06, 0x40, 0x09, 0x65, 0x62,
- 0x00, 0x00, 0x00, 0x40, 0x2c, 0x6c, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x7a, 0x00, 0x60, 0x40, 0x06, 0x6f, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x5e, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe1, 0x6c, 0x00, 0xe4, 0x00, 0x00,
- 0x61, 0x02, 0x6f, 0x07, 0x77, 0x0d, 0x00, 0x2c, 0x40, 0x09, 0x67, 0x65,
- 0x00, 0x40, 0x06, 0x76, 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00,
- 0xe7, 0x00, 0x00, 0x61, 0x02, 0x64, 0x0d, 0x65, 0x19, 0x6e, 0x2a, 0x73,
- 0x4e, 0x79, 0x6b, 0x00, 0x09, 0xe2, 0x63, 0x00, 0x6c, 0x04, 0x40, 0x07,
- 0x68, 0x00, 0x00, 0x56, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x82, 0x00, 0x60, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x74, 0x08, 0x00,
- 0x06, 0x40, 0x3e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x06, 0xe3, 0x61, 0x00,
- 0x65, 0x06, 0x69, 0x18, 0x40, 0x06, 0x6b, 0x65, 0x72, 0x00, 0xe2, 0x72,
- 0x00, 0x79, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40, 0x06,
- 0x74, 0x00, 0x00, 0x08, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x69,
- 0x08, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x00, 0x73,
- 0x68, 0x00, 0x00, 0xf3, 0xe5, 0x61, 0x00, 0x65, 0x0c, 0x69, 0x1b, 0x6f,
- 0x68, 0x79, 0x70, 0xe2, 0x63, 0x00, 0x6c, 0x05, 0x40, 0x06, 0x6c, 0x65,
- 0x00, 0x00, 0xfd, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x04, 0xc3,
- 0x40, 0x00, 0x73, 0x00, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe5, 0x00, 0x00,
- 0x27, 0x02, 0x65, 0x06, 0x6c, 0x0a, 0x75, 0x10, 0x04, 0xc4, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x3b, 0x64, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x25, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x86, 0xe2, 0x73, 0x00, 0x74, 0x12, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x63, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40,
- 0x06, 0x63, 0x68, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x08, 0x66, 0x32, 0x74, 0x38, 0x00, 0x55, 0x40, 0x06,
- 0x61, 0x6c, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x65, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x10,
- 0x00, 0x4d, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x69, 0x72, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04, 0x6c, 0x09, 0x6f,
- 0x0d, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x00, 0x08, 0xf5, 0x61, 0x00,
- 0x00, 0x65, 0x5c, 0x00, 0x69, 0x93, 0x00, 0x6f, 0xd3, 0x00, 0x75, 0xf2,
- 0x00, 0xe3, 0x73, 0x00, 0x74, 0x25, 0x79, 0x3f, 0xe1, 0x68, 0x00, 0xe4,
- 0x00, 0x00, 0x64, 0x02, 0x69, 0x08, 0x79, 0x17, 0x00, 0x59, 0x40, 0x09,
- 0x6f, 0x77, 0x6e, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x95, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x66, 0x02, 0x00, 0x2c, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40,
- 0x00, 0x65, 0x74, 0x00, 0x40, 0x20, 0x6f, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x6e, 0x04, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x18, 0xe2,
- 0x69, 0x00, 0x6f, 0x04, 0x40, 0xda, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x6f, 0x02, 0x00, 0x09, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x07, 0x40, 0x00, 0x74, 0x6f, 0x6d, 0x79, 0x00, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0xe4, 0x63, 0x00, 0x66, 0x0c, 0x6e, 0x10, 0x74,
- 0x2a, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0x40, 0x08, 0x66, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x08,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfa, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x2f, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0x40, 0x09, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x64, 0x00, 0x73,
- 0x05, 0x74, 0x09, 0x40, 0x08, 0x67, 0x65, 0x00, 0x40, 0x3a, 0x68, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x47, 0x00, 0x60, 0xe2, 0x72, 0x00, 0x74, 0x05, 0x40, 0x5e, 0x67, 0x65,
- 0x00, 0x40, 0x59, 0x74, 0x65, 0x72, 0x00, 0xf8, 0x69, 0x00, 0x00, 0x6b,
- 0x29, 0x00, 0x6c, 0x72, 0x00, 0x6e, 0x7b, 0x00, 0x6f, 0xce, 0x00, 0x72,
- 0x0e, 0x01, 0x74, 0xcb, 0x01, 0x75, 0x1f, 0x02, 0xe1, 0x6c, 0x00, 0xe5,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x0b, 0x73, 0x14, 0x04, 0xc5,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x37, 0x01, 0x52, 0x40, 0x09, 0x70, 0x6f, 0x72, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x73, 0x04, 0x00,
- 0x06, 0x00, 0x37, 0xe3, 0x6d, 0x00, 0x70, 0x0d, 0x77, 0x21, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x06, 0x40, 0x00, 0x70, 0x6c, 0x65,
- 0x00, 0x40, 0x09, 0x73, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x41, 0x52, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe3,
- 0x67, 0x00, 0x73, 0x21, 0x74, 0x34, 0xe3, 0x65, 0x00, 0x69, 0x11, 0x79,
- 0x18, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x72, 0x08, 0x00, 0x7e, 0x40, 0x07,
- 0x61, 0x6b, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x15, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x55, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe5, 0x66,
- 0x00, 0x6b, 0x02, 0x6c, 0x14, 0x6e, 0x16, 0x72, 0x33, 0x00, 0x2c, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x2c, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x15, 0x00, 0x2c, 0xe4, 0x00, 0x00, 0x62, 0x02,
- 0x65, 0x08, 0x66, 0x0f, 0x00, 0x2c, 0x40, 0x09, 0x69, 0x6c, 0x6c, 0x00,
- 0x40, 0x09, 0x72, 0x69, 0x73, 0x6d, 0x00, 0x40, 0x06, 0x75, 0x6c, 0x00,
- 0x00, 0x2c, 0xe4, 0x61, 0x00, 0x65, 0x16, 0x72, 0x18, 0x74, 0x1d, 0xe1,
- 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x5e, 0x40,
- 0x08, 0x61, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x73, 0x17, 0x79,
- 0x8c, 0x01, 0xc1, 0xe2, 0x6e, 0x00, 0x76, 0x0c, 0xe2, 0x65, 0x00, 0x67,
- 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x3b, 0x40, 0x3b, 0x65, 0x00,
- 0xe4, 0x63, 0x00, 0x6d, 0x14, 0x70, 0x35, 0x77, 0x49, 0xe1, 0x61, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02,
- 0xdc, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x18, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x73, 0x08, 0x00, 0x07, 0x40, 0x37,
- 0x69, 0x6b, 0x65, 0x00, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x06, 0x40, 0x00,
- 0x70, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x73, 0x6f, 0x6e, 0x00, 0xe3, 0x65,
- 0x00, 0x6f, 0x05, 0x72, 0x15, 0x40, 0x07, 0x61, 0x72, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x06, 0x69, 0x74, 0x65, 0x72, 0x00, 0x01, 0x92, 0xe3,
- 0x00, 0x00, 0x6c, 0x02, 0x74, 0x26, 0x01, 0x07, 0xe2, 0x65, 0x00, 0x69,
- 0x13, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x67, 0x00, 0x74,
- 0x05, 0x40, 0x95, 0x68, 0x74, 0x00, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x79, 0x1e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x00, 0x01, 0x92, 0xe2,
- 0x73, 0x00, 0x74, 0x0b, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x09, 0x6c,
- 0x00, 0x00, 0x06, 0x00, 0x2c, 0xf6, 0x61, 0x00, 0x00, 0x65, 0x2a, 0x00,
- 0x69, 0x5c, 0x00, 0x6f, 0xfa, 0x00, 0x75, 0x0d, 0x01, 0x79, 0x26, 0x01,
- 0xe5, 0x69, 0x00, 0x6e, 0x04, 0x74, 0x08, 0x77, 0x0a, 0x79, 0x0e, 0x40,
- 0x95, 0x6e, 0x00, 0x40, 0x00, 0x67, 0x00, 0x00, 0x06, 0x40, 0x95, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06, 0x00, 0xd5, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x21, 0xe1,
- 0x64, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x10, 0x04, 0xc6, 0xe2,
- 0x61, 0x00, 0x72, 0x07, 0x40, 0x00, 0x67, 0x6c, 0x65, 0x64, 0x00, 0x00,
- 0x07, 0x40, 0x09, 0x68, 0x65, 0x65, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x1a, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x67, 0x00, 0x6e,
- 0x22, 0x74, 0x85, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x68, 0x07, 0x00, 0x06,
- 0x40, 0x00, 0x65, 0x64, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0xf4, 0xe3, 0x67, 0x00, 0x6b, 0x3b, 0x74, 0x51, 0xe6, 0x00, 0x00, 0x62,
- 0x02, 0x69, 0x11, 0x6c, 0x20, 0x74, 0x26, 0x79, 0x2c, 0x01, 0x2f, 0xe1,
- 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x6b, 0x05, 0x40, 0x09, 0x72, 0x64, 0x00,
- 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00, 0x40,
- 0x07, 0x69, 0x6d, 0x65, 0x00, 0x01, 0x15, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x02, 0xd3, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x05,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x7a, 0x02, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x63,
- 0x00, 0x67, 0x06, 0x75, 0x08, 0x40, 0x09, 0x6b, 0x65, 0x74, 0x00, 0x00,
- 0x08, 0x40, 0x95, 0x74, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x10, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0xc7, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x00, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0xda, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe5, 0x64, 0x00, 0x6d, 0x02,
- 0x6e, 0x12, 0x72, 0x22, 0x74, 0x5d, 0x00, 0x09, 0xe3, 0x65, 0x00, 0x6f,
- 0x02, 0x79, 0x07, 0x00, 0x5e, 0x40, 0x07, 0x6e, 0x69, 0x00, 0x00, 0x00,
- 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x06, 0x00, 0x60, 0xe6, 0x00, 0x00, 0x67, 0x02, 0x69, 0x06, 0x6e,
- 0x1c, 0x72, 0x1e, 0x74, 0x2c, 0x00, 0x09, 0x40, 0x07, 0x65, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x7a, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x00, 0x2c, 0xe4, 0x61, 0x00, 0x6e, 0x02, 0x74, 0x07, 0x75, 0x0c,
- 0x00, 0x00, 0x40, 0x09, 0x69, 0x6b, 0x00, 0x40, 0x55, 0x65, 0x72, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6d, 0x09, 0x77,
- 0x11, 0x00, 0xa1, 0x40, 0x09, 0x6c, 0x61, 0x73, 0x73, 0x00, 0x40, 0x08,
- 0x61, 0x73, 0x74, 0x65, 0x72, 0x00, 0x60, 0x09, 0x61, 0x72, 0x65, 0x00,
- 0x07, 0x00, 0xff, 0xff, 0xf3, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0x75,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x61, 0x00, 0x00, 0x65, 0xc2,
- 0x00, 0x69, 0x4a, 0x01, 0xe9, 0x62, 0x00, 0x64, 0x16, 0x6c, 0x22, 0x6d,
- 0x46, 0x6e, 0x4c, 0x72, 0x52, 0x73, 0x69, 0x74, 0x75, 0x77, 0x9d, 0xe2,
- 0x00, 0x00, 0x62, 0x02, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe3, 0x69, 0x00,
- 0x6c, 0x10, 0x6f, 0x19, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x63, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x93, 0x00, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x6f,
- 0x75, 0x73, 0x00, 0x40, 0x0b, 0x64, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0xc9, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0x60, 0xe3, 0x00, 0x00, 0x6e,
- 0x02, 0x74, 0x08, 0x02, 0x7b, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x0f, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00,
- 0x00, 0x00, 0x09, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x48, 0x6c,
- 0x72, 0xe3, 0x6b, 0x00, 0x6c, 0x20, 0x6d, 0x2b, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x79, 0x15, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x3b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xfa, 0x40,
- 0x07, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x67, 0x00, 0x7a, 0x12, 0xe1, 0x65, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xb2, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x72, 0x07, 0x04, 0xc8,
- 0x40, 0x08, 0x6f, 0x78, 0x00, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0x00, 0xe7, 0x62,
- 0x00, 0x64, 0x02, 0x66, 0x0d, 0x67, 0x12, 0x6e, 0x21, 0x72, 0x25, 0x73,
- 0x40, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x00, 0x66, 0x79, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x5e, 0x00, 0x00, 0x44, 0xc9,
- 0x74, 0x00, 0xe4, 0x65, 0x00, 0x6d, 0x02, 0x72, 0x0b, 0x74, 0x10, 0x00,
- 0x5e, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x93, 0x00, 0xf3, 0x40, 0x93,
- 0x65, 0x6c, 0x00, 0x00, 0x93, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x59, 0x00, 0xf3, 0x40, 0x00, 0x69, 0x72, 0x61, 0x63, 0x68,
- 0x61, 0x00, 0x40, 0x00, 0x68, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x64, 0xac, 0x05, 0x65, 0xb7, 0x05, 0x69, 0x66, 0x09, 0x6f, 0x62,
- 0x0b, 0x72, 0x66, 0x0e, 0x75, 0xbd, 0x13, 0x79, 0x96, 0x15, 0x00, 0x00,
- 0xc0, 0x62, 0x18, 0x33, 0x00, 0x97, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xaa,
- 0x00, 0xc5, 0x00, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0x85, 0x01, 0x9e,
- 0x01, 0x05, 0x02, 0x41, 0x02, 0x00, 0x00, 0xe5, 0x02, 0x00, 0x00, 0x20,
- 0x03, 0x25, 0x04, 0x30, 0x04, 0x8e, 0x05, 0xa4, 0x05, 0x00, 0x00, 0x00,
- 0x00, 0xa8, 0x05, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x69, 0x15, 0x6c, 0x39,
- 0x00, 0x86, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x40, 0x09, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x53, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x41, 0x52, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x03, 0x4a, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x79, 0x1b, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x04, 0x7d, 0xe2, 0x61, 0x00,
- 0x65, 0x0b, 0xe2, 0x6e, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x08, 0x65,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x37, 0xe2, 0x63, 0x00, 0x6b, 0x06,
- 0x40, 0x09, 0x61, 0x74, 0x6f, 0x00, 0x00, 0x2c, 0x40, 0x09, 0x69, 0x75,
- 0x6d, 0x00, 0xe1, 0x66, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06,
- 0x69, 0x0a, 0x00, 0xd5, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x66, 0x2c,
- 0x67, 0x35, 0x69, 0x47, 0x6e, 0x4c, 0x79, 0x6b, 0x01, 0x6b, 0xe4, 0x00,
- 0x00, 0x63, 0x02, 0x68, 0x13, 0x73, 0x19, 0x00, 0x06, 0xe2, 0x6f, 0x00,
- 0x72, 0x06, 0x40, 0x09, 0x61, 0x63, 0x68, 0x00, 0x40, 0x07, 0x61, 0x66,
- 0x74, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x74, 0x72,
- 0x75, 0x63, 0x6b, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x55, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0xf3, 0xe3, 0x64, 0x00,
- 0x6e, 0x0d, 0x72, 0x20, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7f, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06,
- 0x00, 0x2c, 0x40, 0x37, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x63, 0x02, 0x77, 0x08, 0x00, 0x06, 0x40, 0x09, 0x61,
- 0x73, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x09, 0x79, 0x00,
- 0x40, 0x06, 0x6c, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x68,
- 0x02, 0x6f, 0x0a, 0x00, 0x5e, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x65, 0x72,
- 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x13, 0x6b,
- 0x28, 0x6c, 0x3a, 0x77, 0x56, 0xe2, 0x63, 0x00, 0x67, 0x07, 0x40, 0x09,
- 0x74, 0x69, 0x74, 0x65, 0x00, 0x40, 0x09, 0x6d, 0x69, 0x74, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x6e, 0x08, 0x01, 0x6f, 0x40, 0x5e, 0x61,
- 0x74, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x04, 0xca, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x68, 0x06, 0x69, 0x0e,
- 0x04, 0xcb, 0x40, 0x00, 0x73, 0x00, 0x40, 0x08, 0x6f, 0x6c, 0x64, 0x65,
- 0x72, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x86, 0x61, 0x72, 0x74,
- 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04, 0x6d, 0x09, 0x70, 0x21, 0x40, 0x06,
- 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xc3, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x01, 0x5b, 0xe2, 0x64, 0x00, 0x72, 0x04, 0x40, 0x82, 0x65, 0x00, 0x00,
- 0x07, 0xe4, 0x63, 0x00, 0x64, 0x13, 0x6b, 0x95, 0x7a, 0x97, 0xe2, 0x65,
- 0x00, 0x68, 0x02, 0x01, 0xa7, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x04, 0xcc,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x62, 0x28,
- 0x65, 0x34, 0x69, 0x3d, 0x6f, 0x42, 0x70, 0x5a, 0x73, 0x6a, 0x04, 0xcd,
- 0xe2, 0x6c, 0x00, 0x72, 0x06, 0x40, 0x00, 0x6f, 0x6e, 0x65, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x7a, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x3a, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x02, 0x00, 0x09, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x66, 0x00, 0x75, 0x0f, 0xe1, 0x66, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x73, 0x68, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x70,
- 0x65, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x74, 0x69,
- 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x06, 0x61, 0x00, 0xe2, 0x68, 0x00,
- 0x6c, 0x2a, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x63, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x75, 0x06, 0x40, 0x00,
- 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xed, 0x00, 0x00, 0x62,
- 0x02, 0x63, 0x13, 0x64, 0x30, 0x65, 0x3e, 0x66, 0x47, 0x67, 0x57, 0x6b,
- 0x69, 0x6c, 0x76, 0x72, 0x98, 0x73, 0xaa, 0x74, 0xb2, 0x76, 0xd1, 0x00,
- 0xfe, 0xe2, 0x6f, 0x00, 0x75, 0x06, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00,
- 0x40, 0x08, 0x72, 0x73, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x79, 0x11, 0x00, 0x59, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe2,
- 0x6f, 0x00, 0x75, 0x04, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x07, 0x73, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe2, 0x69,
- 0x00, 0x72, 0x05, 0x40, 0x09, 0x73, 0x68, 0x00, 0x40, 0x00, 0x75, 0x69,
- 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x7a, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x04, 0xce, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x0b, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x00, 0x73, 0x00, 0x00,
- 0x09, 0xe3, 0x67, 0x00, 0x6e, 0x05, 0x74, 0x09, 0x40, 0x07, 0x68, 0x74,
- 0x00, 0x40, 0x06, 0x67, 0x00, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04,
- 0x79, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00,
- 0x60, 0x40, 0x00, 0x74, 0x72, 0x75, 0x63, 0x6b, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x6c, 0x06, 0x75, 0x12, 0x04, 0xcf, 0x40, 0x09, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x70, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x04, 0xd0, 0x40,
- 0x09, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x02, 0x00, 0x47,
- 0x40, 0x00, 0x73, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x65, 0x02, 0x00, 0x69,
- 0xbb, 0x00, 0x75, 0x11, 0x01, 0x00, 0x09, 0xe9, 0x00, 0x00, 0x63, 0x02,
- 0x64, 0x09, 0x68, 0x0b, 0x6c, 0x1c, 0x6d, 0x3f, 0x72, 0x5a, 0x73, 0x60,
- 0x77, 0xa0, 0x04, 0xd1, 0x40, 0x07, 0x72, 0x61, 0x66, 0x74, 0x00, 0x00,
- 0x37, 0xe1, 0x6f, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x04, 0x40, 0x07, 0x64,
- 0x00, 0x40, 0x09, 0x73, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x13, 0x79,
- 0x1a, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x69, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f, 0x6f,
- 0x6d, 0x00, 0xe3, 0x69, 0x00, 0x6d, 0x05, 0x77, 0x26, 0x40, 0x00, 0x64,
- 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x18, 0xe1, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x73, 0x08, 0x00, 0x07, 0x40, 0x00, 0x69, 0x6b, 0x65,
- 0x00, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x69, 0x64, 0x65, 0x00,
- 0xe3, 0x63, 0x00, 0x6f, 0x0d, 0x73, 0x34, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x6d, 0x13, 0x03, 0xa2, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x07, 0x00, 0x07, 0x40, 0x08, 0x61, 0x73, 0x74, 0x65, 0x72, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x06, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x61,
- 0x6e, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x05, 0x72, 0x19, 0x73, 0x1d, 0x74,
- 0x1f, 0x40, 0x07, 0x72, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x74,
- 0x08, 0x00, 0x06, 0x40, 0x00, 0x71, 0x75, 0x65, 0x00, 0x40, 0x09, 0x74,
- 0x65, 0x00, 0x40, 0x09, 0x65, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x6f,
- 0x02, 0x00, 0x09, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x00, 0x6c, 0x79, 0x00, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0xd2, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x5e, 0x65, 0x00, 0x00, 0xfe, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x00, 0xfc, 0x61, 0x00,
- 0x00, 0x65, 0xcc, 0x00, 0x67, 0x65, 0x01, 0x69, 0x7f, 0x01, 0x6c, 0x83,
- 0x01, 0x6d, 0x89, 0x01, 0x6e, 0xae, 0x01, 0x70, 0xfd, 0x01, 0x72, 0x96,
- 0x02, 0x74, 0x3a, 0x03, 0x76, 0x61, 0x03, 0x77, 0x69, 0x03, 0xe4, 0x64,
- 0x00, 0x6b, 0x32, 0x6c, 0x40, 0x6d, 0x64, 0xe4, 0x00, 0x00, 0x66, 0x02,
- 0x69, 0x18, 0x79, 0x27, 0x00, 0x06, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x37, 0x79,
- 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x02, 0x84, 0xe2, 0x00, 0x00,
- 0x68, 0x02, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x75, 0x73, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x04, 0xd3, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x79, 0x11, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe9,
- 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x66, 0x0c, 0x69, 0x23, 0x70, 0x2a,
- 0x72, 0x30, 0x73, 0x44, 0x79, 0x4a, 0x01, 0x5b, 0x40, 0x09, 0x6f, 0x61,
- 0x74, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x75, 0x6e, 0x6b, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3f, 0x40, 0x2f,
- 0x72, 0x00, 0x40, 0x09, 0x68, 0x69, 0x70, 0x00, 0x01, 0x92, 0xe4, 0x64,
- 0x00, 0x6c, 0x02, 0x70, 0x3d, 0x72, 0x6b, 0x00, 0x06, 0xe5, 0x00, 0x00,
- 0x69, 0x02, 0x6d, 0x09, 0x77, 0x10, 0x79, 0x24, 0x00, 0x2c, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08, 0x61, 0x6b, 0x65, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00,
- 0x73, 0x04, 0x40, 0x06, 0x72, 0x00, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x96, 0x40, 0x06, 0x72, 0x64, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x6c, 0x06, 0x6e, 0x1f, 0x04, 0xd4, 0x40, 0xed, 0x6e, 0x00, 0xe1,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6a, 0x09, 0x00, 0x09, 0x40,
- 0x09, 0x68, 0x61, 0x73, 0x65, 0x00, 0x40, 0x06, 0x61, 0x63, 0x6b, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x07, 0x73, 0x0c, 0x03, 0x18, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69,
- 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40, 0x06, 0x6e,
- 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02,
- 0x6d, 0x08, 0x77, 0x16, 0x00, 0x09, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0xe3, 0x63, 0x00, 0x6f,
- 0x0b, 0x74, 0x36, 0xe2, 0x68, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x59,
- 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x73, 0x1f, 0x00, 0x06, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x04, 0x79, 0x08, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00,
- 0x63, 0x00, 0x00, 0x07, 0x40, 0x00, 0x69, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6f, 0x06, 0x20, 0x09, 0x08, 0x00, 0xff, 0xff, 0x40, 0x00, 0x72, 0x69,
- 0x61, 0x6e, 0x00, 0xe9, 0x00, 0x00, 0x62, 0x02, 0x63, 0x0b, 0x64, 0x23,
- 0x66, 0x35, 0x6c, 0x3d, 0x6d, 0x45, 0x70, 0x55, 0x73, 0x76, 0x01, 0x89,
- 0x40, 0x06, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x00, 0xe1, 0x68, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x64, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40, 0x06, 0x67, 0x68, 0x74,
- 0x65, 0x72, 0x00, 0x40, 0x06, 0x61, 0x74, 0x68, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x61, 0x64, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x09, 0x40, 0x06, 0x68, 0x65, 0x72, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x07, 0x69, 0x10, 0x40, 0x06, 0x72, 0x65, 0x6e, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x06,
- 0x6e, 0x67, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x07, 0x40, 0x09, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x6e, 0x00,
- 0xe6, 0x65, 0x00, 0x69, 0x3d, 0x6c, 0x65, 0x6e, 0x6b, 0x6f, 0x7e, 0x74,
- 0x8f, 0xe1, 0x6f, 0x00, 0xe4, 0x00, 0x00, 0x70, 0x02, 0x73, 0x0a, 0x74,
- 0x1e, 0x00, 0x06, 0x40, 0x00, 0x68, 0x6f, 0x6e, 0x69, 0x63, 0x00, 0xe1,
- 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0xe1, 0x79, 0x00, 0xe1, 0x70,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40, 0x00, 0x63, 0x61,
- 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x00,
- 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x75, 0x08, 0x03, 0x16, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00,
- 0x40, 0x00, 0x6f, 0x72, 0x6f, 0x75, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x68,
- 0x02, 0x73, 0x0b, 0x74, 0x10, 0x00, 0x08, 0x40, 0x09, 0x6f, 0x73, 0x63,
- 0x6f, 0x70, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x65, 0x64, 0x6f, 0x72, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x55, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x73, 0x07, 0x00, 0x59, 0x40, 0x09, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x68, 0x69, 0x70, 0x00, 0xf9, 0x63, 0x00, 0x00, 0x66, 0x42, 0x00, 0x67,
- 0x77, 0x00, 0x6c, 0xa0, 0x00, 0x6d, 0xf5, 0x00, 0x6e, 0x1d, 0x01, 0x70,
- 0x63, 0x01, 0x72, 0xa1, 0x01, 0x74, 0xc1, 0x01, 0xe1, 0x6b, 0x00, 0xe7,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x15, 0x70, 0x25, 0x75, 0x2a,
- 0x79, 0x2e, 0x01, 0x67, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e,
- 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x62, 0x00, 0x72, 0x06, 0x40, 0x06, 0x61, 0x63, 0x6b,
- 0x00, 0x00, 0x09, 0x40, 0x09, 0x69, 0x6e, 0x00, 0x40, 0x09, 0x70, 0x00,
- 0x03, 0x0e, 0xe2, 0x66, 0x00, 0x6c, 0x24, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x6e, 0x17, 0x04, 0xd4, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x02, 0x2d, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x04, 0xd0, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x61,
- 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0xe2, 0x63, 0x00, 0x7a, 0x02, 0x00, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b,
- 0xe3, 0x65, 0x00, 0x6c, 0x0c, 0x74, 0x43, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x06, 0x40, 0x06, 0x74, 0x6f, 0x00, 0xe5, 0x00, 0x00, 0x27, 0x02,
- 0x62, 0x06, 0x65, 0x22, 0x6e, 0x26, 0x04, 0xd5, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x12, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x00, 0x72, 0x6e, 0x00, 0x40, 0x00, 0x72, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xb1, 0x40, 0x3b, 0x64,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x15,
- 0x75, 0x17, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x06, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x01, 0xf4, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0xe3, 0x67, 0x00, 0x6b, 0x27, 0x74, 0x3d,
- 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x72, 0x15, 0x79, 0x1a, 0x01,
- 0x74, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x79,
- 0x00, 0x00, 0xf4, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x07, 0x79, 0x0b,
- 0x01, 0x74, 0x40, 0x06, 0x75, 0x67, 0x00, 0x40, 0x07, 0x72, 0x00, 0x00,
- 0xf3, 0x00, 0x95, 0xe3, 0x65, 0x00, 0x70, 0x13, 0x75, 0x22, 0xe1, 0x6e,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x08, 0x61, 0x72, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x5e, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x26,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09,
- 0xe3, 0x65, 0x00, 0x69, 0x09, 0x75, 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x06, 0x43, 0x6c, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x70,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02,
- 0x65, 0x06, 0x69, 0x0b, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07,
- 0x72, 0x79, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xff, 0x61, 0x00, 0x00,
- 0x63, 0x04, 0x00, 0x64, 0xa5, 0x00, 0x67, 0xc2, 0x00, 0x69, 0xc7, 0x00,
- 0x6b, 0xdc, 0x00, 0x6c, 0xe8, 0x00, 0x6d, 0x13, 0x01, 0x6e, 0x37, 0x01,
- 0x6f, 0x94, 0x01, 0x70, 0xa7, 0x01, 0x72, 0x06, 0x02, 0x75, 0x92, 0x02,
- 0x76, 0xb1, 0x02, 0x77, 0xc1, 0x02, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x68,
- 0x00, 0x6b, 0x08, 0x40, 0x00, 0x61, 0x73, 0x74, 0x69, 0x63, 0x00, 0xea,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x62, 0x0b, 0x68, 0x2b, 0x69, 0x33,
- 0x70, 0x57, 0x72, 0x65, 0x74, 0x6b, 0x79, 0x73, 0x00, 0x61, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x5e, 0x64, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x07, 0x40, 0x09, 0x65, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x6b,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0xe3,
- 0x6c, 0x00, 0x6e, 0x04, 0x73, 0x19, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x67, 0x0e, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x74, 0x65, 0x00, 0x00, 0x06, 0x40, 0x08, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x05, 0x40, 0x82, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6d, 0x00, 0x40, 0x07, 0x61, 0x6b, 0x69,
- 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0xf4, 0x40, 0x09,
- 0x72, 0x64, 0x00, 0xe1, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79,
- 0x11, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0x40, 0x09, 0x69, 0x65,
- 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00,
- 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe3, 0x65,
- 0x00, 0x69, 0x09, 0x6f, 0x20, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x06,
- 0x00, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07,
- 0x01, 0xb4, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x70, 0x1d, 0xe1, 0x63,
- 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x73,
- 0x0c, 0x03, 0xa2, 0x40, 0x06, 0x63, 0x68, 0x65, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x00, 0x00, 0x00, 0x95, 0xe4, 0x65, 0x00, 0x69, 0x33, 0x6b, 0x42,
- 0x79, 0x52, 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x09, 0x77, 0x0b, 0x00,
- 0x7e, 0x40, 0x09, 0x61, 0x73, 0x6f, 0x6e, 0x00, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x6f, 0x15, 0xe3, 0x6c, 0x00, 0x72, 0x04, 0x73, 0x08, 0x40, 0xad,
- 0x6c, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x68, 0x65, 0x64, 0x00,
- 0x40, 0x07, 0x72, 0x6b, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x06, 0x40, 0x00, 0x72, 0x65, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x01, 0x3b, 0xe4, 0x64, 0x00, 0x67, 0x02, 0x6c, 0x06, 0x70, 0x08, 0x00,
- 0x00, 0x40, 0x09, 0x65, 0x00, 0x00, 0x06, 0x00, 0x95, 0xe8, 0x00, 0x00,
- 0x27, 0x02, 0x63, 0x06, 0x67, 0x0c, 0x6c, 0x11, 0x6f, 0x18, 0x70, 0x1e,
- 0x77, 0x47, 0x01, 0x43, 0x40, 0x00, 0x73, 0x00, 0x40, 0x06, 0x6f, 0x63,
- 0x6b, 0x00, 0x40, 0x06, 0x61, 0x70, 0x00, 0x40, 0x09, 0x69, 0x67, 0x68,
- 0x74, 0x00, 0x40, 0x09, 0x76, 0x65, 0x72, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x0e, 0x69, 0x17, 0x6c, 0x1c, 0xe2, 0x62, 0x00, 0x67, 0x05, 0x40, 0x37,
- 0x6c, 0x65, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x37, 0x00, 0x95, 0x40, 0x37, 0x6e, 0x67, 0x00, 0x40, 0x5e, 0x65,
- 0x00, 0x40, 0x09, 0x61, 0x74, 0x63, 0x68, 0x00, 0xe5, 0x61, 0x00, 0x65,
- 0x05, 0x6b, 0x34, 0x6d, 0x36, 0x79, 0x50, 0x40, 0x07, 0x67, 0x65, 0x00,
- 0xe6, 0x00, 0x00, 0x27, 0x02, 0x66, 0x06, 0x68, 0x0d, 0x6b, 0x14, 0x72,
- 0x1c, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x72, 0x6f, 0x6e,
- 0x74, 0x00, 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x06, 0x65,
- 0x65, 0x70, 0x65, 0x72, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6d, 0x00, 0x00,
- 0x06, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x95, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x15, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x74, 0x13, 0x00, 0x1a,
- 0xe1, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x72, 0x64,
- 0x00, 0x40, 0x06, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x70, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe3,
- 0x00, 0x00, 0x68, 0x02, 0x6e, 0x0b, 0x04, 0xd6, 0x40, 0x00, 0x65, 0x61,
- 0x72, 0x74, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0x40, 0x06, 0x69,
- 0x70, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x72, 0xe2, 0x67,
- 0x00, 0x77, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00,
- 0xf6, 0x61, 0x00, 0x00, 0x65, 0xc6, 0x01, 0x69, 0xdd, 0x02, 0x6f, 0x08,
- 0x04, 0x75, 0xb3, 0x04, 0x79, 0x3b, 0x05, 0xf9, 0x64, 0x00, 0x00, 0x66,
- 0x12, 0x00, 0x67, 0x16, 0x00, 0x69, 0x2c, 0x00, 0x6e, 0xbc, 0x00, 0x70,
- 0x04, 0x01, 0x74, 0x27, 0x01, 0x77, 0x9a, 0x01, 0x79, 0xa8, 0x01, 0xe1,
- 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x82, 0x65, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x01, 0x4b, 0x00, 0x07, 0x00, 0x60, 0xe3, 0x67, 0x00, 0x6e, 0x5a,
- 0x74, 0x6b, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe6, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x08, 0x66, 0x1d, 0x6e, 0x3c, 0x77, 0x42, 0x02, 0x38, 0x40,
- 0x06, 0x77, 0x61, 0x79, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x05, 0x40, 0x06,
- 0x67, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0x2d, 0x40, 0x07,
- 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x77, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x04, 0xd7, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x00, 0x61, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x27,
- 0x02, 0x65, 0x06, 0x04, 0xd8, 0x40, 0x00, 0x73, 0x00, 0x40, 0x65, 0x72,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6a, 0x06, 0x6c, 0x0e, 0x03, 0xb4,
- 0x40, 0xed, 0x6e, 0x00, 0x40, 0x93, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x00,
- 0x40, 0x00, 0x61, 0x63, 0x65, 0x64, 0x00, 0xe2, 0x64, 0x00, 0x67, 0x02,
- 0x00, 0x47, 0xe3, 0x65, 0x00, 0x6c, 0x11, 0x75, 0x25, 0xe3, 0x00, 0x00,
- 0x6e, 0x02, 0x72, 0x08, 0x04, 0xd9, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x72, 0x08,
- 0x00, 0x3f, 0x40, 0x06, 0x6f, 0x6c, 0x64, 0x00, 0x00, 0x07, 0xe1, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02,
- 0x6c, 0x06, 0x70, 0x0c, 0x01, 0x43, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x0c, 0x69,
- 0x2e, 0x6f, 0x45, 0x75, 0x5f, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x00,
- 0x40, 0x06, 0x65, 0x6d, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x18, 0xe2, 0x63, 0x00, 0x73, 0x0f, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73,
- 0x06, 0x00, 0x08, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x06, 0x74,
- 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x57, 0xe1, 0x73, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x95, 0x40, 0x06, 0x65, 0x72,
- 0x72, 0x79, 0x00, 0x00, 0x95, 0xf7, 0x61, 0x00, 0x00, 0x65, 0x27, 0x00,
- 0x6e, 0x5b, 0x00, 0x70, 0x95, 0x00, 0x73, 0xc5, 0x00, 0x74, 0xda, 0x00,
- 0x77, 0xf8, 0x00, 0xe2, 0x6b, 0x00, 0x6d, 0x0f, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x79, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x00, 0x60, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x3a, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00,
- 0x63, 0x02, 0x6c, 0x07, 0x77, 0x17, 0x00, 0x09, 0x40, 0x09, 0x61, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x08, 0x6d, 0x70, 0x00, 0x40,
- 0x06, 0x67, 0x68, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x07, 0x40, 0x06,
- 0x6c, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x00, 0x73, 0x65, 0x00, 0xe2, 0x67,
- 0x00, 0x75, 0x1f, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x73, 0x10, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x4b, 0x40, 0x09, 0x72, 0x00, 0x00, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x1a, 0xe1,
- 0x6f, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x04, 0x75, 0x06, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x07, 0x79, 0x63, 0x69, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x66, 0x06, 0x00, 0x47, 0x40, 0x37, 0x64, 0x00,
- 0x40, 0x00, 0x75, 0x6c, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe4,
- 0x00, 0x00, 0x65, 0x02, 0x6d, 0x06, 0x79, 0x0d, 0x01, 0xb0, 0x40, 0x2f,
- 0x72, 0x00, 0x40, 0x00, 0x61, 0x72, 0x6b, 0x73, 0x00, 0x00, 0x60, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x04, 0xda, 0x00, 0x00, 0xf8, 0x61, 0x00, 0x00,
- 0x63, 0x19, 0x00, 0x64, 0x37, 0x00, 0x66, 0x53, 0x00, 0x6b, 0x57, 0x00,
- 0x6e, 0x95, 0x00, 0x70, 0xbe, 0x00, 0x76, 0x06, 0x01, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x74, 0x04, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe2, 0x6b,
- 0x00, 0x74, 0x05, 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x6e,
- 0x02, 0x75, 0x08, 0x00, 0xe0, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x06, 0x72, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x65, 0x05, 0x40, 0x00, 0x65,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x7f, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b, 0x40, 0x07, 0x65, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x34, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6f, 0x24,
- 0x72, 0x29, 0x04, 0xdb, 0xe2, 0x6f, 0x00, 0x72, 0x06, 0x40, 0x00, 0x75,
- 0x6e, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6b, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x75, 0x74, 0x00, 0x00, 0x07, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0xe1, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x14,
- 0x79, 0x1b, 0x00, 0xe7, 0xe2, 0x6e, 0x00, 0x72, 0x0b, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe6, 0x00, 0x00, 0x65, 0x02,
- 0x6c, 0x0b, 0x70, 0x11, 0x74, 0x24, 0x79, 0x39, 0x00, 0x95, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x67,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3c, 0x00, 0x00, 0xe7, 0x62, 0x00, 0x64, 0x1e,
- 0x6b, 0x22, 0x6c, 0x26, 0x6e, 0x34, 0x70, 0x6a, 0x76, 0x98, 0xe2, 0x65,
- 0x00, 0x6f, 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0x40, 0x00, 0x63, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x82, 0x65, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07,
- 0x72, 0x00, 0xe2, 0x67, 0x00, 0x74, 0x2b, 0xe5, 0x00, 0x00, 0x62, 0x02,
- 0x68, 0x07, 0x6d, 0x0d, 0x72, 0x1a, 0x00, 0xda, 0x40, 0x09, 0x6f, 0x78,
- 0x00, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x08, 0x6f, 0x6f,
- 0x6d, 0x00, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x68,
- 0x02, 0x70, 0x0d, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x11, 0x40,
- 0x00, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00,
- 0x40, 0x00, 0x67, 0x00, 0x01, 0x3b, 0x40, 0x00, 0x65, 0x00, 0xe6, 0x63,
- 0x00, 0x64, 0x3b, 0x67, 0x40, 0x6d, 0x46, 0x6e, 0x62, 0x74, 0x66, 0xe2,
- 0x6b, 0x00, 0x74, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00,
- 0x09, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x16, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x08, 0xe3, 0x00, 0x00, 0x27, 0x02,
- 0x64, 0x06, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x00, 0x37, 0x40, 0x06,
- 0x65, 0x6c, 0x00, 0x40, 0x82, 0x67, 0x6c, 0x65, 0x00, 0xe3, 0x00, 0x00,
- 0x6d, 0x02, 0x70, 0x10, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x74,
- 0x00, 0x41, 0x84, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x07, 0x63, 0x68, 0x6e, 0x69, 0x6e, 0x65, 0x00, 0xfa,
- 0x62, 0x00, 0x00, 0x63, 0x39, 0x00, 0x64, 0x4e, 0x00, 0x66, 0xbf, 0x00,
- 0x6c, 0xe2, 0x00, 0x6d, 0xfb, 0x00, 0x6e, 0x18, 0x01, 0x70, 0x50, 0x01,
- 0x72, 0x85, 0x01, 0x74, 0xa6, 0x01, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x09, 0xe5, 0x65, 0x00, 0x69, 0x04, 0x6c, 0x09, 0x6f, 0x12, 0x79, 0x25,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xe0, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0xf3, 0xe2, 0x63, 0x00, 0x6b, 0x0e, 0xe1, 0x6f, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x2f, 0x40, 0x00, 0x73, 0x00, 0x00, 0x37,
- 0xe7, 0x00, 0x00, 0x62, 0x02, 0x64, 0x08, 0x65, 0x16, 0x69, 0x29, 0x6c,
- 0x53, 0x79, 0x57, 0x00, 0x86, 0x40, 0x09, 0x6f, 0x6f, 0x6b, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x06, 0x40, 0x08, 0x68, 0x69, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x0e, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x37, 0x40,
- 0x00, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x09, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0xf3, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00,
- 0x4b, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x66, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x17, 0x00, 0x95, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x00, 0x07, 0x01, 0x15, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x66,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x03, 0xd9, 0xe2, 0x62, 0x00, 0x70, 0x0f, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x95, 0x00, 0x60, 0xe5, 0x00,
- 0x00, 0x67, 0x02, 0x6b, 0x04, 0x6e, 0x06, 0x74, 0x19, 0x00, 0x08, 0x00,
- 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x08, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x95, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x1b, 0x6f,
- 0x2a, 0xe2, 0x66, 0x00, 0x6e, 0x0f, 0xe2, 0x61, 0x00, 0x79, 0x08, 0x40,
- 0x07, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0x40, 0x3b, 0x64,
- 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x01, 0xa3, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2,
- 0x64, 0x00, 0x67, 0x16, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x01, 0x3b, 0x40, 0x06, 0x65, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7,
- 0x40, 0x07, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x4e, 0x70,
- 0x60, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x0b, 0x75, 0x41, 0xe2, 0x00,
- 0x00, 0x27, 0x02, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x00, 0x00,
- 0x73, 0x02, 0x7a, 0x2b, 0x00, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x0d, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0x40, 0x09, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xb2, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x74, 0x69, 0x63, 0x00, 0xc0, 0x61, 0x1a, 0x37, 0x00,
- 0x59, 0x00, 0x3f, 0x06, 0x01, 0x07, 0x22, 0x07, 0x38, 0x07, 0xd4, 0x07,
- 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x9b, 0x08, 0xa3, 0x08, 0x4c, 0x09,
- 0xf4, 0x09, 0x00, 0x00, 0x7a, 0x0b, 0x00, 0x00, 0x23, 0x10, 0x44, 0x12,
- 0xf3, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x09, 0x13, 0xe2, 0x73, 0x00, 0x76, 0x06, 0x40, 0x84, 0x69, 0x6f, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01,
- 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x66, 0x00, 0x88, 0x00, 0x1e,
- 0x01, 0x47, 0x01, 0x4f, 0x01, 0x64, 0x01, 0x6b, 0x01, 0x00, 0x00, 0x88,
- 0x01, 0x00, 0x00, 0xd9, 0x01, 0x33, 0x02, 0xcf, 0x02, 0xd7, 0x02, 0x14,
- 0x03, 0x00, 0x00, 0x52, 0x03, 0x5b, 0x03, 0xe5, 0x04, 0x87, 0x05, 0xa9,
- 0x05, 0xdb, 0x05, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x05, 0x00, 0x06, 0xe4,
- 0x6c, 0x00, 0x71, 0x07, 0x72, 0x0c, 0x74, 0x1b, 0x40, 0x09, 0x74, 0x65,
- 0x72, 0x6e, 0x00, 0x40, 0x00, 0x75, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x65,
- 0x06, 0x40, 0x00, 0x74, 0x69, 0x63, 0x00, 0x40, 0x09, 0x61, 0x00, 0x40,
- 0x00, 0x6f, 0x6d, 0x69, 0x63, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x09, 0x69,
- 0x0d, 0x72, 0x12, 0x40, 0x06, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x61,
- 0x6e, 0x63, 0x68, 0x00, 0xe4, 0x61, 0x00, 0x6c, 0x09, 0x6f, 0x0f, 0x75,
- 0x78, 0x40, 0x06, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x00, 0x40, 0x00,
- 0x61, 0x73, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x13, 0xe2, 0x6d, 0x00,
- 0x70, 0x08, 0x40, 0x06, 0x69, 0x74, 0x74, 0x65, 0x65, 0x00, 0x40, 0x06,
- 0x61, 0x63, 0x74, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x1c, 0xe1, 0x63, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x04, 0xdc, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x69, 0x00, 0x72, 0x17, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x47, 0x40, 0x09, 0x72,
- 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x07, 0x40, 0x09, 0x74, 0x75, 0x72, 0x65,
- 0x00, 0x40, 0x3b, 0x61, 0x6e, 0x65, 0x6f, 0x75, 0x73, 0x00, 0xe3, 0x69,
- 0x00, 0x6f, 0x15, 0x75, 0x1e, 0xe1, 0x76, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x64, 0x00, 0x73, 0x04, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x06, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x6d, 0x69, 0x6e, 0x61, 0x6e, 0x74, 0x00, 0x40,
- 0x3a, 0x65, 0x00, 0x40, 0x08, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x72, 0x07, 0x40, 0x06, 0x6d, 0x69, 0x6c, 0x79, 0x00, 0x40,
- 0x00, 0x65, 0x65, 0x7a, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72, 0x6f,
- 0x75, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x12, 0xe1, 0x61, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x04, 0xdd, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x6d, 0x61, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x6f, 0x24, 0x75, 0x29, 0x00, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x6d, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3b,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x0b, 0x69, 0x6e, 0x00, 0xe2, 0x67,
- 0x00, 0x6e, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x63,
- 0x74, 0x69, 0x76, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x17, 0xe2, 0x61,
- 0x00, 0x74, 0x05, 0x40, 0x82, 0x73, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00,
- 0x6d, 0x0a, 0x6e, 0x30, 0x40, 0x08, 0x75, 0x74, 0x65, 0x6e, 0x61, 0x6e,
- 0x74, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0f, 0x69, 0x11, 0xe1, 0x74, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0x03, 0xbc, 0xe2, 0x6e, 0x00, 0x74, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00,
- 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x67, 0x75, 0x61, 0x6c, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x1e, 0x69, 0x4a, 0xe1, 0x72, 0x00, 0xe2, 0x67, 0x00,
- 0x69, 0x07, 0x40, 0x00, 0x69, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xeb, 0x00, 0x07,
- 0xe1, 0x72, 0x00, 0xe2, 0x67, 0x00, 0x73, 0x0f, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x0b, 0x40, 0x07, 0x63, 0x65, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0xe2, 0x62, 0x00, 0x6f, 0x05, 0x40,
- 0x09, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe3, 0x63, 0x00, 0x73,
- 0x0b, 0x74, 0x2a, 0x40, 0x00, 0x72, 0x6f, 0x73, 0x63, 0x6f, 0x70, 0x69,
- 0x63, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x76, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x77, 0x00, 0x00, 0x40, 0x77, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x62,
- 0x00, 0x64, 0x07, 0x6e, 0x25, 0x40, 0x00, 0x69, 0x74, 0x61, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02,
- 0xa4, 0x40, 0x53, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x5b, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x6c,
- 0x0a, 0x6f, 0x0f, 0x72, 0x15, 0x40, 0x00, 0x72, 0x61, 0x67, 0x72, 0x61,
- 0x70, 0x68, 0x00, 0x40, 0x09, 0x6f, 0x74, 0x00, 0x40, 0x59, 0x65, 0x6e,
- 0x61, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6d, 0x65, 0x00,
- 0xe2, 0x66, 0x00, 0x67, 0x0b, 0x40, 0x06, 0x65, 0x73, 0x73, 0x69, 0x6f,
- 0x6e, 0x61, 0x6c, 0x00, 0x40, 0x08, 0x72, 0x61, 0x6d, 0x00, 0x40, 0x06,
- 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x00, 0xf8, 0x63, 0x00, 0x00, 0x65,
- 0x26, 0x00, 0x69, 0x56, 0x00, 0x6f, 0xa9, 0x00, 0x70, 0xb7, 0x00, 0x74,
- 0xc8, 0x00, 0x75, 0x50, 0x01, 0x79, 0x6a, 0x01, 0xe1, 0x72, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x62, 0x00, 0x70, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x04, 0xde, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe4, 0x63,
- 0x00, 0x71, 0x07, 0x72, 0x0e, 0x74, 0x25, 0x40, 0x09, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x40, 0x3b, 0x75, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x76, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x00, 0x06, 0xe2, 0x64,
- 0x00, 0x73, 0x3e, 0xe3, 0x65, 0x00, 0x69, 0x0c, 0x79, 0x35, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x0b, 0x40, 0x07, 0x63, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x7a, 0x0f, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40,
- 0x00, 0x74, 0x79, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x7a, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x69, 0x00,
- 0x6e, 0x04, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x05, 0x40, 0x00, 0x63, 0x65, 0x00, 0x40, 0x07, 0x63,
- 0x69, 0x65, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x42, 0x72, 0x62, 0xe2,
- 0x6e, 0x00, 0x74, 0x37, 0xe3, 0x63, 0x00, 0x64, 0x04, 0x74, 0x0a, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x00, 0x61, 0x72, 0x64, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x61, 0x00, 0x76, 0x1a, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00, 0x5c,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x39,
- 0x00, 0x37, 0x42, 0xbc, 0x6f, 0x6e, 0x00, 0x40, 0x56, 0x65, 0x00, 0x40,
- 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe2,
- 0x65, 0x00, 0x74, 0x09, 0x60, 0x09, 0x6e, 0x74, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x03, 0x14, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe2, 0x61, 0x00, 0x75, 0x12, 0xe1, 0x74, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x02, 0x75, 0x04, 0x00, 0x00, 0x00, 0x09, 0x40, 0x07, 0x6d, 0x00,
- 0x40, 0x06, 0x63, 0x74, 0x75, 0x72, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x72,
- 0x0e, 0xe2, 0x65, 0x00, 0x70, 0x02, 0x00, 0x3a, 0x40, 0x00, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x66, 0x61, 0x63, 0x65, 0x00, 0x40, 0x06,
- 0x73, 0x74, 0x65, 0x6d, 0x00, 0xe5, 0x65, 0x00, 0x69, 0x39, 0x6c, 0x3f,
- 0x6f, 0x51, 0x72, 0x60, 0xe4, 0x65, 0x00, 0x6e, 0x04, 0x72, 0x19, 0x78,
- 0x2c, 0x40, 0x06, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x64, 0x0e, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x06,
- 0x00, 0x7a, 0xe2, 0x66, 0x00, 0x72, 0x06, 0x40, 0x06, 0x75, 0x67, 0x65,
- 0x00, 0x40, 0x00, 0x61, 0x6e, 0x65, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0x40, 0x5e, 0x74, 0x6c, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0b,
- 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x60, 0x40, 0x06, 0x79, 0x00, 0x00,
- 0x00, 0xe2, 0x70, 0x00, 0x74, 0x05, 0x40, 0x06, 0x69, 0x63, 0x00, 0x40,
- 0x93, 0x61, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x1a, 0xe2, 0x63, 0x00,
- 0x68, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xad,
- 0x40, 0x06, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x64, 0x00, 0xe1,
- 0x70, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x73, 0x06, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x07, 0xe1,
- 0x72, 0x00, 0xe1, 0x62, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x11,
- 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x06, 0x74, 0x65, 0x00, 0x40, 0x07, 0x61, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x6e, 0x00, 0x72, 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x73, 0x00, 0x74, 0x1c, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x02, 0x0c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x7a, 0x40,
- 0x09, 0x61, 0x79, 0x00, 0x40, 0x00, 0x65, 0x72, 0x6f, 0x00, 0xe5, 0x63,
- 0x00, 0x68, 0x85, 0x6b, 0x92, 0x72, 0xab, 0x74, 0xb1, 0xe4, 0x65, 0x00,
- 0x69, 0x2d, 0x6f, 0x43, 0x75, 0x50, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40,
- 0x0b, 0x64, 0x00, 0xe1, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x69,
- 0x07, 0x6f, 0x14, 0x01, 0xe4, 0x40, 0x36, 0x75, 0x6c, 0x00, 0xe2, 0x6f,
- 0x00, 0x76, 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x3b, 0x65, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x93, 0x40, 0x07, 0x61, 0x73,
- 0x68, 0x00, 0xe3, 0x62, 0x00, 0x6c, 0x0b, 0x6d, 0x21, 0xe2, 0x69, 0x00,
- 0x75, 0x02, 0x00, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x40, 0x0b, 0x62, 0x00, 0xe2, 0x00,
- 0x00, 0x6c, 0x02, 0x00, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x6c, 0x06, 0x00, 0xfe, 0x40, 0xec, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x04, 0xd0, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x07, 0x6f, 0x73, 0x65, 0x00, 0x40, 0x2c, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x64, 0x00, 0x73, 0x13, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x60, 0xe3, 0x00, 0x00,
- 0x64, 0x02, 0x74, 0x06, 0x00, 0x3a, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x66, 0x00, 0xe5, 0x65,
- 0x00, 0x69, 0x1d, 0x6f, 0x48, 0x72, 0x5d, 0x75, 0x7f, 0xe1, 0x72, 0x00,
- 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x04, 0x1f, 0x40,
- 0x07, 0x6e, 0x63, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe2, 0x63, 0x00, 0x78, 0x18, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x3a, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x53, 0x79, 0x00, 0x00, 0x5c, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x47, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x04, 0x69, 0x10, 0x40, 0x09, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x06, 0x74, 0x65, 0x00, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x67, 0x2d,
- 0xe1, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x11, 0x70, 0x17,
- 0x79, 0x1d, 0x00, 0x95, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x6e,
- 0x65, 0x00, 0x40, 0x0b, 0x61, 0x74, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x09, 0x6c, 0x75, 0x6d, 0x00, 0x00, 0xf3, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x04,
- 0xdf, 0xe3, 0x62, 0x00, 0x6f, 0x10, 0x76, 0x14, 0xe2, 0x69, 0x00, 0x6c,
- 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x00, 0x65, 0x00,
- 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x11, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x63,
- 0x1f, 0x65, 0x25, 0x69, 0x2e, 0x6f, 0x33, 0x00, 0xb0, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0xdb, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x37, 0x40, 0x06, 0x61, 0x73, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x00, 0x06, 0x00, 0x37, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x72, 0x00, 0x40, 0x07, 0x69, 0x79, 0x61, 0x6b, 0x69, 0x00, 0xe4, 0x66,
- 0x00, 0x6b, 0x38, 0x6c, 0x52, 0x74, 0x70, 0xe4, 0x61, 0x00, 0x69, 0x0b,
- 0x6f, 0x10, 0x75, 0x1a, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x06, 0x64, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x61,
- 0x6d, 0x69, 0x64, 0x65, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x6f, 0x06, 0x00, 0x47, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00,
- 0x75, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x55,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x04, 0xa6, 0xe3, 0x65, 0x00, 0x69, 0x10, 0x79, 0x15,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0xe0, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x37, 0x65, 0x64, 0x00, 0x00, 0x0b, 0xe2,
- 0x61, 0x00, 0x72, 0x15, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x09, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40, 0x09, 0x65,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x6d, 0x06, 0x6f, 0x7b, 0x70, 0x7d, 0x00, 0x06,
- 0x40, 0x07, 0x63, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x25, 0x69, 0x46, 0x6f,
- 0x5a, 0xe2, 0x72, 0x00, 0x74, 0x14, 0xe2, 0x69, 0x00, 0x79, 0x0d, 0xe2,
- 0x6c, 0x00, 0x7a, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x0b, 0x65, 0x00,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x43, 0x72, 0x6f,
- 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe4, 0x00, 0x00,
- 0x68, 0x02, 0x74, 0x09, 0x79, 0x0f, 0x00, 0x47, 0x40, 0x06, 0x6f, 0x75,
- 0x73, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6d, 0x65, 0x00, 0x00, 0x00, 0xe2,
- 0x6e, 0x00, 0x74, 0x04, 0x40, 0x00, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x73, 0x06, 0x01, 0x4b, 0x40, 0x07, 0x72, 0x00, 0x00,
- 0x59, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe1, 0x75,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xfd,
- 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x64, 0x5a, 0x00, 0x66, 0x91, 0x00,
- 0x67, 0xa2, 0x00, 0x68, 0xb1, 0x00, 0x6b, 0xb6, 0x00, 0x6c, 0xb8, 0x00,
- 0x6e, 0xd5, 0x00, 0x72, 0xf1, 0x00, 0x73, 0x00, 0x01, 0x74, 0x38, 0x01,
- 0x75, 0x5a, 0x01, 0x00, 0x06, 0xe5, 0x61, 0x00, 0x65, 0x21, 0x6c, 0x32,
- 0x6f, 0x38, 0x75, 0x3f, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x0b, 0x73, 0x10, 0x00, 0xc3, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00,
- 0x00, 0xe3, 0x61, 0x00, 0x64, 0x04, 0x6c, 0x06, 0x40, 0x06, 0x6d, 0x00,
- 0x00, 0x08, 0x40, 0x00, 0x74, 0x00, 0x40, 0x09, 0x6f, 0x63, 0x6b, 0x00,
- 0x40, 0x06, 0x6e, 0x6e, 0x65, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x6e,
- 0x00, 0x73, 0x02, 0x00, 0x93, 0x40, 0x09, 0x74, 0x00, 0xe5, 0x61, 0x00,
- 0x65, 0x04, 0x69, 0x0f, 0x6f, 0x14, 0x72, 0x19, 0x40, 0x09, 0x65, 0x00,
- 0xe2, 0x63, 0x00, 0x72, 0x04, 0x40, 0x08, 0x6b, 0x00, 0x00, 0x3a, 0x40,
- 0x06, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x77, 0x6e, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x05, 0x79, 0x0a, 0x40, 0x08, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x00, 0x00, 0x08, 0xe2, 0x69, 0x00, 0x6c, 0x05, 0x40, 0x09, 0x73,
- 0x68, 0x00, 0x40, 0x09, 0x6f, 0x77, 0x65, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x37, 0x40, 0x07, 0x61, 0x73, 0x73, 0x65, 0x73, 0x00,
- 0x40, 0x08, 0x61, 0x74, 0x00, 0x00, 0x17, 0xe3, 0x61, 0x00, 0x65, 0x05,
- 0x69, 0x0a, 0x40, 0x06, 0x6d, 0x70, 0x00, 0x40, 0x00, 0x73, 0x73, 0x00,
- 0xe2, 0x67, 0x00, 0x74, 0x05, 0x40, 0x07, 0x68, 0x74, 0x00, 0x00, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x13, 0x40, 0x00, 0x64, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00,
- 0x00, 0x00, 0x01, 0x3b, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x73,
- 0x65, 0x00, 0x40, 0x06, 0x6f, 0x66, 0x00, 0xe5, 0x63, 0x00, 0x65, 0x07,
- 0x68, 0x0b, 0x70, 0x21, 0x74, 0x26, 0x40, 0x09, 0x72, 0x65, 0x65, 0x6e,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x09,
- 0x64, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x06, 0x6f, 0x74, 0x00, 0x40, 0x07, 0x72, 0x6f,
- 0x6b, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x18, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x61, 0x70,
- 0x00, 0x40, 0x07, 0x70, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x69, 0x49, 0x03, 0x70, 0x4e, 0x03, 0x72, 0x61, 0x04, 0x74, 0x94, 0x04,
- 0x00, 0x0f, 0xf1, 0x72, 0x00, 0x00, 0xc1, 0x61, 0x17, 0x33, 0x00, 0x35,
- 0x00, 0x6c, 0x00, 0x6e, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x1d, 0x01, 0x60,
- 0x01, 0x70, 0x01, 0x96, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe9, 0x01, 0xf1,
- 0x01, 0x15, 0x02, 0x00, 0x00, 0x42, 0x02, 0x00, 0x00, 0x00, 0x00, 0x5d,
- 0x02, 0xe9, 0x02, 0xf1, 0x02, 0xf7, 0x02, 0x30, 0x03, 0x00, 0x07, 0xe2,
- 0x62, 0x00, 0x6e, 0x1a, 0xe1, 0x75, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x09, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0xda, 0xe4, 0x61, 0x00, 0x68,
- 0x14, 0x69, 0x29, 0x6f, 0x4b, 0xe1, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe1,
- 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe2, 0x6c,
- 0x00, 0x74, 0x19, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x6d, 0x00, 0x6e,
- 0x08, 0x40, 0x09, 0x70, 0x75, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x64, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x15, 0xe2, 0x6e, 0x00, 0x76, 0x04, 0x40, 0x00, 0x67, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x06, 0x72, 0x00, 0xe2, 0x67, 0x00, 0x72, 0x04, 0x40, 0x09, 0x6f, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00,
- 0x72, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x1e, 0xe2, 0x63, 0x00, 0x6e,
- 0x15, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6c,
- 0x00, 0x72, 0x05, 0x40, 0x00, 0x75, 0x65, 0x00, 0x40, 0x08, 0x61, 0x73,
- 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x11, 0x75, 0x19, 0xe1, 0x72, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x06, 0x67, 0x68, 0x77, 0x61, 0x79, 0x00, 0x40, 0x00,
- 0x6d, 0x61, 0x6e, 0x00, 0xe3, 0x6d, 0x00, 0x6e, 0x17, 0x6f, 0x3d, 0xe1,
- 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x0b, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x3a, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0x40, 0x56, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x0d, 0x6f, 0x11, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00,
- 0x07, 0x40, 0x06, 0x6b, 0x65, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2,
- 0x64, 0x00, 0x6d, 0x05, 0x40, 0x06, 0x65, 0x6c, 0x00, 0x00, 0x09, 0xe3,
- 0x61, 0x00, 0x6f, 0x0e, 0x75, 0x1d, 0xe2, 0x6c, 0x00, 0x74, 0x02, 0x00,
- 0x00, 0x43, 0x6c, 0x75, 0x72, 0x61, 0x6c, 0x00, 0xe1, 0x76, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0x00, 0x00, 0x40,
- 0x06, 0x6d, 0x65, 0x72, 0x61, 0x72, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x73, 0x00, 0x77, 0x0e, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0xe6,
- 0x61, 0x00, 0x63, 0x1b, 0x65, 0x39, 0x69, 0x3e, 0x6f, 0x43, 0x74, 0x49,
- 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x62, 0x00,
- 0x70, 0x04, 0x40, 0x0b, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x0b, 0x64,
- 0x65, 0x00, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x69, 0x63,
- 0x00, 0xe4, 0x61, 0x00, 0x69, 0x0b, 0x6f, 0x1f, 0x72, 0x24, 0xe2, 0x72,
- 0x00, 0x74, 0x02, 0x00, 0x09, 0x40, 0x08, 0x65, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00,
- 0x09, 0x40, 0x3b, 0x73, 0x00, 0x40, 0x09, 0x72, 0x65, 0x00, 0x40, 0x09,
- 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x6b,
- 0x65, 0x72, 0x00, 0x40, 0x08, 0x73, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x10, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x02, 0x00, 0x0b,
- 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x09, 0x6f, 0x0e, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x45, 0x00,
- 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0x40, 0x3b, 0x6e, 0x65, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x6c, 0x12, 0x00, 0x6f, 0x80, 0x00, 0x72, 0xc0, 0x00, 0x75, 0xeb,
- 0x00, 0x01, 0x54, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x40, 0x00, 0x69, 0x6d, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x07, 0x69, 0x39, 0x79, 0x61, 0x00, 0x00, 0x40, 0x7a, 0x6e, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x6d, 0x02, 0x6e, 0x25, 0x04, 0xe0, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x55, 0xe3, 0x6c, 0x00, 0x72, 0x02, 0x74, 0x06, 0x00, 0x00, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x63, 0x05, 0x65, 0x1d, 0x40, 0x06,
- 0x6e, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x09, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x04, 0xe1, 0xe2, 0x72, 0x00,
- 0x73, 0x1b, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08,
- 0x04, 0xe2, 0x40, 0xbb, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x37, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0x0b, 0x00, 0x3b, 0xe1, 0x74, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x79,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x69, 0x07, 0x6f, 0x15, 0x00, 0x0b, 0x40, 0x09, 0x6e,
- 0x74, 0x00, 0xe2, 0x62, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x11, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x00, 0x40, 0x00, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x61, 0x6c, 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0f, 0x6f,
- 0x11, 0xe1, 0x63, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73,
- 0x74, 0x00, 0x00, 0x07, 0x00, 0x3b, 0x00, 0x08, 0x00, 0x00, 0xfb, 0x63,
- 0x00, 0x00, 0x65, 0x1b, 0x00, 0x66, 0x41, 0x00, 0x67, 0x76, 0x00, 0x6c,
- 0x92, 0x00, 0x6d, 0xa0, 0x00, 0x6e, 0xc0, 0x00, 0x70, 0xc6, 0x00, 0x72,
- 0x12, 0x01, 0x74, 0xa6, 0x01, 0x76, 0xb5, 0x01, 0xe3, 0x65, 0x00, 0x68,
- 0x06, 0x69, 0x0d, 0x40, 0x5e, 0x61, 0x73, 0x65, 0x00, 0x40, 0x5e, 0x61,
- 0x72, 0x67, 0x65, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x6c, 0x65, 0x00, 0xe4,
- 0x00, 0x00, 0x66, 0x02, 0x6e, 0x13, 0x74, 0x19, 0x00, 0xd3, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x00, 0x72, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x74,
- 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x62, 0x13, 0x65, 0x1a, 0x69, 0x25,
- 0x00, 0xfe, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x27,
- 0x02, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x40, 0x47, 0x6f, 0x61, 0x72,
- 0x64, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x04, 0x40, 0x47, 0x74, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe3,
- 0x00, 0x00, 0x6f, 0x02, 0x72, 0x06, 0x00, 0x5e, 0x40, 0x09, 0x6e, 0x00,
- 0x40, 0x06, 0x79, 0x00, 0x40, 0x3b, 0x63, 0x61, 0x6c, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96,
- 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x82, 0x73, 0x65, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x04, 0xe3, 0x40, 0x54, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x61, 0x6d,
- 0x65, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x11, 0x72, 0x33, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x0b, 0x40, 0x37,
- 0x64, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x09, 0x63, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x8a, 0x40, 0x36, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x5e, 0xe4,
- 0x61, 0x00, 0x6e, 0x2b, 0x70, 0x31, 0x79, 0x53, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x40, 0x47, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x09, 0xe2, 0x67, 0x00,
- 0x75, 0x10, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x04, 0xe4, 0xe1, 0x6e, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe2, 0x61,
- 0x00, 0x69, 0x04, 0x40, 0x47, 0x78, 0x00, 0x40, 0x08, 0x74, 0x6c, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x26, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40,
- 0x07, 0x6c, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x27,
- 0x02, 0x69, 0x06, 0x6f, 0x0b, 0x01, 0xf9, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x76, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x0f, 0x6f, 0x11, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0xa8, 0x40,
- 0x06, 0x72, 0x00, 0xe5, 0x63, 0x00, 0x68, 0x1f, 0x70, 0x23, 0x73, 0x75,
- 0x74, 0x77, 0xe1, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x06,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x54, 0x65, 0x00, 0x40, 0x07, 0x69,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x39, 0xe2, 0x63, 0x00, 0x6e, 0x0e, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x2c, 0x40, 0x37, 0x64,
- 0x00, 0xe2, 0x64, 0x00, 0x73, 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0xd6, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0c, 0xe2, 0x00,
- 0x00, 0x66, 0x02, 0x04, 0xe5, 0x40, 0x00, 0x75, 0x6c, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00,
- 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x06, 0x40, 0x3b, 0x73, 0x00, 0x00,
- 0x3a, 0xe2, 0x61, 0x00, 0x65, 0x20, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x04, 0xe6, 0xe1, 0x62, 0x00, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x00, 0x6c, 0x69, 0x74, 0x79, 0x00, 0x40, 0x37,
- 0x65, 0x00, 0x40, 0x07, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x00, 0xe3, 0x6c,
- 0x00, 0x74, 0x05, 0x75, 0x0a, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x65, 0x65, 0x00, 0x40, 0x82, 0x72, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40, 0x07, 0x79, 0x00, 0x40, 0x60,
- 0x65, 0x6c, 0x74, 0x65, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x5c, 0x01,
- 0x69, 0x90, 0x02, 0x6f, 0x88, 0x03, 0x75, 0xf9, 0x03, 0xfc, 0x62, 0x00,
- 0x00, 0x64, 0x15, 0x00, 0x67, 0x1b, 0x00, 0x69, 0x35, 0x00, 0x6c, 0x39,
- 0x00, 0x6d, 0x4f, 0x00, 0x6e, 0x6b, 0x00, 0x70, 0xa4, 0x00, 0x72, 0xb9,
- 0x00, 0x73, 0xc9, 0x00, 0x74, 0xf5, 0x00, 0x79, 0x24, 0x01, 0xe2, 0x00,
- 0x00, 0x62, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x3a, 0x64, 0x6c, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x02, 0xd7, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x95, 0x40,
- 0x09, 0x61, 0x69, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x70, 0x04,
- 0x00, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x79, 0x08, 0x00,
- 0x95, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x00, 0x00, 0xf3, 0xe4, 0x00, 0x00,
- 0x6b, 0x02, 0x6e, 0x1c, 0x73, 0x2a, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x11, 0x04, 0xe7, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x08, 0x6f, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x70, 0x02, 0x00,
- 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0xe3, 0x64, 0x00, 0x6d, 0x02, 0x74, 0x04, 0x00, 0x06,
- 0x00, 0x95, 0x40, 0x60, 0x68, 0x79, 0x00, 0xe2, 0x68, 0x00, 0x74, 0x21,
- 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x59, 0xe1, 0x75, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x6b, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x69,
- 0x6b, 0x61, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x68, 0x06, 0x74, 0x13,
- 0x00, 0x09, 0x40, 0x09, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73,
- 0x04, 0x00, 0x59, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x2c, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x00, 0x55, 0x40,
- 0x20, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x37, 0x64, 0x00, 0xf6, 0x61, 0x00,
- 0x00, 0x64, 0x56, 0x00, 0x65, 0x5a, 0x00, 0x6c, 0xe4, 0x00, 0x70, 0x02,
- 0x01, 0x72, 0x12, 0x01, 0xe2, 0x72, 0x00, 0x74, 0x13, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x77, 0x06, 0x04, 0xe8, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09,
- 0x6f, 0x72, 0x64, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x70,
- 0x0c, 0x73, 0x13, 0x79, 0x2f, 0x01, 0x05, 0x40, 0x09, 0x61, 0x6e, 0x64,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61, 0x6e, 0x74, 0x73, 0x00,
- 0xe3, 0x00, 0x00, 0x68, 0x02, 0x75, 0x10, 0x00, 0x07, 0xe2, 0x69, 0x00,
- 0x6f, 0x05, 0x40, 0x06, 0x72, 0x74, 0x00, 0x40, 0x09, 0x70, 0x00, 0x40,
- 0x08, 0x69, 0x74, 0x00, 0x00, 0xf3, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x70,
- 0x00, 0x74, 0x26, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x73, 0x15,
- 0x04, 0xe9, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x12, 0x00, 0x07, 0x40, 0x07, 0x74,
- 0x61, 0x6b, 0x65, 0x73, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x63, 0x14,
- 0x65, 0x1a, 0x68, 0x30, 0x69, 0x37, 0x6d, 0x42, 0x6e, 0x48, 0x04, 0xea,
- 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x06, 0x61, 0x64,
- 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x6e, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x37, 0x00, 0x09, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x65, 0x61, 0x72, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x68, 0x00, 0x40, 0x09, 0x65, 0x61, 0x74, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x74, 0x14, 0xe3, 0x00, 0x00,
- 0x68, 0x02, 0x69, 0x08, 0x04, 0xeb, 0x40, 0xb2, 0x65, 0x61, 0x64, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x93, 0x65, 0x72, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x00, 0x40, 0x00, 0x61, 0x63,
- 0x6b, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x82,
- 0x40, 0x37, 0x6e, 0x67, 0x00, 0xeb, 0x66, 0x00, 0x67, 0x10, 0x6c, 0x25,
- 0x6d, 0x29, 0x6e, 0x4e, 0x70, 0x8b, 0x72, 0x8f, 0x73, 0x9b, 0x74, 0x9f,
- 0x76, 0xca, 0x7a, 0xcf, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x04, 0xec, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x67,
- 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x95, 0x6c, 0x00, 0xe4, 0x00, 0x00,
- 0x6d, 0x02, 0x73, 0x10, 0x77, 0x16, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x12, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x75, 0x69, 0x74, 0x00, 0x40, 0x00, 0x65, 0x61, 0x72, 0x00, 0xe4, 0x64,
- 0x00, 0x65, 0x0f, 0x67, 0x1c, 0x69, 0x2f, 0xe1, 0x6c, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe2, 0x00,
- 0x00, 0x68, 0x02, 0x00, 0x06, 0x40, 0x06, 0x65, 0x72, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x01, 0x74, 0xe2, 0x69, 0x00, 0x72, 0x05, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x00, 0x07, 0x40, 0x00, 0x73, 0x68, 0x00, 0x40,
- 0x5e, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00,
- 0x95, 0x00, 0x00, 0x44, 0xed, 0x68, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x65, 0x1a, 0x01, 0x4f, 0xe3, 0x61,
- 0x00, 0x6c, 0x05, 0x6f, 0x0b, 0x40, 0x09, 0x63, 0x6b, 0x00, 0x40, 0x06,
- 0x61, 0x64, 0x65, 0x00, 0x40, 0x06, 0x61, 0x72, 0x64, 0x00, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x55, 0x65, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x7a, 0x02,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x40, 0x3a, 0x65,
- 0x00, 0xe4, 0x6c, 0x00, 0x6f, 0x06, 0x72, 0x15, 0x74, 0x53, 0x40, 0x00,
- 0x6c, 0x65, 0x6e, 0x00, 0xe3, 0x6e, 0x00, 0x70, 0x02, 0x73, 0x04, 0x00,
- 0x93, 0x00, 0x93, 0x40, 0x47, 0x68, 0x00, 0xe3, 0x64, 0x00, 0x65, 0x33,
- 0x6e, 0x35, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x70, 0x08, 0x73, 0x0e, 0x00,
- 0x06, 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0x40, 0x07, 0x6c, 0x61, 0x79,
- 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x10, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x68, 0x69, 0x70,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x67, 0x00, 0xf8, 0x62, 0x00, 0x00, 0x63, 0x17, 0x00,
- 0x6c, 0x43, 0x00, 0x6d, 0xc5, 0x00, 0x6e, 0xc3, 0x01, 0x70, 0x45, 0x03,
- 0x72, 0x5d, 0x03, 0x73, 0x74, 0x03, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07, 0x40, 0x09,
- 0x6d, 0x6f, 0x72, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63,
- 0x00, 0xe3, 0x6c, 0x00, 0x70, 0x5c, 0x76, 0x76, 0xe2, 0x61, 0x00, 0x6f,
- 0x42, 0xe1, 0x62, 0x00, 0xe3, 0x69, 0x00, 0x6c, 0x2b, 0x75, 0x2f, 0xe2,
- 0x63, 0x00, 0x66, 0x16, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x03, 0xd9, 0x40, 0x09, 0x65, 0x00, 0xe2, 0x62,
- 0x00, 0x73, 0x02, 0x00, 0x08, 0x00, 0x09, 0xe1, 0x67, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02,
- 0x6c, 0x06, 0x73, 0x0c, 0x00, 0x07, 0x40, 0x00, 0x63, 0x00, 0x40, 0x00,
- 0x69, 0x6b, 0x65, 0x00, 0x00, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x00, 0xe3,
- 0x62, 0x00, 0x6d, 0x5b, 0x70, 0x79, 0xe2, 0x69, 0x00, 0x6f, 0x28, 0xe1,
- 0x6f, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x0d, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe3, 0x63, 0x00, 0x73, 0x0b, 0x7a, 0x0f, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x3a, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0e, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x06, 0xe4, 0x61, 0x00, 0x68, 0x3a,
- 0x6f, 0x4b, 0x74, 0x52, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x16, 0x79, 0x2b, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x37, 0x40, 0x37, 0x6c,
- 0x6c, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07,
- 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x04, 0x40, 0x00, 0x63, 0x00, 0x00, 0x06, 0x40, 0x09, 0x73, 0x69, 0x75,
- 0x6d, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x09, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x28, 0x00, 0x64,
- 0x76, 0x00, 0x65, 0xa7, 0x00, 0x66, 0xc3, 0x00, 0x6f, 0xc9, 0x00, 0x74,
- 0x07, 0x01, 0x02, 0xdd, 0xe2, 0x67, 0x00, 0x70, 0x13, 0xe1, 0x6f, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x04, 0x40, 0x00, 0x6c, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x04, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x6f,
- 0x2e, 0x00, 0x47, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x69, 0x00, 0x6f, 0x19, 0xe2, 0x63, 0x00, 0x7a, 0x06, 0x40, 0x00,
- 0x69, 0x74, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe1,
- 0x70, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x07,
- 0xe2, 0x69, 0x00, 0x72, 0x26, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x6c, 0x00, 0x74, 0x0f, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x02, 0xa4, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x6f, 0x6d, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f,
- 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x69, 0x63, 0x00, 0x00, 0x06, 0x40, 0x09, 0x75, 0x65, 0x6c, 0x00, 0xe4,
- 0x64, 0x00, 0x6e, 0x02, 0x70, 0x18, 0x76, 0x2f, 0x00, 0x06, 0xe1, 0x79,
- 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x79, 0x07, 0x00,
- 0x06, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x07, 0xe2, 0x73, 0x00, 0x74,
- 0x0d, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0x40, 0x00, 0x69, 0x61, 0x6c,
- 0x00, 0xe2, 0x61, 0x00, 0x68, 0x1b, 0xe2, 0x63, 0x00, 0x78, 0x14, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00,
- 0x65, 0x05, 0x73, 0x39, 0x40, 0x09, 0x73, 0x65, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x1c, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x73, 0x00, 0x7a, 0x02, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x6c, 0x79,
- 0x00, 0x00, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x06,
- 0x69, 0x63, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x06, 0x40, 0x5e, 0x6e, 0x67,
- 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x07, 0x74, 0x0f, 0x40, 0x08, 0x64,
- 0x6d, 0x69, 0x6e, 0x00, 0x60, 0x09, 0x70, 0x00, 0x08, 0x00, 0xff, 0xff,
- 0xe2, 0x65, 0x00, 0x6f, 0x40, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x69, 0x26, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x63, 0x00, 0x7a, 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x37, 0x40,
- 0x3b, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xff,
- 0x00, 0x00, 0x00, 0x52, 0x02, 0x00, 0x61, 0x07, 0x00, 0x62, 0xe5, 0x08,
- 0x65, 0xf1, 0x08, 0x68, 0x70, 0x14, 0x69, 0xe2, 0x1d, 0x6e, 0x96, 0x23,
- 0x6f, 0xa1, 0x23, 0x72, 0x53, 0x2c, 0x73, 0x9e, 0x3d, 0x74, 0xbe, 0x3d,
- 0x75, 0xc3, 0x3d, 0x77, 0xe6, 0x41, 0x79, 0xe0, 0x43, 0x04, 0xee, 0x40,
- 0x07, 0x4e, 0x41, 0x00, 0xc1, 0x62, 0x17, 0x33, 0x00, 0x35, 0x00, 0xff,
- 0x00, 0xe4, 0x01, 0x00, 0x00, 0xf1, 0x01, 0x08, 0x02, 0x00, 0x00, 0x38,
- 0x02, 0x00, 0x00, 0xd2, 0x02, 0x11, 0x03, 0xcd, 0x03, 0x35, 0x04, 0x00,
- 0x00, 0x5a, 0x05, 0x00, 0x00, 0xc0, 0x05, 0xd1, 0x06, 0x57, 0x07, 0xc4,
- 0x07, 0x21, 0x08, 0x27, 0x08, 0x49, 0x08, 0x00, 0x00, 0xe6, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x1d, 0x6c, 0x26, 0x6f, 0x95, 0x75, 0x9e, 0x00, 0x06,
- 0xe4, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x09, 0x79, 0x10, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x75, 0x6c, 0x65, 0x68,
- 0x00, 0x00, 0x06, 0x40, 0x06, 0x72, 0x6e, 0x61, 0x63, 0x6c, 0x65, 0x00,
- 0xe3, 0x61, 0x00, 0x65, 0x02, 0x6f, 0x63, 0x00, 0x09, 0xe7, 0x00, 0x00,
- 0x61, 0x02, 0x63, 0x0e, 0x6c, 0x23, 0x73, 0x29, 0x74, 0x41, 0x77, 0x4c,
- 0x00, 0x82, 0xe1, 0x75, 0x00, 0xe2, 0x00, 0x00, 0x78, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x06, 0x61, 0x6e, 0x64, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x06,
- 0x40, 0x06, 0x75, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06,
- 0x40, 0x09, 0x70, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0x40, 0x06,
- 0x69, 0x64, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x02, 0x00, 0x47, 0x00, 0x09,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x38, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe5, 0x68, 0x00, 0x69, 0x37,
- 0x6b, 0x5b, 0x6f, 0x81, 0x74, 0x83, 0xe2, 0x6f, 0x00, 0x79, 0x21, 0xe2,
- 0x67, 0x00, 0x6d, 0x15, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x06, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x6f,
- 0x08, 0x40, 0x07, 0x61, 0x72, 0x64, 0x69, 0x61, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x75, 0x08, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79,
- 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x0d, 0x79, 0x19,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0x00, 0xf4, 0x00, 0x09, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x69, 0x15,
- 0x6c, 0x38, 0x02, 0xbc, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x63, 0x00, 0x6c, 0x12, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00,
- 0x06, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x6f, 0x6c, 0x65, 0x00, 0xe1, 0x66, 0x00,
- 0xe3, 0x65, 0x00, 0x72, 0x05, 0x79, 0x0b, 0x40, 0x07, 0x74, 0x61, 0x00,
- 0x40, 0x06, 0x61, 0x69, 0x6c, 0x00, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x67,
- 0x02, 0x6c, 0x15, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x08, 0x40, 0x00, 0x74, 0x65,
- 0x6c, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe3, 0x67, 0x00, 0x6c,
- 0x04, 0x6e, 0x85, 0x40, 0x09, 0x61, 0x00, 0xe9, 0x00, 0x00, 0x62, 0x02,
- 0x63, 0x1a, 0x67, 0x20, 0x6c, 0x32, 0x6f, 0x42, 0x70, 0x51, 0x73, 0x62,
- 0x77, 0x68, 0x04, 0xef, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x63,
- 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x05, 0x40, 0x08, 0x72, 0x64, 0x00,
- 0x40, 0x08, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x74, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xa5, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x73,
- 0x73, 0x00, 0x40, 0x09, 0x67, 0x68, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x93, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1,
- 0x69, 0x00, 0xe2, 0x65, 0x00, 0x70, 0x05, 0x40, 0x08, 0x63, 0x65, 0x00,
- 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x70, 0x69, 0x6e, 0x00, 0x40, 0x06,
- 0x69, 0x6e, 0x64, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x47, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x2b, 0xe5,
- 0x00, 0x00, 0x61, 0x02, 0x6e, 0x08, 0x6f, 0x0a, 0x72, 0x1e, 0x04, 0xf0,
- 0x40, 0x08, 0x77, 0x61, 0x79, 0x00, 0x00, 0x77, 0xe3, 0x66, 0x00, 0x75,
- 0x04, 0x76, 0x08, 0x40, 0x09, 0x66, 0x00, 0x40, 0x09, 0x74, 0x00, 0x40,
- 0x06, 0x65, 0x72, 0x00, 0x00, 0x09, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe7, 0x63, 0x00,
- 0x65, 0x0b, 0x69, 0x2a, 0x6b, 0x37, 0x6c, 0x67, 0x6f, 0xa5, 0x75, 0xa9,
- 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6d, 0x00, 0xe3,
- 0x00, 0x00, 0x62, 0x02, 0x6e, 0x0a, 0x00, 0x09, 0x40, 0x09, 0x65, 0x61,
- 0x72, 0x65, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xb1, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x40, 0x09, 0x6d, 0x61, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x1b, 0x69, 0x1f, 0x79, 0x23, 0x00, 0xc3, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0x41, 0x64, 0x65, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02,
- 0x69, 0x07, 0x6e, 0x14, 0x6f, 0x1a, 0x79, 0x26, 0x01, 0x3b, 0x40, 0x09,
- 0x6f, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x73, 0x04, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x00, 0x68, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x77,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x68, 0x02, 0x00, 0x7e, 0x40, 0x55, 0x6f, 0x00, 0x40, 0x09, 0x6e,
- 0x00, 0x40, 0x09, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x62, 0x1a,
- 0x65, 0x23, 0x6f, 0x38, 0x70, 0x40, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x72,
- 0x04, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x09,
- 0x63, 0x6b, 0x00, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x6f, 0x75,
- 0x72, 0x69, 0x6e, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x04,
- 0x72, 0x0a, 0x04, 0xf1, 0x00, 0x37, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x07, 0x40, 0x00, 0x78, 0x69, 0x66, 0x65, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x6f, 0x10, 0x00, 0x3f, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x02, 0x2d, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x6e,
- 0x00, 0xf9, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x62, 0x08, 0x00, 0x64,
- 0x0e, 0x00, 0x67, 0x1d, 0x00, 0x6b, 0x81, 0x00, 0x6e, 0x9a, 0x00, 0x73,
- 0xc1, 0x00, 0x74, 0xc5, 0x00, 0x00, 0x06, 0x40, 0x09, 0x67, 0x65, 0x72,
- 0x00, 0x40, 0x07, 0x61, 0x72, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04,
- 0x40, 0x06, 0x6d, 0x00, 0x40, 0x07, 0x6f, 0x72, 0x69, 0x00, 0xe6, 0x00,
- 0x00, 0x65, 0x02, 0x69, 0x22, 0x6c, 0x45, 0x6f, 0x53, 0x79, 0x55, 0x00,
- 0x09, 0xe3, 0x6c, 0x00, 0x6e, 0x04, 0x72, 0x13, 0x40, 0x09, 0x6f, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x3b,
- 0x61, 0x6c, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01, 0x89,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x54, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x27, 0x02, 0x00, 0xf1, 0x40, 0x00, 0x73, 0x00, 0x00, 0x47,
- 0x00, 0xf3, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x66, 0x0b, 0x00,
- 0xc3, 0x40, 0x09, 0x72, 0x64, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09,
- 0x75, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x16, 0xe3, 0x64, 0x00, 0x72,
- 0x02, 0x73, 0x0b, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0x06, 0x40, 0x00, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x67, 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x61,
- 0x00, 0x72, 0x34, 0xe2, 0x6c, 0x00, 0x6d, 0x28, 0xe2, 0x69, 0x00, 0x75,
- 0x1f, 0xe1, 0x7a, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x07, 0x69, 0x10, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6d, 0x00,
- 0x40, 0x00, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x02,
- 0x00, 0x07, 0x40, 0x06, 0x6d, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x06, 0x69, 0x27, 0x70, 0x33, 0x72, 0x4a, 0x00, 0xfa, 0x40, 0x00, 0x73,
- 0x00, 0xe5, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x08, 0x73, 0x0a, 0x77, 0x10,
- 0x00, 0x09, 0x40, 0x09, 0x69, 0x6e, 0x65, 0x00, 0x00, 0x2f, 0x40, 0x06,
- 0x74, 0x72, 0x79, 0x00, 0x40, 0x09, 0x6f, 0x72, 0x6d, 0x00, 0xe2, 0x6f,
- 0x00, 0x72, 0x05, 0x40, 0x07, 0x63, 0x61, 0x00, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x69, 0x0d, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x74, 0x04, 0x00, 0x37,
- 0x00, 0x09, 0x00, 0x09, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6f, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x06, 0x00, 0x06,
- 0xee, 0x00, 0x00, 0x61, 0x02, 0x62, 0x24, 0x64, 0x2a, 0x65, 0x40, 0x67,
- 0x42, 0x69, 0x47, 0x6d, 0x4c, 0x6e, 0x6f, 0x6f, 0x87, 0x70, 0x90, 0x72,
- 0xa4, 0x73, 0xbe, 0x74, 0xcf, 0x00, 0x93, 0xe2, 0x6d, 0x00, 0x6e, 0x0a,
- 0x40, 0x00, 0x61, 0x73, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x75, 0x06, 0x40, 0x09, 0x6c, 0x6c, 0x61, 0x00,
- 0x40, 0x06, 0x6c, 0x61, 0x00, 0x40, 0x08, 0x61, 0x6c, 0x6c, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0x00, 0x09, 0x40,
- 0x55, 0x65, 0x74, 0x00, 0x40, 0x09, 0x66, 0x66, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6b, 0x08, 0x00, 0x09,
- 0x40, 0x00, 0x64, 0x61, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x00, 0x59, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x09, 0x00, 0x09, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x09,
- 0x00, 0x09, 0x40, 0x09, 0x75, 0x6c, 0x69, 0x6e, 0x00, 0x40, 0x09, 0x6e,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0a, 0x79, 0x0f, 0x40, 0x06,
- 0x67, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x04, 0xcc, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x75, 0x06, 0x40, 0x09,
- 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x6e, 0x14, 0x79, 0x1a, 0x03, 0xe2, 0xe2, 0x6e, 0x00, 0x72, 0x02,
- 0x00, 0x09, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x63,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x02, 0x2b, 0xe4, 0x65, 0x00,
- 0x6b, 0x04, 0x73, 0x20, 0x74, 0x25, 0x40, 0x59, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x59, 0xe2, 0x61, 0x00, 0x69, 0x07, 0x40, 0x09,
- 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x09, 0x73, 0x74, 0x72, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x47, 0x65, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x3a,
- 0x79, 0x4f, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x66, 0x04, 0x6c, 0x17, 0x72,
- 0x2d, 0x04, 0x53, 0x00, 0x37, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x03, 0x11, 0x40, 0x84, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x07, 0x01, 0x3b, 0xe4,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x74, 0x0b, 0x04, 0xf2, 0x40, 0x09,
- 0x6d, 0x69, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe5, 0x65, 0x00, 0x69, 0x18,
- 0x6c, 0x23, 0x6f, 0x37, 0x79, 0x4c, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x47, 0x40, 0x09, 0x65, 0x6d,
- 0x61, 0x6c, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72,
- 0x02, 0x74, 0x04, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6c, 0x65,
- 0x00, 0xe1, 0x6f, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00,
- 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0x04, 0xf3,
- 0xe5, 0x00, 0x00, 0x67, 0x02, 0x6e, 0x07, 0x70, 0x1c, 0x74, 0x20, 0x00,
- 0x06, 0x41, 0x84, 0x68, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0x40, 0x07, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x6e, 0x06, 0x6f, 0x0c, 0x01, 0x9f, 0x41, 0x20, 0x6e, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x06, 0x79, 0x0b, 0x40, 0x3b, 0x63, 0x61,
- 0x6c, 0x00, 0x40, 0x00, 0x75, 0x73, 0x00, 0x00, 0x06, 0x40, 0x09, 0x65,
- 0x72, 0x6e, 0x00, 0xe2, 0x64, 0x00, 0x6e, 0x19, 0xe1, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0x44, 0x83, 0x79,
- 0x00, 0xe7, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0f, 0x69, 0x13, 0x6d, 0x46,
- 0x6f, 0x53, 0x70, 0x72, 0x01, 0xb0, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe5,
- 0x00, 0x00, 0x63, 0x02, 0x64, 0x07, 0x6d, 0x1c, 0x77, 0x23, 0x00, 0x59,
- 0x40, 0x06, 0x61, 0x62, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0x40, 0x09, 0x65, 0x74, 0x65, 0x72, 0x00, 0x40, 0x08, 0x61,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0b, 0xe2, 0x63, 0x00,
- 0x73, 0x02, 0x00, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x06, 0xe1, 0x61,
- 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x70, 0x02, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x61, 0x00, 0x00, 0x63, 0x20,
- 0x01, 0x64, 0xd9, 0x01, 0x65, 0x02, 0x02, 0x6b, 0x6f, 0x02, 0x6c, 0x76,
- 0x02, 0x6d, 0x22, 0x05, 0x6e, 0x24, 0x06, 0x70, 0xfe, 0x07, 0x71, 0x1e,
- 0x08, 0x72, 0x25, 0x08, 0x73, 0xe9, 0x09, 0x74, 0xc2, 0x0a, 0x78, 0x19,
- 0x0b, 0xfa, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00, 0x63, 0x07, 0x00, 0x6b,
- 0x3c, 0x00, 0x6c, 0x4a, 0x00, 0x6d, 0x57, 0x00, 0x70, 0x74, 0x00, 0x72,
- 0x79, 0x00, 0x73, 0xc7, 0x00, 0x74, 0xf5, 0x00, 0x00, 0x06, 0x40, 0x08,
- 0x61, 0x67, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x05, 0x75, 0x1f, 0x40, 0x06,
- 0x6b, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c,
- 0x04, 0xf4, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x66,
- 0x02, 0x00, 0x09, 0x40, 0x09, 0x75, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x09, 0x40, 0x06, 0x74, 0x74, 0x6c, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x09, 0x67, 0x68, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x6d, 0x02, 0x73, 0x08, 0x77, 0x0e, 0x00, 0x59, 0x40, 0x09,
- 0x61, 0x74, 0x65, 0x00, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0x40, 0x07,
- 0x6f, 0x72, 0x6b, 0x00, 0x40, 0x09, 0x6f, 0x74, 0x00, 0xe8, 0x00, 0x00,
- 0x61, 0x02, 0x64, 0x08, 0x66, 0x0e, 0x67, 0x13, 0x6a, 0x2e, 0x6f, 0x36,
- 0x79, 0x3b, 0x00, 0x59, 0x40, 0x08, 0x77, 0x61, 0x79, 0x00, 0x40, 0x06,
- 0x72, 0x6f, 0x70, 0x00, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x65, 0x72, 0x6b, 0x65, 0x72, 0x00, 0x40, 0x06, 0x6f, 0x6d,
- 0x00, 0x00, 0x60, 0xe3, 0x65, 0x00, 0x69, 0x0d, 0x70, 0x12, 0xe3, 0x00,
- 0x00, 0x6c, 0x02, 0x72, 0x04, 0x00, 0xa5, 0x00, 0x09, 0x00, 0x07, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x06, 0x40, 0x06, 0x75, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x08, 0x6d, 0x65,
- 0x00, 0xe2, 0x68, 0x00, 0x74, 0x9f, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e,
- 0x06, 0x73, 0x94, 0x00, 0x07, 0x40, 0x08, 0x65, 0x00, 0xe3, 0x65, 0x00,
- 0x69, 0x07, 0x6f, 0x32, 0x40, 0x07, 0x74, 0x69, 0x75, 0x6d, 0x00, 0xe2,
- 0x63, 0x00, 0x71, 0x21, 0xe3, 0x61, 0x00, 0x69, 0x0f, 0x6f, 0x14, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x74,
- 0x79, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x40, 0x00, 0x6c, 0x6f, 0x72,
- 0x00, 0x40, 0x06, 0x75, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x63,
- 0x0a, 0x6c, 0x24, 0x70, 0x43, 0x00, 0x00, 0x40, 0x00, 0x61, 0x62, 0x62,
- 0x6c, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0x40, 0x00, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00,
- 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73,
- 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x06,
- 0x40, 0x08, 0x68, 0x6f, 0x62, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x69,
- 0x06, 0x00, 0x08, 0x40, 0x08, 0x79, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x13,
- 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe5,
- 0x00, 0x00, 0x69, 0x02, 0x6d, 0x07, 0x6e, 0x09, 0x74, 0x30, 0x04, 0xf5,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x0b, 0xe3, 0x00, 0x00, 0x61, 0x02,
- 0x79, 0x11, 0x00, 0x09, 0xe1, 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x89, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x62, 0x02,
- 0x00, 0x60, 0x40, 0x09, 0x6f, 0x70, 0x70, 0x65, 0x72, 0x00, 0xe3, 0x65,
- 0x00, 0x68, 0x04, 0x6f, 0x10, 0x40, 0x47, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x0b, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x06, 0x00, 0x89, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x73, 0x6d, 0x00,
- 0x40, 0x06, 0x74, 0x69, 0x74, 0x65, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x6c, 0x73, 0x02, 0x6e, 0x9a, 0x02, 0x00, 0x00, 0xfb, 0x63,
- 0x00, 0x00, 0x67, 0x79, 0x00, 0x6b, 0xc3, 0x00, 0x6d, 0xdb, 0x00, 0x6f,
- 0x0a, 0x01, 0x70, 0x20, 0x01, 0x73, 0xb9, 0x01, 0x74, 0xe1, 0x01, 0x76,
- 0x07, 0x02, 0x77, 0x36, 0x02, 0x78, 0x4d, 0x02, 0xe2, 0x61, 0x00, 0x6f,
- 0x11, 0xe1, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x01, 0x37, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x6d, 0x00, 0x6e, 0x40, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09, 0xe1, 0x75, 0x00, 0xe2, 0x6e, 0x00,
- 0x74, 0x1e, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x82, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x72, 0x06, 0x40, 0x00, 0x6e, 0x69, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x6d, 0x00, 0x70, 0x02, 0x00, 0x09, 0xe1, 0x68, 0x00, 0xe5, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x0d, 0x73, 0x23, 0x79, 0x25, 0x03, 0xa2, 0xe2, 0x72,
- 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x63, 0x00,
- 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c,
- 0x6c, 0x79, 0x00, 0x40, 0x06, 0x74, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe1,
- 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x73, 0x00, 0x74,
- 0x05, 0x40, 0x07, 0x69, 0x73, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x1a, 0xe1, 0x72, 0x00, 0xe1, 0x6b, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x72, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06,
- 0x40, 0x00, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x00, 0xe5, 0x61, 0x00, 0x68,
- 0x1d, 0x6c, 0x54, 0x6f, 0x59, 0x72, 0x6d, 0xe1, 0x74, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x10, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x07,
- 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x1d, 0xe3, 0x65, 0x00, 0x69,
- 0x09, 0x79, 0x14, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07,
- 0xe2, 0x63, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x08, 0x74, 0x00, 0x00,
- 0x07, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40,
- 0x07, 0x72, 0x61, 0x70, 0x68, 0x79, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x00, 0x40, 0x00, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f,
- 0x07, 0x40, 0x09, 0x6e, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x6d,
- 0x09, 0x40, 0x07, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x70, 0x74, 0x65, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x06, 0x40, 0x00,
- 0x6c, 0x65, 0x73, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x5e, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe3, 0x65, 0x00,
- 0x68, 0x05, 0x79, 0x0a, 0x40, 0x09, 0x78, 0x74, 0x00, 0x40, 0x09, 0x6f,
- 0x6e, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x77,
- 0x02, 0x00, 0x08, 0x40, 0x09, 0x72, 0x69, 0x74, 0x65, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x69, 0x1b, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x08, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x47, 0xe6,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x74, 0x0b, 0x75, 0x11, 0x79, 0x18,
- 0x04, 0xf6, 0x40, 0x06, 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x61, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x69, 0x75, 0x6d, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x65, 0x74, 0x00, 0xe3, 0x62, 0x00, 0x65, 0x06,
- 0x70, 0x0d, 0x40, 0x09, 0x6c, 0x6f, 0x72, 0x00, 0x40, 0x07, 0x72, 0x69,
- 0x74, 0x79, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x69, 0x6f, 0x81,
- 0x74, 0xb9, 0x75, 0xdc, 0x02, 0xbd, 0xe2, 0x72, 0x00, 0x73, 0x42, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x2f, 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x6e,
- 0x16, 0x74, 0x1b, 0x04, 0xf7, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x3b, 0x6c,
- 0x00, 0x40, 0x53, 0x63, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x0d, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x06, 0x72, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x75,
- 0x02, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x11, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x08, 0x40, 0x00, 0x73, 0x00, 0x00,
- 0x06, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x69,
- 0x1d, 0xe2, 0x6c, 0x00, 0x72, 0x02, 0x00, 0x3b, 0xe2, 0x69, 0x00, 0x79,
- 0x0f, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x01, 0x94, 0xe1, 0x7a, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x09, 0x69, 0x0d, 0x72, 0x12, 0x00, 0xd6, 0x40, 0x09,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x72, 0x61,
- 0x00, 0xfc, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x57, 0x00, 0x64,
- 0x5b, 0x00, 0x65, 0xf3, 0x00, 0x66, 0x00, 0x01, 0x6e, 0x06, 0x01, 0x6f,
- 0x13, 0x01, 0x70, 0x1c, 0x01, 0x73, 0x2b, 0x01, 0x74, 0x56, 0x01, 0x75,
- 0x92, 0x01, 0x04, 0xf8, 0xe3, 0x62, 0x00, 0x63, 0x15, 0x6e, 0x34, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x00, 0x37, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x6f, 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x79, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x06, 0x00, 0x2c, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe5, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x7c, 0x6f, 0x84, 0x72, 0x88, 0x04, 0xf9, 0xe3, 0x64,
- 0x00, 0x6e, 0x02, 0x72, 0x24, 0x00, 0x37, 0xe2, 0x63, 0x00, 0x74, 0x04,
- 0x40, 0x06, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x66, 0x02, 0x68, 0x08,
- 0x69, 0x27, 0x6c, 0x36, 0x6e, 0x3c, 0x02, 0x18, 0x40, 0x09, 0x6f, 0x6f,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x7a, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07,
- 0x40, 0x06, 0x6f, 0x69, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x6e, 0x69, 0x74, 0x69, 0x73, 0x00, 0x40, 0x06, 0x6e, 0x00,
- 0x40, 0x06, 0x69, 0x6c, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x06, 0x40, 0x06,
- 0x65, 0x6e, 0x74, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6f, 0x6c, 0x64, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x08, 0x72, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x2c, 0x00, 0x06, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00,
- 0x07, 0xe3, 0x65, 0x00, 0x69, 0x0d, 0x6f, 0x20, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x04, 0xfa, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x6c, 0x00,
- 0x6f, 0x04, 0x74, 0x08, 0x40, 0x00, 0x65, 0x00, 0x40, 0x90, 0x6e, 0x00,
- 0x40, 0x53, 0x79, 0x00, 0x40, 0x08, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x61,
- 0x02, 0x65, 0x22, 0x68, 0x2a, 0x01, 0x4a, 0xe2, 0x63, 0x00, 0x74, 0x05,
- 0x40, 0x1a, 0x6c, 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x76, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x09, 0x72, 0x68, 0x6f, 0x6f, 0x6b, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x12, 0x00, 0x00, 0xe3, 0x69, 0x00, 0x6f,
- 0x05, 0x72, 0x18, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x5e, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04,
- 0x40, 0x06, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x6e, 0x07, 0x00, 0x3e, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x06, 0x75, 0x69, 0x6c, 0x61, 0x00, 0xf9, 0x61,
- 0x00, 0x00, 0x62, 0x23, 0x00, 0x63, 0x29, 0x00, 0x69, 0x48, 0x00, 0x6d,
- 0x4f, 0x00, 0x6e, 0xad, 0x00, 0x72, 0xb9, 0x00, 0x73, 0x91, 0x01, 0x74,
- 0xa1, 0x01, 0xe3, 0x62, 0x00, 0x68, 0x0e, 0x70, 0x15, 0xe2, 0x69, 0x00,
- 0x79, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x09, 0x74, 0x65, 0x00, 0x40,
- 0x07, 0x65, 0x72, 0x74, 0x7a, 0x00, 0x40, 0x09, 0x69, 0x78, 0x65, 0x6c,
- 0x00, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x6e, 0x05, 0x40, 0x06, 0x72, 0x79, 0x00, 0x40, 0x06, 0x69, 0x61,
- 0x6c, 0x00, 0x40, 0x00, 0x79, 0x61, 0x6b, 0x69, 0x00, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x69, 0x09, 0x01, 0x17, 0x40, 0x09, 0x67, 0x61, 0x6e, 0x74,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x45, 0xe4, 0x61, 0x00, 0x69, 0x20, 0x6f,
- 0x22, 0x75, 0x38, 0xe3, 0x62, 0x00, 0x6c, 0x05, 0x74, 0x07, 0x44, 0xfb,
- 0x6c, 0x65, 0x00, 0x00, 0x86, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07,
- 0x00, 0x38, 0x41, 0x82, 0x6f, 0x6e, 0x00, 0x40, 0x08, 0x72, 0x00, 0x00,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x06, 0x40, 0x3b, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x06, 0x40,
- 0x07, 0x73, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x01, 0x89, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe6, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x2e, 0x69, 0x37, 0x6f, 0xa1, 0x79, 0xbd, 0x00, 0x00, 0xe5, 0x63,
- 0x00, 0x69, 0x0d, 0x70, 0x11, 0x72, 0x16, 0x7a, 0x1c, 0xe2, 0x65, 0x00,
- 0x6f, 0x02, 0x00, 0x5e, 0x40, 0x07, 0x74, 0x74, 0x61, 0x00, 0x40, 0x06,
- 0x6e, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x00, 0x40, 0x06, 0x69, 0x75, 0x6d,
- 0x00, 0x40, 0x09, 0x7a, 0x6f, 0x00, 0x40, 0x56, 0x73, 0x74, 0x72, 0x69,
- 0x61, 0x6c, 0x00, 0xe5, 0x62, 0x00, 0x65, 0x17, 0x66, 0x1b, 0x6e, 0x3c,
- 0x74, 0x40, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0d, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x10, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x0b, 0x40, 0x3b, 0x6e,
- 0x67, 0x00, 0x40, 0x08, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x74, 0x79, 0x00, 0x00,
- 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2,
- 0x73, 0x00, 0x7a, 0x09, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00,
- 0x06, 0x40, 0x3a, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x2d,
- 0x40, 0x07, 0x6c, 0x6f, 0x74, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x69, 0x61, 0x72, 0x79, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x1b, 0xe1,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0xe7, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x43, 0x69,
- 0x50, 0x6f, 0x9e, 0x79, 0xa8, 0x04, 0xfd, 0x44, 0xfc, 0x73, 0x00, 0xe3,
- 0x62, 0x00, 0x6d, 0x05, 0x74, 0x1a, 0x44, 0xfe, 0x6c, 0x65, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x09, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe3, 0x65, 0x00, 0x6f,
- 0x02, 0x72, 0x06, 0x00, 0x08, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x69, 0x00,
- 0xe2, 0x63, 0x00, 0x78, 0x05, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x07,
- 0xe3, 0x64, 0x00, 0x72, 0x02, 0x73, 0x04, 0x00, 0x37, 0x01, 0xee, 0x00,
- 0x00, 0xe6, 0x63, 0x00, 0x66, 0x0f, 0x6c, 0x1b, 0x6d, 0x1f, 0x6e, 0x31,
- 0x73, 0x3f, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40,
- 0x00, 0x6c, 0x61, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x07,
- 0x65, 0x72, 0x00, 0x00, 0x3f, 0x40, 0x00, 0x79, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x61, 0x6c,
- 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x73, 0x74, 0x65,
- 0x72, 0x6f, 0x6e, 0x65, 0x00, 0x01, 0x0c, 0xe4, 0x61, 0x00, 0x63, 0x06,
- 0x68, 0x15, 0x72, 0x1a, 0x40, 0x07, 0x6e, 0x75, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x01,
- 0x0c, 0x40, 0x2c, 0x65, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe4, 0x00, 0x00,
- 0x63, 0x02, 0x68, 0x0b, 0x6d, 0x21, 0x00, 0x06, 0x40, 0x07, 0x79, 0x63,
- 0x6c, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x40,
- 0x09, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe1, 0x74,
- 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x75, 0x19,
- 0x03, 0x72, 0x40, 0x06, 0x6f, 0x6f, 0x6b, 0x00, 0x40, 0x00, 0x64, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x67,
- 0x00, 0xe2, 0x61, 0x00, 0x72, 0x04, 0x43, 0x09, 0x6c, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6c, 0x00, 0x00, 0x82, 0xf8, 0x61, 0x00,
- 0x00, 0x65, 0x9c, 0x00, 0x69, 0x99, 0x03, 0x6f, 0x40, 0x05, 0x72, 0x1f,
- 0x06, 0x75, 0x2c, 0x08, 0x77, 0x08, 0x09, 0x79, 0x22, 0x09, 0xe4, 0x6c,
- 0x00, 0x6e, 0x2d, 0x74, 0x75, 0x77, 0x91, 0xe3, 0x61, 0x00, 0x69, 0x0e,
- 0x6c, 0x20, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x02, 0x00, 0x00,
- 0x40, 0x07, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x64, 0x05, 0x40, 0x00, 0x6e,
- 0x61, 0x00, 0x40, 0x07, 0x6f, 0x6d, 0x69, 0x64, 0x65, 0x00, 0x40, 0x07,
- 0x69, 0x75, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6b, 0x04, 0x00,
- 0x00, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x15, 0x73, 0x2b,
- 0x00, 0x7a, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x67, 0x69, 0x76,
- 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe1,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xe7, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x55, 0xfd, 0x00,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x65, 0x3a, 0x00, 0x66, 0x3c, 0x00, 0x69,
- 0x40, 0x00, 0x6d, 0x59, 0x00, 0x6e, 0x84, 0x00, 0x6f, 0xaa, 0x00, 0x72,
- 0x45, 0x01, 0x73, 0x8b, 0x02, 0x74, 0xb1, 0x02, 0x77, 0xb5, 0x02, 0x79,
- 0xb7, 0x02, 0x03, 0x94, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x10,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40, 0x06,
- 0x6f, 0x65, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61,
- 0x00, 0x73, 0x13, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73,
- 0x07, 0x02, 0xde, 0x40, 0x07, 0x74, 0x79, 0x00, 0x00, 0x07, 0x00, 0x07,
- 0x00, 0x08, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00,
- 0x08, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x65, 0x18, 0x73, 0x1a, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x6c, 0x6c, 0x79, 0x00, 0x00, 0x1a, 0x40, 0x00, 0x65, 0x6c, 0x76, 0x65,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x07, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x74, 0x00, 0x77, 0x04, 0x40, 0x00, 0x68, 0x00, 0x40, 0x00,
- 0x61, 0x72, 0x64, 0x00, 0xe5, 0x63, 0x00, 0x64, 0x14, 0x6c, 0x1c, 0x72,
- 0x37, 0x73, 0x6c, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0x40,
- 0x08, 0x6f, 0x6c, 0x69, 0x74, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x61, 0x00, 0x63, 0x04, 0x40,
- 0x06, 0x6e, 0x00, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe3, 0x65,
- 0x00, 0x69, 0x1f, 0x79, 0x2c, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x09,
- 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x06, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x00,
- 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x3a, 0x65,
- 0x00, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x14, 0xe2, 0x63, 0x00, 0x73, 0x0b, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x74,
- 0x00, 0x00, 0x07, 0xf3, 0x61, 0x00, 0x00, 0x65, 0x2e, 0x00, 0x6d, 0xb6,
- 0x00, 0xe1, 0x70, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x1d, 0x79, 0x22, 0xe1,
- 0x75, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x73, 0x08, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x6c,
- 0x79, 0x00, 0x00, 0x07, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x06, 0xea,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x17, 0x66, 0x26, 0x69, 0x3c, 0x6d, 0x40,
- 0x6f, 0x45, 0x74, 0x4e, 0x75, 0x5e, 0x77, 0x6d, 0x00, 0x07, 0xe3, 0x62,
- 0x00, 0x66, 0x06, 0x74, 0x0c, 0x40, 0x08, 0x6f, 0x75, 0x74, 0x00, 0x40,
- 0x00, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x08,
- 0x40, 0x00, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x00, 0x00, 0x00, 0xe2, 0x6f,
- 0x00, 0x72, 0x0c, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0x40, 0x06, 0x69, 0x6e, 0x00, 0xe2, 0x66, 0x00, 0x6e, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6f, 0x72, 0x65, 0x00, 0xe2, 0x6e, 0x00, 0x70, 0x05, 0x40,
- 0x00, 0x74, 0x6f, 0x00, 0x40, 0x00, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x69,
- 0x74, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x6f, 0x0d,
- 0x00, 0x06, 0x40, 0x86, 0x6c, 0x00, 0x40, 0x00, 0x6f, 0x6e, 0x69, 0x63,
- 0x00, 0xe5, 0x64, 0x00, 0x6d, 0x1b, 0x6e, 0x2f, 0x70, 0x38, 0x73, 0x41,
- 0xe1, 0x79, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x08, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x72, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x69, 0x63, 0x00, 0x40,
- 0x00, 0x75, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x00, 0x40, 0x06, 0x6c, 0x61,
- 0x73, 0x74, 0x69, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x09, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x11, 0x69, 0x13,
- 0x70, 0x17, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x75,
- 0x02, 0x00, 0x00, 0x40, 0x09, 0x73, 0x00, 0x00, 0x08, 0x40, 0x07, 0x73,
- 0x00, 0x40, 0x06, 0x69, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x61, 0x00, 0x00,
- 0x09, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x00, 0xe4, 0x64, 0x00, 0x6c,
- 0x02, 0x72, 0x06, 0x76, 0x0a, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x40, 0x00, 0x65, 0x00, 0xf9, 0x61, 0x00, 0x00, 0x63,
- 0x07, 0x00, 0x65, 0x47, 0x00, 0x67, 0x6b, 0x00, 0x6d, 0x7f, 0x00, 0x6e,
- 0x94, 0x00, 0x72, 0x11, 0x01, 0x73, 0x6b, 0x01, 0x74, 0x85, 0x01, 0x40,
- 0x07, 0x6d, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x6b, 0x00, 0xe6, 0x00, 0x00,
- 0x65, 0x02, 0x68, 0x1b, 0x6e, 0x23, 0x6f, 0x29, 0x73, 0x2b, 0x04, 0xff,
- 0xe2, 0x6e, 0x00, 0x74, 0x12, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06,
- 0x05, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00,
- 0x09, 0x40, 0x07, 0x65, 0x61, 0x64, 0x65, 0x64, 0x00, 0x40, 0x09, 0x65,
- 0x73, 0x73, 0x00, 0x00, 0x08, 0x40, 0x00, 0x65, 0x74, 0x00, 0xe2, 0x66,
- 0x00, 0x76, 0x02, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x3a, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x6e, 0x00,
- 0x73, 0x04, 0x40, 0x07, 0x67, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe1, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x73, 0x08, 0x00, 0x07, 0x40, 0x09,
- 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x09, 0x40, 0x06,
- 0x75, 0x6c, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x67, 0x04, 0x6b, 0x38,
- 0x6e, 0x54, 0x05, 0x01, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x75,
- 0x17, 0x79, 0x29, 0x00, 0x07, 0xe1, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x62, 0x00, 0x6a, 0x05, 0x40, 0x06, 0x6f, 0x62, 0x00, 0x40, 0x06, 0x69,
- 0x67, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x6d, 0x06, 0x40, 0x08,
- 0x62, 0x6f, 0x62, 0x00, 0x40, 0x08, 0x79, 0x00, 0x00, 0x08, 0xe4, 0x00,
- 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x05, 0x02, 0x40, 0x37, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x27,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x14, 0xe3, 0x64, 0x00, 0x72, 0x02,
- 0x73, 0x04, 0x00, 0x00, 0x00, 0x09, 0xe2, 0x73, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x64, 0x00, 0x73,
- 0x02, 0x74, 0x1f, 0x00, 0x56, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x11, 0x00, 0x93, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92, 0xe3, 0x65,
- 0x00, 0x69, 0x19, 0x79, 0x2b, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x01, 0x58, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x03, 0xc6, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x09, 0x40, 0x07,
- 0x6f, 0x77, 0x6e, 0x00, 0x40, 0x00, 0x68, 0x65, 0x72, 0x00, 0xe6, 0x00,
- 0x00, 0x6c, 0x02, 0x6e, 0x06, 0x72, 0x0a, 0x73, 0x65, 0x75, 0x69, 0x00,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x67, 0x00, 0xe4, 0x61, 0x00,
- 0x69, 0x0c, 0x6e, 0x11, 0x6f, 0x23, 0xe2, 0x63, 0x00, 0x78, 0x05, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0x00, 0x09, 0x40, 0x07, 0x75, 0x6d, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe1, 0x75, 0x00, 0xe1, 0x67, 0x00, 0xe1,
- 0x68, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x66, 0x08, 0x67, 0x0e, 0x6e,
- 0x15, 0x00, 0xe0, 0x40, 0x09, 0x72, 0x65, 0x64, 0x00, 0x40, 0x09, 0x61,
- 0x72, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x67,
- 0x02, 0x73, 0x3e, 0x00, 0x09, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6c, 0x15, 0x00, 0x06,
- 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x64, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x74, 0x08, 0x01, 0x29, 0x40,
- 0x00, 0x6f, 0x6c, 0x64, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65, 0x29, 0x00,
- 0x69, 0xb3, 0x00, 0x6f, 0xfe, 0x00, 0x75, 0xcf, 0x01, 0xe2, 0x6c, 0x00,
- 0x73, 0x0f, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x2c,
- 0x40, 0x07, 0x6f, 0x6d, 0x00, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x03, 0x78, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe5, 0x61, 0x00, 0x65, 0x3a, 0x6e, 0x62, 0x73, 0x68, 0x77,
- 0x7d, 0xe2, 0x64, 0x00, 0x74, 0x1f, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65,
- 0x08, 0x6c, 0x0c, 0x79, 0x12, 0x01, 0x5b, 0x40, 0x00, 0x61, 0x72, 0x65,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00, 0x00,
- 0x60, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xcc, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x01, 0x20, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe4,
- 0x00, 0x00, 0x66, 0x02, 0x70, 0x08, 0x73, 0x0f, 0x00, 0x06, 0x40, 0x00,
- 0x6f, 0x6c, 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x63, 0x65, 0x00, 0xe2,
- 0x63, 0x00, 0x6f, 0x06, 0x40, 0x09, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x06,
- 0x6d, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x64, 0x79, 0x00, 0xe1, 0x68, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x06, 0x6c, 0x64, 0x00, 0x00, 0x00, 0xe4, 0x63, 0x00, 0x66,
- 0x04, 0x6c, 0x29, 0x76, 0x3e, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x74, 0x00,
- 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x11, 0x79, 0x17, 0x00, 0x06, 0xe2,
- 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x00, 0x96, 0xe1, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x5b, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe8,
- 0x61, 0x00, 0x62, 0x1d, 0x65, 0x32, 0x6d, 0x34, 0x6e, 0x64, 0x74, 0x76,
- 0x75, 0x88, 0x77, 0xa1, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x79, 0x11, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0xe2, 0x00, 0x00,
- 0x62, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06, 0xe1, 0x62, 0x00, 0xe3,
- 0x69, 0x00, 0x6f, 0x02, 0x75, 0x22, 0x00, 0x00, 0xe3, 0x6c, 0x00, 0x73,
- 0x07, 0x74, 0x14, 0x40, 0x00, 0x79, 0x74, 0x69, 0x63, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40,
- 0x00, 0x69, 0x63, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x67,
- 0x0b, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x00, 0x08, 0x40, 0x00, 0x73, 0x00,
- 0x00, 0x95, 0xe1, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe1, 0x67, 0x00, 0xe1,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x70, 0x07, 0x00, 0x00, 0x40,
- 0x00, 0x75, 0x74, 0x00, 0x40, 0x07, 0x75, 0x74, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x62, 0x08, 0x65, 0x0e, 0x6e, 0x12, 0x01, 0x67, 0x40, 0x06,
- 0x77, 0x61, 0x79, 0x00, 0x40, 0x06, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x07,
- 0x72, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x73, 0x17, 0x77,
- 0x20, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe2, 0x68, 0x00, 0x74, 0x02, 0x00, 0x09, 0x01, 0x2f, 0x40, 0x09, 0x61,
- 0x79, 0x00, 0xe6, 0x64, 0x00, 0x67, 0x15, 0x6c, 0x2b, 0x6d, 0x31, 0x6e,
- 0x69, 0x73, 0xcd, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x09, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x05,
- 0x40, 0x07, 0x72, 0x79, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0x40, 0x07,
- 0x69, 0x75, 0x6d, 0x00, 0xe2, 0x62, 0x00, 0x70, 0x27, 0xe5, 0x00, 0x00,
- 0x6e, 0x02, 0x70, 0x08, 0x73, 0x0f, 0x74, 0x16, 0x00, 0x2c, 0x40, 0x06,
- 0x61, 0x69, 0x6c, 0x00, 0x40, 0x06, 0x72, 0x69, 0x6e, 0x74, 0x00, 0x40,
- 0x06, 0x63, 0x72, 0x65, 0x77, 0x00, 0x40, 0x06, 0x61, 0x63, 0x6b, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x2c, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe2, 0x64, 0x00, 0x6b, 0x5d, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe8,
- 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x65, 0x19, 0x68, 0x1d, 0x6f, 0x23,
- 0x73, 0x28, 0x79, 0x44, 0x00, 0xc3, 0x40, 0x06, 0x6f, 0x6c, 0x74, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x70, 0x00,
- 0x40, 0x09, 0x75, 0x64, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x65,
- 0x61, 0x64, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe2, 0x68, 0x00, 0x74,
- 0x07, 0x40, 0x06, 0x6f, 0x77, 0x65, 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x72,
- 0x05, 0x40, 0x06, 0x72, 0x6d, 0x00, 0x40, 0x00, 0x75, 0x63, 0x6b, 0x00,
- 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00,
- 0x72, 0x0e, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x05,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x95, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x6d,
- 0x02, 0x72, 0x14, 0x73, 0x28, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02,
- 0x75, 0x07, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x73,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x65,
- 0x6c, 0x66, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00, 0x40, 0x00,
- 0x53, 0x00, 0xa8, 0x00, 0x22, 0x01, 0x58, 0x01, 0x5c, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, 0xf9, 0x01, 0x27, 0x03,
- 0x00, 0x00, 0x17, 0x04, 0x00, 0x00, 0x7e, 0x04, 0xdc, 0x04, 0xe2, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x05,
- 0x00, 0x13, 0x40, 0x06, 0x72, 0x61, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x06, 0xe5, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x0b, 0x6c, 0x10, 0x74, 0x31, 0x00, 0xfe, 0xe2, 0x72,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x95, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e,
- 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x08, 0x40, 0x07, 0x63, 0x6b, 0x74, 0x6f, 0x65, 0x00, 0x40, 0x09,
- 0x63, 0x6b, 0x00, 0xe6, 0x61, 0x00, 0x62, 0x04, 0x64, 0x09, 0x65, 0x2e,
- 0x69, 0x54, 0x79, 0x6b, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x06, 0x69, 0x74,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x04, 0x40, 0x08, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6e, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x08,
- 0x00, 0x07, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x08, 0x77, 0x0e, 0x01,
- 0x01, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x08, 0x61, 0x72, 0x6b,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x74, 0x00, 0x79, 0x05, 0x40, 0x09, 0x65,
- 0x72, 0x00, 0x00, 0x09, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x37, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0xdb, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x73, 0x00, 0x05, 0x03, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x62, 0x06,
- 0x70, 0x24, 0x72, 0x29, 0x05, 0x04, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x72, 0x05, 0x40, 0x09, 0x63, 0x6b, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x04, 0x04,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x69, 0x6e, 0x00, 0x00, 0x20, 0x40,
- 0x55, 0x66, 0x00, 0xe3, 0x65, 0x00, 0x68, 0x0f, 0x72, 0x4c, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x73, 0x68,
- 0x00, 0xe1, 0x74, 0x00, 0xe7, 0x00, 0x00, 0x65, 0x02, 0x66, 0x10, 0x6e,
- 0x18, 0x72, 0x1e, 0x73, 0x24, 0x77, 0x26, 0x05, 0x05, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0x2d, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x00, 0x69, 0x73, 0x74, 0x65, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x09, 0x6f, 0x70, 0x65, 0x00, 0x00, 0x07, 0x40, 0x09, 0x61,
- 0x64, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x64,
- 0x02, 0x65, 0x06, 0x69, 0x0f, 0x6c, 0x14, 0x74, 0x35, 0x00, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06,
- 0x65, 0x14, 0x05, 0x06, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x62, 0x00, 0x67,
- 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x65, 0x00, 0x40, 0x84,
- 0x72, 0x00, 0x00, 0x55, 0xf5, 0x62, 0x00, 0x00, 0x65, 0x2a, 0x00, 0x69,
- 0xcd, 0x00, 0x6f, 0xea, 0x00, 0x70, 0x0a, 0x01, 0xe2, 0x65, 0x00, 0x72,
- 0x19, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x2c, 0xe2,
- 0x61, 0x00, 0x69, 0x05, 0x40, 0x07, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x6e,
- 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06,
- 0x00, 0x06, 0xea, 0x00, 0x00, 0x6b, 0x02, 0x6c, 0x19, 0x6f, 0x46, 0x70,
- 0x4b, 0x72, 0x52, 0x73, 0x54, 0x74, 0x7b, 0x77, 0x82, 0x7a, 0x88, 0x05,
- 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x13, 0x79, 0x24, 0xe1, 0x73, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x09, 0x40, 0xdb, 0x73, 0x00, 0x03, 0x99, 0x40, 0x06, 0x75,
- 0x74, 0x00, 0x40, 0x09, 0x69, 0x65, 0x63, 0x65, 0x00, 0x00, 0x07, 0xe3,
- 0x63, 0x00, 0x65, 0x06, 0x68, 0x1a, 0x40, 0x08, 0x61, 0x6c, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x76, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x06, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x61, 0x72,
- 0x65, 0x00, 0x40, 0x5e, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x6f,
- 0x72, 0x6e, 0x00, 0x40, 0x00, 0x6f, 0x6e, 0x65, 0x00, 0xe2, 0x64, 0x00,
- 0x6e, 0x14, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x07, 0x01, 0xb4, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07,
- 0x67, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x16, 0xe1, 0x6f, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x68, 0x79, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x40, 0x06, 0x74, 0x00, 0xee, 0x00, 0x00, 0x63, 0x02, 0x64,
- 0x09, 0x65, 0x1b, 0x66, 0x1d, 0x67, 0x23, 0x69, 0x44, 0x6b, 0x4b, 0x6e,
- 0x62, 0x70, 0x85, 0x73, 0x94, 0x74, 0xaf, 0x77, 0xcb, 0x79, 0xd1, 0x00,
- 0x06, 0x40, 0x82, 0x74, 0x75, 0x72, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x07, 0x40, 0x09, 0x6f,
- 0x78, 0x00, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x69, 0x6c, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x6c, 0x0e, 0x05, 0x08, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x8a, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x0e, 0xe1, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x01, 0x05, 0x40, 0x07, 0x72, 0x00, 0x40, 0x5e, 0x65,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x1a, 0x40, 0x00, 0x64, 0x00,
- 0xe2, 0x6e, 0x00, 0x74, 0x0c, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07,
- 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x07, 0x75, 0x73, 0x00, 0x01, 0x0c,
- 0xe2, 0x6c, 0x00, 0x6f, 0x06, 0x40, 0x07, 0x61, 0x74, 0x65, 0x00, 0x40,
- 0x00, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x04, 0x40, 0x95, 0x6c, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79,
- 0x10, 0x00, 0x55, 0x40, 0x09, 0x6e, 0x6e, 0x61, 0x62, 0x75, 0x6c, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x70, 0x65, 0x00, 0x40, 0x07,
- 0x61, 0x72, 0x65, 0x00, 0x00, 0xf4, 0xe4, 0x00, 0x00, 0x70, 0x02, 0x73,
- 0x2b, 0x74, 0x48, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x11, 0x6c, 0x16,
- 0xe4, 0x64, 0x00, 0x72, 0x02, 0x74, 0x04, 0x78, 0x06, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x06, 0x00, 0x0b, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe3, 0x69,
- 0x00, 0x74, 0x0f, 0x79, 0x14, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x09, 0x65, 0x72,
- 0x00, 0x01, 0x15, 0xe1, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x70, 0x0c, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x1a, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00,
- 0x06, 0xe2, 0x61, 0x00, 0x65, 0x0f, 0xe2, 0x64, 0x00, 0x6d, 0x04, 0x40,
- 0x06, 0x65, 0x00, 0x40, 0x09, 0x69, 0x73, 0x75, 0x00, 0xe5, 0x00, 0x00,
- 0x27, 0x02, 0x64, 0x06, 0x6c, 0x13, 0x73, 0x29, 0x00, 0x4b, 0x40, 0x00,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7f, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x06, 0x73, 0x75, 0x65, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02, 0x63, 0x17,
- 0x68, 0x23, 0x69, 0x2f, 0x6c, 0x69, 0x6d, 0x86, 0x72, 0x96, 0x74, 0x9a,
- 0x75, 0xab, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe2, 0x63, 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x07, 0x6d,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x08, 0x00,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0xe3, 0x61, 0x00, 0x6c, 0x04, 0x76, 0x21, 0x40, 0x07, 0x6e, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x57, 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x3b, 0x67,
- 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x13, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x68, 0x04, 0x00,
- 0x5e, 0x00, 0x37, 0x40, 0x09, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x00, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x63,
- 0x65, 0x00, 0x40, 0x07, 0x75, 0x73, 0x65, 0x00, 0x40, 0x09, 0x65, 0x00,
- 0xe3, 0x65, 0x00, 0x6c, 0x04, 0x79, 0x08, 0x40, 0x93, 0x72, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0x00, 0x08, 0x40, 0x00, 0x6c, 0x61, 0x72, 0x00, 0xe1,
- 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x06, 0xe2,
- 0x00, 0x00, 0x70, 0x02, 0x00, 0x00, 0x40, 0x00, 0x6b, 0x00, 0xc1, 0x61,
- 0x19, 0x37, 0x00, 0x39, 0x00, 0x83, 0x00, 0xbc, 0x00, 0xcc, 0x00, 0xe8,
- 0x00, 0x12, 0x01, 0x24, 0x01, 0x00, 0x00, 0x62, 0x01, 0x00, 0x00, 0x8c,
- 0x01, 0xa2, 0x01, 0x1a, 0x02, 0xa2, 0x02, 0x43, 0x03, 0xd7, 0x03, 0xd1,
- 0x04, 0xd6, 0x04, 0x3e, 0x06, 0x50, 0x06, 0xbe, 0x06, 0x00, 0x00, 0xa7,
- 0x07, 0x68, 0x08, 0xa6, 0x08, 0x00, 0x9b, 0xe2, 0x64, 0x00, 0x73, 0x1c,
- 0xe3, 0x00, 0x00, 0x73, 0x02, 0x79, 0x09, 0x00, 0x09, 0x40, 0x09, 0x74,
- 0x6f, 0x6f, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40,
- 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x6d, 0x06, 0x79, 0x1b, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x07, 0x40, 0x06, 0x73, 0x74, 0x65, 0x72, 0x00, 0x40, 0x09,
- 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x00, 0x04, 0xf3, 0xe2, 0x61, 0x00,
- 0x6f, 0x16, 0xe1, 0x63, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x09, 0x40, 0x06, 0x69, 0x73, 0x74, 0x00,
- 0xe1, 0x67, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x05, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x06, 0x40,
- 0x08, 0x61, 0x74, 0x61, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x64, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x79, 0x0c,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07,
- 0x00, 0x06, 0xe6, 0x00, 0x00, 0x63, 0x02, 0x68, 0x07, 0x69, 0x0d, 0x6e,
- 0x12, 0x72, 0x18, 0x00, 0x1a, 0x40, 0x06, 0x61, 0x70, 0x00, 0x40, 0x09,
- 0x6f, 0x6c, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x61,
- 0x69, 0x6c, 0x00, 0x40, 0x08, 0x61, 0x67, 0x00, 0xe2, 0x66, 0x00, 0x75,
- 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x08, 0x40, 0x06, 0x65, 0x00,
- 0x00, 0x07, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x04, 0x67, 0x1d, 0x73,
- 0x31, 0x00, 0x06, 0x00, 0xb2, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x5d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6c,
- 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x5e,
- 0x65, 0x00, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x73, 0x1a, 0x00, 0xfe, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe3,
- 0x00, 0x00, 0x72, 0x02, 0x74, 0x06, 0x00, 0x55, 0x40, 0x06, 0x79, 0x00,
- 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x82, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe4, 0x64, 0x00, 0x65,
- 0x02, 0x6c, 0x3e, 0x75, 0x69, 0x01, 0xca, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe3, 0x62, 0x00, 0x6e, 0x0c, 0x74, 0x1f,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x54,
- 0xe2, 0x63, 0x00, 0x74, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x53, 0x00, 0x00, 0x00, 0x5c, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02,
- 0x67, 0x17, 0x77, 0x1d, 0x00, 0x55, 0xe1, 0x6f, 0x00, 0xe1, 0x6f, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x06, 0x61, 0x74, 0x65, 0x00, 0x40, 0x06, 0x61,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x65, 0x00, 0xe8, 0x00, 0x00, 0x61,
- 0x02, 0x62, 0x1b, 0x63, 0x40, 0x65, 0x45, 0x66, 0x47, 0x6f, 0x50, 0x74,
- 0x72, 0x00, 0x06, 0xe2, 0x68, 0x00, 0x74, 0x06, 0x40, 0x93, 0x61, 0x77,
- 0x6b, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0x40, 0x00, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x6f, 0x02, 0x73, 0x17, 0x00,
- 0x55, 0xe2, 0x6c, 0x00, 0x79, 0x04, 0x40, 0x08, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x00, 0x73, 0x68, 0x00, 0x40, 0x09,
- 0x74, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x09, 0x61, 0x74, 0x00, 0x00, 0x09,
- 0x40, 0x06, 0x6f, 0x6f, 0x6c, 0x65, 0x72, 0x79, 0x00, 0xe2, 0x67, 0x00,
- 0x72, 0x17, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00, 0x63, 0x00, 0x00,
- 0x07, 0x40, 0x09, 0x72, 0x6f, 0x77, 0x00, 0x40, 0x09, 0x69, 0x74, 0x00,
- 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11, 0x67, 0x2f, 0x69, 0x46, 0x6e,
- 0x52, 0x73, 0x5e, 0x79, 0x8e, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe5, 0x00,
- 0x00, 0x27, 0x02, 0x61, 0x06, 0x6c, 0x0b, 0x72, 0x11, 0x05, 0x09, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x06, 0x72, 0x6d, 0x00, 0x40, 0x3b, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x53, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x55, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x82, 0x40, 0x00, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40, 0x07,
- 0x68, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x06, 0x67, 0x65,
- 0x00, 0x00, 0x06, 0xe3, 0x69, 0x00, 0x6f, 0x1d, 0x75, 0x24, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69,
- 0x08, 0x40, 0x06, 0x63, 0x74, 0x6f, 0x6d, 0x79, 0x00, 0x40, 0x07, 0x74,
- 0x69, 0x73, 0x00, 0x40, 0x00, 0x72, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x5e,
- 0x72, 0x65, 0x00, 0x00, 0xf3, 0xe4, 0x00, 0x00, 0x6b, 0x02, 0x6c, 0x04,
- 0x74, 0x2e, 0x00, 0x00, 0x00, 0x77, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x62,
- 0x06, 0x6b, 0x13, 0x6d, 0x18, 0x01, 0xf9, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x04, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x78, 0x00,
- 0x40, 0x00, 0x69, 0x74, 0x00, 0x40, 0x09, 0x61, 0x6b, 0x65, 0x72, 0x00,
- 0xe5, 0x00, 0x00, 0x65, 0x02, 0x68, 0x06, 0x6c, 0x49, 0x73, 0x4d, 0x00,
- 0xfe, 0x40, 0x07, 0x72, 0x00, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x62, 0x08,
- 0x69, 0x0f, 0x6c, 0x14, 0x70, 0x1a, 0x73, 0x2a, 0x79, 0x30, 0x00, 0x20,
- 0x40, 0x09, 0x63, 0x68, 0x65, 0x00, 0x40, 0x09, 0x72, 0x75, 0x73, 0x68,
- 0x00, 0x40, 0x00, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x06, 0x40, 0x06, 0x73, 0x74, 0x65, 0x00, 0x40,
- 0x06, 0x63, 0x6b, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0x00, 0xf3,
- 0x40, 0x0b, 0x65, 0x00, 0x40, 0x08, 0x69, 0x65, 0x00, 0xee, 0x00, 0x00,
- 0x61, 0x02, 0x63, 0x06, 0x64, 0x0c, 0x65, 0x16, 0x66, 0x1a, 0x69, 0x22,
- 0x6b, 0x46, 0x6c, 0x4c, 0x6d, 0x52, 0x6e, 0x61, 0x6f, 0x68, 0x70, 0xa7,
- 0x73, 0xc0, 0x00, 0x06, 0x40, 0x09, 0x7a, 0x00, 0x40, 0x06, 0x6f, 0x61,
- 0x74, 0x00, 0x40, 0x06, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x08, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x63, 0x07, 0x00, 0x00, 0x40, 0x07, 0x72,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0x40, 0x06, 0x6e, 0x6f, 0x74, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00, 0x40, 0x00,
- 0x73, 0x74, 0x00, 0x40, 0x00, 0x6f, 0x74, 0x63, 0x68, 0x00, 0xe2, 0x67,
- 0x00, 0x6c, 0x27, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x68, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x12, 0x40, 0x06,
- 0x72, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x3b, 0x63, 0x61, 0x6c, 0x00, 0x00,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x6c, 0x0e, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x06, 0x6e, 0x67, 0x00, 0x40, 0x0b,
- 0x65, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x05, 0x6f, 0x0a, 0x70, 0x0f, 0x40,
- 0x06, 0x69, 0x6c, 0x00, 0x40, 0x06, 0x64, 0x65, 0x00, 0x40, 0x07, 0x69,
- 0x6c, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0x40, 0x06, 0x75, 0x65, 0x00,
- 0xfb, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x65, 0x1d, 0x00, 0x6d, 0x2a,
- 0x00, 0x6e, 0x45, 0x00, 0x70, 0x5d, 0x00, 0x71, 0x88, 0x00, 0x72, 0x8d,
- 0x00, 0x73, 0xbb, 0x00, 0x74, 0xd3, 0x00, 0x75, 0x42, 0x01, 0x00, 0x06,
- 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x0a, 0x00, 0x59,
- 0x40, 0x09, 0x65, 0x61, 0x72, 0x65, 0x72, 0x00, 0x40, 0x07, 0x69, 0x67,
- 0x68, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x09,
- 0x64, 0x6f, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x2c, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x11,
- 0x6f, 0x20, 0xe1, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xec, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x82, 0x75, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x12,
- 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x6e, 0x07, 0x00, 0x3e, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x11, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40,
- 0x00, 0x6c, 0x00, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06,
- 0x69, 0x14, 0x6f, 0x1a, 0x75, 0x37, 0x05, 0x0a, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x06, 0x40, 0x07, 0x6c, 0x69, 0x6e,
- 0x69, 0x00, 0x40, 0x09, 0x6c, 0x6c, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x6e,
- 0x14, 0xe1, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x68, 0x65, 0x6c, 0x6c, 0x00, 0x40, 0x07, 0x69,
- 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x7e, 0x00, 0x07, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40, 0x00, 0x73, 0x00,
- 0xe2, 0x68, 0x00, 0x73, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02,
- 0x00, 0xe7, 0x40, 0x09, 0x70, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x37, 0x74, 0x49, 0x00, 0x93, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x03, 0x0b, 0xe2, 0x74, 0x00, 0x7a, 0x1f, 0xe2, 0x61, 0x00, 0x79,
- 0x18, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x6d,
- 0x00, 0x00, 0x06, 0x40, 0x06, 0x61, 0x74, 0x6f, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x12, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xc3, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe6, 0x63, 0x00, 0x67,
- 0x61, 0x70, 0x8b, 0x72, 0x90, 0x73, 0xd5, 0x74, 0xda, 0xe2, 0x61, 0x00,
- 0x68, 0x04, 0x40, 0x09, 0x6e, 0x00, 0xe8, 0x00, 0x00, 0x64, 0x02, 0x65,
- 0x08, 0x69, 0x11, 0x6c, 0x26, 0x70, 0x2c, 0x73, 0x33, 0x79, 0x45, 0x00,
- 0xc7, 0x40, 0x06, 0x6f, 0x77, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x05, 0x0b, 0x00, 0x37, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x3b, 0x40, 0x08, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x08, 0x61, 0x70, 0x65,
- 0x72, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x07, 0x40, 0x09, 0x72, 0x65, 0x65,
- 0x6e, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x65, 0x00, 0x01, 0x15, 0xe1, 0x68,
- 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x10, 0x6e, 0x14, 0x73, 0x1a,
- 0x05, 0x0c, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x02, 0x2d,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x00, 0x40, 0x09, 0x65, 0x65, 0x00, 0xe4, 0x00, 0x00,
- 0x69, 0x02, 0x6d, 0x1b, 0x6e, 0x23, 0x05, 0x0d, 0xe1, 0x73, 0x00, 0xe2,
- 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x79,
- 0x06, 0x00, 0x09, 0x40, 0x00, 0x63, 0x00, 0x00, 0x00, 0x40, 0x07, 0x61,
- 0x6c, 0x69, 0x6e, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x07, 0x69, 0x0b,
- 0x40, 0x06, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x79, 0x00, 0x40,
- 0x09, 0x71, 0x75, 0x65, 0x74, 0x00, 0x40, 0x0b, 0x6c, 0x65, 0x00, 0x00,
- 0x55, 0xe9, 0x00, 0x00, 0x61, 0x02, 0x62, 0x07, 0x65, 0x0d, 0x68, 0x28,
- 0x6c, 0x36, 0x6e, 0x3c, 0x70, 0x96, 0x72, 0xa8, 0x00, 0xfa, 0x40, 0x08,
- 0x72, 0x64, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x74, 0x00, 0xe2, 0x6c, 0x00,
- 0x72, 0x14, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x08, 0x05, 0x0e, 0x40,
- 0x06, 0x74, 0x74, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0xec,
- 0xe1, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0xb2, 0x64, 0x00,
- 0x00, 0x09, 0x40, 0x09, 0x69, 0x6e, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x65,
- 0x02, 0x68, 0x06, 0x69, 0x0d, 0x73, 0x11, 0x00, 0x09, 0x40, 0x08, 0x65,
- 0x00, 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x09, 0x65, 0x00,
- 0xe5, 0x66, 0x00, 0x68, 0x06, 0x6d, 0x0b, 0x70, 0x18, 0x77, 0x20, 0x40,
- 0x07, 0x6f, 0x6c, 0x6b, 0x00, 0x40, 0x09, 0x69, 0x70, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x07, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x06, 0x6f, 0x70,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06, 0x40, 0x07, 0x6d, 0x69, 0x61,
- 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x2c, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x07, 0x00, 0x00, 0x40, 0x06, 0x74, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e, 0xe2, 0x63,
- 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00, 0x40, 0x06, 0x74, 0x00,
- 0x00, 0x07, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x93, 0x40,
- 0x08, 0x6f, 0x79, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65,
- 0x2b, 0x08, 0x69, 0x26, 0x0a, 0x6f, 0x05, 0x0e, 0x75, 0xaf, 0x0f, 0x79,
- 0x16, 0x11, 0x00, 0x00, 0xff, 0x62, 0x00, 0x00, 0x63, 0x1c, 0x00, 0x64,
- 0xbf, 0x00, 0x66, 0x4a, 0x01, 0x67, 0x6d, 0x01, 0x69, 0xae, 0x01, 0x6a,
- 0x44, 0x02, 0x6d, 0x4d, 0x02, 0x6e, 0xab, 0x02, 0x70, 0xfa, 0x06, 0x73,
- 0x5e, 0x07, 0x75, 0x7a, 0x07, 0x76, 0xa0, 0x07, 0x77, 0xeb, 0x07, 0x79,
- 0xf9, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x65, 0x00, 0x68, 0x18, 0x69,
- 0x34, 0x6b, 0x39, 0x74, 0x66, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x72, 0x08,
- 0x05, 0x0f, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x0d, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x06, 0x74, 0x6f, 0x6d, 0x79, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x12, 0x6c, 0x16, 0x73,
- 0x1c, 0x01, 0x05, 0xe1, 0x61, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x04, 0x40,
- 0x09, 0x6b, 0x00, 0x40, 0x06, 0x6c, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08, 0x75, 0x69, 0x74, 0x00, 0xe5,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x69, 0x1e, 0x6f, 0x23, 0x05, 0x10,
- 0x40, 0x00, 0x73, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07,
- 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x54, 0x00, 0x54, 0x45, 0x11, 0x6f, 0x6e, 0x00, 0x45, 0x12, 0x72,
- 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x44, 0x75, 0x73, 0x00, 0x00,
- 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x72, 0x08, 0x73, 0x0a, 0x05, 0x0f, 0x40,
- 0x93, 0x61, 0x72, 0x6b, 0x00, 0x00, 0x07, 0xe3, 0x6d, 0x00, 0x70, 0x0d,
- 0x77, 0x15, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07,
- 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40,
- 0x07, 0x67, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74,
- 0x02, 0x00, 0x07, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe1, 0x66, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x06,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x19,
- 0xe1, 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x06, 0x6e, 0x00, 0x40, 0x09, 0x6e, 0x6e, 0x65, 0x00, 0x00,
- 0x06, 0xe1, 0x63, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6f, 0x08, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x05, 0x40, 0x06, 0x64, 0x79, 0x00, 0x40, 0x00, 0x63, 0x00,
- 0xe4, 0x6c, 0x00, 0x6e, 0x24, 0x70, 0x72, 0x74, 0x77, 0xe3, 0x00, 0x00,
- 0x62, 0x02, 0x65, 0x19, 0x01, 0x05, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x7a, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe6, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x0f, 0x6c, 0x14, 0x6d, 0x1a, 0x73, 0x27, 0x05, 0x13,
- 0xe3, 0x64, 0x00, 0x65, 0x02, 0x72, 0x04, 0x00, 0x37, 0x00, 0x06, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x64, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x08, 0x72, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x5e, 0x73, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x06, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00,
- 0x06, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x06, 0x65, 0x63, 0x74, 0x6f,
- 0x72, 0x79, 0x00, 0xe6, 0x00, 0x00, 0x63, 0x02, 0x6c, 0x07, 0x6d, 0x0e,
- 0x70, 0x2a, 0x77, 0x4c, 0x00, 0x09, 0x40, 0x08, 0x61, 0x72, 0x00, 0x40,
- 0x00, 0x69, 0x6e, 0x65, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x12, 0xe2,
- 0x64, 0x00, 0x6c, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x93, 0x40, 0x37, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x00,
- 0x00, 0x65, 0x02, 0x6c, 0x06, 0x6f, 0x12, 0x01, 0x05, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0x40, 0x82, 0x6c, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x08, 0x61, 0x79,
- 0x00, 0xf3, 0x63, 0x00, 0x00, 0x71, 0x0b, 0x00, 0x73, 0x30, 0x00, 0xe2,
- 0x65, 0x00, 0x68, 0x02, 0x00, 0x09, 0x40, 0x08, 0x65, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0xda, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xc1,
- 0x61, 0x16, 0x31, 0x00, 0x33, 0x00, 0x00, 0x00, 0x56, 0x00, 0xd6, 0x00,
- 0xdd, 0x00, 0xea, 0x00, 0x6d, 0x01, 0x00, 0x00, 0x9e, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x05, 0x02, 0x73, 0x02, 0x06, 0x03, 0x10, 0x03, 0x1f, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0xa6, 0x03, 0x00, 0x00, 0xe6, 0x03, 0xf5, 0x03,
- 0x00, 0x54, 0xe2, 0x63, 0x00, 0x74, 0x15, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x72, 0x40, 0x06, 0x6f, 0x6e, 0x00,
- 0x40, 0x09, 0x72, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63,
- 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x3e, 0x72, 0x4a, 0xe2, 0x69, 0x00, 0x6e,
- 0x06, 0x40, 0x06, 0x76, 0x65, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0xad, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x07, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0xe1, 0x73,
- 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x06, 0x40, 0x00,
- 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x00, 0xe1, 0x69,
- 0x00, 0xe2, 0x62, 0x00, 0x70, 0x0c, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x09, 0x75,
- 0x63, 0x65, 0x72, 0x00, 0xe2, 0x63, 0x00, 0x70, 0x04, 0x40, 0x3a, 0x74,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x2e, 0x6f, 0x51,
- 0x75, 0x6b, 0xe2, 0x63, 0x00, 0x72, 0x06, 0x40, 0x00, 0x74, 0x65, 0x64,
- 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x06, 0x72, 0x0c, 0x03, 0xc2,
- 0x40, 0x09, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe3, 0x67, 0x00, 0x6e, 0x14, 0x78, 0x1a, 0xe1, 0x75, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x0b, 0x40, 0x00, 0x69, 0x74, 0x65, 0x00, 0x00, 0x3a, 0xe1,
- 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09,
- 0x02, 0xa9, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72,
- 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x11, 0xe1, 0x6e, 0x00,
- 0xe2, 0x64, 0x00, 0x69, 0x05, 0x40, 0x08, 0x65, 0x72, 0x00, 0x40, 0x00,
- 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe3,
- 0x00, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x0b, 0x40, 0x06, 0x6f, 0x6e,
- 0x00, 0x40, 0x06, 0x72, 0x00, 0xe3, 0x65, 0x00, 0x73, 0x13, 0x74, 0x28,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x56, 0xe1, 0x74, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40,
- 0x3a, 0x7a, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x2c, 0x00,
- 0x93, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x95, 0x40, 0x3b, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x05, 0x14, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x00, 0x72, 0x79, 0x00,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x69, 0x26, 0x6f, 0x41, 0x75, 0x4a, 0x00,
- 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0f, 0x6f,
- 0x14, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x02, 0x93, 0x00, 0x37, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00, 0x07,
- 0x00, 0x3b, 0xe3, 0x69, 0x00, 0x6f, 0x5f, 0x75, 0x7b, 0xe3, 0x67, 0x00,
- 0x73, 0x15, 0x74, 0x29, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e,
- 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x62, 0x00, 0x6f, 0x05,
- 0x40, 0x00, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x74, 0x02, 0x00, 0x08, 0xe3, 0x61, 0x00, 0x65, 0x13, 0x69, 0x1c, 0xe3,
- 0x62, 0x00, 0x6c, 0x05, 0x6e, 0x07, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x00,
- 0x07, 0x40, 0x07, 0x63, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x67, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03, 0xd9,
- 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x06, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x03, 0x5a, 0x40, 0x09, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x61, 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x08, 0x40, 0x00, 0x65, 0x61,
- 0x6e, 0x69, 0x63, 0x00, 0x00, 0x06, 0xe4, 0x61, 0x00, 0x69, 0x1d, 0x6c,
- 0x2e, 0x6f, 0x45, 0xe2, 0x63, 0x00, 0x72, 0x07, 0x40, 0x00, 0x69, 0x66,
- 0x69, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00,
- 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x00, 0x3b, 0xe1, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00,
- 0x3a, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x55, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe4, 0x6c, 0x00, 0x6e, 0x05, 0x72, 0x0b, 0x73, 0x22, 0x40, 0x00, 0x61,
- 0x72, 0x00, 0x40, 0x06, 0x64, 0x65, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x02, 0xa9, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x3a, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x68, 0x18, 0xe1, 0x78, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73,
- 0x6d, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x6d,
- 0x02, 0x70, 0x08, 0x00, 0x50, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x62, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x73, 0x05,
- 0x40, 0x86, 0x73, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe2,
- 0x73, 0x00, 0x74, 0x04, 0x40, 0x07, 0x6d, 0x00, 0x40, 0x09, 0x65, 0x00,
- 0xe5, 0x00, 0x00, 0x64, 0x02, 0x65, 0x08, 0x70, 0x2a, 0x73, 0x4f, 0x00,
- 0x09, 0x40, 0x09, 0x6f, 0x6f, 0x72, 0x00, 0xe1, 0x7a, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x06, 0x40, 0x06, 0x75, 0x6d, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0f,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x00, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x08, 0x00, 0x07, 0x40, 0x07, 0x68, 0x6f, 0x6f, 0x74,
- 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02,
- 0x69, 0x07, 0x79, 0x0e, 0x00, 0x59, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe1, 0x6d, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe1, 0x69, 0x00,
- 0xe2, 0x63, 0x00, 0x7a, 0x0d, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x0b, 0x65, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x05, 0x40, 0x93, 0x69, 0x6c, 0x00, 0xe3, 0x6c, 0x00, 0x72,
- 0x27, 0x73, 0x35, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0b, 0x6c, 0x10,
- 0x6f, 0x16, 0x03, 0xc5, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00,
- 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x67, 0x75, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x06, 0x6c, 0x00, 0x00, 0x5e, 0x40, 0xa1, 0x74, 0x79,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x05, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0x09, 0xfc, 0x61, 0x00, 0x00, 0x62, 0x9b, 0x00,
- 0x65, 0xa0, 0x00, 0x66, 0xcc, 0x00, 0x6b, 0xd2, 0x00, 0x6c, 0xec, 0x00,
- 0x6d, 0xf2, 0x00, 0x6e, 0x35, 0x01, 0x70, 0xa4, 0x01, 0x73, 0xae, 0x01,
- 0x77, 0xd0, 0x01, 0x79, 0xd4, 0x01, 0xe4, 0x63, 0x00, 0x64, 0x2e, 0x73,
- 0x41, 0x74, 0x6c, 0xe2, 0x68, 0x00, 0x6c, 0x20, 0xe1, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x6f, 0x00, 0x79, 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x07, 0x00,
- 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6d, 0x06, 0x05, 0x15, 0x40, 0x5e,
- 0x65, 0x00, 0x40, 0x09, 0x69, 0x6c, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x6f,
- 0x02, 0x75, 0x11, 0x00, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0xd4, 0x40, 0x00, 0x75, 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00,
- 0x07, 0x00, 0x06, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c,
- 0x6d, 0x11, 0x79, 0x17, 0x05, 0x16, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x06, 0x73, 0x65, 0x00, 0x40, 0x09, 0x65,
- 0x6e, 0x74, 0x00, 0x00, 0x06, 0x40, 0x82, 0x6c, 0x65, 0x00, 0xe4, 0x00,
- 0x00, 0x69, 0x02, 0x6c, 0x07, 0x74, 0x1e, 0x00, 0xb2, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x73, 0x73, 0x00,
- 0xe2, 0x6b, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x65,
- 0x00, 0x40, 0x06, 0x6f, 0x70, 0x00, 0x40, 0x06, 0x6f, 0x69, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0x40, 0x59, 0x6c, 0x69, 0x73, 0x00, 0xe5, 0x61, 0x00, 0x62,
- 0x07, 0x65, 0x0c, 0x6f, 0x14, 0x75, 0x1f, 0x40, 0x09, 0x74, 0x6f, 0x64,
- 0x65, 0x00, 0x40, 0x5e, 0x6c, 0x65, 0x00, 0x40, 0x3b, 0x6e, 0x64, 0x6f,
- 0x75, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x72, 0x04, 0x40, 0x06, 0x6f, 0x00,
- 0x00, 0x09, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x63, 0x00, 0x64, 0x37, 0xe1, 0x68, 0x00, 0xe4,
- 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x65, 0x14, 0x00, 0xab, 0x40, 0x00,
- 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0x00, 0x3b, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02,
- 0x00, 0x09, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x73, 0x11, 0x79, 0x28,
- 0x00, 0x95, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x08, 0x72, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x03, 0x35, 0x40, 0x07, 0x69, 0x64, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0xe3, 0x70, 0x00, 0x73, 0x14, 0x74, 0x16, 0xe1,
- 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x00, 0xd2, 0x40, 0x09, 0x6c,
- 0x65, 0x00, 0x40, 0x00, 0x73, 0x00, 0x00, 0x09, 0xc0, 0x61, 0x16, 0x2f,
- 0x00, 0x8b, 0x00, 0xfc, 0x00, 0x7d, 0x01, 0x83, 0x01, 0x95, 0x01, 0xb5,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x01, 0xfa, 0x01, 0x44,
- 0x02, 0x91, 0x02, 0xb0, 0x02, 0xb2, 0x02, 0x00, 0x00, 0x25, 0x03, 0x2b,
- 0x03, 0x40, 0x03, 0x5b, 0x03, 0x9f, 0x03, 0xe5, 0x64, 0x00, 0x67, 0x02,
- 0x6c, 0x06, 0x6e, 0x18, 0x74, 0x3d, 0x00, 0x06, 0x40, 0x07, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x65, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x6c, 0x00,
- 0x75, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x3b, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x08, 0x74, 0x65, 0x00, 0x40,
- 0x06, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x0f, 0x75, 0x3b, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07, 0x73, 0x6d,
- 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0xe2, 0x6d, 0x00, 0x77,
- 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe3, 0x6c, 0x00,
- 0x6e, 0x08, 0x74, 0x13, 0x40, 0x06, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x06, 0x6c, 0x00, 0x00, 0x09, 0xe2,
- 0x61, 0x00, 0x65, 0x05, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe2, 0x00, 0x00,
- 0x27, 0x02, 0x05, 0x17, 0x40, 0x00, 0x73, 0x00, 0xe5, 0x65, 0x00, 0x68,
- 0x21, 0x6b, 0x3b, 0x6f, 0x6a, 0x79, 0x70, 0xe4, 0x00, 0x00, 0x6e, 0x02,
- 0x70, 0x0c, 0x72, 0x10, 0x00, 0x07, 0x40, 0x09, 0x74, 0x65, 0x6e, 0x6e,
- 0x69, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x73, 0x00, 0x40, 0x07, 0x61, 0x74,
- 0x6f, 0x70, 0x73, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x40, 0x07, 0x73, 0x69, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69,
- 0x07, 0x6c, 0x16, 0x73, 0x1a, 0x79, 0x20, 0x00, 0x95, 0x40, 0x07, 0x72,
- 0x79, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x82, 0x65, 0x00, 0x40, 0x06, 0x74,
- 0x65, 0x72, 0x00, 0x01, 0x3b, 0x40, 0x06, 0x6c, 0x6f, 0x72, 0x00, 0x40,
- 0x06, 0x63, 0x6c, 0x65, 0x00, 0x40, 0x09, 0x65, 0x6e, 0x74, 0x00, 0xe3,
- 0x64, 0x00, 0x6e, 0x02, 0x72, 0x09, 0x00, 0x37, 0x40, 0x86, 0x6e, 0x69,
- 0x61, 0x6c, 0x00, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x6c, 0x06, 0x6f, 0x12,
- 0x40, 0x06, 0x63, 0x74, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x07, 0x63, 0x61, 0x6c, 0x73,
- 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6c, 0x07, 0x6f, 0x11, 0x00, 0x07,
- 0x40, 0x47, 0x65, 0x72, 0x00, 0x40, 0x09, 0x79, 0x63, 0x65, 0x72, 0x69,
- 0x64, 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x0e, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x07, 0x40, 0x06, 0x65, 0x00, 0xe4, 0x61,
- 0x00, 0x62, 0x08, 0x6c, 0x0c, 0x6f, 0x32, 0x40, 0x08, 0x74, 0x65, 0x72,
- 0x61, 0x6c, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x95, 0xe2, 0x6f, 0x00, 0x75, 0x16, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x01, 0x58, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x07, 0x6d, 0x00, 0xe2, 0x62, 0x00,
- 0x67, 0x06, 0x40, 0x06, 0x69, 0x74, 0x65, 0x00, 0x40, 0x06, 0x79, 0x00,
- 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x6d, 0x0f, 0x6e, 0x32, 0x6f,
- 0x38, 0x01, 0x8f, 0x40, 0x09, 0x72, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x73,
- 0x74, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0f, 0xe3, 0x64, 0x00,
- 0x72, 0x02, 0x73, 0x04, 0x00, 0x37, 0x00, 0x06, 0x40, 0x00, 0x74, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x06, 0x00, 0x07, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6e,
- 0x74, 0x68, 0x6c, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x6b, 0x15, 0xe1, 0x74,
- 0x00, 0xe2, 0x72, 0x00, 0x79, 0x0b, 0x40, 0x07, 0x6f, 0x74, 0x6f, 0x6c,
- 0x75, 0x65, 0x6e, 0x65, 0x00, 0x00, 0x06, 0x40, 0x06, 0x65, 0x74, 0x00,
- 0x00, 0x09, 0xe8, 0x00, 0x00, 0x61, 0x02, 0x65, 0x0a, 0x6c, 0x0c, 0x6f,
- 0x25, 0x70, 0x37, 0x74, 0x4a, 0x77, 0x5c, 0x00, 0x86, 0x40, 0x00, 0x72,
- 0x74, 0x69, 0x74, 0x65, 0x00, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x69, 0x0d,
- 0xe3, 0x00, 0x00, 0x74, 0x02, 0x78, 0x04, 0x00, 0x82, 0x00, 0x06, 0x00,
- 0x09, 0x40, 0x82, 0x63, 0x61, 0x74, 0x65, 0x00, 0xe2, 0x64, 0x00, 0x73,
- 0x0b, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00,
- 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02,
- 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x79, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0x40, 0x08, 0x69, 0x72, 0x65, 0x00, 0x40, 0x06, 0x65,
- 0x6d, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x7a, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x11, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x72, 0x08,
- 0x05, 0x18, 0x42, 0xbc, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x75, 0x6d, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x70, 0x00, 0x76, 0x2a, 0xe1,
- 0x68, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x73, 0x1e, 0x00, 0xec, 0xe2,
- 0x6c, 0x00, 0x6e, 0x13, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,
- 0x3b, 0x74, 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x06, 0x74, 0x65, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x07, 0x69, 0x0b, 0x40, 0x00, 0x6c, 0x65, 0x6e, 0x74,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x75, 0x25, 0xe2, 0x00,
- 0x00, 0x6c, 0x02, 0x00, 0x07, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b,
- 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40,
- 0x07, 0x6d, 0x00, 0xfe, 0x63, 0x00, 0x00, 0x64, 0x11, 0x00, 0x67, 0x1d,
- 0x00, 0x69, 0x26, 0x00, 0x6c, 0x2b, 0x00, 0x6d, 0x4a, 0x00, 0x6e, 0x63,
- 0x00, 0x6f, 0x65, 0x00, 0x70, 0x7b, 0x00, 0x74, 0xab, 0x00, 0x75, 0xc9,
- 0x00, 0x76, 0x6e, 0x01, 0x77, 0x72, 0x01, 0x79, 0x7d, 0x01, 0xe1, 0x68,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x00, 0x69, 0x63, 0x00, 0x40,
- 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x01, 0xca, 0x40, 0x77,
- 0x65, 0x6e, 0x00, 0x40, 0x06, 0x6c, 0x6f, 0x64, 0x79, 0x74, 0x65, 0x00,
- 0x40, 0x09, 0x6b, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6f, 0x11, 0x00, 0x93, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x62,
- 0x02, 0x00, 0x06, 0x40, 0x09, 0x75, 0x73, 0x00, 0x40, 0x06, 0x70, 0x00,
- 0xe2, 0x62, 0x00, 0x70, 0x12, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00,
- 0x5b, 0x00, 0x08, 0xe1, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73,
- 0x06, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0x40, 0x09, 0x68, 0x69, 0x70,
- 0x00, 0xe4, 0x65, 0x00, 0x68, 0x02, 0x69, 0x06, 0x6f, 0x1e, 0x00, 0x06,
- 0x40, 0x06, 0x79, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x0f, 0xe3, 0x00, 0x00,
- 0x61, 0x02, 0x73, 0x06, 0x00, 0x09, 0x40, 0x3b, 0x6c, 0x00, 0x00, 0x07,
- 0x40, 0x06, 0x6d, 0x00, 0x40, 0x06, 0x73, 0x70, 0x68, 0x65, 0x72, 0x65,
- 0x00, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x74, 0x04, 0x00, 0x09, 0x00, 0x07,
- 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe6, 0x62, 0x00, 0x67, 0x4c,
- 0x6e, 0x58, 0x70, 0x67, 0x73, 0x73, 0x74, 0x96, 0xe2, 0x61, 0x00, 0x6c,
- 0x07, 0x40, 0x09, 0x64, 0x6f, 0x75, 0x72, 0x00, 0xe1, 0x65, 0x00, 0xe4,
- 0x00, 0x00, 0x64, 0x02, 0x6d, 0x04, 0x73, 0x0b, 0x00, 0x5e, 0x00, 0x37,
- 0x40, 0x09, 0x61, 0x6b, 0x65, 0x72, 0x00, 0xe2, 0x68, 0x00, 0x6f, 0x1f,
- 0xe1, 0x6f, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x15, 0xe1, 0x74, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x4c, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x40, 0x3b, 0x6d, 0x65, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0xe1, 0x63, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01,
- 0x4b, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0xa5, 0x00, 0x07, 0xe2, 0x65, 0x00, 0x73, 0x0c, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x00, 0x00, 0x78, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x06, 0x40, 0x06, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x3a, 0x40, 0x47, 0x6c, 0x00, 0x00, 0x08, 0xfc, 0x61, 0x00,
- 0x00, 0x63, 0x0e, 0x00, 0x64, 0x4b, 0x00, 0x65, 0x50, 0x00, 0x66, 0x5d,
- 0x00, 0x67, 0x63, 0x00, 0x69, 0x65, 0x00, 0x6c, 0x6a, 0x00, 0x6d, 0x6e,
- 0x00, 0x6e, 0x8c, 0x00, 0x73, 0xbe, 0x00, 0x74, 0x18, 0x01, 0xe1, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x59,
- 0xe3, 0x65, 0x00, 0x6b, 0x02, 0x75, 0x22, 0x00, 0x06, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6c, 0x0b, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x82,
- 0x40, 0x06, 0x61, 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x3b, 0x40, 0x82, 0x67, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x05,
- 0x19, 0x40, 0x06, 0x6f, 0x76, 0x65, 0x00, 0x40, 0x09, 0x66, 0x6c, 0x65,
- 0x00, 0x00, 0x08, 0x40, 0x09, 0x73, 0x6d, 0x00, 0x40, 0x37, 0x79, 0x00,
- 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x93, 0xe2, 0x72,
- 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x63, 0x00, 0x64, 0x1a, 0x6b,
- 0x29, 0xe2, 0x61, 0x00, 0x68, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x65,
- 0x6f, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x02, 0x1a, 0xe2, 0x73, 0x00, 0x74,
- 0x02, 0x00, 0x59, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x66, 0x12, 0x69, 0x25,
- 0x77, 0x2a, 0x79, 0x44, 0x01, 0x87, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x09, 0x40, 0x06, 0x68, 0x69, 0x70, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x7d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x92,
- 0x01, 0x72, 0xe1, 0x68, 0x00, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x69, 0x15,
- 0x73, 0x1c, 0x00, 0xdb, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0xe7, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0x37, 0xe5, 0x00, 0x00, 0x27,
- 0x02, 0x69, 0x06, 0x6f, 0x0b, 0x73, 0x10, 0x00, 0x4b, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0x40,
- 0x2c, 0x74, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x08, 0x70, 0x0e, 0x75, 0x10,
- 0x40, 0x00, 0x72, 0x69, 0x73, 0x74, 0x73, 0x00, 0x40, 0x09, 0x74, 0x73,
- 0x65, 0x00, 0x00, 0x00, 0x40, 0x06, 0x6e, 0x61, 0x6d, 0x69, 0x00, 0x40,
- 0x00, 0x79, 0x73, 0x00, 0xfe, 0x62, 0x00, 0x00, 0x63, 0x84, 0x00, 0x66,
- 0x92, 0x00, 0x67, 0xa0, 0x00, 0x69, 0xbd, 0x00, 0x6c, 0xc4, 0x00, 0x6d,
- 0xdb, 0x00, 0x6e, 0x65, 0x01, 0x70, 0xc9, 0x01, 0x71, 0xe5, 0x01, 0x72,
- 0xea, 0x01, 0x73, 0x76, 0x03, 0x74, 0x99, 0x03, 0x78, 0xec, 0x03, 0xe7,
- 0x00, 0x00, 0x61, 0x02, 0x62, 0x0b, 0x65, 0x0f, 0x66, 0x5d, 0x69, 0x62,
- 0x75, 0x67, 0x00, 0xfa, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x09, 0x00,
- 0x00, 0x40, 0x60, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x72, 0x08,
- 0x00, 0x09, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x63,
- 0x02, 0x6f, 0x2b, 0x00, 0x07, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x06,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x6f, 0x08,
- 0x40, 0x00, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe2, 0x73, 0x00, 0x75,
- 0x05, 0x40, 0x07, 0x69, 0x73, 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x73,
- 0x00, 0x75, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x09, 0x75, 0x6c, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x00, 0x72, 0x00, 0x00, 0x09, 0xe1,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x2f, 0x72,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40,
- 0x07, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x67, 0x08, 0x00, 0x06,
- 0x40, 0x09, 0x6f, 0x61, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40, 0x53, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x08, 0x6c, 0x0c, 0x40, 0x07,
- 0x72, 0x65, 0x6d, 0x69, 0x61, 0x00, 0x40, 0x06, 0x70, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0xe7, 0x00, 0x00, 0x62, 0x02, 0x65, 0x2f, 0x69, 0x46, 0x6d,
- 0x55, 0x6f, 0x59, 0x75, 0x68, 0x00, 0x08, 0xe2, 0x6c, 0x00, 0x72, 0x23,
- 0xe2, 0x65, 0x00, 0x69, 0x19, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x72, 0x08,
- 0x77, 0x0a, 0x00, 0x7e, 0x40, 0x00, 0x6f, 0x77, 0x6e, 0x00, 0x00, 0x07,
- 0x40, 0x06, 0x65, 0x65, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40,
- 0x06, 0x65, 0x6c, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65,
- 0x00, 0x00, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe1, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x00, 0x75, 0x73,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02,
- 0x00, 0x06, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x61,
- 0x02, 0x64, 0x04, 0x65, 0x09, 0x67, 0x35, 0x69, 0x3c, 0x6e, 0x40, 0x00,
- 0xfa, 0x00, 0x09, 0x40, 0x06, 0x72, 0x61, 0x00, 0xe5, 0x00, 0x00, 0x66,
- 0x02, 0x6c, 0x15, 0x72, 0x1b, 0x75, 0x1d, 0x00, 0x09, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b, 0x65, 0x73, 0x73, 0x00, 0x00, 0x07,
- 0x40, 0x06, 0x70, 0x00, 0x40, 0x07, 0x73, 0x74, 0x65, 0x6e, 0x00, 0x40,
- 0x06, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x0e, 0xe1, 0x6c, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x04, 0xc1, 0x40, 0x07, 0x72, 0x00, 0x00, 0x06,
- 0xe2, 0x6c, 0x00, 0x70, 0x04, 0x40, 0x08, 0x65, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x65, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0x40, 0x06, 0x75, 0x65, 0x00, 0xfc, 0x62, 0x00,
- 0x00, 0x64, 0x6f, 0x00, 0x65, 0x7d, 0x00, 0x66, 0x82, 0x00, 0x67, 0x8b,
- 0x00, 0x6b, 0x9d, 0x00, 0x6d, 0xa2, 0x00, 0x6e, 0xb2, 0x00, 0x70, 0x27,
- 0x01, 0x71, 0x3f, 0x01, 0x72, 0x47, 0x01, 0x74, 0x4c, 0x01, 0xe4, 0x61,
- 0x00, 0x69, 0x04, 0x6f, 0x19, 0x75, 0x52, 0x40, 0xb1, 0x6e, 0x00, 0xe2,
- 0x64, 0x00, 0x6e, 0x0c, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40,
- 0x07, 0x74, 0x79, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x63,
- 0x02, 0x66, 0x1a, 0x6a, 0x1f, 0x70, 0x24, 0x74, 0x2a, 0x00, 0x06, 0xe1,
- 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x67, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0x40,
- 0x06, 0x61, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x74, 0x00, 0x40, 0x06, 0x72,
- 0x6f, 0x70, 0x00, 0x00, 0x06, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0x3b, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40, 0x06, 0x63, 0x6b,
- 0x65, 0x6e, 0x00, 0x40, 0x06, 0x65, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x79,
- 0x02, 0x00, 0x47, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40,
- 0x06, 0x65, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x06, 0x40, 0x06, 0x72,
- 0x69, 0x63, 0x00, 0x40, 0x09, 0x69, 0x6c, 0x00, 0xeb, 0x00, 0x00, 0x61,
- 0x02, 0x62, 0x14, 0x63, 0x1c, 0x65, 0x22, 0x69, 0x26, 0x6b, 0x31, 0x6f,
- 0x36, 0x70, 0x4a, 0x73, 0x50, 0x74, 0x57, 0x05, 0x1a, 0xe2, 0x62, 0x00,
- 0x72, 0x06, 0x40, 0x06, 0x6f, 0x75, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x75,
- 0x6e, 0x64, 0x00, 0x40, 0x06, 0x75, 0x63, 0x6b, 0x6c, 0x65, 0x00, 0x40,
- 0x06, 0x6f, 0x61, 0x74, 0x00, 0x40, 0x75, 0x72, 0x00, 0xe2, 0x6e, 0x00,
- 0x70, 0x04, 0x40, 0x09, 0x67, 0x00, 0x00, 0x06, 0x40, 0x09, 0x65, 0x79,
- 0x00, 0xe3, 0x66, 0x00, 0x75, 0x04, 0x76, 0x08, 0x40, 0x09, 0x66, 0x00,
- 0x40, 0x09, 0x74, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x09, 0x69,
- 0x6b, 0x65, 0x00, 0x40, 0x06, 0x74, 0x69, 0x6c, 0x65, 0x00, 0x40, 0x06,
- 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x08, 0x73, 0x0f,
- 0x40, 0x07, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x74, 0x75,
- 0x64, 0x65, 0x00, 0x00, 0x00, 0x40, 0x06, 0x75, 0x6f, 0x69, 0x73, 0x65,
- 0x00, 0x40, 0xb1, 0x65, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x08, 0x00, 0x06, 0x40, 0x06, 0x6f,
- 0x76, 0x65, 0x00, 0x40, 0xb1, 0x65, 0x63, 0x6b, 0x00, 0xe3, 0x68, 0x00,
- 0x6b, 0x02, 0x73, 0x04, 0x00, 0x09, 0x00, 0xb2, 0xe2, 0x6c, 0x00, 0x6f,
- 0x04, 0x40, 0x5e, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x6b, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x65,
- 0x02, 0x6f, 0x15, 0x74, 0x32, 0x75, 0x46, 0x00, 0x06, 0xe1, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x67, 0x00, 0x72, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x73, 0x0b, 0x00, 0x2c, 0x40, 0x37, 0x64, 0x00, 0x40, 0x06,
- 0x61, 0x6c, 0x00, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x67, 0x00, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x09, 0x40, 0x06, 0x64, 0x6f, 0x00, 0xf5, 0x61, 0x00, 0x00, 0x65,
- 0x31, 0x00, 0x69, 0xc5, 0x00, 0x6f, 0xb6, 0x01, 0x70, 0xe8, 0x01, 0xe5,
- 0x64, 0x00, 0x69, 0x12, 0x6e, 0x16, 0x73, 0x22, 0x74, 0x24, 0xe1, 0x64,
- 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xa5, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x2c, 0x00, 0xf3, 0x00, 0x00, 0x00, 0x08,
- 0xe5, 0x61, 0x00, 0x65, 0x04, 0x6c, 0x31, 0x6e, 0x64, 0x72, 0x80, 0x40,
- 0x2c, 0x6b, 0x00, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x0f, 0x74, 0x11,
- 0x7a, 0x1c, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x79, 0x04, 0x00,
- 0x06, 0x00, 0x07, 0x00, 0xf3, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x65, 0x72, 0x73, 0x00,
- 0xe2, 0x66, 0x00, 0x76, 0x0f, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x12, 0xe1,
- 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x01, 0x58, 0xe2, 0x6b, 0x00, 0x70, 0x02,
- 0x00, 0x7a, 0x00, 0x06, 0xe9, 0x63, 0x00, 0x64, 0x04, 0x67, 0x13, 0x6c,
- 0x2c, 0x6e, 0x3f, 0x72, 0x81, 0x73, 0x93, 0x74, 0xab, 0x78, 0xda, 0x40,
- 0x00, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x82, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00,
- 0x09, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x60, 0xe2, 0x69, 0x00, 0x6c, 0x0c,
- 0xe2, 0x67, 0x00, 0x74, 0x05, 0x40, 0x07, 0x68, 0x74, 0x00, 0x00, 0x00,
- 0x00, 0x20, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x67, 0x0b, 0x6b, 0x0f, 0x6e,
- 0x22, 0x73, 0x30, 0x00, 0xe7, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06,
- 0x00, 0x07, 0x40, 0x5e, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x03,
- 0x6c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x01, 0x01, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x40, 0x08, 0x65, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x79, 0x06, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00,
- 0x00, 0x00, 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x65, 0x06,
- 0x79, 0x0a, 0x01, 0x73, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x00, 0x60, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x74, 0x0e, 0x00, 0x09, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x59, 0x00, 0xf3, 0xe2,
- 0x65, 0x00, 0x69, 0x10, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x79, 0x02, 0x00, 0x47, 0x00, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x66, 0x02, 0x70, 0x10,
- 0x73, 0x23, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x6f, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x00, 0x6c, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x63, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x06, 0x6f, 0x6d, 0x65, 0x00, 0x00, 0x00, 0xf6, 0x63, 0x00,
- 0x00, 0x69, 0x06, 0x00, 0x6b, 0x0b, 0x00, 0x6d, 0x0f, 0x00, 0x70, 0x30,
- 0x00, 0x72, 0x25, 0x01, 0x40, 0x06, 0x6f, 0x6f, 0x6e, 0x00, 0x41, 0xca,
- 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x0f, 0xe3, 0x00, 0x00,
- 0x63, 0x02, 0x73, 0x04, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x74, 0x00,
- 0x40, 0x06, 0x6d, 0x00, 0xe4, 0x65, 0x00, 0x68, 0x6d, 0x69, 0x83, 0x6f,
- 0xb6, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x63, 0x06, 0x66, 0x0c, 0x73, 0x12,
- 0x77, 0x36, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x40, 0x3c, 0x61, 0x73,
- 0x74, 0x00, 0x40, 0x09, 0x61, 0x63, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x65,
- 0x07, 0x40, 0x09, 0x72, 0x69, 0x70, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x1d, 0xe1, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09,
- 0x74, 0x0e, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xe8, 0x00, 0x07, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x00, 0x40, 0x00, 0x74,
- 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x75, 0x0d, 0xe2, 0x69, 0x00, 0x6f, 0x04,
- 0x40, 0x07, 0x64, 0x00, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x07, 0x73, 0x00,
- 0xe4, 0x63, 0x00, 0x66, 0x12, 0x6e, 0x22, 0x73, 0x26, 0xe1, 0x61, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x36, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x09, 0x40, 0x07, 0x63, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x02, 0x3e, 0x40, 0x07, 0x67, 0x00, 0x40,
- 0x06, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x6c, 0x29, 0x00, 0x09,
- 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x68, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x12, 0x40, 0x06, 0x72, 0x00, 0xe1,
- 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c,
- 0x00, 0x00, 0x07, 0x40, 0x06, 0x6f, 0x67, 0x79, 0x00, 0xe2, 0x61, 0x00,
- 0x6f, 0x44, 0xe1, 0x6e, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x3a, 0xe3, 0x69,
- 0x00, 0x6f, 0x14, 0x79, 0x31, 0xe2, 0x63, 0x00, 0x7a, 0x0b, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x0b, 0x65,
- 0x00, 0xe2, 0x73, 0x00, 0x75, 0x14, 0xe1, 0x61, 0x00, 0xe1, 0x75, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x09, 0x40, 0x09,
- 0x73, 0x00, 0x40, 0x00, 0x73, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x09,
- 0xc1, 0x62, 0x17, 0x33, 0x00, 0x35, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00,
- 0x00, 0x56, 0x00, 0x6e, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85,
- 0x00, 0x96, 0x00, 0x83, 0x01, 0xef, 0x01, 0x00, 0x00, 0xe3, 0x13, 0x00,
- 0x00, 0x73, 0x16, 0xaa, 0x17, 0x78, 0x18, 0x00, 0x00, 0x05, 0x19, 0x00,
- 0x00, 0x20, 0x19, 0x00, 0x08, 0xe1, 0x69, 0x00, 0xe1, 0x71, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x6f, 0x00, 0x79,
- 0x05, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x00, 0x07, 0x40, 0x06, 0x64, 0x65,
- 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0xe2, 0x68, 0x00, 0x6c, 0x02, 0x00, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0x00,
- 0x00, 0xe2, 0x61, 0x00, 0x75, 0x05, 0x40, 0x06, 0x73, 0x65, 0x00, 0x40,
- 0x06, 0x6c, 0x65, 0x6c, 0x65, 0x00, 0xe5, 0x63, 0x00, 0x6e, 0x23, 0x73,
- 0x33, 0x74, 0x39, 0x75, 0xcd, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x6f, 0x11, 0x00, 0x06, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x40,
- 0x00, 0x75, 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x72, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x74, 0x65,
- 0x72, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x09, 0x72, 0x21, 0x00,
- 0x00, 0x40, 0x00, 0x72, 0x69, 0x6f, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x0e, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x02,
- 0x00, 0x12, 0x40, 0x09, 0x6d, 0x00, 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe7,
- 0x00, 0x00, 0x63, 0x02, 0x68, 0x10, 0x6c, 0x16, 0x6d, 0x1d, 0x73, 0x30,
- 0x76, 0x50, 0x00, 0x06, 0x40, 0x06, 0x6f, 0x6e, 0x73, 0x65, 0x72, 0x76,
- 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x00, 0x69, 0x67, 0x68, 0x00,
- 0x40, 0x06, 0x69, 0x67, 0x68, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x07,
- 0x40, 0x07, 0x72, 0x69, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x64, 0x65, 0x72,
- 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x13, 0xe1, 0x69,
- 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x40, 0x07,
- 0x69, 0x6f, 0x6c, 0x65, 0x74, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x38, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x69, 0x42, 0x6c, 0x47,
- 0x70, 0x4d, 0x00, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x72, 0x23, 0xe2,
- 0x6c, 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x07, 0xe1, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x04, 0x75, 0x06,
- 0x40, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x0b, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0x40, 0x07,
- 0x65, 0x00, 0x40, 0x06, 0x6c, 0x6c, 0x61, 0x00, 0x40, 0x06, 0x61, 0x6b,
- 0x00, 0x40, 0x09, 0x61, 0x75, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02,
- 0x74, 0x07, 0x00, 0x93, 0x40, 0x82, 0x72, 0x65, 0x00, 0x42, 0xdd, 0x65,
- 0x65, 0x6e, 0x00, 0xc0, 0x61, 0x19, 0x35, 0x00, 0x1c, 0x01, 0x7a, 0x01,
- 0x0e, 0x03, 0x5d, 0x08, 0x1a, 0x09, 0x1d, 0x0a, 0x87, 0x0a, 0xce, 0x0a,
- 0x93, 0x0c, 0x99, 0x0c, 0xca, 0x0c, 0x1d, 0x0d, 0xa4, 0x0d, 0xbc, 0x0d,
- 0xed, 0x0d, 0x81, 0x0e, 0x99, 0x0e, 0x53, 0x0f, 0xe0, 0x10, 0x4f, 0x11,
- 0x00, 0x00, 0x6d, 0x11, 0x00, 0x00, 0xea, 0x11, 0xeb, 0x62, 0x00, 0x63,
- 0x09, 0x64, 0x46, 0x65, 0x52, 0x6c, 0x5c, 0x6d, 0x66, 0x6e, 0x70, 0x70,
- 0x85, 0x73, 0xaa, 0x76, 0xc1, 0x77, 0xca, 0x40, 0x09, 0x72, 0x69, 0x64,
- 0x67, 0x65, 0x64, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x1c,
- 0xe1, 0x70, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x00, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0xe2, 0x6d, 0x00, 0x75, 0x0b, 0x40, 0x00, 0x6d,
- 0x6f, 0x64, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6e, 0x74,
- 0x61, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x76, 0x65, 0x6e, 0x74, 0x75,
- 0x72, 0x6f, 0x75, 0x73, 0x00, 0x40, 0x00, 0x73, 0x74, 0x68, 0x65, 0x74,
- 0x69, 0x63, 0x00, 0x40, 0x00, 0x74, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x79,
- 0x00, 0x40, 0x00, 0x62, 0x69, 0x74, 0x69, 0x6f, 0x75, 0x73, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe1, 0x70, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x07, 0x72, 0x10, 0x40, 0x00, 0x72, 0x65, 0x6e, 0x74,
- 0x00, 0x40, 0x00, 0x74, 0x69, 0x7a, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00,
- 0x65, 0x63, 0x69, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x75, 0x08, 0x40, 0x00, 0x72, 0x74, 0x69, 0x76, 0x65,
- 0x00, 0x40, 0x3b, 0x6d, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x61, 0x69,
- 0x6c, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x61, 0x72, 0x65, 0x00, 0xe5,
- 0x65, 0x00, 0x69, 0x17, 0x6c, 0x1b, 0x6f, 0x30, 0x72, 0x3f, 0xe2, 0x6b,
- 0x00, 0x6e, 0x09, 0x40, 0x00, 0x6e, 0x6f, 0x77, 0x6e, 0x73, 0x74, 0x00,
- 0xe2, 0x64, 0x00, 0x74, 0x02, 0x01, 0x21, 0x00, 0x00, 0x40, 0x00, 0x64,
- 0x00, 0xe2, 0x69, 0x00, 0x75, 0x08, 0x40, 0x3b, 0x6e, 0x6b, 0x69, 0x6e,
- 0x67, 0x00, 0x40, 0x3b, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x73,
- 0x00, 0x75, 0x05, 0x41, 0x20, 0x6f, 0x6d, 0x00, 0x40, 0xfc, 0x6e, 0x64,
- 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x09, 0x40, 0x00, 0x61, 0x6b, 0x61, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x00, 0x6b, 0x65, 0x6e, 0x00, 0xf9, 0x61, 0x00,
- 0x00, 0x65, 0x20, 0x00, 0x68, 0x28, 0x00, 0x69, 0x59, 0x00, 0x6c, 0x5e,
- 0x00, 0x6f, 0x7a, 0x00, 0x72, 0x4a, 0x01, 0x74, 0x54, 0x01, 0x75, 0x74,
- 0x01, 0xe4, 0x6e, 0x00, 0x70, 0x05, 0x72, 0x07, 0x74, 0x0d, 0x42, 0x2b,
- 0x6e, 0x79, 0x00, 0x00, 0x08, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x61, 0x6c, 0x6f, 0x67, 0x75, 0x65, 0x64, 0x00, 0x40, 0x3b, 0x61,
- 0x73, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x6e, 0x00, 0x72,
- 0x09, 0x73, 0x22, 0x40, 0x00, 0x67, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x0c, 0x40, 0x00, 0x63, 0x74, 0x65, 0x72, 0x69,
- 0x73, 0x74, 0x69, 0x63, 0x00, 0x40, 0x00, 0x74, 0x61, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0xf3, 0x74, 0x65, 0x00, 0x40, 0x07, 0x61, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe2, 0x6e, 0x00,
- 0x72, 0x0b, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x05, 0x1b, 0x42, 0x2b, 0x79,
- 0x00, 0x05, 0x1c, 0xe4, 0x6d, 0x00, 0x6e, 0x48, 0x6f, 0xb1, 0x75, 0xc2,
- 0xe3, 0x66, 0x00, 0x6d, 0x0a, 0x70, 0x0f, 0x40, 0x00, 0x6f, 0x72, 0x74,
- 0x61, 0x62, 0x6c, 0x65, 0x00, 0x42, 0x2b, 0x6f, 0x6e, 0x00, 0xe2, 0x6c,
- 0x00, 0x72, 0x15, 0xe2, 0x61, 0x00, 0x69, 0x08, 0x40, 0x3b, 0x69, 0x6e,
- 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x63, 0x61, 0x74, 0x65, 0x64, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x0a, 0x40, 0x3b, 0x68, 0x65, 0x6e, 0x64, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x6d, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x00,
- 0xe4, 0x64, 0x00, 0x67, 0x0a, 0x73, 0x12, 0x74, 0x44, 0x40, 0x3b, 0x69,
- 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x69,
- 0x61, 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x21, 0xe1, 0x69, 0x00, 0xe1,
- 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x62,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x3b, 0x69, 0x74, 0x75, 0x74, 0x69,
- 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe2,
- 0x6c, 0x00, 0x76, 0x08, 0x40, 0x00, 0x6c, 0x61, 0x62, 0x6c, 0x79, 0x00,
- 0x40, 0x00, 0x65, 0x72, 0x73, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x6c, 0x00,
- 0x70, 0x02, 0x00, 0x00, 0x40, 0x00, 0x65, 0x72, 0x61, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0x40, 0x3b, 0x74, 0x68, 0x00, 0x40, 0x00, 0x75, 0x73, 0x68,
- 0x61, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x05, 0x40, 0x06,
- 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0xf7, 0x61, 0x00, 0x00, 0x65, 0x08, 0x00,
- 0x69, 0xf8, 0x04, 0x6f, 0xfd, 0x04, 0x72, 0x0b, 0x05, 0x75, 0x14, 0x05,
- 0x79, 0x33, 0x05, 0x40, 0x3b, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x00, 0xf6,
- 0x63, 0x00, 0x00, 0x66, 0x07, 0x00, 0x6d, 0x09, 0x00, 0x6e, 0x16, 0x00,
- 0x72, 0x1e, 0x00, 0x73, 0xd4, 0x04, 0x40, 0x06, 0x69, 0x64, 0x65, 0x64,
- 0x00, 0x00, 0x00, 0x40, 0x3b, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x74,
- 0x69, 0x76, 0x65, 0x00, 0x40, 0x00, 0x69, 0x61, 0x62, 0x6c, 0x79, 0x00,
- 0xc1, 0x61, 0x17, 0x33, 0x00, 0x35, 0x00, 0x6e, 0x00, 0x91, 0x00, 0x11,
- 0x01, 0x3f, 0x01, 0x91, 0x01, 0xc5, 0x01, 0x09, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x29, 0x02, 0x55, 0x02, 0x79, 0x02, 0x00, 0x00, 0xae,
- 0x02, 0x00, 0x00, 0x22, 0x03, 0x38, 0x03, 0xf4, 0x03, 0x2d, 0x04, 0x40,
- 0x04, 0x57, 0x04, 0x00, 0x00, 0xe4, 0x63, 0x00, 0x67, 0x1c, 0x70, 0x20,
- 0x72, 0x2c, 0xe2, 0x68, 0x00, 0x74, 0x15, 0xe1, 0x69, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0x80, 0x00, 0x07, 0x00, 0x7a, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00,
- 0x70, 0x72, 0x65, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x00, 0x40, 0x06,
- 0x6d, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x06, 0x72, 0x16, 0x40, 0x06, 0x6c,
- 0x6c, 0x79, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x08, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x75, 0x73, 0x68,
- 0x00, 0xe5, 0x61, 0x00, 0x68, 0x09, 0x6c, 0x10, 0x6f, 0x43, 0x75, 0x5c,
- 0x40, 0x09, 0x72, 0x72, 0x69, 0x61, 0x67, 0x65, 0x00, 0x40, 0x82, 0x61,
- 0x72, 0x67, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x1a, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x07,
- 0x73, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x61, 0x00, 0x76, 0x0f,
- 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0xfc, 0x40, 0x07,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x72, 0x00, 0xe2, 0x72, 0x00, 0x74,
- 0x07, 0x40, 0x06, 0x72, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x1e, 0xe1, 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe2, 0x67, 0x00, 0x6e,
- 0x02, 0x00, 0x06, 0x40, 0x00, 0x65, 0x00, 0xe3, 0x6d, 0x00, 0x73, 0x1b,
- 0x78, 0x36, 0xe1, 0x70, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x79, 0x00, 0xe2, 0x65, 0x00, 0x6d, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x07, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x8b, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x70, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x75, 0x02, 0x00, 0x0b,
- 0x40, 0x09, 0x72, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x6c, 0x0b, 0x6f, 0x19,
- 0x75, 0x1e, 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x3c, 0x64,
- 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6f, 0x00, 0x77, 0x04, 0x40, 0x00, 0x72,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x72,
- 0x06, 0x40, 0x00, 0x64, 0x65, 0x64, 0x00, 0x00, 0x07, 0xe3, 0x61, 0x00,
- 0x6f, 0x08, 0x72, 0x19, 0x40, 0x06, 0x72, 0x6d, 0x65, 0x6e, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6e, 0x06, 0x00, 0x1c, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x10, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x08, 0x40, 0x06, 0x61, 0x74,
- 0x65, 0x00, 0xe2, 0x75, 0x00, 0x77, 0x05, 0x40, 0x09, 0x6e, 0x64, 0x00,
- 0x40, 0x07, 0x74, 0x68, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe1,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe3, 0x61, 0x00, 0x69, 0x0b, 0x79, 0x1f, 0xe2, 0x69, 0x00, 0x79,
- 0x04, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x6e, 0x02,
- 0x70, 0x0b, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x67, 0x02, 0x00, 0x82, 0x00,
- 0x09, 0x00, 0x06, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe4, 0x61, 0x00,
- 0x65, 0x07, 0x69, 0x11, 0x6f, 0x16, 0x40, 0x00, 0x6e, 0x6e, 0x65, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x00, 0x40,
- 0x0b, 0x6e, 0x65, 0x00, 0x40, 0x00, 0x73, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x6f, 0x12, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x65, 0x00, 0x6d, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0xe5, 0x61, 0x00, 0x69, 0x29, 0x6c, 0x41, 0x6f, 0x46, 0x72,
- 0x50, 0xe5, 0x69, 0x00, 0x6e, 0x04, 0x72, 0x09, 0x73, 0x0d, 0x79, 0x11,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x07, 0x74, 0x73, 0x00, 0x40, 0x09, 0x74,
- 0x00, 0x40, 0x09, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x04, 0x31,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x09, 0x6e, 0x67, 0x00, 0x40, 0x72, 0x61, 0x79, 0x00, 0x40,
- 0x00, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x0a, 0x40, 0x00, 0x76, 0x69, 0x6c, 0x65, 0x67, 0x65, 0x64, 0x00,
- 0x40, 0x07, 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x05, 0x40, 0x0b, 0x74, 0x65, 0x00, 0x40, 0x00, 0x70, 0x72,
- 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x00, 0xe7, 0x63, 0x00, 0x65,
- 0x06, 0x68, 0x23, 0x69, 0x3f, 0x6b, 0x5d, 0x6f, 0x63, 0x74, 0x68, 0x40,
- 0x5e, 0x6f, 0x72, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x63, 0x02, 0x6c, 0x0b,
- 0x78, 0x0f, 0x00, 0x08, 0x40, 0x06, 0x72, 0x65, 0x74, 0x61, 0x72, 0x79,
- 0x00, 0x40, 0x3c, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x05, 0x40, 0x06, 0x72, 0x74, 0x00, 0xe3, 0x6f, 0x00, 0x72,
- 0x04, 0x74, 0x09, 0x41, 0x21, 0x74, 0x00, 0x40, 0x07, 0x74, 0x73, 0x00,
- 0x00, 0x00, 0xe3, 0x64, 0x00, 0x67, 0x04, 0x7a, 0x12, 0x40, 0x09, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x72, 0x40,
- 0x07, 0x64, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00, 0x40, 0x06, 0x69, 0x72,
- 0x74, 0x00, 0x40, 0x00, 0x6c, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x34,
- 0x75, 0x39, 0xe3, 0x66, 0x00, 0x6e, 0x06, 0x74, 0x1d, 0x40, 0x00, 0x66,
- 0x65, 0x64, 0x00, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69,
- 0x08, 0x05, 0x1d, 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x12, 0x6e,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x58,
- 0x40, 0x06, 0x65, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x6f, 0x64, 0x00, 0x40,
- 0xa1, 0x64, 0x79, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x1a, 0x6f, 0x21, 0xe1,
- 0x6b, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0d, 0xe3, 0x00, 0x00, 0x6e, 0x02,
- 0x72, 0x04, 0x03, 0x0c, 0x00, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x69, 0x6e, 0x67, 0x73, 0x00, 0xe3, 0x6e, 0x00, 0x6f,
- 0x04, 0x77, 0x08, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x6b, 0x00, 0x00,
- 0x06, 0xe2, 0x73, 0x00, 0x74, 0x05, 0x40, 0x00, 0x65, 0x64, 0x00, 0x40,
- 0x00, 0x69, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07,
- 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a, 0xe6, 0x61, 0x00, 0x65, 0x0c,
- 0x68, 0x21, 0x69, 0x27, 0x6f, 0x2c, 0x72, 0x32, 0xe2, 0x74, 0x00, 0x79,
- 0x05, 0x40, 0x00, 0x65, 0x72, 0x00, 0x00, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x04, 0x6e, 0x0a, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x67, 0x68, 0x74,
- 0x00, 0x40, 0x00, 0x74, 0x00, 0x40, 0x72, 0x65, 0x6c, 0x6d, 0x00, 0x41,
- 0x1a, 0x72, 0x65, 0x00, 0x40, 0x09, 0x72, 0x6c, 0x64, 0x00, 0xe2, 0x69,
- 0x00, 0x6f, 0x16, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x74, 0x09, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xe5, 0x00, 0x07, 0x40, 0x00, 0x65, 0x6e,
- 0x00, 0x40, 0x00, 0x74, 0x65, 0x00, 0x40, 0x09, 0x69, 0x72, 0x61, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x75,
- 0x02, 0x00, 0x00, 0x40, 0x3b, 0x62, 0x74, 0x65, 0x64, 0x00, 0x40, 0x00,
- 0x61, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x02,
- 0x00, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x00,
- 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x8c, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0xe9, 0x61, 0x00, 0x63,
- 0x22, 0x6d, 0x2b, 0x6e, 0x34, 0x71, 0x4b, 0x72, 0x51, 0x73, 0x58, 0x76,
- 0x62, 0x78, 0x67, 0xe3, 0x72, 0x00, 0x73, 0x0b, 0x74, 0x14, 0x40, 0x07,
- 0x74, 0x68, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0x02, 0x2b, 0x40, 0x00, 0x61, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x00, 0x6f, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x00, 0x40, 0x07,
- 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x64, 0x00, 0xe2, 0x64, 0x00, 0x74, 0x06,
- 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x72, 0x70, 0x72,
- 0x69, 0x73, 0x69, 0x6e, 0x67, 0x00, 0x45, 0x1e, 0x75, 0x61, 0x6c, 0x00,
- 0x40, 0x3b, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x73, 0x65, 0x6e,
- 0x74, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x3b, 0x65, 0x6e, 0x00, 0xe2, 0x63,
- 0x00, 0x70, 0x22, 0xe2, 0x65, 0x00, 0x69, 0x0c, 0x40, 0x00, 0x70, 0x74,
- 0x69, 0x6f, 0x6e, 0x61, 0x62, 0x6c, 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x31, 0x69, 0x49,
- 0x6c, 0x5d, 0x6f, 0xa0, 0x72, 0xc6, 0x75, 0xee, 0xe4, 0x69, 0x00, 0x6c,
- 0x0d, 0x6d, 0x16, 0x74, 0x1e, 0xe2, 0x6c, 0x00, 0x72, 0x06, 0x40, 0x3b,
- 0x69, 0x6e, 0x67, 0x00, 0x00, 0x63, 0x40, 0x00, 0x74, 0x65, 0x72, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x6c, 0x69, 0x61, 0x72, 0x00, 0x40,
- 0x00, 0x68, 0x6f, 0x6d, 0x61, 0x62, 0x6c, 0x79, 0x00, 0xe3, 0x64, 0x00,
- 0x65, 0x02, 0x6d, 0x09, 0x00, 0x00, 0x40, 0x3b, 0x6c, 0x69, 0x6e, 0x67,
- 0x00, 0x40, 0x00, 0x69, 0x6e, 0x69, 0x6e, 0x65, 0x00, 0xe2, 0x74, 0x00,
- 0x78, 0x0d, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x08, 0x40, 0x00, 0x69,
- 0x6e, 0x67, 0x00, 0x00, 0x0b, 0xe2, 0x61, 0x00, 0x69, 0x35, 0xe3, 0x67,
- 0x00, 0x70, 0x07, 0x74, 0x25, 0x40, 0x3b, 0x67, 0x69, 0x6e, 0x67, 0x00,
- 0xe1, 0x70, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00,
- 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x74, 0x65, 0x72, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x6e, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x67, 0x00, 0x74, 0x16, 0xe2, 0x65, 0x00, 0x69,
- 0x09, 0x40, 0x00, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x00,
- 0x76, 0x61, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x09, 0x75, 0x6e, 0x61, 0x74,
- 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x14, 0x75, 0x19, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0xed, 0x42, 0x2b, 0x79, 0x00, 0x41, 0x20, 0x63, 0x6b, 0x00, 0x40, 0x00,
- 0x69, 0x74, 0x66, 0x75, 0x6c, 0x00, 0x40, 0x00, 0x6e, 0x6e, 0x79, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x17, 0x6f, 0x2b, 0x72, 0x31, 0x75, 0x46, 0xe1,
- 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79,
- 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x15, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x74, 0x07, 0x40, 0x00, 0x72, 0x6f, 0x75, 0x73,
- 0x00, 0x40, 0x00, 0x6c, 0x65, 0x00, 0x42, 0x2b, 0x64, 0x6c, 0x79, 0x00,
- 0xe2, 0x61, 0x00, 0x75, 0x08, 0x40, 0x3b, 0x63, 0x65, 0x66, 0x75, 0x6c,
- 0x00, 0x40, 0x00, 0x64, 0x67, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x07, 0x6c, 0x0c, 0x40, 0x00, 0x72, 0x64, 0x65, 0x64, 0x00, 0x40,
- 0x06, 0x6e, 0x74, 0x00, 0x40, 0x09, 0x61, 0x74, 0x65, 0x00, 0xe5, 0x61,
- 0x00, 0x65, 0x0f, 0x69, 0x27, 0x6f, 0x32, 0x75, 0x37, 0xe2, 0x6e, 0x00,
- 0x70, 0x05, 0x42, 0x2b, 0x64, 0x79, 0x00, 0x42, 0x2b, 0x70, 0x79, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00,
- 0xe2, 0x66, 0x00, 0x79, 0x05, 0x40, 0x00, 0x75, 0x6c, 0x00, 0x02, 0x2b,
- 0x40, 0x00, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x42,
- 0x2b, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x72, 0x74, 0x00, 0xfb, 0x63, 0x00,
- 0x00, 0x64, 0x25, 0x00, 0x66, 0x32, 0x00, 0x6c, 0x56, 0x00, 0x6d, 0x74,
- 0x00, 0x6e, 0x8d, 0x00, 0x6f, 0x03, 0x01, 0x71, 0x19, 0x01, 0x73, 0x2c,
- 0x01, 0x74, 0x39, 0x01, 0x76, 0x62, 0x01, 0xe4, 0x61, 0x00, 0x65, 0x08,
- 0x6f, 0x11, 0x79, 0x16, 0x40, 0x00, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x6c, 0x6c, 0x75, 0x6c, 0x61, 0x72, 0x00, 0x40, 0x06, 0x72,
- 0x6e, 0x00, 0x40, 0x06, 0x63, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x69, 0x72,
- 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0xe3, 0x69, 0x00,
- 0x6f, 0x09, 0x79, 0x1b, 0x40, 0x75, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x02, 0x0a, 0x40, 0x07, 0x74, 0x79, 0x00, 0x05, 0x1f, 0xe1, 0x61, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x00,
- 0x73, 0x6d, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x08, 0x40,
- 0x00, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73,
- 0x69, 0x76, 0x65, 0x00, 0xe5, 0x66, 0x00, 0x68, 0x0b, 0x73, 0x14, 0x74,
- 0x25, 0x76, 0x63, 0x40, 0x00, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x76,
- 0x65, 0x00, 0x40, 0x3b, 0x69, 0x62, 0x69, 0x74, 0x65, 0x64, 0x00, 0xe2,
- 0x74, 0x00, 0x75, 0x06, 0x45, 0x20, 0x61, 0x6c, 0x6c, 0x00, 0x40, 0x00,
- 0x72, 0x65, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x6c, 0x00, 0x6e, 0x09,
- 0x72, 0x0f, 0x40, 0x00, 0x6c, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x00, 0x40,
- 0x00, 0x64, 0x65, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x08, 0x40, 0x00,
- 0x73, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x3b, 0x64, 0x00,
- 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x69, 0x74, 0x69, 0x6e,
- 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x65,
- 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x09,
- 0xe1, 0x75, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03,
- 0x3c, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x04,
- 0x40, 0x07, 0x78, 0x00, 0x40, 0x07, 0x6e, 0x00, 0xe4, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x11, 0x79, 0x1e, 0x40, 0x00, 0x72, 0x79, 0x00, 0xe2, 0x00,
- 0x00, 0x64, 0x02, 0x00, 0xce, 0x40, 0x00, 0x6c, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x7a, 0x04, 0x40, 0x00, 0x73, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x00,
- 0x84, 0xe2, 0x61, 0x00, 0x65, 0x11, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x76, 0x05, 0x40, 0x00, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x17, 0x69, 0x19,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x86, 0xe2, 0x74,
- 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x00,
- 0x06, 0x40, 0x06, 0x74, 0x79, 0x00, 0x40, 0x3b, 0x75, 0x73, 0x74, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x06, 0x6e, 0x17, 0x40, 0x00, 0x6d, 0x70, 0x74,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x02, 0x2b, 0x42, 0x2b, 0x79, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x77, 0x00,
- 0xe2, 0x61, 0x00, 0x6e, 0x06, 0x40, 0x07, 0x62, 0x6c, 0x65, 0x00, 0x00,
- 0x06, 0xe4, 0x65, 0x00, 0x69, 0x0f, 0x6f, 0x24, 0x75, 0x44, 0xe2, 0x61,
- 0x00, 0x73, 0x06, 0x40, 0x07, 0x64, 0x65, 0x64, 0x00, 0x40, 0x00, 0x73,
- 0x00, 0xe2, 0x6b, 0x00, 0x74, 0x0e, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x05, 0x21, 0x42, 0x2b, 0x79, 0x00, 0x00, 0x00, 0xe2, 0x63,
- 0x00, 0x76, 0x04, 0x40, 0x3a, 0x6b, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06,
- 0x69, 0x0b, 0x40, 0x00, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x60, 0x6c, 0x79,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x42, 0x2b, 0x63, 0x6b, 0x79, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x11, 0x69, 0x42, 0x6f, 0x63, 0x75, 0x74, 0xe2,
- 0x6e, 0x00, 0x72, 0x05, 0x42, 0x2b, 0x6c, 0x79, 0x00, 0x40, 0x00, 0x72,
- 0x69, 0x65, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x6e, 0x07, 0x74, 0x28, 0x40,
- 0x00, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x09, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x07, 0x40, 0x00,
- 0x64, 0x66, 0x75, 0x6c, 0x00, 0xe2, 0x73, 0x00, 0x74, 0x07, 0x40, 0x00,
- 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x61, 0x6b, 0x61, 0x62, 0x6c,
- 0x79, 0x00, 0xe2, 0x72, 0x00, 0x76, 0x05, 0x40, 0x00, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x73, 0x69, 0x63,
- 0x61, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x09, 0x40,
- 0x00, 0x65, 0x73, 0x73, 0x61, 0x72, 0x79, 0x00, 0x40, 0x3b, 0x76, 0x69,
- 0x6e, 0x67, 0x00, 0xe3, 0x62, 0x00, 0x66, 0x0a, 0x72, 0x21, 0x40, 0x00,
- 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x00, 0xe1, 0x66, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x08, 0x40, 0x00, 0x6e, 0x73, 0x69, 0x76, 0x65, 0x00,
- 0x40, 0x3b, 0x63, 0x69, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x69, 0x67, 0x69,
- 0x6e, 0x61, 0x6c, 0x00, 0xe5, 0x65, 0x00, 0x69, 0x22, 0x6c, 0x2d, 0x6f,
- 0x36, 0x72, 0x4b, 0xe2, 0x6f, 0x00, 0x72, 0x06, 0x40, 0x00, 0x70, 0x6c,
- 0x65, 0x00, 0xe2, 0x63, 0x00, 0x73, 0x09, 0x40, 0x00, 0x65, 0x70, 0x74,
- 0x69, 0x76, 0x65, 0x00, 0x40, 0x00, 0x75, 0x61, 0x73, 0x69, 0x76, 0x65,
- 0x00, 0xe2, 0x63, 0x00, 0x6e, 0x04, 0x40, 0x0b, 0x6b, 0x00, 0x00, 0x08,
- 0x40, 0x00, 0x65, 0x61, 0x73, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x6c, 0x00,
- 0x70, 0x09, 0x40, 0x00, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x40,
- 0x00, 0x75, 0x6c, 0x61, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x09, 0x6f,
- 0x14, 0x40, 0x00, 0x63, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x00, 0x40, 0x3b,
- 0x63, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x00, 0xe3, 0x66, 0x00,
- 0x6d, 0x0b, 0x70, 0x13, 0x40, 0x3b, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
- 0x61, 0x6c, 0x00, 0x40, 0x00, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x69, 0x74, 0x69, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x0b, 0x40, 0x3b, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x60, 0x65, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x8a, 0x6f, 0x8f, 0x75, 0xa0, 0xe6, 0x61, 0x00, 0x67, 0x1a, 0x6c, 0x24,
- 0x6d, 0x40, 0x70, 0x56, 0x73, 0x79, 0xe3, 0x64, 0x00, 0x6c, 0x09, 0x73,
- 0x0b, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x6e,
- 0x65, 0x72, 0x61, 0x74, 0x65, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x06, 0x69,
- 0x0e, 0x40, 0x00, 0x74, 0x65, 0x64, 0x00, 0x40, 0x3b, 0x6e, 0x74, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x3b, 0x65, 0x76, 0x65, 0x64, 0x00, 0xe2, 0x61,
- 0x00, 0x69, 0x09, 0x40, 0x00, 0x72, 0x6b, 0x61, 0x62, 0x6c, 0x65, 0x00,
- 0x40, 0x3b, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x65, 0x00, 0x6f,
- 0x08, 0x72, 0x0f, 0x40, 0x00, 0x6e, 0x74, 0x61, 0x6e, 0x74, 0x00, 0x40,
- 0x00, 0x72, 0x74, 0x65, 0x64, 0x00, 0x40, 0x00, 0x65, 0x73, 0x65, 0x6e,
- 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0x40, 0x07, 0x74, 0x00, 0x40,
- 0x60, 0x70, 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6d, 0x04, 0x40, 0x0b, 0x6c,
- 0x00, 0x40, 0x00, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0xf4, 0xfb, 0x61, 0x00, 0x00, 0x63, 0x19, 0x00, 0x65, 0x21, 0x00,
- 0x68, 0x54, 0x00, 0x69, 0x87, 0x00, 0x6d, 0xa1, 0x00, 0x6f, 0xa9, 0x00,
- 0x70, 0xcb, 0x00, 0x74, 0x06, 0x01, 0x75, 0x2c, 0x01, 0x79, 0x5f, 0x01,
- 0xe3, 0x66, 0x00, 0x6c, 0x04, 0x76, 0x0c, 0x42, 0x4f, 0x65, 0x00, 0x40,
- 0x00, 0x65, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x79,
- 0x00, 0x40, 0x00, 0x61, 0x74, 0x68, 0x65, 0x64, 0x00, 0xe4, 0x61, 0x00,
- 0x65, 0x0a, 0x6e, 0x1d, 0x74, 0x28, 0x40, 0x00, 0x72, 0x63, 0x68, 0x61,
- 0x62, 0x6c, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6d, 0x05, 0x6e, 0x0a, 0x40,
- 0x3b, 0x6e, 0x67, 0x00, 0x42, 0x2b, 0x6c, 0x79, 0x00, 0x00, 0x07, 0x40,
- 0x00, 0x74, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x00, 0x00, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x1d, 0xe2, 0x6b, 0x00, 0x70, 0x12, 0xe1, 0x61,
- 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x65, 0x6c, 0x79, 0x00, 0xe2, 0x63,
- 0x00, 0x72, 0x08, 0x40, 0x00, 0x6b, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x05, 0x22, 0x40, 0x00, 0x69, 0x6c, 0x69, 0x6e, 0x67,
- 0x00, 0xe3, 0x63, 0x00, 0x6c, 0x12, 0x75, 0x16, 0xe1, 0x69, 0x00, 0xe1,
- 0x61, 0x00, 0xe2, 0x62, 0x00, 0x6c, 0x05, 0x40, 0x00, 0x6c, 0x65, 0x00,
- 0x00, 0x00, 0x40, 0x00, 0x64, 0x00, 0x40, 0x7f, 0x6e, 0x64, 0x00, 0xe2,
- 0x65, 0x00, 0x6f, 0x2e, 0xe2, 0x61, 0x00, 0x63, 0x15, 0xe1, 0x6b, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00,
- 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x74, 0x06, 0x40,
- 0x00, 0x66, 0x69, 0x63, 0x00, 0x40, 0x00, 0x61, 0x63, 0x75, 0x6c, 0x61,
- 0x72, 0x00, 0x40, 0x00, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x06, 0x69, 0x0c, 0x72, 0x14, 0x40, 0x00, 0x62, 0x6c, 0x65,
- 0x00, 0x41, 0x3b, 0x61, 0x64, 0x79, 0x00, 0x40, 0x3b, 0x6e, 0x74, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x00,
- 0xe4, 0x62, 0x00, 0x69, 0x14, 0x72, 0x1c, 0x73, 0x20, 0xe2, 0x73, 0x00,
- 0x74, 0x0a, 0x40, 0x00, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x00,
- 0x40, 0x00, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x74, 0x61, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x3b, 0x70, 0x65, 0x63, 0x74, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x61, 0x6c, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x08, 0x69, 0x21, 0x6f, 0x3c,
- 0x72, 0x50, 0x40, 0x00, 0x63, 0x74, 0x66, 0x75, 0x6c, 0x00, 0xe1, 0x69,
- 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x06,
- 0x40, 0x00, 0x62, 0x6c, 0x79, 0x00, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0xe4,
- 0x64, 0x00, 0x6c, 0x04, 0x6d, 0x06, 0x72, 0x0c, 0x40, 0x96, 0x79, 0x00,
- 0x00, 0x00, 0x42, 0x2b, 0x65, 0x6c, 0x79, 0x00, 0x40, 0x3b, 0x69, 0x6e,
- 0x67, 0x00, 0xe2, 0x75, 0x00, 0x77, 0x09, 0x40, 0x09, 0x63, 0x68, 0x61,
- 0x62, 0x6c, 0x65, 0x00, 0x40, 0x00, 0x61, 0x72, 0x64, 0x00, 0xe1, 0x75,
- 0x00, 0xe2, 0x65, 0x00, 0x73, 0x02, 0x00, 0xf3, 0x40, 0x00, 0x74, 0x77,
- 0x6f, 0x72, 0x74, 0x68, 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0xe5, 0x61, 0x00, 0x65, 0x1e, 0x69, 0x32, 0x6f, 0x4f, 0x72, 0x69, 0xe2,
- 0x72, 0x00, 0x76, 0x11, 0xe2, 0x72, 0x00, 0x79, 0x0a, 0x40, 0x00, 0x61,
- 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x02, 0x2b, 0x40, 0x00, 0x65,
- 0x72, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x64, 0x00, 0x6c, 0x02, 0x00, 0x00,
- 0xe2, 0x63, 0x00, 0x6c, 0x06, 0x40, 0x1c, 0x6f, 0x6d, 0x65, 0x00, 0x00,
- 0x00, 0xe2, 0x65, 0x00, 0x73, 0x14, 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x01, 0x3b, 0x40, 0xda, 0x65, 0x00, 0xe2, 0x72, 0x00, 0x75, 0x10, 0xe2,
- 0x72, 0x00, 0x74, 0x06, 0x40, 0x00, 0x69, 0x65, 0x64, 0x00, 0x42, 0x2b,
- 0x68, 0x79, 0x00, 0x40, 0x00, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x61, 0x70,
- 0x70, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x69, 0x65, 0x6c, 0x64, 0x69,
- 0x6e, 0x67, 0x00, 0xc1, 0x62, 0x16, 0x31, 0x00, 0x33, 0x00, 0x4f, 0x00,
- 0x6c, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x88, 0x00, 0x8f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xf9, 0x00,
- 0xfd, 0x00, 0x00, 0x00, 0x75, 0x01, 0xc7, 0x01, 0x42, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x81, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x72, 0x05, 0x40,
- 0x09, 0x61, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x05, 0x40, 0x5b, 0x69,
- 0x64, 0x00, 0x40, 0x09, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x00, 0xe2, 0x68,
- 0x00, 0x6f, 0x06, 0x40, 0x5b, 0x75, 0x63, 0x6b, 0x00, 0xe2, 0x6d, 0x00,
- 0x75, 0x06, 0x40, 0x00, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x74,
- 0x72, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x05, 0x43, 0x4d, 0x74, 0x65,
- 0x00, 0x40, 0x09, 0x61, 0x66, 0x74, 0x00, 0x40, 0x5b, 0x6e, 0x64, 0x00,
- 0x40, 0x00, 0x72, 0x6f, 0x6e, 0x74, 0x00, 0x40, 0x82, 0x72, 0x61, 0x64,
- 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0f, 0x6f, 0x14, 0xe2, 0x61, 0x00,
- 0x6c, 0x06, 0x40, 0x09, 0x76, 0x61, 0x6c, 0x00, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x09, 0x6c, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x73,
- 0x0b, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe5, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x79, 0x06, 0x01, 0x40, 0x40, 0x09, 0x72, 0x00, 0x00, 0x07,
- 0x40, 0x07, 0x65, 0x65, 0x70, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x05, 0x6f,
- 0x0a, 0x40, 0x09, 0x6e, 0x64, 0x00, 0x45, 0x23, 0x66, 0x74, 0x00, 0x40,
- 0x7a, 0x61, 0x64, 0x00, 0x40, 0x00, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x60, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x6d, 0x4c, 0x00,
- 0x06, 0xe3, 0x61, 0x00, 0x6c, 0x05, 0x75, 0x33, 0x40, 0x07, 0x73, 0x65,
- 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x77, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00,
- 0x40, 0x00, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x04, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0x40, 0x00, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0xe3, 0x6e, 0x00,
- 0x73, 0x04, 0x74, 0x08, 0x40, 0x00, 0x67, 0x00, 0x40, 0x00, 0x68, 0x00,
- 0x40, 0x00, 0x79, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0b, 0x6f,
- 0x30, 0x40, 0x3a, 0x69, 0x73, 0x65, 0x00, 0x40, 0xad, 0x61, 0x72, 0x00,
- 0xe3, 0x67, 0x00, 0x73, 0x13, 0x76, 0x19, 0xe1, 0x68, 0x00, 0xe1, 0x74,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x44, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x10, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x40, 0xad,
- 0x74, 0x00, 0xe7, 0x63, 0x00, 0x65, 0x06, 0x68, 0x16, 0x69, 0x1b, 0x74,
- 0x29, 0x75, 0x60, 0x77, 0x66, 0x40, 0x00, 0x61, 0x6c, 0x65, 0x00, 0xe1,
- 0x74, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0x40, 0x00, 0x69,
- 0x6e, 0x67, 0x00, 0x40, 0x06, 0x6f, 0x74, 0x00, 0xe2, 0x64, 0x00, 0x6c,
- 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe2, 0x61,
- 0x00, 0x72, 0x23, 0xe5, 0x67, 0x00, 0x69, 0x04, 0x6e, 0x09, 0x72, 0x10,
- 0x74, 0x14, 0x40, 0x0b, 0x65, 0x00, 0x40, 0x00, 0x72, 0x73, 0x00, 0x40,
- 0x00, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x47, 0x74, 0x00, 0x40, 0x07,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x61, 0x6d, 0x00,
- 0x40, 0x06, 0x6b, 0x65, 0x00, 0x40, 0x82, 0x72, 0x67, 0x65, 0x00, 0x40,
- 0x09, 0x69, 0x6e, 0x67, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x05, 0x68, 0x0b,
- 0x69, 0x12, 0x6f, 0x20, 0x72, 0x25, 0x75, 0x2b, 0x40, 0x06, 0x6b, 0x65,
- 0x00, 0x40, 0x00, 0x6d, 0x70, 0x6f, 0x00, 0x41, 0x2f, 0x72, 0x75, 0x73,
- 0x74, 0x00, 0xe2, 0x63, 0x00, 0x67, 0x04, 0x40, 0x06, 0x6b, 0x00, 0x40,
- 0x00, 0x68, 0x74, 0x00, 0x40, 0x07, 0x77, 0x6e, 0x00, 0x40, 0x00, 0x65,
- 0x6e, 0x64, 0x00, 0x40, 0x95, 0x72, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x05, 0x43, 0x6c, 0x72, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x64, 0x00, 0xfa,
- 0x61, 0x00, 0x00, 0x62, 0x10, 0x00, 0x63, 0x4f, 0x00, 0x65, 0x55, 0x00,
- 0x67, 0x8d, 0x00, 0x69, 0xa2, 0x00, 0x6e, 0xde, 0x00, 0x6f, 0xe0, 0x00,
- 0x73, 0x09, 0x01, 0x74, 0x0f, 0x01, 0xe2, 0x63, 0x00, 0x6e, 0x05, 0x40,
- 0x07, 0x69, 0x6c, 0x00, 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x04, 0x6f,
- 0x1b, 0x00, 0x00, 0x00, 0xda, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07,
- 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f,
- 0x6e, 0x00, 0x00, 0x3a, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x73, 0x74, 0x00, 0x00,
- 0x07, 0x40, 0x06, 0x68, 0x69, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x6d, 0x02,
- 0x74, 0x0e, 0x00, 0x07, 0xe1, 0x69, 0x00, 0xe2, 0x61, 0x00, 0x63, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x68, 0x04, 0x40, 0x06, 0x72,
- 0x00, 0xe2, 0x61, 0x00, 0x72, 0x05, 0x40, 0x07, 0x6e, 0x65, 0x00, 0xe1,
- 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04, 0x00, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x82, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b,
- 0xe2, 0x63, 0x00, 0x6e, 0x02, 0x00, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x2e,
- 0xe3, 0x6c, 0x00, 0x72, 0x17, 0x74, 0x1b, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x07, 0x73, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x42, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x07,
- 0x00, 0x06, 0xe2, 0x67, 0x00, 0x6c, 0x09, 0x40, 0x00, 0x65, 0x6e, 0x69,
- 0x74, 0x61, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0e, 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x00, 0x61, 0x6c,
- 0x00, 0x40, 0x09, 0x74, 0x00, 0x00, 0x07, 0x40, 0x00, 0x69, 0x6e, 0x65,
- 0x00, 0x40, 0x07, 0x69, 0x63, 0x61, 0x72, 0x69, 0x61, 0x00, 0xe4, 0x61,
- 0x00, 0x65, 0x19, 0x68, 0x72, 0x75, 0x85, 0xe2, 0x62, 0x00, 0x67, 0x10,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x41, 0x84, 0x65, 0x00, 0x40, 0x06, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x64,
- 0x02, 0x66, 0x04, 0x6c, 0x17, 0x72, 0x2d, 0x05, 0x24, 0x00, 0x37, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00,
- 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6e, 0x09, 0x70,
- 0x13, 0x00, 0x09, 0x40, 0x09, 0x72, 0x6f, 0x75, 0x70, 0x00, 0x60, 0x09,
- 0x61, 0x6d, 0x65, 0x00, 0x08, 0x00, 0xff, 0xff, 0x40, 0x07, 0x69, 0x63,
- 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x2c, 0x40, 0x06, 0x74, 0x74, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x72, 0x10, 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x27,
- 0x02, 0x00, 0x36, 0x40, 0x00, 0x73, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x04,
- 0x70, 0x0a, 0x79, 0x1e, 0x40, 0x06, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x75,
- 0x73, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65, 0x09, 0x00, 0xd6, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x00, 0x07,
- 0xe5, 0x65, 0x00, 0x69, 0x1f, 0x6d, 0x5b, 0x6f, 0x61, 0x74, 0x67, 0xe2,
- 0x6e, 0x00, 0x72, 0x06, 0x40, 0x06, 0x73, 0x69, 0x6c, 0x00, 0xe2, 0x69,
- 0x00, 0x75, 0x0b, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x09, 0xe2, 0x74, 0x00, 0x7a, 0x1f, 0xe2, 0x61, 0x00,
- 0x79, 0x18, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07, 0x73,
- 0x6d, 0x00, 0x00, 0x06, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0xca, 0x40, 0x07, 0x6f, 0x73, 0x74, 0x00,
- 0x40, 0x06, 0x70, 0x69, 0x61, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6d, 0x08, 0x05, 0x25, 0x40, 0x06, 0x6e,
- 0x63, 0x65, 0x00, 0x40, 0x07, 0x6f, 0x73, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x75, 0x07, 0x40, 0x00, 0x69, 0x74, 0x69, 0x73, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x06, 0x00, 0x09,
- 0x40, 0x00, 0x6f, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x00, 0xfa, 0x00, 0x00,
- 0x00, 0x42, 0x02, 0x00, 0x61, 0x0c, 0x00, 0x62, 0xe7, 0x04, 0x65, 0xe9,
- 0x04, 0x68, 0xd4, 0x0a, 0x69, 0xe1, 0x0a, 0x6f, 0x3d, 0x12, 0x75, 0x2c,
- 0x15, 0x79, 0xea, 0x15, 0x00, 0x76, 0x40, 0x07, 0x75, 0x6c, 0x6c, 0x65,
- 0x74, 0x69, 0x6e, 0x00, 0xfc, 0x63, 0x00, 0x00, 0x67, 0x99, 0x00, 0x69,
- 0x01, 0x01, 0x6c, 0x21, 0x01, 0x6d, 0x60, 0x02, 0x6e, 0x77, 0x02, 0x70,
- 0xf5, 0x02, 0x71, 0x4a, 0x03, 0x72, 0x51, 0x03, 0x73, 0x0d, 0x04, 0x74,
- 0x66, 0x04, 0x75, 0x7b, 0x04, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x63, 0x31,
- 0x69, 0x4d, 0x75, 0x65, 0x00, 0x08, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x06, 0x79, 0x00, 0x00, 0x3b, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x3a, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe3,
- 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x06, 0x73, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x39, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0x00, 0x06, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x45, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe3, 0x69, 0x00,
- 0x6f, 0x05, 0x75, 0x1e, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x6c, 0x00,
- 0x75, 0x04, 0x40, 0x09, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x95,
- 0x6d, 0x00, 0xe4, 0x61, 0x00, 0x69, 0x27, 0x72, 0x3a, 0x75, 0x4b, 0xe2,
- 0x62, 0x00, 0x72, 0x15, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x2c, 0x40, 0x07, 0x67, 0x65,
- 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00,
- 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6c, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3b, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x73, 0x0d, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0xda, 0xe1, 0x6c, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x06, 0x40, 0x3b,
- 0x6f, 0x75, 0x73, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02,
- 0x00, 0x65, 0x08, 0x00, 0x69, 0x74, 0x00, 0x6c, 0xc8, 0x00, 0x6f, 0xcd,
- 0x00, 0x75, 0xdc, 0x00, 0x76, 0x0e, 0x01, 0x00, 0x00, 0x40, 0x09, 0x6e,
- 0x63, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6e, 0x24, 0x74, 0x38,
- 0x00, 0x09, 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x74, 0x00, 0xe2,
- 0x69, 0x00, 0x6f, 0x05, 0x40, 0x09, 0x6f, 0x6e, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x61, 0x6e, 0x00, 0x00, 0x06,
- 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x09,
- 0x00, 0x06, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x75,
- 0x02, 0x00, 0x2c, 0xe1, 0x64, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0x40, 0x07,
- 0x73, 0x6d, 0x00, 0xe4, 0x61, 0x00, 0x64, 0x0e, 0x73, 0x3d, 0x74, 0x41,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00,
- 0x00, 0x3b, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x69, 0x1b, 0x6e, 0x20, 0x00,
- 0x3b, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x02, 0xc9, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x53,
- 0x00, 0x00, 0x40, 0x53, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x73, 0x65, 0x6d, 0x61, 0x6c,
- 0x6c, 0x61, 0x00, 0x40, 0x06, 0x65, 0x79, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x16, 0xe2, 0x62, 0x00, 0x74, 0x05, 0x40, 0x09, 0x6c,
- 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3a, 0x41, 0xed, 0x6f,
- 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x27, 0x02, 0x6c, 0x06, 0x72, 0x0c, 0x01,
- 0xbd, 0x40, 0x00, 0x73, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x06, 0xe2, 0x65, 0x00, 0x75, 0x0d, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00,
- 0x5e, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72,
- 0x00, 0xe2, 0x6f, 0x00, 0x70, 0x06, 0x40, 0x3a, 0x6f, 0x73, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x61, 0x40, 0x06, 0x72, 0x65, 0x00,
- 0xe9, 0x00, 0x00, 0x61, 0x02, 0x64, 0x09, 0x65, 0x23, 0x67, 0x25, 0x69,
- 0x2c, 0x6e, 0x40, 0x71, 0x4e, 0x74, 0x65, 0x00, 0x06, 0x40, 0x07, 0x64,
- 0x69, 0x75, 0x6d, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x07,
- 0x6d, 0x00, 0x40, 0x3a, 0x65, 0x00, 0x00, 0x09, 0x40, 0x09, 0x75, 0x61,
- 0x72, 0x64, 0x00, 0xe3, 0x6c, 0x00, 0x73, 0x05, 0x74, 0x09, 0x40, 0x06,
- 0x6c, 0x61, 0x00, 0x45, 0x26, 0x68, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x68,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3f, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x06, 0x61, 0x67, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f,
- 0x19, 0x00, 0x0b, 0xe1, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x6e,
- 0x07, 0x00, 0x3e, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6f, 0x1a,
- 0x77, 0x1f, 0x79, 0x25, 0x00, 0x06, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07, 0x40, 0x00, 0x75, 0x73, 0x00, 0x40,
- 0x00, 0x61, 0x72, 0x65, 0x00, 0x00, 0x00, 0x40, 0x09, 0x75, 0x65, 0x72,
- 0x6f, 0x00, 0xe7, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x7c, 0x6d, 0x81, 0x6e,
- 0x87, 0x73, 0x9b, 0x79, 0xa1, 0x00, 0x08, 0xe4, 0x61, 0x00, 0x63, 0x33,
- 0x65, 0x46, 0x6f, 0x6c, 0xe3, 0x62, 0x00, 0x6e, 0x15, 0x74, 0x20, 0xe2,
- 0x69, 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2,
- 0x65, 0x00, 0x79, 0x02, 0x01, 0xa7, 0x00, 0x54, 0xe2, 0x63, 0x00, 0x74,
- 0x04, 0x40, 0x06, 0x65, 0x00, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x03, 0xee, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6c,
- 0x00, 0x73, 0x07, 0x40, 0x00, 0x6f, 0x72, 0x65, 0x64, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0xe3, 0x64, 0x00, 0x67, 0x02, 0x74, 0x14, 0x00, 0x37, 0xe1,
- 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57,
- 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x04, 0x40, 0x06,
- 0x6c, 0x00, 0x00, 0x06, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x06, 0x65,
- 0x74, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x59,
- 0x40, 0x37, 0x64, 0x00, 0x40, 0x06, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x3a, 0x40, 0x37, 0x6e, 0x67, 0x00, 0xe5, 0x63,
- 0x00, 0x65, 0x07, 0x6f, 0x15, 0x73, 0x2f, 0x74, 0x41, 0x40, 0x00, 0x75,
- 0x6c, 0x61, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x09, 0x40,
- 0x06, 0x74, 0x6f, 0x6d, 0x79, 0x00, 0xe2, 0x63, 0x00, 0x6d, 0x0e, 0x40,
- 0x00, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x6f, 0x74, 0x6f, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0x40, 0x07, 0x67,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x02, 0x9b, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe3, 0x64, 0x00, 0x6c, 0x1b, 0x6e, 0x30, 0xe1, 0x65, 0x00, 0xe1, 0x76,
- 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0x40, 0x09, 0x61, 0x6e, 0x00, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x01, 0x5b, 0x40, 0x07,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x2c, 0x74, 0x00, 0x00,
- 0x00, 0xfc, 0x61, 0x00, 0x00, 0x63, 0x04, 0x00, 0x65, 0x0a, 0x00, 0x67,
- 0x1a, 0x00, 0x68, 0x9b, 0x00, 0x69, 0xcb, 0x00, 0x6c, 0xdd, 0x00, 0x6e,
- 0x38, 0x01, 0x72, 0xa3, 0x02, 0x73, 0xdf, 0x04, 0x74, 0x60, 0x05, 0x78,
- 0xab, 0x05, 0x40, 0x07, 0x6c, 0x00, 0x40, 0x93, 0x74, 0x6f, 0x72, 0x00,
- 0xe3, 0x6a, 0x00, 0x70, 0x05, 0x72, 0x07, 0x40, 0x06, 0x61, 0x79, 0x00,
- 0x00, 0x09, 0x00, 0x55, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65, 0x11, 0x67,
- 0x52, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x06, 0x40, 0x00, 0x73, 0x6d, 0x00, 0xe3, 0x62, 0x00, 0x73, 0x08, 0x74,
- 0x0a, 0x40, 0x08, 0x75, 0x72, 0x67, 0x65, 0x72, 0x00, 0x00, 0x00, 0xe1,
- 0x61, 0x00, 0xe3, 0x62, 0x00, 0x72, 0x05, 0x74, 0x1a, 0x40, 0x06, 0x6c,
- 0x65, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x02, 0x00, 0xa6, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x0f, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x06, 0x40, 0x08, 0x75, 0x72, 0x67, 0x65, 0x72, 0x00, 0x40, 0x00, 0x67,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x19, 0xe1, 0x6d, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x09, 0xe2, 0x65, 0x00, 0x79,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x00, 0x3b, 0xe1, 0x63, 0x00, 0xe2, 0x6c,
- 0x00, 0x75, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72,
- 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x0b, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x01,
- 0xfe, 0x40, 0x00, 0x73, 0x00, 0x00, 0x55, 0xe6, 0x61, 0x00, 0x64, 0x09,
- 0x6c, 0x0b, 0x6f, 0x10, 0x75, 0x34, 0x76, 0x38, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x09, 0x40, 0x07, 0x75, 0x6d, 0x00,
- 0xe3, 0x63, 0x00, 0x64, 0x12, 0x75, 0x19, 0xe1, 0x69, 0x00, 0xe2, 0x70,
- 0x00, 0x74, 0x06, 0x40, 0x09, 0x65, 0x64, 0x65, 0x00, 0x40, 0x06, 0x79,
- 0x00, 0x40, 0x08, 0x72, 0x6f, 0x6d, 0x65, 0x00, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x07, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x65, 0x02, 0x79, 0x07, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e, 0x00,
- 0x00, 0x00, 0xf8, 0x61, 0x00, 0x00, 0x64, 0x17, 0x00, 0x65, 0x32, 0x00,
- 0x67, 0x66, 0x00, 0x69, 0x79, 0x00, 0x6f, 0x9c, 0x00, 0x74, 0xb1, 0x00,
- 0x75, 0x4e, 0x01, 0xe2, 0x6c, 0x00, 0x74, 0x0c, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6f,
- 0x6e, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x08, 0x6f, 0x0e, 0x00,
- 0x72, 0x40, 0x06, 0x74, 0x74, 0x61, 0x00, 0x40, 0x00, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x09, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x04, 0x40, 0x55,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x21, 0xe2, 0x62, 0x00, 0x74, 0x10,
- 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00,
- 0x40, 0x00, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x57, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x00, 0x61, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x61, 0x00, 0x66, 0x06, 0x40, 0x07, 0x6e, 0x63, 0x65, 0x00, 0x43,
- 0xbf, 0x75, 0x6c, 0x00, 0xe3, 0x61, 0x00, 0x72, 0x04, 0x73, 0x17, 0x40,
- 0x00, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x07,
- 0x6f, 0x6e, 0x00, 0xe2, 0x6d, 0x00, 0x75, 0x0c, 0xe2, 0x00, 0x00, 0x6f,
- 0x02, 0x00, 0x07, 0x40, 0x3b, 0x75, 0x73, 0x00, 0x40, 0x00, 0x73, 0x00,
- 0xe5, 0x00, 0x00, 0x27, 0x02, 0x69, 0x06, 0x72, 0x21, 0x75, 0x5a, 0x00,
- 0x72, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x6c, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x0f, 0xe2, 0x6c,
- 0x00, 0x75, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x00, 0x6c, 0x61, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x71, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x69,
- 0x00, 0x79, 0x0c, 0xe1, 0x73, 0x00, 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00,
- 0x07, 0x00, 0x06, 0x00, 0x07, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f,
- 0x1d, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x5e, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x65, 0x65, 0x00, 0xfd, 0x61, 0x00, 0x00, 0x62, 0x1b, 0x00,
- 0x64, 0x6b, 0x00, 0x67, 0x8b, 0x00, 0x69, 0x9d, 0x00, 0x6d, 0xec, 0x00,
- 0x6e, 0x2a, 0x01, 0x6f, 0x42, 0x01, 0x72, 0x49, 0x01, 0x73, 0x5b, 0x01,
- 0x74, 0xc0, 0x01, 0x76, 0x0e, 0x02, 0x79, 0x12, 0x02, 0xe2, 0x63, 0x00,
- 0x6e, 0x11, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x05, 0x40, 0x3b,
- 0x75, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0x40, 0x06, 0x64, 0x61, 0x00,
- 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x24, 0x69, 0x29, 0x6f, 0x2f, 0x02,
- 0x23, 0xe2, 0x6c, 0x00, 0x74, 0x18, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x86, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x69, 0x6d, 0x00, 0x40,
- 0x06, 0x6e, 0x61, 0x00, 0x40, 0x09, 0x61, 0x67, 0x65, 0x00, 0xe2, 0x73,
- 0x00, 0x74, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0x40, 0x00, 0x65, 0x6e, 0x00, 0xe3, 0x61, 0x00, 0x69,
- 0x05, 0x75, 0x14, 0x40, 0x3b, 0x6e, 0x74, 0x00, 0xe2, 0x63, 0x00, 0x67,
- 0x04, 0x40, 0x06, 0x74, 0x00, 0x40, 0x59, 0x72, 0x69, 0x73, 0x00, 0x40,
- 0x07, 0x72, 0x65, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02,
- 0x72, 0x06, 0x05, 0x27, 0x40, 0x00, 0x73, 0x00, 0x00, 0x09, 0xe4, 0x66,
- 0x00, 0x6c, 0x20, 0x73, 0x24, 0x74, 0x30, 0xe2, 0x69, 0x00, 0x79, 0x19,
- 0xe3, 0x61, 0x00, 0x63, 0x06, 0x65, 0x0e, 0x40, 0x37, 0x62, 0x6c, 0x65,
- 0x00, 0x40, 0x07, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x37, 0x64,
- 0x00, 0x03, 0xd9, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x69, 0x6d, 0x69,
- 0x6c, 0x69, 0x74, 0x75, 0x64, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x79, 0x0f,
- 0xe1, 0x62, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x06, 0xe2, 0x69, 0x00, 0x6f, 0x33, 0xe4, 0x63,
- 0x00, 0x66, 0x12, 0x6c, 0x18, 0x6e, 0x1e, 0xe2, 0x65, 0x00, 0x75, 0x06,
- 0x40, 0x07, 0x6c, 0x6c, 0x69, 0x00, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x65,
- 0x00, 0x40, 0x00, 0x6f, 0x72, 0x6d, 0x00, 0x40, 0x07, 0x69, 0x6f, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07, 0x40, 0x00, 0x75, 0x73,
- 0x00, 0x40, 0x07, 0x75, 0x74, 0x68, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x0e,
- 0xe2, 0x63, 0x00, 0x6c, 0x07, 0x40, 0x09, 0x75, 0x6c, 0x61, 0x72, 0x00,
- 0x00, 0x00, 0x40, 0x06, 0x65, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x69, 0x63,
- 0x61, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x06, 0x00, 0x00, 0xe5, 0x61, 0x00, 0x65,
- 0x19, 0x69, 0x22, 0x6f, 0x54, 0x75, 0x56, 0xe2, 0x00, 0x00, 0x74, 0x02,
- 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x64,
- 0x02, 0x05, 0x28, 0x00, 0x37, 0xe2, 0x66, 0x00, 0x6f, 0x18, 0xe2, 0x69,
- 0x00, 0x79, 0x11, 0xe2, 0x63, 0x00, 0x65, 0x08, 0x40, 0x07, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x72, 0x00, 0x02, 0x7f, 0xe1, 0x6e,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x05, 0x29, 0x40, 0x00,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06, 0x40, 0x00, 0x73,
- 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x27, 0x00, 0x77, 0xe2, 0x62,
- 0x00, 0x78, 0x1e, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x6c, 0x04, 0x74, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x00, 0x01, 0x89, 0x00, 0x09, 0xe2,
- 0x63, 0x00, 0x67, 0x0d, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x86, 0x6c,
- 0x00, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x07, 0x40, 0x00,
- 0x6e, 0x6f, 0x75, 0x73, 0x00, 0x00, 0x07, 0x40, 0x07, 0x65, 0x00, 0x00,
- 0xf3, 0xe4, 0x69, 0x00, 0x70, 0x1d, 0x73, 0x22, 0x74, 0x27, 0xe1, 0x63,
- 0x00, 0xe2, 0x6c, 0x00, 0x75, 0x04, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x74, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x09, 0x65, 0x6c,
- 0x00, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x61, 0x06, 0x69, 0x0a, 0x6d, 0x27,
- 0x72, 0x2d, 0x05, 0x2a, 0x40, 0x00, 0x73, 0x00, 0x40, 0x09, 0x6c, 0x00,
- 0xe3, 0x62, 0x00, 0x67, 0x06, 0x6e, 0x12, 0x40, 0x09, 0x75, 0x6c, 0x65,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x3b, 0x61, 0x6c,
- 0x00, 0x40, 0x07, 0x67, 0x00, 0x41, 0x89, 0x65, 0x6e, 0x74, 0x00, 0xe1,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe2, 0x61, 0x00,
- 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe5, 0x00,
- 0x00, 0x63, 0x02, 0x65, 0x06, 0x6f, 0x27, 0x74, 0x32, 0x00, 0x06, 0x40,
- 0x09, 0x68, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x04, 0x40,
- 0x06, 0x6e, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x09, 0x61, 0x6e, 0x00, 0x00, 0x06,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x2f, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x0b, 0xe1, 0x74, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x6e, 0x00, 0x75, 0x02, 0x00, 0x06,
- 0x40, 0x3b, 0x73, 0x00, 0xe2, 0x66, 0x00, 0x6f, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x73, 0x74, 0x73, 0x00, 0xc1, 0x61, 0x1a, 0x39, 0x00, 0x3b, 0x00,
- 0x69, 0x00, 0xd0, 0x00, 0xaa, 0x01, 0xfc, 0x01, 0x00, 0x00, 0x34, 0x02,
- 0x00, 0x00, 0x96, 0x02, 0x00, 0x00, 0x9f, 0x02, 0xa5, 0x02, 0x15, 0x03,
- 0x17, 0x03, 0xa9, 0x03, 0x24, 0x04, 0x00, 0x00, 0x36, 0x04, 0xf9, 0x04,
- 0xdc, 0x05, 0x00, 0x00, 0xb5, 0x06, 0x00, 0x00, 0x3e, 0x07, 0x00, 0x00,
- 0x50, 0x07, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x62, 0x02, 0x64, 0x17, 0x6c,
- 0x1d, 0x6e, 0x1f, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x07, 0x40, 0x07,
- 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x40, 0x06, 0x75, 0x63, 0x74, 0x00, 0x00, 0x09, 0x40, 0x06,
- 0x64, 0x00, 0xe3, 0x65, 0x00, 0x72, 0x09, 0x75, 0x59, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x09, 0x00, 0x07, 0xe1, 0x61, 0x00, 0xe4, 0x68, 0x00,
- 0x6e, 0x06, 0x70, 0x11, 0x74, 0x26, 0x40, 0x06, 0x61, 0x72, 0x70, 0x00,
- 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x79, 0x00, 0x00, 0x3b, 0xe1,
- 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x09, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69,
- 0x02, 0x6f, 0x07, 0x00, 0x39, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0x00, 0x40, 0x06, 0x72, 0x6e, 0x75, 0x6d, 0x00, 0xe6, 0x61, 0x00,
- 0x65, 0x27, 0x68, 0x54, 0x69, 0x5e, 0x74, 0x8d, 0x75, 0xc8, 0xe1, 0x72,
- 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x07, 0x00, 0x06, 0x40, 0x06,
- 0x67, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x67, 0x04, 0x6e, 0x0c, 0x72, 0x13,
- 0x01, 0x07, 0x00, 0x00, 0x40, 0x06, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x00,
- 0x40, 0x00, 0x6e, 0x69, 0x61, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x06,
- 0x40, 0x00, 0x67, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x79, 0x00, 0x40, 0x07,
- 0x79, 0x73, 0x73, 0x6f, 0x69, 0x73, 0x65, 0x00, 0xe3, 0x6e, 0x00, 0x6f,
- 0x0c, 0x73, 0x1f, 0xe2, 0x67, 0x00, 0x69, 0x02, 0x00, 0x00, 0x40, 0x07,
- 0x74, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06,
- 0x73, 0x69, 0x74, 0x75, 0x64, 0x65, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x1b,
- 0x75, 0x2f, 0xe1, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe1, 0x72, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x79, 0x08, 0x00, 0x09, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0x00,
- 0x06, 0x40, 0x2c, 0x61, 0x6c, 0x00, 0x40, 0x09, 0x6e, 0x61, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6f, 0x07, 0x40, 0x00, 0x69, 0x63, 0x65,
- 0x74, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x64, 0x1d, 0x70, 0x23, 0x74,
- 0x2a, 0x00, 0x95, 0xe2, 0x61, 0x00, 0x6f, 0x09, 0x40, 0x06, 0x73, 0x73,
- 0x65, 0x74, 0x74, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x66, 0x65, 0x72, 0x65,
- 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x69, 0x73, 0x63, 0x00,
- 0x40, 0x09, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05,
- 0x40, 0x5e, 0x70, 0x65, 0x00, 0x40, 0x00, 0x78, 0x00, 0xe2, 0x00, 0x00,
- 0x77, 0x02, 0x01, 0x1a, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x66, 0x12, 0x69,
- 0x1a, 0x70, 0x1f, 0x05, 0x1a, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x75, 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x06, 0x69,
- 0x6e, 0x64, 0x65, 0x72, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0x40, 0x09,
- 0x6f, 0x69, 0x6e, 0x74, 0x00, 0xe4, 0x65, 0x00, 0x69, 0x08, 0x6e, 0x35,
- 0x6f, 0x4a, 0x40, 0x00, 0x73, 0x69, 0x6d, 0x61, 0x6c, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x04, 0x00, 0x3b, 0x00, 0x06, 0xe1, 0x73, 0x00, 0xe2, 0x6d,
- 0x00, 0x74, 0x02, 0x00, 0x07, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40,
- 0x09, 0x73, 0x74, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02,
- 0x00, 0x07, 0x40, 0x3b, 0x75, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x69, 0x6e, 0x67, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x0d, 0x6c, 0x20, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x05, 0x2b,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x69, 0x00,
- 0x79, 0x09, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x03,
- 0xd9, 0xe4, 0x61, 0x00, 0x65, 0x28, 0x69, 0x3a, 0x75, 0x3c, 0xe3, 0x00,
- 0x00, 0x67, 0x02, 0x69, 0x0e, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x94, 0x00, 0x07, 0xe1, 0x6e, 0x00, 0xe3, 0x00,
- 0x00, 0x6f, 0x02, 0x79, 0x07, 0x00, 0x06, 0x40, 0x00, 0x75, 0x73, 0x00,
- 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x06, 0x40, 0x07, 0x67, 0x65, 0x00, 0x00, 0x00, 0x40, 0x07,
- 0x73, 0x00, 0x00, 0x07, 0xe7, 0x61, 0x00, 0x63, 0x0a, 0x64, 0x11, 0x65,
- 0x47, 0x6f, 0x65, 0x74, 0x70, 0x79, 0x7f, 0x40, 0x07, 0x69, 0x67, 0x72,
- 0x65, 0x74, 0x74, 0x65, 0x00, 0x40, 0x54, 0x69, 0x62, 0x6c, 0x65, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x63, 0x00, 0xe2, 0x61, 0x00, 0x74, 0x15, 0xe1,
- 0x74, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x01, 0x26, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1,
- 0x76, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x79,
- 0x11, 0x00, 0x09, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x61, 0x72, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x75, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0xe2,
- 0x61, 0x00, 0x6e, 0x05, 0x40, 0x09, 0x67, 0x65, 0x00, 0x40, 0x09, 0x65,
- 0x72, 0x00, 0x40, 0x06, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe5, 0x00, 0x00,
- 0x61, 0x02, 0x65, 0x22, 0x69, 0x34, 0x6f, 0x52, 0x03, 0xc2, 0xe3, 0x00,
- 0x00, 0x62, 0x02, 0x74, 0x07, 0x00, 0x06, 0x40, 0x54, 0x6c, 0x65, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x02, 0x6f, 0x07, 0x00, 0x39, 0x40, 0x07, 0x6f,
- 0x6e, 0x00, 0x40, 0x06, 0x72, 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x0b, 0xe2,
- 0x63, 0x00, 0x74, 0x04, 0x40, 0x07, 0x65, 0x00, 0x00, 0x3b, 0x00, 0x09,
- 0xe2, 0x6e, 0x00, 0x73, 0x15, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x69, 0x09,
- 0x00, 0x09, 0x40, 0x08, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x40, 0x06, 0x73,
- 0x74, 0x00, 0x40, 0x09, 0x74, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x69, 0x00,
- 0x6f, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00, 0x00, 0x09, 0xe1, 0x65, 0x00,
- 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x00,
- 0x75, 0x73, 0x00, 0xe7, 0x61, 0x00, 0x65, 0x15, 0x67, 0x19, 0x69, 0x38,
- 0x6f, 0x47, 0x74, 0x5c, 0x75, 0x9c, 0xe2, 0x67, 0x00, 0x6c, 0x0e, 0xe1,
- 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73,
- 0x00, 0x00, 0x00, 0x40, 0x06, 0x6f, 0x00, 0xe2, 0x69, 0x00, 0x75, 0x15,
- 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06, 0x00, 0x09,
- 0x40, 0x06, 0x6c, 0x00, 0x40, 0x07, 0x74, 0x79, 0x00, 0x40, 0x09, 0x6c,
- 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x6f, 0x00, 0xe1,
- 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x06, 0x73, 0x74, 0x00,
- 0x00, 0x07, 0xe1, 0x75, 0x00, 0xe3, 0x61, 0x00, 0x65, 0x13, 0x6f, 0x15,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x00,
- 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x06, 0xe2, 0x73, 0x00,
- 0x75, 0x0c, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x07, 0x74, 0x79, 0x00,
- 0x00, 0x07, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x6c, 0x00, 0x73, 0x11, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x63, 0x00, 0x74, 0x04, 0x40, 0x07,
- 0x65, 0x00, 0x00, 0x3b, 0x00, 0x09, 0xe7, 0x61, 0x00, 0x63, 0x0b, 0x65,
- 0x58, 0x69, 0x5a, 0x6f, 0xa7, 0x74, 0xab, 0x75, 0xaf, 0xe2, 0x00, 0x00,
- 0x67, 0x02, 0x00, 0x47, 0x40, 0x09, 0x65, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x0f, 0x6f, 0x13, 0x75, 0x40, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe2,
- 0x00, 0x00, 0x6c, 0x02, 0x00, 0x00, 0x00, 0x3b, 0x40, 0x00, 0x64, 0x00,
- 0xe2, 0x73, 0x00, 0x75, 0x0c, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x07,
- 0x40, 0x07, 0x74, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x15, 0xe1, 0x74,
- 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x65, 0x06, 0x00, 0x06, 0x40, 0x06,
- 0x79, 0x00, 0x40, 0x09, 0x73, 0x73, 0x00, 0x00, 0x00, 0x40, 0x07, 0x73,
- 0x00, 0x05, 0x2c, 0xe3, 0x62, 0x00, 0x6f, 0x15, 0x74, 0x24, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x53, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x54, 0x00, 0x54, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x61, 0x02, 0x05, 0x2d, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe4, 0x00,
- 0x00, 0x27, 0x02, 0x61, 0x06, 0x6f, 0x15, 0x01, 0x40, 0x40, 0x00, 0x73,
- 0x00, 0xe2, 0x6e, 0x00, 0x74, 0x04, 0x40, 0x09, 0x74, 0x00, 0x40, 0x09,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x09, 0x72, 0x00, 0x40, 0x06, 0x72, 0x00,
- 0x40, 0x06, 0x61, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x56, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65,
- 0x07, 0x40, 0x06, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x01, 0x4b, 0x00, 0x07, 0xe5, 0x61, 0x00, 0x69, 0x34, 0x72, 0x63,
- 0x74, 0xad, 0x75, 0xb3, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x6c, 0x04, 0x6d,
- 0x26, 0x00, 0x07, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x19,
- 0x03, 0x6c, 0xe2, 0x74, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x79, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x07, 0x40, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x01,
- 0xbd, 0x00, 0x07, 0x40, 0x09, 0x69, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x63,
- 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x42, 0x40,
- 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x07, 0x40, 0x09, 0x73, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x06,
- 0x40, 0x00, 0x6f, 0x75, 0x73, 0x00, 0xe3, 0x66, 0x00, 0x6e, 0x1a, 0x6f,
- 0x1e, 0xe3, 0x61, 0x00, 0x69, 0x08, 0x79, 0x11, 0x40, 0x07, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x00, 0x00, 0x42, 0x40, 0x06, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x07, 0xe1, 0x63, 0x00, 0xe2, 0x00, 0x00, 0x61,
- 0x02, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x6c, 0x79, 0x00, 0x40, 0x07, 0x6c,
- 0x65, 0x73, 0x00, 0xe1, 0x70, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00,
- 0xe1, 0x61, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00,
- 0xa6, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x69, 0x3a, 0xe3,
- 0x00, 0x00, 0x63, 0x02, 0x72, 0x25, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0xe2, 0x6f, 0x00, 0x74, 0x13, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x61,
- 0x00, 0x75, 0x02, 0x00, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe4, 0x64, 0x00,
- 0x66, 0x0d, 0x70, 0x11, 0x73, 0x19, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x01,
- 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0xab, 0x79, 0x00, 0x40,
- 0x00, 0x61, 0x72, 0x6f, 0x75, 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x63,
- 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x72, 0xe1,
- 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x69, 0x06,
- 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x3b, 0x73, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0x40, 0x06, 0x65, 0x72, 0x00, 0xfc, 0x63, 0x00, 0x00, 0x64, 0x8c, 0x00,
- 0x67, 0x91, 0x00, 0x69, 0xa0, 0x00, 0x6c, 0xde, 0x00, 0x6d, 0x11, 0x02,
- 0x6f, 0x16, 0x02, 0x72, 0x2b, 0x02, 0x74, 0x57, 0x02, 0x75, 0x70, 0x02,
- 0x77, 0x89, 0x02, 0x79, 0x94, 0x02, 0xe2, 0x61, 0x00, 0x69, 0x57, 0xe3,
- 0x62, 0x00, 0x6c, 0x14, 0x74, 0x36, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x75,
- 0x06, 0x00, 0x00, 0x40, 0x09, 0x65, 0x00, 0x40, 0x06, 0x6c, 0x61, 0x72,
- 0x79, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x56, 0xe3, 0x63, 0x00,
- 0x73, 0x02, 0x7a, 0x06, 0x00, 0x00, 0x40, 0x06, 0x74, 0x00, 0xe2, 0x61,
- 0x00, 0x65, 0x07, 0x40, 0x09, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x3a,
- 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x76, 0x0e, 0xe1, 0x6e, 0x00, 0xe2,
- 0x00, 0x00, 0x61, 0x02, 0x05, 0x2e, 0x40, 0x3b, 0x6c, 0x00, 0x40, 0x09,
- 0x65, 0x00, 0xe1, 0x66, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x61, 0x00, 0x6f, 0x0f, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x57, 0x40, 0x07, 0x6f, 0x6e, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x40, 0x06, 0x6b, 0x61, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x02, 0x00, 0x06, 0x40, 0x00, 0x73, 0x68, 0x00, 0xe3, 0x63,
- 0x00, 0x64, 0x2c, 0x6c, 0x2e, 0xe1, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64,
- 0x02, 0x6c, 0x04, 0x6d, 0x1a, 0x05, 0x2f, 0x00, 0x37, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x61, 0x69, 0x6c,
- 0x00, 0x03, 0x87, 0xe2, 0x61, 0x00, 0x65, 0x02, 0x00, 0x00, 0x00, 0x07,
- 0xf8, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x63, 0x1f, 0x00, 0x65, 0x39,
- 0x00, 0x69, 0x3b, 0x00, 0x6c, 0x52, 0x00, 0x74, 0x65, 0x00, 0x75, 0x82,
- 0x00, 0x00, 0x08, 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe2, 0x74, 0x00, 0x7a, 0x04,
- 0x40, 0x07, 0x79, 0x00, 0x40, 0x3a, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6e, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x63, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0x07, 0x40, 0x00, 0x73, 0x00, 0x00, 0x09,
- 0xe1, 0x74, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x07, 0x40, 0x00, 0x6c, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x95,
- 0x40, 0x09, 0x61, 0x6c, 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6d,
- 0x0f, 0x00, 0x69, 0xe2, 0x67, 0x00, 0x69, 0x04, 0x40, 0x09, 0x65, 0x00,
- 0x40, 0x00, 0x63, 0x00, 0x40, 0x06, 0x65, 0x74, 0x65, 0x72, 0x00, 0xe5,
- 0x62, 0x00, 0x6d, 0x15, 0x6e, 0x35, 0x70, 0x66, 0x74, 0x89, 0xe2, 0x69,
- 0x00, 0x6c, 0x07, 0x40, 0x07, 0x6c, 0x69, 0x74, 0x79, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0xe1, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x17, 0xe1,
- 0x72, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0d, 0xe2, 0x6c, 0x00, 0x73, 0x04,
- 0x40, 0x54, 0x79, 0x00, 0x40, 0x07, 0x6d, 0x00, 0x00, 0x06, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x93, 0x40,
- 0x07, 0x73, 0x6d, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x75, 0x00, 0xe2, 0x61,
- 0x00, 0x6f, 0x05, 0x40, 0x06, 0x72, 0x79, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x2c, 0x69, 0x74, 0x00,
- 0xe1, 0x64, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x95, 0x40, 0x07, 0x73, 0x6d, 0x00, 0xe2, 0x61, 0x00,
- 0x74, 0x22, 0xe1, 0x63, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x6f, 0x00, 0x74,
- 0x13, 0xe1, 0x75, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x79, 0x00,
- 0x40, 0x09, 0x65, 0x78, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x06,
- 0x72, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x72, 0x06, 0x05, 0x30,
- 0x40, 0x00, 0x73, 0x00, 0x00, 0x06, 0xe1, 0x63, 0x00, 0xe1, 0x68, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x73, 0x06, 0x01, 0x4b, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x3a, 0x61, 0x66, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02,
- 0x00, 0x93, 0x40, 0x06, 0x6c, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x15, 0xe1,
- 0x67, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x72, 0x02, 0x75, 0x04,
- 0x00, 0xa5, 0x00, 0x07, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00,
- 0xe2, 0x6d, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x00, 0x69, 0x63, 0x00,
- 0xe2, 0x6c, 0x00, 0x76, 0xb1, 0xe6, 0x63, 0x00, 0x67, 0x1a, 0x6e, 0x51,
- 0x70, 0x80, 0x74, 0x86, 0x76, 0x98, 0xe1, 0x61, 0x00, 0xe1, 0x6e, 0x00,
- 0xe1, 0x69, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0xe1, 0x61, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0xda, 0xe4, 0x61, 0x00,
- 0x73, 0x04, 0x74, 0x08, 0x7a, 0x0c, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x09,
- 0x6d, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40,
- 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00,
- 0x3f, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00,
- 0xe1, 0x62, 0x00, 0xe2, 0x69, 0x00, 0x6c, 0x15, 0xe1, 0x6c, 0x00, 0xe1,
- 0x69, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x05, 0x40, 0x00,
- 0x65, 0x73, 0x00, 0x00, 0x53, 0xe2, 0x65, 0x00, 0x79, 0x02, 0x00, 0x54,
- 0x00, 0x54, 0x40, 0x00, 0x69, 0x6e, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1,
- 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x02, 0x00, 0x06, 0x40, 0x00, 0x75,
- 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0x40, 0x09, 0x75, 0x7a, 0x65, 0x6c, 0x61, 0x00, 0x40, 0x00,
- 0x69, 0x6e, 0x67, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0x65,
- 0x90, 0x08, 0x68, 0x47, 0x0d, 0x69, 0x4a, 0x13, 0x6b, 0x70, 0x1a, 0x6f,
- 0x72, 0x1a, 0x70, 0x1d, 0x21, 0x72, 0x21, 0x21, 0x74, 0x30, 0x23, 0x75,
- 0x32, 0x23, 0x05, 0x31, 0xc0, 0x62, 0x19, 0x35, 0x00, 0x3b, 0x00, 0x54,
- 0x00, 0x00, 0x00, 0x8b, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x0d, 0x01, 0x00,
- 0x00, 0xad, 0x01, 0xce, 0x01, 0xa3, 0x02, 0xa9, 0x02, 0x00, 0x00, 0x37,
- 0x03, 0x00, 0x00, 0x3d, 0x03, 0xe4, 0x04, 0x11, 0x06, 0x00, 0x00, 0xac,
- 0x07, 0x00, 0x00, 0x0a, 0x08, 0x2d, 0x08, 0x89, 0x08, 0x40, 0x08, 0x62,
- 0x69, 0x74, 0x00, 0xe1, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6f,
- 0x09, 0x79, 0x0b, 0x05, 0x32, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00,
- 0x00, 0x06, 0x01, 0x15, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x65, 0x16, 0x67,
- 0x26, 0x69, 0x2a, 0x00, 0xfa, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6c, 0x09,
- 0x40, 0x00, 0x64, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x5e, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x07, 0x40, 0x08, 0x65, 0x00, 0x00, 0x09, 0xe3,
- 0x65, 0x00, 0x66, 0x04, 0x74, 0x13, 0x40, 0x06, 0x72, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00,
- 0x07, 0x00, 0x55, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x67, 0x18, 0x6f, 0x47,
- 0x74, 0x55, 0x00, 0xfa, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x72, 0x04, 0x00,
- 0x09, 0x00, 0x37, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x2b, 0x40, 0x07,
- 0x72, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x0b, 0x6c, 0x24, 0xe2, 0x64, 0x00,
- 0x72, 0x02, 0x00, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe2, 0x6e, 0x00, 0x73,
- 0x04, 0x40, 0x00, 0x67, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x82, 0x65,
- 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x23, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x06, 0x61, 0x69, 0x6c, 0x00, 0xe6, 0x66, 0x00,
- 0x6c, 0x02, 0x6e, 0x14, 0x73, 0x3a, 0x74, 0x5a, 0x76, 0x87, 0x00, 0x09,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0xfe, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x73, 0x02, 0x77,
- 0x17, 0x00, 0x09, 0xe1, 0x63, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00,
- 0xe2, 0x00, 0x00, 0x69, 0x02, 0x04, 0x80, 0x40, 0x07, 0x6e, 0x67, 0x00,
- 0x40, 0x09, 0x72, 0x69, 0x67, 0x68, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x62, 0x02, 0x63, 0x08, 0x6c, 0x0e, 0x00, 0x06, 0x40, 0x09,
- 0x61, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x74, 0x00, 0x40, 0x09,
- 0x69, 0x6e, 0x65, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x70,
- 0x0b, 0x72, 0x13, 0x73, 0x19, 0x00, 0xfe, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x00,
- 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x74, 0x61, 0x66, 0x66,
- 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00,
- 0x07, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x6e, 0x15, 0x01,
- 0x01, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0xad, 0xe7, 0x64,
- 0x00, 0x65, 0x0e, 0x6b, 0x10, 0x6c, 0x53, 0x6e, 0xae, 0x72, 0xb3, 0x74,
- 0xb8, 0xe1, 0x6f, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x08, 0x40,
- 0x00, 0x73, 0x00, 0x00, 0x82, 0xe6, 0x00, 0x00, 0x61, 0x02, 0x65, 0x12,
- 0x69, 0x16, 0x6f, 0x23, 0x77, 0x31, 0x00, 0xfe, 0xe2, 0x62, 0x00, 0x77,
- 0x06, 0x40, 0x08, 0x6f, 0x75, 0x74, 0x00, 0x40, 0x09, 0x61, 0x79, 0x00,
- 0x40, 0x07, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x73,
- 0x00, 0x40, 0x07, 0x67, 0x00, 0xe2, 0x75, 0x00, 0x76, 0x04, 0x40, 0x06,
- 0x74, 0x00, 0x40, 0x09, 0x65, 0x72, 0x00, 0x40, 0x06, 0x61, 0x79, 0x00,
- 0xe8, 0x00, 0x00, 0x61, 0x02, 0x62, 0x14, 0x65, 0x1b, 0x66, 0x26, 0x6f,
- 0x2e, 0x70, 0x41, 0x79, 0x48, 0x00, 0x55, 0xe2, 0x62, 0x00, 0x68, 0x04,
- 0x40, 0x06, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x40, 0x07, 0x6f, 0x61, 0x72, 0x64, 0x00, 0xe2, 0x74, 0x00, 0x79,
- 0x02, 0x00, 0x09, 0x40, 0x1a, 0x65, 0x00, 0x40, 0x09, 0x6c, 0x6f, 0x77,
- 0x65, 0x72, 0x00, 0xe2, 0x70, 0x00, 0x77, 0x0c, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x02, 0xce, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x47, 0x40, 0x2c,
- 0x61, 0x70, 0x65, 0x72, 0x00, 0x00, 0x08, 0x40, 0x09, 0x75, 0x74, 0x00,
- 0x40, 0x09, 0x75, 0x73, 0x00, 0xe1, 0x7a, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xc3, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x70, 0x75, 0x6d,
- 0x00, 0xe7, 0x00, 0x00, 0x64, 0x02, 0x65, 0x27, 0x67, 0x29, 0x6b, 0x38,
- 0x6e, 0x3a, 0x74, 0x62, 0x05, 0x33, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x09, 0xe1, 0x72, 0x00, 0xe4, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c,
- 0x0c, 0x04, 0x16, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x73,
- 0x00, 0x40, 0x06, 0x75, 0x73, 0x74, 0x00, 0x00, 0x09, 0xe1, 0x6c, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07,
- 0x00, 0x4c, 0xe2, 0x61, 0x00, 0x65, 0x13, 0xe2, 0x00, 0x00, 0x62, 0x02,
- 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x06,
- 0x00, 0x08, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0xe2, 0x73, 0x00,
- 0x74, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x6f,
- 0x06, 0x00, 0x55, 0x40, 0x37, 0x64, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x05, 0x34, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x69, 0x74, 0x69, 0x00, 0xff, 0x00, 0x00, 0x00, 0x62, 0x02, 0x00,
- 0x64, 0x1a, 0x00, 0x65, 0x43, 0x00, 0x66, 0x55, 0x00, 0x68, 0x5b, 0x00,
- 0x69, 0x6b, 0x00, 0x6c, 0x7a, 0x00, 0x6d, 0x91, 0x00, 0x6e, 0xf7, 0x00,
- 0x70, 0x03, 0x01, 0x72, 0x28, 0x01, 0x73, 0x5a, 0x01, 0x74, 0x60, 0x01,
- 0x79, 0x77, 0x01, 0x00, 0x06, 0xe2, 0x6c, 0x00, 0x6f, 0x0c, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x40, 0x06,
- 0x6e, 0x6e, 0x65, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x72, 0x0b,
- 0x01, 0x61, 0xe2, 0x6e, 0x00, 0x72, 0x02, 0x00, 0x09, 0x00, 0x09, 0xe2,
- 0x65, 0x00, 0x6f, 0x05, 0x40, 0x08, 0x73, 0x73, 0x00, 0xe2, 0x62, 0x00,
- 0x6f, 0x04, 0x40, 0x06, 0x65, 0x00, 0x40, 0x06, 0x6d, 0x00, 0xe3, 0x00,
- 0x00, 0x68, 0x02, 0x7a, 0x09, 0x00, 0x09, 0x40, 0x5e, 0x6f, 0x75, 0x73,
- 0x65, 0x00, 0x00, 0x00, 0x40, 0x07, 0x61, 0x72, 0x65, 0x00, 0xe2, 0x65,
- 0x00, 0x6f, 0x05, 0x40, 0x09, 0x61, 0x64, 0x00, 0x40, 0x06, 0x72, 0x73,
- 0x65, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x37, 0x79, 0x00, 0x40,
- 0xdb, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x00,
- 0x6b, 0x65, 0x00, 0xe2, 0x63, 0x00, 0x72, 0x04, 0x40, 0x09, 0x6b, 0x00,
- 0x40, 0x09, 0x64, 0x00, 0xe8, 0x00, 0x00, 0x62, 0x02, 0x65, 0x0b, 0x68,
- 0x0f, 0x69, 0x2e, 0x6e, 0x33, 0x6f, 0x39, 0x74, 0x51, 0x05, 0x35, 0x40,
- 0x00, 0x6c, 0x6f, 0x6f, 0x64, 0x65, 0x64, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x5d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01,
- 0x25, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x01, 0x1e, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe3, 0x00,
- 0x00, 0x61, 0x02, 0x6c, 0x18, 0x00, 0x55, 0xe2, 0x69, 0x00, 0x74, 0x05,
- 0x40, 0x00, 0x6e, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x07, 0x00, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x65, 0x00, 0xe3,
- 0x61, 0x00, 0x65, 0x15, 0x69, 0x1e, 0xe1, 0x6e, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x06, 0x00, 0x59, 0x40, 0x37, 0x64,
- 0x00, 0x00, 0x5e, 0xe2, 0x64, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x09,
- 0xe2, 0x6e, 0x00, 0x6f, 0x04, 0x40, 0x00, 0x67, 0x00, 0x40, 0x06, 0x72,
- 0x00, 0x40, 0x06, 0x68, 0x69, 0x70, 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02,
- 0x69, 0x07, 0x79, 0x0c, 0x00, 0x09, 0x40, 0x06, 0x6f, 0x67, 0x00, 0x40,
- 0x07, 0x6d, 0x65, 0x00, 0x00, 0x60, 0x03, 0x99, 0xf7, 0x00, 0x00, 0x00,
- 0x61, 0x02, 0x00, 0x68, 0x07, 0x00, 0x6e, 0x9b, 0x00, 0x70, 0xa0, 0x00,
- 0x73, 0xba, 0x00, 0x74, 0xc0, 0x00, 0x00, 0x00, 0x40, 0x00, 0x62, 0x69,
- 0x00, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x62, 0x08, 0x63, 0x21, 0x65, 0x36,
- 0x69, 0x57, 0x6f, 0x5c, 0x72, 0x61, 0x73, 0x6f, 0x74, 0x76, 0x79, 0x7b,
- 0x05, 0x36, 0x40, 0x06, 0x62, 0x6c, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x6f,
- 0x06, 0x40, 0x06, 0x73, 0x69, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x77, 0x05,
- 0x40, 0x06, 0x72, 0x64, 0x00, 0x40, 0x06, 0x6c, 0x00, 0xe1, 0x6c, 0x00,
- 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00,
- 0x73, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x75, 0x74,
- 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x04, 0x40, 0x09, 0x67, 0x00, 0x40, 0x09,
- 0x6f, 0x6d, 0x00, 0x40, 0x06, 0x74, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x09,
- 0x75, 0x62, 0x00, 0x00, 0x60, 0x40, 0x00, 0x27, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x09, 0xe1, 0x73, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x2c, 0x61, 0x69, 0x6c, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x07, 0x72, 0x49, 0x00, 0x00, 0x40, 0x07, 0x67, 0x65, 0x00, 0xe7, 0x00,
- 0x00, 0x62, 0x02, 0x66, 0x0a, 0x6c, 0x1d, 0x70, 0x23, 0x72, 0x2a, 0x77,
- 0x2c, 0x00, 0x7e, 0x40, 0x09, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x00, 0xe1,
- 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00,
- 0x40, 0x07, 0x61, 0x70, 0x65, 0x72, 0x00, 0x00, 0x07, 0x40, 0x00, 0x61,
- 0x74, 0x65, 0x72, 0x00, 0x40, 0x06, 0x65, 0x6c, 0x00, 0xf3, 0x63, 0x00,
- 0x00, 0x65, 0x74, 0x00, 0x74, 0x7f, 0x01, 0xe1, 0x68, 0x00, 0xea, 0x00,
- 0x00, 0x61, 0x02, 0x62, 0x08, 0x64, 0x0e, 0x65, 0x13, 0x66, 0x17, 0x6d,
- 0x2a, 0x73, 0x48, 0x74, 0x4f, 0x77, 0x56, 0x01, 0xb0, 0x40, 0x37, 0x62,
- 0x6c, 0x65, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x6f,
- 0x67, 0x00, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x15, 0xe2, 0x6b, 0x00, 0x6e, 0x0e, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0x00, 0x07, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x08, 0x74, 0x72, 0x61,
- 0x70, 0x00, 0x40, 0x06, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x40, 0x09, 0x6f,
- 0x72, 0x64, 0x00, 0xf1, 0x72, 0x00, 0x00, 0xed, 0x00, 0x00, 0x62, 0x02,
- 0x63, 0x21, 0x66, 0x45, 0x68, 0x5c, 0x69, 0x62, 0x6c, 0x69, 0x6d, 0x82,
- 0x70, 0x99, 0x73, 0xb1, 0x74, 0xcc, 0x77, 0xd3, 0x79, 0xea, 0x00, 0x95,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6f, 0x09, 0x40, 0x09, 0x64, 0x00, 0x40,
- 0x06, 0x72, 0x64, 0x00, 0xe2, 0x61, 0x00, 0x72, 0x05, 0x45, 0x37, 0x72,
- 0x64, 0x00, 0x40, 0x00, 0x6e, 0x65, 0x00, 0xe2, 0x6f, 0x00, 0x72, 0x10,
- 0xe2, 0x6c, 0x00, 0x75, 0x05, 0x40, 0x09, 0x6f, 0x72, 0x00, 0x40, 0x06,
- 0x72, 0x73, 0x65, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x07, 0x66,
- 0x74, 0x00, 0x40, 0x07, 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x6f, 0x05,
- 0x72, 0x0a, 0x40, 0x06, 0x6c, 0x6c, 0x00, 0x40, 0x06, 0x77, 0x6c, 0x00,
- 0x40, 0x09, 0x6f, 0x6e, 0x74, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x65, 0x00,
- 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x0d,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x79, 0x00, 0x40, 0x09, 0x65,
- 0x00, 0x40, 0x00, 0x67, 0x67, 0x65, 0x64, 0x00, 0xe3, 0x61, 0x00, 0x65,
- 0x05, 0x69, 0x0b, 0x40, 0x55, 0x72, 0x6b, 0x00, 0x40, 0x06, 0x6c, 0x6f,
- 0x6e, 0x00, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x66, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x2c, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02,
- 0x69, 0x07, 0x70, 0x0c, 0x00, 0x07, 0x40, 0x09, 0x65, 0x64, 0x00, 0x40,
- 0x09, 0x64, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x75, 0x74, 0x00, 0x40, 0x00,
- 0x69, 0x67, 0x68, 0x74, 0x00, 0xe3, 0x61, 0x00, 0x68, 0x04, 0x6f, 0x0a,
- 0x40, 0x09, 0x79, 0x00, 0x40, 0x06, 0x65, 0x65, 0x6c, 0x00, 0x40, 0x07,
- 0x72, 0x6b, 0x73, 0x00, 0x00, 0x96, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6c,
- 0x07, 0x00, 0x09, 0x40, 0x07, 0x67, 0x65, 0x00, 0x40, 0x82, 0x65, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x4e, 0x79, 0x55, 0xe5, 0x00, 0x00, 0x62, 0x02,
- 0x66, 0x08, 0x6c, 0x0e, 0x72, 0x31, 0x00, 0xa5, 0x40, 0x08, 0x61, 0x6e,
- 0x64, 0x00, 0x40, 0x00, 0x6f, 0x72, 0x6d, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x19, 0xe2, 0x6e, 0x00, 0x74, 0x12, 0xe1, 0x67, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x06, 0x40, 0x00, 0x6b, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x69, 0x06, 0x01, 0x2b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x3b, 0x6e, 0x67,
- 0x00, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x01, 0x0c, 0xe4, 0x00,
- 0x00, 0x69, 0x02, 0x77, 0x09, 0x79, 0x18, 0x04, 0x23, 0x40, 0x07, 0x6e,
- 0x65, 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x6f, 0x05, 0x40, 0x06, 0x6e,
- 0x67, 0x00, 0x40, 0x06, 0x72, 0x6b, 0x00, 0x01, 0x15, 0xe6, 0x00, 0x00,
- 0x62, 0x02, 0x66, 0x08, 0x6c, 0x1c, 0x73, 0x33, 0x77, 0x39, 0x00, 0x06,
- 0x40, 0x06, 0x69, 0x6c, 0x6c, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x06, 0x6e,
- 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00,
- 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe8, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x06, 0x69, 0x64, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x72,
- 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x08, 0x6f, 0x6f, 0x00, 0xfe, 0x00,
- 0x00, 0x00, 0x27, 0x02, 0x00, 0x61, 0x19, 0x00, 0x62, 0x70, 0x01, 0x64,
- 0xfa, 0x01, 0x65, 0x29, 0x02, 0x66, 0xb1, 0x02, 0x69, 0xb5, 0x02, 0x6c,
- 0x44, 0x03, 0x6e, 0xc9, 0x03, 0x70, 0xdc, 0x03, 0x72, 0xe0, 0x03, 0x73,
- 0x03, 0x04, 0x74, 0x50, 0x04, 0x00, 0x00, 0xe4, 0x64, 0x00, 0x6c, 0x02,
- 0x72, 0x06, 0x76, 0x0a, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00,
- 0x65, 0x00, 0x40, 0x00, 0x65, 0x00, 0xf8, 0x6b, 0x00, 0x00, 0x6c, 0x34,
- 0x00, 0x6e, 0x50, 0x00, 0x70, 0x52, 0x00, 0x72, 0x72, 0x00, 0x73, 0xa8,
- 0x00, 0x74, 0xad, 0x00, 0x76, 0x2b, 0x01, 0xe6, 0x00, 0x00, 0x65, 0x02,
- 0x66, 0x10, 0x69, 0x16, 0x6c, 0x1b, 0x6e, 0x21, 0x05, 0x38, 0xe1, 0x6e,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x54, 0x40, 0x07, 0x72, 0x00,
- 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0x40,
- 0x06, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x09, 0x65, 0x73, 0x73, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x01, 0x29, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00,
- 0x69, 0x02, 0x79, 0x09, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x3b, 0x00, 0x72, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe4,
- 0x00, 0x00, 0x69, 0x02, 0x6c, 0x07, 0x72, 0x0d, 0x00, 0x09, 0x40, 0x00,
- 0x7a, 0x65, 0x00, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x79,
- 0x00, 0xe5, 0x00, 0x00, 0x61, 0x02, 0x65, 0x08, 0x69, 0x0c, 0x79, 0x29,
- 0x05, 0x39, 0x40, 0x37, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00,
- 0xe4, 0x65, 0x00, 0x6c, 0x04, 0x6e, 0x08, 0x73, 0x0e, 0x40, 0x37, 0x64,
- 0x00, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x3b, 0x6f, 0x6d, 0x65, 0x00, 0x03, 0x0a, 0x43, 0x7c, 0x65, 0x6c, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe7, 0x00, 0x00,
- 0x62, 0x02, 0x63, 0x09, 0x69, 0x0f, 0x6d, 0x26, 0x70, 0x33, 0x73, 0x45,
- 0x00, 0x2c, 0x41, 0x21, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x40, 0x09, 0x6f,
- 0x63, 0x6b, 0x00, 0xe2, 0x6e, 0x00, 0x7a, 0x04, 0x40, 0x07, 0x67, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69, 0x6f, 0x6e, 0x00,
- 0x00, 0x3a, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40,
- 0x00, 0x6e, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x07, 0x40, 0x09, 0x72, 0x73,
- 0x6f, 0x6e, 0x00, 0x40, 0xad, 0x6f, 0x6f, 0x66, 0x00, 0xe1, 0x74, 0x00,
- 0xe1, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00,
- 0x70, 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67,
- 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x63, 0x10, 0x64, 0x1e, 0x66, 0x26,
- 0x69, 0x35, 0x6c, 0x45, 0x6d, 0x4a, 0x70, 0x5f, 0x73, 0x65, 0x00, 0x06,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x6d, 0x00, 0x73, 0x02, 0x00, 0x09,
- 0x41, 0x25, 0x74, 0x00, 0x40, 0x09, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x65, 0x74, 0x00, 0x40, 0x07,
- 0x6f, 0x74, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x05, 0x40, 0x06, 0x61, 0x72,
- 0x00, 0x40, 0x09, 0x6f, 0x64, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x67, 0x00,
- 0xe2, 0x61, 0x00, 0x69, 0x07, 0x40, 0x06, 0x73, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x09, 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61,
- 0x67, 0x65, 0x00, 0xe2, 0x68, 0x00, 0x69, 0x06, 0x40, 0x09, 0x6f, 0x74,
- 0x73, 0x00, 0x40, 0x06, 0x74, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x64, 0x02,
- 0x67, 0x15, 0x6c, 0x20, 0x00, 0x76, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x77, 0x00, 0x00, 0x40, 0x06, 0x6e, 0x67,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x5e, 0x40, 0x09, 0x65, 0x00,
- 0x40, 0x07, 0x6f, 0x63, 0x6b, 0x00, 0xe7, 0x00, 0x00, 0x64, 0x02, 0x69,
- 0x23, 0x6b, 0x28, 0x6e, 0x4a, 0x70, 0x5f, 0x76, 0x74, 0x01, 0x64, 0xe5,
- 0x00, 0x00, 0x65, 0x02, 0x6b, 0x06, 0x6c, 0x0e, 0x79, 0x14, 0x00, 0xe7,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x08, 0x69, 0x6c, 0x6c, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x00, 0x60, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x65, 0x07, 0x6c, 0x0c, 0x6e, 0x10,
- 0x00, 0x86, 0x40, 0x06, 0x61, 0x79, 0x00, 0x40, 0xfa, 0x6e, 0x64, 0x00,
- 0x40, 0x06, 0x79, 0x00, 0x40, 0x06, 0x69, 0x67, 0x68, 0x74, 0x00, 0xe4,
- 0x00, 0x00, 0x69, 0x02, 0x73, 0x06, 0x79, 0x0a, 0x00, 0x3a, 0x41, 0xa5,
- 0x65, 0x00, 0x40, 0xf3, 0x79, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x65,
- 0x02, 0x69, 0x06, 0x79, 0x0a, 0x03, 0x3d, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x00, 0x65, 0x00, 0x01, 0x72, 0x40, 0x09, 0x69, 0x6c, 0x00, 0x40, 0x09,
- 0x74, 0x00, 0xe2, 0x67, 0x00, 0x72, 0x6c, 0xe1, 0x68, 0x00, 0xe5, 0x00,
- 0x00, 0x27, 0x02, 0x62, 0x06, 0x73, 0x0e, 0x74, 0x10, 0x05, 0x3a, 0x40,
- 0x00, 0x73, 0x00, 0x40, 0x08, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00, 0x00,
- 0x77, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x6c, 0x15, 0x79, 0x41,
- 0x02, 0xce, 0x40, 0x37, 0x64, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x13, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe1, 0x66, 0x00,
- 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x96, 0xe2, 0x00, 0x00, 0x64, 0x02,
- 0x00, 0x09, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x6e, 0x06, 0x6f, 0x0c, 0x00,
- 0x63, 0x40, 0x09, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x09, 0xe7, 0x63, 0x00, 0x64, 0x06, 0x66, 0x11, 0x6b, 0x17, 0x6c, 0x1c,
- 0x73, 0x4f, 0x74, 0x5d, 0x40, 0x82, 0x6f, 0x6d, 0x65, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x02, 0xc8, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x61,
- 0x72, 0x65, 0x00, 0x40, 0x07, 0x69, 0x6e, 0x00, 0xe6, 0x00, 0x00, 0x68,
- 0x02, 0x69, 0x08, 0x6e, 0x16, 0x73, 0x1c, 0x79, 0x24, 0x05, 0x3b, 0x40,
- 0x06, 0x65, 0x61, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x6e, 0x02, 0x00, 0x00,
- 0x40, 0x09, 0x67, 0x74, 0x6f, 0x6e, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x40, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x08, 0xe1,
- 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x3f, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x77, 0x02, 0x00, 0xec, 0x40, 0x06, 0x65, 0x69, 0x67, 0x68,
- 0x74, 0x00, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x64, 0x06, 0x74, 0x08, 0x00,
- 0x07, 0x40, 0x09, 0x68, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6e, 0x02, 0x77, 0x07, 0x00,
- 0x00, 0x40, 0x00, 0x27, 0x74, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00, 0x07, 0x40, 0x00, 0x65, 0x73, 0x00,
- 0xe1, 0x74, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x65, 0x09, 0x77, 0x3b,
- 0x00, 0x07, 0x40, 0x00, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40, 0x06, 0x79, 0x00, 0xe4, 0x00, 0x00,
- 0x65, 0x02, 0x69, 0x06, 0x6d, 0x17, 0x00, 0x0f, 0x40, 0x07, 0x72, 0x00,
- 0xe1, 0x7a, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x07, 0x40, 0x07, 0x74, 0x69,
- 0x6f, 0x6e, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x6f, 0x73, 0x74, 0x00, 0x40,
- 0x08, 0x61, 0x72, 0x64, 0x00, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x08,
- 0x6e, 0x0e, 0x74, 0x14, 0x77, 0x29, 0x02, 0x12, 0x40, 0x06, 0x61, 0x63,
- 0x6b, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x0b, 0xe2, 0x72, 0x00, 0x73, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x40,
- 0x08, 0x61, 0x72, 0x65, 0x00, 0xf6, 0x61, 0x00, 0x00, 0x65, 0xaf, 0x00,
- 0x69, 0x1c, 0x02, 0x6f, 0x76, 0x04, 0x75, 0xc9, 0x05, 0x79, 0xe1, 0x05,
- 0xe5, 0x63, 0x00, 0x6c, 0x0e, 0x6d, 0x33, 0x72, 0x4c, 0x74, 0x58, 0xe1,
- 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe4, 0x40, 0x07, 0x72,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x1b, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x72,
- 0x12, 0x00, 0x7e, 0xe1, 0x6f, 0x00, 0xe2, 0x61, 0x00, 0x6e, 0x04, 0x40,
- 0x09, 0x74, 0x00, 0x40, 0x07, 0x65, 0x00, 0x00, 0x07, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x09, 0xe3, 0x65, 0x00,
- 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x00, 0x06, 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00, 0x07, 0x40, 0x00,
- 0x65, 0x73, 0x00, 0xe5, 0x00, 0x00, 0x63, 0x02, 0x65, 0x0f, 0x6e, 0x15,
- 0x73, 0x1a, 0x00, 0x09, 0x40, 0x09, 0x68, 0x61, 0x6d, 0x61, 0x63, 0x61,
- 0x6c, 0x6c, 0x69, 0x74, 0x00, 0x40, 0x00, 0x76, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x6f, 0x74, 0x00, 0xe3, 0x68, 0x00, 0x69, 0x15, 0x6f, 0x19, 0xe2,
- 0x65, 0x00, 0x69, 0x08, 0x40, 0x00, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x00,
- 0x40, 0x00, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x40, 0x08, 0x74, 0x00,
- 0x40, 0x00, 0x65, 0x76, 0x65, 0x72, 0x00, 0xf8, 0x61, 0x00, 0x00, 0x65,
- 0x1c, 0x00, 0x6c, 0x8b, 0x00, 0x6e, 0x98, 0x00, 0x72, 0xb5, 0x00, 0x74,
- 0x2b, 0x01, 0x77, 0x50, 0x01, 0x79, 0x52, 0x01, 0xe2, 0x6c, 0x00, 0x74,
- 0x02, 0x00, 0x06, 0xe3, 0x00, 0x00, 0x67, 0x02, 0x6d, 0x08, 0x00, 0x14,
- 0x40, 0x00, 0x65, 0x72, 0x6d, 0x00, 0x40, 0x00, 0x65, 0x61, 0x6c, 0x00,
- 0xe4, 0x00, 0x00, 0x64, 0x02, 0x6c, 0x11, 0x7a, 0x4c, 0x00, 0x00, 0xe1,
- 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b,
- 0x00, 0x07, 0xe6, 0x00, 0x00, 0x62, 0x02, 0x63, 0x14, 0x68, 0x1b, 0x69,
- 0x22, 0x77, 0x26, 0x02, 0xd7, 0xe1, 0x61, 0x00, 0xe2, 0x72, 0x00, 0x73,
- 0x06, 0x40, 0x06, 0x72, 0x6f, 0x77, 0x00, 0x40, 0x06, 0x65, 0x00, 0x40,
- 0x06, 0x68, 0x61, 0x69, 0x72, 0x00, 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65,
- 0x00, 0x40, 0x06, 0x65, 0x00, 0x40, 0x09, 0x72, 0x69, 0x67, 0x68, 0x74,
- 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x11, 0x00, 0x5e, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x0c, 0xe3, 0x6b, 0x00, 0x6d, 0x02, 0x70, 0x04, 0x00, 0xb1,
- 0x00, 0x7a, 0x00, 0x2c, 0xe4, 0x00, 0x00, 0x63, 0x02, 0x65, 0x06, 0x73,
- 0x0c, 0x00, 0x09, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x76, 0x65, 0x72,
- 0x00, 0x40, 0x00, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00,
- 0x72, 0x6d, 0xeb, 0x00, 0x00, 0x61, 0x02, 0x62, 0x14, 0x66, 0x18, 0x69,
- 0x1e, 0x6f, 0x22, 0x73, 0x2b, 0x74, 0x33, 0x75, 0x37, 0x76, 0x3d, 0x77,
- 0x42, 0x00, 0x06, 0xe3, 0x62, 0x00, 0x73, 0x07, 0x74, 0x09, 0x40, 0x07,
- 0x6f, 0x75, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x79,
- 0x00, 0x40, 0x09, 0x6f, 0x72, 0x65, 0x00, 0x40, 0x00, 0x6e, 0x00, 0xe2,
- 0x66, 0x00, 0x6e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6f, 0x65,
- 0x76, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x70, 0x6f,
- 0x6e, 0x00, 0x40, 0x00, 0x65, 0x72, 0x00, 0xe1, 0x69, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x00, 0x40,
- 0x07, 0x6c, 0x00, 0x40, 0x06, 0x79, 0x00, 0xe4, 0x00, 0x00, 0x68, 0x02,
- 0x73, 0x07, 0x74, 0x0e, 0x00, 0x08, 0x40, 0x00, 0x65, 0x72, 0x00, 0x40,
- 0x06, 0x74, 0x6f, 0x6e, 0x65, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40,
- 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x07,
- 0xfa, 0x63, 0x00, 0x00, 0x66, 0x10, 0x00, 0x6c, 0x22, 0x00, 0x6d, 0x33,
- 0x00, 0x6e, 0x5d, 0x00, 0x70, 0x84, 0x00, 0x72, 0xdc, 0x00, 0x73, 0x19,
- 0x01, 0x74, 0x66, 0x01, 0x7a, 0x12, 0x02, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x00, 0x00, 0x40, 0x00, 0x76, 0x65, 0x72, 0x00, 0xe1,
- 0x66, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x2c, 0x40, 0x09, 0x65,
- 0x74, 0x72, 0x65, 0x65, 0x00, 0xe3, 0x65, 0x00, 0x6f, 0x02, 0x73, 0x06,
- 0x00, 0x5e, 0x40, 0x00, 0x6d, 0x00, 0x40, 0x00, 0x74, 0x00, 0xe3, 0x00,
- 0x00, 0x70, 0x02, 0x73, 0x07, 0x00, 0x09, 0x40, 0x55, 0x65, 0x72, 0x00,
- 0xe2, 0x69, 0x00, 0x79, 0x15, 0xe1, 0x63, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x3b, 0x40, 0x07, 0x74,
- 0x79, 0x00, 0x00, 0x06, 0xe4, 0x65, 0x00, 0x67, 0x09, 0x6e, 0x18, 0x79,
- 0x1c, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01, 0x4b, 0x40, 0x00, 0x6e, 0x67,
- 0x00, 0x40, 0xa1, 0x79, 0x00, 0x00, 0xf3, 0xe5, 0x00, 0x00, 0x63, 0x02,
- 0x6c, 0x08, 0x70, 0x0e, 0x73, 0x48, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x72,
- 0x64, 0x00, 0x40, 0x09, 0x61, 0x73, 0x68, 0x00, 0xe4, 0x65, 0x00, 0x69,
- 0x1b, 0x6c, 0x20, 0x6f, 0x28, 0xe3, 0x64, 0x00, 0x72, 0x02, 0x74, 0x12,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x09, 0x40, 0x09, 0x6e,
- 0x61, 0x70, 0x70, 0x65, 0x72, 0x00, 0x00, 0x09, 0x40, 0x06, 0x6e, 0x67,
- 0x00, 0x40, 0x06, 0x65, 0x74, 0x72, 0x65, 0x65, 0x00, 0x40, 0x09, 0x6f,
- 0x72, 0x77, 0x69, 0x6c, 0x6c, 0x00, 0x40, 0x55, 0x61, 0x77, 0x00, 0xe3,
- 0x00, 0x00, 0x6c, 0x02, 0x72, 0x28, 0x00, 0x09, 0xe5, 0x00, 0x00, 0x69,
- 0x02, 0x70, 0x08, 0x77, 0x0e, 0x79, 0x14, 0x00, 0x2c, 0x40, 0x09, 0x67,
- 0x69, 0x67, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6c, 0x00, 0x40, 0x09, 0x69,
- 0x6e, 0x64, 0x00, 0x40, 0x06, 0x62, 0x69, 0x72, 0x64, 0x00, 0xe2, 0x65,
- 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0xe3, 0x6b, 0x00, 0x70, 0x22, 0x74, 0x33, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x79, 0x12, 0x01, 0x5b, 0xe2, 0x72, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x73,
- 0x02, 0x00, 0x08, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00,
- 0x00, 0x6c, 0x02, 0x00, 0x07, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72,
- 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x68, 0x80,
- 0x69, 0x85, 0x74, 0x92, 0x05, 0x3c, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x63,
- 0x12, 0x66, 0x17, 0x68, 0x1d, 0x6e, 0x23, 0x6f, 0x3c, 0x70, 0x41, 0x74,
- 0x48, 0x77, 0x4e, 0x79, 0x65, 0x03, 0x39, 0xe2, 0x61, 0x00, 0x6f, 0x05,
- 0x40, 0x00, 0x69, 0x74, 0x00, 0x40, 0x08, 0x61, 0x72, 0x64, 0x00, 0x40,
- 0x06, 0x61, 0x70, 0x00, 0x40, 0x09, 0x69, 0x73, 0x68, 0x00, 0x40, 0x09,
- 0x65, 0x61, 0x64, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x0d, 0x05,
- 0x3d, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07, 0x73, 0x00,
- 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0x40, 0x09,
- 0x61, 0x70, 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x69, 0x6c, 0x00, 0xe1,
- 0x61, 0x00, 0xe3, 0x6c, 0x00, 0x73, 0x04, 0x74, 0x08, 0x40, 0x06, 0x6c,
- 0x00, 0x40, 0x47, 0x68, 0x00, 0x40, 0x07, 0x65, 0x72, 0x00, 0x00, 0x06,
- 0x40, 0x00, 0x65, 0x72, 0x00, 0xe2, 0x6e, 0x00, 0x73, 0x04, 0x40, 0x07,
- 0x67, 0x00, 0x40, 0x00, 0x68, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x3f, 0x00, 0x07, 0xe3, 0x00, 0x00,
- 0x6b, 0x02, 0x7a, 0x07, 0x00, 0x07, 0x40, 0x07, 0x69, 0x64, 0x00, 0xe3,
- 0x62, 0x00, 0x65, 0x06, 0x69, 0x0f, 0x40, 0x09, 0x61, 0x6e, 0x67, 0x00,
- 0xe2, 0x64, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x27, 0x02, 0x00, 0x61, 0x19, 0x00,
- 0x64, 0x1b, 0x00, 0x65, 0x22, 0x00, 0x6c, 0x28, 0x00, 0x6d, 0xb0, 0x00,
- 0x6f, 0xc7, 0x00, 0x70, 0xe0, 0x00, 0x72, 0xfa, 0x00, 0x73, 0x1d, 0x01,
- 0x00, 0x07, 0xe4, 0x64, 0x00, 0x6c, 0x02, 0x72, 0x06, 0x76, 0x0a, 0x00,
- 0x00, 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x65,
- 0x00, 0x00, 0x00, 0x40, 0x09, 0x75, 0x6e, 0x69, 0x74, 0x00, 0x40, 0x00,
- 0x76, 0x65, 0x72, 0x00, 0xe2, 0x65, 0x00, 0x6c, 0x7f, 0xe8, 0x00, 0x00,
- 0x66, 0x02, 0x67, 0x08, 0x68, 0x0f, 0x6d, 0x2e, 0x6e, 0x34, 0x73, 0x3a,
- 0x77, 0x67, 0x02, 0x7b, 0x40, 0x08, 0x6f, 0x6f, 0x64, 0x00, 0x40, 0x00,
- 0x72, 0x61, 0x69, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x72, 0x00, 0xe1, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x65, 0x61, 0x6c, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x61, 0x00, 0x6f, 0x0f, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe1, 0x6d, 0x00, 0xe1,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x06, 0x00, 0xdf, 0x40,
- 0x00, 0x79, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00, 0x68,
- 0x65, 0x61, 0x74, 0x00, 0x40, 0x00, 0x79, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x73, 0x08, 0x00, 0x00, 0x40, 0x00, 0x76, 0x65, 0x72, 0x00, 0x40,
- 0x00, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x00, 0xe2, 0x70, 0x00, 0x73, 0x10,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01, 0x5b, 0xe2, 0x65, 0x00, 0x72, 0x02,
- 0x00, 0x08, 0x00, 0x07, 0x40, 0x47, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x65,
- 0x00, 0x69, 0x15, 0x6c, 0x1a, 0xe3, 0x00, 0x00, 0x68, 0x02, 0x69, 0x09,
- 0x01, 0x25, 0x40, 0x09, 0x6f, 0x75, 0x73, 0x65, 0x00, 0x40, 0x00, 0x73,
- 0x68, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0x00, 0xb1, 0xe2, 0x65, 0x00,
- 0x6f, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x76, 0x65, 0x72, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x08, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02, 0x73, 0x06,
- 0x00, 0x07, 0x40, 0x00, 0x64, 0x00, 0x00, 0x00, 0xff, 0x63, 0x00, 0x00,
- 0x64, 0x2d, 0x00, 0x65, 0x9a, 0x00, 0x66, 0xba, 0x00, 0x67, 0xca, 0x00,
- 0x6b, 0x26, 0x01, 0x6c, 0x2a, 0x01, 0x6d, 0x0f, 0x02, 0x6e, 0x28, 0x02,
- 0x70, 0xfc, 0x04, 0x72, 0x08, 0x05, 0x73, 0x61, 0x05, 0x74, 0xdb, 0x05,
- 0x76, 0xd4, 0x06, 0x7a, 0xd8, 0x06, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00,
- 0x65, 0x02, 0x05, 0x3e, 0xe3, 0x64, 0x00, 0x72, 0x0d, 0x74, 0x1a, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x46, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x00, 0x00, 0x77, 0x02, 0x00, 0x07, 0x40, 0x07, 0x6f, 0x72, 0x6b,
- 0x00, 0x00, 0x06, 0xe4, 0x65, 0x00, 0x67, 0x3d, 0x6f, 0x42, 0x74, 0x58,
- 0xe4, 0x00, 0x00, 0x6d, 0x02, 0x6e, 0x0b, 0x73, 0x1d, 0x03, 0x3c, 0x40,
- 0x00, 0x6f, 0x75, 0x74, 0x68, 0x65, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0xd6, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x07, 0x40, 0x07,
- 0x73, 0x00, 0xe2, 0x63, 0x00, 0x70, 0x0b, 0x60, 0x09, 0x72, 0x65, 0x65,
- 0x6e, 0x00, 0x08, 0x00, 0xff, 0xff, 0x40, 0x00, 0x72, 0x65, 0x61, 0x64,
- 0x00, 0x40, 0x08, 0x65, 0x74, 0x00, 0xe1, 0x77, 0x00, 0xe3, 0x00, 0x00,
- 0x65, 0x02, 0x68, 0x06, 0x01, 0x5b, 0x40, 0x07, 0x72, 0x00, 0x40, 0x07,
- 0x6f, 0x6f, 0x64, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02,
- 0x00, 0x07, 0x00, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x0e, 0xe1, 0x64, 0x00,
- 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xd6, 0x40, 0x07, 0x72, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x04, 0x40, 0x06, 0x72, 0x00, 0x40, 0x06, 0x65, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02, 0x00, 0x12, 0x40, 0x00,
- 0x65, 0x73, 0x73, 0x00, 0xe6, 0x00, 0x00, 0x65, 0x02, 0x67, 0x07, 0x68,
- 0x27, 0x6c, 0x2b, 0x77, 0x30, 0x00, 0x06, 0x40, 0x07, 0x6f, 0x6e, 0x00,
- 0xe3, 0x65, 0x00, 0x69, 0x04, 0x6c, 0x09, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x60, 0x40, 0x06, 0x74, 0x00,
- 0x40, 0x06, 0x65, 0x74, 0x00, 0xe1, 0x61, 0x00, 0xe2, 0x67, 0x00, 0x6d,
- 0x15, 0xe2, 0x00, 0x00, 0x67, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x06,
- 0x40, 0x09, 0x69, 0x00, 0xe6, 0x64, 0x00, 0x65, 0x74, 0x69, 0x76, 0x6c,
- 0x7d, 0x74, 0xd4, 0x79, 0xd6, 0xe7, 0x00, 0x00, 0x63, 0x02, 0x65, 0x2c,
- 0x66, 0x3f, 0x6c, 0x57, 0x6e, 0x5d, 0x73, 0x63, 0x05, 0x3f, 0xe1, 0x61,
- 0x00, 0xe2, 0x72, 0x00, 0x74, 0x08, 0x60, 0x09, 0x64, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xe2, 0x00, 0x00, 0x74, 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00,
- 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x62, 0x00, 0x72, 0x07, 0x40, 0x09, 0x65,
- 0x65, 0x73, 0x74, 0x00, 0x40, 0x09, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe3,
- 0x69, 0x00, 0x6c, 0x05, 0x6f, 0x0c, 0x40, 0x09, 0x72, 0x65, 0x00, 0x40,
- 0x06, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x40, 0x07, 0x77, 0x6c, 0x00, 0x40,
- 0x07, 0x69, 0x66, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0x00, 0x82, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe6, 0x00,
- 0x00, 0x66, 0x02, 0x69, 0x15, 0x6f, 0x35, 0x70, 0x41, 0x79, 0x48, 0x00,
- 0xb2, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x65, 0x00, 0x6e,
- 0x04, 0x77, 0x14, 0x40, 0x07, 0x73, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x02, 0xb1, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x09, 0x61, 0x77, 0x00, 0xe1, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02,
- 0x00, 0x06, 0x00, 0x00, 0x40, 0x07, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x00,
- 0x08, 0x00, 0x47, 0x00, 0xf4, 0xe1, 0x70, 0x00, 0xe4, 0x00, 0x00, 0x69,
- 0x02, 0x6c, 0x07, 0x79, 0x0b, 0x00, 0x47, 0x40, 0x00, 0x73, 0x68, 0x00,
- 0x40, 0x5e, 0x65, 0x00, 0x00, 0xf3, 0xfb, 0x00, 0x00, 0x00, 0x63, 0x02,
- 0x00, 0x64, 0x0b, 0x00, 0x65, 0xd0, 0x01, 0x67, 0xf8, 0x01, 0x6b, 0x38,
- 0x02, 0x6e, 0x49, 0x02, 0x6f, 0x6f, 0x02, 0x73, 0x71, 0x02, 0x74, 0x87,
- 0x02, 0x79, 0xb0, 0x02, 0x00, 0x93, 0xe2, 0x65, 0x00, 0x68, 0x02, 0x00,
- 0x5e, 0x00, 0x47, 0xc1, 0x27, 0x53, 0xab, 0x00, 0xad, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0xdd, 0x00, 0x00, 0x00,
- 0xf1, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x23, 0x01,
- 0x00, 0x00, 0x2b, 0x01, 0x3a, 0x01, 0x00, 0x00, 0x40, 0x01, 0x60, 0x01,
- 0x00, 0x00, 0x70, 0x01, 0x75, 0x01, 0x00, 0x00, 0xb9, 0x01, 0x00, 0x00,
- 0xbd, 0x01, 0x00, 0x00, 0xc3, 0x01, 0x05, 0x40, 0x40, 0x00, 0x73, 0x00,
- 0xe4, 0x61, 0x00, 0x6c, 0x04, 0x72, 0x0a, 0x75, 0x1e, 0x40, 0x06, 0x67,
- 0x00, 0x40, 0x00, 0x6f, 0x77, 0x6e, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61,
- 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x0f, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x20, 0x72, 0x6e, 0x00, 0xe1, 0x68, 0x00, 0xe2,
- 0x65, 0x00, 0x69, 0x07, 0x40, 0x08, 0x61, 0x74, 0x65, 0x72, 0x00, 0x40,
- 0x07, 0x6c, 0x6c, 0x00, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00,
- 0x06, 0xe2, 0x61, 0x00, 0x6c, 0x05, 0x40, 0x09, 0x6c, 0x6c, 0x00, 0x40,
- 0x09, 0x6f, 0x77, 0x65, 0x72, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x04, 0x40,
- 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73,
- 0x00, 0x40, 0x00, 0x27, 0x73, 0x00, 0x40, 0x06, 0x61, 0x6d, 0x6d, 0x65,
- 0x72, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x05, 0x40, 0x09, 0x73, 0x73, 0x00,
- 0x40, 0x00, 0x73, 0x73, 0x00, 0x40, 0x55, 0x69, 0x6c, 0x6c, 0x00, 0xe1,
- 0x77, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x70, 0x08, 0x73, 0x0e, 0x00,
- 0x2c, 0x40, 0x00, 0x65, 0x73, 0x73, 0x00, 0x40, 0x06, 0x61, 0x6e, 0x65,
- 0x00, 0x40, 0x06, 0x69, 0x6c, 0x6c, 0x00, 0xe2, 0x69, 0x00, 0x72, 0x05,
- 0x40, 0x09, 0x70, 0x65, 0x00, 0x40, 0x00, 0x6f, 0x6f, 0x66, 0x00, 0x40,
- 0x06, 0x6f, 0x77, 0x00, 0xe6, 0x63, 0x00, 0x68, 0x07, 0x6f, 0x0e, 0x74,
- 0x13, 0x75, 0x19, 0x77, 0x31, 0x40, 0x06, 0x72, 0x65, 0x65, 0x6e, 0x00,
- 0x40, 0x06, 0x69, 0x65, 0x6c, 0x64, 0x00, 0x40, 0x09, 0x63, 0x6b, 0x00,
- 0x40, 0x09, 0x6f, 0x72, 0x6d, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x66, 0x00,
- 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x00, 0x3f, 0x40, 0x07, 0x72,
- 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x65, 0x70, 0x74, 0x00,
- 0x40, 0x06, 0x70, 0x00, 0x40, 0x07, 0x61, 0x72, 0x64, 0x00, 0x00, 0xf4,
- 0xe4, 0x00, 0x00, 0x67, 0x02, 0x6d, 0x14, 0x72, 0x1b, 0x00, 0x09, 0xe2,
- 0x6c, 0x00, 0x72, 0x06, 0x40, 0x09, 0x61, 0x73, 0x73, 0x00, 0x40, 0x09,
- 0x6f, 0x77, 0x65, 0x72, 0x00, 0x40, 0x09, 0x61, 0x6b, 0x65, 0x72, 0x00,
- 0x40, 0x06, 0x79, 0x00, 0xe6, 0x00, 0x00, 0x64, 0x02, 0x6c, 0x08, 0x6e,
- 0x17, 0x73, 0x1c, 0x74, 0x2e, 0x03, 0xa2, 0x40, 0x09, 0x69, 0x6e, 0x67,
- 0x00, 0xe2, 0x65, 0x00, 0x69, 0x05, 0x40, 0x00, 0x73, 0x73, 0x00, 0x40,
- 0x00, 0x6b, 0x65, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0xe1, 0x70, 0x00,
- 0xe2, 0x61, 0x00, 0x72, 0x04, 0x40, 0x09, 0x6e, 0x00, 0x40, 0x06, 0x65,
- 0x61, 0x64, 0x00, 0x40, 0x06, 0x69, 0x70, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6c, 0x06, 0x00, 0xe7, 0x40, 0x07, 0x72, 0x00, 0x40, 0x5e, 0x65,
- 0x00, 0xe4, 0x61, 0x00, 0x65, 0x06, 0x69, 0x0a, 0x6f, 0x0f, 0x40, 0x37,
- 0x62, 0x6c, 0x65, 0x00, 0x40, 0x06, 0x72, 0x00, 0x40, 0x86, 0x6e, 0x67,
- 0x00, 0xe1, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x48, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0x09, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe1,
- 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x03, 0x3c, 0x40, 0x07, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x20, 0xe1, 0x72, 0x00, 0xe4,
- 0x00, 0x00, 0x67, 0x02, 0x69, 0x09, 0x74, 0x0e, 0x00, 0x95, 0x40, 0x07,
- 0x72, 0x65, 0x65, 0x6e, 0x00, 0x40, 0x0b, 0x7a, 0x65, 0x00, 0x40, 0x07,
- 0x69, 0x6d, 0x65, 0x00, 0x40, 0x60, 0x79, 0x00, 0x00, 0xf3, 0xe1, 0x65,
- 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0xe3, 0x65,
- 0x00, 0x69, 0x41, 0x79, 0x50, 0xe6, 0x00, 0x00, 0x27, 0x02, 0x64, 0x06,
- 0x68, 0x08, 0x6c, 0x0e, 0x74, 0x14, 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00,
- 0x00, 0x08, 0x40, 0x09, 0x61, 0x69, 0x72, 0x00, 0x40, 0x09, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x70, 0x00, 0xe2, 0x00, 0x00, 0x70,
- 0x02, 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x64, 0x00, 0x72,
- 0x02, 0x00, 0x00, 0x00, 0x06, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6e,
- 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00,
- 0x07, 0x00, 0xf4, 0xe5, 0x64, 0x00, 0x65, 0x05, 0x68, 0x22, 0x70, 0x44,
- 0x74, 0x4d, 0x40, 0x07, 0x6f, 0x6d, 0x00, 0xe4, 0x00, 0x00, 0x61, 0x02,
- 0x63, 0x08, 0x67, 0x0f, 0x05, 0x41, 0x40, 0x06, 0x63, 0x72, 0x65, 0x00,
- 0x40, 0x47, 0x72, 0x61, 0x63, 0x6b, 0x00, 0x40, 0x08, 0x75, 0x79, 0x00,
- 0xe5, 0x00, 0x00, 0x62, 0x02, 0x65, 0x08, 0x66, 0x0c, 0x6c, 0x11, 0x00,
- 0xe7, 0x40, 0x06, 0x6f, 0x6e, 0x65, 0x00, 0x40, 0x07, 0x72, 0x00, 0x40,
- 0x3b, 0x75, 0x6c, 0x00, 0x40, 0x06, 0x69, 0x73, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x09, 0x00, 0xf3, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x66, 0x08, 0x00, 0x00, 0x40, 0x06, 0x72, 0x69, 0x61, 0x00, 0xe1, 0x75,
- 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0xe7, 0x00, 0x00, 0x63, 0x02, 0x68, 0x1a,
- 0x6c, 0x9d, 0x6e, 0xb3, 0x73, 0xb9, 0x74, 0xbb, 0x00, 0x06, 0xe1, 0x68,
- 0x00, 0xe3, 0x00, 0x00, 0x63, 0x02, 0x65, 0x09, 0x00, 0x47, 0x40, 0x07,
- 0x72, 0x61, 0x66, 0x74, 0x00, 0x40, 0x07, 0x72, 0x79, 0x00, 0xe8, 0x00,
- 0x00, 0x61, 0x02, 0x64, 0x06, 0x65, 0x24, 0x68, 0x3b, 0x69, 0x57, 0x6f,
- 0x5b, 0x73, 0x60, 0x00, 0x00, 0x40, 0x00, 0x6c, 0x00, 0xe1, 0x72, 0x00,
- 0xe2, 0x61, 0x00, 0x65, 0x12, 0xe1, 0x77, 0x00, 0xe3, 0x00, 0x00, 0x61,
- 0x02, 0x6e, 0x06, 0x01, 0x21, 0x40, 0x09, 0x6c, 0x00, 0x00, 0x00, 0x40,
- 0x00, 0x77, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x7e, 0xe3, 0x00,
- 0x00, 0x69, 0x02, 0x73, 0x07, 0x04, 0x9e, 0x40, 0x3b, 0x6e, 0x67, 0x00,
- 0x00, 0x07, 0xe2, 0x65, 0x00, 0x6f, 0x05, 0x40, 0x00, 0x6c, 0x64, 0x00,
- 0xe1, 0x6c, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x01,
- 0x21, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00,
- 0x75, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x05, 0x40,
- 0x3c, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x6f, 0x64, 0x00, 0xe1, 0x65, 0x00,
- 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x47, 0x65, 0x73, 0x73,
- 0x00, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79, 0x26, 0xe2, 0x64,
- 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x5b, 0xe3, 0x63, 0x00, 0x6c, 0x06,
- 0x6e, 0x0a, 0x40, 0x06, 0x69, 0x73, 0x6d, 0x00, 0x40, 0x00, 0x79, 0x00,
- 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40, 0x07, 0x73, 0x73, 0x00, 0x00, 0x36,
- 0x01, 0x15, 0x40, 0x0b, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x65,
- 0x13, 0x00, 0x00, 0xe1, 0x72, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00,
- 0x72, 0x02, 0x00, 0x56, 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x6e, 0x65,
- 0x64, 0x00, 0x00, 0x3b, 0xc0, 0x61, 0x17, 0x31, 0x00, 0x35, 0x00, 0x00,
- 0x00, 0x4d, 0x00, 0x52, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x88, 0x00, 0x91, 0x00, 0xc6, 0x00, 0x41, 0x01, 0xa5,
- 0x01, 0x23, 0x03, 0x00, 0x00, 0x25, 0x03, 0x00, 0x00, 0x6c, 0x06, 0x78,
- 0x06, 0x9d, 0x06, 0xa9, 0x06, 0x40, 0x07, 0x64, 0x00, 0xe1, 0x62, 0x00,
- 0xe1, 0x6c, 0x00, 0xe3, 0x65, 0x00, 0x69, 0x02, 0x79, 0x09, 0x00, 0x82,
- 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x00, 0xf4, 0x40, 0x08, 0x67,
- 0x65, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x66, 0x0a, 0x00, 0x06, 0x40,
- 0x00, 0x65, 0x67, 0x6f, 0x6e, 0x65, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe3, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x10, 0x00, 0x3e, 0xe1, 0x65,
- 0x00, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00, 0x40, 0x00, 0x74, 0x00,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x08, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x26, 0x00, 0x00, 0xe3, 0x64, 0x00, 0x66, 0x02, 0x76, 0x1e,
- 0x00, 0x09, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x69, 0x09, 0x72, 0x0e, 0x00,
- 0x47, 0x40, 0x06, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x73, 0x68,
- 0x00, 0x40, 0x07, 0x61, 0x6d, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x72, 0x00,
- 0x73, 0x06, 0x40, 0x06, 0x69, 0x6e, 0x65, 0x00, 0x00, 0x00, 0xe3, 0x61,
- 0x00, 0x62, 0x47, 0x65, 0x58, 0xe1, 0x6e, 0x00, 0xe5, 0x00, 0x00, 0x68,
- 0x02, 0x69, 0x08, 0x6b, 0x1d, 0x6c, 0x23, 0x00, 0x07, 0x40, 0x07, 0x6f,
- 0x6f, 0x64, 0x00, 0xe2, 0x73, 0x00, 0x7a, 0x04, 0x40, 0x00, 0x68, 0x00,
- 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x01, 0x4b, 0x00, 0x07,
- 0x40, 0x07, 0x69, 0x6e, 0x64, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2,
- 0x6b, 0x00, 0x6e, 0x04, 0x40, 0x07, 0x65, 0x00, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0x01, 0x15, 0xe3, 0x00, 0x00, 0x61, 0x02, 0x6c, 0x06, 0x00,
- 0x09, 0x40, 0x09, 0x74, 0x00, 0x40, 0x08, 0x65, 0x00, 0xe1, 0x6e, 0x00,
- 0xe2, 0x00, 0x00, 0x66, 0x02, 0x00, 0x07, 0xe1, 0x6f, 0x00, 0xe1, 0x6c,
- 0x00, 0xe1, 0x6b, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00,
- 0x07, 0xe5, 0x00, 0x00, 0x27, 0x02, 0x64, 0x06, 0x6b, 0x45, 0x74, 0x4e,
- 0x00, 0x07, 0x40, 0x00, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x72, 0x34, 0xe1,
- 0x72, 0x00, 0xe5, 0x00, 0x00, 0x66, 0x02, 0x69, 0x15, 0x6c, 0x1a, 0x6d,
- 0x20, 0x01, 0x22, 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x3b,
- 0x6e, 0x67, 0x00, 0x40, 0x09, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x07, 0x65,
- 0x6e, 0x74, 0x00, 0x40, 0x3b, 0x6f, 0x75, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x79, 0x02, 0x00, 0x09, 0x00, 0x60, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00,
- 0x20, 0x40, 0x37, 0x64, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x64, 0x02, 0x00,
- 0x65, 0x15, 0x01, 0x66, 0x19, 0x01, 0x6c, 0x24, 0x01, 0x7a, 0x55, 0x01,
- 0x01, 0x27, 0xeb, 0x00, 0x00, 0x62, 0x02, 0x63, 0x12, 0x65, 0x5a, 0x69,
- 0x6a, 0x6c, 0x71, 0x6d, 0x8e, 0x70, 0x9b, 0x73, 0xac, 0x77, 0xd4, 0x79,
- 0xfa, 0x00, 0xcb, 0xe2, 0x69, 0x00, 0x6c, 0x05, 0x40, 0x07, 0x6e, 0x65,
- 0x00, 0x40, 0x09, 0x6f, 0x63, 0x6b, 0x00, 0xe5, 0x61, 0x00, 0x68, 0x14,
- 0x6f, 0x1a, 0x72, 0x1f, 0x75, 0x25, 0xe1, 0x72, 0x00, 0xe1, 0x76, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x09, 0x72, 0x00, 0x40, 0x06, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x75, 0x63, 0x6b, 0x00, 0x40, 0x06, 0x63, 0x6b,
- 0x00, 0x40, 0x07, 0x61, 0x66, 0x74, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00,
- 0x00, 0x74, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x6e, 0x02, 0x01, 0xb4, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x05, 0x6f,
- 0x0a, 0x40, 0x06, 0x6e, 0x64, 0x00, 0x40, 0x00, 0x63, 0x65, 0x00, 0xe2,
- 0x74, 0x00, 0x75, 0x02, 0x00, 0x06, 0x40, 0x00, 0x73, 0x65, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00,
- 0xe2, 0x65, 0x00, 0x69, 0x07, 0x40, 0x09, 0x63, 0x6b, 0x65, 0x72, 0x00,
- 0x40, 0x06, 0x6c, 0x65, 0x00, 0xe5, 0x00, 0x00, 0x68, 0x02, 0x69, 0x07,
- 0x6d, 0x0e, 0x79, 0x1b, 0x00, 0x07, 0x40, 0x06, 0x65, 0x64, 0x00, 0x40,
- 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40,
- 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0xf4, 0xe2, 0x69, 0x00,
- 0x6f, 0x05, 0x40, 0x09, 0x6e, 0x64, 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x6b,
- 0x00, 0x6d, 0x12, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x69, 0x06, 0x03, 0x42,
- 0x40, 0x07, 0x72, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x00, 0x08, 0x02,
- 0xff, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7,
- 0x40, 0x07, 0x72, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x67, 0x06, 0x69,
- 0x11, 0x6c, 0x18, 0x00, 0x1e, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x07, 0x61,
- 0x74, 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65,
- 0x73, 0x73, 0x00, 0x03, 0x35, 0xe2, 0x69, 0x00, 0x79, 0x0f, 0xe2, 0x6c,
- 0x00, 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73,
- 0x00, 0x01, 0x3b, 0x01, 0xa2, 0xf9, 0x64, 0x00, 0x00, 0x65, 0x5c, 0x00,
- 0x6b, 0x5e, 0x00, 0x6c, 0x27, 0x02, 0x6d, 0x57, 0x02, 0x6e, 0x70, 0x02,
- 0x72, 0x72, 0x02, 0x73, 0xa7, 0x02, 0x74, 0xda, 0x02, 0xe9, 0x00, 0x00,
- 0x27, 0x02, 0x61, 0x06, 0x62, 0x0b, 0x69, 0x11, 0x6c, 0x26, 0x70, 0x2c,
- 0x73, 0x32, 0x79, 0x47, 0x00, 0xab, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07,
- 0x67, 0x65, 0x00, 0x40, 0x06, 0x6f, 0x6f, 0x6b, 0x00, 0xe2, 0x6c, 0x00,
- 0x6e, 0x04, 0x40, 0x00, 0x79, 0x00, 0xe2, 0x65, 0x00, 0x67, 0x05, 0x40,
- 0x07, 0x73, 0x73, 0x00, 0x00, 0x06, 0x40, 0x3b, 0x65, 0x73, 0x73, 0x00,
- 0x40, 0x07, 0x6c, 0x61, 0x79, 0x00, 0xe1, 0x6d, 0x00, 0xe1, 0x69, 0x00,
- 0xe1, 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x92, 0x00, 0x00, 0xc1, 0x27, 0x51, 0xa7, 0x00,
- 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0xce, 0x00,
- 0x00, 0x00, 0xe7, 0x00, 0xec, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x07, 0x01,
- 0x19, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x01, 0x54, 0x01, 0x00, 0x00,
- 0x7b, 0x01, 0x80, 0x01, 0x00, 0x00, 0x87, 0x01, 0x8d, 0x01, 0xb0, 0x01,
- 0xbf, 0x01, 0x00, 0x00, 0xc3, 0x01, 0x05, 0x42, 0x40, 0x00, 0x73, 0x00,
- 0xe4, 0x62, 0x00, 0x64, 0x05, 0x68, 0x0a, 0x72, 0x11, 0x40, 0x37, 0x6c,
- 0x65, 0x00, 0x40, 0x00, 0x61, 0x79, 0x00, 0x40, 0x06, 0x6f, 0x6c, 0x69,
- 0x63, 0x00, 0x40, 0x08, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe3, 0x61, 0x00,
- 0x65, 0x07, 0x6f, 0x0d, 0x40, 0x08, 0x73, 0x6b, 0x65, 0x74, 0x00, 0x40,
- 0x09, 0x6e, 0x63, 0x68, 0x00, 0x40, 0x09, 0x6f, 0x6b, 0x00, 0x40, 0x06,
- 0x61, 0x79, 0x00, 0x40, 0x09, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x6c, 0x05,
- 0x6f, 0x0a, 0x40, 0x07, 0x72, 0x65, 0x00, 0x40, 0x09, 0x6f, 0x77, 0x00,
- 0x40, 0x07, 0x72, 0x63, 0x65, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x72, 0x00,
- 0x75, 0x05, 0x40, 0x06, 0x73, 0x65, 0x00, 0x40, 0x06, 0x73, 0x65, 0x00,
- 0xe1, 0x6e, 0x00, 0xe1, 0x67, 0x00, 0xe4, 0x27, 0x00, 0x6d, 0x04, 0x73,
- 0x11, 0x77, 0x13, 0x40, 0x00, 0x73, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x00, 0x07, 0xe1, 0x6f,
- 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e,
- 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x09, 0x6f, 0x61, 0x64, 0x00, 0xe2,
- 0x61, 0x00, 0x65, 0x1e, 0xe2, 0x6e, 0x00, 0x74, 0x15, 0xe3, 0x00, 0x00,
- 0x6c, 0x02, 0x73, 0x08, 0x00, 0x07, 0x40, 0x00, 0x69, 0x6b, 0x65, 0x00,
- 0x40, 0x07, 0x68, 0x69, 0x70, 0x00, 0x40, 0x08, 0x65, 0x00, 0x40, 0x00,
- 0x6e, 0x00, 0x40, 0x06, 0x75, 0x74, 0x00, 0x40, 0x09, 0x6c, 0x61, 0x63,
- 0x65, 0x00, 0x40, 0x09, 0x6f, 0x6f, 0x6d, 0x00, 0xe3, 0x00, 0x00, 0x68,
- 0x02, 0x74, 0x14, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x6f, 0x05, 0x79, 0x09,
- 0x40, 0x09, 0x65, 0x74, 0x00, 0x40, 0x09, 0x70, 0x00, 0x00, 0x00, 0x40,
- 0x09, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0xe2, 0x61, 0x00, 0x6f, 0x06,
- 0x40, 0x09, 0x62, 0x6c, 0x65, 0x00, 0x40, 0x08, 0x70, 0x00, 0x40, 0x09,
- 0x70, 0x00, 0x40, 0x06, 0x65, 0x65, 0x6b, 0x00, 0xe1, 0x64, 0x00, 0xe4,
- 0x00, 0x00, 0x6c, 0x02, 0x76, 0x18, 0x77, 0x1e, 0x00, 0x06, 0xe2, 0x69,
- 0x00, 0x79, 0x0f, 0xe2, 0x65, 0x00, 0x6e, 0x04, 0x40, 0x00, 0x72, 0x00,
- 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00, 0x05, 0x43, 0x40, 0x06, 0x69, 0x65,
- 0x77, 0x00, 0x40, 0x00, 0x69, 0x64, 0x65, 0x00, 0xe4, 0x00, 0x00, 0x68,
- 0x02, 0x77, 0x08, 0x79, 0x0e, 0x00, 0x47, 0x40, 0x09, 0x6f, 0x6c, 0x65,
- 0x00, 0x40, 0x07, 0x6f, 0x6f, 0x64, 0x00, 0x00, 0x60, 0x00, 0x37, 0xe2,
- 0x69, 0x00, 0x79, 0x1c, 0xe3, 0x65, 0x00, 0x6d, 0x09, 0x73, 0x0f, 0xe2,
- 0x64, 0x00, 0x72, 0x02, 0x00, 0x3b, 0x00, 0x07, 0x40, 0x07, 0x65, 0x6e,
- 0x74, 0x00, 0x40, 0x00, 0x6f, 0x6d, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x69,
- 0x02, 0x77, 0x07, 0x05, 0x44, 0x40, 0x3b, 0x6e, 0x67, 0x00, 0x40, 0x06,
- 0x61, 0x72, 0x74, 0x00, 0xe3, 0x65, 0x00, 0x68, 0x09, 0x74, 0x21, 0xe2,
- 0x00, 0x00, 0x6e, 0x02, 0x00, 0x07, 0x00, 0x3a, 0xe1, 0x69, 0x00, 0xe1,
- 0x70, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x66, 0x06, 0x01, 0x05, 0x40,
- 0x07, 0x72, 0x00, 0x40, 0x00, 0x75, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x00, 0x93, 0x40, 0x07, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0x07, 0xe5, 0x00, 0x00, 0x69, 0x02, 0x6c, 0x17, 0x77, 0x2d, 0x79,
- 0x34, 0x00, 0x07, 0xe3, 0x65, 0x00, 0x6c, 0x04, 0x6e, 0x08, 0x40, 0x00,
- 0x73, 0x00, 0x40, 0x37, 0x79, 0x00, 0x40, 0xdb, 0x65, 0x73, 0x73, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x73, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00,
- 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x00,
- 0x68, 0x69, 0x6c, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02, 0x03, 0x99,
- 0x40, 0x00, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x00, 0x40,
- 0x00, 0x68, 0x61, 0x00, 0xe2, 0x6c, 0x00, 0x6e, 0x1c, 0xe1, 0x64, 0x00,
- 0xe4, 0x00, 0x00, 0x27, 0x02, 0x6e, 0x07, 0x73, 0x0c, 0x00, 0x08, 0x40,
- 0x00, 0x76, 0x65, 0x00, 0x40, 0x00, 0x27, 0x74, 0x00, 0x40, 0x00, 0x74,
- 0x00, 0x40, 0xf7, 0x64, 0x00, 0xe1, 0x65, 0x00, 0xe2, 0x00, 0x00, 0x6e,
- 0x02, 0x00, 0x77, 0x01, 0xca, 0x00, 0x93, 0x40, 0x00, 0x6d, 0x00, 0xf6,
- 0x61, 0x00, 0x00, 0x65, 0x70, 0x00, 0x69, 0xec, 0x00, 0x6f, 0x71, 0x01,
- 0x75, 0xdd, 0x01, 0x79, 0xe2, 0x01, 0xe6, 0x63, 0x00, 0x69, 0x04, 0x6e,
- 0x13, 0x70, 0x25, 0x73, 0x4f, 0x74, 0x54, 0x40, 0x95, 0x6b, 0x00, 0xe1,
- 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe1, 0x67, 0x00, 0xe1, 0x6c, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x72, 0x02, 0x03, 0x19, 0x00, 0x07, 0xe4, 0x00, 0x00, 0x27,
- 0x02, 0x61, 0x06, 0x70, 0x0e, 0x01, 0x43, 0x40, 0x00, 0x73, 0x00, 0x40,
- 0x06, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x37, 0x00, 0x06, 0x40, 0x09, 0x6e,
- 0x67, 0x00, 0x40, 0x09, 0x73, 0x65, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00,
- 0x00, 0x66, 0x02, 0x00, 0x07, 0x40, 0x3b, 0x75, 0x6c, 0x00, 0xe5, 0x61,
- 0x00, 0x63, 0x17, 0x6e, 0x2c, 0x73, 0x37, 0x74, 0x54, 0xe2, 0x6b, 0x00,
- 0x74, 0x02, 0x00, 0x5b, 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02,
- 0x73, 0x04, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x6b, 0x00, 0xe3,
- 0x00, 0x00, 0x61, 0x02, 0x65, 0x07, 0x00, 0xfa, 0x40, 0x07, 0x67, 0x65,
- 0x00, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x09,
- 0x40, 0x47, 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x6c, 0x02,
- 0x00, 0x93, 0xe2, 0x65, 0x00, 0x69, 0x09, 0xe2, 0x00, 0x00, 0x72, 0x02,
- 0x00, 0xa5, 0x00, 0x07, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe1, 0x63, 0x00,
- 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0x09, 0xe1, 0x64,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x46, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe4, 0x67, 0x00, 0x6e, 0x1c, 0x73, 0x3f, 0x74, 0x58, 0xe2,
- 0x67, 0x00, 0x68, 0x13, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x79, 0x09,
- 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0xa5, 0x00, 0x07, 0x00, 0x00, 0x40,
- 0x09, 0x74, 0x00, 0xe2, 0x67, 0x00, 0x6b, 0x0b, 0xe2, 0x00, 0x00, 0x65,
- 0x02, 0x01, 0x37, 0x40, 0x07, 0x72, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65,
- 0x00, 0x79, 0x09, 0xe2, 0x00, 0x00, 0x64, 0x02, 0x00, 0x82, 0x00, 0x37,
- 0x01, 0x72, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x62, 0x02, 0x77, 0x08,
- 0x00, 0x06, 0x40, 0x09, 0x61, 0x6e, 0x64, 0x00, 0x40, 0x09, 0x61, 0x74,
- 0x63, 0x68, 0x00, 0xe5, 0x00, 0x00, 0x65, 0x02, 0x68, 0x0b, 0x69, 0x0f,
- 0x74, 0x14, 0x05, 0x39, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x08, 0x00,
- 0x07, 0x40, 0x82, 0x65, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x41, 0xca,
- 0x65, 0x6e, 0x00, 0xe3, 0x6e, 0x00, 0x74, 0x56, 0x75, 0x5f, 0xe1, 0x67,
- 0x00, 0xe5, 0x00, 0x00, 0x64, 0x02, 0x66, 0x13, 0x68, 0x26, 0x6e, 0x42,
- 0x05, 0x45, 0xe1, 0x6f, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x06,
- 0x72, 0x00, 0x40, 0x06, 0x6e, 0x67, 0x00, 0xe1, 0x75, 0x00, 0xe1, 0x6c,
- 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x4d, 0x40, 0x07, 0x65, 0x73,
- 0x73, 0x00, 0xe1, 0x65, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x64, 0x00, 0xe1,
- 0x65, 0x00, 0xe1, 0x64, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e,
- 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00,
- 0xe2, 0x65, 0x00, 0x68, 0x02, 0x00, 0x77, 0x00, 0x00, 0x40, 0x00, 0x67,
- 0x68, 0x74, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x6e, 0x0d, 0x00, 0x3b, 0xe2, 0x72, 0x00, 0x73, 0x02, 0x00, 0x00,
- 0x40, 0x00, 0x74, 0x00, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00,
- 0xe3, 0x6e, 0x00, 0x72, 0x0a, 0x73, 0x0f, 0x40, 0x08, 0x64, 0x65, 0x72,
- 0x6b, 0x69, 0x6e, 0x64, 0x00, 0x40, 0x06, 0x73, 0x74, 0x00, 0xe1, 0x73,
- 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x09, 0x01, 0x64, 0xfa, 0x00,
- 0x00, 0x00, 0x63, 0x02, 0x00, 0x65, 0x24, 0x00, 0x69, 0x6d, 0x00, 0x6f,
- 0x85, 0x00, 0x72, 0x89, 0x00, 0x74, 0x8e, 0x00, 0x76, 0x94, 0x00, 0x78,
- 0xab, 0x00, 0x79, 0x1d, 0x01, 0x00, 0x00, 0xe2, 0x69, 0x00, 0x76, 0x11,
- 0xe4, 0x00, 0x00, 0x69, 0x02, 0x76, 0x04, 0x78, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x69, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x6e, 0x00, 0x72, 0x23, 0xe1, 0x6f,
- 0x00, 0xe2, 0x6e, 0x00, 0x70, 0x02, 0x00, 0x07, 0xe1, 0x68, 0x00, 0xe1,
- 0x6f, 0x00, 0xe1, 0x62, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x09,
- 0xe2, 0x61, 0x00, 0x63, 0x02, 0x00, 0x07, 0x00, 0x00, 0xe1, 0x6f, 0x00,
- 0xe2, 0x67, 0x00, 0x78, 0x17, 0xe1, 0x72, 0x00, 0xe1, 0x61, 0x00, 0xe1,
- 0x70, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x04, 0x40, 0x00,
- 0x63, 0x00, 0x00, 0x07, 0x00, 0x47, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x76,
- 0x0b, 0x78, 0x0d, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x72, 0x00, 0x40, 0x08,
- 0x65, 0x66, 0x00, 0x40, 0x07, 0x65, 0x72, 0x6d, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe2,
- 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x69,
- 0x02, 0x76, 0x1a, 0x78, 0x31, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02,
- 0x76, 0x0b, 0x78, 0x0d, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x69, 0x02, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x76,
- 0x1a, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x69, 0x02, 0x76, 0x0b, 0x78, 0x0d,
- 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0xe2, 0x00,
- 0x00, 0x69, 0x02, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x65, 0x00, 0x6f, 0x0b, 0xe2, 0x6d,
- 0x00, 0x6e, 0x02, 0x00, 0x07, 0x40, 0x00, 0x65, 0x00, 0xe1, 0x70, 0x00,
- 0xe1, 0x68, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x65, 0x00,
- 0x69, 0x02, 0x00, 0x06, 0x40, 0x09, 0x73, 0x74, 0x00, 0xfa, 0x00, 0x00,
- 0x00, 0x27, 0x02, 0x00, 0x61, 0x08, 0x00, 0x64, 0x15, 0x01, 0x65, 0x17,
- 0x01, 0x69, 0x13, 0x02, 0x6f, 0x4a, 0x02, 0x72, 0x3e, 0x03, 0x74, 0x40,
- 0x03, 0x75, 0x56, 0x03, 0x02, 0xcb, 0x40, 0x00, 0x61, 0x6c, 0x6c, 0x00,
- 0xea, 0x00, 0x00, 0x63, 0x02, 0x68, 0x3b, 0x6b, 0x40, 0x6d, 0x55, 0x6e,
- 0x6d, 0x70, 0x76, 0x72, 0x8b, 0x73, 0xd7, 0x77, 0xde, 0x00, 0x00, 0xe1,
- 0x68, 0x00, 0xe1, 0x74, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07,
- 0x00, 0x2c, 0x40, 0x07, 0x6e, 0x67, 0x00, 0xe2, 0x6d, 0x00, 0x77, 0x0d,
- 0xe2, 0x61, 0x00, 0x65, 0x04, 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x04,
- 0x40, 0x07, 0x6e, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40, 0x06, 0x6f, 0x6f,
- 0x00, 0xe2, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x00,
- 0x00, 0x6d, 0x02, 0x00, 0x06, 0xe1, 0x65, 0x00, 0xe1, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x65, 0x02, 0x00, 0xfa, 0x40, 0x07, 0x72, 0x00, 0xe2, 0x67,
- 0x00, 0x6b, 0x02, 0x00, 0x07, 0x00, 0x47, 0xe2, 0x00, 0x00, 0x70, 0x02,
- 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0xe4, 0x64, 0x00, 0x6d, 0x35, 0x6e, 0x3c, 0x72,
- 0x3e, 0xe4, 0x00, 0x00, 0x61, 0x02, 0x6d, 0x0f, 0x73, 0x25, 0x00, 0x09,
- 0xe2, 0x67, 0x00, 0x72, 0x04, 0x40, 0x09, 0x65, 0x00, 0x40, 0x09, 0x6d,
- 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0d, 0xe2, 0x6e, 0x00, 0x73, 0x02, 0x00,
- 0x07, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0x40, 0x00, 0x6e, 0x00, 0x40,
- 0x09, 0x74, 0x69, 0x63, 0x6b, 0x00, 0x40, 0x06, 0x75, 0x6c, 0x6b, 0x65,
- 0x00, 0x00, 0x09, 0x40, 0x07, 0x6f, 0x77, 0x00, 0x40, 0x08, 0x68, 0x6d,
- 0x61, 0x6b, 0x00, 0xe4, 0x00, 0x00, 0x6c, 0x02, 0x6e, 0x04, 0x73, 0x0f,
- 0x00, 0x93, 0x00, 0x09, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x00, 0xe7, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0x07, 0x00, 0x00, 0xea, 0x00, 0x00, 0x61, 0x02,
- 0x67, 0x52, 0x6c, 0x56, 0x6e, 0x89, 0x6f, 0x8b, 0x70, 0xa5, 0x73, 0xa7,
- 0x74, 0xdc, 0x77, 0xe5, 0x05, 0x46, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x72,
- 0x0b, 0x73, 0x3b, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0xe4, 0x00, 0x00, 0x62, 0x02, 0x6c, 0x08, 0x6e, 0x1b, 0x00,
- 0x86, 0x40, 0x09, 0x6f, 0x6f, 0x6b, 0x00, 0xe3, 0x69, 0x00, 0x6f, 0x05,
- 0x79, 0x0a, 0x40, 0x09, 0x6e, 0x67, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00,
- 0x00, 0x06, 0xe2, 0x00, 0x00, 0x69, 0x02, 0x02, 0x68, 0x40, 0x07, 0x6e,
- 0x67, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x00, 0x00, 0x79, 0x02, 0x00, 0x06,
- 0x00, 0xf3, 0x40, 0x09, 0x67, 0x00, 0xe2, 0x6c, 0x00, 0x70, 0x2c, 0xe2,
- 0x00, 0x00, 0x6f, 0x02, 0x00, 0x47, 0xe1, 0x77, 0x00, 0xe5, 0x00, 0x00,
- 0x68, 0x02, 0x69, 0x0a, 0x6e, 0x0f, 0x79, 0x15, 0x05, 0x47, 0x40, 0x08,
- 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x00, 0x40, 0x00, 0x73, 0x68, 0x00, 0x40,
- 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x06, 0xe1,
- 0x6d, 0x00, 0xe2, 0x61, 0x00, 0x65, 0x0e, 0xe1, 0x6e, 0x00, 0xe2, 0x00,
- 0x00, 0x72, 0x02, 0x00, 0x07, 0x40, 0x07, 0x79, 0x00, 0x40, 0x00, 0x6e,
- 0x00, 0x00, 0x06, 0xe4, 0x00, 0x00, 0x68, 0x02, 0x73, 0x08, 0x74, 0x16,
- 0x00, 0x09, 0x40, 0x06, 0x69, 0x76, 0x61, 0x00, 0xe2, 0x65, 0x00, 0x69,
- 0x04, 0x40, 0x00, 0x64, 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe1, 0x65,
- 0x00, 0xe1, 0x72, 0x00, 0xe2, 0x64, 0x00, 0x79, 0x05, 0x40, 0x09, 0x61,
- 0x79, 0x00, 0x40, 0x07, 0x65, 0x61, 0x72, 0x00, 0xe2, 0x00, 0x00, 0x69,
- 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06, 0xe5, 0x64, 0x00, 0x65, 0x02,
- 0x6b, 0x07, 0x6e, 0x0c, 0x70, 0x0e, 0x00, 0x08, 0x45, 0x48, 0x6c, 0x64,
- 0x00, 0x40, 0x00, 0x65, 0x73, 0x00, 0x00, 0x07, 0xe3, 0x00, 0x00, 0x65,
- 0x02, 0x70, 0x04, 0x00, 0x06, 0x00, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x09,
- 0xe2, 0x64, 0x00, 0x65, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x6e,
- 0x67, 0x00, 0xea, 0x00, 0x00, 0x62, 0x02, 0x64, 0x0d, 0x67, 0x1e, 0x6b,
- 0x35, 0x6c, 0x47, 0x6e, 0x4b, 0x72, 0x5d, 0x75, 0x61, 0x77, 0xd6, 0x00,
- 0x00, 0xe2, 0x00, 0x00, 0x62, 0x02, 0x00, 0x08, 0x40, 0x08, 0x6f, 0x00,
- 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x65, 0x02, 0x01,
- 0x5b, 0x40, 0x07, 0x72, 0x00, 0xe3, 0x61, 0x00, 0x69, 0x02, 0x75, 0x0b,
- 0x00, 0x07, 0xe2, 0x00, 0x00, 0x63, 0x02, 0x00, 0x09, 0x00, 0x00, 0x40,
- 0x06, 0x72, 0x74, 0x00, 0xe1, 0x65, 0x00, 0xe3, 0x00, 0x00, 0x27, 0x02,
- 0x6c, 0x06, 0x01, 0x34, 0x40, 0x00, 0x73, 0x00, 0x00, 0x06, 0x40, 0xb2,
- 0x6b, 0x00, 0xe3, 0x00, 0x00, 0x64, 0x02, 0x6b, 0x07, 0x00, 0x00, 0x40,
- 0x00, 0x65, 0x72, 0x00, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x65, 0x00,
- 0xe5, 0x00, 0x00, 0x27, 0x02, 0x6e, 0x19, 0x72, 0x30, 0x74, 0x49, 0x01,
- 0x58, 0xe4, 0x64, 0x00, 0x6c, 0x02, 0x72, 0x06, 0x76, 0x0a, 0x00, 0x00,
- 0x40, 0x00, 0x6c, 0x00, 0x40, 0x00, 0x65, 0x00, 0x40, 0x00, 0x65, 0x00,
- 0xe1, 0x67, 0x00, 0xe3, 0x00, 0x00, 0x69, 0x02, 0x73, 0x07, 0x05, 0x49,
- 0x40, 0x00, 0x73, 0x68, 0x00, 0x40, 0x09, 0x74, 0x65, 0x72, 0x00, 0xe2,
- 0x00, 0x00, 0x73, 0x02, 0x00, 0x08, 0xe1, 0x65, 0x00, 0xe1, 0x6c, 0x00,
- 0xe2, 0x66, 0x00, 0x76, 0x02, 0x00, 0x00, 0x40, 0x00, 0x65, 0x73, 0x00,
- 0xe1, 0x68, 0x00, 0xe3, 0x00, 0x00, 0x66, 0x02, 0x73, 0x15, 0x00, 0x07,
- 0xe1, 0x75, 0x00, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00,
- 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00,
- 0x6c, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x08, 0xe1, 0x74, 0x00, 0xe2,
- 0x65, 0x00, 0x72, 0x08, 0x40, 0x07, 0x72, 0x62, 0x69, 0x75, 0x6d, 0x00,
- 0x40, 0x07, 0x69, 0x75, 0x6d, 0x00, 0xe7, 0x61, 0x00, 0x63, 0x04, 0x6b,
- 0x16, 0x6c, 0x2f, 0x6d, 0x3f, 0x70, 0x4a, 0x72, 0x5f, 0x40, 0x07, 0x6e,
- 0x00, 0xe2, 0x63, 0x00, 0x6b, 0x04, 0x40, 0x06, 0x61, 0x00, 0xe2, 0x00,
- 0x00, 0x79, 0x02, 0x00, 0x00, 0x00, 0x60, 0xe2, 0x00, 0x00, 0x6b, 0x02,
- 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x04, 0x79, 0x09, 0x40, 0x00, 0x64,
- 0x00, 0x40, 0x00, 0x6e, 0x67, 0x00, 0x00, 0x00, 0xe1, 0x65, 0x00, 0xe2,
- 0x00, 0x00, 0x74, 0x02, 0x00, 0x07, 0x40, 0x07, 0x69, 0x64, 0x65, 0x00,
- 0xe2, 0x00, 0x00, 0x6d, 0x02, 0x00, 0x00, 0x40, 0x60, 0x79, 0x00, 0xe2,
- 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0xe1, 0x69, 0x00, 0xe2, 0x65, 0x00,
- 0x66, 0x02, 0x00, 0x09, 0x40, 0x0b, 0x79, 0x00, 0x40, 0x09, 0x74, 0x00,
- 0xfa, 0x00, 0x00, 0x00, 0x53, 0x02, 0x00, 0x61, 0x09, 0x00, 0x65, 0x3a,
- 0x00, 0x69, 0xf3, 0x00, 0x6c, 0xb0, 0x01, 0x6f, 0xc2, 0x01, 0x75, 0x6f,
- 0x02, 0x77, 0x78, 0x02, 0x79, 0x81, 0x02, 0x05, 0x4a, 0x40, 0x07, 0x68,
- 0x6f, 0x70, 0x73, 0x00, 0xe2, 0x6e, 0x00, 0x70, 0x0e, 0xe2, 0x69, 0x00,
- 0x79, 0x07, 0x40, 0x07, 0x6e, 0x65, 0x73, 0x73, 0x00, 0x03, 0x35, 0xe2,
- 0x00, 0x00, 0x70, 0x02, 0x00, 0x06, 0xe3, 0x65, 0x00, 0x69, 0x09, 0x79,
- 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00,
- 0x6e, 0x67, 0x00, 0x00, 0x00, 0xea, 0x61, 0x00, 0x62, 0x2a, 0x64, 0x35,
- 0x69, 0x37, 0x6e, 0x40, 0x6f, 0x59, 0x70, 0x60, 0x72, 0x71, 0x73, 0x7f,
- 0x74, 0xa0, 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x07,
- 0xe2, 0x74, 0x00, 0x75, 0x0b, 0xe2, 0x00, 0x00, 0x72, 0x02, 0x00, 0x09,
- 0x40, 0x07, 0x79, 0x00, 0xe1, 0x73, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02,
- 0x00, 0x3e, 0x40, 0x07, 0x65, 0x73, 0x73, 0x00, 0xe2, 0x72, 0x00, 0x75,
- 0x04, 0x40, 0x06, 0x61, 0x00, 0x00, 0x09, 0x00, 0x06, 0x40, 0x06, 0x74,
- 0x67, 0x65, 0x69, 0x73, 0x74, 0x00, 0xe2, 0x69, 0x00, 0x6e, 0x0f, 0xe1,
- 0x74, 0x00, 0xe1, 0x68, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x07,
- 0x00, 0x00, 0x40, 0x00, 0x65, 0x64, 0x00, 0x40, 0x08, 0x6c, 0x69, 0x74,
- 0x65, 0x00, 0xe2, 0x68, 0x00, 0x70, 0x05, 0x40, 0x09, 0x79, 0x72, 0x00,
- 0x40, 0x09, 0x65, 0x6c, 0x69, 0x6e, 0x00, 0xe1, 0x6f, 0x00, 0xe2, 0x00,
- 0x00, 0x65, 0x02, 0x05, 0x4b, 0x40, 0x00, 0x73, 0x00, 0xe1, 0x74, 0x00,
- 0xe3, 0x00, 0x00, 0x66, 0x02, 0x79, 0x15, 0x00, 0x09, 0xe1, 0x75, 0x00,
- 0xe1, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x6e, 0x02, 0x00, 0x3e, 0x40, 0x07,
- 0x65, 0x73, 0x73, 0x00, 0x00, 0xf3, 0x40, 0x09, 0x61, 0x00, 0xe6, 0x67,
- 0x00, 0x6c, 0x1e, 0x6e, 0x2d, 0x70, 0x6b, 0x72, 0x8f, 0x74, 0xa4, 0xe1,
- 0x7a, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x00, 0x00, 0x67,
- 0x02, 0x00, 0x06, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00,
- 0x40, 0x00, 0x6e, 0x67, 0x00, 0xe2, 0x63, 0x00, 0x6c, 0x04, 0x40, 0x07,
- 0x68, 0x00, 0x40, 0x09, 0x69, 0x6f, 0x6e, 0x00, 0xe5, 0x63, 0x00, 0x65,
- 0x15, 0x66, 0x17, 0x67, 0x1f, 0x6e, 0x2e, 0xe2, 0x00, 0x00, 0x6b, 0x02,
- 0x00, 0x09, 0xe2, 0x65, 0x00, 0x69, 0x04, 0x40, 0x00, 0x64, 0x00, 0x40,
- 0x00, 0x6e, 0x67, 0x00, 0x00, 0x08, 0x40, 0x07, 0x61, 0x6e, 0x64, 0x65,
- 0x6c, 0x00, 0xe3, 0x00, 0x00, 0x65, 0x02, 0x79, 0x06, 0x03, 0xa2, 0x40,
- 0x07, 0x72, 0x00, 0x00, 0xf3, 0x40, 0x09, 0x69, 0x61, 0x00, 0xe3, 0x00,
- 0x00, 0x27, 0x02, 0x70, 0x06, 0x01, 0x43, 0x40, 0x00, 0x73, 0x00, 0xe3,
- 0x65, 0x00, 0x69, 0x09, 0x79, 0x0e, 0xe2, 0x64, 0x00, 0x72, 0x02, 0x00,
- 0x37, 0x00, 0x55, 0x40, 0x37, 0x6e, 0x67, 0x00, 0x00, 0x60, 0xe1, 0x63,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x6e, 0x00, 0xe2, 0x00, 0x00, 0x69, 0x02,
- 0x00, 0x09, 0x40, 0x07, 0x75, 0x6d, 0x00, 0xe2, 0x00, 0x00, 0x68, 0x02,
- 0x00, 0x06, 0x40, 0x09, 0x65, 0x72, 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74,
- 0x00, 0xe1, 0x79, 0x00, 0xe2, 0x00, 0x00, 0x73, 0x02, 0x00, 0x06, 0x00,
- 0x00, 0xe7, 0x64, 0x00, 0x6d, 0x14, 0x6e, 0x1a, 0x6f, 0x3c, 0x72, 0x8d,
- 0x73, 0x92, 0x75, 0x98, 0xe1, 0x69, 0x00, 0xe1, 0x61, 0x00, 0xe1, 0x63,
- 0x00, 0xe2, 0x00, 0x00, 0x61, 0x02, 0x00, 0x09, 0x40, 0x00, 0x6c, 0x00,
- 0x40, 0x09, 0x62, 0x69, 0x65, 0x00, 0xe4, 0x61, 0x00, 0x65, 0x04, 0x69,
- 0x0f, 0x6b, 0x14, 0x40, 0x3b, 0x6c, 0x00, 0xe2, 0x00, 0x00, 0x27, 0x02,
- 0x00, 0x4b, 0x40, 0x00, 0x73, 0x00, 0x40, 0x07, 0x6e, 0x67, 0x00, 0x40,
- 0x00, 0x65, 0x64, 0x00, 0xe5, 0x00, 0x00, 0x6b, 0x02, 0x6c, 0x0a, 0x6d,
- 0x25, 0x70, 0x27, 0x00, 0x06, 0x40, 0x06, 0x65, 0x65, 0x70, 0x65, 0x72,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x67, 0x00, 0xe2, 0x69, 0x00, 0x79, 0x0e,
- 0xe2, 0x63, 0x00, 0x73, 0x05, 0x40, 0x3b, 0x61, 0x6c, 0x00, 0x40, 0x06,
- 0x74, 0x00, 0x00, 0x07, 0x00, 0x47, 0xe2, 0x68, 0x00, 0x6c, 0x11, 0xe1,
- 0x79, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02, 0x00, 0x06,
- 0x40, 0x00, 0x63, 0x00, 0x40, 0x00, 0x61, 0x6e, 0x6b, 0x74, 0x6f, 0x6e,
- 0x00, 0x40, 0x00, 0x63, 0x68, 0x00, 0x40, 0x00, 0x74, 0x65, 0x72, 0x00,
- 0x40, 0x00, 0x6e, 0x64, 0x73, 0x00, 0x40, 0x09, 0x63, 0x63, 0x68, 0x69,
- 0x6e, 0x69, 0x00, 0x40, 0x07, 0x69, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x00,
- 0xe3, 0x64, 0x00, 0x67, 0x06, 0x6d, 0x17, 0x40, 0x07, 0x65, 0x63, 0x6f,
- 0x00, 0xe1, 0x6f, 0x00, 0xe1, 0x74, 0x00, 0xe2, 0x65, 0x00, 0x69, 0x02,
- 0x00, 0x06, 0x40, 0x00, 0x63, 0x00, 0x40, 0x07, 0x75, 0x72, 0x67, 0x79,
- 0x00, };
-
-#endif // THIRD_PARTY_HUNSPELL_FUZZ_HUNSPELL_FUZZER_HUNSPELL_DICTIONARY_H_
diff --git a/chromium/third_party/libFuzzer/LICENSE.TXT b/chromium/third_party/libFuzzer/LICENSE.TXT
deleted file mode 100644
index 84090c07a54..00000000000
--- a/chromium/third_party/libFuzzer/LICENSE.TXT
+++ /dev/null
@@ -1,70 +0,0 @@
-==============================================================================
-LLVM Release License
-==============================================================================
-University of Illinois/NCSA
-Open Source License
-
-Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign.
-All rights reserved.
-
-Developed by:
-
- LLVM Team
-
- University of Illinois at Urbana-Champaign
-
- http://llvm.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal with
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimers.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimers in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the names of the LLVM Team, University of Illinois at
- Urbana-Champaign, nor the names of its contributors may be used to
- endorse or promote products derived from this Software without specific
- prior written permission.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
-SOFTWARE.
-
-==============================================================================
-Copyrights and Licenses for Third Party Software Distributed with LLVM:
-==============================================================================
-The LLVM software contains code written by third parties. Such software will
-have its own individual LICENSE.TXT file in the directory in which it appears.
-This file will describe the copyrights, license, and restrictions which apply
-to that code.
-
-The disclaimer of warranty in the University of Illinois Open Source License
-applies to all code in the LLVM Distribution, and nothing in any of the
-other licenses gives permission to use the names of the LLVM Team or the
-University of Illinois to endorse or promote products derived from this
-Software.
-
-The following pieces of software have additional or alternate copyrights,
-licenses, and/or restrictions:
-
-Program Directory
-------- ---------
-Autoconf llvm/autoconf
- llvm/projects/ModuleMaker/autoconf
-Google Test llvm/utils/unittest/googletest
-OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
-pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
-ARM contributions llvm/lib/Target/ARM/LICENSE.TXT
-md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
diff --git a/chromium/third_party/libFuzzer/OWNERS b/chromium/third_party/libFuzzer/OWNERS
deleted file mode 100644
index 139269c5c25..00000000000
--- a/chromium/third_party/libFuzzer/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-inferno@chromium.org
-kcc@chromium.org
-metzman@chromium.org
-mmoroz@chromium.org
-ochang@chromium.org
diff --git a/chromium/third_party/libFuzzer/README.chromium b/chromium/third_party/libFuzzer/README.chromium
deleted file mode 100644
index e0438a1bc70..00000000000
--- a/chromium/third_party/libFuzzer/README.chromium
+++ /dev/null
@@ -1,13 +0,0 @@
-Name: libFuzzer
-URL: http://llvm.org/docs/LibFuzzer.html
-Version: 0
-License: University of Illinois/NCSA Open Source
-License File: LICENSE.TXT
-Security Critical: no
-
-Description:
-Library for in-process coverage-guided fuzz testing (fuzzing) of other
-libraries.
-
-Local Modifications:
-None.
diff --git a/chromium/third_party/libFuzzer/src/CMakeLists.txt b/chromium/third_party/libFuzzer/src/CMakeLists.txt
deleted file mode 100644
index caea9734fe5..00000000000
--- a/chromium/third_party/libFuzzer/src/CMakeLists.txt
+++ /dev/null
@@ -1,147 +0,0 @@
-set(LIBFUZZER_SOURCES
- FuzzerCrossOver.cpp
- FuzzerDataFlowTrace.cpp
- FuzzerDriver.cpp
- FuzzerExtFunctionsDlsym.cpp
- FuzzerExtFunctionsWeak.cpp
- FuzzerExtFunctionsWindows.cpp
- FuzzerExtraCounters.cpp
- FuzzerIO.cpp
- FuzzerIOPosix.cpp
- FuzzerIOWindows.cpp
- FuzzerLoop.cpp
- FuzzerMerge.cpp
- FuzzerMutate.cpp
- FuzzerSHA1.cpp
- FuzzerShmemFuchsia.cpp
- FuzzerShmemPosix.cpp
- FuzzerShmemWindows.cpp
- FuzzerTracePC.cpp
- FuzzerUtil.cpp
- FuzzerUtilDarwin.cpp
- FuzzerUtilFuchsia.cpp
- FuzzerUtilLinux.cpp
- FuzzerUtilPosix.cpp
- FuzzerUtilWindows.cpp)
-
-set(LIBFUZZER_HEADERS
- FuzzerBuiltins.h
- FuzzerBuiltinsMsvc.h
- FuzzerCommand.h
- FuzzerCorpus.h
- FuzzerDataFlowTrace.h
- FuzzerDefs.h
- FuzzerDictionary.h
- FuzzerExtFunctions.def
- FuzzerExtFunctions.h
- FuzzerFlags.def
- FuzzerIO.h
- FuzzerInterface.h
- FuzzerInternal.h
- FuzzerMerge.h
- FuzzerMutate.h
- FuzzerOptions.h
- FuzzerRandom.h
- FuzzerSHA1.h
- FuzzerShmem.h
- FuzzerTracePC.h
- FuzzerUtil.h
- FuzzerValueBitMap.h)
-
-CHECK_CXX_SOURCE_COMPILES("
- static thread_local int blah;
- int main() {
- return 0;
- }
- " HAS_THREAD_LOCAL)
-
-set(LIBFUZZER_CFLAGS ${SANITIZER_COMMON_CFLAGS})
-
-if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH)
- list(APPEND LIBFUZZER_CFLAGS -nostdinc++ -D_LIBCPP_ABI_VERSION=Fuzzer)
- # Remove -stdlib= which is unused when passing -nostdinc++.
- string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
-elseif(TARGET cxx-headers OR HAVE_LIBCXX)
- set(LIBFUZZER_DEPS cxx-headers)
-endif()
-
-append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer LIBFUZZER_CFLAGS)
-
-if (CMAKE_CXX_FLAGS MATCHES "fsanitize-coverage")
- list(APPEND LIBFUZZER_CFLAGS -fno-sanitize-coverage=trace-pc-guard,edge,trace-cmp,indirect-calls,8bit-counters)
-endif()
-
-if(NOT HAS_THREAD_LOCAL)
- list(APPEND LIBFUZZER_CFLAGS -Dthread_local=__thread)
-endif()
-
-set(FUZZER_SUPPORTED_OS ${SANITIZER_COMMON_SUPPORTED_OS})
-
-add_compiler_rt_object_libraries(RTfuzzer
- OS ${FUZZER_SUPPORTED_OS}
- ARCHS ${FUZZER_SUPPORTED_ARCH}
- SOURCES ${LIBFUZZER_SOURCES}
- ADDITIONAL_HEADERS ${LIBFUZZER_HEADERS}
- CFLAGS ${LIBFUZZER_CFLAGS}
- DEPS ${LIBFUZZER_DEPS})
-
-add_compiler_rt_object_libraries(RTfuzzer_main
- OS ${FUZZER_SUPPORTED_OS}
- ARCHS ${FUZZER_SUPPORTED_ARCH}
- SOURCES FuzzerMain.cpp
- CFLAGS ${LIBFUZZER_CFLAGS}
- DEPS ${LIBFUZZER_DEPS})
-
-add_compiler_rt_runtime(clang_rt.fuzzer
- STATIC
- OS ${FUZZER_SUPPORTED_OS}
- ARCHS ${FUZZER_SUPPORTED_ARCH}
- OBJECT_LIBS RTfuzzer RTfuzzer_main
- CFLAGS ${LIBFUZZER_CFLAGS}
- PARENT_TARGET fuzzer)
-
-add_compiler_rt_runtime(clang_rt.fuzzer_no_main
- STATIC
- OS ${FUZZER_SUPPORTED_OS}
- ARCHS ${FUZZER_SUPPORTED_ARCH}
- OBJECT_LIBS RTfuzzer
- CFLAGS ${LIBFUZZER_CFLAGS}
- PARENT_TARGET fuzzer)
-
-if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH)
- macro(partially_link_libcxx name dir arch)
- set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir")
- file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir})
- add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD
- COMMAND ${CMAKE_LINKER} --whole-archive "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o
- COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o
- COMMAND ${CMAKE_COMMAND} -E remove "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>"
- COMMAND ${CMAKE_AR} qcs "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" ${name}.o
- WORKING_DIRECTORY ${cxx_${arch}_merge_dir}
- )
- endmacro()
-
- foreach(arch ${FUZZER_SUPPORTED_ARCH})
- get_target_flags_for_arch(${arch} TARGET_CFLAGS)
- set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch})
- add_custom_libcxx(libcxx_fuzzer_${arch} ${LIBCXX_${arch}_PREFIX}
- CFLAGS ${TARGET_CFLAGS}
- -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS=1
- -fvisibility=hidden
- CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON
- -DLIBCXX_ENABLE_EXCEPTIONS=OFF
- -DLIBCXX_ENABLE_SHARED=OFF
- -DLIBCXX_ABI_NAMESPACE=Fuzzer
- -DLIBCXX_CXX_ABI=none)
- target_compile_options(RTfuzzer.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1)
- add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-build)
- target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1)
- add_dependencies(RTfuzzer_main.${arch} libcxx_fuzzer_${arch}-build)
- partially_link_libcxx(fuzzer_no_main ${LIBCXX_${arch}_PREFIX} ${arch})
- partially_link_libcxx(fuzzer ${LIBCXX_${arch}_PREFIX} ${arch})
- endforeach()
-endif()
-
-if(COMPILER_RT_INCLUDE_TESTS)
- add_subdirectory(tests)
-endif()
diff --git a/chromium/third_party/libFuzzer/src/FuzzerBuiltins.h b/chromium/third_party/libFuzzer/src/FuzzerBuiltins.h
deleted file mode 100644
index a80938d9a54..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerBuiltins.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Wrapper functions and marcos around builtin functions.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_BUILTINS_H
-#define LLVM_FUZZER_BUILTINS_H
-
-#include "FuzzerDefs.h"
-
-#if !LIBFUZZER_MSVC
-#include <cstdint>
-
-#define GET_CALLER_PC() __builtin_return_address(0)
-
-namespace fuzzer {
-
-inline uint8_t Bswap(uint8_t x) { return x; }
-inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); }
-inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); }
-inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); }
-
-inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); }
-inline uint32_t Clz(unsigned long long X) { return __builtin_clz(X); }
-inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); }
-
-} // namespace fuzzer
-
-#endif // !LIBFUZZER_MSVC
-#endif // LLVM_FUZZER_BUILTINS_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerBuiltinsMsvc.h b/chromium/third_party/libFuzzer/src/FuzzerBuiltinsMsvc.h
deleted file mode 100644
index 67dd57ff9a9..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerBuiltinsMsvc.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Wrapper functions and marcos that use intrinsics instead of builtin functions
-// which cannot be compiled by MSVC.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_BUILTINS_MSVC_H
-#define LLVM_FUZZER_BUILTINS_MSVC_H
-
-#include "FuzzerDefs.h"
-
-#if LIBFUZZER_MSVC
-#if !defined(_M_ARM) && !defined(_M_X64)
-#error "_BitScanReverse64 unavailable on this platform so MSVC is unsupported."
-#endif
-#include <intrin.h>
-#include <cstdint>
-#include <cstdlib>
-
-// __builtin_return_address() cannot be compiled with MSVC. Use the equivalent
-// from <intrin.h>
-#define GET_CALLER_PC() reinterpret_cast<uintptr_t>(_ReturnAddress())
-
-namespace fuzzer {
-
-inline uint8_t Bswap(uint8_t x) { return x; }
-// Use alternatives to __builtin functions from <stdlib.h> and <intrin.h> on
-// Windows since the builtins are not supported by MSVC.
-inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); }
-inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); }
-inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); }
-
-// The functions below were mostly copied from
-// compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used
-// outside of Windows.
-inline uint32_t Clzll(uint64_t X) {
- unsigned long LeadZeroIdx = 0;
- if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx;
- return 64;
-}
-
-inline uint32_t Clz(uint32_t X) {
- unsigned long LeadZeroIdx = 0;
- if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx;
- return 32;
-}
-
-inline int Popcountll(unsigned long long X) { return __popcnt64(X); }
-
-} // namespace fuzzer
-
-#endif // LIBFUZER_MSVC
-#endif // LLVM_FUZZER_BUILTINS_MSVC_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerCommand.h b/chromium/third_party/libFuzzer/src/FuzzerCommand.h
deleted file mode 100644
index 9d258a228f8..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerCommand.h
+++ /dev/null
@@ -1,179 +0,0 @@
-//===- FuzzerCommand.h - Interface representing a process -------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// FuzzerCommand represents a command to run in a subprocess. It allows callers
-// to manage command line arguments and output and error streams.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_COMMAND_H
-#define LLVM_FUZZER_COMMAND_H
-
-#include "FuzzerDefs.h"
-#include "FuzzerIO.h"
-
-#include <algorithm>
-#include <sstream>
-#include <string>
-#include <vector>
-
-namespace fuzzer {
-
-class Command final {
-public:
- // This command line flag is used to indicate that the remaining command line
- // is immutable, meaning this flag effectively marks the end of the mutable
- // argument list.
- static inline const char *ignoreRemainingArgs() {
- return "-ignore_remaining_args=1";
- }
-
- Command() : CombinedOutAndErr(false) {}
-
- explicit Command(const Vector<std::string> &ArgsToAdd)
- : Args(ArgsToAdd), CombinedOutAndErr(false) {}
-
- explicit Command(const Command &Other)
- : Args(Other.Args), CombinedOutAndErr(Other.CombinedOutAndErr),
- OutputFile(Other.OutputFile) {}
-
- Command &operator=(const Command &Other) {
- Args = Other.Args;
- CombinedOutAndErr = Other.CombinedOutAndErr;
- OutputFile = Other.OutputFile;
- return *this;
- }
-
- ~Command() {}
-
- // Returns true if the given Arg is present in Args. Only checks up to
- // "-ignore_remaining_args=1".
- bool hasArgument(const std::string &Arg) const {
- auto i = endMutableArgs();
- return std::find(Args.begin(), i, Arg) != i;
- }
-
- // Gets all of the current command line arguments, **including** those after
- // "-ignore-remaining-args=1".
- const Vector<std::string> &getArguments() const { return Args; }
-
- // Adds the given argument before "-ignore_remaining_args=1", or at the end
- // if that flag isn't present.
- void addArgument(const std::string &Arg) {
- Args.insert(endMutableArgs(), Arg);
- }
-
- // Adds all given arguments before "-ignore_remaining_args=1", or at the end
- // if that flag isn't present.
- void addArguments(const Vector<std::string> &ArgsToAdd) {
- Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end());
- }
-
- // Removes the given argument from the command argument list. Ignores any
- // occurrences after "-ignore_remaining_args=1", if present.
- void removeArgument(const std::string &Arg) {
- auto i = endMutableArgs();
- Args.erase(std::remove(Args.begin(), i, Arg), i);
- }
-
- // Like hasArgument, but checks for "-[Flag]=...".
- bool hasFlag(const std::string &Flag) const {
- std::string Arg("-" + Flag + "=");
- auto IsMatch = [&](const std::string &Other) {
- return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
- };
- return std::any_of(Args.begin(), endMutableArgs(), IsMatch);
- }
-
- // Returns the value of the first instance of a given flag, or an empty string
- // if the flag isn't present. Ignores any occurrences after
- // "-ignore_remaining_args=1", if present.
- std::string getFlagValue(const std::string &Flag) const {
- std::string Arg("-" + Flag + "=");
- auto IsMatch = [&](const std::string &Other) {
- return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
- };
- auto i = endMutableArgs();
- auto j = std::find_if(Args.begin(), i, IsMatch);
- std::string result;
- if (j != i) {
- result = j->substr(Arg.length());
- }
- return result;
- }
-
- // Like AddArgument, but adds "-[Flag]=[Value]".
- void addFlag(const std::string &Flag, const std::string &Value) {
- addArgument("-" + Flag + "=" + Value);
- }
-
- // Like RemoveArgument, but removes "-[Flag]=...".
- void removeFlag(const std::string &Flag) {
- std::string Arg("-" + Flag + "=");
- auto IsMatch = [&](const std::string &Other) {
- return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
- };
- auto i = endMutableArgs();
- Args.erase(std::remove_if(Args.begin(), i, IsMatch), i);
- }
-
- // Returns whether the command's stdout is being written to an output file.
- bool hasOutputFile() const { return !OutputFile.empty(); }
-
- // Returns the currently set output file.
- const std::string &getOutputFile() const { return OutputFile; }
-
- // Configures the command to redirect its output to the name file.
- void setOutputFile(const std::string &FileName) { OutputFile = FileName; }
-
- // Returns whether the command's stderr is redirected to stdout.
- bool isOutAndErrCombined() const { return CombinedOutAndErr; }
-
- // Sets whether to redirect the command's stderr to its stdout.
- void combineOutAndErr(bool combine = true) { CombinedOutAndErr = combine; }
-
- // Returns a string representation of the command. On many systems this will
- // be the equivalent command line.
- std::string toString() const {
- std::stringstream SS;
- for (auto arg : getArguments())
- SS << arg << " ";
- if (hasOutputFile())
- SS << ">" << getOutputFile() << " ";
- if (isOutAndErrCombined())
- SS << "2>&1 ";
- std::string result = SS.str();
- if (!result.empty())
- result = result.substr(0, result.length() - 1);
- return result;
- }
-
-private:
- Command(Command &&Other) = delete;
- Command &operator=(Command &&Other) = delete;
-
- Vector<std::string>::iterator endMutableArgs() {
- return std::find(Args.begin(), Args.end(), ignoreRemainingArgs());
- }
-
- Vector<std::string>::const_iterator endMutableArgs() const {
- return std::find(Args.begin(), Args.end(), ignoreRemainingArgs());
- }
-
- // The command arguments. Args[0] is the command name.
- Vector<std::string> Args;
-
- // True indicates stderr is redirected to stdout.
- bool CombinedOutAndErr;
-
- // If not empty, stdout is redirected to the named file.
- std::string OutputFile;
-};
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_COMMAND_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerCorpus.h b/chromium/third_party/libFuzzer/src/FuzzerCorpus.h
deleted file mode 100644
index 8ad14656cff..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerCorpus.h
+++ /dev/null
@@ -1,315 +0,0 @@
-//===- FuzzerCorpus.h - Internal header for the Fuzzer ----------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// fuzzer::InputCorpus
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_CORPUS
-#define LLVM_FUZZER_CORPUS
-
-#include "FuzzerDataFlowTrace.h"
-#include "FuzzerDefs.h"
-#include "FuzzerIO.h"
-#include "FuzzerRandom.h"
-#include "FuzzerSHA1.h"
-#include "FuzzerTracePC.h"
-#include <algorithm>
-#include <numeric>
-#include <random>
-#include <unordered_set>
-
-namespace fuzzer {
-
-struct InputInfo {
- Unit U; // The actual input data.
- uint8_t Sha1[kSHA1NumBytes]; // Checksum.
- // Number of features that this input has and no smaller input has.
- size_t NumFeatures = 0;
- size_t Tmp = 0; // Used by ValidateFeatureSet.
- // Stats.
- size_t NumExecutedMutations = 0;
- size_t NumSuccessfullMutations = 0;
- bool MayDeleteFile = false;
- bool Reduced = false;
- bool HasFocusFunction = false;
- Vector<uint32_t> UniqFeatureSet;
- Vector<uint8_t> DataFlowTraceForFocusFunction;
-};
-
-class InputCorpus {
- static const size_t kFeatureSetSize = 1 << 21;
- public:
- InputCorpus(const std::string &OutputCorpus) : OutputCorpus(OutputCorpus) {
- memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature));
- memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature));
- }
- ~InputCorpus() {
- for (auto II : Inputs)
- delete II;
- }
- size_t size() const { return Inputs.size(); }
- size_t SizeInBytes() const {
- size_t Res = 0;
- for (auto II : Inputs)
- Res += II->U.size();
- return Res;
- }
- size_t NumActiveUnits() const {
- size_t Res = 0;
- for (auto II : Inputs)
- Res += !II->U.empty();
- return Res;
- }
- size_t MaxInputSize() const {
- size_t Res = 0;
- for (auto II : Inputs)
- Res = std::max(Res, II->U.size());
- return Res;
- }
-
- size_t NumInputsThatTouchFocusFunction() {
- return std::count_if(Inputs.begin(), Inputs.end(), [](const InputInfo *II) {
- return II->HasFocusFunction;
- });
- }
-
- size_t NumInputsWithDataFlowTrace() {
- return std::count_if(Inputs.begin(), Inputs.end(), [](const InputInfo *II) {
- return !II->DataFlowTraceForFocusFunction.empty();
- });
- }
-
- bool empty() const { return Inputs.empty(); }
- const Unit &operator[] (size_t Idx) const { return Inputs[Idx]->U; }
- void AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile,
- bool HasFocusFunction, const Vector<uint32_t> &FeatureSet,
- const DataFlowTrace &DFT, const InputInfo *BaseII) {
- assert(!U.empty());
- if (FeatureDebug)
- Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures);
- Inputs.push_back(new InputInfo());
- InputInfo &II = *Inputs.back();
- II.U = U;
- II.NumFeatures = NumFeatures;
- II.MayDeleteFile = MayDeleteFile;
- II.UniqFeatureSet = FeatureSet;
- II.HasFocusFunction = HasFocusFunction;
- std::sort(II.UniqFeatureSet.begin(), II.UniqFeatureSet.end());
- ComputeSHA1(U.data(), U.size(), II.Sha1);
- auto Sha1Str = Sha1ToString(II.Sha1);
- Hashes.insert(Sha1Str);
- if (HasFocusFunction)
- if (auto V = DFT.Get(Sha1Str))
- II.DataFlowTraceForFocusFunction = *V;
- // This is a gross heuristic.
- // Ideally, when we add an element to a corpus we need to know its DFT.
- // But if we don't, we'll use the DFT of its base input.
- if (II.DataFlowTraceForFocusFunction.empty() && BaseII)
- II.DataFlowTraceForFocusFunction = BaseII->DataFlowTraceForFocusFunction;
- UpdateCorpusDistribution();
- PrintCorpus();
- // ValidateFeatureSet();
- }
-
- // Debug-only
- void PrintUnit(const Unit &U) {
- if (!FeatureDebug) return;
- for (uint8_t C : U) {
- if (C != 'F' && C != 'U' && C != 'Z')
- C = '.';
- Printf("%c", C);
- }
- }
-
- // Debug-only
- void PrintFeatureSet(const Vector<uint32_t> &FeatureSet) {
- if (!FeatureDebug) return;
- Printf("{");
- for (uint32_t Feature: FeatureSet)
- Printf("%u,", Feature);
- Printf("}");
- }
-
- // Debug-only
- void PrintCorpus() {
- if (!FeatureDebug) return;
- Printf("======= CORPUS:\n");
- int i = 0;
- for (auto II : Inputs) {
- if (std::find(II->U.begin(), II->U.end(), 'F') != II->U.end()) {
- Printf("[%2d] ", i);
- Printf("%s sz=%zd ", Sha1ToString(II->Sha1).c_str(), II->U.size());
- PrintUnit(II->U);
- Printf(" ");
- PrintFeatureSet(II->UniqFeatureSet);
- Printf("\n");
- }
- i++;
- }
- }
-
- void Replace(InputInfo *II, const Unit &U) {
- assert(II->U.size() > U.size());
- Hashes.erase(Sha1ToString(II->Sha1));
- DeleteFile(*II);
- ComputeSHA1(U.data(), U.size(), II->Sha1);
- Hashes.insert(Sha1ToString(II->Sha1));
- II->U = U;
- II->Reduced = true;
- UpdateCorpusDistribution();
- }
-
- bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); }
- bool HasUnit(const std::string &H) { return Hashes.count(H); }
- InputInfo &ChooseUnitToMutate(Random &Rand) {
- InputInfo &II = *Inputs[ChooseUnitIdxToMutate(Rand)];
- assert(!II.U.empty());
- return II;
- };
-
- // Returns an index of random unit from the corpus to mutate.
- size_t ChooseUnitIdxToMutate(Random &Rand) {
- size_t Idx = static_cast<size_t>(CorpusDistribution(Rand));
- assert(Idx < Inputs.size());
- return Idx;
- }
-
- void PrintStats() {
- for (size_t i = 0; i < Inputs.size(); i++) {
- const auto &II = *Inputs[i];
- Printf(" [% 3zd %s] sz: % 5zd runs: % 5zd succ: % 5zd focus: %d\n", i,
- Sha1ToString(II.Sha1).c_str(), II.U.size(),
- II.NumExecutedMutations, II.NumSuccessfullMutations, II.HasFocusFunction);
- }
- }
-
- void PrintFeatureSet() {
- for (size_t i = 0; i < kFeatureSetSize; i++) {
- if(size_t Sz = GetFeature(i))
- Printf("[%zd: id %zd sz%zd] ", i, SmallestElementPerFeature[i], Sz);
- }
- Printf("\n\t");
- for (size_t i = 0; i < Inputs.size(); i++)
- if (size_t N = Inputs[i]->NumFeatures)
- Printf(" %zd=>%zd ", i, N);
- Printf("\n");
- }
-
- void DeleteFile(const InputInfo &II) {
- if (!OutputCorpus.empty() && II.MayDeleteFile)
- RemoveFile(DirPlusFile(OutputCorpus, Sha1ToString(II.Sha1)));
- }
-
- void DeleteInput(size_t Idx) {
- InputInfo &II = *Inputs[Idx];
- DeleteFile(II);
- Unit().swap(II.U);
- if (FeatureDebug)
- Printf("EVICTED %zd\n", Idx);
- }
-
- bool AddFeature(size_t Idx, uint32_t NewSize, bool Shrink) {
- assert(NewSize);
- Idx = Idx % kFeatureSetSize;
- uint32_t OldSize = GetFeature(Idx);
- if (OldSize == 0 || (Shrink && OldSize > NewSize)) {
- if (OldSize > 0) {
- size_t OldIdx = SmallestElementPerFeature[Idx];
- InputInfo &II = *Inputs[OldIdx];
- assert(II.NumFeatures > 0);
- II.NumFeatures--;
- if (II.NumFeatures == 0)
- DeleteInput(OldIdx);
- } else {
- NumAddedFeatures++;
- }
- NumUpdatedFeatures++;
- if (FeatureDebug)
- Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize);
- SmallestElementPerFeature[Idx] = Inputs.size();
- InputSizesPerFeature[Idx] = NewSize;
- return true;
- }
- return false;
- }
-
- bool IsFeatureNew(size_t Idx, uint32_t NewSize, bool Shrink) {
- assert(NewSize);
- uint32_t OldSize = GetFeature(Idx % kFeatureSetSize);
- return OldSize == 0 || (Shrink && OldSize > NewSize);
- }
-
- size_t NumFeatures() const { return NumAddedFeatures; }
- size_t NumFeatureUpdates() const { return NumUpdatedFeatures; }
-
-private:
-
- static const bool FeatureDebug = false;
-
- size_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; }
-
- void ValidateFeatureSet() {
- if (FeatureDebug)
- PrintFeatureSet();
- for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++)
- if (GetFeature(Idx))
- Inputs[SmallestElementPerFeature[Idx]]->Tmp++;
- for (auto II: Inputs) {
- if (II->Tmp != II->NumFeatures)
- Printf("ZZZ %zd %zd\n", II->Tmp, II->NumFeatures);
- assert(II->Tmp == II->NumFeatures);
- II->Tmp = 0;
- }
- }
-
- // Updates the probability distribution for the units in the corpus.
- // Must be called whenever the corpus or unit weights are changed.
- //
- // Hypothesis: units added to the corpus last are more interesting.
- //
- // Hypothesis: inputs with infrequent features are more interesting.
- void UpdateCorpusDistribution() {
- size_t N = Inputs.size();
- assert(N);
- Intervals.resize(N + 1);
- Weights.resize(N);
- std::iota(Intervals.begin(), Intervals.end(), 0);
- for (size_t i = 0; i < N; i++)
- Weights[i] = Inputs[i]->NumFeatures
- ? (i + 1) * (Inputs[i]->HasFocusFunction ? 1000 : 1)
- : 0.;
- if (FeatureDebug) {
- for (size_t i = 0; i < N; i++)
- Printf("%zd ", Inputs[i]->NumFeatures);
- Printf("SCORE\n");
- for (size_t i = 0; i < N; i++)
- Printf("%f ", Weights[i]);
- Printf("Weights\n");
- }
- CorpusDistribution = std::piecewise_constant_distribution<double>(
- Intervals.begin(), Intervals.end(), Weights.begin());
- }
- std::piecewise_constant_distribution<double> CorpusDistribution;
-
- Vector<double> Intervals;
- Vector<double> Weights;
-
- std::unordered_set<std::string> Hashes;
- Vector<InputInfo*> Inputs;
-
- size_t NumAddedFeatures = 0;
- size_t NumUpdatedFeatures = 0;
- uint32_t InputSizesPerFeature[kFeatureSetSize];
- uint32_t SmallestElementPerFeature[kFeatureSetSize];
-
- std::string OutputCorpus;
-};
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_CORPUS
diff --git a/chromium/third_party/libFuzzer/src/FuzzerCrossOver.cpp b/chromium/third_party/libFuzzer/src/FuzzerCrossOver.cpp
deleted file mode 100644
index 8b0fd7d529a..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerCrossOver.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Cross over test inputs.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerDefs.h"
-#include "FuzzerMutate.h"
-#include "FuzzerRandom.h"
-#include <cstring>
-
-namespace fuzzer {
-
-// Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out.
-size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1,
- const uint8_t *Data2, size_t Size2,
- uint8_t *Out, size_t MaxOutSize) {
- assert(Size1 || Size2);
- MaxOutSize = Rand(MaxOutSize) + 1;
- size_t OutPos = 0;
- size_t Pos1 = 0;
- size_t Pos2 = 0;
- size_t *InPos = &Pos1;
- size_t InSize = Size1;
- const uint8_t *Data = Data1;
- bool CurrentlyUsingFirstData = true;
- while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) {
- // Merge a part of Data into Out.
- size_t OutSizeLeft = MaxOutSize - OutPos;
- if (*InPos < InSize) {
- size_t InSizeLeft = InSize - *InPos;
- size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft);
- size_t ExtraSize = Rand(MaxExtraSize) + 1;
- memcpy(Out + OutPos, Data + *InPos, ExtraSize);
- OutPos += ExtraSize;
- (*InPos) += ExtraSize;
- }
- // Use the other input data on the next iteration.
- InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1;
- InSize = CurrentlyUsingFirstData ? Size2 : Size1;
- Data = CurrentlyUsingFirstData ? Data2 : Data1;
- CurrentlyUsingFirstData = !CurrentlyUsingFirstData;
- }
- return OutPos;
-}
-
-} // namespace fuzzer
diff --git a/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.cpp b/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.cpp
deleted file mode 100644
index 764f3e49fd2..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-//===- FuzzerDataFlowTrace.cpp - DataFlowTrace ---*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// fuzzer::DataFlowTrace
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerDataFlowTrace.h"
-#include "FuzzerIO.h"
-
-#include <cstdlib>
-#include <fstream>
-#include <string>
-#include <vector>
-
-namespace fuzzer {
-
-void DataFlowTrace::Init(const std::string &DirPath,
- const std::string &FocusFunction) {
- if (DirPath.empty()) return;
- const char *kFunctionsTxt = "functions.txt";
- Printf("INFO: DataFlowTrace: reading from '%s'\n", DirPath.c_str());
- Vector<SizedFile> Files;
- GetSizedFilesFromDir(DirPath, &Files);
- std::string L;
-
- // Read functions.txt
- std::ifstream IF(DirPlusFile(DirPath, kFunctionsTxt));
- size_t FocusFuncIdx = SIZE_MAX;
- size_t NumFunctions = 0;
- while (std::getline(IF, L, '\n')) {
- NumFunctions++;
- if (FocusFunction == L)
- FocusFuncIdx = NumFunctions - 1;
- }
- if (!NumFunctions || FocusFuncIdx == SIZE_MAX || Files.size() <= 1)
- return;
- // Read traces.
- size_t NumTraceFiles = 0;
- size_t NumTracesWithFocusFunction = 0;
- for (auto &SF : Files) {
- auto Name = Basename(SF.File);
- if (Name == kFunctionsTxt) continue;
- auto ParseError = [&](const char *Err) {
- Printf("DataFlowTrace: parse error: %s\n File: %s\n Line: %s\n", Err,
- Name.c_str(), L.c_str());
- };
- NumTraceFiles++;
- // Printf("=== %s\n", Name.c_str());
- std::ifstream IF(SF.File);
- while (std::getline(IF, L, '\n')) {
- size_t SpacePos = L.find(' ');
- if (SpacePos == std::string::npos)
- return ParseError("no space in the trace line");
- if (L.empty() || L[0] != 'F')
- return ParseError("the trace line doesn't start with 'F'");
- size_t N = std::atol(L.c_str() + 1);
- if (N >= NumFunctions)
- return ParseError("N is greater than the number of functions");
- if (N == FocusFuncIdx) {
- NumTracesWithFocusFunction++;
- const char *Beg = L.c_str() + SpacePos + 1;
- const char *End = L.c_str() + L.size();
- assert(Beg < End);
- size_t Len = End - Beg;
- Vector<uint8_t> V(Len);
- for (size_t I = 0; I < Len; I++) {
- if (Beg[I] != '0' && Beg[I] != '1')
- ParseError("the trace should contain only 0 or 1");
- V[I] = Beg[I] == '1';
- }
- Traces[Name] = V;
- // Print just a few small traces.
- if (NumTracesWithFocusFunction <= 3 && Len <= 16)
- Printf("%s => |%s|\n", Name.c_str(), L.c_str() + SpacePos + 1);
- break; // No need to parse the following lines.
- }
- }
- }
- assert(NumTraceFiles == Files.size() - 1);
- Printf("INFO: DataFlowTrace: %zd trace files, %zd functions, "
- "%zd traces with focus function\n",
- NumTraceFiles, NumFunctions, NumTracesWithFocusFunction);
-}
-
-} // namespace fuzzer
-
diff --git a/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.h b/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.h
deleted file mode 100644
index ad4faeab7b2..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//===- FuzzerDataFlowTrace.h - Internal header for the Fuzzer ---*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// fuzzer::DataFlowTrace; reads and handles a data-flow trace.
-//
-// A data flow trace is generated by e.g. dataflow/DataFlow.cpp
-// and is stored on disk in a separate directory.
-//
-// The trace dir contains a file 'functions.txt' which lists function names,
-// oner per line, e.g.
-// ==> functions.txt <==
-// Func2
-// LLVMFuzzerTestOneInput
-// Func1
-//
-// All other files in the dir are the traces, see dataflow/DataFlow.cpp.
-// The name of the file is sha1 of the input used to generate the trace.
-//
-// Current status:
-// the data is parsed and the summary is printed, but the data is not yet
-// used in any other way.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_DATA_FLOW_TRACE
-#define LLVM_FUZZER_DATA_FLOW_TRACE
-
-#include "FuzzerDefs.h"
-
-#include <unordered_map>
-#include <vector>
-#include <string>
-
-namespace fuzzer {
-class DataFlowTrace {
- public:
- void Init(const std::string &DirPath, const std::string &FocusFunction);
- void Clear() { Traces.clear(); }
- const Vector<uint8_t> *Get(const std::string &InputSha1) const {
- auto It = Traces.find(InputSha1);
- if (It != Traces.end())
- return &It->second;
- return nullptr;
- }
-
- private:
- // Input's sha1 => DFT for the FocusFunction.
- std::unordered_map<std::string, Vector<uint8_t> > Traces;
-};
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_DATA_FLOW_TRACE
diff --git a/chromium/third_party/libFuzzer/src/FuzzerDefs.h b/chromium/third_party/libFuzzer/src/FuzzerDefs.h
deleted file mode 100644
index c3dccbcd86f..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerDefs.h
+++ /dev/null
@@ -1,201 +0,0 @@
-//===- FuzzerDefs.h - Internal header for the Fuzzer ------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Basic definitions.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_DEFS_H
-#define LLVM_FUZZER_DEFS_H
-
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-#include <string>
-#include <vector>
-#include <set>
-#include <memory>
-
-// Platform detection.
-#ifdef __linux__
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_FUCHSIA 0
-#define LIBFUZZER_LINUX 1
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 0
-#define LIBFUZZER_WINDOWS 0
-#elif __APPLE__
-#define LIBFUZZER_APPLE 1
-#define LIBFUZZER_FUCHSIA 0
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 0
-#define LIBFUZZER_WINDOWS 0
-#elif __NetBSD__
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_FUCHSIA 0
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_NETBSD 1
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 0
-#define LIBFUZZER_WINDOWS 0
-#elif __FreeBSD__
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_FUCHSIA 0
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 1
-#define LIBFUZZER_OPENBSD 0
-#define LIBFUZZER_WINDOWS 0
-#elif __OpenBSD__
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_FUCHSIA 0
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 1
-#define LIBFUZZER_WINDOWS 0
-#elif _WIN32
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_FUCHSIA 0
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 0
-#define LIBFUZZER_WINDOWS 1
-#elif __Fuchsia__
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_FUCHSIA 1
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 0
-#define LIBFUZZER_WINDOWS 0
-#else
-#error "Support for your platform has not been implemented"
-#endif
-
-#if defined(_MSC_VER) && !defined(__clang__)
-// MSVC compiler is being used.
-#define LIBFUZZER_MSVC 1
-#else
-#define LIBFUZZER_MSVC 0
-#endif
-
-#ifndef __has_attribute
-# define __has_attribute(x) 0
-#endif
-
-#define LIBFUZZER_POSIX \
- (LIBFUZZER_APPLE || LIBFUZZER_LINUX || LIBFUZZER_NETBSD || \
- LIBFUZZER_FREEBSD || LIBFUZZER_OPENBSD)
-
-#ifdef __x86_64
-# if __has_attribute(target)
-# define ATTRIBUTE_TARGET_POPCNT __attribute__((target("popcnt")))
-# else
-# define ATTRIBUTE_TARGET_POPCNT
-# endif
-#else
-# define ATTRIBUTE_TARGET_POPCNT
-#endif
-
-
-#ifdef __clang__ // avoid gcc warning.
-# if __has_attribute(no_sanitize)
-# define ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
-# else
-# define ATTRIBUTE_NO_SANITIZE_MEMORY
-# endif
-# define ALWAYS_INLINE __attribute__((always_inline))
-#else
-# define ATTRIBUTE_NO_SANITIZE_MEMORY
-# define ALWAYS_INLINE
-#endif // __clang__
-
-#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
-
-#if defined(__has_feature)
-# if __has_feature(address_sanitizer)
-# define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_ADDRESS
-# elif __has_feature(memory_sanitizer)
-# define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_MEMORY
-# else
-# define ATTRIBUTE_NO_SANITIZE_ALL
-# endif
-#else
-# define ATTRIBUTE_NO_SANITIZE_ALL
-#endif
-
-#if LIBFUZZER_WINDOWS
-#define ATTRIBUTE_INTERFACE __declspec(dllexport)
-// This is used for __sancov_lowest_stack which is needed for
-// -fsanitize-coverage=stack-depth. That feature is not yet available on
-// Windows, so make the symbol static to avoid linking errors.
-#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \
- __attribute__((tls_model("initial-exec"))) thread_local static
-#else
-#define ATTRIBUTE_INTERFACE __attribute__((visibility("default")))
-#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \
- ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec"))) thread_local
-#endif
-
-namespace fuzzer {
-
-template <class T> T Min(T a, T b) { return a < b ? a : b; }
-template <class T> T Max(T a, T b) { return a > b ? a : b; }
-
-class Random;
-class Dictionary;
-class DictionaryEntry;
-class MutationDispatcher;
-struct FuzzingOptions;
-class InputCorpus;
-struct InputInfo;
-struct ExternalFunctions;
-
-// Global interface to functions that may or may not be available.
-extern ExternalFunctions *EF;
-
-// We are using a custom allocator to give a different symbol name to STL
-// containers in order to avoid ODR violations.
-template<typename T>
- class fuzzer_allocator: public std::allocator<T> {
- public:
- fuzzer_allocator() = default;
-
- template<class U>
- fuzzer_allocator(const fuzzer_allocator<U>&) {}
-
- template<class Other>
- struct rebind { typedef fuzzer_allocator<Other> other; };
- };
-
-template<typename T>
-using Vector = std::vector<T, fuzzer_allocator<T>>;
-
-template<typename T>
-using Set = std::set<T, std::less<T>, fuzzer_allocator<T>>;
-
-typedef Vector<uint8_t> Unit;
-typedef Vector<Unit> UnitVector;
-typedef int (*UserCallback)(const uint8_t *Data, size_t Size);
-
-int FuzzerDriver(int *argc, char ***argv, UserCallback Callback);
-
-uint8_t *ExtraCountersBegin();
-uint8_t *ExtraCountersEnd();
-void ClearExtraCounters();
-
-extern bool RunningUserCallback;
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_DEFS_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerDictionary.h b/chromium/third_party/libFuzzer/src/FuzzerDictionary.h
deleted file mode 100644
index 0d9d91bcd2f..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerDictionary.h
+++ /dev/null
@@ -1,119 +0,0 @@
-//===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// fuzzer::Dictionary
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_DICTIONARY_H
-#define LLVM_FUZZER_DICTIONARY_H
-
-#include "FuzzerDefs.h"
-#include "FuzzerIO.h"
-#include "FuzzerUtil.h"
-#include <algorithm>
-#include <limits>
-
-namespace fuzzer {
-// A simple POD sized array of bytes.
-template <size_t kMaxSizeT> class FixedWord {
-public:
- static const size_t kMaxSize = kMaxSizeT;
- FixedWord() {}
- FixedWord(const uint8_t *B, uint8_t S) { Set(B, S); }
-
- void Set(const uint8_t *B, uint8_t S) {
- assert(S <= kMaxSize);
- memcpy(Data, B, S);
- Size = S;
- }
-
- bool operator==(const FixedWord<kMaxSize> &w) const {
- return Size == w.Size && 0 == memcmp(Data, w.Data, Size);
- }
-
- static size_t GetMaxSize() { return kMaxSize; }
- const uint8_t *data() const { return Data; }
- uint8_t size() const { return Size; }
-
-private:
- uint8_t Size = 0;
- uint8_t Data[kMaxSize];
-};
-
-typedef FixedWord<64> Word;
-
-class DictionaryEntry {
- public:
- DictionaryEntry() {}
- DictionaryEntry(Word W) : W(W) {}
- DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {}
- const Word &GetW() const { return W; }
-
- bool HasPositionHint() const { return PositionHint != std::numeric_limits<size_t>::max(); }
- size_t GetPositionHint() const {
- assert(HasPositionHint());
- return PositionHint;
- }
- void IncUseCount() { UseCount++; }
- void IncSuccessCount() { SuccessCount++; }
- size_t GetUseCount() const { return UseCount; }
- size_t GetSuccessCount() const {return SuccessCount; }
-
- void Print(const char *PrintAfter = "\n") {
- PrintASCII(W.data(), W.size());
- if (HasPositionHint())
- Printf("@%zd", GetPositionHint());
- Printf("%s", PrintAfter);
- }
-
-private:
- Word W;
- size_t PositionHint = std::numeric_limits<size_t>::max();
- size_t UseCount = 0;
- size_t SuccessCount = 0;
-};
-
-class Dictionary {
- public:
- static const size_t kMaxDictSize = 1 << 14;
-
- bool ContainsWord(const Word &W) const {
- return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) {
- return DE.GetW() == W;
- });
- }
- const DictionaryEntry *begin() const { return &DE[0]; }
- const DictionaryEntry *end() const { return begin() + Size; }
- DictionaryEntry & operator[] (size_t Idx) {
- assert(Idx < Size);
- return DE[Idx];
- }
- void push_back(DictionaryEntry DE) {
- if (Size < kMaxDictSize)
- this->DE[Size++] = DE;
- }
- void clear() { Size = 0; }
- bool empty() const { return Size == 0; }
- size_t size() const { return Size; }
-
-private:
- DictionaryEntry DE[kMaxDictSize];
- size_t Size = 0;
-};
-
-// Parses one dictionary entry.
-// If successful, write the enty to Unit and returns true,
-// otherwise returns false.
-bool ParseOneDictionaryEntry(const std::string &Str, Unit *U);
-// Parses the dictionary file, fills Units, returns true iff all lines
-// were parsed successfully.
-bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units);
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_DICTIONARY_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerDriver.cpp b/chromium/third_party/libFuzzer/src/FuzzerDriver.cpp
deleted file mode 100644
index 918a972fff3..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerDriver.cpp
+++ /dev/null
@@ -1,777 +0,0 @@
-//===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// FuzzerDriver and flag parsing.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerCommand.h"
-#include "FuzzerCorpus.h"
-#include "FuzzerIO.h"
-#include "FuzzerInterface.h"
-#include "FuzzerInternal.h"
-#include "FuzzerMutate.h"
-#include "FuzzerRandom.h"
-#include "FuzzerShmem.h"
-#include "FuzzerTracePC.h"
-#include <algorithm>
-#include <atomic>
-#include <chrono>
-#include <cstdlib>
-#include <cstring>
-#include <mutex>
-#include <string>
-#include <thread>
-
-// This function should be present in the libFuzzer so that the client
-// binary can test for its existence.
-extern "C" __attribute__((used)) void __libfuzzer_is_present() {}
-
-namespace fuzzer {
-
-// Program arguments.
-struct FlagDescription {
- const char *Name;
- const char *Description;
- int Default;
- int *IntFlag;
- const char **StrFlag;
- unsigned int *UIntFlag;
-};
-
-struct {
-#define FUZZER_DEPRECATED_FLAG(Name)
-#define FUZZER_FLAG_INT(Name, Default, Description) int Name;
-#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name;
-#define FUZZER_FLAG_STRING(Name, Description) const char *Name;
-#include "FuzzerFlags.def"
-#undef FUZZER_DEPRECATED_FLAG
-#undef FUZZER_FLAG_INT
-#undef FUZZER_FLAG_UNSIGNED
-#undef FUZZER_FLAG_STRING
-} Flags;
-
-static const FlagDescription FlagDescriptions [] {
-#define FUZZER_DEPRECATED_FLAG(Name) \
- {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr},
-#define FUZZER_FLAG_INT(Name, Default, Description) \
- {#Name, Description, Default, &Flags.Name, nullptr, nullptr},
-#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \
- {#Name, Description, static_cast<int>(Default), \
- nullptr, nullptr, &Flags.Name},
-#define FUZZER_FLAG_STRING(Name, Description) \
- {#Name, Description, 0, nullptr, &Flags.Name, nullptr},
-#include "FuzzerFlags.def"
-#undef FUZZER_DEPRECATED_FLAG
-#undef FUZZER_FLAG_INT
-#undef FUZZER_FLAG_UNSIGNED
-#undef FUZZER_FLAG_STRING
-};
-
-static const size_t kNumFlags =
- sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
-
-static Vector<std::string> *Inputs;
-static std::string *ProgName;
-
-static void PrintHelp() {
- Printf("Usage:\n");
- auto Prog = ProgName->c_str();
- Printf("\nTo run fuzzing pass 0 or more directories.\n");
- Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog);
-
- Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n");
- Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog);
-
- Printf("\nFlags: (strictly in form -flag=value)\n");
- size_t MaxFlagLen = 0;
- for (size_t F = 0; F < kNumFlags; F++)
- MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen);
-
- for (size_t F = 0; F < kNumFlags; F++) {
- const auto &D = FlagDescriptions[F];
- if (strstr(D.Description, "internal flag") == D.Description) continue;
- Printf(" %s", D.Name);
- for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
- Printf(" ");
- Printf("\t");
- Printf("%d\t%s\n", D.Default, D.Description);
- }
- Printf("\nFlags starting with '--' will be ignored and "
- "will be passed verbatim to subprocesses.\n");
-}
-
-static const char *FlagValue(const char *Param, const char *Name) {
- size_t Len = strlen(Name);
- if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
- Param[Len + 1] == '=')
- return &Param[Len + 2];
- return nullptr;
-}
-
-// Avoid calling stol as it triggers a bug in clang/glibc build.
-static long MyStol(const char *Str) {
- long Res = 0;
- long Sign = 1;
- if (*Str == '-') {
- Str++;
- Sign = -1;
- }
- for (size_t i = 0; Str[i]; i++) {
- char Ch = Str[i];
- if (Ch < '0' || Ch > '9')
- return Res;
- Res = Res * 10 + (Ch - '0');
- }
- return Res * Sign;
-}
-
-static bool ParseOneFlag(const char *Param) {
- if (Param[0] != '-') return false;
- if (Param[1] == '-') {
- static bool PrintedWarning = false;
- if (!PrintedWarning) {
- PrintedWarning = true;
- Printf("INFO: libFuzzer ignores flags that start with '--'\n");
- }
- for (size_t F = 0; F < kNumFlags; F++)
- if (FlagValue(Param + 1, FlagDescriptions[F].Name))
- Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1);
- return true;
- }
- for (size_t F = 0; F < kNumFlags; F++) {
- const char *Name = FlagDescriptions[F].Name;
- const char *Str = FlagValue(Param, Name);
- if (Str) {
- if (FlagDescriptions[F].IntFlag) {
- int Val = MyStol(Str);
- *FlagDescriptions[F].IntFlag = Val;
- if (Flags.verbosity >= 2)
- Printf("Flag: %s %d\n", Name, Val);
- return true;
- } else if (FlagDescriptions[F].UIntFlag) {
- unsigned int Val = std::stoul(Str);
- *FlagDescriptions[F].UIntFlag = Val;
- if (Flags.verbosity >= 2)
- Printf("Flag: %s %u\n", Name, Val);
- return true;
- } else if (FlagDescriptions[F].StrFlag) {
- *FlagDescriptions[F].StrFlag = Str;
- if (Flags.verbosity >= 2)
- Printf("Flag: %s %s\n", Name, Str);
- return true;
- } else { // Deprecated flag.
- Printf("Flag: %s: deprecated, don't use\n", Name);
- return true;
- }
- }
- }
- Printf("\n\nWARNING: unrecognized flag '%s'; "
- "use -help=1 to list all flags\n\n", Param);
- return true;
-}
-
-// We don't use any library to minimize dependencies.
-static void ParseFlags(const Vector<std::string> &Args) {
- for (size_t F = 0; F < kNumFlags; F++) {
- if (FlagDescriptions[F].IntFlag)
- *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default;
- if (FlagDescriptions[F].UIntFlag)
- *FlagDescriptions[F].UIntFlag =
- static_cast<unsigned int>(FlagDescriptions[F].Default);
- if (FlagDescriptions[F].StrFlag)
- *FlagDescriptions[F].StrFlag = nullptr;
- }
- Inputs = new Vector<std::string>;
- for (size_t A = 1; A < Args.size(); A++) {
- if (ParseOneFlag(Args[A].c_str())) {
- if (Flags.ignore_remaining_args)
- break;
- continue;
- }
- Inputs->push_back(Args[A]);
- }
-}
-
-static std::mutex Mu;
-
-static void PulseThread() {
- while (true) {
- SleepSeconds(600);
- std::lock_guard<std::mutex> Lock(Mu);
- Printf("pulse...\n");
- }
-}
-
-static void WorkerThread(const Command &BaseCmd, std::atomic<unsigned> *Counter,
- unsigned NumJobs, std::atomic<bool> *HasErrors) {
- while (true) {
- unsigned C = (*Counter)++;
- if (C >= NumJobs) break;
- std::string Log = "fuzz-" + std::to_string(C) + ".log";
- Command Cmd(BaseCmd);
- Cmd.setOutputFile(Log);
- Cmd.combineOutAndErr();
- if (Flags.verbosity) {
- std::string CommandLine = Cmd.toString();
- Printf("%s\n", CommandLine.c_str());
- }
- int ExitCode = ExecuteCommand(Cmd);
- if (ExitCode != 0)
- *HasErrors = true;
- std::lock_guard<std::mutex> Lock(Mu);
- Printf("================== Job %u exited with exit code %d ============\n",
- C, ExitCode);
- fuzzer::CopyFileToErr(Log);
- }
-}
-
-std::string CloneArgsWithoutX(const Vector<std::string> &Args,
- const char *X1, const char *X2) {
- std::string Cmd;
- for (auto &S : Args) {
- if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2))
- continue;
- Cmd += S + " ";
- }
- return Cmd;
-}
-
-static int RunInMultipleProcesses(const Vector<std::string> &Args,
- unsigned NumWorkers, unsigned NumJobs) {
- std::atomic<unsigned> Counter(0);
- std::atomic<bool> HasErrors(false);
- Command Cmd(Args);
- Cmd.removeFlag("jobs");
- Cmd.removeFlag("workers");
- Vector<std::thread> V;
- std::thread Pulse(PulseThread);
- Pulse.detach();
- for (unsigned i = 0; i < NumWorkers; i++)
- V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs, &HasErrors));
- for (auto &T : V)
- T.join();
- return HasErrors ? 1 : 0;
-}
-
-static void RssThread(Fuzzer *F, size_t RssLimitMb) {
- while (true) {
- SleepSeconds(1);
- size_t Peak = GetPeakRSSMb();
- if (Peak > RssLimitMb)
- F->RssLimitCallback();
- }
-}
-
-static void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
- if (!RssLimitMb) return;
- std::thread T(RssThread, F, RssLimitMb);
- T.detach();
-}
-
-int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
- Unit U = FileToVector(InputFilePath);
- if (MaxLen && MaxLen < U.size())
- U.resize(MaxLen);
- F->ExecuteCallback(U.data(), U.size());
- F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
- return 0;
-}
-
-static bool AllInputsAreFiles() {
- if (Inputs->empty()) return false;
- for (auto &Path : *Inputs)
- if (!IsFile(Path))
- return false;
- return true;
-}
-
-static std::string GetDedupTokenFromFile(const std::string &Path) {
- auto S = FileToString(Path);
- auto Beg = S.find("DEDUP_TOKEN:");
- if (Beg == std::string::npos)
- return "";
- auto End = S.find('\n', Beg);
- if (End == std::string::npos)
- return "";
- return S.substr(Beg, End - Beg);
-}
-
-int CleanseCrashInput(const Vector<std::string> &Args,
- const FuzzingOptions &Options) {
- if (Inputs->size() != 1 || !Flags.exact_artifact_path) {
- Printf("ERROR: -cleanse_crash should be given one input file and"
- " -exact_artifact_path\n");
- exit(1);
- }
- std::string InputFilePath = Inputs->at(0);
- std::string OutputFilePath = Flags.exact_artifact_path;
- Command Cmd(Args);
- Cmd.removeFlag("cleanse_crash");
-
- assert(Cmd.hasArgument(InputFilePath));
- Cmd.removeArgument(InputFilePath);
-
- auto LogFilePath = DirPlusFile(
- TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt");
- auto TmpFilePath = DirPlusFile(
- TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".repro");
- Cmd.addArgument(TmpFilePath);
- Cmd.setOutputFile(LogFilePath);
- Cmd.combineOutAndErr();
-
- std::string CurrentFilePath = InputFilePath;
- auto U = FileToVector(CurrentFilePath);
- size_t Size = U.size();
-
- const Vector<uint8_t> ReplacementBytes = {' ', 0xff};
- for (int NumAttempts = 0; NumAttempts < 5; NumAttempts++) {
- bool Changed = false;
- for (size_t Idx = 0; Idx < Size; Idx++) {
- Printf("CLEANSE[%d]: Trying to replace byte %zd of %zd\n", NumAttempts,
- Idx, Size);
- uint8_t OriginalByte = U[Idx];
- if (ReplacementBytes.end() != std::find(ReplacementBytes.begin(),
- ReplacementBytes.end(),
- OriginalByte))
- continue;
- for (auto NewByte : ReplacementBytes) {
- U[Idx] = NewByte;
- WriteToFile(U, TmpFilePath);
- auto ExitCode = ExecuteCommand(Cmd);
- RemoveFile(TmpFilePath);
- if (!ExitCode) {
- U[Idx] = OriginalByte;
- } else {
- Changed = true;
- Printf("CLEANSE: Replaced byte %zd with 0x%x\n", Idx, NewByte);
- WriteToFile(U, OutputFilePath);
- break;
- }
- }
- }
- if (!Changed) break;
- }
- RemoveFile(LogFilePath);
- return 0;
-}
-
-int MinimizeCrashInput(const Vector<std::string> &Args,
- const FuzzingOptions &Options) {
- if (Inputs->size() != 1) {
- Printf("ERROR: -minimize_crash should be given one input file\n");
- exit(1);
- }
- std::string InputFilePath = Inputs->at(0);
- Command BaseCmd(Args);
- BaseCmd.removeFlag("minimize_crash");
- BaseCmd.removeFlag("exact_artifact_path");
- assert(BaseCmd.hasArgument(InputFilePath));
- BaseCmd.removeArgument(InputFilePath);
- if (Flags.runs <= 0 && Flags.max_total_time == 0) {
- Printf("INFO: you need to specify -runs=N or "
- "-max_total_time=N with -minimize_crash=1\n"
- "INFO: defaulting to -max_total_time=600\n");
- BaseCmd.addFlag("max_total_time", "600");
- }
-
- auto LogFilePath = DirPlusFile(
- TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt");
- BaseCmd.setOutputFile(LogFilePath);
- BaseCmd.combineOutAndErr();
-
- std::string CurrentFilePath = InputFilePath;
- while (true) {
- Unit U = FileToVector(CurrentFilePath);
- Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n",
- CurrentFilePath.c_str(), U.size());
-
- Command Cmd(BaseCmd);
- Cmd.addArgument(CurrentFilePath);
-
- std::string CommandLine = Cmd.toString();
- Printf("CRASH_MIN: executing: %s\n", CommandLine.c_str());
- int ExitCode = ExecuteCommand(Cmd);
- if (ExitCode == 0) {
- Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str());
- exit(1);
- }
- Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize "
- "it further\n",
- CurrentFilePath.c_str(), U.size());
- auto DedupToken1 = GetDedupTokenFromFile(LogFilePath);
- if (!DedupToken1.empty())
- Printf("CRASH_MIN: DedupToken1: %s\n", DedupToken1.c_str());
-
- std::string ArtifactPath =
- Flags.exact_artifact_path
- ? Flags.exact_artifact_path
- : Options.ArtifactPrefix + "minimized-from-" + Hash(U);
- Cmd.addFlag("minimize_crash_internal_step", "1");
- Cmd.addFlag("exact_artifact_path", ArtifactPath);
- CommandLine = Cmd.toString();
- Printf("CRASH_MIN: executing: %s\n", CommandLine.c_str());
- ExitCode = ExecuteCommand(Cmd);
- CopyFileToErr(LogFilePath);
- if (ExitCode == 0) {
- if (Flags.exact_artifact_path) {
- CurrentFilePath = Flags.exact_artifact_path;
- WriteToFile(U, CurrentFilePath);
- }
- Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n",
- CurrentFilePath.c_str(), U.size());
- break;
- }
- auto DedupToken2 = GetDedupTokenFromFile(LogFilePath);
- if (!DedupToken2.empty())
- Printf("CRASH_MIN: DedupToken2: %s\n", DedupToken2.c_str());
-
- if (DedupToken1 != DedupToken2) {
- if (Flags.exact_artifact_path) {
- CurrentFilePath = Flags.exact_artifact_path;
- WriteToFile(U, CurrentFilePath);
- }
- Printf("CRASH_MIN: mismatch in dedup tokens"
- " (looks like a different bug). Won't minimize further\n");
- break;
- }
-
- CurrentFilePath = ArtifactPath;
- Printf("*********************************\n");
- }
- RemoveFile(LogFilePath);
- return 0;
-}
-
-int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
- assert(Inputs->size() == 1);
- std::string InputFilePath = Inputs->at(0);
- Unit U = FileToVector(InputFilePath);
- Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size());
- if (U.size() < 2) {
- Printf("INFO: The input is small enough, exiting\n");
- exit(0);
- }
- F->SetMaxInputLen(U.size());
- F->SetMaxMutationLen(U.size() - 1);
- F->MinimizeCrashLoop(U);
- Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n");
- exit(0);
- return 0;
-}
-
-int AnalyzeDictionary(Fuzzer *F, const Vector<Unit>& Dict,
- UnitVector& Corpus) {
- Printf("Started dictionary minimization (up to %d tests)\n",
- Dict.size() * Corpus.size() * 2);
-
- // Scores and usage count for each dictionary unit.
- Vector<int> Scores(Dict.size());
- Vector<int> Usages(Dict.size());
-
- Vector<size_t> InitialFeatures;
- Vector<size_t> ModifiedFeatures;
- for (auto &C : Corpus) {
- // Get coverage for the testcase without modifications.
- F->ExecuteCallback(C.data(), C.size());
- InitialFeatures.clear();
- TPC.CollectFeatures([&](size_t Feature) {
- InitialFeatures.push_back(Feature);
- });
-
- for (size_t i = 0; i < Dict.size(); ++i) {
- Vector<uint8_t> Data = C;
- auto StartPos = std::search(Data.begin(), Data.end(),
- Dict[i].begin(), Dict[i].end());
- // Skip dictionary unit, if the testcase does not contain it.
- if (StartPos == Data.end())
- continue;
-
- ++Usages[i];
- while (StartPos != Data.end()) {
- // Replace all occurrences of dictionary unit in the testcase.
- auto EndPos = StartPos + Dict[i].size();
- for (auto It = StartPos; It != EndPos; ++It)
- *It ^= 0xFF;
-
- StartPos = std::search(EndPos, Data.end(),
- Dict[i].begin(), Dict[i].end());
- }
-
- // Get coverage for testcase with masked occurrences of dictionary unit.
- F->ExecuteCallback(Data.data(), Data.size());
- ModifiedFeatures.clear();
- TPC.CollectFeatures([&](size_t Feature) {
- ModifiedFeatures.push_back(Feature);
- });
-
- if (InitialFeatures == ModifiedFeatures)
- --Scores[i];
- else
- Scores[i] += 2;
- }
- }
-
- Printf("###### Useless dictionary elements. ######\n");
- for (size_t i = 0; i < Dict.size(); ++i) {
- // Dictionary units with positive score are treated as useful ones.
- if (Scores[i] > 0)
- continue;
-
- Printf("\"");
- PrintASCII(Dict[i].data(), Dict[i].size(), "\"");
- Printf(" # Score: %d, Used: %d\n", Scores[i], Usages[i]);
- }
- Printf("###### End of useless dictionary elements. ######\n");
- return 0;
-}
-
-int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
- using namespace fuzzer;
- assert(argc && argv && "Argument pointers cannot be nullptr");
- std::string Argv0((*argv)[0]);
- EF = new ExternalFunctions();
- if (EF->LLVMFuzzerInitialize)
- EF->LLVMFuzzerInitialize(argc, argv);
- if (EF->__msan_scoped_disable_interceptor_checks)
- EF->__msan_scoped_disable_interceptor_checks();
- const Vector<std::string> Args(*argv, *argv + *argc);
- assert(!Args.empty());
- ProgName = new std::string(Args[0]);
- if (Argv0 != *ProgName) {
- Printf("ERROR: argv[0] has been modified in LLVMFuzzerInitialize\n");
- exit(1);
- }
- ParseFlags(Args);
- if (Flags.help) {
- PrintHelp();
- return 0;
- }
-
- if (Flags.close_fd_mask & 2)
- DupAndCloseStderr();
- if (Flags.close_fd_mask & 1)
- CloseStdout();
-
- if (Flags.jobs > 0 && Flags.workers == 0) {
- Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs);
- if (Flags.workers > 1)
- Printf("Running %u workers\n", Flags.workers);
- }
-
- if (Flags.workers > 0 && Flags.jobs > 0)
- return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs);
-
- FuzzingOptions Options;
- Options.Verbosity = Flags.verbosity;
- Options.MaxLen = Flags.max_len;
- Options.LenControl = Flags.len_control;
- Options.UnitTimeoutSec = Flags.timeout;
- Options.ErrorExitCode = Flags.error_exitcode;
- Options.TimeoutExitCode = Flags.timeout_exitcode;
- Options.MaxTotalTimeSec = Flags.max_total_time;
- Options.DoCrossOver = Flags.cross_over;
- Options.MutateDepth = Flags.mutate_depth;
- Options.ReduceDepth = Flags.reduce_depth;
- Options.UseCounters = Flags.use_counters;
- Options.UseMemmem = Flags.use_memmem;
- Options.UseCmp = Flags.use_cmp;
- Options.UseValueProfile = Flags.use_value_profile;
- Options.Shrink = Flags.shrink;
- Options.ReduceInputs = Flags.reduce_inputs;
- Options.ShuffleAtStartUp = Flags.shuffle;
- Options.PreferSmall = Flags.prefer_small;
- Options.ReloadIntervalSec = Flags.reload;
- Options.OnlyASCII = Flags.only_ascii;
- Options.DetectLeaks = Flags.detect_leaks;
- Options.PurgeAllocatorIntervalSec = Flags.purge_allocator_interval;
- Options.TraceMalloc = Flags.trace_malloc;
- Options.RssLimitMb = Flags.rss_limit_mb;
- Options.MallocLimitMb = Flags.malloc_limit_mb;
- if (!Options.MallocLimitMb)
- Options.MallocLimitMb = Options.RssLimitMb;
- if (Flags.runs >= 0)
- Options.MaxNumberOfRuns = Flags.runs;
- if (!Inputs->empty() && !Flags.minimize_crash_internal_step)
- Options.OutputCorpus = (*Inputs)[0];
- Options.ReportSlowUnits = Flags.report_slow_units;
- if (Flags.artifact_prefix)
- Options.ArtifactPrefix = Flags.artifact_prefix;
- if (Flags.exact_artifact_path)
- Options.ExactArtifactPath = Flags.exact_artifact_path;
- Vector<Unit> Dictionary;
- if (Flags.dict)
- if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary))
- return 1;
- if (Flags.verbosity > 0 && !Dictionary.empty())
- Printf("Dictionary: %zd entries\n", Dictionary.size());
- bool DoPlainRun = AllInputsAreFiles();
- Options.SaveArtifacts =
- !DoPlainRun || Flags.minimize_crash_internal_step;
- Options.PrintNewCovPcs = Flags.print_pcs;
- Options.PrintNewCovFuncs = Flags.print_funcs;
- Options.PrintFinalStats = Flags.print_final_stats;
- Options.PrintCorpusStats = Flags.print_corpus_stats;
- Options.PrintCoverage = Flags.print_coverage;
- Options.PrintUnstableStats = Flags.print_unstable_stats;
- if (Flags.handle_unstable == TracePC::MinUnstable ||
- Flags.handle_unstable == TracePC::ZeroUnstable)
- Options.HandleUnstable = Flags.handle_unstable;
- Options.DumpCoverage = Flags.dump_coverage;
- if (Flags.exit_on_src_pos)
- Options.ExitOnSrcPos = Flags.exit_on_src_pos;
- if (Flags.exit_on_item)
- Options.ExitOnItem = Flags.exit_on_item;
- if (Flags.focus_function)
- Options.FocusFunction = Flags.focus_function;
- if (Flags.data_flow_trace)
- Options.DataFlowTrace = Flags.data_flow_trace;
-
- unsigned Seed = Flags.seed;
- // Initialize Seed.
- if (Seed == 0)
- Seed =
- std::chrono::system_clock::now().time_since_epoch().count() + GetPid();
- if (Flags.verbosity)
- Printf("INFO: Seed: %u\n", Seed);
-
- Random Rand(Seed);
- auto *MD = new MutationDispatcher(Rand, Options);
- auto *Corpus = new InputCorpus(Options.OutputCorpus);
- auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
-
- for (auto &U: Dictionary)
- if (U.size() <= Word::GetMaxSize())
- MD->AddWordToManualDictionary(Word(U.data(), U.size()));
-
- StartRssThread(F, Flags.rss_limit_mb);
-
- Options.HandleAbrt = Flags.handle_abrt;
- Options.HandleBus = Flags.handle_bus;
- Options.HandleFpe = Flags.handle_fpe;
- Options.HandleIll = Flags.handle_ill;
- Options.HandleInt = Flags.handle_int;
- Options.HandleSegv = Flags.handle_segv;
- Options.HandleTerm = Flags.handle_term;
- Options.HandleXfsz = Flags.handle_xfsz;
- Options.HandleUsr1 = Flags.handle_usr1;
- Options.HandleUsr2 = Flags.handle_usr2;
- SetSignalHandler(Options);
-
- std::atexit(Fuzzer::StaticExitCallback);
-
- if (Flags.minimize_crash)
- return MinimizeCrashInput(Args, Options);
-
- if (Flags.minimize_crash_internal_step)
- return MinimizeCrashInputInternalStep(F, Corpus);
-
- if (Flags.cleanse_crash)
- return CleanseCrashInput(Args, Options);
-
-#if 0 // deprecated, to be removed.
- if (auto Name = Flags.run_equivalence_server) {
- SMR.Destroy(Name);
- if (!SMR.Create(Name)) {
- Printf("ERROR: can't create shared memory region\n");
- return 1;
- }
- Printf("INFO: EQUIVALENCE SERVER UP\n");
- while (true) {
- SMR.WaitClient();
- size_t Size = SMR.ReadByteArraySize();
- SMR.WriteByteArray(nullptr, 0);
- const Unit tmp(SMR.GetByteArray(), SMR.GetByteArray() + Size);
- F->ExecuteCallback(tmp.data(), tmp.size());
- SMR.PostServer();
- }
- return 0;
- }
-
- if (auto Name = Flags.use_equivalence_server) {
- if (!SMR.Open(Name)) {
- Printf("ERROR: can't open shared memory region\n");
- return 1;
- }
- Printf("INFO: EQUIVALENCE CLIENT UP\n");
- }
-#endif
-
- if (DoPlainRun) {
- Options.SaveArtifacts = false;
- int Runs = std::max(1, Flags.runs);
- Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(),
- Inputs->size(), Runs);
- for (auto &Path : *Inputs) {
- auto StartTime = system_clock::now();
- Printf("Running: %s\n", Path.c_str());
- for (int Iter = 0; Iter < Runs; Iter++)
- RunOneTest(F, Path.c_str(), Options.MaxLen);
- auto StopTime = system_clock::now();
- auto MS = duration_cast<milliseconds>(StopTime - StartTime).count();
- Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS);
- }
- Printf("***\n"
- "*** NOTE: fuzzing was not performed, you have only\n"
- "*** executed the target code on a fixed set of inputs.\n"
- "***\n");
- F->PrintFinalStats();
- exit(0);
- }
-
- if (Flags.merge) {
- F->CrashResistantMerge(Args, *Inputs,
- Flags.load_coverage_summary,
- Flags.save_coverage_summary,
- Flags.merge_control_file);
- exit(0);
- }
-
- if (Flags.merge_inner) {
- const size_t kDefaultMaxMergeLen = 1 << 20;
- if (Options.MaxLen == 0)
- F->SetMaxInputLen(kDefaultMaxMergeLen);
- assert(Flags.merge_control_file);
- F->CrashResistantMergeInternalStep(Flags.merge_control_file);
- exit(0);
- }
-
- if (Flags.analyze_dict) {
- size_t MaxLen = INT_MAX; // Large max length.
- UnitVector InitialCorpus;
- for (auto &Inp : *Inputs) {
- Printf("Loading corpus dir: %s\n", Inp.c_str());
- ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr,
- MaxLen, /*ExitOnError=*/false);
- }
-
- if (Dictionary.empty() || Inputs->empty()) {
- Printf("ERROR: can't analyze dict without dict and corpus provided\n");
- return 1;
- }
- if (AnalyzeDictionary(F, Dictionary, InitialCorpus)) {
- Printf("Dictionary analysis failed\n");
- exit(1);
- }
- Printf("Dictionary analysis succeeded\n");
- exit(0);
- }
-
- F->Loop(*Inputs);
-
- if (Flags.verbosity)
- Printf("Done %zd runs in %zd second(s)\n", F->getTotalNumberOfRuns(),
- F->secondsSinceProcessStartUp());
- F->PrintFinalStats();
-
- exit(0); // Don't let F destroy itself.
-}
-
-// Storage for global ExternalFunctions object.
-ExternalFunctions *EF = nullptr;
-
-} // namespace fuzzer
diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.def b/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.def
deleted file mode 100644
index 8bfffdde56d..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.def
+++ /dev/null
@@ -1,51 +0,0 @@
-//===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// This defines the external function pointers that
-// ``fuzzer::ExternalFunctions`` should contain and try to initialize. The
-// EXT_FUNC macro must be defined at the point of inclusion. The signature of
-// the macro is:
-//
-// EXT_FUNC(<name>, <return_type>, <function_signature>, <warn_if_missing>)
-//===----------------------------------------------------------------------===//
-
-// Optional user functions
-EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false);
-EXT_FUNC(LLVMFuzzerCustomMutator, size_t,
- (uint8_t * Data, size_t Size, size_t MaxSize, unsigned int Seed),
- false);
-EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t,
- (const uint8_t * Data1, size_t Size1,
- const uint8_t * Data2, size_t Size2,
- uint8_t * Out, size_t MaxOutSize, unsigned int Seed),
- false);
-
-// Sanitizer functions
-EXT_FUNC(__lsan_enable, void, (), false);
-EXT_FUNC(__lsan_disable, void, (), false);
-EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false);
-EXT_FUNC(__sanitizer_acquire_crash_state, bool, (), true);
-EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int,
- (void (*malloc_hook)(const volatile void *, size_t),
- void (*free_hook)(const volatile void *)),
- false);
-EXT_FUNC(__sanitizer_purge_allocator, void, (), false);
-EXT_FUNC(__sanitizer_print_memory_profile, int, (size_t, size_t), false);
-EXT_FUNC(__sanitizer_print_stack_trace, void, (), true);
-EXT_FUNC(__sanitizer_symbolize_pc, void,
- (void *, const char *fmt, char *out_buf, size_t out_buf_size), false);
-EXT_FUNC(__sanitizer_get_module_and_offset_for_pc, int,
- (void *pc, char *module_path,
- size_t module_path_len,void **pc_offset), false);
-EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true);
-EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false);
-EXT_FUNC(__sanitizer_dump_coverage, void, (const uintptr_t *, uintptr_t),
- false);
-EXT_FUNC(__msan_scoped_disable_interceptor_checks, void, (), false);
-EXT_FUNC(__msan_scoped_enable_interceptor_checks, void, (), false);
-EXT_FUNC(__msan_unpoison, void, (const volatile void *, size_t size), false);
diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.h b/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.h
deleted file mode 100644
index 2672a385478..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Defines an interface to (possibly optional) functions.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_EXT_FUNCTIONS_H
-#define LLVM_FUZZER_EXT_FUNCTIONS_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-namespace fuzzer {
-
-struct ExternalFunctions {
- // Initialize function pointers. Functions that are not available will be set
- // to nullptr. Do not call this constructor before ``main()`` has been
- // entered.
- ExternalFunctions();
-
-#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
- RETURN_TYPE(*NAME) FUNC_SIG = nullptr
-
-#include "FuzzerExtFunctions.def"
-
-#undef EXT_FUNC
-};
-} // namespace fuzzer
-
-#endif
diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsDlsym.cpp b/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsDlsym.cpp
deleted file mode 100644
index 06bddd5de38..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsDlsym.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Implementation for operating systems that support dlsym(). We only use it on
-// Apple platforms for now. We don't use this approach on Linux because it
-// requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker.
-// That is a complication we don't wish to expose to clients right now.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_APPLE
-
-#include "FuzzerExtFunctions.h"
-#include "FuzzerIO.h"
-#include <dlfcn.h>
-
-using namespace fuzzer;
-
-template <typename T>
-static T GetFnPtr(const char *FnName, bool WarnIfMissing) {
- dlerror(); // Clear any previous errors.
- void *Fn = dlsym(RTLD_DEFAULT, FnName);
- if (Fn == nullptr) {
- if (WarnIfMissing) {
- const char *ErrorMsg = dlerror();
- Printf("WARNING: Failed to find function \"%s\".", FnName);
- if (ErrorMsg)
- Printf(" Reason %s.", ErrorMsg);
- Printf("\n");
- }
- }
- return reinterpret_cast<T>(Fn);
-}
-
-namespace fuzzer {
-
-ExternalFunctions::ExternalFunctions() {
-#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
- this->NAME = GetFnPtr<decltype(ExternalFunctions::NAME)>(#NAME, WARN)
-
-#include "FuzzerExtFunctions.def"
-
-#undef EXT_FUNC
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_APPLE
diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWeak.cpp b/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWeak.cpp
deleted file mode 100644
index 6a6ef4932f4..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWeak.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Implementation for Linux. This relies on the linker's support for weak
-// symbols. We don't use this approach on Apple platforms because it requires
-// clients of LibFuzzer to pass ``-U _<symbol_name>`` to the linker to allow
-// weak symbols to be undefined. That is a complication we don't want to expose
-// to clients right now.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FUCHSIA || \
- LIBFUZZER_FREEBSD || LIBFUZZER_OPENBSD
-
-#include "FuzzerExtFunctions.h"
-#include "FuzzerIO.h"
-
-extern "C" {
-// Declare these symbols as weak to allow them to be optionally defined.
-#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
- __attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG
-
-#include "FuzzerExtFunctions.def"
-
-#undef EXT_FUNC
-}
-
-using namespace fuzzer;
-
-static void CheckFnPtr(void *FnPtr, const char *FnName, bool WarnIfMissing) {
- if (FnPtr == nullptr && WarnIfMissing) {
- Printf("WARNING: Failed to find function \"%s\".\n", FnName);
- }
-}
-
-namespace fuzzer {
-
-ExternalFunctions::ExternalFunctions() {
-#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
- this->NAME = ::NAME; \
- CheckFnPtr(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(::NAME)), \
- #NAME, WARN);
-
-#include "FuzzerExtFunctions.def"
-
-#undef EXT_FUNC
-}
-
-} // namespace fuzzer
-
-#endif
diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWindows.cpp b/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWindows.cpp
deleted file mode 100644
index b01871439ca..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWindows.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//=== FuzzerExtWindows.cpp - Interface to external functions --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Implementation of FuzzerExtFunctions for Windows. Uses alternatename when
-// compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately
-// the method each compiler supports is not supported by the other.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_WINDOWS
-
-#include "FuzzerExtFunctions.h"
-#include "FuzzerIO.h"
-
-using namespace fuzzer;
-
-// Intermediate macro to ensure the parameter is expanded before stringified.
-#define STRINGIFY_(A) #A
-#define STRINGIFY(A) STRINGIFY_(A)
-
-#if LIBFUZZER_MSVC
-// Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
-#if defined(_M_IX86) || defined(__i386__)
-#define WIN_SYM_PREFIX "_"
-#else
-#define WIN_SYM_PREFIX
-#endif
-
-// Declare external functions as having alternativenames, so that we can
-// determine if they are not defined.
-#define EXTERNAL_FUNC(Name, Default) \
- __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \
- Name) "=" WIN_SYM_PREFIX STRINGIFY(Default)))
-#else
-// Declare external functions as weak to allow them to default to a specified
-// function if not defined explicitly. We must use weak symbols because clang's
-// support for alternatename is not 100%, see
-// https://bugs.llvm.org/show_bug.cgi?id=40218 for more details.
-#define EXTERNAL_FUNC(Name, Default) \
- __attribute__((weak, alias(STRINGIFY(Default))))
-#endif // LIBFUZZER_MSVC
-
-extern "C" {
-#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
- RETURN_TYPE NAME##Def FUNC_SIG { \
- Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \
- exit(1); \
- } \
- EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG;
-
-#include "FuzzerExtFunctions.def"
-
-#undef EXT_FUNC
-}
-
-template <typename T>
-static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) {
- if (Fun == FunDef) {
- if (WarnIfMissing)
- Printf("WARNING: Failed to find function \"%s\".\n", FnName);
- return nullptr;
- }
- return Fun;
-}
-
-namespace fuzzer {
-
-ExternalFunctions::ExternalFunctions() {
-#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
- this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN);
-
-#include "FuzzerExtFunctions.def"
-
-#undef EXT_FUNC
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_WINDOWS
diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtraCounters.cpp b/chromium/third_party/libFuzzer/src/FuzzerExtraCounters.cpp
deleted file mode 100644
index c99cd89be29..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerExtraCounters.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Extra coverage counters defined by user code.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerDefs.h"
-
-#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \
- LIBFUZZER_OPENBSD
-__attribute__((weak)) extern uint8_t __start___libfuzzer_extra_counters;
-__attribute__((weak)) extern uint8_t __stop___libfuzzer_extra_counters;
-
-namespace fuzzer {
-uint8_t *ExtraCountersBegin() { return &__start___libfuzzer_extra_counters; }
-uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; }
-ATTRIBUTE_NO_SANITIZE_ALL
-void ClearExtraCounters() { // hand-written memset, don't asan-ify.
- uintptr_t *Beg = reinterpret_cast<uintptr_t*>(ExtraCountersBegin());
- uintptr_t *End = reinterpret_cast<uintptr_t*>(ExtraCountersEnd());
- for (; Beg < End; Beg++) {
- *Beg = 0;
- __asm__ __volatile__("" : : : "memory");
- }
-}
-
-} // namespace fuzzer
-
-#else
-// TODO: implement for other platforms.
-namespace fuzzer {
-uint8_t *ExtraCountersBegin() { return nullptr; }
-uint8_t *ExtraCountersEnd() { return nullptr; }
-void ClearExtraCounters() {}
-} // namespace fuzzer
-
-#endif
diff --git a/chromium/third_party/libFuzzer/src/FuzzerFlags.def b/chromium/third_party/libFuzzer/src/FuzzerFlags.def
deleted file mode 100644
index 9e212ef656d..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerFlags.def
+++ /dev/null
@@ -1,164 +0,0 @@
-//===- FuzzerFlags.def - Run-time flags -------------------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Flags. FUZZER_FLAG_INT/FUZZER_FLAG_STRING macros should be defined at the
-// point of inclusion. We are not using any flag parsing library for better
-// portability and independence.
-//===----------------------------------------------------------------------===//
-FUZZER_FLAG_INT(verbosity, 1, "Verbosity level.")
-FUZZER_FLAG_UNSIGNED(seed, 0, "Random seed. If 0, seed is generated.")
-FUZZER_FLAG_INT(runs, -1,
- "Number of individual test runs (-1 for infinite runs).")
-FUZZER_FLAG_INT(max_len, 0, "Maximum length of the test input. "
- "If 0, libFuzzer tries to guess a good value based on the corpus "
- "and reports it. ")
-FUZZER_FLAG_INT(len_control, 100, "Try generating small inputs first, "
- "then try larger inputs over time. Specifies the rate at which the length "
- "limit is increased (smaller == faster). If 0, immediately try inputs with "
- "size up to max_len.")
-FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.")
-FUZZER_FLAG_INT(mutate_depth, 5,
- "Apply this number of consecutive mutations to each input.")
-FUZZER_FLAG_INT(reduce_depth, 0, "Experimental/internal. "
- "Reduce depth if mutations lose unique features")
-FUZZER_FLAG_INT(shuffle, 1, "Shuffle inputs at startup")
-FUZZER_FLAG_INT(prefer_small, 1,
- "If 1, always prefer smaller inputs during the corpus shuffle.")
-FUZZER_FLAG_INT(
- timeout, 1200,
- "Timeout in seconds (if positive). "
- "If one unit runs more than this number of seconds the process will abort.")
-FUZZER_FLAG_INT(error_exitcode, 77, "When libFuzzer itself reports a bug "
- "this exit code will be used.")
-FUZZER_FLAG_INT(timeout_exitcode, 77, "When libFuzzer reports a timeout "
- "this exit code will be used.")
-FUZZER_FLAG_INT(max_total_time, 0, "If positive, indicates the maximal total "
- "time in seconds to run the fuzzer.")
-FUZZER_FLAG_INT(help, 0, "Print help.")
-FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be "
- "merged into the 1-st corpus. Only interesting units will be taken. "
- "This flag can be used to minimize a corpus.")
-FUZZER_FLAG_STRING(merge_inner, "internal flag")
-FUZZER_FLAG_STRING(merge_control_file,
- "Specify a control file used for the merge process. "
- "If a merge process gets killed it tries to leave this file "
- "in a state suitable for resuming the merge. "
- "By default a temporary file will be used.")
-FUZZER_FLAG_STRING(save_coverage_summary, "Experimental:"
- " save coverage summary to a given file."
- " Used with -merge=1")
-FUZZER_FLAG_STRING(load_coverage_summary, "Experimental:"
- " load coverage summary from a given file."
- " Treat this coverage as belonging to the first corpus. "
- " Used with -merge=1")
-FUZZER_FLAG_INT(minimize_crash, 0, "If 1, minimizes the provided"
- " crash input. Use with -runs=N or -max_total_time=N to limit "
- "the number attempts."
- " Use with -exact_artifact_path to specify the output."
- " Combine with ASAN_OPTIONS=dedup_token_length=3 (or similar) to ensure that"
- " the minimized input triggers the same crash."
- )
-FUZZER_FLAG_INT(cleanse_crash, 0, "If 1, tries to cleanse the provided"
- " crash input to make it contain fewer original bytes."
- " Use with -exact_artifact_path to specify the output."
- )
-FUZZER_FLAG_INT(minimize_crash_internal_step, 0, "internal flag")
-FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters")
-FUZZER_FLAG_INT(use_memmem, 1,
- "Use hints from intercepting memmem, strstr, etc")
-FUZZER_FLAG_INT(use_value_profile, 0,
- "Experimental. Use value profile to guide fuzzing.")
-FUZZER_FLAG_INT(use_cmp, 1, "Use CMP traces to guide mutations")
-FUZZER_FLAG_INT(shrink, 0, "Experimental. Try to shrink corpus inputs.")
-FUZZER_FLAG_INT(reduce_inputs, 1,
- "Try to reduce the size of inputs while preserving their full feature sets")
-FUZZER_FLAG_UNSIGNED(jobs, 0, "Number of jobs to run. If jobs >= 1 we spawn"
- " this number of jobs in separate worker processes"
- " with stdout/stderr redirected to fuzz-JOB.log.")
-FUZZER_FLAG_UNSIGNED(workers, 0,
- "Number of simultaneous worker processes to run the jobs."
- " If zero, \"min(jobs,NumberOfCpuCores()/2)\" is used.")
-FUZZER_FLAG_INT(reload, 1,
- "Reload the main corpus every <N> seconds to get new units"
- " discovered by other processes. If 0, disabled")
-FUZZER_FLAG_INT(report_slow_units, 10,
- "Report slowest units if they run for more than this number of seconds.")
-FUZZER_FLAG_INT(only_ascii, 0,
- "If 1, generate only ASCII (isprint+isspace) inputs.")
-FUZZER_FLAG_STRING(dict, "Experimental. Use the dictionary file.")
-FUZZER_FLAG_STRING(artifact_prefix, "Write fuzzing artifacts (crash, "
- "timeout, or slow inputs) as "
- "$(artifact_prefix)file")
-FUZZER_FLAG_STRING(exact_artifact_path,
- "Write the single artifact on failure (crash, timeout) "
- "as $(exact_artifact_path). This overrides -artifact_prefix "
- "and will not use checksum in the file name. Do not "
- "use the same path for several parallel processes.")
-FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.")
-FUZZER_FLAG_INT(print_funcs, 2, "If >=1, print out at most this number of "
- "newly covered functions.")
-FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.")
-FUZZER_FLAG_INT(print_corpus_stats, 0,
- "If 1, print statistics on corpus elements at exit.")
-FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information as text"
- " at exit.")
-FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated."
- " If 1, dump coverage information as a"
- " .sancov file at exit.")
-FUZZER_FLAG_INT(handle_unstable, 0, "Experimental."
- " Executes every input 3 times in total if a unique feature"
- " is found during the first execution."
- " If 1, we only use the minimum hit count from the 3 runs"
- " to determine whether an input is interesting."
- " If 2, we disregard edges that are found unstable for"
- " feature collection.")
-FUZZER_FLAG_INT(print_unstable_stats, 0, "Experimental."
- " If 1, print unstable statistics at exit.")
-FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
-FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGBUS.")
-FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.")
-FUZZER_FLAG_INT(handle_ill, 1, "If 1, try to intercept SIGILL.")
-FUZZER_FLAG_INT(handle_fpe, 1, "If 1, try to intercept SIGFPE.")
-FUZZER_FLAG_INT(handle_int, 1, "If 1, try to intercept SIGINT.")
-FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.")
-FUZZER_FLAG_INT(handle_xfsz, 1, "If 1, try to intercept SIGXFSZ.")
-FUZZER_FLAG_INT(handle_usr1, 1, "If 1, try to intercept SIGUSR1.")
-FUZZER_FLAG_INT(handle_usr2, 1, "If 1, try to intercept SIGUSR2.")
-FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; "
- "if 2, close stderr; if 3, close both. "
- "Be careful, this will also close e.g. stderr of asan.")
-FUZZER_FLAG_INT(detect_leaks, 1, "If 1, and if LeakSanitizer is enabled "
- "try to detect memory leaks during fuzzing (i.e. not only at shut down).")
-FUZZER_FLAG_INT(purge_allocator_interval, 1, "Purge allocator caches and "
- "quarantines every <N> seconds. When rss_limit_mb is specified (>0), "
- "purging starts when RSS exceeds 50% of rss_limit_mb. Pass "
- "purge_allocator_interval=-1 to disable this functionality.")
-FUZZER_FLAG_INT(trace_malloc, 0, "If >= 1 will print all mallocs/frees. "
- "If >= 2 will also print stack traces.")
-FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon"
- "reaching this limit of RSS memory usage.")
-FUZZER_FLAG_INT(malloc_limit_mb, 0, "If non-zero, the fuzzer will exit "
- "if the target tries to allocate this number of Mb with one malloc call. "
- "If zero (default) same limit as rss_limit_mb is applied.")
-FUZZER_FLAG_STRING(exit_on_src_pos, "Exit if a newly found PC originates"
- " from the given source location. Example: -exit_on_src_pos=foo.cc:123. "
- "Used primarily for testing libFuzzer itself.")
-FUZZER_FLAG_STRING(exit_on_item, "Exit if an item with a given sha1 sum"
- " was added to the corpus. "
- "Used primarily for testing libFuzzer itself.")
-FUZZER_FLAG_INT(ignore_remaining_args, 0, "If 1, ignore all arguments passed "
- "after this one. Useful for fuzzers that need to do their own "
- "argument parsing.")
-FUZZER_FLAG_STRING(focus_function, "Experimental. "
- "Fuzzing will focus on inputs that trigger calls to this function")
-
-FUZZER_DEPRECATED_FLAG(run_equivalence_server)
-FUZZER_DEPRECATED_FLAG(use_equivalence_server)
-FUZZER_FLAG_INT(analyze_dict, 0, "Experimental")
-FUZZER_DEPRECATED_FLAG(use_clang_coverage)
-FUZZER_FLAG_STRING(data_flow_trace, "Experimental: use the data flow trace")
diff --git a/chromium/third_party/libFuzzer/src/FuzzerIO.cpp b/chromium/third_party/libFuzzer/src/FuzzerIO.cpp
deleted file mode 100644
index c4c31e82471..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerIO.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-//===- FuzzerIO.cpp - IO utils. -------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// IO functions.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerIO.h"
-#include "FuzzerDefs.h"
-#include "FuzzerExtFunctions.h"
-#include <algorithm>
-#include <cstdarg>
-#include <fstream>
-#include <iterator>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-namespace fuzzer {
-
-static FILE *OutputFile = stderr;
-
-long GetEpoch(const std::string &Path) {
- struct stat St;
- if (stat(Path.c_str(), &St))
- return 0; // Can't stat, be conservative.
- return St.st_mtime;
-}
-
-Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {
- std::ifstream T(Path, std::ios::binary);
- if (ExitOnError && !T) {
- Printf("No such directory: %s; exiting\n", Path.c_str());
- exit(1);
- }
-
- T.seekg(0, T.end);
- auto EndPos = T.tellg();
- if (EndPos < 0) return {};
- size_t FileLen = EndPos;
- if (MaxSize)
- FileLen = std::min(FileLen, MaxSize);
-
- T.seekg(0, T.beg);
- Unit Res(FileLen);
- T.read(reinterpret_cast<char *>(Res.data()), FileLen);
- return Res;
-}
-
-std::string FileToString(const std::string &Path) {
- std::ifstream T(Path, std::ios::binary);
- return std::string((std::istreambuf_iterator<char>(T)),
- std::istreambuf_iterator<char>());
-}
-
-void CopyFileToErr(const std::string &Path) {
- Printf("%s", FileToString(Path).c_str());
-}
-
-void WriteToFile(const Unit &U, const std::string &Path) {
- // Use raw C interface because this function may be called from a sig handler.
- FILE *Out = fopen(Path.c_str(), "w");
- if (!Out) return;
- fwrite(U.data(), sizeof(U[0]), U.size(), Out);
- fclose(Out);
-}
-
-void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V,
- long *Epoch, size_t MaxSize, bool ExitOnError) {
- long E = Epoch ? *Epoch : 0;
- Vector<std::string> Files;
- ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
- size_t NumLoaded = 0;
- for (size_t i = 0; i < Files.size(); i++) {
- auto &X = Files[i];
- if (Epoch && GetEpoch(X) < E) continue;
- NumLoaded++;
- if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024)
- Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path);
- auto S = FileToVector(X, MaxSize, ExitOnError);
- if (!S.empty())
- V->push_back(S);
- }
-}
-
-
-void GetSizedFilesFromDir(const std::string &Dir, Vector<SizedFile> *V) {
- Vector<std::string> Files;
- ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true);
- for (auto &File : Files)
- if (size_t Size = FileSize(File))
- V->push_back({File, Size});
-}
-
-std::string DirPlusFile(const std::string &DirPath,
- const std::string &FileName) {
- return DirPath + GetSeparator() + FileName;
-}
-
-void DupAndCloseStderr() {
- int OutputFd = DuplicateFile(2);
- if (OutputFd > 0) {
- FILE *NewOutputFile = OpenFile(OutputFd, "w");
- if (NewOutputFile) {
- OutputFile = NewOutputFile;
- if (EF->__sanitizer_set_report_fd)
- EF->__sanitizer_set_report_fd(
- reinterpret_cast<void *>(GetHandleFromFd(OutputFd)));
- DiscardOutput(2);
- }
- }
-}
-
-void CloseStdout() {
- DiscardOutput(1);
-}
-
-void Printf(const char *Fmt, ...) {
- va_list ap;
- va_start(ap, Fmt);
- vfprintf(OutputFile, Fmt, ap);
- va_end(ap);
- fflush(OutputFile);
-}
-
-} // namespace fuzzer
diff --git a/chromium/third_party/libFuzzer/src/FuzzerIO.h b/chromium/third_party/libFuzzer/src/FuzzerIO.h
deleted file mode 100644
index b4a68190e78..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerIO.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// IO interface.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_IO_H
-#define LLVM_FUZZER_IO_H
-
-#include "FuzzerDefs.h"
-
-namespace fuzzer {
-
-long GetEpoch(const std::string &Path);
-
-Unit FileToVector(const std::string &Path, size_t MaxSize = 0,
- bool ExitOnError = true);
-
-std::string FileToString(const std::string &Path);
-
-void CopyFileToErr(const std::string &Path);
-
-void WriteToFile(const Unit &U, const std::string &Path);
-
-void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V,
- long *Epoch, size_t MaxSize, bool ExitOnError);
-
-// Returns "Dir/FileName" or equivalent for the current OS.
-std::string DirPlusFile(const std::string &DirPath,
- const std::string &FileName);
-
-// Returns the name of the dir, similar to the 'dirname' utility.
-std::string DirName(const std::string &FileName);
-
-// Returns path to a TmpDir.
-std::string TmpDir();
-
-bool IsInterestingCoverageFile(const std::string &FileName);
-
-void DupAndCloseStderr();
-
-void CloseStdout();
-
-void Printf(const char *Fmt, ...);
-
-// Print using raw syscalls, useful when printing at early init stages.
-void RawPrint(const char *Str);
-
-// Platform specific functions:
-bool IsFile(const std::string &Path);
-size_t FileSize(const std::string &Path);
-
-void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
- Vector<std::string> *V, bool TopDir);
-
-struct SizedFile {
- std::string File;
- size_t Size;
- bool operator<(const SizedFile &B) const { return Size < B.Size; }
-};
-
-void GetSizedFilesFromDir(const std::string &Dir, Vector<SizedFile> *V);
-
-char GetSeparator();
-// Similar to the basename utility: returns the file name w/o the dir prefix.
-std::string Basename(const std::string &Path);
-
-FILE* OpenFile(int Fd, const char *Mode);
-
-int CloseFile(int Fd);
-
-int DuplicateFile(int Fd);
-
-void RemoveFile(const std::string &Path);
-
-void DiscardOutput(int Fd);
-
-intptr_t GetHandleFromFd(int fd);
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_IO_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerIOPosix.cpp b/chromium/third_party/libFuzzer/src/FuzzerIOPosix.cpp
deleted file mode 100644
index 401b4cbbf74..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerIOPosix.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// IO functions implementation using Posix API.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA
-
-#include "FuzzerExtFunctions.h"
-#include "FuzzerIO.h"
-#include <cstdarg>
-#include <cstdio>
-#include <dirent.h>
-#include <fstream>
-#include <iterator>
-#include <libgen.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace fuzzer {
-
-bool IsFile(const std::string &Path) {
- struct stat St;
- if (stat(Path.c_str(), &St))
- return false;
- return S_ISREG(St.st_mode);
-}
-
-static bool IsDirectory(const std::string &Path) {
- struct stat St;
- if (stat(Path.c_str(), &St))
- return false;
- return S_ISDIR(St.st_mode);
-}
-
-size_t FileSize(const std::string &Path) {
- struct stat St;
- if (stat(Path.c_str(), &St))
- return 0;
- return St.st_size;
-}
-
-std::string Basename(const std::string &Path) {
- size_t Pos = Path.rfind(GetSeparator());
- if (Pos == std::string::npos) return Path;
- assert(Pos < Path.size());
- return Path.substr(Pos + 1);
-}
-
-void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
- Vector<std::string> *V, bool TopDir) {
- auto E = GetEpoch(Dir);
- if (Epoch)
- if (E && *Epoch >= E) return;
-
- DIR *D = opendir(Dir.c_str());
- if (!D) {
- Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str());
- exit(1);
- }
- while (auto E = readdir(D)) {
- std::string Path = DirPlusFile(Dir, E->d_name);
- if (E->d_type == DT_REG || E->d_type == DT_LNK ||
- (E->d_type == DT_UNKNOWN && IsFile(Path)))
- V->push_back(Path);
- else if ((E->d_type == DT_DIR ||
- (E->d_type == DT_UNKNOWN && IsDirectory(Path))) &&
- *E->d_name != '.')
- ListFilesInDirRecursive(Path, Epoch, V, false);
- }
- closedir(D);
- if (Epoch && TopDir)
- *Epoch = E;
-}
-
-char GetSeparator() {
- return '/';
-}
-
-FILE* OpenFile(int Fd, const char* Mode) {
- return fdopen(Fd, Mode);
-}
-
-int CloseFile(int fd) {
- return close(fd);
-}
-
-int DuplicateFile(int Fd) {
- return dup(Fd);
-}
-
-void RemoveFile(const std::string &Path) {
- unlink(Path.c_str());
-}
-
-void DiscardOutput(int Fd) {
- FILE* Temp = fopen("/dev/null", "w");
- if (!Temp)
- return;
- dup2(fileno(Temp), Fd);
- fclose(Temp);
-}
-
-intptr_t GetHandleFromFd(int fd) {
- return static_cast<intptr_t>(fd);
-}
-
-std::string DirName(const std::string &FileName) {
- char *Tmp = new char[FileName.size() + 1];
- memcpy(Tmp, FileName.c_str(), FileName.size() + 1);
- std::string Res = dirname(Tmp);
- delete [] Tmp;
- return Res;
-}
-
-std::string TmpDir() {
- if (auto Env = getenv("TMPDIR"))
- return Env;
- return "/tmp";
-}
-
-bool IsInterestingCoverageFile(const std::string &FileName) {
- if (FileName.find("compiler-rt/lib/") != std::string::npos)
- return false; // sanitizer internal.
- if (FileName.find("/usr/lib/") != std::string::npos)
- return false;
- if (FileName.find("/usr/include/") != std::string::npos)
- return false;
- if (FileName == "<null>")
- return false;
- return true;
-}
-
-
-void RawPrint(const char *Str) {
- write(2, Str, strlen(Str));
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_POSIX
diff --git a/chromium/third_party/libFuzzer/src/FuzzerIOWindows.cpp b/chromium/third_party/libFuzzer/src/FuzzerIOWindows.cpp
deleted file mode 100644
index 75dcaf72a94..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerIOWindows.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-//===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// IO functions implementation for Windows.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_WINDOWS
-
-#include "FuzzerExtFunctions.h"
-#include "FuzzerIO.h"
-#include <cstdarg>
-#include <cstdio>
-#include <fstream>
-#include <io.h>
-#include <iterator>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <windows.h>
-
-namespace fuzzer {
-
-static bool IsFile(const std::string &Path, const DWORD &FileAttributes) {
-
- if (FileAttributes & FILE_ATTRIBUTE_NORMAL)
- return true;
-
- if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- return false;
-
- HANDLE FileHandle(
- CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, 0));
-
- if (FileHandle == INVALID_HANDLE_VALUE) {
- Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
- GetLastError());
- return false;
- }
-
- DWORD FileType = GetFileType(FileHandle);
-
- if (FileType == FILE_TYPE_UNKNOWN) {
- Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
- GetLastError());
- CloseHandle(FileHandle);
- return false;
- }
-
- if (FileType != FILE_TYPE_DISK) {
- CloseHandle(FileHandle);
- return false;
- }
-
- CloseHandle(FileHandle);
- return true;
-}
-
-bool IsFile(const std::string &Path) {
- DWORD Att = GetFileAttributesA(Path.c_str());
-
- if (Att == INVALID_FILE_ATTRIBUTES) {
- Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n",
- Path.c_str(), GetLastError());
- return false;
- }
-
- return IsFile(Path, Att);
-}
-
-std::string Basename(const std::string &Path) {
- size_t Pos = Path.find_last_of("/\\");
- if (Pos == std::string::npos) return Path;
- assert(Pos < Path.size());
- return Path.substr(Pos + 1);
-}
-
-size_t FileSize(const std::string &Path) {
- WIN32_FILE_ATTRIBUTE_DATA attr;
- if (!GetFileAttributesExA(Path.c_str(), GetFileExInfoStandard, &attr)) {
- Printf("GetFileAttributesExA() failed for \"%s\" (Error code: %lu).\n",
- Path.c_str(), GetLastError());
- return 0;
- }
- ULARGE_INTEGER size;
- size.HighPart = attr.nFileSizeHigh;
- size.LowPart = attr.nFileSizeLow;
- return size.QuadPart;
-}
-
-void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
- Vector<std::string> *V, bool TopDir) {
- auto E = GetEpoch(Dir);
- if (Epoch)
- if (E && *Epoch >= E) return;
-
- std::string Path(Dir);
- assert(!Path.empty());
- if (Path.back() != '\\')
- Path.push_back('\\');
- Path.push_back('*');
-
- // Get the first directory entry.
- WIN32_FIND_DATAA FindInfo;
- HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo));
- if (FindHandle == INVALID_HANDLE_VALUE)
- {
- if (GetLastError() == ERROR_FILE_NOT_FOUND)
- return;
- Printf("No such file or directory: %s; exiting\n", Dir.c_str());
- exit(1);
- }
-
- do {
- std::string FileName = DirPlusFile(Dir, FindInfo.cFileName);
-
- if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- size_t FilenameLen = strlen(FindInfo.cFileName);
- if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') ||
- (FilenameLen == 2 && FindInfo.cFileName[0] == '.' &&
- FindInfo.cFileName[1] == '.'))
- continue;
-
- ListFilesInDirRecursive(FileName, Epoch, V, false);
- }
- else if (IsFile(FileName, FindInfo.dwFileAttributes))
- V->push_back(FileName);
- } while (FindNextFileA(FindHandle, &FindInfo));
-
- DWORD LastError = GetLastError();
- if (LastError != ERROR_NO_MORE_FILES)
- Printf("FindNextFileA failed (Error code: %lu).\n", LastError);
-
- FindClose(FindHandle);
-
- if (Epoch && TopDir)
- *Epoch = E;
-}
-
-char GetSeparator() {
- return '\\';
-}
-
-FILE* OpenFile(int Fd, const char* Mode) {
- return _fdopen(Fd, Mode);
-}
-
-int CloseFile(int Fd) {
- return _close(Fd);
-}
-
-int DuplicateFile(int Fd) {
- return _dup(Fd);
-}
-
-void RemoveFile(const std::string &Path) {
- _unlink(Path.c_str());
-}
-
-void DiscardOutput(int Fd) {
- FILE* Temp = fopen("nul", "w");
- if (!Temp)
- return;
- _dup2(_fileno(Temp), Fd);
- fclose(Temp);
-}
-
-intptr_t GetHandleFromFd(int fd) {
- return _get_osfhandle(fd);
-}
-
-static bool IsSeparator(char C) {
- return C == '\\' || C == '/';
-}
-
-// Parse disk designators, like "C:\". If Relative == true, also accepts: "C:".
-// Returns number of characters considered if successful.
-static size_t ParseDrive(const std::string &FileName, const size_t Offset,
- bool Relative = true) {
- if (Offset + 1 >= FileName.size() || FileName[Offset + 1] != ':')
- return 0;
- if (Offset + 2 >= FileName.size() || !IsSeparator(FileName[Offset + 2])) {
- if (!Relative) // Accept relative path?
- return 0;
- else
- return 2;
- }
- return 3;
-}
-
-// Parse a file name, like: SomeFile.txt
-// Returns number of characters considered if successful.
-static size_t ParseFileName(const std::string &FileName, const size_t Offset) {
- size_t Pos = Offset;
- const size_t End = FileName.size();
- for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
- ;
- return Pos - Offset;
-}
-
-// Parse a directory ending in separator, like: `SomeDir\`
-// Returns number of characters considered if successful.
-static size_t ParseDir(const std::string &FileName, const size_t Offset) {
- size_t Pos = Offset;
- const size_t End = FileName.size();
- if (Pos >= End || IsSeparator(FileName[Pos]))
- return 0;
- for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
- ;
- if (Pos >= End)
- return 0;
- ++Pos; // Include separator.
- return Pos - Offset;
-}
-
-// Parse a servername and share, like: `SomeServer\SomeShare\`
-// Returns number of characters considered if successful.
-static size_t ParseServerAndShare(const std::string &FileName,
- const size_t Offset) {
- size_t Pos = Offset, Res;
- if (!(Res = ParseDir(FileName, Pos)))
- return 0;
- Pos += Res;
- if (!(Res = ParseDir(FileName, Pos)))
- return 0;
- Pos += Res;
- return Pos - Offset;
-}
-
-// Parse the given Ref string from the position Offset, to exactly match the given
-// string Patt.
-// Returns number of characters considered if successful.
-static size_t ParseCustomString(const std::string &Ref, size_t Offset,
- const char *Patt) {
- size_t Len = strlen(Patt);
- if (Offset + Len > Ref.size())
- return 0;
- return Ref.compare(Offset, Len, Patt) == 0 ? Len : 0;
-}
-
-// Parse a location, like:
-// \\?\UNC\Server\Share\ \\?\C:\ \\Server\Share\ \ C:\ C:
-// Returns number of characters considered if successful.
-static size_t ParseLocation(const std::string &FileName) {
- size_t Pos = 0, Res;
-
- if ((Res = ParseCustomString(FileName, Pos, R"(\\?\)"))) {
- Pos += Res;
- if ((Res = ParseCustomString(FileName, Pos, R"(UNC\)"))) {
- Pos += Res;
- if ((Res = ParseServerAndShare(FileName, Pos)))
- return Pos + Res;
- return 0;
- }
- if ((Res = ParseDrive(FileName, Pos, false)))
- return Pos + Res;
- return 0;
- }
-
- if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
- ++Pos;
- if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
- ++Pos;
- if ((Res = ParseServerAndShare(FileName, Pos)))
- return Pos + Res;
- return 0;
- }
- return Pos;
- }
-
- if ((Res = ParseDrive(FileName, Pos)))
- return Pos + Res;
-
- return Pos;
-}
-
-std::string DirName(const std::string &FileName) {
- size_t LocationLen = ParseLocation(FileName);
- size_t DirLen = 0, Res;
- while ((Res = ParseDir(FileName, LocationLen + DirLen)))
- DirLen += Res;
- size_t FileLen = ParseFileName(FileName, LocationLen + DirLen);
-
- if (LocationLen + DirLen + FileLen != FileName.size()) {
- Printf("DirName() failed for \"%s\", invalid path.\n", FileName.c_str());
- exit(1);
- }
-
- if (DirLen) {
- --DirLen; // Remove trailing separator.
- if (!FileLen) { // Path ended in separator.
- assert(DirLen);
- // Remove file name from Dir.
- while (DirLen && !IsSeparator(FileName[LocationLen + DirLen - 1]))
- --DirLen;
- if (DirLen) // Remove trailing separator.
- --DirLen;
- }
- }
-
- if (!LocationLen) { // Relative path.
- if (!DirLen)
- return ".";
- return std::string(".\\").append(FileName, 0, DirLen);
- }
-
- return FileName.substr(0, LocationLen + DirLen);
-}
-
-std::string TmpDir() {
- std::string Tmp;
- Tmp.resize(MAX_PATH + 1);
- DWORD Size = GetTempPathA(Tmp.size(), &Tmp[0]);
- if (Size == 0) {
- Printf("Couldn't get Tmp path.\n");
- exit(1);
- }
- Tmp.resize(Size);
- return Tmp;
-}
-
-bool IsInterestingCoverageFile(const std::string &FileName) {
- if (FileName.find("Program Files") != std::string::npos)
- return false;
- if (FileName.find("compiler-rt\\lib\\") != std::string::npos)
- return false; // sanitizer internal.
- if (FileName == "<null>")
- return false;
- return true;
-}
-
-void RawPrint(const char *Str) {
- // Not tested, may or may not work. Fix if needed.
- Printf("%s", Str);
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_WINDOWS
diff --git a/chromium/third_party/libFuzzer/src/FuzzerInterface.h b/chromium/third_party/libFuzzer/src/FuzzerInterface.h
deleted file mode 100644
index 0f7effb2ab6..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerInterface.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- FuzzerInterface.h - Interface header for the Fuzzer ------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Define the interface between libFuzzer and the library being tested.
-//===----------------------------------------------------------------------===//
-
-// NOTE: the libFuzzer interface is thin and in the majority of cases
-// you should not include this file into your target. In 95% of cases
-// all you need is to define the following function in your file:
-// extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
-
-// WARNING: keep the interface in C.
-
-#ifndef LLVM_FUZZER_INTERFACE_H
-#define LLVM_FUZZER_INTERFACE_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-// Mandatory user-provided target function.
-// Executes the code under test with [Data, Data+Size) as the input.
-// libFuzzer will invoke this function *many* times with different inputs.
-// Must return 0.
-__attribute__((visibility("default"))) int
-LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
-
-// Optional user-provided initialization function.
-// If provided, this function will be called by libFuzzer once at startup.
-// It may read and modify argc/argv.
-// Must return 0.
-__attribute__((visibility("default"))) int LLVMFuzzerInitialize(int *argc,
- char ***argv);
-
-// Optional user-provided custom mutator.
-// Mutates raw data in [Data, Data+Size) inplace.
-// Returns the new size, which is not greater than MaxSize.
-// Given the same Seed produces the same mutation.
-__attribute__((visibility("default"))) size_t
-LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize,
- unsigned int Seed);
-
-// Optional user-provided custom cross-over function.
-// Combines pieces of Data1 & Data2 together into Out.
-// Returns the new size, which is not greater than MaxOutSize.
-// Should produce the same mutation given the same Seed.
-__attribute__((visibility("default"))) size_t
-LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
- const uint8_t *Data2, size_t Size2, uint8_t *Out,
- size_t MaxOutSize, unsigned int Seed);
-
-// Experimental, may go away in future.
-// libFuzzer-provided function to be used inside LLVMFuzzerCustomMutator.
-// Mutates raw data in [Data, Data+Size) inplace.
-// Returns the new size, which is not greater than MaxSize.
-__attribute__((visibility("default"))) size_t
-LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // LLVM_FUZZER_INTERFACE_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerInternal.h b/chromium/third_party/libFuzzer/src/FuzzerInternal.h
deleted file mode 100644
index bfc898248ad..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerInternal.h
+++ /dev/null
@@ -1,179 +0,0 @@
-//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Define the main class fuzzer::Fuzzer and most functions.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_INTERNAL_H
-#define LLVM_FUZZER_INTERNAL_H
-
-#include "FuzzerDataFlowTrace.h"
-#include "FuzzerDefs.h"
-#include "FuzzerExtFunctions.h"
-#include "FuzzerInterface.h"
-#include "FuzzerOptions.h"
-#include "FuzzerSHA1.h"
-#include "FuzzerValueBitMap.h"
-#include <algorithm>
-#include <atomic>
-#include <chrono>
-#include <climits>
-#include <cstdlib>
-#include <string.h>
-
-namespace fuzzer {
-
-using namespace std::chrono;
-
-class Fuzzer {
-public:
-
- Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
- FuzzingOptions Options);
- ~Fuzzer();
- void Loop(const Vector<std::string> &CorpusDirs);
- void ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs);
- void MinimizeCrashLoop(const Unit &U);
- void RereadOutputCorpus(size_t MaxSize);
-
- size_t secondsSinceProcessStartUp() {
- return duration_cast<seconds>(system_clock::now() - ProcessStartTime)
- .count();
- }
-
- bool TimedOut() {
- return Options.MaxTotalTimeSec > 0 &&
- secondsSinceProcessStartUp() >
- static_cast<size_t>(Options.MaxTotalTimeSec);
- }
-
- size_t execPerSec() {
- size_t Seconds = secondsSinceProcessStartUp();
- return Seconds ? TotalNumberOfRuns / Seconds : 0;
- }
-
- size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; }
-
- static void StaticAlarmCallback();
- static void StaticCrashSignalCallback();
- static void StaticExitCallback();
- static void StaticInterruptCallback();
- static void StaticFileSizeExceedCallback();
- static void StaticGracefulExitCallback();
-
- void ExecuteCallback(const uint8_t *Data, size_t Size);
- void CheckForUnstableCounters(const uint8_t *Data, size_t Size);
- bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
- InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);
-
- // Merge Corpora[1:] into Corpora[0].
- void Merge(const Vector<std::string> &Corpora);
- void CrashResistantMerge(const Vector<std::string> &Args,
- const Vector<std::string> &Corpora,
- const char *CoverageSummaryInputPathOrNull,
- const char *CoverageSummaryOutputPathOrNull,
- const char *MergeControlFilePathOrNull);
- void CrashResistantMergeInternalStep(const std::string &ControlFilePath);
- MutationDispatcher &GetMD() { return MD; }
- void PrintFinalStats();
- void SetMaxInputLen(size_t MaxInputLen);
- void SetMaxMutationLen(size_t MaxMutationLen);
- void RssLimitCallback();
-
- bool InFuzzingThread() const { return IsMyThread; }
- size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const;
- void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
- bool DuringInitialCorpusExecution);
-
- void HandleMalloc(size_t Size);
- void AnnounceOutput(const uint8_t *Data, size_t Size);
-
-private:
- void AlarmCallback();
- void CrashCallback();
- void ExitCallback();
- void MaybeExitGracefully();
- void CrashOnOverwrittenData();
- void InterruptCallback();
- void MutateAndTestOne();
- void PurgeAllocator();
- void ReportNewCoverage(InputInfo *II, const Unit &U);
- void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size);
- void WriteToOutputCorpus(const Unit &U);
- void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
- void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0);
- void PrintStatusForNewUnit(const Unit &U, const char *Text);
- void CheckExitOnSrcPosOrItem();
-
- static void StaticDeathCallback();
- void DumpCurrentUnit(const char *Prefix);
- void DeathCallback();
-
- void AllocateCurrentUnitData();
- uint8_t *CurrentUnitData = nullptr;
- std::atomic<size_t> CurrentUnitSize;
- uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit.
-
- bool GracefulExitRequested = false;
-
- size_t TotalNumberOfRuns = 0;
- size_t NumberOfNewUnitsAdded = 0;
-
- size_t LastCorpusUpdateRun = 0;
-
- bool HasMoreMallocsThanFrees = false;
- size_t NumberOfLeakDetectionAttempts = 0;
-
- system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now();
-
- UserCallback CB;
- InputCorpus &Corpus;
- MutationDispatcher &MD;
- FuzzingOptions Options;
- DataFlowTrace DFT;
-
- system_clock::time_point ProcessStartTime = system_clock::now();
- system_clock::time_point UnitStartTime, UnitStopTime;
- long TimeOfLongestUnitInSeconds = 0;
- long EpochOfLastReadOfOutputCorpus = 0;
-
- size_t MaxInputLen = 0;
- size_t MaxMutationLen = 0;
- size_t TmpMaxMutationLen = 0;
-
- Vector<uint32_t> UniqFeatureSetTmp;
-
- // Need to know our own thread.
- static thread_local bool IsMyThread;
-};
-
-struct ScopedEnableMsanInterceptorChecks {
- ScopedEnableMsanInterceptorChecks() {
- if (EF->__msan_scoped_enable_interceptor_checks)
- EF->__msan_scoped_enable_interceptor_checks();
- }
- ~ScopedEnableMsanInterceptorChecks() {
- if (EF->__msan_scoped_disable_interceptor_checks)
- EF->__msan_scoped_disable_interceptor_checks();
- }
-};
-
-struct ScopedDisableMsanInterceptorChecks {
- ScopedDisableMsanInterceptorChecks() {
- if (EF->__msan_scoped_disable_interceptor_checks)
- EF->__msan_scoped_disable_interceptor_checks();
- }
- ~ScopedDisableMsanInterceptorChecks() {
- if (EF->__msan_scoped_enable_interceptor_checks)
- EF->__msan_scoped_enable_interceptor_checks();
- }
-};
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_INTERNAL_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerLoop.cpp b/chromium/third_party/libFuzzer/src/FuzzerLoop.cpp
deleted file mode 100644
index 09c57c3f6b7..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerLoop.cpp
+++ /dev/null
@@ -1,905 +0,0 @@
-//===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Fuzzer's main loop.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerCorpus.h"
-#include "FuzzerIO.h"
-#include "FuzzerInternal.h"
-#include "FuzzerMutate.h"
-#include "FuzzerRandom.h"
-#include "FuzzerShmem.h"
-#include "FuzzerTracePC.h"
-#include <algorithm>
-#include <cstring>
-#include <memory>
-#include <mutex>
-#include <set>
-
-#if defined(__has_include)
-#if __has_include(<sanitizer / lsan_interface.h>)
-#include <sanitizer/lsan_interface.h>
-#endif
-#endif
-
-#define NO_SANITIZE_MEMORY
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-#undef NO_SANITIZE_MEMORY
-#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
-#endif
-#endif
-
-namespace fuzzer {
-static const size_t kMaxUnitSizeToPrint = 256;
-
-thread_local bool Fuzzer::IsMyThread;
-
-SharedMemoryRegion SMR;
-
-bool RunningUserCallback = false;
-
-// Only one Fuzzer per process.
-static Fuzzer *F;
-
-// Leak detection is expensive, so we first check if there were more mallocs
-// than frees (using the sanitizer malloc hooks) and only then try to call lsan.
-struct MallocFreeTracer {
- void Start(int TraceLevel) {
- this->TraceLevel = TraceLevel;
- if (TraceLevel)
- Printf("MallocFreeTracer: START\n");
- Mallocs = 0;
- Frees = 0;
- }
- // Returns true if there were more mallocs than frees.
- bool Stop() {
- if (TraceLevel)
- Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(),
- Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT");
- bool Result = Mallocs > Frees;
- Mallocs = 0;
- Frees = 0;
- TraceLevel = 0;
- return Result;
- }
- std::atomic<size_t> Mallocs;
- std::atomic<size_t> Frees;
- int TraceLevel = 0;
-
- std::recursive_mutex TraceMutex;
- bool TraceDisabled = false;
-};
-
-static MallocFreeTracer AllocTracer;
-
-// Locks printing and avoids nested hooks triggered from mallocs/frees in
-// sanitizer.
-class TraceLock {
-public:
- TraceLock() : Lock(AllocTracer.TraceMutex) {
- AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled;
- }
- ~TraceLock() { AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; }
-
- bool IsDisabled() const {
- // This is already inverted value.
- return !AllocTracer.TraceDisabled;
- }
-
-private:
- std::lock_guard<std::recursive_mutex> Lock;
-};
-
-ATTRIBUTE_NO_SANITIZE_MEMORY
-void MallocHook(const volatile void *ptr, size_t size) {
- size_t N = AllocTracer.Mallocs++;
- F->HandleMalloc(size);
- if (int TraceLevel = AllocTracer.TraceLevel) {
- TraceLock Lock;
- if (Lock.IsDisabled())
- return;
- Printf("MALLOC[%zd] %p %zd\n", N, ptr, size);
- if (TraceLevel >= 2 && EF)
- PrintStackTrace();
- }
-}
-
-ATTRIBUTE_NO_SANITIZE_MEMORY
-void FreeHook(const volatile void *ptr) {
- size_t N = AllocTracer.Frees++;
- if (int TraceLevel = AllocTracer.TraceLevel) {
- TraceLock Lock;
- if (Lock.IsDisabled())
- return;
- Printf("FREE[%zd] %p\n", N, ptr);
- if (TraceLevel >= 2 && EF)
- PrintStackTrace();
- }
-}
-
-// Crash on a single malloc that exceeds the rss limit.
-void Fuzzer::HandleMalloc(size_t Size) {
- if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb)
- return;
- Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(),
- Size);
- Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
- PrintStackTrace();
- DumpCurrentUnit("oom-");
- Printf("SUMMARY: libFuzzer: out-of-memory\n");
- PrintFinalStats();
- _Exit(Options.ErrorExitCode); // Stop right now.
-}
-
-Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
- FuzzingOptions Options)
- : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
- if (EF->__sanitizer_set_death_callback)
- EF->__sanitizer_set_death_callback(StaticDeathCallback);
- assert(!F);
- F = this;
- TPC.ResetMaps();
- IsMyThread = true;
- if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks)
- EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook);
- TPC.SetUseCounters(Options.UseCounters);
- TPC.SetUseValueProfileMask(Options.UseValueProfile);
-
- if (Options.Verbosity)
- TPC.PrintModuleInfo();
- if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec)
- EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus);
- MaxInputLen = MaxMutationLen = Options.MaxLen;
- TmpMaxMutationLen = Max(size_t(4), Corpus.MaxInputSize());
- AllocateCurrentUnitData();
- CurrentUnitSize = 0;
- memset(BaseSha1, 0, sizeof(BaseSha1));
- TPC.SetFocusFunction(Options.FocusFunction);
- DFT.Init(Options.DataFlowTrace, Options.FocusFunction);
-}
-
-Fuzzer::~Fuzzer() {}
-
-void Fuzzer::AllocateCurrentUnitData() {
- if (CurrentUnitData || MaxInputLen == 0)
- return;
- CurrentUnitData = new uint8_t[MaxInputLen];
-}
-
-void Fuzzer::StaticDeathCallback() {
- assert(F);
- F->DeathCallback();
-}
-
-void Fuzzer::DumpCurrentUnit(const char *Prefix) {
- if (!CurrentUnitData)
- return; // Happens when running individual inputs.
- ScopedDisableMsanInterceptorChecks S;
- MD.PrintMutationSequence();
- Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str());
- size_t UnitSize = CurrentUnitSize;
- if (UnitSize <= kMaxUnitSizeToPrint) {
- PrintHexArray(CurrentUnitData, UnitSize, "\n");
- PrintASCII(CurrentUnitData, UnitSize, "\n");
- }
- WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize},
- Prefix);
-}
-
-NO_SANITIZE_MEMORY
-void Fuzzer::DeathCallback() {
- DumpCurrentUnit("crash-");
- PrintFinalStats();
-}
-
-void Fuzzer::StaticAlarmCallback() {
- assert(F);
- F->AlarmCallback();
-}
-
-void Fuzzer::StaticCrashSignalCallback() {
- assert(F);
- F->CrashCallback();
-}
-
-void Fuzzer::StaticExitCallback() {
- assert(F);
- F->ExitCallback();
-}
-
-void Fuzzer::StaticInterruptCallback() {
- assert(F);
- F->InterruptCallback();
-}
-
-void Fuzzer::StaticGracefulExitCallback() {
- assert(F);
- F->GracefulExitRequested = true;
- Printf("INFO: signal received, trying to exit gracefully\n");
-}
-
-void Fuzzer::StaticFileSizeExceedCallback() {
- Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid());
- exit(1);
-}
-
-void Fuzzer::CrashCallback() {
- if (EF->__sanitizer_acquire_crash_state)
- EF->__sanitizer_acquire_crash_state();
- Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid());
- PrintStackTrace();
- Printf("NOTE: libFuzzer has rudimentary signal handlers.\n"
- " Combine libFuzzer with AddressSanitizer or similar for better "
- "crash reports.\n");
- Printf("SUMMARY: libFuzzer: deadly signal\n");
- DumpCurrentUnit("crash-");
- PrintFinalStats();
- _Exit(Options.ErrorExitCode); // Stop right now.
-}
-
-void Fuzzer::ExitCallback() {
- if (!RunningUserCallback)
- return; // This exit did not come from the user callback
- if (EF->__sanitizer_acquire_crash_state &&
- !EF->__sanitizer_acquire_crash_state())
- return;
- Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid());
- PrintStackTrace();
- Printf("SUMMARY: libFuzzer: fuzz target exited\n");
- DumpCurrentUnit("crash-");
- PrintFinalStats();
- _Exit(Options.ErrorExitCode);
-}
-
-void Fuzzer::MaybeExitGracefully() {
- if (!GracefulExitRequested) return;
- Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid());
- PrintFinalStats();
- _Exit(0);
-}
-
-void Fuzzer::InterruptCallback() {
- Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
- PrintFinalStats();
- _Exit(0); // Stop right now, don't perform any at-exit actions.
-}
-
-NO_SANITIZE_MEMORY
-void Fuzzer::AlarmCallback() {
- assert(Options.UnitTimeoutSec > 0);
- // In Windows Alarm callback is executed by a different thread.
- // NetBSD's current behavior needs this change too.
-#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD
- if (!InFuzzingThread())
- return;
-#endif
- if (!RunningUserCallback)
- return; // We have not started running units yet.
- size_t Seconds =
- duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
- if (Seconds == 0)
- return;
- if (Options.Verbosity >= 2)
- Printf("AlarmCallback %zd\n", Seconds);
- if (Seconds >= (size_t)Options.UnitTimeoutSec) {
- if (EF->__sanitizer_acquire_crash_state &&
- !EF->__sanitizer_acquire_crash_state())
- return;
- Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
- Printf(" and the timeout value is %d (use -timeout=N to change)\n",
- Options.UnitTimeoutSec);
- DumpCurrentUnit("timeout-");
- Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
- Seconds);
- PrintStackTrace();
- Printf("SUMMARY: libFuzzer: timeout\n");
- PrintFinalStats();
- _Exit(Options.TimeoutExitCode); // Stop right now.
- }
-}
-
-void Fuzzer::RssLimitCallback() {
- if (EF->__sanitizer_acquire_crash_state &&
- !EF->__sanitizer_acquire_crash_state())
- return;
- Printf(
- "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n",
- GetPid(), GetPeakRSSMb(), Options.RssLimitMb);
- Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n");
- PrintMemoryProfile();
- DumpCurrentUnit("oom-");
- Printf("SUMMARY: libFuzzer: out-of-memory\n");
- PrintFinalStats();
- _Exit(Options.ErrorExitCode); // Stop right now.
-}
-
-void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
- size_t ExecPerSec = execPerSec();
- if (!Options.Verbosity)
- return;
- Printf("#%zd\t%s", TotalNumberOfRuns, Where);
- if (size_t N = TPC.GetTotalPCCoverage())
- Printf(" cov: %zd", N);
- if (size_t N = Corpus.NumFeatures())
- Printf(" ft: %zd", N);
- if (!Corpus.empty()) {
- Printf(" corp: %zd", Corpus.NumActiveUnits());
- if (size_t N = Corpus.SizeInBytes()) {
- if (N < (1 << 14))
- Printf("/%zdb", N);
- else if (N < (1 << 24))
- Printf("/%zdKb", N >> 10);
- else
- Printf("/%zdMb", N >> 20);
- }
- if (size_t FF = Corpus.NumInputsThatTouchFocusFunction())
- Printf(" focus: %zd", FF);
- }
- if (TmpMaxMutationLen)
- Printf(" lim: %zd", TmpMaxMutationLen);
- if (Units)
- Printf(" units: %zd", Units);
-
- Printf(" exec/s: %zd", ExecPerSec);
- Printf(" rss: %zdMb", GetPeakRSSMb());
- Printf("%s", End);
-}
-
-void Fuzzer::PrintFinalStats() {
- if (Options.PrintCoverage)
- TPC.PrintCoverage();
- if (Options.PrintUnstableStats)
- TPC.PrintUnstableStats();
- if (Options.DumpCoverage)
- TPC.DumpCoverage();
- if (Options.PrintCorpusStats)
- Corpus.PrintStats();
- if (!Options.PrintFinalStats)
- return;
- size_t ExecPerSec = execPerSec();
- Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
- Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec);
- Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded);
- Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds);
- Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb());
-}
-
-void Fuzzer::SetMaxInputLen(size_t MaxInputLen) {
- assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0.
- assert(MaxInputLen);
- this->MaxInputLen = MaxInputLen;
- this->MaxMutationLen = MaxInputLen;
- AllocateCurrentUnitData();
- Printf("INFO: -max_len is not provided; "
- "libFuzzer will not generate inputs larger than %zd bytes\n",
- MaxInputLen);
-}
-
-void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) {
- assert(MaxMutationLen && MaxMutationLen <= MaxInputLen);
- this->MaxMutationLen = MaxMutationLen;
-}
-
-void Fuzzer::CheckExitOnSrcPosOrItem() {
- if (!Options.ExitOnSrcPos.empty()) {
- static auto *PCsSet = new Set<uintptr_t>;
- auto HandlePC = [&](uintptr_t PC) {
- if (!PCsSet->insert(PC).second)
- return;
- std::string Descr = DescribePC("%F %L", PC + 1);
- if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) {
- Printf("INFO: found line matching '%s', exiting.\n",
- Options.ExitOnSrcPos.c_str());
- _Exit(0);
- }
- };
- TPC.ForEachObservedPC(HandlePC);
- }
- if (!Options.ExitOnItem.empty()) {
- if (Corpus.HasUnit(Options.ExitOnItem)) {
- Printf("INFO: found item with checksum '%s', exiting.\n",
- Options.ExitOnItem.c_str());
- _Exit(0);
- }
- }
-}
-
-void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
- if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec)
- return;
- Vector<Unit> AdditionalCorpus;
- ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
- &EpochOfLastReadOfOutputCorpus, MaxSize,
- /*ExitOnError*/ false);
- if (Options.Verbosity >= 2)
- Printf("Reload: read %zd new units.\n", AdditionalCorpus.size());
- bool Reloaded = false;
- for (auto &U : AdditionalCorpus) {
- if (U.size() > MaxSize)
- U.resize(MaxSize);
- if (!Corpus.HasUnit(U)) {
- if (RunOne(U.data(), U.size())) {
- CheckExitOnSrcPosOrItem();
- Reloaded = true;
- }
- }
- }
- if (Reloaded)
- PrintStats("RELOAD");
-}
-
-void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
- auto TimeOfUnit =
- duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
- if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) &&
- secondsSinceProcessStartUp() >= 2)
- PrintStats("pulse ");
- if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 &&
- TimeOfUnit >= Options.ReportSlowUnits) {
- TimeOfLongestUnitInSeconds = TimeOfUnit;
- Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
- WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
- }
-}
-
-void Fuzzer::CheckForUnstableCounters(const uint8_t *Data, size_t Size) {
- auto CBSetupAndRun = [&]() {
- ScopedEnableMsanInterceptorChecks S;
- UnitStartTime = system_clock::now();
- TPC.ResetMaps();
- RunningUserCallback = true;
- CB(Data, Size);
- RunningUserCallback = false;
- UnitStopTime = system_clock::now();
- };
-
- // Copy original run counters into our unstable counters
- TPC.InitializeUnstableCounters();
-
- // First Rerun
- CBSetupAndRun();
- if (TPC.UpdateUnstableCounters(Options.HandleUnstable)) {
- // Second Rerun
- CBSetupAndRun();
- TPC.UpdateAndApplyUnstableCounters(Options.HandleUnstable);
- }
-}
-
-bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
- InputInfo *II, bool *FoundUniqFeatures) {
- if (!Size)
- return false;
-
- ExecuteCallback(Data, Size);
-
- UniqFeatureSetTmp.clear();
- size_t FoundUniqFeaturesOfII = 0;
- size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
- bool NewFeaturesUnstable = false;
-
- if (Options.HandleUnstable || Options.PrintUnstableStats) {
- TPC.CollectFeatures([&](size_t Feature) {
- if (Corpus.IsFeatureNew(Feature, Size, Options.Shrink))
- NewFeaturesUnstable = true;
- });
- if (NewFeaturesUnstable)
- CheckForUnstableCounters(Data, Size);
- }
-
- TPC.CollectFeatures([&](size_t Feature) {
- if (Corpus.AddFeature(Feature, Size, Options.Shrink))
- UniqFeatureSetTmp.push_back(Feature);
- if (Options.ReduceInputs && II)
- if (std::binary_search(II->UniqFeatureSet.begin(),
- II->UniqFeatureSet.end(), Feature))
- FoundUniqFeaturesOfII++;
- });
-
- if (FoundUniqFeatures)
- *FoundUniqFeatures = FoundUniqFeaturesOfII;
- PrintPulseAndReportSlowInput(Data, Size);
- size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore;
-
- if (NumNewFeatures) {
- TPC.UpdateObservedPCs();
- Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile,
- TPC.ObservedFocusFunction(), UniqFeatureSetTmp, DFT, II);
- return true;
- }
- if (II && FoundUniqFeaturesOfII &&
- II->DataFlowTraceForFocusFunction.empty() &&
- FoundUniqFeaturesOfII == II->UniqFeatureSet.size() &&
- II->U.size() > Size) {
- Corpus.Replace(II, {Data, Data + Size});
- return true;
- }
- return false;
-}
-
-size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
- assert(InFuzzingThread());
- *Data = CurrentUnitData;
- return CurrentUnitSize;
-}
-
-void Fuzzer::CrashOnOverwrittenData() {
- Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n",
- GetPid());
- DumpCurrentUnit("crash-");
- Printf("SUMMARY: libFuzzer: out-of-memory\n");
- _Exit(Options.ErrorExitCode); // Stop right now.
-}
-
-// Compare two arrays, but not all bytes if the arrays are large.
-static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
- const size_t Limit = 64;
- if (Size <= 64)
- return !memcmp(A, B, Size);
- // Compare first and last Limit/2 bytes.
- return !memcmp(A, B, Limit / 2) &&
- !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
-}
-
-void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
- TPC.RecordInitialStack();
- TotalNumberOfRuns++;
- assert(InFuzzingThread());
- if (SMR.IsClient())
- SMR.WriteByteArray(Data, Size);
- // We copy the contents of Unit into a separate heap buffer
- // so that we reliably find buffer overflows in it.
- uint8_t *DataCopy = new uint8_t[Size];
- memcpy(DataCopy, Data, Size);
- if (EF->__msan_unpoison)
- EF->__msan_unpoison(DataCopy, Size);
- if (CurrentUnitData && CurrentUnitData != Data)
- memcpy(CurrentUnitData, Data, Size);
- CurrentUnitSize = Size;
- {
- ScopedEnableMsanInterceptorChecks S;
- AllocTracer.Start(Options.TraceMalloc);
- UnitStartTime = system_clock::now();
- TPC.ResetMaps();
- RunningUserCallback = true;
- int Res = CB(DataCopy, Size);
- RunningUserCallback = false;
- UnitStopTime = system_clock::now();
- (void)Res;
- assert(Res == 0);
- HasMoreMallocsThanFrees = AllocTracer.Stop();
- }
- if (!LooseMemeq(DataCopy, Data, Size))
- CrashOnOverwrittenData();
- CurrentUnitSize = 0;
- delete[] DataCopy;
-}
-
-void Fuzzer::WriteToOutputCorpus(const Unit &U) {
- if (Options.OnlyASCII)
- assert(IsASCII(U));
- if (Options.OutputCorpus.empty())
- return;
- std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
- WriteToFile(U, Path);
- if (Options.Verbosity >= 2)
- Printf("Written %zd bytes to %s\n", U.size(), Path.c_str());
-}
-
-void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
- if (!Options.SaveArtifacts)
- return;
- std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
- if (!Options.ExactArtifactPath.empty())
- Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix.
- WriteToFile(U, Path);
- Printf("artifact_prefix='%s'; Test unit written to %s\n",
- Options.ArtifactPrefix.c_str(), Path.c_str());
- if (U.size() <= kMaxUnitSizeToPrint)
- Printf("Base64: %s\n", Base64(U).c_str());
-}
-
-void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) {
- if (!Options.PrintNEW)
- return;
- PrintStats(Text, "");
- if (Options.Verbosity) {
- Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize());
- MD.PrintMutationSequence();
- Printf("\n");
- }
-}
-
-void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
- II->NumSuccessfullMutations++;
- MD.RecordSuccessfulMutationSequence();
- PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW ");
- WriteToOutputCorpus(U);
- NumberOfNewUnitsAdded++;
- CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus.
- LastCorpusUpdateRun = TotalNumberOfRuns;
-}
-
-// Tries detecting a memory leak on the particular input that we have just
-// executed before calling this function.
-void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
- bool DuringInitialCorpusExecution) {
- if (!HasMoreMallocsThanFrees)
- return; // mallocs==frees, a leak is unlikely.
- if (!Options.DetectLeaks)
- return;
- if (!DuringInitialCorpusExecution &&
- TotalNumberOfRuns >= Options.MaxNumberOfRuns)
- return;
- if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) ||
- !(EF->__lsan_do_recoverable_leak_check))
- return; // No lsan.
- // Run the target once again, but with lsan disabled so that if there is
- // a real leak we do not report it twice.
- EF->__lsan_disable();
- ExecuteCallback(Data, Size);
- EF->__lsan_enable();
- if (!HasMoreMallocsThanFrees)
- return; // a leak is unlikely.
- if (NumberOfLeakDetectionAttempts++ > 1000) {
- Options.DetectLeaks = false;
- Printf("INFO: libFuzzer disabled leak detection after every mutation.\n"
- " Most likely the target function accumulates allocated\n"
- " memory in a global state w/o actually leaking it.\n"
- " You may try running this binary with -trace_malloc=[12]"
- " to get a trace of mallocs and frees.\n"
- " If LeakSanitizer is enabled in this process it will still\n"
- " run on the process shutdown.\n");
- return;
- }
- // Now perform the actual lsan pass. This is expensive and we must ensure
- // we don't call it too often.
- if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it.
- if (DuringInitialCorpusExecution)
- Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
- Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
- CurrentUnitSize = Size;
- DumpCurrentUnit("leak-");
- PrintFinalStats();
- _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on.
- }
-}
-
-void Fuzzer::MutateAndTestOne() {
- MD.StartMutationSequence();
-
- auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
- const auto &U = II.U;
- memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
- assert(CurrentUnitData);
- size_t Size = U.size();
- assert(Size <= MaxInputLen && "Oversized Unit");
- memcpy(CurrentUnitData, U.data(), Size);
-
- assert(MaxMutationLen > 0);
-
- size_t CurrentMaxMutationLen =
- Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen));
- assert(CurrentMaxMutationLen > 0);
-
- for (int i = 0; i < Options.MutateDepth; i++) {
- if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
- break;
- MaybeExitGracefully();
- size_t NewSize = 0;
- if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() &&
- Size <= CurrentMaxMutationLen)
- NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size,
- II.DataFlowTraceForFocusFunction);
- else
- NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen);
- assert(NewSize > 0 && "Mutator returned empty unit");
- assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit");
- Size = NewSize;
- II.NumExecutedMutations++;
-
- bool FoundUniqFeatures = false;
- bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II,
- &FoundUniqFeatures);
- TryDetectingAMemoryLeak(CurrentUnitData, Size,
- /*DuringInitialCorpusExecution*/ false);
- if (NewCov) {
- ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
- break; // We will mutate this input more in the next rounds.
- }
- if (Options.ReduceDepth && !FoundUniqFeatures)
- break;
- }
-}
-
-void Fuzzer::PurgeAllocator() {
- if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator)
- return;
- if (duration_cast<seconds>(system_clock::now() -
- LastAllocatorPurgeAttemptTime)
- .count() < Options.PurgeAllocatorIntervalSec)
- return;
-
- if (Options.RssLimitMb <= 0 ||
- GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2)
- EF->__sanitizer_purge_allocator();
-
- LastAllocatorPurgeAttemptTime = system_clock::now();
-}
-
-void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) {
- const size_t kMaxSaneLen = 1 << 20;
- const size_t kMinDefaultLen = 4096;
- Vector<SizedFile> SizedFiles;
- size_t MaxSize = 0;
- size_t MinSize = -1;
- size_t TotalSize = 0;
- size_t LastNumFiles = 0;
- for (auto &Dir : CorpusDirs) {
- GetSizedFilesFromDir(Dir, &SizedFiles);
- Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles,
- Dir.c_str());
- LastNumFiles = SizedFiles.size();
- }
- for (auto &File : SizedFiles) {
- MaxSize = Max(File.Size, MaxSize);
- MinSize = Min(File.Size, MinSize);
- TotalSize += File.Size;
- }
- if (Options.MaxLen == 0)
- SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen));
- assert(MaxInputLen > 0);
-
- // Test the callback with empty input and never try it again.
- uint8_t dummy = 0;
- ExecuteCallback(&dummy, 0);
-
- if (SizedFiles.empty()) {
- Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
- Unit U({'\n'}); // Valid ASCII input.
- RunOne(U.data(), U.size());
- } else {
- Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb"
- " rss: %zdMb\n",
- SizedFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb());
- if (Options.ShuffleAtStartUp)
- std::shuffle(SizedFiles.begin(), SizedFiles.end(), MD.GetRand());
-
- if (Options.PreferSmall) {
- std::stable_sort(SizedFiles.begin(), SizedFiles.end());
- assert(SizedFiles.front().Size <= SizedFiles.back().Size);
- }
-
- // Load and execute inputs one by one.
- for (auto &SF : SizedFiles) {
- auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false);
- assert(U.size() <= MaxInputLen);
- RunOne(U.data(), U.size());
- CheckExitOnSrcPosOrItem();
- TryDetectingAMemoryLeak(U.data(), U.size(),
- /*DuringInitialCorpusExecution*/ true);
- }
- }
-
- PrintStats("INITED");
- if (!Options.FocusFunction.empty())
- Printf("INFO: %zd/%zd inputs touch the focus function\n",
- Corpus.NumInputsThatTouchFocusFunction(), Corpus.size());
- if (!Options.DataFlowTrace.empty())
- Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n",
- Corpus.NumInputsWithDataFlowTrace(), Corpus.size());
-
- if (Corpus.empty() && Options.MaxNumberOfRuns) {
- Printf("ERROR: no interesting inputs were found. "
- "Is the code instrumented for coverage? Exiting.\n");
- exit(1);
- }
-}
-
-void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) {
- ReadAndExecuteSeedCorpora(CorpusDirs);
- DFT.Clear(); // No need for DFT any more.
- TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
- TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs);
- system_clock::time_point LastCorpusReload = system_clock::now();
- if (Options.DoCrossOver)
- MD.SetCorpus(&Corpus);
- while (true) {
- auto Now = system_clock::now();
- if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
- Options.ReloadIntervalSec) {
- RereadOutputCorpus(MaxInputLen);
- LastCorpusReload = system_clock::now();
- }
- if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
- break;
- if (TimedOut())
- break;
-
- // Update TmpMaxMutationLen
- if (Options.LenControl) {
- if (TmpMaxMutationLen < MaxMutationLen &&
- TotalNumberOfRuns - LastCorpusUpdateRun >
- Options.LenControl * Log(TmpMaxMutationLen)) {
- TmpMaxMutationLen =
- Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen));
- LastCorpusUpdateRun = TotalNumberOfRuns;
- }
- } else {
- TmpMaxMutationLen = MaxMutationLen;
- }
-
- // Perform several mutations and runs.
- MutateAndTestOne();
-
- PurgeAllocator();
- }
-
- PrintStats("DONE ", "\n");
- MD.PrintRecommendedDictionary();
-}
-
-void Fuzzer::MinimizeCrashLoop(const Unit &U) {
- if (U.size() <= 1)
- return;
- while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) {
- MD.StartMutationSequence();
- memcpy(CurrentUnitData, U.data(), U.size());
- for (int i = 0; i < Options.MutateDepth; i++) {
- size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen);
- assert(NewSize > 0 && NewSize <= MaxMutationLen);
- ExecuteCallback(CurrentUnitData, NewSize);
- PrintPulseAndReportSlowInput(CurrentUnitData, NewSize);
- TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
- /*DuringInitialCorpusExecution*/ false);
- }
- }
-}
-
-void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) {
- if (SMR.IsServer()) {
- SMR.WriteByteArray(Data, Size);
- } else if (SMR.IsClient()) {
- SMR.PostClient();
- SMR.WaitServer();
- size_t OtherSize = SMR.ReadByteArraySize();
- uint8_t *OtherData = SMR.GetByteArray();
- if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) {
- size_t i = 0;
- for (i = 0; i < Min(Size, OtherSize); i++)
- if (Data[i] != OtherData[i])
- break;
- Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; "
- "offset %zd\n",
- GetPid(), Size, OtherSize, i);
- DumpCurrentUnit("mismatch-");
- Printf("SUMMARY: libFuzzer: equivalence-mismatch\n");
- PrintFinalStats();
- _Exit(Options.ErrorExitCode);
- }
- }
-}
-
-} // namespace fuzzer
-
-extern "C" {
-
-__attribute__((visibility("default"))) size_t
-LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
- assert(fuzzer::F);
- return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
-}
-
-// Experimental
-__attribute__((visibility("default"))) void
-LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) {
- assert(fuzzer::F);
- fuzzer::F->AnnounceOutput(Data, Size);
-}
-} // extern "C"
diff --git a/chromium/third_party/libFuzzer/src/FuzzerMain.cpp b/chromium/third_party/libFuzzer/src/FuzzerMain.cpp
deleted file mode 100644
index f2c8e9c7bb1..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerMain.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-//===- FuzzerMain.cpp - main() function and flags -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// main() and flags.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerDefs.h"
-
-extern "C" {
-// This function should be defined by the user.
-int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
-} // extern "C"
-
-__attribute__((visibility("default"))) int main(int argc, char **argv) {
- return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput);
-}
diff --git a/chromium/third_party/libFuzzer/src/FuzzerMerge.cpp b/chromium/third_party/libFuzzer/src/FuzzerMerge.cpp
deleted file mode 100644
index 5f3052a39c1..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerMerge.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-//===- FuzzerMerge.cpp - merging corpora ----------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Merging corpora.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerCommand.h"
-#include "FuzzerMerge.h"
-#include "FuzzerIO.h"
-#include "FuzzerInternal.h"
-#include "FuzzerTracePC.h"
-#include "FuzzerUtil.h"
-
-#include <fstream>
-#include <iterator>
-#include <set>
-#include <sstream>
-
-namespace fuzzer {
-
-bool Merger::Parse(const std::string &Str, bool ParseCoverage) {
- std::istringstream SS(Str);
- return Parse(SS, ParseCoverage);
-}
-
-void Merger::ParseOrExit(std::istream &IS, bool ParseCoverage) {
- if (!Parse(IS, ParseCoverage)) {
- Printf("MERGE: failed to parse the control file (unexpected error)\n");
- exit(1);
- }
-}
-
-// The control file example:
-//
-// 3 # The number of inputs
-// 1 # The number of inputs in the first corpus, <= the previous number
-// file0
-// file1
-// file2 # One file name per line.
-// STARTED 0 123 # FileID, file size
-// DONE 0 1 4 6 8 # FileID COV1 COV2 ...
-// STARTED 1 456 # If DONE is missing, the input crashed while processing.
-// STARTED 2 567
-// DONE 2 8 9
-bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
- LastFailure.clear();
- std::string Line;
-
- // Parse NumFiles.
- if (!std::getline(IS, Line, '\n')) return false;
- std::istringstream L1(Line);
- size_t NumFiles = 0;
- L1 >> NumFiles;
- if (NumFiles == 0 || NumFiles > 10000000) return false;
-
- // Parse NumFilesInFirstCorpus.
- if (!std::getline(IS, Line, '\n')) return false;
- std::istringstream L2(Line);
- NumFilesInFirstCorpus = NumFiles + 1;
- L2 >> NumFilesInFirstCorpus;
- if (NumFilesInFirstCorpus > NumFiles) return false;
-
- // Parse file names.
- Files.resize(NumFiles);
- for (size_t i = 0; i < NumFiles; i++)
- if (!std::getline(IS, Files[i].Name, '\n'))
- return false;
-
- // Parse STARTED and DONE lines.
- size_t ExpectedStartMarker = 0;
- const size_t kInvalidStartMarker = -1;
- size_t LastSeenStartMarker = kInvalidStartMarker;
- Vector<uint32_t> TmpFeatures;
- while (std::getline(IS, Line, '\n')) {
- std::istringstream ISS1(Line);
- std::string Marker;
- size_t N;
- ISS1 >> Marker;
- ISS1 >> N;
- if (Marker == "STARTED") {
- // STARTED FILE_ID FILE_SIZE
- if (ExpectedStartMarker != N)
- return false;
- ISS1 >> Files[ExpectedStartMarker].Size;
- LastSeenStartMarker = ExpectedStartMarker;
- assert(ExpectedStartMarker < Files.size());
- ExpectedStartMarker++;
- } else if (Marker == "DONE") {
- // DONE FILE_ID COV1 COV2 COV3 ...
- size_t CurrentFileIdx = N;
- if (CurrentFileIdx != LastSeenStartMarker)
- return false;
- LastSeenStartMarker = kInvalidStartMarker;
- if (ParseCoverage) {
- TmpFeatures.clear(); // use a vector from outer scope to avoid resizes.
- while (ISS1 >> std::hex >> N)
- TmpFeatures.push_back(N);
- std::sort(TmpFeatures.begin(), TmpFeatures.end());
- Files[CurrentFileIdx].Features = TmpFeatures;
- }
- } else {
- return false;
- }
- }
- if (LastSeenStartMarker != kInvalidStartMarker)
- LastFailure = Files[LastSeenStartMarker].Name;
-
- FirstNotProcessedFile = ExpectedStartMarker;
- return true;
-}
-
-size_t Merger::ApproximateMemoryConsumption() const {
- size_t Res = 0;
- for (const auto &F: Files)
- Res += sizeof(F) + F.Features.size() * sizeof(F.Features[0]);
- return Res;
-}
-
-// Decides which files need to be merged (add thost to NewFiles).
-// Returns the number of new features added.
-size_t Merger::Merge(const Set<uint32_t> &InitialFeatures,
- Vector<std::string> *NewFiles) {
- NewFiles->clear();
- assert(NumFilesInFirstCorpus <= Files.size());
- Set<uint32_t> AllFeatures(InitialFeatures);
-
- // What features are in the initial corpus?
- for (size_t i = 0; i < NumFilesInFirstCorpus; i++) {
- auto &Cur = Files[i].Features;
- AllFeatures.insert(Cur.begin(), Cur.end());
- }
- size_t InitialNumFeatures = AllFeatures.size();
-
- // Remove all features that we already know from all other inputs.
- for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) {
- auto &Cur = Files[i].Features;
- Vector<uint32_t> Tmp;
- std::set_difference(Cur.begin(), Cur.end(), AllFeatures.begin(),
- AllFeatures.end(), std::inserter(Tmp, Tmp.begin()));
- Cur.swap(Tmp);
- }
-
- // Sort. Give preference to
- // * smaller files
- // * files with more features.
- std::sort(Files.begin() + NumFilesInFirstCorpus, Files.end(),
- [&](const MergeFileInfo &a, const MergeFileInfo &b) -> bool {
- if (a.Size != b.Size)
- return a.Size < b.Size;
- return a.Features.size() > b.Features.size();
- });
-
- // One greedy pass: add the file's features to AllFeatures.
- // If new features were added, add this file to NewFiles.
- for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) {
- auto &Cur = Files[i].Features;
- // Printf("%s -> sz %zd ft %zd\n", Files[i].Name.c_str(),
- // Files[i].Size, Cur.size());
- size_t OldSize = AllFeatures.size();
- AllFeatures.insert(Cur.begin(), Cur.end());
- if (AllFeatures.size() > OldSize)
- NewFiles->push_back(Files[i].Name);
- }
- return AllFeatures.size() - InitialNumFeatures;
-}
-
-void Merger::PrintSummary(std::ostream &OS) {
- for (auto &File : Files) {
- OS << std::hex;
- OS << File.Name << " size: " << File.Size << " features: ";
- for (auto Feature : File.Features)
- OS << " " << Feature;
- OS << "\n";
- }
-}
-
-Set<uint32_t> Merger::AllFeatures() const {
- Set<uint32_t> S;
- for (auto &File : Files)
- S.insert(File.Features.begin(), File.Features.end());
- return S;
-}
-
-Set<uint32_t> Merger::ParseSummary(std::istream &IS) {
- std::string Line, Tmp;
- Set<uint32_t> Res;
- while (std::getline(IS, Line, '\n')) {
- size_t N;
- std::istringstream ISS1(Line);
- ISS1 >> Tmp; // Name
- ISS1 >> Tmp; // size:
- assert(Tmp == "size:" && "Corrupt summary file");
- ISS1 >> std::hex;
- ISS1 >> N; // File Size
- ISS1 >> Tmp; // features:
- assert(Tmp == "features:" && "Corrupt summary file");
- while (ISS1 >> std::hex >> N)
- Res.insert(N);
- }
- return Res;
-}
-
-// Inner process. May crash if the target crashes.
-void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) {
- Printf("MERGE-INNER: using the control file '%s'\n", CFPath.c_str());
- Merger M;
- std::ifstream IF(CFPath);
- M.ParseOrExit(IF, false);
- IF.close();
- if (!M.LastFailure.empty())
- Printf("MERGE-INNER: '%s' caused a failure at the previous merge step\n",
- M.LastFailure.c_str());
-
- Printf("MERGE-INNER: %zd total files;"
- " %zd processed earlier; will process %zd files now\n",
- M.Files.size(), M.FirstNotProcessedFile,
- M.Files.size() - M.FirstNotProcessedFile);
-
- std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app);
- Set<size_t> AllFeatures;
- for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) {
- MaybeExitGracefully();
- auto U = FileToVector(M.Files[i].Name);
- if (U.size() > MaxInputLen) {
- U.resize(MaxInputLen);
- U.shrink_to_fit();
- }
- std::ostringstream StartedLine;
- // Write the pre-run marker.
- OF << "STARTED " << std::dec << i << " " << U.size() << "\n";
- OF.flush(); // Flush is important since Command::Execute may crash.
- // Run.
- TPC.ResetMaps();
- ExecuteCallback(U.data(), U.size());
- // Collect coverage. We are iterating over the files in this order:
- // * First, files in the initial corpus ordered by size, smallest first.
- // * Then, all other files, smallest first.
- // So it makes no sense to record all features for all files, instead we
- // only record features that were not seen before.
- Set<size_t> UniqFeatures;
- TPC.CollectFeatures([&](size_t Feature) {
- if (AllFeatures.insert(Feature).second)
- UniqFeatures.insert(Feature);
- });
- // Show stats.
- if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)))
- PrintStats("pulse ");
- // Write the post-run marker and the coverage.
- OF << "DONE " << i;
- for (size_t F : UniqFeatures)
- OF << " " << std::hex << F;
- OF << "\n";
- OF.flush();
- }
-}
-
-static void WriteNewControlFile(const std::string &CFPath,
- const Vector<SizedFile> &AllFiles,
- size_t NumFilesInFirstCorpus) {
- RemoveFile(CFPath);
- std::ofstream ControlFile(CFPath);
- ControlFile << AllFiles.size() << "\n";
- ControlFile << NumFilesInFirstCorpus << "\n";
- for (auto &SF: AllFiles)
- ControlFile << SF.File << "\n";
- if (!ControlFile) {
- Printf("MERGE-OUTER: failed to write to the control file: %s\n",
- CFPath.c_str());
- exit(1);
- }
-}
-
-// Outer process. Does not call the target code and thus sohuld not fail.
-void Fuzzer::CrashResistantMerge(const Vector<std::string> &Args,
- const Vector<std::string> &Corpora,
- const char *CoverageSummaryInputPathOrNull,
- const char *CoverageSummaryOutputPathOrNull,
- const char *MergeControlFilePathOrNull) {
- if (Corpora.size() <= 1) {
- Printf("Merge requires two or more corpus dirs\n");
- return;
- }
- auto CFPath =
- MergeControlFilePathOrNull
- ? MergeControlFilePathOrNull
- : DirPlusFile(TmpDir(),
- "libFuzzerTemp." + std::to_string(GetPid()) + ".txt");
-
- size_t NumAttempts = 0;
- if (MergeControlFilePathOrNull && FileSize(MergeControlFilePathOrNull)) {
- Printf("MERGE-OUTER: non-empty control file provided: '%s'\n",
- MergeControlFilePathOrNull);
- Merger M;
- std::ifstream IF(MergeControlFilePathOrNull);
- if (M.Parse(IF, /*ParseCoverage=*/false)) {
- Printf("MERGE-OUTER: control file ok, %zd files total,"
- " first not processed file %zd\n",
- M.Files.size(), M.FirstNotProcessedFile);
- if (!M.LastFailure.empty())
- Printf("MERGE-OUTER: '%s' will be skipped as unlucky "
- "(merge has stumbled on it the last time)\n",
- M.LastFailure.c_str());
- if (M.FirstNotProcessedFile >= M.Files.size()) {
- Printf("MERGE-OUTER: nothing to do, merge has been completed before\n");
- exit(0);
- }
-
- NumAttempts = M.Files.size() - M.FirstNotProcessedFile;
- } else {
- Printf("MERGE-OUTER: bad control file, will overwrite it\n");
- }
- }
-
- if (!NumAttempts) {
- // The supplied control file is empty or bad, create a fresh one.
- Vector<SizedFile> AllFiles;
- GetSizedFilesFromDir(Corpora[0], &AllFiles);
- size_t NumFilesInFirstCorpus = AllFiles.size();
- std::sort(AllFiles.begin(), AllFiles.end());
- for (size_t i = 1; i < Corpora.size(); i++)
- GetSizedFilesFromDir(Corpora[i], &AllFiles);
- std::sort(AllFiles.begin() + NumFilesInFirstCorpus, AllFiles.end());
- Printf("MERGE-OUTER: %zd files, %zd in the initial corpus\n",
- AllFiles.size(), NumFilesInFirstCorpus);
- WriteNewControlFile(CFPath, AllFiles, NumFilesInFirstCorpus);
- NumAttempts = AllFiles.size();
- }
-
- // Execute the inner process until it passes.
- // Every inner process should execute at least one input.
- Command BaseCmd(Args);
- BaseCmd.removeFlag("merge");
- bool Success = false;
- for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) {
- MaybeExitGracefully();
- Printf("MERGE-OUTER: attempt %zd\n", Attempt);
- Command Cmd(BaseCmd);
- Cmd.addFlag("merge_control_file", CFPath);
- Cmd.addFlag("merge_inner", "1");
- auto ExitCode = ExecuteCommand(Cmd);
- if (!ExitCode) {
- Printf("MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt);
- Success = true;
- break;
- }
- }
- if (!Success) {
- Printf("MERGE-OUTER: zero succesfull attempts, exiting\n");
- exit(1);
- }
- // Read the control file and do the merge.
- Merger M;
- std::ifstream IF(CFPath);
- IF.seekg(0, IF.end);
- Printf("MERGE-OUTER: the control file has %zd bytes\n", (size_t)IF.tellg());
- IF.seekg(0, IF.beg);
- M.ParseOrExit(IF, true);
- IF.close();
- Printf("MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n",
- M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb());
- if (CoverageSummaryOutputPathOrNull) {
- Printf("MERGE-OUTER: writing coverage summary for %zd files to %s\n",
- M.Files.size(), CoverageSummaryOutputPathOrNull);
- std::ofstream SummaryOut(CoverageSummaryOutputPathOrNull);
- M.PrintSummary(SummaryOut);
- }
- Vector<std::string> NewFiles;
- Set<uint32_t> InitialFeatures;
- if (CoverageSummaryInputPathOrNull) {
- std::ifstream SummaryIn(CoverageSummaryInputPathOrNull);
- InitialFeatures = M.ParseSummary(SummaryIn);
- Printf("MERGE-OUTER: coverage summary loaded from %s, %zd features found\n",
- CoverageSummaryInputPathOrNull, InitialFeatures.size());
- }
- size_t NumNewFeatures = M.Merge(InitialFeatures, &NewFiles);
- Printf("MERGE-OUTER: %zd new files with %zd new features added\n",
- NewFiles.size(), NumNewFeatures);
- for (auto &F: NewFiles)
- WriteToOutputCorpus(FileToVector(F, MaxInputLen));
- // We are done, delete the control file if it was a temporary one.
- if (!MergeControlFilePathOrNull)
- RemoveFile(CFPath);
-}
-
-} // namespace fuzzer
diff --git a/chromium/third_party/libFuzzer/src/FuzzerMerge.h b/chromium/third_party/libFuzzer/src/FuzzerMerge.h
deleted file mode 100644
index e54885a1eba..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerMerge.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//===- FuzzerMerge.h - merging corpa ----------------------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Merging Corpora.
-//
-// The task:
-// Take the existing corpus (possibly empty) and merge new inputs into
-// it so that only inputs with new coverage ('features') are added.
-// The process should tolerate the crashes, OOMs, leaks, etc.
-//
-// Algorithm:
-// The outter process collects the set of files and writes their names
-// into a temporary "control" file, then repeatedly launches the inner
-// process until all inputs are processed.
-// The outer process does not actually execute the target code.
-//
-// The inner process reads the control file and sees a) list of all the inputs
-// and b) the last processed input. Then it starts processing the inputs one
-// by one. Before processing every input it writes one line to control file:
-// STARTED INPUT_ID INPUT_SIZE
-// After processing an input it write another line:
-// DONE INPUT_ID Feature1 Feature2 Feature3 ...
-// If a crash happens while processing an input the last line in the control
-// file will be "STARTED INPUT_ID" and so the next process will know
-// where to resume.
-//
-// Once all inputs are processed by the innner process(es) the outer process
-// reads the control files and does the merge based entirely on the contents
-// of control file.
-// It uses a single pass greedy algorithm choosing first the smallest inputs
-// within the same size the inputs that have more new features.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_MERGE_H
-#define LLVM_FUZZER_MERGE_H
-
-#include "FuzzerDefs.h"
-
-#include <istream>
-#include <ostream>
-#include <set>
-#include <vector>
-
-namespace fuzzer {
-
-struct MergeFileInfo {
- std::string Name;
- size_t Size = 0;
- Vector<uint32_t> Features;
-};
-
-struct Merger {
- Vector<MergeFileInfo> Files;
- size_t NumFilesInFirstCorpus = 0;
- size_t FirstNotProcessedFile = 0;
- std::string LastFailure;
-
- bool Parse(std::istream &IS, bool ParseCoverage);
- bool Parse(const std::string &Str, bool ParseCoverage);
- void ParseOrExit(std::istream &IS, bool ParseCoverage);
- void PrintSummary(std::ostream &OS);
- Set<uint32_t> ParseSummary(std::istream &IS);
- size_t Merge(const Set<uint32_t> &InitialFeatures,
- Vector<std::string> *NewFiles);
- size_t Merge(Vector<std::string> *NewFiles) {
- return Merge(Set<uint32_t>{}, NewFiles);
- }
- size_t ApproximateMemoryConsumption() const;
- Set<uint32_t> AllFeatures() const;
-};
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_MERGE_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerMutate.cpp b/chromium/third_party/libFuzzer/src/FuzzerMutate.cpp
deleted file mode 100644
index 142b2b0b001..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerMutate.cpp
+++ /dev/null
@@ -1,562 +0,0 @@
-//===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Mutate a test input.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerMutate.h"
-#include "FuzzerCorpus.h"
-#include "FuzzerDefs.h"
-#include "FuzzerExtFunctions.h"
-#include "FuzzerIO.h"
-#include "FuzzerOptions.h"
-
-namespace fuzzer {
-
-const size_t Dictionary::kMaxDictSize;
-
-static void PrintASCII(const Word &W, const char *PrintAfter) {
- PrintASCII(W.data(), W.size(), PrintAfter);
-}
-
-MutationDispatcher::MutationDispatcher(Random &Rand,
- const FuzzingOptions &Options)
- : Rand(Rand), Options(Options) {
- DefaultMutators.insert(
- DefaultMutators.begin(),
- {
- {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
- {&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
- {&MutationDispatcher::Mutate_InsertRepeatedBytes,
- "InsertRepeatedBytes"},
- {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
- {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
- {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
- {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
- {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
- {&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
- {&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
- {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
- "ManualDict"},
- {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
- "PersAutoDict"},
- });
- if(Options.UseCmp)
- DefaultMutators.push_back(
- {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
-
- if (EF->LLVMFuzzerCustomMutator)
- Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
- else
- Mutators = DefaultMutators;
-
- if (EF->LLVMFuzzerCustomCrossOver)
- Mutators.push_back(
- {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
-}
-
-static char RandCh(Random &Rand) {
- if (Rand.RandBool()) return Rand(256);
- const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
- return Special[Rand(sizeof(Special) - 1)];
-}
-
-size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand());
-}
-
-size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (!Corpus || Corpus->size() < 2 || Size == 0)
- return 0;
- size_t Idx = Rand(Corpus->size());
- const Unit &Other = (*Corpus)[Idx];
- if (Other.empty())
- return 0;
- CustomCrossOverInPlaceHere.resize(MaxSize);
- auto &U = CustomCrossOverInPlaceHere;
- size_t NewSize = EF->LLVMFuzzerCustomCrossOver(
- Data, Size, Other.data(), Other.size(), U.data(), U.size(), Rand.Rand());
- if (!NewSize)
- return 0;
- assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
- memcpy(Data, U.data(), NewSize);
- return NewSize;
-}
-
-size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (Size > MaxSize || Size == 0) return 0;
- size_t ShuffleAmount =
- Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
- size_t ShuffleStart = Rand(Size - ShuffleAmount);
- assert(ShuffleStart + ShuffleAmount <= Size);
- std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
- return Size;
-}
-
-size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (Size <= 1) return 0;
- size_t N = Rand(Size / 2) + 1;
- assert(N < Size);
- size_t Idx = Rand(Size - N + 1);
- // Erase Data[Idx:Idx+N].
- memmove(Data + Idx, Data + Idx + N, Size - Idx - N);
- // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx);
- return Size - N;
-}
-
-size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (Size >= MaxSize) return 0;
- size_t Idx = Rand(Size + 1);
- // Insert new value at Data[Idx].
- memmove(Data + Idx + 1, Data + Idx, Size - Idx);
- Data[Idx] = RandCh(Rand);
- return Size + 1;
-}
-
-size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
- size_t Size,
- size_t MaxSize) {
- const size_t kMinBytesToInsert = 3;
- if (Size + kMinBytesToInsert >= MaxSize) return 0;
- size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128);
- size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert;
- assert(Size + N <= MaxSize && N);
- size_t Idx = Rand(Size + 1);
- // Insert new values at Data[Idx].
- memmove(Data + Idx + N, Data + Idx, Size - Idx);
- // Give preference to 0x00 and 0xff.
- uint8_t Byte = Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255);
- for (size_t i = 0; i < N; i++)
- Data[Idx + i] = Byte;
- return Size + N;
-}
-
-size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (Size > MaxSize) return 0;
- size_t Idx = Rand(Size);
- Data[Idx] = RandCh(Rand);
- return Size;
-}
-
-size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (Size > MaxSize) return 0;
- size_t Idx = Rand(Size);
- Data[Idx] ^= 1 << Rand(8);
- return Size;
-}
-
-size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data,
- size_t Size,
- size_t MaxSize) {
- return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize);
-}
-
-size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size,
- size_t MaxSize,
- DictionaryEntry &DE) {
- const Word &W = DE.GetW();
- bool UsePositionHint = DE.HasPositionHint() &&
- DE.GetPositionHint() + W.size() < Size &&
- Rand.RandBool();
- if (Rand.RandBool()) { // Insert W.
- if (Size + W.size() > MaxSize) return 0;
- size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1);
- memmove(Data + Idx + W.size(), Data + Idx, Size - Idx);
- memcpy(Data + Idx, W.data(), W.size());
- Size += W.size();
- } else { // Overwrite some bytes with W.
- if (W.size() > Size) return 0;
- size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size - W.size());
- memcpy(Data + Idx, W.data(), W.size());
- }
- return Size;
-}
-
-// Somewhere in the past we have observed a comparison instructions
-// with arguments Arg1 Arg2. This function tries to guess a dictionary
-// entry that will satisfy that comparison.
-// It first tries to find one of the arguments (possibly swapped) in the
-// input and if it succeeds it creates a DE with a position hint.
-// Otherwise it creates a DE with one of the arguments w/o a position hint.
-DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
- const void *Arg1, const void *Arg2,
- const void *Arg1Mutation, const void *Arg2Mutation,
- size_t ArgSize, const uint8_t *Data,
- size_t Size) {
- bool HandleFirst = Rand.RandBool();
- const void *ExistingBytes, *DesiredBytes;
- Word W;
- const uint8_t *End = Data + Size;
- for (int Arg = 0; Arg < 2; Arg++) {
- ExistingBytes = HandleFirst ? Arg1 : Arg2;
- DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation;
- HandleFirst = !HandleFirst;
- W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize);
- const size_t kMaxNumPositions = 8;
- size_t Positions[kMaxNumPositions];
- size_t NumPositions = 0;
- for (const uint8_t *Cur = Data;
- Cur < End && NumPositions < kMaxNumPositions; Cur++) {
- Cur =
- (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize);
- if (!Cur) break;
- Positions[NumPositions++] = Cur - Data;
- }
- if (!NumPositions) continue;
- return DictionaryEntry(W, Positions[Rand(NumPositions)]);
- }
- DictionaryEntry DE(W);
- return DE;
-}
-
-
-template <class T>
-DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
- T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
- if (Rand.RandBool()) Arg1 = Bswap(Arg1);
- if (Rand.RandBool()) Arg2 = Bswap(Arg2);
- T Arg1Mutation = Arg1 + Rand(-1, 1);
- T Arg2Mutation = Arg2 + Rand(-1, 1);
- return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
- sizeof(Arg1), Data, Size);
-}
-
-DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
- const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) {
- return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(),
- Arg2.data(), Arg1.size(), Data, Size);
-}
-
-size_t MutationDispatcher::Mutate_AddWordFromTORC(
- uint8_t *Data, size_t Size, size_t MaxSize) {
- Word W;
- DictionaryEntry DE;
- switch (Rand(4)) {
- case 0: {
- auto X = TPC.TORC8.Get(Rand.Rand());
- DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
- } break;
- case 1: {
- auto X = TPC.TORC4.Get(Rand.Rand());
- if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
- DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
- else
- DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
- } break;
- case 2: {
- auto X = TPC.TORCW.Get(Rand.Rand());
- DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
- } break;
- case 3: if (Options.UseMemmem) {
- auto X = TPC.MMT.Get(Rand.Rand());
- DE = DictionaryEntry(X);
- } break;
- default:
- assert(0);
- }
- if (!DE.GetW().size()) return 0;
- Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
- if (!Size) return 0;
- DictionaryEntry &DERef =
- CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ %
- kCmpDictionaryEntriesDequeSize];
- DERef = DE;
- CurrentDictionaryEntrySequence.push_back(&DERef);
- return Size;
-}
-
-size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary(
- uint8_t *Data, size_t Size, size_t MaxSize) {
- return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize);
-}
-
-size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data,
- size_t Size, size_t MaxSize) {
- if (Size > MaxSize) return 0;
- if (D.empty()) return 0;
- DictionaryEntry &DE = D[Rand(D.size())];
- Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE);
- if (!Size) return 0;
- DE.IncUseCount();
- CurrentDictionaryEntrySequence.push_back(&DE);
- return Size;
-}
-
-// Overwrites part of To[0,ToSize) with a part of From[0,FromSize).
-// Returns ToSize.
-size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize,
- uint8_t *To, size_t ToSize) {
- // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize).
- size_t ToBeg = Rand(ToSize);
- size_t CopySize = Rand(ToSize - ToBeg) + 1;
- assert(ToBeg + CopySize <= ToSize);
- CopySize = std::min(CopySize, FromSize);
- size_t FromBeg = Rand(FromSize - CopySize + 1);
- assert(FromBeg + CopySize <= FromSize);
- memmove(To + ToBeg, From + FromBeg, CopySize);
- return ToSize;
-}
-
-// Inserts part of From[0,ToSize) into To.
-// Returns new size of To on success or 0 on failure.
-size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,
- uint8_t *To, size_t ToSize,
- size_t MaxToSize) {
- if (ToSize >= MaxToSize) return 0;
- size_t AvailableSpace = MaxToSize - ToSize;
- size_t MaxCopySize = std::min(AvailableSpace, FromSize);
- size_t CopySize = Rand(MaxCopySize) + 1;
- size_t FromBeg = Rand(FromSize - CopySize + 1);
- assert(FromBeg + CopySize <= FromSize);
- size_t ToInsertPos = Rand(ToSize + 1);
- assert(ToInsertPos + CopySize <= MaxToSize);
- size_t TailSize = ToSize - ToInsertPos;
- if (To == From) {
- MutateInPlaceHere.resize(MaxToSize);
- memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize);
- memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
- memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize);
- } else {
- memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize);
- memmove(To + ToInsertPos, From + FromBeg, CopySize);
- }
- return ToSize + CopySize;
-}
-
-size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (Size > MaxSize || Size == 0) return 0;
- // If Size == MaxSize, `InsertPartOf(...)` will
- // fail so there's no point using it in this case.
- if (Size == MaxSize || Rand.RandBool())
- return CopyPartOf(Data, Size, Data, Size);
- else
- return InsertPartOf(Data, Size, Data, Size, MaxSize);
-}
-
-size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (Size > MaxSize) return 0;
- size_t B = Rand(Size);
- while (B < Size && !isdigit(Data[B])) B++;
- if (B == Size) return 0;
- size_t E = B;
- while (E < Size && isdigit(Data[E])) E++;
- assert(B < E);
- // now we have digits in [B, E).
- // strtol and friends don't accept non-zero-teminated data, parse it manually.
- uint64_t Val = Data[B] - '0';
- for (size_t i = B + 1; i < E; i++)
- Val = Val * 10 + Data[i] - '0';
-
- // Mutate the integer value.
- switch(Rand(5)) {
- case 0: Val++; break;
- case 1: Val--; break;
- case 2: Val /= 2; break;
- case 3: Val *= 2; break;
- case 4: Val = Rand(Val * Val); break;
- default: assert(0);
- }
- // Just replace the bytes with the new ones, don't bother moving bytes.
- for (size_t i = B; i < E; i++) {
- size_t Idx = E + B - i - 1;
- assert(Idx >= B && Idx < E);
- Data[Idx] = (Val % 10) + '0';
- Val /= 10;
- }
- return Size;
-}
-
-template<class T>
-size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
- if (Size < sizeof(T)) return 0;
- size_t Off = Rand(Size - sizeof(T) + 1);
- assert(Off + sizeof(T) <= Size);
- T Val;
- if (Off < 64 && !Rand(4)) {
- Val = Size;
- if (Rand.RandBool())
- Val = Bswap(Val);
- } else {
- memcpy(&Val, Data + Off, sizeof(Val));
- T Add = Rand(21);
- Add -= 10;
- if (Rand.RandBool())
- Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
- else
- Val = Val + Add; // Add assuming current endiannes.
- if (Add == 0 || Rand.RandBool()) // Maybe negate.
- Val = -Val;
- }
- memcpy(Data + Off, &Val, sizeof(Val));
- return Size;
-}
-
-size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
- size_t Size,
- size_t MaxSize) {
- if (Size > MaxSize) return 0;
- switch (Rand(4)) {
- case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
- case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
- case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
- case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
- default: assert(0);
- }
- return 0;
-}
-
-size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- if (Size > MaxSize) return 0;
- if (!Corpus || Corpus->size() < 2 || Size == 0) return 0;
- size_t Idx = Rand(Corpus->size());
- const Unit &O = (*Corpus)[Idx];
- if (O.empty()) return 0;
- MutateInPlaceHere.resize(MaxSize);
- auto &U = MutateInPlaceHere;
- size_t NewSize = 0;
- switch(Rand(3)) {
- case 0:
- NewSize = CrossOver(Data, Size, O.data(), O.size(), U.data(), U.size());
- break;
- case 1:
- NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize);
- if (!NewSize)
- NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size());
- break;
- case 2:
- NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size());
- break;
- default: assert(0);
- }
- assert(NewSize > 0 && "CrossOver returned empty unit");
- assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
- memcpy(Data, U.data(), NewSize);
- return NewSize;
-}
-
-void MutationDispatcher::StartMutationSequence() {
- CurrentMutatorSequence.clear();
- CurrentDictionaryEntrySequence.clear();
-}
-
-// Copy successful dictionary entries to PersistentAutoDictionary.
-void MutationDispatcher::RecordSuccessfulMutationSequence() {
- for (auto DE : CurrentDictionaryEntrySequence) {
- // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
- DE->IncSuccessCount();
- assert(DE->GetW().size());
- // Linear search is fine here as this happens seldom.
- if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
- PersistentAutoDictionary.push_back({DE->GetW(), 1});
- }
-}
-
-void MutationDispatcher::PrintRecommendedDictionary() {
- Vector<DictionaryEntry> V;
- for (auto &DE : PersistentAutoDictionary)
- if (!ManualDictionary.ContainsWord(DE.GetW()))
- V.push_back(DE);
- if (V.empty()) return;
- Printf("###### Recommended dictionary. ######\n");
- for (auto &DE: V) {
- assert(DE.GetW().size());
- Printf("\"");
- PrintASCII(DE.GetW(), "\"");
- Printf(" # Uses: %zd\n", DE.GetUseCount());
- }
- Printf("###### End of recommended dictionary. ######\n");
-}
-
-void MutationDispatcher::PrintMutationSequence() {
- Printf("MS: %zd ", CurrentMutatorSequence.size());
- for (auto M : CurrentMutatorSequence)
- Printf("%s-", M.Name);
- if (!CurrentDictionaryEntrySequence.empty()) {
- Printf(" DE: ");
- for (auto DE : CurrentDictionaryEntrySequence) {
- Printf("\"");
- PrintASCII(DE->GetW(), "\"-");
- }
- }
-}
-
-size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
- return MutateImpl(Data, Size, MaxSize, Mutators);
-}
-
-size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
- size_t MaxSize) {
- return MutateImpl(Data, Size, MaxSize, DefaultMutators);
-}
-
-// Mutates Data in place, returns new size.
-size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
- size_t MaxSize,
- Vector<Mutator> &Mutators) {
- assert(MaxSize > 0);
- // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize),
- // in which case they will return 0.
- // Try several times before returning un-mutated data.
- for (int Iter = 0; Iter < 100; Iter++) {
- auto M = Mutators[Rand(Mutators.size())];
- size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize);
- if (NewSize && NewSize <= MaxSize) {
- if (Options.OnlyASCII)
- ToASCII(Data, NewSize);
- CurrentMutatorSequence.push_back(M);
- return NewSize;
- }
- }
- *Data = ' ';
- return 1; // Fallback, should not happen frequently.
-}
-
-// Mask represents the set of Data bytes that are worth mutating.
-size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size,
- size_t MaxSize,
- const Vector<uint8_t> &Mask) {
- assert(Size <= Mask.size());
- // * Copy the worthy bytes into a temporary array T
- // * Mutate T
- // * Copy T back.
- // This is totally unoptimized.
- auto &T = MutateWithMaskTemp;
- if (T.size() < Size)
- T.resize(Size);
- size_t OneBits = 0;
- for (size_t I = 0; I < Size; I++)
- if (Mask[I])
- T[OneBits++] = Data[I];
-
- assert(!T.empty());
- size_t NewSize = Mutate(T.data(), OneBits, OneBits);
- assert(NewSize <= OneBits);
- (void)NewSize;
- // Even if NewSize < OneBits we still use all OneBits bytes.
- for (size_t I = 0, J = 0; I < Size; I++)
- if (Mask[I])
- Data[I] = T[J++];
- return Size;
-}
-
-void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
- ManualDictionary.push_back(
- {W, std::numeric_limits<size_t>::max()});
-}
-
-} // namespace fuzzer
diff --git a/chromium/third_party/libFuzzer/src/FuzzerMutate.h b/chromium/third_party/libFuzzer/src/FuzzerMutate.h
deleted file mode 100644
index a51c7fb44d4..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerMutate.h
+++ /dev/null
@@ -1,157 +0,0 @@
-//===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// fuzzer::MutationDispatcher
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_MUTATE_H
-#define LLVM_FUZZER_MUTATE_H
-
-#include "FuzzerDefs.h"
-#include "FuzzerDictionary.h"
-#include "FuzzerOptions.h"
-#include "FuzzerRandom.h"
-
-namespace fuzzer {
-
-class MutationDispatcher {
-public:
- MutationDispatcher(Random &Rand, const FuzzingOptions &Options);
- ~MutationDispatcher() {}
- /// Indicate that we are about to start a new sequence of mutations.
- void StartMutationSequence();
- /// Print the current sequence of mutations.
- void PrintMutationSequence();
- /// Indicate that the current sequence of mutations was successful.
- void RecordSuccessfulMutationSequence();
- /// Mutates data by invoking user-provided mutator.
- size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by invoking user-provided crossover.
- size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by shuffling bytes.
- size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by erasing bytes.
- size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by inserting a byte.
- size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by inserting several repeated bytes.
- size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by chanding one byte.
- size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by chanding one bit.
- size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Mutates data by copying/inserting a part of data into a different place.
- size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize);
-
- /// Mutates data by adding a word from the manual dictionary.
- size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size,
- size_t MaxSize);
-
- /// Mutates data by adding a word from the TORC.
- size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize);
-
- /// Mutates data by adding a word from the persistent automatic dictionary.
- size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size,
- size_t MaxSize);
-
- /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
- size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
- /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
- size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize);
-
- /// CrossOver Data with some other element of the corpus.
- size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
-
- /// Applies one of the configured mutations.
- /// Returns the new size of data which could be up to MaxSize.
- size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
-
- /// Applies one of the configured mutations to the bytes of Data
- /// that have '1' in Mask.
- /// Mask.size() should be >= Size.
- size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize,
- const Vector<uint8_t> &Mask);
-
- /// Applies one of the default mutations. Provided as a service
- /// to mutation authors.
- size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize);
-
- /// Creates a cross-over of two pieces of Data, returns its size.
- size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
- size_t Size2, uint8_t *Out, size_t MaxOutSize);
-
- void AddWordToManualDictionary(const Word &W);
-
- void PrintRecommendedDictionary();
-
- void SetCorpus(const InputCorpus *Corpus) { this->Corpus = Corpus; }
-
- Random &GetRand() { return Rand; }
-
- private:
- struct Mutator {
- size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
- const char *Name;
- };
-
- size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
- size_t MaxSize);
- size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize,
- Vector<Mutator> &Mutators);
-
- size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
- size_t ToSize, size_t MaxToSize);
- size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To,
- size_t ToSize);
- size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize,
- DictionaryEntry &DE);
-
- template <class T>
- DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2,
- const uint8_t *Data, size_t Size);
- DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2,
- const uint8_t *Data, size_t Size);
- DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2,
- const void *Arg1Mutation,
- const void *Arg2Mutation,
- size_t ArgSize,
- const uint8_t *Data, size_t Size);
-
- Random &Rand;
- const FuzzingOptions Options;
-
- // Dictionary provided by the user via -dict=DICT_FILE.
- Dictionary ManualDictionary;
- // Temporary dictionary modified by the fuzzer itself,
- // recreated periodically.
- Dictionary TempAutoDictionary;
- // Persistent dictionary modified by the fuzzer, consists of
- // entries that led to successful discoveries in the past mutations.
- Dictionary PersistentAutoDictionary;
-
- Vector<DictionaryEntry *> CurrentDictionaryEntrySequence;
-
- static const size_t kCmpDictionaryEntriesDequeSize = 16;
- DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize];
- size_t CmpDictionaryEntriesDequeIdx = 0;
-
- const InputCorpus *Corpus = nullptr;
- Vector<uint8_t> MutateInPlaceHere;
- Vector<uint8_t> MutateWithMaskTemp;
- // CustomCrossOver needs its own buffer as a custom implementation may call
- // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere.
- Vector<uint8_t> CustomCrossOverInPlaceHere;
-
- Vector<Mutator> Mutators;
- Vector<Mutator> DefaultMutators;
- Vector<Mutator> CurrentMutatorSequence;
-};
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_MUTATE_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerOptions.h b/chromium/third_party/libFuzzer/src/FuzzerOptions.h
deleted file mode 100644
index bb642f1e236..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerOptions.h
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// fuzzer::FuzzingOptions
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_OPTIONS_H
-#define LLVM_FUZZER_OPTIONS_H
-
-#include "FuzzerDefs.h"
-
-namespace fuzzer {
-
-struct FuzzingOptions {
- int Verbosity = 1;
- size_t MaxLen = 0;
- size_t LenControl = 1000;
- int UnitTimeoutSec = 300;
- int TimeoutExitCode = 77;
- int ErrorExitCode = 77;
- int MaxTotalTimeSec = 0;
- int RssLimitMb = 0;
- int MallocLimitMb = 0;
- bool DoCrossOver = true;
- int MutateDepth = 5;
- bool ReduceDepth = false;
- bool UseCounters = false;
- bool UseMemmem = true;
- bool UseCmp = false;
- int UseValueProfile = false;
- bool Shrink = false;
- bool ReduceInputs = false;
- int ReloadIntervalSec = 1;
- bool ShuffleAtStartUp = true;
- bool PreferSmall = true;
- size_t MaxNumberOfRuns = -1L;
- int ReportSlowUnits = 10;
- bool OnlyASCII = false;
- std::string OutputCorpus;
- std::string ArtifactPrefix = "./";
- std::string ExactArtifactPath;
- std::string ExitOnSrcPos;
- std::string ExitOnItem;
- std::string FocusFunction;
- std::string DataFlowTrace;
- bool SaveArtifacts = true;
- bool PrintNEW = true; // Print a status line when new units are found;
- bool PrintNewCovPcs = false;
- int PrintNewCovFuncs = 0;
- bool PrintFinalStats = false;
- bool PrintCorpusStats = false;
- bool PrintCoverage = false;
- bool PrintUnstableStats = false;
- int HandleUnstable = 0;
- bool DumpCoverage = false;
- bool DetectLeaks = true;
- int PurgeAllocatorIntervalSec = 1;
- int TraceMalloc = 0;
- bool HandleAbrt = false;
- bool HandleBus = false;
- bool HandleFpe = false;
- bool HandleIll = false;
- bool HandleInt = false;
- bool HandleSegv = false;
- bool HandleTerm = false;
- bool HandleXfsz = false;
- bool HandleUsr1 = false;
- bool HandleUsr2 = false;
-};
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_OPTIONS_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerRandom.h b/chromium/third_party/libFuzzer/src/FuzzerRandom.h
deleted file mode 100644
index 8a1aa3ef5fd..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerRandom.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- FuzzerRandom.h - Internal header for the Fuzzer ----------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// fuzzer::Random
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_RANDOM_H
-#define LLVM_FUZZER_RANDOM_H
-
-#include <random>
-
-namespace fuzzer {
-class Random : public std::mt19937 {
- public:
- Random(unsigned int seed) : std::mt19937(seed) {}
- result_type operator()() { return this->std::mt19937::operator()(); }
- size_t Rand() { return this->operator()(); }
- size_t RandBool() { return Rand() % 2; }
- size_t operator()(size_t n) { return n ? Rand() % n : 0; }
- intptr_t operator()(intptr_t From, intptr_t To) {
- assert(From < To);
- intptr_t RangeSize = To - From + 1;
- return operator()(RangeSize) + From;
- }
-};
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_RANDOM_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerSHA1.cpp b/chromium/third_party/libFuzzer/src/FuzzerSHA1.cpp
deleted file mode 100644
index d2f8e811bbf..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerSHA1.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-//===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// This code is taken from public domain
-// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c)
-// and modified by adding anonymous namespace, adding an interface
-// function fuzzer::ComputeSHA1() and removing unnecessary code.
-//
-// lib/Fuzzer can not use SHA1 implementation from openssl because
-// openssl may not be available and because we may be fuzzing openssl itself.
-// For the same reason we do not want to depend on SHA1 from LLVM tree.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerSHA1.h"
-#include "FuzzerDefs.h"
-
-/* This code is public-domain - it is based on libcrypt
- * placed in the public domain by Wei Dai and other contributors.
- */
-
-#include <iomanip>
-#include <sstream>
-#include <stdint.h>
-#include <string.h>
-
-namespace { // Added for LibFuzzer
-
-#ifdef __BIG_ENDIAN__
-# define SHA_BIG_ENDIAN
-#elif defined __LITTLE_ENDIAN__
-/* override */
-#elif defined __BYTE_ORDER
-# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-# define SHA_BIG_ENDIAN
-# endif
-#else // ! defined __LITTLE_ENDIAN__
-# include <endian.h> // machine/endian.h
-# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-# define SHA_BIG_ENDIAN
-# endif
-#endif
-
-
-/* header */
-
-#define HASH_LENGTH 20
-#define BLOCK_LENGTH 64
-
-typedef struct sha1nfo {
- uint32_t buffer[BLOCK_LENGTH/4];
- uint32_t state[HASH_LENGTH/4];
- uint32_t byteCount;
- uint8_t bufferOffset;
- uint8_t keyBuffer[BLOCK_LENGTH];
- uint8_t innerHash[HASH_LENGTH];
-} sha1nfo;
-
-/* public API - prototypes - TODO: doxygen*/
-
-/**
- */
-void sha1_init(sha1nfo *s);
-/**
- */
-void sha1_writebyte(sha1nfo *s, uint8_t data);
-/**
- */
-void sha1_write(sha1nfo *s, const char *data, size_t len);
-/**
- */
-uint8_t* sha1_result(sha1nfo *s);
-
-
-/* code */
-#define SHA1_K0 0x5a827999
-#define SHA1_K20 0x6ed9eba1
-#define SHA1_K40 0x8f1bbcdc
-#define SHA1_K60 0xca62c1d6
-
-void sha1_init(sha1nfo *s) {
- s->state[0] = 0x67452301;
- s->state[1] = 0xefcdab89;
- s->state[2] = 0x98badcfe;
- s->state[3] = 0x10325476;
- s->state[4] = 0xc3d2e1f0;
- s->byteCount = 0;
- s->bufferOffset = 0;
-}
-
-uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
- return ((number << bits) | (number >> (32-bits)));
-}
-
-void sha1_hashBlock(sha1nfo *s) {
- uint8_t i;
- uint32_t a,b,c,d,e,t;
-
- a=s->state[0];
- b=s->state[1];
- c=s->state[2];
- d=s->state[3];
- e=s->state[4];
- for (i=0; i<80; i++) {
- if (i>=16) {
- t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15];
- s->buffer[i&15] = sha1_rol32(t,1);
- }
- if (i<20) {
- t = (d ^ (b & (c ^ d))) + SHA1_K0;
- } else if (i<40) {
- t = (b ^ c ^ d) + SHA1_K20;
- } else if (i<60) {
- t = ((b & c) | (d & (b | c))) + SHA1_K40;
- } else {
- t = (b ^ c ^ d) + SHA1_K60;
- }
- t+=sha1_rol32(a,5) + e + s->buffer[i&15];
- e=d;
- d=c;
- c=sha1_rol32(b,30);
- b=a;
- a=t;
- }
- s->state[0] += a;
- s->state[1] += b;
- s->state[2] += c;
- s->state[3] += d;
- s->state[4] += e;
-}
-
-void sha1_addUncounted(sha1nfo *s, uint8_t data) {
- uint8_t * const b = (uint8_t*) s->buffer;
-#ifdef SHA_BIG_ENDIAN
- b[s->bufferOffset] = data;
-#else
- b[s->bufferOffset ^ 3] = data;
-#endif
- s->bufferOffset++;
- if (s->bufferOffset == BLOCK_LENGTH) {
- sha1_hashBlock(s);
- s->bufferOffset = 0;
- }
-}
-
-void sha1_writebyte(sha1nfo *s, uint8_t data) {
- ++s->byteCount;
- sha1_addUncounted(s, data);
-}
-
-void sha1_write(sha1nfo *s, const char *data, size_t len) {
- for (;len--;) sha1_writebyte(s, (uint8_t) *data++);
-}
-
-void sha1_pad(sha1nfo *s) {
- // Implement SHA-1 padding (fips180-2 §5.1.1)
-
- // Pad with 0x80 followed by 0x00 until the end of the block
- sha1_addUncounted(s, 0x80);
- while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00);
-
- // Append length in the last 8 bytes
- sha1_addUncounted(s, 0); // We're only using 32 bit lengths
- sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
- sha1_addUncounted(s, 0); // So zero pad the top bits
- sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
- sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
- sha1_addUncounted(s, s->byteCount >> 13); // byte.
- sha1_addUncounted(s, s->byteCount >> 5);
- sha1_addUncounted(s, s->byteCount << 3);
-}
-
-uint8_t* sha1_result(sha1nfo *s) {
- // Pad to complete the last block
- sha1_pad(s);
-
-#ifndef SHA_BIG_ENDIAN
- // Swap byte order back
- int i;
- for (i=0; i<5; i++) {
- s->state[i]=
- (((s->state[i])<<24)& 0xff000000)
- | (((s->state[i])<<8) & 0x00ff0000)
- | (((s->state[i])>>8) & 0x0000ff00)
- | (((s->state[i])>>24)& 0x000000ff);
- }
-#endif
-
- // Return pointer to hash (20 characters)
- return (uint8_t*) s->state;
-}
-
-} // namespace; Added for LibFuzzer
-
-namespace fuzzer {
-
-// The rest is added for LibFuzzer
-void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) {
- sha1nfo s;
- sha1_init(&s);
- sha1_write(&s, (const char*)Data, Len);
- memcpy(Out, sha1_result(&s), HASH_LENGTH);
-}
-
-std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) {
- std::stringstream SS;
- for (int i = 0; i < kSHA1NumBytes; i++)
- SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i];
- return SS.str();
-}
-
-std::string Hash(const Unit &U) {
- uint8_t Hash[kSHA1NumBytes];
- ComputeSHA1(U.data(), U.size(), Hash);
- return Sha1ToString(Hash);
-}
-
-}
diff --git a/chromium/third_party/libFuzzer/src/FuzzerSHA1.h b/chromium/third_party/libFuzzer/src/FuzzerSHA1.h
deleted file mode 100644
index 3b5e6e807f4..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerSHA1.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// SHA1 utils.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_SHA1_H
-#define LLVM_FUZZER_SHA1_H
-
-#include "FuzzerDefs.h"
-#include <cstddef>
-#include <stdint.h>
-
-namespace fuzzer {
-
-// Private copy of SHA1 implementation.
-static const int kSHA1NumBytes = 20;
-
-// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'.
-void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out);
-
-std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]);
-
-std::string Hash(const Unit &U);
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_SHA1_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerShmem.h b/chromium/third_party/libFuzzer/src/FuzzerShmem.h
deleted file mode 100644
index 53568e0acb6..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerShmem.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//===- FuzzerShmem.h - shared memory interface ------------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// SharedMemoryRegion
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_SHMEM_H
-#define LLVM_FUZZER_SHMEM_H
-
-#include <algorithm>
-#include <cstring>
-#include <string>
-
-#include "FuzzerDefs.h"
-
-namespace fuzzer {
-
-class SharedMemoryRegion {
- public:
- bool Create(const char *Name);
- bool Open(const char *Name);
- bool Destroy(const char *Name);
- uint8_t *GetData() { return Data; }
- void PostServer() {Post(0);}
- void WaitServer() {Wait(0);}
- void PostClient() {Post(1);}
- void WaitClient() {Wait(1);}
-
- size_t WriteByteArray(const uint8_t *Bytes, size_t N) {
- assert(N <= kShmemSize - sizeof(N));
- memcpy(GetData(), &N, sizeof(N));
- memcpy(GetData() + sizeof(N), Bytes, N);
- assert(N == ReadByteArraySize());
- return N;
- }
- size_t ReadByteArraySize() {
- size_t Res;
- memcpy(&Res, GetData(), sizeof(Res));
- return Res;
- }
- uint8_t *GetByteArray() { return GetData() + sizeof(size_t); }
-
- bool IsServer() const { return Data && IAmServer; }
- bool IsClient() const { return Data && !IAmServer; }
-
-private:
-
- static const size_t kShmemSize = 1 << 22;
- bool IAmServer;
- std::string Path(const char *Name);
- std::string SemName(const char *Name, int Idx);
- void Post(int Idx);
- void Wait(int Idx);
-
- bool Map(int fd);
- uint8_t *Data = nullptr;
- void *Semaphore[2];
-};
-
-extern SharedMemoryRegion SMR;
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_SHMEM_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerShmemFuchsia.cpp b/chromium/third_party/libFuzzer/src/FuzzerShmemFuchsia.cpp
deleted file mode 100644
index e9ce50c2ac8..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerShmemFuchsia.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// SharedMemoryRegion. For Fuchsia, this is just stubs as equivalence servers
-// are not currently supported.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-
-#if LIBFUZZER_FUCHSIA
-
-#include "FuzzerShmem.h"
-
-namespace fuzzer {
-
-bool SharedMemoryRegion::Create(const char *Name) {
- return false;
-}
-
-bool SharedMemoryRegion::Open(const char *Name) {
- return false;
-}
-
-bool SharedMemoryRegion::Destroy(const char *Name) {
- return false;
-}
-
-void SharedMemoryRegion::Post(int Idx) {}
-
-void SharedMemoryRegion::Wait(int Idx) {}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_FUCHSIA
diff --git a/chromium/third_party/libFuzzer/src/FuzzerShmemPosix.cpp b/chromium/third_party/libFuzzer/src/FuzzerShmemPosix.cpp
deleted file mode 100644
index 41a93f61004..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerShmemPosix.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-//===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// SharedMemoryRegion
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_POSIX
-
-#include "FuzzerIO.h"
-#include "FuzzerShmem.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <semaphore.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace fuzzer {
-
-std::string SharedMemoryRegion::Path(const char *Name) {
- return DirPlusFile(TmpDir(), Name);
-}
-
-std::string SharedMemoryRegion::SemName(const char *Name, int Idx) {
- std::string Res(Name);
- // When passing a name without a leading <slash> character to
- // sem_open, the behaviour is unspecified in POSIX. Add a leading
- // <slash> character for the name if there is no such one.
- if (!Res.empty() && Res[0] != '/')
- Res.insert(Res.begin(), '/');
- return Res + (char)('0' + Idx);
-}
-
-bool SharedMemoryRegion::Map(int fd) {
- Data =
- (uint8_t *)mmap(0, kShmemSize, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
- if (Data == (uint8_t*)-1)
- return false;
- return true;
-}
-
-bool SharedMemoryRegion::Create(const char *Name) {
- int fd = open(Path(Name).c_str(), O_CREAT | O_RDWR, 0777);
- if (fd < 0) return false;
- if (ftruncate(fd, kShmemSize) < 0) return false;
- if (!Map(fd))
- return false;
- for (int i = 0; i < 2; i++) {
- sem_unlink(SemName(Name, i).c_str());
- Semaphore[i] = sem_open(SemName(Name, i).c_str(), O_CREAT, 0644, 0);
- if (Semaphore[i] == SEM_FAILED)
- return false;
- }
- IAmServer = true;
- return true;
-}
-
-bool SharedMemoryRegion::Open(const char *Name) {
- int fd = open(Path(Name).c_str(), O_RDWR);
- if (fd < 0) return false;
- struct stat stat_res;
- if (0 != fstat(fd, &stat_res))
- return false;
- assert(stat_res.st_size == kShmemSize);
- if (!Map(fd))
- return false;
- for (int i = 0; i < 2; i++) {
- Semaphore[i] = sem_open(SemName(Name, i).c_str(), 0);
- if (Semaphore[i] == SEM_FAILED)
- return false;
- }
- IAmServer = false;
- return true;
-}
-
-bool SharedMemoryRegion::Destroy(const char *Name) {
- return 0 == unlink(Path(Name).c_str());
-}
-
-void SharedMemoryRegion::Post(int Idx) {
- assert(Idx == 0 || Idx == 1);
- sem_post((sem_t*)Semaphore[Idx]);
-}
-
-void SharedMemoryRegion::Wait(int Idx) {
- assert(Idx == 0 || Idx == 1);
- for (int i = 0; i < 10 && sem_wait((sem_t*)Semaphore[Idx]); i++) {
- // sem_wait may fail if interrupted by a signal.
- sleep(i);
- if (i)
- Printf("%s: sem_wait[%d] failed %s\n", i < 9 ? "WARNING" : "ERROR", i,
- strerror(errno));
- if (i == 9) abort();
- }
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_POSIX
diff --git a/chromium/third_party/libFuzzer/src/FuzzerShmemWindows.cpp b/chromium/third_party/libFuzzer/src/FuzzerShmemWindows.cpp
deleted file mode 100644
index d330ebf4fd0..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerShmemWindows.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-//===- FuzzerShmemWindows.cpp - Posix shared memory -------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// SharedMemoryRegion
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_WINDOWS
-
-#include "FuzzerIO.h"
-#include "FuzzerShmem.h"
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-namespace fuzzer {
-
-std::string SharedMemoryRegion::Path(const char *Name) {
- return DirPlusFile(TmpDir(), Name);
-}
-
-std::string SharedMemoryRegion::SemName(const char *Name, int Idx) {
- std::string Res(Name);
- return Res + (char)('0' + Idx);
-}
-
-bool SharedMemoryRegion::Map(int fd) {
- assert(0 && "UNIMPLEMENTED");
- return false;
-}
-
-bool SharedMemoryRegion::Create(const char *Name) {
- assert(0 && "UNIMPLEMENTED");
- return false;
-}
-
-bool SharedMemoryRegion::Open(const char *Name) {
- assert(0 && "UNIMPLEMENTED");
- return false;
-}
-
-bool SharedMemoryRegion::Destroy(const char *Name) {
- assert(0 && "UNIMPLEMENTED");
- return false;
-}
-
-void SharedMemoryRegion::Post(int Idx) {
- assert(0 && "UNIMPLEMENTED");
-}
-
-void SharedMemoryRegion::Wait(int Idx) {
- Semaphore[1] = nullptr;
- assert(0 && "UNIMPLEMENTED");
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_WINDOWS
diff --git a/chromium/third_party/libFuzzer/src/FuzzerTracePC.cpp b/chromium/third_party/libFuzzer/src/FuzzerTracePC.cpp
deleted file mode 100644
index 252660b0e11..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerTracePC.cpp
+++ /dev/null
@@ -1,719 +0,0 @@
-//===- FuzzerTracePC.cpp - PC tracing--------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Trace PCs.
-// This module implements __sanitizer_cov_trace_pc_guard[_init],
-// the callback required for -fsanitize-coverage=trace-pc-guard instrumentation.
-//
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerTracePC.h"
-#include "FuzzerBuiltins.h"
-#include "FuzzerBuiltinsMsvc.h"
-#include "FuzzerCorpus.h"
-#include "FuzzerDefs.h"
-#include "FuzzerDictionary.h"
-#include "FuzzerExtFunctions.h"
-#include "FuzzerIO.h"
-#include "FuzzerUtil.h"
-#include "FuzzerValueBitMap.h"
-#include <set>
-
-// The coverage counters and PCs.
-// These are declared as global variables named "__sancov_*" to simplify
-// experiments with inlined instrumentation.
-alignas(64) ATTRIBUTE_INTERFACE
-uint8_t __sancov_trace_pc_guard_8bit_counters[fuzzer::TracePC::kNumPCs];
-
-ATTRIBUTE_INTERFACE
-uintptr_t __sancov_trace_pc_pcs[fuzzer::TracePC::kNumPCs];
-
-// Used by -fsanitize-coverage=stack-depth to track stack depth
-ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC uintptr_t __sancov_lowest_stack;
-
-namespace fuzzer {
-
-TracePC TPC;
-
-uint8_t *TracePC::Counters() const {
- return __sancov_trace_pc_guard_8bit_counters;
-}
-
-uintptr_t *TracePC::PCs() const {
- return __sancov_trace_pc_pcs;
-}
-
-size_t TracePC::GetTotalPCCoverage() {
- if (ObservedPCs.size())
- return ObservedPCs.size();
- size_t Res = 0;
- for (size_t i = 1, N = GetNumPCs(); i < N; i++)
- if (PCs()[i])
- Res++;
- return Res;
-}
-
-template<class CallBack>
-void TracePC::IterateInline8bitCounters(CallBack CB) const {
- if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables) {
- size_t CounterIdx = 0;
- for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
- uint8_t *Beg = ModuleCounters[i].Start;
- size_t Size = ModuleCounters[i].Stop - Beg;
- assert(Size == (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
- for (size_t j = 0; j < Size; j++, CounterIdx++)
- CB(i, j, CounterIdx);
- }
- }
-}
-
-// Initializes unstable counters by copying Inline8bitCounters to unstable
-// counters.
-void TracePC::InitializeUnstableCounters() {
- IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
- UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j];
- });
-}
-
-// Compares the current counters with counters from previous runs
-// and records differences as unstable edges.
-bool TracePC::UpdateUnstableCounters(int UnstableMode) {
- bool Updated = false;
- IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
- if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) {
- Updated = true;
- UnstableCounters[UnstableIdx].IsUnstable = true;
- if (UnstableMode == ZeroUnstable)
- UnstableCounters[UnstableIdx].Counter = 0;
- else if (UnstableMode == MinUnstable)
- UnstableCounters[UnstableIdx].Counter = std::min(
- ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter);
- }
- });
- return Updated;
-}
-
-// Updates and applies unstable counters to ModuleCounters in single iteration
-void TracePC::UpdateAndApplyUnstableCounters(int UnstableMode) {
- IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
- if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) {
- UnstableCounters[UnstableIdx].IsUnstable = true;
- if (UnstableMode == ZeroUnstable)
- ModuleCounters[i].Start[j] = 0;
- else if (UnstableMode == MinUnstable)
- ModuleCounters[i].Start[j] = std::min(
- ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter);
- }
- });
-}
-
-void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) {
- if (Start == Stop) return;
- if (NumModulesWithInline8bitCounters &&
- ModuleCounters[NumModulesWithInline8bitCounters-1].Start == Start) return;
- assert(NumModulesWithInline8bitCounters <
- sizeof(ModuleCounters) / sizeof(ModuleCounters[0]));
- ModuleCounters[NumModulesWithInline8bitCounters++] = {Start, Stop};
- NumInline8bitCounters += Stop - Start;
-}
-
-void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) {
- const PCTableEntry *B = reinterpret_cast<const PCTableEntry *>(Start);
- const PCTableEntry *E = reinterpret_cast<const PCTableEntry *>(Stop);
- if (NumPCTables && ModulePCTable[NumPCTables - 1].Start == B) return;
- assert(NumPCTables < sizeof(ModulePCTable) / sizeof(ModulePCTable[0]));
- ModulePCTable[NumPCTables++] = {B, E};
- NumPCsInPCTables += E - B;
-}
-
-void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) {
- if (Start == Stop || *Start) return;
- assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
- for (uint32_t *P = Start; P < Stop; P++) {
- NumGuards++;
- if (NumGuards == kNumPCs) {
- RawPrint(
- "WARNING: The binary has too many instrumented PCs.\n"
- " You may want to reduce the size of the binary\n"
- " for more efficient fuzzing and precise coverage data\n");
- }
- *P = NumGuards % kNumPCs;
- }
- Modules[NumModules].Start = Start;
- Modules[NumModules].Stop = Stop;
- NumModules++;
-}
-
-void TracePC::PrintModuleInfo() {
- if (NumGuards) {
- Printf("INFO: Loaded %zd modules (%zd guards): ", NumModules, NumGuards);
- for (size_t i = 0; i < NumModules; i++)
- Printf("%zd [%p, %p), ", Modules[i].Stop - Modules[i].Start,
- Modules[i].Start, Modules[i].Stop);
- Printf("\n");
- }
- if (NumModulesWithInline8bitCounters) {
- Printf("INFO: Loaded %zd modules (%zd inline 8-bit counters): ",
- NumModulesWithInline8bitCounters, NumInline8bitCounters);
- for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++)
- Printf("%zd [%p, %p), ", ModuleCounters[i].Stop - ModuleCounters[i].Start,
- ModuleCounters[i].Start, ModuleCounters[i].Stop);
- Printf("\n");
- }
- if (NumPCTables) {
- Printf("INFO: Loaded %zd PC tables (%zd PCs): ", NumPCTables,
- NumPCsInPCTables);
- for (size_t i = 0; i < NumPCTables; i++) {
- Printf("%zd [%p,%p), ", ModulePCTable[i].Stop - ModulePCTable[i].Start,
- ModulePCTable[i].Start, ModulePCTable[i].Stop);
- }
- Printf("\n");
-
- if ((NumGuards && NumGuards != NumPCsInPCTables) ||
- (NumInline8bitCounters && NumInline8bitCounters != NumPCsInPCTables)) {
- Printf("ERROR: The size of coverage PC tables does not match the\n"
- "number of instrumented PCs. This might be a compiler bug,\n"
- "please contact the libFuzzer developers.\n"
- "Also check https://bugs.llvm.org/show_bug.cgi?id=34636\n"
- "for possible workarounds (tl;dr: don't use the old GNU ld)\n");
- _Exit(1);
- }
- }
- if (size_t NumExtraCounters = ExtraCountersEnd() - ExtraCountersBegin())
- Printf("INFO: %zd Extra Counters\n", NumExtraCounters);
-}
-
-ATTRIBUTE_NO_SANITIZE_ALL
-void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) {
- const uintptr_t kBits = 12;
- const uintptr_t kMask = (1 << kBits) - 1;
- uintptr_t Idx = (Caller & kMask) | ((Callee & kMask) << kBits);
- ValueProfileMap.AddValueModPrime(Idx);
-}
-
-/// \return the address of the previous instruction.
-/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.h`
-inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) {
-#if defined(__arm__)
- // T32 (Thumb) branch instructions might be 16 or 32 bit long,
- // so we return (pc-2) in that case in order to be safe.
- // For A32 mode we return (pc-4) because all instructions are 32 bit long.
- return (PC - 3) & (~1);
-#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__)
- // PCs are always 4 byte aligned.
- return PC - 4;
-#elif defined(__sparc__) || defined(__mips__)
- return PC - 8;
-#else
- return PC - 1;
-#endif
-}
-
-/// \return the address of the next instruction.
-/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cc`
-inline ALWAYS_INLINE uintptr_t GetNextInstructionPc(uintptr_t PC) {
-#if defined(__mips__)
- return PC + 8;
-#elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \
- defined(__aarch64__)
- return PC + 4;
-#else
- return PC + 1;
-#endif
-}
-
-void TracePC::UpdateObservedPCs() {
- Vector<uintptr_t> CoveredFuncs;
- auto ObservePC = [&](uintptr_t PC) {
- if (ObservedPCs.insert(PC).second && DoPrintNewPCs) {
- PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", GetNextInstructionPc(PC));
- Printf("\n");
- }
- };
-
- auto Observe = [&](const PCTableEntry &TE) {
- if (TE.PCFlags & 1)
- if (++ObservedFuncs[TE.PC] == 1 && NumPrintNewFuncs)
- CoveredFuncs.push_back(TE.PC);
- ObservePC(TE.PC);
- };
-
- if (NumPCsInPCTables) {
- if (NumInline8bitCounters == NumPCsInPCTables) {
- IterateInline8bitCounters([&](int i, int j, int CounterIdx) {
- if (ModuleCounters[i].Start[j])
- Observe(ModulePCTable[i].Start[j]);
- });
- } else if (NumGuards == NumPCsInPCTables) {
- size_t GuardIdx = 1;
- for (size_t i = 0; i < NumModules; i++) {
- uint32_t *Beg = Modules[i].Start;
- size_t Size = Modules[i].Stop - Beg;
- assert(Size ==
- (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start));
- for (size_t j = 0; j < Size; j++, GuardIdx++)
- if (Counters()[GuardIdx])
- Observe(ModulePCTable[i].Start[j]);
- }
- }
- }
-
- for (size_t i = 0, N = Min(CoveredFuncs.size(), NumPrintNewFuncs); i < N;
- i++) {
- Printf("\tNEW_FUNC[%zd/%zd]: ", i + 1, CoveredFuncs.size());
- PrintPC("%p %F %L", "%p", GetNextInstructionPc(CoveredFuncs[i]));
- Printf("\n");
- }
-}
-
-
-static std::string GetModuleName(uintptr_t PC) {
- char ModulePathRaw[4096] = ""; // What's PATH_MAX in portable C++?
- void *OffsetRaw = nullptr;
- if (!EF->__sanitizer_get_module_and_offset_for_pc(
- reinterpret_cast<void *>(PC), ModulePathRaw,
- sizeof(ModulePathRaw), &OffsetRaw))
- return "";
- return ModulePathRaw;
-}
-
-template<class CallBack>
-void TracePC::IterateCoveredFunctions(CallBack CB) {
- for (size_t i = 0; i < NumPCTables; i++) {
- auto &M = ModulePCTable[i];
- assert(M.Start < M.Stop);
- auto ModuleName = GetModuleName(M.Start->PC);
- for (auto NextFE = M.Start; NextFE < M.Stop; ) {
- auto FE = NextFE;
- assert((FE->PCFlags & 1) && "Not a function entry point");
- do {
- NextFE++;
- } while (NextFE < M.Stop && !(NextFE->PCFlags & 1));
- if (ObservedFuncs.count(FE->PC))
- CB(FE, NextFE, ObservedFuncs[FE->PC]);
- }
- }
-}
-
-void TracePC::SetFocusFunction(const std::string &FuncName) {
- // This function should be called once.
- assert(FocusFunction.first > NumModulesWithInline8bitCounters);
- if (FuncName.empty())
- return;
- for (size_t M = 0; M < NumModulesWithInline8bitCounters; M++) {
- auto &PCTE = ModulePCTable[M];
- size_t N = PCTE.Stop - PCTE.Start;
- for (size_t I = 0; I < N; I++) {
- if (!(PCTE.Start[I].PCFlags & 1)) continue; // not a function entry.
- auto Name = DescribePC("%F", GetNextInstructionPc(PCTE.Start[I].PC));
- if (Name[0] == 'i' && Name[1] == 'n' && Name[2] == ' ')
- Name = Name.substr(3, std::string::npos);
- if (FuncName != Name) continue;
- Printf("INFO: Focus function is set to '%s'\n", Name.c_str());
- FocusFunction = {M, I};
- return;
- }
- }
-}
-
-bool TracePC::ObservedFocusFunction() {
- size_t I = FocusFunction.first;
- size_t J = FocusFunction.second;
- if (I >= NumModulesWithInline8bitCounters)
- return false;
- auto &MC = ModuleCounters[I];
- size_t Size = MC.Stop - MC.Start;
- if (J >= Size)
- return false;
- return MC.Start[J] != 0;
-}
-
-void TracePC::PrintCoverage() {
- if (!EF->__sanitizer_symbolize_pc ||
- !EF->__sanitizer_get_module_and_offset_for_pc) {
- Printf("INFO: __sanitizer_symbolize_pc or "
- "__sanitizer_get_module_and_offset_for_pc is not available,"
- " not printing coverage\n");
- return;
- }
- Printf("COVERAGE:\n");
- auto CoveredFunctionCallback = [&](const PCTableEntry *First,
- const PCTableEntry *Last,
- uintptr_t Counter) {
- assert(First < Last);
- auto VisualizePC = GetNextInstructionPc(First->PC);
- std::string FileStr = DescribePC("%s", VisualizePC);
- if (!IsInterestingCoverageFile(FileStr))
- return;
- std::string FunctionStr = DescribePC("%F", VisualizePC);
- if (FunctionStr.find("in ") == 0)
- FunctionStr = FunctionStr.substr(3);
- std::string LineStr = DescribePC("%l", VisualizePC);
- size_t Line = std::stoul(LineStr);
- size_t NumEdges = Last - First;
- Vector<uintptr_t> UncoveredPCs;
- for (auto TE = First; TE < Last; TE++)
- if (!ObservedPCs.count(TE->PC))
- UncoveredPCs.push_back(TE->PC);
- Printf("COVERED_FUNC: hits: %zd", Counter);
- Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges);
- Printf(" %s %s:%zd\n", FunctionStr.c_str(), FileStr.c_str(), Line);
- for (auto PC: UncoveredPCs)
- Printf(" UNCOVERED_PC: %s\n",
- DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str());
- };
-
- IterateCoveredFunctions(CoveredFunctionCallback);
-}
-
-void TracePC::DumpCoverage() {
- if (EF->__sanitizer_dump_coverage) {
- Vector<uintptr_t> PCsCopy(GetNumPCs());
- for (size_t i = 0; i < GetNumPCs(); i++)
- PCsCopy[i] = PCs()[i] ? GetPreviousInstructionPc(PCs()[i]) : 0;
- EF->__sanitizer_dump_coverage(PCsCopy.data(), PCsCopy.size());
- }
-}
-
-void TracePC::PrintUnstableStats() {
- size_t count = 0;
- Printf("UNSTABLE_FUNCTIONS:\n");
- IterateInline8bitCounters([&](int i, int j, int UnstableIdx) {
- const PCTableEntry &TE = ModulePCTable[i].Start[j];
- if (UnstableCounters[UnstableIdx].IsUnstable) {
- count++;
- if (ObservedFuncs.count(TE.PC)) {
- auto VisualizePC = GetNextInstructionPc(TE.PC);
- std::string FunctionStr = DescribePC("%F", VisualizePC);
- if (FunctionStr.find("in ") == 0)
- FunctionStr = FunctionStr.substr(3);
- Printf("%s\n", FunctionStr.c_str());
- }
- }
- });
-
- Printf("stat::stability_rate: %.2f\n",
- 100 - static_cast<float>(count * 100) / NumInline8bitCounters);
-}
-
-// Value profile.
-// We keep track of various values that affect control flow.
-// These values are inserted into a bit-set-based hash map.
-// Every new bit in the map is treated as a new coverage.
-//
-// For memcmp/strcmp/etc the interesting value is the length of the common
-// prefix of the parameters.
-// For cmp instructions the interesting value is a XOR of the parameters.
-// The interesting value is mixed up with the PC and is then added to the map.
-
-ATTRIBUTE_NO_SANITIZE_ALL
-void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
- size_t n, bool StopAtZero) {
- if (!n) return;
- size_t Len = std::min(n, Word::GetMaxSize());
- const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1);
- const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2);
- uint8_t B1[Word::kMaxSize];
- uint8_t B2[Word::kMaxSize];
- // Copy the data into locals in this non-msan-instrumented function
- // to avoid msan complaining further.
- size_t Hash = 0; // Compute some simple hash of both strings.
- for (size_t i = 0; i < Len; i++) {
- B1[i] = A1[i];
- B2[i] = A2[i];
- size_t T = B1[i];
- Hash ^= (T << 8) | B2[i];
- }
- size_t I = 0;
- for (; I < Len; I++)
- if (B1[I] != B2[I] || (StopAtZero && B1[I] == 0))
- break;
- size_t PC = reinterpret_cast<size_t>(caller_pc);
- size_t Idx = (PC & 4095) | (I << 12);
- ValueProfileMap.AddValue(Idx);
- TORCW.Insert(Idx ^ Hash, Word(B1, Len), Word(B2, Len));
-}
-
-template <class T>
-ATTRIBUTE_TARGET_POPCNT ALWAYS_INLINE
-ATTRIBUTE_NO_SANITIZE_ALL
-void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) {
- uint64_t ArgXor = Arg1 ^ Arg2;
- if (sizeof(T) == 4)
- TORC4.Insert(ArgXor, Arg1, Arg2);
- else if (sizeof(T) == 8)
- TORC8.Insert(ArgXor, Arg1, Arg2);
- uint64_t HammingDistance = Popcountll(ArgXor); // [0,64]
- uint64_t AbsoluteDistance = (Arg1 == Arg2 ? 0 : Clzll(Arg1 - Arg2) + 1);
- ValueProfileMap.AddValue(PC * 128 + HammingDistance);
- ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance);
-}
-
-static size_t InternalStrnlen(const char *S, size_t MaxLen) {
- size_t Len = 0;
- for (; Len < MaxLen && S[Len]; Len++) {}
- return Len;
-}
-
-// Finds min of (strlen(S1), strlen(S2)).
-// Needed bacause one of these strings may actually be non-zero terminated.
-static size_t InternalStrnlen2(const char *S1, const char *S2) {
- size_t Len = 0;
- for (; S1[Len] && S2[Len]; Len++) {}
- return Len;
-}
-
-void TracePC::ClearInlineCounters() {
- for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
- uint8_t *Beg = ModuleCounters[i].Start;
- size_t Size = ModuleCounters[i].Stop - Beg;
- memset(Beg, 0, Size);
- }
-}
-
-ATTRIBUTE_NO_SANITIZE_ALL
-void TracePC::RecordInitialStack() {
- int stack;
- __sancov_lowest_stack = InitialStack = reinterpret_cast<uintptr_t>(&stack);
-}
-
-uintptr_t TracePC::GetMaxStackOffset() const {
- return InitialStack - __sancov_lowest_stack; // Stack grows down
-}
-
-} // namespace fuzzer
-
-extern "C" {
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- uint32_t Idx = *Guard;
- __sancov_trace_pc_pcs[Idx] = PC;
- __sancov_trace_pc_guard_8bit_counters[Idx]++;
-}
-
-// Best-effort support for -fsanitize-coverage=trace-pc, which is available
-// in both Clang and GCC.
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-void __sanitizer_cov_trace_pc() {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- uintptr_t Idx = PC & (((uintptr_t)1 << fuzzer::TracePC::kTracePcBits) - 1);
- __sancov_trace_pc_pcs[Idx] = PC;
- __sancov_trace_pc_guard_8bit_counters[Idx]++;
-}
-
-ATTRIBUTE_INTERFACE
-void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) {
- fuzzer::TPC.HandleInit(Start, Stop);
-}
-
-ATTRIBUTE_INTERFACE
-void __sanitizer_cov_8bit_counters_init(uint8_t *Start, uint8_t *Stop) {
- fuzzer::TPC.HandleInline8bitCountersInit(Start, Stop);
-}
-
-ATTRIBUTE_INTERFACE
-void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
- const uintptr_t *pcs_end) {
- fuzzer::TPC.HandlePCsInit(pcs_beg, pcs_end);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCallerCallee(PC, Callee);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-// Now the __sanitizer_cov_trace_const_cmp[1248] callbacks just mimic
-// the behaviour of __sanitizer_cov_trace_cmp[1248] ones. This, however,
-// should be changed later to make full use of instrumentation.
-void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Arg1, Arg2);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
- uint64_t N = Cases[0];
- uint64_t ValSizeInBits = Cases[1];
- uint64_t *Vals = Cases + 2;
- // Skip the most common and the most boring case.
- if (Vals[N - 1] < 256 && Val < 256)
- return;
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- size_t i;
- uint64_t Token = 0;
- for (i = 0; i < N; i++) {
- Token = Val ^ Vals[i];
- if (Val < Vals[i])
- break;
- }
-
- if (ValSizeInBits == 16)
- fuzzer::TPC.HandleCmp(PC + i, static_cast<uint16_t>(Token), (uint16_t)(0));
- else if (ValSizeInBits == 32)
- fuzzer::TPC.HandleCmp(PC + i, static_cast<uint32_t>(Token), (uint32_t)(0));
- else
- fuzzer::TPC.HandleCmp(PC + i, Token, (uint64_t)(0));
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_div4(uint32_t Val) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_div8(uint64_t Val) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0);
-}
-
-ATTRIBUTE_INTERFACE
-ATTRIBUTE_NO_SANITIZE_ALL
-ATTRIBUTE_TARGET_POPCNT
-void __sanitizer_cov_trace_gep(uintptr_t Idx) {
- uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC());
- fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0);
-}
-
-ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
-void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
- const void *s2, size_t n, int result) {
- if (!fuzzer::RunningUserCallback) return;
- if (result == 0) return; // No reason to mutate.
- if (n <= 1) return; // Not interesting.
- fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/false);
-}
-
-ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
-void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
- const char *s2, size_t n, int result) {
- if (!fuzzer::RunningUserCallback) return;
- if (result == 0) return; // No reason to mutate.
- size_t Len1 = fuzzer::InternalStrnlen(s1, n);
- size_t Len2 = fuzzer::InternalStrnlen(s2, n);
- n = std::min(n, Len1);
- n = std::min(n, Len2);
- if (n <= 1) return; // Not interesting.
- fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/true);
-}
-
-ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
-void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
- const char *s2, int result) {
- if (!fuzzer::RunningUserCallback) return;
- if (result == 0) return; // No reason to mutate.
- size_t N = fuzzer::InternalStrnlen2(s1, s2);
- if (N <= 1) return; // Not interesting.
- fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, N, /*StopAtZero*/true);
-}
-
-ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
-void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1,
- const char *s2, size_t n, int result) {
- if (!fuzzer::RunningUserCallback) return;
- return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result);
-}
-
-ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
-void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,
- const char *s2, int result) {
- if (!fuzzer::RunningUserCallback) return;
- return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result);
-}
-
-ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
-void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1,
- const char *s2, char *result) {
- if (!fuzzer::RunningUserCallback) return;
- fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
-}
-
-ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
-void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1,
- const char *s2, char *result) {
- if (!fuzzer::RunningUserCallback) return;
- fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
-}
-
-ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
-void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1,
- const void *s2, size_t len2, void *result) {
- if (!fuzzer::RunningUserCallback) return;
- fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), len2);
-}
-} // extern "C"
diff --git a/chromium/third_party/libFuzzer/src/FuzzerTracePC.h b/chromium/third_party/libFuzzer/src/FuzzerTracePC.h
deleted file mode 100644
index 39f97acdb07..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerTracePC.h
+++ /dev/null
@@ -1,310 +0,0 @@
-//===- FuzzerTracePC.h - Internal header for the Fuzzer ---------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// fuzzer::TracePC
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_TRACE_PC
-#define LLVM_FUZZER_TRACE_PC
-
-#include "FuzzerDefs.h"
-#include "FuzzerDictionary.h"
-#include "FuzzerValueBitMap.h"
-
-#include <set>
-#include <unordered_map>
-
-namespace fuzzer {
-
-// TableOfRecentCompares (TORC) remembers the most recently performed
-// comparisons of type T.
-// We record the arguments of CMP instructions in this table unconditionally
-// because it seems cheaper this way than to compute some expensive
-// conditions inside __sanitizer_cov_trace_cmp*.
-// After the unit has been executed we may decide to use the contents of
-// this table to populate a Dictionary.
-template<class T, size_t kSizeT>
-struct TableOfRecentCompares {
- static const size_t kSize = kSizeT;
- struct Pair {
- T A, B;
- };
- ATTRIBUTE_NO_SANITIZE_ALL
- void Insert(size_t Idx, const T &Arg1, const T &Arg2) {
- Idx = Idx % kSize;
- Table[Idx].A = Arg1;
- Table[Idx].B = Arg2;
- }
-
- Pair Get(size_t I) { return Table[I % kSize]; }
-
- Pair Table[kSize];
-};
-
-template <size_t kSizeT>
-struct MemMemTable {
- static const size_t kSize = kSizeT;
- Word MemMemWords[kSize];
- Word EmptyWord;
-
- void Add(const uint8_t *Data, size_t Size) {
- if (Size <= 2) return;
- Size = std::min(Size, Word::GetMaxSize());
- size_t Idx = SimpleFastHash(Data, Size) % kSize;
- MemMemWords[Idx].Set(Data, Size);
- }
- const Word &Get(size_t Idx) {
- for (size_t i = 0; i < kSize; i++) {
- const Word &W = MemMemWords[(Idx + i) % kSize];
- if (W.size()) return W;
- }
- EmptyWord.Set(nullptr, 0);
- return EmptyWord;
- }
-};
-
-class TracePC {
- public:
- static const size_t kNumPCs = 1 << 21;
- // How many bits of PC are used from __sanitizer_cov_trace_pc.
- static const size_t kTracePcBits = 18;
-
- enum HandleUnstableOptions {
- MinUnstable = 1,
- ZeroUnstable = 2,
- };
-
- void HandleInit(uint32_t *Start, uint32_t *Stop);
- void HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop);
- void HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop);
- void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
- template <class T> void HandleCmp(uintptr_t PC, T Arg1, T Arg2);
- size_t GetTotalPCCoverage();
- void SetUseCounters(bool UC) { UseCounters = UC; }
- void SetUseValueProfileMask(uint32_t VPMask) { UseValueProfileMask = VPMask; }
- void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; }
- void SetPrintNewFuncs(size_t P) { NumPrintNewFuncs = P; }
- void UpdateObservedPCs();
- template <class Callback> void CollectFeatures(Callback CB) const;
-
- void ResetMaps() {
- ValueProfileMap.Reset();
- if (NumModules)
- memset(Counters(), 0, GetNumPCs());
- ClearExtraCounters();
- ClearInlineCounters();
- }
-
- void ClearInlineCounters();
-
- void UpdateFeatureSet(size_t CurrentElementIdx, size_t CurrentElementSize);
- void PrintFeatureSet();
-
- void PrintModuleInfo();
-
- void PrintCoverage();
- void DumpCoverage();
- void PrintUnstableStats();
-
- template<class CallBack>
- void IterateCoveredFunctions(CallBack CB);
-
- void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
- size_t n, bool StopAtZero);
-
- TableOfRecentCompares<uint32_t, 32> TORC4;
- TableOfRecentCompares<uint64_t, 32> TORC8;
- TableOfRecentCompares<Word, 32> TORCW;
- MemMemTable<1024> MMT;
-
- size_t GetNumPCs() const {
- return NumGuards == 0 ? (1 << kTracePcBits) : Min(kNumPCs, NumGuards + 1);
- }
- uintptr_t GetPC(size_t Idx) {
- assert(Idx < GetNumPCs());
- return PCs()[Idx];
- }
-
- void RecordInitialStack();
- uintptr_t GetMaxStackOffset() const;
-
- template<class CallBack>
- void ForEachObservedPC(CallBack CB) {
- for (auto PC : ObservedPCs)
- CB(PC);
- }
-
- void SetFocusFunction(const std::string &FuncName);
- bool ObservedFocusFunction();
-
- void InitializeUnstableCounters();
- bool UpdateUnstableCounters(int UnstableMode);
- void UpdateAndApplyUnstableCounters(int UnstableMode);
-
-private:
- struct UnstableEdge {
- uint8_t Counter;
- bool IsUnstable;
- };
-
- UnstableEdge UnstableCounters[kNumPCs];
-
- bool UseCounters = false;
- uint32_t UseValueProfileMask = false;
- bool DoPrintNewPCs = false;
- size_t NumPrintNewFuncs = 0;
-
- struct Module {
- uint32_t *Start, *Stop;
- };
-
- Module Modules[4096];
- size_t NumModules; // linker-initialized.
- size_t NumGuards; // linker-initialized.
-
- struct { uint8_t *Start, *Stop; } ModuleCounters[4096];
- size_t NumModulesWithInline8bitCounters; // linker-initialized.
- size_t NumInline8bitCounters;
-
- struct PCTableEntry {
- uintptr_t PC, PCFlags;
- };
-
- struct { const PCTableEntry *Start, *Stop; } ModulePCTable[4096];
- size_t NumPCTables;
- size_t NumPCsInPCTables;
-
- uint8_t *Counters() const;
- uintptr_t *PCs() const;
-
- Set<uintptr_t> ObservedPCs;
- std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs; // PC => Counter.
-
- template <class Callback>
- void IterateInline8bitCounters(Callback CB) const;
-
- std::pair<size_t, size_t> FocusFunction = {-1, -1}; // Module and PC IDs.
-
- ValueBitMap ValueProfileMap;
- uintptr_t InitialStack;
-};
-
-template <class Callback>
-// void Callback(size_t FirstFeature, size_t Idx, uint8_t Value);
-ATTRIBUTE_NO_SANITIZE_ALL
-void ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End,
- size_t FirstFeature, Callback Handle8bitCounter) {
- typedef uintptr_t LargeType;
- const size_t Step = sizeof(LargeType) / sizeof(uint8_t);
- const size_t StepMask = Step - 1;
- auto P = Begin;
- // Iterate by 1 byte until either the alignment boundary or the end.
- for (; reinterpret_cast<uintptr_t>(P) & StepMask && P < End; P++)
- if (uint8_t V = *P)
- Handle8bitCounter(FirstFeature, P - Begin, V);
-
- // Iterate by Step bytes at a time.
- for (; P < End; P += Step)
- if (LargeType Bundle = *reinterpret_cast<const LargeType *>(P))
- for (size_t I = 0; I < Step; I++, Bundle >>= 8)
- if (uint8_t V = Bundle & 0xff)
- Handle8bitCounter(FirstFeature, P - Begin + I, V);
-
- // Iterate by 1 byte until the end.
- for (; P < End; P++)
- if (uint8_t V = *P)
- Handle8bitCounter(FirstFeature, P - Begin, V);
-}
-
-// Given a non-zero Counter returns a number in the range [0,7].
-template<class T>
-unsigned CounterToFeature(T Counter) {
- // Returns a feature number by placing Counters into buckets as illustrated
- // below.
- //
- // Counter bucket: [1] [2] [3] [4-7] [8-15] [16-31] [32-127] [128+]
- // Feature number: 0 1 2 3 4 5 6 7
- //
- // This is a heuristic taken from AFL (see
- // http://lcamtuf.coredump.cx/afl/technical_details.txt).
- //
- // This implementation may change in the future so clients should
- // not rely on it.
- assert(Counter);
- unsigned Bit = 0;
- /**/ if (Counter >= 128) Bit = 7;
- else if (Counter >= 32) Bit = 6;
- else if (Counter >= 16) Bit = 5;
- else if (Counter >= 8) Bit = 4;
- else if (Counter >= 4) Bit = 3;
- else if (Counter >= 3) Bit = 2;
- else if (Counter >= 2) Bit = 1;
- return Bit;
-}
-
-template <class Callback> // void Callback(size_t Feature)
-ATTRIBUTE_NO_SANITIZE_ADDRESS
-__attribute__((noinline))
-void TracePC::CollectFeatures(Callback HandleFeature) const {
- uint8_t *Counters = this->Counters();
- size_t N = GetNumPCs();
- auto Handle8bitCounter = [&](size_t FirstFeature,
- size_t Idx, uint8_t Counter) {
- if (UseCounters)
- HandleFeature(FirstFeature + Idx * 8 + CounterToFeature(Counter));
- else
- HandleFeature(FirstFeature + Idx);
- };
-
- size_t FirstFeature = 0;
-
- if (!NumInline8bitCounters) {
- ForEachNonZeroByte(Counters, Counters + N, FirstFeature, Handle8bitCounter);
- FirstFeature += N * 8;
- }
-
- if (NumInline8bitCounters) {
- for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
- ForEachNonZeroByte(ModuleCounters[i].Start, ModuleCounters[i].Stop,
- FirstFeature, Handle8bitCounter);
- FirstFeature += 8 * (ModuleCounters[i].Stop - ModuleCounters[i].Start);
- }
- }
-
- ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature,
- Handle8bitCounter);
- FirstFeature += (ExtraCountersEnd() - ExtraCountersBegin()) * 8;
-
- if (UseValueProfileMask) {
- ValueProfileMap.ForEach([&](size_t Idx) {
- HandleFeature(FirstFeature + Idx);
- });
- FirstFeature += ValueProfileMap.SizeInBits();
- }
-
- // Step function, grows similar to 8 * Log_2(A).
- auto StackDepthStepFunction = [](uint32_t A) -> uint32_t {
- if (!A) return A;
- uint32_t Log2 = Log(A);
- if (Log2 < 3) return A;
- Log2 -= 3;
- return (Log2 + 1) * 8 + ((A >> Log2) & 7);
- };
- assert(StackDepthStepFunction(1024) == 64);
- assert(StackDepthStepFunction(1024 * 4) == 80);
- assert(StackDepthStepFunction(1024 * 1024) == 144);
-
- if (auto MaxStackOffset = GetMaxStackOffset())
- HandleFeature(FirstFeature + StackDepthStepFunction(MaxStackOffset / 8));
-}
-
-extern TracePC TPC;
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_TRACE_PC
diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtil.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtil.cpp
deleted file mode 100644
index 6286f9a718a..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerUtil.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-//===- FuzzerUtil.cpp - Misc utils ----------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Misc utils.
-//===----------------------------------------------------------------------===//
-
-#include "FuzzerUtil.h"
-#include "FuzzerIO.h"
-#include "FuzzerInternal.h"
-#include <cassert>
-#include <chrono>
-#include <cstring>
-#include <errno.h>
-#include <mutex>
-#include <signal.h>
-#include <sstream>
-#include <stdio.h>
-#include <sys/types.h>
-#include <thread>
-
-namespace fuzzer {
-
-void PrintHexArray(const uint8_t *Data, size_t Size,
- const char *PrintAfter) {
- for (size_t i = 0; i < Size; i++)
- Printf("0x%x,", (unsigned)Data[i]);
- Printf("%s", PrintAfter);
-}
-
-void Print(const Unit &v, const char *PrintAfter) {
- PrintHexArray(v.data(), v.size(), PrintAfter);
-}
-
-void PrintASCIIByte(uint8_t Byte) {
- if (Byte == '\\')
- Printf("\\\\");
- else if (Byte == '"')
- Printf("\\\"");
- else if (Byte >= 32 && Byte < 127)
- Printf("%c", Byte);
- else
- Printf("\\x%02x", Byte);
-}
-
-void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) {
- for (size_t i = 0; i < Size; i++)
- PrintASCIIByte(Data[i]);
- Printf("%s", PrintAfter);
-}
-
-void PrintASCII(const Unit &U, const char *PrintAfter) {
- PrintASCII(U.data(), U.size(), PrintAfter);
-}
-
-bool ToASCII(uint8_t *Data, size_t Size) {
- bool Changed = false;
- for (size_t i = 0; i < Size; i++) {
- uint8_t &X = Data[i];
- auto NewX = X;
- NewX &= 127;
- if (!isspace(NewX) && !isprint(NewX))
- NewX = ' ';
- Changed |= NewX != X;
- X = NewX;
- }
- return Changed;
-}
-
-bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); }
-
-bool IsASCII(const uint8_t *Data, size_t Size) {
- for (size_t i = 0; i < Size; i++)
- if (!(isprint(Data[i]) || isspace(Data[i]))) return false;
- return true;
-}
-
-bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) {
- U->clear();
- if (Str.empty()) return false;
- size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R].
- // Skip spaces from both sides.
- while (L < R && isspace(Str[L])) L++;
- while (R > L && isspace(Str[R])) R--;
- if (R - L < 2) return false;
- // Check the closing "
- if (Str[R] != '"') return false;
- R--;
- // Find the opening "
- while (L < R && Str[L] != '"') L++;
- if (L >= R) return false;
- assert(Str[L] == '\"');
- L++;
- assert(L <= R);
- for (size_t Pos = L; Pos <= R; Pos++) {
- uint8_t V = (uint8_t)Str[Pos];
- if (!isprint(V) && !isspace(V)) return false;
- if (V =='\\') {
- // Handle '\\'
- if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) {
- U->push_back(Str[Pos + 1]);
- Pos++;
- continue;
- }
- // Handle '\xAB'
- if (Pos + 3 <= R && Str[Pos + 1] == 'x'
- && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) {
- char Hex[] = "0xAA";
- Hex[2] = Str[Pos + 2];
- Hex[3] = Str[Pos + 3];
- U->push_back(strtol(Hex, nullptr, 16));
- Pos += 3;
- continue;
- }
- return false; // Invalid escape.
- } else {
- // Any other character.
- U->push_back(V);
- }
- }
- return true;
-}
-
-bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units) {
- if (Text.empty()) {
- Printf("ParseDictionaryFile: file does not exist or is empty\n");
- return false;
- }
- std::istringstream ISS(Text);
- Units->clear();
- Unit U;
- int LineNo = 0;
- std::string S;
- while (std::getline(ISS, S, '\n')) {
- LineNo++;
- size_t Pos = 0;
- while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces.
- if (Pos == S.size()) continue; // Empty line.
- if (S[Pos] == '#') continue; // Comment line.
- if (ParseOneDictionaryEntry(S, &U)) {
- Units->push_back(U);
- } else {
- Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo,
- S.c_str());
- return false;
- }
- }
- return true;
-}
-
-std::string Base64(const Unit &U) {
- static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
- std::string Res;
- size_t i;
- for (i = 0; i + 2 < U.size(); i += 3) {
- uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2];
- Res += Table[(x >> 18) & 63];
- Res += Table[(x >> 12) & 63];
- Res += Table[(x >> 6) & 63];
- Res += Table[x & 63];
- }
- if (i + 1 == U.size()) {
- uint32_t x = (U[i] << 16);
- Res += Table[(x >> 18) & 63];
- Res += Table[(x >> 12) & 63];
- Res += "==";
- } else if (i + 2 == U.size()) {
- uint32_t x = (U[i] << 16) + (U[i + 1] << 8);
- Res += Table[(x >> 18) & 63];
- Res += Table[(x >> 12) & 63];
- Res += Table[(x >> 6) & 63];
- Res += "=";
- }
- return Res;
-}
-
-static std::mutex SymbolizeMutex;
-
-std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) {
- std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock);
- if (!EF->__sanitizer_symbolize_pc || !l.owns_lock())
- return "<can not symbolize>";
- char PcDescr[1024] = {};
- EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC),
- SymbolizedFMT, PcDescr, sizeof(PcDescr));
- PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case.
- return PcDescr;
-}
-
-void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) {
- if (EF->__sanitizer_symbolize_pc)
- Printf("%s", DescribePC(SymbolizedFMT, PC).c_str());
- else
- Printf(FallbackFMT, PC);
-}
-
-void PrintStackTrace() {
- std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock);
- if (EF->__sanitizer_print_stack_trace && l.owns_lock())
- EF->__sanitizer_print_stack_trace();
-}
-
-void PrintMemoryProfile() {
- std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock);
- if (EF->__sanitizer_print_memory_profile && l.owns_lock())
- EF->__sanitizer_print_memory_profile(95, 8);
-}
-
-unsigned NumberOfCpuCores() {
- unsigned N = std::thread::hardware_concurrency();
- if (!N) {
- Printf("WARNING: std::thread::hardware_concurrency not well defined for "
- "your platform. Assuming CPU count of 1.\n");
- N = 1;
- }
- return N;
-}
-
-size_t SimpleFastHash(const uint8_t *Data, size_t Size) {
- size_t Res = 0;
- for (size_t i = 0; i < Size; i++)
- Res = Res * 11 + Data[i];
- return Res;
-}
-
-} // namespace fuzzer
diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtil.h b/chromium/third_party/libFuzzer/src/FuzzerUtil.h
deleted file mode 100644
index d2f1d5de426..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerUtil.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Util functions.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_UTIL_H
-#define LLVM_FUZZER_UTIL_H
-
-#include "FuzzerBuiltins.h"
-#include "FuzzerBuiltinsMsvc.h"
-#include "FuzzerCommand.h"
-#include "FuzzerDefs.h"
-
-namespace fuzzer {
-
-void PrintHexArray(const Unit &U, const char *PrintAfter = "");
-
-void PrintHexArray(const uint8_t *Data, size_t Size,
- const char *PrintAfter = "");
-
-void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = "");
-
-void PrintASCII(const Unit &U, const char *PrintAfter = "");
-
-// Changes U to contain only ASCII (isprint+isspace) characters.
-// Returns true iff U has been changed.
-bool ToASCII(uint8_t *Data, size_t Size);
-
-bool IsASCII(const Unit &U);
-
-bool IsASCII(const uint8_t *Data, size_t Size);
-
-std::string Base64(const Unit &U);
-
-void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC);
-
-std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC);
-
-void PrintStackTrace();
-
-void PrintMemoryProfile();
-
-unsigned NumberOfCpuCores();
-
-// Platform specific functions.
-void SetSignalHandler(const FuzzingOptions& Options);
-
-void SleepSeconds(int Seconds);
-
-unsigned long GetPid();
-
-size_t GetPeakRSSMb();
-
-int ExecuteCommand(const Command &Cmd);
-
-FILE *OpenProcessPipe(const char *Command, const char *Mode);
-
-const void *SearchMemory(const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen);
-
-std::string CloneArgsWithoutX(const Vector<std::string> &Args,
- const char *X1, const char *X2);
-
-inline std::string CloneArgsWithoutX(const Vector<std::string> &Args,
- const char *X) {
- return CloneArgsWithoutX(Args, X, X);
-}
-
-inline std::pair<std::string, std::string> SplitBefore(std::string X,
- std::string S) {
- auto Pos = S.find(X);
- if (Pos == std::string::npos)
- return std::make_pair(S, "");
- return std::make_pair(S.substr(0, Pos), S.substr(Pos));
-}
-
-std::string DisassembleCmd(const std::string &FileName);
-
-std::string SearchRegexCmd(const std::string &Regex);
-
-size_t SimpleFastHash(const uint8_t *Data, size_t Size);
-
-inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; }
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_UTIL_H
diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilDarwin.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilDarwin.cpp
deleted file mode 100644
index 4bfbc11a50c..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerUtilDarwin.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-//===- FuzzerUtilDarwin.cpp - Misc utils ----------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Misc utils for Darwin.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_APPLE
-#include "FuzzerCommand.h"
-#include "FuzzerIO.h"
-#include <mutex>
-#include <signal.h>
-#include <spawn.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/wait.h>
-
-// There is no header for this on macOS so declare here
-extern "C" char **environ;
-
-namespace fuzzer {
-
-static std::mutex SignalMutex;
-// Global variables used to keep track of how signal handling should be
-// restored. They should **not** be accessed without holding `SignalMutex`.
-static int ActiveThreadCount = 0;
-static struct sigaction OldSigIntAction;
-static struct sigaction OldSigQuitAction;
-static sigset_t OldBlockedSignalsSet;
-
-// This is a reimplementation of Libc's `system()`. On Darwin the Libc
-// implementation contains a mutex which prevents it from being used
-// concurrently. This implementation **can** be used concurrently. It sets the
-// signal handlers when the first thread enters and restores them when the last
-// thread finishes execution of the function and ensures this is not racey by
-// using a mutex.
-int ExecuteCommand(const Command &Cmd) {
- std::string CmdLine = Cmd.toString();
- posix_spawnattr_t SpawnAttributes;
- if (posix_spawnattr_init(&SpawnAttributes))
- return -1;
- // Block and ignore signals of the current process when the first thread
- // enters.
- {
- std::lock_guard<std::mutex> Lock(SignalMutex);
- if (ActiveThreadCount == 0) {
- static struct sigaction IgnoreSignalAction;
- sigset_t BlockedSignalsSet;
- memset(&IgnoreSignalAction, 0, sizeof(IgnoreSignalAction));
- IgnoreSignalAction.sa_handler = SIG_IGN;
-
- if (sigaction(SIGINT, &IgnoreSignalAction, &OldSigIntAction) == -1) {
- Printf("Failed to ignore SIGINT\n");
- (void)posix_spawnattr_destroy(&SpawnAttributes);
- return -1;
- }
- if (sigaction(SIGQUIT, &IgnoreSignalAction, &OldSigQuitAction) == -1) {
- Printf("Failed to ignore SIGQUIT\n");
- // Try our best to restore the signal handlers.
- (void)sigaction(SIGINT, &OldSigIntAction, NULL);
- (void)posix_spawnattr_destroy(&SpawnAttributes);
- return -1;
- }
-
- (void)sigemptyset(&BlockedSignalsSet);
- (void)sigaddset(&BlockedSignalsSet, SIGCHLD);
- if (sigprocmask(SIG_BLOCK, &BlockedSignalsSet, &OldBlockedSignalsSet) ==
- -1) {
- Printf("Failed to block SIGCHLD\n");
- // Try our best to restore the signal handlers.
- (void)sigaction(SIGQUIT, &OldSigQuitAction, NULL);
- (void)sigaction(SIGINT, &OldSigIntAction, NULL);
- (void)posix_spawnattr_destroy(&SpawnAttributes);
- return -1;
- }
- }
- ++ActiveThreadCount;
- }
-
- // NOTE: Do not introduce any new `return` statements past this
- // point. It is important that `ActiveThreadCount` always be decremented
- // when leaving this function.
-
- // Make sure the child process uses the default handlers for the
- // following signals rather than inheriting what the parent has.
- sigset_t DefaultSigSet;
- (void)sigemptyset(&DefaultSigSet);
- (void)sigaddset(&DefaultSigSet, SIGQUIT);
- (void)sigaddset(&DefaultSigSet, SIGINT);
- (void)posix_spawnattr_setsigdefault(&SpawnAttributes, &DefaultSigSet);
- // Make sure the child process doesn't block SIGCHLD
- (void)posix_spawnattr_setsigmask(&SpawnAttributes, &OldBlockedSignalsSet);
- short SpawnFlags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
- (void)posix_spawnattr_setflags(&SpawnAttributes, SpawnFlags);
-
- pid_t Pid;
- char **Environ = environ; // Read from global
- const char *CommandCStr = CmdLine.c_str();
- char *const Argv[] = {
- strdup("sh"),
- strdup("-c"),
- strdup(CommandCStr),
- NULL
- };
- int ErrorCode = 0, ProcessStatus = 0;
- // FIXME: We probably shouldn't hardcode the shell path.
- ErrorCode = posix_spawn(&Pid, "/bin/sh", NULL, &SpawnAttributes,
- Argv, Environ);
- (void)posix_spawnattr_destroy(&SpawnAttributes);
- if (!ErrorCode) {
- pid_t SavedPid = Pid;
- do {
- // Repeat until call completes uninterrupted.
- Pid = waitpid(SavedPid, &ProcessStatus, /*options=*/0);
- } while (Pid == -1 && errno == EINTR);
- if (Pid == -1) {
- // Fail for some other reason.
- ProcessStatus = -1;
- }
- } else if (ErrorCode == ENOMEM || ErrorCode == EAGAIN) {
- // Fork failure.
- ProcessStatus = -1;
- } else {
- // Shell execution failure.
- ProcessStatus = W_EXITCODE(127, 0);
- }
- for (unsigned i = 0, n = sizeof(Argv) / sizeof(Argv[0]); i < n; ++i)
- free(Argv[i]);
-
- // Restore the signal handlers of the current process when the last thread
- // using this function finishes.
- {
- std::lock_guard<std::mutex> Lock(SignalMutex);
- --ActiveThreadCount;
- if (ActiveThreadCount == 0) {
- bool FailedRestore = false;
- if (sigaction(SIGINT, &OldSigIntAction, NULL) == -1) {
- Printf("Failed to restore SIGINT handling\n");
- FailedRestore = true;
- }
- if (sigaction(SIGQUIT, &OldSigQuitAction, NULL) == -1) {
- Printf("Failed to restore SIGQUIT handling\n");
- FailedRestore = true;
- }
- if (sigprocmask(SIG_BLOCK, &OldBlockedSignalsSet, NULL) == -1) {
- Printf("Failed to unblock SIGCHLD\n");
- FailedRestore = true;
- }
- if (FailedRestore)
- ProcessStatus = -1;
- }
- }
- return ProcessStatus;
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_APPLE
diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilFuchsia.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilFuchsia.cpp
deleted file mode 100644
index cd48fefef35..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerUtilFuchsia.cpp
+++ /dev/null
@@ -1,473 +0,0 @@
-//===- FuzzerUtilFuchsia.cpp - Misc utils for Fuchsia. --------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Misc utils implementation using Fuchsia/Zircon APIs.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-
-#if LIBFUZZER_FUCHSIA
-
-#include "FuzzerInternal.h"
-#include "FuzzerUtil.h"
-#include <cerrno>
-#include <cinttypes>
-#include <cstdint>
-#include <fcntl.h>
-#include <lib/fdio/spawn.h>
-#include <string>
-#include <sys/select.h>
-#include <thread>
-#include <unistd.h>
-#include <zircon/errors.h>
-#include <zircon/process.h>
-#include <zircon/sanitizer.h>
-#include <zircon/status.h>
-#include <zircon/syscalls.h>
-#include <zircon/syscalls/debug.h>
-#include <zircon/syscalls/exception.h>
-#include <zircon/syscalls/port.h>
-#include <zircon/types.h>
-
-namespace fuzzer {
-
-// Given that Fuchsia doesn't have the POSIX signals that libFuzzer was written
-// around, the general approach is to spin up dedicated threads to watch for
-// each requested condition (alarm, interrupt, crash). Of these, the crash
-// handler is the most involved, as it requires resuming the crashed thread in
-// order to invoke the sanitizers to get the needed state.
-
-// Forward declaration of assembly trampoline needed to resume crashed threads.
-// This appears to have external linkage to C++, which is why it's not in the
-// anonymous namespace. The assembly definition inside MakeTrampoline()
-// actually defines the symbol with internal linkage only.
-void CrashTrampolineAsm() __asm__("CrashTrampolineAsm");
-
-namespace {
-
-// A magic value for the Zircon exception port, chosen to spell 'FUZZING'
-// when interpreted as a byte sequence on little-endian platforms.
-const uint64_t kFuzzingCrash = 0x474e495a5a5546;
-
-// Helper function to handle Zircon syscall failures.
-void ExitOnErr(zx_status_t Status, const char *Syscall) {
- if (Status != ZX_OK) {
- Printf("libFuzzer: %s failed: %s\n", Syscall,
- _zx_status_get_string(Status));
- exit(1);
- }
-}
-
-void AlarmHandler(int Seconds) {
- while (true) {
- SleepSeconds(Seconds);
- Fuzzer::StaticAlarmCallback();
- }
-}
-
-void InterruptHandler() {
- fd_set readfds;
- // Ctrl-C sends ETX in Zircon.
- do {
- FD_ZERO(&readfds);
- FD_SET(STDIN_FILENO, &readfds);
- select(STDIN_FILENO + 1, &readfds, nullptr, nullptr, nullptr);
- } while(!FD_ISSET(STDIN_FILENO, &readfds) || getchar() != 0x03);
- Fuzzer::StaticInterruptCallback();
-}
-
-// For the crash handler, we need to call Fuzzer::StaticCrashSignalCallback
-// without POSIX signal handlers. To achieve this, we use an assembly function
-// to add the necessary CFI unwinding information and a C function to bridge
-// from that back into C++.
-
-// FIXME: This works as a short-term solution, but this code really shouldn't be
-// architecture dependent. A better long term solution is to implement remote
-// unwinding and expose the necessary APIs through sanitizer_common and/or ASAN
-// to allow the exception handling thread to gather the crash state directly.
-//
-// Alternatively, Fuchsia may in future actually implement basic signal
-// handling for the machine trap signals.
-#if defined(__x86_64__)
-#define FOREACH_REGISTER(OP_REG, OP_NUM) \
- OP_REG(rax) \
- OP_REG(rbx) \
- OP_REG(rcx) \
- OP_REG(rdx) \
- OP_REG(rsi) \
- OP_REG(rdi) \
- OP_REG(rbp) \
- OP_REG(rsp) \
- OP_REG(r8) \
- OP_REG(r9) \
- OP_REG(r10) \
- OP_REG(r11) \
- OP_REG(r12) \
- OP_REG(r13) \
- OP_REG(r14) \
- OP_REG(r15) \
- OP_REG(rip)
-
-#elif defined(__aarch64__)
-#define FOREACH_REGISTER(OP_REG, OP_NUM) \
- OP_NUM(0) \
- OP_NUM(1) \
- OP_NUM(2) \
- OP_NUM(3) \
- OP_NUM(4) \
- OP_NUM(5) \
- OP_NUM(6) \
- OP_NUM(7) \
- OP_NUM(8) \
- OP_NUM(9) \
- OP_NUM(10) \
- OP_NUM(11) \
- OP_NUM(12) \
- OP_NUM(13) \
- OP_NUM(14) \
- OP_NUM(15) \
- OP_NUM(16) \
- OP_NUM(17) \
- OP_NUM(18) \
- OP_NUM(19) \
- OP_NUM(20) \
- OP_NUM(21) \
- OP_NUM(22) \
- OP_NUM(23) \
- OP_NUM(24) \
- OP_NUM(25) \
- OP_NUM(26) \
- OP_NUM(27) \
- OP_NUM(28) \
- OP_NUM(29) \
- OP_NUM(30) \
- OP_REG(sp)
-
-#else
-#error "Unsupported architecture for fuzzing on Fuchsia"
-#endif
-
-// Produces a CFI directive for the named or numbered register.
-#define CFI_OFFSET_REG(reg) ".cfi_offset " #reg ", %c[" #reg "]\n"
-#define CFI_OFFSET_NUM(num) CFI_OFFSET_REG(r##num)
-
-// Produces an assembler input operand for the named or numbered register.
-#define ASM_OPERAND_REG(reg) \
- [reg] "i"(offsetof(zx_thread_state_general_regs_t, reg)),
-#define ASM_OPERAND_NUM(num) \
- [r##num] "i"(offsetof(zx_thread_state_general_regs_t, r[num])),
-
-// Trampoline to bridge from the assembly below to the static C++ crash
-// callback.
-__attribute__((noreturn))
-static void StaticCrashHandler() {
- Fuzzer::StaticCrashSignalCallback();
- for (;;) {
- _Exit(1);
- }
-}
-
-// Creates the trampoline with the necessary CFI information to unwind through
-// to the crashing call stack. The attribute is necessary because the function
-// is never called; it's just a container around the assembly to allow it to
-// use operands for compile-time computed constants.
-__attribute__((used))
-void MakeTrampoline() {
- __asm__(".cfi_endproc\n"
- ".pushsection .text.CrashTrampolineAsm\n"
- ".type CrashTrampolineAsm,STT_FUNC\n"
-"CrashTrampolineAsm:\n"
- ".cfi_startproc simple\n"
- ".cfi_signal_frame\n"
-#if defined(__x86_64__)
- ".cfi_return_column rip\n"
- ".cfi_def_cfa rsp, 0\n"
- FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM)
- "call %c[StaticCrashHandler]\n"
- "ud2\n"
-#elif defined(__aarch64__)
- ".cfi_return_column 33\n"
- ".cfi_def_cfa sp, 0\n"
- ".cfi_offset 33, %c[pc]\n"
- FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM)
- "bl %[StaticCrashHandler]\n"
-#else
-#error "Unsupported architecture for fuzzing on Fuchsia"
-#endif
- ".cfi_endproc\n"
- ".size CrashTrampolineAsm, . - CrashTrampolineAsm\n"
- ".popsection\n"
- ".cfi_startproc\n"
- : // No outputs
- : FOREACH_REGISTER(ASM_OPERAND_REG, ASM_OPERAND_NUM)
-#if defined(__aarch64__)
- ASM_OPERAND_REG(pc)
-#endif
- [StaticCrashHandler] "i" (StaticCrashHandler));
-}
-
-void CrashHandler(zx_handle_t *Event) {
- // This structure is used to ensure we close handles to objects we create in
- // this handler.
- struct ScopedHandle {
- ~ScopedHandle() { _zx_handle_close(Handle); }
- zx_handle_t Handle = ZX_HANDLE_INVALID;
- };
-
- // Create and bind the exception port. We need to claim to be a "debugger" so
- // the kernel will allow us to modify and resume dying threads (see below).
- // Once the port is set, we can signal the main thread to continue and wait
- // for the exception to arrive.
- ScopedHandle Port;
- ExitOnErr(_zx_port_create(0, &Port.Handle), "_zx_port_create");
- zx_handle_t Self = _zx_process_self();
-
- ExitOnErr(_zx_task_bind_exception_port(Self, Port.Handle, kFuzzingCrash,
- ZX_EXCEPTION_PORT_DEBUGGER),
- "_zx_task_bind_exception_port");
-
- ExitOnErr(_zx_object_signal(*Event, 0, ZX_USER_SIGNAL_0),
- "_zx_object_signal");
-
- zx_port_packet_t Packet;
- ExitOnErr(_zx_port_wait(Port.Handle, ZX_TIME_INFINITE, &Packet),
- "_zx_port_wait");
-
- // At this point, we want to get the state of the crashing thread, but
- // libFuzzer and the sanitizers assume this will happen from that same thread
- // via a POSIX signal handler. "Resurrecting" the thread in the middle of the
- // appropriate callback is as simple as forcibly setting the instruction
- // pointer/program counter, provided we NEVER EVER return from that function
- // (since otherwise our stack will not be valid).
- ScopedHandle Thread;
- ExitOnErr(_zx_object_get_child(Self, Packet.exception.tid,
- ZX_RIGHT_SAME_RIGHTS, &Thread.Handle),
- "_zx_object_get_child");
-
- zx_thread_state_general_regs_t GeneralRegisters;
- ExitOnErr(_zx_thread_read_state(Thread.Handle, ZX_THREAD_STATE_GENERAL_REGS,
- &GeneralRegisters, sizeof(GeneralRegisters)),
- "_zx_thread_read_state");
-
- // To unwind properly, we need to push the crashing thread's register state
- // onto the stack and jump into a trampoline with CFI instructions on how
- // to restore it.
-#if defined(__x86_64__)
- uintptr_t StackPtr =
- (GeneralRegisters.rsp - (128 + sizeof(GeneralRegisters))) &
- -(uintptr_t)16;
- __unsanitized_memcpy(reinterpret_cast<void *>(StackPtr), &GeneralRegisters,
- sizeof(GeneralRegisters));
- GeneralRegisters.rsp = StackPtr;
- GeneralRegisters.rip = reinterpret_cast<zx_vaddr_t>(CrashTrampolineAsm);
-
-#elif defined(__aarch64__)
- uintptr_t StackPtr =
- (GeneralRegisters.sp - sizeof(GeneralRegisters)) & -(uintptr_t)16;
- __unsanitized_memcpy(reinterpret_cast<void *>(StackPtr), &GeneralRegisters,
- sizeof(GeneralRegisters));
- GeneralRegisters.sp = StackPtr;
- GeneralRegisters.pc = reinterpret_cast<zx_vaddr_t>(CrashTrampolineAsm);
-
-#else
-#error "Unsupported architecture for fuzzing on Fuchsia"
-#endif
-
- // Now force the crashing thread's state.
- ExitOnErr(_zx_thread_write_state(Thread.Handle, ZX_THREAD_STATE_GENERAL_REGS,
- &GeneralRegisters, sizeof(GeneralRegisters)),
- "_zx_thread_write_state");
-
- ExitOnErr(_zx_task_resume_from_exception(Thread.Handle, Port.Handle, 0),
- "_zx_task_resume_from_exception");
-}
-
-} // namespace
-
-// Platform specific functions.
-void SetSignalHandler(const FuzzingOptions &Options) {
- // Set up alarm handler if needed.
- if (Options.UnitTimeoutSec > 0) {
- std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1);
- T.detach();
- }
-
- // Set up interrupt handler if needed.
- if (Options.HandleInt || Options.HandleTerm) {
- std::thread T(InterruptHandler);
- T.detach();
- }
-
- // Early exit if no crash handler needed.
- if (!Options.HandleSegv && !Options.HandleBus && !Options.HandleIll &&
- !Options.HandleFpe && !Options.HandleAbrt)
- return;
-
- // Set up the crash handler and wait until it is ready before proceeding.
- zx_handle_t Event;
- ExitOnErr(_zx_event_create(0, &Event), "_zx_event_create");
-
- std::thread T(CrashHandler, &Event);
- zx_status_t Status =
- _zx_object_wait_one(Event, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, nullptr);
- _zx_handle_close(Event);
- ExitOnErr(Status, "_zx_object_wait_one");
-
- T.detach();
-}
-
-void SleepSeconds(int Seconds) {
- _zx_nanosleep(_zx_deadline_after(ZX_SEC(Seconds)));
-}
-
-unsigned long GetPid() {
- zx_status_t rc;
- zx_info_handle_basic_t Info;
- if ((rc = _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &Info,
- sizeof(Info), NULL, NULL)) != ZX_OK) {
- Printf("libFuzzer: unable to get info about self: %s\n",
- _zx_status_get_string(rc));
- exit(1);
- }
- return Info.koid;
-}
-
-size_t GetPeakRSSMb() {
- zx_status_t rc;
- zx_info_task_stats_t Info;
- if ((rc = _zx_object_get_info(_zx_process_self(), ZX_INFO_TASK_STATS, &Info,
- sizeof(Info), NULL, NULL)) != ZX_OK) {
- Printf("libFuzzer: unable to get info about self: %s\n",
- _zx_status_get_string(rc));
- exit(1);
- }
- return (Info.mem_private_bytes + Info.mem_shared_bytes) >> 20;
-}
-
-template <typename Fn>
-class RunOnDestruction {
- public:
- explicit RunOnDestruction(Fn fn) : fn_(fn) {}
- ~RunOnDestruction() { fn_(); }
-
- private:
- Fn fn_;
-};
-
-template <typename Fn>
-RunOnDestruction<Fn> at_scope_exit(Fn fn) {
- return RunOnDestruction<Fn>(fn);
-}
-
-int ExecuteCommand(const Command &Cmd) {
- zx_status_t rc;
-
- // Convert arguments to C array
- auto Args = Cmd.getArguments();
- size_t Argc = Args.size();
- assert(Argc != 0);
- std::unique_ptr<const char *[]> Argv(new const char *[Argc + 1]);
- for (size_t i = 0; i < Argc; ++i)
- Argv[i] = Args[i].c_str();
- Argv[Argc] = nullptr;
-
- // Determine output. On Fuchsia, the fuzzer is typically run as a component
- // that lacks a mutable working directory. Fortunately, when this is the case
- // a mutable output directory must be specified using "-artifact_prefix=...",
- // so write the log file(s) there.
- int FdOut = STDOUT_FILENO;
- if (Cmd.hasOutputFile()) {
- std::string Path;
- if (Cmd.hasFlag("artifact_prefix"))
- Path = Cmd.getFlagValue("artifact_prefix") + "/" + Cmd.getOutputFile();
- else
- Path = Cmd.getOutputFile();
- FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
- if (FdOut == -1) {
- Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(),
- strerror(errno));
- return ZX_ERR_IO;
- }
- }
- auto CloseFdOut = at_scope_exit([FdOut]() {
- if (FdOut != STDOUT_FILENO)
- close(FdOut);
- });
-
- // Determine stderr
- int FdErr = STDERR_FILENO;
- if (Cmd.isOutAndErrCombined())
- FdErr = FdOut;
-
- // Clone the file descriptors into the new process
- fdio_spawn_action_t SpawnAction[] = {
- {
- .action = FDIO_SPAWN_ACTION_CLONE_FD,
- .fd =
- {
- .local_fd = STDIN_FILENO,
- .target_fd = STDIN_FILENO,
- },
- },
- {
- .action = FDIO_SPAWN_ACTION_CLONE_FD,
- .fd =
- {
- .local_fd = FdOut,
- .target_fd = STDOUT_FILENO,
- },
- },
- {
- .action = FDIO_SPAWN_ACTION_CLONE_FD,
- .fd =
- {
- .local_fd = FdErr,
- .target_fd = STDERR_FILENO,
- },
- },
- };
-
- // Start the process.
- char ErrorMsg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
- zx_handle_t ProcessHandle = ZX_HANDLE_INVALID;
- rc = fdio_spawn_etc(
- ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL & (~FDIO_SPAWN_CLONE_STDIO),
- Argv[0], Argv.get(), nullptr, 3, SpawnAction, &ProcessHandle, ErrorMsg);
- if (rc != ZX_OK) {
- Printf("libFuzzer: failed to launch '%s': %s, %s\n", Argv[0], ErrorMsg,
- _zx_status_get_string(rc));
- return rc;
- }
- auto CloseHandle = at_scope_exit([&]() { _zx_handle_close(ProcessHandle); });
-
- // Now join the process and return the exit status.
- if ((rc = _zx_object_wait_one(ProcessHandle, ZX_PROCESS_TERMINATED,
- ZX_TIME_INFINITE, nullptr)) != ZX_OK) {
- Printf("libFuzzer: failed to join '%s': %s\n", Argv[0],
- _zx_status_get_string(rc));
- return rc;
- }
-
- zx_info_process_t Info;
- if ((rc = _zx_object_get_info(ProcessHandle, ZX_INFO_PROCESS, &Info,
- sizeof(Info), nullptr, nullptr)) != ZX_OK) {
- Printf("libFuzzer: unable to get return code from '%s': %s\n", Argv[0],
- _zx_status_get_string(rc));
- return rc;
- }
-
- return Info.return_code;
-}
-
-const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
- size_t PattLen) {
- return memmem(Data, DataLen, Patt, PattLen);
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_FUCHSIA
diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilLinux.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilLinux.cpp
deleted file mode 100644
index c103fd230b0..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerUtilLinux.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===- FuzzerUtilLinux.cpp - Misc utils for Linux. ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Misc utils for Linux.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \
- LIBFUZZER_OPENBSD
-#include "FuzzerCommand.h"
-
-#include <stdlib.h>
-
-namespace fuzzer {
-
-int ExecuteCommand(const Command &Cmd) {
- std::string CmdLine = Cmd.toString();
- return system(CmdLine.c_str());
-}
-
-} // namespace fuzzer
-
-#endif
diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilPosix.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilPosix.cpp
deleted file mode 100644
index bc64d329370..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerUtilPosix.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Misc utils implementation using Posix API.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_POSIX
-#include "FuzzerIO.h"
-#include "FuzzerInternal.h"
-#include <cassert>
-#include <chrono>
-#include <cstring>
-#include <errno.h>
-#include <iomanip>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <thread>
-#include <unistd.h>
-
-namespace fuzzer {
-
-static void AlarmHandler(int, siginfo_t *, void *) {
- Fuzzer::StaticAlarmCallback();
-}
-
-static void CrashHandler(int, siginfo_t *, void *) {
- Fuzzer::StaticCrashSignalCallback();
-}
-
-static void InterruptHandler(int, siginfo_t *, void *) {
- Fuzzer::StaticInterruptCallback();
-}
-
-static void GracefulExitHandler(int, siginfo_t *, void *) {
- Fuzzer::StaticGracefulExitCallback();
-}
-
-static void FileSizeExceedHandler(int, siginfo_t *, void *) {
- Fuzzer::StaticFileSizeExceedCallback();
-}
-
-static void SetSigaction(int signum,
- void (*callback)(int, siginfo_t *, void *)) {
- struct sigaction sigact = {};
- if (sigaction(signum, nullptr, &sigact)) {
- Printf("libFuzzer: sigaction failed with %d\n", errno);
- exit(1);
- }
- if (sigact.sa_flags & SA_SIGINFO) {
- if (sigact.sa_sigaction)
- return;
- } else {
- if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN &&
- sigact.sa_handler != SIG_ERR)
- return;
- }
-
- sigact = {};
- sigact.sa_sigaction = callback;
- if (sigaction(signum, &sigact, 0)) {
- Printf("libFuzzer: sigaction failed with %d\n", errno);
- exit(1);
- }
-}
-
-void SetTimer(int Seconds) {
- struct itimerval T {
- {Seconds, 0}, { Seconds, 0 }
- };
- if (setitimer(ITIMER_REAL, &T, nullptr)) {
- Printf("libFuzzer: setitimer failed with %d\n", errno);
- exit(1);
- }
- SetSigaction(SIGALRM, AlarmHandler);
-}
-
-void SetSignalHandler(const FuzzingOptions& Options) {
- if (Options.UnitTimeoutSec > 0)
- SetTimer(Options.UnitTimeoutSec / 2 + 1);
- if (Options.HandleInt)
- SetSigaction(SIGINT, InterruptHandler);
- if (Options.HandleTerm)
- SetSigaction(SIGTERM, InterruptHandler);
- if (Options.HandleSegv)
- SetSigaction(SIGSEGV, CrashHandler);
- if (Options.HandleBus)
- SetSigaction(SIGBUS, CrashHandler);
- if (Options.HandleAbrt)
- SetSigaction(SIGABRT, CrashHandler);
- if (Options.HandleIll)
- SetSigaction(SIGILL, CrashHandler);
- if (Options.HandleFpe)
- SetSigaction(SIGFPE, CrashHandler);
- if (Options.HandleXfsz)
- SetSigaction(SIGXFSZ, FileSizeExceedHandler);
- if (Options.HandleUsr1)
- SetSigaction(SIGUSR1, GracefulExitHandler);
- if (Options.HandleUsr2)
- SetSigaction(SIGUSR2, GracefulExitHandler);
-}
-
-void SleepSeconds(int Seconds) {
- sleep(Seconds); // Use C API to avoid coverage from instrumented libc++.
-}
-
-unsigned long GetPid() { return (unsigned long)getpid(); }
-
-size_t GetPeakRSSMb() {
- struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage))
- return 0;
- if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD ||
- LIBFUZZER_OPENBSD) {
- // ru_maxrss is in KiB
- return usage.ru_maxrss >> 10;
- } else if (LIBFUZZER_APPLE) {
- // ru_maxrss is in bytes
- return usage.ru_maxrss >> 20;
- }
- assert(0 && "GetPeakRSSMb() is not implemented for your platform");
- return 0;
-}
-
-FILE *OpenProcessPipe(const char *Command, const char *Mode) {
- return popen(Command, Mode);
-}
-
-const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
- size_t PattLen) {
- return memmem(Data, DataLen, Patt, PattLen);
-}
-
-std::string DisassembleCmd(const std::string &FileName) {
- return "objdump -d " + FileName;
-}
-
-std::string SearchRegexCmd(const std::string &Regex) {
- return "grep '" + Regex + "'";
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_POSIX
diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilWindows.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilWindows.cpp
deleted file mode 100644
index 393b4768be7..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerUtilWindows.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Misc utils implementation for Windows.
-//===----------------------------------------------------------------------===//
-#include "FuzzerDefs.h"
-#if LIBFUZZER_WINDOWS
-#include "FuzzerCommand.h"
-#include "FuzzerIO.h"
-#include "FuzzerInternal.h"
-#include <cassert>
-#include <chrono>
-#include <cstring>
-#include <errno.h>
-#include <iomanip>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <windows.h>
-
-// This must be included after windows.h.
-#include <psapi.h>
-
-namespace fuzzer {
-
-static const FuzzingOptions* HandlerOpt = nullptr;
-
-static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
- switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
- case EXCEPTION_ACCESS_VIOLATION:
- case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
- case EXCEPTION_STACK_OVERFLOW:
- if (HandlerOpt->HandleSegv)
- Fuzzer::StaticCrashSignalCallback();
- break;
- case EXCEPTION_DATATYPE_MISALIGNMENT:
- case EXCEPTION_IN_PAGE_ERROR:
- if (HandlerOpt->HandleBus)
- Fuzzer::StaticCrashSignalCallback();
- break;
- case EXCEPTION_ILLEGAL_INSTRUCTION:
- case EXCEPTION_PRIV_INSTRUCTION:
- if (HandlerOpt->HandleIll)
- Fuzzer::StaticCrashSignalCallback();
- break;
- case EXCEPTION_FLT_DENORMAL_OPERAND:
- case EXCEPTION_FLT_DIVIDE_BY_ZERO:
- case EXCEPTION_FLT_INEXACT_RESULT:
- case EXCEPTION_FLT_INVALID_OPERATION:
- case EXCEPTION_FLT_OVERFLOW:
- case EXCEPTION_FLT_STACK_CHECK:
- case EXCEPTION_FLT_UNDERFLOW:
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- case EXCEPTION_INT_OVERFLOW:
- if (HandlerOpt->HandleFpe)
- Fuzzer::StaticCrashSignalCallback();
- break;
- // TODO: handle (Options.HandleXfsz)
- }
- return EXCEPTION_CONTINUE_SEARCH;
-}
-
-BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
- switch (dwCtrlType) {
- case CTRL_C_EVENT:
- if (HandlerOpt->HandleInt)
- Fuzzer::StaticInterruptCallback();
- return TRUE;
- case CTRL_BREAK_EVENT:
- if (HandlerOpt->HandleTerm)
- Fuzzer::StaticInterruptCallback();
- return TRUE;
- }
- return FALSE;
-}
-
-void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
- Fuzzer::StaticAlarmCallback();
-}
-
-class TimerQ {
- HANDLE TimerQueue;
- public:
- TimerQ() : TimerQueue(NULL) {};
- ~TimerQ() {
- if (TimerQueue)
- DeleteTimerQueueEx(TimerQueue, NULL);
- };
- void SetTimer(int Seconds) {
- if (!TimerQueue) {
- TimerQueue = CreateTimerQueue();
- if (!TimerQueue) {
- Printf("libFuzzer: CreateTimerQueue failed.\n");
- exit(1);
- }
- }
- HANDLE Timer;
- if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,
- Seconds*1000, Seconds*1000, 0)) {
- Printf("libFuzzer: CreateTimerQueueTimer failed.\n");
- exit(1);
- }
- };
-};
-
-static TimerQ Timer;
-
-static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
-
-void SetSignalHandler(const FuzzingOptions& Options) {
- HandlerOpt = &Options;
-
- if (Options.UnitTimeoutSec > 0)
- Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
-
- if (Options.HandleInt || Options.HandleTerm)
- if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
- DWORD LastError = GetLastError();
- Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",
- LastError);
- exit(1);
- }
-
- if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||
- Options.HandleFpe)
- SetUnhandledExceptionFilter(ExceptionHandler);
-
- if (Options.HandleAbrt)
- if (SIG_ERR == signal(SIGABRT, CrashHandler)) {
- Printf("libFuzzer: signal failed with %d\n", errno);
- exit(1);
- }
-}
-
-void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
-
-unsigned long GetPid() { return GetCurrentProcessId(); }
-
-size_t GetPeakRSSMb() {
- PROCESS_MEMORY_COUNTERS info;
- if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
- return 0;
- return info.PeakWorkingSetSize >> 20;
-}
-
-FILE *OpenProcessPipe(const char *Command, const char *Mode) {
- return _popen(Command, Mode);
-}
-
-int ExecuteCommand(const Command &Cmd) {
- std::string CmdLine = Cmd.toString();
- return system(CmdLine.c_str());
-}
-
-const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
- size_t PattLen) {
- // TODO: make this implementation more efficient.
- const char *Cdata = (const char *)Data;
- const char *Cpatt = (const char *)Patt;
-
- if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
- return NULL;
-
- if (PattLen == 1)
- return memchr(Data, *Cpatt, DataLen);
-
- const char *End = Cdata + DataLen - PattLen + 1;
-
- for (const char *It = Cdata; It < End; ++It)
- if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
- return It;
-
- return NULL;
-}
-
-std::string DisassembleCmd(const std::string &FileName) {
- Vector<std::string> command_vector;
- command_vector.push_back("dumpbin /summary > nul");
- if (ExecuteCommand(Command(command_vector)) == 0)
- return "dumpbin /disasm " + FileName;
- Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n");
- exit(1);
-}
-
-std::string SearchRegexCmd(const std::string &Regex) {
- return "findstr /r \"" + Regex + "\"";
-}
-
-} // namespace fuzzer
-
-#endif // LIBFUZZER_WINDOWS
diff --git a/chromium/third_party/libFuzzer/src/FuzzerValueBitMap.h b/chromium/third_party/libFuzzer/src/FuzzerValueBitMap.h
deleted file mode 100644
index 13d7cbd95dd..00000000000
--- a/chromium/third_party/libFuzzer/src/FuzzerValueBitMap.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// ValueBitMap.
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_FUZZER_VALUE_BIT_MAP_H
-#define LLVM_FUZZER_VALUE_BIT_MAP_H
-
-#include "FuzzerDefs.h"
-
-namespace fuzzer {
-
-// A bit map containing kMapSizeInWords bits.
-struct ValueBitMap {
- static const size_t kMapSizeInBits = 1 << 16;
- static const size_t kMapPrimeMod = 65371; // Largest Prime < kMapSizeInBits;
- static const size_t kBitsInWord = (sizeof(uintptr_t) * 8);
- static const size_t kMapSizeInWords = kMapSizeInBits / kBitsInWord;
- public:
-
- // Clears all bits.
- void Reset() { memset(Map, 0, sizeof(Map)); }
-
- // Computes a hash function of Value and sets the corresponding bit.
- // Returns true if the bit was changed from 0 to 1.
- ATTRIBUTE_NO_SANITIZE_ALL
- inline bool AddValue(uintptr_t Value) {
- uintptr_t Idx = Value % kMapSizeInBits;
- uintptr_t WordIdx = Idx / kBitsInWord;
- uintptr_t BitIdx = Idx % kBitsInWord;
- uintptr_t Old = Map[WordIdx];
- uintptr_t New = Old | (1UL << BitIdx);
- Map[WordIdx] = New;
- return New != Old;
- }
-
- ATTRIBUTE_NO_SANITIZE_ALL
- inline bool AddValueModPrime(uintptr_t Value) {
- return AddValue(Value % kMapPrimeMod);
- }
-
- inline bool Get(uintptr_t Idx) {
- assert(Idx < kMapSizeInBits);
- uintptr_t WordIdx = Idx / kBitsInWord;
- uintptr_t BitIdx = Idx % kBitsInWord;
- return Map[WordIdx] & (1UL << BitIdx);
- }
-
- size_t SizeInBits() const { return kMapSizeInBits; }
-
- template <class Callback>
- ATTRIBUTE_NO_SANITIZE_ALL
- void ForEach(Callback CB) const {
- for (size_t i = 0; i < kMapSizeInWords; i++)
- if (uintptr_t M = Map[i])
- for (size_t j = 0; j < sizeof(M) * 8; j++)
- if (M & ((uintptr_t)1 << j))
- CB(i * sizeof(M) * 8 + j);
- }
-
- private:
- uintptr_t Map[kMapSizeInWords] __attribute__((aligned(512)));
-};
-
-} // namespace fuzzer
-
-#endif // LLVM_FUZZER_VALUE_BIT_MAP_H
diff --git a/chromium/third_party/libFuzzer/src/README.txt b/chromium/third_party/libFuzzer/src/README.txt
deleted file mode 100644
index 3eee01c7767..00000000000
--- a/chromium/third_party/libFuzzer/src/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-See http://llvm.org/docs/LibFuzzer.html
diff --git a/chromium/third_party/libFuzzer/src/afl/afl_driver.cpp b/chromium/third_party/libFuzzer/src/afl/afl_driver.cpp
deleted file mode 100644
index 5a10c0d27f3..00000000000
--- a/chromium/third_party/libFuzzer/src/afl/afl_driver.cpp
+++ /dev/null
@@ -1,378 +0,0 @@
-//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===//
-
-/* This file allows to fuzz libFuzzer-style target functions
- (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode.
-
-Usage:
-################################################################################
-cat << EOF > test_fuzzer.cc
-#include <stddef.h>
-#include <stdint.h>
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- if (size > 0 && data[0] == 'H')
- if (size > 1 && data[1] == 'I')
- if (size > 2 && data[2] == '!')
- __builtin_trap();
- return 0;
-}
-EOF
-# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang.
-clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c
-# Build afl-llvm-rt.o.c from the AFL distribution.
-clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c
-# Build this file, link it with afl-llvm-rt.o.o and the target code.
-clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o
-# Run AFL:
-rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
-$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
-################################################################################
-Environment Variables:
-There are a few environment variables that can be set to use features that
-afl-fuzz doesn't have.
-
-AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
-specified. If the file does not exist, it is created. This is useful for getting
-stack traces (when using ASAN for example) or original error messages on hard to
-reproduce bugs.
-
-AFL_DRIVER_EXTRA_STATS_FILENAME: Setting this causes afl_driver to write extra
-statistics to the file specified. Currently these are peak_rss_mb
-(the peak amount of virtual memory used in MB) and slowest_unit_time_secs. If
-the file does not exist it is created. If the file does exist then
-afl_driver assumes it was restarted by afl-fuzz and will try to read old
-statistics from the file. If that fails then the process will quit.
-
-*/
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/resource.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-// Platform detection. Copied from FuzzerInternal.h
-#ifdef __linux__
-#define LIBFUZZER_LINUX 1
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 0
-#elif __APPLE__
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_APPLE 1
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 0
-#elif __NetBSD__
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_NETBSD 1
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 0
-#elif __FreeBSD__
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 1
-#define LIBFUZZER_OPENBSD 0
-#elif __OpenBSD__
-#define LIBFUZZER_LINUX 0
-#define LIBFUZZER_APPLE 0
-#define LIBFUZZER_NETBSD 0
-#define LIBFUZZER_FREEBSD 0
-#define LIBFUZZER_OPENBSD 1
-#else
-#error "Support for your platform has not been implemented"
-#endif
-
-// Used to avoid repeating error checking boilerplate. If cond is false, a
-// fatal error has occurred in the program. In this event print error_message
-// to stderr and abort(). Otherwise do nothing. Note that setting
-// AFL_DRIVER_STDERR_DUPLICATE_FILENAME may cause error_message to be appended
-// to the file as well, if the error occurs after the duplication is performed.
-#define CHECK_ERROR(cond, error_message) \
- if (!(cond)) { \
- fprintf(stderr, "%s\n", (error_message)); \
- abort(); \
- }
-
-// libFuzzer interface is thin, so we don't include any libFuzzer headers.
-extern "C" {
-int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
-__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
-}
-
-// Notify AFL about persistent mode.
-static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
-extern "C" int __afl_persistent_loop(unsigned int);
-static volatile char suppress_warning2 = AFL_PERSISTENT[0];
-
-// Notify AFL about deferred forkserver.
-static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
-extern "C" void __afl_manual_init();
-static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0];
-
-// Input buffer.
-static const size_t kMaxAflInputSize = 1 << 20;
-static uint8_t AflInputBuf[kMaxAflInputSize];
-
-// Variables we need for writing to the extra stats file.
-static FILE *extra_stats_file = NULL;
-static uint32_t previous_peak_rss = 0;
-static time_t slowest_unit_time_secs = 0;
-static const int kNumExtraStats = 2;
-static const char *kExtraStatsFormatString = "peak_rss_mb : %u\n"
- "slowest_unit_time_sec : %u\n";
-
-// Experimental feature to use afl_driver without AFL's deferred mode.
-// Needs to run before __afl_auto_init.
-__attribute__((constructor(0))) void __decide_deferred_forkserver(void) {
- if (getenv("AFL_DRIVER_DONT_DEFER")) {
- if (unsetenv("__AFL_DEFER_FORKSRV")) {
- perror("Failed to unset __AFL_DEFER_FORKSRV");
- abort();
- }
- }
-}
-
-// Copied from FuzzerUtil.cpp.
-size_t GetPeakRSSMb() {
- struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage))
- return 0;
- if (LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD ||
- LIBFUZZER_OPENBSD) {
- // ru_maxrss is in KiB
- return usage.ru_maxrss >> 10;
- } else if (LIBFUZZER_APPLE) {
- // ru_maxrss is in bytes
- return usage.ru_maxrss >> 20;
- }
- assert(0 && "GetPeakRSSMb() is not implemented for your platform");
- return 0;
-}
-
-// Based on SetSigaction in FuzzerUtil.cpp
-static void SetSigaction(int signum,
- void (*callback)(int, siginfo_t *, void *)) {
- struct sigaction sigact;
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_sigaction = callback;
- if (sigaction(signum, &sigact, 0)) {
- fprintf(stderr, "libFuzzer: sigaction failed with %d\n", errno);
- exit(1);
- }
-}
-
-// Write extra stats to the file specified by the user. If none is specified
-// this function will never be called.
-static void write_extra_stats() {
- uint32_t peak_rss = GetPeakRSSMb();
-
- if (peak_rss < previous_peak_rss)
- peak_rss = previous_peak_rss;
-
- int chars_printed = fprintf(extra_stats_file, kExtraStatsFormatString,
- peak_rss, slowest_unit_time_secs);
-
- CHECK_ERROR(chars_printed != 0, "Failed to write extra_stats_file");
-
- CHECK_ERROR(fclose(extra_stats_file) == 0,
- "Failed to close extra_stats_file");
-}
-
-// Call write_extra_stats before we exit.
-static void crash_handler(int, siginfo_t *, void *) {
- // Make sure we don't try calling write_extra_stats again if we crashed while
- // trying to call it.
- static bool first_crash = true;
- CHECK_ERROR(first_crash,
- "Crashed in crash signal handler. This is a bug in the fuzzer.");
-
- first_crash = false;
- write_extra_stats();
-}
-
-// If the user has specified an extra_stats_file through the environment
-// variable AFL_DRIVER_EXTRA_STATS_FILENAME, then perform necessary set up
-// to write stats to it on exit. If no file is specified, do nothing. Otherwise
-// install signal and exit handlers to write to the file when the process exits.
-// Then if the file doesn't exist create it and set extra stats to 0. But if it
-// does exist then read the initial values of the extra stats from the file
-// and check that the file is writable.
-static void maybe_initialize_extra_stats() {
- // If AFL_DRIVER_EXTRA_STATS_FILENAME isn't set then we have nothing to do.
- char *extra_stats_filename = getenv("AFL_DRIVER_EXTRA_STATS_FILENAME");
- if (!extra_stats_filename)
- return;
-
- // Open the file and find the previous peak_rss_mb value.
- // This is necessary because the fuzzing process is restarted after N
- // iterations are completed. So we may need to get this value from a previous
- // process to be accurate.
- extra_stats_file = fopen(extra_stats_filename, "r");
-
- // If extra_stats_file already exists: read old stats from it.
- if (extra_stats_file) {
- int matches = fscanf(extra_stats_file, kExtraStatsFormatString,
- &previous_peak_rss, &slowest_unit_time_secs);
-
- // Make sure we have read a real extra stats file and that we have used it
- // to set slowest_unit_time_secs and previous_peak_rss.
- CHECK_ERROR(matches == kNumExtraStats, "Extra stats file is corrupt");
-
- CHECK_ERROR(fclose(extra_stats_file) == 0, "Failed to close file");
-
- // Now open the file for writing.
- extra_stats_file = fopen(extra_stats_filename, "w");
- CHECK_ERROR(extra_stats_file,
- "Failed to open extra stats file for writing");
- } else {
- // Looks like this is the first time in a fuzzing job this is being called.
- extra_stats_file = fopen(extra_stats_filename, "w+");
- CHECK_ERROR(extra_stats_file, "failed to create extra stats file");
- }
-
- // Make sure that crash_handler gets called on any kind of fatal error.
- int crash_signals[] = {SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGFPE, SIGINT,
- SIGTERM};
-
- const size_t num_signals = sizeof(crash_signals) / sizeof(crash_signals[0]);
-
- for (size_t idx = 0; idx < num_signals; idx++)
- SetSigaction(crash_signals[idx], crash_handler);
-
- // Make sure it gets called on other kinds of exits.
- atexit(write_extra_stats);
-}
-
-// If the user asks us to duplicate stderr, then do it.
-static void maybe_duplicate_stderr() {
- char* stderr_duplicate_filename =
- getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
-
- if (!stderr_duplicate_filename)
- return;
-
- FILE* stderr_duplicate_stream =
- freopen(stderr_duplicate_filename, "a+", stderr);
-
- if (!stderr_duplicate_stream) {
- fprintf(
- stderr,
- "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
- abort();
- }
-}
-
-// Define LLVMFuzzerMutate to avoid link failures for targets that use it
-// with libFuzzer's LLVMFuzzerCustomMutator.
-extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
- assert(false && "LLVMFuzzerMutate should not be called from afl_driver");
- return 0;
-}
-
-// Execute any files provided as parameters.
-int ExecuteFilesOnyByOne(int argc, char **argv) {
- for (int i = 1; i < argc; i++) {
- std::ifstream in(argv[i], std::ios::binary);
- in.seekg(0, in.end);
- size_t length = in.tellg();
- in.seekg (0, in.beg);
- std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl;
- // Allocate exactly length bytes so that we reliably catch buffer overflows.
- std::vector<char> bytes(length);
- in.read(bytes.data(), bytes.size());
- assert(in);
- LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t *>(bytes.data()),
- bytes.size());
- std::cout << "Execution successful" << std::endl;
- }
- return 0;
-}
-
-int main(int argc, char **argv) {
- fprintf(stderr,
- "======================= INFO =========================\n"
- "This binary is built for AFL-fuzz.\n"
- "To run the target function on individual input(s) execute this:\n"
- " %s < INPUT_FILE\n"
- "or\n"
- " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n"
- "To fuzz with afl-fuzz execute this:\n"
- " afl-fuzz [afl-flags] %s [-N]\n"
- "afl-fuzz will run N iterations before "
- "re-spawning the process (default: 1000)\n"
- "======================================================\n",
- argv[0], argv[0], argv[0]);
- if (LLVMFuzzerInitialize)
- LLVMFuzzerInitialize(&argc, &argv);
- // Do any other expensive one-time initialization here.
-
- maybe_duplicate_stderr();
- maybe_initialize_extra_stats();
-
- if (!getenv("AFL_DRIVER_DONT_DEFER"))
- __afl_manual_init();
-
- int N = 1000;
- if (argc == 2 && argv[1][0] == '-')
- N = atoi(argv[1] + 1);
- else if(argc == 2 && (N = atoi(argv[1])) > 0)
- fprintf(stderr, "WARNING: using the deprecated call style `%s %d`\n",
- argv[0], N);
- else if (argc > 1)
- return ExecuteFilesOnyByOne(argc, argv);
-
- assert(N > 0);
-
- // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
- // on the first execution of LLVMFuzzerTestOneInput is ignored.
- uint8_t dummy_input[1] = {0};
- LLVMFuzzerTestOneInput(dummy_input, 1);
-
- time_t unit_time_secs;
- int num_runs = 0;
- while (__afl_persistent_loop(N)) {
- ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize);
- if (n_read > 0) {
- // Copy AflInputBuf into a separate buffer to let asan find buffer
- // overflows. Don't use unique_ptr/etc to avoid extra dependencies.
- uint8_t *copy = new uint8_t[n_read];
- memcpy(copy, AflInputBuf, n_read);
-
- struct timeval unit_start_time;
- CHECK_ERROR(gettimeofday(&unit_start_time, NULL) == 0,
- "Calling gettimeofday failed");
-
- num_runs++;
- LLVMFuzzerTestOneInput(copy, n_read);
-
- struct timeval unit_stop_time;
- CHECK_ERROR(gettimeofday(&unit_stop_time, NULL) == 0,
- "Calling gettimeofday failed");
-
- // Update slowest_unit_time_secs if we see a new max.
- unit_time_secs = unit_stop_time.tv_sec - unit_start_time.tv_sec;
- if (slowest_unit_time_secs < unit_time_secs)
- slowest_unit_time_secs = unit_time_secs;
-
- delete[] copy;
- }
- }
- fprintf(stderr, "%s: successfully executed %d input(s)\n", argv[0], num_runs);
-}
diff --git a/chromium/third_party/libFuzzer/src/build.sh b/chromium/third_party/libFuzzer/src/build.sh
deleted file mode 100755
index 504e54e3a81..00000000000
--- a/chromium/third_party/libFuzzer/src/build.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-LIBFUZZER_SRC_DIR=$(dirname $0)
-CXX="${CXX:-clang}"
-for f in $LIBFUZZER_SRC_DIR/*.cpp; do
- $CXX -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c &
-done
-wait
-rm -f libFuzzer.a
-ar ru libFuzzer.a Fuzzer*.o
-rm -f Fuzzer*.o
-
diff --git a/chromium/third_party/libFuzzer/src/dataflow/DataFlow.cpp b/chromium/third_party/libFuzzer/src/dataflow/DataFlow.cpp
deleted file mode 100644
index a79c796ac45..00000000000
--- a/chromium/third_party/libFuzzer/src/dataflow/DataFlow.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/*===- DataFlow.cpp - a standalone DataFlow tracer -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// An experimental data-flow tracer for fuzz targets.
-// It is based on DFSan and SanitizerCoverage.
-// https://clang.llvm.org/docs/DataFlowSanitizer.html
-// https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow
-//
-// It executes the fuzz target on the given input while monitoring the
-// data flow for every instrumented comparison instruction.
-//
-// The output shows which functions depend on which bytes of the input.
-//
-// Build:
-// 1. Compile this file with -fsanitize=dataflow
-// 2. Build the fuzz target with -g -fsanitize=dataflow
-// -fsanitize-coverage=trace-pc-guard,pc-table,func,trace-cmp
-// 3. Link those together with -fsanitize=dataflow
-//
-// -fsanitize-coverage=trace-cmp inserts callbacks around every comparison
-// instruction, DFSan modifies the calls to pass the data flow labels.
-// The callbacks update the data flow label for the current function.
-// See e.g. __dfsw___sanitizer_cov_trace_cmp1 below.
-//
-// -fsanitize-coverage=trace-pc-guard,pc-table,func instruments function
-// entries so that the comparison callback knows that current function.
-//
-//
-// Run:
-// # Collect data flow for INPUT_FILE, write to OUTPUT_FILE (default: stdout)
-// ./a.out INPUT_FILE [OUTPUT_FILE]
-//
-// # Print all instrumented functions. llvm-symbolizer must be present in PATH
-// ./a.out
-//
-// Example output:
-// ===============
-// F0 11111111111111
-// F1 10000000000000
-// ===============
-// "FN xxxxxxxxxx": tells what bytes of the input does the function N depend on.
-// The byte string is LEN+1 bytes. The last byte is set if the function
-// depends on the input length.
-//===----------------------------------------------------------------------===*/
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <execinfo.h> // backtrace_symbols_fd
-
-#include <sanitizer/dfsan_interface.h>
-
-extern "C" {
-extern int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size);
-__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv);
-} // extern "C"
-
-static size_t InputLen;
-static size_t NumFuncs;
-static const uintptr_t *FuncsBeg;
-static __thread size_t CurrentFunc;
-static dfsan_label *FuncLabels; // Array of NumFuncs elements.
-static char *PrintableStringForLabel; // InputLen + 2 bytes.
-static bool LabelSeen[1 << 8 * sizeof(dfsan_label)];
-
-// Prints all instrumented functions.
-static int PrintFunctions() {
- // We don't have the symbolizer integrated with dfsan yet.
- // So use backtrace_symbols_fd and pipe it through llvm-symbolizer.
- // TODO(kcc): this is pretty ugly and may break in lots of ways.
- // We'll need to make a proper in-process symbolizer work with DFSan.
- FILE *Pipe = popen("sed 's/(+/ /g; s/).*//g' "
- "| llvm-symbolizer "
- "| grep 'dfs\\$' "
- "| sed 's/dfs\\$//g'", "w");
- for (size_t I = 0; I < NumFuncs; I++) {
- uintptr_t PC = FuncsBeg[I * 2];
- void *const Buf[1] = {(void*)PC};
- backtrace_symbols_fd(Buf, 1, fileno(Pipe));
- }
- pclose(Pipe);
- return 0;
-}
-
-extern "C"
-void SetBytesForLabel(dfsan_label L, char *Bytes) {
- if (LabelSeen[L])
- return;
- LabelSeen[L] = true;
- assert(L);
- if (L <= InputLen + 1) {
- Bytes[L - 1] = '1';
- } else {
- auto *DLI = dfsan_get_label_info(L);
- SetBytesForLabel(DLI->l1, Bytes);
- SetBytesForLabel(DLI->l2, Bytes);
- }
-}
-
-static char *GetPrintableStringForLabel(dfsan_label L) {
- memset(PrintableStringForLabel, '0', InputLen + 1);
- PrintableStringForLabel[InputLen + 1] = 0;
- memset(LabelSeen, 0, sizeof(LabelSeen));
- SetBytesForLabel(L, PrintableStringForLabel);
- return PrintableStringForLabel;
-}
-
-static void PrintDataFlow(FILE *Out) {
- for (size_t I = 0; I < NumFuncs; I++)
- if (FuncLabels[I])
- fprintf(Out, "F%zd %s\n", I, GetPrintableStringForLabel(FuncLabels[I]));
-}
-
-int main(int argc, char **argv) {
- if (LLVMFuzzerInitialize)
- LLVMFuzzerInitialize(&argc, &argv);
- if (argc == 1)
- return PrintFunctions();
- assert(argc == 4 || argc == 5);
- size_t Beg = atoi(argv[1]);
- size_t End = atoi(argv[2]);
- assert(Beg < End);
-
- const char *Input = argv[3];
- fprintf(stderr, "INFO: reading '%s'\n", Input);
- FILE *In = fopen(Input, "r");
- assert(In);
- fseek(In, 0, SEEK_END);
- InputLen = ftell(In);
- fseek(In, 0, SEEK_SET);
- unsigned char *Buf = (unsigned char*)malloc(InputLen);
- size_t NumBytesRead = fread(Buf, 1, InputLen, In);
- assert(NumBytesRead == InputLen);
- PrintableStringForLabel = (char*)malloc(InputLen + 2);
- fclose(In);
-
- fprintf(stderr, "INFO: running '%s'\n", Input);
- for (size_t I = 1; I <= InputLen; I++) {
- dfsan_label L = dfsan_create_label("", nullptr);
- assert(L == I);
- size_t Idx = I - 1;
- if (Idx >= Beg && Idx < End)
- dfsan_set_label(L, Buf + Idx, 1);
- }
- dfsan_label SizeL = dfsan_create_label("", nullptr);
- assert(SizeL == InputLen + 1);
- dfsan_set_label(SizeL, &InputLen, sizeof(InputLen));
-
- LLVMFuzzerTestOneInput(Buf, InputLen);
- free(Buf);
-
- bool OutIsStdout = argc == 4;
- fprintf(stderr, "INFO: writing dataflow to %s\n",
- OutIsStdout ? "<stdout>" : argv[4]);
- FILE *Out = OutIsStdout ? stdout : fopen(argv[4], "w");
- PrintDataFlow(Out);
- if (!OutIsStdout) fclose(Out);
-}
-
-extern "C" {
-
-void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
- uint32_t *stop) {
- assert(NumFuncs == 0 && "This tool does not support DSOs");
- assert(start < stop && "The code is not instrumented for coverage");
- if (start == stop || *start) return; // Initialize only once.
- for (uint32_t *x = start; x < stop; x++)
- *x = ++NumFuncs; // The first index is 1.
- FuncLabels = (dfsan_label*)calloc(NumFuncs, sizeof(dfsan_label));
- fprintf(stderr, "INFO: %zd instrumented function(s) observed\n", NumFuncs);
-}
-
-void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
- const uintptr_t *pcs_end) {
- assert(NumFuncs == (pcs_end - pcs_beg) / 2);
- FuncsBeg = pcs_beg;
-}
-
-void __sanitizer_cov_trace_pc_indir(uint64_t x){} // unused.
-
-void __sanitizer_cov_trace_pc_guard(uint32_t *guard){
- uint32_t FuncNum = *guard - 1; // Guards start from 1.
- assert(FuncNum < NumFuncs);
- CurrentFunc = FuncNum;
-}
-
-void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases,
- dfsan_label L1, dfsan_label UnusedL) {
- assert(CurrentFunc < NumFuncs);
- FuncLabels[CurrentFunc] = dfsan_union(FuncLabels[CurrentFunc], L1);
-}
-
-#define HOOK(Name, Type) \
- void Name(Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) { \
- assert(CurrentFunc < NumFuncs); \
- FuncLabels[CurrentFunc] = \
- dfsan_union(FuncLabels[CurrentFunc], dfsan_union(L1, L2)); \
- }
-
-HOOK(__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t)
-HOOK(__dfsw___sanitizer_cov_trace_const_cmp2, uint16_t)
-HOOK(__dfsw___sanitizer_cov_trace_const_cmp4, uint32_t)
-HOOK(__dfsw___sanitizer_cov_trace_const_cmp8, uint64_t)
-HOOK(__dfsw___sanitizer_cov_trace_cmp1, uint8_t)
-HOOK(__dfsw___sanitizer_cov_trace_cmp2, uint16_t)
-HOOK(__dfsw___sanitizer_cov_trace_cmp4, uint32_t)
-HOOK(__dfsw___sanitizer_cov_trace_cmp8, uint64_t)
-
-} // extern "C"
diff --git a/chromium/third_party/libFuzzer/src/scripts/collect_data_flow.py b/chromium/third_party/libFuzzer/src/scripts/collect_data_flow.py
deleted file mode 100755
index 3edff66bb9d..00000000000
--- a/chromium/third_party/libFuzzer/src/scripts/collect_data_flow.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env python
-#===- lib/fuzzer/scripts/collect_data_flow.py ------------------------------===#
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-#===------------------------------------------------------------------------===#
-# Runs the data-flow tracer several times on the same input in order to collect
-# the complete trace for all input bytes (running it on all bytes at once
-# may fail if DFSan runs out of labels).
-# Usage:
-#
-# # Collect dataflow for one input, store it in OUTPUT (default is stdout)
-# collect_data_flow.py BINARY INPUT [OUTPUT]
-#
-# # Collect dataflow for all inputs in CORPUS_DIR, store them in OUTPUT_DIR
-# collect_data_flow.py BINARY CORPUS_DIR OUTPUT_DIR
-#===------------------------------------------------------------------------===#
-import atexit
-import hashlib
-import sys
-import os
-import subprocess
-import tempfile
-import shutil
-
-tmpdir = ""
-
-def cleanup(d):
- print("removing: %s" % d)
- shutil.rmtree(d)
-
-def collect_dataflow_for_corpus(self, exe, corpus_dir, output_dir):
- print("Collecting dataflow for corpus: %s output_dir: %s" % (corpus_dir,
- output_dir))
- assert not os.path.exists(output_dir)
- os.mkdir(output_dir)
- for root, dirs, files in os.walk(corpus_dir):
- for f in files:
- path = os.path.join(root, f)
- sha1 = hashlib.sha1(open(path).read()).hexdigest()
- output = os.path.join(output_dir, sha1)
- subprocess.call([self, exe, path, output])
- functions_txt = open(os.path.join(output_dir, "functions.txt"), "w")
- subprocess.call([exe], stdout=functions_txt)
-
-
-def main(argv):
- exe = argv[1]
- inp = argv[2]
- if os.path.isdir(inp):
- return collect_dataflow_for_corpus(argv[0], exe, inp, argv[3])
- size = os.path.getsize(inp)
- q = [[0, size]]
- tmpdir = tempfile.mkdtemp(prefix="libfuzzer-tmp-")
- atexit.register(cleanup, tmpdir)
- print "tmpdir: ", tmpdir
- outputs = []
- while len(q):
- r = q.pop()
- print "******* Trying: ", r
- tmpfile = os.path.join(tmpdir, str(r[0]) + "-" + str(r[1]))
- ret = subprocess.call([exe, str(r[0]), str(r[1]), inp, tmpfile])
- if ret and r[1] - r[0] >= 2:
- q.append([r[0], (r[1] + r[0]) / 2])
- q.append([(r[1] + r[0]) / 2, r[1]])
- else:
- outputs.append(tmpfile)
- print "******* Success: ", r
- f = sys.stdout
- if len(argv) >= 4:
- f = open(argv[3], "w")
- merge = os.path.join(os.path.dirname(argv[0]), "merge_data_flow.py")
- subprocess.call([merge] + outputs, stdout=f)
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/chromium/third_party/libFuzzer/src/scripts/merge_data_flow.py b/chromium/third_party/libFuzzer/src/scripts/merge_data_flow.py
deleted file mode 100755
index d2f5081e7b8..00000000000
--- a/chromium/third_party/libFuzzer/src/scripts/merge_data_flow.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-#===- lib/fuzzer/scripts/merge_data_flow.py ------------------------------===#
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-#===------------------------------------------------------------------------===#
-# Merge several data flow traces into one.
-# Usage:
-# merge_data_flow.py trace1 trace2 ... > result
-#===------------------------------------------------------------------------===#
-import sys
-import fileinput
-from array import array
-
-def Merge(a, b):
- res = array('b')
- for i in range(0, len(a)):
- res.append(ord('1' if a[i] == '1' or b[i] == '1' else '0'))
- return res.tostring()
-
-def main(argv):
- D = {}
- for line in fileinput.input():
- [F,BV] = line.strip().split(' ')
- if F in D:
- D[F] = Merge(D[F], BV)
- else:
- D[F] = BV;
- for F in D.keys():
- print("%s %s" % (F, D[F]))
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/chromium/third_party/libFuzzer/src/scripts/unbalanced_allocs.py b/chromium/third_party/libFuzzer/src/scripts/unbalanced_allocs.py
deleted file mode 100755
index 74478ad55af..00000000000
--- a/chromium/third_party/libFuzzer/src/scripts/unbalanced_allocs.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-#===- lib/fuzzer/scripts/unbalanced_allocs.py ------------------------------===#
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-#===------------------------------------------------------------------------===#
-#
-# Post-process -trace_malloc=2 output and printout only allocations and frees
-# unbalanced inside of fuzzer runs.
-# Usage:
-# my_fuzzer -trace_malloc=2 -runs=10 2>&1 | unbalanced_allocs.py -skip=5
-#
-#===------------------------------------------------------------------------===#
-
-import argparse
-import sys
-
-_skip = 0
-
-def PrintStack(line, stack):
- global _skip
- if _skip > 0:
- return
- print('Unbalanced ' + line.rstrip());
- for l in stack:
- print(l.rstrip())
-
-def ProcessStack(line, f):
- stack = []
- while line and line.startswith(' #'):
- stack += [line]
- line = f.readline()
- return line, stack
-
-def ProcessFree(line, f, allocs):
- if not line.startswith('FREE['):
- return f.readline()
-
- addr = int(line.split()[1], 16)
- next_line, stack = ProcessStack(f.readline(), f)
- if addr in allocs:
- del allocs[addr]
- else:
- PrintStack(line, stack)
- return next_line
-
-def ProcessMalloc(line, f, allocs):
- if not line.startswith('MALLOC['):
- return ProcessFree(line, f, allocs)
-
- addr = int(line.split()[1], 16)
- assert not addr in allocs
-
- next_line, stack = ProcessStack(f.readline(), f)
- allocs[addr] = (line, stack)
- return next_line
-
-def ProcessRun(line, f):
- if not line.startswith('MallocFreeTracer: START'):
- return ProcessMalloc(line, f, {})
-
- allocs = {}
- print(line.rstrip())
- line = f.readline()
- while line:
- if line.startswith('MallocFreeTracer: STOP'):
- global _skip
- _skip = _skip - 1
- for _, (l, s) in allocs.items():
- PrintStack(l, s)
- print(line.rstrip())
- return f.readline()
- line = ProcessMalloc(line, f, allocs)
- return line
-
-def ProcessFile(f):
- line = f.readline()
- while line:
- line = ProcessRun(line, f);
-
-def main(argv):
- parser = argparse.ArgumentParser()
- parser.add_argument('--skip', default=0, help='number of runs to ignore')
- args = parser.parse_args()
- global _skip
- _skip = int(args.skip) + 1
- ProcessFile(sys.stdin)
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/chromium/third_party/libFuzzer/src/standalone/StandaloneFuzzTargetMain.c b/chromium/third_party/libFuzzer/src/standalone/StandaloneFuzzTargetMain.c
deleted file mode 100644
index 0d76ea49e79..00000000000
--- a/chromium/third_party/libFuzzer/src/standalone/StandaloneFuzzTargetMain.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// This main() function can be linked to a fuzz target (i.e. a library
-// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize())
-// instead of libFuzzer. This main() function will not perform any fuzzing
-// but will simply feed all input files one by one to the fuzz target.
-//
-// Use this file to provide reproducers for bugs when linking against libFuzzer
-// or other fuzzing engine is undesirable.
-//===----------------------------------------------------------------------===*/
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
-__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv);
-int main(int argc, char **argv) {
- fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
- if (LLVMFuzzerInitialize)
- LLVMFuzzerInitialize(&argc, &argv);
- for (int i = 1; i < argc; i++) {
- fprintf(stderr, "Running: %s\n", argv[i]);
- FILE *f = fopen(argv[i], "r");
- assert(f);
- fseek(f, 0, SEEK_END);
- size_t len = ftell(f);
- fseek(f, 0, SEEK_SET);
- unsigned char *buf = (unsigned char*)malloc(len);
- size_t n_read = fread(buf, 1, len, f);
- assert(n_read == len);
- LLVMFuzzerTestOneInput(buf, len);
- free(buf);
- fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
- }
-}
diff --git a/chromium/third_party/libaddressinput/chromium/resources/address_input_strings_te.xtb b/chromium/third_party/libaddressinput/chromium/resources/address_input_strings_te.xtb
index febb2bbec62..0f32c5475ec 100644
--- a/chromium/third_party/libaddressinput/chromium/resources/address_input_strings_te.xtb
+++ b/chromium/third_party/libaddressinput/chromium/resources/address_input_strings_te.xtb
@@ -24,7 +24,7 @@
<translation id="6282194474023008486">పోస్టల్ కోడ్</translation>
<translation id="6327653052522436195">నగరం</translation>
<translation id="6403469950615936250">ఈ పోస్టల్ కోడ్ ఆకృతి గుర్తించబడలేదు. ఇది చెల్లుబాటు అయ్యే పోస్టల్ కోడ్‌కు ఉదాహరణ: <ph name="EXAMPLE" />. మీ పోస్టల్ కోడ్ తెలియదా? దాన్ని <ph name="BEGIN_LINK" />ఇక్కడ<ph name="END_LINK" /> కనుగొనండి.</translation>
-<translation id="6735419622867539268">ఈ ఫీల్డ్ కోసం <ph name="FIELD_VALUE" /> తెలిసిన విలువగా గుర్తించబడలేదు.</translation>
+<translation id="6735419622867539268"><ph name="FIELD_VALUE" /> అనేది ఈ ఫీల్డ్‌కు తగిన విలువలుగా తెలిసిన వాటిలో లేదు.</translation>
<translation id="6768780634682399515">ఈర్‌కోడ్</translation>
<translation id="6777217372746654521">ఈ చిరునామా పంక్తి తపాలా కార్యాలయ పెట్టెను కలిగి ఉన్నట్లుగా కనిపిస్తోంది. దయచేసి వీధి లేదా భవన చిరునామాను ఉపయోగించండి.</translation>
<translation id="6839929833149231406">ప్రాంతం</translation>
diff --git a/chromium/third_party/libaddressinput/fuzz/data/fmt.dict b/chromium/third_party/libaddressinput/fuzz/data/fmt.dict
deleted file mode 100644
index 57de7133c0c..00000000000
--- a/chromium/third_party/libaddressinput/fuzz/data/fmt.dict
+++ /dev/null
@@ -1,76 +0,0 @@
-"%A%n%O%n%N"
-"%N%n%O%n%A"
-"%N%n%O%n%A%nAZ %Z %C"
-"%N%n%O%n%A%n%C"
-"%N%n%O%n%A%n%C%n%S"
-"%N%n%O%n%A%n%C%n%S%n%Z"
-"%N%n%O%n%A%n%C%n%S %X"
-"%N%n%O%n%A%n%C%n%S %Z"
-"%N%n%O%n%A%n%C%n%Z"
-"%N%n%O%n%A%n%C PR %Z"
-"%N%n%O%n%A%n%C, %S"
-"%N%n%O%n%A%n%C, %S%n%Z"
-"%N%n%O%n%A%n%C %S %Z"
-"%N%n%O%n%A%n%C, %S %Z"
-"%N%n%O%n%A%n%C %X"
-"%N%n%O%n%A%n%C %X%n%S"
-"%N%n%O%n%A%n%C - %Z"
-"%N%n%O%n%A%n%C %Z"
-"%N%n%O%n%A%n%C-%Z"
-"%N%n%O%n%A%n%C, %Z"
-"%N%n%O%n%A%n%C %Z%n%S"
-"%N%n%O%n%A%n%C %Z %S"
-"%N%n%O%n%A%n%C %Z, %S"
-"%N%n%O%n%A%n%D %C%n%S %Z"
-"%N%n%O%n%A%n%D%n%Z %C%n%S"
-"%N%n%O%n%A%n%D%n%Z %C, %S"
-"%N%n%O%n%A%nFO%Z %C"
-"%N%n%O%n%A%nHR-%Z %C"
-"%N%n%O%n%A%nHT%Z %C %X"
-"%N%n%O%n%A%nMC-%Z %C %X"
-"%N%n%O%n%A%nMD-%Z %C"
-"%N%n%O%n%A%n%S"
-"%N%n%O%n%A%n%S %C-%X%n%Z"
-"%N%n%O%n%A%nSINGAPORE %Z"
-"%N%n%O%n%A%nSI- %Z %C"
-"%N%n%O%n%A%n%S%n%C"
-"%N%n%O%n%A%n%X%n%C%nGUERNSEY%n%Z"
-"%N%n%O%n%A%n%X%n%C%nJERSEY%n%Z"
-"%N%n%O%n%A%n%X%n%C%n%S"
-"%N%n%O%n%A%n%X%n%C%n%Z"
-"%N%n%O%n%A%n%Z %C"
-"%N%n%O%n%A%n%Z- %C"
-"%N%n%O%n%A%n%Z %C%n%S"
-"%N%n%O%n%A%n%Z-%C%n%S"
-"%N%n%O%n%A%n%Z %C %S"
-"%N%n%O%n%A%n%Z %C %X"
-"%N%n%O%n%A%n%Z%n%C"
-"%N%n%O%n%A%n%Z%n%C%n%S"
-"%N%n%O%n%A%n%Z%n%C, %S"
-"%N%n%O%n%A%n%Z %S"
-"%N%n%O%n%C%n%A%n%Z"
-"%N%n%O%n%X %A %C %X"
-"%N%n%O%n%Z %A %C"
-"%O%n%N%n%A%nAX-%Z %C%n\xc3\x85LAND"
-"%O%n%N%n%A%nCH-%Z %C"
-"%O%n%N%n%A%n%C-%S%n%Z"
-"%O%n%N%n%A%n%C, %S%n%Z"
-"%O%n%N%n%A%n%C %S %Z"
-"%O%n%N%n%A%nFI-%Z %C"
-"%O%n%N%n%A%nFL-%Z %C"
-"%O%n%N%n%A%nLT-%Z %C"
-"%O%n%N%n%A%nL-%Z %C"
-"%O%n%N%n%A%nSE-%Z %C"
-"%O%n%N%n%A%n%Z %C"
-"%O%n%N%n%A%n%Z %C %X"
-"%O%n%N%n%S%n%C, %D%n%A%n%Z"
-"%S %C%D%n%A%n%O%n%N%n%Z"
-"%S%n%A%n%O%n%N"
-"%S%n%Z %C %X%n%A%n%O%n%N"
-"%Z %C %n%A%n%O%n%N"
-"%Z %C%n%A%n%O%n%N"
-"%Z %C %X%n%A%n%O%n%N"
-"%Z%n%S%C%D%n%A%n%O%n%N"
-"%Z%n%S%C%n%A%n%O%n%N"
-"\xe3\x80\x92%Z%n%S%C%n%A%n%O%n%N"
-"%Z%n%S%n%C%n%A%n%O%n%N"
diff --git a/chromium/third_party/libaddressinput/fuzz/data/require.dict b/chromium/third_party/libaddressinput/fuzz/data/require.dict
deleted file mode 100644
index 8c162169f08..00000000000
--- a/chromium/third_party/libaddressinput/fuzz/data/require.dict
+++ /dev/null
@@ -1,8 +0,0 @@
-"A"
-"AC"
-"ACS"
-"ACSZ"
-"ACZ"
-"AS"
-"ASCZ"
-"AZ"
diff --git a/chromium/third_party/libaddressinput/fuzz/parse_address_fields_fuzzer.cc b/chromium/third_party/libaddressinput/fuzz/parse_address_fields_fuzzer.cc
deleted file mode 100644
index 0ff0070e0e7..00000000000
--- a/chromium/third_party/libaddressinput/fuzz/parse_address_fields_fuzzer.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include "third_party/libaddressinput/src/cpp/src/address_field_util.h"
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- std::string input(reinterpret_cast<const char*>(data), size);
- std::vector<i18n::addressinput::AddressField> address_field;
- i18n::addressinput::ParseAddressFieldsRequired(input, &address_field);
- return 0;
-}
diff --git a/chromium/third_party/libaddressinput/fuzz/parse_format_rule_fuzzer.cc b/chromium/third_party/libaddressinput/fuzz/parse_format_rule_fuzzer.cc
deleted file mode 100644
index c3dcf2d3583..00000000000
--- a/chromium/third_party/libaddressinput/fuzz/parse_format_rule_fuzzer.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include "third_party/libaddressinput/src/cpp/src/address_field_util.h"
-#include "third_party/libaddressinput/src/cpp/src/format_element.h"
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- std::string input(reinterpret_cast<const char*>(data), size);
- std::vector<i18n::addressinput::FormatElement> format_element;
- i18n::addressinput::ParseFormatRule(input, &format_element);
- return 0;
-}
diff --git a/chromium/third_party/ots/fuzz/ots_fuzzer.cc b/chromium/third_party/ots/fuzz/ots_fuzzer.cc
deleted file mode 100644
index d52f1b64fd0..00000000000
--- a/chromium/third_party/ots/fuzz/ots_fuzzer.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "third_party/ots/include/opentype-sanitiser.h"
-#include "third_party/ots/include/ots-memory-stream.h"
-
-static uint8_t buffer[256 * 1024] = { 0 };
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- ots::OTSContext context;
- ots::MemoryStream stream(static_cast<void*>(buffer), sizeof(buffer));
- context.Process(&stream, data, size);
- return 0;
-}
diff --git a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.cpp b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.cpp
index 2a896b8eb50..3f974ee72fd 100644
--- a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.cpp
+++ b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.cpp
@@ -97,9 +97,8 @@ void CPDF_ObjectStream::Init(const CPDF_Stream* stream) {
auto stream_acc = pdfium::MakeRetain<CPDF_StreamAcc>(stream);
stream_acc->LoadAllDataFiltered();
const uint32_t data_size = stream_acc->GetSize();
- data_ = stream_acc->DetachData();
data_stream_ = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(
- pdfium::make_span(data_.get(), data_size));
+ stream_acc->DetachData(), data_size);
}
CPDF_SyntaxParser syntax(data_stream_);
diff --git a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.h b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.h
index e96cff0ea9c..008c0cd2bea 100644
--- a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.h
+++ b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_object_stream.h
@@ -47,8 +47,6 @@ class CPDF_ObjectStream {
uint32_t obj_num_ = CPDF_Object::kInvalidObjNum;
uint32_t extends_obj_num_ = CPDF_Object::kInvalidObjNum;
- // |data_| holds the data used by |data_stream_|.
- std::unique_ptr<uint8_t, FxFreeDeleter> data_;
RetainPtr<IFX_SeekableReadStream> data_stream_;
int first_object_offset_ = 0;
std::map<uint32_t, uint32_t> objects_offsets_;
diff --git a/chromium/third_party/pdfium/core/fpdftext/cpdf_textpage.cpp b/chromium/third_party/pdfium/core/fpdftext/cpdf_textpage.cpp
index 13d8f0cf6b2..6b0a72eafe2 100644
--- a/chromium/third_party/pdfium/core/fpdftext/cpdf_textpage.cpp
+++ b/chromium/third_party/pdfium/core/fpdftext/cpdf_textpage.cpp
@@ -154,8 +154,11 @@ uint32_t GetCharWidth(uint32_t charCode, CPDF_Font* pFont) {
if (w > 0)
return w;
- ASSERT(pFont->GetCharBBox(charCode).Width() >= 0);
- return pFont->GetCharBBox(charCode).Width();
+ FX_RECT rect = pFont->GetCharBBox(charCode);
+ if (!rect.Valid())
+ return 0;
+
+ return std::max(rect.Width(), 0);
}
bool GenerateSpace(const CFX_PointF& pos,
diff --git a/chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.cpp b/chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.cpp
index bd31ee318d0..807788a4b89 100644
--- a/chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.cpp
+++ b/chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.cpp
@@ -6,9 +6,16 @@
#include "core/fxcrt/cfx_readonlymemorystream.h"
+#include <utility>
+
#include "core/fxcrt/fx_safe_types.h"
CFX_ReadOnlyMemoryStream::CFX_ReadOnlyMemoryStream(
+ std::unique_ptr<uint8_t, FxFreeDeleter> data,
+ size_t size)
+ : m_data(std::move(data)), m_span(m_data.get(), size) {}
+
+CFX_ReadOnlyMemoryStream::CFX_ReadOnlyMemoryStream(
pdfium::span<const uint8_t> span)
: m_span(span) {}
diff --git a/chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.h b/chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.h
index df277b57c7b..074ed8f5bf0 100644
--- a/chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.h
+++ b/chromium/third_party/pdfium/core/fxcrt/cfx_readonlymemorystream.h
@@ -7,6 +7,9 @@
#ifndef CORE_FXCRT_CFX_READONLYMEMORYSTREAM_H_
#define CORE_FXCRT_CFX_READONLYMEMORYSTREAM_H_
+#include <memory>
+
+#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/retain_ptr.h"
#include "third_party/base/span.h"
@@ -23,9 +26,12 @@ class CFX_ReadOnlyMemoryStream final : public IFX_SeekableReadStream {
size_t size) override;
private:
+ CFX_ReadOnlyMemoryStream(std::unique_ptr<uint8_t, FxFreeDeleter> data,
+ size_t size);
explicit CFX_ReadOnlyMemoryStream(pdfium::span<const uint8_t> span);
~CFX_ReadOnlyMemoryStream() override;
+ std::unique_ptr<uint8_t, FxFreeDeleter> m_data;
const pdfium::span<const uint8_t> m_span;
};
diff --git a/chromium/third_party/pdfium/core/fxge/cfx_renderdevice.cpp b/chromium/third_party/pdfium/core/fxge/cfx_renderdevice.cpp
index f55ad463679..f18966ce09f 100644
--- a/chromium/third_party/pdfium/core/fxge/cfx_renderdevice.cpp
+++ b/chromium/third_party/pdfium/core/fxge/cfx_renderdevice.cpp
@@ -45,11 +45,23 @@ void AdjustGlyphSpace(std::vector<FXTEXT_GLYPHPOS>* pGlyphAndPos) {
float current_origin_f =
bVertical ? current.m_fOrigin.y : current.m_fOrigin.x;
- int space = next_origin - current_origin;
+ FX_SAFE_INT32 safe_space = next_origin;
+ safe_space -= current_origin;
+ if (!safe_space.IsValid())
+ continue;
+
+ int space = safe_space.ValueOrDie();
float space_f = next_origin_f - current_origin_f;
float error = fabs(space_f) - fabs(static_cast<float>(space));
- if (error > 0.5f)
- current_origin += space > 0 ? -1 : 1;
+ if (error <= 0.5f)
+ continue;
+
+ FX_SAFE_INT32 safe_origin = current_origin;
+ safe_origin += space > 0 ? -1 : 1;
+ if (!safe_origin.IsValid())
+ continue;
+
+ current_origin = safe_origin.ValueOrDie();
}
}
diff --git a/chromium/third_party/re2/src/re2/fuzzing/re2_fuzzer.cc b/chromium/third_party/re2/src/re2/fuzzing/re2_fuzzer.cc
deleted file mode 100644
index 084b5c05531..00000000000
--- a/chromium/third_party/re2/src/re2/fuzzing/re2_fuzzer.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2016 The RE2 Authors. All Rights Reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-#include <map>
-#include <memory>
-#include <queue>
-#include <string>
-
-#include "re2/prefilter.h"
-#include "re2/re2.h"
-
-using re2::StringPiece;
-using std::string;
-
-// NOT static, NOT signed.
-uint8_t dummy = 0;
-
-void Test(StringPiece pattern, const RE2::Options& options, StringPiece text) {
- RE2 re(pattern, options);
- if (!re.ok())
- return;
-
- // Don't waste time fuzzing high-size programs.
- // They can cause bug reports due to fuzzer timeouts.
- int size = re.ProgramSize();
- if (size > 9999)
- return;
- int rsize = re.ReverseProgramSize();
- if (rsize > 9999)
- return;
-
- // Don't waste time fuzzing high-fanout programs.
- // They can cause bug reports due to fuzzer timeouts.
- std::map<int, int> histogram;
- int fanout = re.ProgramFanout(&histogram);
- if (fanout > 9)
- return;
- int rfanout = re.ReverseProgramFanout(&histogram);
- if (rfanout > 9)
- return;
-
- // Don't waste time fuzzing programs with large substrings.
- // They can cause bug reports due to fuzzer timeouts when they
- // are repetitions (e.g. hundreds of NUL bytes) and matching is
- // unanchored. And they aren't interesting for fuzzing purposes.
- std::unique_ptr<re2::Prefilter> prefilter(re2::Prefilter::FromRE2(&re));
- if (prefilter == nullptr)
- return;
- std::queue<re2::Prefilter*> nodes;
- nodes.push(prefilter.get());
- while (!nodes.empty()) {
- re2::Prefilter* node = nodes.front();
- nodes.pop();
- if (node->op() == re2::Prefilter::ATOM) {
- if (node->atom().size() > 9)
- return;
- } else if (node->op() == re2::Prefilter::AND ||
- node->op() == re2::Prefilter::OR) {
- for (re2::Prefilter* sub : *node->subs())
- nodes.push(sub);
- }
- }
-
- if (re.NumberOfCapturingGroups() == 0) {
- // Avoid early return due to too many arguments.
- StringPiece sp = text;
- RE2::FullMatch(sp, re);
- RE2::PartialMatch(sp, re);
- RE2::Consume(&sp, re);
- sp = text; // Reset.
- RE2::FindAndConsume(&sp, re);
- } else {
- // Okay, we have at least one capturing group...
- // Try conversion for variously typed arguments.
- StringPiece sp = text;
- short s;
- RE2::FullMatch(sp, re, &s);
- long l;
- RE2::PartialMatch(sp, re, &l);
- float f;
- RE2::Consume(&sp, re, &f);
- sp = text; // Reset.
- double d;
- RE2::FindAndConsume(&sp, re, &d);
- }
-
- string s = string(text);
- RE2::Replace(&s, re, "");
- s = string(text); // Reset.
- RE2::GlobalReplace(&s, re, "");
-
- string min, max;
- re.PossibleMatchRange(&min, &max, /*maxlen=*/9);
-
- // Exercise some other API functionality.
- dummy += re.NamedCapturingGroups().size();
- dummy += re.CapturingGroupNames().size();
- dummy += RE2::QuoteMeta(pattern).size();
-}
-
-// Entry point for libFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- if (size == 0 || size > 999)
- return 0;
-
- // Crudely limit the use of ., \p and \P.
- // Otherwise, we will waste time on inputs that have long runs of Unicode
- // character classes. The fuzzer has shown itself to be easily capable of
- // generating such patterns that fall within the other limits, but result
- // in timeouts nonetheless. The marginal cost is high - even more so when
- // counted repetition is involved - whereas the marginal benefit is zero.
- int dot = 0;
- int backslash_p = 0;
- for (size_t i = 0; i < size; i++) {
- if (data[i] == '.')
- dot++;
- if (data[i] != '\\')
- continue;
- i++;
- if (i >= size)
- break;
- if (data[i] == 'p' || data[i] == 'P')
- backslash_p++;
- }
- if (dot > 99)
- return 0;
- if (backslash_p > 1)
- return 0;
-
- // The one-at-a-time hash by Bob Jenkins.
- uint32_t hash = 0;
- for (size_t i = 0; i < size; i++) {
- hash += data[i];
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
-
- RE2::Options options;
- options.set_log_errors(false);
- options.set_max_mem(64 << 20);
- options.set_encoding(hash & 1 ? RE2::Options::EncodingLatin1
- : RE2::Options::EncodingUTF8);
- options.set_posix_syntax(hash & 2);
- options.set_longest_match(hash & 4);
- options.set_literal(hash & 8);
- options.set_never_nl(hash & 16);
- options.set_dot_nl(hash & 32);
- options.set_never_capture(hash & 64);
- options.set_case_sensitive(hash & 128);
- options.set_perl_classes(hash & 256);
- options.set_word_boundary(hash & 512);
- options.set_one_line(hash & 1024);
-
- const char* ptr = reinterpret_cast<const char*>(data);
- int len = static_cast<int>(size);
-
- StringPiece pattern(ptr, len);
- StringPiece text(ptr, len);
- Test(pattern, options, text);
-
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/Fuzz.cpp b/chromium/third_party/skia/fuzz/Fuzz.cpp
deleted file mode 100644
index 35a00bf85a2..00000000000
--- a/chromium/third_party/skia/fuzz/Fuzz.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "Fuzz.h"
-#include "FuzzCommon.h"
-
-// UBSAN reminds us that bool can only legally hold 0 or 1.
-void Fuzz::next(bool* b) {
- uint8_t n;
- this->next(&n);
- *b = (n & 1) == 1;
-}
-
-void Fuzz::next(SkImageFilter::CropRect* cropRect) {
- SkRect rect;
- uint8_t flags;
- this->next(&rect);
- this->nextRange(&flags, 0, 0xF);
- *cropRect = SkImageFilter::CropRect(rect, flags);
-}
-
-void Fuzz::nextBytes(void* n, size_t size) {
- if ((fNextByte + size) > fBytes->size()) {
- sk_bzero(n, size);
- memcpy(n, fBytes->bytes() + fNextByte, fBytes->size() - fNextByte);
- fNextByte = fBytes->size();
- return;
- }
- memcpy(n, fBytes->bytes() + fNextByte, size);
- fNextByte += size;
-}
-
-void Fuzz::next(SkRegion* region) {
- // See FuzzCommon.h
- FuzzNiceRegion(this, region, 10);
-}
-
-void Fuzz::nextRange(float* f, float min, float max) {
- this->next(f);
- if (!std::isnormal(*f) && *f != 0.0f) {
- // Don't deal with infinity or other strange floats.
- *f = max;
- }
- *f = min + std::fmod(std::abs(*f), (max - min + 1));
-}
diff --git a/chromium/third_party/skia/fuzz/Fuzz.h b/chromium/third_party/skia/fuzz/Fuzz.h
deleted file mode 100644
index f28298ee97f..00000000000
--- a/chromium/third_party/skia/fuzz/Fuzz.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef Fuzz_DEFINED
-#define Fuzz_DEFINED
-
-#include "../tools/Registry.h"
-#include "SkData.h"
-#include "SkImageFilter.h"
-#include "SkMalloc.h"
-#include "SkRegion.h"
-#include "SkTypes.h"
-
-#include <limits>
-#include <cmath>
-#include <signal.h>
-#include <limits>
-
-class Fuzz : SkNoncopyable {
-public:
- explicit Fuzz(sk_sp<SkData> bytes) : fBytes(bytes), fNextByte(0) {}
-
- // Returns the total number of "random" bytes available.
- size_t size() { return fBytes->size(); }
- // Returns if there are no bytes remaining for fuzzing.
- bool exhausted() {
- return fBytes->size() == fNextByte;
- }
-
- size_t remaining() {
- return fBytes->size() - fNextByte;
- }
-
- void deplete() {
- fNextByte = fBytes->size();
- }
-
- // next() loads fuzzed bytes into the variable passed in by pointer.
- // We use this approach instead of T next() because different compilers
- // evaluate function parameters in different orders. If fuzz->next()
- // returned 5 and then 7, foo(fuzz->next(), fuzz->next()) would be
- // foo(5, 7) when compiled on GCC and foo(7, 5) when compiled on Clang.
- // By requiring params to be passed in, we avoid the temptation to call
- // next() in a way that does not consume fuzzed bytes in a single
- // platform-independent order.
- template <typename T>
- void next(T* t) { this->nextBytes(t, sizeof(T)); }
-
- // This is a convenient way to initialize more than one argument at a time.
- template <typename Arg, typename... Args>
- void next(Arg* first, Args... rest);
-
- // nextRange returns values only in [min, max].
- template <typename T, typename Min, typename Max>
- void nextRange(T*, Min, Max);
-
- // nextN loads n * sizeof(T) bytes into ptr
- template <typename T>
- void nextN(T* ptr, int n);
-
- void signalBug(){
- // Tell the fuzzer that these inputs found a bug.
- SkDebugf("Signal bug\n");
- raise(SIGSEGV);
- }
-
- // Specialized versions for when true random doesn't quite make sense
- void next(bool* b);
- void next(SkImageFilter::CropRect* cropRect);
- void next(SkRegion* region);
-
- void nextRange(float* f, float min, float max);
-
-private:
- template <typename T>
- T nextT();
-
- sk_sp<SkData> fBytes;
- size_t fNextByte;
- friend void fuzz__MakeEncoderCorpus(Fuzz*);
-
- void nextBytes(void* ptr, size_t size);
-};
-
-template <typename Arg, typename... Args>
-inline void Fuzz::next(Arg* first, Args... rest) {
- this->next(first);
- this->next(rest...);
-}
-
-template <typename T, typename Min, typename Max>
-inline void Fuzz::nextRange(T* value, Min min, Max max) {
- this->next(value);
- if (*value < (T)min) { *value = (T)min; }
- if (*value > (T)max) { *value = (T)max; }
-}
-
-template <typename T>
-inline void Fuzz::nextN(T* ptr, int n) {
- for (int i = 0; i < n; i++) {
- this->next(ptr+i);
- }
-}
-
-struct Fuzzable {
- const char* name;
- void (*fn)(Fuzz*);
-};
-
-// Not static so that we can link these into oss-fuzz harnesses if we like.
-#define DEF_FUZZ(name, f) \
- void fuzz_##name(Fuzz*); \
- sk_tools::Registry<Fuzzable> register_##name({#name, fuzz_##name}); \
- void fuzz_##name(Fuzz* f)
-
-#endif//Fuzz_DEFINED
diff --git a/chromium/third_party/skia/fuzz/FuzzCanvas.cpp b/chromium/third_party/skia/fuzz/FuzzCanvas.cpp
deleted file mode 100644
index 4cb61ce0a78..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzCanvas.cpp
+++ /dev/null
@@ -1,1731 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "FuzzCommon.h"
-
-// CORE
-#include "SkCanvas.h"
-#include "SkColorFilter.h"
-#include "SkDebugCanvas.h"
-#include "SkFontMgr.h"
-#include "SkImageFilter.h"
-#include "SkMaskFilter.h"
-#include "SkNullCanvas.h"
-#include "SkOSFile.h"
-#include "SkPDFDocument.h"
-#include "SkPathEffect.h"
-#include "SkPicturePriv.h"
-#include "SkPictureRecorder.h"
-#include "SkPoint3.h"
-#include "SkRSXform.h"
-#include "SkRegion.h"
-#include "SkSurface.h"
-#include "SkTo.h"
-#include "SkTypeface.h"
-
-// EFFECTS
-#include "Sk1DPathEffect.h"
-#include "Sk2DPathEffect.h"
-#include "SkAlphaThresholdFilter.h"
-#include "SkArithmeticImageFilter.h"
-#include "SkBlurImageFilter.h"
-#include "SkBlurMaskFilter.h"
-#include "SkColorFilterImageFilter.h"
-#include "SkColorMatrixFilter.h"
-#include "SkComposeImageFilter.h"
-#include "SkCornerPathEffect.h"
-#include "SkDashPathEffect.h"
-#include "SkDiscretePathEffect.h"
-#include "SkDisplacementMapEffect.h"
-#include "SkDropShadowImageFilter.h"
-#include "SkGradientShader.h"
-#include "SkHighContrastFilter.h"
-#include "SkImageSource.h"
-#include "SkLightingImageFilter.h"
-#include "SkLumaColorFilter.h"
-#include "SkMagnifierImageFilter.h"
-#include "SkMatrixConvolutionImageFilter.h"
-#include "SkMergeImageFilter.h"
-#include "SkMorphologyImageFilter.h"
-#include "SkOffsetImageFilter.h"
-#include "SkPaintImageFilter.h"
-#include "SkPerlinNoiseShader.h"
-#include "SkPictureImageFilter.h"
-#include "SkReadBuffer.h"
-#include "SkTableColorFilter.h"
-#include "SkTextBlob.h"
-#include "SkTileImageFilter.h"
-#include "SkXfermodeImageFilter.h"
-
-// SRC
-#include "SkCommandLineFlags.h"
-#include "SkUTF.h"
-
-#if SK_SUPPORT_GPU
-#include "GrContextFactory.h"
-#include "GrContextPriv.h"
-#include "gl/GrGLFunctions.h"
-#include "gl/GrGLGpu.h"
-#include "gl/GrGLUtil.h"
-#endif
-
-// MISC
-
-#include <iostream>
-#include <utility>
-
-DEFINE_bool2(gpuInfo, g, false, "Display GPU information on relevant targets.");
-
-// TODO:
-// SkTextBlob with Unicode
-// SkImage: more types
-
-// be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
-// In fact, all make_fuzz_foo() functions have this potential problem.
-// Use sequence points!
-template <typename T>
-inline T make_fuzz_t(Fuzz* fuzz) {
- T t;
- fuzz->next(&t);
- return t;
-}
-
-static sk_sp<SkImage> make_fuzz_image(Fuzz*);
-
-static SkBitmap make_fuzz_bitmap(Fuzz*);
-
-static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
-
-static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
- if (depth <= 0) {
- return nullptr;
- }
- int colorFilterType;
- fuzz->nextRange(&colorFilterType, 0, 8);
- switch (colorFilterType) {
- case 0:
- return nullptr;
- case 1: {
- SkColor color;
- SkBlendMode mode;
- fuzz->next(&color);
- fuzz->nextRange(&mode, 0, SkBlendMode::kLastMode);
- return SkColorFilter::MakeModeFilter(color, mode);
- }
- case 2: {
- sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
- if (!outer) {
- return nullptr;
- }
- sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
- // makeComposed should be able to handle nullptr.
- return outer->makeComposed(std::move(inner));
- }
- case 3: {
- SkScalar array[20];
- fuzz->nextN(array, SK_ARRAY_COUNT(array));
- return SkColorFilter::MakeMatrixFilterRowMajor255(array);
- }
- case 4: {
- SkColor mul, add;
- fuzz->next(&mul, &add);
- return SkColorMatrixFilter::MakeLightingFilter(mul, add);
- }
- case 5: {
- bool grayscale;
- int invertStyle;
- float contrast;
- fuzz->next(&grayscale);
- fuzz->nextRange(&invertStyle, 0, 2);
- fuzz->nextRange(&contrast, -1.0f, 1.0f);
- return SkHighContrastFilter::Make(SkHighContrastConfig(
- grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
- }
- case 6:
- return SkLumaColorFilter::Make();
- case 7: {
- uint8_t table[256];
- fuzz->nextN(table, SK_ARRAY_COUNT(table));
- return SkTableColorFilter::Make(table);
- }
- case 8: {
- uint8_t tableA[256];
- uint8_t tableR[256];
- uint8_t tableG[256];
- uint8_t tableB[256];
- fuzz->nextN(tableA, SK_ARRAY_COUNT(tableA));
- fuzz->nextN(tableR, SK_ARRAY_COUNT(tableR));
- fuzz->nextN(tableG, SK_ARRAY_COUNT(tableG));
- fuzz->nextN(tableB, SK_ARRAY_COUNT(tableB));
- return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
- }
- default:
- SkASSERT(false);
- break;
- }
- return nullptr;
-}
-
-static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
- SkScalar totalPos = 0;
- for (int i = 0; i < colorCount; ++i) {
- fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
- totalPos += pos[i];
- }
- totalPos = 1.0f / totalPos;
- for (int i = 0; i < colorCount; ++i) {
- pos[i] *= totalPos;
- }
- // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
- pos[colorCount - 1] = 1.0f;
-}
-
-static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
- sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
- sk_sp<SkColorFilter> colorFilter(nullptr);
- SkBitmap bitmap;
- sk_sp<SkImage> img;
- SkShader::TileMode tmX, tmY;
- bool useMatrix;
- SkColor color;
- SkMatrix matrix;
- SkBlendMode blendMode;
- int shaderType;
- if (depth <= 0) {
- return nullptr;
- }
- fuzz->nextRange(&shaderType, 0, 14);
- switch (shaderType) {
- case 0:
- return nullptr;
- case 1:
- return SkShader::MakeEmptyShader();
- case 2:
- fuzz->next(&color);
- return SkShader::MakeColorShader(color);
- case 3:
- img = make_fuzz_image(fuzz);
- fuzz->nextRange(&tmX, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->nextRange(&tmY, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->next(&useMatrix);
- if (useMatrix) {
- FuzzNiceMatrix(fuzz, &matrix);
- }
- return img->makeShader(tmX, tmY, useMatrix ? &matrix : nullptr);
- case 4:
- bitmap = make_fuzz_bitmap(fuzz);
- fuzz->nextRange(&tmX, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->nextRange(&tmY, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->next(&useMatrix);
- if (useMatrix) {
- FuzzNiceMatrix(fuzz, &matrix);
- }
- return SkShader::MakeBitmapShader(bitmap, tmX, tmY, useMatrix ? &matrix : nullptr);
- case 5:
- shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
- FuzzNiceMatrix(fuzz, &matrix);
- return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
- case 6:
- shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
- colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
- return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
- case 7:
- shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
- shader2 = make_fuzz_shader(fuzz, depth - 1);
- fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
- return SkShader::MakeComposeShader(std::move(shader1), std::move(shader2), blendMode);
- case 8: {
- auto pic = make_fuzz_picture(fuzz, depth - 1);
- bool useTile;
- SkRect tile;
- fuzz->nextRange(&tmX, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->nextRange(&tmY, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->next(&useMatrix, &useTile);
- if (useMatrix) {
- FuzzNiceMatrix(fuzz, &matrix);
- }
- if (useTile) {
- fuzz->next(&tile);
- }
- return SkShader::MakePictureShader(std::move(pic), tmX, tmY,
- useMatrix ? &matrix : nullptr,
- useTile ? &tile : nullptr);
- }
- // EFFECTS:
- case 9:
- // Deprecated SkGaussianEdgeShader
- return nullptr;
- case 10: {
- constexpr int kMaxColors = 12;
- SkPoint pts[2];
- SkColor colors[kMaxColors];
- SkScalar pos[kMaxColors];
- int colorCount;
- bool usePos;
- fuzz->nextN(pts, 2);
- fuzz->nextRange(&colorCount, 2, kMaxColors);
- fuzz->nextN(colors, colorCount);
- fuzz->nextRange(&tmX, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->next(&useMatrix, &usePos);
- if (useMatrix) {
- FuzzNiceMatrix(fuzz, &matrix);
- }
- if (usePos) {
- fuzz_gradient_stops(fuzz, pos, colorCount);
- }
- return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
- tmX, 0, useMatrix ? &matrix : nullptr);
- }
- case 11: {
- constexpr int kMaxColors = 12;
- SkPoint center;
- SkScalar radius;
- int colorCount;
- bool usePos;
- SkColor colors[kMaxColors];
- SkScalar pos[kMaxColors];
- fuzz->nextRange(&tmX, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->next(&useMatrix, &usePos, &center, &radius);
- fuzz->nextRange(&colorCount, 2, kMaxColors);
- fuzz->nextN(colors, colorCount);
- if (useMatrix) {
- FuzzNiceMatrix(fuzz, &matrix);
- }
- if (usePos) {
- fuzz_gradient_stops(fuzz, pos, colorCount);
- }
- return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
- colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
- }
- case 12: {
- constexpr int kMaxColors = 12;
- SkPoint start, end;
- SkScalar startRadius, endRadius;
- int colorCount;
- bool usePos;
- SkColor colors[kMaxColors];
- SkScalar pos[kMaxColors];
- fuzz->nextRange(&tmX, 0, SkShader::TileMode::kLast_TileMode);
- fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
- fuzz->nextRange(&colorCount, 2, kMaxColors);
- fuzz->nextN(colors, colorCount);
- if (useMatrix) {
- FuzzNiceMatrix(fuzz, &matrix);
- }
- if (usePos) {
- fuzz_gradient_stops(fuzz, pos, colorCount);
- }
- return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
- usePos ? pos : nullptr, colorCount, tmX, 0,
- useMatrix ? &matrix : nullptr);
- }
- case 13: {
- constexpr int kMaxColors = 12;
- SkScalar cx, cy;
- int colorCount;
- bool usePos;
- SkColor colors[kMaxColors];
- SkScalar pos[kMaxColors];
- fuzz->next(&cx, &cy, &useMatrix, &usePos);
- fuzz->nextRange(&colorCount, 2, kMaxColors);
- fuzz->nextN(colors, colorCount);
- if (useMatrix) {
- FuzzNiceMatrix(fuzz, &matrix);
- }
- if (usePos) {
- fuzz_gradient_stops(fuzz, pos, colorCount);
- }
- return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
- 0, useMatrix ? &matrix : nullptr);
- }
- case 14: {
- SkScalar baseFrequencyX, baseFrequencyY, seed;
- int numOctaves;
- SkISize tileSize;
- bool useTileSize, turbulence;
- fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
- if (useTileSize) {
- fuzz->next(&tileSize);
- }
- fuzz->nextRange(&numOctaves, 2, 7);
- if (turbulence) {
- return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
- numOctaves, seed,
- useTileSize ? &tileSize : nullptr);
- } else {
- return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
- numOctaves, seed,
- useTileSize ? &tileSize : nullptr);
- }
- }
- default:
- SkASSERT(false);
- break;
- }
- return nullptr;
-}
-
-static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
- if (depth <= 0) {
- return nullptr;
- }
- uint8_t pathEffectType;
- fuzz->nextRange(&pathEffectType, 0, 8);
- switch (pathEffectType) {
- case 0: {
- return nullptr;
- }
- case 1: {
- sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
- sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
- return SkPathEffect::MakeSum(std::move(first), std::move(second));
- }
- case 2: {
- sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
- sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
- return SkPathEffect::MakeCompose(std::move(first), std::move(second));
- }
- case 3: {
- SkPath path;
- FuzzNicePath(fuzz, &path, 20);
- SkScalar advance, phase;
- fuzz->next(&advance, &phase);
- SkPath1DPathEffect::Style style;
- fuzz->nextRange(&style, 0, SkPath1DPathEffect::kLastEnum_Style);
- return SkPath1DPathEffect::Make(path, advance, phase, style);
- }
- case 4: {
- SkScalar width;
- SkMatrix matrix;
- fuzz->next(&width);
- FuzzNiceMatrix(fuzz, &matrix);
- return SkLine2DPathEffect::Make(width, matrix);
- }
- case 5: {
- SkPath path;
- FuzzNicePath(fuzz, &path, 20);
- SkMatrix matrix;
- FuzzNiceMatrix(fuzz, &matrix);
- return SkPath2DPathEffect::Make(matrix, path);
- }
- case 6: {
- SkScalar radius;
- fuzz->next(&radius);
- return SkCornerPathEffect::Make(radius);
- }
- case 7: {
- SkScalar phase;
- fuzz->next(&phase);
- SkScalar intervals[20];
- int count;
- fuzz->nextRange(&count, 0, (int)SK_ARRAY_COUNT(intervals));
- fuzz->nextN(intervals, count);
- return SkDashPathEffect::Make(intervals, count, phase);
- }
- case 8: {
- SkScalar segLength, dev;
- uint32_t seed;
- fuzz->next(&segLength, &dev, &seed);
- return SkDiscretePathEffect::Make(segLength, dev, seed);
- }
- default:
- SkASSERT(false);
- return nullptr;
- }
-}
-
-static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
- int maskfilterType;
- fuzz->nextRange(&maskfilterType, 0, 1);
- switch (maskfilterType) {
- case 0:
- return nullptr;
- case 1: {
- SkBlurStyle blurStyle;
- fuzz->nextRange(&blurStyle, 0, kLastEnum_SkBlurStyle);
- SkScalar sigma;
- fuzz->next(&sigma);
- bool respectCTM;
- fuzz->next(&respectCTM);
- return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
- }
- default:
- SkASSERT(false);
- return nullptr;
- }
-}
-
-static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
- if (make_fuzz_t<bool>(fuzz)) {
- return nullptr;
- }
- auto fontMugger = SkFontMgr::RefDefault();
- SkASSERT(fontMugger);
- int familyCount = fontMugger->countFamilies();
- int i, j;
- fuzz->nextRange(&i, 0, familyCount - 1);
- sk_sp<SkFontStyleSet> family(fontMugger->createStyleSet(i));
- int styleCount = family->count();
- fuzz->nextRange(&j, 0, styleCount - 1);
- return sk_sp<SkTypeface>(family->createTypeface(j));
-}
-
-static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
-
-static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
- if (depth <= 0) {
- return nullptr;
- }
- uint8_t imageFilterType;
- fuzz->nextRange(&imageFilterType, 1, 6);
- SkPoint3 p, q;
- SkColor lightColor;
- SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
- sk_sp<SkImageFilter> input;
- SkImageFilter::CropRect cropRect;
- bool useCropRect;
- fuzz->next(&useCropRect);
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- switch (imageFilterType) {
- case 1:
- fuzz->next(&p, &lightColor, &surfaceScale, &k);
- input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkLightingImageFilter::MakeDistantLitDiffuse(p, lightColor, surfaceScale, k,
- std::move(input),
- useCropRect ? &cropRect : nullptr);
- case 2:
- fuzz->next(&p, &lightColor, &surfaceScale, &k);
- input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkLightingImageFilter::MakePointLitDiffuse(p, lightColor, surfaceScale, k,
- std::move(input),
- useCropRect ? &cropRect : nullptr);
- case 3:
- fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
- input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkLightingImageFilter::MakeSpotLitDiffuse(
- p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
- std::move(input), useCropRect ? &cropRect : nullptr);
- case 4:
- fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
- input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkLightingImageFilter::MakeDistantLitSpecular(p, lightColor, surfaceScale, k,
- shininess, std::move(input),
- useCropRect ? &cropRect : nullptr);
- case 5:
- fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
- input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkLightingImageFilter::MakePointLitSpecular(p, lightColor, surfaceScale, k,
- shininess, std::move(input),
- useCropRect ? &cropRect : nullptr);
- case 6:
- fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
- &shininess);
- input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkLightingImageFilter::MakeSpotLitSpecular(
- p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
- std::move(input), useCropRect ? &cropRect : nullptr);
- default:
- SkASSERT(false);
- return nullptr;
- }
-}
-
-static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
-
-static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
- if (depth <= 0) {
- return nullptr;
- }
- uint8_t imageFilterType;
- fuzz->nextRange(&imageFilterType, 0, 23);
- switch (imageFilterType) {
- case 0:
- return nullptr;
- case 1: {
- SkScalar sigmaX, sigmaY;
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- bool useCropRect;
- fuzz->next(&sigmaX, &sigmaY, &useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- return SkBlurImageFilter::Make(sigmaX, sigmaY, std::move(input),
- useCropRect ? &cropRect : nullptr);
- }
- case 2: {
- SkMatrix matrix;
- FuzzNiceMatrix(fuzz, &matrix);
- SkFilterQuality quality;
- fuzz->nextRange(&quality, 0, SkFilterQuality::kLast_SkFilterQuality);
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkImageFilter::MakeMatrixFilter(matrix, quality, std::move(input));
- }
- case 3: {
- SkRegion region;
- SkScalar innerMin, outerMax;
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- bool useCropRect;
- fuzz->next(&region, &innerMin, &outerMax, &useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- return SkAlphaThresholdFilter::Make(region, innerMin, outerMax, std::move(input),
- useCropRect ? &cropRect : nullptr);
- }
- case 4: {
- float k1, k2, k3, k4;
- bool enforcePMColor;
- bool useCropRect;
- fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
- sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
- sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- return SkArithmeticImageFilter::Make(k1, k2, k3, k4, enforcePMColor,
- std::move(background), std::move(foreground),
- useCropRect ? &cropRect : nullptr);
- }
- case 5: {
- sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- bool useCropRect;
- SkImageFilter::CropRect cropRect;
- fuzz->next(&useCropRect);
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- return SkColorFilterImageFilter::Make(std::move(cf), std::move(input),
- useCropRect ? &cropRect : nullptr);
- }
- case 6: {
- sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
- sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkComposeImageFilter::Make(std::move(ifo), std::move(ifi));
- }
- case 7: {
- SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, yChannelSelector;
- fuzz->nextRange(&xChannelSelector, 1, 4);
- fuzz->nextRange(&yChannelSelector, 1, 4);
- SkScalar scale;
- bool useCropRect;
- fuzz->next(&scale, &useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
- sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkDisplacementMapEffect::Make(xChannelSelector, yChannelSelector, scale,
- std::move(displacement), std::move(color),
- useCropRect ? &cropRect : nullptr);
- }
- case 8: {
- SkScalar dx, dy, sigmaX, sigmaY;
- SkColor color;
- SkDropShadowImageFilter::ShadowMode shadowMode;
- fuzz->nextRange(&shadowMode, 0, 1);
- bool useCropRect;
- fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkDropShadowImageFilter::Make(dx, dy, sigmaX, sigmaY, color, shadowMode,
- std::move(input),
- useCropRect ? &cropRect : nullptr);
- }
- case 9:
- return SkImageSource::Make(make_fuzz_image(fuzz));
- case 10: {
- sk_sp<SkImage> image = make_fuzz_image(fuzz);
- SkRect srcRect, dstRect;
- SkFilterQuality filterQuality;
- fuzz->next(&srcRect, &dstRect);
- fuzz->nextRange(&filterQuality, 0, SkFilterQuality::kLast_SkFilterQuality);
- return SkImageSource::Make(std::move(image), srcRect, dstRect, filterQuality);
- }
- case 11:
- return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
- case 12: {
- SkRect srcRect;
- SkScalar inset;
- bool useCropRect;
- SkImageFilter::CropRect cropRect;
- fuzz->next(&srcRect, &inset, &useCropRect);
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkMagnifierImageFilter::Make(srcRect, inset, std::move(input),
- useCropRect ? &cropRect : nullptr);
- }
- case 13: {
- constexpr int kMaxKernelSize = 5;
- int32_t n, m;
- fuzz->nextRange(&n, 1, kMaxKernelSize);
- fuzz->nextRange(&m, 1, kMaxKernelSize);
- SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
- fuzz->nextN(kernel, n * m);
- int32_t offsetX, offsetY;
- fuzz->nextRange(&offsetX, 0, n - 1);
- fuzz->nextRange(&offsetY, 0, m - 1);
- SkScalar gain, bias;
- bool convolveAlpha, useCropRect;
- fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
- SkMatrixConvolutionImageFilter::TileMode tileMode;
- fuzz->nextRange(&tileMode, 0, SkMatrixConvolutionImageFilter::TileMode::kLast_TileMode);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkMatrixConvolutionImageFilter::Make(
- SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
- convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
- }
- case 14: {
- sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
- sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
- bool useCropRect;
- fuzz->next(&useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- return SkMergeImageFilter::Make(std::move(first), std::move(second),
- useCropRect ? &cropRect : nullptr);
- }
- case 15: {
- constexpr int kMaxCount = 4;
- sk_sp<SkImageFilter> ifs[kMaxCount];
- int count;
- fuzz->nextRange(&count, 1, kMaxCount);
- for (int i = 0; i < count; ++i) {
- ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
- }
- bool useCropRect;
- fuzz->next(&useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- return SkMergeImageFilter::Make(ifs, count, useCropRect ? &cropRect : nullptr);
- }
- case 16: {
- int rx, ry;
- fuzz->next(&rx, &ry);
- bool useCropRect;
- fuzz->next(&useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkDilateImageFilter::Make(rx, ry, std::move(input),
- useCropRect ? &cropRect : nullptr);
- }
- case 17: {
- int rx, ry;
- fuzz->next(&rx, &ry);
- bool useCropRect;
- fuzz->next(&useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkErodeImageFilter::Make(rx, ry, std::move(input),
- useCropRect ? &cropRect : nullptr);
- }
- case 18: {
- SkScalar dx, dy;
- fuzz->next(&dx, &dy);
- bool useCropRect;
- fuzz->next(&useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkOffsetImageFilter::Make(dx, dy, std::move(input),
- useCropRect ? &cropRect : nullptr);
- }
- case 19: {
- SkPaint paint;
- fuzz_paint(fuzz, &paint, depth - 1);
- bool useCropRect;
- fuzz->next(&useCropRect);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- return SkPaintImageFilter::Make(paint, useCropRect ? &cropRect : nullptr);
- }
- case 20: {
- sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
- return SkPictureImageFilter::Make(std::move(picture));
- }
- case 21: {
- SkRect cropRect;
- fuzz->next(&cropRect);
- sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
- return SkPictureImageFilter::Make(std::move(picture), cropRect);
- }
- case 22: {
- SkRect src, dst;
- fuzz->next(&src, &dst);
- sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkTileImageFilter::Make(src, dst, std::move(input));
- }
- case 23: {
- SkBlendMode blendMode;
- bool useCropRect;
- fuzz->next(&useCropRect);
- fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
- SkImageFilter::CropRect cropRect;
- if (useCropRect) {
- fuzz->next(&cropRect);
- }
- sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
- sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
- return SkXfermodeImageFilter::Make(blendMode, std::move(bg), std::move(fg),
- useCropRect ? &cropRect : nullptr);
- }
- default:
- SkASSERT(false);
- return nullptr;
- }
-}
-
-static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
- int w, h;
- fuzz->nextRange(&w, 1, 1024);
- fuzz->nextRange(&h, 1, 1024);
- SkAutoTMalloc<SkPMColor> data(w * h);
- SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
- int n = w * h;
- for (int i = 0; i < n; ++i) {
- SkColor c;
- fuzz->next(&c);
- data[i] = SkPreMultiplyColor(c);
- }
- (void)data.release();
- return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
- nullptr);
-}
-
-static SkBitmap make_fuzz_bitmap(Fuzz* fuzz) {
- SkBitmap bitmap;
- int w, h;
- fuzz->nextRange(&w, 1, 1024);
- fuzz->nextRange(&h, 1, 1024);
- if (!bitmap.tryAllocN32Pixels(w, h)) {
- SkDEBUGF("Could not allocate pixels %d x %d", w, h);
- return bitmap;
- }
- for (int y = 0; y < h; ++y) {
- for (int x = 0; x < w; ++x) {
- SkColor c;
- fuzz->next(&c);
- *bitmap.getAddr32(x, y) = SkPreMultiplyColor(c);
- }
- }
- return bitmap;
-}
-
-template <typename T, typename Min, typename Max>
-inline T make_fuzz_t_range(Fuzz* fuzz, Min minv, Max maxv) {
- T value;
- fuzz->nextRange(&value, minv, maxv);
- return value;
-}
-
-static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
- if (!fuzz || !paint || depth <= 0) {
- return;
- }
-
- paint->setAntiAlias( make_fuzz_t<bool>(fuzz));
- paint->setDither( make_fuzz_t<bool>(fuzz));
- paint->setColor( make_fuzz_t<SkColor>(fuzz));
- paint->setBlendMode( make_fuzz_t_range<SkBlendMode>(fuzz, 0, SkBlendMode::kLastMode));
- paint->setFilterQuality(make_fuzz_t_range<SkFilterQuality>(fuzz, 0, kLast_SkFilterQuality));
- paint->setStyle( make_fuzz_t_range<SkPaint::Style>(fuzz, 0, 2));
- paint->setShader( make_fuzz_shader(fuzz, depth - 1));
- paint->setPathEffect( make_fuzz_patheffect(fuzz, depth - 1));
- paint->setMaskFilter( make_fuzz_maskfilter(fuzz));
- paint->setImageFilter( make_fuzz_imageFilter(fuzz, depth - 1));
- paint->setColorFilter( make_fuzz_colorfilter(fuzz, depth - 1));
-
- if (paint->getStyle() != SkPaint::kFill_Style) {
- paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
- paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
- paint->setStrokeCap( make_fuzz_t_range<SkPaint::Cap>(fuzz, 0, SkPaint::kLast_Cap));
- paint->setStrokeJoin( make_fuzz_t_range<SkPaint::Join>(fuzz, 0, SkPaint::kLast_Join));
- }
-}
-
-static SkFont fuzz_font(Fuzz* fuzz) {
- SkFont font;
- font.setTypeface( make_fuzz_typeface(fuzz));
- font.setSize( make_fuzz_t<SkScalar>(fuzz));
- font.setScaleX( make_fuzz_t<SkScalar>(fuzz));
- font.setSkewX( make_fuzz_t<SkScalar>(fuzz));
- font.setLinearMetrics( make_fuzz_t<bool>(fuzz));
- font.setSubpixel( make_fuzz_t<bool>(fuzz));
- font.setEmbeddedBitmaps( make_fuzz_t<bool>(fuzz));
- font.setForceAutoHinting( make_fuzz_t<bool>(fuzz));
- font.setEmbolden( make_fuzz_t<bool>(fuzz));
- font.setHinting( make_fuzz_t_range<SkFontHinting>(fuzz, 0, kFull_SkFontHinting));
- font.setEdging( make_fuzz_t_range<SkFont::Edging>(fuzz, 0,
- (int)SkFont::Edging::kSubpixelAntiAlias));
- return font;
-}
-
-static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
- return make_fuzz_t_range<SkTextEncoding>(fuzz, 0, 3);
-}
-
-constexpr int kMaxGlyphCount = 30;
-
-static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
- SkTDArray<uint8_t> array;
- if (kGlyphID_SkTextEncoding == encoding) {
- int glyphRange = font.getTypefaceOrDefault()->countGlyphs();
- if (glyphRange == 0) {
- // Some fuzzing environments have no fonts, so empty array is the best
- // we can do.
- return array;
- }
- int glyphCount;
- fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
- SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
- for (int i = 0; i < glyphCount; ++i) {
- fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
- }
- return array;
- }
- static const SkUnichar ranges[][2] = {
- {0x0020, 0x007F},
- {0x00A1, 0x0250},
- {0x0400, 0x0500},
- };
- int32_t count = 0;
- for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
- count += (ranges[i][1] - ranges[i][0]);
- }
- constexpr int kMaxLength = kMaxGlyphCount;
- SkUnichar buffer[kMaxLength];
- int length;
- fuzz->nextRange(&length, 1, kMaxLength);
- for (int j = 0; j < length; ++j) {
- int32_t value;
- fuzz->nextRange(&value, 0, count - 1);
- for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
- if (value + ranges[i][0] < ranges[i][1]) {
- buffer[j] = value + ranges[i][0];
- break;
- } else {
- value -= (ranges[i][1] - ranges[i][0]);
- }
- }
- }
- switch (encoding) {
- case kUTF8_SkTextEncoding: {
- size_t utf8len = 0;
- for (int j = 0; j < length; ++j) {
- utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
- }
- char* ptr = (char*)array.append(utf8len);
- for (int j = 0; j < length; ++j) {
- ptr += SkUTF::ToUTF8(buffer[j], ptr);
- }
- } break;
- case kUTF16_SkTextEncoding: {
- size_t utf16len = 0;
- for (int j = 0; j < length; ++j) {
- utf16len += SkUTF::ToUTF16(buffer[j]);
- }
- uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
- for (int j = 0; j < length; ++j) {
- ptr += SkUTF::ToUTF16(buffer[j], ptr);
- }
- } break;
- case kUTF32_SkTextEncoding:
- memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
- break;
- default:
- SkASSERT(false);
- break;
- }
- return array;
-}
-
-static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
- SkTextBlobBuilder textBlobBuilder;
- int8_t runCount;
- fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
- while (runCount-- > 0) {
- SkFont font;
- SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
- font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
- SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
- int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
- SkASSERT(glyphCount <= kMaxGlyphCount);
- SkScalar x, y;
- const SkTextBlobBuilder::RunBuffer* buffer;
- uint8_t runType;
- fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
- const void* textPtr = text.begin();
- size_t textLen = SkToSizeT(text.count());
- switch (runType) {
- case 0:
- fuzz->next(&x, &y);
- // TODO: Test other variations of this.
- buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
- (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
- break;
- case 1:
- fuzz->next(&y);
- // TODO: Test other variations of this.
- buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
- (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
- fuzz->nextN(buffer->pos, glyphCount);
- break;
- case 2:
- // TODO: Test other variations of this.
- buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
- (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
- fuzz->nextN(buffer->pos, glyphCount * 2);
- break;
- default:
- SkASSERT(false);
- break;
- }
- }
- return textBlobBuilder.make();
-}
-
-extern std::atomic<bool> gSkUseDeltaAA;
-extern std::atomic<bool> gSkForceDeltaAA;
-
-static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
- if (!fuzz || !canvas || depth <= 0) {
- return;
- }
- SkAutoCanvasRestore autoCanvasRestore(canvas, false);
- bool useDAA;
- fuzz->next(&useDAA);
- if (useDAA) {
- gSkForceDeltaAA = true;
- gSkUseDeltaAA = true;
- }
- unsigned N;
- fuzz->nextRange(&N, 0, 2000);
- for (unsigned i = 0; i < N; ++i) {
- if (fuzz->exhausted()) {
- return;
- }
- SkPaint paint;
- SkFont font;
- unsigned drawCommand;
- fuzz->nextRange(&drawCommand, 0, 53);
- switch (drawCommand) {
- case 0:
- canvas->flush();
- break;
- case 1:
- canvas->save();
- break;
- case 2: {
- SkRect bounds;
- fuzz->next(&bounds);
- fuzz_paint(fuzz, &paint, depth - 1);
- canvas->saveLayer(&bounds, &paint);
- break;
- }
- case 3: {
- SkRect bounds;
- fuzz->next(&bounds);
- canvas->saveLayer(&bounds, nullptr);
- break;
- }
- case 4:
- fuzz_paint(fuzz, &paint, depth - 1);
- canvas->saveLayer(nullptr, &paint);
- break;
- case 5:
- canvas->saveLayer(nullptr, nullptr);
- break;
- case 6: {
- uint8_t alpha;
- fuzz->next(&alpha);
- canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
- break;
- }
- case 7: {
- SkRect bounds;
- uint8_t alpha;
- fuzz->next(&bounds, &alpha);
- canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
- break;
- }
- case 8: {
- SkCanvas::SaveLayerRec saveLayerRec;
- SkRect bounds;
- if (make_fuzz_t<bool>(fuzz)) {
- fuzz->next(&bounds);
- saveLayerRec.fBounds = &bounds;
- }
- if (make_fuzz_t<bool>(fuzz)) {
- fuzz_paint(fuzz, &paint, depth - 1);
- saveLayerRec.fPaint = &paint;
- }
- sk_sp<SkImageFilter> imageFilter;
- if (make_fuzz_t<bool>(fuzz)) {
- imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
- saveLayerRec.fBackdrop = imageFilter.get();
- }
- // _DumpCanvas can't handle this.
- // if (make_fuzz_t<bool>(fuzz)) {
- // saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
- // }
-
- canvas->saveLayer(saveLayerRec);
- break;
- }
- case 9:
- canvas->restore();
- break;
- case 10: {
- int saveCount;
- fuzz->next(&saveCount);
- canvas->restoreToCount(saveCount);
- break;
- }
- case 11: {
- SkScalar x, y;
- fuzz->next(&x, &y);
- canvas->translate(x, y);
- break;
- }
- case 12: {
- SkScalar x, y;
- fuzz->next(&x, &y);
- canvas->scale(x, y);
- break;
- }
- case 13: {
- SkScalar v;
- fuzz->next(&v);
- canvas->rotate(v);
- break;
- }
- case 14: {
- SkScalar x, y, v;
- fuzz->next(&x, &y, &v);
- canvas->rotate(v, x, y);
- break;
- }
- case 15: {
- SkScalar x, y;
- fuzz->next(&x, &y);
- canvas->skew(x, y);
- break;
- }
- case 16: {
- SkMatrix mat;
- FuzzNiceMatrix(fuzz, &mat);
- canvas->concat(mat);
- break;
- }
- case 17: {
- SkMatrix mat;
- FuzzNiceMatrix(fuzz, &mat);
- canvas->setMatrix(mat);
- break;
- }
- case 18:
- canvas->resetMatrix();
- break;
- case 19: {
- SkRect r;
- int op;
- bool doAntiAlias;
- fuzz->next(&r, &doAntiAlias);
- fuzz->nextRange(&op, 0, 1);
- r.sort();
- canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
- break;
- }
- case 20: {
- SkRRect rr;
- int op;
- bool doAntiAlias;
- FuzzNiceRRect(fuzz, &rr);
- fuzz->next(&doAntiAlias);
- fuzz->nextRange(&op, 0, 1);
- canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
- break;
- }
- case 21: {
- SkPath path;
- FuzzNicePath(fuzz, &path, 30);
- int op;
- bool doAntiAlias;
- fuzz->next(&doAntiAlias);
- fuzz->nextRange(&op, 0, 1);
- canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
- break;
- }
- case 22: {
- SkRegion region;
- int op;
- fuzz->next(&region);
- fuzz->nextRange(&op, 0, 1);
- canvas->clipRegion(region, (SkClipOp)op);
- break;
- }
- case 23:
- fuzz_paint(fuzz, &paint, depth - 1);
- canvas->drawPaint(paint);
- break;
- case 24: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkCanvas::PointMode pointMode;
- fuzz->nextRange(&pointMode,
- SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
- size_t count;
- constexpr int kMaxCount = 30;
- fuzz->nextRange(&count, 0, kMaxCount);
- SkPoint pts[kMaxCount];
- fuzz->nextN(pts, count);
- canvas->drawPoints(pointMode, count, pts, paint);
- break;
- }
- case 25: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkRect r;
- fuzz->next(&r);
- if (!r.isFinite()) {
- break;
- }
- canvas->drawRect(r, paint);
- break;
- }
- case 26: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkRegion region;
- fuzz->next(&region);
- canvas->drawRegion(region, paint);
- break;
- }
- case 27: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkRect r;
- fuzz->next(&r);
- if (!r.isFinite()) {
- break;
- }
- canvas->drawOval(r, paint);
- break;
- }
- case 28: break; // must have deleted this some time earlier
- case 29: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkRRect rr;
- FuzzNiceRRect(fuzz, &rr);
- canvas->drawRRect(rr, paint);
- break;
- }
- case 30: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkRRect orr, irr;
- FuzzNiceRRect(fuzz, &orr);
- FuzzNiceRRect(fuzz, &irr);
- if (orr.getBounds().contains(irr.getBounds())) {
- canvas->drawDRRect(orr, irr, paint);
- }
- break;
- }
- case 31: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkRect r;
- SkScalar start, sweep;
- bool useCenter;
- fuzz->next(&r, &start, &sweep, &useCenter);
- canvas->drawArc(r, start, sweep, useCenter, paint);
- break;
- }
- case 32: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkPath path;
- FuzzNicePath(fuzz, &path, 60);
- canvas->drawPath(path, paint);
- break;
- }
- case 33: {
- sk_sp<SkImage> img = make_fuzz_image(fuzz);
- SkScalar left, top;
- bool usePaint;
- fuzz->next(&left, &top, &usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- canvas->drawImage(img.get(), left, top, usePaint ? &paint : nullptr);
- break;
- }
- case 34: {
- auto img = make_fuzz_image(fuzz);
- SkRect src, dst;
- bool usePaint;
- fuzz->next(&src, &dst, &usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr);
- break;
- }
- case 35: {
- auto img = make_fuzz_image(fuzz);
- SkIRect src;
- SkRect dst;
- bool usePaint;
- fuzz->next(&src, &dst, &usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- SkCanvas::SrcRectConstraint constraint =
- make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
- : SkCanvas::kFast_SrcRectConstraint;
- canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
- break;
- }
- case 36: {
- bool usePaint;
- auto img = make_fuzz_image(fuzz);
- SkRect dst;
- fuzz->next(&dst, &usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- canvas->drawImageRect(img, dst, usePaint ? &paint : nullptr);
- break;
- }
- case 37: {
- auto img = make_fuzz_image(fuzz);
- SkIRect center;
- SkRect dst;
- bool usePaint;
- fuzz->next(&usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- if (make_fuzz_t<bool>(fuzz)) {
- fuzz->next(&center);
- } else { // Make valid center, see SkLatticeIter::Valid().
- fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
- fuzz->nextRange(&center.fTop, 0, img->height() - 1);
- fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
- fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
- }
- fuzz->next(&dst);
- canvas->drawImageNine(img, center, dst, usePaint ? &paint : nullptr);
- break;
- }
- case 38: {
- SkBitmap bitmap = make_fuzz_bitmap(fuzz);
- SkScalar left, top;
- bool usePaint;
- fuzz->next(&left, &top, &usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- canvas->drawBitmap(bitmap, left, top, usePaint ? &paint : nullptr);
- break;
- }
- case 39: {
- SkBitmap bitmap = make_fuzz_bitmap(fuzz);
- SkRect src, dst;
- bool usePaint;
- fuzz->next(&src, &dst, &usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- SkCanvas::SrcRectConstraint constraint =
- make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
- : SkCanvas::kFast_SrcRectConstraint;
- canvas->drawBitmapRect(bitmap, src, dst, usePaint ? &paint : nullptr, constraint);
- break;
- }
- case 40: {
- SkBitmap img = make_fuzz_bitmap(fuzz);
- SkIRect src;
- SkRect dst;
- bool usePaint;
- fuzz->next(&src, &dst, &usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- SkCanvas::SrcRectConstraint constraint =
- make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
- : SkCanvas::kFast_SrcRectConstraint;
- canvas->drawBitmapRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
- break;
- }
- case 41: {
- SkBitmap img = make_fuzz_bitmap(fuzz);
- SkRect dst;
- bool usePaint;
- fuzz->next(&dst, &usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- SkCanvas::SrcRectConstraint constraint =
- make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
- : SkCanvas::kFast_SrcRectConstraint;
- canvas->drawBitmapRect(img, dst, usePaint ? &paint : nullptr, constraint);
- break;
- }
- case 42: {
- SkBitmap img = make_fuzz_bitmap(fuzz);
- SkIRect center;
- SkRect dst;
- bool usePaint;
- fuzz->next(&usePaint);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- if (make_fuzz_t<bool>(fuzz)) {
- fuzz->next(&center);
- } else { // Make valid center, see SkLatticeIter::Valid().
- if (img.width() == 0 || img.height() == 0) {
- // bitmap may not have had its pixels initialized.
- break;
- }
- fuzz->nextRange(&center.fLeft, 0, img.width() - 1);
- fuzz->nextRange(&center.fTop, 0, img.height() - 1);
- fuzz->nextRange(&center.fRight, center.fLeft + 1, img.width());
- fuzz->nextRange(&center.fBottom, center.fTop + 1, img.height());
- }
- fuzz->next(&dst);
- canvas->drawBitmapNine(img, center, dst, usePaint ? &paint : nullptr);
- break;
- }
- case 43: {
- SkBitmap img = make_fuzz_bitmap(fuzz);
- bool usePaint;
- SkRect dst;
- fuzz->next(&usePaint, &dst);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- constexpr int kMax = 6;
- int xDivs[kMax], yDivs[kMax];
- SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
- fuzz->nextRange(&lattice.fXCount, 2, kMax);
- fuzz->nextRange(&lattice.fYCount, 2, kMax);
- fuzz->nextN(xDivs, lattice.fXCount);
- fuzz->nextN(yDivs, lattice.fYCount);
- canvas->drawBitmapLattice(img, lattice, dst, usePaint ? &paint : nullptr);
- break;
- }
- case 44: {
- auto img = make_fuzz_image(fuzz);
- bool usePaint;
- SkRect dst;
- fuzz->next(&usePaint, &dst);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- constexpr int kMax = 6;
- int xDivs[kMax], yDivs[kMax];
- SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
- fuzz->nextRange(&lattice.fXCount, 2, kMax);
- fuzz->nextRange(&lattice.fYCount, 2, kMax);
- fuzz->nextN(xDivs, lattice.fXCount);
- fuzz->nextN(yDivs, lattice.fYCount);
- canvas->drawImageLattice(img.get(), lattice, dst, usePaint ? &paint : nullptr);
- break;
- }
- case 45: {
- fuzz_paint(fuzz, &paint, depth - 1);
- font = fuzz_font(fuzz);
- SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
- SkScalar x, y;
- fuzz->next(&x, &y);
- SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
- canvas->drawSimpleText(text.begin(), SkToSizeT(text.count()), encoding, x, y,
- font, paint);
- break;
- }
- case 46: {
- // was drawPosText
- break;
- }
- case 47: {
- // was drawPosTextH
- break;
- }
- case 48: {
- // was drawtextonpath
- break;
- }
- case 49: {
- // was drawtextonpath
- break;
- }
- case 50: {
- // was drawTextRSXform
- break;
- }
- case 51: {
- sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
- fuzz_paint(fuzz, &paint, depth - 1);
- SkScalar x, y;
- fuzz->next(&x, &y);
- canvas->drawTextBlob(blob, x, y, paint);
- break;
- }
- case 52: {
- SkMatrix matrix;
- bool usePaint, useMatrix;
- fuzz->next(&usePaint, &useMatrix);
- if (usePaint) {
- fuzz_paint(fuzz, &paint, depth - 1);
- }
- if (useMatrix) {
- FuzzNiceMatrix(fuzz, &matrix);
- }
- auto pic = make_fuzz_picture(fuzz, depth - 1);
- canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
- usePaint ? &paint : nullptr);
- break;
- }
- case 53: {
- fuzz_paint(fuzz, &paint, depth - 1);
- SkVertices::VertexMode vertexMode;
- SkBlendMode blendMode;
- fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
- fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
- constexpr int kMaxCount = 100;
- int vertexCount;
- SkPoint vertices[kMaxCount];
- SkPoint texs[kMaxCount];
- SkColor colors[kMaxCount];
- fuzz->nextRange(&vertexCount, 3, kMaxCount);
- fuzz->nextN(vertices, vertexCount);
- bool useTexs, useColors;
- fuzz->next(&useTexs, &useColors);
- if (useTexs) {
- fuzz->nextN(texs, vertexCount);
- }
- if (useColors) {
- fuzz->nextN(colors, vertexCount);
- }
- int indexCount = 0;
- uint16_t indices[kMaxCount * 2];
- if (make_fuzz_t<bool>(fuzz)) {
- fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
- for (int i = 0; i < indexCount; ++i) {
- fuzz->nextRange(&indices[i], 0, vertexCount - 1);
- }
- }
- canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
- useTexs ? texs : nullptr,
- useColors ? colors : nullptr,
- indexCount, indices),
- blendMode, paint);
- break;
- }
- default:
- SkASSERT(false);
- break;
- }
- }
-}
-
-static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
- SkScalar w, h;
- fuzz->next(&w, &h);
- SkPictureRecorder pictureRecorder;
- fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
- return pictureRecorder.finishRecordingAsPicture();
-}
-
-DEF_FUZZ(NullCanvas, fuzz) {
- fuzz_canvas(fuzz, SkMakeNullCanvas().get());
-}
-
-constexpr SkISize kCanvasSize = {128, 160};
-
-DEF_FUZZ(RasterN32Canvas, fuzz) {
- auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
- if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
- fuzz_canvas(fuzz, surface->getCanvas());
-}
-
-DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
- SkPictureRecorder recorder;
- fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
- SkIntToScalar(kCanvasSize.height())));
- sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
- if (!pic) { fuzz->signalBug(); }
- sk_sp<SkData> data = pic->serialize();
- if (!data) { fuzz->signalBug(); }
- SkReadBuffer rb(data->data(), data->size());
- auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
- if (!deserialized) { fuzz->signalBug(); }
- auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
- SkASSERT(surface && surface->getCanvas());
- surface->getCanvas()->drawPicture(deserialized);
-}
-
-DEF_FUZZ(ImageFilter, fuzz) {
- auto fil = make_fuzz_imageFilter(fuzz, 20);
-
- SkPaint paint;
- paint.setImageFilter(fil);
- SkBitmap bitmap;
- SkCanvas canvas(bitmap);
- canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
-}
-
-
-//SkRandom _rand;
-#define SK_ADD_RANDOM_BIT_FLIPS
-
-DEF_FUZZ(SerializedImageFilter, fuzz) {
- auto filter = make_fuzz_imageFilter(fuzz, 20);
- if (!filter) {
- return;
- }
- auto data = filter->serialize();
- const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
- size_t len = data->size();
-#ifdef SK_ADD_RANDOM_BIT_FLIPS
- unsigned char* p = const_cast<unsigned char*>(ptr);
- for (size_t i = 0; i < len; ++i, ++p) {
- uint8_t j;
- fuzz->nextRange(&j, 1, 250);
- if (j == 1) { // 0.4% of the time, flip a bit or byte
- uint8_t k;
- fuzz->nextRange(&k, 1, 10);
- if (k == 1) { // Then 10% of the time, change a whole byte
- uint8_t s;
- fuzz->nextRange(&s, 0, 2);
- switch(s) {
- case 0:
- *p ^= 0xFF; // Flip entire byte
- break;
- case 1:
- *p = 0xFF; // Set all bits to 1
- break;
- case 2:
- *p = 0x00; // Set all bits to 0
- break;
- }
- } else {
- uint8_t s;
- fuzz->nextRange(&s, 0, 7);
- *p ^= (1 << 7);
- }
- }
- }
-#endif // SK_ADD_RANDOM_BIT_FLIPS
- auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
-
- // uncomment below to write out a serialized image filter (to make corpus
- // for -t filter_fuzz)
- // SkString s("./serialized_filters/sf");
- // s.appendU32(_rand.nextU());
- // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
- // sk_fwrite(data->bytes(), data->size(), file);
- // sk_fclose(file);
-
- SkPaint paint;
- paint.setImageFilter(deserializedFil);
- SkBitmap bitmap;
- SkCanvas canvas(bitmap);
- canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
-}
-
-#if SK_SUPPORT_GPU
-
-static void dump_GPU_info(GrContext* context) {
- const GrGLInterface* gl = static_cast<GrGLGpu*>(context->contextPriv().getGpu())
- ->glInterface();
- const GrGLubyte* output;
- GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
- SkDebugf("GL_RENDERER %s\n", (const char*) output);
-
- GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
- SkDebugf("GL_VENDOR %s\n", (const char*) output);
-
- GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
- SkDebugf("GL_VERSION %s\n", (const char*) output);
-}
-
-static void fuzz_ganesh(Fuzz* fuzz, GrContext* context) {
- SkASSERT(context);
- auto surface = SkSurface::MakeRenderTarget(
- context,
- SkBudgeted::kNo,
- SkImageInfo::Make(kCanvasSize.width(), kCanvasSize.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType));
- SkASSERT(surface && surface->getCanvas());
- fuzz_canvas(fuzz, surface->getCanvas());
-}
-
-DEF_FUZZ(NativeGLCanvas, fuzz) {
- sk_gpu_test::GrContextFactory f;
- GrContext* context = f.get(sk_gpu_test::GrContextFactory::kGL_ContextType);
- if (!context) {
- context = f.get(sk_gpu_test::GrContextFactory::kGLES_ContextType);
- }
- if (FLAGS_gpuInfo) {
- dump_GPU_info(context);
- }
- fuzz_ganesh(fuzz, context);
-}
-
-// This target is deprecated, NullGLContext is not well maintained.
-// Please use MockGPUCanvas instead.
-DEF_FUZZ(NullGLCanvas, fuzz) {
- sk_gpu_test::GrContextFactory f;
- fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kNullGL_ContextType));
-}
-
-DEF_FUZZ(MockGPUCanvas, fuzz) {
- sk_gpu_test::GrContextFactory f;
- fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kMock_ContextType));
-}
-#endif
-
-DEF_FUZZ(PDFCanvas, fuzz) {
- SkNullWStream stream;
- auto doc = SkPDF::MakeDocument(&stream);
- fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
- SkIntToScalar(kCanvasSize.height())));
-}
-
-// not a "real" thing to fuzz, used to debug errors found while fuzzing.
-DEF_FUZZ(_DumpCanvas, fuzz) {
- SkDebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
- fuzz_canvas(fuzz, &debugCanvas);
- std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
- UrlDataManager dataManager(SkString("data"));
- Json::Value json = debugCanvas.toJSON(dataManager, debugCanvas.getSize(), nullCanvas.get());
- Json::StyledStreamWriter(" ").write(std::cout, json);
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzCommon.cpp b/chromium/third_party/skia/fuzz/FuzzCommon.cpp
deleted file mode 100644
index 79ffdee5635..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzCommon.cpp
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "FuzzCommon.h"
-
-// We don't always want to test NaNs and infinities.
-static void fuzz_nice_float(Fuzz* fuzz, float* f) {
- float v;
- fuzz->next(&v);
- constexpr float kLimit = 1.0e35f; // FLT_MAX?
- *f = (v == v && v <= kLimit && v >= -kLimit) ? v : 0.0f;
-}
-
-template <typename... Args>
-static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
- fuzz_nice_float(fuzz, f);
- fuzz_nice_float(fuzz, rest...);
-}
-
-static void fuzz_nice_rect(Fuzz* fuzz, SkRect* r) {
- fuzz_nice_float(fuzz, &r->fLeft, &r->fTop, &r->fRight, &r->fBottom);
- r->sort();
-}
-
-// allows some float values for path points
-void FuzzNicePath(Fuzz* fuzz, SkPath* path, int maxOps) {
- if (maxOps <= 0 || fuzz->exhausted() || path->countPoints() > 100000) {
- return;
- }
- uint8_t fillType;
- fuzz->nextRange(&fillType, 0, (uint8_t)SkPath::kInverseEvenOdd_FillType);
- path->setFillType((SkPath::FillType)fillType);
- uint8_t numOps;
- fuzz->nextRange(&numOps, 0, maxOps);
- for (uint8_t i = 0; i < numOps; ++i) {
- // When we start adding the path to itself, the fuzzer can make an
- // exponentially long path, which causes timeouts.
- if (path->countPoints() > 100000) {
- return;
- }
- // How many items in the switch statement below.
- constexpr uint8_t PATH_OPERATIONS = 32;
- uint8_t op;
- fuzz->nextRange(&op, 0, PATH_OPERATIONS);
- bool test;
- SkPath p;
- SkMatrix m;
- SkRRect rr;
- SkRect r;
- SkPath::Direction dir;
- unsigned int ui;
- SkScalar a, b, c, d, e, f;
- switch (op) {
- case 0:
- fuzz_nice_float(fuzz, &a, &b);
- path->moveTo(a, b);
- break;
- case 1:
- fuzz_nice_float(fuzz, &a, &b);
- path->rMoveTo(a, b);
- break;
- case 2:
- fuzz_nice_float(fuzz, &a, &b);
- path->lineTo(a, b);
- break;
- case 3:
- fuzz_nice_float(fuzz, &a, &b);
- path->rLineTo(a, b);
- break;
- case 4:
- fuzz_nice_float(fuzz, &a, &b, &c, &d);
- path->quadTo(a, b, c, d);
- break;
- case 5:
- fuzz_nice_float(fuzz, &a, &b, &c, &d);
- path->rQuadTo(a, b, c, d);
- break;
- case 6:
- fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
- path->conicTo(a, b, c, d, e);
- break;
- case 7:
- fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
- path->rConicTo(a, b, c, d, e);
- break;
- case 8:
- fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
- path->cubicTo(a, b, c, d, e, f);
- break;
- case 9:
- fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
- path->rCubicTo(a, b, c, d, e, f);
- break;
- case 10:
- fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
- path->arcTo(a, b, c, d, e);
- break;
- case 11:
- fuzz_nice_float(fuzz, &a, &b);
- fuzz_nice_rect(fuzz, &r);
- fuzz->next(&test);
- path->arcTo(r, a, b, test);
- break;
- case 12:
- path->close();
- break;
- case 13:
- fuzz_nice_rect(fuzz, &r);
- fuzz->nextRange(&ui, 0, 1);
- dir = static_cast<SkPath::Direction>(ui);
- path->addRect(r, dir);
- break;
- case 14:
- fuzz->nextRange(&ui, 0, 1);
- dir = static_cast<SkPath::Direction>(ui);
- fuzz_nice_rect(fuzz, &r);
- fuzz->next(&ui);
- path->addRect(r, dir, ui);
- break;
- case 15:
- fuzz->nextRange(&ui, 0, 1);
- dir = static_cast<SkPath::Direction>(ui);
- fuzz_nice_rect(fuzz, &r);
- path->addOval(r, dir);
- break;
- case 16:
- fuzz->nextRange(&ui, 0, 1);
- dir = static_cast<SkPath::Direction>(ui);
- fuzz_nice_rect(fuzz, &r);
- fuzz->next(&ui);
- path->addOval(r, dir, ui);
- break;
- case 17:
- fuzz->nextRange(&ui, 0, 1);
- dir = static_cast<SkPath::Direction>(ui);
- fuzz_nice_float(fuzz, &a, &b, &c);
- path->addCircle(a, b, c, dir);
- break;
- case 18:
- fuzz_nice_rect(fuzz, &r);
- fuzz_nice_float(fuzz, &a, &b);
- path->addArc(r, a, b);
- break;
- case 19:
- fuzz_nice_float(fuzz, &a, &b);
- fuzz_nice_rect(fuzz, &r);
- fuzz->nextRange(&ui, 0, 1);
- dir = static_cast<SkPath::Direction>(ui);
- path->addRoundRect(r, a, b, dir);
- break;
- case 20:
- FuzzNiceRRect(fuzz, &rr);
- fuzz->nextRange(&ui, 0, 1);
- dir = static_cast<SkPath::Direction>(ui);
- path->addRRect(rr, dir);
- break;
- case 21:
- fuzz->nextRange(&ui, 0, 1);
- dir = static_cast<SkPath::Direction>(ui);
- FuzzNiceRRect(fuzz, &rr);
- path->addRRect(rr, dir, ui);
- break;
- case 22: {
- fuzz->nextRange(&ui, 0, 1);
- SkPath::AddPathMode mode = static_cast<SkPath::AddPathMode>(ui);
- FuzzNiceMatrix(fuzz, &m);
- FuzzNicePath(fuzz, &p, maxOps-1);
- path->addPath(p, m, mode);
- break;
- }
- case 23: {
- fuzz->nextRange(&ui, 0, 1);
- SkPath::AddPathMode mode = static_cast<SkPath::AddPathMode>(ui);
- FuzzNiceMatrix(fuzz, &m);
- path->addPath(*path, m, mode);
- break;
- }
- case 24:
- FuzzNicePath(fuzz, &p, maxOps-1);
- path->reverseAddPath(p);
- break;
- case 25:
- path->addPath(*path);
- break;
- case 26:
- path->reverseAddPath(*path);
- break;
- case 27:
- fuzz_nice_float(fuzz, &a, &b);
- path->offset(a, b, path);
- break;
- case 28:
- FuzzNicePath(fuzz, &p, maxOps-1);
- fuzz_nice_float(fuzz, &a, &b);
- p.offset(a, b, path);
- break;
- case 29:
- FuzzNiceMatrix(fuzz, &m);
- path->transform(m, path);
- break;
- case 30:
- FuzzNicePath(fuzz, &p, maxOps-1);
- FuzzNiceMatrix(fuzz, &m);
- p.transform(m, path);
- break;
- case 31:
- fuzz_nice_float(fuzz, &a, &b);
- path->setLastPt(a, b);
- break;
- case PATH_OPERATIONS:
- path->shrinkToFit();
- break;
-
- default:
- SkASSERT(false);
- break;
- }
- SkASSERTF( path->isValid(), "path->isValid() failed at op %d, case %d", i, op);
- }
-}
-
-// allows all float values for path points
-void FuzzEvilPath(Fuzz* fuzz, SkPath* path, int last_verb) {
- while (!fuzz->exhausted()) {
- // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
- // smaller, which leads to more efficient fuzzing.
- uint8_t operation;
- fuzz->next(&operation);
- SkScalar a,b,c,d,e,f;
-
- switch (operation % (last_verb + 1)) {
- case SkPath::Verb::kMove_Verb:
- fuzz->next(&a, &b);
- path->moveTo(a, b);
- break;
-
- case SkPath::Verb::kLine_Verb:
- fuzz->next(&a, &b);
- path->lineTo(a, b);
- break;
-
- case SkPath::Verb::kQuad_Verb:
- fuzz->next(&a, &b, &c, &d);
- path->quadTo(a, b, c, d);
- break;
-
- case SkPath::Verb::kConic_Verb:
- fuzz->next(&a, &b, &c, &d, &e);
- path->conicTo(a, b, c, d, e);
- break;
-
- case SkPath::Verb::kCubic_Verb:
- fuzz->next(&a, &b, &c, &d, &e, &f);
- path->cubicTo(a, b, c, d, e, f);
- break;
-
- case SkPath::Verb::kClose_Verb:
- path->close();
- break;
-
- case SkPath::Verb::kDone_Verb:
- // In this case, simply exit.
- return;
- }
- }
-}
-
-void FuzzNiceRRect(Fuzz* fuzz, SkRRect* rr) {
- SkRect r;
- fuzz_nice_rect(fuzz, &r);
-
- SkVector radii[4];
- for (SkVector& vec : radii) {
- fuzz->nextRange(&vec.fX, 0.0f, 1.0f);
- vec.fX *= 0.5f * r.width();
- fuzz->nextRange(&vec.fY, 0.0f, 1.0f);
- vec.fY *= 0.5f * r.height();
- }
- rr->setRectRadii(r, radii);
- SkASSERT(rr->isValid());
-}
-
-void FuzzNiceMatrix(Fuzz* fuzz, SkMatrix* m) {
- constexpr int kArrayLength = 9;
- SkScalar buffer[kArrayLength];
- int matrixType;
- fuzz->nextRange(&matrixType, 0, 4);
- switch (matrixType) {
- case 0: // identity
- *m = SkMatrix::I();
- return;
- case 1: // translate
- fuzz->nextRange(&buffer[0], -4000.0f, 4000.0f);
- fuzz->nextRange(&buffer[1], -4000.0f, 4000.0f);
- *m = SkMatrix::MakeTrans(buffer[0], buffer[1]);
- return;
- case 2: // translate + scale
- fuzz->nextRange(&buffer[0], -400.0f, 400.0f);
- fuzz->nextRange(&buffer[1], -400.0f, 400.0f);
- fuzz->nextRange(&buffer[2], -4000.0f, 4000.0f);
- fuzz->nextRange(&buffer[3], -4000.0f, 4000.0f);
- *m = SkMatrix::MakeScale(buffer[0], buffer[1]);
- m->postTranslate(buffer[2], buffer[3]);
- return;
- case 3: // affine
- fuzz->nextN(buffer, 6);
- m->setAffine(buffer);
- return;
- case 4: // perspective
- fuzz->nextN(buffer, kArrayLength);
- m->set9(buffer);
- return;
- default:
- SkASSERT(false);
- return;
- }
-}
-
-void FuzzNiceRegion(Fuzz* fuzz, SkRegion* region, int maxN) {
- uint8_t N;
- fuzz->nextRange(&N, 0, maxN);
- for (uint8_t i = 0; i < N; ++i) {
- SkIRect r;
- SkRegion::Op op;
- // Avoid the sentinal value used by Region.
- fuzz->nextRange(&r.fLeft, -2147483646, 2147483646);
- fuzz->nextRange(&r.fTop, -2147483646, 2147483646);
- fuzz->nextRange(&r.fRight, -2147483646, 2147483646);
- fuzz->nextRange(&r.fBottom, -2147483646, 2147483646);
- r.sort();
- fuzz->nextRange(&op, 0, SkRegion::kLastOp);
- if (!region->op(r, op)) {
- return;
- }
- }
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzCommon.h b/chromium/third_party/skia/fuzz/FuzzCommon.h
deleted file mode 100644
index c8190231a9e..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzCommon.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef FuzzCommon_DEFINED
-#define FuzzCommon_DEFINED
-
-#include "Fuzz.h"
-#include "SkMatrix.h"
-#include "SkPath.h"
-#include "SkRRect.h"
-#include "SkRegion.h"
-
-// allows some float values for path points
-void FuzzNicePath(Fuzz* fuzz, SkPath* path, int maxOps);
-// allows all float values for path points
-void FuzzEvilPath(Fuzz* fuzz, SkPath* path, int last_verb);
-
-void FuzzNiceRRect(Fuzz* fuzz, SkRRect* rr);
-
-void FuzzNiceMatrix(Fuzz* fuzz, SkMatrix* m);
-
-void FuzzNiceRegion(Fuzz* fuzz, SkRegion* region, int maxN);
-
-#endif
-
diff --git a/chromium/third_party/skia/fuzz/FuzzDrawFunctions.cpp b/chromium/third_party/skia/fuzz/FuzzDrawFunctions.cpp
deleted file mode 100644
index 083c45ac0e1..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzDrawFunctions.cpp
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright 2016 Mozilla Foundation
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkFont.h"
-#include "SkImage.h"
-#include "SkPath.h"
-#include "SkSurface.h"
-#include "SkTextBlob.h"
-#include "SkTypeface.h"
-#include "SkClipOpPriv.h"
-
-static const int kBmpSize = 24;
-static const int kMaxX = 250;
-static const int kMaxY = 250;
-static const int kPtsLen = 10;
-static const int kTxtLen = 5;
-
-static void init_string(Fuzz* fuzz, char* str, size_t bufSize) {
- for (size_t i = 0; i < bufSize-1; ++i) {
- fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII
- }
- str[bufSize-1] = '\0';
-}
-
-// make_paint mostly borrowed from FilterFuzz.cpp
-static void init_paint(Fuzz* fuzz, SkPaint* p) {
- bool b;
- fuzz->next(&b);
- p->setAntiAlias(b);
-
- uint8_t tmp_u8;
- fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode);
- p->setBlendMode(static_cast<SkBlendMode>(tmp_u8));
-
- SkColor co;
- fuzz->next(&co);
- p->setColor(co);
-
- fuzz->next(&b);
- p->setDither(b);
-
- fuzz->nextRange(&tmp_u8, 0, (int)kHigh_SkFilterQuality);
- p->setFilterQuality(static_cast<SkFilterQuality>(tmp_u8));
-
- fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Cap);
- p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8));
-
- fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join);
- p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8));
-
- SkScalar sc;
- fuzz->next(&sc);
- p->setStrokeMiter(sc);
-
- fuzz->next(&sc);
- p->setStrokeWidth(sc);
-
- fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style);
- p->setStyle(static_cast<SkPaint::Style>(tmp_u8));
-}
-
-static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
- uint8_t colorType;
- fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
- // ColorType needs to match what the system configuration is.
- if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
- colorType = kN32_SkColorType;
- }
- bool b;
- fuzz->next(&b);
- SkImageInfo info = SkImageInfo::Make(kBmpSize,
- kBmpSize,
- (SkColorType)colorType,
- b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
- if (!bmp->tryAllocPixels(info)) {
- SkDEBUGF("Bitmap not allocated\n");
- }
- SkColor c;
- fuzz->next(&c);
- bmp->eraseColor(c);
-
- fuzz->next(&b);
- SkPaint p;
- if (b) {
- init_paint(fuzz, &p);
- }
- else {
- fuzz->next(&c);
- p.setColor(c);
- }
-}
-
-static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
- uint8_t x, y;
- fuzz->nextRange(&x, 1, kMaxX);
- fuzz->nextRange(&y, 1, kMaxY);
- *s = SkSurface::MakeRasterN32Premul(x, y);
-
- if (!*s) {
- // Was possibly too big for the memory constrained fuzzing environments
- *s = SkSurface::MakeNull(x, y);
- }
-}
-
-
-static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> typeface) {
- SkFont font(typeface);
- SkPaint p;
- init_paint(fuzz, &p);
- sk_sp<SkSurface> surface;
- init_surface(fuzz, &surface);
-
- char text[kTxtLen];
- init_string(fuzz, text, kTxtLen);
-
- SkScalar x, y;
- fuzz->next(&x, &y);
- // populate pts array
- SkPoint pts[kPtsLen];
- for (uint8_t i = 0; i < kPtsLen; ++i) {
- pts[i].set(x, y);
- x += font.getSize();
- }
-
- bool b;
- fuzz->next(&b);
- font.setForceAutoHinting(b);
- fuzz->next(&b);
- font.setEmbeddedBitmaps(b);
- fuzz->next(&b);
- font.setEmbolden(b);
- fuzz->next(&b);
- font.setEdging(b ? SkFont::Edging::kAntiAlias : SkFont::Edging::kSubpixelAntiAlias);
- fuzz->next(&b);
- font.setLinearMetrics(b);
- fuzz->next(&b);
- font.setSubpixel(b);
- fuzz->next(&x);
- font.setScaleX(x);
- fuzz->next(&x);
- font.setSkewX(x);
- fuzz->next(&x);
- font.setSize(x);
-
- SkCanvas* cnv = surface->getCanvas();
- fuzz->next(&x);
- fuzz->next(&y);
- cnv->drawTextBlob(SkTextBlob::MakeFromPosText(text, kTxtLen-1, pts, font), x, y, p);
-}
-
-static void fuzz_drawCircle(Fuzz* fuzz) {
- SkPaint p;
- init_paint(fuzz, &p);
- sk_sp<SkSurface> surface;
- init_surface(fuzz, &surface);
-
- SkScalar a, b, c;
- fuzz->next(&a, &b, &c);
- surface->getCanvas()->drawCircle(a, b, c, p);
-}
-
-static void fuzz_drawLine(Fuzz* fuzz) {
- SkPaint p;
- init_paint(fuzz, &p);
- sk_sp<SkSurface> surface;
- init_surface(fuzz, &surface);
-
- SkScalar a, b, c, d;
- fuzz->next(&a, &b, &c, &d);
- surface->getCanvas()->drawLine(a, b, c, d, p);
-}
-
-static void fuzz_drawRect(Fuzz* fuzz) {
- SkPaint p;
- init_paint(fuzz, &p);
- sk_sp<SkSurface> surface;
- init_surface(fuzz, &surface);
-
- SkScalar a, b, c, d;
- fuzz->next(&a, &b, &c, &d);
- SkRect r;
- r = SkRect::MakeXYWH(a, b, c, d);
-
- SkCanvas* cnv = surface->getCanvas();
- cnv->drawRect(r, p);
-
- bool bl;
- fuzz->next(&bl);
- fuzz->next(&a, &b, &c, &d);
- r = SkRect::MakeXYWH(a, b, c, d);
- cnv->clipRect(r, kIntersect_SkClipOp, bl);
-}
-
-static void fuzz_drawPath(Fuzz* fuzz) {
- SkPaint p;
- init_paint(fuzz, &p);
- sk_sp<SkSurface> surface;
- init_surface(fuzz, &surface);
-
- // TODO(kjlubick): put the ability to fuzz a path in shared file, with
- // other common things (e.g. rects, lines)
- uint8_t i, j;
- fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
- SkPath path;
- SkScalar a, b, c, d, e, f;
- for (int k = 0; k < i; ++k) {
- fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
- switch (j) {
- case 0:
- fuzz->next(&a, &b);
- path.moveTo(a, b);
- break;
- case 1:
- fuzz->next(&a, &b);
- path.lineTo(a, b);
- break;
- case 2:
- fuzz->next(&a, &b, &c, &d);
- path.quadTo(a, b, c, d);
- break;
- case 3:
- fuzz->next(&a, &b, &c, &d, &e);
- path.conicTo(a, b, c, d, e);
- break;
- case 4:
- fuzz->next(&a, &b, &c, &d, &e, &f);
- path.cubicTo(a, b, c, d, e, f);
- break;
- case 5:
- fuzz->next(&a, &b, &c, &d, &e);
- path.arcTo(a, b, c, d, e);
- break;
- }
- }
- path.close();
-
- SkCanvas* cnv = surface->getCanvas();
- cnv->drawPath(path, p);
-
- bool bl;
- fuzz->next(&bl);
- cnv->clipPath(path, kIntersect_SkClipOp, bl);
-}
-
-static void fuzz_drawBitmap(Fuzz* fuzz) {
- SkPaint p;
- init_paint(fuzz, &p);
- sk_sp<SkSurface> surface;
- init_surface(fuzz, &surface);
- SkBitmap bmp;
- init_bitmap(fuzz, &bmp);
-
- SkScalar a, b;
- fuzz->next(&a, &b);
- surface->getCanvas()->drawBitmap(bmp, a, b, &p);
-}
-
-static void fuzz_drawImage(Fuzz* fuzz) {
- SkPaint p;
- init_paint(fuzz, &p);
- sk_sp<SkSurface> surface;
- init_surface(fuzz, &surface);
- SkBitmap bmp;
- init_bitmap(fuzz, &bmp);
-
- sk_sp<SkImage> image(SkImage::MakeFromBitmap(bmp));
-
- bool bl;
- fuzz->next(&bl);
- SkScalar a, b;
- fuzz->next(&a, &b);
- if (bl) {
- surface->getCanvas()->drawImage(image, a, b, &p);
- }
- else {
- SkRect dst = SkRect::MakeWH(a, b);
- fuzz->next(&a, &b);
- SkRect src = SkRect::MakeWH(a, b);
- uint8_t x;
- fuzz->nextRange(&x, 0, 1);
- SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
- surface->getCanvas()->drawImageRect(image, src, dst, &p, cst);
- }
-}
-
-static void fuzz_drawPaint(Fuzz* fuzz) {
- SkPaint l, p;
- init_paint(fuzz, &p);
- sk_sp<SkSurface> surface;
- init_surface(fuzz, &surface);
-
- surface->getCanvas()->drawPaint(p);
-}
-
-DEF_FUZZ(DrawFunctions, fuzz) {
- uint8_t i;
- fuzz->next(&i);
-
- switch(i) {
- case 0: {
- sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
- if (f == nullptr) {
- SkDebugf("Could not initialize font.\n");
- fuzz->signalBug();
- }
- SkDEBUGF("Fuzz DrawText\n");
- fuzz_drawText(fuzz, f);
- return;
- }
- case 1:
- SkDEBUGF("Fuzz DrawRect\n");
- fuzz_drawRect(fuzz);
- return;
- case 2:
- SkDEBUGF("Fuzz DrawCircle\n");
- fuzz_drawCircle(fuzz);
- return;
- case 3:
- SkDEBUGF("Fuzz DrawLine\n");
- fuzz_drawLine(fuzz);
- return;
- case 4:
- SkDEBUGF("Fuzz DrawPath\n");
- fuzz_drawPath(fuzz);
- return;
- case 5:
- SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
- fuzz_drawImage(fuzz);
- return;
- case 6:
- SkDEBUGF("Fuzz DrawBitmap\n");
- fuzz_drawBitmap(fuzz);
- return;
- case 7:
- SkDEBUGF("Fuzz DrawPaint\n");
- fuzz_drawPaint(fuzz);
- return;
- }
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzEncoders.cpp b/chromium/third_party/skia/fuzz/FuzzEncoders.cpp
deleted file mode 100644
index 7ca4a48d9c6..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzEncoders.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "SkBitmap.h"
-#include "SkImage.h"
-#include "SkImageInfo.h"
-#include "SkJpegEncoder.h"
-#include "SkPixmap.h"
-#include "SkPngEncoder.h"
-#include "SkRandom.h"
-#include "SkWebpEncoder.h"
-#include "SkOSFile.h"
-
-#include <vector>
-
-// These values were picked arbitrarily to hopefully limit the size of the
-// serialized SkPixmaps.
-constexpr int MAX_WIDTH = 512;
-constexpr int MAX_HEIGHT = 512;
-
-static SkBitmap make_fuzzed_bitmap(Fuzz* fuzz) {
- SkBitmap bm;
- uint32_t w, h;
- fuzz->nextRange(&w, 1, MAX_WIDTH);
- fuzz->nextRange(&h, 1, MAX_HEIGHT);
- if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(w, h))) {
- return bm;
- }
- uint32_t n = w * h;
- fuzz->nextN((SkPMColor*)bm.getPixels(), n);
- return bm;
-}
-
-DEF_FUZZ(PNGEncoder, fuzz) {
- auto bm = make_fuzzed_bitmap(fuzz);
-
- auto opts = SkPngEncoder::Options{};
- fuzz->nextRange(&opts.fZLibLevel, 0, 9);
-
- SkDynamicMemoryWStream dest;
- SkPngEncoder::Encode(&dest, bm.pixmap(), opts);
-}
-
-DEF_FUZZ(JPEGEncoder, fuzz) {
- auto bm = make_fuzzed_bitmap(fuzz);
-
- auto opts = SkJpegEncoder::Options{};
- fuzz->nextRange(&opts.fQuality, 0, 100);
-
- SkDynamicMemoryWStream dest;
- (void)SkJpegEncoder::Encode(&dest, bm.pixmap(), opts);
-}
-
-DEF_FUZZ(WEBPEncoder, fuzz) {
- auto bm = make_fuzzed_bitmap(fuzz);
-
- auto opts = SkWebpEncoder::Options{};
- fuzz->nextRange(&opts.fQuality, 0.0f, 100.0f);
- bool lossy;
- fuzz->next(&lossy);
- if (lossy) {
- opts.fCompression = SkWebpEncoder::Compression::kLossy;
- } else {
- opts.fCompression = SkWebpEncoder::Compression::kLossless;
- }
-
- SkDynamicMemoryWStream dest;
- (void)SkWebpEncoder::Encode(&dest, bm.pixmap(), opts);
-}
-
-// Not a real fuzz endpoint, but a helper to take in real, good images
-// and dump out a corpus for this fuzzer.
-DEF_FUZZ(_MakeEncoderCorpus, fuzz) {
- auto bytes = fuzz->fBytes;
- SkDebugf("bytes %d\n", bytes->size());
- auto img = SkImage::MakeFromEncoded(bytes);
- if (nullptr == img.get()) {
- SkDebugf("invalid image, could not decode\n");
- return;
- }
- if (img->width() > MAX_WIDTH || img->height() > MAX_HEIGHT) {
- SkDebugf("Too big (%d x %d)\n", img->width(), img->height());
- return;
- }
- std::vector<int32_t> dstPixels;
- int rowBytes = img->width() * 4;
- dstPixels.resize(img->height() * rowBytes);
- SkPixmap pm(SkImageInfo::MakeN32Premul(img->width(), img->height()),
- &dstPixels.front(), rowBytes);
- if (!img->readPixels(pm, 0, 0)) {
- SkDebugf("Could not read pixmap\n");
- return;
- }
-
- SkString s("./encoded_corpus/enc_");
- static SkRandom rand;
- s.appendU32(rand.nextU());
- auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
- if (!file) {
- SkDebugf("Can't initialize file\n");
- return;
- }
- auto total = pm.info().bytesPerPixel() * pm.width() * pm.height();
- SkDebugf("Writing %d (%d x %d) bytes\n", total, pm.width(), pm.height());
- // Write out the size in two bytes since that's what the fuzzer will
- // read first.
- uint32_t w = pm.width();
- sk_fwrite(&w, sizeof(uint32_t), file);
- uint32_t h = pm.height();
- sk_fwrite(&h, sizeof(uint32_t), file);
- sk_fwrite(pm.addr(), total, file);
- sk_fclose(file);
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzGradients.cpp b/chromium/third_party/skia/fuzz/FuzzGradients.cpp
deleted file mode 100644
index f9d0742382b..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzGradients.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkGradientShader.h"
-#include "SkSurface.h"
-#include "SkTLazy.h"
-
-#include <algorithm>
-#include <vector>
-
-const int MAX_COUNT = 400;
-
-void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
- SkScalar mat[9];
- fuzz->nextN(mat, 9);
- m->set9(mat);
-}
-
-void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
- std::vector<SkScalar>* pos, SkShader::TileMode* mode) {
- int count;
- fuzz->nextRange(&count, 0, MAX_COUNT);
-
- // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
- // smaller, which leads to more efficient fuzzing.
- uint8_t m;
- fuzz->nextRange(&m, 0, 2);
- *mode = static_cast<SkShader::TileMode>(m);
-
- colors->clear();
- pos ->clear();
- for (int i = 0; i < count; i++) {
- SkColor c;
- SkScalar s;
- fuzz->next(&c, &s);
- colors->push_back(c);
- pos ->push_back(s);
- }
- if (count) {
- std::sort(pos->begin(), pos->end());
- // The order matters. If count == 1, we want pos == 0.
- (*pos)[count - 1] = 1;
- (*pos)[0] = 0;
- }
-}
-
-static void logOptionalMatrix(const char* label, const SkMatrix* m) {
- if (!m) {
- return;
- }
-
- SkDEBUGF(" %s: [ ", label);
- for (int i = 0; i < 9; ++i) {
- SkDEBUGF("%.9g ", m->get(i));
- }
- SkDEBUGF("]\n");
-}
-
-static void logLinearGradient(const SkPoint pts[2],
- const std::vector<SkColor>& colors,
- const std::vector<SkScalar> pos,
- SkShader::TileMode mode,
- uint32_t flags,
- const SkMatrix* localMatrix,
- const SkMatrix* globalMatrix) {
- if (!FLAGS_verbose) {
- return;
- }
-
- SkDebugf("--- fuzzLinearGradient ---\n");
- SkDebugf(" pts:\t\t[ (%.9g %.9g) (%.9g %.9g) ]\n",
- pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y());
- SkDebugf(" colors:\t[ ");
- for (auto color : colors) {
- SkDebugf("0x%x ", color);
- }
-
- SkDebugf("]\n pos:\t\t");
- if (pos.empty()) {
- SkDebugf("nullptr");
- } else {
- SkDebugf("[ ");
- for (auto p : pos) {
- SkDebugf("%f ", p);
- }
- }
- SkDebugf("]\n");
-
- static const char* gModeName[] = {
- "kClamp_TileMode", "kRepeat_TileMode", "kMirror_TileMode"
- };
- SkASSERT(mode < SK_ARRAY_COUNT(gModeName));
- SkDebugf(" mode:\t\t%s\n", gModeName[mode]);
- SkDebugf(" flags:\t0x%x\n", flags);
- logOptionalMatrix("local matrix", localMatrix);
- logOptionalMatrix("global matrix", globalMatrix);
-}
-
-void fuzzLinearGradient(Fuzz* fuzz) {
- SkPoint pts[2];
- fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY);
- bool useLocalMatrix, useGlobalMatrix;
- fuzz->next(&useLocalMatrix, &useGlobalMatrix);
-
- std::vector<SkColor> colors;
- std::vector<SkScalar> pos;
- SkShader::TileMode mode;
- initGradientParams(fuzz, &colors, &pos, &mode);
-
- SkPaint p;
- uint32_t flags;
- fuzz->next(&flags);
-
- SkTLazy<SkMatrix> localMatrix;
- if (useLocalMatrix) {
- makeMatrix(fuzz, localMatrix.init());
- }
- p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
- colors.size(), mode, flags, localMatrix.getMaybeNull()));
-
- sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
- if (useGlobalMatrix) {
- SkMatrix gm;
- makeMatrix(fuzz, &gm);
- logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm);
- SkCanvas* c = surface->getCanvas();
- c->setMatrix(gm);
- c->drawPaint(p);
- } else {
- logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr);
- surface->getCanvas()->drawPaint(p);
- }
-}
-
-void fuzzRadialGradient(Fuzz* fuzz) {
- SkPoint center;
- fuzz->next(&center.fX, &center.fY);
- SkScalar radius;
- bool useLocalMatrix, useGlobalMatrix;
- fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
-
-
- std::vector<SkColor> colors;
- std::vector<SkScalar> pos;
- SkShader::TileMode mode;
- initGradientParams(fuzz, &colors, &pos, &mode);
-
- SkPaint p;
- uint32_t flags;
- fuzz->next(&flags);
-
- SkTLazy<SkMatrix> localMatrix;
- if (useLocalMatrix) {
- makeMatrix(fuzz, localMatrix.init());
- }
- p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
- pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
-
-
- sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
- if (useGlobalMatrix) {
- SkMatrix gm;
- makeMatrix(fuzz, &gm);
- SkCanvas* c = surface->getCanvas();
- c->setMatrix(gm);
- c->drawPaint(p);
- } else {
- surface->getCanvas()->drawPaint(p);
- }
-}
-
-void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
- SkPoint start;
- fuzz->next(&start.fX, &start.fY);
- SkPoint end;
- fuzz->next(&end.fX, &end.fY);
- SkScalar startRadius, endRadius;
- bool useLocalMatrix, useGlobalMatrix;
- fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
-
- std::vector<SkColor> colors;
- std::vector<SkScalar> pos;
- SkShader::TileMode mode;
- initGradientParams(fuzz, &colors, &pos, &mode);
-
- SkPaint p;
- uint32_t flags;
- fuzz->next(&flags);
-
- SkTLazy<SkMatrix> localMatrix;
- if (useLocalMatrix) {
- makeMatrix(fuzz, localMatrix.init());
- }
- p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
- end, endRadius, colors.data(), pos.data(), colors.size(), mode,
- flags, localMatrix.getMaybeNull()));
-
- sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
- if (useGlobalMatrix) {
- SkMatrix gm;
- makeMatrix(fuzz, &gm);
- SkCanvas* c = surface->getCanvas();
- c->setMatrix(gm);
- c->drawPaint(p);
- } else {
- surface->getCanvas()->drawPaint(p);
- }
-}
-
-void fuzzSweepGradient(Fuzz* fuzz) {
- SkScalar cx, cy;
- bool useLocalMatrix, useGlobalMatrix;
- fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
-
- std::vector<SkColor> colors;
- std::vector<SkScalar> pos;
- SkShader::TileMode mode;
- initGradientParams(fuzz, &colors, &pos, &mode);
-
- SkPaint p;
- if (useLocalMatrix) {
- SkMatrix m;
- makeMatrix(fuzz, &m);
- uint32_t flags;
- fuzz->next(&flags);
-
- p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
- pos.data(), colors.size(), flags, &m));
- } else {
- p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
- pos.data(), colors.size()));
- }
-
- sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
- if (useGlobalMatrix) {
- SkMatrix gm;
- makeMatrix(fuzz, &gm);
- SkCanvas* c = surface->getCanvas();
- c->setMatrix(gm);
- c->drawPaint(p);
- } else {
- surface->getCanvas()->drawPaint(p);
- }
-}
-
-DEF_FUZZ(Gradients, fuzz) {
- uint8_t i;
- fuzz->next(&i);
-
- switch(i) {
- case 0:
- SkDEBUGF("LinearGradient\n");
- fuzzLinearGradient(fuzz);
- return;
- case 1:
- SkDEBUGF("RadialGradient\n");
- fuzzRadialGradient(fuzz);
- return;
- case 2:
- SkDEBUGF("TwoPointConicalGradient\n");
- fuzzTwoPointConicalGradient(fuzz);
- return;
- }
- SkDEBUGF("SweepGradient\n");
- fuzzSweepGradient(fuzz);
- return;
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzMain.cpp b/chromium/third_party/skia/fuzz/FuzzMain.cpp
deleted file mode 100644
index 0ba3fc96a26..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzMain.cpp
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "SkCanvas.h"
-#include "SkCodec.h"
-#include "SkCommandLineFlags.h"
-#include "SkData.h"
-#include "SkImage.h"
-#include "SkImageEncoder.h"
-#include "SkMallocPixelRef.h"
-#include "SkOSFile.h"
-#include "SkOSPath.h"
-#include "SkPaint.h"
-#include "SkPath.h"
-#include "SkPicturePriv.h"
-#include "SkReadBuffer.h"
-#include "SkStream.h"
-#include "SkSurface.h"
-#include "SkTextBlob.h"
-
-#if SK_SUPPORT_GPU
-#include "SkSLCompiler.h"
-#endif
-
-#include "sk_tool_utils.h"
-
-#include <iostream>
-#include <map>
-#include <regex>
-#include <signal.h>
-
-DEFINE_string2(bytes, b, "", "A path to a file or a directory. If a file, the "
- "contents will be used as the fuzz bytes. If a directory, all files "
- "in the directory will be used as fuzz bytes for the fuzzer, one at a "
- "time.");
-DEFINE_string2(name, n, "", "If --type is 'api', fuzz the API with this name.");
-DEFINE_string2(dump, d, "", "If not empty, dump 'image*' or 'skp' types as a "
- "PNG with this name.");
-DEFINE_bool2(verbose, v, false, "Print more information while fuzzing.");
-
-// This cannot be inlined in DEFINE_string2 due to interleaved ifdefs
-static constexpr char g_type_message[] = "How to interpret --bytes, one of:\n"
- "android_codec\n"
- "animated_image_decode\n"
- "api\n"
- "color_deserialize\n"
- "filter_fuzz (equivalent to Chrome's filter_fuzz_stub)\n"
- "image_decode\n"
- "image_decode_incremental\n"
- "image_mode\n"
- "image_scale\n"
- "json\n"
- "path_deserialize\n"
- "region_deserialize\n"
- "region_set_path\n"
- "skp\n"
- "sksl2glsl\n"
-#if defined(SK_ENABLE_SKOTTIE)
- "skottie_json\n"
-#endif
- "textblob";
-
-DEFINE_string2(type, t, "", g_type_message);
-
-static int fuzz_file(SkString path, SkString type);
-static uint8_t calculate_option(SkData*);
-static SkString try_auto_detect(SkString path, SkString* name);
-
-static void fuzz_android_codec(sk_sp<SkData>);
-static void fuzz_animated_img(sk_sp<SkData>);
-static void fuzz_api(sk_sp<SkData> bytes, SkString name);
-static void fuzz_color_deserialize(sk_sp<SkData>);
-static void fuzz_filter_fuzz(sk_sp<SkData>);
-static void fuzz_image_decode(sk_sp<SkData>);
-static void fuzz_image_decode_incremental(sk_sp<SkData>);
-static void fuzz_img(sk_sp<SkData>, uint8_t, uint8_t);
-static void fuzz_json(sk_sp<SkData>);
-static void fuzz_path_deserialize(sk_sp<SkData>);
-static void fuzz_region_deserialize(sk_sp<SkData>);
-static void fuzz_region_set_path(sk_sp<SkData>);
-static void fuzz_skp(sk_sp<SkData>);
-static void fuzz_textblob_deserialize(sk_sp<SkData>);
-
-static void print_api_names();
-
-#if SK_SUPPORT_GPU
-static void fuzz_sksl2glsl(sk_sp<SkData>);
-#endif
-
-#if defined(SK_ENABLE_SKOTTIE)
-static void fuzz_skottie_json(sk_sp<SkData>);
-#endif
-
-int main(int argc, char** argv) {
- SkCommandLineFlags::SetUsage("Usage: fuzz -t <type> -b <path/to/file> [-n api-to-fuzz]\n"
- " fuzz -b <path/to/file>\n"
- "--help lists the valid types. If type is not specified,\n"
- "fuzz will make a guess based on the name of the file.\n");
- SkCommandLineFlags::Parse(argc, argv);
-
- SkString path = SkString(FLAGS_bytes.isEmpty() ? argv[0] : FLAGS_bytes[0]);
- SkString type = SkString(FLAGS_type.isEmpty() ? "" : FLAGS_type[0]);
-
- if (!sk_isdir(path.c_str())) {
- return fuzz_file(path, type);
- }
-
- SkOSFile::Iter it(path.c_str());
- for (SkString file; it.next(&file); ) {
- SkString p = SkOSPath::Join(path.c_str(), file.c_str());
- SkDebugf("Fuzzing %s\n", p.c_str());
- int rv = fuzz_file(p, type);
- if (rv != 0) {
- return rv;
- }
- }
- return 0;
-}
-
-static int fuzz_file(SkString path, SkString type) {
- sk_sp<SkData> bytes(SkData::MakeFromFileName(path.c_str()));
- if (!bytes) {
- SkDebugf("Could not read %s\n", path.c_str());
- return 1;
- }
-
- SkString name = SkString(FLAGS_name.isEmpty() ? "" : FLAGS_name[0]);
-
- if (type.isEmpty()) {
- type = try_auto_detect(path, &name);
- }
-
- if (type.isEmpty()) {
- SkDebugf("Could not autodetect type of %s\n", path.c_str());
- return 1;
- }
- if (type.equals("android_codec")) {
- fuzz_android_codec(bytes);
- return 0;
- }
- if (type.equals("animated_image_decode")) {
- fuzz_animated_img(bytes);
- return 0;
- }
- if (type.equals("api")) {
- fuzz_api(bytes, name);
- return 0;
- }
- if (type.equals("color_deserialize")) {
- fuzz_color_deserialize(bytes);
- return 0;
- }
- if (type.equals("filter_fuzz")) {
- fuzz_filter_fuzz(bytes);
- return 0;
- }
- if (type.equals("image_decode")) {
- fuzz_image_decode(bytes);
- return 0;
- }
- if (type.equals("image_decode_incremental")) {
- fuzz_image_decode_incremental(bytes);
- return 0;
- }
- if (type.equals("image_scale")) {
- uint8_t option = calculate_option(bytes.get());
- fuzz_img(bytes, option, 0);
- return 0;
- }
- if (type.equals("image_mode")) {
- uint8_t option = calculate_option(bytes.get());
- fuzz_img(bytes, 0, option);
- return 0;
- }
- if (type.equals("json")) {
- fuzz_json(bytes);
- return 0;
- }
- if (type.equals("path_deserialize")) {
- fuzz_path_deserialize(bytes);
- return 0;
- }
- if (type.equals("region_deserialize")) {
- fuzz_region_deserialize(bytes);
- return 0;
- }
- if (type.equals("region_set_path")) {
- fuzz_region_set_path(bytes);
- return 0;
- }
- if (type.equals("pipe")) {
- SkDebugf("I would prefer not to.\n");
- return 0;
- }
-#if defined(SK_ENABLE_SKOTTIE)
- if (type.equals("skottie_json")) {
- fuzz_skottie_json(bytes);
- return 0;
- }
-#endif
- if (type.equals("skp")) {
- fuzz_skp(bytes);
- return 0;
- }
- if (type.equals("textblob")) {
- fuzz_textblob_deserialize(bytes);
- return 0;
- }
-#if SK_SUPPORT_GPU
- if (type.equals("sksl2glsl")) {
- fuzz_sksl2glsl(bytes);
- return 0;
- }
-#endif
- SkDebugf("Unknown type %s\n", type.c_str());
- SkCommandLineFlags::PrintUsage();
- return 1;
-}
-
-static std::map<std::string, std::string> cf_api_map = {
- {"api_draw_functions", "DrawFunctions"},
- {"api_gradients", "Gradients"},
- {"api_image_filter", "ImageFilter"},
- {"api_mock_gpu_canvas", "MockGPUCanvas"},
- {"api_null_canvas", "NullCanvas"},
- {"api_path_measure", "PathMeasure"},
- {"api_pathop", "Pathop"},
- {"api_polyutils", "PolyUtils"},
- {"api_raster_n32_canvas", "RasterN32Canvas"},
- {"jpeg_encoder", "JPEGEncoder"},
- {"png_encoder", "PNGEncoder"},
- {"skia_pathop_fuzzer", "LegacyChromiumPathop"},
- {"webp_encoder", "WEBPEncoder"}
-};
-
-// maps clusterfuzz/oss-fuzz -> Skia's name
-static std::map<std::string, std::string> cf_map = {
- {"android_codec", "android_codec"},
- {"animated_image_decode", "animated_image_decode"},
- {"image_decode", "image_decode"},
- {"image_decode_incremental", "image_decode_incremental"},
- {"image_filter_deserialize", "filter_fuzz"},
- {"image_filter_deserialize_width", "filter_fuzz"},
- {"path_deserialize", "path_deserialize"},
- {"region_deserialize", "region_deserialize"},
- {"region_set_path", "region_set_path"},
- {"skjson", "json"},
-#if defined(SK_ENABLE_SKOTTIE)
- {"skottie_json", "skottie_json"},
-#endif
- {"textblob_deserialize", "textblob"}
-};
-
-static SkString try_auto_detect(SkString path, SkString* name) {
- std::cmatch m;
- std::regex clusterfuzz("clusterfuzz-testcase(-minimized)?-([a-z0-9_]+)-[\\d]+");
- std::regex skiafuzzer("(api-)?(\\w+)-[a-f0-9]+");
-
- if (std::regex_search(path.c_str(), m, clusterfuzz)) {
- std::string type = m.str(2);
-
- if (cf_api_map.find(type) != cf_api_map.end()) {
- *name = SkString(cf_api_map[type].c_str());
- return SkString("api");
- } else {
- if (cf_map.find(type) != cf_map.end()) {
- return SkString(cf_map[type].c_str());
- }
- }
- } else if (std::regex_search(path.c_str(), m, skiafuzzer)) {
- std::string a1 = m.str(1);
- std::string typeOrName = m.str(2);
- if (a1.length() > 0) {
- // it's an api fuzzer
- *name = SkString(typeOrName.c_str());
- return SkString("api");
- } else {
- return SkString(typeOrName.c_str());
- }
- }
-
- return SkString("");
-}
-
-void FuzzJSON(sk_sp<SkData> bytes);
-
-static void fuzz_json(sk_sp<SkData> bytes){
- FuzzJSON(bytes);
- SkDebugf("[terminated] Done parsing!\n");
-}
-
-#if defined(SK_ENABLE_SKOTTIE)
-void FuzzSkottieJSON(sk_sp<SkData> bytes);
-
-static void fuzz_skottie_json(sk_sp<SkData> bytes){
- FuzzSkottieJSON(bytes);
- SkDebugf("[terminated] Done animating!\n");
-}
-#endif
-
-// This adds up the first 1024 bytes and returns it as an 8 bit integer. This allows afl-fuzz to
-// deterministically excercise different paths, or *options* (such as different scaling sizes or
-// different image modes) without needing to introduce a parameter. This way we don't need a
-// image_scale1, image_scale2, image_scale4, etc fuzzer, we can just have a image_scale fuzzer.
-// Clients are expected to transform this number into a different range, e.g. with modulo (%).
-static uint8_t calculate_option(SkData* bytes) {
- uint8_t total = 0;
- const uint8_t* data = bytes->bytes();
- for (size_t i = 0; i < 1024 && i < bytes->size(); i++) {
- total += data[i];
- }
- return total;
-}
-
-static void print_api_names(){
- SkDebugf("When using --type api, please choose an API to fuzz with --name/-n:\n");
- for (const Fuzzable& fuzzable : sk_tools::Registry<Fuzzable>::Range()) {
- SkDebugf("\t%s\n", fuzzable.name);
- }
-}
-
-static void fuzz_api(sk_sp<SkData> bytes, SkString name) {
- for (const Fuzzable& fuzzable : sk_tools::Registry<Fuzzable>::Range()) {
- if (name.equals(fuzzable.name)) {
- SkDebugf("Fuzzing %s...\n", fuzzable.name);
- Fuzz fuzz(std::move(bytes));
- fuzzable.fn(&fuzz);
- SkDebugf("[terminated] Success!\n");
- return;
- }
- }
-
- print_api_names();
-}
-
-static void dump_png(SkBitmap bitmap) {
- if (!FLAGS_dump.isEmpty()) {
- sk_tool_utils::EncodeImageToFile(FLAGS_dump[0], bitmap, SkEncodedImageFormat::kPNG, 100);
- SkDebugf("Dumped to %s\n", FLAGS_dump[0]);
- }
-}
-
-bool FuzzAnimatedImage(sk_sp<SkData> bytes);
-
-static void fuzz_animated_img(sk_sp<SkData> bytes) {
- if (FuzzAnimatedImage(bytes)) {
- SkDebugf("[terminated] Success from decoding/drawing animated image!\n");
- return;
- }
- SkDebugf("[terminated] Could not decode or draw animated image.\n");
-}
-
-bool FuzzImageDecode(sk_sp<SkData> bytes);
-
-static void fuzz_image_decode(sk_sp<SkData> bytes) {
- if (FuzzImageDecode(bytes)) {
- SkDebugf("[terminated] Success from decoding/drawing image!\n");
- return;
- }
- SkDebugf("[terminated] Could not decode or draw image.\n");
-}
-
-bool FuzzIncrementalImageDecode(sk_sp<SkData> bytes);
-
-static void fuzz_image_decode_incremental(sk_sp<SkData> bytes) {
- if (FuzzIncrementalImageDecode(bytes)) {
- SkDebugf("[terminated] Success using incremental decode!\n");
- return;
- }
- SkDebugf("[terminated] Could not incrementally decode and image.\n");
-}
-
-bool FuzzAndroidCodec(sk_sp<SkData> bytes, uint8_t sampleSize);
-
-static void fuzz_android_codec(sk_sp<SkData> bytes) {
- Fuzz fuzz(bytes);
- uint8_t sampleSize;
- fuzz.nextRange(&sampleSize, 1, 64);
- bytes = SkData::MakeSubset(bytes.get(), 1, bytes->size() - 1);
- if (FuzzAndroidCodec(bytes, sampleSize)) {
- SkDebugf("[terminated] Success on Android Codec sampleSize=%u!\n", sampleSize);
- return;
- }
- SkDebugf("[terminated] Could not use Android Codec sampleSize=%u!\n", sampleSize);
-}
-
-// This is a "legacy" fuzzer that likely does too much. It was based off of how
-// DM reads in images. image_decode, image_decode_incremental and android_codec
-// are more targeted fuzzers that do a subset of what this one does.
-static void fuzz_img(sk_sp<SkData> bytes, uint8_t scale, uint8_t mode) {
- // We can scale 1x, 2x, 4x, 8x, 16x
- scale = scale % 5;
- float fscale = (float)pow(2.0f, scale);
- SkDebugf("Scaling factor: %f\n", fscale);
-
- // We have 5 different modes of decoding.
- mode = mode % 5;
- SkDebugf("Mode: %d\n", mode);
-
- // This is mostly copied from DMSrcSink's CodecSrc::draw method.
- SkDebugf("Decoding\n");
- std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(bytes));
- if (nullptr == codec.get()) {
- SkDebugf("[terminated] Couldn't create codec.\n");
- return;
- }
-
- SkImageInfo decodeInfo = codec->getInfo();
- SkISize size = codec->getScaledDimensions(fscale);
- decodeInfo = decodeInfo.makeWH(size.width(), size.height());
-
- SkBitmap bitmap;
- SkCodec::Options options;
- options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
-
- if (!bitmap.tryAllocPixelsFlags(decodeInfo, SkBitmap::kZeroPixels_AllocFlag)) {
- SkDebugf("[terminated] Could not allocate memory. Image might be too large (%d x %d)",
- decodeInfo.width(), decodeInfo.height());
- return;
- }
-
- switch (mode) {
- case 0: {//kCodecZeroInit_Mode, kCodec_Mode
- switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), &options)) {
- case SkCodec::kSuccess:
- SkDebugf("[terminated] Success!\n");
- break;
- case SkCodec::kIncompleteInput:
- SkDebugf("[terminated] Partial Success\n");
- break;
- case SkCodec::kErrorInInput:
- SkDebugf("[terminated] Partial Success with error\n");
- break;
- case SkCodec::kInvalidConversion:
- SkDebugf("Incompatible colortype conversion\n");
- // Crash to allow afl-fuzz to know this was a bug.
- raise(SIGSEGV);
- default:
- SkDebugf("[terminated] Couldn't getPixels.\n");
- return;
- }
- break;
- }
- case 1: {//kScanline_Mode
- if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)) {
- SkDebugf("[terminated] Could not start scanline decoder\n");
- return;
- }
-
- void* dst = bitmap.getAddr(0, 0);
- size_t rowBytes = bitmap.rowBytes();
- uint32_t height = decodeInfo.height();
- // We do not need to check the return value. On an incomplete
- // image, memory will be filled with a default value.
- codec->getScanlines(dst, height, rowBytes);
- SkDebugf("[terminated] Success!\n");
- break;
- }
- case 2: { //kStripe_Mode
- const int height = decodeInfo.height();
- // This value is chosen arbitrarily. We exercise more cases by choosing a value that
- // does not align with image blocks.
- const int stripeHeight = 37;
- const int numStripes = (height + stripeHeight - 1) / stripeHeight;
-
- // Decode odd stripes
- if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo)
- || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOrder()) {
- // This mode was designed to test the new skip scanlines API in libjpeg-turbo.
- // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is not interesting
- // to run this test for image types that do not have this scanline ordering.
- SkDebugf("[terminated] Could not start top-down scanline decoder\n");
- return;
- }
-
- for (int i = 0; i < numStripes; i += 2) {
- // Skip a stripe
- const int linesToSkip = SkTMin(stripeHeight, height - i * stripeHeight);
- codec->skipScanlines(linesToSkip);
-
- // Read a stripe
- const int startY = (i + 1) * stripeHeight;
- const int linesToRead = SkTMin(stripeHeight, height - startY);
- if (linesToRead > 0) {
- codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
- }
- }
-
- // Decode even stripes
- const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo);
- if (SkCodec::kSuccess != startResult) {
- SkDebugf("[terminated] Failed to restart scanline decoder with same parameters.\n");
- return;
- }
- for (int i = 0; i < numStripes; i += 2) {
- // Read a stripe
- const int startY = i * stripeHeight;
- const int linesToRead = SkTMin(stripeHeight, height - startY);
- codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
-
- // Skip a stripe
- const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
- if (linesToSkip > 0) {
- codec->skipScanlines(linesToSkip);
- }
- }
- SkDebugf("[terminated] Success!\n");
- break;
- }
- case 3: { //kSubset_Mode
- // Arbitrarily choose a divisor.
- int divisor = 2;
- // Total width/height of the image.
- const int W = codec->getInfo().width();
- const int H = codec->getInfo().height();
- if (divisor > W || divisor > H) {
- SkDebugf("[terminated] Cannot codec subset: divisor %d is too big "
- "with dimensions (%d x %d)\n", divisor, W, H);
- return;
- }
- // subset dimensions
- // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
- const int w = SkAlign2(W / divisor);
- const int h = SkAlign2(H / divisor);
- SkIRect subset;
- SkCodec::Options opts;
- opts.fSubset = &subset;
- SkBitmap subsetBm;
- // We will reuse pixel memory from bitmap.
- void* pixels = bitmap.getPixels();
- // Keep track of left and top (for drawing subsetBm into canvas). We could use
- // fscale * x and fscale * y, but we want integers such that the next subset will start
- // where the last one ended. So we'll add decodeInfo.width() and height().
- int left = 0;
- for (int x = 0; x < W; x += w) {
- int top = 0;
- for (int y = 0; y < H; y+= h) {
- // Do not make the subset go off the edge of the image.
- const int preScaleW = SkTMin(w, W - x);
- const int preScaleH = SkTMin(h, H - y);
- subset.setXYWH(x, y, preScaleW, preScaleH);
- // And fscale
- // FIXME: Should we have a version of getScaledDimensions that takes a subset
- // into account?
- decodeInfo = decodeInfo.makeWH(
- SkTMax(1, SkScalarRoundToInt(preScaleW * fscale)),
- SkTMax(1, SkScalarRoundToInt(preScaleH * fscale)));
- size_t rowBytes = decodeInfo.minRowBytes();
- if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes)) {
- SkDebugf("[terminated] Could not install pixels.\n");
- return;
- }
- const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes,
- &opts);
- switch (result) {
- case SkCodec::kSuccess:
- case SkCodec::kIncompleteInput:
- case SkCodec::kErrorInInput:
- SkDebugf("okay\n");
- break;
- case SkCodec::kInvalidConversion:
- if (0 == (x|y)) {
- // First subset is okay to return unimplemented.
- SkDebugf("[terminated] Incompatible colortype conversion\n");
- return;
- }
- // If the first subset succeeded, a later one should not fail.
- // fall through to failure
- case SkCodec::kUnimplemented:
- if (0 == (x|y)) {
- // First subset is okay to return unimplemented.
- SkDebugf("[terminated] subset codec not supported\n");
- return;
- }
- // If the first subset succeeded, why would a later one fail?
- // fall through to failure
- default:
- SkDebugf("[terminated] subset codec failed to decode (%d, %d, %d, %d) "
- "with dimensions (%d x %d)\t error %d\n",
- x, y, decodeInfo.width(), decodeInfo.height(),
- W, H, result);
- return;
- }
- // translate by the scaled height.
- top += decodeInfo.height();
- }
- // translate by the scaled width.
- left += decodeInfo.width();
- }
- SkDebugf("[terminated] Success!\n");
- break;
- }
- case 4: { //kAnimated_Mode
- std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
- if (frameInfos.size() == 0) {
- SkDebugf("[terminated] Not an animated image\n");
- break;
- }
-
- for (size_t i = 0; i < frameInfos.size(); i++) {
- options.fFrameIndex = i;
- auto result = codec->startIncrementalDecode(decodeInfo, bitmap.getPixels(),
- bitmap.rowBytes(), &options);
- if (SkCodec::kSuccess != result) {
- SkDebugf("[terminated] failed to start incremental decode "
- "in frame %d with error %d\n", i, result);
- return;
- }
-
- result = codec->incrementalDecode();
- if (result == SkCodec::kIncompleteInput || result == SkCodec::kErrorInInput) {
- SkDebugf("okay\n");
- // Frames beyond this one will not decode.
- break;
- }
- if (result == SkCodec::kSuccess) {
- SkDebugf("okay - decoded frame %d\n", i);
- } else {
- SkDebugf("[terminated] incremental decode failed with "
- "error %d\n", result);
- return;
- }
- }
- SkDebugf("[terminated] Success!\n");
- break;
- }
- default:
- SkDebugf("[terminated] Mode not implemented yet\n");
- }
-
- dump_png(bitmap);
-}
-
-static void fuzz_skp(sk_sp<SkData> bytes) {
- SkReadBuffer buf(bytes->data(), bytes->size());
- SkDebugf("Decoding\n");
- sk_sp<SkPicture> pic(SkPicturePriv::MakeFromBuffer(buf));
- if (!pic) {
- SkDebugf("[terminated] Couldn't decode as a picture.\n");
- return;
- }
- SkDebugf("Rendering\n");
- SkBitmap bitmap;
- if (!FLAGS_dump.isEmpty()) {
- SkIRect size = pic->cullRect().roundOut();
- bitmap.allocN32Pixels(size.width(), size.height());
- }
- SkCanvas canvas(bitmap);
- canvas.drawPicture(pic);
- SkDebugf("[terminated] Success! Decoded and rendered an SkPicture!\n");
- dump_png(bitmap);
-}
-
-static void fuzz_color_deserialize(sk_sp<SkData> bytes) {
- sk_sp<SkColorSpace> space(SkColorSpace::Deserialize(bytes->data(), bytes->size()));
- if (!space) {
- SkDebugf("[terminated] Couldn't deserialize Colorspace.\n");
- return;
- }
- SkDebugf("[terminated] Success! deserialized Colorspace.\n");
-}
-
-void FuzzPathDeserialize(SkReadBuffer& buf);
-
-static void fuzz_path_deserialize(sk_sp<SkData> bytes) {
- SkReadBuffer buf(bytes->data(), bytes->size());
- FuzzPathDeserialize(buf);
- SkDebugf("[terminated] path_deserialize didn't crash!\n");
-}
-
-bool FuzzRegionDeserialize(sk_sp<SkData> bytes);
-
-static void fuzz_region_deserialize(sk_sp<SkData> bytes) {
- if (!FuzzRegionDeserialize(bytes)) {
- SkDebugf("[terminated] Couldn't initialize SkRegion.\n");
- return;
- }
- SkDebugf("[terminated] Success! Initialized SkRegion.\n");
-}
-
-void FuzzTextBlobDeserialize(SkReadBuffer& buf);
-
-static void fuzz_textblob_deserialize(sk_sp<SkData> bytes) {
- SkReadBuffer buf(bytes->data(), bytes->size());
- FuzzTextBlobDeserialize(buf);
- SkDebugf("[terminated] textblob didn't crash!\n");
-}
-
-void FuzzRegionSetPath(Fuzz* fuzz);
-
-static void fuzz_region_set_path(sk_sp<SkData> bytes) {
- Fuzz fuzz(bytes);
- FuzzRegionSetPath(&fuzz);
- SkDebugf("[terminated] region_set_path didn't crash!\n");
-}
-
-void FuzzImageFilterDeserialize(sk_sp<SkData> bytes);
-
-static void fuzz_filter_fuzz(sk_sp<SkData> bytes) {
- FuzzImageFilterDeserialize(bytes);
- SkDebugf("[terminated] filter_fuzz didn't crash!\n");
-}
-
-#if SK_SUPPORT_GPU
-static void fuzz_sksl2glsl(sk_sp<SkData> bytes) {
- SkSL::Compiler compiler;
- SkSL::String output;
- SkSL::Program::Settings settings;
- sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default();
- settings.fCaps = caps.get();
- std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kFragment_Kind,
- SkSL::String((const char*) bytes->data()),
- settings);
- if (!program || !compiler.toGLSL(*program, &output)) {
- SkDebugf("[terminated] Couldn't compile input.\n");
- return;
- }
- SkDebugf("[terminated] Success! Compiled input.\n");
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/FuzzParsePath.cpp b/chromium/third_party/skia/fuzz/FuzzParsePath.cpp
deleted file mode 100644
index 7105f7aebd6..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzParsePath.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "SkString.h"
-#include "SkParsePath.h"
-
-#include <stdlib.h>
-
-// Most of this is taken from random_parse_path.cpp and adapted to use the Fuzz
-// instead of SKRandom
-
-static const struct Legal {
- char fSymbol;
- int fScalars;
-} gLegal[] = {
- { 'M', 2 },
- { 'H', 1 },
- { 'V', 1 },
- { 'L', 2 },
- { 'Q', 4 },
- { 'T', 2 },
- { 'C', 6 },
- { 'S', 4 },
- { 'A', 4 },
- { 'Z', 0 },
-};
-
-static bool gEasy = false; // set to true while debugging to suppress unusual whitespace
-
-// mostly do nothing, then bias towards spaces
-static const char gWhiteSpace[] = { 0, 0, 0, 0, 0, 0, 0, 0, ' ', ' ', ' ', ' ', 0x09, 0x0D, 0x0A };
-
-static void add_white(Fuzz* fuzz, SkString* atom) {
- if (gEasy) {
- atom->append(" ");
- return;
- }
- // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
- // smaller, which leads to more efficient fuzzing.
- uint8_t reps;
- fuzz->nextRange(&reps, 0, 2);
- for (uint8_t rep = 0; rep < reps; ++rep) {
- uint8_t index;
- fuzz->nextRange(&index, 0, (int) SK_ARRAY_COUNT(gWhiteSpace) - 1);
- if (gWhiteSpace[index]) {
- atom->append(&gWhiteSpace[index], 1);
- }
- }
-}
-
-static void add_some_white(Fuzz* fuzz, SkString* atom) {
- for(int i = 0; i < 10; i++) {
- add_white(fuzz, atom);
- }
-}
-
-static void add_comma(Fuzz* fuzz, SkString* atom) {
- if (gEasy) {
- atom->append(",");
- return;
- }
- add_white(fuzz, atom);
- bool b;
- fuzz->next(&b);
- if (b) {
- atom->append(",");
- }
- add_some_white(fuzz, atom);
-}
-
-SkString MakeRandomParsePathPiece(Fuzz* fuzz) {
- SkString atom;
- uint8_t index;
- fuzz->nextRange(&index, 0, (int) SK_ARRAY_COUNT(gLegal) - 1);
- const Legal& legal = gLegal[index];
- gEasy ? atom.append("\n") : add_white(fuzz, &atom);
- bool b;
- fuzz->next(&b);
- char symbol = legal.fSymbol | (b ? 0x20 : 0);
- atom.append(&symbol, 1);
- uint8_t reps;
- fuzz->nextRange(&reps, 1, 3);
- for (int rep = 0; rep < reps; ++rep) {
- for (int index = 0; index < legal.fScalars; ++index) {
- SkScalar coord;
- fuzz->nextRange(&coord, 0.0f, 100.0f);
- add_white(fuzz, &atom);
- atom.appendScalar(coord);
- if (rep < reps - 1 && index < legal.fScalars - 1) {
- add_comma(fuzz, &atom);
- } else {
- add_some_white(fuzz, &atom);
- }
- if ('A' == legal.fSymbol && 1 == index) {
- SkScalar s;
- fuzz->nextRange(&s, -720.0f, 720.0f);
- atom.appendScalar(s);
- add_comma(fuzz, &atom);
- fuzz->next(&b);
- atom.appendU32(b);
- add_comma(fuzz, &atom);
- fuzz->next(&b);
- atom.appendU32(b);
- add_comma(fuzz, &atom);
- }
- }
- }
- return atom;
-}
-
-DEF_FUZZ(ParsePath, fuzz) {
- SkPath path;
- SkString spec;
- uint8_t count;
- fuzz->nextRange(&count, 0, 40);
- for (uint8_t i = 0; i < count; ++i) {
- spec.append(MakeRandomParsePathPiece(fuzz));
- }
- SkDebugf("SkParsePath::FromSVGString(%s, &path);\n",spec.c_str());
- if (!SkParsePath::FromSVGString(spec.c_str(), &path)){
- SkDebugf("Could not decode path\n");
- }
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzPathMeasure.cpp b/chromium/third_party/skia/fuzz/FuzzPathMeasure.cpp
deleted file mode 100644
index 62e7b7434c3..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzPathMeasure.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "FuzzCommon.h"
-#include "SkPathMeasure.h"
-
-void inline ignoreResult(bool ) {}
-
-DEF_FUZZ(PathMeasure, fuzz) {
- uint8_t bits;
- fuzz->next(&bits);
- SkScalar distance[6];
- for (auto index = 0; index < 6; ++index) {
- fuzz->next(&distance[index]);
- }
- SkPath path;
- FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
- SkRect bounds = path.getBounds();
- SkScalar maxDim = SkTMax(bounds.width(), bounds.height());
- SkScalar resScale = maxDim / 1000;
- SkPathMeasure measure(path, bits & 1, resScale);
- SkPoint position;
- SkVector tangent;
- ignoreResult(measure.getPosTan(distance[0], &position, &tangent));
- SkPath dst;
- ignoreResult(measure.getSegment(distance[1], distance[2], &dst, (bits >> 1) & 1));
- ignoreResult(measure.nextContour());
- ignoreResult(measure.getPosTan(distance[3], &position, &tangent));
- ignoreResult(measure.getSegment(distance[4], distance[5], &dst, (bits >> 2) & 1));
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzPathop.cpp b/chromium/third_party/skia/fuzz/FuzzPathop.cpp
deleted file mode 100644
index bb9b88a6892..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzPathop.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "FuzzCommon.h"
-#include "SkPath.h"
-#include "SkPathOps.h"
-#include "SkRect.h"
-
-const uint8_t MAX_OPS = 20;
-
-DEF_FUZZ(Pathop, fuzz) {
-
- uint8_t choice;
- fuzz->nextRange(&choice, 0, 4);
- switch (choice) {
- case 0: {
- uint8_t ops;
- fuzz->nextRange(&ops, 0, MAX_OPS);
- SkOpBuilder builder;
- for (uint8_t i = 0; i < ops && !fuzz->exhausted(); i++) {
- SkPath path;
- FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
- SkPath::FillType ft;
- fuzz->nextRange(&ft, 0, SkPath::kInverseEvenOdd_FillType);
- path.setFillType(ft);
-
- SkPathOp op;
- fuzz->nextRange(&op, 0, SkPathOp::kReverseDifference_SkPathOp);
- builder.add(path, op);
- }
-
- SkPath result;
- builder.resolve(&result);
- break;
- }
- case 1: {
- SkPath path;
- FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
- SkPath::FillType ft;
- fuzz->nextRange(&ft, 0, SkPath::kInverseEvenOdd_FillType);
- path.setFillType(ft);
-
- SkPath result;
- bool isSame;
- fuzz->next(&isSame);
- if (isSame) {
- result = path;
- }
- Simplify(path, &result);
- break;
- }
- case 2: {
- SkPath path;
- FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
- SkPath::FillType ft;
- fuzz->nextRange(&ft, 0, SkPath::kInverseEvenOdd_FillType);
- path.setFillType(ft);
-
- SkPath path2;
- FuzzEvilPath(fuzz, &path2, SkPath::Verb::kDone_Verb);
- fuzz->nextRange(&ft, 0, SkPath::kInverseEvenOdd_FillType);
- path.setFillType(ft);
-
- SkPathOp op;
- fuzz->nextRange(&op, 0, SkPathOp::kReverseDifference_SkPathOp);
-
- SkPath result;
- uint8_t pickOutput;
- fuzz->nextRange(&pickOutput, 0, 2);
- if (pickOutput == 1) {
- result = path;
- } else if (pickOutput == 2) {
- result = path2;
- }
- Op(path, path2, op, &result);
- break;
- }
- case 3: {
- SkPath path;
- FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
- SkPath::FillType ft;
- fuzz->nextRange(&ft, 0, SkPath::kInverseEvenOdd_FillType);
- path.setFillType(ft);
-
- SkPath result;
- bool isSame;
- fuzz->next(&isSame);
- if (isSame) {
- result = path;
- }
- AsWinding(path, &result);
- break;
- }
- case 4: {
- SkPath path;
- FuzzEvilPath(fuzz, &path, SkPath::Verb::kDone_Verb);
- SkPath::FillType ft;
- fuzz->nextRange(&ft, 0, SkPath::kInverseEvenOdd_FillType);
- path.setFillType(ft);
-
- SkRect result;
- TightBounds(path, &result);
- break;
- }
- default: {
- SkASSERT(false);
- break;
- }
- }
-}
-
-
-const int kLastOp = SkPathOp::kReverseDifference_SkPathOp;
-
-void BuildPath(Fuzz* fuzz, SkPath* path) {
- while (!fuzz->exhausted()) {
- // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
- // smaller, which leads to more efficient fuzzing.
- uint8_t operation;
- fuzz->next(&operation);
- SkScalar a,b,c,d,e,f;
-
- switch (operation % (SkPath::Verb::kDone_Verb + 1)) {
- case SkPath::Verb::kMove_Verb:
- if (fuzz->remaining() < (2*sizeof(SkScalar))) {
- fuzz->deplete();
- return;
- }
- fuzz->next(&a, &b);
- path->moveTo(a, b);
- break;
-
- case SkPath::Verb::kLine_Verb:
- if (fuzz->remaining() < (2*sizeof(SkScalar))) {
- fuzz->deplete();
- return;
- }
- fuzz->next(&a, &b);
- path->lineTo(a, b);
- break;
-
- case SkPath::Verb::kQuad_Verb:
- if (fuzz->remaining() < (4*sizeof(SkScalar))) {
- fuzz->deplete();
- return;
- }
- fuzz->next(&a, &b, &c, &d);
- path->quadTo(a, b, c, d);
- break;
-
- case SkPath::Verb::kConic_Verb:
- if (fuzz->remaining() < (5*sizeof(SkScalar))) {
- fuzz->deplete();
- return;
- }
- fuzz->next(&a, &b, &c, &d, &e);
- path->conicTo(a, b, c, d, e);
- break;
-
- case SkPath::Verb::kCubic_Verb:
- if (fuzz->remaining() < (6*sizeof(SkScalar))) {
- fuzz->deplete();
- return;
- }
- fuzz->next(&a, &b, &c, &d, &e, &f);
- path->cubicTo(a, b, c, d, e, f);
- break;
-
- case SkPath::Verb::kClose_Verb:
- path->close();
- break;
-
- case SkPath::Verb::kDone_Verb:
- // In this case, simply exit.
- return;
- }
- }
-}
-
-DEF_FUZZ(LegacyChromiumPathop, fuzz) {
- // See https://cs.chromium.org/chromium/src/testing/libfuzzer/fuzzers/skia_pathop_fuzzer.cc
- SkOpBuilder builder;
- while (!fuzz->exhausted()) {
- SkPath path;
- uint8_t op;
- fuzz->next(&op);
- if (fuzz->exhausted()) {
- break;
- }
-
- BuildPath(fuzz, &path);
- builder.add(path, static_cast<SkPathOp>(op % (kLastOp + 1)));
- }
-
- SkPath result;
- builder.resolve(&result);
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzPolyUtils.cpp b/chromium/third_party/skia/fuzz/FuzzPolyUtils.cpp
deleted file mode 100644
index 50321d3a173..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzPolyUtils.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2018 Google LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "SkPolyUtils.h"
-
-void inline ignoreResult(bool ) {}
-
-DEF_FUZZ(PolyUtils, fuzz) {
- int count;
- fuzz->nextRange(&count, 0, 512);
- SkAutoSTMalloc<64, SkPoint> polygon(count);
- for (int index = 0; index < count; ++index) {
- fuzz->next(&polygon[index].fX, &polygon[index].fY);
- }
-
- ignoreResult(SkGetPolygonWinding(polygon, count));
- ignoreResult(SkIsConvexPolygon(polygon, count));
- ignoreResult(SkIsSimplePolygon(polygon, count));
-
- SkScalar inset;
- fuzz->next(&inset);
- SkTDArray<SkPoint> output;
- ignoreResult(SkInsetConvexPolygon(polygon, count, inset, &output));
-
- SkScalar offset;
- fuzz->next(&offset);
- ignoreResult(SkOffsetSimplePolygon(polygon, count, offset, &output));
-
- SkAutoSTMalloc<64, uint16_t> indexMap(count);
- for (int index = 0; index < count; ++index) {
- fuzz->next(&indexMap[index]);
- }
- SkTDArray<uint16_t> outputIndices;
- ignoreResult(SkTriangulateSimplePolygon(polygon, indexMap, count, &outputIndices));
-}
diff --git a/chromium/third_party/skia/fuzz/FuzzRegionOp.cpp b/chromium/third_party/skia/fuzz/FuzzRegionOp.cpp
deleted file mode 100644
index 8cc315729ac..00000000000
--- a/chromium/third_party/skia/fuzz/FuzzRegionOp.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Fuzz.h"
-#include "FuzzCommon.h"
-
-DEF_FUZZ(RegionOp, fuzz) { // `fuzz -t api -n RegionOp`
- SkRegion regionA, regionB, regionC;
- FuzzNiceRegion(fuzz, &regionA, 2000);
- FuzzNiceRegion(fuzz, &regionB, 2000);
- SkRegion::Op op;
- fuzz->nextRange(&op, 0, SkRegion::kLastOp);
- regionC.op(regionA, regionB, op);
-}
diff --git a/chromium/third_party/skia/fuzz/coverage b/chromium/third_party/skia/fuzz/coverage
deleted file mode 100755
index d681d9369a7..00000000000
--- a/chromium/third_party/skia/fuzz/coverage
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/sh
-# Copyright 2017 Google Inc.
-#
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if [ -z "$1" ]; then
- cat <<-EOM
- Usage:
- $0 [afl-out-loc]
-
- Run something like this:
- $0 ~/afl-out
- where afl-out is the directory containing all the output of the afl-fuzzers.
- You can typically ssh into skia-fuzzer-be-1 and skia-fuzzer-be-2 and run
- tar -czf afl-out.tar.gz /mnt/ssd0/fuzzes/afl-out/*/fuzzer0/queue
- and extract it locally to get the directories needed to assess coverage.
-
- EOM
- exit 1
-fi
-
-set -x
-set -e
-
-cd "$(dirname "$0")/.."
-
-EXECUTABLE="fuzz"
-
-DIR="$(mktemp -d "${TMPDIR:-/tmp}/skia_coverage_XXXXXXXXXX")"
-BUILD=out/coverage
-
-# Build $EXECUTABLE
-bin/sync
-bin/fetch-gn
-
-rm -rf $BUILD
-
-#TODO: make this work with Clang.
-ARGS='cc="gcc" cxx="g++" extra_cflags=["--coverage"] extra_ldflags=["--coverage"]'
-gn gen --args="$ARGS" "$BUILD"
-
-ninja -C "$BUILD" "$EXECUTABLE"
-
-GCOV="$(realpath tools/gcov_shim)"
-
-# Generate a zero-baseline so files not covered by $EXECUTABLE $@ will
-# still show up in the report. This reads the .gcno files that are
-# created at compile time.
-lcov -q --gcov-tool="$GCOV" -c -b "$BUILD" -d "$BUILD" -o "$DIR"/baseline -i
-
-# Running the binary generates the real coverage information, the .gcda files.
-QUEUES=("$1/api_parse_path/fuzzer0/queue/*" "$1/color_deserialize/fuzzer0/queue/*" "$1/skcodec_scale/fuzzer0/queue/*" "$1/skcodec_mode/fuzzer0/queue/*" "$1/api_draw_functions/fuzzer0/queue/*" "$1/api_gradient/fuzzer0/queue/*" "$1/api_image_filter/fuzzer0/queue/*" "$1/api_pathop/fuzzer0/queue/*" "$1/sksl2glsl/fuzzer0/queue/*" "$1/null_canvas/fuzzer0/queue/*" "$1/pdf_canvas/fuzzer0/queue/*" "$1/n32_canvas/fuzzer0/queue/*")
-
-ARGS=("-n ParsePath" "-t color_deserialize" "-t image_scale" "-t image_mode" "-n DrawFunctions" "-n Gradients" "-n SerializedImageFilter" "-n Pathop" "-t sksl2glsl" "-n NullCanvas" "-n PDFCanvas" "-n RasterN32Canvas")
-
-# We can't simply pass the directories to the fuzzers because some of the fuzzes will
-# crash or assert, which would kill the call to fuzz prematurely. Instead we run them
-# individually using the loops below.
-for i in `seq ${#QUEUES[@]}`
-do
- FILES=${QUEUES[i]}
- for f in $FILES
- do
- # Executing the fuzzes sequentially would take a very long time. So, we run them
- # in the background, making sure we don't go crazy and execute them too fast or
- # that they execute for a long time.
- timeout 10 $BUILD/$EXECUTABLE ${ARGS[i]} -b $f &
- sleep .005s
- done
-done
-
-sleep 10s
-
-echo "done running the fuzzes -- generating report"
-
-lcov -q --gcov-tool="$GCOV" -c -b "$BUILD" -d "$BUILD" -o "$DIR"/coverage
-
-lcov -q -a "$DIR"/baseline -a "$DIR"/coverage -o "$DIR"/merged
-
-genhtml -q "$DIR"/merged --legend -o "$DIR"/coverage_report --ignore-errors source
-
-xdg-open "$DIR"/coverage_report/index.html
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAPIImageFilter.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAPIImageFilter.cpp
deleted file mode 100644
index 1f8753d012e..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAPIImageFilter.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_ImageFilter(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_ImageFilter(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAndroidCodec.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAndroidCodec.cpp
deleted file mode 100644
index 2e6e2dd1c84..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAndroidCodec.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkAndroidCodec.h"
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkData.h"
-#include "SkSurface.h"
-
-#include "../Fuzz.h"
-
-bool FuzzAndroidCodec(sk_sp<SkData> bytes, uint8_t sampleSize) {
- auto codec = SkAndroidCodec::MakeFromData(bytes);
- if (!codec) {
- return false;
- }
-
- auto size = codec->getSampledDimensions(sampleSize);
- auto info = SkImageInfo::MakeN32Premul(size);
- SkBitmap bm;
- if (!bm.tryAllocPixels(info)) {
- // May fail in memory-constrained fuzzing environments
- return false;
- }
-
- SkAndroidCodec::AndroidOptions options;
- options.fSampleSize = sampleSize;
-
- auto result = codec->getAndroidPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &options);
- switch (result) {
- case SkCodec::kSuccess:
- case SkCodec::kIncompleteInput:
- case SkCodec::kErrorInInput:
- break;
- default:
- return false;
- }
-
- auto surface = SkSurface::MakeRasterN32Premul(size.width(), size.height());
- if (!surface) {
- // May return nullptr in memory-constrained fuzzing environments
- return false;
- }
-
- surface->getCanvas()->drawBitmap(bm, 0, 0);
- return true;
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto bytes = SkData::MakeWithoutCopy(data, size);
- Fuzz fuzz(bytes);
- uint8_t sampleSize;
- fuzz.nextRange(&sampleSize, 1, 64);
- bytes = SkData::MakeSubset(bytes.get(), 1, size - 1);
- FuzzAndroidCodec(bytes, sampleSize);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAnimatedImage.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAnimatedImage.cpp
deleted file mode 100644
index e99f7bc52ff..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzAnimatedImage.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkAndroidCodec.h"
-#include "SkAnimatedImage.h"
-#include "SkCanvas.h"
-#include "SkData.h"
-#include "SkSurface.h"
-
-bool FuzzAnimatedImage(sk_sp<SkData> bytes) {
- auto codec = SkAndroidCodec::MakeFromData(bytes);
- if (nullptr == codec) {
- return false;
- }
- auto aImg = SkAnimatedImage::Make(std::move(codec));
- if (nullptr == aImg) {
- return false;
- }
-
- auto s = SkSurface::MakeRasterN32Premul(128, 128);
- if (!s) {
- // May return nullptr in memory-constrained fuzzing environments
- return false;
- }
-
- int escape = 0;
- while (!aImg->isFinished() && escape < 100) {
- aImg->draw(s->getCanvas());
- escape++;
- aImg->decodeNextFrame();
- }
- return true;
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto bytes = SkData::MakeWithoutCopy(data, size);
- FuzzAnimatedImage(bytes);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzDrawFunctions.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzDrawFunctions.cpp
deleted file mode 100644
index ec4e766496d..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzDrawFunctions.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_DrawFunctions(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_DrawFunctions(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzGradients.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzGradients.cpp
deleted file mode 100644
index 06948021b36..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzGradients.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_Gradients(Fuzz* f);
-
-bool FLAGS_verbose = false;
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_Gradients(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzImage.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzImage.cpp
deleted file mode 100644
index 735eb9c4c28..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzImage.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkImage.h"
-#include "SkPaint.h"
-#include "SkCanvas.h"
-#include "SkData.h"
-#include "SkSurface.h"
-
-bool FuzzImageDecode(sk_sp<SkData> bytes) {
- auto img = SkImage::MakeFromEncoded(bytes);
- if (nullptr == img.get()) {
- return false;
- }
-
- auto s = SkSurface::MakeRasterN32Premul(128, 128);
- if (!s) {
- // May return nullptr in memory-constrained fuzzing environments
- return false;
- }
-
- SkPaint p;
- s->getCanvas()->drawImage(img, 0, 0, &p);
- return true;
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto bytes = SkData::MakeWithoutCopy(data, size);
- FuzzImageDecode(bytes);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzImageFilterDeserialize.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzImageFilterDeserialize.cpp
deleted file mode 100644
index 7ae7870ee84..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzImageFilterDeserialize.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkData.h"
-#include "SkFontMgrPriv.h"
-#include "SkImageFilter.h"
-#include "SkPaint.h"
-#include "SkTestFontMgr.h"
-
-void FuzzImageFilterDeserialize(sk_sp<SkData> bytes) {
- const int BitmapSize = 24;
- SkBitmap bitmap;
- bitmap.allocN32Pixels(BitmapSize, BitmapSize);
- SkCanvas canvas(bitmap);
- canvas.clear(0x00000000);
-
- auto flattenable = SkImageFilter::Deserialize(bytes->data(), bytes->size());
-
- if (flattenable != nullptr) {
- // Let's see if using the filters can cause any trouble...
- SkPaint paint;
- paint.setImageFilter(flattenable);
- canvas.save();
- canvas.clipRect(SkRect::MakeXYWH(
- 0, 0, SkIntToScalar(BitmapSize), SkIntToScalar(BitmapSize)));
-
- // This call shouldn't crash or cause ASAN to flag any memory issues
- // If nothing bad happens within this call, everything is fine
- canvas.drawBitmap(bitmap, 0, 0, &paint);
-
- canvas.restore();
- }
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- gSkFontMgr_DefaultFactory = &sk_tool_utils::MakePortableFontMgr;
- auto bytes = SkData::MakeWithoutCopy(data, size);
- FuzzImageFilterDeserialize(bytes);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzIncrementalImage.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzIncrementalImage.cpp
deleted file mode 100644
index 4086b3b683e..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzIncrementalImage.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBitmap.h"
-#include "SkCodec.h"
-#include "SkData.h"
-
-bool FuzzIncrementalImageDecode(sk_sp<SkData> bytes) {
- auto codec = SkCodec::MakeFromData(bytes);
- if (!codec) {
- return false;
- }
-
- SkBitmap bm;
- if (!bm.tryAllocPixels(codec->getInfo())) {
- // May fail in memory-constrained fuzzing environments
- return false;
- }
-
- auto result = codec->startIncrementalDecode(bm.info(), bm.getPixels(), bm.rowBytes());
- if (result != SkCodec::kSuccess) {
- return false;
- }
-
- // Deliberately uninitialized to verify that incrementalDecode initializes it when it
- // returns kIncompleteInput or kErrorInInput.
- int rowsDecoded;
- result = codec->incrementalDecode(&rowsDecoded);
- switch (result) {
- case SkCodec::kIncompleteInput:
- case SkCodec::kErrorInInput:
- if (rowsDecoded < bm.height()) {
- void* dst = SkTAddOffset<void>(bm.getPixels(), rowsDecoded * bm.rowBytes());
- sk_bzero(dst, (bm.height() - rowsDecoded) * bm.rowBytes());
- }
- return true; // decoded a partial image
- case SkCodec::kSuccess:
- return true;
- default:
- return false;
- }
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto bytes = SkData::MakeWithoutCopy(data, size);
- FuzzIncrementalImageDecode(bytes);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzJPEGEncoder.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzJPEGEncoder.cpp
deleted file mode 100644
index 3d5ce412e72..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzJPEGEncoder.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_JPEGEncoder(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_JPEGEncoder(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzJSON.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzJSON.cpp
deleted file mode 100644
index d6d3cf8d344..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzJSON.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkData.h"
-#include "SkJSON.h"
-#include "SkStream.h"
-
-void FuzzJSON(sk_sp<SkData> bytes) {
- skjson::DOM dom(static_cast<const char*>(bytes->data()), bytes->size());
- SkDynamicMemoryWStream wstream;
- dom.write(&wstream);
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto bytes = SkData::MakeWithoutCopy(data, size);
- FuzzJSON(bytes);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzMockGPUCanvas.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzMockGPUCanvas.cpp
deleted file mode 100644
index 5a6f389bee1..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzMockGPUCanvas.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-#include "SkTestFontMgr.h"
-#include "SkFontMgrPriv.h"
-
-void fuzz_MockGPUCanvas(Fuzz* f);
-
-extern "C" {
-
- // Set default LSAN options.
- const char *__lsan_default_options() {
- // Don't print the list of LSAN suppressions on every execution.
- return "print_suppressions=0";
- }
-
- int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- gSkFontMgr_DefaultFactory = &sk_tool_utils::MakePortableFontMgr;
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_MockGPUCanvas(&fuzz);
- return 0;
- }
-} // extern "C"
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzNullCanvas.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzNullCanvas.cpp
deleted file mode 100644
index 2363af8dabb..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzNullCanvas.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-#include "SkTestFontMgr.h"
-#include "SkFontMgrPriv.h"
-
-void fuzz_NullCanvas(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- gSkFontMgr_DefaultFactory = &sk_tool_utils::MakePortableFontMgr;
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_NullCanvas(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPNGEncoder.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPNGEncoder.cpp
deleted file mode 100644
index 8e104166cf7..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPNGEncoder.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_PNGEncoder(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_PNGEncoder(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathDeserialize.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathDeserialize.cpp
deleted file mode 100644
index 0584d31e5be..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathDeserialize.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkCanvas.h"
-#include "SkPaint.h"
-#include "SkPath.h"
-#include "SkReadBuffer.h"
-#include "SkSurface.h"
-
-void FuzzPathDeserialize(SkReadBuffer& buf) {
- SkPath path;
- buf.readPath(&path);
- if (!buf.isValid()) {
- return;
- }
-
- auto s = SkSurface::MakeRasterN32Premul(128, 128);
- if (!s) {
- // May return nullptr in memory-constrained fuzzing environments
- return;
- }
- s->getCanvas()->drawPath(path, SkPaint());
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- if (size < 4) {
- return 0;
- }
- uint32_t packed;
- memcpy(&packed, data, 4);
- unsigned version = packed & 0xFF;
- if (version != 4) {
- // Chrome only will produce version 4, so guide the fuzzer to
- // only focus on those branches.
- return 0;
- }
- SkReadBuffer buf(data, size);
- FuzzPathDeserialize(buf);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathMeasure.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathMeasure.cpp
deleted file mode 100644
index 27139429219..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathMeasure.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_PathMeasure(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_PathMeasure(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathop.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathop.cpp
deleted file mode 100644
index d4ddddbfe27..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPathop.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_Pathop(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_Pathop(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPolyUtils.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPolyUtils.cpp
deleted file mode 100644
index 166da7e3291..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzPolyUtils.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_PolyUtils(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_PolyUtils(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRasterN32Canvas.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRasterN32Canvas.cpp
deleted file mode 100644
index 8038cf5a985..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRasterN32Canvas.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-#include "SkTestFontMgr.h"
-#include "SkFontMgrPriv.h"
-
-void fuzz_RasterN32Canvas(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- gSkFontMgr_DefaultFactory = &sk_tool_utils::MakePortableFontMgr;
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_RasterN32Canvas(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp
deleted file mode 100644
index 15cf7863b54..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRegionDeserialize.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkCanvas.h"
-#include "SkPaint.h"
-#include "SkRegionPriv.h"
-#include "SkSurface.h"
-
-bool FuzzRegionDeserialize(sk_sp<SkData> bytes) {
- SkRegion region;
- if (!region.readFromMemory(bytes->data(), bytes->size())) {
- return false;
- }
- region.computeRegionComplexity();
- region.isComplex();
- SkRegion r2;
- if (region == r2) {
- region.contains(0,0);
- } else {
- region.contains(1,1);
- }
- auto s = SkSurface::MakeRasterN32Premul(128, 128);
- if (!s) {
- // May return nullptr in memory-constrained fuzzing environments
- return false;
- }
- s->getCanvas()->drawRegion(region, SkPaint());
- SkDEBUGCODE(SkRegionPriv::Validate(region));
- return true;
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto bytes = SkData::MakeWithoutCopy(data, size);
- FuzzRegionDeserialize(bytes);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRegionSetPath.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRegionSetPath.cpp
deleted file mode 100644
index fa61d49bd98..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzRegionSetPath.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-#include "../FuzzCommon.h"
-#include "SkData.h"
-#include "SkPath.h"
-#include "SkRegion.h"
-
-
-void FuzzRegionSetPath(Fuzz* fuzz) {
- SkPath p;
- FuzzNicePath(fuzz, &p, 1000);
- SkRegion r1;
- bool initR1;
- fuzz->next(&initR1);
- if (initR1) {
- fuzz->next(&r1);
- }
- SkRegion r2;
- fuzz->next(&r2);
-
- r1.setPath(p, r2);
-
- // Do some follow on computations to make sure region is well-formed.
- r1.computeRegionComplexity();
- r1.isComplex();
- if (r1 == r2) {
- r1.contains(0,0);
- } else {
- r1.contains(1,1);
- }
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- sk_sp<SkData> bytes(SkData::MakeWithoutCopy(data, size));
- Fuzz fuzz(bytes);
- FuzzRegionSetPath(&fuzz);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzTextBlobDeserialize.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzTextBlobDeserialize.cpp
deleted file mode 100644
index 6b82c793580..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzTextBlobDeserialize.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkCanvas.h"
-#include "SkFontMgrPriv.h"
-#include "SkPaint.h"
-#include "SkReadBuffer.h"
-#include "SkSurface.h"
-#include "SkTestFontMgr.h"
-#include "SkTextBlobPriv.h"
-
-void FuzzTextBlobDeserialize(SkReadBuffer& buf) {
- auto tb = SkTextBlobPriv::MakeFromBuffer(buf);
- if (!buf.isValid()) {
- return;
- }
-
- auto s = SkSurface::MakeRasterN32Premul(128, 128);
- if (!s) {
- // May return nullptr in memory-constrained fuzzing environments
- return;
- }
- s->getCanvas()->drawTextBlob(tb, 200, 200, SkPaint());
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- gSkFontMgr_DefaultFactory = &sk_tool_utils::MakePortableFontMgr;
- SkReadBuffer buf(data, size);
- FuzzTextBlobDeserialize(buf);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzWEBPEncoder.cpp b/chromium/third_party/skia/fuzz/oss_fuzz/FuzzWEBPEncoder.cpp
deleted file mode 100644
index f1da38d6ca9..00000000000
--- a/chromium/third_party/skia/fuzz/oss_fuzz/FuzzWEBPEncoder.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "../Fuzz.h"
-
-void fuzz_WEBPEncoder(Fuzz* f);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- auto fuzz = Fuzz(SkData::MakeWithoutCopy(data, size));
- fuzz_WEBPEncoder(&fuzz);
- return 0;
-}
diff --git a/chromium/third_party/skia/gm/typeface.cpp b/chromium/third_party/skia/gm/typeface.cpp
index 39d27fd2aa4..b90e9e77ef4 100644
--- a/chromium/third_party/skia/gm/typeface.cpp
+++ b/chromium/third_party/skia/gm/typeface.cpp
@@ -149,8 +149,7 @@ DEF_GM( return new TypefaceStylesGM(true); )
static void draw_typeface_rendering_gm(SkCanvas* canvas, sk_sp<SkTypeface> face,
char character = 'A') {
struct AliasType {
- bool antiAlias;
- bool subpixelAntitalias;
+ SkFont::Edging edging;
bool inLayer;
} constexpr aliasTypes[] {
#ifndef SK_BUILD_FOR_IOS
@@ -164,24 +163,12 @@ static void draw_typeface_rendering_gm(SkCanvas* canvas, sk_sp<SkTypeface> face,
// 0x330b19d8 <+88>: ldr r0, [r4, #0x4]
// Disable testing embedded bitmaps on iOS for now.
// See https://bug.skia.org/5530 .
- { false, false, false }, // aliased
+ { SkFont::Edging::kAlias , false },
#endif
- { true, false, false }, // anti-aliased
- { true, true , false }, // subpixel anti-aliased
- { true, false, true }, // anti-aliased in layer (flat pixel geometry)
- { true, true , true }, // subpixel anti-aliased in layer (flat pixel geometry)
- };
-
- auto compute_edging = [](AliasType at) {
- if (at.antiAlias) {
- if (at.subpixelAntitalias) {
- return SkFont::Edging::kSubpixelAntiAlias;
- } else {
- return SkFont::Edging::kAntiAlias;
- }
- } else {
- return SkFont::Edging::kAlias;
- }
+ { SkFont::Edging::kAntiAlias , false },
+ { SkFont::Edging::kSubpixelAntiAlias, false },
+ { SkFont::Edging::kAntiAlias , true },
+ { SkFont::Edging::kSubpixelAntiAlias, true },
};
// The hintgasp.ttf is designed for the following sizes to be different.
@@ -229,7 +216,7 @@ static void draw_typeface_rendering_gm(SkCanvas* canvas, sk_sp<SkTypeface> face,
font.setSubpixel(subpixel.requested);
for (const AliasType& alias : aliasTypes) {
- font.setEdging(compute_edging(alias));
+ font.setEdging(alias.edging);
SkAutoCanvasRestore acr(canvas, false);
if (alias.inLayer) {
canvas->saveLayer(nullptr, &paint);
@@ -292,7 +279,7 @@ static void draw_typeface_rendering_gm(SkCanvas* canvas, sk_sp<SkTypeface> face,
font.setEmbolden(fakeBold);
for (const AliasType& alias : aliasTypes) {
- font.setEdging(compute_edging(alias));
+ font.setEdging(alias.edging);
SkAutoCanvasRestore acr(canvas, false);
if (alias.inLayer) {
canvas->saveLayer(nullptr, &paint);
@@ -343,7 +330,7 @@ static void draw_typeface_rendering_gm(SkCanvas* canvas, sk_sp<SkTypeface> face,
y += dy;
x = 5;
- font.setEdging(compute_edging(alias));
+ font.setEdging(alias.edging);
SkAutoCanvasRestore acr(canvas, false);
if (alias.inLayer) {
canvas->saveLayer(nullptr, &paint);
diff --git a/chromium/third_party/skia/modules/skottie/fuzz/FuzzSkottieJSON.cpp b/chromium/third_party/skia/modules/skottie/fuzz/FuzzSkottieJSON.cpp
deleted file mode 100644
index 252fd8de686..00000000000
--- a/chromium/third_party/skia/modules/skottie/fuzz/FuzzSkottieJSON.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2018 Google, LLC
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkData.h"
-#include "SkFontMgrPriv.h"
-#include "SkStream.h"
-#include "SkTestFontMgr.h"
-#include "Skottie.h"
-
-void FuzzSkottieJSON(sk_sp<SkData> bytes) {
- SkMemoryStream stream(bytes);
- auto animation = skottie::Animation::Make(&stream);
- if (!animation) {
- return;
- }
- animation->seek(0.1337f); // A "nothing up my sleeve" number
-}
-
-#if defined(IS_FUZZING_WITH_LIBFUZZER)
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- gSkFontMgr_DefaultFactory = &sk_tool_utils::MakePortableFontMgr;
- auto bytes = SkData::MakeWithoutCopy(data, size);
- FuzzSkottieJSON(bytes);
- return 0;
-}
-#endif
diff --git a/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp b/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp
index 4bfc7fa72ab..2f3aa34ff34 100644
--- a/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp
+++ b/chromium/third_party/skia/src/ports/SkFontHost_mac.cpp
@@ -2230,16 +2230,17 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
SmoothBehavior smoothBehavior = smooth_behavior();
// Only two levels of hinting are supported.
- // kNo_Hinting means avoid CoreGraphics outline dilation.
- // kNormal_Hinting means CoreGraphics outline dilation is allowed.
- // If there is no lcd support, hinting (dilation) cannot be supported.
- SkFontHinting hinting = rec->getHinting();
- if (kSlight_SkFontHinting == hinting || smoothBehavior == SmoothBehavior::none) {
- hinting = kNo_SkFontHinting;
- } else if (kFull_SkFontHinting == hinting) {
- hinting = kNormal_SkFontHinting;
+ // kNo_Hinting means avoid CoreGraphics outline dilation (smoothing).
+ // kNormal_Hinting means CoreGraphics outline dilation (smoothing) is allowed.
+ if (kSlight_SkFontHinting == rec->getHinting()) {
+ rec->setHinting(kNo_SkFontHinting);
+ } else if (kFull_SkFontHinting == rec->getHinting()) {
+ rec->setHinting(kNormal_SkFontHinting);
+ }
+ // If smoothing has no effect, don't request it.
+ if (smoothBehavior == SmoothBehavior::none) {
+ rec->setHinting(kNo_SkFontHinting);
}
- rec->setHinting(hinting);
// FIXME: lcd smoothed un-hinted rasterization unsupported.
// Tracked by http://code.google.com/p/skia/issues/detail?id=915 .
@@ -2259,7 +2260,6 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
// [LCD][no-hint]: curently unable to honor, and must pick which to respect.
// Currenly side with LCD, effectively ignoring the hinting setting.
// [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output.
-
if (rec->fMaskFormat == SkMask::kLCD16_Format) {
if (smoothBehavior == SmoothBehavior::subpixel) {
//CoreGraphics creates 555 masks for smoothed text anyway.
@@ -2267,7 +2267,7 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
rec->setHinting(kNormal_SkFontHinting);
} else {
rec->fMaskFormat = SkMask::kA8_Format;
- if (smoothBehavior == SmoothBehavior::some) {
+ if (smoothBehavior != SmoothBehavior::none) {
rec->setHinting(kNormal_SkFontHinting);
}
}
@@ -2282,7 +2282,7 @@ void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const {
// Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8.
// All other masks can use regular gamma.
- if (SkMask::kA8_Format == rec->fMaskFormat && kNo_SkFontHinting == hinting) {
+ if (SkMask::kA8_Format == rec->fMaskFormat && kNo_SkFontHinting == rec->getHinting()) {
#ifndef SK_GAMMA_APPLY_TO_A8
// SRGBTODO: Is this correct? Do we want contrast boost?
rec->ignorePreBlend();
diff --git a/chromium/third_party/sqlite/amalgamation/rename_exports.h b/chromium/third_party/sqlite/amalgamation/rename_exports.h
index 22e7fb57494..904ac258ca6 100644
--- a/chromium/third_party/sqlite/amalgamation/rename_exports.h
+++ b/chromium/third_party/sqlite/amalgamation/rename_exports.h
@@ -7,390 +7,390 @@
#ifndef THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
#define THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
-#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5572-5574
-#define sqlite3_activate_see chrome_sqlite3_activate_see // Lines 5562-5564
-#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5109
-#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 4892
-#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6238
-#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8233
-#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8226-8231
-#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8235
-#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8234
-#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8232
-#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4067
-#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4068-4069
-#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4070
-#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4071
-#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4072
-#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4073
+#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5595-5597
+#define sqlite3_activate_see chrome_sqlite3_activate_see // Lines 5585-5587
+#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5132
+#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 4915
+#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6261
+#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8256
+#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8249-8254
+#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8258
+#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8257
+#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8255
+#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4090
+#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4091-4092
+#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4093
+#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4094
+#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4095
+#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4096
#define sqlite3_bind_parameter_count \
- chrome_sqlite3_bind_parameter_count // Line 4102
+ chrome_sqlite3_bind_parameter_count // Line 4125
#define sqlite3_bind_parameter_index \
- chrome_sqlite3_bind_parameter_index // Line 4148
+ chrome_sqlite3_bind_parameter_index // Line 4171
#define sqlite3_bind_parameter_name \
- chrome_sqlite3_bind_parameter_name // Line 4130
-#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4079
-#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4074
-#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4075
-#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4076-4077
-#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4078
-#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4080
-#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4081
-#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 6787
-#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 6771
-#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 6715-6723
-#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 6816
-#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 6748
-#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 6858
-#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2504
-#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2527
+ chrome_sqlite3_bind_parameter_name // Line 4153
+#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4102
+#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4097
+#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4098
+#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4099-4100
+#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4101
+#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4103
+#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4104
+#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 6810
+#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 6794
+#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 6738-6746
+#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 6839
+#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 6771
+#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 6881
+#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2526
+#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2549
#define sqlite3_cancel_auto_extension \
- chrome_sqlite3_cancel_auto_extension // Line 6250
-#define sqlite3_changes chrome_sqlite3_changes // Line 2333
-#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4158
-#define sqlite3_close chrome_sqlite3_close // Line 331
-#define sqlite3_close_v2 chrome_sqlite3_close_v2 // Line 332
+ chrome_sqlite3_cancel_auto_extension // Line 6273
+#define sqlite3_changes chrome_sqlite3_changes // Line 2355
+#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4181
+#define sqlite3_close chrome_sqlite3_close // Line 331
+#define sqlite3_close_v2 chrome_sqlite3_close_v2 // Line 332
#define sqlite3_collation_needed \
- chrome_sqlite3_collation_needed // Lines 5511-5515
+ chrome_sqlite3_collation_needed // Lines 5534-5538
#define sqlite3_collation_needed16 \
- chrome_sqlite3_collation_needed16 // Lines 5516-5520
-#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4638
-#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4645
-#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4646
-#define sqlite3_column_count chrome_sqlite3_column_count // Line 4174
+ chrome_sqlite3_collation_needed16 // Lines 5539-5543
+#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4661
+#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4668
+#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4669
+#define sqlite3_column_count chrome_sqlite3_column_count // Line 4197
#define sqlite3_column_database_name \
- chrome_sqlite3_column_database_name // Line 4252
+ chrome_sqlite3_column_database_name // Line 4275
#define sqlite3_column_database_name16 \
- chrome_sqlite3_column_database_name16 // Line 4253
-#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4289
-#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4290
-#define sqlite3_column_double chrome_sqlite3_column_double // Line 4639
-#define sqlite3_column_int chrome_sqlite3_column_int // Line 4640
-#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4641
-#define sqlite3_column_name chrome_sqlite3_column_name // Line 4203
-#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4204
+ chrome_sqlite3_column_database_name16 // Line 4276
+#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4312
+#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4313
+#define sqlite3_column_double chrome_sqlite3_column_double // Line 4662
+#define sqlite3_column_int chrome_sqlite3_column_int // Line 4663
+#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4664
+#define sqlite3_column_name chrome_sqlite3_column_name // Line 4226
+#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4227
#define sqlite3_column_origin_name \
- chrome_sqlite3_column_origin_name // Line 4256
+ chrome_sqlite3_column_origin_name // Line 4279
#define sqlite3_column_origin_name16 \
- chrome_sqlite3_column_origin_name16 // Line 4257
-#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4254
+ chrome_sqlite3_column_origin_name16 // Line 4280
+#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4277
#define sqlite3_column_table_name16 \
- chrome_sqlite3_column_table_name16 // Line 4255
-#define sqlite3_column_text chrome_sqlite3_column_text // Line 4642
-#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4643
-#define sqlite3_column_type chrome_sqlite3_column_type // Line 4647
-#define sqlite3_column_value chrome_sqlite3_column_value // Line 4644
-#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 5853
+ chrome_sqlite3_column_table_name16 // Line 4278
+#define sqlite3_column_text chrome_sqlite3_column_text // Line 4665
+#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4666
+#define sqlite3_column_type chrome_sqlite3_column_type // Line 4670
+#define sqlite3_column_value chrome_sqlite3_column_value // Line 4667
+#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 5876
#define sqlite3_compileoption_get chrome_sqlite3_compileoption_get // Line 191
-#define sqlite3_compileoption_used \
- chrome_sqlite3_compileoption_used // Line 190
-#define sqlite3_complete chrome_sqlite3_complete // Line 2442
-#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2443
-#define sqlite3_config chrome_sqlite3_config // Line 1540
-#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5136
+#define sqlite3_compileoption_used chrome_sqlite3_compileoption_used // Line 190
+#define sqlite3_complete chrome_sqlite3_complete // Line 2464
+#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2465
+#define sqlite3_config chrome_sqlite3_config // Line 1550
+#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5159
#define sqlite3_create_collation \
- chrome_sqlite3_create_collation // Lines 5461-5467
+ chrome_sqlite3_create_collation // Lines 5484-5490
#define sqlite3_create_collation16 \
- chrome_sqlite3_create_collation16 // Lines 5476-5482
+ chrome_sqlite3_create_collation16 // Lines 5499-5505
#define sqlite3_create_collation_v2 \
- chrome_sqlite3_create_collation_v2 // Lines 5468-5475
+ chrome_sqlite3_create_collation_v2 // Lines 5491-5498
#define sqlite3_create_function \
- chrome_sqlite3_create_function // Lines 4814-4823
+ chrome_sqlite3_create_function // Lines 4837-4846
#define sqlite3_create_function16 \
- chrome_sqlite3_create_function16 // Lines 4824-4833
+ chrome_sqlite3_create_function16 // Lines 4847-4856
#define sqlite3_create_function_v2 \
- chrome_sqlite3_create_function_v2 // Lines 4834-4844
-#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6518-6523
+ chrome_sqlite3_create_function_v2 // Lines 4857-4867
+#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6541-6546
#define sqlite3_create_module_v2 \
- chrome_sqlite3_create_module_v2 // Lines 6524-6530
+ chrome_sqlite3_create_module_v2 // Lines 6547-6553
#define sqlite3_create_window_function \
- chrome_sqlite3_create_window_function // Lines 4845-4856
-#define sqlite3_data_count chrome_sqlite3_data_count // Line 4395
-#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 5689
-#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 8918
-#define sqlite3_db_config chrome_sqlite3_db_config // Line 1559
-#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 5778
-#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 5761
-#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7162
-#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 5788
-#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 5976
-#define sqlite3_db_status chrome_sqlite3_db_status // Line 7583
-#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 6587
-#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9312-9319
+ chrome_sqlite3_create_window_function // Lines 4868-4879
+#define sqlite3_data_count chrome_sqlite3_data_count // Line 4418
+#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 5712
+#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 8941
+#define sqlite3_db_config chrome_sqlite3_db_config // Line 1569
+#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 5801
+#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 5784
+#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7185
+#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 5811
+#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 5999
+#define sqlite3_db_status chrome_sqlite3_db_status // Line 7606
+#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 6610
+#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9335-9342
#define sqlite3_enable_load_extension \
- chrome_sqlite3_enable_load_extension // Line 6200
+ chrome_sqlite3_enable_load_extension // Line 6223
#define sqlite3_enable_shared_cache \
- chrome_sqlite3_enable_shared_cache // Line 5946
-#define sqlite3_errcode chrome_sqlite3_errcode // Line 3468
-#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3470
-#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3471
-#define sqlite3_errstr chrome_sqlite3_errstr // Line 3472
-#define sqlite3_exec chrome_sqlite3_exec // Lines 403-409
-#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 3835
-#define sqlite3_expired chrome_sqlite3_expired // Line 4893
-#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3469
+ chrome_sqlite3_enable_shared_cache // Line 5969
+#define sqlite3_errcode chrome_sqlite3_errcode // Line 3492
+#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3494
+#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3495
+#define sqlite3_errstr chrome_sqlite3_errstr // Line 3496
+#define sqlite3_exec chrome_sqlite3_exec // Lines 403-409
+#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 3858
+#define sqlite3_expired chrome_sqlite3_expired // Line 4916
+#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3493
#define sqlite3_extended_result_codes \
- chrome_sqlite3_extended_result_codes // Line 2203
-#define sqlite3_file_control chrome_sqlite3_file_control // Line 7205
-#define sqlite3_finalize chrome_sqlite3_finalize // Line 4675
-#define sqlite3_free chrome_sqlite3_free // Line 2749
-#define sqlite3_free_table chrome_sqlite3_free_table // Line 2610
-#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 5748
-#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5195
-#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2602-2609
-#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 4895
-#define sqlite3_initialize chrome_sqlite3_initialize // Line 1504
-#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2407
-#define sqlite3_key chrome_sqlite3_key // Lines 5530-5533
-#define sqlite3_key_v2 chrome_sqlite3_key_v2 // Lines 5534-5538
-#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7313
-#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7311
-#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7312
-#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2265
-#define sqlite3_libversion chrome_sqlite3_libversion // Line 163
+ chrome_sqlite3_extended_result_codes // Line 2225
+#define sqlite3_file_control chrome_sqlite3_file_control // Line 7228
+#define sqlite3_finalize chrome_sqlite3_finalize // Line 4698
+#define sqlite3_free chrome_sqlite3_free // Line 2771
+#define sqlite3_free_table chrome_sqlite3_free_table // Line 2632
+#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 5771
+#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5218
+#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2624-2631
+#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 4918
+#define sqlite3_initialize chrome_sqlite3_initialize // Line 1514
+#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2429
+#define sqlite3_key chrome_sqlite3_key // Lines 5553-5556
+#define sqlite3_key_v2 chrome_sqlite3_key_v2 // Lines 5557-5561
+#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7336
+#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7334
+#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7335
+#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2287
+#define sqlite3_libversion chrome_sqlite3_libversion // Line 163
#define sqlite3_libversion_number chrome_sqlite3_libversion_number // Line 165
-#define sqlite3_limit chrome_sqlite3_limit // Line 3540
-#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6168-6173
-#define sqlite3_log chrome_sqlite3_log // Line 8454
-#define sqlite3_malloc chrome_sqlite3_malloc // Line 2745
-#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2746
-#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 4897-4898
-#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2776
-#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2775
-#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2652
-#define sqlite3_msize chrome_sqlite3_msize // Line 2750
-#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 7007
-#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 7009
-#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 7008
-#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7121
-#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 7011
-#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7122
-#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 7010
-#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 5804
-#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql // Line 3836
-#define sqlite3_open chrome_sqlite3_open // Lines 3357-3360
-#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3361-3364
-#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3365-3370
-#define sqlite3_os_end chrome_sqlite3_os_end // Line 1507
-#define sqlite3_os_init chrome_sqlite3_os_init // Line 1506
-#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 6606
-#define sqlite3_prepare chrome_sqlite3_prepare // Lines 3751-3757
-#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 3773-3779
-#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 3780-3786
-#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 3787-3794
-#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 3758-3764
-#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 3765-3772
-#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 9017
-#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 9018
-#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 9003-9015
-#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 9019
-#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 9016
-#define sqlite3_profile chrome_sqlite3_profile // Lines 3000-3001
-#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3128
-#define sqlite3_randomness chrome_sqlite3_randomness // Line 2799
-#define sqlite3_realloc chrome_sqlite3_realloc // Line 2747
-#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2748
-#define sqlite3_rekey chrome_sqlite3_rekey // Lines 5548-5551
-#define sqlite3_rekey_v2 chrome_sqlite3_rekey_v2 // Lines 5552-5556
-#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 5962
-#define sqlite3_reset chrome_sqlite3_reset // Line 4702
+#define sqlite3_limit chrome_sqlite3_limit // Line 3564
+#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6191-6196
+#define sqlite3_log chrome_sqlite3_log // Line 8477
+#define sqlite3_malloc chrome_sqlite3_malloc // Line 2767
+#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2768
+#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 4920-4921
+#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2798
+#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2797
+#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2674
+#define sqlite3_msize chrome_sqlite3_msize // Line 2772
+#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 7030
+#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 7032
+#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 7031
+#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7144
+#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 7034
+#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7145
+#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 7033
+#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 5827
+#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql // Line 3859
+#define sqlite3_open chrome_sqlite3_open // Lines 3379-3382
+#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3383-3386
+#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3387-3392
+#define sqlite3_os_end chrome_sqlite3_os_end // Line 1517
+#define sqlite3_os_init chrome_sqlite3_os_init // Line 1516
+#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 6629
+#define sqlite3_prepare chrome_sqlite3_prepare // Lines 3774-3780
+#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 3796-3802
+#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 3803-3809
+#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 3810-3817
+#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 3781-3787
+#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 3788-3795
+#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 9040
+#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 9041
+#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 9026-9038
+#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 9042
+#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 9039
+#define sqlite3_profile chrome_sqlite3_profile // Lines 3022-3023
+#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3150
+#define sqlite3_randomness chrome_sqlite3_randomness // Line 2821
+#define sqlite3_realloc chrome_sqlite3_realloc // Line 2769
+#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2770
+#define sqlite3_rekey chrome_sqlite3_rekey // Lines 5571-5574
+#define sqlite3_rekey_v2 chrome_sqlite3_rekey_v2 // Lines 5575-5579
+#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 5985
+#define sqlite3_reset chrome_sqlite3_reset // Line 4725
#define sqlite3_reset_auto_extension \
- chrome_sqlite3_reset_auto_extension // Line 6258
-#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5343
-#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5344-5345
-#define sqlite3_result_double chrome_sqlite3_result_double // Line 5346
-#define sqlite3_result_error chrome_sqlite3_result_error // Line 5347
-#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5348
-#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5351
+ chrome_sqlite3_reset_auto_extension // Line 6281
+#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5366
+#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5367-5368
+#define sqlite3_result_double chrome_sqlite3_result_double // Line 5369
+#define sqlite3_result_error chrome_sqlite3_result_error // Line 5370
+#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5371
+#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5374
#define sqlite3_result_error_nomem \
- chrome_sqlite3_result_error_nomem // Line 5350
+ chrome_sqlite3_result_error_nomem // Line 5373
#define sqlite3_result_error_toobig \
- chrome_sqlite3_result_error_toobig // Line 5349
-#define sqlite3_result_int chrome_sqlite3_result_int // Line 5352
-#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5353
-#define sqlite3_result_null chrome_sqlite3_result_null // Line 5354
-#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5362
-#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5379
-#define sqlite3_result_text chrome_sqlite3_result_text // Line 5355
-#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5358
-#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5360
-#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5359
-#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5356-5357
-#define sqlite3_result_value chrome_sqlite3_result_value // Line 5361
-#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5363
-#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5364
-#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 5854
+ chrome_sqlite3_result_error_toobig // Line 5372
+#define sqlite3_result_int chrome_sqlite3_result_int // Line 5375
+#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5376
+#define sqlite3_result_null chrome_sqlite3_result_null // Line 5377
+#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5385
+#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5402
+#define sqlite3_result_text chrome_sqlite3_result_text // Line 5378
+#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5381
+#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5383
+#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5382
+#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5379-5380
+#define sqlite3_result_value chrome_sqlite3_result_value // Line 5384
+#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5386
+#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5387
+#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 5877
#define sqlite3_rtree_geometry_callback \
- chrome_sqlite3_rtree_geometry_callback // Lines 9399-9404
+ chrome_sqlite3_rtree_geometry_callback // Lines 9422-9427
#define sqlite3_rtree_query_callback \
- chrome_sqlite3_rtree_query_callback // Lines 9425-9431
-#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9260-9265
-#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 2890-2894
-#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5196
+ chrome_sqlite3_rtree_query_callback // Lines 9448-9454
+#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9283-9288
+#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 2912-2916
+#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5219
#define sqlite3_set_last_insert_rowid \
- chrome_sqlite3_set_last_insert_rowid // Line 2275
-#define sqlite3_shutdown chrome_sqlite3_shutdown // Line 1505
-#define sqlite3_sleep chrome_sqlite3_sleep // Line 5594
-#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9194-9197
-#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9167
-#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9101-9105
-#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9150-9154
-#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9222
-#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2654
-#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 6040
-#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 6029
-#define sqlite3_sourceid chrome_sqlite3_sourceid // Line 164
-#define sqlite3_sql chrome_sqlite3_sql // Line 3834
-#define sqlite3_status chrome_sqlite3_status // Line 7473
-#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7474-7479
-#define sqlite3_step chrome_sqlite3_step // Line 4374
-#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 3893
-#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 3872
+ chrome_sqlite3_set_last_insert_rowid // Line 2297
+#define sqlite3_shutdown chrome_sqlite3_shutdown // Line 1515
+#define sqlite3_sleep chrome_sqlite3_sleep // Line 5617
+#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9217-9220
+#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9190
+#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9124-9128
+#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9173-9177
+#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9245
+#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2676
+#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 6063
+#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 6052
+#define sqlite3_sourceid chrome_sqlite3_sourceid // Line 164
+#define sqlite3_sql chrome_sqlite3_sql // Line 3857
+#define sqlite3_status chrome_sqlite3_status // Line 7496
+#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7497-7502
+#define sqlite3_step chrome_sqlite3_step // Line 4397
+#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 3916
+#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 3895
#define sqlite3_stmt_scanstatus \
- chrome_sqlite3_stmt_scanstatus // Lines 8870-8875
+ chrome_sqlite3_stmt_scanstatus // Lines 8893-8898
#define sqlite3_stmt_scanstatus_reset \
- chrome_sqlite3_stmt_scanstatus_reset // Line 8886
-#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 7736
-#define sqlite3_str_append chrome_sqlite3_str_append // Line 7409
-#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7410
-#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7411
-#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7407
-#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7443
-#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7373
-#define sqlite3_str_length chrome_sqlite3_str_length // Line 7444
-#define sqlite3_str_new chrome_sqlite3_str_new // Line 7358
-#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7412
-#define sqlite3_str_value chrome_sqlite3_str_value // Line 7445
-#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7408
-#define sqlite3_strglob chrome_sqlite3_strglob // Line 8385
-#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8367
-#define sqlite3_strlike chrome_sqlite3_strlike // Line 8431
-#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8368
-#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 9032
+ chrome_sqlite3_stmt_scanstatus_reset // Line 8909
+#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 7759
+#define sqlite3_str_append chrome_sqlite3_str_append // Line 7432
+#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7433
+#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7434
+#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7430
+#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7466
+#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7396
+#define sqlite3_str_length chrome_sqlite3_str_length // Line 7467
+#define sqlite3_str_new chrome_sqlite3_str_new // Line 7381
+#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7435
+#define sqlite3_str_value chrome_sqlite3_str_value // Line 7468
+#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7431
+#define sqlite3_strglob chrome_sqlite3_strglob // Line 8408
+#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8390
+#define sqlite3_strlike chrome_sqlite3_strlike // Line 8454
+#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8391
+#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 9055
#define sqlite3_table_column_metadata \
- chrome_sqlite3_table_column_metadata // Lines 6112-6122
-#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 5652
-#define sqlite3_test_control chrome_sqlite3_test_control // Line 7224
-#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 4896
-#define sqlite3_threadsafe chrome_sqlite3_threadsafe // Line 230
-#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2370
-#define sqlite3_trace chrome_sqlite3_trace // Lines 2998-2999
-#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3089-3094
-#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 4894
-#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8352-8356
-#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 5905-5909
-#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3412
-#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3413
-#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3411
-#define sqlite3_user_data chrome_sqlite3_user_data // Line 5124
-#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 5022
-#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 5031
-#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 5032
-#define sqlite3_value_double chrome_sqlite3_value_double // Line 5023
-#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5063
-#define sqlite3_value_free chrome_sqlite3_value_free // Line 5064
-#define sqlite3_value_int chrome_sqlite3_value_int // Line 5024
-#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 5025
-#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 5035
+ chrome_sqlite3_table_column_metadata // Lines 6135-6145
+#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 5675
+#define sqlite3_test_control chrome_sqlite3_test_control // Line 7247
+#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 4919
+#define sqlite3_threadsafe chrome_sqlite3_threadsafe // Line 230
+#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2392
+#define sqlite3_trace chrome_sqlite3_trace // Lines 3020-3021
+#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3111-3116
+#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 4917
+#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8375-8379
+#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 5928-5932
+#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3436
+#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3437
+#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3435
+#define sqlite3_user_data chrome_sqlite3_user_data // Line 5147
+#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 5045
+#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 5054
+#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 5055
+#define sqlite3_value_double chrome_sqlite3_value_double // Line 5046
+#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5086
+#define sqlite3_value_free chrome_sqlite3_value_free // Line 5087
+#define sqlite3_value_int chrome_sqlite3_value_int // Line 5047
+#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 5048
+#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 5058
#define sqlite3_value_numeric_type \
- chrome_sqlite3_value_numeric_type // Line 5034
-#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 5026
-#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5047
-#define sqlite3_value_text chrome_sqlite3_value_text // Line 5027
-#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 5028
-#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 5030
-#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 5029
-#define sqlite3_value_type chrome_sqlite3_value_type // Line 5033
-#define sqlite3_version chrome_sqlite3_version // Line 162
-#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 6889
-#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 6890
-#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 6891
-#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2653
-#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2655
-#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 8765
-#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 8677
-#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 8750
-#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 8731
+ chrome_sqlite3_value_numeric_type // Line 5057
+#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 5049
+#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5070
+#define sqlite3_value_text chrome_sqlite3_value_text // Line 5050
+#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 5051
+#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 5053
+#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 5052
+#define sqlite3_value_type chrome_sqlite3_value_type // Line 5056
+#define sqlite3_version chrome_sqlite3_version // Line 162
+#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 6912
+#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 6913
+#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 6914
+#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2675
+#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2677
+#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 8788
+#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 8700
+#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 8773
+#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 8754
#define sqlite3_wal_autocheckpoint \
- chrome_sqlite3_wal_autocheckpoint // Line 8525
-#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 8547
+ chrome_sqlite3_wal_autocheckpoint // Line 8548
+#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 8570
#define sqlite3_wal_checkpoint_v2 \
- chrome_sqlite3_wal_checkpoint_v2 // Lines 8641-8647
-#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8490-8494
+ chrome_sqlite3_wal_checkpoint_v2 // Lines 8664-8670
+#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8513-8517
#define sqlite3_win32_set_directory \
- chrome_sqlite3_win32_set_directory // Lines 5710-5713
+ chrome_sqlite3_win32_set_directory // Lines 5733-5736
#define sqlite3_win32_set_directory16 \
- chrome_sqlite3_win32_set_directory16 // Line 5715
+ chrome_sqlite3_win32_set_directory16 // Line 5738
#define sqlite3_win32_set_directory8 \
- chrome_sqlite3_win32_set_directory8 // Line 5714
-#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10412
+ chrome_sqlite3_win32_set_directory8 // Line 5737
+#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10435
#define sqlite3changegroup_add_strm \
- chrome_sqlite3changegroup_add_strm // Lines 11074-11077
+ chrome_sqlite3changegroup_add_strm // Lines 11097-11100
#define sqlite3changegroup_delete \
- chrome_sqlite3changegroup_delete // Line 10449
-#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10334
+ chrome_sqlite3changegroup_delete // Line 10472
+#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10357
#define sqlite3changegroup_output \
- chrome_sqlite3changegroup_output // Lines 10439-10443
+ chrome_sqlite3changegroup_output // Lines 10462-10466
#define sqlite3changegroup_output_strm \
- chrome_sqlite3changegroup_output_strm // Lines 11078-11081
+ chrome_sqlite3changegroup_output_strm // Lines 11101-11104
#define sqlite3changeset_apply \
- chrome_sqlite3changeset_apply // Lines 10609-10623
+ chrome_sqlite3changeset_apply // Lines 10632-10646
#define sqlite3changeset_apply_strm \
- chrome_sqlite3changeset_apply_strm // Lines 11007-11021
+ chrome_sqlite3changeset_apply_strm // Lines 11030-11044
#define sqlite3changeset_apply_v2 \
- chrome_sqlite3changeset_apply_v2 // Lines 10624-10640
+ chrome_sqlite3changeset_apply_v2 // Lines 10647-10663
#define sqlite3changeset_apply_v2_strm \
- chrome_sqlite3changeset_apply_v2_strm // Lines 11022-11038
+ chrome_sqlite3changeset_apply_v2_strm // Lines 11045-11061
#define sqlite3changeset_concat \
- chrome_sqlite3changeset_concat // Lines 10280-10287
+ chrome_sqlite3changeset_concat // Lines 10303-10310
#define sqlite3changeset_concat_strm \
- chrome_sqlite3changeset_concat_strm // Lines 11039-11046
+ chrome_sqlite3changeset_concat_strm // Lines 11062-11069
#define sqlite3changeset_conflict \
- chrome_sqlite3changeset_conflict // Lines 10166-10170
+ chrome_sqlite3changeset_conflict // Lines 10189-10193
#define sqlite3changeset_finalize \
- chrome_sqlite3changeset_finalize // Line 10219
+ chrome_sqlite3changeset_finalize // Line 10242
#define sqlite3changeset_fk_conflicts \
- chrome_sqlite3changeset_fk_conflicts // Lines 10183-10186
+ chrome_sqlite3changeset_fk_conflicts // Lines 10206-10209
#define sqlite3changeset_invert \
- chrome_sqlite3changeset_invert // Lines 10249-10252
+ chrome_sqlite3changeset_invert // Lines 10272-10275
#define sqlite3changeset_invert_strm \
- chrome_sqlite3changeset_invert_strm // Lines 11047-11052
-#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10138-10142
-#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 10010
-#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10104-10108
-#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 10039-10045
-#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10073-10077
-#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 9961-9965
+ chrome_sqlite3changeset_invert_strm // Lines 11070-11075
+#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10161-10165
+#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 10033
+#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10127-10131
+#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 10062-10068
+#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10096-10100
+#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 9984-9988
#define sqlite3changeset_start_strm \
- chrome_sqlite3changeset_start_strm // Lines 11053-11057
+ chrome_sqlite3changeset_start_strm // Lines 11076-11080
#define sqlite3changeset_start_v2 \
- chrome_sqlite3changeset_start_v2 // Lines 9966-9971
+ chrome_sqlite3changeset_start_v2 // Lines 9989-9994
#define sqlite3changeset_start_v2_strm \
- chrome_sqlite3changeset_start_v2_strm // Lines 11058-11063
+ chrome_sqlite3changeset_start_v2_strm // Lines 11081-11086
#define sqlite3rebaser_configure \
- chrome_sqlite3rebaser_configure // Lines 10882-10885
-#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 10871
-#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 10915
-#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 10901-10905
+ chrome_sqlite3rebaser_configure // Lines 10905-10908
+#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 10894
+#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 10938
+#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 10924-10928
#define sqlite3rebaser_rebase_strm \
- chrome_sqlite3rebaser_rebase_strm // Lines 11082-11088
-#define sqlite3session_attach chrome_sqlite3session_attach // Lines 9668-9671
+ chrome_sqlite3rebaser_rebase_strm // Lines 11105-11111
+#define sqlite3session_attach chrome_sqlite3session_attach // Lines 9691-9694
#define sqlite3session_changeset \
- chrome_sqlite3session_changeset // Lines 9797-9801
+ chrome_sqlite3session_changeset // Lines 9820-9824
#define sqlite3session_changeset_strm \
- chrome_sqlite3session_changeset_strm // Lines 11064-11068
-#define sqlite3session_config chrome_sqlite3session_config // Line 11123
-#define sqlite3session_create chrome_sqlite3session_create // Lines 9538-9542
-#define sqlite3session_delete chrome_sqlite3session_delete // Line 9557
-#define sqlite3session_diff chrome_sqlite3session_diff // Lines 9860-9865
-#define sqlite3session_enable chrome_sqlite3session_enable // Line 9578
-#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 9608
-#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 9918
+ chrome_sqlite3session_changeset_strm // Lines 11087-11091
+#define sqlite3session_config chrome_sqlite3session_config // Line 11146
+#define sqlite3session_create chrome_sqlite3session_create // Lines 9561-9565
+#define sqlite3session_delete chrome_sqlite3session_delete // Line 9580
+#define sqlite3session_diff chrome_sqlite3session_diff // Lines 9883-9888
+#define sqlite3session_enable chrome_sqlite3session_enable // Line 9601
+#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 9631
+#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 9941
#define sqlite3session_patchset \
- chrome_sqlite3session_patchset // Lines 9897-9901
+ chrome_sqlite3session_patchset // Lines 9920-9924
#define sqlite3session_patchset_strm \
- chrome_sqlite3session_patchset_strm // Lines 11069-11073
+ chrome_sqlite3session_patchset_strm // Lines 11092-11096
#define sqlite3session_table_filter \
- chrome_sqlite3session_table_filter // Lines 9683-9690
+ chrome_sqlite3session_table_filter // Lines 9706-9713
#endif // THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
+
diff --git a/chromium/third_party/sqlite/amalgamation/shell/shell.c b/chromium/third_party/sqlite/amalgamation/shell/shell.c
index 04ff4562761..ff7dc69d808 100644
--- a/chromium/third_party/sqlite/amalgamation/shell/shell.c
+++ b/chromium/third_party/sqlite/amalgamation/shell/shell.c
@@ -156,6 +156,9 @@ typedef unsigned char u8;
# ifndef unlink
# define unlink _unlink
# endif
+# ifndef strdup
+# define strdup _strdup
+# endif
# undef popen
# define popen _popen
# undef pclose
@@ -2143,22 +2146,47 @@ SQLITE_EXTENSION_INIT1
/*
** Set the result stored by context ctx to a blob containing the
-** contents of file zName.
+** contents of file zName. Or, leave the result unchanged (NULL)
+** if the file does not exist or is unreadable.
+**
+** If the file exceeds the SQLite blob size limit, through an
+** SQLITE_TOOBIG error.
+**
+** Throw an SQLITE_IOERR if there are difficulties pulling the file
+** off of disk.
*/
static void readFileContents(sqlite3_context *ctx, const char *zName){
FILE *in;
- long nIn;
+ sqlite3_int64 nIn;
void *pBuf;
+ sqlite3 *db;
+ int mxBlob;
in = fopen(zName, "rb");
- if( in==0 ) return;
+ if( in==0 ){
+ /* File does not exist or is unreadable. Leave the result set to NULL. */
+ return;
+ }
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
- pBuf = sqlite3_malloc( nIn );
- if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
- sqlite3_result_blob(ctx, pBuf, nIn, sqlite3_free);
+ db = sqlite3_context_db_handle(ctx);
+ mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
+ if( nIn>mxBlob ){
+ sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
+ fclose(in);
+ return;
+ }
+ pBuf = sqlite3_malloc64( nIn );
+ if( pBuf==0 ){
+ sqlite3_result_error_nomem(ctx);
+ fclose(in);
+ return;
+ }
+ if( 1==fread(pBuf, nIn, 1, in) ){
+ sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
}else{
+ sqlite3_result_error_code(ctx, SQLITE_IOERR);
sqlite3_free(pBuf);
}
fclose(in);
@@ -2668,8 +2696,8 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
FsdirLevel *pLvl;
if( iNew>=pCur->nLvl ){
int nNew = iNew+1;
- int nByte = nNew*sizeof(FsdirLevel);
- FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc(pCur->aLvl, nByte);
+ sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
+ FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
if( aNew==0 ) return SQLITE_NOMEM;
memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
pCur->aLvl = aNew;
@@ -2749,7 +2777,7 @@ static int fsdirColumn(
}else if( S_ISLNK(m) ){
char aStatic[64];
char *aBuf = aStatic;
- int nBuf = 64;
+ sqlite3_int64 nBuf = 64;
int n;
while( 1 ){
@@ -2757,7 +2785,7 @@ static int fsdirColumn(
if( n<nBuf ) break;
if( aBuf!=aStatic ) sqlite3_free(aBuf);
nBuf = nBuf*2;
- aBuf = sqlite3_malloc(nBuf);
+ aBuf = sqlite3_malloc64(nBuf);
if( aBuf==0 ){
sqlite3_result_error_nomem(ctx);
return SQLITE_NOMEM;
@@ -4061,6 +4089,117 @@ int sqlite3_appendvfs_init(
}
/************************* End ../ext/misc/appendvfs.c ********************/
+/************************* Begin ../ext/misc/memtrace.c ******************/
+/*
+** 2019-01-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
+** mechanism to add a tracing layer on top of SQLite. If this extension
+** is registered prior to sqlite3_initialize(), it will cause all memory
+** allocation activities to be logged on standard output, or to some other
+** FILE specified by the initializer.
+**
+** This file needs to be compiled into the application that uses it.
+**
+** This extension is used to implement the --memtrace option of the
+** command-line shell.
+*/
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+/* The original memory allocation routines */
+static sqlite3_mem_methods memtraceBase;
+static FILE *memtraceOut;
+
+/* Methods that trace memory allocations */
+static void *memtraceMalloc(int n){
+ if( memtraceOut ){
+ fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
+ memtraceBase.xRoundup(n));
+ }
+ return memtraceBase.xMalloc(n);
+}
+static void memtraceFree(void *p){
+ if( p==0 ) return;
+ if( memtraceOut ){
+ fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
+ }
+ memtraceBase.xFree(p);
+}
+static void *memtraceRealloc(void *p, int n){
+ if( p==0 ) return memtraceMalloc(n);
+ if( n==0 ){
+ memtraceFree(p);
+ return 0;
+ }
+ if( memtraceOut ){
+ fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
+ memtraceBase.xSize(p), memtraceBase.xRoundup(n));
+ }
+ return memtraceBase.xRealloc(p, n);
+}
+static int memtraceSize(void *p){
+ return memtraceBase.xSize(p);
+}
+static int memtraceRoundup(int n){
+ return memtraceBase.xRoundup(n);
+}
+static int memtraceInit(void *p){
+ return memtraceBase.xInit(p);
+}
+static void memtraceShutdown(void *p){
+ memtraceBase.xShutdown(p);
+}
+
+/* The substitute memory allocator */
+static sqlite3_mem_methods ersaztMethods = {
+ memtraceMalloc,
+ memtraceFree,
+ memtraceRealloc,
+ memtraceSize,
+ memtraceRoundup,
+ memtraceInit,
+ memtraceShutdown,
+ 0
+};
+
+/* Begin tracing memory allocations to out. */
+int sqlite3MemTraceActivate(FILE *out){
+ int rc = SQLITE_OK;
+ if( memtraceBase.xMalloc==0 ){
+ rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
+ }
+ }
+ memtraceOut = out;
+ return rc;
+}
+
+/* Deactivate memory tracing */
+int sqlite3MemTraceDeactivate(void){
+ int rc = SQLITE_OK;
+ if( memtraceBase.xMalloc!=0 ){
+ rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
+ if( rc==SQLITE_OK ){
+ memset(&memtraceBase, 0, sizeof(memtraceBase));
+ }
+ }
+ memtraceOut = 0;
+ return rc;
+}
+
+/************************* End ../ext/misc/memtrace.c ********************/
#ifdef SQLITE_HAVE_ZLIB
/************************* Begin ../ext/misc/zipfile.c ******************/
/*
@@ -4422,7 +4561,7 @@ static int zipfileConnect(
rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
if( rc==SQLITE_OK ){
- pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
+ pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, nByte+nFile);
pNew->db = db;
@@ -4870,7 +5009,7 @@ static int zipfileGetEntry(
}
if( rc==SQLITE_OK ){
- int nAlloc;
+ sqlite3_int64 nAlloc;
ZipfileEntry *pNew;
int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
@@ -4882,7 +5021,7 @@ static int zipfileGetEntry(
nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
}
- pNew = (ZipfileEntry*)sqlite3_malloc(nAlloc);
+ pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -5045,11 +5184,11 @@ static int zipfileDeflate(
u8 **ppOut, int *pnOut, /* Output */
char **pzErr /* OUT: Error message */
){
- int nAlloc = (int)compressBound(nIn);
+ sqlite3_int64 nAlloc = compressBound(nIn);
u8 *aOut;
int rc = SQLITE_OK;
- aOut = (u8*)sqlite3_malloc(nAlloc);
+ aOut = (u8*)sqlite3_malloc64(nAlloc);
if( aOut==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -5122,7 +5261,7 @@ static int zipfileColumn(
if( pCsr->pCurrent->aData ){
aBuf = pCsr->pCurrent->aData;
}else{
- aBuf = aFree = sqlite3_malloc(sz);
+ aBuf = aFree = sqlite3_malloc64(sz);
if( aBuf==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -5961,14 +6100,14 @@ struct ZipfileCtx {
static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
if( pBuf->n+nByte>pBuf->nAlloc ){
u8 *aNew;
- int nNew = pBuf->n ? pBuf->n*2 : 512;
+ sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
int nReq = pBuf->n + nByte;
while( nNew<nReq ) nNew = nNew*2;
- aNew = sqlite3_realloc(pBuf->a, nNew);
+ aNew = sqlite3_realloc64(pBuf->a, nNew);
if( aNew==0 ) return SQLITE_NOMEM;
pBuf->a = aNew;
- pBuf->nAlloc = nNew;
+ pBuf->nAlloc = (int)nNew;
}
return SQLITE_OK;
}
@@ -6159,7 +6298,7 @@ void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
void zipfileFinal(sqlite3_context *pCtx){
ZipfileCtx *p;
ZipfileEOCD eocd;
- int nZip;
+ sqlite3_int64 nZip;
u8 *aZip;
p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
@@ -6172,14 +6311,14 @@ void zipfileFinal(sqlite3_context *pCtx){
eocd.iOffset = p->body.n;
nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
- aZip = (u8*)sqlite3_malloc(nZip);
+ aZip = (u8*)sqlite3_malloc64(nZip);
if( aZip==0 ){
sqlite3_result_error_nomem(pCtx);
}else{
memcpy(aZip, p->body.a, p->body.n);
memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
- sqlite3_result_blob(pCtx, aZip, nZip, zipfileFree);
+ sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
}
}
@@ -8550,14 +8689,18 @@ struct ShellState {
u8 autoExplain; /* Automatically turn on .explain mode */
u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
u8 autoEQPtest; /* autoEQP is in test mode */
+ u8 autoEQPtrace; /* autoEQP is in trace mode */
u8 statsOn; /* True to display memory stats before each finalize */
u8 scanstatsOn; /* True to display scan stats before each finalize */
u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
u8 nEqpLevel; /* Depth of the EQP output graph */
+ u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
+ int lineno; /* Line number of last line read from in */
+ FILE *in; /* Read commands from this stream */
FILE *out; /* Write results here */
FILE *traceOut; /* Output for sqlite3_trace() */
int nErr; /* Number of errors seen */
@@ -8568,7 +8711,11 @@ struct ShellState {
int writableSchema; /* True if PRAGMA writable_schema=ON */
int showHeader; /* True to show column names in List or Column mode */
int nCheck; /* Number of ".check" commands run */
+ unsigned nProgress; /* Number of progress callbacks encountered */
+ unsigned mxProgress; /* Maximum progress callbacks before failing */
+ unsigned flgProgress; /* Flags for the progress callback */
unsigned shellFlgs; /* Various flags */
+ sqlite3_int64 szMax; /* --maxsize argument to .open */
char *zDestTable; /* Name of destination table when MODE_Insert */
char *zTempFile; /* Temporary file that might need deleting */
char zTestcase[30]; /* Name of current test case */
@@ -8613,6 +8760,20 @@ struct ShellState {
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
+#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
+
+/* Allowed values for ShellState.eTraceType
+*/
+#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
+#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
+#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
+
+/* Bits in the ShellState.flgProgress variable */
+#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
+#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
+ ** callback limit is reached, and for each
+ ** top-level SQL statement */
+#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
/*
** These are the allowed shellFlgs values
@@ -9314,6 +9475,26 @@ static void eqp_render(ShellState *p){
}
}
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+/*
+** Progress handler callback.
+*/
+static int progress_handler(void *pClientData) {
+ ShellState *p = (ShellState*)pClientData;
+ p->nProgress++;
+ if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
+ raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
+ if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
+ if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
+ return 1;
+ }
+ if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
+ raw_printf(p->out, "Progress %u\n", p->nProgress);
+ }
+ return 0;
+}
+#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
+
/*
** This is the callback routine that the shell
** invokes for each row of a query result.
@@ -10918,6 +11099,7 @@ static const char *(azHelp[]) = {
#endif
".backup ?DB? FILE Backup DB (default \"main\") to FILE",
" --append Use the appendvfs",
+ " --async Write to FILE without a journal and without fsync()",
".bail on|off Stop after hitting an error. Default OFF",
".binary on|off Turn binary output on or off. Default OFF",
".cd DIRECTORY Change the working directory to DIRECTORY",
@@ -10933,7 +11115,13 @@ static const char *(azHelp[]) = {
" --newlines Allow unescaped newline characters in output",
" TABLE is LIKE pattern for the tables to dump",
".echo on|off Turn command echo on or off",
- ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN",
+ ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
+ " Other Modes:",
+#ifdef SQLITE_DEBUG
+ " test Show raw EXPLAIN QUERY PLAN output",
+ " trace Like \"full\" but also enable \"PRAGMA vdbe_trace\"",
+#endif
+ " trigger Like \"full\" but also show trigger bytecode",
".excel Display the output of next command in a spreadsheet",
".exit ?CODE? Exit this program with return-code CODE",
".expert EXPERIMENTAL. Suggest indexes for specified queries",
@@ -10984,6 +11172,8 @@ static const char *(azHelp[]) = {
" --append Use appendvfs to append database to the end of FILE",
#ifdef SQLITE_ENABLE_DESERIALIZE
" --deserialize Load into memory useing sqlite3_deserialize()",
+ " --hexdb Load the output of \"dbtotxt\" as an in-memory database",
+ " --maxsize N Maximum size for --hexdb or --deserialized database",
#endif
" --new Initialize FILE to an empty database",
" --readonly Open FILE readonly",
@@ -10991,6 +11181,13 @@ static const char *(azHelp[]) = {
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
" If FILE begins with '|' then open it as a pipe.",
".print STRING... Print literal STRING",
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ ".progress N Invoke progress handler after every N opcodes",
+ " --limit N Interrupt after N progress callbacks",
+ " --once Do no more than one progress interrupt",
+ " --quiet|-q No output except at interrupts",
+ " --reset Reset the count for each input and interrupt",
+#endif
".prompt MAIN CONTINUE Replace the standard prompts",
".quit Exit this program",
".read FILE Read input from FILE",
@@ -11040,7 +11237,22 @@ static const char *(azHelp[]) = {
".testcase NAME Begin redirecting output to 'testcase-out.txt'",
".timeout MS Try opening locked tables for MS milliseconds",
".timer on|off Turn SQL timer on or off",
- ".trace FILE|off Output each SQL statement as it is run",
+#ifndef SQLITE_OMIT_TRACE
+ ".trace ?OPTIONS? Output each SQL statement as it is run",
+ " FILE Send output to FILE",
+ " stdout Send output to stdout",
+ " stderr Send output to stderr",
+ " off Disable tracing",
+ " --expanded Expand query parameters",
+#ifdef SQLITE_ENABLE_NORMALIZE
+ " --normalized Normal the SQL statements",
+#endif
+ " --plain Show SQL as it is input",
+ " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
+ " --profile Profile statements (SQLITE_TRACE_PROFILE)",
+ " --row Trace each row (SQLITE_TRACE_ROW)",
+ " --close Trace connection close (SQLITE_TRACE_CLOSE)",
+#endif /* SQLITE_OMIT_TRACE */
".vfsinfo ?AUX? Information about the top-level VFS",
".vfslist List all available VFSes",
".vfsname ?AUX? Print the name of the VFS stack",
@@ -11118,7 +11330,7 @@ static int showHelp(FILE *out, const char *zPattern){
}
/* Forward reference */
-static int process_input(ShellState *p, FILE *in);
+static int process_input(ShellState *p);
/*
** Read the content of file zName into memory obtained from sqlite3_malloc64()
@@ -11248,6 +11460,94 @@ int deduceDatabaseType(const char *zName, int dfltZip){
return rc;
}
+#ifdef SQLITE_ENABLE_DESERIALIZE
+/*
+** Reconstruct an in-memory database using the output from the "dbtotxt"
+** program. Read content from the file in p->zDbFilename. If p->zDbFilename
+** is 0, then read from standard input.
+*/
+static unsigned char *readHexDb(ShellState *p, int *pnData){
+ unsigned char *a = 0;
+ int nLine;
+ int n = 0;
+ int pgsz = 0;
+ int iOffset = 0;
+ int j, k;
+ int rc;
+ FILE *in;
+ unsigned char x[16];
+ char zLine[1000];
+ if( p->zDbFilename ){
+ in = fopen(p->zDbFilename, "r");
+ if( in==0 ){
+ utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
+ return 0;
+ }
+ nLine = 0;
+ }else{
+ in = p->in;
+ nLine = p->lineno;
+ }
+ *pnData = 0;
+ nLine++;
+ if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
+ rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
+ if( rc!=2 ) goto readHexDb_error;
+ if( n<=0 ) goto readHexDb_error;
+ a = sqlite3_malloc( n );
+ if( a==0 ){
+ utf8_printf(stderr, "Out of memory!\n");
+ goto readHexDb_error;
+ }
+ memset(a, 0, n);
+ if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
+ utf8_printf(stderr, "invalid pagesize\n");
+ goto readHexDb_error;
+ }
+ for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
+ rc = sscanf(zLine, "| page %d offset %d", &j, &k);
+ if( rc==2 ){
+ iOffset = k;
+ continue;
+ }
+ if( strncmp(zLine, "| end ", 6)==0 ){
+ break;
+ }
+ rc = sscanf(zLine,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
+ " %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",
+ &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
+ &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
+ if( rc==17 ){
+ k = iOffset+j;
+ if( k+16<=n ){
+ memcpy(a+k, x, 16);
+ }
+ }
+ }
+ *pnData = n;
+ if( in!=p->in ){
+ fclose(in);
+ }else{
+ p->lineno = nLine;
+ }
+ return a;
+
+readHexDb_error:
+ if( in!=stdin ){
+ fclose(in);
+ }else{
+ while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
+ nLine++;
+ if(strncmp(zLine, "| end ", 6)==0 ) break;
+ }
+ p->lineno = nLine;
+ }
+ sqlite3_free(a);
+ utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
+ return 0;
+}
+#endif /* SQLITE_ENABLE_DESERIALIZE */
+
/* Flags for open_db().
**
** The default behavior of open_db() is to exit(1) if the database fails to
@@ -11281,6 +11581,7 @@ static void open_db(ShellState *p, int openFlags){
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
break;
}
+ case SHELL_OPEN_HEXDB:
case SHELL_OPEN_DESERIALIZE: {
sqlite3_open(0, &p->db);
break;
@@ -11303,7 +11604,10 @@ static void open_db(ShellState *p, int openFlags){
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
p->zDbFilename, sqlite3_errmsg(p->db));
- if( openFlags & OPEN_DB_KEEPALIVE ) return;
+ if( openFlags & OPEN_DB_KEEPALIVE ){
+ sqlite3_open(":memory:", &p->db);
+ return;
+ }
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -11335,15 +11639,29 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_free(zSql);
}
#ifdef SQLITE_ENABLE_DESERIALIZE
- else if( p->openMode==SHELL_OPEN_DESERIALIZE ){
+ else
+ if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
+ int rc;
int nData = 0;
- unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData);
- int rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
+ unsigned char *aData;
+ if( p->openMode==SHELL_OPEN_DESERIALIZE ){
+ aData = (unsigned char*)readFile(p->zDbFilename, &nData);
+ }else{
+ aData = readHexDb(p, &nData);
+ if( aData==0 ){
+ utf8_printf(stderr, "Error in hexdb input\n");
+ return;
+ }
+ }
+ rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
SQLITE_DESERIALIZE_RESIZEABLE |
SQLITE_DESERIALIZE_FREEONCLOSE);
if( rc ){
utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
}
+ if( p->szMax>0 ){
+ sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
+ }
}
#endif
}
@@ -11547,24 +11865,60 @@ static FILE *output_file_open(const char *zFile, int bTextMode){
return f;
}
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
+#ifndef SQLITE_OMIT_TRACE
/*
** A routine for handling output from sqlite3_trace().
*/
static int sql_trace_callback(
- unsigned mType,
- void *pArg,
- void *pP,
- void *pX
+ unsigned mType, /* The trace type */
+ void *pArg, /* The ShellState pointer */
+ void *pP, /* Usually a pointer to sqlite_stmt */
+ void *pX /* Auxiliary output */
){
- FILE *f = (FILE*)pArg;
- UNUSED_PARAMETER(mType);
- UNUSED_PARAMETER(pP);
- if( f ){
- const char *z = (const char*)pX;
- int i = strlen30(z);
- while( i>0 && z[i-1]==';' ){ i--; }
- utf8_printf(f, "%.*s;\n", i, z);
+ ShellState *p = (ShellState*)pArg;
+ sqlite3_stmt *pStmt;
+ const char *zSql;
+ int nSql;
+ if( p->traceOut==0 ) return 0;
+ if( mType==SQLITE_TRACE_CLOSE ){
+ utf8_printf(p->traceOut, "-- closing database connection\n");
+ return 0;
+ }
+ if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
+ zSql = (const char*)pX;
+ }else{
+ pStmt = (sqlite3_stmt*)pP;
+ switch( p->eTraceType ){
+ case SHELL_TRACE_EXPANDED: {
+ zSql = sqlite3_expanded_sql(pStmt);
+ break;
+ }
+#ifdef SQLITE_ENABLE_NORMALIZE
+ case SHELL_TRACE_NORMALIZED: {
+ zSql = sqlite3_normalized_sql(pStmt);
+ break;
+ }
+#endif
+ default: {
+ zSql = sqlite3_sql(pStmt);
+ break;
+ }
+ }
+ }
+ if( zSql==0 ) return 0;
+ nSql = strlen30(zSql);
+ while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
+ switch( mType ){
+ case SQLITE_TRACE_ROW:
+ case SQLITE_TRACE_STMT: {
+ utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
+ break;
+ }
+ case SQLITE_TRACE_PROFILE: {
+ sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
+ utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
+ break;
+ }
}
return 0;
}
@@ -13131,7 +13485,7 @@ static int arCreateOrUpdateCommand(
}
end_ar_transaction:
if( rc!=SQLITE_OK ){
- arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;");
+ sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
}else{
rc = arExecSql(pAr, "RELEASE ar;");
if( pAr->bZip && pAr->zFile ){
@@ -13330,6 +13684,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3 *pDest;
sqlite3_backup *pBackup;
int j;
+ int bAsync = 0;
const char *zVfs = 0;
for(j=1; j<nArg; j++){
const char *z = azArg[j];
@@ -13338,6 +13693,9 @@ static int do_meta_command(char *zLine, ShellState *p){
if( strcmp(z, "-append")==0 ){
zVfs = "apndvfs";
}else
+ if( strcmp(z, "-async")==0 ){
+ bAsync = 1;
+ }else
{
utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
return 1;
@@ -13348,7 +13706,7 @@ static int do_meta_command(char *zLine, ShellState *p){
zDb = zDestFile;
zDestFile = azArg[j];
}else{
- raw_printf(stderr, "Usage: .backup ?DB? ?--append? FILENAME\n");
+ raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
return 1;
}
}
@@ -13364,6 +13722,10 @@ static int do_meta_command(char *zLine, ShellState *p){
close_db(pDest);
return 1;
}
+ if( bAsync ){
+ sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
+ 0, 0, 0);
+ }
open_db(p, 0);
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
if( pBackup==0 ){
@@ -13629,18 +13991,30 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
if( nArg==2 ){
p->autoEQPtest = 0;
+ if( p->autoEQPtrace ){
+ if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
+ p->autoEQPtrace = 0;
+ }
if( strcmp(azArg[1],"full")==0 ){
p->autoEQP = AUTOEQP_full;
}else if( strcmp(azArg[1],"trigger")==0 ){
p->autoEQP = AUTOEQP_trigger;
+#ifdef SQLITE_DEBUG
}else if( strcmp(azArg[1],"test")==0 ){
p->autoEQP = AUTOEQP_on;
p->autoEQPtest = 1;
+ }else if( strcmp(azArg[1],"trace")==0 ){
+ p->autoEQP = AUTOEQP_full;
+ p->autoEQPtrace = 1;
+ open_db(p, 0);
+ sqlite3_exec(p->db, "SELECT name FROM sqlite_master LIMIT 1", 0, 0, 0);
+ sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
+#endif
}else{
p->autoEQP = (u8)booleanValue(azArg[1]);
}
}else{
- raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n");
+ raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
rc = 1;
}
}else
@@ -14214,6 +14588,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(p->zFreeOnClose);
p->zFreeOnClose = 0;
p->openMode = SHELL_OPEN_UNSPEC;
+ p->szMax = 0;
/* Check for command-line arguments */
for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
const char *z = azArg[iName];
@@ -14230,7 +14605,11 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifdef SQLITE_ENABLE_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE;
-#endif
+ }else if( optionMatch(z, "hexdb") ){
+ p->openMode = SHELL_OPEN_HEXDB;
+ }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
+ p->szMax = integerValue(azArg[++iName]);
+#endif /* SQLITE_ENABLE_DESERIALIZE */
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
@@ -14239,7 +14618,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
/* If a filename is specified, try to open it first */
zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
- if( zNewFilename ){
+ if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag ) shellDeleteFile(zNewFilename);
p->zDbFilename = zNewFilename;
open_db(p, OPEN_DB_KEEPALIVE);
@@ -14341,6 +14720,52 @@ static int do_meta_command(char *zLine, ShellState *p){
raw_printf(p->out, "\n");
}else
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
+ int i;
+ int nn = 0;
+ p->flgProgress = 0;
+ p->mxProgress = 0;
+ p->nProgress = 0;
+ for(i=1; i<nArg; i++){
+ const char *z = azArg[i];
+ if( z[0]=='-' ){
+ z++;
+ if( z[0]=='-' ) z++;
+ if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
+ p->flgProgress |= SHELL_PROGRESS_QUIET;
+ continue;
+ }
+ if( strcmp(z,"reset")==0 ){
+ p->flgProgress |= SHELL_PROGRESS_RESET;
+ continue;
+ }
+ if( strcmp(z,"once")==0 ){
+ p->flgProgress |= SHELL_PROGRESS_ONCE;
+ continue;
+ }
+ if( strcmp(z,"limit")==0 ){
+ if( i+1>=nArg ){
+ utf8_printf(stderr, "Error: missing argument on --limit\n");
+ rc = 1;
+ goto meta_command_exit;
+ }else{
+ p->mxProgress = (int)integerValue(azArg[++i]);
+ }
+ continue;
+ }
+ utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
+ rc = 1;
+ goto meta_command_exit;
+ }else{
+ nn = (int)integerValue(z);
+ }
+ }
+ open_db(p, 0);
+ sqlite3_progress_handler(p->db, nn, progress_handler, p);
+ }else
+#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
+
if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
if( nArg >= 2) {
strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
@@ -14355,20 +14780,23 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
- FILE *alt;
+ FILE *inSaved = p->in;
+ int savedLineno = p->lineno;
if( nArg!=2 ){
raw_printf(stderr, "Usage: .read FILE\n");
rc = 1;
goto meta_command_exit;
}
- alt = fopen(azArg[1], "rb");
- if( alt==0 ){
+ p->in = fopen(azArg[1], "rb");
+ if( p->in==0 ){
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
}else{
- rc = process_input(p, alt);
- fclose(alt);
+ rc = process_input(p);
+ fclose(p->in);
}
+ p->in = inSaved;
+ p->lineno = savedLineno;
}else
if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
@@ -15386,23 +15814,55 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
+#ifndef SQLITE_OMIT_TRACE
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
+ int mType = 0;
+ int jj;
open_db(p, 0);
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .trace FILE|off\n");
- rc = 1;
- goto meta_command_exit;
+ for(jj=1; jj<nArg; jj++){
+ const char *z = azArg[jj];
+ if( z[0]=='-' ){
+ if( optionMatch(z, "expanded") ){
+ p->eTraceType = SHELL_TRACE_EXPANDED;
+ }
+#ifdef SQLITE_ENABLE_NORMALIZE
+ else if( optionMatch(z, "normalized") ){
+ p->eTraceType = SHELL_TRACE_NORMALIZED;
+ }
+#endif
+ else if( optionMatch(z, "plain") ){
+ p->eTraceType = SHELL_TRACE_PLAIN;
+ }
+ else if( optionMatch(z, "profile") ){
+ mType |= SQLITE_TRACE_PROFILE;
+ }
+ else if( optionMatch(z, "row") ){
+ mType |= SQLITE_TRACE_ROW;
+ }
+ else if( optionMatch(z, "stmt") ){
+ mType |= SQLITE_TRACE_STMT;
+ }
+ else if( optionMatch(z, "close") ){
+ mType |= SQLITE_TRACE_CLOSE;
+ }
+ else {
+ raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
+ rc = 1;
+ goto meta_command_exit;
+ }
+ }else{
+ output_file_close(p->traceOut);
+ p->traceOut = output_file_open(azArg[1], 0);
+ }
}
- output_file_close(p->traceOut);
- p->traceOut = output_file_open(azArg[1], 0);
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( p->traceOut==0 ){
sqlite3_trace_v2(p->db, 0, 0, 0);
}else{
- sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
+ if( mType==0 ) mType = SQLITE_TRACE_STMT;
+ sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
}
-#endif
}else
+#endif /* !defined(SQLITE_OMIT_TRACE) */
#if SQLITE_USER_AUTHENTICATION
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
@@ -15641,6 +16101,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
open_db(p, 0);
if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
+ if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
BEGIN_TIMER;
rc = shell_exec(p, zSql, &zErrMsg);
END_TIMER;
@@ -15677,7 +16138,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
**
** Return the number of errors.
*/
-static int process_input(ShellState *p, FILE *in){
+static int process_input(ShellState *p){
char *zLine = 0; /* A single input line */
char *zSql = 0; /* Accumulated SQL text */
int nLine; /* Length of current line */
@@ -15686,22 +16147,22 @@ static int process_input(ShellState *p, FILE *in){
int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
int rc; /* Error code */
int errCnt = 0; /* Number of errors seen */
- int lineno = 0; /* Current line number */
int startline = 0; /* Line number for start of current input */
- while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
+ p->lineno = 0;
+ while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
fflush(p->out);
- zLine = one_input_line(in, zLine, nSql>0);
+ zLine = one_input_line(p->in, zLine, nSql>0);
if( zLine==0 ){
/* End of input */
- if( in==0 && stdin_is_interactive ) printf("\n");
+ if( p->in==0 && stdin_is_interactive ) printf("\n");
break;
}
if( seenInterrupt ){
- if( in!=0 ) break;
+ if( p->in!=0 ) break;
seenInterrupt = 0;
}
- lineno++;
+ p->lineno++;
if( nSql==0 && _all_whitespace(zLine) ){
if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
continue;
@@ -15733,7 +16194,7 @@ static int process_input(ShellState *p, FILE *in){
for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
assert( nAlloc>0 && zSql!=0 );
memcpy(zSql, zLine+i, nLine+1-i);
- startline = lineno;
+ startline = p->lineno;
nSql = nLine-i;
}else{
zSql[nSql++] = '\n';
@@ -15742,7 +16203,7 @@ static int process_input(ShellState *p, FILE *in){
}
if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
&& sqlite3_complete(zSql) ){
- errCnt += runOneSqlLine(p, zSql, in, startline);
+ errCnt += runOneSqlLine(p, zSql, p->in, startline);
nSql = 0;
if( p->outCount ){
output_reset(p);
@@ -15756,7 +16217,7 @@ static int process_input(ShellState *p, FILE *in){
}
}
if( nSql && !_all_whitespace(zSql) ){
- errCnt += runOneSqlLine(p, zSql, in, startline);
+ errCnt += runOneSqlLine(p, zSql, p->in, startline);
}
free(zSql);
free(zLine);
@@ -15845,7 +16306,8 @@ static void process_sqliterc(
char *home_dir = NULL;
const char *sqliterc = sqliterc_override;
char *zBuf = 0;
- FILE *in = NULL;
+ FILE *inSaved = p->in;
+ int savedLineno = p->lineno;
if (sqliterc == NULL) {
home_dir = find_home_dir(0);
@@ -15857,14 +16319,16 @@ static void process_sqliterc(
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
sqliterc = zBuf;
}
- in = fopen(sqliterc,"rb");
- if( in ){
+ p->in = fopen(sqliterc,"rb");
+ if( p->in ){
if( stdin_is_interactive ){
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
}
- process_input(p,in);
- fclose(in);
+ process_input(p);
+ fclose(p->in);
}
+ p->in = inSaved;
+ p->lineno = savedLineno;
sqlite3_free(zBuf);
}
@@ -15882,6 +16346,9 @@ static const char zOptions[] =
" -column set output mode to 'column'\n"
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
" -csv set output mode to 'csv'\n"
+#if defined(SQLITE_ENABLE_DESERIALIZE)
+ " -deserialize open the database using sqlite3_deserialize()\n"
+#endif
" -echo print commands before execution\n"
" -init FILENAME read/process named file\n"
" -[no]header turn headers on or off\n"
@@ -15894,6 +16361,10 @@ static const char zOptions[] =
" -line set output mode to 'line'\n"
" -list set output mode to 'list'\n"
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
+#if defined(SQLITE_ENABLE_DESERIALIZE)
+ " -maxsize N maximum size for a --deserialize database\n"
+#endif
+ " -memtrace trace all memory allocations and deallocations\n"
" -mmap N default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
" -multiplex enable the multiplexor VFS\n"
@@ -16214,6 +16685,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#ifdef SQLITE_ENABLE_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
+ }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
+ data.szMax = integerValue(argv[++i]);
#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
@@ -16223,6 +16696,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
** command, so ignore them */
break;
#endif
+ }else if( strcmp(z, "-memtrace")==0 ){
+ sqlite3MemTraceActivate(stderr);
}
}
verify_uninitialized();
@@ -16313,6 +16788,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#ifdef SQLITE_ENABLE_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
+ }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
+ data.szMax = integerValue(argv[++i]);
#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
@@ -16369,6 +16846,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
i+=2;
}else if( strcmp(z,"-mmap")==0 ){
i++;
+ }else if( strcmp(z,"-memtrace")==0 ){
+ i++;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
}else if( strcmp(z,"-sorterref")==0 ){
i++;
@@ -16486,14 +16965,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#elif HAVE_LINENOISE
linenoiseSetCompletionCallback(linenoise_completion);
#endif
- rc = process_input(&data, 0);
+ data.in = 0;
+ rc = process_input(&data);
if( zHistory ){
shell_stifle_history(2000);
shell_write_history(zHistory);
free(zHistory);
}
}else{
- rc = process_input(&data, stdin);
+ data.in = stdin;
+ rc = process_input(&data);
}
}
set_table_name(&data, 0);
diff --git a/chromium/third_party/sqlite/amalgamation/sqlite3.c b/chromium/third_party/sqlite/amalgamation/sqlite3.c
index 3ca72d7bb2b..695c0a5b8f0 100644
--- a/chromium/third_party/sqlite/amalgamation/sqlite3.c
+++ b/chromium/third_party/sqlite/amalgamation/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.26.0. By combining all the individual C code files into this
+** version 3.27.1. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -1162,9 +1162,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.26.0"
-#define SQLITE_VERSION_NUMBER 3026000
-#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt1"
+#define SQLITE_VERSION "3.27.1"
+#define SQLITE_VERSION_NUMBER 3027001
+#define SQLITE_SOURCE_ID "2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959alt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1862,6 +1862,15 @@ struct sqlite3_io_methods {
** file space based on this hint in order to help writes to the database
** file run faster.
**
+** <li>[[SQLITE_FCNTL_SIZE_LIMIT]]
+** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that
+** implements [sqlite3_deserialize()] to set an upper bound on the size
+** of the in-memory database. The argument is a pointer to a [sqlite3_int64].
+** If the integer pointed to is negative, then it is filled in with the
+** current limit. Otherwise the limit is set to the larger of the value
+** of the integer pointed to and the current database size. The integer
+** pointed to is set to the new limit.
+**
** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
** extends and truncates the database file in chunks of a size specified
@@ -2170,6 +2179,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
#define SQLITE_FCNTL_DATA_VERSION 35
+#define SQLITE_FCNTL_SIZE_LIMIT 36
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -3011,6 +3021,17 @@ struct sqlite3_mem_methods {
** negative value for this option restores the default behaviour.
** This option is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
+**
+** [[SQLITE_CONFIG_MEMDB_MAXSIZE]]
+** <dt>SQLITE_CONFIG_MEMDB_MAXSIZE
+** <dd>The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter
+** [sqlite3_int64] parameter which is the default maximum size for an in-memory
+** database created using [sqlite3_deserialize()]. This default maximum
+** size can be adjusted up or down for individual databases using the
+** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this
+** configuration setting is never used, then the default maximum is determined
+** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
+** compile-time option is not set, then the default maximum is 1073741824.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -3041,6 +3062,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
+#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -4030,9 +4052,9 @@ SQLITE_API int sqlite3_set_authorizer(
** time is in units of nanoseconds, however the current implementation
** is only capable of millisecond resolution so the six least significant
** digits in the time are meaningless. Future versions of SQLite
-** might provide greater resolution on the profiler callback. The
-** sqlite3_profile() function is considered experimental and is
-** subject to change in future versions of SQLite.
+** might provide greater resolution on the profiler callback. Invoking
+** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the
+** profile callback.
*/
SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*,
void(*xTrace)(void*,const char*), void*);
@@ -4446,6 +4468,8 @@ SQLITE_API int sqlite3_open_v2(
** is not a database file pathname pointer that SQLite passed into the xOpen
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
+**
+** See the [URI filename] documentation for additional information.
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
@@ -4668,14 +4692,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently.
**
-** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
-** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
-** representation of the SQL statement should be calculated and then
-** associated with the prepared statement, which can be obtained via
-** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
-** normalize a SQL statement are unspecified and subject to change.
-** At a minimum, literal values will be replaced with suitable
-** placeholders.
+** [[SQLITE_PREPARE_NORMALIZE]] <dt>SQLITE_PREPARE_NORMALIZE</dt>
+** <dd>The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used
+** to be required for any prepared statement that wanted to use the
+** [sqlite3_normalized_sql()] interface. However, the
+** [sqlite3_normalized_sql()] interface is now available to all
+** prepared statements, regardless of whether or not they use this
+** flag.
**
** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
@@ -11064,7 +11087,7 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** sqlite3changeset_next() is called on the iterator or until the
** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
** set to the number of columns in the table affected by the change. If
-** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change
+** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
** changes. Finally, if pOp is not NULL, then *pOp is set to one of
@@ -12298,12 +12321,8 @@ struct Fts5PhraseIter {
**
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
** to the column in which it occurs and *piOff the token offset of the
-** first token of the phrase. The exception is if the table was created
-** with the offsets=0 option specified. In this case *piOff is always
-** set to -1.
-**
-** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
-** if an error occurs.
+** first token of the phrase. Returns SQLITE_OK if successful, or an error
+** code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
@@ -12592,11 +12611,11 @@ struct Fts5ExtensionApi {
** the tokenizer substitutes "first" for "1st" and the query works
** as expected.
**
-** <li> By adding multiple synonyms for a single term to the FTS index.
-** In this case, when tokenizing query text, the tokenizer may
-** provide multiple synonyms for a single term within the document.
-** FTS5 then queries the index for each synonym individually. For
-** example, faced with the query:
+** <li> By querying the index for all synonyms of each query term
+** separately. In this case, when tokenizing query text, the
+** tokenizer may provide multiple synonyms for a single term
+** within the document. FTS5 then queries the index for each
+** synonym individually. For example, faced with the query:
**
** <codeblock>
** ... MATCH 'first place'</codeblock>
@@ -12620,7 +12639,7 @@ struct Fts5ExtensionApi {
** "place".
**
** This way, even if the tokenizer does not provide synonyms
-** when tokenizing query text (it should not - to do would be
+** when tokenizing query text (it should not - to do so would be
** inefficient), it doesn't matter if the user queries for
** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
@@ -14555,6 +14574,7 @@ SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*);
+SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
@@ -14794,12 +14814,11 @@ typedef struct VdbeOpList VdbeOpList;
#endif
/*
-** The following macro converts a relative address in the p2 field
-** of a VdbeOp structure into a negative number so that
-** sqlite3VdbeAddOpList() knows that the address is relative. Calling
-** the macro again restores the address.
+** The following macro converts a label returned by sqlite3VdbeMakeLabel()
+** into an index into the Parse.aLabel[] array that contains the resolved
+** address of that label.
*/
-#define ADDR(X) (-1-(X))
+#define ADDR(X) (~(X))
/*
** The makefile scans the vdbe.c source file and creates the "opcodes.h"
@@ -15075,6 +15094,12 @@ SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*);
# define ExplainQueryPlan(P)
# define ExplainQueryPlanPop(P)
# define ExplainQueryPlanParent(P) 0
+# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
+#endif
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
+SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char*,const char*);
+#else
+# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
@@ -15090,7 +15115,7 @@ SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
-SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
@@ -15111,6 +15136,10 @@ SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*);
SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3*,Vdbe*,const char*);
+SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*);
+#endif
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
@@ -16236,10 +16265,13 @@ SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
** in the style of sqlite3_trace()
*/
-#define SQLITE_TRACE_LEGACY 0x80
+#define SQLITE_TRACE_LEGACY 0x40 /* Use the legacy xTrace */
+#define SQLITE_TRACE_XPROFILE 0x80 /* Use the legacy xProfile */
#else
-#define SQLITE_TRACE_LEGACY 0
+#define SQLITE_TRACE_LEGACY 0
+#define SQLITE_TRACE_XPROFILE 0
#endif /* SQLITE_OMIT_DEPRECATED */
+#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
/*
@@ -16298,8 +16330,10 @@ struct sqlite3 {
void **aExtension; /* Array of shared library handles */
int (*xTrace)(u32,void*,void*,void*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
+#ifndef SQLITE_OMIT_DEPRECATED
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
+#endif
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*); /* Invoked at every commit. */
void *pRollbackArg; /* Argument to xRollbackCallback() */
@@ -16430,6 +16464,7 @@ struct sqlite3 {
#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */
+#define SQLITE_ParserTrace HI(0x0020) /* PRAGMA parser_trace=ON */
#endif
/*
@@ -16832,9 +16867,6 @@ struct VTable {
struct Table {
char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */
-#ifdef SQLITE_ENABLE_NORMALIZE
- Hash *pColHash; /* All columns indexed by name */
-#endif
Index *pIndex; /* List of SQL indexes on this table. */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
@@ -17121,7 +17153,7 @@ struct Index {
u16 nKeyCol; /* Number of columns forming the key */
u16 nColumn; /* Number of columns stored in the index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
+ unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
unsigned isResized:1; /* True if resizeIndexObject() has been called */
@@ -17146,6 +17178,7 @@ struct Index {
#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
+#define SQLITE_IDXTYPE_IPK 3 /* INTEGER PRIMARY KEY index */
/* Return true if index X is a PRIMARY KEY index */
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
@@ -17363,6 +17396,10 @@ struct Expr {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
** for a column of an index on an expression */
Window *pWin; /* TK_FUNCTION: Window definition for the func */
+ struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
+ int iAddr; /* Subroutine entry address */
+ int regReturn; /* Register used to hold return address */
+ } sub;
} y;
};
@@ -17394,6 +17431,8 @@ struct Expr {
#define EP_Alias 0x400000 /* Is an alias for a result set column */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
+#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
+#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
/*
** The EP_Propagate mask is a set of properties that automatically propagate
@@ -17943,11 +17982,11 @@ struct Parse {
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
- int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */
- int nLabel; /* Number of labels used */
+ int nLabel; /* The *negative* of the number of labels used */
+ int nLabelAlloc; /* Number of slots in aLabel */
int *aLabel; /* Space to hold the labels */
ExprList *pConstExpr;/* Constant expressions */
Token constraintName;/* Name of the constraint currently being parsed */
@@ -18007,7 +18046,9 @@ struct Parse {
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
- Index *pNewIndex; /* An index being constructed by CREATE INDEX */
+ Index *pNewIndex; /* An index being constructed by CREATE INDEX.
+ ** Also used to hold redundant UNIQUE constraints
+ ** during a RENAME COLUMN */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -18235,6 +18276,7 @@ typedef struct {
int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */
int rc; /* Result code stored here */
u32 mInitFlags; /* Flags controlling error messages */
+ u32 nInitRow; /* Number of rows processed */
} InitData;
/*
@@ -18295,6 +18337,9 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ sqlite3_int64 mxMemdbSize; /* Default max memdb size */
+#endif
#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
@@ -18683,6 +18728,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8);
SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3Dequote(char*);
+SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*);
SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **);
@@ -18711,6 +18757,7 @@ SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
+SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32);
@@ -18744,6 +18791,11 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
+#ifdef SQLITE_HAS_CODEC
+SQLITE_PRIVATE int sqlite3CodecQueryParameters(sqlite3*,const char*,const char*);
+#else
+# define sqlite3CodecQueryParameters(A,B,C) 0
+#endif
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
#ifdef SQLITE_UNTESTABLE
@@ -18796,8 +18848,8 @@ SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upser
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
-SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
-SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, Expr*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
@@ -18864,8 +18916,8 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_ite
SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
-SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*);
-SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int);
+SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*,Expr*);
+SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*);
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int);
@@ -18903,9 +18955,6 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
-#ifdef SQLITE_ENABLE_NORMALIZE
-SQLITE_PRIVATE int sqlite3IsRowidN(const char*, int);
-#endif
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
@@ -18932,9 +18981,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int);
-#ifdef SQLITE_ENABLE_NORMALIZE
-SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN(int,const char*,int);
-#endif
+SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*);
SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void);
@@ -19139,19 +19186,17 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
-#ifdef SQLITE_ENABLE_NORMALIZE
-SQLITE_PRIVATE int sqlite3GetTokenNormalized(const unsigned char *, int *, int *);
-#endif
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
-SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int);
+SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int, int);
+SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
-SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
+SQLITE_PRIVATE int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
@@ -19300,7 +19345,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE void sqlite3ParserReset(Parse*);
#ifdef SQLITE_ENABLE_NORMALIZE
-SQLITE_PRIVATE void sqlite3Normalize(Vdbe*, const char*, int, u8);
+SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*);
#endif
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
@@ -19396,7 +19441,7 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void);
#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */
#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */
#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */
-SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
+SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*);
SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
@@ -19712,6 +19757,13 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
#endif
+/* The default maximum size of an in-memory database created using
+** sqlite3_deserialize()
+*/
+#ifndef SQLITE_MEMDB_DEFAULT_MAXSIZE
+# define SQLITE_MEMDB_DEFAULT_MAXSIZE 1073741824
+#endif
+
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -19759,13 +19811,16 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
+#endif
#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
0, /* bInternalFunctions */
0x7ffffffe, /* iOnceResetThreshold */
- SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */
+ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
};
/*
@@ -20184,6 +20239,9 @@ struct sqlite3_context {
*/
typedef unsigned bft; /* Bit Field Type */
+/* The ScanStatus object holds a single value for the
+** sqlite3_stmt_scanstatus() interface.
+*/
typedef struct ScanStatus ScanStatus;
struct ScanStatus {
int addrExplain; /* OP_Explain for loop */
@@ -20194,6 +20252,19 @@ struct ScanStatus {
char *zName; /* Name of table or index */
};
+/* The DblquoteStr object holds the text of a double-quoted
+** string for a prepared statement. A linked list of these objects
+** is constructed during statement parsing and is held on Vdbe.pDblStr.
+** When computing a normalized SQL statement for an SQL statement, that
+** list is consulted for each double-quoted identifier to see if the
+** identifier should really be a string literal.
+*/
+typedef struct DblquoteStr DblquoteStr;
+struct DblquoteStr {
+ DblquoteStr *pNextStr; /* Next string literal in the list */
+ char z[8]; /* Dequoted value for the string */
+};
+
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
@@ -20213,28 +20284,29 @@ struct Vdbe {
int pc; /* The program counter */
int rc; /* Value to return */
int nChange; /* Number of db changes made since last reset */
- int iStatement; /* Statement number (or 0 if has not opened stmt) */
+ int iStatement; /* Statement number (or 0 if has no opened stmt) */
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
+ Mem *aMem; /* The memory locations */
+ Mem **apArg; /* Arguments to currently executing user function */
+ VdbeCursor **apCsr; /* One element of this array for each open cursor */
+ Mem *aVar; /* Values for the OP_Variable opcode. */
/* When allocating a new Vdbe object, all of the fields below should be
** initialized to zero or NULL */
Op *aOp; /* Space to hold the virtual machine's program */
- Mem *aMem; /* The memory locations */
- Mem **apArg; /* Arguments to currently executing user function */
+ int nOp; /* Number of instructions in the program */
+ int nOpAlloc; /* Slots allocated for aOp[] */
Mem *aColName; /* Column names to return */
Mem *pResultSet; /* Pointer to an array of results */
char *zErrMsg; /* Error message written here */
- VdbeCursor **apCsr; /* One element of this array for each open cursor */
- Mem *aVar; /* Values for the OP_Variable opcode. */
VList *pVList; /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
- int nOp; /* Number of instructions in the program */
#ifdef SQLITE_DEBUG
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
@@ -20257,6 +20329,7 @@ struct Vdbe {
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_ENABLE_NORMALIZE
char *zNormSql; /* Normalization of the associated SQL statement */
+ DblquoteStr *pDblStr; /* List of double-quoted string literals */
#endif
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
@@ -27274,6 +27347,27 @@ static char *getTextArg(PrintfArguments *p){
return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
}
+/*
+** Allocate memory for a temporary buffer needed for printf rendering.
+**
+** If the requested size of the temp buffer is larger than the size
+** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.
+** Do the size check before the memory allocation to prevent rogue
+** SQL from requesting large allocations using the precision or width
+** field of the printf() function.
+*/
+static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
+ char *z;
+ if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
+ setStrAccumError(pAccum, SQLITE_TOOBIG);
+ return 0;
+ }
+ z = sqlite3DbMallocRaw(pAccum->db, n);
+ if( z==0 ){
+ setStrAccumError(pAccum, SQLITE_NOMEM);
+ }
+ return z;
+}
/*
** On machines with a small stack size, you can redefine the
@@ -27356,6 +27450,9 @@ SQLITE_API void sqlite3_str_vappendf(
flag_leftjustify = flag_prefix = cThousand =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
+ width = 0;
+ flag_long = 0;
+ precision = -1;
do{
switch( c ){
case '-': flag_leftjustify = 1; break;
@@ -27366,80 +27463,93 @@ SQLITE_API void sqlite3_str_vappendf(
case '0': flag_zeropad = 1; break;
case ',': cThousand = ','; break;
default: done = 1; break;
- }
- }while( !done && (c=(*++fmt))!=0 );
- /* Get the field width */
- if( c=='*' ){
- if( bArgList ){
- width = (int)getIntArg(pArgList);
- }else{
- width = va_arg(ap,int);
- }
- if( width<0 ){
- flag_leftjustify = 1;
- width = width >= -2147483647 ? -width : 0;
- }
- c = *++fmt;
- }else{
- unsigned wx = 0;
- while( c>='0' && c<='9' ){
- wx = wx*10 + c - '0';
- c = *++fmt;
- }
- testcase( wx>0x7fffffff );
- width = wx & 0x7fffffff;
- }
- assert( width>=0 );
+ case 'l': {
+ flag_long = 1;
+ c = *++fmt;
+ if( c=='l' ){
+ c = *++fmt;
+ flag_long = 2;
+ }
+ done = 1;
+ break;
+ }
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': {
+ unsigned wx = c - '0';
+ while( (c = *++fmt)>='0' && c<='9' ){
+ wx = wx*10 + c - '0';
+ }
+ testcase( wx>0x7fffffff );
+ width = wx & 0x7fffffff;
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
- if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
- width = SQLITE_PRINTF_PRECISION_LIMIT;
- }
+ if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
+ width = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
#endif
-
- /* Get the precision */
- if( c=='.' ){
- c = *++fmt;
- if( c=='*' ){
- if( bArgList ){
- precision = (int)getIntArg(pArgList);
- }else{
- precision = va_arg(ap,int);
+ if( c!='.' && c!='l' ){
+ done = 1;
+ }else{
+ fmt--;
+ }
+ break;
}
- c = *++fmt;
- if( precision<0 ){
- precision = precision >= -2147483647 ? -precision : -1;
+ case '*': {
+ if( bArgList ){
+ width = (int)getIntArg(pArgList);
+ }else{
+ width = va_arg(ap,int);
+ }
+ if( width<0 ){
+ flag_leftjustify = 1;
+ width = width >= -2147483647 ? -width : 0;
+ }
+#ifdef SQLITE_PRINTF_PRECISION_LIMIT
+ if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
+ width = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
+#endif
+ if( (c = fmt[1])!='.' && c!='l' ){
+ c = *++fmt;
+ done = 1;
+ }
+ break;
}
- }else{
- unsigned px = 0;
- while( c>='0' && c<='9' ){
- px = px*10 + c - '0';
+ case '.': {
c = *++fmt;
- }
- testcase( px>0x7fffffff );
- precision = px & 0x7fffffff;
- }
- }else{
- precision = -1;
- }
- assert( precision>=(-1) );
+ if( c=='*' ){
+ if( bArgList ){
+ precision = (int)getIntArg(pArgList);
+ }else{
+ precision = va_arg(ap,int);
+ }
+ if( precision<0 ){
+ precision = precision >= -2147483647 ? -precision : -1;
+ }
+ c = *++fmt;
+ }else{
+ unsigned px = 0;
+ while( c>='0' && c<='9' ){
+ px = px*10 + c - '0';
+ c = *++fmt;
+ }
+ testcase( px>0x7fffffff );
+ precision = px & 0x7fffffff;
+ }
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
- if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
- precision = SQLITE_PRINTF_PRECISION_LIMIT;
- }
+ if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
+ precision = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
#endif
-
-
- /* Get the conversion type modifier */
- if( c=='l' ){
- flag_long = 1;
- c = *++fmt;
- if( c=='l' ){
- flag_long = 2;
- c = *++fmt;
+ if( c=='l' ){
+ --fmt;
+ }else{
+ done = 1;
+ }
+ break;
+ }
}
- }else{
- flag_long = 0;
- }
+ }while( !done && (c=(*++fmt))!=0 );
+
/* Fetch the info entry for the field */
infop = &fmtinfo[0];
xtype = etINVALID;
@@ -27524,12 +27634,11 @@ SQLITE_API void sqlite3_str_vappendf(
nOut = etBUFSIZE;
zOut = buf;
}else{
- u64 n = (u64)precision + 10 + precision/3;
- zOut = zExtra = sqlite3Malloc( n );
- if( zOut==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
+ u64 n;
+ n = (u64)precision + 10;
+ if( cThousand ) n += precision/3;
+ zOut = zExtra = printfTempBuf(pAccum, n);
+ if( zOut==0 ) return;
nOut = (int)n;
}
bufpt = &zOut[nOut-1];
@@ -27648,12 +27757,12 @@ SQLITE_API void sqlite3_str_vappendf(
}else{
e2 = exp;
}
- if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){
- bufpt = zExtra
- = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
- if( bufpt==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
+ {
+ i64 szBufNeeded; /* Size of a temporary buffer needed */
+ szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;
+ if( szBufNeeded > etBUFSIZE ){
+ bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);
+ if( bufpt==0 ) return;
}
}
zOut = bufpt;
@@ -27877,11 +27986,8 @@ SQLITE_API void sqlite3_str_vappendf(
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 3;
if( n>etBUFSIZE ){
- bufpt = zExtra = sqlite3Malloc( n );
- if( bufpt==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
+ bufpt = zExtra = printfTempBuf(pAccum, n);
+ if( bufpt==0 ) return;
}else{
bufpt = buf;
}
@@ -28507,7 +28613,8 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
sqlite3_str_appendf(&x, " %s", pItem->zName);
}
if( pItem->pTab ){
- sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
+ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p",
+ pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab);
}
if( pItem->zAlias ){
sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
@@ -30247,7 +30354,7 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
** dequoted string, exclusive of the zero terminator, if dequoting does
** occur.
**
-** 2002-Feb-14: This routine is extended to remove MS-Access style
+** 2002-02-14: This routine is extended to remove MS-Access style
** brackets from around identifiers. For example: "[a-b-c]" becomes
** "a-b-c".
*/
@@ -30273,6 +30380,11 @@ SQLITE_PRIVATE void sqlite3Dequote(char *z){
}
z[j] = 0;
}
+SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
+ assert( sqlite3Isquote(p->u.zToken[0]) );
+ p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
+ sqlite3Dequote(p->u.zToken);
+}
/*
** Generate a Token object from a string
@@ -31700,20 +31812,6 @@ static unsigned int strHash(const char *z){
}
return h;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-static unsigned int strHashN(const char *z, int n){
- unsigned int h = 0;
- int i;
- for(i=0; i<n; i++){
- /* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
- ** 0x9e3779b1 is 2654435761 which is the closest prime number to
- ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
- h += sqlite3UpperToLower[z[i]];
- h *= 0x9e3779b1;
- }
- return h;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/* Link pNew element into the hash table pH. If pEntry!=0 then also
@@ -31825,40 +31923,6 @@ static HashElem *findElementWithHash(
}
return &nullElement;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-static HashElem *findElementWithHashN(
- const Hash *pH, /* The pH to be searched */
- const char *pKey, /* The key we are searching for */
- int nKey, /* Number of key bytes to use */
- unsigned int *pHash /* Write the hash value here */
-){
- HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- unsigned int h; /* The computed hash */
- static HashElem nullElement = { 0, 0, 0, 0 };
-
- if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
- struct _ht *pEntry;
- h = strHashN(pKey, nKey) % pH->htsize;
- pEntry = &pH->ht[h];
- elem = pEntry->chain;
- count = pEntry->count;
- }else{
- h = 0;
- elem = pH->first;
- count = pH->count;
- }
- if( pHash ) *pHash = h;
- while( count-- ){
- assert( elem!=0 );
- if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- return &nullElement;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
@@ -31903,14 +31967,6 @@ SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){
assert( pKey!=0 );
return findElementWithHash(pH, pKey, 0)->data;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-SQLITE_PRIVATE void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){
- assert( pH!=0 );
- assert( pKey!=0 );
- assert( nKey>=0 );
- return findElementWithHashN(pH, pKey, nKey, 0)->data;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/* Insert an element into the hash table pH. The key is pKey
** and the data is "data".
@@ -46661,7 +46717,8 @@ typedef struct MemFile MemFile;
struct MemFile {
sqlite3_file base; /* IO methods */
sqlite3_int64 sz; /* Size of the file */
- sqlite3_int64 szMax; /* Space allocated to aData */
+ sqlite3_int64 szAlloc; /* Space allocated to aData */
+ sqlite3_int64 szMax; /* Maximum allowed size of the file */
unsigned char *aData; /* content of the file */
int nMmap; /* Number of memory mapped pages */
unsigned mFlags; /* Flags */
@@ -46787,10 +46844,15 @@ static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
return SQLITE_FULL;
}
+ if( newSz>p->szMax ){
+ return SQLITE_FULL;
+ }
+ newSz *= 2;
+ if( newSz>p->szMax ) newSz = p->szMax;
pNew = sqlite3_realloc64(p->aData, newSz);
if( pNew==0 ) return SQLITE_NOMEM;
p->aData = pNew;
- p->szMax = newSz;
+ p->szAlloc = newSz;
return SQLITE_OK;
}
@@ -46804,10 +46866,11 @@ static int memdbWrite(
sqlite_int64 iOfst
){
MemFile *p = (MemFile *)pFile;
+ if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
if( iOfst+iAmt>p->sz ){
int rc;
- if( iOfst+iAmt>p->szMax
- && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK
+ if( iOfst+iAmt>p->szAlloc
+ && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
){
return rc;
}
@@ -46853,6 +46916,11 @@ static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
MemFile *p = (MemFile *)pFile;
+ if( eLock>SQLITE_LOCK_SHARED
+ && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
+ ){
+ return SQLITE_READONLY;
+ }
p->eLock = eLock;
return SQLITE_OK;
}
@@ -46877,6 +46945,19 @@ static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
rc = SQLITE_OK;
}
+ if( op==SQLITE_FCNTL_SIZE_LIMIT ){
+ sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
+ if( iLimit<p->sz ){
+ if( iLimit<0 ){
+ iLimit = p->szMax;
+ }else{
+ iLimit = p->sz;
+ }
+ }
+ p->szMax = iLimit;
+ *(sqlite3_int64*)pArg = iLimit;
+ rc = SQLITE_OK;
+ }
return rc;
}
@@ -46907,8 +46988,12 @@ static int memdbFetch(
void **pp
){
MemFile *p = (MemFile *)pFile;
- p->nMmap++;
- *pp = (void*)(p->aData + iOfst);
+ if( iOfst+iAmt>p->sz ){
+ *pp = 0;
+ }else{
+ p->nMmap++;
+ *pp = (void*)(p->aData + iOfst);
+ }
return SQLITE_OK;
}
@@ -46938,6 +47023,7 @@ static int memdbOpen(
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
p->base.pMethods = &memdb_io_methods;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
return SQLITE_OK;
}
@@ -47187,7 +47273,11 @@ SQLITE_API int sqlite3_deserialize(
}else{
p->aData = pData;
p->sz = szDb;
+ p->szAlloc = szBuf;
p->szMax = szBuf;
+ if( p->szMax<sqlite3GlobalConfig.mxMemdbSize ){
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ }
p->mFlags = mFlags;
rc = SQLITE_OK;
}
@@ -48608,16 +48698,27 @@ typedef struct PGroup PGroup;
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
** PgHdr1.pCache->szPage bytes is allocated directly before this structure
** in memory.
+**
+** Note: Variables isBulkLocal and isAnchor were once type "u8". That works,
+** but causes a 2-byte gap in the structure for most architectures (since
+** pointers must be either 4 or 8-byte aligned). As this structure is located
+** in memory directly after the associated page data, if the database is
+** corrupt, code at the b-tree layer may overread the page buffer and
+** read part of this structure before the corruption is detected. This
+** can cause a valgrind error if the unitialized gap is accessed. Using u16
+** ensures there is no such gap, and therefore no bytes of unitialized memory
+** in the structure.
*/
struct PgHdr1 {
sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
unsigned int iKey; /* Key value (page number) */
- u8 isBulkLocal; /* This page from bulk local storage */
- u8 isAnchor; /* This is the PGroup.lru element */
+ u16 isBulkLocal; /* This page from bulk local storage */
+ u16 isAnchor; /* This is the PGroup.lru element */
PgHdr1 *pNext; /* Next in hash table chain */
PCache1 *pCache; /* Cache that currently owns this page */
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
+ /* NB: pLruPrev is only valid if pLruNext!=0 */
};
/*
@@ -48818,6 +48919,7 @@ static int pcache1InitBulk(PCache1 *pCache){
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
+ pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
pCache->pFree = pX;
zBulk += pCache->szAlloc;
}while( --nBulk );
@@ -49090,7 +49192,8 @@ static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
pPage->pLruPrev->pLruNext = pPage->pLruNext;
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
pPage->pLruNext = 0;
- pPage->pLruPrev = 0;
+ /* pPage->pLruPrev = 0;
+ ** No need to clear pLruPrev as it is never accessed if pLruNext is 0 */
assert( pPage->isAnchor==0 );
assert( pPage->pCache->pGroup->lru.isAnchor==1 );
pPage->pCache->nRecyclable--;
@@ -49427,8 +49530,9 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
pPage->iKey = iKey;
pPage->pNext = pCache->apHash[h];
pPage->pCache = pCache;
- pPage->pLruPrev = 0;
pPage->pLruNext = 0;
+ /* pPage->pLruPrev = 0;
+ ** No need to clear pLruPrev since it is not accessed when pLruNext==0 */
*(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage;
if( iKey>pCache->iMaxKey ){
@@ -49588,7 +49692,7 @@ static void pcache1Unpin(
/* It is an error to call this function if the page is already
** part of the PGroup LRU list.
*/
- assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
+ assert( pPage->pLruNext==0 );
assert( PAGE_IS_PINNED(pPage) );
if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
@@ -54279,7 +54383,10 @@ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
pPager->mxPgno = mxPage;
}
assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */
- assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */
+ /* assert( pPager->mxPgno>=pPager->dbSize ); */
+ /* OP_MaxPgcnt ensures that the parameter passed to this function is not
+ ** less than the total number of valid pages in the database. But this
+ ** may be less than Pager.dbSize, and so the assert() above is not valid */
return pPager->mxPgno;
}
@@ -62518,9 +62625,16 @@ struct CellInfo {
** found at self->pBt->mutex.
**
** skipNext meaning:
-** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op.
-** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op.
-** eState==FAULT: Cursor fault with skipNext as error code.
+** The meaning of skipNext depends on the value of eState:
+**
+** eState Meaning of skipNext
+** VALID skipNext is meaningless and is ignored
+** INVALID skipNext is meaningless and is ignored
+** SKIPNEXT sqlite3BtreeNext() is a no-op if skipNext>0 and
+** sqlite3BtreePrevious() is no-op if skipNext<0.
+** REQUIRESEEK restoreCursorPosition() restores the cursor to
+** eState=SKIPNEXT if skipNext!=0
+** FAULT skipNext holds the cursor fault error code.
*/
struct BtCursor {
u8 eState; /* One of the CURSOR_XXX constants (see below) */
@@ -63828,11 +63942,12 @@ static int btreeMoveto(
UnpackedRecord *pIdxKey; /* Unpacked index key */
if( pKey ){
+ KeyInfo *pKeyInfo = pCur->pKeyInfo;
assert( nKey==(i64)(int)nKey );
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
- if( pIdxKey->nField==0 ){
+ sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+ if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_done;
}
@@ -63868,7 +63983,7 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
- pCur->skipNext |= skipNext;
+ if( skipNext ) pCur->skipNext = skipNext;
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
pCur->eState = CURSOR_SKIPNEXT;
}
@@ -63938,7 +64053,6 @@ SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow)
if( pCur->eState!=CURSOR_VALID ){
*pDifferentRow = 1;
}else{
- assert( pCur->skipNext==0 );
*pDifferentRow = 0;
}
return SQLITE_OK;
@@ -64389,7 +64503,7 @@ static u16 cellSize(MemPage *pPage, int iCell){
** pointer to an overflow page, insert an entry into the pointer-map for
** the overflow page that will be valid after pCell has been moved to pPage.
*/
-static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell, int *pRC){
+static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
CellInfo info;
if( *pRC ) return;
assert( pCell!=0 );
@@ -64464,7 +64578,6 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
if( iFree ){
int iFree2 = get2byte(&data[iFree]);
if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
-
if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
u8 *pEnd = &data[cellOffset + nCell*2];
u8 *pAddr;
@@ -66128,6 +66241,7 @@ static int lockBtree(BtShared *pBt){
){
goto page1_init_failed;
}
+ pBt->btsFlags |= BTS_PAGESIZE_FIXED;
assert( (pageSize & 7)==0 );
/* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte
** integer at offset 20 is the number of bytes of space at the end of
@@ -67444,6 +67558,7 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
sqlite3_free(pCur->aOverflow);
sqlite3_free(pCur->pKey);
sqlite3BtreeLeave(pBtree);
+ pCur->pBtree = 0;
}
return SQLITE_OK;
}
@@ -67543,6 +67658,25 @@ SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor *pCur){
}
/*
+** Return an upper bound on the size of any record for the table
+** that the cursor is pointing into.
+**
+** This is an optimization. Everything will still work if this
+** routine always returns 2147483647 (which is the largest record
+** that SQLite can handle) or more. But returning a smaller value might
+** prevent large memory allocations when trying to interpret a
+** corrupt datrabase.
+**
+** The current implementation merely returns the size of the underlying
+** database file.
+*/
+SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
+}
+
+/*
** Given the page number of an overflow page in the database (parameter
** ovfl), this function finds the page number of the next page in the
** linked list of overflow pages. If possible, it uses the auto-vacuum
@@ -68356,7 +68490,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
** is still obtained without this case, only a little more slowely */
- if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
+ if( pCur->info.nKey+1==intKey ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, 0);
if( rc==SQLITE_OK ){
@@ -68630,7 +68764,6 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur);
@@ -68640,14 +68773,9 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
- if( pCur->skipNext>0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
+ if( pCur->skipNext>0 ) return SQLITE_OK;
}
}
@@ -68702,7 +68830,6 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int flags){
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
@@ -68743,7 +68870,6 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){
@@ -68754,14 +68880,9 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ if( CURSOR_SKIPNEXT==pCur->eState ){
pCur->eState = CURSOR_VALID;
- if( pCur->skipNext<0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
+ if( pCur->skipNext<0 ) return SQLITE_OK;
}
}
@@ -68796,7 +68917,6 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
@@ -69132,7 +69252,7 @@ static int allocateBtreePage(
TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
}
- assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+ assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) );
end_allocate_page:
releasePage(pTrunk);
@@ -69717,8 +69837,82 @@ static void insertCell(
}
/*
+** The following parameters determine how many adjacent pages get involved
+** in a balancing operation. NN is the number of neighbors on either side
+** of the page that participate in the balancing operation. NB is the
+** total number of pages that participate, including the target page and
+** NN neighbors on either side.
+**
+** The minimum value of NN is 1 (of course). Increasing NN above 1
+** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
+** in exchange for a larger degradation in INSERT and UPDATE performance.
+** The value of NN appears to give the best results overall.
+**
+** (Later:) The description above makes it seem as if these values are
+** tunable - as if you could change them and recompile and it would all work.
+** But that is unlikely. NB has been 3 since the inception of SQLite and
+** we have never tested any other value.
+*/
+#define NN 1 /* Number of neighbors on either side of pPage */
+#define NB 3 /* (NN*2+1): Total pages involved in the balance */
+
+/*
** A CellArray object contains a cache of pointers and sizes for a
** consecutive sequence of cells that might be held on multiple pages.
+**
+** The cells in this array are the divider cell or cells from the pParent
+** page plus up to three child pages. There are a total of nCell cells.
+**
+** pRef is a pointer to one of the pages that contributes cells. This is
+** used to access information such as MemPage.intKey and MemPage.pBt->pageSize
+** which should be common to all pages that contribute cells to this array.
+**
+** apCell[] and szCell[] hold, respectively, pointers to the start of each
+** cell and the size of each cell. Some of the apCell[] pointers might refer
+** to overflow cells. In other words, some apCel[] pointers might not point
+** to content area of the pages.
+**
+** A szCell[] of zero means the size of that cell has not yet been computed.
+**
+** The cells come from as many as four different pages:
+**
+** -----------
+** | Parent |
+** -----------
+** / | \
+** / | \
+** --------- --------- ---------
+** |Child-1| |Child-2| |Child-3|
+** --------- --------- ---------
+**
+** The order of cells is in the array is for an index btree is:
+**
+** 1. All cells from Child-1 in order
+** 2. The first divider cell from Parent
+** 3. All cells from Child-2 in order
+** 4. The second divider cell from Parent
+** 5. All cells from Child-3 in order
+**
+** For a table-btree (with rowids) the items 2 and 4 are empty because
+** content exists only in leaves and there are no divider cells.
+**
+** For an index btree, the apEnd[] array holds pointer to the end of page
+** for Child-1, the Parent, Child-2, the Parent (again), and Child-3,
+** respectively. The ixNx[] array holds the number of cells contained in
+** each of these 5 stages, and all stages to the left. Hence:
+**
+** ixNx[0] = Number of cells in Child-1.
+** ixNx[1] = Number of cells in Child-1 plus 1 for first divider.
+** ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
+** ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
+** ixNx[4] = Total number of cells.
+**
+** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2]
+** are used and they point to the leaf pages only, and the ixNx value are:
+**
+** ixNx[0] = Number of cells in Child-1.
+** ixNx[1] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
+** ixNx[2] = Number of cells in Child-1 and Child-2 + both divider cells
*/
typedef struct CellArray CellArray;
struct CellArray {
@@ -69726,6 +69920,8 @@ struct CellArray {
MemPage *pRef; /* Reference page */
u8 **apCell; /* All cells begin balanced */
u16 *szCell; /* Local size of all cells in apCell[] */
+ u8 *apEnd[NB*2]; /* MemPage.aDataEnd values */
+ int ixNx[NB*2]; /* Index of at which we move to the next apEnd[] */
};
/*
@@ -69776,37 +69972,59 @@ static u16 cachedCellSize(CellArray *p, int N){
** responsibility of the caller to set it correctly.
*/
static int rebuildPage(
- MemPage *pPg, /* Edit this page */
+ CellArray *pCArray, /* Content to be added to page pPg */
+ int iFirst, /* First cell in pCArray to use */
int nCell, /* Final number of cells on page */
- u8 **apCell, /* Array of cells */
- u16 *szCell /* Array of cell sizes */
+ MemPage *pPg /* The page to be reconstructed */
){
const int hdr = pPg->hdrOffset; /* Offset of header on pPg */
u8 * const aData = pPg->aData; /* Pointer to data for pPg */
const int usableSize = pPg->pBt->usableSize;
u8 * const pEnd = &aData[usableSize];
- int i;
+ int i = iFirst; /* Which cell to copy from pCArray*/
+ u32 j; /* Start of cell content area */
+ int iEnd = i+nCell; /* Loop terminator */
u8 *pCellptr = pPg->aCellIdx;
u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
u8 *pData;
+ int k; /* Current slot in pCArray->apEnd[] */
+ u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */
- i = get2byte(&aData[hdr+5]);
- memcpy(&pTmp[i], &aData[i], usableSize - i);
+ assert( i<iEnd );
+ j = get2byte(&aData[hdr+5]);
+ if( NEVER(j>(u32)usableSize) ){ j = 0; }
+ memcpy(&pTmp[j], &aData[j], usableSize - j);
+
+ for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
- for(i=0; i<nCell; i++){
- u8 *pCell = apCell[i];
+ while( 1/*exit by break*/ ){
+ u8 *pCell = pCArray->apCell[i];
+ u16 sz = pCArray->szCell[i];
+ assert( sz>0 );
if( SQLITE_WITHIN(pCell,aData,pEnd) ){
- if( ((uptr)(pCell+szCell[i]))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
+ if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
pCell = &pTmp[pCell - aData];
+ }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
+ && (uptr)(pCell)<(uptr)pSrcEnd
+ ){
+ return SQLITE_CORRUPT_BKPT;
}
- pData -= szCell[i];
+
+ pData -= sz;
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
- memcpy(pData, pCell, szCell[i]);
- assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
- testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
+ memcpy(pData, pCell, sz);
+ assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
+ testcase( sz!=pPg->xCellSize(pPg,pCell) );
+ i++;
+ if( i>=iEnd ) break;
+ if( pCArray->ixNx[k]<=i ){
+ k++;
+ pSrcEnd = pCArray->apEnd[k];
+ }
}
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
@@ -69821,12 +70039,11 @@ static int rebuildPage(
}
/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function attempts to
-** add the cells stored in the array to page pPg. If it cannot (because
-** the page needs to be defragmented before the cells will fit), non-zero
-** is returned. Otherwise, if the cells are added successfully, zero is
-** returned.
+** The pCArray objects contains pointers to b-tree cells and the cell sizes.
+** This function attempts to add the cells stored in the array to page pPg.
+** If it cannot (because the page needs to be defragmented before the cells
+** will fit), non-zero is returned. Otherwise, if the cells are added
+** successfully, zero is returned.
**
** Argument pCellptr points to the first entry in the cell-pointer array
** (part of page pPg) to populate. After cell apCell[0] is written to the
@@ -69848,18 +70065,23 @@ static int rebuildPage(
static int pageInsertArray(
MemPage *pPg, /* Page to add cells to */
u8 *pBegin, /* End of cell-pointer array */
- u8 **ppData, /* IN/OUT: Page content -area pointer */
+ u8 **ppData, /* IN/OUT: Page content-area pointer */
u8 *pCellptr, /* Pointer to cell-pointer area */
int iFirst, /* Index of first cell to add */
int nCell, /* Number of cells to add to pPg */
CellArray *pCArray /* Array of cells */
){
- int i;
- u8 *aData = pPg->aData;
- u8 *pData = *ppData;
- int iEnd = iFirst + nCell;
+ int i = iFirst; /* Loop counter - cell index to insert */
+ u8 *aData = pPg->aData; /* Complete page */
+ u8 *pData = *ppData; /* Content area. A subset of aData[] */
+ int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */
+ int k; /* Current slot in pCArray->apEnd[] */
+ u8 *pEnd; /* Maximum extent of cell data */
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
- for(i=iFirst; i<iEnd; i++){
+ if( iEnd<=iFirst ) return 0;
+ for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pEnd = pCArray->apEnd[k];
+ while( 1 /*Exit by break*/ ){
int sz, rc;
u8 *pSlot;
sz = cachedCellSize(pCArray, i);
@@ -69874,20 +70096,33 @@ static int pageInsertArray(
assert( (pSlot+sz)<=pCArray->apCell[i]
|| pSlot>=(pCArray->apCell[i]+sz)
|| CORRUPT_DB );
+ if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
+ && (uptr)(pCArray->apCell[i])<(uptr)pEnd
+ ){
+ assert( CORRUPT_DB );
+ (void)SQLITE_CORRUPT_BKPT;
+ return 1;
+ }
memmove(pSlot, pCArray->apCell[i], sz);
put2byte(pCellptr, (pSlot - aData));
pCellptr += 2;
+ i++;
+ if( i>=iEnd ) break;
+ if( pCArray->ixNx[k]<=i ){
+ k++;
+ pEnd = pCArray->apEnd[k];
+ }
}
*ppData = pData;
return 0;
}
/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function adds the
-** space associated with each cell in the array that is currently stored
-** within the body of pPg to the pPg free-list. The cell-pointers and other
-** fields of the page are not updated.
+** The pCArray object contains pointers to b-tree cells and their sizes.
+**
+** This function adds the space associated with each cell in the array
+** that is currently stored within the body of pPg to the pPg free-list.
+** The cell-pointers and other fields of the page are not updated.
**
** This function returns the total number of cells added to the free-list.
*/
@@ -69937,9 +70172,9 @@ static int pageFreeArray(
}
/*
-** apCell[] and szCell[] contains pointers to and sizes of all cells in the
-** pages being balanced. The current page, pPg, has pPg->nCell cells starting
-** with apCell[iOld]. After balancing, this page should hold nNew cells
+** pCArray contains pointers to and sizes of all cells in the page being
+** balanced. The current page, pPg, has pPg->nCell cells starting with
+** pCArray->apCell[iOld]. After balancing, this page should hold nNew cells
** starting at apCell[iNew].
**
** This routine makes the necessary adjustments to pPg so that it contains
@@ -69971,13 +70206,17 @@ static int editPage(
#endif
/* Remove cells from the start and end of the page */
+ assert( nCell>=0 );
if( iOld<iNew ){
int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
+ if( nShift>nCell ) return SQLITE_CORRUPT_BKPT;
memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
nCell -= nShift;
}
if( iNewEnd < iOldEnd ){
- nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+ int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+ assert( nCell>=nTail );
+ nCell -= nTail;
}
pData = &aData[get2byteNotZero(&aData[hdr+5])];
@@ -69987,6 +70226,7 @@ static int editPage(
if( iNew<iOld ){
int nAdd = MIN(nNew,iOld-iNew);
assert( (iOld-iNew)<nNew || nCell==0 || CORRUPT_DB );
+ assert( nAdd>=0 );
pCellptr = pPg->aCellIdx;
memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
if( pageInsertArray(
@@ -70001,6 +70241,7 @@ static int editPage(
int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
if( iCell>=0 && iCell<nNew ){
pCellptr = &pPg->aCellIdx[iCell * 2];
+ assert( nCell>=iCell );
memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
nCell++;
if( pageInsertArray(
@@ -70011,6 +70252,7 @@ static int editPage(
}
/* Append cells to the end of the page */
+ assert( nCell>=0 );
pCellptr = &pPg->aCellIdx[nCell*2];
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
@@ -70039,24 +70281,9 @@ static int editPage(
editpage_fail:
/* Unable to edit this page. Rebuild it from scratch instead. */
populateCellCache(pCArray, iNew, nNew);
- return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
+ return rebuildPage(pCArray, iNew, nNew, pPg);
}
-/*
-** The following parameters determine how many adjacent pages get involved
-** in a balancing operation. NN is the number of neighbors on either side
-** of the page that participate in the balancing operation. NB is the
-** total number of pages that participate, including the target page and
-** NN neighbors on either side.
-**
-** The minimum value of NN is 1 (of course). Increasing NN above 1
-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-** in exchange for a larger degradation in INSERT and UPDATE performance.
-** The value of NN appears to give the best results overall.
-*/
-#define NN 1 /* Number of neighbors on either side of pPage */
-#define NB (NN*2+1) /* Total pages involved in the balance */
-
#ifndef SQLITE_OMIT_QUICKBALANCE
/*
@@ -70106,12 +70333,22 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
u8 *pCell = pPage->apOvfl[0];
u16 szCell = pPage->xCellSize(pPage, pCell);
u8 *pStop;
+ CellArray b;
assert( sqlite3PagerIswriteable(pNew->pDbPage) );
- assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
+ assert( CORRUPT_DB || pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
- rc = rebuildPage(pNew, 1, &pCell, &szCell);
- if( NEVER(rc) ) return rc;
+ b.nCell = 1;
+ b.pRef = pPage;
+ b.apCell = &pCell;
+ b.szCell = &szCell;
+ b.apEnd[0] = pPage->aDataEnd;
+ b.ixNx[0] = 2;
+ rc = rebuildPage(&b, 0, 1, pNew);
+ if( NEVER(rc) ){
+ releasePage(pNew);
+ return rc;
+ }
pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
/* If this is an auto-vacuum database, update the pointer map
@@ -70589,8 +70826,15 @@ static int balance_nonroot(
**
*/
usableSpace = pBt->usableSize - 12 + leafCorrection;
- for(i=0; i<nOld; i++){
+ for(i=k=0; i<nOld; i++, k++){
MemPage *p = apOld[i];
+ b.apEnd[k] = p->aDataEnd;
+ b.ixNx[k] = cntOld[i];
+ if( !leafData ){
+ k++;
+ b.apEnd[k] = pParent->aDataEnd;
+ b.ixNx[k] = cntOld[i]+1;
+ }
szNew[i] = usableSpace - p->nFree;
for(j=0; j<p->nOverflow; j++){
szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
@@ -71272,7 +71516,11 @@ static int btreeOverwriteContent(
if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
int rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+ /* In a corrupt database, it is possible for the source and destination
+ ** buffers to overlap. This is harmless since the database is already
+ ** corrupt but it does cause valgrind and ASAN warnings. So use
+ ** memmove(). */
+ memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
}
}
return SQLITE_OK;
@@ -72452,7 +72700,7 @@ static void checkList(
checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0);
}
#endif
- if( n>(int)pCheck->pBt->usableSize/4-2 ){
+ if( n>pCheck->pBt->usableSize/4-2 ){
checkAppendMsg(pCheck,
"freelist leaf count too big on page %d", iPage);
N--;
@@ -72834,7 +73082,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
Pgno i;
IntegrityCk sCheck;
BtShared *pBt = p->pBt;
- int savedDbFlags = pBt->db->flags;
+ u64 savedDbFlags = pBt->db->flags;
char zErr[100];
VVA_ONLY( int nRef );
@@ -72901,7 +73149,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
}
#endif
testcase( pBt->db->flags & SQLITE_CellSizeCk );
- pBt->db->flags &= ~SQLITE_CellSizeCk;
+ pBt->db->flags &= ~(u64)SQLITE_CellSizeCk;
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
i64 notUsed;
if( aRoot[i]==0 ) continue;
@@ -74289,7 +74537,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre
** if unable to complete the resizing.
*/
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
- assert( szNew>0 );
+ assert( CORRUPT_DB || szNew>0 );
assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 );
if( pMem->szMalloc<szNew ){
return sqlite3VdbeMemGrow(pMem, szNew, 0);
@@ -75170,6 +75418,9 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
){
int rc;
pMem->flags = MEM_Null;
+ if( sqlite3BtreeMaxRecordSize(pCur)<offset+amt ){
+ return SQLITE_CORRUPT_BKPT;
+ }
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
if( rc==SQLITE_OK ){
@@ -75576,9 +75827,11 @@ static int valueFromExpr(
}
#endif
else if( op==TK_TRUEFALSE ){
- pVal = valueNew(db, pCtx);
- pVal->flags = MEM_Int;
- pVal->u.i = pExpr->u.zToken[4]==0;
+ pVal = valueNew(db, pCtx);
+ if( pVal ){
+ pVal->flags = MEM_Int;
+ pVal->u.i = pExpr->u.zToken[4]==0;
+ }
}
*ppVal = pVal;
@@ -75971,7 +76224,7 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
pParse->pVdbe = p;
assert( pParse->aLabel==0 );
assert( pParse->nLabel==0 );
- assert( pParse->nOpAlloc==0 );
+ assert( p->nOpAlloc==0 );
assert( pParse->szOpAlloc==0 );
sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
return p;
@@ -75999,14 +76252,44 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlag
}
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
+}
+
#ifdef SQLITE_ENABLE_NORMALIZE
- assert( p->zNormSql==0 );
- if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){
- sqlite3Normalize(p, p->zSql, n, prepFlags);
- assert( p->zNormSql!=0 || p->db->mallocFailed );
+/*
+** Add a new element to the Vdbe->pDblStr list.
+*/
+SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3 *db, Vdbe *p, const char *z){
+ if( p ){
+ int n = sqlite3Strlen30(z);
+ DblquoteStr *pStr = sqlite3DbMallocRawNN(db,
+ sizeof(*pStr)+n+1-sizeof(pStr->z));
+ if( pStr ){
+ pStr->pNextStr = p->pDblStr;
+ p->pDblStr = pStr;
+ memcpy(pStr->z, z, n+1);
+ }
}
+}
#endif
+
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** zId of length nId is a double-quoted identifier. Check to see if
+** that identifier is really used as a string literal.
+*/
+SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(
+ Vdbe *pVdbe, /* The prepared statement */
+ const char *zId /* The double-quoted identifier, already dequoted */
+){
+ DblquoteStr *pStr;
+ assert( zId!=0 );
+ if( pVdbe->pDblStr==0 ) return 0;
+ for(pStr=pVdbe->pDblStr; pStr; pStr=pStr->pNextStr){
+ if( strcmp(zId, pStr->z)==0 ) return 1;
+ }
+ return 0;
}
+#endif
/*
** Swap all content between two VDBE structures.
@@ -76027,7 +76310,7 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
-#ifdef SQLITE_ENABLE_NORMALIZE
+#if 0
zTmp = pA->zNormSql;
pA->zNormSql = pB->zNormSql;
pB->zNormSql = zTmp;
@@ -76044,7 +76327,7 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
** to 1024/sizeof(Op).
**
** If an out-of-memory error occurs while resizing the array, return
-** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain
+** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
** unchanged (this is so that any opcodes already allocated can be
** correctly deallocated along with the rest of the Vdbe).
*/
@@ -76060,9 +76343,9 @@ static int growOpArray(Vdbe *v, int nOp){
** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
** size of the op array or add 1KB of space, whichever is smaller. */
#ifdef SQLITE_TEST_REALLOC_STRESS
- int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
+ int nNew = (v->nOpAlloc>=512 ? v->nOpAlloc*2 : v->nOpAlloc+nOp);
#else
- int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
+ int nNew = (v->nOpAlloc ? v->nOpAlloc*2 : (int)(1024/sizeof(Op)));
UNUSED_PARAMETER(nOp);
#endif
@@ -76073,11 +76356,11 @@ static int growOpArray(Vdbe *v, int nOp){
}
assert( nOp<=(1024/sizeof(Op)) );
- assert( nNew>=(p->nOpAlloc+nOp) );
+ assert( nNew>=(v->nOpAlloc+nOp) );
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
if( pNew ){
p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
- p->nOpAlloc = p->szOpAlloc/sizeof(Op);
+ v->nOpAlloc = p->szOpAlloc/sizeof(Op);
v->aOp = pNew;
}
return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT);
@@ -76111,9 +76394,9 @@ static void test_addop_breakpoint(void){
** operand.
*/
static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
- assert( p->pParse->nOpAlloc<=p->nOp );
+ assert( p->nOpAlloc<=p->nOp );
if( growOpArray(p, 1) ) return 1;
- assert( p->pParse->nOpAlloc>p->nOp );
+ assert( p->nOpAlloc>p->nOp );
return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
}
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
@@ -76123,7 +76406,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
i = p->nOp;
assert( p->magic==VDBE_MAGIC_INIT );
assert( op>=0 && op<0xff );
- if( p->pParse->nOpAlloc<=i ){
+ if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
}
p->nOp++;
@@ -76255,13 +76538,29 @@ SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){
}
/*
-** Add a new OP_Explain opcode.
+** Set a debugger breakpoint on the following routine in order to
+** monitor the EXPLAIN QUERY PLAN code generation.
+*/
+#if defined(SQLITE_DEBUG)
+SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char *z1, const char *z2){
+ (void)z1;
+ (void)z2;
+}
+#endif
+
+/*
+** Add a new OP_ opcode.
**
** If the bPush flag is true, then make this opcode the parent for
** subsequent Explains until sqlite3VdbeExplainPop() is called.
*/
SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
- if( pParse->explain==2 ){
+#ifndef SQLITE_DEBUG
+ /* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined.
+ ** But omit them (for performance) during production builds */
+ if( pParse->explain==2 )
+#endif
+ {
char *zMsg;
Vdbe *v;
va_list ap;
@@ -76273,7 +76572,10 @@ SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt
iThis = v->nOp;
sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
zMsg, P4_DYNAMIC);
- if( bPush) pParse->addrExplain = iThis;
+ sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetOp(v,-1)->p4.z);
+ if( bPush){
+ pParse->addrExplain = iThis;
+ }
}
}
@@ -76281,6 +76583,7 @@ SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt
** Pop the EXPLAIN QUERY PLAN stack one level.
*/
SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse *pParse){
+ sqlite3ExplainBreakpoint("POP", 0);
pParse->addrExplain = sqlite3VdbeExplainParent(pParse);
}
#endif /* SQLITE_OMIT_EXPLAIN */
@@ -76345,21 +76648,22 @@ SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){
** The VDBE knows that a P2 value is a label because labels are
** always negative and P2 values are suppose to be non-negative.
** Hence, a negative P2 value is a label that has yet to be resolved.
+** (Later:) This is only true for opcodes that have the OPFLG_JUMP
+** property.
+**
+** Variable usage notes:
**
-** Zero is returned if a malloc() fails.
+** Parse.aLabel[x] Stores the address that the x-th label resolves
+** into. For testing (SQLITE_DEBUG), unresolved
+** labels stores -1, but that is not required.
+** Parse.nLabelAlloc Number of slots allocated to Parse.aLabel[]
+** Parse.nLabel The *negative* of the number of labels that have
+** been issued. The negative is stored because
+** that gives a performance improvement over storing
+** the equivalent positive value.
*/
-SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){
- Parse *p = v->pParse;
- int i = p->nLabel++;
- assert( v->magic==VDBE_MAGIC_INIT );
- if( (i & (i-1))==0 ){
- p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
- (i*2+1)*sizeof(p->aLabel[0]));
- }
- if( p->aLabel ){
- p->aLabel[i] = -1;
- }
- return ADDR(i);
+SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse *pParse){
+ return --pParse->nLabel;
}
/*
@@ -76367,18 +76671,35 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){
** be inserted. The parameter "x" must have been obtained from
** a prior call to sqlite3VdbeMakeLabel().
*/
+static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
+ int nNewSize = 10 - p->nLabel;
+ p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
+ nNewSize*sizeof(p->aLabel[0]));
+ if( p->aLabel==0 ){
+ p->nLabelAlloc = 0;
+ }else{
+#ifdef SQLITE_DEBUG
+ int i;
+ for(i=p->nLabelAlloc; i<nNewSize; i++) p->aLabel[i] = -1;
+#endif
+ p->nLabelAlloc = nNewSize;
+ p->aLabel[j] = v->nOp;
+ }
+}
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
Parse *p = v->pParse;
int j = ADDR(x);
assert( v->magic==VDBE_MAGIC_INIT );
- assert( j<p->nLabel );
+ assert( j<-p->nLabel );
assert( j>=0 );
- if( p->aLabel ){
#ifdef SQLITE_DEBUG
- if( p->db->flags & SQLITE_VdbeAddopTrace ){
- printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
- }
+ if( p->db->flags & SQLITE_VdbeAddopTrace ){
+ printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
+ }
#endif
+ if( p->nLabelAlloc + p->nLabel < 0 ){
+ resizeResolveLabel(p,v,j);
+ }else{
assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */
p->aLabel[j] = v->nOp;
}
@@ -76503,8 +76824,9 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
+ || opcode==OP_VDestroy
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
- && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
+ && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
hasAbort = 1;
break;
@@ -76653,7 +76975,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
** have non-negative values for P2. */
assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 );
- assert( ADDR(pOp->p2)<pParse->nLabel );
+ assert( ADDR(pOp->p2)<-pParse->nLabel );
pOp->p2 = aLabel[ADDR(pOp->p2)];
}
break;
@@ -76692,7 +77014,7 @@ SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
*/
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){
- assert( p->nOp + N <= p->pParse->nOpAlloc );
+ assert( p->nOp + N <= p->nOpAlloc );
}
#endif
@@ -76764,7 +77086,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(
VdbeOp *pOut, *pFirst;
assert( nOp>0 );
assert( p->magic==VDBE_MAGIC_INIT );
- if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
+ if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){
return 0;
}
pFirst = pOut = &p->aOp[p->nOp];
@@ -78086,19 +78408,27 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
** the leftover memory at the end of the opcode array. This can significantly
** reduce the amount of memory held by a prepared statement.
*/
- do {
- x.nNeeded = 0;
- p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
- p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
- p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
- p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
+ x.nNeeded = 0;
+ p->aMem = allocSpace(&x, 0, nMem*sizeof(Mem));
+ p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem));
+ p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*));
+ p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*));
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
+ p->anExec = allocSpace(&x, 0, p->nOp*sizeof(i64));
#endif
- if( x.nNeeded==0 ) break;
+ if( x.nNeeded ){
x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
x.nFree = x.nNeeded;
- }while( !db->mallocFailed );
+ if( !db->mallocFailed ){
+ p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
+ p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
+ p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
+ p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+ p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
+#endif
+ }
+ }
p->pVList = pParse->pVList;
pParse->pVList = 0;
@@ -78790,7 +79120,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
}else{
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
- db->flags &= ~SQLITE_DeferFKs;
+ db->flags &= ~(u64)SQLITE_DeferFKs;
sqlite3CommitInternalChanges(db);
}
}else{
@@ -79105,6 +79435,13 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
sqlite3DbFree(db, p->zSql);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3DbFree(db, p->zNormSql);
+ {
+ DblquoteStr *pThis, *pNext;
+ for(pThis=p->pDblStr; pThis; pThis=pNext){
+ pNext = pThis->pNextStr;
+ sqlite3DbFree(db, pThis);
+ }
+ }
#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
{
@@ -79645,7 +79982,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
UnpackedRecord *p /* Populate this structure before returning. */
){
const unsigned char *aKey = (const unsigned char *)pKey;
- int d;
+ u32 d;
u32 idx; /* Offset in aKey[] to read from */
u16 u; /* Unsigned loop counter */
u32 szHdr;
@@ -79656,7 +79993,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
idx = getVarint32(aKey, szHdr);
d = szHdr;
u = 0;
- while( idx<szHdr && d<=nKey ){
+ while( idx<szHdr && d<=(u32)nKey ){
u32 serial_type;
idx += getVarint32(&aKey[idx], serial_type);
@@ -79669,7 +80006,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
pMem++;
if( (++u)>=p->nField ) break;
}
- if( d>nKey && u ){
+ if( d>(u32)nKey && u ){
assert( CORRUPT_DB );
/* In a corrupt record entry, the last pMem might have been set up using
** uninitialized memory. Overwrite its value with NULL, to prevent
@@ -80890,14 +81227,16 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
sqlite3_int64 iNow;
sqlite3_int64 iElapse;
assert( p->startTime>0 );
- assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 );
+ assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
assert( db->init.busy==0 );
assert( p->zSql!=0 );
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
iElapse = (iNow - p->startTime)*1000000;
+#ifndef SQLITE_OMIT_DEPRECATED
if( db->xProfile ){
db->xProfile(db->pProfileArg, p->zSql, iElapse);
}
+#endif
if( db->mTrace & SQLITE_TRACE_PROFILE ){
db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
}
@@ -81411,7 +81750,7 @@ static int sqlite3Step(Vdbe *p){
return SQLITE_NOMEM_BKPT;
}
- if( p->pc<=0 && p->expired ){
+ if( p->pc<0 && p->expired ){
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
goto end_of_step;
@@ -81430,7 +81769,7 @@ static int sqlite3Step(Vdbe *p){
);
#ifndef SQLITE_OMIT_TRACE
- if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0)
+ if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
&& !db->init.busy && p->zSql ){
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
}else{
@@ -81457,16 +81796,18 @@ static int sqlite3Step(Vdbe *p){
db->nVdbeExec--;
}
+ if( rc!=SQLITE_ROW ){
#ifndef SQLITE_OMIT_TRACE
- /* If the statement completed successfully, invoke the profile callback */
- if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
+ /* If the statement completed successfully, invoke the profile callback */
+ checkProfileCallback(db, p);
#endif
- if( rc==SQLITE_DONE && db->autoCommit ){
- assert( p->rc==SQLITE_OK );
- p->rc = doWalCallbacks(db);
- if( p->rc!=SQLITE_OK ){
- rc = SQLITE_ERROR;
+ if( rc==SQLITE_DONE && db->autoCommit ){
+ assert( p->rc==SQLITE_OK );
+ p->rc = doWalCallbacks(db);
+ if( p->rc!=SQLITE_OK ){
+ rc = SQLITE_ERROR;
+ }
}
}
@@ -81486,9 +81827,9 @@ end_of_step:
|| (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
);
assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
- if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
- && rc!=SQLITE_ROW
+ if( rc!=SQLITE_ROW
&& rc!=SQLITE_DONE
+ && (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
){
/* If this statement was prepared using saved SQL and an
** error has occurred, then return the error code in p->rc to the
@@ -82110,7 +82451,7 @@ static int vdbeUnbind(Vdbe *p, int i){
pVar = &p->aVar[i];
sqlite3VdbeMemRelease(pVar);
pVar->flags = MEM_Null;
- sqlite3Error(p->db, SQLITE_OK);
+ p->db->errCode = SQLITE_OK;
/* If the bit corresponding to this variable in Vdbe.expmask is set, then
** binding a new value to this variable invalidates the current query plan.
@@ -82536,7 +82877,13 @@ SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
*/
SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
- return p ? p->zNormSql : 0;
+ if( p==0 ) return 0;
+ if( p->zNormSql==0 && ALWAYS(p->zSql!=0) ){
+ sqlite3_mutex_enter(p->db->mutex);
+ p->zNormSql = sqlite3Normalize(p, p->zSql);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return p->zNormSql;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
@@ -83236,6 +83583,11 @@ static VdbeCursor *allocateCursor(
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
+ /* Before calling sqlite3VdbeFreeCursor(), ensure the isEphemeral flag
+ ** is clear. Otherwise, if this is an ephemeral cursor created by
+ ** OP_OpenDup, the cursor will not be closed and will still be part
+ ** of a BtShared.pCursor list. */
+ p->apCsr[iCur]->isEphemeral = 0;
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
@@ -83376,6 +83728,7 @@ SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
assert( (pMem->flags & (MEM_Int|MEM_Real))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
+ ExpandBlob(pMem);
if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
return 0;
}
@@ -84663,8 +85016,8 @@ fp_math:
break;
}
default: {
- iA = (i64)rA;
- iB = (i64)rB;
+ iA = sqlite3VdbeIntValue(pIn1);
+ iB = sqlite3VdbeIntValue(pIn2);
if( iA==0 ) goto arithmetic_result_is_null;
if( iA==-1 ) iA = 1;
rB = (double)(iB % iA);
@@ -85010,7 +85363,8 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
*/
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
assert( (flags1 & MEM_Cleared)==0 );
- assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
+ assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB );
+ testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 );
if( (flags1&flags3&MEM_Null)!=0
&& (flags3&MEM_Cleared)==0
){
@@ -86694,7 +87048,8 @@ case OP_OpenDup: {
pCx->isEphemeral = 1;
pCx->pKeyInfo = pOrig->pKeyInfo;
pCx->isTable = pOrig->isTable;
- rc = sqlite3BtreeCursor(pOrig->pBtx, MASTER_ROOT, BTREE_WRCSR,
+ pCx->pgnoRoot = pOrig->pgnoRoot;
+ rc = sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pCx->pKeyInfo, pCx->uc.pCursor);
/* The sqlite3BtreeCursor() routine can only fail for the first cursor
** opened for a database. Since there is already an open cursor when this
@@ -86712,6 +87067,9 @@ case OP_OpenDup: {
** the main database is read-only. The ephemeral
** table is deleted automatically when the cursor is closed.
**
+** If the cursor P1 is already opened on an ephemeral table, the table
+** is cleared (all content is erased).
+**
** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
@@ -86743,41 +87101,50 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
- pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
- if( pCx==0 ) goto no_mem;
- pCx->nullRow = 1;
- pCx->isEphemeral = 1;
- rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
- BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
- }
- if( rc==SQLITE_OK ){
- /* If a transient index is required, create it by calling
- ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
- ** opening it. If a transient table is required, just use the
- ** automatically created table with root-page 1 (an BLOB_INTKEY table).
- */
- if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
- int pgno;
- assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5);
- if( rc==SQLITE_OK ){
- assert( pgno==MASTER_ROOT+1 );
- assert( pKeyInfo->db==db );
- assert( pKeyInfo->enc==ENC(db) );
- rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR,
- pKeyInfo, pCx->uc.pCursor);
+ pCx = p->apCsr[pOp->p1];
+ if( pCx ){
+ /* If the ephermeral table is already open, erase all existing content
+ ** so that the table is empty again, rather than creating a new table. */
+ rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
+ }else{
+ pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
+ if( pCx==0 ) goto no_mem;
+ pCx->nullRow = 1;
+ pCx->isEphemeral = 1;
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
+ BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5,
+ vfsFlags);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
+ }
+ if( rc==SQLITE_OK ){
+ /* If a transient index is required, create it by calling
+ ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
+ ** opening it. If a transient table is required, just use the
+ ** automatically created table with root-page 1 (an BLOB_INTKEY table).
+ */
+ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
+ assert( pOp->p4type==P4_KEYINFO );
+ rc = sqlite3BtreeCreateTable(pCx->pBtx, (int*)&pCx->pgnoRoot,
+ BTREE_BLOBKEY | pOp->p5);
+ if( rc==SQLITE_OK ){
+ assert( pCx->pgnoRoot==MASTER_ROOT+1 );
+ assert( pKeyInfo->db==db );
+ assert( pKeyInfo->enc==ENC(db) );
+ rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
+ pKeyInfo, pCx->uc.pCursor);
+ }
+ pCx->isTable = 0;
+ }else{
+ pCx->pgnoRoot = MASTER_ROOT;
+ rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR,
+ 0, pCx->uc.pCursor);
+ pCx->isTable = 1;
}
- pCx->isTable = 0;
- }else{
- rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR,
- 0, pCx->uc.pCursor);
- pCx->isTable = 1;
}
+ pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
}
if( rc ) goto abort_due_to_error;
- pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
break;
}
@@ -87427,7 +87794,7 @@ case OP_NotExists: /* jump, in3 */
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
- pC->seekOp = OP_SeekRowid;
+ if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid;
#endif
assert( pC->isTable );
assert( pC->eCurType==CURTYPE_BTREE );
@@ -88335,7 +88702,7 @@ case OP_Next: /* jump */
assert( pOp->opcode!=OP_Next
|| pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
- || pC->seekOp==OP_NullRow);
+ || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid);
assert( pOp->opcode!=OP_Prev
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|| pC->seekOp==OP_Last
@@ -88865,9 +89232,16 @@ case OP_ParseSchema: {
assert( db->init.busy==0 );
db->init.busy = 1;
initData.rc = SQLITE_OK;
+ initData.nInitRow = 0;
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_OK ) rc = initData.rc;
+ if( rc==SQLITE_OK && initData.nInitRow==0 ){
+ /* The OP_ParseSchema opcode with a non-NULL P4 argument should parse
+ ** at least one SQL statement. Any less than that indicates that
+ ** the sqlite_master table is corrupt. */
+ rc = SQLITE_CORRUPT_BKPT;
+ }
sqlite3DbFreeNN(db, zSql);
db->init.busy = 0;
}
@@ -89231,6 +89605,17 @@ case OP_Program: { /* jump */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
p->anExec = 0;
#endif
+#ifdef SQLITE_DEBUG
+ /* Verify that second and subsequent executions of the same trigger do not
+ ** try to reuse register values from the first use. */
+ {
+ int i;
+ for(i=0; i<p->nMem; i++){
+ aMem[i].pScopyFrom = 0; /* Prevent false-positive AboutToChange() errs */
+ aMem[i].flags |= MEM_Undefined; /* Cause a fault if this reg is reused */
+ }
+ }
+#endif
pOp = &aOp[-1];
break;
@@ -89769,14 +90154,19 @@ case OP_JournalMode: { /* out2 */
#endif /* SQLITE_OMIT_PRAGMA */
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
-/* Opcode: Vacuum P1 * * * *
+/* Opcode: Vacuum P1 P2 * * *
**
** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more
** for an attached database. The "temp" database may not be vacuumed.
+**
+** If P2 is not zero, then it is a register holding a string which is
+** the file into which the result of vacuum should be written. When
+** P2 is zero, the vacuum overwrites the original database.
*/
case OP_Vacuum: {
assert( p->readOnly==0 );
- rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1);
+ rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1,
+ pOp->p2 ? &aMem[pOp->p2] : 0);
if( rc ) goto abort_due_to_error;
break;
}
@@ -89928,6 +90318,7 @@ case OP_VDestroy: {
db->nVDestroy++;
rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
db->nVDestroy--;
+ assert( p->errorAction==OE_Abort && p->usesStmtJournal );
if( rc ) goto abort_due_to_error;
break;
}
@@ -90171,7 +90562,7 @@ case OP_VRename: {
rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
if( rc ) goto abort_due_to_error;
rc = pVtab->pModule->xRename(pVtab, pName->z);
- if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter;
+ if( isLegacy==0 ) db->flags &= ~(u64)SQLITE_LegacyAlter;
sqlite3VtabImportErrmsg(p, pVtab);
p->expired = 0;
if( rc ) goto abort_due_to_error;
@@ -94398,6 +94789,22 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
/* #include <string.h> */
+#if !defined(SQLITE_OMIT_WINDOWFUNC)
+/*
+** Walk all expressions linked into the list of Window objects passed
+** as the second argument.
+*/
+static int walkWindowList(Walker *pWalker, Window *pList){
+ Window *pWin;
+ for(pWin=pList; pWin; pWin=pWin->pNextWin){
+ if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
+ }
+ return WRC_Continue;
+}
+#endif
+
/*
** Walk an expression tree. Invoke the callback once for each node
** of the expression, while descending. (In other words, the callback
@@ -94437,10 +94844,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
- Window *pWin = pExpr->y.pWin;
- if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
- if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
+ if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
}
#endif
}
@@ -94480,6 +94884,16 @@ SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
+#if !defined(SQLITE_OMIT_WINDOWFUNC) && !defined(SQLITE_OMIT_ALTERTABLE)
+ {
+ Parse *pParse = pWalker->pParse;
+ if( pParse && IN_RENAME_OBJECT ){
+ int rc = walkWindowList(pWalker, p->pWinDefn);
+ assert( rc==WRC_Continue );
+ return rc;
+ }
+ }
+#endif
return WRC_Continue;
}
@@ -94631,7 +95045,6 @@ static void resolveAlias(
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
- ExprSetProperty(pDup, EP_Alias);
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
@@ -95025,6 +95438,25 @@ static int lookupName(
if( cnt==0 && zTab==0 ){
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
+ /* If a double-quoted identifier does not match any known column name,
+ ** then treat it as a string.
+ **
+ ** This hack was added in the early days of SQLite in a misguided attempt
+ ** to be compatible with MySQL 3.x, which used double-quotes for strings.
+ ** I now sorely regret putting in this hack. The effect of this hack is
+ ** that misspelled identifier names are silently converted into strings
+ ** rather than causing an error, to the frustration of countless
+ ** programmers. To all those frustrated programmers, my apologies.
+ **
+ ** Someday, I hope to get rid of this hack. Unfortunately there is
+ ** a huge amount of legacy SQL that uses it. So for now, we just
+ ** issue a warning.
+ */
+ sqlite3_log(SQLITE_WARNING,
+ "double-quoted string literal: \"%w\"", zCol);
+#ifdef SQLITE_ENABLE_NORMALIZE
+ sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
+#endif
pExpr->op = TK_STRING;
pExpr->y.pTab = 0;
return WRC_Prune;
@@ -95391,10 +95823,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pExpr->y.pWin ){
Select *pSel = pNC->pWinSelect;
+ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
- sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
if( 0==pSel->pWin
|| 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin)
){
@@ -95671,32 +96103,53 @@ static int resolveCompoundOrderBy(
}else{
iCol = resolveAsName(pParse, pEList, pE);
if( iCol==0 ){
- pDup = sqlite3ExprDup(db, pE, 0);
+ /* Now test if expression pE matches one of the values returned
+ ** by pSelect. In the usual case this is done by duplicating the
+ ** expression, resolving any symbols in it, and then comparing
+ ** it against each expression returned by the SELECT statement.
+ ** Once the comparisons are finished, the duplicate expression
+ ** is deleted.
+ **
+ ** Or, if this is running as part of an ALTER TABLE operation,
+ ** resolve the symbols in the actual expression, not a duplicate.
+ ** And, if one of the comparisons is successful, leave the expression
+ ** as is instead of transforming it to an integer as in the usual
+ ** case. This allows the code in alter.c to modify column
+ ** refererences within the ORDER BY expression as required. */
+ if( IN_RENAME_OBJECT ){
+ pDup = pE;
+ }else{
+ pDup = sqlite3ExprDup(db, pE, 0);
+ }
if( !db->mallocFailed ){
assert(pDup);
iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
}
- sqlite3ExprDelete(db, pDup);
+ if( !IN_RENAME_OBJECT ){
+ sqlite3ExprDelete(db, pDup);
+ }
}
}
if( iCol>0 ){
/* Convert the ORDER BY term into an integer column number iCol,
** taking care to preserve the COLLATE clause if it exists */
- Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
- if( pNew==0 ) return 1;
- pNew->flags |= EP_IntValue;
- pNew->u.iValue = iCol;
- if( pItem->pExpr==pE ){
- pItem->pExpr = pNew;
- }else{
- Expr *pParent = pItem->pExpr;
- assert( pParent->op==TK_COLLATE );
- while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
- assert( pParent->pLeft==pE );
- pParent->pLeft = pNew;
+ if( !IN_RENAME_OBJECT ){
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+ if( pNew==0 ) return 1;
+ pNew->flags |= EP_IntValue;
+ pNew->u.iValue = iCol;
+ if( pItem->pExpr==pE ){
+ pItem->pExpr = pNew;
+ }else{
+ Expr *pParent = pItem->pExpr;
+ assert( pParent->op==TK_COLLATE );
+ while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
+ assert( pParent->pLeft==pE );
+ pParent->pLeft = pNew;
+ }
+ sqlite3ExprDelete(db, pE);
+ pItem->u.x.iOrderByCol = (u16)iCol;
}
- sqlite3ExprDelete(db, pE);
- pItem->u.x.iOrderByCol = (u16)iCol;
pItem->done = 1;
}else{
moreToDo = 1;
@@ -96045,6 +96498,19 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( IN_RENAME_OBJECT ){
+ Window *pWin;
+ for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
+ if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
+ || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
+ ){
+ return WRC_Abort;
+ }
+ }
+ }
+#endif
+
/* If this is part of a compound SELECT, check that it has the right
** number of expressions in the select list. */
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
@@ -96195,38 +96661,47 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
}
/*
-** Resolve names in expressions that can only reference a single table:
+** Resolve names in expressions that can only reference a single table
+** or which cannot reference any tables at all. Examples:
**
-** * CHECK constraints
-** * WHERE clauses on partial indices
+** (1) CHECK constraints
+** (2) WHERE clauses on partial indices
+** (3) Expressions in indexes on expressions
+** (4) Expression arguments to VACUUM INTO.
**
-** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression
-** is set to -1 and the Expr.iColumn value is set to the column number.
+** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN
+** nodes of the expression is set to -1 and the Expr.iColumn value is
+** set to the column number. In case (4), TK_COLUMN nodes cause an error.
**
** Any errors cause an error message to be set in pParse.
*/
-SQLITE_PRIVATE void sqlite3ResolveSelfReference(
+SQLITE_PRIVATE int sqlite3ResolveSelfReference(
Parse *pParse, /* Parsing context */
- Table *pTab, /* The table being referenced */
- int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */
+ Table *pTab, /* The table being referenced, or NULL */
+ int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr, or 0 */
Expr *pExpr, /* Expression to resolve. May be NULL. */
ExprList *pList /* Expression list to resolve. May be NULL. */
){
SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
NameContext sNC; /* Name context for pParse->pNewTable */
+ int rc;
- assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr );
+ assert( type==0 || pTab!=0 );
+ assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr || pTab==0 );
memset(&sNC, 0, sizeof(sNC));
memset(&sSrc, 0, sizeof(sSrc));
- sSrc.nSrc = 1;
- sSrc.a[0].zName = pTab->zName;
- sSrc.a[0].pTab = pTab;
- sSrc.a[0].iCursor = -1;
+ if( pTab ){
+ sSrc.nSrc = 1;
+ sSrc.a[0].zName = pTab->zName;
+ sSrc.a[0].pTab = pTab;
+ sSrc.a[0].iCursor = -1;
+ }
sNC.pParse = pParse;
sNC.pSrcList = &sSrc;
sNC.ncFlags = type;
- if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
- if( pList ) sqlite3ResolveExprListNames(&sNC, pList);
+ if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
+ if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
+ return rc;
}
/************** End of resolve.c *********************************************/
@@ -96698,6 +97173,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
}else{
if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
pRet = sqlite3ExprDup(pParse->db, pVector, 0);
+ sqlite3RenameTokenRemap(pParse, pRet, pVector);
}
return pRet;
}
@@ -96714,7 +97190,7 @@ static int exprCodeSubselect(Parse *pParse, Expr *pExpr){
int reg = 0;
#ifndef SQLITE_OMIT_SUBQUERY
if( pExpr->op==TK_SELECT ){
- reg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
+ reg = sqlite3CodeSubselect(pParse, pExpr);
}
#endif
return reg;
@@ -96786,7 +97262,7 @@ static void codeVectorCompare(
int regLeft = 0;
int regRight = 0;
u8 opx = op;
- int addrDone = sqlite3VdbeMakeLabel(v);
+ int addrDone = sqlite3VdbeMakeLabel(pParse);
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
@@ -97013,8 +97489,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
pNew->u.zToken[pToken->n] = 0;
if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){
- if( pNew->u.zToken[0]=='"' ) pNew->flags |= EP_DblQuoted;
- sqlite3Dequote(pNew->u.zToken);
+ sqlite3DequoteExpr(pNew);
}
}
}
@@ -97083,7 +97558,7 @@ SQLITE_PRIVATE Expr *sqlite3PExpr(
Expr *pRight /* Right operand */
){
Expr *p;
- if( op==TK_AND && pParse->nErr==0 ){
+ if( op==TK_AND && pParse->nErr==0 && !IN_RENAME_OBJECT ){
/* Take advantage of short-circuit false optimization for AND */
p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
}else{
@@ -97333,6 +97808,16 @@ static int exprStructSize(Expr *p){
}
/*
+** Copy the complete content of an Expr node, taking care not to read
+** past the end of the structure for a reduced-size version of the source
+** Expr.
+*/
+static void exprNodeCopy(Expr *pDest, Expr *pSrc){
+ memset(pDest, 0, sizeof(Expr));
+ memcpy(pDest, pSrc, exprStructSize(pSrc));
+}
+
+/*
** The dupedExpr*Size() routines each return the number of bytes required
** to store a copy of an expression or expression tree. They differ in
** how much of the tree is measured.
@@ -97563,6 +98048,36 @@ static With *withDup(sqlite3 *db, With *p){
# define withDup(x,y) 0
#endif
+#ifndef SQLITE_OMIT_WINDOWFUNC
+/*
+** The gatherSelectWindows() procedure and its helper routine
+** gatherSelectWindowsCallback() are used to scan all the expressions
+** an a newly duplicated SELECT statement and gather all of the Window
+** objects found there, assembling them onto the linked list at Select->pWin.
+*/
+static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_FUNCTION && pExpr->y.pWin!=0 ){
+ assert( ExprHasProperty(pExpr, EP_WinFunc) );
+ pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin;
+ pWalker->u.pSelect->pWin = pExpr->y.pWin;
+ }
+ return WRC_Continue;
+}
+static int gatherSelectWindowsSelectCallback(Walker *pWalker, Select *p){
+ return p==pWalker->u.pSelect ? WRC_Continue : WRC_Prune;
+}
+static void gatherSelectWindows(Select *p){
+ Walker w;
+ w.xExprCallback = gatherSelectWindowsCallback;
+ w.xSelectCallback = gatherSelectWindowsSelectCallback;
+ w.xSelectCallback2 = 0;
+ w.pParse = 0;
+ w.u.pSelect = p;
+ sqlite3WalkSelect(&w, p);
+}
+#endif
+
+
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
@@ -97730,6 +98245,7 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
#ifndef SQLITE_OMIT_WINDOWFUNC
pNew->pWin = 0;
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
+ if( p->pWin ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
*pp = pNew;
@@ -97862,6 +98378,9 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(
}
vector_append_error:
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameExprUnmap(pParse, pExpr);
+ }
sqlite3ExprDelete(db, pExpr);
sqlite3IdListDelete(db, pColumns);
return pList;
@@ -98005,8 +98524,9 @@ SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
*/
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){
assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
- if( sqlite3StrICmp(pExpr->u.zToken, "true")==0
- || sqlite3StrICmp(pExpr->u.zToken, "false")==0
+ if( !ExprHasProperty(pExpr, EP_Quoted)
+ && (sqlite3StrICmp(pExpr->u.zToken, "true")==0
+ || sqlite3StrICmp(pExpr->u.zToken, "false")==0)
){
pExpr->op = TK_TRUEFALSE;
return 1;
@@ -98315,7 +98835,9 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
*/
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
u8 op;
- while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
+ while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
+ p = p->pLeft;
+ }
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
switch( op ){
@@ -98382,14 +98904,6 @@ SQLITE_PRIVATE int sqlite3IsRowid(const char *z){
if( sqlite3StrICmp(z, "OID")==0 ) return 1;
return 0;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-SQLITE_PRIVATE int sqlite3IsRowidN(const char *z, int n){
- if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1;
- if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1;
- if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1;
- return 0;
-}
-#endif
/*
** pX is the RHS of an IN operator. If pX is a SELECT statement
@@ -98559,7 +99073,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
Expr *pX, /* The right-hand side (RHS) of the IN operator */
u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
int *prRhsHasNull, /* Register holding NULL status. See notes */
- int *aiMap /* Mapping from Index fields to RHS fields */
+ int *aiMap, /* Mapping from Index fields to RHS fields */
+ int *piTab /* OUT: index to use */
){
Select *p; /* SELECT to the right of IN operator */
int eType = 0; /* Type of RHS table. IN_INDEX_* */
@@ -98654,6 +99169,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
Bitmask colUsed; /* Columns of the index used */
Bitmask mCol; /* Mask for the current column */
if( pIdx->nColumn<nExpr ) continue;
+ if( pIdx->pPartIdxWhere!=0 ) continue;
/* Maximum nColumn is BMS-2, not BMS-1, so that we can compute
** BITMASK(nExpr) without overflowing */
testcase( pIdx->nColumn==BMS-2 );
@@ -98750,10 +99266,12 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
}else if( prRhsHasNull ){
*prRhsHasNull = rMayHaveNull = ++pParse->nMem;
}
- sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
+ assert( pX->op==TK_IN );
+ sqlite3CodeRhsOfIN(pParse, pX, iTab, eType==IN_INDEX_ROWID);
+ if( rMayHaveNull ){
+ sqlite3SetHasNullFlag(v, iTab, rMayHaveNull);
+ }
pParse->nQueryLoop = savedNQueryLoop;
- }else{
- pX->iTable = iTab;
}
if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){
@@ -98761,6 +99279,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
n = sqlite3ExprVectorSize(pX->pLeft);
for(i=0; i<n; i++) aiMap[i] = i;
}
+ *piTab = iTab;
return eType;
}
#endif
@@ -98834,260 +99353,326 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
}
}
+#ifndef SQLITE_OMIT_SUBQUERY
/*
-** Generate code for scalar subqueries used as a subquery expression, EXISTS,
-** or IN operators. Examples:
+** Generate code that will construct an ephemeral table containing all terms
+** in the RHS of an IN operator. The IN operator can be in either of two
+** forms:
**
-** (SELECT a FROM b) -- subquery
-** EXISTS (SELECT a FROM b) -- EXISTS subquery
** x IN (4,5,11) -- IN operator with list on right-hand side
** x IN (SELECT a FROM b) -- IN operator with subquery on the right
**
-** The pExpr parameter describes the expression that contains the IN
-** operator or subquery.
-**
-** If parameter isRowid is non-zero, then expression pExpr is guaranteed
-** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
-** to some integer key column of a table B-Tree. In this case, use an
-** intkey B-Tree to store the set of IN(...) values instead of the usual
-** (slower) variable length keys B-Tree.
-**
-** If rMayHaveNull is non-zero, that means that the operation is an IN
-** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
-** All this routine does is initialize the register given by rMayHaveNull
-** to NULL. Calling routines will take care of changing this register
-** value to non-NULL if the RHS is NULL-free.
-**
-** For a SELECT or EXISTS operator, return the register that holds the
-** result. For a multi-column SELECT, the result is stored in a contiguous
-** array of registers and the return value is the register of the left-most
-** result column. Return 0 for IN operators or if an error occurs.
-*/
-#ifndef SQLITE_OMIT_SUBQUERY
-SQLITE_PRIVATE int sqlite3CodeSubselect(
+** The pExpr parameter is the IN operator. The cursor number for the
+** constructed ephermeral table is returned. The first time the ephemeral
+** table is computed, the cursor number is also stored in pExpr->iTable,
+** however the cursor number returned might not be the same, as it might
+** have been duplicated using OP_OpenDup.
+**
+** If parameter isRowid is non-zero, then LHS of the IN operator is guaranteed
+** to be a non-null integer. In this case, the ephemeral table can be an
+** table B-Tree that keyed by only integers. The more general cases uses
+** an index B-Tree which can have arbitrary keys, but is slower to both
+** read and write.
+**
+** If the LHS expression ("x" in the examples) is a column value, or
+** the SELECT statement returns a column value, then the affinity of that
+** column is used to build the index keys. If both 'x' and the
+** SELECT... statement are columns, then numeric affinity is used
+** if either column has NUMERIC or INTEGER affinity. If neither
+** 'x' nor the SELECT... statement are columns, then numeric affinity
+** is used.
+*/
+SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
Parse *pParse, /* Parsing context */
- Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
- int rHasNullFlag, /* Register that records whether NULLs exist in RHS */
- int isRowid /* If true, LHS of IN operator is a rowid */
+ Expr *pExpr, /* The IN operator */
+ int iTab, /* Use this cursor number */
+ int isRowid /* If true, LHS is a rowid */
){
- int jmpIfDynamic = -1; /* One-time test address */
- int rReg = 0; /* Register storing resulting */
- Vdbe *v = sqlite3GetVdbe(pParse);
- if( NEVER(v==0) ) return 0;
+ int addrOnce = 0; /* Address of the OP_Once instruction at top */
+ int addr; /* Address of OP_OpenEphemeral instruction */
+ Expr *pLeft; /* the LHS of the IN operator */
+ KeyInfo *pKeyInfo = 0; /* Key information */
+ int nVal; /* Size of vector pLeft */
+ Vdbe *v; /* The prepared statement under construction */
- /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it
+ v = pParse->pVdbe;
+ assert( v!=0 );
+
+ /* The evaluation of the IN must be repeated every time it
** is encountered if any of the following is true:
**
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * We are inside a trigger
**
- ** If all of the above are false, then we can run this code just once
- ** save the results, and reuse the same result on subsequent invocations.
+ ** If all of the above are false, then we can compute the RHS just once
+ ** and reuse it many names.
*/
- if( !ExprHasProperty(pExpr, EP_VarSelect) ){
- jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
+ if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
+ /* Reuse of the RHS is allowed */
+ /* If this routine has already been coded, but the previous code
+ ** might not have been invoked yet, so invoke it now as a subroutine.
+ */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
+ pExpr->x.pSelect->selId));
+ }
+ sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
+ pExpr->y.sub.iAddr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
+ sqlite3VdbeJumpHere(v, addrOnce);
+ return;
+ }
+
+ /* Begin coding the subroutine */
+ ExprSetProperty(pExpr, EP_Subrtn);
+ pExpr->y.sub.regReturn = ++pParse->nMem;
+ pExpr->y.sub.iAddr =
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
+ VdbeComment((v, "return address"));
+
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
- switch( pExpr->op ){
- case TK_IN: {
- int addr; /* Address of OP_OpenEphemeral instruction */
- Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
- KeyInfo *pKeyInfo = 0; /* Key information */
- int nVal; /* Size of vector pLeft */
-
- nVal = sqlite3ExprVectorSize(pLeft);
- assert( !isRowid || nVal==1 );
-
- /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
- ** expression it is handled the same way. An ephemeral table is
- ** filled with index keys representing the results from the
- ** SELECT or the <exprlist>.
- **
- ** If the 'x' expression is a column value, or the SELECT...
- ** statement returns a column value, then the affinity of that
- ** column is used to build the index keys. If both 'x' and the
- ** SELECT... statement are columns, then numeric affinity is used
- ** if either column has NUMERIC or INTEGER affinity. If neither
- ** 'x' nor the SELECT... statement are columns, then numeric affinity
- ** is used.
- */
- pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral,
- pExpr->iTable, (isRowid?0:nVal));
- pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
+ /* Check to see if this is a vector IN operator */
+ pLeft = pExpr->pLeft;
+ nVal = sqlite3ExprVectorSize(pLeft);
+ assert( !isRowid || nVal==1 );
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- /* Case 1: expr IN (SELECT ...)
- **
- ** Generate code to write the results of the select into the temporary
- ** table allocated and opened above.
- */
- Select *pSelect = pExpr->x.pSelect;
- ExprList *pEList = pSelect->pEList;
-
- ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY",
- jmpIfDynamic>=0?"":"CORRELATED "
- ));
- assert( !isRowid );
- /* If the LHS and RHS of the IN operator do not match, that
- ** error will have been caught long before we reach this point. */
- if( ALWAYS(pEList->nExpr==nVal) ){
- SelectDest dest;
- int i;
- sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
- dest.zAffSdst = exprINAffinity(pParse, pExpr);
- pSelect->iLimit = 0;
- testcase( pSelect->selFlags & SF_Distinct );
- testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
- if( sqlite3Select(pParse, pSelect, &dest) ){
- sqlite3DbFree(pParse->db, dest.zAffSdst);
- sqlite3KeyInfoUnref(pKeyInfo);
- return 0;
- }
- sqlite3DbFree(pParse->db, dest.zAffSdst);
- assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
- assert( pEList!=0 );
- assert( pEList->nExpr>0 );
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- for(i=0; i<nVal; i++){
- Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
- pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
- pParse, p, pEList->a[i].pExpr
- );
- }
- }
- }else if( ALWAYS(pExpr->x.pList!=0) ){
- /* Case 2: expr IN (exprlist)
- **
- ** For each expression, build an index key from the evaluation and
- ** store it in the temporary table. If <expr> is a column, then use
- ** that columns affinity when building index keys. If <expr> is not
- ** a column, use numeric affinity.
- */
- char affinity; /* Affinity of the LHS of the IN */
- int i;
- ExprList *pList = pExpr->x.pList;
- struct ExprList_item *pItem;
- int r1, r2, r3;
- affinity = sqlite3ExprAffinity(pLeft);
- if( !affinity ){
- affinity = SQLITE_AFF_BLOB;
- }
- if( pKeyInfo ){
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- }
+ /* Construct the ephemeral table that will contain the content of
+ ** RHS of the IN operator.
+ */
+ pExpr->iTable = iTab;
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral,
+ pExpr->iTable, (isRowid?0:nVal));
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
+ }else{
+ VdbeComment((v, "RHS of IN operator"));
+ }
+#endif
+ pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
- /* Loop through each expression in <exprlist>. */
- r1 = sqlite3GetTempReg(pParse);
- r2 = sqlite3GetTempReg(pParse);
- if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
- for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
- Expr *pE2 = pItem->pExpr;
- int iValToIns;
-
- /* If the expression is not constant then we will need to
- ** disable the test that was generated above that makes sure
- ** this code only executes once. Because for a non-constant
- ** expression we need to rerun this code each time.
- */
- if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){
- sqlite3VdbeChangeToNoop(v, jmpIfDynamic);
- jmpIfDynamic = -1;
- }
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ /* Case 1: expr IN (SELECT ...)
+ **
+ ** Generate code to write the results of the select into the temporary
+ ** table allocated and opened above.
+ */
+ Select *pSelect = pExpr->x.pSelect;
+ ExprList *pEList = pSelect->pEList;
- /* Evaluate the expression and insert it into the temp table */
- if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
- sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
- }else{
- r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
- if( isRowid ){
- sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
- sqlite3VdbeCurrentAddr(v)+2);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
- }else{
- sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
- }
- }
- }
- sqlite3ReleaseTempReg(pParse, r1);
- sqlite3ReleaseTempReg(pParse, r2);
+ ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d",
+ addrOnce?"":"CORRELATED ", pSelect->selId
+ ));
+ assert( !isRowid );
+ /* If the LHS and RHS of the IN operator do not match, that
+ ** error will have been caught long before we reach this point. */
+ if( ALWAYS(pEList->nExpr==nVal) ){
+ SelectDest dest;
+ int i;
+ sqlite3SelectDestInit(&dest, SRT_Set, iTab);
+ dest.zAffSdst = exprINAffinity(pParse, pExpr);
+ pSelect->iLimit = 0;
+ testcase( pSelect->selFlags & SF_Distinct );
+ testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
+ if( sqlite3Select(pParse, pSelect, &dest) ){
+ sqlite3DbFree(pParse->db, dest.zAffSdst);
+ sqlite3KeyInfoUnref(pKeyInfo);
+ return;
}
- if( pKeyInfo ){
- sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
+ sqlite3DbFree(pParse->db, dest.zAffSdst);
+ assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
+ assert( pEList!=0 );
+ assert( pEList->nExpr>0 );
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ for(i=0; i<nVal; i++){
+ Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
+ pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
+ pParse, p, pEList->a[i].pExpr
+ );
}
- break;
+ }
+ }else if( ALWAYS(pExpr->x.pList!=0) ){
+ /* Case 2: expr IN (exprlist)
+ **
+ ** For each expression, build an index key from the evaluation and
+ ** store it in the temporary table. If <expr> is a column, then use
+ ** that columns affinity when building index keys. If <expr> is not
+ ** a column, use numeric affinity.
+ */
+ char affinity; /* Affinity of the LHS of the IN */
+ int i;
+ ExprList *pList = pExpr->x.pList;
+ struct ExprList_item *pItem;
+ int r1, r2, r3;
+ affinity = sqlite3ExprAffinity(pLeft);
+ if( !affinity ){
+ affinity = SQLITE_AFF_BLOB;
+ }
+ if( pKeyInfo ){
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
}
- case TK_EXISTS:
- case TK_SELECT:
- default: {
- /* Case 3: (SELECT ... FROM ...)
- ** or: EXISTS(SELECT ... FROM ...)
- **
- ** For a SELECT, generate code to put the values for all columns of
- ** the first row into an array of registers and return the index of
- ** the first register.
- **
- ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists)
- ** into a register and return that register number.
- **
- ** In both cases, the query is augmented with "LIMIT 1". Any
- ** preexisting limit is discarded in place of the new LIMIT 1.
+ /* Loop through each expression in <exprlist>. */
+ r1 = sqlite3GetTempReg(pParse);
+ r2 = sqlite3GetTempReg(pParse);
+ if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
+ for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
+ Expr *pE2 = pItem->pExpr;
+ int iValToIns;
+
+ /* If the expression is not constant then we will need to
+ ** disable the test that was generated above that makes sure
+ ** this code only executes once. Because for a non-constant
+ ** expression we need to rerun this code each time.
*/
- Select *pSel; /* SELECT statement to encode */
- SelectDest dest; /* How to deal with SELECT result */
- int nReg; /* Registers to allocate */
- Expr *pLimit; /* New limit expression */
-
- testcase( pExpr->op==TK_EXISTS );
- testcase( pExpr->op==TK_SELECT );
- assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
- assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+ if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
+ sqlite3VdbeChangeToNoop(v, addrOnce);
+ addrOnce = 0;
+ }
- pSel = pExpr->x.pSelect;
- ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
- jmpIfDynamic>=0?"":"CORRELATED "));
- nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
- sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
- pParse->nMem += nReg;
- if( pExpr->op==TK_SELECT ){
- dest.eDest = SRT_Mem;
- dest.iSdst = dest.iSDParm;
- dest.nSdst = nReg;
- sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
- VdbeComment((v, "Init subquery result"));
- }else{
- dest.eDest = SRT_Exists;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
- VdbeComment((v, "Init EXISTS result"));
- }
- pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
- if( pSel->pLimit ){
- sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
- pSel->pLimit->pLeft = pLimit;
+ /* Evaluate the expression and insert it into the temp table */
+ if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
+ sqlite3VdbeAddOp3(v, OP_InsertInt, iTab, r2, iValToIns);
}else{
- pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
- }
- pSel->iLimit = 0;
- if( sqlite3Select(pParse, pSel, &dest) ){
- return 0;
+ r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
+ if( isRowid ){
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
+ sqlite3VdbeCurrentAddr(v)+2);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp3(v, OP_Insert, iTab, r2, r3);
+ }else{
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1);
+ }
}
- rReg = dest.iSDParm;
- ExprSetVVAProperty(pExpr, EP_NoReduce);
- break;
}
+ sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3ReleaseTempReg(pParse, r2);
+ }
+ if( pKeyInfo ){
+ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
+ }
+ if( addrOnce ){
+ sqlite3VdbeJumpHere(v, addrOnce);
+ /* Subroutine return */
+ sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
+ sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
+ }
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
+
+/*
+** Generate code for scalar subqueries used as a subquery expression
+** or EXISTS operator:
+**
+** (SELECT a FROM b) -- subquery
+** EXISTS (SELECT a FROM b) -- EXISTS subquery
+**
+** The pExpr parameter is the SELECT or EXISTS operator to be coded.
+**
+** The register that holds the result. For a multi-column SELECT,
+** the result is stored in a contiguous array of registers and the
+** return value is the register of the left-most result column.
+** Return 0 if an error occurs.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
+ int addrOnce = 0; /* Address of OP_Once at top of subroutine */
+ int rReg = 0; /* Register storing resulting */
+ Select *pSel; /* SELECT statement to encode */
+ SelectDest dest; /* How to deal with SELECT result */
+ int nReg; /* Registers to allocate */
+ Expr *pLimit; /* New limit expression */
+
+ Vdbe *v = pParse->pVdbe;
+ assert( v!=0 );
+ testcase( pExpr->op==TK_EXISTS );
+ testcase( pExpr->op==TK_SELECT );
+ assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
+ assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+ pSel = pExpr->x.pSelect;
+
+ /* The evaluation of the EXISTS/SELECT must be repeated every time it
+ ** is encountered if any of the following is true:
+ **
+ ** * The right-hand side is a correlated subquery
+ ** * The right-hand side is an expression list containing variables
+ ** * We are inside a trigger
+ **
+ ** If all of the above are false, then we can run this code just once
+ ** save the results, and reuse the same result on subsequent invocations.
+ */
+ if( !ExprHasProperty(pExpr, EP_VarSelect) ){
+ /* If this routine has already been coded, then invoke it as a
+ ** subroutine. */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId));
+ sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
+ pExpr->y.sub.iAddr);
+ return pExpr->iTable;
+ }
+
+ /* Begin coding the subroutine */
+ ExprSetProperty(pExpr, EP_Subrtn);
+ pExpr->y.sub.regReturn = ++pParse->nMem;
+ pExpr->y.sub.iAddr =
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
+ VdbeComment((v, "return address"));
+
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
- if( rHasNullFlag ){
- sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag);
+ /* For a SELECT, generate code to put the values for all columns of
+ ** the first row into an array of registers and return the index of
+ ** the first register.
+ **
+ ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists)
+ ** into a register and return that register number.
+ **
+ ** In both cases, the query is augmented with "LIMIT 1". Any
+ ** preexisting limit is discarded in place of the new LIMIT 1.
+ */
+ ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY %d",
+ addrOnce?"":"CORRELATED ", pSel->selId));
+ nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
+ sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
+ pParse->nMem += nReg;
+ if( pExpr->op==TK_SELECT ){
+ dest.eDest = SRT_Mem;
+ dest.iSdst = dest.iSDParm;
+ dest.nSdst = nReg;
+ sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
+ VdbeComment((v, "Init subquery result"));
+ }else{
+ dest.eDest = SRT_Exists;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
+ VdbeComment((v, "Init EXISTS result"));
+ }
+ pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
+ if( pSel->pLimit ){
+ sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
+ pSel->pLimit->pLeft = pLimit;
+ }else{
+ pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
}
+ pSel->iLimit = 0;
+ if( sqlite3Select(pParse, pSel, &dest) ){
+ return 0;
+ }
+ pExpr->iTable = rReg = dest.iSDParm;
+ ExprSetVVAProperty(pExpr, EP_NoReduce);
+ if( addrOnce ){
+ sqlite3VdbeJumpHere(v, addrOnce);
- if( jmpIfDynamic>=0 ){
- sqlite3VdbeJumpHere(v, jmpIfDynamic);
+ /* Subroutine return */
+ sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
+ sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
}
return rReg;
@@ -99164,6 +99749,7 @@ static void sqlite3ExprCodeIN(
int addrTruthOp; /* Address of opcode that determines the IN is true */
int destNotNull; /* Jump here if a comparison is not true in step 6 */
int addrTop; /* Top of the step-6 loop */
+ int iTab = 0; /* Index to use */
pLeft = pExpr->pLeft;
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
@@ -99175,7 +99761,7 @@ static void sqlite3ExprCodeIN(
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
/* Attempt to compute the RHS. After this step, if anything other than
- ** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable
+ ** IN_INDEX_NOOP is returned, the table opened with cursor iTab
** contains the values that make up the RHS. If IN_INDEX_NOOP is returned,
** the RHS has not yet been coded. */
v = pParse->pVdbe;
@@ -99183,7 +99769,8 @@ static void sqlite3ExprCodeIN(
VdbeNoopComment((v, "begin IN expr"));
eType = sqlite3FindInIndex(pParse, pExpr,
IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
- destIfFalse==destIfNull ? 0 : &rRhsHasNull, aiMap);
+ destIfFalse==destIfNull ? 0 : &rRhsHasNull,
+ aiMap, &iTab);
assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH
|| eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC
@@ -99229,7 +99816,7 @@ static void sqlite3ExprCodeIN(
if( eType==IN_INDEX_NOOP ){
ExprList *pList = pExpr->x.pList;
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- int labelOk = sqlite3VdbeMakeLabel(v);
+ int labelOk = sqlite3VdbeMakeLabel(pParse);
int r2, regToFree;
int regCkNull = 0;
int ii;
@@ -99273,7 +99860,7 @@ static void sqlite3ExprCodeIN(
if( destIfNull==destIfFalse ){
destStep2 = destIfFalse;
}else{
- destStep2 = destStep6 = sqlite3VdbeMakeLabel(v);
+ destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
}
for(i=0; i<nVector; i++){
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
@@ -99291,19 +99878,19 @@ static void sqlite3ExprCodeIN(
/* In this case, the RHS is the ROWID of table b-tree and so we also
** know that the RHS is non-NULL. Hence, we combine steps 3 and 4
** into a single opcode. */
- sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, rLhs);
+ sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs);
VdbeCoverage(v);
addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */
}else{
sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
if( destIfFalse==destIfNull ){
/* Combine Step 3 and Step 5 into a single opcode */
- sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse,
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
rLhs, nVector); VdbeCoverage(v);
goto sqlite3ExprCodeIN_finished;
}
/* Ordinary Step 3, for the case where FALSE and NULL are distinct */
- addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0,
+ addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, iTab, 0,
rLhs, nVector); VdbeCoverage(v);
}
@@ -99328,10 +99915,10 @@ static void sqlite3ExprCodeIN(
** of the RHS.
*/
if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6);
- addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, destIfFalse);
VdbeCoverage(v);
if( nVector>1 ){
- destNotNull = sqlite3VdbeMakeLabel(v);
+ destNotNull = sqlite3VdbeMakeLabel(pParse);
}else{
/* For nVector==1, combine steps 6 and 7 by immediately returning
** FALSE if the first comparison is not NULL */
@@ -99343,7 +99930,7 @@ static void sqlite3ExprCodeIN(
int r3 = sqlite3GetTempReg(pParse);
p = sqlite3VectorFieldSubexpr(pLeft, i);
pColl = sqlite3ExprCollSeq(pParse, p);
- sqlite3VdbeAddOp3(v, OP_Column, pExpr->iTable, i, r3);
+ sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
(void*)pColl, P4_COLLSEQ);
VdbeCoverage(v);
@@ -99352,7 +99939,7 @@ static void sqlite3ExprCodeIN(
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
if( nVector>1 ){
sqlite3VdbeResolveLabel(v, destNotNull);
- sqlite3VdbeAddOp2(v, OP_Next, pExpr->iTable, addrTop+1);
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addrTop+1);
VdbeCoverage(v);
/* Step 7: If we reach this point, we know that the result must
@@ -99551,7 +100138,7 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
#if SQLITE_OMIT_SUBQUERY
iResult = 0;
#else
- iResult = sqlite3CodeSubselect(pParse, p, 0, 0);
+ iResult = sqlite3CodeSubselect(pParse, p);
#endif
}else{
int i;
@@ -99896,7 +100483,7 @@ expr_code_doover:
** arguments past the first non-NULL argument.
*/
if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
- int endCoalesce = sqlite3VdbeMakeLabel(v);
+ int endCoalesce = sqlite3VdbeMakeLabel(pParse);
assert( nFarg>=2 );
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
for(i=1; i<nFarg; i++){
@@ -100025,14 +100612,14 @@ expr_code_doover:
if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
sqlite3SubselectError(pParse, nCol, 1);
}else{
- return sqlite3CodeSubselect(pParse, pExpr, 0, 0);
+ return sqlite3CodeSubselect(pParse, pExpr);
}
break;
}
case TK_SELECT_COLUMN: {
int n;
if( pExpr->pLeft->iTable==0 ){
- pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
+ pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
}
assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
if( pExpr->iTable
@@ -100044,8 +100631,8 @@ expr_code_doover:
return pExpr->pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
- int destIfFalse = sqlite3VdbeMakeLabel(v);
- int destIfNull = sqlite3VdbeMakeLabel(v);
+ int destIfFalse = sqlite3VdbeMakeLabel(pParse);
+ int destIfNull = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
@@ -100185,9 +100772,9 @@ expr_code_doover:
pEList = pExpr->x.pList;
aListelem = pEList->a;
nExpr = pEList->nExpr;
- endLabel = sqlite3VdbeMakeLabel(v);
+ endLabel = sqlite3VdbeMakeLabel(pParse);
if( (pX = pExpr->pLeft)!=0 ){
- tempX = *pX;
+ exprNodeCopy(&tempX, pX);
testcase( pX->op==TK_COLUMN );
exprToRegister(&tempX, exprCodeVector(pParse, &tempX, &regFree1));
testcase( regFree1==0 );
@@ -100208,7 +100795,7 @@ expr_code_doover:
}else{
pTest = aListelem[i].pExpr;
}
- nextCase = sqlite3VdbeMakeLabel(v);
+ nextCase = sqlite3VdbeMakeLabel(pParse);
testcase( pTest->op==TK_COLUMN );
sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
@@ -100508,13 +101095,12 @@ static void exprCodeBetween(
Expr exprX; /* The x subexpression */
int regFree1 = 0; /* Temporary use register */
-
memset(&compLeft, 0, sizeof(Expr));
memset(&compRight, 0, sizeof(Expr));
memset(&exprAnd, 0, sizeof(Expr));
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- exprX = *pExpr->pLeft;
+ exprNodeCopy(&exprX, pExpr->pLeft);
exprAnd.op = TK_AND;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
@@ -100577,7 +101163,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
op = pExpr->op;
switch( op ){
case TK_AND: {
- int d2 = sqlite3VdbeMakeLabel(v);
+ int d2 = sqlite3VdbeMakeLabel(pParse);
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
@@ -100663,7 +101249,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_IN: {
- int destIfFalse = sqlite3VdbeMakeLabel(v);
+ int destIfFalse = sqlite3VdbeMakeLabel(pParse);
int destIfNull = jumpIfNull ? dest : destIfFalse;
sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
sqlite3VdbeGoto(v, dest);
@@ -100750,7 +101336,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
break;
}
case TK_OR: {
- int d2 = sqlite3VdbeMakeLabel(v);
+ int d2 = sqlite3VdbeMakeLabel(pParse);
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
@@ -100834,7 +101420,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
if( jumpIfNull ){
sqlite3ExprCodeIN(pParse, pExpr, dest, dest);
}else{
- int destIfNull = sqlite3VdbeMakeLabel(v);
+ int destIfNull = sqlite3VdbeMakeLabel(pParse);
sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull);
sqlite3VdbeResolveLabel(v, destIfNull);
}
@@ -101108,6 +101694,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
case TK_ISNOT:
case TK_NOT:
case TK_ISNULL:
+ case TK_NOTNULL:
case TK_IS:
case TK_OR:
case TK_CASE:
@@ -101116,6 +101703,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_ISNOT );
testcase( pExpr->op==TK_NOT );
testcase( pExpr->op==TK_ISNULL );
+ testcase( pExpr->op==TK_NOTNULL );
testcase( pExpr->op==TK_IS );
testcase( pExpr->op==TK_OR );
testcase( pExpr->op==TK_CASE );
@@ -101489,6 +102077,7 @@ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
w.walkerDepth = 0;
w.u.pNC = pNC;
+ w.pParse = 0;
assert( pNC->pSrcList!=0 );
sqlite3WalkExpr(&w, pExpr);
}
@@ -101620,9 +102209,16 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){
**
** Or, if zName is not a system table, zero is returned.
*/
-static int isSystemTable(Parse *pParse, const char *zName){
- if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
- sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
+static int isAlterableTable(Parse *pParse, Table *pTab){
+ if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ || ( (pTab->tabFlags & TF_Shadow)
+ && (pParse->db->flags & SQLITE_Defensive)
+ && pParse->db->nVdbeExec==0
+ )
+#endif
+ ){
+ sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
return 1;
}
return 0;
@@ -101718,7 +102314,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
/* Make sure it is not a system table being altered, or a reserved name
** that the table is being renamed to.
*/
- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_rename_table;
}
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
@@ -102016,7 +102612,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
goto exit_begin_add_column;
}
- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_begin_add_column;
}
@@ -102118,7 +102714,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn(
if( !pTab ) goto exit_rename_column;
/* Cannot alter a system table */
- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column;
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
/* Which schema holds the table to be altered */
@@ -102373,13 +102969,30 @@ static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
}
/*
+** Iterate through the Select objects that are part of WITH clauses attached
+** to select statement pSelect.
+*/
+static void renameWalkWith(Walker *pWalker, Select *pSelect){
+ if( pSelect->pWith ){
+ int i;
+ for(i=0; i<pSelect->pWith->nCte; i++){
+ Select *p = pSelect->pWith->a[i].pSelect;
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pWalker->pParse;
+ sqlite3SelectPrep(sNC.pParse, p, &sNC);
+ sqlite3WalkSelect(pWalker, p);
+ }
+ }
+}
+
+/*
** This is a Walker select callback. It does nothing. It is only required
** because without a dummy callback, sqlite3WalkExpr() and similar do not
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
- UNUSED_PARAMETER(pWalker);
- UNUSED_PARAMETER(p);
+ renameWalkWith(pWalker, p);
return WRC_Continue;
}
@@ -102529,7 +103142,6 @@ static int renameParseSql(
rc = sqlite3RunParser(p, zSql, &zErr);
assert( p->zErrMsg==0 );
assert( rc!=SQLITE_OK || zErr==0 );
- assert( (0!=p->pNewTable) + (0!=p->pNewIndex) + (0!=p->pNewTrigger)<2 );
p->zErrMsg = zErr;
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
@@ -102712,6 +103324,7 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
}
sNC.ncFlags = 0;
}
+ sNC.pSrcList = 0;
}
}
}
@@ -102749,11 +103362,15 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
*/
static void renameParseCleanup(Parse *pParse){
sqlite3 *db = pParse->db;
+ Index *pIdx;
if( pParse->pVdbe ){
sqlite3VdbeFinalize(pParse->pVdbe);
}
sqlite3DeleteTable(db, pParse->pNewTable);
- if( pParse->pNewIndex ) sqlite3FreeIndex(db, pParse->pNewIndex);
+ while( (pIdx = pParse->pNewIndex)!=0 ){
+ pParse->pNewIndex = pIdx->pNext;
+ sqlite3FreeIndex(db, pIdx);
+ }
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->zErrMsg);
renameTokenFree(db, pParse->pRename);
@@ -102864,6 +103481,9 @@ static void renameColumnFunc(
for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
+ for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
+ sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
+ }
}
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
@@ -102950,12 +103570,17 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
+ if( pSrc==0 ){
+ assert( pWalker->pParse->db->mallocFailed );
+ return WRC_Abort;
+ }
for(i=0; i<pSrc->nSrc; i++){
struct SrcList_item *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
}
+ renameWalkWith(pWalker, pSelect);
return WRC_Continue;
}
@@ -104357,7 +104982,7 @@ static void analyzeOneTable(
addrNextRow = sqlite3VdbeCurrentAddr(v);
if( nColTest>0 ){
- int endDistinctTest = sqlite3VdbeMakeLabel(v);
+ int endDistinctTest = sqlite3VdbeMakeLabel(pParse);
int *aGotoChng; /* Array of jump instruction addresses */
aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest);
if( aGotoChng==0 ) continue;
@@ -105295,8 +105920,8 @@ static void attachFunc(
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
- sqlite3_free( zPath );
db->nDb++;
+ pNew->zDbSName = sqlite3DbStrDup(db, zName);
}
db->noSharedCache = 0;
if( rc==SQLITE_CONSTRAINT ){
@@ -105324,7 +105949,6 @@ static void attachFunc(
sqlite3BtreeLeave(pNew->pBt);
}
pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
rc = SQLITE_NOMEM_BKPT;
}
@@ -105352,15 +105976,19 @@ static void attachFunc(
break;
case SQLITE_NULL:
- /* No key specified. Use the key from the main database */
- sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
- if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
- rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
+ /* No key specified. Use the key from URI filename, or if none,
+ ** use the key from the main database. */
+ if( sqlite3CodecQueryParameters(db, zName, zPath)==0 ){
+ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
+ if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
+ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
+ }
}
break;
}
}
#endif
+ sqlite3_free( zPath );
/* If the file was opened successfully, read the schema for the new database.
** If this fails, or if opening the file failed, then close the file and
@@ -106272,7 +106900,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
if( v && pParse->nErr==0 && !db->mallocFailed ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
- if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
+ assert( pParse->pAinc==0 || pParse->nTab>0 );
sqlite3VdbeMakeReady(v, pParse);
pParse->rc = SQLITE_DONE;
}else{
@@ -106687,12 +107315,6 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
/* Delete the Table structure itself.
*/
-#ifdef SQLITE_ENABLE_NORMALIZE
- if( pTable->pColHash ){
- sqlite3HashClear(pTable->pColHash);
- sqlite3_free(pTable->pColHash);
- }
-#endif
sqlite3DeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
@@ -108689,6 +109311,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in
*/
if( IsVirtual(pTab) ){
sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
+ sqlite3MayAbort(pParse);
}
sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
sqlite3ChangeCookie(pParse, iDb);
@@ -109517,6 +110140,11 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
}
}
if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType;
+ if( IN_RENAME_OBJECT ){
+ pIndex->pNext = pParse->pNewIndex;
+ pParse->pNewIndex = pIndex;
+ pIndex = 0;
+ }
goto exit_create_index;
}
}
@@ -109532,6 +110160,14 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
Index *p;
assert( !IN_SPECIAL_PARSE );
assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
+ if( pTblName!=0 ){
+ pIndex->tnum = db->init.newTnum;
+ if( sqlite3IndexHasDuplicateRootPage(pIndex) ){
+ sqlite3ErrorMsg(pParse, "invalid rootpage");
+ pParse->rc = SQLITE_CORRUPT_BKPT;
+ goto exit_create_index;
+ }
+ }
p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
pIndex->zName, pIndex);
if( p ){
@@ -109540,9 +110176,6 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
goto exit_create_index;
}
db->mDbFlags |= DBFLAG_SchemaChange;
- if( pTblName!=0 ){
- pIndex->tnum = db->init.newTnum;
- }
}
/* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
@@ -109869,6 +110502,18 @@ SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){
}
/*
+** Maximum size of a SrcList object.
+** The SrcList object is used to represent the FROM clause of a
+** SELECT statement, and the query planner cannot deal with more
+** than 64 tables in a join. So any value larger than 64 here
+** is sufficient for most uses. Smaller values, like say 10, are
+** appropriate for small and memory-limited applications.
+*/
+#ifndef SQLITE_MAX_SRCLIST
+# define SQLITE_MAX_SRCLIST 200
+#endif
+
+/*
** Expand the space allocated for the given SrcList object by
** creating nExtra new slots beginning at iStart. iStart is zero based.
** New slots are zeroed.
@@ -109884,11 +110529,12 @@ SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){
** the iStart value would be 0. The result then would
** be: nil, nil, nil, A, B.
**
-** If a memory allocation fails the SrcList is unchanged. The
-** db->mallocFailed flag will be set to true.
+** If a memory allocation fails or the SrcList becomes too large, leave
+** the original SrcList unchanged, return NULL, and leave an error message
+** in pParse.
*/
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
- sqlite3 *db, /* Database connection to notify of OOM errors */
+ Parse *pParse, /* Parsing context into which errors are reported */
SrcList *pSrc, /* The SrcList to be enlarged */
int nExtra, /* Number of new slots to add to pSrc->a[] */
int iStart /* Index in pSrc->a[] of first new slot */
@@ -109905,16 +110551,22 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
int nAlloc = pSrc->nSrc*2+nExtra;
- int nGot;
+ sqlite3 *db = pParse->db;
+
+ if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){
+ sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d",
+ SQLITE_MAX_SRCLIST);
+ return 0;
+ }
+ if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
pNew = sqlite3DbRealloc(db, pSrc,
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
if( pNew==0 ){
assert( db->mallocFailed );
- return pSrc;
+ return 0;
}
pSrc = pNew;
- nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
- pSrc->nAlloc = nGot;
+ pSrc->nAlloc = nAlloc;
}
/* Move existing slots that come after the newly inserted slots
@@ -109939,7 +110591,8 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
** Append a new table name to the given SrcList. Create a new SrcList if
** need be. A new entry is created in the SrcList even if pTable is NULL.
**
-** A SrcList is returned, or NULL if there is an OOM error. The returned
+** A SrcList is returned, or NULL if there is an OOM error or if the
+** SrcList grows to large. The returned
** SrcList might be the same as the SrcList that was input or it might be
** a new one. If an OOM error does occurs, then the prior value of pList
** that is input to this routine is automatically freed.
@@ -109970,27 +110623,32 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
** before being added to the SrcList.
*/
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
- sqlite3 *db, /* Connection to notify of malloc failures */
+ Parse *pParse, /* Parsing context, in which errors are reported */
SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */
Token *pTable, /* Table to append */
Token *pDatabase /* Database of the table */
){
struct SrcList_item *pItem;
+ sqlite3 *db;
assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
- assert( db!=0 );
+ assert( pParse!=0 );
+ assert( pParse->db!=0 );
+ db = pParse->db;
if( pList==0 ){
- pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
+ pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
pList->nSrc = 1;
memset(&pList->a[0], 0, sizeof(pList->a[0]));
pList->a[0].iCursor = -1;
}else{
- pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
- }
- if( db->mallocFailed ){
- sqlite3SrcListDelete(db, pList);
- return 0;
+ SrcList *pNew = sqlite3SrcListEnlarge(pParse, pList, 1, pList->nSrc);
+ if( pNew==0 ){
+ sqlite3SrcListDelete(db, pList);
+ return 0;
+ }else{
+ pList = pNew;
+ }
}
pItem = &pList->a[pList->nSrc-1];
if( pDatabase && pDatabase->z==0 ){
@@ -110079,7 +110737,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
);
goto append_from_error;
}
- p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
+ p = sqlite3SrcListAppend(pParse, p, pTable, pDatabase);
if( p==0 ){
goto append_from_error;
}
@@ -110468,7 +111126,7 @@ static int collationMatch(const char *zColl, Index *pIndex){
*/
#ifndef SQLITE_OMIT_REINDEX
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
- if (! IsVirtual(pTab) ){
+ if( !IsVirtual(pTab) ){
Index *pIndex; /* An index associated with pTab */
for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
@@ -110975,7 +111633,7 @@ static int matchQuality(
** Search a FuncDefHash for a function with the given name. Return
** a pointer to the matching FuncDef if found, or 0 if there is no match.
*/
-static FuncDef *functionSearch(
+SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(
int h, /* Hash of the name */
const char *zFunc /* Name of function */
){
@@ -110987,21 +111645,6 @@ static FuncDef *functionSearch(
}
return 0;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN(
- int h, /* Hash of the name */
- const char *zFunc, /* Name of function */
- int nFunc /* Length of the name */
-){
- FuncDef *p;
- for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
- if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){
- return p;
- }
- }
- return 0;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Insert a new FuncDef into a FuncDefHash hash table.
@@ -111017,7 +111660,7 @@ SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(
int nName = sqlite3Strlen30(zName);
int h = SQLITE_FUNC_HASH(zName[0], nName);
assert( zName[0]>='a' && zName[0]<='z' );
- pOther = functionSearch(h, zName);
+ pOther = sqlite3FunctionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
aDef[i].pNext = pOther->pNext;
@@ -111095,7 +111738,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
bestScore = 0;
h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName);
- p = functionSearch(h, zName);
+ p = sqlite3FunctionSearch(h, zName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){
@@ -111315,7 +111958,7 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
sqlite3 *db = pParse->db;
int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
pWhere = sqlite3ExprDup(db, pWhere, 0);
- pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
+ pFrom = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
@@ -111715,7 +112358,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
/* If this DELETE cannot use the ONEPASS strategy, this is the
** end of the WHERE loop */
if( eOnePass!=ONEPASS_OFF ){
- addrBypass = sqlite3VdbeMakeLabel(v);
+ addrBypass = sqlite3VdbeMakeLabel(pParse);
}else{
sqlite3WhereEnd(pWInfo);
}
@@ -111904,7 +112547,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
/* Seek cursor iCur to the row to delete. If this row no longer exists
** (this can happen if a trigger program has already deleted it), do
** not attempt to delete it or fire any DELETE triggers. */
- iLabel = sqlite3VdbeMakeLabel(v);
+ iLabel = sqlite3VdbeMakeLabel(pParse);
opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
if( eMode==ONEPASS_OFF ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
@@ -112110,7 +112753,7 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
if( piPartIdxLabel ){
if( pIdx->pPartIdxWhere ){
- *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
+ *piPartIdxLabel = sqlite3VdbeMakeLabel(pParse);
pParse->iSelfTab = iDataCur + 1;
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
@@ -112366,6 +113009,7 @@ static void instrFunc(
int typeHaystack, typeNeedle;
int N = 1;
int isText;
+ unsigned char firstChar;
UNUSED_PARAMETER(argc);
typeHaystack = sqlite3_value_type(argv[0]);
@@ -112384,7 +113028,10 @@ static void instrFunc(
isText = 1;
}
if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
- while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
+ firstChar = zNeedle[0];
+ while( nNeedle<=nHaystack
+ && (zHaystack[0]!=firstChar || memcmp(zHaystack, zNeedle, nNeedle)!=0)
+ ){
N++;
do{
nHaystack--;
@@ -112675,11 +113322,11 @@ static void randomBlob(
int argc,
sqlite3_value **argv
){
- int n;
+ sqlite3_int64 n;
unsigned char *p;
assert( argc==1 );
UNUSED_PARAMETER(argc);
- n = sqlite3_value_int(argv[0]);
+ n = sqlite3_value_int64(argv[0]);
if( n<1 ){
n = 1;
}
@@ -114515,7 +115162,7 @@ static void fkLookupParent(
int i; /* Iterator variable */
Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */
int iCur = pParse->nTab - 1; /* Cursor number to use */
- int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */
+ int iOk = sqlite3VdbeMakeLabel(pParse); /* jump here if parent key found */
sqlite3VdbeVerifyAbortable(v,
(!pFKey->isDeferred
@@ -114804,7 +115451,6 @@ static void fkScanChildren(
pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight);
}else{
Expr *pEq, *pAll = 0;
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pIdx!=0 );
for(i=0; i<pIdx->nKeyCol; i++){
i16 iCol = pIdx->aiColumn[i];
@@ -114916,7 +115562,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
}
if( !p ) return;
- iSkip = sqlite3VdbeMakeLabel(v);
+ iSkip = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
}
@@ -115201,7 +115847,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
/* Create a SrcList structure containing the child table. We need the
** child table as a SrcList for sqlite3WhereBegin() */
- pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
+ pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
struct SrcList_item *pItem = pSrc->a;
pItem->pTab = pFKey->pFrom;
@@ -115478,7 +116124,7 @@ static Trigger *fkActionTrigger(
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
- sqlite3SrcListAppend(db, 0, &tFrom, 0),
+ sqlite3SrcListAppend(pParse, 0, &tFrom, 0),
pWhere,
0, 0, 0, 0, 0
);
@@ -115940,6 +116586,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){
aOp[7].p2 = memId+2;
aOp[7].p1 = memId;
aOp[10].p2 = memId;
+ if( pParse->nTab==0 ) pParse->nTab = 1;
}
}
@@ -116446,6 +117093,11 @@ SQLITE_PRIVATE void sqlite3Insert(
}
#ifndef SQLITE_OMIT_UPSERT
if( pUpsert ){
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
+ pTab->zName);
+ goto insert_cleanup;
+ }
pTabList->a[0].iCursor = iDataCur;
pUpsert->pUpsertSrc = pTabList;
pUpsert->regData = regData;
@@ -116486,7 +117138,7 @@ SQLITE_PRIVATE void sqlite3Insert(
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
- endOfLoop = sqlite3VdbeMakeLabel(v);
+ endOfLoop = sqlite3VdbeMakeLabel(pParse);
if( tmask & TRIGGER_BEFORE ){
int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1);
@@ -116968,7 +117620,20 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace );
+ addr1 = 0;
switch( onError ){
+ case OE_Replace: {
+ assert( onError==OE_Replace );
+ addr1 = sqlite3VdbeMakeLabel(pParse);
+ sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
+ VdbeCoverage(v);
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
+ sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
+ VdbeCoverage(v);
+ onError = OE_Abort;
+ /* Fall through into the OE_Abort case to generate code that runs
+ ** if both the input and the default value are NULL */
+ }
case OE_Abort:
sqlite3MayAbort(pParse);
/* Fall through */
@@ -116981,21 +117646,15 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
VdbeCoverage(v);
+ if( addr1 ) sqlite3VdbeResolveLabel(v, addr1);
break;
}
- case OE_Ignore: {
+ default: {
+ assert( onError==OE_Ignore );
sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
VdbeCoverage(v);
break;
}
- default: {
- assert( onError==OE_Replace );
- addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i);
- VdbeCoverage(v);
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
- sqlite3VdbeJumpHere(v, addr1);
- break;
- }
}
}
@@ -117016,7 +117675,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** updated so there is no point it verifying the check constraint */
continue;
}
- allOk = sqlite3VdbeMakeLabel(v);
+ allOk = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
if( onError==OE_Ignore ){
@@ -117083,7 +117742,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** exist in the table.
*/
if( pkChng && pPk==0 ){
- int addrRowidOk = sqlite3VdbeMakeLabel(v);
+ int addrRowidOk = sqlite3VdbeMakeLabel(pParse);
/* Figure out what action to take in case of a rowid collision */
onError = pTab->keyConf;
@@ -117233,7 +117892,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
VdbeComment((v, "Skip upsert subroutine"));
sqlite3VdbeJumpHere(v, upsertJump);
}else{
- addrUniqueOk = sqlite3VdbeMakeLabel(v);
+ addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
}
if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
sqlite3TableAffinity(v, pTab, regNewData+1);
@@ -117316,7 +117975,11 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** (3) There are no secondary indexes on the table
** (4) No delete triggers need to be fired if there is a conflict
** (5) No FK constraint counters need to be updated if a conflict occurs.
- */
+ **
+ ** This is not possible for ENABLE_PREUPDATE_HOOK builds, as the row
+ ** must be explicitly deleted in order to ensure any pre-update hook
+ ** is invoked. */
+#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
&& pPk==pIdx /* Condition 2 */
&& onError==OE_Replace /* Condition 1 */
@@ -117328,6 +117991,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue;
}
+#endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */
/* Check to see if the new index entry will be unique */
sqlite3VdbeVerifyAbortable(v, onError);
@@ -118088,7 +118752,7 @@ SQLITE_API int sqlite3_exec(
sqlite3_mutex_enter(db->mutex);
sqlite3Error(db, SQLITE_OK);
while( rc==SQLITE_OK && zSql[0] ){
- int nCol;
+ int nCol = 0;
char **azVals = 0;
pStmt = 0;
@@ -118102,9 +118766,7 @@ SQLITE_API int sqlite3_exec(
zSql = zLeftover;
continue;
}
-
callbackIsInit = 0;
- nCol = sqlite3_column_count(pStmt);
while( 1 ){
int i;
@@ -118115,6 +118777,7 @@ SQLITE_API int sqlite3_exec(
(SQLITE_DONE==rc && !callbackIsInit
&& db->flags&SQLITE_NullCallback)) ){
if( !callbackIsInit ){
+ nCol = sqlite3_column_count(pStmt);
azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*));
if( azCols==0 ){
goto exec_out;
@@ -119469,7 +120132,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
if( onoff ){
db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc;
}else{
- db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
+ db->flags &= ~(u64)(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
}
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
@@ -119728,8 +120391,7 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
#define PragTyp_HEXKEY 41
#define PragTyp_KEY 42
#define PragTyp_LOCK_STATUS 43
-#define PragTyp_PARSER_TRACE 44
-#define PragTyp_STATS 45
+#define PragTyp_STATS 44
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -120140,12 +120802,14 @@ static const PragmaName aPragmaName[] = {
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if defined(SQLITE_DEBUG)
{/* zName: */ "parser_trace",
- /* ePragTyp: */ PragTyp_PARSER_TRACE,
- /* ePragFlg: */ 0,
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
- /* iArg: */ 0 },
+ /* iArg: */ SQLITE_ParserTrace },
+#endif
#endif
#if defined(SQLITE_INTROSPECTION_PRAGMAS)
{/* zName: */ "pragma_list",
@@ -121136,7 +121800,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( sqlite3GetBoolean(zRight, size!=0) ){
db->flags |= SQLITE_CacheSpill;
}else{
- db->flags &= ~SQLITE_CacheSpill;
+ db->flags &= ~(u64)SQLITE_CacheSpill;
}
setAllPagerFlags(db);
}
@@ -121696,7 +122360,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
assert( x==0 );
}
- addrOk = sqlite3VdbeMakeLabel(v);
+ addrOk = sqlite3VdbeMakeLabel(pParse);
/* Generate code to read the child key values into registers
** regRow..regRow+n. If any of the child key values are NULL, this
@@ -121741,19 +122405,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
#endif /* !defined(SQLITE_OMIT_TRIGGER) */
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
-#ifndef NDEBUG
- case PragTyp_PARSER_TRACE: {
- if( zRight ){
- if( sqlite3GetBoolean(zRight, 0) ){
- sqlite3ParserTrace(stdout, "parser: ");
- }else{
- sqlite3ParserTrace(0, 0);
- }
- }
- }
- break;
-#endif
-
/* Reinstall the LIKE and GLOB functions. The variant of LIKE
** used will be case sensitive or not depending on the RHS.
*/
@@ -121916,8 +122567,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
if( db->mallocFailed==0 ){
- int addrCkFault = sqlite3VdbeMakeLabel(v);
- int addrCkOk = sqlite3VdbeMakeLabel(v);
+ int addrCkFault = sqlite3VdbeMakeLabel(pParse);
+ int addrCkOk = sqlite3VdbeMakeLabel(pParse);
char *zErr;
int k;
pParse->iSelfTab = iDataCur + 1;
@@ -121940,7 +122591,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Validate index entries for the current row */
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int jmp2, jmp3, jmp4, jmp5;
- int ckUniq = sqlite3VdbeMakeLabel(v);
+ int ckUniq = sqlite3VdbeMakeLabel(pParse);
if( pPk==pIdx ) continue;
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
pPrior, r1);
@@ -121961,7 +122612,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** current key. The entry is unique if (1) any column is NULL
** or (2) the next entry has a different key */
if( IsUniqueIndex(pIdx) ){
- int uniqOk = sqlite3VdbeMakeLabel(v);
+ int uniqOk = sqlite3VdbeMakeLabel(pParse);
int jmp6;
int kk;
for(kk=0; kk<pIdx->nKeyCol; kk++){
@@ -122876,6 +123527,19 @@ static void corruptSchema(
}
/*
+** Check to see if any sibling index (another index on the same table)
+** of pIndex has the same root page number, and if it does, return true.
+** This would indicate a corrupt schema.
+*/
+SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
+ Index *p;
+ for(p=pIndex->pTable->pIndex; p; p=p->pNext){
+ if( p->tnum==pIndex->tnum && p!=pIndex ) return 1;
+ }
+ return 0;
+}
+
+/*
** This is the callback routine for the code that initializes the
** database. See sqlite3Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
@@ -122896,6 +123560,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
DbClearProperty(db, iDb, DB_Empty);
+ pData->nInitRow++;
if( db->mallocFailed ){
corruptSchema(pData, argv[0], 0);
return 1;
@@ -122952,6 +123617,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
if( pIndex==0
|| sqlite3GetInt32(argv[1],&pIndex->tnum)==0
|| pIndex->tnum<2
+ || sqlite3IndexHasDuplicateRootPage(pIndex)
){
corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
}
@@ -123003,6 +123669,7 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
initData.mInitFlags = mFlags;
+ initData.nInitRow = 0;
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
if( initData.rc ){
rc = initData.rc;
@@ -123120,7 +123787,7 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
** indices that the user might have created.
*/
if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){
- db->flags &= ~SQLITE_LegacyFileFmt;
+ db->flags &= ~(u64)SQLITE_LegacyFileFmt;
}
/* Read the schema information out of the schema tables
@@ -123537,293 +124204,6 @@ static int sqlite3LockAndPrepare(
return rc;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-/*
-** Checks if the specified token is a table, column, or function name,
-** based on the databases associated with the statement being prepared.
-** If the function fails, zero is returned and pRc is filled with the
-** error code.
-*/
-static int shouldTreatAsIdentifier(
- sqlite3 *db, /* Database handle. */
- const char *zToken, /* Pointer to start of token to be checked */
- int nToken, /* Length of token to be checked */
- int *pRc /* Pointer to error code upon failure */
-){
- int bFound = 0; /* Non-zero if token is an identifier name. */
- int i, j; /* Database and column loop indexes. */
- Schema *pSchema; /* Schema for current database. */
- Hash *pHash; /* Hash table of tables for current database. */
- HashElem *e; /* Hash element for hash table iteration. */
- Table *pTab; /* Database table for columns being checked. */
-
- if( sqlite3IsRowidN(zToken, nToken) ){
- return 1;
- }
- if( nToken>0 ){
- int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken);
- if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1;
- }
- assert( db!=0 );
- sqlite3_mutex_enter(db->mutex);
- sqlite3BtreeEnterAll(db);
- for(i=0; i<db->nDb; i++){
- pHash = &db->aFunc;
- if( sqlite3HashFindN(pHash, zToken, nToken) ){
- bFound = 1;
- break;
- }
- pSchema = db->aDb[i].pSchema;
- if( pSchema==0 ) continue;
- pHash = &pSchema->tblHash;
- if( sqlite3HashFindN(pHash, zToken, nToken) ){
- bFound = 1;
- break;
- }
- for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){
- pTab = sqliteHashData(e);
- if( pTab==0 ) continue;
- pHash = pTab->pColHash;
- if( pHash==0 ){
- pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash));
- if( pHash ){
- sqlite3HashInit(pHash);
- for(j=0; j<pTab->nCol; j++){
- Column *pCol = &pTab->aCol[j];
- sqlite3HashInsert(pHash, pCol->zName, pCol);
- }
- }else{
- *pRc = SQLITE_NOMEM_BKPT;
- bFound = 0;
- goto done;
- }
- }
- if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){
- bFound = 1;
- goto done;
- }
- }
- }
-done:
- sqlite3BtreeLeaveAll(db);
- sqlite3_mutex_leave(db->mutex);
- return bFound;
-}
-
-/*
-** Attempt to estimate the final output buffer size needed for the fully
-** normalized version of the specified SQL string. This should take into
-** account any potential expansion that could occur (e.g. via IN clauses
-** being expanded, etc). This size returned is the total number of bytes
-** including the NUL terminator.
-*/
-static int estimateNormalizedSize(
- const char *zSql, /* The original SQL string */
- int nSql, /* Length of original SQL string */
- u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
-){
- int nOut = nSql + 4;
- const char *z = zSql;
- while( nOut<nSql*5 ){
- while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; }
- if( z[0]==0 ) break;
- z++;
- if( z[0]!='N' && z[0]!='n' ) break;
- z++;
- while( sqlite3Isspace(z[0]) ){ z++; }
- if( z[0]!='(' ) break;
- z++;
- nOut += 5; /* ?,?,? */
- }
- return nOut;
-}
-
-/*
-** Copy the current token into the output buffer while dealing with quoted
-** identifiers. By default, all letters will be converted into lowercase.
-** If the bUpper flag is set, uppercase will be used. The piOut argument
-** will be used to update the target index into the output string.
-*/
-static void copyNormalizedToken(
- const char *zSql, /* The original SQL string */
- int iIn, /* Current index into the original SQL string */
- int nToken, /* Number of bytes in the current token */
- int tokenFlags, /* Flags returned by the tokenizer */
- char *zOut, /* The output string */
- int *piOut /* Pointer to target index into the output string */
-){
- int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED;
- int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD;
- int j = *piOut, k = 0;
- for(; k<nToken; k++){
- if( bQuoted ){
- if( k==0 && iIn>0 ){
- zOut[j++] = '"';
- continue;
- }else if( k==nToken-1 ){
- zOut[j++] = '"';
- continue;
- }
- }
- if( bKeyword ){
- zOut[j++] = sqlite3Toupper(zSql[iIn+k]);
- }else{
- zOut[j++] = sqlite3Tolower(zSql[iIn+k]);
- }
- }
- *piOut = j;
-}
-
-/*
-** Perform normalization of the SQL contained in the prepared statement and
-** store the result in the zNormSql field. The schema for the associated
-** databases are consulted while performing the normalization in order to
-** determine if a token appears to be an identifier. All identifiers are
-** left intact in the normalized SQL and all literals are replaced with a
-** single '?'.
-*/
-SQLITE_PRIVATE void sqlite3Normalize(
- Vdbe *pVdbe, /* VM being reprepared */
- const char *zSql, /* The original SQL string */
- int nSql, /* Size of the input string in bytes */
- u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
-){
- sqlite3 *db; /* Database handle. */
- char *z; /* The output string */
- int nZ; /* Size of the output string in bytes */
- int i; /* Next character to read from zSql[] */
- int j; /* Next character to fill in on z[] */
- int tokenType = 0; /* Type of the next token */
- int prevTokenType = 0; /* Type of the previous token, except spaces */
- int n; /* Size of the next token */
- int nParen = 0; /* Nesting level of parenthesis */
- Hash inHash; /* Table of parenthesis levels to output index. */
-
- db = sqlite3VdbeDb(pVdbe);
- assert( db!=0 );
- assert( pVdbe->zNormSql==0 );
- if( zSql==0 ) return;
- nZ = estimateNormalizedSize(zSql, nSql, prepFlags);
- z = sqlite3DbMallocRawNN(db, nZ);
- if( z==0 ) return;
- sqlite3HashInit(&inHash);
- for(i=j=0; i<nSql && zSql[i]; i+=n){
- int flags = 0;
- if( tokenType!=TK_SPACE ) prevTokenType = tokenType;
- n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags);
- switch( tokenType ){
- case TK_SPACE: {
- break;
- }
- case TK_ILLEGAL: {
- sqlite3DbFree(db, z);
- sqlite3HashClear(&inHash);
- return;
- }
- case TK_STRING:
- case TK_INTEGER:
- case TK_FLOAT:
- case TK_VARIABLE:
- case TK_BLOB: {
- z[j++] = '?';
- break;
- }
- case TK_LP:
- case TK_RP: {
- if( tokenType==TK_LP ){
- nParen++;
- if( prevTokenType==TK_IN ){
- assert( nParen<nSql );
- sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j));
- }
- }else{
- int jj;
- assert( nParen<nSql );
- jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen));
- if( jj>0 ){
- sqlite3HashInsert(&inHash, zSql+nParen, 0);
- assert( jj+6<nZ );
- memcpy(z+jj+1, "?,?,?", 5);
- j = jj+6;
- assert( nZ-1-j>=0 );
- assert( nZ-1-j<nZ );
- memset(z+j, 0, nZ-1-j);
- }
- nParen--;
- }
- assert( nParen>=0 );
- /* Fall through */
- }
- case TK_MINUS:
- case TK_SEMI:
- case TK_PLUS:
- case TK_STAR:
- case TK_SLASH:
- case TK_REM:
- case TK_EQ:
- case TK_LE:
- case TK_NE:
- case TK_LSHIFT:
- case TK_LT:
- case TK_RSHIFT:
- case TK_GT:
- case TK_GE:
- case TK_BITOR:
- case TK_CONCAT:
- case TK_COMMA:
- case TK_BITAND:
- case TK_BITNOT:
- case TK_DOT:
- case TK_IN:
- case TK_IS:
- case TK_NOT:
- case TK_NULL:
- case TK_ID: {
- if( tokenType==TK_NULL ){
- if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){
- /* NULL is a keyword in this case, not a literal value */
- }else{
- /* Here the NULL is a literal value */
- z[j++] = '?';
- break;
- }
- }
- if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){
- z[j++] = ' ';
- }
- if( tokenType==TK_ID ){
- int i2 = i, n2 = n, rc = SQLITE_OK;
- if( nParen>0 ){
- assert( nParen<nSql );
- sqlite3HashInsert(&inHash, zSql+nParen, 0);
- }
- if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; }
- if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, z);
- sqlite3HashClear(&inHash);
- return;
- }
- if( sqlite3_keyword_check(zSql+i2, n2)==0 ){
- z[j++] = '?';
- break;
- }
- }
- }
- copyNormalizedToken(zSql, i, n, flags, z, &j);
- break;
- }
- }
- }
- assert( j<nZ && "one" );
- while( j>0 && z[j-1]==' ' ){ j--; }
- if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; }
- z[j] = 0;
- assert( j<nZ && "two" );
- pVdbe->zNormSql = z;
- sqlite3HashClear(&inHash);
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Rerun the compilation of a statement after a schema change.
@@ -124665,7 +125045,7 @@ static void pushOntoSorter(
}
assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
- pSort->labelDone = sqlite3VdbeMakeLabel(v);
+ pSort->labelDone = sqlite3VdbeMakeLabel(pParse);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
if( bSeq ){
@@ -124704,7 +125084,7 @@ static void pushOntoSorter(
pKI->nAllField-pKI->nKeyField-1);
addrJmp = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
- pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
+ pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse);
pSort->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
@@ -125451,7 +125831,7 @@ static void generateSortTail(
){
Vdbe *v = pParse->pVdbe; /* The prepared statement */
int addrBreak = pSort->labelDone; /* Jump here to exit loop */
- int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
+ int addrContinue = sqlite3VdbeMakeLabel(pParse);/* Jump here for next cycle */
int addr; /* Top of output loop. Jump for Next. */
int addrOnce = 0;
int iTab;
@@ -126117,15 +126497,15 @@ SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
Table *pTab;
sqlite3 *db = pParse->db;
- int savedFlags;
+ u64 savedFlags;
savedFlags = db->flags;
- db->flags &= ~SQLITE_FullColNames;
+ db->flags &= ~(u64)SQLITE_FullColNames;
db->flags |= SQLITE_ShortColNames;
sqlite3SelectPrep(pParse, pSelect, 0);
+ db->flags = savedFlags;
if( pParse->nErr ) return 0;
while( pSelect->pPrior ) pSelect = pSelect->pPrior;
- db->flags = savedFlags;
pTab = sqlite3DbMallocZero(db, sizeof(Table) );
if( pTab==0 ){
return 0;
@@ -126369,7 +126749,7 @@ static void generateWithRecursiveQuery(
if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
/* Process the LIMIT and OFFSET clauses, if they exist */
- addrBreak = sqlite3VdbeMakeLabel(v);
+ addrBreak = sqlite3VdbeMakeLabel(pParse);
p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit;
@@ -126439,7 +126819,7 @@ static void generateWithRecursiveQuery(
sqlite3VdbeAddOp1(v, OP_Delete, iQueue);
/* Output the single row in Current */
- addrCont = sqlite3VdbeMakeLabel(v);
+ addrCont = sqlite3VdbeMakeLabel(pParse);
codeOffset(v, regOffset, addrCont);
selectInnerLoop(pParse, p, iCurrent,
0, 0, pDest, addrCont, addrBreak);
@@ -126747,8 +127127,8 @@ static int multiSelect(
if( dest.eDest!=priorOp ){
int iCont, iBreak, iStart;
assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(v);
- iCont = sqlite3VdbeMakeLabel(v);
+ iBreak = sqlite3VdbeMakeLabel(pParse);
+ iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
iStart = sqlite3VdbeCurrentAddr(v);
@@ -126816,8 +127196,8 @@ static int multiSelect(
** tables.
*/
assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(v);
- iCont = sqlite3VdbeMakeLabel(v);
+ iBreak = sqlite3VdbeMakeLabel(pParse);
+ iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
r1 = sqlite3GetTempReg(pParse);
@@ -126947,7 +127327,7 @@ static int generateOutputSubroutine(
int addr;
addr = sqlite3VdbeCurrentAddr(v);
- iContinue = sqlite3VdbeMakeLabel(v);
+ iContinue = sqlite3VdbeMakeLabel(pParse);
/* Suppress duplicates for UNION, EXCEPT, and INTERSECT
*/
@@ -127184,8 +127564,8 @@ static int multiSelectOrderBy(
db = pParse->db;
v = pParse->pVdbe;
assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */
- labelEnd = sqlite3VdbeMakeLabel(v);
- labelCmpr = sqlite3VdbeMakeLabel(v);
+ labelEnd = sqlite3VdbeMakeLabel(pParse);
+ labelCmpr = sqlite3VdbeMakeLabel(pParse);
/* Patch up the ORDER BY clause
@@ -127501,6 +127881,7 @@ static Expr *substExpr(
ifNullRow.iTable = pSubst->iNewTable;
pCopy = &ifNullRow;
}
+ testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
if( pNew && pSubst->isLeftJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
@@ -127993,11 +128374,9 @@ static int flattenSubquery(
jointype = pSubitem->fg.jointype;
}else{
assert( pParent!=p ); /* 2nd and subsequent times through the loop */
- pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pSrc==0 ){
- assert( db->mallocFailed );
- break;
- }
+ pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
+ if( pSrc==0 ) break;
+ pParent->pSrc = pSrc;
}
/* The subquery uses a single slot of the FROM clause of the outer
@@ -128016,10 +128395,9 @@ static int flattenSubquery(
** for the two elements in the FROM clause of the subquery.
*/
if( nSubSrc>1 ){
- pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
- if( db->mallocFailed ){
- break;
- }
+ pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
+ if( pSrc==0 ) break;
+ pParent->pSrc = pSrc;
}
/* Transfer the FROM clause terms from the subquery into the
@@ -128065,7 +128443,8 @@ static int flattenSubquery(
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}
- pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
+ pWhere = pSub->pWhere;
+ pSub->pWhere = 0;
if( isLeftJoin>0 ){
setJoinExpr(pWhere, iNewParent);
}
@@ -129368,7 +129747,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
regAgg = 0;
}
if( pF->iDistinct>=0 ){
- addrNext = sqlite3VdbeMakeLabel(v);
+ addrNext = sqlite3VdbeMakeLabel(pParse);
testcase( nArg==0 ); /* Error condition */
testcase( nArg>1 ); /* Also an error */
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
@@ -129778,6 +130157,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
if( flattenSubquery(pParse, p, i, isAgg) ){
+ if( pParse->nErr ) goto select_end;
/* This subquery can be absorbed into its parent. */
i = -1;
}
@@ -129873,22 +130253,12 @@ SQLITE_PRIVATE int sqlite3Select(
pSub = pItem->pSelect;
if( pSub==0 ) continue;
- /* Sometimes the code for a subquery will be generated more than
- ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
- ** for example. In that case, do not regenerate the code to manifest
- ** a view or the co-routine to implement a view. The first instance
- ** is sufficient, though the subroutine to manifest the view does need
- ** to be invoked again. */
- if( pItem->addrFillSub ){
- if( pItem->fg.viaCoroutine==0 ){
- /* The subroutine that manifests the view might be a one-time routine,
- ** or it might need to be rerun on each iteration because it
- ** encodes a correlated subquery. */
- testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once );
- sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
- }
- continue;
- }
+ /* The code for a subquery should only be generated once, though it is
+ ** technically harmless for it to be generated multiple times. The
+ ** following assert() will detect if something changes to cause
+ ** the same subquery to be coded multiple times, as a signal to the
+ ** developers to try to optimize the situation. */
+ assert( pItem->addrFillSub==0 );
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
@@ -130076,7 +130446,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Set the limiter.
*/
- iEnd = sqlite3VdbeMakeLabel(v);
+ iEnd = sqlite3VdbeMakeLabel(pParse);
if( (p->selFlags & SF_FixedLimit)==0 ){
p->nSelectRow = 320; /* 4 billion rows */
}
@@ -130143,9 +130513,9 @@ SQLITE_PRIVATE int sqlite3Select(
assert( p->pEList==pEList );
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pWin ){
- int addrGosub = sqlite3VdbeMakeLabel(v);
- int iCont = sqlite3VdbeMakeLabel(v);
- int iBreak = sqlite3VdbeMakeLabel(v);
+ int addrGosub = sqlite3VdbeMakeLabel(pParse);
+ int iCont = sqlite3VdbeMakeLabel(pParse);
+ int iBreak = sqlite3VdbeMakeLabel(pParse);
int regGosub = ++pParse->nMem;
sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);
@@ -130220,7 +130590,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
/* Create a label to jump to when we want to abort the query */
- addrEnd = sqlite3VdbeMakeLabel(v);
+ addrEnd = sqlite3VdbeMakeLabel(pParse);
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
@@ -130309,9 +130679,9 @@ SQLITE_PRIVATE int sqlite3Select(
iUseFlag = ++pParse->nMem;
iAbortFlag = ++pParse->nMem;
regOutputRow = ++pParse->nMem;
- addrOutputRow = sqlite3VdbeMakeLabel(v);
+ addrOutputRow = sqlite3VdbeMakeLabel(pParse);
regReset = ++pParse->nMem;
- addrReset = sqlite3VdbeMakeLabel(v);
+ addrReset = sqlite3VdbeMakeLabel(pParse);
iAMem = pParse->nMem + 1;
pParse->nMem += pGroupBy->nExpr;
iBMem = pParse->nMem + 1;
@@ -131598,7 +131968,7 @@ static SrcList *targetSrcList(
int iDb; /* Index of the database to use */
SrcList *pSrc; /* SrcList to be returned */
- pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
+ pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
assert( pSrc->nSrc>0 );
pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
@@ -131811,7 +132181,7 @@ static TriggerPrg *codeRowTrigger(
if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
&& db->mallocFailed==0
){
- iEndTrigger = sqlite3VdbeMakeLabel(v);
+ iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
}
sqlite3ExprDelete(db, pWhen);
@@ -132410,6 +132780,7 @@ SQLITE_PRIVATE void sqlite3Update(
** being updated. Fill in aRegIdx[] with a register number that will hold
** the key for accessing each index.
*/
+ if( onError==OE_Replace ) bReplace = 1;
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
if( chngKey || hasFK>1 || pIdx==pPk
@@ -132423,9 +132794,7 @@ SQLITE_PRIVATE void sqlite3Update(
if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
- if( (onError==OE_Replace)
- || (onError==OE_Default && pIdx->onError==OE_Replace)
- ){
+ if( onError==OE_Default && pIdx->onError==OE_Replace ){
bReplace = 1;
}
break;
@@ -132497,7 +132866,7 @@ SQLITE_PRIVATE void sqlite3Update(
#endif
/* Jump to labelBreak to abandon further processing of this UPDATE */
- labelContinue = labelBreak = sqlite3VdbeMakeLabel(v);
+ labelContinue = labelBreak = sqlite3VdbeMakeLabel(pParse);
/* Not an UPSERT. Normal processing. Begin by
** initialize the count of updated rows */
@@ -132632,13 +133001,13 @@ SQLITE_PRIVATE void sqlite3Update(
VdbeCoverage(v);
}
if( eOnePass!=ONEPASS_SINGLE ){
- labelContinue = sqlite3VdbeMakeLabel(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
}
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
VdbeCoverageIf(v, pPk==0);
VdbeCoverageIf(v, pPk!=0);
}else if( pPk ){
- labelContinue = sqlite3VdbeMakeLabel(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey);
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
@@ -133406,16 +133775,16 @@ static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){
** transient would cause the database file to appear to be deleted
** following reboot.
*/
-SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){
+SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){
Vdbe *v = sqlite3GetVdbe(pParse);
int iDb = 0;
- if( v==0 ) return;
+ if( v==0 ) goto build_vacuum_end;
if( pNm ){
#ifndef SQLITE_BUG_COMPATIBLE_20160819
/* Default behavior: Report an error if the argument to VACUUM is
** not recognized */
iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm);
- if( iDb<0 ) return;
+ if( iDb<0 ) goto build_vacuum_end;
#else
/* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
** to VACUUM are silently ignored. This is a back-out of a bug fix that
@@ -133427,21 +133796,33 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm){
#endif
}
if( iDb!=1 ){
- sqlite3VdbeAddOp1(v, OP_Vacuum, iDb);
+ int iIntoReg = 0;
+ if( pInto && sqlite3ResolveSelfReference(pParse,0,0,pInto,0)==0 ){
+ iIntoReg = ++pParse->nMem;
+ sqlite3ExprCode(pParse, pInto, iIntoReg);
+ }
+ sqlite3VdbeAddOp2(v, OP_Vacuum, iDb, iIntoReg);
sqlite3VdbeUsesBtree(v, iDb);
}
+build_vacuum_end:
+ sqlite3ExprDelete(pParse->db, pInto);
return;
}
/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
-SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
+SQLITE_PRIVATE int sqlite3RunVacuum(
+ char **pzErrMsg, /* Write error message here */
+ sqlite3 *db, /* Database connection */
+ int iDb, /* Which attached DB to vacuum */
+ sqlite3_value *pOut /* Write results here, if not NULL */
+){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
- u16 saved_mDbFlags; /* Saved value of db->mDbFlags */
- u32 saved_flags; /* Saved value of db->flags */
+ u32 saved_mDbFlags; /* Saved value of db->mDbFlags */
+ u64 saved_flags; /* Saved value of db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
u8 saved_mTrace; /* Saved trace settings */
@@ -133450,6 +133831,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
int nRes; /* Bytes of reserved space at the end of each page */
int nDb; /* Number of attached databases */
const char *zDbMain; /* Schema name of database to vacuum */
+ const char *zOut; /* Name of output file */
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
@@ -133459,6 +133841,15 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
return SQLITE_ERROR;
}
+ if( pOut ){
+ if( sqlite3_value_type(pOut)!=SQLITE_TEXT ){
+ sqlite3SetString(pzErrMsg, db, "non-text filename");
+ return SQLITE_ERROR;
+ }
+ zOut = (const char*)sqlite3_value_text(pOut);
+ }else{
+ zOut = "";
+ }
/* Save the current value of the database flags so that it can be
** restored before returning. Then set the writable-schema flag, and
@@ -133470,7 +133861,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
- db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder
+ db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);
db->mTrace = 0;
@@ -133493,19 +133884,21 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
** to write the journal header file.
*/
nDb = db->nDb;
- rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db");
+ rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
assert( (db->nDb-1)==nDb );
pDb = &db->aDb[nDb];
assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
pTemp = pDb->pBt;
-
- /* The call to execSql() to attach the temp database has left the file
- ** locked (as there was more than one active statement when the transaction
- ** to read the schema was concluded. Unlock it here so that this doesn't
- ** cause problems for the call to BtreeSetPageSize() below. */
- sqlite3BtreeCommit(pTemp);
-
+ if( pOut ){
+ sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
+ i64 sz = 0;
+ if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){
+ rc = SQLITE_ERROR;
+ sqlite3SetString(pzErrMsg, db, "output file already exists");
+ goto end_of_vacuum;
+ }
+ }
nRes = sqlite3BtreeGetOptimalReserve(pMain);
/* A VACUUM cannot change the pagesize of an encrypted database. */
@@ -133529,7 +133922,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
*/
rc = execSql(db, pzErrMsg, "BEGIN");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = sqlite3BtreeBeginTrans(pMain, 2, 0);
+ rc = sqlite3BtreeBeginTrans(pMain, pOut==0 ? 2 : 0, 0);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Do not attempt to change the page size for a WAL database */
@@ -133624,7 +134017,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
};
assert( 1==sqlite3BtreeIsInTrans(pTemp) );
- assert( 1==sqlite3BtreeIsInTrans(pMain) );
+ assert( pOut!=0 || 1==sqlite3BtreeIsInTrans(pMain) );
/* Copy Btree meta values */
for(i=0; i<ArraySize(aCopy); i+=2){
@@ -133635,17 +134028,23 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
if( NEVER(rc!=SQLITE_OK) ) goto end_of_vacuum;
}
- rc = sqlite3BtreeCopyFile(pMain, pTemp);
+ if( pOut==0 ){
+ rc = sqlite3BtreeCopyFile(pMain, pTemp);
+ }
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
#ifndef SQLITE_OMIT_AUTOVACUUM
- sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
+ if( pOut==0 ){
+ sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
+ }
#endif
}
assert( rc==SQLITE_OK );
- rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
+ if( pOut==0 ){
+ rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
+ }
end_of_vacuum:
/* Restore the original value of db->flags */
@@ -134686,6 +135085,7 @@ SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
const sqlite3_module *pMod = pVTab->pMod->pModule;
if( pVTab->pVtab && pMod->iVersion>=2 ){
int (*xMethod)(sqlite3_vtab *, int);
+ sqlite3VtabLock(pVTab);
switch( op ){
case SAVEPOINT_BEGIN:
xMethod = pMod->xSavepoint;
@@ -134701,6 +135101,7 @@ SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
if( xMethod && pVTab->iSavepoint>iSavepoint ){
rc = xMethod(pVTab->pVtab, iSavepoint);
}
+ sqlite3VtabUnlock(pVTab);
}
}
}
@@ -135462,8 +135863,11 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus(
# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d)
#endif
SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
+ Parse *pParse, /* Parsing context */
+ Vdbe *v, /* Prepared statement under construction */
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
+ WhereLevel *pLevel, /* The current level pointer */
Bitmask notReady /* Which tables are currently available */
);
@@ -135733,6 +136137,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
}
#endif
zMsg = sqlite3StrAccumFinish(&str);
+ sqlite3ExplainBreakpoint("",zMsg);
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
}
@@ -136058,16 +136463,17 @@ static int codeEqualityTerm(
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
}
+ iTab = 0;
if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0);
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
}else{
sqlite3 *db = pParse->db;
pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
if( !db->mallocFailed ){
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap);
- pTerm->pExpr->iTable = pX->iTable;
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
+ pTerm->pExpr->iTable = iTab;
}
sqlite3ExprDelete(db, pX);
pX = pTerm->pExpr;
@@ -136077,7 +136483,6 @@ static int codeEqualityTerm(
testcase( bRev );
bRev = !bRev;
}
- iTab = pX->iTable;
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
VdbeCoverageIf(v, bRev);
VdbeCoverageIf(v, !bRev);
@@ -136085,7 +136490,7 @@ static int codeEqualityTerm(
pLoop->wsFlags |= WHERE_IN_ABLE;
if( pLevel->u.in.nIn==0 ){
- pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
+ pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
}
i = pLevel->u.in.nIn;
@@ -136596,7 +137001,9 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
#ifndef SQLITE_OMIT_SUBQUERY
if( (p->flags & EP_xIsSelect) ){
Vdbe *v = pParse->pVdbe;
- int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0);
+ int iSelect;
+ assert( p->op==TK_SELECT );
+ iSelect = sqlite3CodeSubselect(pParse, p);
sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1);
}else
#endif
@@ -136682,22 +137089,21 @@ static void whereIndexExprTrans(
** implementation described by pWInfo.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
+ Parse *pParse, /* Parsing context */
+ Vdbe *v, /* Prepared statement under construction */
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
+ WhereLevel *pLevel, /* The current level pointer */
Bitmask notReady /* Which tables are currently available */
){
int j, k; /* Loop counters */
int iCur; /* The VDBE cursor for the table */
int addrNxt; /* Where to jump to continue with the next IN case */
- int omitTable; /* True if we use the index only */
int bRev; /* True if we need to scan in reverse order */
- WhereLevel *pLevel; /* The where level to be coded */
WhereLoop *pLoop; /* The WhereLoop object being coded */
WhereClause *pWC; /* Decomposition of the entire WHERE clause */
WhereTerm *pTerm; /* A WHERE clause term */
- Parse *pParse; /* Parsing context */
sqlite3 *db; /* Database connection */
- Vdbe *v; /* The prepared stmt under constructions */
struct SrcList_item *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
int addrHalt; /* addrBrk for the outermost loop */
@@ -136707,18 +137113,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
Index *pIdx = 0; /* Index used by loop (if any) */
int iLoop; /* Iteration of constraint generator loop */
- pParse = pWInfo->pParse;
- v = pParse->pVdbe;
pWC = &pWInfo->sWC;
db = pParse->db;
- pLevel = &pWInfo->a[iLevel];
pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
- omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0;
VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
/* Create labels for the "break" and "continue" instructions
@@ -136731,8 +137132,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** there are no IN operators in the constraints, the "addrNxt" label
** is the same as "addrBrk".
*/
- addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
- addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v);
+ addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
+ addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);
/* If this is the right table of a LEFT OUTER JOIN, allocate and
** initialize a memory cell that records if this table matches any
@@ -136859,7 +137260,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
- assert( omitTable==0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
iReleaseReg = ++pParse->nMem;
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
@@ -136878,7 +137278,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int memEndValue = 0;
WhereTerm *pStart, *pEnd;
- assert( omitTable==0 );
j = 0;
pStart = pEnd = 0;
if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++];
@@ -137042,6 +137441,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
char *zEndAff = 0; /* Affinity for end of range constraint */
u8 bSeekPastNull = 0; /* True to seek past initial nulls */
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
+ int omitTable; /* True if we use the index only */
+
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
@@ -137243,6 +137644,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
/* Seek the table cursor, if required */
+ omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
+ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0;
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
@@ -137277,8 +137680,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** the cursor. In this case it is important to do the full evaluation,
** as the result of the expression may not be NULL, even if all table
** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
+ **
+ ** Also, do not do this when processing one index an a multi-index
+ ** OR clause, since the transformation will become invalid once we
+ ** move forward to the next index.
+ ** https://sqlite.org/src/info/4e8e4857d32d401f
*/
- if( pLevel->iLeftJoin==0 ){
+ if( pLevel->iLeftJoin==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
}
@@ -137353,7 +137761,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
int regRowset = 0; /* Register for RowSet object */
int regRowid = 0; /* Register holding rowid */
- int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
+ int iLoopBody = sqlite3VdbeMakeLabel(pParse);/* Start of loop body */
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
@@ -137469,6 +137877,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
pOrExpr = pAndExpr;
}
/* Loop through table entries that match term pOrTerm. */
+ ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
wctrlFlags, iCovCur);
@@ -137572,6 +137981,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
+ ExplainQueryPlanPop(pParse);
}
}
}
@@ -138533,6 +138943,7 @@ static void exprAnalyzeOrTerm(
** and column is found but leave okToChngToIN false if not found.
*/
for(j=0; j<2 && !okToChngToIN; j++){
+ Expr *pLeft = 0;
pOrTerm = pOrWc->a;
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
assert( pOrTerm->eOperator & WO_EQ );
@@ -138556,6 +138967,7 @@ static void exprAnalyzeOrTerm(
}
iColumn = pOrTerm->u.leftColumn;
iCursor = pOrTerm->leftCursor;
+ pLeft = pOrTerm->pExpr->pLeft;
break;
}
if( i<0 ){
@@ -138575,7 +138987,9 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->eOperator & WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OR_OK;
- }else if( pOrTerm->u.leftColumn!=iColumn ){
+ }else if( pOrTerm->u.leftColumn!=iColumn || (iColumn==XN_EXPR
+ && sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
+ )){
okToChngToIN = 0;
}else{
int affLeft, affRight;
@@ -139664,6 +140078,17 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
/*
+** This is whereScanInit() for the case of an index on an expression.
+** It is factored out into a separate tail-recursion subroutine so that
+** the normal whereScanInit() routine, which is a high-runner, does not
+** need to push registers onto the stack as part of its prologue.
+*/
+static SQLITE_NOINLINE WhereTerm *whereScanInitIndexExpr(WhereScan *pScan){
+ pScan->idxaff = sqlite3ExprAffinity(pScan->pIdxExpr);
+ return whereScanNext(pScan);
+}
+
+/*
** Initialize a WHERE clause scanner object. Return a pointer to the
** first match. Return NULL if there are no matches.
**
@@ -139695,12 +140120,19 @@ static WhereTerm *whereScanInit(
pScan->pIdxExpr = 0;
pScan->idxaff = 0;
pScan->zCollName = 0;
+ pScan->opMask = opMask;
+ pScan->k = 0;
+ pScan->aiCur[0] = iCur;
+ pScan->nEquiv = 1;
+ pScan->iEquiv = 1;
if( pIdx ){
int j = iColumn;
iColumn = pIdx->aiColumn[j];
if( iColumn==XN_EXPR ){
pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
pScan->zCollName = pIdx->azColl[j];
+ pScan->aiColumn[0] = XN_EXPR;
+ return whereScanInitIndexExpr(pScan);
}else if( iColumn==pIdx->pTable->iPKey ){
iColumn = XN_ROWID;
}else if( iColumn>=0 ){
@@ -139710,12 +140142,7 @@ static WhereTerm *whereScanInit(
}else if( iColumn==XN_EXPR ){
return 0;
}
- pScan->opMask = opMask;
- pScan->k = 0;
- pScan->aiCur[0] = iCur;
pScan->aiColumn[0] = iColumn;
- pScan->nEquiv = 1;
- pScan->iEquiv = 1;
return whereScanNext(pScan);
}
@@ -140190,7 +140617,7 @@ static void constructAutomaticIndex(
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
}
if( pPartial ){
- iContinue = sqlite3VdbeMakeLabel(v);
+ iContinue = sqlite3VdbeMakeLabel(pParse);
sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL);
pLoop->wsFlags |= WHERE_PARTIALIDX;
}
@@ -140207,6 +140634,7 @@ static void constructAutomaticIndex(
translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
pTabItem->regResult, 1);
sqlite3VdbeGoto(v, addrTop);
+ pTabItem->fg.viaCoroutine = 0;
}else{
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
}
@@ -141562,7 +141990,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
rc = whereLoopXfer(db, p, pTemplate);
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
Index *pIndex = p->u.btree.pIndex;
- if( pIndex && pIndex->tnum==0 ){
+ if( pIndex && pIndex->idxType==SQLITE_IDXTYPE_IPK ){
p->u.btree.pIndex = 0;
}
}
@@ -141729,8 +142157,8 @@ static int whereRangeVectorLen(
** terms only. If it is modified, this value is restored before this
** function returns.
**
-** If pProbe->tnum==0, that means pIndex is a fake index used for the
-** INTEGER PRIMARY KEY.
+** If pProbe->idxType==SQLITE_IDXTYPE_IPK, that means pIndex is
+** a fake index used for the INTEGER PRIMARY KEY.
*/
static int whereLoopAddBtreeIndex(
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
@@ -142230,6 +142658,7 @@ static int whereLoopAddBtree(
sPk.onError = OE_Replace;
sPk.pTable = pTab;
sPk.szIdxRow = pTab->szTabRow;
+ sPk.idxType = SQLITE_IDXTYPE_IPK;
aiRowEstPk[0] = pTab->nRowLogEst;
aiRowEstPk[1] = 0;
pFirst = pSrc->pTab->pIndex;
@@ -142320,7 +142749,7 @@ static int whereLoopAddBtree(
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
/* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
- if( pProbe->tnum<=0 ){
+ if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
/* Integer primary key index */
pNew->wsFlags = WHERE_IPK;
@@ -143996,7 +144425,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWInfo->pResultSet = pResultSet;
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
pWInfo->nLevel = nTabList;
- pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
+ pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse);
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->iLimit = iAuxArg;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
@@ -144270,9 +144699,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
+ assert( !(wsFlags & WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pTab) );
if( bOnerow || (
0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW)
- && 0==(wsFlags & WHERE_VIRTUALTABLE)
+ && !IsVirtual(pTabList->a[0].pTab)
&& (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK))
)){
pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
@@ -144427,7 +144857,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pParse, pTabList, pLevel, wctrlFlags
);
pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
- notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady);
+ notReady = sqlite3WhereCodeOneLoopStart(pParse,v,pWInfo,ii,pLevel,notReady);
pWInfo->iContinue = pLevel->addrCont;
if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){
sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain);
@@ -144612,6 +145042,29 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
continue;
}
+#ifdef SQLITE_ENABLE_EARLY_CURSOR_CLOSE
+ /* Close all of the cursors that were opened by sqlite3WhereBegin.
+ ** Except, do not close cursors that will be reused by the OR optimization
+ ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors
+ ** created for the ONEPASS optimization.
+ */
+ if( (pTab->tabFlags & TF_Ephemeral)==0
+ && pTab->pSelect==0
+ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
+ ){
+ int ws = pLoop->wsFlags;
+ if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
+ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
+ }
+ if( (ws & WHERE_INDEXED)!=0
+ && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0
+ && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1]
+ ){
+ sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
+ }
+ }
+#endif
+
/* If this scan uses an index, make VDBE code substitutions to read data
** from the index instead of from the table where possible. In some cases
** this optimization prevents the table from ever being read, which can
@@ -145511,8 +145964,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
pSub = sqlite3SelectNew(
pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
);
- p->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- assert( p->pSrc || db->mallocFailed );
+ p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( p->pSrc ){
p->pSrc->a[0].pSelect = pSub;
sqlite3SrcListAssignCursors(pParse, p->pSrc);
@@ -145569,6 +146021,7 @@ SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p){
*/
static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){
if( 0==sqlite3ExprIsConstant(pExpr) ){
+ if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr);
sqlite3ExprDelete(pParse->db, pExpr);
pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0);
}
@@ -145763,6 +146216,7 @@ static void windowCheckIntValue(Parse *pParse, int reg, int eCond){
VdbeCoverageNeverNullIf(v, eCond==0);
VdbeCoverageNeverNullIf(v, eCond==1);
VdbeCoverageNeverNullIf(v, eCond==2);
+ sqlite3MayAbort(pParse);
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC);
sqlite3ReleaseTempReg(pParse, regZero);
@@ -146018,7 +146472,7 @@ static void windowReturnOneRow(
|| pFunc->zName==first_valueName
){
int csr = pWin->csrApp;
- int lbl = sqlite3VdbeMakeLabel(v);
+ int lbl = sqlite3VdbeMakeLabel(pParse);
int tmpReg = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
@@ -146041,7 +146495,7 @@ static void windowReturnOneRow(
int nArg = pWin->pOwner->x.pList->nExpr;
int iEph = pMWin->iEphCsr;
int csr = pWin->csrApp;
- int lbl = sqlite3VdbeMakeLabel(v);
+ int lbl = sqlite3VdbeMakeLabel(pParse);
int tmpReg = sqlite3GetTempReg(pParse);
if( nArg<3 ){
@@ -146302,8 +146756,8 @@ static void windowCodeRowExprStep(
/* Allocate register and label for the "flush_partition" sub-routine. */
regFlushPart = ++pParse->nMem;
- lblFlushPart = sqlite3VdbeMakeLabel(v);
- lblFlushDone = sqlite3VdbeMakeLabel(v);
+ lblFlushPart = sqlite3VdbeMakeLabel(pParse);
+ lblFlushDone = sqlite3VdbeMakeLabel(pParse);
regStart = ++pParse->nMem;
regEnd = ++pParse->nMem;
@@ -146413,7 +146867,7 @@ static void windowCodeRowExprStep(
|| pMWin->eStart==TK_PRECEDING
|| pMWin->eStart==TK_FOLLOWING
){
- int lblSkipInverse = sqlite3VdbeMakeLabel(v);;
+ int lblSkipInverse = sqlite3VdbeMakeLabel(pParse);;
if( pMWin->eStart==TK_PRECEDING ){
sqlite3VdbeAddOp3(v, OP_IfPos, regStart, lblSkipInverse, 1);
VdbeCoverage(v);
@@ -146578,13 +147032,13 @@ static void windowCodeCacheStep(
|| (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED)
);
- lblEmpty = sqlite3VdbeMakeLabel(v);
+ lblEmpty = sqlite3VdbeMakeLabel(pParse);
regNewPeer = pParse->nMem+1;
pParse->nMem += nPeer;
/* Allocate register and label for the "flush_partition" sub-routine. */
regFlushPart = ++pParse->nMem;
- lblFlushPart = sqlite3VdbeMakeLabel(v);
+ lblFlushPart = sqlite3VdbeMakeLabel(pParse);
csrLead = pParse->nTab++;
regCtr = ++pParse->nMem;
@@ -146821,6 +147275,7 @@ SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
if( pNew ){
pNew->zName = sqlite3DbStrDup(db, p->zName);
pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
+ pNew->pFunc = p->pFunc;
pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
pNew->eType = p->eType;
@@ -147078,8 +147533,7 @@ static void disableLookaside(Parse *pParse){
memcpy(p->u.zToken, t.z, t.n);
p->u.zToken[t.n] = 0;
if( sqlite3Isquote(p->u.zToken[0]) ){
- if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted;
- sqlite3Dequote(p->u.zToken);
+ sqlite3DequoteExpr(p);
}
#if SQLITE_MAX_EXPR_DEPTH>0
p->nHeight = 1;
@@ -147187,26 +147641,26 @@ static void disableLookaside(Parse *pParse){
# define INTERFACE 1
#endif
/************* Begin control #defines *****************************************/
-#define YYCODETYPE unsigned char
-#define YYNOCODE 255
+#define YYCODETYPE unsigned short int
+#define YYNOCODE 256
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 85
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlite3ParserTOKENTYPE yy0;
- const char* yy36;
- TriggerStep* yy47;
- With* yy91;
- struct {int value; int mask;} yy107;
- Expr* yy182;
- Upsert* yy198;
- ExprList* yy232;
- struct TrigEvent yy300;
- Select* yy399;
- SrcList* yy427;
- int yy502;
- IdList* yy510;
+ Expr* yy2;
+ SrcList* yy3;
+ With* yy4;
+ Select* yy43;
+ struct {int value; int mask;} yy239;
+ Upsert* yy258;
+ IdList* yy272;
+ struct TrigEvent yy338;
+ TriggerStep* yy347;
+ int yy348;
+ const char* yy360;
+ ExprList* yy402;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -147222,17 +147676,17 @@ typedef union {
#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse;
#define sqlite3ParserCTX_STORE yypParser->pParse=pParse;
#define YYFALLBACK 1
-#define YYNSTATE 484
-#define YYNRULE 334
+#define YYNSTATE 487
+#define YYNRULE 336
#define YYNTOKEN 146
-#define YY_MAX_SHIFT 483
-#define YY_MIN_SHIFTREDUCE 696
-#define YY_MAX_SHIFTREDUCE 1029
-#define YY_ERROR_ACTION 1030
-#define YY_ACCEPT_ACTION 1031
-#define YY_NO_ACTION 1032
-#define YY_MIN_REDUCE 1033
-#define YY_MAX_REDUCE 1366
+#define YY_MAX_SHIFT 486
+#define YY_MIN_SHIFTREDUCE 700
+#define YY_MAX_SHIFTREDUCE 1035
+#define YY_ERROR_ACTION 1036
+#define YY_ACCEPT_ACTION 1037
+#define YY_NO_ACTION 1038
+#define YY_MIN_REDUCE 1039
+#define YY_MAX_REDUCE 1374
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@@ -147299,493 +147753,494 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (1614)
+#define YY_ACTTAB_COUNT (1617)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 478, 1102, 1102, 97, 94, 182, 97, 94, 182, 1031,
- /* 10 */ 1, 1, 483, 1033, 229, 229, 347, 448, 258, 1114,
- /* 20 */ 119, 57, 57, 1291, 1097, 1076, 475, 1110, 824, 449,
- /* 30 */ 475, 1160, 5, 1097, 214, 123, 825, 28, 12, 12,
- /* 40 */ 303, 104, 105, 95, 1007, 1007, 888, 891, 881, 881,
- /* 50 */ 102, 102, 103, 103, 103, 103, 460, 403, 1330, 235,
- /* 60 */ 235, 235, 235, 236, 236, 450, 1071, 1311, 483, 1033,
- /* 70 */ 1005, 475, 347, 475, 258, 475, 119, 211, 179, 81,
- /* 80 */ 97, 94, 182, 1110, 191, 125, 101, 101, 101, 101,
- /* 90 */ 100, 100, 99, 99, 99, 98, 378, 104, 105, 95,
- /* 100 */ 1007, 1007, 888, 891, 881, 881, 102, 102, 103, 103,
- /* 110 */ 103, 103, 380, 1005, 108, 235, 235, 345, 100, 100,
- /* 120 */ 99, 99, 99, 98, 378, 106, 241, 475, 347, 101,
- /* 130 */ 101, 101, 101, 100, 100, 99, 99, 99, 98, 378,
- /* 140 */ 191, 378, 101, 101, 101, 101, 100, 100, 99, 99,
- /* 150 */ 99, 98, 378, 104, 105, 95, 1007, 1007, 888, 891,
- /* 160 */ 881, 881, 102, 102, 103, 103, 103, 103, 380, 99,
- /* 170 */ 99, 99, 98, 378, 478, 396, 278, 203, 185, 66,
- /* 180 */ 433, 430, 429, 986, 347, 175, 174, 1159, 210, 67,
- /* 190 */ 428, 878, 878, 889, 892, 57, 57, 342, 101, 101,
- /* 200 */ 101, 101, 100, 100, 99, 99, 99, 98, 378, 104,
- /* 210 */ 105, 95, 1007, 1007, 888, 891, 881, 881, 102, 102,
- /* 220 */ 103, 103, 103, 103, 1022, 986, 987, 988, 203, 868,
- /* 230 */ 460, 433, 430, 429, 230, 343, 97, 94, 182, 459,
- /* 240 */ 347, 428, 968, 1360, 292, 861, 1360, 98, 378, 860,
- /* 250 */ 986, 882, 375, 374, 101, 101, 101, 101, 100, 100,
- /* 260 */ 99, 99, 99, 98, 378, 104, 105, 95, 1007, 1007,
- /* 270 */ 888, 891, 881, 881, 102, 102, 103, 103, 103, 103,
- /* 280 */ 860, 860, 862, 478, 1191, 478, 257, 469, 97, 94,
- /* 290 */ 182, 167, 986, 987, 988, 290, 347, 1014, 1004, 1014,
- /* 300 */ 732, 850, 986, 334, 57, 57, 57, 57, 966, 142,
- /* 310 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98,
- /* 320 */ 378, 104, 105, 95, 1007, 1007, 888, 891, 881, 881,
- /* 330 */ 102, 102, 103, 103, 103, 103, 478, 790, 277, 460,
- /* 340 */ 1191, 455, 405, 478, 986, 987, 988, 1334, 439, 257,
- /* 350 */ 469, 360, 347, 472, 472, 472, 725, 56, 56, 285,
- /* 360 */ 336, 288, 142, 420, 57, 57, 101, 101, 101, 101,
- /* 370 */ 100, 100, 99, 99, 99, 98, 378, 104, 105, 95,
- /* 380 */ 1007, 1007, 888, 891, 881, 881, 102, 102, 103, 103,
- /* 390 */ 103, 103, 235, 235, 270, 478, 351, 968, 1361, 373,
- /* 400 */ 171, 1361, 257, 469, 475, 383, 986, 361, 347, 376,
- /* 410 */ 376, 376, 869, 318, 929, 850, 57, 57, 87, 401,
- /* 420 */ 85, 149, 101, 101, 101, 101, 100, 100, 99, 99,
- /* 430 */ 99, 98, 378, 104, 105, 95, 1007, 1007, 888, 891,
- /* 440 */ 881, 881, 102, 102, 103, 103, 103, 103, 986, 987,
- /* 450 */ 988, 377, 277, 391, 265, 477, 8, 381, 267, 356,
- /* 460 */ 269, 167, 986, 966, 347, 934, 934, 417, 855, 325,
- /* 470 */ 315, 414, 931, 339, 411, 263, 931, 163, 101, 101,
- /* 480 */ 101, 101, 100, 100, 99, 99, 99, 98, 378, 104,
- /* 490 */ 105, 95, 1007, 1007, 888, 891, 881, 881, 102, 102,
- /* 500 */ 103, 103, 103, 103, 986, 987, 988, 235, 235, 415,
- /* 510 */ 476, 478, 780, 780, 699, 700, 701, 396, 278, 475,
- /* 520 */ 347, 166, 1100, 1100, 268, 264, 395, 206, 205, 204,
- /* 530 */ 454, 275, 42, 42, 101, 101, 101, 101, 100, 100,
- /* 540 */ 99, 99, 99, 98, 378, 104, 105, 95, 1007, 1007,
- /* 550 */ 888, 891, 881, 881, 102, 102, 103, 103, 103, 103,
- /* 560 */ 386, 180, 1260, 235, 235, 356, 478, 317, 331, 1027,
- /* 570 */ 331, 967, 1362, 332, 256, 475, 347, 386, 385, 1260,
- /* 580 */ 1262, 303, 303, 344, 1108, 1298, 1051, 43, 43, 442,
- /* 590 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98,
- /* 600 */ 378, 104, 105, 95, 1007, 1007, 888, 891, 881, 881,
- /* 610 */ 102, 102, 103, 103, 103, 103, 235, 235, 235, 235,
- /* 620 */ 403, 235, 235, 403, 785, 356, 127, 124, 475, 784,
- /* 630 */ 475, 242, 347, 475, 1028, 420, 1028, 168, 420, 420,
- /* 640 */ 445, 420, 386, 463, 1260, 83, 101, 101, 101, 101,
- /* 650 */ 100, 100, 99, 99, 99, 98, 378, 104, 105, 95,
- /* 660 */ 1007, 1007, 888, 891, 881, 881, 102, 102, 103, 103,
- /* 670 */ 103, 103, 235, 235, 478, 235, 235, 1290, 478, 1191,
- /* 680 */ 1256, 1109, 1191, 1105, 475, 382, 420, 475, 347, 245,
- /* 690 */ 303, 243, 246, 990, 304, 11, 11, 409, 304, 33,
- /* 700 */ 33, 86, 101, 101, 101, 101, 100, 100, 99, 99,
- /* 710 */ 99, 98, 378, 104, 105, 95, 1007, 1007, 888, 891,
- /* 720 */ 881, 881, 102, 102, 103, 103, 103, 103, 283, 478,
- /* 730 */ 364, 478, 1295, 1191, 371, 126, 990, 1054, 353, 471,
- /* 740 */ 353, 8, 257, 469, 347, 176, 362, 354, 143, 416,
- /* 750 */ 44, 44, 45, 45, 103, 103, 103, 103, 101, 101,
- /* 760 */ 101, 101, 100, 100, 99, 99, 99, 98, 378, 104,
- /* 770 */ 93, 95, 1007, 1007, 888, 891, 881, 881, 102, 102,
- /* 780 */ 103, 103, 103, 103, 478, 451, 478, 244, 101, 101,
- /* 790 */ 101, 101, 100, 100, 99, 99, 99, 98, 378, 347,
- /* 800 */ 372, 234, 179, 188, 207, 46, 46, 47, 47, 409,
- /* 810 */ 409, 410, 80, 438, 101, 101, 101, 101, 100, 100,
- /* 820 */ 99, 99, 99, 98, 378, 105, 95, 1007, 1007, 888,
- /* 830 */ 891, 881, 881, 102, 102, 103, 103, 103, 103, 785,
- /* 840 */ 1333, 478, 824, 755, 784, 963, 274, 262, 333, 80,
- /* 850 */ 825, 745, 744, 347, 78, 369, 1258, 157, 352, 122,
- /* 860 */ 752, 753, 48, 48, 13, 928, 735, 928, 452, 101,
- /* 870 */ 101, 101, 101, 100, 100, 99, 99, 99, 98, 378,
- /* 880 */ 95, 1007, 1007, 888, 891, 881, 881, 102, 102, 103,
- /* 890 */ 103, 103, 103, 90, 470, 986, 3, 721, 737, 276,
- /* 900 */ 247, 711, 301, 407, 397, 950, 190, 1145, 852, 735,
- /* 910 */ 473, 213, 300, 402, 1144, 232, 213, 390, 809, 927,
- /* 920 */ 951, 927, 746, 101, 101, 101, 101, 100, 100, 99,
- /* 930 */ 99, 99, 98, 378, 379, 366, 952, 986, 987, 988,
- /* 940 */ 721, 221, 238, 302, 436, 297, 435, 208, 467, 90,
- /* 950 */ 470, 986, 3, 295, 434, 388, 22, 766, 142, 404,
- /* 960 */ 142, 868, 213, 394, 747, 1301, 473, 88, 88, 767,
- /* 970 */ 158, 271, 1279, 1080, 89, 167, 379, 480, 479, 1079,
- /* 980 */ 1278, 860, 387, 214, 375, 374, 408, 346, 23, 911,
- /* 990 */ 379, 1078, 1011, 986, 987, 988, 181, 1013, 257, 469,
- /* 1000 */ 257, 469, 412, 367, 467, 1012, 280, 249, 986, 249,
- /* 1010 */ 4, 425, 860, 860, 862, 863, 19, 868, 1141, 1005,
- /* 1020 */ 284, 809, 918, 88, 88, 789, 1249, 287, 289, 1014,
- /* 1030 */ 89, 1014, 379, 480, 479, 986, 2, 860, 398, 207,
- /* 1040 */ 90, 470, 478, 3, 291, 478, 279, 1132, 986, 80,
- /* 1050 */ 986, 987, 988, 461, 1093, 1077, 440, 473, 82, 470,
- /* 1060 */ 847, 3, 1005, 57, 57, 918, 38, 38, 860, 860,
- /* 1070 */ 862, 863, 19, 426, 986, 473, 209, 986, 987, 988,
- /* 1080 */ 293, 379, 237, 80, 478, 235, 235, 986, 235, 235,
- /* 1090 */ 986, 987, 988, 352, 864, 467, 950, 475, 460, 379,
- /* 1100 */ 475, 441, 296, 305, 811, 9, 9, 462, 868, 295,
- /* 1110 */ 306, 951, 1153, 467, 88, 88, 986, 987, 988, 358,
- /* 1120 */ 809, 89, 1190, 379, 480, 479, 868, 952, 860, 986,
- /* 1130 */ 987, 988, 88, 88, 1128, 254, 478, 864, 1139, 89,
- /* 1140 */ 464, 379, 480, 479, 914, 465, 860, 209, 466, 818,
- /* 1150 */ 1196, 478, 213, 478, 1060, 1053, 810, 34, 34, 860,
- /* 1160 */ 860, 862, 863, 19, 1042, 1041, 103, 103, 103, 103,
- /* 1170 */ 96, 1043, 9, 9, 9, 9, 1317, 860, 860, 862,
- /* 1180 */ 863, 19, 1310, 976, 239, 421, 363, 1323, 365, 329,
- /* 1190 */ 329, 328, 224, 326, 478, 169, 708, 1125, 181, 478,
- /* 1200 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98,
- /* 1210 */ 378, 261, 227, 7, 308, 9, 9, 478, 310, 260,
- /* 1220 */ 9, 9, 478, 809, 478, 312, 478, 173, 478, 248,
- /* 1230 */ 782, 330, 478, 92, 457, 478, 184, 728, 35, 35,
- /* 1240 */ 389, 1175, 266, 37, 37, 49, 49, 50, 50, 51,
- /* 1250 */ 51, 1183, 186, 10, 10, 478, 52, 52, 177, 719,
- /* 1260 */ 187, 478, 121, 137, 868, 976, 239, 431, 478, 338,
- /* 1270 */ 478, 329, 329, 328, 224, 326, 110, 110, 708, 728,
- /* 1280 */ 861, 1076, 53, 53, 860, 478, 299, 478, 273, 39,
- /* 1290 */ 39, 54, 54, 261, 406, 1253, 783, 478, 348, 92,
- /* 1300 */ 478, 260, 478, 257, 469, 1252, 55, 55, 40, 40,
- /* 1310 */ 478, 314, 323, 468, 478, 860, 860, 862, 131, 131,
- /* 1320 */ 172, 132, 132, 62, 62, 1320, 384, 478, 1022, 478,
- /* 1330 */ 1019, 41, 41, 145, 186, 58, 58, 478, 65, 68,
- /* 1340 */ 478, 216, 187, 478, 400, 137, 478, 1180, 111, 111,
- /* 1350 */ 59, 59, 355, 478, 155, 478, 140, 478, 112, 112,
- /* 1360 */ 478, 113, 113, 25, 109, 109, 147, 130, 130, 478,
- /* 1370 */ 78, 478, 392, 478, 129, 129, 117, 117, 116, 116,
- /* 1380 */ 348, 114, 114, 478, 1172, 257, 469, 393, 478, 150,
- /* 1390 */ 115, 115, 61, 61, 63, 63, 424, 478, 337, 151,
- /* 1400 */ 152, 193, 153, 26, 60, 60, 335, 413, 384, 32,
- /* 1410 */ 32, 197, 399, 1186, 159, 1247, 419, 73, 36, 36,
- /* 1420 */ 228, 199, 164, 286, 1267, 282, 200, 422, 1044, 340,
- /* 1430 */ 201, 437, 1096, 1095, 1094, 368, 737, 1087, 341, 1067,
- /* 1440 */ 370, 1068, 298, 453, 77, 252, 1136, 253, 1066, 1332,
- /* 1450 */ 307, 215, 309, 1086, 444, 6, 311, 447, 1137, 316,
- /* 1460 */ 1135, 1233, 1134, 84, 255, 313, 458, 107, 222, 79,
- /* 1470 */ 456, 1050, 24, 481, 981, 223, 225, 226, 482, 349,
- /* 1480 */ 1039, 1118, 1034, 133, 321, 319, 320, 322, 170, 120,
- /* 1490 */ 1283, 350, 1284, 250, 259, 134, 1282, 1281, 183, 240,
- /* 1500 */ 118, 926, 144, 1064, 1063, 924, 64, 844, 135, 1061,
- /* 1510 */ 146, 136, 189, 148, 769, 272, 192, 940, 154, 138,
- /* 1520 */ 848, 357, 359, 156, 69, 139, 70, 71, 72, 943,
- /* 1530 */ 194, 195, 939, 14, 128, 196, 932, 281, 213, 160,
- /* 1540 */ 1016, 418, 198, 161, 27, 710, 423, 300, 202, 427,
- /* 1550 */ 432, 748, 162, 74, 15, 141, 294, 16, 75, 251,
- /* 1560 */ 867, 866, 894, 178, 971, 29, 76, 30, 443, 972,
- /* 1570 */ 165, 446, 231, 233, 812, 779, 212, 817, 92, 80,
- /* 1580 */ 909, 895, 893, 897, 949, 17, 898, 948, 18, 217,
- /* 1590 */ 218, 20, 31, 474, 865, 720, 91, 327, 21, 977,
- /* 1600 */ 324, 1032, 1032, 219, 220, 1032, 1032, 1032, 1325, 1032,
- /* 1610 */ 1032, 1032, 1032, 1324,
+ /* 0 */ 99, 96, 185, 481, 1108, 1108, 232, 408, 1037, 1,
+ /* 10 */ 1, 486, 1039, 481, 1103, 1082, 350, 260, 451, 121,
+ /* 20 */ 348, 1299, 1120, 1103, 9, 9, 1116, 345, 828, 99,
+ /* 30 */ 96, 185, 452, 478, 58, 58, 829, 13, 361, 12,
+ /* 40 */ 12, 106, 107, 97, 1013, 1013, 892, 895, 885, 885,
+ /* 50 */ 104, 104, 105, 105, 105, 105, 1106, 1106, 237, 237,
+ /* 60 */ 99, 96, 185, 481, 237, 237, 1319, 486, 1039, 463,
+ /* 70 */ 478, 346, 350, 260, 992, 121, 478, 400, 453, 83,
+ /* 80 */ 213, 182, 1116, 193, 57, 57, 103, 103, 103, 103,
+ /* 90 */ 102, 102, 101, 101, 101, 100, 381, 106, 107, 97,
+ /* 100 */ 1013, 1013, 892, 895, 885, 885, 104, 104, 105, 105,
+ /* 110 */ 105, 105, 383, 481, 237, 237, 992, 993, 994, 205,
+ /* 120 */ 399, 281, 436, 433, 432, 108, 478, 381, 350, 974,
+ /* 130 */ 1368, 1166, 431, 1368, 58, 58, 475, 475, 475, 193,
+ /* 140 */ 321, 480, 103, 103, 103, 103, 102, 102, 101, 101,
+ /* 150 */ 101, 100, 381, 106, 107, 97, 1013, 1013, 892, 895,
+ /* 160 */ 885, 885, 104, 104, 105, 105, 105, 105, 383, 463,
+ /* 170 */ 102, 102, 101, 101, 101, 100, 381, 273, 462, 67,
+ /* 180 */ 99, 96, 185, 205, 350, 170, 436, 433, 432, 68,
+ /* 190 */ 101, 101, 101, 100, 381, 972, 431, 337, 103, 103,
+ /* 200 */ 103, 103, 102, 102, 101, 101, 101, 100, 381, 106,
+ /* 210 */ 107, 97, 1013, 1013, 892, 895, 885, 885, 104, 104,
+ /* 220 */ 105, 105, 105, 105, 481, 401, 103, 103, 103, 103,
+ /* 230 */ 102, 102, 101, 101, 101, 100, 381, 1165, 974, 1369,
+ /* 240 */ 350, 270, 1369, 272, 295, 58, 58, 851, 992, 882,
+ /* 250 */ 882, 893, 896, 1342, 103, 103, 103, 103, 102, 102,
+ /* 260 */ 101, 101, 101, 100, 381, 106, 107, 97, 1013, 1013,
+ /* 270 */ 892, 895, 885, 885, 104, 104, 105, 105, 105, 105,
+ /* 280 */ 463, 231, 231, 794, 318, 872, 99, 96, 185, 442,
+ /* 290 */ 992, 993, 994, 478, 378, 377, 350, 703, 704, 705,
+ /* 300 */ 736, 865, 992, 1341, 972, 864, 759, 271, 145, 886,
+ /* 310 */ 103, 103, 103, 103, 102, 102, 101, 101, 101, 100,
+ /* 320 */ 381, 106, 107, 97, 1013, 1013, 892, 895, 885, 885,
+ /* 330 */ 104, 104, 105, 105, 105, 105, 864, 864, 866, 1020,
+ /* 340 */ 481, 1020, 481, 179, 992, 993, 994, 457, 259, 472,
+ /* 350 */ 100, 381, 350, 379, 379, 379, 729, 212, 1370, 335,
+ /* 360 */ 183, 58, 58, 58, 58, 854, 103, 103, 103, 103,
+ /* 370 */ 102, 102, 101, 101, 101, 100, 381, 106, 107, 97,
+ /* 380 */ 1013, 1013, 892, 895, 885, 885, 104, 104, 105, 105,
+ /* 390 */ 105, 105, 481, 170, 481, 8, 458, 359, 376, 320,
+ /* 400 */ 406, 328, 280, 394, 268, 342, 238, 238, 350, 423,
+ /* 410 */ 935, 854, 873, 42, 42, 58, 58, 306, 478, 145,
+ /* 420 */ 1306, 266, 103, 103, 103, 103, 102, 102, 101, 101,
+ /* 430 */ 101, 100, 381, 106, 107, 97, 1013, 1013, 892, 895,
+ /* 440 */ 885, 885, 104, 104, 105, 105, 105, 105, 280, 481,
+ /* 450 */ 380, 386, 80, 237, 237, 259, 472, 385, 1197, 259,
+ /* 460 */ 472, 169, 127, 267, 350, 478, 398, 306, 859, 243,
+ /* 470 */ 43, 43, 940, 940, 420, 278, 188, 1114, 103, 103,
+ /* 480 */ 103, 103, 102, 102, 101, 101, 101, 100, 381, 106,
+ /* 490 */ 107, 97, 1013, 1013, 892, 895, 885, 885, 104, 104,
+ /* 500 */ 105, 105, 105, 105, 384, 359, 389, 237, 237, 237,
+ /* 510 */ 237, 110, 129, 399, 281, 334, 1033, 258, 992, 478,
+ /* 520 */ 350, 478, 1028, 389, 388, 363, 347, 479, 937, 784,
+ /* 530 */ 784, 1057, 937, 152, 103, 103, 103, 103, 102, 102,
+ /* 540 */ 101, 101, 101, 100, 381, 106, 107, 97, 1013, 1013,
+ /* 550 */ 892, 895, 885, 885, 104, 104, 105, 105, 105, 105,
+ /* 560 */ 992, 993, 994, 237, 237, 418, 481, 334, 973, 1338,
+ /* 570 */ 293, 244, 208, 207, 206, 478, 350, 1077, 359, 306,
+ /* 580 */ 1303, 1034, 178, 177, 339, 423, 445, 11, 11, 389,
+ /* 590 */ 103, 103, 103, 103, 102, 102, 101, 101, 101, 100,
+ /* 600 */ 381, 106, 107, 97, 1013, 1013, 892, 895, 885, 885,
+ /* 610 */ 104, 104, 105, 105, 105, 105, 237, 237, 237, 237,
+ /* 620 */ 406, 828, 406, 1197, 126, 1197, 1197, 1298, 478, 829,
+ /* 630 */ 478, 209, 350, 1034, 288, 264, 291, 171, 423, 423,
+ /* 640 */ 448, 423, 466, 404, 245, 85, 103, 103, 103, 103,
+ /* 650 */ 102, 102, 101, 101, 101, 100, 381, 106, 107, 97,
+ /* 660 */ 1013, 1013, 892, 895, 885, 885, 104, 104, 105, 105,
+ /* 670 */ 105, 105, 237, 237, 237, 237, 969, 481, 1197, 336,
+ /* 680 */ 1262, 1115, 1151, 1111, 478, 355, 478, 306, 350, 247,
+ /* 690 */ 364, 248, 365, 419, 412, 423, 412, 307, 33, 33,
+ /* 700 */ 307, 88, 103, 103, 103, 103, 102, 102, 101, 101,
+ /* 710 */ 101, 100, 381, 106, 107, 97, 1013, 1013, 892, 895,
+ /* 720 */ 885, 885, 104, 104, 105, 105, 105, 105, 265, 481,
+ /* 730 */ 1268, 8, 128, 367, 1060, 356, 374, 286, 474, 356,
+ /* 740 */ 259, 472, 357, 146, 350, 375, 1010, 1268, 1270, 277,
+ /* 750 */ 44, 44, 82, 412, 105, 105, 105, 105, 103, 103,
+ /* 760 */ 103, 103, 102, 102, 101, 101, 101, 100, 381, 106,
+ /* 770 */ 95, 97, 1013, 1013, 892, 895, 885, 885, 104, 104,
+ /* 780 */ 105, 105, 105, 105, 481, 246, 481, 279, 103, 103,
+ /* 790 */ 103, 103, 102, 102, 101, 101, 101, 100, 381, 350,
+ /* 800 */ 236, 182, 413, 996, 739, 45, 45, 46, 46, 89,
+ /* 810 */ 1263, 87, 190, 1268, 103, 103, 103, 103, 102, 102,
+ /* 820 */ 101, 101, 101, 100, 381, 107, 97, 1013, 1013, 892,
+ /* 830 */ 895, 885, 885, 104, 104, 105, 105, 105, 105, 125,
+ /* 840 */ 481, 28, 481, 354, 249, 789, 996, 739, 174, 856,
+ /* 850 */ 788, 405, 215, 350, 215, 372, 407, 454, 1150, 215,
+ /* 860 */ 922, 47, 47, 48, 48, 749, 748, 393, 22, 103,
+ /* 870 */ 103, 103, 103, 102, 102, 101, 101, 101, 100, 381,
+ /* 880 */ 97, 1013, 1013, 892, 895, 885, 885, 104, 104, 105,
+ /* 890 */ 105, 105, 105, 92, 473, 992, 3, 410, 481, 391,
+ /* 900 */ 23, 715, 234, 922, 282, 813, 429, 82, 296, 211,
+ /* 910 */ 476, 82, 756, 757, 145, 192, 1309, 274, 417, 49,
+ /* 920 */ 49, 124, 414, 103, 103, 103, 103, 102, 102, 101,
+ /* 930 */ 101, 101, 100, 381, 382, 369, 390, 992, 993, 994,
+ /* 940 */ 455, 223, 240, 305, 439, 300, 438, 210, 470, 92,
+ /* 950 */ 473, 992, 3, 298, 259, 472, 441, 956, 145, 725,
+ /* 960 */ 82, 872, 918, 397, 1287, 211, 476, 90, 90, 160,
+ /* 970 */ 1286, 70, 957, 1086, 91, 415, 382, 483, 482, 481,
+ /* 980 */ 411, 864, 789, 184, 378, 377, 1138, 788, 958, 915,
+ /* 990 */ 382, 239, 1017, 992, 993, 994, 283, 1019, 259, 472,
+ /* 1000 */ 34, 34, 725, 822, 470, 1018, 215, 992, 813, 770,
+ /* 1010 */ 161, 428, 864, 864, 866, 867, 19, 872, 304, 786,
+ /* 1020 */ 1147, 771, 94, 90, 90, 793, 1255, 287, 303, 1020,
+ /* 1030 */ 91, 1020, 382, 483, 482, 723, 4, 864, 123, 209,
+ /* 1040 */ 92, 473, 481, 3, 290, 481, 741, 468, 992, 992,
+ /* 1050 */ 993, 994, 787, 464, 292, 94, 443, 476, 84, 473,
+ /* 1060 */ 868, 3, 992, 58, 58, 294, 38, 38, 864, 864,
+ /* 1070 */ 866, 867, 19, 2, 992, 476, 934, 166, 934, 1099,
+ /* 1080 */ 933, 382, 933, 1085, 1083, 237, 237, 992, 237, 237,
+ /* 1090 */ 992, 993, 994, 355, 1084, 470, 1331, 478, 463, 382,
+ /* 1100 */ 478, 444, 299, 868, 992, 993, 994, 465, 872, 298,
+ /* 1110 */ 308, 992, 309, 470, 90, 90, 992, 993, 994, 956,
+ /* 1120 */ 1159, 91, 1196, 382, 483, 482, 872, 1134, 864, 992,
+ /* 1130 */ 993, 994, 90, 90, 957, 256, 5, 1145, 216, 91,
+ /* 1140 */ 467, 382, 483, 482, 992, 1202, 864, 1066, 813, 1059,
+ /* 1150 */ 958, 481, 229, 992, 993, 994, 815, 1048, 424, 864,
+ /* 1160 */ 864, 866, 867, 19, 1047, 1049, 105, 105, 105, 105,
+ /* 1170 */ 98, 469, 35, 35, 1011, 1325, 172, 864, 864, 866,
+ /* 1180 */ 867, 19, 1318, 982, 241, 7, 992, 993, 994, 332,
+ /* 1190 */ 332, 331, 226, 329, 481, 176, 712, 1131, 333, 481,
+ /* 1200 */ 103, 103, 103, 103, 102, 102, 101, 101, 101, 100,
+ /* 1210 */ 381, 263, 216, 814, 187, 9, 9, 1011, 481, 262,
+ /* 1220 */ 9, 9, 481, 392, 170, 481, 184, 750, 481, 366,
+ /* 1230 */ 311, 313, 315, 269, 368, 276, 349, 732, 1181, 9,
+ /* 1240 */ 9, 1189, 341, 9, 9, 409, 37, 37, 1011, 50,
+ /* 1250 */ 50, 813, 189, 250, 434, 481, 251, 460, 251, 437,
+ /* 1260 */ 138, 481, 1082, 140, 872, 982, 241, 180, 481, 751,
+ /* 1270 */ 302, 332, 332, 331, 226, 329, 51, 51, 712, 732,
+ /* 1280 */ 865, 1259, 52, 52, 864, 481, 1258, 471, 481, 10,
+ /* 1290 */ 10, 1011, 481, 263, 317, 175, 326, 481, 351, 1328,
+ /* 1300 */ 481, 262, 148, 259, 472, 1028, 53, 53, 370, 112,
+ /* 1310 */ 112, 1025, 66, 54, 54, 864, 864, 866, 39, 39,
+ /* 1320 */ 69, 55, 55, 218, 358, 481, 387, 481, 1186, 70,
+ /* 1330 */ 403, 481, 1264, 158, 189, 25, 481, 143, 481, 150,
+ /* 1340 */ 481, 80, 138, 481, 1178, 140, 56, 56, 40, 40,
+ /* 1350 */ 481, 395, 133, 133, 481, 153, 481, 134, 134, 63,
+ /* 1360 */ 63, 41, 41, 154, 59, 59, 396, 481, 427, 481,
+ /* 1370 */ 155, 113, 113, 481, 195, 60, 60, 114, 114, 481,
+ /* 1380 */ 351, 481, 156, 481, 338, 259, 472, 402, 115, 115,
+ /* 1390 */ 111, 111, 340, 481, 132, 132, 1192, 481, 162, 26,
+ /* 1400 */ 131, 131, 119, 119, 118, 118, 481, 1253, 387, 481,
+ /* 1410 */ 416, 481, 75, 481, 116, 116, 199, 422, 117, 117,
+ /* 1420 */ 481, 1275, 230, 167, 201, 425, 289, 62, 62, 202,
+ /* 1430 */ 64, 64, 61, 61, 32, 32, 440, 1050, 203, 285,
+ /* 1440 */ 343, 36, 36, 371, 1102, 1101, 741, 1100, 373, 456,
+ /* 1450 */ 1142, 1074, 254, 344, 79, 255, 1073, 1093, 301, 1072,
+ /* 1460 */ 1340, 310, 217, 6, 1092, 447, 450, 1239, 1143, 1141,
+ /* 1470 */ 312, 314, 319, 86, 257, 109, 1140, 461, 81, 316,
+ /* 1480 */ 459, 224, 1056, 24, 987, 484, 225, 228, 1124, 227,
+ /* 1490 */ 352, 322, 325, 323, 324, 485, 353, 1045, 1040, 1291,
+ /* 1500 */ 147, 1292, 1290, 1289, 122, 135, 136, 173, 252, 261,
+ /* 1510 */ 186, 242, 120, 1070, 1069, 932, 930, 848, 149, 65,
+ /* 1520 */ 137, 139, 1067, 191, 151, 773, 275, 194, 946, 141,
+ /* 1530 */ 157, 852, 360, 71, 362, 159, 72, 73, 74, 142,
+ /* 1540 */ 949, 196, 197, 945, 14, 130, 198, 938, 163, 284,
+ /* 1550 */ 1022, 215, 421, 200, 164, 27, 714, 426, 204, 303,
+ /* 1560 */ 430, 435, 752, 165, 76, 15, 144, 297, 16, 77,
+ /* 1570 */ 253, 871, 870, 898, 983, 977, 29, 78, 30, 446,
+ /* 1580 */ 978, 181, 449, 233, 235, 168, 783, 214, 821, 816,
+ /* 1590 */ 94, 82, 913, 17, 899, 220, 18, 897, 901, 955,
+ /* 1600 */ 902, 954, 20, 219, 31, 477, 869, 221, 724, 93,
+ /* 1610 */ 21, 330, 1038, 327, 222, 1333, 1332,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 153, 192, 193, 226, 227, 228, 226, 227, 228, 146,
- /* 10 */ 147, 148, 149, 150, 196, 197, 16, 153, 155, 197,
- /* 20 */ 157, 174, 175, 246, 181, 182, 208, 164, 28, 164,
- /* 30 */ 208, 177, 19, 190, 21, 19, 36, 21, 174, 175,
- /* 40 */ 153, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- /* 50 */ 50, 51, 52, 53, 54, 55, 209, 153, 173, 196,
- /* 60 */ 197, 196, 197, 196, 197, 218, 181, 148, 149, 150,
- /* 70 */ 57, 208, 16, 208, 155, 208, 157, 212, 213, 23,
- /* 80 */ 226, 227, 228, 164, 221, 198, 86, 87, 88, 89,
+ /* 0 */ 226, 227, 228, 153, 192, 193, 172, 153, 146, 147,
+ /* 10 */ 148, 149, 150, 153, 181, 182, 16, 155, 153, 157,
+ /* 20 */ 174, 247, 197, 190, 174, 175, 164, 174, 28, 226,
+ /* 30 */ 227, 228, 164, 208, 174, 175, 36, 19, 188, 174,
+ /* 40 */ 175, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ /* 50 */ 50, 51, 52, 53, 54, 55, 192, 193, 196, 197,
+ /* 60 */ 226, 227, 228, 153, 196, 197, 148, 149, 150, 209,
+ /* 70 */ 208, 174, 16, 155, 57, 157, 208, 59, 218, 23,
+ /* 80 */ 212, 213, 164, 221, 174, 175, 86, 87, 88, 89,
/* 90 */ 90, 91, 92, 93, 94, 95, 96, 41, 42, 43,
/* 100 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 110 */ 54, 55, 249, 100, 19, 196, 197, 174, 90, 91,
- /* 120 */ 92, 93, 94, 95, 96, 69, 222, 208, 16, 86,
- /* 130 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
- /* 140 */ 221, 96, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 110 */ 54, 55, 250, 153, 196, 197, 99, 100, 101, 102,
+ /* 120 */ 111, 112, 105, 106, 107, 69, 208, 96, 16, 19,
+ /* 130 */ 20, 177, 115, 23, 174, 175, 169, 170, 171, 221,
+ /* 140 */ 230, 153, 86, 87, 88, 89, 90, 91, 92, 93,
/* 150 */ 94, 95, 96, 41, 42, 43, 44, 45, 46, 47,
- /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 249, 92,
- /* 170 */ 93, 94, 95, 96, 153, 111, 112, 102, 12, 67,
- /* 180 */ 105, 106, 107, 57, 16, 90, 91, 177, 23, 21,
- /* 190 */ 115, 44, 45, 46, 47, 174, 175, 174, 86, 87,
+ /* 160 */ 48, 49, 50, 51, 52, 53, 54, 55, 250, 209,
+ /* 170 */ 90, 91, 92, 93, 94, 95, 96, 13, 218, 67,
+ /* 180 */ 226, 227, 228, 102, 16, 153, 105, 106, 107, 21,
+ /* 190 */ 92, 93, 94, 95, 96, 85, 115, 165, 86, 87,
/* 200 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 41,
/* 210 */ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 220 */ 52, 53, 54, 55, 58, 99, 100, 101, 102, 84,
- /* 230 */ 209, 105, 106, 107, 172, 174, 226, 227, 228, 218,
- /* 240 */ 16, 115, 19, 20, 20, 100, 23, 95, 96, 104,
- /* 250 */ 57, 104, 90, 91, 86, 87, 88, 89, 90, 91,
+ /* 220 */ 52, 53, 54, 55, 153, 112, 86, 87, 88, 89,
+ /* 230 */ 90, 91, 92, 93, 94, 95, 96, 177, 19, 20,
+ /* 240 */ 16, 77, 23, 79, 20, 174, 175, 134, 57, 44,
+ /* 250 */ 45, 46, 47, 187, 86, 87, 88, 89, 90, 91,
/* 260 */ 92, 93, 94, 95, 96, 41, 42, 43, 44, 45,
/* 270 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 280 */ 135, 136, 137, 153, 153, 153, 121, 122, 226, 227,
- /* 290 */ 228, 153, 99, 100, 101, 13, 16, 135, 23, 137,
- /* 300 */ 20, 73, 57, 165, 174, 175, 174, 175, 85, 81,
+ /* 280 */ 209, 196, 197, 92, 153, 84, 226, 227, 228, 218,
+ /* 290 */ 99, 100, 101, 208, 90, 91, 16, 4, 5, 6,
+ /* 300 */ 20, 100, 57, 20, 85, 104, 23, 143, 81, 104,
/* 310 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
/* 320 */ 96, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- /* 330 */ 50, 51, 52, 53, 54, 55, 153, 92, 110, 209,
- /* 340 */ 153, 209, 153, 153, 99, 100, 101, 187, 218, 121,
- /* 350 */ 122, 220, 16, 169, 170, 171, 20, 174, 175, 77,
- /* 360 */ 164, 79, 81, 153, 174, 175, 86, 87, 88, 89,
+ /* 330 */ 50, 51, 52, 53, 54, 55, 135, 136, 137, 135,
+ /* 340 */ 153, 137, 153, 23, 99, 100, 101, 153, 121, 122,
+ /* 350 */ 95, 96, 16, 169, 170, 171, 20, 23, 253, 254,
+ /* 360 */ 153, 174, 175, 174, 175, 73, 86, 87, 88, 89,
/* 370 */ 90, 91, 92, 93, 94, 95, 96, 41, 42, 43,
/* 380 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 390 */ 54, 55, 196, 197, 13, 153, 158, 19, 20, 209,
- /* 400 */ 125, 23, 121, 122, 208, 195, 57, 220, 16, 169,
- /* 410 */ 170, 171, 20, 230, 8, 73, 174, 175, 140, 223,
- /* 420 */ 142, 72, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 390 */ 54, 55, 153, 153, 153, 172, 209, 153, 209, 153,
+ /* 400 */ 153, 161, 110, 111, 112, 165, 196, 197, 16, 153,
+ /* 410 */ 8, 73, 20, 174, 175, 174, 175, 153, 208, 81,
+ /* 420 */ 153, 164, 86, 87, 88, 89, 90, 91, 92, 93,
/* 430 */ 94, 95, 96, 41, 42, 43, 44, 45, 46, 47,
- /* 440 */ 48, 49, 50, 51, 52, 53, 54, 55, 99, 100,
- /* 450 */ 101, 209, 110, 111, 112, 153, 172, 247, 77, 153,
- /* 460 */ 79, 153, 57, 85, 16, 110, 111, 112, 20, 161,
- /* 470 */ 153, 233, 26, 165, 236, 164, 30, 72, 86, 87,
+ /* 440 */ 48, 49, 50, 51, 52, 53, 54, 55, 110, 153,
+ /* 450 */ 209, 195, 132, 196, 197, 121, 122, 153, 153, 121,
+ /* 460 */ 122, 238, 198, 219, 16, 208, 243, 153, 20, 222,
+ /* 470 */ 174, 175, 110, 111, 112, 164, 12, 164, 86, 87,
/* 480 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 41,
/* 490 */ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 500 */ 52, 53, 54, 55, 99, 100, 101, 196, 197, 63,
- /* 510 */ 117, 153, 119, 120, 4, 5, 6, 111, 112, 208,
- /* 520 */ 16, 237, 192, 193, 143, 219, 242, 110, 111, 112,
- /* 530 */ 153, 164, 174, 175, 86, 87, 88, 89, 90, 91,
+ /* 500 */ 52, 53, 54, 55, 248, 153, 153, 196, 197, 196,
+ /* 510 */ 197, 19, 198, 111, 112, 19, 20, 201, 57, 208,
+ /* 520 */ 16, 208, 58, 170, 171, 220, 210, 117, 26, 119,
+ /* 530 */ 120, 164, 30, 72, 86, 87, 88, 89, 90, 91,
/* 540 */ 92, 93, 94, 95, 96, 41, 42, 43, 44, 45,
/* 550 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 560 */ 153, 153, 153, 196, 197, 153, 153, 153, 19, 20,
- /* 570 */ 19, 20, 252, 253, 201, 208, 16, 170, 171, 170,
- /* 580 */ 171, 153, 153, 210, 164, 153, 164, 174, 175, 164,
+ /* 560 */ 99, 100, 101, 196, 197, 63, 153, 19, 20, 173,
+ /* 570 */ 13, 219, 110, 111, 112, 208, 16, 181, 153, 153,
+ /* 580 */ 153, 85, 90, 91, 164, 153, 164, 174, 175, 236,
/* 590 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
/* 600 */ 96, 41, 42, 43, 44, 45, 46, 47, 48, 49,
/* 610 */ 50, 51, 52, 53, 54, 55, 196, 197, 196, 197,
- /* 620 */ 153, 196, 197, 153, 118, 153, 198, 198, 208, 123,
- /* 630 */ 208, 219, 16, 208, 85, 153, 85, 21, 153, 153,
- /* 640 */ 164, 153, 235, 164, 235, 141, 86, 87, 88, 89,
+ /* 620 */ 153, 28, 153, 153, 198, 153, 153, 195, 208, 36,
+ /* 630 */ 208, 44, 16, 85, 77, 153, 79, 21, 153, 153,
+ /* 640 */ 164, 153, 164, 223, 219, 141, 86, 87, 88, 89,
/* 650 */ 90, 91, 92, 93, 94, 95, 96, 41, 42, 43,
/* 660 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 670 */ 54, 55, 196, 197, 153, 196, 197, 195, 153, 153,
- /* 680 */ 195, 195, 153, 195, 208, 153, 153, 208, 16, 222,
- /* 690 */ 153, 219, 222, 57, 153, 174, 175, 153, 153, 174,
- /* 700 */ 175, 141, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 670 */ 54, 55, 196, 197, 196, 197, 20, 153, 153, 23,
+ /* 680 */ 195, 195, 153, 195, 208, 98, 208, 153, 16, 222,
+ /* 690 */ 220, 222, 220, 220, 153, 153, 153, 153, 174, 175,
+ /* 700 */ 153, 141, 86, 87, 88, 89, 90, 91, 92, 93,
/* 710 */ 94, 95, 96, 41, 42, 43, 44, 45, 46, 47,
- /* 720 */ 48, 49, 50, 51, 52, 53, 54, 55, 195, 153,
- /* 730 */ 189, 153, 153, 153, 189, 198, 100, 167, 168, 167,
- /* 740 */ 168, 172, 121, 122, 16, 23, 220, 250, 251, 220,
- /* 750 */ 174, 175, 174, 175, 52, 53, 54, 55, 86, 87,
+ /* 720 */ 48, 49, 50, 51, 52, 53, 54, 55, 153, 153,
+ /* 730 */ 153, 172, 198, 189, 167, 168, 189, 195, 167, 168,
+ /* 740 */ 121, 122, 251, 252, 16, 220, 23, 170, 171, 20,
+ /* 750 */ 174, 175, 23, 153, 52, 53, 54, 55, 86, 87,
/* 760 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 41,
/* 770 */ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 780 */ 52, 53, 54, 55, 153, 16, 153, 243, 86, 87,
+ /* 780 */ 52, 53, 54, 55, 153, 244, 153, 244, 86, 87,
/* 790 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 16,
- /* 800 */ 220, 212, 213, 21, 44, 174, 175, 174, 175, 153,
- /* 810 */ 153, 242, 23, 92, 86, 87, 88, 89, 90, 91,
+ /* 800 */ 212, 213, 243, 57, 57, 174, 175, 174, 175, 140,
+ /* 810 */ 235, 142, 21, 236, 86, 87, 88, 89, 90, 91,
/* 820 */ 92, 93, 94, 95, 96, 42, 43, 44, 45, 46,
- /* 830 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 118,
- /* 840 */ 20, 153, 28, 23, 123, 20, 20, 153, 23, 23,
- /* 850 */ 36, 103, 104, 16, 132, 16, 153, 19, 98, 19,
- /* 860 */ 4, 5, 174, 175, 19, 135, 57, 137, 99, 86,
+ /* 830 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 19,
+ /* 840 */ 153, 21, 153, 158, 244, 118, 100, 100, 125, 20,
+ /* 850 */ 123, 20, 23, 16, 23, 16, 20, 16, 153, 23,
+ /* 860 */ 57, 174, 175, 174, 175, 103, 104, 153, 19, 86,
/* 870 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
/* 880 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 890 */ 53, 54, 55, 16, 17, 57, 19, 57, 109, 243,
- /* 900 */ 243, 18, 104, 16, 59, 9, 124, 153, 20, 100,
- /* 910 */ 33, 23, 114, 20, 153, 20, 23, 153, 23, 135,
- /* 920 */ 24, 137, 32, 86, 87, 88, 89, 90, 91, 92,
- /* 930 */ 93, 94, 95, 96, 57, 96, 40, 99, 100, 101,
- /* 940 */ 100, 102, 103, 104, 105, 106, 107, 108, 71, 16,
- /* 950 */ 17, 57, 19, 114, 64, 223, 19, 61, 81, 20,
- /* 960 */ 81, 84, 23, 80, 74, 153, 33, 90, 91, 73,
- /* 970 */ 19, 153, 153, 183, 97, 153, 99, 100, 101, 183,
- /* 980 */ 153, 104, 103, 21, 90, 91, 99, 165, 51, 106,
- /* 990 */ 57, 183, 98, 99, 100, 101, 101, 103, 121, 122,
- /* 1000 */ 121, 122, 153, 113, 71, 111, 153, 185, 57, 187,
- /* 1010 */ 19, 16, 135, 136, 137, 138, 139, 84, 153, 57,
- /* 1020 */ 153, 126, 57, 90, 91, 92, 143, 153, 153, 135,
- /* 1030 */ 97, 137, 99, 100, 101, 57, 19, 104, 112, 44,
- /* 1040 */ 16, 17, 153, 19, 153, 153, 20, 214, 57, 23,
- /* 1050 */ 99, 100, 101, 164, 153, 153, 164, 33, 16, 17,
- /* 1060 */ 134, 19, 100, 174, 175, 100, 174, 175, 135, 136,
- /* 1070 */ 137, 138, 139, 20, 57, 33, 23, 99, 100, 101,
- /* 1080 */ 20, 57, 19, 23, 153, 196, 197, 57, 196, 197,
- /* 1090 */ 99, 100, 101, 98, 57, 71, 9, 208, 209, 57,
- /* 1100 */ 208, 209, 153, 153, 126, 174, 175, 218, 84, 114,
- /* 1110 */ 153, 24, 153, 71, 90, 91, 99, 100, 101, 188,
- /* 1120 */ 23, 97, 153, 99, 100, 101, 84, 40, 104, 99,
- /* 1130 */ 100, 101, 90, 91, 153, 211, 153, 100, 153, 97,
- /* 1140 */ 153, 99, 100, 101, 20, 193, 104, 23, 61, 20,
- /* 1150 */ 153, 153, 23, 153, 153, 153, 126, 174, 175, 135,
+ /* 890 */ 53, 54, 55, 16, 17, 57, 19, 16, 153, 223,
+ /* 900 */ 51, 18, 20, 100, 20, 23, 20, 23, 20, 23,
+ /* 910 */ 33, 23, 4, 5, 81, 124, 153, 153, 233, 174,
+ /* 920 */ 175, 19, 237, 86, 87, 88, 89, 90, 91, 92,
+ /* 930 */ 93, 94, 95, 96, 57, 96, 103, 99, 100, 101,
+ /* 940 */ 99, 102, 103, 104, 105, 106, 107, 108, 71, 16,
+ /* 950 */ 17, 57, 19, 114, 121, 122, 92, 9, 81, 57,
+ /* 960 */ 23, 84, 20, 80, 153, 23, 33, 90, 91, 19,
+ /* 970 */ 153, 133, 24, 183, 97, 153, 99, 100, 101, 153,
+ /* 980 */ 99, 104, 118, 101, 90, 91, 214, 123, 40, 106,
+ /* 990 */ 57, 19, 98, 99, 100, 101, 153, 103, 121, 122,
+ /* 1000 */ 174, 175, 100, 20, 71, 111, 23, 57, 126, 61,
+ /* 1010 */ 19, 16, 135, 136, 137, 138, 139, 84, 104, 20,
+ /* 1020 */ 153, 73, 23, 90, 91, 92, 143, 153, 114, 135,
+ /* 1030 */ 97, 137, 99, 100, 101, 20, 19, 104, 23, 44,
+ /* 1040 */ 16, 17, 153, 19, 153, 153, 109, 193, 57, 99,
+ /* 1050 */ 100, 101, 20, 164, 153, 23, 164, 33, 16, 17,
+ /* 1060 */ 57, 19, 57, 174, 175, 153, 174, 175, 135, 136,
+ /* 1070 */ 137, 138, 139, 19, 57, 33, 135, 72, 137, 153,
+ /* 1080 */ 135, 57, 137, 183, 153, 196, 197, 57, 196, 197,
+ /* 1090 */ 99, 100, 101, 98, 183, 71, 124, 208, 209, 57,
+ /* 1100 */ 208, 209, 153, 100, 99, 100, 101, 218, 84, 114,
+ /* 1110 */ 153, 57, 153, 71, 90, 91, 99, 100, 101, 9,
+ /* 1120 */ 153, 97, 153, 99, 100, 101, 84, 153, 104, 99,
+ /* 1130 */ 100, 101, 90, 91, 24, 211, 19, 153, 21, 97,
+ /* 1140 */ 153, 99, 100, 101, 57, 153, 104, 153, 23, 153,
+ /* 1150 */ 40, 153, 239, 99, 100, 101, 126, 153, 240, 135,
/* 1160 */ 136, 137, 138, 139, 153, 153, 52, 53, 54, 55,
- /* 1170 */ 56, 153, 174, 175, 174, 175, 153, 135, 136, 137,
- /* 1180 */ 138, 139, 0, 1, 2, 239, 188, 124, 188, 7,
- /* 1190 */ 8, 9, 10, 11, 153, 199, 14, 211, 101, 153,
+ /* 1170 */ 56, 61, 174, 175, 57, 153, 199, 135, 136, 137,
+ /* 1180 */ 138, 139, 0, 1, 2, 200, 99, 100, 101, 7,
+ /* 1190 */ 8, 9, 10, 11, 153, 172, 14, 211, 151, 153,
/* 1200 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- /* 1210 */ 96, 29, 238, 200, 211, 174, 175, 153, 211, 37,
- /* 1220 */ 174, 175, 153, 126, 153, 211, 153, 172, 153, 188,
- /* 1230 */ 20, 151, 153, 23, 188, 153, 248, 57, 174, 175,
- /* 1240 */ 215, 203, 215, 174, 175, 174, 175, 174, 175, 174,
- /* 1250 */ 175, 203, 70, 174, 175, 153, 174, 175, 186, 20,
- /* 1260 */ 78, 153, 23, 81, 84, 1, 2, 178, 153, 203,
- /* 1270 */ 153, 7, 8, 9, 10, 11, 174, 175, 14, 99,
- /* 1280 */ 100, 182, 174, 175, 104, 153, 177, 153, 244, 174,
- /* 1290 */ 175, 174, 175, 29, 244, 177, 20, 153, 116, 23,
- /* 1300 */ 153, 37, 153, 121, 122, 177, 174, 175, 174, 175,
- /* 1310 */ 153, 215, 202, 232, 153, 135, 136, 137, 174, 175,
- /* 1320 */ 200, 174, 175, 174, 175, 156, 144, 153, 58, 153,
- /* 1330 */ 35, 174, 175, 248, 70, 174, 175, 153, 245, 245,
- /* 1340 */ 153, 124, 78, 153, 98, 81, 153, 225, 174, 175,
- /* 1350 */ 174, 175, 160, 153, 19, 153, 41, 153, 174, 175,
- /* 1360 */ 153, 174, 175, 224, 174, 175, 191, 174, 175, 153,
- /* 1370 */ 132, 153, 15, 153, 174, 175, 174, 175, 174, 175,
- /* 1380 */ 116, 174, 175, 153, 203, 121, 122, 160, 153, 194,
- /* 1390 */ 174, 175, 174, 175, 174, 175, 15, 153, 225, 194,
- /* 1400 */ 194, 159, 194, 224, 174, 175, 203, 160, 144, 174,
- /* 1410 */ 175, 159, 203, 191, 191, 203, 60, 140, 174, 175,
- /* 1420 */ 160, 159, 19, 160, 241, 240, 159, 179, 160, 179,
- /* 1430 */ 159, 98, 176, 176, 176, 62, 109, 184, 179, 178,
- /* 1440 */ 96, 176, 176, 127, 98, 234, 217, 234, 176, 176,
- /* 1450 */ 216, 160, 216, 184, 179, 19, 216, 179, 217, 160,
- /* 1460 */ 217, 229, 217, 140, 231, 216, 128, 131, 22, 130,
- /* 1470 */ 129, 163, 23, 162, 10, 154, 154, 3, 152, 254,
- /* 1480 */ 152, 207, 152, 166, 204, 206, 205, 203, 19, 180,
- /* 1490 */ 172, 254, 172, 180, 145, 166, 172, 172, 12, 83,
- /* 1500 */ 13, 20, 251, 172, 172, 20, 172, 122, 166, 172,
- /* 1510 */ 133, 113, 21, 125, 17, 13, 127, 1, 125, 113,
- /* 1520 */ 134, 59, 34, 133, 51, 113, 51, 51, 51, 99,
- /* 1530 */ 31, 124, 1, 19, 2, 98, 68, 143, 23, 68,
- /* 1540 */ 75, 38, 124, 98, 21, 17, 16, 114, 108, 67,
- /* 1550 */ 67, 25, 19, 19, 19, 34, 20, 19, 19, 67,
- /* 1560 */ 20, 20, 20, 124, 20, 19, 23, 19, 21, 20,
- /* 1570 */ 19, 21, 20, 20, 126, 118, 31, 99, 23, 23,
- /* 1580 */ 20, 20, 20, 20, 20, 31, 8, 20, 31, 23,
- /* 1590 */ 19, 19, 19, 23, 20, 20, 19, 12, 19, 1,
- /* 1600 */ 20, 255, 255, 124, 124, 255, 255, 255, 124, 255,
- /* 1610 */ 255, 255, 255, 124, 255, 255, 255, 255, 255, 255,
- /* 1620 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1630 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1640 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1650 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1660 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1670 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1680 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1690 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1700 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1710 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1720 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1730 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1740 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1750 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ /* 1210 */ 96, 29, 21, 126, 249, 174, 175, 100, 153, 37,
+ /* 1220 */ 174, 175, 153, 215, 153, 153, 101, 32, 153, 188,
+ /* 1230 */ 211, 211, 211, 215, 188, 245, 165, 57, 203, 174,
+ /* 1240 */ 175, 203, 203, 174, 175, 245, 174, 175, 57, 174,
+ /* 1250 */ 175, 126, 70, 188, 178, 153, 185, 188, 187, 64,
+ /* 1260 */ 78, 153, 182, 81, 84, 1, 2, 186, 153, 74,
+ /* 1270 */ 177, 7, 8, 9, 10, 11, 174, 175, 14, 99,
+ /* 1280 */ 100, 177, 174, 175, 104, 153, 177, 232, 153, 174,
+ /* 1290 */ 175, 100, 153, 29, 215, 200, 202, 153, 116, 156,
+ /* 1300 */ 153, 37, 249, 121, 122, 58, 174, 175, 113, 174,
+ /* 1310 */ 175, 35, 246, 174, 175, 135, 136, 137, 174, 175,
+ /* 1320 */ 246, 174, 175, 124, 160, 153, 144, 153, 225, 133,
+ /* 1330 */ 98, 153, 235, 19, 70, 224, 153, 41, 153, 191,
+ /* 1340 */ 153, 132, 78, 153, 203, 81, 174, 175, 174, 175,
+ /* 1350 */ 153, 15, 174, 175, 153, 194, 153, 174, 175, 174,
+ /* 1360 */ 175, 174, 175, 194, 174, 175, 160, 153, 15, 153,
+ /* 1370 */ 194, 174, 175, 153, 159, 174, 175, 174, 175, 153,
+ /* 1380 */ 116, 153, 194, 153, 203, 121, 122, 203, 174, 175,
+ /* 1390 */ 174, 175, 225, 153, 174, 175, 191, 153, 191, 224,
+ /* 1400 */ 174, 175, 174, 175, 174, 175, 153, 203, 144, 153,
+ /* 1410 */ 160, 153, 140, 153, 174, 175, 159, 60, 174, 175,
+ /* 1420 */ 153, 242, 160, 19, 159, 179, 160, 174, 175, 159,
+ /* 1430 */ 174, 175, 174, 175, 174, 175, 98, 160, 159, 241,
+ /* 1440 */ 179, 174, 175, 62, 176, 176, 109, 176, 96, 127,
+ /* 1450 */ 217, 176, 234, 179, 98, 234, 178, 184, 176, 176,
+ /* 1460 */ 176, 216, 160, 19, 184, 179, 179, 229, 217, 217,
+ /* 1470 */ 216, 216, 160, 140, 231, 131, 217, 128, 130, 216,
+ /* 1480 */ 129, 22, 163, 23, 10, 162, 154, 3, 207, 154,
+ /* 1490 */ 255, 206, 203, 205, 204, 152, 255, 152, 152, 172,
+ /* 1500 */ 252, 172, 172, 172, 180, 166, 166, 19, 180, 145,
+ /* 1510 */ 12, 83, 13, 172, 172, 20, 20, 122, 133, 172,
+ /* 1520 */ 166, 113, 172, 21, 125, 17, 13, 127, 1, 113,
+ /* 1530 */ 125, 134, 59, 51, 34, 133, 51, 51, 51, 113,
+ /* 1540 */ 99, 31, 124, 1, 19, 2, 98, 68, 68, 143,
+ /* 1550 */ 75, 23, 38, 124, 98, 21, 17, 16, 108, 114,
+ /* 1560 */ 67, 67, 25, 19, 19, 19, 34, 20, 19, 19,
+ /* 1570 */ 67, 20, 20, 20, 1, 20, 19, 23, 19, 21,
+ /* 1580 */ 20, 124, 21, 20, 20, 19, 118, 31, 99, 126,
+ /* 1590 */ 23, 23, 20, 31, 20, 19, 31, 20, 20, 20,
+ /* 1600 */ 8, 20, 19, 23, 19, 23, 20, 124, 20, 19,
+ /* 1610 */ 19, 12, 256, 20, 124, 124, 124, 256, 256, 256,
+ /* 1620 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1630 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1640 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1650 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1660 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1670 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1680 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1690 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1700 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1710 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1720 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1730 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1740 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1750 */ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ /* 1760 */ 256, 256, 256,
};
-#define YY_SHIFT_COUNT (483)
+#define YY_SHIFT_COUNT (486)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (1598)
+#define YY_SHIFT_MAX (1599)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 1264, 1182, 877, 877, 281, 1024, 1024, 1024, 228, 0,
+ /* 0 */ 1264, 1182, 877, 877, 227, 1024, 1024, 1024, 338, 0,
/* 10 */ 0, 112, 672, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
- /* 20 */ 1024, 1024, 894, 894, 126, 879, 281, 281, 281, 281,
- /* 30 */ 281, 281, 56, 168, 224, 280, 336, 392, 448, 504,
+ /* 20 */ 1024, 1024, 894, 894, 17, 833, 227, 227, 227, 227,
+ /* 30 */ 227, 227, 56, 168, 224, 280, 336, 392, 448, 504,
/* 40 */ 560, 616, 672, 672, 672, 672, 672, 672, 672, 672,
- /* 50 */ 672, 672, 672, 672, 672, 672, 672, 672, 672, 728,
- /* 60 */ 672, 783, 837, 837, 933, 1024, 1024, 1024, 1024, 1024,
+ /* 50 */ 672, 672, 672, 672, 672, 672, 672, 672, 672, 672,
+ /* 60 */ 728, 672, 783, 837, 837, 933, 1024, 1024, 1024, 1024,
/* 70 */ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
/* 80 */ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
- /* 90 */ 1024, 1024, 1024, 1024, 1024, 1042, 1024, 1024, 1024, 1024,
- /* 100 */ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1114,
- /* 110 */ 702, 702, 702, 702, 702, 43, 28, 77, 193, 883,
- /* 120 */ 995, 162, 162, 193, 165, 165, 165, 165, 64, 152,
- /* 130 */ 45, 1614, 1614, 839, 839, 839, 838, 349, 838, 838,
- /* 140 */ 896, 896, 405, 223, 378, 193, 193, 193, 193, 193,
- /* 150 */ 193, 193, 193, 193, 193, 193, 193, 193, 193, 193,
- /* 160 */ 193, 193, 193, 193, 193, 193, 406, 636, 636, 621,
- /* 170 */ 1614, 1614, 1614, 1180, 145, 145, 951, 75, 245, 991,
- /* 180 */ 978, 1030, 1017, 193, 193, 193, 193, 193, 193, 193,
- /* 190 */ 193, 342, 193, 193, 193, 193, 193, 193, 193, 193,
- /* 200 */ 193, 193, 193, 193, 890, 890, 890, 193, 193, 193,
- /* 210 */ 193, 895, 193, 193, 193, 13, 193, 193, 1087, 193,
- /* 220 */ 193, 193, 193, 193, 193, 193, 193, 355, 446, 393,
- /* 230 */ 962, 962, 962, 962, 1097, 393, 393, 721, 95, 510,
- /* 240 */ 166, 722, 769, 769, 887, 722, 722, 887, 789, 820,
- /* 250 */ 760, 814, 814, 814, 769, 278, 275, 506, 16, 1270,
- /* 260 */ 1295, 1295, 1217, 1246, 1335, 1315, 1238, 1357, 1357, 1357,
- /* 270 */ 1357, 1217, 1381, 1238, 1238, 1246, 1335, 1315, 1315, 1238,
- /* 280 */ 1217, 1381, 1277, 1356, 1217, 1381, 1403, 1217, 1381, 1217,
- /* 290 */ 1381, 1403, 1333, 1333, 1333, 1373, 1403, 1333, 1327, 1333,
- /* 300 */ 1373, 1333, 1333, 1403, 1344, 1344, 1403, 1316, 1346, 1316,
- /* 310 */ 1346, 1316, 1346, 1316, 1346, 1217, 1436, 1217, 1323, 1336,
- /* 320 */ 1338, 1339, 1341, 1238, 1446, 1449, 1464, 1464, 1474, 1474,
- /* 330 */ 1474, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
- /* 340 */ 1614, 1614, 1614, 1614, 1614, 1614, 1614, 147, 381, 549,
- /* 350 */ 551, 282, 417, 840, 825, 937, 782, 926, 826, 845,
- /* 360 */ 888, 893, 939, 1026, 1053, 1060, 809, 748, 856, 798,
- /* 370 */ 965, 1124, 1129, 1210, 730, 784, 1239, 1276, 1037, 1063,
- /* 380 */ 1469, 1349, 1486, 1416, 1487, 1481, 1485, 1385, 1377, 1398,
- /* 390 */ 1491, 1388, 1497, 1389, 1502, 1516, 1393, 1386, 1406, 1462,
- /* 400 */ 1488, 1390, 1473, 1475, 1476, 1477, 1412, 1430, 1499, 1407,
- /* 410 */ 1531, 1532, 1514, 1437, 1394, 1468, 1515, 1471, 1465, 1503,
- /* 420 */ 1418, 1445, 1523, 1528, 1530, 1433, 1440, 1533, 1482, 1534,
- /* 430 */ 1535, 1536, 1538, 1483, 1526, 1539, 1492, 1521, 1540, 1541,
- /* 440 */ 1542, 1543, 1544, 1546, 1547, 1549, 1548, 1550, 1439, 1552,
- /* 450 */ 1553, 1478, 1545, 1551, 1448, 1555, 1554, 1556, 1557, 1560,
- /* 460 */ 1555, 1561, 1562, 1563, 1564, 1566, 1567, 1571, 1578, 1572,
- /* 470 */ 1573, 1574, 1575, 1577, 1579, 1570, 1457, 1479, 1480, 1484,
- /* 480 */ 1489, 1580, 1585, 1598,
+ /* 90 */ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1042, 1024, 1024,
+ /* 100 */ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+ /* 110 */ 1024, 1114, 702, 702, 702, 702, 702, 140, 80, 98,
+ /* 120 */ 245, 883, 995, 204, 204, 245, 334, 334, 334, 334,
+ /* 130 */ 9, 255, 31, 1617, 1617, 839, 839, 839, 838, 950,
+ /* 140 */ 461, 950, 950, 948, 948, 1005, 110, 219, 245, 245,
+ /* 150 */ 245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
+ /* 160 */ 245, 245, 245, 245, 245, 245, 245, 245, 245, 402,
+ /* 170 */ 746, 746, 619, 1617, 1617, 1617, 1180, 201, 201, 991,
+ /* 180 */ 81, 191, 1017, 1030, 1087, 1054, 245, 245, 245, 245,
+ /* 190 */ 245, 245, 245, 292, 245, 245, 245, 245, 245, 245,
+ /* 200 */ 245, 245, 245, 245, 245, 245, 1195, 1195, 1195, 245,
+ /* 210 */ 245, 245, 245, 882, 245, 245, 245, 1117, 245, 245,
+ /* 220 */ 1110, 245, 245, 245, 245, 245, 245, 245, 245, 362,
+ /* 230 */ 502, 410, 1191, 1191, 1191, 1191, 1125, 410, 410, 864,
+ /* 240 */ 492, 293, 464, 320, 841, 841, 881, 320, 320, 881,
+ /* 250 */ 937, 283, 587, 593, 593, 593, 841, 669, 723, 727,
+ /* 260 */ 820, 1247, 1276, 1276, 1199, 1196, 1232, 1314, 1296, 1209,
+ /* 270 */ 1336, 1336, 1336, 1336, 1199, 1353, 1209, 1209, 1232, 1314,
+ /* 280 */ 1296, 1296, 1209, 1199, 1353, 1272, 1357, 1199, 1353, 1404,
+ /* 290 */ 1199, 1353, 1199, 1353, 1404, 1338, 1338, 1338, 1381, 1404,
+ /* 300 */ 1338, 1337, 1338, 1381, 1338, 1338, 1404, 1352, 1352, 1404,
+ /* 310 */ 1322, 1356, 1322, 1356, 1322, 1356, 1322, 1356, 1199, 1444,
+ /* 320 */ 1199, 1333, 1344, 1349, 1348, 1351, 1209, 1459, 1460, 1474,
+ /* 330 */ 1474, 1484, 1484, 1484, 1617, 1617, 1617, 1617, 1617, 1617,
+ /* 340 */ 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617, 1617,
+ /* 350 */ 205, 164, 496, 548, 557, 462, 902, 656, 849, 791,
+ /* 360 */ 113, 729, 18, 829, 831, 836, 884, 886, 888, 747,
+ /* 370 */ 762, 908, 914, 803, 942, 983, 999, 941, 945, 1015,
+ /* 380 */ 1032, 1003, 972, 1488, 1364, 1498, 1428, 1499, 1495, 1496,
+ /* 390 */ 1395, 1385, 1408, 1502, 1399, 1508, 1400, 1513, 1527, 1405,
+ /* 400 */ 1397, 1416, 1473, 1500, 1402, 1482, 1485, 1486, 1487, 1426,
+ /* 410 */ 1441, 1510, 1418, 1542, 1543, 1525, 1448, 1406, 1479, 1528,
+ /* 420 */ 1480, 1475, 1514, 1429, 1456, 1534, 1539, 1541, 1445, 1450,
+ /* 430 */ 1544, 1493, 1545, 1546, 1547, 1549, 1494, 1537, 1550, 1503,
+ /* 440 */ 1532, 1551, 1552, 1553, 1554, 1555, 1557, 1558, 1560, 1559,
+ /* 450 */ 1561, 1457, 1563, 1564, 1489, 1556, 1566, 1463, 1567, 1562,
+ /* 460 */ 1568, 1565, 1572, 1567, 1574, 1577, 1578, 1579, 1580, 1581,
+ /* 470 */ 1576, 1592, 1583, 1585, 1586, 1588, 1590, 1591, 1582, 1468,
+ /* 480 */ 1483, 1490, 1491, 1492, 1593, 1599, 1573,
};
-#define YY_REDUCE_COUNT (346)
-#define YY_REDUCE_MIN (-223)
-#define YY_REDUCE_MAX (1342)
+#define YY_REDUCE_COUNT (349)
+#define YY_REDUCE_MIN (-226)
+#define YY_REDUCE_MAX (1354)
static const short yy_reduce_ofst[] = {
- /* 0 */ -137, -81, 889, 892, -135, -153, 21, 130, 196, -146,
- /* 10 */ 10, -223, 62, 931, 998, 1000, 1041, 132, 1046, 183,
- /* 20 */ 190, 242, 407, 409, 822, 311, 367, 420, 422, 425,
- /* 30 */ 476, 479, -220, -220, -220, -220, -220, -220, -220, -220,
- /* 40 */ -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
- /* 50 */ -220, -220, -220, -220, -220, -220, -220, -220, -220, -220,
- /* 60 */ -220, -220, -220, -220, -136, 358, 413, 521, 525, 576,
- /* 70 */ 578, 631, 633, 688, 983, 1064, 1069, 1071, 1073, 1075,
- /* 80 */ 1079, 1082, 1102, 1108, 1115, 1117, 1132, 1134, 1144, 1147,
- /* 90 */ 1149, 1157, 1161, 1174, 1176, 1184, 1187, 1190, 1193, 1200,
- /* 100 */ 1202, 1204, 1207, 1216, 1218, 1220, 1230, 1235, 1244, -220,
- /* 110 */ -220, -220, -220, -220, -220, -220, -220, -220, 210, 238,
- /* 120 */ -157, 184, 240, 308, -182, -133, -182, -133, 284, -220,
- /* 130 */ -220, -220, -220, -115, -115, -115, -96, -113, 467, 470,
- /* 140 */ -191, 330, 428, 320, 320, 138, 306, 412, 472, 429,
- /* 150 */ 482, 485, 486, 488, 544, 131, 656, 187, 526, 657,
- /* 160 */ 529, 533, 541, 537, 545, 580, 569, 570, 572, -178,
- /* 170 */ 497, 589, 373, -57, 23, 61, 189, 160, 302, 317,
- /* 180 */ 377, 408, 414, 432, 532, 579, 694, 703, 754, 761,
- /* 190 */ 764, 732, 812, 818, 819, 827, 849, 853, 865, 867,
- /* 200 */ 874, 875, 891, 901, 790, 796, 808, 902, 949, 950,
- /* 210 */ 957, 833, 959, 969, 981, 924, 985, 987, 952, 997,
- /* 220 */ 302, 1001, 1002, 1011, 1012, 1018, 1023, 946, 974, 996,
- /* 230 */ 986, 1003, 1007, 1014, 833, 996, 996, 1013, 1055, 1080,
- /* 240 */ 988, 1038, 1025, 1027, 1044, 1048, 1066, 1050, 1089, 1072,
- /* 250 */ 1099, 1109, 1118, 1128, 1096, 1081, 1110, 1120, 1169, 1085,
- /* 260 */ 1093, 1094, 1192, 1122, 1139, 1175, 1181, 1195, 1205, 1206,
- /* 270 */ 1208, 1227, 1242, 1203, 1209, 1173, 1179, 1222, 1223, 1212,
- /* 280 */ 1247, 1252, 1183, 1185, 1260, 1262, 1248, 1263, 1267, 1268,
- /* 290 */ 1271, 1250, 1256, 1257, 1258, 1253, 1259, 1265, 1261, 1266,
- /* 300 */ 1269, 1272, 1273, 1275, 1211, 1213, 1278, 1229, 1234, 1241,
- /* 310 */ 1236, 1243, 1240, 1245, 1249, 1291, 1232, 1299, 1233, 1274,
- /* 320 */ 1279, 1281, 1280, 1284, 1308, 1311, 1321, 1322, 1326, 1328,
- /* 330 */ 1330, 1225, 1237, 1251, 1317, 1318, 1320, 1324, 1325, 1329,
- /* 340 */ 1309, 1313, 1331, 1332, 1334, 1337, 1342,
+ /* 0 */ -138, -82, 889, 892, -132, -140, -40, 71, 420, -46,
+ /* 10 */ 60, -226, -166, -150, 1041, 1046, 1065, 187, 1069, -90,
+ /* 20 */ 189, 241, 353, 577, 1071, 257, 311, 313, 367, 422,
+ /* 30 */ 476, 478, -197, -197, -197, -197, -197, -197, -197, -197,
+ /* 40 */ -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+ /* 50 */ -197, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+ /* 60 */ -197, -197, -197, -197, -197, -135, 239, 296, 413, 524,
+ /* 70 */ 576, 631, 633, 687, 689, 745, 826, 998, 1072, 1075,
+ /* 80 */ 1102, 1108, 1115, 1132, 1135, 1139, 1144, 1147, 1172, 1174,
+ /* 90 */ 1178, 1183, 1185, 1187, 1190, 1197, 1201, 1203, 1214, 1216,
+ /* 100 */ 1220, 1226, 1228, 1230, 1240, 1244, 1253, 1256, 1258, 1260,
+ /* 110 */ 1267, -197, -197, -197, -197, -197, -197, -197, -197, -197,
+ /* 120 */ 256, 685, -167, -33, 184, 240, 85, 210, 85, 210,
+ /* 130 */ 223, -197, -197, -197, -197, 396, 396, 396, 575, 247,
+ /* 140 */ 264, 467, 469, -188, -136, 314, 105, 105, 32, 244,
+ /* 150 */ 352, 425, 426, 432, 485, 486, 488, 541, 305, 543,
+ /* 160 */ 470, 472, 600, 473, 542, 544, 534, 547, 525, 559,
+ /* 170 */ 567, 571, -175, 491, 588, 316, -154, -147, -103, -146,
+ /* 180 */ 66, -12, 131, 194, 207, 246, 267, 304, 427, 482,
+ /* 190 */ 529, 705, 714, 676, 763, 764, 811, 817, 822, 843,
+ /* 200 */ 867, 874, 891, 901, 912, 926, 790, 900, 911, 931,
+ /* 210 */ 949, 957, 959, 772, 967, 969, 974, 924, 984, 987,
+ /* 220 */ 854, 992, -12, 994, 996, 1004, 1011, 1012, 1022, 918,
+ /* 230 */ 913, 977, 986, 1019, 1020, 1021, 772, 977, 977, 985,
+ /* 240 */ 1023, 1047, 965, 1035, 1008, 1018, 990, 1038, 1039, 1000,
+ /* 250 */ 1076, 1081, 1080, 1093, 1104, 1109, 1079, 1055, 1094, 1095,
+ /* 260 */ 1143, 1053, 1066, 1074, 1164, 1097, 1103, 1111, 1148, 1141,
+ /* 270 */ 1161, 1169, 1176, 1188, 1206, 1215, 1181, 1184, 1167, 1175,
+ /* 280 */ 1205, 1207, 1204, 1250, 1257, 1179, 1198, 1262, 1265, 1246,
+ /* 290 */ 1266, 1270, 1277, 1279, 1261, 1268, 1269, 1271, 1273, 1274,
+ /* 300 */ 1275, 1278, 1282, 1280, 1283, 1284, 1286, 1218, 1221, 1287,
+ /* 310 */ 1233, 1245, 1251, 1254, 1252, 1255, 1259, 1263, 1302, 1238,
+ /* 320 */ 1312, 1243, 1281, 1285, 1288, 1290, 1289, 1319, 1323, 1332,
+ /* 330 */ 1335, 1343, 1345, 1346, 1235, 1241, 1248, 1339, 1327, 1329,
+ /* 340 */ 1330, 1331, 1340, 1324, 1328, 1341, 1342, 1347, 1350, 1354,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1366, 1366, 1242, 1030, 1133, 1242, 1242, 1242, 1030, 1163,
- /* 10 */ 1163, 1293, 1059, 1030, 1030, 1030, 1030, 1030, 1030, 1241,
- /* 20 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 30 */ 1030, 1030, 1169, 1030, 1030, 1030, 1030, 1243, 1244, 1030,
- /* 40 */ 1030, 1030, 1292, 1294, 1179, 1178, 1177, 1176, 1275, 1150,
- /* 50 */ 1174, 1167, 1171, 1237, 1238, 1236, 1240, 1244, 1243, 1030,
- /* 60 */ 1170, 1208, 1222, 1207, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 70 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 80 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 90 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 100 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1216,
- /* 110 */ 1221, 1227, 1220, 1217, 1210, 1209, 1211, 1212, 1030, 1049,
- /* 120 */ 1098, 1030, 1030, 1030, 1307, 1306, 1030, 1030, 1059, 1213,
- /* 130 */ 1214, 1224, 1223, 1296, 1322, 1321, 1030, 1030, 1030, 1030,
- /* 140 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 150 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 160 */ 1030, 1030, 1030, 1030, 1030, 1030, 1059, 1055, 1055, 1030,
- /* 170 */ 1302, 1133, 1124, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 180 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1257, 1030, 1030,
- /* 190 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 200 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 210 */ 1030, 1030, 1030, 1030, 1030, 1129, 1030, 1030, 1030, 1030,
- /* 220 */ 1030, 1030, 1030, 1030, 1030, 1030, 1316, 1030, 1270, 1112,
- /* 230 */ 1129, 1129, 1129, 1129, 1131, 1113, 1111, 1123, 1059, 1035,
- /* 240 */ 1358, 1173, 1152, 1152, 1355, 1173, 1173, 1355, 1073, 1336,
- /* 250 */ 1070, 1163, 1163, 1163, 1152, 1239, 1130, 1123, 1030, 1358,
- /* 260 */ 1357, 1357, 1138, 1182, 1188, 1101, 1173, 1107, 1107, 1107,
- /* 270 */ 1107, 1138, 1046, 1173, 1173, 1182, 1188, 1101, 1101, 1173,
- /* 280 */ 1138, 1046, 1274, 1352, 1138, 1046, 1250, 1138, 1046, 1138,
- /* 290 */ 1046, 1250, 1099, 1099, 1099, 1088, 1250, 1099, 1073, 1099,
- /* 300 */ 1088, 1099, 1099, 1250, 1254, 1254, 1250, 1156, 1151, 1156,
- /* 310 */ 1151, 1156, 1151, 1156, 1151, 1138, 1245, 1138, 1030, 1168,
- /* 320 */ 1157, 1166, 1164, 1173, 1052, 1091, 1319, 1319, 1315, 1315,
- /* 330 */ 1315, 1363, 1363, 1302, 1331, 1059, 1059, 1059, 1059, 1331,
- /* 340 */ 1075, 1075, 1059, 1059, 1059, 1059, 1331, 1030, 1030, 1030,
- /* 350 */ 1030, 1030, 1030, 1326, 1030, 1259, 1142, 1030, 1030, 1030,
- /* 360 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 370 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1193,
- /* 380 */ 1299, 1030, 1030, 1297, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 390 */ 1143, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 400 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1354,
- /* 410 */ 1030, 1030, 1030, 1030, 1030, 1030, 1273, 1272, 1030, 1030,
- /* 420 */ 1140, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 430 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 440 */ 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 450 */ 1030, 1030, 1030, 1030, 1030, 1165, 1030, 1158, 1030, 1030,
- /* 460 */ 1345, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030,
- /* 470 */ 1030, 1030, 1030, 1030, 1030, 1340, 1115, 1195, 1030, 1194,
- /* 480 */ 1198, 1030, 1040, 1030,
+ /* 0 */ 1374, 1374, 1248, 1036, 1139, 1248, 1248, 1248, 1036, 1169,
+ /* 10 */ 1169, 1301, 1065, 1036, 1036, 1036, 1036, 1036, 1036, 1247,
+ /* 20 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 30 */ 1036, 1036, 1175, 1036, 1036, 1036, 1036, 1249, 1250, 1036,
+ /* 40 */ 1036, 1036, 1300, 1302, 1265, 1185, 1184, 1183, 1182, 1283,
+ /* 50 */ 1156, 1180, 1173, 1177, 1243, 1244, 1242, 1246, 1250, 1249,
+ /* 60 */ 1036, 1176, 1214, 1228, 1213, 1036, 1036, 1036, 1036, 1036,
+ /* 70 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 80 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 90 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 100 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 110 */ 1036, 1222, 1227, 1233, 1226, 1223, 1216, 1215, 1217, 1218,
+ /* 120 */ 1036, 1055, 1104, 1036, 1036, 1036, 1315, 1314, 1036, 1036,
+ /* 130 */ 1065, 1219, 1220, 1230, 1229, 1304, 1330, 1329, 1266, 1036,
+ /* 140 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 150 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 160 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1065,
+ /* 170 */ 1061, 1061, 1036, 1310, 1139, 1130, 1036, 1036, 1036, 1036,
+ /* 180 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 190 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 200 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 210 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1135, 1036, 1036,
+ /* 220 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1324, 1036,
+ /* 230 */ 1278, 1118, 1135, 1135, 1135, 1135, 1137, 1119, 1117, 1129,
+ /* 240 */ 1065, 1041, 1366, 1179, 1158, 1158, 1363, 1179, 1179, 1363,
+ /* 250 */ 1079, 1344, 1076, 1169, 1169, 1169, 1158, 1245, 1136, 1129,
+ /* 260 */ 1036, 1366, 1365, 1365, 1144, 1266, 1188, 1194, 1107, 1179,
+ /* 270 */ 1113, 1113, 1113, 1113, 1144, 1052, 1179, 1179, 1188, 1194,
+ /* 280 */ 1107, 1107, 1179, 1144, 1052, 1282, 1360, 1144, 1052, 1256,
+ /* 290 */ 1144, 1052, 1144, 1052, 1256, 1105, 1105, 1105, 1094, 1256,
+ /* 300 */ 1105, 1079, 1105, 1094, 1105, 1105, 1256, 1260, 1260, 1256,
+ /* 310 */ 1162, 1157, 1162, 1157, 1162, 1157, 1162, 1157, 1144, 1251,
+ /* 320 */ 1144, 1036, 1174, 1163, 1172, 1170, 1179, 1058, 1097, 1327,
+ /* 330 */ 1327, 1323, 1323, 1323, 1371, 1371, 1310, 1339, 1065, 1065,
+ /* 340 */ 1065, 1065, 1339, 1081, 1081, 1065, 1065, 1065, 1065, 1339,
+ /* 350 */ 1036, 1036, 1036, 1036, 1036, 1036, 1334, 1036, 1267, 1148,
+ /* 360 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 370 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 380 */ 1036, 1036, 1199, 1307, 1036, 1036, 1305, 1036, 1036, 1036,
+ /* 390 */ 1036, 1036, 1036, 1149, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 400 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 410 */ 1036, 1036, 1362, 1036, 1036, 1036, 1036, 1036, 1036, 1281,
+ /* 420 */ 1280, 1036, 1036, 1146, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 430 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 440 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 450 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1171, 1036,
+ /* 460 */ 1164, 1036, 1036, 1353, 1036, 1036, 1036, 1036, 1036, 1036,
+ /* 470 */ 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1348, 1121,
+ /* 480 */ 1201, 1036, 1200, 1204, 1036, 1046, 1036,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -148212,26 +148667,27 @@ static const char *const yyTokenName[] = {
/* 232 */ "case_else",
/* 233 */ "uniqueflag",
/* 234 */ "collate",
- /* 235 */ "nmnum",
- /* 236 */ "trigger_decl",
- /* 237 */ "trigger_cmd_list",
- /* 238 */ "trigger_time",
- /* 239 */ "trigger_event",
- /* 240 */ "foreach_clause",
- /* 241 */ "when_clause",
- /* 242 */ "trigger_cmd",
- /* 243 */ "trnm",
- /* 244 */ "tridxby",
- /* 245 */ "database_kw_opt",
- /* 246 */ "key_opt",
- /* 247 */ "add_column_fullname",
- /* 248 */ "kwcolumn_opt",
- /* 249 */ "create_vtab",
- /* 250 */ "vtabarglist",
- /* 251 */ "vtabarg",
- /* 252 */ "vtabargtoken",
- /* 253 */ "lp",
- /* 254 */ "anylist",
+ /* 235 */ "vinto",
+ /* 236 */ "nmnum",
+ /* 237 */ "trigger_decl",
+ /* 238 */ "trigger_cmd_list",
+ /* 239 */ "trigger_time",
+ /* 240 */ "trigger_event",
+ /* 241 */ "foreach_clause",
+ /* 242 */ "when_clause",
+ /* 243 */ "trigger_cmd",
+ /* 244 */ "trnm",
+ /* 245 */ "tridxby",
+ /* 246 */ "database_kw_opt",
+ /* 247 */ "key_opt",
+ /* 248 */ "add_column_fullname",
+ /* 249 */ "kwcolumn_opt",
+ /* 250 */ "create_vtab",
+ /* 251 */ "vtabarglist",
+ /* 252 */ "vtabarg",
+ /* 253 */ "vtabargtoken",
+ /* 254 */ "lp",
+ /* 255 */ "anylist",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -148463,116 +148919,118 @@ static const char *const yyRuleName[] = {
/* 221 */ "collate ::=",
/* 222 */ "collate ::= COLLATE ID|STRING",
/* 223 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 224 */ "cmd ::= VACUUM",
- /* 225 */ "cmd ::= VACUUM nm",
- /* 226 */ "cmd ::= PRAGMA nm dbnm",
- /* 227 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 228 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 229 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 230 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 231 */ "plus_num ::= PLUS INTEGER|FLOAT",
- /* 232 */ "minus_num ::= MINUS INTEGER|FLOAT",
- /* 233 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 234 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 235 */ "trigger_time ::= BEFORE|AFTER",
- /* 236 */ "trigger_time ::= INSTEAD OF",
- /* 237 */ "trigger_time ::=",
- /* 238 */ "trigger_event ::= DELETE|INSERT",
- /* 239 */ "trigger_event ::= UPDATE",
- /* 240 */ "trigger_event ::= UPDATE OF idlist",
- /* 241 */ "when_clause ::=",
- /* 242 */ "when_clause ::= WHEN expr",
- /* 243 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 244 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 245 */ "trnm ::= nm DOT nm",
- /* 246 */ "tridxby ::= INDEXED BY nm",
- /* 247 */ "tridxby ::= NOT INDEXED",
- /* 248 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
- /* 249 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
- /* 250 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
- /* 251 */ "trigger_cmd ::= scanpt select scanpt",
- /* 252 */ "expr ::= RAISE LP IGNORE RP",
- /* 253 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 254 */ "raisetype ::= ROLLBACK",
- /* 255 */ "raisetype ::= ABORT",
- /* 256 */ "raisetype ::= FAIL",
- /* 257 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 258 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 259 */ "cmd ::= DETACH database_kw_opt expr",
- /* 260 */ "key_opt ::=",
- /* 261 */ "key_opt ::= KEY expr",
- /* 262 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 263 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
- /* 264 */ "add_column_fullname ::= fullname",
- /* 265 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
- /* 266 */ "cmd ::= create_vtab",
- /* 267 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 268 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 269 */ "vtabarg ::=",
- /* 270 */ "vtabargtoken ::= ANY",
- /* 271 */ "vtabargtoken ::= lp anylist RP",
- /* 272 */ "lp ::= LP",
- /* 273 */ "with ::= WITH wqlist",
- /* 274 */ "with ::= WITH RECURSIVE wqlist",
- /* 275 */ "wqlist ::= nm eidlist_opt AS LP select RP",
- /* 276 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
- /* 277 */ "input ::= cmdlist",
- /* 278 */ "cmdlist ::= cmdlist ecmd",
- /* 279 */ "cmdlist ::= ecmd",
- /* 280 */ "ecmd ::= SEMI",
- /* 281 */ "ecmd ::= cmdx SEMI",
- /* 282 */ "trans_opt ::=",
- /* 283 */ "trans_opt ::= TRANSACTION",
- /* 284 */ "trans_opt ::= TRANSACTION nm",
- /* 285 */ "savepoint_opt ::= SAVEPOINT",
- /* 286 */ "savepoint_opt ::=",
- /* 287 */ "cmd ::= create_table create_table_args",
- /* 288 */ "columnlist ::= columnlist COMMA columnname carglist",
- /* 289 */ "columnlist ::= columnname carglist",
- /* 290 */ "nm ::= ID|INDEXED",
- /* 291 */ "nm ::= STRING",
- /* 292 */ "nm ::= JOIN_KW",
- /* 293 */ "typetoken ::= typename",
- /* 294 */ "typename ::= ID|STRING",
- /* 295 */ "signed ::= plus_num",
- /* 296 */ "signed ::= minus_num",
- /* 297 */ "carglist ::= carglist ccons",
- /* 298 */ "carglist ::=",
- /* 299 */ "ccons ::= NULL onconf",
- /* 300 */ "conslist_opt ::= COMMA conslist",
- /* 301 */ "conslist ::= conslist tconscomma tcons",
- /* 302 */ "conslist ::= tcons",
- /* 303 */ "tconscomma ::=",
- /* 304 */ "defer_subclause_opt ::= defer_subclause",
- /* 305 */ "resolvetype ::= raisetype",
- /* 306 */ "selectnowith ::= oneselect",
- /* 307 */ "oneselect ::= values",
- /* 308 */ "sclp ::= selcollist COMMA",
- /* 309 */ "as ::= ID|STRING",
- /* 310 */ "expr ::= term",
- /* 311 */ "likeop ::= LIKE_KW|MATCH",
- /* 312 */ "exprlist ::= nexprlist",
- /* 313 */ "nmnum ::= plus_num",
- /* 314 */ "nmnum ::= nm",
- /* 315 */ "nmnum ::= ON",
- /* 316 */ "nmnum ::= DELETE",
- /* 317 */ "nmnum ::= DEFAULT",
- /* 318 */ "plus_num ::= INTEGER|FLOAT",
- /* 319 */ "foreach_clause ::=",
- /* 320 */ "foreach_clause ::= FOR EACH ROW",
- /* 321 */ "trnm ::= nm",
- /* 322 */ "tridxby ::=",
- /* 323 */ "database_kw_opt ::= DATABASE",
- /* 324 */ "database_kw_opt ::=",
- /* 325 */ "kwcolumn_opt ::=",
- /* 326 */ "kwcolumn_opt ::= COLUMNKW",
- /* 327 */ "vtabarglist ::= vtabarg",
- /* 328 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 329 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 330 */ "anylist ::=",
- /* 331 */ "anylist ::= anylist LP anylist RP",
- /* 332 */ "anylist ::= anylist ANY",
- /* 333 */ "with ::=",
+ /* 224 */ "cmd ::= VACUUM vinto",
+ /* 225 */ "cmd ::= VACUUM nm vinto",
+ /* 226 */ "vinto ::= INTO expr",
+ /* 227 */ "vinto ::=",
+ /* 228 */ "cmd ::= PRAGMA nm dbnm",
+ /* 229 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 230 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 231 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 232 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 233 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 234 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 235 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 236 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 237 */ "trigger_time ::= BEFORE|AFTER",
+ /* 238 */ "trigger_time ::= INSTEAD OF",
+ /* 239 */ "trigger_time ::=",
+ /* 240 */ "trigger_event ::= DELETE|INSERT",
+ /* 241 */ "trigger_event ::= UPDATE",
+ /* 242 */ "trigger_event ::= UPDATE OF idlist",
+ /* 243 */ "when_clause ::=",
+ /* 244 */ "when_clause ::= WHEN expr",
+ /* 245 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 246 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 247 */ "trnm ::= nm DOT nm",
+ /* 248 */ "tridxby ::= INDEXED BY nm",
+ /* 249 */ "tridxby ::= NOT INDEXED",
+ /* 250 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
+ /* 251 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
+ /* 252 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
+ /* 253 */ "trigger_cmd ::= scanpt select scanpt",
+ /* 254 */ "expr ::= RAISE LP IGNORE RP",
+ /* 255 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 256 */ "raisetype ::= ROLLBACK",
+ /* 257 */ "raisetype ::= ABORT",
+ /* 258 */ "raisetype ::= FAIL",
+ /* 259 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 260 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 261 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 262 */ "key_opt ::=",
+ /* 263 */ "key_opt ::= KEY expr",
+ /* 264 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 265 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 266 */ "add_column_fullname ::= fullname",
+ /* 267 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
+ /* 268 */ "cmd ::= create_vtab",
+ /* 269 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 270 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 271 */ "vtabarg ::=",
+ /* 272 */ "vtabargtoken ::= ANY",
+ /* 273 */ "vtabargtoken ::= lp anylist RP",
+ /* 274 */ "lp ::= LP",
+ /* 275 */ "with ::= WITH wqlist",
+ /* 276 */ "with ::= WITH RECURSIVE wqlist",
+ /* 277 */ "wqlist ::= nm eidlist_opt AS LP select RP",
+ /* 278 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
+ /* 279 */ "input ::= cmdlist",
+ /* 280 */ "cmdlist ::= cmdlist ecmd",
+ /* 281 */ "cmdlist ::= ecmd",
+ /* 282 */ "ecmd ::= SEMI",
+ /* 283 */ "ecmd ::= cmdx SEMI",
+ /* 284 */ "trans_opt ::=",
+ /* 285 */ "trans_opt ::= TRANSACTION",
+ /* 286 */ "trans_opt ::= TRANSACTION nm",
+ /* 287 */ "savepoint_opt ::= SAVEPOINT",
+ /* 288 */ "savepoint_opt ::=",
+ /* 289 */ "cmd ::= create_table create_table_args",
+ /* 290 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 291 */ "columnlist ::= columnname carglist",
+ /* 292 */ "nm ::= ID|INDEXED",
+ /* 293 */ "nm ::= STRING",
+ /* 294 */ "nm ::= JOIN_KW",
+ /* 295 */ "typetoken ::= typename",
+ /* 296 */ "typename ::= ID|STRING",
+ /* 297 */ "signed ::= plus_num",
+ /* 298 */ "signed ::= minus_num",
+ /* 299 */ "carglist ::= carglist ccons",
+ /* 300 */ "carglist ::=",
+ /* 301 */ "ccons ::= NULL onconf",
+ /* 302 */ "conslist_opt ::= COMMA conslist",
+ /* 303 */ "conslist ::= conslist tconscomma tcons",
+ /* 304 */ "conslist ::= tcons",
+ /* 305 */ "tconscomma ::=",
+ /* 306 */ "defer_subclause_opt ::= defer_subclause",
+ /* 307 */ "resolvetype ::= raisetype",
+ /* 308 */ "selectnowith ::= oneselect",
+ /* 309 */ "oneselect ::= values",
+ /* 310 */ "sclp ::= selcollist COMMA",
+ /* 311 */ "as ::= ID|STRING",
+ /* 312 */ "expr ::= term",
+ /* 313 */ "likeop ::= LIKE_KW|MATCH",
+ /* 314 */ "exprlist ::= nexprlist",
+ /* 315 */ "nmnum ::= plus_num",
+ /* 316 */ "nmnum ::= nm",
+ /* 317 */ "nmnum ::= ON",
+ /* 318 */ "nmnum ::= DELETE",
+ /* 319 */ "nmnum ::= DEFAULT",
+ /* 320 */ "plus_num ::= INTEGER|FLOAT",
+ /* 321 */ "foreach_clause ::=",
+ /* 322 */ "foreach_clause ::= FOR EACH ROW",
+ /* 323 */ "trnm ::= nm",
+ /* 324 */ "tridxby ::=",
+ /* 325 */ "database_kw_opt ::= DATABASE",
+ /* 326 */ "database_kw_opt ::=",
+ /* 327 */ "kwcolumn_opt ::=",
+ /* 328 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 329 */ "vtabarglist ::= vtabarg",
+ /* 330 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 331 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 332 */ "anylist ::=",
+ /* 333 */ "anylist ::= anylist LP anylist RP",
+ /* 334 */ "anylist ::= anylist ANY",
+ /* 335 */ "with ::=",
};
#endif /* NDEBUG */
@@ -148703,7 +149161,7 @@ static void yy_destructor(
case 197: /* oneselect */
case 208: /* values */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy399));
+sqlite3SelectDelete(pParse->db, (yypminor->yy43));
}
break;
case 174: /* term */
@@ -148713,10 +149171,11 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy399));
case 216: /* on_opt */
case 230: /* case_operand */
case 232: /* case_else */
- case 241: /* when_clause */
- case 246: /* key_opt */
+ case 235: /* vinto */
+ case 242: /* when_clause */
+ case 247: /* key_opt */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy182));
+sqlite3ExprDelete(pParse->db, (yypminor->yy2));
}
break;
case 179: /* eidlist_opt */
@@ -148732,7 +149191,7 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy182));
case 229: /* paren_exprlist */
case 231: /* case_exprlist */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy232));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy402));
}
break;
case 195: /* fullname */
@@ -148741,30 +149200,30 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy232));
case 213: /* stl_prefix */
case 219: /* xfullname */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy427));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy3));
}
break;
case 198: /* wqlist */
{
-sqlite3WithDelete(pParse->db, (yypminor->yy91));
+sqlite3WithDelete(pParse->db, (yypminor->yy4));
}
break;
case 217: /* using_opt */
case 220: /* idlist */
case 224: /* idlist_opt */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy510));
+sqlite3IdListDelete(pParse->db, (yypminor->yy272));
}
break;
- case 237: /* trigger_cmd_list */
- case 242: /* trigger_cmd */
+ case 238: /* trigger_cmd_list */
+ case 243: /* trigger_cmd */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy47));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy347));
}
break;
- case 239: /* trigger_event */
+ case 240: /* trigger_event */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy300).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy338).b);
}
break;
/********* End destructor definitions *****************************************/
@@ -149056,347 +149515,686 @@ static void yy_shift(
yyTraceShift(yypParser, yyNewState, "Shift");
}
-/* The following table contains information about every rule that
-** is used during the reduce.
-*/
-static const struct {
- YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
- signed char nrhs; /* Negative of the number of RHS symbols in the rule */
-} yyRuleInfo[] = {
- { 149, -1 }, /* (0) cmdx ::= cmd */
- { 150, -3 }, /* (1) cmd ::= BEGIN transtype trans_opt */
- { 151, 0 }, /* (2) transtype ::= */
- { 151, -1 }, /* (3) transtype ::= DEFERRED */
- { 151, -1 }, /* (4) transtype ::= IMMEDIATE */
- { 151, -1 }, /* (5) transtype ::= EXCLUSIVE */
- { 150, -2 }, /* (6) cmd ::= COMMIT|END trans_opt */
- { 150, -2 }, /* (7) cmd ::= ROLLBACK trans_opt */
- { 150, -2 }, /* (8) cmd ::= SAVEPOINT nm */
- { 150, -3 }, /* (9) cmd ::= RELEASE savepoint_opt nm */
- { 150, -5 }, /* (10) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
- { 155, -6 }, /* (11) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
- { 157, -1 }, /* (12) createkw ::= CREATE */
- { 159, 0 }, /* (13) ifnotexists ::= */
- { 159, -3 }, /* (14) ifnotexists ::= IF NOT EXISTS */
- { 158, -1 }, /* (15) temp ::= TEMP */
- { 158, 0 }, /* (16) temp ::= */
- { 156, -5 }, /* (17) create_table_args ::= LP columnlist conslist_opt RP table_options */
- { 156, -2 }, /* (18) create_table_args ::= AS select */
- { 163, 0 }, /* (19) table_options ::= */
- { 163, -2 }, /* (20) table_options ::= WITHOUT nm */
- { 165, -2 }, /* (21) columnname ::= nm typetoken */
- { 167, 0 }, /* (22) typetoken ::= */
- { 167, -4 }, /* (23) typetoken ::= typename LP signed RP */
- { 167, -6 }, /* (24) typetoken ::= typename LP signed COMMA signed RP */
- { 168, -2 }, /* (25) typename ::= typename ID|STRING */
- { 172, 0 }, /* (26) scanpt ::= */
- { 173, -2 }, /* (27) ccons ::= CONSTRAINT nm */
- { 173, -4 }, /* (28) ccons ::= DEFAULT scanpt term scanpt */
- { 173, -4 }, /* (29) ccons ::= DEFAULT LP expr RP */
- { 173, -4 }, /* (30) ccons ::= DEFAULT PLUS term scanpt */
- { 173, -4 }, /* (31) ccons ::= DEFAULT MINUS term scanpt */
- { 173, -3 }, /* (32) ccons ::= DEFAULT scanpt ID|INDEXED */
- { 173, -3 }, /* (33) ccons ::= NOT NULL onconf */
- { 173, -5 }, /* (34) ccons ::= PRIMARY KEY sortorder onconf autoinc */
- { 173, -2 }, /* (35) ccons ::= UNIQUE onconf */
- { 173, -4 }, /* (36) ccons ::= CHECK LP expr RP */
- { 173, -4 }, /* (37) ccons ::= REFERENCES nm eidlist_opt refargs */
- { 173, -1 }, /* (38) ccons ::= defer_subclause */
- { 173, -2 }, /* (39) ccons ::= COLLATE ID|STRING */
- { 178, 0 }, /* (40) autoinc ::= */
- { 178, -1 }, /* (41) autoinc ::= AUTOINCR */
- { 180, 0 }, /* (42) refargs ::= */
- { 180, -2 }, /* (43) refargs ::= refargs refarg */
- { 182, -2 }, /* (44) refarg ::= MATCH nm */
- { 182, -3 }, /* (45) refarg ::= ON INSERT refact */
- { 182, -3 }, /* (46) refarg ::= ON DELETE refact */
- { 182, -3 }, /* (47) refarg ::= ON UPDATE refact */
- { 183, -2 }, /* (48) refact ::= SET NULL */
- { 183, -2 }, /* (49) refact ::= SET DEFAULT */
- { 183, -1 }, /* (50) refact ::= CASCADE */
- { 183, -1 }, /* (51) refact ::= RESTRICT */
- { 183, -2 }, /* (52) refact ::= NO ACTION */
- { 181, -3 }, /* (53) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- { 181, -2 }, /* (54) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- { 184, 0 }, /* (55) init_deferred_pred_opt ::= */
- { 184, -2 }, /* (56) init_deferred_pred_opt ::= INITIALLY DEFERRED */
- { 184, -2 }, /* (57) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- { 162, 0 }, /* (58) conslist_opt ::= */
- { 186, -1 }, /* (59) tconscomma ::= COMMA */
- { 187, -2 }, /* (60) tcons ::= CONSTRAINT nm */
- { 187, -7 }, /* (61) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
- { 187, -5 }, /* (62) tcons ::= UNIQUE LP sortlist RP onconf */
- { 187, -5 }, /* (63) tcons ::= CHECK LP expr RP onconf */
- { 187, -10 }, /* (64) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
- { 190, 0 }, /* (65) defer_subclause_opt ::= */
- { 176, 0 }, /* (66) onconf ::= */
- { 176, -3 }, /* (67) onconf ::= ON CONFLICT resolvetype */
- { 191, 0 }, /* (68) orconf ::= */
- { 191, -2 }, /* (69) orconf ::= OR resolvetype */
- { 192, -1 }, /* (70) resolvetype ::= IGNORE */
- { 192, -1 }, /* (71) resolvetype ::= REPLACE */
- { 150, -4 }, /* (72) cmd ::= DROP TABLE ifexists fullname */
- { 194, -2 }, /* (73) ifexists ::= IF EXISTS */
- { 194, 0 }, /* (74) ifexists ::= */
- { 150, -9 }, /* (75) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
- { 150, -4 }, /* (76) cmd ::= DROP VIEW ifexists fullname */
- { 150, -1 }, /* (77) cmd ::= select */
- { 164, -3 }, /* (78) select ::= WITH wqlist selectnowith */
- { 164, -4 }, /* (79) select ::= WITH RECURSIVE wqlist selectnowith */
- { 164, -1 }, /* (80) select ::= selectnowith */
- { 196, -3 }, /* (81) selectnowith ::= selectnowith multiselect_op oneselect */
- { 199, -1 }, /* (82) multiselect_op ::= UNION */
- { 199, -2 }, /* (83) multiselect_op ::= UNION ALL */
- { 199, -1 }, /* (84) multiselect_op ::= EXCEPT|INTERSECT */
- { 197, -9 }, /* (85) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- { 208, -4 }, /* (86) values ::= VALUES LP nexprlist RP */
- { 208, -5 }, /* (87) values ::= values COMMA LP nexprlist RP */
- { 200, -1 }, /* (88) distinct ::= DISTINCT */
- { 200, -1 }, /* (89) distinct ::= ALL */
- { 200, 0 }, /* (90) distinct ::= */
- { 210, 0 }, /* (91) sclp ::= */
- { 201, -5 }, /* (92) selcollist ::= sclp scanpt expr scanpt as */
- { 201, -3 }, /* (93) selcollist ::= sclp scanpt STAR */
- { 201, -5 }, /* (94) selcollist ::= sclp scanpt nm DOT STAR */
- { 211, -2 }, /* (95) as ::= AS nm */
- { 211, 0 }, /* (96) as ::= */
- { 202, 0 }, /* (97) from ::= */
- { 202, -2 }, /* (98) from ::= FROM seltablist */
- { 213, -2 }, /* (99) stl_prefix ::= seltablist joinop */
- { 213, 0 }, /* (100) stl_prefix ::= */
- { 212, -7 }, /* (101) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
- { 212, -9 }, /* (102) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
- { 212, -7 }, /* (103) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
- { 212, -7 }, /* (104) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
- { 160, 0 }, /* (105) dbnm ::= */
- { 160, -2 }, /* (106) dbnm ::= DOT nm */
- { 195, -1 }, /* (107) fullname ::= nm */
- { 195, -3 }, /* (108) fullname ::= nm DOT nm */
- { 219, -1 }, /* (109) xfullname ::= nm */
- { 219, -3 }, /* (110) xfullname ::= nm DOT nm */
- { 219, -5 }, /* (111) xfullname ::= nm DOT nm AS nm */
- { 219, -3 }, /* (112) xfullname ::= nm AS nm */
- { 214, -1 }, /* (113) joinop ::= COMMA|JOIN */
- { 214, -2 }, /* (114) joinop ::= JOIN_KW JOIN */
- { 214, -3 }, /* (115) joinop ::= JOIN_KW nm JOIN */
- { 214, -4 }, /* (116) joinop ::= JOIN_KW nm nm JOIN */
- { 216, -2 }, /* (117) on_opt ::= ON expr */
- { 216, 0 }, /* (118) on_opt ::= */
- { 215, 0 }, /* (119) indexed_opt ::= */
- { 215, -3 }, /* (120) indexed_opt ::= INDEXED BY nm */
- { 215, -2 }, /* (121) indexed_opt ::= NOT INDEXED */
- { 217, -4 }, /* (122) using_opt ::= USING LP idlist RP */
- { 217, 0 }, /* (123) using_opt ::= */
- { 206, 0 }, /* (124) orderby_opt ::= */
- { 206, -3 }, /* (125) orderby_opt ::= ORDER BY sortlist */
- { 188, -4 }, /* (126) sortlist ::= sortlist COMMA expr sortorder */
- { 188, -2 }, /* (127) sortlist ::= expr sortorder */
- { 177, -1 }, /* (128) sortorder ::= ASC */
- { 177, -1 }, /* (129) sortorder ::= DESC */
- { 177, 0 }, /* (130) sortorder ::= */
- { 204, 0 }, /* (131) groupby_opt ::= */
- { 204, -3 }, /* (132) groupby_opt ::= GROUP BY nexprlist */
- { 205, 0 }, /* (133) having_opt ::= */
- { 205, -2 }, /* (134) having_opt ::= HAVING expr */
- { 207, 0 }, /* (135) limit_opt ::= */
- { 207, -2 }, /* (136) limit_opt ::= LIMIT expr */
- { 207, -4 }, /* (137) limit_opt ::= LIMIT expr OFFSET expr */
- { 207, -4 }, /* (138) limit_opt ::= LIMIT expr COMMA expr */
- { 150, -6 }, /* (139) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
- { 203, 0 }, /* (140) where_opt ::= */
- { 203, -2 }, /* (141) where_opt ::= WHERE expr */
- { 150, -8 }, /* (142) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
- { 222, -5 }, /* (143) setlist ::= setlist COMMA nm EQ expr */
- { 222, -7 }, /* (144) setlist ::= setlist COMMA LP idlist RP EQ expr */
- { 222, -3 }, /* (145) setlist ::= nm EQ expr */
- { 222, -5 }, /* (146) setlist ::= LP idlist RP EQ expr */
- { 150, -7 }, /* (147) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- { 150, -7 }, /* (148) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
- { 225, 0 }, /* (149) upsert ::= */
- { 225, -11 }, /* (150) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
- { 225, -8 }, /* (151) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
- { 225, -4 }, /* (152) upsert ::= ON CONFLICT DO NOTHING */
- { 223, -2 }, /* (153) insert_cmd ::= INSERT orconf */
- { 223, -1 }, /* (154) insert_cmd ::= REPLACE */
- { 224, 0 }, /* (155) idlist_opt ::= */
- { 224, -3 }, /* (156) idlist_opt ::= LP idlist RP */
- { 220, -3 }, /* (157) idlist ::= idlist COMMA nm */
- { 220, -1 }, /* (158) idlist ::= nm */
- { 175, -3 }, /* (159) expr ::= LP expr RP */
- { 175, -1 }, /* (160) expr ::= ID|INDEXED */
- { 175, -1 }, /* (161) expr ::= JOIN_KW */
- { 175, -3 }, /* (162) expr ::= nm DOT nm */
- { 175, -5 }, /* (163) expr ::= nm DOT nm DOT nm */
- { 174, -1 }, /* (164) term ::= NULL|FLOAT|BLOB */
- { 174, -1 }, /* (165) term ::= STRING */
- { 174, -1 }, /* (166) term ::= INTEGER */
- { 175, -1 }, /* (167) expr ::= VARIABLE */
- { 175, -3 }, /* (168) expr ::= expr COLLATE ID|STRING */
- { 175, -6 }, /* (169) expr ::= CAST LP expr AS typetoken RP */
- { 175, -5 }, /* (170) expr ::= ID|INDEXED LP distinct exprlist RP */
- { 175, -4 }, /* (171) expr ::= ID|INDEXED LP STAR RP */
- { 174, -1 }, /* (172) term ::= CTIME_KW */
- { 175, -5 }, /* (173) expr ::= LP nexprlist COMMA expr RP */
- { 175, -3 }, /* (174) expr ::= expr AND expr */
- { 175, -3 }, /* (175) expr ::= expr OR expr */
- { 175, -3 }, /* (176) expr ::= expr LT|GT|GE|LE expr */
- { 175, -3 }, /* (177) expr ::= expr EQ|NE expr */
- { 175, -3 }, /* (178) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- { 175, -3 }, /* (179) expr ::= expr PLUS|MINUS expr */
- { 175, -3 }, /* (180) expr ::= expr STAR|SLASH|REM expr */
- { 175, -3 }, /* (181) expr ::= expr CONCAT expr */
- { 226, -2 }, /* (182) likeop ::= NOT LIKE_KW|MATCH */
- { 175, -3 }, /* (183) expr ::= expr likeop expr */
- { 175, -5 }, /* (184) expr ::= expr likeop expr ESCAPE expr */
- { 175, -2 }, /* (185) expr ::= expr ISNULL|NOTNULL */
- { 175, -3 }, /* (186) expr ::= expr NOT NULL */
- { 175, -3 }, /* (187) expr ::= expr IS expr */
- { 175, -4 }, /* (188) expr ::= expr IS NOT expr */
- { 175, -2 }, /* (189) expr ::= NOT expr */
- { 175, -2 }, /* (190) expr ::= BITNOT expr */
- { 175, -2 }, /* (191) expr ::= PLUS|MINUS expr */
- { 227, -1 }, /* (192) between_op ::= BETWEEN */
- { 227, -2 }, /* (193) between_op ::= NOT BETWEEN */
- { 175, -5 }, /* (194) expr ::= expr between_op expr AND expr */
- { 228, -1 }, /* (195) in_op ::= IN */
- { 228, -2 }, /* (196) in_op ::= NOT IN */
- { 175, -5 }, /* (197) expr ::= expr in_op LP exprlist RP */
- { 175, -3 }, /* (198) expr ::= LP select RP */
- { 175, -5 }, /* (199) expr ::= expr in_op LP select RP */
- { 175, -5 }, /* (200) expr ::= expr in_op nm dbnm paren_exprlist */
- { 175, -4 }, /* (201) expr ::= EXISTS LP select RP */
- { 175, -5 }, /* (202) expr ::= CASE case_operand case_exprlist case_else END */
- { 231, -5 }, /* (203) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- { 231, -4 }, /* (204) case_exprlist ::= WHEN expr THEN expr */
- { 232, -2 }, /* (205) case_else ::= ELSE expr */
- { 232, 0 }, /* (206) case_else ::= */
- { 230, -1 }, /* (207) case_operand ::= expr */
- { 230, 0 }, /* (208) case_operand ::= */
- { 218, 0 }, /* (209) exprlist ::= */
- { 209, -3 }, /* (210) nexprlist ::= nexprlist COMMA expr */
- { 209, -1 }, /* (211) nexprlist ::= expr */
- { 229, 0 }, /* (212) paren_exprlist ::= */
- { 229, -3 }, /* (213) paren_exprlist ::= LP exprlist RP */
- { 150, -12 }, /* (214) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- { 233, -1 }, /* (215) uniqueflag ::= UNIQUE */
- { 233, 0 }, /* (216) uniqueflag ::= */
- { 179, 0 }, /* (217) eidlist_opt ::= */
- { 179, -3 }, /* (218) eidlist_opt ::= LP eidlist RP */
- { 189, -5 }, /* (219) eidlist ::= eidlist COMMA nm collate sortorder */
- { 189, -3 }, /* (220) eidlist ::= nm collate sortorder */
- { 234, 0 }, /* (221) collate ::= */
- { 234, -2 }, /* (222) collate ::= COLLATE ID|STRING */
- { 150, -4 }, /* (223) cmd ::= DROP INDEX ifexists fullname */
- { 150, -1 }, /* (224) cmd ::= VACUUM */
- { 150, -2 }, /* (225) cmd ::= VACUUM nm */
- { 150, -3 }, /* (226) cmd ::= PRAGMA nm dbnm */
- { 150, -5 }, /* (227) cmd ::= PRAGMA nm dbnm EQ nmnum */
- { 150, -6 }, /* (228) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- { 150, -5 }, /* (229) cmd ::= PRAGMA nm dbnm EQ minus_num */
- { 150, -6 }, /* (230) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- { 170, -2 }, /* (231) plus_num ::= PLUS INTEGER|FLOAT */
- { 171, -2 }, /* (232) minus_num ::= MINUS INTEGER|FLOAT */
- { 150, -5 }, /* (233) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- { 236, -11 }, /* (234) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- { 238, -1 }, /* (235) trigger_time ::= BEFORE|AFTER */
- { 238, -2 }, /* (236) trigger_time ::= INSTEAD OF */
- { 238, 0 }, /* (237) trigger_time ::= */
- { 239, -1 }, /* (238) trigger_event ::= DELETE|INSERT */
- { 239, -1 }, /* (239) trigger_event ::= UPDATE */
- { 239, -3 }, /* (240) trigger_event ::= UPDATE OF idlist */
- { 241, 0 }, /* (241) when_clause ::= */
- { 241, -2 }, /* (242) when_clause ::= WHEN expr */
- { 237, -3 }, /* (243) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- { 237, -2 }, /* (244) trigger_cmd_list ::= trigger_cmd SEMI */
- { 243, -3 }, /* (245) trnm ::= nm DOT nm */
- { 244, -3 }, /* (246) tridxby ::= INDEXED BY nm */
- { 244, -2 }, /* (247) tridxby ::= NOT INDEXED */
- { 242, -8 }, /* (248) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
- { 242, -8 }, /* (249) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- { 242, -6 }, /* (250) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- { 242, -3 }, /* (251) trigger_cmd ::= scanpt select scanpt */
- { 175, -4 }, /* (252) expr ::= RAISE LP IGNORE RP */
- { 175, -6 }, /* (253) expr ::= RAISE LP raisetype COMMA nm RP */
- { 193, -1 }, /* (254) raisetype ::= ROLLBACK */
- { 193, -1 }, /* (255) raisetype ::= ABORT */
- { 193, -1 }, /* (256) raisetype ::= FAIL */
- { 150, -4 }, /* (257) cmd ::= DROP TRIGGER ifexists fullname */
- { 150, -6 }, /* (258) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- { 150, -3 }, /* (259) cmd ::= DETACH database_kw_opt expr */
- { 246, 0 }, /* (260) key_opt ::= */
- { 246, -2 }, /* (261) key_opt ::= KEY expr */
- { 150, -6 }, /* (262) cmd ::= ALTER TABLE fullname RENAME TO nm */
- { 150, -7 }, /* (263) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- { 247, -1 }, /* (264) add_column_fullname ::= fullname */
- { 150, -8 }, /* (265) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- { 150, -1 }, /* (266) cmd ::= create_vtab */
- { 150, -4 }, /* (267) cmd ::= create_vtab LP vtabarglist RP */
- { 249, -8 }, /* (268) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- { 251, 0 }, /* (269) vtabarg ::= */
- { 252, -1 }, /* (270) vtabargtoken ::= ANY */
- { 252, -3 }, /* (271) vtabargtoken ::= lp anylist RP */
- { 253, -1 }, /* (272) lp ::= LP */
- { 221, -2 }, /* (273) with ::= WITH wqlist */
- { 221, -3 }, /* (274) with ::= WITH RECURSIVE wqlist */
- { 198, -6 }, /* (275) wqlist ::= nm eidlist_opt AS LP select RP */
- { 198, -8 }, /* (276) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- { 146, -1 }, /* (277) input ::= cmdlist */
- { 147, -2 }, /* (278) cmdlist ::= cmdlist ecmd */
- { 147, -1 }, /* (279) cmdlist ::= ecmd */
- { 148, -1 }, /* (280) ecmd ::= SEMI */
- { 148, -2 }, /* (281) ecmd ::= cmdx SEMI */
- { 152, 0 }, /* (282) trans_opt ::= */
- { 152, -1 }, /* (283) trans_opt ::= TRANSACTION */
- { 152, -2 }, /* (284) trans_opt ::= TRANSACTION nm */
- { 154, -1 }, /* (285) savepoint_opt ::= SAVEPOINT */
- { 154, 0 }, /* (286) savepoint_opt ::= */
- { 150, -2 }, /* (287) cmd ::= create_table create_table_args */
- { 161, -4 }, /* (288) columnlist ::= columnlist COMMA columnname carglist */
- { 161, -2 }, /* (289) columnlist ::= columnname carglist */
- { 153, -1 }, /* (290) nm ::= ID|INDEXED */
- { 153, -1 }, /* (291) nm ::= STRING */
- { 153, -1 }, /* (292) nm ::= JOIN_KW */
- { 167, -1 }, /* (293) typetoken ::= typename */
- { 168, -1 }, /* (294) typename ::= ID|STRING */
- { 169, -1 }, /* (295) signed ::= plus_num */
- { 169, -1 }, /* (296) signed ::= minus_num */
- { 166, -2 }, /* (297) carglist ::= carglist ccons */
- { 166, 0 }, /* (298) carglist ::= */
- { 173, -2 }, /* (299) ccons ::= NULL onconf */
- { 162, -2 }, /* (300) conslist_opt ::= COMMA conslist */
- { 185, -3 }, /* (301) conslist ::= conslist tconscomma tcons */
- { 185, -1 }, /* (302) conslist ::= tcons */
- { 186, 0 }, /* (303) tconscomma ::= */
- { 190, -1 }, /* (304) defer_subclause_opt ::= defer_subclause */
- { 192, -1 }, /* (305) resolvetype ::= raisetype */
- { 196, -1 }, /* (306) selectnowith ::= oneselect */
- { 197, -1 }, /* (307) oneselect ::= values */
- { 210, -2 }, /* (308) sclp ::= selcollist COMMA */
- { 211, -1 }, /* (309) as ::= ID|STRING */
- { 175, -1 }, /* (310) expr ::= term */
- { 226, -1 }, /* (311) likeop ::= LIKE_KW|MATCH */
- { 218, -1 }, /* (312) exprlist ::= nexprlist */
- { 235, -1 }, /* (313) nmnum ::= plus_num */
- { 235, -1 }, /* (314) nmnum ::= nm */
- { 235, -1 }, /* (315) nmnum ::= ON */
- { 235, -1 }, /* (316) nmnum ::= DELETE */
- { 235, -1 }, /* (317) nmnum ::= DEFAULT */
- { 170, -1 }, /* (318) plus_num ::= INTEGER|FLOAT */
- { 240, 0 }, /* (319) foreach_clause ::= */
- { 240, -3 }, /* (320) foreach_clause ::= FOR EACH ROW */
- { 243, -1 }, /* (321) trnm ::= nm */
- { 244, 0 }, /* (322) tridxby ::= */
- { 245, -1 }, /* (323) database_kw_opt ::= DATABASE */
- { 245, 0 }, /* (324) database_kw_opt ::= */
- { 248, 0 }, /* (325) kwcolumn_opt ::= */
- { 248, -1 }, /* (326) kwcolumn_opt ::= COLUMNKW */
- { 250, -1 }, /* (327) vtabarglist ::= vtabarg */
- { 250, -3 }, /* (328) vtabarglist ::= vtabarglist COMMA vtabarg */
- { 251, -2 }, /* (329) vtabarg ::= vtabarg vtabargtoken */
- { 254, 0 }, /* (330) anylist ::= */
- { 254, -4 }, /* (331) anylist ::= anylist LP anylist RP */
- { 254, -2 }, /* (332) anylist ::= anylist ANY */
- { 221, 0 }, /* (333) with ::= */
+/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
+** of that rule */
+static const YYCODETYPE yyRuleInfoLhs[] = {
+ 149, /* (0) cmdx ::= cmd */
+ 150, /* (1) cmd ::= BEGIN transtype trans_opt */
+ 151, /* (2) transtype ::= */
+ 151, /* (3) transtype ::= DEFERRED */
+ 151, /* (4) transtype ::= IMMEDIATE */
+ 151, /* (5) transtype ::= EXCLUSIVE */
+ 150, /* (6) cmd ::= COMMIT|END trans_opt */
+ 150, /* (7) cmd ::= ROLLBACK trans_opt */
+ 150, /* (8) cmd ::= SAVEPOINT nm */
+ 150, /* (9) cmd ::= RELEASE savepoint_opt nm */
+ 150, /* (10) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+ 155, /* (11) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+ 157, /* (12) createkw ::= CREATE */
+ 159, /* (13) ifnotexists ::= */
+ 159, /* (14) ifnotexists ::= IF NOT EXISTS */
+ 158, /* (15) temp ::= TEMP */
+ 158, /* (16) temp ::= */
+ 156, /* (17) create_table_args ::= LP columnlist conslist_opt RP table_options */
+ 156, /* (18) create_table_args ::= AS select */
+ 163, /* (19) table_options ::= */
+ 163, /* (20) table_options ::= WITHOUT nm */
+ 165, /* (21) columnname ::= nm typetoken */
+ 167, /* (22) typetoken ::= */
+ 167, /* (23) typetoken ::= typename LP signed RP */
+ 167, /* (24) typetoken ::= typename LP signed COMMA signed RP */
+ 168, /* (25) typename ::= typename ID|STRING */
+ 172, /* (26) scanpt ::= */
+ 173, /* (27) ccons ::= CONSTRAINT nm */
+ 173, /* (28) ccons ::= DEFAULT scanpt term scanpt */
+ 173, /* (29) ccons ::= DEFAULT LP expr RP */
+ 173, /* (30) ccons ::= DEFAULT PLUS term scanpt */
+ 173, /* (31) ccons ::= DEFAULT MINUS term scanpt */
+ 173, /* (32) ccons ::= DEFAULT scanpt ID|INDEXED */
+ 173, /* (33) ccons ::= NOT NULL onconf */
+ 173, /* (34) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ 173, /* (35) ccons ::= UNIQUE onconf */
+ 173, /* (36) ccons ::= CHECK LP expr RP */
+ 173, /* (37) ccons ::= REFERENCES nm eidlist_opt refargs */
+ 173, /* (38) ccons ::= defer_subclause */
+ 173, /* (39) ccons ::= COLLATE ID|STRING */
+ 178, /* (40) autoinc ::= */
+ 178, /* (41) autoinc ::= AUTOINCR */
+ 180, /* (42) refargs ::= */
+ 180, /* (43) refargs ::= refargs refarg */
+ 182, /* (44) refarg ::= MATCH nm */
+ 182, /* (45) refarg ::= ON INSERT refact */
+ 182, /* (46) refarg ::= ON DELETE refact */
+ 182, /* (47) refarg ::= ON UPDATE refact */
+ 183, /* (48) refact ::= SET NULL */
+ 183, /* (49) refact ::= SET DEFAULT */
+ 183, /* (50) refact ::= CASCADE */
+ 183, /* (51) refact ::= RESTRICT */
+ 183, /* (52) refact ::= NO ACTION */
+ 181, /* (53) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ 181, /* (54) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ 184, /* (55) init_deferred_pred_opt ::= */
+ 184, /* (56) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ 184, /* (57) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ 162, /* (58) conslist_opt ::= */
+ 186, /* (59) tconscomma ::= COMMA */
+ 187, /* (60) tcons ::= CONSTRAINT nm */
+ 187, /* (61) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ 187, /* (62) tcons ::= UNIQUE LP sortlist RP onconf */
+ 187, /* (63) tcons ::= CHECK LP expr RP onconf */
+ 187, /* (64) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ 190, /* (65) defer_subclause_opt ::= */
+ 176, /* (66) onconf ::= */
+ 176, /* (67) onconf ::= ON CONFLICT resolvetype */
+ 191, /* (68) orconf ::= */
+ 191, /* (69) orconf ::= OR resolvetype */
+ 192, /* (70) resolvetype ::= IGNORE */
+ 192, /* (71) resolvetype ::= REPLACE */
+ 150, /* (72) cmd ::= DROP TABLE ifexists fullname */
+ 194, /* (73) ifexists ::= IF EXISTS */
+ 194, /* (74) ifexists ::= */
+ 150, /* (75) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ 150, /* (76) cmd ::= DROP VIEW ifexists fullname */
+ 150, /* (77) cmd ::= select */
+ 164, /* (78) select ::= WITH wqlist selectnowith */
+ 164, /* (79) select ::= WITH RECURSIVE wqlist selectnowith */
+ 164, /* (80) select ::= selectnowith */
+ 196, /* (81) selectnowith ::= selectnowith multiselect_op oneselect */
+ 199, /* (82) multiselect_op ::= UNION */
+ 199, /* (83) multiselect_op ::= UNION ALL */
+ 199, /* (84) multiselect_op ::= EXCEPT|INTERSECT */
+ 197, /* (85) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ 208, /* (86) values ::= VALUES LP nexprlist RP */
+ 208, /* (87) values ::= values COMMA LP nexprlist RP */
+ 200, /* (88) distinct ::= DISTINCT */
+ 200, /* (89) distinct ::= ALL */
+ 200, /* (90) distinct ::= */
+ 210, /* (91) sclp ::= */
+ 201, /* (92) selcollist ::= sclp scanpt expr scanpt as */
+ 201, /* (93) selcollist ::= sclp scanpt STAR */
+ 201, /* (94) selcollist ::= sclp scanpt nm DOT STAR */
+ 211, /* (95) as ::= AS nm */
+ 211, /* (96) as ::= */
+ 202, /* (97) from ::= */
+ 202, /* (98) from ::= FROM seltablist */
+ 213, /* (99) stl_prefix ::= seltablist joinop */
+ 213, /* (100) stl_prefix ::= */
+ 212, /* (101) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ 212, /* (102) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ 212, /* (103) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ 212, /* (104) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ 160, /* (105) dbnm ::= */
+ 160, /* (106) dbnm ::= DOT nm */
+ 195, /* (107) fullname ::= nm */
+ 195, /* (108) fullname ::= nm DOT nm */
+ 219, /* (109) xfullname ::= nm */
+ 219, /* (110) xfullname ::= nm DOT nm */
+ 219, /* (111) xfullname ::= nm DOT nm AS nm */
+ 219, /* (112) xfullname ::= nm AS nm */
+ 214, /* (113) joinop ::= COMMA|JOIN */
+ 214, /* (114) joinop ::= JOIN_KW JOIN */
+ 214, /* (115) joinop ::= JOIN_KW nm JOIN */
+ 214, /* (116) joinop ::= JOIN_KW nm nm JOIN */
+ 216, /* (117) on_opt ::= ON expr */
+ 216, /* (118) on_opt ::= */
+ 215, /* (119) indexed_opt ::= */
+ 215, /* (120) indexed_opt ::= INDEXED BY nm */
+ 215, /* (121) indexed_opt ::= NOT INDEXED */
+ 217, /* (122) using_opt ::= USING LP idlist RP */
+ 217, /* (123) using_opt ::= */
+ 206, /* (124) orderby_opt ::= */
+ 206, /* (125) orderby_opt ::= ORDER BY sortlist */
+ 188, /* (126) sortlist ::= sortlist COMMA expr sortorder */
+ 188, /* (127) sortlist ::= expr sortorder */
+ 177, /* (128) sortorder ::= ASC */
+ 177, /* (129) sortorder ::= DESC */
+ 177, /* (130) sortorder ::= */
+ 204, /* (131) groupby_opt ::= */
+ 204, /* (132) groupby_opt ::= GROUP BY nexprlist */
+ 205, /* (133) having_opt ::= */
+ 205, /* (134) having_opt ::= HAVING expr */
+ 207, /* (135) limit_opt ::= */
+ 207, /* (136) limit_opt ::= LIMIT expr */
+ 207, /* (137) limit_opt ::= LIMIT expr OFFSET expr */
+ 207, /* (138) limit_opt ::= LIMIT expr COMMA expr */
+ 150, /* (139) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ 203, /* (140) where_opt ::= */
+ 203, /* (141) where_opt ::= WHERE expr */
+ 150, /* (142) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
+ 222, /* (143) setlist ::= setlist COMMA nm EQ expr */
+ 222, /* (144) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ 222, /* (145) setlist ::= nm EQ expr */
+ 222, /* (146) setlist ::= LP idlist RP EQ expr */
+ 150, /* (147) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ 150, /* (148) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ 225, /* (149) upsert ::= */
+ 225, /* (150) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
+ 225, /* (151) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
+ 225, /* (152) upsert ::= ON CONFLICT DO NOTHING */
+ 223, /* (153) insert_cmd ::= INSERT orconf */
+ 223, /* (154) insert_cmd ::= REPLACE */
+ 224, /* (155) idlist_opt ::= */
+ 224, /* (156) idlist_opt ::= LP idlist RP */
+ 220, /* (157) idlist ::= idlist COMMA nm */
+ 220, /* (158) idlist ::= nm */
+ 175, /* (159) expr ::= LP expr RP */
+ 175, /* (160) expr ::= ID|INDEXED */
+ 175, /* (161) expr ::= JOIN_KW */
+ 175, /* (162) expr ::= nm DOT nm */
+ 175, /* (163) expr ::= nm DOT nm DOT nm */
+ 174, /* (164) term ::= NULL|FLOAT|BLOB */
+ 174, /* (165) term ::= STRING */
+ 174, /* (166) term ::= INTEGER */
+ 175, /* (167) expr ::= VARIABLE */
+ 175, /* (168) expr ::= expr COLLATE ID|STRING */
+ 175, /* (169) expr ::= CAST LP expr AS typetoken RP */
+ 175, /* (170) expr ::= ID|INDEXED LP distinct exprlist RP */
+ 175, /* (171) expr ::= ID|INDEXED LP STAR RP */
+ 174, /* (172) term ::= CTIME_KW */
+ 175, /* (173) expr ::= LP nexprlist COMMA expr RP */
+ 175, /* (174) expr ::= expr AND expr */
+ 175, /* (175) expr ::= expr OR expr */
+ 175, /* (176) expr ::= expr LT|GT|GE|LE expr */
+ 175, /* (177) expr ::= expr EQ|NE expr */
+ 175, /* (178) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ 175, /* (179) expr ::= expr PLUS|MINUS expr */
+ 175, /* (180) expr ::= expr STAR|SLASH|REM expr */
+ 175, /* (181) expr ::= expr CONCAT expr */
+ 226, /* (182) likeop ::= NOT LIKE_KW|MATCH */
+ 175, /* (183) expr ::= expr likeop expr */
+ 175, /* (184) expr ::= expr likeop expr ESCAPE expr */
+ 175, /* (185) expr ::= expr ISNULL|NOTNULL */
+ 175, /* (186) expr ::= expr NOT NULL */
+ 175, /* (187) expr ::= expr IS expr */
+ 175, /* (188) expr ::= expr IS NOT expr */
+ 175, /* (189) expr ::= NOT expr */
+ 175, /* (190) expr ::= BITNOT expr */
+ 175, /* (191) expr ::= PLUS|MINUS expr */
+ 227, /* (192) between_op ::= BETWEEN */
+ 227, /* (193) between_op ::= NOT BETWEEN */
+ 175, /* (194) expr ::= expr between_op expr AND expr */
+ 228, /* (195) in_op ::= IN */
+ 228, /* (196) in_op ::= NOT IN */
+ 175, /* (197) expr ::= expr in_op LP exprlist RP */
+ 175, /* (198) expr ::= LP select RP */
+ 175, /* (199) expr ::= expr in_op LP select RP */
+ 175, /* (200) expr ::= expr in_op nm dbnm paren_exprlist */
+ 175, /* (201) expr ::= EXISTS LP select RP */
+ 175, /* (202) expr ::= CASE case_operand case_exprlist case_else END */
+ 231, /* (203) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ 231, /* (204) case_exprlist ::= WHEN expr THEN expr */
+ 232, /* (205) case_else ::= ELSE expr */
+ 232, /* (206) case_else ::= */
+ 230, /* (207) case_operand ::= expr */
+ 230, /* (208) case_operand ::= */
+ 218, /* (209) exprlist ::= */
+ 209, /* (210) nexprlist ::= nexprlist COMMA expr */
+ 209, /* (211) nexprlist ::= expr */
+ 229, /* (212) paren_exprlist ::= */
+ 229, /* (213) paren_exprlist ::= LP exprlist RP */
+ 150, /* (214) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ 233, /* (215) uniqueflag ::= UNIQUE */
+ 233, /* (216) uniqueflag ::= */
+ 179, /* (217) eidlist_opt ::= */
+ 179, /* (218) eidlist_opt ::= LP eidlist RP */
+ 189, /* (219) eidlist ::= eidlist COMMA nm collate sortorder */
+ 189, /* (220) eidlist ::= nm collate sortorder */
+ 234, /* (221) collate ::= */
+ 234, /* (222) collate ::= COLLATE ID|STRING */
+ 150, /* (223) cmd ::= DROP INDEX ifexists fullname */
+ 150, /* (224) cmd ::= VACUUM vinto */
+ 150, /* (225) cmd ::= VACUUM nm vinto */
+ 235, /* (226) vinto ::= INTO expr */
+ 235, /* (227) vinto ::= */
+ 150, /* (228) cmd ::= PRAGMA nm dbnm */
+ 150, /* (229) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ 150, /* (230) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ 150, /* (231) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ 150, /* (232) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ 170, /* (233) plus_num ::= PLUS INTEGER|FLOAT */
+ 171, /* (234) minus_num ::= MINUS INTEGER|FLOAT */
+ 150, /* (235) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ 237, /* (236) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ 239, /* (237) trigger_time ::= BEFORE|AFTER */
+ 239, /* (238) trigger_time ::= INSTEAD OF */
+ 239, /* (239) trigger_time ::= */
+ 240, /* (240) trigger_event ::= DELETE|INSERT */
+ 240, /* (241) trigger_event ::= UPDATE */
+ 240, /* (242) trigger_event ::= UPDATE OF idlist */
+ 242, /* (243) when_clause ::= */
+ 242, /* (244) when_clause ::= WHEN expr */
+ 238, /* (245) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ 238, /* (246) trigger_cmd_list ::= trigger_cmd SEMI */
+ 244, /* (247) trnm ::= nm DOT nm */
+ 245, /* (248) tridxby ::= INDEXED BY nm */
+ 245, /* (249) tridxby ::= NOT INDEXED */
+ 243, /* (250) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+ 243, /* (251) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ 243, /* (252) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ 243, /* (253) trigger_cmd ::= scanpt select scanpt */
+ 175, /* (254) expr ::= RAISE LP IGNORE RP */
+ 175, /* (255) expr ::= RAISE LP raisetype COMMA nm RP */
+ 193, /* (256) raisetype ::= ROLLBACK */
+ 193, /* (257) raisetype ::= ABORT */
+ 193, /* (258) raisetype ::= FAIL */
+ 150, /* (259) cmd ::= DROP TRIGGER ifexists fullname */
+ 150, /* (260) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ 150, /* (261) cmd ::= DETACH database_kw_opt expr */
+ 247, /* (262) key_opt ::= */
+ 247, /* (263) key_opt ::= KEY expr */
+ 150, /* (264) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ 150, /* (265) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ 248, /* (266) add_column_fullname ::= fullname */
+ 150, /* (267) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ 150, /* (268) cmd ::= create_vtab */
+ 150, /* (269) cmd ::= create_vtab LP vtabarglist RP */
+ 250, /* (270) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 252, /* (271) vtabarg ::= */
+ 253, /* (272) vtabargtoken ::= ANY */
+ 253, /* (273) vtabargtoken ::= lp anylist RP */
+ 254, /* (274) lp ::= LP */
+ 221, /* (275) with ::= WITH wqlist */
+ 221, /* (276) with ::= WITH RECURSIVE wqlist */
+ 198, /* (277) wqlist ::= nm eidlist_opt AS LP select RP */
+ 198, /* (278) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ 146, /* (279) input ::= cmdlist */
+ 147, /* (280) cmdlist ::= cmdlist ecmd */
+ 147, /* (281) cmdlist ::= ecmd */
+ 148, /* (282) ecmd ::= SEMI */
+ 148, /* (283) ecmd ::= cmdx SEMI */
+ 152, /* (284) trans_opt ::= */
+ 152, /* (285) trans_opt ::= TRANSACTION */
+ 152, /* (286) trans_opt ::= TRANSACTION nm */
+ 154, /* (287) savepoint_opt ::= SAVEPOINT */
+ 154, /* (288) savepoint_opt ::= */
+ 150, /* (289) cmd ::= create_table create_table_args */
+ 161, /* (290) columnlist ::= columnlist COMMA columnname carglist */
+ 161, /* (291) columnlist ::= columnname carglist */
+ 153, /* (292) nm ::= ID|INDEXED */
+ 153, /* (293) nm ::= STRING */
+ 153, /* (294) nm ::= JOIN_KW */
+ 167, /* (295) typetoken ::= typename */
+ 168, /* (296) typename ::= ID|STRING */
+ 169, /* (297) signed ::= plus_num */
+ 169, /* (298) signed ::= minus_num */
+ 166, /* (299) carglist ::= carglist ccons */
+ 166, /* (300) carglist ::= */
+ 173, /* (301) ccons ::= NULL onconf */
+ 162, /* (302) conslist_opt ::= COMMA conslist */
+ 185, /* (303) conslist ::= conslist tconscomma tcons */
+ 185, /* (304) conslist ::= tcons */
+ 186, /* (305) tconscomma ::= */
+ 190, /* (306) defer_subclause_opt ::= defer_subclause */
+ 192, /* (307) resolvetype ::= raisetype */
+ 196, /* (308) selectnowith ::= oneselect */
+ 197, /* (309) oneselect ::= values */
+ 210, /* (310) sclp ::= selcollist COMMA */
+ 211, /* (311) as ::= ID|STRING */
+ 175, /* (312) expr ::= term */
+ 226, /* (313) likeop ::= LIKE_KW|MATCH */
+ 218, /* (314) exprlist ::= nexprlist */
+ 236, /* (315) nmnum ::= plus_num */
+ 236, /* (316) nmnum ::= nm */
+ 236, /* (317) nmnum ::= ON */
+ 236, /* (318) nmnum ::= DELETE */
+ 236, /* (319) nmnum ::= DEFAULT */
+ 170, /* (320) plus_num ::= INTEGER|FLOAT */
+ 241, /* (321) foreach_clause ::= */
+ 241, /* (322) foreach_clause ::= FOR EACH ROW */
+ 244, /* (323) trnm ::= nm */
+ 245, /* (324) tridxby ::= */
+ 246, /* (325) database_kw_opt ::= DATABASE */
+ 246, /* (326) database_kw_opt ::= */
+ 249, /* (327) kwcolumn_opt ::= */
+ 249, /* (328) kwcolumn_opt ::= COLUMNKW */
+ 251, /* (329) vtabarglist ::= vtabarg */
+ 251, /* (330) vtabarglist ::= vtabarglist COMMA vtabarg */
+ 252, /* (331) vtabarg ::= vtabarg vtabargtoken */
+ 255, /* (332) anylist ::= */
+ 255, /* (333) anylist ::= anylist LP anylist RP */
+ 255, /* (334) anylist ::= anylist ANY */
+ 221, /* (335) with ::= */
+};
+
+/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
+** of symbols on the right-hand side of that rule. */
+static const signed char yyRuleInfoNRhs[] = {
+ -1, /* (0) cmdx ::= cmd */
+ -3, /* (1) cmd ::= BEGIN transtype trans_opt */
+ 0, /* (2) transtype ::= */
+ -1, /* (3) transtype ::= DEFERRED */
+ -1, /* (4) transtype ::= IMMEDIATE */
+ -1, /* (5) transtype ::= EXCLUSIVE */
+ -2, /* (6) cmd ::= COMMIT|END trans_opt */
+ -2, /* (7) cmd ::= ROLLBACK trans_opt */
+ -2, /* (8) cmd ::= SAVEPOINT nm */
+ -3, /* (9) cmd ::= RELEASE savepoint_opt nm */
+ -5, /* (10) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+ -6, /* (11) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+ -1, /* (12) createkw ::= CREATE */
+ 0, /* (13) ifnotexists ::= */
+ -3, /* (14) ifnotexists ::= IF NOT EXISTS */
+ -1, /* (15) temp ::= TEMP */
+ 0, /* (16) temp ::= */
+ -5, /* (17) create_table_args ::= LP columnlist conslist_opt RP table_options */
+ -2, /* (18) create_table_args ::= AS select */
+ 0, /* (19) table_options ::= */
+ -2, /* (20) table_options ::= WITHOUT nm */
+ -2, /* (21) columnname ::= nm typetoken */
+ 0, /* (22) typetoken ::= */
+ -4, /* (23) typetoken ::= typename LP signed RP */
+ -6, /* (24) typetoken ::= typename LP signed COMMA signed RP */
+ -2, /* (25) typename ::= typename ID|STRING */
+ 0, /* (26) scanpt ::= */
+ -2, /* (27) ccons ::= CONSTRAINT nm */
+ -4, /* (28) ccons ::= DEFAULT scanpt term scanpt */
+ -4, /* (29) ccons ::= DEFAULT LP expr RP */
+ -4, /* (30) ccons ::= DEFAULT PLUS term scanpt */
+ -4, /* (31) ccons ::= DEFAULT MINUS term scanpt */
+ -3, /* (32) ccons ::= DEFAULT scanpt ID|INDEXED */
+ -3, /* (33) ccons ::= NOT NULL onconf */
+ -5, /* (34) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ -2, /* (35) ccons ::= UNIQUE onconf */
+ -4, /* (36) ccons ::= CHECK LP expr RP */
+ -4, /* (37) ccons ::= REFERENCES nm eidlist_opt refargs */
+ -1, /* (38) ccons ::= defer_subclause */
+ -2, /* (39) ccons ::= COLLATE ID|STRING */
+ 0, /* (40) autoinc ::= */
+ -1, /* (41) autoinc ::= AUTOINCR */
+ 0, /* (42) refargs ::= */
+ -2, /* (43) refargs ::= refargs refarg */
+ -2, /* (44) refarg ::= MATCH nm */
+ -3, /* (45) refarg ::= ON INSERT refact */
+ -3, /* (46) refarg ::= ON DELETE refact */
+ -3, /* (47) refarg ::= ON UPDATE refact */
+ -2, /* (48) refact ::= SET NULL */
+ -2, /* (49) refact ::= SET DEFAULT */
+ -1, /* (50) refact ::= CASCADE */
+ -1, /* (51) refact ::= RESTRICT */
+ -2, /* (52) refact ::= NO ACTION */
+ -3, /* (53) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ -2, /* (54) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ 0, /* (55) init_deferred_pred_opt ::= */
+ -2, /* (56) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ -2, /* (57) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ 0, /* (58) conslist_opt ::= */
+ -1, /* (59) tconscomma ::= COMMA */
+ -2, /* (60) tcons ::= CONSTRAINT nm */
+ -7, /* (61) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ -5, /* (62) tcons ::= UNIQUE LP sortlist RP onconf */
+ -5, /* (63) tcons ::= CHECK LP expr RP onconf */
+ -10, /* (64) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ 0, /* (65) defer_subclause_opt ::= */
+ 0, /* (66) onconf ::= */
+ -3, /* (67) onconf ::= ON CONFLICT resolvetype */
+ 0, /* (68) orconf ::= */
+ -2, /* (69) orconf ::= OR resolvetype */
+ -1, /* (70) resolvetype ::= IGNORE */
+ -1, /* (71) resolvetype ::= REPLACE */
+ -4, /* (72) cmd ::= DROP TABLE ifexists fullname */
+ -2, /* (73) ifexists ::= IF EXISTS */
+ 0, /* (74) ifexists ::= */
+ -9, /* (75) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ -4, /* (76) cmd ::= DROP VIEW ifexists fullname */
+ -1, /* (77) cmd ::= select */
+ -3, /* (78) select ::= WITH wqlist selectnowith */
+ -4, /* (79) select ::= WITH RECURSIVE wqlist selectnowith */
+ -1, /* (80) select ::= selectnowith */
+ -3, /* (81) selectnowith ::= selectnowith multiselect_op oneselect */
+ -1, /* (82) multiselect_op ::= UNION */
+ -2, /* (83) multiselect_op ::= UNION ALL */
+ -1, /* (84) multiselect_op ::= EXCEPT|INTERSECT */
+ -9, /* (85) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ -4, /* (86) values ::= VALUES LP nexprlist RP */
+ -5, /* (87) values ::= values COMMA LP nexprlist RP */
+ -1, /* (88) distinct ::= DISTINCT */
+ -1, /* (89) distinct ::= ALL */
+ 0, /* (90) distinct ::= */
+ 0, /* (91) sclp ::= */
+ -5, /* (92) selcollist ::= sclp scanpt expr scanpt as */
+ -3, /* (93) selcollist ::= sclp scanpt STAR */
+ -5, /* (94) selcollist ::= sclp scanpt nm DOT STAR */
+ -2, /* (95) as ::= AS nm */
+ 0, /* (96) as ::= */
+ 0, /* (97) from ::= */
+ -2, /* (98) from ::= FROM seltablist */
+ -2, /* (99) stl_prefix ::= seltablist joinop */
+ 0, /* (100) stl_prefix ::= */
+ -7, /* (101) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ -9, /* (102) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ -7, /* (103) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ -7, /* (104) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ 0, /* (105) dbnm ::= */
+ -2, /* (106) dbnm ::= DOT nm */
+ -1, /* (107) fullname ::= nm */
+ -3, /* (108) fullname ::= nm DOT nm */
+ -1, /* (109) xfullname ::= nm */
+ -3, /* (110) xfullname ::= nm DOT nm */
+ -5, /* (111) xfullname ::= nm DOT nm AS nm */
+ -3, /* (112) xfullname ::= nm AS nm */
+ -1, /* (113) joinop ::= COMMA|JOIN */
+ -2, /* (114) joinop ::= JOIN_KW JOIN */
+ -3, /* (115) joinop ::= JOIN_KW nm JOIN */
+ -4, /* (116) joinop ::= JOIN_KW nm nm JOIN */
+ -2, /* (117) on_opt ::= ON expr */
+ 0, /* (118) on_opt ::= */
+ 0, /* (119) indexed_opt ::= */
+ -3, /* (120) indexed_opt ::= INDEXED BY nm */
+ -2, /* (121) indexed_opt ::= NOT INDEXED */
+ -4, /* (122) using_opt ::= USING LP idlist RP */
+ 0, /* (123) using_opt ::= */
+ 0, /* (124) orderby_opt ::= */
+ -3, /* (125) orderby_opt ::= ORDER BY sortlist */
+ -4, /* (126) sortlist ::= sortlist COMMA expr sortorder */
+ -2, /* (127) sortlist ::= expr sortorder */
+ -1, /* (128) sortorder ::= ASC */
+ -1, /* (129) sortorder ::= DESC */
+ 0, /* (130) sortorder ::= */
+ 0, /* (131) groupby_opt ::= */
+ -3, /* (132) groupby_opt ::= GROUP BY nexprlist */
+ 0, /* (133) having_opt ::= */
+ -2, /* (134) having_opt ::= HAVING expr */
+ 0, /* (135) limit_opt ::= */
+ -2, /* (136) limit_opt ::= LIMIT expr */
+ -4, /* (137) limit_opt ::= LIMIT expr OFFSET expr */
+ -4, /* (138) limit_opt ::= LIMIT expr COMMA expr */
+ -6, /* (139) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ 0, /* (140) where_opt ::= */
+ -2, /* (141) where_opt ::= WHERE expr */
+ -8, /* (142) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
+ -5, /* (143) setlist ::= setlist COMMA nm EQ expr */
+ -7, /* (144) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ -3, /* (145) setlist ::= nm EQ expr */
+ -5, /* (146) setlist ::= LP idlist RP EQ expr */
+ -7, /* (147) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ -7, /* (148) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ 0, /* (149) upsert ::= */
+ -11, /* (150) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
+ -8, /* (151) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
+ -4, /* (152) upsert ::= ON CONFLICT DO NOTHING */
+ -2, /* (153) insert_cmd ::= INSERT orconf */
+ -1, /* (154) insert_cmd ::= REPLACE */
+ 0, /* (155) idlist_opt ::= */
+ -3, /* (156) idlist_opt ::= LP idlist RP */
+ -3, /* (157) idlist ::= idlist COMMA nm */
+ -1, /* (158) idlist ::= nm */
+ -3, /* (159) expr ::= LP expr RP */
+ -1, /* (160) expr ::= ID|INDEXED */
+ -1, /* (161) expr ::= JOIN_KW */
+ -3, /* (162) expr ::= nm DOT nm */
+ -5, /* (163) expr ::= nm DOT nm DOT nm */
+ -1, /* (164) term ::= NULL|FLOAT|BLOB */
+ -1, /* (165) term ::= STRING */
+ -1, /* (166) term ::= INTEGER */
+ -1, /* (167) expr ::= VARIABLE */
+ -3, /* (168) expr ::= expr COLLATE ID|STRING */
+ -6, /* (169) expr ::= CAST LP expr AS typetoken RP */
+ -5, /* (170) expr ::= ID|INDEXED LP distinct exprlist RP */
+ -4, /* (171) expr ::= ID|INDEXED LP STAR RP */
+ -1, /* (172) term ::= CTIME_KW */
+ -5, /* (173) expr ::= LP nexprlist COMMA expr RP */
+ -3, /* (174) expr ::= expr AND expr */
+ -3, /* (175) expr ::= expr OR expr */
+ -3, /* (176) expr ::= expr LT|GT|GE|LE expr */
+ -3, /* (177) expr ::= expr EQ|NE expr */
+ -3, /* (178) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ -3, /* (179) expr ::= expr PLUS|MINUS expr */
+ -3, /* (180) expr ::= expr STAR|SLASH|REM expr */
+ -3, /* (181) expr ::= expr CONCAT expr */
+ -2, /* (182) likeop ::= NOT LIKE_KW|MATCH */
+ -3, /* (183) expr ::= expr likeop expr */
+ -5, /* (184) expr ::= expr likeop expr ESCAPE expr */
+ -2, /* (185) expr ::= expr ISNULL|NOTNULL */
+ -3, /* (186) expr ::= expr NOT NULL */
+ -3, /* (187) expr ::= expr IS expr */
+ -4, /* (188) expr ::= expr IS NOT expr */
+ -2, /* (189) expr ::= NOT expr */
+ -2, /* (190) expr ::= BITNOT expr */
+ -2, /* (191) expr ::= PLUS|MINUS expr */
+ -1, /* (192) between_op ::= BETWEEN */
+ -2, /* (193) between_op ::= NOT BETWEEN */
+ -5, /* (194) expr ::= expr between_op expr AND expr */
+ -1, /* (195) in_op ::= IN */
+ -2, /* (196) in_op ::= NOT IN */
+ -5, /* (197) expr ::= expr in_op LP exprlist RP */
+ -3, /* (198) expr ::= LP select RP */
+ -5, /* (199) expr ::= expr in_op LP select RP */
+ -5, /* (200) expr ::= expr in_op nm dbnm paren_exprlist */
+ -4, /* (201) expr ::= EXISTS LP select RP */
+ -5, /* (202) expr ::= CASE case_operand case_exprlist case_else END */
+ -5, /* (203) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ -4, /* (204) case_exprlist ::= WHEN expr THEN expr */
+ -2, /* (205) case_else ::= ELSE expr */
+ 0, /* (206) case_else ::= */
+ -1, /* (207) case_operand ::= expr */
+ 0, /* (208) case_operand ::= */
+ 0, /* (209) exprlist ::= */
+ -3, /* (210) nexprlist ::= nexprlist COMMA expr */
+ -1, /* (211) nexprlist ::= expr */
+ 0, /* (212) paren_exprlist ::= */
+ -3, /* (213) paren_exprlist ::= LP exprlist RP */
+ -12, /* (214) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ -1, /* (215) uniqueflag ::= UNIQUE */
+ 0, /* (216) uniqueflag ::= */
+ 0, /* (217) eidlist_opt ::= */
+ -3, /* (218) eidlist_opt ::= LP eidlist RP */
+ -5, /* (219) eidlist ::= eidlist COMMA nm collate sortorder */
+ -3, /* (220) eidlist ::= nm collate sortorder */
+ 0, /* (221) collate ::= */
+ -2, /* (222) collate ::= COLLATE ID|STRING */
+ -4, /* (223) cmd ::= DROP INDEX ifexists fullname */
+ -2, /* (224) cmd ::= VACUUM vinto */
+ -3, /* (225) cmd ::= VACUUM nm vinto */
+ -2, /* (226) vinto ::= INTO expr */
+ 0, /* (227) vinto ::= */
+ -3, /* (228) cmd ::= PRAGMA nm dbnm */
+ -5, /* (229) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ -6, /* (230) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ -5, /* (231) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ -6, /* (232) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ -2, /* (233) plus_num ::= PLUS INTEGER|FLOAT */
+ -2, /* (234) minus_num ::= MINUS INTEGER|FLOAT */
+ -5, /* (235) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ -11, /* (236) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ -1, /* (237) trigger_time ::= BEFORE|AFTER */
+ -2, /* (238) trigger_time ::= INSTEAD OF */
+ 0, /* (239) trigger_time ::= */
+ -1, /* (240) trigger_event ::= DELETE|INSERT */
+ -1, /* (241) trigger_event ::= UPDATE */
+ -3, /* (242) trigger_event ::= UPDATE OF idlist */
+ 0, /* (243) when_clause ::= */
+ -2, /* (244) when_clause ::= WHEN expr */
+ -3, /* (245) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ -2, /* (246) trigger_cmd_list ::= trigger_cmd SEMI */
+ -3, /* (247) trnm ::= nm DOT nm */
+ -3, /* (248) tridxby ::= INDEXED BY nm */
+ -2, /* (249) tridxby ::= NOT INDEXED */
+ -8, /* (250) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+ -8, /* (251) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ -6, /* (252) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ -3, /* (253) trigger_cmd ::= scanpt select scanpt */
+ -4, /* (254) expr ::= RAISE LP IGNORE RP */
+ -6, /* (255) expr ::= RAISE LP raisetype COMMA nm RP */
+ -1, /* (256) raisetype ::= ROLLBACK */
+ -1, /* (257) raisetype ::= ABORT */
+ -1, /* (258) raisetype ::= FAIL */
+ -4, /* (259) cmd ::= DROP TRIGGER ifexists fullname */
+ -6, /* (260) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ -3, /* (261) cmd ::= DETACH database_kw_opt expr */
+ 0, /* (262) key_opt ::= */
+ -2, /* (263) key_opt ::= KEY expr */
+ -6, /* (264) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ -7, /* (265) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ -1, /* (266) add_column_fullname ::= fullname */
+ -8, /* (267) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ -1, /* (268) cmd ::= create_vtab */
+ -4, /* (269) cmd ::= create_vtab LP vtabarglist RP */
+ -8, /* (270) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 0, /* (271) vtabarg ::= */
+ -1, /* (272) vtabargtoken ::= ANY */
+ -3, /* (273) vtabargtoken ::= lp anylist RP */
+ -1, /* (274) lp ::= LP */
+ -2, /* (275) with ::= WITH wqlist */
+ -3, /* (276) with ::= WITH RECURSIVE wqlist */
+ -6, /* (277) wqlist ::= nm eidlist_opt AS LP select RP */
+ -8, /* (278) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ -1, /* (279) input ::= cmdlist */
+ -2, /* (280) cmdlist ::= cmdlist ecmd */
+ -1, /* (281) cmdlist ::= ecmd */
+ -1, /* (282) ecmd ::= SEMI */
+ -2, /* (283) ecmd ::= cmdx SEMI */
+ 0, /* (284) trans_opt ::= */
+ -1, /* (285) trans_opt ::= TRANSACTION */
+ -2, /* (286) trans_opt ::= TRANSACTION nm */
+ -1, /* (287) savepoint_opt ::= SAVEPOINT */
+ 0, /* (288) savepoint_opt ::= */
+ -2, /* (289) cmd ::= create_table create_table_args */
+ -4, /* (290) columnlist ::= columnlist COMMA columnname carglist */
+ -2, /* (291) columnlist ::= columnname carglist */
+ -1, /* (292) nm ::= ID|INDEXED */
+ -1, /* (293) nm ::= STRING */
+ -1, /* (294) nm ::= JOIN_KW */
+ -1, /* (295) typetoken ::= typename */
+ -1, /* (296) typename ::= ID|STRING */
+ -1, /* (297) signed ::= plus_num */
+ -1, /* (298) signed ::= minus_num */
+ -2, /* (299) carglist ::= carglist ccons */
+ 0, /* (300) carglist ::= */
+ -2, /* (301) ccons ::= NULL onconf */
+ -2, /* (302) conslist_opt ::= COMMA conslist */
+ -3, /* (303) conslist ::= conslist tconscomma tcons */
+ -1, /* (304) conslist ::= tcons */
+ 0, /* (305) tconscomma ::= */
+ -1, /* (306) defer_subclause_opt ::= defer_subclause */
+ -1, /* (307) resolvetype ::= raisetype */
+ -1, /* (308) selectnowith ::= oneselect */
+ -1, /* (309) oneselect ::= values */
+ -2, /* (310) sclp ::= selcollist COMMA */
+ -1, /* (311) as ::= ID|STRING */
+ -1, /* (312) expr ::= term */
+ -1, /* (313) likeop ::= LIKE_KW|MATCH */
+ -1, /* (314) exprlist ::= nexprlist */
+ -1, /* (315) nmnum ::= plus_num */
+ -1, /* (316) nmnum ::= nm */
+ -1, /* (317) nmnum ::= ON */
+ -1, /* (318) nmnum ::= DELETE */
+ -1, /* (319) nmnum ::= DEFAULT */
+ -1, /* (320) plus_num ::= INTEGER|FLOAT */
+ 0, /* (321) foreach_clause ::= */
+ -3, /* (322) foreach_clause ::= FOR EACH ROW */
+ -1, /* (323) trnm ::= nm */
+ 0, /* (324) tridxby ::= */
+ -1, /* (325) database_kw_opt ::= DATABASE */
+ 0, /* (326) database_kw_opt ::= */
+ 0, /* (327) kwcolumn_opt ::= */
+ -1, /* (328) kwcolumn_opt ::= COLUMNKW */
+ -1, /* (329) vtabarglist ::= vtabarg */
+ -3, /* (330) vtabarglist ::= vtabarglist COMMA vtabarg */
+ -2, /* (331) vtabarg ::= vtabarg vtabargtoken */
+ 0, /* (332) anylist ::= */
+ -4, /* (333) anylist ::= anylist LP anylist RP */
+ -2, /* (334) anylist ::= anylist ANY */
+ 0, /* (335) with ::= */
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -149428,7 +150226,7 @@ static YYACTIONTYPE yy_reduce(
yymsp = yypParser->yytos;
#ifndef NDEBUG
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
- yysize = yyRuleInfo[yyruleno].nrhs;
+ yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
yyTracePrompt,
@@ -149443,7 +150241,7 @@ static YYACTIONTYPE yy_reduce(
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
- if( yyRuleInfo[yyruleno].nrhs==0 ){
+ if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
@@ -149487,15 +150285,15 @@ static YYACTIONTYPE yy_reduce(
{ sqlite3FinishCoding(pParse); }
break;
case 1: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy348);}
break;
case 2: /* transtype ::= */
-{yymsp[1].minor.yy502 = TK_DEFERRED;}
+{yymsp[1].minor.yy348 = TK_DEFERRED;}
break;
case 3: /* transtype ::= DEFERRED */
case 4: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==4);
case 5: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==5);
-{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/}
+{yymsp[0].minor.yy348 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 6: /* cmd ::= COMMIT|END trans_opt */
case 7: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==7);
@@ -149518,7 +150316,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 11: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy348,0,0,yymsp[-2].minor.yy348);
}
break;
case 12: /* createkw ::= CREATE */
@@ -149533,32 +150331,32 @@ static YYACTIONTYPE yy_reduce(
case 74: /* ifexists ::= */ yytestcase(yyruleno==74);
case 90: /* distinct ::= */ yytestcase(yyruleno==90);
case 221: /* collate ::= */ yytestcase(yyruleno==221);
-{yymsp[1].minor.yy502 = 0;}
+{yymsp[1].minor.yy348 = 0;}
break;
case 14: /* ifnotexists ::= IF NOT EXISTS */
-{yymsp[-2].minor.yy502 = 1;}
+{yymsp[-2].minor.yy348 = 1;}
break;
case 15: /* temp ::= TEMP */
case 41: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==41);
-{yymsp[0].minor.yy502 = 1;}
+{yymsp[0].minor.yy348 = 1;}
break;
case 17: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
{
- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy502,0);
+ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy348,0);
}
break;
case 18: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy399);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy399);
+ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy43);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43);
}
break;
case 20: /* table_options ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
- yymsp[-1].minor.yy502 = TF_WithoutRowid | TF_NoVisibleRowid;
+ yymsp[-1].minor.yy348 = TF_WithoutRowid | TF_NoVisibleRowid;
}else{
- yymsp[-1].minor.yy502 = 0;
+ yymsp[-1].minor.yy348 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
@@ -149587,7 +150385,7 @@ static YYACTIONTYPE yy_reduce(
case 26: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
- yymsp[1].minor.yy36 = yyLookaheadToken.z;
+ yymsp[1].minor.yy360 = yyLookaheadToken.z;
}
break;
case 27: /* ccons ::= CONSTRAINT nm */
@@ -149595,18 +150393,18 @@ static YYACTIONTYPE yy_reduce(
{pParse->constraintName = yymsp[0].minor.yy0;}
break;
case 28: /* ccons ::= DEFAULT scanpt term scanpt */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy36,yymsp[0].minor.yy36);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy2,yymsp[-2].minor.yy360,yymsp[0].minor.yy360);}
break;
case 29: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy2,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
break;
case 30: /* ccons ::= DEFAULT PLUS term scanpt */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy36);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy2,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy360);}
break;
case 31: /* ccons ::= DEFAULT MINUS term scanpt */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy182, 0);
- sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy36);
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy2, 0);
+ sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy360);
}
break;
case 32: /* ccons ::= DEFAULT scanpt ID|INDEXED */
@@ -149620,170 +150418,170 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 33: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy348);}
break;
case 34: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy348,yymsp[0].minor.yy348,yymsp[-2].minor.yy348);}
break;
case 35: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy348,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 36: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy182);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy2);}
break;
case 37: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy232,yymsp[0].minor.yy502);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy402,yymsp[0].minor.yy348);}
break;
case 38: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy348);}
break;
case 39: /* ccons ::= COLLATE ID|STRING */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 42: /* refargs ::= */
-{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */}
+{ yymsp[1].minor.yy348 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
case 43: /* refargs ::= refargs refarg */
-{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy107.mask) | yymsp[0].minor.yy107.value; }
+{ yymsp[-1].minor.yy348 = (yymsp[-1].minor.yy348 & ~yymsp[0].minor.yy239.mask) | yymsp[0].minor.yy239.value; }
break;
case 44: /* refarg ::= MATCH nm */
-{ yymsp[-1].minor.yy107.value = 0; yymsp[-1].minor.yy107.mask = 0x000000; }
+{ yymsp[-1].minor.yy239.value = 0; yymsp[-1].minor.yy239.mask = 0x000000; }
break;
case 45: /* refarg ::= ON INSERT refact */
-{ yymsp[-2].minor.yy107.value = 0; yymsp[-2].minor.yy107.mask = 0x000000; }
+{ yymsp[-2].minor.yy239.value = 0; yymsp[-2].minor.yy239.mask = 0x000000; }
break;
case 46: /* refarg ::= ON DELETE refact */
-{ yymsp[-2].minor.yy107.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy107.mask = 0x0000ff; }
+{ yymsp[-2].minor.yy239.value = yymsp[0].minor.yy348; yymsp[-2].minor.yy239.mask = 0x0000ff; }
break;
case 47: /* refarg ::= ON UPDATE refact */
-{ yymsp[-2].minor.yy107.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy107.mask = 0x00ff00; }
+{ yymsp[-2].minor.yy239.value = yymsp[0].minor.yy348<<8; yymsp[-2].minor.yy239.mask = 0x00ff00; }
break;
case 48: /* refact ::= SET NULL */
-{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy348 = OE_SetNull; /* EV: R-33326-45252 */}
break;
case 49: /* refact ::= SET DEFAULT */
-{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy348 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
case 50: /* refact ::= CASCADE */
-{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy348 = OE_Cascade; /* EV: R-33326-45252 */}
break;
case 51: /* refact ::= RESTRICT */
-{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy348 = OE_Restrict; /* EV: R-33326-45252 */}
break;
case 52: /* refact ::= NO ACTION */
-{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy348 = OE_None; /* EV: R-33326-45252 */}
break;
case 53: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-{yymsp[-2].minor.yy502 = 0;}
+{yymsp[-2].minor.yy348 = 0;}
break;
case 54: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 69: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==69);
case 153: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==153);
-{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;}
+{yymsp[-1].minor.yy348 = yymsp[0].minor.yy348;}
break;
case 56: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 73: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==73);
case 193: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==193);
case 196: /* in_op ::= NOT IN */ yytestcase(yyruleno==196);
case 222: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==222);
-{yymsp[-1].minor.yy502 = 1;}
+{yymsp[-1].minor.yy348 = 1;}
break;
case 57: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-{yymsp[-1].minor.yy502 = 0;}
+{yymsp[-1].minor.yy348 = 0;}
break;
case 59: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
break;
case 61: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy232,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy402,yymsp[0].minor.yy348,yymsp[-2].minor.yy348,0);}
break;
case 62: /* tcons ::= UNIQUE LP sortlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy232,yymsp[0].minor.yy502,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy402,yymsp[0].minor.yy348,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 63: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy182);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy2);}
break;
case 64: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy232, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy232, yymsp[-1].minor.yy502);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy402, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[-1].minor.yy348);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy348);
}
break;
case 66: /* onconf ::= */
case 68: /* orconf ::= */ yytestcase(yyruleno==68);
-{yymsp[1].minor.yy502 = OE_Default;}
+{yymsp[1].minor.yy348 = OE_Default;}
break;
case 67: /* onconf ::= ON CONFLICT resolvetype */
-{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;}
+{yymsp[-2].minor.yy348 = yymsp[0].minor.yy348;}
break;
case 70: /* resolvetype ::= IGNORE */
-{yymsp[0].minor.yy502 = OE_Ignore;}
+{yymsp[0].minor.yy348 = OE_Ignore;}
break;
case 71: /* resolvetype ::= REPLACE */
case 154: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==154);
-{yymsp[0].minor.yy502 = OE_Replace;}
+{yymsp[0].minor.yy348 = OE_Replace;}
break;
case 72: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy427, 0, yymsp[-1].minor.yy502);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy3, 0, yymsp[-1].minor.yy348);
}
break;
case 75: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{
- sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy232, yymsp[0].minor.yy399, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502);
+ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy402, yymsp[0].minor.yy43, yymsp[-7].minor.yy348, yymsp[-5].minor.yy348);
}
break;
case 76: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy427, 1, yymsp[-1].minor.yy502);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy3, 1, yymsp[-1].minor.yy348);
}
break;
case 77: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy399, &dest);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy399);
+ sqlite3Select(pParse, yymsp[0].minor.yy43, &dest);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43);
}
break;
case 78: /* select ::= WITH wqlist selectnowith */
{
- Select *p = yymsp[0].minor.yy399;
+ Select *p = yymsp[0].minor.yy43;
if( p ){
- p->pWith = yymsp[-1].minor.yy91;
+ p->pWith = yymsp[-1].minor.yy4;
parserDoubleLinkSelect(pParse, p);
}else{
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy91);
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy4);
}
- yymsp[-2].minor.yy399 = p;
+ yymsp[-2].minor.yy43 = p;
}
break;
case 79: /* select ::= WITH RECURSIVE wqlist selectnowith */
{
- Select *p = yymsp[0].minor.yy399;
+ Select *p = yymsp[0].minor.yy43;
if( p ){
- p->pWith = yymsp[-1].minor.yy91;
+ p->pWith = yymsp[-1].minor.yy4;
parserDoubleLinkSelect(pParse, p);
}else{
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy91);
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy4);
}
- yymsp[-3].minor.yy399 = p;
+ yymsp[-3].minor.yy43 = p;
}
break;
case 80: /* select ::= selectnowith */
{
- Select *p = yymsp[0].minor.yy399;
+ Select *p = yymsp[0].minor.yy43;
if( p ){
parserDoubleLinkSelect(pParse, p);
}
- yymsp[0].minor.yy399 = p; /*A-overwrites-X*/
+ yymsp[0].minor.yy43 = p; /*A-overwrites-X*/
}
break;
case 81: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
- Select *pRhs = yymsp[0].minor.yy399;
- Select *pLhs = yymsp[-2].minor.yy399;
+ Select *pRhs = yymsp[0].minor.yy43;
+ Select *pLhs = yymsp[-2].minor.yy43;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
@@ -149793,53 +150591,53 @@ static YYACTIONTYPE yy_reduce(
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
- pRhs->op = (u8)yymsp[-1].minor.yy502;
+ pRhs->op = (u8)yymsp[-1].minor.yy348;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
pRhs->selFlags &= ~SF_MultiValue;
- if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1;
+ if( yymsp[-1].minor.yy348!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
}
- yymsp[-2].minor.yy399 = pRhs;
+ yymsp[-2].minor.yy43 = pRhs;
}
break;
case 82: /* multiselect_op ::= UNION */
case 84: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==84);
-{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/}
+{yymsp[0].minor.yy348 = yymsp[0].major; /*A-overwrites-OP*/}
break;
case 83: /* multiselect_op ::= UNION ALL */
-{yymsp[-1].minor.yy502 = TK_ALL;}
+{yymsp[-1].minor.yy348 = TK_ALL;}
break;
case 85: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yymsp[-8].minor.yy399 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy232,yymsp[-5].minor.yy427,yymsp[-4].minor.yy182,yymsp[-3].minor.yy232,yymsp[-2].minor.yy182,yymsp[-1].minor.yy232,yymsp[-7].minor.yy502,yymsp[0].minor.yy182);
+ yymsp[-8].minor.yy43 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy402,yymsp[-5].minor.yy3,yymsp[-4].minor.yy2,yymsp[-3].minor.yy402,yymsp[-2].minor.yy2,yymsp[-1].minor.yy402,yymsp[-7].minor.yy348,yymsp[0].minor.yy2);
}
break;
case 86: /* values ::= VALUES LP nexprlist RP */
{
- yymsp[-3].minor.yy399 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy232,0,0,0,0,0,SF_Values,0);
+ yymsp[-3].minor.yy43 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy402,0,0,0,0,0,SF_Values,0);
}
break;
case 87: /* values ::= values COMMA LP nexprlist RP */
{
- Select *pRight, *pLeft = yymsp[-4].minor.yy399;
- pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy232,0,0,0,0,0,SF_Values|SF_MultiValue,0);
+ Select *pRight, *pLeft = yymsp[-4].minor.yy43;
+ pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy402,0,0,0,0,0,SF_Values|SF_MultiValue,0);
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){
pRight->op = TK_ALL;
pRight->pPrior = pLeft;
- yymsp[-4].minor.yy399 = pRight;
+ yymsp[-4].minor.yy43 = pRight;
}else{
- yymsp[-4].minor.yy399 = pLeft;
+ yymsp[-4].minor.yy43 = pLeft;
}
}
break;
case 88: /* distinct ::= DISTINCT */
-{yymsp[0].minor.yy502 = SF_Distinct;}
+{yymsp[0].minor.yy348 = SF_Distinct;}
break;
case 89: /* distinct ::= ALL */
-{yymsp[0].minor.yy502 = SF_All;}
+{yymsp[0].minor.yy348 = SF_All;}
break;
case 91: /* sclp ::= */
case 124: /* orderby_opt ::= */ yytestcase(yyruleno==124);
@@ -149847,19 +150645,19 @@ static YYACTIONTYPE yy_reduce(
case 209: /* exprlist ::= */ yytestcase(yyruleno==209);
case 212: /* paren_exprlist ::= */ yytestcase(yyruleno==212);
case 217: /* eidlist_opt ::= */ yytestcase(yyruleno==217);
-{yymsp[1].minor.yy232 = 0;}
+{yymsp[1].minor.yy402 = 0;}
break;
case 92: /* selcollist ::= sclp scanpt expr scanpt as */
{
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy232, yymsp[-2].minor.yy182);
- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy232, &yymsp[0].minor.yy0, 1);
- sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy232,yymsp[-3].minor.yy36,yymsp[-1].minor.yy36);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[-2].minor.yy2);
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[0].minor.yy0, 1);
+ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy402,yymsp[-3].minor.yy360,yymsp[-1].minor.yy360);
}
break;
case 93: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
- yymsp[-2].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy232, p);
+ yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy402, p);
}
break;
case 94: /* selcollist ::= sclp scanpt nm DOT STAR */
@@ -149867,70 +150665,76 @@ static YYACTIONTYPE yy_reduce(
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, pDot);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, pDot);
}
break;
case 95: /* as ::= AS nm */
case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106);
- case 231: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==231);
- case 232: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==232);
+ case 233: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==233);
+ case 234: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==234);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
case 97: /* from ::= */
-{yymsp[1].minor.yy427 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy427));}
+{yymsp[1].minor.yy3 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy3));}
break;
case 98: /* from ::= FROM seltablist */
{
- yymsp[-1].minor.yy427 = yymsp[0].minor.yy427;
- sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy427);
+ yymsp[-1].minor.yy3 = yymsp[0].minor.yy3;
+ sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy3);
}
break;
case 99: /* stl_prefix ::= seltablist joinop */
{
- if( ALWAYS(yymsp[-1].minor.yy427 && yymsp[-1].minor.yy427->nSrc>0) ) yymsp[-1].minor.yy427->a[yymsp[-1].minor.yy427->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502;
+ if( ALWAYS(yymsp[-1].minor.yy3 && yymsp[-1].minor.yy3->nSrc>0) ) yymsp[-1].minor.yy3->a[yymsp[-1].minor.yy3->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy348;
}
break;
case 100: /* stl_prefix ::= */
-{yymsp[1].minor.yy427 = 0;}
+{yymsp[1].minor.yy3 = 0;}
break;
case 101: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
- yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
- sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy427, &yymsp[-2].minor.yy0);
+ yymsp[-6].minor.yy3 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy3,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy2,yymsp[0].minor.yy272);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy3, &yymsp[-2].minor.yy0);
}
break;
case 102: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
{
- yymsp[-8].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy427,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
- sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy427, yymsp[-4].minor.yy232);
+ yymsp[-8].minor.yy3 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy3,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy2,yymsp[0].minor.yy272);
+ sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy3, yymsp[-4].minor.yy402);
}
break;
case 103: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
- yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy399,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
+ yymsp[-6].minor.yy3 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy3,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy43,yymsp[-1].minor.yy2,yymsp[0].minor.yy272);
}
break;
case 104: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
- if( yymsp[-6].minor.yy427==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy182==0 && yymsp[0].minor.yy510==0 ){
- yymsp[-6].minor.yy427 = yymsp[-4].minor.yy427;
- }else if( yymsp[-4].minor.yy427->nSrc==1 ){
- yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
- if( yymsp[-6].minor.yy427 ){
- struct SrcList_item *pNew = &yymsp[-6].minor.yy427->a[yymsp[-6].minor.yy427->nSrc-1];
- struct SrcList_item *pOld = yymsp[-4].minor.yy427->a;
+ if( yymsp[-6].minor.yy3==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy2==0 && yymsp[0].minor.yy272==0 ){
+ yymsp[-6].minor.yy3 = yymsp[-4].minor.yy3;
+ }else if( yymsp[-4].minor.yy3->nSrc==1 ){
+ yymsp[-6].minor.yy3 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy3,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy2,yymsp[0].minor.yy272);
+ if( yymsp[-6].minor.yy3 ){
+ struct SrcList_item *pNew = &yymsp[-6].minor.yy3->a[yymsp[-6].minor.yy3->nSrc-1];
+ struct SrcList_item *pOld = yymsp[-4].minor.yy3->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
+ if( pOld->fg.isTabFunc ){
+ pNew->u1.pFuncArg = pOld->u1.pFuncArg;
+ pOld->u1.pFuncArg = 0;
+ pOld->fg.isTabFunc = 0;
+ pNew->fg.isTabFunc = 1;
+ }
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy427);
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy3);
}else{
Select *pSubquery;
- sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy427);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy427,0,0,0,0,SF_NestedFrom,0);
- yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
+ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy3);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy3,0,0,0,0,SF_NestedFrom,0);
+ yymsp[-6].minor.yy3 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy3,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy2,yymsp[0].minor.yy272);
}
}
break;
@@ -149940,53 +150744,54 @@ static YYACTIONTYPE yy_reduce(
break;
case 107: /* fullname ::= nm */
{
- yylhsminor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0);
- if( IN_RENAME_OBJECT && yylhsminor.yy427 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy427->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy3 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy3 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy3->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[0].minor.yy427 = yylhsminor.yy427;
+ yymsp[0].minor.yy3 = yylhsminor.yy3;
break;
case 108: /* fullname ::= nm DOT nm */
{
- yylhsminor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- if( IN_RENAME_OBJECT && yylhsminor.yy427 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy427->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy3 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy3 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy3->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[-2].minor.yy427 = yylhsminor.yy427;
+ yymsp[-2].minor.yy3 = yylhsminor.yy3;
break;
case 109: /* xfullname ::= nm */
-{yymsp[0].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
+{yymsp[0].minor.yy3 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
break;
case 110: /* xfullname ::= nm DOT nm */
-{yymsp[-2].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{yymsp[-2].minor.yy3 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 111: /* xfullname ::= nm DOT nm AS nm */
{
- yymsp[-4].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
- if( yymsp[-4].minor.yy427 ) yymsp[-4].minor.yy427->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-4].minor.yy3 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
+ if( yymsp[-4].minor.yy3 ) yymsp[-4].minor.yy3->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 112: /* xfullname ::= nm AS nm */
{
- yymsp[-2].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
- if( yymsp[-2].minor.yy427 ) yymsp[-2].minor.yy427->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-2].minor.yy3 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
+ if( yymsp[-2].minor.yy3 ) yymsp[-2].minor.yy3->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
case 113: /* joinop ::= COMMA|JOIN */
-{ yymsp[0].minor.yy502 = JT_INNER; }
+{ yymsp[0].minor.yy348 = JT_INNER; }
break;
case 114: /* joinop ::= JOIN_KW JOIN */
-{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
+{yymsp[-1].minor.yy348 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
case 115: /* joinop ::= JOIN_KW nm JOIN */
-{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
+{yymsp[-2].minor.yy348 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
case 116: /* joinop ::= JOIN_KW nm nm JOIN */
-{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
+{yymsp[-3].minor.yy348 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
case 117: /* on_opt ::= ON expr */
case 134: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==134);
case 141: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==141);
case 205: /* case_else ::= ELSE expr */ yytestcase(yyruleno==205);
-{yymsp[-1].minor.yy182 = yymsp[0].minor.yy182;}
+ case 226: /* vinto ::= INTO expr */ yytestcase(yyruleno==226);
+{yymsp[-1].minor.yy2 = yymsp[0].minor.yy2;}
break;
case 118: /* on_opt ::= */
case 133: /* having_opt ::= */ yytestcase(yyruleno==133);
@@ -149994,7 +150799,8 @@ static YYACTIONTYPE yy_reduce(
case 140: /* where_opt ::= */ yytestcase(yyruleno==140);
case 206: /* case_else ::= */ yytestcase(yyruleno==206);
case 208: /* case_operand ::= */ yytestcase(yyruleno==208);
-{yymsp[1].minor.yy182 = 0;}
+ case 227: /* vinto ::= */ yytestcase(yyruleno==227);
+{yymsp[1].minor.yy2 = 0;}
break;
case 120: /* indexed_opt ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
@@ -150003,119 +150809,119 @@ static YYACTIONTYPE yy_reduce(
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
case 122: /* using_opt ::= USING LP idlist RP */
-{yymsp[-3].minor.yy510 = yymsp[-1].minor.yy510;}
+{yymsp[-3].minor.yy272 = yymsp[-1].minor.yy272;}
break;
case 123: /* using_opt ::= */
case 155: /* idlist_opt ::= */ yytestcase(yyruleno==155);
-{yymsp[1].minor.yy510 = 0;}
+{yymsp[1].minor.yy272 = 0;}
break;
case 125: /* orderby_opt ::= ORDER BY sortlist */
case 132: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==132);
-{yymsp[-2].minor.yy232 = yymsp[0].minor.yy232;}
+{yymsp[-2].minor.yy402 = yymsp[0].minor.yy402;}
break;
case 126: /* sortlist ::= sortlist COMMA expr sortorder */
{
- yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy232,yymsp[-1].minor.yy182);
- sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy232,yymsp[0].minor.yy502);
+ yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy402,yymsp[-1].minor.yy2);
+ sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy402,yymsp[0].minor.yy348);
}
break;
case 127: /* sortlist ::= expr sortorder */
{
- yymsp[-1].minor.yy232 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy182); /*A-overwrites-Y*/
- sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy232,yymsp[0].minor.yy502);
+ yymsp[-1].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy2); /*A-overwrites-Y*/
+ sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy402,yymsp[0].minor.yy348);
}
break;
case 128: /* sortorder ::= ASC */
-{yymsp[0].minor.yy502 = SQLITE_SO_ASC;}
+{yymsp[0].minor.yy348 = SQLITE_SO_ASC;}
break;
case 129: /* sortorder ::= DESC */
-{yymsp[0].minor.yy502 = SQLITE_SO_DESC;}
+{yymsp[0].minor.yy348 = SQLITE_SO_DESC;}
break;
case 130: /* sortorder ::= */
-{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;}
+{yymsp[1].minor.yy348 = SQLITE_SO_UNDEFINED;}
break;
case 136: /* limit_opt ::= LIMIT expr */
-{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy182,0);}
+{yymsp[-1].minor.yy2 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy2,0);}
break;
case 137: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy182,yymsp[0].minor.yy182);}
+{yymsp[-3].minor.yy2 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy2,yymsp[0].minor.yy2);}
break;
case 138: /* limit_opt ::= LIMIT expr COMMA expr */
-{yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy182,yymsp[-2].minor.yy182);}
+{yymsp[-3].minor.yy2 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy2,yymsp[-2].minor.yy2);}
break;
case 139: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy427, &yymsp[-1].minor.yy0);
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy427,yymsp[0].minor.yy182,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy3, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy3,yymsp[0].minor.yy2,0,0);
}
break;
case 142: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy427, &yymsp[-3].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy232,"set list");
- sqlite3Update(pParse,yymsp[-4].minor.yy427,yymsp[-1].minor.yy232,yymsp[0].minor.yy182,yymsp[-5].minor.yy502,0,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy3, &yymsp[-3].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy402,"set list");
+ sqlite3Update(pParse,yymsp[-4].minor.yy3,yymsp[-1].minor.yy402,yymsp[0].minor.yy2,yymsp[-5].minor.yy348,0,0,0);
}
break;
case 143: /* setlist ::= setlist COMMA nm EQ expr */
{
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy232, yymsp[0].minor.yy182);
- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy232, &yymsp[-2].minor.yy0, 1);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy402, yymsp[0].minor.yy2);
+ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, 1);
}
break;
case 144: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
- yymsp[-6].minor.yy232 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy232, yymsp[-3].minor.yy510, yymsp[0].minor.yy182);
+ yymsp[-6].minor.yy402 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy402, yymsp[-3].minor.yy272, yymsp[0].minor.yy2);
}
break;
case 145: /* setlist ::= nm EQ expr */
{
- yylhsminor.yy232 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy182);
- sqlite3ExprListSetName(pParse, yylhsminor.yy232, &yymsp[-2].minor.yy0, 1);
+ yylhsminor.yy402 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy2);
+ sqlite3ExprListSetName(pParse, yylhsminor.yy402, &yymsp[-2].minor.yy0, 1);
}
- yymsp[-2].minor.yy232 = yylhsminor.yy232;
+ yymsp[-2].minor.yy402 = yylhsminor.yy402;
break;
case 146: /* setlist ::= LP idlist RP EQ expr */
{
- yymsp[-4].minor.yy232 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy510, yymsp[0].minor.yy182);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy272, yymsp[0].minor.yy2);
}
break;
case 147: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy427, yymsp[-1].minor.yy399, yymsp[-2].minor.yy510, yymsp[-5].minor.yy502, yymsp[0].minor.yy198);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy3, yymsp[-1].minor.yy43, yymsp[-2].minor.yy272, yymsp[-5].minor.yy348, yymsp[0].minor.yy258);
}
break;
case 148: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy427, 0, yymsp[-2].minor.yy510, yymsp[-5].minor.yy502, 0);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy3, 0, yymsp[-2].minor.yy272, yymsp[-5].minor.yy348, 0);
}
break;
case 149: /* upsert ::= */
-{ yymsp[1].minor.yy198 = 0; }
+{ yymsp[1].minor.yy258 = 0; }
break;
case 150: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
-{ yymsp[-10].minor.yy198 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy232,yymsp[-5].minor.yy182,yymsp[-1].minor.yy232,yymsp[0].minor.yy182);}
+{ yymsp[-10].minor.yy258 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy402,yymsp[-5].minor.yy2,yymsp[-1].minor.yy402,yymsp[0].minor.yy2);}
break;
case 151: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
-{ yymsp[-7].minor.yy198 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy232,yymsp[-2].minor.yy182,0,0); }
+{ yymsp[-7].minor.yy258 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy402,yymsp[-2].minor.yy2,0,0); }
break;
case 152: /* upsert ::= ON CONFLICT DO NOTHING */
-{ yymsp[-3].minor.yy198 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
+{ yymsp[-3].minor.yy258 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
break;
case 156: /* idlist_opt ::= LP idlist RP */
-{yymsp[-2].minor.yy510 = yymsp[-1].minor.yy510;}
+{yymsp[-2].minor.yy272 = yymsp[-1].minor.yy272;}
break;
case 157: /* idlist ::= idlist COMMA nm */
-{yymsp[-2].minor.yy510 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy510,&yymsp[0].minor.yy0);}
+{yymsp[-2].minor.yy272 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy272,&yymsp[0].minor.yy0);}
break;
case 158: /* idlist ::= nm */
-{yymsp[0].minor.yy510 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
+{yymsp[0].minor.yy272 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
case 159: /* expr ::= LP expr RP */
-{yymsp[-2].minor.yy182 = yymsp[-1].minor.yy182;}
+{yymsp[-2].minor.yy2 = yymsp[-1].minor.yy2;}
break;
case 160: /* expr ::= ID|INDEXED */
case 161: /* expr ::= JOIN_KW */ yytestcase(yyruleno==161);
-{yymsp[0].minor.yy182=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{yymsp[0].minor.yy2=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 162: /* expr ::= nm DOT nm */
{
@@ -150125,9 +150931,9 @@ static YYACTIONTYPE yy_reduce(
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0);
sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0);
}
- yylhsminor.yy182 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
+ yylhsminor.yy2 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
- yymsp[-2].minor.yy182 = yylhsminor.yy182;
+ yymsp[-2].minor.yy2 = yylhsminor.yy2;
break;
case 163: /* expr ::= nm DOT nm DOT nm */
{
@@ -150139,26 +150945,26 @@ static YYACTIONTYPE yy_reduce(
sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0);
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0);
}
- yylhsminor.yy182 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
+ yylhsminor.yy2 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
- yymsp[-4].minor.yy182 = yylhsminor.yy182;
+ yymsp[-4].minor.yy2 = yylhsminor.yy2;
break;
case 164: /* term ::= NULL|FLOAT|BLOB */
case 165: /* term ::= STRING */ yytestcase(yyruleno==165);
-{yymsp[0].minor.yy182=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+{yymsp[0].minor.yy2=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
case 166: /* term ::= INTEGER */
{
- yylhsminor.yy182 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
+ yylhsminor.yy2 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
}
- yymsp[0].minor.yy182 = yylhsminor.yy182;
+ yymsp[0].minor.yy2 = yylhsminor.yy2;
break;
case 167: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
- yymsp[0].minor.yy182 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy182, n);
+ yymsp[0].minor.yy2 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
+ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy2, n);
}else{
/* When doing a nested parse, one can include terms in an expression
** that look like this: #1 #2 ... These terms refer to registers
@@ -150167,49 +150973,49 @@ static YYACTIONTYPE yy_reduce(
assert( t.n>=2 );
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
- yymsp[0].minor.yy182 = 0;
+ yymsp[0].minor.yy2 = 0;
}else{
- yymsp[0].minor.yy182 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
- if( yymsp[0].minor.yy182 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy182->iTable);
+ yymsp[0].minor.yy2 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
+ if( yymsp[0].minor.yy2 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy2->iTable);
}
}
}
break;
case 168: /* expr ::= expr COLLATE ID|STRING */
{
- yymsp[-2].minor.yy182 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy182, &yymsp[0].minor.yy0, 1);
+ yymsp[-2].minor.yy2 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy2, &yymsp[0].minor.yy0, 1);
}
break;
case 169: /* expr ::= CAST LP expr AS typetoken RP */
{
- yymsp[-5].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy182, yymsp[-3].minor.yy182, 0);
+ yymsp[-5].minor.yy2 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
+ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy2, yymsp[-3].minor.yy2, 0);
}
break;
case 170: /* expr ::= ID|INDEXED LP distinct exprlist RP */
{
- yylhsminor.yy182 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy232, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy502);
+ yylhsminor.yy2 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy402, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy348);
}
- yymsp[-4].minor.yy182 = yylhsminor.yy182;
+ yymsp[-4].minor.yy2 = yylhsminor.yy2;
break;
case 171: /* expr ::= ID|INDEXED LP STAR RP */
{
- yylhsminor.yy182 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
+ yylhsminor.yy2 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
}
- yymsp[-3].minor.yy182 = yylhsminor.yy182;
+ yymsp[-3].minor.yy2 = yylhsminor.yy2;
break;
case 172: /* term ::= CTIME_KW */
{
- yylhsminor.yy182 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
+ yylhsminor.yy2 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
}
- yymsp[0].minor.yy182 = yylhsminor.yy182;
+ yymsp[0].minor.yy2 = yylhsminor.yy2;
break;
case 173: /* expr ::= LP nexprlist COMMA expr RP */
{
- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy232, yymsp[-1].minor.yy182);
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( yymsp[-4].minor.yy182 ){
- yymsp[-4].minor.yy182->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy402, yymsp[-1].minor.yy2);
+ yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
+ if( yymsp[-4].minor.yy2 ){
+ yymsp[-4].minor.yy2->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
@@ -150223,7 +151029,7 @@ static YYACTIONTYPE yy_reduce(
case 179: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==179);
case 180: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==180);
case 181: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==181);
-{yymsp[-2].minor.yy182=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy182,yymsp[0].minor.yy182);}
+{yymsp[-2].minor.yy2=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy2,yymsp[0].minor.yy2);}
break;
case 182: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
@@ -150233,11 +151039,11 @@ static YYACTIONTYPE yy_reduce(
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
yymsp[-1].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy182);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy182);
- yymsp[-2].minor.yy182 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
- if( bNot ) yymsp[-2].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy182, 0);
- if( yymsp[-2].minor.yy182 ) yymsp[-2].minor.yy182->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy2);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy2);
+ yymsp[-2].minor.yy2 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ if( bNot ) yymsp[-2].minor.yy2 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy2, 0);
+ if( yymsp[-2].minor.yy2 ) yymsp[-2].minor.yy2->flags |= EP_InfixFunc;
}
break;
case 184: /* expr ::= expr likeop expr ESCAPE expr */
@@ -150245,62 +151051,62 @@ static YYACTIONTYPE yy_reduce(
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
yymsp[-3].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy182);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy182);
- yymsp[-4].minor.yy182 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
- if( bNot ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
- if( yymsp[-4].minor.yy182 ) yymsp[-4].minor.yy182->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy2);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy2);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy2);
+ yymsp[-4].minor.yy2 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
+ if( bNot ) yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy2, 0);
+ if( yymsp[-4].minor.yy2 ) yymsp[-4].minor.yy2->flags |= EP_InfixFunc;
}
break;
case 185: /* expr ::= expr ISNULL|NOTNULL */
-{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy182,0);}
+{yymsp[-1].minor.yy2 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy2,0);}
break;
case 186: /* expr ::= expr NOT NULL */
-{yymsp[-2].minor.yy182 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy182,0);}
+{yymsp[-2].minor.yy2 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy2,0);}
break;
case 187: /* expr ::= expr IS expr */
{
- yymsp[-2].minor.yy182 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy182,yymsp[0].minor.yy182);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy182, yymsp[-2].minor.yy182, TK_ISNULL);
+ yymsp[-2].minor.yy2 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy2,yymsp[0].minor.yy2);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy2, yymsp[-2].minor.yy2, TK_ISNULL);
}
break;
case 188: /* expr ::= expr IS NOT expr */
{
- yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy182,yymsp[0].minor.yy182);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy182, yymsp[-3].minor.yy182, TK_NOTNULL);
+ yymsp[-3].minor.yy2 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy2,yymsp[0].minor.yy2);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy2, yymsp[-3].minor.yy2, TK_NOTNULL);
}
break;
case 189: /* expr ::= NOT expr */
case 190: /* expr ::= BITNOT expr */ yytestcase(yyruleno==190);
-{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy182, 0);/*A-overwrites-B*/}
+{yymsp[-1].minor.yy2 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy2, 0);/*A-overwrites-B*/}
break;
case 191: /* expr ::= PLUS|MINUS expr */
{
- yymsp[-1].minor.yy182 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy182, 0);
+ yymsp[-1].minor.yy2 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy2, 0);
/*A-overwrites-B*/
}
break;
case 192: /* between_op ::= BETWEEN */
case 195: /* in_op ::= IN */ yytestcase(yyruleno==195);
-{yymsp[0].minor.yy502 = 0;}
+{yymsp[0].minor.yy348 = 0;}
break;
case 194: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy182);
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy182, 0);
- if( yymsp[-4].minor.yy182 ){
- yymsp[-4].minor.yy182->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy2);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy2);
+ yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy2, 0);
+ if( yymsp[-4].minor.yy2 ){
+ yymsp[-4].minor.yy2->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
+ if( yymsp[-3].minor.yy348 ) yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy2, 0);
}
break;
case 197: /* expr ::= expr in_op LP exprlist RP */
{
- if( yymsp[-1].minor.yy232==0 ){
+ if( yymsp[-1].minor.yy402==0 ){
/* Expressions of the form
**
** expr1 IN ()
@@ -150309,9 +151115,11 @@ static YYACTIONTYPE yy_reduce(
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
- sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy182);
- yymsp[-4].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy502],1);
- }else if( yymsp[-1].minor.yy232->nExpr==1 ){
+ if( IN_RENAME_OBJECT==0 ){
+ sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy2);
+ yymsp[-4].minor.yy2 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy348],1);
+ }
+ }else if( yymsp[-1].minor.yy402->nExpr==1 ){
/* Expressions of the form:
**
** expr1 IN (?1)
@@ -150328,198 +151136,198 @@ static YYACTIONTYPE yy_reduce(
** affinity or the collating sequence to use for comparison. Otherwise,
** the semantics would be subtly different from IN or NOT IN.
*/
- Expr *pRHS = yymsp[-1].minor.yy232->a[0].pExpr;
- yymsp[-1].minor.yy232->a[0].pExpr = 0;
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy232);
+ Expr *pRHS = yymsp[-1].minor.yy402->a[0].pExpr;
+ yymsp[-1].minor.yy402->a[0].pExpr = 0;
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402);
/* pRHS cannot be NULL because a malloc error would have been detected
** before now and control would have never reached this point */
if( ALWAYS(pRHS) ){
pRHS->flags &= ~EP_Collate;
pRHS->flags |= EP_Generic;
}
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, yymsp[-3].minor.yy502 ? TK_NE : TK_EQ, yymsp[-4].minor.yy182, pRHS);
+ yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, yymsp[-3].minor.yy348 ? TK_NE : TK_EQ, yymsp[-4].minor.yy2, pRHS);
}else{
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0);
- if( yymsp[-4].minor.yy182 ){
- yymsp[-4].minor.yy182->x.pList = yymsp[-1].minor.yy232;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy182);
+ yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy2, 0);
+ if( yymsp[-4].minor.yy2 ){
+ yymsp[-4].minor.yy2->x.pList = yymsp[-1].minor.yy402;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy2);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy232);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy402);
}
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
+ if( yymsp[-3].minor.yy348 ) yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy2, 0);
}
}
break;
case 198: /* expr ::= LP select RP */
{
- yymsp[-2].minor.yy182 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy182, yymsp[-1].minor.yy399);
+ yymsp[-2].minor.yy2 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy2, yymsp[-1].minor.yy43);
}
break;
case 199: /* expr ::= expr in_op LP select RP */
{
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy182, yymsp[-1].minor.yy399);
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
+ yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy2, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy2, yymsp[-1].minor.yy43);
+ if( yymsp[-3].minor.yy348 ) yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy2, 0);
}
break;
case 200: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
- SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
+ SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
- if( yymsp[0].minor.yy232 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy232);
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy182, pSelect);
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
+ if( yymsp[0].minor.yy402 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy402);
+ yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy2, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy2, pSelect);
+ if( yymsp[-3].minor.yy348 ) yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy2, 0);
}
break;
case 201: /* expr ::= EXISTS LP select RP */
{
Expr *p;
- p = yymsp[-3].minor.yy182 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy399);
+ p = yymsp[-3].minor.yy2 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
+ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy43);
}
break;
case 202: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy182, 0);
- if( yymsp[-4].minor.yy182 ){
- yymsp[-4].minor.yy182->x.pList = yymsp[-1].minor.yy182 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy232,yymsp[-1].minor.yy182) : yymsp[-2].minor.yy232;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy182);
+ yymsp[-4].minor.yy2 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy2, 0);
+ if( yymsp[-4].minor.yy2 ){
+ yymsp[-4].minor.yy2->x.pList = yymsp[-1].minor.yy2 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[-1].minor.yy2) : yymsp[-2].minor.yy402;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy2);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy232);
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy182);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy402);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy2);
}
}
break;
case 203: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, yymsp[-2].minor.yy182);
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, yymsp[0].minor.yy182);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[-2].minor.yy2);
+ yymsp[-4].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy402, yymsp[0].minor.yy2);
}
break;
case 204: /* case_exprlist ::= WHEN expr THEN expr */
{
- yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182);
- yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy232, yymsp[0].minor.yy182);
+ yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy2);
+ yymsp[-3].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy402, yymsp[0].minor.yy2);
}
break;
case 207: /* case_operand ::= expr */
-{yymsp[0].minor.yy182 = yymsp[0].minor.yy182; /*A-overwrites-X*/}
+{yymsp[0].minor.yy2 = yymsp[0].minor.yy2; /*A-overwrites-X*/}
break;
case 210: /* nexprlist ::= nexprlist COMMA expr */
-{yymsp[-2].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy232,yymsp[0].minor.yy182);}
+{yymsp[-2].minor.yy402 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy402,yymsp[0].minor.yy2);}
break;
case 211: /* nexprlist ::= expr */
-{yymsp[0].minor.yy232 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy182); /*A-overwrites-Y*/}
+{yymsp[0].minor.yy402 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy2); /*A-overwrites-Y*/}
break;
case 213: /* paren_exprlist ::= LP exprlist RP */
case 218: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==218);
-{yymsp[-2].minor.yy232 = yymsp[-1].minor.yy232;}
+{yymsp[-2].minor.yy402 = yymsp[-1].minor.yy402;}
break;
case 214: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
- sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy232, yymsp[-10].minor.yy502,
- &yymsp[-11].minor.yy0, yymsp[0].minor.yy182, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF);
+ sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy402, yymsp[-10].minor.yy348,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy2, SQLITE_SO_ASC, yymsp[-8].minor.yy348, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
}
}
break;
case 215: /* uniqueflag ::= UNIQUE */
- case 255: /* raisetype ::= ABORT */ yytestcase(yyruleno==255);
-{yymsp[0].minor.yy502 = OE_Abort;}
+ case 257: /* raisetype ::= ABORT */ yytestcase(yyruleno==257);
+{yymsp[0].minor.yy348 = OE_Abort;}
break;
case 216: /* uniqueflag ::= */
-{yymsp[1].minor.yy502 = OE_None;}
+{yymsp[1].minor.yy348 = OE_None;}
break;
case 219: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
- yymsp[-4].minor.yy232 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy232, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502);
+ yymsp[-4].minor.yy402 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy402, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy348, yymsp[0].minor.yy348);
}
break;
case 220: /* eidlist ::= nm collate sortorder */
{
- yymsp[-2].minor.yy232 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/
+ yymsp[-2].minor.yy402 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy348, yymsp[0].minor.yy348); /*A-overwrites-Y*/
}
break;
case 223: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy427, yymsp[-1].minor.yy502);}
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy3, yymsp[-1].minor.yy348);}
break;
- case 224: /* cmd ::= VACUUM */
-{sqlite3Vacuum(pParse,0);}
+ case 224: /* cmd ::= VACUUM vinto */
+{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy2);}
break;
- case 225: /* cmd ::= VACUUM nm */
-{sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);}
+ case 225: /* cmd ::= VACUUM nm vinto */
+{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy2);}
break;
- case 226: /* cmd ::= PRAGMA nm dbnm */
+ case 228: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 227: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 229: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 228: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 230: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 229: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 231: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
- case 230: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ case 232: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
- case 233: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ case 235: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy47, &all);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy347, &all);
}
break;
- case 234: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 236: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy300.a, yymsp[-4].minor.yy300.b, yymsp[-2].minor.yy427, yymsp[0].minor.yy182, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy348, yymsp[-4].minor.yy338.a, yymsp[-4].minor.yy338.b, yymsp[-2].minor.yy3, yymsp[0].minor.yy2, yymsp[-10].minor.yy348, yymsp[-8].minor.yy348);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
- case 235: /* trigger_time ::= BEFORE|AFTER */
-{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ }
+ case 237: /* trigger_time ::= BEFORE|AFTER */
+{ yymsp[0].minor.yy348 = yymsp[0].major; /*A-overwrites-X*/ }
break;
- case 236: /* trigger_time ::= INSTEAD OF */
-{ yymsp[-1].minor.yy502 = TK_INSTEAD;}
+ case 238: /* trigger_time ::= INSTEAD OF */
+{ yymsp[-1].minor.yy348 = TK_INSTEAD;}
break;
- case 237: /* trigger_time ::= */
-{ yymsp[1].minor.yy502 = TK_BEFORE; }
+ case 239: /* trigger_time ::= */
+{ yymsp[1].minor.yy348 = TK_BEFORE; }
break;
- case 238: /* trigger_event ::= DELETE|INSERT */
- case 239: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==239);
-{yymsp[0].minor.yy300.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy300.b = 0;}
+ case 240: /* trigger_event ::= DELETE|INSERT */
+ case 241: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==241);
+{yymsp[0].minor.yy338.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy338.b = 0;}
break;
- case 240: /* trigger_event ::= UPDATE OF idlist */
-{yymsp[-2].minor.yy300.a = TK_UPDATE; yymsp[-2].minor.yy300.b = yymsp[0].minor.yy510;}
+ case 242: /* trigger_event ::= UPDATE OF idlist */
+{yymsp[-2].minor.yy338.a = TK_UPDATE; yymsp[-2].minor.yy338.b = yymsp[0].minor.yy272;}
break;
- case 241: /* when_clause ::= */
- case 260: /* key_opt ::= */ yytestcase(yyruleno==260);
-{ yymsp[1].minor.yy182 = 0; }
+ case 243: /* when_clause ::= */
+ case 262: /* key_opt ::= */ yytestcase(yyruleno==262);
+{ yymsp[1].minor.yy2 = 0; }
break;
- case 242: /* when_clause ::= WHEN expr */
- case 261: /* key_opt ::= KEY expr */ yytestcase(yyruleno==261);
-{ yymsp[-1].minor.yy182 = yymsp[0].minor.yy182; }
+ case 244: /* when_clause ::= WHEN expr */
+ case 263: /* key_opt ::= KEY expr */ yytestcase(yyruleno==263);
+{ yymsp[-1].minor.yy2 = yymsp[0].minor.yy2; }
break;
- case 243: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 245: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- assert( yymsp[-2].minor.yy47!=0 );
- yymsp[-2].minor.yy47->pLast->pNext = yymsp[-1].minor.yy47;
- yymsp[-2].minor.yy47->pLast = yymsp[-1].minor.yy47;
+ assert( yymsp[-2].minor.yy347!=0 );
+ yymsp[-2].minor.yy347->pLast->pNext = yymsp[-1].minor.yy347;
+ yymsp[-2].minor.yy347->pLast = yymsp[-1].minor.yy347;
}
break;
- case 244: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ case 246: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
- assert( yymsp[-1].minor.yy47!=0 );
- yymsp[-1].minor.yy47->pLast = yymsp[-1].minor.yy47;
+ assert( yymsp[-1].minor.yy347!=0 );
+ yymsp[-1].minor.yy347->pLast = yymsp[-1].minor.yy347;
}
break;
- case 245: /* trnm ::= nm DOT nm */
+ case 247: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
@@ -150527,194 +151335,194 @@ static YYACTIONTYPE yy_reduce(
"statements within triggers");
}
break;
- case 246: /* tridxby ::= INDEXED BY nm */
+ case 248: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 247: /* tridxby ::= NOT INDEXED */
+ case 249: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 248: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
-{yylhsminor.yy47 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy232, yymsp[-1].minor.yy182, yymsp[-6].minor.yy502, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy36);}
- yymsp[-7].minor.yy47 = yylhsminor.yy47;
+ case 250: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+{yylhsminor.yy347 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy402, yymsp[-1].minor.yy2, yymsp[-6].minor.yy348, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy360);}
+ yymsp[-7].minor.yy347 = yylhsminor.yy347;
break;
- case 249: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ case 251: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
{
- yylhsminor.yy47 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy510,yymsp[-2].minor.yy399,yymsp[-6].minor.yy502,yymsp[-1].minor.yy198,yymsp[-7].minor.yy36,yymsp[0].minor.yy36);/*yylhsminor.yy47-overwrites-yymsp[-6].minor.yy502*/
+ yylhsminor.yy347 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy272,yymsp[-2].minor.yy43,yymsp[-6].minor.yy348,yymsp[-1].minor.yy258,yymsp[-7].minor.yy360,yymsp[0].minor.yy360);/*yylhsminor.yy347-overwrites-yymsp[-6].minor.yy348*/
}
- yymsp[-7].minor.yy47 = yylhsminor.yy47;
+ yymsp[-7].minor.yy347 = yylhsminor.yy347;
break;
- case 250: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-{yylhsminor.yy47 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy182, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy36);}
- yymsp[-5].minor.yy47 = yylhsminor.yy47;
+ case 252: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+{yylhsminor.yy347 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy2, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy360);}
+ yymsp[-5].minor.yy347 = yylhsminor.yy347;
break;
- case 251: /* trigger_cmd ::= scanpt select scanpt */
-{yylhsminor.yy47 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy399, yymsp[-2].minor.yy36, yymsp[0].minor.yy36); /*yylhsminor.yy47-overwrites-yymsp[-1].minor.yy399*/}
- yymsp[-2].minor.yy47 = yylhsminor.yy47;
+ case 253: /* trigger_cmd ::= scanpt select scanpt */
+{yylhsminor.yy347 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy43, yymsp[-2].minor.yy360, yymsp[0].minor.yy360); /*yylhsminor.yy347-overwrites-yymsp[-1].minor.yy43*/}
+ yymsp[-2].minor.yy347 = yylhsminor.yy347;
break;
- case 252: /* expr ::= RAISE LP IGNORE RP */
+ case 254: /* expr ::= RAISE LP IGNORE RP */
{
- yymsp[-3].minor.yy182 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
- if( yymsp[-3].minor.yy182 ){
- yymsp[-3].minor.yy182->affinity = OE_Ignore;
+ yymsp[-3].minor.yy2 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
+ if( yymsp[-3].minor.yy2 ){
+ yymsp[-3].minor.yy2->affinity = OE_Ignore;
}
}
break;
- case 253: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 255: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yymsp[-5].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
- if( yymsp[-5].minor.yy182 ) {
- yymsp[-5].minor.yy182->affinity = (char)yymsp[-3].minor.yy502;
+ yymsp[-5].minor.yy2 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
+ if( yymsp[-5].minor.yy2 ) {
+ yymsp[-5].minor.yy2->affinity = (char)yymsp[-3].minor.yy348;
}
}
break;
- case 254: /* raisetype ::= ROLLBACK */
-{yymsp[0].minor.yy502 = OE_Rollback;}
+ case 256: /* raisetype ::= ROLLBACK */
+{yymsp[0].minor.yy348 = OE_Rollback;}
break;
- case 256: /* raisetype ::= FAIL */
-{yymsp[0].minor.yy502 = OE_Fail;}
+ case 258: /* raisetype ::= FAIL */
+{yymsp[0].minor.yy348 = OE_Fail;}
break;
- case 257: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 259: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy427,yymsp[-1].minor.yy502);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy3,yymsp[-1].minor.yy348);
}
break;
- case 258: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 260: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy182, yymsp[-1].minor.yy182, yymsp[0].minor.yy182);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy2, yymsp[-1].minor.yy2, yymsp[0].minor.yy2);
}
break;
- case 259: /* cmd ::= DETACH database_kw_opt expr */
+ case 261: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy182);
+ sqlite3Detach(pParse, yymsp[0].minor.yy2);
}
break;
- case 262: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 264: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy427,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy3,&yymsp[0].minor.yy0);
}
break;
- case 263: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ case 265: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
}
break;
- case 264: /* add_column_fullname ::= fullname */
+ case 266: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy427);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy3);
}
break;
- case 265: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ case 267: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
{
- sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy427, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
+ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy3, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 266: /* cmd ::= create_vtab */
+ case 268: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 267: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 269: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 268: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 270: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
- sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy502);
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy348);
}
break;
- case 269: /* vtabarg ::= */
+ case 271: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 270: /* vtabargtoken ::= ANY */
- case 271: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==271);
- case 272: /* lp ::= LP */ yytestcase(yyruleno==272);
+ case 272: /* vtabargtoken ::= ANY */
+ case 273: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==273);
+ case 274: /* lp ::= LP */ yytestcase(yyruleno==274);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
- case 273: /* with ::= WITH wqlist */
- case 274: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==274);
-{ sqlite3WithPush(pParse, yymsp[0].minor.yy91, 1); }
+ case 275: /* with ::= WITH wqlist */
+ case 276: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==276);
+{ sqlite3WithPush(pParse, yymsp[0].minor.yy4, 1); }
break;
- case 275: /* wqlist ::= nm eidlist_opt AS LP select RP */
+ case 277: /* wqlist ::= nm eidlist_opt AS LP select RP */
{
- yymsp[-5].minor.yy91 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy232, yymsp[-1].minor.yy399); /*A-overwrites-X*/
+ yymsp[-5].minor.yy4 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy402, yymsp[-1].minor.yy43); /*A-overwrites-X*/
}
break;
- case 276: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ case 278: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
{
- yymsp[-7].minor.yy91 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy91, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy232, yymsp[-1].minor.yy399);
+ yymsp[-7].minor.yy4 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy4, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy402, yymsp[-1].minor.yy43);
}
break;
default:
- /* (277) input ::= cmdlist */ yytestcase(yyruleno==277);
- /* (278) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==278);
- /* (279) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=279);
- /* (280) ecmd ::= SEMI */ yytestcase(yyruleno==280);
- /* (281) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==281);
- /* (282) trans_opt ::= */ yytestcase(yyruleno==282);
- /* (283) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==283);
- /* (284) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==284);
- /* (285) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==285);
- /* (286) savepoint_opt ::= */ yytestcase(yyruleno==286);
- /* (287) cmd ::= create_table create_table_args */ yytestcase(yyruleno==287);
- /* (288) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==288);
- /* (289) columnlist ::= columnname carglist */ yytestcase(yyruleno==289);
- /* (290) nm ::= ID|INDEXED */ yytestcase(yyruleno==290);
- /* (291) nm ::= STRING */ yytestcase(yyruleno==291);
- /* (292) nm ::= JOIN_KW */ yytestcase(yyruleno==292);
- /* (293) typetoken ::= typename */ yytestcase(yyruleno==293);
- /* (294) typename ::= ID|STRING */ yytestcase(yyruleno==294);
- /* (295) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=295);
- /* (296) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=296);
- /* (297) carglist ::= carglist ccons */ yytestcase(yyruleno==297);
- /* (298) carglist ::= */ yytestcase(yyruleno==298);
- /* (299) ccons ::= NULL onconf */ yytestcase(yyruleno==299);
- /* (300) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==300);
- /* (301) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==301);
- /* (302) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=302);
- /* (303) tconscomma ::= */ yytestcase(yyruleno==303);
- /* (304) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=304);
- /* (305) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=305);
- /* (306) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=306);
- /* (307) oneselect ::= values */ yytestcase(yyruleno==307);
- /* (308) sclp ::= selcollist COMMA */ yytestcase(yyruleno==308);
- /* (309) as ::= ID|STRING */ yytestcase(yyruleno==309);
- /* (310) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=310);
- /* (311) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==311);
- /* (312) exprlist ::= nexprlist */ yytestcase(yyruleno==312);
- /* (313) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=313);
- /* (314) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=314);
- /* (315) nmnum ::= ON */ yytestcase(yyruleno==315);
- /* (316) nmnum ::= DELETE */ yytestcase(yyruleno==316);
- /* (317) nmnum ::= DEFAULT */ yytestcase(yyruleno==317);
- /* (318) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==318);
- /* (319) foreach_clause ::= */ yytestcase(yyruleno==319);
- /* (320) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==320);
- /* (321) trnm ::= nm */ yytestcase(yyruleno==321);
- /* (322) tridxby ::= */ yytestcase(yyruleno==322);
- /* (323) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==323);
- /* (324) database_kw_opt ::= */ yytestcase(yyruleno==324);
- /* (325) kwcolumn_opt ::= */ yytestcase(yyruleno==325);
- /* (326) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==326);
- /* (327) vtabarglist ::= vtabarg */ yytestcase(yyruleno==327);
- /* (328) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==328);
- /* (329) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==329);
- /* (330) anylist ::= */ yytestcase(yyruleno==330);
- /* (331) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==331);
- /* (332) anylist ::= anylist ANY */ yytestcase(yyruleno==332);
- /* (333) with ::= */ yytestcase(yyruleno==333);
+ /* (279) input ::= cmdlist */ yytestcase(yyruleno==279);
+ /* (280) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==280);
+ /* (281) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=281);
+ /* (282) ecmd ::= SEMI */ yytestcase(yyruleno==282);
+ /* (283) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==283);
+ /* (284) trans_opt ::= */ yytestcase(yyruleno==284);
+ /* (285) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==285);
+ /* (286) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==286);
+ /* (287) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==287);
+ /* (288) savepoint_opt ::= */ yytestcase(yyruleno==288);
+ /* (289) cmd ::= create_table create_table_args */ yytestcase(yyruleno==289);
+ /* (290) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==290);
+ /* (291) columnlist ::= columnname carglist */ yytestcase(yyruleno==291);
+ /* (292) nm ::= ID|INDEXED */ yytestcase(yyruleno==292);
+ /* (293) nm ::= STRING */ yytestcase(yyruleno==293);
+ /* (294) nm ::= JOIN_KW */ yytestcase(yyruleno==294);
+ /* (295) typetoken ::= typename */ yytestcase(yyruleno==295);
+ /* (296) typename ::= ID|STRING */ yytestcase(yyruleno==296);
+ /* (297) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=297);
+ /* (298) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=298);
+ /* (299) carglist ::= carglist ccons */ yytestcase(yyruleno==299);
+ /* (300) carglist ::= */ yytestcase(yyruleno==300);
+ /* (301) ccons ::= NULL onconf */ yytestcase(yyruleno==301);
+ /* (302) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==302);
+ /* (303) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==303);
+ /* (304) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=304);
+ /* (305) tconscomma ::= */ yytestcase(yyruleno==305);
+ /* (306) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=306);
+ /* (307) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=307);
+ /* (308) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=308);
+ /* (309) oneselect ::= values */ yytestcase(yyruleno==309);
+ /* (310) sclp ::= selcollist COMMA */ yytestcase(yyruleno==310);
+ /* (311) as ::= ID|STRING */ yytestcase(yyruleno==311);
+ /* (312) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=312);
+ /* (313) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==313);
+ /* (314) exprlist ::= nexprlist */ yytestcase(yyruleno==314);
+ /* (315) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=315);
+ /* (316) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=316);
+ /* (317) nmnum ::= ON */ yytestcase(yyruleno==317);
+ /* (318) nmnum ::= DELETE */ yytestcase(yyruleno==318);
+ /* (319) nmnum ::= DEFAULT */ yytestcase(yyruleno==319);
+ /* (320) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==320);
+ /* (321) foreach_clause ::= */ yytestcase(yyruleno==321);
+ /* (322) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==322);
+ /* (323) trnm ::= nm */ yytestcase(yyruleno==323);
+ /* (324) tridxby ::= */ yytestcase(yyruleno==324);
+ /* (325) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==325);
+ /* (326) database_kw_opt ::= */ yytestcase(yyruleno==326);
+ /* (327) kwcolumn_opt ::= */ yytestcase(yyruleno==327);
+ /* (328) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==328);
+ /* (329) vtabarglist ::= vtabarg */ yytestcase(yyruleno==329);
+ /* (330) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==330);
+ /* (331) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==331);
+ /* (332) anylist ::= */ yytestcase(yyruleno==332);
+ /* (333) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==333);
+ /* (334) anylist ::= anylist ANY */ yytestcase(yyruleno==334);
+ /* (335) with ::= */ yytestcase(yyruleno==335);
break;
/********** End reduce actions ************************************************/
};
- assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
- yygoto = yyRuleInfo[yyruleno].lhs;
- yysize = yyRuleInfo[yyruleno].nrhs;
+ assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
+ yygoto = yyRuleInfoLhs[yyruleno];
+ yysize = yyRuleInfoNRhs[yyruleno];
yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
/* There are no SHIFTREDUCE actions on nonterminals because the table
@@ -151862,73 +152670,6 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
return i;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-/*
-** Return the length (in bytes) of the token that begins at z[0].
-** Store the token type in *tokenType before returning. If flags has
-** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type
-** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was
-** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags
-** if the token was recognized as a keyword; this is useful when the
-** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller
-** to differentiate between a keyword being treated as an identifier
-** (for normalization purposes) and an actual identifier.
-*/
-SQLITE_PRIVATE int sqlite3GetTokenNormalized(
- const unsigned char *z,
- int *tokenType,
- int *flags
-){
- int n;
- unsigned char iClass = aiClass[*z];
- if( iClass==CC_KYWD ){
- int i;
- for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
- if( IdChar(z[i]) ){
- /* This token started out using characters that can appear in keywords,
- ** but z[i] is a character not allowed within keywords, so this must
- ** be an identifier instead */
- i++;
- while( IdChar(z[i]) ){ i++; }
- *tokenType = TK_ID;
- return i;
- }
- *tokenType = TK_ID;
- n = keywordCode((char*)z, i, tokenType);
- /* If the token is no longer considered to be an identifier, then it is a
- ** keyword of some kind. Make the token back into an identifier and then
- ** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are
- ** used verbatim, including IN, IS, NOT, and NULL. */
- switch( *tokenType ){
- case TK_ID: {
- /* do nothing, handled by caller */
- break;
- }
- case TK_IN:
- case TK_IS:
- case TK_NOT:
- case TK_NULL: {
- *flags |= SQLITE_TOKEN_KEYWORD;
- break;
- }
- default: {
- *tokenType = TK_ID;
- *flags |= SQLITE_TOKEN_KEYWORD;
- break;
- }
- }
- }else{
- n = sqlite3GetToken(z, tokenType);
- /* If the token is considered to be an identifier and the character class
- ** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */
- if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){
- *flags |= SQLITE_TOKEN_QUOTED;
- }
- }
- return n;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
-
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
@@ -151956,7 +152697,14 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
pParse->rc = SQLITE_OK;
pParse->zTail = zSql;
assert( pzErrMsg!=0 );
- /* sqlite3ParserTrace(stdout, "parser: "); */
+#ifdef SQLITE_DEBUG
+ if( db->flags & SQLITE_ParserTrace ){
+ printf("parser: [[[%s]]]\n", zSql);
+ sqlite3ParserTrace(stdout, "parser: ");
+ }else{
+ sqlite3ParserTrace(0, 0);
+ }
+#endif
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
pEngine = &sEngine;
sqlite3ParserInit(pEngine, pParse);
@@ -152099,6 +152847,141 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
return nErr;
}
+
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Insert a single space character into pStr if the current string
+** ends with an identifier
+*/
+static void addSpaceSeparator(sqlite3_str *pStr){
+ if( pStr->nChar && sqlite3IsIdChar(pStr->zText[pStr->nChar-1]) ){
+ sqlite3_str_append(pStr, " ", 1);
+ }
+}
+
+/*
+** Compute a normalization of the SQL given by zSql[0..nSql-1]. Return
+** the normalization in space obtained from sqlite3DbMalloc(). Or return
+** NULL if anything goes wrong or if zSql is NULL.
+*/
+SQLITE_PRIVATE char *sqlite3Normalize(
+ Vdbe *pVdbe, /* VM being reprepared */
+ const char *zSql /* The original SQL string */
+){
+ sqlite3 *db; /* The database connection */
+ int i; /* Next unread byte of zSql[] */
+ int n; /* length of current token */
+ int tokenType; /* type of current token */
+ int prevType = 0; /* Previous non-whitespace token */
+ int nParen; /* Number of nested levels of parentheses */
+ int iStartIN; /* Start of RHS of IN operator in z[] */
+ int nParenAtIN; /* Value of nParent at start of RHS of IN operator */
+ int j; /* Bytes of normalized SQL generated so far */
+ sqlite3_str *pStr; /* The normalized SQL string under construction */
+
+ db = sqlite3VdbeDb(pVdbe);
+ tokenType = -1;
+ nParen = iStartIN = nParenAtIN = 0;
+ pStr = sqlite3_str_new(db);
+ assert( pStr!=0 ); /* sqlite3_str_new() never returns NULL */
+ for(i=0; zSql[i] && pStr->accError==0; i+=n){
+ if( tokenType!=TK_SPACE ){
+ prevType = tokenType;
+ }
+ n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
+ if( NEVER(n<=0) ) break;
+ switch( tokenType ){
+ case TK_SPACE: {
+ break;
+ }
+ case TK_NULL: {
+ if( prevType==TK_IS || prevType==TK_NOT ){
+ sqlite3_str_append(pStr, " NULL", 5);
+ break;
+ }
+ /* Fall through */
+ }
+ case TK_STRING:
+ case TK_INTEGER:
+ case TK_FLOAT:
+ case TK_VARIABLE:
+ case TK_BLOB: {
+ sqlite3_str_append(pStr, "?", 1);
+ break;
+ }
+ case TK_LP: {
+ nParen++;
+ if( prevType==TK_IN ){
+ iStartIN = pStr->nChar;
+ nParenAtIN = nParen;
+ }
+ sqlite3_str_append(pStr, "(", 1);
+ break;
+ }
+ case TK_RP: {
+ if( iStartIN>0 && nParen==nParenAtIN ){
+ assert( pStr->nChar>=iStartIN );
+ pStr->nChar = iStartIN+1;
+ sqlite3_str_append(pStr, "?,?,?", 5);
+ iStartIN = 0;
+ }
+ nParen--;
+ sqlite3_str_append(pStr, ")", 1);
+ break;
+ }
+ case TK_ID: {
+ iStartIN = 0;
+ j = pStr->nChar;
+ if( sqlite3Isquote(zSql[i]) ){
+ char *zId = sqlite3DbStrNDup(db, zSql+i, n);
+ int nId;
+ int eType = 0;
+ if( zId==0 ) break;
+ sqlite3Dequote(zId);
+ if( zSql[i]=='"' && sqlite3VdbeUsesDoubleQuotedString(pVdbe, zId) ){
+ sqlite3_str_append(pStr, "?", 1);
+ sqlite3DbFree(db, zId);
+ break;
+ }
+ nId = sqlite3Strlen30(zId);
+ if( sqlite3GetToken((u8*)zId, &eType)==nId && eType==TK_ID ){
+ addSpaceSeparator(pStr);
+ sqlite3_str_append(pStr, zId, nId);
+ }else{
+ sqlite3_str_appendf(pStr, "\"%w\"", zId);
+ }
+ sqlite3DbFree(db, zId);
+ }else{
+ addSpaceSeparator(pStr);
+ sqlite3_str_append(pStr, zSql+i, n);
+ }
+ while( j<pStr->nChar ){
+ pStr->zText[j] = sqlite3Tolower(pStr->zText[j]);
+ j++;
+ }
+ break;
+ }
+ case TK_SELECT: {
+ iStartIN = 0;
+ /* fall through */
+ }
+ default: {
+ if( sqlite3IsIdChar(zSql[i]) ) addSpaceSeparator(pStr);
+ j = pStr->nChar;
+ sqlite3_str_append(pStr, zSql+i, n);
+ while( j<pStr->nChar ){
+ pStr->zText[j] = sqlite3Toupper(pStr->zText[j]);
+ j++;
+ }
+ break;
+ }
+ }
+ }
+ if( tokenType!=TK_SEMI ) sqlite3_str_append(pStr, ";", 1);
+ return sqlite3_str_finish(pStr);
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
+
/************** End of tokenize.c ********************************************/
/************** Begin file complete.c ****************************************/
/*
@@ -153144,6 +154027,13 @@ SQLITE_API int sqlite3_config(int op, ...){
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ case SQLITE_CONFIG_MEMDB_MAXSIZE: {
+ sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
+ break;
+ }
+#endif /* SQLITE_ENABLE_DESERIALIZE */
+
default: {
rc = SQLITE_ERROR;
break;
@@ -153334,11 +154224,11 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
if( aFlagOp[i].op==op ){
int onoff = va_arg(ap, int);
int *pRes = va_arg(ap, int*);
- u32 oldFlags = db->flags;
+ u64 oldFlags = db->flags;
if( onoff>0 ){
db->flags |= aFlagOp[i].mask;
}else if( onoff==0 ){
- db->flags &= ~aFlagOp[i].mask;
+ db->flags &= ~(u64)aFlagOp[i].mask;
}
if( oldFlags!=db->flags ){
sqlite3ExpirePreparedStatements(db, 0);
@@ -153801,7 +154691,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
- db->flags &= ~SQLITE_DeferFKs;
+ db->flags &= ~(u64)SQLITE_DeferFKs;
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
@@ -154543,6 +155433,8 @@ SQLITE_API void *sqlite3_profile(
pOld = db->pProfileArg;
db->xProfile = xProfile;
db->pProfileArg = pArg;
+ db->mTrace &= SQLITE_TRACE_NONLEGACY_MASK;
+ if( db->xProfile ) db->mTrace |= SQLITE_TRACE_XPROFILE;
sqlite3_mutex_leave(db->mutex);
return pOld;
}
@@ -154894,7 +155786,7 @@ SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){
z = sqlite3ErrStr(SQLITE_NOMEM_BKPT);
}else{
testcase( db->pErr==0 );
- z = (char*)sqlite3_value_text(db->pErr);
+ z = db->errCode ? (char*)sqlite3_value_text(db->pErr) : 0;
assert( !db->mallocFailed );
if( z==0 ){
z = sqlite3ErrStr(db->errCode);
@@ -155424,6 +156316,40 @@ SQLITE_PRIVATE int sqlite3ParseUri(
return rc;
}
+#if defined(SQLITE_HAS_CODEC)
+/*
+** Process URI filename query parameters relevant to the SQLite Encryption
+** Extension. Return true if any of the relevant query parameters are
+** seen and return false if not.
+*/
+SQLITE_PRIVATE int sqlite3CodecQueryParameters(
+ sqlite3 *db, /* Database connection */
+ const char *zDb, /* Which schema is being created/attached */
+ const char *zUri /* URI filename */
+){
+ const char *zKey;
+ if( (zKey = sqlite3_uri_parameter(zUri, "hexkey"))!=0 && zKey[0] ){
+ u8 iByte;
+ int i;
+ char zDecoded[40];
+ for(i=0, iByte=0; i<sizeof(zDecoded)*2 && sqlite3Isxdigit(zKey[i]); i++){
+ iByte = (iByte<<4) + sqlite3HexToInt(zKey[i]);
+ if( (i&1)!=0 ) zDecoded[i/2] = iByte;
+ }
+ sqlite3_key_v2(db, zDb, zDecoded, i/2);
+ return 1;
+ }else if( (zKey = sqlite3_uri_parameter(zUri, "key"))!=0 ){
+ sqlite3_key_v2(db, zDb, zKey, sqlite3Strlen30(zKey));
+ return 1;
+ }else if( (zKey = sqlite3_uri_parameter(zUri, "textkey"))!=0 ){
+ sqlite3_key_v2(db, zDb, zKey, -1);
+ return 1;
+ }else{
+ return 0;
+ }
+}
+#endif
+
/*
** This routine does the work of opening a database on behalf of
@@ -155777,26 +156703,13 @@ opendb_out:
}
#endif
#if defined(SQLITE_HAS_CODEC)
- if( rc==SQLITE_OK ){
- const char *zKey;
- if( (zKey = sqlite3_uri_parameter(zOpen, "hexkey"))!=0 && zKey[0] ){
- u8 iByte;
- int i;
- char zDecoded[40];
- for(i=0, iByte=0; i<sizeof(zDecoded)*2 && sqlite3Isxdigit(zKey[i]); i++){
- iByte = (iByte<<4) + sqlite3HexToInt(zKey[i]);
- if( (i&1)!=0 ) zDecoded[i/2] = iByte;
- }
- sqlite3_key_v2(db, 0, zDecoded, i/2);
- }else if( (zKey = sqlite3_uri_parameter(zOpen, "key"))!=0 ){
- sqlite3_key_v2(db, 0, zKey, sqlite3Strlen30(zKey));
- }
- }
+ if( rc==SQLITE_OK ) sqlite3CodecQueryParameters(db, 0, zOpen);
#endif
sqlite3_free(zOpen);
return rc & 0xff;
}
+
/*
** Open a new database handle.
*/
@@ -157858,6 +158771,8 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
*/
#define FTS3_VARINT_MAX 10
+#define FTS3_BUFFER_PADDING 8
+
/*
** FTS4 virtual tables may maintain multiple indexes - one index of all terms
** in the document set and zero or more prefix indexes. All indexes are stored
@@ -157891,6 +158806,18 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
#define POS_END (0) /* Position-list terminator */
/*
+** The assert_fts3_nc() macro is similar to the assert() macro, except that it
+** is used for assert() conditions that are true only if it can be
+** guranteed that the database is not corrupt.
+*/
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+SQLITE_API extern int sqlite3_fts3_may_be_corrupt;
+# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
+#else
+# define assert_fts3_nc(x) assert(x)
+#endif
+
+/*
** This section provides definitions to allow the
** FTS3 extension to be compiled outside of the
** amalgamation.
@@ -158415,6 +159342,14 @@ SQLITE_PRIVATE int sqlite3Fts3Never(int b) { assert( !b ); return b; }
#endif
/*
+** This variable is set to false when running tests for which the on disk
+** structures should not be corrupt. Otherwise, true. If it is false, extra
+** assert() conditions in the fts3 code are activated - conditions that are
+** only true if it is guaranteed that the fts3 database is not corrupt.
+*/
+SQLITE_API int sqlite3_fts3_may_be_corrupt = 1;
+
+/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
@@ -158432,7 +159367,7 @@ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
}
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
- v = (v & mask1) | ( (*ptr++) << shift ); \
+ v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift ); \
if( (v & mask2)==0 ){ var = v; return ret; }
#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
v = (*ptr++); \
@@ -158470,20 +159405,21 @@ SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
** a non-negative 32-bit integer before it is returned.
*/
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *p, int *pi){
+ const unsigned char *ptr = (const unsigned char*)p;
u32 a;
#ifndef fts3GetVarint32
- GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
+ GETVARINT_INIT(a, ptr, 0, 0x00, 0x80, *pi, 1);
#else
- a = (*p++);
+ a = (*ptr++);
assert( a & 0x80 );
#endif
- GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *pi, 2);
- GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
- GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
+ GETVARINT_STEP(a, ptr, 7, 0x7F, 0x4000, *pi, 2);
+ GETVARINT_STEP(a, ptr, 14, 0x3FFF, 0x200000, *pi, 3);
+ GETVARINT_STEP(a, ptr, 21, 0x1FFFFF, 0x10000000, *pi, 4);
a = (a & 0x0FFFFFFF );
- *pi = (int)(a | ((u32)(*p & 0x07) << 28));
+ *pi = (int)(a | ((u32)(*ptr & 0x07) << 28));
assert( 0==(a & 0x80000000) );
assert( *pi>=0 );
return 5;
@@ -158654,13 +159590,18 @@ static int fts3DestroyMethod(sqlite3_vtab *pVtab){
sqlite3 *db = p->db; /* Database handle */
/* Drop the shadow tables */
- if( p->zContentTbl==0 ){
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
- }
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
+ fts3DbExec(&rc, db,
+ "DROP TABLE IF EXISTS %Q.'%q_segments';"
+ "DROP TABLE IF EXISTS %Q.'%q_segdir';"
+ "DROP TABLE IF EXISTS %Q.'%q_docsize';"
+ "DROP TABLE IF EXISTS %Q.'%q_stat';"
+ "%s DROP TABLE IF EXISTS %Q.'%q_content';",
+ zDb, p->zName,
+ zDb, p->zName,
+ zDb, p->zName,
+ zDb, p->zName,
+ (p->zContentTbl ? "--" : ""), zDb,p->zName
+ );
/* If everything has worked, invoke fts3DisconnectMethod() to free the
** memory associated with the Fts3Table structure and return SQLITE_OK.
@@ -158892,10 +159833,10 @@ static void fts3Appendf(
** memory.
*/
static char *fts3QuoteId(char const *zInput){
- int nRet;
+ sqlite3_int64 nRet;
char *zRet;
nRet = 2 + (int)strlen(zInput)*2 + 1;
- zRet = sqlite3_malloc(nRet);
+ zRet = sqlite3_malloc64(nRet);
if( zRet ){
int i;
char *z = zRet;
@@ -159076,7 +160017,7 @@ static int fts3PrefixParameter(
}
}
- aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
+ aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex);
*apIndex = aIndex;
if( !aIndex ){
return SQLITE_NOMEM;
@@ -159155,7 +160096,7 @@ static int fts3ContentColumns(
if( rc==SQLITE_OK ){
const char **azCol; /* Output array */
- int nStr = 0; /* Size of all column names (incl. 0x00) */
+ sqlite3_int64 nStr = 0; /* Size of all column names (incl. 0x00) */
int nCol; /* Number of table columns */
int i; /* Used to iterate through columns */
@@ -159165,11 +160106,11 @@ static int fts3ContentColumns(
nCol = sqlite3_column_count(pStmt);
for(i=0; i<nCol; i++){
const char *zCol = sqlite3_column_name(pStmt, i);
- nStr += (int)strlen(zCol) + 1;
+ nStr += strlen(zCol) + 1;
}
/* Allocate and populate the array to return. */
- azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
+ azCol = (const char **)sqlite3_malloc64(sizeof(char *) * nCol + nStr);
if( azCol==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -159217,7 +160158,7 @@ static int fts3InitVtab(
Fts3Table *p = 0; /* Pointer to allocated vtab */
int rc = SQLITE_OK; /* Return code */
int i; /* Iterator variable */
- int nByte; /* Size of allocation used for *p */
+ sqlite3_int64 nByte; /* Size of allocation used for *p */
int iCol; /* Column index */
int nString = 0; /* Bytes required to hold all column names */
int nCol = 0; /* Number of columns in the FTS table */
@@ -159251,10 +160192,10 @@ static int fts3InitVtab(
nName = (int)strlen(argv[2]) + 1;
nByte = sizeof(const char *) * (argc-2);
- aCol = (const char **)sqlite3_malloc(nByte);
+ aCol = (const char **)sqlite3_malloc64(nByte);
if( aCol ){
memset((void*)aCol, 0, nByte);
- azNotindexed = (char **)sqlite3_malloc(nByte);
+ azNotindexed = (char **)sqlite3_malloc64(nByte);
}
if( azNotindexed ){
memset(azNotindexed, 0, nByte);
@@ -159449,7 +160390,7 @@ static int fts3InitVtab(
nName + /* zName */
nDb + /* zDb */
nString; /* Space for azColumn strings */
- p = (Fts3Table*)sqlite3_malloc(nByte);
+ p = (Fts3Table*)sqlite3_malloc64(nByte);
if( p==0 ){
rc = SQLITE_NOMEM;
goto fts3_init_out;
@@ -160228,7 +161169,7 @@ static int fts3PutColNumber(char **pp, int iCol){
** updated appropriately. The caller is responsible for insuring
** that there is enough space in *pp to hold the complete output.
*/
-static void fts3PoslistMerge(
+static int fts3PoslistMerge(
char **pp, /* Output buffer */
char **pp1, /* Left input list */
char **pp2 /* Right input list */
@@ -160241,11 +161182,17 @@ static void fts3PoslistMerge(
int iCol1; /* The current column index in pp1 */
int iCol2; /* The current column index in pp2 */
- if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
+ if( *p1==POS_COLUMN ){
+ fts3GetVarint32(&p1[1], &iCol1);
+ if( iCol1==0 ) return FTS_CORRUPT_VTAB;
+ }
else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
else iCol1 = 0;
- if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
+ if( *p2==POS_COLUMN ){
+ fts3GetVarint32(&p2[1], &iCol2);
+ if( iCol2==0 ) return FTS_CORRUPT_VTAB;
+ }
else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
else iCol2 = 0;
@@ -160293,6 +161240,7 @@ static void fts3PoslistMerge(
*pp = p;
*pp1 = p1 + 1;
*pp2 = p2 + 1;
+ return SQLITE_OK;
}
/*
@@ -160357,10 +161305,9 @@ static int fts3PoslistPhraseMerge(
p += sqlite3Fts3PutVarint(p, iCol1);
}
- assert( *p1!=POS_END && *p1!=POS_COLUMN );
- assert( *p2!=POS_END && *p2!=POS_COLUMN );
fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
+ if( iPos1<0 || iPos2<0 ) break;
while( 1 ){
if( iPos2==iPos1+nToken
@@ -160586,6 +161533,7 @@ static int fts3DoclistOrMerge(
char *a2, int n2, /* Second doclist */
char **paOut, int *pnOut /* OUT: Malloc'd doclist */
){
+ int rc = SQLITE_OK;
sqlite3_int64 i1 = 0;
sqlite3_int64 i2 = 0;
sqlite3_int64 iPrev = 0;
@@ -160629,7 +161577,7 @@ static int fts3DoclistOrMerge(
** A symetric argument may be made if the doclists are in descending
** order.
*/
- aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
+ aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
if( !aOut ) return SQLITE_NOMEM;
p = aOut;
@@ -160640,7 +161588,8 @@ static int fts3DoclistOrMerge(
if( p2 && p1 && iDiff==0 ){
fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
- fts3PoslistMerge(&p, &p1, &p2);
+ rc = fts3PoslistMerge(&p, &p1, &p2);
+ if( rc ) break;
fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}else if( !p2 || (p1 && iDiff<0) ){
@@ -160654,10 +161603,16 @@ static int fts3DoclistOrMerge(
}
}
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(aOut);
+ p = aOut = 0;
+ }else{
+ assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 );
+ memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING);
+ }
*paOut = aOut;
*pnOut = (int)(p-aOut);
- assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
- return SQLITE_OK;
+ return rc;
}
/*
@@ -160692,7 +161647,7 @@ static int fts3DoclistPhraseMerge(
assert( nDist>0 );
if( bDescDoclist ){
- aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
+ aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX);
if( aOut==0 ) return SQLITE_NOMEM;
}else{
aOut = aRight;
@@ -160876,6 +161831,7 @@ static int fts3TermSelectMerge(
pTS->anOutput[0] = nDoclist;
if( pTS->aaOutput[0] ){
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
+ memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX);
}else{
return SQLITE_NOMEM;
}
@@ -160927,8 +161883,8 @@ static int fts3SegReaderCursorAppend(
){
if( (pCsr->nSegment%16)==0 ){
Fts3SegReader **apNew;
- int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
- apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
+ sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
+ apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte);
if( !apNew ){
sqlite3Fts3SegReaderFree(pNew);
return SQLITE_NOMEM;
@@ -161934,7 +162890,6 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts3Table *p = (Fts3Table*)pVtab;
UNUSED_PARAMETER(iSavepoint);
assert( p->inTransaction );
- assert( p->mxSavepoint >= iSavepoint );
TESTONLY( p->mxSavepoint = iSavepoint );
sqlite3Fts3PendingTermsClear(p);
return SQLITE_OK;
@@ -162717,9 +163672,10 @@ static int fts3EvalIncrPhraseNext(
if( bEof==0 ){
int nList = 0;
int nByte = a[p->nToken-1].nList;
- char *aDoclist = sqlite3_malloc(nByte+1);
+ char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING);
if( !aDoclist ) return SQLITE_NOMEM;
memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
+ memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);
for(i=0; i<(p->nToken-1); i++){
if( a[i].bIgnore==0 ){
@@ -163110,7 +164066,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
Fts3Expr **apOr;
- aTC = (Fts3TokenAndCost *)sqlite3_malloc(
+ aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr * 2
);
@@ -163421,7 +164377,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
- int nTmp = 0; /* Bytes of temp space */
+ sqlite3_int64 nTmp = 0; /* Bytes of temp space */
char *aTmp; /* Temp space for PoslistNearMerge() */
/* Allocate temporary working space. */
@@ -163430,7 +164386,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
- aTmp = sqlite3_malloc(nTmp*2);
+ aTmp = sqlite3_malloc64(nTmp*2);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
@@ -163700,15 +164656,14 @@ static void fts3EvalRestart(
** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
** expression nodes.
*/
-static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
+static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){
if( pExpr ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pPhrase && pPhrase->doclist.pList ){
int iCol = 0;
char *p = pPhrase->doclist.pList;
- assert( *p );
- while( 1 ){
+ do{
u8 c = 0;
int iCnt = 0;
while( 0xFE & (*p | c) ){
@@ -163724,11 +164679,11 @@ static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
if( *p==0x00 ) break;
p++;
p += fts3GetVarint32(p, &iCol);
- }
+ }while( iCol<nCol );
}
- fts3EvalUpdateCounts(pExpr->pLeft);
- fts3EvalUpdateCounts(pExpr->pRight);
+ fts3EvalUpdateCounts(pExpr->pLeft, nCol);
+ fts3EvalUpdateCounts(pExpr->pRight, nCol);
}
}
@@ -163772,7 +164727,7 @@ static int fts3EvalGatherStats(
for(p=pRoot; p; p=p->pLeft){
Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
assert( pE->aMI==0 );
- pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
+ pE->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32));
if( !pE->aMI ) return SQLITE_NOMEM;
memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
}
@@ -163798,7 +164753,7 @@ static int fts3EvalGatherStats(
);
if( rc==SQLITE_OK && pCsr->isEof==0 ){
- fts3EvalUpdateCounts(pRoot);
+ fts3EvalUpdateCounts(pRoot, pTab->nColumn);
}
}
@@ -164148,7 +165103,7 @@ static int fts3auxConnectMethod(
char const *zFts3; /* Name of fts3 table */
int nDb; /* Result of strlen(zDb) */
int nFts3; /* Result of strlen(zFts3) */
- int nByte; /* Bytes of space to allocate here */
+ sqlite3_int64 nByte; /* Bytes of space to allocate here */
int rc; /* value returned by declare_vtab() */
Fts3auxTable *p; /* Virtual table object to return */
@@ -164180,7 +165135,7 @@ static int fts3auxConnectMethod(
if( rc!=SQLITE_OK ) return rc;
nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
- p = (Fts3auxTable *)sqlite3_malloc(nByte);
+ p = (Fts3auxTable *)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, nByte);
@@ -164330,7 +165285,7 @@ static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){
static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
if( nSize>pCsr->nStat ){
struct Fts3auxColstats *aNew;
- aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
+ aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat,
sizeof(struct Fts3auxColstats) * nSize
);
if( aNew==0 ) return SQLITE_NOMEM;
@@ -164498,15 +165453,15 @@ static int fts3auxFilterMethod(
assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
if( zStr ){
pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
- pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
+ pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm);
}
}
if( iLe>=0 ){
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
- pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
+ pCsr->nStop = (int)strlen(pCsr->zStop);
}
if( iLangid>=0 ){
@@ -164758,8 +165713,8 @@ static int fts3isspace(char c){
** zero the memory before returning a pointer to it. If unsuccessful,
** return NULL.
*/
-static void *fts3MallocZero(int nByte){
- void *pRet = sqlite3_malloc(nByte);
+static void *fts3MallocZero(sqlite3_int64 nByte){
+ void *pRet = sqlite3_malloc64(nByte);
if( pRet ) memset(pRet, 0, nByte);
return pRet;
}
@@ -164834,7 +165789,7 @@ static int getNextToken(
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
- int nByte; /* total space to allocate */
+ sqlite3_int64 nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
@@ -164888,8 +165843,8 @@ static int getNextToken(
** Enlarge a memory allocation. If an out-of-memory allocation occurs,
** then free the old allocation.
*/
-static void *fts3ReallocOrFree(void *pOrig, int nNew){
- void *pRet = sqlite3_realloc(pOrig, nNew);
+static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){
+ void *pRet = sqlite3_realloc64(pOrig, nNew);
if( !pRet ){
sqlite3_free(pOrig);
}
@@ -165133,7 +166088,6 @@ static int getNextNode(
int nConsumed = 0;
pParse->nNest++;
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
- if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
return rc;
}else if( *zInput==')' ){
@@ -165432,7 +166386,7 @@ static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
if( rc==SQLITE_OK ){
if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
Fts3Expr **apLeaf;
- apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
+ apLeaf = (Fts3Expr **)sqlite3_malloc64(sizeof(Fts3Expr *) * nMaxDepth);
if( 0==apLeaf ){
rc = SQLITE_NOMEM;
}else{
@@ -165852,7 +166806,7 @@ static void fts3ExprTestCommon(
zExpr = (const char *)sqlite3_value_text(argv[1]);
nExpr = sqlite3_value_bytes(argv[1]);
nCol = argc-2;
- azCol = (char **)sqlite3_malloc(nCol*sizeof(char *));
+ azCol = (char **)sqlite3_malloc64(nCol*sizeof(char *));
if( !azCol ){
sqlite3_result_error_nomem(context);
goto exprtest_out;
@@ -165966,8 +166920,8 @@ SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash
/*
** Malloc and Free functions
*/
-static void *fts3HashMalloc(int n){
- void *p = sqlite3_malloc(n);
+static void *fts3HashMalloc(sqlite3_int64 n){
+ void *p = sqlite3_malloc64(n);
if( p ){
memset(p, 0, n);
}
@@ -167860,7 +168814,7 @@ static int fts3tokDequoteArray(
nByte += (int)(strlen(argv[i]) + 1);
}
- *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
+ *pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
if( azDequote==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -168763,7 +169717,7 @@ static sqlite3_int64 getAbsoluteLevel(
int iLevel /* Level of segments */
){
sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
- assert( iLangid>=0 );
+ assert_fts3_nc( iLangid>=0 );
assert( p->nIndex>0 );
assert( iIndex>=0 && iIndex<p->nIndex );
@@ -169605,7 +170559,7 @@ static int fts3SegReaderNext(
** b-tree node. And that the final byte of the doclist is 0x00. If either
** of these statements is untrue, then the data structure is corrupt.
*/
- if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist
+ if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode)
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
){
return FTS_CORRUPT_VTAB;
@@ -169805,8 +170759,13 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
Fts3SegReader *pReader; /* Newly allocated SegReader object */
int nExtra = 0; /* Bytes to allocate segment root node */
- assert( iStartLeaf<=iEndLeaf );
+ assert( zRoot!=0 || nRoot==0 );
+#ifdef CORRUPT_DB
+ assert( zRoot!=0 || CORRUPT_DB );
+#endif
+
if( iStartLeaf==0 ){
+ if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB;
nExtra = nRoot + FTS3_NODE_PADDING;
}
@@ -169826,7 +170785,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
pReader->aNode = (char *)&pReader[1];
pReader->rootOnly = 1;
pReader->nNode = nRoot;
- memcpy(pReader->aNode, zRoot, nRoot);
+ if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot);
memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
}else{
pReader->iCurrentBlock = iStartLeaf-1;
@@ -170446,6 +171405,11 @@ static int fts3SegWriterAdd(
nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
+ /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
+ ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
+ ** compared with BINARY collation. This indicates corruption. */
+ if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
+
/* Figure out how many bytes are required by this new entry */
nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */
sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */
@@ -171153,7 +172117,9 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
}else{
iDelta = iDocid - iPrev;
}
- assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
+ if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){
+ return FTS_CORRUPT_VTAB;
+ }
assert( nDoclist>0 || iDelta==iDocid );
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
@@ -171519,14 +172485,16 @@ static void fts3DecodeIntArray(
const char *zBuf, /* The BLOB containing the varints */
int nBuf /* size of the BLOB */
){
- int i, j;
- UNUSED_PARAMETER(nBuf);
- for(i=j=0; i<N; i++){
- sqlite3_int64 x;
- j += sqlite3Fts3GetVarint(&zBuf[j], &x);
- assert(j<=nBuf);
- a[i] = (u32)(x & 0xffffffff);
+ int i = 0;
+ if( nBuf && (zBuf[nBuf-1]&0x80)==0 ){
+ int j;
+ for(i=j=0; i<N && j<nBuf; i++){
+ sqlite3_int64 x;
+ j += sqlite3Fts3GetVarint(&zBuf[j], &x);
+ a[i] = (u32)(x & 0xffffffff);
+ }
}
+ while( i<N ) a[i++] = 0;
}
/*
@@ -171932,7 +172900,7 @@ static int nodeReaderNext(NodeReader *p){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
if( rc==SQLITE_OK ){
@@ -171942,7 +172910,7 @@ static int nodeReaderNext(NodeReader *p){
if( p->iChild==0 ){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
if( (p->nNode-p->iOff)<p->nDoclist ){
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
p->aDoclist = &p->aNode[p->iOff];
p->iOff += p->nDoclist;
@@ -174072,7 +175040,7 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
aOut = &p->aMatchinfo[p->nElem+2];
xRet = fts3MIBufferFree;
}else{
- aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32));
+ aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
if( aOut ){
xRet = sqlite3_free;
if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
@@ -174327,7 +175295,8 @@ static void fts3SnippetDetails(
int j;
u64 mPhrase = (u64)1 << i;
u64 mPos = (u64)1 << (iCsr - iStart);
- assert( iCsr>=iStart );
+ assert( iCsr>=iStart && (iCsr - iStart)<=64 );
+ assert( i>=0 && i<=64 );
if( (mCover|mCovered)&mPhrase ){
iScore++;
}else{
@@ -174369,11 +175338,14 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
int iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
- assert( iFirst>=0 );
- pPhrase->pHead = pCsr;
- pPhrase->pTail = pCsr;
- pPhrase->iHead = iFirst;
- pPhrase->iTail = iFirst;
+ if( iFirst<0 ){
+ rc = FTS_CORRUPT_VTAB;
+ }else{
+ pPhrase->pHead = pCsr;
+ pPhrase->pTail = pCsr;
+ pPhrase->iHead = iFirst;
+ pPhrase->iTail = iFirst;
+ }
}else{
assert( rc!=SQLITE_OK || (
pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0
@@ -174410,7 +175382,7 @@ static int fts3BestSnippet(
int rc; /* Return Code */
int nList; /* Number of phrases in expression */
SnippetIter sIter; /* Iterates through snippet candidates */
- int nByte; /* Number of bytes of space to allocate */
+ sqlite3_int64 nByte; /* Number of bytes of space to allocate */
int iBestScore = -1; /* Best snippet score found so far */
int i; /* Loop counter */
@@ -174428,7 +175400,7 @@ static int fts3BestSnippet(
** the required space using malloc().
*/
nByte = sizeof(SnippetPhrase) * nList;
- sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
+ sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc64(nByte);
if( !sIter.aPhrase ){
return SQLITE_NOMEM;
}
@@ -174498,8 +175470,8 @@ static int fts3StringAppend(
** appended data.
*/
if( pStr->n+nAppend+1>=pStr->nAlloc ){
- int nAlloc = pStr->nAlloc+nAppend+100;
- char *zNew = sqlite3_realloc(pStr->z, nAlloc);
+ sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
+ char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
if( !zNew ){
return SQLITE_NOMEM;
}
@@ -174554,6 +175526,7 @@ static int fts3SnippetShift(
for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
+ assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 );
nDesired = (nLeft-nRight)/2;
/* Ideally, the start of the snippet should be pushed forward in the
@@ -174746,7 +175719,7 @@ static int fts3ColumnlistCount(char **ppCollist){
/*
** This function gathers 'y' or 'b' data for a single phrase.
*/
-static void fts3ExprLHits(
+static int fts3ExprLHits(
Fts3Expr *pExpr, /* Phrase expression node */
MatchInfo *p /* Matchinfo context */
){
@@ -174776,25 +175749,29 @@ static void fts3ExprLHits(
if( *pIter!=0x01 ) break;
pIter++;
pIter += fts3GetVarint32(pIter, &iCol);
+ if( iCol>=p->nCol ) return FTS_CORRUPT_VTAB;
}
+ return SQLITE_OK;
}
/*
** Gather the results for matchinfo directives 'y' and 'b'.
*/
-static void fts3ExprLHitGather(
+static int fts3ExprLHitGather(
Fts3Expr *pExpr,
MatchInfo *p
){
+ int rc = SQLITE_OK;
assert( (pExpr->pLeft==0)==(pExpr->pRight==0) );
if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
if( pExpr->pLeft ){
- fts3ExprLHitGather(pExpr->pLeft, p);
- fts3ExprLHitGather(pExpr->pRight, p);
+ rc = fts3ExprLHitGather(pExpr->pLeft, p);
+ if( rc==SQLITE_OK ) rc = fts3ExprLHitGather(pExpr->pRight, p);
}else{
- fts3ExprLHits(pExpr, p);
+ rc = fts3ExprLHits(pExpr, p);
}
}
+ return rc;
}
/*
@@ -175011,11 +175988,12 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
int i;
int iCol;
int nToken = 0;
+ int rc = SQLITE_OK;
/* Allocate and populate the array of LcsIterator objects. The array
** contains one element for each matchable phrase in the query.
**/
- aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
+ aIter = sqlite3_malloc64(sizeof(LcsIterator) * pCsr->nPhrase);
if( !aIter ) return SQLITE_NOMEM;
memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
@@ -175031,13 +176009,16 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
int nLive = 0; /* Number of iterators in aIter not at EOF */
for(i=0; i<pInfo->nPhrase; i++){
- int rc;
LcsIterator *pIt = &aIter[i];
rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead);
- if( rc!=SQLITE_OK ) return rc;
+ if( rc!=SQLITE_OK ) goto matchinfo_lcs_out;
if( pIt->pRead ){
pIt->iPos = pIt->iPosOffset;
- fts3LcsIteratorAdvance(&aIter[i]);
+ fts3LcsIteratorAdvance(pIt);
+ if( pIt->pRead==0 ){
+ rc = FTS_CORRUPT_VTAB;
+ goto matchinfo_lcs_out;
+ }
nLive++;
}
}
@@ -175069,8 +176050,9 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
pInfo->aMatchinfo[iCol] = nLcs;
}
+ matchinfo_lcs_out:
sqlite3_free(aIter);
- return SQLITE_OK;
+ return rc;
}
/*
@@ -175166,7 +176148,7 @@ static int fts3MatchinfoValues(
case FTS3_MATCHINFO_LHITS: {
int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
memset(pInfo->aMatchinfo, 0, nZero);
- fts3ExprLHitGather(pCsr->pExpr, pInfo);
+ rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
break;
}
@@ -175318,6 +176300,10 @@ SQLITE_PRIVATE void sqlite3Fts3Snippet(
return;
}
+ /* Limit the snippet length to 64 tokens. */
+ if( nToken<-64 ) nToken = -64;
+ if( nToken>+64 ) nToken = +64;
+
for(nSnippet=1; 1; nSnippet++){
int iSnip; /* Loop counter 0..nSnippet-1 */
@@ -175460,7 +176446,7 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
if( rc!=SQLITE_OK ) goto offsets_out;
/* Allocate the array of TermOffset iterators. */
- sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
+ sCtx.aTerm = (TermOffset *)sqlite3_malloc64(sizeof(TermOffset)*nToken);
if( 0==sCtx.aTerm ){
rc = SQLITE_NOMEM;
goto offsets_out;
@@ -175685,7 +176671,7 @@ typedef struct unicode_cursor unicode_cursor;
struct unicode_tokenizer {
sqlite3_tokenizer base;
- int bRemoveDiacritic;
+ int eRemoveDiacritic;
int nException;
int *aiException;
};
@@ -175758,7 +176744,7 @@ static int unicodeAddExceptions(
int *aNew; /* New aiException[] array */
int nNew; /* Number of valid entries in array aNew[] */
- aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
+ aNew = sqlite3_realloc64(p->aiException,(p->nException+nEntry)*sizeof(int));
if( aNew==0 ) return SQLITE_NOMEM;
nNew = p->nException;
@@ -175830,17 +176816,20 @@ static int unicodeCreate(
pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
if( pNew==NULL ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(unicode_tokenizer));
- pNew->bRemoveDiacritic = 1;
+ pNew->eRemoveDiacritic = 1;
for(i=0; rc==SQLITE_OK && i<nArg; i++){
const char *z = azArg[i];
int n = (int)strlen(z);
if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
- pNew->bRemoveDiacritic = 1;
+ pNew->eRemoveDiacritic = 1;
}
else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
- pNew->bRemoveDiacritic = 0;
+ pNew->eRemoveDiacritic = 0;
+ }
+ else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){
+ pNew->eRemoveDiacritic = 2;
}
else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
@@ -175944,7 +176933,7 @@ static int unicodeNext(
/* Grow the output buffer if required. */
if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
- char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
+ char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64);
if( !zNew ) return SQLITE_NOMEM;
zOut = &zNew[zOut - pCsr->zToken];
pCsr->zToken = zNew;
@@ -175953,7 +176942,7 @@ static int unicodeNext(
/* Write the folded case of the last character read to the output */
zEnd = z;
- iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
+ iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic);
if( iOut ){
WRITE_UTF8(zOut, iOut);
}
@@ -175998,7 +176987,7 @@ SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const *
/************** End of fts3_unicode.c ****************************************/
/************** Begin file fts3_unicode2.c ***********************************/
/*
-** 2012 May 25
+** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -176158,32 +177147,48 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
-static int remove_diacritic(int c){
+static int remove_diacritic(int c, int bComplex){
unsigned short aDia[] = {
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
- 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
- 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
- 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
- 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
- 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
- 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
- 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
- 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
- 62924, 63050, 63082, 63274, 63390,
+ 3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
+ 3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
+ 4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
+ 4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
+ 6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
+ 61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
+ 61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
+ 61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
+ 62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
+ 62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
+ 62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
+ 63182, 63242, 63274, 63310, 63368, 63390,
};
- char aChar[] = {
- '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
- 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
- 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
- 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
- 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
- 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
- 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
- 'e', 'i', 'o', 'u', 'y',
+#define HIBIT ((unsigned char)0x80)
+ unsigned char aChar[] = {
+ '\0', 'a', 'c', 'e', 'i', 'n',
+ 'o', 'u', 'y', 'y', 'a', 'c',
+ 'd', 'e', 'e', 'g', 'h', 'i',
+ 'j', 'k', 'l', 'n', 'o', 'r',
+ 's', 't', 'u', 'u', 'w', 'y',
+ 'z', 'o', 'u', 'a', 'i', 'o',
+ 'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
+ 'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
+ 'e', 'i', 'o', 'r', 'u', 's',
+ 't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
+ 'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', 'a', 'b',
+ 'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
+ 'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
+ 'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
+ 'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
+ 's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
+ 'w', 'x', 'y', 'z', 'h', 't',
+ 'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
+ 'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
+ 'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
@@ -176200,7 +177205,8 @@ static int remove_diacritic(int c){
}
}
assert( key>=aDia[iRes] );
- return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
+ if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
+ return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
}
@@ -176213,8 +177219,8 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int c){
unsigned int mask1 = 0x000361F8;
if( c<768 || c>817 ) return 0;
return (c < 768+32) ?
- (mask0 & (1 << (c-768))) :
- (mask1 & (1 << (c-768-32)));
+ (mask0 & ((unsigned int)1 << (c-768))) :
+ (mask1 & ((unsigned int)1 << (c-768-32)));
}
@@ -176227,7 +177233,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int c){
** The results are undefined if the value passed to this function
** is less than zero.
*/
-SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
+SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
/* Each entry in the following array defines a rule for folding a range
** of codepoints to lower case. The rule applies to a range of nRange
** codepoints starting at codepoint iCode.
@@ -176350,7 +177356,9 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
assert( ret>0 );
}
- if( bRemoveDiacritic ) ret = remove_diacritic(ret);
+ if( eRemoveDiacritic ){
+ ret = remove_diacritic(ret, eRemoveDiacritic==2);
+ }
}
else if( c>=66560 && c<66600 ){
@@ -177057,7 +178065,7 @@ static JSON_NOINLINE int jsonParseAddNodeExpand(
assert( pParse->nNode>=pParse->nAlloc );
if( pParse->oom ) return -1;
nNew = pParse->nAlloc*2 + 10;
- pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
+ pNew = sqlite3_realloc64(pParse->aNode, sizeof(JsonNode)*nNew);
if( pNew==0 ){
pParse->oom = 1;
return -1;
@@ -177331,7 +178339,7 @@ static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
static int jsonParseFindParents(JsonParse *pParse){
u32 *aUp;
assert( pParse->aUp==0 );
- aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode );
+ aUp = pParse->aUp = sqlite3_malloc64( sizeof(u32)*pParse->nNode );
if( aUp==0 ){
pParse->oom = 1;
return SQLITE_NOMEM;
@@ -177393,7 +178401,7 @@ static JsonParse *jsonParseCached(
pMatch->iHold = iMaxHold+1;
return pMatch;
}
- p = sqlite3_malloc( sizeof(*p) + nJson + 1 );
+ p = sqlite3_malloc64( sizeof(*p) + nJson + 1 );
if( p==0 ){
sqlite3_result_error_nomem(pCtx);
return 0;
@@ -179038,6 +180046,9 @@ struct Rtree {
u8 inWrTrans; /* True if inside write transaction */
u8 nAux; /* # of auxiliary columns in %_rowid */
u8 nAuxNotNull; /* Number of initial not-null aux columns */
+#ifdef SQLITE_DEBUG
+ u8 bCorrupt; /* Shadow table corruption detected */
+#endif
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
char *zName; /* Name of r-tree table */
@@ -179098,6 +180109,15 @@ struct Rtree {
#endif
/*
+** Set the Rtree.bCorrupt flag
+*/
+#ifdef SQLITE_DEBUG
+# define RTREE_IS_CORRUPT(X) ((X)->bCorrupt = 1)
+#else
+# define RTREE_IS_CORRUPT(X)
+#endif
+
+/*
** When doing a search of an r-tree, instances of the following structure
** record intermediate results from the tree walk.
**
@@ -179463,8 +180483,8 @@ static void nodeZero(Rtree *pRtree, RtreeNode *p){
** Given a node number iNode, return the corresponding key to use
** in the Rtree.aHash table.
*/
-static int nodeHash(i64 iNode){
- return iNode % HASHSIZE;
+static unsigned int nodeHash(i64 iNode){
+ return ((unsigned)iNode) % HASHSIZE;
}
/*
@@ -179509,7 +180529,7 @@ static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){
*/
static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
RtreeNode *pNode;
- pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize);
+ pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode) + pRtree->iNodeSize);
if( pNode ){
memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
pNode->zData = (u8 *)&pNode[1];
@@ -179534,6 +180554,18 @@ static void nodeBlobReset(Rtree *pRtree){
}
/*
+** Check to see if pNode is the same as pParent or any of the parents
+** of pParent.
+*/
+static int nodeInParentChain(const RtreeNode *pNode, const RtreeNode *pParent){
+ do{
+ if( pNode==pParent ) return 1;
+ pParent = pParent->pParent;
+ }while( pParent );
+ return 0;
+}
+
+/*
** Obtain a reference to an r-tree node.
*/
static int nodeAcquire(
@@ -179551,6 +180583,10 @@ static int nodeAcquire(
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
if( pParent && !pNode->pParent ){
+ if( nodeInParentChain(pNode, pParent) ){
+ RTREE_IS_CORRUPT(pRtree);
+ return SQLITE_CORRUPT_VTAB;
+ }
pParent->nRef++;
pNode->pParent = pParent;
}
@@ -179581,9 +180617,12 @@ static int nodeAcquire(
*ppNode = 0;
/* If unable to open an sqlite3_blob on the desired row, that can only
** be because the shadow tables hold erroneous data. */
- if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB;
+ if( rc==SQLITE_ERROR ){
+ rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
+ }
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
- pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
+ pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
if( !pNode ){
rc = SQLITE_NOMEM;
}else{
@@ -179596,7 +180635,6 @@ static int nodeAcquire(
pNode->pNext = 0;
rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
pRtree->iNodeSize, 0);
- nodeReference(pParent);
}
}
@@ -179610,6 +180648,7 @@ static int nodeAcquire(
pRtree->iDepth = readInt16(pNode->zData);
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
}
}
@@ -179620,14 +180659,17 @@ static int nodeAcquire(
if( pNode && rc==SQLITE_OK ){
if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
}
}
if( rc==SQLITE_OK ){
if( pNode!=0 ){
+ nodeReference(pParent);
nodeHashInsert(pRtree, pNode);
}else{
rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
}
*ppNode = pNode;
}else{
@@ -179853,7 +180895,7 @@ static void rtreeRelease(Rtree *pRtree){
pRtree->inWrTrans = 0;
assert( pRtree->nCursor==0 );
nodeBlobReset(pRtree);
- assert( pRtree->nNodeRef==0 );
+ assert( pRtree->nNodeRef==0 || pRtree->bCorrupt );
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
sqlite3_finalize(pRtree->pReadRowid);
@@ -179912,7 +180954,7 @@ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
Rtree *pRtree = (Rtree *)pVTab;
RtreeCursor *pCsr;
- pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
+ pCsr = (RtreeCursor *)sqlite3_malloc64(sizeof(RtreeCursor));
if( pCsr ){
memset(pCsr, 0, sizeof(RtreeCursor));
pCsr->base.pVtab = pVTab;
@@ -180185,6 +181227,7 @@ static int nodeRowidIndex(
return SQLITE_OK;
}
}
+ RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -180278,7 +181321,7 @@ static RtreeSearchPoint *rtreeEnqueue(
RtreeSearchPoint *pNew;
if( pCur->nPoint>=pCur->nPointAlloc ){
int nNew = pCur->nPointAlloc*2 + 8;
- pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
+ pNew = sqlite3_realloc64(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
if( pNew==0 ) return 0;
pCur->aPoint = pNew;
pCur->nPointAlloc = nNew;
@@ -180680,7 +181723,7 @@ static int rtreeFilter(
*/
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
if( rc==SQLITE_OK && argc>0 ){
- pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
+ pCsr->aConstraint = sqlite3_malloc64(sizeof(RtreeConstraint)*argc);
pCsr->nConstraint = argc;
if( !pCsr->aConstraint ){
rc = SQLITE_NOMEM;
@@ -180825,20 +181868,20 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
){
u8 op;
switch( p->op ){
- case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
- case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
- case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
- case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
- case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
- default:
- assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
- op = RTREE_MATCH;
- break;
+ case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
+ case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
+ case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
+ case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
+ case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
+ case SQLITE_INDEX_CONSTRAINT_MATCH: op = RTREE_MATCH; break;
+ default: op = 0; break;
+ }
+ if( op ){
+ zIdxStr[iIdx++] = op;
+ zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
+ pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
+ pIdxInfo->aConstraintUsage[ii].omit = 1;
}
- zIdxStr[iIdx++] = op;
- zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
- pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
- pIdxInfo->aConstraintUsage[ii].omit = 1;
}
}
@@ -180874,11 +181917,11 @@ static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
#endif
{
switch( pRtree->nDim ){
- case 5: area = p->aCoord[9].i - p->aCoord[8].i;
- case 4: area *= p->aCoord[7].i - p->aCoord[6].i;
- case 3: area *= p->aCoord[5].i - p->aCoord[4].i;
- case 2: area *= p->aCoord[3].i - p->aCoord[2].i;
- default: area *= p->aCoord[1].i - p->aCoord[0].i;
+ case 5: area = (i64)p->aCoord[9].i - (i64)p->aCoord[8].i;
+ case 4: area *= (i64)p->aCoord[7].i - (i64)p->aCoord[6].i;
+ case 3: area *= (i64)p->aCoord[5].i - (i64)p->aCoord[4].i;
+ case 2: area *= (i64)p->aCoord[3].i - (i64)p->aCoord[2].i;
+ default: area *= (i64)p->aCoord[1].i - (i64)p->aCoord[0].i;
}
}
return area;
@@ -181047,12 +182090,14 @@ static int AdjustTree(
RtreeCell *pCell /* This cell was just inserted */
){
RtreeNode *p = pNode;
+ int cnt = 0;
while( p->pParent ){
RtreeNode *pParent = p->pParent;
RtreeCell cell;
int iCell;
- if( nodeParentIndex(pRtree, p, &iCell) ){
+ if( (++cnt)>1000 || nodeParentIndex(pRtree, p, &iCell) ){
+ RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -181249,9 +182294,9 @@ static int splitNodeStartree(
int iBestSplit = 0;
RtreeDValue fBestMargin = RTREE_ZERO;
- int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
+ sqlite3_int64 nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
- aaSorted = (int **)sqlite3_malloc(nByte);
+ aaSorted = (int **)sqlite3_malloc64(nByte);
if( !aaSorted ){
return SQLITE_NOMEM;
}
@@ -181372,7 +182417,7 @@ static int SplitNode(
/* Allocate an array and populate it with a copy of pCell and
** all cells from node pLeft. Then zero the original node.
*/
- aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
+ aCell = sqlite3_malloc64((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
if( !aCell ){
rc = SQLITE_NOMEM;
goto splitnode_out;
@@ -181520,7 +182565,10 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
}
rc = sqlite3_reset(pRtree->pReadParent);
if( rc==SQLITE_OK ) rc = rc2;
- if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
+ if( rc==SQLITE_OK && !pChild->pParent ){
+ RTREE_IS_CORRUPT(pRtree);
+ rc = SQLITE_CORRUPT_VTAB;
+ }
pChild = pChild->pParent;
}
return rc;
@@ -181660,7 +182708,7 @@ static int Reinsert(
/* Allocate the buffers used by this operation. The allocation is
** relinquished before this function returns.
*/
- aCell = (RtreeCell *)sqlite3_malloc(n * (
+ aCell = (RtreeCell *)sqlite3_malloc64(n * (
sizeof(RtreeCell) + /* aCell array */
sizeof(int) + /* aOrder array */
sizeof(int) + /* aSpare array */
@@ -181834,8 +182882,12 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
rc = findLeafNode(pRtree, iDelete, &pLeaf, 0);
}
+#ifdef CORRUPT_DB
+ assert( pLeaf!=0 || rc!=SQLITE_OK || CORRUPT_DB );
+#endif
+
/* Delete the cell in question from the leaf node. */
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && pLeaf ){
int rc2;
rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
if( rc==SQLITE_OK ){
@@ -182107,7 +183159,7 @@ static int rtreeUpdate(
rc = rc2;
}
}
- if( pRtree->nAux ){
+ if( rc==SQLITE_OK && pRtree->nAux ){
sqlite3_stmt *pUp = pRtree->pWriteAux;
int jj;
sqlite3_bind_int64(pUp, 1, *pRowid);
@@ -182468,6 +183520,7 @@ static int getNodeSize(
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else if( pRtree->iNodeSize<(512-64) ){
rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
*pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
pRtree->zName);
}
@@ -182523,7 +183576,7 @@ static int rtreeInit(
/* Allocate the sqlite3_vtab structure */
nDb = (int)strlen(argv[1]);
nName = (int)strlen(argv[2]);
- pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
+ pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2);
if( !pRtree ){
return SQLITE_NOMEM;
}
@@ -182791,8 +183844,7 @@ static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
u8 *pRet = 0; /* Return value */
- assert( pCheck->rc==SQLITE_OK );
- if( pCheck->pGetNode==0 ){
+ if( pCheck->rc==SQLITE_OK && pCheck->pGetNode==0 ){
pCheck->pGetNode = rtreeCheckPrepare(pCheck,
"SELECT data FROM %Q.'%q_node' WHERE nodeno=?",
pCheck->zDb, pCheck->zTab
@@ -182804,7 +183856,7 @@ static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){
int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0);
const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0);
- pRet = sqlite3_malloc(nNode);
+ pRet = sqlite3_malloc64(nNode);
if( pRet==0 ){
pCheck->rc = SQLITE_NOMEM;
}else{
@@ -183283,6 +184335,14 @@ struct GeoPoly {
*/
#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))
+/* Macros to access coordinates of a GeoPoly.
+** We have to use these macros, rather than just say p->a[i] in order
+** to silence (incorrect) UBSAN warnings if the array index is too large.
+*/
+#define GeoX(P,I) (((GeoCoord*)(P)->a)[(I)*2])
+#define GeoY(P,I) (((GeoCoord*)(P)->a)[(I)*2+1])
+
+
/*
** State of a parse of a GeoJSON input.
*/
@@ -183475,8 +184535,9 @@ static GeoPoly *geopolyFuncParam(
memcpy(p->hdr, a, nByte);
if( a[0] != *(unsigned char*)&x ){
int ii;
- for(ii=0; ii<nVertex*2; ii++){
- geopolySwab32((unsigned char*)&p->a[ii]);
+ for(ii=0; ii<nVertex; ii++){
+ geopolySwab32((unsigned char*)&GeoX(p,ii));
+ geopolySwab32((unsigned char*)&GeoY(p,ii));
}
p->hdr[0] ^= 1;
}
@@ -183535,9 +184596,9 @@ static void geopolyJsonFunc(
int i;
sqlite3_str_append(x, "[", 1);
for(i=0; i<p->nVertex; i++){
- sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]);
+ sqlite3_str_appendf(x, "[%!g,%!g],", GeoX(p,i), GeoY(p,i));
}
- sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]);
+ sqlite3_str_appendf(x, "[%!g,%!g]]", GeoX(p,0), GeoY(p,0));
sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free);
sqlite3_free(p);
}
@@ -183554,7 +184615,9 @@ static void geopolySvgFunc(
int argc,
sqlite3_value **argv
){
- GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ GeoPoly *p;
+ if( argc<1 ) return;
+ p = geopolyFuncParam(context, argv[0], 0);
if( p ){
sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_str *x = sqlite3_str_new(db);
@@ -183562,10 +184625,10 @@ static void geopolySvgFunc(
char cSep = '\'';
sqlite3_str_appendf(x, "<polyline points=");
for(i=0; i<p->nVertex; i++){
- sqlite3_str_appendf(x, "%c%g,%g", cSep, p->a[i*2], p->a[i*2+1]);
+ sqlite3_str_appendf(x, "%c%g,%g", cSep, GeoX(p,i), GeoY(p,i));
cSep = ' ';
}
- sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]);
+ sqlite3_str_appendf(x, " %g,%g'", GeoX(p,0), GeoY(p,0));
for(i=1; i<argc; i++){
const char *z = (const char*)sqlite3_value_text(argv[i]);
if( z && z[0] ){
@@ -183610,12 +184673,12 @@ static void geopolyXformFunc(
int ii;
if( p ){
for(ii=0; ii<p->nVertex; ii++){
- x0 = p->a[ii*2];
- y0 = p->a[ii*2+1];
+ x0 = GeoX(p,ii);
+ y0 = GeoY(p,ii);
x1 = (GeoCoord)(A*x0 + B*y0 + E);
y1 = (GeoCoord)(C*x0 + D*y0 + F);
- p->a[ii*2] = x1;
- p->a[ii*2+1] = y1;
+ GeoX(p,ii) = x1;
+ GeoY(p,ii) = y1;
}
sqlite3_result_blob(context, p->hdr,
4+8*p->nVertex, SQLITE_TRANSIENT);
@@ -183634,12 +184697,12 @@ static double geopolyArea(GeoPoly *p){
double rArea = 0.0;
int ii;
for(ii=0; ii<p->nVertex-1; ii++){
- rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
- * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
+ rArea += (GeoX(p,ii) - GeoX(p,ii+1)) /* (x0 - x1) */
+ * (GeoY(p,ii) + GeoY(p,ii+1)) /* (y0 + y1) */
* 0.5;
}
- rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
- * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
+ rArea += (GeoX(p,ii) - GeoX(p,0)) /* (xN - x0) */
+ * (GeoY(p,ii) + GeoY(p,0)) /* (yN + y0) */
* 0.5;
return rArea;
}
@@ -183686,13 +184749,13 @@ static void geopolyCcwFunc(
if( p ){
if( geopolyArea(p)<0.0 ){
int ii, jj;
- for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){
- GeoCoord t = p->a[ii];
- p->a[ii] = p->a[jj];
- p->a[jj] = t;
- t = p->a[ii+1];
- p->a[ii+1] = p->a[jj+1];
- p->a[jj+1] = t;
+ for(ii=1, jj=p->nVertex-1; ii<jj; ii++, jj--){
+ GeoCoord t = GeoX(p,ii);
+ GeoX(p,ii) = GeoX(p,jj);
+ GeoX(p,jj) = t;
+ t = GeoY(p,ii);
+ GeoY(p,ii) = GeoY(p,jj);
+ GeoY(p,jj) = t;
}
}
sqlite3_result_blob(context, p->hdr,
@@ -183752,8 +184815,8 @@ static void geopolyRegularFunc(
p->hdr[3] = n&0xff;
for(i=0; i<n; i++){
double rAngle = 2.0*GEOPOLY_PI*i/n;
- p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
- p->a[i*2+1] = y + r*geopolySine(rAngle);
+ GeoX(p,i) = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
+ GeoY(p,i) = y + r*geopolySine(rAngle);
}
sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
sqlite3_free(p);
@@ -183790,13 +184853,13 @@ static GeoPoly *geopolyBBox(
}
if( p ){
int ii;
- mnX = mxX = p->a[0];
- mnY = mxY = p->a[1];
+ mnX = mxX = GeoX(p,0);
+ mnY = mxY = GeoY(p,0);
for(ii=1; ii<p->nVertex; ii++){
- double r = p->a[ii*2];
+ double r = GeoX(p,ii);
if( r<mnX ) mnX = (float)r;
else if( r>mxX ) mxX = (float)r;
- r = p->a[ii*2+1];
+ r = GeoY(p,ii);
if( r<mnY ) mnY = (float)r;
else if( r>mxY ) mxY = (float)r;
}
@@ -183816,14 +184879,14 @@ static GeoPoly *geopolyBBox(
pOut->hdr[1] = 0;
pOut->hdr[2] = 0;
pOut->hdr[3] = 4;
- pOut->a[0] = mnX;
- pOut->a[1] = mnY;
- pOut->a[2] = mxX;
- pOut->a[3] = mnY;
- pOut->a[4] = mxX;
- pOut->a[5] = mxY;
- pOut->a[6] = mnX;
- pOut->a[7] = mxY;
+ GeoX(pOut,0) = mnX;
+ GeoY(pOut,0) = mnY;
+ GeoX(pOut,1) = mxX;
+ GeoY(pOut,1) = mnY;
+ GeoX(pOut,2) = mxX;
+ GeoY(pOut,2) = mxY;
+ GeoX(pOut,3) = mnX;
+ GeoY(pOut,3) = mxY;
}else{
sqlite3_free(p);
aCoord[0].f = mnX;
@@ -183961,14 +185024,14 @@ static void geopolyContainsPointFunc(
int ii;
if( p1==0 ) return;
for(ii=0; ii<p1->nVertex-1; ii++){
- v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
- p1->a[ii*2+2],p1->a[ii*2+3]);
+ v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii),
+ GeoX(p1,ii+1),GeoY(p1,ii+1));
if( v==2 ) break;
cnt += v;
}
if( v!=2 ){
- v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
- p1->a[0],p1->a[1]);
+ v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii),
+ GeoX(p1,0), GeoY(p1,0));
}
if( v==2 ){
sqlite3_result_int(context, 1);
@@ -184090,10 +185153,10 @@ static void geopolyAddSegments(
unsigned int i;
GeoCoord *x;
for(i=0; i<(unsigned)pPoly->nVertex-1; i++){
- x = pPoly->a + (i*2);
+ x = &GeoX(pPoly,i);
geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i);
}
- x = pPoly->a + (i*2);
+ x = &GeoX(pPoly,i);
geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i);
}
@@ -185038,12 +186101,12 @@ static void rtreeMatchArgFree(void *pArg){
static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
RtreeMatchArg *pBlob;
- int nBlob;
+ sqlite3_int64 nBlob;
int memErr = 0;
nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
+ nArg*sizeof(sqlite3_value*);
- pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
+ pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
if( !pBlob ){
sqlite3_result_error_nomem(ctx);
}else{
@@ -185754,7 +186817,7 @@ static int icuCreate(
if( argc>0 ){
n = strlen(argv[0])+1;
}
- p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
+ p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n);
if( !p ){
return SQLITE_NOMEM;
}
@@ -185811,7 +186874,7 @@ static int icuOpen(
nInput = strlen(zInput);
}
nChar = nInput+1;
- pCsr = (IcuCursor *)sqlite3_malloc(
+ pCsr = (IcuCursor *)sqlite3_malloc64(
sizeof(IcuCursor) + /* IcuCursor */
((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
(nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
@@ -186385,6 +187448,10 @@ SQLITE_API sqlite3rbu *sqlite3rbu_open(
** state database is not already present in the file-system, it is created
** with the same permissions as the target db is made.
**
+** With an RBU vacuum, it is an SQLITE_MISUSE error if the name of the
+** state database ends with "-vactmp". This name is reserved for internal
+** use.
+**
** This function does not delete the state database after an RBU vacuum
** is completed, even if it created it. However, if the call to
** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
@@ -189041,7 +190108,7 @@ static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
if( *zExtra=='\0' ) zExtra = 0;
}
- zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s",
+ zTarget = sqlite3_mprintf("file:%s-vactmp?rbu_memory=1%s%s",
sqlite3_db_filename(p->dbRbu, "main"),
(zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra)
);
@@ -190307,6 +191374,12 @@ SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
const char *zState
){
if( zTarget==0 ){ return rbuMisuseError(); }
+ if( zState ){
+ int n = strlen(zState);
+ if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
+ return rbuMisuseError();
+ }
+ }
/* TODO: Check that both arguments are non-NULL */
return openRbuHandle(0, zTarget, zState);
}
@@ -190503,7 +191576,10 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *p){
if( p->eStage==RBU_STAGE_OAL ){
assert( rc!=SQLITE_DONE );
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0);
- if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, 0);
+ if( rc==SQLITE_OK ){
+ const char *zBegin = rbuIsVacuum(p) ? "BEGIN" : "BEGIN IMMEDIATE";
+ rc = sqlite3_exec(p->dbRbu, zBegin, 0, 0, 0);
+ }
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0,0);
}
@@ -192034,6 +193110,10 @@ statNextRestart:
goto statNextRestart; /* Tail recursion */
}
pCsr->iPage++;
+ if( pCsr->iPage>=ArraySize(pCsr->aPage) ){
+ statResetCsr(pCsr);
+ return SQLITE_CORRUPT_BKPT;
+ }
assert( p==&pCsr->aPage[pCsr->iPage-1] );
if( p->iCell==p->nCell ){
@@ -192105,7 +193185,6 @@ static int statFilter(
StatTable *pTab = (StatTable*)(pCursor->pVtab);
char *zSql;
int rc = SQLITE_OK;
- char *zMaster;
if( idxNum==1 ){
const char *zDbase = (const char*)sqlite3_value_text(argv[0]);
@@ -192121,13 +193200,12 @@ static int statFilter(
statResetCsr(pCsr);
sqlite3_finalize(pCsr->pStmt);
pCsr->pStmt = 0;
- zMaster = pCsr->iDb==1 ? "sqlite_temp_master" : "sqlite_master";
zSql = sqlite3_mprintf(
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type"
- " FROM \"%w\".%s WHERE rootpage!=0"
- " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster);
+ " FROM \"%w\".sqlite_master WHERE rootpage!=0"
+ " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName);
if( zSql==0 ){
return SQLITE_NOMEM_BKPT;
}else{
@@ -193015,7 +194093,7 @@ static void sessionPutI64(u8 *aBuf, sqlite3_int64 i){
static int sessionSerializeValue(
u8 *aBuf, /* If non-NULL, write serialized value here */
sqlite3_value *pValue, /* Value to serialize */
- int *pnWrite /* IN/OUT: Increment by bytes written */
+ sqlite3_int64 *pnWrite /* IN/OUT: Increment by bytes written */
){
int nByte; /* Size of serialized value in bytes */
@@ -193556,7 +194634,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
SessionChange **apNew;
int nNew = (pTab->nChange ? pTab->nChange : 128) * 2;
- apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew);
+ apNew = (SessionChange **)sqlite3_malloc64(sizeof(SessionChange *) * nNew);
if( apNew==0 ){
if( pTab->nChange==0 ){
return SQLITE_ERROR;
@@ -193622,7 +194700,7 @@ static int sessionTableInfo(
char *zPragma;
sqlite3_stmt *pStmt;
int rc;
- int nByte;
+ sqlite3_int64 nByte;
int nDbCol = 0;
int nThis;
int i;
@@ -193665,7 +194743,7 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
- pAlloc = sqlite3_malloc(nByte);
+ pAlloc = sqlite3_malloc64(nByte);
if( pAlloc==0 ){
rc = SQLITE_NOMEM;
}
@@ -193806,7 +194884,7 @@ static void sessionPreupdateOneChange(
int iHash;
int bNull = 0;
int rc = SQLITE_OK;
- SessionStat1Ctx stat1 = {0};
+ SessionStat1Ctx stat1 = {{0,0,0,0,0},0};
if( pSession->rc ) return;
@@ -193863,7 +194941,7 @@ static void sessionPreupdateOneChange(
** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
** values (if this is an INSERT). */
SessionChange *pChange; /* New change object */
- int nByte; /* Number of bytes to allocate */
+ sqlite3_int64 nByte; /* Number of bytes to allocate */
int i; /* Used to iterate through columns */
assert( rc==SQLITE_OK );
@@ -193888,7 +194966,7 @@ static void sessionPreupdateOneChange(
}
/* Allocate the change object */
- pChange = (SessionChange *)sqlite3_malloc(nByte);
+ pChange = (SessionChange *)sqlite3_malloc64(nByte);
if( !pChange ){
rc = SQLITE_NOMEM;
goto error_out;
@@ -194332,7 +195410,7 @@ SQLITE_API int sqlite3session_create(
*ppSession = 0;
/* Allocate and populate the new session object. */
- pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1);
+ pNew = (sqlite3_session *)sqlite3_malloc64(sizeof(sqlite3_session) + nDb + 1);
if( !pNew ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(sqlite3_session));
pNew->db = db;
@@ -194451,7 +195529,7 @@ SQLITE_API int sqlite3session_attach(
if( !pTab ){
/* Allocate new SessionTable object. */
- pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);
+ pTab = (SessionTable *)sqlite3_malloc64(sizeof(SessionTable) + nName + 1);
if( !pTab ){
rc = SQLITE_NOMEM;
}else{
@@ -194511,7 +195589,7 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){
static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){
int rc = *pRc;
if( rc==SQLITE_OK ){
- int nByte = 0;
+ sqlite3_int64 nByte = 0;
rc = sessionSerializeValue(0, pVal, &nByte);
sessionBufferGrow(p, nByte, &rc);
if( rc==SQLITE_OK ){
@@ -195387,7 +196465,7 @@ static int sessionValueSetStr(
** argument to sqlite3ValueSetStr() and have the copy created
** automatically. But doing so makes it difficult to detect any OOM
** error. Hence the code to create the copy externally. */
- u8 *aCopy = sqlite3_malloc(nData+1);
+ u8 *aCopy = sqlite3_malloc64((sqlite3_int64)nData+1);
if( aCopy==0 ) return SQLITE_NOMEM;
memcpy(aCopy, aData, nData);
sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free);
@@ -196000,7 +197078,7 @@ static int sessionChangesetInvert(
int iCol;
if( 0==apVal ){
- apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2);
+ apVal = (sqlite3_value **)sqlite3_malloc64(sizeof(apVal[0])*nCol*2);
if( 0==apVal ){
rc = SQLITE_NOMEM;
goto finished_invert;
@@ -197273,7 +198351,7 @@ static int sessionChangeMerge(
int rc = SQLITE_OK;
if( !pExist ){
- pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec);
+ pNew = (SessionChange *)sqlite3_malloc64(sizeof(SessionChange) + nRec);
if( !pNew ){
return SQLITE_NOMEM;
}
@@ -197306,8 +198384,8 @@ static int sessionChangeMerge(
if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){
*ppNew = pExist;
}else{
- int nByte = nRec + pExist->nRecord + sizeof(SessionChange);
- pNew = (SessionChange*)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = nRec + pExist->nRecord + sizeof(SessionChange);
+ pNew = (SessionChange*)sqlite3_malloc64(nByte);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -197367,14 +198445,14 @@ static int sessionChangeMerge(
assert( pNew==0 );
}else{
u8 *aExist = pExist->aRecord;
- int nByte;
+ sqlite3_int64 nByte;
u8 *aCsr;
/* Allocate a new SessionChange object. Ensure that the aRecord[]
** buffer of the new object is large enough to hold any record that
** may be generated by combining the input records. */
nByte = sizeof(SessionChange) + pExist->nRecord + nRec;
- pNew = (SessionChange *)sqlite3_malloc(nByte);
+ pNew = (SessionChange *)sqlite3_malloc64(nByte);
if( !pNew ){
sqlite3_free(pExist);
return SQLITE_NOMEM;
@@ -197480,7 +198558,7 @@ static int sessionChangesetToHash(
if( !pTab ){
SessionTable **ppTab;
- pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1);
+ pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1);
if( !pTab ){
rc = SQLITE_NOMEM;
break;
@@ -198254,12 +199332,8 @@ struct Fts5PhraseIter {
**
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
** to the column in which it occurs and *piOff the token offset of the
-** first token of the phrase. The exception is if the table was created
-** with the offsets=0 option specified. In this case *piOff is always
-** set to -1.
-**
-** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
-** if an error occurs.
+** first token of the phrase. Returns SQLITE_OK if successful, or an error
+** code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
@@ -198548,11 +199622,11 @@ struct Fts5ExtensionApi {
** the tokenizer substitutes "first" for "1st" and the query works
** as expected.
**
-** <li> By adding multiple synonyms for a single term to the FTS index.
-** In this case, when tokenizing query text, the tokenizer may
-** provide multiple synonyms for a single term within the document.
-** FTS5 then queries the index for each synonym individually. For
-** example, faced with the query:
+** <li> By querying the index for all synonyms of each query term
+** separately. In this case, when tokenizing query text, the
+** tokenizer may provide multiple synonyms for a single term
+** within the document. FTS5 then queries the index for each
+** synonym individually. For example, faced with the query:
**
** <codeblock>
** ... MATCH 'first place'</codeblock>
@@ -198576,7 +199650,7 @@ struct Fts5ExtensionApi {
** "place".
**
** This way, even if the tokenizer does not provide synonyms
-** when tokenizing query text (it should not - to do would be
+** when tokenizing query text (it should not - to do so would be
** inefficient), it doesn't matter if the user queries for
** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
@@ -198801,6 +199875,12 @@ SQLITE_API extern int sqlite3_fts5_may_be_corrupt;
# define assert_nc(x) assert(x)
#endif
+/*
+** A version of memcmp() that does not cause asan errors if one of the pointer
+** parameters is NULL and the number of bytes to compare is zero.
+*/
+#define fts5Memcmp(s1, s2, n) ((n)==0 ? 0 : memcmp((s1), (s2), (n)))
+
/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAM
@@ -198988,7 +200068,7 @@ static void sqlite3Fts5Put32(u8*, int);
static int sqlite3Fts5Get32(const u8*);
#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
-#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF)
+#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF)
typedef struct Fts5PoslistReader Fts5PoslistReader;
struct Fts5PoslistReader {
@@ -199023,7 +200103,7 @@ static int sqlite3Fts5PoslistNext64(
);
/* Malloc utility */
-static void *sqlite3Fts5MallocZero(int *pRc, int nByte);
+static void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte);
static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
/* Character set tests (like isspace(), isalpha() etc.) */
@@ -199234,8 +200314,18 @@ static int sqlite3Fts5PutVarint(unsigned char *p, u64 v);
/**************************************************************************
-** Interface to code in fts5.c.
+** Interface to code in fts5_main.c.
+*/
+
+/*
+** Virtual-table object.
*/
+typedef struct Fts5Table Fts5Table;
+struct Fts5Table {
+ sqlite3_vtab base; /* Base class used by SQLite core */
+ Fts5Config *pConfig; /* Virtual table configuration */
+ Fts5Index *pIndex; /* Full-text index */
+};
static int sqlite3Fts5GetTokenizer(
Fts5Global*,
@@ -199246,7 +200336,9 @@ static int sqlite3Fts5GetTokenizer(
char **pzErr
);
-static Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
+static Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
+
+static int sqlite3Fts5FlushToDisk(Fts5Table*);
/*
** End of interface to code in fts5.c.
@@ -199502,7 +200594,7 @@ static int sqlite3Fts5UnicodeIsdiacritic(int c);
static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic);
static int sqlite3Fts5UnicodeCatParse(const char*, u8*);
-static int sqlite3Fts5UnicodeCategory(int iCode);
+static int sqlite3Fts5UnicodeCategory(u32 iCode);
static void sqlite3Fts5UnicodeAscii(u8*, u8*);
/*
** End of interface to code in fts5_unicode2.c.
@@ -200406,41 +201498,70 @@ static void fts5yy_shift(
fts5yyTraceShift(fts5yypParser, fts5yyNewState, "Shift");
}
-/* The following table contains information about every rule that
-** is used during the reduce.
-*/
-static const struct {
- fts5YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
- signed char nrhs; /* Negative of the number of RHS symbols in the rule */
-} fts5yyRuleInfo[] = {
- { 16, -1 }, /* (0) input ::= expr */
- { 20, -4 }, /* (1) colset ::= MINUS LCP colsetlist RCP */
- { 20, -3 }, /* (2) colset ::= LCP colsetlist RCP */
- { 20, -1 }, /* (3) colset ::= STRING */
- { 20, -2 }, /* (4) colset ::= MINUS STRING */
- { 21, -2 }, /* (5) colsetlist ::= colsetlist STRING */
- { 21, -1 }, /* (6) colsetlist ::= STRING */
- { 17, -3 }, /* (7) expr ::= expr AND expr */
- { 17, -3 }, /* (8) expr ::= expr OR expr */
- { 17, -3 }, /* (9) expr ::= expr NOT expr */
- { 17, -5 }, /* (10) expr ::= colset COLON LP expr RP */
- { 17, -3 }, /* (11) expr ::= LP expr RP */
- { 17, -1 }, /* (12) expr ::= exprlist */
- { 19, -1 }, /* (13) exprlist ::= cnearset */
- { 19, -2 }, /* (14) exprlist ::= exprlist cnearset */
- { 18, -1 }, /* (15) cnearset ::= nearset */
- { 18, -3 }, /* (16) cnearset ::= colset COLON nearset */
- { 22, -1 }, /* (17) nearset ::= phrase */
- { 22, -2 }, /* (18) nearset ::= CARET phrase */
- { 22, -5 }, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */
- { 23, -1 }, /* (20) nearphrases ::= phrase */
- { 23, -2 }, /* (21) nearphrases ::= nearphrases phrase */
- { 25, 0 }, /* (22) neardist_opt ::= */
- { 25, -2 }, /* (23) neardist_opt ::= COMMA STRING */
- { 24, -4 }, /* (24) phrase ::= phrase PLUS STRING star_opt */
- { 24, -2 }, /* (25) phrase ::= STRING star_opt */
- { 26, -1 }, /* (26) star_opt ::= STAR */
- { 26, 0 }, /* (27) star_opt ::= */
+/* For rule J, fts5yyRuleInfoLhs[J] contains the symbol on the left-hand side
+** of that rule */
+static const fts5YYCODETYPE fts5yyRuleInfoLhs[] = {
+ 16, /* (0) input ::= expr */
+ 20, /* (1) colset ::= MINUS LCP colsetlist RCP */
+ 20, /* (2) colset ::= LCP colsetlist RCP */
+ 20, /* (3) colset ::= STRING */
+ 20, /* (4) colset ::= MINUS STRING */
+ 21, /* (5) colsetlist ::= colsetlist STRING */
+ 21, /* (6) colsetlist ::= STRING */
+ 17, /* (7) expr ::= expr AND expr */
+ 17, /* (8) expr ::= expr OR expr */
+ 17, /* (9) expr ::= expr NOT expr */
+ 17, /* (10) expr ::= colset COLON LP expr RP */
+ 17, /* (11) expr ::= LP expr RP */
+ 17, /* (12) expr ::= exprlist */
+ 19, /* (13) exprlist ::= cnearset */
+ 19, /* (14) exprlist ::= exprlist cnearset */
+ 18, /* (15) cnearset ::= nearset */
+ 18, /* (16) cnearset ::= colset COLON nearset */
+ 22, /* (17) nearset ::= phrase */
+ 22, /* (18) nearset ::= CARET phrase */
+ 22, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */
+ 23, /* (20) nearphrases ::= phrase */
+ 23, /* (21) nearphrases ::= nearphrases phrase */
+ 25, /* (22) neardist_opt ::= */
+ 25, /* (23) neardist_opt ::= COMMA STRING */
+ 24, /* (24) phrase ::= phrase PLUS STRING star_opt */
+ 24, /* (25) phrase ::= STRING star_opt */
+ 26, /* (26) star_opt ::= STAR */
+ 26, /* (27) star_opt ::= */
+};
+
+/* For rule J, fts5yyRuleInfoNRhs[J] contains the negative of the number
+** of symbols on the right-hand side of that rule. */
+static const signed char fts5yyRuleInfoNRhs[] = {
+ -1, /* (0) input ::= expr */
+ -4, /* (1) colset ::= MINUS LCP colsetlist RCP */
+ -3, /* (2) colset ::= LCP colsetlist RCP */
+ -1, /* (3) colset ::= STRING */
+ -2, /* (4) colset ::= MINUS STRING */
+ -2, /* (5) colsetlist ::= colsetlist STRING */
+ -1, /* (6) colsetlist ::= STRING */
+ -3, /* (7) expr ::= expr AND expr */
+ -3, /* (8) expr ::= expr OR expr */
+ -3, /* (9) expr ::= expr NOT expr */
+ -5, /* (10) expr ::= colset COLON LP expr RP */
+ -3, /* (11) expr ::= LP expr RP */
+ -1, /* (12) expr ::= exprlist */
+ -1, /* (13) exprlist ::= cnearset */
+ -2, /* (14) exprlist ::= exprlist cnearset */
+ -1, /* (15) cnearset ::= nearset */
+ -3, /* (16) cnearset ::= colset COLON nearset */
+ -1, /* (17) nearset ::= phrase */
+ -2, /* (18) nearset ::= CARET phrase */
+ -5, /* (19) nearset ::= STRING LP nearphrases neardist_opt RP */
+ -1, /* (20) nearphrases ::= phrase */
+ -2, /* (21) nearphrases ::= nearphrases phrase */
+ 0, /* (22) neardist_opt ::= */
+ -2, /* (23) neardist_opt ::= COMMA STRING */
+ -4, /* (24) phrase ::= phrase PLUS STRING star_opt */
+ -2, /* (25) phrase ::= STRING star_opt */
+ -1, /* (26) star_opt ::= STAR */
+ 0, /* (27) star_opt ::= */
};
static void fts5yy_accept(fts5yyParser*); /* Forward Declaration */
@@ -200472,7 +201593,7 @@ static fts5YYACTIONTYPE fts5yy_reduce(
fts5yymsp = fts5yypParser->fts5yytos;
#ifndef NDEBUG
if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){
- fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs;
+ fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
if( fts5yysize ){
fprintf(fts5yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
fts5yyTracePrompt,
@@ -200487,7 +201608,7 @@ static fts5YYACTIONTYPE fts5yy_reduce(
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
- if( fts5yyRuleInfo[fts5yyruleno].nrhs==0 ){
+ if( fts5yyRuleInfoNRhs[fts5yyruleno]==0 ){
#ifdef fts5YYTRACKMAXSTACKDEPTH
if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){
fts5yypParser->fts5yyhwm++;
@@ -200666,9 +201787,9 @@ static fts5YYACTIONTYPE fts5yy_reduce(
break;
/********** End reduce actions ************************************************/
};
- assert( fts5yyruleno<sizeof(fts5yyRuleInfo)/sizeof(fts5yyRuleInfo[0]) );
- fts5yygoto = fts5yyRuleInfo[fts5yyruleno].lhs;
- fts5yysize = fts5yyRuleInfo[fts5yyruleno].nrhs;
+ assert( fts5yyruleno<sizeof(fts5yyRuleInfoLhs)/sizeof(fts5yyRuleInfoLhs[0]) );
+ fts5yygoto = fts5yyRuleInfoLhs[fts5yyruleno];
+ fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
fts5yyact = fts5yy_find_reduce_action(fts5yymsp[fts5yysize].stateno,(fts5YYCODETYPE)fts5yygoto);
/* There are no SHIFTREDUCE actions on nonterminals because the table
@@ -201099,7 +202220,7 @@ static void fts5HighlightAppend(
HighlightContext *p,
const char *z, int n
){
- if( *pRc==SQLITE_OK ){
+ if( *pRc==SQLITE_OK && z ){
if( n<0 ) n = (int)strlen(z);
p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z);
if( p->zOut==0 ) *pRc = SQLITE_NOMEM;
@@ -201231,7 +202352,7 @@ static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){
int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64;
int *aNew;
- aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int));
+ aNew = (int*)sqlite3_realloc64(p->aFirst, nNew*sizeof(int));
if( aNew==0 ) return SQLITE_NOMEM;
p->aFirst = aNew;
p->nFirstAlloc = nNew;
@@ -201298,11 +202419,12 @@ static int fts5SnippetScore(
int nInst;
int nScore = 0;
int iLast = 0;
+ sqlite3_int64 iEnd = (sqlite3_int64)iPos + nToken;
rc = pApi->xInstCount(pFts, &nInst);
for(i=0; i<nInst && rc==SQLITE_OK; i++){
rc = pApi->xInst(pFts, i, &ip, &ic, &iOff);
- if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){
+ if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<iEnd ){
nScore += (aSeen[ip] ? 1 : 1000);
aSeen[ip] = 1;
if( iFirst<0 ) iFirst = iOff;
@@ -201312,7 +202434,7 @@ static int fts5SnippetScore(
*pnScore = nScore;
if( piPos ){
- int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
+ sqlite3_int64 iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken;
if( iAdj<0 ) iAdj = 0;
*piPos = iAdj;
@@ -201405,7 +202527,9 @@ static void fts5SnippetFunction(
int jj;
rc = pApi->xInst(pFts, ii, &ip, &ic, &io);
- if( ic!=i || rc!=SQLITE_OK ) continue;
+ if( ic!=i ) continue;
+ if( io>nDocsize ) rc = FTS5_CORRUPT;
+ if( rc!=SQLITE_OK ) continue;
memset(aSeen, 0, nPhrase);
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
io, nToken, &nScore, &iAdj
@@ -201531,13 +202655,13 @@ static int fts5Bm25GetData(
int nPhrase; /* Number of phrases in query */
sqlite3_int64 nRow = 0; /* Number of rows in table */
sqlite3_int64 nToken = 0; /* Number of tokens in table */
- int nByte; /* Bytes of space to allocate */
+ sqlite3_int64 nByte; /* Bytes of space to allocate */
int i;
/* Allocate the Fts5Bm25Data object */
nPhrase = pApi->xPhraseCount(pFts);
nByte = sizeof(Fts5Bm25Data) + nPhrase*2*sizeof(double);
- p = (Fts5Bm25Data*)sqlite3_malloc(nByte);
+ p = (Fts5Bm25Data*)sqlite3_malloc64(nByte);
if( p==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -201549,6 +202673,7 @@ static int fts5Bm25GetData(
/* Calculate the average document length for this FTS5 table */
if( rc==SQLITE_OK ) rc = pApi->xRowCount(pFts, &nRow);
+ assert( rc!=SQLITE_OK || nRow>0 );
if( rc==SQLITE_OK ) rc = pApi->xColumnTotalSize(pFts, -1, &nToken);
if( rc==SQLITE_OK ) p->avgdl = (double)nToken / (double)nRow;
@@ -201674,8 +202799,6 @@ static int sqlite3Fts5AuxInit(fts5_api *pApi){
return rc;
}
-
-
/*
** 2014 May 31
**
@@ -201695,12 +202818,12 @@ static int sqlite3Fts5AuxInit(fts5_api *pApi){
static int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){
if( (u32)pBuf->nSpace<nByte ){
- u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
+ u64 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
u8 *pNew;
while( nNew<nByte ){
nNew = nNew * 2;
}
- pNew = sqlite3_realloc(pBuf->p, nNew);
+ pNew = sqlite3_realloc64(pBuf->p, nNew);
if( pNew==0 ){
*pRc = SQLITE_NOMEM;
return 1;
@@ -201730,7 +202853,7 @@ static void sqlite3Fts5Put32(u8 *aBuf, int iVal){
}
static int sqlite3Fts5Get32(const u8 *aBuf){
- return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
+ return (int)((((u32)aBuf[0])<<24) + (aBuf[1]<<16) + (aBuf[2]<<8) + aBuf[3]);
}
/*
@@ -201861,7 +202984,7 @@ static int sqlite3Fts5PoslistNext64(
iOff = ((i64)iVal) << 32;
fts5FastGetVarint32(a, i, iVal);
}
- *piOff = iOff + (iVal-2);
+ *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
*pi = i;
return 0;
}
@@ -201922,10 +203045,10 @@ static int sqlite3Fts5PoslistWriterAppend(
return SQLITE_OK;
}
-static void *sqlite3Fts5MallocZero(int *pRc, int nByte){
+static void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte){
void *pRet = 0;
if( *pRc==SQLITE_OK ){
- pRet = sqlite3_malloc(nByte);
+ pRet = sqlite3_malloc64(nByte);
if( pRet==0 ){
if( nByte>0 ) *pRc = SQLITE_NOMEM;
}else{
@@ -202368,7 +203491,7 @@ static int fts5ConfigParseSpecial(
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
const char *p = (const char*)zArg;
- int nArg = (int)strlen(zArg) + 1;
+ sqlite3_int64 nArg = strlen(zArg) + 1;
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
char *pSpace = pDel;
@@ -202498,8 +203621,8 @@ static const char *fts5ConfigGobbleWord(
){
const char *zRet = 0;
- int nIn = (int)strlen(zIn);
- char *zOut = sqlite3_malloc(nIn+1);
+ sqlite3_int64 nIn = strlen(zIn);
+ char *zOut = sqlite3_malloc64(nIn+1);
assert( *pRc==SQLITE_OK );
*pbQuoted = 0;
@@ -202602,7 +203725,7 @@ static int sqlite3Fts5ConfigParse(
int rc = SQLITE_OK; /* Return code */
Fts5Config *pRet; /* New object to return */
int i;
- int nByte;
+ sqlite3_int64 nByte;
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
if( pRet==0 ) return SQLITE_NOMEM;
@@ -203246,7 +204369,7 @@ static int fts5ExprGetToken(
return tok;
}
-static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc((int)t); }
+static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
static void fts5ParseFree(void *p){ sqlite3_free(p); }
static int sqlite3Fts5ExprNew(
@@ -203391,8 +204514,8 @@ static int fts5ExprSynonymList(
if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){
if( pIter->nData==0 ) continue;
if( nIter==nAlloc ){
- int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
- Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
+ Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
goto synonym_poslist_out;
@@ -203472,8 +204595,8 @@ static int fts5ExprPhraseIsMatch(
/* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */
if( pPhrase->nTerm>ArraySize(aStatic) ){
- int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
- aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
+ aIter = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
if( !aIter ) return SQLITE_NOMEM;
}
memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);
@@ -203607,7 +204730,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
/* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */
if( pNear->nPhrase>ArraySize(aStatic) ){
- int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
+ sqlite3_int64 nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
}else{
memset(aStatic, 0, sizeof(aStatic));
@@ -204516,8 +205639,9 @@ static Fts5ExprNearset *sqlite3Fts5ParseNearset(
return pNear;
}
if( pNear==0 ){
- int nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
- pRet = sqlite3_malloc(nByte);
+ sqlite3_int64 nByte;
+ nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
+ pRet = sqlite3_malloc64(nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
}else{
@@ -204525,9 +205649,10 @@ static Fts5ExprNearset *sqlite3Fts5ParseNearset(
}
}else if( (pNear->nPhrase % SZALLOC)==0 ){
int nNew = pNear->nPhrase + SZALLOC;
- int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
+ sqlite3_int64 nByte;
- pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte);
+ nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
+ pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
}
@@ -204591,8 +205716,8 @@ static int fts5ParseTokenize(
if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){
Fts5ExprTerm *pSyn;
- int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
- pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
+ pSyn = (Fts5ExprTerm*)sqlite3_malloc64(nByte);
if( pSyn==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -204608,7 +205733,7 @@ static int fts5ParseTokenize(
Fts5ExprPhrase *pNew;
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
- pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase,
+ pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
);
if( pNew==0 ){
@@ -204694,9 +205819,9 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm(
if( pAppend==0 ){
if( (pParse->nPhrase % 8)==0 ){
- int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
+ sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
Fts5ExprPhrase **apNew;
- apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte);
+ apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
if( apNew==0 ){
pParse->rc = SQLITE_NOMEM;
fts5ExprPhraseFree(sCtx.pPhrase);
@@ -204751,8 +205876,10 @@ static int sqlite3Fts5ExprClonePhrase(
if( rc==SQLITE_OK ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
- int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
- Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
+ sqlite3_int64 nByte;
+ Fts5Colset *pColset;
+ nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
+ pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
if( pColset ){
memcpy(pColset, pColsetOrig, nByte);
}
@@ -204872,7 +205999,7 @@ static Fts5Colset *fts5ParseColset(
assert( pParse->rc==SQLITE_OK );
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
- pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
+ pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
if( pNew==0 ){
pParse->rc = SQLITE_NOMEM;
}else{
@@ -204968,7 +206095,7 @@ static Fts5Colset *sqlite3Fts5ParseColset(
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
Fts5Colset *pRet;
if( pOrig ){
- int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
+ sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
if( pRet ){
memcpy(pRet, pOrig, nByte);
@@ -205122,7 +206249,7 @@ static Fts5ExprNode *sqlite3Fts5ParseNode(
if( pParse->rc==SQLITE_OK ){
int nChild = 0; /* Number of children of returned node */
- int nByte; /* Bytes of space to allocate for this node */
+ sqlite3_int64 nByte; /* Bytes of space to allocate for this node */
assert( (eType!=FTS5_STRING && !pNear)
|| (eType==FTS5_STRING && !pLeft && !pRight)
@@ -205254,7 +206381,7 @@ static Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
}
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
- int nByte = 0;
+ sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
char *zQuoted;
@@ -205262,7 +206389,7 @@ static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
for(p=pTerm; p; p=p->pSynonym){
nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2;
}
- zQuoted = sqlite3_malloc(nByte);
+ zQuoted = sqlite3_malloc64(nByte);
if( zQuoted ){
int i = 0;
@@ -205502,7 +206629,7 @@ static void fts5ExprFunction(
}
nConfig = 3 + (nArg-iArg);
- azConfig = (const char**)sqlite3_malloc(sizeof(char*) * nConfig);
+ azConfig = (const char**)sqlite3_malloc64(sizeof(char*) * nConfig);
if( azConfig==0 ){
sqlite3_result_error_nomem(pCtx);
return;
@@ -205588,7 +206715,7 @@ static void fts5ExprIsAlnum(
sqlite3Fts5UnicodeCatParse("N*", aArr);
sqlite3Fts5UnicodeCatParse("Co", aArr);
iCode = sqlite3_value_int(apVal[0]);
- sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]);
+ sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory((u32)iCode)]);
}
static void fts5ExprFold(
@@ -205683,7 +206810,7 @@ struct Fts5PoslistPopulator {
static Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
Fts5PoslistPopulator *pRet;
- pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
+ pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
if( pRet ){
int i;
memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
@@ -205883,7 +207010,6 @@ static int sqlite3Fts5ExprPhraseCollist(
return rc;
}
-
/*
** 2014 August 11
**
@@ -205976,14 +207102,14 @@ static int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
- int nByte;
+ sqlite3_int64 nByte;
memset(pNew, 0, sizeof(Fts5Hash));
pNew->pnByte = pnByte;
pNew->eDetail = pConfig->eDetail;
pNew->nSlot = 1024;
nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
- pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
+ pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc64(nByte);
if( pNew->aSlot==0 ){
sqlite3_free(pNew);
*ppNew = 0;
@@ -206051,7 +207177,7 @@ static int fts5HashResize(Fts5Hash *pHash){
Fts5HashEntry **apNew;
Fts5HashEntry **apOld = pHash->aSlot;
- apNew = (Fts5HashEntry**)sqlite3_malloc(nNew*sizeof(Fts5HashEntry*));
+ apNew = (Fts5HashEntry**)sqlite3_malloc64(nNew*sizeof(Fts5HashEntry*));
if( !apNew ) return SQLITE_NOMEM;
memset(apNew, 0, nNew*sizeof(Fts5HashEntry*));
@@ -206145,7 +207271,7 @@ static int sqlite3Fts5HashWrite(
if( p==0 ){
/* Figure out how much space to allocate */
char *zKey;
- int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
+ sqlite3_int64 nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
if( nByte<128 ) nByte = 128;
/* Grow the Fts5Hash.aSlot[] array if necessary. */
@@ -206156,7 +207282,7 @@ static int sqlite3Fts5HashWrite(
}
/* Allocate new Fts5HashEntry and add it to the hash table. */
- p = (Fts5HashEntry*)sqlite3_malloc(nByte);
+ p = (Fts5HashEntry*)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, sizeof(Fts5HashEntry));
p->nAlloc = nByte;
@@ -206195,12 +207321,12 @@ static int sqlite3Fts5HashWrite(
** + 5 bytes for the new position offset (32-bit max).
*/
if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
- int nNew = p->nAlloc * 2;
+ sqlite3_int64 nNew = p->nAlloc * 2;
Fts5HashEntry *pNew;
Fts5HashEntry **pp;
- pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
+ pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew);
if( pNew==0 ) return SQLITE_NOMEM;
- pNew->nAlloc = nNew;
+ pNew->nAlloc = (int)nNew;
for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
*pp = pNew;
p = pNew;
@@ -206324,7 +207450,7 @@ static int fts5HashEntrySort(
int i;
*ppSorted = 0;
- ap = sqlite3_malloc(sizeof(Fts5HashEntry*) * nMergeSlot);
+ ap = sqlite3_malloc64(sizeof(Fts5HashEntry*) * nMergeSlot);
if( !ap ) return SQLITE_NOMEM;
memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);
@@ -206369,7 +207495,8 @@ static int sqlite3Fts5HashQuery(
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
zKey = fts5EntryKey(p);
- if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
+ assert( p->nKey+1==(int)strlen(zKey) );
+ if( nTerm==p->nKey+1 && memcmp(zKey, pTerm, nTerm)==0 ) break;
}
if( p ){
@@ -206421,7 +207548,6 @@ static void sqlite3Fts5HashScanEntry(
}
}
-
/*
** 2014 May 31
**
@@ -206936,7 +208062,6 @@ struct Fts5Iter {
Fts5IndexIter base; /* Base class containing output vars */
Fts5Index *pIndex; /* Index that owns this iterator */
- Fts5Structure *pStruct; /* Database structure for this iterator */
Fts5Buffer poslist; /* Buffer containing current poslist */
Fts5Colset *pColset; /* Restrict matches to these columns */
@@ -206997,7 +208122,7 @@ static u16 fts5GetU16(const u8 *aIn){
** If an OOM error is encountered, return NULL and set the error code in
** the Fts5Index handle passed as the first argument.
*/
-static void *fts5IdxMalloc(Fts5Index *p, int nByte){
+static void *fts5IdxMalloc(Fts5Index *p, sqlite3_int64 nByte){
return sqlite3Fts5MallocZero(&p->rc, nByte);
}
@@ -207031,7 +208156,7 @@ static int fts5BufferCompareBlob(
*/
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
int nCmp = MIN(pLeft->n, pRight->n);
- int res = memcmp(pLeft->p, pRight->p, nCmp);
+ int res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
return (res==0 ? (pLeft->n - pRight->n) : res);
}
@@ -207097,8 +208222,8 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
if( rc==SQLITE_OK ){
u8 *aOut = 0; /* Read blob data into this buffer */
int nByte = sqlite3_blob_bytes(p->pReader);
- int nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
- pRet = (Fts5Data*)sqlite3_malloc(nAlloc);
+ sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
+ pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
if( pRet ){
pRet->nn = nByte;
aOut = pRet->p = (u8*)&pRet[1];
@@ -207114,6 +208239,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
pRet = 0;
}else{
/* TODO1: Fix this */
+ pRet->p[nByte] = 0x00;
pRet->szLeaf = fts5GetU16(&pRet->p[2]);
}
}
@@ -207272,7 +208398,7 @@ static int fts5StructureDecode(
int iLvl;
int nLevel = 0;
int nSegment = 0;
- int nByte; /* Bytes of space to allocate at pRet */
+ sqlite3_int64 nByte; /* Bytes of space to allocate at pRet */
Fts5Structure *pRet = 0; /* Structure object to return */
/* Grab the cookie value */
@@ -207283,6 +208409,11 @@ static int fts5StructureDecode(
** structure record. */
i += fts5GetVarint32(&pData[i], nLevel);
i += fts5GetVarint32(&pData[i], nSegment);
+ if( nLevel>FTS5_MAX_SEGMENT || nLevel<0
+ || nSegment>FTS5_MAX_SEGMENT || nSegment<0
+ ){
+ return FTS5_CORRUPT;
+ }
nByte = (
sizeof(Fts5Structure) + /* Main structure */
sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
@@ -207305,25 +208436,35 @@ static int fts5StructureDecode(
}else{
i += fts5GetVarint32(&pData[i], pLvl->nMerge);
i += fts5GetVarint32(&pData[i], nTotal);
- assert( nTotal>=pLvl->nMerge );
+ if( nTotal<pLvl->nMerge ) rc = FTS5_CORRUPT;
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
nTotal * sizeof(Fts5StructureSegment)
);
+ nSegment -= nTotal;
}
if( rc==SQLITE_OK ){
pLvl->nSeg = nTotal;
for(iSeg=0; iSeg<nTotal; iSeg++){
+ Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
if( i>=nData ){
rc = FTS5_CORRUPT;
break;
}
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid);
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst);
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast);
+ i += fts5GetVarint32(&pData[i], pSeg->iSegid);
+ i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst);
+ i += fts5GetVarint32(&pData[i], pSeg->pgnoLast);
+ if( pSeg->pgnoLast<pSeg->pgnoFirst ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
}
+ if( iLvl>0 && pLvl[-1].nMerge && nTotal==0 ) rc = FTS5_CORRUPT;
+ if( iLvl==nLevel-1 && pLvl->nMerge ) rc = FTS5_CORRUPT;
}
}
+ if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT;
+
if( rc!=SQLITE_OK ){
fts5StructureRelease(pRet);
pRet = 0;
@@ -207341,12 +208482,12 @@ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
if( *pRc==SQLITE_OK ){
Fts5Structure *pStruct = *ppStruct;
int nLevel = pStruct->nLevel;
- int nByte = (
+ sqlite3_int64 nByte = (
sizeof(Fts5Structure) + /* Main structure */
sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
);
- pStruct = sqlite3_realloc(pStruct, nByte);
+ pStruct = sqlite3_realloc64(pStruct, nByte);
if( pStruct ){
memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
pStruct->nLevel++;
@@ -207371,10 +208512,10 @@ static void fts5StructureExtendLevel(
if( *pRc==SQLITE_OK ){
Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
Fts5StructureSegment *aNew;
- int nByte;
+ sqlite3_int64 nByte;
nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment);
- aNew = sqlite3_realloc(pLvl->aSeg, nByte);
+ aNew = sqlite3_realloc64(pLvl->aSeg, nByte);
if( aNew ){
if( bInsert==0 ){
memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra);
@@ -207888,10 +209029,10 @@ static Fts5DlidxIter *fts5DlidxIterInit(
int bDone = 0;
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
- int nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
+ sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
Fts5DlidxIter *pNew;
- pNew = (Fts5DlidxIter*)sqlite3_realloc(pIter, nByte);
+ pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
if( pNew==0 ){
p->rc = SQLITE_NOMEM;
}else{
@@ -208061,12 +209202,13 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
int nNew; /* Bytes of new data */
iOff += fts5GetVarint32(&a[iOff], nNew);
- if( iOff+nNew>pIter->pLeaf->nn ){
+ if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
p->rc = FTS5_CORRUPT;
return;
}
pIter->term.n = nKeep;
fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
+ assert( pIter->term.n<=pIter->term.nSpace );
iOff += nNew;
pIter->iTermLeafOffset = iOff;
pIter->iTermLeafPgno = pIter->iLeafPgno;
@@ -208131,7 +209273,7 @@ static void fts5SegIterInit(
if( p->rc==SQLITE_OK ){
pIter->iLeafOffset = 4;
assert_nc( pIter->pLeaf->nn>4 );
- assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
+ assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
fts5SegIterLoadTerm(p, pIter, 0);
fts5SegIterLoadNPos(p, pIter);
@@ -208187,7 +209329,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
/* If necessary, grow the pIter->aRowidOffset[] array. */
if( iRowidOffset>=pIter->nRowidOffset ){
int nNew = pIter->nRowidOffset + 8;
- int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
+ int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
if( aNew==0 ){
p->rc = SQLITE_NOMEM;
break;
@@ -208641,10 +209783,10 @@ static void fts5LeafSeek(
int szLeaf = pIter->pLeaf->szLeaf;
int n = pIter->pLeaf->nn;
- int nMatch = 0;
- int nKeep = 0;
- int nNew = 0;
- int iTermOff;
+ u32 nMatch = 0;
+ u32 nKeep = 0;
+ u32 nNew = 0;
+ u32 iTermOff;
int iPgidx; /* Current offset in pgidx */
int bEndOfPage = 0;
@@ -208668,15 +209810,15 @@ static void fts5LeafSeek(
assert( nKeep>=nMatch );
if( nKeep==nMatch ){
- int nCmp;
- int i;
- nCmp = MIN(nNew, nTerm-nMatch);
+ u32 nCmp;
+ u32 i;
+ nCmp = (u32)MIN(nNew, nTerm-nMatch);
for(i=0; i<nCmp; i++){
if( a[iOff+i]!=pTerm[nMatch+i] ) break;
}
nMatch += i;
- if( nTerm==nMatch ){
+ if( (u32)nTerm==nMatch ){
if( i==nNew ){
goto search_success;
}else{
@@ -208720,6 +209862,7 @@ static void fts5LeafSeek(
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
+ return;
}else{
nKeep = 0;
iTermOff = iOff;
@@ -208732,8 +209875,11 @@ static void fts5LeafSeek(
}
search_success:
-
pIter->iLeafOffset = iOff + nNew;
+ if( pIter->iLeafOffset>n || nNew<1 ){
+ p->rc = FTS5_CORRUPT;
+ return;
+ }
pIter->iTermLeafOffset = pIter->iLeafOffset;
pIter->iTermLeafPgno = pIter->iLeafPgno;
@@ -208840,7 +209986,7 @@ static void fts5SegIterSeekInit(
** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points
** to an entry with a term greater than or equal to (pTerm/nTerm).
*/
- assert( p->rc!=SQLITE_OK /* 1 */
+ assert_nc( p->rc!=SQLITE_OK /* 1 */
|| pIter->pLeaf==0 /* 2 */
|| fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */
|| (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */
@@ -208938,7 +210084,7 @@ static void fts5AssertComparisonResult(
assert( pRes->iFirst==i1 );
}else{
int nMin = MIN(p1->term.n, p2->term.n);
- int res = memcmp(p1->term.p, p2->term.p, nMin);
+ int res = fts5Memcmp(p1->term.p, p2->term.p, nMin);
if( res==0 ) res = p1->term.n - p2->term.n;
if( res==0 ){
@@ -209161,7 +210307,6 @@ static void fts5MultiIterFree(Fts5Iter *pIter){
for(i=0; i<pIter->nSeg; i++){
fts5SegIterClear(&pIter->aSeg[i]);
}
- fts5StructureRelease(pIter->pStruct);
fts5BufferFree(&pIter->poslist);
sqlite3_free(pIter);
}
@@ -209509,7 +210654,8 @@ static void fts5SegiterPoslist(
Fts5Colset *pColset,
Fts5Buffer *pBuf
){
- if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
+ if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
+ memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
if( pColset==0 ){
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
}else{
@@ -209807,9 +210953,7 @@ static void fts5MultiIterNew(
if( pNew==0 ) return;
pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
- pNew->pStruct = pStruct;
pNew->pColset = pColset;
- fts5StructureRef(pStruct);
if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
fts5IterSetOutputCb(&p->rc, pNew);
}
@@ -209987,24 +211131,24 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid;
- if( iId<=FTS5_MAX_SEGMENT ){
- aUsed[(iId-1) / 32] |= 1 << ((iId-1) % 32);
+ if( iId<=FTS5_MAX_SEGMENT && iId>0 ){
+ aUsed[(iId-1) / 32] |= (u32)1 << ((iId-1) % 32);
}
}
}
for(i=0; aUsed[i]==0xFFFFFFFF; i++);
mask = aUsed[i];
- for(iSegid=0; mask & (1 << iSegid); iSegid++);
+ for(iSegid=0; mask & ((u32)1 << iSegid); iSegid++);
iSegid += 1 + i*32;
#ifdef SQLITE_DEBUG
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
- assert( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
+ assert_nc( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
}
}
- assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
+ assert_nc( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
{
sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p);
@@ -210012,7 +211156,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
u8 aBlob[2] = {0xff, 0xff};
sqlite3_bind_int(pIdxSelect, 1, iSegid);
sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
- assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
+ assert_nc( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
p->rc = sqlite3_reset(pIdxSelect);
sqlite3_bind_null(pIdxSelect, 2);
}
@@ -210082,7 +211226,7 @@ static int fts5WriteDlidxGrow(
int nLvl
){
if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){
- Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc(
+ Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc64(
pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl
);
if( aDlidx==0 ){
@@ -210161,8 +211305,10 @@ static void fts5WriteBtreeTerm(
int nTerm, const u8 *pTerm /* First term on new page */
){
fts5WriteFlushBtree(p, pWriter);
- fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
- pWriter->iBtPage = pWriter->writer.pgno;
+ if( p->rc==SQLITE_OK ){
+ fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
+ pWriter->iBtPage = pWriter->writer.pgno;
+ }
}
/*
@@ -210313,6 +211459,7 @@ static void fts5WriteAppendTerm(
int nPrefix; /* Bytes of prefix compression for term */
Fts5PageWriter *pPage = &pWriter->writer;
Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
+ int nMin = MIN(pPage->term.n, nTerm);
assert( p->rc==SQLITE_OK );
assert( pPage->buf.n>=4 );
@@ -210322,6 +211469,7 @@ static void fts5WriteAppendTerm(
if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){
if( pPage->buf.n>4 ){
fts5WriteFlushLeaf(p, pWriter);
+ if( p->rc!=SQLITE_OK ) return;
}
fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING);
}
@@ -210354,13 +211502,14 @@ static void fts5WriteAppendTerm(
** inefficient, but still correct. */
int n = nTerm;
if( pPage->term.n ){
- n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
+ n = 1 + fts5PrefixCompress(nMin, pPage->term.p, pTerm);
}
fts5WriteBtreeTerm(p, pWriter, n, pTerm);
+ if( p->rc!=SQLITE_OK ) return;
pPage = &pWriter->writer;
}
}else{
- nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
+ nPrefix = fts5PrefixCompress(nMin, pPage->term.p, pTerm);
fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix);
}
@@ -210407,7 +211556,7 @@ static void fts5WriteAppendRowid(
if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
}else{
- assert( p->rc || iRowid>pWriter->iPrevRowid );
+ assert_nc( p->rc || iRowid>pWriter->iPrevRowid );
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
}
pWriter->iPrevRowid = iRowid;
@@ -210529,7 +211678,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
int i;
Fts5Buffer buf;
memset(&buf, 0, sizeof(Fts5Buffer));
- for(i=0; i<pIter->nSeg; i++){
+ for(i=0; i<pIter->nSeg && p->rc==SQLITE_OK; i++){
Fts5SegIter *pSeg = &pIter->aSeg[i];
if( pSeg->pSeg==0 ){
/* no-op */
@@ -210547,35 +211696,43 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00};
iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno);
- pData = fts5DataRead(p, iLeafRowid);
+ pData = fts5LeafRead(p, iLeafRowid);
if( pData ){
- fts5BufferZero(&buf);
- fts5BufferGrow(&p->rc, &buf, pData->nn);
- fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
- fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
- fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
- fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]);
- if( p->rc==SQLITE_OK ){
- /* Set the szLeaf field */
- fts5PutU16(&buf.p[2], (u16)buf.n);
- }
+ if( iOff>pData->szLeaf ){
+ /* This can occur if the pages that the segments occupy overlap - if
+ ** a single page has been assigned to more than one segment. In
+ ** this case a prior iteration of this loop may have corrupted the
+ ** segment currently being trimmed. */
+ p->rc = FTS5_CORRUPT;
+ }else{
+ fts5BufferZero(&buf);
+ fts5BufferGrow(&p->rc, &buf, pData->nn);
+ fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
+ fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
+ fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
+ fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff,&pData->p[iOff]);
+ if( p->rc==SQLITE_OK ){
+ /* Set the szLeaf field */
+ fts5PutU16(&buf.p[2], (u16)buf.n);
+ }
- /* Set up the new page-index array */
- fts5BufferAppendVarint(&p->rc, &buf, 4);
- if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
- && pSeg->iEndofDoclist<pData->szLeaf
- ){
- int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
- fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
- fts5BufferAppendBlob(&p->rc, &buf,
- pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
- );
- }
+ /* Set up the new page-index array */
+ fts5BufferAppendVarint(&p->rc, &buf, 4);
+ if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
+ && pSeg->iEndofDoclist<pData->szLeaf
+ ){
+ int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
+ fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
+ fts5BufferAppendBlob(&p->rc, &buf,
+ pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
+ );
+ }
+ pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
+ fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
+ fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
+ }
fts5DataRelease(pData);
- pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
- fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
- fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
}
}
}
@@ -210667,7 +211824,7 @@ static void fts5IndexMergeLevel(
const u8 *pTerm;
pTerm = fts5MultiIterTerm(pIter, &nTerm);
- if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
+ if( nTerm!=term.n || fts5Memcmp(pTerm, term.p, nTerm) ){
if( pnRem && writer.nLeafWritten>nRem ){
break;
}
@@ -210922,6 +212079,7 @@ static void fts5FlushOneHash(Fts5Index *p){
/* Write the term for this entry to disk. */
sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm);
+ if( p->rc!=SQLITE_OK ) break;
assert( writer.bFirstRowidInPage==0 );
if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
@@ -210944,6 +212102,7 @@ static void fts5FlushOneHash(Fts5Index *p){
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
writer.bFirstRowidInPage = 0;
fts5WriteDlidxAppend(p, &writer, iRowid);
+ if( p->rc!=SQLITE_OK ) break;
}else{
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
}
@@ -211001,7 +212160,7 @@ static void fts5FlushOneHash(Fts5Index *p){
/* TODO2: Doclist terminator written here. */
/* pBuf->p[pBuf->n++] = '\0'; */
assert( pBuf->n<=pBuf->nSpace );
- sqlite3Fts5HashScanNext(pHash);
+ if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash);
}
sqlite3Fts5HashClear(pHash);
fts5WriteFinish(p, &writer, &pgnoLast);
@@ -211045,7 +212204,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
Fts5Structure *pStruct
){
Fts5Structure *pNew = 0;
- int nByte = sizeof(Fts5Structure);
+ sqlite3_int64 nByte = sizeof(Fts5Structure);
int nSeg = pStruct->nSegment;
int i;
@@ -211175,11 +212334,13 @@ static void fts5AppendPoslist(
Fts5Buffer *pBuf
){
int nData = pMulti->base.nData;
+ int nByte = nData + 9 + 9 + FTS5_DATA_ZERO_PADDING;
assert( nData>0 );
- if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){
+ if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nByte) ){
fts5BufferSafeAppendVarint(pBuf, iDelta);
fts5BufferSafeAppendVarint(pBuf, nData*2);
fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData);
+ memset(&pBuf->p[pBuf->n], 0, FTS5_DATA_ZERO_PADDING);
}
}
@@ -211360,6 +212521,8 @@ static void fts5MergePrefixLists(
int iOff2 = 0;
u8 *a1 = &i1.aPoslist[i1.nSize];
u8 *a2 = &i2.aPoslist[i2.nSize];
+ int nCopy;
+ u8 *aCopy;
i64 iPrev = 0;
Fts5PoslistWriter writer;
@@ -211391,7 +212554,7 @@ static void fts5MergePrefixLists(
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
if( iPos1<0 ) break;
}else{
- assert( iPos2!=iPrev );
+ assert_nc( iPos2!=iPrev );
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
if( iPos2<0 ) break;
@@ -211403,11 +212566,16 @@ static void fts5MergePrefixLists(
if( iPos1!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
}
- fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1);
+ aCopy = &a1[iOff1];
+ nCopy = i1.nPoslist - iOff1;
}else{
assert( iPos2>=0 && iPos2!=iPrev );
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2);
+ aCopy = &a2[iOff2];
+ nCopy = i2.nPoslist - iOff2;
+ }
+ if( nCopy>0 ){
+ fts5BufferSafeAppendBlob(&tmp, aCopy, nCopy);
}
/* WRITEPOSLISTSIZE */
@@ -211415,6 +212583,7 @@ static void fts5MergePrefixLists(
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
fts5DoclistIterNext(&i1);
fts5DoclistIterNext(&i2);
+ assert( out.n<=(p1->n+p2->n+9) );
if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
}
}
@@ -211516,7 +212685,7 @@ static void fts5SetupPrefixIter(
}
fts5MultiIterFree(p1);
- pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n);
+ pData = fts5IdxMalloc(p, sizeof(Fts5Data)+doclist.n+FTS5_DATA_ZERO_PADDING);
if( pData ){
pData->p = (u8*)&pData[1];
pData->nn = pData->szLeaf = doclist.n;
@@ -212278,11 +213447,11 @@ static void fts5IndexIntegrityCheckSegment(
iOff = fts5LeafFirstTermOff(pLeaf);
iRowidOff = fts5LeafFirstRowidOff(pLeaf);
- if( iRowidOff>=iOff ){
+ if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
}else{
iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
- res = memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
+ res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
if( res==0 ) res = nTerm - nIdxTerm;
if( res<0 ) p->rc = FTS5_CORRUPT;
}
@@ -212677,7 +213846,7 @@ static void fts5DecodeFunction(
u8 *a = 0;
Fts5Buffer s; /* Build up text to return here */
int rc = SQLITE_OK; /* Return code */
- int nSpace = 0;
+ sqlite3_int64 nSpace = 0;
int eDetailNone = (sqlite3_user_data(pCtx)!=0);
assert( nArg==2 );
@@ -212693,8 +213862,7 @@ static void fts5DecodeFunction(
nSpace = n + FTS5_DATA_ZERO_PADDING;
a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
if( a==0 ) goto decode_out;
- memcpy(a, aBlob, n);
-
+ if( n>0 ) memcpy(a, aBlob, n);
fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno);
@@ -212789,6 +213957,9 @@ static void fts5DecodeFunction(
iPgidxOff = szLeaf = fts5GetU16(&a[2]);
if( iPgidxOff<n ){
fts5GetVarint32(&a[iPgidxOff], iTermOff);
+ }else if( iPgidxOff>n ){
+ rc = FTS5_CORRUPT;
+ goto decode_out;
}
}
@@ -212800,14 +213971,22 @@ static void fts5DecodeFunction(
}else{
iOff = szLeaf;
}
+ if( iOff>n ){
+ rc = FTS5_CORRUPT;
+ goto decode_out;
+ }
fts5DecodePoslist(&rc, &s, &a[4], iOff-4);
/* Decode any more doclist data that appears on the page before the
** first term. */
nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff;
+ if( nDoclist+iOff>n ){
+ rc = FTS5_CORRUPT;
+ goto decode_out;
+ }
fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist);
- while( iPgidxOff<n ){
+ while( iPgidxOff<n && rc==SQLITE_OK ){
int bFirst = (iPgidxOff==szLeaf); /* True for first term on page */
int nByte; /* Bytes of data */
int iEnd;
@@ -212822,12 +214001,24 @@ static void fts5DecodeFunction(
}else{
iEnd = szLeaf;
}
+ if( iEnd>szLeaf ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
if( bFirst==0 ){
iOff += fts5GetVarint32(&a[iOff], nByte);
+ if( nByte>term.n ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
term.n = nByte;
}
iOff += fts5GetVarint32(&a[iOff], nByte);
+ if( iOff+nByte>n ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
iOff += nByte;
@@ -212951,8 +214142,8 @@ SQLITE_API int sqlite3_fts5_may_be_corrupt = 1;
typedef struct Fts5Auxdata Fts5Auxdata;
typedef struct Fts5Auxiliary Fts5Auxiliary;
typedef struct Fts5Cursor Fts5Cursor;
+typedef struct Fts5FullTable Fts5FullTable;
typedef struct Fts5Sorter Fts5Sorter;
-typedef struct Fts5Table Fts5Table;
typedef struct Fts5TokenizerModule Fts5TokenizerModule;
/*
@@ -213033,13 +214224,8 @@ struct Fts5TokenizerModule {
Fts5TokenizerModule *pNext; /* Next registered tokenizer module */
};
-/*
-** Virtual-table object.
-*/
-struct Fts5Table {
- sqlite3_vtab base; /* Base class used by SQLite core */
- Fts5Config *pConfig; /* Virtual table configuration */
- Fts5Index *pIndex; /* Full-text index */
+struct Fts5FullTable {
+ Fts5Table p; /* Public class members from fts5Int.h */
Fts5Storage *pStorage; /* Document store */
Fts5Global *pGlobal; /* Global (connection wide) data */
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
@@ -213177,7 +214363,7 @@ struct Fts5Auxdata {
#define FTS5_SAVEPOINT 5
#define FTS5_RELEASE 6
#define FTS5_ROLLBACKTO 7
-static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
+static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
switch( op ){
case FTS5_BEGIN:
assert( p->ts.eState==0 );
@@ -213216,7 +214402,7 @@ static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
case FTS5_ROLLBACKTO:
assert( p->ts.eState==1 );
- assert( iSavepoint>=0 );
+ assert( iSavepoint>=-1 );
assert( iSavepoint<=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint;
break;
@@ -213229,18 +214415,18 @@ static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
/*
** Return true if pTab is a contentless table.
*/
-static int fts5IsContentless(Fts5Table *pTab){
- return pTab->pConfig->eContent==FTS5_CONTENT_NONE;
+static int fts5IsContentless(Fts5FullTable *pTab){
+ return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE;
}
/*
** Delete a virtual table handle allocated by fts5InitVtab().
*/
-static void fts5FreeVtab(Fts5Table *pTab){
+static void fts5FreeVtab(Fts5FullTable *pTab){
if( pTab ){
- sqlite3Fts5IndexClose(pTab->pIndex);
+ sqlite3Fts5IndexClose(pTab->p.pIndex);
sqlite3Fts5StorageClose(pTab->pStorage);
- sqlite3Fts5ConfigFree(pTab->pConfig);
+ sqlite3Fts5ConfigFree(pTab->p.pConfig);
sqlite3_free(pTab);
}
}
@@ -213249,7 +214435,7 @@ static void fts5FreeVtab(Fts5Table *pTab){
** The xDisconnect() virtual table method.
*/
static int fts5DisconnectMethod(sqlite3_vtab *pVtab){
- fts5FreeVtab((Fts5Table*)pVtab);
+ fts5FreeVtab((Fts5FullTable*)pVtab);
return SQLITE_OK;
}
@@ -213260,7 +214446,7 @@ static int fts5DestroyMethod(sqlite3_vtab *pVtab){
Fts5Table *pTab = (Fts5Table*)pVtab;
int rc = sqlite3Fts5DropAll(pTab->pConfig);
if( rc==SQLITE_OK ){
- fts5FreeVtab((Fts5Table*)pVtab);
+ fts5FreeVtab((Fts5FullTable*)pVtab);
}
return rc;
}
@@ -213289,28 +214475,28 @@ static int fts5InitVtab(
const char **azConfig = (const char**)argv;
int rc = SQLITE_OK; /* Return code */
Fts5Config *pConfig = 0; /* Results of parsing argc/argv */
- Fts5Table *pTab = 0; /* New virtual table object */
+ Fts5FullTable *pTab = 0; /* New virtual table object */
/* Allocate the new vtab object and parse the configuration */
- pTab = (Fts5Table*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Table));
+ pTab = (Fts5FullTable*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5FullTable));
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
}
if( rc==SQLITE_OK ){
- pTab->pConfig = pConfig;
+ pTab->p.pConfig = pConfig;
pTab->pGlobal = pGlobal;
}
/* Open the index sub-system */
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->pIndex, pzErr);
+ rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr);
}
/* Open the storage sub-system */
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageOpen(
- pConfig, pTab->pIndex, bCreate, &pTab->pStorage, pzErr
+ pConfig, pTab->p.pIndex, bCreate, &pTab->pStorage, pzErr
);
}
@@ -213323,8 +214509,8 @@ static int fts5InitVtab(
if( rc==SQLITE_OK ){
assert( pConfig->pzErrmsg==0 );
pConfig->pzErrmsg = pzErr;
- rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
- sqlite3Fts5IndexRollback(pTab->pIndex);
+ rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
+ sqlite3Fts5IndexRollback(pTab->p.pIndex);
pConfig->pzErrmsg = 0;
}
@@ -213537,7 +214723,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
return SQLITE_OK;
}
-static int fts5NewTransaction(Fts5Table *pTab){
+static int fts5NewTransaction(Fts5FullTable *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
@@ -213549,16 +214735,16 @@ static int fts5NewTransaction(Fts5Table *pTab){
** Implementation of xOpen method.
*/
static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
- Fts5Table *pTab = (Fts5Table*)pVTab;
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVTab;
+ Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = 0; /* New cursor object */
- int nByte; /* Bytes of space to allocate */
+ sqlite3_int64 nByte; /* Bytes of space to allocate */
int rc; /* Return code */
rc = fts5NewTransaction(pTab);
if( rc==SQLITE_OK ){
nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
- pCsr = (Fts5Cursor*)sqlite3_malloc(nByte);
+ pCsr = (Fts5Cursor*)sqlite3_malloc64(nByte);
if( pCsr ){
Fts5Global *pGlobal = pTab->pGlobal;
memset(pCsr, 0, nByte);
@@ -213596,7 +214782,7 @@ static void fts5CsrNewrow(Fts5Cursor *pCsr){
}
static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
Fts5Auxdata *pData;
Fts5Auxdata *pNext;
@@ -213640,7 +214826,7 @@ static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
*/
static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
if( pCursor ){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
Fts5Cursor **pp;
@@ -213697,7 +214883,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
** open on table pTab.
*/
-static void fts5TripCursors(Fts5Table *pTab){
+static void fts5TripCursors(Fts5FullTable *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->ePlan==FTS5_PLAN_MATCH
@@ -213724,11 +214910,11 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
int rc = SQLITE_OK;
assert( *pbSkip==0 );
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int bDesc = pCsr->bDesc;
i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
- rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc);
+ rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc);
if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
*pbSkip = 1;
}
@@ -213825,18 +215011,22 @@ static int fts5PrepareStatement(
return rc;
}
-static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
- Fts5Config *pConfig = pTab->pConfig;
+static int fts5CursorFirstSorted(
+ Fts5FullTable *pTab,
+ Fts5Cursor *pCsr,
+ int bDesc
+){
+ Fts5Config *pConfig = pTab->p.pConfig;
Fts5Sorter *pSorter;
int nPhrase;
- int nByte;
+ sqlite3_int64 nByte;
int rc;
const char *zRank = pCsr->zRank;
const char *zRankArgs = pCsr->zRankArgs;
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
- pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
+ pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
if( pSorter==0 ) return SQLITE_NOMEM;
memset(pSorter, 0, nByte);
pSorter->nIdx = nPhrase;
@@ -213873,10 +215063,10 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
return rc;
}
-static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
+static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
int rc;
Fts5Expr *pExpr = pCsr->pExpr;
- rc = sqlite3Fts5ExprFirst(pExpr, pTab->pIndex, pCsr->iFirstRowid, bDesc);
+ rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc);
if( sqlite3Fts5ExprEof(pExpr) ){
CsrFlagSet(pCsr, FTS5CSR_EOF);
}
@@ -213891,7 +215081,7 @@ static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
** parameters.
*/
static int fts5SpecialMatch(
- Fts5Table *pTab,
+ Fts5FullTable *pTab,
Fts5Cursor *pCsr,
const char *zQuery
){
@@ -213902,18 +215092,18 @@ static int fts5SpecialMatch(
while( z[0]==' ' ) z++;
for(n=0; z[n] && z[n]!=' '; n++);
- assert( pTab->base.zErrMsg==0 );
+ assert( pTab->p.base.zErrMsg==0 );
pCsr->ePlan = FTS5_PLAN_SPECIAL;
if( 0==sqlite3_strnicmp("reads", z, n) ){
- pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->pIndex);
+ pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex);
}
else if( 0==sqlite3_strnicmp("id", z, n) ){
pCsr->iSpecial = pCsr->iCsrId;
}
else{
/* An unrecognized directive. Return an error message. */
- pTab->base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
+ pTab->p.base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
rc = SQLITE_ERROR;
}
@@ -213925,7 +215115,7 @@ static int fts5SpecialMatch(
** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary
** structure. Otherwise, if no such function exists, return NULL.
*/
-static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
+static Fts5Auxiliary *fts5FindAuxiliary(Fts5FullTable *pTab, const char *zName){
Fts5Auxiliary *pAux;
for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){
@@ -213938,8 +215128,8 @@ static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
static int fts5FindRankFunction(Fts5Cursor *pCsr){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
+ Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
Fts5Auxiliary *pAux = 0;
const char *zRank = pCsr->zRank;
@@ -213955,7 +215145,7 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
if( rc==SQLITE_OK ){
if( SQLITE_ROW==sqlite3_step(pStmt) ){
- int nByte;
+ sqlite3_int64 nByte;
pCsr->nRankArg = sqlite3_column_count(pStmt);
nByte = sizeof(sqlite3_value*)*pCsr->nRankArg;
pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte);
@@ -213977,8 +215167,8 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
if( rc==SQLITE_OK ){
pAux = fts5FindAuxiliary(pTab, zRank);
if( pAux==0 ){
- assert( pTab->base.zErrMsg==0 );
- pTab->base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
+ assert( pTab->p.base.zErrMsg==0 );
+ pTab->p.base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
rc = SQLITE_ERROR;
}
}
@@ -214053,8 +215243,8 @@ static int fts5FilterMethod(
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
+ Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK; /* Error code */
int iVal = 0; /* Counter for apVal[] */
@@ -214083,8 +215273,8 @@ static int fts5FilterMethod(
assert( pCsr->zRank==0 );
assert( pCsr->zRankArgs==0 );
- assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg );
- pConfig->pzErrmsg = &pTab->base.zErrMsg;
+ assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
+ pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Decode the arguments passed through to this function.
**
@@ -214150,7 +215340,7 @@ static int fts5FilterMethod(
** but a request for an internal parameter. */
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
}else{
- char **pzErr = &pTab->base.zErrMsg;
+ char **pzErr = &pTab->p.base.zErrMsg;
rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
if( rc==SQLITE_OK ){
if( bOrderByRank ){
@@ -214173,7 +215363,7 @@ static int fts5FilterMethod(
** by rowid (ePlan==FTS5_PLAN_ROWID). */
pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
rc = sqlite3Fts5StorageStmt(
- pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->base.zErrMsg
+ pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
);
if( rc==SQLITE_OK ){
if( pCsr->ePlan==FTS5_PLAN_ROWID ){
@@ -214256,12 +215446,12 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
/* If the cursor does not yet have a statement handle, obtain one now. */
if( pCsr->pStmt==0 ){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int eStmt = fts5StmtType(pCsr);
rc = sqlite3Fts5StorageStmt(
- pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->base.zErrMsg:0)
+ pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->p.base.zErrMsg:0)
);
- assert( rc!=SQLITE_OK || pTab->base.zErrMsg==0 );
+ assert( rc!=SQLITE_OK || pTab->p.base.zErrMsg==0 );
assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
}
@@ -214283,11 +215473,11 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
return rc;
}
-static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
+static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
va_list ap; /* ... printf arguments */
va_start(ap, zFormat);
- assert( p->base.zErrMsg==0 );
- p->base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
+ assert( p->p.base.zErrMsg==0 );
+ p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
}
@@ -214307,11 +215497,11 @@ static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
** more commands are added to this function.
*/
static int fts5SpecialInsert(
- Fts5Table *pTab, /* Fts5 table object */
+ Fts5FullTable *pTab, /* Fts5 table object */
const char *zCmd, /* Text inserted into table-name column */
sqlite3_value *pVal /* Value inserted into rank column */
){
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
int bError = 0;
@@ -214346,9 +215536,9 @@ static int fts5SpecialInsert(
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
#endif
}else{
- rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
+ rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError);
+ rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError);
}
if( rc==SQLITE_OK ){
if( bError ){
@@ -214362,7 +215552,7 @@ static int fts5SpecialInsert(
}
static int fts5SpecialDelete(
- Fts5Table *pTab,
+ Fts5FullTable *pTab,
sqlite3_value **apVal
){
int rc = SQLITE_OK;
@@ -214376,7 +215566,7 @@ static int fts5SpecialDelete(
static void fts5StorageInsert(
int *pRc,
- Fts5Table *pTab,
+ Fts5FullTable *pTab,
sqlite3_value **apVal,
i64 *piRowid
){
@@ -214410,8 +215600,8 @@ static int fts5UpdateMethod(
sqlite3_value **apVal, /* Array of arguments */
sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
+ Fts5Config *pConfig = pTab->p.pConfig;
int eType0; /* value_type() of apVal[0] */
int rc = SQLITE_OK; /* Return code */
@@ -214420,12 +215610,11 @@ static int fts5UpdateMethod(
assert( pVtab->zErrMsg==0 );
assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
- assert( nArg==1
- || sqlite3_value_type(apVal[1])==SQLITE_INTEGER
- || sqlite3_value_type(apVal[1])==SQLITE_NULL
+ assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER
+ || sqlite3_value_type(apVal[0])==SQLITE_NULL
);
- assert( pTab->pConfig->pzErrmsg==0 );
- pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
+ assert( pTab->p.pConfig->pzErrmsg==0 );
+ pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Put any active cursors into REQUIRE_SEEK state. */
fts5TripCursors(pTab);
@@ -214466,7 +215655,7 @@ static int fts5UpdateMethod(
/* Filter out attempts to run UPDATE or DELETE on contentless tables.
** This is not suported. */
if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
- pTab->base.zErrMsg = sqlite3_mprintf(
+ pTab->p.base.zErrMsg = sqlite3_mprintf(
"cannot %s contentless fts5 table: %s",
(nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
);
@@ -214479,46 +215668,52 @@ static int fts5UpdateMethod(
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
}
- /* INSERT */
- else if( eType0!=SQLITE_INTEGER ){
- /* If this is a REPLACE, first remove the current entry (if any) */
- if( eConflict==SQLITE_REPLACE
- && sqlite3_value_type(apVal[1])==SQLITE_INTEGER
- ){
- i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+ /* INSERT or UPDATE */
+ else{
+ int eType1 = sqlite3_value_numeric_type(apVal[1]);
+
+ if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){
+ rc = SQLITE_MISMATCH;
}
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
- }
- /* UPDATE */
- else{
- i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
- i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
- if( iOld!=iNew ){
- if( eConflict==SQLITE_REPLACE ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
- }
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
- }else{
- rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
- if( rc==SQLITE_OK ){
+ else if( eType0!=SQLITE_INTEGER ){
+ /* If this is a REPLACE, first remove the current entry (if any) */
+ if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
+ i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+ }
+ fts5StorageInsert(&rc, pTab, apVal, pRowid);
+ }
+
+ /* UPDATE */
+ else{
+ i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
+ i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
+ if( eType1==SQLITE_INTEGER && iOld!=iNew ){
+ if( eConflict==SQLITE_REPLACE ){
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+ }
+ fts5StorageInsert(&rc, pTab, apVal, pRowid);
+ }else{
+ rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
+ }
}
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
- }
+ }else{
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
- }else{
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
}
}
- pTab->pConfig->pzErrmsg = 0;
+ pTab->p.pConfig->pzErrmsg = 0;
return rc;
}
@@ -214527,12 +215722,12 @@ static int fts5UpdateMethod(
*/
static int fts5SyncMethod(sqlite3_vtab *pVtab){
int rc;
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
- pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
+ pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
fts5TripCursors(pTab);
rc = sqlite3Fts5StorageSync(pTab->pStorage);
- pTab->pConfig->pzErrmsg = 0;
+ pTab->p.pConfig->pzErrmsg = 0;
return rc;
}
@@ -214540,8 +215735,8 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
** Implementation of xBegin() method.
*/
static int fts5BeginMethod(sqlite3_vtab *pVtab){
- fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0);
- fts5NewTransaction((Fts5Table*)pVtab);
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
+ fts5NewTransaction((Fts5FullTable*)pVtab);
return SQLITE_OK;
}
@@ -214552,7 +215747,7 @@ static int fts5BeginMethod(sqlite3_vtab *pVtab){
*/
static int fts5CommitMethod(sqlite3_vtab *pVtab){
UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0);
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_COMMIT, 0);
return SQLITE_OK;
}
@@ -214562,7 +215757,7 @@ static int fts5CommitMethod(sqlite3_vtab *pVtab){
*/
static int fts5RollbackMethod(sqlite3_vtab *pVtab){
int rc;
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
return rc;
@@ -214586,13 +215781,13 @@ static int fts5ApiColumnTotalSize(
sqlite3_int64 *pnToken
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken);
}
static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
}
@@ -214627,7 +215822,9 @@ static int fts5ApiColumnText(
){
int rc = SQLITE_OK;
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
+ if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
+ || pCsr->ePlan==FTS5_PLAN_SPECIAL
+ ){
*pz = 0;
*pn = 0;
}else{
@@ -214696,10 +215893,11 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
int rc = SQLITE_OK;
Fts5PoslistReader *aIter; /* One iterator for each phrase */
int nIter; /* Number of iterators/phrases */
+ int nCol = ((Fts5Table*)pCsr->base.pVtab)->pConfig->nCol;
nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
if( pCsr->aInstIter==0 ){
- int nByte = sizeof(Fts5PoslistReader) * nIter;
+ sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nIter;
pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
}
aIter = pCsr->aInstIter;
@@ -214734,7 +215932,7 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
nInst++;
if( nInst>=pCsr->nInstAlloc ){
pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
- aInst = (int*)sqlite3_realloc(
+ aInst = (int*)sqlite3_realloc64(
pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
);
if( aInst ){
@@ -214749,6 +215947,10 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
aInst[0] = iBest;
aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
+ if( aInst[1]<0 || aInst[1]>=nCol ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
}
}
@@ -214821,8 +216023,8 @@ static int fts5ColumnSizeCb(
static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
+ Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
@@ -215078,7 +216280,7 @@ static int fts5ApiQueryPhrase(
int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int rc;
Fts5Cursor *pNew = 0;
@@ -215155,25 +216357,19 @@ static void fts5ApiCallback(
/*
-** Given cursor id iId, return a pointer to the corresponding Fts5Index
+** Given cursor id iId, return a pointer to the corresponding Fts5Table
** object. Or NULL If the cursor id does not exist.
-**
-** If successful, set *ppConfig to point to the associated config object
-** before returning.
*/
-static Fts5Index *sqlite3Fts5IndexFromCsrid(
+static Fts5Table *sqlite3Fts5TableFromCsrid(
Fts5Global *pGlobal, /* FTS5 global context for db handle */
- i64 iCsrId, /* Id of cursor to find */
- Fts5Config **ppConfig /* OUT: Configuration object */
+ i64 iCsrId /* Id of cursor to find */
){
Fts5Cursor *pCsr;
- Fts5Table *pTab;
-
pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
- pTab = (Fts5Table*)pCsr->base.pVtab;
- *ppConfig = pTab->pConfig;
-
- return pTab->pIndex;
+ if( pCsr ){
+ return (Fts5Table*)pCsr->base.pVtab;
+ }
+ return 0;
}
/*
@@ -215253,8 +216449,8 @@ static int fts5ColumnMethod(
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
+ Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK;
@@ -215306,7 +216502,7 @@ static int fts5FindFunctionMethod(
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
void **ppArg /* OUT: User data for *pxFunc */
){
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
Fts5Auxiliary *pAux;
UNUSED_PARAM(nUnused);
@@ -215328,21 +216524,24 @@ static int fts5RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
return sqlite3Fts5StorageRename(pTab->pStorage, zName);
}
+static int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
+ fts5TripCursors((Fts5FullTable*)pTab);
+ return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage);
+}
+
/*
** The xSavepoint() method.
**
** Flush the contents of the pending-terms table to disk.
*/
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
- fts5TripCursors(pTab);
- return sqlite3Fts5StorageSync(pTab->pStorage);
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_SAVEPOINT, iSavepoint);
+ return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
}
/*
@@ -215351,11 +216550,9 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
** This is a no-op.
*/
static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
- fts5TripCursors(pTab);
- return sqlite3Fts5StorageSync(pTab->pStorage);
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_RELEASE, iSavepoint);
+ return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
}
/*
@@ -215364,7 +216561,7 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
** Discard the contents of the pending terms table.
*/
static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
fts5TripCursors(pTab);
@@ -215565,7 +216762,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959a1dd", -1, SQLITE_TRANSIENT);
}
/*
@@ -215814,7 +217011,7 @@ static int fts5StorageGetStmt(
char *zBind;
int i;
- zBind = sqlite3_malloc(1 + nCol*2);
+ zBind = sqlite3_malloc64(1 + nCol*2);
if( zBind ){
for(i=0; i<nCol; i++){
zBind[i*2] = '?';
@@ -215981,11 +217178,11 @@ static int sqlite3Fts5StorageOpen(
){
int rc = SQLITE_OK;
Fts5Storage *p; /* New object */
- int nByte; /* Bytes of space to allocate */
+ sqlite3_int64 nByte; /* Bytes of space to allocate */
nByte = sizeof(Fts5Storage) /* Fts5Storage object */
+ pConfig->nCol * sizeof(i64); /* Fts5Storage.aTotalSize[] */
- *pp = p = (Fts5Storage*)sqlite3_malloc(nByte);
+ *pp = p = (Fts5Storage*)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, nByte);
@@ -215996,7 +217193,7 @@ static int sqlite3Fts5StorageOpen(
if( bCreate ){
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
int nDefn = 32 + pConfig->nCol*10;
- char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
+ char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
if( zDefn==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -216287,7 +217484,7 @@ static int sqlite3Fts5StorageRebuild(Fts5Storage *p){
Fts5Config *pConfig = p->pConfig;
sqlite3_stmt *pScan = 0;
Fts5InsertCtx ctx;
- int rc;
+ int rc, rc2;
memset(&ctx, 0, sizeof(Fts5InsertCtx));
ctx.pStorage = p;
@@ -216326,6 +217523,8 @@ static int sqlite3Fts5StorageRebuild(Fts5Storage *p){
}
}
sqlite3_free(buf.p);
+ rc2 = sqlite3_reset(pScan);
+ if( rc==SQLITE_OK ) rc = rc2;
/* Write the averages record */
if( rc==SQLITE_OK ){
@@ -216575,7 +217774,7 @@ static int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
ctx.pConfig = p->pConfig;
- aTotalSize = (i64*)sqlite3_malloc(pConfig->nCol * (sizeof(int)+sizeof(i64)));
+ aTotalSize = (i64*)sqlite3_malloc64(pConfig->nCol*(sizeof(int)+sizeof(i64)));
if( !aTotalSize ) return SQLITE_NOMEM;
aColSize = (int*)&aTotalSize[pConfig->nCol];
memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
@@ -216775,7 +217974,13 @@ static int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){
static int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
int rc = fts5StorageLoadTotals(p, 0);
if( rc==SQLITE_OK ){
+ /* nTotalRow being zero does not necessarily indicate a corrupt
+ ** database - it might be that the FTS5 table really does contain zero
+ ** rows. However this function is only called from the xRowCount() API,
+ ** and there is no way for that API to be invoked if the table contains
+ ** no rows. Hence the FTS5_CORRUPT return. */
*pnRow = p->nTotalRow;
+ if( p->nTotalRow<=0 ) rc = FTS5_CORRUPT;
}
return rc;
}
@@ -216985,7 +218190,7 @@ static int fts5AsciiTokenize(
nByte = ie-is;
if( nByte>nFold ){
if( pFold!=aFold ) sqlite3_free(pFold);
- pFold = sqlite3_malloc(nByte*2);
+ pFold = sqlite3_malloc64((sqlite3_int64)nByte*2);
if( pFold==0 ){
rc = SQLITE_NOMEM;
break;
@@ -217067,13 +218272,18 @@ struct Unicode61Tokenizer {
unsigned char aTokenChar[128]; /* ASCII range token characters */
char *aFold; /* Buffer to fold text into */
int nFold; /* Size of aFold[] in bytes */
- int bRemoveDiacritic; /* True if remove_diacritics=1 is set */
+ int eRemoveDiacritic; /* True if remove_diacritics=1 is set */
int nException;
int *aiException;
unsigned char aCategory[32]; /* True for token char categories */
};
+/* Values for eRemoveDiacritic (must match internals of fts5_unicode2.c) */
+#define FTS5_REMOVE_DIACRITICS_NONE 0
+#define FTS5_REMOVE_DIACRITICS_SIMPLE 1
+#define FTS5_REMOVE_DIACRITICS_COMPLEX 2
+
static int fts5UnicodeAddExceptions(
Unicode61Tokenizer *p, /* Tokenizer object */
const char *z, /* Characters to treat as exceptions */
@@ -217084,13 +218294,14 @@ static int fts5UnicodeAddExceptions(
int *aNew;
if( n>0 ){
- aNew = (int*)sqlite3_realloc(p->aiException, (n+p->nException)*sizeof(int));
+ aNew = (int*)sqlite3_realloc64(p->aiException,
+ (n+p->nException)*sizeof(int));
if( aNew ){
int nNew = p->nException;
const unsigned char *zCsr = (const unsigned char*)z;
const unsigned char *zTerm = (const unsigned char*)&z[n];
while( zCsr<zTerm ){
- int iCode;
+ u32 iCode;
int bToken;
READ_UTF8(zCsr, zTerm, iCode);
if( iCode<128 ){
@@ -217102,7 +218313,7 @@ static int fts5UnicodeAddExceptions(
if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){
int i;
for(i=0; i<nNew; i++){
- if( aNew[i]>iCode ) break;
+ if( (u32)aNew[i]>iCode ) break;
}
memmove(&aNew[i+1], &aNew[i], (nNew-i)*sizeof(int));
aNew[i] = iCode;
@@ -217194,7 +218405,7 @@ static int fts5UnicodeCreate(
int i;
memset(p, 0, sizeof(Unicode61Tokenizer));
- p->bRemoveDiacritic = 1;
+ p->eRemoveDiacritic = FTS5_REMOVE_DIACRITICS_SIMPLE;
p->nFold = 64;
p->aFold = sqlite3_malloc(p->nFold * sizeof(char));
if( p->aFold==0 ){
@@ -217215,10 +218426,15 @@ static int fts5UnicodeCreate(
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
const char *zArg = azArg[i+1];
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
- if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
+ if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
rc = SQLITE_ERROR;
+ }else{
+ p->eRemoveDiacritic = (zArg[0] - '0');
+ assert( p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_NONE
+ || p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_SIMPLE
+ || p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_COMPLEX
+ );
}
- p->bRemoveDiacritic = (zArg[0]=='1');
}else
if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
rc = fts5UnicodeAddExceptions(p, zArg, 1);
@@ -217252,7 +218468,7 @@ static int fts5UnicodeCreate(
*/
static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){
return (
- p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]
+ p->aCategory[sqlite3Fts5UnicodeCategory((u32)iCode)]
^ fts5UnicodeIsException(p, iCode)
);
}
@@ -217281,7 +218497,7 @@ static int fts5UnicodeTokenize(
/* Each iteration of this loop gobbles up a contiguous run of separators,
** then the next token. */
while( rc==SQLITE_OK ){
- int iCode; /* non-ASCII codepoint read from input */
+ u32 iCode; /* non-ASCII codepoint read from input */
char *zOut = aFold;
int is;
int ie;
@@ -217313,7 +218529,7 @@ static int fts5UnicodeTokenize(
/* Grow the output buffer so that there is sufficient space to fit the
** largest possible utf-8 character. */
if( zOut>pEnd ){
- aFold = sqlite3_malloc(nFold*2);
+ aFold = sqlite3_malloc64((sqlite3_int64)nFold*2);
if( aFold==0 ){
rc = SQLITE_NOMEM;
goto tokenize_done;
@@ -217332,7 +218548,7 @@ static int fts5UnicodeTokenize(
READ_UTF8(zCsr, zTerm, iCode);
if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){
non_ascii_tokenchar:
- iCode = sqlite3Fts5UnicodeFold(iCode, p->bRemoveDiacritic);
+ iCode = sqlite3Fts5UnicodeFold(iCode, p->eRemoveDiacritic);
if( iCode ) WRITE_UTF8(zOut, iCode);
}else{
break;
@@ -218108,10 +219324,8 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
return rc;
}
-
-
/*
-** 2012 May 25
+** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -218140,32 +219354,48 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
-static int fts5_remove_diacritic(int c){
+static int fts5_remove_diacritic(int c, int bComplex){
unsigned short aDia[] = {
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
- 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
- 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
- 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
- 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
- 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
- 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
- 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
- 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
- 62924, 63050, 63082, 63274, 63390,
+ 3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
+ 3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
+ 4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
+ 4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
+ 6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
+ 61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
+ 61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
+ 61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
+ 62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
+ 62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
+ 62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
+ 63182, 63242, 63274, 63310, 63368, 63390,
};
- char aChar[] = {
- '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
- 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
- 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
- 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
- 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
- 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
- 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
- 'e', 'i', 'o', 'u', 'y',
+#define HIBIT ((unsigned char)0x80)
+ unsigned char aChar[] = {
+ '\0', 'a', 'c', 'e', 'i', 'n',
+ 'o', 'u', 'y', 'y', 'a', 'c',
+ 'd', 'e', 'e', 'g', 'h', 'i',
+ 'j', 'k', 'l', 'n', 'o', 'r',
+ 's', 't', 'u', 'u', 'w', 'y',
+ 'z', 'o', 'u', 'a', 'i', 'o',
+ 'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
+ 'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
+ 'e', 'i', 'o', 'r', 'u', 's',
+ 't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
+ 'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', 'a', 'b',
+ 'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
+ 'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
+ 'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
+ 'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
+ 's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
+ 'w', 'x', 'y', 'z', 'h', 't',
+ 'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
+ 'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
+ 'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
@@ -218182,7 +219412,8 @@ static int fts5_remove_diacritic(int c){
}
}
assert( key>=aDia[iRes] );
- return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
+ if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
+ return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
}
@@ -218195,8 +219426,8 @@ static int sqlite3Fts5UnicodeIsdiacritic(int c){
unsigned int mask1 = 0x000361F8;
if( c<768 || c>817 ) return 0;
return (c < 768+32) ?
- (mask0 & (1 << (c-768))) :
- (mask1 & (1 << (c-768-32)));
+ (mask0 & ((unsigned int)1 << (c-768))) :
+ (mask1 & ((unsigned int)1 << (c-768-32)));
}
@@ -218209,7 +219440,7 @@ static int sqlite3Fts5UnicodeIsdiacritic(int c){
** The results are undefined if the value passed to this function
** is less than zero.
*/
-static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
+static int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){
/* Each entry in the following array defines a rule for folding a range
** of codepoints to lower case. The rule applies to a range of nRange
** codepoints starting at codepoint iCode.
@@ -218332,7 +219563,9 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
assert( ret>0 );
}
- if( bRemoveDiacritic ) ret = fts5_remove_diacritic(ret);
+ if( eRemoveDiacritic ){
+ ret = fts5_remove_diacritic(ret, eRemoveDiacritic==2);
+ }
}
else if( c>=66560 && c<66600 ){
@@ -218343,12 +219576,6 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
}
-#if 0
-static int sqlite3Fts5UnicodeNCat(void) {
- return 32;
-}
-#endif
-
static int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
aArray[0] = 1;
switch( zCat[0] ){
@@ -218830,7 +220057,7 @@ static u16 aFts5UnicodeData[] = {
34, 3074, 7692, 63, 63,
};
-static int sqlite3Fts5UnicodeCategory(int iCode) {
+static int sqlite3Fts5UnicodeCategory(u32 iCode) {
int iRes = -1;
int iHi;
int iLo;
@@ -218868,13 +220095,12 @@ static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
int n = (aFts5UnicodeData[iTbl] >> 5) + i;
for(; i<128 && i<n; i++){
- aAscii[i] = (u8)bToken;
+ aAscii[i] = bToken;
}
iTbl++;
}
}
-
/*
** 2015 May 30
**
@@ -218953,7 +220179,7 @@ static int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v){
u8 n;
p -= 2;
n = sqlite3Fts5GetVarint(p, &v64);
- *v = (u32)v64;
+ *v = ((u32)v64) & 0x7FFFFFFF;
assert( n>3 && n<=9 );
return n;
}
@@ -219220,7 +220446,6 @@ static int sqlite3Fts5GetVarintLen(u32 iVal){
return 5;
}
-
/*
** 2015 May 08
**
@@ -219278,7 +220503,7 @@ struct Fts5VocabTable {
struct Fts5VocabCursor {
sqlite3_vtab_cursor base;
sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
- Fts5Index *pIndex; /* Associated FTS5 index */
+ Fts5Table *pFts5; /* Associated FTS5 table */
int bEof; /* True if this cursor is at EOF */
Fts5IndexIter *pIter; /* Term/rowid iterator object */
@@ -219287,7 +220512,6 @@ struct Fts5VocabCursor {
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
/* These are used by 'col' tables only */
- Fts5Config *pConfig; /* Fts5 table configuration */
int iCol;
i64 *aCnt;
i64 *aDoc;
@@ -219550,8 +220774,7 @@ static int fts5VocabOpenMethod(
sqlite3_vtab_cursor **ppCsr
){
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
- Fts5Index *pIndex = 0;
- Fts5Config *pConfig = 0;
+ Fts5Table *pFts5 = 0;
Fts5VocabCursor *pCsr = 0;
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
@@ -219570,31 +220793,34 @@ static int fts5VocabOpenMethod(
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
i64 iId = sqlite3_column_int64(pStmt, 0);
- pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
+ pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId);
}
- if( rc==SQLITE_OK && pIndex==0 ){
- rc = sqlite3_finalize(pStmt);
- pStmt = 0;
- if( rc==SQLITE_OK ){
- pVTab->zErrMsg = sqlite3_mprintf(
- "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
- );
- rc = SQLITE_ERROR;
+ if( rc==SQLITE_OK ){
+ if( pFts5==0 ){
+ rc = sqlite3_finalize(pStmt);
+ pStmt = 0;
+ if( rc==SQLITE_OK ){
+ pVTab->zErrMsg = sqlite3_mprintf(
+ "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
+ );
+ rc = SQLITE_ERROR;
+ }
+ }else{
+ rc = sqlite3Fts5FlushToDisk(pFts5);
}
}
if( rc==SQLITE_OK ){
- int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
+ int nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
}
if( pCsr ){
- pCsr->pIndex = pIndex;
+ pCsr->pFts5 = pFts5;
pCsr->pStmt = pStmt;
- pCsr->pConfig = pConfig;
pCsr->aCnt = (i64*)&pCsr[1];
- pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
+ pCsr->aDoc = &pCsr->aCnt[pFts5->pConfig->nCol];
}else{
sqlite3_finalize(pStmt);
}
@@ -219610,6 +220836,7 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
sqlite3_free(pCsr->zLeTerm);
pCsr->nLeTerm = -1;
pCsr->zLeTerm = 0;
+ pCsr->bEof = 0;
}
/*
@@ -219648,7 +220875,7 @@ static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
}
static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
- int eDetail = pCsr->pConfig->eDetail;
+ int eDetail = pCsr->pFts5->pConfig->eDetail;
int rc = SQLITE_OK;
Fts5IndexIter *pIter = pCsr->pIter;
i64 *pp = &pCsr->iInstPos;
@@ -219683,7 +220910,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
int rc = SQLITE_OK;
- int nCol = pCsr->pConfig->nCol;
+ int nCol = pCsr->pFts5->pConfig->nCol;
pCsr->rowid++;
@@ -219705,6 +220932,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
int nTerm;
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
+ assert( nTerm>=0 );
if( pCsr->nLeTerm>=0 ){
int nCmp = MIN(nTerm, pCsr->nLeTerm);
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
@@ -219721,7 +220949,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
while( rc==SQLITE_OK ){
- int eDetail = pCsr->pConfig->eDetail;
+ int eDetail = pCsr->pFts5->pConfig->eDetail;
const u8 *pPos; int nPos; /* Position list */
i64 iPos = 0; /* 64-bit position read from poslist */
int iOff = 0; /* Current offset within position list */
@@ -219744,7 +220972,6 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
int iCol = -1;
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
int ii = FTS5_POS2COLUMN(iPos);
- pCsr->aCnt[ii]++;
if( iCol!=ii ){
if( ii>=nCol ){
rc = FTS5_CORRUPT;
@@ -219753,6 +220980,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->aDoc[ii]++;
iCol = ii;
}
+ pCsr->aCnt[ii]++;
}
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
@@ -219781,7 +221009,9 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( rc==SQLITE_OK ){
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
- if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
+ if( nTerm!=pCsr->term.n
+ || (nTerm>0 && memcmp(zTerm, pCsr->term.p, nTerm))
+ ){
break;
}
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
@@ -219792,7 +221022,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++;
- assert( pCsr->iCol<pCsr->pConfig->nCol );
+ assert( pCsr->iCol<pCsr->pFts5->pConfig->nCol );
}
return rc;
}
@@ -219839,6 +221069,7 @@ static int fts5VocabFilterMethod(
}
if( pLe ){
const char *zCopy = (const char *)sqlite3_value_text(pLe);
+ if( zCopy==0 ) zCopy = "";
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
if( pCsr->zLeTerm==0 ){
@@ -219850,14 +221081,15 @@ static int fts5VocabFilterMethod(
}
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
+ Fts5Index *pIndex = pCsr->pFts5->pIndex;
+ rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
}
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
rc = fts5VocabInstanceNewTerm(pCsr);
}
- if( rc==SQLITE_OK
- && !pCsr->bEof
- && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
+ if( rc==SQLITE_OK && !pCsr->bEof
+ && (eType!=FTS5_VOCAB_INSTANCE
+ || pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE)
){
rc = fts5VocabNextMethod(pCursor);
}
@@ -219880,7 +221112,7 @@ static int fts5VocabColumnMethod(
int iCol /* Index of column to read value from */
){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
- int eDetail = pCsr->pConfig->eDetail;
+ int eDetail = pCsr->pFts5->pConfig->eDetail;
int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
i64 iVal = 0;
@@ -219892,7 +221124,7 @@ static int fts5VocabColumnMethod(
assert( iCol==1 || iCol==2 || iCol==3 );
if( iCol==1 ){
if( eDetail!=FTS5_DETAIL_NONE ){
- const char *z = pCsr->pConfig->azCol[pCsr->iCol];
+ const char *z = pCsr->pFts5->pConfig->azCol[pCsr->iCol];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
}else if( iCol==2 ){
@@ -219920,8 +221152,8 @@ static int fts5VocabColumnMethod(
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
ii = (int)pCsr->iInstPos;
}
- if( ii>=0 && ii<pCsr->pConfig->nCol ){
- const char *z = pCsr->pConfig->azCol[ii];
+ if( ii>=0 && ii<pCsr->pFts5->pConfig->nCol ){
+ const char *z = pCsr->pFts5->pConfig->azCol[ii];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
break;
@@ -220294,9 +221526,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=220297
+#if __LINE__!=221529
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt2"
+#define SQLITE_SOURCE_ID "2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/chromium/third_party/sqlite/amalgamation/sqlite3.h b/chromium/third_party/sqlite/amalgamation/sqlite3.h
index 3caa3d50732..0755e9c1f72 100644
--- a/chromium/third_party/sqlite/amalgamation/sqlite3.h
+++ b/chromium/third_party/sqlite/amalgamation/sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.26.0"
-#define SQLITE_VERSION_NUMBER 3026000
-#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt1"
+#define SQLITE_VERSION "3.27.1"
+#define SQLITE_VERSION_NUMBER 3027001
+#define SQLITE_SOURCE_ID "2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959alt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -823,6 +823,15 @@ struct sqlite3_io_methods {
** file space based on this hint in order to help writes to the database
** file run faster.
**
+** <li>[[SQLITE_FCNTL_SIZE_LIMIT]]
+** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that
+** implements [sqlite3_deserialize()] to set an upper bound on the size
+** of the in-memory database. The argument is a pointer to a [sqlite3_int64].
+** If the integer pointed to is negative, then it is filled in with the
+** current limit. Otherwise the limit is set to the larger of the value
+** of the integer pointed to and the current database size. The integer
+** pointed to is set to the new limit.
+**
** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
** extends and truncates the database file in chunks of a size specified
@@ -1131,6 +1140,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
#define SQLITE_FCNTL_DATA_VERSION 35
+#define SQLITE_FCNTL_SIZE_LIMIT 36
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1972,6 +1982,17 @@ struct sqlite3_mem_methods {
** negative value for this option restores the default behaviour.
** This option is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
+**
+** [[SQLITE_CONFIG_MEMDB_MAXSIZE]]
+** <dt>SQLITE_CONFIG_MEMDB_MAXSIZE
+** <dd>The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter
+** [sqlite3_int64] parameter which is the default maximum size for an in-memory
+** database created using [sqlite3_deserialize()]. This default maximum
+** size can be adjusted up or down for individual databases using the
+** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this
+** configuration setting is never used, then the default maximum is determined
+** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
+** compile-time option is not set, then the default maximum is 1073741824.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -2002,6 +2023,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
+#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -2991,9 +3013,9 @@ SQLITE_API int sqlite3_set_authorizer(
** time is in units of nanoseconds, however the current implementation
** is only capable of millisecond resolution so the six least significant
** digits in the time are meaningless. Future versions of SQLite
-** might provide greater resolution on the profiler callback. The
-** sqlite3_profile() function is considered experimental and is
-** subject to change in future versions of SQLite.
+** might provide greater resolution on the profiler callback. Invoking
+** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the
+** profile callback.
*/
SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*,
void(*xTrace)(void*,const char*), void*);
@@ -3407,6 +3429,8 @@ SQLITE_API int sqlite3_open_v2(
** is not a database file pathname pointer that SQLite passed into the xOpen
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
+**
+** See the [URI filename] documentation for additional information.
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
@@ -3629,14 +3653,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently.
**
-** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
-** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
-** representation of the SQL statement should be calculated and then
-** associated with the prepared statement, which can be obtained via
-** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
-** normalize a SQL statement are unspecified and subject to change.
-** At a minimum, literal values will be replaced with suitable
-** placeholders.
+** [[SQLITE_PREPARE_NORMALIZE]] <dt>SQLITE_PREPARE_NORMALIZE</dt>
+** <dd>The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used
+** to be required for any prepared statement that wanted to use the
+** [sqlite3_normalized_sql()] interface. However, the
+** [sqlite3_normalized_sql()] interface is now available to all
+** prepared statements, regardless of whether or not they use this
+** flag.
**
** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
@@ -10025,7 +10048,7 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** sqlite3changeset_next() is called on the iterator or until the
** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
** set to the number of columns in the table affected by the change. If
-** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change
+** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
** changes. Finally, if pOp is not NULL, then *pOp is set to one of
@@ -11259,12 +11282,8 @@ struct Fts5PhraseIter {
**
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
** to the column in which it occurs and *piOff the token offset of the
-** first token of the phrase. The exception is if the table was created
-** with the offsets=0 option specified. In this case *piOff is always
-** set to -1.
-**
-** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
-** if an error occurs.
+** first token of the phrase. Returns SQLITE_OK if successful, or an error
+** code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
@@ -11553,11 +11572,11 @@ struct Fts5ExtensionApi {
** the tokenizer substitutes "first" for "1st" and the query works
** as expected.
**
-** <li> By adding multiple synonyms for a single term to the FTS index.
-** In this case, when tokenizing query text, the tokenizer may
-** provide multiple synonyms for a single term within the document.
-** FTS5 then queries the index for each synonym individually. For
-** example, faced with the query:
+** <li> By querying the index for all synonyms of each query term
+** separately. In this case, when tokenizing query text, the
+** tokenizer may provide multiple synonyms for a single term
+** within the document. FTS5 then queries the index for each
+** synonym individually. For example, faced with the query:
**
** <codeblock>
** ... MATCH 'first place'</codeblock>
@@ -11581,7 +11600,7 @@ struct Fts5ExtensionApi {
** "place".
**
** This way, even if the tokenizer does not provide synonyms
-** when tokenizing query text (it should not - to do would be
+** when tokenizing query text (it should not - to do so would be
** inefficient), it doesn't matter if the user queries for
** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
diff --git a/chromium/third_party/sqlite/fuzz/DEPS b/chromium/third_party/sqlite/fuzz/DEPS
deleted file mode 100644
index 8eb68bc404d..00000000000
--- a/chromium/third_party/sqlite/fuzz/DEPS
+++ /dev/null
@@ -1 +0,0 @@
-include_rules = [ '+testing/libfuzzer/proto', '+base' ]
diff --git a/chromium/third_party/sqlite/fuzz/disabled_queries_parser.cc b/chromium/third_party/sqlite/fuzz/disabled_queries_parser.cc
deleted file mode 100644
index c2bd17b7ffb..00000000000
--- a/chromium/third_party/sqlite/fuzz/disabled_queries_parser.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/sqlite/fuzz/disabled_queries_parser.h"
-
-namespace sql_fuzzer {
-
-std::set<std::string> ParseDisabledQueries(std::string query_list) {
- // Trimming
- query_list.erase(query_list.find_last_not_of(" \t\n\r\f\v") + 1);
- query_list.erase(0, query_list.find_first_not_of(" \t\n\r\f\v"));
- std::set<std::string> ret;
- std::string curr_query;
- for (size_t i = 0; i < query_list.length(); i++) {
- if (query_list[i] == ',') {
- ret.insert(curr_query);
- curr_query.clear();
- continue;
- }
- curr_query += query_list[i];
- }
- if (curr_query.length() != 0) {
- // Add last query, which doesn't have a trailing comma
- ret.insert(curr_query);
- }
- return ret;
-}
-
-} // namespace sql_fuzzer
diff --git a/chromium/third_party/sqlite/fuzz/disabled_queries_parser.h b/chromium/third_party/sqlite/fuzz/disabled_queries_parser.h
deleted file mode 100644
index 665b8719d01..00000000000
--- a/chromium/third_party/sqlite/fuzz/disabled_queries_parser.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_SQLITE_FUZZ_DISABLED_QUERIES_PARSER_H_
-#define THIRD_PARTY_SQLITE_FUZZ_DISABLED_QUERIES_PARSER_H_
-
-#include <set>
-#include <string>
-
-namespace sql_fuzzer {
-// |query_list| should be a list of disabled queries separated only by commas.
-std::set<std::string> ParseDisabledQueries(std::string query_list);
-} // namespace sql_fuzzer
-
-#endif // THIRD_PARTY_SQLITE_FUZZ_DISABLED_QUERIES_PARSER_H_
diff --git a/chromium/third_party/sqlite/fuzz/icu_codes.proto b/chromium/third_party/sqlite/fuzz/icu_codes.proto
deleted file mode 100644
index d3d470a79b5..00000000000
--- a/chromium/third_party/sqlite/fuzz/icu_codes.proto
+++ /dev/null
@@ -1,189 +0,0 @@
-syntax = "proto2";
-
-package sql_query_grammar;
-
-enum IsoLangCode {
- ISO_LANG_CODE_ab = 1;
- ISO_LANG_CODE_af = 2;
- ISO_LANG_CODE_ak = 3;
- ISO_LANG_CODE_sq = 4;
- ISO_LANG_CODE_am = 5;
- ISO_LANG_CODE_ar = 6;
- ISO_LANG_CODE_an = 7;
- ISO_LANG_CODE_hy = 8;
- ISO_LANG_CODE_as = 9;
- ISO_LANG_CODE_av = 10;
- ISO_LANG_CODE_ae = 11;
- ISO_LANG_CODE_ay = 12;
- ISO_LANG_CODE_az = 13;
- ISO_LANG_CODE_ba = 14;
- ISO_LANG_CODE_bm = 15;
- ISO_LANG_CODE_eu = 16;
- ISO_LANG_CODE_be = 17;
- ISO_LANG_CODE_bn = 18;
- ISO_LANG_CODE_bh = 19;
- ISO_LANG_CODE_bi = 20;
- ISO_LANG_CODE_bs = 21;
- ISO_LANG_CODE_br = 22;
- ISO_LANG_CODE_bg = 23;
- ISO_LANG_CODE_my = 24;
- ISO_LANG_CODE_ca = 25;
- ISO_LANG_CODE_ch = 26;
- ISO_LANG_CODE_ce = 27;
- ISO_LANG_CODE_zh = 28;
- ISO_LANG_CODE_cu = 29;
- ISO_LANG_CODE_cv = 30;
- ISO_LANG_CODE_kw = 31;
- ISO_LANG_CODE_co = 32;
- ISO_LANG_CODE_cr = 33;
- ISO_LANG_CODE_cs = 34;
- ISO_LANG_CODE_da = 35;
- ISO_LANG_CODE_dv = 36;
- ISO_LANG_CODE_nl = 37;
- ISO_LANG_CODE_dz = 38;
- ISO_LANG_CODE_en = 39;
- ISO_LANG_CODE_eo = 40;
- ISO_LANG_CODE_et = 41;
- ISO_LANG_CODE_ee = 42;
- ISO_LANG_CODE_fo = 43;
- ISO_LANG_CODE_fj = 44;
- ISO_LANG_CODE_fi = 45;
- ISO_LANG_CODE_fr = 46;
- ISO_LANG_CODE_fy = 47;
- ISO_LANG_CODE_ff = 48;
- ISO_LANG_CODE_ka = 49;
- ISO_LANG_CODE_de = 50;
- ISO_LANG_CODE_gd = 51;
- ISO_LANG_CODE_ga = 52;
- ISO_LANG_CODE_gl = 53;
- ISO_LANG_CODE_gv = 54;
- ISO_LANG_CODE_el = 55;
- ISO_LANG_CODE_gn = 56;
- ISO_LANG_CODE_gu = 57;
- ISO_LANG_CODE_ht = 58;
- ISO_LANG_CODE_ha = 59;
- ISO_LANG_CODE_he = 60;
- ISO_LANG_CODE_hz = 61;
- ISO_LANG_CODE_hi = 62;
- ISO_LANG_CODE_ho = 63;
- ISO_LANG_CODE_hr = 64;
- ISO_LANG_CODE_hu = 65;
- ISO_LANG_CODE_ig = 66;
- ISO_LANG_CODE_is = 67;
- ISO_LANG_CODE_io = 68;
- ISO_LANG_CODE_ii = 69;
- ISO_LANG_CODE_iu = 70;
- ISO_LANG_CODE_ie = 71;
- ISO_LANG_CODE_ia = 72;
- ISO_LANG_CODE_id = 73;
- ISO_LANG_CODE_ik = 74;
- ISO_LANG_CODE_it = 75;
- ISO_LANG_CODE_jv = 76;
- ISO_LANG_CODE_ja = 77;
- ISO_LANG_CODE_kl = 78;
- ISO_LANG_CODE_kn = 79;
- ISO_LANG_CODE_ks = 80;
- ISO_LANG_CODE_kr = 81;
- ISO_LANG_CODE_kk = 82;
- ISO_LANG_CODE_km = 83;
- ISO_LANG_CODE_ki = 84;
- ISO_LANG_CODE_rw = 85;
- ISO_LANG_CODE_ky = 86;
- ISO_LANG_CODE_kv = 87;
- ISO_LANG_CODE_kg = 88;
- ISO_LANG_CODE_ko = 89;
- ISO_LANG_CODE_kj = 90;
- ISO_LANG_CODE_ku = 91;
- ISO_LANG_CODE_lo = 92;
- ISO_LANG_CODE_la = 93;
- ISO_LANG_CODE_lv = 94;
- ISO_LANG_CODE_li = 95;
- ISO_LANG_CODE_ln = 96;
- ISO_LANG_CODE_lt = 97;
- ISO_LANG_CODE_lb = 98;
- ISO_LANG_CODE_lu = 99;
- ISO_LANG_CODE_lg = 100;
- ISO_LANG_CODE_mk = 101;
- ISO_LANG_CODE_mh = 102;
- ISO_LANG_CODE_ml = 103;
- ISO_LANG_CODE_mi = 104;
- ISO_LANG_CODE_mr = 105;
- ISO_LANG_CODE_ms = 106;
- ISO_LANG_CODE_mg = 107;
- ISO_LANG_CODE_mt = 108;
- ISO_LANG_CODE_mn = 109;
- ISO_LANG_CODE_na = 110;
- ISO_LANG_CODE_nv = 111;
- ISO_LANG_CODE_nr = 112;
- ISO_LANG_CODE_nd = 113;
- ISO_LANG_CODE_ng = 114;
- ISO_LANG_CODE_ne = 115;
- ISO_LANG_CODE_nn = 116;
- ISO_LANG_CODE_nb = 117;
- ISO_LANG_CODE_no = 118;
- ISO_LANG_CODE_ny = 119;
- ISO_LANG_CODE_oc = 120;
- ISO_LANG_CODE_oj = 121;
- ISO_LANG_CODE_or = 122;
- ISO_LANG_CODE_om = 123;
- ISO_LANG_CODE_os = 124;
- ISO_LANG_CODE_pa = 125;
- ISO_LANG_CODE_fa = 126;
- ISO_LANG_CODE_pi = 127;
- ISO_LANG_CODE_pl = 128;
- ISO_LANG_CODE_pt = 129;
- ISO_LANG_CODE_ps = 130;
- ISO_LANG_CODE_qu = 131;
- ISO_LANG_CODE_rm = 132;
- ISO_LANG_CODE_ro = 133;
- ISO_LANG_CODE_rn = 134;
- ISO_LANG_CODE_ru = 135;
- ISO_LANG_CODE_sg = 136;
- ISO_LANG_CODE_sa = 137;
- ISO_LANG_CODE_si = 138;
- ISO_LANG_CODE_sk = 139;
- ISO_LANG_CODE_sl = 140;
- ISO_LANG_CODE_se = 141;
- ISO_LANG_CODE_sm = 142;
- ISO_LANG_CODE_sn = 143;
- ISO_LANG_CODE_sd = 144;
- ISO_LANG_CODE_so = 145;
- ISO_LANG_CODE_st = 146;
- ISO_LANG_CODE_es = 147;
- ISO_LANG_CODE_sc = 148;
- ISO_LANG_CODE_sr = 149;
- ISO_LANG_CODE_ss = 150;
- ISO_LANG_CODE_su = 151;
- ISO_LANG_CODE_sw = 152;
- ISO_LANG_CODE_sv = 153;
- ISO_LANG_CODE_ty = 154;
- ISO_LANG_CODE_ta = 155;
- ISO_LANG_CODE_tt = 156;
- ISO_LANG_CODE_te = 157;
- ISO_LANG_CODE_tg = 158;
- ISO_LANG_CODE_tl = 159;
- ISO_LANG_CODE_th = 160;
- ISO_LANG_CODE_bo = 161;
- ISO_LANG_CODE_ti = 162;
- ISO_LANG_CODE_to = 163;
- ISO_LANG_CODE_tn = 164;
- ISO_LANG_CODE_ts = 165;
- ISO_LANG_CODE_tk = 166;
- ISO_LANG_CODE_tr = 167;
- ISO_LANG_CODE_tw = 168;
- ISO_LANG_CODE_ug = 169;
- ISO_LANG_CODE_uk = 170;
- ISO_LANG_CODE_ur = 171;
- ISO_LANG_CODE_uz = 172;
- ISO_LANG_CODE_ve = 173;
- ISO_LANG_CODE_vi = 174;
- ISO_LANG_CODE_vo = 175;
- ISO_LANG_CODE_cy = 176;
- ISO_LANG_CODE_wa = 177;
- ISO_LANG_CODE_wo = 178;
- ISO_LANG_CODE_xh = 179;
- ISO_LANG_CODE_yi = 180;
- ISO_LANG_CODE_yo = 181;
- ISO_LANG_CODE_za = 182;
- ISO_LANG_CODE_zu = 183;
-}
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries0 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries0
deleted file mode 100644
index 7a36870f564..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries0
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries1 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries1
deleted file mode 100644
index f2853929d0c..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries1
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries10 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries10
deleted file mode 100644
index cbc9fa63c8d..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries10
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries11 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries11
deleted file mode 100644
index 9ee13e908f9..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries11
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries12 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries12
deleted file mode 100644
index 04ae159ae62..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries12
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries13 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries13
deleted file mode 100644
index 25fc7c70260..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries13
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries14 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries14
deleted file mode 100644
index e4e0a74810a..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries14
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries15 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries15
deleted file mode 100644
index 6ef088e4694..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries15
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries16 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries16
deleted file mode 100644
index f45f4a2229d..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries16
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries17 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries17
deleted file mode 100644
index 6d48cb7e597..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries17
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries18 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries18
deleted file mode 100644
index 4fb9debe4a4..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries18
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries19 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries19
deleted file mode 100644
index 529b54edfb1..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries19
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries2 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries2
deleted file mode 100644
index c51cd5f3081..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries2
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries3 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries3
deleted file mode 100644
index 530de34a290..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries3
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries4 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries4
deleted file mode 100644
index b879fe23c80..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries4
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries5 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries5
deleted file mode 100644
index c443de66e6d..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries5
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries6 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries6
deleted file mode 100644
index 3841499fd98..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries6
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries7 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries7
deleted file mode 100644
index a90d08846bb..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries7
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries8 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries8
deleted file mode 100644
index 98ede46b5b8..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries8
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries9 b/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries9
deleted file mode 100644
index 4d4c15c39c7..00000000000
--- a/chromium/third_party/sqlite/fuzz/lpm_fuzzer_seed_corpus/corpus_queries9
+++ /dev/null
Binary files differ
diff --git a/chromium/third_party/sqlite/fuzz/sql.dict b/chromium/third_party/sqlite/fuzz/sql.dict
deleted file mode 100644
index 691b961ac21..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql.dict
+++ /dev/null
@@ -1,909 +0,0 @@
-#
-# AFL dictionary for SQL
-# ----------------------
-#
-# Modeled based on SQLite documentation, contains some number of SQLite
-# extensions. Other dialects of SQL may benefit from customized dictionaries.
-#
-# If you append @1 to the file name when loading this dictionary, afl-fuzz
-# will also additionally load a selection of pragma keywords that are very
-# specific to SQLite (and are probably less interesting from the security
-# standpoint, because they are usually not allowed in non-privileged
-# contexts).
-#
-# Created by Michal Zalewski <lcamtuf@google.com>
-#
-
-function_abs=" abs(1)"
-function_avg=" avg(1)"
-function_changes=" changes()"
-function_char=" char(1)"
-function_coalesce=" coalesce(1,1)"
-function_count=" count(1)"
-function_date=" date(1,1,1)"
-function_datetime=" datetime(1,1,1)"
-function_decimal=" decimal(1,1)"
-function_glob=" glob(1,1)"
-function_group_concat=" group_concat(1,1)"
-function_hex=" hex(1)"
-function_ifnull=" ifnull(1,1)"
-function_instr=" instr(1,1)"
-function_julianday=" julianday(1,1,1)"
-function_last_insert_rowid=" last_insert_rowid()"
-function_length=" length(1)"
-function_like=" like(1,1)"
-function_likelihood=" likelihood(1,1)"
-function_likely=" likely(1)"
-function_load_extension=" load_extension(1,1)"
-function_lower=" lower(1)"
-function_ltrim=" ltrim(1,1)"
-function_max=" max(1,1)"
-function_min=" min(1,1)"
-function_nullif=" nullif(1,1)"
-function_printf=" printf(1,1)"
-function_quote=" quote(1)"
-function_random=" random()"
-function_randomblob=" randomblob(1)"
-function_replace=" replace(1,1,1)"
-function_round=" round(1,1)"
-function_rtrim=" rtrim(1,1)"
-function_soundex=" soundex(1)"
-function_sqlite_compileoption_get=" sqlite_compileoption_get(1)"
-function_sqlite_compileoption_used=" sqlite_compileoption_used(1)"
-function_sqlite_source_id=" sqlite_source_id()"
-function_sqlite_version=" sqlite_version()"
-function_strftime=" strftime(1,1,1,1)"
-function_substr=" substr(1,1,1)"
-function_sum=" sum(1)"
-function_time=" time(1,1,1)"
-function_total=" total(1)"
-function_total_changes=" total_changes()"
-function_trim=" trim(1,1)"
-function_typeof=" typeof(1)"
-function_unicode=" unicode(1)"
-function_unlikely=" unlikely(1)"
-function_upper=" upper(1)"
-function_varchar=" varchar(1)"
-function_zeroblob=" zeroblob(1)"
-
-keyword_ABORT="ABORT"
-keyword_ACTION="ACTION"
-keyword_ADD="ADD"
-keyword_AFTER="AFTER"
-keyword_ALL="ALL"
-keyword_ALTER="ALTER"
-keyword_ANALYZE="ANALYZE"
-keyword_AND="AND"
-keyword_AS="AS"
-keyword_ASC="ASC"
-keyword_ATTACH="ATTACH"
-keyword_AUTOINCREMENT="AUTOINCREMENT"
-keyword_BEFORE="BEFORE"
-keyword_BEGIN="BEGIN"
-keyword_BETWEEN="BETWEEN"
-keyword_BY="BY"
-keyword_CASCADE="CASCADE"
-keyword_CASE="CASE"
-keyword_CAST="CAST"
-keyword_CHECK="CHECK"
-keyword_COLLATE="COLLATE"
-keyword_COLUMN="COLUMN"
-keyword_COMMIT="COMMIT"
-keyword_CONFLICT="CONFLICT"
-keyword_CONSTRAINT="CONSTRAINT"
-keyword_CREATE="CREATE"
-keyword_CROSS="CROSS"
-keyword_CURRENT_DATE="CURRENT_DATE"
-keyword_CURRENT_TIME="CURRENT_TIME"
-keyword_CURRENT_TIMESTAMP="CURRENT_TIMESTAMP"
-keyword_DATABASE="DATABASE"
-keyword_DEFAULT="DEFAULT"
-keyword_DEFERRABLE="DEFERRABLE"
-keyword_DEFERRED="DEFERRED"
-keyword_DELETE="DELETE"
-keyword_DESC="DESC"
-keyword_DETACH="DETACH"
-keyword_DISTINCT="DISTINCT"
-keyword_DROP="DROP"
-keyword_EACH="EACH"
-keyword_ELSE="ELSE"
-keyword_END="END"
-keyword_ESCAPE="ESCAPE"
-keyword_EXCEPT="EXCEPT"
-keyword_EXCLUSIVE="EXCLUSIVE"
-keyword_EXISTS="EXISTS"
-keyword_EXPLAIN="EXPLAIN"
-keyword_FAIL="FAIL"
-keyword_FOR="FOR"
-keyword_FOREIGN="FOREIGN"
-keyword_FROM="FROM"
-keyword_FULL="FULL"
-keyword_GLOB="GLOB"
-keyword_GROUP="GROUP"
-keyword_HAVING="HAVING"
-keyword_IF="IF"
-keyword_IGNORE="IGNORE"
-keyword_IMMEDIATE="IMMEDIATE"
-keyword_IN="IN"
-keyword_INDEX="INDEX"
-keyword_INDEXED="INDEXED"
-keyword_INITIALLY="INITIALLY"
-keyword_INNER="INNER"
-keyword_INSERT="INSERT"
-keyword_INSTEAD="INSTEAD"
-keyword_INTERSECT="INTERSECT"
-keyword_INTO="INTO"
-keyword_IS="IS"
-keyword_ISNULL="ISNULL"
-keyword_JOIN="JOIN"
-keyword_KEY="KEY"
-keyword_LEFT="LEFT"
-keyword_LIKE="LIKE"
-keyword_LIMIT="LIMIT"
-keyword_MATCH="MATCH"
-keyword_NATURAL="NATURAL"
-keyword_NO="NO"
-keyword_NOT="NOT"
-keyword_NOTNULL="NOTNULL"
-keyword_NULL="NULL"
-keyword_OF="OF"
-keyword_OFFSET="OFFSET"
-keyword_ON="ON"
-keyword_OR="OR"
-keyword_ORDER="ORDER"
-keyword_OUTER="OUTER"
-keyword_PLAN="PLAN"
-keyword_PRAGMA="PRAGMA"
-keyword_PRIMARY="PRIMARY"
-keyword_QUERY="QUERY"
-keyword_RAISE="RAISE"
-keyword_RECURSIVE="RECURSIVE"
-keyword_REFERENCES="REFERENCES"
-#keyword_REGEXP="REGEXP"
-keyword_REINDEX="REINDEX"
-keyword_RELEASE="RELEASE"
-keyword_RENAME="RENAME"
-keyword_REPLACE="REPLACE"
-keyword_RESTRICT="RESTRICT"
-keyword_RIGHT="RIGHT"
-keyword_ROLLBACK="ROLLBACK"
-keyword_ROW="ROW"
-keyword_SAVEPOINT="SAVEPOINT"
-keyword_SELECT="SELECT"
-keyword_SET="SET"
-keyword_TABLE="TABLE"
-keyword_TEMP="TEMP"
-keyword_TEMPORARY="TEMPORARY"
-keyword_THEN="THEN"
-keyword_TO="TO"
-keyword_TRANSACTION="TRANSACTION"
-keyword_TRIGGER="TRIGGER"
-keyword_UNION="UNION"
-keyword_UNIQUE="UNIQUE"
-keyword_UPDATE="UPDATE"
-keyword_USING="USING"
-keyword_VACUUM="VACUUM"
-keyword_VALUES="VALUES"
-keyword_VIEW="VIEW"
-keyword_VIRTUAL="VIRTUAL"
-keyword_WHEN="WHEN"
-keyword_WHERE="WHERE"
-keyword_WITH="WITH"
-keyword_WITHOUT="WITHOUT"
-
-operator_concat=" || "
-operator_ebove_eq=" >="
-
-snippet_1eq1=" 1=1"
-snippet_at=" @1"
-snippet_backticks=" `a`"
-snippet_blob=" blob"
-snippet_brackets=" [a]"
-snippet_colon=" :1"
-snippet_comment=" /* */"
-snippet_date="2001-01-01"
-snippet_dollar=" $1"
-snippet_dotref=" a.b"
-snippet_fmtY="%Y"
-snippet_int=" int"
-snippet_neg1=" -1"
-snippet_pair=" a,b"
-snippet_parentheses=" (1)"
-snippet_plus2days="+2 days"
-snippet_qmark=" ?1"
-snippet_semicolon=" ;"
-snippet_star=" *"
-snippet_string_pair=" \"a\",\"b\""
-
-string_dbl_q=" \"a\""
-string_escaped_q=" 'a''b'"
-string_single_q=" 'a'"
-
-pragma_application_id@1=" application_id"
-pragma_auto_vacuum@1=" auto_vacuum"
-pragma_automatic_index@1=" automatic_index"
-pragma_busy_timeout@1=" busy_timeout"
-pragma_cache_size@1=" cache_size"
-pragma_cache_spill@1=" cache_spill"
-pragma_case_sensitive_like@1=" case_sensitive_like"
-pragma_checkpoint_fullfsync@1=" checkpoint_fullfsync"
-pragma_collation_list@1=" collation_list"
-pragma_compile_options@1=" compile_options"
-pragma_count_changes@1=" count_changes"
-pragma_data_store_directory@1=" data_store_directory"
-pragma_database_list@1=" database_list"
-pragma_default_cache_size@1=" default_cache_size"
-pragma_defer_foreign_keys@1=" defer_foreign_keys"
-pragma_empty_result_callbacks@1=" empty_result_callbacks"
-pragma_encoding@1=" encoding"
-pragma_foreign_key_check@1=" foreign_key_check"
-pragma_foreign_key_list@1=" foreign_key_list"
-pragma_foreign_keys@1=" foreign_keys"
-pragma_freelist_count@1=" freelist_count"
-pragma_full_column_names@1=" full_column_names"
-pragma_fullfsync@1=" fullfsync"
-pragma_ignore_check_constraints@1=" ignore_check_constraints"
-pragma_incremental_vacuum@1=" incremental_vacuum"
-pragma_index_info@1=" index_info"
-pragma_index_list@1=" index_list"
-pragma_integrity_check@1=" integrity_check"
-pragma_journal_mode@1=" journal_mode"
-pragma_journal_size_limit@1=" journal_size_limit"
-pragma_legacy_file_format@1=" legacy_file_format"
-pragma_locking_mode@1=" locking_mode"
-pragma_max_page_count@1=" max_page_count"
-pragma_mmap_size@1=" mmap_size"
-pragma_page_count@1=" page_count"
-pragma_page_size@1=" page_size"
-pragma_parser_trace@1=" parser_trace"
-pragma_query_only@1=" query_only"
-pragma_quick_check@1=" quick_check"
-pragma_read_uncommitted@1=" read_uncommitted"
-pragma_recursive_triggers@1=" recursive_triggers"
-pragma_reverse_unordered_selects@1=" reverse_unordered_selects"
-pragma_schema_version@1=" schema_version"
-pragma_secure_delete@1=" secure_delete"
-pragma_short_column_names@1=" short_column_names"
-pragma_shrink_memory@1=" shrink_memory"
-pragma_soft_heap_limit@1=" soft_heap_limit"
-pragma_stats@1=" stats"
-pragma_synchronous@1=" synchronous"
-pragma_table_info@1=" table_info"
-pragma_temp_store@1=" temp_store"
-pragma_temp_store_directory@1=" temp_store_directory"
-pragma_threads@1=" threads"
-pragma_user_version@1=" user_version"
-pragma_vdbe_addoptrace@1=" vdbe_addoptrace"
-pragma_vdbe_debug@1=" vdbe_debug"
-pragma_vdbe_listing@1=" vdbe_listing"
-pragma_vdbe_trace@1=" vdbe_trace"
-pragma_wal_autocheckpoint@1=" wal_autocheckpoint"
-pragma_wal_checkpoint@1=" wal_checkpoint"
-pragma_writable_schema@1=" writable_schema"
-
-
-# This part has been generated with testing/libfuzzer/dictionary_generator.py
-# using sqlite3_prepare_v2_fuzzer binary and ISO/IEC FCD 9075-1.
-"all"
-"code"
-"BE"
-"text"
-"TP2,"
-"supported"
-"GR4)"
-"syntax"
-"S151,"
-"S043,"
-"\xe2\x80\x9cCR\xe2\x80\x9d"
-"(SQL/PSM)"
-"query"
-"expressions"
-"TP2;"
-"row"
-"[ISO9075-14],"
-"BNF."
-"<SQL"
-"parameters"
-"title"
-"S211,"
-"ISO/IEC:"
-"BNF,"
-"SQL_FEATURES"
-"should"
-"to"
-"only"
-"program"
-"present"
-"T211,"
-"G,"
-"local"
-"NY"
-"columns"
-"END."
-"do"
-"OBJECT"
-"rollback"
-"string"
-"FEAT2."
-"get"
-"H"
-"P001,"
-"between"
-"RI."
-"[ISO9075-11]"
-"cannot"
-"entries"
-"referencing"
-"datetime"
-"[UCS]."
-"BNF"
-"MINUTE"
-"(BNF"
-"IEC,"
-"False"
-"OF,"
-"level"
-"did"
-"W."
-"list"
-"large"
-"SQL)"
-"PSM."
-"(ISO/IEC"
-"SQL,"
-"SQL-"
-"SQL."
-"small"
-"x"
-"DEFINITION_SCHEMA;"
-"view"
-"Index"
-"[ISO9075-3])."
-"set"
-"S024,"
-"CHANGE."
-"reference"
-"T1,"
-"OLAP."
-"direct"
-"(SQL/XML)."
-"LARGE"
-"likely"
-"result"
-"T341,"
-"ST"
-"ISO/JTC"
-"INSERT,"
-"PKG004"
-"index"
-"PKG006"
-"PKG007"
-"PKG001"
-"PKG002"
-"PKG008"
-"supplied"
-"T611,"
-"access"
-"3"
-"version"
-"NULL."
-"routine"
-"[ISO9075-10])."
-"S1"
-"[UCS],"
-"P003,"
-"C"
-"terms"
-"(SQL/MED)"
-"JTC1/SC32"
-"K"
-"(SQL/JRT)"
-"modify"
-"reported"
-"S"
-"objects"
-"32N1821"
-"SECOND."
-"key"
-"UNDER"
-"(ANSI)"
-"rows"
-"come"
-"(CALL"
-"change"
-"P-"
-"both"
-"search"
-"SQLSTATE,"
-"[ISO9075-"
-"[ISO9075-14]."
-"many"
-"changed"
-"foreign"
-"Symbols"
-"S023,"
-"connection"
-"SQL\xe2\x80\x9d),"
-"context"
-"delete"
-"changes"
-"REFERENCES,"
-"page."
-"named"
-"point"
-"UPDATE."
-"S2"
-"UPDATE,"
-"[ISO9075-13]"
-"Y\xe2\x80\x9d"
-"replace"
-"\xe2\x80\x9cPSM\xe2\x80\x9d"
-"SERIALIZABLE,"
-"names"
-"E"
-"PUBLIC."
-"table"
-"REF"
-"INFORMATION_SCHEMA"
-"C1."
-"ID."
-"use"
-"[ISO9075-2]."
-"from"
-"USA"
-"0"
-"distinct"
-"create"
-"contains"
-"due"
-"ISO."
-"few"
-"duplicate"
-"trigger"
-"call"
-"S111,"
-"expected"
-"REPEATABLE"
-"C1"
-"DOCUMENT"
-"type"
-"authorization"
-"more"
-"XML"
-"[ISO9075-3],"
-"<A>,"
-"P"
-"on"
-"initial"
-"name,"
-"[ISO9075-11]),"
-"QE,"
-"STANDARD"
-"PKG010"
-"TRIGGER,"
-"V"
-"CS"
-"SQL\xe2\x80\x9d:"
-"IEC"
-"Expression"
-"F521,"
-"sequence:"
-"must"
-"none"
-"SR3)"
-"word"
-"INTERNATIONAL"
-"ANSI"
-"this"
-"PSM"
-"PUBLIC),"
-"modified"
-"value"
-"<"
-"descriptor"
-"while"
-"paragraph"
-"values"
-"resources"
-"error"
-"exceptions"
-"IT"
-"F,"
-"CO,"
-"[ISO9075-4],"
-"control"
-"type,"
-"reserved"
-"SQL:"
-"<C>"
-"[ISO9075-2])."
-"F052,"
-"attribute"
-"is"
-"type:"
-"level,"
-"it"
-"[ISO9075-2],"
-"incremental"
-"MONTH,"
-"dropped"
-"MONTH."
-"allowed"
-"S241,"
-"\xe2\x80\x9cSQL"
-"TIMESTAMP"
-"failed"
-"SC"
-"end"
-"Format"
-"ST."
-"permission"
-"V,"
-"length"
-"same"
-"[ISO10646]."
-"write"
-"arguments"
-"F555,"
-"F671,"
-"<C>,"
-"<C>."
-"parameter"
-"NATIONAL"
-"Types"
-"A"
-"Insert"
-"32/WG"
-"used"
-"temporary"
-"\xe2\x80\x9cOLAP\xe2\x80\x9d"
-"(FCD)"
-"may"
-"after"
-"(SQL/OLB)"
-"THIS"
-"Q"
-"SQL/CLI"
-"levels"
-"two"
-"characters"
-"date"
-"such"
-"[ISO9075-9]"
-"data"
-"stack"
-"single"
-"a"
-"FEAT,"
-"lower"
-"transaction"
-"in"
-"database"
-"EXTRACT)"
-"expression"
-"32N1963"
-"CD"
-"without"
-"QE."
-"1"
-"CALL"
-"F"
-"[ISO9075-4])."
-"entry"
-"the"
-"SUBJECT"
-"N1968;"
-"order"
-"left"
-"FEAT1,"
-"FEAT1."
-"S081,"
-"YEAR"
-"READ,"
-"SQL;"
-"A,"
-"symbols"
-"S161,"
-"[ISO9075-10]"
-"already"
-"identify"
-"V."
-"during"
-"differs"
-"(UCS)."
-"Final"
-"before"
-"tables"
-"[UCS]"
-"Multiple"
-"integer"
-"NT,"
-"character"
-","
-"ID\xe2\x80\x9d"
-"(INFORMATION_SCHEMA)"
-"source"
-"add"
-"other"
-"TP1"
-"SQLSTATE"
-"has"
-"match"
-"KEY."
-"real"
-"On"
-"C1,"
-"D"
-"[ISO14651]"
-"views"
-"read"
-"\xe2\x80\x9cGR\xe2\x80\x9d"
-"L"
-"primary"
-"TB1."
-"qualified"
-"(SUBSTRING,"
-"T"
-"compound"
-"not"
-"using"
-"unique"
-"LOB"
-"name"
-"term"
-"sorting"
-"like"
-"B,"
-"[ISO9075-1]"
-"RESULT,"
-"Numeric"
-"MONTH"
-"PURPOSES."
-"[ISO9075-11]."
-"mode"
-"(DEFINITION_SCHEMA)."
-"SQL"
-"ISO"
-"page"
-"constraints"
-"\xc2\xa9ISO/IEC"
-"right"
-"Java"
-"sequence"
-"TB1"
-"TB2"
-"P002,"
-"DAY,"
-"extended"
-"(SQL/CLI)"
-"X"
-"specified"
-"S051,"
-"clauses"
-"operation"
-"FEAT"
-"out"
-"E,"
-"XML."
-"for"
-"space"
-"support"
-"T041,"
-"[ISO9075-4]"
-"content"
-"I"
-"does"
-"STUDY"
-"CHARACTER,"
-"B1"
-"T212,"
-"be"
-"object"
-"[ISO9075-11],"
-"G"
-"ZONE,"
-"S2."
-"collations"
-"[ISO9075-2]:"
-"<A>"
-"O"
-"standard"
-"[ISO9075-2]"
-"base"
-"W"
-"collation"
-"HOUR,"
-"UNDER,"
-"JTC"
-"C."
-"definition"
-"Square"
-"\xe2\x80\x9cSR\xe2\x80\x9d"
-"extension"
-"constraint"
-"column"
-"of"
-"C,"
-"F701,"
-"(SQL/CLI)."
-"T191,"
-"range"
-"GR"
-"1,"
-"constructor"
-"commit"
-"or"
-"first"
-"referenced"
-"statements"
-"encoding"
-"B1."
-"clause"
-"variables"
-"within"
-"number"
-"one"
-"NT"
-"variable"
-"because"
-"references"
-"another"
-"blank"
-"operator"
-"RETURN"
-"COMMITTED,"
-"9075-1:2011(E)"
-"[ISO9075-14]"
-"(SQL/OLB)."
-"D1"
-"exists"
-"REFERENCE"
-"area"
-"S041,"
-"unknown"
-"Symbol"
-"there"
-"system"
-"long"
-"ID"
-"start"
-"returns"
-"2"
-"authorized"
-"statement"
-"X2"
-"FCD"
-"STILL"
-"S231,"
-"final"
-"READ"
-"schema"
-"function"
-"DELETE,"
-"B"
-"TC\xe2\x80\x9d."
-"declare"
-"month"
-"Deprecated"
-"exactly"
-"[ISO10646]"
-"JTC1"
-"but"
-"9075-1:2010(E)"
-"part"
-"T201,"
-"D2."
-"<B>,"
-"attempt"
-"line"
-"with"
-"than"
-"<B>"
-"BEFORE,"
-"DAY."
-"DATE"
-"default"
-"EXECUTE."
-"B1,"
-"F191,"
-"tree"
-"second"
-"SHOULD"
-"[ISO9075-13],"
-"A1,"
-"1/SC"
-"VARYING,"
-"<B>."
-"SQL/CLI,"
-"were"
-"1)"
-"<A>."
-"CLI,"
-"called"
-"are"
-"and"
-"(SQL/MED)."
-"[ISO9075-4]:"
-"associated"
-"\xe2\x80\x9cAR\xe2\x80\x9d"
-"defined"
-"(SQL/XML)"
-"CHARACTER"
-"argument"
-"an"
-"[ISO9075-4])"
-"non-deterministic"
-"as"
-"Other"
-"at"
-"have"
-"[ISO9075-4]."
-"CS."
-"\xe2\x80\x9cV\xe2\x80\x9d"
-"Y."
-"null"
-"any"
-"CLI"
-"Function"
-"NOTE"
-"functions"
-"UCS"
-"returned"
-"F411,"
-"no"
-"TIME"
-"that"
-"-"
-"RETURN),"
-"A1"
-"OLAP"
-"internal"
-"S071,"
-"[ISO9075-10],"
-"T431,"
-"A1."
-"\xe2\x80\x9cONLY"
-"Y"
-"SS"
-"UNCOMMITTED,"
-"multiple"
-"Name"
-"truncate"
-"normal"
-"symbol"
-"literal"
-"M"
-"\xe2\x80\x9c<SQL"
-"prepared"
-"most"
-"ATOMIC,"
-"E."
-"U"
-"letter"
-"PUBLIC"
-"identical"
-"F491,"
-"N"
-"inserted"
-"Page"
-"(SQL/JRT)."
-"D,"
-"SELECT,"
-"USED"
-"lead"
-"Sequence"
-"FEAT1"
-"into"
-"required"
-"[ISO9075-9],"
-"USAGE,"
-"2nd"
-"depth"
-"R"
-"ISO,"
-"time"
-"SQL\xe2\x80\x9d,"
-"FEAT2"
-"[ISO9075-3]"
-"(SQL/PSM)."
-"ISO/IEC"
diff --git a/chromium/third_party/sqlite/fuzz/sql_expr_fuzzer.cc b/chromium/third_party/sqlite/fuzz/sql_expr_fuzzer.cc
deleted file mode 100644
index f20e5d9fb93..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_expr_fuzzer.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "testing/libfuzzer/proto/lpm_interface.h"
-#include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
-#include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
-#include "third_party/sqlite/fuzz/sql_run_queries.h"
-
-using namespace sql_query_grammar;
-
-DEFINE_BINARY_PROTO_FUZZER(const Expr& expr) {
- std::string expr_str = sql_fuzzer::ExprToString(expr);
- // Convert printf command into runnable SQL query.
- expr_str = "SELECT " + expr_str + ";";
-
- if (::getenv("LPM_DUMP_NATIVE_INPUT")) {
- std::cout << "_________________________" << std::endl;
- std::cout << expr_str << std::endl;
- std::cout << "------------------------" << std::endl;
- }
-
- std::vector<std::string> queries;
- queries.push_back(expr_str);
- sql_fuzzer::RunSqlQueries(queries, ::getenv("LPM_SQLITE_TRACE"));
-}
diff --git a/chromium/third_party/sqlite/fuzz/sql_fuzzer.cc b/chromium/third_party/sqlite/fuzz/sql_fuzzer.cc
deleted file mode 100644
index 5b5c8009bdf..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_fuzzer.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "testing/libfuzzer/proto/lpm_interface.h"
-#include "third_party/sqlite/fuzz/disabled_queries_parser.h"
-#include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
-#include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
-#include "third_party/sqlite/fuzz/sql_run_queries.h"
-
-using namespace sql_query_grammar;
-
-// TODO(mpdenton) Fuzzing tasks
-// 5. Definitely fix a lot of the syntax errors that SQlite spits out
-// 12. CORPUS Indexes on expressions (https://www.sqlite.org/expridx.html) and
-// other places using functions on columns???
-// 17. Generate a nice big random, well-formed corpus.
-// 18. Possibly very difficult for fuzzer to find certain areas of code, because
-// some protobufs need to be mutated together. For example, an index on an
-// expression is useless to change, if you don't change the SELECTs that use
-// that expression. May need to create a mechanism for the protobufs to
-// "register" (in the c++ fuzzer) expressions being used for certain purposes,
-// and then protobufs can simple reference those expressions later (similarly to
-// columns or tables, with just an index). This should be added if coverage
-// shows it is the case.
-
-// FIXME in the future
-// 1. Rest of the pragmas
-// 2. Make sure defensive config is off
-// 3. Fuzz the recover extension from the third patch
-// 5. Temp-file database, for better fuzzing of VACUUM and journalling.
-
-DEFINE_BINARY_PROTO_FUZZER(const SQLQueries& sql_queries) {
- char* skip_queries = ::getenv("SQL_SKIP_QUERIES");
- if (skip_queries) {
- sql_fuzzer::SetDisabledQueries(
- sql_fuzzer::ParseDisabledQueries(skip_queries));
- }
-
- std::vector<std::string> queries = sql_fuzzer::SQLQueriesToVec(sql_queries);
-
- if (::getenv("LPM_DUMP_NATIVE_INPUT") && queries.size() != 0) {
- std::cout << "_________________________" << std::endl;
- for (std::string query : queries) {
- if (query == ";")
- continue;
- std::cout << query << std::endl;
- }
- std::cout << "------------------------" << std::endl;
- }
-
- sql_fuzzer::RunSqlQueries(queries, ::getenv("LPM_SQLITE_TRACE"));
-}
diff --git a/chromium/third_party/sqlite/fuzz/sql_generate_corpus.cc b/chromium/third_party/sqlite/fuzz/sql_generate_corpus.cc
deleted file mode 100644
index a16101ebae7..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_generate_corpus.cc
+++ /dev/null
@@ -1,969 +0,0 @@
-#include <unistd.h>
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "base/no_destructor.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/time/default_clock.h"
-// TODO(mpdenton) okay to include this? Otherwise I'm copying it into this file
-// Tehcnically the std random number engines are banned in Chrome but if this
-// used base::Rand* this turns milliseconds into hours.
-#include "third_party/libFuzzer/src/FuzzerRandom.h"
-#include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
-#include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
-#include "third_party/sqlite/fuzz/sql_run_queries.h"
-
-using namespace sql_query_grammar;
-
-// TODO(mpdenton):
-// 2. Add functionality to start with a specific database so that the
-// fuzzer doesn't waste so much time getting a sufficiently complicated
-// database.
-// 3. FTS3 Corpus
-
-namespace {
-constexpr int kMinNumInsertions = 15;
-constexpr int kMaxNumInsertions = 20;
-constexpr int kMinNumIndexes = 5;
-constexpr int kMaxNumIndexes = 8;
-constexpr int kMinNumSelects = 3;
-constexpr int kMaxNumSelects = 6;
-constexpr int kMinNumJoins = 3;
-constexpr int kMaxNumJoins = 3;
-constexpr int kMinNumUpdates = 15;
-constexpr int kMaxNumUpdates = 20;
-constexpr int kMinNumDeletes = 5;
-constexpr int kMaxNumDeletes = 5;
-constexpr int kMinNumOthers = 10;
-constexpr int kMaxNumOthers = 10;
-} // namespace
-
-fuzzer::Random& GetRandom() {
- static base::NoDestructor<fuzzer::Random> rand([] {
- unsigned seed = base::DefaultClock::GetInstance()
- ->Now()
- .ToDeltaSinceWindowsEpoch()
- .InMicroseconds() +
- getpid();
- return fuzzer::Random(seed);
- }());
- return *rand;
-}
-
-// Inclusive range.
-int RandInt(int min, int max) {
- return GetRandom()(max - min + 1) + min;
-}
-
-void RandBytes(void* output, size_t output_len) {
- uint8_t* out = static_cast<uint8_t*>(output);
- for (size_t i = 0; i < output_len / sizeof(size_t); i++) {
- size_t rand_num = GetRandom()();
- for (size_t j = 0; j < sizeof(size_t); j++) {
- *out = *reinterpret_cast<uint8_t*>(&rand_num);
- out++;
- rand_num >>= 8;
- }
- }
- size_t rand_num = GetRandom()();
- for (size_t j = 0; j < output_len % sizeof(size_t); j++) {
- *out = *reinterpret_cast<uint8_t*>(&rand_num);
- out++;
- rand_num >>= 8;
- }
-}
-
-std::string RandBytesAsString(size_t length) {
- std::string result;
- RandBytes(base::WriteInto(&result, length + 1), length);
- return result;
-}
-
-uint64_t RandUint64() {
- if (sizeof(size_t) == sizeof(uint64_t))
- return GetRandom()();
-
- CHECK(sizeof(size_t) == sizeof(uint32_t));
- uint64_t rand = GetRandom()();
- rand <<= 32;
- rand |= GetRandom()();
- return rand;
-}
-
-namespace i {
-struct Table {
- uint32_t table_num;
- int num_columns;
- std::vector<CastTypeName::CastTypeNameEnum> col_types;
- std::vector<std::unique_ptr<Expr>> index_exprs;
-};
-
-struct Schema {
- int num_tables;
- std::vector<i::Table> tables;
-};
-} // namespace i
-
-// WOW, a template AND a macro??? :)
-template <typename T>
-int GetRandomEnum(T is_valid_fn, int min, int max) {
- int r;
- while (!is_valid_fn(r = RandInt(min, max)))
- ;
- return r;
-}
-
-#define RANDOM_ENUM(CLASS_NAME, ENUM_NAME) \
- static_cast<CLASS_NAME::ENUM_NAME>( \
- GetRandomEnum(CLASS_NAME::ENUM_NAME##_IsValid, \
- CLASS_NAME::ENUM_NAME##_MIN, CLASS_NAME::ENUM_NAME##_MAX))
-
-std::set<uint32_t> GetRandomNums(size_t size, uint32_t max_num) {
- std::set<unsigned int> ret;
- while (ret.size() < size)
- ret.insert(RandInt(0, max_num));
- return ret;
-}
-
-template <typename T>
-std::set<T> GetRandomSubset(const std::set<T>& s, size_t size) {
- std::set<T> ret;
- std::set<uint32_t> indices = GetRandomNums(size, s.size() - 1);
-
- auto it = s.begin();
- for (unsigned int i = 0; i < s.size(); i++) {
- if (indices.count(i) > 0) {
- ret.insert(*it);
- }
- it++;
- }
-
- return ret;
-}
-
-inline ColumnDef* CreateDefaultColDef(ColumnDef* cd) {
- cd->mutable_col()->set_column(0);
- return cd;
-}
-
-inline ComplicatedExpr* CreateDefaultCompExpr(ComplicatedExpr* ce) {
- ce->mutable_lit_val();
- return ce;
-}
-
-inline void CreateColumn(Column* col_ptr, uint32_t col) {
- col_ptr->set_column(col);
-}
-
-inline void CreateTableFromUint32(Table* table_ptr, uint32_t table) {
- table_ptr->set_table(table);
-}
-
-inline void CreateSchemaTable(ExprSchemaTable* e, i::Table* table) {
- CreateTableFromUint32(e->mutable_table_name(), table->table_num);
-}
-
-inline void CreateColumnExpr(Expr* e, uint32_t col, i::Table* table) {
- ExprSchemaTableColumn* stc =
- CreateDefaultCompExpr(e->mutable_comp_expr())->mutable_expr_stc();
- CreateColumn(stc->mutable_col(), col);
- if (table)
- CreateTableFromUint32(stc->mutable_table(), table->table_num);
-}
-
-std::set<uint32_t> GenerateColumnList(ColumnList* ret, i::Table* table) {
- std::set<uint32_t> cols;
- for (int i = 0; i < RandInt(1, table->num_columns); i++) {
- cols.insert(RandInt(0, table->num_columns - 1));
- }
- std::set<uint32_t> cols_copy = cols;
- auto it = cols.begin();
- CreateColumn(ret->mutable_col(), *it);
- cols.erase(it);
- ret->mutable_extra_cols()->Reserve(cols.size());
- for (uint32_t col : cols) {
- CreateColumn(ret->mutable_extra_cols()->Add(), col);
- }
- return cols_copy;
-}
-
-void GenerateNumericLit(NumericLiteral* nl) {
- for (int i = 0; i < RandInt(1, 20); i++) {
- nl->add_digits(RandInt(0, 9));
- }
- nl->set_decimal_point(true);
- for (int i = 0; i < RandInt(1, 20); i++) {
- nl->add_dec_digits(RandInt(0, 9));
- }
-}
-
-void GenerateLiteralValue(LiteralValue* ret,
- CastTypeName::CastTypeNameEnum type) {
- if (RandInt(1, 10) == 1) {
- ret->set_special_val(RANDOM_ENUM(LiteralValue, SpecialVal));
- return;
- }
-
- if (type == CastTypeName::INTEGER ||
- (type == CastTypeName::NUMERIC && RandInt(1, 2) == 1)) {
- if (RandInt(1, 3) == 1)
- ret->set_num_lit((int64_t)RandInt(1, 3));
- else
- ret->set_num_lit((int64_t)RandUint64());
- } else if (type == CastTypeName::TEXT) {
- if (RandInt(1, 3) == 1)
- ret->set_string_lit("a");
- else
- // string literals too often have unreadable chars, so instead of rand
- // bytes just use a couple extra #'s
- ret->set_string_lit("#####");
- } else if (type == CastTypeName::BLOB) {
- if (RandInt(1, 3) == 1)
- ret->set_blob_lit("a");
- else
- ret->set_blob_lit(RandBytesAsString(5));
- } else if (type == CastTypeName::REAL) {
- GenerateNumericLit(ret->mutable_numeric_lit());
- } else {
- ret->set_special_val(RANDOM_ENUM(LiteralValue, SpecialVal));
- }
-}
-
-void GenerateValuesStatement(ValuesStatement* v,
- i::Table* table,
- std::set<uint32_t> cols) {
- int rand_num_values = RandInt(1, 10);
- if (rand_num_values > 1)
- v->mutable_extra_expr_lists()->Reserve(rand_num_values - 1);
- for (int i = 0; i < rand_num_values; i++) {
- ExprList* el;
- if (i == 0) {
- el = v->mutable_expr_list();
- } else {
- el = v->mutable_extra_expr_lists()->Add();
- }
- auto it = cols.begin();
- GenerateLiteralValue(el->mutable_expr()->mutable_lit_val(),
- table->col_types[*it]);
- it++;
- el->mutable_extra_exprs()->Reserve(cols.size() - 1);
- for (size_t i = 0; i < cols.size() - 1; i++) {
- GenerateLiteralValue(el->mutable_extra_exprs()->Add()->mutable_lit_val(),
- table->col_types[*it]);
- it++;
- }
- }
-}
-
-void GenerateWhereStatement(WhereStatement* where,
- i::Schema* schema,
- i::Table* table,
- bool join = false) {
- BinaryExpr* we = where->mutable_expr()
- ->mutable_expr()
- ->mutable_comp_expr()
- ->mutable_binary_expr();
-
- // TODO(mpdenton) exclude joins for now.
- if (!join && table->index_exprs.size() != 0 && RandInt(1, 5) >= 4) {
- // Use an indexed expression
- *we->mutable_lhs() =
- *table->index_exprs[RandInt(0, table->index_exprs.size() - 1)];
- we->set_op(BINOP_LEQ);
- GenerateLiteralValue(we->mutable_rhs()->mutable_lit_val(),
- CastTypeName::NUMERIC);
- return;
- }
-
- // Otherwise just use a simple predicate
- uint32_t col = RandInt(0, table->num_columns - 1);
- ExprSchemaTableColumn* stc =
- we->mutable_lhs()->mutable_comp_expr()->mutable_expr_stc();
- CreateColumn(stc->mutable_col(), col);
- if (join)
- CreateTableFromUint32(stc->mutable_table(), table->table_num);
- if (table->col_types[col] == CastTypeName::BLOB) {
- we->set_op(BINOP_NOTEQ);
- we->mutable_rhs()->mutable_lit_val()->set_special_val(
- LiteralValue::VAL_NULL);
- } else if (table->col_types[col] == CastTypeName::TEXT) {
- we->set_op(BINOP_REGEXP);
- we->mutable_rhs()->mutable_lit_val()->set_string_lit(".*");
- } else {
- we->set_op(BINOP_LEQ);
- we->mutable_rhs()->mutable_lit_val()->set_num_lit(RandUint64());
- }
-}
-
-void GenerateInsertion(Insert* i, i::Schema* schema, i::Table* table) {
- // TODO(mpdenton) generate With statement
- // i->set_insert_type(RANDOM_ENUM(Insert, InsertType));
-
- if (RandInt(1, 2) == 1)
- i->set_insert_type(Insert::INSERT);
- else
- i->set_insert_type(Insert::REPLACE);
-
- SchemaTableAsAlias* staa = i->mutable_staa();
- CreateSchemaTable(staa->mutable_schema_table(), table);
-
- if (RandInt(1, 5) >= 2) {
- std::set<uint32_t> cols = GenerateColumnList(i->mutable_col_list(), table);
- GenerateValuesStatement(i->mutable_values(), table, cols);
- }
-}
-
-void GenerateUpdate(Update* u, i::Schema* schema, i::Table* table) {
- SchemaTableAsAlias* staa = u->mutable_qtn()->mutable_staa();
- CreateSchemaTable(staa->mutable_schema_table(), table);
-
- ColEqualsExpr* cee = u->mutable_ucp2()->mutable_cee();
- uint32_t col = RandInt(0, table->num_columns - 1);
- CreateColumn(cee->mutable_col(), col);
- GenerateLiteralValue(cee->mutable_expr()->mutable_lit_val(),
- table->col_types[col]);
-
- if (RandInt(1, 10) >= 2)
- GenerateWhereStatement(u->mutable_ucp2()->mutable_where_stmt(), schema,
- table);
-}
-
-void GenerateDelete(Delete* d, i::Schema* schema, i::Table* table) {
- SchemaTableAsAlias* staa = d->mutable_qtn()->mutable_staa();
- CreateSchemaTable(staa->mutable_schema_table(), table);
-
- if (RandInt(1, 20) >= 2)
- GenerateWhereStatement(d->mutable_where(), schema, table);
-}
-
-void GenerateCreateTable(CreateTable* ct, i::Schema* schema, i::Table* table) {
- ct->set_if_not_exists(false);
- if (RandInt(1, 4) == 1) {
- ct->set_temp_modifier(TM_TEMP);
- }
-
- CreateSchemaTable(ct->mutable_schema_table(), table);
-
- if (table->num_columns > 1)
- ct->mutable_op1()->mutable_extra_col_defs()->Reserve(table->num_columns -
- 1);
-
- for (int i = 0; i < table->num_columns; i++) {
- ColumnDef* col_def;
- if (i == 0)
- col_def = ct->mutable_op1()->mutable_col_def();
- else
- col_def = ct->mutable_op1()->mutable_extra_col_defs()->Add();
- CreateColumn(col_def->mutable_col(), i);
- col_def->mutable_type_name()->mutable_ctn()->set_type_enum(
- table->col_types[i]);
- // Set default values
- GenerateLiteralValue(
- col_def->add_col_constraints()->mutable_opt2()->mutable_lit_val(),
- table->col_types[i]);
- }
-}
-
-bool IsNumeric(CastTypeName::CastTypeNameEnum type) {
- return (type == CastTypeName::NUMERIC || type == CastTypeName::INTEGER ||
- type == CastTypeName::REAL);
-}
-
-Expr* GenerateJoinConstaints(i::Table* table,
- const std::vector<i::Table*>& join_tables) {
- std::vector<i::Table*> all_tables = join_tables;
- all_tables.push_back(table);
- // Decide some columns have to be equal
- std::vector<std::pair<ExprSchemaTableColumn*, ExprSchemaTableColumn*>>
- equal_cols;
- std::vector<BinaryOperator> comparison_ops;
-
- // Would be better if the num_constraints
- do {
- ExprSchemaTableColumn* a = new ExprSchemaTableColumn;
- ExprSchemaTableColumn* b = new ExprSchemaTableColumn;
- int table_index_a = RandInt(0, all_tables.size() - 1);
- CreateTableFromUint32(a->mutable_table(),
- all_tables[table_index_a]->table_num);
- int table_index_b;
- while ((table_index_b = RandInt(0, all_tables.size() - 1)) == table_index_a)
- ;
- CreateTableFromUint32(b->mutable_table(),
- all_tables[table_index_b]->table_num);
-
- uint32_t col_a = RandInt(0, all_tables[table_index_a]->num_columns - 1);
- uint32_t col_b = RandInt(0, all_tables[table_index_b]->num_columns - 1);
- CreateColumn(a->mutable_col(), col_a);
- CreateColumn(b->mutable_col(), col_b);
-
- equal_cols.push_back({a, b});
-
- // If both columns are numeric, small chance of using a comparison op
- // instead.
- if (IsNumeric(all_tables[table_index_a]->col_types[col_a]) &&
- IsNumeric(all_tables[table_index_b]->col_types[col_b]) &&
- RandInt(1, 2) == 1)
- comparison_ops.push_back(BINOP_LEQ);
- else
- comparison_ops.push_back(BINOP_EQ);
- } while (RandInt(1, 3) >= 2);
-
- // Actually generate the expressions.
- Expr* initial_expr = new Expr;
- Expr* curr_expr = initial_expr;
- for (size_t i = 0; i < equal_cols.size() - 1; i++) {
- BinaryExpr* bin_expr = CreateDefaultCompExpr(curr_expr->mutable_comp_expr())
- ->mutable_binary_expr();
- BinaryExpr* lhs_bin_expr =
- bin_expr->mutable_lhs()->mutable_comp_expr()->mutable_binary_expr();
- lhs_bin_expr->mutable_lhs()->mutable_comp_expr()->set_allocated_expr_stc(
- equal_cols[i].first);
- lhs_bin_expr->set_op(comparison_ops[i]);
- lhs_bin_expr->mutable_rhs()->mutable_comp_expr()->set_allocated_expr_stc(
- equal_cols[i].second);
-
- if (RandInt(1, 2) == 1)
- bin_expr->set_op(BINOP_AND);
- else
- bin_expr->set_op(BINOP_OR);
-
- curr_expr = bin_expr->mutable_rhs();
- }
- // Finish off final expr
- size_t last_index = equal_cols.size() - 1;
- BinaryExpr* bin_expr = CreateDefaultCompExpr(curr_expr->mutable_comp_expr())
- ->mutable_binary_expr();
- bin_expr->mutable_lhs()->mutable_comp_expr()->set_allocated_expr_stc(
- equal_cols[last_index].first);
- bin_expr->set_op(comparison_ops[last_index]);
- bin_expr->mutable_rhs()->mutable_comp_expr()->set_allocated_expr_stc(
- equal_cols[last_index].second);
-
- return initial_expr;
-}
-
-void GenerateFromStatement(FromStatement* from,
- i::Schema* schema,
- i::Table* table,
- const std::vector<i::Table*>& join_tables) {
- // TODO(mpdenton) join statements?
- if (join_tables.size() == 0) {
- SchemaTableAsAlias* staa =
- from->mutable_tos3()->add_tos_list()->mutable_qtn()->mutable_staa();
- CreateSchemaTable(staa->mutable_schema_table(), table);
- return;
- }
-
- // Write some nice joins.
- CreateSchemaTable(from->mutable_tos3()
- ->mutable_join_clause()
- ->mutable_tos()
- ->mutable_qtn()
- ->mutable_staa()
- ->mutable_schema_table(),
- table);
-
- // For each table in join_tables, write a JoinClauseCore that inner joins
- // with some comparisons between any two columns
- for (i::Table* curr_table : join_tables) {
- JoinClauseCore* jcc =
- from->mutable_tos3()->mutable_join_clause()->add_clauses();
-
- // Just generate inner joins, fuzzer should be smart enough to find other
- // join types.
- jcc->mutable_join_op()->set_join_type(JoinOperator::INNER);
-
- // Fill in the join clause core with the current table
- CreateSchemaTable(jcc->mutable_tos()
- ->mutable_qtn()
- ->mutable_staa()
- ->mutable_schema_table(),
- curr_table);
-
- jcc->mutable_join_constraint()->set_allocated_on_expr(
- GenerateJoinConstaints(table, join_tables));
- }
-
- // TODO(mpdenton) multiple Tables with aliases?
-}
-
-void GenerateGroupByStatement(GroupByStatement* gbs,
- i::Schema* schema,
- i::Table* table,
- bool join = false) {
- ExprSchemaTableColumn* stc = gbs->mutable_exprs()
- ->mutable_expr()
- ->mutable_comp_expr()
- ->mutable_expr_stc();
- // fine to just pick a single random column.
- CreateColumn(stc->mutable_col(), RandInt(0, table->num_columns - 1));
- if (join)
- CreateTableFromUint32(stc->mutable_table(), table->table_num);
-}
-
-std::set<uint32_t> GenerateSelectStatementCore(
- SelectStatementCore* ssc,
- i::Schema* schema,
- i::Table* table,
- std::vector<i::Table*> join_tables) {
- if (RandInt(1, 2) == 1) {
- ssc->set_s_or_d(SelectStatementCore::SELECT);
- } else {
- ssc->set_s_or_d(SelectStatementCore::SELECT_DISTINCT);
- }
-
- std::set<uint32_t> cols;
- if (join_tables.size() > 0) {
- // This is a join. Add columns from all the tables and include the table.
- for (size_t i = 0; i <= join_tables.size(); i++) {
- i::Table* table2;
- if (i == join_tables.size())
- table2 = table;
- else
- table2 = join_tables[i];
-
- cols = GetRandomNums(RandInt(1, table2->num_columns - 1),
- table2->num_columns - 1);
- for (uint32_t col : cols) {
- ExprSchemaTableColumn* stc = ssc->add_result_columns()
- ->mutable_eca()
- ->mutable_expr()
- ->mutable_comp_expr()
- ->mutable_expr_stc();
- CreateColumn(stc->mutable_col(), col);
- CreateTableFromUint32(stc->mutable_table(), table2->table_num);
- }
- }
- } else {
- if (RandInt(1, 2) == 1) {
- cols = GetRandomNums(RandInt(1, table->num_columns - 1),
- table->num_columns - 1);
- for (uint32_t col : cols) {
- CreateColumn(ssc->add_result_columns()->mutable_col(), col);
- }
- } else {
- AggregateFn* af = ssc->add_result_columns()
- ->mutable_eca()
- ->mutable_expr()
- ->mutable_comp_expr()
- ->mutable_fn_expr()
- ->mutable_aggregate_fn();
- af->set_fn_name(RANDOM_ENUM(AggregateFn, FnName));
- af->set_distinct((bool)RandInt(0, 1));
- CreateColumn(af->mutable_col1(), RandInt(0, table->num_columns - 1));
- }
- }
-
- bool join = join_tables.size() > 0;
-
- GenerateFromStatement(ssc->mutable_from(), schema, table, join_tables);
-
- if (RandInt(1, 3) >= 2) {
- GenerateWhereStatement(ssc->mutable_where(), schema, table, join);
- }
-
- if (RandInt(1, 3) == 1) {
- GenerateGroupByStatement(ssc->mutable_groupby(), schema, table, join);
- }
-
- return cols;
-}
-
-void GenerateOrderByStatement(OrderByStatement* obs,
- i::Schema* schema,
- i::Table* table,
- std::set<uint32_t> cols_tmp,
- bool join = false) {
- // TODO(mpdenton) exclude joins for now.
- if (!join && table->index_exprs.size() != 0 && RandInt(1, 5) >= 4) {
- // Use an indexed expression
- *obs->mutable_ord_term()->mutable_expr() =
- *table->index_exprs[RandInt(0, table->index_exprs.size() - 1)];
- return;
- }
-
- std::set<uint32_t> cols =
- GetRandomSubset(cols_tmp, RandInt(1, cols_tmp.size() - 1));
-
- std::vector<uint32_t> v;
- std::copy(cols.begin(), cols.end(), std::back_inserter(v));
- std::shuffle(v.begin(), v.end(), GetRandom());
-
- i::Table* table_in_col = join ? table : nullptr;
- auto it = v.begin();
- CreateColumnExpr(obs->mutable_ord_term()->mutable_expr(), *it, table_in_col);
- it++;
- for (size_t i = 0; i < v.size() - 1; i++) {
- CreateColumnExpr(obs->add_extra_ord_terms()->mutable_expr(), *it,
- table_in_col);
- it++;
- }
-}
-
-void GenerateSelect(Select* s,
- i::Schema* schema,
- i::Table* table,
- std::vector<i::Table*> join_tables = {}) {
- // Could be empty.
- std::set<uint32_t> cols = GenerateSelectStatementCore(
- s->mutable_select_core(), schema, table, join_tables);
- // TODO(mpdenton)
-
- if (RandInt(1, 2) == 1) {
- GenerateOrderByStatement(s->mutable_orderby(), schema, table,
- GetRandomNums(RandInt(1, table->num_columns - 1),
- table->num_columns - 1),
- join_tables.size() > 0);
- }
-
- // Limits are not very interesting from a corpus standpoint.
-}
-
-void InsertUpdateSelectOrDelete(SQLQuery* q,
- i::Schema* main_schema,
- int table_num) {
- int rand = RandInt(1, 4);
- if (rand == 1) {
- GenerateInsertion(q->mutable_insert(), main_schema,
- &main_schema->tables[table_num]);
- } else if (rand == 2) {
- GenerateDelete(q->mutable_delete_(), main_schema,
- &main_schema->tables[table_num]);
- } else if (rand == 3) {
- GenerateUpdate(q->mutable_update(), main_schema,
- &main_schema->tables[table_num]);
- } else if (rand == 4) {
- GenerateSelect(q->mutable_select(), main_schema,
- &main_schema->tables[table_num]);
- }
-}
-
-inline ExprSchemaTableColumn* GetSTC(Expr* expr) {
- return CreateDefaultCompExpr(expr->mutable_comp_expr())->mutable_expr_stc();
-}
-
-Expr* GenerateCreateIndex(CreateIndex* ci,
- i::Schema* schema,
- i::Table* table,
- std::set<uint32_t>& free_index_nums) {
- CHECK(free_index_nums.size() != 0);
-
- std::set<uint32_t> index_num_set = GetRandomSubset(free_index_nums, 1);
- uint32_t index_num = *index_num_set.begin();
- ci->mutable_index()->set_index(index_num);
- free_index_nums.erase(index_num);
- CreateTableFromUint32(ci->mutable_table(), table->table_num);
-
- if (RandInt(1, 3) >= 2) {
- Expr* expr = new Expr;
- int expr_type = RandInt(1, 2);
- if (expr_type == 1) {
- // Select two random columns of the table, add or subtract them.
- uint32_t col1 = RandInt(0, table->num_columns - 1);
- uint32_t col2 = RandInt(0, table->num_columns - 1);
-
- BinaryExpr* bin_expr = CreateDefaultCompExpr(expr->mutable_comp_expr())
- ->mutable_binary_expr();
- ExprSchemaTableColumn* lhs_stc = GetSTC(bin_expr->mutable_lhs());
- ExprSchemaTableColumn* rhs_stc = GetSTC(bin_expr->mutable_rhs());
-
- CreateColumn(lhs_stc->mutable_col(), col1);
- CreateColumn(rhs_stc->mutable_col(), col2);
-
- // TODO(mpdenton) perhaps set the tables here? The tables must not be set
- // for CREATE INDEX, but MUST be set for JOINs to avoid ambiguous columns.
- // Does it still count as the same expression if the table is included in
- // the JOIN but not the CREATE INDEX?
- if (RandInt(1, 2) == 1)
- bin_expr->set_op(BINOP_PLUS);
- else
- bin_expr->set_op(BINOP_MINUS);
- } else if (expr_type == 2) {
- // Or, apply abs to a single column.
- OneArgFn* oaf = CreateDefaultCompExpr(expr->mutable_comp_expr())
- ->mutable_fn_expr()
- ->mutable_simple_fn()
- ->mutable_one_arg_fn();
- oaf->set_fn_enum(OneArgFn::ABS);
- uint32_t col = RandInt(0, table->num_columns - 1);
- ExprSchemaTableColumn* stc = GetSTC(oaf->mutable_arg1());
- CreateColumn(stc->mutable_col(), col);
- // TODO(mpdenton) see above about setting tables.
- }
-
- ci->mutable_icol_list()->mutable_indexed_col()->set_allocated_expr(expr);
-
- // Make a copy that isn't owned by another protobuf
- Expr* ret_expr = new Expr;
- *ret_expr = *expr;
-
- return ret_expr;
- }
-
- IndexedColumnList* icol_list = ci->mutable_icol_list();
- std::set<uint32_t> cols =
- GetRandomNums(RandInt(1, table->num_columns - 1), table->num_columns - 1);
- bool first;
- for (uint32_t col : cols) {
- IndexedColumn* icol;
- if (first) {
- first = false;
- icol = icol_list->mutable_indexed_col();
- } else {
- icol = icol_list->add_extra_indexed_cols();
- }
- CreateColumn(icol->mutable_col(), col);
- }
-
- return NULL;
-}
-
-namespace {
-enum class GenQueryInstr {
- SUCCESS,
- MOVE_ON,
- TRY_AGAIN,
-};
-}
-
-template <typename T>
-void GenQueries(SQLQueries& queries,
- int min,
- int max,
- bool txn,
- int num_tables,
- T gen) {
- queries.mutable_extra_queries()->Reserve(queries.extra_queries_size() + max +
- 2);
- SQLQuery* q;
- if (txn) {
- q = new SQLQuery;
- q->mutable_begin_txn(); // constructs a begin txn.
- queries.mutable_extra_queries()->AddAllocated(q);
- }
- for (int i = 0; i < num_tables; i++) {
- for (int j = 0; j < RandInt(min, max); j++) {
- // continue; // TODO(mpdenton)
- q = new SQLQuery;
- GenQueryInstr success = gen(q, i);
- // Try again
- if (success != GenQueryInstr::SUCCESS) {
- if (success == GenQueryInstr::TRY_AGAIN)
- j--;
- delete q;
- continue;
- }
- queries.mutable_extra_queries()->AddAllocated(q);
- }
- }
- if (txn) {
- q = new SQLQuery;
- q->mutable_commit_txn(); // constructs a begin txn.
- queries.mutable_extra_queries()->AddAllocated(q);
- }
-}
-
-void FirstCreateTable(CreateTable* ct) {
- ct->mutable_schema_table()->mutable_schema_name()->set_schema(5);
- ct->mutable_schema_table()->mutable_schema_name()->set_main(false);
- ct->mutable_schema_table()->mutable_schema_name()->set_temp(false);
- ct->mutable_schema_table()->mutable_table_name()->set_table(0);
- ct->set_if_not_exists(false);
- ct->mutable_op();
-}
-
-SQLQueries GenCorpusEntry() {
- // The answer is no, I free nothing at any point.
-
- // Create the tables, and attached databases with tables
- // Schema schemas[i::kNumSchemas];
- // for (int i = 0; i < i::kNumSchemas; i++) {
- // // schemas[i] = Schema{
- // // .num_tables = RandInt(1, 5);
- // // };
- // }
- SQLQueries queries;
- FirstCreateTable(queries.mutable_create_table());
-
- // Just get rid of the first CreateTable, it will error out but not screw up
- // anything below
-
- i::Schema main_schema;
- main_schema.num_tables = RandInt(1, 5);
-
- std::set<uint32_t> free_index_nums;
- for (uint32_t i = 0; i < 10; i++) {
- free_index_nums.insert(i);
- }
-
- GenQueries(
- queries, 1, 1, false, main_schema.num_tables, [&](SQLQuery* q, int i) {
- i::Table t = i::Table{
- .table_num = i,
- .num_columns = RandInt(1, 8),
- };
- for (int j = 0; j < t.num_columns; j++) {
- t.col_types.push_back(RANDOM_ENUM(CastTypeName, CastTypeNameEnum));
- }
- main_schema.tables.push_back(std::move(t));
- GenerateCreateTable(q->mutable_create_table(), &main_schema,
- &main_schema.tables[i]);
- return GenQueryInstr::SUCCESS;
- });
-
- GenQueries(queries, kMinNumIndexes, kMaxNumIndexes, false,
- main_schema.num_tables, [&](SQLQuery* q, int i) {
- if (free_index_nums.size() == 0)
- return GenQueryInstr::MOVE_ON;
-
- Expr* index_expr =
- GenerateCreateIndex(q->mutable_create_index(), &main_schema,
- &main_schema.tables[i], free_index_nums);
- if (index_expr)
- main_schema.tables[i].index_exprs.emplace_back(index_expr);
- return GenQueryInstr::SUCCESS;
- });
-
- // Generate a bunch of inserts in a transaction (for speed)
- GenQueries(queries, kMinNumInsertions, kMaxNumInsertions, true,
- main_schema.num_tables, [&](SQLQuery* q, int i) {
- GenerateInsertion(q->mutable_insert(), &main_schema,
- &main_schema.tables[i]);
- return GenQueryInstr::SUCCESS;
- });
-
- // Generate a bunch of interesting selects with GroupBys, OrderBys, aggregate
- // functions, etc.
- GenQueries(queries, kMinNumSelects, kMaxNumSelects, false,
- main_schema.num_tables, [&](SQLQuery* q, int i) {
- GenerateSelect(q->mutable_select(), &main_schema,
- &main_schema.tables[i]);
- return GenQueryInstr::SUCCESS;
- });
-
- // Generate lots of interesting JOINs.
- if (main_schema.num_tables > 1) {
- GenQueries(queries, kMinNumJoins, kMaxNumJoins, false,
- main_schema.num_tables, [&](SQLQuery* q, int i) {
- std::set<uint32_t> tables =
- GetRandomNums(RandInt(1, main_schema.num_tables - 1),
- main_schema.num_tables - 1);
- tables.erase((uint32_t)i);
- if (tables.size() == 0) {
- // try again
- return GenQueryInstr::TRY_AGAIN;
- }
- std::vector<i::Table*> tables_p;
- for (uint32_t t : tables) {
- tables_p.push_back(&main_schema.tables[t]);
- }
- GenerateSelect(q->mutable_select(), &main_schema,
- &main_schema.tables[i], tables_p);
- return GenQueryInstr::SUCCESS;
- });
- }
-
- // Generate a bunch of interesting updates.
- GenQueries(queries, kMinNumUpdates, kMaxNumUpdates, true,
- main_schema.num_tables, [&](SQLQuery* q, int i) {
- GenerateUpdate(q->mutable_update(), &main_schema,
- &main_schema.tables[i]);
- return GenQueryInstr::SUCCESS;
- });
-
- // Generate interesting deletes.
- GenQueries(queries, kMinNumDeletes, kMaxNumDeletes, true,
- main_schema.num_tables, [&](SQLQuery* q, int i) {
- GenerateDelete(q->mutable_delete_(), &main_schema,
- &main_schema.tables[i]);
- return GenQueryInstr::SUCCESS;
- });
-
- // Do everything except joins.
- GenQueries(queries, kMinNumOthers, kMaxNumOthers, true,
- main_schema.num_tables, [&](SQLQuery* q, int i) {
- InsertUpdateSelectOrDelete(q, &main_schema, i);
- return GenQueryInstr::SUCCESS;
- });
-
- return queries;
-}
-
-int main(int argc, char** argv) {
- base::CommandLine cl(argc, argv);
-
- int num_entries;
- if (!cl.HasSwitch("num_entries"))
- LOG(FATAL) << "num_entries not specified.";
- if (!base::StringToInt(cl.GetSwitchValueASCII("num_entries"), &num_entries))
- LOG(FATAL) << "num_entries not parseable as an int.";
-
- bool to_stdout = true;
- base::FilePath dir_path;
- if (cl.HasSwitch("corpus_dir")) {
- to_stdout = false;
-
- dir_path = cl.GetSwitchValuePath("corpus_dir");
- base::File dir(dir_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
- if (!dir.IsValid())
- LOG(FATAL) << "corpus_dir " << dir_path << " could not be opened.";
-
- base::File::Info dir_info;
- if (!dir.GetInfo(&dir_info))
- LOG(FATAL) << "Could not get corpus_dir " << dir_path << " file info.";
- if (!dir_info.is_directory)
- LOG(FATAL) << "corpus_dir " << dir_path << " is not a directory.";
- } else {
- LOG(INFO) << "corpus_dir not specified, writing serialized output to "
- "stdout instead.";
- }
-
- int last_index = 0;
- for (int total = 0; total < num_entries; total++) {
- SQLQueries queries = GenCorpusEntry();
- std::vector<std::string> queries_str;
- for (int i = 0; i < queries.extra_queries_size(); i++) {
- queries_str.push_back(
- sql_fuzzer::SQLQueryToString(queries.extra_queries(i)));
- if (to_stdout || ::getenv("LPM_DUMP_NATIVE_INPUT"))
- std::cout << queries_str[i] << std::endl;
- }
-
- if (getenv("PRINT_SQLITE_ERRORS"))
- sql_fuzzer::RunSqlQueries(queries_str, ::getenv("LPM_SQLITE_TRACE"));
-
- // If we just want to print to stdout, skip the directory stuff below.
- if (to_stdout)
- continue;
-
- // It's okay to serialize without all required fields, as LPM uses
- // ParsePartial* as well.
- std::string proto_text;
- if (!queries.SerializePartialToString(&proto_text))
- LOG(FATAL) << "Could not serialize queries to string.";
-
- bool found_file = false;
- while (!found_file) {
- base::FilePath file_path =
- dir_path.Append("corpus_queries" + std::to_string(last_index));
- base::File file(file_path,
- base::File::FLAG_CREATE | base::File::FLAG_WRITE);
- if (file.created()) {
- found_file = true;
- if (file.Write(0, proto_text.data(), proto_text.length()) < 0) {
- LOG(FATAL) << "Failed to write to file " << file_path;
- }
- }
- last_index++;
- }
- }
-
- return 0;
-}
diff --git a/chromium/third_party/sqlite/fuzz/sql_multithreaded_fuzzer.cc b/chromium/third_party/sqlite/fuzz/sql_multithreaded_fuzzer.cc
deleted file mode 100644
index 000e4afa42f..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_multithreaded_fuzzer.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Unused because SQLite is so serialized and concurrency-unfriendly that this
-// really wouldn't test anything.
-
-#include <condition_variable>
-#include <cstdlib>
-#include <iostream>
-#include <mutex>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include "testing/libfuzzer/proto/lpm_interface.h"
-#include "third_party/sqlite/fuzz/disabled_queries_parser.h"
-#include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
-#include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
-#include "third_party/sqlite/fuzz/sql_run_queries.h"
-#include "third_party/sqlite/sqlite3.h"
-
-using namespace sql_query_grammar;
-
-namespace {
-constexpr int kNumThreads = 4; // Must change with MultipleSQLQueries protobuf.
-}
-
-DEFINE_BINARY_PROTO_FUZZER(const MultipleSQLQueries& multiple_sql_queries) {
- char* skip_queries = ::getenv("SQL_SKIP_QUERIES");
- if (skip_queries) {
- sql_fuzzer::SetDisabledQueries(
- sql_fuzzer::ParseDisabledQueries(skip_queries));
- }
-
- assert(multiple_sql_queries.GetDescriptor()->field_count() == kNumThreads);
-
- sqlite3* db = sql_fuzzer::InitConnectionForFuzzing();
- if (!db)
- return;
-
- if (::getenv("LPM_SQLITE_TRACE")) {
- sql_fuzzer::EnableSqliteTracing(db);
- }
-
- std::vector<std::string> query_strs[kNumThreads];
- query_strs[0] = sql_fuzzer::SQLQueriesToVec(multiple_sql_queries.queries1());
- query_strs[1] = sql_fuzzer::SQLQueriesToVec(multiple_sql_queries.queries2());
- query_strs[2] = sql_fuzzer::SQLQueriesToVec(multiple_sql_queries.queries3());
- query_strs[3] = sql_fuzzer::SQLQueriesToVec(multiple_sql_queries.queries4());
-
- if (::getenv("LPM_DUMP_NATIVE_INPUT")) {
- std::cout << "_________________________" << std::endl;
- for (int i = 0; i < kNumThreads; i++) {
- std::cout << "Thread " << i << ":" << std::endl;
- for (std::string query : query_strs[i]) {
- if (query == ";")
- continue;
- std::cout << query << std::endl;
- }
- }
- std::cout << "------------------------" << std::endl;
- }
-
- int num_threads_started = 0;
- std::mutex m;
- std::condition_variable cv;
-
- std::vector<std::thread> threads;
-
- auto to_run = [&](std::vector<std::string> queries) {
- // Wait for all the threads to start.
- std::unique_lock<std::mutex> lk(m);
- num_threads_started++;
- cv.notify_all();
- cv.wait(lk, [&] { return num_threads_started == kNumThreads; });
- m.unlock();
-
- sql_fuzzer::RunSqlQueriesOnConnection(db, queries);
- };
-
- for (int i = 0; i < kNumThreads; i++) {
- threads.emplace_back(to_run, query_strs[i]);
- }
-
- for (int i = 0; i < kNumThreads; i++) {
- threads[i].join();
- }
-
- sql_fuzzer::CloseConnection(db);
-}
diff --git a/chromium/third_party/sqlite/fuzz/sql_printf_fuzzer.cc b/chromium/third_party/sqlite/fuzz/sql_printf_fuzzer.cc
deleted file mode 100644
index eb0dafb5c06..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_printf_fuzzer.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "testing/libfuzzer/proto/lpm_interface.h"
-#include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
-#include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
-#include "third_party/sqlite/fuzz/sql_run_queries.h"
-
-using namespace sql_query_grammar;
-
-DEFINE_BINARY_PROTO_FUZZER(const Printf& sql_printf) {
- std::string printf_str = sql_fuzzer::PrintfToString(sql_printf);
- // Convert printf command into runnable SQL query.
- printf_str = "SELECT " + printf_str + ";";
-
- if (::getenv("LPM_DUMP_NATIVE_INPUT")) {
- std::cout << "_________________________" << std::endl;
- std::cout << printf_str << std::endl;
- std::cout << "------------------------" << std::endl;
- }
-
- std::vector<std::string> queries;
- queries.push_back(printf_str);
- sql_fuzzer::RunSqlQueries(queries, ::getenv("LPM_SQLITE_TRACE"));
-}
diff --git a/chromium/third_party/sqlite/fuzz/sql_queries.proto b/chromium/third_party/sqlite/fuzz/sql_queries.proto
deleted file mode 100644
index d12ebe7b981..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_queries.proto
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto2";
-
-import "sql_query_grammar.proto";
-
-package sql_query_grammar;
-
-message MultipleSQLQueries {
- required SQLQueries queries1 = 1;
- required SQLQueries queries2 = 2;
- required SQLQueries queries3 = 3;
- required SQLQueries queries4 = 4;
-}
-
-message SQLQueries {
- // Always have a CreateTable first because otherwise the queries are
- // pointless.
- required CreateTable create_table = 1;
- repeated SQLQuery extra_queries = 2;
-}
diff --git a/chromium/third_party/sqlite/fuzz/sql_query_grammar.proto b/chromium/third_party/sqlite/fuzz/sql_query_grammar.proto
deleted file mode 100644
index ceb67799cd7..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_query_grammar.proto
+++ /dev/null
@@ -1,1663 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto2";
-
-import "icu_codes.proto";
-
-package sql_query_grammar;
-
-/* Generates SQL queries in protobuf format, using enums for the tables and
- integers for column names. The column name integers will be wrapped.
- Relies heavily on the sqlite grammar from here:
- https://www.sqlite.org/lang.html
-
- Yes, it is all in one big blobby proto file, as everything is extremely
- mutually recursive and there is no such thing as circular imports or forward
- declarations in protobuf.
-*/
-
-message SQLQuery {
- // No comments generated, nor EXPLAIN queries
- oneof query_oneof {
- Select select = 1;
- CreateTable create_table = 2;
- Insert insert = 3;
- Delete delete = 4;
- CreateFTS3Table fts3_table = 5;
- FTS3SpecificQuery fts_query = 6;
- BeginTransaction begin_txn = 7;
- CommitTransaction commit_txn = 8;
- RollbackStatement rollback_stmt = 9;
- CreateSavePoint create_save_point = 10;
- ReleaseSavePoint release_save_point = 11;
- Analyze analyze = 12;
- Vacuum vacuum = 13;
- Pragma pragma = 14;
- Update update = 15;
- CreateIndex create_index = 16;
- CreateView create_view = 17;
- CreateTrigger create_trigger = 18;
- ReIndex reindex = 19;
- Drop drop = 20;
- AlterTable alter_table = 21;
- AttachDatabase attach_db = 22;
- DetachDatabase detach_db = 23;
- FTS3HiddenTableInsert fts3_insert = 24;
- FTS3HiddenTableUpdate fts3_update = 25;
- FTS3HiddenTableDelete fts3_delete = 26;
- }
-}
-
-// ~~~~FTS3~~~
-
-message FTS3SpecificQuery {
- oneof query_oneof {
- FTS3SpecialCommand command = 1;
- // The following exists to increase the probability of hitting MATCH
- // queries.
- FTS3SelectMatch select = 2;
- }
-}
-
-message FTS3SelectMatch {
- // SELECT * FROM |table| WHERE |col| MATCH |match_pattern|
- required FTS3Table table = 1;
- required Column col = 2;
- required FTS3MatchFormat match_pattern = 3;
-}
-
-message FTS3SpecialCommand {
- // INSERT INTO xyz(xyz) VALUES('optimize');
- // is a special command that optimizes FTS table xyz.
- required FTS3Table table = 1;
- enum Command {
- OPTIMIZE = 0;
- REBUILD = 1;
- INTEGRITY_CHECK = 2;
- MERGE = 3;
- AUTOMERGE = 4;
- }
- required Command command = 2;
- required uint32 val1 = 3;
- required uint32 val2 = 4;
-}
-
-message ICULocale {
- required IsoLangCode iso_lang_code = 1;
- // least significant 2 bytes will each be clamped to within 'A' and
- // 'Z' and then concatenated together to form a country code.
- required uint32 country_code = 2;
- // TODO(mpdenton) generate anything else here? Will sqlite care?
-}
-
-enum TokenizerType {
- TT_SIMPLE = 0;
- TT_PORTER = 1;
- TT_ICU = 2;
- TT_UNICODE61 = 3; // FIXME in the future: remove_diacritics, separators,
- // token_chars.... (not supported in Chrome)
-}
-
-// FIXME in the future: maybe also fuzz the tokenizer type/icu locales with
-// random strings???
-message CreateFTS3Table {
- required bool if_not_exists = 1;
- optional Schema schema = 6;
- required FTS3Table table = 2;
- optional ColumnList col_list = 3;
- optional TokenizerType tokenizer_type = 4;
- required ICULocale locale = 5; // used if tokenizer_type == TT_ICU.
-}
-
-message FTS3Table {
- required uint32 table = 1;
-}
-
-// TODO(mpdenton) query by row id?
-
-message FTS3MatchFormat {
- repeated FTS3MatchCompoundFormat ft = 1;
-}
-
-message FTS3MatchCompoundFormat {
- required FTS3MatchFormatCore core = 1;
- repeated FTS3CompoundAndCore compound_and_cores = 2;
-}
-
-message FTS3CompoundAndCore {
- enum CompoundOp {
- OR = 0;
- // Chrome does not enable the enhanced query syntax. FIXME in the future.
- // AND = 1;
- // NOT = 2;
- }
- required CompoundOp op = 1;
- required FTS3MatchFormatCore core = 2;
-}
-
-message FTS3MatchFormatCore {
- oneof ft_oneof {
- FTS3PhraseQuery pq = 1;
- FTS3NearQuery nq = 2;
- }
- required FTS3MatchToken mt_fallback = 3;
-}
-
-message FTS3NearQuery {
- // May generate into another NEAR query, this is fine.
- required FTS3MatchFormatCore format_core1 = 1;
- optional uint32 num_tokens_near = 2;
- required FTS3MatchFormatCore format_core2 = 3;
-}
-
-message FTS3PhraseQuery {
- required FTS3MatchToken mt = 1;
- repeated FTS3MatchToken extra_mts = 2;
-}
-
-message FTS3MatchToken {
- optional Column col = 1; // search in this column specifically
- required bool negate = 4;
- required string token = 2; // token (or prefix) to search for
- required bool prefix = 3; // append star to end
-}
-
-// FIXME in the future: https://www.sqlite.org/fts3.html Section 8.2: Query
-// tokenizers themselves. Unsupported by Chrome.
-
-message FTS3OffsetsFn {
- required FTS3Table table = 1;
-}
-
-message FTS3SnippetsFn {
- required FTS3Table table = 1;
- enum NumArgs {
- A0 = 0;
- A1 = 1;
- A2 = 2;
- A3 = 3;
- A4 = 4;
- A5 = 5;
- }
- required NumArgs num_optional_args = 2;
- required string start_match = 3;
- required string end_match = 4;
- required string ellipses = 5;
- optional uint32 col_number = 6; // capped by KMaxColumnNumber
- required uint32 num_tokens = 7; // in [-64, 64].
-}
-
-message FTS3MatchInfoFn {
- required FTS3Table table = 1;
-
- // The following will be wrapped to any of the characters p,c,n,a,,l,s,x,y,b.
- repeated uint32 chars = 2;
-}
-
-// FTS3 Auxiliary function format
-message FTS3AuxiliaryFn {
- required FTS3OffsetsFn offsets_fallback = 1;
- oneof fts_aux_fn_oneof {
- FTS3SnippetsFn snippets = 2;
- FTS3MatchInfoFn matchinfo = 3;
- }
-}
-
-// Types of hidden tables in FTS3
-message FTS3HiddenTable {
- enum HiddenTableVal {
- // CONTENT = 0; // Taken care of in |Table|
- SEGDIR = 1;
- SEGMENTS = 2;
- // stat and docsize are FTS4
- }
- required HiddenTableVal htv = 1;
- required FTS3Table table = 2;
-}
-
-// The different columns that go into the FTS3 hidden tables above
-enum FTS3HiddenTableColumn {
- FTS3_HT_BLOCKID = 0;
- FTS3_HT_BLOCK = 1;
- FTS3_HT_LEVEL = 2;
- FTS3_HT_IDX = 3;
- FTS3_HT_START_BLOCK = 4;
- FTS3_HT_LEAVES_END_BLOCK = 5;
- FTS3_HT_END_BLOCK = 6;
- FTS3_HT_ROOT = 7;
-}
-
-// Some extra stuff to modify the FTS3 Hidden tables, only used for FTS3
-// Fuzzing.
-
-// Used to insert single values in.
-message FTS3HiddenTableInsert {
- required FTS3HiddenTable fht = 1;
- repeated FTS3HiddenTableColumnValue col_vals = 2;
-}
-
-message FTS3HiddenTableUpdate {
- required FTS3HiddenTable fht = 1;
- repeated FTS3HiddenTableColumnValue col_vals = 2;
-
- // mini WHERE clause with some BinOp
- optional FTS3HiddenTableColumn col_where = 3;
- required BinaryOperator bin_op = 4;
- required Expr comp_expr = 5;
-}
-
-message FTS3HiddenTableDelete {
- required FTS3HiddenTable fht = 1;
- optional FTS3HiddenTableColumn col_where = 2;
- required BinaryOperator bin_op = 3;
- required Expr comp_expr = 4;
-}
-
-message FTS3HiddenTableColumnValue {
- required FTS3HiddenTableColumn col = 1;
- required Expr expr = 2;
-}
-
-// ~~~~TRANSACTIONs~~~~
-// TODO(mpdenton) these could be meta-statements that enclose a bunch of other
-// statements. Is that worthwhile or should I just let the fuzzer generate them
-// haphazardly?
-message BeginTransaction {
- enum TransactionType {
- DEFERRED = 0;
- IMMEDIATE = 1;
- EXCLUSIVE = 2;
- }
- optional TransactionType type = 1;
-}
-
-message CommitTransaction {
- enum CommitText {
- COMMIT = 0;
- END = 1;
- COMMIT_TRANSACTION = 2;
- END_TRANSACTION = 3;
- }
- required CommitText text = 1;
-}
-
-message SavePoint {
- required uint32 savepoint_num = 1;
-}
-
-message RollbackStatement {
- optional SavePoint save_point = 1;
-}
-
-message CreateSavePoint {
- required SavePoint save_point = 1;
-}
-
-message ReleaseSavePoint {
- required SavePoint save_point = 1;
-}
-
-// ~~~~ANALYZE~~~~
-message Analyze {
- optional Schema schema_name = 1;
- optional Table table_name = 2;
- optional Index index_name = 3;
-}
-
-// ~~~~VACUUM~~~~
-message Vacuum {
- optional Schema schema = 1;
-}
-
-// ~~~~PRAGMA~~~~
-message Pragma {
- // FIXME in the future: full list here: https://www.sqlite.org/pragma.html
- // These are the ones I've seen in Chrome
- enum PragmaCommand {
- // QUICK_CHECK = 0;
- // INTEGRITY_CHECK = 1;
- AUTO_VACUUM = 2;
- WRITEABLE_SCHEMA = 3;
- LOCKING_MODE = 4;
- TEMP_STORE = 5;
- PAGE_SIZE_ = 6;
- TABLE_INFO = 7;
- JOURNAL_MODE = 8;
- MMAP_SIZE = 9;
- }
- required PragmaCommand command = 1;
- optional Schema schema = 2;
- required int32 arg1 = 3;
-}
-
-// ~~~~CREATE_TABLE~~~~
-enum TempModifier {
- TM_TEMP = 3;
- TM_TEMPORARY = 4;
-}
-
-message CreateTable {
- optional TempModifier temp_modifier = 1;
- required bool if_not_exists = 2;
- required ExprSchemaTable schema_table = 3;
- oneof create_table_oneof {
- CreateTableOpt1 op1 = 4;
- Select as_select_stmt = 5; // AS select-stmt
- }
- required CreateTableOpt1 op = 6; // used only if the above oneof is empty
-}
-
-message CreateTableOpt1 {
- required ColumnDef col_def = 1;
- repeated ColumnDef extra_col_defs = 2;
- repeated TableConstraint table_constraints = 3;
- required bool without_rowid = 4;
-}
-
-message ColumnDef {
- required Column col = 1;
- optional TypeName type_name = 2;
- repeated ColumnConstraint col_constraints = 3;
-}
-
-message TypeName {
- // Things like VARCHAR(100) are simply not enforced by SQLite (this example
- // would end up with a column affinity of TEXT). So I don't make much effort
- // to generate them.
- required CastTypeName ctn = 1;
- optional uint32 sn = 2;
-}
-
-message ColumnConstraint {
- optional ColumnConstraintName constraint_name = 1;
- oneof col_constraint_oneof {
- ColConstraintOpt1 opt1 = 2;
- ConflictClause not_null_conf_clause = 3;
- ConflictClause unique_conf_clause = 4;
- Expr check_expr = 5; // CORPUS specialize??
- ColConstraintOpt2 opt2 = 6;
- CollateType collate = 7;
- ForeignKeyClause fkey_clause = 8;
- }
- required ColConstraintOpt2 opt2_fallback = 9;
-}
-
-message ColConstraintOpt1 {
- required AscDesc asc_desc = 1;
- required ConflictClause conflict = 2;
- required bool autoincrement = 3;
-}
-
-message ColConstraintOpt2 {
- required LiteralValue lit_val = 1;
- optional Expr expr = 2; // CORPUS specialize?
-}
-
-message ConflictClause {
- enum OnConflict {
- ROLLBACK = 0;
- ABORT = 1;
- FAIL = 2;
- IGNORE = 3;
- REPLACE = 4;
- }
- optional OnConflict on_conflict = 1;
-}
-
-message TableConstraint {
- optional TableConstraintName name = 1;
- oneof table_constraint_oneof {
- TableConstraintOpt1 opt1 = 2;
- Expr check_expr = 3; // CORPUS specialize?
- TableConstraintOpt2 opt2 = 4;
- }
-}
-
-message TableConstraintOpt1 {
- enum ConstraintType {
- PRIMARY_KEY = 0;
- UNIQUE = 1;
- }
- required ConstraintType constraint_type = 1;
- required IndexedColumnList indexed_col_list = 2;
- required ConflictClause conf_clause = 3;
-}
-
-message TableConstraintOpt2 {
- required ColumnList cols = 1;
- required ForeignKeyClause fkey_clause = 2;
-}
-
-message IndexedColumn {
- optional Expr expr = 1; // CORPUS specialize?
- required Column col = 2; // only used if expr non-existent
- optional CollateType collate_type = 3;
- required AscDesc asc_desc = 4;
-}
-
-message IndexedColumnList {
- required IndexedColumn indexed_col = 1;
- repeated IndexedColumn extra_indexed_cols = 2;
-}
-
-message ForeignKeyClause {
- required Table foreign_table = 1;
- optional ColumnList col_list = 2;
- repeated ForeignKeyClauseCore fkey_cores = 3;
- optional DeferStrategy defer_strat = 4;
-}
-
-message ForeignKeyClauseCore {
- optional ForeignKeyClauseNotMatch fkey_not_match = 1;
- // Sqlite doesn't obey MATCH expressions, MATCH SIMPLE is always assumed
-}
-
-message ForeignKeyClauseNotMatch {
- enum DeleteOrUpdate {
- DELETE = 0;
- UPDATE = 1;
- }
- required DeleteOrUpdate del_or_update = 1;
-
- enum Action {
- SET_NULL = 0;
- SET_DEFAULT = 1;
- CASCADE = 2;
- RESTRICT = 3;
- NO_ACTION = 4;
- }
- required Action action = 2;
-}
-
-message DeferStrategy {
- required bool not = 1;
- enum DeferStratEnum {
- INITIALLY_DEFERRED = 0;
- INITIALLY_IMMEDIATE = 1;
- NONE = 2;
- }
- required DeferStratEnum strat = 2;
-}
-
-// ~~~~DELETE~~~~
-// FIXME in the future: SQL_ENABLE_UPDATE_DELETE_LIMIT
-message Delete {
- optional WithStatement with = 1;
- required QualifiedTableName qtn = 2;
- optional WhereStatement where = 3;
-}
-
-message QualifiedTableName {
- required SchemaTableAsAlias staa = 1;
- required bool indexed = 2;
- required bool not_indexed = 3;
- required Index indexed_by = 4;
-}
-
-// ~~~~INSERT~~~~
-
-message UpsertClausePart1 {
- required IndexedColumnList icol_list = 1;
- optional WhereStatement where_stmt = 2;
-}
-
-message ColEqualsExpr {
- oneof uclause_p2_oneof {
- Column col = 1;
- ColumnList col_list = 2;
- }
- required Expr expr = 3;
-}
-
-message UpsertClausePart2 {
- required ColEqualsExpr cee = 1;
- repeated ColEqualsExpr extra_cees = 2;
- optional WhereStatement where_stmt = 3;
-}
-
-message UpsertClause {
- optional UpsertClausePart1 uclause_p1 = 1;
- optional UpsertClausePart2 uclause_p2 = 2;
-}
-
-message SchemaTableAsAlias {
- required ExprSchemaTable schema_table = 1;
- optional Table as_table_alias = 2;
-}
-
-message Insert {
- optional WithStatement with = 1;
- enum InsertType {
- INSERT = 0;
- REPLACE = 1;
- INSERT_OR_REPLACE = 2;
- INSERT_OR_ROLLBACK = 3;
- INSERT_OR_ABORT = 4;
- INSERT_OR_FAIL = 5;
- INSERT_OR_IGNORE = 6;
- }
- required InsertType insert_type = 2;
- required SchemaTableAsAlias staa = 3;
- optional ColumnList col_list = 5;
- oneof insert_oneof {
- ValuesStatement values = 6;
- Select select = 7;
- } // if empty, DEFAULT VALUES
- optional UpsertClause upsert_clause = 8;
-}
-
-// ~~~~UPDATE~~~~
-message Update {
- optional WithStatement with = 1;
- enum UpdateType {
- OR_ROLLBACK = 0;
- OR_ABORT = 1;
- OR_REPLACE = 2;
- OR_FAIL = 3;
- OR_IGNORE = 4;
- }
- optional UpdateType update_type = 2;
- required QualifiedTableName qtn = 3;
- required UpsertClausePart2 ucp2 = 4;
-}
-
-// ~~~~CREATE INDEX~~~~
-message CreateIndex {
- required bool unique = 1;
- required bool if_not_exists = 2;
- optional Schema schema = 3;
- required Index index = 4;
- required Table table = 5;
- required IndexedColumnList icol_list = 6;
- optional WhereStatement where = 7;
-}
-
-// ~~~~CREATE VIEW~~~~
-message View {
- required uint32 view = 1;
-}
-message CreateView {
- optional TempModifier temp_modifier = 1;
- required bool if_not_exists = 2;
- optional Schema schema = 3;
- required View view = 4;
- optional ColumnList col_list = 5;
- required Select select = 6;
-}
-
-// ~~~~CREATE TRIGGER~~~~
-message Trigger {
- required uint32 trigger = 1;
-}
-
-message CreateTrigger {
- optional TempModifier temp_modifier = 1;
- required bool if_not_exists = 2;
- optional Schema schema = 3;
- required Trigger trigger = 4;
- enum TriggerType {
- BEFORE = 0;
- AFTER = 1;
- INSTEAD_OF = 2;
- }
- optional TriggerType trigger_type = 5;
- enum TriggerInstr {
- DELETE = 0;
- UPDATE = 1;
- INSERT = 2;
- }
- optional TriggerInstr trigger_instr = 6;
- required ColumnList col_list = 7; // CORPUS create corpus item with an Update
- // using the same ColumnList as this
- required Table table = 8;
- required bool for_each_row = 9;
- optional ExprComparisonHighProbability when = 10; // for the WHEN statement
- // There are significant restrictions on update, insert, select, and delete
- // expressions used in triggers. However, we might as well generate normal
- // queries and see if these restrictions are adequately enforced.
-
- // Also, from https://www.sqlite.org/lang_createtrigger.html: "If a BEFORE
- // UPDATE or BEFORE DELETE trigger modifies or deletes a row that was to have
- // been updated or deleted, then the result of the subsequent update or delete
- // operation is undefined. Furthermore, if a BEFORE trigger modifies or
- // deletes a row, then it is undefined whether or not AFTER triggers that
- // would have otherwise run on those rows will in fact run."
-
- // It is unclear what is meant by "undefined". Are we talking memory
- // corruption? I suppose the fuzzer will find it and we'll see.
- required TypicalQuery tq = 11;
- repeated TypicalQuery extra_tqs = 12;
-}
-
-message TypicalQuery {
- oneof tq_oneof {
- Update update = 1;
- Insert insert = 2;
- Select select = 3;
- }
- required Delete delete_fallback = 4;
-}
-
-// ~~~~REINDEX~~~~
-message ReIndex {
- required bool empty = 5;
- optional CollateType collate_type = 4; // used if schema does not exist
- optional Schema schema = 1;
- optional Table table = 2;
- required Index index = 3; // used if table does not exist.
-}
-
-// ~~~~DROP *~~~~
-message Drop {
- required bool if_exists = 5;
- optional Schema schema = 6;
- oneof drop_oneof {
- Index index = 1;
- Table table = 2;
- Trigger trigger = 3;
- }
- required View view_fallback = 4;
-}
-
-// ~~~~ALTER TABLE~~~~
-message AlterTable {
- required ExprSchemaTable schema_table = 1;
- required bool column = 2;
- optional Column col = 4;
- required Column col_to = 5;
- optional ColumnDef col_def = 6;
- required Table table_fallback = 3;
-}
-
-// ~~~~ATTACH DATABASE~~~~
-
-// SEE: https://www.sqlite.org/inmemorydb.html
-// Lots of different options.
-// TODO(mpdenton) may want to experiment with on-filesystem main dbs as well...
-message AttachDatabase {
- required bool in_memory = 1;
- required bool file_uri = 2;
- optional Schema db_name = 3;
- required bool shared_cache = 4;
- required Schema schema = 5;
-}
-
-// ~~~~DETACH DATABASE~~~~
-message DetachDatabase {
- required Schema schema = 1;
-}
-
-// ~~~~SELECT~~~~
-/*
- Select is obviously the most complicated syntax in the language, and the
- fuzzer will likely generate plenty of invalid SELECT statements. As long as
- it does not generate too many, we should still be perfectly fine.
-
- From sqlite docs:
- Note that there are paths through the syntax diagrams that are not allowed in
- practice. Some examples:
-
- A VALUES clause can be the first element in a compound SELECT that uses a WITH
- clause, but a simple SELECT that consists of just a VALUES clause cannot be
- preceded by a WITH clause. The WITH clause must occur on the first SELECT of a
- compound SELECT. It cannot follow a compound-operator.
-
-
- See https://www.sqlite.org/lang_select.html.
-*/
-message Select {
- optional WithStatement with = 1;
-
- // SQL grammar specifies SelectSubStatement here but that just leads
- // to a bunch of unparseable VALUES ... ; statements. So require
- // SelectCore here.
- required SelectStatementCore select_core = 2;
- repeated ExtraSelectSubStatement extra_select_substatements = 3;
- optional OrderByStatement orderby = 4;
- optional LimitStatement limit = 5;
-}
-
-message OrderByStatement {
- required ExprOrderingTerm ord_term = 1;
- repeated ExprOrderingTerm extra_ord_terms = 2;
-}
-
-message LimitStatement {
- // CORPUS specialize these exprs???
- required Expr limit_expr = 1;
- required bool offset = 2; // this is only used if second_expr exists
- optional Expr second_expr = 3;
-}
-
-message ExtraSelectSubStatement {
- required CompoundOperator compound_op = 1;
- required SelectSubStatement select_substatement = 2;
-}
-
-enum CompoundOperator {
- CO_UNION = 0;
- CO_UNION_ALL = 1;
- CO_INTERSECT = 2;
- CO_EXCEPT = 3;
-}
-
-message SelectSubStatement {
- oneof select_subexpr_oneof {
- SelectStatementCore select_core = 1;
- ValuesStatement values = 2;
- }
- required ValuesStatement values_fallback = 3;
-}
-
-message ValuesStatement {
- required ExprList expr_list = 1;
- repeated ExprList extra_expr_lists = 2; // CORPUS specialize?
-}
-
-message ExprColAlias {
- required Expr expr = 1;
- optional Column col_alias = 2;
- required bool as = 3;
-}
-
-message ResultColumn {
- oneof result_col_oneof {
- Column col = 1;
- ExprColAlias eca = 2;
- Table table_star = 3;
- FTS3AuxiliaryFn fts3_fn = 4; // Only emitted when FUZZ_FTS3 enabled
- } // if nothing, use star *
-}
-
-message SelectStatementCore {
- enum SelectOrDistinct {
- SELECT_DISTINCT = 0;
- SELECT = 1;
- SELECT_ALL = 2;
- }
- required SelectOrDistinct s_or_d = 1;
- repeated ResultColumn result_columns = 2;
- optional FromStatement from = 3;
- optional WhereStatement where = 4;
- optional GroupByStatement groupby = 5;
- optional WindowStatement window = 6;
-}
-
-message WithStatement {
- required bool recursive = 1;
- required CommonTableExpr table_expr = 2;
- repeated CommonTableExpr extra_table_exprs = 3;
-}
-
-message FromStatement {
- required TableOrSubqueryOption3 tos3 = 1;
-}
-
-message WindowStatement {
- required WindowStatementNaming win = 1;
- repeated WindowStatementNaming extra_wins = 2;
-}
-
-message WindowStatementNaming {
- required WindowName name = 1;
- required WindowDefn defn = 2;
-}
-
-message GroupByStatement {
- // CORPUS specialize all these exprs????
- required ExprList exprs = 1;
- optional Expr having_expr = 3;
-}
-
-message WhereStatement {
- required ExprComparisonHighProbability expr = 1;
-}
-
-message CommonTableExpr {
- required Table table = 1;
- repeated Column columns = 2;
- required Select select = 3;
-}
-
-// ~~~~Join stuff~~~~~
-message JoinClause {
- required TableOrSubquery tos = 1;
- repeated JoinClauseCore clauses = 2;
-}
-
-message JoinClauseCore {
- required JoinOperator join_op = 1;
- required TableOrSubquery tos = 2;
- required JoinConstraint join_constraint = 3;
-}
-
-message JoinOperator {
- required bool comma = 1;
- // the following fields only used if comma is false
- required bool natural = 2;
- enum JoinType {
- LEFT = 0;
- LEFT_OUTER = 1;
- INNER = 2;
- CROSS = 3;
- NONE = 4;
- }
- required JoinType join_type = 3;
-}
-
-message JoinConstraint {
- oneof join_constraint_oneof {
- Expr on_expr = 1;
- UsingExpr using_expr = 2;
- } // fine if empty
-}
-
-message UsingExpr {
- required ColumnList col_list = 1;
-}
-
-// ~~~~~Table names etc.~~~~~
-
-// First checks if main is set. Then checks if temp is set. Then checks if
-// other schema number is set.
-message Schema {
- required uint32 schema = 1;
- required bool main = 2;
- required bool temp = 3;
-}
-
-message Table {
- required uint32 table = 1;
- optional bool fts3_content_table = 2; // only used for FTS3 fuzzing
-}
-
-message Column {
- required uint32 column = 1;
- optional bool rowid = 2; // can also have "rowid" column
-
- // FTS has a hidden column with the same name as the table.
- optional FTS3Table fts3_table = 3;
- // FTS3 tables have "docid" as an alias for "rowid".
- optional bool fts3_docid = 4;
-}
-
-message WindowName {
- required uint32 window_name = 1;
-}
-
-message ColumnConstraintName {
- required uint32 constraint_name = 1;
-}
-
-message TableConstraintName {
- required uint32 constraint_name = 1;
-}
-
-message Index {
- required uint32 index = 1;
-}
-
-// Example:
-// column1, column2, column3
-message ColumnList {
- required Column col = 1;
- repeated Column extra_cols = 2;
-}
-
-// ~~~~table-or-subquery~~~~
-message TableOrSubquery {
- oneof tos_oneof {
- QualifiedTableName qtn = 1;
- TableOrSubqueryOption2 toso2 = 2;
- TableOrSubqueryOption3 toso3 = 3;
- TableOrSubqueryOption4 toso4 = 4;
- }
- required ExprSchemaTable schema_table_expr = 5; // used if the oneof is empty
-}
-
-message TableOrSubqueryOption2 {
- required ExprSchemaTableFn schema_table_fn = 1;
- optional AsTableAlias as_table_alias = 2;
-}
-
-message TableOrSubqueryOption3 {
- repeated TableOrSubquery tos_list = 1; // if empty, use the join clause
- required JoinClause join_clause = 2;
-}
-
-message TableOrSubqueryOption4 {
- required Select select = 1;
- optional AsTableAlias as_table_alias = 2;
-}
-
-message AsTableAlias {
- required bool as = 2;
- required Table table_alias = 3;
-}
-
-// ~~~~Expressions~~~~
-message Expr {
- oneof expr_oneof {
- LiteralValue lit_val = 1;
- ComplicatedExpr comp_expr = 2;
- }
-}
-
-message NumericLiteral {
- repeated uint32 hex_digits = 1;
- repeated uint32 digits = 2;
- required bool decimal_point = 3;
- repeated uint32 dec_digits = 4;
- repeated uint32 exp_digits = 5;
- required bool negative_exp = 6;
-}
-
-message LiteralValue {
- enum SpecialVal {
- VAL_NULL = 0; // using just "NULL" vauses it not to compile.
- VAL_TRUE = 1;
- VAL_FALSE = 2;
- CURRENT_TIME = 3;
- CURRENT_DATE = 4;
- CURRENT_TIMESTAMP = 5;
- }
- oneof lit_val_oneof {
- int64 num_lit = 1;
- string string_lit = 2;
- bytes blob_lit = 3;
- SpecialVal special_val = 4;
- NumericLiteral numeric_lit = 5;
- } // If no value, just use int64(1)
-}
-
-enum UnaryOperator {
- UNOP_MINUS = 1;
- UNOP_PLUS = 2;
- UNOP_TILDE = 3;
- UNOP_NOT = 4;
-}
-
-message UnaryExpr {
- required UnaryOperator unary_op = 1;
- required Expr expr = 2;
-}
-
-enum BinaryOperator {
- BINOP_CONCAT = 1; // double pipe
- BINOP_STAR = 2;
- BINOP_SLASH = 3;
- BINOP_PERCENT = 4;
- BINOP_PLUS = 5;
- BINOP_MINUS = 6;
- BINOP_LELE = 7; // <<
- BINOP_GRGR = 8; // >>
- BINOP_AMPERSAND = 9;
- BINOP_PIPE = 10;
- BINOP_LE = 11;
- BINOP_LEQ = 12;
- BINOP_GR = 13;
- BINOP_GREQ = 14;
- BINOP_EQ = 15;
- BINOP_EQEQ = 16;
- BINOP_NOTEQ = 17;
- BINOP_LEGR = 18; // <> (not equal)
- BINOP_IS = 19;
- BINOP_ISNOT = 20;
- BINOP_IN = 21;
- BINOP_LIKE = 22;
- BINOP_GLOB = 23;
- BINOP_MATCH = 24;
- BINOP_REGEXP = 25;
- BINOP_AND = 26;
- BINOP_OR = 27;
-}
-
-message BinaryExpr {
- required Expr lhs = 1;
- required BinaryOperator op = 2;
- required Expr rhs = 3;
-
- // In FUZZ_FTS3 mode, if |fmt| exists we will use it instead of rhs to
- // help generate better MATCH queries.
- optional FTS3MatchFormat fmt = 4;
-}
-
-// Used to inflate the probability that we get a comparison of a column with an
-// expr. This is useful, as an example, for WHERE expressions.
-message ExprComparisonHighProbability {
- oneof expr_comp_oneof {
- ColumnComparison cc = 1;
- Expr expr = 2;
- }
-}
-
-// Special version of expr that only generates predicates with a column on the
-// left.
-message ColumnComparison {
- required ExprSchemaTableColumn col = 1;
- required BinaryOperator op = 2;
- required Expr expr = 3;
- // In FUZZ_FTS3 mode, if |fmt| exists we will use it instead of rhs to
- // help generate better MATCH queries.
- optional FTS3MatchFormat fmt = 4;
-}
-
-message ExprSchemaTableColumn {
- optional Schema schema = 1;
- optional Table table = 2;
- required Column col = 3;
-}
-
-// Separate this out to inflate the probability of having a literal value
-message ComplicatedExpr {
- // Don't want bind-parameter, unless fuzzing sql_bind
- oneof complicated_expr_oneof {
- ExprSchemaTableColumn expr_stc = 2;
- UnaryExpr unary_expr = 3;
- BinaryExpr binary_expr = 4;
- Fn fn_expr = 5;
- ParenthesesExpr par_expr = 6;
- CastExpr cast_expr = 7;
- CollateExpr collate_expr = 8;
- Expr1 expr1 = 9;
- ExprNullTests expr_null_tests = 10;
- ExprIs expr_is = 11;
- ExprBetween expr_between = 12;
- ExprIn expr_in = 17;
- ExprExists expr_exists = 13;
- ExprCase expr_case = 14;
- ExprRaiseFn expr_raise = 15;
- }
- required LiteralValue lit_val = 16; // used if oneof is empty.
-}
-
-message ExprRaiseFn {
- required bool ignore = 3;
- enum RaiseFnEnum {
- ROLLBACK = 0;
- ABORT = 1;
- FAIL = 2;
- }
- required RaiseFnEnum raise_fn = 1;
- required string error_msg = 2;
-}
-
-message ExprCase {
- optional Expr expr = 1;
- required ExprWhenThen when_then = 2;
- repeated ExprWhenThen extra_when_thens = 3;
- optional Expr else_expr = 4;
-}
-
-message ExprWhenThen {
- required Expr when_expr = 1;
- required Expr then_expr = 2;
-}
-
-message ExprExists {
- required bool not = 1;
- required bool exists = 2;
- required Select select = 3;
-}
-
-message ExprIn {
- required Expr expr = 5;
- required bool not = 1;
- oneof exprin_oneof {
- ExprInParen expr_in_paren = 2;
- ExprSchemaTable schema_table = 3;
- ExprSchemaTableFn schema_table_fn = 4;
- }
-}
-
-message ExprSchemaTable {
- optional Schema schema_name = 1;
- required Table table_name = 2;
-}
-
-message ExprSchemaTableFn {
- required TableFn table_fn = 2;
- // FIXME in the future add more. For now, no exprs.
-}
-
-message ExprInParen {
- oneof exprin_paren_oneof {
- Select select = 1;
- ExprList exprs = 2;
- } // if zero, can just emit closed parentheses
-}
-
-message ExprList {
- required Expr expr = 1;
- repeated Expr extra_exprs = 2;
-}
-
-message Expr1 {
- required Expr expr1 = 5;
- required bool not = 1;
- enum PossibleKeywords {
- LIKE = 0;
- GLOB = 1;
- REGEXP = 2;
- MATCH = 3;
- }
- required PossibleKeywords keyword = 2;
- required Expr expr2 = 3;
- optional Expr escape_expr = 4; // CORPUS specialize?
-}
-
-message ExprNullTests {
- required Expr expr = 1;
- enum PossibleKeywords {
- ISNULL = 0;
- NOTNULL = 1;
- NOT_NULL = 2;
- }
- required PossibleKeywords keyword = 2;
-}
-
-message ExprIs {
- required bool not = 1;
- required Expr expr1 = 2;
- required Expr expr2 = 3;
-}
-
-message ExprBetween {
- required bool not = 1;
- required Expr expr1 = 2;
- required Expr expr2 = 3;
- required Expr expr3 = 4;
-}
-
-enum CollateType {
- COLLATE_BINARY = 1;
- COLLATE_NOCASE = 2;
- COLLATE_RTRIM = 3;
-}
-
-message CollateExpr {
- required Expr expr = 1;
- required CollateType collate_type = 2;
-}
-
-message CastTypeName {
- enum CastTypeNameEnum {
- BLOB = 0;
- TEXT = 1;
- REAL = 2;
- INTEGER = 3;
- NUMERIC = 4;
- }
- required CastTypeNameEnum type_enum = 1;
-}
-
-message CastExpr {
- required Expr expr = 1;
- required CastTypeName type_name = 2;
-}
-
-message ParenthesesExpr {
- required Expr expr = 1;
- repeated Expr other_exprs = 2;
-}
-
-message Fn {
- oneof fn_oneof {
- SimpleFn simple_fn = 1;
- FTS3AuxiliaryFn fts_aux_fn = 2;
- DateAndTimeFn dat_fn = 3;
- AggregateFn aggregate_fn = 4;
- Printf printf = 5;
- }
- // FIXME in the future: JSON functions. Not used in Chrome.
-}
-
-// Aggregate FNs
-message AggregateFn {
- optional bool count_star = 7;
- enum FnName {
- AVG = 0;
- COUNT = 1;
- GROUP_CONCAT = 2;
- MAX = 3;
- MIN = 4;
- SUM = 5;
- TOTAL = 6;
- }
- required FnName fn_name = 6;
- required bool distinct = 5;
- optional Column col1 = 1;
- optional Column col2 = 2;
- required Expr expr1 = 3;
- optional Expr expr2 = 4;
-}
-
-// Date and Time Functions
-message DateAndTimeFn {
- optional SimpleDateAndTimeFn simple = 1;
- required StrftimeFn strftime = 2;
-}
-
-message StrftimeFn {
- repeated StrftimeFormat fmts = 1;
- required TimeString time_string = 2;
- repeated TimeModifier modifiers = 3;
-}
-
-message StrftimeFormat {
- enum Substitution {
- D = 0;
- F = 1;
- H = 2;
- J = 3;
- M = 4;
- S = 5;
- W = 6;
- Y = 7;
- }
- required bool lowercase = 1;
- optional Substitution subs = 2;
- required string bytes = 3;
-}
-
-message SimpleDateAndTimeFn {
- enum FnName {
- DATE = 0;
- TIME = 1;
- DATETIME = 2;
- JULIANDAY = 3;
- }
- required FnName fn_name = 1;
- required TimeString time_string = 2;
- repeated TimeModifier modifiers = 3;
-}
-
-message HoursStuff {
- optional uint32 hh = 1;
- optional uint32 mm = 2;
- optional uint32 ss = 3;
- optional uint32 sss = 4;
-}
-
-message TimeString {
- optional uint32 yyyy = 1;
- optional uint32 mm = 2;
- optional uint32 dd = 3;
- optional HoursStuff hs = 4;
- required bool extra_t = 6;
-
- optional uint32 dddddddddd = 7;
-
- required bool now = 8;
-
- optional string random_bytes = 9;
-
- required bool z = 13;
- required bool plus = 14;
- optional bool tz_plus = 10;
- optional uint32 tz_hh = 11;
- optional uint32 tz_mm = 12;
-}
-
-message TimeModifier {
- enum NumberedModifiers {
- DAYS = 0;
- HOURS = 1;
- MINUTES = 2;
- SECONDS = 3;
- MONTHS = 4;
- YEARS = 5;
- }
- required uint32 num = 4;
- optional uint32 dot_num = 5;
- optional NumberedModifiers nm = 1;
- enum OtherModifiers {
- START_OF_MONTH = 0;
- START_OF_YEAR = 1;
- START_OF_DAY = 2;
- WEEKDAY = 3;
- UNIXEPOCH = 4;
- LOCALTIME = 5;
- UTC = 6;
- }
- required OtherModifiers om = 2;
- required uint32 weekday = 3;
-}
-
-// Simple Functions finish
-message SimpleFn {
- oneof simple_fn_oneof {
- ZeroArgFn zero_arg_fn = 1;
- OneArgFn one_arg_fn = 2;
- TwoArgFn two_arg_fn = 3;
- ThreeArgFn three_arg_fn = 4;
- VarNumFn varnum_fn = 5;
- CharFn char_fn = 6;
- }
-}
-
-// Zero arguments fn
-enum ZeroArgFn {
- ZFN_CHANGES = 0;
- ZFN_LAST_INSERT_ROWID = 1;
- ZFN_RANDOM = 2;
- ZFN_SQLITE_SOURCE_ID = 3;
- ZFN_SQLITE_VERSION = 4;
- ZFN_TOTAL_CHANGES = 5;
-}
-
-message OneArgFn {
- enum OneArgFnEnum {
- ABS = 1;
- HEX = 2;
- LENGTH = 3;
- LIKELY = 4;
- LOWER = 5;
- LTRIM = 6;
- LOAD_EXTENSION = 7;
- QUOTE = 8;
- ROUND = 9;
- RTRIM = 10;
- RANDOMBLOB = 11;
- SOUNDEX = 12;
- SQLITE_COMPILE_OPTION_GET = 13;
- SQLITE_COMPILE_OPTION_USED = 14;
- SQLITE_OFFSET = 15;
- TRIM = 16;
- TYPEOF = 17;
- UNICODE_ = 18;
- UNLIKELY = 19;
- UPPER = 20;
- ZEROBLOB = 21;
- }
- required OneArgFnEnum fn_enum = 1;
- required Expr arg1 = 2;
-}
-
-message TwoArgFn {
- enum TwoArgFnEnum {
- GLOB = 1;
- IFNULL = 2;
- INSTR = 3;
- LIKE = 4;
- LIKELIHOOD = 5;
- LOAD_EXTENSION = 6;
- LTRIM = 7;
- NULLIF = 8;
- ROUND = 9;
- RTRIM = 10;
- SUBSTR = 11;
- TRIM = 12;
- }
- required TwoArgFnEnum fn_enum = 1;
- required Expr arg1 = 2;
- required Expr arg2 = 3;
-}
-
-message ThreeArgFn {
- enum ThreeArgFnEnum {
- LIKE = 0;
- REPLACE = 1;
- SUBSTR = 2;
- }
- required ThreeArgFnEnum fn_enum = 1;
- required Expr arg1 = 2;
- required Expr arg2 = 3;
- required Expr arg3 = 4;
-}
-
-// Fns with two args required + an arbitrary number of other args.
-message VarNumFn {
- enum VarNumFnEnum {
- COALESCE = 1;
- MAX = 2;
- MIN = 3;
- }
- required VarNumFnEnum fn_enum = 1;
- required Expr arg1 = 2;
- required Expr arg2 = 3;
- repeated Expr other_args = 4;
-}
-
-message CharFn {
- required uint64 char = 1;
- repeated uint64 extra_chars = 2;
-}
-
-message Printf {
- repeated string strings = 1;
- repeated PrintfFormatSpecifier specifiers = 2;
- repeated Expr exprs = 3;
-}
-
-message PrintfFormatSpecifier {
- enum Flags {
- MINUS = 0;
- PLUS = 1;
- SPACE = 2;
- ZERO = 3;
- HASH = 4;
- COMMA = 5;
- BANG = 6;
- }
- repeated Flags flags = 1;
- optional uint32 precision = 2;
- optional uint32 width = 3;
- optional bool width_star = 4;
- // The length modifiers make no difference for the sqlite function.
- optional uint32 length = 5;
- enum SubType {
- I = 0;
- D = 1;
- U = 2;
- F = 3;
- E = 4;
- G = 5;
- X = 6;
- O = 7;
- S = 8;
- Z = 9;
- C = 10;
- P = 11;
- N = 12;
- Q = 13;
- W = 14;
- }
- optional bool percent = 8;
- required SubType sub_type = 6;
- required bool lowercase = 7;
-}
-
-// Window fns!
-// FIXME in the future: this may only be in the result set and the ORDER_BY
-// clause of a SELECT statement.
-message WindowFnInvocation {
- oneof window_fn_oneof {
- ZeroArgWinFn zero_arg_fn = 1;
- OneArgWinFn one_arg_fn = 2;
- NthValueFn nth_value_fn = 4;
- MiscWinFn misc_fn = 3;
- }
-
- // Used if the above oneof produces zero values.
- required ZeroArgWinFn fallback_zero_arg_fn = 5;
-
- // FIXME in the future: may just replace with a WHERE expr.
- optional ExprFilter expr_filter = 6;
- optional WindowDefn win_defn = 7;
- required WindowName win_name = 8; // used only if win_defn above is unused.
-}
-
-message WindowDefn {
- // FIXME in the future: change to specialized expr
- optional ExprList partition_exprs = 1;
- optional MultipleOrderingTerm ordering_terms = 2;
- optional ExprFrameSpec frame_spec = 3;
-}
-
-message ExprFrameSpec {
- enum RangeRows {
- RANGE = 0;
- ROWS = 1;
- }
- required RangeRows range_rows = 1;
- required FrameSpecSubExpr left_expr = 2;
- // if this exists, then this is a BETWEEN statement.
- optional FrameSpecSubExprRight right_expr = 3;
-}
-
-message FrameSpecSubExpr {
- enum Which {
- UNBOUNDED_PRECEDING = 0;
- EXPR_PRECEDING = 1;
- CURRENT_ROW = 2;
- EXPR_FOLLOWING = 3;
- }
- required Which which = 1;
- // only used if which is EXPR_PRECEDING or EXPR_FOLLOWING
- optional Expr expr = 2; // CORPUS specialize? integer?
-}
-
-message FrameSpecSubExprRight {
- enum Which {
- UNBOUNDED_FOLLOWING = 0;
- EXPR_PRECEDING = 1;
- CURRENT_ROW = 2;
- EXPR_FOLLOWING = 3;
- }
- required Which which = 1;
- // only used if which is EXPR_PRECEDING or EXPR_FOLLOWING
- optional Expr expr = 2; // CORPUS specialize? integer?
-}
-
-message MultipleOrderingTerm {
- repeated ExprOrderingTerm terms = 1;
-}
-
-message ExprOrderingTerm {
- required Expr expr = 1; // CORPUS specialize???
- optional CollateType collate_type = 2;
- required AscDesc asc_desc = 3;
-}
-
-enum AscDesc {
- ASCDESC_NONE = 0;
- ASCDESC_ASC = 1;
- ASCDESC_DESC = 2;
-}
-
-message ExprFilter {
- required Expr expr = 1;
-}
-
-message ZeroArgWinFn {
- enum ZeroArgWinFnEnum {
- ROW_NUMBER = 0;
- RANK = 1;
- DENSE_RANK = 2;
- PERCENT_RANK = 3;
- CUME_DIST = 4;
- }
- required ZeroArgWinFnEnum win_fn = 1;
-}
-
-message OneArgWinFn {
- enum OneArgWinFnEnum {
- NTILE = 0;
- FIRST_VALUE = 1;
- LAST_VALUE = 2;
- }
- required OneArgWinFnEnum win_fn = 1;
- required Expr expr = 2;
-}
-
-message NthValueFn {
- required Expr expr = 1;
- required uint32 row_num = 2;
-}
-
-message MiscWinFn {
- enum MiscWinFnEnum {
- LAG = 0;
- LEAD = 1;
- }
- required MiscWinFnEnum fn = 1;
- required Expr expr = 2;
- optional uint32 offset = 3;
- optional Expr default = 4; // unused if offset non-existent
-}
-// FIXME in the future: all aggregate functions may be used as window aggregate
-// functions!
-
-// Table-valued FNs, including pragma table-valued fns.
-enum PragmaFnZeroArgOneResult {
- PFN_ZO_APPLICATION_ID = 0;
- PFN_ZO_AUTO_VACUUM = 1;
- PFN_ZO_AUTOMATIC_INDEX = 2;
- PFN_ZO_BUSY_TIMEOUT = 3;
- PFN_ZO_CACHE_SIZE = 4;
- PFN_ZO_CACHE_SPILL = 5;
- PFN_ZO_CELL_SIZE_CHECK = 6;
- PFN_ZO_CHECKPOINT_FULL_FSYNC = 7;
- PFN_ZO_COLLATION_LIST = 8;
- PFN_ZO_COMPILE_OPTIONS = 9;
- PFN_ZO_COUNT_CHANGES = 10;
- PFN_ZO_DATA_VERSION = 11;
- PFN_ZO_DATABASE_LIST = 12;
- PFN_ZO_DEFAULT_CACHE_SIZE = 13;
- PFN_ZO_DEFER_FOREIGN_KEYS = 14;
- PFN_ZO_EMPTY_RESULT_CALLBACKS = 15;
- PFN_ZO_ENCODING = 16;
- PFN_ZO_FOREIGN_KEY_CHECK = 17;
- PFN_ZO_FOREIGN_KEYS = 18;
- PFN_ZO_FREELIST_COUNT = 19;
- PFN_ZO_FULL_COLUMN_NAMES = 20;
- PFN_ZO_FULLFSYNC = 21;
- PFN_ZO_FUNCTION_LIST = 22;
- PFN_ZO_IGNORE_CHECK_CONSTRAINTS = 23;
- PFN_ZO_INTEGRITY_CHECK = 24;
- PFN_ZO_JOURNAL_SIZE_LIMIT = 25;
- PFN_ZO_LEGACY_ALTER_TABLE = 26;
- PFN_ZO_LEGACY_FILE_FORMAT = 27;
- PFN_ZO_LOCK_STATUS = 28;
- PFN_ZO_LOCKING_MODE = 29;
- PFN_ZO_MAX_PAGE_COUNT = 30;
- PFN_ZO_MODULE_LIST = 31;
- PFN_ZO_PAGE_COUNT = 32;
- PFN_ZO_PAGE_SIZE = 33;
- PFN_ZO_PRAGMA_LIST = 34;
- PFN_ZO_QUERY_ONLY = 35;
- PFN_ZO_QUICK_CHECK = 36;
- PFN_ZO_READ_UNCOMMITTED = 37;
- PFN_ZO_RECURSIVE_TRIGGERS = 38;
- PFN_ZO_REVERSE_UNORDERED_SELECTS = 39;
- PFN_ZO_SCHEMA_VERSION = 40;
- PFN_ZO_SECURE_DELETE = 41;
- PFN_ZO_SHORT_COLUMN_NAMES = 42;
- PFN_ZO_SOFT_HEAP_LIMIT = 43;
- PFN_ZO_SQL_TRACE = 44;
- PFN_ZO_STATS = 45;
- PFN_ZO_SYNCHRONOUS = 46;
- PFN_ZO_TEMP_STORE = 47;
- PFN_ZO_THREADS = 48;
- PFN_ZO_USER_VERSION = 49;
- // omit vdbe_* debug pragmas
- PFN_ZO_WRITEABLE_SCHEMA = 50;
-}
-
-message TableFn {
- required PragmaFnZeroArgOneResult no_arg_one_result = 10;
- oneof pragma_fn_oneof {
- Table foreign_key_list = 1;
- Index index_info = 2;
- Table index_list = 3;
- Index index_xinfo = 4;
- uint32 integrity_check = 5;
- uint32 optimize = 6;
- uint32 quick_check = 7;
- Table table_info = 8;
- Table table_xinfo = 9;
- }
-}
diff --git a/chromium/third_party/sqlite/fuzz/sql_query_proto_to_string.cc b/chromium/third_party/sqlite/fuzz/sql_query_proto_to_string.cc
deleted file mode 100644
index 84a09fd1604..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_query_proto_to_string.cc
+++ /dev/null
@@ -1,2757 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <array>
-#include <cctype>
-#include <cstdint>
-#include <iomanip>
-#include <map>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "third_party/sqlite/fuzz/icu_codes.pb.h"
-#include "third_party/sqlite/fuzz/sql_queries.pb.h"
-#include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
-#include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
-
-using namespace sql_query_grammar;
-
-#define CONV_FN(TYPE, VAR_NAME) std::string TYPE##ToString(const TYPE& VAR_NAME)
-
-#define RETURN_IF_DISABLED_QUERY(TYPE) \
- if (disabled_queries_.count(#TYPE) != 0) \
- return "";
-
-namespace sql_fuzzer {
-
-namespace {
-constexpr uint32_t kMaxColumnNumber = 20;
-#if !defined(FUZZ_FTS3)
-constexpr uint32_t kMaxTableNumber = 8;
-#endif
-constexpr uint32_t kMaxSchemaNumber = 4;
-constexpr uint32_t kMaxWindowNumber = 5;
-
-constexpr uint32_t kMaxColumnConstraintNumber = 10;
-constexpr uint32_t kMaxTableConstraintNumber = 10;
-
-constexpr uint32_t kMaxIndexNumber = 10;
-
-// should be less than kMaxTableNumber
-constexpr uint32_t kMaxFTS3TableNumber = 2;
-
-constexpr uint32_t kMaxStrLength =
- 200; // So these are readable and somewhat performant, keep a maximum
- // string length......
-
-#if !defined(FUZZ_OMIT_SAVEPOINT)
-constexpr uint32_t kMaxSavePointNumber = 10;
-#endif
-
-constexpr uint32_t kMaxViewNumber = 5;
-constexpr uint32_t kMaxTriggerNumber = 10;
-
-std::set<std::string> disabled_queries_;
-} // namespace
-
-CONV_FN(Expr, expr);
-CONV_FN(Select, select);
-CONV_FN(TableOrSubquery, tos);
-CONV_FN(FTS3Table, ft);
-CONV_FN(FTS3NearQuery, fnq);
-CONV_FN(FTS3AuxiliaryFn, faf);
-CONV_FN(FTS3MatchFormat, fmf);
-CONV_FN(DateAndTimeFn, sfn);
-CONV_FN(ExprSchemaTableFn, estf);
-
-// ~~~~Numbered values to string~~~
-
-// WARNING does not include space at the end
-CONV_FN(Column, col) {
- if (col.has_rowid() && col.rowid())
- return "rowid";
-#if defined(FUZZ_FTS3)
- if (col.has_fts3_docid() && col.fts3_docid())
- return "docid";
- if (col.has_fts3_table())
- return FTS3TableToString(col.fts3_table());
-#endif
- std::string ret("Col");
- ret += std::to_string(col.column() % kMaxColumnNumber);
- return ret;
-}
-
-// WARNING does not include space at the end
-CONV_FN(Table, table) {
- std::string ret("Table");
-#if defined(FUZZ_FTS3)
- // only fuzzing FTS3 tables, clamp to the max FTS3 table num.
- ret += std::to_string(table.table() & kMaxFTS3TableNumber);
- if (table.fts3_content_table())
- ret += "_content";
-#else
- ret += std::to_string(table.table() % kMaxTableNumber);
-#endif
- return ret;
-}
-
-// WARNING does not include space at the end
-CONV_FN(Schema, schema) {
- if (schema.main()) {
- return "main";
- }
- if (schema.temp()) {
- return "temp";
- }
- std::string ret("Schema");
- ret += std::to_string(schema.schema() % kMaxSchemaNumber);
- return ret;
-}
-
-// WARNING does not include space at the end
-CONV_FN(WindowName, win) {
- std::string ret("Window");
- ret += std::to_string(win.window_name() % kMaxWindowNumber);
- return ret;
-}
-
-// WARNING does not include space at the end
-CONV_FN(ColumnConstraintName, cc) {
- std::string ret("ColConstraint");
- ret += std::to_string(cc.constraint_name() % kMaxColumnConstraintNumber);
- return ret;
-}
-
-// WARNING does not include space at the end
-CONV_FN(TableConstraintName, tc) {
- std::string ret("TableConstraint");
- ret += std::to_string(tc.constraint_name() % kMaxTableConstraintNumber);
- return ret;
-}
-
-// WARNING does not include space at the end
-CONV_FN(Index, index) {
- std::string ret("Index");
- ret += std::to_string(index.index() % kMaxIndexNumber);
- return ret;
-}
-
-#if !defined(FUZZ_OMIT_SAVEPOINT)
-CONV_FN(SavePoint, sp) {
- std::string ret("SavePoint");
- ret += std::to_string(sp.savepoint_num() % kMaxSavePointNumber);
- return ret;
-}
-#endif
-
-CONV_FN(View, v) {
- std::string ret("View");
- ret += std::to_string(v.view() % kMaxViewNumber);
- return ret;
-}
-
-CONV_FN(Trigger, t) {
- std::string ret("Trigger");
- ret += std::to_string(t.trigger() % kMaxTriggerNumber);
- return ret;
-}
-
-// ~~~~Utility functions~~~~
-
-std::string AscDescToString(AscDesc a) {
- switch (a) {
- case ASCDESC_NONE:
- return " ";
- case ASCDESC_ASC:
- return "ASC ";
- case ASCDESC_DESC:
- return "DESC ";
- default:
- return " ";
- }
-}
-
-std::string StrToLower(std::string s) {
- std::transform(
- s.begin(), s.end(), s.begin(),
- [](unsigned char c) -> unsigned char { return std::tolower(c); });
- return s;
-}
-
-std::string StripTrailingUnderscores(std::string s) {
- s.erase(std::find_if(s.rbegin(), s.rend(),
- [](unsigned char ch) { return ch != '_'; })
- .base(),
- s.end());
- return s;
-}
-
-// Converts underscores to spaces in a string.
-// This is because many enums like SET_NULL will be displayed at SET NULL in
-// the query, and I want to use protobuf's enum to string function to save time.
-std::string EnumStrReplaceUnderscores(std::string s) {
- std::transform(s.begin(), s.end(), s.begin(),
- [](unsigned char c) -> unsigned char {
- if (c == '_')
- return ' ';
- return c;
- });
- return s;
-}
-
-// Takes garbage data and produces a string, with quotes escaped.
-// Caps the number of bytes received from the protobuf at kMaxStrLength.
-// The final string could be as much as kMaxStrLength*2 as we added an extra
-// single quote for every single quote in the input string.
-std::string ConvertToSqlString(const std::string& s) {
- std::string ret;
- ret.reserve(kMaxStrLength * 2);
- for (size_t i = 0; i < s.length() && i < kMaxStrLength; i++) {
- ret += s[i];
- if (s[i] == '\'')
- ret += '\'';
- }
- return ret;
-}
-
-// WARNING does not include space
-std::string BytesToHex(const std::string& str) {
- std::ostringstream ss;
- ss << std::hex << std::setfill('0');
- for (size_t i = 0; i < str.size() && i < kMaxStrLength; i++) {
- ss << std::setw(2) << static_cast<int>(str[i]);
- }
- return ss.str();
-}
-
-// WARNING no space at end
-CONV_FN(ExprSchemaTable, st) {
- std::string ret;
- if (st.has_schema_name()) {
- ret += SchemaToString(st.schema_name());
- ret += ".";
- }
- ret += TableToString(st.table_name());
- return ret;
-}
-
-CONV_FN(ExprSchemaTableColumn, stc) {
- std::string ret;
- if (stc.has_schema()) {
- ret += SchemaToString(stc.schema());
- ret += ".";
- }
- if (stc.has_table()) {
- ret += TableToString(stc.table());
- ret += ".";
- }
- ret += ColumnToString(stc.col());
- return ret;
-}
-
-// WARNING does not include parentheses, nor a space at the end
-CONV_FN(ColumnList, cl) {
- std::string ret = ColumnToString(cl.col());
- for (int i = 0; i < cl.extra_cols_size(); i++) {
- ret += ", ";
- ret += ColumnToString(cl.extra_cols(i));
- }
- return ret;
-}
-
-CONV_FN(ExprList, me) {
- std::string ret = ExprToString(me.expr());
- for (int i = 0; i < me.extra_exprs_size(); i++) {
- ret += ", ";
- ret += ExprToString(me.extra_exprs(i));
- }
- return ret;
-}
-
-// WARNING does not include space
-CONV_FN(CollateType, collate_type) {
- std::string ct = CollateType_Name(collate_type);
- ct.erase(0, std::string("COLLATE_").length());
- return ct;
-}
-
-// WARNING does not include space
-CONV_FN(IndexedColumn, ic) {
- std::string ret;
- if (ic.has_expr()) {
- ret += ExprToString(ic.expr());
- } else {
- ret += ColumnToString(ic.col());
- }
- ret += " ";
- if (ic.has_collate_type()) {
- ret += "COLLATE ";
- ret += CollateTypeToString(ic.collate_type());
- ret += " ";
- }
- ret += AscDescToString(ic.asc_desc());
-
- return ret;
-}
-
-CONV_FN(IndexedColumnList, ic_list) {
- std::string ret;
- ret += IndexedColumnToString(ic_list.indexed_col());
- for (int i = 0; i < ic_list.extra_indexed_cols_size(); i++) {
- ret += ", ";
- ret += IndexedColumnToString(ic_list.extra_indexed_cols(i));
- }
- return ret;
-}
-
-CONV_FN(SchemaTableAsAlias, staa) {
- std::string ret;
- ret += ExprSchemaTableToString(staa.schema_table());
- ret += " ";
-
- if (staa.has_as_table_alias()) {
- ret += "AS ";
- ret += TableToString(staa.as_table_alias());
- ret += " ";
- }
- return ret;
-}
-
-// ~~~~Expression stuff~~~~
-
-// WARNING does not include space
-CONV_FN(NumericLiteral, nl) {
- static constexpr char hex_digits[] = "0123456789ABCDEF";
- static constexpr char digits[] = "0123456789";
- std::string ret;
- if (nl.hex_digits_size() > 0) {
- ret += "0x";
- for (int i = 0; i < nl.hex_digits_size(); i++) {
- ret += hex_digits[nl.hex_digits(i) % sizeof(hex_digits)];
- }
-
- return ret;
- }
- for (int i = 0; i < nl.digits_size(); i++) {
- ret += digits[nl.digits(i) % sizeof(digits)];
- }
- if (nl.decimal_point()) {
- ret += ".";
- if (nl.dec_digits_size() == 0) {
- ret += "0";
- } else {
- for (int i = 0; i < nl.dec_digits_size(); i++) {
- ret += digits[nl.dec_digits(i) % sizeof(digits)];
- }
- }
- }
- if (nl.exp_digits_size() > 0) {
- ret += "E";
- if (nl.negative_exp())
- ret += "-";
- if (nl.exp_digits_size() == 0) {
- ret += "0";
- } else {
- for (int i = 0; i < nl.exp_digits_size(); i++) {
- ret += digits[nl.exp_digits(i) % sizeof(digits)];
- }
- }
- }
-
- return ret;
-}
-
-// WARNING does not include space
-CONV_FN(LiteralValue, lit_val) {
- std::string ret;
- using LitValType = LiteralValue::LitValOneofCase;
- switch (lit_val.lit_val_oneof_case()) {
- case LitValType::kNumLit:
- return std::to_string(lit_val.num_lit());
- case LitValType::kStringLit:
- ret += '\'';
- ret += ConvertToSqlString(lit_val.string_lit());
- ret += '\'';
- return ret;
- case LitValType::kBlobLit:
- ret += "x\'";
- ret += BytesToHex(lit_val.blob_lit());
- ret += '\'';
- return ret;
- case LitValType::kSpecialVal:
- // special case for NULL, TRUE, FALSE
- if (lit_val.special_val() == LiteralValue::VAL_NULL)
- return "NULL";
- if (lit_val.special_val() == LiteralValue::VAL_TRUE)
- return "TRUE";
- if (lit_val.special_val() == LiteralValue::VAL_FALSE)
- return "FALSE";
- // do not remove underscores
- return LiteralValue_SpecialVal_Name(lit_val.special_val());
- case LitValType::kNumericLit:
- return NumericLiteralToString(lit_val.numeric_lit());
- default:
- return "1";
- }
-}
-
-CONV_FN(UnaryExpr, uexpr) {
- std::string ret;
- switch (uexpr.unary_op()) {
- case UNOP_MINUS:
- ret += "-";
- break;
- case UNOP_PLUS:
- ret += "+";
- break;
- case UNOP_TILDE:
- ret += "~";
- break;
- case UNOP_NOT:
- ret += "NOT ";
- break;
- default:
- break;
- }
- ret += ExprToString(uexpr.expr());
- return ret;
-}
-
-CONV_FN(BinaryOperator, bop) {
- switch (bop) {
- case BINOP_CONCAT:
- return " || ";
- break;
- case BINOP_STAR:
- return " * ";
- break;
- case BINOP_SLASH:
- return " / ";
- break;
- case BINOP_PERCENT:
- return " % ";
- break;
- case BINOP_PLUS:
- return " + ";
- break;
- case BINOP_MINUS:
- return " - ";
- break;
- case BINOP_LELE:
- return " << ";
- break;
- case BINOP_GRGR:
- return " >> ";
- break;
- case BINOP_AMPERSAND:
- return " & ";
- break;
- case BINOP_PIPE:
- return " | ";
- break;
- case BINOP_LE:
- return " < ";
- break;
- case BINOP_LEQ:
- return " <= ";
- break;
- case BINOP_GR:
- return " > ";
- break;
- case BINOP_GREQ:
- return " >= ";
- break;
- case BINOP_EQ:
- return " = ";
- break;
- case BINOP_EQEQ:
- return " == ";
- break;
- case BINOP_NOTEQ:
- return " != ";
- break;
- case BINOP_LEGR:
- return " <> ";
- break;
- case BINOP_IS:
- return " IS ";
- break;
- case BINOP_ISNOT:
- return " IS NOT ";
- break;
- case BINOP_IN:
- return " IN "; // CORPUS specialize?
- break;
- case BINOP_LIKE:
- return " LIKE "; // CORPUS specialize?
- break;
- case BINOP_GLOB:
- return " GLOB "; // CORPUS
- break;
- case BINOP_MATCH:
- return " MATCH "; // CORPUS
- break;
- case BINOP_REGEXP:
- return " REGEXP "; // CORPUS
- break;
- case BINOP_AND:
- return " AND ";
- break;
- case BINOP_OR:
- return " OR ";
- break;
- default:
- return " AND ";
- break;
- }
-}
-
-// TODO(mpdenton) generate better REGEXP queries in non-fts3 case. (in
-// ColumnComparison as well)
-// TODO(mpdenton) generate better MATCH queries in non-fts3 case.
-CONV_FN(BinaryExpr, bexpr) {
- std::string ret;
- ret += ExprToString(bexpr.lhs());
- ret += BinaryOperatorToString(bexpr.op());
-#if defined(FUZZ_FTS3)
- if (bexpr.op() == BINOP_MATCH && bexpr.has_fmt()) {
- ret += FTS3MatchFormatToString(bexpr.fmt());
- return ret;
- }
-#endif
- ret += ExprToString(bexpr.rhs());
- return ret;
-}
-
-CONV_FN(AggregateFn, af) {
- std::string ret;
- ret += StrToLower(AggregateFn_FnName_Name(af.fn_name()));
- ret += "(";
- if (af.fn_name() == AggregateFn::COUNT && af.count_star())
- return ret + "*) ";
- if (af.distinct())
- ret += "DISTINCT ";
- if (af.has_col1()) {
- ret += ColumnToString(af.col1());
- if (af.fn_name() == AggregateFn::GROUP_CONCAT && af.has_col2()) {
- ret += ", ";
- ret += ColumnToString(af.col2());
- }
- } else {
- ret += ExprToString(af.expr1());
- if (af.fn_name() == AggregateFn::GROUP_CONCAT && af.has_expr2()) {
- ret += ", ";
- ret += ExprToString(af.expr2());
- }
- }
-
- ret += ") ";
- return ret;
-}
-
-CONV_FN(ZeroArgFn, zaf) {
- std::string func = ZeroArgFn_Name(zaf);
- // Remove ZFN_ prefix
- func.erase(0, std::string("ZFN_").length());
- return StrToLower(func) + "() ";
-}
-
-CONV_FN(OneArgFn, oaf) {
- std::string ret;
- ret += StripTrailingUnderscores(
- StrToLower(OneArgFn_OneArgFnEnum_Name(oaf.fn_enum())));
- ret += "(";
- ret += ExprToString(oaf.arg1());
- ret += ") ";
- return ret;
-}
-
-CONV_FN(TwoArgFn, taf) {
- std::string ret;
- ret += StrToLower(TwoArgFn_TwoArgFnEnum_Name(taf.fn_enum()));
- ret += "(";
- ret += ExprToString(taf.arg1());
- ret += ", ";
- ret += ExprToString(taf.arg2());
- ret += ") ";
- return ret;
-}
-
-CONV_FN(ThreeArgFn, taf) {
- std::string ret;
- ret += StrToLower(ThreeArgFn_ThreeArgFnEnum_Name(taf.fn_enum()));
- ret += "(";
- ret += ExprToString(taf.arg1());
- ret += ", ";
- ret += ExprToString(taf.arg2());
- ret += ", ";
- ret += ExprToString(taf.arg3());
- ret += ") ";
- return ret;
-}
-
-CONV_FN(VarNumFn, vfn) {
- std::string ret;
- ret += StrToLower(VarNumFn_VarNumFnEnum_Name(vfn.fn_enum()));
- ret += "(";
- ret += ExprToString(vfn.arg1());
- ret += ", ";
- ret += ExprToString(vfn.arg2());
- for (int i = 0; i < vfn.other_args_size(); i++) {
- ret += ", ";
- ret += ExprToString(vfn.other_args(i));
- }
- ret += ") ";
- return ret;
-}
-
-CONV_FN(CharFn, cfn) {
- std::string ret("char(");
- ret += std::to_string(cfn.char_());
- for (int i = 0; i < cfn.extra_chars_size(); i++) {
- ret += ", ";
- ret += std::to_string(cfn.extra_chars(i));
- }
- ret += ") ";
- return ret;
-}
-
-CONV_FN(SimpleFn, sfn) {
- // oneof
- if (sfn.has_zero_arg_fn()) {
- return ZeroArgFnToString(sfn.zero_arg_fn());
- } else if (sfn.has_one_arg_fn()) {
- return OneArgFnToString(sfn.one_arg_fn());
- } else if (sfn.has_two_arg_fn()) {
- return TwoArgFnToString(sfn.two_arg_fn());
- } else if (sfn.has_three_arg_fn()) {
- return ThreeArgFnToString(sfn.three_arg_fn());
- } else if (sfn.has_varnum_fn()) {
- return VarNumFnToString(sfn.varnum_fn());
- } else if (sfn.has_char_fn()) {
- return CharFnToString(sfn.char_fn());
- } else {
- return "changes() ";
- }
-}
-
-CONV_FN(PrintfFormatSpecifier, pfs) {
- std::string ret("%");
- for (int i = 0; i < pfs.flags_size(); i++) {
- switch (pfs.flags(i)) {
- case PrintfFormatSpecifier::MINUS:
- ret += "-";
- break;
- case PrintfFormatSpecifier::PLUS:
- ret += "+";
- break;
- case PrintfFormatSpecifier::SPACE:
- ret += " ";
- break;
- case PrintfFormatSpecifier::ZERO:
- ret += "0";
- break;
- case PrintfFormatSpecifier::HASH:
- ret += "#";
- break;
- case PrintfFormatSpecifier::COMMA:
- ret += ",";
- break;
- case PrintfFormatSpecifier::BANG:
- ret += "!";
- break;
- }
- }
- if (pfs.has_width()) {
- ret += std::to_string(pfs.width());
- } else if (pfs.width_star()) {
- ret += "*";
- }
- if (pfs.has_precision()) {
- ret += ".";
- ret += std::to_string(pfs.precision());
- }
- if (pfs.has_length()) {
- if (pfs.length() % 3 == 1) {
- ret += "l";
- } else if (pfs.length() % 3 == 2) {
- ret += "ll";
- }
- }
- if (pfs.percent()) {
- ret += "%";
- } else {
- std::string specifier = PrintfFormatSpecifier_SubType_Name(pfs.sub_type());
- if (pfs.lowercase())
- specifier = StrToLower(specifier);
- ret += specifier;
- }
- return ret;
-}
-
-CONV_FN(Printf, p) {
- std::string ret("printf(\'");
- for (int i = 0; i < p.specifiers_size(); i++) {
- ret += PrintfFormatSpecifierToString(p.specifiers(i));
- if (i < p.strings_size()) {
- ret += ConvertToSqlString(p.strings(i));
- }
- }
- ret += "\'";
- for (int i = 0; i < p.exprs_size(); i++) {
- ret += ", ";
- ret += ExprToString(p.exprs(i));
- }
- ret += ") ";
- return ret;
-}
-
-CONV_FN(Fn, fn) {
- // oneof
- if (fn.has_simple_fn()) {
- return SimpleFnToString(fn.simple_fn());
- } else if (fn.has_fts_aux_fn()) {
-#if defined(FUZZ_FTS3)
- return FTS3AuxiliaryFnToString(fn.fts_aux_fn()) + " ";
-#else
- return "changes() ";
-#endif
- } else if (fn.has_dat_fn()) {
- return DateAndTimeFnToString(fn.dat_fn());
- } else if (fn.has_aggregate_fn()) {
- return AggregateFnToString(fn.aggregate_fn());
- } else if (fn.has_printf()) {
- return PrintfToString(fn.printf());
- } else {
- return "changes() ";
- }
-}
-
-CONV_FN(ParenthesesExpr, pexpr) {
- std::string ret("(");
- ret += ExprToString(pexpr.expr());
- for (int i = 0; i < pexpr.other_exprs_size(); i++) {
- ret += ", ";
- ret += ExprToString(pexpr.other_exprs(i));
- }
- ret += ") ";
- return ret;
-}
-
-CONV_FN(CastExpr, cexpr) {
- std::string ret("CAST(");
- ret += ExprToString(cexpr.expr());
- ret += " AS ";
- ret += EnumStrReplaceUnderscores(
- CastTypeName_CastTypeNameEnum_Name(cexpr.type_name().type_enum()));
- ret += ") ";
- return ret;
-}
-
-CONV_FN(CollateExpr, cexpr) {
- std::string ret;
- ret += ExprToString(cexpr.expr());
- ret += " COLLATE ";
- ret += CollateTypeToString(cexpr.collate_type());
- return ret;
-}
-
-CONV_FN(Expr1, e) {
- std::string ret;
- ret += ExprToString(e.expr1());
- ret += " ";
- if (e.not_())
- ret += "NOT ";
- ret += EnumStrReplaceUnderscores(Expr1_PossibleKeywords_Name(e.keyword()));
- ret += " ";
- ret += ExprToString(e.expr2());
- ret += " "; //
- if (e.has_escape_expr()) {
- ret += "ESCAPE ";
- ret += ExprToString(e.escape_expr());
- ret += " "; //
- }
- return ret;
-}
-
-CONV_FN(ExprNullTests, e) {
- std::string ret = ExprToString(e.expr());
- ret += " ";
- ret += EnumStrReplaceUnderscores(
- ExprNullTests_PossibleKeywords_Name(e.keyword()));
- ret += " ";
- return ret;
-}
-
-CONV_FN(ExprIs, e) {
- std::string ret = ExprToString(e.expr1());
- ret += " IS ";
- if (e.not_())
- ret += "NOT ";
- ret += ExprToString(e.expr2());
- ret += " "; //
- return ret;
-}
-
-CONV_FN(ExprBetween, e) {
- std::string ret;
- ret += ExprToString(e.expr1());
- ret += " ";
- if (e.not_())
- ret += "NOT ";
- ret += "BETWEEN ";
- ret += ExprToString(e.expr2());
- ret += " AND ";
- ret += ExprToString(e.expr3());
- return ret;
-}
-
-CONV_FN(ExprInParen, e) {
- std::string ret("(");
- // oneof
- if (e.has_select()) {
- ret += SelectToString(e.select());
- } else if (e.has_exprs()) {
- ret += ExprListToString(e.exprs());
- }
-
- ret += ") ";
- return ret;
-}
-
-CONV_FN(ExprIn, e) {
- std::string ret = ExprToString(e.expr());
- ret += " ";
- if (e.not_())
- ret += "NOT ";
- if (e.has_expr_in_paren()) {
- ret += ExprInParenToString(e.expr_in_paren());
- } else if (e.has_schema_table()) {
- ret += ExprSchemaTableToString(e.schema_table());
- } else if (e.has_schema_table_fn()) {
- ret += ExprSchemaTableFnToString(e.schema_table_fn());
- } else {
- ret += "()";
- }
- return ret + " ";
-}
-
-CONV_FN(ExprExists, e) {
- std::string ret;
- if (e.not_())
- ret += "NOT EXISTS ";
- else if (e.exists())
- ret += "EXISTS ";
- ret += "(";
- ret += SelectToString(e.select());
- ret += ") ";
- return ret;
-}
-
-// WARNING no space at end
-CONV_FN(ExprWhenThen, e) {
- std::string ret("WHEN ");
- ret += ExprToString(e.when_expr());
- ret += " THEN ";
- ret += ExprToString(e.then_expr());
- return ret;
-}
-
-CONV_FN(ExprCase, e) {
- std::string ret("CASE ");
- if (e.has_expr()) {
- ret += ExprToString(e.expr());
- ret += " ";
- }
- ret += ExprWhenThenToString(e.when_then());
- ret += " ";
- for (int i = 0; i < e.extra_when_thens_size(); i++) {
- ret += ExprWhenThenToString(e.extra_when_thens(i));
- ret += " ";
- }
- if (e.has_else_expr()) {
- ret += "ELSE ";
- ret += ExprToString(e.else_expr());
- ret += " ";
- }
- ret += "END ";
- return ret;
-}
-
-CONV_FN(ExprRaiseFn, e) {
- std::string ret("RAISE(");
- if (e.ignore()) {
- ret += "IGNORE";
- } else {
- ret +=
- EnumStrReplaceUnderscores(ExprRaiseFn_RaiseFnEnum_Name(e.raise_fn()));
- ret += " ";
- ret += ", \'";
- ret += ConvertToSqlString(e.error_msg());
- ret += "\'";
- }
- ret += ") ";
- return ret;
-}
-
-CONV_FN(ComplicatedExpr, expr) {
- using ExprType = ComplicatedExpr::ComplicatedExprOneofCase;
- switch (expr.complicated_expr_oneof_case()) {
- case ExprType::kExprStc:
- return ExprSchemaTableColumnToString(expr.expr_stc());
- case ExprType::kUnaryExpr:
- return UnaryExprToString(expr.unary_expr());
- case ExprType::kBinaryExpr:
- return BinaryExprToString(expr.binary_expr());
- case ExprType::kFnExpr:
- return FnToString(expr.fn_expr());
- case ExprType::kParExpr:
- return ParenthesesExprToString(expr.par_expr());
- case ExprType::kCastExpr:
- return CastExprToString(expr.cast_expr());
- case ExprType::kCollateExpr:
- return CollateExprToString(expr.collate_expr());
- case ExprType::kExpr1:
- return Expr1ToString(expr.expr1());
- case ExprType::kExprNullTests:
- return ExprNullTestsToString(expr.expr_null_tests());
- case ExprType::kExprIs:
- return ExprIsToString(expr.expr_is());
- case ExprType::kExprBetween:
- return ExprBetweenToString(expr.expr_between());
- case ExprType::kExprIn:
- return ExprInToString(expr.expr_in());
- case ExprType::kExprExists:
- return ExprExistsToString(expr.expr_exists());
- case ExprType::kExprCase:
- return ExprCaseToString(expr.expr_case());
- case ExprType::kExprRaise:
- return ExprRaiseFnToString(expr.expr_raise());
- default:
- return "1";
- }
-}
-
-// TODO(mpdenton) wrap in parentheses???
-CONV_FN(Expr, expr) {
- if (expr.has_lit_val()) {
- return LiteralValueToString(expr.lit_val());
- } else if (expr.has_comp_expr()) {
- return ComplicatedExprToString(expr.comp_expr());
- } else { // default
- return "1";
- }
-}
-
-// ~~~~Other~~~~
-
-std::string ForeignKeyClauseNotMatchToString(
- const ForeignKeyClauseNotMatch& nm) {
- std::string ret("ON ");
- ret += EnumStrReplaceUnderscores(
- ForeignKeyClauseNotMatch_DeleteOrUpdate_Name(nm.del_or_update()));
- ret += " ";
- ret += EnumStrReplaceUnderscores(
- ForeignKeyClauseNotMatch_Action_Name(nm.action()));
- ret += " ";
- return ret;
-}
-
-CONV_FN(ForeignKeyClauseCore, fkc) {
- if (fkc.has_fkey_not_match())
- return ForeignKeyClauseNotMatchToString(fkc.fkey_not_match());
-
- return "MATCH PARTIAL"; // Sqlite does not actually parse MATCH clauses. This
- // is assumed to be MATCH SIMPLE.
-}
-
-CONV_FN(DeferStrategy, ds) {
- std::string ret;
- if (ds.not_()) {
- ret += "NOT ";
- }
- ret += "DEFERRABLE ";
- ret +=
- EnumStrReplaceUnderscores(DeferStrategy_DeferStratEnum_Name(ds.strat()));
- return ret;
-}
-
-CONV_FN(ForeignKeyClause, fkey_clause) {
- std::string ret("REFERENCES ");
- ret += TableToString(fkey_clause.foreign_table());
- if (fkey_clause.has_col_list()) {
- ret += "(";
- ret += ColumnListToString(fkey_clause.col_list());
- ret += ")";
- }
- ret += " ";
- for (int i = 0; i < fkey_clause.fkey_cores_size(); i++) {
- ret += ForeignKeyClauseCoreToString(fkey_clause.fkey_cores(i));
- ret += " ";
- }
- if (fkey_clause.has_defer_strat()) {
- ret += DeferStrategyToString(fkey_clause.defer_strat());
- ret += " ";
- }
- return ret;
-}
-
-CONV_FN(ConflictClause, conf) {
- if (!conf.has_on_conflict())
- return " ";
-
- std::string ret("ON CONFLICT ");
- ret += EnumStrReplaceUnderscores(
- ConflictClause_OnConflict_Name(conf.on_conflict()));
- ret += " ";
- return ret;
-}
-
-CONV_FN(ColConstraintOpt1, opt1) {
- std::string ret("PRIMARY KEY ");
- ret += AscDescToString(opt1.asc_desc());
- // space at the end already
- ret += ConflictClauseToString(opt1.conflict());
- if (opt1.autoincrement())
- ret += "AUTOINCREMENT ";
-
- return ret;
-}
-
-CONV_FN(ColConstraintOpt2, opt2) {
- std::string ret("DEFAULT ");
- if (opt2.has_expr()) {
- ret += "(";
- ret += ExprToString(opt2.expr());
- ret += ")";
- } else {
- ret += LiteralValueToString(opt2.lit_val());
- }
-
- ret += " ";
- return ret;
-}
-
-CONV_FN(ColumnConstraint, col_constr) {
- std::string ret;
- if (col_constr.has_constraint_name()) {
- ret += "CONSTRAINT ";
- ret += ColumnConstraintNameToString(col_constr.constraint_name());
- ret += " ";
- }
-
- using ColConstrType = ColumnConstraint::ColConstraintOneofCase;
- switch (col_constr.col_constraint_oneof_case()) {
- case ColConstrType::kOpt1:
- ret += ColConstraintOpt1ToString(col_constr.opt1());
- break;
- case ColConstrType::kNotNullConfClause:
- ret += "NOT NULL ";
- ret += ConflictClauseToString(col_constr.not_null_conf_clause());
- break;
- case ColConstrType::kUniqueConfClause:
- ret += "UNIQUE ";
- ret += ConflictClauseToString(col_constr.unique_conf_clause());
- break;
- case ColConstrType::kCheckExpr:
- ret += "CHECK(";
- ret += ExprToString(col_constr.check_expr());
- ret += ") ";
- break;
- case ColConstrType::kOpt2:
- ret += ColConstraintOpt2ToString(col_constr.opt2());
- break;
- case ColConstrType::kCollate:
- ret += "COLLATE ";
- ret += CollateTypeToString(col_constr.collate());
- ret += " ";
- break;
- case ColConstrType::kFkeyClause:
- ret += ForeignKeyClauseToString(col_constr.fkey_clause());
- break;
- default:
- ret += ColConstraintOpt2ToString(col_constr.opt2_fallback());
- }
-
- return ret;
-}
-
-CONV_FN(TypeName, type_name) {
- std::string ret;
- ret += EnumStrReplaceUnderscores(
- CastTypeName_CastTypeNameEnum_Name(type_name.ctn().type_enum()));
- if (type_name.has_sn()) {
- ret += "(";
- ret += std::to_string(type_name.sn());
- ret += ")";
- }
- ret += " ";
- return ret;
-}
-
-CONV_FN(ColumnDef, col_def) {
- std::string ret;
- ret += ColumnToString(col_def.col());
- ret += " ";
- if (col_def.has_type_name()) {
- ret += TypeNameToString(col_def.type_name());
- ret += " ";
- }
-
- for (int i = 0; i < col_def.col_constraints_size(); i++) {
- ret += ColumnConstraintToString(col_def.col_constraints(i));
- ret += " ";
- }
-
- return ret;
-}
-
-CONV_FN(TableConstraintOpt1, opt1) {
- std::string ret;
- ret += EnumStrReplaceUnderscores(
- TableConstraintOpt1_ConstraintType_Name(opt1.constraint_type()));
- ret += "(";
- ret += IndexedColumnListToString(opt1.indexed_col_list());
- ret += ") ";
- ret += ConflictClauseToString(opt1.conf_clause());
-
- return ret;
-}
-
-CONV_FN(TableConstraintOpt2, opt2) {
- std::string ret("FOREIGN KEY (");
- ret += ColumnListToString(opt2.cols());
- ret += ") ";
-
- ret += ForeignKeyClauseToString(opt2.fkey_clause());
- return ret;
-}
-
-CONV_FN(TableConstraint, t_constr) {
- std::string ret;
- if (t_constr.has_name()) {
- ret += "CONSTRAINT ";
- ret += TableConstraintNameToString(t_constr.name());
- ret += " ";
- }
-
- if (t_constr.has_opt1()) {
- ret += TableConstraintOpt1ToString(t_constr.opt1());
- } else if (t_constr.has_check_expr()) {
- ret += "CHECK(";
- ret += ExprToString(t_constr.check_expr()); // TODO(mpdenton)
- ret += ") ";
- } else if (t_constr.has_opt2()) {
- ret += TableConstraintOpt2ToString(t_constr.opt2());
- } else {
- // default to no constraint
- ret += "CHECK(1)";
- }
-
- ret += " ";
- return ret;
-}
-
-CONV_FN(CreateTableOpt1, opt1) {
- std::string ret("(");
- ret += ColumnDefToString(opt1.col_def());
- for (int i = 0; i < opt1.extra_col_defs_size(); i++) {
- ret += ", ";
- ret += ColumnDefToString(opt1.extra_col_defs(i));
- }
- for (int i = 0; i < opt1.table_constraints_size(); i++) {
- ret += ", ";
- ret += TableConstraintToString(opt1.table_constraints(i));
- }
- ret += ") ";
-
- if (opt1.without_rowid())
- ret += "WITHOUT ROWID ";
-
- return ret;
-}
-
-CONV_FN(CreateTable, create_table) {
- RETURN_IF_DISABLED_QUERY(CreateTable);
-#if defined(FUZZ_FTS3)
- return ""; // Don't create normal tables in FTS3 fuzzing mode.
-#endif
- std::string ret("CREATE ");
- if (create_table.has_temp_modifier()) {
- ret += EnumStrReplaceUnderscores(
- TempModifier_Name(create_table.temp_modifier()))
- .erase(0, std::string("TM_").length());
- ret += " ";
- }
- ret += "TABLE ";
- if (create_table.if_not_exists())
- ret += "IF NOT EXISTS ";
-
- ret += ExprSchemaTableToString(create_table.schema_table());
- ret += " ";
-
- // TODO(mpdenton) need spaces at the end here???
- using TableCreationType = CreateTable::CreateTableOneofCase;
- switch (create_table.create_table_oneof_case()) {
- case TableCreationType::kOp1:
- ret += CreateTableOpt1ToString(create_table.op1());
- break;
- case TableCreationType::kAsSelectStmt:
- ret += SelectToString(create_table.as_select_stmt());
- break;
- default:
- ret += CreateTableOpt1ToString(create_table.op());
- break;
- }
-
- return ret; // TODO(mpdenton)
-}
-
-// ~~~~For INSERT and SELECT~~~~
-
-CONV_FN(CommonTableExpr, cte) {
- std::string ret;
- ret += TableToString(cte.table());
- if (cte.columns_size() > 0) {
- ret += "(";
- ret += ColumnToString(cte.columns(0));
- for (int i = 1; i < cte.columns_size(); i++) {
- ret += ", ";
- ret += ColumnToString(cte.columns(i));
- }
- ret += ")";
- }
- ret += " AS (";
- ret += SelectToString(cte.select());
- ret += ") ";
- return ret;
-}
-
-CONV_FN(WithStatement, ws) {
- std::string ret("WITH ");
- if (ws.recursive())
- ret += "RECURSIVE ";
- ret += CommonTableExprToString(ws.table_expr());
- ret += " ";
- for (int i = 0; i < ws.extra_table_exprs_size(); i++) {
- ret += CommonTableExprToString(ws.extra_table_exprs(i));
- ret += " ";
- }
- ret += " ";
- return ret;
-}
-
-// ~~~~INSERT~~~~
-
-// WARNING no space at end
-CONV_FN(ColumnComparison, cc) {
- std::string ret;
- ret += ExprSchemaTableColumnToString(cc.col());
- ret += BinaryOperatorToString(cc.op());
-#if defined(FUZZ_FTS3)
- if (cc.op() == BINOP_MATCH && cc.has_fmt()) {
- ret += FTS3MatchFormatToString(cc.fmt());
- return ret;
- }
-#endif
- ret += ExprToString(cc.expr());
- return ret;
-}
-
-// WARNING no space at end
-CONV_FN(ExprComparisonHighProbability, echp) {
- if (echp.has_cc()) {
- return ColumnComparisonToString(echp.cc());
- } else if (echp.has_expr()) {
- return ExprToString(echp.expr());
- } else {
- return "Col0 = 1"; // default
- }
-}
-
-CONV_FN(WhereStatement, ws) {
- return "WHERE " + ExprComparisonHighProbabilityToString(ws.expr()) + " ";
-}
-
-#ifndef SQLITE_OMIT_UPSERT
-CONV_FN(UpsertClausePart1, uc1) {
- std::string ret;
- ret += "(";
- ret += IndexedColumnListToString(uc1.icol_list());
- ret += ") ";
- if (uc1.has_where_stmt()) {
- ret += WhereStatementToString(uc1.where_stmt());
- ret += " ";
- }
- return ret;
-}
-#endif
-
-// WARNING no space at end
-CONV_FN(ColEqualsExpr, cee) {
- std::string ret;
- if (cee.has_col()) {
- ret += ColumnToString(cee.col());
- } else if (cee.has_col_list()) {
- ret += ColumnListToString(cee.col_list());
- } else {
- ret += "Col0"; // default
- }
- ret += " = ";
- ret += ExprToString(cee.expr());
- return ret;
-}
-
-CONV_FN(UpsertClausePart2, uc2) {
- std::string ret("SET ");
- ret += ColEqualsExprToString(uc2.cee());
- for (int i = 0; i < uc2.extra_cees_size(); i++) {
- ret += ", ";
- ret += ColEqualsExprToString(uc2.extra_cees(i));
- }
- if (uc2.has_where_stmt()) {
- ret += " ";
- ret += WhereStatementToString(uc2.where_stmt());
- }
- ret += " ";
- return ret;
-}
-
-CONV_FN(UpsertClause, uc) {
-#ifndef SQLITE_OMIT_UPSERT
- std::string ret("ON CONFLICT ");
- if (uc.has_uclause_p1()) {
- ret += UpsertClausePart1ToString(uc.uclause_p1());
- }
- ret += "DO ";
- if (uc.has_uclause_p2()) {
- ret += "UPDATE ";
- ret += UpsertClausePart2ToString(uc.uclause_p2());
- } else {
- ret += "NOTHING ";
- }
- return ret;
-#else
- return ""; // fine to return empty string here
-#endif
-}
-
-CONV_FN(ValuesStatement, values) {
- std::string ret("VALUES (");
- ret += ExprListToString(values.expr_list());
- ret += ")";
- for (int i = 0; i < values.extra_expr_lists_size(); i++) {
- ret += ", (";
- ret += ExprListToString(values.extra_expr_lists(i));
- ret += ")";
- }
- ret += " ";
- return ret;
-}
-
-CONV_FN(Insert, insert) {
- RETURN_IF_DISABLED_QUERY(Insert);
- std::string ret;
- if (insert.has_with()) {
- ret += WithStatementToString(insert.with());
- ret += " ";
- }
-
- ret +=
- EnumStrReplaceUnderscores(Insert_InsertType_Name(insert.insert_type()));
- ret += " INTO ";
- ret += SchemaTableAsAliasToString(insert.staa());
-
- if (insert.has_col_list()) {
- ret += "(";
- ret += ColumnListToString(insert.col_list());
- ret += ") ";
- }
-
- // oneof
- if (insert.has_values()) {
- ret += ValuesStatementToString(insert.values());
- ret += " ";
- } else if (insert.has_select()) {
- ret += SelectToString(insert.select());
- ret += " ";
- } else {
- ret += "DEFAULT VALUES ";
- }
-
- if (insert.has_upsert_clause()) {
- ret += UpsertClauseToString(insert.upsert_clause());
- ret += " ";
- }
- return ret;
-}
-
-// ~~~~DELETE~~~~
-
-CONV_FN(QualifiedTableName, qtn) {
- std::string ret;
- ret += SchemaTableAsAliasToString(qtn.staa());
- ret += " ";
- if (qtn.indexed()) {
- if (qtn.not_indexed()) {
- ret += "NOT INDEXED ";
- } else {
- ret += "INDEXED BY ";
- ret += IndexToString(qtn.indexed_by());
- ret += " ";
- }
- }
- return ret;
-}
-
-CONV_FN(Delete, delete_) {
- RETURN_IF_DISABLED_QUERY(Delete);
- std::string ret;
- if (delete_.has_with()) {
- ret += WithStatementToString(delete_.with());
- ret += " ";
- }
- ret += "DELETE FROM ";
- ret += QualifiedTableNameToString(delete_.qtn());
- if (delete_.has_where()) {
- ret += WhereStatementToString(delete_.where());
- }
- ret += " ";
- return ret;
-}
-
-// ~~~~UPDATE~~~~
-// WARNING no space at end
-CONV_FN(Update, update) {
- RETURN_IF_DISABLED_QUERY(Update);
- std::string ret;
- if (update.has_with()) {
- ret += WithStatementToString(update.with());
- ret += " ";
- }
- ret += "UPDATE ";
- if (update.has_update_type()) {
- ret +=
- EnumStrReplaceUnderscores(Update_UpdateType_Name(update.update_type()));
- ret += " ";
- }
- ret += QualifiedTableNameToString(update.qtn());
- ret += " ";
- ret += UpsertClausePart2ToString(update.ucp2());
- return ret;
-}
-// TODO(mpdenton) restrictions on UPDATEs in CREATE TRIGGER????
-
-// ~~~~SELECT~~~~
-
-CONV_FN(ExprColAlias, eca) {
- std::string ret;
- ret += ExprToString(eca.expr());
- ret += " ";
- if (eca.has_col_alias()) {
- if (eca.as()) {
- ret += "AS ";
- }
- ret += ColumnToString(eca.col_alias());
- ret += " ";
- }
- return ret;
-}
-
-// WARNING no space at end
-CONV_FN(ResultColumn, rc) {
- std::string ret;
- // oneof
- if (rc.has_col()) {
- return ColumnToString(rc.col());
- } else if (rc.has_eca()) {
- return ExprColAliasToString(rc.eca());
- } else if (rc.has_table_star()) {
- return TableToString(rc.table_star()) + ".*";
- } else if (rc.has_fts3_fn()) {
-#if defined(FUZZ_FTS3)
- return FTS3AuxiliaryFnToString(rc.fts3_fn());
-#else
- return "*";
-#endif
- } else {
- return "*";
- }
-}
-
-CONV_FN(AsTableAlias, ata) {
- std::string ret;
- if (ata.as()) {
- ret += "AS ";
- }
- ret += TableToString(ata.table_alias());
- ret += " ";
- return ret;
-}
-
-// WARNING no space at end
-CONV_FN(JoinOperator, jo) {
- if (jo.comma())
- return ",";
-
- std::string ret;
- if (jo.natural())
- ret += "NATURAL ";
-
- if (jo.join_type() != JoinOperator::NONE) {
- ret +=
- EnumStrReplaceUnderscores(JoinOperator_JoinType_Name(jo.join_type()));
- ret += " ";
- }
- ret += "JOIN ";
- return ret;
-}
-
-CONV_FN(JoinConstraint, jc) {
- // oneof
- if (jc.has_on_expr()) {
- return "ON " + ExprToString(jc.on_expr()) + " ";
- } else if (jc.has_using_expr()) {
- std::string ret("(");
- ret += ColumnListToString(jc.using_expr().col_list());
- ret += ") ";
- return ret;
- }
- return " ";
-}
-
-CONV_FN(JoinClauseCore, jcc) {
- std::string ret;
- ret += JoinOperatorToString(jcc.join_op());
- ret += " ";
- ret += TableOrSubqueryToString(jcc.tos());
- ret += " ";
- ret += JoinConstraintToString(jcc.join_constraint());
- ret += " ";
- return ret;
-}
-
-CONV_FN(JoinClause, jc) {
- std::string ret;
- ret += TableOrSubqueryToString(jc.tos());
- ret += " ";
- for (int i = 0; i < jc.clauses_size(); i++) {
- ret += JoinClauseCoreToString(jc.clauses(i));
- }
- ret += " ";
- return ret;
-}
-
-// TODO(mpdenton) ExprIn needs it schematablefn!!!!!
-
-CONV_FN(ExprSchemaTableFn, estf) {
- std::string ret;
- const TableFn& tfn = estf.table_fn();
- // oneof for pragma fns
- if (tfn.has_foreign_key_list()) {
- ret += "pragma_foreign_key_list(\'";
- ret += TableToString(tfn.foreign_key_list());
- ret += "\') ";
- } else if (tfn.has_index_info()) {
- ret += "pragma_index_info(\'";
- ret += IndexToString(tfn.index_info());
- ret += "\') ";
- } else if (tfn.has_index_list()) {
- ret += "pragma_index_list(\'";
- ret += TableToString(tfn.index_list());
- ret += "\') ";
- } else if (tfn.has_index_xinfo()) {
- ret += "pragma_index_xinfo(\'";
- ret += IndexToString(tfn.index_xinfo());
- ret += "\') ";
- } else if (tfn.has_integrity_check()) {
- ret += "pragma_integrity_check(\'";
- ret += std::to_string(tfn.integrity_check());
- ret += "\') ";
- } else if (tfn.has_optimize()) {
- ret += "pragma_optimize(\'";
- ret += std::to_string(tfn.optimize());
- ret += "\') ";
- } else if (tfn.has_quick_check()) {
- ret += "pragma_quick_check(\'";
- ret += std::to_string(tfn.quick_check());
- ret += "\') ";
- } else if (tfn.has_table_info()) {
- ret += "pragma_table_info(\'";
- ret += TableToString(tfn.table_info());
- ret += "\') ";
- } else if (tfn.has_table_xinfo()) {
- ret += "pragma_table_xinfo(\'";
- ret += TableToString(tfn.table_xinfo());
- ret += "\') ";
- } else {
- ret += StrToLower(PragmaFnZeroArgOneResult_Name(tfn.no_arg_one_result()))
- .erase(0, std::string("PFN_ZO_").length());
- ret += "() ";
- }
- return ret;
-}
-
-CONV_FN(TableOrSubqueryOption2, toso2) {
- std::string ret;
- ret += ExprSchemaTableFnToString(toso2.schema_table_fn());
- ret += " ";
- if (toso2.has_as_table_alias()) {
- ret += AsTableAliasToString(toso2.as_table_alias());
- }
- return ret;
-}
-
-CONV_FN(TableOrSubqueryOption3, tos3) {
- std::string ret;
- if (tos3.tos_list_size() > 0) {
- ret += TableOrSubqueryToString(tos3.tos_list(0));
- for (int i = 1; i < tos3.tos_list_size(); i++) {
- ret += ", ";
- ret += TableOrSubqueryToString(tos3.tos_list(i));
- }
- } else {
- ret += JoinClauseToString(tos3.join_clause());
- }
- return ret;
-}
-
-CONV_FN(TableOrSubqueryOption4, tos4) {
- std::string ret("(");
- ret += SelectToString(tos4.select());
- ret += ") ";
- if (tos4.has_as_table_alias()) {
- ret += AsTableAliasToString(tos4.as_table_alias());
- ret += " ";
- }
- return ret;
-}
-
-CONV_FN(TableOrSubquery, tos) {
- // oneof
- if (tos.has_qtn()) {
- return QualifiedTableNameToString(tos.qtn()) + " ";
- } else if (tos.has_toso2()) {
- return TableOrSubqueryOption2ToString(tos.toso2()) + " ";
- } else if (tos.has_toso3()) {
- return "(" + TableOrSubqueryOption3ToString(tos.toso3()) + ") ";
- } else if (tos.has_toso4()) {
- return TableOrSubqueryOption4ToString(tos.toso4()) + " ";
- } else {
- return ExprSchemaTableToString(tos.schema_table_expr()) + " ";
- }
-}
-
-CONV_FN(FromStatement, fs) {
- return "FROM " + TableOrSubqueryOption3ToString(fs.tos3());
-}
-
-CONV_FN(GroupByStatement, gbs) {
- std::string ret("GROUP BY ");
- ret += ExprListToString(gbs.exprs());
- ret += " ";
- if (gbs.has_having_expr()) {
- ret += "HAVING ";
- ret += ExprToString(gbs.having_expr());
- ret += " ";
- }
- return ret;
-}
-
-CONV_FN(WindowStatement, ws) {
-#if !defined(SQLITE_OMIT_WINDOWFUNC)
- return "";
-#else
- return "";
-#endif
-}
-
-CONV_FN(SelectStatementCore, ssc) {
- std::string ret;
- ret += EnumStrReplaceUnderscores(
- SelectStatementCore_SelectOrDistinct_Name(ssc.s_or_d()));
- ret += " ";
- if (ssc.result_columns_size() == 0) {
- ret += "* ";
- } else {
- ret += ResultColumnToString(ssc.result_columns(0));
- for (int i = 1; i < ssc.result_columns_size(); i++) {
- ret += ", ";
- ret += ResultColumnToString(ssc.result_columns(i));
- }
- ret += " ";
- }
- if (ssc.has_from()) {
- ret += FromStatementToString(ssc.from());
- ret += " ";
- }
- if (ssc.has_where()) {
- ret += WhereStatementToString(ssc.where());
- ret += " ";
- }
- if (ssc.has_groupby()) {
- ret += GroupByStatementToString(ssc.groupby());
- ret += " ";
- }
- if (ssc.has_window()) {
- ret += WindowStatementToString(ssc.window());
- ret += " ";
- }
- return ret;
-}
-
-CONV_FN(SelectSubStatement, sss) {
- // oneof
- if (sss.has_select_core()) {
- return SelectStatementCoreToString(sss.select_core());
- } else if (sss.has_values()) {
- return ValuesStatementToString(sss.values());
- } else {
- return ValuesStatementToString(sss.values_fallback());
- }
-}
-
-CONV_FN(ExprOrderingTerm, eot) {
- std::string ret = ExprToString(eot.expr());
- ret += " ";
- if (eot.has_collate_type()) {
- ret += "COLLATE ";
- ret += CollateTypeToString(eot.collate_type());
- ret += " ";
- }
- ret += AscDescToString(eot.asc_desc());
- return ret;
-}
-
-CONV_FN(OrderByStatement, obs) {
- std::string ret("ORDER BY ");
- ret += ExprOrderingTermToString(obs.ord_term());
- for (int i = 0; i < obs.extra_ord_terms_size(); i++) {
- ret += ", ";
- ret += ExprOrderingTermToString(obs.extra_ord_terms(i));
- }
- ret += " ";
- return ret;
-}
-
-CONV_FN(LimitStatement, ls) {
- std::string ret("LIMIT ");
- ret += ExprToString(ls.limit_expr());
- ret += " ";
- if (ls.has_second_expr()) {
- if (ls.offset()) {
- ret += "OFFSET ";
- } else {
- ret += ", ";
- }
- ret += ExprToString(ls.second_expr());
- ret += " ";
- }
- return ret;
-}
-
-CONV_FN(ExtraSelectSubStatement, esss) {
- std::string ret, enum1;
- enum1 = CompoundOperator_Name(esss.compound_op());
- // erase prefix
- enum1.erase(0, std::string("CO_").length());
- ret += EnumStrReplaceUnderscores(enum1);
- ret += " ";
- ret += SelectSubStatementToString(esss.select_substatement());
- return ret;
-}
-
-CONV_FN(Select, select) {
- RETURN_IF_DISABLED_QUERY(Select);
- std::string ret;
- if (select.has_with()) {
- ret += WithStatementToString(select.with());
- ret += " ";
- }
- ret += SelectStatementCoreToString(select.select_core());
- for (int i = 0; i < select.extra_select_substatements_size(); i++) {
- ret +=
- ExtraSelectSubStatementToString(select.extra_select_substatements(i));
- ret += " ";
- }
- if (select.has_orderby()) {
- ret += OrderByStatementToString(select.orderby());
- ret += " ";
- }
- if (select.has_limit()) {
- ret += LimitStatementToString(select.limit());
- }
- return ret;
-}
-
-// ~~~~FTS3~~~~
-
-// CORPUS currently relying on normal SELECTs to generate good compound
-// queries for FTS, like AND, OR, and NOT. Generate a corpus entry with a lot of
-// creative FTS queries.
-
-CONV_FN(FTS3Table, ft) {
- // std::string ret("FTS3Table");
- std::string ret(
- "Table"); // for now, use the same naming scheme as normal tables.
- ret += std::to_string(ft.table() % kMaxFTS3TableNumber);
- return ret;
-}
-
-CONV_FN(FTS3MatchToken, fmt) {
- std::string ret;
- if (fmt.has_col()) {
- ret += ColumnToString(fmt.col());
- ret += ":";
- }
- if (fmt.negate()) {
- ret += "-";
- }
- if (fmt.token().length() == 0)
- ret += "a";
- else
- ret += ConvertToSqlString(
- fmt.token()); // TODO(mpdenton) good enough? Need something better????
- if (fmt.prefix())
- ret += "*";
- return ret;
-}
-
-CONV_FN(FTS3PhraseQuery, fpq) {
- std::string ret("\"");
- ret += FTS3MatchTokenToString(fpq.mt());
- for (int i = 0; i < fpq.extra_mts_size(); i++) {
- ret += " ";
- ret += FTS3MatchTokenToString(fpq.extra_mts(i));
- }
- ret += "\"";
- return ret;
-}
-
-CONV_FN(FTS3MatchFormatCore, fmfc) {
- // oneof
- if (fmfc.has_pq()) {
- return FTS3PhraseQueryToString(fmfc.pq());
- } else if (fmfc.has_nq()) {
- return FTS3NearQueryToString(fmfc.nq());
- } else {
- return FTS3MatchTokenToString(fmfc.mt_fallback());
- }
-}
-
-CONV_FN(FTS3NearQuery, fnq) {
- std::string ret = FTS3MatchFormatCoreToString(fnq.format_core1());
- ret += " NEAR";
- if (fnq.has_num_tokens_near()) {
- ret += "/";
- ret += std::to_string(fnq.num_tokens_near());
- }
- ret += " ";
- ret += FTS3MatchFormatCoreToString(fnq.format_core2());
- return ret;
-}
-
-CONV_FN(FTS3CompoundAndCore, fcac) {
- std::string ret(" ");
- ret += FTS3CompoundAndCore_CompoundOp_Name(fcac.op());
- ret += " ";
- ret += FTS3MatchFormatCoreToString(fcac.core());
- return ret;
-}
-
-CONV_FN(FTS3MatchCompoundFormat, fmcf) {
- std::string ret = FTS3MatchFormatCoreToString(fmcf.core());
- for (int i = 0; i < fmcf.compound_and_cores_size(); i++) {
- ret += FTS3CompoundAndCoreToString(fmcf.compound_and_cores(i));
- }
- return ret;
-}
-
-CONV_FN(FTS3MatchFormat, fmf) {
- std::string ret("\'");
- if (fmf.ft_size() > 0) {
- ret += FTS3MatchCompoundFormatToString(fmf.ft(0));
- }
- for (int i = 1; i < fmf.ft_size(); i++) {
- ret += " ";
- ret += FTS3MatchCompoundFormatToString(fmf.ft(i));
- }
- ret += "\'";
- return ret;
-}
-
-CONV_FN(FTS3SpecialCommand, fsc) {
- RETURN_IF_DISABLED_QUERY(FTS3SpecialCommand);
- std::string ret("INSERT INTO ");
- ret += FTS3TableToString(fsc.table());
- ret += "(";
- ret += FTS3TableToString(fsc.table());
- ret += ") VALUES(\'";
- switch (fsc.command()) {
- case FTS3SpecialCommand::OPTIMIZE:
- ret += "optimize";
- break;
- case FTS3SpecialCommand::REBUILD:
- ret += "rebuild";
- break;
- case FTS3SpecialCommand::INTEGRITY_CHECK:
- ret += "integrity-check";
- break;
- case FTS3SpecialCommand::MERGE:
- ret += "merge=";
- ret += std::to_string(fsc.val1());
- ret += ",";
- ret += std::to_string(fsc.val2());
- break;
- case FTS3SpecialCommand::AUTOMERGE:
- ret += "automerge=";
- ret += std::to_string(fsc.val1() % 16);
- break;
- }
- ret += "\')";
- return ret;
-}
-
-// WARNING no space at end
-CONV_FN(FTS3SelectMatch, fsm) {
- RETURN_IF_DISABLED_QUERY(FTS3SelectMatch);
- std::string ret("SELECT * FROM ");
- ret += FTS3TableToString(fsm.table());
- ret += " WHERE ";
- ret += ColumnToString(fsm.col());
- ret += " MATCH ";
- ret += FTS3MatchFormatToString(fsm.match_pattern());
- return ret;
-}
-
-CONV_FN(FTS3SpecificQuery, fsq) {
- RETURN_IF_DISABLED_QUERY(FTS3SpecificQuery);
-#if defined(FUZZ_FTS3)
- // oneof
- if (fsq.has_command()) {
- return FTS3SpecialCommandToString(fsq.command());
- } else if (fsq.has_select()) {
- return FTS3SelectMatchToString(fsq.select());
- } else {
- return "";
- }
-
-#else
- return "";
-#endif
-}
-
-CONV_FN(ICULocale, il) {
- std::string ret;
- std::string lc = IsoLangCode_Name(il.iso_lang_code());
- lc.erase(0, std::string("ISO_LANG_CODE_").length());
- ret += lc;
- ret += "_";
- // extract country code from integer
- ret += (char)((il.country_code() & 0xFF) % 26) + 'A';
- ret += (char)(((il.country_code() & 0xFF00) >> 8) % 26) + 'A';
- return ret;
-}
-
-CONV_FN(CreateFTS3Table, cft) {
- RETURN_IF_DISABLED_QUERY(CreateFTS3Table);
- std::string ret("CREATE VIRTUAL TABLE ");
- if (cft.if_not_exists())
- ret += "IF NOT EXISTS ";
- if (cft.has_schema()) {
- ret += SchemaToString(cft.schema());
- ret += ".";
- }
- ret += FTS3TableToString(cft.table());
- ret += " USING fts3(";
- // TODO(mpdenton) not using schema here, should I???
- if (cft.has_col_list()) {
- ret += ColumnListToString(cft.col_list());
- if (cft.has_tokenizer_type())
- ret += ", ";
- }
- if (cft.has_tokenizer_type()) {
- ret += "tokenize=";
- std::string tt = TokenizerType_Name(cft.tokenizer_type());
- tt.erase(0, std::string("TT_").length());
- tt = StrToLower(tt);
-#if defined(SQLITE_DISABLE_FTS3_UNICODE)
- if (tt == "unicode61")
- tt = "porter";
-#endif
- ret += tt;
- // now generate locales for ICU
- if (cft.tokenizer_type() == TokenizerType::TT_ICU) {
- ret += " ";
- ret += ICULocaleToString(cft.locale());
- } else if (cft.tokenizer_type() == TokenizerType::TT_UNICODE61) {
- // Chrome does not actually enable this option. FIXME in the future.
- }
- }
- ret += ")";
- return ret;
-}
-
-// WARNING no space at end
-CONV_FN(FTS3OffsetsFn, fof) {
- return "offsets(" + FTS3TableToString(fof.table()) + ")";
-}
-
-// WARNING no space at end
-CONV_FN(FTS3SnippetsFn, fsf) {
- std::string ret("snippets(");
- ret += FTS3TableToString(fsf.table());
- // Now (possibly) emit the five optional arguments.
- int num_args = (int)fsf.num_optional_args();
- if (num_args >= 1) {
- ret += ", \'";
- ret += ConvertToSqlString(fsf.start_match());
- ret += "\'";
- }
- if (num_args >= 2) {
- ret += ", \'";
- ret += ConvertToSqlString(fsf.end_match());
- ret += "\'";
- }
- if (num_args >= 3) {
- ret += ", \'";
- ret += ConvertToSqlString(fsf.ellipses());
- ret += "\'";
- }
- if (num_args >= 4) {
- ret += ", ";
- if (fsf.has_col_number()) {
- ret += std::to_string(fsf.col_number() % kMaxColumnNumber);
- } else {
- ret += "-1";
- }
- }
- if (num_args >= 5) {
- ret += ", ";
- ret +=
- std::to_string((fsf.num_tokens() % 129) - 64); // clamp into [-64, 64]
- }
- ret += ")";
- return ret;
-}
-
-// WARNING no space at end
-CONV_FN(FTS3MatchInfoFn, fmi) {
- constexpr static char matchinfo_chars[] = {
- 'p', 'c', 's', 'x', 'y', 'b',
- // 'n', 'a', 'l', // These characters only available for FTS4.
- };
- std::string ret("matchinfo(");
- ret += FTS3TableToString(fmi.table());
- if (fmi.chars_size() > 0) {
- ret += ", \'";
- for (int i = 0; i < fmi.chars_size(); i++) {
- ret += matchinfo_chars[fmi.chars(i) % sizeof(matchinfo_chars)];
- }
- ret += "\'";
- }
- ret += ")";
- return ret;
-}
-
-// WARNING no space at end
-CONV_FN(FTS3AuxiliaryFn, faf) {
- if (faf.has_snippets()) {
- return FTS3SnippetsFnToString(faf.snippets());
- } else if (faf.has_matchinfo()) {
- return FTS3MatchInfoFnToString(faf.matchinfo());
- } else {
- return FTS3OffsetsFnToString(faf.offsets_fallback());
- }
-}
-
-CONV_FN(FTS3HiddenTable, fht) {
- std::string tab = FTS3HiddenTable_HiddenTableVal_Name(fht.htv());
- tab = StrToLower(tab);
- return FTS3TableToString(fht.table()) + "_" + tab;
-}
-
-CONV_FN(FTS3HiddenTableColumn, fhtc) {
- std::string tab = FTS3HiddenTableColumn_Name(fhtc);
- tab = tab.erase(0, std::string("FTS3_HT_").length());
- tab = StrToLower(tab);
- return tab;
-}
-
-CONV_FN(FTS3HiddenTableInsert, fi) {
- RETURN_IF_DISABLED_QUERY(FTS3HiddenTableInsert);
- std::string ret("INSERT INTO ");
- ret += FTS3HiddenTableToString(fi.fht());
- if (fi.col_vals_size() == 0) {
- ret += " DEFAULT VALUES";
- return ret;
- }
- ret += "(";
- ret += FTS3HiddenTableColumnToString(fi.col_vals(0).col());
- for (int i = 1; i < fi.col_vals_size(); i++) {
- ret += ", ";
- ret += FTS3HiddenTableColumnToString(fi.col_vals(i).col());
- }
- ret += ") VALUES(";
- ret += ExprToString(fi.col_vals(0).expr());
- for (int i = 0; i < fi.col_vals_size(); i++) {
- ret += ", ";
- ret += ExprToString(fi.col_vals(i).expr());
- }
- ret += ")";
- return ret;
-}
-
-CONV_FN(FTS3HiddenTableUpdate, fu) {
- RETURN_IF_DISABLED_QUERY(FTS3HiddenTableUpdate);
- std::string ret("UPDATE ");
- ret += FTS3HiddenTableToString(fu.fht());
- ret += " ";
- if (fu.col_vals_size() == 0) {
- ret += "start_block = 0";
- return ret;
- }
- ret += "SET ";
- ret += FTS3HiddenTableColumnToString(fu.col_vals(0).col());
- ret += " = ";
- ret += ExprToString(fu.col_vals(0).expr());
- for (int i = 1; i < fu.col_vals_size(); i++) {
- ret += ", ";
- ret += FTS3HiddenTableColumnToString(fu.col_vals(i).col());
- ret += " = ";
- ret += ExprToString(fu.col_vals(i).expr());
- }
- if (fu.has_col_where()) {
- ret += " WHERE ";
- ret += FTS3HiddenTableColumnToString(fu.col_where());
- ret += BinaryOperatorToString(fu.bin_op());
- ret += ExprToString(fu.comp_expr());
- }
- return ret;
-}
-
-CONV_FN(FTS3HiddenTableDelete, fd) {
- RETURN_IF_DISABLED_QUERY(FTS3HiddenTableDelete);
- std::string ret("DELETE FROM ");
- ret += FTS3HiddenTableToString(fd.fht());
- if (fd.has_col_where()) {
- ret += " WHERE ";
- ret += FTS3HiddenTableColumnToString(fd.col_where());
- ret += BinaryOperatorToString(fd.bin_op());
- ret += ExprToString(fd.comp_expr());
- }
- return ret;
-}
-
-// ~~~~TRANSACTIONS/SAVEPOINTS
-CONV_FN(BeginTransaction, bt) {
- RETURN_IF_DISABLED_QUERY(BeginTransaction);
- std::string ret("BEGIN ");
- if (bt.has_type()) {
- ret += BeginTransaction_TransactionType_Name(bt.type());
- ret += " ";
- }
- ret += "TRANSACTION";
- return ret;
-}
-
-CONV_FN(CommitTransaction, ct) {
- RETURN_IF_DISABLED_QUERY(CommitTransaction);
- return EnumStrReplaceUnderscores(
- CommitTransaction_CommitText_Name(ct.text()));
-}
-
-CONV_FN(RollbackStatement, rt) {
- RETURN_IF_DISABLED_QUERY(RollbackStatement);
-#if !defined(FUZZ_OMIT_SAVEPOINT)
- if (rt.has_save_point()) {
- return "ROLLBACK TO SAVEPOINT " + SavePointToString(rt.save_point());
- }
-#endif
- return "ROLLBACK TRANSACTION";
-}
-
-#if !defined(FUZZ_OMIT_SAVEPOINT)
-CONV_FN(CreateSavePoint, csp) {
- RETURN_IF_DISABLED_QUERY(CreateSavePoint);
- return "SAVEPOINT " + SavePointToString(csp.save_point());
-}
-
-CONV_FN(ReleaseSavePoint, rsp) {
- RETURN_IF_DISABLED_QUERY(ReleaseSavePoint);
- return "RELEASE SAVEPOINT " + SavePointToString(rsp.save_point());
-}
-#endif
-
-CONV_FN(Analyze, a) {
- RETURN_IF_DISABLED_QUERY(Analyze);
- std::string ret("ANALYZE");
- if (a.has_schema_name()) {
- ret += " ";
- ret += SchemaToString(a.schema_name());
- if (a.has_table_name()) {
- ret += ".";
- ret += TableToString(a.table_name());
- } else if (a.has_index_name()) {
- ret += ".";
- ret += IndexToString(a.index_name());
- }
- } else if (a.has_table_name()) {
- ret += " ";
- ret += TableToString(a.table_name());
- } else if (a.has_index_name()) {
- ret += " ";
- ret += IndexToString(a.index_name());
- }
-
- return ret;
-}
-
-// ~~~~VACUUM~~~~
-CONV_FN(Vacuum, v) {
- RETURN_IF_DISABLED_QUERY(Vacuum);
- std::string ret("VACUUM");
- if (v.has_schema()) {
- ret += " ";
- ret += SchemaToString(v.schema());
- }
- return ret;
-}
-
-// ~~~~PRAGMA~~~~
-CONV_FN(Pragma, p) {
- RETURN_IF_DISABLED_QUERY(Pragma);
-#if defined(FUZZ_OMIT_PRAGMA)
- return "";
-#else
- constexpr static const char* locking_modes[] = {"NORMAL", "EXCLUSIVE"};
- constexpr static const char* journal_modes[] = {
- "DELETE", "TRUNCATE", "PERSIST", "MEMORY", "WAL", "OFF"};
-
- Table table;
- std::string ret("PRAGMA ");
- if (p.has_schema()) {
- ret += SchemaToString(p.schema());
- ret += ".";
- }
- ret += StripTrailingUnderscores(
- StrToLower(Pragma_PragmaCommand_Name(p.command())));
- switch (p.command()) {
- case Pragma::AUTO_VACUUM:
- ret += " = ";
- ret += std::to_string((uint32_t)p.arg1() % 3);
- break;
- case Pragma::WRITEABLE_SCHEMA:
- ret += " = ";
- ret += std::to_string((uint32_t)p.arg1() % 2);
- break;
- case Pragma::LOCKING_MODE:
- ret += " = ";
- ret += locking_modes[(uint32_t)p.arg1() % 2];
- break;
- case Pragma::TEMP_STORE:
- ret += " = ";
- ret += std::to_string((uint32_t)p.arg1() % 3);
- break;
- case Pragma::PAGE_SIZE_:
- ret += " = ";
- ret += std::to_string(p.arg1());
- break;
- case Pragma::TABLE_INFO:
- ret += "(\'";
- table.set_table((uint32_t)p.arg1());
- ret += TableToString(table);
- ret += "\')";
- break;
- case Pragma::JOURNAL_MODE:
- ret += " = ";
- ret += journal_modes[(uint32_t)p.arg1() % 6];
- break;
- case Pragma::MMAP_SIZE:
- ret += " = ";
- ret += std::to_string(p.arg1());
- break;
- }
- return ret;
-#endif
-}
-
-// ~~~~CREATE INDEX~~~~
-CONV_FN(CreateIndex, ci) {
- RETURN_IF_DISABLED_QUERY(CreateIndex);
- std::string ret("CREATE ");
- if (ci.unique())
- ret += "UNIQUE ";
- ret += "INDEX ";
- if (ci.if_not_exists())
- ret += "IF NOT EXISTS ";
- if (ci.has_schema()) {
- ret += SchemaToString(ci.schema());
- ret += ".";
- }
- ret += IndexToString(ci.index());
- ret += " ON ";
- ret += TableToString(ci.table());
- ret += "(";
- ret += IndexedColumnListToString(ci.icol_list());
- ret += ")";
- if (ci.has_where()) {
- ret += " ";
- ret += WhereStatementToString(ci.where());
- }
- return ret;
-}
-
-// ~~~~CREATE VIEW~~~~
-CONV_FN(CreateView, cv) {
- RETURN_IF_DISABLED_QUERY(CreateView);
- std::string ret("CREATE ");
- if (cv.has_temp_modifier()) {
- ret += EnumStrReplaceUnderscores(TempModifier_Name(cv.temp_modifier()))
- .erase(0, std::string("TM_").length());
- ret += " ";
- }
- ret += "VIEW ";
- if (cv.if_not_exists())
- ret += "IF NOT EXISTS ";
-
- if (cv.has_schema()) {
- ret += SchemaToString(cv.schema());
- ret += ".";
- }
- ret += ViewToString(cv.view());
- ret += " ";
- if (cv.has_col_list()) {
- ret += "(";
- ret += ColumnListToString(cv.col_list());
- ret += ") ";
- }
- ret += SelectToString(cv.select());
- return ret;
-}
-
-// ~~~~CREATE TRIGGER~~~~
-
-CONV_FN(TypicalQuery, tq) {
- // oneof
- if (tq.has_update())
- return UpdateToString(tq.update());
- else if (tq.has_insert())
- return InsertToString(tq.insert());
- else if (tq.has_select())
- return SelectToString(tq.select());
- else
- return DeleteToString(tq.delete_fallback());
-}
-
-// WARNING no space at end
-CONV_FN(CreateTrigger, ct) {
- RETURN_IF_DISABLED_QUERY(CreateTrigger);
- std::string ret("CREATE ");
- if (ct.has_temp_modifier()) {
- ret += EnumStrReplaceUnderscores(TempModifier_Name(ct.temp_modifier()))
- .erase(0, std::string("TM_").length());
- ret += " ";
- }
- ret += "TRIGGER ";
- if (ct.if_not_exists())
- ret += "IF NOT EXISTS ";
-
- if (ct.has_schema()) {
- ret += SchemaToString(ct.schema());
- ret += " ";
- }
-
- ret += TriggerToString(ct.trigger());
- ret += " ";
- if (ct.has_trigger_type()) {
- ret += EnumStrReplaceUnderscores(
- CreateTrigger_TriggerType_Name(ct.trigger_type()));
- ret += " ";
- }
- ret += CreateTrigger_TriggerInstr_Name(ct.trigger_instr());
- ret += " ";
- if (ct.trigger_instr() == CreateTrigger::UPDATE) {
- ret += "OF ";
- ret += ColumnListToString(ct.col_list());
- ret += " ";
- }
- ret += "ON ";
- ret += TableToString(ct.table());
- ret += " ";
- if (ct.for_each_row())
- ret += "FOR EACH ROW ";
-
- if (ct.has_when()) {
- ret += "WHEN ";
- ret += ExprComparisonHighProbabilityToString(ct.when());
- ret += " ";
- }
-
- ret += "BEGIN ";
- ret += TypicalQueryToString(ct.tq());
- ret += "; ";
- for (int i = 0; i < ct.extra_tqs_size(); i++) {
- ret += TypicalQueryToString(ct.extra_tqs(i));
- ret += "; ";
- }
- ret += "END";
- return ret;
-}
-
-// ~~~~REINDEX~~~~
-CONV_FN(ReIndex, ri) {
- RETURN_IF_DISABLED_QUERY(ReIndex);
-// Chrome doesn't use REINDEX
-#if !defined(SQLITE_OMIT_REINDEX)
- if (ri.empty())
- return "REINDEX";
- std::string ret("REINDEX ");
- if (ri.has_collate_type()) {
- ret += CollateTypeToString(ri.collate_type());
- return ret;
- }
- if (ri.has_schema()) {
- ret += SchemaToString(ri.schema());
- ret += ".";
- }
- if (ri.has_table())
- ret += TableToString(ri.table());
- else
- ret += IndexToString(ri.index());
-
- return ret;
-#else
- return "";
-#endif
-}
-
-CONV_FN(Drop, d) {
- RETURN_IF_DISABLED_QUERY(Drop);
- std::string ret("DROP ");
- std::string if_exists("");
- std::string schema("");
- if (d.if_exists())
- if_exists = "IF EXISTS ";
- if (d.has_schema()) {
- schema = SchemaToString(d.schema());
- schema += " ";
- }
- // oneof
- if (d.has_index()) {
- ret += "INDEX ";
- ret += if_exists;
- ret += schema;
- ret += IndexToString(d.index());
- } else if (d.has_table()) {
- ret += "TABLE ";
- ret += if_exists;
- ret += schema;
- ret += TableToString(d.table());
- } else if (d.has_trigger()) {
- ret += "TRIGGER ";
- ret += if_exists;
- ret += schema;
- ret += TriggerToString(d.trigger());
- } else {
- ret += "VIEW ";
- ret += if_exists;
- ret += schema;
- ret += ViewToString(d.view_fallback());
- }
- return ret;
-}
-
-// ~~~~ALTER TABLE~~~~
-CONV_FN(AlterTable, at) {
- RETURN_IF_DISABLED_QUERY(AlterTable);
- std::string ret("ALTER TABLE ");
- ret += ExprSchemaTableToString(at.schema_table());
- ret += " ";
- if (at.has_col()) {
- ret += "RENAME ";
- if (at.column())
- ret += "COLUMN ";
- ret += ColumnToString(at.col());
- ret += " TO ";
- ret += ColumnToString(at.col_to());
- } else if (at.has_col_def()) {
- ret += "ADD ";
- if (at.column())
- ret += "COLUMN ";
- ret += ColumnDefToString(at.col_def());
- } else {
- ret += "RENAME TO ";
- ret += TableToString(at.table_fallback());
- }
- return ret;
-}
-
-// ~~~~ATTACH DATABASE~~~~
-CONV_FN(AttachDatabase, ad) {
- RETURN_IF_DISABLED_QUERY(AttachDatabase);
- std::string ret("ATTACH DATABASE \'");
- if (ad.in_memory()) {
- if (ad.file_uri()) {
- ret += "file:";
- std::string add;
- if (ad.has_db_name()) {
- ret += SchemaToString(ad.db_name());
- ret += "?mode=memory";
- add = "&";
- } else {
- ret += ":memory:";
- add = "?";
- }
-
- if (ad.shared_cache()) {
- ret += add;
- ret += "cache=shared";
- }
- }
- }
- ret += "\' AS ";
- ret += SchemaToString(ad.schema());
- return ret;
-}
-
-// ~~~~DETACH DATABASE~~~~
-CONV_FN(DetachDatabase, dd) {
- RETURN_IF_DISABLED_QUERY(DetachDatabase);
- std::string ret("DETACH DATABASE ");
- ret += SchemaToString(dd.schema());
- return ret;
-}
-
-// ~~~~Time and date fns~~~~
-CONV_FN(HoursStuff, hs) {
- std::string ret;
- if (hs.has_hh()) {
- ret += std::to_string(hs.hh() % 100);
- if (hs.has_mm()) {
- ret += ":";
- ret += std::to_string(hs.mm() % 100);
- if (hs.has_ss()) {
- ret += ":";
- ret += std::to_string(hs.ss() % 100);
- if (hs.has_sss()) {
- ret += ".";
- ret += std::to_string(hs.sss() % 1000);
- }
- }
- }
- }
- return ret;
-}
-
-CONV_FN(TimeString, ts) {
- std::string ret;
- if (ts.has_yyyy()) {
- // FIXME in the future add zeroes for integers < 1000.
- ret += std::to_string(ts.yyyy() % 10000);
- ret += "-";
- ret += std::to_string(ts.mm() % 100);
- ret += "-";
- ret += std::to_string(ts.dd() % 100);
- if (ts.extra_t())
- ret += "T";
- if (ts.has_hs())
- ret += HoursStuffToString(ts.hs());
- } else if (ts.has_hs()) {
- ret += HoursStuffToString(ts.hs());
- } else if (ts.has_dddddddddd()) {
- ret += std::to_string(ts.dddddddddd() % 10000000000);
- } else if (ts.now()) {
- ret += "now";
- } else {
- ret += ConvertToSqlString(ts.random_bytes());
- }
-
- if (ts.has_tz_plus()) {
- if (ts.z()) {
- ret += "Z";
- } else {
- if (ts.plus())
- ret += "+";
- else
- ret += "-";
- ret += std::to_string(ts.tz_hh() % 100);
- ret += std::to_string(ts.tz_mm() % 100);
- }
- }
- return ret;
-}
-
-CONV_FN(TimeModifier, tm) {
- std::string ret;
- if (tm.has_nm()) {
- ret += std::to_string(tm.num());
- ret += " ";
- if (tm.has_dot_num()) {
- ret += ".";
- ret += std::to_string(tm.dot_num());
- }
- ret += StrToLower(TimeModifier_NumberedModifiers_Name(tm.nm()));
- } else {
- ret += StrToLower(
- EnumStrReplaceUnderscores(TimeModifier_OtherModifiers_Name(tm.om())));
- }
- if (tm.om() == TimeModifier::WEEKDAY) {
- ret += " ";
- ret += std::to_string(tm.num());
- }
- return ret;
-}
-
-CONV_FN(SimpleDateAndTimeFn, sfn) {
- std::string ret;
- ret += StrToLower(SimpleDateAndTimeFn_FnName_Name(sfn.fn_name()));
- ret += "(\'";
- ret += TimeStringToString(sfn.time_string());
- ret += "\'";
- for (int i = 0; i < sfn.modifiers_size(); i++) {
- ret += ", \'";
- ret += TimeModifierToString(sfn.modifiers(i));
- ret += "\'";
- }
- ret += ") ";
- return ret;
-}
-
-CONV_FN(StrftimeFormat, sf) {
- std::string ret;
- if (sf.has_subs()) {
- std::string subs = StrftimeFormat_Substitution_Name(sf.subs());
- if (sf.lowercase())
- subs = StrToLower(subs);
- ret += "%" + subs;
- } else {
- ret += "%%";
- }
-
- ret += ConvertToSqlString(sf.bytes());
- return ret;
-}
-
-CONV_FN(StrftimeFn, sfn) {
- std::string ret("strftime(\'");
- for (int i = 0; i < sfn.fmts_size(); i++) {
- ret += StrftimeFormatToString(sfn.fmts(i));
- }
- ret += "\', \'";
- ret += TimeStringToString(sfn.time_string());
- ret += "\'";
- for (int i = 0; i < sfn.modifiers_size(); i++) {
- ret += ", \'";
- ret += TimeModifierToString(sfn.modifiers(i));
- ret += "\'";
- }
- ret += ") ";
- return ret;
-}
-
-CONV_FN(DateAndTimeFn, dat) {
- if (dat.has_simple())
- return SimpleDateAndTimeFnToString(dat.simple());
- else
- return StrftimeFnToString(dat.strftime());
-}
-
-// ~~~~QUERY~~~~
-CONV_FN(SQLQuery, query) {
- using QueryType = SQLQuery::QueryOneofCase;
- switch (query.query_oneof_case()) {
- case QueryType::kSelect:
- return SelectToString(query.select());
- case QueryType::kCreateTable:
- return CreateTableToString(query.create_table());
- case QueryType::kInsert:
- return InsertToString(query.insert());
- case QueryType::kDelete:
- return DeleteToString(query.delete_());
- case QueryType::kFts3Table:
- return CreateFTS3TableToString(query.fts3_table());
- case QueryType::kFtsQuery:
- return FTS3SpecificQueryToString(query.fts_query());
- case QueryType::kBeginTxn:
- return BeginTransactionToString(query.begin_txn());
- case QueryType::kCommitTxn:
- return CommitTransactionToString(query.commit_txn());
- case QueryType::kRollbackStmt:
- return RollbackStatementToString(query.rollback_stmt());
-#if !defined(FUZZ_OMIT_SAVEPOINT)
- case QueryType::kCreateSavePoint:
- return CreateSavePointToString(query.create_save_point());
- case QueryType::kReleaseSavePoint:
- return ReleaseSavePointToString(query.release_save_point());
-#endif
- case QueryType::kAnalyze:
- return AnalyzeToString(query.analyze());
- case QueryType::kVacuum:
- return VacuumToString(query.vacuum());
- case QueryType::kPragma:
- return PragmaToString(query.pragma());
- case QueryType::kUpdate:
- return UpdateToString(query.update());
- case QueryType::kCreateIndex:
- return CreateIndexToString(query.create_index());
- case QueryType::kCreateView:
- return CreateViewToString(query.create_view());
- case QueryType::kCreateTrigger:
- return CreateTriggerToString(query.create_trigger());
- case QueryType::kReindex:
- return ReIndexToString(query.reindex());
- case QueryType::kDrop:
- return DropToString(query.drop());
- case QueryType::kAlterTable:
- return AlterTableToString(query.alter_table());
- case QueryType::kAttachDb:
- return AttachDatabaseToString(query.attach_db());
- case QueryType::kDetachDb:
- return DetachDatabaseToString(query.detach_db());
-#if defined(FUZZ_FTS3)
- case QueryType::kFts3Insert:
- return FTS3HiddenTableInsertToString(query.fts3_insert());
- case QueryType::kFts3Update:
- return FTS3HiddenTableUpdateToString(query.fts3_update());
- case QueryType::kFts3Delete:
- return FTS3HiddenTableDeleteToString(query.fts3_delete());
-#endif
- default:
- return "";
- }
-}
-
-std::vector<std::string> SQLQueriesToVec(const SQLQueries& sql_queries) {
- std::vector<std::string> queries;
- queries.reserve(sql_queries.extra_queries_size() + 1);
- queries.push_back(CreateTableToString(sql_queries.create_table()) + ";");
- for (int i = 0; i < sql_queries.extra_queries_size(); i++) {
- std::string query = SQLQueryToString(sql_queries.extra_queries(i));
- if (query == "")
- continue;
- query += ";";
- queries.push_back(query);
- }
- return queries;
-}
-
-CONV_FN(SQLQueries, sql_queries) {
- std::string queries;
-
- for (std::string& query : SQLQueriesToVec(sql_queries)) {
- queries += query;
- queries += "\n";
- }
-
- return queries;
-}
-
-void SetDisabledQueries(std::set<std::string> disabled_queries) {
- disabled_queries_ = disabled_queries;
-}
-
-} // namespace sql_fuzzer
diff --git a/chromium/third_party/sqlite/fuzz/sql_query_proto_to_string.h b/chromium/third_party/sqlite/fuzz/sql_query_proto_to_string.h
deleted file mode 100644
index b4b7fe9104f..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_query_proto_to_string.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_SQLITE_FUZZ_SQL_QUERY_PROTO_TO_STRING_H_
-#define THIRD_PARTY_SQLITE_FUZZ_SQL_QUERY_PROTO_TO_STRING_H_
-
-#include <string>
-#include <vector>
-
-#include "third_party/sqlite/fuzz/sql_queries.pb.h"
-
-namespace sql_fuzzer {
-
-std::string SQLQueriesToString(
- const sql_query_grammar::SQLQueries& sql_queries);
-std::vector<std::string> SQLQueriesToVec(
- const sql_query_grammar::SQLQueries& sql_queries);
-
-std::string PrintfToString(const sql_query_grammar::Printf&);
-std::string StrftimeFnToString(const sql_query_grammar::StrftimeFn&);
-std::string ExprToString(const sql_query_grammar::Expr&);
-
-std::string SQLQueryToString(const sql_query_grammar::SQLQuery&);
-
-void SetDisabledQueries(std::set<std::string> disabled_queries);
-
-} // namespace sql_fuzzer
-
-#endif // THIRD_PARTY_SQLITE_FUZZ_SQL_QUERY_PROTO_TO_STRING_H_
diff --git a/chromium/third_party/sqlite/fuzz/sql_run_queries.cc b/chromium/third_party/sqlite/fuzz/sql_run_queries.cc
deleted file mode 100644
index 010b67efcae..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_run_queries.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Adapted from sqlite's ossfuzz.c
-
-#include <cstdlib>
-#include <iostream> // TODO(mpdenton) remove
-#include <string>
-#include <vector>
-
-#include "third_party/sqlite/sqlite3.h"
-
-namespace sql_fuzzer {
-
-namespace {
-constexpr int kMaxNumRows = 10;
-constexpr int kMaxNumColumns = 10;
-
-sqlite3_int64 killTime;
-
-/* Return the current real-world time in milliseconds since the
-** Julian epoch (-4714-11-24).
-*/
-static sqlite3_int64 timeOfDay(void) {
- static sqlite3_vfs* clockVfs = 0;
- sqlite3_int64 t;
- if (clockVfs == 0) {
- clockVfs = sqlite3_vfs_find(0);
- if (clockVfs == 0)
- return 0;
- }
- if (clockVfs->iVersion >= 2 && clockVfs->xCurrentTimeInt64 != 0) {
- clockVfs->xCurrentTimeInt64(clockVfs, &t);
- } else {
- double r;
- clockVfs->xCurrentTime(clockVfs, &r);
- t = (sqlite3_int64)(r * 86400000.0);
- }
- return t;
-}
-
-int progress_handler(void*) {
- sqlite3_int64 iNow = timeOfDay();
- int rc = iNow >= killTime;
- return rc;
-}
-} // namespace
-
-void RunSqlQueriesOnSameDB() {
- // TODO(mpdenton) unimplemented
-}
-
-sqlite3* InitConnectionForFuzzing() {
- int rc; // Return code from various interfaces.
- sqlite3* db; // Sqlite db.
-
- rc = sqlite3_initialize();
- if (rc) {
- std::cerr << "Failed initialization. " << std::endl;
- return nullptr;
- }
-
- // Open the database connection. Only use an in-memory database.
- rc = sqlite3_open_v2(
- "fuzz.db", &db,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
- if (rc) {
- std::cerr << "Failed to open DB. " << std::endl;
- return nullptr;
- }
-
- // Enables foreign key constraints
- sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, 1, &rc);
-
- // sqlite3_db_config(db, SQLITE_DBCONFIG_DEFENSIVE, 0, &rc); // TODO(pwnall)
-
- return db;
-}
-
-void EnableSqliteTracing(sqlite3* db) {
- sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
-}
-
-void CloseConnection(sqlite3* db) {
- // Cleanup and return.
- sqlite3_exec(db, "PRAGMA temp_store_directory=''", 0, 0, 0);
- sqlite3_close(db);
-}
-
-void RunSqlQueriesOnConnection(sqlite3* db, std::vector<std::string> queries) {
- int rc;
- for (size_t i = 0; i < queries.size(); i++) {
- // Run each query one by one.
- // First, compile the query.
- sqlite3_stmt* stmt;
- const char* pzTail;
- rc = sqlite3_prepare_v2(db, queries[i].c_str(), -1, &stmt, &pzTail);
- if (rc != SQLITE_OK) {
- if (::getenv("PRINT_SQLITE_ERRORS")) {
- std::cerr << "Could not compile: " << queries[i] << std::endl;
- std::cerr << "Error message from db: " << sqlite3_errmsg(db)
- << std::endl;
- std::cerr << "-----------------------------" << std::endl;
- }
- continue;
- }
-
- // No sqlite3_bind.
-
- // Reset progress callback for every query. Timeout after 1 second.
- // ClusterFuzz timeouts are not useful, so we try to avoid them.
- // This will hopefully make Clusterfuzz find better, smaller SELECT
- // statements.
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- killTime = timeOfDay() + 1000;
- sqlite3_progress_handler(db, 100, progress_handler, nullptr);
-#endif
-
- // Now run the compiled query.
- int col_cnt = sqlite3_column_count(stmt);
- int count = 0;
- rc = SQLITE_ROW;
- while (rc == SQLITE_ROW && count++ <= kMaxNumRows) {
- rc = sqlite3_step(stmt);
- if (rc != SQLITE_DONE && rc != SQLITE_ROW) {
- if (::getenv("PRINT_SQLITE_ERRORS")) {
- std::cerr << "Step problem: " << queries[i] << std::endl;
- std::cerr << "Error message from db: " << sqlite3_errmsg(db)
- << std::endl;
- std::cerr << "-----------------------------" << std::endl;
- }
- goto free_stmt;
- }
- // Loop through the columns to catch a little bit more coverage.
- for (int i = 0; i < col_cnt && i < kMaxNumColumns; i++) {
- switch (sqlite3_column_type(stmt, i)) {
- case SQLITE_INTEGER:
- sqlite3_column_int(stmt, i);
- break;
- case SQLITE_FLOAT:
- sqlite3_column_double(stmt, i);
- break;
- case SQLITE_TEXT:
- sqlite3_column_text(stmt, i);
- break;
- case SQLITE_BLOB:
- sqlite3_column_blob(stmt, i);
- break;
- default:
- break;
- }
- }
- }
-
- // Finalize the query
- free_stmt:
- sqlite3_finalize(stmt);
- }
-}
-
-void RunSqlQueries(std::vector<std::string> queries, bool enable_tracing) {
- sqlite3* db = InitConnectionForFuzzing();
- if (enable_tracing)
- EnableSqliteTracing(db);
-
- RunSqlQueriesOnConnection(db, queries);
-
- CloseConnection(db);
-}
-
-} // namespace sql_fuzzer
diff --git a/chromium/third_party/sqlite/fuzz/sql_run_queries.h b/chromium/third_party/sqlite/fuzz/sql_run_queries.h
deleted file mode 100644
index 95506d92713..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_run_queries.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-#include <vector>
-
-#include "third_party/sqlite/sqlite3.h"
-
-namespace sql_fuzzer {
-/* Standalone function that wraps the three functions below. */
-void RunSqlQueries(std::vector<std::string> queries, bool enable_tracing);
-
-sqlite3* InitConnectionForFuzzing();
-void EnableSqliteTracing(sqlite3* db);
-void RunSqlQueriesOnConnection(sqlite3* db, std::vector<std::string> queries);
-void CloseConnection(sqlite3* db);
-} // namespace sql_fuzzer
diff --git a/chromium/third_party/sqlite/fuzz/sql_strftime_fuzzer.cc b/chromium/third_party/sqlite/fuzz/sql_strftime_fuzzer.cc
deleted file mode 100644
index 7c4322ea912..00000000000
--- a/chromium/third_party/sqlite/fuzz/sql_strftime_fuzzer.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <cstdlib>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "testing/libfuzzer/proto/lpm_interface.h"
-#include "third_party/sqlite/fuzz/sql_query_grammar.pb.h"
-#include "third_party/sqlite/fuzz/sql_query_proto_to_string.h"
-#include "third_party/sqlite/fuzz/sql_run_queries.h"
-
-using namespace sql_query_grammar;
-
-DEFINE_BINARY_PROTO_FUZZER(const StrftimeFn& sql_strftime) {
- std::string strftime_str = sql_fuzzer::StrftimeFnToString(sql_strftime);
- // Convert printf command into runnable SQL query.
- strftime_str = "SELECT " + strftime_str + ";";
-
- if (getenv("LPM_DUMP_NATIVE_INPUT")) {
- std::cout << "_________________________" << std::endl;
- std::cout << strftime_str << std::endl;
- std::cout << "------------------------" << std::endl;
- }
-
- std::vector<std::string> queries;
- queries.push_back(strftime_str);
- sql_fuzzer::RunSqlQueries(queries, ::getenv("LPM_SQLITE_TRACE"));
-}
diff --git a/chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch b/chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
index 1d86c19c32f..69f62077520 100644
--- a/chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
+++ b/chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dumi <dumi@chromium.org>
Date: Mon, 20 Jul 2009 23:40:51 +0000
-Subject: [PATCH 01/40] Modify default VFS to support WebDatabase.
+Subject: [PATCH 1/7] Modify default VFS to support WebDatabase.
The renderer WebDatabase implementation needs to broker certain requests
to the browser. This modifies SQLite to allow monkey-patching the VFS
@@ -141,10 +141,10 @@ index aafc89f7d2d5..76743781a019 100644
+
#endif /* SQLITE_OS_WIN */
diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src/sqlite.h.in
-index cf17bc015fa7..11622a49697f 100644
+index fd6046dfe169..3d6b63e006a0 100644
--- a/third_party/sqlite/src/src/sqlite.h.in
+++ b/third_party/sqlite/src/src/sqlite.h.in
-@@ -8378,6 +8378,29 @@ int sqlite3_strnicmp(const char *, const char *, int);
+@@ -8407,6 +8407,29 @@ int sqlite3_strnicmp(const char *, const char *, int);
*/
int sqlite3_strglob(const char *zGlob, const char *zStr);
@@ -175,5 +175,5 @@ index cf17bc015fa7..11622a49697f 100644
** CAPI3REF: String LIKE Matching
*
--
-2.18.0
+2.20.0
diff --git a/chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch b/chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
index ef5d82012f0..0e343fc21e7 100644
--- a/chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
+++ b/chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
@@ -1,8 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Scott Hess <shess@chromium.org>
Date: Sat, 20 Jul 2013 11:42:21 -0700
-Subject: [PATCH 02/40] Virtual table supporting recovery of corrupted
- databases.
+Subject: [PATCH 2/7] Virtual table supporting recovery of corrupted databases.
"recover" implements a virtual table which uses the SQLite pager layer
to read table pages and pull out the data which is structurally sound
@@ -34,7 +33,7 @@ third_party/sqlite/src/src/{recover,recover-alt}.c .
create mode 100644 third_party/sqlite/src/test/recover2.test
diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
-index d18313bdc79a..81774f9b100f 100644
+index c4e8b78e911f..57a27c1e3fc1 100644
--- a/third_party/sqlite/src/main.mk
+++ b/third_party/sqlite/src/main.mk
@@ -77,6 +77,8 @@ LIBOBJ+= vdbe.o parse.o \
@@ -46,7 +45,7 @@ index d18313bdc79a..81774f9b100f 100644
LIBOBJ += sqlite3session.o
# All of the source code files.
-@@ -409,6 +411,8 @@ TESTSRC2 = \
+@@ -410,6 +412,8 @@ TESTSRC2 = \
$(TOP)/src/prepare.c \
$(TOP)/src/printf.c \
$(TOP)/src/random.c \
@@ -55,7 +54,7 @@ index d18313bdc79a..81774f9b100f 100644
$(TOP)/src/pcache.c \
$(TOP)/src/pcache1.c \
$(TOP)/src/select.c \
-@@ -876,6 +880,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
+@@ -898,6 +902,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
@@ -64,10 +63,10 @@ index d18313bdc79a..81774f9b100f 100644
testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main.c
-index d994c7176ea4..478428ac27c8 100644
+index c98cfe99eed3..d58f8c633f8b 100644
--- a/third_party/sqlite/src/src/main.c
+++ b/third_party/sqlite/src/src/main.c
-@@ -3201,6 +3201,14 @@ static int openDatabase(
+@@ -3244,6 +3244,14 @@ static int openDatabase(
}
#endif
diff --git a/chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch b/chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
index 6a49c96d76a..286ef28f2cb 100644
--- a/chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
+++ b/chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "tc@google.com" <tc@google.com>
Date: Tue, 6 Jan 2009 22:39:41 +0000
-Subject: [PATCH 03/40] Custom shell.c helpers to load Chromium's ICU data.
+Subject: [PATCH 3/7] Custom shell.c helpers to load Chromium's ICU data.
History uses fts3 with an icu-based segmenter. These changes allow building a
sqlite3 binary for Linux or Windows which can read those files.
@@ -36,10 +36,10 @@ index b838b844a312..3047d172389b 100644
# Nothing for unix.
#
diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
-index 81774f9b100f..b460a58d9a94 100644
+index 57a27c1e3fc1..ee8ebbb92f50 100644
--- a/third_party/sqlite/src/main.mk
+++ b/third_party/sqlite/src/main.mk
-@@ -549,7 +549,7 @@ libsqlite3.a: $(LIBOBJ)
+@@ -556,7 +556,7 @@ libsqlite3.a: $(LIBOBJ)
sqlite3$(EXE): shell.c libsqlite3.a sqlite3.h
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
@@ -49,10 +49,10 @@ index 81774f9b100f..b460a58d9a94 100644
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
diff --git a/third_party/sqlite/src/src/shell.c.in b/third_party/sqlite/src/src/shell.c.in
-index 0007d984d045..b13551dc61f2 100644
+index cca409a6ac73..9ccac2b34ee5 100644
--- a/third_party/sqlite/src/src/shell.c.in
+++ b/third_party/sqlite/src/src/shell.c.in
-@@ -8555,6 +8555,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
+@@ -8891,6 +8891,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
}
#endif
diff --git a/chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch b/chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
index e77c9494f8c..72b1a2d664c 100644
--- a/chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
+++ b/chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Scott Hess <shess@chromium.org>
Date: Tue, 16 Dec 2014 13:02:27 -0800
-Subject: [PATCH 04/40] [fts3] Disable fts3_tokenizer and fts4.
+Subject: [PATCH 4/7] [fts3] Disable fts3_tokenizer and fts4.
fts3_tokenizer allows a SQLite user to specify a pointer to call as a
function, which has obvious sercurity implications. Disable fts4 until
@@ -14,7 +14,7 @@ No original review URL because this was part of the initial Chromium commit.
1 file changed, 9 insertions(+)
diff --git a/third_party/sqlite/src/ext/fts3/fts3.c b/third_party/sqlite/src/ext/fts3/fts3.c
-index 44d9e20cc667..ef69a7b18681 100644
+index 823e1b6a81fe..c371d3e8f0b5 100644
--- a/third_party/sqlite/src/ext/fts3/fts3.c
+++ b/third_party/sqlite/src/ext/fts3/fts3.c
@@ -287,6 +287,7 @@
@@ -25,7 +25,7 @@ index 44d9e20cc667..ef69a7b18681 100644
#include "fts3Int.h"
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-@@ -3988,7 +3989,11 @@ int sqlite3Fts3Init(sqlite3 *db){
+@@ -4016,7 +4017,11 @@ int sqlite3Fts3Init(sqlite3 *db){
** module with sqlite.
*/
if( SQLITE_OK==rc
@@ -37,7 +37,7 @@ index 44d9e20cc667..ef69a7b18681 100644
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
-@@ -3998,6 +4003,9 @@ int sqlite3Fts3Init(sqlite3 *db){
+@@ -4026,6 +4031,9 @@ int sqlite3Fts3Init(sqlite3 *db){
rc = sqlite3_create_module_v2(
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
);
@@ -47,7 +47,7 @@ index 44d9e20cc667..ef69a7b18681 100644
if( rc==SQLITE_OK ){
rc = sqlite3_create_module_v2(
db, "fts4", &fts3Module, (void *)pHash, 0
-@@ -4006,6 +4014,7 @@ int sqlite3Fts3Init(sqlite3 *db){
+@@ -4034,6 +4042,7 @@ int sqlite3Fts3Init(sqlite3 *db){
if( rc==SQLITE_OK ){
rc = sqlite3Fts3InitTok(db, (void *)pHash);
}
@@ -56,5 +56,5 @@ index 44d9e20cc667..ef69a7b18681 100644
}
--
-2.18.0
+2.20.0
diff --git a/chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch b/chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
index 8f4f6e01db9..839564ce711 100644
--- a/chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
+++ b/chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Scott Graham <scottmg@chromium.org>
Date: Mon, 11 Sep 2017 13:37:46 -0700
-Subject: [PATCH 05/40] fuchsia: Use dot-file locking for sqlite
+Subject: [PATCH 5/7] fuchsia: Use dot-file locking for sqlite
---
third_party/sqlite/src/src/os_unix.c | 4 ++++
diff --git a/chromium/third_party/sqlite/patches/0006-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch b/chromium/third_party/sqlite/patches/0006-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch
new file mode 100644
index 00000000000..8b30021ec55
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0006-Fix-compilation-with-SQLITE_OMIT_WINDOWFUNC.patch
@@ -0,0 +1,32 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Sun, 10 Feb 2019 13:12:57 -0800
+Subject: [PATCH 6/7] Fix compilation with SQLITE_OMIT_WINDOWFUNC.
+
+---
+ third_party/sqlite/src/src/resolve.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/third_party/sqlite/src/src/resolve.c b/third_party/sqlite/src/src/resolve.c
+index 00c6bb9680b0..edf1e203440c 100644
+--- a/third_party/sqlite/src/src/resolve.c
++++ b/third_party/sqlite/src/src/resolve.c
+@@ -1533,6 +1533,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
+ }
+ }
+
++#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( IN_RENAME_OBJECT ){
+ Window *pWin;
+ for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
+@@ -1543,6 +1544,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
+ }
+ }
+ }
++#endif
+
+ /* If this is part of a compound SELECT, check that it has the right
+ ** number of expressions in the select list. */
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch b/chromium/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch
deleted file mode 100644
index c5cd6153bd8..00000000000
--- a/chromium/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Matthew Denton <mpdenton@chromium.org>
-Date: Fri, 7 Dec 2018 14:49:36 -0700
-Subject: [PATCH 06/40] Fix dbfuzz2 for Clusterfuzz.
-
-This backports https://www.sqlite.org/src/info/9ad796a8822f1b7e
----
- third_party/sqlite/src/test/dbfuzz2.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/third_party/sqlite/src/test/dbfuzz2.c b/third_party/sqlite/src/test/dbfuzz2.c
-index 0833f0386884..9e3aca25274b 100644
---- a/third_party/sqlite/src/test/dbfuzz2.c
-+++ b/third_party/sqlite/src/test/dbfuzz2.c
-@@ -78,6 +78,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
- printf("************** nByte=%d ***************\n", (int)nByte);
- fflush(stdout);
- }
-+ if( sqlite3_initialize() ) return 0;
- rc = sqlite3_open(0, &db);
- if( rc ) return 1;
- a = sqlite3_malloc64(nByte+1);
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0007-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch b/chromium/third_party/sqlite/patches/0007-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch
new file mode 100644
index 00000000000..d3f19f5d02f
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0007-Fix-dbfuzz2.c-compilation-errors-on-Windows.patch
@@ -0,0 +1,43 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Sun, 10 Feb 2019 15:18:43 -0800
+Subject: [PATCH 7/7] Fix dbfuzz2.c compilation errors on Windows.
+
+---
+ third_party/sqlite/src/test/dbfuzz2.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/third_party/sqlite/src/test/dbfuzz2.c b/third_party/sqlite/src/test/dbfuzz2.c
+index c964ad4f018f..dd1ed061717b 100644
+--- a/third_party/sqlite/src/test/dbfuzz2.c
++++ b/third_party/sqlite/src/test/dbfuzz2.c
+@@ -43,8 +43,10 @@
+ #include <stdarg.h>
+ #include <ctype.h>
+ #include <stdint.h>
++#ifndef _WIN32
+ #include <sys/time.h>
+ #include <sys/resource.h>
++#endif
+ #include "sqlite3.h"
+
+ /*
+@@ -261,6 +263,7 @@ int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
+ szMax = strtol(argv[++i], 0, 0);
+ continue;
+ }
++#ifndef _WIN32
+ if( strcmp(z,"max-stack")==0
+ || strcmp(z,"max-data")==0
+ || strcmp(z,"max-as")==0
+@@ -291,6 +294,7 @@ int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
+ zType, (int)x.rlim_cur, (int)y.rlim_cur);
+ continue;
+ }
++#endif
+ }
+ argv[j++] = argv[i];
+ }
+--
+2.20.0
+
diff --git a/chromium/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch b/chromium/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch
deleted file mode 100644
index 8886eabfca3..00000000000
--- a/chromium/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Wed, 19 Dec 2018 18:22:15 -0800
-Subject: [PATCH 07/40] Fix the Makefile so that it honors CFLAGS when building
- sessionfuzz.
-
-This backports https://www.sqlite.org/src/info/54231ac4ca506e6c
----
- third_party/sqlite/src/Makefile.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/Makefile.in b/third_party/sqlite/src/Makefile.in
-index d2f97100597b..3b05f1e25ca7 100644
---- a/third_party/sqlite/src/Makefile.in
-+++ b/third_party/sqlite/src/Makefile.in
-@@ -669,7 +669,7 @@ ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.
- $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
-
- sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
-- $(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
-+ $(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
-
- dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
- $(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch b/chromium/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch
deleted file mode 100644
index 8d86320bf7e..00000000000
--- a/chromium/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 02:01:53 -0800
-Subject: [PATCH 08/40] Adjustments to the page cache to try to avoid harmless
- TSAN warnings
-
-This backports https://www.sqlite.org/src/info/383437be276719ac
-
-Bug: 917380
----
- third_party/sqlite/src/src/pcache1.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/pcache1.c b/third_party/sqlite/src/src/pcache1.c
-index 59c1869ff707..1986b22ca61c 100644
---- a/third_party/sqlite/src/src/pcache1.c
-+++ b/third_party/sqlite/src/src/pcache1.c
-@@ -167,6 +167,7 @@ struct PCache1 {
- unsigned int nMax; /* Configured "cache_size" value */
- unsigned int n90pct; /* nMax*9/10 */
- unsigned int iMaxKey; /* Largest key seen since xTruncate() */
-+ unsigned int nPurgeableDummy; /* pnPurgeable points here when not used*/
-
- /* Hash table of all pages. The following variables may only be accessed
- ** when the accessor is holding the PGroup mutex.
-@@ -780,8 +781,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
- pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
- pCache->pnPurgeable = &pGroup->nPurgeable;
- }else{
-- static unsigned int dummyCurrentPage;
-- pCache->pnPurgeable = &dummyCurrentPage;
-+ pCache->pnPurgeable = &pCache->nPurgeableDummy;
- }
- pcache1LeaveMutex(pGroup);
- if( pCache->nHash==0 ){
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch b/chromium/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch
deleted file mode 100644
index d5159f6edd3..00000000000
--- a/chromium/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 02:26:10 -0800
-Subject: [PATCH 09/40] Remove an ALWAYS() from a branch that is not always
- taken.
-
-This backports https://www.sqlite.org/src/info/5c7dab
-
-Bug: 918035
----
- third_party/sqlite/src/src/expr.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
-index 4aff7f67c9b6..6b2c5a540a82 100644
---- a/third_party/sqlite/src/src/expr.c
-+++ b/third_party/sqlite/src/src/expr.c
-@@ -4755,7 +4755,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
- }
- }
- if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
-- if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
-+ if( (combinedFlags & EP_TokenOnly)==0 ){
- if( combinedFlags & EP_xIsSelect ) return 2;
- if( (combinedFlags & EP_FixedCol)==0
- && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch b/chromium/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch
deleted file mode 100644
index 216d8ef8117..00000000000
--- a/chromium/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 02:30:28 -0800
-Subject: [PATCH 10/40] Fix a problem with nested CTEs with the same table.
-
-This backports https://www.sqlite.org/src/info/202dd033019dd274
-
-Bug: 917834
----
- third_party/sqlite/src/src/select.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/select.c b/third_party/sqlite/src/src/select.c
-index 870c3b5c1739..fab4df68fa17 100644
---- a/third_party/sqlite/src/src/select.c
-+++ b/third_party/sqlite/src/src/select.c
-@@ -5464,14 +5464,19 @@ static struct SrcList_item *isSelfJoinView(
- ){
- struct SrcList_item *pItem;
- for(pItem = pTabList->a; pItem<pThis; pItem++){
-+ Select *pS1;
- if( pItem->pSelect==0 ) continue;
- if( pItem->fg.viaCoroutine ) continue;
- if( pItem->zName==0 ) continue;
- if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
- if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
-- if( sqlite3ExprCompare(0,
-- pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1)
-- ){
-+ pS1 = pItem->pSelect;
-+ if( pThis->pSelect->selId!=pS1->selId ){
-+ /* The query flattener left two different CTE tables with identical
-+ ** names in the same FROM clause. */
-+ continue;
-+ }
-+ if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1) ){
- /* The view was modified by some other optimization such as
- ** pushDownWhereTerms() */
- continue;
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch b/chromium/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch
deleted file mode 100644
index 878c4b23cae..00000000000
--- a/chromium/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 03:45:18 -0800
-Subject: [PATCH 11/40] Fix detection of self-referencing rows in foreign key
- processing.
-
-This backports https://www.sqlite.org/src/info/16fff05347f42fe9
-
-Bug: 916478
----
- third_party/sqlite/src/src/fkey.c | 13 ++++++++-----
- 1 file changed, 8 insertions(+), 5 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/fkey.c b/third_party/sqlite/src/src/fkey.c
-index 71e55adaf8ab..b9aad0c96588 100644
---- a/third_party/sqlite/src/src/fkey.c
-+++ b/third_party/sqlite/src/src/fkey.c
-@@ -602,8 +602,11 @@ static void fkScanChildren(
- ** NOT( $current_a==a AND $current_b==b AND ... )
- **
- ** The first form is used for rowid tables. The second form is used
-- ** for WITHOUT ROWID tables. In the second form, the primary key is
-- ** (a,b,...)
-+ ** for WITHOUT ROWID tables. In the second form, the *parent* key is
-+ ** (a,b,...). Either the parent or primary key could be used to
-+ ** uniquely identify the current row, but the parent key is more convenient
-+ ** as the required values have already been loaded into registers
-+ ** by the caller.
- */
- if( pTab==pFKey->pFrom && nIncr>0 ){
- Expr *pNe; /* Expression (pLeft != pRight) */
-@@ -617,12 +620,12 @@ static void fkScanChildren(
- Expr *pEq, *pAll = 0;
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- assert( pIdx!=0 );
-- for(i=0; i<pPk->nKeyCol; i++){
-+ for(i=0; i<pIdx->nKeyCol; i++){
- i16 iCol = pIdx->aiColumn[i];
- assert( iCol>=0 );
- pLeft = exprTableRegister(pParse, pTab, regData, iCol);
-- pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
-- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
-+ pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
-+ pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
- pAll = sqlite3ExprAnd(db, pAll, pEq);
- }
- pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch b/chromium/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch
deleted file mode 100644
index 5f739802ad8..00000000000
--- a/chromium/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 03:52:20 -0800
-Subject: [PATCH 12/40] Fix a segfault caused by using the RAISE function
- incorrectly.
-
-This backports https://sqlite.org/src/info/ddf06db702761d66
-
-Bug: 915479
----
- third_party/sqlite/src/src/expr.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
-index 6b2c5a540a82..0aa11c43bf4a 100644
---- a/third_party/sqlite/src/src/expr.c
-+++ b/third_party/sqlite/src/src/expr.c
-@@ -4722,7 +4722,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
- }
- return 2;
- }
-- if( pA->op!=pB->op ){
-+ if( pA->op!=pB->op || pA->op==TK_RAISE ){
- if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
- return 1;
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch b/chromium/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch
deleted file mode 100644
index d9e280440e7..00000000000
--- a/chromium/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 04:18:45 -0800
-Subject: [PATCH 13/40] Fix for an assert() that could be false.
-
-This backports https://www.sqlite.org/src/info/23b62fb160d86dc9 /
-https://www.sqlite.org/src/info/bc891ac6b62fe7d9
-
-Bug: 911255
----
- third_party/sqlite/src/src/expr.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
-index 0aa11c43bf4a..05c9521b2030 100644
---- a/third_party/sqlite/src/src/expr.c
-+++ b/third_party/sqlite/src/src/expr.c
-@@ -4761,8 +4761,10 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
- && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
- if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
- if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
-- assert( (combinedFlags & EP_Reduced)==0 );
-- if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
-+ if( pA->op!=TK_STRING
-+ && pA->op!=TK_TRUEFALSE
-+ && (combinedFlags & EP_Reduced)==0
-+ ){
- if( pA->iColumn!=pB->iColumn ) return 2;
- if( pA->iTable!=pB->iTable
- && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch b/chromium/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch
deleted file mode 100644
index 4b4c61a4d89..00000000000
--- a/chromium/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 04:21:21 -0800
-Subject: [PATCH 14/40] Fix another problem found by Matthew Denton's new
- fuzzer.
-
-This backports https://sqlite.org/src/info/2b690dbdffe144bd
-
-Bug: 911253
----
- third_party/sqlite/src/src/expr.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
-index 05c9521b2030..c61528288baf 100644
---- a/third_party/sqlite/src/src/expr.c
-+++ b/third_party/sqlite/src/src/expr.c
-@@ -141,8 +141,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
- while( p ){
- int op = p->op;
- if( p->flags & EP_Generic ) break;
-- if( (op==TK_AGG_COLUMN || op==TK_COLUMN
-- || op==TK_REGISTER || op==TK_TRIGGER)
-+ if( op==TK_REGISTER ) op = p->op2;
-+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
- && p->y.pTab!=0
- ){
- /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
-@@ -158,7 +158,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
- p = p->pLeft;
- continue;
- }
-- if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
-+ if( op==TK_COLLATE ){
- pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
- break;
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch b/chromium/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch
deleted file mode 100644
index 12ea8973467..00000000000
--- a/chromium/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 12:15:27 -0800
-Subject: [PATCH 15/40] Report a new corruption case.
-
-This backports https://sqlite.org/src/info/cc42dd15100db28a
-
-Bug: 917285
----
- third_party/sqlite/src/src/btree.c | 7 +++++++
- third_party/sqlite/src/test/fuzzcheck.c | 2 +-
- 2 files changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 7a8de2d78c6a..6b17bdee5c4f 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -992,6 +992,13 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
- *pRC = rc;
- return;
- }
-+ if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){
-+ /* The first byte of the extra data is the MemPage.isInit byte.
-+ ** If that byte is set, it means this page is also being used
-+ ** as a btree page. */
-+ *pRC = SQLITE_CORRUPT_BKPT;
-+ goto ptrmap_exit;
-+ }
- offset = PTRMAP_PTROFFSET(iPtrmap, key);
- if( offset<0 ){
- *pRC = SQLITE_CORRUPT_BKPT;
-diff --git a/third_party/sqlite/src/test/fuzzcheck.c b/third_party/sqlite/src/test/fuzzcheck.c
-index 61925fcbe435..7ed17ae8a7d1 100644
---- a/third_party/sqlite/src/test/fuzzcheck.c
-+++ b/third_party/sqlite/src/test/fuzzcheck.c
-@@ -447,7 +447,7 @@ static int inmemRead(
- if( iOfst+iAmt>pVFile->sz ){
- memset(pData, 0, iAmt);
- iAmt = (int)(pVFile->sz - iOfst);
-- memcpy(pData, pVFile->a, iAmt);
-+ memcpy(pData, pVFile->a + iOfst, iAmt);
- return SQLITE_IOERR_SHORT_READ;
- }
- memcpy(pData, pVFile->a + iOfst, iAmt);
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch b/chromium/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch
deleted file mode 100644
index a912e8b7b54..00000000000
--- a/chromium/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 12:19:01 -0800
-Subject: [PATCH 16/40] Avoid a buffer overread in ptrmapPutOvflPtr().
-
-This backports https://sqlite.org/src/info/f8b781cf41800e9f
-
-Bug: 914407
----
- third_party/sqlite/src/src/btree.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 6b17bdee5c4f..14af51e15ab2 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -1364,7 +1364,12 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
- assert( pCell!=0 );
- pPage->xParseCell(pPage, pCell, &info);
- if( info.nLocal<info.nPayload ){
-- Pgno ovfl = get4byte(&pCell[info.nSize-4]);
-+ Pgno ovfl;
-+ if( SQLITE_WITHIN(pPage->aDataEnd, pCell, pCell+info.nLocal) ){
-+ *pRC = SQLITE_CORRUPT_BKPT;
-+ return;
-+ }
-+ ovfl = get4byte(&pCell[info.nSize-4]);
- ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
- }
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch b/chromium/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch
deleted file mode 100644
index 9417c68acb5..00000000000
--- a/chromium/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 11 Jan 2019 13:22:44 -0800
-Subject: [PATCH 17/40] Improved detection of cell corruption in
- sqlite3VdbeRecordCompareWithSkip().
-
-This backports https://www.sqlite.org/src/info/fa47f4c6589c431c
-
-Bug: 915348
----
- third_party/sqlite/src/src/vdbeaux.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/vdbeaux.c b/third_party/sqlite/src/src/vdbeaux.c
-index ebcb652bad20..15a095ff6e7b 100644
---- a/third_party/sqlite/src/src/vdbeaux.c
-+++ b/third_party/sqlite/src/src/vdbeaux.c
-@@ -4167,12 +4167,12 @@ int sqlite3VdbeRecordCompareWithSkip(
- }else{
- idx1 = getVarint32(aKey1, szHdr1);
- d1 = szHdr1;
-- if( d1>(unsigned)nKey1 ){
-- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
-- return 0; /* Corruption */
-- }
- i = 0;
- }
-+ if( d1>(unsigned)nKey1 ){
-+ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
-+ return 0; /* Corruption */
-+ }
-
- VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
- assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0018-Fix-a-segfault-in-fts3-prompted-by-a-corrupted-datab.patch b/chromium/third_party/sqlite/patches/0018-Fix-a-segfault-in-fts3-prompted-by-a-corrupted-datab.patch
deleted file mode 100644
index d7272249a80..00000000000
--- a/chromium/third_party/sqlite/patches/0018-Fix-a-segfault-in-fts3-prompted-by-a-corrupted-datab.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sat, 12 Jan 2019 12:36:35 -0800
-Subject: [PATCH 18/40] Fix a segfault in fts3 prompted by a corrupted
- database.
-
-This backports https://www.sqlite.org/src/info/2d7b1d1d41ff69d5
-
-Bug: 915499
----
- third_party/sqlite/src/ext/fts3/fts3.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/ext/fts3/fts3.c b/third_party/sqlite/src/ext/fts3/fts3.c
-index ef69a7b18681..005d8e50212e 100644
---- a/third_party/sqlite/src/ext/fts3/fts3.c
-+++ b/third_party/sqlite/src/ext/fts3/fts3.c
-@@ -2899,7 +2899,7 @@ static int fts3SegReaderCursor(
-
- /* If zTerm is not NULL, and this segment is not stored entirely on its
- ** root node, the range of leaves scanned can be reduced. Do this. */
-- if( iStartBlock && zTerm ){
-+ if( iStartBlock && zTerm && zRoot ){
- sqlite3_int64 *pi = (isPrefix ? &iLeavesEndBlock : 0);
- rc = fts3SelectLeaf(p, zTerm, nTerm, zRoot, nRoot, &iStartBlock, pi);
- if( rc!=SQLITE_OK ) goto finished;
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0019-Prevent-integer-overflow-from-leading-to-buffer-over.patch b/chromium/third_party/sqlite/patches/0019-Prevent-integer-overflow-from-leading-to-buffer-over.patch
deleted file mode 100644
index de615a94fba..00000000000
--- a/chromium/third_party/sqlite/patches/0019-Prevent-integer-overflow-from-leading-to-buffer-over.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sat, 12 Jan 2019 14:30:08 -0800
-Subject: [PATCH 19/40] Prevent integer overflow from leading to buffer
- overread inside of an assert().
-
-This backports https://www.sqlite.org/src/info/0f850a25d67a752f
-
-Bug: 921298
----
- third_party/sqlite/src/src/vdbeaux.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/vdbeaux.c b/third_party/sqlite/src/src/vdbeaux.c
-index 15a095ff6e7b..9ba127360fea 100644
---- a/third_party/sqlite/src/src/vdbeaux.c
-+++ b/third_party/sqlite/src/src/vdbeaux.c
-@@ -3799,8 +3799,8 @@ static int vdbeRecordCompareDebug(
- ** Use that approximation to avoid the more expensive call to
- ** sqlite3VdbeSerialTypeLen() in the common case.
- */
-- if( d1+serial_type1+2>(u32)nKey1
-- && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1
-+ if( d1+(u64)serial_type1+2>(u64)nKey1
-+ && d1+(u64)sqlite3VdbeSerialTypeLen(serial_type1)>(u64)nKey1
- ){
- break;
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0020-Add-extra-tests-for-database-corruption-inside-defra.patch b/chromium/third_party/sqlite/patches/0020-Add-extra-tests-for-database-corruption-inside-defra.patch
deleted file mode 100644
index b4d050318b9..00000000000
--- a/chromium/third_party/sqlite/patches/0020-Add-extra-tests-for-database-corruption-inside-defra.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sat, 12 Jan 2019 17:56:03 -0800
-Subject: [PATCH 20/40] Add extra tests for database corruption inside
- defragmentPage().
-
-This backports https://sqlite.org/src/info/997b65117f8c12db
-
-Bug: 921355
----
- third_party/sqlite/src/src/btree.c | 20 ++++++++------------
- 1 file changed, 8 insertions(+), 12 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 14af51e15ab2..aee43cccde46 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -1424,18 +1424,14 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
- ** reconstruct the entire page. */
- if( (int)data[hdr+7]<=nMaxFrag ){
- int iFree = get2byte(&data[hdr+1]);
-+
-+ /* If the initial freeblock offset were out of bounds, that would
-+ ** have been detected by btreeInitPage() when it was computing the
-+ ** number of free bytes on the page. */
-+ assert( iFree<=usableSize-4 );
- if( iFree ){
- int iFree2 = get2byte(&data[iFree]);
--
-- /* pageFindSlot() has already verified that free blocks are sorted
-- ** in order of offset within the page, and that no block extends
-- ** past the end of the page. Provided the two free slots do not
-- ** overlap, this guarantees that the memmove() calls below will not
-- ** overwrite the usableSize byte buffer, even if the database page
-- ** is corrupt. */
-- assert( iFree2==0 || iFree2>iFree );
-- assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
-- assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
-+ if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
-
- if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
- u8 *pEnd = &data[cellOffset + nCell*2];
-@@ -1447,9 +1443,9 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
- if( iFree2 ){
-- assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
-+ if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
- sz2 = get2byte(&data[iFree2+2]);
-- assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
-+ if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
- memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
- sz += sz2;
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0021-Fix-an-off-by-one-error-on-a-Goto-in-the-code-genera.patch b/chromium/third_party/sqlite/patches/0021-Fix-an-off-by-one-error-on-a-Goto-in-the-code-genera.patch
deleted file mode 100644
index 2ed2dd9b83b..00000000000
--- a/chromium/third_party/sqlite/patches/0021-Fix-an-off-by-one-error-on-a-Goto-in-the-code-genera.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sat, 12 Jan 2019 18:04:58 -0800
-Subject: [PATCH 21/40] Fix an off-by-one error on a Goto in the code
- generator.
-
-This backports https://www.sqlite.org/src/info/e35eb8776ed539af
-
-Bug: 914507, 914648
----
- third_party/sqlite/src/src/insert.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/insert.c b/third_party/sqlite/src/src/insert.c
-index cd2eec12864e..a834f3918439 100644
---- a/third_party/sqlite/src/src/insert.c
-+++ b/third_party/sqlite/src/src/insert.c
-@@ -1824,7 +1824,7 @@ void sqlite3GenerateConstraintChecks(
-
- /* If the IPK constraint is a REPLACE, run it last */
- if( ipkTop ){
-- sqlite3VdbeGoto(v, ipkTop+1);
-+ sqlite3VdbeGoto(v, ipkTop);
- VdbeComment((v, "Do IPK REPLACE"));
- sqlite3VdbeJumpHere(v, ipkBottom);
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0022-Fix-overread-on-corrupted-btree-key.patch b/chromium/third_party/sqlite/patches/0022-Fix-overread-on-corrupted-btree-key.patch
deleted file mode 100644
index 315ba67c5b2..00000000000
--- a/chromium/third_party/sqlite/patches/0022-Fix-overread-on-corrupted-btree-key.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sun, 13 Jan 2019 13:36:26 -0800
-Subject: [PATCH 22/40] Fix overread on corrupted btree key.
-
-This backports https://sqlite.org/src/info/160b1e31c0f27257
-
-Bug: 914155
----
- third_party/sqlite/src/src/btree.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index aee43cccde46..1f1c9e0402c8 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -660,10 +660,15 @@ static int saveCursorKey(BtCursor *pCur){
- /* Only the rowid is required for a table btree */
- pCur->nKey = sqlite3BtreeIntegerKey(pCur);
- }else{
-- /* For an index btree, save the complete key content */
-+ /* For an index btree, save the complete key content. It is possible
-+ ** that the current key is corrupt. In that case, it is possible that
-+ ** the sqlite3VdbeRecordUnpack() function may overread the buffer by
-+ ** up to the size of 1 varint plus 1 8-byte value when the cursor
-+ ** position is restored. Hence the 17 bytes of padding allocated
-+ ** below. */
- void *pKey;
- pCur->nKey = sqlite3BtreePayloadSize(pCur);
-- pKey = sqlite3Malloc( pCur->nKey );
-+ pKey = sqlite3Malloc( pCur->nKey + 9 + 8 );
- if( pKey ){
- rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
- if( rc==SQLITE_OK ){
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0023-Avoid-buffer-overreads-on-corrupted-database-files.patch b/chromium/third_party/sqlite/patches/0023-Avoid-buffer-overreads-on-corrupted-database-files.patch
deleted file mode 100644
index ea5da8995e7..00000000000
--- a/chromium/third_party/sqlite/patches/0023-Avoid-buffer-overreads-on-corrupted-database-files.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sun, 13 Jan 2019 15:17:27 -0800
-Subject: [PATCH 23/40] Avoid buffer overreads on corrupted database files.
-
-This backports https://sqlite.org/src/info/32754ca6f86da816
-
-Bug: 914022, 914023
----
- third_party/sqlite/src/src/pcache1.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/pcache1.c b/third_party/sqlite/src/src/pcache1.c
-index 1986b22ca61c..4fd6cb7bed39 100644
---- a/third_party/sqlite/src/src/pcache1.c
-+++ b/third_party/sqlite/src/src/pcache1.c
-@@ -477,7 +477,10 @@ static void pcache1FreePage(PgHdr1 *p){
- ** exists, this function falls back to sqlite3Malloc().
- */
- void *sqlite3PageMalloc(int sz){
-- return pcache1Alloc(sz);
-+ /* During rebalance operations on a corrupt database file, it is sometimes
-+ ** (rarely) possible to overread the temporary page buffer by a few bytes.
-+ ** Enlarge the allocation slightly so that this does not cause problems. */
-+ return pcache1Alloc(sz + 32);
- }
-
- /*
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0024-Fix-integer-overflow-while-running-PRAGMA-integrity_.patch b/chromium/third_party/sqlite/patches/0024-Fix-integer-overflow-while-running-PRAGMA-integrity_.patch
deleted file mode 100644
index 01912a037e4..00000000000
--- a/chromium/third_party/sqlite/patches/0024-Fix-integer-overflow-while-running-PRAGMA-integrity_.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sun, 13 Jan 2019 16:12:08 -0800
-Subject: [PATCH 24/40] Fix integer overflow while running PRAGMA
- integrity_check.
-
-This backports https://sqlite.org/src/info/395599116d801324
-
-Bug: 913235
----
- third_party/sqlite/src/src/btree.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 1f1c9e0402c8..eb7d8d0cb6bd 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -9414,7 +9414,7 @@ static void checkList(
- }
- pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
- if( isFreeList ){
-- int n = get4byte(&pOvflData[4]);
-+ u32 n = (u32)get4byte(&pOvflData[4]);
- #ifndef SQLITE_OMIT_AUTOVACUUM
- if( pCheck->pBt->autoVacuum ){
- checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0);
-@@ -9425,7 +9425,7 @@ static void checkList(
- "freelist leaf count too big on page %d", iPage);
- N--;
- }else{
-- for(i=0; i<n; i++){
-+ for(i=0; i<(int)n; i++){
- Pgno iFreePage = get4byte(&pOvflData[8+i*4]);
- #ifndef SQLITE_OMIT_AUTOVACUUM
- if( pCheck->pBt->autoVacuum ){
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0025-Improved-corruption-handling-while-balancing-pages.patch b/chromium/third_party/sqlite/patches/0025-Improved-corruption-handling-while-balancing-pages.patch
deleted file mode 100644
index d8e9a64a4da..00000000000
--- a/chromium/third_party/sqlite/patches/0025-Improved-corruption-handling-while-balancing-pages.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sun, 13 Jan 2019 18:06:01 -0800
-Subject: [PATCH 25/40] Improved corruption handling while balancing pages.
-
-This backports https://www.sqlite.org/src/info/35f04235c4775013
-
-Bug: 921348
----
- third_party/sqlite/src/src/btree.c | 31 +++++++++++++++---------------
- 1 file changed, 15 insertions(+), 16 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index eb7d8d0cb6bd..5713bd09e49f 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -1066,7 +1066,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
- #else /* if defined SQLITE_OMIT_AUTOVACUUM */
- #define ptrmapPut(w,x,y,z,rc)
- #define ptrmapGet(w,x,y,z) SQLITE_OK
-- #define ptrmapPutOvflPtr(x, y, rc)
-+ #define ptrmapPutOvflPtr(x, y, z, rc)
- #endif
-
- /*
-@@ -1359,18 +1359,20 @@ static u16 cellSize(MemPage *pPage, int iCell){
-
- #ifndef SQLITE_OMIT_AUTOVACUUM
- /*
--** If the cell pCell, part of page pPage contains a pointer
--** to an overflow page, insert an entry into the pointer-map
--** for the overflow page.
-+** The cell pCell is currently part of page pSrc but will ultimately be part
-+** of pPage. (pSrc and pPager are often the same.) If pCell contains a
-+** pointer to an overflow page, insert an entry into the pointer-map for
-+** the overflow page that will be valid after pCell has been moved to pPage.
- */
--static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
-+static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell, int *pRC){
- CellInfo info;
- if( *pRC ) return;
- assert( pCell!=0 );
- pPage->xParseCell(pPage, pCell, &info);
- if( info.nLocal<info.nPayload ){
- Pgno ovfl;
-- if( SQLITE_WITHIN(pPage->aDataEnd, pCell, pCell+info.nLocal) ){
-+ if( SQLITE_WITHIN(pSrc->aDataEnd, pCell, pCell+info.nLocal) ){
-+ testcase( pSrc!=pPage );
- *pRC = SQLITE_CORRUPT_BKPT;
- return;
- }
-@@ -3491,7 +3493,7 @@ static int setChildPtrmaps(MemPage *pPage){
- for(i=0; i<nCell; i++){
- u8 *pCell = findCell(pPage, i);
-
-- ptrmapPutOvflPtr(pPage, pCell, &rc);
-+ ptrmapPutOvflPtr(pPage, pPage, pCell, &rc);
-
- if( !pPage->leaf ){
- Pgno childPgno = get4byte(pCell);
-@@ -6676,7 +6678,7 @@ static void insertCell(
- /* The cell may contain a pointer to an overflow page. If so, write
- ** the entry for the overflow page into the pointer map.
- */
-- ptrmapPutOvflPtr(pPage, pCell, pRC);
-+ ptrmapPutOvflPtr(pPage, pPage, pCell, pRC);
- }
- #endif
- }
-@@ -7092,7 +7094,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
- if( ISAUTOVACUUM ){
- ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno, &rc);
- if( szCell>pNew->minLocal ){
-- ptrmapPutOvflPtr(pNew, pCell, &rc);
-+ ptrmapPutOvflPtr(pNew, pNew, pCell, &rc);
- }
- }
-
-@@ -7315,10 +7317,6 @@ static int balance_nonroot(
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
-
--#if 0
-- TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
--#endif
--
- /* At this point pParent may have at most one overflow cell. And if
- ** this overflow cell is present, it must be the cell with
- ** index iParentIdx. This scenario comes about when this function
-@@ -7784,7 +7782,8 @@ static int balance_nonroot(
- ** populated, not here.
- */
- if( ISAUTOVACUUM ){
-- MemPage *pNew = apNew[0];
-+ MemPage *pOld;
-+ MemPage *pNew = pOld = apNew[0];
- u8 *aOld = pNew->aData;
- int cntOldNext = pNew->nCell + pNew->nOverflow;
- int usableSize = pBt->usableSize;
-@@ -7794,7 +7793,7 @@ static int balance_nonroot(
- for(i=0; i<b.nCell; i++){
- u8 *pCell = b.apCell[i];
- if( i==cntOldNext ){
-- MemPage *pOld = (++iOld)<nNew ? apNew[iOld] : apOld[iOld];
-+ pOld = (++iOld)<nNew ? apNew[iOld] : apOld[iOld];
- cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;
- aOld = pOld->aData;
- }
-@@ -7817,7 +7816,7 @@ static int balance_nonroot(
- ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
- }
- if( cachedCellSize(&b,i)>pNew->minLocal ){
-- ptrmapPutOvflPtr(pNew, pCell, &rc);
-+ ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
- }
- if( rc ) goto balance_cleanup;
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0026-Avoid-reading-off-the-front-of-a-page-buffer-when-ba.patch b/chromium/third_party/sqlite/patches/0026-Avoid-reading-off-the-front-of-a-page-buffer-when-ba.patch
deleted file mode 100644
index 3cbd94d874b..00000000000
--- a/chromium/third_party/sqlite/patches/0026-Avoid-reading-off-the-front-of-a-page-buffer-when-ba.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sun, 13 Jan 2019 23:10:51 -0800
-Subject: [PATCH 26/40] Avoid reading off the front of a page buffer when
- balancing a corrupt btree.
-
-This backports https://www.sqlite.org/src/info/cb50509020d952fa
-
-Bug: 914027
----
- third_party/sqlite/src/src/btree.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 5713bd09e49f..13342288934d 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -6662,9 +6662,16 @@ static void insertCell(
- assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB );
- assert( idx+sz <= (int)pPage->pBt->usableSize );
- pPage->nFree -= (u16)(2 + sz);
-- memcpy(&data[idx], pCell, sz);
- if( iChild ){
-+ /* In a corrupt database where an entry in the cell index section of
-+ ** a btree page has a value of 3 or less, the pCell value might point
-+ ** as many as 4 bytes in front of the start of the aData buffer for
-+ ** the source page. Make sure this does not cause problems by not
-+ ** reading the first 4 bytes */
-+ memcpy(&data[idx+4], pCell+4, sz-4);
- put4byte(&data[idx], iChild);
-+ }else{
-+ memcpy(&data[idx], pCell, sz);
- }
- pIns = pPage->aCellIdx + i*2;
- memmove(pIns+2, pIns, 2*(pPage->nCell - i));
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0027-Fix-MSAN-error-in-sqlite3VdbeRecordUnpack-on-a-corru.patch b/chromium/third_party/sqlite/patches/0027-Fix-MSAN-error-in-sqlite3VdbeRecordUnpack-on-a-corru.patch
deleted file mode 100644
index f3eecc7aaaa..00000000000
--- a/chromium/third_party/sqlite/patches/0027-Fix-MSAN-error-in-sqlite3VdbeRecordUnpack-on-a-corru.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Mon, 14 Jan 2019 12:32:04 -0800
-Subject: [PATCH 27/40] Fix MSAN error in sqlite3VdbeRecordUnpack() on a
- corrupt record.
-
-This backports https://www.sqlite.org/src/info/ddc3697efd61830f
-
-Bug: 914970
----
- third_party/sqlite/src/src/vdbeaux.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/third_party/sqlite/src/src/vdbeaux.c b/third_party/sqlite/src/src/vdbeaux.c
-index 9ba127360fea..1e9812288cfa 100644
---- a/third_party/sqlite/src/src/vdbeaux.c
-+++ b/third_party/sqlite/src/src/vdbeaux.c
-@@ -3734,6 +3734,13 @@ void sqlite3VdbeRecordUnpack(
- pMem++;
- if( (++u)>=p->nField ) break;
- }
-+ if( d>nKey && u ){
-+ assert( CORRUPT_DB );
-+ /* In a corrupt record entry, the last pMem might have been set up using
-+ ** uninitialized memory. Overwrite its value with NULL, to prevent
-+ ** warnings from MSAN. */
-+ sqlite3VdbeMemSetNull(pMem-1);
-+ }
- assert( u<=pKeyInfo->nKeyField + 1 );
- p->nField = u;
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0028-Fix-deleting-a-B-tree-entry-in-a-corrupt-database.patch b/chromium/third_party/sqlite/patches/0028-Fix-deleting-a-B-tree-entry-in-a-corrupt-database.patch
deleted file mode 100644
index a5de315c0df..00000000000
--- a/chromium/third_party/sqlite/patches/0028-Fix-deleting-a-B-tree-entry-in-a-corrupt-database.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Tue, 15 Jan 2019 20:35:58 -0800
-Subject: [PATCH 28/40] Fix deleting a B-tree entry in a corrupt database.
-
-This backports https://sqlite.org/src/info/682053d1e603c21b
-
-Bug: 921894
----
- third_party/sqlite/src/src/btree.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 13342288934d..9b5745558514 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -8642,6 +8642,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
- if( bPreserve ){
- if( !pPage->leaf
- || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
-+ || pPage->nCell==1 /* See dbfuzz001.test for a test case */
- ){
- /* A b-tree rebalance will be required after deleting this entry.
- ** Save the cursor key. */
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0029-Fix-sorting-results-with-SRT_EphemTab-and-a-LIMIT-cl.patch b/chromium/third_party/sqlite/patches/0029-Fix-sorting-results-with-SRT_EphemTab-and-a-LIMIT-cl.patch
deleted file mode 100644
index 34eb6b470e9..00000000000
--- a/chromium/third_party/sqlite/patches/0029-Fix-sorting-results-with-SRT_EphemTab-and-a-LIMIT-cl.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Wed, 16 Jan 2019 12:46:56 -0800
-Subject: [PATCH 29/40] Fix sorting results with SRT_EphemTab and a LIMIT
- clause.
-
-This backports https://www.sqlite.org/src/info/49fcde2f1f981ac0
-
-Bug: 922312
----
- third_party/sqlite/src/src/select.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/select.c b/third_party/sqlite/src/src/select.c
-index fab4df68fa17..c68c1ddc643d 100644
---- a/third_party/sqlite/src/src/select.c
-+++ b/third_party/sqlite/src/src/select.c
-@@ -1457,7 +1457,12 @@ static void generateSortTail(
- regRow = pDest->iSdst;
- }else{
- regRowid = sqlite3GetTempReg(pParse);
-- regRow = sqlite3GetTempRange(pParse, nColumn);
-+ if( eDest==SRT_EphemTab || eDest==SRT_Table ){
-+ regRow = sqlite3GetTempReg(pParse);
-+ nColumn = 0;
-+ }else{
-+ regRow = sqlite3GetTempRange(pParse, nColumn);
-+ }
- }
- nKey = pOrderBy->nExpr - pSort->nOBSat;
- if( pSort->sortFlags & SORTFLAG_UseSorter ){
-@@ -1537,6 +1542,7 @@ static void generateSortTail(
- switch( eDest ){
- case SRT_Table:
- case SRT_EphemTab: {
-+ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq, regRow);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0030-Fix-detection-of-orphaned-and-malformed-autoindexes.patch b/chromium/third_party/sqlite/patches/0030-Fix-detection-of-orphaned-and-malformed-autoindexes.patch
deleted file mode 100644
index e2529c39fe6..00000000000
--- a/chromium/third_party/sqlite/patches/0030-Fix-detection-of-orphaned-and-malformed-autoindexes.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Wed, 16 Jan 2019 13:07:12 -0800
-Subject: [PATCH 30/40] Fix detection of orphaned and malformed autoindexes.
-
-This backports https://sqlite.org/src/info/10f9e39d6ed2413f
-
-Bug: 922213
----
- third_party/sqlite/src/src/prepare.c | 14 +++++---------
- 1 file changed, 5 insertions(+), 9 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/prepare.c b/third_party/sqlite/src/src/prepare.c
-index fe098cfa092e..cdf6f65bb115 100644
---- a/third_party/sqlite/src/src/prepare.c
-+++ b/third_party/sqlite/src/src/prepare.c
-@@ -118,15 +118,11 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
- */
- Index *pIndex;
- pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
-- if( pIndex==0 ){
-- /* This can occur if there exists an index on a TEMP table which
-- ** has the same name as another index on a permanent index. Since
-- ** the permanent table is hidden by the TEMP table, we can also
-- ** safely ignore the index on the permanent table.
-- */
-- /* Do Nothing */;
-- }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){
-- corruptSchema(pData, argv[0], "invalid rootpage");
-+ if( pIndex==0
-+ || sqlite3GetInt32(argv[1],&pIndex->tnum)==0
-+ || pIndex->tnum<2
-+ ){
-+ corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
- }
- }
- return 0;
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0031-Fix-potential-buffer-overread.patch b/chromium/third_party/sqlite/patches/0031-Fix-potential-buffer-overread.patch
deleted file mode 100644
index c933c09eb1d..00000000000
--- a/chromium/third_party/sqlite/patches/0031-Fix-potential-buffer-overread.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Fri, 18 Jan 2019 23:20:17 -0800
-Subject: [PATCH 31/40] Fix potential buffer overread.
-
-This backports https://sqlite.org/src/info/8ba3d9f38090c4bb
-
-Bug: 923196
----
- third_party/sqlite/src/src/btree.c | 1 +
- third_party/sqlite/src/src/pcache1.c | 2 +-
- 2 files changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 9b5745558514..5eb83736533a 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -6772,6 +6772,7 @@ static int rebuildPage(
- for(i=0; i<nCell; i++){
- u8 *pCell = apCell[i];
- if( SQLITE_WITHIN(pCell,aData,pEnd) ){
-+ if( ((uptr)(pCell+szCell[i]))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
- pCell = &pTmp[pCell - aData];
- }
- pData -= szCell[i];
-diff --git a/third_party/sqlite/src/src/pcache1.c b/third_party/sqlite/src/src/pcache1.c
-index 4fd6cb7bed39..05ef4bde330b 100644
---- a/third_party/sqlite/src/src/pcache1.c
-+++ b/third_party/sqlite/src/src/pcache1.c
-@@ -480,7 +480,7 @@ void *sqlite3PageMalloc(int sz){
- /* During rebalance operations on a corrupt database file, it is sometimes
- ** (rarely) possible to overread the temporary page buffer by a few bytes.
- ** Enlarge the allocation slightly so that this does not cause problems. */
-- return pcache1Alloc(sz + 32);
-+ return pcache1Alloc(sz);
- }
-
- /*
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0032-Fix-handling-negative-number-of-pages-database-field.patch b/chromium/third_party/sqlite/patches/0032-Fix-handling-negative-number-of-pages-database-field.patch
deleted file mode 100644
index 7111acbfd28..00000000000
--- a/chromium/third_party/sqlite/patches/0032-Fix-handling-negative-number-of-pages-database-field.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sat, 19 Jan 2019 02:33:28 -0800
-Subject: [PATCH 32/40] Fix handling negative "number-of-pages" database field.
-
-This backports https://www.sqlite.org/src/info/556dd8922f
-
-Bug: 922849
----
- third_party/sqlite/src/src/btree.c | 8 ++++----
- third_party/sqlite/src/src/build.c | 16 +++++++++-------
- 2 files changed, 13 insertions(+), 11 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 5eb83736533a..dbff913299a9 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -3007,9 +3007,9 @@ static int newDatabase(BtShared*);
- static int lockBtree(BtShared *pBt){
- int rc; /* Result code from subfunctions */
- MemPage *pPage1; /* Page 1 of the database file */
-- int nPage; /* Number of pages in the database */
-- int nPageFile = 0; /* Number of pages in the database file */
-- int nPageHeader; /* Number of pages in the database according to hdr */
-+ u32 nPage; /* Number of pages in the database */
-+ u32 nPageFile = 0; /* Number of pages in the database file */
-+ u32 nPageHeader; /* Number of pages in the database according to hdr */
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pBt->pPage1==0 );
-@@ -3022,7 +3022,7 @@ static int lockBtree(BtShared *pBt){
- ** a valid database file.
- */
- nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
-- sqlite3PagerPagecount(pBt->pPager, &nPageFile);
-+ sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
- if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
- nPage = nPageFile;
- }
-diff --git a/third_party/sqlite/src/src/build.c b/third_party/sqlite/src/src/build.c
-index 806c89f439bf..5939fa9974a8 100644
---- a/third_party/sqlite/src/src/build.c
-+++ b/third_party/sqlite/src/src/build.c
-@@ -4417,13 +4417,15 @@ static int collationMatch(const char *zColl, Index *pIndex){
- */
- #ifndef SQLITE_OMIT_REINDEX
- static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
-- Index *pIndex; /* An index associated with pTab */
--
-- for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
-- if( zColl==0 || collationMatch(zColl, pIndex) ){
-- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
-- sqlite3BeginWriteOperation(pParse, 0, iDb);
-- sqlite3RefillIndex(pParse, pIndex, -1);
-+ if (! IsVirtual(pTab) ){
-+ Index *pIndex; /* An index associated with pTab */
-+
-+ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
-+ if( zColl==0 || collationMatch(zColl, pIndex) ){
-+ int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
-+ sqlite3BeginWriteOperation(pParse, 0, iDb);
-+ sqlite3RefillIndex(pParse, pIndex, -1);
-+ }
- }
- }
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0033-Fix-corner-case-in-inserting-null-into-integer-prima.patch b/chromium/third_party/sqlite/patches/0033-Fix-corner-case-in-inserting-null-into-integer-prima.patch
deleted file mode 100644
index 77dbd02f020..00000000000
--- a/chromium/third_party/sqlite/patches/0033-Fix-corner-case-in-inserting-null-into-integer-prima.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sat, 19 Jan 2019 14:27:29 -0800
-Subject: [PATCH 33/40] Fix corner case in inserting null into integer primary
- key.
-
-This backports https://www.sqlite.org/src/info/9a425051e7ba59e7
-
-Bug: 922844
----
- third_party/sqlite/src/src/insert.c | 14 +++++---------
- 1 file changed, 5 insertions(+), 9 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/insert.c b/third_party/sqlite/src/src/insert.c
-index a834f3918439..2dd4d8227a6c 100644
---- a/third_party/sqlite/src/src/insert.c
-+++ b/third_party/sqlite/src/src/insert.c
-@@ -947,16 +947,12 @@ void sqlite3Insert(
- }else if( pSelect ){
- sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
- }else{
-- VdbeOp *pOp;
-- sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
-- pOp = sqlite3VdbeGetOp(v, -1);
-- assert( pOp!=0 );
-- if( pOp->opcode==OP_Null && !IsVirtual(pTab) ){
-+ Expr *pIpk = pList->a[ipkColumn].pExpr;
-+ if( pIpk->op==TK_NULL && !IsVirtual(pTab) ){
-+ sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
- appendFlag = 1;
-- pOp->opcode = OP_NewRowid;
-- pOp->p1 = iDataCur;
-- pOp->p2 = regRowid;
-- pOp->p3 = regAutoinc;
-+ }else{
-+ sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
- }
- }
- /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0034-Fix-insert-infinite-recursion-on-some-corrupted-data.patch b/chromium/third_party/sqlite/patches/0034-Fix-insert-infinite-recursion-on-some-corrupted-data.patch
deleted file mode 100644
index 8ff6e693947..00000000000
--- a/chromium/third_party/sqlite/patches/0034-Fix-insert-infinite-recursion-on-some-corrupted-data.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sat, 19 Jan 2019 15:39:26 -0800
-Subject: [PATCH 34/40] Fix insert infinite recursion on some corrupted
- databases.
-
-This backports https://www.sqlite.org/src/info/f31b3bd2a6a8aa35
-
-Bug: 921684
----
- third_party/sqlite/src/src/insert.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/insert.c b/third_party/sqlite/src/src/insert.c
-index 2dd4d8227a6c..b21bf714923a 100644
---- a/third_party/sqlite/src/src/insert.c
-+++ b/third_party/sqlite/src/src/insert.c
-@@ -2190,7 +2190,8 @@ static int xferOptimization(
- if( pSrc==0 ){
- return 0; /* FROM clause does not contain a real table */
- }
-- if( pSrc==pDest ){
-+ if( pSrc->tnum==pDest->tnum && pSrc->pSchema==pDest->pSchema ){
-+ testcase( pSrc!=pDest ); /* Possible due to bad sqlite_master.rootpage */
- return 0; /* tab1 and tab2 may not be the same table */
- }
- if( HasRowid(pDest)!=HasRowid(pSrc) ){
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0035-Fix-null-pointer-dereference-in-sqlite3ExprCompare.patch b/chromium/third_party/sqlite/patches/0035-Fix-null-pointer-dereference-in-sqlite3ExprCompare.patch
deleted file mode 100644
index 8afbbd97b30..00000000000
--- a/chromium/third_party/sqlite/patches/0035-Fix-null-pointer-dereference-in-sqlite3ExprCompare.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Sat, 19 Jan 2019 15:48:54 -0800
-Subject: [PATCH 35/40] Fix null pointer dereference in sqlite3ExprCompare.
-
-This backports https://www.sqlite.org/src/info/835e2cc55feea2f2
-
-Bug: 921417
----
- third_party/sqlite/src/src/expr.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
-index c61528288baf..50c398266f33 100644
---- a/third_party/sqlite/src/src/expr.c
-+++ b/third_party/sqlite/src/src/expr.c
-@@ -4748,9 +4748,11 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
- if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2;
- }
- #endif
-+ }else if( pA->op==TK_NULL ){
-+ return 0;
- }else if( pA->op==TK_COLLATE ){
- if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
-- }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
-+ }else if( ALWAYS(pB->u.zToken!=0) && strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
- return 2;
- }
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0036-Fix-NEVER-that-is-sometimes-true.patch b/chromium/third_party/sqlite/patches/0036-Fix-NEVER-that-is-sometimes-true.patch
deleted file mode 100644
index 9d1bedac82d..00000000000
--- a/chromium/third_party/sqlite/patches/0036-Fix-NEVER-that-is-sometimes-true.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Mon, 21 Jan 2019 14:26:47 -0800
-Subject: [PATCH 36/40] Fix NEVER that is sometimes true.
-
-This backports https://sqlite.org/src/info/1201615cbbd30701
-
-Bug: 923715
----
- third_party/sqlite/src/src/btree.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index dbff913299a9..cc4de24d79db 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -7067,8 +7067,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
- assert( pPage->nOverflow==1 );
-
-- /* This error condition is now caught prior to reaching this function */
-- if( NEVER(pPage->nCell==0) ) return SQLITE_CORRUPT_BKPT;
-+ if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; /* dbfuzz001.test */
-
- /* Allocate a new page. This page will become the right-sibling of
- ** pPage. Make the parent page writable, so that the new divider cell
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0037-Initialize-extra-bytes-allocated-for-saved-cursor-po.patch b/chromium/third_party/sqlite/patches/0037-Initialize-extra-bytes-allocated-for-saved-cursor-po.patch
deleted file mode 100644
index a281eb69f02..00000000000
--- a/chromium/third_party/sqlite/patches/0037-Initialize-extra-bytes-allocated-for-saved-cursor-po.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Mon, 21 Jan 2019 14:32:00 -0800
-Subject: [PATCH 37/40] Initialize extra bytes allocated for saved cursor
- position.
-
-This backports https://www.sqlite.org/src/info/2737564929e86ead
-
-Bug: 923743
----
- third_party/sqlite/src/src/btree.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index cc4de24d79db..3b018b5cc3c8 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -672,6 +672,7 @@ static int saveCursorKey(BtCursor *pCur){
- if( pKey ){
- rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
- if( rc==SQLITE_OK ){
-+ memset(((u8*)pKey)+pCur->nKey, 0, 9+8);
- pCur->pKey = pKey;
- }else{
- sqlite3_free(pKey);
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0038-Fix-leaks-caused-by-circular-references-in-vtable-sh.patch b/chromium/third_party/sqlite/patches/0038-Fix-leaks-caused-by-circular-references-in-vtable-sh.patch
deleted file mode 100644
index 4cf0bbb27a3..00000000000
--- a/chromium/third_party/sqlite/patches/0038-Fix-leaks-caused-by-circular-references-in-vtable-sh.patch
+++ /dev/null
@@ -1,246 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Mon, 21 Jan 2019 14:57:17 -0800
-Subject: [PATCH 38/40] Fix leaks caused by circular references in vtable
- shadow tables.
-
-This backports https://sqlite.org/src/info/da587d18575ac06a
-
-Bug: 914028, 917075, 917786, 922399
----
- third_party/sqlite/src/ext/fts3/fts3_write.c | 5 +--
- third_party/sqlite/src/ext/fts5/fts5_index.c | 16 ++-------
- .../sqlite/src/ext/fts5/fts5_storage.c | 5 +--
- third_party/sqlite/src/ext/rtree/rtree.c | 7 ++--
- third_party/sqlite/src/src/build.c | 34 +++++++++++--------
- third_party/sqlite/src/src/prepare.c | 1 +
- third_party/sqlite/src/src/sqlite.h.in | 6 ++++
- third_party/sqlite/src/src/sqliteInt.h | 1 +
- third_party/sqlite/src/src/trigger.c | 1 +
- 9 files changed, 41 insertions(+), 35 deletions(-)
-
-diff --git a/third_party/sqlite/src/ext/fts3/fts3_write.c b/third_party/sqlite/src/ext/fts3/fts3_write.c
-index fc599a0c3e04..9bc6d70f45cb 100644
---- a/third_party/sqlite/src/ext/fts3/fts3_write.c
-+++ b/third_party/sqlite/src/ext/fts3/fts3_write.c
-@@ -396,10 +396,12 @@ static int fts3SqlStmt(
-
- pStmt = p->aStmt[eStmt];
- if( !pStmt ){
-+ int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
- char *zSql;
- if( eStmt==SQL_CONTENT_INSERT ){
- zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName, p->zWriteExprlist);
- }else if( eStmt==SQL_SELECT_CONTENT_BY_ROWID ){
-+ f &= ~SQLITE_PREPARE_NO_VTAB;
- zSql = sqlite3_mprintf(azSql[eStmt], p->zReadExprlist);
- }else{
- zSql = sqlite3_mprintf(azSql[eStmt], p->zDb, p->zName);
-@@ -407,8 +409,7 @@ static int fts3SqlStmt(
- if( !zSql ){
- rc = SQLITE_NOMEM;
- }else{
-- rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
-- &pStmt, NULL);
-+ rc = sqlite3_prepare_v3(p->db, zSql, -1, f, &pStmt, NULL);
- sqlite3_free(zSql);
- assert( rc==SQLITE_OK || pStmt==0 );
- p->aStmt[eStmt] = pStmt;
-diff --git a/third_party/sqlite/src/ext/fts5/fts5_index.c b/third_party/sqlite/src/ext/fts5/fts5_index.c
-index 833b5e283644..7cacf930cc85 100644
---- a/third_party/sqlite/src/ext/fts5/fts5_index.c
-+++ b/third_party/sqlite/src/ext/fts5/fts5_index.c
-@@ -729,7 +729,8 @@ static int fts5IndexPrepareStmt(
- if( p->rc==SQLITE_OK ){
- if( zSql ){
- p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
-- SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
-+ SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB,
-+ ppStmt, 0);
- }else{
- p->rc = SQLITE_NOMEM;
- }
-@@ -770,23 +771,12 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
- if( p->rc!=SQLITE_OK ) return;
-
- if( p->pDeleter==0 ){
-- int rc;
- Fts5Config *pConfig = p->pConfig;
- char *zSql = sqlite3_mprintf(
- "DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?",
- pConfig->zDb, pConfig->zName
- );
-- if( zSql==0 ){
-- rc = SQLITE_NOMEM;
-- }else{
-- rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
-- SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
-- sqlite3_free(zSql);
-- }
-- if( rc!=SQLITE_OK ){
-- p->rc = rc;
-- return;
-- }
-+ if( fts5IndexPrepareStmt(p, &p->pDeleter, zSql) ) return;
- }
-
- sqlite3_bind_int64(p->pDeleter, 1, iFirst);
-diff --git a/third_party/sqlite/src/ext/fts5/fts5_storage.c b/third_party/sqlite/src/ext/fts5/fts5_storage.c
-index 8424f9d536b2..1f08a9a7a848 100644
---- a/third_party/sqlite/src/ext/fts5/fts5_storage.c
-+++ b/third_party/sqlite/src/ext/fts5/fts5_storage.c
-@@ -136,8 +136,9 @@ static int fts5StorageGetStmt(
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
-- rc = sqlite3_prepare_v3(pC->db, zSql, -1,
-- SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
-+ int f = SQLITE_PREPARE_PERSISTENT;
-+ if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
-+ rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
- sqlite3_free(zSql);
- if( rc!=SQLITE_OK && pzErrMsg ){
- *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
-diff --git a/third_party/sqlite/src/ext/rtree/rtree.c b/third_party/sqlite/src/ext/rtree/rtree.c
-index 9c436d5989e5..e09db482279e 100644
---- a/third_party/sqlite/src/ext/rtree/rtree.c
-+++ b/third_party/sqlite/src/ext/rtree/rtree.c
-@@ -3395,6 +3395,7 @@ static int rtreeSqlInit(
- };
- sqlite3_stmt **appStmt[N_STATEMENT];
- int i;
-+ const int f = SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_NO_VTAB;
-
- pRtree->db = db;
-
-@@ -3451,8 +3452,7 @@ static int rtreeSqlInit(
- }
- zSql = sqlite3_mprintf(zFormat, zDb, zPrefix);
- if( zSql ){
-- rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
-- appStmt[i], 0);
-+ rc = sqlite3_prepare_v3(db, zSql, -1, f, appStmt[i], 0);
- }else{
- rc = SQLITE_NOMEM;
- }
-@@ -3482,8 +3482,7 @@ static int rtreeSqlInit(
- if( zSql==0 ){
- rc = SQLITE_NOMEM;
- }else{
-- rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
-- &pRtree->pWriteAux, 0);
-+ rc = sqlite3_prepare_v3(db, zSql, -1, f, &pRtree->pWriteAux, 0);
- sqlite3_free(zSql);
- }
- }
-diff --git a/third_party/sqlite/src/src/build.c b/third_party/sqlite/src/src/build.c
-index 5939fa9974a8..e6e48875d129 100644
---- a/third_party/sqlite/src/src/build.c
-+++ b/third_party/sqlite/src/src/build.c
-@@ -354,26 +354,32 @@ Table *sqlite3LocateTable(
-
- p = sqlite3FindTable(db, zName, zDbase);
- if( p==0 ){
-- const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
- #ifndef SQLITE_OMIT_VIRTUALTABLE
- /* If zName is the not the name of a table in the schema created using
- ** CREATE, then check to see if it is the name of an virtual table that
- ** can be an eponymous virtual table. */
-- Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
-- if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
-- pMod = sqlite3PragmaVtabRegister(db, zName);
-- }
-- if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
-- return pMod->pEpoTab;
-+ if( pParse->disableVtab==0 ){
-+ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
-+ if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
-+ pMod = sqlite3PragmaVtabRegister(db, zName);
-+ }
-+ if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
-+ return pMod->pEpoTab;
-+ }
- }
- #endif
-- if( (flags & LOCATE_NOERR)==0 ){
-- if( zDbase ){
-- sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
-- }else{
-- sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
-- }
-- pParse->checkSchema = 1;
-+ if( flags & LOCATE_NOERR ) return 0;
-+ pParse->checkSchema = 1;
-+ }else if( IsVirtual(p) && pParse->disableVtab ){
-+ p = 0;
-+ }
-+
-+ if( p==0 ){
-+ const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
-+ if( zDbase ){
-+ sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
-+ }else{
-+ sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
- }
- }
-
-diff --git a/third_party/sqlite/src/src/prepare.c b/third_party/sqlite/src/src/prepare.c
-index cdf6f65bb115..87711315a0c0 100644
---- a/third_party/sqlite/src/src/prepare.c
-+++ b/third_party/sqlite/src/src/prepare.c
-@@ -541,6 +541,7 @@ static int sqlite3Prepare(
- sParse.disableLookaside++;
- db->lookaside.bDisable++;
- }
-+ sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0;
-
- /* Check to verify that it is possible to get a read lock on all
- ** database schemas. The inability to get a read lock indicates that
-diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src/sqlite.h.in
-index 11622a49697f..cf623163eaa1 100644
---- a/third_party/sqlite/src/src/sqlite.h.in
-+++ b/third_party/sqlite/src/src/sqlite.h.in
-@@ -3637,10 +3637,16 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
- ** normalize a SQL statement are unspecified and subject to change.
- ** At a minimum, literal values will be replaced with suitable
- ** placeholders.
-+**
-+** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
-+** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
-+** to return an error (error code SQLITE_ERROR) if the statement uses
-+** any virtual tables.
- ** </dl>
- */
- #define SQLITE_PREPARE_PERSISTENT 0x01
- #define SQLITE_PREPARE_NORMALIZE 0x02
-+#define SQLITE_PREPARE_NO_VTAB 0x04
-
- /*
- ** CAPI3REF: Compiling An SQL Statement
-diff --git a/third_party/sqlite/src/src/sqliteInt.h b/third_party/sqlite/src/src/sqliteInt.h
-index 44d1406110ee..1aae87ea13b4 100644
---- a/third_party/sqlite/src/src/sqliteInt.h
-+++ b/third_party/sqlite/src/src/sqliteInt.h
-@@ -3057,6 +3057,7 @@ struct Parse {
- u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
- u8 okConstFactor; /* OK to factor out constants */
- u8 disableLookaside; /* Number of times lookaside has been disabled */
-+ u8 disableVtab; /* Disable all virtual tables for this parse */
- int nRangeReg; /* Size of the temporary register block */
- int iRangeReg; /* First register in temporary register block */
- int nErr; /* Number of errors seen */
-diff --git a/third_party/sqlite/src/src/trigger.c b/third_party/sqlite/src/src/trigger.c
-index cf31851f038f..69fddedd914a 100644
---- a/third_party/sqlite/src/src/trigger.c
-+++ b/third_party/sqlite/src/src/trigger.c
-@@ -916,6 +916,7 @@ static TriggerPrg *codeRowTrigger(
- pSubParse->zAuthContext = pTrigger->zName;
- pSubParse->eTriggerOp = pTrigger->op;
- pSubParse->nQueryLoop = pParse->nQueryLoop;
-+ pSubParse->disableVtab = pParse->disableVtab;
-
- v = sqlite3GetVdbe(pSubParse);
- if( v ){
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0039-Fix-overly-large-malloc-on-btree-corruption.patch b/chromium/third_party/sqlite/patches/0039-Fix-overly-large-malloc-on-btree-corruption.patch
deleted file mode 100644
index 83d67645830..00000000000
--- a/chromium/third_party/sqlite/patches/0039-Fix-overly-large-malloc-on-btree-corruption.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Mon, 21 Jan 2019 16:37:48 -0800
-Subject: [PATCH 39/40] Fix overly large malloc on btree corruption.
-
-This backports https://www.sqlite.org/src/info/3ecaaee69f49e43d
-
-Bug: 914614
----
- third_party/sqlite/src/src/btree.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
-index 3b018b5cc3c8..eaff20b24e2a 100644
---- a/third_party/sqlite/src/src/btree.c
-+++ b/third_party/sqlite/src/src/btree.c
-@@ -5474,7 +5474,7 @@ int sqlite3BtreeMovetoUnpacked(
- testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
- testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
- testcase( nCell==2 ); /* Minimum legal index key size */
-- if( nCell<2 ){
-+ if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
- rc = SQLITE_CORRUPT_PAGE(pPage);
- goto moveto_finish;
- }
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0040-Fix-null-pointer-access-on-corrupted-index-key.patch b/chromium/third_party/sqlite/patches/0040-Fix-null-pointer-access-on-corrupted-index-key.patch
deleted file mode 100644
index 873861030df..00000000000
--- a/chromium/third_party/sqlite/patches/0040-Fix-null-pointer-access-on-corrupted-index-key.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Victor Costan <pwnall@chromium.org>
-Date: Mon, 21 Jan 2019 22:29:21 -0800
-Subject: [PATCH 40/40] Fix null pointer access on corrupted index key.
-
-This backports https://www.sqlite.org/src/info/058a8006dceda78a
-
-Bug: 923902
----
- third_party/sqlite/src/src/vdbeaux.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/third_party/sqlite/src/src/vdbeaux.c b/third_party/sqlite/src/src/vdbeaux.c
-index 1e9812288cfa..13b2e1ef7280 100644
---- a/third_party/sqlite/src/src/vdbeaux.c
-+++ b/third_party/sqlite/src/src/vdbeaux.c
-@@ -3818,7 +3818,8 @@ static int vdbeRecordCompareDebug(
-
- /* Do the comparison
- */
-- rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
-+ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
-+ pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0);
- if( rc!=0 ){
- assert( mem1.szMalloc==0 ); /* See comment below */
- if( pKeyInfo->aSortOrder[i] ){
-@@ -4249,10 +4250,12 @@ int sqlite3VdbeRecordCompareWithSkip(
- mem1.n = (serial_type - 12) / 2;
- testcase( (d1+mem1.n)==(unsigned)nKey1 );
- testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
-- if( (d1+mem1.n) > (unsigned)nKey1 ){
-+ if( (d1+mem1.n) > (unsigned)nKey1
-+ || (pKeyInfo = pPKey2->pKeyInfo)->nAllField<=i
-+ ){
- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
- return 0; /* Corruption */
-- }else if( (pKeyInfo = pPKey2->pKeyInfo)->aColl[i] ){
-+ }else if( pKeyInfo->aColl[i] ){
- mem1.enc = pKeyInfo->enc;
- mem1.db = pKeyInfo->db;
- mem1.flags = MEM_Str;
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/src/Makefile.in b/chromium/third_party/sqlite/src/Makefile.in
index 3b05f1e25ca..65530e33c53 100644
--- a/chromium/third_party/sqlite/src/Makefile.in
+++ b/chromium/third_party/sqlite/src/Makefile.in
@@ -452,6 +452,7 @@ TESTSRC += \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/normalize.c \
$(TOP)/ext/misc/percentile.c \
+ $(TOP)/ext/misc/prefixes.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
@@ -588,7 +589,8 @@ FUZZDATA = \
$(TOP)/test/fuzzdata4.db \
$(TOP)/test/fuzzdata5.db \
$(TOP)/test/fuzzdata6.db \
- $(TOP)/test/fuzzdata7.db
+ $(TOP)/test/fuzzdata7.db \
+ $(TOP)/test/fuzzdata8.db
# Standard options to testfixture
#
@@ -611,6 +613,12 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
+FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
+FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
+#FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
+FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
+FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
+FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
DBFUZZ_OPT =
@@ -682,11 +690,26 @@ DBFUZZ2_OPTS = \
-DSQLITE_ENABLE_DBSTAT_VTAB \
-DSQLITE_ENABLE_RTREE \
-DSQLITE_ENABLE_FTS4 \
- -DSQLITE_EANBLE_FTS5
+ -DSQLITE_ENABLE_FTS5
-dbfuzz2: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
- clang-6.0 -I. -g -O0 -fsanitize=fuzzer,undefined,address -o dbfuzz2 \
- $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c
+dbfuzz2$(TEXE): $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
+ $(CC) $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
+ -DSTANDALONE -o dbfuzz2 \
+ $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
+ mkdir -p dbfuzz2-dir
+ cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
+
+dbfuzz2-asan: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
+ clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
+ -fsanitize=fuzzer,undefined,address -o dbfuzz2-asan \
+ $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
+ mkdir -p dbfuzz2-dir
+ cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
+
+dbfuzz2-msan: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
+ clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
+ -fsanitize=fuzzer,undefined,memory -o dbfuzz2-msan \
+ $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS)
mkdir -p dbfuzz2-dir
cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
@@ -1052,6 +1075,7 @@ SHELL_SRC = \
$(TOP)/ext/expert/sqlite3expert.c \
$(TOP)/ext/expert/sqlite3expert.h \
$(TOP)/ext/misc/zipfile.c \
+ $(TOP)/ext/misc/memtrace.c \
$(TOP)/src/test_windirent.c
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
@@ -1189,6 +1213,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
+TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
@@ -1291,6 +1316,9 @@ dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
+dbtotxt$(TEXE): $(TOP)/tool/dbtotxt.c
+ $(LTLINK)-o $@ $(TOP)/tool/dbtotxt.c
+
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
@@ -1306,6 +1334,9 @@ showwal$(TEXE): $(TOP)/tool/showwal.c sqlite3.lo
showshm$(TEXE): $(TOP)/tool/showshm.c
$(LTLINK) -o $@ $(TOP)/tool/showshm.c
+index_usage$(TEXE): $(TOP)/tool/index_usage.c sqlite3.lo
+ $(LTLINK) $(SHELL_OPT) -o $@ $(TOP)/tool/index_usage.c sqlite3.lo $(TLIBS)
+
changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
diff --git a/chromium/third_party/sqlite/src/Makefile.msc b/chromium/third_party/sqlite/src/Makefile.msc
index e3feffab357..b4fa372f9a9 100644
--- a/chromium/third_party/sqlite/src/Makefile.msc
+++ b/chromium/third_party/sqlite/src/Makefile.msc
@@ -1527,6 +1527,7 @@ TESTEXT = \
$(TOP)\ext\misc\nextchar.c \
$(TOP)\ext\misc\normalize.c \
$(TOP)\ext\misc\percentile.c \
+ $(TOP)\ext\misc\prefixes.c \
$(TOP)\ext\misc\regexp.c \
$(TOP)\ext\misc\remember.c \
$(TOP)\ext\misc\series.c \
@@ -1625,7 +1626,8 @@ FUZZDATA = \
$(TOP)\test\fuzzdata4.db \
$(TOP)\test\fuzzdata5.db \
$(TOP)\test\fuzzdata6.db \
- $(TOP)\test\fuzzdata7.db
+ $(TOP)\test\fuzzdata7.db \
+ $(TOP)\test\fuzzdata8.db
# <</mark>>
# Additional compiler options for the shell. These are only effective
@@ -1643,7 +1645,13 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
#
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
-FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
+FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
+FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
+FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
+FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
+FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
+FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
+
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
@@ -1730,10 +1738,10 @@ dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
+ $(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
- $(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
+ $(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
sessionfuzz.exe: zlib $(TOP)\test\sessionfuzz.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -I$(ZLIBINCDIR) $(TOP)\test\sessionfuzz.c /link $(LDFLAGS) $(LTLINKOPTS) /LIBPATH:$(ZLIBLIBDIR) $(ZLIBLIB)
@@ -2130,6 +2138,7 @@ SHELL_SRC = \
$(TOP)\ext\misc\completion.c \
$(TOP)\ext\expert\sqlite3expert.c \
$(TOP)\ext\expert\sqlite3expert.h \
+ $(TOP)\ext\misc\memtrace.c \
$(TOP)\src\test_windirent.c
# If use of zlib is enabled, add the "zipfile.c" source file.
@@ -2298,6 +2307,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
+TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
@@ -2425,6 +2435,9 @@ testloadext.lo: $(TOP)\src\test_loadext.c $(SQLITE3H)
testloadext.dll: testloadext.lo
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
+dbtotxt.exe: $(TOP)\tool\dbtotxt.c
+ $(LTLINK) $(NO_WARN) $(TOP)\tool\dbtotxt.c /link $(LDFLAGS) $(LTLINKOPTS)
+
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
@@ -2444,6 +2457,10 @@ showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
showshm.exe: $(TOP)\tool\showshm.c
$(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS)
+index_usage.exe: $(TOP)\tool\index_usage.c $(SQLITE3C) $(SQLITE3H)
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
+ $(TOP)\tool\index_usage.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
+
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
diff --git a/chromium/third_party/sqlite/src/VERSION b/chromium/third_party/sqlite/src/VERSION
index 419ede3b9cb..c521c77d0c0 100644
--- a/chromium/third_party/sqlite/src/VERSION
+++ b/chromium/third_party/sqlite/src/VERSION
@@ -1 +1 @@
-3.26.0
+3.27.1
diff --git a/chromium/third_party/sqlite/src/autoconf/Makefile.msc b/chromium/third_party/sqlite/src/autoconf/Makefile.msc
index 270c83c2308..a131d4c6e73 100644
--- a/chromium/third_party/sqlite/src/autoconf/Makefile.msc
+++ b/chromium/third_party/sqlite/src/autoconf/Makefile.msc
@@ -283,6 +283,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -937,6 +938,7 @@ LIBRESOBJS =
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
+SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
diff --git a/chromium/third_party/sqlite/src/configure b/chromium/third_party/sqlite/src/configure
index 51653aa5994..bb8daa5a6ab 100755
--- a/chromium/third_party/sqlite/src/configure
+++ b/chromium/third_party/sqlite/src/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sqlite 3.26.0.
+# Generated by GNU Autoconf 2.69 for sqlite 3.27.1.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.26.0'
-PACKAGE_STRING='sqlite 3.26.0'
+PACKAGE_VERSION='3.27.1'
+PACKAGE_STRING='sqlite 3.27.1'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1466,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.27.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1531,7 +1531,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.26.0:";;
+ short | recursive ) echo "Configuration of sqlite 3.27.1:";;
esac
cat <<\_ACEOF
@@ -1657,7 +1657,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.26.0
+sqlite configure 3.27.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2076,7 +2076,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sqlite $as_me 3.26.0, which was
+It was created by sqlite $as_me 3.27.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12232,7 +12232,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sqlite $as_me 3.26.0, which was
+This file was extended by sqlite $as_me 3.27.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12298,7 +12298,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sqlite config.status 3.26.0
+sqlite config.status 3.27.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/chromium/third_party/sqlite/src/ext/expert/expert1.test b/chromium/third_party/sqlite/src/ext/expert/expert1.test
index 0ced8828289..356b828f6e5 100644
--- a/chromium/third_party/sqlite/src/ext/expert/expert1.test
+++ b/chromium/third_party/sqlite/src/ext/expert/expert1.test
@@ -243,8 +243,10 @@ do_setup_rec_test $tn.12.1 {
CREATE INDEX t7_idx_00000062 ON t7(b);
CREATE INDEX t7_idx_00000061 ON t7(a);
MULTI-INDEX OR
- SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
- SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
+ INDEX 1
+ SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
+ INDEX 2
+ SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
}
# rowid terms.
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3.c b/chromium/third_party/sqlite/src/ext/fts3/fts3.c
index 005d8e50212..c371d3e8f0b 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3.c
@@ -322,6 +322,14 @@ int sqlite3Fts3Never(int b) { assert( !b ); return b; }
#endif
/*
+** This variable is set to false when running tests for which the on disk
+** structures should not be corrupt. Otherwise, true. If it is false, extra
+** assert() conditions in the fts3 code are activated - conditions that are
+** only true if it is guaranteed that the fts3 database is not corrupt.
+*/
+int sqlite3_fts3_may_be_corrupt = 1;
+
+/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
@@ -339,7 +347,7 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
}
#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
- v = (v & mask1) | ( (*ptr++) << shift ); \
+ v = (v & mask1) | ( (*(const unsigned char*)(ptr++)) << shift ); \
if( (v & mask2)==0 ){ var = v; return ret; }
#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
v = (*ptr++); \
@@ -377,20 +385,21 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
** a non-negative 32-bit integer before it is returned.
*/
int sqlite3Fts3GetVarint32(const char *p, int *pi){
+ const unsigned char *ptr = (const unsigned char*)p;
u32 a;
#ifndef fts3GetVarint32
- GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
+ GETVARINT_INIT(a, ptr, 0, 0x00, 0x80, *pi, 1);
#else
- a = (*p++);
+ a = (*ptr++);
assert( a & 0x80 );
#endif
- GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *pi, 2);
- GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
- GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
+ GETVARINT_STEP(a, ptr, 7, 0x7F, 0x4000, *pi, 2);
+ GETVARINT_STEP(a, ptr, 14, 0x3FFF, 0x200000, *pi, 3);
+ GETVARINT_STEP(a, ptr, 21, 0x1FFFFF, 0x10000000, *pi, 4);
a = (a & 0x0FFFFFFF );
- *pi = (int)(a | ((u32)(*p & 0x07) << 28));
+ *pi = (int)(a | ((u32)(*ptr & 0x07) << 28));
assert( 0==(a & 0x80000000) );
assert( *pi>=0 );
return 5;
@@ -561,13 +570,18 @@ static int fts3DestroyMethod(sqlite3_vtab *pVtab){
sqlite3 *db = p->db; /* Database handle */
/* Drop the shadow tables */
- if( p->zContentTbl==0 ){
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_content'", zDb, p->zName);
- }
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segments'", zDb,p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_segdir'", zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_docsize'", zDb, p->zName);
- fts3DbExec(&rc, db, "DROP TABLE IF EXISTS %Q.'%q_stat'", zDb, p->zName);
+ fts3DbExec(&rc, db,
+ "DROP TABLE IF EXISTS %Q.'%q_segments';"
+ "DROP TABLE IF EXISTS %Q.'%q_segdir';"
+ "DROP TABLE IF EXISTS %Q.'%q_docsize';"
+ "DROP TABLE IF EXISTS %Q.'%q_stat';"
+ "%s DROP TABLE IF EXISTS %Q.'%q_content';",
+ zDb, p->zName,
+ zDb, p->zName,
+ zDb, p->zName,
+ zDb, p->zName,
+ (p->zContentTbl ? "--" : ""), zDb,p->zName
+ );
/* If everything has worked, invoke fts3DisconnectMethod() to free the
** memory associated with the Fts3Table structure and return SQLITE_OK.
@@ -799,10 +813,10 @@ static void fts3Appendf(
** memory.
*/
static char *fts3QuoteId(char const *zInput){
- int nRet;
+ sqlite3_int64 nRet;
char *zRet;
nRet = 2 + (int)strlen(zInput)*2 + 1;
- zRet = sqlite3_malloc(nRet);
+ zRet = sqlite3_malloc64(nRet);
if( zRet ){
int i;
char *z = zRet;
@@ -983,7 +997,7 @@ static int fts3PrefixParameter(
}
}
- aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
+ aIndex = sqlite3_malloc64(sizeof(struct Fts3Index) * nIndex);
*apIndex = aIndex;
if( !aIndex ){
return SQLITE_NOMEM;
@@ -1062,7 +1076,7 @@ static int fts3ContentColumns(
if( rc==SQLITE_OK ){
const char **azCol; /* Output array */
- int nStr = 0; /* Size of all column names (incl. 0x00) */
+ sqlite3_int64 nStr = 0; /* Size of all column names (incl. 0x00) */
int nCol; /* Number of table columns */
int i; /* Used to iterate through columns */
@@ -1072,11 +1086,11 @@ static int fts3ContentColumns(
nCol = sqlite3_column_count(pStmt);
for(i=0; i<nCol; i++){
const char *zCol = sqlite3_column_name(pStmt, i);
- nStr += (int)strlen(zCol) + 1;
+ nStr += strlen(zCol) + 1;
}
/* Allocate and populate the array to return. */
- azCol = (const char **)sqlite3_malloc(sizeof(char *) * nCol + nStr);
+ azCol = (const char **)sqlite3_malloc64(sizeof(char *) * nCol + nStr);
if( azCol==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1124,7 +1138,7 @@ static int fts3InitVtab(
Fts3Table *p = 0; /* Pointer to allocated vtab */
int rc = SQLITE_OK; /* Return code */
int i; /* Iterator variable */
- int nByte; /* Size of allocation used for *p */
+ sqlite3_int64 nByte; /* Size of allocation used for *p */
int iCol; /* Column index */
int nString = 0; /* Bytes required to hold all column names */
int nCol = 0; /* Number of columns in the FTS table */
@@ -1158,10 +1172,10 @@ static int fts3InitVtab(
nName = (int)strlen(argv[2]) + 1;
nByte = sizeof(const char *) * (argc-2);
- aCol = (const char **)sqlite3_malloc(nByte);
+ aCol = (const char **)sqlite3_malloc64(nByte);
if( aCol ){
memset((void*)aCol, 0, nByte);
- azNotindexed = (char **)sqlite3_malloc(nByte);
+ azNotindexed = (char **)sqlite3_malloc64(nByte);
}
if( azNotindexed ){
memset(azNotindexed, 0, nByte);
@@ -1356,7 +1370,7 @@ static int fts3InitVtab(
nName + /* zName */
nDb + /* zDb */
nString; /* Space for azColumn strings */
- p = (Fts3Table*)sqlite3_malloc(nByte);
+ p = (Fts3Table*)sqlite3_malloc64(nByte);
if( p==0 ){
rc = SQLITE_NOMEM;
goto fts3_init_out;
@@ -2135,7 +2149,7 @@ static int fts3PutColNumber(char **pp, int iCol){
** updated appropriately. The caller is responsible for insuring
** that there is enough space in *pp to hold the complete output.
*/
-static void fts3PoslistMerge(
+static int fts3PoslistMerge(
char **pp, /* Output buffer */
char **pp1, /* Left input list */
char **pp2 /* Right input list */
@@ -2148,11 +2162,17 @@ static void fts3PoslistMerge(
int iCol1; /* The current column index in pp1 */
int iCol2; /* The current column index in pp2 */
- if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
+ if( *p1==POS_COLUMN ){
+ fts3GetVarint32(&p1[1], &iCol1);
+ if( iCol1==0 ) return FTS_CORRUPT_VTAB;
+ }
else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
else iCol1 = 0;
- if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
+ if( *p2==POS_COLUMN ){
+ fts3GetVarint32(&p2[1], &iCol2);
+ if( iCol2==0 ) return FTS_CORRUPT_VTAB;
+ }
else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
else iCol2 = 0;
@@ -2200,6 +2220,7 @@ static void fts3PoslistMerge(
*pp = p;
*pp1 = p1 + 1;
*pp2 = p2 + 1;
+ return SQLITE_OK;
}
/*
@@ -2264,10 +2285,9 @@ static int fts3PoslistPhraseMerge(
p += sqlite3Fts3PutVarint(p, iCol1);
}
- assert( *p1!=POS_END && *p1!=POS_COLUMN );
- assert( *p2!=POS_END && *p2!=POS_COLUMN );
fts3GetDeltaVarint(&p1, &iPos1); iPos1 -= 2;
fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
+ if( iPos1<0 || iPos2<0 ) break;
while( 1 ){
if( iPos2==iPos1+nToken
@@ -2493,6 +2513,7 @@ static int fts3DoclistOrMerge(
char *a2, int n2, /* Second doclist */
char **paOut, int *pnOut /* OUT: Malloc'd doclist */
){
+ int rc = SQLITE_OK;
sqlite3_int64 i1 = 0;
sqlite3_int64 i2 = 0;
sqlite3_int64 iPrev = 0;
@@ -2536,7 +2557,7 @@ static int fts3DoclistOrMerge(
** A symetric argument may be made if the doclists are in descending
** order.
*/
- aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
+ aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
if( !aOut ) return SQLITE_NOMEM;
p = aOut;
@@ -2547,7 +2568,8 @@ static int fts3DoclistOrMerge(
if( p2 && p1 && iDiff==0 ){
fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i1);
- fts3PoslistMerge(&p, &p1, &p2);
+ rc = fts3PoslistMerge(&p, &p1, &p2);
+ if( rc ) break;
fts3GetDeltaVarint3(&p1, pEnd1, bDescDoclist, &i1);
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
}else if( !p2 || (p1 && iDiff<0) ){
@@ -2561,10 +2583,16 @@ static int fts3DoclistOrMerge(
}
}
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(aOut);
+ p = aOut = 0;
+ }else{
+ assert( (p-aOut)<=n1+n2+FTS3_VARINT_MAX-1 );
+ memset(&aOut[(p-aOut)], 0, FTS3_BUFFER_PADDING);
+ }
*paOut = aOut;
*pnOut = (int)(p-aOut);
- assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
- return SQLITE_OK;
+ return rc;
}
/*
@@ -2599,7 +2627,7 @@ static int fts3DoclistPhraseMerge(
assert( nDist>0 );
if( bDescDoclist ){
- aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
+ aOut = sqlite3_malloc64((sqlite3_int64)*pnRight + FTS3_VARINT_MAX);
if( aOut==0 ) return SQLITE_NOMEM;
}else{
aOut = aRight;
@@ -2783,6 +2811,7 @@ static int fts3TermSelectMerge(
pTS->anOutput[0] = nDoclist;
if( pTS->aaOutput[0] ){
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
+ memset(&pTS->aaOutput[0][nDoclist], 0, FTS3_VARINT_MAX);
}else{
return SQLITE_NOMEM;
}
@@ -2834,8 +2863,8 @@ static int fts3SegReaderCursorAppend(
){
if( (pCsr->nSegment%16)==0 ){
Fts3SegReader **apNew;
- int nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
- apNew = (Fts3SegReader **)sqlite3_realloc(pCsr->apSegment, nByte);
+ sqlite3_int64 nByte = (pCsr->nSegment + 16)*sizeof(Fts3SegReader*);
+ apNew = (Fts3SegReader **)sqlite3_realloc64(pCsr->apSegment, nByte);
if( !apNew ){
sqlite3Fts3SegReaderFree(pNew);
return SQLITE_NOMEM;
@@ -3841,7 +3870,6 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
Fts3Table *p = (Fts3Table*)pVtab;
UNUSED_PARAMETER(iSavepoint);
assert( p->inTransaction );
- assert( p->mxSavepoint >= iSavepoint );
TESTONLY( p->mxSavepoint = iSavepoint );
sqlite3Fts3PendingTermsClear(p);
return SQLITE_OK;
@@ -4624,9 +4652,10 @@ static int fts3EvalIncrPhraseNext(
if( bEof==0 ){
int nList = 0;
int nByte = a[p->nToken-1].nList;
- char *aDoclist = sqlite3_malloc(nByte+1);
+ char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING);
if( !aDoclist ) return SQLITE_NOMEM;
memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
+ memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);
for(i=0; i<(p->nToken-1); i++){
if( a[i].bIgnore==0 ){
@@ -5017,7 +5046,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
Fts3Expr **apOr;
- aTC = (Fts3TokenAndCost *)sqlite3_malloc(
+ aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr * 2
);
@@ -5328,7 +5357,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
- int nTmp = 0; /* Bytes of temp space */
+ sqlite3_int64 nTmp = 0; /* Bytes of temp space */
char *aTmp; /* Temp space for PoslistNearMerge() */
/* Allocate temporary working space. */
@@ -5337,7 +5366,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
- aTmp = sqlite3_malloc(nTmp*2);
+ aTmp = sqlite3_malloc64(nTmp*2);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
@@ -5607,15 +5636,14 @@ static void fts3EvalRestart(
** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
** expression nodes.
*/
-static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
+static void fts3EvalUpdateCounts(Fts3Expr *pExpr, int nCol){
if( pExpr ){
Fts3Phrase *pPhrase = pExpr->pPhrase;
if( pPhrase && pPhrase->doclist.pList ){
int iCol = 0;
char *p = pPhrase->doclist.pList;
- assert( *p );
- while( 1 ){
+ do{
u8 c = 0;
int iCnt = 0;
while( 0xFE & (*p | c) ){
@@ -5631,11 +5659,11 @@ static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
if( *p==0x00 ) break;
p++;
p += fts3GetVarint32(p, &iCol);
- }
+ }while( iCol<nCol );
}
- fts3EvalUpdateCounts(pExpr->pLeft);
- fts3EvalUpdateCounts(pExpr->pRight);
+ fts3EvalUpdateCounts(pExpr->pLeft, nCol);
+ fts3EvalUpdateCounts(pExpr->pRight, nCol);
}
}
@@ -5679,7 +5707,7 @@ static int fts3EvalGatherStats(
for(p=pRoot; p; p=p->pLeft){
Fts3Expr *pE = (p->eType==FTSQUERY_PHRASE?p:p->pRight);
assert( pE->aMI==0 );
- pE->aMI = (u32 *)sqlite3_malloc(pTab->nColumn * 3 * sizeof(u32));
+ pE->aMI = (u32 *)sqlite3_malloc64(pTab->nColumn * 3 * sizeof(u32));
if( !pE->aMI ) return SQLITE_NOMEM;
memset(pE->aMI, 0, pTab->nColumn * 3 * sizeof(u32));
}
@@ -5705,7 +5733,7 @@ static int fts3EvalGatherStats(
);
if( rc==SQLITE_OK && pCsr->isEof==0 ){
- fts3EvalUpdateCounts(pRoot);
+ fts3EvalUpdateCounts(pRoot, pTab->nColumn);
}
}
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3Int.h b/chromium/third_party/sqlite/src/ext/fts3/fts3Int.h
index 3c6501cea43..c64cb701b59 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3Int.h
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3Int.h
@@ -95,6 +95,8 @@ SQLITE_EXTENSION_INIT3
*/
#define FTS3_VARINT_MAX 10
+#define FTS3_BUFFER_PADDING 8
+
/*
** FTS4 virtual tables may maintain multiple indexes - one index of all terms
** in the document set and zero or more prefix indexes. All indexes are stored
@@ -128,6 +130,18 @@ SQLITE_EXTENSION_INIT3
#define POS_END (0) /* Position-list terminator */
/*
+** The assert_fts3_nc() macro is similar to the assert() macro, except that it
+** is used for assert() conditions that are true only if it can be
+** guranteed that the database is not corrupt.
+*/
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+extern int sqlite3_fts3_may_be_corrupt;
+# define assert_fts3_nc(x) assert(sqlite3_fts3_may_be_corrupt || (x))
+#else
+# define assert_fts3_nc(x) assert(x)
+#endif
+
+/*
** This section provides definitions to allow the
** FTS3 extension to be compiled outside of the
** amalgamation.
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c
index 1ca830dd226..a88c3cc9244 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c
@@ -66,7 +66,7 @@ static int fts3auxConnectMethod(
char const *zFts3; /* Name of fts3 table */
int nDb; /* Result of strlen(zDb) */
int nFts3; /* Result of strlen(zFts3) */
- int nByte; /* Bytes of space to allocate here */
+ sqlite3_int64 nByte; /* Bytes of space to allocate here */
int rc; /* value returned by declare_vtab() */
Fts3auxTable *p; /* Virtual table object to return */
@@ -98,7 +98,7 @@ static int fts3auxConnectMethod(
if( rc!=SQLITE_OK ) return rc;
nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
- p = (Fts3auxTable *)sqlite3_malloc(nByte);
+ p = (Fts3auxTable *)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, nByte);
@@ -248,7 +248,7 @@ static int fts3auxCloseMethod(sqlite3_vtab_cursor *pCursor){
static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
if( nSize>pCsr->nStat ){
struct Fts3auxColstats *aNew;
- aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
+ aNew = (struct Fts3auxColstats *)sqlite3_realloc64(pCsr->aStat,
sizeof(struct Fts3auxColstats) * nSize
);
if( aNew==0 ) return SQLITE_NOMEM;
@@ -416,15 +416,15 @@ static int fts3auxFilterMethod(
assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
if( zStr ){
pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
- pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
+ pCsr->filter.nTerm = (int)strlen(pCsr->filter.zTerm);
}
}
if( iLe>=0 ){
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
- pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
+ pCsr->nStop = (int)strlen(pCsr->zStop);
}
if( iLangid>=0 ){
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_expr.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_expr.c
index 5ca9de3c392..dcf922eea6a 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_expr.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_expr.c
@@ -122,8 +122,8 @@ static int fts3isspace(char c){
** zero the memory before returning a pointer to it. If unsuccessful,
** return NULL.
*/
-static void *fts3MallocZero(int nByte){
- void *pRet = sqlite3_malloc(nByte);
+static void *fts3MallocZero(sqlite3_int64 nByte){
+ void *pRet = sqlite3_malloc64(nByte);
if( pRet ) memset(pRet, 0, nByte);
return pRet;
}
@@ -198,7 +198,7 @@ static int getNextToken(
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
- int nByte; /* total space to allocate */
+ sqlite3_int64 nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
@@ -252,8 +252,8 @@ static int getNextToken(
** Enlarge a memory allocation. If an out-of-memory allocation occurs,
** then free the old allocation.
*/
-static void *fts3ReallocOrFree(void *pOrig, int nNew){
- void *pRet = sqlite3_realloc(pOrig, nNew);
+static void *fts3ReallocOrFree(void *pOrig, sqlite3_int64 nNew){
+ void *pRet = sqlite3_realloc64(pOrig, nNew);
if( !pRet ){
sqlite3_free(pOrig);
}
@@ -497,7 +497,6 @@ static int getNextNode(
int nConsumed = 0;
pParse->nNest++;
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
- if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
return rc;
}else if( *zInput==')' ){
@@ -796,7 +795,7 @@ static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
if( rc==SQLITE_OK ){
if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){
Fts3Expr **apLeaf;
- apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth);
+ apLeaf = (Fts3Expr **)sqlite3_malloc64(sizeof(Fts3Expr *) * nMaxDepth);
if( 0==apLeaf ){
rc = SQLITE_NOMEM;
}else{
@@ -1216,7 +1215,7 @@ static void fts3ExprTestCommon(
zExpr = (const char *)sqlite3_value_text(argv[1]);
nExpr = sqlite3_value_bytes(argv[1]);
nCol = argc-2;
- azCol = (char **)sqlite3_malloc(nCol*sizeof(char *));
+ azCol = (char **)sqlite3_malloc64(nCol*sizeof(char *));
if( !azCol ){
sqlite3_result_error_nomem(context);
goto exprtest_out;
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_hash.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_hash.c
index 0a192220b77..1b1098712a6 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_hash.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_hash.c
@@ -35,8 +35,8 @@
/*
** Malloc and Free functions
*/
-static void *fts3HashMalloc(int n){
- void *p = sqlite3_malloc(n);
+static void *fts3HashMalloc(sqlite3_int64 n){
+ void *p = sqlite3_malloc64(n);
if( p ){
memset(p, 0, n);
}
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_icu.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_icu.c
index 211803d7687..92ee4c9647a 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_icu.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_icu.c
@@ -60,7 +60,7 @@ static int icuCreate(
if( argc>0 ){
n = strlen(argv[0])+1;
}
- p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
+ p = (IcuTokenizer *)sqlite3_malloc64(sizeof(IcuTokenizer)+n);
if( !p ){
return SQLITE_NOMEM;
}
@@ -117,7 +117,7 @@ static int icuOpen(
nInput = strlen(zInput);
}
nChar = nInput+1;
- pCsr = (IcuCursor *)sqlite3_malloc(
+ pCsr = (IcuCursor *)sqlite3_malloc64(
sizeof(IcuCursor) + /* IcuCursor */
((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
(nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_snippet.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_snippet.c
index 41f64468281..953dd1954da 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_snippet.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_snippet.c
@@ -178,7 +178,7 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
aOut = &p->aMatchinfo[p->nElem+2];
xRet = fts3MIBufferFree;
}else{
- aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32));
+ aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
if( aOut ){
xRet = sqlite3_free;
if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
@@ -433,7 +433,8 @@ static void fts3SnippetDetails(
int j;
u64 mPhrase = (u64)1 << i;
u64 mPos = (u64)1 << (iCsr - iStart);
- assert( iCsr>=iStart );
+ assert( iCsr>=iStart && (iCsr - iStart)<=64 );
+ assert( i>=0 && i<=64 );
if( (mCover|mCovered)&mPhrase ){
iScore++;
}else{
@@ -475,11 +476,14 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
int iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
- assert( iFirst>=0 );
- pPhrase->pHead = pCsr;
- pPhrase->pTail = pCsr;
- pPhrase->iHead = iFirst;
- pPhrase->iTail = iFirst;
+ if( iFirst<0 ){
+ rc = FTS_CORRUPT_VTAB;
+ }else{
+ pPhrase->pHead = pCsr;
+ pPhrase->pTail = pCsr;
+ pPhrase->iHead = iFirst;
+ pPhrase->iTail = iFirst;
+ }
}else{
assert( rc!=SQLITE_OK || (
pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0
@@ -516,7 +520,7 @@ static int fts3BestSnippet(
int rc; /* Return Code */
int nList; /* Number of phrases in expression */
SnippetIter sIter; /* Iterates through snippet candidates */
- int nByte; /* Number of bytes of space to allocate */
+ sqlite3_int64 nByte; /* Number of bytes of space to allocate */
int iBestScore = -1; /* Best snippet score found so far */
int i; /* Loop counter */
@@ -534,7 +538,7 @@ static int fts3BestSnippet(
** the required space using malloc().
*/
nByte = sizeof(SnippetPhrase) * nList;
- sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc(nByte);
+ sIter.aPhrase = (SnippetPhrase *)sqlite3_malloc64(nByte);
if( !sIter.aPhrase ){
return SQLITE_NOMEM;
}
@@ -604,8 +608,8 @@ static int fts3StringAppend(
** appended data.
*/
if( pStr->n+nAppend+1>=pStr->nAlloc ){
- int nAlloc = pStr->nAlloc+nAppend+100;
- char *zNew = sqlite3_realloc(pStr->z, nAlloc);
+ sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64)nAppend+100;
+ char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
if( !zNew ){
return SQLITE_NOMEM;
}
@@ -660,6 +664,7 @@ static int fts3SnippetShift(
for(nLeft=0; !(hlmask & ((u64)1 << nLeft)); nLeft++);
for(nRight=0; !(hlmask & ((u64)1 << (nSnippet-1-nRight))); nRight++);
+ assert( (nSnippet-1-nRight)<=63 && (nSnippet-1-nRight)>=0 );
nDesired = (nLeft-nRight)/2;
/* Ideally, the start of the snippet should be pushed forward in the
@@ -852,7 +857,7 @@ static int fts3ColumnlistCount(char **ppCollist){
/*
** This function gathers 'y' or 'b' data for a single phrase.
*/
-static void fts3ExprLHits(
+static int fts3ExprLHits(
Fts3Expr *pExpr, /* Phrase expression node */
MatchInfo *p /* Matchinfo context */
){
@@ -882,25 +887,29 @@ static void fts3ExprLHits(
if( *pIter!=0x01 ) break;
pIter++;
pIter += fts3GetVarint32(pIter, &iCol);
+ if( iCol>=p->nCol ) return FTS_CORRUPT_VTAB;
}
+ return SQLITE_OK;
}
/*
** Gather the results for matchinfo directives 'y' and 'b'.
*/
-static void fts3ExprLHitGather(
+static int fts3ExprLHitGather(
Fts3Expr *pExpr,
MatchInfo *p
){
+ int rc = SQLITE_OK;
assert( (pExpr->pLeft==0)==(pExpr->pRight==0) );
if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
if( pExpr->pLeft ){
- fts3ExprLHitGather(pExpr->pLeft, p);
- fts3ExprLHitGather(pExpr->pRight, p);
+ rc = fts3ExprLHitGather(pExpr->pLeft, p);
+ if( rc==SQLITE_OK ) rc = fts3ExprLHitGather(pExpr->pRight, p);
}else{
- fts3ExprLHits(pExpr, p);
+ rc = fts3ExprLHits(pExpr, p);
}
}
+ return rc;
}
/*
@@ -1117,11 +1126,12 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
int i;
int iCol;
int nToken = 0;
+ int rc = SQLITE_OK;
/* Allocate and populate the array of LcsIterator objects. The array
** contains one element for each matchable phrase in the query.
**/
- aIter = sqlite3_malloc(sizeof(LcsIterator) * pCsr->nPhrase);
+ aIter = sqlite3_malloc64(sizeof(LcsIterator) * pCsr->nPhrase);
if( !aIter ) return SQLITE_NOMEM;
memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
@@ -1137,13 +1147,16 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
int nLive = 0; /* Number of iterators in aIter not at EOF */
for(i=0; i<pInfo->nPhrase; i++){
- int rc;
LcsIterator *pIt = &aIter[i];
rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead);
- if( rc!=SQLITE_OK ) return rc;
+ if( rc!=SQLITE_OK ) goto matchinfo_lcs_out;
if( pIt->pRead ){
pIt->iPos = pIt->iPosOffset;
- fts3LcsIteratorAdvance(&aIter[i]);
+ fts3LcsIteratorAdvance(pIt);
+ if( pIt->pRead==0 ){
+ rc = FTS_CORRUPT_VTAB;
+ goto matchinfo_lcs_out;
+ }
nLive++;
}
}
@@ -1175,8 +1188,9 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
pInfo->aMatchinfo[iCol] = nLcs;
}
+ matchinfo_lcs_out:
sqlite3_free(aIter);
- return SQLITE_OK;
+ return rc;
}
/*
@@ -1272,7 +1286,7 @@ static int fts3MatchinfoValues(
case FTS3_MATCHINFO_LHITS: {
int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32);
memset(pInfo->aMatchinfo, 0, nZero);
- fts3ExprLHitGather(pCsr->pExpr, pInfo);
+ rc = fts3ExprLHitGather(pCsr->pExpr, pInfo);
break;
}
@@ -1424,6 +1438,10 @@ void sqlite3Fts3Snippet(
return;
}
+ /* Limit the snippet length to 64 tokens. */
+ if( nToken<-64 ) nToken = -64;
+ if( nToken>+64 ) nToken = +64;
+
for(nSnippet=1; 1; nSnippet++){
int iSnip; /* Loop counter 0..nSnippet-1 */
@@ -1566,7 +1584,7 @@ void sqlite3Fts3Offsets(
if( rc!=SQLITE_OK ) goto offsets_out;
/* Allocate the array of TermOffset iterators. */
- sCtx.aTerm = (TermOffset *)sqlite3_malloc(sizeof(TermOffset)*nToken);
+ sCtx.aTerm = (TermOffset *)sqlite3_malloc64(sizeof(TermOffset)*nToken);
if( 0==sCtx.aTerm ){
rc = SQLITE_NOMEM;
goto offsets_out;
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_term.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_term.c
index 4b2872fe99b..ea51f43c6cc 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_term.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_term.c
@@ -68,9 +68,9 @@ static int fts3termConnectMethod(
char const *zFts3; /* Name of fts3 table */
int nDb; /* Result of strlen(zDb) */
int nFts3; /* Result of strlen(zFts3) */
- int nByte; /* Bytes of space to allocate here */
+ sqlite3_int64 nByte; /* Bytes of space to allocate here */
int rc; /* value returned by declare_vtab() */
- Fts3termTable *p; /* Virtual table object to return */
+ Fts3termTable *p; /* Virtual table object to return */
int iIndex = 0;
UNUSED_PARAMETER(pCtx);
@@ -96,7 +96,7 @@ static int fts3termConnectMethod(
if( rc!=SQLITE_OK ) return rc;
nByte = sizeof(Fts3termTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
- p = (Fts3termTable *)sqlite3_malloc(nByte);
+ p = (Fts3termTable *)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, nByte);
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_test.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_test.c
index ac2a4adf055..01aa8e96fd4 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_test.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_test.c
@@ -574,6 +574,33 @@ static int SQLITE_TCLAPI fts3_test_varint_cmd(
** End of tokenizer code.
**************************************************************************/
+/*
+** sqlite3_fts3_may_be_corrupt BOOLEAN
+**
+** Set or clear the global "may-be-corrupt" flag. Return the old value.
+*/
+static int SQLITE_TCLAPI fts3_may_be_corrupt(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ int bOld = sqlite3_fts3_may_be_corrupt;
+
+ if( objc!=2 && objc!=1 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
+ return TCL_ERROR;
+ }
+ if( objc==2 ){
+ int bNew;
+ if( Tcl_GetBooleanFromObj(interp, objv[1], &bNew) ) return TCL_ERROR;
+ sqlite3_fts3_may_be_corrupt = bNew;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld));
+ return TCL_OK;
+}
+
int Sqlitetestfts3_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "fts3_near_match", fts3_near_match_cmd, 0, 0);
Tcl_CreateObjCommand(interp,
@@ -582,10 +609,12 @@ int Sqlitetestfts3_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(
interp, "fts3_test_tokenizer", fts3_test_tokenizer_cmd, 0, 0
);
-
Tcl_CreateObjCommand(
interp, "fts3_test_varint", fts3_test_varint_cmd, 0, 0
);
+ Tcl_CreateObjCommand(
+ interp, "sqlite3_fts3_may_be_corrupt", fts3_may_be_corrupt, 0, 0
+ );
return TCL_OK;
}
#endif /* SQLITE_ENABLE_FTS3 || SQLITE_ENABLE_FTS4 */
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c
index 87c5da3ce43..6dfde7b91b6 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c
@@ -122,7 +122,7 @@ static int fts3tokDequoteArray(
nByte += (int)(strlen(argv[i]) + 1);
}
- *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
+ *pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
if( azDequote==0 ){
rc = SQLITE_NOMEM;
}else{
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_unicode.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_unicode.c
index a89b90ff77f..3101f3479f7 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_unicode.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_unicode.c
@@ -82,7 +82,7 @@ typedef struct unicode_cursor unicode_cursor;
struct unicode_tokenizer {
sqlite3_tokenizer base;
- int bRemoveDiacritic;
+ int eRemoveDiacritic;
int nException;
int *aiException;
};
@@ -155,7 +155,7 @@ static int unicodeAddExceptions(
int *aNew; /* New aiException[] array */
int nNew; /* Number of valid entries in array aNew[] */
- aNew = sqlite3_realloc(p->aiException, (p->nException+nEntry)*sizeof(int));
+ aNew = sqlite3_realloc64(p->aiException,(p->nException+nEntry)*sizeof(int));
if( aNew==0 ) return SQLITE_NOMEM;
nNew = p->nException;
@@ -227,17 +227,20 @@ static int unicodeCreate(
pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
if( pNew==NULL ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(unicode_tokenizer));
- pNew->bRemoveDiacritic = 1;
+ pNew->eRemoveDiacritic = 1;
for(i=0; rc==SQLITE_OK && i<nArg; i++){
const char *z = azArg[i];
int n = (int)strlen(z);
if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
- pNew->bRemoveDiacritic = 1;
+ pNew->eRemoveDiacritic = 1;
}
else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
- pNew->bRemoveDiacritic = 0;
+ pNew->eRemoveDiacritic = 0;
+ }
+ else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){
+ pNew->eRemoveDiacritic = 2;
}
else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
@@ -341,7 +344,7 @@ static int unicodeNext(
/* Grow the output buffer if required. */
if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){
- char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64);
+ char *zNew = sqlite3_realloc64(pCsr->zToken, pCsr->nAlloc+64);
if( !zNew ) return SQLITE_NOMEM;
zOut = &zNew[zOut - pCsr->zToken];
pCsr->zToken = zNew;
@@ -350,7 +353,7 @@ static int unicodeNext(
/* Write the folded case of the last character read to the output */
zEnd = z;
- iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
+ iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic);
if( iOut ){
WRITE_UTF8(zOut, iOut);
}
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_unicode2.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_unicode2.c
index b38d2fa54c4..243bbc6c7cf 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_unicode2.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_unicode2.c
@@ -1,5 +1,5 @@
/*
-** 2012 May 25
+** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -159,32 +159,48 @@ int sqlite3FtsUnicodeIsalnum(int c){
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
-static int remove_diacritic(int c){
+static int remove_diacritic(int c, int bComplex){
unsigned short aDia[] = {
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
- 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
- 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
- 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
- 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
- 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
- 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
- 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
- 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
- 62924, 63050, 63082, 63274, 63390,
+ 3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
+ 3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
+ 4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
+ 4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
+ 6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
+ 61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
+ 61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
+ 61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
+ 62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
+ 62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
+ 62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
+ 63182, 63242, 63274, 63310, 63368, 63390,
};
- char aChar[] = {
- '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
- 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
- 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
- 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
- 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
- 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
- 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
- 'e', 'i', 'o', 'u', 'y',
+#define HIBIT ((unsigned char)0x80)
+ unsigned char aChar[] = {
+ '\0', 'a', 'c', 'e', 'i', 'n',
+ 'o', 'u', 'y', 'y', 'a', 'c',
+ 'd', 'e', 'e', 'g', 'h', 'i',
+ 'j', 'k', 'l', 'n', 'o', 'r',
+ 's', 't', 'u', 'u', 'w', 'y',
+ 'z', 'o', 'u', 'a', 'i', 'o',
+ 'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
+ 'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
+ 'e', 'i', 'o', 'r', 'u', 's',
+ 't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
+ 'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', 'a', 'b',
+ 'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
+ 'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
+ 'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
+ 'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
+ 's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
+ 'w', 'x', 'y', 'z', 'h', 't',
+ 'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
+ 'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
+ 'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
@@ -201,7 +217,8 @@ static int remove_diacritic(int c){
}
}
assert( key>=aDia[iRes] );
- return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
+ if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
+ return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
}
@@ -214,8 +231,8 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
unsigned int mask1 = 0x000361F8;
if( c<768 || c>817 ) return 0;
return (c < 768+32) ?
- (mask0 & (1 << (c-768))) :
- (mask1 & (1 << (c-768-32)));
+ (mask0 & ((unsigned int)1 << (c-768))) :
+ (mask1 & ((unsigned int)1 << (c-768-32)));
}
@@ -228,7 +245,7 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
** The results are undefined if the value passed to this function
** is less than zero.
*/
-int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
+int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
/* Each entry in the following array defines a rule for folding a range
** of codepoints to lower case. The rule applies to a range of nRange
** codepoints starting at codepoint iCode.
@@ -351,7 +368,9 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
assert( ret>0 );
}
- if( bRemoveDiacritic ) ret = remove_diacritic(ret);
+ if( eRemoveDiacritic ){
+ ret = remove_diacritic(ret, eRemoveDiacritic==2);
+ }
}
else if( c>=66560 && c<66600 ){
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_write.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_write.c
index 9bc6d70f45c..e368c09247d 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_write.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_write.c
@@ -567,7 +567,7 @@ static sqlite3_int64 getAbsoluteLevel(
int iLevel /* Level of segments */
){
sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */
- assert( iLangid>=0 );
+ assert_fts3_nc( iLangid>=0 );
assert( p->nIndex>0 );
assert( iIndex>=0 && iIndex<p->nIndex );
@@ -1409,7 +1409,7 @@ static int fts3SegReaderNext(
** b-tree node. And that the final byte of the doclist is 0x00. If either
** of these statements is untrue, then the data structure is corrupt.
*/
- if( (&pReader->aNode[pReader->nNode] - pReader->aDoclist)<pReader->nDoclist
+ if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode)
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
){
return FTS_CORRUPT_VTAB;
@@ -1609,8 +1609,13 @@ int sqlite3Fts3SegReaderNew(
Fts3SegReader *pReader; /* Newly allocated SegReader object */
int nExtra = 0; /* Bytes to allocate segment root node */
- assert( iStartLeaf<=iEndLeaf );
+ assert( zRoot!=0 || nRoot==0 );
+#ifdef CORRUPT_DB
+ assert( zRoot!=0 || CORRUPT_DB );
+#endif
+
if( iStartLeaf==0 ){
+ if( iEndLeaf!=0 ) return FTS_CORRUPT_VTAB;
nExtra = nRoot + FTS3_NODE_PADDING;
}
@@ -1630,7 +1635,7 @@ int sqlite3Fts3SegReaderNew(
pReader->aNode = (char *)&pReader[1];
pReader->rootOnly = 1;
pReader->nNode = nRoot;
- memcpy(pReader->aNode, zRoot, nRoot);
+ if( nRoot ) memcpy(pReader->aNode, zRoot, nRoot);
memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
}else{
pReader->iCurrentBlock = iStartLeaf-1;
@@ -2250,6 +2255,11 @@ static int fts3SegWriterAdd(
nPrefix = fts3PrefixCompress(pWriter->zTerm, pWriter->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
+ /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
+ ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
+ ** compared with BINARY collation. This indicates corruption. */
+ if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
+
/* Figure out how many bytes are required by this new entry */
nReq = sqlite3Fts3VarintLen(nPrefix) + /* varint containing prefix size */
sqlite3Fts3VarintLen(nSuffix) + /* varint containing suffix size */
@@ -2957,7 +2967,9 @@ int sqlite3Fts3SegReaderStep(
}else{
iDelta = iDocid - iPrev;
}
- assert( iDelta>0 || (nDoclist==0 && iDelta==iDocid) );
+ if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){
+ return FTS_CORRUPT_VTAB;
+ }
assert( nDoclist>0 || iDelta==iDocid );
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
@@ -3323,14 +3335,16 @@ static void fts3DecodeIntArray(
const char *zBuf, /* The BLOB containing the varints */
int nBuf /* size of the BLOB */
){
- int i, j;
- UNUSED_PARAMETER(nBuf);
- for(i=j=0; i<N; i++){
- sqlite3_int64 x;
- j += sqlite3Fts3GetVarint(&zBuf[j], &x);
- assert(j<=nBuf);
- a[i] = (u32)(x & 0xffffffff);
+ int i = 0;
+ if( nBuf && (zBuf[nBuf-1]&0x80)==0 ){
+ int j;
+ for(i=j=0; i<N && j<nBuf; i++){
+ sqlite3_int64 x;
+ j += sqlite3Fts3GetVarint(&zBuf[j], &x);
+ a[i] = (u32)(x & 0xffffffff);
+ }
}
+ while( i<N ) a[i++] = 0;
}
/*
@@ -3736,7 +3750,7 @@ static int nodeReaderNext(NodeReader *p){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
if( nPrefix>p->iOff || nSuffix>p->nNode-p->iOff ){
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
if( rc==SQLITE_OK ){
@@ -3746,7 +3760,7 @@ static int nodeReaderNext(NodeReader *p){
if( p->iChild==0 ){
p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
if( (p->nNode-p->iOff)<p->nDoclist ){
- return SQLITE_CORRUPT_VTAB;
+ return FTS_CORRUPT_VTAB;
}
p->aDoclist = &p->aNode[p->iOff];
p->iOff += p->nDoclist;
diff --git a/chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl b/chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl
index ba11ab28ff7..b809abf218b 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl
+++ b/chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl
@@ -9,11 +9,12 @@ proc print_rd {map} {
set nRange 1
set iFirst [lindex $map 0 0]
set cPrev [lindex $map 0 1]
+ set fPrev [lindex $map 0 2]
foreach m [lrange $map 1 end] {
- foreach {i c} $m {}
+ foreach {i c f} $m {}
- if {$cPrev == $c} {
+ if {$cPrev == $c && $fPrev==$f} {
for {set j [expr $iFirst+$nRange]} {$j<$i} {incr j} {
if {[info exists tl_lookup_table($j)]==0} break
}
@@ -29,13 +30,16 @@ proc print_rd {map} {
lappend lRange [list $iFirst $nRange]
lappend aChar $cPrev
+ lappend aFlag $fPrev
set iFirst $i
set cPrev $c
+ set fPrev $f
set nRange 1
}
lappend lRange [list $iFirst $nRange]
lappend aChar $cPrev
+ lappend aFlag $fPrev
puts "/*"
puts "** If the argument is a codepoint corresponding to a lowercase letter"
@@ -45,7 +49,7 @@ proc print_rd {map} {
puts "** E\"). The resuls of passing a codepoint that corresponds to an"
puts "** uppercase letter are undefined."
puts "*/"
- puts "static int ${::remove_diacritic}(int c)\{"
+ puts "static int ${::remove_diacritic}(int c, int bComplex)\{"
puts " unsigned short aDia\[\] = \{"
puts -nonewline " 0, "
set i 1
@@ -59,14 +63,19 @@ proc print_rd {map} {
}
puts ""
puts " \};"
- puts " char aChar\[\] = \{"
- puts -nonewline " '\\0', "
+ puts "#define HIBIT ((unsigned char)0x80)"
+ puts " unsigned char aChar\[\] = \{"
+ puts -nonewline " '\\0', "
set i 1
- foreach c $aChar {
- set str "'$c', "
- if {$c == ""} { set str "'\\0', " }
+ foreach c $aChar f $aFlag {
+ if { $f } {
+ set str "'$c'|HIBIT, "
+ } else {
+ set str "'$c', "
+ }
+ if {$c == ""} { set str "'\\0', " }
- if {($i % 12)==0} {puts "" ; puts -nonewline " " }
+ if {($i % 6)==0} {puts "" ; puts -nonewline " " }
incr i
puts -nonewline "$str"
}
@@ -87,7 +96,8 @@ proc print_rd {map} {
}
}
assert( key>=aDia[iRes] );
- return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);}
+ if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
+ return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);}
puts "\}"
}
@@ -95,7 +105,8 @@ proc print_isdiacritic {zFunc map} {
set lCode [list]
foreach m $map {
- foreach {code char} $m {}
+ foreach {code char flag} $m {}
+ if {$flag} continue
if {$code && $char == ""} { lappend lCode $code }
}
set lCode [lsort -integer $lCode]
@@ -124,8 +135,8 @@ proc print_isdiacritic {zFunc map} {
puts " if( c<$iFirst || c>$iLast ) return 0;"
puts " return (c < $iFirst+32) ?"
- puts " (mask0 & (1 << (c-$iFirst))) :"
- puts " (mask1 & (1 << (c-$iFirst-32)));"
+ puts " (mask0 & ((unsigned int)1 << (c-$iFirst))) :"
+ puts " (mask1 & ((unsigned int)1 << (c-$iFirst-32)));"
puts "\}"
}
@@ -472,7 +483,7 @@ proc print_fold {zFunc} {
puts "** The results are undefined if the value passed to this function"
puts "** is less than zero."
puts "*/"
- puts "int ${zFunc}\(int c, int bRemoveDiacritic)\{"
+ puts "int ${zFunc}\(int c, int eRemoveDiacritic)\{"
set liOff [tl_generate_ioff_table $lRecord]
tl_print_table_header
@@ -516,7 +527,9 @@ proc print_fold {zFunc} {
assert( ret>0 );
}
- if( bRemoveDiacritic ) ret = ${::remove_diacritic}(ret);
+ if( eRemoveDiacritic ){
+ ret = ${::remove_diacritic}(ret, eRemoveDiacritic==2);
+ }
}
}]
@@ -605,10 +618,6 @@ proc print_categories {lMap} {
set nCat [expr [llength [array names C]] + 1]
puts [code {
- int sqlite3Fts5UnicodeNCat(void) {
- return $nCat;
- }
-
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
aArray[0] = 1;
switch( zCat[0] ){
@@ -691,7 +700,7 @@ proc print_categories {lMap} {
static u16 aFts5UnicodeMap[] = {$aMapArray};
static u16 aFts5UnicodeData[] = {$aDataArray};
- int sqlite3Fts5UnicodeCategory(int iCode) {
+ int sqlite3Fts5UnicodeCategory(u32 iCode) {
int iRes = -1;
int iHi;
int iLo;
@@ -774,7 +783,7 @@ proc print_test_categories {lMap} {
aArray[0] = 1;
}
- c = sqlite3Fts5UnicodeCategory(i);
+ c = sqlite3Fts5UnicodeCategory((u32)i);
if( aArray[c]==0 ){
*piCode = i;
return 1;
@@ -829,7 +838,7 @@ proc print_fold_test {zFunc mappings} {
proc print_fileheader {} {
puts [string trim {
/*
-** 2012 May 25
+** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
diff --git a/chromium/third_party/sqlite/src/ext/fts3/unicode/parseunicode.tcl b/chromium/third_party/sqlite/src/ext/fts3/unicode/parseunicode.tcl
index dda01396701..d7ec90dcd8b 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/unicode/parseunicode.tcl
+++ b/chromium/third_party/sqlite/src/ext/fts3/unicode/parseunicode.tcl
@@ -7,12 +7,24 @@
# character that it should be replaced with, or an empty string if the
# codepoint should simply be removed from the input. Examples:
#
-# { 224 a } (replace codepoint 224 to "a")
-# { 769 "" } (remove codepoint 769 from input)
+# { 224 a 0 } (replace codepoint 224 to "a")
+# { 769 "" 0 } (remove codepoint 769 from input)
#
# Mappings are only returned for non-upper case codepoints. It is assumed
# that the input has already been folded to lower case.
#
+# The third value in the list is always either 0 or 1. 0 if the
+# UnicodeData.txt file maps the codepoint to a single ASCII character and
+# a diacritic, or 1 if the mapping is indirect. For example, consider the
+# two entries:
+#
+# 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC
+# 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8
+#
+# The first codepoint is a direct mapping (as 006F is ASCII and 0323 is a
+# diacritic). The second is an indirect mapping, as it maps to the
+# first codepoint plus 0302 (a diacritic).
+#
proc rd_load_unicodedata_text {zName} {
global tl_lookup_table
@@ -53,18 +65,29 @@ proc rd_load_unicodedata_text {zName} {
set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"]
set iDia [expr "0x[lindex $character_decomposition_mapping 1]"]
+ # Filter out upper-case characters, as they will be mapped to their
+ # lower-case equivalents before this data is used.
if {[info exists tl_lookup_table($iCode)]} continue
+ # Check if this is an indirect mapping. If so, set bIndirect to true
+ # and change $iAscii to the indirectly mappped ASCII character.
+ set bIndirect 0
+ if {[info exists dia($iDia)] && [info exists mapping($iAscii)]} {
+ set iAscii $mapping($iAscii)
+ set bIndirect 1
+ }
+
if { ($iAscii >= 97 && $iAscii <= 122)
|| ($iAscii >= 65 && $iAscii <= 90)
} {
- lappend lRet [list $iCode [string tolower [format %c $iAscii]]]
+ lappend lRet [list $iCode [string tolower [format %c $iAscii]] $bIndirect]
+ set mapping($iCode) $iAscii
set dia($iDia) 1
}
}
foreach d [array names dia] {
- lappend lRet [list $d ""]
+ lappend lRet [list $d "" 0]
}
set lRet [lsort -integer -index 0 $lRet]
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5.h b/chromium/third_party/sqlite/src/ext/fts5/fts5.h
index 08a1f5c4332..ad73ebaf4c2 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5.h
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5.h
@@ -120,12 +120,8 @@ struct Fts5PhraseIter {
**
** Usually, output parameter *piPhrase is set to the phrase number, *piCol
** to the column in which it occurs and *piOff the token offset of the
-** first token of the phrase. The exception is if the table was created
-** with the offsets=0 option specified. In this case *piOff is always
-** set to -1.
-**
-** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
-** if an error occurs.
+** first token of the phrase. Returns SQLITE_OK if successful, or an error
+** code (i.e. SQLITE_NOMEM) if an error occurs.
**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
@@ -414,11 +410,11 @@ struct Fts5ExtensionApi {
** the tokenizer substitutes "first" for "1st" and the query works
** as expected.
**
-** <li> By adding multiple synonyms for a single term to the FTS index.
-** In this case, when tokenizing query text, the tokenizer may
-** provide multiple synonyms for a single term within the document.
-** FTS5 then queries the index for each synonym individually. For
-** example, faced with the query:
+** <li> By querying the index for all synonyms of each query term
+** separately. In this case, when tokenizing query text, the
+** tokenizer may provide multiple synonyms for a single term
+** within the document. FTS5 then queries the index for each
+** synonym individually. For example, faced with the query:
**
** <codeblock>
** ... MATCH 'first place'</codeblock>
@@ -442,7 +438,7 @@ struct Fts5ExtensionApi {
** "place".
**
** This way, even if the tokenizer does not provide synonyms
-** when tokenizing query text (it should not - to do would be
+** when tokenizing query text (it should not - to do so would be
** inefficient), it doesn't matter if the user queries for
** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5Int.h b/chromium/third_party/sqlite/src/ext/fts5/fts5Int.h
index 06f82505535..8cfad43094e 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5Int.h
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5Int.h
@@ -87,6 +87,12 @@ extern int sqlite3_fts5_may_be_corrupt;
# define assert_nc(x) assert(x)
#endif
+/*
+** A version of memcmp() that does not cause asan errors if one of the pointer
+** parameters is NULL and the number of bytes to compare is zero.
+*/
+#define fts5Memcmp(s1, s2, n) ((n)==0 ? 0 : memcmp((s1), (s2), (n)))
+
/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAM
@@ -274,7 +280,7 @@ void sqlite3Fts5Put32(u8*, int);
int sqlite3Fts5Get32(const u8*);
#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32)
-#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF)
+#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0x7FFFFFFF)
typedef struct Fts5PoslistReader Fts5PoslistReader;
struct Fts5PoslistReader {
@@ -309,7 +315,7 @@ int sqlite3Fts5PoslistNext64(
);
/* Malloc utility */
-void *sqlite3Fts5MallocZero(int *pRc, int nByte);
+void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte);
char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
/* Character set tests (like isspace(), isalpha() etc.) */
@@ -520,8 +526,18 @@ int sqlite3Fts5PutVarint(unsigned char *p, u64 v);
/**************************************************************************
-** Interface to code in fts5.c.
+** Interface to code in fts5_main.c.
+*/
+
+/*
+** Virtual-table object.
*/
+typedef struct Fts5Table Fts5Table;
+struct Fts5Table {
+ sqlite3_vtab base; /* Base class used by SQLite core */
+ Fts5Config *pConfig; /* Virtual table configuration */
+ Fts5Index *pIndex; /* Full-text index */
+};
int sqlite3Fts5GetTokenizer(
Fts5Global*,
@@ -532,7 +548,9 @@ int sqlite3Fts5GetTokenizer(
char **pzErr
);
-Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
+Fts5Table *sqlite3Fts5TableFromCsrid(Fts5Global*, i64);
+
+int sqlite3Fts5FlushToDisk(Fts5Table*);
/*
** End of interface to code in fts5.c.
@@ -788,7 +806,7 @@ int sqlite3Fts5UnicodeIsdiacritic(int c);
int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic);
int sqlite3Fts5UnicodeCatParse(const char*, u8*);
-int sqlite3Fts5UnicodeCategory(int iCode);
+int sqlite3Fts5UnicodeCategory(u32 iCode);
void sqlite3Fts5UnicodeAscii(u8*, u8*);
/*
** End of interface to code in fts5_unicode2.c.
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c
index c841d887b03..087416aae69 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c
@@ -136,7 +136,7 @@ static void fts5HighlightAppend(
HighlightContext *p,
const char *z, int n
){
- if( *pRc==SQLITE_OK ){
+ if( *pRc==SQLITE_OK && z ){
if( n<0 ) n = (int)strlen(z);
p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z);
if( p->zOut==0 ) *pRc = SQLITE_NOMEM;
@@ -268,7 +268,7 @@ static int fts5SentenceFinderAdd(Fts5SFinder *p, int iAdd){
int nNew = p->nFirstAlloc ? p->nFirstAlloc*2 : 64;
int *aNew;
- aNew = (int*)sqlite3_realloc(p->aFirst, nNew*sizeof(int));
+ aNew = (int*)sqlite3_realloc64(p->aFirst, nNew*sizeof(int));
if( aNew==0 ) return SQLITE_NOMEM;
p->aFirst = aNew;
p->nFirstAlloc = nNew;
@@ -335,11 +335,12 @@ static int fts5SnippetScore(
int nInst;
int nScore = 0;
int iLast = 0;
+ sqlite3_int64 iEnd = (sqlite3_int64)iPos + nToken;
rc = pApi->xInstCount(pFts, &nInst);
for(i=0; i<nInst && rc==SQLITE_OK; i++){
rc = pApi->xInst(pFts, i, &ip, &ic, &iOff);
- if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<(iPos+nToken) ){
+ if( rc==SQLITE_OK && ic==iCol && iOff>=iPos && iOff<iEnd ){
nScore += (aSeen[ip] ? 1 : 1000);
aSeen[ip] = 1;
if( iFirst<0 ) iFirst = iOff;
@@ -349,7 +350,7 @@ static int fts5SnippetScore(
*pnScore = nScore;
if( piPos ){
- int iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
+ sqlite3_int64 iAdj = iFirst - (nToken - (iLast-iFirst)) / 2;
if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken;
if( iAdj<0 ) iAdj = 0;
*piPos = iAdj;
@@ -442,7 +443,9 @@ static void fts5SnippetFunction(
int jj;
rc = pApi->xInst(pFts, ii, &ip, &ic, &io);
- if( ic!=i || rc!=SQLITE_OK ) continue;
+ if( ic!=i ) continue;
+ if( io>nDocsize ) rc = FTS5_CORRUPT;
+ if( rc!=SQLITE_OK ) continue;
memset(aSeen, 0, nPhrase);
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
io, nToken, &nScore, &iAdj
@@ -568,13 +571,13 @@ static int fts5Bm25GetData(
int nPhrase; /* Number of phrases in query */
sqlite3_int64 nRow = 0; /* Number of rows in table */
sqlite3_int64 nToken = 0; /* Number of tokens in table */
- int nByte; /* Bytes of space to allocate */
+ sqlite3_int64 nByte; /* Bytes of space to allocate */
int i;
/* Allocate the Fts5Bm25Data object */
nPhrase = pApi->xPhraseCount(pFts);
nByte = sizeof(Fts5Bm25Data) + nPhrase*2*sizeof(double);
- p = (Fts5Bm25Data*)sqlite3_malloc(nByte);
+ p = (Fts5Bm25Data*)sqlite3_malloc64(nByte);
if( p==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -586,6 +589,7 @@ static int fts5Bm25GetData(
/* Calculate the average document length for this FTS5 table */
if( rc==SQLITE_OK ) rc = pApi->xRowCount(pFts, &nRow);
+ assert( rc!=SQLITE_OK || nRow>0 );
if( rc==SQLITE_OK ) rc = pApi->xColumnTotalSize(pFts, -1, &nToken);
if( rc==SQLITE_OK ) p->avgdl = (double)nToken / (double)nRow;
@@ -710,5 +714,3 @@ int sqlite3Fts5AuxInit(fts5_api *pApi){
return rc;
}
-
-
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_buffer.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_buffer.c
index 516174d3de6..3f5595a8517 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_buffer.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_buffer.c
@@ -17,12 +17,12 @@
int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){
if( (u32)pBuf->nSpace<nByte ){
- u32 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
+ u64 nNew = pBuf->nSpace ? pBuf->nSpace : 64;
u8 *pNew;
while( nNew<nByte ){
nNew = nNew * 2;
}
- pNew = sqlite3_realloc(pBuf->p, nNew);
+ pNew = sqlite3_realloc64(pBuf->p, nNew);
if( pNew==0 ){
*pRc = SQLITE_NOMEM;
return 1;
@@ -52,7 +52,7 @@ void sqlite3Fts5Put32(u8 *aBuf, int iVal){
}
int sqlite3Fts5Get32(const u8 *aBuf){
- return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3];
+ return (int)((((u32)aBuf[0])<<24) + (aBuf[1]<<16) + (aBuf[2]<<8) + aBuf[3]);
}
/*
@@ -183,7 +183,7 @@ int sqlite3Fts5PoslistNext64(
iOff = ((i64)iVal) << 32;
fts5FastGetVarint32(a, i, iVal);
}
- *piOff = iOff + (iVal-2);
+ *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
*pi = i;
return 0;
}
@@ -244,10 +244,10 @@ int sqlite3Fts5PoslistWriterAppend(
return SQLITE_OK;
}
-void *sqlite3Fts5MallocZero(int *pRc, int nByte){
+void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte){
void *pRet = 0;
if( *pRc==SQLITE_OK ){
- pRet = sqlite3_malloc(nByte);
+ pRet = sqlite3_malloc64(nByte);
if( pRet==0 ){
if( nByte>0 ) *pRc = SQLITE_NOMEM;
}else{
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_config.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_config.c
index d0718f4dec6..f479d7ab163 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_config.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_config.c
@@ -295,7 +295,7 @@ static int fts5ConfigParseSpecial(
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
const char *p = (const char*)zArg;
- int nArg = (int)strlen(zArg) + 1;
+ sqlite3_int64 nArg = strlen(zArg) + 1;
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2);
char *pSpace = pDel;
@@ -425,8 +425,8 @@ static const char *fts5ConfigGobbleWord(
){
const char *zRet = 0;
- int nIn = (int)strlen(zIn);
- char *zOut = sqlite3_malloc(nIn+1);
+ sqlite3_int64 nIn = strlen(zIn);
+ char *zOut = sqlite3_malloc64(nIn+1);
assert( *pRc==SQLITE_OK );
*pbQuoted = 0;
@@ -529,7 +529,7 @@ int sqlite3Fts5ConfigParse(
int rc = SQLITE_OK; /* Return code */
Fts5Config *pRet; /* New object to return */
int i;
- int nByte;
+ sqlite3_int64 nByte;
*ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config));
if( pRet==0 ) return SQLITE_NOMEM;
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c
index 8d155df4ae4..dc52cf602ee 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c
@@ -211,7 +211,7 @@ static int fts5ExprGetToken(
return tok;
}
-static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc((int)t); }
+static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc64((sqlite3_int64)t);}
static void fts5ParseFree(void *p){ sqlite3_free(p); }
int sqlite3Fts5ExprNew(
@@ -356,8 +356,8 @@ static int fts5ExprSynonymList(
if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){
if( pIter->nData==0 ) continue;
if( nIter==nAlloc ){
- int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
- Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
+ Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
goto synonym_poslist_out;
@@ -437,8 +437,8 @@ static int fts5ExprPhraseIsMatch(
/* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */
if( pPhrase->nTerm>ArraySize(aStatic) ){
- int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
- aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm;
+ aIter = (Fts5PoslistReader*)sqlite3_malloc64(nByte);
if( !aIter ) return SQLITE_NOMEM;
}
memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm);
@@ -572,7 +572,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
/* If the aStatic[] array is not large enough, allocate a large array
** using sqlite3_malloc(). This approach could be improved upon. */
if( pNear->nPhrase>ArraySize(aStatic) ){
- int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
+ sqlite3_int64 nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase;
a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte);
}else{
memset(aStatic, 0, sizeof(aStatic));
@@ -1481,8 +1481,9 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
return pNear;
}
if( pNear==0 ){
- int nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
- pRet = sqlite3_malloc(nByte);
+ sqlite3_int64 nByte;
+ nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
+ pRet = sqlite3_malloc64(nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
}else{
@@ -1490,9 +1491,10 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
}
}else if( (pNear->nPhrase % SZALLOC)==0 ){
int nNew = pNear->nPhrase + SZALLOC;
- int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
+ sqlite3_int64 nByte;
- pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte);
+ nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
+ pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
}
@@ -1556,8 +1558,8 @@ static int fts5ParseTokenize(
if( pPhrase && pPhrase->nTerm>0 && (tflags & FTS5_TOKEN_COLOCATED) ){
Fts5ExprTerm *pSyn;
- int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
- pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1;
+ pSyn = (Fts5ExprTerm*)sqlite3_malloc64(nByte);
if( pSyn==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1573,7 +1575,7 @@ static int fts5ParseTokenize(
Fts5ExprPhrase *pNew;
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
- pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase,
+ pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
);
if( pNew==0 ){
@@ -1659,9 +1661,9 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
if( pAppend==0 ){
if( (pParse->nPhrase % 8)==0 ){
- int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
+ sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
Fts5ExprPhrase **apNew;
- apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte);
+ apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
if( apNew==0 ){
pParse->rc = SQLITE_NOMEM;
fts5ExprPhraseFree(sCtx.pPhrase);
@@ -1716,8 +1718,10 @@ int sqlite3Fts5ExprClonePhrase(
if( rc==SQLITE_OK ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
- int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
- Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
+ sqlite3_int64 nByte;
+ Fts5Colset *pColset;
+ nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
+ pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
if( pColset ){
memcpy(pColset, pColsetOrig, nByte);
}
@@ -1837,7 +1841,7 @@ static Fts5Colset *fts5ParseColset(
assert( pParse->rc==SQLITE_OK );
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
- pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
+ pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
if( pNew==0 ){
pParse->rc = SQLITE_NOMEM;
}else{
@@ -1933,7 +1937,7 @@ Fts5Colset *sqlite3Fts5ParseColset(
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
Fts5Colset *pRet;
if( pOrig ){
- int nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
+ sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
if( pRet ){
memcpy(pRet, pOrig, nByte);
@@ -2087,7 +2091,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
if( pParse->rc==SQLITE_OK ){
int nChild = 0; /* Number of children of returned node */
- int nByte; /* Bytes of space to allocate for this node */
+ sqlite3_int64 nByte; /* Bytes of space to allocate for this node */
assert( (eType!=FTS5_STRING && !pNear)
|| (eType==FTS5_STRING && !pLeft && !pRight)
@@ -2219,7 +2223,7 @@ Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
}
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
- int nByte = 0;
+ sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
char *zQuoted;
@@ -2227,7 +2231,7 @@ static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
for(p=pTerm; p; p=p->pSynonym){
nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2;
}
- zQuoted = sqlite3_malloc(nByte);
+ zQuoted = sqlite3_malloc64(nByte);
if( zQuoted ){
int i = 0;
@@ -2467,7 +2471,7 @@ static void fts5ExprFunction(
}
nConfig = 3 + (nArg-iArg);
- azConfig = (const char**)sqlite3_malloc(sizeof(char*) * nConfig);
+ azConfig = (const char**)sqlite3_malloc64(sizeof(char*) * nConfig);
if( azConfig==0 ){
sqlite3_result_error_nomem(pCtx);
return;
@@ -2553,7 +2557,7 @@ static void fts5ExprIsAlnum(
sqlite3Fts5UnicodeCatParse("N*", aArr);
sqlite3Fts5UnicodeCatParse("Co", aArr);
iCode = sqlite3_value_int(apVal[0]);
- sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]);
+ sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory((u32)iCode)]);
}
static void fts5ExprFold(
@@ -2648,7 +2652,7 @@ struct Fts5PoslistPopulator {
Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
Fts5PoslistPopulator *pRet;
- pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
+ pRet = sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
if( pRet ){
int i;
memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
@@ -2847,4 +2851,3 @@ int sqlite3Fts5ExprPhraseCollist(
return rc;
}
-
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c
index bc79aad2515..71219ab3e14 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c
@@ -90,14 +90,14 @@ int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
- int nByte;
+ sqlite3_int64 nByte;
memset(pNew, 0, sizeof(Fts5Hash));
pNew->pnByte = pnByte;
pNew->eDetail = pConfig->eDetail;
pNew->nSlot = 1024;
nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
- pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
+ pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc64(nByte);
if( pNew->aSlot==0 ){
sqlite3_free(pNew);
*ppNew = 0;
@@ -165,7 +165,7 @@ static int fts5HashResize(Fts5Hash *pHash){
Fts5HashEntry **apNew;
Fts5HashEntry **apOld = pHash->aSlot;
- apNew = (Fts5HashEntry**)sqlite3_malloc(nNew*sizeof(Fts5HashEntry*));
+ apNew = (Fts5HashEntry**)sqlite3_malloc64(nNew*sizeof(Fts5HashEntry*));
if( !apNew ) return SQLITE_NOMEM;
memset(apNew, 0, nNew*sizeof(Fts5HashEntry*));
@@ -259,7 +259,7 @@ int sqlite3Fts5HashWrite(
if( p==0 ){
/* Figure out how much space to allocate */
char *zKey;
- int nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
+ sqlite3_int64 nByte = sizeof(Fts5HashEntry) + (nToken+1) + 1 + 64;
if( nByte<128 ) nByte = 128;
/* Grow the Fts5Hash.aSlot[] array if necessary. */
@@ -270,7 +270,7 @@ int sqlite3Fts5HashWrite(
}
/* Allocate new Fts5HashEntry and add it to the hash table. */
- p = (Fts5HashEntry*)sqlite3_malloc(nByte);
+ p = (Fts5HashEntry*)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, sizeof(Fts5HashEntry));
p->nAlloc = nByte;
@@ -309,12 +309,12 @@ int sqlite3Fts5HashWrite(
** + 5 bytes for the new position offset (32-bit max).
*/
if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
- int nNew = p->nAlloc * 2;
+ sqlite3_int64 nNew = p->nAlloc * 2;
Fts5HashEntry *pNew;
Fts5HashEntry **pp;
- pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
+ pNew = (Fts5HashEntry*)sqlite3_realloc64(p, nNew);
if( pNew==0 ) return SQLITE_NOMEM;
- pNew->nAlloc = nNew;
+ pNew->nAlloc = (int)nNew;
for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
*pp = pNew;
p = pNew;
@@ -438,7 +438,7 @@ static int fts5HashEntrySort(
int i;
*ppSorted = 0;
- ap = sqlite3_malloc(sizeof(Fts5HashEntry*) * nMergeSlot);
+ ap = sqlite3_malloc64(sizeof(Fts5HashEntry*) * nMergeSlot);
if( !ap ) return SQLITE_NOMEM;
memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot);
@@ -483,7 +483,8 @@ int sqlite3Fts5HashQuery(
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
zKey = fts5EntryKey(p);
- if( memcmp(zKey, pTerm, nTerm)==0 && zKey[nTerm]==0 ) break;
+ assert( p->nKey+1==(int)strlen(zKey) );
+ if( nTerm==p->nKey+1 && memcmp(zKey, pTerm, nTerm)==0 ) break;
}
if( p ){
@@ -534,4 +535,3 @@ void sqlite3Fts5HashScanEntry(
*pnDoclist = 0;
}
}
-
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c
index 7cacf930cc8..bc85d864d79 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c
@@ -512,7 +512,6 @@ struct Fts5Iter {
Fts5IndexIter base; /* Base class containing output vars */
Fts5Index *pIndex; /* Index that owns this iterator */
- Fts5Structure *pStruct; /* Database structure for this iterator */
Fts5Buffer poslist; /* Buffer containing current poslist */
Fts5Colset *pColset; /* Restrict matches to these columns */
@@ -573,7 +572,7 @@ static u16 fts5GetU16(const u8 *aIn){
** If an OOM error is encountered, return NULL and set the error code in
** the Fts5Index handle passed as the first argument.
*/
-static void *fts5IdxMalloc(Fts5Index *p, int nByte){
+static void *fts5IdxMalloc(Fts5Index *p, sqlite3_int64 nByte){
return sqlite3Fts5MallocZero(&p->rc, nByte);
}
@@ -607,7 +606,7 @@ static int fts5BufferCompareBlob(
*/
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
int nCmp = MIN(pLeft->n, pRight->n);
- int res = memcmp(pLeft->p, pRight->p, nCmp);
+ int res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
return (res==0 ? (pLeft->n - pRight->n) : res);
}
@@ -673,8 +672,8 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
if( rc==SQLITE_OK ){
u8 *aOut = 0; /* Read blob data into this buffer */
int nByte = sqlite3_blob_bytes(p->pReader);
- int nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
- pRet = (Fts5Data*)sqlite3_malloc(nAlloc);
+ sqlite3_int64 nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING;
+ pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
if( pRet ){
pRet->nn = nByte;
aOut = pRet->p = (u8*)&pRet[1];
@@ -690,6 +689,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
pRet = 0;
}else{
/* TODO1: Fix this */
+ pRet->p[nByte] = 0x00;
pRet->szLeaf = fts5GetU16(&pRet->p[2]);
}
}
@@ -848,7 +848,7 @@ static int fts5StructureDecode(
int iLvl;
int nLevel = 0;
int nSegment = 0;
- int nByte; /* Bytes of space to allocate at pRet */
+ sqlite3_int64 nByte; /* Bytes of space to allocate at pRet */
Fts5Structure *pRet = 0; /* Structure object to return */
/* Grab the cookie value */
@@ -859,6 +859,11 @@ static int fts5StructureDecode(
** structure record. */
i += fts5GetVarint32(&pData[i], nLevel);
i += fts5GetVarint32(&pData[i], nSegment);
+ if( nLevel>FTS5_MAX_SEGMENT || nLevel<0
+ || nSegment>FTS5_MAX_SEGMENT || nSegment<0
+ ){
+ return FTS5_CORRUPT;
+ }
nByte = (
sizeof(Fts5Structure) + /* Main structure */
sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
@@ -881,25 +886,35 @@ static int fts5StructureDecode(
}else{
i += fts5GetVarint32(&pData[i], pLvl->nMerge);
i += fts5GetVarint32(&pData[i], nTotal);
- assert( nTotal>=pLvl->nMerge );
+ if( nTotal<pLvl->nMerge ) rc = FTS5_CORRUPT;
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
nTotal * sizeof(Fts5StructureSegment)
);
+ nSegment -= nTotal;
}
if( rc==SQLITE_OK ){
pLvl->nSeg = nTotal;
for(iSeg=0; iSeg<nTotal; iSeg++){
+ Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg];
if( i>=nData ){
rc = FTS5_CORRUPT;
break;
}
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid);
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst);
- i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast);
+ i += fts5GetVarint32(&pData[i], pSeg->iSegid);
+ i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst);
+ i += fts5GetVarint32(&pData[i], pSeg->pgnoLast);
+ if( pSeg->pgnoLast<pSeg->pgnoFirst ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
}
+ if( iLvl>0 && pLvl[-1].nMerge && nTotal==0 ) rc = FTS5_CORRUPT;
+ if( iLvl==nLevel-1 && pLvl->nMerge ) rc = FTS5_CORRUPT;
}
}
+ if( nSegment!=0 && rc==SQLITE_OK ) rc = FTS5_CORRUPT;
+
if( rc!=SQLITE_OK ){
fts5StructureRelease(pRet);
pRet = 0;
@@ -917,12 +932,12 @@ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
if( *pRc==SQLITE_OK ){
Fts5Structure *pStruct = *ppStruct;
int nLevel = pStruct->nLevel;
- int nByte = (
+ sqlite3_int64 nByte = (
sizeof(Fts5Structure) + /* Main structure */
sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
);
- pStruct = sqlite3_realloc(pStruct, nByte);
+ pStruct = sqlite3_realloc64(pStruct, nByte);
if( pStruct ){
memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel));
pStruct->nLevel++;
@@ -947,10 +962,10 @@ static void fts5StructureExtendLevel(
if( *pRc==SQLITE_OK ){
Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl];
Fts5StructureSegment *aNew;
- int nByte;
+ sqlite3_int64 nByte;
nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment);
- aNew = sqlite3_realloc(pLvl->aSeg, nByte);
+ aNew = sqlite3_realloc64(pLvl->aSeg, nByte);
if( aNew ){
if( bInsert==0 ){
memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra);
@@ -1464,10 +1479,10 @@ static Fts5DlidxIter *fts5DlidxIterInit(
int bDone = 0;
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
- int nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
+ sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
Fts5DlidxIter *pNew;
- pNew = (Fts5DlidxIter*)sqlite3_realloc(pIter, nByte);
+ pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
if( pNew==0 ){
p->rc = SQLITE_NOMEM;
}else{
@@ -1637,12 +1652,13 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
int nNew; /* Bytes of new data */
iOff += fts5GetVarint32(&a[iOff], nNew);
- if( iOff+nNew>pIter->pLeaf->nn ){
+ if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
p->rc = FTS5_CORRUPT;
return;
}
pIter->term.n = nKeep;
fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
+ assert( pIter->term.n<=pIter->term.nSpace );
iOff += nNew;
pIter->iTermLeafOffset = iOff;
pIter->iTermLeafPgno = pIter->iLeafPgno;
@@ -1707,7 +1723,7 @@ static void fts5SegIterInit(
if( p->rc==SQLITE_OK ){
pIter->iLeafOffset = 4;
assert_nc( pIter->pLeaf->nn>4 );
- assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
+ assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
fts5SegIterLoadTerm(p, pIter, 0);
fts5SegIterLoadNPos(p, pIter);
@@ -1763,7 +1779,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
/* If necessary, grow the pIter->aRowidOffset[] array. */
if( iRowidOffset>=pIter->nRowidOffset ){
int nNew = pIter->nRowidOffset + 8;
- int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
+ int *aNew = (int*)sqlite3_realloc64(pIter->aRowidOffset,nNew*sizeof(int));
if( aNew==0 ){
p->rc = SQLITE_NOMEM;
break;
@@ -2217,10 +2233,10 @@ static void fts5LeafSeek(
int szLeaf = pIter->pLeaf->szLeaf;
int n = pIter->pLeaf->nn;
- int nMatch = 0;
- int nKeep = 0;
- int nNew = 0;
- int iTermOff;
+ u32 nMatch = 0;
+ u32 nKeep = 0;
+ u32 nNew = 0;
+ u32 iTermOff;
int iPgidx; /* Current offset in pgidx */
int bEndOfPage = 0;
@@ -2244,15 +2260,15 @@ static void fts5LeafSeek(
assert( nKeep>=nMatch );
if( nKeep==nMatch ){
- int nCmp;
- int i;
- nCmp = MIN(nNew, nTerm-nMatch);
+ u32 nCmp;
+ u32 i;
+ nCmp = (u32)MIN(nNew, nTerm-nMatch);
for(i=0; i<nCmp; i++){
if( a[iOff+i]!=pTerm[nMatch+i] ) break;
}
nMatch += i;
- if( nTerm==nMatch ){
+ if( (u32)nTerm==nMatch ){
if( i==nNew ){
goto search_success;
}else{
@@ -2296,6 +2312,7 @@ static void fts5LeafSeek(
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
+ return;
}else{
nKeep = 0;
iTermOff = iOff;
@@ -2308,8 +2325,11 @@ static void fts5LeafSeek(
}
search_success:
-
pIter->iLeafOffset = iOff + nNew;
+ if( pIter->iLeafOffset>n || nNew<1 ){
+ p->rc = FTS5_CORRUPT;
+ return;
+ }
pIter->iTermLeafOffset = pIter->iLeafOffset;
pIter->iTermLeafPgno = pIter->iLeafPgno;
@@ -2416,7 +2436,7 @@ static void fts5SegIterSeekInit(
** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points
** to an entry with a term greater than or equal to (pTerm/nTerm).
*/
- assert( p->rc!=SQLITE_OK /* 1 */
+ assert_nc( p->rc!=SQLITE_OK /* 1 */
|| pIter->pLeaf==0 /* 2 */
|| fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */
|| (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */
@@ -2514,7 +2534,7 @@ static void fts5AssertComparisonResult(
assert( pRes->iFirst==i1 );
}else{
int nMin = MIN(p1->term.n, p2->term.n);
- int res = memcmp(p1->term.p, p2->term.p, nMin);
+ int res = fts5Memcmp(p1->term.p, p2->term.p, nMin);
if( res==0 ) res = p1->term.n - p2->term.n;
if( res==0 ){
@@ -2737,7 +2757,6 @@ static void fts5MultiIterFree(Fts5Iter *pIter){
for(i=0; i<pIter->nSeg; i++){
fts5SegIterClear(&pIter->aSeg[i]);
}
- fts5StructureRelease(pIter->pStruct);
fts5BufferFree(&pIter->poslist);
sqlite3_free(pIter);
}
@@ -3085,7 +3104,8 @@ static void fts5SegiterPoslist(
Fts5Colset *pColset,
Fts5Buffer *pBuf
){
- if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
+ if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
+ memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
if( pColset==0 ){
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
}else{
@@ -3383,9 +3403,7 @@ static void fts5MultiIterNew(
if( pNew==0 ) return;
pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
- pNew->pStruct = pStruct;
pNew->pColset = pColset;
- fts5StructureRef(pStruct);
if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){
fts5IterSetOutputCb(&p->rc, pNew);
}
@@ -3563,24 +3581,24 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
int iId = pStruct->aLevel[iLvl].aSeg[iSeg].iSegid;
- if( iId<=FTS5_MAX_SEGMENT ){
- aUsed[(iId-1) / 32] |= 1 << ((iId-1) % 32);
+ if( iId<=FTS5_MAX_SEGMENT && iId>0 ){
+ aUsed[(iId-1) / 32] |= (u32)1 << ((iId-1) % 32);
}
}
}
for(i=0; aUsed[i]==0xFFFFFFFF; i++);
mask = aUsed[i];
- for(iSegid=0; mask & (1 << iSegid); iSegid++);
+ for(iSegid=0; mask & ((u32)1 << iSegid); iSegid++);
iSegid += 1 + i*32;
#ifdef SQLITE_DEBUG
for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
- assert( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
+ assert_nc( iSegid!=pStruct->aLevel[iLvl].aSeg[iSeg].iSegid );
}
}
- assert( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
+ assert_nc( iSegid>0 && iSegid<=FTS5_MAX_SEGMENT );
{
sqlite3_stmt *pIdxSelect = fts5IdxSelectStmt(p);
@@ -3588,7 +3606,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){
u8 aBlob[2] = {0xff, 0xff};
sqlite3_bind_int(pIdxSelect, 1, iSegid);
sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC);
- assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
+ assert_nc( sqlite3_step(pIdxSelect)!=SQLITE_ROW );
p->rc = sqlite3_reset(pIdxSelect);
sqlite3_bind_null(pIdxSelect, 2);
}
@@ -3658,7 +3676,7 @@ static int fts5WriteDlidxGrow(
int nLvl
){
if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){
- Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc(
+ Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc64(
pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl
);
if( aDlidx==0 ){
@@ -3737,8 +3755,10 @@ static void fts5WriteBtreeTerm(
int nTerm, const u8 *pTerm /* First term on new page */
){
fts5WriteFlushBtree(p, pWriter);
- fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
- pWriter->iBtPage = pWriter->writer.pgno;
+ if( p->rc==SQLITE_OK ){
+ fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm);
+ pWriter->iBtPage = pWriter->writer.pgno;
+ }
}
/*
@@ -3889,6 +3909,7 @@ static void fts5WriteAppendTerm(
int nPrefix; /* Bytes of prefix compression for term */
Fts5PageWriter *pPage = &pWriter->writer;
Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
+ int nMin = MIN(pPage->term.n, nTerm);
assert( p->rc==SQLITE_OK );
assert( pPage->buf.n>=4 );
@@ -3898,6 +3919,7 @@ static void fts5WriteAppendTerm(
if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){
if( pPage->buf.n>4 ){
fts5WriteFlushLeaf(p, pWriter);
+ if( p->rc!=SQLITE_OK ) return;
}
fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING);
}
@@ -3930,13 +3952,14 @@ static void fts5WriteAppendTerm(
** inefficient, but still correct. */
int n = nTerm;
if( pPage->term.n ){
- n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
+ n = 1 + fts5PrefixCompress(nMin, pPage->term.p, pTerm);
}
fts5WriteBtreeTerm(p, pWriter, n, pTerm);
+ if( p->rc!=SQLITE_OK ) return;
pPage = &pWriter->writer;
}
}else{
- nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm);
+ nPrefix = fts5PrefixCompress(nMin, pPage->term.p, pTerm);
fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix);
}
@@ -3983,7 +4006,7 @@ static void fts5WriteAppendRowid(
if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
}else{
- assert( p->rc || iRowid>pWriter->iPrevRowid );
+ assert_nc( p->rc || iRowid>pWriter->iPrevRowid );
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
}
pWriter->iPrevRowid = iRowid;
@@ -4105,7 +4128,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
int i;
Fts5Buffer buf;
memset(&buf, 0, sizeof(Fts5Buffer));
- for(i=0; i<pIter->nSeg; i++){
+ for(i=0; i<pIter->nSeg && p->rc==SQLITE_OK; i++){
Fts5SegIter *pSeg = &pIter->aSeg[i];
if( pSeg->pSeg==0 ){
/* no-op */
@@ -4123,35 +4146,43 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00};
iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno);
- pData = fts5DataRead(p, iLeafRowid);
+ pData = fts5LeafRead(p, iLeafRowid);
if( pData ){
- fts5BufferZero(&buf);
- fts5BufferGrow(&p->rc, &buf, pData->nn);
- fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
- fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
- fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
- fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]);
- if( p->rc==SQLITE_OK ){
- /* Set the szLeaf field */
- fts5PutU16(&buf.p[2], (u16)buf.n);
- }
+ if( iOff>pData->szLeaf ){
+ /* This can occur if the pages that the segments occupy overlap - if
+ ** a single page has been assigned to more than one segment. In
+ ** this case a prior iteration of this loop may have corrupted the
+ ** segment currently being trimmed. */
+ p->rc = FTS5_CORRUPT;
+ }else{
+ fts5BufferZero(&buf);
+ fts5BufferGrow(&p->rc, &buf, pData->nn);
+ fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr);
+ fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n);
+ fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p);
+ fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff,&pData->p[iOff]);
+ if( p->rc==SQLITE_OK ){
+ /* Set the szLeaf field */
+ fts5PutU16(&buf.p[2], (u16)buf.n);
+ }
- /* Set up the new page-index array */
- fts5BufferAppendVarint(&p->rc, &buf, 4);
- if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
- && pSeg->iEndofDoclist<pData->szLeaf
- ){
- int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
- fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
- fts5BufferAppendBlob(&p->rc, &buf,
- pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
- );
- }
+ /* Set up the new page-index array */
+ fts5BufferAppendVarint(&p->rc, &buf, 4);
+ if( pSeg->iLeafPgno==pSeg->iTermLeafPgno
+ && pSeg->iEndofDoclist<pData->szLeaf
+ ){
+ int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
+ fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
+ fts5BufferAppendBlob(&p->rc, &buf,
+ pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
+ );
+ }
+ pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
+ fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
+ fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
+ }
fts5DataRelease(pData);
- pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
- fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
- fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
}
}
}
@@ -4243,7 +4274,7 @@ static void fts5IndexMergeLevel(
const u8 *pTerm;
pTerm = fts5MultiIterTerm(pIter, &nTerm);
- if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){
+ if( nTerm!=term.n || fts5Memcmp(pTerm, term.p, nTerm) ){
if( pnRem && writer.nLeafWritten>nRem ){
break;
}
@@ -4498,6 +4529,7 @@ static void fts5FlushOneHash(Fts5Index *p){
/* Write the term for this entry to disk. */
sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm);
+ if( p->rc!=SQLITE_OK ) break;
assert( writer.bFirstRowidInPage==0 );
if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
@@ -4520,6 +4552,7 @@ static void fts5FlushOneHash(Fts5Index *p){
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
writer.bFirstRowidInPage = 0;
fts5WriteDlidxAppend(p, &writer, iRowid);
+ if( p->rc!=SQLITE_OK ) break;
}else{
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
}
@@ -4577,7 +4610,7 @@ static void fts5FlushOneHash(Fts5Index *p){
/* TODO2: Doclist terminator written here. */
/* pBuf->p[pBuf->n++] = '\0'; */
assert( pBuf->n<=pBuf->nSpace );
- sqlite3Fts5HashScanNext(pHash);
+ if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash);
}
sqlite3Fts5HashClear(pHash);
fts5WriteFinish(p, &writer, &pgnoLast);
@@ -4621,7 +4654,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
Fts5Structure *pStruct
){
Fts5Structure *pNew = 0;
- int nByte = sizeof(Fts5Structure);
+ sqlite3_int64 nByte = sizeof(Fts5Structure);
int nSeg = pStruct->nSegment;
int i;
@@ -4751,11 +4784,13 @@ static void fts5AppendPoslist(
Fts5Buffer *pBuf
){
int nData = pMulti->base.nData;
+ int nByte = nData + 9 + 9 + FTS5_DATA_ZERO_PADDING;
assert( nData>0 );
- if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){
+ if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nByte) ){
fts5BufferSafeAppendVarint(pBuf, iDelta);
fts5BufferSafeAppendVarint(pBuf, nData*2);
fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData);
+ memset(&pBuf->p[pBuf->n], 0, FTS5_DATA_ZERO_PADDING);
}
}
@@ -4936,6 +4971,8 @@ static void fts5MergePrefixLists(
int iOff2 = 0;
u8 *a1 = &i1.aPoslist[i1.nSize];
u8 *a2 = &i2.aPoslist[i2.nSize];
+ int nCopy;
+ u8 *aCopy;
i64 iPrev = 0;
Fts5PoslistWriter writer;
@@ -4967,7 +5004,7 @@ static void fts5MergePrefixLists(
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
if( iPos1<0 ) break;
}else{
- assert( iPos2!=iPrev );
+ assert_nc( iPos2!=iPrev );
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
if( iPos2<0 ) break;
@@ -4979,11 +5016,16 @@ static void fts5MergePrefixLists(
if( iPos1!=iPrev ){
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
}
- fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1);
+ aCopy = &a1[iOff1];
+ nCopy = i1.nPoslist - iOff1;
}else{
assert( iPos2>=0 && iPos2!=iPrev );
sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2);
+ aCopy = &a2[iOff2];
+ nCopy = i2.nPoslist - iOff2;
+ }
+ if( nCopy>0 ){
+ fts5BufferSafeAppendBlob(&tmp, aCopy, nCopy);
}
/* WRITEPOSLISTSIZE */
@@ -4991,6 +5033,7 @@ static void fts5MergePrefixLists(
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
fts5DoclistIterNext(&i1);
fts5DoclistIterNext(&i2);
+ assert( out.n<=(p1->n+p2->n+9) );
if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
}
}
@@ -5092,7 +5135,7 @@ static void fts5SetupPrefixIter(
}
fts5MultiIterFree(p1);
- pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n);
+ pData = fts5IdxMalloc(p, sizeof(Fts5Data)+doclist.n+FTS5_DATA_ZERO_PADDING);
if( pData ){
pData->p = (u8*)&pData[1];
pData->nn = pData->szLeaf = doclist.n;
@@ -5854,11 +5897,11 @@ static void fts5IndexIntegrityCheckSegment(
iOff = fts5LeafFirstTermOff(pLeaf);
iRowidOff = fts5LeafFirstRowidOff(pLeaf);
- if( iRowidOff>=iOff ){
+ if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
}else{
iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
- res = memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
+ res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
if( res==0 ) res = nTerm - nIdxTerm;
if( res<0 ) p->rc = FTS5_CORRUPT;
}
@@ -6253,7 +6296,7 @@ static void fts5DecodeFunction(
u8 *a = 0;
Fts5Buffer s; /* Build up text to return here */
int rc = SQLITE_OK; /* Return code */
- int nSpace = 0;
+ sqlite3_int64 nSpace = 0;
int eDetailNone = (sqlite3_user_data(pCtx)!=0);
assert( nArg==2 );
@@ -6269,8 +6312,7 @@ static void fts5DecodeFunction(
nSpace = n + FTS5_DATA_ZERO_PADDING;
a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
if( a==0 ) goto decode_out;
- memcpy(a, aBlob, n);
-
+ if( n>0 ) memcpy(a, aBlob, n);
fts5DecodeRowid(iRowid, &iSegid, &bDlidx, &iHeight, &iPgno);
@@ -6365,6 +6407,9 @@ static void fts5DecodeFunction(
iPgidxOff = szLeaf = fts5GetU16(&a[2]);
if( iPgidxOff<n ){
fts5GetVarint32(&a[iPgidxOff], iTermOff);
+ }else if( iPgidxOff>n ){
+ rc = FTS5_CORRUPT;
+ goto decode_out;
}
}
@@ -6376,14 +6421,22 @@ static void fts5DecodeFunction(
}else{
iOff = szLeaf;
}
+ if( iOff>n ){
+ rc = FTS5_CORRUPT;
+ goto decode_out;
+ }
fts5DecodePoslist(&rc, &s, &a[4], iOff-4);
/* Decode any more doclist data that appears on the page before the
** first term. */
nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff;
+ if( nDoclist+iOff>n ){
+ rc = FTS5_CORRUPT;
+ goto decode_out;
+ }
fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist);
- while( iPgidxOff<n ){
+ while( iPgidxOff<n && rc==SQLITE_OK ){
int bFirst = (iPgidxOff==szLeaf); /* True for first term on page */
int nByte; /* Bytes of data */
int iEnd;
@@ -6398,12 +6451,24 @@ static void fts5DecodeFunction(
}else{
iEnd = szLeaf;
}
+ if( iEnd>szLeaf ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
if( bFirst==0 ){
iOff += fts5GetVarint32(&a[iOff], nByte);
+ if( nByte>term.n ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
term.n = nByte;
}
iOff += fts5GetVarint32(&a[iOff], nByte);
+ if( iOff+nByte>n ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
iOff += nByte;
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c
index 9c10405c627..8d4ddabb46c 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c
@@ -28,8 +28,8 @@ int sqlite3_fts5_may_be_corrupt = 1;
typedef struct Fts5Auxdata Fts5Auxdata;
typedef struct Fts5Auxiliary Fts5Auxiliary;
typedef struct Fts5Cursor Fts5Cursor;
+typedef struct Fts5FullTable Fts5FullTable;
typedef struct Fts5Sorter Fts5Sorter;
-typedef struct Fts5Table Fts5Table;
typedef struct Fts5TokenizerModule Fts5TokenizerModule;
/*
@@ -110,13 +110,8 @@ struct Fts5TokenizerModule {
Fts5TokenizerModule *pNext; /* Next registered tokenizer module */
};
-/*
-** Virtual-table object.
-*/
-struct Fts5Table {
- sqlite3_vtab base; /* Base class used by SQLite core */
- Fts5Config *pConfig; /* Virtual table configuration */
- Fts5Index *pIndex; /* Full-text index */
+struct Fts5FullTable {
+ Fts5Table p; /* Public class members from fts5Int.h */
Fts5Storage *pStorage; /* Document store */
Fts5Global *pGlobal; /* Global (connection wide) data */
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
@@ -254,7 +249,7 @@ struct Fts5Auxdata {
#define FTS5_SAVEPOINT 5
#define FTS5_RELEASE 6
#define FTS5_ROLLBACKTO 7
-static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
+static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
switch( op ){
case FTS5_BEGIN:
assert( p->ts.eState==0 );
@@ -293,7 +288,7 @@ static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
case FTS5_ROLLBACKTO:
assert( p->ts.eState==1 );
- assert( iSavepoint>=0 );
+ assert( iSavepoint>=-1 );
assert( iSavepoint<=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint;
break;
@@ -306,18 +301,18 @@ static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
/*
** Return true if pTab is a contentless table.
*/
-static int fts5IsContentless(Fts5Table *pTab){
- return pTab->pConfig->eContent==FTS5_CONTENT_NONE;
+static int fts5IsContentless(Fts5FullTable *pTab){
+ return pTab->p.pConfig->eContent==FTS5_CONTENT_NONE;
}
/*
** Delete a virtual table handle allocated by fts5InitVtab().
*/
-static void fts5FreeVtab(Fts5Table *pTab){
+static void fts5FreeVtab(Fts5FullTable *pTab){
if( pTab ){
- sqlite3Fts5IndexClose(pTab->pIndex);
+ sqlite3Fts5IndexClose(pTab->p.pIndex);
sqlite3Fts5StorageClose(pTab->pStorage);
- sqlite3Fts5ConfigFree(pTab->pConfig);
+ sqlite3Fts5ConfigFree(pTab->p.pConfig);
sqlite3_free(pTab);
}
}
@@ -326,7 +321,7 @@ static void fts5FreeVtab(Fts5Table *pTab){
** The xDisconnect() virtual table method.
*/
static int fts5DisconnectMethod(sqlite3_vtab *pVtab){
- fts5FreeVtab((Fts5Table*)pVtab);
+ fts5FreeVtab((Fts5FullTable*)pVtab);
return SQLITE_OK;
}
@@ -337,7 +332,7 @@ static int fts5DestroyMethod(sqlite3_vtab *pVtab){
Fts5Table *pTab = (Fts5Table*)pVtab;
int rc = sqlite3Fts5DropAll(pTab->pConfig);
if( rc==SQLITE_OK ){
- fts5FreeVtab((Fts5Table*)pVtab);
+ fts5FreeVtab((Fts5FullTable*)pVtab);
}
return rc;
}
@@ -366,28 +361,28 @@ static int fts5InitVtab(
const char **azConfig = (const char**)argv;
int rc = SQLITE_OK; /* Return code */
Fts5Config *pConfig = 0; /* Results of parsing argc/argv */
- Fts5Table *pTab = 0; /* New virtual table object */
+ Fts5FullTable *pTab = 0; /* New virtual table object */
/* Allocate the new vtab object and parse the configuration */
- pTab = (Fts5Table*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Table));
+ pTab = (Fts5FullTable*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5FullTable));
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr);
assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 );
}
if( rc==SQLITE_OK ){
- pTab->pConfig = pConfig;
+ pTab->p.pConfig = pConfig;
pTab->pGlobal = pGlobal;
}
/* Open the index sub-system */
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->pIndex, pzErr);
+ rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->p.pIndex, pzErr);
}
/* Open the storage sub-system */
if( rc==SQLITE_OK ){
rc = sqlite3Fts5StorageOpen(
- pConfig, pTab->pIndex, bCreate, &pTab->pStorage, pzErr
+ pConfig, pTab->p.pIndex, bCreate, &pTab->pStorage, pzErr
);
}
@@ -400,8 +395,8 @@ static int fts5InitVtab(
if( rc==SQLITE_OK ){
assert( pConfig->pzErrmsg==0 );
pConfig->pzErrmsg = pzErr;
- rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
- sqlite3Fts5IndexRollback(pTab->pIndex);
+ rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
+ sqlite3Fts5IndexRollback(pTab->p.pIndex);
pConfig->pzErrmsg = 0;
}
@@ -614,7 +609,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
return SQLITE_OK;
}
-static int fts5NewTransaction(Fts5Table *pTab){
+static int fts5NewTransaction(Fts5FullTable *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->base.pVtab==(sqlite3_vtab*)pTab ) return SQLITE_OK;
@@ -626,16 +621,16 @@ static int fts5NewTransaction(Fts5Table *pTab){
** Implementation of xOpen method.
*/
static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
- Fts5Table *pTab = (Fts5Table*)pVTab;
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVTab;
+ Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = 0; /* New cursor object */
- int nByte; /* Bytes of space to allocate */
+ sqlite3_int64 nByte; /* Bytes of space to allocate */
int rc; /* Return code */
rc = fts5NewTransaction(pTab);
if( rc==SQLITE_OK ){
nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int);
- pCsr = (Fts5Cursor*)sqlite3_malloc(nByte);
+ pCsr = (Fts5Cursor*)sqlite3_malloc64(nByte);
if( pCsr ){
Fts5Global *pGlobal = pTab->pGlobal;
memset(pCsr, 0, nByte);
@@ -673,7 +668,7 @@ static void fts5CsrNewrow(Fts5Cursor *pCsr){
}
static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
Fts5Auxdata *pData;
Fts5Auxdata *pNext;
@@ -717,7 +712,7 @@ static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
*/
static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
if( pCursor ){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
Fts5Cursor **pp;
@@ -774,7 +769,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors
** open on table pTab.
*/
-static void fts5TripCursors(Fts5Table *pTab){
+static void fts5TripCursors(Fts5FullTable *pTab){
Fts5Cursor *pCsr;
for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
if( pCsr->ePlan==FTS5_PLAN_MATCH
@@ -801,11 +796,11 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
int rc = SQLITE_OK;
assert( *pbSkip==0 );
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int bDesc = pCsr->bDesc;
i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
- rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc);
+ rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc);
if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
*pbSkip = 1;
}
@@ -902,18 +897,22 @@ static int fts5PrepareStatement(
return rc;
}
-static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
- Fts5Config *pConfig = pTab->pConfig;
+static int fts5CursorFirstSorted(
+ Fts5FullTable *pTab,
+ Fts5Cursor *pCsr,
+ int bDesc
+){
+ Fts5Config *pConfig = pTab->p.pConfig;
Fts5Sorter *pSorter;
int nPhrase;
- int nByte;
+ sqlite3_int64 nByte;
int rc;
const char *zRank = pCsr->zRank;
const char *zRankArgs = pCsr->zRankArgs;
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
- pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
+ pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
if( pSorter==0 ) return SQLITE_NOMEM;
memset(pSorter, 0, nByte);
pSorter->nIdx = nPhrase;
@@ -950,10 +949,10 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
return rc;
}
-static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
+static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
int rc;
Fts5Expr *pExpr = pCsr->pExpr;
- rc = sqlite3Fts5ExprFirst(pExpr, pTab->pIndex, pCsr->iFirstRowid, bDesc);
+ rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc);
if( sqlite3Fts5ExprEof(pExpr) ){
CsrFlagSet(pCsr, FTS5CSR_EOF);
}
@@ -968,7 +967,7 @@ static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){
** parameters.
*/
static int fts5SpecialMatch(
- Fts5Table *pTab,
+ Fts5FullTable *pTab,
Fts5Cursor *pCsr,
const char *zQuery
){
@@ -979,18 +978,18 @@ static int fts5SpecialMatch(
while( z[0]==' ' ) z++;
for(n=0; z[n] && z[n]!=' '; n++);
- assert( pTab->base.zErrMsg==0 );
+ assert( pTab->p.base.zErrMsg==0 );
pCsr->ePlan = FTS5_PLAN_SPECIAL;
if( 0==sqlite3_strnicmp("reads", z, n) ){
- pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->pIndex);
+ pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex);
}
else if( 0==sqlite3_strnicmp("id", z, n) ){
pCsr->iSpecial = pCsr->iCsrId;
}
else{
/* An unrecognized directive. Return an error message. */
- pTab->base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
+ pTab->p.base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z);
rc = SQLITE_ERROR;
}
@@ -1002,7 +1001,7 @@ static int fts5SpecialMatch(
** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary
** structure. Otherwise, if no such function exists, return NULL.
*/
-static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
+static Fts5Auxiliary *fts5FindAuxiliary(Fts5FullTable *pTab, const char *zName){
Fts5Auxiliary *pAux;
for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){
@@ -1015,8 +1014,8 @@ static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){
static int fts5FindRankFunction(Fts5Cursor *pCsr){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
+ Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
Fts5Auxiliary *pAux = 0;
const char *zRank = pCsr->zRank;
@@ -1032,7 +1031,7 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
if( rc==SQLITE_OK ){
if( SQLITE_ROW==sqlite3_step(pStmt) ){
- int nByte;
+ sqlite3_int64 nByte;
pCsr->nRankArg = sqlite3_column_count(pStmt);
nByte = sizeof(sqlite3_value*)*pCsr->nRankArg;
pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte);
@@ -1054,8 +1053,8 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
if( rc==SQLITE_OK ){
pAux = fts5FindAuxiliary(pTab, zRank);
if( pAux==0 ){
- assert( pTab->base.zErrMsg==0 );
- pTab->base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
+ assert( pTab->p.base.zErrMsg==0 );
+ pTab->p.base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank);
rc = SQLITE_ERROR;
}
}
@@ -1130,8 +1129,8 @@ static int fts5FilterMethod(
int nVal, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
+ Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK; /* Error code */
int iVal = 0; /* Counter for apVal[] */
@@ -1160,8 +1159,8 @@ static int fts5FilterMethod(
assert( pCsr->zRank==0 );
assert( pCsr->zRankArgs==0 );
- assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg );
- pConfig->pzErrmsg = &pTab->base.zErrMsg;
+ assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
+ pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Decode the arguments passed through to this function.
**
@@ -1227,7 +1226,7 @@ static int fts5FilterMethod(
** but a request for an internal parameter. */
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
}else{
- char **pzErr = &pTab->base.zErrMsg;
+ char **pzErr = &pTab->p.base.zErrMsg;
rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
if( rc==SQLITE_OK ){
if( bOrderByRank ){
@@ -1250,7 +1249,7 @@ static int fts5FilterMethod(
** by rowid (ePlan==FTS5_PLAN_ROWID). */
pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN);
rc = sqlite3Fts5StorageStmt(
- pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->base.zErrMsg
+ pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
);
if( rc==SQLITE_OK ){
if( pCsr->ePlan==FTS5_PLAN_ROWID ){
@@ -1333,12 +1332,12 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
/* If the cursor does not yet have a statement handle, obtain one now. */
if( pCsr->pStmt==0 ){
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int eStmt = fts5StmtType(pCsr);
rc = sqlite3Fts5StorageStmt(
- pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->base.zErrMsg:0)
+ pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->p.base.zErrMsg:0)
);
- assert( rc!=SQLITE_OK || pTab->base.zErrMsg==0 );
+ assert( rc!=SQLITE_OK || pTab->p.base.zErrMsg==0 );
assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
}
@@ -1360,11 +1359,11 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
return rc;
}
-static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
+static void fts5SetVtabError(Fts5FullTable *p, const char *zFormat, ...){
va_list ap; /* ... printf arguments */
va_start(ap, zFormat);
- assert( p->base.zErrMsg==0 );
- p->base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
+ assert( p->p.base.zErrMsg==0 );
+ p->p.base.zErrMsg = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
}
@@ -1384,11 +1383,11 @@ static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){
** more commands are added to this function.
*/
static int fts5SpecialInsert(
- Fts5Table *pTab, /* Fts5 table object */
+ Fts5FullTable *pTab, /* Fts5 table object */
const char *zCmd, /* Text inserted into table-name column */
sqlite3_value *pVal /* Value inserted into rank column */
){
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
int bError = 0;
@@ -1423,9 +1422,9 @@ static int fts5SpecialInsert(
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
#endif
}else{
- rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
+ rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex);
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError);
+ rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError);
}
if( rc==SQLITE_OK ){
if( bError ){
@@ -1439,7 +1438,7 @@ static int fts5SpecialInsert(
}
static int fts5SpecialDelete(
- Fts5Table *pTab,
+ Fts5FullTable *pTab,
sqlite3_value **apVal
){
int rc = SQLITE_OK;
@@ -1453,7 +1452,7 @@ static int fts5SpecialDelete(
static void fts5StorageInsert(
int *pRc,
- Fts5Table *pTab,
+ Fts5FullTable *pTab,
sqlite3_value **apVal,
i64 *piRowid
){
@@ -1487,8 +1486,8 @@ static int fts5UpdateMethod(
sqlite3_value **apVal, /* Array of arguments */
sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */
){
- Fts5Table *pTab = (Fts5Table*)pVtab;
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
+ Fts5Config *pConfig = pTab->p.pConfig;
int eType0; /* value_type() of apVal[0] */
int rc = SQLITE_OK; /* Return code */
@@ -1497,12 +1496,11 @@ static int fts5UpdateMethod(
assert( pVtab->zErrMsg==0 );
assert( nArg==1 || nArg==(2+pConfig->nCol+2) );
- assert( nArg==1
- || sqlite3_value_type(apVal[1])==SQLITE_INTEGER
- || sqlite3_value_type(apVal[1])==SQLITE_NULL
+ assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER
+ || sqlite3_value_type(apVal[0])==SQLITE_NULL
);
- assert( pTab->pConfig->pzErrmsg==0 );
- pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
+ assert( pTab->p.pConfig->pzErrmsg==0 );
+ pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
/* Put any active cursors into REQUIRE_SEEK state. */
fts5TripCursors(pTab);
@@ -1543,7 +1541,7 @@ static int fts5UpdateMethod(
/* Filter out attempts to run UPDATE or DELETE on contentless tables.
** This is not suported. */
if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){
- pTab->base.zErrMsg = sqlite3_mprintf(
+ pTab->p.base.zErrMsg = sqlite3_mprintf(
"cannot %s contentless fts5 table: %s",
(nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
);
@@ -1556,46 +1554,52 @@ static int fts5UpdateMethod(
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0);
}
- /* INSERT */
- else if( eType0!=SQLITE_INTEGER ){
- /* If this is a REPLACE, first remove the current entry (if any) */
- if( eConflict==SQLITE_REPLACE
- && sqlite3_value_type(apVal[1])==SQLITE_INTEGER
- ){
- i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+ /* INSERT or UPDATE */
+ else{
+ int eType1 = sqlite3_value_numeric_type(apVal[1]);
+
+ if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){
+ rc = SQLITE_MISMATCH;
}
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
- }
- /* UPDATE */
- else{
- i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
- i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
- if( iOld!=iNew ){
- if( eConflict==SQLITE_REPLACE ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
- }
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
- }else{
- rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
- if( rc==SQLITE_OK ){
+ else if( eType0!=SQLITE_INTEGER ){
+ /* If this is a REPLACE, first remove the current entry (if any) */
+ if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){
+ i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+ }
+ fts5StorageInsert(&rc, pTab, apVal, pRowid);
+ }
+
+ /* UPDATE */
+ else{
+ i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */
+ i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */
+ if( eType1==SQLITE_INTEGER && iOld!=iNew ){
+ if( eConflict==SQLITE_REPLACE ){
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0);
+ }
+ fts5StorageInsert(&rc, pTab, apVal, pRowid);
+ }else{
+ rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid);
+ }
}
- if( rc==SQLITE_OK ){
- rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid);
- }
+ }else{
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
+ fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
- }else{
- rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0);
- fts5StorageInsert(&rc, pTab, apVal, pRowid);
}
}
}
- pTab->pConfig->pzErrmsg = 0;
+ pTab->p.pConfig->pzErrmsg = 0;
return rc;
}
@@ -1604,12 +1608,12 @@ static int fts5UpdateMethod(
*/
static int fts5SyncMethod(sqlite3_vtab *pVtab){
int rc;
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
fts5CheckTransactionState(pTab, FTS5_SYNC, 0);
- pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
+ pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
fts5TripCursors(pTab);
rc = sqlite3Fts5StorageSync(pTab->pStorage);
- pTab->pConfig->pzErrmsg = 0;
+ pTab->p.pConfig->pzErrmsg = 0;
return rc;
}
@@ -1617,8 +1621,8 @@ static int fts5SyncMethod(sqlite3_vtab *pVtab){
** Implementation of xBegin() method.
*/
static int fts5BeginMethod(sqlite3_vtab *pVtab){
- fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0);
- fts5NewTransaction((Fts5Table*)pVtab);
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_BEGIN, 0);
+ fts5NewTransaction((Fts5FullTable*)pVtab);
return SQLITE_OK;
}
@@ -1629,7 +1633,7 @@ static int fts5BeginMethod(sqlite3_vtab *pVtab){
*/
static int fts5CommitMethod(sqlite3_vtab *pVtab){
UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0);
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_COMMIT, 0);
return SQLITE_OK;
}
@@ -1639,7 +1643,7 @@ static int fts5CommitMethod(sqlite3_vtab *pVtab){
*/
static int fts5RollbackMethod(sqlite3_vtab *pVtab){
int rc;
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
return rc;
@@ -1663,13 +1667,13 @@ static int fts5ApiColumnTotalSize(
sqlite3_int64 *pnToken
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken);
}
static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow);
}
@@ -1704,7 +1708,9 @@ static int fts5ApiColumnText(
){
int rc = SQLITE_OK;
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
+ if( fts5IsContentless((Fts5FullTable*)(pCsr->base.pVtab))
+ || pCsr->ePlan==FTS5_PLAN_SPECIAL
+ ){
*pz = 0;
*pn = 0;
}else{
@@ -1773,10 +1779,11 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
int rc = SQLITE_OK;
Fts5PoslistReader *aIter; /* One iterator for each phrase */
int nIter; /* Number of iterators/phrases */
+ int nCol = ((Fts5Table*)pCsr->base.pVtab)->pConfig->nCol;
nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
if( pCsr->aInstIter==0 ){
- int nByte = sizeof(Fts5PoslistReader) * nIter;
+ sqlite3_int64 nByte = sizeof(Fts5PoslistReader) * nIter;
pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
}
aIter = pCsr->aInstIter;
@@ -1811,7 +1818,7 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
nInst++;
if( nInst>=pCsr->nInstAlloc ){
pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
- aInst = (int*)sqlite3_realloc(
+ aInst = (int*)sqlite3_realloc64(
pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
);
if( aInst ){
@@ -1826,6 +1833,10 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
aInst[0] = iBest;
aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
+ if( aInst[1]<0 || aInst[1]>=nCol ){
+ rc = FTS5_CORRUPT;
+ break;
+ }
sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
}
}
@@ -1898,8 +1909,8 @@ static int fts5ColumnSizeCb(
static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
+ Fts5Config *pConfig = pTab->p.pConfig;
int rc = SQLITE_OK;
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
@@ -2155,7 +2166,7 @@ static int fts5ApiQueryPhrase(
int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*)
){
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCsr->base.pVtab);
int rc;
Fts5Cursor *pNew = 0;
@@ -2232,25 +2243,19 @@ static void fts5ApiCallback(
/*
-** Given cursor id iId, return a pointer to the corresponding Fts5Index
+** Given cursor id iId, return a pointer to the corresponding Fts5Table
** object. Or NULL If the cursor id does not exist.
-**
-** If successful, set *ppConfig to point to the associated config object
-** before returning.
*/
-Fts5Index *sqlite3Fts5IndexFromCsrid(
+Fts5Table *sqlite3Fts5TableFromCsrid(
Fts5Global *pGlobal, /* FTS5 global context for db handle */
- i64 iCsrId, /* Id of cursor to find */
- Fts5Config **ppConfig /* OUT: Configuration object */
+ i64 iCsrId /* Id of cursor to find */
){
Fts5Cursor *pCsr;
- Fts5Table *pTab;
-
pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
- pTab = (Fts5Table*)pCsr->base.pVtab;
- *ppConfig = pTab->pConfig;
-
- return pTab->pIndex;
+ if( pCsr ){
+ return (Fts5Table*)pCsr->base.pVtab;
+ }
+ return 0;
}
/*
@@ -2330,8 +2335,8 @@ static int fts5ColumnMethod(
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
- Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
- Fts5Config *pConfig = pTab->pConfig;
+ Fts5FullTable *pTab = (Fts5FullTable*)(pCursor->pVtab);
+ Fts5Config *pConfig = pTab->p.pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK;
@@ -2383,7 +2388,7 @@ static int fts5FindFunctionMethod(
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
void **ppArg /* OUT: User data for *pxFunc */
){
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
Fts5Auxiliary *pAux;
UNUSED_PARAM(nUnused);
@@ -2405,21 +2410,24 @@ static int fts5RenameMethod(
sqlite3_vtab *pVtab, /* Virtual table handle */
const char *zName /* New name of table */
){
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
return sqlite3Fts5StorageRename(pTab->pStorage, zName);
}
+int sqlite3Fts5FlushToDisk(Fts5Table *pTab){
+ fts5TripCursors((Fts5FullTable*)pTab);
+ return sqlite3Fts5StorageSync(((Fts5FullTable*)pTab)->pStorage);
+}
+
/*
** The xSavepoint() method.
**
** Flush the contents of the pending-terms table to disk.
*/
static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint);
- fts5TripCursors(pTab);
- return sqlite3Fts5StorageSync(pTab->pStorage);
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_SAVEPOINT, iSavepoint);
+ return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
}
/*
@@ -2428,11 +2436,9 @@ static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
** This is a no-op.
*/
static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
- fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint);
- fts5TripCursors(pTab);
- return sqlite3Fts5StorageSync(pTab->pStorage);
+ fts5CheckTransactionState((Fts5FullTable*)pVtab, FTS5_RELEASE, iSavepoint);
+ return sqlite3Fts5FlushToDisk((Fts5Table*)pVtab);
}
/*
@@ -2441,7 +2447,7 @@ static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
** Discard the contents of the pending terms table.
*/
static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
- Fts5Table *pTab = (Fts5Table*)pVtab;
+ Fts5FullTable *pTab = (Fts5FullTable*)pVtab;
UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */
fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint);
fts5TripCursors(pTab);
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c
index 1f08a9a7a84..633e5a4d96c 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c
@@ -115,7 +115,7 @@ static int fts5StorageGetStmt(
char *zBind;
int i;
- zBind = sqlite3_malloc(1 + nCol*2);
+ zBind = sqlite3_malloc64(1 + nCol*2);
if( zBind ){
for(i=0; i<nCol; i++){
zBind[i*2] = '?';
@@ -282,11 +282,11 @@ int sqlite3Fts5StorageOpen(
){
int rc = SQLITE_OK;
Fts5Storage *p; /* New object */
- int nByte; /* Bytes of space to allocate */
+ sqlite3_int64 nByte; /* Bytes of space to allocate */
nByte = sizeof(Fts5Storage) /* Fts5Storage object */
+ pConfig->nCol * sizeof(i64); /* Fts5Storage.aTotalSize[] */
- *pp = p = (Fts5Storage*)sqlite3_malloc(nByte);
+ *pp = p = (Fts5Storage*)sqlite3_malloc64(nByte);
if( !p ) return SQLITE_NOMEM;
memset(p, 0, nByte);
@@ -297,7 +297,7 @@ int sqlite3Fts5StorageOpen(
if( bCreate ){
if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
int nDefn = 32 + pConfig->nCol*10;
- char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
+ char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 10);
if( zDefn==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -588,7 +588,7 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
Fts5Config *pConfig = p->pConfig;
sqlite3_stmt *pScan = 0;
Fts5InsertCtx ctx;
- int rc;
+ int rc, rc2;
memset(&ctx, 0, sizeof(Fts5InsertCtx));
ctx.pStorage = p;
@@ -627,6 +627,8 @@ int sqlite3Fts5StorageRebuild(Fts5Storage *p){
}
}
sqlite3_free(buf.p);
+ rc2 = sqlite3_reset(pScan);
+ if( rc==SQLITE_OK ) rc = rc2;
/* Write the averages record */
if( rc==SQLITE_OK ){
@@ -876,7 +878,7 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
ctx.pConfig = p->pConfig;
- aTotalSize = (i64*)sqlite3_malloc(pConfig->nCol * (sizeof(int)+sizeof(i64)));
+ aTotalSize = (i64*)sqlite3_malloc64(pConfig->nCol*(sizeof(int)+sizeof(i64)));
if( !aTotalSize ) return SQLITE_NOMEM;
aColSize = (int*)&aTotalSize[pConfig->nCol];
memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
@@ -1076,7 +1078,13 @@ int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){
int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
int rc = fts5StorageLoadTotals(p, 0);
if( rc==SQLITE_OK ){
+ /* nTotalRow being zero does not necessarily indicate a corrupt
+ ** database - it might be that the FTS5 table really does contain zero
+ ** rows. However this function is only called from the xRowCount() API,
+ ** and there is no way for that API to be invoked if the table contains
+ ** no rows. Hence the FTS5_CORRUPT return. */
*pnRow = p->nTotalRow;
+ if( p->nTotalRow<=0 ) rc = FTS5_CORRUPT;
}
return rc;
}
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_test_mi.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_test_mi.c
index d520d0fc17f..a0e8be959cd 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_test_mi.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_test_mi.c
@@ -309,7 +309,7 @@ static Fts5MatchinfoCtx *fts5MatchinfoNew(
int nPhrase;
int i;
int nInt;
- int nByte;
+ sqlite3_int64 nByte;
int rc;
nCol = pApi->xColumnCount(pFts);
@@ -330,7 +330,7 @@ static Fts5MatchinfoCtx *fts5MatchinfoNew(
nByte = sizeof(Fts5MatchinfoCtx) /* The struct itself */
+ sizeof(u32) * nInt /* The p->aRet[] array */
+ (i+1); /* The p->zArg string */
- p = (Fts5MatchinfoCtx*)sqlite3_malloc(nByte);
+ p = (Fts5MatchinfoCtx*)sqlite3_malloc64(nByte);
if( p==0 ){
sqlite3_result_error_nomem(pCtx);
return 0;
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c
index 7453638b317..3d957d4b877 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c
@@ -137,7 +137,7 @@ static int fts5tokDequoteArray(
nByte += (int)(strlen(argv[i]) + 1);
}
- *pazDequote = azDequote = sqlite3_malloc(sizeof(char *)*argc + nByte);
+ *pazDequote = azDequote = sqlite3_malloc64(sizeof(char *)*argc + nByte);
if( azDequote==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -335,7 +335,7 @@ static int fts5tokCb(
if( (pCsr->nRow & (pCsr->nRow-1))==0 ){
int nNew = pCsr->nRow ? pCsr->nRow*2 : 32;
Fts5tokRow *aNew;
- aNew = (Fts5tokRow*)sqlite3_realloc(pCsr->aRow, nNew*sizeof(Fts5tokRow));
+ aNew = (Fts5tokRow*)sqlite3_realloc64(pCsr->aRow, nNew*sizeof(Fts5tokRow));
if( aNew==0 ) return SQLITE_NOMEM;
memset(&aNew[pCsr->nRow], 0, sizeof(Fts5tokRow)*(nNew-pCsr->nRow));
pCsr->aRow = aNew;
@@ -378,7 +378,7 @@ static int fts5tokFilterMethod(
if( pCsr->zInput==0 ){
rc = SQLITE_NOMEM;
}else{
- memcpy(pCsr->zInput, zByte, nByte);
+ if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
pCsr->zInput[nByte] = 0;
rc = pTab->tok.xTokenize(
pTab->pTok, (void*)pCsr, 0, zByte, nByte, fts5tokCb
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c
index b02707d8b6d..b39221bc253 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c
@@ -152,7 +152,7 @@ static int fts5AsciiTokenize(
nByte = ie-is;
if( nByte>nFold ){
if( pFold!=aFold ) sqlite3_free(pFold);
- pFold = sqlite3_malloc(nByte*2);
+ pFold = sqlite3_malloc64((sqlite3_int64)nByte*2);
if( pFold==0 ){
rc = SQLITE_NOMEM;
break;
@@ -234,13 +234,18 @@ struct Unicode61Tokenizer {
unsigned char aTokenChar[128]; /* ASCII range token characters */
char *aFold; /* Buffer to fold text into */
int nFold; /* Size of aFold[] in bytes */
- int bRemoveDiacritic; /* True if remove_diacritics=1 is set */
+ int eRemoveDiacritic; /* True if remove_diacritics=1 is set */
int nException;
int *aiException;
unsigned char aCategory[32]; /* True for token char categories */
};
+/* Values for eRemoveDiacritic (must match internals of fts5_unicode2.c) */
+#define FTS5_REMOVE_DIACRITICS_NONE 0
+#define FTS5_REMOVE_DIACRITICS_SIMPLE 1
+#define FTS5_REMOVE_DIACRITICS_COMPLEX 2
+
static int fts5UnicodeAddExceptions(
Unicode61Tokenizer *p, /* Tokenizer object */
const char *z, /* Characters to treat as exceptions */
@@ -251,13 +256,14 @@ static int fts5UnicodeAddExceptions(
int *aNew;
if( n>0 ){
- aNew = (int*)sqlite3_realloc(p->aiException, (n+p->nException)*sizeof(int));
+ aNew = (int*)sqlite3_realloc64(p->aiException,
+ (n+p->nException)*sizeof(int));
if( aNew ){
int nNew = p->nException;
const unsigned char *zCsr = (const unsigned char*)z;
const unsigned char *zTerm = (const unsigned char*)&z[n];
while( zCsr<zTerm ){
- int iCode;
+ u32 iCode;
int bToken;
READ_UTF8(zCsr, zTerm, iCode);
if( iCode<128 ){
@@ -269,7 +275,7 @@ static int fts5UnicodeAddExceptions(
if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){
int i;
for(i=0; i<nNew; i++){
- if( aNew[i]>iCode ) break;
+ if( (u32)aNew[i]>iCode ) break;
}
memmove(&aNew[i+1], &aNew[i], (nNew-i)*sizeof(int));
aNew[i] = iCode;
@@ -361,7 +367,7 @@ static int fts5UnicodeCreate(
int i;
memset(p, 0, sizeof(Unicode61Tokenizer));
- p->bRemoveDiacritic = 1;
+ p->eRemoveDiacritic = FTS5_REMOVE_DIACRITICS_SIMPLE;
p->nFold = 64;
p->aFold = sqlite3_malloc(p->nFold * sizeof(char));
if( p->aFold==0 ){
@@ -382,10 +388,15 @@ static int fts5UnicodeCreate(
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
const char *zArg = azArg[i+1];
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
- if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
+ if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
rc = SQLITE_ERROR;
+ }else{
+ p->eRemoveDiacritic = (zArg[0] - '0');
+ assert( p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_NONE
+ || p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_SIMPLE
+ || p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_COMPLEX
+ );
}
- p->bRemoveDiacritic = (zArg[0]=='1');
}else
if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
rc = fts5UnicodeAddExceptions(p, zArg, 1);
@@ -419,7 +430,7 @@ static int fts5UnicodeCreate(
*/
static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){
return (
- p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]
+ p->aCategory[sqlite3Fts5UnicodeCategory((u32)iCode)]
^ fts5UnicodeIsException(p, iCode)
);
}
@@ -448,7 +459,7 @@ static int fts5UnicodeTokenize(
/* Each iteration of this loop gobbles up a contiguous run of separators,
** then the next token. */
while( rc==SQLITE_OK ){
- int iCode; /* non-ASCII codepoint read from input */
+ u32 iCode; /* non-ASCII codepoint read from input */
char *zOut = aFold;
int is;
int ie;
@@ -480,7 +491,7 @@ static int fts5UnicodeTokenize(
/* Grow the output buffer so that there is sufficient space to fit the
** largest possible utf-8 character. */
if( zOut>pEnd ){
- aFold = sqlite3_malloc(nFold*2);
+ aFold = sqlite3_malloc64((sqlite3_int64)nFold*2);
if( aFold==0 ){
rc = SQLITE_NOMEM;
goto tokenize_done;
@@ -499,7 +510,7 @@ static int fts5UnicodeTokenize(
READ_UTF8(zCsr, zTerm, iCode);
if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){
non_ascii_tokenchar:
- iCode = sqlite3Fts5UnicodeFold(iCode, p->bRemoveDiacritic);
+ iCode = sqlite3Fts5UnicodeFold(iCode, p->eRemoveDiacritic);
if( iCode ) WRITE_UTF8(zOut, iCode);
}else{
break;
@@ -1274,5 +1285,3 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
return rc;
}
-
-
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c
index 163800537b4..1f3522ff728 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c
@@ -1,5 +1,5 @@
/*
-** 2012 May 25
+** 2012-05-25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -28,32 +28,48 @@
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
-static int fts5_remove_diacritic(int c){
+static int fts5_remove_diacritic(int c, int bComplex){
unsigned short aDia[] = {
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
- 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
- 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
- 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
- 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
- 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
- 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
- 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
- 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
- 62924, 63050, 63082, 63274, 63390,
+ 3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
+ 3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
+ 4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
+ 4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
+ 6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
+ 61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
+ 61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
+ 61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
+ 62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
+ 62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
+ 62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
+ 63182, 63242, 63274, 63310, 63368, 63390,
};
- char aChar[] = {
- '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
- 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
- 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
- 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
- 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
- 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
- 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
- 'e', 'i', 'o', 'u', 'y',
+#define HIBIT ((unsigned char)0x80)
+ unsigned char aChar[] = {
+ '\0', 'a', 'c', 'e', 'i', 'n',
+ 'o', 'u', 'y', 'y', 'a', 'c',
+ 'd', 'e', 'e', 'g', 'h', 'i',
+ 'j', 'k', 'l', 'n', 'o', 'r',
+ 's', 't', 'u', 'u', 'w', 'y',
+ 'z', 'o', 'u', 'a', 'i', 'o',
+ 'u', 'u'|HIBIT, 'a'|HIBIT, 'g', 'k', 'o',
+ 'o'|HIBIT, 'j', 'g', 'n', 'a'|HIBIT, 'a',
+ 'e', 'i', 'o', 'r', 'u', 's',
+ 't', 'h', 'a', 'e', 'o'|HIBIT, 'o',
+ 'o'|HIBIT, 'y', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', 'a', 'b',
+ 'c'|HIBIT, 'd', 'd', 'e'|HIBIT, 'e', 'e'|HIBIT,
+ 'f', 'g', 'h', 'h', 'i', 'i'|HIBIT,
+ 'k', 'l', 'l'|HIBIT, 'l', 'm', 'n',
+ 'o'|HIBIT, 'p', 'r', 'r'|HIBIT, 'r', 's',
+ 's'|HIBIT, 't', 'u', 'u'|HIBIT, 'v', 'w',
+ 'w', 'x', 'y', 'z', 'h', 't',
+ 'w', 'y', 'a', 'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
+ 'e', 'e'|HIBIT, 'e'|HIBIT, 'i', 'o', 'o'|HIBIT,
+ 'o'|HIBIT, 'o'|HIBIT, 'u', 'u'|HIBIT, 'u'|HIBIT, 'y',
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
@@ -70,7 +86,8 @@ static int fts5_remove_diacritic(int c){
}
}
assert( key>=aDia[iRes] );
- return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
+ if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
+ return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
}
@@ -83,8 +100,8 @@ int sqlite3Fts5UnicodeIsdiacritic(int c){
unsigned int mask1 = 0x000361F8;
if( c<768 || c>817 ) return 0;
return (c < 768+32) ?
- (mask0 & (1 << (c-768))) :
- (mask1 & (1 << (c-768-32)));
+ (mask0 & ((unsigned int)1 << (c-768))) :
+ (mask1 & ((unsigned int)1 << (c-768-32)));
}
@@ -97,7 +114,7 @@ int sqlite3Fts5UnicodeIsdiacritic(int c){
** The results are undefined if the value passed to this function
** is less than zero.
*/
-int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
+int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){
/* Each entry in the following array defines a rule for folding a range
** of codepoints to lower case. The rule applies to a range of nRange
** codepoints starting at codepoint iCode.
@@ -220,7 +237,9 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
assert( ret>0 );
}
- if( bRemoveDiacritic ) ret = fts5_remove_diacritic(ret);
+ if( eRemoveDiacritic ){
+ ret = fts5_remove_diacritic(ret, eRemoveDiacritic==2);
+ }
}
else if( c>=66560 && c<66600 ){
@@ -231,12 +250,6 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
}
-#if 0
-int sqlite3Fts5UnicodeNCat(void) {
- return 32;
-}
-#endif
-
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
aArray[0] = 1;
switch( zCat[0] ){
@@ -718,7 +731,7 @@ static u16 aFts5UnicodeData[] = {
34, 3074, 7692, 63, 63,
};
-int sqlite3Fts5UnicodeCategory(int iCode) {
+int sqlite3Fts5UnicodeCategory(u32 iCode) {
int iRes = -1;
int iHi;
int iLo;
@@ -756,9 +769,8 @@ void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
int n = (aFts5UnicodeData[iTbl] >> 5) + i;
for(; i<128 && i<n; i++){
- aAscii[i] = (u8)bToken;
+ aAscii[i] = bToken;
}
iTbl++;
}
}
-
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_varint.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_varint.c
index 91c5333933a..a982d46c522 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_varint.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_varint.c
@@ -76,7 +76,7 @@ int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v){
u8 n;
p -= 2;
n = sqlite3Fts5GetVarint(p, &v64);
- *v = (u32)v64;
+ *v = ((u32)v64) & 0x7FFFFFFF;
assert( n>3 && n<=9 );
return n;
}
@@ -342,4 +342,3 @@ int sqlite3Fts5GetVarintLen(u32 iVal){
if( iVal<(1 << 28) ) return 4;
return 5;
}
-
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c
index 6820706fd8f..fcc9e55497a 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c
@@ -55,7 +55,7 @@ struct Fts5VocabTable {
struct Fts5VocabCursor {
sqlite3_vtab_cursor base;
sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */
- Fts5Index *pIndex; /* Associated FTS5 index */
+ Fts5Table *pFts5; /* Associated FTS5 table */
int bEof; /* True if this cursor is at EOF */
Fts5IndexIter *pIter; /* Term/rowid iterator object */
@@ -64,7 +64,6 @@ struct Fts5VocabCursor {
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
/* These are used by 'col' tables only */
- Fts5Config *pConfig; /* Fts5 table configuration */
int iCol;
i64 *aCnt;
i64 *aDoc;
@@ -327,8 +326,7 @@ static int fts5VocabOpenMethod(
sqlite3_vtab_cursor **ppCsr
){
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
- Fts5Index *pIndex = 0;
- Fts5Config *pConfig = 0;
+ Fts5Table *pFts5 = 0;
Fts5VocabCursor *pCsr = 0;
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
@@ -347,31 +345,34 @@ static int fts5VocabOpenMethod(
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
i64 iId = sqlite3_column_int64(pStmt, 0);
- pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
+ pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId);
}
- if( rc==SQLITE_OK && pIndex==0 ){
- rc = sqlite3_finalize(pStmt);
- pStmt = 0;
- if( rc==SQLITE_OK ){
- pVTab->zErrMsg = sqlite3_mprintf(
- "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
- );
- rc = SQLITE_ERROR;
+ if( rc==SQLITE_OK ){
+ if( pFts5==0 ){
+ rc = sqlite3_finalize(pStmt);
+ pStmt = 0;
+ if( rc==SQLITE_OK ){
+ pVTab->zErrMsg = sqlite3_mprintf(
+ "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
+ );
+ rc = SQLITE_ERROR;
+ }
+ }else{
+ rc = sqlite3Fts5FlushToDisk(pFts5);
}
}
if( rc==SQLITE_OK ){
- int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
+ int nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
}
if( pCsr ){
- pCsr->pIndex = pIndex;
+ pCsr->pFts5 = pFts5;
pCsr->pStmt = pStmt;
- pCsr->pConfig = pConfig;
pCsr->aCnt = (i64*)&pCsr[1];
- pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
+ pCsr->aDoc = &pCsr->aCnt[pFts5->pConfig->nCol];
}else{
sqlite3_finalize(pStmt);
}
@@ -387,6 +388,7 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
sqlite3_free(pCsr->zLeTerm);
pCsr->nLeTerm = -1;
pCsr->zLeTerm = 0;
+ pCsr->bEof = 0;
}
/*
@@ -425,7 +427,7 @@ static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
}
static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
- int eDetail = pCsr->pConfig->eDetail;
+ int eDetail = pCsr->pFts5->pConfig->eDetail;
int rc = SQLITE_OK;
Fts5IndexIter *pIter = pCsr->pIter;
i64 *pp = &pCsr->iInstPos;
@@ -460,7 +462,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
int rc = SQLITE_OK;
- int nCol = pCsr->pConfig->nCol;
+ int nCol = pCsr->pFts5->pConfig->nCol;
pCsr->rowid++;
@@ -482,6 +484,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
int nTerm;
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
+ assert( nTerm>=0 );
if( pCsr->nLeTerm>=0 ){
int nCmp = MIN(nTerm, pCsr->nLeTerm);
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
@@ -498,7 +501,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
while( rc==SQLITE_OK ){
- int eDetail = pCsr->pConfig->eDetail;
+ int eDetail = pCsr->pFts5->pConfig->eDetail;
const u8 *pPos; int nPos; /* Position list */
i64 iPos = 0; /* 64-bit position read from poslist */
int iOff = 0; /* Current offset within position list */
@@ -521,7 +524,6 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
int iCol = -1;
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
int ii = FTS5_POS2COLUMN(iPos);
- pCsr->aCnt[ii]++;
if( iCol!=ii ){
if( ii>=nCol ){
rc = FTS5_CORRUPT;
@@ -530,6 +532,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->aDoc[ii]++;
iCol = ii;
}
+ pCsr->aCnt[ii]++;
}
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
@@ -558,7 +561,9 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( rc==SQLITE_OK ){
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
- if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
+ if( nTerm!=pCsr->term.n
+ || (nTerm>0 && memcmp(zTerm, pCsr->term.p, nTerm))
+ ){
break;
}
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
@@ -569,7 +574,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++;
- assert( pCsr->iCol<pCsr->pConfig->nCol );
+ assert( pCsr->iCol<pCsr->pFts5->pConfig->nCol );
}
return rc;
}
@@ -616,6 +621,7 @@ static int fts5VocabFilterMethod(
}
if( pLe ){
const char *zCopy = (const char *)sqlite3_value_text(pLe);
+ if( zCopy==0 ) zCopy = "";
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
if( pCsr->zLeTerm==0 ){
@@ -627,14 +633,15 @@ static int fts5VocabFilterMethod(
}
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
+ Fts5Index *pIndex = pCsr->pFts5->pIndex;
+ rc = sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
}
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
rc = fts5VocabInstanceNewTerm(pCsr);
}
- if( rc==SQLITE_OK
- && !pCsr->bEof
- && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
+ if( rc==SQLITE_OK && !pCsr->bEof
+ && (eType!=FTS5_VOCAB_INSTANCE
+ || pCsr->pFts5->pConfig->eDetail!=FTS5_DETAIL_NONE)
){
rc = fts5VocabNextMethod(pCursor);
}
@@ -657,7 +664,7 @@ static int fts5VocabColumnMethod(
int iCol /* Index of column to read value from */
){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
- int eDetail = pCsr->pConfig->eDetail;
+ int eDetail = pCsr->pFts5->pConfig->eDetail;
int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
i64 iVal = 0;
@@ -669,7 +676,7 @@ static int fts5VocabColumnMethod(
assert( iCol==1 || iCol==2 || iCol==3 );
if( iCol==1 ){
if( eDetail!=FTS5_DETAIL_NONE ){
- const char *z = pCsr->pConfig->azCol[pCsr->iCol];
+ const char *z = pCsr->pFts5->pConfig->azCol[pCsr->iCol];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
}else if( iCol==2 ){
@@ -697,8 +704,8 @@ static int fts5VocabColumnMethod(
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
ii = (int)pCsr->iInstPos;
}
- if( ii>=0 && ii<pCsr->pConfig->nCol ){
- const char *z = pCsr->pConfig->azCol[ii];
+ if( ii>=0 && ii<pCsr->pFts5->pConfig->nCol ){
+ const char *z = pCsr->pFts5->pConfig->azCol[ii];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
break;
diff --git a/chromium/third_party/sqlite/src/ext/misc/amatch.c b/chromium/third_party/sqlite/src/ext/misc/amatch.c
index 519a5a0bf62..7bc09be38f1 100644
--- a/chromium/third_party/sqlite/src/ext/misc/amatch.c
+++ b/chromium/third_party/sqlite/src/ext/misc/amatch.c
@@ -619,7 +619,7 @@ static int amatchLoadOneRule(
if( p->rDel==0 || p->rDel>rCost ) p->rDel = rCost;
}else
{
- pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
+ pRule = sqlite3_malloc64( sizeof(*pRule) + nFrom + nTo );
if( pRule==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -738,11 +738,11 @@ static int amatchLoadRules(
** `mno` becomes mno
*/
static char *amatchDequote(const char *zIn){
- int nIn; /* Size of input string, in bytes */
+ sqlite3_int64 nIn; /* Size of input string, in bytes */
char *zOut; /* Output (dequoted) string */
- nIn = (int)strlen(zIn);
- zOut = sqlite3_malloc(nIn+1);
+ nIn = strlen(zIn);
+ zOut = sqlite3_malloc64(nIn+1);
if( zOut ){
char q = zIn[0]; /* Quote character (if any ) */
@@ -1069,7 +1069,7 @@ static void amatchAddWord(
}
return;
}
- pWord = sqlite3_malloc( sizeof(*pWord) + nBase + nTail - 1 );
+ pWord = sqlite3_malloc64( sizeof(*pWord) + nBase + nTail - 1 );
if( pWord==0 ) return;
memset(pWord, 0, sizeof(*pWord));
pWord->rCost = rCost;
diff --git a/chromium/third_party/sqlite/src/ext/misc/closure.c b/chromium/third_party/sqlite/src/ext/misc/closure.c
index bf1a8696fcb..6aa2b1ef919 100644
--- a/chromium/third_party/sqlite/src/ext/misc/closure.c
+++ b/chromium/third_party/sqlite/src/ext/misc/closure.c
@@ -422,11 +422,11 @@ static closure_avl *queuePull(closure_queue *pQueue){
** `mno` becomes mno
*/
static char *closureDequote(const char *zIn){
- int nIn; /* Size of input string, in bytes */
+ sqlite3_int64 nIn; /* Size of input string, in bytes */
char *zOut; /* Output (dequoted) string */
- nIn = (int)strlen(zIn);
- zOut = sqlite3_malloc(nIn+1);
+ nIn = strlen(zIn);
+ zOut = sqlite3_malloc64(nIn+1);
if( zOut ){
char q = zIn[0]; /* Quote character (if any ) */
diff --git a/chromium/third_party/sqlite/src/ext/misc/csv.c b/chromium/third_party/sqlite/src/ext/misc/csv.c
index be58a3a9f8b..f0b7ba7b75d 100644
--- a/chromium/third_party/sqlite/src/ext/misc/csv.c
+++ b/chromium/third_party/sqlite/src/ext/misc/csv.c
@@ -621,7 +621,7 @@ static int csvtabConnect(
}else if( pNew->zData ){
pNew->iStart = (int)sRdr.iIn;
}else{
- pNew->iStart = ftell(sRdr.in);
+ pNew->iStart = (int)(ftell(sRdr.in) - sRdr.nIn + sRdr.iIn);
}
csv_reader_reset(&sRdr);
rc = sqlite3_declare_vtab(db, CSV_SCHEMA);
diff --git a/chromium/third_party/sqlite/src/ext/misc/dbdump.c b/chromium/third_party/sqlite/src/ext/misc/dbdump.c
index 60ade041ef1..014e7e312af 100644
--- a/chromium/third_party/sqlite/src/ext/misc/dbdump.c
+++ b/chromium/third_party/sqlite/src/ext/misc/dbdump.c
@@ -195,7 +195,7 @@ static char **tableColumnList(DState *p, const char *zTab){
if( nCol>=nAlloc-2 ){
char **azNew;
nAlloc = nAlloc*2 + nCol + 10;
- azNew = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
+ azNew = sqlite3_realloc64(azCol, nAlloc*sizeof(azCol[0]));
if( azNew==0 ) goto col_oom;
azCol = azNew;
azCol[0] = 0;
diff --git a/chromium/third_party/sqlite/src/ext/misc/eval.c b/chromium/third_party/sqlite/src/ext/misc/eval.c
index 9094e8f43ae..4990bc0d8da 100644
--- a/chromium/third_party/sqlite/src/ext/misc/eval.c
+++ b/chromium/third_party/sqlite/src/ext/misc/eval.c
@@ -44,7 +44,7 @@ static int callback(void *pCtx, int argc, char **argv, char **colnames){
/* Using sqlite3_realloc64() would be better, but it is a recent
** addition and will cause a segfault if loaded by an older version
** of SQLite. */
- zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
+ zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc64(p->z, p->nAlloc) : 0;
if( zNew==0 ){
sqlite3_free(p->z);
memset(p, 0, sizeof(*p));
diff --git a/chromium/third_party/sqlite/src/ext/misc/fileio.c b/chromium/third_party/sqlite/src/ext/misc/fileio.c
index 49f6f8aeb43..2383cd9446c 100644
--- a/chromium/third_party/sqlite/src/ext/misc/fileio.c
+++ b/chromium/third_party/sqlite/src/ext/misc/fileio.c
@@ -121,22 +121,47 @@ SQLITE_EXTENSION_INIT1
/*
** Set the result stored by context ctx to a blob containing the
-** contents of file zName.
+** contents of file zName. Or, leave the result unchanged (NULL)
+** if the file does not exist or is unreadable.
+**
+** If the file exceeds the SQLite blob size limit, through an
+** SQLITE_TOOBIG error.
+**
+** Throw an SQLITE_IOERR if there are difficulties pulling the file
+** off of disk.
*/
static void readFileContents(sqlite3_context *ctx, const char *zName){
FILE *in;
- long nIn;
+ sqlite3_int64 nIn;
void *pBuf;
+ sqlite3 *db;
+ int mxBlob;
in = fopen(zName, "rb");
- if( in==0 ) return;
+ if( in==0 ){
+ /* File does not exist or is unreadable. Leave the result set to NULL. */
+ return;
+ }
fseek(in, 0, SEEK_END);
nIn = ftell(in);
rewind(in);
- pBuf = sqlite3_malloc( nIn );
- if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
- sqlite3_result_blob(ctx, pBuf, nIn, sqlite3_free);
+ db = sqlite3_context_db_handle(ctx);
+ mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
+ if( nIn>mxBlob ){
+ sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
+ fclose(in);
+ return;
+ }
+ pBuf = sqlite3_malloc64( nIn );
+ if( pBuf==0 ){
+ sqlite3_result_error_nomem(ctx);
+ fclose(in);
+ return;
+ }
+ if( 1==fread(pBuf, nIn, 1, in) ){
+ sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
}else{
+ sqlite3_result_error_code(ctx, SQLITE_IOERR);
sqlite3_free(pBuf);
}
fclose(in);
@@ -646,8 +671,8 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){
FsdirLevel *pLvl;
if( iNew>=pCur->nLvl ){
int nNew = iNew+1;
- int nByte = nNew*sizeof(FsdirLevel);
- FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc(pCur->aLvl, nByte);
+ sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
+ FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
if( aNew==0 ) return SQLITE_NOMEM;
memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
pCur->aLvl = aNew;
@@ -727,7 +752,7 @@ static int fsdirColumn(
}else if( S_ISLNK(m) ){
char aStatic[64];
char *aBuf = aStatic;
- int nBuf = 64;
+ sqlite3_int64 nBuf = 64;
int n;
while( 1 ){
@@ -735,7 +760,7 @@ static int fsdirColumn(
if( n<nBuf ) break;
if( aBuf!=aStatic ) sqlite3_free(aBuf);
nBuf = nBuf*2;
- aBuf = sqlite3_malloc(nBuf);
+ aBuf = sqlite3_malloc64(nBuf);
if( aBuf==0 ){
sqlite3_result_error_nomem(ctx);
return SQLITE_NOMEM;
diff --git a/chromium/third_party/sqlite/src/ext/misc/fuzzer.c b/chromium/third_party/sqlite/src/ext/misc/fuzzer.c
index 8756b6313ac..94bf74dae93 100644
--- a/chromium/third_party/sqlite/src/ext/misc/fuzzer.c
+++ b/chromium/third_party/sqlite/src/ext/misc/fuzzer.c
@@ -337,7 +337,7 @@ static int fuzzerLoadOneRule(
rc = SQLITE_ERROR;
}else{
- pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
+ pRule = sqlite3_malloc64( sizeof(*pRule) + nFrom + nTo );
if( pRule==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -447,11 +447,11 @@ static int fuzzerLoadRules(
** `mno` becomes mno
*/
static char *fuzzerDequote(const char *zIn){
- int nIn; /* Size of input string, in bytes */
+ sqlite3_int64 nIn; /* Size of input string, in bytes */
char *zOut; /* Output (dequoted) string */
- nIn = (int)strlen(zIn);
- zOut = sqlite3_malloc(nIn+1);
+ nIn = strlen(zIn);
+ zOut = sqlite3_malloc64(nIn+1);
if( zOut ){
char q = zIn[0]; /* Quote character (if any ) */
@@ -513,10 +513,10 @@ static int fuzzerConnect(
);
rc = SQLITE_ERROR;
}else{
- int nModule; /* Length of zModule, in bytes */
+ sqlite3_int64 nModule; /* Length of zModule, in bytes */
- nModule = (int)strlen(zModule);
- pNew = sqlite3_malloc( sizeof(*pNew) + nModule + 1);
+ nModule = strlen(zModule);
+ pNew = sqlite3_malloc64( sizeof(*pNew) + nModule + 1);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -872,7 +872,7 @@ static fuzzer_stem *fuzzerNewStem(
fuzzer_rule *pRule;
unsigned int h;
- pNew = sqlite3_malloc( sizeof(*pNew) + (int)strlen(zWord) + 1 );
+ pNew = sqlite3_malloc64( sizeof(*pNew) + strlen(zWord) + 1 );
if( pNew==0 ) return 0;
memset(pNew, 0, sizeof(*pNew));
pNew->zBasis = (char*)&pNew[1];
diff --git a/chromium/third_party/sqlite/src/ext/misc/json1.c b/chromium/third_party/sqlite/src/ext/misc/json1.c
index 2a99e3b73b7..8a64103043f 100644
--- a/chromium/third_party/sqlite/src/ext/misc/json1.c
+++ b/chromium/third_party/sqlite/src/ext/misc/json1.c
@@ -691,7 +691,7 @@ static JSON_NOINLINE int jsonParseAddNodeExpand(
assert( pParse->nNode>=pParse->nAlloc );
if( pParse->oom ) return -1;
nNew = pParse->nAlloc*2 + 10;
- pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
+ pNew = sqlite3_realloc64(pParse->aNode, sizeof(JsonNode)*nNew);
if( pNew==0 ){
pParse->oom = 1;
return -1;
@@ -965,7 +965,7 @@ static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
static int jsonParseFindParents(JsonParse *pParse){
u32 *aUp;
assert( pParse->aUp==0 );
- aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode );
+ aUp = pParse->aUp = sqlite3_malloc64( sizeof(u32)*pParse->nNode );
if( aUp==0 ){
pParse->oom = 1;
return SQLITE_NOMEM;
@@ -1027,7 +1027,7 @@ static JsonParse *jsonParseCached(
pMatch->iHold = iMaxHold+1;
return pMatch;
}
- p = sqlite3_malloc( sizeof(*p) + nJson + 1 );
+ p = sqlite3_malloc64( sizeof(*p) + nJson + 1 );
if( p==0 ){
sqlite3_result_error_nomem(pCtx);
return 0;
diff --git a/chromium/third_party/sqlite/src/ext/misc/memstat.c b/chromium/third_party/sqlite/src/ext/misc/memstat.c
index f072398d2f6..2c7c69eff10 100644
--- a/chromium/third_party/sqlite/src/ext/misc/memstat.c
+++ b/chromium/third_party/sqlite/src/ext/misc/memstat.c
@@ -143,7 +143,7 @@ static int memstatFindSchemas(memstat_cursor *pCur){
}
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char **az, *z;
- az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
+ az = sqlite3_realloc64(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
if( az==0 ){
memstatClearSchema(pCur);
return SQLITE_NOMEM;
diff --git a/chromium/third_party/sqlite/src/ext/misc/memtrace.c b/chromium/third_party/sqlite/src/ext/misc/memtrace.c
new file mode 100644
index 00000000000..8a33caeb823
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/misc/memtrace.c
@@ -0,0 +1,108 @@
+/*
+** 2019-01-21
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
+** mechanism to add a tracing layer on top of SQLite. If this extension
+** is registered prior to sqlite3_initialize(), it will cause all memory
+** allocation activities to be logged on standard output, or to some other
+** FILE specified by the initializer.
+**
+** This file needs to be compiled into the application that uses it.
+**
+** This extension is used to implement the --memtrace option of the
+** command-line shell.
+*/
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+/* The original memory allocation routines */
+static sqlite3_mem_methods memtraceBase;
+static FILE *memtraceOut;
+
+/* Methods that trace memory allocations */
+static void *memtraceMalloc(int n){
+ if( memtraceOut ){
+ fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
+ memtraceBase.xRoundup(n));
+ }
+ return memtraceBase.xMalloc(n);
+}
+static void memtraceFree(void *p){
+ if( p==0 ) return;
+ if( memtraceOut ){
+ fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
+ }
+ memtraceBase.xFree(p);
+}
+static void *memtraceRealloc(void *p, int n){
+ if( p==0 ) return memtraceMalloc(n);
+ if( n==0 ){
+ memtraceFree(p);
+ return 0;
+ }
+ if( memtraceOut ){
+ fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
+ memtraceBase.xSize(p), memtraceBase.xRoundup(n));
+ }
+ return memtraceBase.xRealloc(p, n);
+}
+static int memtraceSize(void *p){
+ return memtraceBase.xSize(p);
+}
+static int memtraceRoundup(int n){
+ return memtraceBase.xRoundup(n);
+}
+static int memtraceInit(void *p){
+ return memtraceBase.xInit(p);
+}
+static void memtraceShutdown(void *p){
+ memtraceBase.xShutdown(p);
+}
+
+/* The substitute memory allocator */
+static sqlite3_mem_methods ersaztMethods = {
+ memtraceMalloc,
+ memtraceFree,
+ memtraceRealloc,
+ memtraceSize,
+ memtraceRoundup,
+ memtraceInit,
+ memtraceShutdown,
+ 0
+};
+
+/* Begin tracing memory allocations to out. */
+int sqlite3MemTraceActivate(FILE *out){
+ int rc = SQLITE_OK;
+ if( memtraceBase.xMalloc==0 ){
+ rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
+ }
+ }
+ memtraceOut = out;
+ return rc;
+}
+
+/* Deactivate memory tracing */
+int sqlite3MemTraceDeactivate(void){
+ int rc = SQLITE_OK;
+ if( memtraceBase.xMalloc!=0 ){
+ rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
+ if( rc==SQLITE_OK ){
+ memset(&memtraceBase, 0, sizeof(memtraceBase));
+ }
+ }
+ memtraceOut = 0;
+ return rc;
+}
diff --git a/chromium/third_party/sqlite/src/ext/misc/mmapwarm.c b/chromium/third_party/sqlite/src/ext/misc/mmapwarm.c
index f4d1a01b54e..3e6a91d7393 100644
--- a/chromium/third_party/sqlite/src/ext/misc/mmapwarm.c
+++ b/chromium/third_party/sqlite/src/ext/misc/mmapwarm.c
@@ -105,4 +105,3 @@ int sqlite3_mmap_warm(sqlite3 *db, const char *zDb){
return rc;
}
-
diff --git a/chromium/third_party/sqlite/src/ext/misc/nextchar.c b/chromium/third_party/sqlite/src/ext/misc/nextchar.c
index 3a6e23de897..a0f77b04640 100644
--- a/chromium/third_party/sqlite/src/ext/misc/nextchar.c
+++ b/chromium/third_party/sqlite/src/ext/misc/nextchar.c
@@ -85,7 +85,7 @@ static void nextCharAppend(nextCharContext *p, unsigned c){
if( p->nUsed+1 > p->nAlloc ){
unsigned int *aNew;
int n = p->nAlloc*2 + 30;
- aNew = sqlite3_realloc(p->aResult, n*sizeof(unsigned int));
+ aNew = sqlite3_realloc64(p->aResult, n*sizeof(unsigned int));
if( aNew==0 ){
p->mallocFailed = 1;
return;
@@ -269,7 +269,7 @@ static void nextCharFunc(
sqlite3_result_error_nomem(context);
}else{
unsigned char *pRes;
- pRes = sqlite3_malloc( c.nUsed*4 + 1 );
+ pRes = sqlite3_malloc64( c.nUsed*4 + 1 );
if( pRes==0 ){
sqlite3_result_error_nomem(context);
}else{
diff --git a/chromium/third_party/sqlite/src/ext/misc/percentile.c b/chromium/third_party/sqlite/src/ext/misc/percentile.c
index 5b76777505c..dba66ca4766 100644
--- a/chromium/third_party/sqlite/src/ext/misc/percentile.c
+++ b/chromium/third_party/sqlite/src/ext/misc/percentile.c
@@ -151,7 +151,7 @@ static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
/* Allocate and store the Y */
if( p->nUsed>=p->nAlloc ){
unsigned n = p->nAlloc*2 + 250;
- double *a = sqlite3_realloc(p->a, sizeof(double)*n);
+ double *a = sqlite3_realloc64(p->a, sizeof(double)*n);
if( a==0 ){
sqlite3_free(p->a);
memset(p, 0, sizeof(*p));
diff --git a/chromium/third_party/sqlite/src/ext/misc/prefixes.c b/chromium/third_party/sqlite/src/ext/misc/prefixes.c
new file mode 100644
index 00000000000..40fecd5e1df
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/misc/prefixes.c
@@ -0,0 +1,319 @@
+/*
+** 2018-04-19
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements a table-valued function:
+**
+** prefixes('abcdefg')
+**
+** The function has a single (non-HIDDEN) column named prefix that takes
+** on all prefixes of the string in its argument, including an empty string
+** and the input string itself. The order of prefixes is from longest
+** to shortest.
+*/
+#if !defined(SQLITE_CORE) || !defined(SQLITE_OMIT_VIRTUALTABLE)
+#if !defined(SQLITEINT_H)
+#include "sqlite3ext.h"
+#endif
+SQLITE_EXTENSION_INIT1
+#include <string.h>
+#include <assert.h>
+
+/* prefixes_vtab is a subclass of sqlite3_vtab which is
+** underlying representation of the virtual table
+*/
+typedef struct prefixes_vtab prefixes_vtab;
+struct prefixes_vtab {
+ sqlite3_vtab base; /* Base class - must be first */
+ /* No additional fields are necessary */
+};
+
+/* prefixes_cursor is a subclass of sqlite3_vtab_cursor which will
+** serve as the underlying representation of a cursor that scans
+** over rows of the result
+*/
+typedef struct prefixes_cursor prefixes_cursor;
+struct prefixes_cursor {
+ sqlite3_vtab_cursor base; /* Base class - must be first */
+ sqlite3_int64 iRowid; /* The rowid */
+ char *zStr; /* Original string to be prefixed */
+ int nStr; /* Length of the string in bytes */
+};
+
+/*
+** The prefixesConnect() method is invoked to create a new
+** template virtual table.
+**
+** Think of this routine as the constructor for prefixes_vtab objects.
+**
+** All this routine needs to do is:
+**
+** (1) Allocate the prefixes_vtab object and initialize all fields.
+**
+** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
+** result set of queries against the virtual table will look like.
+*/
+static int prefixesConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ prefixes_vtab *pNew;
+ int rc;
+
+ rc = sqlite3_declare_vtab(db,
+ "CREATE TABLE prefixes(prefix TEXT, original_string TEXT HIDDEN)"
+ );
+ if( rc==SQLITE_OK ){
+ pNew = sqlite3_malloc( sizeof(*pNew) );
+ *ppVtab = (sqlite3_vtab*)pNew;
+ if( pNew==0 ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(*pNew));
+ }
+ return rc;
+}
+
+/*
+** This method is the destructor for prefixes_vtab objects.
+*/
+static int prefixesDisconnect(sqlite3_vtab *pVtab){
+ prefixes_vtab *p = (prefixes_vtab*)pVtab;
+ sqlite3_free(p);
+ return SQLITE_OK;
+}
+
+/*
+** Constructor for a new prefixes_cursor object.
+*/
+static int prefixesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+ prefixes_cursor *pCur;
+ pCur = sqlite3_malloc( sizeof(*pCur) );
+ if( pCur==0 ) return SQLITE_NOMEM;
+ memset(pCur, 0, sizeof(*pCur));
+ *ppCursor = &pCur->base;
+ return SQLITE_OK;
+}
+
+/*
+** Destructor for a prefixes_cursor.
+*/
+static int prefixesClose(sqlite3_vtab_cursor *cur){
+ prefixes_cursor *pCur = (prefixes_cursor*)cur;
+ sqlite3_free(pCur->zStr);
+ sqlite3_free(pCur);
+ return SQLITE_OK;
+}
+
+
+/*
+** Advance a prefixes_cursor to its next row of output.
+*/
+static int prefixesNext(sqlite3_vtab_cursor *cur){
+ prefixes_cursor *pCur = (prefixes_cursor*)cur;
+ pCur->iRowid++;
+ return SQLITE_OK;
+}
+
+/*
+** Return values of columns for the row at which the prefixes_cursor
+** is currently pointing.
+*/
+static int prefixesColumn(
+ sqlite3_vtab_cursor *cur, /* The cursor */
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
+ int i /* Which column to return */
+){
+ prefixes_cursor *pCur = (prefixes_cursor*)cur;
+ switch( i ){
+ case 0:
+ sqlite3_result_text(ctx, pCur->zStr, pCur->nStr - (int)pCur->iRowid,
+ 0);
+ break;
+ default:
+ sqlite3_result_text(ctx, pCur->zStr, pCur->nStr, 0);
+ break;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row. In this implementation, the
+** rowid is the same as the output value.
+*/
+static int prefixesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ prefixes_cursor *pCur = (prefixes_cursor*)cur;
+ *pRowid = pCur->iRowid;
+ return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int prefixesEof(sqlite3_vtab_cursor *cur){
+ prefixes_cursor *pCur = (prefixes_cursor*)cur;
+ return pCur->iRowid>pCur->nStr;
+}
+
+/*
+** This method is called to "rewind" the prefixes_cursor object back
+** to the first row of output. This method is always called at least
+** once prior to any call to prefixesColumn() or prefixesRowid() or
+** prefixesEof().
+*/
+static int prefixesFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ prefixes_cursor *pCur = (prefixes_cursor *)pVtabCursor;
+ sqlite3_free(pCur->zStr);
+ if( argc>0 ){
+ pCur->zStr = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
+ pCur->nStr = pCur->zStr ? (int)strlen(pCur->zStr) : 0;
+ }else{
+ pCur->zStr = 0;
+ pCur->nStr = 0;
+ }
+ pCur->iRowid = 0;
+ return SQLITE_OK;
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the virtual table. This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+*/
+static int prefixesBestIndex(
+ sqlite3_vtab *tab,
+ sqlite3_index_info *pIdxInfo
+){
+ /* Search for a usable equality constraint against column 1
+ ** (original_string) and use it if at all possible */
+ int i;
+ const struct sqlite3_index_constraint *p;
+
+ for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
+ if( p->iColumn!=1 ) continue;
+ if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
+ if( !p->usable ) continue;
+ pIdxInfo->aConstraintUsage[i].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[i].omit = 1;
+ pIdxInfo->estimatedCost = (double)10;
+ pIdxInfo->estimatedRows = 10;
+ return SQLITE_OK;
+ }
+ pIdxInfo->estimatedCost = (double)1000000000;
+ pIdxInfo->estimatedRows = 1000000000;
+ return SQLITE_OK;
+}
+
+/*
+** This following structure defines all the methods for the
+** virtual table.
+*/
+static sqlite3_module prefixesModule = {
+ /* iVersion */ 0,
+ /* xCreate */ 0,
+ /* xConnect */ prefixesConnect,
+ /* xBestIndex */ prefixesBestIndex,
+ /* xDisconnect */ prefixesDisconnect,
+ /* xDestroy */ 0,
+ /* xOpen */ prefixesOpen,
+ /* xClose */ prefixesClose,
+ /* xFilter */ prefixesFilter,
+ /* xNext */ prefixesNext,
+ /* xEof */ prefixesEof,
+ /* xColumn */ prefixesColumn,
+ /* xRowid */ prefixesRowid,
+ /* xUpdate */ 0,
+ /* xBegin */ 0,
+ /* xSync */ 0,
+ /* xCommit */ 0,
+ /* xRollback */ 0,
+ /* xFindMethod */ 0,
+ /* xRename */ 0,
+ /* xSavepoint */ 0,
+ /* xRelease */ 0,
+ /* xRollbackTo */ 0,
+ /* xShadowName */ 0
+};
+
+/*
+** This is a copy of the SQLITE_SKIP_UTF8(zIn) macro in sqliteInt.h.
+**
+** Assuming zIn points to the first byte of a UTF-8 character,
+** advance zIn to point to the first byte of the next UTF-8 character.
+*/
+#define PREFIX_SKIP_UTF8(zIn) { \
+ if( (*(zIn++))>=0xc0 ){ \
+ while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
+ } \
+}
+
+/*
+** Implementation of function prefix_length(). This function accepts two
+** strings as arguments and returns the length in characters (not bytes),
+** of the longest prefix shared by the two strings. For example:
+**
+** prefix_length('abcdxxx', 'abcyy') == 3
+** prefix_length('abcdxxx', 'bcyyy') == 0
+** prefix_length('abcdxxx', 'ab') == 2
+** prefix_length('ab', 'abcd') == 2
+**
+** This function assumes the input is well-formed utf-8. If it is not,
+** it is possible for this function to return -1.
+*/
+static void prefixLengthFunc(
+ sqlite3_context *ctx,
+ int nVal,
+ sqlite3_value **apVal
+){
+ int nByte; /* Number of bytes to compare */
+ int nRet = 0; /* Return value */
+ const unsigned char *zL = sqlite3_value_text(apVal[0]);
+ const unsigned char *zR = sqlite3_value_text(apVal[1]);
+ int nL = sqlite3_value_bytes(apVal[0]);
+ int nR = sqlite3_value_bytes(apVal[1]);
+ int i;
+
+ nByte = (nL > nR ? nL : nR);
+ for(i=0; i<nByte; i++){
+ if( zL[i]!=zR[i] ) break;
+ if( (zL[i] & 0xC0)!=0x80 ) nRet++;
+ }
+
+ if( (zL[i] & 0xC0)==0x80 ) nRet--;
+ sqlite3_result_int(ctx, nRet);
+}
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int sqlite3_prefixes_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ int rc = SQLITE_OK;
+ SQLITE_EXTENSION_INIT2(pApi);
+ rc = sqlite3_create_module(db, "prefixes", &prefixesModule, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_function(
+ db, "prefix_length", 2, SQLITE_UTF8, 0, prefixLengthFunc, 0, 0
+ );
+ }
+ return rc;
+}
+#endif /* !defined(SQLITE_CORE) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
diff --git a/chromium/third_party/sqlite/src/ext/misc/regexp.c b/chromium/third_party/sqlite/src/ext/misc/regexp.c
index 9001fef6fd9..5f6b7ce3e74 100644
--- a/chromium/third_party/sqlite/src/ext/misc/regexp.c
+++ b/chromium/third_party/sqlite/src/ext/misc/regexp.c
@@ -225,7 +225,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
pToFree = 0;
aStateSet[0].aState = aSpace;
}else{
- pToFree = sqlite3_malloc( sizeof(ReStateNumber)*2*pRe->nState );
+ pToFree = sqlite3_malloc64( sizeof(ReStateNumber)*2*pRe->nState );
if( pToFree==0 ) return -1;
aStateSet[0].aState = pToFree;
}
@@ -337,10 +337,10 @@ re_match_end:
static int re_resize(ReCompiled *p, int N){
char *aOp;
int *aArg;
- aOp = sqlite3_realloc(p->aOp, N*sizeof(p->aOp[0]));
+ aOp = sqlite3_realloc64(p->aOp, N*sizeof(p->aOp[0]));
if( aOp==0 ) return 1;
p->aOp = aOp;
- aArg = sqlite3_realloc(p->aArg, N*sizeof(p->aArg[0]));
+ aArg = sqlite3_realloc64(p->aArg, N*sizeof(p->aArg[0]));
if( aArg==0 ) return 1;
p->aArg = aArg;
p->nAlloc = N;
diff --git a/chromium/third_party/sqlite/src/ext/misc/unionvtab.c b/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
index 8a1d493de50..8e3784e81fd 100644
--- a/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
+++ b/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
@@ -250,11 +250,11 @@ struct UnionCsr {
** is attempted but fails, NULL is returned and *pRc is set to
** SQLITE_NOMEM.
*/
-static void *unionMalloc(int *pRc, int nByte){
+static void *unionMalloc(int *pRc, sqlite3_int64 nByte){
void *pRet;
assert( nByte>0 );
if( *pRc==SQLITE_OK ){
- pRet = sqlite3_malloc(nByte);
+ pRet = sqlite3_malloc64(nByte);
if( pRet ){
memset(pRet, 0, nByte);
}else{
@@ -276,7 +276,7 @@ static void *unionMalloc(int *pRc, int nByte){
static char *unionStrdup(int *pRc, const char *zIn){
char *zRet = 0;
if( zIn ){
- int nByte = (int)strlen(zIn) + 1;
+ sqlite3_int64 nByte = strlen(zIn) + 1;
zRet = unionMalloc(pRc, nByte);
if( zRet ){
memcpy(zRet, zIn, nByte);
@@ -939,7 +939,7 @@ static int unionConnect(
/* Grow the pTab->aSrc[] array if required. */
if( nAlloc<=pTab->nSrc ){
int nNew = nAlloc ? nAlloc*2 : 8;
- UnionSrc *aNew = (UnionSrc*)sqlite3_realloc(
+ UnionSrc *aNew = (UnionSrc*)sqlite3_realloc64(
pTab->aSrc, nNew*sizeof(UnionSrc)
);
if( aNew==0 ){
diff --git a/chromium/third_party/sqlite/src/ext/misc/vfslog.c b/chromium/third_party/sqlite/src/ext/misc/vfslog.c
index 263037ef77d..c9cbc80f72b 100644
--- a/chromium/third_party/sqlite/src/ext/misc/vfslog.c
+++ b/chromium/third_party/sqlite/src/ext/misc/vfslog.c
@@ -276,7 +276,7 @@ static VLogLog *vlogLogOpen(const char *zFilename){
&& sqlite3_strglob("-mj??????9??", zFilename+nName-12)==0 ){
return 0; /* Do not log master journal files */
}
- pTemp = sqlite3_malloc( sizeof(*pLog)*2 + nName + 60 );
+ pTemp = sqlite3_malloc64( sizeof(*pLog)*2 + nName + 60 );
if( pTemp==0 ) return 0;
pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(pMutex);
diff --git a/chromium/third_party/sqlite/src/ext/misc/zipfile.c b/chromium/third_party/sqlite/src/ext/misc/zipfile.c
index a69f3a7e9e9..5a88389bf2d 100644
--- a/chromium/third_party/sqlite/src/ext/misc/zipfile.c
+++ b/chromium/third_party/sqlite/src/ext/misc/zipfile.c
@@ -358,7 +358,7 @@ static int zipfileConnect(
rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
if( rc==SQLITE_OK ){
- pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
+ pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, nByte+nFile);
pNew->db = db;
@@ -806,7 +806,7 @@ static int zipfileGetEntry(
}
if( rc==SQLITE_OK ){
- int nAlloc;
+ sqlite3_int64 nAlloc;
ZipfileEntry *pNew;
int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
@@ -818,7 +818,7 @@ static int zipfileGetEntry(
nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
}
- pNew = (ZipfileEntry*)sqlite3_malloc(nAlloc);
+ pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -981,11 +981,11 @@ static int zipfileDeflate(
u8 **ppOut, int *pnOut, /* Output */
char **pzErr /* OUT: Error message */
){
- int nAlloc = (int)compressBound(nIn);
+ sqlite3_int64 nAlloc = compressBound(nIn);
u8 *aOut;
int rc = SQLITE_OK;
- aOut = (u8*)sqlite3_malloc(nAlloc);
+ aOut = (u8*)sqlite3_malloc64(nAlloc);
if( aOut==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1058,7 +1058,7 @@ static int zipfileColumn(
if( pCsr->pCurrent->aData ){
aBuf = pCsr->pCurrent->aData;
}else{
- aBuf = aFree = sqlite3_malloc(sz);
+ aBuf = aFree = sqlite3_malloc64(sz);
if( aBuf==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1897,14 +1897,14 @@ struct ZipfileCtx {
static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
if( pBuf->n+nByte>pBuf->nAlloc ){
u8 *aNew;
- int nNew = pBuf->n ? pBuf->n*2 : 512;
+ sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
int nReq = pBuf->n + nByte;
while( nNew<nReq ) nNew = nNew*2;
- aNew = sqlite3_realloc(pBuf->a, nNew);
+ aNew = sqlite3_realloc64(pBuf->a, nNew);
if( aNew==0 ) return SQLITE_NOMEM;
pBuf->a = aNew;
- pBuf->nAlloc = nNew;
+ pBuf->nAlloc = (int)nNew;
}
return SQLITE_OK;
}
@@ -2095,7 +2095,7 @@ void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
void zipfileFinal(sqlite3_context *pCtx){
ZipfileCtx *p;
ZipfileEOCD eocd;
- int nZip;
+ sqlite3_int64 nZip;
u8 *aZip;
p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
@@ -2108,14 +2108,14 @@ void zipfileFinal(sqlite3_context *pCtx){
eocd.iOffset = p->body.n;
nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
- aZip = (u8*)sqlite3_malloc(nZip);
+ aZip = (u8*)sqlite3_malloc64(nZip);
if( aZip==0 ){
sqlite3_result_error_nomem(pCtx);
}else{
memcpy(aZip, p->body.a, p->body.n);
memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
- sqlite3_result_blob(pCtx, aZip, nZip, zipfileFree);
+ sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
}
}
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu_common.tcl b/chromium/third_party/sqlite/src/ext/rbu/rbu_common.tcl
index 2b263b7660d..b5e63aafe55 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu_common.tcl
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu_common.tcl
@@ -86,12 +86,13 @@ proc step_rbu_legacy {target rbu} {
set rc
}
-proc do_rbu_vacuum_test {tn step} {
- forcedelete state.db
- uplevel [list do_test $tn.1 {
- if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
+proc do_rbu_vacuum_test {tn step {statedb state.db}} {
+ forcedelete $statedb
+ if {$statedb=="" && $step==1} breakpoint
+ uplevel [list do_test $tn.1 [string map [list %state% $statedb] {
+ if {$step==0} { sqlite3rbu_vacuum rbu test.db {%state%}}
while 1 {
- if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
+ if {$step==1} { sqlite3rbu_vacuum rbu test.db {%state%}}
set state [rbu state]
check_prestep_state test.db $state
set rc [rbu step]
@@ -100,7 +101,7 @@ proc do_rbu_vacuum_test {tn step} {
if {$step==1} { rbu close }
}
rbu close
- } {SQLITE_DONE}]
+ }] {SQLITE_DONE}]
uplevel [list do_execsql_test $tn.2 {
PRAGMA integrity_check
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test b/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test
index 140a0c1a8c4..6827725fb57 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test
@@ -16,8 +16,11 @@
source [file join [file dirname [info script]] rbu_common.tcl]
-foreach step {0 1} {
- set ::testprefix rbuvacuum2-$step
+foreach {step} {0 1} {
+foreach {ttt state} {
+ s state.db t test.db-vacuum n {}
+} {
+ set ::testprefix rbuvacuum2-$step$ttt
#-------------------------------------------------------------------------
# Test that a database that contains fts3 tables can be vacuumed.
@@ -29,7 +32,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('fix this issue', 'at some point');
}
- do_rbu_vacuum_test 1.2 $step
+ do_rbu_vacuum_test 1.2 $step $state
do_execsql_test 1.3 {
SELECT * FROM t1;
@@ -46,7 +49,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('a b c', 'x y z');
}
- do_rbu_vacuum_test 1.6 $step
+ do_rbu_vacuum_test 1.6 $step $state
do_execsql_test 1.7 {
INSERT INTO t1(t1) VALUES('integrity-check');
SELECT * FROM t1;
@@ -67,7 +70,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('fix this issue', 'at some point');
}
- do_rbu_vacuum_test 2.2 $step
+ do_rbu_vacuum_test 2.2 $step $state
do_execsql_test 2.3 {
SELECT * FROM t1;
@@ -84,7 +87,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('a b c', 'x y z');
}
- do_rbu_vacuum_test 2.6 $step
+ do_rbu_vacuum_test 2.6 $step $state
do_execsql_test 2.7 {
INSERT INTO t1(t1) VALUES('integrity-check');
SELECT * FROM t1;
@@ -107,7 +110,7 @@ foreach step {0 1} {
INSERT INTO rt VALUES(3, 55, 65);
}
- do_rbu_vacuum_test 3.2 $step
+ do_rbu_vacuum_test 3.2 $step $state
do_execsql_test 3.3 {
SELECT * FROM rt;
@@ -120,7 +123,7 @@ foreach step {0 1} {
SELECT rowid FROM rt WHERE x2>59 AND x1 < 59
} {2 3}
- do_rbu_vacuum_test 3.5 $step
+ do_rbu_vacuum_test 3.5 $step $state
do_execsql_test 3.6.1 {
SELECT rowid FROM rt WHERE x2>51 AND x1 < 51
@@ -147,7 +150,7 @@ foreach step {0 1} {
trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
}
- do_rbu_vacuum_test 4.3 $step
+ do_rbu_vacuum_test 4.3 $step $state
do_execsql_test 4.4 {
SELECT * FROM sqlite_master;
} {
@@ -157,6 +160,7 @@ foreach step {0 1} {
}
}
}
+}
#-------------------------------------------------------------------------
# Test that passing a NULL value as the second argument to
@@ -231,4 +235,9 @@ do_test 6.3 {
execsql { PRAGMA integrity_check }
} {ok}
+do_test 6.4 {
+ sqlite3rbu_vacuum rbu test.db test.db-vactmp
+ list [catch { rbu close } msg] $msg
+} {1 SQLITE_MISUSE}
+
finish_test
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum3.test b/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum3.test
new file mode 100644
index 00000000000..d0cf461b2b3
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum3.test
@@ -0,0 +1,63 @@
+# 2019 Jan 3
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file contains tests for the RBU module. More specifically, it
+# contains tests to ensure that the sqlite3rbu_vacuum() API works as
+# expected.
+#
+
+source [file join [file dirname [info script]] rbu_common.tcl]
+set testprefix rbuvacuum3
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a PRIMARY KEY, b, c);
+ CREATE INDEX i1b ON t1(b);
+ CREATE INDEX i1c ON t1(c);
+
+ WITH s(i) AS (
+ VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100
+ )
+ INSERT INTO t1 SELECT i, randomblob(100), randomblob(100) FROM s;
+}
+
+forcedelete state.db
+do_test 1.1 {
+ sqlite3rbu_vacuum rbu test.db state.db
+ while {1} {
+ set rc [rbu step]
+ if {$rc!="SQLITE_OK"} break
+ rbu savestate
+ }
+ rbu close
+} {SQLITE_DONE}
+
+do_test 1.2 {
+ sqlite3rbu_vacuum rbu test.db state.db
+ while {1} {
+ set rc [rbu step]
+ if {$rc!="SQLITE_OK"} break
+ rbu savestate
+ }
+ rbu close
+} {SQLITE_DONE}
+
+do_test 1.3 {
+ while {1} {
+ sqlite3rbu_vacuum rbu test.db state.db
+ set rc [rbu step]
+ if {$rc!="SQLITE_OK"} break
+ rbu savestate
+ rbu close
+ }
+ rbu close
+} {SQLITE_DONE}
+
+finish_test
diff --git a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
index 0762529dcb0..4c81dcf1107 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
+++ b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
@@ -2477,7 +2477,7 @@ static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
if( *zExtra=='\0' ) zExtra = 0;
}
- zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s",
+ zTarget = sqlite3_mprintf("file:%s-vactmp?rbu_memory=1%s%s",
sqlite3_db_filename(p->dbRbu, "main"),
(zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra)
);
@@ -3743,6 +3743,12 @@ sqlite3rbu *sqlite3rbu_vacuum(
const char *zState
){
if( zTarget==0 ){ return rbuMisuseError(); }
+ if( zState ){
+ int n = strlen(zState);
+ if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
+ return rbuMisuseError();
+ }
+ }
/* TODO: Check that both arguments are non-NULL */
return openRbuHandle(0, zTarget, zState);
}
@@ -3939,7 +3945,10 @@ int sqlite3rbu_savestate(sqlite3rbu *p){
if( p->eStage==RBU_STAGE_OAL ){
assert( rc!=SQLITE_DONE );
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "COMMIT", 0, 0, 0);
- if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbRbu, "BEGIN IMMEDIATE", 0, 0, 0);
+ if( rc==SQLITE_OK ){
+ const char *zBegin = rbuIsVacuum(p) ? "BEGIN" : "BEGIN IMMEDIATE";
+ rc = sqlite3_exec(p->dbRbu, zBegin, 0, 0, 0);
+ }
if( rc==SQLITE_OK ) rc = sqlite3_exec(p->dbMain, "BEGIN IMMEDIATE", 0, 0,0);
}
diff --git a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h
index 07b8685e243..1ffbd271f85 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h
+++ b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h
@@ -335,6 +335,10 @@ SQLITE_API sqlite3rbu *sqlite3rbu_open(
** state database is not already present in the file-system, it is created
** with the same permissions as the target db is made.
**
+** With an RBU vacuum, it is an SQLITE_MISUSE error if the name of the
+** state database ends with "-vactmp". This name is reserved for internal
+** use.
+**
** This function does not delete the state database after an RBU vacuum
** is completed, even if it created it. However, if the call to
** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents
diff --git a/chromium/third_party/sqlite/src/ext/rbu/test_rbu.c b/chromium/third_party/sqlite/src/ext/rbu/test_rbu.c
index 1c1c9b41cc4..054774e606c 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/test_rbu.c
+++ b/chromium/third_party/sqlite/src/ext/rbu/test_rbu.c
@@ -273,6 +273,7 @@ static int SQLITE_TCLAPI test_sqlite3rbu_vacuum(
zCmd = Tcl_GetString(objv[1]);
zTarget = Tcl_GetString(objv[2]);
if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
+ if( zStateDb && zStateDb[0]=='\0' ) zStateDb = 0;
pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
diff --git a/chromium/third_party/sqlite/src/ext/rtree/geopoly.c b/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
index d7f6cd5f253..3652d14a1f3 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
+++ b/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
@@ -124,6 +124,14 @@ struct GeoPoly {
*/
#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))
+/* Macros to access coordinates of a GeoPoly.
+** We have to use these macros, rather than just say p->a[i] in order
+** to silence (incorrect) UBSAN warnings if the array index is too large.
+*/
+#define GeoX(P,I) (((GeoCoord*)(P)->a)[(I)*2])
+#define GeoY(P,I) (((GeoCoord*)(P)->a)[(I)*2+1])
+
+
/*
** State of a parse of a GeoJSON input.
*/
@@ -316,8 +324,9 @@ static GeoPoly *geopolyFuncParam(
memcpy(p->hdr, a, nByte);
if( a[0] != *(unsigned char*)&x ){
int ii;
- for(ii=0; ii<nVertex*2; ii++){
- geopolySwab32((unsigned char*)&p->a[ii]);
+ for(ii=0; ii<nVertex; ii++){
+ geopolySwab32((unsigned char*)&GeoX(p,ii));
+ geopolySwab32((unsigned char*)&GeoY(p,ii));
}
p->hdr[0] ^= 1;
}
@@ -376,9 +385,9 @@ static void geopolyJsonFunc(
int i;
sqlite3_str_append(x, "[", 1);
for(i=0; i<p->nVertex; i++){
- sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]);
+ sqlite3_str_appendf(x, "[%!g,%!g],", GeoX(p,i), GeoY(p,i));
}
- sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]);
+ sqlite3_str_appendf(x, "[%!g,%!g]]", GeoX(p,0), GeoY(p,0));
sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free);
sqlite3_free(p);
}
@@ -395,7 +404,9 @@ static void geopolySvgFunc(
int argc,
sqlite3_value **argv
){
- GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ GeoPoly *p;
+ if( argc<1 ) return;
+ p = geopolyFuncParam(context, argv[0], 0);
if( p ){
sqlite3 *db = sqlite3_context_db_handle(context);
sqlite3_str *x = sqlite3_str_new(db);
@@ -403,10 +414,10 @@ static void geopolySvgFunc(
char cSep = '\'';
sqlite3_str_appendf(x, "<polyline points=");
for(i=0; i<p->nVertex; i++){
- sqlite3_str_appendf(x, "%c%g,%g", cSep, p->a[i*2], p->a[i*2+1]);
+ sqlite3_str_appendf(x, "%c%g,%g", cSep, GeoX(p,i), GeoY(p,i));
cSep = ' ';
}
- sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]);
+ sqlite3_str_appendf(x, " %g,%g'", GeoX(p,0), GeoY(p,0));
for(i=1; i<argc; i++){
const char *z = (const char*)sqlite3_value_text(argv[i]);
if( z && z[0] ){
@@ -451,12 +462,12 @@ static void geopolyXformFunc(
int ii;
if( p ){
for(ii=0; ii<p->nVertex; ii++){
- x0 = p->a[ii*2];
- y0 = p->a[ii*2+1];
+ x0 = GeoX(p,ii);
+ y0 = GeoY(p,ii);
x1 = (GeoCoord)(A*x0 + B*y0 + E);
y1 = (GeoCoord)(C*x0 + D*y0 + F);
- p->a[ii*2] = x1;
- p->a[ii*2+1] = y1;
+ GeoX(p,ii) = x1;
+ GeoY(p,ii) = y1;
}
sqlite3_result_blob(context, p->hdr,
4+8*p->nVertex, SQLITE_TRANSIENT);
@@ -475,12 +486,12 @@ static double geopolyArea(GeoPoly *p){
double rArea = 0.0;
int ii;
for(ii=0; ii<p->nVertex-1; ii++){
- rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
- * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
+ rArea += (GeoX(p,ii) - GeoX(p,ii+1)) /* (x0 - x1) */
+ * (GeoY(p,ii) + GeoY(p,ii+1)) /* (y0 + y1) */
* 0.5;
}
- rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
- * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
+ rArea += (GeoX(p,ii) - GeoX(p,0)) /* (xN - x0) */
+ * (GeoY(p,ii) + GeoY(p,0)) /* (yN + y0) */
* 0.5;
return rArea;
}
@@ -527,13 +538,13 @@ static void geopolyCcwFunc(
if( p ){
if( geopolyArea(p)<0.0 ){
int ii, jj;
- for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){
- GeoCoord t = p->a[ii];
- p->a[ii] = p->a[jj];
- p->a[jj] = t;
- t = p->a[ii+1];
- p->a[ii+1] = p->a[jj+1];
- p->a[jj+1] = t;
+ for(ii=1, jj=p->nVertex-1; ii<jj; ii++, jj--){
+ GeoCoord t = GeoX(p,ii);
+ GeoX(p,ii) = GeoX(p,jj);
+ GeoX(p,jj) = t;
+ t = GeoY(p,ii);
+ GeoY(p,ii) = GeoY(p,jj);
+ GeoY(p,jj) = t;
}
}
sqlite3_result_blob(context, p->hdr,
@@ -593,8 +604,8 @@ static void geopolyRegularFunc(
p->hdr[3] = n&0xff;
for(i=0; i<n; i++){
double rAngle = 2.0*GEOPOLY_PI*i/n;
- p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
- p->a[i*2+1] = y + r*geopolySine(rAngle);
+ GeoX(p,i) = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
+ GeoY(p,i) = y + r*geopolySine(rAngle);
}
sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
sqlite3_free(p);
@@ -631,13 +642,13 @@ static GeoPoly *geopolyBBox(
}
if( p ){
int ii;
- mnX = mxX = p->a[0];
- mnY = mxY = p->a[1];
+ mnX = mxX = GeoX(p,0);
+ mnY = mxY = GeoY(p,0);
for(ii=1; ii<p->nVertex; ii++){
- double r = p->a[ii*2];
+ double r = GeoX(p,ii);
if( r<mnX ) mnX = (float)r;
else if( r>mxX ) mxX = (float)r;
- r = p->a[ii*2+1];
+ r = GeoY(p,ii);
if( r<mnY ) mnY = (float)r;
else if( r>mxY ) mxY = (float)r;
}
@@ -657,14 +668,14 @@ static GeoPoly *geopolyBBox(
pOut->hdr[1] = 0;
pOut->hdr[2] = 0;
pOut->hdr[3] = 4;
- pOut->a[0] = mnX;
- pOut->a[1] = mnY;
- pOut->a[2] = mxX;
- pOut->a[3] = mnY;
- pOut->a[4] = mxX;
- pOut->a[5] = mxY;
- pOut->a[6] = mnX;
- pOut->a[7] = mxY;
+ GeoX(pOut,0) = mnX;
+ GeoY(pOut,0) = mnY;
+ GeoX(pOut,1) = mxX;
+ GeoY(pOut,1) = mnY;
+ GeoX(pOut,2) = mxX;
+ GeoY(pOut,2) = mxY;
+ GeoX(pOut,3) = mnX;
+ GeoY(pOut,3) = mxY;
}else{
sqlite3_free(p);
aCoord[0].f = mnX;
@@ -802,14 +813,14 @@ static void geopolyContainsPointFunc(
int ii;
if( p1==0 ) return;
for(ii=0; ii<p1->nVertex-1; ii++){
- v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
- p1->a[ii*2+2],p1->a[ii*2+3]);
+ v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii),
+ GeoX(p1,ii+1),GeoY(p1,ii+1));
if( v==2 ) break;
cnt += v;
}
if( v!=2 ){
- v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
- p1->a[0],p1->a[1]);
+ v = pointBeneathLine(x0,y0,GeoX(p1,ii), GeoY(p1,ii),
+ GeoX(p1,0), GeoY(p1,0));
}
if( v==2 ){
sqlite3_result_int(context, 1);
@@ -931,10 +942,10 @@ static void geopolyAddSegments(
unsigned int i;
GeoCoord *x;
for(i=0; i<(unsigned)pPoly->nVertex-1; i++){
- x = pPoly->a + (i*2);
+ x = &GeoX(pPoly,i);
geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i);
}
- x = pPoly->a + (i*2);
+ x = &GeoX(pPoly,i);
geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i);
}
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtree.c b/chromium/third_party/sqlite/src/ext/rtree/rtree.c
index e09db482279..3a16c5d4e18 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtree.c
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtree.c
@@ -128,6 +128,9 @@ struct Rtree {
u8 inWrTrans; /* True if inside write transaction */
u8 nAux; /* # of auxiliary columns in %_rowid */
u8 nAuxNotNull; /* Number of initial not-null aux columns */
+#ifdef SQLITE_DEBUG
+ u8 bCorrupt; /* Shadow table corruption detected */
+#endif
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
char *zName; /* Name of r-tree table */
@@ -188,6 +191,15 @@ struct Rtree {
#endif
/*
+** Set the Rtree.bCorrupt flag
+*/
+#ifdef SQLITE_DEBUG
+# define RTREE_IS_CORRUPT(X) ((X)->bCorrupt = 1)
+#else
+# define RTREE_IS_CORRUPT(X)
+#endif
+
+/*
** When doing a search of an r-tree, instances of the following structure
** record intermediate results from the tree walk.
**
@@ -553,8 +565,8 @@ static void nodeZero(Rtree *pRtree, RtreeNode *p){
** Given a node number iNode, return the corresponding key to use
** in the Rtree.aHash table.
*/
-static int nodeHash(i64 iNode){
- return iNode % HASHSIZE;
+static unsigned int nodeHash(i64 iNode){
+ return ((unsigned)iNode) % HASHSIZE;
}
/*
@@ -599,7 +611,7 @@ static void nodeHashDelete(Rtree *pRtree, RtreeNode *pNode){
*/
static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
RtreeNode *pNode;
- pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode) + pRtree->iNodeSize);
+ pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode) + pRtree->iNodeSize);
if( pNode ){
memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
pNode->zData = (u8 *)&pNode[1];
@@ -624,6 +636,18 @@ static void nodeBlobReset(Rtree *pRtree){
}
/*
+** Check to see if pNode is the same as pParent or any of the parents
+** of pParent.
+*/
+static int nodeInParentChain(const RtreeNode *pNode, const RtreeNode *pParent){
+ do{
+ if( pNode==pParent ) return 1;
+ pParent = pParent->pParent;
+ }while( pParent );
+ return 0;
+}
+
+/*
** Obtain a reference to an r-tree node.
*/
static int nodeAcquire(
@@ -641,6 +665,10 @@ static int nodeAcquire(
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
if( pParent && !pNode->pParent ){
+ if( nodeInParentChain(pNode, pParent) ){
+ RTREE_IS_CORRUPT(pRtree);
+ return SQLITE_CORRUPT_VTAB;
+ }
pParent->nRef++;
pNode->pParent = pParent;
}
@@ -671,9 +699,12 @@ static int nodeAcquire(
*ppNode = 0;
/* If unable to open an sqlite3_blob on the desired row, that can only
** be because the shadow tables hold erroneous data. */
- if( rc==SQLITE_ERROR ) rc = SQLITE_CORRUPT_VTAB;
+ if( rc==SQLITE_ERROR ){
+ rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
+ }
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
- pNode = (RtreeNode *)sqlite3_malloc(sizeof(RtreeNode)+pRtree->iNodeSize);
+ pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
if( !pNode ){
rc = SQLITE_NOMEM;
}else{
@@ -686,7 +717,6 @@ static int nodeAcquire(
pNode->pNext = 0;
rc = sqlite3_blob_read(pRtree->pNodeBlob, pNode->zData,
pRtree->iNodeSize, 0);
- nodeReference(pParent);
}
}
@@ -700,6 +730,7 @@ static int nodeAcquire(
pRtree->iDepth = readInt16(pNode->zData);
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
}
}
@@ -710,14 +741,17 @@ static int nodeAcquire(
if( pNode && rc==SQLITE_OK ){
if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
}
}
if( rc==SQLITE_OK ){
if( pNode!=0 ){
+ nodeReference(pParent);
nodeHashInsert(pRtree, pNode);
}else{
rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
}
*ppNode = pNode;
}else{
@@ -943,7 +977,7 @@ static void rtreeRelease(Rtree *pRtree){
pRtree->inWrTrans = 0;
assert( pRtree->nCursor==0 );
nodeBlobReset(pRtree);
- assert( pRtree->nNodeRef==0 );
+ assert( pRtree->nNodeRef==0 || pRtree->bCorrupt );
sqlite3_finalize(pRtree->pWriteNode);
sqlite3_finalize(pRtree->pDeleteNode);
sqlite3_finalize(pRtree->pReadRowid);
@@ -1002,7 +1036,7 @@ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
Rtree *pRtree = (Rtree *)pVTab;
RtreeCursor *pCsr;
- pCsr = (RtreeCursor *)sqlite3_malloc(sizeof(RtreeCursor));
+ pCsr = (RtreeCursor *)sqlite3_malloc64(sizeof(RtreeCursor));
if( pCsr ){
memset(pCsr, 0, sizeof(RtreeCursor));
pCsr->base.pVtab = pVTab;
@@ -1275,6 +1309,7 @@ static int nodeRowidIndex(
return SQLITE_OK;
}
}
+ RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -1368,7 +1403,7 @@ static RtreeSearchPoint *rtreeEnqueue(
RtreeSearchPoint *pNew;
if( pCur->nPoint>=pCur->nPointAlloc ){
int nNew = pCur->nPointAlloc*2 + 8;
- pNew = sqlite3_realloc(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
+ pNew = sqlite3_realloc64(pCur->aPoint, nNew*sizeof(pCur->aPoint[0]));
if( pNew==0 ) return 0;
pCur->aPoint = pNew;
pCur->nPointAlloc = nNew;
@@ -1770,7 +1805,7 @@ static int rtreeFilter(
*/
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
if( rc==SQLITE_OK && argc>0 ){
- pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
+ pCsr->aConstraint = sqlite3_malloc64(sizeof(RtreeConstraint)*argc);
pCsr->nConstraint = argc;
if( !pCsr->aConstraint ){
rc = SQLITE_NOMEM;
@@ -1915,20 +1950,20 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
){
u8 op;
switch( p->op ){
- case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
- case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
- case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
- case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
- case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
- default:
- assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
- op = RTREE_MATCH;
- break;
+ case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
+ case SQLITE_INDEX_CONSTRAINT_GT: op = RTREE_GT; break;
+ case SQLITE_INDEX_CONSTRAINT_LE: op = RTREE_LE; break;
+ case SQLITE_INDEX_CONSTRAINT_LT: op = RTREE_LT; break;
+ case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
+ case SQLITE_INDEX_CONSTRAINT_MATCH: op = RTREE_MATCH; break;
+ default: op = 0; break;
+ }
+ if( op ){
+ zIdxStr[iIdx++] = op;
+ zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
+ pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
+ pIdxInfo->aConstraintUsage[ii].omit = 1;
}
- zIdxStr[iIdx++] = op;
- zIdxStr[iIdx++] = (char)(p->iColumn - 1 + '0');
- pIdxInfo->aConstraintUsage[ii].argvIndex = (iIdx/2);
- pIdxInfo->aConstraintUsage[ii].omit = 1;
}
}
@@ -1964,11 +1999,11 @@ static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){
#endif
{
switch( pRtree->nDim ){
- case 5: area = p->aCoord[9].i - p->aCoord[8].i;
- case 4: area *= p->aCoord[7].i - p->aCoord[6].i;
- case 3: area *= p->aCoord[5].i - p->aCoord[4].i;
- case 2: area *= p->aCoord[3].i - p->aCoord[2].i;
- default: area *= p->aCoord[1].i - p->aCoord[0].i;
+ case 5: area = (i64)p->aCoord[9].i - (i64)p->aCoord[8].i;
+ case 4: area *= (i64)p->aCoord[7].i - (i64)p->aCoord[6].i;
+ case 3: area *= (i64)p->aCoord[5].i - (i64)p->aCoord[4].i;
+ case 2: area *= (i64)p->aCoord[3].i - (i64)p->aCoord[2].i;
+ default: area *= (i64)p->aCoord[1].i - (i64)p->aCoord[0].i;
}
}
return area;
@@ -2137,12 +2172,14 @@ static int AdjustTree(
RtreeCell *pCell /* This cell was just inserted */
){
RtreeNode *p = pNode;
+ int cnt = 0;
while( p->pParent ){
RtreeNode *pParent = p->pParent;
RtreeCell cell;
int iCell;
- if( nodeParentIndex(pRtree, p, &iCell) ){
+ if( (++cnt)>1000 || nodeParentIndex(pRtree, p, &iCell) ){
+ RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -2339,9 +2376,9 @@ static int splitNodeStartree(
int iBestSplit = 0;
RtreeDValue fBestMargin = RTREE_ZERO;
- int nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
+ sqlite3_int64 nByte = (pRtree->nDim+1)*(sizeof(int*)+nCell*sizeof(int));
- aaSorted = (int **)sqlite3_malloc(nByte);
+ aaSorted = (int **)sqlite3_malloc64(nByte);
if( !aaSorted ){
return SQLITE_NOMEM;
}
@@ -2462,7 +2499,7 @@ static int SplitNode(
/* Allocate an array and populate it with a copy of pCell and
** all cells from node pLeft. Then zero the original node.
*/
- aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
+ aCell = sqlite3_malloc64((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
if( !aCell ){
rc = SQLITE_NOMEM;
goto splitnode_out;
@@ -2610,7 +2647,10 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
}
rc = sqlite3_reset(pRtree->pReadParent);
if( rc==SQLITE_OK ) rc = rc2;
- if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
+ if( rc==SQLITE_OK && !pChild->pParent ){
+ RTREE_IS_CORRUPT(pRtree);
+ rc = SQLITE_CORRUPT_VTAB;
+ }
pChild = pChild->pParent;
}
return rc;
@@ -2750,7 +2790,7 @@ static int Reinsert(
/* Allocate the buffers used by this operation. The allocation is
** relinquished before this function returns.
*/
- aCell = (RtreeCell *)sqlite3_malloc(n * (
+ aCell = (RtreeCell *)sqlite3_malloc64(n * (
sizeof(RtreeCell) + /* aCell array */
sizeof(int) + /* aOrder array */
sizeof(int) + /* aSpare array */
@@ -2924,8 +2964,12 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
rc = findLeafNode(pRtree, iDelete, &pLeaf, 0);
}
+#ifdef CORRUPT_DB
+ assert( pLeaf!=0 || rc!=SQLITE_OK || CORRUPT_DB );
+#endif
+
/* Delete the cell in question from the leaf node. */
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && pLeaf ){
int rc2;
rc = nodeRowidIndex(pRtree, pLeaf, iDelete, &iCell);
if( rc==SQLITE_OK ){
@@ -3197,7 +3241,7 @@ static int rtreeUpdate(
rc = rc2;
}
}
- if( pRtree->nAux ){
+ if( rc==SQLITE_OK && pRtree->nAux ){
sqlite3_stmt *pUp = pRtree->pWriteAux;
int jj;
sqlite3_bind_int64(pUp, 1, *pRowid);
@@ -3558,6 +3602,7 @@ static int getNodeSize(
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else if( pRtree->iNodeSize<(512-64) ){
rc = SQLITE_CORRUPT_VTAB;
+ RTREE_IS_CORRUPT(pRtree);
*pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
pRtree->zName);
}
@@ -3613,7 +3658,7 @@ static int rtreeInit(
/* Allocate the sqlite3_vtab structure */
nDb = (int)strlen(argv[1]);
nName = (int)strlen(argv[2]);
- pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
+ pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2);
if( !pRtree ){
return SQLITE_NOMEM;
}
@@ -3881,8 +3926,7 @@ static void rtreeCheckAppendMsg(RtreeCheck *pCheck, const char *zFmt, ...){
static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
u8 *pRet = 0; /* Return value */
- assert( pCheck->rc==SQLITE_OK );
- if( pCheck->pGetNode==0 ){
+ if( pCheck->rc==SQLITE_OK && pCheck->pGetNode==0 ){
pCheck->pGetNode = rtreeCheckPrepare(pCheck,
"SELECT data FROM %Q.'%q_node' WHERE nodeno=?",
pCheck->zDb, pCheck->zTab
@@ -3894,7 +3938,7 @@ static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
if( sqlite3_step(pCheck->pGetNode)==SQLITE_ROW ){
int nNode = sqlite3_column_bytes(pCheck->pGetNode, 0);
const u8 *pNode = (const u8*)sqlite3_column_blob(pCheck->pGetNode, 0);
- pRet = sqlite3_malloc(nNode);
+ pRet = sqlite3_malloc64(nNode);
if( pRet==0 ){
pCheck->rc = SQLITE_NOMEM;
}else{
@@ -4327,12 +4371,12 @@ static void rtreeMatchArgFree(void *pArg){
static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
RtreeGeomCallback *pGeomCtx = (RtreeGeomCallback *)sqlite3_user_data(ctx);
RtreeMatchArg *pBlob;
- int nBlob;
+ sqlite3_int64 nBlob;
int memErr = 0;
nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
+ nArg*sizeof(sqlite3_value*);
- pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
+ pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
if( !pBlob ){
sqlite3_result_error_nomem(ctx);
}else{
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtree1.test b/chromium/third_party/sqlite/src/ext/rtree/rtree1.test
index 9e10fee8e68..ddc5f182f09 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtree1.test
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtree1.test
@@ -647,5 +647,19 @@ do_execsql_test 16.130 {
SELECT * FROM rt1 WHERE id IN (1, 2, 3, 4);
} {1 1.0 2.0 aux1 2 2.0 3.0 aux2 3 3.0 4.0 aux3 4 4.0 5.0 aux4}
+reset_db
+do_execsql_test 17.0 {
+ CREATE VIRTUAL TABLE t1 USING rtree(id, x1 PRIMARY KEY, x2, y1, y2);
+ CREATE VIRTUAL TABLE t2 USING rtree(id, x1, x2, y1, y2 UNIQUE);
+}
+do_execsql_test 17.1 {
+ REINDEX t1;
+ REINDEX t2;
+} {}
+
+do_execsql_test 17.2 {
+ REINDEX;
+} {}
+
expand_all_sql db
finish_test
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtree6.test b/chromium/third_party/sqlite/src/ext/rtree/rtree6.test
index ec8672e56af..29300882028 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtree6.test
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtree6.test
@@ -15,6 +15,7 @@ if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
+set testprefix rtree6
ifcapable {!rtree || rtree_int_only} {
finish_test
@@ -58,6 +59,9 @@ do_test rtree6-1.1 {
do_test rtree6-1.2 {
rtree_strategy {SELECT * FROM t1 WHERE x1>10}
} {E0}
+do_test rtree6-1.2.1 {
+ rtree_strategy {SELECT * FROM t1 WHERE x1>10 AND x2 LIKE '%x%'}
+} {E0}
do_test rtree6-1.3 {
rtree_strategy {SELECT * FROM t1 WHERE x1<10}
@@ -164,5 +168,14 @@ do_execsql_test rtree6-3.5 {
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>1.1
} {}
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 4.0 {
+ CREATE VIRTUAL TABLE t1 USING rtree(id,x0,x1,y0,y1);
+}
+do_execsql_test 4.1 {
+ DELETE FROM t1 WHERE x0>1 AND x1<2 OR y0<92;
+}
+
expand_all_sql db
finish_test
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtreecirc.test b/chromium/third_party/sqlite/src/ext/rtree/rtreecirc.test
new file mode 100644
index 00000000000..d77ed04b3de
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtreecirc.test
@@ -0,0 +1,66 @@
+# 2018 Dec 22
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#*************************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is testing the FTS5 module.
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source [file join [file dirname [info script]] rtree_util.tcl]
+source $testdir/tester.tcl
+set testprefix rtreecirc
+
+ifcapable !rtree {
+ finish_test
+ return
+}
+
+do_execsql_test 1.0 {
+ CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, y1, y2);
+ SELECT name FROM sqlite_master ORDER BY 1;
+} {
+ rt rt_node rt_parent rt_rowid
+}
+db_save_and_close
+
+foreach {tn schema sql} {
+ 1 {
+ CREATE TRIGGER tr1 AFTER INSERT ON rt_node BEGIN
+ SELECT * FROM rt;
+ END;
+ } {
+ INSERT INTO rt VALUES(1, 2, 3, 4, 5);
+ }
+ 2 {
+ CREATE TRIGGER tr1 AFTER INSERT ON rt_parent BEGIN
+ SELECT * FROM rt;
+ END;
+ } {
+ INSERT INTO rt VALUES(1, 2, 3, 4, 5);
+ }
+ 3 {
+ CREATE TRIGGER tr1 AFTER INSERT ON rt_rowid BEGIN
+ SELECT * FROM rt;
+ END;
+ } {
+ INSERT INTO rt VALUES(1, 2, 3, 4, 5);
+ }
+} {
+ db_restore_and_reopen
+ do_execsql_test 1.1.$tn.1 $schema
+ do_catchsql_test 1.1.$tn.2 $sql {1 {no such table: main.rt}}
+ db close
+}
+
+
+finish_test
+
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtreefuzz001.test b/chromium/third_party/sqlite/src/ext/rtree/rtreefuzz001.test
new file mode 100644
index 00000000000..36c8d27ec74
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtreefuzz001.test
@@ -0,0 +1,777 @@
+# 2012-12-21
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# Test cases for corrupt database files.
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source $testdir/tester.tcl
+
+ifcapable !deserialize||!rtree {
+ finish_test
+ return
+}
+database_may_be_corrupt
+
+do_test rtreefuzz001-100 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 24576 pagesize 4096 filename c1b.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 03 00 00 00 06 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 04 ................
+| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
+| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 ................
+| 96: 00 2e 30 38 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f ..08...........O
+| 112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17 ............^...
+| 3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72 .....tablet1_par
+| 3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45 entt1_parent.CRE
+| 3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61 ATE TABLE .t1_pa
+| 3792: 72 66 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 rfnt.(nodeno INT
+| 3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
+| 3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17 ,parentnode)Q...
+| 3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65 ....tablet1_node
+| 3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54 t1_node.CREATE T
+| 3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e ABLE .t1_node.(n
+| 3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52 odeno INTEGER PR
+| 3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c IMARY KEY,data).
+| 3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f ........tablet1_
+| 3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52 rowidt1_rowid.CR
+| 3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72 EATE TABLE .t1_r
+| 3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
+| 3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
+| 4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07 nodeno,a0,a1)Q..
+| 4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43 ......tablet1t1C
+| 4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
+| 4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 BLE t1 USING rtr
+| 4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79 ee(id,x0,x1,y0,y
+| 4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29 1,+label,+other)
+| page 2 offset 4096
+| 0: 0d 0c cd 00 74 08 75 01 0f e8 0c b3 0f d0 0f b7 ....t.u.........
+| 16: 0f 9e 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29 .......p.^.O.9.)
+| 32: 0f 18 0f 06 0e f7 0c 65 0e 58 0d c2 0d 2c 0c 25 .......e.X...,.%
+| 48: 0b 85 0a e5 0a 45 09 a5 09 05 0c 83 0c 93 0c a3 .....E..........
+| 64: 0f f0 0c 15 0b 75 0a d5 0a 35 09 95 08 f5 0e d8 .....u...5......
+| 80: 0e 42 0d ac 0d 16 0c 05 0b 65 0a c5 0a 25 09 85 .B.......e...%..
+| 96: 08 e5 0e c8 0e 32 0d 9c 0d 06 0b f5 0b 55 0a b5 .....2.......U..
+| 112: 0a 15 09 75 08 d5 0e b8 0e 22 0d 8c 0c f6 0b e5 ...u............
+| 128: 0b 45 0a a5 0a 05 09 65 08 c5 0e a8 0e 12 0d 7c .E.....e.......|
+| 144: 0c e6 0b d5 0b 35 0a 95 09 f5 09 55 08 b5 0e 98 .....5.....U....
+| 160: 0e 02 0d 6c 0c d6 0b c5 0b 25 0a 85 09 e5 09 45 ...l.....%.....E
+| 176: 08 a5 0e 88 0d f2 0d 5c 0c 55 0b b5 0b 15 0a 75 .........U.....u
+| 192: 09 d5 09 35 08 95 0e 78 0d e2 0d 4c 0c 45 0b a5 ...5...x...L.E..
+| 208: 0b 05 0a 65 09 c5 09 25 08 85 0e 68 0d d2 0d 3c ...e...%...h...<
+| 224: 0c 35 0b 95 0a f5 0a 55 09 b5 09 15 08 75 0c 75 .5.....U.....u.u
+| 2160: 00 00 00 00 00 0d 8e 75 05 00 01 1b 00 04 62 6f .......u......bo
+| 2176: 78 2d 39 2c 39 0d 8e 11 05 00 01 1b 00 02 62 6f x-9,9.........bo
+| 2192: 78 2d 39 2c 38 0d 8d 2d 05 00 01 1b 00 02 62 6f x-9,8..-......bo
+| 2208: 78 2d 39 2c 37 0d 8c 49 05 00 01 1b 00 02 62 6f x-9,7..I......bo
+| 2224: 78 2d 39 2c 36 0d 8b 65 05 00 01 1b 00 02 62 6f x-9,6..e......bo
+| 2240: 78 2d 39 2c 35 0d 8b 01 05 00 01 1b 00 02 62 6f x-9,5.........bo
+| 2256: 78 2d 39 2c 34 0d 8a 1d 05 00 01 1b 00 02 62 6f x-9,4.........bo
+| 2272: 78 2d 39 2c 33 0d 89 39 05 00 01 1b 00 02 62 6f x-9,3..9......bo
+| 2288: 78 2d 39 2c 32 0d 88 55 05 00 01 1b 00 02 62 6f x-9,2..U......bo
+| 2304: 78 2d 39 2c 31 0d 87 71 05 00 01 1b 00 02 62 6f x-9,1..q......bo
+| 2320: 78 2d 39 2c 30 0d 8e 74 05 00 01 1b 00 04 62 6f x-9,0..t......bo
+| 2336: 78 2d 38 2c 39 0d 8e 10 05 00 01 1b 00 02 62 6f x-8,9.........bo
+| 2352: 78 2d 38 2c 38 0d 8d 2c 05 00 01 1b 00 02 62 6f x-8,8..,......bo
+| 2368: 78 2d 38 2c 37 0d 8c 48 05 00 01 1b 00 02 62 6f x-8,7..H......bo
+| 2384: 78 2d 38 2c 36 0d 8b 64 05 00 01 1b 00 02 62 6f x-8,6..d......bo
+| 2400: 78 2d 38 2c 35 0d 8b 00 05 00 01 1b 00 02 62 6f x-8,5.........bo
+| 2416: 78 2d 38 2c 34 0d 8a 1c 05 00 01 1b 00 02 62 6f x-8,4.........bo
+| 2432: 78 2d 38 2c 33 0d 89 38 05 00 01 1b 00 02 62 6f x-8,3..8......bo
+| 2448: 78 2d 38 2c 32 0d 88 54 05 00 01 1b 00 02 62 6f x-8,2..T......bo
+| 2464: 78 2d 38 2c 31 0d 87 70 05 00 01 1b 00 02 62 6f x-8,1..p......bo
+| 2480: 78 2d 38 2c 30 0d 8e 73 05 00 01 1b 00 05 62 6f x-8,0..s......bo
+| 2496: 78 2d 37 2c 39 0d 8e 0f 05 00 01 1b 00 05 62 6f x-7,9.........bo
+| 2512: 78 2d 37 2c 38 0d 8d 2b 05 00 01 1b 00 05 62 6f x-7,8..+......bo
+| 2528: 78 2d 37 2c 37 0d 8c 47 05 00 01 1b 00 05 62 6f x-7,7..G......bo
+| 2544: 78 2d 37 2c 36 0d 8b 63 05 00 01 1b 00 05 62 6f x-7,6..c......bo
+| 2560: 78 2d 37 2c 35 0d 8a 7f 05 00 01 1b 00 05 62 6f x-7,5.........bo
+| 2576: 78 2d 37 2c 34 0d 8a 1b 05 00 01 1b 00 05 62 6f x-7,4.........bo
+| 2592: 78 2d 37 2c 33 0d 89 37 05 00 01 1b 00 05 62 6f x-7,3..7......bo
+| 2608: 78 2d 37 2c 32 0d 88 53 05 00 01 1b 00 05 62 6f x-7,2..S......bo
+| 2624: 78 2d 37 2c 31 0d 87 6f 05 00 01 1b 00 05 62 6f x-7,1..o......bo
+| 2640: 78 2d 37 2c 30 0d 8e 72 05 00 01 1b 00 04 62 6f x-7,0..r......bo
+| 2656: 78 2d 36 2c 39 0d 8e 0e 05 00 01 1b 00 05 62 6f x-6,9.........bo
+| 2672: 78 2d 36 2c 38 0d 8d 2a 05 00 01 1b 00 05 62 6f x-6,8..*......bo
+| 2688: 78 2d 36 2c 37 0d 8c 46 05 00 01 1b 00 05 62 6f x-6,7..F......bo
+| 2704: 78 2d 36 2c 36 0d 8b 62 05 00 01 1b 00 05 62 6f x-6,6..b......bo
+| 2720: 78 2d 36 2c 35 0d 8a 7e 05 00 01 1b 00 05 62 6f x-6,5..~......bo
+| 2736: 78 2d 36 2c 34 0d 8a 1a 05 00 01 1b 00 05 62 6f x-6,4.........bo
+| 2752: 78 2d 36 2c 33 0d 89 36 05 00 01 1b 00 05 62 6f x-6,3..6......bo
+| 2768: 78 2d 36 2c 32 0d 88 52 05 00 01 1b 00 05 62 6f x-6,2..R......bo
+| 2784: 78 2d 36 2c 31 0d 87 6e 05 00 01 1b 00 05 62 6f x-6,1..n......bo
+| 2800: 78 2d 36 2c 30 0d 8e 71 05 00 01 1b 00 04 62 6f x-6,0..q......bo
+| 2816: 78 2d 35 2c 39 0d 8e 0d 05 00 01 1b 00 05 62 6f x-5,9.........bo
+| 2832: 78 2d 35 2c 38 0d 8d 29 05 00 01 1b 00 05 62 6f x-5,8..)......bo
+| 2848: 78 2d 35 2c 37 0d 8c 45 05 00 01 1b 00 05 62 6f x-5,7..E......bo
+| 2864: 78 2d 35 2c 36 0d 8b 61 05 00 01 1b 00 05 62 6f x-5,6..a......bo
+| 2880: 78 2d 35 2c 35 0d 8a 7d 05 00 01 1b 00 05 62 6f x-5,5.........bo
+| 2896: 78 2d 35 2c 34 0d 8a 19 05 00 01 1b 00 05 62 6f x-5,4.........bo
+| 2912: 78 2d 35 2c 33 0d 89 35 05 00 01 1b 00 05 62 6f x-5,3..5......bo
+| 2928: 78 2d 35 2c 32 0d 88 51 05 00 01 1b 00 05 62 6f x-5,2..Q......bo
+| 2944: 78 2d 35 2c 31 0d 87 6d 05 00 01 1b 00 05 62 6f x-5,1..m......bo
+| 2960: 78 2d 35 2c 30 0d 8e 70 05 00 01 1b 00 04 62 6f x-5,0..p......bo
+| 2976: 78 2d 34 2c 39 0d 8e 0c 05 00 01 1b 00 04 62 6f x-4,9.........bo
+| 2992: 78 2d 34 2c 38 0d 8d 28 05 00 01 1b 00 04 62 6f x-4,8..(......bo
+| 3008: 78 2d 34 2c 37 0d 8c 44 05 00 01 1b 00 04 62 6f x-4,7..D......bo
+| 3024: 78 2d 34 2c 36 0d 8b 60 05 00 01 1b 00 02 62 6f x-4,6..`......bo
+| 3040: 78 2d 34 2c 35 0d 8a 7c 05 00 01 1b 00 02 62 6f x-4,5..|......bo
+| 3056: 78 2d 34 2c 34 0d 8a 18 05 00 01 1b 00 02 62 6f x-4,4.........bo
+| 3072: 78 2d 34 2c 33 0d 89 34 05 00 01 1b 00 02 62 6f x-4,3..4......bo
+| 3088: 78 2d 34 2c 32 0d 88 50 05 00 01 1b 00 02 62 6f x-4,2..P......bo
+| 3104: 78 2d 34 2c 31 0d 87 6c 05 00 01 1b 00 02 62 6f x-4,1..l......bo
+| 3120: 78 2d 34 2c 30 0d 8e 6f 05 00 01 1b 00 04 62 6f x-4,0..o......bo
+| 3136: 78 2d 33 2c 39 0d 8e 0b 05 00 01 1b 00 04 62 6f x-3,9.........bo
+| 3152: 78 2d 33 2c 38 0d 8d 27 05 00 01 1b 00 04 62 6f x-3,8..'......bo
+| 3168: 78 2d 33 2c 37 0d 87 68 05 00 01 1b 00 03 62 6f x-3,7..h......bo
+| 3184: 78 2d 30 2c 30 06 90 d9 80 80 81 84 4c 05 00 01 x-0,0.......L...
+| 3200: 00 00 03 0d 88 4c 05 00 01 1b 00 02 62 6f 78 2d .....L......box-
+| 3216: 30 2c 31 0d 88 4d 05 00 01 1b 00 02 62 6f 78 2d 0,1..M......box-
+| 3232: 31 2c 31 0d 88 4e 05 00 01 1b 00 02 62 6f 78 2d 1,1..N......box-
+| 3248: 32 2c 31 17 01 05 00 01 2f 00 02 6c 6f 77 65 72 2,1...../..lower
+| 3264: 2d 6c 65 66 74 20 63 6f 72 6e 65 72 0d 0d 26 00 -left corner..&.
+| 3280: 09 00 01 00 00 04 0d 8c 43 05 00 01 1b 00 04 62 ........C......b
+| 3296: 6f 78 2d 33 2c 36 0d 8b 5f 05 00 01 1b 00 02 62 ox-3,6.._......b
+| 3312: 6f 78 2d 33 2c 35 0d 8a 7b 05 00 01 1b 00 02 62 ox-3,5.........b
+| 3328: 6f 78 2d 33 2c 34 0d 8a 17 05 00 01 1b 00 02 62 ox-3,4.........b
+| 3344: 6f 78 2d 33 2c 33 0d 89 33 05 00 01 1b 00 02 62 ox-3,3..3......b
+| 3360: 6f 78 2d 33 2c 32 0d bc 00 06 00 09 0d 87 6b 05 ox-3,2........k.
+| 3376: 00 01 1b 00 03 62 6f 78 2d 33 2c 30 0d 8e 6e 05 .....box-3,0..n.
+| 3392: 00 01 1b 00 04 62 6f 78 2d 32 2c 39 0d 8e 0a 05 .....box-2,9....
+| 3408: 00 01 1b 00 04 62 6f 78 2d 32 2c 38 0d 8d 26 05 .....box-2,8..&.
+| 3424: 00 01 1b 00 04 62 6f 78 2d 32 2c 37 0d 8c 42 05 .....box-2,7..B.
+| 3440: 00 01 1b 00 04 62 6f 78 2d 32 2c 36 0d 8b 5e 05 .....box-2,6..^.
+| 3456: 00 01 1b 00 02 62 6f 78 2d 32 2c 35 0d 8a 7a 05 .....box-2,5..z.
+| 3472: 00 01 1b 00 02 62 6f 78 2d 32 2c 34 0d 8a 16 05 .....box-2,4....
+| 3488: 00 01 1b 00 02 62 6f 78 2d 32 2c 33 0d 89 32 05 .....box-2,3..2.
+| 3504: 00 01 1b 00 02 62 6f 78 2d 32 2c 32 0e 52 00 06 .....box-2,2.R..
+| 3520: 00 09 0d 87 6a 05 00 01 1b 00 03 62 6f 78 2d 32 ....j......box-2
+| 3536: 2c 30 0d 8e 6d 05 00 01 1b 00 04 62 6f 78 2d 31 ,0..m......box-1
+| 3552: 2c 39 0d 8e 09 05 00 01 1b 00 04 62 6f 78 2d 31 ,9.........box-1
+| 3568: 2c 38 0d 8d 25 05 00 01 1b 00 04 62 6f 78 2d 31 ,8..%......box-1
+| 3584: 2c 37 0d 8c 41 05 00 01 1b 00 04 62 6f 78 2d 31 ,7..A......box-1
+| 3600: 2c 36 0d 8b 5d 05 00 01 1b 00 02 62 6f 78 2d 31 ,6..]......box-1
+| 3616: 2c 35 0d 8a 79 05 00 01 1b 00 02 62 6f 78 2d 31 ,5..y......box-1
+| 3632: 2c 34 0d 8a 15 05 00 01 1b 00 02 62 6f 78 2d 31 ,4.........box-1
+| 3648: 2c 33 0d 89 31 05 00 01 1b 00 02 62 6f 78 2d 31 ,3..1......box-1
+| 3664: 2c 32 0e e8 00 06 00 09 0d 87 69 05 00 01 1b 00 ,2........i.....
+| 3680: 03 62 6f 78 2d 31 2c 30 0d 8e 6c 05 00 01 1b 00 .box-1,0..l.....
+| 3696: 04 62 6f 78 2d 30 2c 39 0d 8e 08 05 00 01 1b 00 .box-0,9........
+| 3712: 04 62 6f 78 2d 30 2c 38 0d 8d 24 05 00 01 1b 00 .box-0,8..$.....
+| 3728: 04 62 6f 78 2d 30 2c 37 0d 8c 40 05 00 01 1b 00 .box-0,7..@.....
+| 3744: 04 62 6f 78 2d 30 2c 36 0d 8b 5c 05 00 01 1b 00 .box-0,6........
+| 3760: 02 62 6f 78 2d 30 2c 35 0d 8a 78 05 00 01 1b 00 .box-0,5..x.....
+| 3776: 02 62 6f 78 2d 30 2c 34 0d 8a 14 05 00 01 1b 00 .box-0,4........
+| 3792: 02 62 6f 78 2d 30 2c 33 0d 89 30 05 00 01 1b 00 .box-0,3..0.....
+| 3808: 02 62 6f 78 2d 30 2c 32 00 00 00 0f 00 09 1b 00 .box-0,2........
+| 3824: 62 6f 78 2d 30 2c 30 0d 0e 05 00 09 1d 00 74 6f box-0,0.......to
+| 3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74 p half.....#.bot
+| 3856: 74 6f 6d 20 68 61 6c 66 0f 0c 02 05 09 01 00 72 tom half.......r
+| 3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00 ight half.......
+| 3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00 left half.....+.
+| 3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d the whole thing.
+| 3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08 ......top edge..
+| 3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65 ...#.bottom edge
+| 3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 .....!.right edg
+| 3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 e.......left edg
+| 3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04 e.......center..
+| 4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 ...1.upper-right
+| 4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f corner.....1.lo
+| 4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72 wer-right corner
+| 4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 ...../.upper-lef
+| 4064: 74 20 63 6f 72 6e 65 72 06 00 05 00 01 00 00 03 t corner........
+| 4080: 0d 88 4f 05 00 01 1b 00 02 62 6f 78 2d 33 2c 31 ..O......box-3,1
+| page 3 offset 8192
+| 0: 05 00 00 00 01 0f fb 00 00 00 00 06 0f fb 00 00 ................
+| 384: 00 00 00 00 00 00 00 89 50 03 04 00 93 24 00 00 ........P....$..
+| 400: 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 688: 00 00 00 00 42 c8 00 00 42 4c 00 00 42 00 00 00 ....B...BL..B...
+| 720: 03 eb 40 40 00 00 40 80 00 00 00 00 00 00 3f 80 ..@@..@.......?.
+| 736: 00 00 00 00 00 00 00 00 03 ea 40 00 00 00 40 40 ..........@...@@
+| 752: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00 ......?.........
+| 768: 03 e9 3f 80 00 00 40 00 00 00 00 00 00 00 3f 80 ..?...@.......?.
+| 784: 00 00 00 00 00 00 00 00 03 e8 00 00 00 00 3f 80 ..............?.
+| 800: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00 ......?.........
+| 1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93 ...........P....
+| 1632: 24 00 00 00 33 00 00 00 00 00 00 00 01 00 00 00 $...3...........
+| 1648: 00 41 20 00 00 00 00 00 00 41 0e 00 00 00 00 00 .A ......A......
+| 1664: 00 00 00 04 4f 40 40 00 00 40 80 00 00 3f 80 00 ....O@@..@...?..
+| 1680: 00 40 00 00 00 00 00 00 00 00 00 04 4e 40 00 00 .@..........N@..
+| 1696: 00 40 40 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@@..?...@......
+| 1712: 00 00 00 04 4d 3f 80 00 00 40 00 00 00 3f 80 00 ....M?...@...?..
+| 1728: 00 40 00 00 00 00 00 00 00 00 00 04 4c 00 00 00 .@..........L...
+| 1744: 00 3f 80 00 00 3f 80 00 00 40 00 00 00 00 00 00 .?...?...@......
+| 1760: 00 00 00 04 b3 40 40 00 00 40 80 00 00 40 00 00 .....@@..@...@..
+| 1776: 00 40 40 00 00 00 00 00 00 00 00 04 b2 40 00 00 .@@..........@..
+| 1792: 00 40 40 00 00 40 00 00 00 40 40 00 00 00 00 00 .@@..@...@@.....
+| 1808: 00 00 00 04 b1 3f 80 00 00 40 00 00 00 40 00 00 .....?...@...@..
+| 1824: 00 40 40 00 00 00 00 00 00 00 00 04 b0 00 00 00 .@@.............
+| 1840: 00 3f 80 00 00 40 00 00 00 40 40 00 00 00 00 00 .?...@...@@.....
+| 1856: 00 00 00 05 17 40 40 00 00 40 80 00 00 40 40 00 .....@@..@...@@.
+| 1872: 00 40 80 00 00 00 00 00 00 00 00 05 16 40 00 00 .@...........@..
+| 1888: 00 40 40 00 00 40 40 00 00 40 80 00 00 00 00 00 .@@..@@..@......
+| 1904: 00 00 00 05 15 3f 80 00 00 40 00 00 00 40 40 00 .....?...@...@@.
+| 1920: 00 40 80 00 00 00 00 00 00 00 00 05 14 00 00 00 .@..............
+| 1936: 00 3f 80 00 00 40 40 00 00 40 80 00 00 00 00 00 .?...@@..@......
+| 1952: 00 00 00 05 7b 40 40 00 00 40 80 00 00 40 80 00 .....@@..@...@..
+| 1968: 00 40 a0 00 00 00 00 00 00 00 00 05 7a 40 00 00 .@..........z@..
+| 1984: 00 40 40 00 00 40 80 00 00 40 a0 00 00 00 00 00 .@@..@...@......
+| 2000: 00 00 00 05 79 3f 80 00 00 40 00 00 00 40 80 00 ....y?...@...@..
+| 2016: 00 40 a0 00 00 00 00 00 00 00 00 05 78 00 00 00 .@..........x...
+| 2032: 00 3f 80 00 00 40 80 00 00 40 a0 00 00 00 00 00 .?...@...@......
+| 2048: 00 00 00 05 df 40 40 00 00 40 80 00 00 40 a0 00 .....@@..@...@..
+| 2064: 00 40 c0 00 00 00 00 00 00 00 00 05 de 40 00 00 .@...........@..
+| 2080: 00 40 40 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@@..@...@......
+| 2096: 00 00 00 05 dd 3f 80 00 00 40 00 00 00 40 a0 00 .....?...@...@..
+| 2112: 00 40 c0 00 00 00 00 00 00 00 00 05 dc 00 00 00 .@..............
+| 2128: 00 3f 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .?...@...@......
+| 2144: 00 00 00 06 43 40 40 00 00 40 80 00 00 40 c0 00 ....C@@..@...@..
+| 2160: 00 40 e0 00 00 00 00 00 00 00 00 06 42 40 00 00 .@..........B@..
+| 2176: 00 40 40 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .@@..@...@......
+| 2192: 00 00 00 06 41 3f 80 00 00 40 00 00 00 40 c0 00 ....A?...@...@..
+| 2208: 00 40 e0 00 00 00 00 00 00 00 00 06 40 00 00 00 .@..........@...
+| 2224: 00 3f 80 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .?...@...@......
+| 2240: 00 00 00 06 a7 40 40 00 00 40 80 00 00 40 e0 00 .....@@..@...@..
+| 2256: 00 41 00 00 00 00 00 00 00 00 00 06 a6 40 00 00 .A...........@..
+| 2272: 00 40 40 00 00 40 e0 00 00 41 00 00 00 00 00 00 .@@..@...A......
+| 2288: 00 00 00 06 a5 3f 80 00 00 40 00 00 00 40 e0 00 .....?...@...@..
+| 2304: 00 41 00 00 00 00 00 00 00 00 00 06 a4 00 00 00 .A..............
+| 2320: 00 3f 80 00 00 40 e0 00 00 41 00 00 00 00 00 00 .?...@...A......
+| 2336: 00 00 00 07 0a 40 00 00 00 40 40 00 00 41 00 00 .....@...@@..A..
+| 2352: 00 41 10 00 00 00 00 00 00 00 00 07 09 3f 80 00 .A...........?..
+| 2368: 00 40 00 00 00 41 00 00 00 41 10 00 00 00 00 00 .@...A...A......
+| 2384: 00 00 00 07 08 00 00 00 00 3f 80 00 00 41 00 00 .........?...A..
+| 2400: 00 41 10 00 00 00 00 00 00 00 00 07 6e 40 00 00 .A..........n@..
+| 2416: 00 40 40 00 00 41 10 00 00 41 20 00 00 00 00 00 .@@..A...A .....
+| 2432: 00 00 00 07 6d 3f 80 00 00 40 00 00 00 41 10 00 ....m?...@...A..
+| 2448: 00 41 20 00 00 00 00 00 00 00 00 07 6c 00 00 00 .A .........l...
+| 2464: 00 3f 80 00 00 41 10 00 00 41 20 00 00 00 00 00 .?...A...A .....
+| 2480: 00 00 00 07 0b 40 40 00 00 40 80 00 00 41 00 00 .....@@..@...A..
+| 2496: 00 41 10 00 00 00 00 00 00 00 00 07 6f 40 40 00 .A..........o@@.
+| 2512: 00 40 80 00 00 41 10 00 00 41 20 00 00 00 00 00 .@...A...A .....
+| 2528: 00 00 00 03 ec 40 80 00 00 40 a0 00 00 00 00 00 .....@...@......
+| 2544: 00 3f 80 00 00 00 00 00 00 00 00 04 50 40 80 00 .?..........P@..
+| 2560: 00 40 a0 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
+| 2576: 00 00 00 04 b4 40 80 00 00 40 a0 00 00 40 00 00 .....@...@...@..
+| 2592: 00 40 40 00 00 00 00 00 00 00 00 05 18 40 80 00 .@@..........@..
+| 2608: 00 40 a0 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
+| 2624: 00 00 00 05 7c 40 80 00 00 40 a0 00 00 40 80 00 ....|@...@...@..
+| 2640: 00 40 a0 00 00 00 00 00 00 00 00 05 e0 40 80 00 .@...........@..
+| 2656: 00 40 a0 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
+| 2672: 00 00 00 06 44 40 80 00 00 40 a0 00 00 40 c0 00 ....D@...@...@..
+| 2688: 00 40 e0 00 00 00 00 00 00 00 00 06 a8 40 80 00 .@...........@..
+| 2704: 00 40 a0 00 00 40 e0 00 00 41 00 00 00 00 00 00 .@...@...A......
+| 2720: 00 00 00 07 0c 40 80 00 00 40 a0 00 00 41 00 00 .....@...@...A..
+| 2736: 00 41 10 00 00 00 00 00 00 00 00 07 70 40 80 00 .A..........p@..
+| 2752: 00 40 a0 00 00 41 10 00 00 41 20 00 00 00 00 00 .@...A...A .....
+| 2768: 00 00 00 03 ed 40 a0 00 00 40 c0 00 00 00 00 00 .....@...@......
+| 2784: 00 3f 80 00 00 00 00 00 00 00 00 04 51 40 a0 00 .?..........Q@..
+| 2800: 00 40 c0 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
+| 2816: 00 00 00 04 b5 40 a0 00 00 40 c0 00 00 40 00 00 .....@...@...@..
+| 2832: 00 40 40 00 00 00 00 00 00 00 00 05 19 40 a0 00 .@@..........@..
+| 2848: 00 40 c0 00 00 40 40 00 00 40 80 00 00 89 50 01 .@...@@..@....P.
+| 2864: 04 00 93 24 00 01 00 02 00 00 00 00 00 00 00 03 ...$............
+| 2880: 00 00 00 00 40 80 00 00 00 00 00 00 3f 80 00 00 ....@.......?...
+| 2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 20 00 00 ............A ..
+| 2912: 00 00 00 00 41 20 00 00 00 00 00 00 00 00 00 00 ....A ..........
+| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05 03 ................
+| page 4 offset 12288
+| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
+| page 5 offset 16384
+| 0: 0d 00 00 00 03 01 87 00 0b 2d 06 5a 01 87 00 00 .........-.Z....
+| 384: 00 00 00 00 00 00 00 89 50 03 04 00 93 24 00 00 ........P....$..
+| 400: 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 688: 00 00 00 00 42 c8 00 00 42 4c 00 00 42 00 00 00 ....B...BL..B...
+| 720: 03 eb 40 40 00 00 40 80 00 00 00 00 00 00 3f 80 ..@@..@.......?.
+| 736: 00 00 00 00 00 00 00 00 03 ea 40 00 00 00 40 40 ..........@...@@
+| 752: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00 ......?.........
+| 768: 03 e9 3f 80 00 00 40 00 00 00 00 00 00 00 3f 80 ..?...@.......?.
+| 784: 00 00 00 00 00 00 00 00 03 e8 00 00 00 00 3f 80 ..............?.
+| 800: 00 00 00 00 00 00 3f 80 00 00 00 00 00 00 00 00 ......?.........
+| 1616: 00 00 00 00 00 00 00 00 00 00 89 50 02 04 00 93 ...........P....
+| 1632: 24 00 00 00 2d 00 00 00 00 00 00 04 4c 00 00 00 $...-.......L...
+| 1648: 00 3f 80 00 00 3f 80 00 00 40 00 00 00 00 00 00 .?...?...@......
+| 1664: 00 00 00 04 b0 00 00 00 00 3f 80 00 00 40 00 00 .........?...@..
+| 1680: 00 40 40 00 00 00 00 00 00 00 00 05 14 00 00 00 .@@.............
+| 1696: 00 3f 80 00 00 40 40 00 00 40 80 00 00 00 00 00 .?...@@..@......
+| 1712: 00 00 00 05 78 00 00 00 00 3f 80 00 00 40 80 00 ....x....?...@..
+| 1728: 00 40 a0 00 00 00 00 00 00 00 00 05 dc 00 00 00 .@..............
+| 1744: 00 3f 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .?...@...@......
+| 1760: 00 00 00 00 01 00 00 00 00 41 20 00 00 00 00 00 .........A .....
+| 1776: 00 41 0e 00 00 00 00 00 00 00 00 04 4d 3f 80 00 .A..........M?..
+| 1792: 00 40 00 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
+| 1808: 00 00 00 04 b1 3f 80 00 00 40 00 00 00 40 00 00 .....?...@...@..
+| 1824: 00 40 40 00 00 00 00 00 00 00 00 05 15 3f 80 00 .@@..........?..
+| 1840: 00 40 00 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
+| 1856: 00 00 00 05 79 3f 80 00 00 40 00 00 00 40 80 00 ....y?...@...@..
+| 1872: 00 40 a0 00 00 00 00 00 00 00 00 05 dd 3f 80 00 .@...........?..
+| 1888: 00 40 00 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
+| 1904: 00 00 00 04 4e 40 00 00 00 40 40 00 00 3f 80 00 ....N@...@@..?..
+| 1920: 00 40 00 00 00 00 00 00 00 00 00 04 b2 40 00 00 .@...........@..
+| 1936: 00 40 40 00 00 40 00 00 00 40 40 00 00 00 00 00 .@@..@...@@.....
+| 1952: 00 00 00 05 16 40 00 00 00 40 40 00 00 40 40 00 .....@...@@..@@.
+| 1968: 00 40 80 00 00 00 00 00 00 00 00 05 7a 40 00 00 .@..........z@..
+| 1984: 00 40 40 00 00 40 80 00 00 40 a0 00 00 00 00 00 .@@..@...@......
+| 2000: 00 00 00 05 de 40 00 00 00 40 40 00 00 40 a0 00 .....@...@@..@..
+| 2016: 00 40 c0 00 00 00 00 00 00 00 00 04 4f 40 40 00 .@..........O@@.
+| 2032: 00 40 80 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
+| 2048: 00 00 00 04 b3 40 40 00 00 40 80 00 00 40 00 00 .....@@..@...@..
+| 2064: 00 40 40 00 00 00 00 00 00 00 00 05 17 40 40 00 .@@..........@@.
+| 2080: 00 40 80 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
+| 2096: 00 00 00 05 7b 40 40 00 00 40 80 00 00 40 80 00 .....@@..@...@..
+| 2112: 00 40 a0 00 00 00 00 00 00 00 00 05 df 40 40 00 .@...........@@.
+| 2128: 00 40 80 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
+| 2144: 00 00 00 03 ec 40 80 00 00 40 a0 00 00 00 00 00 .....@...@......
+| 2160: 00 3f 80 00 00 00 00 00 00 00 00 04 50 40 80 00 .?..........P@..
+| 2176: 00 40 a0 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
+| 2192: 00 00 00 04 b4 40 80 00 00 40 a0 00 00 40 00 00 .....@...@...@..
+| 2208: 00 40 40 00 00 00 00 00 00 00 00 05 18 40 80 00 .@@..........@..
+| 2224: 00 40 a0 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
+| 2240: 00 00 00 05 7c 40 80 00 00 40 a0 00 00 40 80 00 ....|@...@...@..
+| 2256: 00 40 a0 00 00 00 00 00 00 00 00 05 e0 40 80 00 .@...........@..
+| 2272: 00 40 a0 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
+| 2288: 00 00 00 03 f0 41 00 00 00 41 10 00 00 00 00 00 .....A...A......
+| 2304: 00 3f 80 00 00 00 00 00 00 00 00 04 54 41 00 00 .?..........TA..
+| 2320: 00 41 10 00 00 3f 80 00 00 40 00 00 00 00 00 00 .A...?...@......
+| 2336: 00 00 00 04 b8 41 00 00 00 41 10 00 00 40 00 00 .....A...A...@..
+| 2352: 00 40 40 00 00 00 00 00 00 00 00 05 1c 41 00 00 .@@..........A..
+| 2368: 00 41 10 00 00 40 40 00 00 40 80 00 00 00 00 00 .A...@@..@......
+| 2384: 00 00 00 05 80 41 00 00 00 41 10 00 00 40 80 00 .....A...A...@..
+| 2400: 00 40 a0 00 00 00 00 00 00 00 00 05 e4 41 00 00 .@...........A..
+| 2416: 00 41 10 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .A...@...@......
+| 2432: 00 00 00 06 48 41 00 00 00 41 10 00 00 40 c0 00 ....HA...A...@..
+| 2448: 00 40 e0 00 00 00 00 00 00 00 00 06 ac 41 00 00 .@...........A..
+| 2464: 00 41 10 00 00 40 e0 00 00 41 00 00 00 00 00 00 .A...@...A......
+| 2480: 00 00 00 07 10 41 00 00 00 41 10 00 00 41 00 00 .....A...A...A..
+| 2496: 00 41 10 00 00 00 00 00 00 00 00 03 f1 41 10 00 .A...........A..
+| 2512: 00 41 20 00 00 00 00 00 00 3f 80 00 00 00 00 00 .A ......?......
+| 2528: 00 00 00 04 55 41 10 00 00 41 20 00 00 3f 80 00 ....UA...A ..?..
+| 2544: 00 40 00 00 00 00 00 00 00 00 00 04 b9 41 10 00 .@...........A..
+| 2560: 00 41 20 00 00 40 00 00 00 40 40 00 00 00 00 00 .A ..@...@@.....
+| 2576: 00 00 00 05 1d 41 10 00 00 41 20 00 00 40 40 00 .....A...A ..@@.
+| 2592: 00 40 80 00 00 00 00 00 00 00 00 05 81 41 10 00 .@...........A..
+| 2608: 00 41 20 00 00 40 80 00 00 40 a0 00 00 00 00 00 .A ..@...@......
+| 2624: 00 00 00 05 e5 41 10 00 00 41 20 00 00 40 a0 00 .....A...A ..@..
+| 2640: 00 40 c0 00 00 00 00 00 00 00 00 06 49 41 10 00 .@..........IA..
+| 2656: 00 41 20 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .A ..@...@......
+| 2672: 00 00 00 06 ad 41 10 00 00 41 20 00 00 40 e0 00 .....A...A ..@..
+| 2688: 00 41 00 00 00 00 00 00 00 00 00 07 11 41 10 00 .A...........A..
+| 2704: 00 41 20 00 00 41 00 00 00 41 10 00 00 00 00 00 .A ..A...A......
+| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
+| 2864: 04 00 93 24 00 01 00 04 00 00 00 00 00 00 00 03 ...$............
+| 2880: 00 00 00 00 40 80 00 00 00 00 00 00 3f 80 00 00 ....@.......?...
+| 2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 20 00 00 ............A ..
+| 2912: 00 00 00 00 41 10 00 00 00 00 00 00 00 00 00 04 ....A...........
+| 2928: 00 00 00 00 41 20 00 00 40 c0 00 00 41 20 00 00 ....A ..@...A ..
+| 2944: 00 00 00 00 00 00 00 05 40 a0 00 00 41 00 00 00 ........@...A...
+| 2960: 00 00 00 00 41 20 00 00 00 00 00 00 00 00 00 00 ....A ..........
+| page 6 offset 20480
+| 0: 0d 00 00 00 02 06 5a 00 0b 2d 06 5a 00 00 00 00 ......Z..-.Z....
+| 1616: 00 00 00 00 00 00 00 00 00 00 89 50 05 04 00 93 ...........P....
+| 1632: 24 00 00 00 1c 00 00 00 00 00 00 03 ed 40 a0 00 $............@..
+| 1648: 00 40 c0 00 00 00 00 00 00 3f 80 00 00 00 00 00 .@.......?......
+| 1664: 00 00 00 04 51 40 a0 00 00 40 c0 00 00 3f 80 00 ....Q@...@...?..
+| 1680: 00 40 00 00 00 00 00 00 00 00 00 04 b5 40 a0 00 .@...........@..
+| 1696: 00 40 c0 00 00 40 00 00 00 40 40 00 00 00 00 00 .@...@...@@.....
+| 1712: 00 00 00 05 19 40 a0 00 00 40 c0 00 00 40 40 00 .....@...@...@@.
+| 1728: 00 40 80 00 00 00 00 00 00 00 00 05 7d 40 a0 00 .@...........@..
+| 1744: 00 40 c0 00 00 40 80 00 00 40 a0 00 00 00 00 00 .@...@...@......
+| 1760: 00 00 00 05 e1 40 a0 00 00 40 c0 00 00 40 a0 00 .....@...@...@..
+| 1776: 00 40 c0 00 00 00 00 00 00 00 00 06 45 40 a0 00 .@..........E@..
+| 1792: 00 40 c0 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .@...@...@......
+| 1808: 00 00 00 06 a9 40 a0 00 00 40 c0 00 00 40 e0 00 .....@...@...@..
+| 1824: 00 41 00 00 00 00 00 00 00 00 00 07 0d 40 a0 00 .A...........@..
+| 1840: 00 40 c0 00 00 41 00 00 00 41 10 00 00 00 00 00 .@...A...A......
+| 1856: 00 00 00 03 ee 40 c0 00 00 40 e0 00 00 00 00 00 .....@...@......
+| 1872: 00 3f 80 00 00 00 00 00 00 00 00 04 52 40 c0 00 .?..........R@..
+| 1888: 00 40 e0 00 00 3f 80 00 00 40 00 00 00 00 00 00 .@...?...@......
+| 1904: 00 00 00 04 b6 40 c0 00 00 40 e0 00 00 40 00 00 .....@...@...@..
+| 1920: 00 40 40 00 00 00 00 00 00 00 00 05 1a 40 c0 00 .@@..........@..
+| 1936: 00 40 e0 00 00 40 40 00 00 40 80 00 00 00 00 00 .@...@@..@......
+| 1952: 00 00 00 05 7e 40 c0 00 00 40 e0 00 00 40 80 00 ....~@...@...@..
+| 1968: 00 40 a0 00 00 00 00 00 00 00 00 05 e2 40 c0 00 .@...........@..
+| 1984: 00 40 e0 00 00 40 a0 00 00 40 c0 00 00 00 00 00 .@...@...@......
+| 2000: 00 00 00 06 46 40 c0 00 00 40 e0 00 00 40 c0 00 ....F@...@...@..
+| 2016: 00 40 e0 00 00 00 00 00 00 00 00 06 aa 40 c0 00 .@...........@..
+| 2032: 00 40 e0 00 00 40 e0 00 00 41 00 00 00 00 00 00 .@...@...A......
+| 2048: 00 00 00 07 0e 40 c0 00 00 40 e0 00 00 41 00 00 .....@...@...A..
+| 2064: 00 41 10 00 00 00 00 00 00 00 00 03 ef 40 e0 00 .A...........@..
+| 2080: 00 41 00 00 00 00 00 00 00 3f 80 00 00 00 00 00 .A.......?......
+| 2096: 00 00 00 04 53 40 e0 00 00 41 00 00 00 3f 80 00 ....S@...A...?..
+| 2112: 00 40 00 00 00 00 00 00 00 00 00 04 b7 40 e0 00 .@...........@..
+| 2128: 00 41 00 00 00 40 00 00 00 40 40 00 00 00 00 00 .A...@...@@.....
+| 2144: 00 00 00 05 1b 40 e0 00 00 41 00 00 00 40 40 00 .....@...A...@@.
+| 2160: 00 40 80 00 00 00 00 00 00 00 00 05 7f 40 e0 00 .@...........@..
+| 2176: 00 41 00 00 00 40 80 00 00 40 a0 00 00 00 00 00 .A...@...@......
+| 2192: 00 00 00 05 e3 40 e0 00 00 41 00 00 00 40 a0 00 .....@...A...@..
+| 2208: 00 40 c0 00 00 00 00 00 00 00 00 06 47 40 e0 00 .@..........G@..
+| 2224: 00 41 00 00 00 40 c0 00 00 40 e0 00 00 00 00 00 .A...@...@......
+| 2240: 00 00 00 06 ab 40 e0 00 00 41 00 00 00 40 e0 00 .....@...A...@..
+| 2256: 00 41 00 00 00 00 00 00 00 00 00 07 0f 40 e0 00 .A...........@..
+| 2272: 00 41 00 00 00 41 00 00 00 41 10 00 00 00 00 00 .A...A...A......
+| 2288: 00 00 00 07 73 40 e0 00 00 41 00 00 00 41 10 00 ....s@...A...A..
+| 2304: 00 41 20 00 00 00 00 00 00 00 00 00 00 00 00 00 .A .............
+| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 04 ..............P.
+| 2864: 04 00 93 24 00 00 00 18 00 00 00 00 00 00 06 43 ...$...........C
+| 2880: 40 40 00 00 40 80 00 00 40 c0 00 00 40 e0 00 00 @@..@...@...@...
+| 2896: 00 00 00 00 00 00 06 42 40 00 00 00 40 40 00 00 .......B@...@@..
+| 2912: 40 c0 00 00 40 e0 00 00 00 00 00 00 00 00 06 41 @...@..........A
+| 2928: 3f 80 00 00 40 00 00 00 40 c0 00 00 40 e0 00 00 ?...@...@...@...
+| 2944: 00 00 00 00 00 00 06 40 00 00 00 00 3f 80 00 00 .......@....?...
+| 2960: 40 c0 00 00 40 e0 00 00 00 00 00 00 00 00 06 44 @...@..........D
+| 2976: 40 80 00 00 40 a0 00 00 40 c0 00 00 40 e0 00 00 @...@...@...@...
+| 2992: 00 00 00 00 00 00 06 a7 40 40 00 00 40 80 00 00 ........@@..@...
+| 3008: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 06 a6 @...A...........
+| 3024: 40 00 00 00 40 40 00 00 40 e0 00 00 41 00 00 00 @...@@..@...A...
+| 3040: 00 00 00 00 00 00 06 a5 3f 80 00 00 40 00 00 00 ........?...@...
+| 3056: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 06 a4 @...A...........
+| 3072: 00 00 00 00 3f 80 00 00 40 e0 00 00 41 00 00 00 ....?...@...A...
+| 3088: 00 00 00 00 00 00 06 a8 40 80 00 00 40 a0 00 00 ........@...@...
+| 3104: 40 e0 00 00 41 00 00 00 00 00 00 00 00 00 07 0a @...A...........
+| 3120: 40 00 00 00 40 40 00 00 41 00 00 00 41 10 00 00 @...@@..A...A...
+| 3136: 00 00 00 00 00 00 07 09 3f 80 00 00 40 00 00 00 ........?...@...
+| 3152: 41 00 00 00 41 10 00 00 00 00 00 00 00 00 07 08 A...A...........
+| 3168: 00 00 00 00 3f 80 00 00 41 00 00 00 41 10 00 00 ....?...A...A...
+| 3184: 00 00 00 00 00 00 07 0b 40 40 00 00 40 80 00 00 ........@@..@...
+| 3200: 41 00 00 00 41 10 00 00 00 00 00 00 00 00 07 0c A...A...........
+| 3216: 40 80 00 00 40 a0 00 00 41 00 00 00 41 10 00 00 @...@...A...A...
+| 3232: 00 00 00 00 00 00 07 6e 40 00 00 00 40 40 00 00 .......n@...@@..
+| 3248: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 6d A...A .........m
+| 3264: 3f 80 00 00 40 00 00 00 41 10 00 00 41 20 00 00 ?...@...A...A ..
+| 3280: 00 00 00 00 00 00 07 6c 00 00 00 00 3f 80 00 00 .......l....?...
+| 3296: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 6f A...A .........o
+| 3312: 40 40 00 00 40 80 00 00 41 10 00 00 41 20 00 00 @@..@...A...A ..
+| 3328: 00 00 00 00 00 00 07 70 40 80 00 00 40 a0 00 00 .......p@...@...
+| 3344: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 71 A...A .........q
+| 3360: 40 a0 00 00 40 c0 00 00 41 10 00 00 41 20 00 00 @...@...A...A ..
+| 3376: 00 00 00 00 00 00 07 72 40 c0 00 00 40 e0 00 00 .......r@...@...
+| 3392: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 07 74 A...A .........t
+| 3408: 41 00 00 00 41 10 00 00 41 10 00 00 41 20 00 00 A...A...A...A ..
+| 3424: 00 00 00 00 00 00 07 75 41 10 00 00 41 20 00 00 .......uA...A ..
+| 3440: 41 10 00 00 41 20 00 00 00 00 00 00 00 00 00 00 A...A ..........
+| end c1b.db
+ }]
+ catchsql {
+ SELECT rtreecheck('t1');
+ }
+} {1 {SQL logic error}}
+
+do_test rtreefuzz001-200 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 16384 pagesize 4096 filename c3.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04 .....@ ........
+| 32: 00 00 00 00 01 00 00 00 00 00 00 04 00 00 00 04 ................
+| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
+| 96: 00 00 00 00 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f ...............O
+| 112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17 ............^...
+| 3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72 .....tablet1_par
+| 3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45 entt1_parent.CRE
+| 3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61 ATE TABLE .t1_pa
+| 3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 rent.(nodeno INT
+| 3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
+| 3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17 ,parentnode)Q...
+| 3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65 ....tablet1_node
+| 3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54 t1_node.CREATE T
+| 3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e ABLE .t1_node.(n
+| 3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52 odeno INTEGER PR
+| 3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c IMARY KEY,data).
+| 3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f ........tablet1_
+| 3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52 rowidt1_rowid.CR
+| 3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72 EATE TABLE .t1_r
+| 3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
+| 3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
+| 4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07 nodeno,a0,a1)Q..
+| 4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43 ......tablet1t1C
+| 4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
+| 4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 BLE t1 USING rtr
+| 4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79 ee(id,x0,x1,y0,y
+| 4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29 1,+label,+other)
+| page 2 offset 4096
+| 0: 0d 00 00 00 0e 0e f7 00 0f e8 0f d0 0f b7 0f 9e ................
+| 16: 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29 0f 18 .....p.^.O.9.)..
+| 32: 0f 06 0e f7 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f ..............to
+| 3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74 p half.....#.bot
+| 3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72 tom half.....!.r
+| 3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00 ight half.......
+| 3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00 left half.....+.
+| 3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d the whole thing.
+| 3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08 ......top edge..
+| 3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65 ...#.bottom edge
+| 3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 .....!.right edg
+| 3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 e.......left edg
+| 3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04 e.......center..
+| 4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 ...1.upper-right
+| 4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f corner.....1.lo
+| 4032: 77 65 72 2d 72 69 67 68 74 27 60 f6 32 6e 65 72 wer-right'`.2ner
+| 4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 ...../.upper-lef
+| 4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c t corner...../.l
+| 4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72 ower-left corner
+| page 3 offset 8192
+| 0: 0d 00 00 00 02 0b 2d 00 0b 2d 00 00 00 00 00 00 ......-..-......
+| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
+| 2864: 04 00 93 24 00 00 00 0e 00 00 00 00 00 00 00 01 ...$............
+| 2880: 00 00 00 00 41 20 00 00 00 00 00 00 41 20 01 00 ....A ......A ..
+| 2896: 00 00 00 00 00 00 00 02 00 00 00 00 41 00 00 04 ............A...
+| 2912: 2b 40 00 0c 42 c8 00 00 00 00 00 00 00 00 00 03 +@..B...........
+| 2928: 42 b4 00 00 42 c8 00 00 00 00 00 00 41 20 00 00 B...B.......A ..
+| 2944: 00 00 00 00 00 00 00 04 42 b4 00 00 42 c8 00 00 ........B...B...
+| 2960: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 05 B...B...........
+| 2976: 42 20 00 00 42 70 00 00 42 20 00 00 42 70 00 00 B ..Bp..B ..Bp..
+| 2992: 00 00 00 00 00 00 00 60 00 00 00 04 0a 00 00 00 .......`........
+| 3008: 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 07 42 ...B...........B
+| 3024: be 00 00 42 c8 00 00 00 00 00 00 42 c8 00 00 00 ...B.......B....
+| 3040: 00 00 00 00 00 00 08 00 00 00 00 42 c8 00 00 00 ...........B....
+| 3056: 00 00 00 40 a0 00 00 00 00 00 00 00 00 00 09 00 ...@............
+| 3072: 00 00 00 42 c8 00 00 42 be 00 00 42 c8 00 00 00 ...B...B...B....
+| 3088: 00 00 00 00 00 00 0a 00 00 00 00 42 c8 00 00 00 ...........B....
+| 3104: 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 0b 00 ...B............
+| 3120: 00 00 00 42 48 00 00 00 00 00 04 2c 80 00 00 00 ...BH......,....
+| 3136: 00 00 00 00 00 00 c4 24 c0 00 04 2c 80 00 00 00 .......$...,....
+| 3152: 00 00 04 2c 80 00 00 00 00 00 00 00 00 00 d0 00 ...,............
+| 3168: 00 00 04 2c 80 00 00 00 00 00 04 24 80 00 00 00 ...,.......$....
+| 3184: 00 00 00 00 00 00 e0 00 00 00 04 2c 80 00 04 24 ...........,...$
+| 3200: c0 00 04 2c 00 00 00 00 00 00 00 00 00 00 00 00 ...,............
+| page 4 offset 12288
+| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
+| end c3.db
+ }]
+ catchsql {
+ WITH RECURSIVE
+ c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<99),
+ c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<99)
+ INSERT INTO t1(id, x0,x1,y0,y1,label)
+ SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
+ }
+} {1 {database disk image is malformed}}
+do_test rtreefuzz001-210 {
+ catchsql {
+ SELECT rtreecheck('t1');
+ }
+} {/1 .*corrupt.*/}
+
+do_test rtreefuzz001-300 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 16384 pagesize 4096 filename c4.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 04 ................
+| 96: 00 00 00 00 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f ...............O
+| 112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17 ............^...
+| 3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72 .....tablet1_par
+| 3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45 entt1_parent.CRE
+| 3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61 ATE TABLE .t1_pa
+| 3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 rent.(nodeno INT
+| 3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
+| 3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17 ,parentnode)Q...
+| 3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65 ....tablet1_node
+| 3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54 t1_node.CREATE T
+| 3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e ABLE .t1_node.(n
+| 3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52 odeno INTEGER PR
+| 3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c IMARY KEY,data).
+| 3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f ........tablet1_
+| 3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52 rowidt1_rowid.CR
+| 3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72 EATE TABLE .t1_r
+| 3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
+| 3984: 47 45 72 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GEr PRIMARY KEY,
+| 4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07 nodeno,a0,a1)Q..
+| 4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43 ......tablet1t1C
+| 4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
+| 4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 BLE t1 USING rtr
+| 4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79 ee(id,x0,x1,y0,y
+| 4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29 1,+label,+other)
+| page 2 offset 4096
+| 0: 0d 00 00 00 0e 0e f7 00 0f e8 0f 00 fb 70 f9 e0 .............p..
+| 16: f9 10 f8 10 f7 00 f5 e0 f4 f0 f3 90 f2 90 f1 80 ................
+| 32: f0 60 ef 00 00 00 00 00 00 00 00 00 00 00 00 00 .`..............
+| 3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f ..............to
+| 3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74 p half.....#.bot
+| 3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72 tom half.....!.r
+| 3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00 ight half.......
+| 3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00 left half.....+.
+| 3904: 00 03 98 20 49 98 2f 6c 62 05 74 68 69 6e 67 0d ... I./lb.thing.
+| 3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08 ......top edge..
+| 3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65 ...#.bottom edge
+| 3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 .....!.right edg
+| 3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 e.......left edg
+| 3984: 65 0b 05 05 00 09 19 00 63 65 6e 74 65 72 17 04 e.......center..
+| 4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 ...1.upper-right
+| 4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f corner.....1.lo
+| 4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72 wer-right corner
+| 4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 ...../.upper-lef
+| 4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c t corner...../.l
+| 4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72 ower-left corner
+| page 3 offset 8192
+| 0: 0d 00 00 00 01 0b 2d 00 0b 2d 00 00 00 00 00 00 ......-..-......
+| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
+| 2864: 04 00 93 24 00 00 00 0e 00 00 00 00 00 00 00 01 ...$............
+| 2880: 00 00 00 04 01 20 00 00 00 00 00 04 12 00 00 00 ..... ..........
+| 2896: 00 00 00 00 00 00 00 23 00 00 00 00 41 20 00 00 .......#....A ..
+| 2912: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 03 B...B...........
+| 2928: 42 b4 00 00 42 c8 00 00 00 00 00 00 41 20 00 00 B...B.......A ..
+| 2944: 00 00 00 00 00 00 00 04 42 b4 00 00 42 c8 00 00 ........B...B...
+| 2960: 42 b4 00 00 42 c8 00 00 00 00 00 00 00 00 00 05 B...B...........
+| 2976: 42 20 00 00 42 70 00 00 42 20 00 00 42 70 00 00 B ..Bp..B ..Bp..
+| 2992: 00 00 00 00 00 00 00 06 00 00 00 00 40 a0 00 00 ............@...
+| 3008: 00 00 00 04 2c 80 00 00 00 00 00 00 00 00 00 74 ....,..........t
+| 3024: 2b e0 00 04 2c 80 00 04 2c 80 00 00 00 00 00 00 +...,...,.......
+| 3040: 00 00 00 80 00 00 00 04 2c 80 00 00 00 00 00 04 ........,.......
+| 3056: 0a 00 00 00 00 00 b0 80 00 00 04 2c 80 00 04 2b ...........,...+
+| 3072: e0 00 04 2c 80 00 00 00 00 00 00 00 00 00 a0 00 ...,............
+| 3088: 00 00 04 2c 80 00 00 00 00 00 04 2c 80 00 00 00 ...,.......,....
+| 3104: 00 00 00 00 00 00 b0 00 00 00 04 24 80 00 00 00 ...........$....
+| 3120: 00 00 04 2c 80 00 00 00 00 00 00 00 50 00 91 f0 ...,........P...
+| 3136: 06 c6 56 67 42 06 86 16 c6 61 40 a0 50 00 92 b0 ..VgB....a@.P...
+| 3152: 07 46 86 52 07 76 86 f6 c6 52 07 46 86 96 e6 70 .F.R.v...R.F...p
+| 3168: d0 90 50 00 91 d0 07 46 f7 02 06 56 46 76 51 00 ..P....F...VFvQ.
+| 3184: 80 50 00 92 30 06 26 f7 47 46 f6 d2 06 56 46 76 .P..0.&.GF...VFv
+| 3200: 50 f0 70 50 00 92 10 07 26 96 76 87 42 06 56 46 P.pP....&.v.B.VF
+| 3216: 76 50 e0 60 50 00 91 f0 06 c6 56 67 42 06 56 46 vP.`P.....VgB.VF
+| 3232: 76 50 b0 50 50 00 91 90 06 36 56 e7 46 57 21 70 vP.PP....6V.FW!p
+| 3248: 40 50 00 93 10 07 57 07 06 57 22 d7 26 96 76 87 @P....W..W..&.v.
+| 3264: 42 06 36 f7 26 e6 57 21 70 30 50 00 93 10 06 c6 B.6.&.W!p0P.....
+| 3280: f7 76 57 22 d7 26 96 76 87 42 06 36 f7 26 e6 57 .vW..&.v.B.6.&.W
+| 3296: 21 60 20 50 00 92 f0 07 57 07 06 57 22 d6 c6 56 !` P....W..W...V
+| 3312: 60 00 00 c4 24 c0 00 04 2c 80 00 00 00 00 00 04 `...$...,.......
+| 3328: 2c 80 00 00 00 00 00 00 00 00 00 d0 00 00 00 04 ,...............
+| 3344: 2c 80 00 00 00 00 00 04 24 80 00 00 00 00 00 00 ,.......$.......
+| 3360: 00 00 00 e0 00 00 00 04 2c 80 00 04 24 c0 00 04 ........,...$...
+| 3376: 2c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ,...............
+| page 4 offset 12288
+| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
+| end c4.db
+ }]
+ catchsql {
+ UPDATE t1 SET label='x';
+ }
+} {1 {rtree constraint failed: t1.(y0<=y1)}}
+do_test rtreefuzz001-310 {
+ catchsql {
+ SELECT rtreecheck('t1');
+ }
+} {/1 .*corrupt.*/}
+
+do_test rtreefuzz001-400 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 16384 pagesize 4096 filename c7.db
+| page 1 offset 0
+| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04 .....@ ........
+| 32: 00 00 00 00 01 00 00 00 00 00 00 04 00 00 00 04 ................
+| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
+| 96: 00 00 00 00 0d 00 00 00 04 0e 9c 00 0f ad 0f 4f ...............O
+| 112: 0e fc 0e 9c 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3728: 00 00 00 00 00 00 00 00 00 00 00 00 5e 04 07 17 ............^...
+| 3744: 1f 1f 01 81 0b 74 61 62 6c 65 74 31 5f 70 61 72 .....tablet1_par
+| 3760: 65 6e 74 74 31 5f 70 61 72 65 6e 74 04 43 52 45 entt1_parent.CRE
+| 3776: 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 70 61 ATE TABLE .t1_pa
+| 3792: 72 65 6e 74 22 28 6e 6f 64 65 6e 6f 20 49 4e 54 rent.(nodeno INT
+| 3808: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
+| 3824: 2c 70 61 72 65 6e 74 6e 6f 64 65 29 51 03 06 17 ,parentnode)Q...
+| 3840: 1b 1b 01 7b 74 61 62 6c 65 74 31 5f 6e 6f 64 65 ....tablet1_node
+| 3856: 74 31 5f 6e 6f 64 65 03 43 52 45 41 54 45 20 54 t1_node.CREATE T
+| 3872: 41 42 4c 45 20 22 74 31 5f 6e 6f 64 65 22 28 6e ABLE .t1_node.(n
+| 3888: 6f 64 65 6e 6f 20 49 4e 54 45 47 45 52 20 50 52 odeno INTEGER PR
+| 3904: 49 4d 41 52 59 20 4b 45 59 2c 64 61 74 61 29 5c IMARY KEY,data).
+| 3920: 02 07 17 1d 1d 01 81 0b 74 61 62 6c 65 74 31 5f ........tablet1_
+| 3936: 72 6f 77 69 64 74 31 5f 72 6f 77 69 64 02 43 52 rowidt1_rowid.CR
+| 3952: 45 41 54 45 20 54 41 42 4c 45 20 22 74 31 5f 72 EATE TABLE .t1_r
+| 3968: 6f 77 69 64 22 28 72 6f 77 69 64 20 49 4e 54 45 owid.(rowid INTE
+| 3984: 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c GER PRIMARY KEY,
+| 4000: 6e 6f 64 65 6e 6f 2c 61 30 2c 61 31 29 51 01 07 nodeno,a0,a1)Q..
+| 4016: 17 11 11 08 81 0f 74 61 62 6c 65 74 31 74 31 43 ......tablet1t1C
+| 4032: 52 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 REATE VIRTUAL TA
+| 4048: 42 4c 45 20 74 31 20 55 53 49 4e 47 20 72 74 72 BLE t1 USING rtr
+| 4064: 65 65 28 69 64 2c 78 30 2c 78 31 2c 79 30 2c 79 ee(id,x0,x1,y0,y
+| 4080: 31 2c 2b 6c 61 62 65 6c 2c 2b 6f 74 68 65 72 29 1,+label,+other)
+| page 2 offset 4096
+| 0: 0d 00 00 00 0e 0e f7 00 0f e8 0f d0 0f b7 0f 9e ................
+| 16: 0f 91 0f 81 0f 70 0f 5e 0f 4f 0f 39 0f 29 0f 18 .....p.^.O.9.)..
+| 32: 0f 06 0e f7 00 00 00 00 00 00 00 00 00 00 00 00 ................
+| 3824: 00 00 00 00 00 00 00 0d 0e 05 00 09 1d 00 74 6f ..............to
+| 3840: 70 20 68 61 6c 66 10 0d 05 00 09 23 00 62 6f 74 p half.....#.bot
+| 3856: 74 6f 6d 20 68 61 6c 66 0f 0c 05 00 09 21 00 72 tom half.....!.r
+| 3872: 69 67 68 74 20 68 61 6c 66 0e 0b 05 00 09 1f 00 ight half.......
+| 3888: 6c 65 66 74 20 68 61 6c 66 14 0a 05 00 09 2b 00 left half.....+.
+| 3904: 74 68 65 20 77 68 6f 6c 65 20 74 68 69 6e 67 0d the whole thing.
+| 3920: 09 05 00 09 1d 00 74 6f 70 20 65 64 67 65 10 08 ......top edge..
+| 3936: 05 00 09 23 00 62 6f 74 74 6f 6d 20 65 64 67 65 ...#.bottom edge
+| 3952: 0f 07 05 00 09 21 00 72 69 67 68 74 20 65 64 67 .....!.right edg
+| 3968: 65 0e 06 05 00 09 1f 00 6c 65 66 74 20 65 64 67 e.......left edg
+| 3984: 65 0b 05 05 00 09 19 00 23 65 6e 74 65 72 17 04 e.......#enter..
+| 4000: 05 00 09 31 00 75 70 70 65 72 2d 72 69 67 68 74 ...1.upper-right
+| 4016: 20 63 6f 72 6e 65 72 17 03 05 00 09 31 00 6c 6f corner.....1.lo
+| 4032: 77 65 72 2d 72 69 67 68 74 20 63 6f 72 6e 65 72 wer-right corner
+| 4048: 16 02 05 00 09 2f 00 75 70 70 65 72 2d 6c 65 66 ...../.upper-lef
+| 4064: 74 20 63 6f 72 6e 65 72 16 01 05 00 09 2f 00 6c t corner...../.l
+| 4080: 6f 77 65 72 2d 6c 65 66 74 20 63 6f 72 6e 65 72 ower-left corner
+| page 3 offset 8192
+| 0: 0d 00 00 00 02 0b 2d 00 0b 2d 00 00 00 00 00 00 ......-..-......
+| 2848: 00 00 00 00 00 00 00 00 00 00 00 00 00 89 50 01 ..............P.
+| 2864: 04 00 93 24 00 00 00 00 00 00 00 00 08 00 00 00 ...$............
+| 2880: 00 42 c8 00 00 00 00 00 00 40 a0 00 00 00 00 00 .B.......@......
+| 2896: 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 07 ....B...........
+| 2912: 42 be 00 00 42 c8 00 00 00 00 00 00 42 c8 00 00 B...B.......B...
+| 2928: 00 00 00 00 00 00 00 08 00 00 00 00 42 c8 00 00 ............B...
+| 2944: 00 00 00 00 40 a0 00 00 00 00 00 00 00 00 00 09 ....@...........
+| 2960: 00 00 00 00 42 c8 00 00 42 be 00 00 42 c8 00 00 ....B...B...B...
+| 2976: 00 00 00 00 00 00 00 0a 00 00 00 00 42 c8 00 00 ............B...
+| 2992: 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 0b ....B...........
+| 3008: 00 00 00 00 42 48 00 00 00 00 00 04 2c 80 00 00 ....BH......,...
+| 3024: 00 00 00 00 00 00 00 c4 00 00 00 00 00 42 c8 00 .............B..
+| 3040: 00 00 00 00 00 00 00 00 07 42 be 00 00 42 c8 00 .........B...B..
+| 3056: 00 00 00 00 00 42 c8 00 00 00 00 00 00 00 00 00 .....B..........
+| 3072: 08 00 00 00 00 42 c8 00 00 00 00 00 00 40 a0 00 .....B.......@..
+| 3088: 00 00 00 00 00 00 00 00 09 00 00 00 00 42 c8 00 .............B..
+| 3104: 00 42 be 00 00 42 c8 00 00 00 00 00 00 00 00 00 .B...B..........
+| 3120: 0a 00 00 00 00 42 c8 00 00 00 00 00 00 42 c8 00 .....B.......B..
+| 3136: 00 00 00 00 00 00 00 00 0b 00 00 00 00 42 48 00 .............BH.
+| 3152: 00 00 00 00 04 2c 80 00 00 00 00 00 00 00 00 00 .....,..........
+| 3168: c4 24 c0 00 04 2c 80 00 00 00 00 00 04 2c 80 00 .$...,.......,..
+| 3184: 00 00 00 00 00 00 00 00 d0 00 00 00 04 2c 80 00 .............,..
+| 3200: 00 00 00 00 04 24 80 00 00 00 00 00 00 00 00 00 .....$..........
+| 3216: e0 00 00 00 04 2c 80 00 04 24 c0 00 04 2c 00 00 .....,...$...,..
+| page 4 offset 12288
+| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 0e 00 00 00 ................
+| 16: 00 42 c8 00 00 42 4c 00 00 42 c8 00 00 00 00 00 .B...BL..B......
+| 32: 00 00 00 0a 00 00 00 00 42 c8 00 00 00 00 00 00 ........B.......
+| 48: 42 c8 00 00 00 00 00 00 00 00 00 0b 00 00 00 00 B...............
+| 64: 42 48 00 00 00 00 00 04 2c 80 00 00 00 00 00 00 BH......,.......
+| 80: 00 00 00 c4 24 c0 00 04 2c 80 00 00 00 00 00 04 ....$...,.......
+| 96: 2c 80 00 00 00 00 00 00 00 00 00 d0 00 00 00 04 ,...............
+| 112: 2c 80 00 00 00 00 00 04 24 80 00 00 00 00 00 00 ,.......$.......
+| 128: 00 00 00 e0 00 00 00 04 2c 80 00 04 24 c0 00 04 ........,...$...
+| 144: 2c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ,...............
+| end c7.db
+ }]
+ catchsql {
+ WITH RECURSIVE
+ c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<8),
+ c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<5)
+ INSERT INTO t1(id, x0,x1,y0,y1,label)
+ SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
+ }
+} {1 {database disk image is malformed}}
+
+finish_test
diff --git a/chromium/third_party/sqlite/src/ext/session/changeset.c b/chromium/third_party/sqlite/src/ext/session/changeset.c
index 88db9da1b47..651d3066544 100644
--- a/chromium/third_party/sqlite/src/ext/session/changeset.c
+++ b/chromium/third_party/sqlite/src/ext/session/changeset.c
@@ -42,7 +42,7 @@ static void usage(const char *argv0){
*/
static void readFile(const char *zFilename, int *pSz, void **ppBuf){
FILE *f;
- int sz;
+ sqlite3_int64 sz;
void *pBuf;
f = fopen(zFilename, "rb");
if( f==0 ){
@@ -50,9 +50,9 @@ static void readFile(const char *zFilename, int *pSz, void **ppBuf){
exit(1);
}
fseek(f, 0, SEEK_END);
- sz = (int)ftell(f);
+ sz = ftell(f);
rewind(f);
- pBuf = sqlite3_malloc( sz ? sz : 1 );
+ pBuf = sqlite3_malloc64( sz ? sz : 1 );
if( pBuf==0 ){
fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
sz, zFilename);
diff --git a/chromium/third_party/sqlite/src/ext/session/changesetfuzz.c b/chromium/third_party/sqlite/src/ext/session/changesetfuzz.c
index 9b3619d64fe..3ebf7c7536d 100644
--- a/chromium/third_party/sqlite/src/ext/session/changesetfuzz.c
+++ b/chromium/third_party/sqlite/src/ext/session/changesetfuzz.c
@@ -141,7 +141,7 @@ static void usage(const char *argv0){
*/
static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){
FILE *f;
- int sz;
+ sqlite3_int64 sz;
void *pBuf;
f = fopen(zFilename, "rb");
if( f==0 ){
@@ -149,9 +149,9 @@ static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){
exit(1);
}
fseek(f, 0, SEEK_END);
- sz = (int)ftell(f);
+ sz = ftell(f);
rewind(f);
- pBuf = sqlite3_malloc( sz ? sz : 1 );
+ pBuf = sqlite3_malloc64( sz ? sz : 1 );
if( pBuf==0 ){
fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
sz, zFilename);
@@ -340,8 +340,8 @@ struct FuzzChange {
/*
** Allocate and return nByte bytes of zeroed memory.
*/
-static void *fuzzMalloc(int nByte){
- void *pRet = sqlite3_malloc(nByte);
+static void *fuzzMalloc(sqlite3_int64 nByte){
+ void *pRet = sqlite3_malloc64(nByte);
if( pRet ){
memset(pRet, 0, nByte);
}
@@ -631,7 +631,7 @@ static int fuzzParseChangeset(
/* If the table-header was successfully parsed, add the new change-group
** to the array and parse the associated changes. */
if( rc==SQLITE_OK ){
- FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc(
+ FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc64(
pParse->apGroup, sizeof(FuzzChangesetGroup*)*(pParse->nGroup+1)
);
if( apNew==0 ){
@@ -1214,7 +1214,7 @@ int main(int argc, char **argv){
fuzzPrintGroup(&changeset, changeset.apGroup[i]);
}
}else{
- pBuf = (u8*)fuzzMalloc(nChangeset*2 + 1024);
+ pBuf = (u8*)fuzzMalloc((sqlite3_int64)nChangeset*2 + 1024);
if( pBuf==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -1237,4 +1237,3 @@ int main(int argc, char **argv){
return rc;
}
-
diff --git a/chromium/third_party/sqlite/src/ext/session/session_speed_test.c b/chromium/third_party/sqlite/src/ext/session/session_speed_test.c
index f18bb306e44..de9de273f62 100644
--- a/chromium/third_party/sqlite/src/ext/session/session_speed_test.c
+++ b/chromium/third_party/sqlite/src/ext/session/session_speed_test.c
@@ -356,5 +356,3 @@ int main(int argc, char **argv){
return 0;
}
-
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionwor.test b/chromium/third_party/sqlite/src/ext/session/sessionwor.test
index e9545c5376e..1d594c5624f 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionwor.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionwor.test
@@ -30,27 +30,71 @@ proc test_reset {} {
sqlite3 db2 test.db2
}
+foreach {tn wo} {
+ 1 ""
+ 2 "WITHOUT ROWID"
+} {
+ reset_db
-do_execsql_test 1.0 {
- CREATE TABLE t1(a PRIMARY KEY, b) WITHOUT ROWID;
-}
+ do_execsql_test 1.$tn.0 "CREATE TABLE t1(a PRIMARY KEY, b) $wo ;"
-do_iterator_test 1.1 t1 {
- INSERT INTO t1 VALUES('one', 'two');
-} {
- {INSERT t1 0 X. {} {t one t two}}
-}
+ do_iterator_test 1.$tn.1 t1 {
+ INSERT INTO t1 VALUES('one', 'two');
+ } {
+ {INSERT t1 0 X. {} {t one t two}}
+ }
-do_iterator_test 1.2 t1 {
- UPDATE t1 SET b='three'
-} {
- {UPDATE t1 0 X. {t one t two} {{} {} t three}}
+ do_iterator_test 1.$tn.2 t1 {
+ UPDATE t1 SET b='three'
+ } {
+ {UPDATE t1 0 X. {t one t two} {{} {} t three}}
+ }
+
+ do_iterator_test 1.$tn.3 t1 {
+ REPLACE INTO t1 VALUES('one', 'four');
+ } {
+ {UPDATE t1 0 X. {t one t three} {{} {} t four}}
+ }
+
+ do_iterator_test 1.$tn.4 t1 {
+ DELETE FROM t1;
+ } {
+ {DELETE t1 0 X. {t one t four} {}}
+ }
}
-do_iterator_test 1.3 t1 {
- DELETE FROM t1;
+foreach {tn wo} {
+ 1 ""
+ 2 "WITHOUT ROWID"
} {
- {DELETE t1 0 X. {t one t three} {}}
+ reset_db
+
+ do_execsql_test 2.$tn.0 "CREATE TABLE t1(a INTEGER PRIMARY KEY, b) $wo ;"
+
+ do_iterator_test 1.1 t1 {
+ INSERT INTO t1 VALUES(1, 'two');
+ } {
+ {INSERT t1 0 X. {} {i 1 t two}}
+ }
+
+ do_iterator_test 2.$tn.2 t1 {
+ UPDATE t1 SET b='three'
+ } {
+ {UPDATE t1 0 X. {i 1 t two} {{} {} t three}}
+ }
+
+ do_iterator_test 2.$tn.3 t1 {
+ REPLACE INTO t1 VALUES(1, 'four');
+ } {
+ {UPDATE t1 0 X. {i 1 t three} {{} {} t four}}
+ }
+
+ do_iterator_test 2.$tn.4 t1 {
+ DELETE FROM t1;
+ } {
+ {DELETE t1 0 X. {i 1 t four} {}}
+ }
}
finish_test
+
diff --git a/chromium/third_party/sqlite/src/ext/session/sqlite3session.c b/chromium/third_party/sqlite/src/ext/session/sqlite3session.c
index 2e9a8ba7278..012473599b4 100644
--- a/chromium/third_party/sqlite/src/ext/session/sqlite3session.c
+++ b/chromium/third_party/sqlite/src/ext/session/sqlite3session.c
@@ -363,7 +363,7 @@ static void sessionPutI64(u8 *aBuf, sqlite3_int64 i){
static int sessionSerializeValue(
u8 *aBuf, /* If non-NULL, write serialized value here */
sqlite3_value *pValue, /* Value to serialize */
- int *pnWrite /* IN/OUT: Increment by bytes written */
+ sqlite3_int64 *pnWrite /* IN/OUT: Increment by bytes written */
){
int nByte; /* Size of serialized value in bytes */
@@ -904,7 +904,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
SessionChange **apNew;
int nNew = (pTab->nChange ? pTab->nChange : 128) * 2;
- apNew = (SessionChange **)sqlite3_malloc(sizeof(SessionChange *) * nNew);
+ apNew = (SessionChange **)sqlite3_malloc64(sizeof(SessionChange *) * nNew);
if( apNew==0 ){
if( pTab->nChange==0 ){
return SQLITE_ERROR;
@@ -970,7 +970,7 @@ static int sessionTableInfo(
char *zPragma;
sqlite3_stmt *pStmt;
int rc;
- int nByte;
+ sqlite3_int64 nByte;
int nDbCol = 0;
int nThis;
int i;
@@ -1013,7 +1013,7 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
- pAlloc = sqlite3_malloc(nByte);
+ pAlloc = sqlite3_malloc64(nByte);
if( pAlloc==0 ){
rc = SQLITE_NOMEM;
}
@@ -1154,7 +1154,7 @@ static void sessionPreupdateOneChange(
int iHash;
int bNull = 0;
int rc = SQLITE_OK;
- SessionStat1Ctx stat1 = {0};
+ SessionStat1Ctx stat1 = {{0,0,0,0,0},0};
if( pSession->rc ) return;
@@ -1211,7 +1211,7 @@ static void sessionPreupdateOneChange(
** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
** values (if this is an INSERT). */
SessionChange *pChange; /* New change object */
- int nByte; /* Number of bytes to allocate */
+ sqlite3_int64 nByte; /* Number of bytes to allocate */
int i; /* Used to iterate through columns */
assert( rc==SQLITE_OK );
@@ -1236,7 +1236,7 @@ static void sessionPreupdateOneChange(
}
/* Allocate the change object */
- pChange = (SessionChange *)sqlite3_malloc(nByte);
+ pChange = (SessionChange *)sqlite3_malloc64(nByte);
if( !pChange ){
rc = SQLITE_NOMEM;
goto error_out;
@@ -1680,7 +1680,7 @@ int sqlite3session_create(
*ppSession = 0;
/* Allocate and populate the new session object. */
- pNew = (sqlite3_session *)sqlite3_malloc(sizeof(sqlite3_session) + nDb + 1);
+ pNew = (sqlite3_session *)sqlite3_malloc64(sizeof(sqlite3_session) + nDb + 1);
if( !pNew ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(sqlite3_session));
pNew->db = db;
@@ -1799,7 +1799,7 @@ int sqlite3session_attach(
if( !pTab ){
/* Allocate new SessionTable object. */
- pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);
+ pTab = (SessionTable *)sqlite3_malloc64(sizeof(SessionTable) + nName + 1);
if( !pTab ){
rc = SQLITE_NOMEM;
}else{
@@ -1859,7 +1859,7 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){
static void sessionAppendValue(SessionBuffer *p, sqlite3_value *pVal, int *pRc){
int rc = *pRc;
if( rc==SQLITE_OK ){
- int nByte = 0;
+ sqlite3_int64 nByte = 0;
rc = sessionSerializeValue(0, pVal, &nByte);
sessionBufferGrow(p, nByte, &rc);
if( rc==SQLITE_OK ){
@@ -2735,7 +2735,7 @@ static int sessionValueSetStr(
** argument to sqlite3ValueSetStr() and have the copy created
** automatically. But doing so makes it difficult to detect any OOM
** error. Hence the code to create the copy externally. */
- u8 *aCopy = sqlite3_malloc(nData+1);
+ u8 *aCopy = sqlite3_malloc64((sqlite3_int64)nData+1);
if( aCopy==0 ) return SQLITE_NOMEM;
memcpy(aCopy, aData, nData);
sqlite3ValueSetStr(pVal, nData, (char*)aCopy, enc, sqlite3_free);
@@ -3348,7 +3348,7 @@ static int sessionChangesetInvert(
int iCol;
if( 0==apVal ){
- apVal = (sqlite3_value **)sqlite3_malloc(sizeof(apVal[0])*nCol*2);
+ apVal = (sqlite3_value **)sqlite3_malloc64(sizeof(apVal[0])*nCol*2);
if( 0==apVal ){
rc = SQLITE_NOMEM;
goto finished_invert;
@@ -4621,7 +4621,7 @@ static int sessionChangeMerge(
int rc = SQLITE_OK;
if( !pExist ){
- pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec);
+ pNew = (SessionChange *)sqlite3_malloc64(sizeof(SessionChange) + nRec);
if( !pNew ){
return SQLITE_NOMEM;
}
@@ -4654,8 +4654,8 @@ static int sessionChangeMerge(
if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){
*ppNew = pExist;
}else{
- int nByte = nRec + pExist->nRecord + sizeof(SessionChange);
- pNew = (SessionChange*)sqlite3_malloc(nByte);
+ sqlite3_int64 nByte = nRec + pExist->nRecord + sizeof(SessionChange);
+ pNew = (SessionChange*)sqlite3_malloc64(nByte);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -4715,14 +4715,14 @@ static int sessionChangeMerge(
assert( pNew==0 );
}else{
u8 *aExist = pExist->aRecord;
- int nByte;
+ sqlite3_int64 nByte;
u8 *aCsr;
/* Allocate a new SessionChange object. Ensure that the aRecord[]
** buffer of the new object is large enough to hold any record that
** may be generated by combining the input records. */
nByte = sizeof(SessionChange) + pExist->nRecord + nRec;
- pNew = (SessionChange *)sqlite3_malloc(nByte);
+ pNew = (SessionChange *)sqlite3_malloc64(nByte);
if( !pNew ){
sqlite3_free(pExist);
return SQLITE_NOMEM;
@@ -4828,7 +4828,7 @@ static int sessionChangesetToHash(
if( !pTab ){
SessionTable **ppTab;
- pTab = sqlite3_malloc(sizeof(SessionTable) + nCol + nNew+1);
+ pTab = sqlite3_malloc64(sizeof(SessionTable) + nCol + nNew+1);
if( !pTab ){
rc = SQLITE_NOMEM;
break;
diff --git a/chromium/third_party/sqlite/src/ext/session/sqlite3session.h b/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
index c93d0ecdaf4..d145733dc27 100644
--- a/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
+++ b/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
@@ -548,7 +548,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** sqlite3changeset_next() is called on the iterator or until the
** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
** set to the number of columns in the table affected by the change. If
-** pbIncorrect is not NULL, then *pbIndirect is set to true (1) if the change
+** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlite3session_indirect()] for a description of direct and indirect
** changes. Finally, if pOp is not NULL, then *pOp is set to one of
diff --git a/chromium/third_party/sqlite/src/main.mk b/chromium/third_party/sqlite/src/main.mk
index b460a58d9a9..ee8ebbb92f5 100644
--- a/chromium/third_party/sqlite/src/main.mk
+++ b/chromium/third_party/sqlite/src/main.mk
@@ -371,6 +371,7 @@ TESTSRC += \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/normalize.c \
$(TOP)/ext/misc/percentile.c \
+ $(TOP)/ext/misc/prefixes.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
@@ -513,7 +514,8 @@ FUZZDATA = \
$(TOP)/test/fuzzdata4.db \
$(TOP)/test/fuzzdata5.db \
$(TOP)/test/fuzzdata6.db \
- $(TOP)/test/fuzzdata7.db
+ $(TOP)/test/fuzzdata7.db \
+ $(TOP)/test/fuzzdata8.db
# Standard options to testfixture
#
@@ -534,6 +536,11 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
+FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
+FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
+FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
+FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
+FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
ST_OPT = -DSQLITE_THREADSAFE=0
@@ -578,6 +585,20 @@ dbfuzz$(EXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c \
$(TLIBS) $(THREADLIB)
+DBFUZZ2_OPTS = \
+ -DSQLITE_THREADSAFE=0 \
+ -DSQLITE_OMIT_LOAD_EXTENSION \
+ -DSQLITE_ENABLE_DESERIALIZE \
+ -DSQLITE_DEBUG \
+ -DSQLITE_ENABLE_DBSTAT_VTAB \
+ -DSQLITE_ENABLE_RTREE \
+ -DSQLITE_ENABLE_FTS4 \
+ -DSQLITE_ENABLE_FTS5
+
+dbfuzz2$(EXE): $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
+ $(TCCX) -I. -g -O0 -DSTANDALONE -o dbfuzz2$(EXE) \
+ $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c $(TLIBS) $(THREADLIB)
+
fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c
$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
@@ -723,6 +744,7 @@ SHELL_SRC = \
$(TOP)/ext/expert/sqlite3expert.c \
$(TOP)/ext/expert/sqlite3expert.h \
$(TOP)/ext/misc/zipfile.c \
+ $(TOP)/ext/misc/memtrace.c \
$(TOP)/src/test_windirent.c
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
@@ -981,6 +1003,9 @@ $(TEST_EXTENSION): $(TOP)/src/test_loadext.c
extensiontest: testfixture$(EXE) $(TEST_EXTENSION)
./testfixture$(EXE) $(TOP)/test/loadext.test
+dbtotxt$(EXE): $(TOP)/tool/dbtotxt.c
+ $(TCC) -o dbtotxt$(EXE) $(TOP)/tool/dbtotxt.c
+
showdb$(EXE): $(TOP)/tool/showdb.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showdb$(EXE) \
$(TOP)/tool/showdb.c sqlite3.o $(THREADLIB)
@@ -1000,6 +1025,10 @@ showwal$(EXE): $(TOP)/tool/showwal.c sqlite3.o
showshm$(EXE): $(TOP)/tool/showshm.c
$(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c
+index_usage$(EXE): $(TOP)/tool/index_usage.c sqlite3.o
+ $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_DEPRECATED $(SHELL_OPTS) -o index_usage$(EXE) \
+ $(TOP)/tool/index_usage.c sqlite3.o $(THREADLIB)
+
changeset$(EXE): $(TOP)/ext/session/changeset.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \
$(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB)
diff --git a/chromium/third_party/sqlite/src/manifest b/chromium/third_party/sqlite/src/manifest
index bb8f3728c11..65f29c943fc 100644
--- a/chromium/third_party/sqlite/src/manifest
+++ b/chromium/third_party/sqlite/src/manifest
@@ -1,12 +1,12 @@
-C Version\s3.26.0
-D 2018-12-01T12:34:55.966
+C Version\s3.27.1
+D 2019-02-08T13:17:39.690
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
-F Makefile.in a050c8670ea0d7b37b2192306cbb50d392acd9902b84e9b56f3444d006f97a6c
+F Makefile.in 178d8eb6840771149cee40b322d1b3be30d330198c522c903c1b66fb5a1bfca4
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
-F Makefile.msc 0d6831ff7951b302e888d86d4c469e2ec3c22f59eba4118b8c38d5a51d9e2d4f
+F Makefile.msc 5df60c70edb157feb2148a14c687551969599bd065875a0b959b6b139721ca72
F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee
-F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb
+F VERSION 15b2d421b2265aad451c0493066c1c31a511a72c5153bb4e9d5f62adbc12134c
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -14,7 +14,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am e14b629addaa1ce372b72043f28f40de2e32b7e211b6e0fc18dbb87989197e40
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.msc 9e73d9abaadb7a4951ddd0e947c5c791770f23bb1e04bfa50b43c01bee0575f2
+F autoconf/Makefile.msc ee8ab2b6b5d712f68acc4c186e3fad7b831b87a2b118e0a123043ea8a2c8b016
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192
@@ -33,7 +33,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
-F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x
+F configure 2b0310f5ddb82f4e2c524c0bc7bacf480b0ac21bf05b543d7e72e2682772eaac x
F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
@@ -46,7 +46,7 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
-F ext/expert/expert1.test 333d037021c901322f9afc4a5687648ea23d56f1a0a079358a390664babf01be
+F ext/expert/expert1.test 358e416877a5693fb99d5514f5d88452b5239dc2196b74e0e926718502faef6d
F ext/expert/sqlite3expert.c 3da865f2286433588260f41e796422c611bceaca3a0bbf9139a619cf7d062c19
F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
@@ -80,55 +80,55 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 65b8489e35da23b127992c6dd6cfd382a486f8c87bf26dfa72876efe46e551bb
+F ext/fts3/fts3.c 5da1329ccf66b6d597dfb16b1f81aa204133c1ec96117d82a59c20126f483b17
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5
-F ext/fts3/fts3_aux.c e9b465f8469acc2cd700a90c0242912a3202e4e4e15df72d7db7f1e3a2222c85
-F ext/fts3/fts3_expr.c 3b1dbceddd8622599f3cc2626897667fe40487aaa1676707d6c37ec5a8422fc1
-F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
+F ext/fts3/fts3Int.h 74384e28b778a057f1467529715668b98f3f12f52eeb564fd6ae1e894125c00c
+F ext/fts3/fts3_aux.c 96708c8b3a7d9b8ca1b68ea2b7e503e283f20e95f145becadedfad096dbd0f34
+F ext/fts3/fts3_expr.c b132af223e90e35b9f9efa9fe63d6ae737d34153a3b6066736086df8abc78a1f
+F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6bdb48b7
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
-F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
+F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
-F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
-F ext/fts3/fts3_term.c 9b8065cc70ad514fcc25a7b099ddab8b5333f724dedd57184b7e79238e2b2a39
-F ext/fts3/fts3_test.c 79f2a7fbb3f672fa032e5a432ca274ea3ee93c34
-F ext/fts3/fts3_tokenize_vtab.c a47c2a33de6db00816704315ac0a9afdfa1c71fa5b99f79171c0f7b30861f784
+F ext/fts3/fts3_snippet.c ac1f8945375d07076b7178de1fe549982e6ae6f050095e7f7e400ec4448f31df
+F ext/fts3/fts3_term.c 12f7b2318f1254e6cc46dd306e5f2ac5b00b06d6761f5cae09fee5e1817cc32a
+F ext/fts3/fts3_test.c b6e9f3fd7155cb388c6bc203fb24817a721fb61d9ce28810c73fcfda8c16fda6
+F ext/fts3/fts3_tokenize_vtab.c 969c132816b6f46ee2c7efafd2547a9bfd50b0aac3f8cef3f2dca2cbd90639c7
F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
-F ext/fts3/fts3_unicode.c 525a3bd9a7564603c5c061b7de55403a565307758a94600e8a2f6b00d1c40d9d
-F ext/fts3/fts3_unicode2.c cc04fc672bfd42b1e650398cb0bf71f64f9aae032cfe75bbcfe75b9cf966029c
-F ext/fts3/fts3_write.c a85bc4885fde7f1b44c9de013b62f7cd3332dc59e208053d878729b1d04745bc
+F ext/fts3/fts3_unicode.c 4b9af6151c29b35ed09574937083cece7c31e911f69615e168a39677569b684d
+F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
+F ext/fts3/fts3_write.c 45cbe0b06221f5debefe37f8f9882cf0401592668cb76624a64c0f3f185115de
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
-F ext/fts3/unicode/mkunicode.tcl 0069320b64db6ee269c5e95f1f150d070fbf0a863fc7b3549d7e52bd068fb118
-F ext/fts3/unicode/parseunicode.tcl 024ae0bdd96309d7b8fc479148191e9b3001dc74017a3f65f9a27de3b3ff968b
+F ext/fts3/unicode/mkunicode.tcl 49499f7964504438e2b04cca0627827945bb2499154e2d3ec216b22d20b969ae
+F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
-F ext/fts5/fts5.h 5edc74ca603d71284d475886e6e91b5c5cf2e8e93e9ba3a36ba2f2440ee97948
-F ext/fts5/fts5Int.h 39f12034b598df4e0f59bbe6cf03af03a905a534b04f182d155641a04e1eb797
-F ext/fts5/fts5_aux.c ca666a3bbe07c5a3bbe9fffaea19c935a1efaf337333e28bad7bdd1971ffd093
-F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff
-F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
-F ext/fts5/fts5_expr.c 5aef080ba3c8947e22f38ce1ff9fe548e4a740e72b77241f35ed941ae128d2c7
-F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
-F ext/fts5/fts5_index.c baf3ad4451d32d35c2bd692ee4a81235ca7f26bd6f7613f7f73505474c33bbf2
-F ext/fts5/fts5_main.c 287a1a56580df304d7fa2fc1890f85b9cb6ac6b9e7c8af7dfa2151528db4b059
-F ext/fts5/fts5_storage.c 4bec8a1b3905978b22a67bca5f4a3cfdb94af234cf51efb36f4f2d733d278634
+F ext/fts5/fts5.h fed314270c1a61de3a0e373b11c2f8228b1c76ce59447dd96d0b6fae7d66399b
+F ext/fts5/fts5Int.h 0b002fc71ea705d2c4ec66a63ecd38a2c11127e5b52239b5d71d1dd28309fc19
+F ext/fts5/fts5_aux.c afe8c2394cf6de2a48f278442f4f4342365bf99a5983709ef8e6955c2cf4daf9
+F ext/fts5/fts5_buffer.c 2e750cd4c0d456d4e1a8dcc649382708422b535dc32b375fd3d3306fb9727046
+F ext/fts5/fts5_config.c eeec97cb0237991e7fa3bbae07b5cc354e3f238b661200c11228fe167c18f882
+F ext/fts5/fts5_expr.c 188d1dca5a262a0708efc5deb809f1aa6ecea4158986a439d2670cfe72d10b65
+F ext/fts5/fts5_hash.c d415f5ad332b051f0ade564bcf1762c4467cc49b2ba8ea5873d8744c705d8d42
+F ext/fts5/fts5_index.c ffff7e8d41594256cacf7b32072f8bc06478a86026196a7eb084450065df8d92
+F ext/fts5/fts5_main.c 95d63bbe6075955961e56878c3a8705dc475c2b17f5c767f7b8af14093ae614b
+F ext/fts5/fts5_storage.c 57e3f2b1a612961a27c944d6b8821028ec5fdb541d7e6b841785003ac3b0b43a
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
-F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
-F ext/fts5/fts5_test_tok.c 80de1a4b1a3caa216c3be8862440f0117a8357dd9b7cfc5a2a2ce11fe6eb64ae
-F ext/fts5/fts5_tokenize.c ebd13d034f3dc7c841e1c32c364a4fca5cc2e05a0b91682a93fa1e6defcd4292
-F ext/fts5/fts5_unicode2.c 543cf0987c27ad59e5a7a6222480b917b5431009b7b139027c9581a63e39e37e
-F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
-F ext/fts5/fts5_vocab.c fbe38044889b2d2d99babeeef239c620fb0332bb928a84506ac748d81500b354
+F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
+F ext/fts5/fts5_test_tok.c f96c6e193c466711d6d7828d5f190407fe7ab897062d371426dd3036f01258e7
+F ext/fts5/fts5_tokenize.c 4d904c237707de8fbb8ab98d24d5c55d47204a3f1f35895d8a53a5327079b32c
+F ext/fts5/fts5_unicode2.c d8a1528c9a19f79b843c486e5e64bff17d667791ae7f658e11131ebac4b33c59
+F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
+F ext/fts5/fts5_vocab.c 906dff069840347e68f654b12ca60a53a27cd1780daf155fbe7dd331f27c2329
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
-F ext/fts5/test/fts5aa.test 840081efaee97f5ec570146bbdd79cfdfaea0ab303de3d5037b6d6c78b42ccdd
+F ext/fts5/test/fts5aa.test 1706f816308e5855fe493be85aa0fd28eea78fb163ab1d60a20bca4f0ebcf68d
F ext/fts5/test/fts5ab.test 9205c839332c908aaad2b01ab8670ece8b161e8f2ec8a9fabf18ca9385880bb7
F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
@@ -136,9 +136,9 @@ F ext/fts5/test/fts5ae.test 1142d16d9cc193894dc13cc8f9c7a8a21411ac61b5567a878514
F ext/fts5/test/fts5af.test 724247405b13f8f06cc6ce464dc4f152dc5dd4e86b12c2099685d8f19747bf7b
F ext/fts5/test/fts5ag.test 7816f25a0707578f08145ab539fc0ca025f8951e788b28a6a18a06b2099469dd
F ext/fts5/test/fts5ah.test 27b5a33bfd0363ca8a4dc659e6e2a5df3dea1c3c5b04bc51ca6aeb1277bd9b21
-F ext/fts5/test/fts5ai.test d837c42249c0d8ad1a2912270e22cf2f303790a611f85c0be3a58e42a3696e3d
+F ext/fts5/test/fts5ai.test bc97e4758cc93e06bf851d61c98fdf4e8b8f8315ee28a84fb15f916360856414
F ext/fts5/test/fts5aj.test 745020852d85f5dd49d11cb7ad11d3cc6dafc4fe6d6d24bc0875ac8f43ee4149
-F ext/fts5/test/fts5ak.test 0d41cbf04e70249c84670e1782aa8972e4f67d91c9bc6205d0ba7c34e159481b
+F ext/fts5/test/fts5ak.test fc3595f8e6873bb86d70c9bd4b67d0413ce577bd4793c39a2b60a7b8825b60a6
F ext/fts5/test/fts5al.test 00c4c1c6a1366b73aa48ce2068c634520867c3cf7f5d1676ebbb775ee1f35734
F ext/fts5/test/fts5alter.test 5565f7e4605512b69171ac18ca84398603f9f6456dbe377beeca97e83cc242cd
F ext/fts5/test/fts5auto.test 78989e6527ce69c9eddbef7392fea5c10b0010cd2b2ae68eec7bc869c471e691
@@ -147,6 +147,7 @@ F ext/fts5/test/fts5auxdata.test eacc97ff04892f1a5f3d4df5a73f8bcbc3955ea1d12c9f2
F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a664fe1e7a8f5fd3
F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
F ext/fts5/test/fts5cat.test daba0b80659460b0cb60bd1f40b402478a761fe7ea414c3c94c2be25568cc33a
+F ext/fts5/test/fts5circref.test f880dfd0d99f6fb73b88ccacb0927d18e833672fd906cc47d6b4e529419eaa62
F ext/fts5/test/fts5colset.test a30473451321bbf0b6218af62e96b4ae5fa99931cfdb210b5ecc804623b30f75
F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f348ca8c1630f9edbf5482
F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
@@ -155,7 +156,7 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 688d5ac7af194ebc67495daea76a69e3cd5480122c2320e72d41241b423b4116
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
-F ext/fts5/test/fts5corrupt3.test ff9aee403611461e2619d2217c0d7d101a9c0179277c13c8a89516d7cf0dda43
+F ext/fts5/test/fts5corrupt3.test 4c506a138797d23049bf08552b4571f5beb5138ab7b3329b9210fe5aac8796d2
F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
@@ -180,6 +181,7 @@ F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b
F ext/fts5/test/fts5integrity.test 4317561cd25eca7df16aa1f7d1a700ee958059fa639785f94aba0a84df9ab17b
+F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8975d15c279374e82e35
@@ -206,16 +208,17 @@ F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074
F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947ec60b6fadbc4b3fb17a
F ext/fts5/test/fts5tok1.test ce6551e41ff56f30b69963577324624733bed0d1753589f06120d664d9cd45c9
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
-F ext/fts5/test/fts5tokenizer.test 6aeb5e8061ffc0ff9a5299f27beaee3b2b4b8b336d4f107262bca338bea8f8e9
+F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
+F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
F ext/fts5/test/fts5unicode2.test 9b3df486de05fb4bde4aa7ee8de2e6dae1df6eb90e3f2e242c9383b95d314e3e
-F ext/fts5/test/fts5unicode3.test c3caecbe8264629ffe653b43ca5790b9793eba4422f92203e5247558e5a534e7
+F ext/fts5/test/fts5unicode3.test 590c72e18195bda2446133f9d82d04a4e89d094bba58c75ae10f4afc6faa0744
F ext/fts5/test/fts5unicode4.test 6463301d669f963c83988017aa354108be0b947d325aef58d3abddf27147b687
F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d
-F ext/fts5/test/fts5update.test 0737876e20e97a6a6abf45de19fc99315727bcee6a83fadcada1cc080b9aa8f0
+F ext/fts5/test/fts5update.test b8affd796e45c94a4d19ad5c26606ea06065a0f162a9562d9f005b5a80ccf0bc
F ext/fts5/test/fts5version.test c8f2cc105f0abf0224965f93e584633dee3e06c91478bc67e468f7cfdf97fd6a
-F ext/fts5/test/fts5vocab.test 2de834ee6405130d3373817ced8fefbfee392b63d932e471740e09829f1e4510
-F ext/fts5/test/fts5vocab2.test d6039b20118e886113fc63614d9ad39a466fc2af34184f3e915b9f92b7ebfa10
+F ext/fts5/test/fts5vocab.test 648fb2fe86b55e08295e34504704718d92fba3e2cf3e1f5d72fa3682df4cd0f0
+F ext/fts5/test/fts5vocab2.test e0fdc3a3095f6eda68ac9bf9a443ff929a124d46f00af19933604085712e9d47
F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
@@ -270,29 +273,31 @@ F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1ded
F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422
F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0
F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
-F ext/misc/amatch.c c0a6a807a553eaa220bf69fca0353cd1587a3bfb3d2224fa425e3e6efcacc98a
+F ext/misc/amatch.c cc9835931fbe46f9c6b8dbb51779c16f169bee50ae372a20532ff5154ebaf5b1
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7
F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2
F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005
-F ext/misc/closure.c 9f8fa11aa6c6e2f6d7296ffa88f103df4b46abd9602bcab3ea2f8fc24f334f63
+F ext/misc/closure.c 037d055c5a4880d41607a3ea44037f655b5e8ac1bdce305ec497903fd2646960
F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f
F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
-F ext/misc/csv.c 88333dc9f7dcf6a8148406f10ae04261e24e3b4c721550ae33e9e71f1265c1f1
-F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a
-F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
+F ext/misc/csv.c 7f047aeb68f5802e7ce6639292095d622a488bb43526ed04810e0649faa71ceb
+F ext/misc/dbdump.c baf6e37447c9d6968417b1cd34cbedb0b0ab3f91b5329501d8a8d5be3287c336
+F ext/misc/eval.c 4b4757592d00fd32e44c7a067e6a0e4839c81a4d57abc4131ee7806d1be3104e
F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f
-F ext/misc/fileio.c e3153b04433897a18a3d17185845f286892e96fdf87f4301290d09c36ae1759f
-F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
+F ext/misc/fileio.c 592d6531d8413d81b25f5a47a45d7e310e455d33e03a64c6ae85724c6524a5d5
+F ext/misc/fuzzer.c 9e79c337faffdd4c5fe4485467537438359b43e0858a40038d4300b894ff553f
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
-F ext/misc/json1.c 3f017d2659e531d021d015ec5d69ea0b1c71f2e15bf9768b1e149fcdf6c3e0b1
-F ext/misc/memstat.c 941928c6104d8ed569a6c47caa756dc78b8091f7a15f87d3004f3b1e576b10da
+F ext/misc/json1.c 8af4672f43634257dbcfdb4515b4070325463d67c6968b4be1bd414de28d4d58
+F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
+F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
-F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
-F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
+F ext/misc/mmapwarm.c 8c5fe90d807a23e44a8b93e96e8b812b19b300d5fd8c1d40a4fd1d8224e33f46
+F ext/misc/nextchar.c 279f80fe8ef5ba413242e2704e246503ac601f005eefb180d19e6c920338a0ba
F ext/misc/normalize.c b4290464f542bae7a97b43f15bd197949b833ffd668b7c313631bd5d4610212c
-F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
-F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
+F ext/misc/percentile.c a6a1594c104da2d0ceab38fe609eb2f65529272377827f6f8a2b5c9fa6119e7e
+F ext/misc/prefixes.c 7be86d17525cfae6ed462fc3c519efc44488ac329890f77491c8f82871f57e17
+F ext/misc/regexp.c 79345bf03496155a640ee0300d3307296761cebb5e115b4e342cc2fb5861ec10
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
@@ -305,13 +310,13 @@ F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983
F ext/misc/stmt.c 8a8dc4675042e4551e4afe99b8d0cc7a4a2fc1a8dacc0a9ce1b1bbff145da93d
F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
-F ext/misc/unionvtab.c acf947858054850db2d4a611bfeae072cdc6d9f517b46a993fe1f2f1ea20031e
-F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
+F ext/misc/unionvtab.c 34ee634d09670909563dbde59c5bfb2ac048b27051f65f1aeac918b061d646d8
+F ext/misc/vfslog.c 3b25c2f56ba60788db247287be6ab024b53c4afffd412b4876db563389be0d35
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
-F ext/misc/zipfile.c 1d731db326c40e11fc608f38132acff31619946c000e85ab8efe75bbedc2a441
+F ext/misc/zipfile.c c1ca8f52330b4564207036b978edac8141c737bf612659bf6f7bee3ddd563a03
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce
F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
@@ -329,7 +334,7 @@ F ext/rbu/rbu9.test 0e4d985e25620d61920597e8ea69c871c9e8c1f5a0be2ae9fa70bb641d74
F ext/rbu/rbuA.test b34a90cb495682c25b5fc03a9d5e7a4fc99541c29256f25e2e2a4f6542b4f5b3
F ext/rbu/rbuB.test 52b07158824c6927b7e25554ace92a695cdebfc296ae3d308ac386984aded9bc
F ext/rbu/rbuC.test 80f1cc2fb74f44b1128fd0ed8eedab3a76fefeb72a947860e2869ef76fc8dc6b
-F ext/rbu/rbu_common.tcl acfb7fbbaf8d46a9f6f6a5ec795616c84d705e1565d918afe43f0ff53ea0efa5
+F ext/rbu/rbu_common.tcl 4b3d033b3e3844292ae3a1aefc0e524e64b0db5a0e4310657919e4504ac3073f
F ext/rbu/rbucollate.test cac528a9a46318cba42e61258bb42660bbbf4fdb9a8c863de5a54ad0c658d197
F ext/rbu/rbucrash.test 000981a1fe8a6e4d9a684232f6a129e66a3ef595f5ed74655e2f9c68ffa613b4
F ext/rbu/rbucrash2.test efa143cc94228eb0266d3f1abfbee60a5838a84cef7cc3fcb8c145b74d96fd41
@@ -347,10 +352,11 @@ F ext/rbu/rbusave.test f4190a1a86fccf84f723af5c93813365ae33feda35845ba107b59683d
F ext/rbu/rbusplit.test b37e7b40b38760881dc9c854bd40b4744c6b6cd74990754eca3bda0f407051e8
F ext/rbu/rbutemplimit.test 7f408f49b90fa0a720d7599f3aec74a3c85e6cd78e56fdf726ce00af9147a341
F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534
-F ext/rbu/rbuvacuum2.test 0a7669bbabdaeed915f02f59f33fe20e13d4932ba2086fe00a82064d9424c80b
-F ext/rbu/sqlite3rbu.c 71f8c09948d09ec9c5a8dbe7127e8ef61ef0853e698b2650be2485ac7b9c75c8
-F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
-F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90
+F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
+F ext/rbu/rbuvacuum3.test 8addd82e4b83b4c93fa47428eae4fd0dbf410f8512c186f38e348feb49ba03dc
+F ext/rbu/sqlite3rbu.c d643661c7c85e79f4d0bc56c73f6f2dd55c35732dd41f378b0fd3b182a33242d
+F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
+F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F ext/repair/checkfreelist.c 0dbae18c1b552f58d64f8969e4fb1e7f11930c60a8c2a9a8d50b7f15bdfd54bd
F ext/repair/checkindex.c 7d28c01a2e012ac64257d230fc452b2cafb78311a91a343633d01d95220f66f3
@@ -361,15 +367,15 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/geopoly.c d56ff997f2646b03be742eb85e8206f779d777f3a282fe0da576780ca0e11f20
-F ext/rtree/rtree.c 7125183bf6c37b8b8ee1a04d2b0fe258531fd31650fdd050ed041817f1943d17
+F ext/rtree/geopoly.c 061432bddc38c4c10c7e4ce940d581c886d65bb5814b4b65b46ad046aa85eaa2
+F ext/rtree/rtree.c 57729cc19f3832e5f9051556af44ed264b5bd54b01543cd7e50d5143817b964c
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
-F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
+F ext/rtree/rtree1.test 7573134f1b4f59df36c1b0a6de51268fd3b9c714d91f3811482263e734e416ea
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
-F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4
+F ext/rtree/rtree6.test 1252a0439da01d2f1f5cbbdeeb80455a2d68b9bae2a9787937b167a5e3957828
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
@@ -384,14 +390,16 @@ F ext/rtree/rtreeH.test aa08cc4fa8005b4c67446c7110205055b4d6da90e760e6f44b82dfa4
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35
+F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
+F ext/rtree/rtreefuzz001.test 836d87653851ae8e7b506d8bd3d62329548adc48ff9bc0a9051efd576710be7b
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1d2f94ac66
-F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
-F ext/session/changesetfuzz.c 255826ee367781ec4c29a36c7c63e9ee6387dc03a8346cf240feb8d597958b0e
+F ext/session/changeset.c d046906a0c9a37862fcd5dbfda5eb08dea361b9abdd959b34358a63fa246164f
+F ext/session/changesetfuzz.c 01023c41cfb02e191d144ea8bfdc46443393b62d13873f5fa044fc9886e60142
F ext/session/changesetfuzz1.test 2e1b90d888fbf0eea5e1bd2f1e527a48cc85f8e0ff75df1ec4e320b21f580b3a
F ext/session/session1.test 0b2f88995832ea040ae8e83a1ad4afa99c00b85c779d213da73a95ea4113233e
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
@@ -410,7 +418,7 @@ F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6d
F ext/session/sessionG.test 3828b944cd1285f4379340fd36f8b64c464fc84df6ff3ccbc95578fd87140b9c
F ext/session/sessionH.test a417559f29a7e775950fc5fc82b3d01256a7cbe793ddf1180df234df823d56e2
F ext/session/session_common.tcl 29ec9910aca1e996ca1c8531b8cecabf96eb576aa53de65a8ff03d848b9a2a8b
-F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723
+F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8be518b62d6cbdef88b3
F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
@@ -418,9 +426,9 @@ F ext/session/sessionfault2.test dd593f80b6b4786f7adfe83c5939620bc505559770cc181
F ext/session/sessioninvert.test ae1a003a9ab1f8d64227dbb5c3a4c97e65b561b01e7b2953cf48683fb2724169
F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
-F ext/session/sessionwor.test 07f0b304dc4df5454906069140bf6ec67edcaa3c548f3683354003cf2c22b64a
-F ext/session/sqlite3session.c dbd6f7a89c1236d8e7b58f4e217391670ce91b9e6f85c16ba02832674ef0cf3c
-F ext/session/sqlite3session.h 05351d2f50a1203fdffbeb590fdbbc796c9a6bfcd0c9b26cf6db3854e3eb4294
+F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d
+F ext/session/sqlite3session.c 4c79daf65e89c78dd62fd97a1b2eac3e53be700b29914101453a0d951f7ba9c8
+F ext/session/sqlite3session.h 54d6356f5769d3695e5f63d719c6ee27671b2614973a2b675a3ff4d30d574233
F ext/session/test_session.c 98797aba475a799376c9a42214f2d1debf2d0c3cb657d9c8bbf4f70bf3fb4aec
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
@@ -428,7 +436,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk eeaa279fa6acdcfa6555058548075569a06f891fd67f5901b1e7700d18052fda
+F main.mk 3930eb2fcbebe49ab7408f6fef3baa8c4bf3c84540f9f29dfe849bf561ff6e51
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -440,44 +448,44 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c f886160da189e4e99093cd5a2aca625652cc9b027d5100b87f81c175d1056387
-F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
-F src/attach.c 92b51739a885da8bd84bc9a05485f1e48148bce5c15432f059b45af98fff75cd
+F src/alter.c cb691d6cd330312b7951c9d3bc0bc29804bbe80beac1cdd137d824b119b6f28a
+F src/analyze.c 58db66344a5c58dcabb57f26696f6f2993956c830446da40b444051d2fdaf644
+F src/attach.c 3f9b0f6c79500cc40f4e543bc130a0b4ee13f52b45cbb6735608776cbdb79f0e
F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c ba7c7eef4461790f37c309936bfc5d0d6ba9b194b02d3c8ff1fd53b420ea6d3b
-F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
-F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
-F src/build.c 127d33ad57b455a9339e9fabff41284c8b030cc6247ca7a2a6c0ad7abfc1ce85
-F src/callback.c 789bd33d188146f66c0dd8306472a72d1c05f71924b24a91caf6bd45cf9aba73
+F src/btree.c 84b7c5c3829b60823e15e7a8407462b69be3818f96518fef28f97ac0fbbca72b
+F src/btree.h 63b94fb38ce571c15eb6a3661815561b501d23d5948b2d1e951fbd7a2d04e8d3
+F src/btreeInt.h cd82f0f08886078bf99b29e1a7045960b1ca5d9d5829c38607e1299c508eaf00
+F src/build.c 906ca6663b9dcd413e72ae9c44dd51e596d8336b04d52e678a7501e71c20cab2
+F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
-F src/dbstat.c 3c8bd4e77f0244fd2bd7cc90acf116ad2f8e82d70e536637f35ac2bc99b726f9
-F src/delete.c f7938125847e8ef485448db5fbad29acb2991381a02887dd854c1617315ab9fb
-F src/expr.c 9aacc0b72348ba90010b672dcbbbe2fa56e1182043bc917a3a147b2bc57a5497
+F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319
+F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf
+F src/expr.c 182dc9ff30aa6a430b7f728ce84fda85ec10890e29fdf75be1e871d13222a99c
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
-F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
-F src/global.c 8291eee0782b83124de14ec0389ec9fd6ae1873358a6b0d9469fe17a46ad803b
-F src/hash.c 931ec82d7e070654a8facb42549bbb3a25720171d73ba94c3d3160580d01ef1f
+F src/fkey.c bd0138acdc008c1845ccf92f8e73787880562de649471804801c06fed814c765
+F src/func.c 0341881d22903aac5ba7f352b188806d6436e1d6ae4235ff01e44d56879dfe63
+F src/global.c 0dea3065ea72a65ae941559b6686aad6516d4913e76fa4f79a95ff7787f624ec
+F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 6b81aae27b196925d8ff78824f4bbd435d6a40cd38dc324685e21735bb402109
-F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
-F src/loadext.c 9050dd153b5583804184be9c9dee9ebb554178d6db1f8ac280899e8aad9060e6
-F src/main.c 4cfb3913cc9e65d3ac649b1785ac753fc225d29425d5437e012f7eac0cefe0eb
+F src/insert.c 3ed9ceaa4b7d56a6f2613355e1cd1ae5cfe31712bce2bf5aa93c5f1f130704b2
+F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
+F src/loadext.c e6f10875d52aca3b7e57ce1ec174aeafc9b6c00b43000cd30d791f9cb490b7a6
+F src/main.c 27d7265625ea6eaccdfe7c53ef41adc179c9357a077702a860c1a3b0a037a16f
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memdb.c cb4013d56fa71c79c498717cbc47b27dd1c7653fd866584b2071ae04114eec46
+F src/memdb.c 02a5fcec19b9d40dd449ca802dc1b2e8f93f255fbf2a886277a3c3800d8d35db
F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604
@@ -493,30 +501,30 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c f6e91b8fd82af7afbfd073c4974ad6cdb8e62d9f65ceddb45167835a0567fdc0
F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 75e0f3cfa3962c714f519f8a3d1e67ecca1c91de0e010a036b988e40ce9e4c73
+F src/pager.c 857dde3e525f665cfab23b6765bf04ca6638c0759ae7da6d63acfb463e230aa6
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
-F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179
+F src/parse.y 741a270b7f2f85bc5d026d06fb5a9ccba5335304ff2831e1cb44b36cd0da6006
F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
-F src/pcache1.c bf9fcea656dce1cd2cca6b77a1d1d3552050d55a31c98bf0d9f405930a83bc95
-F src/pragma.c 4e056f042683b99c4ea0db395f68d051b1a95833ab40951c40d3ef7e1fee1354
-F src/pragma.h fdd03d78a7497f74a3f652909f945328480089189526841ae829ce7313d98d13
-F src/prepare.c f81f8d707e583192c28fea0b2e19385415b7d188123b23f49b038076408d7a69
-F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
+F src/pcache1.c a72804486dfa8e4b6bc30d666c97ecf1155f91a4351fc6e48ea4097e4eb304fb
+F src/pragma.c af67dedaad8bafe9a5f9adcec32a0da6dd118617dd8220ad1d118f5a6bf83a02
+F src/pragma.h a776bb9c915207e9d1117b5754743ddf1bf6a39cc092a4a44e74e6cb5fab1177
+F src/prepare.c 78027c6231fbb19ca186a5f5f0c0a1375d9c2cec0655273f9bd90d9ff74a34b3
+F src/printf.c cbf27c320091a83279d1738f68a27a9fe01698c607ce80516ab6bdb5a9c36a1a
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 4cfc44def0f0690ceaab8f6481f5d76284d7f9509aab6e218a679b4836a54614
+F src/resolve.c c8f207247472c41ac73d738e1c1a80719ad253d1dbb617ed57740492b2a6c097
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f
-F src/shell.c.in 482e23a370cbe5b0d4c73a0f0f5fce34f7caa08a14a8d75e12f0225c4e14915c
-F src/sqlite.h.in cce9feede1c1c03923c091b4bbbd081dd77aaf92024cc2cdbf65f712c2f668c3
+F src/select.c c998f694759e37799929e28df8a2649747f8774d4fc233529ab6bda689388e15
+F src/shell.c.in f2c1adbee3f6f36686b4a38d2168ebfc25298b4ad1e6d95199fc4e95b539251d
+F src/sqlite.h.in 7da74fd5bd7a9dbe92297060f036935520b26e240457287c5e67c7b9db51a986
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
-F src/sqliteInt.h 1161f7579cdd6217737a66517ef27f4016426603eff492e9b31f45a7d7d4c61f
+F src/sqliteInt.h f657e35d824fdc17ddf46bb85f0193df3b965e8354ded9ec37825057e3224bcc
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
-F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6
-F src/test1.c 5390e5afb31fed61f72d0be0cb1b322d198a6e03fc13ff245ae76d17b4dcf2e9
+F src/tclsqlite.c 6b19e7562195aaf881f3e35e2472dc01ae3cb156961db5126c3d616744729b7e
+F src/test1.c 353b066e7ec761c4c715c1c20b888e0e7a0b0c0eda7f68c110e032d63713cade
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@@ -541,7 +549,7 @@ F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71
F src/test_intarray.h d57ae92f420cda25e22790dac474d60961bd0c500cbaa3338a05152d4a669ef7
-F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
+F src/test_journal.c a0b9709b2f12b1ec819eea8a1176f283bca6d688a6d4a502bd6fd79786f4e287
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242
F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
@@ -562,40 +570,40 @@ F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
F src/test_tclsh.c 06317648b0d85a85fd823f7973b55535c59a3156c1ef59394fe511f932cfa78d
F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858
-F src/test_vfs.c 112f1f9271c33c211812e0e681830a84262dac065da58579ff49f9cefec97d4f
+F src/test_vfs.c c6c6a58f66b26876c7b5769fb323a58b2c7120299b5084e7212c4116f902cbaa
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
-F src/tokenize.c 9e781e1ca80eefe7b5d6a9e2cd5c678c847da55fd6f093781fad7950934d4c83
-F src/treeview.c 7b12ac059de54c939b6eb0dbffc9410c29c80d2470cee5cbe07d5ff9ea2d9253
-F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
-F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274
+F src/tokenize.c 0a065eaa31f494ba31ac21d4a5d24a5a7865a7d849459f8c6266df1ac6b9aedf
+F src/treeview.c c6ff90da4cc1813ff2d9bb11f17d4d927db62c47e552faa1835edc47269d753d
+F src/trigger.c bb034c08eca111e66a19cda045903a12547c1be2294b5570d794b869d9c44a73
+F src/update.c 0b973357d88092140531e07ff641139c26fb4380b0b9f5ed98c5f7691b4604d1
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
-F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
-F src/vacuum.c 836cadc922de866c849e23a75f93d344cdc143d388339305d09a3fed27e8798d
-F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b
-F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
-F src/vdbeInt.h 437e6c6af679fdf157867eb83a8adc6cf5145d6774453c2214cfd0bd01d92980
-F src/vdbeapi.c ecccfce6f614c33a95952efeec969d163e8349eac314ee2b7b163eda921b5eb0
-F src/vdbeaux.c f547901b1aa9e2d81c63f06893f633648e434180666a827aacb547d7d6c8a601
+F src/util.c 82a2e3f691a3b654be872e305dab1f455e565dedf5e6a90c818c1ab307c00432
+F src/vacuum.c a9f389f41556c0ec310bc9169dc9476603c30a0a913ad92bfbc75c86886967ca
+F src/vdbe.c b7b6f965153607072917dbd81d654a268abf4872c58d556701d1549550766c02
+F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
+F src/vdbeInt.h a76d5eed62c76bcd8de7afd3147fac1bc40c5a870582664bcd7d071ef437c37f
+F src/vdbeapi.c 57a2d794a8833f269b878dbc24e955369bdb379af6c4e93ebc5ce1a20fa3daf4
+F src/vdbeaux.c 4fa28b32452f6197dba7c8780dde11576b9a6d8ce6f35adbb69efc3e7d37fa0c
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
-F src/vdbemem.c 7b3305bc4a5139f4536ac9b5f61da0f915e49d2e3fdfa87dfdfa9d7aba8bc1e9
+F src/vdbemem.c 3173f0275cf8643a03ed02084ee56b97fc1a17a2edb5907facec504f59c3172d
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
-F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa
+F src/vtab.c 2462b7d6fd72b0b916477f5ef210ee49ab58cec195483ebdac0c8c5e3ec42cab
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
-F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
-F src/where.c 3818e8a736a05d2cb194e64399af707e367fbcc5c251d785804d02eaf121288e
-F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
-F src/wherecode.c c45f03aefc2266b990df0fc4d7acc4e27f56f881f4fc0fc355b7cbc4d7189da5
-F src/whereexpr.c 491f0894ad9903750cdecb7894437a0cabdffdd88f574d2b1c9ac85d14fe4b9c
-F src/window.c 6550e2850ebced51100ef83d49b00a1cf03f81a482dafedafb0320df647ed8fc
+F src/walker.c 7607f1a68130c028255d8d56094ea602fc402c79e1e35a46e6282849d90d5fe4
+F src/where.c 8a207cb2ca6b99e1edb1e4bbff9b0504385a759cbf66180d1deb34d80ca4b799
+F src/whereInt.h 5f14db426ca46a83eabab1ae9aa6d4b8f27504ad35b64c290916289b1ddb2e88
+F src/wherecode.c a571d8d7c19d6db786a201f2df8788b320fefcb2842f2a1eb9a85b85e91bc35f
+F src/whereexpr.c 36b47f7261d6b6f1a72d774c113b74beddf6745aba1018e64b196e29db233442
+F src/window.c df2456386e0b1553a8d1fcf3a0ddc4c058fe2c650ea8c74b6bf8862082ddafc9
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -609,12 +617,13 @@ F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499
-F test/altercol.test 313ed080ed61691c52cd87053129889f71582d6d0efebdd5f3edad2a98c66874
+F test/altercol.test 54374d2ba18af25bb24e23acf18a60270d4ec120b7ec0558078b59d5aa1a31ad
F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
-F test/altertab.test 17e46baa6b2234048c91891a303141afceca4da95a36ee1a0a9fec6ccef1f4da
-F test/altertab2.test 0d64de5632ca5de13b023839cfe5b8952d029e4622befcea1433adaa93883220
+F test/altertab.test 6e13f13d8c30708f16187908c31dadb1bfff9e3cb2a07a7392a7a5e076f58f4a
+F test/altertab2.test 7bedde2e6e71fdecd7a2af64b696cd0b3d3a344f5cf1db6785d9e3b5665193cf
+F test/altertab3.test 9dd97ab8161eb6afc0e30e7c61a38336687fbd09e6ddc4c9f1e450cc0b12160b
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 7168c8bffa5d5cbc53c05b7e9c7fcdd24b365a1bc5046ce80c45efa3c02e6b7c
F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8
@@ -650,7 +659,7 @@ F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
F test/autoinc.test 381f494fefa90acd999933829e2934efb6b40906db9d6a39e822e3f7b4c8bf61
-F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0
+F test/autoindex1.test 96185415f5faacd5b8d7a7f505efddd5abb1f111d58338e9c0b1dc40b87cd3cc
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
@@ -670,7 +679,7 @@ F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a
F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
-F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
+F test/bestindex3.test 7622e792ff2da16d262d3cea6ad914591ac4806d57ed128e6c940b7920b47b84
F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601
F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
@@ -693,7 +702,7 @@ F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45
F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
-F test/btree02.test a0f33669ba76632247c14718af32db939fa6de5cd13890798ad3f2a362cf7fe4
+F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1d6cc
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
@@ -724,7 +733,7 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
F test/colname.test fb28b3687e03625425bc216edf8b186ce974aa71008e2aa1f426a7dcb75a601d
-F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db
+F test/conflict.test c7cc007e2af151516ddf38f7412fe10d473a694f55e3df437e2c7b31c2590e8d
F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
@@ -748,7 +757,8 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
F test/corruptK.test 5ef338c560ca4dfb7360828da16f1829be4deba3b378cafdc7a1cdaf027eb5c4
-F test/cost.test b37db8a10d467a69e71a9f3d40bbb266c2f587742b37c6912f6e3f7185a0e216
+F test/corruptL.test 0f64242b83db6d0bd5b6e38c205bf7c2a3bc6c9f80351f49c4dee1639aca60d8
+F test/cost.test 51f4fcaae6e78ad5a57096831259ed6c760e2ac6876836e91c00030fad385b34
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
F test/countofview.test e3d4cd6900e4e4f074968ab24b8b87d3671cd624961bef40fd3a6b8f574343cf
F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
@@ -764,7 +774,7 @@ F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
-F test/csv01.test 4a92840619ef435b905e6d3f35cd0644df23225d7b7967d7940b40f06d6a90a6
+F test/csv01.test c9c3af0d58c34e9ac970c5875a77939edb958762c8aafb95409e19a3f088b6cd
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
@@ -772,8 +782,9 @@ F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
+F test/dbfuzz001.test 29b6c6b39a701b6b5b08035c637674b76e1ecea515b1a184b29e3bd0f2d02dad
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
-F test/dbfuzz2.c 652f85bac1770e927da139db513234a3eba308f72ac2f8b32f0093d7d19def70
+F test/dbfuzz2.c 5d5eb817dc8195e0228227510ee6a4b49f46e679fc2d5be96841cce819bf42f7
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
F test/dbstatus.test cd83aa623b8aab477269bc94cf8aa90c1e195a144561dd04a1620770aaa8524e
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
@@ -805,7 +816,7 @@ F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5e
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164
F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
-F test/e_select.test c5a669b4d63217aa10094ba737ba3ddd07bd439d4bc7a5b798f6ea32511cbe7c
+F test/e_select.test f9474205669a7736ef725b29cc7ae9e8601919a3d0ffc0ab30745a028f2a4b61
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
@@ -820,7 +831,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
-F test/eqp.test fc00ad1a7f5b90bf1bbccbf877ae9abef8bf5c7896174830d438c8f91a6ead88
+F test/eqp.test 84879b63e3110552bf8ce648a3507dc3ceb72109ecec83c2aef0db37a27f6382
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3
@@ -830,7 +841,7 @@ F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/expr.test 7cb55e80aeb41d65fec968c08212505123063fea60bdc355d764d747670e9eea
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
-F test/fallocate.test 07416bd593a116d5893cb244f45a94d5c6fe030561df3bd972e6135f8106e509
+F test/fallocate.test 37a62e396a68eeede8f8d2ecf23573a80faceb630788d314d0a073d862616717
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768
@@ -840,7 +851,7 @@ F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a
F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0
F test/fkey7.test 24076d43d3449f12f25503909ca4bfb5fc5fefd5af1f930723a496343eb28454
-F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c
+F test/fkey8.test 863c6d84f0d289fd2c1a1c293abb9803f77efd35211d9012c0986c8f6ccf5d5a
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
F test/fordelete.test eb93a2f34137bb87bdab88fcab06c0bd92719aff
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -880,8 +891,8 @@ F test/fts2q.test b2fbbe038b7a31a52a6079b215e71226d8c6a682
F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
-F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
-F test/fts3aa.test f267fcd6aca30fc70b81e5d82b68b34b38f581896020b57ed49e9777c7ebd85f
+F test/fts3_common.tcl dffad248f9ce090800e272017d2898005c28ee6314fc1dd5550643a02666907a
+F test/fts3aa.test 814d60a1ba30b4a71d8f9306a6564bc7b636dd6efacd2ad80306f9b23ef3ebee
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
@@ -899,7 +910,7 @@ F test/fts3ao.test 266989148fec6d9f1bb6c5382f7aa3dcea0e9cd444576e28dd2b9287ac7dd
F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1
F test/fts3auto.test 19097050a3ca7ab7a43b2be967cb3dfd8ddf841dfdc4eac88deb172ad2f209f2
F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6
-F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
+F test/fts3aux2.test 2459e7fa3e22734aed237d1e2ae192f5541c4d8b218956ad2d90754977bf907f
F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
@@ -907,7 +918,7 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f
F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae
F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3
F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
-F test/fts3corrupt4.test a27259f4f25d60b4eca481d050b3cfee97eddb0d937d38f231408c5239066e11
+F test/fts3corrupt4.test ff7313656c4ad446e61c41e5cb81336441eaaafe6f4fd6938f1c3ac0c985045e
F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338
F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
@@ -919,10 +930,11 @@ F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c7
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8
F test/fts3expr4.test cac5dd815fe6b5921741abdccdde3b7f50b86394de91e13308ee7986859c4a9f
-F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
-F test/fts3fault.test 9fb7d6266a38806de841f7244bac1b0fe3a1477184bbb10b172d19d2ca6ad692
+F test/fts3expr5.test 1368738e3298a7ce0dee3a44d6ebb8f468b2a76f3d1dd18d4ea6d8bc2eeccc1b
+F test/fts3fault.test 798e45af84be7978ca33d5bdc94246eb44724db24174b5d8e9b1ac46c57fb08d
F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
+F test/fts3fuzz001.test e3c7b0ce9b04cc02281dcc96812a277f02df03cd7dc082055d87e11eb18aaf56
F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
@@ -935,7 +947,7 @@ F test/fts3query.test ca033ff2ebcc22c69d89032fb0bc1850997d31e7e60ecd26440796ba16
F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
-F test/fts3snippet.test 8cf586fe4b6878192602a81a665448aacbbad80ade0867bb5299d40e73584311
+F test/fts3snippet.test dace744104d1a44dc12dc9dd10b8d7542342df503d96942b7c4a55034e761789
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
@@ -956,6 +968,7 @@ F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a
+F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test 09dda479bcfc568f99f3070413e9672a8eeedc1be9c5d819bf55d4788c2583b7
@@ -968,16 +981,18 @@ F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
+F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c fda41c0e4e667fae96b002410bb19cece7a33314264ed6bbc6d012909ee9fd58
+F test/fuzzcheck.c 7ab35ca464fa0fa9c8340b71f08a16c50c14b961264c172cc3d1a67289b2800d
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
-F test/fuzzdata7.db a1bf54eb455e9772942abae1b2d1cf1e3d3659f0e5dd14f00792fd01411ae8ef
+F test/fuzzdata7.db 3fc78e65dfe0be9df9e262075d5a335f18f627da47dfc691d1a7b822f34d4b99
+F test/fuzzdata8.db 3f7c67741ba91c13955609700a44608d2dfe4f037e508f77d236ea9abb431a02
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
@@ -1013,20 +1028,21 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
-F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a617d
+F test/index6.test 6b3e6cd4bef343ed4541e74c55936ed112962a6552c085242612b598e12910a4
F test/index7.test 72b59b8ddc5c13f4962886b4011eb9975014317d17ef36c6297921362fb7dd98
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
-F test/indexexpr2.test fc994dcd4b3da932d4add8e65ed7ca08166d541e00a46874cfacd98dfb93a31b
+F test/indexexpr2.test 38020c247ee77ba19322fadde99db84bdf2aef34f714866786563c3834bb2dce
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
-F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a
+F test/insert.test 9773604f8e1a2595f51488a5643c359d8a11dc55a11cb185910d93387d378458
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test 46bead5f39e181850ee56adcf49d3a3157c460c52249211714612ac89fe34835
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
+F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c776e4a7f74
F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba
F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a
F test/intarray.test 8319986182af37c8eb4879c6bfe9cf0074e9d43b193a4c728a0efa3417c53fb7
@@ -1041,11 +1057,11 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test 62372ad3ddcc5d0eb8ff9097dcb0aad8961bf1b9cb45ba634f6e284695126f9a
-F test/join.test 2ad9d7fe10e0cc06bc7803c22e5533be11cdadbc592f5f95d789a873b57a5a66
+F test/join.test d53a3662762eff50b65da8775201e609878a27dd0885a1ae7bcde9bb46cecbc5
F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
-F test/join5.test 5a2da0c3ea852a7063d3e72fc7d5a04a6de5ef6e6d85092582f69033f7459adc
+F test/join5.test f8b5ffdf3c1513486b52ad4e49225507ecee5005f210eb18688f791d25370972
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
@@ -1053,7 +1069,7 @@ F test/journal3.test c9c29883f5bf535ae82ae21c472df6263806a22e467b6db7cd0d6d54530
F test/jrnlmode.test a6693f2bed4541a21e703aaa37bb3e10de154130645952933b82b2dec0a8b539
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
-F test/json101.test b40a9f5395d8e669b0bc3eb550ad2ae9e5ada01fbce23c446c2a30a305a6d575
+F test/json101.test 8f8977b00ba02f9a26c1d1f52f29f540f6d5eb162cbd5eb78bb805366d4ab26d
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
@@ -1076,7 +1092,7 @@ F test/lock4.test 27143363eda1622f03c133efc8db808fc331afd973486cb571ea71cd717d37
F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
-F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
+F test/lock_common.tcl 2f3f7f2e9637f93ccf609df48ef5b27a50278b6b1cd752b445d52262e5841413
F test/lookaside.test 5a828e7256f1ee4da8e1bdaa03373a3ccdb0f1ff98dfa82e9b76cb41a45b1083
F test/main.test 6bbb3999fd461eb8fb335cbab97409a3d7f91bbb8da60635e8be3e4a04a77772
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
@@ -1107,7 +1123,7 @@ F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0f
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
-F test/memdb1.test 61aa1dbdeea6320791d2ff42a9a6149d5716be674bf06ee0ffa0aad1bf3eb5f8
+F test/memdb1.test 0632e6ea56c48e3c6e9b0c73e120310bad8f93762543f809e267888f5a37943f
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
@@ -1115,13 +1131,13 @@ F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
F test/minmax2.test dae92964ac87c1d2ef978c582e81a95e11c00f1cbef68980bfb2abaf10315063
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
-F test/misc1.test c8cfd1c3f842b3341fda9d81a96236d5c76ca89973aeff3fe50bac6fefcfc421
+F test/misc1.test 7ce84b25df9872e7d7878613a96815d2ba5bc974ac4e15a50118dde8f3917599
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
F test/misc5.test c4aeaa0fa28faa08f2485309c38db4719e6cd1364215d5687a5b96d340a3fa58
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
-F test/misc7.test 10d639a5e0fdf1bd51ad42be705393a38780ad71b6957110035a4e6c1e5e7f40
+F test/misc7.test 4f21954012e4eb0a923c54a311f38c81bf6798ccdd7b51584db46d4007f63daa
F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
@@ -1140,7 +1156,7 @@ F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
-F test/normalize.test 6a80564d2000702b5919ed2c1069fef0f95762142bc96a71b4c124a845165713
+F test/normalize.test 422027884ffb67ebba32bb78487c67cf67643496d19c077b07044bdba071a3f6
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
@@ -1163,7 +1179,7 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace
-F test/ossfuzz.c 273eaea2d65b70d77ea4f01404114b9e0244488943f768dc39458c72bd722e0e
+F test/ossfuzz.c 18af635fa73d12a109b305faca727a734c1fa28a421b161d9d15c5a84a4998a2
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
F test/pager1.test 1e9ee778bdeaf4f7f09997d029cdaca6a42dfc2092edafe4f5e590acbf1eab13
@@ -1179,7 +1195,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test cf0b4e498db1d0143c19641d4420df7cc27fab2c95ed0abd2c7c5753beab25b8
+F test/permutations.test 52d2c37fe8cc07ec7362024c214b04bb69432995b3a984a3fbabc60fa6ada3ee
F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30
F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@ -1187,6 +1203,7 @@ F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c
F test/pragma4.test 52d8186f9e8d09b87189432cdd401dfa66d0b32445e837fa19046c8ae7621b0e
F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
+F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
@@ -1205,8 +1222,8 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
-F test/releasetest.tcl b290d538ffcb2ff711f09eadc7396c1a42580f3fb078605471dc8875ca0b4d1e x
-F test/resetdb.test 373a9eb8fcbd58bf87affec6a88c6353038f98a5d25be5ab75a0b9636c462a36
+F test/releasetest.tcl 7712811e0f4e2f198ec786cb2e1352b3793d7395f48a3cceef0572d8823eb75e x
+F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
@@ -1217,7 +1234,7 @@ F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d
F test/rowvalue.test b8680f07d19c8c5223b808bba998faffcec6d505f5689ff6070280119173bb51
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
-F test/rowvalue4.test 2b20468da3775aba971caf3158e9696a4d99c69a7623fb495f332a596daebbee
+F test/rowvalue4.test 02e35f7762371c2f57ebd856aa056eac56cb27ef7715a0bb31eac1895a745356
F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8
@@ -1243,7 +1260,7 @@ F test/schema6.test e4bd1f23d368695eb9e7b51ef6e02ca0642ea2ab4a52579959826b5e7dce
F test/schemafault.test 1936bceca55ac82c5efbcc9fc91a1933e45c8d1e1d106b9a7e56c972a5a2a51e
F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2ff09384
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
-F test/select1.test 2e760bab8f3658b3b97debcf52860d0d2e20aa6cbe8b40e678ddb99871a15491
+F test/select1.test 7d41f354998524070317207d4e2b68e725e4cf14a57835fc746d4bea686a8714
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
@@ -1275,14 +1292,15 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
-F test/shell1.test d2bf5daeb6f449f0169c9ef3094db17a16a02199c5dcf1a635a3e79b07eb0edd
+F test/shell1.test 0378c4e9e800da6fbb3c86c0c8f2cf5efc9e4155b4b6447d27dc71de648fc0a1
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
-F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
+F test/shell4.test 1c6aef11daaa2d6830acaba3ac9cbec93fbc1c3d5530743a637f39b3987d08ce
F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shell8.test 96be02ea0c21f05b24c1883d7b711a1fa8525a68ab7b636aacf6057876941013
+F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
@@ -1296,7 +1314,7 @@ F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
-F test/snapshot_fault.test 508ae6f211d4991e9ff3b5080aeb0a179bf6755138aabeac4bca8083044d895a
+F test/snapshot_fault.test f6c5ef7cb93bf92fbb4e864ecc5c87df7d3a250064838822db5b4d3a5563ede4
F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c
F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
@@ -1343,7 +1361,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
-F test/tabfunc01.test 54300134f76db817685194d2f0e63e3fbf7380b45e0d426e00a9aee752497cfb
+F test/tabfunc01.test 20e98ffe55f35d8d33fd834ca8bf9d4b637e560af8fcd00464b4154d90a4db45
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1355,7 +1373,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl fa5656391e3b477508abe12b3b81f019b2e71397399ab38a2f32d8d7f3bf8e56
+F test/tester.tcl 499a5086815aa416d971ff438d7425c64f41ed3233251db4836d270f9a6671e8
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1530,10 +1548,10 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
-F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
+F test/triggerC.test c7fbc3eb241b5a7ba4b0815f76c3708483e91890f9573add12a610c45b2a6022
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
F test/triggerE.test ede2e4bce4ba802337bd69d39447fa04a938e06d84a8bfc53c76850fc36ed86d
-F test/triggerF.test 6a8c22bd058cf467f0c7d112afe87f7a8c579c0c4681b914b8f19020f48528a4
+F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad
F test/triggerG.test d5caeef6144ede2426dd13211fd72248241ff2ebc68e12a4c0bf30f5faa21499
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
@@ -1543,14 +1561,14 @@ F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
-F test/unionvtab.test 5ae0f0b4f302a4c6bb310b64386f9ac6a4c1c271c08f31cc7c5d92722e2b2729
+F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4
F test/unionvtabfault.test e8759f3d14fb938ce9657e2342db34aeac0fb9bc1692b0d1ebb0069630151d06
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981
F test/update.test 1148de8d913e9817717990603aadeca07aab9ddbb10a30f167cbfd8d3a3ccb60
-F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e
+F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3
F test/upsert1.test 994bde41800bb77dbe32fcd2e1f6c4b49cc9f2c6cd345731c774dff02b51c110
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
@@ -1560,6 +1578,7 @@ F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
+F test/vacuum-into.test 41d84c0603f3e8f3540321e5974d69008c562238c30924a9390c211a8c0a415e
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
@@ -1590,7 +1609,8 @@ F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca675
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
-F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
+F test/vtabdrop.test 65d4cf6722972e5499bdaf0c0d70ee3b8133944a4e4bc31862563f32a7edca12
+F test/wal.test cdf0ca6cc0447520d19ef1c83287824ebeb3e82d75af856511ba96841a79fc9b
F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918
F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
@@ -1610,6 +1630,7 @@ F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af
F test/walcrash4.test e7b6e7639a950a0cca8e210e248c8dad4d63bf20
F test/walfault.test 09b8ad7e52d2f54bce50e31aa7ea51412bb9f70ac13c74e669ddcd8b48b0d98d
+F test/walfault2.test e039ac66c78d5561683cacde04097213cdad3b58e2b3f3fe1112862217bfd915
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
F test/walmode.test cd6e7cff618eaaa5910ce57c3657aa50110397f86213886a2400afb9bfec7b7b
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
@@ -1623,15 +1644,16 @@ F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cf
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
+F test/walvfs.test c0faffda13d045a96dfc541347886bb1a3d6f3205857fc98e683edfab766ea88
F test/where.test 8215d220633f08da331781cf9ede7fb7aed50eb113473c10acd39a643fd258ba
F test/where2.test 478d2170637b9211f593120648858593bf2445a1
F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
-F test/where7.test e579da972eb3372edc9de850efc221848c763f9e4feafc8426d84a4453b92b23
+F test/where7.test 75722434c486ac9e74718caa6cce234f45ba34c0b6c0f9555b29eb8bb5f6ade1
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
-F test/where9.test ad2ddb339d10d324763c3da60502b8631f15a2397b869192fbd4e82f40e167d3
+F test/where9.test 4fb43ad451758d9535693e110d4398fb6a6e3e153dc57bba5e61f884566c725f
F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
@@ -1640,7 +1662,7 @@ F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
F test/whereG.test 0158783235a6dd82fc0e37652b8522b186b9510594ac0a4bff0c4101b4396a52
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
-F test/whereI.test b7769ee8dbefd987fb266715fee887f05f9ff180016b06fca7fa402df739193b
+F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364
F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
F test/whereL.test 0a19fc44cd1122040f56c934f1b14d0ca85bde28f270268a428dd9796ea0634c
@@ -1653,7 +1675,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test 02e481ac48c445b43bab7b3cf1e4115165b5127a1aa29e14f5372922c836f1a4
+F test/window1.test 2798c8249e0f122c9bacce6aa7324765a5cd9106e49e7aacc81f6033d281577b
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823
@@ -1663,9 +1685,9 @@ F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c19
F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e
F test/window6.test 5eae4ae7a590ccf1e605880969ca0bad3955616ac91cad3031baea38748badb3
F test/windowfault.test 12ceb6bbb355d13e8fcd88c5731a57256dfdf77b9a7ae20842a76fcd4623df5b
-F test/with1.test 2465d98ffce80d00553ac7135697c18b0369275b6ecc750daa2af320b8c812ca
+F test/with1.test a07b5aad7f77acdf13e52e8814ea94606fcc72e9ea4c99baf293e9d7c63940be
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
-F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
+F test/with3.test 8d26920c88283e0a473ceebd3451554922108ce7b2a6a1157c47eb0a7011212c
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f
@@ -1676,7 +1698,7 @@ F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
F test/wordcount.c d721a4b6fae93e6e33449700bce1686bc23257c27425bc3ef1599dc912adec66
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
-F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
+F test/zeroblob.test 07a5b11ab591d1f26c626945fb7f228f68b993533b2ada77273edf6ee29db174
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
F test/zipfile.test b3b558639f7a103e095713ad0f57fec1fce1b7d60c8054df5789b98f7547a395
F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d
@@ -1690,6 +1712,8 @@ F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/dbhash.c a06228aa21ebc4e6ea8daa486601d938499238a5
+F tool/dbtotxt.c 04e25f26be7c7743cdfb4111a8483de0b111925d6afeeb7559ade0ceb73f7f52
+F tool/dbtotxt.md c9a57af8739957ef36d2cfad5c4b1443ff3688ed33e4901ee200c8b651f43f3c
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
@@ -1697,9 +1721,10 @@ F tool/fuzzershell.c e1d90a03ca790d7c331c2aae08ca46ff435f1ae1faa6cb9cc48f4687c18
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
+F tool/index_usage.c 9ec344d29cbeb03fdc0fce668eedfb7495792170de933adf95cf8d6904a166ad
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 60d1e1eb0f7ebae709f68f1472d77fbf291c5345cd98ff417219da7e74fd09e9
-F tool/lempar.c 452f12d40229847634a160e5666b6c4ec4392fd81941c3443861b48d497054cc
+F tool/lemon.c 900a15b9efba9890d10e7959914db94c4ad5162912127f061c4328add122d6fb
+F tool/lempar.c 61af95b8fac2bfd59c09d55330e78f3f5e352d7aa80bf37404b96ef795be3fdc
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1712,7 +1737,7 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
-F tool/mkpragmatab.tcl a1334e70a08fdf5de32cd0093613212bb11ac8f880487540987175c536ac335f
+F tool/mkpragmatab.tcl 49039adedafbc430d2959400da2e0e8f20ef8dcf6898e447c946e7d50ef5906b
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1779,11 +1804,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 23684cb841ac2cb0d69e5470253bd96feb733762a7553b952a08470834fe85fa
-R dcc394af10af6094607f56a6086fb748
+P d5d944d7947d7b44ba9a1c844418af49c5f39dbe84f181af790bb1412daed578
+R 2251df76230cd55e64293ef8a825ebab
T +bgcolor * #d0c0ff
T +sym-release *
-T +sym-version-3.26.0 *
+T +sym-version-3.27.1 *
U drh
-Z 560a5decbb241d53eb97e72267b6e6e8
+Z 4aa002629995b65b1d5f498ebad69e25
# Remove this line to create a well-formed manifest.
diff --git a/chromium/third_party/sqlite/src/manifest.uuid b/chromium/third_party/sqlite/src/manifest.uuid
index 166b1b3d3af..68364f77ee9 100644
--- a/chromium/third_party/sqlite/src/manifest.uuid
+++ b/chromium/third_party/sqlite/src/manifest.uuid
@@ -1 +1 @@
-bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9
+0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959a1dd
diff --git a/chromium/third_party/sqlite/src/src/alter.c b/chromium/third_party/sqlite/src/src/alter.c
index fcddc40d0c5..408270854a6 100644
--- a/chromium/third_party/sqlite/src/src/alter.c
+++ b/chromium/third_party/sqlite/src/src/alter.c
@@ -28,9 +28,16 @@
**
** Or, if zName is not a system table, zero is returned.
*/
-static int isSystemTable(Parse *pParse, const char *zName){
- if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
- sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
+static int isAlterableTable(Parse *pParse, Table *pTab){
+ if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ || ( (pTab->tabFlags & TF_Shadow)
+ && (pParse->db->flags & SQLITE_Defensive)
+ && pParse->db->nVdbeExec==0
+ )
+#endif
+ ){
+ sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
return 1;
}
return 0;
@@ -126,7 +133,7 @@ void sqlite3AlterRenameTable(
/* Make sure it is not a system table being altered, or a reserved name
** that the table is being renamed to.
*/
- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_rename_table;
}
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
@@ -424,7 +431,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
goto exit_begin_add_column;
}
- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
goto exit_begin_add_column;
}
@@ -526,7 +533,7 @@ void sqlite3AlterRenameColumn(
if( !pTab ) goto exit_rename_column;
/* Cannot alter a system table */
- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column;
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
/* Which schema holds the table to be altered */
@@ -781,13 +788,30 @@ static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
}
/*
+** Iterate through the Select objects that are part of WITH clauses attached
+** to select statement pSelect.
+*/
+static void renameWalkWith(Walker *pWalker, Select *pSelect){
+ if( pSelect->pWith ){
+ int i;
+ for(i=0; i<pSelect->pWith->nCte; i++){
+ Select *p = pSelect->pWith->a[i].pSelect;
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pWalker->pParse;
+ sqlite3SelectPrep(sNC.pParse, p, &sNC);
+ sqlite3WalkSelect(pWalker, p);
+ }
+ }
+}
+
+/*
** This is a Walker select callback. It does nothing. It is only required
** because without a dummy callback, sqlite3WalkExpr() and similar do not
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
- UNUSED_PARAMETER(pWalker);
- UNUSED_PARAMETER(p);
+ renameWalkWith(pWalker, p);
return WRC_Continue;
}
@@ -937,7 +961,6 @@ static int renameParseSql(
rc = sqlite3RunParser(p, zSql, &zErr);
assert( p->zErrMsg==0 );
assert( rc!=SQLITE_OK || zErr==0 );
- assert( (0!=p->pNewTable) + (0!=p->pNewIndex) + (0!=p->pNewTrigger)<2 );
p->zErrMsg = zErr;
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
@@ -1120,6 +1143,7 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
}
sNC.ncFlags = 0;
}
+ sNC.pSrcList = 0;
}
}
}
@@ -1157,11 +1181,15 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
*/
static void renameParseCleanup(Parse *pParse){
sqlite3 *db = pParse->db;
+ Index *pIdx;
if( pParse->pVdbe ){
sqlite3VdbeFinalize(pParse->pVdbe);
}
sqlite3DeleteTable(db, pParse->pNewTable);
- if( pParse->pNewIndex ) sqlite3FreeIndex(db, pParse->pNewIndex);
+ while( (pIdx = pParse->pNewIndex)!=0 ){
+ pParse->pNewIndex = pIdx->pNext;
+ sqlite3FreeIndex(db, pIdx);
+ }
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->zErrMsg);
renameTokenFree(db, pParse->pRename);
@@ -1272,6 +1300,9 @@ static void renameColumnFunc(
for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
+ for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
+ sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
+ }
}
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
@@ -1358,12 +1389,17 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
+ if( pSrc==0 ){
+ assert( pWalker->pParse->db->mallocFailed );
+ return WRC_Abort;
+ }
for(i=0; i<pSrc->nSrc; i++){
struct SrcList_item *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
}
+ renameWalkWith(pWalker, pSelect);
return WRC_Continue;
}
diff --git a/chromium/third_party/sqlite/src/src/analyze.c b/chromium/third_party/sqlite/src/src/analyze.c
index 6fbf46a9d2c..2b324ec8130 100644
--- a/chromium/third_party/sqlite/src/src/analyze.c
+++ b/chromium/third_party/sqlite/src/src/analyze.c
@@ -1156,7 +1156,7 @@ static void analyzeOneTable(
addrNextRow = sqlite3VdbeCurrentAddr(v);
if( nColTest>0 ){
- int endDistinctTest = sqlite3VdbeMakeLabel(v);
+ int endDistinctTest = sqlite3VdbeMakeLabel(pParse);
int *aGotoChng; /* Array of jump instruction addresses */
aGotoChng = sqlite3DbMallocRawNN(db, sizeof(int)*nColTest);
if( aGotoChng==0 ) continue;
diff --git a/chromium/third_party/sqlite/src/src/attach.c b/chromium/third_party/sqlite/src/src/attach.c
index fcb05046de2..02af65ce3ea 100644
--- a/chromium/third_party/sqlite/src/src/attach.c
+++ b/chromium/third_party/sqlite/src/src/attach.c
@@ -155,8 +155,8 @@ static void attachFunc(
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
- sqlite3_free( zPath );
db->nDb++;
+ pNew->zDbSName = sqlite3DbStrDup(db, zName);
}
db->noSharedCache = 0;
if( rc==SQLITE_CONSTRAINT ){
@@ -184,7 +184,6 @@ static void attachFunc(
sqlite3BtreeLeave(pNew->pBt);
}
pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName);
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
rc = SQLITE_NOMEM_BKPT;
}
@@ -212,15 +211,19 @@ static void attachFunc(
break;
case SQLITE_NULL:
- /* No key specified. Use the key from the main database */
- sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
- if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
- rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
+ /* No key specified. Use the key from URI filename, or if none,
+ ** use the key from the main database. */
+ if( sqlite3CodecQueryParameters(db, zName, zPath)==0 ){
+ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
+ if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
+ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
+ }
}
break;
}
}
#endif
+ sqlite3_free( zPath );
/* If the file was opened successfully, read the schema for the new database.
** If this fails, or if opening the file failed, then close the file and
diff --git a/chromium/third_party/sqlite/src/src/btree.c b/chromium/third_party/sqlite/src/src/btree.c
index eaff20b24e2..773be164691 100644
--- a/chromium/third_party/sqlite/src/src/btree.c
+++ b/chromium/third_party/sqlite/src/src/btree.c
@@ -804,11 +804,12 @@ static int btreeMoveto(
UnpackedRecord *pIdxKey; /* Unpacked index key */
if( pKey ){
+ KeyInfo *pKeyInfo = pCur->pKeyInfo;
assert( nKey==(i64)(int)nKey );
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
- if( pIdxKey->nField==0 ){
+ sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+ if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_done;
}
@@ -844,7 +845,7 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
- pCur->skipNext |= skipNext;
+ if( skipNext ) pCur->skipNext = skipNext;
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
pCur->eState = CURSOR_SKIPNEXT;
}
@@ -914,7 +915,6 @@ int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
if( pCur->eState!=CURSOR_VALID ){
*pDifferentRow = 1;
}else{
- assert( pCur->skipNext==0 );
*pDifferentRow = 0;
}
return SQLITE_OK;
@@ -1365,7 +1365,7 @@ static u16 cellSize(MemPage *pPage, int iCell){
** pointer to an overflow page, insert an entry into the pointer-map for
** the overflow page that will be valid after pCell has been moved to pPage.
*/
-static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell, int *pRC){
+static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
CellInfo info;
if( *pRC ) return;
assert( pCell!=0 );
@@ -1440,7 +1440,6 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
if( iFree ){
int iFree2 = get2byte(&data[iFree]);
if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
-
if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
u8 *pEnd = &data[cellOffset + nCell*2];
u8 *pAddr;
@@ -3104,6 +3103,7 @@ static int lockBtree(BtShared *pBt){
){
goto page1_init_failed;
}
+ pBt->btsFlags |= BTS_PAGESIZE_FIXED;
assert( (pageSize & 7)==0 );
/* EVIDENCE-OF: R-59310-51205 The "reserved space" size in the 1-byte
** integer at offset 20 is the number of bytes of space at the end of
@@ -4420,6 +4420,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
sqlite3_free(pCur->aOverflow);
sqlite3_free(pCur->pKey);
sqlite3BtreeLeave(pBtree);
+ pCur->pBtree = 0;
}
return SQLITE_OK;
}
@@ -4519,6 +4520,25 @@ u32 sqlite3BtreePayloadSize(BtCursor *pCur){
}
/*
+** Return an upper bound on the size of any record for the table
+** that the cursor is pointing into.
+**
+** This is an optimization. Everything will still work if this
+** routine always returns 2147483647 (which is the largest record
+** that SQLite can handle) or more. But returning a smaller value might
+** prevent large memory allocations when trying to interpret a
+** corrupt datrabase.
+**
+** The current implementation merely returns the size of the underlying
+** database file.
+*/
+sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
+}
+
+/*
** Given the page number of an overflow page in the database (parameter
** ovfl), this function finds the page number of the next page in the
** linked list of overflow pages. If possible, it uses the auto-vacuum
@@ -5332,7 +5352,7 @@ int sqlite3BtreeMovetoUnpacked(
** try to get there using sqlite3BtreeNext() rather than a full
** binary search. This is an optimization only. The correct answer
** is still obtained without this case, only a little more slowely */
- if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
+ if( pCur->info.nKey+1==intKey ){
*pRes = 0;
rc = sqlite3BtreeNext(pCur, 0);
if( rc==SQLITE_OK ){
@@ -5606,7 +5626,6 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur);
@@ -5616,14 +5635,9 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
- if( pCur->skipNext>0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
+ if( pCur->skipNext>0 ) return SQLITE_OK;
}
}
@@ -5678,7 +5692,6 @@ int sqlite3BtreeNext(BtCursor *pCur, int flags){
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
@@ -5719,7 +5732,6 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){
@@ -5730,14 +5742,9 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
if( CURSOR_INVALID==pCur->eState ){
return SQLITE_DONE;
}
- if( pCur->skipNext ){
- assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ if( CURSOR_SKIPNEXT==pCur->eState ){
pCur->eState = CURSOR_VALID;
- if( pCur->skipNext<0 ){
- pCur->skipNext = 0;
- return SQLITE_OK;
- }
- pCur->skipNext = 0;
+ if( pCur->skipNext<0 ) return SQLITE_OK;
}
}
@@ -5772,7 +5779,6 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
int sqlite3BtreePrevious(BtCursor *pCur, int flags){
assert( cursorOwnsBtShared(pCur) );
assert( flags==0 || flags==1 );
- assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
@@ -6108,7 +6114,7 @@ static int allocateBtreePage(
TRACE(("ALLOCATE: %d from end of file\n", *pPgno));
}
- assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
+ assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) );
end_allocate_page:
releasePage(pTrunk);
@@ -6693,8 +6699,82 @@ static void insertCell(
}
/*
+** The following parameters determine how many adjacent pages get involved
+** in a balancing operation. NN is the number of neighbors on either side
+** of the page that participate in the balancing operation. NB is the
+** total number of pages that participate, including the target page and
+** NN neighbors on either side.
+**
+** The minimum value of NN is 1 (of course). Increasing NN above 1
+** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
+** in exchange for a larger degradation in INSERT and UPDATE performance.
+** The value of NN appears to give the best results overall.
+**
+** (Later:) The description above makes it seem as if these values are
+** tunable - as if you could change them and recompile and it would all work.
+** But that is unlikely. NB has been 3 since the inception of SQLite and
+** we have never tested any other value.
+*/
+#define NN 1 /* Number of neighbors on either side of pPage */
+#define NB 3 /* (NN*2+1): Total pages involved in the balance */
+
+/*
** A CellArray object contains a cache of pointers and sizes for a
** consecutive sequence of cells that might be held on multiple pages.
+**
+** The cells in this array are the divider cell or cells from the pParent
+** page plus up to three child pages. There are a total of nCell cells.
+**
+** pRef is a pointer to one of the pages that contributes cells. This is
+** used to access information such as MemPage.intKey and MemPage.pBt->pageSize
+** which should be common to all pages that contribute cells to this array.
+**
+** apCell[] and szCell[] hold, respectively, pointers to the start of each
+** cell and the size of each cell. Some of the apCell[] pointers might refer
+** to overflow cells. In other words, some apCel[] pointers might not point
+** to content area of the pages.
+**
+** A szCell[] of zero means the size of that cell has not yet been computed.
+**
+** The cells come from as many as four different pages:
+**
+** -----------
+** | Parent |
+** -----------
+** / | \
+** / | \
+** --------- --------- ---------
+** |Child-1| |Child-2| |Child-3|
+** --------- --------- ---------
+**
+** The order of cells is in the array is for an index btree is:
+**
+** 1. All cells from Child-1 in order
+** 2. The first divider cell from Parent
+** 3. All cells from Child-2 in order
+** 4. The second divider cell from Parent
+** 5. All cells from Child-3 in order
+**
+** For a table-btree (with rowids) the items 2 and 4 are empty because
+** content exists only in leaves and there are no divider cells.
+**
+** For an index btree, the apEnd[] array holds pointer to the end of page
+** for Child-1, the Parent, Child-2, the Parent (again), and Child-3,
+** respectively. The ixNx[] array holds the number of cells contained in
+** each of these 5 stages, and all stages to the left. Hence:
+**
+** ixNx[0] = Number of cells in Child-1.
+** ixNx[1] = Number of cells in Child-1 plus 1 for first divider.
+** ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
+** ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
+** ixNx[4] = Total number of cells.
+**
+** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2]
+** are used and they point to the leaf pages only, and the ixNx value are:
+**
+** ixNx[0] = Number of cells in Child-1.
+** ixNx[1] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
+** ixNx[2] = Number of cells in Child-1 and Child-2 + both divider cells
*/
typedef struct CellArray CellArray;
struct CellArray {
@@ -6702,6 +6782,8 @@ struct CellArray {
MemPage *pRef; /* Reference page */
u8 **apCell; /* All cells begin balanced */
u16 *szCell; /* Local size of all cells in apCell[] */
+ u8 *apEnd[NB*2]; /* MemPage.aDataEnd values */
+ int ixNx[NB*2]; /* Index of at which we move to the next apEnd[] */
};
/*
@@ -6752,37 +6834,59 @@ static u16 cachedCellSize(CellArray *p, int N){
** responsibility of the caller to set it correctly.
*/
static int rebuildPage(
- MemPage *pPg, /* Edit this page */
+ CellArray *pCArray, /* Content to be added to page pPg */
+ int iFirst, /* First cell in pCArray to use */
int nCell, /* Final number of cells on page */
- u8 **apCell, /* Array of cells */
- u16 *szCell /* Array of cell sizes */
+ MemPage *pPg /* The page to be reconstructed */
){
const int hdr = pPg->hdrOffset; /* Offset of header on pPg */
u8 * const aData = pPg->aData; /* Pointer to data for pPg */
const int usableSize = pPg->pBt->usableSize;
u8 * const pEnd = &aData[usableSize];
- int i;
+ int i = iFirst; /* Which cell to copy from pCArray*/
+ u32 j; /* Start of cell content area */
+ int iEnd = i+nCell; /* Loop terminator */
u8 *pCellptr = pPg->aCellIdx;
u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
u8 *pData;
+ int k; /* Current slot in pCArray->apEnd[] */
+ u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */
+
+ assert( i<iEnd );
+ j = get2byte(&aData[hdr+5]);
+ if( NEVER(j>(u32)usableSize) ){ j = 0; }
+ memcpy(&pTmp[j], &aData[j], usableSize - j);
- i = get2byte(&aData[hdr+5]);
- memcpy(&pTmp[i], &aData[i], usableSize - i);
+ for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
- for(i=0; i<nCell; i++){
- u8 *pCell = apCell[i];
+ while( 1/*exit by break*/ ){
+ u8 *pCell = pCArray->apCell[i];
+ u16 sz = pCArray->szCell[i];
+ assert( sz>0 );
if( SQLITE_WITHIN(pCell,aData,pEnd) ){
- if( ((uptr)(pCell+szCell[i]))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
+ if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
pCell = &pTmp[pCell - aData];
+ }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
+ && (uptr)(pCell)<(uptr)pSrcEnd
+ ){
+ return SQLITE_CORRUPT_BKPT;
}
- pData -= szCell[i];
+
+ pData -= sz;
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
- memcpy(pData, pCell, szCell[i]);
- assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
- testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
+ memcpy(pData, pCell, sz);
+ assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
+ testcase( sz!=pPg->xCellSize(pPg,pCell) );
+ i++;
+ if( i>=iEnd ) break;
+ if( pCArray->ixNx[k]<=i ){
+ k++;
+ pSrcEnd = pCArray->apEnd[k];
+ }
}
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
@@ -6797,12 +6901,11 @@ static int rebuildPage(
}
/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function attempts to
-** add the cells stored in the array to page pPg. If it cannot (because
-** the page needs to be defragmented before the cells will fit), non-zero
-** is returned. Otherwise, if the cells are added successfully, zero is
-** returned.
+** The pCArray objects contains pointers to b-tree cells and the cell sizes.
+** This function attempts to add the cells stored in the array to page pPg.
+** If it cannot (because the page needs to be defragmented before the cells
+** will fit), non-zero is returned. Otherwise, if the cells are added
+** successfully, zero is returned.
**
** Argument pCellptr points to the first entry in the cell-pointer array
** (part of page pPg) to populate. After cell apCell[0] is written to the
@@ -6824,18 +6927,23 @@ static int rebuildPage(
static int pageInsertArray(
MemPage *pPg, /* Page to add cells to */
u8 *pBegin, /* End of cell-pointer array */
- u8 **ppData, /* IN/OUT: Page content -area pointer */
+ u8 **ppData, /* IN/OUT: Page content-area pointer */
u8 *pCellptr, /* Pointer to cell-pointer area */
int iFirst, /* Index of first cell to add */
int nCell, /* Number of cells to add to pPg */
CellArray *pCArray /* Array of cells */
){
- int i;
- u8 *aData = pPg->aData;
- u8 *pData = *ppData;
- int iEnd = iFirst + nCell;
+ int i = iFirst; /* Loop counter - cell index to insert */
+ u8 *aData = pPg->aData; /* Complete page */
+ u8 *pData = *ppData; /* Content area. A subset of aData[] */
+ int iEnd = iFirst + nCell; /* End of loop. One past last cell to ins */
+ int k; /* Current slot in pCArray->apEnd[] */
+ u8 *pEnd; /* Maximum extent of cell data */
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
- for(i=iFirst; i<iEnd; i++){
+ if( iEnd<=iFirst ) return 0;
+ for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+ pEnd = pCArray->apEnd[k];
+ while( 1 /*Exit by break*/ ){
int sz, rc;
u8 *pSlot;
sz = cachedCellSize(pCArray, i);
@@ -6850,20 +6958,33 @@ static int pageInsertArray(
assert( (pSlot+sz)<=pCArray->apCell[i]
|| pSlot>=(pCArray->apCell[i]+sz)
|| CORRUPT_DB );
+ if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
+ && (uptr)(pCArray->apCell[i])<(uptr)pEnd
+ ){
+ assert( CORRUPT_DB );
+ (void)SQLITE_CORRUPT_BKPT;
+ return 1;
+ }
memmove(pSlot, pCArray->apCell[i], sz);
put2byte(pCellptr, (pSlot - aData));
pCellptr += 2;
+ i++;
+ if( i>=iEnd ) break;
+ if( pCArray->ixNx[k]<=i ){
+ k++;
+ pEnd = pCArray->apEnd[k];
+ }
}
*ppData = pData;
return 0;
}
/*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function adds the
-** space associated with each cell in the array that is currently stored
-** within the body of pPg to the pPg free-list. The cell-pointers and other
-** fields of the page are not updated.
+** The pCArray object contains pointers to b-tree cells and their sizes.
+**
+** This function adds the space associated with each cell in the array
+** that is currently stored within the body of pPg to the pPg free-list.
+** The cell-pointers and other fields of the page are not updated.
**
** This function returns the total number of cells added to the free-list.
*/
@@ -6913,9 +7034,9 @@ static int pageFreeArray(
}
/*
-** apCell[] and szCell[] contains pointers to and sizes of all cells in the
-** pages being balanced. The current page, pPg, has pPg->nCell cells starting
-** with apCell[iOld]. After balancing, this page should hold nNew cells
+** pCArray contains pointers to and sizes of all cells in the page being
+** balanced. The current page, pPg, has pPg->nCell cells starting with
+** pCArray->apCell[iOld]. After balancing, this page should hold nNew cells
** starting at apCell[iNew].
**
** This routine makes the necessary adjustments to pPg so that it contains
@@ -6947,13 +7068,17 @@ static int editPage(
#endif
/* Remove cells from the start and end of the page */
+ assert( nCell>=0 );
if( iOld<iNew ){
int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
+ if( nShift>nCell ) return SQLITE_CORRUPT_BKPT;
memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
nCell -= nShift;
}
if( iNewEnd < iOldEnd ){
- nCell -= pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+ int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+ assert( nCell>=nTail );
+ nCell -= nTail;
}
pData = &aData[get2byteNotZero(&aData[hdr+5])];
@@ -6963,6 +7088,7 @@ static int editPage(
if( iNew<iOld ){
int nAdd = MIN(nNew,iOld-iNew);
assert( (iOld-iNew)<nNew || nCell==0 || CORRUPT_DB );
+ assert( nAdd>=0 );
pCellptr = pPg->aCellIdx;
memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
if( pageInsertArray(
@@ -6977,6 +7103,7 @@ static int editPage(
int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
if( iCell>=0 && iCell<nNew ){
pCellptr = &pPg->aCellIdx[iCell * 2];
+ assert( nCell>=iCell );
memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
nCell++;
if( pageInsertArray(
@@ -6987,6 +7114,7 @@ static int editPage(
}
/* Append cells to the end of the page */
+ assert( nCell>=0 );
pCellptr = &pPg->aCellIdx[nCell*2];
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
@@ -7015,24 +7143,9 @@ static int editPage(
editpage_fail:
/* Unable to edit this page. Rebuild it from scratch instead. */
populateCellCache(pCArray, iNew, nNew);
- return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
+ return rebuildPage(pCArray, iNew, nNew, pPg);
}
-/*
-** The following parameters determine how many adjacent pages get involved
-** in a balancing operation. NN is the number of neighbors on either side
-** of the page that participate in the balancing operation. NB is the
-** total number of pages that participate, including the target page and
-** NN neighbors on either side.
-**
-** The minimum value of NN is 1 (of course). Increasing NN above 1
-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-** in exchange for a larger degradation in INSERT and UPDATE performance.
-** The value of NN appears to give the best results overall.
-*/
-#define NN 1 /* Number of neighbors on either side of pPage */
-#define NB (NN*2+1) /* Total pages involved in the balance */
-
#ifndef SQLITE_OMIT_QUICKBALANCE
/*
@@ -7082,12 +7195,22 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
u8 *pCell = pPage->apOvfl[0];
u16 szCell = pPage->xCellSize(pPage, pCell);
u8 *pStop;
+ CellArray b;
assert( sqlite3PagerIswriteable(pNew->pDbPage) );
- assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
+ assert( CORRUPT_DB || pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
- rc = rebuildPage(pNew, 1, &pCell, &szCell);
- if( NEVER(rc) ) return rc;
+ b.nCell = 1;
+ b.pRef = pPage;
+ b.apCell = &pCell;
+ b.szCell = &szCell;
+ b.apEnd[0] = pPage->aDataEnd;
+ b.ixNx[0] = 2;
+ rc = rebuildPage(&b, 0, 1, pNew);
+ if( NEVER(rc) ){
+ releasePage(pNew);
+ return rc;
+ }
pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
/* If this is an auto-vacuum database, update the pointer map
@@ -7565,8 +7688,15 @@ static int balance_nonroot(
**
*/
usableSpace = pBt->usableSize - 12 + leafCorrection;
- for(i=0; i<nOld; i++){
+ for(i=k=0; i<nOld; i++, k++){
MemPage *p = apOld[i];
+ b.apEnd[k] = p->aDataEnd;
+ b.ixNx[k] = cntOld[i];
+ if( !leafData ){
+ k++;
+ b.apEnd[k] = pParent->aDataEnd;
+ b.ixNx[k] = cntOld[i]+1;
+ }
szNew[i] = usableSpace - p->nFree;
for(j=0; j<p->nOverflow; j++){
szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
@@ -8248,7 +8378,11 @@ static int btreeOverwriteContent(
if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
int rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+ /* In a corrupt database, it is possible for the source and destination
+ ** buffers to overlap. This is harmless since the database is already
+ ** corrupt but it does cause valgrind and ASAN warnings. So use
+ ** memmove(). */
+ memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
}
}
return SQLITE_OK;
@@ -9428,7 +9562,7 @@ static void checkList(
checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0);
}
#endif
- if( n>(int)pCheck->pBt->usableSize/4-2 ){
+ if( n>pCheck->pBt->usableSize/4-2 ){
checkAppendMsg(pCheck,
"freelist leaf count too big on page %d", iPage);
N--;
@@ -9810,7 +9944,7 @@ char *sqlite3BtreeIntegrityCheck(
Pgno i;
IntegrityCk sCheck;
BtShared *pBt = p->pBt;
- int savedDbFlags = pBt->db->flags;
+ u64 savedDbFlags = pBt->db->flags;
char zErr[100];
VVA_ONLY( int nRef );
@@ -9877,7 +10011,7 @@ char *sqlite3BtreeIntegrityCheck(
}
#endif
testcase( pBt->db->flags & SQLITE_CellSizeCk );
- pBt->db->flags &= ~SQLITE_CellSizeCk;
+ pBt->db->flags &= ~(u64)SQLITE_CellSizeCk;
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
i64 notUsed;
if( aRoot[i]==0 ) continue;
diff --git a/chromium/third_party/sqlite/src/src/btree.h b/chromium/third_party/sqlite/src/src/btree.h
index e4bd09c7e72..52d09b21575 100644
--- a/chromium/third_party/sqlite/src/src/btree.h
+++ b/chromium/third_party/sqlite/src/src/btree.h
@@ -315,6 +315,7 @@ i64 sqlite3BtreeOffset(BtCursor*);
int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
u32 sqlite3BtreePayloadSize(BtCursor*);
+sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
struct Pager *sqlite3BtreePager(Btree*);
diff --git a/chromium/third_party/sqlite/src/src/btreeInt.h b/chromium/third_party/sqlite/src/src/btreeInt.h
index 8fe8e280fe5..af29c897f9b 100644
--- a/chromium/third_party/sqlite/src/src/btreeInt.h
+++ b/chromium/third_party/sqlite/src/src/btreeInt.h
@@ -494,9 +494,16 @@ struct CellInfo {
** found at self->pBt->mutex.
**
** skipNext meaning:
-** eState==SKIPNEXT && skipNext>0: Next sqlite3BtreeNext() is no-op.
-** eState==SKIPNEXT && skipNext<0: Next sqlite3BtreePrevious() is no-op.
-** eState==FAULT: Cursor fault with skipNext as error code.
+** The meaning of skipNext depends on the value of eState:
+**
+** eState Meaning of skipNext
+** VALID skipNext is meaningless and is ignored
+** INVALID skipNext is meaningless and is ignored
+** SKIPNEXT sqlite3BtreeNext() is a no-op if skipNext>0 and
+** sqlite3BtreePrevious() is no-op if skipNext<0.
+** REQUIRESEEK restoreCursorPosition() restores the cursor to
+** eState=SKIPNEXT if skipNext!=0
+** FAULT skipNext holds the cursor fault error code.
*/
struct BtCursor {
u8 eState; /* One of the CURSOR_XXX constants (see below) */
diff --git a/chromium/third_party/sqlite/src/src/build.c b/chromium/third_party/sqlite/src/src/build.c
index e6e48875d12..e9371afd2b7 100644
--- a/chromium/third_party/sqlite/src/src/build.c
+++ b/chromium/third_party/sqlite/src/src/build.c
@@ -227,7 +227,7 @@ void sqlite3FinishCoding(Parse *pParse){
if( v && pParse->nErr==0 && !db->mallocFailed ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
- if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
+ assert( pParse->pAinc==0 || pParse->nTab>0 );
sqlite3VdbeMakeReady(v, pParse);
pParse->rc = SQLITE_DONE;
}else{
@@ -642,12 +642,6 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
/* Delete the Table structure itself.
*/
-#ifdef SQLITE_ENABLE_NORMALIZE
- if( pTable->pColHash ){
- sqlite3HashClear(pTable->pColHash);
- sqlite3_free(pTable->pColHash);
- }
-#endif
sqlite3DeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
@@ -2644,6 +2638,7 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
*/
if( IsVirtual(pTab) ){
sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
+ sqlite3MayAbort(pParse);
}
sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
sqlite3ChangeCookie(pParse, iDb);
@@ -3472,6 +3467,11 @@ void sqlite3CreateIndex(
}
}
if( idxType==SQLITE_IDXTYPE_PRIMARYKEY ) pIdx->idxType = idxType;
+ if( IN_RENAME_OBJECT ){
+ pIndex->pNext = pParse->pNewIndex;
+ pParse->pNewIndex = pIndex;
+ pIndex = 0;
+ }
goto exit_create_index;
}
}
@@ -3487,6 +3487,14 @@ void sqlite3CreateIndex(
Index *p;
assert( !IN_SPECIAL_PARSE );
assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
+ if( pTblName!=0 ){
+ pIndex->tnum = db->init.newTnum;
+ if( sqlite3IndexHasDuplicateRootPage(pIndex) ){
+ sqlite3ErrorMsg(pParse, "invalid rootpage");
+ pParse->rc = SQLITE_CORRUPT_BKPT;
+ goto exit_create_index;
+ }
+ }
p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
pIndex->zName, pIndex);
if( p ){
@@ -3495,9 +3503,6 @@ void sqlite3CreateIndex(
goto exit_create_index;
}
db->mDbFlags |= DBFLAG_SchemaChange;
- if( pTblName!=0 ){
- pIndex->tnum = db->init.newTnum;
- }
}
/* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
@@ -3824,6 +3829,18 @@ int sqlite3IdListIndex(IdList *pList, const char *zName){
}
/*
+** Maximum size of a SrcList object.
+** The SrcList object is used to represent the FROM clause of a
+** SELECT statement, and the query planner cannot deal with more
+** than 64 tables in a join. So any value larger than 64 here
+** is sufficient for most uses. Smaller values, like say 10, are
+** appropriate for small and memory-limited applications.
+*/
+#ifndef SQLITE_MAX_SRCLIST
+# define SQLITE_MAX_SRCLIST 200
+#endif
+
+/*
** Expand the space allocated for the given SrcList object by
** creating nExtra new slots beginning at iStart. iStart is zero based.
** New slots are zeroed.
@@ -3839,11 +3856,12 @@ int sqlite3IdListIndex(IdList *pList, const char *zName){
** the iStart value would be 0. The result then would
** be: nil, nil, nil, A, B.
**
-** If a memory allocation fails the SrcList is unchanged. The
-** db->mallocFailed flag will be set to true.
+** If a memory allocation fails or the SrcList becomes too large, leave
+** the original SrcList unchanged, return NULL, and leave an error message
+** in pParse.
*/
SrcList *sqlite3SrcListEnlarge(
- sqlite3 *db, /* Database connection to notify of OOM errors */
+ Parse *pParse, /* Parsing context into which errors are reported */
SrcList *pSrc, /* The SrcList to be enlarged */
int nExtra, /* Number of new slots to add to pSrc->a[] */
int iStart /* Index in pSrc->a[] of first new slot */
@@ -3860,16 +3878,22 @@ SrcList *sqlite3SrcListEnlarge(
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
int nAlloc = pSrc->nSrc*2+nExtra;
- int nGot;
+ sqlite3 *db = pParse->db;
+
+ if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){
+ sqlite3ErrorMsg(pParse, "too many FROM clause terms, max: %d",
+ SQLITE_MAX_SRCLIST);
+ return 0;
+ }
+ if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
pNew = sqlite3DbRealloc(db, pSrc,
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
if( pNew==0 ){
assert( db->mallocFailed );
- return pSrc;
+ return 0;
}
pSrc = pNew;
- nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
- pSrc->nAlloc = nGot;
+ pSrc->nAlloc = nAlloc;
}
/* Move existing slots that come after the newly inserted slots
@@ -3894,7 +3918,8 @@ SrcList *sqlite3SrcListEnlarge(
** Append a new table name to the given SrcList. Create a new SrcList if
** need be. A new entry is created in the SrcList even if pTable is NULL.
**
-** A SrcList is returned, or NULL if there is an OOM error. The returned
+** A SrcList is returned, or NULL if there is an OOM error or if the
+** SrcList grows to large. The returned
** SrcList might be the same as the SrcList that was input or it might be
** a new one. If an OOM error does occurs, then the prior value of pList
** that is input to this routine is automatically freed.
@@ -3925,27 +3950,32 @@ SrcList *sqlite3SrcListEnlarge(
** before being added to the SrcList.
*/
SrcList *sqlite3SrcListAppend(
- sqlite3 *db, /* Connection to notify of malloc failures */
+ Parse *pParse, /* Parsing context, in which errors are reported */
SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */
Token *pTable, /* Table to append */
Token *pDatabase /* Database of the table */
){
struct SrcList_item *pItem;
+ sqlite3 *db;
assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
- assert( db!=0 );
+ assert( pParse!=0 );
+ assert( pParse->db!=0 );
+ db = pParse->db;
if( pList==0 ){
- pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
+ pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
pList->nSrc = 1;
memset(&pList->a[0], 0, sizeof(pList->a[0]));
pList->a[0].iCursor = -1;
}else{
- pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
- }
- if( db->mallocFailed ){
- sqlite3SrcListDelete(db, pList);
- return 0;
+ SrcList *pNew = sqlite3SrcListEnlarge(pParse, pList, 1, pList->nSrc);
+ if( pNew==0 ){
+ sqlite3SrcListDelete(db, pList);
+ return 0;
+ }else{
+ pList = pNew;
+ }
}
pItem = &pList->a[pList->nSrc-1];
if( pDatabase && pDatabase->z==0 ){
@@ -4034,7 +4064,7 @@ SrcList *sqlite3SrcListAppendFromTerm(
);
goto append_from_error;
}
- p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
+ p = sqlite3SrcListAppend(pParse, p, pTable, pDatabase);
if( p==0 ){
goto append_from_error;
}
@@ -4423,7 +4453,7 @@ static int collationMatch(const char *zColl, Index *pIndex){
*/
#ifndef SQLITE_OMIT_REINDEX
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
- if (! IsVirtual(pTab) ){
+ if( !IsVirtual(pTab) ){
Index *pIndex; /* An index associated with pTab */
for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
diff --git a/chromium/third_party/sqlite/src/src/callback.c b/chromium/third_party/sqlite/src/src/callback.c
index 3d55b286736..e356b19e612 100644
--- a/chromium/third_party/sqlite/src/src/callback.c
+++ b/chromium/third_party/sqlite/src/src/callback.c
@@ -283,7 +283,7 @@ static int matchQuality(
** Search a FuncDefHash for a function with the given name. Return
** a pointer to the matching FuncDef if found, or 0 if there is no match.
*/
-static FuncDef *functionSearch(
+FuncDef *sqlite3FunctionSearch(
int h, /* Hash of the name */
const char *zFunc /* Name of function */
){
@@ -295,21 +295,6 @@ static FuncDef *functionSearch(
}
return 0;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-FuncDef *sqlite3FunctionSearchN(
- int h, /* Hash of the name */
- const char *zFunc, /* Name of function */
- int nFunc /* Length of the name */
-){
- FuncDef *p;
- for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
- if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){
- return p;
- }
- }
- return 0;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Insert a new FuncDef into a FuncDefHash hash table.
@@ -325,7 +310,7 @@ void sqlite3InsertBuiltinFuncs(
int nName = sqlite3Strlen30(zName);
int h = SQLITE_FUNC_HASH(zName[0], nName);
assert( zName[0]>='a' && zName[0]<='z' );
- pOther = functionSearch(h, zName);
+ pOther = sqlite3FunctionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
aDef[i].pNext = pOther->pNext;
@@ -403,7 +388,7 @@ FuncDef *sqlite3FindFunction(
if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
bestScore = 0;
h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName);
- p = functionSearch(h, zName);
+ p = sqlite3FunctionSearch(h, zName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){
diff --git a/chromium/third_party/sqlite/src/src/dbstat.c b/chromium/third_party/sqlite/src/src/dbstat.c
index 73ab7d926e2..96008f358ec 100644
--- a/chromium/third_party/sqlite/src/src/dbstat.c
+++ b/chromium/third_party/sqlite/src/src/dbstat.c
@@ -531,6 +531,10 @@ statNextRestart:
goto statNextRestart; /* Tail recursion */
}
pCsr->iPage++;
+ if( pCsr->iPage>=ArraySize(pCsr->aPage) ){
+ statResetCsr(pCsr);
+ return SQLITE_CORRUPT_BKPT;
+ }
assert( p==&pCsr->aPage[pCsr->iPage-1] );
if( p->iCell==p->nCell ){
@@ -602,7 +606,6 @@ static int statFilter(
StatTable *pTab = (StatTable*)(pCursor->pVtab);
char *zSql;
int rc = SQLITE_OK;
- char *zMaster;
if( idxNum==1 ){
const char *zDbase = (const char*)sqlite3_value_text(argv[0]);
@@ -618,13 +621,12 @@ static int statFilter(
statResetCsr(pCsr);
sqlite3_finalize(pCsr->pStmt);
pCsr->pStmt = 0;
- zMaster = pCsr->iDb==1 ? "sqlite_temp_master" : "sqlite_master";
zSql = sqlite3_mprintf(
"SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
" UNION ALL "
"SELECT name, rootpage, type"
- " FROM \"%w\".%s WHERE rootpage!=0"
- " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster);
+ " FROM \"%w\".sqlite_master WHERE rootpage!=0"
+ " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName);
if( zSql==0 ){
return SQLITE_NOMEM_BKPT;
}else{
diff --git a/chromium/third_party/sqlite/src/src/delete.c b/chromium/third_party/sqlite/src/src/delete.c
index 69135c226e9..dcb117f2e10 100644
--- a/chromium/third_party/sqlite/src/src/delete.c
+++ b/chromium/third_party/sqlite/src/src/delete.c
@@ -117,7 +117,7 @@ void sqlite3MaterializeView(
sqlite3 *db = pParse->db;
int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
pWhere = sqlite3ExprDup(db, pWhere, 0);
- pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
+ pFrom = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
@@ -517,7 +517,7 @@ void sqlite3DeleteFrom(
/* If this DELETE cannot use the ONEPASS strategy, this is the
** end of the WHERE loop */
if( eOnePass!=ONEPASS_OFF ){
- addrBypass = sqlite3VdbeMakeLabel(v);
+ addrBypass = sqlite3VdbeMakeLabel(pParse);
}else{
sqlite3WhereEnd(pWInfo);
}
@@ -706,7 +706,7 @@ void sqlite3GenerateRowDelete(
/* Seek cursor iCur to the row to delete. If this row no longer exists
** (this can happen if a trigger program has already deleted it), do
** not attempt to delete it or fire any DELETE triggers. */
- iLabel = sqlite3VdbeMakeLabel(v);
+ iLabel = sqlite3VdbeMakeLabel(pParse);
opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
if( eMode==ONEPASS_OFF ){
sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
@@ -912,7 +912,7 @@ int sqlite3GenerateIndexKey(
if( piPartIdxLabel ){
if( pIdx->pPartIdxWhere ){
- *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
+ *piPartIdxLabel = sqlite3VdbeMakeLabel(pParse);
pParse->iSelfTab = iDataCur + 1;
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
diff --git a/chromium/third_party/sqlite/src/src/expr.c b/chromium/third_party/sqlite/src/src/expr.c
index 50c398266f3..eb75cb863d1 100644
--- a/chromium/third_party/sqlite/src/src/expr.c
+++ b/chromium/third_party/sqlite/src/src/expr.c
@@ -465,6 +465,7 @@ Expr *sqlite3ExprForVectorField(
}else{
if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
pRet = sqlite3ExprDup(pParse->db, pVector, 0);
+ sqlite3RenameTokenRemap(pParse, pRet, pVector);
}
return pRet;
}
@@ -481,7 +482,7 @@ static int exprCodeSubselect(Parse *pParse, Expr *pExpr){
int reg = 0;
#ifndef SQLITE_OMIT_SUBQUERY
if( pExpr->op==TK_SELECT ){
- reg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
+ reg = sqlite3CodeSubselect(pParse, pExpr);
}
#endif
return reg;
@@ -553,7 +554,7 @@ static void codeVectorCompare(
int regLeft = 0;
int regRight = 0;
u8 opx = op;
- int addrDone = sqlite3VdbeMakeLabel(v);
+ int addrDone = sqlite3VdbeMakeLabel(pParse);
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
@@ -780,8 +781,7 @@ Expr *sqlite3ExprAlloc(
if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
pNew->u.zToken[pToken->n] = 0;
if( dequote && sqlite3Isquote(pNew->u.zToken[0]) ){
- if( pNew->u.zToken[0]=='"' ) pNew->flags |= EP_DblQuoted;
- sqlite3Dequote(pNew->u.zToken);
+ sqlite3DequoteExpr(pNew);
}
}
}
@@ -850,7 +850,7 @@ Expr *sqlite3PExpr(
Expr *pRight /* Right operand */
){
Expr *p;
- if( op==TK_AND && pParse->nErr==0 ){
+ if( op==TK_AND && pParse->nErr==0 && !IN_RENAME_OBJECT ){
/* Take advantage of short-circuit false optimization for AND */
p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
}else{
@@ -1100,6 +1100,16 @@ static int exprStructSize(Expr *p){
}
/*
+** Copy the complete content of an Expr node, taking care not to read
+** past the end of the structure for a reduced-size version of the source
+** Expr.
+*/
+static void exprNodeCopy(Expr *pDest, Expr *pSrc){
+ memset(pDest, 0, sizeof(Expr));
+ memcpy(pDest, pSrc, exprStructSize(pSrc));
+}
+
+/*
** The dupedExpr*Size() routines each return the number of bytes required
** to store a copy of an expression or expression tree. They differ in
** how much of the tree is measured.
@@ -1330,6 +1340,36 @@ static With *withDup(sqlite3 *db, With *p){
# define withDup(x,y) 0
#endif
+#ifndef SQLITE_OMIT_WINDOWFUNC
+/*
+** The gatherSelectWindows() procedure and its helper routine
+** gatherSelectWindowsCallback() are used to scan all the expressions
+** an a newly duplicated SELECT statement and gather all of the Window
+** objects found there, assembling them onto the linked list at Select->pWin.
+*/
+static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_FUNCTION && pExpr->y.pWin!=0 ){
+ assert( ExprHasProperty(pExpr, EP_WinFunc) );
+ pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin;
+ pWalker->u.pSelect->pWin = pExpr->y.pWin;
+ }
+ return WRC_Continue;
+}
+static int gatherSelectWindowsSelectCallback(Walker *pWalker, Select *p){
+ return p==pWalker->u.pSelect ? WRC_Continue : WRC_Prune;
+}
+static void gatherSelectWindows(Select *p){
+ Walker w;
+ w.xExprCallback = gatherSelectWindowsCallback;
+ w.xSelectCallback = gatherSelectWindowsSelectCallback;
+ w.xSelectCallback2 = 0;
+ w.pParse = 0;
+ w.u.pSelect = p;
+ sqlite3WalkSelect(&w, p);
+}
+#endif
+
+
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
@@ -1497,6 +1537,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
#ifndef SQLITE_OMIT_WINDOWFUNC
pNew->pWin = 0;
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
+ if( p->pWin ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
*pp = pNew;
@@ -1629,6 +1670,9 @@ ExprList *sqlite3ExprListAppendVector(
}
vector_append_error:
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameExprUnmap(pParse, pExpr);
+ }
sqlite3ExprDelete(db, pExpr);
sqlite3IdListDelete(db, pColumns);
return pList;
@@ -1772,8 +1816,9 @@ int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
*/
int sqlite3ExprIdToTrueFalse(Expr *pExpr){
assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
- if( sqlite3StrICmp(pExpr->u.zToken, "true")==0
- || sqlite3StrICmp(pExpr->u.zToken, "false")==0
+ if( !ExprHasProperty(pExpr, EP_Quoted)
+ && (sqlite3StrICmp(pExpr->u.zToken, "true")==0
+ || sqlite3StrICmp(pExpr->u.zToken, "false")==0)
){
pExpr->op = TK_TRUEFALSE;
return 1;
@@ -2082,7 +2127,9 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
*/
int sqlite3ExprCanBeNull(const Expr *p){
u8 op;
- while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
+ while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
+ p = p->pLeft;
+ }
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
switch( op ){
@@ -2149,14 +2196,6 @@ int sqlite3IsRowid(const char *z){
if( sqlite3StrICmp(z, "OID")==0 ) return 1;
return 0;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-int sqlite3IsRowidN(const char *z, int n){
- if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1;
- if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1;
- if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1;
- return 0;
-}
-#endif
/*
** pX is the RHS of an IN operator. If pX is a SELECT statement
@@ -2326,7 +2365,8 @@ int sqlite3FindInIndex(
Expr *pX, /* The right-hand side (RHS) of the IN operator */
u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
int *prRhsHasNull, /* Register holding NULL status. See notes */
- int *aiMap /* Mapping from Index fields to RHS fields */
+ int *aiMap, /* Mapping from Index fields to RHS fields */
+ int *piTab /* OUT: index to use */
){
Select *p; /* SELECT to the right of IN operator */
int eType = 0; /* Type of RHS table. IN_INDEX_* */
@@ -2421,6 +2461,7 @@ int sqlite3FindInIndex(
Bitmask colUsed; /* Columns of the index used */
Bitmask mCol; /* Mask for the current column */
if( pIdx->nColumn<nExpr ) continue;
+ if( pIdx->pPartIdxWhere!=0 ) continue;
/* Maximum nColumn is BMS-2, not BMS-1, so that we can compute
** BITMASK(nExpr) without overflowing */
testcase( pIdx->nColumn==BMS-2 );
@@ -2517,10 +2558,12 @@ int sqlite3FindInIndex(
}else if( prRhsHasNull ){
*prRhsHasNull = rMayHaveNull = ++pParse->nMem;
}
- sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
+ assert( pX->op==TK_IN );
+ sqlite3CodeRhsOfIN(pParse, pX, iTab, eType==IN_INDEX_ROWID);
+ if( rMayHaveNull ){
+ sqlite3SetHasNullFlag(v, iTab, rMayHaveNull);
+ }
pParse->nQueryLoop = savedNQueryLoop;
- }else{
- pX->iTable = iTab;
}
if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){
@@ -2528,6 +2571,7 @@ int sqlite3FindInIndex(
n = sqlite3ExprVectorSize(pX->pLeft);
for(i=0; i<n; i++) aiMap[i] = i;
}
+ *piTab = iTab;
return eType;
}
#endif
@@ -2601,260 +2645,326 @@ void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
}
}
+#ifndef SQLITE_OMIT_SUBQUERY
/*
-** Generate code for scalar subqueries used as a subquery expression, EXISTS,
-** or IN operators. Examples:
+** Generate code that will construct an ephemeral table containing all terms
+** in the RHS of an IN operator. The IN operator can be in either of two
+** forms:
**
-** (SELECT a FROM b) -- subquery
-** EXISTS (SELECT a FROM b) -- EXISTS subquery
** x IN (4,5,11) -- IN operator with list on right-hand side
** x IN (SELECT a FROM b) -- IN operator with subquery on the right
**
-** The pExpr parameter describes the expression that contains the IN
-** operator or subquery.
-**
-** If parameter isRowid is non-zero, then expression pExpr is guaranteed
-** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
-** to some integer key column of a table B-Tree. In this case, use an
-** intkey B-Tree to store the set of IN(...) values instead of the usual
-** (slower) variable length keys B-Tree.
-**
-** If rMayHaveNull is non-zero, that means that the operation is an IN
-** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
-** All this routine does is initialize the register given by rMayHaveNull
-** to NULL. Calling routines will take care of changing this register
-** value to non-NULL if the RHS is NULL-free.
-**
-** For a SELECT or EXISTS operator, return the register that holds the
-** result. For a multi-column SELECT, the result is stored in a contiguous
-** array of registers and the return value is the register of the left-most
-** result column. Return 0 for IN operators or if an error occurs.
+** The pExpr parameter is the IN operator. The cursor number for the
+** constructed ephermeral table is returned. The first time the ephemeral
+** table is computed, the cursor number is also stored in pExpr->iTable,
+** however the cursor number returned might not be the same, as it might
+** have been duplicated using OP_OpenDup.
+**
+** If parameter isRowid is non-zero, then LHS of the IN operator is guaranteed
+** to be a non-null integer. In this case, the ephemeral table can be an
+** table B-Tree that keyed by only integers. The more general cases uses
+** an index B-Tree which can have arbitrary keys, but is slower to both
+** read and write.
+**
+** If the LHS expression ("x" in the examples) is a column value, or
+** the SELECT statement returns a column value, then the affinity of that
+** column is used to build the index keys. If both 'x' and the
+** SELECT... statement are columns, then numeric affinity is used
+** if either column has NUMERIC or INTEGER affinity. If neither
+** 'x' nor the SELECT... statement are columns, then numeric affinity
+** is used.
*/
-#ifndef SQLITE_OMIT_SUBQUERY
-int sqlite3CodeSubselect(
+void sqlite3CodeRhsOfIN(
Parse *pParse, /* Parsing context */
- Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
- int rHasNullFlag, /* Register that records whether NULLs exist in RHS */
- int isRowid /* If true, LHS of IN operator is a rowid */
+ Expr *pExpr, /* The IN operator */
+ int iTab, /* Use this cursor number */
+ int isRowid /* If true, LHS is a rowid */
){
- int jmpIfDynamic = -1; /* One-time test address */
- int rReg = 0; /* Register storing resulting */
- Vdbe *v = sqlite3GetVdbe(pParse);
- if( NEVER(v==0) ) return 0;
+ int addrOnce = 0; /* Address of the OP_Once instruction at top */
+ int addr; /* Address of OP_OpenEphemeral instruction */
+ Expr *pLeft; /* the LHS of the IN operator */
+ KeyInfo *pKeyInfo = 0; /* Key information */
+ int nVal; /* Size of vector pLeft */
+ Vdbe *v; /* The prepared statement under construction */
+
+ v = pParse->pVdbe;
+ assert( v!=0 );
- /* The evaluation of the IN/EXISTS/SELECT must be repeated every time it
+ /* The evaluation of the IN must be repeated every time it
** is encountered if any of the following is true:
**
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * We are inside a trigger
**
- ** If all of the above are false, then we can run this code just once
- ** save the results, and reuse the same result on subsequent invocations.
+ ** If all of the above are false, then we can compute the RHS just once
+ ** and reuse it many names.
*/
- if( !ExprHasProperty(pExpr, EP_VarSelect) ){
- jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- }
+ if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
+ /* Reuse of the RHS is allowed */
+ /* If this routine has already been coded, but the previous code
+ ** might not have been invoked yet, so invoke it now as a subroutine.
+ */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
+ pExpr->x.pSelect->selId));
+ }
+ sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
+ pExpr->y.sub.iAddr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
+ sqlite3VdbeJumpHere(v, addrOnce);
+ return;
+ }
- switch( pExpr->op ){
- case TK_IN: {
- int addr; /* Address of OP_OpenEphemeral instruction */
- Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
- KeyInfo *pKeyInfo = 0; /* Key information */
- int nVal; /* Size of vector pLeft */
-
- nVal = sqlite3ExprVectorSize(pLeft);
- assert( !isRowid || nVal==1 );
-
- /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
- ** expression it is handled the same way. An ephemeral table is
- ** filled with index keys representing the results from the
- ** SELECT or the <exprlist>.
- **
- ** If the 'x' expression is a column value, or the SELECT...
- ** statement returns a column value, then the affinity of that
- ** column is used to build the index keys. If both 'x' and the
- ** SELECT... statement are columns, then numeric affinity is used
- ** if either column has NUMERIC or INTEGER affinity. If neither
- ** 'x' nor the SELECT... statement are columns, then numeric affinity
- ** is used.
- */
- pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral,
- pExpr->iTable, (isRowid?0:nVal));
- pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
+ /* Begin coding the subroutine */
+ ExprSetProperty(pExpr, EP_Subrtn);
+ pExpr->y.sub.regReturn = ++pParse->nMem;
+ pExpr->y.sub.iAddr =
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
+ VdbeComment((v, "return address"));
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- /* Case 1: expr IN (SELECT ...)
- **
- ** Generate code to write the results of the select into the temporary
- ** table allocated and opened above.
- */
- Select *pSelect = pExpr->x.pSelect;
- ExprList *pEList = pSelect->pEList;
-
- ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY",
- jmpIfDynamic>=0?"":"CORRELATED "
- ));
- assert( !isRowid );
- /* If the LHS and RHS of the IN operator do not match, that
- ** error will have been caught long before we reach this point. */
- if( ALWAYS(pEList->nExpr==nVal) ){
- SelectDest dest;
- int i;
- sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
- dest.zAffSdst = exprINAffinity(pParse, pExpr);
- pSelect->iLimit = 0;
- testcase( pSelect->selFlags & SF_Distinct );
- testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
- if( sqlite3Select(pParse, pSelect, &dest) ){
- sqlite3DbFree(pParse->db, dest.zAffSdst);
- sqlite3KeyInfoUnref(pKeyInfo);
- return 0;
- }
- sqlite3DbFree(pParse->db, dest.zAffSdst);
- assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
- assert( pEList!=0 );
- assert( pEList->nExpr>0 );
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- for(i=0; i<nVal; i++){
- Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
- pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
- pParse, p, pEList->a[i].pExpr
- );
- }
- }
- }else if( ALWAYS(pExpr->x.pList!=0) ){
- /* Case 2: expr IN (exprlist)
- **
- ** For each expression, build an index key from the evaluation and
- ** store it in the temporary table. If <expr> is a column, then use
- ** that columns affinity when building index keys. If <expr> is not
- ** a column, use numeric affinity.
- */
- char affinity; /* Affinity of the LHS of the IN */
- int i;
- ExprList *pList = pExpr->x.pList;
- struct ExprList_item *pItem;
- int r1, r2, r3;
- affinity = sqlite3ExprAffinity(pLeft);
- if( !affinity ){
- affinity = SQLITE_AFF_BLOB;
- }
- if( pKeyInfo ){
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- }
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
+ }
- /* Loop through each expression in <exprlist>. */
- r1 = sqlite3GetTempReg(pParse);
- r2 = sqlite3GetTempReg(pParse);
- if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
- for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
- Expr *pE2 = pItem->pExpr;
- int iValToIns;
-
- /* If the expression is not constant then we will need to
- ** disable the test that was generated above that makes sure
- ** this code only executes once. Because for a non-constant
- ** expression we need to rerun this code each time.
- */
- if( jmpIfDynamic>=0 && !sqlite3ExprIsConstant(pE2) ){
- sqlite3VdbeChangeToNoop(v, jmpIfDynamic);
- jmpIfDynamic = -1;
- }
+ /* Check to see if this is a vector IN operator */
+ pLeft = pExpr->pLeft;
+ nVal = sqlite3ExprVectorSize(pLeft);
+ assert( !isRowid || nVal==1 );
- /* Evaluate the expression and insert it into the temp table */
- if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
- sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
- }else{
- r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
- if( isRowid ){
- sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
- sqlite3VdbeCurrentAddr(v)+2);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
- }else{
- sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
- }
- }
- }
- sqlite3ReleaseTempReg(pParse, r1);
- sqlite3ReleaseTempReg(pParse, r2);
+ /* Construct the ephemeral table that will contain the content of
+ ** RHS of the IN operator.
+ */
+ pExpr->iTable = iTab;
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral,
+ pExpr->iTable, (isRowid?0:nVal));
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
+ }else{
+ VdbeComment((v, "RHS of IN operator"));
+ }
+#endif
+ pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
+
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ /* Case 1: expr IN (SELECT ...)
+ **
+ ** Generate code to write the results of the select into the temporary
+ ** table allocated and opened above.
+ */
+ Select *pSelect = pExpr->x.pSelect;
+ ExprList *pEList = pSelect->pEList;
+
+ ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d",
+ addrOnce?"":"CORRELATED ", pSelect->selId
+ ));
+ assert( !isRowid );
+ /* If the LHS and RHS of the IN operator do not match, that
+ ** error will have been caught long before we reach this point. */
+ if( ALWAYS(pEList->nExpr==nVal) ){
+ SelectDest dest;
+ int i;
+ sqlite3SelectDestInit(&dest, SRT_Set, iTab);
+ dest.zAffSdst = exprINAffinity(pParse, pExpr);
+ pSelect->iLimit = 0;
+ testcase( pSelect->selFlags & SF_Distinct );
+ testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
+ if( sqlite3Select(pParse, pSelect, &dest) ){
+ sqlite3DbFree(pParse->db, dest.zAffSdst);
+ sqlite3KeyInfoUnref(pKeyInfo);
+ return;
}
- if( pKeyInfo ){
- sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
+ sqlite3DbFree(pParse->db, dest.zAffSdst);
+ assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
+ assert( pEList!=0 );
+ assert( pEList->nExpr>0 );
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ for(i=0; i<nVal; i++){
+ Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
+ pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
+ pParse, p, pEList->a[i].pExpr
+ );
}
- break;
+ }
+ }else if( ALWAYS(pExpr->x.pList!=0) ){
+ /* Case 2: expr IN (exprlist)
+ **
+ ** For each expression, build an index key from the evaluation and
+ ** store it in the temporary table. If <expr> is a column, then use
+ ** that columns affinity when building index keys. If <expr> is not
+ ** a column, use numeric affinity.
+ */
+ char affinity; /* Affinity of the LHS of the IN */
+ int i;
+ ExprList *pList = pExpr->x.pList;
+ struct ExprList_item *pItem;
+ int r1, r2, r3;
+ affinity = sqlite3ExprAffinity(pLeft);
+ if( !affinity ){
+ affinity = SQLITE_AFF_BLOB;
+ }
+ if( pKeyInfo ){
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
}
- case TK_EXISTS:
- case TK_SELECT:
- default: {
- /* Case 3: (SELECT ... FROM ...)
- ** or: EXISTS(SELECT ... FROM ...)
- **
- ** For a SELECT, generate code to put the values for all columns of
- ** the first row into an array of registers and return the index of
- ** the first register.
- **
- ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists)
- ** into a register and return that register number.
- **
- ** In both cases, the query is augmented with "LIMIT 1". Any
- ** preexisting limit is discarded in place of the new LIMIT 1.
+ /* Loop through each expression in <exprlist>. */
+ r1 = sqlite3GetTempReg(pParse);
+ r2 = sqlite3GetTempReg(pParse);
+ if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
+ for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
+ Expr *pE2 = pItem->pExpr;
+ int iValToIns;
+
+ /* If the expression is not constant then we will need to
+ ** disable the test that was generated above that makes sure
+ ** this code only executes once. Because for a non-constant
+ ** expression we need to rerun this code each time.
*/
- Select *pSel; /* SELECT statement to encode */
- SelectDest dest; /* How to deal with SELECT result */
- int nReg; /* Registers to allocate */
- Expr *pLimit; /* New limit expression */
-
- testcase( pExpr->op==TK_EXISTS );
- testcase( pExpr->op==TK_SELECT );
- assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
- assert( ExprHasProperty(pExpr, EP_xIsSelect) );
-
- pSel = pExpr->x.pSelect;
- ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
- jmpIfDynamic>=0?"":"CORRELATED "));
- nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
- sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
- pParse->nMem += nReg;
- if( pExpr->op==TK_SELECT ){
- dest.eDest = SRT_Mem;
- dest.iSdst = dest.iSDParm;
- dest.nSdst = nReg;
- sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
- VdbeComment((v, "Init subquery result"));
- }else{
- dest.eDest = SRT_Exists;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
- VdbeComment((v, "Init EXISTS result"));
+ if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
+ sqlite3VdbeChangeToNoop(v, addrOnce);
+ addrOnce = 0;
}
- pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
- if( pSel->pLimit ){
- sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
- pSel->pLimit->pLeft = pLimit;
+
+ /* Evaluate the expression and insert it into the temp table */
+ if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
+ sqlite3VdbeAddOp3(v, OP_InsertInt, iTab, r2, iValToIns);
}else{
- pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
- }
- pSel->iLimit = 0;
- if( sqlite3Select(pParse, pSel, &dest) ){
- return 0;
+ r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
+ if( isRowid ){
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
+ sqlite3VdbeCurrentAddr(v)+2);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp3(v, OP_Insert, iTab, r2, r3);
+ }else{
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1);
+ }
}
- rReg = dest.iSDParm;
- ExprSetVVAProperty(pExpr, EP_NoReduce);
- break;
}
+ sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3ReleaseTempReg(pParse, r2);
}
+ if( pKeyInfo ){
+ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
+ }
+ if( addrOnce ){
+ sqlite3VdbeJumpHere(v, addrOnce);
+ /* Subroutine return */
+ sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
+ sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
+ }
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
- if( rHasNullFlag ){
- sqlite3SetHasNullFlag(v, pExpr->iTable, rHasNullFlag);
+/*
+** Generate code for scalar subqueries used as a subquery expression
+** or EXISTS operator:
+**
+** (SELECT a FROM b) -- subquery
+** EXISTS (SELECT a FROM b) -- EXISTS subquery
+**
+** The pExpr parameter is the SELECT or EXISTS operator to be coded.
+**
+** The register that holds the result. For a multi-column SELECT,
+** the result is stored in a contiguous array of registers and the
+** return value is the register of the left-most result column.
+** Return 0 if an error occurs.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
+ int addrOnce = 0; /* Address of OP_Once at top of subroutine */
+ int rReg = 0; /* Register storing resulting */
+ Select *pSel; /* SELECT statement to encode */
+ SelectDest dest; /* How to deal with SELECT result */
+ int nReg; /* Registers to allocate */
+ Expr *pLimit; /* New limit expression */
+
+ Vdbe *v = pParse->pVdbe;
+ assert( v!=0 );
+ testcase( pExpr->op==TK_EXISTS );
+ testcase( pExpr->op==TK_SELECT );
+ assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
+ assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+ pSel = pExpr->x.pSelect;
+
+ /* The evaluation of the EXISTS/SELECT must be repeated every time it
+ ** is encountered if any of the following is true:
+ **
+ ** * The right-hand side is a correlated subquery
+ ** * The right-hand side is an expression list containing variables
+ ** * We are inside a trigger
+ **
+ ** If all of the above are false, then we can run this code just once
+ ** save the results, and reuse the same result on subsequent invocations.
+ */
+ if( !ExprHasProperty(pExpr, EP_VarSelect) ){
+ /* If this routine has already been coded, then invoke it as a
+ ** subroutine. */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId));
+ sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
+ pExpr->y.sub.iAddr);
+ return pExpr->iTable;
+ }
+
+ /* Begin coding the subroutine */
+ ExprSetProperty(pExpr, EP_Subrtn);
+ pExpr->y.sub.regReturn = ++pParse->nMem;
+ pExpr->y.sub.iAddr =
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
+ VdbeComment((v, "return address"));
+
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
+ }
+
+ /* For a SELECT, generate code to put the values for all columns of
+ ** the first row into an array of registers and return the index of
+ ** the first register.
+ **
+ ** If this is an EXISTS, write an integer 0 (not exists) or 1 (exists)
+ ** into a register and return that register number.
+ **
+ ** In both cases, the query is augmented with "LIMIT 1". Any
+ ** preexisting limit is discarded in place of the new LIMIT 1.
+ */
+ ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY %d",
+ addrOnce?"":"CORRELATED ", pSel->selId));
+ nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
+ sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
+ pParse->nMem += nReg;
+ if( pExpr->op==TK_SELECT ){
+ dest.eDest = SRT_Mem;
+ dest.iSdst = dest.iSDParm;
+ dest.nSdst = nReg;
+ sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
+ VdbeComment((v, "Init subquery result"));
+ }else{
+ dest.eDest = SRT_Exists;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
+ VdbeComment((v, "Init EXISTS result"));
+ }
+ pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
+ if( pSel->pLimit ){
+ sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
+ pSel->pLimit->pLeft = pLimit;
+ }else{
+ pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
+ }
+ pSel->iLimit = 0;
+ if( sqlite3Select(pParse, pSel, &dest) ){
+ return 0;
}
+ pExpr->iTable = rReg = dest.iSDParm;
+ ExprSetVVAProperty(pExpr, EP_NoReduce);
+ if( addrOnce ){
+ sqlite3VdbeJumpHere(v, addrOnce);
- if( jmpIfDynamic>=0 ){
- sqlite3VdbeJumpHere(v, jmpIfDynamic);
+ /* Subroutine return */
+ sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
+ sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
}
return rReg;
@@ -2931,6 +3041,7 @@ static void sqlite3ExprCodeIN(
int addrTruthOp; /* Address of opcode that determines the IN is true */
int destNotNull; /* Jump here if a comparison is not true in step 6 */
int addrTop; /* Top of the step-6 loop */
+ int iTab = 0; /* Index to use */
pLeft = pExpr->pLeft;
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
@@ -2942,7 +3053,7 @@ static void sqlite3ExprCodeIN(
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
/* Attempt to compute the RHS. After this step, if anything other than
- ** IN_INDEX_NOOP is returned, the table opened ith cursor pExpr->iTable
+ ** IN_INDEX_NOOP is returned, the table opened with cursor iTab
** contains the values that make up the RHS. If IN_INDEX_NOOP is returned,
** the RHS has not yet been coded. */
v = pParse->pVdbe;
@@ -2950,7 +3061,8 @@ static void sqlite3ExprCodeIN(
VdbeNoopComment((v, "begin IN expr"));
eType = sqlite3FindInIndex(pParse, pExpr,
IN_INDEX_MEMBERSHIP | IN_INDEX_NOOP_OK,
- destIfFalse==destIfNull ? 0 : &rRhsHasNull, aiMap);
+ destIfFalse==destIfNull ? 0 : &rRhsHasNull,
+ aiMap, &iTab);
assert( pParse->nErr || nVector==1 || eType==IN_INDEX_EPH
|| eType==IN_INDEX_INDEX_ASC || eType==IN_INDEX_INDEX_DESC
@@ -2996,7 +3108,7 @@ static void sqlite3ExprCodeIN(
if( eType==IN_INDEX_NOOP ){
ExprList *pList = pExpr->x.pList;
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- int labelOk = sqlite3VdbeMakeLabel(v);
+ int labelOk = sqlite3VdbeMakeLabel(pParse);
int r2, regToFree;
int regCkNull = 0;
int ii;
@@ -3040,7 +3152,7 @@ static void sqlite3ExprCodeIN(
if( destIfNull==destIfFalse ){
destStep2 = destIfFalse;
}else{
- destStep2 = destStep6 = sqlite3VdbeMakeLabel(v);
+ destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
}
for(i=0; i<nVector; i++){
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
@@ -3058,19 +3170,19 @@ static void sqlite3ExprCodeIN(
/* In this case, the RHS is the ROWID of table b-tree and so we also
** know that the RHS is non-NULL. Hence, we combine steps 3 and 4
** into a single opcode. */
- sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, rLhs);
+ sqlite3VdbeAddOp3(v, OP_SeekRowid, iTab, destIfFalse, rLhs);
VdbeCoverage(v);
addrTruthOp = sqlite3VdbeAddOp0(v, OP_Goto); /* Return True */
}else{
sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
if( destIfFalse==destIfNull ){
/* Combine Step 3 and Step 5 into a single opcode */
- sqlite3VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse,
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
rLhs, nVector); VdbeCoverage(v);
goto sqlite3ExprCodeIN_finished;
}
/* Ordinary Step 3, for the case where FALSE and NULL are distinct */
- addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0,
+ addrTruthOp = sqlite3VdbeAddOp4Int(v, OP_Found, iTab, 0,
rLhs, nVector); VdbeCoverage(v);
}
@@ -3095,10 +3207,10 @@ static void sqlite3ExprCodeIN(
** of the RHS.
*/
if( destStep6 ) sqlite3VdbeResolveLabel(v, destStep6);
- addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, destIfFalse);
VdbeCoverage(v);
if( nVector>1 ){
- destNotNull = sqlite3VdbeMakeLabel(v);
+ destNotNull = sqlite3VdbeMakeLabel(pParse);
}else{
/* For nVector==1, combine steps 6 and 7 by immediately returning
** FALSE if the first comparison is not NULL */
@@ -3110,7 +3222,7 @@ static void sqlite3ExprCodeIN(
int r3 = sqlite3GetTempReg(pParse);
p = sqlite3VectorFieldSubexpr(pLeft, i);
pColl = sqlite3ExprCollSeq(pParse, p);
- sqlite3VdbeAddOp3(v, OP_Column, pExpr->iTable, i, r3);
+ sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
(void*)pColl, P4_COLLSEQ);
VdbeCoverage(v);
@@ -3119,7 +3231,7 @@ static void sqlite3ExprCodeIN(
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull);
if( nVector>1 ){
sqlite3VdbeResolveLabel(v, destNotNull);
- sqlite3VdbeAddOp2(v, OP_Next, pExpr->iTable, addrTop+1);
+ sqlite3VdbeAddOp2(v, OP_Next, iTab, addrTop+1);
VdbeCoverage(v);
/* Step 7: If we reach this point, we know that the result must
@@ -3318,7 +3430,7 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
#if SQLITE_OMIT_SUBQUERY
iResult = 0;
#else
- iResult = sqlite3CodeSubselect(pParse, p, 0, 0);
+ iResult = sqlite3CodeSubselect(pParse, p);
#endif
}else{
int i;
@@ -3663,7 +3775,7 @@ expr_code_doover:
** arguments past the first non-NULL argument.
*/
if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
- int endCoalesce = sqlite3VdbeMakeLabel(v);
+ int endCoalesce = sqlite3VdbeMakeLabel(pParse);
assert( nFarg>=2 );
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
for(i=1; i<nFarg; i++){
@@ -3792,14 +3904,14 @@ expr_code_doover:
if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
sqlite3SubselectError(pParse, nCol, 1);
}else{
- return sqlite3CodeSubselect(pParse, pExpr, 0, 0);
+ return sqlite3CodeSubselect(pParse, pExpr);
}
break;
}
case TK_SELECT_COLUMN: {
int n;
if( pExpr->pLeft->iTable==0 ){
- pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
+ pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
}
assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
if( pExpr->iTable
@@ -3811,8 +3923,8 @@ expr_code_doover:
return pExpr->pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
- int destIfFalse = sqlite3VdbeMakeLabel(v);
- int destIfNull = sqlite3VdbeMakeLabel(v);
+ int destIfFalse = sqlite3VdbeMakeLabel(pParse);
+ int destIfNull = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
@@ -3952,9 +4064,9 @@ expr_code_doover:
pEList = pExpr->x.pList;
aListelem = pEList->a;
nExpr = pEList->nExpr;
- endLabel = sqlite3VdbeMakeLabel(v);
+ endLabel = sqlite3VdbeMakeLabel(pParse);
if( (pX = pExpr->pLeft)!=0 ){
- tempX = *pX;
+ exprNodeCopy(&tempX, pX);
testcase( pX->op==TK_COLUMN );
exprToRegister(&tempX, exprCodeVector(pParse, &tempX, &regFree1));
testcase( regFree1==0 );
@@ -3975,7 +4087,7 @@ expr_code_doover:
}else{
pTest = aListelem[i].pExpr;
}
- nextCase = sqlite3VdbeMakeLabel(v);
+ nextCase = sqlite3VdbeMakeLabel(pParse);
testcase( pTest->op==TK_COLUMN );
sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
@@ -4275,13 +4387,12 @@ static void exprCodeBetween(
Expr exprX; /* The x subexpression */
int regFree1 = 0; /* Temporary use register */
-
memset(&compLeft, 0, sizeof(Expr));
memset(&compRight, 0, sizeof(Expr));
memset(&exprAnd, 0, sizeof(Expr));
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- exprX = *pExpr->pLeft;
+ exprNodeCopy(&exprX, pExpr->pLeft);
exprAnd.op = TK_AND;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
@@ -4344,7 +4455,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
op = pExpr->op;
switch( op ){
case TK_AND: {
- int d2 = sqlite3VdbeMakeLabel(v);
+ int d2 = sqlite3VdbeMakeLabel(pParse);
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
@@ -4430,7 +4541,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_IN: {
- int destIfFalse = sqlite3VdbeMakeLabel(v);
+ int destIfFalse = sqlite3VdbeMakeLabel(pParse);
int destIfNull = jumpIfNull ? dest : destIfFalse;
sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
sqlite3VdbeGoto(v, dest);
@@ -4517,7 +4628,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
break;
}
case TK_OR: {
- int d2 = sqlite3VdbeMakeLabel(v);
+ int d2 = sqlite3VdbeMakeLabel(pParse);
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
@@ -4601,7 +4712,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
if( jumpIfNull ){
sqlite3ExprCodeIN(pParse, pExpr, dest, dest);
}else{
- int destIfNull = sqlite3VdbeMakeLabel(v);
+ int destIfNull = sqlite3VdbeMakeLabel(pParse);
sqlite3ExprCodeIN(pParse, pExpr, dest, destIfNull);
sqlite3VdbeResolveLabel(v, destIfNull);
}
@@ -4875,6 +4986,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
case TK_ISNOT:
case TK_NOT:
case TK_ISNULL:
+ case TK_NOTNULL:
case TK_IS:
case TK_OR:
case TK_CASE:
@@ -4883,6 +4995,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_ISNOT );
testcase( pExpr->op==TK_NOT );
testcase( pExpr->op==TK_ISNULL );
+ testcase( pExpr->op==TK_NOTNULL );
testcase( pExpr->op==TK_IS );
testcase( pExpr->op==TK_OR );
testcase( pExpr->op==TK_CASE );
@@ -5256,6 +5369,7 @@ void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
w.walkerDepth = 0;
w.u.pNC = pNC;
+ w.pParse = 0;
assert( pNC->pSrcList!=0 );
sqlite3WalkExpr(&w, pExpr);
}
diff --git a/chromium/third_party/sqlite/src/src/fkey.c b/chromium/third_party/sqlite/src/src/fkey.c
index b9aad0c9658..4106d12aaef 100644
--- a/chromium/third_party/sqlite/src/src/fkey.c
+++ b/chromium/third_party/sqlite/src/src/fkey.c
@@ -329,7 +329,7 @@ static void fkLookupParent(
int i; /* Iterator variable */
Vdbe *v = sqlite3GetVdbe(pParse); /* Vdbe to add code to */
int iCur = pParse->nTab - 1; /* Cursor number to use */
- int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */
+ int iOk = sqlite3VdbeMakeLabel(pParse); /* jump here if parent key found */
sqlite3VdbeVerifyAbortable(v,
(!pFKey->isDeferred
@@ -618,7 +618,6 @@ static void fkScanChildren(
pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight);
}else{
Expr *pEq, *pAll = 0;
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pIdx!=0 );
for(i=0; i<pIdx->nKeyCol; i++){
i16 iCol = pIdx->aiColumn[i];
@@ -730,7 +729,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
}
if( !p ) return;
- iSkip = sqlite3VdbeMakeLabel(v);
+ iSkip = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_FkIfZero, 1, iSkip); VdbeCoverage(v);
}
@@ -1015,7 +1014,7 @@ void sqlite3FkCheck(
/* Create a SrcList structure containing the child table. We need the
** child table as a SrcList for sqlite3WhereBegin() */
- pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
+ pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
struct SrcList_item *pItem = pSrc->a;
pItem->pTab = pFKey->pFrom;
@@ -1292,7 +1291,7 @@ static Trigger *fkActionTrigger(
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
- sqlite3SrcListAppend(db, 0, &tFrom, 0),
+ sqlite3SrcListAppend(pParse, 0, &tFrom, 0),
pWhere,
0, 0, 0, 0, 0
);
diff --git a/chromium/third_party/sqlite/src/src/func.c b/chromium/third_party/sqlite/src/src/func.c
index 94d94f995ac..b08fa5e5454 100644
--- a/chromium/third_party/sqlite/src/src/func.c
+++ b/chromium/third_party/sqlite/src/src/func.c
@@ -201,6 +201,7 @@ static void instrFunc(
int typeHaystack, typeNeedle;
int N = 1;
int isText;
+ unsigned char firstChar;
UNUSED_PARAMETER(argc);
typeHaystack = sqlite3_value_type(argv[0]);
@@ -219,7 +220,10 @@ static void instrFunc(
isText = 1;
}
if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
- while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
+ firstChar = zNeedle[0];
+ while( nNeedle<=nHaystack
+ && (zHaystack[0]!=firstChar || memcmp(zHaystack, zNeedle, nNeedle)!=0)
+ ){
N++;
do{
nHaystack--;
@@ -510,11 +514,11 @@ static void randomBlob(
int argc,
sqlite3_value **argv
){
- int n;
+ sqlite3_int64 n;
unsigned char *p;
assert( argc==1 );
UNUSED_PARAMETER(argc);
- n = sqlite3_value_int(argv[0]);
+ n = sqlite3_value_int64(argv[0]);
if( n<1 ){
n = 1;
}
diff --git a/chromium/third_party/sqlite/src/src/global.c b/chromium/third_party/sqlite/src/src/global.c
index 8011df7e564..4e7bc0e946b 100644
--- a/chromium/third_party/sqlite/src/src/global.c
+++ b/chromium/third_party/sqlite/src/src/global.c
@@ -189,6 +189,13 @@ const unsigned char sqlite3CtypeMap[256] = {
#endif
+/* The default maximum size of an in-memory database created using
+** sqlite3_deserialize()
+*/
+#ifndef SQLITE_MEMDB_DEFAULT_MAXSIZE
+# define SQLITE_MEMDB_DEFAULT_MAXSIZE 1073741824
+#endif
+
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -236,13 +243,16 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
+#endif
#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
0, /* bInternalFunctions */
0x7ffffffe, /* iOnceResetThreshold */
- SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */
+ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
};
/*
diff --git a/chromium/third_party/sqlite/src/src/hash.c b/chromium/third_party/sqlite/src/src/hash.c
index 04f67f67d27..1f0ef154f35 100644
--- a/chromium/third_party/sqlite/src/src/hash.c
+++ b/chromium/third_party/sqlite/src/src/hash.c
@@ -64,20 +64,6 @@ static unsigned int strHash(const char *z){
}
return h;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-static unsigned int strHashN(const char *z, int n){
- unsigned int h = 0;
- int i;
- for(i=0; i<n; i++){
- /* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
- ** 0x9e3779b1 is 2654435761 which is the closest prime number to
- ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
- h += sqlite3UpperToLower[z[i]];
- h *= 0x9e3779b1;
- }
- return h;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/* Link pNew element into the hash table pH. If pEntry!=0 then also
@@ -189,40 +175,6 @@ static HashElem *findElementWithHash(
}
return &nullElement;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-static HashElem *findElementWithHashN(
- const Hash *pH, /* The pH to be searched */
- const char *pKey, /* The key we are searching for */
- int nKey, /* Number of key bytes to use */
- unsigned int *pHash /* Write the hash value here */
-){
- HashElem *elem; /* Used to loop thru the element list */
- int count; /* Number of elements left to test */
- unsigned int h; /* The computed hash */
- static HashElem nullElement = { 0, 0, 0, 0 };
-
- if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
- struct _ht *pEntry;
- h = strHashN(pKey, nKey) % pH->htsize;
- pEntry = &pH->ht[h];
- elem = pEntry->chain;
- count = pEntry->count;
- }else{
- h = 0;
- elem = pH->first;
- count = pH->count;
- }
- if( pHash ) *pHash = h;
- while( count-- ){
- assert( elem!=0 );
- if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
- return elem;
- }
- elem = elem->next;
- }
- return &nullElement;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
@@ -267,14 +219,6 @@ void *sqlite3HashFind(const Hash *pH, const char *pKey){
assert( pKey!=0 );
return findElementWithHash(pH, pKey, 0)->data;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){
- assert( pH!=0 );
- assert( pKey!=0 );
- assert( nKey>=0 );
- return findElementWithHashN(pH, pKey, nKey, 0)->data;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/* Insert an element into the hash table pH. The key is pKey
** and the data is "data".
diff --git a/chromium/third_party/sqlite/src/src/insert.c b/chromium/third_party/sqlite/src/src/insert.c
index b21bf714923..6c358726f8d 100644
--- a/chromium/third_party/sqlite/src/src/insert.c
+++ b/chromium/third_party/sqlite/src/src/insert.c
@@ -319,6 +319,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){
aOp[7].p2 = memId+2;
aOp[7].p1 = memId;
aOp[10].p2 = memId;
+ if( pParse->nTab==0 ) pParse->nTab = 1;
}
}
@@ -825,6 +826,11 @@ void sqlite3Insert(
}
#ifndef SQLITE_OMIT_UPSERT
if( pUpsert ){
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
+ pTab->zName);
+ goto insert_cleanup;
+ }
pTabList->a[0].iCursor = iDataCur;
pUpsert->pUpsertSrc = pTabList;
pUpsert->regData = regData;
@@ -865,7 +871,7 @@ void sqlite3Insert(
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
- endOfLoop = sqlite3VdbeMakeLabel(v);
+ endOfLoop = sqlite3VdbeMakeLabel(pParse);
if( tmask & TRIGGER_BEFORE ){
int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1);
@@ -1347,7 +1353,20 @@ void sqlite3GenerateConstraintChecks(
}
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace );
+ addr1 = 0;
switch( onError ){
+ case OE_Replace: {
+ assert( onError==OE_Replace );
+ addr1 = sqlite3VdbeMakeLabel(pParse);
+ sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
+ VdbeCoverage(v);
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
+ sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
+ VdbeCoverage(v);
+ onError = OE_Abort;
+ /* Fall through into the OE_Abort case to generate code that runs
+ ** if both the input and the default value are NULL */
+ }
case OE_Abort:
sqlite3MayAbort(pParse);
/* Fall through */
@@ -1360,21 +1379,15 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
VdbeCoverage(v);
+ if( addr1 ) sqlite3VdbeResolveLabel(v, addr1);
break;
}
- case OE_Ignore: {
+ default: {
+ assert( onError==OE_Ignore );
sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
VdbeCoverage(v);
break;
}
- default: {
- assert( onError==OE_Replace );
- addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i);
- VdbeCoverage(v);
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
- sqlite3VdbeJumpHere(v, addr1);
- break;
- }
}
}
@@ -1395,7 +1408,7 @@ void sqlite3GenerateConstraintChecks(
** updated so there is no point it verifying the check constraint */
continue;
}
- allOk = sqlite3VdbeMakeLabel(v);
+ allOk = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
if( onError==OE_Ignore ){
@@ -1462,7 +1475,7 @@ void sqlite3GenerateConstraintChecks(
** exist in the table.
*/
if( pkChng && pPk==0 ){
- int addrRowidOk = sqlite3VdbeMakeLabel(v);
+ int addrRowidOk = sqlite3VdbeMakeLabel(pParse);
/* Figure out what action to take in case of a rowid collision */
onError = pTab->keyConf;
@@ -1612,7 +1625,7 @@ void sqlite3GenerateConstraintChecks(
VdbeComment((v, "Skip upsert subroutine"));
sqlite3VdbeJumpHere(v, upsertJump);
}else{
- addrUniqueOk = sqlite3VdbeMakeLabel(v);
+ addrUniqueOk = sqlite3VdbeMakeLabel(pParse);
}
if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
sqlite3TableAffinity(v, pTab, regNewData+1);
@@ -1695,7 +1708,11 @@ void sqlite3GenerateConstraintChecks(
** (3) There are no secondary indexes on the table
** (4) No delete triggers need to be fired if there is a conflict
** (5) No FK constraint counters need to be updated if a conflict occurs.
- */
+ **
+ ** This is not possible for ENABLE_PREUPDATE_HOOK builds, as the row
+ ** must be explicitly deleted in order to ensure any pre-update hook
+ ** is invoked. */
+#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
&& pPk==pIdx /* Condition 2 */
&& onError==OE_Replace /* Condition 1 */
@@ -1707,6 +1724,7 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue;
}
+#endif /* ifndef SQLITE_ENABLE_PREUPDATE_HOOK */
/* Check to see if the new index entry will be unique */
sqlite3VdbeVerifyAbortable(v, onError);
diff --git a/chromium/third_party/sqlite/src/src/legacy.c b/chromium/third_party/sqlite/src/src/legacy.c
index 2efbc52c127..06b8f4e8e91 100644
--- a/chromium/third_party/sqlite/src/src/legacy.c
+++ b/chromium/third_party/sqlite/src/src/legacy.c
@@ -46,7 +46,7 @@ int sqlite3_exec(
sqlite3_mutex_enter(db->mutex);
sqlite3Error(db, SQLITE_OK);
while( rc==SQLITE_OK && zSql[0] ){
- int nCol;
+ int nCol = 0;
char **azVals = 0;
pStmt = 0;
@@ -60,9 +60,7 @@ int sqlite3_exec(
zSql = zLeftover;
continue;
}
-
callbackIsInit = 0;
- nCol = sqlite3_column_count(pStmt);
while( 1 ){
int i;
@@ -73,6 +71,7 @@ int sqlite3_exec(
(SQLITE_DONE==rc && !callbackIsInit
&& db->flags&SQLITE_NullCallback)) ){
if( !callbackIsInit ){
+ nCol = sqlite3_column_count(pStmt);
azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*));
if( azCols==0 ){
goto exec_out;
diff --git a/chromium/third_party/sqlite/src/src/loadext.c b/chromium/third_party/sqlite/src/src/loadext.c
index 142a89a52e7..b926ea4c89e 100644
--- a/chromium/third_party/sqlite/src/src/loadext.c
+++ b/chromium/third_party/sqlite/src/src/loadext.c
@@ -650,7 +650,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
if( onoff ){
db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc;
}else{
- db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
+ db->flags &= ~(u64)(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
}
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
diff --git a/chromium/third_party/sqlite/src/src/main.c b/chromium/third_party/sqlite/src/src/main.c
index 478428ac27c..d58f8c633f8 100644
--- a/chromium/third_party/sqlite/src/src/main.c
+++ b/chromium/third_party/sqlite/src/src/main.c
@@ -653,6 +653,13 @@ int sqlite3_config(int op, ...){
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ case SQLITE_CONFIG_MEMDB_MAXSIZE: {
+ sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
+ break;
+ }
+#endif /* SQLITE_ENABLE_DESERIALIZE */
+
default: {
rc = SQLITE_ERROR;
break;
@@ -843,11 +850,11 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
if( aFlagOp[i].op==op ){
int onoff = va_arg(ap, int);
int *pRes = va_arg(ap, int*);
- u32 oldFlags = db->flags;
+ u64 oldFlags = db->flags;
if( onoff>0 ){
db->flags |= aFlagOp[i].mask;
}else if( onoff==0 ){
- db->flags &= ~aFlagOp[i].mask;
+ db->flags &= ~(u64)aFlagOp[i].mask;
}
if( oldFlags!=db->flags ){
sqlite3ExpirePreparedStatements(db, 0);
@@ -1310,7 +1317,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
- db->flags &= ~SQLITE_DeferFKs;
+ db->flags &= ~(u64)SQLITE_DeferFKs;
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
@@ -2052,6 +2059,8 @@ void *sqlite3_profile(
pOld = db->pProfileArg;
db->xProfile = xProfile;
db->pProfileArg = pArg;
+ db->mTrace &= SQLITE_TRACE_NONLEGACY_MASK;
+ if( db->xProfile ) db->mTrace |= SQLITE_TRACE_XPROFILE;
sqlite3_mutex_leave(db->mutex);
return pOld;
}
@@ -2403,7 +2412,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
z = sqlite3ErrStr(SQLITE_NOMEM_BKPT);
}else{
testcase( db->pErr==0 );
- z = (char*)sqlite3_value_text(db->pErr);
+ z = db->errCode ? (char*)sqlite3_value_text(db->pErr) : 0;
assert( !db->mallocFailed );
if( z==0 ){
z = sqlite3ErrStr(db->errCode);
@@ -2933,6 +2942,40 @@ int sqlite3ParseUri(
return rc;
}
+#if defined(SQLITE_HAS_CODEC)
+/*
+** Process URI filename query parameters relevant to the SQLite Encryption
+** Extension. Return true if any of the relevant query parameters are
+** seen and return false if not.
+*/
+int sqlite3CodecQueryParameters(
+ sqlite3 *db, /* Database connection */
+ const char *zDb, /* Which schema is being created/attached */
+ const char *zUri /* URI filename */
+){
+ const char *zKey;
+ if( (zKey = sqlite3_uri_parameter(zUri, "hexkey"))!=0 && zKey[0] ){
+ u8 iByte;
+ int i;
+ char zDecoded[40];
+ for(i=0, iByte=0; i<sizeof(zDecoded)*2 && sqlite3Isxdigit(zKey[i]); i++){
+ iByte = (iByte<<4) + sqlite3HexToInt(zKey[i]);
+ if( (i&1)!=0 ) zDecoded[i/2] = iByte;
+ }
+ sqlite3_key_v2(db, zDb, zDecoded, i/2);
+ return 1;
+ }else if( (zKey = sqlite3_uri_parameter(zUri, "key"))!=0 ){
+ sqlite3_key_v2(db, zDb, zKey, sqlite3Strlen30(zKey));
+ return 1;
+ }else if( (zKey = sqlite3_uri_parameter(zUri, "textkey"))!=0 ){
+ sqlite3_key_v2(db, zDb, zKey, -1);
+ return 1;
+ }else{
+ return 0;
+ }
+}
+#endif
+
/*
** This routine does the work of opening a database on behalf of
@@ -3286,26 +3329,13 @@ opendb_out:
}
#endif
#if defined(SQLITE_HAS_CODEC)
- if( rc==SQLITE_OK ){
- const char *zKey;
- if( (zKey = sqlite3_uri_parameter(zOpen, "hexkey"))!=0 && zKey[0] ){
- u8 iByte;
- int i;
- char zDecoded[40];
- for(i=0, iByte=0; i<sizeof(zDecoded)*2 && sqlite3Isxdigit(zKey[i]); i++){
- iByte = (iByte<<4) + sqlite3HexToInt(zKey[i]);
- if( (i&1)!=0 ) zDecoded[i/2] = iByte;
- }
- sqlite3_key_v2(db, 0, zDecoded, i/2);
- }else if( (zKey = sqlite3_uri_parameter(zOpen, "key"))!=0 ){
- sqlite3_key_v2(db, 0, zKey, sqlite3Strlen30(zKey));
- }
- }
+ if( rc==SQLITE_OK ) sqlite3CodecQueryParameters(db, 0, zOpen);
#endif
sqlite3_free(zOpen);
return rc & 0xff;
}
+
/*
** Open a new database handle.
*/
diff --git a/chromium/third_party/sqlite/src/src/memdb.c b/chromium/third_party/sqlite/src/src/memdb.c
index 15b4b277ee3..58da0488918 100644
--- a/chromium/third_party/sqlite/src/src/memdb.c
+++ b/chromium/third_party/sqlite/src/src/memdb.c
@@ -34,7 +34,8 @@ typedef struct MemFile MemFile;
struct MemFile {
sqlite3_file base; /* IO methods */
sqlite3_int64 sz; /* Size of the file */
- sqlite3_int64 szMax; /* Space allocated to aData */
+ sqlite3_int64 szAlloc; /* Space allocated to aData */
+ sqlite3_int64 szMax; /* Maximum allowed size of the file */
unsigned char *aData; /* content of the file */
int nMmap; /* Number of memory mapped pages */
unsigned mFlags; /* Flags */
@@ -160,10 +161,15 @@ static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
return SQLITE_FULL;
}
+ if( newSz>p->szMax ){
+ return SQLITE_FULL;
+ }
+ newSz *= 2;
+ if( newSz>p->szMax ) newSz = p->szMax;
pNew = sqlite3_realloc64(p->aData, newSz);
if( pNew==0 ) return SQLITE_NOMEM;
p->aData = pNew;
- p->szMax = newSz;
+ p->szAlloc = newSz;
return SQLITE_OK;
}
@@ -177,10 +183,11 @@ static int memdbWrite(
sqlite_int64 iOfst
){
MemFile *p = (MemFile *)pFile;
+ if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
if( iOfst+iAmt>p->sz ){
int rc;
- if( iOfst+iAmt>p->szMax
- && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK
+ if( iOfst+iAmt>p->szAlloc
+ && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
){
return rc;
}
@@ -226,6 +233,11 @@ static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
MemFile *p = (MemFile *)pFile;
+ if( eLock>SQLITE_LOCK_SHARED
+ && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
+ ){
+ return SQLITE_READONLY;
+ }
p->eLock = eLock;
return SQLITE_OK;
}
@@ -250,6 +262,19 @@ static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
rc = SQLITE_OK;
}
+ if( op==SQLITE_FCNTL_SIZE_LIMIT ){
+ sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
+ if( iLimit<p->sz ){
+ if( iLimit<0 ){
+ iLimit = p->szMax;
+ }else{
+ iLimit = p->sz;
+ }
+ }
+ p->szMax = iLimit;
+ *(sqlite3_int64*)pArg = iLimit;
+ rc = SQLITE_OK;
+ }
return rc;
}
@@ -280,8 +305,12 @@ static int memdbFetch(
void **pp
){
MemFile *p = (MemFile *)pFile;
- p->nMmap++;
- *pp = (void*)(p->aData + iOfst);
+ if( iOfst+iAmt>p->sz ){
+ *pp = 0;
+ }else{
+ p->nMmap++;
+ *pp = (void*)(p->aData + iOfst);
+ }
return SQLITE_OK;
}
@@ -311,6 +340,7 @@ static int memdbOpen(
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
p->base.pMethods = &memdb_io_methods;
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
return SQLITE_OK;
}
@@ -560,7 +590,11 @@ int sqlite3_deserialize(
}else{
p->aData = pData;
p->sz = szDb;
+ p->szAlloc = szBuf;
p->szMax = szBuf;
+ if( p->szMax<sqlite3GlobalConfig.mxMemdbSize ){
+ p->szMax = sqlite3GlobalConfig.mxMemdbSize;
+ }
p->mFlags = mFlags;
rc = SQLITE_OK;
}
diff --git a/chromium/third_party/sqlite/src/src/pager.c b/chromium/third_party/sqlite/src/src/pager.c
index 771330e9ab2..35f625d2c03 100644
--- a/chromium/third_party/sqlite/src/src/pager.c
+++ b/chromium/third_party/sqlite/src/src/pager.c
@@ -3839,7 +3839,10 @@ int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
pPager->mxPgno = mxPage;
}
assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */
- assert( pPager->mxPgno>=pPager->dbSize ); /* OP_MaxPgcnt enforces this */
+ /* assert( pPager->mxPgno>=pPager->dbSize ); */
+ /* OP_MaxPgcnt ensures that the parameter passed to this function is not
+ ** less than the total number of valid pages in the database. But this
+ ** may be less than Pager.dbSize, and so the assert() above is not valid */
return pPager->mxPgno;
}
diff --git a/chromium/third_party/sqlite/src/src/parse.y b/chromium/third_party/sqlite/src/src/parse.y
index cd38ebf51b5..845aec962fb 100644
--- a/chromium/third_party/sqlite/src/src/parse.y
+++ b/chromium/third_party/sqlite/src/src/parse.y
@@ -664,6 +664,12 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
+ if( pOld->fg.isTabFunc ){
+ pNew->u1.pFuncArg = pOld->u1.pFuncArg;
+ pOld->u1.pFuncArg = 0;
+ pOld->fg.isTabFunc = 0;
+ pNew->fg.isTabFunc = 1;
+ }
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
@@ -684,26 +690,26 @@ dbnm(A) ::= DOT nm(X). {A = X;}
%type fullname {SrcList*}
%destructor fullname {sqlite3SrcListDelete(pParse->db, $$);}
fullname(A) ::= nm(X). {
- A = sqlite3SrcListAppend(pParse->db,0,&X,0);
+ A = sqlite3SrcListAppend(pParse,0,&X,0);
if( IN_RENAME_OBJECT && A ) sqlite3RenameTokenMap(pParse, A->a[0].zName, &X);
}
fullname(A) ::= nm(X) DOT nm(Y). {
- A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);
+ A = sqlite3SrcListAppend(pParse,0,&X,&Y);
if( IN_RENAME_OBJECT && A ) sqlite3RenameTokenMap(pParse, A->a[0].zName, &Y);
}
%type xfullname {SrcList*}
%destructor xfullname {sqlite3SrcListDelete(pParse->db, $$);}
xfullname(A) ::= nm(X).
- {A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/}
+ {A = sqlite3SrcListAppend(pParse,0,&X,0); /*A-overwrites-X*/}
xfullname(A) ::= nm(X) DOT nm(Y).
- {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/}
+ {A = sqlite3SrcListAppend(pParse,0,&X,&Y); /*A-overwrites-X*/}
xfullname(A) ::= nm(X) DOT nm(Y) AS nm(Z). {
- A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/
+ A = sqlite3SrcListAppend(pParse,0,&X,&Y); /*A-overwrites-X*/
if( A ) A->a[0].zAlias = sqlite3NameFromToken(pParse->db, &Z);
}
xfullname(A) ::= nm(X) AS nm(Z). {
- A = sqlite3SrcListAppend(pParse->db,0,&X,0); /*A-overwrites-X*/
+ A = sqlite3SrcListAppend(pParse,0,&X,0); /*A-overwrites-X*/
if( A ) A->a[0].zAlias = sqlite3NameFromToken(pParse->db, &Z);
}
@@ -820,6 +826,10 @@ limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W)
orderby_opt(O) limit_opt(L). {
sqlite3SrcListIndexedBy(pParse, X, &I);
+#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ sqlite3ExprListDelete(pParse->db, O); O = 0;
+ sqlite3ExprDelete(pParse->db, L); L = 0;
+#endif
sqlite3DeleteFrom(pParse,X,W,O,L);
}
%endif
@@ -949,8 +959,7 @@ idlist(A) ::= nm(Y).
memcpy(p->u.zToken, t.z, t.n);
p->u.zToken[t.n] = 0;
if( sqlite3Isquote(p->u.zToken[0]) ){
- if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted;
- sqlite3Dequote(p->u.zToken);
+ sqlite3DequoteExpr(p);
}
#if SQLITE_MAX_EXPR_DEPTH>0
p->nHeight = 1;
@@ -1161,8 +1170,10 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
- sqlite3ExprDelete(pParse->db, A);
- A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1);
+ if( IN_RENAME_OBJECT==0 ){
+ sqlite3ExprDelete(pParse->db, A);
+ A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1);
+ }
}else if( Y->nExpr==1 ){
/* Expressions of the form:
**
@@ -1211,7 +1222,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
}
expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z) paren_exprlist(E). [IN] {
- SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
+ SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&Y,&Z);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
if( E ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, E);
A = sqlite3PExpr(pParse, TK_IN, A, 0);
@@ -1282,7 +1293,7 @@ paren_exprlist(A) ::= LP exprlist(X) RP. {A = X;}
cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D)
ON nm(Y) LP sortlist(Z) RP where_opt(W). {
sqlite3CreateIndex(pParse, &X, &D,
- sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U,
+ sqlite3SrcListAppend(pParse,0,&Y,0), Z, U,
&S, W, SQLITE_SO_ASC, NE, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &Y);
@@ -1361,8 +1372,12 @@ cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);}
//
%ifndef SQLITE_OMIT_VACUUM
%ifndef SQLITE_OMIT_ATTACH
-cmd ::= VACUUM. {sqlite3Vacuum(pParse,0);}
-cmd ::= VACUUM nm(X). {sqlite3Vacuum(pParse,&X);}
+%type vinto {Expr*}
+%destructor vinto {sqlite3ExprDelete(pParse->db, $$);}
+cmd ::= VACUUM vinto(Y). {sqlite3Vacuum(pParse,0,Y);}
+cmd ::= VACUUM nm(X) vinto(Y). {sqlite3Vacuum(pParse,&X,Y);}
+vinto(A) ::= INTO expr(X). {A = X;}
+vinto(A) ::= . {A = 0;}
%endif SQLITE_OMIT_ATTACH
%endif SQLITE_OMIT_VACUUM
diff --git a/chromium/third_party/sqlite/src/src/pcache1.c b/chromium/third_party/sqlite/src/src/pcache1.c
index 05ef4bde330..aac42677e42 100644
--- a/chromium/third_party/sqlite/src/src/pcache1.c
+++ b/chromium/third_party/sqlite/src/src/pcache1.c
@@ -92,16 +92,27 @@ typedef struct PGroup PGroup;
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
** PgHdr1.pCache->szPage bytes is allocated directly before this structure
** in memory.
+**
+** Note: Variables isBulkLocal and isAnchor were once type "u8". That works,
+** but causes a 2-byte gap in the structure for most architectures (since
+** pointers must be either 4 or 8-byte aligned). As this structure is located
+** in memory directly after the associated page data, if the database is
+** corrupt, code at the b-tree layer may overread the page buffer and
+** read part of this structure before the corruption is detected. This
+** can cause a valgrind error if the unitialized gap is accessed. Using u16
+** ensures there is no such gap, and therefore no bytes of unitialized memory
+** in the structure.
*/
struct PgHdr1 {
sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
unsigned int iKey; /* Key value (page number) */
- u8 isBulkLocal; /* This page from bulk local storage */
- u8 isAnchor; /* This is the PGroup.lru element */
+ u16 isBulkLocal; /* This page from bulk local storage */
+ u16 isAnchor; /* This is the PGroup.lru element */
PgHdr1 *pNext; /* Next in hash table chain */
PCache1 *pCache; /* Cache that currently owns this page */
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
+ /* NB: pLruPrev is only valid if pLruNext!=0 */
};
/*
@@ -302,6 +313,7 @@ static int pcache1InitBulk(PCache1 *pCache){
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
+ pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
pCache->pFree = pX;
zBulk += pCache->szAlloc;
}while( --nBulk );
@@ -574,7 +586,8 @@ static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
pPage->pLruPrev->pLruNext = pPage->pLruNext;
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
pPage->pLruNext = 0;
- pPage->pLruPrev = 0;
+ /* pPage->pLruPrev = 0;
+ ** No need to clear pLruPrev as it is never accessed if pLruNext is 0 */
assert( pPage->isAnchor==0 );
assert( pPage->pCache->pGroup->lru.isAnchor==1 );
pPage->pCache->nRecyclable--;
@@ -911,8 +924,9 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
pPage->iKey = iKey;
pPage->pNext = pCache->apHash[h];
pPage->pCache = pCache;
- pPage->pLruPrev = 0;
pPage->pLruNext = 0;
+ /* pPage->pLruPrev = 0;
+ ** No need to clear pLruPrev since it is not accessed when pLruNext==0 */
*(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage;
if( iKey>pCache->iMaxKey ){
@@ -1072,7 +1086,7 @@ static void pcache1Unpin(
/* It is an error to call this function if the page is already
** part of the PGroup LRU list.
*/
- assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
+ assert( pPage->pLruNext==0 );
assert( PAGE_IS_PINNED(pPage) );
if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
diff --git a/chromium/third_party/sqlite/src/src/pragma.c b/chromium/third_party/sqlite/src/src/pragma.c
index 264b10d9464..7dec846f22d 100644
--- a/chromium/third_party/sqlite/src/src/pragma.c
+++ b/chromium/third_party/sqlite/src/src/pragma.c
@@ -816,7 +816,7 @@ void sqlite3Pragma(
if( sqlite3GetBoolean(zRight, size!=0) ){
db->flags |= SQLITE_CacheSpill;
}else{
- db->flags &= ~SQLITE_CacheSpill;
+ db->flags &= ~(u64)SQLITE_CacheSpill;
}
setAllPagerFlags(db);
}
@@ -1376,7 +1376,7 @@ void sqlite3Pragma(
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
assert( x==0 );
}
- addrOk = sqlite3VdbeMakeLabel(v);
+ addrOk = sqlite3VdbeMakeLabel(pParse);
/* Generate code to read the child key values into registers
** regRow..regRow+n. If any of the child key values are NULL, this
@@ -1421,19 +1421,6 @@ void sqlite3Pragma(
#endif /* !defined(SQLITE_OMIT_TRIGGER) */
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
-#ifndef NDEBUG
- case PragTyp_PARSER_TRACE: {
- if( zRight ){
- if( sqlite3GetBoolean(zRight, 0) ){
- sqlite3ParserTrace(stdout, "parser: ");
- }else{
- sqlite3ParserTrace(0, 0);
- }
- }
- }
- break;
-#endif
-
/* Reinstall the LIKE and GLOB functions. The variant of LIKE
** used will be case sensitive or not depending on the RHS.
*/
@@ -1596,8 +1583,8 @@ void sqlite3Pragma(
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
if( db->mallocFailed==0 ){
- int addrCkFault = sqlite3VdbeMakeLabel(v);
- int addrCkOk = sqlite3VdbeMakeLabel(v);
+ int addrCkFault = sqlite3VdbeMakeLabel(pParse);
+ int addrCkOk = sqlite3VdbeMakeLabel(pParse);
char *zErr;
int k;
pParse->iSelfTab = iDataCur + 1;
@@ -1620,7 +1607,7 @@ void sqlite3Pragma(
/* Validate index entries for the current row */
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int jmp2, jmp3, jmp4, jmp5;
- int ckUniq = sqlite3VdbeMakeLabel(v);
+ int ckUniq = sqlite3VdbeMakeLabel(pParse);
if( pPk==pIdx ) continue;
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
pPrior, r1);
@@ -1641,7 +1628,7 @@ void sqlite3Pragma(
** current key. The entry is unique if (1) any column is NULL
** or (2) the next entry has a different key */
if( IsUniqueIndex(pIdx) ){
- int uniqOk = sqlite3VdbeMakeLabel(v);
+ int uniqOk = sqlite3VdbeMakeLabel(pParse);
int jmp6;
int kk;
for(kk=0; kk<pIdx->nKeyCol; kk++){
diff --git a/chromium/third_party/sqlite/src/src/pragma.h b/chromium/third_party/sqlite/src/src/pragma.h
index c16dd2f0878..6dbc995610d 100644
--- a/chromium/third_party/sqlite/src/src/pragma.h
+++ b/chromium/third_party/sqlite/src/src/pragma.h
@@ -49,8 +49,7 @@
#define PragTyp_HEXKEY 41
#define PragTyp_KEY 42
#define PragTyp_LOCK_STATUS 43
-#define PragTyp_PARSER_TRACE 44
-#define PragTyp_STATS 45
+#define PragTyp_STATS 44
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -461,12 +460,14 @@ static const PragmaName aPragmaName[] = {
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if defined(SQLITE_DEBUG)
{/* zName: */ "parser_trace",
- /* ePragTyp: */ PragTyp_PARSER_TRACE,
- /* ePragFlg: */ 0,
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
- /* iArg: */ 0 },
+ /* iArg: */ SQLITE_ParserTrace },
+#endif
#endif
#if defined(SQLITE_INTROSPECTION_PRAGMAS)
{/* zName: */ "pragma_list",
diff --git a/chromium/third_party/sqlite/src/src/prepare.c b/chromium/third_party/sqlite/src/src/prepare.c
index 87711315a0c..5f009c28636 100644
--- a/chromium/third_party/sqlite/src/src/prepare.c
+++ b/chromium/third_party/sqlite/src/src/prepare.c
@@ -45,6 +45,19 @@ static void corruptSchema(
}
/*
+** Check to see if any sibling index (another index on the same table)
+** of pIndex has the same root page number, and if it does, return true.
+** This would indicate a corrupt schema.
+*/
+int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
+ Index *p;
+ for(p=pIndex->pTable->pIndex; p; p=p->pNext){
+ if( p->tnum==pIndex->tnum && p!=pIndex ) return 1;
+ }
+ return 0;
+}
+
+/*
** This is the callback routine for the code that initializes the
** database. See sqlite3Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
@@ -65,6 +78,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
DbClearProperty(db, iDb, DB_Empty);
+ pData->nInitRow++;
if( db->mallocFailed ){
corruptSchema(pData, argv[0], 0);
return 1;
@@ -121,6 +135,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
if( pIndex==0
|| sqlite3GetInt32(argv[1],&pIndex->tnum)==0
|| pIndex->tnum<2
+ || sqlite3IndexHasDuplicateRootPage(pIndex)
){
corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
}
@@ -172,6 +187,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
initData.mInitFlags = mFlags;
+ initData.nInitRow = 0;
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
if( initData.rc ){
rc = initData.rc;
@@ -289,7 +305,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
** indices that the user might have created.
*/
if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){
- db->flags &= ~SQLITE_LegacyFileFmt;
+ db->flags &= ~(u64)SQLITE_LegacyFileFmt;
}
/* Read the schema information out of the schema tables
@@ -706,293 +722,6 @@ static int sqlite3LockAndPrepare(
return rc;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-/*
-** Checks if the specified token is a table, column, or function name,
-** based on the databases associated with the statement being prepared.
-** If the function fails, zero is returned and pRc is filled with the
-** error code.
-*/
-static int shouldTreatAsIdentifier(
- sqlite3 *db, /* Database handle. */
- const char *zToken, /* Pointer to start of token to be checked */
- int nToken, /* Length of token to be checked */
- int *pRc /* Pointer to error code upon failure */
-){
- int bFound = 0; /* Non-zero if token is an identifier name. */
- int i, j; /* Database and column loop indexes. */
- Schema *pSchema; /* Schema for current database. */
- Hash *pHash; /* Hash table of tables for current database. */
- HashElem *e; /* Hash element for hash table iteration. */
- Table *pTab; /* Database table for columns being checked. */
-
- if( sqlite3IsRowidN(zToken, nToken) ){
- return 1;
- }
- if( nToken>0 ){
- int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken);
- if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1;
- }
- assert( db!=0 );
- sqlite3_mutex_enter(db->mutex);
- sqlite3BtreeEnterAll(db);
- for(i=0; i<db->nDb; i++){
- pHash = &db->aFunc;
- if( sqlite3HashFindN(pHash, zToken, nToken) ){
- bFound = 1;
- break;
- }
- pSchema = db->aDb[i].pSchema;
- if( pSchema==0 ) continue;
- pHash = &pSchema->tblHash;
- if( sqlite3HashFindN(pHash, zToken, nToken) ){
- bFound = 1;
- break;
- }
- for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){
- pTab = sqliteHashData(e);
- if( pTab==0 ) continue;
- pHash = pTab->pColHash;
- if( pHash==0 ){
- pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash));
- if( pHash ){
- sqlite3HashInit(pHash);
- for(j=0; j<pTab->nCol; j++){
- Column *pCol = &pTab->aCol[j];
- sqlite3HashInsert(pHash, pCol->zName, pCol);
- }
- }else{
- *pRc = SQLITE_NOMEM_BKPT;
- bFound = 0;
- goto done;
- }
- }
- if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){
- bFound = 1;
- goto done;
- }
- }
- }
-done:
- sqlite3BtreeLeaveAll(db);
- sqlite3_mutex_leave(db->mutex);
- return bFound;
-}
-
-/*
-** Attempt to estimate the final output buffer size needed for the fully
-** normalized version of the specified SQL string. This should take into
-** account any potential expansion that could occur (e.g. via IN clauses
-** being expanded, etc). This size returned is the total number of bytes
-** including the NUL terminator.
-*/
-static int estimateNormalizedSize(
- const char *zSql, /* The original SQL string */
- int nSql, /* Length of original SQL string */
- u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
-){
- int nOut = nSql + 4;
- const char *z = zSql;
- while( nOut<nSql*5 ){
- while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; }
- if( z[0]==0 ) break;
- z++;
- if( z[0]!='N' && z[0]!='n' ) break;
- z++;
- while( sqlite3Isspace(z[0]) ){ z++; }
- if( z[0]!='(' ) break;
- z++;
- nOut += 5; /* ?,?,? */
- }
- return nOut;
-}
-
-/*
-** Copy the current token into the output buffer while dealing with quoted
-** identifiers. By default, all letters will be converted into lowercase.
-** If the bUpper flag is set, uppercase will be used. The piOut argument
-** will be used to update the target index into the output string.
-*/
-static void copyNormalizedToken(
- const char *zSql, /* The original SQL string */
- int iIn, /* Current index into the original SQL string */
- int nToken, /* Number of bytes in the current token */
- int tokenFlags, /* Flags returned by the tokenizer */
- char *zOut, /* The output string */
- int *piOut /* Pointer to target index into the output string */
-){
- int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED;
- int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD;
- int j = *piOut, k = 0;
- for(; k<nToken; k++){
- if( bQuoted ){
- if( k==0 && iIn>0 ){
- zOut[j++] = '"';
- continue;
- }else if( k==nToken-1 ){
- zOut[j++] = '"';
- continue;
- }
- }
- if( bKeyword ){
- zOut[j++] = sqlite3Toupper(zSql[iIn+k]);
- }else{
- zOut[j++] = sqlite3Tolower(zSql[iIn+k]);
- }
- }
- *piOut = j;
-}
-
-/*
-** Perform normalization of the SQL contained in the prepared statement and
-** store the result in the zNormSql field. The schema for the associated
-** databases are consulted while performing the normalization in order to
-** determine if a token appears to be an identifier. All identifiers are
-** left intact in the normalized SQL and all literals are replaced with a
-** single '?'.
-*/
-void sqlite3Normalize(
- Vdbe *pVdbe, /* VM being reprepared */
- const char *zSql, /* The original SQL string */
- int nSql, /* Size of the input string in bytes */
- u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
-){
- sqlite3 *db; /* Database handle. */
- char *z; /* The output string */
- int nZ; /* Size of the output string in bytes */
- int i; /* Next character to read from zSql[] */
- int j; /* Next character to fill in on z[] */
- int tokenType = 0; /* Type of the next token */
- int prevTokenType = 0; /* Type of the previous token, except spaces */
- int n; /* Size of the next token */
- int nParen = 0; /* Nesting level of parenthesis */
- Hash inHash; /* Table of parenthesis levels to output index. */
-
- db = sqlite3VdbeDb(pVdbe);
- assert( db!=0 );
- assert( pVdbe->zNormSql==0 );
- if( zSql==0 ) return;
- nZ = estimateNormalizedSize(zSql, nSql, prepFlags);
- z = sqlite3DbMallocRawNN(db, nZ);
- if( z==0 ) return;
- sqlite3HashInit(&inHash);
- for(i=j=0; i<nSql && zSql[i]; i+=n){
- int flags = 0;
- if( tokenType!=TK_SPACE ) prevTokenType = tokenType;
- n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags);
- switch( tokenType ){
- case TK_SPACE: {
- break;
- }
- case TK_ILLEGAL: {
- sqlite3DbFree(db, z);
- sqlite3HashClear(&inHash);
- return;
- }
- case TK_STRING:
- case TK_INTEGER:
- case TK_FLOAT:
- case TK_VARIABLE:
- case TK_BLOB: {
- z[j++] = '?';
- break;
- }
- case TK_LP:
- case TK_RP: {
- if( tokenType==TK_LP ){
- nParen++;
- if( prevTokenType==TK_IN ){
- assert( nParen<nSql );
- sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j));
- }
- }else{
- int jj;
- assert( nParen<nSql );
- jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen));
- if( jj>0 ){
- sqlite3HashInsert(&inHash, zSql+nParen, 0);
- assert( jj+6<nZ );
- memcpy(z+jj+1, "?,?,?", 5);
- j = jj+6;
- assert( nZ-1-j>=0 );
- assert( nZ-1-j<nZ );
- memset(z+j, 0, nZ-1-j);
- }
- nParen--;
- }
- assert( nParen>=0 );
- /* Fall through */
- }
- case TK_MINUS:
- case TK_SEMI:
- case TK_PLUS:
- case TK_STAR:
- case TK_SLASH:
- case TK_REM:
- case TK_EQ:
- case TK_LE:
- case TK_NE:
- case TK_LSHIFT:
- case TK_LT:
- case TK_RSHIFT:
- case TK_GT:
- case TK_GE:
- case TK_BITOR:
- case TK_CONCAT:
- case TK_COMMA:
- case TK_BITAND:
- case TK_BITNOT:
- case TK_DOT:
- case TK_IN:
- case TK_IS:
- case TK_NOT:
- case TK_NULL:
- case TK_ID: {
- if( tokenType==TK_NULL ){
- if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){
- /* NULL is a keyword in this case, not a literal value */
- }else{
- /* Here the NULL is a literal value */
- z[j++] = '?';
- break;
- }
- }
- if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){
- z[j++] = ' ';
- }
- if( tokenType==TK_ID ){
- int i2 = i, n2 = n, rc = SQLITE_OK;
- if( nParen>0 ){
- assert( nParen<nSql );
- sqlite3HashInsert(&inHash, zSql+nParen, 0);
- }
- if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; }
- if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, z);
- sqlite3HashClear(&inHash);
- return;
- }
- if( sqlite3_keyword_check(zSql+i2, n2)==0 ){
- z[j++] = '?';
- break;
- }
- }
- }
- copyNormalizedToken(zSql, i, n, flags, z, &j);
- break;
- }
- }
- }
- assert( j<nZ && "one" );
- while( j>0 && z[j-1]==' ' ){ j--; }
- if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; }
- z[j] = 0;
- assert( j<nZ && "two" );
- pVdbe->zNormSql = z;
- sqlite3HashClear(&inHash);
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Rerun the compilation of a statement after a schema change.
diff --git a/chromium/third_party/sqlite/src/src/printf.c b/chromium/third_party/sqlite/src/src/printf.c
index 8474195d3c9..5c388797072 100644
--- a/chromium/third_party/sqlite/src/src/printf.c
+++ b/chromium/third_party/sqlite/src/src/printf.c
@@ -155,6 +155,27 @@ static char *getTextArg(PrintfArguments *p){
return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
}
+/*
+** Allocate memory for a temporary buffer needed for printf rendering.
+**
+** If the requested size of the temp buffer is larger than the size
+** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.
+** Do the size check before the memory allocation to prevent rogue
+** SQL from requesting large allocations using the precision or width
+** field of the printf() function.
+*/
+static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
+ char *z;
+ if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
+ setStrAccumError(pAccum, SQLITE_TOOBIG);
+ return 0;
+ }
+ z = sqlite3DbMallocRaw(pAccum->db, n);
+ if( z==0 ){
+ setStrAccumError(pAccum, SQLITE_NOMEM);
+ }
+ return z;
+}
/*
** On machines with a small stack size, you can redefine the
@@ -237,6 +258,9 @@ void sqlite3_str_vappendf(
flag_leftjustify = flag_prefix = cThousand =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
+ width = 0;
+ flag_long = 0;
+ precision = -1;
do{
switch( c ){
case '-': flag_leftjustify = 1; break;
@@ -247,80 +271,93 @@ void sqlite3_str_vappendf(
case '0': flag_zeropad = 1; break;
case ',': cThousand = ','; break;
default: done = 1; break;
- }
- }while( !done && (c=(*++fmt))!=0 );
- /* Get the field width */
- if( c=='*' ){
- if( bArgList ){
- width = (int)getIntArg(pArgList);
- }else{
- width = va_arg(ap,int);
- }
- if( width<0 ){
- flag_leftjustify = 1;
- width = width >= -2147483647 ? -width : 0;
- }
- c = *++fmt;
- }else{
- unsigned wx = 0;
- while( c>='0' && c<='9' ){
- wx = wx*10 + c - '0';
- c = *++fmt;
- }
- testcase( wx>0x7fffffff );
- width = wx & 0x7fffffff;
- }
- assert( width>=0 );
+ case 'l': {
+ flag_long = 1;
+ c = *++fmt;
+ if( c=='l' ){
+ c = *++fmt;
+ flag_long = 2;
+ }
+ done = 1;
+ break;
+ }
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9': {
+ unsigned wx = c - '0';
+ while( (c = *++fmt)>='0' && c<='9' ){
+ wx = wx*10 + c - '0';
+ }
+ testcase( wx>0x7fffffff );
+ width = wx & 0x7fffffff;
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
- if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
- width = SQLITE_PRINTF_PRECISION_LIMIT;
- }
+ if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
+ width = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
#endif
-
- /* Get the precision */
- if( c=='.' ){
- c = *++fmt;
- if( c=='*' ){
- if( bArgList ){
- precision = (int)getIntArg(pArgList);
- }else{
- precision = va_arg(ap,int);
+ if( c!='.' && c!='l' ){
+ done = 1;
+ }else{
+ fmt--;
+ }
+ break;
}
- c = *++fmt;
- if( precision<0 ){
- precision = precision >= -2147483647 ? -precision : -1;
+ case '*': {
+ if( bArgList ){
+ width = (int)getIntArg(pArgList);
+ }else{
+ width = va_arg(ap,int);
+ }
+ if( width<0 ){
+ flag_leftjustify = 1;
+ width = width >= -2147483647 ? -width : 0;
+ }
+#ifdef SQLITE_PRINTF_PRECISION_LIMIT
+ if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
+ width = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
+#endif
+ if( (c = fmt[1])!='.' && c!='l' ){
+ c = *++fmt;
+ done = 1;
+ }
+ break;
}
- }else{
- unsigned px = 0;
- while( c>='0' && c<='9' ){
- px = px*10 + c - '0';
+ case '.': {
c = *++fmt;
- }
- testcase( px>0x7fffffff );
- precision = px & 0x7fffffff;
- }
- }else{
- precision = -1;
- }
- assert( precision>=(-1) );
+ if( c=='*' ){
+ if( bArgList ){
+ precision = (int)getIntArg(pArgList);
+ }else{
+ precision = va_arg(ap,int);
+ }
+ if( precision<0 ){
+ precision = precision >= -2147483647 ? -precision : -1;
+ }
+ c = *++fmt;
+ }else{
+ unsigned px = 0;
+ while( c>='0' && c<='9' ){
+ px = px*10 + c - '0';
+ c = *++fmt;
+ }
+ testcase( px>0x7fffffff );
+ precision = px & 0x7fffffff;
+ }
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
- if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
- precision = SQLITE_PRINTF_PRECISION_LIMIT;
- }
+ if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
+ precision = SQLITE_PRINTF_PRECISION_LIMIT;
+ }
#endif
-
-
- /* Get the conversion type modifier */
- if( c=='l' ){
- flag_long = 1;
- c = *++fmt;
- if( c=='l' ){
- flag_long = 2;
- c = *++fmt;
+ if( c=='l' ){
+ --fmt;
+ }else{
+ done = 1;
+ }
+ break;
+ }
}
- }else{
- flag_long = 0;
- }
+ }while( !done && (c=(*++fmt))!=0 );
+
/* Fetch the info entry for the field */
infop = &fmtinfo[0];
xtype = etINVALID;
@@ -405,12 +442,11 @@ void sqlite3_str_vappendf(
nOut = etBUFSIZE;
zOut = buf;
}else{
- u64 n = (u64)precision + 10 + precision/3;
- zOut = zExtra = sqlite3Malloc( n );
- if( zOut==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
+ u64 n;
+ n = (u64)precision + 10;
+ if( cThousand ) n += precision/3;
+ zOut = zExtra = printfTempBuf(pAccum, n);
+ if( zOut==0 ) return;
nOut = (int)n;
}
bufpt = &zOut[nOut-1];
@@ -529,12 +565,12 @@ void sqlite3_str_vappendf(
}else{
e2 = exp;
}
- if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){
- bufpt = zExtra
- = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
- if( bufpt==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
+ {
+ i64 szBufNeeded; /* Size of a temporary buffer needed */
+ szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;
+ if( szBufNeeded > etBUFSIZE ){
+ bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);
+ if( bufpt==0 ) return;
}
}
zOut = bufpt;
@@ -758,11 +794,8 @@ void sqlite3_str_vappendf(
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 3;
if( n>etBUFSIZE ){
- bufpt = zExtra = sqlite3Malloc( n );
- if( bufpt==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
- return;
- }
+ bufpt = zExtra = printfTempBuf(pAccum, n);
+ if( bufpt==0 ) return;
}else{
bufpt = buf;
}
diff --git a/chromium/third_party/sqlite/src/src/resolve.c b/chromium/third_party/sqlite/src/src/resolve.c
index 9d03e075d2b..edf1e203440 100644
--- a/chromium/third_party/sqlite/src/src/resolve.c
+++ b/chromium/third_party/sqlite/src/src/resolve.c
@@ -80,7 +80,6 @@ static void resolveAlias(
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
- ExprSetProperty(pDup, EP_Alias);
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
@@ -474,6 +473,25 @@ static int lookupName(
if( cnt==0 && zTab==0 ){
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
+ /* If a double-quoted identifier does not match any known column name,
+ ** then treat it as a string.
+ **
+ ** This hack was added in the early days of SQLite in a misguided attempt
+ ** to be compatible with MySQL 3.x, which used double-quotes for strings.
+ ** I now sorely regret putting in this hack. The effect of this hack is
+ ** that misspelled identifier names are silently converted into strings
+ ** rather than causing an error, to the frustration of countless
+ ** programmers. To all those frustrated programmers, my apologies.
+ **
+ ** Someday, I hope to get rid of this hack. Unfortunately there is
+ ** a huge amount of legacy SQL that uses it. So for now, we just
+ ** issue a warning.
+ */
+ sqlite3_log(SQLITE_WARNING,
+ "double-quoted string literal: \"%w\"", zCol);
+#ifdef SQLITE_ENABLE_NORMALIZE
+ sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
+#endif
pExpr->op = TK_STRING;
pExpr->y.pTab = 0;
return WRC_Prune;
@@ -840,10 +858,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pExpr->y.pWin ){
Select *pSel = pNC->pWinSelect;
+ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
- sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
if( 0==pSel->pWin
|| 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin)
){
@@ -1120,32 +1138,53 @@ static int resolveCompoundOrderBy(
}else{
iCol = resolveAsName(pParse, pEList, pE);
if( iCol==0 ){
- pDup = sqlite3ExprDup(db, pE, 0);
+ /* Now test if expression pE matches one of the values returned
+ ** by pSelect. In the usual case this is done by duplicating the
+ ** expression, resolving any symbols in it, and then comparing
+ ** it against each expression returned by the SELECT statement.
+ ** Once the comparisons are finished, the duplicate expression
+ ** is deleted.
+ **
+ ** Or, if this is running as part of an ALTER TABLE operation,
+ ** resolve the symbols in the actual expression, not a duplicate.
+ ** And, if one of the comparisons is successful, leave the expression
+ ** as is instead of transforming it to an integer as in the usual
+ ** case. This allows the code in alter.c to modify column
+ ** refererences within the ORDER BY expression as required. */
+ if( IN_RENAME_OBJECT ){
+ pDup = pE;
+ }else{
+ pDup = sqlite3ExprDup(db, pE, 0);
+ }
if( !db->mallocFailed ){
assert(pDup);
iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
}
- sqlite3ExprDelete(db, pDup);
+ if( !IN_RENAME_OBJECT ){
+ sqlite3ExprDelete(db, pDup);
+ }
}
}
if( iCol>0 ){
/* Convert the ORDER BY term into an integer column number iCol,
** taking care to preserve the COLLATE clause if it exists */
- Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
- if( pNew==0 ) return 1;
- pNew->flags |= EP_IntValue;
- pNew->u.iValue = iCol;
- if( pItem->pExpr==pE ){
- pItem->pExpr = pNew;
- }else{
- Expr *pParent = pItem->pExpr;
- assert( pParent->op==TK_COLLATE );
- while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
- assert( pParent->pLeft==pE );
- pParent->pLeft = pNew;
+ if( !IN_RENAME_OBJECT ){
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+ if( pNew==0 ) return 1;
+ pNew->flags |= EP_IntValue;
+ pNew->u.iValue = iCol;
+ if( pItem->pExpr==pE ){
+ pItem->pExpr = pNew;
+ }else{
+ Expr *pParent = pItem->pExpr;
+ assert( pParent->op==TK_COLLATE );
+ while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
+ assert( pParent->pLeft==pE );
+ pParent->pLeft = pNew;
+ }
+ sqlite3ExprDelete(db, pE);
+ pItem->u.x.iOrderByCol = (u16)iCol;
}
- sqlite3ExprDelete(db, pE);
- pItem->u.x.iOrderByCol = (u16)iCol;
pItem->done = 1;
}else{
moreToDo = 1;
@@ -1494,6 +1533,19 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( IN_RENAME_OBJECT ){
+ Window *pWin;
+ for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
+ if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
+ || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
+ ){
+ return WRC_Abort;
+ }
+ }
+ }
+#endif
+
/* If this is part of a compound SELECT, check that it has the right
** number of expressions in the select list. */
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
@@ -1644,36 +1696,45 @@ void sqlite3ResolveSelectNames(
}
/*
-** Resolve names in expressions that can only reference a single table:
+** Resolve names in expressions that can only reference a single table
+** or which cannot reference any tables at all. Examples:
**
-** * CHECK constraints
-** * WHERE clauses on partial indices
+** (1) CHECK constraints
+** (2) WHERE clauses on partial indices
+** (3) Expressions in indexes on expressions
+** (4) Expression arguments to VACUUM INTO.
**
-** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression
-** is set to -1 and the Expr.iColumn value is set to the column number.
+** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN
+** nodes of the expression is set to -1 and the Expr.iColumn value is
+** set to the column number. In case (4), TK_COLUMN nodes cause an error.
**
** Any errors cause an error message to be set in pParse.
*/
-void sqlite3ResolveSelfReference(
+int sqlite3ResolveSelfReference(
Parse *pParse, /* Parsing context */
- Table *pTab, /* The table being referenced */
- int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr */
+ Table *pTab, /* The table being referenced, or NULL */
+ int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr, or 0 */
Expr *pExpr, /* Expression to resolve. May be NULL. */
ExprList *pList /* Expression list to resolve. May be NULL. */
){
SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
NameContext sNC; /* Name context for pParse->pNewTable */
+ int rc;
- assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr );
+ assert( type==0 || pTab!=0 );
+ assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr || pTab==0 );
memset(&sNC, 0, sizeof(sNC));
memset(&sSrc, 0, sizeof(sSrc));
- sSrc.nSrc = 1;
- sSrc.a[0].zName = pTab->zName;
- sSrc.a[0].pTab = pTab;
- sSrc.a[0].iCursor = -1;
+ if( pTab ){
+ sSrc.nSrc = 1;
+ sSrc.a[0].zName = pTab->zName;
+ sSrc.a[0].pTab = pTab;
+ sSrc.a[0].iCursor = -1;
+ }
sNC.pParse = pParse;
sNC.pSrcList = &sSrc;
sNC.ncFlags = type;
- if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
- if( pList ) sqlite3ResolveExprListNames(&sNC, pList);
+ if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
+ if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
+ return rc;
}
diff --git a/chromium/third_party/sqlite/src/src/select.c b/chromium/third_party/sqlite/src/src/select.c
index c68c1ddc643..eeb6044a976 100644
--- a/chromium/third_party/sqlite/src/src/select.c
+++ b/chromium/third_party/sqlite/src/src/select.c
@@ -631,7 +631,7 @@ static void pushOntoSorter(
}
assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
- pSort->labelDone = sqlite3VdbeMakeLabel(v);
+ pSort->labelDone = sqlite3VdbeMakeLabel(pParse);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
if( bSeq ){
@@ -670,7 +670,7 @@ static void pushOntoSorter(
pKI->nAllField-pKI->nKeyField-1);
addrJmp = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
- pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
+ pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse);
pSort->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
@@ -1417,7 +1417,7 @@ static void generateSortTail(
){
Vdbe *v = pParse->pVdbe; /* The prepared statement */
int addrBreak = pSort->labelDone; /* Jump here to exit loop */
- int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
+ int addrContinue = sqlite3VdbeMakeLabel(pParse);/* Jump here for next cycle */
int addr; /* Top of output loop. Jump for Next. */
int addrOnce = 0;
int iTab;
@@ -2083,15 +2083,15 @@ void sqlite3SelectAddColumnTypeAndCollation(
Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
Table *pTab;
sqlite3 *db = pParse->db;
- int savedFlags;
+ u64 savedFlags;
savedFlags = db->flags;
- db->flags &= ~SQLITE_FullColNames;
+ db->flags &= ~(u64)SQLITE_FullColNames;
db->flags |= SQLITE_ShortColNames;
sqlite3SelectPrep(pParse, pSelect, 0);
+ db->flags = savedFlags;
if( pParse->nErr ) return 0;
while( pSelect->pPrior ) pSelect = pSelect->pPrior;
- db->flags = savedFlags;
pTab = sqlite3DbMallocZero(db, sizeof(Table) );
if( pTab==0 ){
return 0;
@@ -2335,7 +2335,7 @@ static void generateWithRecursiveQuery(
if( sqlite3AuthCheck(pParse, SQLITE_RECURSIVE, 0, 0, 0) ) return;
/* Process the LIMIT and OFFSET clauses, if they exist */
- addrBreak = sqlite3VdbeMakeLabel(v);
+ addrBreak = sqlite3VdbeMakeLabel(pParse);
p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit;
@@ -2405,7 +2405,7 @@ static void generateWithRecursiveQuery(
sqlite3VdbeAddOp1(v, OP_Delete, iQueue);
/* Output the single row in Current */
- addrCont = sqlite3VdbeMakeLabel(v);
+ addrCont = sqlite3VdbeMakeLabel(pParse);
codeOffset(v, regOffset, addrCont);
selectInnerLoop(pParse, p, iCurrent,
0, 0, pDest, addrCont, addrBreak);
@@ -2713,8 +2713,8 @@ static int multiSelect(
if( dest.eDest!=priorOp ){
int iCont, iBreak, iStart;
assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(v);
- iCont = sqlite3VdbeMakeLabel(v);
+ iBreak = sqlite3VdbeMakeLabel(pParse);
+ iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
iStart = sqlite3VdbeCurrentAddr(v);
@@ -2782,8 +2782,8 @@ static int multiSelect(
** tables.
*/
assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(v);
- iCont = sqlite3VdbeMakeLabel(v);
+ iBreak = sqlite3VdbeMakeLabel(pParse);
+ iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
r1 = sqlite3GetTempReg(pParse);
@@ -2913,7 +2913,7 @@ static int generateOutputSubroutine(
int addr;
addr = sqlite3VdbeCurrentAddr(v);
- iContinue = sqlite3VdbeMakeLabel(v);
+ iContinue = sqlite3VdbeMakeLabel(pParse);
/* Suppress duplicates for UNION, EXCEPT, and INTERSECT
*/
@@ -3150,8 +3150,8 @@ static int multiSelectOrderBy(
db = pParse->db;
v = pParse->pVdbe;
assert( v!=0 ); /* Already thrown the error if VDBE alloc failed */
- labelEnd = sqlite3VdbeMakeLabel(v);
- labelCmpr = sqlite3VdbeMakeLabel(v);
+ labelEnd = sqlite3VdbeMakeLabel(pParse);
+ labelCmpr = sqlite3VdbeMakeLabel(pParse);
/* Patch up the ORDER BY clause
@@ -3467,6 +3467,7 @@ static Expr *substExpr(
ifNullRow.iTable = pSubst->iNewTable;
pCopy = &ifNullRow;
}
+ testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
if( pNew && pSubst->isLeftJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
@@ -3959,11 +3960,9 @@ static int flattenSubquery(
jointype = pSubitem->fg.jointype;
}else{
assert( pParent!=p ); /* 2nd and subsequent times through the loop */
- pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pSrc==0 ){
- assert( db->mallocFailed );
- break;
- }
+ pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
+ if( pSrc==0 ) break;
+ pParent->pSrc = pSrc;
}
/* The subquery uses a single slot of the FROM clause of the outer
@@ -3982,10 +3981,9 @@ static int flattenSubquery(
** for the two elements in the FROM clause of the subquery.
*/
if( nSubSrc>1 ){
- pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
- if( db->mallocFailed ){
- break;
- }
+ pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
+ if( pSrc==0 ) break;
+ pParent->pSrc = pSrc;
}
/* Transfer the FROM clause terms from the subquery into the
@@ -4031,7 +4029,8 @@ static int flattenSubquery(
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}
- pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
+ pWhere = pSub->pWhere;
+ pSub->pWhere = 0;
if( isLeftJoin>0 ){
setJoinExpr(pWhere, iNewParent);
}
@@ -5334,7 +5333,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
regAgg = 0;
}
if( pF->iDistinct>=0 ){
- addrNext = sqlite3VdbeMakeLabel(v);
+ addrNext = sqlite3VdbeMakeLabel(pParse);
testcase( nArg==0 ); /* Error condition */
testcase( nArg>1 ); /* Also an error */
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
@@ -5744,6 +5743,7 @@ int sqlite3Select(
}
if( flattenSubquery(pParse, p, i, isAgg) ){
+ if( pParse->nErr ) goto select_end;
/* This subquery can be absorbed into its parent. */
i = -1;
}
@@ -5839,22 +5839,12 @@ int sqlite3Select(
pSub = pItem->pSelect;
if( pSub==0 ) continue;
- /* Sometimes the code for a subquery will be generated more than
- ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
- ** for example. In that case, do not regenerate the code to manifest
- ** a view or the co-routine to implement a view. The first instance
- ** is sufficient, though the subroutine to manifest the view does need
- ** to be invoked again. */
- if( pItem->addrFillSub ){
- if( pItem->fg.viaCoroutine==0 ){
- /* The subroutine that manifests the view might be a one-time routine,
- ** or it might need to be rerun on each iteration because it
- ** encodes a correlated subquery. */
- testcase( sqlite3VdbeGetOp(v, pItem->addrFillSub)->opcode==OP_Once );
- sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
- }
- continue;
- }
+ /* The code for a subquery should only be generated once, though it is
+ ** technically harmless for it to be generated multiple times. The
+ ** following assert() will detect if something changes to cause
+ ** the same subquery to be coded multiple times, as a signal to the
+ ** developers to try to optimize the situation. */
+ assert( pItem->addrFillSub==0 );
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
@@ -6042,7 +6032,7 @@ int sqlite3Select(
/* Set the limiter.
*/
- iEnd = sqlite3VdbeMakeLabel(v);
+ iEnd = sqlite3VdbeMakeLabel(pParse);
if( (p->selFlags & SF_FixedLimit)==0 ){
p->nSelectRow = 320; /* 4 billion rows */
}
@@ -6109,9 +6099,9 @@ int sqlite3Select(
assert( p->pEList==pEList );
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pWin ){
- int addrGosub = sqlite3VdbeMakeLabel(v);
- int iCont = sqlite3VdbeMakeLabel(v);
- int iBreak = sqlite3VdbeMakeLabel(v);
+ int addrGosub = sqlite3VdbeMakeLabel(pParse);
+ int iCont = sqlite3VdbeMakeLabel(pParse);
+ int iBreak = sqlite3VdbeMakeLabel(pParse);
int regGosub = ++pParse->nMem;
sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);
@@ -6186,7 +6176,7 @@ int sqlite3Select(
}
/* Create a label to jump to when we want to abort the query */
- addrEnd = sqlite3VdbeMakeLabel(v);
+ addrEnd = sqlite3VdbeMakeLabel(pParse);
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
@@ -6275,9 +6265,9 @@ int sqlite3Select(
iUseFlag = ++pParse->nMem;
iAbortFlag = ++pParse->nMem;
regOutputRow = ++pParse->nMem;
- addrOutputRow = sqlite3VdbeMakeLabel(v);
+ addrOutputRow = sqlite3VdbeMakeLabel(pParse);
regReset = ++pParse->nMem;
- addrReset = sqlite3VdbeMakeLabel(v);
+ addrReset = sqlite3VdbeMakeLabel(pParse);
iAMem = pParse->nMem + 1;
pParse->nMem += pGroupBy->nExpr;
iBMem = pParse->nMem + 1;
diff --git a/chromium/third_party/sqlite/src/src/shell.c.in b/chromium/third_party/sqlite/src/src/shell.c.in
index b13551dc61f..9ccac2b34ee 100644
--- a/chromium/third_party/sqlite/src/src/shell.c.in
+++ b/chromium/third_party/sqlite/src/src/shell.c.in
@@ -138,6 +138,9 @@ typedef unsigned char u8;
# ifndef unlink
# define unlink _unlink
# endif
+# ifndef strdup
+# define strdup _strdup
+# endif
# undef popen
# define popen _popen
# undef pclose
@@ -937,6 +940,7 @@ INCLUDE ../ext/misc/shathree.c
INCLUDE ../ext/misc/fileio.c
INCLUDE ../ext/misc/completion.c
INCLUDE ../ext/misc/appendvfs.c
+INCLUDE ../ext/misc/memtrace.c
#ifdef SQLITE_HAVE_ZLIB
INCLUDE ../ext/misc/zipfile.c
INCLUDE ../ext/misc/sqlar.c
@@ -1002,14 +1006,18 @@ struct ShellState {
u8 autoExplain; /* Automatically turn on .explain mode */
u8 autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
u8 autoEQPtest; /* autoEQP is in test mode */
+ u8 autoEQPtrace; /* autoEQP is in trace mode */
u8 statsOn; /* True to display memory stats before each finalize */
u8 scanstatsOn; /* True to display scan stats before each finalize */
u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
u8 nEqpLevel; /* Depth of the EQP output graph */
+ u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
+ int lineno; /* Line number of last line read from in */
+ FILE *in; /* Read commands from this stream */
FILE *out; /* Write results here */
FILE *traceOut; /* Output for sqlite3_trace() */
int nErr; /* Number of errors seen */
@@ -1020,7 +1028,11 @@ struct ShellState {
int writableSchema; /* True if PRAGMA writable_schema=ON */
int showHeader; /* True to show column names in List or Column mode */
int nCheck; /* Number of ".check" commands run */
+ unsigned nProgress; /* Number of progress callbacks encountered */
+ unsigned mxProgress; /* Maximum progress callbacks before failing */
+ unsigned flgProgress; /* Flags for the progress callback */
unsigned shellFlgs; /* Various flags */
+ sqlite3_int64 szMax; /* --maxsize argument to .open */
char *zDestTable; /* Name of destination table when MODE_Insert */
char *zTempFile; /* Temporary file that might need deleting */
char zTestcase[30]; /* Name of current test case */
@@ -1065,6 +1077,20 @@ struct ShellState {
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
+#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
+
+/* Allowed values for ShellState.eTraceType
+*/
+#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
+#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
+#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
+
+/* Bits in the ShellState.flgProgress variable */
+#define SHELL_PROGRESS_QUIET 0x01 /* Omit announcing every progress callback */
+#define SHELL_PROGRESS_RESET 0x02 /* Reset the count when the progres
+ ** callback limit is reached, and for each
+ ** top-level SQL statement */
+#define SHELL_PROGRESS_ONCE 0x04 /* Cancel the --limit after firing once */
/*
** These are the allowed shellFlgs values
@@ -1766,6 +1792,26 @@ static void eqp_render(ShellState *p){
}
}
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+/*
+** Progress handler callback.
+*/
+static int progress_handler(void *pClientData) {
+ ShellState *p = (ShellState*)pClientData;
+ p->nProgress++;
+ if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
+ raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
+ if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
+ if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
+ return 1;
+ }
+ if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
+ raw_printf(p->out, "Progress %u\n", p->nProgress);
+ }
+ return 0;
+}
+#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
+
/*
** This is the callback routine that the shell
** invokes for each row of a query result.
@@ -3370,6 +3416,7 @@ static const char *(azHelp[]) = {
#endif
".backup ?DB? FILE Backup DB (default \"main\") to FILE",
" --append Use the appendvfs",
+ " --async Write to FILE without a journal and without fsync()",
".bail on|off Stop after hitting an error. Default OFF",
".binary on|off Turn binary output on or off. Default OFF",
".cd DIRECTORY Change the working directory to DIRECTORY",
@@ -3385,7 +3432,13 @@ static const char *(azHelp[]) = {
" --newlines Allow unescaped newline characters in output",
" TABLE is LIKE pattern for the tables to dump",
".echo on|off Turn command echo on or off",
- ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN",
+ ".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
+ " Other Modes:",
+#ifdef SQLITE_DEBUG
+ " test Show raw EXPLAIN QUERY PLAN output",
+ " trace Like \"full\" but also enable \"PRAGMA vdbe_trace\"",
+#endif
+ " trigger Like \"full\" but also show trigger bytecode",
".excel Display the output of next command in a spreadsheet",
".exit ?CODE? Exit this program with return-code CODE",
".expert EXPERIMENTAL. Suggest indexes for specified queries",
@@ -3436,6 +3489,8 @@ static const char *(azHelp[]) = {
" --append Use appendvfs to append database to the end of FILE",
#ifdef SQLITE_ENABLE_DESERIALIZE
" --deserialize Load into memory useing sqlite3_deserialize()",
+ " --hexdb Load the output of \"dbtotxt\" as an in-memory database",
+ " --maxsize N Maximum size for --hexdb or --deserialized database",
#endif
" --new Initialize FILE to an empty database",
" --readonly Open FILE readonly",
@@ -3443,6 +3498,13 @@ static const char *(azHelp[]) = {
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
" If FILE begins with '|' then open it as a pipe.",
".print STRING... Print literal STRING",
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ ".progress N Invoke progress handler after every N opcodes",
+ " --limit N Interrupt after N progress callbacks",
+ " --once Do no more than one progress interrupt",
+ " --quiet|-q No output except at interrupts",
+ " --reset Reset the count for each input and interrupt",
+#endif
".prompt MAIN CONTINUE Replace the standard prompts",
".quit Exit this program",
".read FILE Read input from FILE",
@@ -3492,7 +3554,22 @@ static const char *(azHelp[]) = {
".testcase NAME Begin redirecting output to 'testcase-out.txt'",
".timeout MS Try opening locked tables for MS milliseconds",
".timer on|off Turn SQL timer on or off",
- ".trace FILE|off Output each SQL statement as it is run",
+#ifndef SQLITE_OMIT_TRACE
+ ".trace ?OPTIONS? Output each SQL statement as it is run",
+ " FILE Send output to FILE",
+ " stdout Send output to stdout",
+ " stderr Send output to stderr",
+ " off Disable tracing",
+ " --expanded Expand query parameters",
+#ifdef SQLITE_ENABLE_NORMALIZE
+ " --normalized Normal the SQL statements",
+#endif
+ " --plain Show SQL as it is input",
+ " --stmt Trace statement execution (SQLITE_TRACE_STMT)",
+ " --profile Profile statements (SQLITE_TRACE_PROFILE)",
+ " --row Trace each row (SQLITE_TRACE_ROW)",
+ " --close Trace connection close (SQLITE_TRACE_CLOSE)",
+#endif /* SQLITE_OMIT_TRACE */
".vfsinfo ?AUX? Information about the top-level VFS",
".vfslist List all available VFSes",
".vfsname ?AUX? Print the name of the VFS stack",
@@ -3570,7 +3647,7 @@ static int showHelp(FILE *out, const char *zPattern){
}
/* Forward reference */
-static int process_input(ShellState *p, FILE *in);
+static int process_input(ShellState *p);
/*
** Read the content of file zName into memory obtained from sqlite3_malloc64()
@@ -3700,6 +3777,94 @@ int deduceDatabaseType(const char *zName, int dfltZip){
return rc;
}
+#ifdef SQLITE_ENABLE_DESERIALIZE
+/*
+** Reconstruct an in-memory database using the output from the "dbtotxt"
+** program. Read content from the file in p->zDbFilename. If p->zDbFilename
+** is 0, then read from standard input.
+*/
+static unsigned char *readHexDb(ShellState *p, int *pnData){
+ unsigned char *a = 0;
+ int nLine;
+ int n = 0;
+ int pgsz = 0;
+ int iOffset = 0;
+ int j, k;
+ int rc;
+ FILE *in;
+ unsigned char x[16];
+ char zLine[1000];
+ if( p->zDbFilename ){
+ in = fopen(p->zDbFilename, "r");
+ if( in==0 ){
+ utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
+ return 0;
+ }
+ nLine = 0;
+ }else{
+ in = p->in;
+ nLine = p->lineno;
+ }
+ *pnData = 0;
+ nLine++;
+ if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
+ rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
+ if( rc!=2 ) goto readHexDb_error;
+ if( n<=0 ) goto readHexDb_error;
+ a = sqlite3_malloc( n );
+ if( a==0 ){
+ utf8_printf(stderr, "Out of memory!\n");
+ goto readHexDb_error;
+ }
+ memset(a, 0, n);
+ if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
+ utf8_printf(stderr, "invalid pagesize\n");
+ goto readHexDb_error;
+ }
+ for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
+ rc = sscanf(zLine, "| page %d offset %d", &j, &k);
+ if( rc==2 ){
+ iOffset = k;
+ continue;
+ }
+ if( strncmp(zLine, "| end ", 6)==0 ){
+ break;
+ }
+ rc = sscanf(zLine,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
+ " %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",
+ &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
+ &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
+ if( rc==17 ){
+ k = iOffset+j;
+ if( k+16<=n ){
+ memcpy(a+k, x, 16);
+ }
+ }
+ }
+ *pnData = n;
+ if( in!=p->in ){
+ fclose(in);
+ }else{
+ p->lineno = nLine;
+ }
+ return a;
+
+readHexDb_error:
+ if( in!=stdin ){
+ fclose(in);
+ }else{
+ while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
+ nLine++;
+ if(strncmp(zLine, "| end ", 6)==0 ) break;
+ }
+ p->lineno = nLine;
+ }
+ sqlite3_free(a);
+ utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
+ return 0;
+}
+#endif /* SQLITE_ENABLE_DESERIALIZE */
+
/* Flags for open_db().
**
** The default behavior of open_db() is to exit(1) if the database fails to
@@ -3733,6 +3898,7 @@ static void open_db(ShellState *p, int openFlags){
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
break;
}
+ case SHELL_OPEN_HEXDB:
case SHELL_OPEN_DESERIALIZE: {
sqlite3_open(0, &p->db);
break;
@@ -3755,7 +3921,10 @@ static void open_db(ShellState *p, int openFlags){
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
p->zDbFilename, sqlite3_errmsg(p->db));
- if( openFlags & OPEN_DB_KEEPALIVE ) return;
+ if( openFlags & OPEN_DB_KEEPALIVE ){
+ sqlite3_open(":memory:", &p->db);
+ return;
+ }
exit(1);
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -3787,15 +3956,29 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_free(zSql);
}
#ifdef SQLITE_ENABLE_DESERIALIZE
- else if( p->openMode==SHELL_OPEN_DESERIALIZE ){
+ else
+ if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
+ int rc;
int nData = 0;
- unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData);
- int rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
+ unsigned char *aData;
+ if( p->openMode==SHELL_OPEN_DESERIALIZE ){
+ aData = (unsigned char*)readFile(p->zDbFilename, &nData);
+ }else{
+ aData = readHexDb(p, &nData);
+ if( aData==0 ){
+ utf8_printf(stderr, "Error in hexdb input\n");
+ return;
+ }
+ }
+ rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
SQLITE_DESERIALIZE_RESIZEABLE |
SQLITE_DESERIALIZE_FREEONCLOSE);
if( rc ){
utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
}
+ if( p->szMax>0 ){
+ sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
+ }
}
#endif
}
@@ -3999,24 +4182,60 @@ static FILE *output_file_open(const char *zFile, int bTextMode){
return f;
}
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
+#ifndef SQLITE_OMIT_TRACE
/*
** A routine for handling output from sqlite3_trace().
*/
static int sql_trace_callback(
- unsigned mType,
- void *pArg,
- void *pP,
- void *pX
+ unsigned mType, /* The trace type */
+ void *pArg, /* The ShellState pointer */
+ void *pP, /* Usually a pointer to sqlite_stmt */
+ void *pX /* Auxiliary output */
){
- FILE *f = (FILE*)pArg;
- UNUSED_PARAMETER(mType);
- UNUSED_PARAMETER(pP);
- if( f ){
- const char *z = (const char*)pX;
- int i = strlen30(z);
- while( i>0 && z[i-1]==';' ){ i--; }
- utf8_printf(f, "%.*s;\n", i, z);
+ ShellState *p = (ShellState*)pArg;
+ sqlite3_stmt *pStmt;
+ const char *zSql;
+ int nSql;
+ if( p->traceOut==0 ) return 0;
+ if( mType==SQLITE_TRACE_CLOSE ){
+ utf8_printf(p->traceOut, "-- closing database connection\n");
+ return 0;
+ }
+ if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
+ zSql = (const char*)pX;
+ }else{
+ pStmt = (sqlite3_stmt*)pP;
+ switch( p->eTraceType ){
+ case SHELL_TRACE_EXPANDED: {
+ zSql = sqlite3_expanded_sql(pStmt);
+ break;
+ }
+#ifdef SQLITE_ENABLE_NORMALIZE
+ case SHELL_TRACE_NORMALIZED: {
+ zSql = sqlite3_normalized_sql(pStmt);
+ break;
+ }
+#endif
+ default: {
+ zSql = sqlite3_sql(pStmt);
+ break;
+ }
+ }
+ }
+ if( zSql==0 ) return 0;
+ nSql = strlen30(zSql);
+ while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
+ switch( mType ){
+ case SQLITE_TRACE_ROW:
+ case SQLITE_TRACE_STMT: {
+ utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
+ break;
+ }
+ case SQLITE_TRACE_PROFILE: {
+ sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
+ utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
+ break;
+ }
}
return 0;
}
@@ -5583,7 +5802,7 @@ static int arCreateOrUpdateCommand(
}
end_ar_transaction:
if( rc!=SQLITE_OK ){
- arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;");
+ sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
}else{
rc = arExecSql(pAr, "RELEASE ar;");
if( pAr->bZip && pAr->zFile ){
@@ -5782,6 +6001,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3 *pDest;
sqlite3_backup *pBackup;
int j;
+ int bAsync = 0;
const char *zVfs = 0;
for(j=1; j<nArg; j++){
const char *z = azArg[j];
@@ -5790,6 +6010,9 @@ static int do_meta_command(char *zLine, ShellState *p){
if( strcmp(z, "-append")==0 ){
zVfs = "apndvfs";
}else
+ if( strcmp(z, "-async")==0 ){
+ bAsync = 1;
+ }else
{
utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
return 1;
@@ -5800,7 +6023,7 @@ static int do_meta_command(char *zLine, ShellState *p){
zDb = zDestFile;
zDestFile = azArg[j];
}else{
- raw_printf(stderr, "Usage: .backup ?DB? ?--append? FILENAME\n");
+ raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
return 1;
}
}
@@ -5816,6 +6039,10 @@ static int do_meta_command(char *zLine, ShellState *p){
close_db(pDest);
return 1;
}
+ if( bAsync ){
+ sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
+ 0, 0, 0);
+ }
open_db(p, 0);
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
if( pBackup==0 ){
@@ -6081,18 +6308,30 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
if( nArg==2 ){
p->autoEQPtest = 0;
+ if( p->autoEQPtrace ){
+ if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
+ p->autoEQPtrace = 0;
+ }
if( strcmp(azArg[1],"full")==0 ){
p->autoEQP = AUTOEQP_full;
}else if( strcmp(azArg[1],"trigger")==0 ){
p->autoEQP = AUTOEQP_trigger;
+#ifdef SQLITE_DEBUG
}else if( strcmp(azArg[1],"test")==0 ){
p->autoEQP = AUTOEQP_on;
p->autoEQPtest = 1;
+ }else if( strcmp(azArg[1],"trace")==0 ){
+ p->autoEQP = AUTOEQP_full;
+ p->autoEQPtrace = 1;
+ open_db(p, 0);
+ sqlite3_exec(p->db, "SELECT name FROM sqlite_master LIMIT 1", 0, 0, 0);
+ sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
+#endif
}else{
p->autoEQP = (u8)booleanValue(azArg[1]);
}
}else{
- raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n");
+ raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
rc = 1;
}
}else
@@ -6666,6 +6905,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3_free(p->zFreeOnClose);
p->zFreeOnClose = 0;
p->openMode = SHELL_OPEN_UNSPEC;
+ p->szMax = 0;
/* Check for command-line arguments */
for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
const char *z = azArg[iName];
@@ -6682,7 +6922,11 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifdef SQLITE_ENABLE_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE;
-#endif
+ }else if( optionMatch(z, "hexdb") ){
+ p->openMode = SHELL_OPEN_HEXDB;
+ }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
+ p->szMax = integerValue(azArg[++iName]);
+#endif /* SQLITE_ENABLE_DESERIALIZE */
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
@@ -6691,7 +6935,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
/* If a filename is specified, try to open it first */
zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
- if( zNewFilename ){
+ if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag ) shellDeleteFile(zNewFilename);
p->zDbFilename = zNewFilename;
open_db(p, OPEN_DB_KEEPALIVE);
@@ -6793,6 +7037,52 @@ static int do_meta_command(char *zLine, ShellState *p){
raw_printf(p->out, "\n");
}else
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
+ int i;
+ int nn = 0;
+ p->flgProgress = 0;
+ p->mxProgress = 0;
+ p->nProgress = 0;
+ for(i=1; i<nArg; i++){
+ const char *z = azArg[i];
+ if( z[0]=='-' ){
+ z++;
+ if( z[0]=='-' ) z++;
+ if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
+ p->flgProgress |= SHELL_PROGRESS_QUIET;
+ continue;
+ }
+ if( strcmp(z,"reset")==0 ){
+ p->flgProgress |= SHELL_PROGRESS_RESET;
+ continue;
+ }
+ if( strcmp(z,"once")==0 ){
+ p->flgProgress |= SHELL_PROGRESS_ONCE;
+ continue;
+ }
+ if( strcmp(z,"limit")==0 ){
+ if( i+1>=nArg ){
+ utf8_printf(stderr, "Error: missing argument on --limit\n");
+ rc = 1;
+ goto meta_command_exit;
+ }else{
+ p->mxProgress = (int)integerValue(azArg[++i]);
+ }
+ continue;
+ }
+ utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
+ rc = 1;
+ goto meta_command_exit;
+ }else{
+ nn = (int)integerValue(z);
+ }
+ }
+ open_db(p, 0);
+ sqlite3_progress_handler(p->db, nn, progress_handler, p);
+ }else
+#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
+
if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
if( nArg >= 2) {
strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
@@ -6807,20 +7097,23 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
- FILE *alt;
+ FILE *inSaved = p->in;
+ int savedLineno = p->lineno;
if( nArg!=2 ){
raw_printf(stderr, "Usage: .read FILE\n");
rc = 1;
goto meta_command_exit;
}
- alt = fopen(azArg[1], "rb");
- if( alt==0 ){
+ p->in = fopen(azArg[1], "rb");
+ if( p->in==0 ){
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
}else{
- rc = process_input(p, alt);
- fclose(alt);
+ rc = process_input(p);
+ fclose(p->in);
}
+ p->in = inSaved;
+ p->lineno = savedLineno;
}else
if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
@@ -7838,23 +8131,55 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
+#ifndef SQLITE_OMIT_TRACE
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
+ int mType = 0;
+ int jj;
open_db(p, 0);
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .trace FILE|off\n");
- rc = 1;
- goto meta_command_exit;
+ for(jj=1; jj<nArg; jj++){
+ const char *z = azArg[jj];
+ if( z[0]=='-' ){
+ if( optionMatch(z, "expanded") ){
+ p->eTraceType = SHELL_TRACE_EXPANDED;
+ }
+#ifdef SQLITE_ENABLE_NORMALIZE
+ else if( optionMatch(z, "normalized") ){
+ p->eTraceType = SHELL_TRACE_NORMALIZED;
+ }
+#endif
+ else if( optionMatch(z, "plain") ){
+ p->eTraceType = SHELL_TRACE_PLAIN;
+ }
+ else if( optionMatch(z, "profile") ){
+ mType |= SQLITE_TRACE_PROFILE;
+ }
+ else if( optionMatch(z, "row") ){
+ mType |= SQLITE_TRACE_ROW;
+ }
+ else if( optionMatch(z, "stmt") ){
+ mType |= SQLITE_TRACE_STMT;
+ }
+ else if( optionMatch(z, "close") ){
+ mType |= SQLITE_TRACE_CLOSE;
+ }
+ else {
+ raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
+ rc = 1;
+ goto meta_command_exit;
+ }
+ }else{
+ output_file_close(p->traceOut);
+ p->traceOut = output_file_open(azArg[1], 0);
+ }
}
- output_file_close(p->traceOut);
- p->traceOut = output_file_open(azArg[1], 0);
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( p->traceOut==0 ){
sqlite3_trace_v2(p->db, 0, 0, 0);
}else{
- sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
+ if( mType==0 ) mType = SQLITE_TRACE_STMT;
+ sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
}
-#endif
}else
+#endif /* !defined(SQLITE_OMIT_TRACE) */
#if SQLITE_USER_AUTHENTICATION
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
@@ -8093,6 +8418,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
open_db(p, 0);
if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
+ if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
BEGIN_TIMER;
rc = shell_exec(p, zSql, &zErrMsg);
END_TIMER;
@@ -8129,7 +8455,7 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
**
** Return the number of errors.
*/
-static int process_input(ShellState *p, FILE *in){
+static int process_input(ShellState *p){
char *zLine = 0; /* A single input line */
char *zSql = 0; /* Accumulated SQL text */
int nLine; /* Length of current line */
@@ -8138,22 +8464,22 @@ static int process_input(ShellState *p, FILE *in){
int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
int rc; /* Error code */
int errCnt = 0; /* Number of errors seen */
- int lineno = 0; /* Current line number */
int startline = 0; /* Line number for start of current input */
- while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
+ p->lineno = 0;
+ while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
fflush(p->out);
- zLine = one_input_line(in, zLine, nSql>0);
+ zLine = one_input_line(p->in, zLine, nSql>0);
if( zLine==0 ){
/* End of input */
- if( in==0 && stdin_is_interactive ) printf("\n");
+ if( p->in==0 && stdin_is_interactive ) printf("\n");
break;
}
if( seenInterrupt ){
- if( in!=0 ) break;
+ if( p->in!=0 ) break;
seenInterrupt = 0;
}
- lineno++;
+ p->lineno++;
if( nSql==0 && _all_whitespace(zLine) ){
if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
continue;
@@ -8185,7 +8511,7 @@ static int process_input(ShellState *p, FILE *in){
for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
assert( nAlloc>0 && zSql!=0 );
memcpy(zSql, zLine+i, nLine+1-i);
- startline = lineno;
+ startline = p->lineno;
nSql = nLine-i;
}else{
zSql[nSql++] = '\n';
@@ -8194,7 +8520,7 @@ static int process_input(ShellState *p, FILE *in){
}
if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
&& sqlite3_complete(zSql) ){
- errCnt += runOneSqlLine(p, zSql, in, startline);
+ errCnt += runOneSqlLine(p, zSql, p->in, startline);
nSql = 0;
if( p->outCount ){
output_reset(p);
@@ -8208,7 +8534,7 @@ static int process_input(ShellState *p, FILE *in){
}
}
if( nSql && !_all_whitespace(zSql) ){
- errCnt += runOneSqlLine(p, zSql, in, startline);
+ errCnt += runOneSqlLine(p, zSql, p->in, startline);
}
free(zSql);
free(zLine);
@@ -8297,7 +8623,8 @@ static void process_sqliterc(
char *home_dir = NULL;
const char *sqliterc = sqliterc_override;
char *zBuf = 0;
- FILE *in = NULL;
+ FILE *inSaved = p->in;
+ int savedLineno = p->lineno;
if (sqliterc == NULL) {
home_dir = find_home_dir(0);
@@ -8309,14 +8636,16 @@ static void process_sqliterc(
zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
sqliterc = zBuf;
}
- in = fopen(sqliterc,"rb");
- if( in ){
+ p->in = fopen(sqliterc,"rb");
+ if( p->in ){
if( stdin_is_interactive ){
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
}
- process_input(p,in);
- fclose(in);
+ process_input(p);
+ fclose(p->in);
}
+ p->in = inSaved;
+ p->lineno = savedLineno;
sqlite3_free(zBuf);
}
@@ -8334,6 +8663,9 @@ static const char zOptions[] =
" -column set output mode to 'column'\n"
" -cmd COMMAND run \"COMMAND\" before reading stdin\n"
" -csv set output mode to 'csv'\n"
+#if defined(SQLITE_ENABLE_DESERIALIZE)
+ " -deserialize open the database using sqlite3_deserialize()\n"
+#endif
" -echo print commands before execution\n"
" -init FILENAME read/process named file\n"
" -[no]header turn headers on or off\n"
@@ -8346,6 +8678,10 @@ static const char zOptions[] =
" -line set output mode to 'line'\n"
" -list set output mode to 'list'\n"
" -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
+#if defined(SQLITE_ENABLE_DESERIALIZE)
+ " -maxsize N maximum size for a --deserialize database\n"
+#endif
+ " -memtrace trace all memory allocations and deallocations\n"
" -mmap N default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
" -multiplex enable the multiplexor VFS\n"
@@ -8666,6 +9002,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#ifdef SQLITE_ENABLE_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
+ }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
+ data.szMax = integerValue(argv[++i]);
#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
@@ -8675,6 +9013,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
** command, so ignore them */
break;
#endif
+ }else if( strcmp(z, "-memtrace")==0 ){
+ sqlite3MemTraceActivate(stderr);
}
}
verify_uninitialized();
@@ -8765,6 +9105,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#ifdef SQLITE_ENABLE_DESERIALIZE
}else if( strcmp(z,"-deserialize")==0 ){
data.openMode = SHELL_OPEN_DESERIALIZE;
+ }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
+ data.szMax = integerValue(argv[++i]);
#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
@@ -8821,6 +9163,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
i+=2;
}else if( strcmp(z,"-mmap")==0 ){
i++;
+ }else if( strcmp(z,"-memtrace")==0 ){
+ i++;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
}else if( strcmp(z,"-sorterref")==0 ){
i++;
@@ -8938,14 +9282,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#elif HAVE_LINENOISE
linenoiseSetCompletionCallback(linenoise_completion);
#endif
- rc = process_input(&data, 0);
+ data.in = 0;
+ rc = process_input(&data);
if( zHistory ){
shell_stifle_history(2000);
shell_write_history(zHistory);
free(zHistory);
}
}else{
- rc = process_input(&data, stdin);
+ data.in = stdin;
+ rc = process_input(&data);
}
}
set_table_name(&data, 0);
diff --git a/chromium/third_party/sqlite/src/src/sqlite.h.in b/chromium/third_party/sqlite/src/src/sqlite.h.in
index cf623163eaa..3d6b63e006a 100644
--- a/chromium/third_party/sqlite/src/src/sqlite.h.in
+++ b/chromium/third_party/sqlite/src/src/sqlite.h.in
@@ -823,6 +823,15 @@ struct sqlite3_io_methods {
** file space based on this hint in order to help writes to the database
** file run faster.
**
+** <li>[[SQLITE_FCNTL_SIZE_LIMIT]]
+** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that
+** implements [sqlite3_deserialize()] to set an upper bound on the size
+** of the in-memory database. The argument is a pointer to a [sqlite3_int64].
+** If the integer pointed to is negative, then it is filled in with the
+** current limit. Otherwise the limit is set to the larger of the value
+** of the integer pointed to and the current database size. The integer
+** pointed to is set to the new limit.
+**
** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
** extends and truncates the database file in chunks of a size specified
@@ -1131,6 +1140,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
#define SQLITE_FCNTL_DATA_VERSION 35
+#define SQLITE_FCNTL_SIZE_LIMIT 36
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1972,6 +1982,17 @@ struct sqlite3_mem_methods {
** negative value for this option restores the default behaviour.
** This option is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
+**
+** [[SQLITE_CONFIG_MEMDB_MAXSIZE]]
+** <dt>SQLITE_CONFIG_MEMDB_MAXSIZE
+** <dd>The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter
+** [sqlite3_int64] parameter which is the default maximum size for an in-memory
+** database created using [sqlite3_deserialize()]. This default maximum
+** size can be adjusted up or down for individual databases using the
+** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this
+** configuration setting is never used, then the default maximum is determined
+** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
+** compile-time option is not set, then the default maximum is 1073741824.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -2002,6 +2023,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
+#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -2991,9 +3013,9 @@ int sqlite3_set_authorizer(
** time is in units of nanoseconds, however the current implementation
** is only capable of millisecond resolution so the six least significant
** digits in the time are meaningless. Future versions of SQLite
-** might provide greater resolution on the profiler callback. The
-** sqlite3_profile() function is considered experimental and is
-** subject to change in future versions of SQLite.
+** might provide greater resolution on the profiler callback. Invoking
+** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the
+** profile callback.
*/
SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*,
void(*xTrace)(void*,const char*), void*);
@@ -3407,6 +3429,8 @@ int sqlite3_open_v2(
** is not a database file pathname pointer that SQLite passed into the xOpen
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
+**
+** See the [URI filename] documentation for additional information.
*/
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
@@ -3629,14 +3653,13 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently.
**
-** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
-** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
-** representation of the SQL statement should be calculated and then
-** associated with the prepared statement, which can be obtained via
-** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
-** normalize a SQL statement are unspecified and subject to change.
-** At a minimum, literal values will be replaced with suitable
-** placeholders.
+** [[SQLITE_PREPARE_NORMALIZE]] <dt>SQLITE_PREPARE_NORMALIZE</dt>
+** <dd>The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used
+** to be required for any prepared statement that wanted to use the
+** [sqlite3_normalized_sql()] interface. However, the
+** [sqlite3_normalized_sql()] interface is now available to all
+** prepared statements, regardless of whether or not they use this
+** flag.
**
** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
diff --git a/chromium/third_party/sqlite/src/src/sqliteInt.h b/chromium/third_party/sqlite/src/src/sqliteInt.h
index 1aae87ea13b..467a273a995 100644
--- a/chromium/third_party/sqlite/src/src/sqliteInt.h
+++ b/chromium/third_party/sqlite/src/src/sqliteInt.h
@@ -1356,10 +1356,13 @@ void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
** in the style of sqlite3_trace()
*/
-#define SQLITE_TRACE_LEGACY 0x80
+#define SQLITE_TRACE_LEGACY 0x40 /* Use the legacy xTrace */
+#define SQLITE_TRACE_XPROFILE 0x80 /* Use the legacy xProfile */
#else
-#define SQLITE_TRACE_LEGACY 0
+#define SQLITE_TRACE_LEGACY 0
+#define SQLITE_TRACE_XPROFILE 0
#endif /* SQLITE_OMIT_DEPRECATED */
+#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
/*
@@ -1418,8 +1421,10 @@ struct sqlite3 {
void **aExtension; /* Array of shared library handles */
int (*xTrace)(u32,void*,void*,void*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
+#ifndef SQLITE_OMIT_DEPRECATED
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
+#endif
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*); /* Invoked at every commit. */
void *pRollbackArg; /* Argument to xRollbackCallback() */
@@ -1550,6 +1555,7 @@ struct sqlite3 {
#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */
#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */
#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */
+#define SQLITE_ParserTrace HI(0x0020) /* PRAGMA parser_trace=ON */
#endif
/*
@@ -1952,9 +1958,6 @@ struct VTable {
struct Table {
char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */
-#ifdef SQLITE_ENABLE_NORMALIZE
- Hash *pColHash; /* All columns indexed by name */
-#endif
Index *pIndex; /* List of SQL indexes on this table. */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
@@ -2241,7 +2244,7 @@ struct Index {
u16 nKeyCol; /* Number of columns forming the key */
u16 nColumn; /* Number of columns stored in the index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
+ unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
unsigned isResized:1; /* True if resizeIndexObject() has been called */
@@ -2266,6 +2269,7 @@ struct Index {
#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
+#define SQLITE_IDXTYPE_IPK 3 /* INTEGER PRIMARY KEY index */
/* Return true if index X is a PRIMARY KEY index */
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
@@ -2483,6 +2487,10 @@ struct Expr {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
** for a column of an index on an expression */
Window *pWin; /* TK_FUNCTION: Window definition for the func */
+ struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
+ int iAddr; /* Subroutine entry address */
+ int regReturn; /* Register used to hold return address */
+ } sub;
} y;
};
@@ -2514,6 +2522,8 @@ struct Expr {
#define EP_Alias 0x400000 /* Is an alias for a result set column */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
+#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
+#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
/*
** The EP_Propagate mask is a set of properties that automatically propagate
@@ -3063,11 +3073,11 @@ struct Parse {
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
- int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */
- int nLabel; /* Number of labels used */
+ int nLabel; /* The *negative* of the number of labels used */
+ int nLabelAlloc; /* Number of slots in aLabel */
int *aLabel; /* Space to hold the labels */
ExprList *pConstExpr;/* Constant expressions */
Token constraintName;/* Name of the constraint currently being parsed */
@@ -3127,7 +3137,9 @@ struct Parse {
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
- Index *pNewIndex; /* An index being constructed by CREATE INDEX */
+ Index *pNewIndex; /* An index being constructed by CREATE INDEX.
+ ** Also used to hold redundant UNIQUE constraints
+ ** during a RENAME COLUMN */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -3355,6 +3367,7 @@ typedef struct {
int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */
int rc; /* Result code stored here */
u32 mInitFlags; /* Flags controlling error messages */
+ u32 nInitRow; /* Number of rows processed */
} InitData;
/*
@@ -3415,6 +3428,9 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ sqlite3_int64 mxMemdbSize; /* Default max memdb size */
+#endif
#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
@@ -3803,6 +3819,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
void sqlite3SetString(char **, sqlite3*, const char*);
void sqlite3ErrorMsg(Parse*, const char*, ...);
void sqlite3Dequote(char*);
+void sqlite3DequoteExpr(Expr*);
void sqlite3TokenInit(Token*,char*);
int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
@@ -3831,6 +3848,7 @@ void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
u32 sqlite3ExprListFlags(const ExprList*);
+int sqlite3IndexHasDuplicateRootPage(Index*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);
int sqlite3InitOne(sqlite3*, int, char**, u32);
@@ -3864,6 +3882,11 @@ void sqlite3AddCollateType(Parse*, Token*);
void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
+#ifdef SQLITE_HAS_CODEC
+ int sqlite3CodecQueryParameters(sqlite3*,const char*,const char*);
+#else
+# define sqlite3CodecQueryParameters(A,B,C) 0
+#endif
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
#ifdef SQLITE_UNTESTABLE
@@ -3916,8 +3939,8 @@ void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
-SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
-SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
+SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
+SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, Expr*, IdList*);
void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
@@ -3984,8 +4007,8 @@ Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
-void sqlite3Vacuum(Parse*,Token*);
-int sqlite3RunVacuum(char**, sqlite3*, int);
+void sqlite3Vacuum(Parse*,Token*,Expr*);
+int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*);
char *sqlite3NameFromToken(sqlite3*, Token*);
int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
int sqlite3ExprCompareSkip(Expr*, Expr*, int);
@@ -4023,9 +4046,6 @@ int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3ExprCanBeNull(const Expr*);
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
int sqlite3IsRowid(const char*);
-#ifdef SQLITE_ENABLE_NORMALIZE
-int sqlite3IsRowidN(const char*, int);
-#endif
void sqlite3GenerateRowDelete(
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
@@ -4052,9 +4072,7 @@ ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*,int);
-#ifdef SQLITE_ENABLE_NORMALIZE
-FuncDef *sqlite3FunctionSearchN(int,const char*,int);
-#endif
+FuncDef *sqlite3FunctionSearch(int,const char*);
void sqlite3InsertBuiltinFuncs(FuncDef*,int);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
void sqlite3RegisterBuiltinFunctions(void);
@@ -4259,19 +4277,17 @@ void sqlite3AlterFunctions(void);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
-#ifdef SQLITE_ENABLE_NORMALIZE
-int sqlite3GetTokenNormalized(const unsigned char *, int *, int *);
-#endif
void sqlite3NestedParse(Parse*, const char*, ...);
void sqlite3ExpirePreparedStatements(sqlite3*, int);
-int sqlite3CodeSubselect(Parse*, Expr *, int, int);
+void sqlite3CodeRhsOfIN(Parse*, Expr*, int, int);
+int sqlite3CodeSubselect(Parse*, Expr*);
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
int sqlite3ResolveExprNames(NameContext*, Expr*);
int sqlite3ResolveExprListNames(NameContext*, ExprList*);
void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
-void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
+int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
void sqlite3AlterFinishAddColumn(Parse *, Token *);
@@ -4420,7 +4436,7 @@ int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
#ifdef SQLITE_ENABLE_NORMALIZE
-void sqlite3Normalize(Vdbe*, const char*, int, u8);
+char *sqlite3Normalize(Vdbe*, const char*);
#endif
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
@@ -4516,7 +4532,7 @@ const char *sqlite3JournalModename(int);
#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */
#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */
#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */
-int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
+int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*);
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
int sqlite3JournalSize(sqlite3_vfs *);
diff --git a/chromium/third_party/sqlite/src/src/tclsqlite.c b/chromium/third_party/sqlite/src/src/tclsqlite.c
index 9dd32ef8e19..d3b62d931cf 100644
--- a/chromium/third_party/sqlite/src/src/tclsqlite.c
+++ b/chromium/third_party/sqlite/src/src/tclsqlite.c
@@ -2418,7 +2418,7 @@ static int SQLITE_TCLAPI DbObjCmd(
}
/*
- ** $db deserialize ?DATABASE? VALUE
+ ** $db deserialize ?-maxsize N? ?-readonly BOOL? ?DATABASE? VALUE
**
** Reopen DATABASE (default "main") using the content in $VALUE
*/
@@ -2428,38 +2428,65 @@ static int SQLITE_TCLAPI DbObjCmd(
(char*)0);
rc = TCL_ERROR;
#else
- const char *zSchema;
- Tcl_Obj *pValue;
+ const char *zSchema = 0;
+ Tcl_Obj *pValue = 0;
unsigned char *pBA;
unsigned char *pData;
int len, xrc;
+ sqlite3_int64 mxSize = 0;
+ int i;
+ int isReadonly = 0;
- if( objc==3 ){
- zSchema = 0;
- pValue = objv[2];
- }else if( objc==4 ){
- zSchema = Tcl_GetString(objv[2]);
- pValue = objv[3];
- }else{
+
+ if( objc<3 ){
Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? VALUE");
rc = TCL_ERROR;
break;
}
+ for(i=2; i<objc-1; i++){
+ const char *z = Tcl_GetString(objv[i]);
+ if( strcmp(z,"-maxsize")==0 && i<objc-2 ){
+ rc = Tcl_GetWideIntFromObj(interp, objv[++i], &mxSize);
+ if( rc ) goto deserialize_error;
+ continue;
+ }
+ if( strcmp(z,"-readonly")==0 && i<objc-2 ){
+ rc = Tcl_GetBooleanFromObj(interp, objv[++i], &isReadonly);
+ if( rc ) goto deserialize_error;
+ continue;
+ }
+ if( zSchema==0 && i==objc-2 && z[0]!='-' ){
+ zSchema = z;
+ continue;
+ }
+ Tcl_AppendResult(interp, "unknown option: ", z, (char*)0);
+ rc = TCL_ERROR;
+ goto deserialize_error;
+ }
+ pValue = objv[objc-1];
pBA = Tcl_GetByteArrayFromObj(pValue, &len);
pData = sqlite3_malloc64( len );
if( pData==0 && len>0 ){
Tcl_AppendResult(interp, "out of memory", (char*)0);
rc = TCL_ERROR;
}else{
+ int flags;
if( len>0 ) memcpy(pData, pBA, len);
- xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len,
- SQLITE_DESERIALIZE_FREEONCLOSE |
- SQLITE_DESERIALIZE_RESIZEABLE);
+ if( isReadonly ){
+ flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_READONLY;
+ }else{
+ flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE;
+ }
+ xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, flags);
if( xrc ){
Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0);
rc = TCL_ERROR;
}
+ if( mxSize>0 ){
+ sqlite3_file_control(pDb->db, zSchema,SQLITE_FCNTL_SIZE_LIMIT,&mxSize);
+ }
}
+deserialize_error:
#endif
break;
}
diff --git a/chromium/third_party/sqlite/src/src/test1.c b/chromium/third_party/sqlite/src/src/test1.c
index 5d6a01f319f..81d77d96d9b 100644
--- a/chromium/third_party/sqlite/src/src/test1.c
+++ b/chromium/third_party/sqlite/src/src/test1.c
@@ -7141,6 +7141,9 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ extern int sqlite3_prefixes_init(sqlite3*,char**,const sqlite3_api_routines*);
+#endif
extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
@@ -7166,6 +7169,9 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
{ "ieee754", sqlite3_ieee_init },
{ "nextchar", sqlite3_nextchar_init },
{ "percentile", sqlite3_percentile_init },
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ { "prefixes", sqlite3_prefixes_init },
+#endif
{ "regexp", sqlite3_regexp_init },
{ "remember", sqlite3_remember_init },
{ "series", sqlite3_series_init },
@@ -7642,6 +7648,79 @@ static int SQLITE_TCLAPI test_mmap_warm(
}
/*
+** Usage: decode_hexdb TEXT
+**
+** Example: db deserialize [decode_hexdb $output_of_dbtotxt]
+**
+** This routine returns a byte-array for an SQLite database file that
+** is constructed from a text input which is the output of the "dbtotxt"
+** utility.
+*/
+static int SQLITE_TCLAPI test_decode_hexdb(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ const char *zIn = 0;
+ unsigned char *a = 0;
+ int n = 0;
+ int lineno = 0;
+ int i, iNext;
+ int iOffset = 0;
+ int j, k;
+ int rc;
+ unsigned char x[16];
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "HEXDB");
+ return TCL_ERROR;
+ }
+ zIn = Tcl_GetString(objv[1]);
+ for(i=0; zIn[i]; i=iNext){
+ lineno++;
+ for(iNext=i; zIn[iNext] && zIn[iNext]!='\n'; iNext++){}
+ if( zIn[iNext]=='\n' ) iNext++;
+ while( zIn[i]==' ' || zIn[i]=='\t' ){ i++; }
+ if( a==0 ){
+ int pgsz;
+ rc = sscanf(zIn+i, "| size %d pagesize %d", &n, &pgsz);
+ if( rc!=2 ) continue;
+ if( n<512 ){
+ Tcl_AppendResult(interp, "bad 'size' field", (void*)0);
+ return TCL_ERROR;
+ }
+ a = malloc( n );
+ if( a==0 ){
+ Tcl_AppendResult(interp, "out of memory", (void*)0);
+ return TCL_ERROR;
+ }
+ memset(a, 0, n);
+ continue;
+ }
+ rc = sscanf(zIn+i, "| page %d offset %d", &j, &k);
+ if( rc==2 ){
+ iOffset = k;
+ continue;
+ }
+ rc = sscanf(zIn+i,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
+ " %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",
+ &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
+ &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
+ if( rc==17 ){
+ k = iOffset+j;
+ if( k+16<=n ){
+ memcpy(a+k, x, 16);
+ }
+ continue;
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(a, n));
+ free(a);
+ return TCL_OK;
+}
+
+
+/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
@@ -7920,6 +7999,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "atomic_batch_write", test_atomic_batch_write, 0 },
{ "sqlite3_mmap_warm", test_mmap_warm, 0 },
{ "sqlite3_config_sorterref", test_config_sorterref, 0 },
+ { "decode_hexdb", test_decode_hexdb, 0 },
};
static int bitmask_size = sizeof(Bitmask)*8;
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
diff --git a/chromium/third_party/sqlite/src/src/test_journal.c b/chromium/third_party/sqlite/src/src/test_journal.c
index 8ee609797b2..e89ff768d73 100644
--- a/chromium/third_party/sqlite/src/src/test_journal.c
+++ b/chromium/third_party/sqlite/src/src/test_journal.c
@@ -560,7 +560,7 @@ static int jtWrite(
/* The following assert() statements may fail if this layer is used
** with a connection in "PRAGMA synchronous=off" mode. If they
** fail with sync=normal or sync=full, this may indicate problem. */
- assert( pgno<=p->nPage || p->nSync>0 );
+ assert( p->nPage==0 || pgno<=p->nPage || p->nSync>0 );
assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) );
}
}
diff --git a/chromium/third_party/sqlite/src/src/test_vfs.c b/chromium/third_party/sqlite/src/src/test_vfs.c
index e3d35584774..24799a452c9 100644
--- a/chromium/third_party/sqlite/src/src/test_vfs.c
+++ b/chromium/third_party/sqlite/src/src/test_vfs.c
@@ -228,11 +228,13 @@ static int tvfsResultCode(Testvfs *p, int *pRc){
int eCode;
const char *zCode;
} aCode[] = {
- { SQLITE_OK, "SQLITE_OK" },
- { SQLITE_ERROR, "SQLITE_ERROR" },
- { SQLITE_IOERR, "SQLITE_IOERR" },
- { SQLITE_LOCKED, "SQLITE_LOCKED" },
- { SQLITE_BUSY, "SQLITE_BUSY" },
+ { SQLITE_OK, "SQLITE_OK" },
+ { SQLITE_ERROR, "SQLITE_ERROR" },
+ { SQLITE_IOERR, "SQLITE_IOERR" },
+ { SQLITE_LOCKED, "SQLITE_LOCKED" },
+ { SQLITE_BUSY, "SQLITE_BUSY" },
+ { SQLITE_READONLY, "SQLITE_READONLY" },
+ { SQLITE_READONLY_CANTINIT, "SQLITE_READONLY_CANTINIT" },
};
const char *z;
@@ -865,7 +867,7 @@ static int tvfsShmOpen(sqlite3_file *pFile){
pFd->pNext = pBuffer->pFile;
pBuffer->pFile = pFd;
pFd->pShm = pBuffer;
- return SQLITE_OK;
+ return rc;
}
static void tvfsAllocPage(TestvfsBuffer *p, int iPage, int pgsz){
@@ -918,7 +920,9 @@ static int tvfsShmMap(
if( rc==SQLITE_OK && isWrite && !pFd->pShm->aPage[iPage] ){
tvfsAllocPage(pFd->pShm, iPage, pgsz);
}
- *pp = (void volatile *)pFd->pShm->aPage[iPage];
+ if( rc==SQLITE_OK || rc==SQLITE_READONLY ){
+ *pp = (void volatile *)pFd->pShm->aPage[iPage];
+ }
return rc;
}
@@ -1563,8 +1567,115 @@ static int SQLITE_TCLAPI testvfs_cmd(
return TCL_ERROR;
}
+extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
+extern const char *sqlite3ErrName(int);
+
+/*
+** tclcmd: vfs_shmlock DB DBNAME (shared|exclusive) (lock|unlock) OFFSET N
+*/
+static int SQLITE_TCLAPI test_vfs_shmlock(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ const char *azArg1[] = {"shared", "exclusive", 0};
+ const char *azArg2[] = {"lock", "unlock", 0};
+ sqlite3 *db = 0;
+ int rc = SQLITE_OK;
+ const char *zDbname = 0;
+ int iArg1 = 0;
+ int iArg2 = 0;
+ int iOffset = 0;
+ int n = 0;
+ sqlite3_file *pFd;
+
+ if( objc!=7 ){
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "DB DBNAME (shared|exclusive) (lock|unlock) OFFSET N"
+ );
+ return TCL_ERROR;
+ }
+
+ zDbname = Tcl_GetString(objv[2]);
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
+ || Tcl_GetIndexFromObj(interp, objv[3], azArg1, "ARG", 0, &iArg1)
+ || Tcl_GetIndexFromObj(interp, objv[4], azArg2, "ARG", 0, &iArg2)
+ || Tcl_GetIntFromObj(interp, objv[5], &iOffset)
+ || Tcl_GetIntFromObj(interp, objv[6], &n)
+ ){
+ return TCL_ERROR;
+ }
+
+ sqlite3_file_control(db, zDbname, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
+ if( pFd==0 ){
+ return TCL_ERROR;
+ }
+ rc = pFd->pMethods->xShmLock(pFd, iOffset, n,
+ (iArg1==0 ? SQLITE_SHM_SHARED : SQLITE_SHM_EXCLUSIVE)
+ | (iArg2==0 ? SQLITE_SHM_LOCK : SQLITE_SHM_UNLOCK)
+ );
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ return TCL_OK;
+}
+
+static int SQLITE_TCLAPI test_vfs_set_readmark(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3 *db = 0;
+ int rc = SQLITE_OK;
+ const char *zDbname = 0;
+ int iSlot = 0;
+ int iVal = -1;
+ sqlite3_file *pFd;
+ void volatile *pShm = 0;
+ u32 *aShm;
+ int iOff;
+
+ if( objc!=4 && objc!=5 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SLOT ?VALUE?");
+ return TCL_ERROR;
+ }
+
+ zDbname = Tcl_GetString(objv[2]);
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
+ || Tcl_GetIntFromObj(interp, objv[3], &iSlot)
+ || (objc==5 && Tcl_GetIntFromObj(interp, objv[4], &iVal))
+ ){
+ return TCL_ERROR;
+ }
+
+ sqlite3_file_control(db, zDbname, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
+ if( pFd==0 ){
+ return TCL_ERROR;
+ }
+ rc = pFd->pMethods->xShmMap(pFd, 0, 32*1024, 0, &pShm);
+ if( rc!=SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ return TCL_ERROR;
+ }
+ if( pShm==0 ){
+ Tcl_AppendResult(interp, "*-shm is not yet mapped", 0);
+ return TCL_ERROR;
+ }
+ aShm = (u32*)pShm;
+ iOff = 12*2+1+iSlot;
+
+ if( objc==5 ){
+ aShm[iOff] = iVal;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(aShm[iOff]));
+
+ return TCL_OK;
+}
+
int Sqlitetestvfs_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0);
+ Tcl_CreateObjCommand(interp, "vfs_shmlock", test_vfs_shmlock, 0, 0);
+ Tcl_CreateObjCommand(interp, "vfs_set_readmark", test_vfs_set_readmark, 0, 0);
return TCL_OK;
}
diff --git a/chromium/third_party/sqlite/src/src/tokenize.c b/chromium/third_party/sqlite/src/src/tokenize.c
index 4e56a487e54..896c5702579 100644
--- a/chromium/third_party/sqlite/src/src/tokenize.c
+++ b/chromium/third_party/sqlite/src/src/tokenize.c
@@ -545,73 +545,6 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
return i;
}
-#ifdef SQLITE_ENABLE_NORMALIZE
-/*
-** Return the length (in bytes) of the token that begins at z[0].
-** Store the token type in *tokenType before returning. If flags has
-** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type
-** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was
-** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags
-** if the token was recognized as a keyword; this is useful when the
-** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller
-** to differentiate between a keyword being treated as an identifier
-** (for normalization purposes) and an actual identifier.
-*/
-int sqlite3GetTokenNormalized(
- const unsigned char *z,
- int *tokenType,
- int *flags
-){
- int n;
- unsigned char iClass = aiClass[*z];
- if( iClass==CC_KYWD ){
- int i;
- for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
- if( IdChar(z[i]) ){
- /* This token started out using characters that can appear in keywords,
- ** but z[i] is a character not allowed within keywords, so this must
- ** be an identifier instead */
- i++;
- while( IdChar(z[i]) ){ i++; }
- *tokenType = TK_ID;
- return i;
- }
- *tokenType = TK_ID;
- n = keywordCode((char*)z, i, tokenType);
- /* If the token is no longer considered to be an identifier, then it is a
- ** keyword of some kind. Make the token back into an identifier and then
- ** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are
- ** used verbatim, including IN, IS, NOT, and NULL. */
- switch( *tokenType ){
- case TK_ID: {
- /* do nothing, handled by caller */
- break;
- }
- case TK_IN:
- case TK_IS:
- case TK_NOT:
- case TK_NULL: {
- *flags |= SQLITE_TOKEN_KEYWORD;
- break;
- }
- default: {
- *tokenType = TK_ID;
- *flags |= SQLITE_TOKEN_KEYWORD;
- break;
- }
- }
- }else{
- n = sqlite3GetToken(z, tokenType);
- /* If the token is considered to be an identifier and the character class
- ** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */
- if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){
- *flags |= SQLITE_TOKEN_QUOTED;
- }
- }
- return n;
-}
-#endif /* SQLITE_ENABLE_NORMALIZE */
-
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
@@ -639,7 +572,14 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
pParse->rc = SQLITE_OK;
pParse->zTail = zSql;
assert( pzErrMsg!=0 );
- /* sqlite3ParserTrace(stdout, "parser: "); */
+#ifdef SQLITE_DEBUG
+ if( db->flags & SQLITE_ParserTrace ){
+ printf("parser: [[[%s]]]\n", zSql);
+ sqlite3ParserTrace(stdout, "parser: ");
+ }else{
+ sqlite3ParserTrace(0, 0);
+ }
+#endif
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
pEngine = &sEngine;
sqlite3ParserInit(pEngine, pParse);
@@ -781,3 +721,138 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
assert( nErr==0 || pParse->rc!=SQLITE_OK );
return nErr;
}
+
+
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Insert a single space character into pStr if the current string
+** ends with an identifier
+*/
+static void addSpaceSeparator(sqlite3_str *pStr){
+ if( pStr->nChar && sqlite3IsIdChar(pStr->zText[pStr->nChar-1]) ){
+ sqlite3_str_append(pStr, " ", 1);
+ }
+}
+
+/*
+** Compute a normalization of the SQL given by zSql[0..nSql-1]. Return
+** the normalization in space obtained from sqlite3DbMalloc(). Or return
+** NULL if anything goes wrong or if zSql is NULL.
+*/
+char *sqlite3Normalize(
+ Vdbe *pVdbe, /* VM being reprepared */
+ const char *zSql /* The original SQL string */
+){
+ sqlite3 *db; /* The database connection */
+ int i; /* Next unread byte of zSql[] */
+ int n; /* length of current token */
+ int tokenType; /* type of current token */
+ int prevType = 0; /* Previous non-whitespace token */
+ int nParen; /* Number of nested levels of parentheses */
+ int iStartIN; /* Start of RHS of IN operator in z[] */
+ int nParenAtIN; /* Value of nParent at start of RHS of IN operator */
+ int j; /* Bytes of normalized SQL generated so far */
+ sqlite3_str *pStr; /* The normalized SQL string under construction */
+
+ db = sqlite3VdbeDb(pVdbe);
+ tokenType = -1;
+ nParen = iStartIN = nParenAtIN = 0;
+ pStr = sqlite3_str_new(db);
+ assert( pStr!=0 ); /* sqlite3_str_new() never returns NULL */
+ for(i=0; zSql[i] && pStr->accError==0; i+=n){
+ if( tokenType!=TK_SPACE ){
+ prevType = tokenType;
+ }
+ n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
+ if( NEVER(n<=0) ) break;
+ switch( tokenType ){
+ case TK_SPACE: {
+ break;
+ }
+ case TK_NULL: {
+ if( prevType==TK_IS || prevType==TK_NOT ){
+ sqlite3_str_append(pStr, " NULL", 5);
+ break;
+ }
+ /* Fall through */
+ }
+ case TK_STRING:
+ case TK_INTEGER:
+ case TK_FLOAT:
+ case TK_VARIABLE:
+ case TK_BLOB: {
+ sqlite3_str_append(pStr, "?", 1);
+ break;
+ }
+ case TK_LP: {
+ nParen++;
+ if( prevType==TK_IN ){
+ iStartIN = pStr->nChar;
+ nParenAtIN = nParen;
+ }
+ sqlite3_str_append(pStr, "(", 1);
+ break;
+ }
+ case TK_RP: {
+ if( iStartIN>0 && nParen==nParenAtIN ){
+ assert( pStr->nChar>=iStartIN );
+ pStr->nChar = iStartIN+1;
+ sqlite3_str_append(pStr, "?,?,?", 5);
+ iStartIN = 0;
+ }
+ nParen--;
+ sqlite3_str_append(pStr, ")", 1);
+ break;
+ }
+ case TK_ID: {
+ iStartIN = 0;
+ j = pStr->nChar;
+ if( sqlite3Isquote(zSql[i]) ){
+ char *zId = sqlite3DbStrNDup(db, zSql+i, n);
+ int nId;
+ int eType = 0;
+ if( zId==0 ) break;
+ sqlite3Dequote(zId);
+ if( zSql[i]=='"' && sqlite3VdbeUsesDoubleQuotedString(pVdbe, zId) ){
+ sqlite3_str_append(pStr, "?", 1);
+ sqlite3DbFree(db, zId);
+ break;
+ }
+ nId = sqlite3Strlen30(zId);
+ if( sqlite3GetToken((u8*)zId, &eType)==nId && eType==TK_ID ){
+ addSpaceSeparator(pStr);
+ sqlite3_str_append(pStr, zId, nId);
+ }else{
+ sqlite3_str_appendf(pStr, "\"%w\"", zId);
+ }
+ sqlite3DbFree(db, zId);
+ }else{
+ addSpaceSeparator(pStr);
+ sqlite3_str_append(pStr, zSql+i, n);
+ }
+ while( j<pStr->nChar ){
+ pStr->zText[j] = sqlite3Tolower(pStr->zText[j]);
+ j++;
+ }
+ break;
+ }
+ case TK_SELECT: {
+ iStartIN = 0;
+ /* fall through */
+ }
+ default: {
+ if( sqlite3IsIdChar(zSql[i]) ) addSpaceSeparator(pStr);
+ j = pStr->nChar;
+ sqlite3_str_append(pStr, zSql+i, n);
+ while( j<pStr->nChar ){
+ pStr->zText[j] = sqlite3Toupper(pStr->zText[j]);
+ j++;
+ }
+ break;
+ }
+ }
+ }
+ if( tokenType!=TK_SEMI ) sqlite3_str_append(pStr, ";", 1);
+ return sqlite3_str_finish(pStr);
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
diff --git a/chromium/third_party/sqlite/src/src/treeview.c b/chromium/third_party/sqlite/src/src/treeview.c
index e7483dde25f..2cb5197740b 100644
--- a/chromium/third_party/sqlite/src/src/treeview.c
+++ b/chromium/third_party/sqlite/src/src/treeview.c
@@ -138,7 +138,8 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
sqlite3_str_appendf(&x, " %s", pItem->zName);
}
if( pItem->pTab ){
- sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
+ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p",
+ pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab);
}
if( pItem->zAlias ){
sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
diff --git a/chromium/third_party/sqlite/src/src/trigger.c b/chromium/third_party/sqlite/src/src/trigger.c
index 69fddedd914..fba75d8fb4d 100644
--- a/chromium/third_party/sqlite/src/src/trigger.c
+++ b/chromium/third_party/sqlite/src/src/trigger.c
@@ -731,7 +731,7 @@ static SrcList *targetSrcList(
int iDb; /* Index of the database to use */
SrcList *pSrc; /* SrcList to be returned */
- pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
+ pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
assert( pSrc->nSrc>0 );
pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
@@ -944,7 +944,7 @@ static TriggerPrg *codeRowTrigger(
if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
&& db->mallocFailed==0
){
- iEndTrigger = sqlite3VdbeMakeLabel(v);
+ iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
}
sqlite3ExprDelete(db, pWhen);
diff --git a/chromium/third_party/sqlite/src/src/update.c b/chromium/third_party/sqlite/src/src/update.c
index b328d3b229b..98ed29244f2 100644
--- a/chromium/third_party/sqlite/src/src/update.c
+++ b/chromium/third_party/sqlite/src/src/update.c
@@ -354,6 +354,7 @@ void sqlite3Update(
** being updated. Fill in aRegIdx[] with a register number that will hold
** the key for accessing each index.
*/
+ if( onError==OE_Replace ) bReplace = 1;
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
if( chngKey || hasFK>1 || pIdx==pPk
@@ -367,9 +368,7 @@ void sqlite3Update(
if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
- if( (onError==OE_Replace)
- || (onError==OE_Default && pIdx->onError==OE_Replace)
- ){
+ if( onError==OE_Default && pIdx->onError==OE_Replace ){
bReplace = 1;
}
break;
@@ -441,7 +440,7 @@ void sqlite3Update(
#endif
/* Jump to labelBreak to abandon further processing of this UPDATE */
- labelContinue = labelBreak = sqlite3VdbeMakeLabel(v);
+ labelContinue = labelBreak = sqlite3VdbeMakeLabel(pParse);
/* Not an UPSERT. Normal processing. Begin by
** initialize the count of updated rows */
@@ -576,13 +575,13 @@ void sqlite3Update(
VdbeCoverage(v);
}
if( eOnePass!=ONEPASS_SINGLE ){
- labelContinue = sqlite3VdbeMakeLabel(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
}
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
VdbeCoverageIf(v, pPk==0);
VdbeCoverageIf(v, pPk!=0);
}else if( pPk ){
- labelContinue = sqlite3VdbeMakeLabel(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
addrTop = sqlite3VdbeAddOp2(v, OP_RowData, iEph, regKey);
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
diff --git a/chromium/third_party/sqlite/src/src/util.c b/chromium/third_party/sqlite/src/src/util.c
index 4f700d4d538..7e4bb725280 100644
--- a/chromium/third_party/sqlite/src/src/util.c
+++ b/chromium/third_party/sqlite/src/src/util.c
@@ -238,7 +238,7 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
** dequoted string, exclusive of the zero terminator, if dequoting does
** occur.
**
-** 2002-Feb-14: This routine is extended to remove MS-Access style
+** 2002-02-14: This routine is extended to remove MS-Access style
** brackets from around identifiers. For example: "[a-b-c]" becomes
** "a-b-c".
*/
@@ -264,6 +264,11 @@ void sqlite3Dequote(char *z){
}
z[j] = 0;
}
+void sqlite3DequoteExpr(Expr *p){
+ assert( sqlite3Isquote(p->u.zToken[0]) );
+ p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
+ sqlite3Dequote(p->u.zToken);
+}
/*
** Generate a Token object from a string
diff --git a/chromium/third_party/sqlite/src/src/vacuum.c b/chromium/third_party/sqlite/src/src/vacuum.c
index 6ee545d18fc..8ed587c81f9 100644
--- a/chromium/third_party/sqlite/src/src/vacuum.c
+++ b/chromium/third_party/sqlite/src/src/vacuum.c
@@ -102,16 +102,16 @@ static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){
** transient would cause the database file to appear to be deleted
** following reboot.
*/
-void sqlite3Vacuum(Parse *pParse, Token *pNm){
+void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){
Vdbe *v = sqlite3GetVdbe(pParse);
int iDb = 0;
- if( v==0 ) return;
+ if( v==0 ) goto build_vacuum_end;
if( pNm ){
#ifndef SQLITE_BUG_COMPATIBLE_20160819
/* Default behavior: Report an error if the argument to VACUUM is
** not recognized */
iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm);
- if( iDb<0 ) return;
+ if( iDb<0 ) goto build_vacuum_end;
#else
/* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
** to VACUUM are silently ignored. This is a back-out of a bug fix that
@@ -123,21 +123,33 @@ void sqlite3Vacuum(Parse *pParse, Token *pNm){
#endif
}
if( iDb!=1 ){
- sqlite3VdbeAddOp1(v, OP_Vacuum, iDb);
+ int iIntoReg = 0;
+ if( pInto && sqlite3ResolveSelfReference(pParse,0,0,pInto,0)==0 ){
+ iIntoReg = ++pParse->nMem;
+ sqlite3ExprCode(pParse, pInto, iIntoReg);
+ }
+ sqlite3VdbeAddOp2(v, OP_Vacuum, iDb, iIntoReg);
sqlite3VdbeUsesBtree(v, iDb);
}
+build_vacuum_end:
+ sqlite3ExprDelete(pParse->db, pInto);
return;
}
/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
-int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
+int sqlite3RunVacuum(
+ char **pzErrMsg, /* Write error message here */
+ sqlite3 *db, /* Database connection */
+ int iDb, /* Which attached DB to vacuum */
+ sqlite3_value *pOut /* Write results here, if not NULL */
+){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
- u16 saved_mDbFlags; /* Saved value of db->mDbFlags */
- u32 saved_flags; /* Saved value of db->flags */
+ u32 saved_mDbFlags; /* Saved value of db->mDbFlags */
+ u64 saved_flags; /* Saved value of db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
u8 saved_mTrace; /* Saved trace settings */
@@ -146,6 +158,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
int nRes; /* Bytes of reserved space at the end of each page */
int nDb; /* Number of attached databases */
const char *zDbMain; /* Schema name of database to vacuum */
+ const char *zOut; /* Name of output file */
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
@@ -155,6 +168,15 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
return SQLITE_ERROR;
}
+ if( pOut ){
+ if( sqlite3_value_type(pOut)!=SQLITE_TEXT ){
+ sqlite3SetString(pzErrMsg, db, "non-text filename");
+ return SQLITE_ERROR;
+ }
+ zOut = (const char*)sqlite3_value_text(pOut);
+ }else{
+ zOut = "";
+ }
/* Save the current value of the database flags so that it can be
** restored before returning. Then set the writable-schema flag, and
@@ -166,7 +188,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
- db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder
+ db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);
db->mTrace = 0;
@@ -189,19 +211,21 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
** to write the journal header file.
*/
nDb = db->nDb;
- rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db");
+ rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
assert( (db->nDb-1)==nDb );
pDb = &db->aDb[nDb];
assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
pTemp = pDb->pBt;
-
- /* The call to execSql() to attach the temp database has left the file
- ** locked (as there was more than one active statement when the transaction
- ** to read the schema was concluded. Unlock it here so that this doesn't
- ** cause problems for the call to BtreeSetPageSize() below. */
- sqlite3BtreeCommit(pTemp);
-
+ if( pOut ){
+ sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
+ i64 sz = 0;
+ if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){
+ rc = SQLITE_ERROR;
+ sqlite3SetString(pzErrMsg, db, "output file already exists");
+ goto end_of_vacuum;
+ }
+ }
nRes = sqlite3BtreeGetOptimalReserve(pMain);
/* A VACUUM cannot change the pagesize of an encrypted database. */
@@ -225,7 +249,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
*/
rc = execSql(db, pzErrMsg, "BEGIN");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = sqlite3BtreeBeginTrans(pMain, 2, 0);
+ rc = sqlite3BtreeBeginTrans(pMain, pOut==0 ? 2 : 0, 0);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Do not attempt to change the page size for a WAL database */
@@ -320,7 +344,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
};
assert( 1==sqlite3BtreeIsInTrans(pTemp) );
- assert( 1==sqlite3BtreeIsInTrans(pMain) );
+ assert( pOut!=0 || 1==sqlite3BtreeIsInTrans(pMain) );
/* Copy Btree meta values */
for(i=0; i<ArraySize(aCopy); i+=2){
@@ -331,17 +355,23 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
if( NEVER(rc!=SQLITE_OK) ) goto end_of_vacuum;
}
- rc = sqlite3BtreeCopyFile(pMain, pTemp);
+ if( pOut==0 ){
+ rc = sqlite3BtreeCopyFile(pMain, pTemp);
+ }
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
#ifndef SQLITE_OMIT_AUTOVACUUM
- sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
+ if( pOut==0 ){
+ sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
+ }
#endif
}
assert( rc==SQLITE_OK );
- rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
+ if( pOut==0 ){
+ rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
+ }
end_of_vacuum:
/* Restore the original value of db->flags */
diff --git a/chromium/third_party/sqlite/src/src/vdbe.c b/chromium/third_party/sqlite/src/src/vdbe.c
index ae2ff53d5e2..1d712239562 100644
--- a/chromium/third_party/sqlite/src/src/vdbe.c
+++ b/chromium/third_party/sqlite/src/src/vdbe.c
@@ -240,6 +240,11 @@ static VdbeCursor *allocateCursor(
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
+ /* Before calling sqlite3VdbeFreeCursor(), ensure the isEphemeral flag
+ ** is clear. Otherwise, if this is an ephemeral cursor created by
+ ** OP_OpenDup, the cursor will not be closed and will still be part
+ ** of a BtShared.pCursor list. */
+ p->apCsr[iCur]->isEphemeral = 0;
sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
@@ -380,6 +385,7 @@ void sqlite3ValueApplyAffinity(
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
assert( (pMem->flags & (MEM_Int|MEM_Real))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
+ ExpandBlob(pMem);
if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
return 0;
}
@@ -1578,8 +1584,8 @@ fp_math:
break;
}
default: {
- iA = (i64)rA;
- iB = (i64)rB;
+ iA = sqlite3VdbeIntValue(pIn1);
+ iB = sqlite3VdbeIntValue(pIn2);
if( iA==0 ) goto arithmetic_result_is_null;
if( iA==-1 ) iA = 1;
rB = (double)(iB % iA);
@@ -1925,7 +1931,8 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
*/
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
assert( (flags1 & MEM_Cleared)==0 );
- assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
+ assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB );
+ testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 );
if( (flags1&flags3&MEM_Null)!=0
&& (flags3&MEM_Cleared)==0
){
@@ -3609,7 +3616,8 @@ case OP_OpenDup: {
pCx->isEphemeral = 1;
pCx->pKeyInfo = pOrig->pKeyInfo;
pCx->isTable = pOrig->isTable;
- rc = sqlite3BtreeCursor(pOrig->pBtx, MASTER_ROOT, BTREE_WRCSR,
+ pCx->pgnoRoot = pOrig->pgnoRoot;
+ rc = sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pCx->pKeyInfo, pCx->uc.pCursor);
/* The sqlite3BtreeCursor() routine can only fail for the first cursor
** opened for a database. Since there is already an open cursor when this
@@ -3627,6 +3635,9 @@ case OP_OpenDup: {
** the main database is read-only. The ephemeral
** table is deleted automatically when the cursor is closed.
**
+** If the cursor P1 is already opened on an ephemeral table, the table
+** is cleared (all content is erased).
+**
** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
@@ -3658,41 +3669,50 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
- pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
- if( pCx==0 ) goto no_mem;
- pCx->nullRow = 1;
- pCx->isEphemeral = 1;
- rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
- BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
- }
- if( rc==SQLITE_OK ){
- /* If a transient index is required, create it by calling
- ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
- ** opening it. If a transient table is required, just use the
- ** automatically created table with root-page 1 (an BLOB_INTKEY table).
- */
- if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
- int pgno;
- assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5);
- if( rc==SQLITE_OK ){
- assert( pgno==MASTER_ROOT+1 );
- assert( pKeyInfo->db==db );
- assert( pKeyInfo->enc==ENC(db) );
- rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR,
- pKeyInfo, pCx->uc.pCursor);
+ pCx = p->apCsr[pOp->p1];
+ if( pCx ){
+ /* If the ephermeral table is already open, erase all existing content
+ ** so that the table is empty again, rather than creating a new table. */
+ rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
+ }else{
+ pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
+ if( pCx==0 ) goto no_mem;
+ pCx->nullRow = 1;
+ pCx->isEphemeral = 1;
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
+ BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5,
+ vfsFlags);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
+ }
+ if( rc==SQLITE_OK ){
+ /* If a transient index is required, create it by calling
+ ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
+ ** opening it. If a transient table is required, just use the
+ ** automatically created table with root-page 1 (an BLOB_INTKEY table).
+ */
+ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
+ assert( pOp->p4type==P4_KEYINFO );
+ rc = sqlite3BtreeCreateTable(pCx->pBtx, (int*)&pCx->pgnoRoot,
+ BTREE_BLOBKEY | pOp->p5);
+ if( rc==SQLITE_OK ){
+ assert( pCx->pgnoRoot==MASTER_ROOT+1 );
+ assert( pKeyInfo->db==db );
+ assert( pKeyInfo->enc==ENC(db) );
+ rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
+ pKeyInfo, pCx->uc.pCursor);
+ }
+ pCx->isTable = 0;
+ }else{
+ pCx->pgnoRoot = MASTER_ROOT;
+ rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR,
+ 0, pCx->uc.pCursor);
+ pCx->isTable = 1;
}
- pCx->isTable = 0;
- }else{
- rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR,
- 0, pCx->uc.pCursor);
- pCx->isTable = 1;
}
+ pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
}
if( rc ) goto abort_due_to_error;
- pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
break;
}
@@ -4342,7 +4362,7 @@ case OP_NotExists: /* jump, in3 */
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
- pC->seekOp = OP_SeekRowid;
+ if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid;
#endif
assert( pC->isTable );
assert( pC->eCurType==CURTYPE_BTREE );
@@ -5250,7 +5270,7 @@ case OP_Next: /* jump */
assert( pOp->opcode!=OP_Next
|| pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
- || pC->seekOp==OP_NullRow);
+ || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid);
assert( pOp->opcode!=OP_Prev
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|| pC->seekOp==OP_Last
@@ -5780,9 +5800,16 @@ case OP_ParseSchema: {
assert( db->init.busy==0 );
db->init.busy = 1;
initData.rc = SQLITE_OK;
+ initData.nInitRow = 0;
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_OK ) rc = initData.rc;
+ if( rc==SQLITE_OK && initData.nInitRow==0 ){
+ /* The OP_ParseSchema opcode with a non-NULL P4 argument should parse
+ ** at least one SQL statement. Any less than that indicates that
+ ** the sqlite_master table is corrupt. */
+ rc = SQLITE_CORRUPT_BKPT;
+ }
sqlite3DbFreeNN(db, zSql);
db->init.busy = 0;
}
@@ -6146,6 +6173,17 @@ case OP_Program: { /* jump */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
p->anExec = 0;
#endif
+#ifdef SQLITE_DEBUG
+ /* Verify that second and subsequent executions of the same trigger do not
+ ** try to reuse register values from the first use. */
+ {
+ int i;
+ for(i=0; i<p->nMem; i++){
+ aMem[i].pScopyFrom = 0; /* Prevent false-positive AboutToChange() errs */
+ aMem[i].flags |= MEM_Undefined; /* Cause a fault if this reg is reused */
+ }
+ }
+#endif
pOp = &aOp[-1];
break;
@@ -6684,14 +6722,19 @@ case OP_JournalMode: { /* out2 */
#endif /* SQLITE_OMIT_PRAGMA */
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
-/* Opcode: Vacuum P1 * * * *
+/* Opcode: Vacuum P1 P2 * * *
**
** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more
** for an attached database. The "temp" database may not be vacuumed.
+**
+** If P2 is not zero, then it is a register holding a string which is
+** the file into which the result of vacuum should be written. When
+** P2 is zero, the vacuum overwrites the original database.
*/
case OP_Vacuum: {
assert( p->readOnly==0 );
- rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1);
+ rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1,
+ pOp->p2 ? &aMem[pOp->p2] : 0);
if( rc ) goto abort_due_to_error;
break;
}
@@ -6843,6 +6886,7 @@ case OP_VDestroy: {
db->nVDestroy++;
rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
db->nVDestroy--;
+ assert( p->errorAction==OE_Abort && p->usesStmtJournal );
if( rc ) goto abort_due_to_error;
break;
}
@@ -7086,7 +7130,7 @@ case OP_VRename: {
rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
if( rc ) goto abort_due_to_error;
rc = pVtab->pModule->xRename(pVtab, pName->z);
- if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter;
+ if( isLegacy==0 ) db->flags &= ~(u64)SQLITE_LegacyAlter;
sqlite3VtabImportErrmsg(p, pVtab);
p->expired = 0;
if( rc ) goto abort_due_to_error;
diff --git a/chromium/third_party/sqlite/src/src/vdbe.h b/chromium/third_party/sqlite/src/src/vdbe.h
index ef422bb2cd4..5522e62e75d 100644
--- a/chromium/third_party/sqlite/src/src/vdbe.h
+++ b/chromium/third_party/sqlite/src/src/vdbe.h
@@ -156,12 +156,11 @@ typedef struct VdbeOpList VdbeOpList;
#endif
/*
-** The following macro converts a relative address in the p2 field
-** of a VdbeOp structure into a negative number so that
-** sqlite3VdbeAddOpList() knows that the address is relative. Calling
-** the macro again restores the address.
+** The following macro converts a label returned by sqlite3VdbeMakeLabel()
+** into an index into the Parse.aLabel[] array that contains the resolved
+** address of that label.
*/
-#define ADDR(X) (-1-(X))
+#define ADDR(X) (~(X))
/*
** The makefile scans the vdbe.c source file and creates the "opcodes.h"
@@ -215,6 +214,12 @@ VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
# define ExplainQueryPlan(P)
# define ExplainQueryPlanPop(P)
# define ExplainQueryPlanParent(P) 0
+# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
+#endif
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
+ void sqlite3ExplainBreakpoint(const char*,const char*);
+#else
+# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
@@ -230,7 +235,7 @@ void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
-int sqlite3VdbeMakeLabel(Vdbe*);
+int sqlite3VdbeMakeLabel(Parse*);
void sqlite3VdbeRunOnlyOnce(Vdbe*);
void sqlite3VdbeReusable(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
@@ -251,6 +256,10 @@ void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
u8 sqlite3VdbePrepareFlags(Vdbe*);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
+#ifdef SQLITE_ENABLE_NORMALIZE
+void sqlite3VdbeAddDblquoteStr(sqlite3*,Vdbe*,const char*);
+int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*);
+#endif
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
diff --git a/chromium/third_party/sqlite/src/src/vdbeInt.h b/chromium/third_party/sqlite/src/src/vdbeInt.h
index 23c5b37cb47..7147547b407 100644
--- a/chromium/third_party/sqlite/src/src/vdbeInt.h
+++ b/chromium/third_party/sqlite/src/src/vdbeInt.h
@@ -335,6 +335,9 @@ struct sqlite3_context {
*/
typedef unsigned bft; /* Bit Field Type */
+/* The ScanStatus object holds a single value for the
+** sqlite3_stmt_scanstatus() interface.
+*/
typedef struct ScanStatus ScanStatus;
struct ScanStatus {
int addrExplain; /* OP_Explain for loop */
@@ -345,6 +348,19 @@ struct ScanStatus {
char *zName; /* Name of table or index */
};
+/* The DblquoteStr object holds the text of a double-quoted
+** string for a prepared statement. A linked list of these objects
+** is constructed during statement parsing and is held on Vdbe.pDblStr.
+** When computing a normalized SQL statement for an SQL statement, that
+** list is consulted for each double-quoted identifier to see if the
+** identifier should really be a string literal.
+*/
+typedef struct DblquoteStr DblquoteStr;
+struct DblquoteStr {
+ DblquoteStr *pNextStr; /* Next string literal in the list */
+ char z[8]; /* Dequoted value for the string */
+};
+
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
@@ -364,28 +380,29 @@ struct Vdbe {
int pc; /* The program counter */
int rc; /* Value to return */
int nChange; /* Number of db changes made since last reset */
- int iStatement; /* Statement number (or 0 if has not opened stmt) */
+ int iStatement; /* Statement number (or 0 if has no opened stmt) */
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
+ Mem *aMem; /* The memory locations */
+ Mem **apArg; /* Arguments to currently executing user function */
+ VdbeCursor **apCsr; /* One element of this array for each open cursor */
+ Mem *aVar; /* Values for the OP_Variable opcode. */
/* When allocating a new Vdbe object, all of the fields below should be
** initialized to zero or NULL */
Op *aOp; /* Space to hold the virtual machine's program */
- Mem *aMem; /* The memory locations */
- Mem **apArg; /* Arguments to currently executing user function */
+ int nOp; /* Number of instructions in the program */
+ int nOpAlloc; /* Slots allocated for aOp[] */
Mem *aColName; /* Column names to return */
Mem *pResultSet; /* Pointer to an array of results */
char *zErrMsg; /* Error message written here */
- VdbeCursor **apCsr; /* One element of this array for each open cursor */
- Mem *aVar; /* Values for the OP_Variable opcode. */
VList *pVList; /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
- int nOp; /* Number of instructions in the program */
#ifdef SQLITE_DEBUG
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
@@ -408,6 +425,7 @@ struct Vdbe {
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_ENABLE_NORMALIZE
char *zNormSql; /* Normalization of the associated SQL statement */
+ DblquoteStr *pDblStr; /* List of double-quoted string literals */
#endif
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
diff --git a/chromium/third_party/sqlite/src/src/vdbeapi.c b/chromium/third_party/sqlite/src/src/vdbeapi.c
index 7cc7b1bdbf3..5b2f43d6782 100644
--- a/chromium/third_party/sqlite/src/src/vdbeapi.c
+++ b/chromium/third_party/sqlite/src/src/vdbeapi.c
@@ -62,14 +62,16 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
sqlite3_int64 iNow;
sqlite3_int64 iElapse;
assert( p->startTime>0 );
- assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 );
+ assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
assert( db->init.busy==0 );
assert( p->zSql!=0 );
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
iElapse = (iNow - p->startTime)*1000000;
+#ifndef SQLITE_OMIT_DEPRECATED
if( db->xProfile ){
db->xProfile(db->pProfileArg, p->zSql, iElapse);
}
+#endif
if( db->mTrace & SQLITE_TRACE_PROFILE ){
db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
}
@@ -583,7 +585,7 @@ static int sqlite3Step(Vdbe *p){
return SQLITE_NOMEM_BKPT;
}
- if( p->pc<=0 && p->expired ){
+ if( p->pc<0 && p->expired ){
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
goto end_of_step;
@@ -602,7 +604,7 @@ static int sqlite3Step(Vdbe *p){
);
#ifndef SQLITE_OMIT_TRACE
- if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0)
+ if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
&& !db->init.busy && p->zSql ){
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
}else{
@@ -629,16 +631,18 @@ static int sqlite3Step(Vdbe *p){
db->nVdbeExec--;
}
+ if( rc!=SQLITE_ROW ){
#ifndef SQLITE_OMIT_TRACE
- /* If the statement completed successfully, invoke the profile callback */
- if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
+ /* If the statement completed successfully, invoke the profile callback */
+ checkProfileCallback(db, p);
#endif
- if( rc==SQLITE_DONE && db->autoCommit ){
- assert( p->rc==SQLITE_OK );
- p->rc = doWalCallbacks(db);
- if( p->rc!=SQLITE_OK ){
- rc = SQLITE_ERROR;
+ if( rc==SQLITE_DONE && db->autoCommit ){
+ assert( p->rc==SQLITE_OK );
+ p->rc = doWalCallbacks(db);
+ if( p->rc!=SQLITE_OK ){
+ rc = SQLITE_ERROR;
+ }
}
}
@@ -658,9 +662,9 @@ end_of_step:
|| (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
);
assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
- if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
- && rc!=SQLITE_ROW
+ if( rc!=SQLITE_ROW
&& rc!=SQLITE_DONE
+ && (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
){
/* If this statement was prepared using saved SQL and an
** error has occurred, then return the error code in p->rc to the
@@ -1282,7 +1286,7 @@ static int vdbeUnbind(Vdbe *p, int i){
pVar = &p->aVar[i];
sqlite3VdbeMemRelease(pVar);
pVar->flags = MEM_Null;
- sqlite3Error(p->db, SQLITE_OK);
+ p->db->errCode = SQLITE_OK;
/* If the bit corresponding to this variable in Vdbe.expmask is set, then
** binding a new value to this variable invalidates the current query plan.
@@ -1708,7 +1712,13 @@ char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
*/
const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
- return p ? p->zNormSql : 0;
+ if( p==0 ) return 0;
+ if( p->zNormSql==0 && ALWAYS(p->zSql!=0) ){
+ sqlite3_mutex_enter(p->db->mutex);
+ p->zNormSql = sqlite3Normalize(p, p->zSql);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return p->zNormSql;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
diff --git a/chromium/third_party/sqlite/src/src/vdbeaux.c b/chromium/third_party/sqlite/src/src/vdbeaux.c
index 13b2e1ef728..ca2f3874106 100644
--- a/chromium/third_party/sqlite/src/src/vdbeaux.c
+++ b/chromium/third_party/sqlite/src/src/vdbeaux.c
@@ -36,7 +36,7 @@ Vdbe *sqlite3VdbeCreate(Parse *pParse){
pParse->pVdbe = p;
assert( pParse->aLabel==0 );
assert( pParse->nLabel==0 );
- assert( pParse->nOpAlloc==0 );
+ assert( p->nOpAlloc==0 );
assert( pParse->szOpAlloc==0 );
sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
return p;
@@ -64,14 +64,44 @@ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){
}
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
+}
+
#ifdef SQLITE_ENABLE_NORMALIZE
- assert( p->zNormSql==0 );
- if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){
- sqlite3Normalize(p, p->zSql, n, prepFlags);
- assert( p->zNormSql!=0 || p->db->mallocFailed );
+/*
+** Add a new element to the Vdbe->pDblStr list.
+*/
+void sqlite3VdbeAddDblquoteStr(sqlite3 *db, Vdbe *p, const char *z){
+ if( p ){
+ int n = sqlite3Strlen30(z);
+ DblquoteStr *pStr = sqlite3DbMallocRawNN(db,
+ sizeof(*pStr)+n+1-sizeof(pStr->z));
+ if( pStr ){
+ pStr->pNextStr = p->pDblStr;
+ p->pDblStr = pStr;
+ memcpy(pStr->z, z, n+1);
+ }
}
+}
#endif
+
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** zId of length nId is a double-quoted identifier. Check to see if
+** that identifier is really used as a string literal.
+*/
+int sqlite3VdbeUsesDoubleQuotedString(
+ Vdbe *pVdbe, /* The prepared statement */
+ const char *zId /* The double-quoted identifier, already dequoted */
+){
+ DblquoteStr *pStr;
+ assert( zId!=0 );
+ if( pVdbe->pDblStr==0 ) return 0;
+ for(pStr=pVdbe->pDblStr; pStr; pStr=pStr->pNextStr){
+ if( strcmp(zId, pStr->z)==0 ) return 1;
+ }
+ return 0;
}
+#endif
/*
** Swap all content between two VDBE structures.
@@ -92,7 +122,7 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
-#ifdef SQLITE_ENABLE_NORMALIZE
+#if 0
zTmp = pA->zNormSql;
pA->zNormSql = pB->zNormSql;
pB->zNormSql = zTmp;
@@ -109,7 +139,7 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
** to 1024/sizeof(Op).
**
** If an out-of-memory error occurs while resizing the array, return
-** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain
+** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
** unchanged (this is so that any opcodes already allocated can be
** correctly deallocated along with the rest of the Vdbe).
*/
@@ -125,9 +155,9 @@ static int growOpArray(Vdbe *v, int nOp){
** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
** size of the op array or add 1KB of space, whichever is smaller. */
#ifdef SQLITE_TEST_REALLOC_STRESS
- int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
+ int nNew = (v->nOpAlloc>=512 ? v->nOpAlloc*2 : v->nOpAlloc+nOp);
#else
- int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
+ int nNew = (v->nOpAlloc ? v->nOpAlloc*2 : (int)(1024/sizeof(Op)));
UNUSED_PARAMETER(nOp);
#endif
@@ -138,11 +168,11 @@ static int growOpArray(Vdbe *v, int nOp){
}
assert( nOp<=(1024/sizeof(Op)) );
- assert( nNew>=(p->nOpAlloc+nOp) );
+ assert( nNew>=(v->nOpAlloc+nOp) );
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
if( pNew ){
p->szOpAlloc = sqlite3DbMallocSize(p->db, pNew);
- p->nOpAlloc = p->szOpAlloc/sizeof(Op);
+ v->nOpAlloc = p->szOpAlloc/sizeof(Op);
v->aOp = pNew;
}
return (pNew ? SQLITE_OK : SQLITE_NOMEM_BKPT);
@@ -176,9 +206,9 @@ static void test_addop_breakpoint(void){
** operand.
*/
static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){
- assert( p->pParse->nOpAlloc<=p->nOp );
+ assert( p->nOpAlloc<=p->nOp );
if( growOpArray(p, 1) ) return 1;
- assert( p->pParse->nOpAlloc>p->nOp );
+ assert( p->nOpAlloc>p->nOp );
return sqlite3VdbeAddOp3(p, op, p1, p2, p3);
}
int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
@@ -188,7 +218,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
i = p->nOp;
assert( p->magic==VDBE_MAGIC_INIT );
assert( op>=0 && op<0xff );
- if( p->pParse->nOpAlloc<=i ){
+ if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
}
p->nOp++;
@@ -320,13 +350,29 @@ int sqlite3VdbeExplainParent(Parse *pParse){
}
/*
-** Add a new OP_Explain opcode.
+** Set a debugger breakpoint on the following routine in order to
+** monitor the EXPLAIN QUERY PLAN code generation.
+*/
+#if defined(SQLITE_DEBUG)
+void sqlite3ExplainBreakpoint(const char *z1, const char *z2){
+ (void)z1;
+ (void)z2;
+}
+#endif
+
+/*
+** Add a new OP_ opcode.
**
** If the bPush flag is true, then make this opcode the parent for
** subsequent Explains until sqlite3VdbeExplainPop() is called.
*/
void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
- if( pParse->explain==2 ){
+#ifndef SQLITE_DEBUG
+ /* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined.
+ ** But omit them (for performance) during production builds */
+ if( pParse->explain==2 )
+#endif
+ {
char *zMsg;
Vdbe *v;
va_list ap;
@@ -338,7 +384,10 @@ void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
iThis = v->nOp;
sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
zMsg, P4_DYNAMIC);
- if( bPush) pParse->addrExplain = iThis;
+ sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetOp(v,-1)->p4.z);
+ if( bPush){
+ pParse->addrExplain = iThis;
+ }
}
}
@@ -346,6 +395,7 @@ void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
** Pop the EXPLAIN QUERY PLAN stack one level.
*/
void sqlite3VdbeExplainPop(Parse *pParse){
+ sqlite3ExplainBreakpoint("POP", 0);
pParse->addrExplain = sqlite3VdbeExplainParent(pParse);
}
#endif /* SQLITE_OMIT_EXPLAIN */
@@ -410,21 +460,22 @@ void sqlite3VdbeEndCoroutine(Vdbe *v, int regYield){
** The VDBE knows that a P2 value is a label because labels are
** always negative and P2 values are suppose to be non-negative.
** Hence, a negative P2 value is a label that has yet to be resolved.
+** (Later:) This is only true for opcodes that have the OPFLG_JUMP
+** property.
**
-** Zero is returned if a malloc() fails.
+** Variable usage notes:
+**
+** Parse.aLabel[x] Stores the address that the x-th label resolves
+** into. For testing (SQLITE_DEBUG), unresolved
+** labels stores -1, but that is not required.
+** Parse.nLabelAlloc Number of slots allocated to Parse.aLabel[]
+** Parse.nLabel The *negative* of the number of labels that have
+** been issued. The negative is stored because
+** that gives a performance improvement over storing
+** the equivalent positive value.
*/
-int sqlite3VdbeMakeLabel(Vdbe *v){
- Parse *p = v->pParse;
- int i = p->nLabel++;
- assert( v->magic==VDBE_MAGIC_INIT );
- if( (i & (i-1))==0 ){
- p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
- (i*2+1)*sizeof(p->aLabel[0]));
- }
- if( p->aLabel ){
- p->aLabel[i] = -1;
- }
- return ADDR(i);
+int sqlite3VdbeMakeLabel(Parse *pParse){
+ return --pParse->nLabel;
}
/*
@@ -432,18 +483,35 @@ int sqlite3VdbeMakeLabel(Vdbe *v){
** be inserted. The parameter "x" must have been obtained from
** a prior call to sqlite3VdbeMakeLabel().
*/
+static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
+ int nNewSize = 10 - p->nLabel;
+ p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
+ nNewSize*sizeof(p->aLabel[0]));
+ if( p->aLabel==0 ){
+ p->nLabelAlloc = 0;
+ }else{
+#ifdef SQLITE_DEBUG
+ int i;
+ for(i=p->nLabelAlloc; i<nNewSize; i++) p->aLabel[i] = -1;
+#endif
+ p->nLabelAlloc = nNewSize;
+ p->aLabel[j] = v->nOp;
+ }
+}
void sqlite3VdbeResolveLabel(Vdbe *v, int x){
Parse *p = v->pParse;
int j = ADDR(x);
assert( v->magic==VDBE_MAGIC_INIT );
- assert( j<p->nLabel );
+ assert( j<-p->nLabel );
assert( j>=0 );
- if( p->aLabel ){
#ifdef SQLITE_DEBUG
- if( p->db->flags & SQLITE_VdbeAddopTrace ){
- printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
- }
+ if( p->db->flags & SQLITE_VdbeAddopTrace ){
+ printf("RESOLVE LABEL %d to %d\n", x, v->nOp);
+ }
#endif
+ if( p->nLabelAlloc + p->nLabel < 0 ){
+ resizeResolveLabel(p,v,j);
+ }else{
assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */
p->aLabel[j] = v->nOp;
}
@@ -568,8 +636,9 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
+ || opcode==OP_VDestroy
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
- && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
+ && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
hasAbort = 1;
break;
@@ -718,7 +787,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
** have non-negative values for P2. */
assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 );
- assert( ADDR(pOp->p2)<pParse->nLabel );
+ assert( ADDR(pOp->p2)<-pParse->nLabel );
pOp->p2 = aLabel[ADDR(pOp->p2)];
}
break;
@@ -757,7 +826,7 @@ int sqlite3VdbeCurrentAddr(Vdbe *p){
*/
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){
- assert( p->nOp + N <= p->pParse->nOpAlloc );
+ assert( p->nOp + N <= p->nOpAlloc );
}
#endif
@@ -829,7 +898,7 @@ VdbeOp *sqlite3VdbeAddOpList(
VdbeOp *pOut, *pFirst;
assert( nOp>0 );
assert( p->magic==VDBE_MAGIC_INIT );
- if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
+ if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){
return 0;
}
pFirst = pOut = &p->aOp[p->nOp];
@@ -2151,19 +2220,27 @@ void sqlite3VdbeMakeReady(
** the leftover memory at the end of the opcode array. This can significantly
** reduce the amount of memory held by a prepared statement.
*/
- do {
- x.nNeeded = 0;
- p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
- p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
- p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
- p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
+ x.nNeeded = 0;
+ p->aMem = allocSpace(&x, 0, nMem*sizeof(Mem));
+ p->aVar = allocSpace(&x, 0, nVar*sizeof(Mem));
+ p->apArg = allocSpace(&x, 0, nArg*sizeof(Mem*));
+ p->apCsr = allocSpace(&x, 0, nCursor*sizeof(VdbeCursor*));
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
+ p->anExec = allocSpace(&x, 0, p->nOp*sizeof(i64));
#endif
- if( x.nNeeded==0 ) break;
+ if( x.nNeeded ){
x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
x.nFree = x.nNeeded;
- }while( !db->mallocFailed );
+ if( !db->mallocFailed ){
+ p->aMem = allocSpace(&x, p->aMem, nMem*sizeof(Mem));
+ p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
+ p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
+ p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+ p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
+#endif
+ }
+ }
p->pVList = pParse->pVList;
pParse->pVList = 0;
@@ -2855,7 +2932,7 @@ int sqlite3VdbeHalt(Vdbe *p){
}else{
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
- db->flags &= ~SQLITE_DeferFKs;
+ db->flags &= ~(u64)SQLITE_DeferFKs;
sqlite3CommitInternalChanges(db);
}
}else{
@@ -3170,6 +3247,13 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
sqlite3DbFree(db, p->zSql);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3DbFree(db, p->zNormSql);
+ {
+ DblquoteStr *pThis, *pNext;
+ for(pThis=p->pDblStr; pThis; pThis=pNext){
+ pNext = pThis->pNextStr;
+ sqlite3DbFree(db, pThis);
+ }
+ }
#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
{
@@ -3710,7 +3794,7 @@ void sqlite3VdbeRecordUnpack(
UnpackedRecord *p /* Populate this structure before returning. */
){
const unsigned char *aKey = (const unsigned char *)pKey;
- int d;
+ u32 d;
u32 idx; /* Offset in aKey[] to read from */
u16 u; /* Unsigned loop counter */
u32 szHdr;
@@ -3721,7 +3805,7 @@ void sqlite3VdbeRecordUnpack(
idx = getVarint32(aKey, szHdr);
d = szHdr;
u = 0;
- while( idx<szHdr && d<=nKey ){
+ while( idx<szHdr && d<=(u32)nKey ){
u32 serial_type;
idx += getVarint32(&aKey[idx], serial_type);
@@ -3734,7 +3818,7 @@ void sqlite3VdbeRecordUnpack(
pMem++;
if( (++u)>=p->nField ) break;
}
- if( d>nKey && u ){
+ if( d>(u32)nKey && u ){
assert( CORRUPT_DB );
/* In a corrupt record entry, the last pMem might have been set up using
** uninitialized memory. Overwrite its value with NULL, to prevent
diff --git a/chromium/third_party/sqlite/src/src/vdbemem.c b/chromium/third_party/sqlite/src/src/vdbemem.c
index 04c8f9440e9..d1abbe3d37c 100644
--- a/chromium/third_party/sqlite/src/src/vdbemem.c
+++ b/chromium/third_party/sqlite/src/src/vdbemem.c
@@ -243,7 +243,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
** if unable to complete the resizing.
*/
int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
- assert( szNew>0 );
+ assert( CORRUPT_DB || szNew>0 );
assert( (pMem->flags & MEM_Dyn)==0 || pMem->szMalloc==0 );
if( pMem->szMalloc<szNew ){
return sqlite3VdbeMemGrow(pMem, szNew, 0);
@@ -1124,6 +1124,9 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
){
int rc;
pMem->flags = MEM_Null;
+ if( sqlite3BtreeMaxRecordSize(pCur)<offset+amt ){
+ return SQLITE_CORRUPT_BKPT;
+ }
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
if( rc==SQLITE_OK ){
@@ -1530,9 +1533,11 @@ static int valueFromExpr(
}
#endif
else if( op==TK_TRUEFALSE ){
- pVal = valueNew(db, pCtx);
- pVal->flags = MEM_Int;
- pVal->u.i = pExpr->u.zToken[4]==0;
+ pVal = valueNew(db, pCtx);
+ if( pVal ){
+ pVal->flags = MEM_Int;
+ pVal->u.i = pExpr->u.zToken[4]==0;
+ }
}
*ppVal = pVal;
diff --git a/chromium/third_party/sqlite/src/src/vtab.c b/chromium/third_party/sqlite/src/src/vtab.c
index 0062984b3fd..8a4d2a5cbf2 100644
--- a/chromium/third_party/sqlite/src/src/vtab.c
+++ b/chromium/third_party/sqlite/src/src/vtab.c
@@ -1001,6 +1001,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
const sqlite3_module *pMod = pVTab->pMod->pModule;
if( pVTab->pVtab && pMod->iVersion>=2 ){
int (*xMethod)(sqlite3_vtab *, int);
+ sqlite3VtabLock(pVTab);
switch( op ){
case SAVEPOINT_BEGIN:
xMethod = pMod->xSavepoint;
@@ -1016,6 +1017,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
if( xMethod && pVTab->iSavepoint>iSavepoint ){
rc = xMethod(pVTab->pVtab, iSavepoint);
}
+ sqlite3VtabUnlock(pVTab);
}
}
}
diff --git a/chromium/third_party/sqlite/src/src/walker.c b/chromium/third_party/sqlite/src/src/walker.c
index 3d36a8cabf9..8ddeae98c19 100644
--- a/chromium/third_party/sqlite/src/src/walker.c
+++ b/chromium/third_party/sqlite/src/src/walker.c
@@ -17,6 +17,22 @@
#include <string.h>
+#if !defined(SQLITE_OMIT_WINDOWFUNC)
+/*
+** Walk all expressions linked into the list of Window objects passed
+** as the second argument.
+*/
+static int walkWindowList(Walker *pWalker, Window *pList){
+ Window *pWin;
+ for(pWin=pList; pWin; pWin=pWin->pNextWin){
+ if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
+ }
+ return WRC_Continue;
+}
+#endif
+
/*
** Walk an expression tree. Invoke the callback once for each node
** of the expression, while descending. (In other words, the callback
@@ -56,10 +72,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
- Window *pWin = pExpr->y.pWin;
- if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
- if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
+ if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
}
#endif
}
@@ -99,6 +112,16 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
+#if !defined(SQLITE_OMIT_WINDOWFUNC) && !defined(SQLITE_OMIT_ALTERTABLE)
+ {
+ Parse *pParse = pWalker->pParse;
+ if( pParse && IN_RENAME_OBJECT ){
+ int rc = walkWindowList(pWalker, p->pWinDefn);
+ assert( rc==WRC_Continue );
+ return rc;
+ }
+ }
+#endif
return WRC_Continue;
}
diff --git a/chromium/third_party/sqlite/src/src/where.c b/chromium/third_party/sqlite/src/src/where.c
index 0a264cf14f1..5710b9518e9 100644
--- a/chromium/third_party/sqlite/src/src/where.c
+++ b/chromium/third_party/sqlite/src/src/where.c
@@ -311,6 +311,17 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
/*
+** This is whereScanInit() for the case of an index on an expression.
+** It is factored out into a separate tail-recursion subroutine so that
+** the normal whereScanInit() routine, which is a high-runner, does not
+** need to push registers onto the stack as part of its prologue.
+*/
+static SQLITE_NOINLINE WhereTerm *whereScanInitIndexExpr(WhereScan *pScan){
+ pScan->idxaff = sqlite3ExprAffinity(pScan->pIdxExpr);
+ return whereScanNext(pScan);
+}
+
+/*
** Initialize a WHERE clause scanner object. Return a pointer to the
** first match. Return NULL if there are no matches.
**
@@ -342,12 +353,19 @@ static WhereTerm *whereScanInit(
pScan->pIdxExpr = 0;
pScan->idxaff = 0;
pScan->zCollName = 0;
+ pScan->opMask = opMask;
+ pScan->k = 0;
+ pScan->aiCur[0] = iCur;
+ pScan->nEquiv = 1;
+ pScan->iEquiv = 1;
if( pIdx ){
int j = iColumn;
iColumn = pIdx->aiColumn[j];
if( iColumn==XN_EXPR ){
pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
pScan->zCollName = pIdx->azColl[j];
+ pScan->aiColumn[0] = XN_EXPR;
+ return whereScanInitIndexExpr(pScan);
}else if( iColumn==pIdx->pTable->iPKey ){
iColumn = XN_ROWID;
}else if( iColumn>=0 ){
@@ -357,12 +375,7 @@ static WhereTerm *whereScanInit(
}else if( iColumn==XN_EXPR ){
return 0;
}
- pScan->opMask = opMask;
- pScan->k = 0;
- pScan->aiCur[0] = iCur;
pScan->aiColumn[0] = iColumn;
- pScan->nEquiv = 1;
- pScan->iEquiv = 1;
return whereScanNext(pScan);
}
@@ -837,7 +850,7 @@ static void constructAutomaticIndex(
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
}
if( pPartial ){
- iContinue = sqlite3VdbeMakeLabel(v);
+ iContinue = sqlite3VdbeMakeLabel(pParse);
sqlite3ExprIfFalse(pParse, pPartial, iContinue, SQLITE_JUMPIFNULL);
pLoop->wsFlags |= WHERE_PARTIALIDX;
}
@@ -854,6 +867,7 @@ static void constructAutomaticIndex(
translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
pTabItem->regResult, 1);
sqlite3VdbeGoto(v, addrTop);
+ pTabItem->fg.viaCoroutine = 0;
}else{
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
}
@@ -2209,7 +2223,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
rc = whereLoopXfer(db, p, pTemplate);
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
Index *pIndex = p->u.btree.pIndex;
- if( pIndex && pIndex->tnum==0 ){
+ if( pIndex && pIndex->idxType==SQLITE_IDXTYPE_IPK ){
p->u.btree.pIndex = 0;
}
}
@@ -2376,8 +2390,8 @@ static int whereRangeVectorLen(
** terms only. If it is modified, this value is restored before this
** function returns.
**
-** If pProbe->tnum==0, that means pIndex is a fake index used for the
-** INTEGER PRIMARY KEY.
+** If pProbe->idxType==SQLITE_IDXTYPE_IPK, that means pIndex is
+** a fake index used for the INTEGER PRIMARY KEY.
*/
static int whereLoopAddBtreeIndex(
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
@@ -2877,6 +2891,7 @@ static int whereLoopAddBtree(
sPk.onError = OE_Replace;
sPk.pTable = pTab;
sPk.szIdxRow = pTab->szTabRow;
+ sPk.idxType = SQLITE_IDXTYPE_IPK;
aiRowEstPk[0] = pTab->nRowLogEst;
aiRowEstPk[1] = 0;
pFirst = pSrc->pTab->pIndex;
@@ -2967,7 +2982,7 @@ static int whereLoopAddBtree(
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
/* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
- if( pProbe->tnum<=0 ){
+ if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
/* Integer primary key index */
pNew->wsFlags = WHERE_IPK;
@@ -4643,7 +4658,7 @@ WhereInfo *sqlite3WhereBegin(
pWInfo->pResultSet = pResultSet;
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
pWInfo->nLevel = nTabList;
- pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
+ pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(pParse);
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->iLimit = iAuxArg;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
@@ -4917,9 +4932,10 @@ WhereInfo *sqlite3WhereBegin(
if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 ){
int wsFlags = pWInfo->a[0].pWLoop->wsFlags;
int bOnerow = (wsFlags & WHERE_ONEROW)!=0;
+ assert( !(wsFlags & WHERE_VIRTUALTABLE) || IsVirtual(pTabList->a[0].pTab) );
if( bOnerow || (
0!=(wctrlFlags & WHERE_ONEPASS_MULTIROW)
- && 0==(wsFlags & WHERE_VIRTUALTABLE)
+ && !IsVirtual(pTabList->a[0].pTab)
&& (0==(wsFlags & WHERE_MULTI_OR) || (wctrlFlags & WHERE_DUPLICATES_OK))
)){
pWInfo->eOnePass = bOnerow ? ONEPASS_SINGLE : ONEPASS_MULTI;
@@ -5074,7 +5090,7 @@ WhereInfo *sqlite3WhereBegin(
pParse, pTabList, pLevel, wctrlFlags
);
pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
- notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady);
+ notReady = sqlite3WhereCodeOneLoopStart(pParse,v,pWInfo,ii,pLevel,notReady);
pWInfo->iContinue = pLevel->addrCont;
if( (wsFlags&WHERE_MULTI_OR)==0 && (wctrlFlags&WHERE_OR_SUBCLAUSE)==0 ){
sqlite3WhereAddScanStatus(v, pTabList, pLevel, addrExplain);
@@ -5259,6 +5275,29 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
continue;
}
+#ifdef SQLITE_ENABLE_EARLY_CURSOR_CLOSE
+ /* Close all of the cursors that were opened by sqlite3WhereBegin.
+ ** Except, do not close cursors that will be reused by the OR optimization
+ ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors
+ ** created for the ONEPASS optimization.
+ */
+ if( (pTab->tabFlags & TF_Ephemeral)==0
+ && pTab->pSelect==0
+ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
+ ){
+ int ws = pLoop->wsFlags;
+ if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
+ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
+ }
+ if( (ws & WHERE_INDEXED)!=0
+ && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0
+ && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1]
+ ){
+ sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
+ }
+ }
+#endif
+
/* If this scan uses an index, make VDBE code substitutions to read data
** from the index instead of from the table where possible. In some cases
** this optimization prevents the table from ever being read, which can
diff --git a/chromium/third_party/sqlite/src/src/whereInt.h b/chromium/third_party/sqlite/src/src/whereInt.h
index 6925e39e1d2..07461a5bac3 100644
--- a/chromium/third_party/sqlite/src/src/whereInt.h
+++ b/chromium/third_party/sqlite/src/src/whereInt.h
@@ -507,8 +507,11 @@ void sqlite3WhereAddScanStatus(
# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d)
#endif
Bitmask sqlite3WhereCodeOneLoopStart(
+ Parse *pParse, /* Parsing context */
+ Vdbe *v, /* Prepared statement under construction */
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
+ WhereLevel *pLevel, /* The current level pointer */
Bitmask notReady /* Which tables are currently available */
);
diff --git a/chromium/third_party/sqlite/src/src/wherecode.c b/chromium/third_party/sqlite/src/src/wherecode.c
index bbd738b8edd..7a0547d348d 100644
--- a/chromium/third_party/sqlite/src/src/wherecode.c
+++ b/chromium/third_party/sqlite/src/src/wherecode.c
@@ -213,6 +213,7 @@ int sqlite3WhereExplainOneScan(
}
#endif
zMsg = sqlite3StrAccumFinish(&str);
+ sqlite3ExplainBreakpoint("",zMsg);
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
}
@@ -538,16 +539,17 @@ static int codeEqualityTerm(
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
}
+ iTab = 0;
if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0);
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
}else{
sqlite3 *db = pParse->db;
pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
if( !db->mallocFailed ){
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap);
- pTerm->pExpr->iTable = pX->iTable;
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
+ pTerm->pExpr->iTable = iTab;
}
sqlite3ExprDelete(db, pX);
pX = pTerm->pExpr;
@@ -557,7 +559,6 @@ static int codeEqualityTerm(
testcase( bRev );
bRev = !bRev;
}
- iTab = pX->iTable;
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
VdbeCoverageIf(v, bRev);
VdbeCoverageIf(v, !bRev);
@@ -565,7 +566,7 @@ static int codeEqualityTerm(
pLoop->wsFlags |= WHERE_IN_ABLE;
if( pLevel->u.in.nIn==0 ){
- pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
+ pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
}
i = pLevel->u.in.nIn;
@@ -1076,7 +1077,9 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
#ifndef SQLITE_OMIT_SUBQUERY
if( (p->flags & EP_xIsSelect) ){
Vdbe *v = pParse->pVdbe;
- int iSelect = sqlite3CodeSubselect(pParse, p, 0, 0);
+ int iSelect;
+ assert( p->op==TK_SELECT );
+ iSelect = sqlite3CodeSubselect(pParse, p);
sqlite3VdbeAddOp3(v, OP_Copy, iSelect, iReg, nReg-1);
}else
#endif
@@ -1162,22 +1165,21 @@ static void whereIndexExprTrans(
** implementation described by pWInfo.
*/
Bitmask sqlite3WhereCodeOneLoopStart(
+ Parse *pParse, /* Parsing context */
+ Vdbe *v, /* Prepared statement under construction */
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
+ WhereLevel *pLevel, /* The current level pointer */
Bitmask notReady /* Which tables are currently available */
){
int j, k; /* Loop counters */
int iCur; /* The VDBE cursor for the table */
int addrNxt; /* Where to jump to continue with the next IN case */
- int omitTable; /* True if we use the index only */
int bRev; /* True if we need to scan in reverse order */
- WhereLevel *pLevel; /* The where level to be coded */
WhereLoop *pLoop; /* The WhereLoop object being coded */
WhereClause *pWC; /* Decomposition of the entire WHERE clause */
WhereTerm *pTerm; /* A WHERE clause term */
- Parse *pParse; /* Parsing context */
sqlite3 *db; /* Database connection */
- Vdbe *v; /* The prepared stmt under constructions */
struct SrcList_item *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
int addrHalt; /* addrBrk for the outermost loop */
@@ -1187,18 +1189,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
Index *pIdx = 0; /* Index used by loop (if any) */
int iLoop; /* Iteration of constraint generator loop */
- pParse = pWInfo->pParse;
- v = pParse->pVdbe;
pWC = &pWInfo->sWC;
db = pParse->db;
- pLevel = &pWInfo->a[iLevel];
pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
- omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0;
VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
/* Create labels for the "break" and "continue" instructions
@@ -1211,8 +1208,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** there are no IN operators in the constraints, the "addrNxt" label
** is the same as "addrBrk".
*/
- addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
- addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v);
+ addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
+ addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);
/* If this is the right table of a LEFT OUTER JOIN, allocate and
** initialize a memory cell that records if this table matches any
@@ -1339,7 +1336,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
- assert( omitTable==0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
iReleaseReg = ++pParse->nMem;
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
@@ -1358,7 +1354,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
int memEndValue = 0;
WhereTerm *pStart, *pEnd;
- assert( omitTable==0 );
j = 0;
pStart = pEnd = 0;
if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++];
@@ -1522,6 +1517,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
char *zEndAff = 0; /* Affinity for end of range constraint */
u8 bSeekPastNull = 0; /* True to seek past initial nulls */
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
+ int omitTable; /* True if we use the index only */
+
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
@@ -1723,6 +1720,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
/* Seek the table cursor, if required */
+ omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
+ && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0;
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
@@ -1757,8 +1756,13 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** the cursor. In this case it is important to do the full evaluation,
** as the result of the expression may not be NULL, even if all table
** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
+ **
+ ** Also, do not do this when processing one index an a multi-index
+ ** OR clause, since the transformation will become invalid once we
+ ** move forward to the next index.
+ ** https://sqlite.org/src/info/4e8e4857d32d401f
*/
- if( pLevel->iLeftJoin==0 ){
+ if( pLevel->iLeftJoin==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
}
@@ -1833,7 +1837,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
int regRowset = 0; /* Register for RowSet object */
int regRowid = 0; /* Register holding rowid */
- int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
+ int iLoopBody = sqlite3VdbeMakeLabel(pParse);/* Start of loop body */
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
@@ -1949,6 +1953,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pOrExpr = pAndExpr;
}
/* Loop through table entries that match term pOrTerm. */
+ ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
wctrlFlags, iCovCur);
@@ -2052,6 +2057,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
+ ExplainQueryPlanPop(pParse);
}
}
}
diff --git a/chromium/third_party/sqlite/src/src/whereexpr.c b/chromium/third_party/sqlite/src/src/whereexpr.c
index e91f1d72165..db5500cce7a 100644
--- a/chromium/third_party/sqlite/src/src/whereexpr.c
+++ b/chromium/third_party/sqlite/src/src/whereexpr.c
@@ -777,6 +777,7 @@ static void exprAnalyzeOrTerm(
** and column is found but leave okToChngToIN false if not found.
*/
for(j=0; j<2 && !okToChngToIN; j++){
+ Expr *pLeft = 0;
pOrTerm = pOrWc->a;
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
assert( pOrTerm->eOperator & WO_EQ );
@@ -800,6 +801,7 @@ static void exprAnalyzeOrTerm(
}
iColumn = pOrTerm->u.leftColumn;
iCursor = pOrTerm->leftCursor;
+ pLeft = pOrTerm->pExpr->pLeft;
break;
}
if( i<0 ){
@@ -819,7 +821,9 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->eOperator & WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OR_OK;
- }else if( pOrTerm->u.leftColumn!=iColumn ){
+ }else if( pOrTerm->u.leftColumn!=iColumn || (iColumn==XN_EXPR
+ && sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
+ )){
okToChngToIN = 0;
}else{
int affLeft, affRight;
diff --git a/chromium/third_party/sqlite/src/src/window.c b/chromium/third_party/sqlite/src/src/window.c
index ec3d55cef7e..11b7afed2cd 100644
--- a/chromium/third_party/sqlite/src/src/window.c
+++ b/chromium/third_party/sqlite/src/src/window.c
@@ -823,8 +823,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
pSub = sqlite3SelectNew(
pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
);
- p->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- assert( p->pSrc || db->mallocFailed );
+ p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
if( p->pSrc ){
p->pSrc->a[0].pSelect = pSub;
sqlite3SrcListAssignCursors(pParse, p->pSrc);
@@ -881,6 +880,7 @@ void sqlite3WindowListDelete(sqlite3 *db, Window *p){
*/
static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){
if( 0==sqlite3ExprIsConstant(pExpr) ){
+ if( IN_RENAME_OBJECT ) sqlite3RenameExprUnmap(pParse, pExpr);
sqlite3ExprDelete(pParse->db, pExpr);
pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0);
}
@@ -1075,6 +1075,7 @@ static void windowCheckIntValue(Parse *pParse, int reg, int eCond){
VdbeCoverageNeverNullIf(v, eCond==0);
VdbeCoverageNeverNullIf(v, eCond==1);
VdbeCoverageNeverNullIf(v, eCond==2);
+ sqlite3MayAbort(pParse);
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC);
sqlite3ReleaseTempReg(pParse, regZero);
@@ -1330,7 +1331,7 @@ static void windowReturnOneRow(
|| pFunc->zName==first_valueName
){
int csr = pWin->csrApp;
- int lbl = sqlite3VdbeMakeLabel(v);
+ int lbl = sqlite3VdbeMakeLabel(pParse);
int tmpReg = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
@@ -1353,7 +1354,7 @@ static void windowReturnOneRow(
int nArg = pWin->pOwner->x.pList->nExpr;
int iEph = pMWin->iEphCsr;
int csr = pWin->csrApp;
- int lbl = sqlite3VdbeMakeLabel(v);
+ int lbl = sqlite3VdbeMakeLabel(pParse);
int tmpReg = sqlite3GetTempReg(pParse);
if( nArg<3 ){
@@ -1614,8 +1615,8 @@ static void windowCodeRowExprStep(
/* Allocate register and label for the "flush_partition" sub-routine. */
regFlushPart = ++pParse->nMem;
- lblFlushPart = sqlite3VdbeMakeLabel(v);
- lblFlushDone = sqlite3VdbeMakeLabel(v);
+ lblFlushPart = sqlite3VdbeMakeLabel(pParse);
+ lblFlushDone = sqlite3VdbeMakeLabel(pParse);
regStart = ++pParse->nMem;
regEnd = ++pParse->nMem;
@@ -1725,7 +1726,7 @@ static void windowCodeRowExprStep(
|| pMWin->eStart==TK_PRECEDING
|| pMWin->eStart==TK_FOLLOWING
){
- int lblSkipInverse = sqlite3VdbeMakeLabel(v);;
+ int lblSkipInverse = sqlite3VdbeMakeLabel(pParse);;
if( pMWin->eStart==TK_PRECEDING ){
sqlite3VdbeAddOp3(v, OP_IfPos, regStart, lblSkipInverse, 1);
VdbeCoverage(v);
@@ -1890,13 +1891,13 @@ static void windowCodeCacheStep(
|| (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED)
);
- lblEmpty = sqlite3VdbeMakeLabel(v);
+ lblEmpty = sqlite3VdbeMakeLabel(pParse);
regNewPeer = pParse->nMem+1;
pParse->nMem += nPeer;
/* Allocate register and label for the "flush_partition" sub-routine. */
regFlushPart = ++pParse->nMem;
- lblFlushPart = sqlite3VdbeMakeLabel(v);
+ lblFlushPart = sqlite3VdbeMakeLabel(pParse);
csrLead = pParse->nTab++;
regCtr = ++pParse->nMem;
@@ -2133,6 +2134,7 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
if( pNew ){
pNew->zName = sqlite3DbStrDup(db, p->zName);
pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
+ pNew->pFunc = p->pFunc;
pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
pNew->eType = p->eType;
diff --git a/chromium/third_party/sqlite/src/tool/dbtotxt.c b/chromium/third_party/sqlite/src/tool/dbtotxt.c
new file mode 100644
index 00000000000..da9abf9ebd4
--- /dev/null
+++ b/chromium/third_party/sqlite/src/tool/dbtotxt.c
@@ -0,0 +1,146 @@
+/*
+** Copyright 2008 D. Richard Hipp and Hipp, Wyrick & Company, Inc.
+** All Rights Reserved
+**
+******************************************************************************
+**
+** This file implements a stand-alone utility program that converts
+** a binary file (usually an SQLite database) into a text format that
+** is compact and friendly to human-readers.
+**
+** Usage:
+**
+** dbtotxt [--pagesize N] FILENAME
+**
+** The translation of the database appears on standard output. If the
+** --pagesize command-line option is omitted, then the page size is taken
+** from the database header.
+**
+** Compactness is achieved by suppressing lines of all zero bytes. This
+** works well at compressing test databases that are mostly empty. But
+** the output will probably be lengthy for a real database containing lots
+** of real content. For maximum compactness, it is suggested that test
+** databases be constructed with "zeroblob()" rather than "randomblob()"
+** used for filler content and with "PRAGMA secure_delete=ON" selected to
+** zero-out deleted content.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+/* Return true if the line is all zeros */
+static int allZero(unsigned char *aLine){
+ int i;
+ for(i=0; i<16 && aLine[i]==0; i++){}
+ return i==16;
+}
+
+int main(int argc, char **argv){
+ int pgsz = 0; /* page size */
+ long szFile; /* Size of the input file in bytes */
+ FILE *in; /* Input file */
+ int i, j; /* Loop counters */
+ int nErr = 0; /* Number of errors */
+ const char *zInputFile = 0; /* Name of the input file */
+ const char *zBaseName = 0; /* Base name of the file */
+ int lastPage = 0; /* Last page number shown */
+ int iPage; /* Current page number */
+ unsigned char aLine[16]; /* A single line of the file */
+ unsigned char aHdr[100]; /* File header */
+ unsigned char bShow[256]; /* Characters ok to display */
+ memset(bShow, '.', sizeof(bShow));
+ for(i=' '; i<='~'; i++){
+ if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = i;
+ }
+ for(i=1; i<argc; i++){
+ if( argv[i][0]=='-' ){
+ const char *z = argv[i];
+ z++;
+ if( z[0]=='-' ) z++;
+ if( strcmp(z,"pagesize")==0 ){
+ i++;
+ pgsz = atoi(argv[i]);
+ if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
+ fprintf(stderr, "Page size must be a power of two between"
+ " 512 and 65536.\n");
+ nErr++;
+ }
+ continue;
+ }
+ fprintf(stderr, "Unknown option: %s\n", argv[i]);
+ nErr++;
+ }else if( zInputFile ){
+ fprintf(stderr, "Already using a different input file: [%s]\n", argv[i]);
+ nErr++;
+ }else{
+ zInputFile = argv[i];
+ }
+ }
+ if( zInputFile==0 ){
+ fprintf(stderr, "No input file specified.\n");
+ nErr++;
+ }
+ if( nErr ){
+ fprintf(stderr, "Usage: %s [--pagesize N] FILENAME\n", argv[0]);
+ exit(1);
+ }
+ in = fopen(zInputFile, "rb");
+ if( in==0 ){
+ fprintf(stderr, "Cannot open input file [%s]\n", zInputFile);
+ exit(1);
+ }
+ fseek(in, 0, SEEK_END);
+ szFile = ftell(in);
+ rewind(in);
+ if( szFile<100 ){
+ fprintf(stderr, "File too short. Minimum size is 100 bytes.\n");
+ exit(1);
+ }
+ if( fread(aHdr, 100, 1, in)!=1 ){
+ fprintf(stderr, "Cannot read file header\n");
+ exit(1);
+ }
+ rewind(in);
+ if( pgsz==0 ){
+ pgsz = (aHdr[16]<<8) | aHdr[17];
+ if( pgsz==1 ) pgsz = 65536;
+ if( pgsz<512 || (pgsz&(pgsz-1))!=0 ){
+ fprintf(stderr, "Invalid page size in header: %d\n", pgsz);
+ exit(1);
+ }
+ }
+ zBaseName = zInputFile;
+ for(i=0; zInputFile[i]; i++){
+ if( zInputFile[i]=='/' && zInputFile[i+1]!=0 ) zBaseName = zInputFile+i+1;
+ }
+ printf("| size %d pagesize %d filename %s\n",(int)szFile,pgsz,zBaseName);
+ for(i=0; i<szFile; i+=16){
+ int got = (int)fread(aLine, 1, 16, in);
+ if( got!=16 ){
+ static int once = 1;
+ if( once ){
+ fprintf(stderr, "Could not read input file starting at byte %d\n",
+ i+got);
+ }
+ memset(aLine+got, 0, 16-got);
+ }
+ if( allZero(aLine) ) continue;
+ iPage = i/pgsz + 1;
+ if( lastPage!=iPage ){
+ printf("| page %d offset %d\n", iPage, (iPage-1)*pgsz);
+ lastPage = iPage;
+ }
+ printf("| %5d:", i-(iPage-1)*pgsz);
+ for(j=0; j<16; j++) printf(" %02x", aLine[j]);
+ printf(" ");
+ for(j=0; j<16; j++){
+ unsigned char c = (unsigned char)aLine[j];
+ fputc( bShow[c], stdout);
+ }
+ fputc('\n', stdout);
+ }
+ fclose(in);
+ printf("| end %s\n", zBaseName);
+ return 0;
+}
diff --git a/chromium/third_party/sqlite/src/tool/dbtotxt.md b/chromium/third_party/sqlite/src/tool/dbtotxt.md
new file mode 100644
index 00000000000..c755843d120
--- /dev/null
+++ b/chromium/third_party/sqlite/src/tool/dbtotxt.md
@@ -0,0 +1,56 @@
+<h1 align="center">The dbtotxt Tool</h1>
+
+The dbtotxt utility program reads an SQLite database file and writes its
+raw binary content to screen as a hex dump for testing and debugging
+purposes.
+
+The hex-dump output is formatted in such a way as to be easily readable
+both by humans and by software. The dbtotxt utility has long been a part
+of the TH3 test suite. The output of dbtotxt can be embedded in TH3 test
+scripts and used to generate very specific database files, perhaps with
+deliberately introduced corruption. The cov1/corrupt*.test modules in
+TH3 make extensive use of dbtotxt.
+
+More recently (2018-12-13) the dbtotxt utility has been added to the SQLite
+core and the command-line shell (CLI) has been augmented to be able to read
+dbtotxt output. The CLI dot-command is:
+
+> .open --hexdb ?OPTIONAL-FILENAME?
+
+If the OPTIONAL-FILENAME is included, then content is read from that file.
+If OPTIONAL-FILENAME is omitted, then the text is taken from the input stream,
+terminated by the "| end" line of the dbtotxt text. This allows small test
+databases to be embedded directly in scripts. Consider this example:
+
+>
+ .open --hexdb
+ | size 8192 pagesize 4096 filename x9.db
+ | page 1 offset 0
+ | 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
+ | 16: 10 00 01 01 00 40 20 20 00 00 00 04 00 00 00 02 .....@ ........
+ | 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
+ | 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
+ | 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................
+ | 96: 00 2e 30 38 0d 00 00 00 01 0f c0 00 0f c0 00 00 ..08............
+ | 4032: 3e 01 06 17 11 11 01 69 74 61 62 6c 65 74 31 74 >......itablet1t
+ | 4048: 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 1.CREATE TABLE t
+ | 4064: 31 28 78 2c 79 20 44 45 46 41 55 4c 54 20 78 27 1(x,y DEFAULT x'
+ | 4080: 66 66 27 2c 7a 20 44 45 46 41 55 4c 54 20 30 29 ff',z DEFAULT 0)
+ | page 2 offset 4096
+ | 0: 0d 08 14 00 04 00 10 00 0e 05 0a 0f 04 15 00 10 ................
+ | 16: 88 02 03 05 90 04 0e 08 00 00 00 00 00 00 00 00 ................
+ | 1040: 00 00 00 00 ff 87 7c 02 05 8f 78 0e 08 00 00 00 ......|...x.....
+ | 2064: 00 00 00 ff 0c 0a 01 fb 00 00 00 00 00 00 00 00 ................
+ | 2560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 83 ................
+ | 2576: 78 01 05 87 70 0e 08 00 00 00 00 00 00 00 00 00 x...p...........
+ | 3072: 00 00 00 00 00 00 00 00 00 ff 00 00 01 fb 00 00 ................
+ | 3584: 00 00 00 00 00 83 78 00 05 87 70 0e 08 00 00 00 ......x...p.....
+ | 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ................
+ | end x9.db
+ SELECT rowid FROM t1;
+ PRAGMA integrity_check;
+
+You can run this script to see that the database file is correctly decoded
+and loaded. Furthermore, you can make subtle corruptions to the input
+database simply by editing the hexadecimal description, then rerun the
+script to verify that SQLite correctly handles the corruption.
diff --git a/chromium/third_party/sqlite/src/tool/index_usage.c b/chromium/third_party/sqlite/src/tool/index_usage.c
new file mode 100644
index 00000000000..7ec5fc1b443
--- /dev/null
+++ b/chromium/third_party/sqlite/src/tool/index_usage.c
@@ -0,0 +1,233 @@
+/*
+** 2018-12-04
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements a utility program used to help determine which
+** indexes in a database schema are used and unused, and how often specific
+** indexes are used.
+*/
+#include "sqlite3.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+static void usage(const char *argv0){
+ printf("Usage: %s [OPTIONS] DATABASE LOG\n\n", argv0);
+ printf(
+ "DATABASE is an SQLite database against which various statements\n"
+ "have been run. The SQL text is stored in LOG. LOG is an SQLite\n"
+ "database with this schema:\n"
+ "\n"
+ " CREATE TABLE sqllog(sql TEXT);\n"
+ "\n"
+ "This utility program analyzes statements contained in LOG and prints\n"
+ "a report showing how many times each index in DATABASE is used by the\n"
+ "statements in LOG.\n"
+ "\n"
+ "DATABASE only needs to contain the schema used by the statements in\n"
+ "LOG. The content can be removed from DATABASE.\n"
+ );
+ printf(
+ "\nOPTIONS:\n\n"
+ " --progress N Show a progress message after every N input rows\n"
+ " -q Omit error message when parsing log entries\n"
+ " --using NAME Print SQL statements that use index NAME\n"
+ );
+ printf("\nAnalysis will be done by SQLite version %s dated %.20s\n"
+ "checkin number %.40s. Different versions\n"
+ "of SQLite might use different indexes.\n",
+ sqlite3_libversion(), sqlite3_sourceid(), sqlite3_sourceid()+21);
+ exit(1);
+}
+
+int main(int argc, char **argv){
+ sqlite3 *db = 0; /* The main database */
+ sqlite3_stmt *pStmt = 0; /* a query */
+ char *zSql;
+ int nErr = 0;
+ int rc;
+ int bQuiet = 0;
+ int i, j;
+ const char *zUsing = 0;
+ sqlite3_stmt *pIncrCnt = 0;
+ int nRow = 0;
+ int iProgress = 0;
+
+ for(i=j=1; i<argc; i++){
+ const char *z = argv[i];
+ if( z[0]=='-' ){
+ z++;
+ if( z[0]=='-' ) z++;
+ if( strcmp(z,"progress")==0 ){
+ if( i+1<argc ){
+ iProgress = strtol(argv[++i],0,0);
+ continue;
+ }
+ printf("The --progress option requires an argument\n");
+ exit(0);
+ }
+ if( strcmp(z,"q")==0 ){
+ bQuiet = 1;
+ continue;
+ }
+ if( strcmp(z,"using")==0 ){
+ if( i+1<argc ){
+ zUsing = argv[++i];
+ continue;
+ }
+ printf("The --using option requires an argument\n");
+ exit(0);
+ }
+ if( strcmp(z, "help")==0 || strcmp(z, "?")==0 ){
+ usage(argv[0]);
+ }
+ printf("Unknown command-line option: \"%s\"\n", argv[i]);
+ exit(0);
+ }else{
+ if( j<i ) argv[j++] = argv[i];
+ }
+ }
+ argc = j;
+
+ if( argc!=3 ) usage(argv[0]);
+ rc = sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READONLY, 0);
+ if( rc ){
+ printf("Cannot open \"%s\" for reading: %s\n", argv[1], sqlite3_errmsg(db));
+ goto errorOut;
+ }
+ rc = sqlite3_prepare_v2(db, "SELECT * FROM sqlite_master", -1, &pStmt, 0);
+ if( rc ){
+ printf("Cannot read the schema from \"%s\" - %s\n", argv[1],
+ sqlite3_errmsg(db));
+ goto errorOut;
+ }
+ sqlite3_finalize(pStmt);
+ pStmt = 0;
+ rc = sqlite3_exec(db,
+ "CREATE TABLE temp.idxu(\n"
+ " tbl TEXT COLLATE nocase,\n"
+ " idx TEXT COLLATE nocase,\n"
+ " cnt INT,\n"
+ " PRIMARY KEY(idx)\n"
+ ") WITHOUT ROWID;", 0, 0, 0);
+ if( rc ){
+ printf("Cannot create the result table - %s\n",
+ sqlite3_errmsg(db));
+ goto errorOut;
+ }
+ rc = sqlite3_exec(db,
+ "INSERT INTO temp.idxu(tbl,idx,cnt)"
+ " SELECT tbl_name, name, 0 FROM sqlite_master"
+ " WHERE type='index' AND sql IS NOT NULL", 0, 0, 0);
+
+ /* Open the LOG database */
+ zSql = sqlite3_mprintf("ATTACH %Q AS log", argv[2]);
+ rc = sqlite3_exec(db, zSql, 0, 0, 0);
+ sqlite3_free(zSql);
+ if( rc ){
+ printf("Cannot open the LOG database \"%s\" - %s\n",
+ argv[2], sqlite3_errmsg(db));
+ goto errorOut;
+ }
+ rc = sqlite3_prepare_v2(db,
+ "SELECT sql, rowid FROM log.sqllog"
+ " WHERE upper(substr(sql,1,5)) NOT IN ('BEGIN','COMMI','ROLLB','PRAGM')",
+ -1, &pStmt, 0);
+ if( rc ){
+ printf("Cannot read the SQLLOG table in the LOG database \"%s\" - %s\n",
+ argv[2], sqlite3_errmsg(db));
+ goto errorOut;
+ }
+
+ rc = sqlite3_prepare_v2(db,
+ "UPDATE temp.idxu SET cnt=cnt+1 WHERE idx=?1",
+ -1, &pIncrCnt, 0);
+ if( rc ){
+ printf("Cannot prepare a statement to increment a counter for "
+ "indexes used\n");
+ goto errorOut;
+ }
+
+ /* Update the counts based on LOG */
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ const char *zLog = (const char*)sqlite3_column_text(pStmt, 0);
+ sqlite3_stmt *pS2;
+ if( zLog==0 ) continue;
+ zSql = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zLog);
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pS2, 0);
+ sqlite3_free(zSql);
+ if( rc ){
+ if( !bQuiet ){
+ printf("Cannot compile LOG entry %d (%s): %s\n",
+ sqlite3_column_int(pStmt, 1), zLog, sqlite3_errmsg(db));
+ fflush(stdout);
+ }
+ nErr++;
+ }else{
+ nRow++;
+ if( iProgress>0 && (nRow%iProgress)==0 ){
+ printf("%d...\n", nRow);
+ fflush(stdout);
+ }
+ while( sqlite3_step(pS2)==SQLITE_ROW ){
+ const char *zExplain = (const char*)sqlite3_column_text(pS2,3);
+ const char *z1, *z2;
+ int n;
+ /* printf("EXPLAIN: %s\n", zExplain); */
+ z1 = strstr(zExplain, " USING INDEX ");
+ if( z1==0 ) continue;
+ z1 += 13;
+ for(z2=z1+1; z2[0] && z2[1]!='('; z2++){}
+ n = z2 - z1;
+ if( zUsing && sqlite3_strnicmp(zUsing, z1, n)==0 ){
+ printf("Using %s:\n%s\n", zUsing, zLog);
+ fflush(stdout);
+ }
+ sqlite3_bind_text(pIncrCnt,1,z1,n,SQLITE_STATIC);
+ sqlite3_step(pIncrCnt);
+ sqlite3_reset(pIncrCnt);
+ }
+ }
+ sqlite3_finalize(pS2);
+ }
+ sqlite3_finalize(pStmt);
+
+ /* Generate the report */
+ rc = sqlite3_prepare_v2(db,
+ "SELECT tbl, idx, cnt, "
+ " (SELECT group_concat(name,',') FROM pragma_index_info(idx))"
+ " FROM temp.idxu, main.sqlite_master"
+ " WHERE temp.idxu.tbl=main.sqlite_master.tbl_name"
+ " AND temp.idxu.idx=main.sqlite_master.name"
+ " ORDER BY cnt DESC, tbl, idx",
+ -1, &pStmt, 0);
+ if( rc ){
+ printf("Cannot query the result table - %s\n",
+ sqlite3_errmsg(db));
+ goto errorOut;
+ }
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ printf("%10d %s on %s(%s)\n",
+ sqlite3_column_int(pStmt, 2),
+ sqlite3_column_text(pStmt, 1),
+ sqlite3_column_text(pStmt, 0),
+ sqlite3_column_text(pStmt, 3));
+ }
+ sqlite3_finalize(pStmt);
+ pStmt = 0;
+
+errorOut:
+ sqlite3_finalize(pIncrCnt);
+ sqlite3_finalize(pStmt);
+ sqlite3_close(db);
+ return nErr;
+}
diff --git a/chromium/third_party/sqlite/src/tool/lemon.c b/chromium/third_party/sqlite/src/tool/lemon.c
index e7eaaa6eeec..a90bb33f46c 100644
--- a/chromium/third_party/sqlite/src/tool/lemon.c
+++ b/chromium/third_party/sqlite/src/tool/lemon.c
@@ -4590,13 +4590,20 @@ void ReportTable(
tplt_print(out,lemp,lemp->overflow,&lineno);
tplt_xfer(lemp->name,in,out,&lineno);
- /* Generate the table of rule information
+ /* Generate the tables of rule information. yyRuleInfoLhs[] and
+ ** yyRuleInfoNRhs[].
**
** Note: This code depends on the fact that rules are number
** sequentually beginning with 0.
*/
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
- fprintf(out," { %4d, %4d }, /* (%d) ",rp->lhs->index,-rp->nrhs,i);
+ fprintf(out," %4d, /* (%d) ", rp->lhs->index, i);
+ rule_print(out, rp);
+ fprintf(out," */\n"); lineno++;
+ }
+ tplt_xfer(lemp->name,in,out,&lineno);
+ for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
+ fprintf(out," %3d, /* (%d) ", -rp->nrhs, i);
rule_print(out, rp);
fprintf(out," */\n"); lineno++;
}
@@ -4667,6 +4674,7 @@ void ReportTable(
/* Append any addition code the user desires */
tplt_print(out,lemp,lemp->extracode,&lineno);
+ acttab_free(pActtab);
fclose(in);
fclose(out);
return;
diff --git a/chromium/third_party/sqlite/src/tool/lempar.c b/chromium/third_party/sqlite/src/tool/lempar.c
index 2ea791518f7..5a0d56fa36c 100644
--- a/chromium/third_party/sqlite/src/tool/lempar.c
+++ b/chromium/third_party/sqlite/src/tool/lempar.c
@@ -686,13 +686,15 @@ static void yy_shift(
yyTraceShift(yypParser, yyNewState, "Shift");
}
-/* The following table contains information about every rule that
-** is used during the reduce.
-*/
-static const struct {
- YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
- signed char nrhs; /* Negative of the number of RHS symbols in the rule */
-} yyRuleInfo[] = {
+/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
+** of that rule */
+static const YYCODETYPE yyRuleInfoLhs[] = {
+%%
+};
+
+/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
+** of symbols on the right-hand side of that rule. */
+static const signed char yyRuleInfoNRhs[] = {
%%
};
@@ -725,7 +727,7 @@ static YYACTIONTYPE yy_reduce(
yymsp = yypParser->yytos;
#ifndef NDEBUG
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
- yysize = yyRuleInfo[yyruleno].nrhs;
+ yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
yyTracePrompt,
@@ -740,7 +742,7 @@ static YYACTIONTYPE yy_reduce(
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
- if( yyRuleInfo[yyruleno].nrhs==0 ){
+ if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
@@ -782,9 +784,9 @@ static YYACTIONTYPE yy_reduce(
%%
/********** End reduce actions ************************************************/
};
- assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
- yygoto = yyRuleInfo[yyruleno].lhs;
- yysize = yyRuleInfo[yyruleno].nrhs;
+ assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
+ yygoto = yyRuleInfoLhs[yyruleno];
+ yysize = yyRuleInfoNRhs[yyruleno];
yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
/* There are no SHIFTREDUCE actions on nonterminals because the table
diff --git a/chromium/third_party/sqlite/src/tool/mkpragmatab.tcl b/chromium/third_party/sqlite/src/tool/mkpragmatab.tcl
index f6cf7790317..0b3b7ef70ae 100644
--- a/chromium/third_party/sqlite/src/tool/mkpragmatab.tcl
+++ b/chromium/third_party/sqlite/src/tool/mkpragmatab.tcl
@@ -294,7 +294,10 @@ set pragma_def {
IF: !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
NAME: parser_trace
- IF: defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_PARSER_TRACE)
+ TYPE: FLAG
+ ARG: SQLITE_ParserTrace
+ IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ IF: defined(SQLITE_DEBUG)
NAME: case_sensitive_like
FLAG: NoColumns
diff --git a/chromium/third_party/webrtc/rtc_base/network.cc b/chromium/third_party/webrtc/rtc_base/network.cc
index 0bbb260b206..496c769b17a 100644
--- a/chromium/third_party/webrtc/rtc_base/network.cc
+++ b/chromium/third_party/webrtc/rtc_base/network.cc
@@ -283,8 +283,8 @@ void NetworkManagerBase::GetAnyAddressNetworks(NetworkList* networks) {
ipv4_any_address_network_.reset(
new rtc::Network("any", "any", ipv4_any_address, 0, ADAPTER_TYPE_ANY));
ipv4_any_address_network_->set_default_local_address_provider(this);
+ ipv4_any_address_network_->set_mdns_responder_provider(this);
ipv4_any_address_network_->AddIP(ipv4_any_address);
- ipv4_any_address_network_->SetMdnsResponder(GetMdnsResponder());
}
networks->push_back(ipv4_any_address_network_.get());
@@ -293,8 +293,8 @@ void NetworkManagerBase::GetAnyAddressNetworks(NetworkList* networks) {
ipv6_any_address_network_.reset(
new rtc::Network("any", "any", ipv6_any_address, 0, ADAPTER_TYPE_ANY));
ipv6_any_address_network_->set_default_local_address_provider(this);
+ ipv6_any_address_network_->set_mdns_responder_provider(this);
ipv6_any_address_network_->AddIP(ipv6_any_address);
- ipv6_any_address_network_->SetMdnsResponder(GetMdnsResponder());
}
networks->push_back(ipv6_any_address_network_.get());
}
@@ -383,7 +383,7 @@ void NetworkManagerBase::MergeNetworkList(const NetworkList& new_networks,
delete net;
}
}
- networks_map_[key]->SetMdnsResponder(GetMdnsResponder());
+ networks_map_[key]->set_mdns_responder_provider(this);
}
// It may still happen that the merged list is a subset of |networks_|.
// To detect this change, we compare their sizes.
@@ -739,6 +739,7 @@ bool BasicNetworkManager::CreateNetworks(bool include_ignored,
std::unique_ptr<Network> network(new Network(
name, description, prefix, prefix_length, adapter_type));
network->set_default_local_address_provider(this);
+ network->set_mdns_responder_provider(this);
network->set_scope_id(scope_id);
network->AddIP(ip);
bool ignored = IsIgnoredNetwork(*network);
@@ -1049,6 +1050,13 @@ IPAddress Network::GetBestIP() const {
return static_cast<IPAddress>(selected_ip);
}
+webrtc::MdnsResponderInterface* Network::GetMdnsResponder() const {
+ if (mdns_responder_provider_ == nullptr) {
+ return nullptr;
+ }
+ return mdns_responder_provider_->GetMdnsResponder();
+}
+
uint16_t Network::GetCost() const {
AdapterType type = IsVpn() ? underlying_type_for_vpn_ : type_;
return ComputeNetworkCostByType(type);
diff --git a/chromium/third_party/webrtc/rtc_base/network.h b/chromium/third_party/webrtc/rtc_base/network.h
index aa806af5140..d202f6eb6c5 100644
--- a/chromium/third_party/webrtc/rtc_base/network.h
+++ b/chromium/third_party/webrtc/rtc_base/network.h
@@ -57,12 +57,24 @@ AdapterType GetAdapterTypeFromName(const char* network_name);
class DefaultLocalAddressProvider {
public:
virtual ~DefaultLocalAddressProvider() = default;
+
// The default local address is the local address used in multi-homed endpoint
// when the any address (0.0.0.0 or ::) is used as the local address. It's
// important to check the return value as a IP family may not be enabled.
virtual bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const = 0;
};
+class MdnsResponderProvider {
+ public:
+ virtual ~MdnsResponderProvider() = default;
+
+ // Returns the mDNS responder that can be used to obfuscate the local IP
+ // addresses of ICE host candidates by mDNS hostnames.
+ //
+ // The provider MUST outlive the mDNS responder.
+ virtual webrtc::MdnsResponderInterface* GetMdnsResponder() const = 0;
+};
+
// Generic network manager interface. It provides list of local
// networks.
//
@@ -72,7 +84,8 @@ class DefaultLocalAddressProvider {
//
// This allows constructing a NetworkManager subclass on one thread and
// passing it into an object that uses it on a different thread.
-class NetworkManager : public DefaultLocalAddressProvider {
+class NetworkManager : public DefaultLocalAddressProvider,
+ public MdnsResponderProvider {
public:
typedef std::vector<Network*> NetworkList;
@@ -139,9 +152,8 @@ class NetworkManager : public DefaultLocalAddressProvider {
}
};
- // Returns the mDNS responder that can be used to obfuscate the local IP
- // addresses of ICE host candidates by mDNS hostnames.
- virtual webrtc::MdnsResponderInterface* GetMdnsResponder() const;
+ // MdnsResponderProvider interface.
+ webrtc::MdnsResponderInterface* GetMdnsResponder() const override;
};
// Base class for NetworkManager implementations.
@@ -303,7 +315,11 @@ class Network {
default_local_address_provider_ = provider;
}
- // Returns the name of the interface this network is associated wtih.
+ void set_mdns_responder_provider(const MdnsResponderProvider* provider) {
+ mdns_responder_provider_ = provider;
+ }
+
+ // Returns the name of the interface this network is associated with.
const std::string& name() const { return name_; }
// Returns the OS-assigned name for this network. This is useful for
@@ -322,7 +338,7 @@ class Network {
// Returns the Network's current idea of the 'best' IP it has.
// Or return an unset IP if this network has no active addresses.
// Here is the rule on how we mark the IPv6 address as ignorable for WebRTC.
- // 1) return all global temporary dynamic and non-deprecrated ones.
+ // 1) return all global temporary dynamic and non-deprecated ones.
// 2) if #1 not available, return global ones.
// 3) if #2 not available, use ULA ipv6 as last resort. (ULA stands
// for unique local address, which is not route-able in open
@@ -354,19 +370,11 @@ class Network {
const std::vector<InterfaceAddress>& GetIPs() const { return ips_; }
// Clear the network's list of addresses.
void ClearIPs() { ips_.clear(); }
- // Sets the mDNS responder that can be used to obfuscate the local IP
+ // Returns the mDNS responder that can be used to obfuscate the local IP
// addresses of host candidates by mDNS names in ICE gathering. After a
// name-address mapping is created by the mDNS responder, queries for the
// created name will be resolved by the responder.
- //
- // The mDNS responder, if not null, should outlive this rtc::Network.
- void SetMdnsResponder(webrtc::MdnsResponderInterface* mdns_responder) {
- mdns_responder_ = mdns_responder;
- }
- // Returns the mDNS responder, which is null by default.
- webrtc::MdnsResponderInterface* GetMdnsResponder() const {
- return mdns_responder_;
- }
+ webrtc::MdnsResponderInterface* GetMdnsResponder() const;
// Returns the scope-id of the network's address.
// Should only be relevant for link-local IPv6 addresses.
@@ -433,13 +441,13 @@ class Network {
private:
const DefaultLocalAddressProvider* default_local_address_provider_ = nullptr;
+ const MdnsResponderProvider* mdns_responder_provider_ = nullptr;
std::string name_;
std::string description_;
IPAddress prefix_;
int prefix_length_;
std::string key_;
std::vector<InterfaceAddress> ips_;
- webrtc::MdnsResponderInterface* mdns_responder_ = nullptr;
int scope_id_;
bool ignored_;
AdapterType type_;
diff --git a/chromium/tools/binary_size/libsupersize/apkanalyzer.py b/chromium/tools/binary_size/libsupersize/apkanalyzer.py
index 3803adec966..259e95afa20 100644
--- a/chromium/tools/binary_size/libsupersize/apkanalyzer.py
+++ b/chromium/tools/binary_size/libsupersize/apkanalyzer.py
@@ -29,18 +29,10 @@ def _ParseJarInfoFile(file_name):
return source_map
-def _LoadSourceMap(apk_name, output_directory):
- apk_jar_info_name = apk_name + '.jar.info'
- jar_info_path = os.path.join(
- output_directory, 'size-info', apk_jar_info_name)
- return _ParseJarInfoFile(jar_info_path)
-
-
-def _RunApkAnalyzer(apk_path, output_directory):
+def _RunApkAnalyzer(apk_path, mapping_path, output_directory):
args = [path_util.GetApkAnalyzerPath(output_directory), 'dex', 'packages',
apk_path]
- mapping_path = apk_path + '.mapping'
- if os.path.exists(mapping_path):
+ if mapping_path and os.path.exists(mapping_path):
args.extend(['--proguard-mappings', mapping_path])
output = subprocess.check_output(args)
data = []
@@ -138,10 +130,13 @@ def UndoHierarchicalSizing(data):
return nodes
-def CreateDexSymbols(apk_path, output_directory):
- apk_name = os.path.basename(apk_path)
- source_map = _LoadSourceMap(apk_name, output_directory)
- nodes = UndoHierarchicalSizing(_RunApkAnalyzer(apk_path, output_directory))
+def CreateDexSymbols(apk_path, mapping_path, size_info_prefix,
+ output_directory):
+ source_map = _ParseJarInfoFile(size_info_prefix + '.jar.info')
+
+ nodes = _RunApkAnalyzer(apk_path, mapping_path, output_directory)
+ nodes = UndoHierarchicalSizing(nodes)
+
dex_expected_size = _ExpectedDexTotalSize(apk_path)
total_node_size = sum(map(lambda x: x[2], nodes))
# TODO(agrieve): Figure out why this log is triggering for
diff --git a/chromium/tools/binary_size/libsupersize/archive.py b/chromium/tools/binary_size/libsupersize/archive.py
index bf947922fd1..ef8a76fa85f 100644
--- a/chromium/tools/binary_size/libsupersize/archive.py
+++ b/chromium/tools/binary_size/libsupersize/archive.py
@@ -41,6 +41,7 @@ _OWNERS_FILENAME = 'OWNERS'
_COMPONENT_REGEX = re.compile(r'\s*#\s*COMPONENT\s*:\s*(\S+)')
_FILE_PATH_REGEX = re.compile(r'\s*file://(\S+)')
_UNCOMPRESSED_COMPRESSION_RATIO_THRESHOLD = 0.9
+_APKS_MAIN_APK = 'splits/base-master.apk'
# Holds computation state that is live only when an output directory exists.
_OutputDirectoryContext = collections.namedtuple('_OutputDirectoryContext', [
@@ -727,8 +728,24 @@ def LoadAndPostProcessSizeInfo(path, file_obj=None):
return size_info
-def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory,
- linker_name):
+def _CollectModuleSizes(minimal_apks_path):
+ sizes_by_module = collections.defaultdict(int)
+ with zipfile.ZipFile(minimal_apks_path) as z:
+ for info in z.infolist():
+ # E.g.:
+ # splits/base-master.apk
+ # splits/base-en.apk
+ # splits/vr-master.apk
+ # splits/vr-en.apk
+ # TODO(agrieve): Might be worth measuring a non-en locale as well.
+ m = re.match(r'splits/(.*)-master\.apk', info.filename)
+ if m:
+ sizes_by_module[m.group(1)] += info.file_size
+ return sizes_by_module
+
+
+def CreateMetadata(map_path, elf_path, apk_path, minimal_apks_path,
+ tool_prefix, output_directory, linker_name):
"""Creates metadata dict.
Args:
@@ -736,6 +753,7 @@ def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory,
elf_path: Path to the corresponding unstripped ELF file. Used to find symbol
aliases and inlined functions. Can be None.
apk_path: Path to the .apk file to measure.
+ minimal_apks_path: Path to the .minimal.apks file to measure.
tool_prefix: Prefix for c++filt & nm.
output_directory: Build output directory.
linker_name: A coded linker name (see linker_map_parser.py).
@@ -746,6 +764,7 @@ def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory,
If |elf_path| is supplied, git revision and elf info are included.
If |output_directory| is also supplied, then filenames will be included.
"""
+ assert not (apk_path and minimal_apks_path)
metadata = None
if elf_path:
logging.debug('Constructing metadata')
@@ -776,6 +795,15 @@ def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory,
if apk_path:
metadata[models.METADATA_APK_FILENAME] = relative_to_out(apk_path)
metadata[models.METADATA_APK_SIZE] = os.path.getsize(apk_path)
+ elif minimal_apks_path:
+ sizes_by_module = _CollectModuleSizes(minimal_apks_path)
+ metadata[models.METADATA_APK_FILENAME] = relative_to_out(
+ minimal_apks_path)
+ for name, size in sizes_by_module.iteritems():
+ key = models.METADATA_APK_SIZE
+ if name != 'base':
+ key += '-' + name
+ metadata[key] = size
return metadata
@@ -949,9 +977,9 @@ def _IsPakContentUncompressed(content):
class _ResourceSourceMapper(object):
- def __init__(self, apk_path, output_directory, knobs):
+ def __init__(self, size_info_prefix, knobs):
self._knobs = knobs
- self._res_info = self._LoadResInfo(apk_path, output_directory)
+ self._res_info = self._LoadResInfo(size_info_prefix)
self._pattern_dollar_underscore = re.compile(r'\$(.*?)__\d+')
self._pattern_version_suffix = re.compile(r'-v\d+/')
@@ -976,11 +1004,8 @@ class _ResourceSourceMapper(object):
res_info[dest] = actual_source
return res_info
- def _LoadResInfo(self, apk_path, output_directory):
- apk_name = os.path.basename(apk_path)
- apk_res_info_name = apk_name + '.res.info'
- apk_res_info_path = os.path.join(
- output_directory, 'size-info', apk_res_info_name)
+ def _LoadResInfo(self, size_info_prefix):
+ apk_res_info_path = size_info_prefix + '.res.info'
res_info_without_root = self._ParseResInfoFile(apk_res_info_path)
# We package resources in the res/ folder only in the apk.
res_info = {
@@ -1081,16 +1106,18 @@ def _ParseApkElfSectionSize(section_sizes, metadata, apk_elf_result):
return section_sizes, 0
-def _ParseDexSymbols(section_sizes, apk_path, output_directory):
- symbols = apkanalyzer.CreateDexSymbols(apk_path, output_directory)
+def _ParseDexSymbols(section_sizes, apk_path, mapping_path, size_info_prefix,
+ output_directory):
+ symbols = apkanalyzer.CreateDexSymbols(
+ apk_path, mapping_path, size_info_prefix, output_directory)
prev = section_sizes.setdefault(models.SECTION_DEX, 0)
section_sizes[models.SECTION_DEX] = prev + sum(s.size for s in symbols)
return symbols
def _ParseApkOtherSymbols(section_sizes, apk_path, apk_so_path,
- output_directory, knobs):
- res_source_mapper = _ResourceSourceMapper(apk_path, output_directory, knobs)
+ size_info_prefix, knobs):
+ res_source_mapper = _ResourceSourceMapper(size_info_prefix, knobs)
apk_symbols = []
zip_info_total = 0
with zipfile.ZipFile(apk_path) as z:
@@ -1133,11 +1160,10 @@ def _CreatePakObjectMap(object_paths_by_name):
return object_paths_by_pak_id
-def _FindPakSymbolsFromApk(apk_path, output_directory, knobs):
+def _FindPakSymbolsFromApk(apk_path, size_info_prefix, knobs):
with zipfile.ZipFile(apk_path) as z:
pak_zip_infos = (f for f in z.infolist() if f.filename.endswith('.pak'))
- apk_info_name = os.path.basename(apk_path) + '.pak.info'
- pak_info_path = os.path.join(output_directory, 'size-info', apk_info_name)
+ pak_info_path = size_info_prefix + '.pak.info'
res_info = _ParsePakInfoFile(pak_info_path)
symbols_by_id = {}
total_compressed_size = 0
@@ -1189,9 +1215,9 @@ def _CalculateElfOverhead(section_sizes, elf_path):
def CreateSectionSizesAndSymbols(
map_path=None, tool_prefix=None, output_directory=None, elf_path=None,
- apk_path=None, track_string_literals=True, metadata=None,
- apk_so_path=None, pak_files=None, pak_info_file=None, linker_name=None,
- knobs=SectionSizeKnobs()):
+ apk_path=None, mapping_path=None, track_string_literals=True,
+ metadata=None, apk_so_path=None, pak_files=None, pak_info_file=None,
+ linker_name=None, size_info_prefix=None, knobs=SectionSizeKnobs()):
"""Creates sections sizes and symbols for a SizeInfo.
Args:
@@ -1209,6 +1235,7 @@ def CreateSectionSizesAndSymbols(
pak_files: List of paths to .pak files.
pak_info_file: Path to a .pak.info file.
linker_name: A coded linker name (see linker_map_parser.py).
+ size_info_prefix: Path to $out/size-info/$ApkName.
knobs: Instance of SectionSizeKnobs with tunable knobs and options.
Returns:
@@ -1261,17 +1288,21 @@ def CreateSectionSizesAndSymbols(
elf_overhead_size = _CalculateElfOverhead(section_sizes, elf_path)
pak_symbols_by_id = None
- if apk_path:
+ if apk_path and size_info_prefix:
pak_symbols_by_id = _FindPakSymbolsFromApk(
- apk_path, output_directory, knobs)
+ apk_path, size_info_prefix, knobs)
if elf_path:
section_sizes, elf_overhead_size = _ParseApkElfSectionSize(
section_sizes, metadata, apk_elf_result)
raw_symbols.extend(
- _ParseDexSymbols(section_sizes, apk_path, output_directory))
+ _ParseDexSymbols(section_sizes,
+ apk_path,
+ mapping_path,
+ size_info_prefix,
+ output_directory))
raw_symbols.extend(
_ParseApkOtherSymbols(section_sizes, apk_path, apk_so_path,
- output_directory, knobs))
+ size_info_prefix, knobs))
elif pak_files and pak_info_file:
pak_symbols_by_id = _FindPakSymbolsFromFiles(
pak_files, pak_info_file, output_directory)
@@ -1408,34 +1439,35 @@ def _ElfInfoFromApk(apk_path, apk_so_path, tool_prefix):
def _AutoIdentifyInputFile(args):
- file_output = subprocess.check_output(['file', args.f])
- format_text = file_output[file_output.find(': ') + 2:]
- # File-not-found -> 'cannot ...' and directory -> 'directory', which don't
- # match anything here, so they are handled by the final 'return False'.
- if (format_text.startswith('Java archive data') or
- format_text.startswith('Zip archive data')):
- logging.info('Auto-identified --apk-file.')
+ if args.f.endswith('.minimal.apks'):
+ args.minimal_apks_file = args.f
+ logging.info('Auto-identified --minimal-apks-file.')
+ elif args.f.endswith('.apk'):
args.apk_file = args.f
- return True
- if format_text.startswith('ELF '):
+ logging.info('Auto-identified --apk-file.')
+ elif args.f.endswith('.so') or '.' not in args.f:
logging.info('Auto-identified --elf-file.')
args.elf_file = args.f
- return True
- if format_text.startswith('ASCII text'):
+ elif args.f.endswith('.map') or args.f.endswith('.map.gz'):
logging.info('Auto-identified --map-file.')
args.map_file = args.f
- return True
- return False
+ else:
+ return False
+ return True
def AddMainPathsArguments(parser):
- """Add arguments for DeduceMainPaths()."""
+ """Add arguments for _DeduceMainPaths()."""
parser.add_argument('-f', metavar='FILE',
help='Auto-identify input file type.')
parser.add_argument('--apk-file',
- help='.apk file to measure. When set, --elf-file will be '
- 'derived (if unset). Providing the .apk allows '
- 'for the size of packed relocations to be recorded')
+ help='.apk file to measure. Other flags can generally be '
+ 'derived when this is used.')
+ parser.add_argument('--minimal-apks-file',
+ help='.minimal.apks file to measure. Other flags can '
+ 'generally be derived when this is used.')
+ parser.add_argument('--mapping-file',
+ help='Proguard .mapping file for deobfuscation.')
parser.add_argument('--elf-file',
help='Path to input ELF file. Currently used for '
'capturing metadata.')
@@ -1468,22 +1500,27 @@ def AddArguments(parser):
AddMainPathsArguments(parser)
-def DeduceMainPaths(args, parser):
+def _DeduceMainPaths(args, parser, extracted_minimal_apk_path=None):
"""Computes main paths based on input, and deduces them if needed."""
- if args.f is not None:
- if not _AutoIdentifyInputFile(args):
- parser.error('Cannot find or identify file %s' % args.f)
-
- apk_path = args.apk_file
elf_path = args.elf_file
map_path = args.map_file
- any_input = apk_path or elf_path or map_path
+ any_input = args.apk_file or args.minimal_apks_file or elf_path or map_path
if not any_input:
- parser.error('Must pass at least one of --apk-file, --elf-file, --map-file')
+ parser.error('Must pass at least one of --apk-file, --minimal-apks-file, '
+ '--elf-file, --map-file')
output_directory_finder = path_util.OutputDirectoryFinder(
value=args.output_directory,
any_path_within_output_directory=any_input)
+ aab_or_apk = args.apk_file or args.minimal_apks_file
+ mapping_path = args.mapping_file
+ if aab_or_apk:
+ aab_or_apk = aab_or_apk.replace('.minimal.apks', '.aab')
+ if not mapping_path:
+ mapping_path = aab_or_apk + '.mapping'
+ logging.debug('Detected --mapping-file=%s', mapping_path)
+
+ apk_path = extracted_minimal_apk_path or args.apk_file
apk_so_path = None
if apk_path:
with zipfile.ZipFile(apk_path) as z:
@@ -1522,18 +1559,49 @@ def DeduceMainPaths(args, parser):
output_directory = None
if not args.no_source_paths:
output_directory = output_directory_finder.Finalized()
- return (output_directory, tool_prefix, apk_path, apk_so_path, elf_path,
- map_path, linker_name)
+
+ size_info_prefix = None
+ if output_directory and aab_or_apk:
+ size_info_prefix = os.path.join(
+ output_directory, 'size-info', os.path.basename(aab_or_apk))
+
+ return (output_directory, tool_prefix, apk_path, mapping_path, apk_so_path,
+ elf_path, map_path, linker_name, size_info_prefix)
def Run(args, parser):
if not args.size_file.endswith('.size'):
parser.error('size_file must end with .size')
- (output_directory, tool_prefix, apk_path, apk_so_path, elf_path, map_path,
- linker_name) = (DeduceMainPaths(args, parser))
+ if args.f is not None:
+ if not _AutoIdentifyInputFile(args):
+ parser.error('Cannot identify file %s' % args.f)
+ if args.apk_file and args.minimal_apks_file:
+ parser.error('Cannot use both --apk-file and --minimal-apks-file.')
+
+ if args.minimal_apks_file:
+ # Can't use NamedTemporaryFile() because it uses atexit, which does
+ # not play nice with fork().
+ fd, extracted_minimal_apk_path = tempfile.mkstemp(suffix='.apk')
+ try:
+ logging.debug('Extracting %s', _APKS_MAIN_APK)
+ with zipfile.ZipFile(args.minimal_apks_file) as z:
+ os.write(fd, z.read(_APKS_MAIN_APK))
+ os.close(fd)
+ _RunInternal(args, parser, extracted_minimal_apk_path)
+ finally:
+ os.unlink(extracted_minimal_apk_path)
+ else:
+ _RunInternal(args, parser, None)
+
+
+def _RunInternal(args, parser, extracted_minimal_apk_path):
+ (output_directory, tool_prefix, apk_path, mapping_path, apk_so_path, elf_path,
+ map_path, linker_name, size_info_prefix) = _DeduceMainPaths(
+ args, parser, extracted_minimal_apk_path)
- metadata = CreateMetadata(map_path, elf_path, apk_path, tool_prefix,
+ metadata = CreateMetadata(map_path, elf_path, args.apk_file,
+ args.minimal_apks_file, tool_prefix,
output_directory, linker_name)
knobs = SectionSizeKnobs()
@@ -1542,11 +1610,12 @@ def Run(args, parser):
section_sizes, raw_symbols = CreateSectionSizesAndSymbols(
map_path=map_path, tool_prefix=tool_prefix, elf_path=elf_path,
- apk_path=apk_path, output_directory=output_directory,
+ apk_path=apk_path, mapping_path=mapping_path,
+ output_directory=output_directory,
track_string_literals=args.track_string_literals,
metadata=metadata, apk_so_path=apk_so_path,
pak_files=args.pak_file, pak_info_file=args.pak_info_file,
- linker_name=linker_name, knobs=knobs)
+ linker_name=linker_name, size_info_prefix=size_info_prefix, knobs=knobs)
size_info = CreateSizeInfo(
section_sizes, raw_symbols, metadata=metadata, normalize_names=False)
diff --git a/chromium/tools/binary_size/libsupersize/integration_test.py b/chromium/tools/binary_size/libsupersize/integration_test.py
index edaf2895edd..65c07929cb6 100755
--- a/chromium/tools/binary_size/libsupersize/integration_test.py
+++ b/chromium/tools/binary_size/libsupersize/integration_test.py
@@ -42,6 +42,7 @@ _TEST_APK_PAK_PATH = os.path.join(_TEST_APK_ROOT_DIR, 'assets/resources.pak')
# The following files are dynamically created.
_TEST_ELF_PATH = os.path.join(_TEST_OUTPUT_DIR, 'elf')
_TEST_APK_PATH = os.path.join(_TEST_OUTPUT_DIR, 'test.apk')
+_TEST_MINIMAL_APKS_PATH = os.path.join(_TEST_OUTPUT_DIR, 'Bundle.minimal.apks')
# Generated file paths relative to apk
_TEST_APK_SO_PATH = 'test.so'
@@ -121,6 +122,7 @@ class IntegrationTest(unittest.TestCase):
# Exactly 128MB of data (2^27), extra bytes will be accounted in overhead.
with open(_TEST_ELF_PATH, 'a') as elf_file:
elf_file.write(IntegrationTest._CreateBlankData(27))
+
with zipfile.ZipFile(_TEST_APK_PATH, 'w') as apk_file:
apk_file.write(_TEST_ELF_PATH, _TEST_APK_SO_PATH)
# Exactly 4MB of data (2^22).
@@ -141,18 +143,27 @@ class IntegrationTest(unittest.TestCase):
apk_file.writestr(
_TEST_APK_DEX_PATH, IntegrationTest._CreateBlankData(23))
+ with zipfile.ZipFile(_TEST_MINIMAL_APKS_PATH, 'w') as apk_file:
+ apk_file.write(_TEST_APK_PATH, 'splits/base-master.apk')
+ apk_file.writestr('splits/base-en.apk', 'x' * 10)
+ apk_file.writestr('splits/vr-master.apk', 'x' * 20)
+ apk_file.writestr('splits/vr-en.apk', 'x' * 40)
+ apk_file.writestr('toc.pb', 'x' * 80)
+
@classmethod
def tearDownClass(cls):
IntegrationTest._SafeRemoveFiles([
_TEST_ELF_PATH,
_TEST_APK_PATH,
+ _TEST_MINIMAL_APKS_PATH,
])
def _CloneSizeInfo(self, use_output_directory=True, use_elf=True,
- use_apk=False, use_pak=False):
+ use_apk=False, use_minimal_apks=False, use_pak=False):
assert not use_elf or use_output_directory
assert not (use_apk and use_pak)
- cache_key = (use_output_directory, use_elf, use_apk, use_pak)
+ cache_key = (
+ use_output_directory, use_elf, use_apk, use_minimal_apks, use_pak)
if cache_key not in IntegrationTest.cached_size_info:
elf_path = _TEST_ELF_PATH if use_elf else None
output_directory = _TEST_OUTPUT_DIR if use_output_directory else None
@@ -162,10 +173,24 @@ class IntegrationTest(unittest.TestCase):
knobs.max_same_name_alias_count = 3
knobs.src_root = _TEST_SOURCE_DIR
apk_path = None
+ minimal_apks_path = None
apk_so_path = None
+ size_info_prefix = None
+ extracted_minimal_apk_path = None
if use_apk:
apk_path = _TEST_APK_PATH
+ elif use_minimal_apks:
+ minimal_apks_path = _TEST_MINIMAL_APKS_PATH
+ extracted_minimal_apk_path = _TEST_APK_PATH
+ if use_apk or use_minimal_apks:
apk_so_path = _TEST_APK_SO_PATH
+ if output_directory:
+ if use_apk:
+ orig_path = _TEST_APK_PATH
+ else:
+ orig_path = _TEST_MINIMAL_APKS_PATH.replace('.minimal.apks', '.aab')
+ size_info_prefix = os.path.join(
+ output_directory, 'size-info', os.path.basename(orig_path))
pak_files = None
pak_info_file = None
if use_pak:
@@ -176,20 +201,22 @@ class IntegrationTest(unittest.TestCase):
if use_elf:
with _AddMocksToPath():
metadata = archive.CreateMetadata(
- _TEST_MAP_PATH, elf_path, apk_path, _TEST_TOOL_PREFIX,
- output_directory, linker_name)
+ _TEST_MAP_PATH, elf_path, apk_path, minimal_apks_path,
+ _TEST_TOOL_PREFIX, output_directory, linker_name)
section_sizes, raw_symbols = archive.CreateSectionSizesAndSymbols(
map_path=_TEST_MAP_PATH, tool_prefix=_TEST_TOOL_PREFIX,
elf_path=elf_path, output_directory=output_directory,
- apk_path=apk_path, apk_so_path=apk_so_path, metadata=metadata,
- pak_files=pak_files, pak_info_file=pak_info_file,
- linker_name=linker_name, knobs=knobs)
+ apk_path=apk_path or extracted_minimal_apk_path,
+ apk_so_path=apk_so_path, metadata=metadata, pak_files=pak_files,
+ pak_info_file=pak_info_file, linker_name=linker_name,
+ size_info_prefix=size_info_prefix, knobs=knobs)
IntegrationTest.cached_size_info[cache_key] = archive.CreateSizeInfo(
section_sizes, raw_symbols, metadata=metadata)
return copy.deepcopy(IntegrationTest.cached_size_info[cache_key])
def _DoArchive(self, archive_path, use_output_directory=True, use_elf=True,
- use_apk=False, use_pak=False, debug_measures=False):
+ use_apk=False, use_minimal_apks=False, use_pak=False,
+ debug_measures=False):
args = [
archive_path,
'--map-file', _TEST_MAP_PATH,
@@ -201,10 +228,15 @@ class IntegrationTest(unittest.TestCase):
args += ['--output-directory', _TEST_OUTPUT_DIR]
else:
args += ['--no-source-paths']
- if use_elf:
- args += ['--elf-file', _TEST_ELF_PATH]
if use_apk:
- args += ['--apk-file', _TEST_APK_PATH]
+ args += ['-f', _TEST_APK_PATH]
+ elif use_minimal_apks:
+ args += ['-f', _TEST_MINIMAL_APKS_PATH]
+ if use_elf:
+ if use_apk or use_minimal_apks:
+ args += ['--elf-file', _TEST_ELF_PATH]
+ else:
+ args += ['-f', _TEST_ELF_PATH]
if use_pak:
args += ['--pak-file', _TEST_APK_LOCALE_PAK_PATH,
'--pak-file', _TEST_APK_PAK_PATH,
@@ -212,17 +244,18 @@ class IntegrationTest(unittest.TestCase):
_RunApp('archive', args, debug_measures=debug_measures)
def _DoArchiveTest(self, use_output_directory=True, use_elf=True,
- use_apk=False, use_pak=False, debug_measures=False):
+ use_apk=False, use_minimal_apks=False, use_pak=False,
+ debug_measures=False):
with tempfile.NamedTemporaryFile(suffix='.size') as temp_file:
self._DoArchive(
temp_file.name, use_output_directory=use_output_directory,
- use_elf=use_elf, use_apk=use_apk, use_pak=use_pak,
- debug_measures=debug_measures)
+ use_elf=use_elf, use_apk=use_apk, use_minimal_apks=use_minimal_apks,
+ use_pak=use_pak, debug_measures=debug_measures)
size_info = archive.LoadAndPostProcessSizeInfo(temp_file.name)
# Check that saving & loading is the same as directly parsing.
expected_size_info = self._CloneSizeInfo(
use_output_directory=use_output_directory, use_elf=use_elf,
- use_apk=use_apk, use_pak=use_pak)
+ use_apk=use_apk, use_minimal_apks=use_minimal_apks, use_pak=use_pak)
self.assertEquals(expected_size_info.metadata, size_info.metadata)
# Don't cluster.
expected_size_info.symbols = expected_size_info.raw_symbols
@@ -256,6 +289,10 @@ class IntegrationTest(unittest.TestCase):
return self._DoArchiveTest(use_apk=True)
@_CompareWithGolden()
+ def test_Archive_MinimalApks(self):
+ return self._DoArchiveTest(use_minimal_apks=True)
+
+ @_CompareWithGolden()
def test_Archive_Pak_Files(self):
return self._DoArchiveTest(use_pak=True)
diff --git a/chromium/tools/cfi/blacklist.txt b/chromium/tools/cfi/blacklist.txt
index 643bb198835..aca6c88a658 100644
--- a/chromium/tools/cfi/blacklist.txt
+++ b/chromium/tools/cfi/blacklist.txt
@@ -137,6 +137,11 @@ fun:*BrokerProcessDispatcher*
# Blacklist base::Callback due to https://crbug.com/845855
fun:*FunctorTraits*
+# PipeWire due to https://crbug.com/926115
+src:*/include/spa/*
+src:*third_party/webrtc/modules/desktop_capture/linux/pipewire_stubs.cc
+src:*third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc
+
# Calls to auto-generated stubs by generate_stubs.py
src:*audio/pulse/pulse_stubs.cc
src:*media/gpu/vaapi/va_stubs.cc
diff --git a/chromium/tools/gn/README.md b/chromium/tools/gn/README.chromium.md
index b9da9f3d3d0..b9da9f3d3d0 100644
--- a/chromium/tools/gn/README.md
+++ b/chromium/tools/gn/README.chromium.md
diff --git a/chromium/tools/gn/bootstrap/bootstrap.py b/chromium/tools/gn/bootstrap/bootstrap.py
index 1945852c419..f12a63b9ddb 100755
--- a/chromium/tools/gn/bootstrap/bootstrap.py
+++ b/chromium/tools/gn/bootstrap/bootstrap.py
@@ -52,6 +52,11 @@ def main(argv):
action='store_true',
help='Do not run GN after building it. Causes --gn-gen-args '
'to have no effect.')
+ parser.add_option(
+ '--use-custom-libcxx',
+ action='store_true',
+ help='Build with in-tree libc++. This may be necessary if the system '
+ 'libstdc++ does not support C++14 features.')
options, args = parser.parse_args(argv)
if args:
parser.error('Unrecognized command line arguments: %s.' % ', '.join(args))
@@ -66,6 +71,41 @@ def main(argv):
gn_path = options.output or os.path.join(out_dir, 'gn')
gn_build_dir = os.path.join(out_dir, 'gn_build')
+ # TODO(thomasanderson): Remove this once Ubuntu Trusty reaches EOL, or when
+ # Chromium's infrastructure is upgraded from Trusty to Xenial, whichever comes
+ # second ideally. This can be done by reverting this CL:
+ # https://chromium-review.googlesource.com/c/chromium/src/+/1460187/
+ if options.use_custom_libcxx:
+ libcxx_dir = os.path.join(gn_build_dir, 'libc++')
+ if not os.path.exists(libcxx_dir):
+ os.makedirs(libcxx_dir)
+ shutil.copy2(
+ os.path.join(BOOTSTRAP_DIR, 'libc++.ninja'),
+ os.path.join(libcxx_dir, 'build.ninja'))
+ with open(os.path.join(libcxx_dir, 'toolchain.ninja'), 'w') as f:
+ f.write('\n'.join([
+ 'cxx = ' + os.environ.get('CXX', 'clang++'),
+ 'ar = ' + os.environ.get('AR', 'ar'),
+ 'cxxflags = ' + ' '.join(
+ os.environ.get('CFLAGS', '').split() +
+ os.environ.get('CXXFLAGS', '').split()),
+ ]) + '\n')
+ subprocess.check_call(['ninja', '-C', libcxx_dir])
+ shutil.copy2(os.path.join(gn_build_dir, 'libc++.gn.so'), out_dir)
+
+ def append_to_env(var, vals):
+ os.putenv(var, os.environ.get(var, '') + ' ' + ' '.join(vals))
+
+ append_to_env('LDFLAGS', [
+ '-nodefaultlibs', 'libc++.gn.so', '-lc', '-lm',
+ '-Wl,-rpath="\$$ORIGIN/."', '-Wl,-rpath-link=.'
+ ])
+ append_to_env('CXXFLAGS', [
+ '-nostdinc++',
+ ' -isystem../../../buildtools/third_party/libc++/trunk/include',
+ '-isystem../../../buildtools/third_party/libc++abi/trunk/include'
+ ])
+
cmd = [
sys.executable,
os.path.join(GN_ROOT, 'build', 'gen.py'),
diff --git a/chromium/tools/gn/bootstrap/libc++.ninja b/chromium/tools/gn/bootstrap/libc++.ninja
new file mode 100644
index 00000000000..a22d0ded115
--- /dev/null
+++ b/chromium/tools/gn/bootstrap/libc++.ninja
@@ -0,0 +1,71 @@
+include toolchain.ninja
+
+buildtools = ../../../../buildtools
+libcxx = third_party/libc++/trunk/src
+libcxxabi = third_party/libc++abi/trunk/src
+
+defines = -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FILE_OFFSET_BITS=64
+includes = -isystem$buildtools/$libcxx/../include -isystem$buildtools/$libcxxabi/../include
+cflags = $cxxflags $defines $includes -O2 -g0 -pthread -pipe -fno-exceptions -std=c++14 -Wno-c++11-narrowing -nostdinc++ -fPIC
+
+rule cxx_libcxx
+ command = $cxx $cflags -D_LIBCPP_NO_EXCEPTIONS -D_LIBCPP_BUILDING_LIBRARY -DLIBCXX_BUILDING_LIBCXXABI -c $in -o $out
+ description = CXX $out
+
+rule cxx_libcxxabi
+ command = $cxx $cflags -D_LIBCXXABI_NO_EXCEPTIONS -DLIBCXXABI_SILENT_TERMINATE -c $in -o $out
+ description = CXX $out
+
+rule link
+ command = $cxx -shared -fPIC -o $out -Wl,--start-group $in -Wl,--end-group
+ description = LINK $out
+
+build $libcxx/algorithm.o: cxx_libcxx $buildtools/$libcxx/algorithm.cpp
+build $libcxx/any.o: cxx_libcxx $buildtools/$libcxx/any.cpp
+build $libcxx/bind.o: cxx_libcxx $buildtools/$libcxx/bind.cpp
+build $libcxx/chrono.o: cxx_libcxx $buildtools/$libcxx/chrono.cpp
+build $libcxx/condition_variable.o: cxx_libcxx $buildtools/$libcxx/condition_variable.cpp
+build $libcxx/debug.o: cxx_libcxx $buildtools/$libcxx/debug.cpp
+build $libcxx/exception.o: cxx_libcxx $buildtools/$libcxx/exception.cpp
+build $libcxx/functional.o: cxx_libcxx $buildtools/$libcxx/functional.cpp
+build $libcxx/future.o: cxx_libcxx $buildtools/$libcxx/future.cpp
+build $libcxx/hash.o: cxx_libcxx $buildtools/$libcxx/hash.cpp
+build $libcxx/ios.o: cxx_libcxx $buildtools/$libcxx/ios.cpp
+build $libcxx/iostream.o: cxx_libcxx $buildtools/$libcxx/iostream.cpp
+build $libcxx/locale.o: cxx_libcxx $buildtools/$libcxx/locale.cpp
+build $libcxx/memory.o: cxx_libcxx $buildtools/$libcxx/memory.cpp
+build $libcxx/mutex.o: cxx_libcxx $buildtools/$libcxx/mutex.cpp
+build $libcxx/new.o: cxx_libcxx $buildtools/$libcxx/new.cpp
+build $libcxx/optional.o: cxx_libcxx $buildtools/$libcxx/optional.cpp
+build $libcxx/random.o: cxx_libcxx $buildtools/$libcxx/random.cpp
+build $libcxx/regex.o: cxx_libcxx $buildtools/$libcxx/regex.cpp
+build $libcxx/shared_mutex.o: cxx_libcxx $buildtools/$libcxx/shared_mutex.cpp
+build $libcxx/stdexcept.o: cxx_libcxx $buildtools/$libcxx/stdexcept.cpp
+build $libcxx/string.o: cxx_libcxx $buildtools/$libcxx/string.cpp
+build $libcxx/strstream.o: cxx_libcxx $buildtools/$libcxx/strstream.cpp
+build $libcxx/system_error.o: cxx_libcxx $buildtools/$libcxx/system_error.cpp
+build $libcxx/thread.o: cxx_libcxx $buildtools/$libcxx/thread.cpp
+build $libcxx/typeinfo.o: cxx_libcxx $buildtools/$libcxx/typeinfo.cpp
+build $libcxx/utility.o: cxx_libcxx $buildtools/$libcxx/utility.cpp
+build $libcxx/valarray.o: cxx_libcxx $buildtools/$libcxx/valarray.cpp
+build $libcxx/variant.o: cxx_libcxx $buildtools/$libcxx/variant.cpp
+build $libcxx/vector.o: cxx_libcxx $buildtools/$libcxx/vector.cpp
+
+build $libcxxabi/abort_message.o: cxx_libcxxabi $buildtools/$libcxxabi/abort_message.cpp
+build $libcxxabi/cxa_aux_runtime.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_aux_runtime.cpp
+build $libcxxabi/cxa_default_handlers.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_default_handlers.cpp
+build $libcxxabi/cxa_demangle.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_demangle.cpp
+build $libcxxabi/cxa_exception_storage.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_exception_storage.cpp
+build $libcxxabi/cxa_guard.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_guard.cpp
+build $libcxxabi/cxa_handlers.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_handlers.cpp
+build $libcxxabi/cxa_noexception.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_noexception.cpp
+build $libcxxabi/cxa_unexpected.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_unexpected.cpp
+build $libcxxabi/cxa_vector.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_vector.cpp
+build $libcxxabi/cxa_virtual.o: cxx_libcxxabi $buildtools/$libcxxabi/cxa_virtual.cpp
+build $libcxxabi/fallback_malloc.o: cxx_libcxxabi $buildtools/$libcxxabi/fallback_malloc.cpp
+build $libcxxabi/private_typeinfo.o: cxx_libcxxabi $buildtools/$libcxxabi/private_typeinfo.cpp
+build $libcxxabi/stdlib_exception.o: cxx_libcxxabi $buildtools/$libcxxabi/stdlib_exception.cpp
+build $libcxxabi/stdlib_stdexcept.o: cxx_libcxxabi $buildtools/$libcxxabi/stdlib_stdexcept.cpp
+build $libcxxabi/stdlib_typeinfo.o: cxx_libcxxabi $buildtools/$libcxxabi/stdlib_typeinfo.cpp
+
+build ../libc++.gn.so: link $libcxx/algorithm.o $libcxx/any.o $libcxx/bind.o $libcxx/chrono.o $libcxx/condition_variable.o $libcxx/debug.o $libcxx/exception.o $libcxx/functional.o $libcxx/future.o $libcxx/hash.o $libcxx/ios.o $libcxx/iostream.o $libcxx/locale.o $libcxx/memory.o $libcxx/mutex.o $libcxx/new.o $libcxx/optional.o $libcxx/random.o $libcxx/regex.o $libcxx/shared_mutex.o $libcxx/stdexcept.o $libcxx/string.o $libcxx/strstream.o $libcxx/system_error.o $libcxx/thread.o $libcxx/typeinfo.o $libcxx/utility.o $libcxx/valarray.o $libcxx/variant.o $libcxx/vector.o $libcxxabi/abort_message.o $libcxxabi/cxa_aux_runtime.o $libcxxabi/cxa_default_handlers.o $libcxxabi/cxa_demangle.o $libcxxabi/cxa_exception_storage.o $libcxxabi/cxa_guard.o $libcxxabi/cxa_handlers.o $libcxxabi/cxa_noexception.o $libcxxabi/cxa_unexpected.o $libcxxabi/cxa_vector.o $libcxxabi/cxa_virtual.o $libcxxabi/fallback_malloc.o $libcxxabi/private_typeinfo.o $libcxxabi/stdlib_exception.o $libcxxabi/stdlib_stdexcept.o $libcxxabi/stdlib_typeinfo.o
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/DEPS b/chromium/tools/ipc_fuzzer/fuzzer/DEPS
deleted file mode 100644
index 48e88750d4a..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/DEPS
+++ /dev/null
@@ -1,2 +0,0 @@
-include_rules = [
-]
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc
deleted file mode 100644
index 76d8c6f21e7..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc
+++ /dev/null
@@ -1,1749 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <iostream>
-#include <set>
-#include <string>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory_handle.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "base/unguessable_token.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_utils.h"
-#include "ipc/ipc_sync_channel.h"
-#include "ipc/ipc_sync_message.h"
-#include "tools/ipc_fuzzer/fuzzer/fuzzer.h"
-#include "tools/ipc_fuzzer/fuzzer/rand_util.h"
-#include "tools/ipc_fuzzer/message_lib/message_cracker.h"
-#include "tools/ipc_fuzzer/message_lib/message_file.h"
-
-#if defined(OS_POSIX)
-#include <unistd.h>
-#endif
-
-// First include of all message files to provide basic types.
-#include "tools/ipc_fuzzer/message_lib/all_messages.h"
-#include "tools/ipc_fuzzer/message_lib/all_message_null_macros.h"
-
-namespace IPC {
-class Message;
-} // namespace IPC
-
-namespace {
-// For breaking deep recursion.
-int g_depth = 0;
-} // namespace
-
-namespace ipc_fuzzer {
-
-FuzzerFunctionVector g_function_vector;
-
-bool Fuzzer::ShouldGenerate() {
- return false;
-}
-
-// Partially-specialized class that knows how to handle a given type.
-template <class P>
-struct FuzzTraits {
- static bool Fuzz(P* p, Fuzzer *fuzzer) {
- // This is the catch-all for types we don't have enough information
- // to generate.
- std::cerr << "Can't handle " << PRETTY_FUNCTION << "\n";
- return false;
- }
-};
-
-// Template function to invoke partially-specialized class method.
-template <class P>
-static bool FuzzParam(P* p, Fuzzer* fuzzer) {
- return FuzzTraits<P>::Fuzz(p, fuzzer);
-}
-
-template <class P>
-static bool FuzzParamArray(P* p, size_t length, Fuzzer* fuzzer) {
- for (size_t i = 0; i < length; i++, p++) {
- if (!FuzzTraits<P>::Fuzz(p, fuzzer))
- return false;
- }
- return true;
-}
-
-// Specializations to generate primitive types.
-template <>
-struct FuzzTraits<bool> {
- static bool Fuzz(bool* p, Fuzzer* fuzzer) {
- fuzzer->FuzzBool(p);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<int> {
- static bool Fuzz(int* p, Fuzzer* fuzzer) {
- fuzzer->FuzzInt(p);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<unsigned int> {
- static bool Fuzz(unsigned int* p, Fuzzer* fuzzer) {
- fuzzer->FuzzInt(reinterpret_cast<int*>(p));
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<long> {
- static bool Fuzz(long* p, Fuzzer* fuzzer) {
- fuzzer->FuzzLong(p);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<unsigned long> {
- static bool Fuzz(unsigned long* p, Fuzzer* fuzzer) {
- fuzzer->FuzzLong(reinterpret_cast<long*>(p));
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<long long> {
- static bool Fuzz(long long* p, Fuzzer* fuzzer) {
- fuzzer->FuzzInt64(reinterpret_cast<int64_t*>(p));
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<unsigned long long> {
- static bool Fuzz(unsigned long long* p, Fuzzer* fuzzer) {
- fuzzer->FuzzInt64(reinterpret_cast<int64_t*>(p));
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<short> {
- static bool Fuzz(short* p, Fuzzer* fuzzer) {
- fuzzer->FuzzUInt16(reinterpret_cast<uint16_t*>(p));
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<unsigned short> {
- static bool Fuzz(unsigned short* p, Fuzzer* fuzzer) {
- fuzzer->FuzzUInt16(reinterpret_cast<uint16_t*>(p));
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<signed char> {
- static bool Fuzz(signed char* p, Fuzzer* fuzzer) {
- fuzzer->FuzzUChar(reinterpret_cast<unsigned char*>(p));
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<unsigned char> {
- static bool Fuzz(unsigned char* p, Fuzzer* fuzzer) {
- fuzzer->FuzzUChar(p);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<wchar_t> {
- static bool Fuzz(wchar_t* p, Fuzzer* fuzzer) {
- fuzzer->FuzzWChar(p);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<float> {
- static bool Fuzz(float* p, Fuzzer* fuzzer) {
- fuzzer->FuzzFloat(p);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<double> {
- static bool Fuzz(double* p, Fuzzer* fuzzer) {
- fuzzer->FuzzDouble(p);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<std::string> {
- static bool Fuzz(std::string* p, Fuzzer* fuzzer) {
- fuzzer->FuzzString(p);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::string16> {
- static bool Fuzz(base::string16* p, Fuzzer* fuzzer) {
- fuzzer->FuzzString16(p);
- return true;
- }
-};
-
-// Specializations for tuples.
-template <>
-struct FuzzTraits<std::tuple<>> {
- static bool Fuzz(std::tuple<>* p, Fuzzer* fuzzer) { return true; }
-};
-
-template <class A>
-struct FuzzTraits<std::tuple<A>> {
- static bool Fuzz(std::tuple<A>* p, Fuzzer* fuzzer) {
- return FuzzParam(&std::get<0>(*p), fuzzer);
- }
-};
-
-template <class A, class B>
-struct FuzzTraits<std::tuple<A, B>> {
- static bool Fuzz(std::tuple<A, B>* p, Fuzzer* fuzzer) {
- return FuzzParam(&std::get<0>(*p), fuzzer) &&
- FuzzParam(&std::get<1>(*p), fuzzer);
- }
-};
-
-template <class A, class B, class C>
-struct FuzzTraits<std::tuple<A, B, C>> {
- static bool Fuzz(std::tuple<A, B, C>* p, Fuzzer* fuzzer) {
- return FuzzParam(&std::get<0>(*p), fuzzer) &&
- FuzzParam(&std::get<1>(*p), fuzzer) &&
- FuzzParam(&std::get<2>(*p), fuzzer);
- }
-};
-
-template <class A, class B, class C, class D>
-struct FuzzTraits<std::tuple<A, B, C, D>> {
- static bool Fuzz(std::tuple<A, B, C, D>* p, Fuzzer* fuzzer) {
- return FuzzParam(&std::get<0>(*p), fuzzer) &&
- FuzzParam(&std::get<1>(*p), fuzzer) &&
- FuzzParam(&std::get<2>(*p), fuzzer) &&
- FuzzParam(&std::get<3>(*p), fuzzer);
- }
-};
-
-template <class A, class B, class C, class D, class E>
-struct FuzzTraits<std::tuple<A, B, C, D, E>> {
- static bool Fuzz(std::tuple<A, B, C, D, E>* p, Fuzzer* fuzzer) {
- return FuzzParam(&std::get<0>(*p), fuzzer) &&
- FuzzParam(&std::get<1>(*p), fuzzer) &&
- FuzzParam(&std::get<2>(*p), fuzzer) &&
- FuzzParam(&std::get<3>(*p), fuzzer) &&
- FuzzParam(&std::get<4>(*p), fuzzer);
- }
-};
-
-// Specializations for containers.
-template <class A>
-struct FuzzTraits<std::vector<A> > {
- static bool Fuzz(std::vector<A>* p, Fuzzer* fuzzer) {
- ++g_depth;
- size_t count = p->size();
- if (fuzzer->ShouldGenerate()) {
- count = g_depth > 3 ? 0 : RandElementCount();
- p->resize(count);
- }
- for (size_t i = 0; i < count; ++i) {
- if (!FuzzParam(&p->at(i), fuzzer)) {
- --g_depth;
- return false;
- }
- }
- --g_depth;
- return true;
- }
-};
-
-template <class A>
-struct FuzzTraits<std::set<A> > {
- static bool Fuzz(std::set<A>* p, Fuzzer* fuzzer) {
- if (!fuzzer->ShouldGenerate()) {
- std::set<A> result;
- typename std::set<A>::iterator it;
- for (it = p->begin(); it != p->end(); ++it) {
- A item = *it;
- if (!FuzzParam(&item, fuzzer))
- return false;
- result.insert(item);
- }
- *p = result;
- return true;
- }
-
- static int g_depth = 0;
- size_t count = ++g_depth > 3 ? 0 : RandElementCount();
- A a;
- for (size_t i = 0; i < count; ++i) {
- if (!FuzzParam(&a, fuzzer)) {
- --g_depth;
- return false;
- }
- p->insert(a);
- }
- --g_depth;
- return true;
- }
-};
-
-template <class A, class B>
-struct FuzzTraits<std::map<A, B> > {
- static bool Fuzz(std::map<A, B>* p, Fuzzer* fuzzer) {
- if (!fuzzer->ShouldGenerate()) {
- typename std::map<A, B>::iterator it;
- for (it = p->begin(); it != p->end(); ++it) {
- if (!FuzzParam(&it->second, fuzzer))
- return false;
- }
- return true;
- }
-
- static int g_depth = 0;
- size_t count = ++g_depth > 3 ? 0 : RandElementCount();
- std::pair<A, B> place_holder;
- for (size_t i = 0; i < count; ++i) {
- if (!FuzzParam(&place_holder, fuzzer)) {
- --g_depth;
- return false;
- }
- p->insert(place_holder);
- }
- --g_depth;
- return true;
- }
-};
-
-template <class A, class B, class C, class D>
-struct FuzzTraits<std::map<A, B, C, D>> {
- static bool Fuzz(std::map<A, B, C, D>* p, Fuzzer* fuzzer) {
- if (!fuzzer->ShouldGenerate()) {
- typename std::map<A, B, C, D>::iterator it;
- for (it = p->begin(); it != p->end(); ++it) {
- if (!FuzzParam(&it->second, fuzzer))
- return false;
- }
- return true;
- }
-
- static int g_depth = 0;
- size_t count = ++g_depth > 3 ? 0 : RandElementCount();
- std::pair<A, B> place_holder;
- for (size_t i = 0; i < count; ++i) {
- if (!FuzzParam(&place_holder, fuzzer)) {
- --g_depth;
- return false;
- }
- p->insert(place_holder);
- }
- --g_depth;
- return true;
- }
-};
-
-template <class A, class B>
-struct FuzzTraits<std::pair<A, B> > {
- static bool Fuzz(std::pair<A, B>* p, Fuzzer* fuzzer) {
- return
- FuzzParam(&p->first, fuzzer) &&
- FuzzParam(&p->second, fuzzer);
- }
-};
-
-// Specializations for hand-coded types.
-
-template <>
-struct FuzzTraits<base::FilePath> {
- static bool Fuzz(base::FilePath* p, Fuzzer* fuzzer) {
- if (!fuzzer->ShouldGenerate()) {
- base::FilePath::StringType path = p->value();
- if(!FuzzParam(&path, fuzzer))
- return false;
- *p = base::FilePath(path);
- return true;
- }
-
- const char path_chars[] = "ACz0/.~:";
- size_t count = RandInRange(60);
- base::FilePath::StringType random_path;
- for (size_t i = 0; i < count; ++i)
- random_path += path_chars[RandInRange(sizeof(path_chars) - 1)];
- *p = base::FilePath(random_path);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::File::Error> {
- static bool Fuzz(base::File::Error* p, Fuzzer* fuzzer) {
- int value = static_cast<int>(*p);
- if (!FuzzParam(&value, fuzzer))
- return false;
- *p = static_cast<base::File::Error>(value);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::File::Info> {
- static bool Fuzz(base::File::Info* p, Fuzzer* fuzzer) {
- double last_modified = p->last_modified.ToDoubleT();
- double last_accessed = p->last_accessed.ToDoubleT();
- double creation_time = p->creation_time.ToDoubleT();
- if (!FuzzParam(&p->size, fuzzer))
- return false;
- if (!FuzzParam(&p->is_directory, fuzzer))
- return false;
- if (!FuzzParam(&last_modified, fuzzer))
- return false;
- if (!FuzzParam(&last_accessed, fuzzer))
- return false;
- if (!FuzzParam(&creation_time, fuzzer))
- return false;
- p->last_modified = base::Time::FromDoubleT(last_modified);
- p->last_accessed = base::Time::FromDoubleT(last_accessed);
- p->creation_time = base::Time::FromDoubleT(creation_time);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::NullableString16> {
- static bool Fuzz(base::NullableString16* p, Fuzzer* fuzzer) {
- base::string16 string = p->string();
- bool is_null = p->is_null();
- if (!FuzzParam(&string, fuzzer))
- return false;
- if (!FuzzParam(&is_null, fuzzer))
- return false;
- *p = base::NullableString16(string, is_null);
- return true;
- }
-};
-
-#if defined(OS_WIN) || defined(OS_MACOSX)
-template <>
-struct FuzzTraits<base::SharedMemoryHandle> {
- static bool Fuzz(base::SharedMemoryHandle* p, Fuzzer* fuzzer) {
- // This generates an invalid SharedMemoryHandle. Generating a valid
- // SharedMemoryHandle requires setting/knowing state in both the sending and
- // receiving process, which is not currently possible.
- return true;
- }
-};
-#endif // defined(OS_WIN) || defined(OS_MACOSX)
-
-template <>
-struct FuzzTraits<base::Time> {
- static bool Fuzz(base::Time* p, Fuzzer* fuzzer) {
- int64_t internal_value = p->ToInternalValue();
- if (!FuzzParam(&internal_value, fuzzer))
- return false;
- *p = base::Time::FromInternalValue(internal_value);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::TimeDelta> {
- static bool Fuzz(base::TimeDelta* p, Fuzzer* fuzzer) {
- int64_t internal_value = p->ToInternalValue();
- if (!FuzzParam(&internal_value, fuzzer))
- return false;
- *p = base::TimeDelta::FromInternalValue(internal_value);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::TimeTicks> {
- static bool Fuzz(base::TimeTicks* p, Fuzzer* fuzzer) {
- int64_t internal_value = p->ToInternalValue();
- if (!FuzzParam(&internal_value, fuzzer))
- return false;
- *p = base::TimeTicks::FromInternalValue(internal_value);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::ListValue> {
- static bool Fuzz(base::ListValue* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- ++g_depth;
- size_t list_length = p->GetSize();
- if (fuzzer->ShouldGenerate())
- list_length = g_depth > 3 ? 0 : RandInRange(8);
- for (size_t index = 0; index < list_length; ++index) {
- switch (static_cast<base::Value::Type>(RandInRange(8))) {
- case base::Value::Type::BOOLEAN: {
- bool tmp;
- p->GetBoolean(index, &tmp);
- fuzzer->FuzzBool(&tmp);
- p->Set(index, std::make_unique<base::Value>(tmp));
- break;
- }
- case base::Value::Type::INTEGER: {
- int tmp;
- p->GetInteger(index, &tmp);
- fuzzer->FuzzInt(&tmp);
- p->Set(index, std::make_unique<base::Value>(tmp));
- break;
- }
- case base::Value::Type::DOUBLE: {
- double tmp;
- p->GetDouble(index, &tmp);
- fuzzer->FuzzDouble(&tmp);
- p->Set(index, std::make_unique<base::Value>(tmp));
- break;
- }
- case base::Value::Type::STRING: {
- std::string tmp;
- p->GetString(index, &tmp);
- fuzzer->FuzzString(&tmp);
- p->Set(index, std::make_unique<base::Value>(tmp));
- break;
- }
- case base::Value::Type::BINARY: {
- char tmp[200];
- size_t bin_length = RandInRange(sizeof(tmp));
- fuzzer->FuzzData(tmp, bin_length);
- p->Set(index, base::Value::CreateWithCopiedBuffer(tmp, bin_length));
- break;
- }
- case base::Value::Type::DICTIONARY: {
- base::DictionaryValue* dict_weak = nullptr;
- if (p->GetDictionary(index, &dict_weak)) {
- FuzzParam(dict_weak, fuzzer);
- } else {
- auto dict = std::make_unique<base::DictionaryValue>();
- FuzzParam(dict.get(), fuzzer);
- p->Set(index, std::move(dict));
- }
- break;
- }
- case base::Value::Type::LIST: {
- base::ListValue* list_weak = nullptr;
- if (p->GetList(index, &list_weak)) {
- FuzzParam(list_weak, fuzzer);
- } else {
- auto list = std::make_unique<base::ListValue>();
- FuzzParam(list.get(), fuzzer);
- p->Set(index, std::move(list));
- }
- break;
- }
- case base::Value::Type::NONE:
- default:
- break;
- }
- }
- --g_depth;
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::DictionaryValue> {
- static bool Fuzz(base::DictionaryValue* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- ++g_depth;
- size_t dict_length = g_depth > 3 ? 0 : RandInRange(8);
- for (size_t index = 0; index < dict_length; ++index) {
- std::string property;
- fuzzer->FuzzString(&property);
- switch (static_cast<base::Value::Type>(RandInRange(8))) {
- case base::Value::Type::BOOLEAN: {
- bool tmp;
- fuzzer->FuzzBool(&tmp);
- p->SetKey(property, base::Value(tmp));
- break;
- }
- case base::Value::Type::INTEGER: {
- int tmp;
- fuzzer->FuzzInt(&tmp);
- p->SetKey(property, base::Value(tmp));
- break;
- }
- case base::Value::Type::DOUBLE: {
- double tmp;
- fuzzer->FuzzDouble(&tmp);
- p->SetKey(property, base::Value(tmp));
- break;
- }
- case base::Value::Type::STRING: {
- std::string tmp;
- fuzzer->FuzzString(&tmp);
- p->SetKey(property, base::Value(tmp));
- break;
- }
- case base::Value::Type::BINARY: {
- char tmp[200];
- size_t bin_length = RandInRange(sizeof(tmp));
- fuzzer->FuzzData(tmp, bin_length);
- p->SetWithoutPathExpansion(
- property, base::Value::CreateWithCopiedBuffer(tmp, bin_length));
- break;
- }
- case base::Value::Type::DICTIONARY: {
- auto tmp = std::make_unique<base::DictionaryValue>();
- FuzzParam(tmp.get(), fuzzer);
- p->SetWithoutPathExpansion(property, std::move(tmp));
- break;
- }
- case base::Value::Type::LIST: {
- auto tmp = std::make_unique<base::ListValue>();
- FuzzParam(tmp.get(), fuzzer);
- p->SetWithoutPathExpansion(property, std::move(tmp));
- break;
- }
- case base::Value::Type::NONE:
- default:
- break;
- }
- }
- --g_depth;
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<base::UnguessableToken> {
- static bool Fuzz(base::UnguessableToken* p, Fuzzer* fuzzer) {
- auto low = p->GetLowForSerialization();
- auto high = p->GetHighForSerialization();
- if (!FuzzParam(&low, fuzzer))
- return false;
- if (!FuzzParam(&high, fuzzer))
- return false;
- *p = base::UnguessableToken::Deserialize(high, low);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<viz::CompositorFrame> {
- static bool Fuzz(viz::CompositorFrame* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- if (!FuzzParam(&p->metadata, fuzzer))
- return false;
-
- switch (RandInRange(2)) {
- case 0: {
- if (!FuzzParam(&p->resource_list, fuzzer))
- return false;
- if (!FuzzParam(&p->render_pass_list, fuzzer))
- return false;
- return true;
- }
- default:
- // Fuzz nothing to handle the no frame case.
- return true;
- }
- }
-};
-
-template <class A>
-struct FuzzTraits<cc::ListContainer<A>> {
- static bool Fuzz(cc::ListContainer<A>* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<viz::QuadList> {
- static bool Fuzz(viz::QuadList* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<viz::RenderPass> {
- static bool Fuzz(viz::RenderPass* p, Fuzzer* fuzzer) {
- if (!FuzzParam(&p->id, fuzzer))
- return false;
- if (!FuzzParam(&p->output_rect, fuzzer))
- return false;
- if (!FuzzParam(&p->damage_rect, fuzzer))
- return false;
- if (!FuzzParam(&p->transform_to_root_target, fuzzer))
- return false;
- if (!FuzzParam(&p->has_transparent_background, fuzzer))
- return false;
- if (!FuzzParam(&p->quad_list, fuzzer))
- return false;
- if (!FuzzParam(&p->shared_quad_state_list, fuzzer))
- return false;
- // Omitting |copy_requests| as it is not sent over IPC.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<viz::RenderPassList> {
- static bool Fuzz(viz::RenderPassList* p, Fuzzer* fuzzer) {
- if (!fuzzer->ShouldGenerate()) {
- for (size_t i = 0; i < p->size(); ++i) {
- if (!FuzzParam(p->at(i).get(), fuzzer))
- return false;
- }
- return true;
- }
-
- size_t count = RandElementCount();
- for (size_t i = 0; i < count; ++i) {
- std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
- if (!FuzzParam(render_pass.get(), fuzzer))
- return false;
- p->push_back(std::move(render_pass));
- }
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<content::PageState> {
- static bool Fuzz(content::PageState* p, Fuzzer* fuzzer) {
- std::string data = p->ToEncodedData();
- if (!FuzzParam(&data, fuzzer))
- return false;
- *p = content::PageState::CreateFromEncodedData(data);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<content::WebCursor> {
- static bool Fuzz(content::WebCursor* p, Fuzzer* fuzzer) {
- content::CursorInfo info;
- p->GetCursorInfo(&info);
-
- // |type| enum is not validated on de-serialization, so pick random value.
- if (!FuzzParam(reinterpret_cast<int*>(&info.type), fuzzer))
- return false;
- if (!FuzzParam(&info.hotspot, fuzzer))
- return false;
- if (!FuzzParam(&info.image_scale_factor, fuzzer))
- return false;
- if (!FuzzParam(&info.custom_image, fuzzer))
- return false;
- // Omitting |externalHandle| since it is not serialized.
-
- // Scale factor is expected to be greater than 0, otherwise we hit
- // a check failure.
- info.image_scale_factor = fabs(info.image_scale_factor);
- if (!(info.image_scale_factor > 0.0))
- info.image_scale_factor = 1;
-
- *p = content::WebCursor();
- p->InitFromCursorInfo(info);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ContentSettingsPattern> {
- static bool Fuzz(ContentSettingsPattern* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): This can crash if a pattern is generated from a random
- // string. We could carefully generate a pattern or fix pattern generation.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ExtensionMsg_PermissionSetStruct> {
- static bool Fuzz(ExtensionMsg_PermissionSetStruct* p,
- Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<extensions::URLPatternSet> {
- static bool Fuzz(extensions::URLPatternSet* p, Fuzzer* fuzzer) {
- std::set<URLPattern> patterns = p->patterns();
- if (!FuzzParam(&patterns, fuzzer))
- return false;
- *p = extensions::URLPatternSet(patterns);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::Point> {
- static bool Fuzz(gfx::Point* p, Fuzzer* fuzzer) {
- int x = p->x();
- int y = p->y();
- if (!FuzzParam(&x, fuzzer))
- return false;
- if (!FuzzParam(&y, fuzzer))
- return false;
- p->SetPoint(x, y);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::PointF> {
- static bool Fuzz(gfx::PointF* p, Fuzzer* fuzzer) {
- float x = p->x();
- float y = p->y();
- if (!FuzzParam(&x, fuzzer))
- return false;
- if (!FuzzParam(&y, fuzzer))
- return false;
- p->SetPoint(x, y);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::Rect> {
- static bool Fuzz(gfx::Rect* p, Fuzzer* fuzzer) {
- gfx::Point origin = p->origin();
- gfx::Size size = p->size();
- if (!FuzzParam(&origin, fuzzer))
- return false;
- if (!FuzzParam(&size, fuzzer))
- return false;
- p->set_origin(origin);
- p->set_size(size);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::RectF> {
- static bool Fuzz(gfx::RectF* p, Fuzzer* fuzzer) {
- gfx::PointF origin = p->origin();
- gfx::SizeF size = p->size();
- if (!FuzzParam(&origin, fuzzer))
- return false;
- if (!FuzzParam(&size, fuzzer))
- return false;
- p->set_origin(origin);
- p->set_size(size);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::Range> {
- static bool Fuzz(gfx::Range* p, Fuzzer* fuzzer) {
- size_t start = p->start();
- size_t end = p->end();
- if (!FuzzParam(&start, fuzzer))
- return false;
- if (!FuzzParam(&end, fuzzer))
- return false;
- *p = gfx::Range(start, end);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::Size> {
- static bool Fuzz(gfx::Size* p, Fuzzer* fuzzer) {
- int width = p->width();
- int height = p->height();
- if (!FuzzParam(&width, fuzzer))
- return false;
- if (!FuzzParam(&height, fuzzer))
- return false;
- p->SetSize(width, height);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::SizeF> {
- static bool Fuzz(gfx::SizeF* p, Fuzzer* fuzzer) {
- float w;
- float h;
- if (!FuzzParam(&w, fuzzer))
- return false;
- if (!FuzzParam(&h, fuzzer))
- return false;
- p->SetSize(w, h);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::Transform> {
- static bool Fuzz(gfx::Transform* p, Fuzzer* fuzzer) {
- SkMScalar matrix[16];
- for (size_t i = 0; i < base::size(matrix); i++) {
- matrix[i] = p->matrix().get(i / 4, i % 4);
- }
- if (!FuzzParamArray(&matrix[0], base::size(matrix), fuzzer))
- return false;
- *p = gfx::Transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4],
- matrix[5], matrix[6], matrix[7], matrix[8], matrix[9],
- matrix[10], matrix[11], matrix[12], matrix[13],
- matrix[14], matrix[15]);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::Vector2d> {
- static bool Fuzz(gfx::Vector2d* p, Fuzzer* fuzzer) {
- int x = p->x();
- int y = p->y();
- if (!FuzzParam(&x, fuzzer))
- return false;
- if (!FuzzParam(&y, fuzzer))
- return false;
- *p = gfx::Vector2d(x, y);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gfx::Vector2dF> {
- static bool Fuzz(gfx::Vector2dF* p, Fuzzer* fuzzer) {
- float x = p->x();
- float y = p->y();
- if (!FuzzParam(&x, fuzzer))
- return false;
- if (!FuzzParam(&y, fuzzer))
- return false;
- *p = gfx::Vector2dF(x, y);
- return true;
- }
-};
-
-template <typename TypeMarker, typename WrappedType, WrappedType kInvalidValue>
-struct FuzzTraits<gpu::IdType<TypeMarker, WrappedType, kInvalidValue>> {
- using param_type = gpu::IdType<TypeMarker, WrappedType, kInvalidValue>;
- static bool Fuzz(param_type* id, Fuzzer* fuzzer) {
- WrappedType raw_value = id->GetUnsafeValue();
- if (!FuzzParam(&raw_value, fuzzer))
- return false;
- *id = param_type::FromUnsafeValue(raw_value);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gpu::Mailbox> {
- static bool Fuzz(gpu::Mailbox* p, Fuzzer* fuzzer) {
- fuzzer->FuzzBytes(p->name, sizeof(p->name));
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gpu::SyncToken> {
- static bool Fuzz(gpu::SyncToken* p, Fuzzer* fuzzer) {
- bool verified_flush = false;
- gpu::CommandBufferNamespace namespace_id =
- gpu::CommandBufferNamespace::INVALID;
- gpu::CommandBufferId command_buffer_id;
- uint64_t release_count = 0;
-
- if (!FuzzParam(&verified_flush, fuzzer))
- return false;
- if (!FuzzParam(&namespace_id, fuzzer))
- return false;
- if (!FuzzParam(&command_buffer_id, fuzzer))
- return false;
- if (!FuzzParam(&release_count, fuzzer))
- return false;
-
- p->Clear();
- p->Set(namespace_id, command_buffer_id, release_count);
- if (verified_flush)
- p->SetVerifyFlush();
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<gpu::MailboxHolder> {
- static bool Fuzz(gpu::MailboxHolder* p, Fuzzer* fuzzer) {
- if (!FuzzParam(&p->mailbox, fuzzer))
- return false;
- if (!FuzzParam(&p->sync_token, fuzzer))
- return false;
- if (!FuzzParam(&p->texture_target, fuzzer))
- return false;
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<GURL> {
- static bool Fuzz(GURL* p, Fuzzer* fuzzer) {
- if (!fuzzer->ShouldGenerate()) {
- std::string spec = p->possibly_invalid_spec();
- if (!FuzzParam(&spec, fuzzer))
- return false;
- if (spec != p->possibly_invalid_spec())
- *p = GURL(spec);
- return true;
- }
-
- const char url_chars[] = "Ahtp0:/.?+\\%&#";
- size_t count = RandInRange(100);
- std::string random_url;
- for (size_t i = 0; i < count; ++i)
- random_url += url_chars[RandInRange(sizeof(url_chars) - 1)];
- int selector = RandInRange(10);
- if (selector == 0)
- random_url = std::string("http://") + random_url;
- else if (selector == 1)
- random_url = std::string("file://") + random_url;
- else if (selector == 2)
- random_url = std::string("javascript:") + random_url;
- else if (selector == 2)
- random_url = std::string("data:") + random_url;
- *p = GURL(random_url);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<HostID> {
- static bool Fuzz(HostID* p, Fuzzer* fuzzer) {
- HostID::HostType type = p->type();
- std::string id = p->id();
- if (!FuzzParam(&type, fuzzer))
- return false;
- if (!FuzzParam(&id, fuzzer))
- return false;
- *p = HostID(type, id);
- return true;
- }
-};
-
-#if defined(OS_WIN)
-template <>
-struct FuzzTraits<HWND> {
- static bool Fuzz(HWND* p, Fuzzer* fuzzer) {
- // TODO(aarya): This should actually do something.
- return true;
- }
-};
-#endif
-
-template <>
-struct FuzzTraits<std::unique_ptr<IPC::Message>> {
- static bool Fuzz(std::unique_ptr<IPC::Message>* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- if (g_function_vector.empty())
- return false;
- size_t index = RandInRange(g_function_vector.size());
- std::unique_ptr<IPC::Message> ipc_message =
- (*g_function_vector[index])(nullptr, fuzzer);
- if (!ipc_message)
- return false;
- *p = std::move(ipc_message);
- return true;
- }
-};
-
-#if !defined(OS_WIN)
-// PlatformfileForTransit is just SharedMemoryHandle on Windows, which already
-// has a trait, see ipc/ipc_platform_file.h
-template <>
-struct FuzzTraits<IPC::PlatformFileForTransit> {
- static bool Fuzz(IPC::PlatformFileForTransit* p, Fuzzer* fuzzer) {
- // TODO(inferno): I don't think we can generate real ones due to check on
- // construct.
- return true;
- }
-};
-#endif
-
-template <>
-struct FuzzTraits<IPC::ChannelHandle> {
- static bool Fuzz(IPC::ChannelHandle* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- return FuzzParam(&p->mojo_handle, fuzzer);
- }
-};
-
-#if defined(OS_WIN)
-template <>
-struct FuzzTraits<LOGFONT> {
- static bool Fuzz(LOGFONT* p, Fuzzer* fuzzer) {
- // TODO(aarya): This should actually do something.
- return true;
- }
-};
-#endif
-
-template <>
-struct FuzzTraits<media::AudioParameters> {
- static bool Fuzz(media::AudioParameters* p, Fuzzer* fuzzer) {
- int channel_layout = p->channel_layout();
- int format = p->format();
- int sample_rate = p->sample_rate();
- int frames_per_buffer = p->frames_per_buffer();
- int channels = p->channels();
- int effects = p->effects();
- // TODO(mbarbella): Support ChannelLayout mutation and invalid values.
- if (fuzzer->ShouldGenerate()) {
- channel_layout =
- RandInRange(media::ChannelLayout::CHANNEL_LAYOUT_MAX + 1);
- }
- if (!FuzzParam(&format, fuzzer))
- return false;
- if (!FuzzParam(&sample_rate, fuzzer))
- return false;
- if (!FuzzParam(&frames_per_buffer, fuzzer))
- return false;
- if (!FuzzParam(&channels, fuzzer))
- return false;
- if (!FuzzParam(&effects, fuzzer))
- return false;
- media::AudioParameters params(
- static_cast<media::AudioParameters::Format>(format),
- static_cast<media::ChannelLayout>(channel_layout), sample_rate,
- frames_per_buffer);
- params.set_channels_for_discrete(channels);
- params.set_effects(effects);
- *p = params;
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<media::cast::RtpTimeTicks> {
- static bool Fuzz(media::cast::RtpTimeTicks* p, Fuzzer* fuzzer) {
- base::TimeDelta delta;
- int base;
- if (!FuzzParam(&delta, fuzzer))
- return false;
- if (!FuzzParam(&base, fuzzer))
- return false;
- *p = media::cast::RtpTimeTicks::FromTimeDelta(delta, base);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<net::LoadTimingInfo> {
- static bool Fuzz(net::LoadTimingInfo* p, Fuzzer* fuzzer) {
- return FuzzParam(&p->socket_log_id, fuzzer) &&
- FuzzParam(&p->socket_reused, fuzzer) &&
- FuzzParam(&p->request_start_time, fuzzer) &&
- FuzzParam(&p->request_start, fuzzer) &&
- FuzzParam(&p->proxy_resolve_start, fuzzer) &&
- FuzzParam(&p->proxy_resolve_end, fuzzer) &&
- FuzzParam(&p->connect_timing.dns_start, fuzzer) &&
- FuzzParam(&p->connect_timing.dns_end, fuzzer) &&
- FuzzParam(&p->connect_timing.connect_start, fuzzer) &&
- FuzzParam(&p->connect_timing.connect_end, fuzzer) &&
- FuzzParam(&p->connect_timing.ssl_start, fuzzer) &&
- FuzzParam(&p->connect_timing.ssl_end, fuzzer) &&
- FuzzParam(&p->send_start, fuzzer) &&
- FuzzParam(&p->send_end, fuzzer) &&
- FuzzParam(&p->receive_headers_end, fuzzer);
- }
-};
-
-template <>
-struct FuzzTraits<net::HostPortPair> {
- static bool Fuzz(net::HostPortPair* p, Fuzzer* fuzzer) {
- std::string host = p->host();
- uint16_t port = p->port();
- if (!FuzzParam(&host, fuzzer))
- return false;
- if (!FuzzParam(&port, fuzzer))
- return false;
- p->set_host(host);
- p->set_port(port);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<net::IPAddress> {
- static bool Fuzz(net::IPAddress* p, Fuzzer* fuzzer) {
- std::vector<uint8_t> bytes = p->CopyBytesToVector();
- if (!FuzzParam(&bytes, fuzzer))
- return false;
- net::IPAddress ip_address(bytes.data(), bytes.size());
- *p = ip_address;
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<net::IPEndPoint> {
- static bool Fuzz(net::IPEndPoint* p, Fuzzer* fuzzer) {
- net::IPAddress ip_address = p->address();
- int port = p->port();
- if (!FuzzParam(&ip_address, fuzzer))
- return false;
- if (!FuzzParam(&port, fuzzer))
- return false;
- net::IPEndPoint ip_endpoint(ip_address, port);
- *p = ip_endpoint;
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<network_hints::LookupRequest> {
- static bool Fuzz(network_hints::LookupRequest* p, Fuzzer* fuzzer) {
- if (!FuzzParam(&p->hostname_list, fuzzer))
- return false;
- return true;
- }
-};
-
-// PP_ traits.
-template <>
-struct FuzzTraits<PP_Bool> {
- static bool Fuzz(PP_Bool* p, Fuzzer* fuzzer) {
- bool tmp = PP_ToBool(*p);
- if (!FuzzParam(&tmp, fuzzer))
- return false;
- *p = PP_FromBool(tmp);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<PP_NetAddress_Private> {
- static bool Fuzz(PP_NetAddress_Private* p, Fuzzer* fuzzer) {
- p->size = RandInRange(sizeof(p->data) + 1);
- fuzzer->FuzzBytes(&p->data, p->size);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::PPB_X509Certificate_Fields> {
- static bool Fuzz(ppapi::PPB_X509Certificate_Fields* p,
- Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params> {
- static bool Fuzz(ppapi::proxy::PPBFlash_DrawGlyphs_Params* p,
- Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::proxy::ResourceMessageCallParams> {
- static bool Fuzz(
- ppapi::proxy::ResourceMessageCallParams* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- PP_Resource resource;
- int32_t sequence;
- bool has_callback;
- if (!FuzzParam(&resource, fuzzer))
- return false;
- if (!FuzzParam(&sequence, fuzzer))
- return false;
- if (!FuzzParam(&has_callback, fuzzer))
- return false;
- *p = ppapi::proxy::ResourceMessageCallParams(resource, sequence);
- if (has_callback)
- p->set_has_callback();
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::proxy::ResourceMessageReplyParams> {
- static bool Fuzz(
- ppapi::proxy::ResourceMessageReplyParams* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- PP_Resource resource;
- int32_t sequence;
- int32_t result;
- if (!FuzzParam(&resource, fuzzer))
- return false;
- if (!FuzzParam(&sequence, fuzzer))
- return false;
- if (!FuzzParam(&result, fuzzer))
- return false;
- *p = ppapi::proxy::ResourceMessageReplyParams(resource, sequence);
- p->set_result(result);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::proxy::SerializedHandle> {
- static bool Fuzz(ppapi::proxy::SerializedHandle* p,
- Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::proxy::SerializedFontDescription> {
- static bool Fuzz(ppapi::proxy::SerializedFontDescription* p,
- Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::proxy::SerializedTrueTypeFontDesc> {
- static bool Fuzz(ppapi::proxy::SerializedTrueTypeFontDesc* p,
- Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::proxy::SerializedVar> {
- static bool Fuzz(ppapi::proxy::SerializedVar* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::HostResource> {
- static bool Fuzz(ppapi::HostResource* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- PP_Instance instance;
- PP_Resource resource;
- if (!FuzzParam(&instance, fuzzer))
- return false;
- if (!FuzzParam(&resource, fuzzer))
- return false;
- p->SetHostResource(instance, resource);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::PepperFilePath> {
- static bool Fuzz(ppapi::PepperFilePath *p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- unsigned domain = RandInRange(ppapi::PepperFilePath::DOMAIN_MAX_VALID+1);
- base::FilePath path;
- if (!FuzzParam(&path, fuzzer))
- return false;
- *p = ppapi::PepperFilePath(
- static_cast<ppapi::PepperFilePath::Domain>(domain), path);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::PpapiPermissions> {
- static bool Fuzz(ppapi::PpapiPermissions* p, Fuzzer* fuzzer) {
- uint32_t bits = p->GetBits();
- if (!FuzzParam(&bits, fuzzer))
- return false;
- *p = ppapi::PpapiPermissions(bits);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<ppapi::SocketOptionData> {
- static bool Fuzz(ppapi::SocketOptionData* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): This can be improved.
- int32_t tmp;
- p->GetInt32(&tmp);
- if (!FuzzParam(&tmp, fuzzer))
- return false;
- p->SetInt32(tmp);
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<SkBitmap> {
- static bool Fuzz(SkBitmap* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): This should actually do something.
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<network::DataElement> {
- static bool Fuzz(network::DataElement* p, Fuzzer* fuzzer) {
- // TODO(mbarbella): Support mutation.
- if (!fuzzer->ShouldGenerate())
- return true;
-
- switch (RandInRange(3)) {
- case 0: {
- // network::DataElement::Type::TYPE_BYTES
- if (RandEvent(2)) {
- p->SetToEmptyBytes();
- } else {
- char data[256];
- int data_len = RandInRange(sizeof(data));
- fuzzer->FuzzBytes(&data[0], data_len);
- p->SetToBytes(&data[0], data_len);
- }
- return true;
- }
- case 1: {
- // network::DataElement::Type::TYPE_FILE
- base::FilePath path;
- uint64_t offset;
- uint64_t length;
- base::Time modification_time;
- if (!FuzzParam(&path, fuzzer))
- return false;
- if (!FuzzParam(&offset, fuzzer))
- return false;
- if (!FuzzParam(&length, fuzzer))
- return false;
- if (!FuzzParam(&modification_time, fuzzer))
- return false;
- p->SetToFilePathRange(path, offset, length, modification_time);
- return true;
- }
- case 2: {
- // network::DataElement::Type::TYPE_BLOB
- std::string uuid;
- uint64_t offset;
- uint64_t length;
- if (!FuzzParam(&uuid, fuzzer))
- return false;
- if (!FuzzParam(&offset, fuzzer))
- return false;
- if (!FuzzParam(&length, fuzzer))
- return false;
- p->SetToBlobRange(uuid, offset, length);
- return true;
- }
- default: {
- NOTREACHED();
- return false;
- }
- }
- }
-};
-
-template <>
-struct FuzzTraits<ui::LatencyInfo> {
- static bool Fuzz(ui::LatencyInfo* p, Fuzzer* fuzzer) {
- // TODO(inferno): Add param traits for |latency_components|.
- int64_t trace_id = p->trace_id();
- bool terminated = p->terminated();
- if (!FuzzParam(&trace_id, fuzzer))
- return false;
- if (!FuzzParam(&terminated, fuzzer))
- return false;
-
- ui::LatencyInfo latency(trace_id, terminated);
- *p = latency;
-
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<url::Origin> {
- static bool Fuzz(url::Origin* p, Fuzzer* fuzzer) {
- bool opaque = p->opaque();
- if (!FuzzParam(&opaque, fuzzer))
- return false;
- std::string scheme = p->GetTupleOrPrecursorTupleIfOpaque().scheme();
- std::string host = p->GetTupleOrPrecursorTupleIfOpaque().host();
- uint16_t port = p->GetTupleOrPrecursorTupleIfOpaque().port();
- if (!FuzzParam(&scheme, fuzzer))
- return false;
- if (!FuzzParam(&host, fuzzer))
- return false;
- if (!FuzzParam(&port, fuzzer))
- return false;
-
- base::Optional<url::Origin> origin;
- if (!opaque) {
- origin = url::Origin::UnsafelyCreateTupleOriginWithoutNormalization(
- scheme, host, port);
- } else {
- base::Optional<base::UnguessableToken> token =
- p->GetNonceForSerialization();
- if (!token)
- token = base::UnguessableToken::Deserialize(RandU64(), RandU64());
- if (!FuzzParam(&(*token), fuzzer))
- return false;
- origin = url::Origin::UnsafelyCreateOpaqueOriginWithoutNormalization(
- scheme, host, port, url::Origin::Nonce(*token));
- }
-
- if (!origin) {
- // This means that we produced non-canonical values that were rejected by
- // UnsafelyCreate. Which is nice, except, those are arguably interesting
- // values to be sending over the wire sometimes, to make sure they're
- // rejected at the receiving end.
- //
- // We could potentially call CreateFromNormalizedTuple here to force their
- // creation, except that could lead to invariant violations within the
- // url::Origin we construct -- and potentially crash the fuzzer. What to
- // do?
- return false;
- }
-
- *p = std::move(origin).value();
- return true;
- }
-};
-
-template <>
-struct FuzzTraits<URLPattern> {
- static bool Fuzz(URLPattern* p, Fuzzer* fuzzer) {
- int valid_schemes = p->valid_schemes();
- std::string host = p->host();
- std::string port = p->port();
- std::string path = p->path();
- if (!FuzzParam(&valid_schemes, fuzzer))
- return false;
- if (!FuzzParam(&host, fuzzer))
- return false;
- if (!FuzzParam(&port, fuzzer))
- return false;
- if (!FuzzParam(&path, fuzzer))
- return false;
- *p = URLPattern(valid_schemes);
- p->SetHost(host);
- p->SetPort(port);
- p->SetPath(path);
- return true;
- }
-};
-
-// Redefine macros to generate generating from traits declarations.
-// STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
-#undef IPC_STRUCT_BEGIN
-#undef IPC_STRUCT_BEGIN_WITH_PARENT
-#undef IPC_STRUCT_MEMBER
-#undef IPC_STRUCT_END
-#define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
- IPC_STRUCT_BEGIN(struct_name)
-#define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
-#define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name)
-#define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
-
-// Set up so next include will generate generate trait classes.
-#undef IPC_STRUCT_TRAITS_BEGIN
-#undef IPC_STRUCT_TRAITS_MEMBER
-#undef IPC_STRUCT_TRAITS_PARENT
-#undef IPC_STRUCT_TRAITS_END
-#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
- template <> \
- struct FuzzTraits<struct_name> { \
- static bool Fuzz(struct_name *p, Fuzzer* fuzzer) {
-
-#define IPC_STRUCT_TRAITS_MEMBER(name) \
- if (!FuzzParam(&p->name, fuzzer)) \
- return false;
-
-#define IPC_STRUCT_TRAITS_PARENT(type) \
- if (!FuzzParam(static_cast<type*>(p), fuzzer)) \
- return false;
-
-#define IPC_STRUCT_TRAITS_END() \
- return true; \
- } \
- };
-
-// If |condition| isn't met, the messsge will fail to serialize. Try
-// increasingly smaller ranges until we find one that happens to meet
-// the condition, or fail trying.
-// TODO(mbarbella): Attempt to validate even in the mutation case.
-#undef IPC_ENUM_TRAITS_VALIDATE
-#define IPC_ENUM_TRAITS_VALIDATE(enum_name, condition) \
- template <> \
- struct FuzzTraits<enum_name> { \
- static bool Fuzz(enum_name* p, Fuzzer* fuzzer) { \
- if (!fuzzer->ShouldGenerate()) { \
- return FuzzParam(reinterpret_cast<int*>(p), fuzzer); \
- } \
- for (int shift = 30; shift; --shift) { \
- for (int tries = 0; tries < 2; ++tries) { \
- int value = RandInRange(1 << shift); \
- if (condition) { \
- *reinterpret_cast<int*>(p) = value; \
- return true; \
- } \
- } \
- } \
- std::cerr << "failed to satisfy " << #condition << "\n"; \
- return false; \
- } \
- };
-
-// Bring them into existence.
-#include "tools/ipc_fuzzer/message_lib/all_messages.h"
-#include "tools/ipc_fuzzer/message_lib/all_message_null_macros.h"
-
-#define MAX_FAKE_ROUTING_ID 15
-
-// MessageFactory abstracts away constructing control/routed messages by
-// providing an additional random routing ID argument when necessary.
-template <typename Message, IPC::MessageKind>
-class MessageFactory;
-
-template <typename Message>
-class MessageFactory<Message, IPC::MessageKind::CONTROL> {
- public:
- template <typename... Args>
- static std::unique_ptr<Message> New(const Args&... args) {
- return std::make_unique<Message>(args...);
- }
-};
-
-template <typename Message>
-class MessageFactory<Message, IPC::MessageKind::ROUTED> {
- public:
- template <typename... Args>
- static std::unique_ptr<Message> New(const Args&... args) {
- return std::make_unique<Message>(RandInRange(MAX_FAKE_ROUTING_ID), args...);
- }
-};
-
-template <typename Message>
-class FuzzerHelper;
-
-template <typename Meta, typename... Ins>
-class FuzzerHelper<IPC::MessageT<Meta, std::tuple<Ins...>, void>> {
- public:
- using Message = IPC::MessageT<Meta, std::tuple<Ins...>, void>;
-
- static std::unique_ptr<IPC::Message> Fuzz(IPC::Message* msg, Fuzzer* fuzzer) {
- return FuzzImpl(msg, fuzzer, std::index_sequence_for<Ins...>());
- }
-
- private:
- template <size_t... Ns>
- static std::unique_ptr<IPC::Message> FuzzImpl(IPC::Message* msg,
- Fuzzer* fuzzer,
- std::index_sequence<Ns...>) {
- typename Message::Param p;
- if (msg) {
- Message::Read(static_cast<Message*>(msg), &p);
- }
- if (FuzzParam(&p, fuzzer)) {
- return MessageFactory<Message, Meta::kKind>::New(std::get<Ns>(p)...);
- }
- std::cerr << "Don't know how to handle " << Meta::kName << "\n";
- return nullptr;
- }
-};
-
-template <typename Meta, typename... Ins, typename... Outs>
-class FuzzerHelper<
- IPC::MessageT<Meta, std::tuple<Ins...>, std::tuple<Outs...>>> {
- public:
- using Message = IPC::MessageT<Meta, std::tuple<Ins...>, std::tuple<Outs...>>;
-
- static std::unique_ptr<IPC::Message> Fuzz(IPC::Message* msg, Fuzzer* fuzzer) {
- return FuzzImpl(msg, fuzzer, std::index_sequence_for<Ins...>());
- }
-
- private:
- template <size_t... Ns>
- static std::unique_ptr<IPC::Message> FuzzImpl(IPC::Message* msg,
- Fuzzer* fuzzer,
- std::index_sequence<Ns...>) {
- typename Message::SendParam p;
- Message* real_msg = static_cast<Message*>(msg);
- std::unique_ptr<Message> new_msg;
- if (real_msg) {
- Message::ReadSendParam(real_msg, &p);
- }
- if (FuzzParam(&p, fuzzer)) {
- new_msg = MessageFactory<Message, Meta::kKind>::New(
- std::get<Ns>(p)..., static_cast<Outs*>(nullptr)...);
- }
- if (real_msg && new_msg) {
- MessageCracker::CopyMessageID(new_msg.get(), real_msg);
- } else if (!new_msg) {
- std::cerr << "Don't know how to handle " << Meta::kName << "\n";
- }
- return new_msg;
- }
-};
-
-#include "tools/ipc_fuzzer/message_lib/all_message_null_macros.h"
-
-void PopulateFuzzerFunctionVector(
- FuzzerFunctionVector* function_vector) {
-#undef IPC_MESSAGE_DECL
-#define IPC_MESSAGE_DECL(name, ...) \
- function_vector->push_back(FuzzerHelper<name>::Fuzz);
-#include "tools/ipc_fuzzer/message_lib/all_messages.h"
-}
-
-// Redefine macros to register fuzzing functions into map.
-#include "tools/ipc_fuzzer/message_lib/all_message_null_macros.h"
-#undef IPC_MESSAGE_DECL
-#define IPC_MESSAGE_DECL(name, ...) \
- (*map)[static_cast<uint32_t>(name::ID)] = FuzzerHelper<name>::Fuzz;
-
-void PopulateFuzzerFunctionMap(FuzzerFunctionMap* map) {
-#include "tools/ipc_fuzzer/message_lib/all_messages.h"
-}
-
-} // namespace ipc_fuzzer
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.h b/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.h
deleted file mode 100644
index 531bbe77499..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_IPC_FUZZER_MUTATE_FUZZER_H_
-#define TOOLS_IPC_FUZZER_MUTATE_FUZZER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "base/strings/string_util.h"
-#include "ipc/ipc_message.h"
-
-namespace ipc_fuzzer {
-
-// Interface implemented by those who generate basic types. The types all
-// correspond to the types which a pickle from base/pickle.h can pickle,
-// plus the floating point types.
-class Fuzzer {
- public:
- // Functions for various data types.
- virtual void FuzzBool(bool* value) = 0;
- virtual void FuzzInt(int* value) = 0;
- virtual void FuzzLong(long* value) = 0;
- virtual void FuzzSize(size_t* value) = 0;
- virtual void FuzzUChar(unsigned char* value) = 0;
- virtual void FuzzWChar(wchar_t* value) = 0;
- virtual void FuzzUInt16(uint16_t* value) = 0;
- virtual void FuzzUInt32(uint32_t* value) = 0;
- virtual void FuzzInt64(int64_t* value) = 0;
- virtual void FuzzUInt64(uint64_t* value) = 0;
- virtual void FuzzFloat(float* value) = 0;
- virtual void FuzzDouble(double *value) = 0;
- virtual void FuzzString(std::string* value) = 0;
- virtual void FuzzString16(base::string16* value) = 0;
- virtual void FuzzData(char* data, int length) = 0;
- virtual void FuzzBytes(void* data, int data_len) = 0;
-
- // Used to determine if a completely new value should be generated for
- // certain types instead of attempting to modify the existing one.
- virtual bool ShouldGenerate();
-};
-
-class NoOpFuzzer : public Fuzzer {
- public:
- NoOpFuzzer() {}
- virtual ~NoOpFuzzer() {}
-
- void FuzzBool(bool* value) override {}
- void FuzzInt(int* value) override {}
- void FuzzLong(long* value) override {}
- void FuzzSize(size_t* value) override {}
- void FuzzUChar(unsigned char* value) override {}
- void FuzzWChar(wchar_t* value) override {}
- void FuzzUInt16(uint16_t* value) override {}
- void FuzzUInt32(uint32_t* value) override {}
- void FuzzInt64(int64_t* value) override {}
- void FuzzUInt64(uint64_t* value) override {}
- void FuzzFloat(float* value) override {}
- void FuzzDouble(double* value) override {}
- void FuzzString(std::string* value) override {}
- void FuzzString16(base::string16* value) override {}
- void FuzzData(char* data, int length) override {}
- void FuzzBytes(void* data, int data_len) override {}
-};
-
-using FuzzerFunction = std::unique_ptr<IPC::Message> (*)(IPC::Message*,
- Fuzzer*);
-
-// Used for mutating messages. Once populated, the map associates a message ID
-// with a FuzzerFunction used for mutation of that message type.
-using FuzzerFunctionMap = std::unordered_map<uint32_t, FuzzerFunction>;
-void PopulateFuzzerFunctionMap(FuzzerFunctionMap* map);
-
-// Used for generating new messages. Once populated, the vector contains
-// FuzzerFunctions for all message types that we know how to generate.
-using FuzzerFunctionVector = std::vector<FuzzerFunction>;
-void PopulateFuzzerFunctionVector(FuzzerFunctionVector* function_vector);
-
-// Since IPC::Message can be serialized, we also track a global function vector
-// to handle generation of new messages while fuzzing.
-extern FuzzerFunctionVector g_function_vector;
-
-} // namespace ipc_fuzzer
-
-#endif // TOOLS_IPC_FUZZER_MUTATE_FUZZER_H_
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/fuzzer_main.cc b/chromium/tools/ipc_fuzzer/fuzzer/fuzzer_main.cc
deleted file mode 100644
index b899c856191..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/fuzzer_main.cc
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <iostream>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/strings/string_split.h"
-#include "ipc/ipc_message_macros.h"
-#include "tools/ipc_fuzzer/fuzzer/fuzzer.h"
-#include "tools/ipc_fuzzer/fuzzer/generator.h"
-#include "tools/ipc_fuzzer/fuzzer/mutator.h"
-#include "tools/ipc_fuzzer/fuzzer/rand_util.h"
-#include "tools/ipc_fuzzer/message_lib/message_file.h"
-
-namespace ipc_fuzzer {
-
-namespace {
-
-// TODO(mbarbella): Check to see if this value is actually reasonable.
-const int kFrequency = 23;
-
-const char kCountSwitch[] = "count";
-const char kCountSwitchHelp[] =
- "Number of messages to generate (generator).";
-
-const char kFrequencySwitch[] = "frequency";
-const char kFrequencySwitchHelp[] =
- "Probability of mutation; tweak every 1/|q| times (mutator).";
-
-const char kFuzzerNameSwitch[] = "fuzzer-name";
-const char kFuzzerNameSwitchHelp[] =
- "Select from generate, mutate, or no-op. Default: generate";
-
-const char kHelpSwitch[] = "help";
-const char kHelpSwitchHelp[] =
- "Show this message.";
-
-const char kPermuteSwitch[] = "permute";
-const char kPermuteSwitchHelp[] =
- "Randomly shuffle the order of all messages (mutator).";
-
-const char kTypeListSwitch[] = "type-list";
-const char kTypeListSwitchHelp[] =
- "Explicit list of the only message-ids to mutate (mutator).";
-
-void usage() {
- std::cerr << "Mutate messages from an exiting message file.\n";
-
- std::cerr << "Usage:\n"
- << " ipc_fuzzer"
- << " [--" << kCountSwitch << "=c]"
- << " [--" << kFrequencySwitch << "=q]"
- << " [--" << kFuzzerNameSwitch << "=f]"
- << " [--" << kHelpSwitch << "]"
- << " [--" << kTypeListSwitch << "=x,y,z...]"
- << " [--" << kPermuteSwitch << "]"
- << " [infile (mutation only)] outfile\n";
-
- std::cerr
- << " --" << kCountSwitch << " - " << kCountSwitchHelp << "\n"
- << " --" << kFrequencySwitch << " - " << kFrequencySwitchHelp << "\n"
- << " --" << kFuzzerNameSwitch << " - " << kFuzzerNameSwitchHelp << "\n"
- << " --" << kHelpSwitch << " - " << kHelpSwitchHelp << "\n"
- << " --" << kTypeListSwitch << " - " << kTypeListSwitchHelp << "\n"
- << " --" << kPermuteSwitch << " - " << kPermuteSwitchHelp << "\n";
-}
-
-} // namespace
-
-class FuzzerFactory {
- public:
- static Fuzzer *Create(const std::string& name, int frequency) {
- if (name == "default")
- return new Generator();
-
- if (name == "generate")
- return new Generator();
-
- if (name == "mutate")
- return new Mutator(frequency);
-
- if (name == "no-op")
- return new NoOpFuzzer();
-
- std::cerr << "No such fuzzer: " << name << "\n";
- return 0;
- }
-};
-
-static std::unique_ptr<IPC::Message> RewriteMessage(IPC::Message* message,
- Fuzzer* fuzzer,
- FuzzerFunctionMap* map) {
- FuzzerFunctionMap::iterator it = map->find(message->type());
- if (it == map->end()) {
- // This usually indicates a missing message file in all_messages.h, or
- // that the message dump file is taken from a different revision of
- // chromium from this executable.
- std::cerr << "Unknown message type: ["
- << IPC_MESSAGE_ID_CLASS(message->type()) << ", "
- << IPC_MESSAGE_ID_LINE(message->type()) << "].\n";
- return 0;
- }
-
- return (*it->second)(message, fuzzer);
-}
-
-int Generate(base::CommandLine* cmd, Fuzzer* fuzzer) {
- base::CommandLine::StringVector args = cmd->GetArgs();
- if (args.size() != 1) {
- usage();
- return EXIT_FAILURE;
- }
- base::FilePath::StringType output_file_name = args[0];
-
- int message_count = 1000;
- if (cmd->HasSwitch(kCountSwitch))
- message_count = atoi(cmd->GetSwitchValueASCII(kCountSwitch).c_str());
-
- MessageVector message_vector;
- int bad_count = 0;
- if (message_count < 0) {
- // Enumerate them all.
- for (size_t i = 0; i < g_function_vector.size(); ++i) {
- std::unique_ptr<IPC::Message> new_message =
- (*g_function_vector[i])(nullptr, fuzzer);
- if (new_message)
- message_vector.push_back(std::move(new_message));
- else
- bad_count += 1;
- }
- } else {
- // Fuzz a random batch.
- for (int i = 0; i < message_count; ++i) {
- size_t index = RandInRange(g_function_vector.size());
- std::unique_ptr<IPC::Message> new_message =
- (*g_function_vector[index])(nullptr, fuzzer);
- if (new_message)
- message_vector.push_back(std::move(new_message));
- else
- bad_count += 1;
- }
- }
-
- std::cerr << "Failed to generate " << bad_count << " messages.\n";
- if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
- return EXIT_FAILURE;
- return EXIT_SUCCESS;
-}
-
-int Mutate(base::CommandLine* cmd, Fuzzer* fuzzer) {
- base::CommandLine::StringVector args = cmd->GetArgs();
- if (args.size() != 2) {
- usage();
- return EXIT_FAILURE;
- }
- base::FilePath::StringType input_file_name = args[0];
- base::FilePath::StringType output_file_name = args[1];
-
- bool permute = cmd->HasSwitch(kPermuteSwitch);
-
- std::string type_string_list = cmd->GetSwitchValueASCII(kTypeListSwitch);
- std::vector<std::string> type_string_vector = base::SplitString(
- type_string_list, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- std::set<uint32_t> type_set;
- for (size_t i = 0; i < type_string_vector.size(); ++i) {
- type_set.insert(atoi(type_string_vector[i].c_str()));
- }
-
- FuzzerFunctionMap fuzz_function_map;
- PopulateFuzzerFunctionMap(&fuzz_function_map);
-
- MessageVector message_vector;
- if (!MessageFile::Read(base::FilePath(input_file_name), &message_vector))
- return EXIT_FAILURE;
-
- for (size_t i = 0; i < message_vector.size(); ++i) {
- IPC::Message* msg = message_vector[i].get();
- // If an explicit type set is specified, make sure we should be mutating
- // this message type on this run.
- if (!type_set.empty() && type_set.end() == std::find(
- type_set.begin(), type_set.end(), msg->type())) {
- continue;
- }
- std::unique_ptr<IPC::Message> new_message =
- RewriteMessage(msg, fuzzer, &fuzz_function_map);
- if (new_message)
- message_vector[i] = std::move(new_message);
- }
-
- if (permute) {
- std::shuffle(message_vector.begin(), message_vector.end(),
- *g_mersenne_twister);
- }
-
- if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
- return EXIT_FAILURE;
- return EXIT_SUCCESS;
-}
-
-int FuzzerMain(int argc, char** argv) {
- base::CommandLine::Init(argc, argv);
- base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
- base::CommandLine::StringVector args = cmd->GetArgs();
-
- if (args.size() == 0 || args.size() > 2 || cmd->HasSwitch(kHelpSwitch)) {
- usage();
- return EXIT_FAILURE;
- }
-
- InitRand();
-
- PopulateFuzzerFunctionVector(&g_function_vector);
- std::cerr << "Counted " << g_function_vector.size()
- << " distinct messages present in chrome.\n";
-
- std::string fuzzer_name = "default";
- if (cmd->HasSwitch(kFuzzerNameSwitch))
- fuzzer_name = cmd->GetSwitchValueASCII(kFuzzerNameSwitch);
-
- int frequency = kFrequency;
- if (cmd->HasSwitch(kFrequencySwitch))
- frequency = atoi(cmd->GetSwitchValueASCII(kFrequencySwitch).c_str());
-
- Fuzzer* fuzzer = FuzzerFactory::Create(fuzzer_name, frequency);
- if (!fuzzer)
- return EXIT_FAILURE;
-
- int result;
- base::FilePath::StringType output_file_name;
- if (fuzzer_name == "default" || fuzzer_name == "generate") {
- result = Generate(cmd, fuzzer);
- } else {
- result = Mutate(cmd, fuzzer);
- }
-
- return result;
-}
-
-} // namespace ipc_fuzzer
-
-int main(int argc, char** argv) {
- return ipc_fuzzer::FuzzerMain(argc, argv);
-}
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/generator.cc b/chromium/tools/ipc_fuzzer/fuzzer/generator.cc
deleted file mode 100644
index bcf827c7af5..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/generator.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <string>
-
-#include "base/strings/string_util.h"
-#include "tools/ipc_fuzzer/fuzzer/generator.h"
-#include "tools/ipc_fuzzer/fuzzer/rand_util.h"
-
-namespace ipc_fuzzer {
-
-template <typename T>
-void GenerateIntegralType(T* value) {
- switch (RandInRange(16)) {
- case 0:
- *value = static_cast<T>(0);
- break;
- case 1:
- *value = static_cast<T>(1);
- break;
- case 2:
- *value = static_cast<T>(-1);
- break;
- case 3:
- *value = static_cast<T>(2);
- break;
- default:
- *value = static_cast<T>(RandU64());
- break;
- }
-}
-
-template <typename T>
-void GenerateFloatingType(T* value) {
- *value = RandDouble();
-}
-
-template <typename T>
-void GenerateStringType(T* value) {
- T temp_string;
- size_t length = RandInRange(300);
- for (size_t i = 0; i < length; ++i)
- temp_string += RandInRange(256);
- *value = temp_string;
-}
-
-void Generator::FuzzBool(bool* value) {
- *value = RandInRange(2) ? true: false;
-}
-
-void Generator::FuzzInt(int* value) {
- GenerateIntegralType<int>(value);
-}
-
-void Generator::FuzzLong(long* value) {
- GenerateIntegralType<long>(value);
-}
-
-void Generator::FuzzSize(size_t* value) {
- GenerateIntegralType<size_t>(value);
-}
-
-void Generator::FuzzUChar(unsigned char* value) {
- GenerateIntegralType<unsigned char>(value);
-}
-
-void Generator::FuzzWChar(wchar_t* value) {
- GenerateIntegralType<wchar_t>(value);
-}
-
-void Generator::FuzzUInt16(uint16_t* value) {
- GenerateIntegralType<uint16_t>(value);
-}
-
-void Generator::FuzzUInt32(uint32_t* value) {
- GenerateIntegralType<uint32_t>(value);
-}
-
-void Generator::FuzzInt64(int64_t* value) {
- GenerateIntegralType<int64_t>(value);
-}
-
-void Generator::FuzzUInt64(uint64_t* value) {
- GenerateIntegralType<uint64_t>(value);
-}
-
-void Generator::FuzzFloat(float* value) {
- GenerateFloatingType<float>(value);
-}
-
-void Generator::FuzzDouble(double* value) {
- GenerateFloatingType<double>(value);
-}
-
-void Generator::FuzzString(std::string* value) {
- GenerateStringType<std::string>(value);
-}
-
-void Generator::FuzzString16(base::string16* value) {
- GenerateStringType<base::string16>(value);
-}
-
-void Generator::FuzzData(char* data, int length) {
- for (int i = 0; i < length; ++i) {
- GenerateIntegralType<char>(&data[i]);
- }
-}
-
-void Generator::FuzzBytes(void* data, int data_len) {
- FuzzData(static_cast<char*>(data), data_len);
-}
-
-bool Generator::ShouldGenerate() {
- // The generator fuzzer should always generate new values.
- return true;
-}
-
-} // namespace ipc_fuzzer
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/generator.h b/chromium/tools/ipc_fuzzer/fuzzer/generator.h
deleted file mode 100644
index 2e1e6a0e556..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/generator.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_IPC_FUZZER_MUTATE_GENERATOR_H_
-#define TOOLS_IPC_FUZZER_MUTATE_GENERATOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "tools/ipc_fuzzer/fuzzer/fuzzer.h"
-
-namespace ipc_fuzzer {
-
-class Generator : public Fuzzer {
- public:
- Generator() {}
- virtual ~Generator() {}
-
- void FuzzBool(bool* value) override;
- void FuzzInt(int* value) override;
- void FuzzLong(long* value) override;
- void FuzzSize(size_t* value) override;
- void FuzzUChar(unsigned char* value) override;
- void FuzzWChar(wchar_t* value) override;
- void FuzzUInt16(uint16_t* value) override;
- void FuzzUInt32(uint32_t* value) override;
- void FuzzInt64(int64_t* value) override;
- void FuzzUInt64(uint64_t* value) override;
- void FuzzFloat(float* value) override;
- void FuzzDouble(double* value) override;
- void FuzzString(std::string* value) override;
- void FuzzString16(base::string16* value) override;
- void FuzzData(char* data, int length) override;
- void FuzzBytes(void* data, int data_len) override;
- bool ShouldGenerate() override;
-};
-
-} // namespace ipc_fuzzer
-
-#endif // TOOLS_IPC_FUZZER_MUTATE_GENERATOR_H_
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/mutator.cc b/chromium/tools/ipc_fuzzer/fuzzer/mutator.cc
deleted file mode 100644
index 6e74d205d91..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/mutator.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <string>
-
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "tools/ipc_fuzzer/fuzzer/mutator.h"
-#include "tools/ipc_fuzzer/fuzzer/rand_util.h"
-
-namespace ipc_fuzzer {
-
-template <typename T>
-void FuzzIntegralType(T* value, unsigned int frequency) {
- if (RandEvent(frequency)) {
- switch (RandInRange(4)) {
- case 0: (*value) = 0; break;
- case 1: (*value)--; break;
- case 2: (*value)++; break;
- case 3: (*value) = RandU64(); break;
- }
- }
-}
-
-template <typename T>
-void FuzzStringType(T* value, unsigned int frequency,
- const T& literal1, const T& literal2) {
- if (RandEvent(frequency)) {
- switch (RandInRange(5)) {
- case 4: (*value) = (*value) + (*value); FALLTHROUGH;
- case 3: (*value) = (*value) + (*value); FALLTHROUGH;
- case 2: (*value) = (*value) + (*value); break;
- case 1: (*value) += literal1; break;
- case 0: (*value) = literal2; break;
- }
- }
-}
-
-void Mutator::FuzzBool(bool* value) {
- if (RandEvent(frequency_))
- (*value) = !(*value);
-}
-
-void Mutator::FuzzInt(int* value) {
- FuzzIntegralType<int>(value, frequency_);
-}
-
-void Mutator::FuzzLong(long* value) {
- FuzzIntegralType<long>(value, frequency_);
-}
-
-void Mutator::FuzzSize(size_t* value) {
- FuzzIntegralType<size_t>(value, frequency_);
-}
-
-void Mutator::FuzzUChar(unsigned char* value) {
- FuzzIntegralType<unsigned char>(value, frequency_);
-}
-
-void Mutator::FuzzWChar(wchar_t* value) {
- FuzzIntegralType<wchar_t>(value, frequency_);
-}
-
-void Mutator::FuzzUInt16(uint16_t* value) {
- FuzzIntegralType<uint16_t>(value, frequency_);
-}
-
-void Mutator::FuzzUInt32(uint32_t* value) {
- FuzzIntegralType<uint32_t>(value, frequency_);
-}
-
-void Mutator::FuzzInt64(int64_t* value) {
- FuzzIntegralType<int64_t>(value, frequency_);
-}
-
-void Mutator::FuzzUInt64(uint64_t* value) {
- FuzzIntegralType<uint64_t>(value, frequency_);
-}
-
-void Mutator::FuzzFloat(float* value) {
- if (RandEvent(frequency_))
- *value = RandDouble();
-}
-
-void Mutator::FuzzDouble(double* value) {
- if (RandEvent(frequency_))
- *value = RandDouble();
-}
-
-void Mutator:: FuzzString(std::string* value) {
- FuzzStringType<std::string>(value, frequency_, "BORKED", std::string());
-}
-
-void Mutator::FuzzString16(base::string16* value) {
- FuzzStringType<base::string16>(value, frequency_,
- base::WideToUTF16(L"BORKED"),
- base::WideToUTF16(L""));
-}
-
-void Mutator::FuzzData(char* data, int length) {
- if (RandEvent(frequency_)) {
- for (int i = 0; i < length; ++i) {
- FuzzIntegralType<char>(&data[i], frequency_);
- }
- }
-}
-
-void Mutator::FuzzBytes(void* data, int data_len) {
- FuzzData(static_cast<char*>(data), data_len);
-}
-
-bool Mutator::ShouldGenerate() {
- // TODO(mbarbella): With a low probability, allow something to be fully
- // rewritten while mutating instead of always changing the existing value.
- return false;
-}
-
-} // namespace ipc_fuzzer
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/mutator.h b/chromium/tools/ipc_fuzzer/fuzzer/mutator.h
deleted file mode 100644
index 993b25482dd..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/mutator.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_IPC_FUZZER_MUTATE_MUTATOR_H_
-#define TOOLS_IPC_FUZZER_MUTATE_MUTATOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "tools/ipc_fuzzer/fuzzer/fuzzer.h"
-
-namespace ipc_fuzzer {
-
-class Mutator : public Fuzzer {
- public:
- explicit Mutator(unsigned int frequency) : frequency_(frequency) {}
- virtual ~Mutator() {}
-
- void FuzzBool(bool* value) override;
- void FuzzInt(int* value) override;
- void FuzzLong(long* value) override;
- void FuzzSize(size_t* value) override;
- void FuzzUChar(unsigned char* value) override;
- void FuzzWChar(wchar_t* value) override;
- void FuzzUInt16(uint16_t* value) override;
- void FuzzUInt32(uint32_t* value) override;
- void FuzzInt64(int64_t* value) override;
- void FuzzUInt64(uint64_t* value) override;
- void FuzzFloat(float* value) override;
- void FuzzDouble(double* value) override;
- void FuzzString(std::string* value) override;
- void FuzzString16(base::string16* value) override;
- void FuzzData(char* data, int length) override;
- void FuzzBytes(void* data, int data_len) override;
- bool ShouldGenerate() override;
-
- private:
- // TODO(mbarbella): Use double frequencies.
- unsigned int frequency_;
-};
-
-} // namespace ipc_fuzzer
-
-#endif // TOOLS_IPC_FUZZER_MUTATE_MUTATOR_H_
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/rand_util.cc b/chromium/tools/ipc_fuzzer/fuzzer/rand_util.cc
deleted file mode 100644
index e0a16e8e204..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/rand_util.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/rand_util.h"
-#include "tools/ipc_fuzzer/fuzzer/rand_util.h"
-
-namespace ipc_fuzzer {
-
-std::mt19937* g_mersenne_twister = nullptr;
-
-void InitRand() {
- g_mersenne_twister =
- new std::mt19937(static_cast<uint32_t>(base::RandUint64()));
-}
-
-} // namespace ipc_fuzzer
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/rand_util.h b/chromium/tools/ipc_fuzzer/fuzzer/rand_util.h
deleted file mode 100644
index af433c0de93..00000000000
--- a/chromium/tools/ipc_fuzzer/fuzzer/rand_util.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_IPC_FUZZER_MUTATE_RAND_UTIL_H_
-#define TOOLS_IPC_FUZZER_MUTATE_RAND_UTIL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <random>
-
-namespace ipc_fuzzer {
-
-extern std::mt19937* g_mersenne_twister;
-
-void InitRand();
-
-inline uint32_t RandU32() {
- return (*g_mersenne_twister)();
-}
-
-inline uint64_t RandU64() {
- return (static_cast<uint64_t>(RandU32()) << 32) | RandU32();
-}
-
-inline double RandDouble() {
- uint64_t rand_u64 = RandU64();
- return *reinterpret_cast<double*>(&rand_u64);
-}
-
-inline uint32_t RandInRange(uint32_t range) {
- return RandU32() % range;
-}
-
-inline bool RandEvent(uint32_t frequency) {
- return RandInRange(frequency) == 0;
-}
-
-inline size_t RandElementCount() {
- return RandU32() % 10;
-}
-
-} // namespace ipc_fuzzer
-
-#endif // TOOLS_IPC_FUZZER_MUTATE_RAND_UTIL_H_
diff --git a/chromium/tools/metrics/actions/actions.xml b/chromium/tools/metrics/actions/actions.xml
index 0076970f61c..038408bf6d5 100644
--- a/chromium/tools/metrics/actions/actions.xml
+++ b/chromium/tools/metrics/actions/actions.xml
@@ -17565,6 +17565,31 @@ should be able to be added at any place in this file.
</description>
</action>
+<action name="Signin_Signin_AbortAdvancedSyncSettings">
+ <owner>tangltom@chromium.org</owner>
+ <description>
+ Recorded when the user closes the tab, quits Chrome, reloads the page, etc.
+ during the advanced sync opt-in flow.
+ </description>
+</action>
+
+<action name="Signin_Signin_BackOnAdvancedSyncSettings">
+ <owner>tangltom@chromium.org</owner>
+ <description>
+ Recorded when the user clicks the &quot;browser back&quot; or the
+ &quot;settings back&quot; button to leave the sync settings page during the
+ advanced sync opt-in flow.
+ </description>
+</action>
+
+<action name="Signin_Signin_CancelAbortAdvancedSyncSettings">
+ <owner>tangltom@chromium.org</owner>
+ <description>
+ Recorded when the user hits 'Cancel' on the 'Leave site?' dialog during the
+ advanced sync opt-in flow. This means the user continues their sync setup.
+ </description>
+</action>
+
<action name="Signin_Signin_CancelAdvancedSyncSettings">
<owner>tangltom@chromium.org</owner>
<description>
diff --git a/chromium/tools/metrics/histograms/enums.xml b/chromium/tools/metrics/histograms/enums.xml
index 42670b474fc..75dbd91652a 100644
--- a/chromium/tools/metrics/histograms/enums.xml
+++ b/chromium/tools/metrics/histograms/enums.xml
@@ -4805,6 +4805,11 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="1" label="Expired"/>
</enum>
+<enum name="BooleanFocused">
+ <int value="0" label="Unfocused"/>
+ <int value="1" label="Focused"/>
+</enum>
+
<enum name="BooleanForced">
<int value="0" label="Not forced"/>
<int value="1" label="Forced"/>
@@ -7602,7 +7607,7 @@ Called by update_net_error_codes.py.-->
<int value="-143" label="SPDY_SESSION_ALREADY_EXISTS"/>
<int value="-142" label="MSG_TOO_BIG"/>
<int value="-141" label="SSL_CLIENT_AUTH_SIGNATURE_FAILED"/>
- <int value="-140" label="HTTPS_PROXY_TUNNEL_RESPONSE"/>
+ <int value="-140" label="HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT"/>
<int value="-139" label="TEMPORARILY_THROTTLED"/>
<int value="-138" label="NETWORK_ACCESS_DENIED"/>
<int value="-137" label="NAME_RESOLUTION_FAILED"/>
@@ -28287,6 +28292,15 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="5" label="Third Party Unsafe Headers"/>
</enum>
+<enum name="InterceptionType">
+ <int value="0" label="Not intercepted"/>
+ <int value="1" label="Other"/>
+ <int value="2" label="Http scheme"/>
+ <int value="3" label="Https scheme"/>
+ <int value="4" label="File scheme"/>
+ <int value="5" label="Data scheme"/>
+</enum>
+
<enum name="InternalErrorLoadEvent">
<summary>Internal Errors in the page_load_metrics system</summary>
<int value="0" label="Invalid timing IPC sent from renderer (deprecated)"/>
@@ -30727,6 +30741,8 @@ from previous Chrome versions.
<int value="-1720653947" label="WebRtcHybridAgc:disabled"/>
<int value="-1719833926" label="disable-answers-in-suggest"/>
<int value="-1716654100" label="tab-capture-downscale-quality"/>
+ <int value="-1715180530"
+ label="OmniboxUIExperimentShowSuffixOnAllSearchSuggestions:disabled"/>
<int value="-1714128884" label="disable-launcher-search-provider-api"/>
<int value="-1713564656" label="ProtectSyncCredentialOnReauth:enabled"/>
<int value="-1711751318" label="enable-data-reduction-proxy-lo-fi-preview"/>
@@ -31018,6 +31034,8 @@ from previous Chrome versions.
<int value="-1261263046"
label="RemoveUsageOfDeprecatedGaiaSigninEndpoint:disabled"/>
<int value="-1259901957" label="VrBrowserKeyboard:disabled"/>
+ <int value="-1256747007"
+ label="OminboxUIExperimentUseGenericSearchEngineIcon:disabled"/>
<int value="-1255427595" label="HomePageButtonForceEnabled:enabled"/>
<int value="-1254070521" label="enable-slimming-paint-invalidation"/>
<int value="-1253608371" label="IncognitoStrings:disabled"/>
@@ -31361,6 +31379,8 @@ from previous Chrome versions.
<int value="-671992446" label="TranslateRankerEnforcement:disabled"/>
<int value="-670188266" label="enable-zip-archiver-unpacker"/>
<int value="-667517406" label="overscroll-history-navigation"/>
+ <int value="-667018797"
+ label="OmniboxUIExperimentBlueTitlesAndGrayUrlsOnPageSuggestions:disabled"/>
<int value="-666508951" label="CrOSContainer:enabled"/>
<int value="-663476391" label="enable-pixel-canvas-recording:enabled"/>
<int value="-662064703" label="MediaSessionService:enabled"/>
@@ -31376,6 +31396,8 @@ from previous Chrome versions.
<int value="-641719457" label="disable-compositor-touch-hit-testing"/>
<int value="-639026783" label="disable-gpu-appcontainer"/>
<int value="-638952203" label="RendererSideResourceScheduler:disabled"/>
+ <int value="-634116286"
+ label="OmniboxUIExperimentUnboldSuggestionText:enabled"/>
<int value="-633274640" label="WebRTCPipeWireCapturer:enabled"/>
<int value="-632030508" label="NativeWindowNavButtons:disabled"/>
<int value="-631740127" label="inert-visual-viewport"/>
@@ -31398,6 +31420,8 @@ from previous Chrome versions.
<int value="-599932554" label="DoodlesOnLocalNtp:disabled"/>
<int value="-598050737" label="disable-es3-apis"/>
<int value="-596337171" label="disable-ash-sidebar"/>
+ <int value="-595819071"
+ label="OmniboxUIExperimentBlueTitlesOnPageSuggestions:disabled"/>
<int value="-593536514" label="ExperimentalTabController:enabled"/>
<int value="-592331266" label="ForegroundNotificationManager:enabled"/>
<int value="-589096918" label="ash-enable-fullscreen-app-list"/>
@@ -31469,6 +31493,8 @@ from previous Chrome versions.
<int value="-470247915"
label="AutofillUpstreamEditableExpirationDate:enabled"/>
<int value="-468697885" label="ArcInputMethod:enabled"/>
+ <int value="-462554210"
+ label="OminboxUIExperimentUseGenericSearchEngineIcon:enabled"/>
<int value="-462205750" label="enable-service-worker-sync"/>
<int value="-461292699" label="ContentSuggestionsCategoryOrder:enabled"/>
<int value="-460313418" label="ProgressBarThrottle:enabled"/>
@@ -31490,6 +31516,8 @@ from previous Chrome versions.
<int value="-410852857" label="ImprovedA2HS:disabled"/>
<int value="-406850932" label="EnableEmojiContextMenu:enabled"/>
<int value="-405380243" label="enable-encryption-migration"/>
+ <int value="-402038055"
+ label="OmniboxUIExperimentBlueTitlesAndGrayUrlsOnPageSuggestions:enabled"/>
<int value="-401170566"
label="OmniboxUIExperimentHideSuggestionUrlPath:disabled"/>
<int value="-400584764" label="ChromeHomeNtpRedesign:enabled"/>
@@ -31610,6 +31638,8 @@ from previous Chrome versions.
<int value="-192389983" label="NoStatePrefetch:enabled"/>
<int value="-191256027" label="AvoidFlashBetweenNavigation:disabled"/>
<int value="-185162926" label="IncreaseInputAudioBufferSize:enabled"/>
+ <int value="-184091779"
+ label="OmniboxUIExperimentWhiteBackgroundOnBlur:enabled"/>
<int value="-183246373" label="enable-multilingual-spellchecker"/>
<int value="-181590721"
label="AutofillEnforceMinRequiredFieldsForHeuristics:enabled"/>
@@ -31640,6 +31670,8 @@ from previous Chrome versions.
<int value="-138773929" label="PassiveDocumentEventListeners:enabled"/>
<int value="-138760381" label="AutofillManualFallbackAndroid:enabled"/>
<int value="-137303226" label="enable-chromevox-developer-option"/>
+ <int value="-135584721"
+ label="OmniboxUIExperimentBoldUserTextOnSearchSuggestions:disabled"/>
<int value="-135223364" label="AutofillShowTypePredictions:disabled"/>
<int value="-133098377" label="SyncPseudoUSSSearchEngines:disabled"/>
<int value="-128687277"
@@ -31715,6 +31747,8 @@ from previous Chrome versions.
<int value="-18464041" label="AutofillPrefilledFields:disabled"/>
<int value="-17698200" label="DoubleTapToZoomInTabletMode:disabled"/>
<int value="-16824589" label="ash-shelf-color"/>
+ <int value="-15879016"
+ label="OmniboxUIExperimentUnboldSuggestionText:disabled"/>
<int value="-13918890" label="disable-download-notification"/>
<int value="-11260186" label="enable-offline-pages-as-saved-pages"/>
<int value="-10709540"
@@ -31733,7 +31767,6 @@ from previous Chrome versions.
<int value="11698808" label="enable-dom-distiller-button-animation"/>
<int value="19815558" label="EnableSettingsShortcutSearch:disabled"/>
<int value="23556595" label="MarkHttpAs:enabled"/>
- <int value="26875005" label="disable-explicit-dma-fences"/>
<int value="27507364" label="apps-keep-chrome-alive"/>
<int value="29212695" label="OfflineIndicator:enabled"/>
<int value="31848187" label="ViewsTaskManager:disabled"/>
@@ -31829,6 +31862,8 @@ from previous Chrome versions.
<int value="201343576" label="enable-password-change-support:enabled"/>
<int value="203239167" label="ImprovedGeoLanguageData:enabled"/>
<int value="203776499" label="enable-virtual-keyboard-overscroll"/>
+ <int value="207907053"
+ label="OmniboxUIExperimentBlueSearchLoopAndSearchQuery:enabled"/>
<int value="215328738" label="ImprovedGeoLanguageData:disabled"/>
<int value="217455219" label="SyncStandaloneTransport:enabled"/>
<int value="218890378" label="ManualSaving:disabled"/>
@@ -32067,6 +32102,8 @@ from previous Chrome versions.
<int value="636425179" label="mhtml-generator-option"/>
<int value="637396292" label="AllBookmarks:enabled"/>
<int value="637452937" label="ChromeHomeSurvey:enabled"/>
+ <int value="638845342"
+ label="OmniboxUIExperimentShowSuffixOnAllSearchSuggestions:enabled"/>
<int value="642037198" label="SoleIntegration:disabled"/>
<int value="643725031" label="disable-touch-feedback"/>
<int value="644084236" label="CloseButtonsInactiveTabs:enabled"/>
@@ -32298,6 +32335,8 @@ from previous Chrome versions.
<int value="1049885154" label="OfflinePagesPrefetching:disabled"/>
<int value="1050048304" label="enable-font-cache-scaling"/>
<int value="1050321458" label="new-profile-management"/>
+ <int value="1050442356"
+ label="OmniboxUIExperimentBlueTitlesOnPageSuggestions:enabled"/>
<int value="1050664817" label="CSSFragmentIdentifiers:enabled"/>
<int value="1053743655" label="NewOverviewAnimations:enabled"/>
<int value="1054910800" label="enable-timezone-tracking-option"/>
@@ -32614,6 +32653,7 @@ from previous Chrome versions.
<int value="1577205328"
label="DataReductionProxyEnabledWithNetworkService:enabled"/>
<int value="1579461102" label="MemoryCoordinator:disabled"/>
+ <int value="1581002467" label="enable-explicit-dma-fences"/>
<int value="1586022426" label="AutofillCreditCardAssist:enabled"/>
<int value="1587521886" label="SSLCommittedInterstitials:enabled"/>
<int value="1589341623" label="disable-easy-unlock"/>
@@ -32635,6 +32675,8 @@ from previous Chrome versions.
<int value="1614309501" label="DataSaverLiteModeRebranding:enabled"/>
<int value="1614596813" label="CloseButtonsInactiveTabs:disabled"/>
<int value="1615988672" label="GrantNotificationsToDSE:enabled"/>
+ <int value="1616938915"
+ label="OmniboxUIExperimentWhiteBackgroundOnBlur:disabled"/>
<int value="1617187093" label="enable-improved-a2hs"/>
<int value="1618633341" label="MashOopViz:enabled"/>
<int value="1621298798" label="VrBrowserKeyboard:enabled"/>
@@ -32709,6 +32751,8 @@ from previous Chrome versions.
<int value="1735934914" label="OverlayScrollbarFlashWhenMouseEnter:disabled"/>
<int value="1736698988" label="FsNosymfollow:disabled"/>
<int value="1739456903" label="PWAFullCodeCache:enabled"/>
+ <int value="1742398600"
+ label="OmniboxUIExperimentBoldUserTextOnSearchSuggestions:enabled"/>
<int value="1747279677" label="disable-delegated-renderer"/>
<int value="1750822869" label="CrostiniBackup:disabled"/>
<int value="1752168018" label="enable-stale-while-revalidate"/>
@@ -32811,6 +32855,8 @@ from previous Chrome versions.
<int value="1913298816" label="OverlayScrollbar:enabled"/>
<int value="1913926782" label="ChromeModernAlternateCardLayout:disabled"/>
<int value="1915178511" label="disable-blink-features"/>
+ <int value="1918984253"
+ label="OmniboxUIExperimentBlueSearchLoopAndSearchQuery:disabled"/>
<int value="1919917329" label="ImplicitRootScroller:disabled"/>
<int value="1924192543" label="ProactiveTabFreezeAndDiscard:enabled"/>
<int value="1925627218" label="FullscreenToolbarReveal:disabled"/>
@@ -36298,7 +36344,7 @@ Called by update_net_error_codes.py.-->
<int value="137" label="NAME_RESOLUTION_FAILED"/>
<int value="138" label="NETWORK_ACCESS_DENIED"/>
<int value="139" label="TEMPORARILY_THROTTLED"/>
- <int value="140" label="HTTPS_PROXY_TUNNEL_RESPONSE"/>
+ <int value="140" label="HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT"/>
<int value="141" label="SSL_CLIENT_AUTH_SIGNATURE_FAILED"/>
<int value="142" label="MSG_TOO_BIG"/>
<int value="143" label="SPDY_SESSION_ALREADY_EXISTS"/>
@@ -40144,6 +40190,7 @@ Called by update_net_trust_anchors.py.-->
<int value="3" label="NSTemporaryDirectory"/>
<int value="4" label="TMPDIR"/>
<int value="5" label="/tmp"/>
+ <int value="6" label="/tmp, different volume"/>
</enum>
<enum name="OtherPossibleUsernamesUsage">
@@ -43453,7 +43500,9 @@ Called by update_net_trust_anchors.py.-->
<int value="0" label="Preview Allowed."/>
<int value="1" label="Blacklist not created."/>
<int value="2" label="Blacklist data not loaded yet from disk."/>
- <int value="3" label="User opted out of a preview recently."/>
+ <int value="3"
+ label="User opted out of a preview recently or reloaded on a preview
+ page recently."/>
<int value="4" label="User is blacklisted for all hosts."/>
<int value="5" label="User is blacklisted for the specific host."/>
<int value="6" label="The network quality estimate is not available."/>
@@ -43474,6 +43523,9 @@ Called by update_net_trust_anchors.py.-->
</int>
<int value="14" label="Network is not slow per session threshold."/>
<int value="15" label="Device was reported as offline."/>
+ <int value="16"
+ label="URL contained Basic Authentication, i.e.: a username or
+ password."/>
</enum>
<enum name="PreviewsHintCacheLevelDBStoreLoadMetadataResult">
@@ -43577,6 +43629,7 @@ Called by update_net_trust_anchors.py.-->
<int value="9"
label="Exceeded maximum number of navigation restarts or a redirect
loop was detected"/>
+ <int value="10" label="Disallowed by PreviewsState"/>
</enum>
<enum name="PreviewsServerLitePageServerResponse">
@@ -43657,6 +43710,8 @@ Called by update_net_trust_anchors.py.-->
<int value="11" label="PPD Rejected by cupstestppd"/>
<int value="12" label="Could not find PPD"/>
<int value="13" label="Failed to download PPD"/>
+ <int value="64" label="No reply from debugd over D-Bus"/>
+ <int value="65" label="Generic D-Bus timeout"/>
</enum>
<enum name="PrintJobResult">
@@ -52654,6 +52709,13 @@ Full version information for the fingerprint enum values:
<int value="3" label="Fallback for Status Bar and content"/>
</enum>
+<enum name="TunnelRedirectHistogramValue">
+ <int value="0" label="Subresource fetched using an explicit proxy"/>
+ <int value="1" label="Mainframe fetched using an explicit proxy"/>
+ <int value="2" label="Subresource fetched using an auto-detected proxy"/>
+ <int value="3" label="Mainframe fetched using an auto-detected proxy"/>
+</enum>
+
<enum name="UIEventType">
<int value="0" label="Unknown"/>
<int value="1" label="Touch released"/>
diff --git a/chromium/tools/metrics/histograms/histograms.xml b/chromium/tools/metrics/histograms/histograms.xml
index e9ab759f843..96056c0fac1 100644
--- a/chromium/tools/metrics/histograms/histograms.xml
+++ b/chromium/tools/metrics/histograms/histograms.xml
@@ -2945,6 +2945,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Android.WebView.ShouldInterceptRequest.InterceptionType"
+ enum="InterceptionType" expires_after="2020-02-11">
+ <owner>timvolodine@chromium.org</owner>
+ <owner>ntfschr@chromium.org</owner>
+ <summary>
+ Whether the request was intercepted by the embedder of Android WebView, and
+ if so which url scheme was used. Intercepted request are requests for which
+ the shouldInterceptRequest() callback returned a non-null response.
+ </summary>
+</histogram>
+
<histogram name="Android.WebView.SplitApkWorkaroundResult"
enum="SplitApkWorkaroundResult" expires_after="M72">
<owner>tiborg@chromium.org</owner>
@@ -11937,6 +11948,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Bluetooth.Availability" enum="BluetoothAvailability"
+ expires_after="2019-12-31">
+ <owner>kenrb@chromium.org</owner>
+ <owner>kpaulhamus@chromium.org</owner>
+ <summary>
+ Determines the availability and capabilities of the Bluetooth driver. This
+ metric is logged on startup.
+ </summary>
+</histogram>
+
<histogram name="Bluetooth.ConnectedDeviceCount" units="devices">
<owner>keybuk@chromium.org</owner>
<summary>
@@ -27319,6 +27340,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Enterprise.PolicyInvalidationsRegistrationResult"
+ enum="BooleanSuccess" expires_after="2020-02-14">
+ <owner>poromov@chromium.org</owner>
+ <summary>
+ Tracks the result of registration for policy invalidations. It will fail
+ when duplicate invalidation names are used for different policies due to
+ http://b/119860379.
+ </summary>
+</histogram>
+
<histogram name="Enterprise.PolicyInvalidationsStartupTime" units="ms">
<owner>mnissler@chromium.org</owner>
<summary>
@@ -49210,6 +49241,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.Session.UserAction.Focus" enum="BooleanFocused"
+ expires_after="M77">
+ <owner>steimel@chromium.org</owner>
+ <owner>media-dev@chromium.org</owner>
+ <summary>
+ The focused state of the WebContents associated with the MediaSession that
+ the user is interacting with. Recorded when the user interacts with a
+ MediaSession (e.g. by pressing the play/pause key on their keyboard).
+ </summary>
+</histogram>
+
<histogram name="Media.SRC.PreloadAutoHasPoster" enum="Boolean">
<owner>media-dev@chromium.org</owner>
<summary>
@@ -50283,6 +50325,44 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.WebMediaPlayerImpl.HLS.IsCorsCrossOrigin" enum="Boolean"
+ expires_after="2019-12-31">
+ <owner>sandersd@chromium.org</owner>
+ <owner>tguilbert@chromium.org</owner>
+ <summary>
+ When an HLS manifest is found during loading (on Android only), records
+ whether the request was CORS cross-origin. These are cases that could not be
+ implemented using fetch(). Note: subresources referenced by the manifest are
+ not considered; they may have different origins or CORS configurations.
+ </summary>
+</histogram>
+
+<histogram name="Media.WebMediaPlayerImpl.HLS.IsMixedContent" enum="Boolean"
+ expires_after="2019-12-31">
+ <owner>sandersd@chromium.org</owner>
+ <owner>tguilbert@chromium.org</owner>
+ <summary>
+ When an HLS manifest is found during loading (on Android only), records
+ whether the request would be mixed content. These are cases that could not
+ be implemented using fetch(). Note: subresources referenced by the manifest
+ are not considered; they may have different origins.
+ </summary>
+</histogram>
+
+<histogram name="Media.WebMediaPlayerImpl.HLS.WouldTaintOrigin" enum="Boolean"
+ expires_after="2019-12-31">
+ <owner>sandersd@chromium.org</owner>
+ <owner>tguilbert@chromium.org</owner>
+ <summary>
+ When an HLS manifest is found during loading (on Android only), records
+ whether the request was CORS cross-origin or redirected between origins.
+ These are cases that may or may not be able to be implemented using fetch(),
+ depending on details of the redirection and the setting of the crossorigin
+ attribute. Note: subresources referenced by the manifest are not considered;
+ they may have different origins or CORS configurations.
+ </summary>
+</histogram>
+
<histogram base="true" name="Media.WebMediaPlayerImpl.Memory" units="KB">
<owner>servolk@chromium.org</owner>
<summary>
@@ -61272,6 +61352,22 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Net.Proxy.RedirectDuringConnect"
+ enum="TunnelRedirectHistogramValue" expires_after="2019-05-19">
+ <owner>eroman@chromium.org</owner>
+ <owner>mmenke@chromium.org</owner>
+ <summary>
+ Counts how often a 302 (redirect) response is observed during CONNECT (proxy
+ tunnel establishment). The counts are bucketed by proxy settings source
+ (auto-detect vs explicit) and load type (subresource vs main frame).
+
+ To interpret this histogram, the most interesting property will be the
+ number of users in each of the buckets, which can be used to approximate
+ what fraction of users would be affected by a policy change that blocked
+ redirects on subresources/non-autodetected proxies.
+ </summary>
+</histogram>
+
<histogram name="Net.ProxyAuthRequested.HasConnection">
<owner>rch@chromium.org</owner>
<summary>
@@ -75339,6 +75435,9 @@ uploading your change for review.
<histogram name="OSX.BluetoothAvailability" enum="BluetoothAvailability"
expires_after="2018-08-30">
+ <obsolete>
+ Obsolete as of Chrome 73. This has been replaced by Bluetooth.Availability.
+ </obsolete>
<owner>erikchen@chromium.org</owner>
<summary>
The availability and capabilities of the Bluetooth driver on OSX devices.
@@ -75528,14 +75627,27 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="OSX.StagingDirectoryLocation" enum="OSXStagingDirectoryStep"
- expires_after="2019-12-31">
+<histogram name="OSX.StagingDirectoryLocation" enum="OSXStagingDirectoryStep">
+ <obsolete>
+ Deprecated as of 02/2019 in favor of StagingDirectoryLocation2.
+ </obsolete>
<owner>avi@chromium.org</owner>
<owner>rsesek@chromium.org</owner>
<owner>mark@chromium.org</owner>
<summary>Records first staging directory location that works.</summary>
</histogram>
+<histogram name="OSX.StagingDirectoryLocation2" enum="OSXStagingDirectoryStep"
+ expires_after="2019-12-31">
+ <owner>avi@chromium.org</owner>
+ <owner>rsesek@chromium.org</owner>
+ <owner>mark@chromium.org</owner>
+ <summary>
+ Records, during Chrome startup, the first staging directory location that
+ works. This is for the change to the updating system.
+ </summary>
+</histogram>
+
<histogram name="OSX.SystemHotkeyMap.LoadSuccess" enum="BooleanSuccess"
expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
diff --git a/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h b/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
index a4e7fe3b401..42e274c4d47 100644
--- a/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
+++ b/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
@@ -81,6 +81,10 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
bool AddContentLayer(CARendererLayerTree* tree,
const CARendererLayerParams& params);
+ // Workaround for https://crbug.com/923427. Only allow any
+ // AVSampleBufferDisplayLayer if there is exactly one video quad.
+ void EnforceOnlyOneAVLayer();
+
// Allocate CALayers for this layer and its children, and set their
// properties appropriately. Re-use the CALayers from |old_layer| if
// possible. If re-using a CALayer from |old_layer|, reset its |ca_layer|
@@ -92,7 +96,7 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
// Return true if the CALayer tree is just a video layer on a black or
// transparent background, false otherwise.
- bool WantsFullcreenLowPowerBackdrop();
+ bool WantsFullcreenLowPowerBackdrop() const;
std::vector<ClipAndSortingLayer> clip_and_sorting_layers;
base::scoped_nsobject<CALayer> ca_layer;
diff --git a/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
index 1c5988fe068..c9b20cf4a63 100644
--- a/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
+++ b/chromium/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -238,7 +238,7 @@ void CARendererLayerTree::CommitScheduledCALayers(
scale_factor_ = scale_factor;
}
-bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop() {
+bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop() const {
bool found_video_layer = false;
for (auto& clip_layer : clip_and_sorting_layers) {
for (auto& transform_layer : clip_layer.transform_layers) {
@@ -271,6 +271,28 @@ bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop() {
return found_video_layer;
}
+void CARendererLayerTree::RootLayer::EnforceOnlyOneAVLayer() {
+ size_t video_layer_count = 0;
+ for (auto& clip_layer : clip_and_sorting_layers) {
+ for (auto& transform_layer : clip_layer.transform_layers) {
+ for (auto& content_layer : transform_layer.content_layers) {
+ if (content_layer.use_av_layer)
+ video_layer_count += 1;
+ }
+ }
+ }
+ if (video_layer_count <= 1)
+ return;
+ for (auto& clip_layer : clip_and_sorting_layers) {
+ for (auto& transform_layer : clip_layer.transform_layers) {
+ for (auto& content_layer : transform_layer.content_layers) {
+ if (content_layer.use_av_layer)
+ content_layer.use_av_layer = false;
+ }
+ }
+ }
+}
+
id CARendererLayerTree::ContentsForSolidColorForTesting(SkColor color) {
return SolidColorContents::Get(color)->GetContents();
}
@@ -566,6 +588,8 @@ void CARendererLayerTree::RootLayer::CommitToCA(CALayer* superlayer,
DLOG(ERROR) << "CARendererLayerTree root layer not attached to tree.";
}
+ EnforceOnlyOneAVLayer();
+
if (WantsFullcreenLowPowerBackdrop()) {
const gfx::RectF bg_rect(
ScaleSize(gfx::SizeF(pixel_size), 1 / scale_factor));
diff --git a/chromium/ui/accessibility/ax_tree_serializer.h b/chromium/ui/accessibility/ax_tree_serializer.h
index 6875d414453..485e495796f 100644
--- a/chromium/ui/accessibility/ax_tree_serializer.h
+++ b/chromium/ui/accessibility/ax_tree_serializer.h
@@ -170,6 +170,9 @@ class AXTreeSerializer {
AXSourceNode node,
AXTreeUpdateBase<AXNodeData, AXTreeData>* out_update);
+ // Visit all of the descendants of |node| once.
+ void WalkAllDescendants(AXSourceNode node);
+
// Delete the entire client subtree but don't set the did_reset_ flag
// like when Reset() is called.
void InternalReset();
@@ -411,6 +414,12 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::SerializeChanges(
if (!tree_->IsValid(lca))
lca = tree_->GetRoot();
+ // Work around flaky source trees where nodes don't figure out their
+ // correct parent/child relationships until you walk the whole tree once.
+ // Covered by this test in the content_browsertests suite:
+ // DumpAccessibilityTreeTest.AccessibilityAriaOwns.
+ WalkAllDescendants(lca);
+
if (!SerializeChangedNodes(lca, out_update))
return false;
@@ -607,6 +616,15 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::
return true;
}
+template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
+void AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::WalkAllDescendants(
+ AXSourceNode node) {
+ std::vector<AXSourceNode> children;
+ tree_->GetChildren(node, &children);
+ for (size_t i = 0; i < children.size(); ++i)
+ WalkAllDescendants(children[i]);
+}
+
} // namespace ui
#endif // UI_ACCESSIBILITY_AX_TREE_SERIALIZER_H_
diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_te.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_te.xtb
index 73636791de4..991f5b1da06 100644
--- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_te.xtb
+++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_te.xtb
@@ -12,7 +12,7 @@
<translation id="1996252509865389616">ప్రారంభించాలా?</translation>
<translation id="2079545284768500474">చర్య రద్దు</translation>
<translation id="2179565792157161713">సుదీర్ఘ వివరణను కొత్త ట్యాబ్‌లో తెరువు</translation>
-<translation id="2223143012868735942">రంగు గ్రాహ్యతను మెరుగుపరచడానికి, అనుకూలీకరించగల రంగు ఫిల్టర్ వెబ్‌పేజీలకు వర్తింపజేయబడింది.</translation>
+<translation id="2223143012868735942">రంగు గ్రాహ్యతను మెరుగుపరచడానికి వెబ్‌పేజీలకు వర్తింపజేసే అనుకూలీకరించగల రంగు ఫిల్టర్.</translation>
<translation id="2394933097471027016">ఇప్పుడే దీన్ని ప్రయత్నించండి - కేరెట్ బ్రౌజింగ్ ఈ పేజీలో ఎల్లప్పుడూ ప్రారంభించబడి ఉంటుంది!</translation>
<translation id="2471847333270902538"><ph name="SITE" /> కోసం రంగు స్కీమ్:</translation>
<translation id="2648340354586434750">పదాల వారీగా తరలించడానికి &lt;span class='key'&gt;Option&lt;/span&gt;ని నొక్కి పట్టుకోండి.</translation>
@@ -26,8 +26,8 @@
<translation id="3812541808639806898">చిత్రం ప్రత్యామ్నాయ వచన వ్యూయర్</translation>
<translation id="381767806621926835">"longdesc" లేదా "aria-describedat" ఫీచర్ ఉన్న ఏదైనా అంశం యొక్క సుదీర్ఘ వివరణను యాక్సెస్ చేయడానికి దానిపై కుడి క్లిక్ చేయండి.</translation>
<translation id="4023902424053835668">బాణం కీలను ఉపయోగించి వెబ్ పేజీల వచనాన్ని బ్రౌజ్ చేయండి.</translation>
-<translation id="4388820049312272371">కర్సర్ స్థానాన్ని శీఘ్ర ఫ్లాష్‌తో హైలైట్ చేయండి.</translation>
-<translation id="4394049700291259645">ఆపివెయ్యి</translation>
+<translation id="4388820049312272371">కర్సర్ స్థానాన్ని త్వరిత ఫ్లాష్‌తో హైలైట్ చేయండి.</translation>
+<translation id="4394049700291259645">నిలిపివేయి</translation>
<translation id="4769065380738716500">చిత్రాలు వాటి alt వచనంతో భర్తీ చేయబడ్డాయి.</translation>
<translation id="4896660567607030658">అభిప్రాయం వద్దు, కేవలం కర్సర్‌ను చూపండి.</translation>
<translation id="4937901943818762779">యానిమేట్ చేసిన చిత్రాలను చూపండి, కానీ ఒకసారి మాత్రమే.</translation>
diff --git a/chromium/ui/base/ui_base_features.cc b/chromium/ui/base/ui_base_features.cc
index 71bd2fbcf77..07f73f85aef 100644
--- a/chromium/ui/base/ui_base_features.cc
+++ b/chromium/ui/base/ui_base_features.cc
@@ -176,7 +176,11 @@ bool IsOzoneDrmMojo() {
IsMultiProcessMash();
}
+#if defined(OS_MACOSX)
+const base::Feature kDarkMode = {"DarkMode", base::FEATURE_ENABLED_BY_DEFAULT};
+#else
const base::Feature kDarkMode = {"DarkMode", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
#if defined(OS_CHROMEOS)
const base::Feature kHandwritingGesture = {"HandwritingGesture",
diff --git a/chromium/ui/base/x/x11_display_util.cc b/chromium/ui/base/x/x11_display_util.cc
index d2e8edab3d7..e34c5cc6fda 100644
--- a/chromium/ui/base/x/x11_display_util.cc
+++ b/chromium/ui/base/x/x11_display_util.cc
@@ -57,6 +57,50 @@ std::map<RROutput, int> GetMonitors(int version,
return output_to_monitor;
}
+// Sets the work area on a list of displays. The work area for each display
+// must already be initialized to the display bounds. At most one display out
+// of |displays| will be affected.
+void ClipWorkArea(std::vector<display::Display>* displays,
+ int64_t primary_display_index,
+ float scale) {
+ XDisplay* xdisplay = gfx::GetXDisplay();
+ GLXWindow x_root_window = DefaultRootWindow(xdisplay);
+
+ std::vector<int> value;
+ if (!ui::GetIntArrayProperty(x_root_window, "_NET_WORKAREA", &value) ||
+ value.size() < 4) {
+ return;
+ }
+ gfx::Rect work_area = gfx::ScaleToEnclosingRect(
+ gfx::Rect(value[0], value[1], value[2], value[3]), 1.0f / scale);
+
+ // If the work area entirely contains exactly one display, assume it's meant
+ // for that display (and so do nothing).
+ if (std::count_if(displays->begin(), displays->end(),
+ [&](const display::Display& display) {
+ return work_area.Contains(display.bounds());
+ }) == 1) {
+ return;
+ }
+
+ // If the work area is entirely contained within exactly one display, assume
+ // it's meant for that display and intersect the work area with only that
+ // display.
+ auto found = std::find_if(displays->begin(), displays->end(),
+ [&](const display::Display& display) {
+ return display.bounds().Contains(work_area);
+ });
+
+ // If the work area spans multiple displays, intersect the work area with the
+ // primary display, like GTK does.
+ display::Display& primary =
+ found == displays->end() ? (*displays)[primary_display_index] : *found;
+
+ work_area.Intersect(primary.work_area());
+ if (!work_area.IsEmpty())
+ primary.set_work_area(work_area);
+}
+
} // namespace
int GetXrandrVersion(XDisplay* xdisplay) {
@@ -85,9 +129,15 @@ std::vector<display::Display> GetFallbackDisplayList(float scale) {
!display::IsDisplaySizeBlackListed(physical_size)) {
DCHECK_LE(1.0f, scale);
gfx_display.SetScaleAndBounds(scale, bounds_in_pixels);
+ gfx_display.set_work_area(
+ gfx::ScaleToEnclosingRect(bounds_in_pixels, 1.0f / scale));
+ } else {
+ scale = 1;
}
- return {gfx_display};
+ std::vector<display::Display> displays{gfx_display};
+ ClipWorkArea(&displays, 0, scale);
+ return displays;
}
std::vector<display::Display> BuildDisplaysFromXRandRInfo(
@@ -116,15 +166,6 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo(
int explicit_primary_display_index = -1;
int monitor_order_primary_display_index = -1;
- bool has_work_area = false;
- gfx::Rect work_area_in_pixels;
- std::vector<int> value;
- if (ui::GetIntArrayProperty(x_root_window, "_NET_WORKAREA", &value) &&
- value.size() >= 4) {
- work_area_in_pixels = gfx::Rect(value[0], value[1], value[2], value[3]);
- has_work_area = true;
- }
-
// As per-display scale factor is not supported right now,
// the X11 root window's scale factor is always used.
for (int i = 0; i < resources->noutput; ++i) {
@@ -161,20 +202,8 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo(
if (!display::Display::HasForceDeviceScaleFactor()) {
display.SetScaleAndBounds(scale, crtc_bounds);
- }
-
- if (has_work_area) {
- gfx::Rect intersection_in_pixels = crtc_bounds;
- if (is_primary_display) {
- intersection_in_pixels.Intersect(work_area_in_pixels);
- }
- // SetScaleAndBounds() above does the conversion from pixels to DIP for
- // us, but set_work_area does not, so we need to do it here.
- display.set_work_area(gfx::Rect(
- gfx::ScaleToFlooredPoint(intersection_in_pixels.origin(),
- 1.0f / display.device_scale_factor()),
- gfx::ScaleToFlooredSize(intersection_in_pixels.size(),
- 1.0f / display.device_scale_factor())));
+ display.set_work_area(
+ gfx::ScaleToEnclosingRect(crtc_bounds, 1.0f / scale));
}
switch (crtc->rotation) {
@@ -219,6 +248,7 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo(
if (displays.empty())
return GetFallbackDisplayList(scale);
+ ClipWorkArea(&displays, *primary_display_index_out, scale);
return displays;
}
diff --git a/chromium/ui/events/ozone/evdev/event_device_info.cc b/chromium/ui/events/ozone/evdev/event_device_info.cc
index 4a001a73888..fd279b18ee0 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_info.cc
@@ -118,6 +118,24 @@ void AssignBitset(const unsigned long* src,
memset(&dst[src_len], 0, (dst_len - src_len) * sizeof(unsigned long));
}
+bool IsBlacklistedAbsoluteMouseDevice(const input_id& id) {
+ static constexpr struct {
+ uint16_t vid;
+ uint16_t pid;
+ } kUSBLegacyBlackListedDevices[] = {
+ {0x222a, 0x0001}, // ILITEK ILITEK-TP
+ };
+
+ for (size_t i = 0; i < base::size(kUSBLegacyBlackListedDevices); ++i) {
+ if (id.vendor == kUSBLegacyBlackListedDevices[i].vid &&
+ id.product == kUSBLegacyBlackListedDevices[i].pid) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace
EventDeviceInfo::EventDeviceInfo() {
@@ -506,7 +524,8 @@ EventDeviceInfo::ProbeLegacyAbsoluteDevice() const {
return LegacyAbsoluteDeviceType::TOUCHSCREEN;
// ABS_Z mitigation for extra device on some Elo devices.
- if (HasKeyEvent(BTN_LEFT) && !HasAbsEvent(ABS_Z))
+ if (HasKeyEvent(BTN_LEFT) && !HasAbsEvent(ABS_Z) &&
+ !IsBlacklistedAbsoluteMouseDevice(input_id_))
return LegacyAbsoluteDeviceType::TOUCHSCREEN;
return LegacyAbsoluteDeviceType::NONE;
diff --git a/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc b/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
index 4248eecbe4f..3e7c0818006 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_info_unittest.cc
@@ -225,4 +225,32 @@ TEST(EventDeviceInfoTest, HammerTouchpad) {
EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_INTERNAL, devinfo.device_type());
}
+TEST(EventDeviceInfoTest, IllitekTP_Mouse) {
+ EventDeviceInfo devinfo;
+ EXPECT_TRUE(CapabilitiesToDeviceInfo(kIlitekTP_Mouse, &devinfo));
+
+ EXPECT_FALSE(devinfo.HasKeyboard());
+ EXPECT_FALSE(devinfo.HasMouse());
+ EXPECT_FALSE(devinfo.HasTouchpad());
+ EXPECT_FALSE(devinfo.HasTouchscreen());
+ EXPECT_FALSE(devinfo.HasTablet());
+ EXPECT_FALSE(devinfo.HasGamepad());
+
+ EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
+}
+
+TEST(EventDeviceInfoTest, IllitekTP) {
+ EventDeviceInfo devinfo;
+ EXPECT_TRUE(CapabilitiesToDeviceInfo(kIlitekTP, &devinfo));
+
+ EXPECT_FALSE(devinfo.HasKeyboard());
+ EXPECT_FALSE(devinfo.HasMouse());
+ EXPECT_FALSE(devinfo.HasTouchpad());
+ EXPECT_TRUE(devinfo.HasTouchscreen());
+ EXPECT_FALSE(devinfo.HasTablet());
+ EXPECT_FALSE(devinfo.HasGamepad());
+
+ EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_USB, devinfo.device_type());
+}
+
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/event_device_test_util.cc b/chromium/ui/events/ozone/evdev/event_device_test_util.cc
index 1172b988fe2..e652ea76271 100644
--- a/chromium/ui/events/ozone/evdev/event_device_test_util.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_test_util.cc
@@ -700,6 +700,66 @@ const DeviceCapabilities kHammerTouchpad = {
base::size(kHammerTouchpadAbsAxes),
};
+// Captured from Logitech Tap touch controller
+const DeviceAbsoluteAxis kIlitekTP_Mouse_AbsAxes[] = {
+ {ABS_X, {0, 0, 16384, 0, 0, 76}},
+ {ABS_Y, {0, 0, 9600, 0, 0, 71}},
+};
+const DeviceCapabilities kIlitekTP_Mouse = {
+ /* path */
+ "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.1/1-2.1.1/1-2.1.1.4/"
+ "1-2.1.1.4.2/1-2.1.1.4.2:1.1/0003:222A:0001.0015/input/input19/event9",
+ /* name */ "ILITEK ILITEK-TP",
+ /* phys */ "usb-0000:00:14.0-2.1.1.4.2/input1",
+ /* uniq */ "",
+ /* bustype */ "0003",
+ /* vendor */ "222a",
+ /* product */ "0001",
+ /* version */ "0110",
+ /* prop */ "0",
+ /* ev */ "1b",
+ /* key */ "1f0000 0 0 0 0",
+ /* rel */ "0",
+ /* abs */ "3",
+ /* msc */ "10",
+ /* sw */ "0",
+ /* led */ "0",
+ /* ff */ "0",
+ kIlitekTP_Mouse_AbsAxes,
+ base::size(kIlitekTP_Mouse_AbsAxes),
+};
+const DeviceAbsoluteAxis kIlitekTPAbsAxes[] = {
+ {ABS_X, {0, 0, 16384, 0, 0, 76}},
+ {ABS_Y, {0, 0, 9600, 0, 0, 71}},
+ {ABS_MT_SLOT, {0, 0, 9, 0, 0, 0}},
+ {ABS_MT_POSITION_X, {0, 0, 16384, 0, 0, 76}},
+ {ABS_MT_POSITION_Y, {0, 0, 9600, 0, 0, 71}},
+ {ABS_MT_TRACKING_ID, {0, 0, 65535, 0, 0, 0}},
+};
+const DeviceCapabilities kIlitekTP = {
+ /* path */
+ "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2.1/1-2.1.1/1-2.1.1.4/"
+ "1-2.1.1.4.2/1-2.1.1.4.2:1.0/0003:222A:0001.0014/input/input18/event8",
+ /* name */ "ILITEK ILITEK-TP",
+ /* phys */ "usb-0000:00:14.0-2.1.1.4.2/input0",
+ /* uniq */ "",
+ /* bustype */ "0003",
+ /* vendor */ "222a",
+ /* product */ "0001",
+ /* version */ "0110",
+ /* prop */ "2",
+ /* ev */ "1b",
+ /* key */ "400 0 0 0 0 0",
+ /* rel */ "0",
+ /* abs */ "260800000000003",
+ /* msc */ "20",
+ /* sw */ "0",
+ /* led */ "0",
+ /* ff */ "0",
+ kIlitekTPAbsAxes,
+ base::size(kIlitekTPAbsAxes),
+};
+
// NB: Please use the capture_device_capabilities.py script to add more
// test data here. This will help ensure the data matches what the kernel
// reports for a real device and is entered correctly.
diff --git a/chromium/ui/events/ozone/evdev/event_device_test_util.h b/chromium/ui/events/ozone/evdev/event_device_test_util.h
index 00eb3479c7e..533690fc7a6 100644
--- a/chromium/ui/events/ozone/evdev/event_device_test_util.h
+++ b/chromium/ui/events/ozone/evdev/event_device_test_util.h
@@ -79,6 +79,8 @@ extern const DeviceCapabilities kWilsonBeachActiveStylus;
extern const DeviceCapabilities kEveStylus;
extern const DeviceCapabilities kHammerKeyboard;
extern const DeviceCapabilities kHammerTouchpad;
+extern const DeviceCapabilities kIlitekTP_Mouse;
+extern const DeviceCapabilities kIlitekTP;
} // namspace ui
diff --git a/chromium/ui/gl/gl_context_egl.cc b/chromium/ui/gl/gl_context_egl.cc
index a8f1c62ba78..00471969c41 100644
--- a/chromium/ui/gl/gl_context_egl.cc
+++ b/chromium/ui/gl/gl_context_egl.cc
@@ -62,11 +62,7 @@ using ui::GetLastEGLErrorString;
namespace gl {
GLContextEGL::GLContextEGL(GLShareGroup* share_group)
- : GLContextReal(share_group),
- context_(EGL_NO_CONTEXT),
- display_(EGL_NO_DISPLAY),
- config_(nullptr),
- unbind_fbo_on_makecurrent_(false) {}
+ : GLContextReal(share_group) {}
bool GLContextEGL::Initialize(GLSurface* compatible_surface,
const GLContextAttribs& attribs) {
@@ -278,8 +274,10 @@ void GLContextEGL::ReleaseYUVToRGBConverters() {
bool GLContextEGL::MakeCurrent(GLSurface* surface) {
DCHECK(context_);
+ if (lost_)
+ return false;
if (IsCurrent(surface))
- return true;
+ return true;
ScopedReleaseCurrent release_current;
TRACE_EVENT2("gpu", "GLContextEGL::MakeCurrent",
@@ -326,14 +324,20 @@ void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
SetCurrent(nullptr);
- eglMakeCurrent(display_,
- EGL_NO_SURFACE,
- EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
+ if (!eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT)) {
+ DVLOG(1) << "eglMakeCurrent failed to release current with error "
+ << GetLastEGLErrorString();
+ lost_ = true;
+ }
+
+ DCHECK(!IsCurrent(nullptr));
}
bool GLContextEGL::IsCurrent(GLSurface* surface) {
DCHECK(context_);
+ if (lost_)
+ return false;
bool native_context_is_current = context_ == eglGetCurrentContext();
diff --git a/chromium/ui/gl/gl_context_egl.h b/chromium/ui/gl/gl_context_egl.h
index 3e0346c586e..09ffe6a477c 100644
--- a/chromium/ui/gl/gl_context_egl.h
+++ b/chromium/ui/gl/gl_context_egl.h
@@ -45,10 +45,11 @@ class GL_EXPORT GLContextEGL : public GLContextReal {
void Destroy();
void ReleaseYUVToRGBConverters();
- EGLContext context_;
- EGLDisplay display_;
- EGLConfig config_;
- bool unbind_fbo_on_makecurrent_;
+ EGLContext context_ = nullptr;
+ EGLDisplay display_ = nullptr;
+ EGLConfig config_ = nullptr;
+ bool unbind_fbo_on_makecurrent_ = false;
+ bool lost_ = false;
std::map<gfx::ColorSpace, std::unique_ptr<YUVToRGBConverter>>
yuv_to_rgb_converters_;
diff --git a/chromium/ui/gl/init/gl_factory_mac.cc b/chromium/ui/gl/init/gl_factory_mac.cc
index d691934d92d..a084ec60985 100644
--- a/chromium/ui/gl/init/gl_factory_mac.cc
+++ b/chromium/ui/gl/init/gl_factory_mac.cc
@@ -63,12 +63,12 @@ class NoOpGLSurface : public GLSurface {
std::vector<GLImplementation> GetAllowedGLImplementations() {
std::vector<GLImplementation> impls;
impls.push_back(kGLImplementationDesktopGLCoreProfile);
+ impls.push_back(kGLImplementationDesktopGL);
+ impls.push_back(kGLImplementationAppleGL);
#if BUILDFLAG(USE_EGL_ON_MAC)
impls.push_back(kGLImplementationEGLGLES2);
impls.push_back(kGLImplementationSwiftShaderGL);
#endif // BUILDFLAG(USE_EGL_ON_MAC)
- impls.push_back(kGLImplementationDesktopGL);
- impls.push_back(kGLImplementationAppleGL);
return impls;
}
diff --git a/chromium/ui/native_theme/common_theme.cc b/chromium/ui/native_theme/common_theme.cc
index 120aa3abb15..739ce75518b 100644
--- a/chromium/ui/native_theme/common_theme.cc
+++ b/chromium/ui/native_theme/common_theme.cc
@@ -45,6 +45,7 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
case NativeTheme::kColorId_LabelEnabledColor:
case NativeTheme::kColorId_TextfieldDefaultColor:
case NativeTheme::kColorId_SelectedMenuItemForegroundColor:
+ case NativeTheme::kColorId_HighlightedMenuItemForegroundColor:
return gfx::kGoogleGrey200;
case NativeTheme::kColorId_UnfocusedBorderColor:
return SK_ColorTRANSPARENT;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc
index d9e6790be02..927e20acc21 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc
@@ -42,8 +42,8 @@ bool DrmWindowProxy::SupportsGpuFences() const {
drm_thread_->task_runner(),
base::BindOnce(&DrmThread::IsDeviceAtomic, base::Unretained(drm_thread_),
widget_, &is_atomic));
- return is_atomic && !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableExplicitDmaFences);
+ return is_atomic && base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExplicitDmaFences);
}
} // namespace ui
diff --git a/chromium/ui/ozone/public/ozone_switches.cc b/chromium/ui/ozone/public/ozone_switches.cc
index 46c48204470..14a8b4db343 100644
--- a/chromium/ui/ozone/public/ozone_switches.cc
+++ b/chromium/ui/ozone/public/ozone_switches.cc
@@ -15,7 +15,7 @@ const char kOzoneDumpFile[] = "ozone-dump-file";
// Try to enable wayland input method editor.
const char kEnableWaylandIme[] = "enable-wayland-ime";
-// Disable explicit DMA-fences
-const char kDisableExplicitDmaFences[] = "disable-explicit-dma-fences";
+// Enable explicit DMA-fences
+const char kEnableExplicitDmaFences[] = "enable-explicit-dma-fences";
} // namespace switches
diff --git a/chromium/ui/ozone/public/ozone_switches.h b/chromium/ui/ozone/public/ozone_switches.h
index 24d30c19eea..26eebcb0590 100644
--- a/chromium/ui/ozone/public/ozone_switches.h
+++ b/chromium/ui/ozone/public/ozone_switches.h
@@ -16,7 +16,7 @@ OZONE_BASE_EXPORT extern const char kOzoneDumpFile[];
OZONE_BASE_EXPORT extern const char kEnableWaylandIme[];
-OZONE_BASE_EXPORT extern const char kDisableExplicitDmaFences[];
+OZONE_BASE_EXPORT extern const char kEnableExplicitDmaFences[];
} // namespace switches
diff --git a/chromium/ui/shell_dialogs/execute_select_file_win.cc b/chromium/ui/shell_dialogs/execute_select_file_win.cc
index 504e6cb50d0..22f5eed21a0 100644
--- a/chromium/ui/shell_dialogs/execute_select_file_win.cc
+++ b/chromium/ui/shell_dialogs/execute_select_file_win.cc
@@ -196,6 +196,12 @@ bool RunOpenFileDialog(HWND owner,
return false;
}
+ // The FOS_FORCEFILESYSTEM option ensures that if the user enters a URL in the
+ // "File name" box, it will be downloaded locally and its new file path will
+ // be returned by the dialog. This was a default option in the deprecated
+ // GetOpenFileName API.
+ dialog_options |= FOS_FORCEFILESYSTEM;
+
if (!ConfigureDialog(file_open_dialog.Get(), title, ok_button_label,
default_path, filter, *filter_index, dialog_options)) {
return false;
@@ -267,7 +273,7 @@ bool ExecuteSelectFolder(HWND owner,
IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON);
}
- DWORD dialog_options = FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM;
+ DWORD dialog_options = FOS_PICKFOLDERS;
std::vector<FileFilterSpec> no_filter;
int filter_index = 0;
diff --git a/chromium/ui/strings/translations/ui_strings_ja.xtb b/chromium/ui/strings/translations/ui_strings_ja.xtb
index 3f7f4a72dec..c152ed21fbe 100644
--- a/chromium/ui/strings/translations/ui_strings_ja.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ja.xtb
@@ -20,7 +20,7 @@
<translation id="1710340000377843106">現在</translation>
<translation id="1752946267035950200">{MINUTES,plural, =1{1 分}other{# 分}}</translation>
<translation id="1761785978543082658"><ph name="QUANTITY" /> B</translation>
-<translation id="1801827354178857021">期間</translation>
+<translation id="1801827354178857021">ピリオド</translation>
<translation id="1803208670097017349">{MONTHS,plural, =1{1 か月}other{# か月}}</translation>
<translation id="1809410197924942083"><ph name="QUANTITY" /> MB/秒</translation>
<translation id="1812519734428420144">評価 <ph name="RATING_SCORE" /></translation>
diff --git a/chromium/ui/strings/translations/ui_strings_kn.xtb b/chromium/ui/strings/translations/ui_strings_kn.xtb
index 59075009150..02ce022ca9f 100644
--- a/chromium/ui/strings/translations/ui_strings_kn.xtb
+++ b/chromium/ui/strings/translations/ui_strings_kn.xtb
@@ -5,7 +5,7 @@
<translation id="1127811143501539442">{DAYS,plural, =1{1 ದಿನದ ಹಿಂದೆ}one{# ದಿನಗಳ ಹಿಂದೆ}other{# ದಿನಗಳ ಹಿಂದೆ}}</translation>
<translation id="1156623771253174079">{SECONDS,plural, =1{1 ನಿಮಿಷದ ಹಿಂದೆ}one{# ನಿಮಿಷಗಳ ಹಿಂದೆ}other{# ನಿಮಿಷಗಳ ಹಿಂದೆ}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1ಮೀ}one{#ಮೀ}other{#ಮೀ}}</translation>
-<translation id="1181037720776840403">ತೆಗೆದುಹಾಕಿ</translation>
+<translation id="1181037720776840403">ತೆಗೆದುಹಾಕು</translation>
<translation id="1243314992276662751">ಅಪ್‌ಲೋಡ್</translation>
<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ta.xtb b/chromium/ui/strings/translations/ui_strings_ta.xtb
index eb4f23bc83f..85b64bbbe10 100644
--- a/chromium/ui/strings/translations/ui_strings_ta.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ta.xtb
@@ -81,7 +81,7 @@
<translation id="3909791450649380159">வெட்&amp;டு</translation>
<translation id="3990502903496589789">வலது விளிம்பு</translation>
<translation id="4202807286478387388">தாவு</translation>
-<translation id="4250229828105606438">ஸ்கிரீன் ஷாட்</translation>
+<translation id="4250229828105606438">ஸ்கிரீன்ஷாட்</translation>
<translation id="4266252015790371705">{MONTHS,plural, =1{1 மாதத்திற்கு முன்}other{# மாதங்களுக்கு முன்}}</translation>
<translation id="4289300219472526559">பேச்சைத் தொடங்கு</translation>
<translation id="4316910396681052118">எல்லாப் பயன்பாடுகளும்</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_te.xtb b/chromium/ui/strings/translations/ui_strings_te.xtb
index 381b21ac069..f35ea8f5ca2 100644
--- a/chromium/ui/strings/translations/ui_strings_te.xtb
+++ b/chromium/ui/strings/translations/ui_strings_te.xtb
@@ -60,7 +60,7 @@
<translation id="3087734570205094154">దిగువ</translation>
<translation id="3126026824346185272">Ctrl</translation>
<translation id="3157931365184549694">పునరుద్ధరించు</translation>
-<translation id="3183922693828471536">ఇక్కడ స్క్రోల్ చెయ్యండి</translation>
+<translation id="3183922693828471536">ఇక్కడికి స్క్రోల్ చేయండి</translation>
<translation id="3234408098842461169">క్రింది బాణం</translation>
<translation id="3291688615589870984">{DAYS,plural, =1{1 రోజు}other{# రోజులు}}</translation>
<translation id="335581015389089642">ప్రసంగం</translation>
@@ -85,7 +85,7 @@
<translation id="4266252015790371705">{MONTHS,plural, =1{1 నెల క్రితం}other{# నెలల క్రితం}}</translation>
<translation id="4289300219472526559">మాట్లాడటాన్ని ప్రారంభించు</translation>
<translation id="4316910396681052118">అన్ని అనువర్తనాలు</translation>
-<translation id="4588090240171750605">కుడికి స్క్రోల్ చెయ్యి</translation>
+<translation id="4588090240171750605">కుడికి స్క్రోల్ చేయి</translation>
<translation id="4724120544754982507">నోటిఫికేషన్ కేంద్రం, <ph name="UNREAD_NOTIFICATION_COUNT" /> చదవని నోటిఫికేషన్‌లు</translation>
<translation id="4730374152663651037">తరచుగా ఉపయోగించేవి</translation>
<translation id="4788285488841504513">{MONTHS,plural, =1{1 నెల మిగిలి ఉంది}other{# నెలలు మిగిలి ఉన్నాయి}}</translation>
@@ -117,10 +117,10 @@
<translation id="6129953537138746214">ఖాళీ</translation>
<translation id="6135826906199951471">Del</translation>
<translation id="6142413573757616983"><ph name="QUANTITY" /> B/s</translation>
-<translation id="6156262341071374681">అన్ని యాప్‌లు కోసం విస్తరించండి</translation>
+<translation id="6156262341071374681">అన్ని యాప్‌ల కోసం విస్తరించండి</translation>
<translation id="6264365405983206840">&amp;అన్నీ ఎంచుకోండి</translation>
<translation id="6351032674660237738">యాప్ సూచనలు</translation>
-<translation id="6364916375976753737">ఎడమకి స్క్రోల్ చేయి</translation>
+<translation id="6364916375976753737">ఎడమకు స్క్రోల్ చేయి</translation>
<translation id="6394627529324717982">కామా</translation>
<translation id="6397363302884558537">మాట్లాడటాన్ని ఆపివేయి</translation>
<translation id="6404817160109697034">{SECONDS,plural, =1{1 సెక. క్రితం}other{# సెక. క్రితం}}</translation>
@@ -148,7 +148,7 @@
<translation id="7130207228079676353">అత్యంత ఇష్టపడేవి</translation>
<translation id="7222373446505536781">F11</translation>
<translation id="7238427729722629793">{MINUTES,plural, =1{1 నిమి. మిగిలి ఉంది}other{# నిమి. మిగిలి ఉన్నాయి}}</translation>
-<translation id="7319740667687257810">లాంచర్, పాక్షిక వీక్షణ</translation>
+<translation id="7319740667687257810">లాంఛ‌ర్‌, పాక్షిక వీక్షణ</translation>
<translation id="7365057348334984696">{MINUTES,plural, =1{1 నిమి. క్రితం}other{# నిమి. క్రితం}}</translation>
<translation id="7389409599945284130">- <ph name="MESSAGE" /></translation>
<translation id="7410957453383678442">{MINUTES,plural, =1{1 నిమిషం మిగిలి ఉంది}other{# నిమిషాలు మిగిలి ఉన్నాయి}}</translation>
@@ -164,13 +164,13 @@
<translation id="8106081041558092062">{HOURS,plural, =1{1 గంట క్రితం}other{# గంటల క్రితం}}</translation>
<translation id="8131263257437993507">{SECONDS,plural, =1{1 సెక. మిగిలి ఉంది}other{# సెక. మిగిలి ఉన్నాయి}}</translation>
<translation id="8152264887680882389"><ph name="TEXT" />, స్వయంపూర్తి</translation>
-<translation id="815598010540052116">క్రిందికి స్క్రోల్ చేయి</translation>
+<translation id="815598010540052116">కిందికి స్క్రోల్ చేయి</translation>
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">పేజీ క్రిందికి</translation>
<translation id="8245914219290430011">ట్యాబ్</translation>
<translation id="8259556432390118667">హెక్స్ రంగు విలువ</translation>
<translation id="8328145009876646418">ఎడమ హద్దు</translation>
-<translation id="8331626408530291785">పైకి స్క్రోల్ చెయ్యి</translation>
+<translation id="8331626408530291785">పైకి స్క్రోల్ చేయి</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 సంవత్సరం}other{# సంవత్సరాలు}}</translation>
<translation id="838869780401515933">తనిఖీ చేయి</translation>
<translation id="8393700583063109961">సందేశాన్ని పంపండి</translation>
diff --git a/chromium/ui/views/controls/native/native_view_host_mac.mm b/chromium/ui/views/controls/native/native_view_host_mac.mm
index efd578dcff3..6fda67ff23d 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.mm
+++ b/chromium/ui/views/controls/native/native_view_host_mac.mm
@@ -122,15 +122,17 @@ void NativeViewHostMac::AttachNativeView() {
EnsureNativeViewHasNoChildWidgets(native_view_);
auto* bridge_host = GetBridgedNativeWidgetHost();
- DCHECK(bridge_host);
+ CHECK(bridge_host);
- if (native_view_hostable_) {
+ // TODO(https://crbug.com/933679): This is lifted out the ViewsHostableAttach
+ // call below because of crashes being observed in the field.
+ NSView* superview =
+ bridge_host->native_widget_mac()->GetNativeView().GetNativeNSView();
+ [superview addSubview:native_view_];
+
+ if (native_view_hostable_)
native_view_hostable_->ViewsHostableAttach(this);
- } else {
- NSView* superview =
- bridge_host->native_widget_mac()->GetNativeView().GetNativeNSView();
- [superview addSubview:native_view_];
- }
+
bridge_host->SetAssociationForView(host_, native_view_);
}
diff --git a/chromium/ui/views/event_monitor_aura.cc b/chromium/ui/views/event_monitor_aura.cc
index d560a66bd72..5909080e22a 100644
--- a/chromium/ui/views/event_monitor_aura.cc
+++ b/chromium/ui/views/event_monitor_aura.cc
@@ -4,7 +4,10 @@
#include "ui/views/event_monitor_aura.h"
+#include <memory>
+
#include "base/logging.h"
+#include "base/scoped_observer.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/events/event_observer.h"
@@ -12,6 +15,38 @@
namespace views {
+namespace {
+
+// An EventMonitorAura that removes its event observer on window destruction.
+class WindowMonitorAura : public EventMonitorAura, public aura::WindowObserver {
+ public:
+ WindowMonitorAura(aura::Env* env,
+ ui::EventObserver* event_observer,
+ aura::Window* target_window,
+ const std::set<ui::EventType>& types)
+ : EventMonitorAura(env, event_observer, target_window, types),
+ target_window_(target_window) {
+ window_observer_.Add(target_window);
+ }
+ ~WindowMonitorAura() override = default;
+
+ // aura::WindowObserver:
+ void OnWindowDestroying(aura::Window* window) override {
+ DCHECK_EQ(window, target_window_);
+ window_observer_.Remove(target_window_);
+ target_window_ = nullptr;
+ TearDown();
+ }
+
+ private:
+ aura::Window* target_window_;
+ ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(WindowMonitorAura);
+};
+
+} // namespace
+
// static
std::unique_ptr<EventMonitor> EventMonitor::CreateApplicationMonitor(
ui::EventObserver* event_observer,
@@ -26,7 +61,7 @@ std::unique_ptr<EventMonitor> EventMonitor::CreateWindowMonitor(
ui::EventObserver* event_observer,
gfx::NativeWindow target_window,
const std::set<ui::EventType>& types) {
- return std::make_unique<EventMonitorAura>(
+ return std::make_unique<WindowMonitorAura>(
target_window->env(), event_observer, target_window, types);
}
@@ -42,11 +77,17 @@ EventMonitorAura::EventMonitorAura(aura::Env* env,
}
EventMonitorAura::~EventMonitorAura() {
- env_->RemoveEventObserver(event_observer_);
+ TearDown();
}
gfx::Point EventMonitorAura::GetLastMouseLocation() {
return env_->last_mouse_location();
}
+void EventMonitorAura::TearDown() {
+ if (event_observer_)
+ env_->RemoveEventObserver(event_observer_);
+ event_observer_ = nullptr;
+}
+
} // namespace views
diff --git a/chromium/ui/views/event_monitor_aura.h b/chromium/ui/views/event_monitor_aura.h
index 222b8a15bc9..8f23c005114 100644
--- a/chromium/ui/views/event_monitor_aura.h
+++ b/chromium/ui/views/event_monitor_aura.h
@@ -18,6 +18,7 @@ class EventTarget;
namespace views {
+// Observes events by installing a pre-target handler on the ui::EventTarget.
class EventMonitorAura : public EventMonitor {
public:
EventMonitorAura(aura::Env* env,
@@ -29,6 +30,10 @@ class EventMonitorAura : public EventMonitor {
// EventMonitor:
gfx::Point GetLastMouseLocation() override;
+ protected:
+ // Removes the pre-target handler. Called by window monitors on window close.
+ void TearDown();
+
private:
aura::Env* env_; // Weak.
ui::EventObserver* event_observer_; // Weak. Owned by our owner.
diff --git a/chromium/ui/views/event_monitor_unittest.cc b/chromium/ui/views/event_monitor_unittest.cc
index fdda4562448..398b364b4d0 100644
--- a/chromium/ui/views/event_monitor_unittest.cc
+++ b/chromium/ui/views/event_monitor_unittest.cc
@@ -112,6 +112,18 @@ TEST_F(EventMonitorTest, ShouldOnlyReceiveRequestedEventTypes) {
monitor.reset();
}
+TEST_F(EventMonitorTest, WindowMonitorTornDownOnWindowClose) {
+ Widget* widget2 = CreateTopLevelNativeWidget();
+ widget2->Show();
+
+ std::unique_ptr<EventMonitor> monitor(EventMonitor::CreateWindowMonitor(
+ &observer_, widget2->GetNativeWindow(), {ui::ET_MOUSE_PRESSED}));
+
+ // Closing the widget before destroying the monitor should not crash.
+ widget2->CloseNow();
+ monitor.reset();
+}
+
namespace {
class DeleteOtherOnEventObserver : public ui::EventObserver {
public:
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index e43193ea912..f35f4a62754 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -873,9 +873,6 @@ void DesktopWindowTreeHostWin::HandleWindowMinimizedOrRestored(bool restored) {
window()->Show();
else
window()->Hide();
-
- if (compositor())
- compositor()->SetVisible(restored);
}
void DesktopWindowTreeHostWin::HandleClientSizeChanged(
diff --git a/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js b/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
index aeaa6c0b605..9578da26b27 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
@@ -161,6 +161,7 @@ cr_slider.SliderTick;
'onTicksChanged_(ticks.*)',
'updateLabelAndAria_(value, min, max)',
'updateKnobAndBar_(value, min, max)',
+ 'updateValue_(value, min, max)',
],
listeners: {
diff --git a/chromium/v8/AUTHORS b/chromium/v8/AUTHORS
index 57c8890f297..7adf005528b 100644
--- a/chromium/v8/AUTHORS
+++ b/chromium/v8/AUTHORS
@@ -68,6 +68,7 @@ Colin Ihrig <cjihrig@gmail.com>
Daniel Andersson <kodandersson@gmail.com>
Daniel Bevenius <daniel.bevenius@gmail.com>
Daniel James <dnljms@gmail.com>
+Deepak Mohan <hop2deep@gmail.com>
Deon Dior <diaoyuanjie@gmail.com>
Dominic Farolini <domfarolino@gmail.com>
Douglas Crosher <dtc-v8@scieneer.com>
diff --git a/chromium/v8/DEPS b/chromium/v8/DEPS
index a5ec023677b..ec6045a90a0 100644
--- a/chromium/v8/DEPS
+++ b/chromium/v8/DEPS
@@ -54,7 +54,7 @@ deps = {
'v8/third_party/markupsafe':
Var('chromium_url') + '/chromium/src/third_party/markupsafe.git' + '@' + '8f45f5cfa0009d2a70589bcda0349b8cb2b72783',
'v8/tools/swarming_client':
- Var('chromium_url') + '/infra/luci/client-py.git' + '@' + '0e3e1c4dc4e79f25a5b58fcbc135dc93183c0c54',
+ Var('chromium_url') + '/infra/luci/client-py.git' + '@' + 'd50a88f50782ba29076061b94c7b9d08a6c7e424',
'v8/test/benchmarks/data':
Var('chromium_url') + '/v8/deps/third_party/benchmarks.git' + '@' + '05d7188267b4560491ff9155c5ee13e207ecd65f',
'v8/test/mozilla/data':
diff --git a/chromium/v8/include/v8-version.h b/chromium/v8/include/v8-version.h
index fe2016fd481..e1ffcf2a981 100644
--- a/chromium/v8/include/v8-version.h
+++ b/chromium/v8/include/v8-version.h
@@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 7
#define V8_MINOR_VERSION 3
#define V8_BUILD_NUMBER 492
-#define V8_PATCH_LEVEL 10
+#define V8_PATCH_LEVEL 19
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/chromium/v8/infra/testing/builders.pyl b/chromium/v8/infra/testing/builders.pyl
index 375c98dc199..f15358405ca 100644
--- a/chromium/v8/infra/testing/builders.pyl
+++ b/chromium/v8/infra/testing/builders.pyl
@@ -1527,11 +1527,6 @@
##############################################################################
# Branches.
'V8 Linux - beta branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
@@ -1539,11 +1534,6 @@
],
},
'V8 Linux - beta branch - debug': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
@@ -1551,11 +1541,6 @@
],
},
'V8 Linux - stable branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
@@ -1563,11 +1548,6 @@
],
},
'V8 Linux - stable branch - debug': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
@@ -1575,11 +1555,6 @@
],
},
'V8 Linux64 - beta branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
@@ -1587,11 +1562,6 @@
],
},
'V8 Linux64 - beta branch - debug': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
@@ -1599,11 +1569,6 @@
],
},
'V8 Linux64 - stable branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
@@ -1611,11 +1576,6 @@
],
},
'V8 Linux64 - stable branch - debug': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
@@ -1623,129 +1583,69 @@
],
},
'V8 arm - sim - beta branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
- {'name': 'v8testing', 'shards': 2},
+ {'name': 'v8testing', 'shards': 4},
],
},
'V8 arm - sim - beta branch - debug': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
- {'name': 'v8testing', 'shards': 3},
+ {'name': 'v8testing', 'shards': 8},
],
},
'V8 arm - sim - stable branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
- {'name': 'v8testing', 'shards': 2},
+ {'name': 'v8testing', 'shards': 4},
],
},
'V8 arm - sim - stable branch - debug': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'mozilla'},
{'name': 'test262'},
- {'name': 'v8testing', 'shards': 3},
+ {'name': 'v8testing', 'shards': 8},
],
},
'V8 mips64el - sim - beta branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'unittests'},
],
},
'V8 mips64el - sim - stable branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'unittests'},
],
},
'V8 mipsel - sim - beta branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'v8testing', 'shards': 4},
],
},
'V8 mipsel - sim - stable branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'v8testing', 'shards': 4},
],
},
'V8 ppc64 - sim - beta branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'unittests'},
],
},
'V8 ppc64 - sim - stable branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'unittests'},
],
},
'V8 s390x - sim - beta branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'unittests'},
],
},
'V8 s390x - sim - stable branch': {
- 'swarming_task_attrs': {
- 'expiration': 14400,
- 'hard_timeout': 5400,
- 'priority': 35,
- },
'tests': [
{'name': 'unittests'},
],
diff --git a/chromium/v8/src/arm/macro-assembler-arm.h b/chromium/v8/src/arm/macro-assembler-arm.h
index 9b67a683e84..29fa10cfeac 100644
--- a/chromium/v8/src/arm/macro-assembler-arm.h
+++ b/chromium/v8/src/arm/macro-assembler-arm.h
@@ -825,6 +825,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// Needs access to SafepointRegisterStackIndex for compiled frame
// traversal.
friend class StandardFrame;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
};
// -----------------------------------------------------------------------------
diff --git a/chromium/v8/src/arm64/macro-assembler-arm64.h b/chromium/v8/src/arm64/macro-assembler-arm64.h
index 9327fce6406..ba1885a2484 100644
--- a/chromium/v8/src/arm64/macro-assembler-arm64.h
+++ b/chromium/v8/src/arm64/macro-assembler-arm64.h
@@ -1994,6 +1994,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// branch isntructions with a range of +-128MB. If that becomes too little
// (!), the mechanism can be extended to generate special veneers for really
// far targets.
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
};
diff --git a/chromium/v8/src/builtins/ppc/builtins-ppc.cc b/chromium/v8/src/builtins/ppc/builtins-ppc.cc
index 47f6e79561e..58419b1ccc3 100644
--- a/chromium/v8/src/builtins/ppc/builtins-ppc.cc
+++ b/chromium/v8/src/builtins/ppc/builtins-ppc.cc
@@ -556,9 +556,6 @@ void Generate_JSEntryVariant(MacroAssembler* masm, StackFrame::Type type,
Label invoke, handler_entry, exit;
- // Called from C
- __ function_descriptor();
-
{
NoRootArrayScope no_root_array(masm);
@@ -2605,16 +2602,6 @@ void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
__ Move(isolate_reg, ExternalReference::isolate_address(masm->isolate()));
Register target = r15;
- if (ABI_USES_FUNCTION_DESCRIPTORS) {
- // AIX/PPC64BE Linux use a function descriptor.
- __ LoadP(ToRegister(ABI_TOC_REGISTER), MemOperand(r15, kPointerSize));
- __ LoadP(ip, MemOperand(r15, 0)); // Instruction address
- target = ip;
- } else if (ABI_CALL_VIA_IP) {
- __ Move(ip, r15);
- target = ip;
- }
-
__ StoreReturnAddressAndCall(target);
// If return value is on the stack, pop it to registers.
diff --git a/chromium/v8/src/compiler/backend/arm/instruction-selector-arm.cc b/chromium/v8/src/compiler/backend/arm/instruction-selector-arm.cc
index cf8c1223e56..04f46a1d6b4 100644
--- a/chromium/v8/src/compiler/backend/arm/instruction-selector-arm.cc
+++ b/chromium/v8/src/compiler/backend/arm/instruction-selector-arm.cc
@@ -769,6 +769,7 @@ void EmitBic(InstructionSelector* selector, Node* node, Node* left,
void EmitUbfx(InstructionSelector* selector, Node* node, Node* left,
uint32_t lsb, uint32_t width) {
+ DCHECK_LE(lsb, 31u);
DCHECK_LE(1u, width);
DCHECK_LE(width, 32u - lsb);
ArmOperandGenerator g(selector);
@@ -948,7 +949,7 @@ void InstructionSelector::VisitWord32Shr(Node* node) {
uint32_t value = (mleft.right().Value() >> lsb) << lsb;
uint32_t width = base::bits::CountPopulation(value);
uint32_t msb = base::bits::CountLeadingZeros32(value);
- if (msb + width + lsb == 32) {
+ if ((width != 0) && (msb + width + lsb == 32)) {
DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value));
return EmitUbfx(this, node, mleft.left().node(), lsb, width);
}
diff --git a/chromium/v8/src/compiler/backend/ppc/code-generator-ppc.cc b/chromium/v8/src/compiler/backend/ppc/code-generator-ppc.cc
index b60fc9c26d9..b74834df171 100644
--- a/chromium/v8/src/compiler/backend/ppc/code-generator-ppc.cc
+++ b/chromium/v8/src/compiler/backend/ppc/code-generator-ppc.cc
@@ -2289,7 +2289,6 @@ void CodeGenerator::AssembleConstructFrame() {
auto call_descriptor = linkage()->GetIncomingDescriptor();
if (frame_access_state()->has_frame()) {
if (call_descriptor->IsCFunctionCall()) {
- __ function_descriptor();
__ mflr(r0);
if (FLAG_enable_embedded_constant_pool) {
__ Push(r0, fp, kConstantPoolRegister);
diff --git a/chromium/v8/src/ia32/macro-assembler-ia32.h b/chromium/v8/src/ia32/macro-assembler-ia32.h
index 6839a1ac5b1..d26152663aa 100644
--- a/chromium/v8/src/ia32/macro-assembler-ia32.h
+++ b/chromium/v8/src/ia32/macro-assembler-ia32.h
@@ -695,6 +695,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// Needs access to SafepointRegisterStackIndex for compiled frame
// traversal.
friend class StandardFrame;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
};
// -----------------------------------------------------------------------------
diff --git a/chromium/v8/src/mips/macro-assembler-mips.h b/chromium/v8/src/mips/macro-assembler-mips.h
index a833eeb0327..303fbb76b21 100644
--- a/chromium/v8/src/mips/macro-assembler-mips.h
+++ b/chromium/v8/src/mips/macro-assembler-mips.h
@@ -1148,6 +1148,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// Needs access to SafepointRegisterStackIndex for compiled frame
// traversal.
friend class StandardFrame;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
};
template <typename Func>
diff --git a/chromium/v8/src/mips64/macro-assembler-mips64.h b/chromium/v8/src/mips64/macro-assembler-mips64.h
index 40c2d49ca53..2e6991c1ba4 100644
--- a/chromium/v8/src/mips64/macro-assembler-mips64.h
+++ b/chromium/v8/src/mips64/macro-assembler-mips64.h
@@ -1218,6 +1218,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// Needs access to SafepointRegisterStackIndex for compiled frame
// traversal.
friend class StandardFrame;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
};
template <typename Func>
diff --git a/chromium/v8/src/parsing/parser-base.h b/chromium/v8/src/parsing/parser-base.h
index 969f1777759..33c165cd92e 100644
--- a/chromium/v8/src/parsing/parser-base.h
+++ b/chromium/v8/src/parsing/parser-base.h
@@ -3728,6 +3728,8 @@ void ParserBase<Impl>::ParseFunctionBody(
StatementListT* body, IdentifierT function_name, int pos,
const FormalParametersT& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, FunctionBodyType body_type) {
+ FunctionBodyParsingScope body_parsing_scope(impl());
+
if (IsResumableFunction(kind)) impl()->PrepareGeneratorVariables();
DeclarationScope* function_scope = parameters.scope;
diff --git a/chromium/v8/src/parsing/parser.cc b/chromium/v8/src/parsing/parser.cc
index 0b9f211ef95..d6d55af2b68 100644
--- a/chromium/v8/src/parsing/parser.cc
+++ b/chromium/v8/src/parsing/parser.cc
@@ -578,7 +578,8 @@ FunctionLiteral* Parser::DoParseProgram(Isolate* isolate, ParseInfo* info) {
factory()->NewExpressionStatement(initial_yield, kNoSourcePosition));
ParseModuleItemList(&body);
- if (!module()->Validate(this->scope()->AsModuleScope(),
+ if (!has_error() &&
+ !module()->Validate(this->scope()->AsModuleScope(),
pending_error_handler(), zone())) {
scanner()->set_parser_error();
}
diff --git a/chromium/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc b/chromium/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc
index 8e5b37dea79..d205ac9bb42 100644
--- a/chromium/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc
+++ b/chromium/v8/src/regexp/ppc/regexp-macro-assembler-ppc.cc
@@ -110,9 +110,6 @@ RegExpMacroAssemblerPPC::RegExpMacroAssemblerPPC(Isolate* isolate, Zone* zone,
internal_failure_label_() {
DCHECK_EQ(0, registers_to_save % 2);
-// Called from C
- __ function_descriptor();
-
__ b(&entry_label_); // We'll write the entry code later.
// If the code gets too big or corrupted, an internal exception will be
// raised, and we will exit right away.
diff --git a/chromium/v8/src/simulator.h b/chromium/v8/src/simulator.h
index e8ed111cfd8..9342ac4987a 100644
--- a/chromium/v8/src/simulator.h
+++ b/chromium/v8/src/simulator.h
@@ -121,7 +121,19 @@ class GeneratedCode {
#else
DISABLE_CFI_ICALL Return Call(Args... args) {
// When running without a simulator we call the entry directly.
+#if V8_OS_AIX
+ // AIX ABI requires function descriptors (FD). Artificially create a pseudo
+ // FD to ensure correct dispatch to generated code. The 'volatile'
+ // declaration is required to avoid the compiler from not observing the
+ // alias of the pseudo FD to the function pointer, and hence, optimizing the
+ // pseudo FD declaration/initialization away.
+ volatile Address function_desc[] = {reinterpret_cast<Address>(fn_ptr_), 0,
+ 0};
+ Signature* fn = reinterpret_cast<Signature*>(function_desc);
+ return fn(args...);
+#else
return fn_ptr_(args...);
+#endif // V8_OS_AIX
}
#endif
diff --git a/chromium/v8/src/x64/macro-assembler-x64.h b/chromium/v8/src/x64/macro-assembler-x64.h
index 97292b98fa4..cfd040a5c3f 100644
--- a/chromium/v8/src/x64/macro-assembler-x64.h
+++ b/chromium/v8/src/x64/macro-assembler-x64.h
@@ -899,6 +899,8 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// Needs access to SafepointRegisterStackIndex for compiled frame
// traversal.
friend class StandardFrame;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
};
// -----------------------------------------------------------------------------
diff --git a/chromium/v8/tools/gen-postmortem-metadata.py b/chromium/v8/tools/gen-postmortem-metadata.py
index 889e00511b4..af6e2f3cb46 100644
--- a/chromium/v8/tools/gen-postmortem-metadata.py
+++ b/chromium/v8/tools/gen-postmortem-metadata.py
@@ -245,6 +245,7 @@ consts_misc = [
#
extras_accessors = [
'JSFunction, context, Context, kContextOffset',
+ 'JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset',
'HeapObject, map, Map, kMapOffset',
'JSObject, elements, Object, kElementsOffset',
'JSObject, internal_fields, uintptr_t, kHeaderSize',